[
  {
    "path": ".fossil-settings/binary-glob",
    "content": "*.bmp\n*.gif\n*.png\n"
  },
  {
    "path": ".fossil-settings/crlf-glob",
    "content": "win/*.bat\nwin/*.vc\nwin/rc/*.rc\n"
  },
  {
    "path": ".fossil-settings/encoding-glob",
    "content": "win/buildall.vc.bat\nwin/makefile.vc\nwin/rules-ext.vc\nwin/rules.vc\nwin/targets.vc\nwin/rc/*.bmp\nwin/rc/*.cur\nwin/rc/*.ico\nwin/rc/*.rc\n"
  },
  {
    "path": ".fossil-settings/ignore-glob",
    "content": "*.a\n*.dll\n*.dylib\n*.dylib.E\n*.exe\n*.exp\n*.la\n*.lib\n*.lo\n*.o\n*.obj\n*.pdb\n*.res\n*.sl\n*.so\n*/Makefile\n*/autom4te.cache\n*/config.cache\n*/config.log\n*/config.status\n*/tkConfig.sh\n*/wish*\n*/tktest\n*/versions.vc\n*/version.vc\n*/libtk.vfs\n*/libtk*.zip\n*/tkUuid.h\n.git\nhtml\nmacosx/configure\nwin/Debug*\nwin/Release*\nwin/*.manifest\nwin/nmhlp-out.txt\nwin/nmakehlp.out\nunix/tk.pc\nunix/Tk-Info.plist\nunix/Wish-Info.plist\nunix/Credits.html\n"
  },
  {
    "path": ".fossil-settings/manifest",
    "content": "u\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior, in case people don't have core.autocrlf set.\n* eol=lf\n* text=auto\n\n# Explicitly declare text files you want to always be normalized and converted\n# to native line endings on checkout.\n*.3 text\n*.c text\n*.css text\n*.enc text\n*.h text\n*.htm text\n*.html text\n*.java text\n*.js text\n*.json text\n*.n text\n*.svg text\n*.ts text\n*.tcl text\n*.test text\n\n# Declare files that will always have CRLF line endings on checkout.\n*.bat eol=crlf\n*.rc eol=crlf\n*.sln eol=crlf\n*.vc eol=crlf\n\n# Denote all files that are truly binary and should not be modified.\n*.a binary\n*.bmp binary\n*.cur binary\n*.dll binary\n*.exe binary\n*.gif binary\n*.gz binary\n*.ico binary\n*.jpg binary\n*.lib binary\n*.pdf binary\n*.png binary\n*.xlsx binary\n*.zip binary\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "Important Note\n==========\nPlease do not file issues with Tk on Github. They are unlikely to be noticed in a timely fashion. Tk issues are hosted in the [tk fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tk/tktnew); please post them there.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Important Note\n==========\nPlease do not file pull requests with Tk on Github. They are unlikely to be noticed in a timely fashion. Tk issues (including patches) are hosted in the [tk fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tk/tktnew); please post them there.\n"
  },
  {
    "path": ".github/workflows/linux-build.yml",
    "content": "name: Linux\non:\n  push:\n    branches:\n    - \"main\"\n    - \"core-9-0-branch\"\n    tags:\n    - \"core-**\"\npermissions:\n  contents: read\ndefaults:\n  run:\n    shell: bash\n    working-directory: tk/unix\nenv:\n  ERROR_ON_FAILURES: 1\njobs:\n  build:\n    runs-on: ubuntu-24.04\n    strategy:\n      matrix:\n        compiler:\n          - \"gcc\"\n          - \"clang\"\n        config:\n          - \"\"\n          - \"CFLAGS=-DTK_NO_DEPRECATED=1\"\n          - \"--disable-shared\"\n          - \"--enable-symbols\"\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Setup Environment (compiler=${{ matrix.compiler }})\n        run: |\n          sudo apt-get update\n          sudo apt-get install libxss-dev libxft-dev libcups2-dev libatk1.0-dev libatk-bridge2.0-dev\n          mkdir \"$HOME/install dir\"\n          touch tk/doc/man.macros tk/generic/tkStubInit.c\n          echo \"CFGOPT=$CFGOPT\" >> $GITHUB_ENV\n          echo \"CC=$COMPILER\" >> $GITHUB_ENV\n          echo \"TOOL_DIR=$(cd tcl/tools;pwd)\" >> $GITHUB_ENV\n          echo \"BUILD_CONFIG_ID=$OPTS\" >> $GITHUB_ENV\n        working-directory: \".\"\n        env:\n          CFGOPT: ${{ matrix.config }}\n          COMPILER: ${{ matrix.compiler }}\n          OPTS: ${{ matrix.compiler }}${{ matrix.config }}\n      - name: Configure and Build Tcl\n        run: |\n          ./configure $CFGOPT \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::warning::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all install  || {\n            echo \"::warning::Failure during Tcl Build\"\n            exit 1\n          }\n          echo \"TCL_CONFIG_PATH=`pwd`\" >> $GITHUB_ENV\n        working-directory: tcl/unix\n      - name: Configure (opts=${{ matrix.config }})\n        run: |\n          ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n      - name: Build\n        run: |\n          make binaries libraries || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Build Test Harness\n        run: |\n          make tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Test-Drive Installation\n        run: |\n          make install || {\n            echo \"::error::Failure during Install\"\n            exit 1\n          }\n      - name: Create Distribution Package\n        run: |\n          make dist || {\n            echo \"::error::Failure during Distribute\"\n            exit 1\n          }\n      - name: Convert Documentation to HTML\n        run: |\n          make html-tk TOOL_DIR=$TOOL_DIR || {\n            echo \"::error::Failure during Distribute\"\n            exit 1\n          }\n      - name: Discover Version ID\n        if: ${{ env.BUILD_CONFIG_ID == 'gcc' }}\n        run: |\n          cd /tmp/dist\n          echo \"VERSION=`ls -d tk* | sed 's/tk//'`\" >> $GITHUB_ENV\n      - name: Upload Source Distribution\n        if: ${{ env.BUILD_CONFIG_ID == 'gcc' }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: Tk ${{ env.VERSION }} Source distribution (snapshot)\n          path: |\n            /tmp/dist/tk*\n            !/tmp/dist/tk*/html/**\n      - name: Upload Documentation Distribution\n        if: ${{ env.BUILD_CONFIG_ID == 'gcc' }}\n        uses: actions/upload-artifact@v7\n        with:\n          name: Tk ${{ env.VERSION }} HTML documentation (snapshot)\n          path: /tmp/dist/tk*/html\n  test:\n    runs-on: ubuntu-24.04\n    strategy:\n      matrix:\n        compiler:\n          - \"gcc\"\n        config:\n          - \"\"\n          - \"--enable-symbols\"\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v5\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Setup Environment (compiler=${{ matrix.compiler }})\n        run: |\n          sudo apt-get update\n          sudo apt-get install libxss-dev libxft-dev libcups2-dev xvfb libicu-dev xfonts-75dpi xfonts-100dpi xfonts-scalable libxfont2 unifont\n          mkdir \"$HOME/install dir\"\n          touch tk/doc/man.macros tk/generic/tkStubInit.c\n          echo \"CFGOPT=$CFGOPT\" >> $GITHUB_ENV\n          echo \"CC=$COMPILER\" >> $GITHUB_ENV\n        working-directory: \".\"\n        env:\n          CFGOPT: ${{ matrix.config }}\n          COMPILER: ${{ matrix.compiler }}\n      - name: Configure and Build Tcl\n        run: |\n          ./configure $CFGOPT \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::warning::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all install  || {\n            echo \"::warning::Failure during Tcl Build\"\n            exit 1\n          }\n          echo \"TCL_CONFIG_PATH=`pwd`\" >> $GITHUB_ENV\n        working-directory: tcl/unix\n      - name: Configure ${{ matrix.config }}\n        run: |\n          ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n      - name: Build\n        run: |\n          make binaries libraries tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Run Tests\n        run: |\n          xvfb-run --auto-servernum make test-classic | tee out-classic.txt\n          xvfb-run --auto-servernum make test-ttk | tee out-ttk.txt\n          grep -q \"Failed\t0\" out-classic.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          grep -q \"Failed\t0\" out-ttk.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n        timeout-minutes: 10\n"
  },
  {
    "path": ".github/workflows/linux-with-tcl9-build.yml",
    "content": "name: Linux (with Tcl 9.0)\non:\n  push:\n    branches:\n    - \"main\"\n    - \"core-9-0-branch\"\n    tags:\n    - \"core-**\"\npermissions:\n  contents: read\ndefaults:\n  run:\n    shell: bash\n    working-directory: tk/unix\nenv:\n  ERROR_ON_FAILURES: 1\njobs:\n  build:\n    runs-on: ubuntu-24.04\n    strategy:\n      matrix:\n        compiler:\n          - \"gcc\"\n          - \"clang\"\n        config:\n          - \"\"\n          - \"CFLAGS=-DTK_NO_DEPRECATED=1\"\n          - \"--disable-shared\"\n          - \"--enable-symbols\"\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          path: tk\n      - name: Checkout Tcl 9.0\n        uses: actions/checkout@v4\n        with:\n          repository: tcltk/tcl\n          ref: core-9-0-branch\n          path: tcl\n      - name: Setup Environment (compiler=${{ matrix.compiler }})\n        run: |\n          sudo apt-get install libx11-dev\n          mkdir \"$HOME/install dir\"\n          touch tk/doc/man.macros tk/generic/tkStubInit.c\n          echo \"CFGOPT=$CFGOPT\" >> $GITHUB_ENV\n          echo \"CC=$COMPILER\" >> $GITHUB_ENV\n          echo \"TOOL_DIR=$(cd tcl/tools;pwd)\" >> $GITHUB_ENV\n          echo \"BUILD_CONFIG_ID=$OPTS\" >> $GITHUB_ENV\n        working-directory: \".\"\n        env:\n          CFGOPT: ${{ matrix.config }}\n          COMPILER: ${{ matrix.compiler }}\n          OPTS: ${{ matrix.compiler }}${{ matrix.config }}\n      - name: Configure and Build Tcl\n        run: |\n          ./configure $CFGOPT \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::warning::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all install  || {\n            echo \"::warning::Failure during Tcl Build\"\n            exit 1\n          }\n          echo \"TCL_CONFIG_PATH=`pwd`\" >> $GITHUB_ENV\n        working-directory: tcl/unix\n      - name: Configure (opts=${{ matrix.config }})\n        run: |\n          ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n      - name: Build\n        run: |\n          make binaries libraries || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Build Test Harness\n        run: |\n          make tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Test-Drive Installation\n        run: |\n          make install || {\n            echo \"::error::Failure during Install\"\n            exit 1\n          }\n      - name: Create Distribution Package\n        run: |\n          make dist || {\n            echo \"::error::Failure during Distribute\"\n            exit 1\n          }\n      - name: Convert Documentation to HTML\n        run: |\n          make html-tk TOOL_DIR=$TOOL_DIR || {\n            echo \"::error::Failure during Distribute\"\n            exit 1\n          }\n  test:\n    runs-on: ubuntu-24.04\n    strategy:\n      matrix:\n        compiler:\n          - \"gcc\"\n        config:\n          - \"\"\n          - \"--enable-symbols\"\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          path: tk\n      - name: Checkout Tcl 9.0\n        uses: actions/checkout@v4\n        with:\n          repository: tcltk/tcl\n          ref: core-9-0-branch\n          path: tcl\n      - name: Setup Environment (compiler=${{ matrix.compiler }})\n        run: |\n          sudo apt-get update\n          sudo apt-get install xvfb libx11-dev libicu-dev xfonts-75dpi xfonts-100dpi xfonts-scalable libxfont2 unifont\n          mkdir \"$HOME/install dir\"\n          touch tk/doc/man.macros tk/generic/tkStubInit.c\n          echo \"CFGOPT=$CFGOPT\" >> $GITHUB_ENV\n          echo \"CC=$COMPILER\" >> $GITHUB_ENV\n        working-directory: \".\"\n        env:\n          CFGOPT: ${{ matrix.config }}\n          COMPILER: ${{ matrix.compiler }}\n      - name: Configure and Build Tcl\n        run: |\n          ./configure $CFGOPT \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::warning::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all install  || {\n            echo \"::warning::Failure during Tcl Build\"\n            exit 1\n          }\n          echo \"TCL_CONFIG_PATH=`pwd`\" >> $GITHUB_ENV\n        working-directory: tcl/unix\n      - name: Configure ${{ matrix.config }}\n        run: |\n          ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n      - name: Build\n        run: |\n          make binaries libraries tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Run Tests\n        run: |\n          xvfb-run --auto-servernum make test-classic | tee out-classic.txt\n          xvfb-run --auto-servernum make test-ttk | tee out-ttk.txt\n          grep -q \"Failed\t0\" out-classic.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          grep -q \"Failed\t0\" out-ttk.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n        timeout-minutes: 15\n"
  },
  {
    "path": ".github/workflows/mac-build.yml",
    "content": "name: macOS\non:\n  push:\n    branches:\n    - \"main\"\n    - \"core-9-0-branch\"\n    tags:\n    - \"core-**\"\npermissions:\n  contents: read\nenv:\n  ERROR_ON_FAILURES: 1\njobs:\n  framework:\n    runs-on: macos-26\n    defaults:\n      run:\n        shell: bash\n        working-directory: tk/macosx\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Check out Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Prepare checked out repositories\n        run: |\n          touch tk/generic/tkStubInit.c\n          mkdir build\n          echo \"BUILD_DIR=`cd build && pwd`\" >> $GITHUB_ENV\n          echo \"DESTDIR=`cd build && pwd`\" >> $GITHUB_ENV\n        working-directory: .\n      - name: Build Tcl\n        run: |\n          make all\n        working-directory: tcl/macosx\n      - name: Build\n        run: |\n          make all install || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Run Tests\n        run: |\n          make TK_NO_STDERR=1 test | tee out.txt\n          nmatches=$( grep -c \"Failed\t0\" out.txt )\n          if [ $nmatches -lt 4 ]\n          then\n            echo \"::error::Failure during Test\"\n            exit 1\n          fi\n        timeout-minutes: 30\n  prefix:\n    runs-on: macos-26\n    strategy:\n      matrix:\n        symbols:\n          - 'no'\n          - 'mem'\n        options:\n          - '--enable-aqua'\n          - '--disable-aqua'\n    defaults:\n      run:\n        shell: bash\n        working-directory: tk/unix\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Check out Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Prepare checked out repositories\n        env:\n          SET_DISPLAY: ${{ contains(matrix.options, '--disable-aqua') }}\n        run: |\n          touch tkStubInit.c\n          mkdir \"$HOME/install dir\"\n          echo \"USE_XVFB=$SET_DISPLAY\" >> $GITHUB_ENV\n        working-directory: tk/generic\n      - name: Add X11 (if required)\n        if: ${{ env.USE_XVFB == 'true' }}\n        run: |\n          brew install --cask xquartz\n          sudo /opt/X11/libexec/privileged_startx || true\n        working-directory: .\n      - name: Build Tcl\n        run: |\n          ./configure $CFGOPT --disable-zipfs \"--prefix=$HOME/install dir\" || {\n            cat config.log\n            echo \"::error::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all || {\n            echo \"::error::Failure during Tcl Build\"\n            exit 1\n          }\n          make install || {\n            echo \"::error::Failure during Tcl Install\"\n            exit 1\n          }\n        working-directory: tcl/unix\n        env:\n          CFGOPT: --enable-symbols=${{ matrix.symbols }}\n      - name: Configure (symbols=${{ matrix.symbols }} ${{matrix.options }})\n        run: |\n          ./configure $CFGOPT --disable-zipfs \"--prefix=$HOME/install dir\" --disable-xft || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n        env:\n          CFGOPT: --enable-symbols=${{ matrix.symbols }} ${{matrix.options }}\n      - name: Build\n        run: |\n          make all tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Run Tests\n        run: |\n          if [ $USE_XVFB == true ]; then\n            function runXvfb {\n              PATH=$PATH:/opt/X11/bin\n              Xvfb $1 &\n              XVFB_PID=$!\n              echo Launched Xvfb $1 as process $XVFB_PID >&2\n              trap \"echo killing process $XVFB_PID... >&2; kill $XVFB_PID\" 0\n              export DISPLAY=$1\n              sleep 2\n            }\n          else\n            function runXvfb {\n              echo Xvfb not used, this is a --enable-aqua build\n              export TK_NO_STDERR=1\n            }\n          fi\n          ( runXvfb :0; make test-classic; exit $? ) | tee out-classic.txt || {\n            echo \"::error::Failure during Test (classic)\"\n            exit 1\n          }\n          ( runXvfb :0; make test-ttk; exit $? ) | tee out-ttk.txt || {\n            echo \"::error::Failure during Test (ttk)\"\n            exit 1\n          }\n          cat out-classic.txt | grep -q \"Failed\t0\" || {\n            echo \"::error::Failure in classic test results\"\n            exit 1\n          }\n          cat out-ttk.txt | grep -q \"Failed\t0\" || {\n            echo \"::error::Failure in ttk test results\"\n            exit 1\n          }\n        timeout-minutes: 20\n      - name: Carry out trial installation\n        run: |\n          make install || {\n            cat config.log\n            echo \"::error::Failure during Install\"\n            exit 1\n          }\n"
  },
  {
    "path": ".github/workflows/onefiledist.yml",
    "content": "name: Build Binaries\non:\n  push:\n    branches:\n    - \"main\"\n    - \"core-9-0-branch\"\n    tags:\n    - \"core-**\"\npermissions:\n  contents: read\njobs:\n  linux:\n    name: Linux\n    runs-on: ubuntu-24.04\n    defaults:\n      run:\n        shell: bash\n    env:\n      CC: gcc\n      CFGOPT: --disable-symbols --disable-shared\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Prepare\n        run: |\n          sudo apt-get update\n          sudo apt-get install libxss-dev libxft-dev libcups2-dev libatk1.0-dev libatk-bridge2.0-dev\n          touch tcl/generic/tclStubInit.c tcl/generic/tclOOStubInit.c\n          touch tk/generic/tkStubInit.c\n          echo \"INST_DIR=$(cd install;pwd)\" >> $GITHUB_ENV\n          echo \"VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl\" >> $GITHUB_ENV\n        working-directory: \".\"\n      - name: Configure Tcl\n        run: |\n          ./configure $CFGOPT --prefix=$INST_DIR\n        working-directory: tcl/unix\n      - name: Build & Install Tcl\n        run: |\n          make binaries libraries install\n          make shell SCRIPT=\"$VER_PATH $GITHUB_ENV\"\n        working-directory: tcl/unix\n      - name: Configure Tk\n        run: |\n          ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR\n        working-directory: tk/unix\n      - name: Build & Install Tk\n        run: |\n          make binaries libraries install\n        working-directory: tk/unix\n        # TODO: need the Tk version separately for distro naming below\n      - name: Package\n        run: |\n          cp bin/wish9.1 ${BUILD_NAME}\n          chmod +x ${BUILD_NAME}\n          tar -cf ${BUILD_NAME}.tar ${BUILD_NAME}\n        working-directory: ${{ env.INST_DIR }}\n        env:\n          BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_snapshot\n      - name: Upload\n        uses: actions/upload-artifact@v7\n        with:\n          name: Wish ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot)\n          path: ${{ env.INST_DIR }}/*.tar\n      - name: Describe Installation Zip Contents\n        if: ${{ always() }}\n        run: |\n          unzip -l wish${{ env.TCL_PATCHLEVEL }}_snapshot || true\n        working-directory: ${{ env.INST_DIR }}\n  macos:\n    name: macOS\n    runs-on: macos-15\n    defaults:\n      run:\n        shell: bash\n    env:\n      CC: gcc\n      CFGOPT: --disable-symbols --disable-shared\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Checkout create-dmg\n        uses: actions/checkout@v6\n        with:\n          repository: create-dmg/create-dmg\n          ref: v1.2.2\n          path: create-dmg\n      - name: Prepare\n        run: |\n          mkdir -p install/contents\n          touch tcl/generic/tclStubInit.c tcl/generic/tclOOStubInit.c || true\n          touch tk/generic/tkStubInit.c || true\n          wget https://github.com/culler/macher/releases/download/v1.8/macher\n          sudo cp macher /usr/local/bin\n          sudo chmod a+x /usr/local/bin/macher\n          echo \"INST_DIR=$(cd install;pwd)\" >> $GITHUB_ENV\n          echo \"VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl\" >> $GITHUB_ENV\n          echo \"CREATE_DMG=$(cd create-dmg;pwd)/create-dmg\" >> $GITHUB_ENV\n          echo \"CFLAGS=-arch x86_64 -arch arm64\" >> $GITHUB_ENV\n        working-directory: \".\"\n      - name: Configure Tcl\n        run: |\n          ./configure $CFGOPT --prefix=$INST_DIR\n        working-directory: tcl/unix\n      - name: Build & Install Tcl\n        run: |\n          make binaries libraries install\n          make shell SCRIPT=\"$VER_PATH $GITHUB_ENV\"\n        working-directory: tcl/unix\n      - name: Configure Tk\n        run: |\n          ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR \\\n              --enable-aqua\n        working-directory: tk/unix\n      - name: Build & Install Tk\n        run: |\n          make binaries libraries install\n        working-directory: tk/unix\n        # TODO: need the Tk version separately for distro naming below\n      - name: Package\n        run: |\n          cp ../tk/unix/wish contents/${BUILD_NAME}\n          chmod +x contents/${BUILD_NAME}\n          cat > contents/README.txt <<EOF\n          This is a single-file executable developer preview of Tcl/Tk $TCL_PATCHLEVEL\n\n          It is not intended as an official release at all, so it is unsigned and unnotarized.\n          Use strictly at your own risk.\n\n          To run it, you need to copy the executable out and run:\n              xattr -d com.apple.quarantine ${BUILD_NAME}\n          to mark the executable as runnable on your machine.\n          EOF\n          $CREATE_DMG \\\n              --volname \"TclTk $TCL_PATCHLEVEL (snapshot)\" \\\n              --window-pos 200 120 \\\n              --window-size 800 400 \\\n              \"TclTk-$TCL_PATCHLEVEL-(snapshot).dmg\" \\\n              \"contents/\"\n        working-directory: ${{ env.INST_DIR }}\n        env:\n          BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_snapshot\n      - name: Upload\n        uses: actions/upload-artifact@v7\n        with:\n          name: Wish ${{ env.TCL_PATCHLEVEL }} macOS single-file build (snapshot)\n          path: ${{ env.INST_DIR }}/*.dmg\n  win:\n    name: Windows\n    runs-on: windows-latest\n    defaults:\n      run:\n        shell: msys2 {0}\n    env:\n      CC: gcc\n      CFGOPT: --disable-symbols --disable-shared\n    steps:\n      - name: Install MSYS2\n        uses: msys2/setup-msys2@v2\n        with:\n          msystem: MINGW64\n          install: git mingw-w64-x86_64-toolchain make zip\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Prepare\n        run: |\n          mkdir -p install/combined\n          touch tcl/generic/tclStubInit.c tcl/generic/tclOOStubInit.c\n          touch tk/generic/tkStubInit.c\n          echo \"INST_DIR=$(cd install;pwd)\" >> $GITHUB_ENV\n          echo \"VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl\" >> $GITHUB_ENV\n        working-directory: \".\"\n      - name: Configure Tcl\n        run: |\n          ./configure $CFGOPT --prefix=$INST_DIR\n        working-directory: tcl/win\n      - name: Build & Install Tcl\n        run: |\n          make binaries libraries install\n          $INST_DIR/bin/tclsh* $VER_PATH $GITHUB_ENV\n        working-directory: tcl/win\n      - name: Configure Tk\n        run: |\n          ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR\n        working-directory: tk/win\n      - name: Build & Install Tk\n        run: |\n          make all install\n          echo \"TK_BIN=`pwd`/`echo wish*.exe`\" >> $GITHUB_ENV\n        working-directory: tk/win\n        # TODO: need the Tk version separately for distro naming below\n      - name: Package\n        run: |\n          cp ${TK_BIN} combined/${BUILD_NAME}.exe\n        working-directory: install\n        env:\n          BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_snapshot\n      - name: Upload\n        uses: actions/upload-artifact@v7\n        with:\n          name: Wish ${{ env.TCL_PATCHLEVEL }} Windows single-file build (snapshot)\n          path: install/combined/wish${{ env.TCL_PATCHLEVEL }}_snapshot.exe\n"
  },
  {
    "path": ".github/workflows/win-build.yml",
    "content": "name: Windows\non:\n  push:\n    branches:\n    - \"main\"\n    - \"core-9-0-branch\"\n    tags:\n    - \"core-**\"\npermissions:\n  contents: read\nenv:\n  ERROR_ON_FAILURES: 1\njobs:\n  msvc:\n    runs-on: windows-2025\n    defaults:\n      run:\n        shell: powershell\n        working-directory: tk/win\n    # Using powershell means we need to explicitly stop on failure\n    strategy:\n      matrix:\n        config:\n          - \"\"\n          - \"OPTS=symbols\"\n          - \"OPTS=static\"\n    steps:\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n        with:\n          path: tk\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Init MSVC\n        uses: ilammy/msvc-dev-cmd@v1\n      - name: Make Install Location\n        working-directory: tcl\n        run: |\n          echo \"TCLDIR=`pwd`\" >> $GITHUB_ENV\n          cd ..\n          mkdir install\n          cd install\n          echo \"INSTALLDIR=`pwd`\" >> $GITHUB_ENV\n      - name: Build Tcl (${{ matrix.config }})\n        run: |\n          &nmake -f makefile.vc release install ${{ matrix.config }}\n          if ($lastexitcode -ne 0) {\n             throw \"nmake exit code: $lastexitcode\"\n          }\n        working-directory: tcl/win\n      - name: Build Tk (${{ matrix.config }})\n        run: |\n          &nmake -f makefile.vc all ${{ matrix.config }}\n          if ($lastexitcode -ne 0) {\n             throw \"nmake exit code: $lastexitcode\"\n          }\n      - name: Build Test Harness (${{ matrix.config }})\n        run: |\n          &nmake -f makefile.vc tktest ${{ matrix.config }}\n          if ($lastexitcode -ne 0) {\n             throw \"nmake exit code: $lastexitcode\"\n          }\n      - name: Run Tk Tests (${{ matrix.config }})\n        run: |\n          nmake -f makefile.vc test-classic ${{ matrix.config }} | tee out-classic.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          nmake -f makefile.vc test-ttk ${{ matrix.config }} | tee out-ttk.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          grep -q \"Failed\t0\" out-classic.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          grep -q \"Failed\t0\" out-ttk.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n        env:\n          CI_BUILD_WITH_MSVC: 1\n        shell: bash\n        timeout-minutes: 10\n      - name: Build Help (${{ matrix.config }})\n        run: |\n          &nmake -f makefile.vc htmlhelp ${{ matrix.config }}\n          if ($lastexitcode -ne 0) {\n             throw \"nmake exit code: $lastexitcode\"\n          }\n      - name: Install (${{ matrix.config }})\n        run: |\n          &nmake -f makefile.vc install ${{ matrix.config }}\n          if ($lastexitcode -ne 0) {\n             throw \"nmake exit code: $lastexitcode\"\n          }\n  gcc:\n    runs-on: windows-2025\n    defaults:\n      run:\n        shell: msys2 {0}\n        working-directory: win\n    strategy:\n      matrix:\n        config:\n          - \"\"\n          - \"--enable-symbols=mem\"\n          - \"--enable-symbols=all\"\n          - \"--disable-shared\"\n    steps:\n      - name: Install MSYS2\n        uses: msys2/setup-msys2@v2\n        with:\n          msystem: MINGW64\n          install: git mingw-w64-x86_64-toolchain make zip\n      - name: Checkout Tk\n        uses: actions/checkout@v6\n      - name: Checkout Tcl 9.1\n        uses: actions/checkout@v6\n        with:\n          repository: tcltk/tcl\n          ref: main\n          path: tcl\n      - name: Prepare\n        run: |\n          touch tkStubInit.c\n          touch \"${HOME}/forWinDialog-5.12.7\"\n          mkdir \"${HOME}/install_dir\"\n          echo \"INSTALL_DIR=${HOME}/install_dir\" >> $GITHUB_ENV\n        working-directory: generic\n      - name: Configure and Build Tcl (${{ matrix.config }})\n        run: |\n          ./configure $CFGOPT \"--prefix=$INSTALL_DIR\" || {\n            cat config.log\n            echo \"::warning::Failure during Tcl Configure\"\n            exit 1\n          }\n          make all install  || {\n            echo \"::warning::Failure during Tcl Build\"\n            exit 1\n          }\n          echo \"TCL_CONFIG_PATH=`pwd`\" >> $GITHUB_ENV\n        env:\n          CFGOPT: --enable-64bit ${{ matrix.config }}\n        working-directory: tcl/win\n      - name: Configure Tk (${{ matrix.config }})\n        run: |\n          ./configure $CFGOPT \"--prefix=$HOME/INSTALL_DIR\" \"--with-tcl=$TCL_CONFIG_PATH\" || {\n            cat config.log\n            echo \"::error::Failure during Configure\"\n            exit 1\n          }\n        env:\n          CFGOPT: --enable-64bit ${{ matrix.config }}\n      - name: Build Tk\n        run: |\n          make all install tktest || {\n            echo \"::error::Failure during Build\"\n            exit 1\n          }\n      - name: Run Tk Tests\n        run: |\n          make test-classic | tee out-classic.txt\n          make test-ttk | tee out-ttk.txt\n          grep -q \"Failed\t0\" out-classic.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n          grep -q \"Failed\t0\" out-ttk.txt || {\n            echo \"::error::Failure during Test\"\n            exit 1\n          }\n        timeout-minutes: 10\n"
  },
  {
    "path": ".gitignore",
    "content": "*.a\n*.bundle\n*.dll\n*.dylib\n*.dylib.E\n*.exe\n*.exp\n*.lib\n*.o\n*.obj\n*.pdb\n*.res\n*.sl\n*.so\n.fslckout\n_FOSSIL_\nMakefile\nTk-Info.plist\nWish-Info.plist\nCredits.html\nautom4te.cache\nconfig.cache\nconfig.log\nconfig.status\nconfig.status.lineno\nhtml\nmanifest.uuid\n_FOSSIL_\n*/tkConfig.sh\n*/wish\n*/tktest\n*/versions.vc\n*/version.vc\n*/libtk.vfs\n*/libtk*.zip\n*/tkUuid.h\nlibtommath/bn.ilg\nlibtommath/bn.ind\nlibtommath/pretty.build\nlibtommath/tommath.src\nlibtommath/*.log\nlibtommath/*.pdf\nlibtommath/*.pl\nlibtommath/*.sh\nlibtommath/doc/*\nlibtommath/tombc/*\nlibtommath/pre_gen/*\nlibtommath/pics/*\nlibtommath/mtest/*\nlibtommath/logs/*\nlibtommath/etc/*\nlibtommath/demo/*\nlibtommath/*.out\nlibtommath/*.tex\nmacosx/configure\nunix/autoMkindex.tcl\nunix/dltest.marker\nunix/tk.pc\nunix/tclIndex\nwin/Debug*\nwin/Release*\nwin/tk.pc\nwin/*.manifest\nwin/nmakehlp.out\nwin/nmhlp-out.txt\n"
  },
  {
    "path": ".project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>tk9.1</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t</buildSpec>\n\t<natures>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": ".settings/org.eclipse.core.resources.prefs",
    "content": "eclipse.preferences.version=1\nencoding/<project>=UTF-8\n"
  },
  {
    "path": ".settings/org.eclipse.core.runtime.prefs",
    "content": "eclipse.preferences.version=1\nline.separator=\\n\n"
  },
  {
    "path": "README.md",
    "content": "# README:  Tk\n\nThis is the **Tk 9.1a2** source distribution.\n\nYou can get any source release of Tk from [our distribution\nsite](https://sourceforge.net/projects/tcl/files/Tcl/).\n\n9.1 (in development, daily build)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/linux-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/linux-build.yml?query=branch%3Amain)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/win-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/win-build.yml?query=branch%3Amain)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/mac-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/mac-build.yml?query=branch%3Amain)\n<br>\n9.0 (production release, daily build)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/linux-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tk/actions/workflows/linux-build.yml?query=branch%3Acore-9-0-branch)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/win-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tk/actions/workflows/win-build.yml?query=branch%3Acore-9-0-branch)\n[![Build Status](https://github.com/tcltk/tk/actions/workflows/mac-build.yml/badge.svg?branch=core-9-0-branch)](https://github.com/tcltk/tk/actions/workflows/mac-build.yml?query=branch%3Acore-9-0-branch)\n\n## <a id=\"intro\">1.</a> Introduction\n\nThis directory contains the sources and documentation for Tk, a\ncross-platform GUI toolkit implemented with the Tcl scripting language.\n\nFor details on features, incompatibilities, and potential problems with\nthis release, see [the Tcl/Tk 9.1 Web page](https://www.tcl-lang.org/software/tcltk/9.1.html)\nor refer to the \"changes\" file in this directory, which contains a\ndescription of the changes in Tk 9.1 compared to Tk 9.0\n\nTk is maintained, enhanced, and distributed freely by the Tcl community.\nSource code development and tracking of bug reports and feature requests\ntake place at [core.tcl-lang.org](https://core.tcl-lang.org/).\nTcl/Tk release and mailing list services are [hosted by\nSourceForge](https://sourceforge.net/projects/tcl/)\nwith the Tcl Developer Xchange hosted at\n[www.tcl-lang.org](https://www.tcl-lang.org).\n\nTk is a freely available open-source package.  You can do virtually\nanything you like with it, such as modifying it, redistributing it,\nand selling it either in whole or in part.  See the file\n`license.terms` for complete information.\n\n## <a id=\"tcl\">2.</a> See Tcl README.md\n\nPlease see the README.md file that comes with the associated Tcl release\nfor more information.  There are pointers there to extensive\ndocumentation.  In addition, there are additional README files\nin the subdirectories of this distribution.\n"
  },
  {
    "path": "bitmaps/error.xbm",
    "content": "#define error_width 17\n#define error_height 17\nstatic unsigned char error_bits[] = {\n   0xf0, 0x0f, 0x00, 0x58, 0x15, 0x00, 0xac, 0x2a, 0x00, 0x16, 0x50, 0x00,\n   0x2b, 0xa0, 0x00, 0x55, 0x40, 0x01, 0xa3, 0xc0, 0x00, 0x45, 0x41, 0x01,\n   0x83, 0xc2, 0x00, 0x05, 0x45, 0x01, 0x03, 0xca, 0x00, 0x05, 0x74, 0x01,\n   0x0a, 0xa8, 0x00, 0x14, 0x58, 0x00, 0xe8, 0x2f, 0x00, 0x50, 0x15, 0x00,\n   0xa0, 0x0a, 0x00};\n"
  },
  {
    "path": "bitmaps/gray12.xbm",
    "content": "#define gray12_width 16\n#define gray12_height 16\nstatic unsigned char gray12_bits[] = {\n   0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22,\n   0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88,\n   0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88};\n"
  },
  {
    "path": "bitmaps/gray25.xbm",
    "content": "#define gray25_width 16\n#define gray25_height 16\nstatic unsigned char gray25_bits[] = {\n   0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22,\n   0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22,\n   0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22};\n"
  },
  {
    "path": "bitmaps/gray50.xbm",
    "content": "#define gray50_width 16\n#define gray50_height 16\nstatic unsigned char gray50_bits[] = {\n   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,\n   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,\n   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};\n"
  },
  {
    "path": "bitmaps/gray75.xbm",
    "content": "#define gray75_width 16\n#define gray75_height 16\nstatic unsigned char gray75_bits[] = {\n   0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd,\n   0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd,\n   0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd};\n"
  },
  {
    "path": "bitmaps/hourglass.xbm",
    "content": "#define hourglass_width 19\n#define hourglass_height 21\nstatic unsigned char hourglass_bits[] = {\n   0xff, 0xff, 0x07, 0x55, 0x55, 0x05, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01,\n   0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xc2, 0x0a, 0x03, 0x46, 0x05, 0x01,\n   0x82, 0x0a, 0x03, 0x06, 0x05, 0x01, 0x02, 0x03, 0x03, 0x86, 0x05, 0x01,\n   0xc2, 0x0a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01,\n   0xa2, 0x2a, 0x03, 0x66, 0x15, 0x01, 0xa2, 0x2a, 0x03, 0xff, 0xff, 0x07,\n   0xab, 0xaa, 0x02};\n"
  },
  {
    "path": "bitmaps/info.xbm",
    "content": "#define info_width 8\n#define info_height 21\nstatic unsigned char info_bits[] = {\n   0x3c, 0x2a, 0x16, 0x2a, 0x14, 0x00, 0x00, 0x3f, 0x15, 0x2e, 0x14, 0x2c,\n   0x14, 0x2c, 0x14, 0x2c, 0x14, 0x2c, 0xd7, 0xab, 0x55};\n"
  },
  {
    "path": "bitmaps/questhead.xbm",
    "content": "#define questhead_width 20\n#define questhead_height 22\nstatic unsigned char questhead_bits[] = {\n   0xf8, 0x1f, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00, 0xeb, 0xaf, 0x00,\n   0xf5, 0x5f, 0x01, 0xfb, 0xbf, 0x00, 0x75, 0x5d, 0x01, 0xfb, 0xbe, 0x02,\n   0x75, 0x5d, 0x05, 0xab, 0xbe, 0x0a, 0x55, 0x5f, 0x07, 0xab, 0xaf, 0x00,\n   0xd6, 0x57, 0x01, 0xac, 0xab, 0x00, 0xd8, 0x57, 0x00, 0xb0, 0xaa, 0x00,\n   0x50, 0x55, 0x00, 0xb0, 0x0b, 0x00, 0xd0, 0x17, 0x00, 0xb0, 0x0b, 0x00,\n   0x58, 0x15, 0x00, 0xa8, 0x2a, 0x00};\n"
  },
  {
    "path": "bitmaps/question.xbm",
    "content": "#define question_width 17\n#define question_height 27\nstatic unsigned char question_bits[] = {\n   0xf0, 0x0f, 0x00, 0x58, 0x15, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00,\n   0x2b, 0xa8, 0x00, 0x15, 0x50, 0x01, 0x0b, 0xa0, 0x00, 0x05, 0x60, 0x01,\n   0x0b, 0xa0, 0x00, 0x05, 0x60, 0x01, 0x0b, 0xb0, 0x00, 0x00, 0x58, 0x01,\n   0x00, 0xaf, 0x00, 0x80, 0x55, 0x00, 0xc0, 0x2a, 0x00, 0x40, 0x15, 0x00,\n   0xc0, 0x02, 0x00, 0x40, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x40, 0x01, 0x00,\n   0xc0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x02, 0x00,\n   0x40, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x00, 0x01, 0x00};\n"
  },
  {
    "path": "bitmaps/warning.xbm",
    "content": "#define warning_width 6\n#define warning_height 19\nstatic unsigned char warning_bits[] = {\n   0x0c, 0x16, 0x2b, 0x15, 0x2b, 0x15, 0x2b, 0x16, 0x0a, 0x16, 0x0a, 0x16,\n   0x0a, 0x00, 0x00, 0x1e, 0x0a, 0x16, 0x0a};\n"
  },
  {
    "path": "changes.md",
    "content": "\nThe source code for Tk is managed by fossil.  Tk developers coordinate all\nchanges to the Tk source code at\n\n> [Tk Source Code](https://core.tcl-lang.org/tk/)\n\nRelease Tk 9.1a2 arises from the check-in with tag `core-9-1-a2`.\n\nTk 9.1a2 continues the Tk 9.x series of releases.  The Tk 9.x series\ndo not support Tcl 8.6.  The Tk 9.1 series extends the Tcl 9.0 series.\nTo make use of Tk 9.1a2, first a Tcl 9.0 or 9.1 release must be present.\nAs new Tk features are developed, expect them to appear in Tk 9, but not\nnecessarily in Tk 8.\n\n# 9.1 Features and Interfaces\n - [MS-Win: remove Windows XP dialog variants for tk_chooseDirectory and tk_getOpenFile](https://core.tcl-lang.org/tk/tktview/441c52)\n - [Extend Tk_CanvasTextInfo](https://core.tcl-lang.org/tips/doc/trunk/tip/704.md)\n - [Add new states to ttk::treeview and ttk::notebook](https://core.tcl-lang.org/tips/doc/trunk/tip/719.md)\n - [Limit tk_messageBox to physical screen width](https://core.tcl-lang.org/tk/info/e19f1d891)\n - [Constrain own Dialogs to the physical screen size](https://core.tcl-lang.org/tk/info/7c28f835)\n - [Add a ttk::toggleswitch widget to the core](https://core.tcl-lang.org/tips/doc/trunk/tip/727.md)\n - [Add a tk attribtable command to the core](https://core.tcl-lang.org/tips/doc/trunk/tip/729.md)\n - [Implement more X11 region functions on Windows and Aqua](https://core.tcl-lang.org/tk/info/50fdbc36ad)\n - [Add accessibility/screen reader support to the core](https://core.tcl-lang.org/tips/doc/trunk/tip/733.md)\n - [Scroll entry with mouse wheel](https://core.tcl-lang.org/tips/doc/trunk/tip/736.md)\n - [Add a Wide.TSpinbox style to the core](https://core.tcl-lang.org/tips/doc/trunk/tip/739.md)\n - [Add support for native file icons to the core](https://core.tcl-lang.org/tips/doc/trunk/tip/743.md)\n - [Re-implement the Aqua send command](https://core.tcl-lang.org/tk/info/1574913cc772201e)\n - [Make the selection colors of the listbox widget fully native-conform](https://core.tcl-lang.org/tips/doc/trunk/tip/747.md)\n - [Add support for bidrectional text / RTL languages on Windows and X11](https://core.tcl-lang.org/tk/info/058e738f9f06fe20)\n - [Add Mouse Wheel Zoom Support to Tk Console](https://core.tcl-lang.org/tips/doc/trunk/tip/742.md)\n\n# Potential incompatibilities to 9.0\n - [MS-Win: Remove the -xpstyle option from tk_chooseDirectory and tk_getOpenFile](https://core.tcl-lang.org/tk/tktview/441c52)\n - [MS-Win: Eliminate the \"xpnative\" ttk style, in favor of \"vista\"](https://core.tcl-lang.org/tk/tktview/441c52)\n - [No longer allow negative screen distances in most cases](https://core.tcl-lang.org/tips/doc/trunk/tip/698.md)\n - [RTL/bidirectional text is a configure option on X11 (--enable-bidi). Additionally, there are some visual artifacts with bidi strings in the text widget in cursor and selection events on all platforms](https://core.tcl-lang.org/tk/tktview/cf94f5afd)\n"
  },
  {
    "path": "doc/3DBorder.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_Alloc3DBorderFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_Alloc3DBorderFromObj, Tk_ClipDrawableToRect, Tk_DrawHighlightBorder, Tk_Get3DBorder, Tk_Get3DBorderColors, Tk_Get3DBorderFromObj, Tk_Draw3DRectangle, Tk_Fill3DRectangle, Tk_Draw3DPolygon, Tk_Fill3DPolygon, Tk_3DVerticalBevel, Tk_3DHorizontalBevel, Tk_SetBackgroundFromBorder, Tk_NameOf3DBorder, Tk_3DBorderColor, Tk_3DBorderGC, Tk_Free3DBorderFromObj, Tk_Free3DBorder \\- draw borders with three-dimensional appearance\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n\nTk_3DBorder\n\\fBTk_Alloc3DBorderFromObj\\fR(\\fIinterp, tkwin, objPtr\\fR)\n.sp\n\\fBTk_ClipDrawableToRect\\fR(\\fIdisplay, drawable, x, y, width, height\\fR)\n.sp\n\\fBTk_DrawHighlightBorder\\fR(\\fItkwin, fgGC, bgGC, highlightWidth, drawable\\fR)\n.sp\nTk_3DBorder\n\\fBTk_Get3DBorder\\fR(\\fIinterp, tkwin, colorName\\fR)\n.sp\n\\fBTk_Get3DBorderColors\\fR(\\fIborder, bgColorPtr, darkColorPtr, lightColorPtr\\fR)\n.sp\nTk_3DBorder\n\\fBTk_Get3DBorderFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_Draw3DRectangle\\fR(\\fItkwin, drawable, border, x, y, width, height, borderWidth, relief\\fR)\n.sp\n\\fBTk_Fill3DRectangle\\fR(\\fItkwin, drawable, border, x, y, width, height, borderWidth, relief\\fR)\n.sp\n\\fBTk_Draw3DPolygon\\fR(\\fItkwin, drawable, border, pointPtr, numPoints, polyBorderWidth, leftRelief\\fR)\n.sp\n\\fBTk_Fill3DPolygon\\fR(\\fItkwin, drawable, border, pointPtr, numPoints, polyBorderWidth, leftRelief\\fR)\n.sp\n\\fBTk_3DVerticalBevel\\fR(\\fItkwin, drawable, border, x, y, width, height, leftBevel, relief\\fR)\n.sp\n\\fBTk_3DHorizontalBevel\\fR(\\fItkwin, drawable, border, x, y, width, height, leftIn, rightIn, topBevel, relief\\fR)\n.sp\n\\fBTk_SetBackgroundFromBorder\\fR(\\fItkwin, border\\fR)\n.sp\nconst char *\n\\fBTk_NameOf3DBorder\\fR(\\fIborder\\fR)\n.sp\nXColor *\n\\fBTk_3DBorderColor\\fR(\\fIborder\\fR)\n.sp\nGC *\n\\fBTk_3DBorderGC\\fR(\\fItkwin, border, which\\fR)\n.sp\n\\fBTk_Free3DBorderFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_Free3DBorder\\fR(\\fIborder\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_3DBorder\" borderWidth\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nToken for window (for all procedures except \\fBTk_Get3DBorder\\fR,\nmust be the window for which the border was allocated).\n.AP Tcl_Obj *objPtr in\nPointer to value whose value describes color corresponding to\nbackground (flat areas).  Illuminated edges will be brighter than\nthis and shadowed edges will be darker than this.\n.AP \"const char\" *colorName in\nSame as \\fIobjPtr\\fR except value is supplied as a string rather\nthan a value.\n.AP Drawable drawable in\nX token for window or pixmap;  indicates where graphics are to be drawn.\nMust either be the X window for \\fItkwin\\fR or a pixmap with the\nsame screen and depth as \\fItkwin\\fR.\n.AP Tk_3DBorder border in\nToken for border previously allocated in call to \\fBTk_Get3DBorder\\fR.\n.AP int x in\nX-coordinate of upper-left corner of rectangle describing border\nor bevel, in pixels.\n.AP int y in\nY-coordinate of upper-left corner of rectangle describing border or\nbevel, in pixels.\n.AP int width in\nWidth of rectangle describing border or bevel, in pixels.\n.AP int height in\nHeight of rectangle describing border or bevel, in pixels.\n.AP int borderWidth in\nWidth of border in pixels. Positive means border is inside rectangle\ngiven by \\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, \\fIheight\\fR, negative means\nborder is outside rectangle.\n.AP int highlightWidth in\nWidth of ring around the outside of the widget if the widget has received the\ninput focus.\n.AP int relief in\nIndicates 3-D position of interior of value relative to exterior;\nshould be \\fBTK_RELIEF_RAISED\\fR, \\fBTK_RELIEF_SUNKEN\\fR, \\fBTK_RELIEF_GROOVE\\fR,\n\\fBTK_RELIEF_SOLID\\fR, or \\fBTK_RELIEF_RIDGE\\fR (may also be \\fBTK_RELIEF_FLAT\\fR\nfor \\fBTk_Fill3DRectangle\\fR).\n.AP XPoint *pointPtr in\nPointer to array of points describing the set of vertices in a polygon.\nThe polygon need not be closed (it will be closed automatically if it\nis not).\n.AP int numPoints in\nNumber of points at \\fI*pointPtr\\fR.\n.AP int polyBorderWidth in\nWidth of border in pixels.  If positive, border is drawn to left of\ntrajectory given by \\fIpointPtr\\fR;  if negative, border is drawn to\nright of trajectory.  If \\fIleftRelief\\fR is \\fBTK_RELIEF_GROOVE\\fR or\n\\fBTK_RELIEF_RIDGE\\fR then the border is centered on the trajectory.\n.AP int leftRelief in\nHeight of left side of polygon's path relative to right.  \\fBTK_RELIEF_RAISED\\fR\nmeans left side should appear higher and \\fBTK_RELIEF_SUNKEN\\fR means right side\nshould appear higher;\n\\fBTK_RELIEF_GROOVE\\fR and \\fBTK_RELIEF_RIDGE\\fR mean the obvious things.\nFor \\fBTk_Fill3DPolygon\\fR, \\fBTK_RELIEF_FLAT\\fR may also be specified to\nindicate no difference in height.\n.AP int leftBevel in\nNon-zero means this bevel forms the left side of the value;  zero means\nit forms the right side.\n.AP int leftIn in\nNon-zero means that the left edge of the horizontal bevel angles in,\nso that the bottom of the edge is farther to the right than\nthe top.\nZero means the edge angles out, so that the bottom is farther to the\nleft than the top.\n.AP int rightIn in\nNon-zero means that the right edge of the horizontal bevel angles in,\nso that the bottom of the edge is farther to the left than the top.\nZero means the edge angles out, so that the bottom is farther to the\nright than the top.\n.AP int topBevel in\nNon-zero means this bevel forms the top side of the value;  zero means\nit forms the bottom side.\n.AP int which in\nSpecifies which of the border's graphics contexts is desired.\nMust be \\fBTK_3D_FLAT_GC\\fR, \\fBTK_3D_LIGHT_GC\\fR, or \\fBTK_3D_DARK_GC\\fR.\n.AP XColor *bgColorPtr out\nPointer to location in which to store the background color of the given border.\n.AP XColor *darkColorPtr out\nPointer to location in which to store the color for darker areas of the\ngiven border.\n.AP XColor *lightColorPtr out\nPointer to location in which to store the color for lighter areas of the\ngiven border.\n.AP GC fgGC in\nForeground X graphics context.\n.AP GC fgGC in\nBackground X graphics context.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures provide facilities for drawing window borders in a\nway that produces a three-dimensional appearance.\n\\fBTk_Alloc3DBorderFromObj\\fR\nallocates colors and Pixmaps needed to draw a border in the window\ngiven by the \\fItkwin\\fR argument.  The value of \\fIobjPtr\\fR\nis a standard Tk color name that determines the border colors.\nThe color indicated by \\fIobjPtr\\fR will not actually be used in\nthe border;  it indicates the background color for the window\n(i.e. a color for flat surfaces).\nThe illuminated portions of the border will appear brighter than indicated\nby \\fIobjPtr\\fR, and the shadowed portions of the border will appear\ndarker than \\fIobjPtr\\fR.\n.PP\n\\fBTk_Alloc3DBorderFromObj\\fR returns a token that may be used in later calls\nto \\fBTk_Draw3DRectangle\\fR.  If an error occurs in allocating information\nfor the border (e.g. a bogus color name was given)\nthen NULL is returned and an error message is left as the result of\ninterpreter \\fIinterp\\fR.\nIf it returns successfully, \\fBTk_Alloc3DBorderFromObj\\fR caches\ninformation about the return value in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_Alloc3DBorderFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\n\\fBTk_ClipDrawableToRect\\fR will clip all drawing into the drawable \\fId\\fR\nto the given rectangle. If \\fIwidth\\fR or \\fIheight\\fR are negative, reset\nto no clipping.\nSubsequent drawing into \\fId\\fR is offset and clipped as specified.\nThe function is only used when \\fBTK_NO_DOUBLE_BUFFERING\\fR is specified at\ncompile time.\n.PP\n\\fBTk_DrawHighlightBorder\\fR draws a rectangular ring around the outside of\na widget to indicate that it has received the input focus.\nOn the Macintosh, this puts a 1 pixel border in the bgGC color between\nthe widget and the focus ring, except in the case where highlightWidth\nis 0 or 1, in which case the border is left out.\nFor proper Mac L&F, use highlightWidth of 3.\n.PP\n\\fBTk_Get3DBorder\\fR is identical to \\fBTk_Alloc3DBorderFromObj\\fR except\nthat the color is specified with a string instead of a value.  This\nprevents \\fBTk_Get3DBorder\\fR from caching the return value, so\n\\fBTk_Get3DBorder\\fR is less efficient than \\fBTk_Alloc3DBorderFromObj\\fR.\n.PP\n\\fBTk_Get3DBorderColors\\fR returns the used colors of the given border.\n.PP\n\\fBTk_Get3DBorderFromObj\\fR returns the token for an existing border, given\nthe window and color name used to create the border.\n\\fBTk_Get3DBorderFromObj\\fR does not actually create the border; it must\nalready have been created with a previous call to\n\\fBTk_Alloc3DBorderFromObj\\fR or \\fBTk_Get3DBorder\\fR.  The return\nvalue is cached in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_Get3DBorderFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\nOnce a border structure has been created, \\fBTk_Draw3DRectangle\\fR may be\ninvoked to draw the border.\nThe \\fItkwin\\fR argument specifies the\nwindow for which the border was allocated, and \\fIdrawable\\fR\nspecifies a window or pixmap in which the border is to be drawn.\n\\fIDrawable\\fR need not refer to the same window as \\fItkwin\\fR, but it\nmust refer to a compatible\npixmap or window:  one associated with the same screen and with the\nsame depth as \\fItkwin\\fR.\nThe \\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and\n\\fIheight\\fR arguments define the bounding box of the border region\nwithin \\fIdrawable\\fR (usually \\fIx\\fR and \\fIy\\fR are zero and\n\\fIwidth\\fR and \\fIheight\\fR are the dimensions of the window), and\n\\fIborderWidth\\fR specifies the number of pixels actually\noccupied by the border.  The \\fIrelief\\fR argument indicates\nwhich of several three-dimensional effects is desired:\n\\fBTK_RELIEF_RAISED\\fR means that the interior of the rectangle should\nappear raised relative to the exterior of the rectangle, and\n\\fBTK_RELIEF_SUNKEN\\fR means that the interior should appear depressed.\n\\fBTK_RELIEF_GROOVE\\fR and \\fBTK_RELIEF_RIDGE\\fR mean that there should\nappear to be a groove or ridge around the exterior of the rectangle.\n.PP\n\\fBTk_Fill3DRectangle\\fR is somewhat like \\fBTk_Draw3DRectangle\\fR except\nthat it first fills the rectangular area with the background color\n(one corresponding\nto the color used to create \\fIborder\\fR).  Then it calls\n\\fBTk_Draw3DRectangle\\fR to draw a border just inside the outer edge of\nthe rectangular area.  The argument \\fIrelief\\fR indicates the desired\neffect (\\fBTK_RELIEF_FLAT\\fR means no border should be drawn; all that\nhappens is to fill the rectangle with the background color).\n.PP\nThe procedure \\fBTk_Draw3DPolygon\\fR may be used to draw more complex\nshapes with a three-dimensional appearance.  The \\fIpointPtr\\fR and\n\\fInumPoints\\fR arguments define a trajectory, \\fIpolyBorderWidth\\fR\nindicates how wide the border should be (and on which side of the\ntrajectory to draw it), and \\fIleftRelief\\fR indicates which side\nof the trajectory should appear raised.  \\fBTk_Draw3DPolygon\\fR\ndraws a border around the given trajectory using the colors from\n\\fIborder\\fR to produce a three-dimensional appearance.  If the trajectory is\nnon-self-intersecting, the appearance will be a raised or sunken\npolygon shape.  The trajectory may be self-intersecting, although\nit's not clear how useful this is.\n.PP\n\\fBTk_Fill3DPolygon\\fR is to \\fBTk_Draw3DPolygon\\fR what\n\\fBTk_Fill3DRectangle\\fR is to \\fBTk_Draw3DRectangle\\fR:  it fills\nthe polygonal area with the background color from \\fIborder\\fR,\nthen calls \\fBTk_Draw3DPolygon\\fR to draw a border around the\narea (unless \\fIleftRelief\\fR is \\fBTK_RELIEF_FLAT\\fR; in this case no\nborder is drawn).\n.PP\nThe procedures \\fBTk_3DVerticalBevel\\fR and \\fBTk_3DHorizontalBevel\\fR\nprovide lower-level drawing primitives that are used by\nprocedures such as \\fBTk_Draw3DRectangle\\fR.\nThese procedures are also useful in their own right for drawing\nrectilinear border shapes.\n\\fBTk_3DVerticalBevel\\fR draws a vertical beveled edge, such as the\nleft or right side of a rectangle, and \\fBTk_3DHorizontalBevel\\fR\ndraws a horizontal beveled edge, such as the top or bottom of a\nrectangle.\nEach procedure takes \\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and \\fIheight\\fR\narguments that describe the rectangular area of the beveled edge\n(e.g., \\fIwidth\\fR is the border width for \\fBTk_3DVerticalBevel\\fR).\nThe \\fIleftBorder\\fR and \\fItopBorder\\fR arguments indicate the\nposition of the border relative to the\n.QW inside\nof the value, and\n\\fIrelief\\fR indicates the relief of the inside of the value relative\nto the outside.\n\\fBTk_3DVerticalBevel\\fR just draws a rectangular region.\n\\fBTk_3DHorizontalBevel\\fR draws a trapezoidal region to generate\nmitered corners;  it should be called after \\fBTk_3DVerticalBevel\\fR\n(otherwise \\fBTk_3DVerticalBevel\\fR will overwrite the mitering in\nthe corner).\nThe \\fIleftIn\\fR and \\fIrightIn\\fR arguments to \\fBTk_3DHorizontalBevel\\fR\ndescribe the mitering at the corners;  a value of 1 means that the bottom\nedge of the trapezoid will be shorter than the top, 0 means it will\nbe longer.\nFor example, to draw a rectangular border the top bevel should be\ndrawn with 1 for both \\fIleftIn\\fR and \\fIrightIn\\fR, and the\nbottom bevel should be drawn with 0 for both arguments.\n.PP\nThe procedure \\fBTk_SetBackgroundFromBorder\\fR will modify the background\npixel and/or pixmap of \\fItkwin\\fR to produce a result compatible\nwith \\fIborder\\fR.  For color displays, the resulting background will\njust be the color specified when \\fIborder\\fR was created;  for monochrome\ndisplays, the resulting background\nwill be a light stipple pattern, in order to distinguish the background from\nthe illuminated portion of the border.\n.PP\nGiven a token for a border, the procedure \\fBTk_NameOf3DBorder\\fR\nwill return the color name that was used to create the border.\n.PP\nThe procedure \\fBTk_3DBorderColor\\fR returns the XColor structure\nthat will be used for flat surfaces drawn for its \\fIborder\\fR\nargument by procedures like \\fBTk_Fill3DRectangle\\fR.\nThe return value corresponds to the color name that was used to\ncreate the border.\nThe XColor, and its associated pixel value, will remain allocated\nas long as \\fIborder\\fR exists.\n.PP\nThe procedure \\fBTk_3DBorderGC\\fR returns one of the X graphics contexts\nthat are used to draw the border.\nThe argument \\fIwhich\\fR selects which one of the three possible GC's:\n\\fBTK_3D_FLAT_GC\\fR returns the context used for flat surfaces,\n\\fBTK_3D_LIGHT_GC\\fR returns the context for light shadows,\nand \\fBTK_3D_DARK_GC\\fR returns the context for dark shadows.\n.PP\nWhen a border is no longer needed, \\fBTk_Free3DBorderFromObj\\fR\nor \\fBTk_Free3DBorder\\fR should\nbe called to release the resources associated with it.\nFor \\fBTk_Free3DBorderFromObj\\fR the border to release is specified\nwith the window and color name used to create the\nborder; for \\fBTk_Free3DBorder\\fR the border to release is specified\nwith the Tk_3DBorder token for the border.\nThere should be exactly one call to \\fBTk_Free3DBorderFromObj\\fR or\n\\fBTk_Free3DBorder\\fR for each call to \\fBTk_Alloc3DBorderFromObj\\fR\nor \\fBTk_Get3DBorder\\fR.\n.SH KEYWORDS\n3D, background, border, color, depressed, illumination, value, polygon,\nraised, shadow, three-dimensional effect\n"
  },
  {
    "path": "doc/AddOption.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH Tk_AddOption 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_AddOption \\- Add an option to the option database\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nvoid\n\\fBTk_AddOption\\fR(\\fItkwin, name, value, priority\\fR)\n.sp\nTcl_Obj *\n\\fBTk_GetSystemDefault\\fR(\\fItkwin, dbName, className\\fR)\n.fi\n.SH ARGUMENTS\n.AP Tk_Window tkwin in\nToken for window.\n.AP \"const char\" *name in\nMulti-element name of option.\n.AP \"const char\" *value in\nValue of option.\n.AP \"const char\" *dbName in\nThe option database name.\n.AP \"const char\" *className in\nThe name of the option class.\n.AP int priority in\nOverall priority level to use for option.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_AddOption\\fR is invoked to add an option to the database\nassociated with \\fItkwin\\fR's main window.  \\fIName\\fR\ncontains the option being specified and consists of names and/or\nclasses separated by asterisks or dots, in the usual X format.\n\\fIValue\\fR contains the text string to associate with \\fIname\\fR;\nthis value will be returned in calls to \\fBTk_GetOption\\fR.\n\\fIPriority\\fR specifies the priority of the value; when options are\nqueried using \\fBTk_GetOption\\fR, the value with the highest priority\nis returned.  \\fIPriority\\fR must be between 0 and \\fBTK_MAX_PRIO\\fR (100).\nSome common priority values are:\n.IP \\fBTK_WIDGET_DEFAULT_PRIO\\fR (20)\nUsed for default values hard-coded into widgets.\n.IP \\fBTK_STARTUP_FILE_PRIO\\fR (40)\nUsed for options specified in application-specific startup files.\n.IP \\fBTK_USER_DEFAULT_PRIO\\fR (60)\nUsed for options specified in user-specific defaults files, such as\n\\fB.Xdefaults\\fR, resource databases loaded into the X server, or\nuser-specific startup files.\n.IP \\fBTK_INTERACTIVE_PRIO\\fR (80)\nUsed for options specified interactively after the application starts\nrunning.\n.PP\n\\fBTk_GetSystemDefault\\fR returns a Tcl_Obj* with the string identifying\na configuration option matching the given \\fIdbname\\fR and \\fIclassName\\fR.\nReturns NULL if there are no system defaults that match this pair.\n.SH KEYWORDS\nclass, name, option, add\n"
  },
  {
    "path": "doc/BindTable.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateBindingTable 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateBindingTable, Tk_DeleteBindingTable, Tk_CreateBinding, Tk_DeleteBinding, Tk_GetBinding, Tk_GetAllBindings, Tk_DeleteAllBindings, Tk_BindEvent \\- invoke scripts in response to X events\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_BindingTable\n\\fBTk_CreateBindingTable\\fR(\\fIinterp\\fR)\n.sp\n\\fBTk_DeleteBindingTable\\fR(\\fIbindingTable\\fR)\n.sp\nunsigned long\n\\fBTk_CreateBinding\\fR(\\fIinterp, bindingTable, object, eventString, script, append\\fR)\n.sp\nint\n\\fBTk_DeleteBinding\\fR(\\fIinterp, bindingTable, object, eventString\\fR)\n.sp\nconst char *\n\\fBTk_GetBinding\\fR(\\fIinterp, bindingTable, object, eventString\\fR)\n.sp\n\\fBTk_GetAllBindings\\fR(\\fIinterp, bindingTable, object\\fR)\n.sp\n\\fBTk_DeleteAllBindings\\fR(\\fIbindingTable, object\\fR)\n.sp\n\\fBTk_BindEvent\\fR(\\fIbindingTable, eventPtr, tkwin, numObjects, objectPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_BindingTable bindingTable\n.AP Tcl_Interp *interp in\nInterpreter to use when invoking bindings in binding table.  Also\nused for returning results and errors from binding procedures.\n.AP Tk_BindingTable bindingTable in\nToken for binding table;  must have been returned by some previous\ncall to \\fBTk_CreateBindingTable\\fR.\n.AP \"void *\" object in\nIdentifies object with which binding is associated.\n.AP \"const char\" *eventString in\nString describing event sequence.\n.AP \"const char\" *script in\nTcl script to invoke when binding triggers.\n.AP int append in\nNon-zero means append \\fIscript\\fR to existing script for binding,\nif any; zero means replace existing script with new one.\n.AP XEvent *eventPtr in\nX event to match against bindings in \\fIbindingTable\\fR.\n.AP Tk_Window tkwin in\nIdentifier for any window on the display where the event occurred.\nUsed to find display-related information such as key maps.\n.AP Tcl_Size numObjects in\nNumber of object identifiers pointed to by \\fIobjectPtr\\fR.\n.AP \"void **\" objectPtr in\nPoints to an array of object identifiers:  bindings will be considered\nfor each of these objects in order from first to last.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures provide a general-purpose mechanism for creating\nand invoking bindings.\nBindings are organized in terms of \\fIbinding tables\\fR.\nA binding table consists of a collection of bindings plus a history\nof recent events.\nWithin a binding table, bindings are associated with \\fIobjects\\fR.\nThe meaning of an object is defined by clients of the binding package.\nFor example, Tk keeps uses one binding table to hold all of the bindings\ncreated by the \\fBbind\\fR command.\nFor this table, objects are pointers to strings such as window names, class\nnames, or other binding tags such as \\fBall\\fR.\nTk also keeps a separate binding table for each canvas widget, which manages\nbindings created by the canvas's \\fBbind\\fR widget command;  within\nthis table, an object is either a pointer to the internal structure for a\ncanvas item or a Tk_Uid identifying a tag.\n.PP\nThe procedure \\fBTk_CreateBindingTable\\fR creates a new binding\ntable and associates \\fIinterp\\fR with it (when bindings in the\ntable are invoked, the scripts will be evaluated in \\fIinterp\\fR).\n\\fBTk_CreateBindingTable\\fR returns a token for the table, which\nmust be used in calls to other procedures such as \\fBTk_CreateBinding\\fR\nor \\fBTk_BindEvent\\fR.\n.PP\n\\fBTk_DeleteBindingTable\\fR frees all of the state associated\nwith a binding table.\nOnce it returns the caller should not use the \\fIbindingTable\\fR\ntoken again.\n.PP\n\\fBTk_CreateBinding\\fR adds a new binding to an existing table.\nThe \\fIobject\\fR argument identifies the object with which the\nbinding is to be associated, and it may be any one-word value.\nTypically it is a pointer to a string or data structure.\nThe \\fIeventString\\fR argument identifies the event or sequence\nof events for the binding;  see the documentation for the\n\\fBbind\\fR command for a description of its format.\n\\fIscript\\fR is the Tcl script to be evaluated when the binding\ntriggers.\n\\fIappend\\fR indicates what to do if there already\nexists a binding for \\fIobject\\fR and \\fIeventString\\fR:  if \\fIappend\\fR\nis zero then \\fIscript\\fR replaces the old script;  if \\fIappend\\fR\nis non-zero then the new script is appended to the old one.\n\\fBTk_CreateBinding\\fR returns an X event mask for all the events\nassociated with the bindings.\nThis information may be useful to invoke \\fBXSelectInput\\fR to\nselect relevant events, or to disallow the use of certain events\nin bindings.\nIf an error occurred while creating the binding (e.g., \\fIeventString\\fR\nrefers to a non-existent event), then 0 is returned and an error\nmessage is left as the result of interpreter \\fIinterp\\fR.\n.PP\n\\fBTk_DeleteBinding\\fR removes from \\fIbindingTable\\fR the\nbinding given by \\fIobject\\fR and \\fIeventString\\fR, if\nsuch a binding exists.\n\\fBTk_DeleteBinding\\fR always returns \\fBTCL_OK\\fR.\nIn some cases it may reset the interpreter result to the default\nempty value.\n.PP\n\\fBTk_GetBinding\\fR returns a pointer to the script associated\nwith \\fIeventString\\fR and \\fIobject\\fR in \\fIbindingTable\\fR.\nIf no such binding exists then NULL is returned and an error\nmessage is left as the result of interpreter \\fIinterp\\fR.\n.PP\n\\fBTk_GetAllBindings\\fR returns in \\fIinterp\\fR's result a list\nof all the event strings for which there are bindings in\n\\fIbindingTable\\fR associated with \\fIobject\\fR.\nIf there are no bindings for \\fIobject\\fR, the result will be an empty\nstring.\n.PP\n\\fBTk_DeleteAllBindings\\fR deletes all of the bindings in\n\\fIbindingTable\\fR that are associated with \\fIobject\\fR.\n.PP\n\\fBTk_BindEvent\\fR is called to process an event.\nIt makes a copy of the event in an internal history list associated\nwith the binding table, then it checks for bindings that match\nthe event.\n\\fBTk_BindEvent\\fR processes each of the objects pointed to\nby \\fIobjectPtr\\fR in turn.\nFor each object, it finds all the bindings that match the current\nevent history, selects the most specific binding using the priority\nmechanism described in the documentation for \\fBbind\\fR,\nand invokes the script for that binding.\nIf there are no matching bindings for a particular object, then\nthe object is skipped.\n\\fBTk_BindEvent\\fR continues through all of the objects, handling\nexceptions such as errors, \\fBbreak\\fR, and \\fBcontinue\\fR as\ndescribed in the documentation for \\fBbind\\fR.\n.SH KEYWORDS\nbinding, event, object, script\n"
  },
  {
    "path": "doc/CanvPsY.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CanvasPs 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CanvasPsY, Tk_CanvasPsBitmap, Tk_CanvasPsColor, Tk_CanvasPsFont, Tk_CanvasPsPath, Tk_CanvasPsStipple \\- utility procedures for generating Postscript for canvases\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\ndouble\n\\fBTk_CanvasPsY\\fR(\\fIcanvas, canvasY\\fR)\n.sp\nint\n\\fBTk_CanvasPsBitmap\\fR(\\fIinterp, canvas, bitmap, x, y, width, height\\fR)\n.sp\nint\n\\fBTk_CanvasPsColor\\fR(\\fIinterp, canvas, colorPtr\\fR)\n.sp\nint\n\\fBTk_CanvasPsFont\\fR(\\fIinterp, canvas, tkFont\\fR)\n.sp\n\\fBTk_CanvasPsPath\\fR(\\fIinterp, canvas, coordPtr, numPoints\\fR)\n.sp\nint\n\\fBTk_CanvasPsStipple\\fR(\\fIinterp, canvas, bitmap\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Size \"numPoints\"\n.AP Tk_Canvas canvas in\nA token that identifies a canvas widget for which Postscript is\nbeing generated.\n.AP double canvasY in\nY-coordinate in the space of the canvas.\n.AP Tcl_Interp *interp in/out\nA Tcl interpreter;  Postscript is appended to its result, or the\nresult may be replaced with an error message.\n.AP Pixmap bitmap in\nBitmap to use for generating Postscript.\n.AP int x in\nX-coordinate within \\fIbitmap\\fR of left edge of region to output.\n.AP int y in\nY-coordinate within \\fIbitmap\\fR of top edge of region to output.\n.AP \"int\" width in\nWidth of region of bitmap to output, in pixels.\n.AP \"int\" height in\nHeight of region of bitmap to output, in pixels.\n.AP XColor *colorPtr in\nInformation about color value to set in Postscript.\n.AP Tk_Font tkFont in\nFont for which Postscript is to be generated.\n.AP double *coordPtr in\nPointer to an array of coordinates for one or more\npoints specified in canvas coordinates.\nThe order of values in \\fIcoordPtr\\fR is x1, y1, x2, y2, x3, y3,\nand so on.\n.AP Tcl_Size numPoints in\nNumber of points at \\fIcoordPtr\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are called by canvas type managers to carry out\ncommon functions related to generating Postscript.\nMost of the procedures take a \\fIcanvas\\fR argument, which\nrefers to a canvas widget for which Postscript is being\ngenerated.\n.PP\n\\fBTk_CanvasPsY\\fR takes as argument a y-coordinate in the space of\na canvas and returns the value that should be used for that point\nin the Postscript currently being generated for \\fIcanvas\\fR.\nY coordinates require transformation because Postscript uses an\norigin at the lower-left corner whereas X uses an origin at the\nupper-left corner.\nCanvas x coordinates can be used directly in Postscript without\ntransformation.\n.PP\n\\fBTk_CanvasPsBitmap\\fR generates Postscript to describe a region\nof a bitmap.\nThe Postscript is generated in proper image data format for Postscript,\ni.e., as data between angle brackets, one bit per pixel.\nThe Postscript is appended to the result of interpreter \\fIinterp\\fR\nand \\fBTCL_OK\\fR is returned unless an error occurs, in which case\n\\fBTCL_ERROR\\fR is returned and the interpreter result is overwritten\nwith an error message.\n.PP\n\\fBTk_CanvasPsColor\\fR generates Postscript to set the current color\nto correspond to its \\fIcolorPtr\\fR argument, taking into account any\ncolor map specified in the \\fBpostscript\\fR command.\nIt appends the Postscript to the interpreter \\fIinterp\\fR's result and returns\n\\fBTCL_OK\\fR unless an error occurs, in which case \\fBTCL_ERROR\\fR is\nreturned and the interpreter's result is overwritten with an error message.\n.PP\n\\fBTk_CanvasPsFont\\fR generates Postscript that sets the current font\nto match \\fItkFont\\fR as closely as possible.\n\\fBTk_CanvasPsFont\\fR takes into account any font map specified\nin the \\fBpostscript\\fR command, and it does\nthe best it can at mapping X fonts to Postscript fonts.\nIt appends the Postscript to interpreter \\fIinterp\\fR's result and\nreturns \\fBTCL_OK\\fR unless an error occurs, in which case\n\\fBTCL_ERROR\\fR is returned and the interpreter's result is\noverwritten with an error message.\n.PP\n\\fBTk_CanvasPsPath\\fR generates Postscript to set the current path\nto the set of points given by \\fIcoordPtr\\fR and \\fInumPoints\\fR.\nIt appends the resulting Postscript to the result of interpreter \\fIinterp\\fR.\n.PP\n\\fBTk_CanvasPsStipple\\fR generates Postscript that will fill the\ncurrent path in stippled fashion.\nIt uses \\fIbitmap\\fR as the stipple pattern and the current Postscript\ncolor;  ones in the stipple bitmap are drawn in the current color, and\nzeroes are not drawn at all.\nThe Postscript is appended to interpreter \\fIinterp\\fR's result and\n\\fBTCL_OK\\fR is returned, unless an error occurs, in which case\n\\fBTCL_ERROR\\fR is returned and the interpreter's result is\noverwritten with an error message.\n.SH KEYWORDS\nbitmap, canvas, color, font, path, Postscript, stipple\n"
  },
  {
    "path": "doc/CanvTkwin.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CanvasTkwin 3 4.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CanvasTkwin, Tk_CanvasGetCoord, Tk_CanvasDrawableCoords, Tk_CanvasSetStippleOrigin, Tk_CanvasWindowCoords, Tk_CanvasEventuallyRedraw, Tk_CanvasTagsOption \\- utility procedures for canvas type managers\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_CanvasTkwin\\fR(\\fIcanvas\\fR)\n.sp\nint\n\\fBTk_CanvasGetCoord\\fR(\\fIinterp, canvas, string, doublePtr\\fR)\n.sp\n\\fBTk_CanvasDrawableCoords\\fR(\\fIcanvas, x, y, drawableXPtr, drawableYPtr\\fR)\n.sp\n\\fBTk_CanvasSetStippleOrigin\\fR(\\fIcanvas, gc\\fR)\n.sp\n\\fBTk_CanvasWindowCoords\\fR(\\fIcanvas, x, y, screenXPtr, screenYPtr\\fR)\n.sp\n\\fBTk_CanvasEventuallyRedraw\\fR(\\fIcanvas, x1, y1, x2, y2\\fR)\n.sp\nTk_OptionParseProc *\\fBTk_CanvasTagsParseProc\\fR;\n.sp\nTk_OptionPrintProc *\\fBTk_CanvasTagsPrintProc\\fR;\n.fi\n.SH ARGUMENTS\n.AS Tk_ItemType *drawableXPtr\n.AP Tk_Canvas canvas in\nA token that identifies a canvas widget.\n.AP Tcl_Interp *interp in/out\nInterpreter to use for error reporting.\n.AP \"const char\" *string in\nTextual description of a canvas coordinate.\n.AP double *doublePtr out\nPoints to place to store a converted coordinate.\n.AP double x in\nAn x coordinate in the space of the canvas.\n.AP double y in\nA y coordinate in the space of the canvas.\n.AP short *drawableXPtr out\nPointer to a location in which to store an x coordinate in the space\nof the drawable currently being used to redisplay the canvas.\n.AP short *drawableYPtr out\nPointer to a location in which to store a y coordinate in the space\nof the drawable currently being used to redisplay the canvas.\n.AP GC gc out\nGraphics context to modify.\n.AP short *screenXPtr out\nPoints to a location in which to store the screen coordinate in the\ncanvas window that corresponds to \\fIx\\fR.\n.AP short *screenYPtr out\nPoints to a location in which to store the screen coordinate in the\ncanvas window that corresponds to \\fIy\\fR.\n.AP int x1 in\nLeft edge of the region that needs redisplay.  Only pixels at or to\nthe right of this coordinate need to be redisplayed.\n.AP int y1 in\nTop edge of the region that needs redisplay.  Only pixels at or below\nthis coordinate need to be redisplayed.\n.AP int x2 in\nRight edge of the region that needs redisplay.  Only pixels to\nthe left of this coordinate need to be redisplayed.\n.AP int y2 in\nBottom edge of the region that needs redisplay.  Only pixels above\nthis coordinate need to be redisplayed.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are called by canvas type managers to perform various\nutility functions.\n.PP\n\\fBTk_CanvasTkwin\\fR returns the Tk_Window associated with a particular\ncanvas.\n.PP\n\\fBTk_CanvasGetCoord\\fR translates a string specification of a\ncoordinate (such as \\fB2p\\fR or \\fB1.6c\\fR) into a double-precision\ncanvas coordinate.\nIf \\fIstring\\fR is a valid coordinate description then \\fBTk_CanvasGetCoord\\fR\nstores the corresponding canvas coordinate at *\\fIdoublePtr\\fR\nand returns \\fBTCL_OK\\fR.\nOtherwise it stores an error message in the interpreter result and\nreturns \\fBTCL_ERROR\\fR.\n.PP\n\\fBTk_CanvasDrawableCoords\\fR is called by type managers during\nredisplay to compute where to draw things.\nGiven \\fIx\\fR and \\fIy\\fR coordinates in the space of the\ncanvas, \\fBTk_CanvasDrawableCoords\\fR computes the corresponding\npixel in the drawable that is currently being used for redisplay;\nit returns those coordinates in *\\fIdrawableXPtr\\fR and *\\fIdrawableYPtr\\fR.\nThis procedure should not be invoked except during redisplay.\n.PP\n\\fBTk_CanvasSetStippleOrigin\\fR is also used during redisplay.\nIt sets the stipple origin in \\fIgc\\fR so that stipples drawn\nwith \\fIgc\\fR in the current offscreen pixmap will line up\nwith stipples drawn with origin (0,0) in the canvas's actual\nwindow.\n\\fBTk_CanvasSetStippleOrigin\\fR is needed in order to guarantee\nthat stipple patterns line up properly when the canvas is\nredisplayed in small pieces.\nRedisplays are carried out in double-buffered fashion where a\npiece of the canvas is redrawn in an offscreen pixmap and then\ncopied back onto the screen.\nIn this approach the stipple origins in graphics contexts need to\nbe adjusted during each redisplay to compensate for the position\nof the off-screen pixmap relative to the window.\nIf an item is being drawn with stipples, its type manager typically\ncalls \\fBTk_CanvasSetStippleOrigin\\fR just before using \\fIgc\\fR\nto draw something;  after it is finished drawing, the type manager\ncalls \\fBXSetTSOrigin\\fR to restore the origin in \\fIgc\\fR back to (0,0)\n(the restore is needed because graphics contexts are shared, so\nthey cannot be modified permanently).\n.PP\n\\fBTk_CanvasWindowCoords\\fR is similar to \\fBTk_CanvasDrawableCoords\\fR\nexcept that it returns coordinates in the canvas's window on the\nscreen, instead of coordinates in an off-screen pixmap.\n.PP\n\\fBTk_CanvasEventuallyRedraw\\fR may be invoked by a type manager\nto inform Tk that a portion of a canvas needs to be redrawn.\nThe \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR arguments\nspecify the region that needs to be redrawn, in canvas coordinates.\nType managers rarely need to invoke \\fBTk_CanvasEventuallyRedraw\\fR,\nsince Tk can normally figure out when an item has changed and make\nthe redisplay request on its behalf (this happens, for example\nwhenever Tk calls a \\fIconfigureProc\\fR or \\fIscaleProc\\fR).\nThe only time that a type manager needs to call\n\\fBTk_CanvasEventuallyRedraw\\fR is if an item has changed on its own\nwithout being invoked through one of the procedures in its Tk_ItemType;\nthis could happen, for example, in an image item if the image is\nmodified using image commands.\n.PP\n\\fBTk_CanvasTagsParseProc\\fR and \\fBTk_CanvasTagsPrintProc\\fR are\nprocedures that handle the \\fB\\-tags\\fR option for canvas items.\nThe code of a canvas type manager will not call these procedures\ndirectly, but will use their addresses to create a \\fBTk_CustomOption\\fR\nstructure for the \\fB\\-tags\\fR option.   The code typically looks\nlike this:\n.PP\n.CS\nstatic const Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,\n    Tk_CanvasTagsPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    ...\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n        NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    ...\n};\n.CE\n.SH KEYWORDS\ncanvas, focus, item type, redisplay, selection, type manager\n"
  },
  {
    "path": "doc/CanvTxtInfo.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CanvasTextInfo 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CanvasTextInfo \\- additional information for managing text items in canvases\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_CanvasTextInfo *\n\\fBTk_CanvasGetTextInfo\\fR(\\fIcanvas\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Canvas canvas\n.AP Tk_Canvas canvas in\nA token that identifies a particular canvas widget.\n.BE\n.SH DESCRIPTION\n.PP\nTextual canvas items are somewhat more complicated to manage than\nother items, due to things like the selection and the input focus.\n\\fBTk_CanvasGetTextInfo\\fR may be invoked by a type manager\nto obtain additional information needed for items that display text.\nThe return value from \\fBTk_CanvasGetTextInfo\\fR is a pointer to\na structure that is shared between Tk and all the items that display\ntext.\nThe structure has the following form:\n.CS\ntypedef struct {\n    Tk_3DBorder \\fIselBorder\\fR;\n    int \\fIselBorderWidth\\fR;\n    XColor *\\fIselFgColorPtr\\fR;\n    Tk_Item *\\fIselItemPtr\\fR;\n    Tcl_Size \\fIselectFirst\\fR;\n    Tcl_Size \\fIselectLast\\fR;\n    Tk_Item *\\fIanchorItemPtr\\fR;\n    Tcl_Size \\fIselectAnchor\\fR;\n    Tk_3DBorder \\fIinsertBorder\\fR;\n    int \\fIinsertWidth\\fR;\n    int \\fIinsertBorderWidth\\fR;\n    Tk_Item *\\fIfocusItemPtr\\fR;\n    int \\fIgotFocus\\fR;\n    int \\fIcursorOn\\fR;\n    Tcl_Obj *\\fIinsertBorderWidthObj\\fR;\n    Tcl_Obj *\\fIinsertWidthObj\\fR;\n    Tcl_Obj *\\fIselBorderWidthObj\\fR;\n} \\fBTk_CanvasTextInfo\\fR;\n.CE\nThe \\fBselBorder\\fR field identifies a Tk_3DBorder that should be\nused for drawing the background under selected text.\n\\fIselBorderWidth\\fR gives the width of the raised border around\nselected text, in pixels. \\fIselBorderWidthObj\\fR contains the\nsame information, but the original Tcl_Obj * value;\n\\fIselFgColorPtr\\fR points to an XColor that describes the foreground\ncolor to be used when drawing selected text.\n\\fIselItemPtr\\fR points to the item that is currently selected, or\nNULL if there is no item selected or if the canvas does not have the\nselection.\n\\fIselectFirst\\fR and \\fIselectLast\\fR give the indices of the first\nand last selected characters in \\fIselItemPtr\\fR, as returned by the\n\\fIindexProc\\fR for that item.\n\\fIanchorItemPtr\\fR points to the item that currently has the selection\nanchor;  this is not necessarily the same as \\fIselItemPtr\\fR.\n\\fIselectAnchor\\fR is an index that identifies the anchor position\nwithin \\fIanchorItemPtr\\fR.\n\\fIinsertBorder\\fR contains a Tk_3DBorder to use when drawing the\ninsertion cursor;  \\fIinsertWidth\\fR gives the total width of the\ninsertion cursor in pixels, and \\fIinsertBorderWidth\\fR gives the\nwidth of the raised  border around the insertion cursor.\n\\fIinsertWidthObj\\fR and \\fIinsertBorderWidthObj\\fR contain the\nsame information, but the original Tcl_Obj * value.\n\\fIfocusItemPtr\\fR identifies the item that currently has the input\nfocus, or NULL if there is no such item.\n\\fIgotFocus\\fR is 1 if the canvas widget has the input focus and\n0 otherwise.\n\\fIcursorOn\\fR is 1 if the insertion cursor should be drawn in\n\\fIfocusItemPtr\\fR and 0 if it should not be drawn;  this field\nis toggled on and off by Tk to make the cursor blink.\n.PP\nThe structure returned by \\fBTk_CanvasGetTextInfo\\fR\nis shared between Tk and the type managers;  typically the type manager\ncalls \\fBTk_CanvasGetTextInfo\\fR once when an item is created and\nthen saves the pointer in the item's record.\nTk will update information in the Tk_CanvasTextInfo;  for example,\na \\fBconfigure\\fR widget command might change the \\fIselBorder\\fR\nfield, or a \\fBselect\\fR widget command might change the \\fIselectFirst\\fR\nfield, or Tk might change \\fIcursorOn\\fR in order to make the insertion\ncursor flash on and off during successive redisplays.\n.PP\nType managers should treat all of the fields of the Tk_CanvasTextInfo\nstructure as read-only, except for \\fIselItemPtr\\fR, \\fIselectFirst\\fR,\n\\fIselectLast\\fR, and \\fIselectAnchor\\fR.\nType managers may change \\fIselectFirst\\fR, \\fIselectLast\\fR, and\n\\fIselectAnchor\\fR to adjust for insertions and deletions in the\nitem (but only if the item is the current owner of the selection or\nanchor, as determined by \\fIselItemPtr\\fR or \\fIanchorItemPtr\\fR).\nIf all of the selected text in the item is deleted, the item should\nset \\fIselItemPtr\\fR to NULL to indicate that there is no longer a\nselection.\n.SH KEYWORDS\ncanvas, focus, insertion cursor, selection, selection anchor, text\n"
  },
  {
    "path": "doc/Clipboard.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ClipboardClear 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ClipboardClear, Tk_ClipboardAppend \\- Manage the clipboard\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_ClipboardClear\\fR(\\fIinterp, tkwin\\fR)\n.sp\nint\n\\fBTk_ClipboardAppend\\fR(\\fIinterp, tkwin, target, format, buffer\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ClipboardClear tkwin\n.AP Tcl_Interp *interp in\nInterpreter to use for reporting errors.\n.AP Tk_Window tkwin in\nWindow that determines which display's clipboard to manipulate.\n.AP Atom target in\nConversion type for this clipboard item;  has same meaning as\n\\fItarget\\fR argument to \\fBTk_CreateSelHandler\\fR.\n.AP Atom format in\nRepresentation to use when data is retrieved;  has same meaning as\n\\fIformat\\fR argument to \\fBTk_CreateSelHandler\\fR.\n.AP \"const char\" *buffer in\nNull terminated string containing the data to be appended to the clipboard.\n.BE\n.SH DESCRIPTION\n.PP\nThese two procedures manage the clipboard for Tk.\nThe clipboard is typically managed by calling \\fBTk_ClipboardClear\\fR\nonce, then calling \\fBTk_ClipboardAppend\\fR to add data for any\nnumber of targets.\n.PP\n\\fBTk_ClipboardClear\\fR claims the CLIPBOARD selection and frees any\ndata items previously stored on the clipboard in this application.\nIt normally returns \\fBTCL_OK\\fR, but if an error occurs it returns\n\\fBTCL_ERROR\\fR and leaves an error message in interpreter\n\\fIinterp\\fR's result.\n\\fBTk_ClipboardClear\\fR must be called before a sequence of\n\\fBTk_ClipboardAppend\\fR calls can be issued.\n.PP\n\\fBTk_ClipboardAppend\\fR appends a buffer of data to the clipboard.\nThe first buffer for a given \\fItarget\\fR determines the \\fIformat\\fR\nfor that \\fItarget\\fR.\nAny successive appends for that \\fItarget\\fR must have\nthe same format or an error will be returned.\n\\fBTk_ClipboardAppend\\fR returns \\fBTCL_OK\\fR if the buffer is\nsuccessfully copied onto the clipboard.  If the clipboard is not\ncurrently owned by the application, either\nbecause \\fBTk_ClipboardClear\\fR has not been called or because\nownership of the clipboard has changed since the last call to\n\\fBTk_ClipboardClear\\fR,\n\\fBTk_ClipboardAppend\\fR returns \\fBTCL_ERROR\\fR and leaves an error\nmessage in the result of interpreter \\fIinterp\\fR.\n.PP\nIn order to guarantee atomicity, no event handling should occur\nbetween \\fBTk_ClipboardClear\\fR and the following\n\\fBTk_ClipboardAppend\\fR calls (otherwise someone could retrieve\na partially completed clipboard or claim ownership away from\nthis application).\n.PP\n\\fBTk_ClipboardClear\\fR may invoke callbacks, including arbitrary\nTcl scripts, as a result of losing the CLIPBOARD selection, so\nany calling function should take care to be re-entrant at the point\n\\fBTk_ClipboardClear\\fR is invoked.\n.SH KEYWORDS\nappend, clipboard, clear, format, type\n"
  },
  {
    "path": "doc/ClrSelect.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1992-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ClearSelection 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ClearSelection \\- Deselect a selection\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_ClearSelection\\fR(\\fItkwin, selection\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP Tk_Window tkwin in\nThe selection will be cleared from the display containing this\nwindow.\n.AP Atom selection in\nThe name of selection to be cleared.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_ClearSelection\\fR cancels the selection specified by the atom\n\\fIselection\\fR for the display containing \\fItkwin\\fR.\nThe selection need not be in \\fItkwin\\fR itself or even in\n\\fItkwin\\fR's application.\nIf there is a window anywhere on \\fItkwin\\fR's display that\nowns \\fIselection\\fR, the window will be notified and the\nselection will be cleared.\nIf there is no owner for \\fIselection\\fR on the display, then the\nprocedure has no effect.\n.SH KEYWORDS\nclear, selection\n"
  },
  {
    "path": "doc/ConfigWidg.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ConfigureWidget 3 4.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ConfigureWidget, Tk_ConfigureInfo, Tk_ConfigureValue, Tk_FreeOptions \\- process configuration options for widgets\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_ConfigureWidget\\fR(\\fIinterp, tkwin, specs, objc, objv, widgRec, flags\\fR)\n.sp\nint\n\\fBTk_ConfigureInfo\\fR(\\fIinterp, tkwin, specs, widgRec, argvName, flags\\fR)\n.sp\nint\n\\fBTk_ConfigureValue\\fR(\\fIinterp, tkwin, specs, widgRec, argvName, flags\\fR)\n.sp\n\\fBTk_FreeOptions\\fR(\\fIspecs, widgRec, display, flags\\fR)\n.fi\n.SH ARGUMENTS\n.AS void *widgRec in/out\n.AP Tcl_Interp *interp in\nInterpreter to use for returning error messages.\n.AP Tk_Window tkwin in\nWindow used to represent widget (needed to set up X resources).\n.AP \"const Tk_ConfigSpec\" *specs in\nPointer to table specifying legal configuration options for this\nwidget.\n.AP Tcl_Size objc in\nNumber of arguments in \\fIobjv\\fR.\n.AP \"Tcl_Obj *const *\" objv in\nCommand-line options for configuring widget.\n.AP char *widgRec in/out\nPoints to widget record structure.  Fields in this structure get\nmodified by \\fBTk_ConfigureWidget\\fR to hold configuration information.\n.AP int flags in\nIf non-zero, then it specifies an OR-ed combination of flags that\ncontrol the processing of configuration information.\n\\fBTK_CONFIG_ARGV_ONLY\\fR causes the option database and defaults to be\nignored, and flag bits \\fBTK_CONFIG_USER_BIT\\fR and higher are used to\nselectively disable entries in \\fIspecs\\fR.\n.AP \"type name\" type in\nThe name of the type of a widget record.\n.AP \"field name\" field in\nThe name of a field in records of type \\fItype\\fR.\n.AP \"const char\" *argvName in\nThe name used on Tcl command lines to refer to a particular option\n(e.g. when creating a widget or invoking the \\fBconfigure\\fR widget\ncommand).  If non-NULL, then information is returned only for this\noption.  If NULL, then information is returned for all available\noptions.\n.AP Display *display in\nDisplay containing widget whose record is being freed;  needed in\norder to free up resources.\n.BE\n.SH DESCRIPTION\n.PP\nNote that \\fBTk_ConfigureWidget\\fR should be replaced with the new\n\\fBTcl_Obj\\fR based API, \\fBTk_SetOptions\\fR.  The old interface is\nretained for backward compatibility.\n.PP\n\\fBTk_ConfigureWidget\\fR is called to configure various aspects of a\nwidget, such as colors, fonts, border width, etc.\nIt is intended as a convenience procedure to reduce the amount\nof code that must be written in individual widget managers to\nhandle configuration information.\nIt is typically\ninvoked when widgets are created, and again when the \\fBconfigure\\fR\ncommand is invoked for a widget.\nAlthough intended primarily for widgets, \\fBTk_ConfigureWidget\\fR\ncan be used in other situations where \\fIobjc-objv\\fR information\nis to be used to fill in a record structure, such as configuring\ngraphical elements for a canvas widget or entries of a menu.\n.PP\n\\fBTk_ConfigureWidget\\fR processes\na table specifying the configuration options that are supported\n(\\fIspecs\\fR) and a collection of command-line arguments (\\fIobjc\\fR and\n\\fIobjv\\fR) to fill in fields of a record (\\fIwidgRec\\fR).\nIt uses the option database and defaults specified in \\fIspecs\\fR\nto fill in fields of \\fIwidgRec\\fR that are not specified in \\fIobjv\\fR.\n\\fBTk_ConfigureWidget\\fR normally returns the value \\fBTCL_OK\\fR; in this\ncase it does not modify \\fIinterp\\fR.\nIf an error\noccurs then \\fBTCL_ERROR\\fR is returned and \\fBTk_ConfigureWidget\\fR will\nleave an error message in interpreter \\fIinterp\\fR's result in the standard Tcl\nfashion.\nIn the event of an error return, some of the fields of \\fIwidgRec\\fR\ncould already have been set, if configuration information for them\nwas successfully processed before the error occurred.\nThe other fields will be set to reasonable initial values so that\n\\fBTk_FreeOptions\\fR can be called for cleanup.\n.PP\nThe \\fIspecs\\fR array specifies the kinds of configuration options\nexpected by the widget.  Each of its entries specifies one configuration\noption and has the following structure:\n.CS\ntypedef struct {\n    int \\fItype\\fR;\n    const char *\\fIargvName\\fR;\n    const char *\\fIdbName\\fR;\n    const char *\\fIdbClass\\fR;\n    const char *\\fIdefValue\\fR;\n    Tcl_Size \\fIoffset\\fR;\n    int \\fIspecFlags\\fR;\n    const Tk_CustomOption *\\fIcustomPtr\\fR;\n} \\fBTk_ConfigSpec\\fR;\n.CE\nThe \\fItype\\fR field indicates what type of configuration option this is\n(e.g. \\fBTK_CONFIG_COLOR\\fR for a color value, or \\fBTK_CONFIG_INT\\fR for\nan integer value).  The \\fItype\\fR field indicates how to use the\nvalue of the option (more on this below).\nThe \\fIargvName\\fR field is a string such as\n.QW \\-font\nor\n.QW \\-bg ,\nwhich is compared with the values in \\fIobjv\\fR (if \\fIargvName\\fR is\nNULL it means this is a grouped entry;  see \\fBGROUPED ENTRIES\\fR below).  The\n\\fIdbName\\fR and \\fIdbClass\\fR fields are used to look up a value\nfor this option in the option database.  The \\fIdefValue\\fR field\nspecifies a default value for this configuration option if no\nvalue is specified in either \\fIobjv\\fR or the option database.\n\\fIOffset\\fR indicates where in \\fIwidgRec\\fR to store information\nabout this option, and \\fIspecFlags\\fR contains additional information\nto control the processing of this configuration option (see FLAGS\nbelow).\nThe last field, \\fIcustomPtr\\fR, is only used if \\fItype\\fR is\n\\fBTK_CONFIG_CUSTOM\\fR;  see CUSTOM OPTION TYPES below.\n.PP\n\\fBTk_ConfigureWidget\\fR first processes \\fIobjv\\fR to see which\n(if any) configuration options are specified there.  \\fIArgv\\fR\nmust contain an even number of fields;  the first of each pair\nof fields must match the \\fIargvName\\fR of some entry in \\fIspecs\\fR\n(unique abbreviations are acceptable),\nand the second field of the pair contains the value for that\nconfiguration option.  If there are entries in \\fIspec\\fR for which\nthere were no matching entries in \\fIobjv\\fR,\n\\fBTk_ConfigureWidget\\fR uses the \\fIdbName\\fR and \\fIdbClass\\fR\nfields of the \\fIspecs\\fR entry to probe the option database;  if\na value is found, then it is used as the value for the option.\nFinally, if no entry is found in the option database, the\n\\fIdefValue\\fR field of the \\fIspecs\\fR entry is used as the\nvalue for the configuration option.  If the \\fIdefValue\\fR is\nNULL, or if the \\fBTK_CONFIG_DONT_SET_DEFAULT\\fR bit is set in\n\\fIflags\\fR, then there is no default value and this \\fIspecs\\fR entry\nwill be ignored if no value is specified in \\fIobjv\\fR or the\noption database.\n.PP\nOnce a string value has been determined for a configuration option,\n\\fBTk_ConfigureWidget\\fR translates the string value into a more useful\nform, such as a color if \\fItype\\fR is \\fBTK_CONFIG_COLOR\\fR or an integer\nif \\fItype\\fR is \\fBTK_CONFIG_INT\\fR.  This value is then stored in the\nrecord pointed to by \\fIwidgRec\\fR.  This record is assumed to\ncontain information relevant to the manager of the widget;  its exact\ntype is unknown to \\fBTk_ConfigureWidget\\fR.  The \\fIoffset\\fR field\nof each \\fIspecs\\fR entry indicates where in \\fIwidgRec\\fR to store\nthe information about this configuration option.  You should use the\n\\fBoffsetof\\fR macro to generate \\fIoffset\\fR values.  The location\nindicated by \\fIwidgRec\\fR and \\fIoffset\\fR will be referred to as the\n.QW target\nin the descriptions below.\n.PP\nThe \\fItype\\fR field of each entry in \\fIspecs\\fR determines what\nto do with the string value of that configuration option.  The\nlegal values for \\fItype\\fR, and the corresponding actions, are:\n.TP\n\\fBTK_CONFIG_ACTIVE_CURSOR\\fR\n.\nThe value\nmust be an ASCII string identifying a cursor in a form\nsuitable for passing to \\fBTk_GetCursor\\fR.\nThe value is converted to a \\fBTk_Cursor\\fR by calling\n\\fBTk_GetCursor\\fR and the result is stored in the target.\nIn addition, the resulting cursor is made the active cursor\nfor \\fItkwin\\fR by calling \\fBXDefineCursor\\fR.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target and \\fItkwin\\fR's\nactive cursor will be set to \\fBNone\\fR.\nIf the previous value of the target\nwas not \\fBNone\\fR, then it is freed by passing it to \\fBTk_FreeCursor\\fR.\n.TP\n\\fBTK_CONFIG_ANCHOR\\fR\n.\nThe value must be an ASCII string identifying an anchor point in one of the ways\naccepted by \\fBTk_GetAnchor\\fR.\nThe string is converted to a \\fBTk_Anchor\\fR by calling\n\\fBTk_GetAnchor\\fR and the result is stored in the target.\n.TP\n\\fBTK_CONFIG_BITMAP\\fR\n.\nThe value must be an ASCII string identifying a bitmap in a form\nsuitable for passing to \\fBTk_GetBitmap\\fR.  The value is converted\nto a \\fBPixmap\\fR by calling \\fBTk_GetBitmap\\fR and the result\nis stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target is set to \\fBNone\\fR.\nIf the previous value of the target\nwas not \\fBNone\\fR, then it is freed by passing it to \\fBTk_FreeBitmap\\fR.\n.TP\n\\fBTK_CONFIG_BOOLEAN\\fR\n.\nThe value must be an ASCII string specifying a boolean value.  Any\nof the values\n.QW true ,\n.QW yes ,\n.QW on ,\nor\n.QW 1 ,\nor an abbreviation of one of these values, means true;\nany of the values\n.QW false ,\n.QW no ,\n.QW off ,\nor\n.QW 0 ,\nor an abbreviation of one of these values, means false.\nThe target is expected to be an integer;  for true values it will\nbe set to 1 and for false values it will be set to 0.\n.TP\n\\fBTK_CONFIG_BORDER\\fR\n.\nThe value must be an ASCII string identifying a border color in a form\nsuitable for passing to \\fBTk_Get3DBorder\\fR.  The value is converted\nto a (\\fBTk_3DBorder *\\fR) by calling \\fBTk_Get3DBorder\\fR and the result\nis stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target will be set to NULL.\nIf the previous value of the target\nwas not NULL, then it is freed by passing it to \\fBTk_Free3DBorder\\fR.\n.TP\n\\fBTK_CONFIG_CAP_STYLE\\fR\n.\nThe value must be\nan ASCII string identifying a cap style in one of the ways\naccepted by \\fBTk_GetCapStyle\\fR.\nThe string is converted to an integer value corresponding\nto the cap style by calling\n\\fBTk_GetCapStyle\\fR and the result is stored in the target.\n.TP\n\\fBTK_CONFIG_COLOR\\fR\n.\nThe value must be an ASCII string identifying a color in a form\nsuitable for passing to \\fBTk_GetColor\\fR.  The value is converted\nto an (\\fBXColor *\\fR) by calling \\fBTk_GetColor\\fR and the result\nis stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target will be set to \\fBNone\\fR.\nIf the previous value of the target\nwas not NULL, then it is freed by passing it to \\fBTk_FreeColor\\fR.\n.TP\n\\fBTK_CONFIG_CURSOR\\fR\n.\nThis option is identical to \\fBTK_CONFIG_ACTIVE_CURSOR\\fR except\nthat the new cursor is not made the active one for \\fItkwin\\fR.\n.TP\n\\fBTK_CONFIG_CUSTOM\\fR\n.\nThis option allows applications to define new option types.\nThe \\fIcustomPtr\\fR field of the entry points to a structure\ndefining the new option type.\nSee the section \\fBCUSTOM OPTION TYPES\\fR below for details.\n.TP\n\\fBTK_CONFIG_DOUBLE\\fR\n.\nThe value must be an ASCII floating-point number in\nthe format accepted by \\fBstrtol\\fR.  The string is converted\nto a \\fBdouble\\fR value, and the value is stored in the\ntarget.\n.TP\n\\fBTK_CONFIG_END\\fR\n.\nMarks the end of the table.  The last entry in \\fIspecs\\fR\nmust have this type;  all of its other fields are ignored and it\nwill never match any arguments.\n.TP\n\\fBTK_CONFIG_FONT\\fR\n.\nThe value must be an ASCII string identifying a font in a form\nsuitable for passing to \\fBTk_GetFont\\fR.  The value is converted\nto a \\fBTk_Font\\fR by calling \\fBTk_GetFont\\fR and the result\nis stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target will be set to NULL.\nIf the previous value of the target\nwas not NULL, then it is freed by passing it to \\fBTk_FreeFont\\fR.\n.TP\n\\fBTK_CONFIG_INT\\fR\n.\nThe value must be an ASCII integer string\nin the format accepted by \\fBstrtol\\fR (e.g.\n.QW 0\nand\n.QW 0x\nprefixes may be used to specify octal or hexadecimal\nnumbers, respectively).  The string is converted to an integer\nvalue and the integer is stored in the target.\n.TP\n\\fBTK_CONFIG_JOIN_STYLE\\fR\n.\nThe value must be\nan ASCII string identifying a join style in one of the ways\naccepted by \\fBTk_GetJoinStyle\\fR.\nThe string is converted to an integer value corresponding\nto the join style by calling\n\\fBTk_GetJoinStyle\\fR and the result is stored in the target.\n.TP\n\\fBTK_CONFIG_JUSTIFY\\fR\n.\nThe value must be\nan ASCII string identifying a justification method in one of the\nways accepted by \\fBTk_GetJustify\\fR.\nThe string is converted to a \\fBTk_Justify\\fR by calling\n\\fBTk_GetJustify\\fR and the result is stored in the target.\n.TP\n\\fBTK_CONFIG_MM\\fR\n.\nThe value must specify a screen distance in one of the forms acceptable\nto \\fBTk_GetScreenMM\\fR.\nThe string is converted to double-precision floating-point distance\nin millimeters and the value is stored in the target.\n.TP\n\\fBTK_CONFIG_PIXELS\\fR\n.\nThe value must specify screen units in one of the forms acceptable\nto \\fBTk_GetPixels\\fR.\nThe string is converted to an integer distance in pixels and the\nvalue is stored in the target.\n.TP\n\\fBTK_CONFIG_RELIEF\\fR\n.\nThe value must be an ASCII string identifying a relief in a form\nsuitable for passing to \\fBTk_GetRelief\\fR.  The value is converted\nto an integer relief value by calling \\fBTk_GetRelief\\fR and the result\nis stored in the target.\n.TP\n\\fBTK_CONFIG_STRING\\fR\n.\nA copy of the value is made by allocating memory space with\n\\fBTcl_Alloc\\fR and copying the value into the dynamically-allocated\nspace.  A pointer to the new string is stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR then the value\nmay be an empty string, in which case the target will be set to NULL.\nIf the previous value of the target was not NULL, then it is\nfreed by passing it to \\fBTcl_Free\\fR.\n.TP\n\\fBTK_CONFIG_SYNONYM\\fR\n.\nThis \\fItype\\fR value identifies special entries in \\fIspecs\\fR that\nare synonyms for other entries.  If an \\fIobjv\\fR value matches the\n\\fIargvName\\fR of a \\fBTK_CONFIG_SYNONYM\\fR entry, the entry is not used\ndirectly. Instead, \\fBTk_ConfigureWidget\\fR searches \\fIspecs\\fR\nfor another entry whose \\fIargvName\\fR is the same as the \\fIdbName\\fR\nfield in the \\fBTK_CONFIG_SYNONYM\\fR entry;  this new entry is used just\nas if its \\fIargvName\\fR had matched the \\fIobjv\\fR value.  The\nsynonym mechanism allows multiple \\fIobjv\\fR values to be used for\na single configuration option, such as\n.QW \\-background\nand\n.QW \\-bg .\n.TP\n\\fBTK_CONFIG_UID\\fR\n.\nThe value is translated to a \\fBTk_Uid\\fR\n(by passing it to \\fBTk_GetUid\\fR).  The resulting value\nis stored in the target.\nIf \\fBTK_CONFIG_NULL_OK\\fR is specified in \\fIspecFlags\\fR and the value\nis an empty string then the target will be set to NULL.\n.TP\n\\fBTK_CONFIG_WINDOW\\fR\n.\nThe value must be a window path name.  It is translated to a\n\\fBTk_Window\\fR token and the token is stored in the target.\n.SH \"GROUPED ENTRIES\"\n.PP\nIn some cases it is useful to generate multiple resources from\na single configuration value.  For example, a color name might\nbe used both to generate the background color for a widget (using\n\\fBTK_CONFIG_COLOR\\fR) and to generate a 3-D border to draw around the\nwidget (using \\fBTK_CONFIG_BORDER\\fR).  In cases like this it is possible\nto specify that several consecutive entries in \\fIspecs\\fR are to\nbe treated as a group.  The first entry is used to determine a value\n(using its \\fIargvName\\fR, \\fIdbName\\fR,\n\\fIdbClass\\fR, and \\fIdefValue\\fR fields).  The value will be processed\nseveral times (one for each entry in the group), generating multiple\ndifferent resources and modifying multiple targets within \\fIwidgRec\\fR.\nEach of the entries after the first must have a NULL value in its\n\\fIargvName\\fR field;  this indicates that the entry is to be grouped\nwith the entry that precedes it.  Only the \\fItype\\fR and \\fIoffset\\fR\nfields are used from these follow-on entries.\n.SH \"FLAGS\"\n.PP\nThe \\fIflags\\fR argument passed to \\fBTk_ConfigureWidget\\fR is used\nin conjunction with the \\fIspecFlags\\fR fields in the entries of \\fIspecs\\fR\nto provide additional control over the processing of configuration\noptions.  These values are used in three different ways as\ndescribed below.\n.PP\nFirst, if the \\fIflags\\fR argument to \\fBTk_ConfigureWidget\\fR has\nthe \\fBTK_CONFIG_ARGV_ONLY\\fR bit set\n(i.e., \\fIflags\\fR | \\fBTK_CONFIG_ARGV_ONLY\\fR != 0),\nthen the option database and\n\\fIdefValue\\fR fields are not used.  In this case, if an entry in\n\\fIspecs\\fR does not match a field in \\fIobjv\\fR then nothing happens:\nthe corresponding target is not modified.  This feature is useful\nwhen the goal is to modify certain configuration options while\nleaving others in their current state, such as when a \\fBconfigure\\fR\nwidget command is being processed.\n.PP\nSecond, the \\fIspecFlags\\fR field of an entry in \\fIspecs\\fR may be used\nto control the processing of that entry.  Each \\fIspecFlags\\fR\nfield may consists of an OR-ed combination of the following values:\n.TP\n\\fBTK_CONFIG_COLOR_ONLY\\fR\n.\nIf this bit is set then the entry will only be considered if the\ndisplay for \\fItkwin\\fR has more than one bit plane.  If the display\nis monochromatic then this \\fIspecs\\fR entry will be ignored.\n.TP\n\\fBTK_CONFIG_MONO_ONLY\\fR\n.\nIf this bit is set then the entry will only be considered if the\ndisplay for \\fItkwin\\fR has exactly one bit plane.  If the display\nis not monochromatic then this \\fIspecs\\fR entry will be ignored.\n.TP\n\\fBTK_CONFIG_NULL_OK\\fR\n.\nThis bit is only relevant for some types of entries (see the\ndescriptions of the various entry types above).\nIf this bit is set, it indicates that an empty string value\nfor the field is acceptable and if it occurs then the\ntarget should be set to NULL or \\fBNone\\fR, depending\non the type of the target.\nThis flag is typically used to allow a\nfeature to be turned off entirely, e.g. set a cursor value to\n\\fBNone\\fR so that a window simply inherits its parent's cursor.\nIf this bit is not set then empty strings are processed as strings,\nwhich generally results in an error.\n.TP\n\\fBTK_CONFIG_DONT_SET_DEFAULT\\fR\n.\nIf this bit is one, it means that the \\fIdefValue\\fR field of the\nentry should only be used for returning the default value in\n\\fBTk_ConfigureInfo\\fR.\nIn calls to \\fBTk_ConfigureWidget\\fR no default will be supplied\nfor entries with this flag set;  it is assumed that the\ncaller has already supplied a default value in the target location.\nThis flag provides a performance optimization where it is expensive\nto process the default string:  the client can compute the default\nonce, save the value, and provide it before calling\n\\fBTk_ConfigureWidget\\fR.\n.PP\nThe \\fBTK_CONFIG_MONO_ONLY\\fR and \\fBTK_CONFIG_COLOR_ONLY\\fR flags are typically\nused to specify different default values for\nmonochrome and color displays.  This is done by creating two\nentries in \\fIspecs\\fR that are identical except for their\n\\fIdefValue\\fR and \\fIspecFlags\\fR fields.  One entry should have\nthe value \\fBTK_CONFIG_MONO_ONLY\\fR in its \\fIspecFlags\\fR and the\ndefault value for monochrome displays in its \\fIdefValue\\fR;  the\nother entry should have the value \\fBTK_CONFIG_COLOR_ONLY\\fR in\nits \\fIspecFlags\\fR and the appropriate \\fIdefValue\\fR for\ncolor displays.\n.PP\nThird, it is possible to use \\fIflags\\fR and \\fIspecFlags\\fR\ntogether to selectively disable some entries.  This feature is\nnot needed very often.  It is useful in cases where several\nsimilar kinds of widgets are implemented in one place.  It allows\na single \\fIspecs\\fR table to be created with all the configuration\noptions for all the widget types.  When processing a particular\nwidget type, only entries relevant to that type will be used.  This\neffect is achieved by setting the high-order bits (those in positions\nequal to or greater than \\fBTK_CONFIG_USER_BIT\\fR) in \\fIspecFlags\\fR\nvalues or in \\fIflags\\fR.  In order for a particular entry in\n\\fIspecs\\fR to be used, its high-order bits must match exactly\nthe high-order bits of the \\fIflags\\fR value passed to\n\\fBTk_ConfigureWidget\\fR.  If a \\fIspecs\\fR table is being used\nfor N different widget types, then N of the high-order bits will\nbe used.  Each \\fIspecs\\fR entry will have one of more of those\nbits set in its \\fIspecFlags\\fR field to indicate the widget types\nfor which this entry is valid.  When calling \\fBTk_ConfigureWidget\\fR,\n\\fIflags\\fR will have a single one of these bits set to select the\nentries for the desired widget type.  For a working example of\nthis feature, see the code in tkButton.c.\n.SH TK_CONFIGUREINFO\n.PP\nThe \\fBTk_ConfigureInfo\\fR procedure may be used to obtain\ninformation about one or all of the options for a given widget.\nGiven a token for a window (\\fItkwin\\fR), a table describing the\nconfiguration options for a class of widgets (\\fIspecs\\fR), a\npointer to a widget record containing the current information for\na widget (\\fIwidgRec\\fR), and a NULL \\fIargvName\\fR argument,\n\\fBTk_ConfigureInfo\\fR generates a string describing all of the\nconfiguration options for the window.  The string is placed\nin interpreter \\fIinterp\\fR's result.  Under normal circumstances\nit returns \\fBTCL_OK\\fR;  if an error occurs then it returns \\fBTCL_ERROR\\fR\nand the interpreter's result will contain an error message.\n.PP\nIf \\fIargvName\\fR is NULL, then the value left in\nthe interpreter's result by \\fBTk_ConfigureInfo\\fR\nconsists of a list of one or more entries, each of which describes\none configuration option (i.e. one entry in \\fIspecs\\fR).  Each\nentry in the list will contain either two or five values.  If the\ncorresponding entry in \\fIspecs\\fR has type \\fBTK_CONFIG_SYNONYM\\fR, then\nthe list will contain two values:  the \\fIargvName\\fR for the entry\nand the \\fIdbName\\fR (synonym name).  Otherwise the list will contain\nfive values:  \\fIargvName\\fR, \\fIdbName\\fR, \\fIdbClass\\fR, \\fIdefValue\\fR,\nand current value.  The current value is computed from the appropriate\nfield of \\fIwidgRec\\fR by calling procedures like \\fBTk_NameOfColor\\fR.\n.PP\nIf the \\fIargvName\\fR argument to \\fBTk_ConfigureInfo\\fR is non-NULL,\nthen it indicates a single option, and information is returned only\nfor that option.  The string placed in the interpreter's result will be\na list containing two or five values as described above;  this will\nbe identical to the corresponding sublist that would have been returned\nif \\fIargvName\\fR had been NULL.\n.PP\nThe \\fIflags\\fR argument to \\fBTk_ConfigureInfo\\fR is used to restrict\nthe \\fIspecs\\fR entries to consider, just as for \\fBTk_ConfigureWidget\\fR.\n.SH TK_CONFIGUREVALUE\n.PP\n\\fBTk_ConfigureValue\\fR takes arguments similar to \\fBTk_ConfigureInfo\\fR;\ninstead of returning a list of values, it just returns the current value\nof the option given by \\fIargvName\\fR (\\fIargvName\\fR must not be NULL).\nThe value is returned in interpreter \\fIinterp\\fR's result and \\fBTCL_OK\\fR is\nnormally returned as the procedure's result.\nIf an error occurs in \\fBTk_ConfigureValue\\fR (e.g., \\fIargvName\\fR is\nnot a valid option name), \\fBTCL_ERROR\\fR is returned and an error message\nis left in the interpreter's result.\nThis procedure is typically called to implement \\fBcget\\fR widget\ncommands.\n.SH TK_FREEOPTIONS\n.PP\nThe \\fBTk_FreeOptions\\fR procedure may be invoked during widget cleanup\nto release all of the resources associated with configuration options.\nIt scans through \\fIspecs\\fR and for each entry corresponding to a\nresource that must be explicitly freed (e.g. those with\ntype \\fBTK_CONFIG_COLOR\\fR), it frees the resource in the widget record.\nIf the field in the widget record does not refer to a resource (e.g.\nit contains a null pointer) then no resource is freed for that\nentry.\nAfter freeing a resource, \\fBTk_FreeOptions\\fR sets the\ncorresponding field of the widget record to null.\n.SH \"CUSTOM OPTION TYPES\"\n.PP\nApplications can extend the built-in configuration types with additional\nconfiguration types by writing procedures to parse and print options\nof the a type and creating a structure pointing to those procedures:\n.CS\ntypedef struct {\n    Tk_OptionParseProc *\\fIparseProc\\fR;\n    Tk_OptionPrintProc *\\fIprintProc\\fR;\n    void *\\fIclientData\\fR;\n} \\fBTk_CustomOption\\fR;\n\ntypedef int \\fBTk_OptionParseProc\\fR(\n        void *\\fIclientData\\fR,\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Window \\fItkwin\\fR,\n        const char *\\fIvalue\\fR,\n        char *\\fIwidgRec\\fR,\n        Tcl_Size \\fIoffset\\fR);\n\ntypedef const char *\\fBTk_OptionPrintProc\\fR(\n        void *\\fIclientData\\fR,\n        Tk_Window \\fItkwin\\fR,\n        char *\\fIwidgRec\\fR,\n        Tcl_Size \\fIoffset\\fR,\n        Tcl_FreeProc **\\fIfreeProcPtr\\fR);\n.CE\nThe Tk_CustomOption structure contains three fields, which are pointers\nto the two procedures and a \\fIclientData\\fR value to be passed to those\nprocedures when they are invoked.  The \\fIclientData\\fR value typically\npoints to a structure containing information that is needed by the\nprocedures when they are parsing and printing options.\n.PP\nThe \\fIparseProc\\fR procedure is invoked by\n\\fBTk_ConfigureWidget\\fR to parse a string and store the resulting\nvalue in the widget record.\nThe \\fIclientData\\fR argument is a copy of the \\fIclientData\\fR\nfield in the Tk_CustomOption structure.\nThe \\fIinterp\\fR argument points to a Tcl interpreter used for\nerror reporting.  \\fITkwin\\fR is a copy of the \\fItkwin\\fR argument\nto \\fBTk_ConfigureWidget\\fR.  The \\fIvalue\\fR argument is a string\ndescribing the value for the option;  it could have been specified\nexplicitly in the call to \\fBTk_ConfigureWidget\\fR or it could\ncome from the option database or a default.\n\\fIValue\\fR will never be a null pointer but it may point to\nan empty string.\n\\fIRecordPtr\\fR is the same as the \\fIwidgRec\\fR argument to\n\\fBTk_ConfigureWidget\\fR;  it points to the start of the widget\nrecord to modify.\nThe last argument, \\fIoffset\\fR, gives the offset in bytes from the start\nof the widget record to the location where the option value is to\nbe placed.  The procedure should translate the string to whatever\nform is appropriate for the option and store the value in the widget\nrecord.  It should normally return \\fBTCL_OK\\fR, but if an error occurs\nin translating the string to a value then it should return \\fBTCL_ERROR\\fR\nand store an error message in interpreter \\fIinterp\\fR's result.\n.PP\nThe \\fIprintProc\\fR procedure is called\nby \\fBTk_ConfigureInfo\\fR to produce a string value describing an\nexisting option.\nIts \\fIclientData\\fR, \\fItkwin\\fR, \\fIwidgRec\\fR, and \\fIoffset\\fR\narguments all have the same meaning as for Tk_OptionParseProc\nprocedures.\nThe \\fIprintProc\\fR procedure should examine the option whose value\nis stored at \\fIoffset\\fR in \\fIwidgRec\\fR, produce a string describing\nthat option, and return a pointer to the string.\nIf the string is stored in dynamically-allocated memory, then\nthe procedure must set \\fI*freeProcPtr\\fR to the address of\na procedure to call to free the string's memory;  \\fBTk_ConfigureInfo\\fR\nwill call this procedure when it is finished with the string.\nIf the result string is stored in static memory then \\fIprintProc\\fR\nneed not do anything with the \\fIfreeProcPtr\\fR argument.\n.PP\nOnce \\fIparseProc\\fR and \\fIprintProc\\fR have been defined and a\nTk_CustomOption structure has been created for them, options of this\nnew type may be manipulated with Tk_ConfigSpec entries whose \\fItype\\fR\nfields are \\fBTK_CONFIG_CUSTOM\\fR and whose \\fIcustomPtr\\fR fields point\nto the Tk_CustomOption structure.\n.SH EXAMPLES\n.PP\nAlthough the explanation of \\fBTk_ConfigureWidget\\fR is fairly\ncomplicated, its actual use is pretty straightforward.\nThe easiest way to get started is to copy the code\nfrom an existing widget.\nThe library implementation of frames\n(tkFrame.c) has a simple configuration table, and the library\nimplementation of buttons (tkButton.c) has a much more complex\ntable that uses many of the fancy \\fIspecFlags\\fR mechanisms.\n.SH \"SEE ALSO\"\nTk_SetOptions(3)\n.SH KEYWORDS\nanchor, bitmap, boolean, border, cap style, color, configuration options,\ncursor, custom, double, font, integer, join style, justify, millimeters,\npixels, relief, synonym, uid\n"
  },
  {
    "path": "doc/ConfigWind.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ConfigureWindow 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ConfigureWindow, Tk_MoveWindow, Tk_ResizeWindow, Tk_MoveResizeWindow, Tk_SetWindowBorderWidth, Tk_ChangeWindowAttributes, Tk_SetWindowBackground, Tk_SetWindowBackgroundPixmap, Tk_SetWindowBorder, Tk_SetWindowBorderPixmap, Tk_SetWindowColormap, Tk_DefineCursor, Tk_UndefineCursor \\- change window configuration or attributes\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_ConfigureWindow\\fR(\\fItkwin, valueMask, valuePtr\\fR)\n.sp\n\\fBTk_MoveWindow\\fR(\\fItkwin, x, y\\fR)\n.sp\n\\fBTk_ResizeWindow\\fR(\\fItkwin, width, height\\fR)\n.sp\n\\fBTk_MoveResizeWindow\\fR(\\fItkwin, x,  y, width, height\\fR)\n.sp\n\\fBTk_SetWindowBorderWidth\\fR(\\fItkwin, borderWidth\\fR)\n.sp\n\\fBTk_ChangeWindowAttributes\\fR(\\fItkwin, valueMask, attsPtr\\fR)\n.sp\n\\fBTk_SetWindowBackground\\fR(\\fItkwin, pixel\\fR)\n.sp\n\\fBTk_SetWindowBackgroundPixmap\\fR(\\fItkwin, pixmap\\fR)\n.sp\n\\fBTk_SetWindowBorder\\fR(\\fItkwin, pixel\\fR)\n.sp\n\\fBTk_SetWindowBorderPixmap\\fR(\\fItkwin, pixmap\\fR)\n.sp\n\\fBTk_SetWindowColormap\\fR(\\fItkwin, colormap\\fR)\n.sp\n\\fBTk_DefineCursor\\fR(\\fItkwin, cursor\\fR)\n.sp\n\\fBTk_UndefineCursor\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS XSetWindowAttributes borderWidth\n.AP Tk_Window tkwin in\nToken for window.\n.AP \"unsigned int\" valueMask in\nOR-ed mask of values like \\fBCWX\\fR or \\fBCWBorderPixel\\fR,\nindicating which fields of \\fI*valuePtr\\fR or \\fI*attsPtr\\fR to use.\n.AP XWindowChanges *valuePtr in\nPoints to a structure containing new values for the configuration\nparameters selected by \\fIvalueMask\\fR.  Fields not selected\nby \\fIvalueMask\\fR are ignored.\n.AP int x in\nNew x-coordinate for \\fItkwin\\fR's top left pixel (including\nborder, if any) within tkwin's parent.\n.AP int y in\nNew y-coordinate for \\fItkwin\\fR's top left pixel (including\nborder, if any) within tkwin's parent.\n.AP \"int\" width in\nNew width for \\fItkwin\\fR (interior, not including border).\n.AP \"int\" height in\nNew height for \\fItkwin\\fR (interior, not including border).\n.AP \"int\" borderWidth in\nNew width for \\fItkwin\\fR's border.\n.AP XSetWindowAttributes *attsPtr in\nPoints to a structure containing new values for the attributes\ngiven by the \\fIvalueMask\\fR argument.  Attributes not selected\nby \\fIvalueMask\\fR are ignored.\n.AP \"unsigned long\" pixel in\nNew background or border color for window.\n.AP Pixmap pixmap in\nNew pixmap to use for background or border of \\fItkwin\\fR.  WARNING:\ncannot necessarily be deleted immediately, as for Xlib calls.  See\nnote below.\n.AP Colormap colormap in\nNew colormap to use for \\fItkwin\\fR.\n.AP Tk_Cursor cursor in\nNew cursor to use for \\fItkwin\\fR.  If \\fBNone\\fR is specified, then\n\\fItkwin\\fR will not have its own cursor;  it will use the cursor\nof its parent.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are analogous to the X library procedures\nwith similar names, such as \\fBXConfigureWindow\\fR.  Each\none of the above procedures calls the corresponding X procedure\nand also saves the configuration information in Tk's local\nstructure for the window.  This allows the information to\nbe retrieved quickly by the application (using macros such\nas \\fBTk_X\\fR and \\fBTk_Height\\fR) without having to contact\nthe X server.  In addition, if no X window has actually been\ncreated for \\fItkwin\\fR yet, these procedures do not issue\nX operations or cause event handlers to be invoked;  they save\nthe information in Tk's local\nstructure for the window;  when the window is created later,\nthe saved information will be used to configure the window.\n.PP\nSee the X library documentation for details on what these\nprocedures do and how they use their arguments.\n.PP\nIn the procedures \\fBTk_ConfigureWindow\\fR, \\fBTk_MoveWindow\\fR,\n\\fBTk_ResizeWindow\\fR, \\fBTk_MoveResizeWindow\\fR, and\n\\fBTk_SetWindowBorderWidth\\fR,\nif \\fItkwin\\fR is an internal window then event handlers interested\nin configure events are invoked immediately, before the procedure\nreturns.  If \\fItkwin\\fR is a top-level window\nthen the event handlers will be invoked later, after X has seen\nthe request and returned an event for it.\n.PP\nApplications using Tk should never call procedures like\n\\fBXConfigureWindow\\fR directly;  they should always use the\ncorresponding Tk procedures.\n.PP\nThe size and location of a window should only be modified by the\nappropriate geometry manager for that window and never by a window\nitself (but see \\fBTk_MoveToplevelWindow\\fR for moving a top-level\nwindow).\n.PP\nYou may not use \\fBTk_ConfigureWindow\\fR to change the\nstacking order of a window (\\fIvalueMask\\fR may not contain the\n\\fBCWSibling\\fR or \\fBCWStackMode\\fR bits).\nTo change the stacking order, use the procedure \\fBTk_RestackWindow\\fR.\n.PP\nThe procedure \\fBTk_SetWindowColormap\\fR will automatically add\n\\fItkwin\\fR to the \\fBTK_COLORMAP_WINDOWS\\fR property of its\nnearest top-level ancestor if the new colormap is different from\nthat of \\fItkwin\\fR's parent and \\fItkwin\\fR is not already in\nthe \\fBTK_COLORMAP_WINDOWS\\fR property.\n.SH BUGS\n.PP\n\\fBTk_SetWindowBackgroundPixmap\\fR and \\fBTk_SetWindowBorderPixmap\\fR\ndiffer slightly from their Xlib counterparts in that the \\fIpixmap\\fR\nargument may not necessarily be deleted immediately after calling\none of these procedures.  This is because \\fItkwin\\fR's window\nmay not exist yet at the time of the call, in which case \\fIpixmap\\fR\nis merely saved and used later when \\fItkwin\\fR's window is actually\ncreated.  If you wish to delete \\fIpixmap\\fR, then call\n\\fBTk_MakeWindowExist\\fR first to be sure that \\fItkwin\\fR's window exists\nand \\fIpixmap\\fR has been passed to the X server.\n.PP\nA similar problem occurs for the \\fIcursor\\fR argument passed to\n\\fBTk_DefineCursor\\fR.  The solution is the same as for pixmaps above:\ncall \\fBTk_MakeWindowExist\\fR before freeing the cursor.\n.SH \"SEE ALSO\"\nTk_MoveToplevelWindow, Tk_RestackWindow\n.SH KEYWORDS\nattributes, border, color, configure, height, pixel, pixmap, width, window, x, y\n"
  },
  {
    "path": "doc/CoordToWin.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CoordsToWindow 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CoordsToWindow \\- Find window containing a point\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_CoordsToWindow\\fR(\\fIrootX, rootY, tkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP int rootX in\nX-coordinate (in root window coordinates).\n.AP int rootY in\nY-coordinate (in root window coordinates).\n.AP Tk_Window tkwin in\nToken for window that identifies application.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CoordsToWindow\\fR locates the window that contains a given point.\nThe point is specified in root coordinates with \\fIrootX\\fR and\n\\fIrootY\\fR (if a virtual-root window manager is in use then\n\\fIrootX\\fR and \\fIrootY\\fR are in the coordinate system of the\nvirtual root window).\nThe return value from the procedure is a token for the window that\ncontains the given point.\nIf the point is not in any window, or if the containing window\nis not in the same application as \\fItkwin\\fR, then NULL is\nreturned.\n.PP\nThe containing window is decided using the same rules that determine\nwhich window contains the mouse cursor:  if a parent and a child both\ncontain the point then the child gets preference, and if two siblings\nboth contain the point then the highest one in the stacking order\n(i.e. the one that's visible on the screen) gets preference.\n.SH KEYWORDS\ncontaining, coordinates, root window\n"
  },
  {
    "path": "doc/CrtCmHdlr.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2000 Ajuba Solutions.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateClientMessageHandler 3 \"8.4\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateClientMessageHandler, Tk_DeleteClientMessageHandler \\- associate procedure callback with ClientMessage type X events\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateClientMessageHandler\\fR(\\fIproc\\fR)\n.sp\n\\fBTk_DeleteClientMessageHandler\\fR(\\fIproc\\fR)\n.fi\n.SH ARGUMENTS\n.AP Tk_ClientMessageProc *proc in\nProcedure to invoke whenever a ClientMessage X event occurs on any display.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateClientMessageHandler\\fR arranges for \\fIproc\\fR to be invoked\nin the future whenever a ClientMessage X event occurs that is not handled by\n\\fBWM_PROTOCOL\\fR.  \\fBTk_CreateClientMessageHandler\\fR is intended for use\nby applications which need to watch X ClientMessage events, such as drag and\ndrop applications.\n.PP\nThe callback to \\fIproc\\fR will be made by \\fBTk_HandleEvent\\fR;\nthis mechanism only works in programs that dispatch events\nthrough \\fBTk_HandleEvent\\fR (or through other Tk procedures that\ncall \\fBTk_HandleEvent\\fR, such as \\fBTcl_DoOneEvent\\fR or\n\\fBTk_MainLoop\\fR).\n.PP\n\\fIProc\\fR should have arguments and result that match the\ntype \\fBTk_ClientMessageProc\\fR:\n.CS\ntypedef int \\fBTk_ClientMessageProc\\fR(\n        Tk_Window \\fItkwin\\fR,\n        XEvent *\\fIeventPtr\\fR);\n.CE\nThe \\fItkwin\\fR parameter to \\fIproc\\fR is the Tk window which is\nassociated with this event.  \\fIEventPtr\\fR is a pointer to the X event.\n.PP\nWhenever an X ClientMessage event is processed by \\fBTk_HandleEvent\\fR,\nthe \\fIproc\\fR is called if it was not handled as a \\fBWM_PROTOCOL\\fR.\nThe return value from \\fIproc\\fR is normally 0.\nA non-zero return value indicates that the event is not to be handled\nfurther; that is, \\fIproc\\fR has done all processing that is to be\nallowed for the event.\n.PP\nIf there are multiple ClientMessage event handlers, each one is called\nfor each event, in the order in which they were established.\n.PP\n\\fBTk_DeleteClientMessageHandler\\fR may be called to delete a\npreviously-created ClientMessage event handler: it deletes each handler it\nfinds that matches the \\fIproc\\fR argument.  If no such handler exists,\nthen \\fBTk_DeleteClientMessageHandler\\fR returns without doing anything.\nAlthough Tk supports it, it's probably a bad idea to have more than one\ncallback with the same \\fIproc\\fR argument.\n.SH KEYWORDS\nbind, callback, event, handler\n"
  },
  {
    "path": "doc/CrtConsoleChan.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2007 ActiveState Software Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_InitConsoleChannels 3 8.5 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_InitConsoleChannels \\- Install the console channels as standard channels\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_InitConsoleChannels\\fR(\\fIinterp\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *interp in\n.AP Tcl_Interp *interp in\nInterpreter in which the console channels are created.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_InitConsoleChannels\\fR is invoked to create a set of console\nchannels and install them as the standard channels. All I/O on these\nchannels will be discarded until \\fBTk_CreateConsoleWindow\\fR is\ncalled to attach the console to a text widget.\n.PP\nThis function is for use by shell applications based on Tk, like\n\\fBwish\\fR, on platforms which have no standard channels in graphical\nmode, like Win32.\n.PP\nThe \\fIinterp\\fR argument is the interpreter in which to create and\ninstall the console channels.\n.PP\n\\fBNOTE:\\fR If this function is used it has to be called before the\nfirst call to \\fBTcl_RegisterChannel\\fR, directly, or indirectly\nthrough other channel functions. Because otherwise the standard\nchannels will be already initialized to the system defaults, which will\nbe nonsensical for the case \\fBTk_InitConsoleChannels\\fR is for.\n.SH \"SEE ALSO\"\nconsole(n)\n.SH KEYWORDS\nstandard channels, console\n"
  },
  {
    "path": "doc/CrtErrHdlr.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateErrorHandler 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateErrorHandler, Tk_DeleteErrorHandler \\- handle X protocol errors\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_ErrorHandler\n\\fBTk_CreateErrorHandler\\fR(\\fIdisplay, error, request, minor, proc, clientData\\fR)\n.sp\n\\fBTk_DeleteErrorHandler\\fR(\\fIhandler\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_ErrorHandler\" clientData\n.AP Display *display in\nDisplay whose errors are to be handled.\n.AP int error in\nMatch only error events with this value in the \\fIerror_code\\fR\nfield.  If \\-1, then match any \\fIerror_code\\fR value.\n.AP int request in\nMatch only error events with this value in the \\fIrequest_code\\fR\nfield.  If \\-1, then match any \\fIrequest_code\\fR value.\n.AP int minor in\nMatch only error events with this value in the \\fIminor_code\\fR\nfield.  If \\-1, then match any \\fIminor_code\\fR value.\n.AP Tk_ErrorProc *proc in\nProcedure to invoke whenever an error event is received for\n\\fIdisplay\\fR and matches \\fIerror\\fR, \\fIrequest\\fR, and \\fIminor\\fR.\nNULL means ignore any matching errors.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.AP Tk_ErrorHandler handler in\nToken for error handler to delete (return value from a previous\ncall to \\fBTk_CreateErrorHandler\\fR).\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateErrorHandler\\fR arranges for a particular procedure\n(\\fIproc\\fR) to be called whenever certain protocol errors occur on a\nparticular display (\\fIdisplay\\fR).  Protocol errors occur when\nthe X protocol is used incorrectly, such as attempting to map a window\nthat does not exist.  See the Xlib documentation for \\fBXSetErrorHandler\\fR\nfor more information on the kinds of errors that can occur.\nFor \\fIproc\\fR to be invoked\nto handle a particular error, five things must occur:\n.IP [1]\nThe error must pertain to \\fIdisplay\\fR.\n.IP [2]\nEither the \\fIerror\\fR argument to \\fBTk_CreateErrorHandler\\fR\nmust have been \\-1, or the \\fIerror\\fR argument must match\nthe \\fIerror_code\\fR field from the error event.\n.IP [3]\nEither the \\fIrequest\\fR argument to \\fBTk_CreateErrorHandler\\fR\nmust have been \\-1, or the \\fIrequest\\fR argument must match\nthe \\fIrequest_code\\fR field from the error event.\n.IP [4]\nEither the \\fIminor\\fR argument to \\fBTk_CreateErrorHandler\\fR\nmust have been \\-1, or the \\fIminor\\fR argument must match\nthe \\fIminor_code\\fR field from the error event.\n.IP [5]\nThe protocol request to which the error pertains must have been\nmade when the handler was active (see below for more information).\n.PP\n\\fIProc\\fR should have arguments and result that match the\nfollowing type:\n.CS\ntypedef int \\fBTk_ErrorProc\\fR(\n        void *\\fIclientData\\fR,\n        XErrorEvent *\\fIerrEventPtr\\fR);\n.CE\nThe \\fIclientData\\fR parameter to \\fIproc\\fR is a copy of the \\fIclientData\\fR\nargument given to \\fBTcl_CreateErrorHandler\\fR when the callback\nwas created.  Typically, \\fIclientData\\fR points to a data\nstructure containing application-specific information that is\nneeded to deal with the error.  \\fIErrEventPtr\\fR is\na pointer to the X error event.\nThe procedure \\fIproc\\fR should return an integer value.  If it\nreturns 0 it means that \\fIproc\\fR handled the error completely and there\nis no need to take any other action for the error.  If it returns\nnon-zero it means \\fIproc\\fR was unable to handle the error.\n.PP\nIf a value of NULL is specified for \\fIproc\\fR, all matching errors\nwill be ignored:  this will produce the same result as if a procedure\nhad been specified that always returns 0.\n.PP\nIf more than more than one handler matches a particular error, then\nthey are invoked in turn.  The handlers will be invoked in reverse\norder of creation:  most recently declared handler first.\nIf any handler returns 0, then subsequent (older) handlers will\nnot be invoked.  If no handler returns 0, then Tk invokes X's\ndefault error handler, which prints an error message and aborts the\nprogram.  If you wish to have a default handler that deals with errors\nthat no other handler can deal with, then declare it first.\n.PP\nThe X documentation states that\n.QW \"the error handler should not call any functions (directly or indirectly) on the display that will generate protocol requests or that will look for input events.\"\nThis restriction applies to handlers declared by \\fBTk_CreateErrorHandler\\fR;\ndisobey it at your own risk.\n.PP\n\\fBTk_DeleteErrorHandler\\fR may be called to delete a\npreviously-created error handler.  The \\fIhandler\\fR argument\nidentifies the error handler, and should be a value returned by\na previous call to \\fBTk_CreateEventHandler\\fR.\n.PP\nA particular error handler applies to errors resulting\nfrom protocol requests generated between\nthe call to \\fBTk_CreateErrorHandler\\fR and the call to\n\\fBTk_DeleteErrorHandler\\fR.  However, the actual callback\nto \\fIproc\\fR may not occur until after the \\fBTk_DeleteErrorHandler\\fR\ncall, due to buffering in the client and server.\nIf an error event pertains to\na protocol request made just before calling \\fBTk_DeleteErrorHandler\\fR,\nthen the error event may not have been processed\nbefore the \\fBTk_DeleteErrorHandler\\fR\ncall.  When this situation arises, Tk will save information about\nthe handler and\ninvoke the handler's \\fIproc\\fR later when the error event\nfinally arrives.\nIf an application wishes to delete an error handler and know\nfor certain that all relevant errors have been processed,\nit should first call \\fBTk_DeleteErrorHandler\\fR and then\ncall \\fBXSync\\fR;  this will flush out any buffered requests and errors,\nbut will result in a performance penalty because\nit requires communication to and from the X server.  After the\n\\fBXSync\\fR call Tk is guaranteed not to call any error\nhandlers deleted before the \\fBXSync\\fR call.\n.PP\nFor the Tk error handling mechanism to work properly, it is essential\nthat application code never calls \\fBXSetErrorHandler\\fR directly;\napplications should use only \\fBTk_CreateErrorHandler\\fR.\n.SH KEYWORDS\ncallback, error, event, handler\n"
  },
  {
    "path": "doc/CrtGenHdlr.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1992-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateGenericHandler 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateGenericHandler, Tk_DeleteGenericHandler \\- associate procedure callback with all X events\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateGenericHandler\\fR(\\fIproc, clientData\\fR)\n.sp\n\\fBTk_DeleteGenericHandler\\fR(\\fIproc, clientData\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_GenericProc\" clientData\n.AP Tk_GenericProc *proc in\nProcedure to invoke whenever any X event occurs on any display.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateGenericHandler\\fR arranges for \\fIproc\\fR to be\ninvoked in the future whenever any X event occurs.  This mechanism is\n\\fInot\\fR intended for dispatching X events on windows managed by Tk\n(you should use \\fBTk_CreateEventHandler\\fR for this purpose).\n\\fBTk_CreateGenericHandler\\fR is intended for other purposes, such\nas tracing X events, monitoring events on windows not owned by Tk,\naccessing X-related libraries that were not originally designed for\nuse with Tk, and so on.\n.PP\nThe callback to \\fIproc\\fR will be made by \\fBTk_HandleEvent\\fR;\nthis mechanism only works in programs that dispatch events\nthrough \\fBTk_HandleEvent\\fR (or through other Tk procedures that\ncall \\fBTk_HandleEvent\\fR, such as \\fBTcl_DoOneEvent\\fR or\n\\fBTk_MainLoop\\fR).\n.PP\n\\fIProc\\fR should have arguments and result that match the\ntype \\fBTk_GenericProc\\fR:\n.CS\ntypedef int \\fBTk_GenericProc\\fR(\n        void *\\fIclientData\\fR,\n        XEvent *\\fIeventPtr\\fR);\n.CE\nThe \\fIclientData\\fR parameter to \\fIproc\\fR is a copy of the \\fIclientData\\fR\nargument given to \\fBTk_CreateGenericHandler\\fR when the callback\nwas created.  Typically, \\fIclientData\\fR points to a data\nstructure containing application-specific information about\nhow to handle events.\n\\fIEventPtr\\fR is a pointer to the X event.\n.PP\nWhenever an X event is processed by \\fBTk_HandleEvent\\fR, \\fIproc\\fR\nis called.  The return value from \\fIproc\\fR is normally 0.\nA non-zero return value indicates that the event is not to be handled\nfurther; that is, \\fIproc\\fR has done all processing that is to be\nallowed for the event.\n.PP\nIf there are multiple generic event handlers, each one is called\nfor each event, in the order in which they were established.\n.PP\n\\fBTk_DeleteGenericHandler\\fR may be called to delete a\npreviously-created generic event handler:  it deletes each handler\nit finds that matches the \\fIproc\\fR and \\fIclientData\\fR arguments.  If\nno such handler exists, then \\fBTk_DeleteGenericHandler\\fR returns\nwithout doing anything.  Although Tk supports it, it's probably\na bad idea to have more than one callback with the same\n\\fIproc\\fR and \\fIclientData\\fR arguments.\n.PP\nEstablishing a generic event handler does nothing to ensure that the\nprocess will actually receive the X events that the handler wants to\nprocess.\nFor example, it is the caller's responsibility to invoke\n\\fBXSelectInput\\fR to select the desired events, if that is necessary.\n.SH KEYWORDS\nbind, callback, event, handler\n"
  },
  {
    "path": "doc/CrtImgType.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateImageType 3 8.5 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateImageType, Tk_GetImageModelData \\- define new kind of image\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateImageType\\fR(\\fItypePtr\\fR)\n.sp\nvoid *\n\\fBTk_GetImageModelData\\fR(\\fIinterp, name, typePtrPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"const Tk_ImageType\" *typePtrPtr\n.AP \"const Tk_ImageType\" *typePtr in\nStructure that defines the new type of image.\nFor Tk 8.4 and earlier this must be static: a\npointer to this structure is retained by the image code.\nIn Tk 8.5, this limitation was relaxed.\n.AP Tcl_Interp *interp in\nInterpreter in which image was created.\n.AP \"const char\" *name in\nName of existing image.\n.AP Tk_ImageType **typePtrPtr out\nPoints to word in which to store a pointer to type information for\nthe given image, if it exists.\n.AP char ***argvPtr in/out\nPointer to argument list\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateImageType\\fR is invoked to define a new kind of image.\nAn image type corresponds to a particular value of the \\fItype\\fR\nargument for the \\fBimage create\\fR command.  There may exist\nany number of different image types, and new types may be defined\ndynamically by calling \\fBTk_CreateImageType\\fR.\nFor example, there might be one type for 2-color bitmaps,\nanother for multi-color images, another for dithered images,\nanother for video, and so on.\n.PP\nThe code that implements a new image type is called an\n\\fIimage manager\\fR.\nIt consists of a collection of procedures plus three different\nkinds of data structures.\nThe first data structure is a Tk_ImageType structure, which contains\nthe name of the image type and pointers to five procedures provided\nby the image manager to deal with images of this type:\n.CS\ntypedef struct {\n    const char *\\fIname\\fR;\n    Tk_ImageCreateProc *\\fIcreateProc\\fR;\n    Tk_ImageGetProc *\\fIgetProc\\fR;\n    Tk_ImageDisplayProc *\\fIdisplayProc\\fR;\n    Tk_ImageFreeProc *\\fIfreeProc\\fR;\n    Tk_ImageDeleteProc *\\fIdeleteProc\\fR;\n} \\fBTk_ImageType\\fR;\n.CE\nThe fields of this structure will be described in later subsections\nof this entry.\n.PP\nThe second major data structure manipulated by an image manager\nis called an \\fIimage model\\fR;  it contains overall information\nabout a particular image, such as the values of the configuration\noptions specified in an \\fBimage create\\fR command.\nThere will usually be one of these structures for each\ninvocation of the \\fBimage create\\fR command.\n.PP\nThe third data structure related to images is an \\fIimage instance\\fR.\nThere will usually be one of these structures for each usage of an\nimage in a particular widget.\nIt is possible for a single image to appear simultaneously\nin multiple widgets, or even multiple times in the same widget.\nFurthermore, different instances may be on different screens\nor displays.\nThe image instance data structure describes things that may\nvary from instance to instance, such as colors and graphics\ncontexts for redisplay.\nThere is usually one instance structure for each \\fB\\-image\\fR\noption specified for a widget or canvas item.\n.PP\nThe following subsections describe the fields of a Tk_ImageType\nin more detail.\n.SS NAME\n.PP\n\\fItypePtr->name\\fR provides a name for the image type.\nOnce \\fBTk_CreateImageType\\fR returns, this name may be used\nin \\fBimage create\\fR commands to create images of the new\ntype.\nIf there already existed an image type by this name then\nthe new image type replaces the old one.\n.SS CREATEPROC\n.PP\n\\fItypePtr->createProc\\fR provides the address of a procedure for\nTk to call whenever \\fBimage create\\fR is invoked to create\nan image of the new type.\n\\fItypePtr->createProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageCreateProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        const char *\\fIname\\fR,\n        int \\fIobjc\\fR,\n        Tcl_Obj *const *\\fIobjv\\fR,\n        const Tk_ImageType *\\fItypePtr\\fR,\n        Tk_ImageModel \\fImodel\\fR,\n        void **\\fImodelDataPtr\\fR);\n.CE\nThe \\fIinterp\\fR argument is the interpreter in which the \\fBimage\\fR\ncommand was invoked, and \\fIname\\fR is the name for the new image,\nwhich was either specified explicitly in the \\fBimage\\fR command\nor generated automatically by the \\fBimage\\fR command.\nThe \\fIobjc\\fR and \\fIobjv\\fR arguments describe all the configuration\noptions for the new image (everything after the name argument to\n\\fBimage\\fR).\nThe \\fImodel\\fR argument is a token that refers to Tk's information\nabout this image;  the image manager must return this token to\nTk when invoking the \\fBTk_ImageChanged\\fR procedure.\nTypically \\fIcreateProc\\fR will parse \\fIobjc\\fR and \\fIobjv\\fR\nand create an image model data structure for the new image.\n\\fIcreateProc\\fR may store an arbitrary one-word value at\n*\\fImodelDataPtr\\fR, which will be passed back to the\nimage manager when other callbacks are invoked.\nTypically the value is a pointer to the model data\nstructure for the image.\n.PP\nIf \\fIcreateProc\\fR encounters an error, it should leave an error\nmessage in the interpreter result and return \\fBTCL_ERROR\\fR;  otherwise\nit should return \\fBTCL_OK\\fR.\n.PP\n\\fIcreateProc\\fR should call \\fBTk_ImageChanged\\fR in order to set the\nsize of the image and request an initial redisplay.\n.SS GETPROC\n.PP\n\\fItypePtr->getProc\\fR is invoked by Tk whenever a widget\ncalls \\fBTk_GetImage\\fR to use a particular image.\nThis procedure must match the following prototype:\n.CS\ntypedef void *\\fBTk_ImageGetProc\\fR(\n        Tk_Window \\fItkwin\\fR,\n        void *\\fImodelData\\fR);\n.CE\nThe \\fItkwin\\fR argument identifies the window in which the\nimage will be used and \\fImodelData\\fR is the value\nreturned by \\fIcreateProc\\fR when the image model was created.\n\\fIgetProc\\fR will usually create a data structure for the new\ninstance, including such things as the resources needed to\ndisplay the image in the given window.\n\\fIgetProc\\fR returns a one-word token for the instance, which\nis typically the address of the instance data structure.\nTk will pass this value back to the image manager when invoking\nits \\fIdisplayProc\\fR and \\fIfreeProc\\fR procedures.\n.SS DISPLAYPROC\n.PP\n\\fItypePtr->displayProc\\fR is invoked by Tk whenever an image needs\nto be displayed (i.e., whenever a widget calls \\fBTk_RedrawImage\\fR).\n\\fIdisplayProc\\fR must match the following prototype:\n.CS\ntypedef void \\fBTk_ImageDisplayProc\\fR(\n        void *\\fIinstanceData\\fR,\n        Display *\\fIdisplay\\fR,\n        Drawable \\fIdrawable\\fR,\n        int \\fIimageX\\fR,\n        int \\fIimageY\\fR,\n        int \\fIwidth\\fR,\n        int \\fIheight\\fR,\n        int \\fIdrawableX\\fR,\n        int \\fIdrawableY\\fR);\n.CE\nThe \\fIinstanceData\\fR will be the same as the value returned by\n\\fIgetProc\\fR when the instance was created.\n\\fIdisplay\\fR and \\fIdrawable\\fR indicate where to display the\nimage;  \\fIdrawable\\fR may be a pixmap rather than\nthe window specified to \\fIgetProc\\fR (this is usually the case,\nsince most widgets double-buffer their redisplay to get smoother\nvisual effects).\n\\fIimageX\\fR, \\fIimageY\\fR, \\fIwidth\\fR, and \\fIheight\\fR\nidentify the region of the image that must be redisplayed.\nThis region will always be within the size of the image\nas specified in the most recent call to \\fBTk_ImageChanged\\fR.\n\\fIdrawableX\\fR and \\fIdrawableY\\fR indicate where in \\fIdrawable\\fR\nthe image should be displayed;  \\fIdisplayProc\\fR should display\nthe given region of the image so that point (\\fIimageX\\fR, \\fIimageY\\fR)\nin the image appears at (\\fIdrawableX\\fR, \\fIdrawableY\\fR) in \\fIdrawable\\fR.\n.SS FREEPROC\n.PP\n\\fItypePtr->freeProc\\fR contains the address of a procedure that\nTk will invoke when an image instance is released (i.e., when\n\\fBTk_FreeImage\\fR is invoked).\nThis can happen, for example, when a widget is deleted or a image item\nin a canvas is deleted, or when the image displayed in a widget or\ncanvas item is changed.\n\\fIfreeProc\\fR must match the following prototype:\n.CS\ntypedef void \\fBTk_ImageFreeProc\\fR(\n        void *\\fIinstanceData\\fR,\n        Display *\\fIdisplay\\fR);\n.CE\nThe \\fIinstanceData\\fR will be the same as the value returned by\n\\fIgetProc\\fR when the instance was created, and \\fIdisplay\\fR\nis the display containing the window for the instance.\n\\fIfreeProc\\fR should release any resources associated with the\nimage instance, since the instance will never be used again.\n.SS DELETEPROC\n.PP\n\\fItypePtr->deleteProc\\fR is a procedure that Tk invokes when an\nimage is being deleted (i.e. when the \\fBimage delete\\fR command\nis invoked).\nBefore invoking \\fIdeleteProc\\fR Tk will invoke \\fIfreeProc\\fR for\neach of the image's instances.\n\\fIdeleteProc\\fR must match the following prototype:\n.CS\ntypedef void \\fBTk_ImageDeleteProc\\fR(\n        void *\\fImodelData\\fR);\n.CE\nThe \\fImodelData\\fR argument will be the same as the value\nstored in \\fI*modelDataPtr\\fR by \\fIcreateProc\\fR when the\nimage was created.\n\\fIdeleteProc\\fR should release any resources associated with\nthe image.\n.SH TK_GETIMAGEMODELDATA\n.PP\nThe procedure \\fBTk_GetImageModelData\\fR may be invoked to retrieve\ninformation about an image.  For example, an image manager can use this\nprocedure to locate its image model data for an image.\nIf there exists an image named \\fIname\\fR\nin the interpreter given by \\fIinterp\\fR, then \\fI*typePtrPtr\\fR is\nfilled in with type information for the image (the \\fItypePtr\\fR value\npassed to \\fBTk_CreateImageType\\fR when the image type was registered)\nand the return value is the clientData value returned by the\n\\fIcreateProc\\fR when the image was created (this is typically a\npointer to the image model data structure).  If no such image exists\nthen NULL is returned and NULL is stored at \\fI*typePtrPtr\\fR.\n.SH \"SEE ALSO\"\nTk_ImageChanged, Tk_GetImage, Tk_FreeImage, Tk_RedrawImage, Tk_SizeOfImage\n.SH KEYWORDS\nimage manager, image type, instance, model\n"
  },
  {
    "path": "doc/CrtItemType.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1995 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateItemType 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateItemType, Tk_GetItemTypes \\- define new kind of canvas item\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateItemType\\fR(\\fItypePtr\\fR)\n.sp\nTk_ItemType *\n\\fBTk_GetItemTypes\\fR()\n.fi\n.SH ARGUMENTS\n.AS Tk_ItemType *typePtr\n.AP Tk_ItemType *typePtr in\nStructure that defines the new type of canvas item.\nNote that this is not \\fIconst\\fR; Tk may write to these structures.\n.BE\n.SH INTRODUCTION\n.PP\n\\fBTk_CreateItemType\\fR is invoked to define a new kind of canvas item\ndescribed by the \\fItypePtr\\fR argument.\nAn item type corresponds to a particular value of the \\fItype\\fR\nargument to the \\fBcreate\\fR widget command for canvases, and\nthe code that implements a canvas item type is called a \\fItype manager\\fR.\nTk defines several built-in item types, such as \\fBrectangle\\fR\nand \\fBtext\\fR and \\fBimage\\fR, but \\fBTk_CreateItemType\\fR\nallows additional item types to be defined.\nOnce \\fBTk_CreateItemType\\fR returns, the new item type may be used\nin new or existing canvas widgets just like the built-in item\ntypes.\n.PP\n\\fBTk_GetItemTypes\\fR returns a pointer to the first in the list\nof all item types currently defined for canvases.\nThe entries in the list are linked together through their\n\\fInextPtr\\fR fields, with the end of the list marked by a\nNULL \\fInextPtr\\fR.\n.PP\nYou may find it easier to understand the rest of this manual entry\nby looking at the code for an existing canvas item type such as\nbitmap (in the file tkCanvBmap.c) or text (tkCanvText.c).\nThe easiest way to create a new type manager is to copy the code\nfor an existing type and modify it for the new type.\n.PP\nTk provides a number of utility procedures for the use of canvas\ntype managers, such as \\fBTk_CanvasCoords\\fR and \\fBTk_CanvasPsColor\\fR;\nthese are described in separate manual entries.\n.SH \"DATA STRUCTURES\"\n.PP\nA type manager consists of a collection of procedures that provide a\nstandard set of operations on items of that type.\nThe type manager deals with three kinds of data\nstructures.\nThe first data structure is a Tk_ItemType; it contains\ninformation such as the name of the type and pointers to\nthe standard procedures implemented by the type manager:\n.PP\n.CS\ntypedef struct Tk_ItemType {\n    const char *\\fIname\\fR;\n    Tcl_Size \\fIitemSize\\fR;\n    Tk_ItemCreateProc *\\fIcreateProc\\fR;\n    const Tk_ConfigSpec *\\fIconfigSpecs\\fR;\n    Tk_ItemConfigureProc *\\fIconfigProc\\fR;\n    Tk_ItemCoordProc *\\fIcoordProc\\fR;\n    Tk_ItemDeleteProc *\\fIdeleteProc\\fR;\n    Tk_ItemDisplayProc *\\fIdisplayProc\\fR;\n    int \\fIflags\\fR;\n    Tk_ItemPointProc *\\fIpointProc\\fR;\n    Tk_ItemAreaProc *\\fIareaProc\\fR;\n    Tk_ItemPostscriptProc *\\fIpostscriptProc\\fR;\n    Tk_ItemScaleProc *\\fIscaleProc\\fR;\n    Tk_ItemTranslateProc *\\fItranslateProc\\fR;\n    Tk_ItemIndexProc *\\fIindexProc\\fR;\n    Tk_ItemCursorProc *\\fIicursorProc\\fR;\n    Tk_ItemSelectionProc *\\fIselectionProc\\fR;\n    Tk_ItemInsertProc *\\fIinsertProc\\fR;\n    Tk_ItemDCharsProc *\\fIdCharsProc\\fR;\n    struct Tk_ItemType *\\fInextPtr\\fR;\n.VS \"9.0, TIP164\"\n    Tk_ItemRotateProc *\\fIrotateProc\\fR;\n.VE \"9.0, TIP164\"\n} \\fBTk_ItemType\\fR;\n.CE\n.PP\nThe fields of a Tk_ItemType structure are described in more detail\nlater in this manual entry.\nWhen \\fBTk_CreateItemType\\fR is called, its \\fItypePtr\\fR\nargument must point to a structure with all of the fields initialized\nexcept \\fInextPtr\\fR, which Tk sets to link all the types together\ninto a list.\nThe structure must be in permanent memory (either statically\nallocated or dynamically allocated but never freed); Tk retains\na pointer to this structure.\n.PP\nThe second data structure manipulated by a type manager is an\n\\fIitem record\\fR.\nFor each item in a canvas there exists one item record.\nAll of the items of a given type generally have item records with\nthe same structure, but different types usually have different\nformats for their item records.\nThe first part of each item record is a header with a standard structure\ndefined by Tk via the type Tk_Item; the rest of the item\nrecord is defined by the type manager.\nA type manager must define its item records with a Tk_Item as\nthe first field.\nFor example, the item record for bitmap items is defined as follows:\n.PP\n.CS\ntypedef struct {\n    Tk_Item \\fIheader\\fR;\n    double \\fIx\\fR, \\fIy\\fR;\n    Tk_Anchor \\fIanchor\\fR;\n    Pixmap \\fIbitmap\\fR;\n    XColor *\\fIfgColor\\fR;\n    XColor *\\fIbgColor\\fR;\n    GC \\fIgc\\fR;\n} \\fBBitmapItem\\fR;\n.CE\n.PP\nThe \\fIheader\\fR substructure contains information used by Tk\nto manage the item, such as its identifier, its tags, its type,\nand its bounding box.\nThe fields starting with \\fIx\\fR belong to the type manager:\nTk will never read or write them.\nThe type manager should not need to read or write any of the\nfields in the header except for four fields\nwhose names are \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR.\nThese fields give a bounding box for the items using integer\ncanvas coordinates: the item should not cover any pixels\nwith x-coordinate lower than \\fIx1\\fR or y-coordinate\nlower than \\fIy1\\fR, nor should it cover any pixels with\nx-coordinate greater than or equal to \\fIx2\\fR or y-coordinate\ngreater than or equal to \\fIy2\\fR.\nIt is up to the type manager to keep the bounding box up to\ndate as the item is moved and reconfigured.\n.PP\nWhenever Tk calls a procedure in a type manager it passes in a pointer\nto an item record.\nThe argument is always passed as a pointer to a Tk_Item; the type\nmanager will typically cast this into a pointer to its own specific\ntype, such as BitmapItem.\n.PP\nThe third data structure used by type managers has type\nTk_Canvas; it serves as an opaque handle for the canvas widget\nas a whole.\nType managers need not know anything about the contents of this\nstructure.\nA Tk_Canvas handle is typically passed in to the\nprocedures of a type manager, and the type manager can pass the\nhandle back to library procedures such as Tk_CanvasTkwin\nto fetch information about the canvas.\n.SH \"TK_ITEMTYPE FIELDS\"\n.SS NAME\n.PP\nThis section and the ones that follow describe each of the fields\nin a Tk_ItemType structure in detail.\nThe \\fIname\\fR field provides a string name for the item type.\nOnce \\fBTk_CreateImageType\\fR returns, this name may be used\nin \\fBcreate\\fR widget commands to create items of the new\ntype.\nIf there already existed an item type by this name then\nthe new item type replaces the old one.\n.SS \"FLAGS (IN ALWAYSREDRAW)\"\n.PP\nThe \\fItypePtr\\->flags\\fR field\ncontains a collection of flag bits that modify how the canvas core interacts\nwith the item. The following bits are defined:\n.TP\n\\fBTK_ALWAYS_REDRAW\\fR\n.\nIndicates that the item should always be redrawn when any part of the canvas\nis redrawn, rather than only when the bounding box of the item overlaps the\narea being redrawn. This is used by window items, for example, which need to\nunmap subwindows that are not on the screen.\n.TP\n\\fBTK_MOVABLE_POINTS\\fR\n.VS 8.6\nIndicates that the item supports the \\fIdCharsProc\\fR, \\fIindexProc\\fR and\n\\fIinsertProc\\fR with the same semantics as Tk's built-in line and polygon\ntypes, and that hence individual coordinate points can be moved. Must not be\nset if any of the above methods is NULL.\n.VE 8.6\n.SS ITEMSIZE\n.PP\n\\fItypePtr\\->itemSize\\fR gives the size in bytes of item records\nof this type, including the Tk_Item header.\nTk uses this size to allocate memory space for items of the type.\nAll of the item records for a given type must have the same size.\nIf variable length fields are needed for an item (such as a list\nof points for a polygon), the type manager can allocate a separate\nobject of variable length and keep a pointer to it in the item record.\n.SS CREATEPROC\n.PP\n\\fItypePtr\\->createProc\\fR points to a procedure for\nTk to call whenever a new item of this type is created.\n\\fItypePtr\\->createProc\\fR must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemCreateProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIobjc\\fR,\n        Tcl_Obj *const *\\fIobjv\\fR);\n.CE\n.PP\nThe \\fIinterp\\fR argument is the interpreter in which the canvas's\n\\fBcreate\\fR widget command was invoked, and \\fIcanvas\\fR is a\nhandle for the canvas widget.\n\\fIitemPtr\\fR is a pointer to a newly-allocated item of\nsize \\fItypePtr\\->itemSize\\fR.\nTk has already initialized the item's header (the first\n\\fBsizeof(Tk_ItemType)\\fR bytes).\nThe \\fIobjc\\fR and \\fIobjv\\fR arguments describe all of the\narguments to the \\fBcreate\\fR command after the \\fItype\\fR\nargument.\nFor example, in the widget command:\n.PP\n.CS\n\\fB\\&.c create rectangle 10 20 50 50 \\-fill black\\fR\n.CE\n.PP\n\\fIobjc\\fR will be \\fB6\\fR and \\fIobjv\\fR[0] will contain the\ninteger object \\fB10\\fR.\n.PP\n\\fIcreateProc\\fR should use \\fIobjc\\fR and \\fIobjv\\fR to initialize\nthe type-specific parts of the item record and set an initial value\nfor the bounding box in the item's header.\nIt should return a standard Tcl completion code and leave an\nerror message in the interpreter result if an error occurs.\nIf an error occurs Tk will free the item record, so \\fIcreateProc\\fR\nmust be sure to leave the item record in a clean state if it returns an error\n(e.g., it must free any additional memory that it allocated for\nthe item).\n.SS CONFIGSPECS\n.PP\nEach type manager must provide a standard table describing its\nconfiguration options, in a form suitable for use with\n\\fBTk_ConfigureWidget\\fR.\nThis table will normally be used by \\fItypePtr\\->createProc\\fR\nand \\fItypePtr\\->configProc\\fR, but Tk also uses it directly\nto retrieve option information in the \\fBitemcget\\fR and\n\\fBitemconfigure\\fR widget commands.\n\\fItypePtr\\->configSpecs\\fR must point to the configuration table\nfor this type.\n.PP\nNote that Tk provides a custom option type \\fBtk_CanvasTagsOption\\fR\nfor implementing the \\fB\\-tags\\fR option; see an existing type\nmanager for an example of how to use it in \\fIconfigSpecs\\fR.\n.SS CONFIGPROC\n.PP\n\\fItypePtr\\->configProc\\fR is called by Tk whenever the\n\\fBitemconfigure\\fR widget command is invoked to change the\nconfiguration options for a canvas item.\nThis procedure must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemConfigureProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIobjc\\fR,\n        Tcl_Obj *const *\\fIobjv\\fR,\n        int \\fIflags\\fR);\n.CE\n.PP\nThe \\fIinterp\\fR argument identifies the interpreter in which the\nwidget command was invoked, \\fIcanvas\\fR is a handle for the canvas\nwidget, and \\fIitemPtr\\fR is a pointer to the item being configured.\n\\fIobjc\\fR and \\fIobjv\\fR contain the configuration options.\nFor example, if the following command is invoked:\n.PP\n.CS\n\\fB\\&.c itemconfigure 2 \\-fill red \\-outline black\\fR\n.CE\n.PP\n\\fIobjc\\fR is \\fB4\\fR and \\fIobjv\\fR contains the string objects \\fB\\-fill\\fR\nthrough \\fBblack\\fR.\n\\fIobjc\\fR will always be an even value.\nThe \\fIflags\\fR argument contains flags to pass to \\fBTk_ConfigureWidget\\fR;\ncurrently this value is always \\fBTK_CONFIG_ARGV_ONLY\\fR when Tk\ninvokes \\fItypePtr\\->configProc\\fR, but the type manager's \\fIcreateProc\\fR\nprocedure will usually invoke \\fIconfigProc\\fR with different flag values.\n.PP\n\\fItypePtr\\->configProc\\fR returns a standard Tcl completion code and\nleaves an error message in the interpreter result if an error occurs.\nIt must update the item's bounding box to reflect the new configuration\noptions.\n.SS COORDPROC\n.PP\n\\fItypePtr\\->coordProc\\fR is invoked by Tk to implement the \\fBcoords\\fR\nwidget command for an item.\nIt must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemCoordProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIobjc\\fR,\n        Tcl_Obj *const *\\fIobjv\\fR);\n.CE\n.PP\nThe arguments \\fIinterp\\fR, \\fIcanvas\\fR, and \\fIitemPtr\\fR\nall have the standard meanings, and \\fIobjc\\fR and \\fIobjv\\fR\ndescribe the coordinate arguments.\nFor example, if the following widget command is invoked:\n.PP\n.CS\n\\fB\\&.c coords 2 30 90\\fR\n.CE\n.PP\n\\fIobjc\\fR will be \\fB2\\fR and \\fBobjv\\fR will contain the integer objects\n\\fB30\\fR and \\fB90\\fR.\n.PP\nThe \\fIcoordProc\\fR procedure should process the new coordinates,\nupdate the item appropriately (e.g., it must reset the bounding\nbox in the item's header), and return a standard Tcl completion\ncode.\nIf an error occurs, \\fIcoordProc\\fR must leave an error message in\nthe interpreter result.\n.SS DELETEPROC\n.PP\n\\fItypePtr\\->deleteProc\\fR is invoked by Tk to delete an item\nand free any resources allocated to it.\nIt must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemDeleteProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        Display *\\fIdisplay\\fR);\n.CE\n.PP\nThe \\fIcanvas\\fR and \\fIitemPtr\\fR arguments have the usual\ninterpretations, and \\fIdisplay\\fR identifies the X display containing\nthe canvas.\n\\fIdeleteProc\\fR must free up any resources allocated for the item,\nso that Tk can free the item record.\n\\fIdeleteProc\\fR should not actually free the item record; this will\nbe done by Tk when \\fIdeleteProc\\fR returns.\n.SS \"DISPLAYPROC\"\n.PP\n\\fItypePtr\\->displayProc\\fR is invoked by Tk to redraw an item\non the screen.\nIt must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemDisplayProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        Display *\\fIdisplay\\fR,\n        Drawable \\fIdst\\fR,\n        int \\fIx\\fR,\n        int \\fIy\\fR,\n        int \\fIwidth\\fR,\n        int \\fIheight\\fR);\n.CE\n.PP\nThe \\fIcanvas\\fR and \\fIitemPtr\\fR arguments have the usual meaning.\n\\fIdisplay\\fR identifies the display containing the canvas, and\n\\fIdst\\fR specifies a drawable in which the item should be rendered;\ntypically this is an off-screen pixmap, which Tk will copy into\nthe canvas's window once all relevant items have been drawn.\n\\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and \\fIheight\\fR specify a rectangular\nregion in canvas coordinates, which is the area to be redrawn;\nonly information that overlaps this area needs to be redrawn.\nTk will not call \\fIdisplayProc\\fR unless the item's bounding box\noverlaps the redraw area, but the type manager may wish to use\nthe redraw area to optimize the redisplay of the item.\n.PP\nBecause of scrolling and the use of off-screen pixmaps for\ndouble-buffered redisplay, the item's coordinates in \\fIdst\\fR\nwill not necessarily be the same as those in the canvas.\n\\fIdisplayProc\\fR should call \\fBTk_CanvasDrawableCoords\\fR\nto transform coordinates from those of the canvas to those\nof \\fIdst\\fR.\n.PP\nNormally an item's \\fIdisplayProc\\fR is only invoked if the item\noverlaps the area being displayed.\nHowever, if bit zero of \\fItypePtr\\->flags\\fR is 1,\n(i.e.\\|\n.QW \"\\fItypePtr\\->flags & 1 == 1\\fR\" )\nthen \\fIdisplayProc\\fR is invoked during every redisplay operation,\neven if the item does not overlap the area of redisplay; this is useful for\ncases such as window items, where the subwindow needs to be unmapped when it\nis off the screen.\n.SS POINTPROC\n.PP\n\\fItypePtr\\->pointProc\\fR is invoked by Tk to find out how close\na given point is to a canvas item.\nTk uses this procedure for purposes such as locating the item\nunder the mouse or finding the closest item to a given point.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef double \\fBTk_ItemPointProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        double *\\fIpointPtr\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meaning.\n\\fIpointPtr\\fR points to an array of two numbers giving\nthe x and y coordinates of a point.\n\\fIpointProc\\fR must return a real value giving the distance\nfrom the point to the item, or 0 if the point lies inside\nthe item.\n.SS AREAPROC\n.PP\n\\fItypePtr\\->areaProc\\fR is invoked by Tk to find out the relationship\nbetween an item and a rectangular area.\nIt must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemAreaProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        double *\\fIrectPtr\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meaning.\n\\fIrectPtr\\fR points to an array of four real numbers;\nthe first two give the x and y coordinates of the upper left\ncorner of a rectangle, and the second two give the x and y\ncoordinates of the lower right corner.\n\\fIareaProc\\fR must return \\-1 if the item lies entirely outside\nthe given area, 0 if it lies partially inside and partially\noutside the area, and 1 if it lies entirely inside the area.\n.SS POSTSCRIPTPROC\n.PP\n\\fItypePtr\\->postscriptProc\\fR is invoked by Tk to generate\nPostscript for an item during the \\fBpostscript\\fR widget command.\nIf the type manager is not capable of generating Postscript then\n\\fItypePtr\\->postscriptProc\\fR should be NULL.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemPostscriptProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIprepass\\fR);\n.CE\n.PP\nThe \\fIinterp\\fR, \\fIcanvas\\fR, and \\fIitemPtr\\fR arguments all have\nstandard meanings; \\fIprepass\\fR will be described below.\nIf \\fIpostscriptProc\\fR completes successfully, it should append\nPostscript for the item to the information in the interpreter result\n(e.g. by calling \\fBTcl_AppendResult\\fR, not \\fBTcl_SetResult\\fR)\nand return \\fBTCL_OK\\fR.\nIf an error occurs, \\fIpostscriptProc\\fR should clear the result\nand replace its contents with an error message; then it should\nreturn \\fBTCL_ERROR\\fR.\n.PP\nTk provides a collection of utility procedures to simplify\n\\fIpostscriptProc\\fR.\nFor example, \\fBTk_CanvasPsColor\\fR will generate Postscript to set\nthe current color to a given Tk color and \\fBTk_CanvasPsFont\\fR will\nset up font information.\nWhen generating Postscript, the type manager is free to change the\ngraphics state of the Postscript interpreter, since Tk places\n\\fBgsave\\fR and \\fBgrestore\\fR commands around the Postscript for\nthe item.\nThe type manager can use canvas x coordinates directly in its Postscript,\nbut it must call \\fBTk_CanvasPsY\\fR to convert y coordinates from\nthe space of the canvas (where the origin is at the\nupper left) to the space of Postscript (where the origin is at the\nlower left).\n.PP\nIn order to generate Postscript that complies with the Adobe Document\nStructuring Conventions, Tk actually generates Postscript in two passes.\nIt calls each item's \\fIpostscriptProc\\fR in each pass.\nThe only purpose of the first pass is to collect font information\n(which is done by \\fBTk_CanvasPsFont\\fR); the actual Postscript is\ndiscarded.\nTk sets the \\fIprepass\\fR argument to \\fIpostscriptProc\\fR to 1\nduring the first pass; the type manager can use \\fIprepass\\fR to skip\nall Postscript generation except for calls to \\fBTk_CanvasPsFont\\fR.\nDuring the second pass \\fIprepass\\fR will be 0, so the type manager\nmust generate complete Postscript.\n.SS SCALEPROC\n.PP\n\\fItypePtr\\->scaleProc\\fR is invoked by Tk to rescale a canvas item\nduring the \\fBscale\\fR widget command.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemScaleProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        double \\fIoriginX\\fR,\n        double \\fIoriginY\\fR,\n        double \\fIscaleX\\fR,\n        double \\fIscaleY\\fR);\n.CE\n.PP\nThe \\fIcanvas\\fR and \\fIitemPtr\\fR arguments have the usual meaning.\n\\fIoriginX\\fR and \\fIoriginY\\fR specify an origin relative to which\nthe item is to be scaled, and \\fIscaleX\\fR and \\fIscaleY\\fR give the\nx and y scale factors.\nThe item should adjust its coordinates so that a point in the item\nthat used to have coordinates \\fIx\\fR and \\fIy\\fR will have new\ncoordinates \\fIx\\(fm\\fR and \\fIy\\(fm\\fR, where\n.PP\n.CS\n\\fIx\\(fm\\fR = \\fIoriginX\\fR + \\fIscaleX\\fR \\(mu (\\fIx\\fR \\(mi \\fIoriginX\\fR)\n\\fIy\\(fm\\fR = \\fIoriginY\\fR + \\fIscaleY\\fR \\(mu (\\fIy\\fR \\(mi \\fIoriginY\\fR)\n.CE\n.PP\n\\fIscaleProc\\fR must also update the bounding box in the item's\nheader.\n.SS TRANSLATEPROC\n.PP\n\\fItypePtr\\->translateProc\\fR is invoked by Tk to translate a canvas item\nduring the \\fBmove\\fR widget command.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemTranslateProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        double \\fIdeltaX\\fR,\n        double \\fIdeltaY\\fR);\n.CE\n.PP\nThe \\fIcanvas\\fR and \\fIitemPtr\\fR arguments have the usual meaning,\nand \\fIdeltaX\\fR and \\fIdeltaY\\fR give the amounts that should be\nadded to each x and y coordinate within the item.\nThe type manager should adjust the item's coordinates and\nupdate the bounding box in the item's header.\n.SS ROTATEPROC\n.VS \"9.0, TIP164\"\n.PP\n\\fItypePtr\\->rotateProc\\fR is invoked by Tk to rotate a canvas item\nduring the \\fBrotate\\fR widget command.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemRotateProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        double \\fIoriginX\\fR,\n        double \\fIoriginY\\fR,\n        double \\fIangleRad\\fR);\n.CE\n.PP\nThe \\fIcanvas\\fR and \\fIitemPtr\\fR arguments have the usual meaning.\n\\fIoriginX\\fR and \\fIoriginY\\fR specify an origin relative to which\nthe item is to be rotated, and \\fIangleRad\\fR gives the anticlockwise\nrotation to be applied in radians.\nThe item should adjust the coordinates of its control points so that where\nthey used to have coordinates \\fIx\\fR and \\fIy\\fR, they will have new\ncoordinates \\fIx\\(fm\\fR and \\fIy\\(fm\\fR, where\n.PP\n.CS\n\\fIrelX\\fR = \\fIx\\fR \\(mi \\fIoriginX\\fR\n\\fIrelY\\fR = \\fIy\\fR \\(mi \\fIoriginY\\fR\n\\fIx\\(fm\\fR = \\fIoriginX\\fR + \\fIrelX\\fR \\(mu cos(\\fIangleRad\\fR) + \\fIrelY\\fR \\(mu sin(\\fIangleRad\\fR)\n\\fIy\\(fm\\fR = \\fIoriginY\\fR \\(mi \\fIrelX\\fR \\(mu sin(\\fIangleRad\\fR) + \\fIrelY\\fR \\(mu cos(\\fIangleRad\\fR)\n.CE\n.PP\nThe control points for an item are not necessarily the coordinates provided to\nthe item when it is created (or via the \\fItypePtr\\->coordProc\\fR), but could\ninstead be derived from them.\n\\fIrotateProc\\fR must also update the bounding box in the item's header.\n.PP\nItem types do not need to provide a \\fItypePtr\\->rotateProc\\fR. If the\n\\fItypePtr\\->rotateProc\\fR is NULL, the \\fItypePtr\\->coordProc\\fR will be\nused instead to retrieve and update the list of coordinates.\n.VE \"9.0, TIP164\"\n.SS INDEXPROC\n.PP\n\\fItypePtr\\->indexProc\\fR is invoked by Tk to translate a string\nindex specification into a numerical index, for example during the\n\\fBindex\\fR widget command.\nIt is only relevant for item types that support indexable text or coordinates;\n\\fItypePtr\\->indexProc\\fR may be specified as NULL for non-textual\nitem types if they do not support detailed coordinate addressing.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemIndexProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        Tcl_Obj *\\fIindexObj\\fR,\n        int *\\fIindexPtr\\fR);\n.CE\n.PP\nThe \\fIinterp\\fR, \\fIcanvas\\fR, and \\fIitemPtr\\fR arguments all\nhave the usual meaning.\n\\fIindexObj\\fR contains a textual description of an index,\nand \\fIindexPtr\\fR points to an integer value that should be\nfilled in with a numerical index.\nIt is up to the type manager to decide what forms of index\nare supported (e.g., numbers, \\fBinsert\\fR, \\fBsel.first\\fR,\n\\fBend\\fR, etc.).\n\\fIindexProc\\fR should return a Tcl completion code and set\nthe interpreter result in the event of an error.\n.SS ICURSORPROC\n.PP\n\\fItypePtr\\->icursorProc\\fR is invoked by Tk during\nthe \\fBicursor\\fR widget command to set the position of the\ninsertion cursor in a textual item.\nIt is only relevant for item types that support an insertion cursor;\n\\fItypePtr\\->icursorProc\\fR may be specified as NULL for item types\nthat do not support an insertion cursor.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemCursorProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIindex\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meanings, and\n\\fIindex\\fR is an index into the item's text, as returned by a\nprevious call to \\fItypePtr\\->insertProc\\fR.\nThe type manager should position the insertion cursor in the\nitem just before the character given by \\fIindex\\fR.\nWhether or not to actually display the insertion cursor is\ndetermined by other information provided by \\fBTk_CanvasGetTextInfo\\fR.\n.SS SELECTIONPROC\n.PP\n\\fItypePtr\\->selectionProc\\fR is invoked by Tk during selection\nretrievals; it must return part or all of the selected text in\nthe item (if any).\nIt is only relevant for item types that support text;\n\\fItypePtr\\->selectionProc\\fR may be specified as NULL for non-textual\nitem types.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef int \\fBTk_ItemSelectionProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIoffset\\fR,\n        char *\\fIbuffer\\fR,\n        int \\fImaxBytes\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meanings.\n\\fIoffset\\fR is an offset in bytes into the selection where 0 refers\nto the first byte of the selection; it identifies\nthe first character that is to be returned in this call.\n\\fIbuffer\\fR points to an area of memory in which to store the\nrequested bytes, and \\fImaxBytes\\fR specifies the maximum number\nof bytes to return.\n\\fIselectionProc\\fR should extract up to \\fImaxBytes\\fR characters\nfrom the selection and copy them to \\fImaxBytes\\fR; it should\nreturn a count of the number of bytes actually copied, which may\nbe less than \\fImaxBytes\\fR if there are not \\fIoffset+maxBytes\\fR bytes\nin the selection.\n.SS INSERTPROC\n.PP\n\\fItypePtr\\->insertProc\\fR is invoked by Tk during\nthe \\fBinsert\\fR widget command to insert new text or coordinates into a\ncanvas item.\nIt is only relevant for item types that support the \\fBinsert\\fR method;\n\\fItypePtr\\->insertProc\\fR may be specified as NULL for other\nitem types.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemInsertProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIindex\\fR,\n        Tcl_Obj *\\fIobj\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meanings.\n\\fIindex\\fR is an index into the item's text, as returned by a\nprevious call to \\fItypePtr\\->insertProc\\fR, and \\fIobj\\fR\ncontains new text to insert just before the character given\nby \\fIindex\\fR.\nIf the item supports modification of the coordinates list by this\n.PP\nThe type manager should insert the text and recompute the bounding\nbox in the item's header.\n.SS DCHARSPROC\n.PP\n\\fItypePtr\\->dCharsProc\\fR is invoked by Tk during the \\fBdchars\\fR\nwidget command to delete a range of text from a canvas item or a range of\ncoordinates from a pathed item.\nIt is only relevant for item types that support text;\n\\fItypePtr\\->dCharsProc\\fR may be specified as NULL for non-textual\nitem types that do not want to support coordinate deletion.\nThe procedure must match the following prototype:\n.PP\n.CS\ntypedef void \\fBTk_ItemDCharsProc\\fR(\n        Tk_Canvas \\fIcanvas\\fR,\n        Tk_Item *\\fIitemPtr\\fR,\n        int \\fIfirst\\fR,\n        int \\fIlast\\fR);\n.CE\n.PP\n\\fIcanvas\\fR and \\fIitemPtr\\fR have the usual meanings.\n\\fIfirst\\fR and \\fIlast\\fR give the indices of the first and last bytes\nto be deleted, as returned by previous calls to \\fItypePtr\\->indexProc\\fR.\nThe type manager should delete the specified characters and update\nthe bounding box in the item's header.\n.SH \"SEE ALSO\"\nTk_CanvasPsY, Tk_CanvasTextInfo, Tk_CanvasTkwin\n.SH KEYWORDS\ncanvas, focus, item type, selection, type manager\n"
  },
  {
    "path": "doc/CrtPhImgFmt.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Australian National University\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n'\\\" Author: Paul Mackerras (paulus@cs.anu.edu.au),\n'\\\"\t    Department of Computer Science,\n'\\\"\t    Australian National University.\n'\\\"\n.TH Tk_CreatePhotoImageFormat 3 9.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreatePhotoImageFormat \\- define new file format for photo images\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n.VS 9.0\n\\fBTk_CreatePhotoImageFormatVersion3\\fR(\\fIformatVersion3Ptr\\fR)\n.VE 9.0\n.sp\n\\fBTk_CreatePhotoImageFormat\\fR(\\fIformatPtr\\fR)\n.SH ARGUMENTS\n.AS \"const Tk_PhotoImageFormatVersion3\" *formatVersion3Ptr\n.VS 9.0\n.AP \"const Tk_PhotoImageFormatVersion3\" *formatVersion3Ptr in\nStructure that defines the new file format including metadata functionality.\n.VE 9.0\n.AP \"const Tk_PhotoImageFormat\" *formatPtr in\nStructure that defines the new file format.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreatePhotoImageFormatVersion3\\fR is invoked to define a new file format\nfor image data for use with photo images.  The code that implements an\nimage file format is called an image file format handler, or\nhandler for short.  The photo image code\nmaintains a list of handlers that can be used to read and\nwrite data to or from a file.  Some handlers may also\nsupport reading image data from a string or converting image data to a\nstring format.\nThe user can specify which handler to use with the \\fB\\-format\\fR\nimage configuration option or the \\fB\\-format\\fR option to the\n\\fBread\\fR and \\fBwrite\\fR photo image subcommands.\n.PP\nThe alternate version 2 function \\fBTk_CreatePhotoImageFormat\\fR has\nidentical functionality, but does not allow the handler to get or return\nthe metadata dictionary of the image.\nIt is described in section \\fBVERSION 2 INTERFACE\\fR below.\n.PP\nAn image file format handler consists of a collection of procedures\nplus a \\fBTk_PhotoImageFormatVersion3\\fR structure, which contains the\nname of the image file format and pointers to six procedures provided\nby the handler to deal with files and strings in this format.  The\nTk_PhotoImageFormatVersion3 structure contains the following fields:\n.VS 9.0\n.CS\ntypedef struct {\n    const char *\\fIname\\fR;\n    Tk_ImageFileMatchProcVersion3 *\\fIfileMatchProc\\fR;\n    Tk_ImageStringMatchProcVersion3 *\\fIstringMatchProc\\fR;\n    Tk_ImageFileReadProcVersion3 *\\fIfileReadProc\\fR;\n    Tk_ImageStringReadProcVersion3 *\\fIstringReadProc\\fR;\n    Tk_ImageFileWriteProcVersion3 *\\fIfileWriteProc\\fR;\n    Tk_ImageStringWriteProcVersion3 *\\fIstringWriteProc\\fR;\n} \\fBTk_PhotoImageFormatVersion3\\fR;\n.CE\n.VE 9.0\n.PP\nThe handler need not provide implementations of all six procedures.\nFor example, the procedures that handle string data would not be\nprovided for a format in which the image data are stored in binary,\nand could therefore contain null characters.  If any procedure is not\nimplemented, the corresponding pointer in the Tk_PhotoImageFormat\nstructure should be set to NULL.  The handler must provide the\n\\fIfileMatchProc\\fR procedure if it provides the \\fIfileReadProc\\fR\nprocedure, and the \\fIstringMatchProc\\fR procedure if it provides the\n\\fIstringReadProc\\fR procedure.\n.SS NAME\n.PP\n\\fIformatPtr->name\\fR provides a name for the image type.\nOnce \\fBTk_CreatePhotoImageFormatVersion3\\fR returns, this name may be\nused in the \\fB\\-format\\fR photo image configuration and subcommand\noption.\nThe manual page for the photo image (photo(n)) describes how image\nfile formats are chosen based on their names and the value given to\nthe \\fB\\-format\\fR option. The first character of \\fIformatPtr->name\\fR\nmust not be an uppercase character from the ASCII character set\n(that is, one of the characters \\fBA\\fR-\\fBZ\\fR).  Such names are used\nonly for legacy interface support (see below).\n.VS 9.0\n.SS FILEMATCHPROC\n.PP\n\\fIformatPtr->fileMatchProc\\fR provides the address of a procedure for\nTk to call when it is searching for an image file format handler\nsuitable for reading data in a given file.\n\\fIformatPtr->fileMatchProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileMatchProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Channel \\fIchan\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        int *\\fIwidthPtr\\fR,\n        int *\\fIheightPtr\\fR,\n        Tcl_Obj *\\fImetadataOut\\fR);\n.CE\nThe \\fIfileName\\fR argument is the name of the file containing the\nimage data, which is open for reading as \\fIchan\\fR.  The\n\\fIformat\\fR argument contains the value given for the\n\\fB\\-format\\fR option, or NULL if the option was not specified.\n\\fBmetadataIn\\fR and \\fBmetadataOut\\fR inputs and returns a metadata\ndictionary as described in section \\fBMETADATA INTERFACE\\fR below.\nIf the data in the file appears to be in the format supported by this\nhandler, the \\fIformatPtr->fileMatchProc\\fR procedure should store the\nwidth and height of the image in *\\fIwidthPtr\\fR and *\\fIheightPtr\\fR\nrespectively, and return 1.  Otherwise it should return 0.\n.SS STRINGMATCHPROC\n.PP\n\\fIformatPtr->stringMatchProc\\fR provides the address of a procedure\nfor Tk to call when it is searching for an image file format handler\nsuitable for reading data from a given string.\n\\fIformatPtr->stringMatchProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringMatchProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Obj *\\fIdata\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        int *\\fIwidthPtr\\fR,\n        int *\\fIheightPtr\\fR,\n        Tcl_Obj *\\fImetadataOut\\fR);\n.CE\nThe \\fIdata\\fR argument points to the object containing the image\ndata.  The \\fIformat\\fR argument contains the value given for\nthe \\fB\\-format\\fR option, or NULL if the option was not specified.\n\\fBmetadataIn\\fR and \\fBmetadataOut\\fR inputs and returns a metadata\ndictionary as described in section \\fBMETADATA INTERFACE\\fR below.\nIf the data in the string appears to be in the format supported by\nthis handler, the \\fIformatPtr->stringMatchProc\\fR procedure should\nstore the width and height of the image in *\\fIwidthPtr\\fR and\n*\\fIheightPtr\\fR respectively, and return 1.  Otherwise it should\nreturn 0.\n.SS FILEREADPROC\n.PP\n\\fIformatPtr->fileReadProc\\fR provides the address of a procedure for\nTk to call to read data from an image file into a photo image.\n\\fIformatPtr->fileReadProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileReadProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Channel \\fIchan\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        PhotoHandle \\fIimageHandle\\fR,\n        int \\fIdestX\\fR, int \\fIdestY\\fR,\n        int \\fIwidth\\fR, int \\fIheight\\fR,\n        int \\fIsrcX\\fR, int \\fIsrcY\\fR,\n        Tcl_Obj *\\fImetadataOut\\fR);\n.CE\nThe \\fIinterp\\fR argument is the interpreter in which the command was\ninvoked to read the image; it should be used for reporting errors.\nThe image data is in the file named \\fIfileName\\fR, which is open for\nreading as \\fIchan\\fR.  The \\fIformat\\fR argument contains the\nvalue given for the \\fB\\-format\\fR option, or NULL if the option was\nnot specified.  The image data in the file, or a subimage of it, is to\nbe read into the photo image identified by the handle\n\\fIimageHandle\\fR.  The subimage of the data in the file is of\ndimensions \\fIwidth\\fR x \\fIheight\\fR and has its top-left corner at\ncoordinates (\\fIsrcX\\fR,\\fIsrcY\\fR).  It is to be stored in the photo\nimage with its top-left corner at coordinates\n(\\fIdestX\\fR,\\fIdestY\\fR) using the \\fBTk_PhotoPutBlock\\fR procedure.\n\\fBmetadataIn\\fR and \\fBmetadataOut\\fR inputs and returns a metadata\ndictionary as described in section \\fBMETADATA INTERFACE\\fR below.\nThe return value is a standard Tcl return value.\n.SS STRINGREADPROC\n.PP\n\\fIformatPtr->stringReadProc\\fR provides the address of a procedure\nfor Tk to call to read data from a string into a photo image.\n\\fIformatPtr->stringReadProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringReadProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Obj *\\fIdata\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        PhotoHandle \\fIimageHandle\\fR,\n        int \\fIdestX\\fR, int \\fIdestY\\fR,\n        int \\fIwidth\\fR, int \\fIheight\\fR,\n        int \\fIsrcX\\fR, int \\fIsrcY\\fR,\n        Tcl_Obj *\\fImetadataOut\\fR);\n.CE\nThe \\fIinterp\\fR argument is the interpreter in which the command was\ninvoked to read the image; it should be used for reporting errors.\nThe \\fIdata\\fR argument points to the image data in object form.\nThe \\fIformat\\fR argument contains the\nvalue given for the \\fB\\-format\\fR option, or NULL if the option was\nnot specified.  The image data in the string, or a subimage of it, is\nto be read into the photo image identified by the handle\n\\fIimageHandle\\fR.  The subimage of the data in the string is of\ndimensions \\fIwidth\\fR x \\fIheight\\fR and has its top-left corner at\ncoordinates (\\fIsrcX\\fR,\\fIsrcY\\fR).  It is to be stored in the photo\nimage with its top-left corner at coordinates\n(\\fIdestX\\fR,\\fIdestY\\fR) using the \\fBTk_PhotoPutBlock\\fR procedure.\n\\fBmetadataIn\\fR and \\fBmetadataOut\\fR inputs and returns a metadata\ndictionary as described in section \\fBMETADATA INTERFACE\\fR below.\nThe return value is a standard Tcl return value.\n.SS FILEWRITEPROC\n.PP\n\\fIformatPtr->fileWriteProc\\fR provides the address of a procedure for\nTk to call to write data from a photo image to a file.\n\\fIformatPtr->fileWriteProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileWriteProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        Tk_PhotoImageBlock *\\fIblockPtr\\fR);\n.CE\nThe \\fIinterp\\fR argument is the interpreter in which the command was\ninvoked to write the image; it should be used for reporting errors.\nThe image data to be written are in memory and are described by the\nTk_PhotoImageBlock structure pointed to by \\fIblockPtr\\fR; see the\nmanual page FindPhoto(3) for details.  The \\fIfileName\\fR argument\npoints to the string giving the name of the file in which to write the\nimage data.  The \\fIformat\\fR argument contains the\nvalue given for the \\fB\\-format\\fR option, or NULL if the option was\nnot specified.  The format string can contain extra characters\nafter the name of the format.  If appropriate, the\n\\fIformatPtr->fileWriteProc\\fR procedure may interpret these\ncharacters to specify further details about the image file.\n\\fBmetadataIn\\fR may contain metadata keys that a driver may include\ninto the output data.\nThe return value is a standard Tcl return value.\n.SS STRINGWRITEPROC\n.PP\n\\fIformatPtr->stringWriteProc\\fR provides the address of a procedure\nfor Tk to call to translate image data from a photo image into a\nstring.\n\\fIformatPtr->stringWriteProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringWriteProcVersion3\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tcl_Obj *\\fImetadataIn\\fR,\n        Tk_PhotoImageBlock *\\fIblockPtr\\fR);\n.CE\nThe \\fIinterp\\fR argument is the interpreter in which the command was\ninvoked to convert the image; it should be used for reporting errors.\nThe image data to be converted are in memory and are described by the\nTk_PhotoImageBlock structure pointed to by \\fIblockPtr\\fR; see the\nmanual page FindPhoto(3) for details.  The data for the string\nshould be put in the interpreter \\fIinterp\\fR result.\nThe \\fIformat\\fR argument contains the\nvalue given for the \\fB\\-format\\fR option, or NULL if the option was\nnot specified.  The format string can contain extra characters\nafter the name of the format.  If appropriate, the\n\\fIformatPtr->stringWriteProc\\fR procedure may interpret these\ncharacters to specify further details about the image file.\n\\fBmetadataIn\\fR may contain metadata keys that a driver may include\ninto the output data.\nThe return value is a standard Tcl return value.\n.PP\n.SH \"METADATA INTERFACE\"\n.PP\nImage formats contain a description of the image bitmap and may\ncontain additional information like image resolution or comments.\nImage metadata may be read from image files and passed to the script\nlevel by including dictionary keys into the metadata property of the\nimage. Image metadata may be written to image data on file write or\nimage data output.\n.PP\n.SS \"METADATA KEYS\"\n.PP\nThe metadata may contain any key.\nA driver will handle only a set of dictionary keys documented in the\ndocumentation. See the photo image manual page for currently defined\nkeys for the system drivers.\n.PP\nThe following rules may give guidance to name metadata keys:\n.IP \\(bu\nAbbreviations are in upper case.\n.IP \\(bu\nWords are in US English in small case (except proper nouns)\n.IP \\(bu\nVertical DPI is expressed as DPI/aspect. The reason is, that some\nimage formats may feature aspect and no resolution value.\n.SS \"METADATA INPUT\"\n.PP\nEach driver function gets a Tcl object pointer \\fBmetadataIn\\fR as\nparameter. This parameter serves to input a metadata dict to the\ndriver function.\nIt may be NULL to flag that the metadata dict is empty.\n.PP\nA typical driver code snipped to check for a metadata key is:\n.CS\nif (NULL != metadataIn) {\n    Tcl_Obj *itemData;\n    Tcl_DictObjGet(interp, metadataIn, Tcl_NewStringObj(\"Comment\",-1),\n            &itemData));\n    // use value reference in itemData\n}\n.CE\n.PP\nThe \\fB\\-metadata\\fR command option data of the following commands is passed\nto the driver: \\fBimage create\\fR, \\fBconfigure\\fR, \\fBput\\fR,\n\\fBread\\fR, \\fBdata\\fR and \\fBwrite\\fR.\nIf no \\fB\\-metadata\\fR command option available or not given, the metadata\nproperty of the image is passed to the driver using the following\ncommands: \\fBcget\\fR, \\fBconfigure\\fR, \\fBdata\\fR and \\fBwrite\\fR.\n.PP\nNote that setting the \\fB\\-metadata\\fR property of an image using\n\\fBconfigure\\fR without any other option does not invoke any driver\nfunction.\n.PP\nThe metadata dictionary is not suited to pass options to the driver\nrelated to the bitmap representation, as the image bitmap is not\nrecreated on a metadata change. The format string should be used for\nthis purpose.\n.PP\n.SS \"METADATA OUTPUT\"\n.PP\nThe image match and read driver functions may set keys in a prepared\nmetadata dict to return them.\nThose functions get a Tcl object pointer \\fImetadataOut\\fR as\nparameter.\n\\fImetadataOut\\fR may be NULL to indicate, that no metadata return is\nrequired (\\fBput\\fR, \\fBread\\fR subcommands). The variable pointed to\nby \\fImetadataOut\\fR is initialized to an empty unshared dict object if\nmetadata return is attended (\\fBimage create\\fR command, \\fBconfigure\\fR\nsubcommand). The driver may set dict keys in this object to return\nmetadata.\nIf a match function succeeds, the metadataOut pointer is passed to the\ncorresponding read function.\n.PP\nA sample driver code snippet is:\n.CS\nif (NULL != metadataOut) {\n    Tcl_DictObjPut(NULL, metadataOut, Tcl_NewStringObj(\"XMP\",-1),\n            Tcl_NewStringObj(xmpMetadata));\n}\n.CE\n.PP\nThe metadata keys returned by the driver are merged into the present\nmetadata property of the image or into the metadata dict given by the\n\\fB\\-metadata\\fR command line option.\nAt the script level, the command \\fBimage create\\fR and the\n\\fBconfigure\\fR method may return metadata from the driver.\n.PP\nFormat string options or metadata keys may influence the creation of\nmetadata within the driver.\nFor example, the creation of an expensive metadata key may depend on a\nformat string option or on a metadata input key.\n.PP\n.VE 9.0\n.SH \"VERSION 2 INTERFACE\"\n.PP\nVersion 2 Interface does not include the possibility for the driver to\nuse the metadata dict for input or output.\n.SS SYNOPSIS\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreatePhotoImageFormat\\fR(\\fIformatPtr\\fR)\n.SS ARGUMENTS\n.AS \"const Tk_PhotoImageFormat\" *formatPtr\n.AP \"const Tk_PhotoImageFormat\" *formatPtr in\nStructure that defines the new file format.\n.BE\n.SS DESCRIPTION\nA driver using the version 2 interface invokes \\fBTk_CreatePhotoImageFormat\\fR\nfor driver registration. The Tk_PhotoImageFormat structure\ncontains the following fields:\n.CS\ntypedef struct {\n    const char *\\fIname\\fR;\n    Tk_ImageFileMatchProc *\\fIfileMatchProc\\fR;\n    Tk_ImageStringMatchProc *\\fIstringMatchProc\\fR;\n    Tk_ImageFileReadProc *\\fIfileReadProc\\fR;\n    Tk_ImageStringReadProc *\\fIstringReadProc\\fR;\n    Tk_ImageFileWriteProc *\\fIfileWriteProc\\fR;\n    Tk_ImageStringWriteProc *\\fIstringWriteProc\\fR;\n} \\fBTk_PhotoImageFormat\\fR;\n.CE\n.PP\n.SS FILEMATCHPROC\n.PP\n\\fIformatPtr->fileMatchProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileMatchProc\\fR(\n        Tcl_Channel \\fIchan\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        int *\\fIwidthPtr\\fR,\n        int *\\fIheightPtr\\fR,\n        Tcl_Interp *\\fIinterp\\fR);\n.CE\n.PP\n.SS STRINGMATCHPROC\n.PP\n\\fIformatPtr->stringMatchProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringMatchProc\\fR(\n        Tcl_Obj *\\fIdata\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        int *\\fIwidthPtr\\fR,\n        int *\\fIheightPtr\\fR,\n        Tcl_Interp *\\fIinterp\\fR);\n.CE\n.SS FILEREADPROC\n.PP\n\\fIformatPtr->fileReadProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileReadProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Channel \\fIchan\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        PhotoHandle \\fIimageHandle\\fR,\n        int \\fIdestX\\fR, int \\fIdestY\\fR,\n        int \\fIwidth\\fR, int \\fIheight\\fR,\n        int \\fIsrcX\\fR, int \\fIsrcY\\fR);\n.CE\n.SS STRINGREADPROC\n.PP\n\\fIformatPtr->stringReadProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringReadProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Obj *\\fIdata\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        PhotoHandle \\fIimageHandle\\fR,\n        int \\fIdestX\\fR, int \\fIdestY\\fR,\n        int \\fIwidth\\fR, int \\fIheight\\fR,\n        int \\fIsrcX\\fR, int \\fIsrcY\\fR);\n.CE\n.SS FILEWRITEPROC\n.PP\n\\fIformatPtr->fileWriteProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageFileWriteProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        const char *\\fIfileName\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tk_PhotoImageBlock *\\fIblockPtr\\fR);\n.CE\n.SS STRINGWRITEPROC\n.PP\n\\fIformatPtr->stringWriteProc\\fR must match the following prototype:\n.CS\ntypedef int \\fBTk_ImageStringWriteProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR,\n        Tcl_Obj *\\fIformat\\fR,\n        Tk_PhotoImageBlock *\\fIblockPtr\\fR);\n.CE\n.SH \"SEE ALSO\"\nTk_FindPhoto, Tk_PhotoPutBlock\n.SH KEYWORDS\nphoto image, image file\n"
  },
  {
    "path": "doc/CrtSelHdlr.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateSelHandler 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateSelHandler, Tk_DeleteSelHandler \\- arrange to handle requests for a selection\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateSelHandler\\fR(\\fItkwin, selection, target, proc, clientData, format\\fR)\n.sp\n\\fBTk_DeleteSelHandler\\fR(\\fItkwin, selection, target\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_SelectionProc clientData\n.AP Tk_Window tkwin in\nWindow for which \\fIproc\\fR will provide selection information.\n.AP Atom selection in\nThe name of the selection for which \\fIproc\\fR will provide\nselection information.\n.AP Atom target in\nForm in which \\fIproc\\fR can provide the selection (e.g. STRING\nor FILE_NAME).  Corresponds to \\fItype\\fR arguments in \\fBselection\\fR\ncommands.\n.AP Tk_SelectionProc *proc in\nProcedure to invoke whenever the selection is owned by \\fItkwin\\fR\nand the selection contents are requested in the format given by\n\\fItarget\\fR.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.AP Atom format in\nIf the selection requestor is not in this process, \\fIformat\\fR determines\nthe representation used to transmit the selection to its\nrequestor.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateSelHandler\\fR arranges for a particular procedure\n(\\fIproc\\fR) to be called whenever \\fIselection\\fR is owned by\n\\fItkwin\\fR and the selection contents are requested in the\nform given by \\fItarget\\fR.\n\\fITarget\\fR should be one of\nthe entries defined in the left column of Table 2 of the\nX Inter-Client Communication Conventions Manual (ICCCM) or\nany other form in which an application is willing to present\nthe selection.  The most common form is STRING.\n.PP\n\\fIProc\\fR should have arguments and result that match the\ntype \\fBTk_SelectionProc\\fR:\n.CS\ntypedef Tcl_Size \\fBTk_SelectionProc\\fR(\n        void *\\fIclientData\\fR,\n        Tcl_Size \\fIoffset\\fR,\n        char *\\fIbuffer\\fR,\n        Tcl_Size \\fImaxBytes\\fR);\n.CE\nThe \\fIclientData\\fR parameter to \\fIproc\\fR is a copy of the\n\\fIclientData\\fR argument given to \\fBTk_CreateSelHandler\\fR.\nTypically, \\fIclientData\\fR points to a data\nstructure containing application-specific information that is\nneeded to retrieve the selection.  \\fIOffset\\fR specifies an\noffset position into the selection, \\fIbuffer\\fR specifies a\nlocation at which to copy information about the selection, and\n\\fImaxBytes\\fR specifies the amount of space available at\n\\fIbuffer\\fR.  \\fIProc\\fR should place a NULL-terminated string\nat \\fIbuffer\\fR containing \\fImaxBytes\\fR or fewer characters\n(not including the terminating NULL), and it should return a\ncount of the number of non-NULL characters stored at\n\\fIbuffer\\fR.  If the selection no longer exists (e.g. it once\nexisted but the user deleted the range of characters containing\nit), then \\fIproc\\fR should return \\-1.\n.PP\nWhen transferring large selections, Tk will break them up into\nsmaller pieces (typically a few thousand bytes each) for more\nefficient transmission.  It will do this by calling \\fIproc\\fR\none or more times, using successively higher values of \\fIoffset\\fR\nto retrieve successive portions of the selection.  If \\fIproc\\fR\nreturns a count less than \\fImaxBytes\\fR it means that the entire\nremainder of the selection has been returned.  If \\fIproc\\fR's return\nvalue is \\fImaxBytes\\fR it means there may be additional information\nin the selection, so Tk must make another call to \\fIproc\\fR to\nretrieve the next portion.\n.PP\n\\fIProc\\fR always returns selection information in the form of a\ncharacter string.  However, the ICCCM allows for information to\nbe transmitted from the selection owner to the selection requestor\nin any of several formats, such as a string, an array of atoms, an\narray of integers, etc.  The \\fIformat\\fR argument to\n\\fBTk_CreateSelHandler\\fR indicates what format should be used to\ntransmit the selection to its requestor (see the middle column of\nTable 2 of the ICCCM for examples).  If \\fIformat\\fR is not\nSTRING, then Tk will take the value returned by \\fIproc\\fR and divided\nit into fields separated by white space.  If \\fIformat\\fR is ATOM,\nthen Tk will return the selection as an array of atoms, with each\nfield in \\fIproc\\fR's result treated as the name of one atom.  For\nany other value of \\fIformat\\fR, Tk will return the selection as an\narray of 32-bit values where each field of \\fIproc\\fR's result is\ntreated as a number and translated to a 32-bit value.  In any event,\nthe \\fIformat\\fR atom is returned to the selection requestor along\nwith the contents of the selection.\n.PP\nIf \\fBTk_CreateSelHandler\\fR is called when there already exists a\nhandler for \\fIselection\\fR and \\fItarget\\fR on \\fItkwin\\fR, then the\nexisting handler is replaced with a new one.\n.PP\n\\fBTk_DeleteSelHandler\\fR removes the handler given by \\fItkwin\\fR,\n\\fIselection\\fR, and \\fItarget\\fR, if such a handler exists.\nIf there is no such handler then it has no effect.\n.SH KEYWORDS\nformat, handler, selection, target\n"
  },
  {
    "path": "doc/CrtWindow.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateWindow 3 4.2 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateWindow, Tk_CreateWindowFromPath, Tk_DestroyWindow, Tk_MakeWindowExist \\- create or delete window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_CreateWindow\\fR(\\fIinterp, parent, name, topLevScreen\\fR)\n.sp\nTk_Window\n\\fBTk_CreateAnonymousWindow\\fR(\\fIinterp, parent, topLevScreen\\fR)\n.sp\nTk_Window\n\\fBTk_CreateWindowFromPath\\fR(\\fIinterp, tkwin, pathName, topLevScreen\\fR)\n.sp\n\\fBTk_DestroyWindow\\fR(\\fItkwin\\fR)\n.sp\n\\fBTk_MakeWindowExist\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *topLevScreen\n.AP Tcl_Interp *interp out\nTcl interpreter to use for error reporting.  If no error occurs,\nthen \\fI*interp\\fR is not modified.\n.AP Tk_Window parent in\nToken for the window that is to serve as the logical parent of\nthe new window.\n.AP \"const char\" *name in\nName to use for this window.  Must be unique among all children of\nthe same \\fIparent\\fR.\n.AP \"const char\" *topLevScreen in\nHas same format as \\fIscreenName\\fR.  If NULL, then new window is\ncreated as an internal window.  If non-NULL, new window is created as\na top-level window on screen \\fItopLevScreen\\fR.  If \\fItopLevScreen\\fR\nis an empty string\n.PQ \"\"\nthen new window is created as top-level window of \\fIparent\\fR's screen.\n.AP Tk_Window tkwin in\nToken for window.\n.AP \"const char\" *pathName in\nName of new window, specified as path name within application\n(e.g. \\fB.a.b.c\\fR).\n.BE\n.SH DESCRIPTION\n.PP\nThe procedures \\fBTk_CreateWindow\\fR,\n\\fBTk_CreateAnonymousWindow\\fR, and \\fBTk_CreateWindowFromPath\\fR\nare used to create new windows for\nuse in Tk-based applications.  Each of the procedures returns a token\nthat can be used to manipulate the window in other calls to the Tk\nlibrary.  If the window could not be created successfully, then NULL\nis returned and the result of interpreter \\fIinterp\\fR is modified to\nhold an error message.\n.PP\nTk supports two different kinds of windows:  internal\nwindows and top-level windows.\nAn internal window is an interior window of a Tk application, such as a\nscrollbar or menu bar or button.  A top-level window is one that is\ncreated as a child of a screen's root window, rather than as an\ninterior window, but which is logically part of some existing main\nwindow.  Examples of top-level windows are pop-up menus and dialog boxes.\n.PP\nNew windows may be created by calling\n\\fBTk_CreateWindow\\fR.  If the \\fItopLevScreen\\fR argument is\nNULL, then the new window will be an internal window.  If\n\\fItopLevScreen\\fR is non-NULL, then the new window will be a\ntop-level window: \\fItopLevScreen\\fR indicates the name of\na screen and the new window will be created as a child of the\nroot window of \\fItopLevScreen\\fR.  In either case Tk will\nconsider the new window to be the logical child of \\fIparent\\fR:\nthe new window's path name will reflect this fact, options may\nbe specified for the new window under this assumption, and so on.\nThe only difference is that new X window for a top-level window\nwill not be a child of \\fIparent\\fR's X window.  For example, a pull-down\nmenu's \\fIparent\\fR would be the button-like window used to invoke it,\nwhich would in turn be a child of the menu bar window.  A dialog box might\nhave the application's main window as its parent.\n.PP\n\\fBTk_CreateAnonymousWindow\\fR differs from \\fBTk_CreateWindow\\fR in\nthat it creates an unnamed window.  This window will be manipulatable\nonly using C interfaces, and will not be visible to Tcl scripts.  Both\ninterior windows and top-level windows may be created with\n\\fBTk_CreateAnonymousWindow\\fR.\n.PP\n\\fBTk_CreateWindowFromPath\\fR offers an alternate way of specifying\nnew windows.  In \\fBTk_CreateWindowFromPath\\fR the new\nwindow is specified with a token for any window in the target\napplication (\\fItkwin\\fR), plus a path name for the new window.\nIt produces the same effect as \\fBTk_CreateWindow\\fR and allows\nboth top-level and internal windows to be created, depending on\nthe value of \\fItopLevScreen\\fR.  In calls to \\fBTk_CreateWindowFromPath\\fR,\nas in calls to \\fBTk_CreateWindow\\fR, the parent of the new window\nmust exist at the time of the call, but the new window must not\nalready exist.\n.PP\nThe window creation procedures do not\nactually issue the command to X to create a window.\nInstead, they create a local data structure associated with\nthe window and defer the creation of the X window.\nThe window will actually be created by the first call to\n\\fBTk_MapWindow\\fR.  Deferred window creation allows various\naspects of the window (such as its size, background color,\netc.) to be modified after its creation without incurring\nany overhead in the X server.  When the window is finally\nmapped all of the window attributes can be set while creating\nthe window.\n.PP\nThe value returned by a window-creation procedure is not the\nX token for the window (it cannot be, since X has not been\nasked to create the window yet).  Instead, it is a token\nfor Tk's local data structure for the window.  Most\nof the Tk library procedures take Tk_Window tokens, rather\nthan X identifiers.  The actual\nX window identifier can be retrieved from the local\ndata structure using the \\fBTk_WindowId\\fR macro;  see\nthe manual entry for \\fBTk_WindowId\\fR for details.\n.PP\n\\fBTk_DestroyWindow\\fR deletes a window and all the data\nstructures associated with it, including any event handlers\ncreated with \\fBTk_CreateEventHandler\\fR.  In addition,\n\\fBTk_DestroyWindow\\fR will delete any children of \\fItkwin\\fR\nrecursively (where children are defined in the Tk sense, consisting\nof all windows that were created with the given window as \\fIparent\\fR).\nIf \\fItkwin\\fR is an internal window, then event\nhandlers interested in destroy events\nare invoked immediately.  If \\fItkwin\\fR is a top-level or main window,\nthen the event handlers will be invoked later, after X has seen\nthe request and returned an event for it.\n.PP\nIf a window has been created\nbut has not been mapped, so no X window exists, it is\npossible to force the creation of the X window by\ncalling \\fBTk_MakeWindowExist\\fR.  This procedure issues\nthe X commands to instantiate the window given by \\fItkwin\\fR.\n.SH KEYWORDS\ncreate, deferred creation, destroy, display, internal window,\nscreen, top-level window, window\n"
  },
  {
    "path": "doc/DeleteImg.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_DeleteImage 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_DeleteImage \\- Destroy an image.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_DeleteImage\\fR(\\fIinterp, name\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *interp\n.AP Tcl_Interp *interp in\nInterpreter for which the image was created.\n.AP \"const char\" *name in\nName of the image.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_DeleteImage\\fR deletes the image given by \\fIinterp\\fR\nand \\fIname\\fR, if there is one.  All instances of that image\nwill redisplay as empty regions.  If the given image does not\nexist then the procedure has no effect.\n.SH KEYWORDS\ndelete image, image manager\n"
  },
  {
    "path": "doc/DrawFocHlt.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_DrawFocusHighlight 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_DrawFocusHighlight \\- draw the traversal highlight ring for a widget\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_DrawFocusHighlight\\fR(\\fItkwin, gc, width, drawable\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *joinPtr\n.AP Tk_Window tkwin in\nWindow for which the highlight is being drawn.  Used to retrieve\nthe window's dimensions, among other things.\n.AP GC gc in\nGraphics context to use for drawing the highlight.\n.AP int width in\nWidth of the highlight ring, in pixels.\n.AP Drawable drawable in\nDrawable in which to draw the highlight;  usually an offscreen\npixmap for double buffering.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_DrawFocusHighlight\\fR is a utility procedure that draws the\ntraversal highlight ring for a widget.\nIt is typically invoked by widgets during redisplay.\n.SH KEYWORDS\nfocus, traversal highlight\n"
  },
  {
    "path": "doc/EventHndlr.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_CreateEventHandler 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateEventHandler, Tk_DeleteEventHandler, Tk_GetButtonMask, Tk_SendVirtualEvent \\- associate procedure callback with an X event\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_CreateEventHandler\\fR(\\fItkwin, mask, proc, clientData\\fR)\n.sp\n\\fBTk_DeleteEventHandler\\fR(\\fItkwin, mask, proc, clientData\\fR)\n.sp\n\\fBTk_GetButtonMask\\fR(\\fIbutton\\fR)\n.sp\n\\fBTk_SendVirtualEvent\\fR(\\fItkwin, eventName, detail\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"unsigned long\" clientData\n.AP unsigned button in\nButton number.\n.AP \"const char\" *eventName in\nThe name of the virtual event.\n.AP Tcl_Obj *detail in\nDetail information for the virtual event. May be NULL.\n.AP Tk_Window tkwin in\nToken for window in which events may occur.\n.AP \"unsigned long\" mask in\nBit-mask of events (such as \\fBButtonPressMask\\fR)\nfor which \\fIproc\\fR should be called.\n.AP Tk_EventProc *proc in\nProcedure to invoke whenever an event in \\fImask\\fR occurs\nin the window given by \\fItkwin\\fR.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_CreateEventHandler\\fR arranges for \\fIproc\\fR to be\ninvoked in the future whenever one of the event types specified\nby \\fImask\\fR occurs in the window specified by \\fItkwin\\fR.\nThe callback to \\fIproc\\fR will be made by \\fBTk_HandleEvent\\fR;\nthis mechanism only works in programs that dispatch events\nthrough \\fBTk_HandleEvent\\fR (or through other Tk procedures that\ncall \\fBTk_HandleEvent\\fR, such as \\fBTcl_DoOneEvent\\fR or\n\\fBTk_MainLoop\\fR).\n.PP\n\\fIProc\\fR should have arguments and result that match the\ntype \\fBTk_EventProc\\fR:\n.CS\ntypedef void \\fBTk_EventProc\\fR(\n        void *\\fIclientData\\fR,\n        XEvent *\\fIeventPtr\\fR);\n.CE\nThe \\fIclientData\\fR parameter to \\fIproc\\fR is a copy of the \\fIclientData\\fR\nargument given to \\fBTk_CreateEventHandler\\fR when the callback\nwas created.  Typically, \\fIclientData\\fR points to a data\nstructure containing application-specific information about\nthe window in which the event occurred.  \\fIEventPtr\\fR is\na pointer to the X event, which will be one of the ones\nspecified in the \\fImask\\fR argument to \\fBTk_CreateEventHandler\\fR.\n.PP\n\\fBTk_DeleteEventHandler\\fR may be called to delete a\npreviously-created event handler:  it deletes the first handler\nit finds that is associated with \\fItkwin\\fR and matches the\n\\fImask\\fR, \\fIproc\\fR, and \\fIclientData\\fR arguments.  If\nno such handler exists, then \\fBTk_HandleEvent\\fR returns\nwithout doing anything.  Although Tk supports it, it's probably\na bad idea to have more than one callback with the same \\fImask\\fR,\n\\fIproc\\fR, and \\fIclientData\\fR arguments.\nWhen a window is deleted all of its handlers will be deleted\nautomatically;  in this case there is no need to call\n\\fBTk_DeleteEventHandler\\fR.\n.PP\nIf multiple handlers are declared for the same type of X event\non the same window, then the handlers will be invoked in the\norder they were created.\n.PP\n\\fBTk_GetButtonMask\\fR returns the button mask corresponding to\nthe button. E.g it will return \\fIButton1Mask\\fR for button \\fIButton1\\fR.\n.PP\n\\fBTk_SendVirtualEvent\\fR sends a virtual event to Tk's event queue.\n.SH KEYWORDS\nbind, callback, event, handler\n"
  },
  {
    "path": "doc/FindPhoto.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Australian National University\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n'\\\" Author: Paul Mackerras (paulus@cs.anu.edu.au),\n'\\\"\t    Department of Computer Science,\n'\\\"\t    Australian National University.\n'\\\"\n.TH Tk_FindPhoto 3 8.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_FindPhoto, Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock, Tk_PhotoGetImage, Tk_PhotoBlank, Tk_PhotoExpand, Tk_PhotoGetSize, Tk_PhotoSetSize \\- manipulate the image data stored in a photo image.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_PhotoHandle\n\\fBTk_FindPhoto\\fR(\\fIinterp, imageName\\fR)\n.sp\nint\n\\fBTk_PhotoPutBlock\\fR(\\fIinterp, handle, blockPtr, x, y, width, height,\\\ncompRule\\fR)\n.sp\nint\n\\fBTk_PhotoPutZoomedBlock\\fR(\\fIinterp, handle, blockPtr, x, y, width, height,\\\nzoomX, zoomY, subsampleX, subsampleY, compRule\\fR)\n.sp\nint\n\\fBTk_PhotoGetImage\\fR(\\fIhandle, blockPtr\\fR)\n.sp\n\\fBTk_PhotoBlank\\fR(\\fIhandle\\fR)\n.sp\nint\n\\fBTk_PhotoExpand\\fR(\\fIinterp, handle, width, height\\fR)\n.sp\n\\fBTk_PhotoGetSize\\fR(\\fIhandle, widthPtr, heightPtr\\fR)\n.sp\nint\n\\fBTk_PhotoSetSize\\fR(\\fIinterp. handle, width, height\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_PhotoImageBlock window_path\n.AP Tcl_Interp *interp in\nInterpreter in which image was created and in which error reporting is\nto be done.\n.AP \"const char\" *imageName in\nName of the photo image.\n.AP Tk_PhotoHandle handle in\nOpaque handle identifying the photo image to be affected.\n.AP Tk_PhotoImageBlock *blockPtr in\nSpecifies the address and storage layout of image data.\n.AP int x in\nSpecifies the X coordinate where the top-left corner of the block is\nto be placed within the image.\n.AP int y in\nSpecifies the Y coordinate where the top-left corner of the block is\nto be placed within the image.\n.AP int width in\nSpecifies the width of the image area to be affected (for\n\\fBTk_PhotoPutBlock\\fR) or the desired image width (for\n\\fBTk_PhotoExpand\\fR and \\fBTk_PhotoSetSize\\fR).\n.AP int compRule in\nSpecifies the compositing rule used when combining transparent pixels\nin a block of data with a photo image.  Must be one of\n\\fBTK_PHOTO_COMPOSITE_OVERLAY\\fR (which puts the block of data over the top\nof the existing photo image, with the previous contents showing\nthrough in the transparent bits) or \\fBTK_PHOTO_COMPOSITE_SET\\fR (which\ndiscards the existing photo image contents in the rectangle covered by\nthe data block.)\n.AP int height in\nSpecifies the height of the image area to be affected (for\n\\fBTk_PhotoPutBlock\\fR) or the desired image height (for\n\\fBTk_PhotoExpand\\fR and \\fBTk_PhotoSetSize\\fR).\n.AP int *widthPtr out\nPointer to location in which to store the image width.\n.AP int *heightPtr out\nPointer to location in which to store the image height.\n.AP int subsampleX in\nSpecifies the subsampling factor in the X direction for input\nimage data.\n.AP int subsampleY in\nSpecifies the subsampling factor in the Y direction for input\nimage data.\n.AP int zoomX in\nSpecifies the zoom factor to be applied in the X direction to pixels\nbeing written to the photo image.\n.AP int zoomY in\nSpecifies the zoom factor to be applied in the Y direction to pixels\nbeing written to the photo image.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_FindPhoto\\fR returns an opaque handle that is used to identify a\nparticular photo image to the other procedures.  The parameter is the\nname of the image, that is, the name specified to the \\fBimage create\nphoto\\fR command, or assigned by that command if no name was specified.\nIf \\fIimageName\\fR does not exist or is not a photo image,\n\\fBTk_FindPhoto\\fR returns NULL.\n.PP\n\\fBTk_PhotoPutBlock\\fR is used to supply blocks of image data to be\ndisplayed.  The call affects an area of the image of size\n\\fIwidth\\fR x \\fIheight\\fR pixels, with its top-left corner at\ncoordinates (\\fIx\\fR,\\fIy\\fR).  All of \\fIwidth\\fR, \\fIheight\\fR,\n\\fIx\\fR, and \\fIy\\fR must be non-negative.\nIf part of this area lies outside the\ncurrent bounds of the image, the image will be expanded to include the\narea, unless the user has specified an explicit image size with the\n\\fB\\-width\\fR and/or \\fB\\-height\\fR widget configuration options\n(see photo(n)); in that\ncase the area is silently clipped to the image boundaries.\n.PP\nThe \\fIblock\\fR parameter is a pointer to a\n\\fBTk_PhotoImageBlock\\fR structure, defined as follows:\n.CS\ntypedef struct {\n    unsigned char *\\fIpixelPtr\\fR;\n    int \\fIwidth\\fR;\n    int \\fIheight\\fR;\n    int \\fIpitch\\fR;\n    int \\fIpixelSize\\fR;\n    int \\fIoffset\\fR[4];\n} \\fBTk_PhotoImageBlock\\fR;\n.CE\nThe \\fIpixelPtr\\fR field points to the first pixel, that is, the\ntop-left pixel in the block.\nThe \\fIwidth\\fR and \\fIheight\\fR fields specify the dimensions of the\nblock of pixels.  The \\fIpixelSize\\fR field specifies the address\ndifference between two horizontally adjacent pixels.  It should be 4 for\nRGB and 2 for grayscale image data.  Other values are possible, if the\noffsets in the \\fIoffset\\fR array are adjusted accordingly (e.g. for\nred, green and blue data stored in different planes).  Using such a\nlayout is strongly discouraged, though. Due to a bug, it might not work\ncorrectly if an alpha channel is provided. (see the \\fBBUGS\\fR section\nbelow). The \\fIpitch\\fR field specifies the\naddress difference between two vertically adjacent pixels.  The\n\\fIoffset\\fR array contains the offsets from the address of a pixel\nto the addresses of the bytes containing the red, green, blue and alpha\n(transparency) components.  If the offsets for red, green and blue are\nequal, the image is interpreted as grayscale. If they differ, RGB data\nis assumed. Normally the offsets will be 0, 1, 2, 3 for RGB data\nand 0, 0, 0, 1 for grayscale.  It is possible to provide image data\nwithout an alpha channel by setting the offset for alpha to a negative\nvalue and adjusting the \\fIpixelSize\\fR field accordingly. This use is\ndiscouraged, though (see the \\fBBUGS\\fR section below).\n.PP\nThe \\fIcompRule\\fR parameter to \\fBTk_PhotoPutBlock\\fR specifies a\ncompositing rule that says what to do with transparent pixels.  The\nvalue \\fBTK_PHOTO_COMPOSITE_OVERLAY\\fR says that the previous contents of\nthe photo image should show through, and the value\n\\fBTK_PHOTO_COMPOSITE_SET\\fR says that the previous contents of the photo\nimage should be completely ignored, and the values from the block be\ncopied directly across.  The behavior in Tk8.3 and earlier was\nequivalent to having \\fBTK_PHOTO_COMPOSITE_OVERLAY\\fR as a compositing rule.\n.PP\nThe value given for the \\fIwidth\\fR and \\fIheight\\fR parameters to\n\\fBTk_PhotoPutBlock\\fR do not have to correspond to the values specified\nin \\fIblock\\fR.  If they are smaller, \\fBTk_PhotoPutBlock\\fR extracts a\nsub-block from the image data supplied.  If they are larger, the data\ngiven are replicated (in a tiled fashion) to fill the specified area.\nThese rules operate independently in the horizontal and vertical\ndirections.\n.PP\n\\fBTk_PhotoPutBlock\\fR normally returns \\fBTCL_OK\\fR, though if it cannot\nallocate sufficient memory to hold the resulting image, \\fBTCL_ERROR\\fR is\nreturned instead and, if the \\fIinterp\\fR argument is non-NULL, an\nerror message is placed in the interpreter's result.\n.PP\n\\fBTk_PhotoPutZoomedBlock\\fR works like \\fBTk_PhotoPutBlock\\fR except that\nthe image can be reduced or enlarged for display.  The\n\\fIsubsampleX\\fR and \\fIsubsampleY\\fR parameters allow the size of the\nimage to be reduced by subsampling.\n\\fBTk_PhotoPutZoomedBlock\\fR will use only pixels from the input image\nwhose X coordinates are multiples of \\fIsubsampleX\\fR, and whose Y\ncoordinates are multiples of \\fIsubsampleY\\fR.  For example, an image\nof 512x512 pixels can be reduced to 256x256 by setting\n\\fIsubsampleX\\fR and \\fIsubsampleY\\fR to 2.\n.PP\nThe \\fIzoomX\\fR and \\fIzoomY\\fR parameters allow the image to be\nenlarged by pixel replication.  Each pixel of the (possibly subsampled)\ninput image will be written to a block \\fIzoomX\\fR pixels wide and\n\\fIzoomY\\fR pixels high of the displayed image.  Subsampling and\nzooming can be used together for special effects.\n.PP\n\\fBTk_PhotoGetImage\\fR can be used to retrieve image data from a photo\nimage.  \\fBTk_PhotoGetImage\\fR fills\nin the structure pointed to by the \\fIblockPtr\\fR parameter with values\nthat describe the address and layout of the image data that the\nphoto image has stored internally.  The values are valid\nuntil the image is destroyed or its size is changed.\n.PP\nIt is possible to modify an image by writing directly to the data\nthe \\fIpixelPtr\\fR field points to. The size of the image cannot be\nchanged this way, though.\nAlso, changes made by writing directly to \\fIpixelPtr\\fR will not be\nimmediately visible, but only after a call to\n\\fBTk_ImageChanged\\fR or after an event that causes the interested\nwidgets to redraw themselves.\nFor these reasons usually it is preferable to make changes to\na copy of the image data and write it back with\n\\fBTk_PhotoPutBlock\\fR or \\fBTk_PhotoPutZoomedBlock\\fR.\n.PP\n\\fBTk_PhotoGetImage\\fR returns 1 for compatibility with the\ncorresponding procedure in the old photo widget.\n.PP\n\\fBTk_PhotoBlank\\fR blanks the entire area of the\nphoto image.  Blank areas of a photo image are transparent.\n.PP\n\\fBTk_PhotoExpand\\fR requests that the widget's image be expanded to be\nat least \\fIwidth\\fR x \\fIheight\\fR pixels in size.  The width and/or\nheight are unchanged if the user has specified an explicit image width\nor height with the \\fB\\-width\\fR and/or \\fB\\-height\\fR configuration\noptions, respectively.\nIf the image data\nare being supplied in many small blocks, it is more efficient to use\n\\fBTk_PhotoExpand\\fR or \\fBTk_PhotoSetSize\\fR at the beginning rather than\nallowing the image to expand in many small increments as image blocks\nare supplied.\n.PP\n\\fBTk_PhotoExpand\\fR normally returns \\fBTCL_OK\\fR, though if it cannot\nallocate sufficient memory to hold the resulting image, \\fBTCL_ERROR\\fR is\nreturned instead and, if the \\fIinterp\\fR argument is non-NULL, an\nerror message is placed in the interpreter's result.\n.PP\n\\fBTk_PhotoSetSize\\fR specifies the size of the image, as if the user\nhad specified the given \\fIwidth\\fR and \\fIheight\\fR values to the\n\\fB\\-width\\fR and \\fB\\-height\\fR configuration options.  A value of\nzero for \\fIwidth\\fR or \\fIheight\\fR does not change the image's width\nor height, but allows the width or height to be changed by subsequent\ncalls to \\fBTk_PhotoPutBlock\\fR, \\fBTk_PhotoPutZoomedBlock\\fR or\n\\fBTk_PhotoExpand\\fR.\n.PP\n\\fBTk_PhotoSetSize\\fR normally returns \\fBTCL_OK\\fR, though if it cannot\nallocate sufficient memory to hold the resulting image, \\fBTCL_ERROR\\fR is\nreturned instead and, if the \\fIinterp\\fR argument is non-NULL, an\nerror message is placed in the interpreter's result.\n.PP\n\\fBTk_PhotoGetSize\\fR returns the dimensions of the image in\n*\\fIwidthPtr\\fR and *\\fIheightPtr\\fR.\n.SH PORTABILITY\n.PP\nIn Tk 8.3 and earlier, \\fBTk_PhotoPutBlock\\fR and\n\\fBTk_PhotoPutZoomedBlock\\fR had different signatures. If you want to\ncompile code that uses the old interface against 8.4 without updating\nyour code, compile it with the flag\n-DUSE_COMPOSITELESS_PHOTO_PUT_BLOCK.  Code linked using Stubs against\nolder versions of Tk will continue to work.\n.PP\nIn Tk 8.4, \\fBTk_PhotoPutBlock\\fR, \\fBTk_PhotoPutZoomedBlock\\fR,\n\\fBTk_PhotoExpand\\fR and \\fBTk_PhotoSetSize\\fR did not take an\n\\fIinterp\\fR argument or return any result code.  If insufficient\nmemory was available for an image, Tk would panic.  This behaviour is\nstill supported if you compile your extension with the additional flag\n-DUSE_PANIC_ON_PHOTO_ALLOC_FAILURE.  Code linked using Stubs against\nolder versions of Tk will continue to work.\n.SH BUGS\nThe \\fBTk_PhotoImageBlock\\fR structure used to provide image data to\n\\fBTk_PhotoPutBlock\\fR promises great flexibility in the layout of the\ndata (e.g. separate planes for the red, green, blue and alpha\nchannels).  Unfortunately, the implementation fails to hold this\npromise.  The problem is that the \\fIpixelSize\\fR field is\n(incorrectly) used to determine whether the image has an alpha channel.\nCurrently, if the offset for the alpha channel is greater than or equal to\n\\fIpixelSize\\fR, \\fBtk_PhotoPutblock\\fR assumes no alpha data is\npresent and makes the image fully opaque.  This means that for layouts\nwhere the channels are separate (or any other exotic layout where\n\\fIpixelSize\\fR has to be smaller than the alpha offset), the alpha\nchannel will not be read correctly.  In order to be on the safe side\nif this issue will be corrected in a future release, it is strongly\nrecommended you always provide alpha data - even if the image has no\ntransparency - and only use the \"standard\" layout with a\n\\fIpixelSize\\fR of 2 for grayscale and 4 for RGB data with\n\\fIoffset\\fRs of 0, 0, 0, 1 or 0, 1, 2, 3 respectively.\n.SH CREDITS\n.PP\nThe code for the photo image type was developed by Paul Mackerras,\nbased on his earlier photo widget code.\n.SH KEYWORDS\nphoto, image\n"
  },
  {
    "path": "doc/FontId.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_FontId 3 8.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_FontId, Tk_GetFontMetrics, Tk_PostscriptFontName \\- accessor functions for\nfonts\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nFont\n\\fBTk_FontId\\fR(\\fItkfont\\fR)\n.sp\n\\fBTk_GetFontMetrics\\fR(\\fItkfont, fmPtr\\fR)\n.sp\nint\n\\fBTk_PostscriptFontName\\fR(\\fItkfont, dsPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_FontMetrics *dsPtr\n.AP Tk_Font tkfont in\nOpaque font token being queried.  Must have been returned by a previous\ncall to \\fBTk_GetFont\\fR.\n.AP Tk_FontMetrics *fmPtr out\nPointer to structure in which the font metrics for \\fItkfont\\fR will\nbe stored. See \\fBDATA STRUCTURES\\fR below for details.\n.AP Tcl_DString *dsPtr out\nPointer to an initialized \\fBTcl_DString\\fR to which the name of the\nPostscript font that corresponds to \\fItkfont\\fR will be appended.\n.BE\n.SH DESCRIPTION\n.PP\nGiven a \\fItkfont\\fR, \\fBTk_FontId\\fR returns the token that should be\nselected into an XGCValues structure in order to construct a graphics\ncontext that can be used to draw text in the specified font.\n.PP\n\\fBTk_GetFontMetrics\\fR computes the ascent, descent, and linespace of the\n\\fItkfont\\fR in pixels and stores those values in the structure pointer to by\n\\fIfmPtr\\fR.  These values can be used in computations such as to space\nmultiple lines of text, to align the baselines of text in different\nfonts, and to vertically align text in a given region.  See the\ndocumentation for the \\fBfont\\fR command for definitions of the terms\nascent, descent, and linespace, used in font metrics.\n.PP\n\\fBTk_PostscriptFontName\\fR maps a \\fItkfont\\fR to the corresponding\nPostscript font name that should be used when printing.  The return value\nis the size in points of the \\fItkfont\\fR and the Postscript font name is\nappended to \\fIdsPtr\\fR.  \\fIDsPtr\\fR must refer to an initialized\n\\fBTcl_DString\\fR.  Given a\n.QW reasonable\nPostscript printer, the\nfollowing screen font families should print correctly:\n.IP\n\\fBAvant Garde\\fR, \\fBArial\\fR, \\fBBookman\\fR, \\fBCourier\\fR,\n\\fBCourier New\\fR, \\fBGeneva\\fR, \\fBHelvetica\\fR, \\fBMonaco\\fR,\n\\fBNew Century Schoolbook\\fR, \\fBNew York\\fR, \\fBPalatino\\fR, \\fBSymbol\\fR,\n\\fBTimes\\fR, \\fBTimes New Roman\\fR, \\fBZapf Chancery\\fR, and\n\\fBZapf Dingbats\\fR.\n.PP\nAny other font families may not print correctly because the computed\nPostscript font name may be incorrect or not exist on the printer.\n.SH \"DATA STRUCTURES\"\n.PP\nThe \\fBTk_FontMetrics\\fR data structure is used by \\fBTk_GetFontMetrics\\fR to\nreturn information about a font and is defined as follows:\n.CS\ntypedef struct {\n    int \\fIascent\\fR;\n    int \\fIdescent\\fR;\n    int \\fIlinespace\\fR;\n} \\fBTk_FontMetrics\\fR;\n.CE\n.PP\nThe \\fIascent\\fR field is the amount in pixels that the tallest\nletter sticks up above the baseline, plus any extra blank space added\nby the designer of the font.\n.PP\nThe \\fIdescent\\fR is the largest amount in pixels that any letter\nsticks below the baseline, plus any extra blank space added by the\ndesigner of the font.\n.PP\nThe \\fIlinespace\\fR is the sum of the ascent and descent.  How far\napart two lines of text in the same font should be placed so that none\nof the characters in one line overlap any of the characters in the\nother line.\n.SH \"SEE ALSO\"\nfont(n), MeasureChar(3)\n.SH KEYWORDS\nfont, measurement, Postscript\n"
  },
  {
    "path": "doc/GeomReq.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GeometryRequest 3 \"8.4\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GeometryRequest, Tk_SetMinimumRequestSize, Tk_SetInternalBorder, Tk_SetInternalBorderEx \\- specify desired geometry or internal border for a window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_GeometryRequest\\fR(\\fItkwin, reqWidth, reqHeight\\fR)\n.sp\n\\fBTk_SetMinimumRequestSize\\fR(\\fItkwin, minWidth, minHeight\\fR)\n.sp\n\\fBTk_SetInternalBorder\\fR(\\fItkwin, width\\fR)\n.sp\n\\fBTk_SetInternalBorderEx\\fR(\\fItkwin, left, right, top, bottom\\fR)\n.fi\n.SH ARGUMENTS\n.AS baseHeight clientData\n.AP Tk_Window tkwin in\nWindow for which geometry is being requested.\n.AP int reqWidth in\nDesired width for \\fItkwin\\fR, in pixel units.\n.AP int reqHeight in\nDesired height for \\fItkwin\\fR, in pixel units.\n.AP int minWidth in\nDesired minimum requested width for \\fItkwin\\fR, in pixel units.\n.AP int minHeight in\nDesired minimum requested height for \\fItkwin\\fR, in pixel units.\n.AP int width in\nSpace to leave for internal border for \\fItkwin\\fR, in pixel units.\n.AP int left in\nSpace to leave for left side of internal border for \\fItkwin\\fR,\nin pixel units.\n.AP int right in\nSpace to leave for right side of internal border for \\fItkwin\\fR,\nin pixel units.\n.AP int top in\nSpace to leave for top side of internal border for \\fItkwin\\fR,\nin pixel units.\n.AP int bottom in\nSpace to leave for bottom side of internal border for \\fItkwin\\fR,\nin pixel units.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GeometryRequest\\fR is called by widget code to indicate its\npreference for the dimensions of a particular window.  The arguments\nto \\fBTk_GeometryRequest\\fR are made available to the geometry\nmanager for the window, which then decides on the actual geometry\nfor the window.  Although geometry managers generally try to satisfy\nrequests made to \\fBTk_GeometryRequest\\fR, there is no guarantee that\nthis will always be possible.  Widget code should not assume that\na geometry request will be satisfied until it receives a\n\\fBConfigureNotify\\fR event indicating that the geometry change has\noccurred.  Widget code should never call procedures like\n\\fBTk_ResizeWindow\\fR directly.  Instead, it should invoke\n\\fBTk_GeometryRequest\\fR and leave the final geometry decisions to\nthe geometry manager.\n.PP\nIf \\fItkwin\\fR is a top-level window, then the geometry information\nwill be passed to the window manager using the standard ICCCM protocol.\n.PP\n\\fBTk_SetInternalBorder\\fR is called by widget code to indicate that\nthe widget has an internal border.  This means that the widget draws\na decorative border inside the window instead of using the standard\nX borders, which are external to the window's area.  For example,\ninternal borders are used to draw 3-D effects.  \\fIWidth\\fR\nspecifies the width of the border in pixels.  Geometry managers will\nuse this information to avoid placing any children of \\fItkwin\\fR\noverlapping the outermost \\fIwidth\\fR pixels of \\fItkwin\\fR's area.\n.PP\n\\fBTk_SetInternalBorderEx\\fR works like \\fBTk_SetInternalBorder\\fR\nbut lets you specify different widths for different sides of the window.\n.PP\n\\fBTk_SetMinimumRequestSize\\fR is called by widget code to indicate\nthat a geometry manager should request at least this size for the\nwidget.  This allows a widget to have some control over its size when\na propagating geometry manager is used inside it.\n.PP\nThe information specified in calls to \\fBTk_GeometryRequest\\fR,\n\\fBTk_SetMinimumRequestSize\\fR, \\fBTk_SetInternalBorder\\fR and\n\\fBTk_SetInternalBorderEx\\fR can be retrieved using the macros\n\\fBTk_ReqWidth\\fR, \\fBTk_ReqHeight\\fR, \\fBTk_MinReqWidth\\fR,\n\\fBTk_MinReqHeight\\fR, \\fBTk_MinReqWidth\\fR, \\fBTk_InternalBorderLeft\\fR,\n\\fBTk_InternalBorderRight\\fR, \\fBTk_InternalBorderTop\\fR and\n\\fBTk_InternalBorderBottom\\fR.\nSee the \\fBTk_WindowId\\fR manual entry for details.\n.SH KEYWORDS\ngeometry, request\n"
  },
  {
    "path": "doc/GetAnchor.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetAnchorFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetAnchorFromObj, Tk_GetAnchor, Tk_NameOfAnchor \\- translate between strings and anchor positions\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetAnchorFromObj\\fR(\\fIinterp, objPtr, anchorPtr\\fR)\n.sp\nint\n\\fBTk_GetAnchor\\fR(\\fIinterp, string, anchorPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfAnchor\\fR(\\fIanchor\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_Anchor\" *anchorPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting, or NULL.\n.AP Tcl_Obj *objPtr in/out\nString value contains name of anchor point:\n.QW \\fBn\\fR  ,\n.QW \\fBne\\fR ,\n.QW \\fBe\\fR  ,\n.QW \\fBse\\fR ,\n.QW \\fBs\\fR  ,\n.QW \\fBsw\\fR ,\n.QW \\fBw\\fR  ,\n.QW \\fBnw\\fR ,\nor\n.QW \\fBcenter\\fR ;\ninternal rep will be modified to cache corresponding Tk_Anchor. In the\ncase of\n.QW \\fBcenter\\fR\non input, a non-empty abbreviation of it may also be used on input.\n.AP \"const char\" *string in\nSame as \\fIobjPtr\\fR except description of anchor point is passed as\na string.\n.AP int *anchorPtr out\nPointer to location in which to store anchor position corresponding to\n\\fIobjPtr\\fR or \\fIstring\\fR.\n.AP Tk_Anchor anchor in\nAnchor position, e.g. \\fBTCL_ANCHOR_CENTER\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetAnchorFromObj\\fR places in \\fI*anchorPtr\\fR an anchor position\n(enumerated type \\fBTk_Anchor\\fR)\ncorresponding to \\fIobjPtr\\fR's value.  The result will be one of\n\\fBTK_ANCHOR_N\\fR, \\fBTK_ANCHOR_NE\\fR, \\fBTK_ANCHOR_E\\fR, \\fBTK_ANCHOR_SE\\fR,\n\\fBTK_ANCHOR_S\\fR, \\fBTK_ANCHOR_SW\\fR, \\fBTK_ANCHOR_W\\fR, \\fBTK_ANCHOR_NW\\fR,\nor \\fBTK_ANCHOR_CENTER\\fR.\nAnchor positions are typically used for indicating a point on an object\nthat will be used to position the object, e.g. \\fBTK_ANCHOR_N\\fR means\nposition the top center point of the object at a particular place.\n.PP\nUnder normal circumstances the return value is \\fBTCL_OK\\fR and\n\\fIinterp\\fR is unused.\nIf \\fIstring\\fR does not contain a valid anchor position\nor an abbreviation of one of these names, \\fBTCL_ERROR\\fR is returned,\n\\fI*anchorPtr\\fR is unmodified, and an error message is\nstored in \\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\n\\fBTk_GetAnchorFromObj\\fR caches information about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to\n\\fBTk_GetAnchorFromObj\\fR with the same \\fIobjPtr\\fR.\n.PP\n\\fBTk_GetAnchor\\fR is identical to \\fBTk_GetAnchorFromObj\\fR except\nthat the description of the anchor is specified with a string instead\nof an object.  This prevents \\fBTk_GetAnchor\\fR from caching the\nreturn value, so \\fBTk_GetAnchor\\fR is less efficient than\n\\fBTk_GetAnchorFromObj\\fR.\n.PP\n\\fBTk_NameOfAnchor\\fR is the logical inverse of \\fBTk_GetAnchor\\fR.\nGiven an anchor position such as \\fBTK_ANCHOR_N\\fR it returns a\nstatically-allocated string corresponding to \\fIanchor\\fR.\nIf \\fIanchor\\fR is not a legal anchor value, then\n.QW \"unknown anchor position\"\nis returned.\n.SH KEYWORDS\nanchor position\n"
  },
  {
    "path": "doc/GetBitmap.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_AllocBitmapFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_AllocBitmapFromObj, Tk_GetBitmap, Tk_GetBitmapFromObj, Tk_DefineBitmap, Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_FreeBitmapFromObj, Tk_FreeBitmap \\- maintain database of single-plane pixmaps\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nPixmap\n\\fBTk_AllocBitmapFromObj\\fR(\\fIinterp, tkwin, objPtr\\fR)\n.sp\nPixmap\n\\fBTk_GetBitmap\\fR(\\fIinterp, tkwin, info\\fR)\n.sp\nPixmap\n\\fBTk_GetBitmapFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\nint\n\\fBTk_DefineBitmap\\fR(\\fIinterp, name, source, width, height\\fR)\n.sp\nconst char *\n\\fBTk_NameOfBitmap\\fR(\\fIdisplay, bitmap\\fR)\n.sp\n\\fBTk_SizeOfBitmap\\fR(\\fIdisplay, bitmap, widthPtr, heightPtr\\fR)\n.sp\n\\fBTk_FreeBitmapFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_FreeBitmap\\fR(\\fIdisplay, bitmap\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"unsigned long\" *pixelPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting; if NULL then no error message\nis left after errors.\n.AP Tk_Window tkwin in\nToken for window in which the bitmap will be used.\n.AP Tcl_Obj *objPtr in/out\nString value describes desired bitmap; internal rep will be\nmodified to cache pointer to corresponding Pixmap.\n.AP \"const char\" *info in\nSame as \\fIobjPtr\\fR except description of bitmap is passed as a string and\nresulting Pixmap is not cached.\n.AP \"const char\" *name in\nName for new bitmap to be defined.\n.AP \"const void\" *source in\nData for bitmap, in standard bitmap format.\nMust be stored in static memory whose value will never change.\n.AP \"int\" width in\nWidth of bitmap.\n.AP \"int\" height in\nHeight of bitmap.\n.AP \"int\" *widthPtr out\nPointer to word to fill in with \\fIbitmap\\fR's width.\n.AP \"int\" *heightPtr out\nPointer to word to fill in with \\fIbitmap\\fR's height.\n.AP Display *display in\nDisplay for which \\fIbitmap\\fR was allocated.\n.AP Pixmap bitmap in\nIdentifier for a bitmap allocated by \\fBTk_AllocBitmapFromObj\\fR or\n\\fBTk_GetBitmap\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures manage a collection of bitmaps (one-plane pixmaps)\nbeing used by an application.  The procedures allow bitmaps to be\nre-used efficiently, thereby avoiding server overhead, and also\nallow bitmaps to be named with character strings.\n.PP\n\\fBTk_AllocBitmapFromObj\\fR returns a Pixmap identifier for a bitmap\nthat matches the description in \\fIobjPtr\\fR and is suitable for use\nin \\fItkwin\\fR.  It re-uses an existing bitmap, if possible, and\ncreates a new one otherwise.  \\fIObjPtr\\fR's value must have one\nof the following forms:\n.TP 20\n\\fB@\\fIfileName\\fR\n.\n\\fIFileName\\fR must be the name of a file containing a bitmap\ndescription in the standard X11 format.\n.TP 20\n\\fIname\\fR\n.\n\\fIName\\fR must be the name of a bitmap defined previously with\na call to \\fBTk_DefineBitmap\\fR.  The following names are pre-defined\nby Tk:\n.RS\n.IP \\fBerror\\fR 12\nThe international\n.QW don't\nsymbol:  a circle with a diagonal line across it.\n.IP \\fBgray75\\fR 12\n75% gray: a checkerboard pattern where three out of four bits are on.\n.IP \\fBgray50\\fR 12\n50% gray: a checkerboard pattern where every other bit is on.\n.IP \\fBgray25\\fR 12\n25% gray: a checkerboard pattern where one out of every four bits is on.\n.IP \\fBgray12\\fR 12\n12.5% gray: a pattern where one-eighth of the bits are on, consisting of\nevery fourth pixel in every other row.\n.IP \\fBhourglass\\fR 12\nAn hourglass symbol.\n.IP \\fBinfo\\fR 12\nA large letter\n.QW i .\n.IP \\fBquesthead\\fR 12\nThe silhouette of a human head, with a question mark in it.\n.IP \\fBquestion\\fR 12\nA large question-mark.\n.IP \\fBwarning\\fR 12\nA large exclamation point.\n.PP\nIn addition, the following pre-defined names are available only on the\n\\fBMacintosh\\fR platform:\n.IP \\fBdocument\\fR 12\nA generic document.\n.IP \\fBstationery\\fR 12\nDocument stationery.\n.IP \\fBedition\\fR 12\nThe \\fIedition\\fR symbol.\n.IP \\fBapplication\\fR 12\nGeneric application icon.\n.IP \\fBaccessory\\fR 12\nA desk accessory.\n.IP \\fBfolder\\fR 12\nGeneric folder icon.\n.IP \\fBpfolder\\fR 12\nA locked folder.\n.IP \\fBtrash\\fR 12\nA trash can.\n.IP \\fBfloppy\\fR 12\nA floppy disk.\n.IP \\fBramdisk\\fR 12\nA floppy disk with chip.\n.IP \\fBcdrom\\fR 12\nA cd disk icon.\n.IP \\fBpreferences\\fR 12\nA folder with prefs symbol.\n.IP \\fBquerydoc\\fR 12\nA database document icon.\n.IP \\fBstop\\fR 12\nA stop sign.\n.IP \\fBnote\\fR 12\nA face with balloon words.\n.IP \\fBcaution\\fR 12\nA triangle with an exclamation point.\n.RE\n.LP\nUnder normal conditions, \\fBTk_AllocBitmapFromObj\\fR\nreturns an identifier for the requested bitmap.  If an error\noccurs in creating the bitmap, such as when \\fIobjPtr\\fR refers\nto a non-existent file, then \\fBNone\\fR is returned and an error\nmessage is left in \\fIinterp\\fR's result if \\fIinterp\\fR is not\nNULL. \\fBTk_AllocBitmapFromObj\\fR caches information about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to procedures\nsuch as \\fBTk_AllocBitmapFromObj\\fR and \\fBTk_GetBitmapFromObj\\fR.\n.PP\n\\fBTk_GetBitmap\\fR is identical to \\fBTk_AllocBitmapFromObj\\fR except\nthat the description of the bitmap is specified with a string instead\nof an object.  This prevents \\fBTk_GetBitmap\\fR from caching the\nreturn value, so \\fBTk_GetBitmap\\fR is less efficient than\n\\fBTk_AllocBitmapFromObj\\fR.\n.PP\n\\fBTk_GetBitmapFromObj\\fR returns the token for an existing bitmap, given\nthe window and description used to create the bitmap.\n\\fBTk_GetBitmapFromObj\\fR does not actually create the bitmap; the bitmap\nmust already have been created with a previous call to\n\\fBTk_AllocBitmapFromObj\\fR or \\fBTk_GetBitmap\\fR.  The return\nvalue is cached in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_GetBitmapFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\n\\fBTk_DefineBitmap\\fR associates a name with\nin-memory bitmap data so that the name can be used in later\ncalls to \\fBTk_AllocBitmapFromObj\\fR or \\fBTk_GetBitmap\\fR.  The \\fInameId\\fR\nargument gives a name for the bitmap;  it must not previously\nhave been used in a call to \\fBTk_DefineBitmap\\fR.\nThe arguments \\fIsource\\fR, \\fIwidth\\fR, and \\fIheight\\fR\ndescribe the bitmap.\n\\fBTk_DefineBitmap\\fR normally returns \\fBTCL_OK\\fR; if an error occurs\n(e.g. a bitmap named \\fInameId\\fR has already been defined) then\n\\fBTCL_ERROR\\fR is returned and an error message is left in\ninterpreter \\fIinterp\\fR's result.\nNote that \\fBTk_DefineBitmap\\fR expects the memory pointed to by\n\\fIsource\\fR to be static:  \\fBTk_DefineBitmap\\fR does not make\na private copy of this memory, but uses the bytes pointed to\nby \\fIsource\\fR later in calls to \\fBTk_AllocBitmapFromObj\\fR or\n\\fBTk_GetBitmap\\fR.\n.PP\nTypically \\fBTk_DefineBitmap\\fR is used by \\fB#include\\fR-ing a\nbitmap file directly into a C program and then referencing\nthe variables defined by the file.\nFor example, suppose there exists a file \\fBstip.bitmap\\fR,\nwhich was created by the \\fBbitmap\\fR program and contains\na stipple pattern.\nThe following code uses \\fBTk_DefineBitmap\\fR to define a\nnew bitmap named \\fBfoo\\fR:\n.CS\nPixmap bitmap;\n#include \"stip.bitmap\"\nTk_DefineBitmap(interp, \"foo\", stip_bits,\n    stip_width, stip_height);\n\\&...\nbitmap = Tk_GetBitmap(interp, tkwin, \"foo\");\n.CE\nThis code causes the bitmap file to be read\nat compile-time and incorporates the bitmap information into\nthe program's executable image.  The same bitmap file could be\nread at run-time using \\fBTk_GetBitmap\\fR:\n.CS\nPixmap bitmap;\nbitmap = Tk_GetBitmap(interp, tkwin, \"@stip.bitmap\");\n.CE\nThe second form is a bit more flexible (the file could be modified\nafter the program has been compiled, or a different string could be\nprovided to read a different file), but it is a little slower and\nrequires the bitmap file to exist separately from the program.\n.PP\nTk maintains a database of all the bitmaps that are currently in use.\nWhenever possible, it will return an existing bitmap rather\nthan creating a new one.\nWhen a bitmap is no longer used, Tk will release it automatically.\nThis approach can substantially reduce server overhead, so\n\\fBTk_AllocBitmapFromObj\\fR and \\fBTk_GetBitmap\\fR should generally\nbe used in preference to Xlib procedures like \\fBXReadBitmapFile\\fR.\n.PP\nThe bitmaps returned by \\fBTk_AllocBitmapFromObj\\fR and \\fBTk_GetBitmap\\fR\nare shared, so callers should never modify them.\nIf a bitmap must be modified dynamically, then it should be\ncreated by calling Xlib procedures such as \\fBXReadBitmapFile\\fR\nor \\fBXCreatePixmap\\fR directly.\n.PP\nThe procedure \\fBTk_NameOfBitmap\\fR is roughly the inverse of\n\\fBTk_GetBitmap\\fR.\nGiven an X Pixmap argument, it returns the textual description that was\npassed to \\fBTk_GetBitmap\\fR when the bitmap was created.\n\\fIBitmap\\fR must have been the return value from a previous\ncall to \\fBTk_AllocBitmapFromObj\\fR or \\fBTk_GetBitmap\\fR.\n.PP\n\\fBTk_SizeOfBitmap\\fR returns the dimensions of its \\fIbitmap\\fR\nargument in the words pointed to by the \\fIwidthPtr\\fR and\n\\fIheightPtr\\fR arguments.  As with \\fBTk_NameOfBitmap\\fR,\n\\fIbitmap\\fR must have been created by \\fBTk_AllocBitmapFromObj\\fR or\n\\fBTk_GetBitmap\\fR.\n.PP\nWhen a bitmap is no longer needed, \\fBTk_FreeBitmapFromObj\\fR or\n\\fBTk_FreeBitmap\\fR should be called to release it.\nFor \\fBTk_FreeBitmapFromObj\\fR the bitmap to release is specified\nwith the same information used to create it; for\n\\fBTk_FreeBitmap\\fR the bitmap to release is specified\nwith its Pixmap token.\nThere should be exactly one call to \\fBTk_FreeBitmapFromObj\\fR\nor \\fBTk_FreeBitmap\\fR for each call to \\fBTk_AllocBitmapFromObj\\fR or\n\\fBTk_GetBitmap\\fR.\n.SH BUGS\n.PP\nIn determining whether an existing bitmap can be used to satisfy\na new request, \\fBTk_AllocBitmapFromObj\\fR and \\fBTk_GetBitmap\\fR\nconsider only the immediate value of the string description.  For\nexample, when a file name is passed to \\fBTk_GetBitmap\\fR,\n\\fBTk_GetBitmap\\fR will assume it is safe to re-use an existing\nbitmap created from the same file name:  it will not check to\nsee whether the file itself has changed, or whether the current\ndirectory has changed, thereby causing the name to refer to\na different file.\n.SH KEYWORDS\nbitmap, pixmap\n"
  },
  {
    "path": "doc/GetCapStyl.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetCapStyle 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetCapStyle, Tk_NameOfCapStyle \\- translate between strings and cap styles\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetCapStyle\\fR(\\fIinterp, string, capPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfCapStyle\\fR(\\fIcap\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *capPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP \"const char\" *string in\nString containing name of cap style \\- one of\n.QW \\fBbutt\\fR ,\n.QW \\fBprojecting\\fR ,\nor\n.QW \\fBround\\fR\n\\- or a unique abbreviation of one.\n.AP int *capPtr out\nPointer to location in which to store X cap style corresponding to\n\\fIstring\\fR.\n.AP int cap in\nCap style: one of \\fBCapButt\\fR, \\fBCapProjecting\\fR, or \\fBCapRound\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetCapStyle\\fR places in \\fI*capPtr\\fR the X cap style\ncorresponding to \\fIstring\\fR.\nThis will be one of the values\n\\fBCapButt\\fR, \\fBCapProjecting\\fR, or \\fBCapRound\\fR.\nCap styles are typically used in X graphics contexts to indicate\nhow the end-points of lines should be capped.\nSee the X documentation for information on what each style\nimplies.\n.PP\nUnder normal circumstances the return value is \\fBTCL_OK\\fR and\n\\fIinterp\\fR is unused.\nIf \\fIstring\\fR does not contain a valid cap style\nor an abbreviation of one of these names, then an error message is\nstored in interpreter \\fIinterp\\fR's result, \\fBTCL_ERROR\\fR is returned, and\n\\fI*capPtr\\fR is unmodified.\n.PP\n\\fBTk_NameOfCapStyle\\fR is the logical inverse of \\fBTk_GetCapStyle\\fR.\nGiven a cap style such as \\fBCapButt\\fR it returns a\nstatically-allocated string corresponding to \\fIcap\\fR.\nIf \\fIcap\\fR is not a legal cap style, then\n.QW \"unknown cap style\"\nis returned.\n.SH KEYWORDS\nbutt, cap style, projecting, round\n"
  },
  {
    "path": "doc/GetClrmap.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetColormap 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetColormap, Tk_PreserveColormap, Tk_FreeColormap \\- allocate and free colormaps\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nColormap\n\\fBTk_GetColormap\\fR(\\fIinterp, tkwin, string\\fR)\n.sp\n\\fBTk_PreserveColormap\\fR(\\fIdisplay, colormap\\fR)\n.sp\n\\fBTk_FreeColormap\\fR(\\fIdisplay, colormap\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Colormap\" colormap\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nToken for window in which colormap will be used.\n.AP \"const char\" *string in\nSelects a colormap:  either \\fBnew\\fR or the name of a window\nwith the same screen and visual as \\fItkwin\\fR.\n.AP Display *display in\nDisplay for which \\fIcolormap\\fR was allocated.\n.AP Colormap colormap in\nColormap to free or preserve;  must have been returned by a previous\ncall to \\fBTk_GetColormap\\fR or \\fBTk_GetVisual\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are used to manage colormaps.\n\\fBTk_GetColormap\\fR returns a colormap suitable for use in \\fItkwin\\fR.\nIf its \\fIstring\\fR argument is \\fBnew\\fR then a new colormap is\ncreated;  otherwise \\fIstring\\fR must be the name of another window\nwith the same screen and visual as \\fItkwin\\fR, and the colormap from that\nwindow is returned.\nIf \\fIstring\\fR does not make sense, or if it refers to a window on\na different screen from \\fItkwin\\fR or with\na different visual than \\fItkwin\\fR, then \\fBTk_GetColormap\\fR returns\n\\fBNone\\fR and leaves an error message in \\fIinterp\\fR's result.\n.PP\n\\fBTk_PreserveColormap\\fR increases the internal reference count for a\ncolormap previously returned by \\fBTk_GetColormap\\fR, which allows the\ncolormap to be stored in several locations without knowing which order\nthey will be released.\n.PP\n\\fBTk_FreeColormap\\fR should be called when a colormap returned by\n\\fBTk_GetColormap\\fR is no longer needed.\nTk maintains a reference count for each colormap returned by\n\\fBTk_GetColormap\\fR, so there should eventually be one call to\n\\fBTk_FreeColormap\\fR for each call to \\fBTk_GetColormap\\fR and each\ncall to \\fBTk_PreserveColormap\\fR.\nWhen a colormap's reference count becomes zero, Tk releases the\nX colormap.\n.PP\n\\fBTk_GetVisual\\fR and \\fBTk_GetColormap\\fR work together, in that\na new colormap created by \\fBTk_GetVisual\\fR may later be returned\nby \\fBTk_GetColormap\\fR.\nThe reference counting mechanism for colormaps includes both procedures,\nso callers of \\fBTk_GetVisual\\fR must also call \\fBTk_FreeColormap\\fR\nto release the colormap.\nIf \\fBTk_GetColormap\\fR is called with a \\fIstring\\fR value of\n\\fBnew\\fR then the resulting colormap will never\nbe returned by \\fBTk_GetVisual\\fR;  however, it can be used in other\nwindows by calling \\fBTk_GetColormap\\fR with the original window's\nname as \\fIstring\\fR.\n.SH KEYWORDS\ncolormap, visual\n"
  },
  {
    "path": "doc/GetColor.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1991 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_AllocColorFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_AllocColorFromObj, Tk_GetColor, Tk_GetColorFromObj, Tk_GetColorByValue, Tk_NameOfColor, Tk_FreeColorFromObj, Tk_FreeColor \\- maintain database of colors\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nXColor *\n\\fBTk_AllocColorFromObj\\fR(\\fIinterp, tkwin, objPtr\\fR)\n.sp\nXColor *\n\\fBTk_GetColor\\fR(\\fIinterp, tkwin, name\\fR)\n.sp\nXColor *\n\\fBTk_GetColorFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\nXColor *\n\\fBTk_GetColorByValue\\fR(\\fItkwin, prefPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfColor\\fR(\\fIcolorPtr\\fR)\n.sp\nGC\n\\fBTk_GCForColor\\fR(\\fIcolorPtr, drawable\\fR)\n.sp\n\\fBTk_FreeColorFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_FreeColor\\fR(\\fIcolorPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *colorPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nToken for window in which color will be used.\n.AP Tcl_Obj *objPtr in/out\nString value describes desired color; internal rep will be\nmodified to cache pointer to corresponding (XColor *).\n.AP \"const char\" *name in\nSame as \\fIobjPtr\\fR except description of color is passed as a string and\nresulting (XColor *) is not cached.\n.AP XColor *prefPtr in\nIndicates red, green, and blue intensities of desired\ncolor.\n.AP XColor *colorPtr in\nPointer to X color information.  Must have been allocated by previous\ncall to \\fBTk_AllocColorFromObj\\fR, \\fBTk_GetColor\\fR or\n\\fBTk_GetColorByValue\\fR, except when passed to \\fBTk_NameOfColor\\fR.\n.AP Drawable drawable in\nDrawable in which the result graphics context will be used.  Must have\nsame screen and depth as the window for which the color was allocated.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures manage the colors being used by a Tk application.\nThey allow colors to be shared whenever possible, so that colormap\nspace is preserved, and they pick closest available colors when\ncolormap space is exhausted.\n.PP\nGiven a textual description of a color, \\fBTk_AllocColorFromObj\\fR\nlocates a pixel value that may be used to render the color\nin a particular window.  The desired color is specified with a\nvalue whose string value must have one of the following forms:\n.TP 20\n\\fIcolorname\\fR\n.\nAny of the valid textual names for a color defined in the\nserver's color database file, such as \\fBred\\fR or \\fBPeachPuff\\fR.\n.TP 20\n\\fB#\\fIRGB\\fR\n.TP 20\n\\fB#\\fIRRGGBB\\fR\n.TP 20\n\\fB#\\fIRRRGGGBBB\\fR\n.TP 20\n\\fB#\\fIRRRRGGGGBBBB\\fR\n.\nA numeric specification of the red, green, and blue intensities\nto use to display the color.  Each \\fIR\\fR, \\fIG\\fR, or \\fIB\\fR\nrepresents a single hexadecimal digit.  The four forms permit\ncolors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values.\nWhen fewer than 16 bits are provided for each color, they represent\nthe most significant bits of the color, while the lower unfilled\nbits will be repeatedly replicated from the available higher bits.\nFor example, #3a7 is the same as #3333aaaa7777.\n.PP\n\\fBTk_AllocColorFromObj\\fR returns a pointer to\nan XColor structure;  the structure indicates the exact intensities of\nthe allocated color (which may differ slightly from those requested,\ndepending on the limitations of the screen) and a pixel value\nthat may be used to draw with the color in \\fItkwin\\fR.\nIf an error occurs in \\fBTk_AllocColorFromObj\\fR (such as an unknown\ncolor name) then NULL is returned and an error message is stored in\n\\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\nIf the colormap for \\fItkwin\\fR is full, \\fBTk_AllocColorFromObj\\fR\nwill use the closest existing color in the colormap.\n\\fBTk_AllocColorFromObj\\fR caches information about\nthe return value in \\fIobjPtr\\fR, which speeds up future calls to procedures\nsuch as \\fBTk_AllocColorFromObj\\fR and \\fBTk_GetColorFromObj\\fR.\n.PP\n\\fBTk_GetColor\\fR is identical to \\fBTk_AllocColorFromObj\\fR except\nthat the description of the color is specified with a string instead\nof a value.  This prevents \\fBTk_GetColor\\fR from caching the\nreturn value, so \\fBTk_GetColor\\fR is less efficient than\n\\fBTk_AllocColorFromObj\\fR.\n.PP\n\\fBTk_GetColorFromObj\\fR returns the token for an existing color, given\nthe window and description used to create the color.\n\\fBTk_GetColorFromObj\\fR does not actually create the color; the color\nmust already have been created with a previous call to\n\\fBTk_AllocColorFromObj\\fR or \\fBTk_GetColor\\fR.  The return\nvalue is cached in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_GetColorFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\n\\fBTk_GetColorByValue\\fR is similar to \\fBTk_GetColor\\fR except that\nthe desired color is indicated with the \\fIred\\fR, \\fIgreen\\fR, and\n\\fIblue\\fR fields of the structure pointed to by \\fIcolorPtr\\fR.\n.PP\nThis package maintains a database\nof all the colors currently in use.\nIf the same color is requested multiple times from\n\\fBTk_GetColor\\fR or \\fBTk_AllocColorFromObj\\fR (e.g. by different\nwindows), or if the\nsame intensities are requested multiple times from\n\\fBTk_GetColorByValue\\fR, then existing pixel values will\nbe re-used.  Re-using an existing pixel avoids any interaction\nwith the window server, which makes the allocation much more\nefficient.  These procedures also provide a portable interface that\nworks across all platforms.  For this reason, you should generally use\n\\fBTk_AllocColorFromObj\\fR, \\fBTk_GetColor\\fR, or \\fBTk_GetColorByValue\\fR\ninstead of lower level procedures like \\fBXAllocColor\\fR.\n.PP\nSince different calls to this package\nmay return the same shared\npixel value, callers should never change the color of a pixel\nreturned by the procedures.\nIf you need to change a color value dynamically, you should use\n\\fBXAllocColorCells\\fR to allocate the pixel value for the color.\n.PP\nThe procedure \\fBTk_NameOfColor\\fR is roughly the inverse of\n\\fBTk_GetColor\\fR.  If its \\fIcolorPtr\\fR argument was created\nby \\fBTk_AllocColorFromObj\\fR or \\fBTk_GetColor\\fR then the return value\nis the string that was used to create the\ncolor.  If \\fIcolorPtr\\fR was created by a call to \\fBTk_GetColorByValue\\fR,\nor by any other mechanism, then the return value is a string\nthat could be passed to \\fBTk_GetColor\\fR to return the same\ncolor.  Note:  the string returned by \\fBTk_NameOfColor\\fR is\nonly guaranteed to persist until the next call to\n\\fBTk_NameOfColor\\fR.\n.PP\n\\fBTk_GCForColor\\fR returns a graphics context whose \\fBforeground\\fR\nfield is the pixel allocated for \\fIcolorPtr\\fR and whose other fields\nall have default values.\nThis provides an easy way to do basic drawing with a color.\nThe graphics context is cached with the color and will exist only as\nlong as \\fIcolorPtr\\fR exists;  it is freed when the last reference\nto \\fIcolorPtr\\fR is freed by calling \\fBTk_FreeColor\\fR.\n.PP\nWhen a color is no longer needed \\fBTk_FreeColorFromObj\\fR or\n\\fBTk_FreeColor\\fR should be called to release it.\nFor \\fBTk_FreeColorFromObj\\fR the color to release is specified\nwith the same information used to create it; for\n\\fBTk_FreeColor\\fR the color to release is specified\nwith a pointer to its XColor structure.\nThere should be exactly one call to \\fBTk_FreeColorFromObj\\fR\nor \\fBTk_FreeColor\\fR for each call to \\fBTk_AllocColorFromObj\\fR,\n\\fBTk_GetColor\\fR, or \\fBTk_GetColorByValue\\fR.\n.SH KEYWORDS\ncolor, intensity, value, pixel value\n"
  },
  {
    "path": "doc/GetCursor.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_AllocCursorFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_AllocCursorFromObj, Tk_GetCursor, Tk_GetCursorFromObj, Tk_GetCursorFromData, Tk_NameOfCursor, Tk_FreeCursorFromObj, Tk_FreeCursor \\- maintain database of cursors\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Cursor\n\\fBTk_AllocCursorFromObj\\fR(\\fIinterp, tkwin, objPtr\\fR)\n.sp\nTk_Cursor\n\\fBTk_GetCursor\\fR(\\fIinterp, tkwin, name\\fR)\n.sp\nTk_Cursor\n\\fBTk_GetCursorFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\nTk_Cursor\n\\fBTk_GetCursorFromData\\fR(\\fIinterp, tkwin, source, mask, width, height, xHot, yHot, fg, bg\\fR)\n.sp\nconst char *\n\\fBTk_NameOfCursor\\fR(\\fIdisplay, cursor\\fR)\n.sp\n\\fBTk_FreeCursorFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_FreeCursor\\fR(\\fIdisplay, cursor\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"unsigned long\" *pixelPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nToken for window in which the cursor will be used.\n.AP Tcl_Obj *objPtr in/out\nDescription of cursor;  see below for possible values.  Internal rep will be\nmodified to cache pointer to corresponding Tk_Cursor.\n.AP \"const char\" *name in\nSame as \\fIobjPtr\\fR except description of cursor is passed as a string and\nresulting Tk_Cursor is not cached.\n.AP \"const char\" *source in\nData for cursor cursor, in standard cursor format.\n.AP \"const char\" *mask in\nData for mask cursor, in standard cursor format.\n.AP \"int\" width in\nWidth of \\fIsource\\fR and \\fImask\\fR.\n.AP \"int\" height in\nHeight of \\fIsource\\fR and \\fImask\\fR.\n.AP \"int\" xHot in\nX-location of cursor hot-spot.\n.AP \"int\" yHot in\nY-location of cursor hot-spot.\n.AP \"const char\" *fg in\nTextual description of foreground color for cursor.\n.AP \"const char\" *bg in\nTextual description of background color for cursor.\n.AP Display *display in\nDisplay for which \\fIcursor\\fR was allocated.\n.AP Tk_Cursor cursor in\nOpaque Tk identifier for cursor.  If passed to \\fBTk_FreeCursor\\fR, must\nhave been returned by some previous call to \\fBTk_GetCursor\\fR or\n\\fBTk_GetCursorFromData\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures manage a collection of cursors\nbeing used by an application.  The procedures allow cursors to be\nre-used efficiently, thereby avoiding server overhead, and also\nallow cursors to be named with character strings.\n.PP\n\\fBTk_AllocCursorFromObj\\fR takes as argument an object describing a\ncursor, and returns an opaque Tk identifier for a cursor corresponding\nto the description.  It re-uses an existing cursor if possible and\ncreates a new one otherwise.  \\fBTk_AllocCursorFromObj\\fR caches\ninformation about the return value in \\fIobjPtr\\fR, which speeds up\nfuture calls to procedures such as \\fBTk_AllocCursorFromObj\\fR and\n\\fBTk_GetCursorFromObj\\fR. If an error occurs in creating the cursor,\nsuch as when \\fIobjPtr\\fR refers to a non-existent file, then \\fBNone\\fR\nis returned and an error message will be stored in \\fIinterp\\fR's result\nif \\fIinterp\\fR is not NULL.  \\fIObjPtr\\fR must contain a standard Tcl\nlist with one of the following forms:\n.TP\n\\fIname\\fR\\0[\\fIfgColor\\fR\\0[\\fIbgColor\\fR]]\n.\n\\fIName\\fR is the name of a cursor in the standard X cursor cursor,\ni.e., any of the names defined in \\fBcursorcursor.h\\fR, without\nthe \\fBXC_\\fR.  Some example values are \\fBX_cursor\\fR, \\fBhand2\\fR,\nor \\fBleft_ptr\\fR.  Appendix B of\n.QW \"The X Window System\"\nby Scheifler & Gettys has illustrations showing what each of these\ncursors looks like.  If \\fIfgColor\\fR and \\fIbgColor\\fR are both\nspecified, they give the foreground and background colors to use\nfor the cursor (any of the forms acceptable to \\fBTk_GetColor\\fR\nmay be used).  If only \\fIfgColor\\fR is specified, then there\nwill be no background color:  the background will be transparent.\nIf no colors are specified, then the cursor\nwill use black for its foreground color and white for its background\ncolor.\n.RS\n.PP\nThe Macintosh version of Tk supports all of the X cursors and\nwill also accept any of the standard Mac cursors\nincluding \\fBibeam\\fR, \\fBcrosshair\\fR, \\fBwatch\\fR, \\fBplus\\fR, and\n\\fBarrow\\fR.  In addition, Tk will load Macintosh cursor resources of\nthe types \\fBcrsr\\fR (color) and \\fBCURS\\fR (black and white) by the\nname of the resource.  The application and all its open\ndynamic library's resource files will be searched for the named\ncursor.  If there are conflicts color cursors will always be loaded\nin preference to black and white cursors.\n.RE\n.TP\n\\fB@\\fIsourceName\\0maskName\\0fgColor\\0bgColor\\fR\n.\nIn this form, \\fIsourceName\\fR and \\fImaskName\\fR are the names of\nfiles describing cursors for the cursor's source bits and mask.\nEach file must be in standard X11 cursor format.\n\\fIFgColor\\fR and \\fIbgColor\\fR\nindicate the colors to use for the\ncursor, in any of the forms acceptable to \\fBTk_GetColor\\fR.  This\nform of the command will not work on Macintosh or Windows computers.\n.TP\n\\fB@\\fIsourceName\\0fgColor\\fR\n.\nThis form is similar to the one above, except that the source is\nused as mask also.  This means that the cursor's background is\ntransparent.  This form of the command will not work on Macintosh\nor Windows computers.\n.TP\n\\fB@\\fIsourceName\\fR\n.\nThis form only works on Windows, and will load a Windows system\ncursor (\\fB.ani\\fR or \\fB.cur\\fR) from the file specified in\n\\fIsourceName\\fR.\n.PP\n\\fBTk_GetCursor\\fR is identical to \\fBTk_AllocCursorFromObj\\fR except\nthat the description of the cursor is specified with a string instead\nof an object.  This prevents \\fBTk_GetCursor\\fR from caching the\nreturn value, so \\fBTk_GetCursor\\fR is less efficient than\n\\fBTk_AllocCursorFromObj\\fR.\n.PP\n\\fBTk_GetCursorFromObj\\fR returns the token for an existing cursor, given\nthe window and description used to create the cursor.\n\\fBTk_GetCursorFromObj\\fR does not actually create the cursor; the cursor\nmust already have been created with a previous call to\n\\fBTk_AllocCursorFromObj\\fR or \\fBTk_GetCursor\\fR.  The return\nvalue is cached in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_GetCursorFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\n\\fBTk_GetCursorFromData\\fR allows cursors to be created from\nin-memory descriptions of their source and mask cursors.  \\fISource\\fR\npoints to standard cursor data for the cursor's source bits, and\n\\fImask\\fR points to standard cursor data describing\nwhich pixels of \\fIsource\\fR are to be drawn and which are to be\nconsidered transparent.  \\fIWidth\\fR and \\fIheight\\fR give the\ndimensions of the cursor, \\fIxHot\\fR and \\fIyHot\\fR indicate the\nlocation of the cursor's hot-spot (the point that is reported when\nan event occurs), and \\fIfg\\fR and \\fIbg\\fR describe the cursor's\nforeground and background colors textually (any of the forms\nsuitable for \\fBTk_GetColor\\fR may be used).  Typically, the\narguments to \\fBTk_GetCursorFromData\\fR are created by including\na cursor file directly into the source code for a program, as in\nthe following example:\n.CS\nTk_Cursor cursor;\n#include \"source.cursor\"\n#include \"mask.cursor\"\ncursor = Tk_GetCursorFromData(interp, tkwin, source_bits,\n    mask_bits, source_width, source_height, source_x_hot,\n    source_y_hot, \"red\", \"blue\");\n.CE\n.PP\nUnder normal conditions \\fBTk_GetCursorFromData\\fR\nwill return an identifier for the requested cursor.  If an error\noccurs in creating the cursor then \\fBNone\\fR is returned and an error\nmessage will be stored in \\fIinterp\\fR's result.\n.PP\n\\fBTk_AllocCursorFromObj\\fR, \\fBTk_GetCursor\\fR, and\n\\fBTk_GetCursorFromData\\fR maintain a\ndatabase of all the cursors they have created.  Whenever possible,\na call to \\fBTk_AllocCursorFromObj\\fR, \\fBTk_GetCursor\\fR, or\n\\fBTk_GetCursorFromData\\fR will\nreturn an existing cursor rather than creating a new one.  This\napproach can substantially reduce server overhead, so the Tk\nprocedures should generally be used in preference to Xlib procedures\nlike \\fBXCreateFontCursor\\fR or \\fBXCreatePixmapCursor\\fR, which\ncreate a new cursor on each call.  The Tk procedures are also more\nportable than the lower-level X procedures.\n.PP\nThe procedure \\fBTk_NameOfCursor\\fR is roughly the inverse of\n\\fBTk_GetCursor\\fR.  If its \\fIcursor\\fR argument was created\nby \\fBTk_GetCursor\\fR, then the return value is the \\fIname\\fR\nargument that was passed to \\fBTk_GetCursor\\fR to create the\ncursor.  If \\fIcursor\\fR was created by a call to \\fBTk_GetCursorFromData\\fR,\nor by any other mechanism, then the return value is a hexadecimal string\ngiving the X identifier for the cursor.\nNote that the string returned by \\fBTk_NameOfCursor\\fR is\nonly guaranteed to persist until the next call to\n\\fBTk_NameOfCursor\\fR.  Also, this call is not portable except for\ncursors returned by \\fBTk_GetCursor\\fR.\n.PP\nWhen a cursor returned by \\fBTk_AllocCursorFromObj\\fR, \\fBTk_GetCursor\\fR,\nor \\fBTk_GetCursorFromData\\fR\nis no longer needed, \\fBTk_FreeCursorFromObj\\fR or\n\\fBTk_FreeCursor\\fR should be called to release it.\nFor \\fBTk_FreeCursorFromObj\\fR the cursor to release is specified\nwith the same information used to create it; for\n\\fBTk_FreeCursor\\fR the cursor to release is specified\nwith its Tk_Cursor token.\nThere should be exactly one call to \\fBTk_FreeCursor\\fR for\neach call to \\fBTk_AllocCursorFromObj\\fR, \\fBTk_GetCursor\\fR,\nor \\fBTk_GetCursorFromData\\fR.\n.SH BUGS\n.PP\nIn determining whether an existing cursor can be used to satisfy\na new request, \\fBTk_AllocCursorFromObj\\fR, \\fBTk_GetCursor\\fR,\nand \\fBTk_GetCursorFromData\\fR\nconsider only the immediate values of their arguments.  For\nexample, when a file name is passed to \\fBTk_GetCursor\\fR,\n\\fBTk_GetCursor\\fR will assume it is safe to re-use an existing\ncursor created from the same file name:  it will not check to\nsee whether the file itself has changed, or whether the current\ndirectory has changed, thereby causing the name to refer to\na different file.  Similarly, \\fBTk_GetCursorFromData\\fR assumes\nthat if the same \\fIsource\\fR pointer is used in two different calls,\nthen the pointers refer to the same data;  it does not check to\nsee if the actual data values have changed.\n.SH KEYWORDS\ncursor\n"
  },
  {
    "path": "doc/GetDash.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1989-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetDash 3 8.3 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetDash \\- convert from string to valid dash structure.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n\nint\n\\fBTk_GetDash\\fR(\\fIinterp, string, dashPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Dash *dashPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP \"const char\" *string in\nTextual value to be converted.\n.AP Tk_Dash *dashPtr out\nPoints to place to store the dash pattern\nvalue converted from \\fIstring\\fR. Must not be NULL.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedure parses the string and fills in the result in the\nTk_Dash structure. The string can be a list of integers or a\ncharacter string containing only\n.QW \\fB.,-_\\fR\nand spaces. If all\ngoes well, \\fBTCL_OK\\fR is returned and a dash descriptor is stored\nin the variable pointed to by \\fIdashPtr\\fR.\nIf \\fIstring\\fR does not have the\nproper syntax then \\fBTCL_ERROR\\fR is returned, an error message is left\nin the interpreter's result, and nothing is stored at *\\fIdashPtr\\fR.\n.PP\nThe first possible syntax is a list of integers. Each element\nrepresents the number of pixels of a line segment. Only the odd\nsegments are drawn using the\n.QW outline\ncolor. The other segments are drawn transparent.\n.PP\nThe second possible syntax is a character list containing only\n5 possible characters\n.QW \"\\fB.,-_ \\fR\" .\nThe space can be used\nto enlarge the space between other line elements, and can not\noccur in the first position of the string. Some examples:\n.PP\n.CS\n    \\-dash .     = \\-dash {2 4}\n    \\-dash -     = \\-dash {6 4}\n    \\-dash -.    = \\-dash {6 4 2 4}\n    \\-dash -..   = \\-dash {6 4 2 4 2 4}\n    \\-dash {. }  = \\-dash {2 8}\n    \\-dash ,     = \\-dash {4 4}\n.CE\n.PP\nThe main difference between this syntax and the numeric is that it\nis shape-conserving. This means that all values in the dash\nlist will be multiplied by the line width before display. This\nensures that\n.QW .\nwill always be displayed as a dot and\n.QW -\nalways as a dash regardless of the line width.\n.PP\nOn systems where only a limited set of dash patterns, the dash\npattern will be displayed as the most close dash pattern that\nis available. For example, on Windows only the first 4 of the\nabove examples are available; the last 2 examples will be\ndisplayed identically to the first one.\n.SH \"SEE ALSO\"\ncanvas(n), Tk_CreateItemType(3)\n.SH KEYWORDS\ndash, conversion\n"
  },
  {
    "path": "doc/GetFont.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_AllocFontFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_AllocFontFromObj, Tk_GetFont, Tk_GetFontFromObj, Tk_NameOfFont, Tk_FontGetDescription, Tk_FreeFontFromObj, Tk_FreeFont \\- maintain database of fonts\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Font\n\\fBTk_AllocFontFromObj\\fR(\\fIinterp, tkwin, objPtr\\fR)\n.sp\nTk_Font\n\\fBTk_GetFont\\fR(\\fIinterp, tkwin, string\\fR)\n.sp\nTk_Font\n\\fBTk_GetFontFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\nTcl_Obj *\n\\fBTk_FontGetDescription\\fR(\\fItkfont\\fR)\n.sp\nconst char *\n\\fBTk_NameOfFont\\fR(\\fItkfont\\fR)\n.sp\nTk_Font\n\\fBTk_FreeFontFromObj\\fR(\\fItkwin, objPtr\\fR)\n.sp\n\\fBTk_FreeFont\\fR(\\fItkfont\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"const char\" *tkfont\n.AP \"Tcl_Interp\" *interp in\nInterpreter to use for error reporting.  If \\fBNULL\\fR, then no error\nmessages are left after errors.\n.AP Tk_Window tkwin in\nToken for window in which font will be used.\n.AP Tcl_Obj *objPtr in/out\nGives name or description of font.  See documentation\nfor the \\fBfont\\fR command for details on acceptable formats.\nInternal rep will be modified to cache corresponding Tk_Font.\n.AP \"const char\" *string in\nSame as \\fIobjPtr\\fR except description of font is passed as a string and\nresulting Tk_Font is not cached.\n.AP Tk_Font tkfont in\nOpaque font token.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_AllocFontFromObj\\fR finds the font indicated by \\fIobjPtr\\fR and\nreturns a token that represents the font.  The return value can be used\nin subsequent calls to procedures such as \\fBTk_GetFontMetrics\\fR,\n\\fBTk_MeasureChars\\fR, and \\fBTk_FreeFont\\fR.  The Tk_Font token\nwill remain valid until\n\\fBTk_FreeFontFromObj\\fR or \\fBTk_FreeFont\\fR is called to release it.\n\\fIObjPtr\\fR can contain either a symbolic name or a font description; see\nthe documentation for the \\fBfont\\fR command for a description of the\nvalid formats.  If \\fBTk_AllocFontFromObj\\fR is unsuccessful (because,\nfor example, \\fIobjPtr\\fR did not contain a valid font specification) then it\nreturns \\fBNULL\\fR and leaves an error message in \\fIinterp\\fR's result\nif \\fIinterp\\fR is not \\fBNULL\\fR.  \\fBTk_AllocFontFromObj\\fR caches\ninformation about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to procedures\nsuch as \\fBTk_AllocFontFromObj\\fR and \\fBTk_GetFontFromObj\\fR.\n.PP\n\\fBTk_GetFont\\fR is identical to \\fBTk_AllocFontFromObj\\fR except\nthat the description of the font is specified with a string instead\nof an object.  This prevents \\fBTk_GetFont\\fR from caching the\nmatching Tk_Font, so \\fBTk_GetFont\\fR is less efficient than\n\\fBTk_AllocFontFromObj\\fR.\n.PP\n\\fBTk_GetFontFromObj\\fR returns the token for an existing font, given\nthe window and description used to create the font.\n\\fBTk_GetFontFromObj\\fR does not actually create the font; the font\nmust already have been created with a previous call to\n\\fBTk_AllocFontFromObj\\fR or \\fBTk_GetFont\\fR.  The return\nvalue is cached in \\fIobjPtr\\fR, which speeds up\nfuture calls to \\fBTk_GetFontFromObj\\fR with the same \\fIobjPtr\\fR\nand \\fItkwin\\fR.\n.PP\n\\fBTk_AllocFontFromObj\\fR and \\fBTk_GetFont\\fR maintain\na database of all fonts they have allocated.  If\nthe same font is requested multiple times (e.g. by different\nwindows or for different purposes), then a single Tk_Font will be\nshared for all uses.  The underlying resources will be freed automatically\nwhen no-one is using the font anymore.\n.PP\nThe procedure \\fBTk_FontGetDescription\\fR returns information about the font\ndescription as a Tcl list. One possible result is\n.QW \"{{DejaVu Sans} -16 bold underline}\" .\n.PP\nThe procedure \\fBTk_NameOfFont\\fR is roughly the inverse of\n\\fBTk_GetFont\\fR.  Given a \\fItkfont\\fR that was created by\n\\fBTk_GetFont\\fR (or \\fBTk_AllocFontFromObj\\fR), the return value is\nthe \\fIstring\\fR argument that was\npassed to \\fBTk_GetFont\\fR to create the font.  The string returned by\n\\fBTk_NameOfFont\\fR is only guaranteed to persist until the \\fItkfont\\fR\nis deleted.  The caller must not modify this string.\n.PP\nWhen a font is no longer needed,\n\\fBTk_FreeFontFromObj\\fR or \\fBTk_FreeFont\\fR should be called to\nrelease it.  For \\fBTk_FreeFontFromObj\\fR the font to release is specified\nwith the same information used to create it; for\n\\fBTk_FreeFont\\fR the font to release is specified\nwith its Tk_Font token.  There should be\nexactly one call to \\fBTk_FreeFontFromObj\\fR or \\fBTk_FreeFont\\fR\nfor each call to \\fBTk_AllocFontFromObj\\fR or \\fBTk_GetFont\\fR.\n.SH \"SEE ALSO\"\nTk_FontId(3)\n.SH KEYWORDS\nfont\n"
  },
  {
    "path": "doc/GetGC.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetGC 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetGC, Tk_FreeGC \\- maintain database of read-only graphics contexts\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nGC\n\\fBTk_GetGC\\fR(\\fItkwin, valueMask, valuePtr\\fR)\n.sp\n\\fBTk_FreeGC\\fR(\\fIdisplay, gc\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"unsigned long\" valueMask\n.AP Tk_Window tkwin in\nToken for window in which the graphics context will be used.\n.AP \"unsigned long\" valueMask in\nMask of bits (such as \\fBGCForeground\\fR or \\fBGCStipple\\fR)\nindicating which fields of \\fI*valuePtr\\fR are valid.\n.AP XGCValues *valuePtr in\nPointer to structure describing the desired values for the\ngraphics context.\n.AP Display *display in\nDisplay for which \\fIgc\\fR was allocated.\n.AP GC gc in\nX identifier for graphics context that is no longer needed.\nMust have been allocated by \\fBTk_GetGC\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetGC\\fR and \\fBTk_FreeGC\\fR manage a collection of graphics contexts\nbeing used by an application.  The procedures allow graphics contexts to be\nshared, thereby avoiding the server overhead that would be incurred\nif a separate GC were created for each use.  \\fBTk_GetGC\\fR takes arguments\ndescribing the desired graphics context and returns an X identifier\nfor a GC that fits the description.  The graphics context that is returned\nwill have default values in all of the fields not specified explicitly\nby \\fIvalueMask\\fR and \\fIvaluePtr\\fR.\n.PP\n\\fBTk_GetGC\\fR maintains a\ndatabase of all the graphics contexts it has created.  Whenever possible,\na call to \\fBTk_GetGC\\fR will\nreturn an existing graphics context rather than creating a new one.  This\napproach can substantially reduce server overhead, so \\fBTk_GetGC\\fR\nshould generally be used in preference to the Xlib procedure\n\\fBXCreateGC\\fR, which creates a new graphics context on each call.\n.PP\nSince the return values of \\fBTk_GetGC\\fR\nare shared, callers should never modify the graphics contexts\nreturned by \\fBTk_GetGC\\fR.\nIf a graphics context must be modified dynamically, then it should be\ncreated by calling \\fBXCreateGC\\fR instead of \\fBTk_GetGC\\fR.\n.PP\nWhen a graphics context\nis no longer needed, \\fBTk_FreeGC\\fR should be called to release it.\nThere should be exactly one call to \\fBTk_FreeGC\\fR for\neach call to \\fBTk_GetGC\\fR.\nWhen a graphics context is no longer in use anywhere (i.e. it has\nbeen freed as many times as it has been gotten) \\fBTk_FreeGC\\fR\nwill release it to the X server and delete it from the database.\n.SH KEYWORDS\ngraphics context\n"
  },
  {
    "path": "doc/GetHINSTANCE.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH Tk_GetHISTANCE 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetHINSTANCE \\- retrieve the global application instance handle\n.SH SYNOPSIS\n.nf\n\\fB#include <tkPlatDecls.h>\\fR\n.sp\nHINSTANCE\n\\fBTk_GetHINSTANCE\\fR()\n.fi\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetHINSTANCE\\fR returns the Windows application instance handle\nfor the Tk application.  This function is only available on Windows platforms.\n.SH KEYWORDS\nidentifier, instance\n"
  },
  {
    "path": "doc/GetHWND.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH HWND 3 8.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetHWND, Tk_AttachHWND \\- manage interactions between the Windows handle and an X window\n.SH SYNOPSIS\n.nf\n\\fB#include <tkPlatDecls.h>\\fR\n.sp\nHWND\n\\fBTk_GetHWND\\fR(\\fIwindow\\fR)\n.sp\nWindow\n\\fBTk_AttachHWND\\fR(\\fItkwin, hwnd\\fR)\n.fi\n.SH ARGUMENTS\n.AP Window window in\nX token for window.\n.AP Tk_Window tkwin in\nTk window for window.\n.AP HWND hwnd in\nWindows HWND for window.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetHWND\\fR returns the Windows HWND identifier for X Windows\nwindow given by \\fIwindow\\fR.\n.PP\n\\fBTk_AttachHWND\\fR binds the Windows HWND identifier to the\nspecified Tk_Window given by \\fItkwin\\fR. It returns an X Windows\nwindow that encapsulates the HWND.\n.SH KEYWORDS\nidentifier, window\n"
  },
  {
    "path": "doc/GetImage.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetImage 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetImage, Tk_RedrawImage, Tk_SizeOfImage, Tk_FreeImage \\- use an image in a widget\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Image\n\\fBTk_GetImage\\fR(\\fIinterp, tkwin, name, changeProc, clientData\\fR)\n.sp\n\\fBTk_RedrawImage\\fR(\\fIimage, imageX, imageY, width, height, drawable, drawableX, drawableY\\fR)\n.sp\n\\fBTk_SizeOfImage\\fR(\\fIimage, widthPtr, heightPtr\\fR)\n.sp\n\\fBTk_FreeImage\\fR(\\fIimage\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ImageChangedProc *changeProc\n.AP Tcl_Interp *interp in\nPlace to leave error message.\n.AP Tk_Window tkwin in\nWindow in which image will be used.\n.AP \"const char\" *name in\nName of image.\n.AP Tk_ImageChangedProc *changeProc in\nProcedure for Tk to invoke whenever image content or size changes.\n.AP void *clientData in\nOne-word value for Tk to pass to \\fIchangeProc\\fR.\n.AP Tk_Image image in\nToken for image instance;  must have been returned by a previous\ncall to \\fBTk_GetImage\\fR.\n.AP int imageX in\nX-coordinate of upper-left corner of region of image to redisplay\n(measured in pixels from the image's upper-left corner).\n.AP int imageY in\nY-coordinate of upper-left corner of region of image to redisplay\n(measured in pixels from the image's upper-left corner).\n.AP \"int\" width (in)\nWidth of region of image to redisplay.\n.AP \"int\" height (in)\nHeight of region of image to redisplay.\n.AP Drawable drawable in\nWhere to display image.  Must either be window specified to\n\\fBTk_GetImage\\fR or a pixmap compatible with that window.\n.AP int drawableX in\nWhere to display image in \\fIdrawable\\fR: this is the x-coordinate\nin \\fIdrawable\\fR where x-coordinate \\fIimageX\\fR of the image\nshould be displayed.\n.AP int drawableY in\nWhere to display image in \\fIdrawable\\fR: this is the y-coordinate\nin \\fIdrawable\\fR where y-coordinate \\fIimageY\\fR of the image\nshould be displayed.\n.AP \"int\" widthPtr out\nStore width of \\fIimage\\fR (in pixels) here.\n.AP \"int\" heightPtr out\nStore height of \\fIimage\\fR (in pixels) here.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are invoked by widgets that wish to display images.\n\\fBTk_GetImage\\fR is invoked by a widget when it first decides to\ndisplay an image.\n\\fIname\\fR gives the name of the desired image and \\fItkwin\\fR\nidentifies the window where the image will be displayed.\n\\fBTk_GetImage\\fR looks up the image in the table of existing\nimages and returns a token for a new instance of the image.\nIf the image does not exist then \\fBTk_GetImage\\fR returns NULL\nand leaves an error message in interpreter \\fIinterp\\fR's result.\n.PP\nWhen a widget wishes to actually display an image it must\ncall \\fBTk_RedrawImage\\fR, identifying the image (\\fIimage\\fR),\na region within the image to redisplay (\\fIimageX\\fR, \\fIimageY\\fR,\n\\fIwidth\\fR, and \\fIheight\\fR), and a place to display the\nimage (\\fIdrawable\\fR, \\fIdrawableX\\fR, and \\fIdrawableY\\fR).\nTk will then invoke the appropriate image manager, which will\ndisplay the requested portion of the image before returning.\n.PP\nA widget can find out the dimensions of an image by calling\n\\fBTk_SizeOfImage\\fR:  the width and height will be stored\nin the locations given by \\fIwidthPtr\\fR and \\fIheightPtr\\fR,\nrespectively.\n.PP\nWhen a widget is finished with an image (e.g., the widget is\nbeing deleted or it is going to use a different image instead\nof the current one), it must call \\fBTk_FreeImage\\fR to\nrelease the image instance.\nThe widget should never again use the image token after passing\nit to \\fBTk_FreeImage\\fR.\nThere must be exactly one call to \\fBTk_FreeImage\\fR for each\ncall to \\fBTk_GetImage\\fR.\n.PP\nIf the contents or size of an image changes, then any widgets\nusing the image will need to find out about the changes so that\nthey can redisplay themselves.\nThe \\fIchangeProc\\fR and \\fIclientData\\fR arguments to\n\\fBTk_GetImage\\fR are used for this purpose.\n\\fIchangeProc\\fR will be called by Tk whenever a change occurs\nin the image;  it must match the following prototype:\n.CS\ntypedef void \\fBTk_ImageChangedProc\\fR(\n        void *\\fIclientData\\fR,\n        int \\fIx\\fR,\n        int \\fIy\\fR,\n        int \\fIwidth\\fR,\n        int \\fIheight\\fR,\n        int \\fIimageWidth\\fR,\n        int \\fIimageHeight\\fR);\n.CE\nThe \\fIclientData\\fR argument to \\fIchangeProc\\fR is the same as the\n\\fIclientData\\fR argument to \\fBTk_GetImage\\fR.\nIt is usually a pointer to the widget record for the widget or\nsome other data structure managed by the widget.\nThe arguments \\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and \\fIheight\\fR\nidentify a region within the image that must be redisplayed;\nthey are specified in pixels measured from the upper-left\ncorner of the image.\nThe arguments \\fIimageWidth\\fR and \\fIimageHeight\\fR give\nthe image's (new) size.\n.SH \"SEE ALSO\"\nTk_CreateImageType\n.SH KEYWORDS\nimages, redisplay\n"
  },
  {
    "path": "doc/GetJoinStl.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetJoinStyle 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetJoinStyle, Tk_NameOfJoinStyle \\- translate between strings and join styles\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetJoinStyle\\fR(\\fIinterp, string, joinPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfJoinStyle\\fR(\\fIjoin\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *joinPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP \"const char\" *string in\nString containing name of join style \\- one of\n.QW \\fBbevel\\fR ,\n.QW \\fBmiter\\fR ,\nor\n.QW \\fBround\\fR\n\\- or a unique abbreviation of one.\n.AP int *joinPtr out\nPointer to location in which to store X join style corresponding to\n\\fIstring\\fR.\n.AP int join in\nJoin style: one of \\fBJoinBevel\\fR, \\fBJoinMiter\\fR, \\fBJoinRound\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetJoinStyle\\fR places in \\fI*joinPtr\\fR the X join style\ncorresponding to \\fIstring\\fR, which will be one of\n\\fBJoinBevel\\fR, \\fBJoinMiter\\fR, or \\fBJoinRound\\fR.\nJoin styles are typically used in X graphics contexts to indicate\nhow adjacent line segments should be joined together.\nSee the X documentation for information on what each style\nimplies.\n.PP\nUnder normal circumstances the return value is \\fBTCL_OK\\fR and\n\\fIinterp\\fR is unused.\nIf \\fIstring\\fR does not contain a valid join style\nor an abbreviation of one of these names, then an error message is\nstored in interpreter \\fIinterp\\fR's result, \\fBTCL_ERROR\\fR is returned, and\n\\fI*joinPtr\\fR is unmodified.\n.PP\n\\fBTk_NameOfJoinStyle\\fR is the logical inverse of \\fBTk_GetJoinStyle\\fR.\nGiven a join style such as \\fBJoinBevel\\fR it returns a\nstatically-allocated string corresponding to \\fIjoin\\fR.\nIf \\fIjoin\\fR is not a legal join style, then\n.QW \"unknown join style\"\nis returned.\n.SH KEYWORDS\nbevel, join style, miter, round\n"
  },
  {
    "path": "doc/GetJustify.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetJustifyFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetJustifyFromObj, Tk_GetJustify, Tk_NameOfJustify \\- translate between strings and justification styles\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetJustifyFromObj\\fR(\\fIinterp, objPtr, justifyPtr\\fR)\n.sp\nint\n\\fBTk_GetJustify\\fR(\\fIinterp, string, justifyPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfJustify\\fR(\\fIjustify\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_Justify\" *justifyPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting, or NULL.\n.AP Tcl_Obj *objPtr in/out\nString value contains name of justification style \\- one of\n.QW \\fBleft\\fR ,\n.QW \\fBright\\fR ,\nor\n.QW \\fBcenter\\fR\n\\- or a unique abbreviation of one.\nThe internal rep will be modified to cache corresponding justify value.\n.AP \"const char\" *string in\nSame as \\fIobjPtr\\fR except description of justification style is passed as\na string.\n.AP int *justifyPtr out\nPointer to location in which to store justify value corresponding to\n\\fIobjPtr\\fR or \\fIstring\\fR.\n.AP Tk_Justify justify in\nJustification style (one of the values listed below).\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetJustifyFromObj\\fR places in \\fI*justifyPtr\\fR the justify value\ncorresponding to \\fIobjPtr\\fR's value.\nThis value will be one of the following:\n.IP \\fBTK_JUSTIFY_LEFT\\fR\nMeans that the text on each line should start at the left edge of\nthe line;  as a result, the right edges of lines may be ragged.\n.IP \\fBTK_JUSTIFY_RIGHT\\fR\nMeans that the text on each line should end at the right edge of\nthe line;  as a result, the left edges of lines may be ragged.\n.IP \\fBTK_JUSTIFY_CENTER\\fR\nMeans that the text on each line should be centered;  as a result,\nboth the left and right edges of lines may be ragged.\n.PP\nUnder normal circumstances the return value is \\fBTCL_OK\\fR and\n\\fIinterp\\fR is unused.\nIf \\fIobjPtr\\fR does not contain a valid justification style\nor an abbreviation of one of these names, \\fBTCL_ERROR\\fR is returned,\n\\fI*justifyPtr\\fR is unmodified, and an error message is\nstored in \\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\n\\fBTk_GetJustifyFromObj\\fR caches information about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to\n\\fBTk_GetJustifyFromObj\\fR with the same \\fIobjPtr\\fR.\n.PP\n\\fBTk_GetJustify\\fR is identical to \\fBTk_GetJustifyFromObj\\fR except\nthat the description of the justification is specified with a string instead\nof an object.  This prevents \\fBTk_GetJustify\\fR from caching the\nreturn value, so \\fBTk_GetJustify\\fR is less efficient than\n\\fBTk_GetJustifyFromObj\\fR.\n.PP\n\\fBTk_NameOfJustify\\fR is the logical inverse of \\fBTk_GetJustify\\fR.\nGiven a justify value it returns a statically-allocated string\ncorresponding to \\fIjustify\\fR.\nIf \\fIjustify\\fR is not a legal justify value, then\n.QW \"unknown justification style\"\nis returned.\n.SH KEYWORDS\ncenter, fill, justification, string\n"
  },
  {
    "path": "doc/GetOption.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetOption 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetOption \\- retrieve an option from the option database\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Uid\n\\fBTk_GetOption\\fR(\\fItkwin, name, class\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window *class\n.AP Tk_Window tkwin in\nToken for window.\n.AP \"const char\" *name in\nName of desired option.\n.AP \"const char\" *class in\nClass of desired option.  Null means there is no class for\nthis option;  do lookup based on name only.\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure is invoked to retrieve an option from the database\nassociated with \\fItkwin\\fR's main window.  If there is an option\nfor \\fItkwin\\fR that matches the given \\fIname\\fR or \\fIclass\\fR,\nthen it is returned in the form of a Tk_Uid.  If multiple options\nmatch \\fIname\\fR and \\fIclass\\fR, then the highest-priority one\nis returned.  If no option matches, then NULL is returned.\n.PP\n\\fBTk_GetOption\\fR caches options related to \\fItkwin\\fR so that\nsuccessive calls for the same \\fItkwin\\fR will execute much more\nquickly than successive calls for different windows.\n.SH KEYWORDS\nclass, name, option, retrieve\n"
  },
  {
    "path": "doc/GetPixels.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetPixelsFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetPixelsFromObj, Tk_GetPixels, Tk_GetMMFromObj, Tk_GetScreenMM, Tk_GetDoublePixelsFromObj \\- translate between strings and screen units\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetPixelsFromObj\\fR(\\fIinterp, tkwin, objPtr, intPtr\\fR)\n.sp\nint\n\\fBTk_GetDoublePixelsFromObj\\fR(\\fIinterp, tkwin, objPtr, doublePtr\\fR)\n.sp\nint\n\\fBTk_GetPixels\\fR(\\fIinterp, tkwin, string, intPtr\\fR)\n.sp\nint\n\\fBTk_GetMMFromObj\\fR(\\fIinterp, tkwin, objPtr, doublePtr\\fR)\n.sp\nint\n\\fBTk_GetScreenMM\\fR(\\fIinterp, tkwin, string, doublePtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *joinPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nWindow whose screen geometry determines the conversion between absolute\nunits and pixels.\n.AP Tcl_Obj *objPtr in/out\nString value specifies a distance on the screen;\ninternal rep will be modified to cache converted distance.\n.AP \"const char\" *string in\nSame as \\fIobjPtr\\fR except specification of distance is passed as\na string.\n.AP int *intPtr out\nPointer to location in which to store converted distance in pixels.\n.AP double *doublePtr out\nPointer to location in which to store converted distance in millimeters.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures take as argument a specification of distance on\nthe screen (\\fIobjPtr\\fR or \\fIstring\\fR) and compute the\ncorresponding distance either in integer pixels or floating-point millimeters.\nIn either case,\n\\fIobjPtr\\fR or \\fIstring\\fR\nspecifies a screen distance as a\nfloating-point number followed by one of the following characters\nthat indicates units:\n.IP <none>\nThe number specifies a distance in pixels.\n.IP \\fBc\\fR\nThe number specifies a distance in centimeters on the screen.\n.IP \\fBi\\fR\nThe number specifies a distance in inches on the screen.\n.IP \\fBm\\fR\nThe number specifies a distance in millimeters on the screen.\n.IP \\fBp\\fR\nThe number specifies a distance in printer's points (1/72 inch)\non the screen.\n.PP\n\\fBTk_GetPixelsFromObj\\fR converts the value of \\fIobjPtr\\fR to the\nnearest even number of pixels and stores that value at \\fI*intPtr\\fR.\nIt returns \\fBTCL_OK\\fR under normal circumstances.\nIf an error occurs (e.g. \\fIobjPtr\\fR contains a number followed\nby a character that is not one of the ones above) then\n\\fBTCL_ERROR\\fR is returned and an error message is left\nin \\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\n\\fBTk_GetPixelsFromObj\\fR caches information about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to\n\\fBTk_GetPixelsFromObj\\fR with the same \\fIobjPtr\\fR.\n.PP\n\\fBTk_GetDoublePixelsFromObj\\fR is identical to \\fBTk_GetPixelsFromObj\\fR\nexcept it returns a double not rounded to the nearest integer.\n.PP\n\\fBTk_GetPixels\\fR is identical to \\fBTk_GetPixelsFromObj\\fR except\nthat the screen distance is specified with a string instead\nof an object.  This prevents \\fBTk_GetPixels\\fR from caching the\nreturn value, so \\fBTk_GetPixels\\fR is less efficient than\n\\fBTk_GetPixelsFromObj\\fR.\n.PP\n\\fBTk_GetMMFromObj\\fR and \\fBTk_GetScreenMM\\fR are similar to\n\\fBTk_GetPixelsFromObj\\fR and \\fBTk_GetPixels\\fR (respectively) except\nthat they convert the screen distance to millimeters and\nstore a double-precision floating-point result at \\fI*doublePtr\\fR.\n.SH KEYWORDS\ncentimeters, convert, inches, millimeters, pixels, points, screen units\n"
  },
  {
    "path": "doc/GetPixmap.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetPixmap 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetPixmap, Tk_FreePixmap \\- allocate and free pixmaps\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nPixmap\n\\fBTk_GetPixmap\\fR(\\fIdisplay, d, width, height, depth\\fR)\n.sp\n\\fBTk_FreePixmap\\fR(\\fIdisplay, pixmap\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Drawable\" *pixelPtr\n.AP Display *display in\nX display for the pixmap.\n.AP Drawable d in\nPixmap or window where the new pixmap will be used for drawing.\n.AP \"int\" width in\nWidth of pixmap.\n.AP \"int\" height in\nHeight of pixmap.\n.AP \"int\" depth in\nNumber of bits per pixel in pixmap.\n.AP Pixmap pixmap in\nPixmap to destroy.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are identical to the Xlib procedures \\fBXCreatePixmap\\fR\nand \\fBXFreePixmap\\fR, except that they have extra code to manage X\nresource identifiers so that identifiers for deleted pixmaps can be\nreused in the future.\nIt is important for Tk applications to use these procedures rather\nthan \\fBXCreatePixmap\\fR and \\fBXFreePixmap\\fR;  otherwise long-running\napplications may run out of resource identifiers.\n.PP\n\\fBTk_GetPixmap\\fR creates a pixmap suitable for drawing in \\fId\\fR,\nwith dimensions given by \\fIwidth\\fR, \\fIheight\\fR, and \\fIdepth\\fR,\nand returns its identifier.\n\\fBTk_FreePixmap\\fR destroys the pixmap given by \\fIpixmap\\fR and makes\nits resource identifier available for reuse.\n.SH KEYWORDS\npixmap, resource identifier\n"
  },
  {
    "path": "doc/GetRelief.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetReliefFromObj 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetReliefFromObj, Tk_GetRelief, Tk_NameOfRelief \\- translate between strings and relief values\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetReliefFromObj\\fR(\\fIinterp, objPtr, reliefPtr\\fR)\n.sp\nint\n\\fBTk_GetRelief\\fR(\\fIinterp, name, reliefPtr\\fR)\n.sp\nconst char *\n\\fBTk_NameOfRelief\\fR(\\fIrelief\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *reliefPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tcl_Obj *objPtr in/out\nString value contains name of relief, one of\n.QW \\fBflat\\fR ,\n.QW \\fBgroove\\fR ,\n.QW \\fBraised\\fR ,\n.QW \\fBridge\\fR ,\n.QW \\fBsolid\\fR ,\nor\n.QW \\fBsunken\\fR\n(or any unique abbreviation thereof on input);\nthe internal rep will be modified to cache corresponding relief value.\n.AP \"const char\" *name in\nSame as \\fIobjPtr\\fR except description of relief is passed as\na string.\n.AP int *reliefPtr out\nPointer to location in which to store relief value corresponding to\n\\fIobjPtr\\fR or \\fIname\\fR.\n.AP int relief in\nRelief value (one of \\fBTK_RELIEF_FLAT\\fR, \\fBTK_RELIEF_RAISED\\fR,\n\\fBTK_RELIEF_SUNKEN\\fR, \\fBTK_RELIEF_GROOVE\\fR, \\fBTK_RELIEF_SOLID\\fR,\nor \\fBTK_RELIEF_RIDGE\\fR).\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetReliefFromObj\\fR places in \\fI*reliefPtr\\fR the relief value\ncorresponding to the value of \\fIobjPtr\\fR.  This value will be one of\n\\fBTK_RELIEF_FLAT\\fR, \\fBTK_RELIEF_RAISED\\fR, \\fBTK_RELIEF_SUNKEN\\fR,\n\\fBTK_RELIEF_GROOVE\\fR, \\fBTK_RELIEF_SOLID\\fR, or \\fBTK_RELIEF_RIDGE\\fR.\nUnder normal circumstances the return value is \\fBTCL_OK\\fR and\n\\fIinterp\\fR is unused.\nIf \\fIobjPtr\\fR does not contain one of the valid relief names\nor an abbreviation of one of them, then \\fBTCL_ERROR\\fR is returned,\n\\fI*reliefPtr\\fR is unmodified, and an error message\nis stored in \\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\n\\fBTk_GetReliefFromObj\\fR caches information about the return\nvalue in \\fIobjPtr\\fR, which speeds up future calls to\n\\fBTk_GetReliefFromObj\\fR with the same \\fIobjPtr\\fR.\n.PP\n\\fBTk_GetRelief\\fR is identical to \\fBTk_GetReliefFromObj\\fR except\nthat the description of the relief is specified with a string instead\nof an object.  This prevents \\fBTk_GetRelief\\fR from caching the\nreturn value, so \\fBTk_GetRelief\\fR is less efficient than\n\\fBTk_GetReliefFromObj\\fR.\n.PP\n\\fBTk_NameOfRelief\\fR is the logical inverse of \\fBTk_GetRelief\\fR.\nGiven a relief value it returns the corresponding string (\\fBflat\\fR,\n\\fBraised\\fR, \\fBsunken\\fR, \\fBgroove\\fR, \\fBsolid\\fR, or \\fBridge\\fR).\nIf \\fIrelief\\fR is not a legal relief value, then\n.QW \"unknown relief\"\nis returned.\n.SH KEYWORDS\nname, relief, string\n"
  },
  {
    "path": "doc/GetRootCrd.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetRootCoords 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetRootCoords \\- Compute root-window coordinates of window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_GetRootCoords\\fR(\\fItkwin, xPtr, yPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP Tk_Window tkwin in\nToken for window.\n.AP int *xPtr out\nPointer to location in which to store root-window x-coordinate\ncorresponding to left edge of \\fItkwin\\fR's border.\n.AP int *yPtr out\nPointer to location in which to store root-window y-coordinate\ncorresponding to top edge of \\fItkwin\\fR's border.\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure scans through the structural information maintained\nby Tk to compute the root-window coordinates corresponding to\nthe upper-left corner of \\fItkwin\\fR's border.  If \\fItkwin\\fR has\nno border, then \\fBTk_GetRootCoords\\fR returns the root-window\ncoordinates corresponding to location (0,0) in \\fItkwin\\fR.\n\\fBTk_GetRootCoords\\fR is relatively efficient, since it does not have to\ncommunicate with the X server.\n.SH KEYWORDS\ncoordinates, root window\n"
  },
  {
    "path": "doc/GetScroll.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetScrollInfo 3 8.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetScrollInfoObj, Tk_GetScrollInfo \\- parse arguments for scrolling commands\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetScrollInfoObj\\fR(\\fIinterp, objc, objv, fractionPtr, stepsPtr\\fR)\n.sp\nint\n\\fBTk_GetScrollInfo\\fR(\\fIinterp, argc, argv, fractionPtr, stepsPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *fractionPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tcl_Size objc in\nNumber of Tcl_Obj's in \\fIobjv\\fR array.\n.AP \"Tcl_Obj *const *\" objv in\nArgument objects.  These represent the entire widget command, of\nwhich the first word is typically the widget name and the second\nword is typically \\fBxview\\fR or \\fByview\\fR.\n.AP int argc in\nNumber of strings in \\fIargv\\fR array.\n.AP \"const char **\" argv in\nArgument strings.  These represent the entire widget command, of\nwhich the first word is typically the widget name and the second\nword is typically \\fBxview\\fR or \\fByview\\fR.\n.AP double *fractionPtr out\nFilled in with fraction from \\fBmoveto\\fR option, if any.\n.AP int *stepsPtr out\nFilled in with line or page count from \\fBscroll\\fR option, if any.\nThe value may be negative.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetScrollInfoObj\\fR parses the arguments expected by widget\nscrolling commands such as \\fBxview\\fR and \\fByview\\fR.\nIt receives the entire list of words that make up a widget command\nand parses the words starting with \\fIobjv\\fR[2].\nThe words starting with \\fIobjv\\fR[2] must have one of the following forms:\n.CS\n\\fBmoveto \\fIfraction\\fR\n\\fBscroll \\fInumber\\fB pages\\fR\n\\fBscroll \\fInumber\\fB units\\fR\n.CE\n.LP\nAny of the \\fBmoveto\\fR, \\fBscroll\\fR, \\fBpages\\fR, and \\fBunits\\fR\nkeywords may be abbreviated.\nIf \\fIobjv\\fR has the \\fBmoveto\\fR form, \\fBTK_SCROLL_MOVETO\\fR\nis returned as result and \\fI*fractionPtr\\fR is filled in with the\n\\fIfraction\\fR argument to the command, which must be a proper real\nvalue.\nIf \\fIobjv\\fR has the \\fBscroll\\fR form, \\fBTK_SCROLL_PAGES\\fR\nor \\fBTK_SCROLL_UNITS\\fR is returned and \\fI*stepsPtr\\fR is filled\nin with the \\fInumber\\fR value, which must be a  integer or a float,\nbut if it is a float then it is converted to an integer, rounded away from 0.\nIf an error occurs in parsing the arguments, \\fBTK_SCROLL_ERROR\\fR\nis returned and an error message is left in interpreter\n\\fIinterp\\fR's result.\n.PP\n\\fBTk_GetScrollInfo\\fR is identical in function to\n\\fBTk_GetScrollInfoObj\\fR.  However, \\fBTk_GetScrollInfo\\fR accepts\nstring arguments, making it more appropriate for use with legacy\nwidgets.\n.SH KEYWORDS\nparse, scrollbar, scrolling command, xview, yview\n"
  },
  {
    "path": "doc/GetSelect.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetSelection 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetSelection \\- retrieve the contents of a selection\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_GetSelection\\fR(\\fIinterp, tkwin, selection, target, proc, clientData\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_GetSelProc clientData\n.AP Tcl_Interp *interp in\nInterpreter to use for reporting errors.\n.AP Tk_Window tkwin in\nWindow on whose behalf to retrieve the selection (determines\ndisplay from which to retrieve).\n.AP Atom selection in\nThe name of the selection to be retrieved.\n.AP Atom target in\nForm in which to retrieve selection.\n.AP Tk_GetSelProc *proc in\nProcedure to invoke to process pieces of the selection as they\nare retrieved.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetSelection\\fR retrieves the selection specified by the atom\n\\fIselection\\fR in the format specified by \\fItarget\\fR.  The\nselection may actually be retrieved in several pieces; as each piece\nis retrieved, \\fIproc\\fR is called to process the piece.  \\fIProc\\fR\nshould have arguments and result that match the type\n\\fBTk_GetSelProc\\fR:\n.PP\n.CS\ntypedef int \\fBTk_GetSelProc\\fR(\n        void *\\fIclientData\\fR,\n        Tcl_Interp *\\fIinterp\\fR,\n        char *\\fIportion\\fR);\n.CE\n.PP\nThe \\fIclientData\\fR and \\fIinterp\\fR parameters to \\fIproc\\fR\nwill be copies of the corresponding arguments to\n\\fBTk_GetSelection\\fR.  \\fIPortion\\fR will be a pointer to\na string containing part or all of the selection.  For large\nselections, \\fIproc\\fR will be called several times with successive\nportions of the selection.  The X Inter-Client Communication\nConventions Manual allows a selection to be returned in formats\nother than strings, e.g. as an array of atoms or integers.  If\nthis happens, Tk converts the selection back into a string\nbefore calling \\fIproc\\fR.  If a selection is returned as an\narray of atoms, Tk converts it to a string containing the atom names\nseparated by white space.  For any other format besides string,\nTk converts a selection to a string containing hexadecimal\nvalues separated by white space.\n.PP\n\\fBTk_GetSelection\\fR returns to its caller when the selection has\nbeen completely retrieved and processed by \\fIproc\\fR, or when a\nfatal error has occurred (e.g. the selection owner did not respond\npromptly).  \\fBTk_GetSelection\\fR normally returns \\fBTCL_OK\\fR;  if\nan error occurs, it returns \\fBTCL_ERROR\\fR and leaves an error message\nin interpreter \\fIinterp\\fR's result.  \\fIProc\\fR should also return either\n\\fBTCL_OK\\fR or \\fBTCL_ERROR\\fR.  If \\fIproc\\fR encounters an error in\ndealing with the selection, it should leave an error message in the\ninterpreter result and return \\fBTCL_ERROR\\fR;  this will abort the\nselection retrieval.\n.SH KEYWORDS\nformat, get, selection retrieval\n"
  },
  {
    "path": "doc/GetUid.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetUid 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetUid, Tk_Uid \\- convert from string to unique identifier\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Uid\n\\fBTk_GetUid\\fR(\\fIstring\\fR)\n.fi\n.SH ARGUMENTS\n.AP char *string in\nString for which the corresponding unique identifier is\ndesired.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetUid\\fR returns the unique identifier corresponding\nto \\fIstring\\fR.\nUnique identifiers are similar to atoms in Lisp, and are used\nin Tk to speed up comparisons and\nsearches.  A unique identifier (type Tk_Uid) is a string pointer\nand may be used anywhere that a variable of type\n.QW \"char *\"\ncould be used.  However, there is guaranteed to be exactly\none unique identifier for any given string value.  If \\fBTk_GetUid\\fR\nis called twice, once with string \\fIa\\fR and once with string\n\\fIb\\fR, and if \\fIa\\fR and \\fIb\\fR have the same string value\n(strcmp(a, b) == 0), then \\fBTk_GetUid\\fR will return exactly\nthe same Tk_Uid value for each call (Tk_GetUid(a) == Tk_GetUid(b)).\nThis means that variables of type\nTk_Uid may be compared directly (x == y) without having to call\n\\fBstrcmp\\fR.\nIn addition, the return value from \\fBTk_GetUid\\fR will have the\nsame string value as its argument (strcmp(Tk_GetUid(a), a) == 0).\n.SH KEYWORDS\natom, unique identifier\n"
  },
  {
    "path": "doc/GetVRoot.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetVRootGeometry 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetVRootGeometry \\- Get location and size of virtual root for window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_GetVRootGeometry\\fR(\\fItkwin, xPtr, yPtr, widthPtr, heightPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window heightPtr\n.AP Tk_Window tkwin in\nToken for window whose virtual root is to be queried.\n.AP int xPtr out\nPoints to word in which to store x-offset of virtual root.\n.AP int yPtr out\nPoints to word in which to store y-offset of virtual root.\n.AP \"int\" widthPtr out\nPoints to word in which to store width of virtual root.\n.AP \"int\" heightPtr out\nPoints to word in which to store height of virtual root.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetVRootGeometry\\fR returns geometry information about the virtual\nroot window associated with \\fItkwin\\fR.  The\n.QW associated\nvirtual root is the one in which \\fItkwin\\fR's nearest top-level ancestor (or\n\\fItkwin\\fR itself if it is a top-level window) has\nbeen reparented by the window manager.  This window is identified by\na \\fB__SWM_ROOT\\fR or \\fB__WM_ROOT\\fR property placed on the top-level\nwindow by the window manager.\nIf \\fItkwin\\fR is not associated with a virtual root (e.g.\nbecause the window manager does not use virtual roots) then *\\fIxPtr\\fR and\n*\\fIyPtr\\fR will be set to 0 and *\\fIwidthPtr\\fR and *\\fIheightPtr\\fR\nwill be set to the dimensions of the screen containing \\fItkwin\\fR.\n.SH KEYWORDS\ngeometry, height, location, virtual root, width, window manager\n"
  },
  {
    "path": "doc/GetVisual.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_GetVisual 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetVisual \\- translate from string to visual\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nVisual *\n\\fBTk_GetVisual\\fR(\\fIinterp, tkwin, string, depthPtr, colormapPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tcl_Interp\" *colormapPtr\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting.\n.AP Tk_Window tkwin in\nToken for window in which the visual will be used.\n.AP \"const char\" *string in\nString that identifies the desired visual.  See below for\nvalid formats.\n.AP int *depthPtr out\nDepth of returned visual gets stored here.\n.AP Colormap *colormapPtr out\nIf non-NULL then a suitable colormap for visual is found and its\nidentifier is stored here.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetVisual\\fR takes a string description of a visual and\nfinds a suitable X Visual for use in \\fItkwin\\fR, if there is one.\nIt returns a pointer to the X Visual structure for the visual\nand stores the number of bits per pixel for it at \\fI*depthPtr\\fR.\nIf \\fIstring\\fR is unrecognizable or if no suitable visual could\nbe found, then NULL is returned and \\fBTk_GetVisual\\fR leaves\nan error message in interpreter \\fIinterp\\fR's result.\nIf \\fIcolormap\\fR is non-NULL then \\fBTk_GetVisual\\fR\nalso locates an appropriate colormap for use with the result visual\nand stores its X identifier at \\fI*colormapPtr\\fR.\n.PP\nThe \\fIstring\\fR argument specifies the desired visual in one\nof the following ways:\n.TP 15\n\\fIclass depth\\fR\n.\nThe string consists of a class name followed by an integer depth,\nwith any amount of white space (including none) in between.\n\\fIclass\\fR selects what sort of visual is desired and must be one of\n\\fBdirectcolor\\fR, \\fBgrayscale\\fR, \\fBgreyscale\\fR, \\fBpseudocolor\\fR,\n\\fBstaticcolor\\fR, \\fBstaticgray\\fR, \\fBstaticgrey\\fR, or\n\\fBtruecolor\\fR, or a unique abbreviation.\n\\fIdepth\\fR specifies how many bits per pixel are needed for the\nvisual.\nIf possible, \\fBTk_GetVisual\\fR will return a visual with this depth;\nif there is no visual of the desired depth then \\fBTk_GetVisual\\fR\nlooks first for a visual with greater depth, then one with less\ndepth.\n.TP 15\n\\fBdefault\\fR\n.\nUse the default visual for \\fItkwin\\fR's screen.\n.TP 15\n\\fIpathName\\fR\n.\nUse the visual for the window given by \\fIpathName\\fR.\n\\fIpathName\\fR must be the name of a window on the same screen\nas \\fItkwin\\fR.\n.TP 15\n\\fInumber\\fR\n.\nUse the visual whose X identifier is \\fInumber\\fR.\n.TP 15\n\\fBbest\\fR ?\\fIdepth\\fR?\n.\nChoose the\n.QW \"best possible\"\nvisual, using the following rules, in decreasing order of priority:\n.RS\n.IP (a)\na visual that has exactly the desired depth is best, followed\nby a visual with greater depth than requested (but as little extra\nas possible), followed by a visual with less depth than requested\n(but as great a depth as possible);\n.IP (b)\nif no \\fIdepth\\fR is specified, then the deepest available visual\nis chosen;\n.IP (c)\n\\fBpseudocolor\\fR is better than \\fBtruecolor\\fR or \\fBdirectcolor\\fR,\nwhich are better than \\fBstaticcolor\\fR, which is better than\n\\fBstaticgray\\fR or \\fBgrayscale\\fR;\n.IP (d)\nthe default visual for the screen is better than any other visual.\n.RE\n.SH CREDITS\n.PP\nThe idea for \\fBTk_GetVisual\\fR, and the first implementation, came\nfrom Paul Mackerras.\n.SH KEYWORDS\ncolormap, screen, visual\n"
  },
  {
    "path": "doc/Grab.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH Tk_Grab 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_Grab, Tk_Ungrab \\- manipulate grab state in an application\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_Grab\\fR(\\fIinterp, tkwin, grabGlobal\\fR)\n.sp\n\\fBTk_Ungrab\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AP Tcl_Interp *interp in\nInterpreter to use for error reporting\n.AP Tk_Window tkwin in\nWindow on whose behalf the pointer is to be grabbed or released\n.AP int grabGlobal in\nBoolean indicating whether the grab is global or application local\n.BE\n.SH DESCRIPTION\n.PP\nThese functions are used to set or release a global or\napplication local grab.  When a grab is set on a particular window\nin a Tk application, mouse and keyboard events can only be received by\nthat window and its descendants.  Mouse and keyboard events for\nwindows outside the tree rooted at \\fItkwin\\fR will be redirected to\n\\fItkwin\\fR.  If the grab is global, then all mouse and keyboard\nevents for windows outside the tree rooted at \\fItkwin\\fR (even those\nintended for windows in other applications) will be redirected to\n\\fItkwin\\fR.  If the grab is application local, only mouse and\nkeyboard events intended for a windows within the same application\n(but outside the tree rooted at \\fItkwin\\fR) will be redirected.\n.PP\n\\fBTk_Grab\\fR sets a grab on a particular window.  \\fITkwin\\fR\nspecifies the window on whose behalf the pointer is to be grabbed.\n\\fIGrabGlobal\\fR indicates whether the grab should be global or\napplication local; if it is non-zero, it means the grab should be\nglobal.  Normally, \\fBTk_Grab\\fR returns \\fBTCL_OK\\fR; if an error occurs\nand the grab cannot be set, \\fBTCL_ERROR\\fR is returned and an error message\nis left if \\fIinterp\\fR's result.  Once this call completes\nsuccessfully, no window outside the tree rooted at \\fItkwin\\fR will\nreceive pointer- or keyboard-related events until the next call to\nTk_Ungrab.  If a previous grab was in effect within the application,\nthen it is replaced with a new one.\n.PP\n\\fBTk_Ungrab\\fR releases a grab on the mouse pointer and keyboard, if\nthere is one set on the window given by \\fItkwin\\fR.  Once a grab is\nreleased, pointer and keyboard events will start being delivered to\nother windows again.\n.SH KEYWORDS\ngrab, window\n"
  },
  {
    "path": "doc/HWNDToWindow.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH Tk_HWNDToWindow 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_HWNDToWindow \\- Find Tk's window information for a Windows window\n.SH SYNOPSIS\n.nf\n\\fB#include <tkPlatDecls.h>\\fR\n.sp\nTk_Window\n\\fBTk_HWNDToWindow\\fR(\\fIhwnd\\fR)\n.fi\n.SH ARGUMENTS\n.AP HWND hwnd in\nWindows handle for the window.\n.BE\n.SH DESCRIPTION\n.PP\nGiven a Windows HWND window identifier, this procedure returns the\ncorresponding Tk_Window handle. If there is no Tk_Window corresponding\nto \\fIhwnd\\fR then NULL is returned.\n.SH KEYWORDS\nWindows window id\n"
  },
  {
    "path": "doc/HandleEvent.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_HandleEvent 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_HandleEvent \\- invoke event handlers for window system events\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_HandleEvent\\fR(\\fIeventPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS XEvent *eventPtr\n.AP XEvent *eventPtr in\nPointer to X event to dispatch to relevant handler(s). It is important\nthat all unused fields of the structure be set to zero.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_HandleEvent\\fR is a lower-level procedure that deals with window\nevents.  It is called by \\fBTcl_ServiceEvent\\fR (and indirectly by\n\\fBTcl_DoOneEvent\\fR), and in a few other cases within Tk.\nIt makes callbacks to any window event\nhandlers (created by calls to \\fBTk_CreateEventHandler\\fR)\nthat match \\fIeventPtr\\fR and then returns.  In some cases\nit may be useful for an application to bypass the Tk event\nqueue and call \\fBTk_HandleEvent\\fR directly instead of\ncalling \\fBTcl_QueueEvent\\fR followed by\n\\fBTcl_ServiceEvent\\fR.\n.PP\nThis procedure may be invoked recursively.  For example,\nit is possible to invoke \\fBTk_HandleEvent\\fR recursively\nfrom a handler called by \\fBTk_HandleEvent\\fR.  This sort\nof operation is useful in some modal situations, such\nas when a\nnotifier has been popped up and an application wishes to\nwait for the user to click a button in the notifier before\ndoing anything else.\n.SH KEYWORDS\ncallback, event, handler, window\n"
  },
  {
    "path": "doc/IdToWindow.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_IdToWindow 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_IdToWindow \\- Find Tk's window information for an X window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_IdToWindow\\fR(\\fIdisplay, window\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window display\n.AP Display *display in\nX display containing the window.\n.AP Window window in\nX id for window.\n.BE\n.SH DESCRIPTION\n.PP\nGiven an X window identifier and the X display it corresponds to,\nthis procedure returns the corresponding Tk_Window handle.\nIf there is no Tk_Window corresponding to \\fIwindow\\fR then\nNULL is returned.\n.SH KEYWORDS\nX window id\n"
  },
  {
    "path": "doc/ImgChanged.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ImageChanged 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ImageChanged \\- notify widgets that image needs to be redrawn\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_ImageChanged\\fR(\\fImodel, x, y, width, height, imageWidth, imageHeight\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ImageModel imageHeight\n.AP Tk_ImageModel model in\nToken for image, which was passed to image's \\fIcreateProc\\fR when\nthe image was created.\n.AP int x in\nX-coordinate of upper-left corner of region that needs redisplay (measured\nfrom upper-left corner of image).\n.AP int y in\nY-coordinate of upper-left corner of region that needs redisplay (measured\nfrom upper-left corner of image).\n.AP \"int\" width in\nWidth of region that needs to be redrawn, in pixels.\n.AP \"int\" height in\nHeight of region that needs to be redrawn, in pixels.\n.AP \"int\" imageWidth in\nCurrent width of image, in pixels.\n.AP \"int\" imageHeight in\nCurrent height of image, in pixels.\n.BE\n.SH DESCRIPTION\n.PP\nAn image manager calls \\fBTk_ImageChanged\\fR for an image\nwhenever anything happens that requires the image to be redrawn.\nAs a result of calling \\fBTk_ImageChanged\\fR, any widgets using\nthe image are notified so that they can redisplay themselves\nappropriately.\nThe \\fImodel\\fR argument identifies the image, and\n\\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and \\fIheight\\fR\nspecify a rectangular region within the image that needs to\nbe redrawn.\n\\fIimageWidth\\fR and \\fIimageHeight\\fR specify the image's (new) size.\n.PP\nAn image manager should call \\fBTk_ImageChanged\\fR during\nits \\fIcreateProc\\fR to specify the image's initial size and to\nforce redisplay if there are existing instances for the image.\nIf any of the pixel values in the image should change later on,\n\\fBTk_ImageChanged\\fR should be called again with \\fIx\\fR, \\fIy\\fR,\n\\fIwidth\\fR, and \\fIheight\\fR values that cover all the pixels\nthat changed.\nIf the size of the image should change, then \\fBTk_ImageChanged\\fR\nmust be called to indicate the new size, even if no pixels\nneed to be redisplayed.\n.SH \"SEE ALSO\"\nTk_CreateImageType\n.SH KEYWORDS\nimages, redisplay, image size changes\n"
  },
  {
    "path": "doc/Inactive.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH Tk_GetUserInactiveTime 3 8.5 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetUserInactiveTime, Tk_ResetUserInactiveTime \\- discover user inactivity time\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nlong\n\\fBTk_GetUserInactiveTime\\fR(\\fIdisplay\\fR)\n.sp\n\\fBTk_ResetUserInactiveTime\\fR(\\fIdisplay\\fR)\n.fi\n.SH ARGUMENTS\n.AS Display *display\n.AP Display *display in\nThe display on which the user inactivity timer is to be queried or\nreset.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_GetUserInactiveTime\\fR returns the number of milliseconds that\nhave passed since the last user interaction (usually via keyboard or\nmouse) with the respective display. On systems and displays that do not\nsupport querying the user inactivity time, \\fB\\-1\\fR is returned.\n\\fBTk_ResetUserInactiveTime\\fR resets the user inactivity timer of the\ngiven display to zero.  On windowing systems that do not support\nmultiple displays \\fIdisplay\\fR can be passed as \\fBNULL\\fR.\n.SH KEYWORDS\nidle, inactive\n"
  },
  {
    "path": "doc/InternAtom.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_InternAtom 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_InternAtom, Tk_GetAtomName \\- manage cache of X atoms\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nAtom\n\\fBTk_InternAtom\\fR(\\fItkwin, name\\fR)\n.sp\nconst char *\n\\fBTk_GetAtomName\\fR(\\fItkwin, atom\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window parent\n.AP Tk_Window tkwin in\nToken for window.  Used to map atom or name relative to a particular display.\n.AP \"const char\" *name in\nString name for which atom is desired.\n.AP Atom atom in\nAtom for which corresponding string name is desired.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures are similar to the Xlib procedures\n\\fBXInternAtom\\fR and \\fBXGetAtomName\\fR.  \\fBTk_InternAtom\\fR\nreturns the atom identifier associated with string given by\n\\fIname\\fR;  the atom identifier is only valid for the display\nassociated with \\fItkwin\\fR.\n\\fBTk_GetAtomName\\fR returns the string associated\nwith \\fIatom\\fR on \\fItkwin\\fR's display.  The string returned\nby \\fBTk_GetAtomName\\fR is in Tk's storage:  the caller need\nnot free this space when finished with the string, and the caller\nshould not modify the contents of the returned string.\nIf there is no atom \\fIatom\\fR on \\fItkwin\\fR's display,\nthen \\fBTk_GetAtomName\\fR returns the string\n.QW \"?bad atom?\" .\n.PP\nTk caches\nthe information returned by \\fBTk_InternAtom\\fR and \\fBTk_GetAtomName\\fR\nso that future calls\nfor the same information can be serviced from the cache without\ncontacting the server.  Thus \\fBTk_InternAtom\\fR and \\fBTk_GetAtomName\\fR\nare generally much faster than their Xlib counterparts, and they\nshould be used in place of the Xlib procedures.\n.SH KEYWORDS\natom, cache, display\n"
  },
  {
    "path": "doc/MainLoop.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MainLoop 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MainLoop \\- loop for events until all windows are deleted\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_MainLoop\\fR()\n.fi\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_MainLoop\\fR is a procedure that loops repeatedly calling\n\\fBTcl_DoOneEvent\\fR.  It returns only when there are no applications\nleft in this process (i.e. no main windows exist anymore).  Most\nwindowing applications will call \\fBTk_MainLoop\\fR after\ninitialization; the main execution of the application will consist\nentirely of callbacks invoked via \\fBTcl_DoOneEvent\\fR.\n.SH KEYWORDS\napplication, event, main loop\n"
  },
  {
    "path": "doc/MainWin.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MainWindow 3 7.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MainWindow, Tk_GetNumMainWindows \\- functions for querying main window information\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_MainWindow\\fR(\\fIinterp\\fR)\n.sp\n\\fBTk_SetMainMenubar\\fR(\\fIinterp, tkwin, menuName\\fR)\n.sp\n\\fBTk_SetWindowMenubar\\fR(\\fIinterp, tkwin, oldMenuName, menuName\\fR)\n.sp\nint\n\\fBTk_GetNumMainWindows\\fR()\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *pathName\n.AP Tcl_Interp *interp in/out\nInterpreter associated with the application.\n.AP Tk_Window tkwin in\nToken for main window.\n.AP const char *menuName in\nThe name of the new menubar that the toplevel needs to be set to.\nNULL means that their is no menu now.\n.AP const char *oldMenuName in\nThe name of the menubar previously set in this toplevel.\nNULL means no menu was set previously.\n.BE\n.SH DESCRIPTION\n.PP\nA main window is a special kind of toplevel window used as the\noutermost window in an application.\n.PP\nIf \\fIinterp\\fR is associated with a Tk application then \\fBTk_MainWindow\\fR\nreturns the application's main window. If there is no Tk application\nassociated with \\fIinterp\\fR then \\fBTk_MainWindow\\fR returns NULL and\nleaves an error message in interpreter \\fIinterp\\fR's result.\n.PP\n\\fBTk_GetNumMainWindows\\fR returns a count of the number of main\nwindows currently open in the current thread.\n\\fBTk_SetMainMenubar\\fR\nCalled when a toplevel widget is brought to front. On the Macintosh,\nsets up the menubar that goes across the top of the main monitor. On\nother platforms, nothing is necessary.\n\\fBTk_SetWindowMenubar\\fR associates a menu with a window.\nThe old menu clones for the menubar are thrown away, and a handler is\nset up to allocate the new ones.\n.SH KEYWORDS\napplication, main window\n"
  },
  {
    "path": "doc/MaintGeom.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MaintainGeometry 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MaintainGeometry, Tk_UnmaintainGeometry \\- maintain geometry of one window relative to another\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_MaintainGeometry\\fR(\\fIwindow, container, x, y, width, height\\fR)\n.sp\n\\fBTk_UnmaintainGeometry\\fR(\\fIwindow, container\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window container\n.AP Tk_Window window in\nWindow whose geometry is to be controlled.\n.AP Tk_Window container in\nWindow relative to which \\fIwindow\\fR's geometry will be controlled.\n.AP int x in\nDesired x-coordinate of \\fIwindow\\fR in \\fIcontainer\\fR, measured in pixels\nfrom the inside of \\fIcontainer\\fR's left border to the outside of\n\\fIwindow\\fR's left border.\n.AP int y in\nDesired y-coordinate of \\fIwindow\\fR in \\fIcontainer\\fR, measured in pixels\nfrom the inside of \\fIcontainer\\fR's top border to the outside of\n\\fIwindow\\fR's top border.\n.AP int width in\nDesired width for \\fIwindow\\fR, in pixels.\n.AP int height in\nDesired height for \\fIwindow\\fR, in pixels.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_MaintainGeometry\\fR and \\fBTk_UnmaintainGeometry\\fR make it\neasier for geometry managers to deal with windows whose containers are not\ntheir parents.\nThree problems arise if the container for a window is not its parent:\n.IP [1]\nThe x- and y-position of the window must be translated from the\ncoordinate system of the container to that of the parent before\npositioning the window.\n.IP [2]\nIf the container window, or any of its ancestors up to the window's\nparent, is moved, then the window must be repositioned within its\nparent in order to maintain the correct position relative to the\ncontainer.\n.IP [3]\nIf the container or one of its ancestors is mapped or unmapped, then\nthe window must be mapped or unmapped to correspond.\n.LP\nNone of these problems is an issue if the parent and container are\nthe same.  For example, if the container or one of its ancestors\nis unmapped, the window is automatically removed by the screen\nby X.\n.PP\n\\fBTk_MaintainGeometry\\fR deals with these problems for windows\nwhose containers are not their parents, as well as handling the simpler\ncase of windows whose container are their parents.\n\\fBTk_MaintainGeometry\\fR is typically called by a window manager\nonce it has decided where a window should be positioned relative\nto its container.\n\\fBTk_MaintainGeometry\\fR translates the coordinates to the\ncoordinate system of \\fIwindow\\fR's parent and then moves and\nresizes the window appropriately.\nFurthermore, it remembers the desired position and creates event\nhandlers to monitor the container and all of its ancestors up\nto (but not including) the window's parent.\nIf any of these windows is moved, mapped, or unmapped,\nthe window will be adjusted so that it is mapped only when the\ncontainer is mapped and its geometry relative to the container\nremains as specified by \\fIx\\fR, \\fIy\\fR, \\fIwidth\\fR, and\n\\fIheight\\fR.\n.PP\nWhen a window manager relinquishes control over a window, or\nif it decides that it does not want the window to appear on the\nscreen under any conditions, it calls \\fBTk_UnmaintainGeometry\\fR.\n\\fBTk_UnmaintainGeometry\\fR unmaps the window and cancels any\nprevious calls to \\fBTk_MaintainGeometry\\fR for the\n\\fIcontainer\\fR\\-\\fIwindow\\fR pair, so that the window's\ngeometry and mapped state are no longer maintained\nautomatically.\n\\fBTk_UnmaintainGeometry\\fR need not be called by a geometry\nmanager if the window, the container, or any of the container's ancestors\nis destroyed:  Tk will call it automatically.\n.PP\nIf \\fBTk_MaintainGeometry\\fR is called repeatedly for the same\n\\fIcontainer\\fR\\-\\fIwindow\\fR pair, the information from the most\nrecent call supersedes any older information.\nIf \\fBTk_UnmaintainGeometry\\fR is called for a \\fIcontainer\\fR\\-\\fIwindow\\fR\npair that is is not currently managed, the call has no effect.\n.SH KEYWORDS\ngeometry manager, map, container, parent, position, window, unmap\n"
  },
  {
    "path": "doc/ManageGeom.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ManageGeometry 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ManageGeometry \\- arrange to handle geometry requests for a window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_ManageGeometry\\fR(\\fItkwin, mgrPtr, clientData\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_GeometryProc clientData\n.AP Tk_Window tkwin in\nToken for window to be managed.\n.AP \"const Tk_GeomMgr\" *mgrPtr in\nPointer to data structure containing information about the\ngeometry manager, or NULL to indicate that \\fItkwin\\fR's geometry\nshould not be managed anymore.\nThe data structure pointed to by \\fImgrPtr\\fR must be static:\nTk keeps a reference to it as long as the window is managed.\n.AP void *clientData in\nArbitrary one-word value to pass to geometry manager callbacks.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_ManageGeometry\\fR arranges for a particular geometry manager,\ndescribed by the \\fImgrPtr\\fR argument, to control the geometry\nof a particular content window, given by \\fItkwin\\fR.\nIf \\fItkwin\\fR was previously managed by some other geometry manager,\nthe previous manager loses control in favor of the new one.\nIf \\fImgrPtr\\fR is NULL, geometry management is cancelled for\n\\fItkwin\\fR.\n.PP\nThe structure pointed to by \\fImgrPtr\\fR contains information about\nthe geometry manager:\n.CS\ntypedef struct {\n    const char *\\fIname\\fR;\n    Tk_GeomRequestProc *\\fIrequestProc\\fR;\n    Tk_GeomLostContentProc *\\fIlostContentProc\\fR;\n} \\fBTk_GeomMgr\\fR;\n.CE\nThe \\fIname\\fR field is the textual name for the geometry manager,\nsuch as \\fBpack\\fR or \\fBplace\\fR;  this value will be returned\nby the command \\fBwinfo manager\\fR.\n.PP\n\\fIrequestProc\\fR is a procedure in the geometry manager that\nwill be invoked whenever \\fBTk_GeometryRequest\\fR is called by the\ncontent window to change its desired geometry.\n\\fIrequestProc\\fR should have arguments and results that match the\ntype \\fBTk_GeomRequestProc\\fR:\n.CS\ntypedef void \\fBTk_GeomRequestProc\\fR(\n        void *\\fIclientData\\fR,\n        Tk_Window \\fItkwin\\fR);\n.CE\nThe parameters to \\fIrequestProc\\fR will be identical to the\ncorresponding parameters passed to \\fBTk_ManageGeometry\\fR.\n\\fIclientData\\fR usually points to a data\nstructure containing application-specific information about\nhow to manage \\fItkwin\\fR's geometry.\n.PP\nThe \\fIlostContentProc\\fR field of \\fImgrPtr\\fR points to another\nprocedure in the geometry manager.\nTk will invoke \\fIlostContentProc\\fR if some other manager\ncalls \\fBTk_ManageGeometry\\fR to claim\n\\fItkwin\\fR away from the current geometry manager.\n\\fIlostContentProc\\fR is not invoked if \\fBTk_ManageGeometry\\fR is\ncalled with a NULL value for \\fImgrPtr\\fR (presumably the current\ngeometry manager has made this call, so it already knows that the\nwindow is no longer managed), nor is it called if \\fImgrPtr\\fR\nis the same as the window's current geometry manager.\n\\fIlostContentProc\\fR should have\narguments and results that match the following prototype:\n.CS\ntypedef void \\fBTk_GeomLostContentProc\\fR(\n        void *\\fIclientData\\fR,\n        Tk_Window \\fItkwin\\fR);\n.CE\nThe parameters to \\fIlostContentProc\\fR will be identical to the\ncorresponding parameters passed to \\fBTk_ManageGeometry\\fR.\n.SH KEYWORDS\ncallback, geometry, managed, request, unmanaged\n"
  },
  {
    "path": "doc/MapWindow.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MapWindow 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MapWindow, Tk_UnmapWindow \\- map or unmap a window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_MapWindow\\fR(\\fItkwin\\fR)\n.sp\n\\fBTk_UnmapWindow\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window parent\n.AP Tk_Window tkwin in\nToken for window.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures may be used to map and unmap windows\nmanaged by Tk.  \\fBTk_MapWindow\\fR maps the window given\nby \\fItkwin\\fR, and also creates an X window corresponding\nto \\fItkwin\\fR if it does not already exist.  See the\n\\fBTk_CreateWindow\\fR manual entry for information on\ndeferred window creation.\n\\fBTk_UnmapWindow\\fR unmaps \\fItkwin\\fR's window\nfrom the screen.\n.PP\nIf \\fItkwin\\fR is a child window (i.e. \\fBTk_CreateWindow\\fR was\nused to create a child window), then event handlers interested in map\nand unmap events are invoked immediately.  If \\fItkwin\\fR is not an\ninternal window, then the event handlers will be invoked later, after\nX has seen the request and returned an event for it.\n.PP\nThese procedures should be used in place of the X procedures\n\\fBXMapWindow\\fR and \\fBXUnmapWindow\\fR, since they update\nTk's local data structure for \\fItkwin\\fR.  Applications\nusing Tk should not invoke \\fBXMapWindow\\fR and \\fBXUnmapWindow\\fR\ndirectly.\n.SH KEYWORDS\nmap, unmap, window\n"
  },
  {
    "path": "doc/MeasureChar.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MeasureChars 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MeasureChars, Tk_MeasureCharsInContext, Tk_TextWidth, Tk_DrawChars, Tk_DrawCharsInContext,\nTk_UnderlineChars, Tk_UnderlineCharsInContext \\- routines to measure and display simple single-line strings.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_MeasureChars\\fR(\\fItkfont, string, numBytes, maxPixels, flags, lengthPtr\\fR)\n.sp\nint\n\\fBTk_MeasureCharsInContext\\fR(\\fItkfont, string, numBytes, rangeStart, rangeLength, maxPixels, flags, lengthPtr\\fR)\n.sp\nint\n\\fBTk_TextWidth\\fR(\\fItkfont, string, numBytes\\fR)\n.sp\n\\fBTk_DrawChars\\fR(\\fIdisplay, drawable, gc, tkfont, string, numBytes, x, y\\fR)\n.sp\n\\fBTk_DrawCharsInContext\\fR(\\fIdisplay, drawable, gc, tkfont, string, numBytes, rangeStart, rangeLength, x, y\\fR)\n.sp\n\\fBTk_UnderlineChars\\fR(\\fIdisplay, drawable, gc, tkfont, string, x, y, firstByte, lastByte\\fR)\n.sp\n\\fBTk_UnderlineCharsInContext\\fR(\\fIdisplay, drawable, gc, tkfont, string, numBytes, x, y, firstByte, lastByte\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"const char\" firstChar\n.AP Tk_Font tkfont in\nToken for font in which text is to be drawn or measured.  Must have been\nreturned by a previous call to \\fBTk_GetFont\\fR.\n.AP \"const char\" *string in\nText to be measured or displayed.  Need not be null terminated.  Any\nnon-printing meta-characters in the string (such as tabs, newlines, and\nother control characters) will be measured or displayed in a\nplatform-dependent manner.\n.AP Tcl_Size numBytes in\nThe maximum number of bytes to consider when measuring or drawing\n\\fIstring\\fR.  Must be greater than or equal to 0.\n.AP int maxPixels in\nIf \\fImaxPixels\\fR is >= 0, it specifies the longest permissible\nline length in pixels.  Characters from \\fIstring\\fR are processed only\nuntil this many pixels have been covered.  If \\fImaxPixels\\fR is < 0, then\nthe line length is unbounded and the \\fIflags\\fR argument is ignored.\n.AP int flags in\nVarious flag bits OR-ed together: \\fBTK_PARTIAL_OK\\fR means include a character\nas long as any part of it fits in the length given by \\fImaxPixels\\fR;\notherwise, a character must fit completely to be considered.\n\\fBTK_WHOLE_WORDS\\fR means stop on a word boundary, if possible.  If\n\\fBTK_AT_LEAST_ONE\\fR is set, it means return at least one character even if no\ncharacters could fit in the length given by \\fImaxPixels\\fR.  If\n\\fBTK_AT_LEAST_ONE\\fR is set and \\fBTK_WHOLE_WORDS\\fR is also set, it means\nthat if not even one word fits on the line, return the first few letters of the\nword that did fit; if not even one letter of the word fit, then the first\nletter will still be returned.\n\\fBTK_ISOLATE_END\\fR means that the last character should not be considered in\ncontext with the rest of the string (used for breaking lines, with the\nTk_*InContext variants of the functions only).\n.AP int *lengthPtr out\nFilled with the number of pixels occupied by the number of characters\nreturned as the result of \\fBTk_MeasureChars\\fR.\n.AP Display *display in\nDisplay on which to draw.\n.AP Drawable drawable in\nWindow or pixmap in which to draw.\n.AP GC gc in\nGraphics context for drawing characters.  The font selected into this GC\nmust be the same as the \\fItkfont\\fR.\n.AP int \"x, y\" in\nCoordinates at which to place the left edge of the baseline when displaying\n\\fIstring\\fR.\n.AP int firstByte in\nThe index of the first byte of the first character to underline in the\n\\fIstring\\fR.  Underlining begins at the left edge of this character.\n.AP int lastByte in\nThe index of the first byte of the last character up to which the\nunderline will be drawn.  The character specified by \\fIlastByte\\fR\nwill not itself be underlined.\n.AP Tcl_Size rangeStart in\nIndex of first byte to draw or to measure.\n.AP Tcl_Size rangeLength in\nLength of range to draw or to measure, in bytes.\n.BE\n.SH DESCRIPTION\n.PP\nThese routines are for measuring and displaying simple single-font,\nsingle-line strings.  To measure and display single-font, multi-line,\njustified text, refer to the documentation for \\fBTk_ComputeTextLayout\\fR.\nThere is no programming interface in the core of Tk that supports\nmulti-font, multi-line text; support for that behavior must be built on\ntop of simpler layers.\nNote that the interfaces described here are\nbyte-oriented not character-oriented, so index values coming from Tcl\nscripts need to be converted to byte offsets using the\n\\fBTcl_UtfAtIndex\\fR and related routines.\n.PP\nA glyph is the displayable picture of a letter, number, or some other\nsymbol.  Not all character codes in a given font have a glyph.\nCharacters such as tabs, newlines/returns, and control characters that\nhave no glyph are measured and displayed by these procedures in a\nplatform-dependent manner; under X, they are replaced with backslashed\nescape sequences, while under Windows and Macintosh hollow or solid boxes\nmay be substituted.  Refer to the documentation for\n\\fBTk_ComputeTextLayout\\fR for a programming interface that supports the\nplatform-independent expansion of tab characters into columns and\nnewlines/returns into multi-line text.\n.PP\n\\fBTk_MeasureChars\\fR is used both to compute the length of a given\nstring and to compute how many characters from a string fit in a given\namount of space.  The return value is the number of bytes from\n\\fIstring\\fR that fit in the space specified by \\fImaxPixels\\fR subject to\nthe conditions described by \\fIflags\\fR.  If all characters fit, the return\nvalue will be \\fInumBytes\\fR.  \\fI*lengthPtr\\fR is filled with the computed\nwidth, in pixels, of the portion of the string that was measured.  For\nexample, if the return value is 5, then \\fI*lengthPtr\\fR is filled with the\ndistance between the left edge of \\fIstring\\fR[0] and the right edge of\n\\fIstring\\fR[4].\n.PP\n\\fBTk_TextWidth\\fR is a wrapper function that provides a simpler interface\nto the \\fBTk_MeasureChars\\fR function.  The return value is how much\nspace in pixels the given \\fIstring\\fR needs.\n.PP\n\\fBTk_DrawChars\\fR draws the \\fIstring\\fR at the given location in the\ngiven \\fIdrawable\\fR.\n.PP\n\\fBTk_UnderlineChars\\fR underlines the given range of characters in the\ngiven \\fIstring\\fR.  It does not draw the characters (which are assumed to\nhave been displayed previously by \\fBTk_DrawChars\\fR); it just draws the\nunderline.  This procedure is used to underline a few characters without\nhaving to construct an underlined font.  To produce natively underlined\ntext, the appropriate underlined font should be constructed and used.\n.PP\n\\fBTk_MeasureCharsInContext\\fR, \\fBTk_DrawCharsInContext\\fR,\n\\fBTk_UnderlineCharsInContext\\fR are variants of respectively\n\\fBTk_MeasureChars\\fR, \\fBTk_DrawChars\\fR and \\fBTk_UnderlineChars\\fR,\nbut with access to all the characters on the line for context. Except\non macOS, this context isn't actually consulted (meaning the out of\ncontext variants are called).\n.SH \"SEE ALSO\"\nfont(n), FontId(3)\n.SH KEYWORDS\nfont, measurement\n"
  },
  {
    "path": "doc/MoveToplev.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_MoveToplevelWindow 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_MoveToplevelWindow \\- Adjust the position of a top-level window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_MoveToplevelWindow\\fR(\\fItkwin, x, y\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP Tk_Window tkwin in\nToken for top-level window to move.\n.AP int x in\nNew x-coordinate for the top-left pixel of \\fItkwin\\fR's border, or the\ntop-left pixel of the decorative border supplied for \\fItkwin\\fR by the\nwindow manager, if there is one.\n.AP int y in\nNew y-coordinate for the top-left pixel of \\fItkwin\\fR's border, or the\ntop-left pixel of the decorative border supplied for \\fItkwin\\fR by the\nwindow manager, if there is one.\n.BE\n.SH DESCRIPTION\n.PP\nIn general, a window should never set its own position;  this should be\ndone only by the geometry manger that is responsible for the window.\nFor top-level windows the window manager is effectively the geometry\nmanager;  Tk provides interface code between the application and the\nwindow manager to convey the application's desires to the geometry\nmanager.  The desired size for a top-level window is conveyed using\nthe usual \\fBTk_GeometryRequest\\fR mechanism.  The procedure\n\\fBTk_MoveToplevelWindow\\fR may be used by an application to request\na particular position for a top-level window;  this procedure is\nsimilar in function to the \\fBwm geometry\\fR Tcl command except that\nnegative offsets cannot be specified.  It is invoked by widgets such as\nmenus that want to appear at a particular place on the screen.\n.PP\nWhen \\fBTk_MoveToplevelWindow\\fR is called it does not immediately\npass on the new desired location to the window manager;  it defers\nthis action until all other outstanding work has been completed,\nusing the \\fBTcl_DoWhenIdle\\fR mechanism.\n.SH KEYWORDS\nposition, top-level window, window manager\n"
  },
  {
    "path": "doc/Name.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_Name 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_Name, Tk_PathName, Tk_NameToWindow \\- convert between names and window tokens\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Uid\n\\fBTk_Name\\fR(\\fItkwin\\fR)\n.sp\nchar *\n\\fBTk_PathName\\fR(\\fItkwin\\fR)\n.sp\nTk_Window\n\\fBTk_NameToWindow\\fR(\\fIinterp, pathName, tkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *pathName\n.AP Tk_Window tkwin in\nToken for window.\n.AP Tcl_Interp *interp out\nInterpreter to use for error reporting (can be NULL).\n.AP \"const char\" *pathName in\nCharacter string containing path name of window.\n.BE\n.SH DESCRIPTION\n.PP\nEach window managed by Tk has two names, a short name that identifies\na window among children of the same parent, and a path name that\nidentifies the window uniquely among all the windows belonging to the\nsame main window.  The path name is used more often in Tk than the\nshort name;  many commands, like \\fBbind\\fR, expect path names as\narguments.\n.PP\nThe \\fBTk_Name\\fR macro returns a window's\nshort name, which is the same as the \\fIname\\fR argument\npassed to \\fBTk_CreateWindow\\fR when\nthe window was created.  The value is returned\nas a Tk_Uid, which may be used just like a string pointer but also has\nthe properties of a unique identifier (see the manual entry for\n\\fBTk_GetUid\\fR for details).\n.PP\nThe \\fBTk_PathName\\fR macro returns a hierarchical name for \\fItkwin\\fR.\nPath names have a structure similar to file names in Unix but with\ndots between elements instead of slashes:  the main window for\nan application has the path name\n.QW . ;\nits children have names like\n.QW .a\nand\n.QW .b ;\ntheir children have names like\n.QW .a.aa\nand\n.QW .b.bb ;\nand so on.  A window is considered to be a child of\nanother window for naming purposes if the second window was named\nas the first window's \\fIparent\\fR when the first window was created.\nThis is not always the same as the X window hierarchy.  For\nexample, a pop-up\nis created as a child of the root window, but its logical parent will\nusually be a window within the application.\n.PP\nThe procedure \\fBTk_NameToWindow\\fR returns the token for a window\ngiven its path name (the \\fIpathName\\fR argument) and another window\nbelonging to the same main window (\\fItkwin\\fR).  It normally\nreturns a token for the named window, but if no such window exists\n\\fBTk_NameToWindow\\fR leaves an error message in interpreter\n\\fIinterp\\fR's result\nand returns NULL.  The \\fItkwin\\fR argument to \\fBTk_NameToWindow\\fR\nis needed because path names are only unique within a single\napplication hierarchy.  If, for example, a single process has opened\ntwo main windows, each will have a separate naming hierarchy and the\nsame path name might appear in each of the hierarchies.  Normally\n\\fItkwin\\fR is the main window of the desired hierarchy, but this\nneed not be the case:  any window in the desired hierarchy may be used.\n.SH KEYWORDS\nname, path name, token, window\n"
  },
  {
    "path": "doc/NameOfImg.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_NameOfImage 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_NameOfImage \\- Return name of image.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nconst char *\n\\fBTk_NameOfImage\\fR(\\fIimageModel\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ImageModel imageModel\n.AP Tk_ImageModel imageModel in\nToken for image, which was passed to image manager's \\fIcreateProc\\fR when\nthe image was created.\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure is invoked by image managers to find out the name\nof an image.  Given the token for the image, it returns the\nstring name for the image.\n.SH KEYWORDS\nimage manager, image name\n"
  },
  {
    "path": "doc/OwnSelect.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_OwnSelection 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_OwnSelection \\- make a window the owner of the primary selection\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_OwnSelection\\fR(\\fItkwin, selection, proc, clientData\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_LostSelProc clientData\n.AP Tk_Window tkwin in\nWindow that is to become new selection owner.\n.AP Atom selection in\nThe name of the selection to be owned, such as XA_PRIMARY.\n.AP Tk_LostSelProc *proc in\nProcedure to invoke when \\fItkwin\\fR loses selection ownership later.\n.AP void *clientData in\nArbitrary one-word value to pass to \\fIproc\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_OwnSelection\\fR arranges for \\fItkwin\\fR to become the\nnew owner of the selection specified by the atom\n\\fIselection\\fR.  After this call completes, future requests\nfor the selection will be directed to handlers created for\n\\fItkwin\\fR using \\fBTk_CreateSelHandler\\fR.  When \\fItkwin\\fR\neventually loses the selection ownership, \\fIproc\\fR will be\ninvoked so that the window can clean itself up (e.g. by\nunhighlighting the selection).  \\fIProc\\fR should have arguments and\nresult that match the type \\fBTk_LostSelProc\\fR:\n.CS\ntypedef void \\fBTk_LostSelProc\\fR(\n        void *\\fIclientData\\fR);\n.CE\nThe \\fIclientData\\fR parameter to \\fIproc\\fR is a copy of the\n\\fIclientData\\fR argument given to \\fBTk_OwnSelection\\fR, and is\nusually a pointer to a data structure containing application-specific\ninformation about \\fItkwin\\fR.\n.SH KEYWORDS\nown, selection owner\n"
  },
  {
    "path": "doc/ParseArgv.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ParseArgv 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ParseArgv \\- process command-line options\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_ParseArgv\\fR(\\fIinterp, tkwin, argcPtr, argv, argTable, flags\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ArgvInfo *argTable\n.AP Tcl_Interp *interp in\nInterpreter to use for returning error messages.\n.AP Tk_Window tkwin in\nWindow to use when arguments specify Tk options.  If NULL, then\nno Tk options will be processed.\n.AP int argcPtr in/out\nPointer to number of arguments in argv;  gets modified to hold\nnumber of unprocessed arguments that remain after the call.\n.AP \"const char\" **argv in/out\nCommand line arguments passed to main program.  Modified to\nhold unprocessed arguments that remain after the call.\n.AP Tk_ArgvInfo *argTable in\nArray of argument descriptors, terminated by element with\ntype \\fBTK_ARGV_END\\fR.\n.AP int flags in\nIf non-zero, then it specifies one or more flags that control the\nparsing of arguments.  Different flags may be OR'ed together.\nThe flags currently defined are \\fBTK_ARGV_DONT_SKIP_FIRST_ARG\\fR,\n\\fBTK_ARGV_NO_ABBREV\\fR, \\fBTK_ARGV_NO_LEFTOVERS\\fR, and\n\\fBTK_ARGV_NO_DEFAULTS\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_ParseArgv\\fR processes an array of command-line arguments according\nto a table describing the kinds of arguments that are expected.\nEach of the arguments in \\fIargv\\fR is processed in turn:  if it matches\none of the entries in \\fIargTable\\fR, the argument is processed\naccording to that entry and discarded.  The arguments that do not\nmatch anything in \\fIargTable\\fR are copied down to the beginning\nof \\fIargv\\fR (retaining their original order) and returned to\nthe caller.  At the end of the call\n\\fBTk_ParseArgv\\fR sets \\fI*argcPtr\\fR to hold the number of\narguments that are left in \\fIargv\\fR, and \\fIargv[*argcPtr]\\fR\nwill hold the value NULL.  Normally, \\fBTk_ParseArgv\\fR\nassumes that \\fIargv[0]\\fR is a command name, so it is treated like\nan argument that does not match \\fIargTable\\fR and returned to the\ncaller;  however, if the \\fBTK_ARGV_DONT_SKIP_FIRST_ARG\\fR bit is set in\n\\fIflags\\fR then \\fIargv[0]\\fR will be processed just like the other\nelements of \\fIargv\\fR.\n.PP\n\\fBTk_ParseArgv\\fR normally returns the value \\fBTCL_OK\\fR.  If an error\noccurs while parsing the arguments, then \\fBTCL_ERROR\\fR is returned and\n\\fBTk_ParseArgv\\fR will leave an error message in the result of\ninterpreter \\fIinterp\\fR in the standard Tcl fashion.  In\nthe event of an error return, \\fI*argvPtr\\fR will not have been\nmodified, but \\fIargv\\fR could have been partially modified.  The\npossible causes of errors are explained below.\n.PP\nThe \\fIargTable\\fR array specifies the kinds of arguments that are\nexpected;  each of its entries has the following structure:\n.CS\ntypedef struct {\n    const char *\\fIkey\\fR;\n    int \\fItype\\fR;\n    void *\\fIsrc\\fR;\n    void *\\fIdst\\fR;\n    const char *\\fIhelp\\fR;\n} \\fBTk_ArgvInfo\\fR;\n.CE\nThe \\fIkey\\fR field is a string such as\n.QW \\-display\nor\n.QW \\-bg\nthat is compared with the values in \\fIargv\\fR.  \\fIType\\fR\nindicates how to process an argument that matches \\fIkey\\fR\n(more on this below).  \\fISrc\\fR and \\fIdst\\fR are additional\nvalues used in processing the argument.  Their exact usage\ndepends on \\fItype\\fR, but typically \\fIsrc\\fR indicates\na value and \\fIdst\\fR indicates where to store the\nvalue.  The \\fBchar *\\fR declarations for \\fIsrc\\fR and \\fIdst\\fR\nare placeholders:  the actual types may be different.  Lastly,\n\\fIhelp\\fR is a string giving a brief description\nof this option;  this string is printed when users ask for help\nabout command-line options.\n.PP\nWhen processing an argument in \\fIargv\\fR, \\fBTk_ParseArgv\\fR\ncompares the argument to each of the \\fIkey\\fR's in \\fIargTable\\fR.\n\\fBTk_ParseArgv\\fR selects the first specifier whose \\fIkey\\fR matches\nthe argument exactly, if such a specifier exists.  Otherwise\n\\fBTk_ParseArgv\\fR selects a specifier for which the argument\nis a unique abbreviation.  If the argument is a unique abbreviation\nfor more than one specifier, then an error is returned.  If there\nis no matching entry in \\fIargTable\\fR, then the argument is\nskipped and returned to the caller.\n.PP\nOnce a matching argument specifier is found, \\fBTk_ParseArgv\\fR\nprocesses the argument according to the \\fItype\\fR field of the\nspecifier.  The argument that matched \\fIkey\\fR is called\n.QW \"the matching argument\"\nin the descriptions below.  As part of the processing,\n\\fBTk_ParseArgv\\fR may also use the next argument in \\fIargv\\fR\nafter the matching argument, which is called\n.QW \"the following argument\" .\nThe legal values for \\fItype\\fR, and the processing\nthat they cause, are as follows:\n.IP \\fBTK_ARGV_END\\fR\nMarks the end of the table.  The last entry in \\fIargTable\\fR\nmust have this type;  all of its other fields are ignored and it\nwill never match any arguments.\n.IP \\fBTK_ARGV_CONSTANT\\fR\n\\fISrc\\fR is treated as an integer and \\fIdst\\fR is treated\nas a pointer to an integer.  \\fISrc\\fR is stored at \\fI*dst\\fR.\nThe matching argument is discarded.\n.IP \\fBTK_ARGV_INT\\fR\nThe following argument must contain an\ninteger string in the format accepted by \\fBstrtol\\fR (e.g.\n.QW 0\nand\n.QW 0x\nprefixes may be used to specify octal or hexadecimal\nnumbers, respectively).  \\fIDst\\fR is treated as a pointer to an\ninteger;  the following argument is converted to an integer value\nand stored at \\fI*dst\\fR.  \\fISrc\\fR is ignored.  The matching\nand following arguments are discarded from \\fIargv\\fR.\n.IP \\fBTK_ARGV_FLOAT\\fR\nThe following argument must contain a floating-point number in\nthe format accepted by \\fBstrtol\\fR.\n\\fIDst\\fR is treated as the address of a double-precision\nfloating point value;  the following argument is converted to a\ndouble-precision value and stored at \\fI*dst\\fR.  The matching\nand following arguments are discarded from \\fIargv\\fR.\n.IP \\fBTK_ARGV_STRING\\fR\nIn this form, \\fIdst\\fR is treated as a pointer to a (char *);\n\\fBTk_ParseArgv\\fR stores at \\fI*dst\\fR a pointer to the following\nargument, and discards the matching and following arguments from\n\\fIargv\\fR.  \\fISrc\\fR is ignored.\n.IP \\fBTK_ARGV_UID\\fR\nThis form is similar to \\fBTK_ARGV_STRING\\fR, except that the argument\nis turned into a Tk_Uid by calling \\fBTk_GetUid\\fR.\n\\fIDst\\fR is treated as a pointer to a\nTk_Uid; \\fBTk_ParseArgv\\fR stores at \\fI*dst\\fR the Tk_Uid\ncorresponding to the following\nargument, and discards the matching and following arguments from\n\\fIargv\\fR.  \\fISrc\\fR is ignored.\n.IP \\fBTK_ARGV_CONST_OPTION\\fR\nThis form causes a Tk option to be set (as if the \\fBoption\\fR\ncommand had been invoked).  The \\fIsrc\\fR field is treated as a\npointer to a string giving the value of an option, and \\fIdst\\fR\nis treated as a pointer to the name of the option.  The matching\nargument is discarded.  If \\fItkwin\\fR is NULL, then argument\nspecifiers of this type are ignored (as if they did not exist).\n.IP \\fBTK_ARGV_OPTION_VALUE\\fR\nThis form is similar to \\fBTK_ARGV_CONST_OPTION\\fR, except that the\nvalue of the option is taken from the following argument instead\nof from \\fIsrc\\fR.  \\fIDst\\fR is used as the name of the option.\n\\fISrc\\fR is ignored.  The matching and following arguments\nare discarded.  If \\fItkwin\\fR is NULL, then argument\nspecifiers of this type are ignored (as if they did not exist).\n.IP \\fBTK_ARGV_OPTION_NAME_VALUE\\fR\nIn this case the following argument is taken as the name of a Tk\noption and the argument after that is taken as the value for that\noption.  Both \\fIsrc\\fR and \\fIdst\\fR are ignored.  All three\narguments are discarded from \\fIargv\\fR.  If \\fItkwin\\fR is NULL,\nthen argument\nspecifiers of this type are ignored (as if they did not exist).\n.IP \\fBTK_ARGV_HELP\\fR\nWhen this kind of option is encountered, \\fBTk_ParseArgv\\fR uses the\n\\fIhelp\\fR fields of \\fIargTable\\fR to format a message describing\nall the valid arguments.  The message is placed in interpreter\n\\fIinterp\\fR's result\nand \\fBTk_ParseArgv\\fR returns \\fBTCL_ERROR\\fR.  When this happens, the\ncaller normally prints the help message and aborts.  If the \\fIkey\\fR\nfield of a \\fBTK_ARGV_HELP\\fR specifier is NULL, then the specifier will\nnever match any arguments;  in this case the specifier simply provides\nextra documentation, which will be included when some other\n\\fBTK_ARGV_HELP\\fR entry causes help information to be returned.\n.IP \\fBTK_ARGV_REST\\fR\nThis option is used by programs or commands that allow the last\nseveral of their options to be the name and/or options for some\nother program.  If a \\fBTK_ARGV_REST\\fR argument is found, then\n\\fBTk_ParseArgv\\fR does not process any\nof the remaining arguments;  it returns them all at\nthe beginning of \\fIargv\\fR (along with any other unprocessed arguments).\nIn addition, \\fBTk_ParseArgv\\fR treats \\fIdst\\fR as the address of an\ninteger value, and stores at \\fI*dst\\fR the index of the first of the\n\\fBTK_ARGV_REST\\fR options in the returned \\fIargv\\fR.  This allows the\nprogram to distinguish the \\fBTK_ARGV_REST\\fR options from other\nunprocessed options that preceded the \\fBTK_ARGV_REST\\fR.\n.IP \\fBTK_ARGV_FUNC\\fR\nFor this kind of argument, \\fIsrc\\fR is treated as the address of\na procedure, which is invoked to process the following argument.\nThe procedure should have the following structure:\n.RS\n.CS\nint\n\\fIfunc\\fR(\\fIdst\\fR, \\fIkey\\fR, \\fInextArg\\fR)\n    char *\\fIdst\\fR;\n    char *\\fIkey\\fR;\n    char *\\fInextArg\\fR;\n{\n}\n.CE\nThe \\fIdst\\fR and \\fIkey\\fR parameters will contain the\ncorresponding fields from the \\fIargTable\\fR entry, and\n\\fInextArg\\fR will point to the following argument from \\fIargv\\fR\n(or NULL if there are not any more arguments left in \\fIargv\\fR).\nIf \\fIfunc\\fR uses \\fInextArg\\fR (so that\n\\fBTk_ParseArgv\\fR should discard it), then it should return 1.  Otherwise it\nshould return 0 and \\fBTkParseArgv\\fR will process the following\nargument in the normal fashion.  In either event the matching argument\nis discarded.\n.RE\n.IP \\fBTK_ARGV_GENFUNC\\fR\nThis form provides a more general procedural escape.  It treats\n\\fIsrc\\fR as the address of a procedure, and passes that procedure\nall of the remaining arguments.  The procedure should have the following\nform:\n.RS\n.CS\nint\n\\fIgenfunc\\fR(dst, interp, key, argc, argv)\n    char *\\fIdst\\fR;\n    Tcl_Interp *\\fIinterp\\fR;\n    char *\\fIkey\\fR;\n    int \\fIargc\\fR;\n    char **\\fIargv\\fR;\n{\n}\n.CE\nThe \\fIdst\\fR and \\fIkey\\fR parameters will contain the\ncorresponding fields from the \\fIargTable\\fR entry.  \\fIInterp\\fR\nwill be the same as the \\fIinterp\\fR argument to \\fBTcl_ParseArgv\\fR.\n\\fIArgc\\fR and \\fIargv\\fR refer to all of the options after the\nmatching one.  \\fIGenfunc\\fR should behave in a fashion similar\nto \\fBTk_ParseArgv\\fR:  parse as many of the remaining arguments as it can,\nthen return any that are left by compacting them to the beginning of\n\\fIargv\\fR (starting at \\fIargv\\fR[0]).  \\fIGenfunc\\fR\nshould return a count of how many arguments are left in \\fIargv\\fR;\n\\fBTk_ParseArgv\\fR will process them.  If \\fIgenfunc\\fR encounters\nan error then it should leave an error message in interpreter\n\\fIinterp\\fR's result,\nin the usual Tcl fashion, and return \\-1;  when this happens\n\\fBTk_ParseArgv\\fR will abort its processing and return \\fBTCL_ERROR\\fR.\n.RE\n.SS \"FLAGS\"\n.IP \\fBTK_ARGV_DONT_SKIP_FIRST_ARG\\fR\n\\fBTk_ParseArgv\\fR normally treats \\fIargv[0]\\fR as a program\nor command name, and returns it to the caller just as if it\nhad not matched \\fIargTable\\fR.  If this flag is given, then\n\\fIargv[0]\\fR is not given special treatment.\n.IP \\fBTK_ARGV_NO_ABBREV\\fR\nNormally, \\fBTk_ParseArgv\\fR accepts unique abbreviations for\n\\fIkey\\fR values in \\fIargTable\\fR.  If this flag is given then\nonly exact matches will be acceptable.\n.IP \\fBTK_ARGV_NO_LEFTOVERS\\fR\nNormally, \\fBTk_ParseArgv\\fR returns unrecognized arguments to the\ncaller.  If this bit is set in \\fIflags\\fR then \\fBTk_ParseArgv\\fR\nwill return an error if it encounters any argument that does not\nmatch \\fIargTable\\fR.  The only exception to this rule is \\fIargv[0]\\fR,\nwhich will be returned to the caller with no errors as\nlong as \\fBTK_ARGV_DONT_SKIP_FIRST_ARG\\fR is not specified.\n.IP \\fBTK_ARGV_NO_DEFAULTS\\fR\nNormally, \\fBTk_ParseArgv\\fR searches an internal table of\nstandard argument specifiers in addition to \\fIargTable\\fR.  If\nthis bit is set in \\fIflags\\fR, then \\fBTk_ParseArgv\\fR will\nuse only \\fIargTable\\fR and not its default table.\n.SH EXAMPLE\n.PP\nHere is an example definition of an \\fIargTable\\fR and\nsome sample command lines that use the options.  Note the effect\non \\fIargc\\fR and \\fIargv\\fR;  arguments processed by \\fBTk_ParseArgv\\fR\nare eliminated from \\fIargv\\fR, and \\fIargc\\fR\nis updated to reflect reduced number of arguments.\n.CS\n/*\n * Define and set default values for globals.\n */\nint debugFlag = 0;\nint numReps = 100;\nconst char defaultFileName[] = \"out\";\nconst char *fileName = defaultFileName;\nBoolean exec = FALSE;\n\n/*\n * Define option descriptions.\n */\nstatic Tk_ArgvInfo argTable[] = {\n    {\"-X\", TK_ARGV_CONSTANT, (char *) 1, &debugFlag,\n        \"Turn on debugging printfs\"},\n    {\"-N\", TK_ARGV_INT, NULL, &numReps,\n        \"Number of repetitions\"},\n    {\"-of\", TK_ARGV_STRING, NULL, &fileName,\n        \"Name of file for output\"},\n    {\"x\", TK_ARGV_REST, NULL, &exec,\n        \"File to exec, followed by any arguments (must be last argument).\"},\n    {NULL, TK_ARGV_END, NULL, NULL,\n        NULL}\n};\n\nint main(int argc, char *argv[])\n{\n    \\&...\n\n    if (Tk_ParseArgv(interp, tkwin, &argc, argv, argTable, 0) != TCL_OK) {\n        fprintf(stderr, \"%s\\en\", Tcl_GetString(Tcl_GetObjResult(interp)));\n        exit(1);\n    }\n\n    /*\n     * Remainder of the program.\n     */\n}\n.CE\n.PP\nNote that default values can be assigned to variables named in\n\\fIargTable\\fR:  the variables will only be overwritten if the\nparticular arguments are present in \\fIargv\\fR.\nHere are some example command lines and their effects.\n.CS\nprog -N 200 infile        # just sets the numReps variable to 200\nprog -of out200 infile    # sets fileName to reference \"out200\"\nprog -XN 10 infile        # sets the debug flag, also sets numReps\n.CE\nIn all of the above examples, \\fIargc\\fR will be set by \\fBTk_ParseArgv\\fR to 2,\n\\fIargv\\fR[0] will be\n.QW prog ,\n\\fIargv\\fR[1] will be\n.QW infile ,\nand \\fIargv\\fR[2] will be NULL.\n.SH KEYWORDS\narguments, command line, options\n"
  },
  {
    "path": "doc/QWinEvent.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_QueueWindowEvent 3 7.5 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CollapseMotionEvents, Tk_QueueWindowEvent \\- Add a window event to the Tcl event queue\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_CollapseMotionEvents\\fR(\\fIdisplay, collapse\\fR)\n.sp\n\\fBTk_QueueWindowEvent\\fR(\\fIeventPtr, position\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_QueuePosition position\n.AP Display *display  in\nDisplay for which to control motion event collapsing.\n.AP int collapse in\nIndicates whether motion events should be collapsed or not.\n.AP XEvent *eventPtr  in\nAn event to add to the event queue. It is important\nthat all unused fields of the structure be set to zero.\n.AP Tcl_QueuePosition position in\nWhere to add the new event in the queue:  \\fBTCL_QUEUE_TAIL\\fR,\n\\fBTCL_QUEUE_HEAD\\fR, or \\fBTCL_QUEUE_MARK\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_QueueWindowEvent\\fR places a window event on Tcl's internal event\nqueue for eventual servicing.  It creates a Tcl_Event structure, copies the\nevent into that structure, and calls \\fBTcl_QueueEvent\\fR to add the event\nto the queue.  When the event is eventually removed from the queue it is\nprocessed just like all window events.\n.PP\nWhen multiple motion events are received for the same window in rapid\nsuccession, they are collapsed by default.  This behavior can be controlled\nwith \\fBTk_CollapseMotionEvents\\fR.  \\fBTk_CollapseMotionEvents\\fR always\nreturns the previous value for collapse behavior on the \\fIdisplay\\fR.\n.PP\nThe \\fIposition\\fR argument to \\fBTk_QueueWindowEvent\\fR has\nthe same significance as for \\fBTcl_QueueEvent\\fR;  see the\ndocumentation for \\fBTcl_QueueEvent\\fR for details.\n.SH KEYWORDS\ncallback, clock, handler, modal timeout, events\n"
  },
  {
    "path": "doc/Restack.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_RestackWindow 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_RestackWindow \\- Change a window's position in the stacking order\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_RestackWindow\\fR(\\fItkwin, aboveBelow, other\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window aboveBelow\n.AP Tk_Window tkwin in\nToken for window to restack.\n.AP int aboveBelow in\nIndicates new position of \\fItkwin\\fR relative to \\fIother\\fR;\nmust be \\fBAbove\\fR or \\fBBelow\\fR.\n.AP Tk_Window other in\n\\fITkwin\\fR will be repositioned just above or below this window.\nMust be a sibling of \\fItkwin\\fR or a descendant of a sibling.\nIf NULL then \\fItkwin\\fR is restacked above or below all siblings.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_RestackWindow\\fR changes the stacking order of \\fIwindow\\fR relative\nto its siblings.\nIf \\fIother\\fR is specified as NULL then \\fIwindow\\fR is repositioned\nat the top or bottom of its stacking order, depending on whether\n\\fIaboveBelow\\fR is \\fBAbove\\fR or \\fBBelow\\fR.\nIf \\fIother\\fR has a non-NULL value then \\fIwindow\\fR is repositioned\njust above or below \\fIother\\fR.\n.PP\nThe \\fIaboveBelow\\fR argument must have one of the symbolic values\n\\fBAbove\\fR or \\fBBelow\\fR.\nBoth of these values are defined by the include file <X11/Xlib.h>.\n.SH KEYWORDS\nabove, below, obscure, stacking order\n"
  },
  {
    "path": "doc/RestrictEv.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_RestrictEvents 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_RestrictEvents \\- filter and selectively delay X events\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_RestrictProc *\n\\fBTk_RestrictEvents\\fR(\\fIproc, arg, prevArgPtr\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_RestrictProc **prevArgPtr\n.AP Tk_RestrictProc *proc in\nPredicate procedure to call to filter incoming X events.\nNULL means do not restrict events at all.\n.AP void *arg in\nArbitrary argument to pass to \\fIproc\\fR.\n.AP void **prevArgPtr out\nPointer to place to save argument to previous restrict procedure.\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure is useful in certain situations where applications\nare only prepared to receive certain X events.  After\n\\fBTk_RestrictEvents\\fR is called, \\fBTcl_DoOneEvent\\fR (and\nhence \\fBTk_MainLoop\\fR) will filter X input events through\n\\fIproc\\fR.  \\fIProc\\fR indicates whether a\ngiven event is to be processed immediately, deferred until some\nlater time (e.g. when the event restriction is lifted), or discarded.\n\\fIProc\\fR\nis a procedure with arguments and result that match\nthe type \\fBTk_RestrictProc\\fR:\n.CS\ntypedef Tk_RestrictAction \\fBTk_RestrictProc\\fR(\n        void *\\fIarg\\fR,\n        XEvent *\\fIeventPtr\\fR);\n.CE\nThe \\fIarg\\fR argument is a copy of the \\fIarg\\fR passed\nto \\fBTk_RestrictEvents\\fR; it may be used to provide \\fIproc\\fR with\ninformation it needs to filter events.  The \\fIeventPtr\\fR points to\nan event under consideration.  \\fIProc\\fR returns a restrict action\n(enumerated type \\fBTk_RestrictAction\\fR) that indicates what\n\\fBTcl_DoOneEvent\\fR should do with the event.  If the return value is\n\\fBTK_PROCESS_EVENT\\fR, then the event will be handled immediately.\nIf the return value is \\fBTK_DEFER_EVENT\\fR, then the event will be\nleft on the event queue for later processing.  If the return value is\n\\fBTK_DISCARD_EVENT\\fR, then the event will be removed from the event\nqueue and discarded without being processed.\n.PP\n\\fBTk_RestrictEvents\\fR uses its return value and \\fIprevArgPtr\\fR\nto return information about the current event restriction procedure\n(a NULL return value means there are currently no restrictions).\nThese values may be used to restore the previous restriction state\nwhen there is no longer any need for the current restriction.\n.PP\nThere are very few places where \\fBTk_RestrictEvents\\fR is needed.\nIn most cases, the best way to restrict events is by changing the\nbindings with the \\fBbind\\fR Tcl command or by calling\n\\fBTk_CreateEventHandler\\fR and \\fBTk_DeleteEventHandler\\fR from C.\nThe main place where \\fBTk_RestrictEvents\\fR must be used is when\nperforming synchronous actions (for example, if you need to wait\nfor a particular event to occur on a particular window but you do not\nwant to invoke any handlers for any other events).  The\n.QW obvious\nsolution in these situations is to call \\fBXNextEvent\\fR or\n\\fBXWindowEvent\\fR, but these procedures cannot be used because\nTk keeps its own event queue that is separate from the X event\nqueue.  Instead, call \\fBTk_RestrictEvents\\fR to set up a filter,\nthen call \\fBTcl_DoOneEvent\\fR to retrieve the desired event(s).\n.SH KEYWORDS\ndelay, event, filter, restriction\n"
  },
  {
    "path": "doc/SetAppName.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetAppName 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetAppName \\- Set the name of an application for 'send' commands\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nconst char *\n\\fBTk_SetAppName\\fR(\\fItkwin, name\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window parent\n.AP Tk_Window tkwin in\nToken for window in application.  Used only to select a particular\napplication.\n.AP \"const char\" *name in\nName under which to register the application.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_SetAppName\\fR associates a name with a given application and\nrecords that association on the display containing with the application's\nmain window.\nAfter this procedure has been invoked, other applications on the\ndisplay will be able to use the \\fBsend\\fR command to invoke operations\nin the application.\nIf \\fIname\\fR is already in use by some other application on the\ndisplay, then a new name will be generated by appending\n.QW \"\\fB #2\\fR\"\nto \\fIname\\fR;  if this name is also in use,\nthe number will be incremented until an unused name is found.\nThe return value from the procedure is a pointer to the name actually\nused.\n.PP\nIf the application already has a name when \\fBTk_SetAppName\\fR is\ncalled, then the new name replaces the old name.\n.PP\n\\fBTk_SetAppName\\fR also adds a \\fBsend\\fR command to the application's\ninterpreter, which can be used to send commands from this application\nto others on any of the displays where the application has windows.\n.PP\nThe application's name registration persists until the interpreter is\ndeleted or the \\fBsend\\fR command is deleted from \\fIinterp\\fR, at which\npoint the name is automatically unregistered and the application\nbecomes inaccessible via \\fBsend\\fR.\nThe application can be made accessible again by calling \\fBTk_SetAppName\\fR.\n.PP\n\\fBTk_SetAppName\\fR is called automatically by \\fBTk_Init\\fR,\nso applications do not normally need to call it explicitly.\n.PP\nThe command \\fBtk appname\\fR provides Tcl-level access to the\nfunctionality of \\fBTk_SetAppName\\fR.\n.SH KEYWORDS\napplication, name, register, send command\n"
  },
  {
    "path": "doc/SetCaret.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2002 ActiveState Corporation.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetCaretPos 3 8.4 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetCaretPos \\- set the display caret location\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_SetCaretPos\\fR(\\fItkwin, x, y, height\\fR)\n.fi\n.SH ARGUMENTS\n.AP Tk_Window tkwin in\nToken for window.\n.AP int x in\nWindow-relative x coordinate.\n.AP int y in\nWindow-relative y coordinate.\n.AP int h in\nHeight of the caret in the window.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_SetCaretPos\\fR sets the caret location for the display of the\nspecified Tk_Window \\fItkwin\\fR.  The caret is the per-display cursor\nlocation used for indicating global focus (e.g. to comply with Microsoft\nAccessibility guidelines), as well as for location of the over-the-spot XIM\n(X Input Methods) or Windows IME windows.\n.SH KEYWORDS\ncaret, cursor\n"
  },
  {
    "path": "doc/SetClass.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetClass 3 \"\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetClass, Tk_Class \\- set or retrieve a window's class\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_SetClass\\fR(\\fItkwin, class\\fR)\n.sp\nTk_Uid\n\\fBTk_Class\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window parent\n.AP Tk_Window tkwin in\nToken for window.\n.AP char *class in\nNew class name for window.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_SetClass\\fR is called to associate a class with a particular\nwindow.  The \\fIclass\\fR string identifies the type of the\nwindow;  all windows with the same general class of behavior\n(button, menu, etc.) should have the same class.  By\nconvention all class names start with a capital letter, and\nthere exists a Tcl command with the same name as\neach class (except all in lower-case) which can be used to\ncreate and manipulate windows of that class.\nA window's class string is initialized to NULL\nwhen the window is created.\n.PP\nFor main windows, Tk automatically propagates the name and class\nto the WM_CLASS property used by window managers.  This happens\neither when a main window is actually created (e.g. in\n\\fBTk_MakeWindowExist\\fR), or when \\fBTk_SetClass\\fR\nis called, whichever occurs later.  If a main window has not been\nassigned a class then Tk will not set the WM_CLASS property for\nthe window.\n.PP\n\\fBTk_Class\\fR is a macro that returns the\ncurrent value of \\fItkwin\\fR's class.  The value is returned\nas a Tk_Uid, which may be used just like a string pointer but also has\nthe properties of a unique identifier (see the manual entry for\n\\fBTk_GetUid\\fR for details).\nIf \\fItkwin\\fR has not yet been given a class, then\n\\fBTk_Class\\fR will return NULL.\n.SH KEYWORDS\nclass, unique identifier, window, window manager\n"
  },
  {
    "path": "doc/SetClassProcs.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2000 Ajuba Solutions.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetClassProcs 3 8.4 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetClassProcs \\- register widget specific procedures\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_SetClassProcs\\fR(\\fItkwin, procs, instanceData\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_ClassProc instanceData\n.AP Tk_Window tkwin in\nToken for window to modify.\n.AP \"const Tk_ClassProcs\" *procs in\nPointer to data structure containing widget specific procedures.\nThe data structure pointed to by \\fIprocs\\fR must be static:\nTk keeps a reference to it as long as the window exists.\n.AP void *instanceData in\nArbitrary one-word value to pass to widget callbacks.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_SetClassProcs\\fR is called to register a set of procedures that\nare used as callbacks in different places.\n.PP\nThe structure pointed to by \\fIprocs\\fR contains the following:\n.CS\ntypedef struct {\n    Tcl_Size \\fIsize\\fR;\n    Tk_ClassWorldChangedProc *\\fIworldChangedProc\\fR;\n    Tk_ClassCreateProc *\\fIcreateProc\\fR;\n    Tk_ClassModalProc *\\fImodalProc\\fR;\n} \\fBTk_ClassProcs\\fR;\n.CE\nThe \\fIsize\\fR field is used to simplify future expansion of the\nstructure. It should always be set to (literally) \\fBsizeof(Tk_ClassProcs)\\fR.\n.PP\n\\fIworldChangedProc\\fR is invoked when the system has altered\nin some way that requires some reaction from the widget.  For example,\nwhen a font alias (see the \\fBfont\\fR manual entry) is reconfigured,\nwidgets configured to use that font alias must update their display\naccordingly.  \\fIworldChangedProc\\fR should have arguments and results\nthat match the type \\fBTk_ClassWorldChangedProc\\fR:\n.CS\ntypedef void \\fBTk_ClassWorldChangedProc\\fR(\n        void *\\fIinstanceData\\fR);\n.CE\nThe \\fIinstanceData\\fR parameter passed to the \\fIworldChangedProc\\fR\nwill be identical to the \\fIinstanceData\\fR parameter passed to\n\\fBTk_SetClassProcs\\fR.\n.PP\n\\fIcreateProc\\fR is used to create platform-dependent windows.  It is\ninvoked by \\fBTk_MakeWindowExist\\fR.  \\fIcreateProc\\fR should have\narguments and results that match the type \\fBTk_ClassCreateProc\\fR:\n.CS\ntypedef Window \\fBTk_ClassCreateProc\\fR(\n        Tk_Window \\fItkwin\\fR,\n        Window \\fIparent\\fR,\n        void *\\fIinstanceData\\fR);\n.CE\nThe \\fItkwin\\fR and \\fIinstanceData\\fR parameters will be identical to\nthe \\fItkwin\\fR and \\fIinstanceData\\fR parameters passed to\n\\fBTk_SetClassProcs\\fR.  The \\fIparent\\fR parameter will be the parent\nof the window to be created.  The \\fIcreateProc\\fR should return the\ncreated window.\n.PP\n\\fImodalProc\\fR is invoked after all bindings on a widget have been\ntriggered in order to handle a modal loop.  \\fImodalProc\\fR should\nhave arguments and results that match the type \\fBTk_ClassModalProc\\fR:\n.CS\ntypedef void \\fBTk_ClassModalProc\\fR(\n        Tk_Window \\fItkwin\\fR,\n        XEvent *\\fIeventPtr\\fR);\n.CE\nThe \\fItkwin\\fR parameter to \\fImodalProc\\fR will be identical to the\n\\fItkwin\\fR parameter passed to \\fBTk_SetClassProcs\\fR.  The\n\\fIeventPtr\\fR parameter will be a pointer to an XEvent structure\ndescribing the event being processed.\n.SH KEYWORDS\ncallback, class\n"
  },
  {
    "path": "doc/SetGrid.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetGrid 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetGrid, Tk_UnsetGrid \\- control the grid for interactive resizing\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_SetGrid\\fR(\\fItkwin, reqWidth, reqHeight, widthInc, heightInc\\fR)\n.sp\n\\fBTk_UnsetGrid\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window heightInc\n.AP Tk_Window tkwin in\nToken for window.\n.AP int reqWidth in\nWidth in grid units that corresponds to the pixel dimension \\fItkwin\\fR\nhas requested via \\fBTk_GeometryRequest\\fR.\n.AP int reqHeight in\nHeight in grid units that corresponds to the pixel dimension \\fItkwin\\fR\nhas requested via \\fBTk_GeometryRequest\\fR.\n.AP int widthInc in\nWidth of one grid unit, in pixels.\n.AP int heightInc in\nHeight of one grid unit, in pixels.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_SetGrid\\fR turns on gridded geometry management for \\fItkwin\\fR's\ntoplevel window and specifies the geometry of the grid.\n\\fBTk_SetGrid\\fR is typically invoked by a widget when its \\fBsetGrid\\fR\noption is true.\nIt restricts interactive resizing of \\fItkwin\\fR's toplevel window so\nthat the space allocated to the toplevel is equal to its requested\nsize plus or minus even multiples of \\fIwidthInc\\fR and \\fIheightInc\\fR.\nFurthermore, the \\fIreqWidth\\fR and \\fIreqHeight\\fR values are\npassed to the window manager so that it can report the window's\nsize in grid units during interactive resizes.\nIf \\fItkwin\\fR's configuration changes (e.g., the size of a grid unit\nchanges) then the widget should invoke \\fBTk_SetGrid\\fR again with the new\ninformation.\n.PP\n\\fBTk_UnsetGrid\\fR cancels gridded geometry management for\n\\fItkwin\\fR's toplevel window.\n.PP\nFor each toplevel window there can be at most one internal window\nwith gridding enabled.\nIf \\fBTk_SetGrid\\fR or \\fBTk_UnsetGrid\\fR is invoked when some\nother window is already controlling gridding for \\fItkwin\\fR's\ntoplevel, the calls for the new window have no effect.\n.PP\nSee the \\fBwm\\fR manual entry for additional information on gridded geometry\nmanagement.\n.SH KEYWORDS\ngrid, window, window manager\n"
  },
  {
    "path": "doc/SetOptions.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1998 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetOptions 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue,  Tk_GetOptionInfo, Tk_FreeConfigOptions \\- process configuration options\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_OptionTable\n\\fBTk_CreateOptionTable\\fR(\\fIinterp, templatePtr\\fR)\n.sp\n\\fBTk_DeleteOptionTable\\fR(\\fIoptionTable\\fR)\n.sp\nint\n\\fBTk_InitOptions\\fR(\\fIinterp, recordPtr, optionTable, tkwin\\fR)\n.sp\nint\n\\fBTk_SetOptions\\fR(\\fIinterp, recordPtr, optionTable, objc, objv, tkwin, savePtr, maskPtr\\fR)\n.sp\n\\fBTk_FreeSavedOptions\\fR(\\fIsavedPtr\\fR)\n.sp\n\\fBTk_RestoreSavedOptions\\fR(\\fIsavedPtr\\fR)\n.sp\nTcl_Obj *\n\\fBTk_GetOptionValue\\fR(\\fIinterp, recordPtr, optionTable, namePtr, tkwin\\fR)\n.sp\nTcl_Obj *\n\\fBTk_GetOptionInfo\\fR(\\fIinterp, recordPtr, optionTable, namePtr, tkwin\\fR)\n.sp\n\\fBTk_FreeConfigOptions\\fR(\\fIrecordPtr, optionTable, tkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_SavedOptions \"*const *objv\" in/out\n.AP Tcl_Interp *interp in\nA Tcl interpreter.  Most procedures use this only for returning error\nmessages; if it is NULL then no error messages are returned.  For\n\\fBTk_CreateOptionTable\\fR the value cannot be NULL; it gives the\ninterpreter in which the option table will be used.\n.AP \"const Tk_OptionSpec\" *templatePtr in\nPoints to an array of static information that describes the configuration\noptions that are supported.  Used to build a Tk_OptionTable.  The information\npointed to by this argument must exist for the lifetime of the Tk_OptionTable.\n.AP Tk_OptionTable optionTable in\nToken for an option table.  Must have been returned by a previous call\nto \\fBTk_CreateOptionTable\\fR.\n.AP void *recordPtr in/out\nPoints to structure in which values of configuration options are stored;\nfields of this record are modified by procedures such as \\fBTk_SetOptions\\fR\nand read by procedures such as \\fBTk_GetOptionValue\\fR.\n.AP Tk_Window tkwin in\nFor options such as \\fBTK_OPTION_COLOR\\fR, this argument indicates\nthe window in which the option will be used.  If \\fIoptionTable\\fR uses\nno window-dependent options, then a NULL value may be supplied for\nthis argument.\n.AP Tcl_Size objc in\nNumber of values in \\fIobjv\\fR.\n.AP Tcl_Obj \"*const *objv\" in\nCommand-line arguments for setting configuring options.\n.AP Tk_SavedOptions *savePtr out\nIf not NULL, the structure pointed to by this argument is filled\nin with the old values of any options that were modified and old\nvalues are restored automatically if an error occurs in \\fBTk_SetOptions\\fR.\n.AP int *maskPtr out\nIf not NULL, the word pointed to by \\fImaskPtr\\fR is filled in with the\nbit-wise OR of the \\fItypeMask\\fR fields for the options that\nwere modified.\n.AP Tk_SavedOptions *savedPtr in/out\nPoints to a structure previously filled in by \\fBTk_SetOptions\\fR with\nold values of modified options.\n.AP Tcl_Obj *namePtr in\nThe value of this object is the name of a particular option.  If NULL\nis passed to \\fBTk_GetOptionInfo\\fR then information is returned for\nall options.  Must not be NULL when \\fBTk_GetOptionValue\\fR is called.\n.AP \"type name\" type in\nThe name of the type of a record.\n.AP \"field name\" field in\nThe name of a field in records of type \\fItype\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese procedures handle most of the details of parsing configuration\noptions such as those for Tk widgets.  Given a description of what\noptions are supported, these procedures handle all the details of\nparsing options and storing their values into a C structure associated\nwith the widget or object. The procedures were designed primarily for\nwidgets in Tk, but they can also be used for other kinds of objects that\nhave configuration options.  In the rest of this manual page\n.QW widget\nwill be used to refer to the object whose options are being managed; in\npractice the object may not actually be a widget.  The term\n.QW \"widget record\"\nis used to refer to the C-level structure in\nwhich information about a particular widget or object is stored.\n.PP\nNote that the easiest way to learn how to use these procedures is to\nlook at a working example.  In Tk, the simplest example is the code\nthat implements the button family of widgets, which is in \\fBtkButton.c\\fR.\nOther examples are in \\fBtkSquare.c\\fR and \\fBtkMenu.c\\fR.\n.PP\nIn order to use these procedures, the code that implements the widget\nmust contain a static array of Tk_OptionSpec structures. This is a\ntemplate that describes the various options supported by that class of\nwidget; there is a separate template for each kind of widget.  The\ntemplate contains information such as the name of each option, its type,\nits default value, and where the value of the option is stored in the\nwidget record.  See TEMPLATES below for more detail.\n.PP\nIn order to process configuration options efficiently, the static\ntemplate must be augmented with additional information that is available\nonly at runtime.  The procedure \\fBTk_CreateOptionTable\\fR creates this\ndynamic information from the template and returns a Tk_OptionTable token\nthat describes both the static and dynamic information.  All of the\nother procedures, such as \\fBTk_SetOptions\\fR, take a Tk_OptionTable\ntoken as argument.  Typically, \\fBTk_CreateOptionTable\\fR is called the\nfirst time that a widget of a particular class is created and the\nresulting Tk_OptionTable is used in the future for all widgets of that\nclass.  A Tk_OptionTable may be used only in a single interpreter, given\nby the \\fIinterp\\fR argument to \\fBTk_CreateOptionTable\\fR.  When an\noption table is no longer needed \\fBTk_DeleteOptionTable\\fR should be\ncalled to free all of its resources.  All of the option tables\nfor a Tcl interpreter are freed automatically if the interpreter is deleted.\n.PP\n\\fBTk_InitOptions\\fR is invoked when a new widget is created to set the\ndefault values.\n\\fBTk_InitOptions\\fR is passed a token for an option table\n(\\fIoptionTable\\fR) and a pointer to a widget record (\\fIrecordPtr\\fR),\nwhich is the C structure that holds information about this widget.\n\\fBTk_InitOptions\\fR uses the information in the option table to choose an\nappropriate default for each option, then it stores the default value\ndirectly into the widget record, overwriting any information that was\nalready present in the widget record.  \\fBTk_InitOptions\\fR normally\nreturns \\fBTCL_OK\\fR.  If an error occurred while setting the default\nvalues (e.g., because a default value was erroneous) then \\fBTCL_ERROR\\fR\nis returned and an error message is left in \\fIinterp\\fR's result if\n\\fIinterp\\fR is not NULL. For any widget's configuration option that\nhas \\fBTK_OPTION_DONT_SET_DEFAULT\\fR set in its \\fIflags\\fR field,\nthe above initialization is fully skipped, see below.\n.PP\n\\fBTk_SetOptions\\fR is invoked to modify configuration options based\non information specified in a Tcl command.  The command might be one that\ncreates a new widget, or a command that modifies options on an existing\nwidget.  The \\fIobjc\\fR and \\fIobjv\\fR arguments describe the\nvalues of the arguments from the Tcl command.  \\fIObjv\\fR must contain\nan even number of objects: the first object of each pair gives the name of\nan option and the second object gives the new value for that option.\n\\fBTk_SetOptions\\fR looks up each name in \\fIoptionTable\\fR, checks that\nthe new value of the option conforms to the type in \\fIoptionTable\\fR,\nand stores the value of the option into the widget record given by\n\\fIrecordPtr\\fR.  \\fBTk_SetOptions\\fR normally returns \\fBTCL_OK\\fR.  If\nan error occurred (such as an unknown option name or an illegal option\nvalue) then \\fBTCL_ERROR\\fR is returned and an error message is left in\n\\fIinterp\\fR's result if \\fIinterp\\fR is not NULL.\n.PP\n\\fBTk_SetOptions\\fR has two additional features.  First, if the\n\\fImaskPtr\\fR argument is not NULL then it points to an integer\nvalue that is filled in with information about the options that were\nmodified.  For each option in the template passed to\n\\fBTk_CreateOptionTable\\fR there is a \\fItypeMask\\fR field.  The\nbits of this field are defined by the code that implements the widget;\nfor example, each bit might correspond to a particular configuration option.\nAlternatively, bits might be used functionally.  For example, one bit might\nbe used for redisplay: all options that affect the widget's display, such\nthat changing the option requires the widget to be redisplayed, might have\nthat bit set.  Another bit might indicate that the geometry of the widget\nmust be recomputed, and so on.  \\fBTk_SetOptions\\fR OR's together the\n\\fItypeMask\\fR fields from all the options that were modified and returns\nthis value at *\\fImaskPtr\\fR; the caller can then use this information\nto optimize itself so that, for example, it does not redisplay the widget\nif the modified options do not affect the widget's appearance.\n.PP\nThe second additional feature of \\fBTk_SetOptions\\fR has to do with error\nrecovery.  If an error occurs while processing configuration options, this\nfeature makes it possible to restore all the configuration options to their\nprevious values.  Errors can occur either while processing options in\n\\fBTk_SetOptions\\fR or later in the caller.  In many cases the caller does\nadditional processing after \\fBTk_SetOptions\\fR returns; for example, it\nmight use an option value to set a trace on a variable and may detect\nan error if the variable is an array instead of a scalar.  Error recovery\nis enabled by passing in a non-NULL value for the \\fIsavePtr\\fR argument\nto \\fBTk_SetOptions\\fR; this should be a pointer to an uninitialized\nTk_SavedOptions structure on the caller's stack.  \\fBTk_SetOptions\\fR\noverwrites the structure pointed to by \\fIsavePtr\\fR with information\nabout the old values of any options modified by the procedure.\nIf \\fBTk_SetOptions\\fR returns successfully, the\ncaller uses the structure in one of two ways.  If the caller completes\nits processing of the new options without any errors, then it must pass\nthe structure to \\fBTk_FreeSavedOptions\\fR so that the old values can be\nfreed.  If the caller detects an error in its processing of the new\noptions, then it should pass the structure to \\fBTk_RestoreSavedOptions\\fR,\nwhich will copy the old values back into the widget record and free\nthe new values.\nIf \\fBTk_SetOptions\\fR detects an error then it automatically restores\nany options that had already been modified and leaves *\\fIsavePtr\\fR in\nan empty state: the caller need not call either \\fBTk_FreeSavedOptions\\fR or\n\\fBTk_RestoreSavedOptions\\fR.\nIf the \\fIsavePtr\\fR argument to \\fBTk_SetOptions\\fR is NULL then\n\\fBTk_SetOptions\\fR frees each old option value immediately when it sets a new\nvalue for the option.  In this case, if an error occurs in the third\noption, the old values for the first two options cannot be restored.\n.PP\n\\fBTk_GetOptionValue\\fR returns the current value of a configuration option\nfor a particular widget.  The \\fInamePtr\\fR argument contains the name of\nan option; \\fBTk_GetOptionValue\\fR uses \\fIoptionTable\\fR\nto lookup the option and extract its value from the widget record\npointed to by \\fIrecordPtr\\fR, then it returns an object containing\nthat value.  If an error occurs (e.g., because \\fInamePtr\\fR contains an\nunknown option name) then NULL is returned and an error message is left\nin \\fIinterp\\fR's result unless \\fIinterp\\fR is NULL.\n.PP\n\\fBTk_GetOptionInfo\\fR returns information about configuration options in\na form suitable for \\fBconfigure\\fR widget commands.  If the \\fInamePtr\\fR\nargument is not NULL, it points to an object that gives the name of a\nconfiguration option; \\fBTk_GetOptionInfo\\fR returns an object containing\na list with five elements, which are the name of the option, the name and\nclass used for the option in the option database, the default value for\nthe option, and the current value for the option.  If the \\fInamePtr\\fR\nargument is NULL, then \\fBTk_GetOptionInfo\\fR returns information about\nall options in the form of a list of lists; each sublist describes one\noption.  Synonym options are handled differently depending on whether\n\\fInamePtr\\fR is NULL: if \\fInamePtr\\fR is NULL then the sublist for\neach synonym option has only two elements, which are the name of the\noption and the name of the other option that it refers to; if \\fInamePtr\\fR\nis non-NULL and names a synonym option then the object returned\nis the five-element list\nfor the other option that the synonym refers to.  If an error occurs\n(e.g., because \\fInamePtr\\fR contains an unknown option name) then NULL\nis returned and an error message is left in \\fIinterp\\fR's result unless\n\\fIinterp\\fR is NULL.\n.PP\n\\fBTk_FreeConfigOptions\\fR must be invoked when a widget is deleted.\nIt frees all of the resources associated with any of the configuration\noptions defined in \\fIrecordPtr\\fR by \\fIoptionTable\\fR.\n.SH \"TEMPLATES\"\n.PP\nThe array of Tk_OptionSpec structures passed to \\fBTk_CreateOptionTable\\fR\nvia its \\fItemplatePtr\\fR argument describes the configuration options\nsupported by a particular class of widgets.  Each structure specifies\none configuration option and has the following fields:\n.CS\ntypedef struct {\n    Tk_OptionType \\fItype\\fR;\n    const char *\\fIoptionName\\fR;\n    const char *\\fIdbName\\fR;\n    const char *\\fIdbClass\\fR;\n    const char *\\fIdefValue\\fR;\n    Tcl_Size \\fIobjOffset\\fR;\n    Tcl_Size \\fIinternalOffset\\fR;\n    int \\fIflags\\fR;\n    const void *\\fIclientData\\fR;\n    int \\fItypeMask\\fR;\n} \\fBTk_OptionSpec\\fR;\n.CE\nThe \\fItype\\fR field indicates what kind of configuration option this is\n(e.g. \\fBTK_OPTION_COLOR\\fR for a color value, or \\fBTK_OPTION_INT\\fR for\nan integer value).  \\fIType\\fR determines how the\nvalue of the option is parsed (more on this below).\nThe \\fIoptionName\\fR field is a string such as \\fB\\-font\\fR or \\fB\\-bg\\fR;\nit is the name used for the option in Tcl commands and passed to\nprocedures via the \\fIobjc\\fR or \\fInamePtr\\fR arguments.\nThe \\fIdbName\\fR and \\fIdbClass\\fR fields are used by \\fBTk_InitOptions\\fR\nto look up a default value for this option in the option database; if\n\\fIdbName\\fR is NULL then the option database is not used by\n\\fBTk_InitOptions\\fR for this option.  The \\fIdefValue\\fR field\nspecifies a default value for this configuration option if no\nvalue is specified in the option database.  The \\fIobjOffset\\fR and\n\\fIinternalOffset\\fR fields indicate where to store the value of this\noption in widget records (more on this below); values for the \\fIobjOffset\\fR\nand \\fIinternalOffset\\fR fields should always be generated with the\n\\fBoffsetof\\fR macro.\nThe \\fIflags\\fR field contains additional information\nto control the processing of this configuration option (see below\nfor details).\n\\fIClientData\\fR provides additional type-specific data needed\nby certain types.  For instance, for \\fBTK_OPTION_COLOR\\fR types,\n\\fIclientData\\fR is a string giving the default value to use on\nmonochrome displays.  See the descriptions of the different types\nbelow for details.\nThe last field, \\fItypeMask\\fR, is used by \\fBTk_SetOptions\\fR to\nreturn information about which options were modified; see the description\nof \\fBTk_SetOptions\\fR above for details.\n.PP\nWhen \\fBTk_InitOptions\\fR and \\fBTk_SetOptions\\fR store the value of an\noption into the widget record, they can do it in either of two ways.\nIf the \\fIobjOffset\\fR field of the Tk_OptionSpec is greater than\nor equal to zero, then the value of the option is stored as a\n(Tcl_Obj *) at the location in the widget record given by \\fIobjOffset\\fR.\nIf the \\fIinternalOffset\\fR field of the Tk_OptionSpec is\ngreater than or equal to zero, then the value of the option is stored\nin a type-specific internal form at the location in the widget record\ngiven by \\fIinternalOffset\\fR.  For example, if the option's type is\n\\fBTK_OPTION_INT\\fR then the internal form is an integer.  If the\n\\fIobjOffset\\fR or \\fIinternalOffset\\fR field is negative then the\nvalue is not stored in that form.  At least one of the offsets must be\ngreater than or equal to zero.\n.PP\nThe \\fIflags\\fR field consists of one or more bits ORed together. The\nfollowing flags are supported:\n.IP \\fBTK_OPTION_NULL_OK\\fR\nIf this bit is set for an option then an empty string will be accepted as\nthe value for the option and the resulting internal form will be a NULL\npointer, a zero value, or \\fBNone\\fR, depending on the type of the option.\nIf the flag is not set then empty strings will result in errors.\n\\fBTK_OPTION_NULL_OK\\fR is typically used to allow a\nfeature to be turned off entirely, e.g. set a cursor value to\n\\fBNone\\fR so that a window simply inherits its parent's cursor.\nNot all option types support the \\fBTK_OPTION_NULL_OK\\fR\nflag; for those that do, there is an explicit indication of that fact\nin the descriptions below.\n.IP \\fBTK_OPTION_DONT_SET_DEFAULT\\fR\nIf this bit is set for an option then no default value will be set in\n\\fBTk_InitOptions\\fR for this option. Neither the option database, nor any\nsystem default value, nor \\fIoptionTable\\fR are used to give a default\nvalue to this option. Instead it is assumed that the caller has already\nsupplied a default value in the widget code.\n.IP \\fBTK_OPTION_ENUM_VAR\\fR\nIf this value is set for an option, then it indicates the the\ninternalOffset points to an enum variable in stead of an int variable.\nOnly useful in combination with \\fBTK_OPTION_STRING_TABLE\\fR,\n\\fBTK_OPTION_BOOLEAN\\fR, \\fBTK_OPTION_ANCHOR\\fR, \\fBTK_OPTION_JUSTIFY\\fR,\nor \\fBTK_OPTION_ANCHOR\\fR.\n.IP \\fBTK_OPTION_VAR(\\fItype\\fB)\\fR\nIf this value is set for an option, then it indicates the the\ninternalOffset points to a \\fItype\\fR variable in stead of an int variable.\nOnly useful in combination with \\fBTK_OPTION_STRING_TABLE\\fR or\n\\fBTK_OPTION_BOOLEAN\\fR, or as \\fBTK_OPTION_VAR(Tcl_Size)\\fR\nwith \\fBTK_OPTION_INT\\fR\n.RS\n.PP\nThe \\fItype\\fR field of each Tk_OptionSpec structure determines\nhow to parse the value of that configuration option. The\nlegal value for \\fItype\\fR, and the corresponding actions, are\ndescribed below.  If the type requires a \\fItkwin\\fR value to be\npassed into procedures like \\fBTk_SetOptions\\fR, or if it uses\nthe \\fIclientData\\fR field of the Tk_OptionSpec, then it is indicated\nexplicitly; if not mentioned, the type requires neither \\fItkwin\\fR\nnor \\fIclientData\\fR.\n.RE\n.IP \\fBTK_OPTION_ANCHOR\\fR\nThe value must be a standard anchor position such as \\fBne\\fR or\n\\fBcenter\\fR.  The internal form is a Tk_Anchor value like the ones\nreturned by \\fBTk_GetAnchorFromObj\\fR.  This option type supports the\n\\fBTK_OPTION_NULL_OK\\fR flag; if the empty string is specified as the\nvalue for the option, the integer relief value is set to \\fBTK_ANCHOR_NULL\\fR.\n.IP \\fBTK_OPTION_BITMAP\\fR\nThe value must be a standard Tk bitmap name. The internal form is a\nPixmap token like the ones returned by \\fBTk_AllocBitmapFromObj\\fR.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR, and it supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_BOOLEAN\\fR\nThe value must be a standard boolean value such as \\fBtrue\\fR or\n\\fBno\\fR.  The internal form is an integer with value 0 or 1.  Note that if\nthe \\fIobjOffset\\fR field is not used, information about the original\nvalue of this option will be lost.  This option type supports the\n\\fBTK_OPTION_NULL_OK\\fR flag; if a NULL value is set, the internal\nrepresentation is set to -1.\n.IP \\fBTK_OPTION_BORDER\\fR\nThe value must be a standard color name such as \\fBred\\fR or \\fB#ff8080\\fR.\nThe internal form is a Tk_3DBorder token like the ones returned\nby \\fBTk_Alloc3DBorderFromObj\\fR.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR, and it supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_COLOR\\fR\nThe value must be a standard color name such as \\fBred\\fR or \\fB#ff8080\\fR.\nThe internal form is an (XColor *) token like the ones returned by\n\\fBTk_AllocColorFromObj\\fR.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR, and it supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_CURSOR\\fR\nThe value must be a standard cursor name such as \\fBcross\\fR or \\fB@foo\\fR.\nThe internal form is a Tk_Cursor token like the ones returned by\n\\fBTk_AllocCursorFromObj\\fR.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR, and when the option is set the cursor\nfor the window is changed by calling \\fBXDefineCursor\\fR.  This\noption type also supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_CUSTOM\\fR\nThis option allows applications to define new option types.  The\nclientData field of the entry points to a structure defining the new\noption type.  See the section \\fBCUSTOM OPTION TYPES\\fR below for details.\n.IP \\fBTK_OPTION_DOUBLE\\fR\nThe string value must be a floating-point number in\nthe format accepted by \\fBstrtol\\fR.  The internal form is a C\n\\fBdouble\\fR value.  This option type supports the \\fBTK_OPTION_NULL_OK\\fR\nflag; if a NULL value is set, the internal representation is set to NaN.\n.IP \\fBTK_OPTION_END\\fR\nMarks the end of the template.  There must be a Tk_OptionSpec structure\nwith \\fItype\\fR \\fBTK_OPTION_END\\fR at the end of each template.  If the\n\\fIclientData\\fR field of this structure is not NULL, then it points to\nan additional array of Tk_OptionSpec's, which is itself terminated by\nanother \\fBTK_OPTION_END\\fR entry.  Templates may be chained arbitrarily\ndeeply.  This feature allows common options to be shared by several\nwidget classes.\n.IP \\fBTK_OPTION_FONT\\fR\nThe value must be a standard font name such as \\fBTimes 16\\fR.\nThe internal form is a Tk_Font handle like the ones returned by\n\\fBTk_AllocFontFromObj\\fR.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR, and it supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_INT\\fR\nThe string value must be an integer in the format accepted by\n\\fBstrtol\\fR (e.g. \\fB0\\fR and \\fB0x\\fR prefixes may be used to\nspecify octal or hexadecimal numbers, respectively).  The internal form is\na C \\fBint\\fR value.  This option type supports the \\fBTK_OPTION_NULL_OK\\fR\nflag; if a NULL value is set, the internal representation is set to INT_MIN.\n.IP \\fBTK_OPTION_INDEX\\fR\nThe string value must be an index in the format accepted by\n\\fBTcl_GetIntForIndex()\\fR\nor the empty string.  The internal form is a C \\fBint\\fR value. If the string\nstarts with \\fB\\-\\fR, the internal representation will be set to INT_MIN. If the\nstring has the form \\fBend-???\\fR, then the result will be a negative number:\n\\fB-1\\fR stands for \\fBend\\fR, \\fB-2\\fR stands for \\fBend-1\\fR and so on.\nThis option type supports the \\fBTK_OPTION_NULL_OK\\fR flag;\nif a NULL value is set, the internal representation is set to INT_MIN.\n.IP \\fBTK_OPTION_JUSTIFY\\fR\nThe value must be a standard justification value such as \\fBleft\\fR.\nThe internal form is a Tk_Justify like the values returned by\n\\fBTk_GetJustifyFromObj\\fR.  This option type supports the\n\\fBTK_OPTION_NULL_OK\\fR\nflag; if the empty string is specified as the value for the option,\nthe integer relief value is set to \\fBTK_JUSTIFY_NULL\\fR.\n.IP \\fBTK_OPTION_PIXELS\\fR\nThe value must specify a screen distance such as \\fB2i\\fR or \\fB6.4\\fR.\nThe internal form is an integer value giving a\ndistance in pixels, like the values returned by\n\\fBTk_GetPixelsFromObj\\fR.  Note that if the \\fIobjOffset\\fR field is not\nused, information about the original value of this option will be lost.\nSee \\fBOBJOFFSET VS. INTERNALOFFSET\\fR below for details.  This option\ntype supports the \\fBTK_OPTION_NULL_OK\\fR flag; if a NULL value is set, the\ninternal representation is set to INT_MIN.\n.IP \\fBTK_OPTION_RELIEF\\fR\nThe value must be standard relief such as \\fBraised\\fR.\nThe internal form is an integer relief value such as\n\\fBTK_RELIEF_RAISED\\fR.  This option type supports the \\fBTK_OPTION_NULL_OK\\fR\nflag; if a NULL value is set, the internal representation is set to\n\\fBTK_RELIEF_NULL\\fR.\n.IP \\fBTK_OPTION_STRING\\fR\nThe value may be any string.  The internal form is a (char *) pointer\nthat points to a dynamically allocated copy of the value.\nThis option type supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fBTK_OPTION_STRING_TABLE\\fR\nFor this type, \\fIclientData\\fR is a pointer to an array of strings\nsuitable for passing to \\fBTcl_GetIndexFromObj\\fR.  The value must\nbe one of the strings in the table, or a unique abbreviation of\none of the strings.  The internal form is an integer giving the index\ninto the table of the matching string, like the return value\nfrom \\fBTcl_GetStringFromObj\\fR.  This option type supports the\n\\fBTK_OPTION_NULL_OK\\fR flag; if a NULL value is set, the internal\nrepresentation is set to -1.\n.IP \\fBTK_OPTION_SYNONYM\\fR\nThis type is used to provide alternative names for an option (for\nexample, \\fB\\-bg\\fR is often used as a synonym for \\fB\\-background\\fR).\nThe \\fBclientData\\fR field is a string that gives the name of another\noption in the same table.  Whenever the synonym option is used, the\ninformation from the other option will be used instead.\n.IP \\fBTK_OPTION_WINDOW\\fR\nThe value must be a window path name.  The internal form is a\n\\fBTk_Window\\fR token for the window.\nThis option type requires \\fItkwin\\fR to be supplied to procedures\nsuch as \\fBTk_SetOptions\\fR (in order to identify the application),\nand it supports the \\fBTK_OPTION_NULL_OK\\fR flag.\n.SH \"STORAGE MANAGEMENT ISSUES\"\n.PP\nIf a field of a widget record has its offset stored in the \\fIobjOffset\\fR\nor \\fIinternalOffset\\fR field of a Tk_OptionSpec structure then the\nprocedures described here will handle all of the storage allocation and\nresource management issues associated with the field.  When the value\nof an option is changed, \\fBTk_SetOptions\\fR (or \\fBTk_FreeSavedOptions\\fR)\nwill automatically free any resources associated with the old value, such as\nTk_Fonts for \\fBTK_OPTION_FONT\\fR options or dynamically allocated memory for\n\\fBTK_OPTION_STRING\\fR options.  For an option stored as an object using the\n\\fIobjOffset\\fR field of a Tk_OptionSpec, the widget record shares the\nobject pointed to by the \\fIobjv\\fR value from the call to\n\\fBTk_SetOptions\\fR.  The reference count for this object is incremented\nwhen a pointer to it is stored in the widget record and decremented when\nthe option is modified.  When the widget is deleted\n\\fBTk_FreeConfigOptions\\fR should be invoked; it will free the resources\nassociated with all options and decrement reference counts for any\nobjects.\n.PP\nHowever, the widget code is responsible for storing NULL or \\fBNone\\fR in\nall pointer and token fields before invoking \\fBTk_InitOptions\\fR.\nThis is needed to allow proper cleanup in the rare case where\nan error occurs in \\fBTk_InitOptions\\fR.\n.SH \"OBJOFFSET VS. INTERNALOFFSET\"\n.PP\nIn most cases it is simplest to use the \\fIinternalOffset\\fR field of\na Tk_OptionSpec structure and not the \\fIobjOffset\\fR field.  This\nmakes the internal form of the value immediately available to the\nwidget code so the value does not have to be extracted from an object\neach time it is used.  However, there are two cases where the\n\\fIobjOffset\\fR field is useful.  The first case is for\n\\fBTK_OPTION_PIXELS\\fR options.  In this case, the internal form is\nan integer pixel value that is valid only for a particular screen.\nIf the value of the option is retrieved, it will be returned as a simple\nnumber.  For example, after the command \\fB.b configure \\-borderwidth 2m\\fR,\nthe command \\fB.b configure \\-borderwidth\\fR might return 7, which is the\ninteger pixel value corresponding to \\fB2m\\fR.  Unfortunately, this loses\nthe original screen-independent value. Thus for \\fBTK_OPTION_PIXELS\\fR options\nit is better to use the \\fIobjOffset\\fR field.  In this case the original\nvalue of the option is retained in the object and can be returned when\nthe option is retrieved.  It might seem convenient to use the\n\\fIinternalOffset\\fR field as well, so that the integer value is\nimmediately available for use in the widget code. But if scaling is\ninvolved, \\fIinternalOffset\\fR won't change value when the scaling\nchanges. Therefore it is better always to use\n\\fBTk_GetPixelsFromObj\\fR to extract the integer value from\nthe object whenever it is needed.  Note: the problem of losing\ninformation on retrievals exists only for \\fBTK_OPTION_PIXELS\\fR options.\n.PP\nThe second reason to use the \\fIobjOffset\\fR field is in order to\nimplement new types of options not supported by these procedures.\nTo implement a new type of option, you can use \\fBTK_OPTION_STRING\\fR as\nthe type in the Tk_OptionSpec structure and set the \\fIobjOffset\\fR field\nbut not the \\fIinternalOffset\\fR field.  Then, after calling\n\\fBTk_SetOptions\\fR, convert the object to internal form yourself.\n.PP\nTtk widgets do not support the \\fIinternalOffset\\fR machinery.\nOption values of Ttk widgets are always stored as (Tcl_Obj *), meaning that\nthe \\fIobjOffset\\fR field must be used.\n.SH \"CUSTOM OPTION TYPES\"\n.PP\nApplications can extend the built-in configuration types with\nadditional configuration types by writing procedures to parse, print,\nfree, and restore saved copies of the type and creating a structure\npointing to those procedures:\n.CS\ntypedef struct {\n    const char *\\fIname\\fR;\n    Tk_CustomOptionSetProc *\\fIsetProc\\fR;\n    Tk_CustomOptionGetProc *\\fIgetProc\\fR;\n    Tk_CustomOptionRestoreProc *\\fIrestoreProc\\fR;\n    Tk_CustomOptionFreeProc *\\fIfreeProc\\fR;\n    void *\\fIclientData\\fR;\n} \\fBTk_ObjCustomOption\\fR;\n\ntypedef int \\fBTk_CustomOptionSetProc\\fR(\n    void *\\fIclientData\\fR,\n    Tcl_Interp *\\fIinterp\\fR,\n    Tk_Window \\fItkwin\\fR,\n    Tcl_Obj **\\fIvaluePtr\\fR,\n    char *\\fIrecordPtr\\fR,\n    Tcl_Size \\fIinternalOffset\\fR,\n    char *\\fIsaveInternalPtr\\fR,\n    int \\fIflags\\fR);\n\ntypedef Tcl_Obj *\\fBTk_CustomOptionGetProc\\fR(\n    void *\\fIclientData\\fR,\n    Tk_Window \\fItkwin\\fR,\n    char *\\fIrecordPtr\\fR,\n    Tcl_Size \\fIinternalOffset\\fR);\n\ntypedef void \\fBTk_CustomOptionRestoreProc\\fR(\n    void *\\fIclientData\\fR,\n    Tk_Window \\fItkwin\\fR,\n    char *\\fIinternalPtr\\fR,\n    char *\\fIsaveInternalPtr\\fR);\n\ntypedef void \\fBTk_CustomOptionFreeProc\\fR(\n    void *\\fIclientData\\fR,\n    Tk_Window \\fItkwin\\fR,\n    char *\\fIinternalPtr\\fR);\n.CE\n.PP\nThe Tk_ObjCustomOption structure contains six fields: a name\nfor the custom option type; pointers to the four procedures; and a\n\\fIclientData\\fR value to be passed to those procedures when they are\ninvoked.  The \\fIclientData\\fR value typically points to a structure\ncontaining information that is needed by the procedures when they are\nparsing and printing options.  \\fIRestoreProc\\fR and \\fIfreeProc\\fR\nmay be NULL, indicating that no function should be called for those\noperations.\n.PP\nThe \\fIsetProc\\fR procedure is invoked by \\fBTk_SetOptions\\fR to\nconvert a Tcl_Obj into an internal representation and store the\nresulting value in the widget record.  The arguments are:\n.RS\n.IP \\fIclientData\\fR\nA copy of the \\fIclientData\\fR field in the Tk_ObjCustomOption\nstructure.\n.IP \\fIinterp\\fR\nA pointer to a Tcl interpreter, used for error reporting.\n.IP \\fITkwin\\fR\nA copy of the \\fItkwin\\fR argument to \\fBTk_SetOptions\\fR\n.IP \\fIvaluePtr\\fR\nA pointer to a reference to a Tcl_Obj describing the new value for the\noption; it could have been specified explicitly in the call to\n\\fBTk_SetOptions\\fR or it could come from the option database or a\ndefault.  If the objOffset for the option is non-negative (the option\nvalue is stored as a (Tcl_Obj *) in the widget record), the Tcl_Obj\npointer referenced by \\fIvaluePtr\\fR is the pointer that will be\nstored at the objOffset for the option.  \\fISetProc\\fR may modify the\nvalue if necessary; for example, \\fIsetProc\\fR may change the value to\nNULL to support the \\fBTK_OPTION_NULL_OK\\fR flag.\n.IP \\fIrecordPtr\\fR\nA pointer to the start of the widget record to modify.\n.IP \\fIinternalOffset\\fR\nOffset in bytes from the start of the widget record to the location\nwhere the internal representation of the option value is to be placed.\n.IP \\fIsaveInternalPtr\\fR\nA pointer to storage allocated in a Tk_SavedOptions structure for the\ninternal representation of the original option value.  Before setting\nthe option to its new value, \\fIsetProc\\fR should set the value\nreferenced by \\fIsaveInternalPtr\\fR to the original value of the\noption in order to support \\fBTk_RestoreSavedOptions\\fR.\n.IP \\fIflags\\fR\nA copy of the \\fIflags\\fR field in the Tk_OptionSpec structure for the\noption\n.RE\n.PP\n\\fISetProc\\fR returns a standard Tcl result: \\fBTCL_OK\\fR to indicate successful\nprocessing, or \\fBTCL_ERROR\\fR to indicate a failure of any kind.  An error\nmessage may be left in the Tcl interpreter given by \\fIinterp\\fR in\nthe case of an error.\n.PP\nThe \\fIgetProc\\fR procedure is invoked by \\fBTk_GetOptionValue\\fR and\n\\fBTk_GetOptionInfo\\fR to retrieve a Tcl_Obj representation of the\ninternal representation of an option.  The \\fIclientData\\fR argument\nis a copy of the \\fIclientData\\fR field in the Tk_ObjCustomOption\nstructure.  \\fITkwin\\fR is a copy of the \\fItkwin\\fR argument to\n\\fBTk_GetOptionValue\\fR or \\fBTk_GetOptionInfo\\fR.  \\fIRecordPtr\\fR\nis a pointer to the beginning of the widget record to query.\n\\fIInternalOffset\\fR is the offset in bytes from the beginning of the\nwidget record to the location where the internal representation of the\noption value is stored.  \\fIGetProc\\fR must return a pointer to a\nTcl_Obj representing the value of the option.\n.PP\nThe \\fIrestoreProc\\fR procedure is invoked by\n\\fBTk_RestoreSavedOptions\\fR to restore a previously saved internal\nrepresentation of a custom option value.  The \\fIclientData\\fR argument\nis a copy of the \\fIclientData\\fR field in the Tk_ObjCustomOption\nstructure.  \\fITkwin\\fR is a copy of the \\fItkwin\\fR argument to\n\\fBTk_GetOptionValue\\fR or \\fBTk_GetOptionInfo\\fR.  \\fIInternalPtr\\fR\nis a pointer to the location where internal representation of the\noption value is stored.\n\\fISaveInternalPtr\\fR is a pointer to the saved value.\n\\fIRestoreProc\\fR must copy the value from \\fIsaveInternalPtr\\fR to\n\\fIinternalPtr\\fR to restore the value.  \\fIRestoreProc\\fR need not\nfree any memory associated with either \\fIinternalPtr\\fR or\n\\fIsaveInternalPtr\\fR; \\fIfreeProc\\fR will be invoked to free that\nmemory if necessary.  \\fIRestoreProc\\fR has no return value.\n.PP\nThe \\fIfreeProc\\fR procedure is invoked by \\fBTk_SetOptions\\fR and\n\\fBTk_FreeSavedOptions\\fR to free any storage allocated for the\ninternal representation of a custom option.  The \\fIclientData\\fR argument\nis a copy of the \\fIclientData\\fR field in the Tk_ObjCustomOption\nstructure.  \\fITkwin\\fR is a copy of the \\fItkwin\\fR argument to\n\\fBTk_GetOptionValue\\fR or \\fBTk_GetOptionInfo\\fR.  \\fIInternalPtr\\fR\nis a pointer to the location where the internal representation of the\noption value is stored.  The \\fIfreeProc\\fR must free any storage\nassociated with the option.  \\fIFreeProc\\fR has no return value.\n.SH KEYWORDS\nanchor, bitmap, boolean, border, color, configuration option,\ncursor, double, font, integer, justify,\npixels, relief, screen distance, synonym\n"
  },
  {
    "path": "doc/SetVisual.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_SetWindowVisual 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_SetWindowVisual \\- change visual characteristics of window\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_SetWindowVisual\\fR(\\fItkwin, visual, depth, colormap\\fR)\n.fi\n.SH ARGUMENTS\n.AS \"Tk_Window int\" colormap\n.AP Tk_Window tkwin in\nToken for window.\n.AP Visual *visual in\nNew visual type to use for \\fItkwin\\fR.\n.AP \"int\" depth in\nNumber of bits per pixel desired for \\fItkwin\\fR.\n.AP Colormap colormap in\nNew colormap for \\fItkwin\\fR, which must be compatible with\n\\fIvisual\\fR and \\fIdepth\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nWhen Tk creates a new window it assigns it the default visual\ncharacteristics (visual, depth, and colormap) for its screen.\n\\fBTk_SetWindowVisual\\fR may be called to change them.\n\\fBTk_SetWindowVisual\\fR must be called before the window has\nactually been created in X (e.g. before \\fBTk_MapWindow\\fR or\n\\fBTk_MakeWindowExist\\fR has been invoked for the window).\nThe safest thing is to call \\fBTk_SetWindowVisual\\fR immediately\nafter calling \\fBTk_CreateWindow\\fR.\nIf \\fItkwin\\fR has already been created before \\fBTk_SetWindowVisual\\fR\nis called then it returns 0 and does not make any changes;  otherwise\nit returns 1 to signify that the operation\ncompleted successfully.\n.PP\nNote that \\fBTk_SetWindowVisual\\fR should not be called if you just want\nto change a window's colormap without changing its visual or depth;\ncall \\fBTk_SetWindowColormap\\fR instead.\n.SH KEYWORDS\ncolormap, depth, visual\n"
  },
  {
    "path": "doc/StrictMotif.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_StrictMotif 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_StrictMotif \\- Return value of tk_strictMotif variable\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_StrictMotif\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP Tk_Window tkwin in\nToken for window.\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure returns the current value of the \\fBtk_strictMotif\\fR\nvariable in the interpreter associated with \\fItkwin\\fR's application.\nThe value is returned as an integer that is either 0 or 1.\n1 means that strict Motif compliance has been requested, so anything\nthat is not part of the Motif specification should be avoided.\n0 means that\n.QW Motif-like\nis good enough, and extra features are welcome.\n.PP\nThis procedure uses a link to the Tcl variable to provide much\nfaster access to the variable's value than could be had by calling\n\\fBTcl_GetVar\\fR.\n.SH KEYWORDS\nMotif compliance, tk_strictMotif variable\n"
  },
  {
    "path": "doc/TextLayout.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ComputeTextLayout 3 8.1 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_ComputeTextLayout, Tk_FreeTextLayout, Tk_DrawTextLayout, Tk_UnderlineTextLayout, Tk_PointToChar, Tk_CharBbox, Tk_DistanceToTextLayout, Tk_IntersectTextLayout, Tk_TextLayoutToPostscript \\- routines to measure and display single-font, multi-line, justified text.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_TextLayout\n\\fBTk_ComputeTextLayout\\fR(\\fItkfont, string, numChars, wrapLength, justify, flags, widthPtr, heightPtr\\fR)\n.sp\n\\fBTk_FreeTextLayout\\fR(\\fIlayout\\fR)\n.sp\n\\fBTk_DrawTextLayout\\fR(\\fIdisplay, drawable, gc, layout, x, y, firstChar, lastChar\\fR)\n.sp\n\\fBTk_UnderlineTextLayout\\fR(\\fIdisplay, drawable, gc, layout, x, y, underline\\fR)\n.sp\nTcl_Size\n\\fBTk_PointToChar\\fR(\\fIlayout, x, y\\fR)\n.sp\nint\n\\fBTk_CharBbox\\fR(\\fIlayout, index, xPtr, yPtr, widthPtr, heightPtr\\fR)\n.sp\nint\n\\fBTk_DistanceToTextLayout\\fR(\\fIlayout, x, y\\fR)\n.sp\nint\n\\fBTk_IntersectTextLayout\\fR(\\fIlayout, x, y, width, height\\fR)\n.sp\n\\fBTk_TextLayoutToPostscript\\fR(\\fIinterp, layout\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_TextLayout \"*xPtr, *yPtr\"\n.AP Tk_Font tkfont in\nFont to use when constructing and displaying a text layout.  The\n\\fItkfont\\fR must remain valid for the lifetime of the text layout.  Must\nhave been returned by a previous call to \\fBTk_GetFont\\fR.\n.AP \"const char\" *string in\nPotentially multi-line string whose dimensions are to be computed and\nstored in the text layout.  The \\fIstring\\fR must remain valid for the\nlifetime of the text layout.\n.AP int numChars in\nThe number of characters to consider from \\fIstring\\fR.  If\n\\fInumChars\\fR is negative, then assumes \\fIstring\\fR is null\nterminated and uses \\fBTcl_NumUtfChars\\fR to determine the length of\n\\fIstring\\fR.\n.AP int wrapLength in\nLongest permissible line length, in pixels.  Lines in \\fIstring\\fR will\nautomatically be broken at word boundaries and wrapped when they reach\nthis length.  If \\fIwrapLength\\fR is too small for even a single\ncharacter to fit on a line, it will be expanded to allow one character to\nfit on each line.  If \\fIwrapLength\\fR is <= 0, there is no automatic\nwrapping; lines will get as long as they need to be and only wrap if a\nnewline/return character is encountered.\n.AP Tk_Justify justify in\nHow to justify the lines in a multi-line text layout.  Possible values\nare \\fBTK_JUSTIFY_LEFT\\fR, \\fBTK_JUSTIFY_CENTER\\fR, or\n\\fBTK_JUSTIFY_RIGHT\\fR. If the text layout only occupies a single\nline, then \\fIjustify\\fR is irrelevant.\n.AP int flags in\nVarious flag bits OR-ed together. \\fBTK_IGNORE_TABS\\fR means that tab\ncharacters should not be expanded to the next tab stop.\n\\fBTK_IGNORE_NEWLINES\\fR means that newline/return characters should\nnot cause a line break.  If either tabs or newlines/returns are\nignored, then they will be treated as regular characters, being\nmeasured and displayed in a platform-dependent manner as described in\n\\fBTk_MeasureChars\\fR, and will not have any special behaviors.\n.AP int *widthPtr out\nIf non-NULL, filled with either the width, in pixels, of the widest\nline in the text layout, or the width, in pixels, of the bounding box for the\ncharacter specified by \\fIindex\\fR.\n.AP int *heightPtr out\nIf non-NULL, filled with either the total height, in pixels, of all\nthe lines in the text layout, or the height, in pixels, of the bounding\nbox for the character specified by \\fIindex\\fR.\n.AP Tk_TextLayout layout in\nA token that represents the cached layout information about the single-font,\nmulti-line, justified piece of text.  This token is returned by\n\\fBTk_ComputeTextLayout\\fR.\n.AP Display *display in\nDisplay on which to draw.\n.AP Drawable drawable in\nWindow or pixmap in which to draw.\n.AP GC gc in\nGraphics context to use for drawing text layout.  The font selected in\nthis GC must correspond to the \\fItkfont\\fR used when constructing the\ntext layout.\n.AP int \"x, y\" in\nPoint, in pixels, at which to place the upper-left hand corner of the\ntext layout when it is being drawn, or the coordinates of a point (with\nrespect to the upper-left hand corner of the text layout) to check\nagainst the text layout.\n.AP Tcl_Size firstChar in\nThe index of the first character to draw from the given text layout.\nThe number 0 means to draw from the beginning.\n.AP Tcl_Size lastChar in\nThe index of the last character up to which to draw.  The character\nspecified by \\fIlastChar\\fR itself will not be drawn.  A number less\nthan 0 means to draw all characters in the text layout.\n.AP int underline in\nIndex of the single character to underline in the text layout, or a\nnegative number counting backwards from the end of the string. Any\nout-of-range number (e.g. INT_MIN) means no underline.\n.AP Tcl_Size index in\nThe index of the character whose bounding box is desired.  The bounding\nbox is computed with respect to the upper-left hand corner of the text layout.\n.AP int \"*xPtr, *yPtr\" out\nFilled with the upper-left hand corner, in pixels, of the bounding box\nfor the character specified by \\fIindex\\fR.  Either or both \\fIxPtr\\fR\nand \\fIyPtr\\fR may be NULL, in which case the corresponding value\nis not calculated.\n.AP int \"width, height\" in\nSpecifies the width and height, in pixels, of the rectangular area to\ncompare for intersection against the text layout.\n.AP Tcl_Interp *interp out\nPostscript code that will print the text layout is appended to\nthe result of interpreter \\fIinterp\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThese routines are for measuring and displaying single-font, multi-line,\njustified text.  To measure and display simple single-font, single-line\nstrings, refer to the documentation for \\fBTk_MeasureChars\\fR.  There is\nno programming interface in the core of Tk that supports multi-font,\nmulti-line text; support for that behavior must be built on top of\nsimpler layers.\nNote that unlike the lower level text display routines, the functions\ndescribed here all operate on character-oriented lengths and indices\nrather than byte-oriented values.  See the description of\n\\fBTcl_UtfAtIndex\\fR for more details on converting between character\nand byte offsets.\n.PP\nThe routines described here are built on top of the programming interface\ndescribed in the \\fBTk_MeasureChars\\fR documentation.  Tab characters and\nnewline/return characters may be treated specially by these procedures,\nbut all other characters are passed through to the lower level.\n.PP\n\\fBTk_ComputeTextLayout\\fR computes the layout information needed to\ndisplay a single-font, multi-line, justified \\fIstring\\fR of text and\nreturns a Tk_TextLayout token that holds this information.  This token is\nused in subsequent calls to procedures such as \\fBTk_DrawTextLayout\\fR,\n\\fBTk_DistanceToTextLayout\\fR, and \\fBTk_FreeTextLayout\\fR.  The\n\\fIstring\\fR and \\fItkfont\\fR used when computing the layout must remain\nvalid for the lifetime of this token.\n.PP\n\\fBTk_FreeTextLayout\\fR is called to release the storage associated with\n\\fIlayout\\fR when it is no longer needed.  A \\fIlayout\\fR should not be used\nin any other text layout procedures once it has been released.\n.PP\n\\fBTk_DrawTextLayout\\fR uses the information in \\fIlayout\\fR to display a\nsingle-font, multi-line, justified string of text at the specified location.\n.PP\n\\fBTk_UnderlineTextLayout\\fR uses the information in \\fIlayout\\fR to\ndisplay an underline below an individual character.  This procedure does\nnot draw the text, just the underline.  To produce natively underlined\ntext, an underlined font should be constructed and used.  All characters,\nincluding tabs, newline/return characters, and spaces at the ends of\nlines, can be underlined using this method.  However, the underline will\nnever be drawn outside of the computed width of \\fIlayout\\fR; the\nunderline will stop at the edge for any character that would extend\npartially outside of \\fIlayout\\fR, and the underline will not be visible\nat all for any character that would be located completely outside of the\nlayout.\n.PP\n\\fBTk_PointToChar\\fR uses the information in \\fIlayout\\fR to determine the\ncharacter closest to the given point.  The point is specified with respect\nto the upper-left hand corner of the \\fIlayout\\fR, which is considered to be\nlocated at (0, 0).  Any point whose \\fIy\\fR-value is less that 0 will be\nconsidered closest to the first character in the text layout; any point\nwhose \\fIy\\fR-value is greater than the height of the text layout will be\nconsidered closest to the last character in the text layout.  Any point\nwhose \\fIx\\fR-value is negative will be considered closest to the first\ncharacter on that line; any point whose \\fIx\\fR-value is greater than the\nwidth of the text layout will be considered closest to the last character on\nthat line.  The return value is the index of the character that was closest\nto the point, or one more than the index of any character (to indicate that\nthe point was after the end of the string and that the corresponding caret\nwould be at the end of the string).  Given a \\fIlayout\\fR with no characters,\nthe value 0 will always be returned, referring to a hypothetical zero-width\nplaceholder character.\n.PP\n\\fBTk_CharBbox\\fR uses the information in \\fIlayout\\fR to return the\nbounding box for the character specified by \\fIindex\\fR.  The width of the\nbounding box is the advance width of the character, and does not include any\nleft or right bearing.  Any character that extends partially outside of\n\\fIlayout\\fR is considered to be truncated at the edge.  Any character\nthat would be located completely outside of \\fIlayout\\fR is considered to\nbe zero-width and pegged against the edge.  The height of the bounding\nbox is the line height for this font, extending from the top of the\nascent to the bottom of the descent; information about the actual height\nof individual letters is not available.  For measurement purposes, a\n\\fIlayout\\fR that contains no characters is considered to contain a\nsingle zero-width placeholder character at index 0.  If \\fIindex\\fR was\nnot a valid character index, the return value is 0 and \\fI*xPtr\\fR,\n\\fI*yPtr\\fR, \\fI*widthPtr\\fR, and \\fI*heightPtr\\fR are unmodified.\nOtherwise, if \\fIindex\\fR did specify a valid, the return value is\nnon-zero, and \\fI*xPtr\\fR, \\fI*yPtr\\fR, \\fI*widthPtr\\fR, and\n\\fI*heightPtr\\fR are filled with the bounding box information for the\ncharacter.  If any of \\fIxPtr\\fR, \\fIyPtr\\fR, \\fIwidthPtr\\fR, or\n\\fIheightPtr\\fR are NULL, the corresponding value is not calculated or\nstored.\n.PP\n\\fBTk_DistanceToTextLayout\\fR computes the shortest distance in pixels from\nthe given point (\\fIx, y\\fR) to the characters in \\fIlayout\\fR.\nNewline/return characters and non-displaying space characters that occur at\nthe end of individual lines in the text layout are ignored for hit detection\npurposes, but tab characters are not.  The return value is 0 if the point\nactually hits the \\fIlayout\\fR.  If the point did not hit the \\fIlayout\\fR\nthen the return value is the distance in pixels from the point to the\n\\fIlayout\\fR.\n.PP\n\\fBTk_IntersectTextLayout\\fR determines whether a \\fIlayout\\fR lies\nentirely inside, entirely outside, or overlaps a given rectangle.\nNewline/return characters and non-displaying space characters that occur\nat the end of individual lines in the \\fIlayout\\fR are ignored for\nintersection calculations.  The return value is \\-1 if the \\fIlayout\\fR is\nentirely outside of the rectangle, 0 if it overlaps, and 1 if it is\nentirely inside of the rectangle.\n.PP\n\\fBTk_TextLayoutToPostscript\\fR outputs code consisting of a Postscript\narray of strings that represent the individual lines in \\fIlayout\\fR.  It\nis the responsibility of the caller to take the Postscript array of\nstrings and add some Postscript function operate on the array to render\neach of the lines.  The code that represents the Postscript array of\nstrings is appended to interpreter \\fIinterp\\fR's result.\n.SH \"DISPLAY MODEL\"\n.PP\nWhen measuring a text layout, space characters that occur at the end of a\nline are ignored.  The space characters still exist and the insertion point\ncan be positioned amongst them, but their additional width is ignored when\njustifying lines or returning the total width of a text layout.  All\nend-of-line space characters are considered to be attached to the right edge\nof the line; this behavior is logical for left-justified text and reasonable\nfor center-justified text, but not very useful when editing right-justified\ntext.  Spaces are considered variable width characters; the first space that\nextends past the edge of the text layout is clipped to the edge, and any\nsubsequent spaces on the line are considered zero width and pegged against\nthe edge.  Space characters that occur in the middle of a line of text are\nnot suppressed and occupy their normal space width.\n.PP\nTab characters are not ignored for measurement calculations.  If wrapping\nis turned on and there are enough tabs on a line, the next tab will wrap\nto the beginning of the next line.  There are some possible strange\ninteractions between tabs and justification; tab positions are calculated\nand the line length computed in a left-justified world, and then the\nwhole resulting line is shifted so it is centered or right-justified,\ncausing the tab columns not to align any more.\n.PP\nWhen wrapping is turned on, lines may wrap at word breaks (space or tab\ncharacters) or newline/returns.  A dash or hyphen character in the middle\nof a word is not considered a word break.  \\fBTk_ComputeTextLayout\\fR\nalways attempts to place at least one word on each line.  If it cannot\nbecause the \\fIwrapLength\\fR is too small, the word will be broken and as\nmuch as fits placed on the line and the rest on subsequent line(s).  If\n\\fIwrapLength\\fR is so small that not even one character can fit on a\ngiven line, the \\fIwrapLength\\fR is ignored for that line and one\ncharacter will be placed on the line anyhow.  When wrapping is turned\noff, only newline/return characters may cause a line break.\n.PP\nWhen a text layout has been created using an underlined \\fItkfont\\fR,\nthen any space characters that occur at the end of individual lines,\nnewlines/returns, and tabs will not be displayed underlined when\n\\fBTk_DrawTextLayout\\fR is called, because those characters are never\nactually drawn \\- they are merely placeholders maintained in the\n\\fIlayout\\fR.\n.SH KEYWORDS\nfont\n"
  },
  {
    "path": "doc/TkInitStubs.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1999 Scriptics Corporation\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_InitStubs 3 8.4 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_InitStubs \\- initialize the Tk stubs mechanism\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nconst char *\n\\fBTk_InitStubs\\fR(\\fIinterp, version, exact\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tcl_Interp *interp in\n.AP Tcl_Interp *interp in\nTcl interpreter handle.\n.AP char *version in\nA version string consisting of one or more decimal numbers\nseparated by dots.\n.AP int exact in\nNon-zero means that only the particular Tk version specified by\n\\fIversion\\fR is acceptable.\nZero means that versions newer than \\fIversion\\fR are also\nacceptable as long as they have the same major version number\nas \\fIversion\\fR.\n.BE\n.SH INTRODUCTION\n.PP\nThe Tcl stubs mechanism defines a way to dynamically bind\nextensions to a particular Tcl implementation at run time.\nthe stubs mechanism requires no changes to applications\nincorporating Tcl/Tk interpreters.  Only developers creating\nC-based Tcl/Tk extensions need to take steps to use the\nstubs mechanism with their extensions.\nSee the \\fBTcl_InitStubs\\fR page for more information.\n.PP\nEnabling the stubs mechanism for a Tcl/Tk extension requires the following\nsteps:\n.IP 1) 5\nCall \\fBTcl_InitStubs\\fR in the extension before calling any other\nTcl functions.\n.IP 2) 5\nCall \\fBTk_InitStubs\\fR if the extension before calling any other\nTk functions.\n.IP 2) 5\nDefine the \\fBUSE_TCL_STUBS\\fR and the \\fBUSE_TK_STUBS\\fR\nsymbols. Typically, you would include the \\fB\\-DUSE_TCL_STUBS\\fR and\nthe \\fB\\-DUSE_TK_STUBS\\fR flags when compiling the extension.\n.IP 3) 5\nLink the extension with the Tcl and Tk stubs libraries instead of the\nstandard Tcl and Tk libraries.  On Unix platforms, the library names\nare \\fIlibtclstub8.4.a\\fR and \\fIlibtkstub8.4.a\\fR; on Windows\nplatforms, the library names are \\fItclstub84.lib\\fR and\n\\fItkstub84.lib\\fR. Adjust the library names with appropriate version\nnumber but note that the extension may only be used with versions of\nTcl/Tk that have that version number or higher.\n.SH DESCRIPTION\n.PP\n\\fBTk_InitStubs\\fR attempts to initialize the Tk stub table pointers\nand ensure that the correct version of Tk is loaded.  In addition\nto an interpreter handle, it accepts as arguments a version number\nand a Boolean flag indicating whether the extension requires\nan exact version match or not.  If \\fIexact\\fR is 0, then the\nextension is indicating that newer versions of Tk are acceptable\nas long as they have the same major version number as \\fIversion\\fR;\nnon-zero means that only the specified \\fIversion\\fR is acceptable.\n\\fBTcl_InitStubs\\fR returns a string containing the actual version\nof Tk satisfying the request, or NULL if the Tk version is not\nacceptable, does not support the stubs mechanism, or any other\nerror condition occurred.\n.SH \"SEE ALSO\"\n\\fBTcl_InitStubs\\fR\n.SH KEYWORDS\nstubs\n"
  },
  {
    "path": "doc/Tk_Init.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_Init 3 8.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_Init, Tk_SafeInit \\- add Tk to an interpreter and make a new Tk application.\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nint\n\\fBTk_Init\\fR(\\fIinterp\\fR)\n.sp\nint\n\\fBTk_SafeInit\\fR(\\fIinterp\\fR)\n.SH ARGUMENTS\n.AP Tcl_Interp *interp in\nInterpreter in which to load Tk.  Tk should not already be loaded\nin this interpreter.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_Init\\fR is the package initialization procedure for Tk.\nIt is normally invoked by the \\fBTcl_AppInit\\fR procedure\nfor an application or by the \\fBload\\fR command.\n\\fBTk_Init\\fR adds all of Tk's commands to \\fIinterp\\fR\nand creates a new Tk application, including its main window.\nIf the initialization is successful \\fBTk_Init\\fR returns\n\\fBTCL_OK\\fR;  if there is an error it returns \\fBTCL_ERROR\\fR.\n\\fBTk_Init\\fR also leaves a result or error message\nin interpreter \\fIinterp\\fR's result.\n.PP\nIf there is a variable \\fBargv\\fR in \\fIinterp\\fR, \\fBTk_Init\\fR\ntreats the contents of this variable as a list of options for the\nnew Tk application.\nThe options may have any of the forms documented for the\n\\fBwish\\fR application (in fact, \\fBwish\\fR uses Tk_Init to process\nits command-line arguments).\n.PP\n\\fBTk_SafeInit\\fR is identical to \\fBTk_Init\\fR except that it removes\nall Tk commands that are considered unsafe.  Those commands and the\nreasons for their exclusion are:\n.TP\n\\fBbell\\fR\n.\nContinuous ringing of the bell is a nuisance.\n.TP\n\\fBclipboard\\fR\n.\nA malicious script could replace the contents of the clipboard with\nthe string\n.QW \"\\fBrm \\-r *\\fR\"\nand lead to surprises when the contents of the clipboard are pasted.\n.TP\n\\fBgrab\\fR\n.\nGrab can be used to block the user from using any other applications.\n.TP\n\\fBmenu\\fR\n.\nMenus can be used to cover the entire screen and to steal input from\nthe user.\n.TP\n\\fBselection\\fR\n.\nSee clipboard.\n.TP\n\\fBsend\\fR\n.\nSend can be used to cause unsafe interpreters to execute commands.\n.TP\n\\fBtk\\fR\n.\nThe tk command recreates the send command, which is unsafe.\n.TP\n\\fBtkwait\\fR\n.\nTkwait can block the containing process forever\n.TP\n\\fBtoplevel\\fR\n.\nToplevels can be used to cover the entire screen and to steal input\nfrom the user.\n.TP\n\\fBwm\\fR\n.\nIf toplevels are ever allowed, wm can be used to remove decorations,\nmove windows around, etc.\n.SH KEYWORDS\nsafe, application, initialization, load, main window\n"
  },
  {
    "path": "doc/Tk_Main.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_Main 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_Main \\- main program for Tk-based applications\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\n\\fBTk_Main\\fR(\\fIargc, argv, appInitProc\\fR)\n.SH ARGUMENTS\n.AS Tcl_AppInitProc *appInitProc\n.AP Tcl_Size argc in\nNumber of elements in \\fIargv\\fR.\n.AP char *argv[] in\nArray of strings containing command-line arguments. On Windows, when\nusing -DUNICODE, the parameter type changes to wchar_t *.\n.AP Tcl_AppInitProc *appInitProc in\nAddress of an application-specific initialization procedure.\nThe value for this argument is usually \\fBTcl_AppInit\\fR.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_Main\\fR acts as the main program for most Tk-based applications.\nStarting with Tk 4.0 it is not called \\fBmain\\fR anymore because it\nis part of the Tk library and having a function \\fBmain\\fR\nin a library (particularly a shared library) causes problems on many\nsystems.\nHaving \\fBmain\\fR in the Tk library would also make it hard to use\nTk in C++ programs, since C++ programs must have special C++\n\\fBmain\\fR functions.\n.PP\nNormally each application contains a small \\fBmain\\fR function that does\nnothing but invoke \\fBTk_Main\\fR.\n\\fBTk_Main\\fR then does all the work of creating and running a\n\\fBwish\\fR-like application.\n.PP\nWhen it is has finished its own initialization, but before\nit processes commands, \\fBTk_Main\\fR calls the procedure given by\nthe \\fIappInitProc\\fR argument.  This procedure provides a\n.QW hook\nfor the application to perform its own initialization, such as defining\napplication-specific commands.  The procedure must have an interface\nthat matches the type \\fBTcl_AppInitProc\\fR:\n.CS\ntypedef int \\fBTcl_AppInitProc\\fR(\n        Tcl_Interp *\\fIinterp\\fR);\n.CE\n\\fIAppInitProc\\fR is almost always a pointer to \\fBTcl_AppInit\\fR;\nfor more details on this procedure, see the documentation\nfor \\fBTcl_AppInit\\fR.\n.PP\n\\fBTk_Main\\fR functions much the same as \\fBTcl_Main\\fR.  In particular,\n\\fBTk_Main\\fR supports both an interactive mode and a startup script\nmode, with the file name and encoding of a startup script under the\ncontrol of the \\fBTcl_SetStartupScript\\fR and \\fBTcl_GetStartupScript\\fR\nroutines. However it calls \\fBTk_MainLoop\\fR after processing any\nsupplied script, and in interactive uses events registered with\n\\fBTcl_CreateFileHandler\\fR to process user input.\n.SH \"SEE ALSO\"\nTcl_DoOneEvent(3)\n.SH KEYWORDS\napplication-specific initialization, command-line arguments, main program\n"
  },
  {
    "path": "doc/WinUtil.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_ConfigureWindow 3 4.0 Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_GetOtherWindow, Tk_MakeContainer, Tk_MakeWindow, Tk_UseWindow \\- window utility functions\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nTk_Window\n\\fBTk_GetOtherWindow\\fR(\\fItkwin\\fR)\n.sp\n\\fBTk_MakeContainer\\fR(\\fItkwin\\fR)\n.sp\n\\fBTk_MakeWindow\\fR(\\fItkwin, parent\\fR)\n.sp\nint\n\\fBTk_UseWindow\\fR(\\fIinterp, tkwin, string\\fR)\n.fi\n.SH ARGUMENTS\n.AS XSetWindowAttributes borderWidth\n.AP Tcl_Interp * interp in\nInterpreter associated with the application.\n.AP Tk_Window tkwin in\nToken for window.\n.AP Window parent in\nParent window.\n.AP \"const char\" *string in\nString identifying an X window to use for \\fItkwin\\fR; must be an integer value.\n.BE\n.SH DESCRIPTION\n.PP\nIf both the container and embedded window are in the same process,\n\\fBTk_GetOtherWindow\\fR will return either one, given the other.\nIf winPtr is a container, the return value is the token for the\nembedded window, and vice versa. If the \"other\" window isn't in this\nprocess, NULL is returned.\n.PP\n\\fBTk_MakeContainer\\fR is called to indicate that a particular window will be a\ncontainer for an embedded application. This changes certain aspects of\nthe window's behavior, such as whether it will receive events anymore.\n.PP\n\\fBTk_MakeWindow\\fR creates an actual window system window object based on the\ncurrent attributes of the specified TkWindow. It returns the handle to the new\nwindow, or None on failure.\n.PP\n\\fBTk_UseWindow\\fR causes a Tk window to use a given X window as its\nparent window, rather than the root window for the screen. It is\ninvoked by an embedded application to specify the window in which it\nis embedded.\n.PP\nThe return value is normally TCL_OK. If an error occurs (such as\nstring not being a valid window spec), then the return value is\nTCL_ERROR and an error message is left in the interp's result if\ninterp is non-NULL.\n.PP\n.SH KEYWORDS\nparent, window\n"
  },
  {
    "path": "doc/WindowId.3",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1993 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Tk_WindowId 3 \"8.4\" Tk \"Tk Library Procedures\"\n.so man.macros\n.BS\n.SH NAME\nTk_WindowId, Tk_Parent, Tk_Display, Tk_DisplayName, Tk_ScreenNumber, Tk_AlwaysShowSelection, Tk_Screen, Tk_X, Tk_Y, Tk_Width, Tk_Height, Tk_Changes, Tk_Attributes, Tk_IsContainer, Tk_IsEmbedded, Tk_IsMapped, Tk_IsTopLevel, Tk_ReqWidth, Tk_ReqHeight, Tk_MinReqWidth, Tk_MinReqHeight, Tk_InternalBorderLeft, Tk_InternalBorderRight, Tk_InternalBorderTop, Tk_InternalBorderBottom, Tk_Visual, Tk_Depth, Tk_Colormap, Tk_Interp, Tk_NewWindowObj  \\- retrieve information from Tk's local data structure\n.SH SYNOPSIS\n.nf\n\\fB#include <tk.h>\\fR\n.sp\nWindow\n\\fBTk_WindowId\\fR(\\fItkwin\\fR)\n.sp\nTk_Window\n\\fBTk_Parent\\fR(\\fItkwin\\fR)\n.sp\nDisplay *\n\\fBTk_Display\\fR(\\fItkwin\\fR)\n.sp\nconst char *\n\\fBTk_DisplayName\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_ScreenNumber\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_AlwaysShowSelection\\fR(\\fItkwin\\fR)\n.sp\nScreen *\n\\fBTk_Screen\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_X\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_Y\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_Width\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_Height\\fR(\\fItkwin\\fR)\n.sp\nXWindowChanges *\n\\fBTk_Changes\\fR(\\fItkwin\\fR)\n.sp\nXSetWindowAttributes *\n\\fBTk_Attributes\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_IsContainer\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_IsEmbedded\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_IsMapped\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_IsTopLevel\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_ReqWidth\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_ReqHeight\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_MinReqWidth\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_MinReqHeight\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_InternalBorderLeft\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_InternalBorderRight\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_InternalBorderTop\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_InternalBorderBottom\\fR(\\fItkwin\\fR)\n.sp\nVisual *\n\\fBTk_Visual\\fR(\\fItkwin\\fR)\n.sp\nint\n\\fBTk_Depth\\fR(\\fItkwin\\fR)\n.sp\nColormap\n\\fBTk_Colormap\\fR(\\fItkwin\\fR)\n.sp\nTcl_Interp *\n\\fBTk_Interp\\fR(\\fItkwin\\fR)\n.sp\nTcl_Obj *\n\\fBTk_NewWindowObj\\fR(\\fItkwin\\fR)\n.fi\n.SH ARGUMENTS\n.AS Tk_Window tkwin\n.AP Tk_Window tkwin in\nToken for window.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBTk_WindowId\\fR and the other names listed above are\nall macros that return fields from Tk's local data structure\nfor \\fItkwin\\fR.  None of these macros requires any\ninteraction with the server;  it is safe to assume that\nall are fast.\n.PP\n\\fBTk_WindowId\\fR returns the X identifier for \\fItkwin\\fR,\nor \\fBNULL\\fR if no X window has been created for \\fItkwin\\fR\nyet.\n.PP\n\\fBTk_Parent\\fR returns Tk's token for the logical parent of\n\\fItkwin\\fR.  The parent is the token that was specified when\n\\fItkwin\\fR was created, or NULL for main windows.\n.PP\n\\fBTk_Interp\\fR returns the Tcl interpreter associated with a\n\\fItkwin\\fR or NULL if there is an error.\n.PP\n\\fBTk_Display\\fR returns a pointer to the Xlib display structure\ncorresponding to \\fItkwin\\fR.  \\fBTk_DisplayName\\fR returns an\nASCII string identifying \\fItkwin\\fR's display.  \\fBTk_ScreenNumber\\fR\nreturns the index of \\fItkwin\\fR's screen among all the screens\nof \\fItkwin\\fR's display.  \\fBTk_Screen\\fR returns a pointer to\nthe Xlib structure corresponding to \\fItkwin\\fR's screen.\n\\fBTk_AlwaysShowSelection\\fR indicates whether text/entry widgets\nshould always display their selection, regardless of window focus.\n.PP\n\\fBTk_X\\fR, \\fBTk_Y\\fR, \\fBTk_Width\\fR, and \\fBTk_Height\\fR\nreturn information about \\fItkwin's\\fR location within its\nparent and its size.  The location information refers to the\nupper-left pixel in the window, or its border if there is one.\nThe width and height information refers to the interior size\nof the window, not including any border.  \\fBTk_Changes\\fR\nreturns a pointer to a structure containing all of the above\ninformation plus a few other fields.  \\fBTk_Attributes\\fR\nreturns a pointer to an XSetWindowAttributes structure describing\nall of the attributes of the \\fItkwin\\fR's window, such as background\npixmap, event mask, and so on (Tk keeps track of all this information\nas it is changed by the application).  Note that it is essential that\napplications use Tk procedures like \\fBTk_ResizeWindow\\fR instead\nof X procedures like \\fBXResizeWindow\\fR, so that Tk can keep its\ndata structures up-to-date.\n.PP\n\\fBTk_IsContainer\\fR returns a non-zero value if \\fItkwin\\fR\nis a container, and that some other application may be embedding\nitself inside \\fItkwin\\fR.\n.PP\n\\fBTk_IsEmbedded\\fR returns a non-zero value if \\fItkwin\\fR\nis not a free-standing window, but rather is embedded in some\nother application.\n.PP\n\\fBTk_IsMapped\\fR returns a non-zero value if \\fItkwin\\fR\nis mapped and zero if \\fItkwin\\fR is not mapped.\n.PP\n\\fBTk_IsTopLevel\\fR returns a non-zero value if \\fItkwin\\fR\nis a top-level window (its X parent is the root window of the\nscreen) and zero if \\fItkwin\\fR is not a top-level window.\n.PP\n\\fBTk_ReqWidth\\fR and \\fBTk_ReqHeight\\fR return information about\nthe window's requested size.  These values correspond to the last\ncall to \\fBTk_GeometryRequest\\fR for \\fItkwin\\fR.\n.PP\n\\fBTk_MinReqWidth\\fR and \\fBTk_MinReqHeight\\fR return information about\nthe window's minimum requested size.  These values correspond to the last\ncall to \\fBTk_SetMinimumRequestSize\\fR for \\fItkwin\\fR.\n.PP\n\\fBTk_InternalBorderLeft\\fR, \\fBTk_InternalBorderRight\\fR,\n\\fBTk_InternalBorderTop\\fR and \\fBTk_InternalBorderBottom\\fR\nreturn the width of one side of the internal border\nthat has been requested for \\fItkwin\\fR, or 0 if no internal border was\nrequested.  The return value is simply the last value passed to\n\\fBTk_SetInternalBorder\\fR or \\fBTk_SetInternalBorderEx\\fR for \\fItkwin\\fR.\n.PP\n\\fBTk_Visual\\fR, \\fBTk_Depth\\fR, and \\fBTk_Colormap\\fR return\ninformation about the visual characteristics of a window.\n\\fBTk_Visual\\fR returns the visual type for\nthe window, \\fBTk_Depth\\fR returns the number of bits per pixel,\nand \\fBTk_Colormap\\fR returns the current\ncolormap for the window.  The visual characteristics are\nnormally set from the defaults for the window's screen, but\nthey may be overridden by calling \\fBTk_SetWindowVisual\\fR.\n.PP\n\\fBTk_NewWindowObj\\fR creates a new \\fBTcl_Obj\\fR from the window.\n.SH KEYWORDS\nattributes, colormap, depth, display, height, geometry manager,\nidentifier, mapped, requested size, screen, top-level,\nvisual, width, window, x, y\n"
  },
  {
    "path": "doc/accessible.n",
    "content": ".\\\" Automatically generated by Pandoc 3.6.4\n'\\\"\n'\\\" Copyright (c) 2025 Kevin Walzer\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n.TH tk accessible n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n.SH NAME\naccessible \\- Adds screenreader support for core Tk and ttk  widgets.\n.SH SYNOPSIS\n.nf\n\\fBtk accessible set_acc_role \\fIwindow value\\fR\n\\fBtk accessible set_acc_name \\fIwindow value\\fR\n\\fBtk accessible set_acc_description \\fIwindow value\\fR\n\\fBtk accessible set_acc_value \\fIwindow value\\fR\n\\fBtk accessible set_acc_state \\fIwindow value\\fR\n\\fBtk accessible set_acc_action \\fIwindow value\\fR\n\\fBtk accessible set_acc_help \\fIwindow value\\fR\n\\fBtk accessible get_acc_role \\fIwindow \\fR\n\\fBtk accessible get_acc_name \\fIwindow\\fR\n\\fBtk accessible get_acc_description \\fIwindow\\fR\n\\fBtk accessible get_acc_value \\fIwindow \\fR\n\\fBtk accessible get_acc_state \\fIwindow\\fR\n\\fBtk accessible get_acc_action \\fIwindow \\fR\n\\fBtk accessible get_acc_help \\fIwindow\\fR\n\\fBtk accessible add_acc_object \\fIwindow\\fR\n\\fBtk accessible emit_selection_change \\fIwindow\\fR\n\\fBtk accessible emit_focus_change \\fIwindow\\fR\n\\fBtk accessible check_screenreader\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk accessible\\fR command makes core Tk and ttk widgets\naccessible to a screen reader.\n.BE\n.SH INTRODUCTION\n.PP\nAll major computing platforms provide one or more API's to make GUI\napplications accessible to visually-impaired users who work using screen\nreader tools.\nScreen readers provide auditory feedback to users of a GUI application,\nand may provide additional or alternative methods to navigating\nGUI's apart from standard keyboard navigation.\nThe \\fBtk accessible \\fRcommand layers a platform neutral API on top\nof platform-specific API's to support accessibility on Linux/Unix,\nmacOS, and Windows.\n.PP\nThe \\fBtk accessible\\fR command is intended to provide a basic\naccessible-out-of-the-box experience for end users and\nrequires little additional work by developers.\nIf a screen reader is in operation, Tcl/Tk applications will be\naccessible.\nThe \\fBtk accessible \\fRcommand set does allow for additional\ncustomization on the part of developers.\nAnd widgets that are not part of the core Tk widget set can enable\naccessibility by using the tk accessible command set to specific the\naccessible role, name, description, value, state (if applicable), and\naction (if applicable).\n.SH OPERATIONS\n.PP\nThe following operations are available for the \\fBtk accessible\\fR\ncommand:\n.TP\n\\fBtk accessible set_acc_role \\fIwindow value\\fR\n.\nAssigns one of the following accessibility roles to a Tk widget: Button,\nCanvas, Checkbutton, Combobox, Entry, Label, Listbox, Menu, Notebook,\nProgressbar, Scale, Scrollbar, Spinbox, Table, Text, and Tree.\nTk and ttk widgets having similar roles, such as a button and a\nttk::button, will both be assigned the same accessibility role as these\nwidgets are the same from an accessibility standpoint.\n.TP\n\\fBtk accessible set_acc_name \\fIwindow value\\fR\n.\nShort label identifying the widget.\nDefaults to the accessibility role.\n.TP\n\\fBtk accessible set_acc_description\\fI window value\\fR\n.\nLonger string providing additional detail about the widget.\nDepending on the widget, may default to returning the widget's -text\noption or some similar detail.\n.TP\n\\fBtk accessible set_acc_value \\fIwindow value\\fR\n.\nSets the widget's accessibility value.\nFor instance, with a scale widget, will return the current numeric value\nof the scale.\n.TP\n\\fBtk accessible set_acc_state \\fIwindow value\\fR\n.\n\\fI \\fRSets the widget's accessibility state, from one of the\nstandard Tk widget states.\n.TP\n\\fBtk accessible set_acc_action \\fIwindow value\\fR\n.\n\\fI \\fRSets the command associated with the widget, if any.\\fI\n\\fR\n.TP\n\\fBtk accessible set_acc_help \\fIwindow value\\fR\n.\nString providing additional information on the widget and its purpose.\nFor instance, can provide details on specific keyboard navigation for\nthe widget.\n.TP\n\\fBtk accessible get_acc_role \\fIwindow \\fR\n.\nReturns the widget's accessibility role.\n.TP\n\\fBtk accessible get_acc_name \\fIwindow\\fR\n.\nReturns the widget's accessibility name.\n.TP\n\\fBtk accessible get_acc_description \\fIwindow\\fR\n.\nReturns the widget's accessibility description.\n.TP\n\\fBtk accessible get_acc_value \\fIwindow \\fR\n.\nReturns the widget's accessibility value.\n.TP\n\\fBtk accessible get_acc_state \\fIwindow\\fR\n.\nReturns the widget's accessibility state.\n.TP\n\\fBtk accessible get_acc_action \\fIwindow \\fR\n.\nReturns the widget's accessibility action.\n.TP\n\\fBtk accessible get_acc_help \\fIwindow\\fR\n.\nReturns the widget's accessibility help.\\fI \\fR\n.TP\n\\fBtk accessible add_acc_object \\fIwindow\\fR\n.\nRegisters the widget with the platform's accessibility API and\nenables accessibility for the widget.\n.TP\n\\fBtk accessible emit_selection_change \\fIwindow\\fR\n.\nNotifies the system when selection, value or other data associated with\nthe widget changes.\n.TP\n\\fBtk accessible emit_focus_change \\fIwindow\\fR\n.\nNotifies the accessibility system when focus changes.\n.TP\n\\fBtk accessible check_screenreader\\fR\n.\nChecks to see if the system is running a screen reader or other\naccessibility process.\n.PP\n.SH ADDITIONAL NOTES\n.PP\nSome Tk GUI components, such as frames and panedwindows, are not\nincluded in the accessibility API because they are just containers and\ndo not handle actions or data.\nAlso, the canvas is not included in the accessibility API because it is\na purely visual widget; the HTML5 canvas widget is not accessible to web\nAPI's for the same reason.\nDevelopers may choose to provide alternative data to provide information\non the canvas widget, such as labels or help text. Finally,\naccessibility only runs in the main Tk interpreter, because of\npotential conflicts in child interpreters; also, accessibility is not\nsupported under XQuartz (the X11 environment on macOS) because of too\nmany conflicts between the X11 and macOS versions of accessibility.\n.SH KEYWORDS\nwidget, tk\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/attribtable.n",
    "content": ".\\\"\n.\\\" Copyright (c) 2025 Csaba Nemethi\n.\\\"\n.\\\" See the file \"license.terms\" for information on usage and redistribution\n.\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n.\\\"\n.TH tk attribtable n 9.1 \"\" Tk \"Tk Built-in Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nattribtable \\- Create an attribute table, used to query and modify\narbitrary data attached to any widget.\n.SH SYNOPSIS\n\\fBtk attribtable \\fItableName\\fR\n.BE\n.SH DESCRIPTION\n.PP\nThis command creates an attribute table of the name \\fItableName\\fR,\nimplemented as a hash table and accessible as a command in the namespace of\nthe calling context if not fully qualified, and returns the fully qualified\nname of the command just created.\n.PP\nAn attribute table is used to query and modify arbitrary data attached to any\nwidget.  These data are commonly called \\fIattributes\\fR.\n.PP\nIf an attribute table of the given name already exists then it is replaced\nwith the new one and all the attributes of all widgets set using the old table\ninstance will be unset.\n.PP\n\\fBREMARK 1:\\fR  When the \\fItableName\\fR command is deleted (via \\fBrename\\fR\n\\fItableName\\fR \"\" or by deleting the containing namespace), all the\nattributes of all widgets set using this command are automatically unset and\nthe underlying hash table is deleted.  This will free all the memory used by\nthe table.\n.PP\n\\fBREMARK 2:\\fR  When a widget is destroyed, all of its attributes set by all\nattribute table commands are automatically unset.  This will free all the\nmemory used by the widget's attributes.\n.PP\nThe command \\fItableName\\fR created by this command has the signature\n.PP\n.CS\n\\fItableName\\fR \\fBset\\fR|\\fBget\\fR|\\fBunset\\fR|\\fBclear\\fR|\\fBexists\\fR|\\fBnames\\fR|\\fBpathnames\\fR \\fIargs\\fR\n.CE\n.PP\nIn the description of the supported forms below, \\fIpathName\\fR specifies a\nwidget whose attributes are being queried or modified via the \\fItableName\\fR\ncommand.\n.\\\" METHOD: set\n.TP\n\\fItableName\\fR \\fBset\\fR \\fIpathName name value\\fR ?\\fIname value\\fR ...?\n.\nSets (i.e., adds or updates) the attributes identified by the \\fIname\\fR\narguments to the values given by the \\fIvalue\\fR arguments.  Returns an empty\nstring.  Example:\n.RS\n.PP\n.CS\n# Save and then change the button's text\n\\fBtk attribtable\\fR table\ntable \\fBset\\fR .btn prevText [.btn cget -text]\n\\&.btn configure -text \"NewText\"\n.CE\n.RE\n.\\\" METHOD: get\n.TP\n\\fItableName\\fR \\fBget\\fR \\fIpathName\\fR ?\\fIname\\fR ?\\fIdefaultValue\\fR??\n.\nIf \\fIname\\fR is specified then returns the corresponding attribute value, or\nan empty string or \\fIdefaultValue\\fR (if given) if no corresponding value\nexists.  Otherwise returns a list consisting of all attribute names and values\nof the widget \\fIpathName\\fR.  Example:\n.RS\n.PP\n.CS\n# Restore the button's previous text\n\\&.btn configure -text [table \\fBget\\fR .btn prevText]\n.CE\n.RE\n.\\\" METHOD: unset\n.TP\n\\fItableName\\fR \\fBunset\\fR \\fIpathName name\\fR ?\\fIname\\fR ...?\n.\nUnsets the attributes identified by the \\fIname\\fR arguments.  Returns an\nempty string.  Example:\n.RS\n.PP\n.CS\ntable \\fBunset\\fR .btn prevText\n.CE\n.RE\n.\\\" METHOD: clear\n.TP\n\\fItableName\\fR \\fBclear\\fR \\fIpathName\\fR\n.\nUnsets all attributes and removes \\fIpathName\\fR from the list of those\nwidgets that have attributes set via \\fItableName\\fR \\fBset\\fR.  Returns an\nempty string.  Example:\n.RS\n.PP\n.CS\ntable \\fBclear\\fR .btn\n.CE\n.RE\n.\\\" METHOD: exists\n.TP\n\\fItableName\\fR \\fBexists\\fR \\fIpathName\\fR ?\\fIname\\fR?\n.\nIf the optional argument is present then returns \\fB1\\fR if the attribute\nidentified by \\fIname\\fR exists and \\fB0\\fR otherwise.  Without the optional\nargument the return value is \\fB1\\fR if the widget \\fIpathName\\fR has at\nleast one attribute set via \\fItableName\\fR \\fBset\\fR and \\fB0\\fR otherwise.\nExample:\n.RS\n.PP\n.CS\nif [table \\fBexists\\fR .btn prevText] {\n    # Restore the button's previous text\n    \\&.btn configure -text [table \\fBget\\fR .btn prevText]\n}\n.CE\n.RE\n.\\\" METHOD: names\n.TP\n\\fItableName\\fR \\fBnames\\fR \\fIpathName\\fR\n.\nReturns a list consisting of all attribute names of the widget\n\\fIpathName\\fR.  Example:\n.RS\n.PP\n.CS\nputs \"attribute names for .btn: [table \\fBnames\\fR .btn]\"\n.CE\n.RE\n.\\\" METHOD: pathnames\n.TP\n\\fItableName\\fR \\fBpathnames\\fR\n.\nReturns a list consisting of the path names of all widgets that have\nattributes set via \\fItableName\\fR \\fBset\\fR.\nExample:\n.RS\n.PP\n.CS\nputs \"widgets in table: [table \\fBpathnames\\fR]\"\n.CE\n.RE\n.SH KEYWORDS\nwidget, attribute, attribute table\n.\\\" Local Variables:\n.\\\" mode: nroff\n.\\\" fill-column: 78\n.\\\" End:\n"
  },
  {
    "path": "doc/bell.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 2000 Ajuba Solutions.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH bell n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbell \\- Ring a display's bell\n.SH SYNOPSIS\n\\fBbell \\fR?\\fB\\-displayof \\fIwindow\\fR? ?\\fB\\-nice\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis command rings the bell on the display for \\fIwindow\\fR and\nreturns an empty string.\nIf the \\fB\\-displayof\\fR option is omitted, the display of the\napplication's main window is used by default.\nThe command uses the current bell-related settings for the display, which\nmay be modified with programs such as \\fBxset\\fR.\n.PP\nIf \\fB\\-nice\\fR is not specified, this command also resets the screen saver\nfor the screen.  Some screen savers will ignore this, but others will reset\nso that the screen becomes visible again.\n.SH KEYWORDS\nbeep, bell, ring\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/bind.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 1998 Scriptics Corporation.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH bind n 8.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbind \\- Arrange for X events to invoke Tcl scripts\n.SH SYNOPSIS\n\\fBbind\\fI tag\\fR ?\\fIsequence\\fR? ?\\fB+\\fR??\\fIscript\\fR?\n.BE\n.SH \"INTRODUCTION\"\n.PP\nThe \\fBbind\\fR command associates Tcl scripts with X events.\nIf all three arguments are specified, \\fBbind\\fR will\narrange for \\fIscript\\fR (a Tcl script called the\n.QW \"binding script\")\nto be evaluated whenever the event(s) given by \\fIsequence\\fR\noccur in the window(s) identified by \\fItag\\fR.\nIf \\fIscript\\fR is prefixed with a\n.QW + ,\nthen it is appended to\nany existing binding for \\fIsequence\\fR;  otherwise \\fIscript\\fR replaces\nany existing binding.\nIf \\fIscript\\fR is an empty string then the current binding for\n\\fIsequence\\fR is destroyed, leaving \\fIsequence\\fR unbound.\nIn all of the cases where a \\fIscript\\fR argument is provided,\n\\fBbind\\fR returns an empty string.\n.PP\nIf \\fIsequence\\fR is specified without a \\fIscript\\fR, then the\nscript currently bound to \\fIsequence\\fR is returned, or\nan empty string is returned if there is no binding for \\fIsequence\\fR.\nIf neither \\fIsequence\\fR nor \\fIscript\\fR is specified, then the\nreturn value is a list whose elements are all the sequences\nfor which there exist bindings for \\fItag\\fR.\n.PP\nThe \\fItag\\fR argument determines which window(s) the binding applies to.\nIf \\fItag\\fR begins with a dot, as in \\fB.a.b.c\\fR, then it must\nbe the path name for a window; otherwise it may be an arbitrary\nstring.\nEach window has an associated list of tags, and a binding applies\nto a particular window if its tag is among those specified for\nthe window.\nAlthough the \\fBbindtags\\fR command may be used to assign an\narbitrary set of binding tags to a window, the default binding\ntags provide the following behavior:\n.IP \\(bu 3\nIf a tag is the name of an internal window the binding applies\nto that window.\n.IP \\(bu 3\nIf the tag is the name of a class of widgets, such as \\fBButton\\fR,\nthe binding applies to all widgets in that class.\n.IP \\(bu 3\nIf the tag is the name of a toplevel window the binding applies\nto the toplevel window and all its internal windows.\n.IP \\(bu 3\nIf \\fItag\\fR has the value \\fBall\\fR,\nthe binding applies to all windows in the application.\n.SH \"EVENT PATTERNS\"\n.PP\nThe \\fIsequence\\fR argument specifies a sequence of one or more\nevent patterns, with optional white space between the patterns.  Each\nevent pattern may\ntake one of three forms.  In the simplest case it is a single\nprinting ASCII character, such as \\fBa\\fR or \\fB[\\fR.  The character\nmay not be a space character or the character \\fB<\\fR.  This form of\npattern matches a \\fBKey\\fR event for the particular\ncharacter.  The second form of pattern is longer but more general.\nIt has the following syntax:\n.CS\n\\fB<\\fImodifier\\-modifier\\-type\\-detail\\fB>\\fR\n.CE\nThe entire event pattern is surrounded by angle brackets.\nInside the angle brackets are zero or more modifiers, an event\ntype, and an extra piece of information (\\fIdetail\\fR) identifying\na particular button or keysym.  Any of the fields may be omitted,\nas long as at least one of \\fItype\\fR and \\fIdetail\\fR is present.\nThe fields must be separated by white space or dashes.\n.PP\nThe third form of pattern is used to specify a user-defined, named virtual\nevent.  It has the following syntax:\n.CS\n\\fB<<\\fIname\\fB>>\\fR\n.CE\nThe entire virtual event pattern is surrounded by double angle brackets.\nInside the angle brackets is the user-defined name of the virtual event.\nModifiers, such as \\fBShift\\fR or \\fBControl\\fR, may not be combined with a\nvirtual event to modify it.  Bindings on a virtual event may be created\nbefore the virtual event is defined, and if the definition of a virtual\nevent changes dynamically, all windows bound to that virtual event will\nrespond immediately to the new definition.\n.PP\nSome widgets (e.g. \\fBmenu\\fR and \\fBtext\\fR) issue virtual events\nwhen their internal state is updated in some ways.  Please see the\nmanual page for each widget for details.\n.SS \"MODIFIERS\"\n.PP\nModifiers consist of any of the following values:\n.DS\n.ta 6c\n\\fBControl\\fR\t\\fBMod1\\fR, \\fBM1\\fR, \\fBCommand\\fR\n\\fBAlt\\fR\t\\fBMod2\\fR, \\fBM2\\fR, \\fBOption\\fR\n\\fBShift\\fR\t\\fBMod3\\fR, \\fBM3\\fR, \\fBNum\\fR\n\\fBLock\\fR\t\\fBMod4\\fR, \\fBM4\\fR, \\fBFn\\fR\n\\fBExtended\\fR\t\\fBMod5\\fR, \\fBM5\\fR\n\\fBButton1\\fR, \\fBB1\\fR\t\\fBMeta\\fR, \\fBM\\fR\n\\fBButton2\\fR, \\fBB2\\fR\t\\fBDouble\\fR\n\\fBButton3\\fR, \\fBB3\\fR\t\\fBTriple\\fR\n\\fBButton4\\fR, \\fBB4\\fR\t\\fBQuadruple\\fR\n\\fBButton5\\fR, \\fBB5\\fR\n.DE\nWhere more than one value is listed, separated by commas, the values\nare equivalent.\nMost of the modifiers have the obvious X meanings.\nFor example, \\fBButton1\\fR requires that\nbutton 1 be depressed when the event occurs.\nFor a binding to match a given event, the modifiers in the event\nmust include all of those specified in the event pattern.\nAn event may also contain additional modifiers not specified in\nthe binding.\nFor example, if button 1 is pressed while the shift and control keys\nare down, the pattern \\fB<Control\\-Button\\-1>\\fR will match\nthe event, but \\fB<Mod1\\-Button\\-1>\\fR will not.\nIf no modifiers are specified, then any combination of modifiers may\nbe present in the event.\n.PP\n\\fBMeta\\fR and \\fBM\\fR refer to whichever of the\n\\fBM1\\fR through \\fBM5\\fR modifiers is associated with the Meta\nkey(s) on the keyboard (keysyms \\fBMeta_R\\fR and \\fBMeta_L\\fR).\nIf there are no Meta keys, or if they are not associated with any\nmodifiers, then \\fBMeta\\fR and \\fBM\\fR will not match any events.\nSimilarly, the \\fBAlt\\fR modifier refers to whichever modifier\nis associated with the alt key(s) on the keyboard (keysyms\n\\fBAlt_L\\fR and \\fBAlt_R\\fR).\n.PP\nThe \\fBDouble\\fR, \\fBTriple\\fR and \\fBQuadruple\\fR modifiers are a\nconvenience for specifying double mouse clicks and other repeated\nevents. They cause a particular event pattern to be repeated 2, 3 or 4\ntimes, and also place a time and space requirement on the sequence: for a\nsequence of events to match a \\fBDouble\\fR, \\fBTriple\\fR or \\fBQuadruple\\fR\npattern, all of the events must occur close together in time and without\nsubstantial mouse motion in between.  For example, \\fB<Double\\-Button\\-1>\\fR\nis equivalent to \\fB<Button\\-1><Button\\-1>\\fR with the extra time and space\nrequirement.\n.PP\nThe \\fBCommand\\fR, \\fBOption\\fR, \\fBNum\\fR and \\fBFn\\fRmodifiers are\nequivalents of \\fBMod1\\fR up to \\fBMod4\\fR; they correspond to\nMacintosh-specific modifier keys.\n.PP\nThe \\fBExtended\\fR modifier is, at present, specific to Windows.  It\nappears on events that are associated with the keys on the\n.QW \"extended keyboard\" .\nOn a US keyboard, the extended keys include the \\fBAlt\\fR\nand \\fBControl\\fR keys at the right of the keyboard, the cursor keys\nin the cluster to the left of the numeric pad, the \\fBNumLock\\fR key,\nthe \\fBBreak\\fR key, the \\fBPrintScreen\\fR key, and the \\fB/\\fR and\n\\fBEnter\\fR keys in the numeric keypad.\n.SS \"EVENT TYPES\"\n.PP\nThe \\fItype\\fR field may be any of the standard X event types, with a\nfew extra abbreviations.  The \\fItype\\fR field will also accept a\ncouple non-standard X event types that were added to better support\nthe Macintosh and Windows platforms.  Below is a list of all the valid\ntypes; where two names appear together, they are synonyms.\n.DS\n.ta \\w'\\fBButton, ButtonPress\\0\\0\\0\\fR'u +\\w'\\fBKey, KeyPress\\0\\0\\0\\fR'u\n\\fBActivate\\fR\t\\fBDestroy\\fR\t\\fBMap\\fR\n\\fBButton\\fR, \\fBButtonPress\\fR\t\\fBEnter\\fR\t\\fBMapRequest\\fR\n\\fBButtonRelease\\fR\t\\fBExpose\\fR\t\\fBMotion\\fR\n\\fBCirculate\\fR\t\\fBFocusIn\\fR\t\\fBMouseWheel\\fR\n\\fBTouchpadScroll\\fR\t\\fBCirculateRequest\\fR\t\\fBFocusOut\\fR\n\\fBProperty\\fR\t\\fBColormap\\fR\t\\fBGravity\\fR\n\\fBReparent\\fR\t\\fBConfigure\\fR\t\\fBKey\\fR, \\fBKeyPress\\fR\n\\fBResizeRequest\\fR\t\\fBConfigureRequest\\fR\t\\fBKeyRelease\\fR\n\\fBUnmap\\fR   \\fBCreate\\fR\t\\fBLeave\\fR\t\\fBVisibility\\fR\n\\fBDeactivate\\fR\n.DE\nMost of the above events have the same fields and behaviors as events\nin the X Windowing system.  You can find more detailed descriptions of\nthese events in any X window programming book.  A couple of the events\nare extensions to the X event system to support features unique to the\nMacintosh and Windows platforms.  We provide a little more detail on\nthese events here.  These include:\n.IP \"\\fBActivate\\fR, \\fBDeactivate\\fR\" 5\nThese two events are sent to every sub-window of a toplevel when they\nchange state.  In addition to the focus Window, the Macintosh platform\nand Windows platforms have a notion of an active window (which often\nhas but is not required to have the focus).  On the Macintosh, widgets\nin the active window have a different appearance than widgets in\ndeactive windows.  The \\fBActivate\\fR event is sent to all the\nsub-windows in a toplevel when it changes from being deactive to\nactive.  Likewise, the \\fBDeactive\\fR event is sent when the window's\nstate changes from active to deactive.  There are no useful percent\nsubstitutions you would make when binding to these events.\n.IP \\fBMouseWheel\\fR 5\nMany contemporary mice include a mouse wheel, which is used\nfor scrolling documents without using the scrollbars.  By rolling the\nwheel, the system will generate \\fBMouseWheel\\fR events that the\napplication can use to scroll.  The event is routed to the\nwindow currently under the mouse pointer. When the event\nis received you can use the \\fB%D\\fR substitution to get the\n\\fIdelta\\fR field for the event, which is an integer value describing how\nthe mouse wheel has moved.  The smallest value for which the\nsystem will report is defined by the OS.  The sign of the\nvalue determines which direction your widget should scroll.  Positive\nvalues should scroll up and negative values should scroll down.\n.RS\n.PP\nHorizontal scrolling uses \\fBShift-MouseWheel\\fR events, with positive\n\\fB%D\\fR \\fIdelta\\fR substitution indicating left scrolling and\nnegative right scrolling. Horizontal scrolling events are generated\ntilt wheels on some mice.  Horizontal scrolling can also be emulated\nby holding Shift and scrolling vertically.\n.RE\n.IP \"\\fBTouchpadScroll\\fR\" 5\nOn some platforms (currently Windows and macOS) there is support for\nhigh-resolution scrolling devices, such as touchpads.  This is\nprovided via \\fBTouchpadScroll\\fR events.  These events store two\n16 bit delta values in the integer provided by the \\fB%D\\fR\nsubstitution.  The \\fIX\\fR delta is in the high order 16 bits and the\n\\fIY\\fR delta is in the low order 16 bits.  These values can be\nunpacked by using the tk::PreciseScrollDeltas utility procedure.  For\nexample:\n.CS\nlassign [tk::PreciseScrollDeltas %D] deltaX deltaY\n.CE\nThe \\fB$#\\fR substitution is a counter for \\fBTouchpadScroll\\fR events\nwhich can be used by widgets that only support scrolling by units to\nignore some portion of the events.\n.IP \"\\fBKeyPress\\fR, \\fBKeyRelease\\fR\" 5\nThe \\fBKeyPress\\fR and \\fBKeyRelease\\fR events are generated\nwhenever a key is pressed or released.  \\fBKeyPress\\fR and \\fBKeyRelease\\fR\n.IP \"\\fBKey\\fR, \\fBKeyRelease\\fR\" 5\nThe \\fBKey\\fR and \\fBKeyRelease\\fR events are generated\nwhenever a key is pressed or released.  \\fBKey\\fR and \\fBKeyRelease\\fR\nevents are sent to the window which currently has the keyboard focus.\n.IP \"\\fBButton\\fR, \\fBButtonRelease\\fR, \\fBMotion\\fR\" 5\nThe \\fBButton\\fR and \\fBButtonRelease\\fR events\nare generated when the user presses or releases a mouse button.\n\\fBMotion\\fR events are generated whenever the pointer is moved.\n\\fBButton\\fR, \\fBButtonRelease\\fR, and \\fBMotion\\fR events are\nnormally sent to the window containing the pointer.\n.RS\n.PP\nWhen a mouse button is pressed, the window containing the pointer\nautomatically obtains a temporary pointer grab.\nSubsequent \\fBButton\\fR, \\fBButtonRelease\\fR, and \\fBMotion\\fR\nevents will be sent to that window,\nregardless of which window contains the pointer,\nuntil all buttons have been released.\n.RE\n.IP \\fBConfigure\\fR 5\nA \\fBConfigure\\fR event is sent to a window whenever its\nsize, position, or border width changes, and sometimes\nwhen it has changed position in the stacking order.\n.IP \"\\fBMap\\fR, \\fBUnmap\\fR\" 5\nThe \\fBMap\\fR and \\fBUnmap\\fR events are generated whenever the mapping\nstate of a window changes.\n.RS\n.PP\nWindows are created in the unmapped state.\nTop-level windows become mapped when they transition to the\n\\fBnormal\\fR state, and are unmapped in the \\fBwithdrawn\\fR\nand \\fBiconic\\fR states.\nOther windows become mapped when they are placed under control\nof a geometry manager (for example \\fBpack\\fR or \\fBgrid\\fR).\n.PP\nA window is \\fIviewable\\fR only if it and all of its ancestors are mapped.\nNote that geometry managers typically do not map their children until\nthey have been mapped themselves, and unmap all children\nwhen they become unmapped; hence in Tk \\fBMap\\fR and \\fBUnmap\\fR\nevents indicate whether or not a window is viewable.\n.RE\n.IP \\fBVisibility\\fR 5\nA window is said to be \\fIobscured\\fR when another window\nabove it in the stacking order fully or partially overlaps it.\n\\fBVisibility\\fR events are generated whenever a window's\nobscurity state changes; the \\fIstate\\fR field (\\fB%s\\fR)\nspecifies the new state.\n.IP \\fBExpose\\fR 5\nAn \\fBExpose\\fR event is generated whenever all or part of a\nwindow should be redrawn (for example, when a window is\nfirst mapped or if it becomes unobscured).\nIt is normally not necessary for client applications to\nhandle \\fBExpose\\fR events, since Tk handles them internally.\n.IP \\fBDestroy\\fR 5\nA \\fBDestroy\\fR event is delivered to a window when\nit is destroyed.\n.RS\n.PP\nWhen the \\fBDestroy\\fR event is delivered\nto a widget, it is in a\n.QW half-dead\nstate: the widget still exists, but operations that involve it\nmay return invalid results, or return an error.\n.RE\n.IP \"\\fBFocusIn\\fR, \\fBFocusOut\\fR\" 5\nThe \\fBFocusIn\\fR and \\fBFocusOut\\fR events are generated\nwhenever the keyboard focus changes.\nA \\fBFocusOut\\fR event is sent to the old focus window,\nand a \\fBFocusIn\\fR event is sent to the new one.\n.RS\n.PP\nIn addition,\nif the old and new focus windows do not share a common parent,\n.QW \"virtual crossing\"\nfocus events are sent to the intermediate windows in the hierarchy.\nThus a \\fBFocusIn\\fR event indicates\nthat the target window or one of its descendants has acquired the focus,\nand a \\fBFocusOut\\fR event indicates that the focus\nhas been changed to a window outside the target window's hierarchy.\n.PP\nThe keyboard focus may be changed explicitly by a call to \\fBfocus\\fR,\nor implicitly by the window manager.\n.RE\n.IP \"\\fBEnter\\fR, \\fBLeave\\fR\" 5\nAn \\fBEnter\\fR event is sent to a window when the pointer\nenters that window, and a \\fBLeave\\fR event is sent when\nthe pointer leaves it.\n.RS\n.PP\nIf there is a pointer grab in effect, \\fBEnter\\fR and \\fBLeave\\fR\nevents are only delivered to the window owning the grab.\n.PP\nIn addition, when the pointer moves\nbetween two windows, \\fBEnter\\fR and \\fBLeave\\fR\n.QW \"virtual crossing\"\nevents are sent to intermediate windows\nin the hierarchy in the same manner as for \\fBFocusIn\\fR and\n\\fBFocusOut\\fR events.\n.RE\n.IP \\fBProperty\\fR\nA \\fBProperty\\fR event is sent to a window whenever an X property\nbelonging to that window is changed or deleted.\n\\fBProperty\\fR events are not normally delivered to Tk applications as\nthey are handled by the Tk core.\n.IP \\fBColormap\\fR\nA \\fBColormap\\fR event is generated whenever the colormap\nassociated with a window has been changed, installed, or uninstalled.\n.RS\n.PP\nWidgets may be assigned a private colormap by\nspecifying a \\fB\\-colormap\\fR option; the window manager\nis responsible for installing and uninstalling colormaps\nas necessary.\n.PP\nNote that Tk provides no useful details for this event type.\n.RE\n'\\\" The following events were added in TIP#47\n.IP \"\\fBMapRequest\\fR, \\fBCirculateRequest\\fR, \\fBResizeRequest\\fR, \\fBConfigureRequest\\fR, \\fBCreate\\fR\" 5\nThese events are not normally delivered to Tk applications.\nThey are included for completeness, to make it possible to\nwrite X11 window managers in Tk.\n(These events are only delivered when a client has\nselected \\fBSubstructureRedirectMask\\fR on a window;\nthe Tk core does not use this mask.)\n.IP \"\\fBGravity\\fR, \\fBReparent\\fR, \\fBCirculate\\fR\" 5\nThe events \\fBGravity\\fR and \\fBReparent\\fR\nare not normally delivered to Tk applications.\nThey are included for completeness.\n.RS\n.PP\nA \\fBCirculate\\fR event indicates that the window has moved\nto the top or to the bottom of the stacking order as\na result of an \\fBXCirculateSubwindows\\fR protocol request.\nNote that the stacking order may be changed for other reasons\nwhich do not generate a \\fBCirculate\\fR event, and that\nTk does not use \\fBXCirculateSubwindows()\\fR internally.\nThis event type is included only for completeness;\nthere is no reliable way to track changes to a window's\nposition in the stacking order.\n.RE\n.SS \"EVENT DETAILS\"\n.PP\nThe last part of a long event specification is \\fIdetail\\fR.  In the\ncase of a \\fBButton\\fR or \\fBButtonRelease\\fR event, it is the\nnumber of a button (1\\-9).  If a button number is given, then only an\nevent on that particular button will match;  if no button number is\ngiven, then an event on any button will match.  Note:  giving a\nspecific button number is different than specifying a button modifier;\nin the first case, it refers to a button being pressed or released,\nwhile in the second it refers to some other button that is already\ndepressed when the matching event occurs.  If a button\nnumber is given then \\fItype\\fR may be omitted:  if will default\nto \\fBButton\\fR.  For example, the specifier \\fB<1>\\fR\nis equivalent to \\fB<Button\\-1>\\fR.\n.PP\nIf the event type is \\fBKey\\fR or \\fBKeyRelease\\fR, then\n\\fIdetail\\fR may be specified in the form of an X keysym.  Keysyms\nare textual specifications for particular keys on the keyboard;\nthey include all the alphanumeric ASCII characters (e.g.\n.QW a\nis the keysym for the ASCII character\n.QW a ),\nplus descriptions for non-alphanumeric characters\n.PQ comma \"is the keysym for the comma character\" ,\nplus descriptions for all the non-ASCII keys on the keyboard (e.g.\n.QW Shift_L\nis the keysym for the left shift key, and\n.QW F1\nis the keysym for the F1 function key, if it exists).  The\ncomplete list of keysyms is not presented here;  it is\navailable in other X documentation and may vary from system to\nsystem.\nIf necessary, you can use the \\fB%K\\fR notation described below\nto print out the keysym name for a particular key.\nIf a keysym \\fIdetail\\fR is given, then the\n\\fItype\\fR field may be omitted;  it will default to \\fBKey\\fR.\nFor example, \\fB<Control\\-comma>\\fR is equivalent to\n\\fB<Control\\-Key\\-comma>\\fR.\n.SH \"BINDING SCRIPTS AND SUBSTITUTIONS\"\n.PP\nThe \\fIscript\\fR argument to \\fBbind\\fR is a Tcl script, called the\n.QW \"binding script\",\nwhich will be executed whenever the given event sequence occurs.\n\\fICommand\\fR will be executed in the same interpreter that the\n\\fBbind\\fR command was executed in, and it will run at global\nlevel (only global variables will be accessible).\nIf \\fIscript\\fR contains\nany \\fB%\\fR characters, then the script will not be\nexecuted directly.  Instead, a new script will be\ngenerated by replacing each \\fB%\\fR, and the character following\nit, with information from the current event.  The replacement\ndepends on the character following the \\fB%\\fR, as defined in the\nlist below.  Unless otherwise indicated, the\nreplacement string is the decimal value of the given field from\nthe current event.\nSome of the substitutions are only valid for\ncertain types of events;  if they are used for other types of events\nthe value substituted is undefined.\n.IP \\fB%%\\fR 5\nReplaced with a single percent.\n.IP \\fB%#\\fR 5\nThe number of the last client request processed by the server\n(the \\fIserial\\fR field from the event).  Valid for all event\ntypes.\n.IP \\fB%a\\fR 5\nThe \\fIabove\\fR field from the event,\nformatted as a hexadecimal number.\nValid only for \\fBConfigure\\fR events.\nIndicates the sibling window immediately below the receiving window\nin the stacking order, or \\fB0\\fR if the receiving window is at the\nbottom.\n.IP \\fB%b\\fR 5\nThe number of the button that was pressed or released.  Valid only\nfor \\fBButton\\fR and \\fBButtonRelease\\fR events.\n.IP \\fB%c\\fR 5\nThe \\fIcount\\fR field from the event.  Valid only for \\fBExpose\\fR events.\nIndicates that there are \\fIcount\\fR pending \\fBExpose\\fR events which have not\nyet been delivered to the window.\n.IP \\fB%d\\fR 5\nThe \\fIdetail\\fR or \\fIuser_data\\fR\nfield from the event.  The \\fB%d\\fR is replaced by\na string identifying the detail.  For \\fBEnter\\fR,\n\\fBLeave\\fR, \\fBFocusIn\\fR, and \\fBFocusOut\\fR events,\nthe string will be one of the following:\n.RS\n.DS\n.ta 6c\n\\fBNotifyAncestor\\fR\t\\fBNotifyNonlinearVirtual\\fR\n\\fBNotifyDetailNone\\fR\t\\fBNotifyPointer\\fR\n\\fBNotifyInferior\\fR\t\\fBNotifyPointerRoot\\fR\n\\fBNotifyNonlinear\\fR\t\\fBNotifyVirtual\\fR\n.DE\nFor \\fBConfigureRequest\\fR events, the string will be one of:\n.DS\n.ta 6c\n\\fBAbove\\fR\t\\fBOpposite\\fR\n\\fBBelow\\fR\t\\fBNone\\fR\n\\fBBottomIf\\fR\t\\fBTopIf\\fR\n.DE\nFor virtual events, the string will be whatever value is stored in the\n\\fIuser_data\\fR field when the event was created (typically with\n\\fBevent generate\\fR), or the empty string if the field is NULL.\nVirtual events corresponding to key sequence presses (see \\fBevent\nadd\\fR for details) set the \\fIuser_data\\fR to NULL.\nFor events other than these, the substituted string is undefined.\n.RE\n.IP \\fB%f\\fR 5\nThe \\fIfocus\\fR field from the event (\\fB0\\fR or \\fB1\\fR).  Valid only\nfor \\fBEnter\\fR and \\fBLeave\\fR events.  \\fB1\\fR if the receiving\nwindow is the focus window or a descendant of the focus window,\n\\fB0\\fR otherwise.\n.IP \\fB%h\\fR 5\nThe \\fIheight\\fR field from the event.  Valid for the \\fBConfigure\\fR,\n\\fBConfigureRequest\\fR, \\fBCreate\\fR, \\fBResizeRequest\\fR, and\n\\fBExpose\\fR events.\nIndicates the new or requested height of the window.\n.IP \\fB%i\\fR 5\nThe \\fIwindow\\fR field from the event, represented as a hexadecimal\ninteger.  Valid for all event types.\n.IP \\fB%k\\fR 5\nThe \\fIkeycode\\fR field from the event.  Valid only for \\fBKey\\fR\nand \\fBKeyRelease\\fR events.\n.IP \\fB%m\\fR 5\nThe \\fImode\\fR field from the event.  The substituted string is one of\n\\fBNotifyNormal\\fR, \\fBNotifyGrab\\fR, \\fBNotifyUngrab\\fR, or\n\\fBNotifyWhileGrabbed\\fR.  Valid only for \\fBEnter\\fR,\n\\fBFocusIn\\fR, \\fBFocusOut\\fR, and \\fBLeave\\fR events.\n.IP \\fB%o\\fR 5\nThe \\fIoverride_redirect\\fR field from the event.  Valid only for\n\\fBMap\\fR, \\fBReparent\\fR, and \\fBConfigure\\fR events.\n.IP \\fB%p\\fR 5\nThe \\fIplace\\fR field from the event, substituted as one of the\nstrings \\fBPlaceOnTop\\fR or \\fBPlaceOnBottom\\fR.  Valid only\nfor \\fBCirculate\\fR and \\fBCirculateRequest\\fR events.\n.IP \\fB%s\\fR 5\nThe \\fIstate\\fR field from the event.  For \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBKey\\fR, \\fBKeyRelease\\fR,\n\\fBLeave\\fR, and \\fBMotion\\fR events, a decimal string\nis substituted.  For \\fBVisibility\\fR, one of the strings\n\\fBVisibilityUnobscured\\fR, \\fBVisibilityPartiallyObscured\\fR,\nand \\fBVisibilityFullyObscured\\fR is substituted.\nFor \\fBProperty\\fR events, substituted with\neither the string \\fBNewValue\\fR (indicating that the property\nhas been created or modified) or \\fBDelete\\fR (indicating that\nthe property has been removed).\n.IP \\fB%t\\fR 5\nThe \\fItime\\fR field from the event.\nThis is the X server timestamp (typically the time since\nthe last server reset) in milliseconds, when the event occurred.\nValid for most events.\n.IP \\fB%w\\fR 5\nThe \\fIwidth\\fR field from the event.\nIndicates the new or requested width of the window.\nValid only for\n\\fBConfigure\\fR, \\fBConfigureRequest\\fR, \\fBCreate\\fR,\n\\fBResizeRequest\\fR, and \\fBExpose\\fR events.\n.IP \"\\fB%x\\fR, \\fB%y\\fR\" 5\nThe \\fIx\\fR and \\fIy\\fR fields from the event.\nFor \\fBButton\\fR, \\fBButtonRelease\\fR, \\fBMotion\\fR,\n\\fBKey\\fR, \\fBKeyRelease\\fR, and \\fBMouseWheel\\fR events,\n\\fB%x\\fR and \\fB%y\\fR indicate the position of the mouse pointer\nrelative to the receiving window.\nFor key events on the Macintosh these are the coordinates of the\nmouse at the moment when an X11 KeyEvent is sent to Tk, which could\nbe slightly later than the time of the physical press or release.\nFor \\fBEnter\\fR and \\fBLeave\\fR events, the position where the\nmouse pointer crossed the window, relative to the receiving window.\nFor \\fBConfigure\\fR and \\fBCreate\\fR requests, the \\fIx\\fR and \\fIy\\fR\ncoordinates of the window relative to its parent window.\n.IP \\fB%A\\fR 5\nSubstitutes the UNICODE character corresponding to the event, or\nthe empty string if the event does not correspond to a UNICODE character\n(e.g. the shift key was pressed). On X11, \\fBXmbLookupString\\fR (or\n\\fBXLookupString\\fR when input method support is turned off) does all\nthe work of translating from the event to a UNICODE character.\nOn X11, valid only for \\fBKey\\fR event. On Windows and macOS/aqua,\nvalid only for \\fBKey\\fR and \\fBKeyRelease\\fR events.\n.IP \\fB%B\\fR 5\nThe \\fIborder_width\\fR field from the event.  Valid only for\n\\fBConfigure\\fR, \\fBConfigureRequest\\fR, and \\fBCreate\\fR events.\n.IP \\fB%D\\fR 5\nThis reports the \\fIdelta\\fR value of a \\fBMouseWheel\\fR event.  The\n\\fIdelta\\fR value represents the rotation units the mouse wheel has\nbeen moved. The sign of the value represents the direction the mouse\nwheel was scrolled.\n.IP \\fB%E\\fR 5\nThe \\fIsend_event\\fR field from the event.  Valid for all event types.\n\\fB0\\fR indicates that this is a\n.QW normal\nevent, \\fB1\\fR indicates that it is a\n.QW synthetic\nevent generated by \\fBSendEvent\\fR.\n.IP \\fB%K\\fR 5\nThe keysym corresponding to the event, substituted as a textual\nstring.  Valid only for \\fBKey\\fR and \\fBKeyRelease\\fR events.\n.IP \\fB%M\\fR 5\nThe number of script-based binding patterns matched so far for the\nevent.  Valid for all event types.\n.IP \\fB%N\\fR 5\nThe keysym corresponding to the event, substituted as a decimal\nnumber.  Valid only for \\fBKey\\fR and \\fBKeyRelease\\fR events.\n.IP \\fB%P\\fR 5\nThe name of the property being updated or deleted (which\nmay be converted to an XAtom using \\fBwinfo atom\\fR.) Valid\nonly for \\fBProperty\\fR events.\n.IP \\fB%R\\fR 5\nThe \\fIroot\\fR window identifier from the event.  Valid only for\nevents containing a \\fIroot\\fR field.\n.IP \\fB%S\\fR 5\nThe \\fIsubwindow\\fR window identifier from the event,\nformatted as a hexadecimal number.\nValid only for events containing a \\fIsubwindow\\fR field.\n.IP \\fB%T\\fR 5\nThe \\fItype\\fR field from the event.  Valid for all event types.\n.IP \\fB%W\\fR 5\nThe path name of the window to which the event was reported (the\n\\fIwindow\\fR field from the event).  Valid for all event types.\n.IP \"\\fB%X\\fR, \\fB%Y\\fR\" 5\nThe \\fIx_root\\fR and  \\fIy_root\\fR fields from the event.\nIf a virtual-root window manager is being used then the substituted\nvalues are the corresponding x-coordinate and y-coordinate in the virtual root.\nValid only for\n\\fBButton\\fR, \\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBKey\\fR,\n\\fBKeyRelease\\fR, \\fBLeave\\fR and \\fBMotion\\fR events.\nSame meaning as \\fB%x\\fR and \\fB%y\\fR, except relative to the (virtual) root\nwindow.\n.LP\nThe replacement string for a %-replacement is formatted as a proper\nTcl list element.\nThis means that spaces or special characters such as \\fB$\\fR and\n\\fB{\\fR may be preceded by backslashes.\nThis guarantees that the string will be passed through the Tcl\nparser when the binding script is evaluated.\nMost replacements are numbers or well-defined strings such\nas \\fBAbove\\fR;  for these replacements no special formatting\nis ever necessary.\nThe most common case where reformatting occurs is for the \\fB%A\\fR\nsubstitution.  For example, if \\fIscript\\fR is\n.CS\n\\fBinsert\\0%A\\fR\n.CE\nand the character typed is an open square bracket, then the script\nactually executed will be\n.CS\n\\fBinsert\\0\\e[\\fR\n.CE\nThis will cause the \\fBinsert\\fR to receive the original replacement\nstring (open square bracket) as its first argument.\nIf the extra backslash had not been added, Tcl would not have been\nable to parse the script correctly.\n.SH \"MULTIPLE MATCHES\"\n.PP\nIt is possible for several bindings to match a given X event.\nIf the bindings are associated with different \\fItag\\fR's,\nthen each of the bindings will be executed, in order.\nBy default, a binding for the widget will be executed first, followed\nby a class binding, a binding for its toplevel, and\nan \\fBall\\fR binding.\nThe \\fBbindtags\\fR command may be used to change this order for\na particular window or to associate additional binding tags with\nthe window.\n.PP\nThe \\fBcontinue\\fR and \\fBbreak\\fR commands may be used inside a\nbinding script to control the processing of matching scripts.\nIf \\fBcontinue\\fR is invoked within a binding script, then this\nbinding script, including all other\n.QW +\nappended scripts, is terminated but Tk will continue processing\nbinding scripts associated with other \\fItag\\fR's.\nIf the \\fBbreak\\fR command is invoked within a binding script,\nthen that script terminates and no other scripts will be invoked\nfor the event.\n.PP\nWithin a script called from the binding script, \\fBreturn\\fR\n\\fB\\-code ok\\fR may be used to continue processing (including\n.QW +\nappended scripts), or \\fBreturn\\fR \\fB\\-code break\\fR may be used to\nstop processing all other binding scripts.\n.PP\nIf more than one binding matches a particular event and they\nhave the same \\fItag\\fR, then the most specific binding\nis chosen and its script is evaluated.\nThe following tests are applied, in order, to determine which of\nseveral matching sequences is more specific:\n.RS\n.IP (a)\nan event pattern that specifies a specific button or key is more specific\nthan one that does not;\n.IP (b)\na sequence with the most highest-ordered patterns (in term of highest\nrepetition count) is more specific than a sequence with less\nhighest-ordered patterns;\n.IP (c)\nif the modifiers specified in one pattern are a subset of the\nmodifiers in another pattern, then the pattern with more modifiers\nis more specific;\n.IP (d)\na virtual event whose physical pattern matches the sequence is less\nspecific than the same physical pattern that is not associated with a\nvirtual event;\n.IP (e)\ngiven a sequence that matches two or more virtual events, one\nof the virtual events will be chosen, but the order is undefined.\n.RE\n.PP\nIf the matching sequences contain more than one event, then tests\n(c)\\-(e) are applied in order from the most recent event to the least recent\nevent in the sequences.  If these tests fail to determine a winner, then the\nmost recently registered sequence is the winner.\n.PP\nIf there are two (or more) virtual events that are both triggered by the\nsame sequence, and both of those virtual events are bound to the same window\ntag, then only one of the virtual events will be triggered, and it will\nbe picked at random:\n.CS\nevent add <<Paste>> <Control\\-y>\nevent add <<Paste>> <Button\\-2>\nevent add <<Scroll>> <Button\\-2>\n\\fBbind\\fR Entry <<Paste>> {puts Paste}\n\\fBbind\\fR Entry <<Scroll>> {puts Scroll}\n.CE\nIf the user types Control\\-y, the \\fB<<Paste>>\\fR binding\nwill be invoked, but if the user presses button 2 then one of\neither the \\fB<<Paste>>\\fR or the \\fB<<Scroll>>\\fR bindings will\nbe invoked, but exactly which one gets invoked is undefined.\n.PP\nIf an X event does not match any of the existing bindings, then the\nevent is ignored.\nAn unbound event is not considered to be an error.\n.SH \"MULTI-EVENT SEQUENCES AND IGNORED EVENTS\"\n.PP\nWhen a \\fIsequence\\fR specified in a \\fBbind\\fR command contains\nmore than one event pattern, then its script is executed whenever\nthe recent events (leading up to and including the current event)\nmatch the given sequence.  This means, for example, that if button 1 is\nclicked repeatedly the sequence \\fB<Double\\-Button\\-1>\\fR will match\neach button press but the first.\nIf extraneous events that would prevent a match occur in the middle\nof an event sequence then the extraneous events are\nignored unless they are \\fBKey\\fR or \\fBButton\\fR events.\nFor example, \\fB<Double\\-Button\\-1>\\fR will match a sequence of\npresses of button 1, even though there will be \\fBButtonRelease\\fR\nevents (and possibly \\fBMotion\\fR events) between the\n\\fBButton\\fR events.\nFurthermore, a \\fBKey\\fR event may be preceded by any number\nof other \\fBKey\\fR events for modifier keys without the\nmodifier keys preventing a match.\nFor example, the event sequence \\fBaB\\fR will match a press of the\n\\fBa\\fR key, a release of the \\fBa\\fR key, a press of the \\fBShift\\fR\nkey, and a press of the \\fBb\\fR key:  the press of \\fBShift\\fR is\nignored because it is a modifier key.\nFinally, if several \\fBMotion\\fR events occur in a row, only\nthe last one is used for purposes of matching binding sequences.\n.SH \"ERRORS\"\n.PP\nIf an error occurs in executing the script for a binding then the\n\\fBbgerror\\fR mechanism is used to report the error.\nThe \\fBbgerror\\fR command will be executed at global level\n(outside the context of any Tcl procedure).\n.SH \"EXAMPLES\"\n.PP\nArrange for a string describing the motion of the mouse to be printed\nout when the mouse is double-clicked:\n.CS\n\\fBbind\\fR . <Double-1> {\n    puts \"hi from (%x,%y)\"\n}\n.CE\n.PP\nA little GUI that displays what the keysym name of the last key\npressed is:\n.CS\nset keysym \"Press any key\"\npack [label .l -textvariable keysym -padx 2m -pady 1m]\n\\fBbind\\fR . <Key> {\n    set keysym \"You pressed %K\"\n}\n.CE\n.SH \"SEE ALSO\"\nbgerror(n), bindtags(n), event(n), focus(n), grab(n), keysyms(n)\n.SH KEYWORDS\nbinding, event\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/bindtags.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH bindtags n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbindtags \\- Determine which bindings apply to a window, and order of evaluation\n.SH SYNOPSIS\n\\fBbindtags \\fIwindow \\fR?\\fItagList\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nWhen a binding is created with the \\fBbind\\fR command, it is\nassociated either with a particular window such as \\fB.a.b.c\\fR,\na class name such as \\fBButton\\fR, the keyword \\fBall\\fR, or any\nother string.\nAll of these forms are called \\fIbinding tags\\fR.\nEach window contains a list of binding tags that determine how\nevents are processed for the window.\nWhen an event occurs in a window, it is applied to each of the\nwindow's tags in order:  for each tag, the most specific binding\nthat matches the given tag and event is executed.\nSee the \\fBbind\\fR command for more information on the matching\nprocess.\n.PP\nBy default, each window has four binding tags consisting of the\nname of the window, the window's class name, the name of the window's\nnearest toplevel ancestor, and \\fBall\\fR, in that order.\nToplevel windows have only three tags by default, since the toplevel\nname is the same as that of the window.\nThe \\fBbindtags\\fR command allows the binding tags for a window to be\nread and modified.\n.PP\nIf \\fBbindtags\\fR is invoked with only one argument, then the\ncurrent set of binding tags for \\fIwindow\\fR is returned as a list.\nIf the \\fItagList\\fR argument is specified to \\fBbindtags\\fR,\nthen it must be a proper list; the tags for \\fIwindow\\fR are changed\nto the elements of the list.\nThe elements of \\fItagList\\fR may be arbitrary strings;  however,\nany tag starting with a dot is treated as the name of a window;  if\nno window by that name exists at the time an event is processed,\nthen the tag is ignored for that event.\nThe order of the elements in \\fItagList\\fR determines the order in\nwhich binding scripts are executed in response to events.\nFor example, the command\n.CS\n\\fBbindtags .b {all . Button .b}\\fR\n.CE\nreverses the order in which binding scripts will be evaluated for\na button named \\fB.b\\fR so that \\fBall\\fR bindings are invoked\nfirst, following by bindings for \\fB.b\\fR's toplevel\n.PQ . \"\" ,\nfollowed by class bindings, followed by bindings for \\fB.b\\fR.\nIf \\fItagList\\fR is an empty list then the binding tags for \\fIwindow\\fR\nare returned to the default state described above.\n.PP\nThe \\fBbindtags\\fR command may be used to introduce arbitrary\nadditional binding tags for a window, or to remove standard tags.\nFor example, the command\n.CS\n\\fBbindtags .b {.b TrickyButton . all}\\fR\n.CE\nreplaces the \\fBButton\\fR tag for \\fB.b\\fR with \\fBTrickyButton\\fR.\nThis means that the default widget bindings for buttons, which are\nassociated with the \\fBButton\\fR tag, will no longer apply to \\fB.b\\fR,\nbut any bindings associated with \\fBTrickyButton\\fR (perhaps some\nnew button behavior) will apply.\n.SH EXAMPLE\n.PP\nIf you have a set of nested \\fBframe\\fR widgets and you want events\nsent to a \\fBbutton\\fR widget to also be delivered to all the widgets\nup to the current \\fBtoplevel\\fR (in contrast to Tk's default\nbehavior, where events are not delivered to those intermediate\nwindows) to make it easier to have accelerators that are only active\nfor part of a window, you could use a helper procedure like this to\nhelp set things up:\n.CS\nproc setupBindtagsForTreeDelivery {widget} {\n    set tags [list $widget [winfo class $widget]]\n    set w $widget\n    set t [winfo toplevel $w]\n    while {$w ne $t} {\n        set w [winfo parent $w]\n        lappend tags $w\n    }\n    lappend tags all\n    \\fBbindtags\\fR $widget $tags\n}\n.CE\n.SH \"SEE ALSO\"\nbind(n)\n.SH KEYWORDS\nbinding, event, tag\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/bitmap.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH bitmap n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbitmap \\- Images that display two colors\n.SH SYNOPSIS\n.nf\n\\fBimage create bitmap \\fR?\\fIname\\fR? ?\\fIoptions\\fR?\n\n\\fIimageName \\fBcget\\fI option\\fR\n\\fIimageName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nA bitmap is an image whose pixels can display either of two colors\nor be transparent.\nA bitmap image is defined by four things:  a background color,\na foreground color, and two bitmaps, called the \\fIsource\\fR\nand the \\fImask\\fR.\nEach of the bitmaps specifies 0/1 values for a rectangular\narray of pixels, and the two bitmaps must have the same\ndimensions.\nFor pixels where the mask is zero, the image displays nothing,\nproducing a transparent effect.\nFor other pixels, the image displays the foreground color if\nthe source data is one and the background color if the source\ndata is zero.\n.SH \"CREATING BITMAPS\"\n.PP\nLike all images, bitmaps are created using the \\fBimage create\\fR\ncommand.\nBitmaps support the following \\fIoptions\\fR:\n.\\\" OPTION: -background\n.TP\n\\fB\\-background \\fIcolor\\fR\n.\nSpecifies a background color for the image in any of the standard\nways accepted by Tk.  If this option is set to an empty string\nthen the background pixels will be transparent.  This effect\nis achieved by using the source bitmap as the mask bitmap, ignoring\nany \\fB\\-maskdata\\fR or \\fB\\-maskfile\\fR options.\n.\\\" OPTION: -data\n.TP\n\\fB\\-data \\fIstring\\fR\n.\nSpecifies the contents of the source bitmap as a string.\nThe string must adhere to X11 bitmap format (e.g., as generated\nby the \\fBbitmap\\fR program).\nIf both the \\fB\\-data\\fR and \\fB\\-file\\fR options are specified,\nthe \\fB\\-data\\fR option takes precedence.\n.\\\" OPTION: -file\n.TP\n\\fB\\-file \\fIname\\fR\n.\n\\fIname\\fR gives the name of a file whose contents define the\nsource bitmap.\nThe file must adhere to X11 bitmap format (e.g., as generated\nby the \\fBbitmap\\fR program).\n.\\\" OPTION: -foreground\n.TP\n\\fB\\-foreground \\fIcolor\\fR\n.\nSpecifies a foreground color for the image in any of the standard\nways accepted by Tk.\n.\\\" OPTION: -maskdata\n.TP\n\\fB\\-maskdata \\fIstring\\fR\n.\nSpecifies the contents of the mask as a string.\nThe string must adhere to X11 bitmap format (e.g., as generated\nby the \\fBbitmap\\fR program).\nIf both the \\fB\\-maskdata\\fR and \\fB\\-maskfile\\fR options are specified,\nthe \\fB\\-maskdata\\fR option takes precedence.\n.\\\" OPTION: -maskfile\n.TP\n\\fB\\-maskfile \\fIname\\fR\n.\n\\fIname\\fR gives the name of a file whose contents define the\nmask.\nThe file must adhere to X11 bitmap format (e.g., as generated\nby the \\fBbitmap\\fR program).\n.SH \"IMAGE COMMAND\"\n.PP\nWhen a bitmap image is created, Tk also creates a new command\nwhose name is the same as the image.\nThis command may be used to invoke various operations\non the image.\nIt has the following general form:\n.CS\n\\fIimageName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for bitmap images:\n.\\\" METHOD: cget\n.TP\n\\fIimageName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the\n\\fBimage create\\fR \\fBbitmap\\fR command.\n.\\\" METHOD: configure\n.TP\n\\fIimageName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options for the image.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIimageName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the\n\\fBimage create\\fR \\fBbitmap\\fR command.\n.SH KEYWORDS\nbitmap, image\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/busy.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1993-1998 Lucent Technologies, Inc.\n'\\\" Copyright (c) 2008 Jos Decoster\n'\\\"\n'\\\" Permission to use, copy, modify, and distribute this software and its\n'\\\" documentation for any purpose and without fee is hereby granted, provided\n'\\\" that the above copyright notice appear in all copies and that both that\n'\\\" the copyright notice and warranty disclaimer appear in supporting\n'\\\" documentation, and that the names of Lucent Technologies any of their\n'\\\" entities not be used in advertising or publicity pertaining to\n'\\\" distribution of the software without specific, written prior permission.\n'\\\"\n'\\\" Lucent Technologies disclaims all warranties with regard to this software,\n'\\\" including all implied warranties of merchantability and fitness. In no\n'\\\" event shall Lucent Technologies be liable for any special, indirect or\n'\\\" consequential damages or any damages whatsoever resulting from loss of\n'\\\" use, data or profits, whether in an action of contract, negligence or\n'\\\" other tortuous action, arising out of or in connection with the use or\n'\\\" performance of this software.\n'\\\"\n'\\\" BLT::busy command created by George Howlett.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH busy n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbusy \\- Make Tk widgets busy, temporarily blocking user interactions\n.SH SYNOPSIS\n.nf\n\\fBtk busy\\fI window \\fR?\\fIoptions\\fR?\n\\fBtk busy busywindow \\fIwindow\\fR\n\\fBtk busy hold\\fI window \\fR?\\fIoptions\\fR?\n\\fBtk busy configure \\fIwindow\\fR ?\\fIoption value\\fR?...\n\\fBtk busy forget\\fI window \\fR?\\fIwindow \\fR?...\n\\fBtk busy current\\fR ?\\fIpattern\\fR?\n\\fBtk busy status \\fIwindow\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk busy\\fR command provides a simple means to block mouse pointer events\nfrom Tk widgets, while overriding the widget's cursor with a configurable busy\ncursor. Note this command does not prevent keyboard events from being sent to\nthe widgets made busy.\n.SH INTRODUCTION\n.PP\nThere are many times in applications where you want to temporarily restrict\nwhat actions the user can take. For example, an application could have a\n.QW Run\nbutton that when pressed causes some processing to occur. However, while the\napplication is busy processing, you probably don't want the user to be\nable to click the\n.QW Run\nbutton again. You may also want restrict the user from other tasks such as\nclicking a\n.QW Print\nbutton.\n.PP\nThe \\fBtk busy\\fR command lets you make Tk widgets busy. This means that user\ninteractions such as button clicks, moving the mouse, typing at the keyboard,\netc.\\0are ignored by the widget. You can set a special cursor (like a watch)\nthat overrides the widget's normal cursor, providing feedback that the\napplication (widget) is temporarily busy.\n.PP\nWhen a widget is made busy, the widget and all of its descendants will ignore\npointer events. It's easy to make an entire panel of widgets busy. You can\nsimply make the toplevel widget (such as\n.QW . )\nbusy. This is easier and far much more efficient than recursively traversing\nthe widget hierarchy, disabling each widget and re-configuring its cursor.\n.PP\nOften, the \\fBtk busy\\fR command can be used instead of Tk's \\fBgrab\\fR\ncommand. Unlike \\fBgrab\\fR which restricts all user interactions to one\nwidget, with the \\fBtk busy\\fR command you can have more than one widget\nactive (for example, a\n.QW Cancel\ndialog and a\n.QW Help\nbutton).\n.SS EXAMPLE\n.PP\nYou can make several widgets busy by simply making its ancestor widget busy\nusing the \\fBhold\\fR operation.\n.PP\n.CS\nframe .top\nbutton .top.button; canvas .top.canvas\npack .top.button .top.canvas\npack .top\n# . . .\n\\fBtk busy\\fR hold .top\nupdate\n.CE\n.PP\nAll the widgets within \\fB.top\\fR (including \\fB.top\\fR) are now busy. Using\n\\fBupdate\\fR insures that \\fBtk busy\\fR command will take effect before any\nother user events can occur.\n.PP\nWhen the application is no longer busy processing, you can allow user\ninteractions again and free any resources it allocated by the \\fBforget\\fR\noperation.\n.PP\n.CS\n\\fBtk busy\\fR forget .top\n.CE\n.PP\nThe busy window has a configurable cursor. You can change the busy cursor\nusing the \\fBconfigure\\fR operation.\n.PP\n.CS\n\\fBtk busy\\fR configure .top -cursor \"watch\"\n.CE\n.PP\nDestroying the widget will also clean up any resources allocated by the \\fBtk\nbusy\\fR command.\n.PP\n.SH OPERATIONS\n.PP\nThe following operations are available for the \\fBtk busy\\fR command:\n.TP\n\\fBtk busy \\fIwindow\\fR ?\\fIoption value\\fR?...\n.\nShortcut for \\fBtk busy hold\\fR command.\n.\\\" METHOD: busywindow\n.TP\n\\fBtk busy busywindow \\fIwindow\\fR\n.\nReturns the pathname of the busy window (i.e. the transparent window\nshielding the window appearing busy) created by the \\fBtk busy hold\\fR\ncommand for \\fIwindow\\fR, or the empty string if \\fIwindow\\fR is not busy.\n.\\\" METHOD: cget\n.TP\n\\fBtk busy cget \\fIwindow option\\fR\n.\nQueries the \\fBtk busy\\fR command configuration options for \\fIwindow\\fR.\n\\fIWindow\\fR must be the path name of a widget previously made busy by the\n\\fBhold\\fR operation. The command returns the present value of the specified\n\\fIoption\\fR. \\fIOption\\fR may have any of the values accepted by the\n\\fBhold\\fR operation.\n.\\\" METHOD: configure\n.TP\n\\fBtk busy configure \\fIwindow\\fR ?\\fIoption value\\fR?...\n.\nQueries or modifies the \\fBtk busy\\fR command configuration options for\n\\fIwindow\\fR. \\fIWindow\\fR must be the path name of a widget previously made\nbusy by the \\fBhold\\fR operation.  If no options are specified, a list\ndescribing all of the available options for \\fIwindow\\fR (see\n\\fBTk_ConfigureInfo\\fR for information on the format of this list) is\nreturned. If \\fIoption\\fR is specified with no \\fIvalue\\fR, then the command\nreturns a list describing the one named option (this list will be identical to\nthe corresponding sublist of the value returned if no \\fIoption\\fR is\nspecified). If one or more \\fIoption\\-value\\fR pairs are specified, then the\ncommand modifies the given widget option(s) to have the given value(s); in\nthis case the command returns the empty string. \\fIOption\\fR may have any of\nthe values accepted by the \\fBhold\\fR operation.\n.RS\n.PP\nPlease note that the option database is referenced through \\fIwindow\\fR. For\nexample, if the widget \\fB.frame\\fR is to be made busy, the busy cursor can be\nspecified for it by either \\fBoption\\fR command:\n.PP\n.CS\noption add *frame.busyCursor gumby\noption add *Frame.BusyCursor gumby\n.CE\n.RE\n.\\\" METHOD: current\n.TP\n\\fBtk busy current \\fR?\\fIpattern\\fR?\n.\nReturns the pathnames of all widgets that are currently busy. If a\n\\fIpattern\\fR is given, only the path names of busy widgets matching\n\\fIpattern\\fR are returned.\n.\\\" METHOD: forget\n.TP\n\\fBtk busy forget \\fIwindow\\fR ?\\fIwindow\\fR?...\n.\nReleases resources allocated by the \\fBtk busy\\fR command for \\fIwindow\\fR,\nincluding the transparent window. User events will again be received by\n\\fIwindow\\fR. Resources are also released when \\fIwindow\\fR is destroyed.\n\\fIWindow\\fR must be the name of a widget specified in the \\fBhold\\fR\noperation, otherwise an error is reported.\n.\\\" METHOD: hold\n.TP\n\\fBtk busy hold \\fIwindow\\fR ?\\fIoption value\\fR?...\n.\nMakes the specified \\fIwindow\\fR (and its descendants in the Tk window\nhierarchy) appear busy. \\fIWindow\\fR must be a valid path name of a Tk widget.\nA transparent window is put in front of the specified window. This transparent\nwindow is mapped the next time idle tasks are processed, and the specified\nwindow and its descendants will be blocked from user interactions. Normally\n\\fBupdate\\fR should be called immediately afterward to insure that the hold\noperation is in effect before the application starts its processing. The\ncommand returns the pathname of the busy window that was created (i.e. the\ntransparent window shielding the window appearing busy). The following\nconfiguration options are valid:\n.RS\n.\\\" OPTION: -cursor\n.TP\n\\fB\\-cursor \\fIcursorName\\fR\n.\nSpecifies the cursor to be displayed when the widget is made busy.\n\\fICursorName\\fR can be in any form accepted by \\fBTk_GetCursor\\fR. The\ndefault cursor is \\fBwait\\fR on Windows and \\fBwatch\\fR on other platforms.\n.RE\n.\\\" METHOD: status\n.TP\n\\fBtk busy status \\fIwindow\\fR\n.\nReturns the status of a widget \\fIwindow\\fR. If \\fIwindow\\fR presently can not\nreceive user interactions, \\fB1\\fR is returned, otherwise \\fB0\\fR.\n.SH \"EVENT HANDLING\"\n.SS BINDINGS\n.PP\nThe event blocking feature is implemented by creating and mapping a\ntransparent window that completely covers the widget. When the busy window is\nmapped, it invisibly shields the widget and its hierarchy from all events that\nmay be sent. Like Tk widgets, busy windows have widget names in the Tk window\nhierarchy. This means that you can use the \\fBbind\\fR command to handle\nevents in the busy window:\n.PP\n.CS\n\\fBtk busy\\fR hold .frame.canvas\nbind [\\fBtk busy\\fR busywindow .frame.canvas] <Enter> { ... }\n.CE\n.PP\nor\n.CS\nset busyWin [\\fBtk busy\\fR hold .frame.canvas]\nbind $busyWin <Enter> { ... }\n.CE\n.SS \"ENTER/LEAVE EVENTS\"\n.PP\nMapping and unmapping busy windows generates Enter/Leave events for all\nwidgets they cover. Please note this if you are tracking Enter/Leave events in\nwidgets.\n.SS \"KEYBOARD EVENTS\"\n.PP\nWhen a widget is made busy, the widget is prevented from gaining the keyboard\nfocus by a user clicking on it by the busy window. But if the widget already had\nfocus, it still may receive keyboard events. The widget can also still receive\nfocus through keyboard traversal. To prevent this, you must move\nfocus to another window and make sure the focus can not go back to the widgets\nmade busy (e.g. but restricting focus to a cancel button).\n.PP\n.CS\npack [frame .frame]\npack [text .frame.text]\n\\fBtk busy\\fR hold .frame\npack [button .cancel -text \"Cancel\" -command exit]\nfocus .cancel\nbind .cancel <Tab> {break}\nbind .cancel <Shift-Tab> {break}\nupdate\n.CE\n.PP\nThe above example moves the focus from .frame immediately after invoking the\n\\fBhold\\fR so that no keyboard events will be sent to \\fB.frame\\fR or any of\nits descendants. It also makes sure it's not possible to leave button\n\\fB.cancel\\fR using the keyboard.\n.SH PORTABILITY\n.PP\nNote that the \\fBtk busy\\fR command does not currently have any effect on macOS\nwhen Tk is built using Aqua support.\n.SH \"SEE ALSO\"\ngrab(n)\n.SH KEYWORDS\nbusy, keyboard events, pointer events, window\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/button.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH button n 4.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nbutton \\- Create and manipulate 'button' action widgets\n.SH SYNOPSIS\n\\fBbutton\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-font\t\\-relief\n\\-activeforeground\t\\-foreground\t\\-repeatdelay\n\\-anchor\t\\-highlightbackground\t\\-repeatinterval\n\\-background\t\\-highlightcolor\t\\-takefocus\n\\-bitmap\t\\-highlightthickness\t\\-text\n\\-borderwidth\t\\-image\t\\-textvariable\n\\-compound\t\\-justify\t\\-underline\n\\-cursor\t\\-padx\t\\-wraplength\n\\-disabledforeground\t\\-pady\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies a Tcl command to associate with the button.  This command\nis typically invoked when mouse button 1 is released over the button\nwindow.\n.OP \\-default default Default\nSpecifies one of three states for the default ring: \\fBnormal\\fR,\n\\fBactive\\fR, or \\fBdisabled\\fR.  In active state, the button is drawn\nwith the platform specific appearance for a default button.  In normal\nstate, the button is drawn with the platform specific appearance for a\nnon-default button, leaving enough space to draw the default button\nappearance.  The normal and active states will result in buttons of\nthe same size.  In disabled state, the button is drawn with the\nnon-default button appearance without leaving space for the default\nappearance.  The disabled state may result in a smaller button than\nthe active state.\n.OP \\-height height Height\nSpecifies a desired height for the button.\nIf an image or bitmap is being displayed in the button then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in lines of text.\nIf this option is not specified, the button's desired height is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.OP \\-overrelief overRelief OverRelief\nSpecifies an alternative relief for the button, to be used when the\nmouse cursor is over the widget.  This option can be used to make\ntoolbar buttons, by configuring \\fB\\-relief flat \\-overrelief\nraised\\fR.  If the value of this option is the empty string, then no\nalternative relief is used when the mouse cursor is over the button.\nThe empty string is the default value.\n.OP \\-state state State\nSpecifies one of three states for the button:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the button is displayed using the\n\\fB\\-foreground\\fR and \\fB\\-background\\fR options.  The active state is\ntypically used when the pointer is over the button.  In active state\nthe button is displayed using the \\fB\\-activeforeground\\fR and\n\\fB\\-activebackground\\fR options.  Disabled state means that the button\nshould be insensitive:  the default bindings will refuse to activate\nthe widget and will ignore mouse button presses.\nIn this state the \\fB\\-disabledforeground\\fR and\n\\fB\\-background\\fR options determine how the button is displayed.\n.OP \\-width width Width\nSpecifies a desired width for the button.\nIf an image or bitmap is being displayed in the button then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR).\nFor a text button (no image or with \\fB\\-compound none\\fR) then the width\nspecifies how much space in characters to allocate for the text label.\nIf the width is negative then this specifies a minimum width.\nIf this option is not specified, the button's desired width is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBbutton\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a button widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the button such as its colors, font,\ntext, and initial relief.  The \\fBbutton\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA button is a widget that displays a textual string, bitmap or image.\nIf text is displayed, it must all be in a single font, but it\ncan occupy multiple lines on the screen (if it contains newlines\nor if wrapping occurs because of the \\fB\\-wraplength\\fR option) and\none of the characters may optionally be underlined using the\n\\fB\\-underline\\fR option.\nIt can display itself in either of three different ways, according\nto\nthe \\fB\\-state\\fR option;\nit can be made to appear raised, sunken, or flat;\nand it can be made to flash.  When a user invokes the\nbutton (by pressing mouse button 1 with the cursor over the\nbutton), then the Tcl command specified in the \\fB\\-command\\fR\noption is invoked.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBbutton\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for button widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBbutton\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBbutton\\fR\ncommand.\n.\\\" METHOD: flash\n.TP\n\\fIpathName \\fBflash\\fR\n.\nFlash the button.  This is accomplished by redisplaying the button\nseveral times, alternating between the configured activebackground\nand background colors.  At the end of the flash the button is left\nin the same normal/active state as when the command was invoked.\nThis command is ignored if the button's state is \\fBdisabled\\fR.\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke\\fR\n.\nInvoke the Tcl command associated with the button, if there is one.\nThe return value is the return value from the Tcl command, or an\nempty string if there is no command associated with the button.\nThis command is ignored if the button's state is \\fBdisabled\\fR.\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for buttons that give them\ndefault behavior:\n.IP [1]\nA button activates whenever the mouse passes over it and deactivates\nwhenever the mouse leaves the button.\nUnder Windows, this binding is only active when mouse button 1 has\nbeen pressed over the button.\n.IP [2]\nA button's relief is changed to sunken whenever mouse button 1 is\npressed over the button, and the relief is restored to its original\nvalue when button 1 is later released.\n.IP [3]\nIf mouse button 1 is pressed over a button and later released over\nthe button, the button is invoked.  However, if the mouse is not\nover the button when button 1 is released, then no invocation occurs.\n.IP [4]\nWhen a button has the input focus, the space key causes the button\nto be invoked.\n.PP\nIf the button's state is \\fBdisabled\\fR then none of the above\nactions occur:  the button is completely non-responsive.\n.PP\nThe behavior of buttons can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"PLATFORM NOTES\"\n.PP\nOn Aqua/macOS, some configuration options are ignored for the purpose of\ndrawing of the widget because they would otherwise conflict with platform\nguidelines. The \\fBconfigure\\fR and \\fBcget\\fR subcommands can still\nmanipulate the values, but do not cause any variation to the look of the\nwidget. The options affected notably include \\fB\\-background\\fR and\n\\fB\\-relief\\fR.\n.SH EXAMPLES\n.PP\nThis is the classic Tk\n.QW \"Hello, World!\"\ndemonstration:\n.PP\n.CS\n\\fBbutton\\fR .b -text \"Hello, World!\" -command exit\npack .b\n.CE\n.PP\nThis example demonstrates how to handle button accelerators:\n.PP\n.CS\n\\fBbutton\\fR .b1 -text Hello -underline 0\n\\fBbutton\\fR .b2 -text World -underline 0\nbind . <Key-h> {.b1 flash; .b1 invoke}\nbind . <Key-w> {.b2 flash; .b2 invoke}\npack .b1 .b2\n.CE\n.SH \"SEE ALSO\"\nttk::button(n)\n.SH KEYWORDS\nbutton, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/canvas.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 1997-1999 Scriptics Corporation.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH canvas n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ncanvas \\- Create and manipulate 'canvas' hypergraphics drawing surface widgets\n.SH SYNOPSIS\n\\fBcanvas\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-background\t\\-borderwidth\t\\-cursor\n\\-highlightbackground\t\\-highlightcolor\t\\-highlightthickness\n\\-insertbackground\t\\-insertborderwidth\t\\-insertofftime\n\\-insertontime\t\\-insertwidth\t\\-relief\n\\-selectbackground\t\\-selectborderwidth\t\\-selectforeground\n\\-takefocus\t\\-xscrollcommand\t\\-yscrollcommand\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-closeenough closeEnough CloseEnough\nSpecifies a floating-point value indicating how close the mouse cursor\nmust be to an item before it is considered to be\n.QW inside\nthe item. Defaults to 1.0.\n.OP \\-confine confine Confine\nSpecifies a boolean value that indicates whether or not it should be\nallowable to set the canvas's view outside the region defined by the\n\\fBscrollRegion\\fR argument.\nDefaults to true, which means that the view will\nbe constrained within the scroll region.\n.OP \\-height height Height\nSpecifies a desired window height that the canvas widget should request from\nits geometry manager. The value may be specified in any\nof the forms described in the \\fBCOORDINATES\\fR section below.\n.OP \\-scrollregion scrollRegion ScrollRegion\nSpecifies a list with four coordinates describing the left, top, right, and\nbottom coordinates of a rectangular region.\nThis region is used for scrolling purposes and is considered to be\nthe boundary of the information in the canvas.\nEach of the coordinates may be specified\nin any of the forms given in the \\fBCOORDINATES\\fR section below.\n.OP \\-state state State\nModifies the default state of the canvas where \\fIstate\\fR may be set to\none of: \\fBnormal\\fR, \\fBdisabled\\fR, or \\fBhidden\\fR. Individual canvas\nobjects all have their own state option which may override the default\nstate. Many options can take separate specifications such that the\nappearance of the item can be different in different situations. The\noptions that start with \\fBactive\\fR control the appearance when the mouse\npointer is over it, while the option starting with \\fBdisabled\\fR controls\nthe appearance when the state is disabled. Canvas items which are\n\\fBdisabled\\fR will not react to canvas bindings.\n.OP \\-width width width\nSpecifies a desired window width that the canvas widget should request from\nits geometry manager. The value may be specified in any\nof the forms described in the \\fBCOORDINATES\\fR section below.\n.OP \\-xscrollincrement xScrollIncrement ScrollIncrement\nSpecifies an increment for horizontal scrolling, in any of the usual forms\npermitted for screen distances. If the value of this option is greater\nthan zero, the horizontal view in the window will be constrained so that\nthe canvas x coordinate at the left edge of the window is always an even\nmultiple of \\fBxScrollIncrement\\fR; furthermore, the units for scrolling\n(e.g., the change in view when the left and right arrows of a scrollbar\nare selected) will also be \\fBxScrollIncrement\\fR. If the value of\nthis option is negative or zero, then horizontal scrolling\nis unconstrained.\n.OP \\-yscrollincrement yScrollIncrement ScrollIncrement\nSpecifies an increment for vertical scrolling, in any of the usual forms\npermitted for screen distances. If the value of this option is greater\nthan zero, the vertical view in the window will be constrained so that\nthe canvas y coordinate at the top edge of the window is always an even\nmultiple of \\fByScrollIncrement\\fR; furthermore, the units for scrolling\n(e.g., the change in view when the top and bottom arrows of a scrollbar\nare selected) will also be \\fByScrollIncrement\\fR. If the value of\nthis option is negative or zero, then vertical scrolling\nis unconstrained.\n.BE\n.SH INTRODUCTION\n.PP\nThe \\fBcanvas\\fR command creates a new window (given\nby the \\fIpathName\\fR argument) and makes it into a canvas widget.\nAdditional options, described above, may be specified on the\ncommand line or in the option database\nto configure aspects of the canvas such as its colors and 3-D relief.\nThe \\fBcanvas\\fR command returns its\n\\fIpathName\\fR argument. At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nCanvas widgets implement structured graphics.\nA canvas displays any number of \\fIitems\\fR, which may be things like\nrectangles, circles, lines, and text.\nItems may be manipulated (e.g. moved or re-colored) and commands may\nbe associated with items in much the same way that the \\fBbind\\fR\ncommand allows commands to be bound to widgets. For example,\na particular command may be associated with the <Button-1> event\nso that the command is invoked whenever button 1 is pressed with\nthe mouse cursor over an item.\nThis means that items in a canvas can have behaviors defined by\nthe Tcl scripts bound to them.\n.SH \"DISPLAY LIST\"\n.PP\nThe items in a canvas are ordered for purposes of display,\nwith the first item in the display list being displayed\nfirst, followed by the next item in the list, and so on.\nItems later in the display list obscure those that are\nearlier in the display list and are sometimes referred to as being\n.QW \"on top\"\nof earlier items.\nWhen a new item is created it is placed at the end of the\ndisplay list, on top of everything else.\nWidget commands may be used to re-arrange the order of the\ndisplay list.\n.PP\nWindow items are an exception to the above rules. The underlying\nwindow systems require them always to be drawn on top of other items.\nIn addition, the stacking order of window items\nis not affected by any of the canvas widget commands; you must use\nthe Tk \\fBraise\\fR command and \\fBlower\\fR command instead.\n.SH \"ITEM IDS AND TAGS\"\n.PP\nItems in a canvas widget may be named in either of two ways:\nby id or by tag.\nEach item has a unique identifying number, which is assigned to\nthat item when it is created. The id of an item never changes\nand id numbers are never re-used within the lifetime of a\ncanvas widget.\n.PP\nEach item may also have any number of \\fItags\\fR associated\nwith it. A tag is just a string of characters, and it may\ntake any form except that of an integer.\nFor example,\n.QW x123\nis OK but\n.QW 123\nis not.\nThe same tag may be associated with many different items.\nThis is commonly done to group items in various interesting\nways; for example, all selected items might be given the tag\n.QW selected .\n.PP\nThe tag \\fBall\\fR is implicitly associated with every item\nin the canvas; it may be used to invoke operations on\nall the items in the canvas.\n.PP\nThe tag \\fBcurrent\\fR is managed automatically by Tk;\nit applies to the \\fIcurrent item\\fR, which is the\ntopmost item whose drawn area covers the position of\nthe mouse cursor (different item types interpret this in varying ways; see the\nindividual item type documentation for details).\nIf the mouse is not in the canvas widget or is not over\nan item, then no item has the \\fBcurrent\\fR tag.\n.PP\nWhen specifying items in canvas widget commands, if the\nspecifier is an integer then it is assumed to refer to\nthe single item with that id.\nIf the specifier is not an integer, then it is assumed to\nrefer to all of the items in the canvas that have a tag\nmatching the specifier.\nThe symbol \\fItagOrId\\fR is used below to indicate that\nan argument specifies either an id that selects a single\nitem or a tag that selects zero or more items.\n.PP\n\\fItagOrId\\fR may contain a logical expressions of\ntags by using operators:\n.QW \\fB&&\\fR ,\n.QW \\fB||\\fR ,\n.QW \\fB^\\fR ,\n.QW \\fB!\\fR ,\nand parenthesized subexpressions. For example:\n.CS\n      .c find withtag {(a&&!b)||(!a&&b)}\n.CE\nor equivalently:\n.CS\n      .c find withtag {a^b}\n.CE\nwill find only those items with either\n.QW a\nor\n.QW b\ntags, but not both.\n.PP\nSome widget commands only operate on a single item at a\ntime; if \\fItagOrId\\fR is specified in a way that\nnames multiple items, then the normal behavior is for\nthe command to use the first (lowest) of these items in\nthe display list that is suitable for the command.\nExceptions are noted in the widget command descriptions\nbelow.\n.SH \"COORDINATES\"\n.PP\nAll coordinates related to canvases are stored as floating-point\nnumbers.\nCoordinates and distances are specified in screen units,\nwhich are floating-point numbers optionally followed\nby one of several letters.\nIf no letter is supplied then the distance is in pixels.\nIf the letter is \\fBm\\fR then the distance is in millimeters on\nthe screen; if it is \\fBc\\fR then the distance is in centimeters;\n\\fBi\\fR means inches, and \\fBp\\fR means printers points (1/72 inch).\nLarger y-coordinates refer to points lower on the screen; larger\nx-coordinates refer to points farther to the right.\nCoordinates can be specified either as an even number of parameters,\nor as a single list parameter containing an even number of x and y\ncoordinate values.\n.SS TRANSFORMATIONS\n.PP\nNormally the origin of the canvas coordinate system is at the\nupper-left corner of the window containing the canvas.\nIt is possible to adjust the origin of the canvas\ncoordinate system relative to the origin of the window using the\n\\fBxview\\fR and \\fByview\\fR widget commands; this is typically used\nfor scrolling.\nCanvases do not support scaling or rotation of the canvas coordinate\nsystem relative to the window coordinate system.\n.PP\nIndividual items may be moved, scaled\n.VS \"9.0, TIP164\"\nor rotated\n.VE \"9.0, TIP164\"\nusing widget commands\ndescribed below.\n.PP\nNote that the default origin of the canvas's visible area is\ncoincident with the origin for the whole window as that makes bindings\nusing the mouse position easier to work with; you only need to use the\n\\fBcanvasx\\fR and \\fBcanvasy\\fR widget commands if you adjust the\norigin of the visible area. However, this also means that any focus\nring (as controlled by the \\fB\\-highlightthickness\\fR option) and\nwindow border (as controlled by the \\fB\\-borderwidth\\fR option) must\nbe taken into account before you get to the visible area of the\ncanvas.\n.SH \"INDICES\"\n.PP\nText items support the notion of an \\fIindex\\fR for identifying\nparticular positions within the item.\nIn a similar fashion, line and polygon items support \\fIindex\\fR for\nidentifying, inserting and deleting subsets of their coordinates.\nIndices are used for commands such as inserting or deleting\na range of characters or coordinates, and setting the insertion\ncursor position. An index may be specified in any of a number\nof ways, and different types of items may support different forms\nfor specifying indices.\nText items support the following forms for an index; if you\ndefine new types of text-like items, it would be advisable to\nsupport as many of these forms as practical.\nNote that it is possible to refer to the character just after\nthe last one in the text item; this is necessary for such\ntasks as inserting new text at the end of the item.\nLines and Polygons do not support the insertion cursor\nand the selection. Their indices are supposed to be even\nalways, because coordinates always appear in pairs.\n.IP \\fInumber\\fR 10\nA decimal number giving the position of the desired character\nwithin the text item.\n0 refers to the first character, 1 to the next character, and\nso on. If indexes are odd for lines and polygons, they will be\nautomatically decremented by one.\nA negative number  is treated as if it were zero, and a\nnumber greater than the length of the text item is treated\nas if it were equal to the length of the text item. For\npolygons, negative numbers or numbers greater than the length\nof the coordinate list will be adjusted by adding or subtracting\nthe length until the result is between zero and the length,\ninclusive.\n.IP \\fBend\\fR 10\nRefers to the character or coordinate just after the last one\nin the item (same as the number of characters or coordinates\nin the item).\n.IP \\fBinsert\\fR 10\nRefers to the character just before which the insertion cursor\nis drawn in this item. Not valid for lines and polygons.\n.IP \\fBsel.first\\fR 10\nRefers to the first selected character in the item.\nIf the selection is not in this item then this form is illegal.\n.IP \\fBsel.last\\fR 10\nRefers to the last selected character in the item.\nIf the selection is not in this item then this form is illegal.\n.IP \\fB@\\fIx,y\\fR 10\nRefers to the character or coordinate at the point given by \\fIx\\fR and\n\\fIy\\fR, where \\fIx\\fR and \\fIy\\fR are specified in the coordinate\nsystem of the canvas.\nIf \\fIx\\fR and \\fIy\\fR lie outside the coordinates covered by the\ntext item, then they refer to the first or last character in the\nline that is closest to the given point.\n.SH \"DASH PATTERNS\"\n.PP\nMany items support the notion of a dash pattern for outlines.\n.PP\nThe first possible syntax is a list of integers. Each element\nrepresents the number of pixels of a line segment. Only the odd\nsegments are drawn using the\n.QW outline\ncolor. The other segments are drawn transparent.\n.PP\nThe second possible syntax is a character list containing only\n5 possible characters\n.QW \"\\fB.,-_ \\fR\" .\nThe space can be used\nto enlarge the space between other line elements, and cannot\noccur as the first position in the string. Some examples:\n.PP\n.CS\n\\-dash .     \\(-> \\-dash {2 4}\n\\-dash -     \\(-> \\-dash {6 4}\n\\-dash -.    \\(-> \\-dash {6 4 2 4}\n\\-dash -..   \\(-> \\-dash {6 4 2 4 2 4}\n\\-dash {. }  \\(-> \\-dash {2 8}\n\\-dash ,     \\(-> \\-dash {4 4}\n.CE\n.PP\nThe main difference of this syntax with the previous is that it\nis shape-conserving. This means that all values in the dash\nlist will be multiplied by the line width before display. This\nassures that\n.QW .\nwill always be displayed as a dot and\n.QW -\nalways as a dash regardless of the line width.\n.PP\nOn systems which support only a limited set of dash patterns, the dash\npattern will be displayed as the closest dash pattern that is available.\nFor example, on Windows only the first 4 of the above examples are\navailable. The last 2 examples will be displayed identically to the first\none.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBcanvas\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR. This\ncommand may be used to invoke various\noperations on the widget. It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.\nThe following widget commands are possible for canvas widgets:\n.\\\" METHOD: addtag\n.TP\n\\fIpathName \\fBaddtag \\fItag searchSpec \\fR?\\fIarg ...\\fR?\n.\nFor each item that meets the constraints specified by\n\\fIsearchSpec\\fR and the \\fIarg\\fRs, add\n\\fItag\\fR to the list of tags associated with the item if it\nis not already present on that list.\nIt is possible that no items will satisfy the constraints\ngiven by \\fIsearchSpec\\fR and \\fIarg\\fRs, in which case the\ncommand has no effect.\nThis command returns an empty string as result.\n\\fISearchSpec\\fR and \\fIarg\\fR's may take any of the following\nforms:\n.RS\n.IP \"\\fBabove \\fItagOrId\\fR\"\nSelects the item just after (above) the one given by \\fItagOrId\\fR\nin the display list.\nIf \\fItagOrId\\fR denotes more than one item, then the last (topmost)\nof these items in the display list is used.\n.IP \\fBall\\fR\nSelects all the items in the canvas.\n.IP \"\\fBbelow \\fItagOrId\\fR\"\nSelects the item just before (below) the one given by \\fItagOrId\\fR\nin the display list.\nIf \\fItagOrId\\fR denotes more than one item, then the first (lowest)\nof these items in the display list is used.\n.IP \"\\fBclosest \\fIx y \\fR?\\fIhalo\\fR? ?\\fIstart\\fR?\"\nSelects the item closest to the point given by \\fIx\\fR and \\fIy\\fR.\nIf more than one item is at the same closest distance (e.g. two\nitems overlap the point), then the top-most of these items (the\nlast one in the display list) is used.\nIf \\fIhalo\\fR is specified, then it must be a non-negative\nvalue.\nAny item closer than \\fIhalo\\fR to the point is considered to\noverlap it.\nThe \\fIstart\\fR argument may be used to step circularly through\nall the closest items.\nIf \\fIstart\\fR is specified, it names an item using a tag or id\n(if by tag, it selects the first item in the display list with\nthe given tag).\nInstead of selecting the topmost closest item, this form will\nselect the topmost closest item that is below \\fIstart\\fR in\nthe display list; if no such item exists, then the selection\nbehaves as if the \\fIstart\\fR argument had not been specified.\n.IP \"\\fBenclosed\\fI x1 y1 x2 y2\\fR\"\nSelects all the items completely enclosed within the rectangular\nregion given by \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR.\n\\fIX1\\fR must be no greater than \\fIx2\\fR and \\fIy1\\fR must be\nno greater than \\fIy2\\fR.\n.IP \"\\fBoverlapping\\fI x1 y1 x2 y2\\fR\"\nSelects all the items that overlap or are enclosed within the\nrectangular region given by \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR,\nand \\fIy2\\fR.\n\\fIX1\\fR must be no greater than \\fIx2\\fR and \\fIy1\\fR must be\nno greater than \\fIy2\\fR.\n.IP \"\\fBwithtag \\fItagOrId\\fR\"\nSelects all the items given by \\fItagOrId\\fR.\n.RE\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox \\fItagOrId\\fR ?\\fItagOrId tagOrId ...\\fR?\n.\nReturns a list with four elements giving an approximate bounding box\nfor all the items named by the \\fItagOrId\\fR arguments.\nThe list has the form\n.QW \"\\fIx1 y1 x2 y2\\fR\"\nsuch that the drawn\nareas of all the named elements are within the region bounded by\n\\fIx1\\fR on the left, \\fIx2\\fR on the right, \\fIy1\\fR on the top,\nand \\fIy2\\fR on the bottom.\nThe return value may overestimate the actual bounding box by\na few pixels.\nIf no items match any of the \\fItagOrId\\fR arguments or if the\nmatching items have empty bounding boxes (i.e. they have nothing\nto display)\nthen an empty string is returned.\n.\\\" METHOD: bind\n.TP\n\\fIpathName \\fBbind \\fItagOrId\\fR ?\\fIsequence\\fR? ?\\fIcommand\\fR?\n.\nThis command associates \\fIcommand\\fR with all the items given by\n\\fItagOrId\\fR such that whenever the event sequence given by\n\\fIsequence\\fR occurs for one of the items the command will\nbe invoked.\nThis widget command is similar to the \\fBbind\\fR command except that\nit operates on items in a canvas rather than entire widgets.\nSee the \\fBbind\\fR manual entry for complete details\non the syntax of \\fIsequence\\fR and the substitutions performed\non \\fIcommand\\fR before invoking it.\nIf all arguments are specified then a new binding is created, replacing\nany existing binding for the same \\fIsequence\\fR and \\fItagOrId\\fR\n(if the first character of \\fIcommand\\fR is\n.QW +\nthen \\fIcommand\\fR augments an existing binding rather than replacing it).\nIn this case the return value is an empty string.\nIf \\fIcommand\\fR is omitted then the command returns the \\fIcommand\\fR\nassociated with \\fItagOrId\\fR and \\fIsequence\\fR (an error occurs\nif there is no such binding).\nIf both \\fIcommand\\fR and \\fIsequence\\fR are omitted then the command\nreturns a list of all the sequences for which bindings have been\ndefined for \\fItagOrId\\fR.\n.RS\n.PP\nThe only events for which bindings may be specified are those related to\nthe mouse and keyboard (such as \\fBEnter\\fR, \\fBLeave\\fR,\n\\fBButton\\fR, \\fBMotion\\fR, and \\fBKey\\fR) or virtual events.\nThe handling of events in canvases uses the current item defined in\n\\fBITEM IDS AND TAGS\\fR above. \\fBEnter\\fR and \\fBLeave\\fR events\ntrigger for an\nitem when it becomes the current item or ceases to be the current item;\nnote that these events are different than \\fBEnter\\fR and \\fBLeave\\fR\nevents for windows. Mouse-related events are directed to the current\nitem, if any. Keyboard-related events are directed to the focus item, if\nany (see the \\fBfocus\\fR widget command below for more on this). If a\nvirtual event is used in a binding, that binding can trigger only if the\nvirtual event is defined by an underlying mouse-related or\nkeyboard-related event.\n.PP\nIt is possible for multiple bindings to match a particular event.\nThis could occur, for example, if one binding is associated with the\nitem's id and another is associated with one of the item's tags.\nWhen this occurs, all of the matching bindings are invoked.\nA binding associated with the \\fBall\\fR tag is invoked first,\nfollowed by one binding for each of the item's tags (in order),\nfollowed by a binding associated with the item's id.\nIf there are multiple matching bindings for a single tag,\nthen only the most specific binding is invoked.\nA \\fBcontinue\\fR command in a binding script terminates that\nscript, and a \\fBbreak\\fR command terminates that script\nand skips any remaining scripts for the event, just as for the\n\\fBbind\\fR command.\n.PP\nIf bindings have been created for a canvas window using the \\fBbind\\fR\ncommand, then they are invoked in addition to bindings created for\nthe canvas's items using the \\fBbind\\fR widget command.\nThe bindings for items will be invoked before any of the bindings\nfor the window as a whole.\n.RE\n.\\\" METHOD: canvasx\n.TP\n\\fIpathName \\fBcanvasx \\fIscreenx\\fR ?\\fIgridspacing\\fR?\n.\nGiven a window x-coordinate in the canvas \\fIscreenx\\fR, this command returns\nthe canvas x-coordinate that is displayed at that location.\nIf \\fIgridspacing\\fR is specified, then the canvas coordinate is\nrounded to the nearest multiple of \\fIgridspacing\\fR units.\n.\\\" METHOD: canvasy\n.TP\n\\fIpathName \\fBcanvasy \\fIscreeny\\fR ?\\fIgridspacing\\fR?\n.\nGiven a window y-coordinate in the canvas \\fIscreeny\\fR this command returns\nthe canvas y-coordinate that is displayed at that location.\nIf \\fIgridspacing\\fR is specified, then the canvas coordinate is\nrounded to the nearest multiple of \\fIgridspacing\\fR units.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBcanvas\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure ?\\fIoption\\fR? ?\\fIvalue\\fR? ?\\fIoption value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list). If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified). If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s); in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBcanvas\\fR\ncommand.\n.\\\" METHOD: coords\n.TP\n\\fIpathName \\fBcoords \\fItagOrId \\fR?\\fIx0 y0 ...\\fR?\n.TP\n\\fIpathName \\fBcoords \\fItagOrId \\fR?\\fIcoordList\\fR?\n.\nQuery or modify the coordinates that define an item.\nIf no coordinates are specified, this command returns a list\nwhose elements are the coordinates of the item named by\n\\fItagOrId\\fR.\nIf coordinates are specified, then they replace the current\ncoordinates for the named item.\nIf \\fItagOrId\\fR refers to multiple items, then\nthe first one in the display list is used.\n.RS\n.PP\nNote that for rectangles, ovals and arcs the returned list of coordinates\nhas a fixed order, namely the left, top, right and bottom coordinates,\nwhich may not be the order originally given. Also the coordinates are always\nreturned in screen units with no units (that is, in pixels). So if the\noriginal coordinates were specified for instance in centimeters or inches,\nthe returned values will nevertheless be in pixels.\n.RE\n.\\\" METHOD: create\n.TP\n\\fIpathName \\fBcreate \\fItype x y \\fR?\\fIx y ...\\fR? ?\\fIoption value ...\\fR?\n.TP\n\\fIpathName \\fBcreate \\fItype coordList \\fR?\\fIoption value ...\\fR?\n.\nCreate a new item in \\fIpathName\\fR of type \\fItype\\fR.\nThe exact format of the arguments after \\fItype\\fR depends\non \\fItype\\fR, but usually they consist of the coordinates for\none or more points, followed by specifications for zero or\nmore item options.\nSee the subsections on individual item types below for more\non the syntax of this command.\nThis command returns the id for the new item.\n.\\\" METHOD: dchars\n.TP\n\\fIpathName \\fBdchars \\fItagOrId first \\fR?\\fIlast\\fR?\n.\nFor each item given by \\fItagOrId\\fR, delete the characters, or coordinates,\nin the range given by \\fIfirst\\fR and \\fIlast\\fR, inclusive.\nIf some of the items given by \\fItagOrId\\fR do not support\nindexing operations then they ignore this operation.\nText items interpret \\fIfirst\\fR and \\fIlast\\fR as indices to a character,\nline and polygon items interpret them as indices to a coordinate (an x,y pair).\nIndices are described in \\fBINDICES\\fR above.\nIf \\fIlast\\fR is omitted, it defaults to \\fIfirst\\fR.\nThis command returns an empty string.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fR?\\fItagOrId tagOrId ...\\fR?\n.\nDelete each of the items given by each \\fItagOrId\\fR, and return\nan empty string.\n.\\\" METHOD: dtag\n.TP\n\\fIpathName \\fBdtag \\fItagOrId \\fR?\\fItagToDelete\\fR?\n.\nFor each of the items given by \\fItagOrId\\fR, delete the\ntag given by \\fItagToDelete\\fR from the list of those\nassociated with the item.\nIf an item does not have the tag \\fItagToDelete\\fR then\nthe item is unaffected by the command.\nIf \\fItagToDelete\\fR is omitted then it defaults to \\fItagOrId\\fR.\nThis command returns an empty string.\n.\\\" METHOD: find\n.TP\n\\fIpathName \\fBfind \\fIsearchCommand \\fR?\\fIarg ...\\fR?\n.\nThis command returns a list consisting of all the items that\nmeet the constraints specified by \\fIsearchCommand\\fR and\n\\fIarg\\fR's.\n\\fISearchCommand\\fR and \\fIargs\\fR have any of the forms\naccepted by the \\fBaddtag\\fR command.\nThe items are returned in stacking order, with the lowest item first.\n.\\\" METHOD: focus\n.TP\n\\fIpathName \\fBfocus \\fR?\\fItagOrId\\fR?\n.\nSet the keyboard focus for the canvas widget to the item given by\n\\fItagOrId\\fR.\nIf \\fItagOrId\\fR refers to several items, then the focus is set\nto the first such item in the display list that supports the\ninsertion cursor.\nIf \\fItagOrId\\fR does not refer to any items, or if none of them\nsupport the insertion cursor, then the focus is not changed.\nIf \\fItagOrId\\fR is an empty\nstring, then the focus item is reset so that no item has the focus.\nIf \\fItagOrId\\fR is not specified then the command returns the\nid for the item that currently has the focus, or an empty string\nif no item has the focus.\n.RS\n.PP\nOnce the focus has been set to an item, the item will display\nthe insertion cursor and all keyboard events will be directed\nto that item.\nThe focus item within a canvas and the focus window on the\nscreen (set with the \\fBfocus\\fR command) are totally independent:\na given item does not actually have the input focus unless (a)\nits canvas is the focus window and (b) the item is the focus item\nwithin the canvas.\nIn most cases it is advisable to follow the \\fBfocus\\fR widget\ncommand with the \\fBfocus\\fR command to set the focus window to\nthe canvas (if it was not there already).\n.RE\n.\\\" METHOD: gettags\n.TP\n\\fIpathName \\fBgettags\\fI tagOrId\\fR\n.\nReturn a list whose elements are the tags associated with the\nitem given by \\fItagOrId\\fR.\nIf \\fItagOrId\\fR refers to more than one item, then the tags\nare returned from the first such item in the display list.\nIf \\fItagOrId\\fR does not refer to any items, or if the item\ncontains no tags, then an empty string is returned.\n.\\\" METHOD: icursor\n.TP\n\\fIpathName \\fBicursor \\fItagOrId index\\fR\n.\nSet the position of the insertion cursor for the item(s) given by \\fItagOrId\\fR\nto just before the character whose position is given by \\fIindex\\fR.\nIf some or all of the items given by \\fItagOrId\\fR do not support\nan insertion cursor then this command has no effect on them.\nSee \\fBINDICES\\fR above for a description of the\nlegal forms for \\fIindex\\fR.\n.RS\n.PP\nNote that the insertion cursor is only displayed in an item if\nthat item currently has the keyboard focus (see the \\fBfocus\\fR widget\ncommand, above), but the cursor position may\nbe set even when the item does not have the focus.\n.PP\nThis command returns an empty string.\n.RE\n.\\\" METHOD: image\n.TP\n\\fIpathName \\fBimage \\fIimagename\\fR ?\\fIsubsample\\fR? ?\\fIzoom\\fR?\n.\nDraw the canvas into the Tk photo image named \\fIimagename\\fR.\nIf a \\fB\\-scrollregion\\fR has been defined then this will be the boundaries\nof the canvas region drawn and the final size of the photo image. Otherwise\nthe widget width and height with an origin of 0,0 will be the size of the\ncanvas region drawn and the final size of the photo image. Optionally an\ninteger \\fIsubsample\\fR factor may be given and the photo image\nwill be reduced in size.\n.RS\n.PP\nIn addition to the \\fIsubsample\\fR an integer \\fIzoom\\fR factor can also\nbe given and the photo image will be enlarged. The image background will\nbe filled with the canvas background colour. The canvas widget does not\nneed to be mapped for this widget command to work, but at least one of\nit's ancestors must be mapped.\n.PP\nThis command returns an empty string.\n.RE\n.\\\" METHOD: imove\n.TP\n\\fIpathName \\fBimove \\fItagOrId index x y\\fR\n.\nThis command causes the \\fIindex\\fR'th coordinate of each of the items\nindicated by \\fItagOrId\\fR to be relocated to the location (\\fIx\\fR,\\fIy\\fR).\nEach item interprets \\fIindex\\fR independently according to the rules\ndescribed in \\fBINDICES\\fR above. Out of the standard set of items, only line\nand polygon items may have their coordinates relocated this way.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex \\fItagOrId index\\fR\n.\nThis command returns a decimal string giving the numerical index\nwithin \\fItagOrId\\fR corresponding to \\fIindex\\fR.\n\\fIIndex\\fR gives a textual description of the desired position\nas described in \\fBINDICES\\fR above.\nText items interpret \\fIindex\\fR as an index to a character,\nline and polygon items interpret it as an index to a coordinate (an x,y pair).\nThe return value is guaranteed to lie between 0 and the number\nof characters, or coordinates, within the item, inclusive.\nIf \\fItagOrId\\fR refers to multiple items, then the index\nis processed in the first of these items that supports indexing\noperations (in display list order).\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fItagOrId beforeThis string\\fR\n.\nFor each of the items given by \\fItagOrId\\fR, if the item supports\ntext or coordinate, insertion then \\fIstring\\fR is inserted into the item's\ntext just before the character, or coordinate, whose index is \\fIbeforeThis\\fR.\nText items interpret \\fIbeforeThis\\fR as an index to a character,\nline and polygon items interpret it as an index to a coordinate (an x,y pair).\nFor lines and polygons the \\fIstring\\fR must be a valid coordinate\nsequence.\n.RS\n.PP\nSee \\fBINDICES\\fR above for information about the forms allowed\nfor \\fIbeforeThis\\fR.\n.PP\nThis command returns an empty string.\n.RE\n.\\\" METHOD: itemcget\n.TP\n\\fIpathName \\fBitemcget\\fI tagOrId option\\fR\n.\nReturns the current value of the configuration option for the\nitem given by \\fItagOrId\\fR whose name is \\fIoption\\fR.\nThis command is similar to the \\fBcget\\fR widget command except that\nit applies to a particular item rather than the widget as a whole.\n\\fIOption\\fR may have any of the values accepted by the \\fBcreate\\fR\nwidget command when the item was created.\nIf \\fItagOrId\\fR is a tag that refers to more than one item,\nthe first (lowest) such item is used.\n.\\\" METHOD: itemconfigure\n.TP\n\\fIpathName \\fBitemconfigure \\fItagOrId\\fR ?\\fIoption\\fR? ?\\fIvalue\\fR? ?\\fIoption value ...\\fR?\n.\nThis command is similar to the \\fBconfigure\\fR widget command except\nthat it modifies item-specific options for the items given by\n\\fItagOrId\\fR instead of modifying options for the overall\ncanvas widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for the first item given by \\fItagOrId\\fR\n(see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list). If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified). If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s) in\neach of the items given by \\fItagOrId\\fR; in\nthis case the command returns an empty string.\nThe \\fIoption\\fRs and \\fIvalue\\fRs are the same as those permissible\nin the \\fBcreate\\fR widget command when the item(s) were created;\nsee the sections describing individual item types below for details\non the legal options.\n.\\\" METHOD: lower\n.TP\n\\fIpathName \\fBlower \\fItagOrId \\fR?\\fIbelowThis\\fR?\n.\nMove all of the items given by \\fItagOrId\\fR to a new position\nin the display list just before the item given by \\fIbelowThis\\fR.\nIf \\fItagOrId\\fR refers to more than one item then all are moved\nbut the relative order of the moved items will not be changed.\n\\fIBelowThis\\fR is a tag or id; if it refers to more than one\nitem then the first (lowest) of these items in the display list is used\nas the destination location for the moved items.\nNote that this command has no effect on window items. Window items always\nobscure other item types, and the stacking order of window items is\ndetermined by the \\fBraise\\fR command and \\fBlower\\fR command, not the\n\\fBraise\\fR widget command and \\fBlower\\fR widget command for canvases.\nThis command returns an empty string.\n.\\\" METHOD: move\n.TP\n\\fIpathName \\fBmove \\fItagOrId xAmount yAmount\\fR\n.\nMove each of the items given by \\fItagOrId\\fR in the canvas coordinate\nspace by adding \\fIxAmount\\fR to the x-coordinate of each point\nassociated with the item and \\fIyAmount\\fR to the y-coordinate of\neach point associated with the item.\nThis command returns an empty string.\n.\\\" METHOD: moveto\n.TP\n\\fIpathName \\fBmoveto \\fItagOrId xPos yPos\\fR\n.\nMove the items given by \\fItagOrId\\fR in the canvas coordinate\nspace so that the first coordinate pair (the upper-left corner of the\nbounding box) of the first item (the lowest in the display list) with\ntag \\fItagOrId\\fR is located at\nposition (\\fIxPos\\fR,\\fIyPos\\fR). \\fIxPos\\fR and \\fIyPos\\fR may be\nthe empty string, in which case the corresponding coordinate\nwill be unchanged. All items matching\n\\fItagOrId\\fR remain in the same positions relative to each other.\nThis command returns an empty string.\n.\\\" METHOD: postscript\n.TP\n\\fIpathName \\fBpostscript \\fR?\\fIoption value option value ...\\fR?\n.\nGenerate a Postscript representation for part or all of the canvas.\nIf the \\fB\\-file\\fR option is specified then the Postscript is written\nto a file and an empty string is returned; otherwise the Postscript\nis returned as the result of the command.\nIf the interpreter that owns the canvas is marked as safe, the operation\nwill fail because safe interpreters are not allowed to write files.\nIf the \\fB\\-channel\\fR option is specified, the argument denotes the name\nof a channel already opened for writing. The Postscript is written to\nthat channel, and the channel is left open for further writing at the end\nof the operation.\nThe Postscript is created in Encapsulated Postscript form using\nversion 3.0 of the Document Structuring Conventions.\nNote: by default Postscript is only generated for information that\nappears in the canvas's window on the screen. If the canvas is\nfreshly created it may still have its initial size of 1x1 pixel\nso nothing will appear in the Postscript. To get around this problem\neither invoke the \\fBupdate\\fR command to wait for the canvas window\nto reach its final size, or else use the \\fB\\-width\\fR and \\fB\\-height\\fR\noptions to specify the area of the canvas to print.\nThe \\fIoption\\fR\\-\\fIvalue\\fR argument pairs provide additional\ninformation to control the generation of Postscript. The following\noptions are supported:\n.RS\n.\\\" OPTION: -channel\n.TP\n\\fB\\-channel \\fIchannelName\\fR\n.\nSpecifies the name of the channel to which to write the Postscript.\nIf this option and the \\fB\\-file\\fR option are\nnot specified then the Postscript is returned as the\nresult of the command.\n.\\\" OPTION: -colormap\n.TP\n\\fB\\-colormap \\fIvarName\\fR\n.\n\\fIVarName\\fR must be the name of an array variable\nthat specifies a color mapping to use in the Postscript.\nEach element of \\fIvarName\\fR must consist of Postscript\ncode to set a particular color value (e.g.\n.QW \"\\fB1.0 1.0 0.0 setrgbcolor\\fR\" ).\nWhen outputting color information in the Postscript, Tk checks\nto see if there is an element of \\fIvarName\\fR with the same\nname as the color.\nIf so, Tk uses the value of the element as the Postscript command\nto set the color.\n.RS\n.PP\nIf this option has not been specified, or if there is no entry\nin \\fIvarName\\fR for a given color, then Tk uses the red, green,\nand blue intensities from the X color.\n.RE\n.\\\" OPTION: -colormode\n.TP\n\\fB\\-colormode \\fImode\\fR\n.\nSpecifies how to output color information. \\fIMode\\fR must be either\n\\fBcolor\\fR (for full color output), \\fBgray\\fR (convert all colors\nto their gray-scale equivalents) or \\fBmono\\fR (convert all colors\nto black or white).\n.\\\" OPTION: -file\n.TP\n\\fB\\-file \\fIfileName\\fR\n.\nSpecifies the name of the file in which to write the Postscript.\nIf this option and the \\fB\\-channel\\fR option are\nnot specified then the Postscript is returned as the\nresult of the command.\n.\\\" OPTION: -fontmap\n.TP\n\\fB\\-fontmap \\fIvarName\\fR\n.\n\\fIVarName\\fR must be the name of an array variable\nthat specifies a font mapping to use in the Postscript.\nEach element of \\fIvarName\\fR must consist of a Tcl list with\ntwo elements, which are the name and point size of a Postscript font.\nWhen outputting Postscript commands for a particular font, Tk\nchecks to see if \\fIvarName\\fR contains an element with the same\nname as the font.\nIf there is such an element, then the font information contained in\nthat element is used in the Postscript.\nOtherwise Tk attempts to guess what Postscript font to use.\nTk's guesses generally only work for well-known fonts such as\nTimes and Helvetica and Courier, and only if the X font name does not\nomit any dashes up through the point size.\n.RS\n.PP\nFor example, \\fB\\-*\\-Courier\\-Bold\\-R\\-Normal\\-\\-*\\-120\\-*\\fR will work but\n\\fB*Courier\\-Bold\\-R\\-Normal*120*\\fR will not; Tk needs the dashes to\nparse the font name).\n.RE\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIsize\\fR\n.\nSpecifies the height of the area of the canvas to print.\nDefaults to the height of the canvas window.\n.\\\" OPTION: -pageanchor\n.TP\n\\fB\\-pageanchor \\fIanchor\\fR\n.\nSpecifies which point of the printed area of the canvas should appear over\nthe positioning point on the page (which is given by the \\fB\\-pagex\\fR\nand \\fB\\-pagey\\fR options).\n.RS\n.PP\nFor example, \\fB\\-pageanchor n\\fR means that the top center of the\narea of the canvas being printed (as it appears in the canvas window)\nshould be over the positioning point. Defaults to \\fBcenter\\fR.\n.RE\n.\\\" OPTION: -pageheight\n.TP\n\\fB\\-pageheight \\fIsize\\fR\n.\nSpecifies that the Postscript should be scaled in both x and y so\nthat the printed area is \\fIsize\\fR high on the Postscript page.\n\\fISize\\fR consists of a floating-point number followed by\n\\fBc\\fR for centimeters, \\fBi\\fR for inches, \\fBm\\fR for millimeters,\nor \\fBp\\fR or nothing for printer's points (1/72 inch).\nDefaults to the height of the printed area on the screen.\nIf both \\fB\\-pageheight\\fR and \\fB\\-pagewidth\\fR are specified then\nthe scale factor from \\fB\\-pagewidth\\fR is used (non-uniform scaling\nis not implemented).\n.\\\" OPTION: -pagewidth\n.TP\n\\fB\\-pagewidth \\fIsize\\fR\n.\nSpecifies that the Postscript should be scaled in both x and y so\nthat the printed area is \\fIsize\\fR wide on the Postscript page.\n\\fISize\\fR has the same form as for \\fB\\-pageheight\\fR.\nDefaults to the width of the printed area on the screen.\nIf both \\fB\\-pageheight\\fR and \\fB\\-pagewidth\\fR are specified then\nthe scale factor from \\fB\\-pagewidth\\fR is used (non-uniform scaling\nis not implemented).\n.\\\" OPTION: -pagex\n.TP\n\\fB\\-pagex \\fIposition\\fR\n.\n\\fIPosition\\fR gives the x-coordinate of the positioning point on\nthe Postscript page, using any of the forms allowed for \\fB\\-pageheight\\fR.\nUsed in conjunction with the \\fB\\-pagey\\fR and \\fB\\-pageanchor\\fR options\nto determine where the printed area appears on the Postscript page.\nDefaults to the center of the page.\n.\\\" OPTION: -pagey\n.TP\n\\fB\\-pagey \\fIposition\\fR\n.\n\\fIPosition\\fR gives the y-coordinate of the positioning point on\nthe Postscript page, using any of the forms allowed for \\fB\\-pageheight\\fR.\nUsed in conjunction with the \\fB\\-pagex\\fR and \\fB\\-pageanchor\\fR options\nto determine where the printed area appears on the Postscript page.\nDefaults to the center of the page.\n.\\\" OPTION: -rotate\n.TP\n\\fB\\-rotate \\fIboolean\\fR\n.\n\\fIBoolean\\fR specifies whether the printed area is to be rotated 90\ndegrees.\nIn non-rotated output the x-axis of the printed area runs along\nthe short dimension of the page\n.PQ portrait \" orientation\" ;\nin rotated output the x-axis runs along the long dimension of the page\n.PQ landscape \" orientation\" .\nDefaults to non-rotated.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIsize\\fR\n.\nSpecifies the width of the area of the canvas to print.\nDefaults to the width of the canvas window.\n.\\\" OPTION: -x\n.TP\n\\fB\\-x \\fIposition\\fR\n.\nSpecifies the x-coordinate of the left edge of the area of the\ncanvas that is to be printed, in canvas coordinates, not window\ncoordinates.\nDefaults to the coordinate of the left edge of the window.\n.\\\" OPTION: -y\n.TP\n\\fB\\-y \\fIposition\\fR\n.\nSpecifies the y-coordinate of the top edge of the area of the\ncanvas that is to be printed, in canvas coordinates, not window\ncoordinates.\nDefaults to the coordinate of the top edge of the window.\n.RE\n.\\\" METHOD: raise\n.TP\n\\fIpathName \\fBraise \\fItagOrId \\fR?\\fIaboveThis\\fR?\n.\nMove all of the items given by \\fItagOrId\\fR to a new position\nin the display list just after the item given by \\fIaboveThis\\fR.\nIf \\fItagOrId\\fR refers to more than one item then all are moved\nbut the relative order of the moved items will not be changed.\n\\fIAboveThis\\fR is a tag or id; if it refers to more than one\nitem then the last (topmost) of these items in the display list is used\nas the destination location for the moved items.\nThis command returns an empty string.\n.RS\n.PP\nNote this this command has no effect on window items. Window items always\nobscure other item types, and the stacking order of window items is\ndetermined by the \\fBraise\\fR command and \\fBlower\\fR command, not the\n\\fBraise\\fR widget command and \\fBlower\\fR widget command for canvases.\n.RE\n.\\\" METHOD: rchars\n.TP\n\\fIpathName \\fBrchars \\fItagOrId first last string\\fR\n.\nThis command causes the text or coordinates between \\fIfirst\\fR and \\fIlast\\fR\nfor each of the items indicated by \\fItagOrId\\fR to be replaced by\n\\fIstring\\fR. Each item interprets \\fIfirst\\fR and \\fIlast\\fR independently\naccording to the rules described in \\fBINDICES\\fR above. Out of the standard\nset of items, text items support this operation by altering their text as\ndirected, and line and polygon items support this operation by altering their\ncoordinate list (in which case \\fIstring\\fR should be a list of coordinates to\nuse as a replacement). The other items ignore this operation.\n.\\\" METHOD: rotate\n.TP\n\\fIpathName \\fBrotate \\fItagOrId xOrigin yOrigin angle\\fR\n.VS \"9.0, TIP164\"\nRotate the coordinates of all of the items given by \\fItagOrId\\fR in canvas\ncoordinate space.\n\\fIXOrigin\\fR and \\fIyOrigin\\fR identify the origin for the rotation\noperation and \\fIangle\\fR identifies the amount to rotate the coordinates\nanticlockwise, in degrees. (Negative values rotate clockwise.)\nThis command returns an empty string.\n.RS\n.PP\nImplementation note: not all item types work the same with rotations. In\nparticular,\\fB bitmap\\fR,\\fB image\\fR,\\fB text\\fR and\\fB window\\fR items only\nrotate their anchor points and do not rotate the items themselves about those\npoints, and the \\fBarc\\fR, \\fBoval\\fR and \\fBrectangle\\fR types rotate about a\ncomputed center point instead of moving the bounding box coordinates directly.\n.PP\nSome items (currently \\fBarc\\fR and\\fB text\\fR) have angles in their options;\nthis command \\fIdoes not\\fR affect those options.\n.RE\n.VE \"9.0, TIP164\"\n.\\\" METHOD: scale\n.TP\n\\fIpathName \\fBscale \\fItagOrId xOrigin yOrigin xScale yScale\\fR\n.\nRescale the coordinates of all of the items given by \\fItagOrId\\fR in canvas\ncoordinate space.\n\\fIXOrigin\\fR and \\fIyOrigin\\fR identify the origin for the scaling\noperation and \\fIxScale\\fR and \\fIyScale\\fR identify the scale\nfactors for x- and y-coordinates, respectively (a scale factor of\n1.0 implies no change to that coordinate).\nFor each of the points defining each item, the x-coordinate is\nadjusted to change the distance from \\fIxOrigin\\fR by a factor\nof \\fIxScale\\fR.\nSimilarly, each y-coordinate is adjusted to change the distance\nfrom \\fIyOrigin\\fR by a factor of \\fIyScale\\fR.\nThis command returns an empty string.\n.RS\n.PP\nNote that some items have only a single pair of coordinates (e.g., text,\nimages and windows) and so scaling of them by this command can only move them\naround.\n.RE\n.\\\" METHOD: scan\n.TP\n\\fIpathName \\fBscan\\fI option args\\fR\n.\nThis command is used to implement scanning on canvases. It has\ntwo forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBscan mark \\fIx y\\fR\n.\nRecords \\fIx\\fR and \\fIy\\fR and the canvas's current view; used\nin conjunction with later \\fBscan dragto\\fR commands.\nTypically this command is associated with a mouse button press in\nthe widget and \\fIx\\fR and \\fIy\\fR are the coordinates of the\nmouse. It returns an empty string.\n.TP\n\\fIpathName \\fBscan dragto \\fIx y ?gain?\\fR\n.\nThis command computes the difference between its \\fIx\\fR and \\fIy\\fR\narguments (which are typically mouse coordinates) and the \\fIx\\fR and\n\\fIy\\fR arguments to the last \\fBscan mark\\fR command for the widget.\nIt then adjusts the view by \\fIgain\\fR times the\ndifference in coordinates, where \\fIgain\\fR defaults to 10.\nThis command is typically associated\nwith mouse motion events in the widget, to produce the effect of\ndragging the canvas at high speed through its window. The return\nvalue is an empty string.\n.RE\n.\\\" METHOD: select\n.TP\n\\fIpathName \\fBselect \\fIoption\\fR ?\\fItagOrId arg\\fR?\n.\nManipulates the selection in one of several ways, depending on\n\\fIoption\\fR.\nThe command may take any of the forms described below.\nIn all of the descriptions below, \\fItagOrId\\fR must refer to\nan item that supports indexing and selection; if it refers to\nmultiple items then the first of\nthese that supports indexing and the selection is used.\n\\fIIndex\\fR gives a textual description of a position\nwithin \\fItagOrId\\fR, as described in \\fBINDICES\\fR above.\n.RS\n.TP\n\\fIpathName \\fBselect adjust \\fItagOrId index\\fR\n.\nLocate the end of the selection in \\fItagOrId\\fR nearest\nto the character given by \\fIindex\\fR, and adjust that\nend of the selection to be at \\fIindex\\fR (i.e. including\nbut not going beyond \\fIindex\\fR).\nThe other end of the selection is made the anchor point\nfor future \\fBselect to\\fR commands.\nIf the selection is not currently in \\fItagOrId\\fR then\nthis command behaves the same as the \\fBselect to\\fR widget\ncommand.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselect clear\\fR\n.\nClear the selection if it is in this widget.\nIf the selection is not in this widget then the command\nhas no effect.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselect from \\fItagOrId index\\fR\n.\nSet the selection anchor point for the widget to be just\nbefore the character\ngiven by \\fIindex\\fR in the item given by \\fItagOrId\\fR.\nThis command does not change the selection; it just sets\nthe fixed end of the selection for future \\fBselect to\\fR\ncommands.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselect item\\fR\n.\nReturns the id of the selected item, if the selection is in an\nitem in this canvas.\nIf the selection is not in this canvas then an empty string\nis returned.\n.TP\n\\fIpathName \\fBselect to \\fItagOrId index\\fR\n.\nSet the selection to consist of those characters of \\fItagOrId\\fR\nbetween the selection anchor point and\n\\fIindex\\fR.\nThe new selection will include the character given by \\fIindex\\fR;\nit will include the character given by the anchor point only if\n\\fIindex\\fR is greater than or equal to the anchor point.\nThe anchor point is determined by the most recent \\fBselect adjust\\fR\nor \\fBselect from\\fR command for this widget.\nIf the selection anchor point for the widget is not currently in\n\\fItagOrId\\fR, then it is set to the same character given\nby \\fIindex\\fR.\nReturns an empty string.\n.RE\n.\\\" METHOD: type\n.TP\n\\fIpathName \\fBtype\\fI tagOrId\\fR\n.\nReturns the type of the item given by \\fItagOrId\\fR, such as\n\\fBrectangle\\fR or \\fBtext\\fR.\nIf \\fItagOrId\\fR refers to more than one item, then the type\nof the first item in the display list is returned.\nIf \\fItagOrId\\fR does not refer to any items at all then\nan empty string is returned.\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fR?\\fIargs\\fR?\n.\nThis command is used to query and change the horizontal position of the\ninformation displayed in the canvas's window.\nIt can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1; together they describe\nthe horizontal span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the canvas's area (as defined by the \\fB\\-scrollregion\\fR option)\nis off-screen to the left, the middle 40% is visible\nin the window, and 40% of the canvas is off-screen to the right.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that \\fIfraction\\fR of the\ntotal width of the canvas is off-screen to the left.\n\\fIFraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR or an abbreviation\nof one of these.\nIf \\fIwhat is \\fBpages\\fR then the view\nadjusts in units of nine-tenths the window's width.\nIf \\fInumber\\fR is negative then information farther to the left\nbecomes visible; if it is positive then information farther to the right\nbecomes visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts left or right in units\nof the \\fBxScrollIncrement\\fR option, if it is greater than zero,\nor in units of one-tenth the window's width otherwise.\n.RE\n.\\\" METHOD: yview\n.TP\n\\fIpathName \\fByview ?\\fIargs\\fR?\n.\nThis command is used to query and change the vertical position of the\ninformation displayed in the canvas's window.\nIt can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fByview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1; together they describe\nthe vertical span that is visible in the window.\nFor example, if the first element is .6 and the second element is 1.0,\nthe lowest 40% of the canvas's area (as defined by the \\fB\\-scrollregion\\fR\noption) is visible in the window.\nThese are the same values passed to scrollbars via the \\fB\\-yscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fByview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that \\fIfraction\\fR of the canvas's\narea is off-screen to the top.\n\\fIFraction\\fR is a fraction between 0 and 1.\n.TP\n\\fIpathName \\fByview scroll \\fInumber what\\fR\n.\nThis command adjusts the view in the window up or down according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR.\nIf \\fIwhat\\fR is \\fBpages\\fR then\nthe view adjusts in units of nine-tenths the window's height.\nIf \\fInumber\\fR is negative then higher information becomes\nvisible; if it is positive then lower information\nbecomes visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts up or down in units\nof the \\fByScrollIncrement\\fR option, if it is greater than zero,\nor in units of one-tenth the window's height otherwise.\n.RE\n.SH \"OVERVIEW OF ITEM TYPES\"\n.PP\nThe sections below describe the various types of items supported\nby canvas widgets. Each item type is characterized by two things:\nfirst, the form of the \\fBcreate\\fR command used to create\ninstances of the type; and second, a set of configuration options\nfor items of that type, which may be used in the\n\\fBcreate\\fR and \\fBitemconfigure\\fR widget commands.\nMost items do not support indexing or selection or the commands\nrelated to them, such as \\fBindex\\fR and \\fBinsert\\fR.\nWhere items do support these facilities, it is noted explicitly\nin the descriptions below.\nAt present, text, line and polygon items provide this support.\nFor lines and polygons the indexing facility is used to manipulate\nthe coordinates of the item.\n.SS \"COMMON ITEM OPTIONS\"\n.PP\nMany items share a common set of options. These options are\nexplained here, and then referred to be each widget type for brevity.\n.\\\" OPTION: -anchor\n.TP\n\\fB\\-anchor \\fIanchorPos\\fR\n.\n\\fIAnchorPos\\fR tells how to position the item relative to the\npositioning point for the item; it may have any of the forms\naccepted by \\fBTk_GetAnchor\\fR. For example, if \\fIanchorPos\\fR\nis \\fBcenter\\fR then the item is centered on the point; if\n\\fIanchorPos\\fR is \\fBn\\fR then the item will be drawn so that\nits top center point is at the positioning point.\nThis option defaults to \\fBcenter\\fR.\n.\\\" OPTION: -dash\n.TP\n\\fB\\-dash \\fIpattern\\fR\n.\\\" OPTION: -activedash\n.TP\n\\fB\\-activedash \\fIpattern\\fR\n.\\\" OPTION: -disableddash\n.TP\n\\fB\\-disableddash \\fIpattern\\fR\n.\nThese options specify dash patterns for the normal, active\nstate, and disabled state of an item.\n\\fIpattern\\fR may have any of the forms accepted by \\fBTk_GetDash\\fR.\nIf the dash options are omitted then the default is a solid outline.\nSee \\fBDASH PATTERNS\\fR for more information.\n.\\\" OPTION: -dashoffset\n.TP\n\\fB\\-dashoffset \\fIoffset\\fR\n.\nThe starting \\fIoffset\\fR in pixels into the pattern provided by the\n\\fB\\-dash\\fR option. \\fB\\-dashoffset\\fR is ignored if there is no\n\\fB\\-dash\\fR pattern. The \\fIoffset\\fR may have any of the forms described\nin the \\fBCOORDINATES\\fR section above.\n.\\\" OPTION: -fill\n.TP\n\\fB\\-fill \\fIcolor\\fR\n.\\\" OPTION: -activefill\n.TP\n\\fB\\-activefill \\fIcolor\\fR\n.\\\" OPTION: -disabledfill\n.TP\n\\fB\\-disabledfill \\fIcolor\\fR\n.\nThese options specify the color to be used to fill item's area.\nin its normal, active, and disabled states.\nThe even-odd fill rule is used.\n\\fIColor\\fR may have any of the forms accepted by \\fBTk_GetColor\\fR.\nFor the line item, it specifies the color of the line drawn.\nFor the text item, it specifies the foreground color of the text.\nIf \\fIcolor\\fR is an empty string (the default for all canvas items\nexcept line and text), then the item will not be filled.\n.\\\" OPTION: -outline\n.TP\n\\fB\\-outline \\fIcolor\\fR\n.\\\" OPTION: -activeoutline\n.TP\n\\fB\\-activeoutline \\fIcolor\\fR\n.\\\" OPTION: -disabledoutline\n.TP\n\\fB\\-disabledoutline \\fIcolor\\fR\n.\nThese options specify the color that should be used to draw the\noutline of the item in its normal, active and disabled states.\n\\fIColor\\fR may have any of the forms accepted by \\fBTk_GetColor\\fR.\nIf \\fIcolor\\fR is specified as an empty string then no outline is drawn\nfor the item.\n.\\\" OPTION: -offset\n.TP\n\\fB\\-offset \\fIoffset\\fR\n.\nSpecifies the offset of stipples. The offset value can be of the form\n\\fBx,y\\fR or \\fIside\\fR, where side can be \\fBn\\fR, \\fBne\\fR, \\fBe\\fR,\n\\fBse\\fR, \\fBs\\fR, \\fBsw\\fR, \\fBw\\fR, \\fBnw\\fR, or \\fBcenter\\fR. In the\nfirst case the origin is the origin of the toplevel of the current window.\nFor the canvas itself and canvas objects the origin is the canvas origin,\nbut putting \\fB#\\fR in front of the coordinate pair indicates using the\ntoplevel origin instead. For canvas objects, the \\fB\\-offset\\fR option is\nused for stippling as well. For the line and polygon canvas items you can\nalso specify an index as argument, which connects the stipple origin to one\nof the coordinate points of the line/polygon. Note that stipple offsets are\n\\fIonly supported on X11\\fR; they are silently ignored on other platforms.\n.\\\" OPTION: -outlinestipple\n.TP\n\\fB\\-outlinestipple \\fIbitmap\\fR\n.\\\" OPTION: -activeoutlinestipple\n.TP\n\\fB\\-activeoutlinestipple \\fIbitmap\\fR\n.\\\" OPTION: -disabledoutlinestipple\n.TP\n\\fB\\-disabledoutlinestipple \\fIbitmap\\fR\n.\nThese options specify stipple patterns that should be used to draw the\noutline of the item in its normal, active and disabled states.\nIndicates that the outline for the item should be drawn with a stipple pattern;\n\\fIbitmap\\fR specifies the stipple pattern to use, in any of the\nforms accepted by \\fBTk_GetBitmap\\fR.\nIf the \\fB\\-outline\\fR option has not been specified then this option\nhas no effect.\nIf \\fIbitmap\\fR is an empty string (the default), then the outline is drawn\nin a solid fashion.\n\\fINote that stipples are not well supported on platforms that do not\nuse X11 as their drawing API.\\fR\n.\\\" OPTION: -outlineoffset\n.TP\n\\fB\\-outlineoffset \\fIoffset\\fR\n.\nSpecifies the offset of the stipple pattern used for outlines, in the same way\nthat the \\fB\\-outline\\fR option controls fill stipples. (See the\n\\fB\\-outline\\fR option for a description of the syntax of \\fIoffset\\fR.)\n.\\\" OPTION: -stipple\n.TP\n\\fB\\-stipple \\fIbitmap\\fR\n.\\\" OPTION: -activestipple\n.TP\n\\fB\\-activestipple \\fIbitmap\\fR\n.\\\" OPTION: -disabledstipple\n.TP\n\\fB\\-disabledstipple \\fIbitmap\\fR\n.\nThese options specify stipple patterns that should be used to fill\nthe item in its normal, active and disabled states.\n\\fIbitmap\\fR specifies the stipple pattern to use, in any of the\nforms accepted by \\fBTk_GetBitmap\\fR.\nIf the \\fB\\-fill\\fR option has not been specified then this option\nhas no effect.\nIf \\fIbitmap\\fR is an empty string (the default), then filling is done\nin a solid fashion.\nFor the text item, it affects the actual text.\n\\fINote that stipples are not well supported on platforms that do not\nuse X11 as their drawing API.\\fR\n.\\\" OPTION: -state\n.TP\n\\fB\\-state \\fIstate\\fR\n.\nThis allows an item to override the canvas widget's global \\fIstate\\fR\noption. It takes the same values:\n\\fInormal\\fR, \\fIdisabled\\fR or \\fIhidden\\fR.\n.\\\" OPTION: -tags\n.TP\n\\fB\\-tags \\fItagList\\fR\n.\nSpecifies a set of tags to apply to the item.\n\\fITagList\\fR consists of a list of tag names, which replace any\nexisting tags for the item. \\fITagList\\fR may be an empty list.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIoutlineWidth\\fR\n.\\\" OPTION: -activewidth\n.TP\n\\fB\\-activewidth \\fIoutlineWidth\\fR\n.\\\" OPTION: -disabledwidth\n.TP\n\\fB\\-disabledwidth \\fIoutlineWidth\\fR\n.\nThese options specify the width of the outline to be drawn around\nthe item's region, in its normal, active and disabled states.\n\\fIoutlineWidth\\fR may be in any of the forms described in the\n\\fBCOORDINATES\\fR section above.\nIf the \\fB\\-outline\\fR option has been specified as an empty string then\nthis option has no effect. This option defaults to 1.0.\nFor arcs, wide outlines will be drawn centered on the edges of the\narc's region.\n.SH \"STANDARD ITEM TYPES\"\n.SS \"ARC ITEMS\"\n.PP\nItems of type \\fBarc\\fR appear on the display as arc-shaped regions.\nAn arc is a section of an oval delimited by two angles (specified\nby either the \\fB\\-start\\fR and \\fB\\-extent\\fR options or the \\fB\\-height\\fR\noption) and displayed in one of several ways (specified by the \\fB\\-style\\fR\noption).\nArcs are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate arc \\fIx1 y1 x2 y2 \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate arc \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR or \\fIcoordList\\fR give\nthe coordinates of two diagonally opposite corners of a\nrectangular region enclosing the oval that defines the arc (except when\n\\fB\\-height\\fR is specified - see below).\n.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. An arc item becomes the current item when the mouse pointer is\nover any part that is painted or (when fully transparent) that would be\npainted if both the \\fB\\-fill\\fR and \\fB\\-outline\\fR options were non-empty.\n.PP\nThe following standard options are supported by arcs:\n.DS\n.ta 3i\n\\fB\\-dash\\fR\t\\fB\\-activedash\\fR\n\\fB\\-disableddash\\fR\t\\fB\\-dashoffset\\fR\n\\fB\\-fill\\fR\t\\fB\\-activefill\\fR\n\\fB\\-disabledfill\\fR\t\\fB\\-offset\\fR\n\\fB\\-outline\\fR\t\\fB\\-activeoutline\\fR\n\\fB\\-disabledoutline\\fR\t\\fB\\-outlineoffset\\fR\n\\fB\\-outlinestipple\\fR\t\\fB\\-activeoutlinestipple\\fR\n\\fB\\-disabledoutlinestipple\\fR\t\\fB\\-stipple\\fR\n\\fB\\-activestipple\\fR\t\\fB\\-disabledstipple\\fR\n\\fB\\-state\\fR\t\\fB\\-tags\\fR\n\\fB\\-width\\fR\t\\fB\\-activewidth\\fR\n\\fB\\-disabledwidth\\fR\n.DE\nThe following extra options are supported for arcs:\n.\\\" OPTION: -extent\n.TP\n\\fB\\-extent \\fIdegrees\\fR\n.\nSpecifies the size of the angular range occupied by the arc.\nThe arc's range extends for \\fIdegrees\\fR degrees counter-clockwise\nfrom the starting angle given by the \\fB\\-start\\fR option.\n\\fIDegrees\\fR may be negative.\nIf it is greater than 360 or less than \\-360, then \\fIdegrees\\fR\nmodulo 360 is used as the extent.\n.\\\" OPTION: -start\n.TP\n\\fB\\-start \\fIdegrees\\fR\n.\nSpecifies the beginning of the angular range occupied by the\narc.\n\\fIDegrees\\fR is given in units of degrees measured counter-clockwise\nfrom the 3-o'clock position; it may be either positive or negative.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIdistance\\fR\n.\nProvides a shortcut for creating a circular arc segment by defining the\ndistance of the mid-point of the arc from its chord. When this option\nis used the coordinates are interpreted as the start and end coordinates\nof the chord, and the options \\fB\\-start\\fR and \\fB\\-extent\\fR are ignored.\nThe value of \\fIdistance\\fR has the following meaning:\n.RS\n.PP\n.RS\n\\fIdistance\\fR > 0 creates a clockwise arc\n.br\n\\fIdistance\\fR < 0 creates an counter-clockwise arc\n.br\n\\fIdistance\\fR = 0 creates an arc as if this option had not been specified\n.RE\n.PP\nIf you want the arc to have a specific radius, \\fIr\\fR, use the formula:\n.PP\n.RS\n\\fIdistance\\fR = \\fIr\\fR \\(+- sqrt(\\fIr\\fR**2 - (chordLength / 2)**2)\n.RE\n.PP\nchoosing the minus sign for the minor arc and the plus sign for the major arc.\n.PP\nNote that \\fBitemcget \\-height\\fR always returns 0 so that introspection code\ncan be kept simple.\n.RE\n.\\\" OPTION: -style\n.TP\n\\fB\\-style \\fItype\\fR\n.\nSpecifies how to draw the arc. If \\fItype\\fR is \\fBpieslice\\fR\n(the default) then the arc's region is defined by a section\nof the oval's perimeter plus two line segments, one between the center\nof the oval and each end of the perimeter section.\nIf \\fItype\\fR is \\fBchord\\fR then the arc's region is defined\nby a section of the oval's perimeter plus a single line segment\nconnecting the two end points of the perimeter section.\nIf \\fItype\\fR is \\fBarc\\fR then the arc's region consists of\na section of the perimeter alone.\nIn this last case the \\fB\\-fill\\fR option is ignored.\n.SS \"BITMAP ITEMS\"\n.PP\nItems of type \\fBbitmap\\fR appear on the display as images with\ntwo colors, foreground and background.\nBitmaps are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate bitmap \\fIx y \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate bitmap \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx\\fR and \\fIy\\fR or \\fIcoordList\\fR (which must have two\nelements) specify the coordinates of a\npoint used to position the bitmap on the display, as controlled by the\n\\fB\\-anchor\\fR option.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. A bitmap item becomes the current item when the mouse pointer\nis over any part of its bounding box.\n.PP\nThe following standard options are supported by bitmaps:\n.DS\n.ta 3i\n\\fB\\-anchor\\fR\t\\fB\\-state\\fR\n\\fB\\-tags\\fR\n.DE\nThe following extra options are supported for bitmaps:\n.\\\" OPTION: -background\n.TP\n\\fB\\-background \\fIcolor\\fR\n.\\\" OPTION: -activebackground\n.TP\n\\fB\\-activebackground \\fIcolor\\fR\n.\\\" OPTION: -disabledbackground\n.TP\n\\fB\\-disabledbackground \\fIcolor\\fR\n.\nSpecifies the color to use for each of the bitmap's\n.QW 0\nvalued pixels in its normal, active and disabled states.\n\\fIColor\\fR may have any of the forms accepted by \\fBTk_GetColor\\fR.\nIf this option is not specified, or if it is specified as an empty\nstring, then nothing is displayed where the bitmap pixels are 0; this\nproduces a transparent effect.\n.\\\" OPTION: -bitmap\n.TP\n\\fB\\-bitmap \\fIbitmap\\fR\n.\\\" OPTION: -activebitmap\n.TP\n\\fB\\-activebitmap \\fIbitmap\\fR\n.\\\" OPTION: -disabledbitmap\n.TP\n\\fB\\-disabledbitmap \\fIbitmap\\fR\n.\nThese options specify the bitmaps to display in the item in its normal,\nactive and disabled states.\n\\fIBitmap\\fR may have any of the forms accepted by \\fBTk_GetBitmap\\fR.\n.\\\" OPTION: -foreground\n.TP\n\\fB\\-foreground \\fIcolor\\fR\n.\\\" OPTION: -activeforeground\n.TP\n\\fB\\-activeforeground \\fIcolor\\fR\n.\\\" OPTION: -disabledforeground\n.TP\n\\fB\\-disabledforeground \\fIcolor\\fR\n.\nThese options specify the color to use for each of the bitmap's\n.QW 1\nvalued pixels in its normal, active and disabled states.\n\\fIColor\\fR may have any of the forms accepted by \\fBTk_GetColor\\fR.\n.SS \"IMAGE ITEMS\"\n.PP\nItems of type \\fBimage\\fR are used to display images on a\ncanvas.\nImages are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate image \\fIx y \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate image \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx\\fR and \\fIy\\fR or \\fIcoordList\\fR specify the coordinates of a\npoint used to position the image on the display, as controlled by the\n\\fB\\-anchor\\fR option.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. An image item becomes the current item when the mouse pointer\nis over any part of its bounding box.\n.PP\nThe following standard options are supported by images:\n.DS\n.ta 3i\n\\fB\\-anchor\\fR\t\\fB\\-state\\fR\n\\fB\\-tags\\fR\n.DE\nThe following extra options are supported for images:\n.\\\" OPTION: -image\n.TP\n\\fB\\-image \\fIname\\fR\n.\\\" OPTION: -activeimage\n.TP\n\\fB\\-activeimage \\fIname\\fR\n.\\\" OPTION: -disabledimage\n.TP\n\\fB\\-disabledimage \\fIname\\fR\n.\nSpecifies the name of the images to display in the item in is normal,\nactive and disabled states.\nThis image must have been created previously with the\n\\fBimage create\\fR command.\n.SS \"LINE ITEMS\"\n.PP\nItems of type \\fBline\\fR appear on the display as one or more connected\nline segments or curves.\nLine items support coordinate indexing operations using the \\fBdchars\\fR,\n\\fBindex\\fR and \\fBinsert\\fR widget commands.\nLines are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate line \\fIx1 y1... xn yn \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate line \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx1\\fR through \\fIyn\\fR or \\fIcoordList\\fR give\nthe coordinates for a series of two or more points that describe\na series of connected line segments.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. A line item is the current item whenever the mouse pointer is\nover any segment of the line, whether drawn or not and whether or not the line\nis smoothed.\n.PP\nThe following standard options are supported by lines:\n.DS\n.ta 3i\n\\fB\\-dash\\fR\t\\fB\\-activedash\\fR\n\\fB\\-disableddash\\fR\t\\fB\\-dashoffset\\fR\n\\fB\\-fill\\fR\t\\fB\\-activefill\\fR\n\\fB\\-disabledfill\\fR\t\\fB\\-stipple\\fR\n\\fB\\-activestipple\\fR\t\\fB\\-disabledstipple\\fR\n\\fB\\-state\\fR\t\\fB\\-tags\\fR\n\\fB\\-width\\fR\t\\fB\\-activewidth\\fR\n\\fB\\-disabledwidth\\fR\n.DE\nThe following extra options are supported for lines:\n.\\\" OPTION: -arrow\n.TP\n\\fB\\-arrow \\fIwhere\\fR\n.\nIndicates whether or not arrowheads are to be drawn at one or both\nends of the line.\n\\fIWhere\\fR must have one of the values \\fBnone\\fR (for no arrowheads),\n\\fBfirst\\fR (for an arrowhead at the first point of the line),\n\\fBlast\\fR (for an arrowhead at the last point of the line), or\n\\fBboth\\fR (for arrowheads at both ends).\nThis option defaults to \\fBnone\\fR.\nWhen requested to draw an arrowhead, Tk internally adjusts the corresponding\nline end point so that the rendered line ends at the neck of the arrowhead\nrather than at its tip so that the line doesn't extend past the edge of the\narrowhead. This may trigger a \\fBLeave\\fR event if the mouse is hovering this\nline end. Conversely, when removing an arrowhead Tk adjusts the corresponding\nline point the other way round, which may trigger an \\fBEnter\\fR event.\n.\\\" OPTION: -arrowshape\n.TP\n\\fB\\-arrowshape \\fIshape\\fR\n.\nThis option indicates how to draw arrowheads.\nThe \\fIshape\\fR argument must be a list with three elements, each\nspecifying a distance in any of the forms described in\nthe \\fBCOORDINATES\\fR section above.\nThe first element of the list gives the distance along the line\nfrom the neck of the arrowhead to its tip.\nThe second element gives the distance along the line from the\ntrailing points of the arrowhead to the tip, and the third\nelement gives the distance from the outside edge of the line to the\ntrailing points.\nIf this option is not specified then Tk picks a\n.QW reasonable\nshape.\n.\\\" OPTION: -capstyle\n.TP\n\\fB\\-capstyle \\fIstyle\\fR\n.\nSpecifies the ways in which caps are to be drawn at the endpoints\nof the line.\n\\fIStyle\\fR may have any of the forms accepted by \\fBTk_GetCapStyle\\fR\n(\\fBbutt\\fR, \\fBprojecting\\fR, or \\fBround\\fR).\nIf this option is not specified then it defaults to \\fBbutt\\fR.\nWhere arrowheads are drawn the cap style is ignored.\n.\\\" OPTION: -joinstyle\n.TP\n\\fB\\-joinstyle \\fIstyle\\fR\n.\nSpecifies the ways in which joints are to be drawn at the vertices\nof the line.\n\\fIStyle\\fR may have any of the forms accepted by \\fBTk_GetJoinStyle\\fR\n(\\fBbevel\\fR, \\fBmiter\\fR, or \\fBround\\fR).\nIf this option is not specified then it defaults to \\fBround\\fR.\nIf the line only contains two points then this option is\nirrelevant.\n.\\\" OPTION: -smooth\n.TP\n\\fB\\-smooth \\fIsmoothMethod\\fR\n.\n\\fIsmoothMethod\\fR must have one of the forms accepted by\n\\fBTcl_GetBoolean\\fR or a line smoothing method.\nOnly \\fBtrue\\fR and \\fBraw\\fR are\nsupported in the core (with \\fBbezier\\fR being an alias for \\fBtrue\\fR),\nbut more can be added at runtime. If a boolean\nfalse value or empty string is given, no smoothing is applied. A boolean\ntruth value assumes \\fBtrue\\fR smoothing.\nIf the smoothing method is \\fBtrue\\fR, this indicates that the line\nshould be drawn as a curve, rendered as a set of quadratic splines: one spline\nis drawn for the first and second line segments, one for the second\nand third, and so on. Straight-line segments can be generated within\na curve by duplicating the end-points of the desired line segment.\nIf the smoothing method is \\fBraw\\fR, this indicates that the line\nshould also be drawn as a curve but where the list of coordinates is\nsuch that the first coordinate pair (and every third coordinate pair\nthereafter) is a knot point on a cubic Bezier curve, and the other\ncoordinates are control points on the cubic Bezier curve. Straight\nline segments can be generated within a curve by making control points\nequal to their neighbouring knot points. If the last point is a\ncontrol point and not a knot point, the point is repeated (one or two\ntimes) so that it also becomes a knot point.\n.\\\" OPTION: -splinesteps\n.TP\n\\fB\\-splinesteps \\fInumber\\fR\n.\nSpecifies the degree of smoothness desired for curves: each spline\nwill be approximated with \\fInumber\\fR line segments. This\noption is ignored unless the \\fB\\-smooth\\fR option is true or \\fBraw\\fR.\n.SS \"OVAL ITEMS\"\n.PP\nItems of type \\fBoval\\fR appear as circular or oval regions on\nthe display. Each oval may have an outline, a fill, or\nboth. Ovals are created with widget commands of the\nfollowing form:\n.CS\n\\fIpathName \\fBcreate oval \\fIx1 y1 x2 y2 \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate oval \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR or \\fIcoordList\\fR give\nthe coordinates of two diagonally opposite corners of a\nrectangular region enclosing the oval.\nThe oval will include the top and left edges of the rectangle\nnot the lower or right edges.\nIf the region is square then the resulting oval is circular;\notherwise it is elongated in shape.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. An oval item becomes the current item when the mouse pointer is\nover any part that is painted or (when fully transparent) that would be\npainted if both the \\fB\\-fill\\fR and \\fB\\-outline\\fR options were non-empty.\n.PP\nThe following standard options are supported by ovals:\n.DS\n.ta 3i\n\\fB\\-dash\\fR\t\\fB\\-activedash\\fR\n\\fB\\-disableddash\\fR\t\\fB\\-dashoffset\\fR\n\\fB\\-fill\\fR\t\\fB\\-activefill\\fR\n\\fB\\-disabledfill\\fR\t\\fB\\-offset\\fR\n\\fB\\-outline\\fR\t\\fB\\-activeoutline\\fR\n\\fB\\-disabledoutline\\fR\t\\fB\\-outlineoffset\\fR\n\\fB\\-outlinestipple\\fR\t\\fB\\-activeoutlinestipple\\fR\n\\fB\\-disabledoutlinestipple\\fR\t\\fB\\-stipple\\fR\n\\fB\\-activestipple\\fR\t\\fB\\-disabledstipple\\fR\n\\fB\\-state\\fR\t\\fB\\-tags\\fR\n\\fB\\-width\\fR\t\\fB\\-activewidth\\fR\n\\fB\\-disabledwidth\\fR\n.DE\nThere are no oval-specific options.\n.SS \"POLYGON ITEMS\"\n.PP\nItems of type \\fBpolygon\\fR appear as polygonal or curved filled regions\non the display.\nPolygon items support coordinate indexing operations using the \\fBdchars\\fR,\n\\fBindex\\fR and \\fBinsert\\fR widget commands.\nPolygons are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate polygon \\fIx1 y1 ... xn yn \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate polygon \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx1\\fR through \\fIyn\\fR or \\fIcoordList\\fR specify the\ncoordinates for three or more points that define a polygon.\nThe first point should not be repeated as the last to\nclose the shape; Tk will automatically close the periphery between\nthe first and last points.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. A polygon item is the current item whenever the mouse pointer\nis over any part of the polygon, whether drawn or not and whether or not the\noutline is smoothed.\n.PP\nThe following standard options are supported by polygons:\n.DS\n.ta 3i\n\\fB\\-dash\\fR\t\\fB\\-activedash\\fR\n\\fB\\-disableddash\\fR\t\\fB\\-dashoffset\\fR\n\\fB\\-fill\\fR\t\\fB\\-activefill\\fR\n\\fB\\-disabledfill\\fR\t\\fB\\-offset\\fR\n\\fB\\-outline\\fR\t\\fB\\-activeoutline\\fR\n\\fB\\-disabledoutline\\fR\t\\fB\\-outlineoffset\\fR\n\\fB\\-outlinestipple\\fR\t\\fB\\-activeoutlinestipple\\fR\n\\fB\\-disabledoutlinestipple\\fR\t\\fB\\-stipple\\fR\n\\fB\\-activestipple\\fR\t\\fB\\-disabledstipple\\fR\n\\fB\\-state\\fR\t\\fB\\-tags\\fR\n\\fB\\-width\\fR\t\\fB\\-activewidth\\fR\n\\fB\\-disabledwidth\\fR\n.DE\nThe following extra options are supported for polygons:\n.\\\" OPTION: -joinstyle\n.TP\n\\fB\\-joinstyle \\fIstyle\\fR\n.\nSpecifies the ways in which joints are to be drawn at the vertices\nof the outline.\n\\fIStyle\\fR may have any of the forms accepted by \\fBTk_GetJoinStyle\\fR\n(\\fBbevel\\fR, \\fBmiter\\fR, or \\fBround\\fR).\nIf this option is not specified then it defaults to \\fBround\\fR.\n.\\\" OPTION: -smooth\n.TP\n\\fB\\-smooth \\fIboolean\\fR\n.\n\\fIBoolean\\fR must have one of the forms accepted by \\fBTcl_GetBoolean\\fR\nor a line smoothing method. Only \\fBtrue\\fR and \\fBraw\\fR are\nsupported in the core (with \\fBbezier\\fR being an alias for \\fBtrue\\fR),\nbut more can be added at runtime. If a boolean\nfalse value or empty string is given, no smoothing is applied. A boolean\ntruth value assumes \\fBtrue\\fR smoothing.\nIf the smoothing method is \\fBtrue\\fR, this indicates that the polygon\nshould be drawn as a curve, rendered as a set of quadratic splines: one spline\nis drawn for the first and second line segments, one for the second\nand third, and so on. Straight-line segments can be generated within\na curve by duplicating the end-points of the desired line segment.\nIf the smoothing method is \\fBraw\\fR, this indicates that the polygon\nshould also be drawn as a curve but where the list of coordinates is\nsuch that the first coordinate pair (and every third coordinate pair\nthereafter) is a knot point on a cubic Bezier curve, and the other\ncoordinates are control points on the cubic Bezier curve. Straight\nline segments can be generated within a curve by making control points\nequal to their neighbouring knot points. If the last point is not the\nsecond point of a pair of control points, the point is repeated (one or two\ntimes) so that it also becomes the second point of a pair of control\npoints (the associated knot point will be the first control point).\n.\\\" OPTION: -splinesteps\n.TP\n\\fB\\-splinesteps \\fInumber\\fR\n.\nSpecifies the degree of smoothness desired for curves: each spline\nwill be approximated with \\fInumber\\fR line segments. This\noption is ignored unless the \\fB\\-smooth\\fR option is true or \\fBraw\\fR.\n.PP\nPolygon items are different from other items such as rectangles, ovals\nand arcs in that interior points are considered to be\n.QW inside\na polygon (e.g. for purposes of the \\fBfind closest\\fR and\n\\fBfind overlapping\\fR widget commands) even if it is not filled.\nFor most other item types, an\ninterior point is considered to be inside the item only if the item\nis filled or if it has neither a fill nor an outline. If you would\nlike an unfilled polygon whose interior points are not considered\nto be inside the polygon, use a line item instead.\n.SS \"RECTANGLE ITEMS\"\n.PP\nItems of type \\fBrectangle\\fR appear as rectangular regions on\nthe display. Each rectangle may have an outline, a fill, or\nboth. Rectangles are created with widget commands of the\nfollowing form:\n.CS\n\\fIpathName \\fBcreate rectangle \\fIx1 y1 x2 y2 \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate rectangle \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx1\\fR, \\fIy1\\fR, \\fIx2\\fR, and \\fIy2\\fR or \\fIcoordList\\fR\n(which must have four elements) give\nthe coordinates of two diagonally opposite corners of the rectangle\n(the rectangle will include its upper and left edges but not\nits lower or right edges).\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. A rectangle item becomes the current item when the mouse\npointer is over any part that is painted or (when fully transparent) that\nwould be painted if both the \\fB\\-fill\\fR and \\fB\\-outline\\fR options were\nnon-empty.\n.PP\nThe following standard options are supported by rectangles:\n.DS\n.ta 3i\n\\fB\\-dash\\fR\t\\fB\\-activedash\\fR\n\\fB\\-disableddash\\fR\t\\fB\\-dashoffset\\fR\n\\fB\\-fill\\fR\t\\fB\\-activefill\\fR\n\\fB\\-disabledfill\\fR\t\\fB\\-offset\\fR\n\\fB\\-outline\\fR\t\\fB\\-activeoutline\\fR\n\\fB\\-disabledoutline\\fR\t\\fB\\-outlineoffset\\fR\n\\fB\\-outlinestipple\\fR\t\\fB\\-activeoutlinestipple\\fR\n\\fB\\-disabledoutlinestipple\\fR\t\\fB\\-stipple\\fR\n\\fB\\-activestipple\\fR\t\\fB\\-disabledstipple\\fR\n\\fB\\-state\\fR\t\\fB\\-tags\\fR\n\\fB\\-width\\fR\t\\fB\\-activewidth\\fR\n\\fB\\-disabledwidth\\fR\n.DE\nThere are no rectangle-specific options.\n.SS \"TEXT ITEMS\"\n.PP\nA text item displays a string of characters on the screen in one\nor more lines.\nText items support indexing, editing and selection through the \\fBdchars\\fR\nwidget command, the \\fBfocus\\fR widget command, the \\fBicursor\\fR widget\ncommand, the \\fBindex\\fR widget command, the \\fBinsert\\fR widget command, and\nthe \\fBselect\\fR widget command.\nText items are created with widget commands of the following\nform:\n.CS\n\\fIpathName \\fBcreate text \\fIx y \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate text \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx\\fR and \\fIy\\fR or \\fIcoordList\\fR (which must have two\nelements) specify the coordinates of a\npoint used to position the text on the display (see the options\nbelow for more information on how text is displayed).\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. A text item becomes the current item when the mouse pointer\nis over any part of its bounding box.\n.PP\nThe following standard options are supported by text items:\n.DS\n.ta 3i\n\\fB\\-anchor\\fR\t\\fB\\-fill\\fR\n\\fB\\-activefill\\fR\t\\fB\\-disabledfill\\fR\n\\fB\\-stipple\\fR\t\\fB\\-activestipple\\fR\n\\fB\\-disabledstipple\\fR\t\\fB\\-state\\fR\n\\fB\\-tags\\fR\n.DE\nThe following extra options are supported for text items:\n.\\\" OPTION: -angle\n.TP\n\\fB\\-angle \\fIrotationDegrees\\fR\n.\n\\fIRotationDegrees\\fR tells how many degrees to rotate the text anticlockwise\nabout the positioning point for the text; it may have any floating-point value\nfrom 0.0 to 360.0. For example, if \\fIrotationDegrees\\fR is \\fB90\\fR, then the\ntext will be drawn vertically from bottom to top.\nThis option defaults to \\fB0.0\\fR.\n.\\\" OPTION: -font\n.TP\n\\fB\\-font \\fIfontName\\fR\n.\nSpecifies the font to use for the text item.\n\\fIFontName\\fR may be any string acceptable to \\fBTk_GetFont\\fR.\nIf this option is not specified, it defaults to a system-dependent\nfont.\n.\\\" OPTION: -justify\n.TP\n\\fB\\-justify \\fIhow\\fR\n.\nSpecifies how to justify the text within its bounding region.\n\\fIHow\\fR must be one of the values \\fBleft\\fR, \\fBright\\fR,\nor \\fBcenter\\fR.\nThis option will only matter if the text is displayed as multiple\nlines.\nIf the option is omitted, it defaults to \\fBleft\\fR.\n.\\\" OPTION: -text\n.TP\n\\fB\\-text \\fIstring\\fR\n.\n\\fIString\\fR specifies the characters to be displayed in the text item.\nNewline characters cause line breaks.\nThe characters in the item may also be changed with the\n\\fBinsert\\fR and \\fBdelete\\fR widget commands.\nThis option defaults to an empty string.\n.\\\" OPTION: -underline\n.TP\n\\fB\\-underline \\fInumber\\fR\n.\nSpecifies the integer index of a character within the text to be\nunderlined. 0 corresponds to the first character of the text\ndisplayed, 1 to the next character, and so on. \\-1 means that no\nunderline should be drawn (if the whole text item is to be underlined,\nthe appropriate font should be used instead).\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIlineLength\\fR\n.\nSpecifies a maximum line length for the text, in any of the forms\ndescribed in the \\fBCOORDINATES\\fR section above.\nIf this option is zero (the default) the text is broken into\nlines only at newline characters.\nHowever, if this option is non-zero then any line that would\nbe longer than \\fIlineLength\\fR is broken just before a space\ncharacter to make the line shorter than \\fIlineLength\\fR; the\nspace character is treated as if it were a newline\ncharacter.\n.SS \"WINDOW ITEMS\"\n.PP\nItems of type \\fBwindow\\fR cause a particular window to be displayed\nat a given position on the canvas.\nWindow items are created with widget commands of the following form:\n.CS\n\\fIpathName \\fBcreate window \\fIx y \\fR?\\fIoption value ...\\fR?\n\\fIpathName \\fBcreate window \\fIcoordList\\fR ?\\fIoption value ...\\fR?\n.CE\nThe arguments \\fIx\\fR and \\fIy\\fR or \\fIcoordList\\fR (which must have two\nelements) specify the coordinates of a\npoint used to position the window on the display, as controlled by the\n\\fB\\-anchor\\fR option.\nAfter the coordinates there may be any number of \\fIoption\\fR\\-\\fIvalue\\fR\npairs, each of which sets one of the configuration options\nfor the item. These same \\fIoption\\fR\\-\\fIvalue\\fR pairs may be\nused in \\fBitemconfigure\\fR widget commands to change the item's\nconfiguration. Theoretically, a window item becomes the current item when the\nmouse pointer is over any part of its bounding box, but in practice this\ntypically does not happen because the mouse pointer ceases to be over the\ncanvas at that point.\n.PP\nThe following standard options are supported by window items:\n.DS\n.ta 3i\n\\fB\\-anchor\\fR\t\\fB\\-state\\fR\n\\fB\\-tags\\fR\n.DE\nThe following extra options are supported for window items:\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIpixels\\fR\n.\nSpecifies the height to assign to the item's window.\n\\fIPixels\\fR may have any of the\nforms described in the \\fBCOORDINATES\\fR section above.\nIf this option is not specified, or if it is specified as zero,\nthen the window is given whatever height it requests internally.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIpixels\\fR\n.\nSpecifies the width to assign to the item's window.\n\\fIPixels\\fR may have any of the\nforms described in the \\fBCOORDINATES\\fR section above.\nIf this option is not specified, or if it is specified as zero,\nthen the window is given whatever width it requests internally.\n.\\\" OPTION: -window\n.TP\n\\fB\\-window \\fIpathName\\fR\n.\nSpecifies the window to associate with this item.\nThe window specified by \\fIpathName\\fR must either be a child of\nthe canvas widget or a child of some ancestor of the canvas widget.\n\\fIPathName\\fR may not refer to a top-level window.\n.PP\nNote that, due to restrictions in the ways that windows are managed, it is not\npossible to draw other graphical items (such as lines and images) on top\nof window items. A window item always obscures any graphics that\noverlap it, regardless of their order in the display list. Also note that\nwindow items, unlike other canvas items, are not clipped for display by their\ncontaining canvas's border, and are instead clipped by the parent widget of\nthe window specified by the \\fB\\-window\\fR option; when the parent widget is\nthe canvas, this means that the window item can overlap the canvas's border.\n.SH \"APPLICATION-DEFINED ITEM TYPES\"\n.PP\nIt is possible for individual applications to define new item\ntypes for canvas widgets using C code.\nSee the documentation for \\fBTk_CreateItemType\\fR.\n.SH BINDINGS\n.PP\nIn the current implementation, new canvases are not given any\ndefault behavior: you will have to execute explicit Tcl commands\nto give the canvas its behavior.\n.SH CREDITS\n.PP\nTk's canvas widget is a blatant ripoff of ideas from Joel Bartlett's\n\\fIezd\\fR program. \\fIEzd\\fR provides structured graphics in a Scheme\nenvironment and preceded canvases by a year or two. Its simple\nmechanisms for placing and animating graphical objects inspired the\nfunctions of canvases.\n.SH \"SEE ALSO\"\nbind(n), font(n), image(n), scrollbar(n)\n.SH KEYWORDS\ncanvas, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" fill-column: 78\n'\\\" End:\n"
  },
  {
    "path": "doc/checkbutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH checkbutton n 4.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ncheckbutton \\- Create and manipulate 'checkbutton' boolean selection widgets\n.SH SYNOPSIS\n\\fBcheckbutton\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-disabledforeground\t\\-padx\n\\-activeforeground\t\\-font\t\\-pady\n\\-anchor\t\\-foreground\t\\-relief\n\\-background\t\\-highlightbackground\t\\-takefocus\n\\-bitmap\t\\-highlightcolor\t\\-text\n\\-borderwidth\t\\-highlightthickness\t\\-textvariable\n\\-compound\t\\-image\t\\-underline\n\\-cursor\t\\-justify\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies a Tcl command to associate with the button.  This command\nis typically invoked when mouse button 1 is released over the button\nwindow.  The button's global variable (\\fB\\-variable\\fR option) will\nbe updated before the command is invoked.\n.OP \\-height height Height\nSpecifies a desired height for the button.\nIf an image or bitmap is being displayed in the button then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in lines of text.\nIf this option is not specified, the button's desired height is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.OP \\-indicatoron indicatorOn IndicatorOn\nSpecifies whether or not the indicator should be drawn.  Must be a\nproper boolean value.  If false, the \\fB\\-relief\\fR option is\nignored and the widget's relief is always sunken if the widget is\nselected and raised otherwise.\n.OP \\-offrelief offRelief OffRelief\nSpecifies the relief for the checkbutton when the indicator is not drawn and\nthe checkbutton is off.  The default value is\n.QW raised .\nBy setting this option to\n.QW flat\nand setting \\fB\\-indicatoron\\fR to false and \\fB\\-overrelief\\fR to\n.QW raised ,\nthe effect is achieved\nof having a flat button that raises on mouse-over and which is\ndepressed when activated.  This is the behavior typically exhibited by\nthe Bold, Italic, and Underline checkbuttons on the toolbar of a\nword-processor, for example.\n.OP \\-offvalue offValue Value\nSpecifies value to store in the button's associated variable whenever\nthis button is deselected.  Defaults to\n.QW 0 .\n.OP \\-onvalue onValue Value\nSpecifies value to store in the button's associated variable whenever\nthis button is selected.  Defaults to\n.QW 1 .\n.OP \\-overrelief overRelief OverRelief\nSpecifies an alternative relief for the checkbutton, to be used when the\nmouse cursor is over the widget.  This option can be used to make\ntoolbar buttons, by configuring \\fB\\-relief flat \\-overrelief\nraised\\fR.  If the value of this option is the empty string, then no\nalternative relief is used when the mouse cursor is over the checkbutton.\nThe empty string is the default value.\n.OP \\-selectcolor selectColor Background\nSpecifies a background color to use when the button is selected.\nIf \\fBindicatorOn\\fR is true then the color is used as the background for\nthe indicator regardless of the select state.\nIf \\fBindicatorOn\\fR is false, this color is used as the background\nfor the entire widget, in place of \\fBbackground\\fR or \\fBactiveBackground\\fR,\nwhenever the widget is selected.\nIf specified as an empty string then no special color is used for\ndisplaying when the widget is selected.\n.OP \\-selectimage selectImage SelectImage\nSpecifies an image to display (in place of the \\fB\\-image\\fR option)\nwhen the checkbutton is selected.\nThis option is ignored unless the \\fB\\-image\\fR option has been\nspecified.\n.OP \\-state state State\nSpecifies one of three states for the checkbutton:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the checkbutton is displayed using the\n\\fB\\-foreground\\fR and \\fB\\-background\\fR options.  The active state is\ntypically used when the pointer is over the checkbutton.  In active state\nthe checkbutton is displayed using the \\fB\\-activeforeground\\fR and\n\\fB\\-activebackground\\fR options.  Disabled state means that the checkbutton\nshould be insensitive:  the default bindings will refuse to activate\nthe widget and will ignore mouse button presses.\nIn this state the \\fB\\-disabledforeground\\fR and\n\\fB\\-background\\fR options determine how the checkbutton is displayed.\n.OP \\-tristateimage tristateImage TristateImage\nSpecifies an image to display (in place of the \\fB\\-image\\fR option)\nwhen the checkbutton is in tri-state mode.\nThis option is ignored unless the \\fB\\-image\\fR option has been\nspecified.\n.OP \\-tristatevalue tristateValue Value\nSpecifies the value that causes the checkbutton to display the multi-value\nselection, also known as the tri-state mode.  Defaults to\n.QW \"\" .\n.OP \\-variable variable Variable\nSpecifies the name of a global variable to set to indicate whether\nor not this button is selected.  Defaults to the name of the\nbutton within its parent (i.e. the last element of the button\nwindow's path name).\n.OP \\-width width Width\nSpecifies a desired width for the button.\nIf an image or bitmap is being displayed in the button then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in characters.\nIf this option is not specified, the button's desired width is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBcheckbutton\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a checkbutton widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the checkbutton such as its colors, font,\ntext, and initial relief.  The \\fBcheckbutton\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA checkbutton is a widget\nthat displays a textual string, bitmap or image\nand a square called an \\fIindicator\\fR.\nIf text is displayed, it must all be in a single font, but it\ncan occupy multiple lines on the screen (if it contains newlines\nor if wrapping occurs because of the \\fB\\-wraplength\\fR option) and\none of the characters may optionally be underlined using the\n\\fB\\-underline\\fR option.\nA checkbutton has\nall of the behavior of a simple button, including the\nfollowing: it can display itself in either of three different\nways, according to the \\fB\\-state\\fR option;\nit can be made to appear\nraised, sunken, or flat; it can be made to flash; and it invokes\na Tcl command whenever mouse button 1 is clicked over the\ncheckbutton.\n.PP\nIn addition, checkbuttons can be \\fIselected\\fR.\nIf a checkbutton is selected then the indicator is normally\ndrawn with a selected appearance, and\na Tcl variable associated with the checkbutton is set to a particular\nvalue (normally 1).\nThe indicator is drawn with a check mark inside.\nIf the checkbutton is not selected, then the indicator is drawn with a\ndeselected appearance, and the associated variable is\nset to a different value (typically 0).\nThe indicator is drawn without a check mark inside.  In the special case\nwhere the variable (if specified) has a value that matches the tristatevalue,\nthe indicator is drawn with a tri-state appearance and is in the tri-state\nmode indicating mixed or multiple values.  (This is used when the check\nbox represents the state of multiple items.)\nThe indicator is drawn in a platform dependent manner.  Under Unix and\nWindows, the background interior of the box is\n.QW grayed .\nUnder Mac, the indicator is drawn with a dash mark inside.\nBy default, the name of the variable associated with a checkbutton is the\nsame as the \\fIname\\fR used to create the checkbutton.\nThe variable name, and the\n.QW on ,\n.QW off\nand\n.QW tristate\nvalues stored in it, may be modified with options on the command line\nor in the option database.\nConfiguration options may also be used to modify the way the\nindicator is displayed (or whether it is displayed at all).\nBy default a checkbutton is configured to select and deselect\nitself on alternate button clicks.\nIn addition, each checkbutton monitors its associated variable and\nautomatically selects and deselects itself when the variables value\nchanges to and from the button's\n.QW on ,\n.QW off\nand\n.QW tristate\nvalues.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBcheckbutton\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for checkbutton widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBcheckbutton\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBcheckbutton\\fR\ncommand.\n.\\\" METHOD: deselect\n.TP\n\\fIpathName \\fBdeselect\\fR\n.\nDeselects the checkbutton and sets the associated variable to its\n.QW off\nvalue.\n.\\\" METHOD: flash\n.TP\n\\fIpathName \\fBflash\\fR\n.\nFlashes the checkbutton.  This is accomplished by redisplaying the checkbutton\nseveral times, alternating between active and normal colors.  At\nthe end of the flash the checkbutton is left in the same normal/active\nstate as when the command was invoked.\nThis command is ignored if the checkbutton's state is \\fBdisabled\\fR.\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke\\fR\n.\nDoes just what would have happened if the user invoked the checkbutton\nwith the mouse: toggle the selection state of the button and invoke\nthe Tcl command associated with the checkbutton, if there is one.\nThe return value is the return value from the Tcl command, or an\nempty string if there is no command associated with the checkbutton.\nThis command is ignored if the checkbutton's state is \\fBdisabled\\fR.\n.\\\" METHOD: select\n.TP\n\\fIpathName \\fBselect\\fR\n.\nSelects the checkbutton and sets the associated variable to its\n.QW on\nvalue.\n.\\\" METHOD: toggle\n.TP\n\\fIpathName \\fBtoggle\\fR\n.\nToggles the selection state of the button, redisplaying it and\nmodifying its associated variable to reflect the new state.\n.SH BINDINGS\n.PP\nTk automatically creates class bindings for checkbuttons that give them\nthe following default behavior:\n.IP [1]\nOn Unix systems, a checkbutton activates whenever the mouse passes\nover it and deactivates whenever the mouse leaves the checkbutton.  On\nMac and Windows systems, when mouse button 1 is pressed over a\ncheckbutton, the button activates whenever the mouse pointer is inside\nthe button, and deactivates whenever the mouse pointer leaves the\nbutton.\n.IP [2]\nWhen mouse button 1 is pressed over a checkbutton, it is invoked (its\nselection state toggles and the command associated with the button is\ninvoked, if there is one).\n.IP [3]\nWhen a checkbutton has the input focus, the space key causes the checkbutton\nto be invoked.  Under Windows, there are additional key bindings; plus\n(\\fB+\\fR) and equal (\\fB=\\fR) select the button, and minus (\\fB\\-\\fR)\ndeselects the button.\n.PP\nIf the checkbutton's state is \\fBdisabled\\fR then none of the above\nactions occur:  the checkbutton is completely non-responsive.\n.PP\nThe behavior of checkbuttons can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH EXAMPLE\n.PP\nThis example shows a group of uncoupled checkbuttons.\n.PP\n.CS\nlabelframe .lbl -text \"Steps:\"\n\\fBcheckbutton\\fR .c1 -text Lights  -variable lights\n\\fBcheckbutton\\fR .c2 -text Cameras -variable cameras\n\\fBcheckbutton\\fR .c3 -text Action! -variable action\npack .c1 .c2 .c3 -in .lbl\npack .lbl\n.CE\n.SH \"SEE ALSO\"\nbutton(n), options(n), radiobutton(n), ttk::checkbutton(n)\n.SH KEYWORDS\ncheckbutton, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/chooseColor.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_chooseColor n 4.2 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_chooseColor \\- pops up a dialog box for the user to select a color.\n.SH SYNOPSIS\n\\fBtk_chooseColor \\fR?\\fIoption value ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe procedure \\fBtk_chooseColor\\fR pops up a dialog box for the\nuser to select a color. The following \\fIoption\\-value\\fR pairs are\npossible as command line arguments:\n.\\\" OPTION: -initialcolor\n.TP\n\\fB\\-initialcolor\\fI color\\fR\n.\nSpecifies the color to display in the color dialog when it pops\nup. \\fIcolor\\fR must be in a form acceptable to the \\fBTk_GetColor\\fR\nfunction.\n.\\\" OPTION: -parent\n.TP\n\\fB\\-parent\\fI window\\fR\n.\nMakes \\fIwindow\\fR the logical parent of the color dialog. The color\ndialog is displayed on top of its parent window.\n.\\\" OPTION: -title\n.TP\n\\fB\\-title\\fI titleString\\fR\n.\nSpecifies a string to display as the title of the dialog box. If this\noption is not specified, then a default title will be displayed.\n.LP\nIf the user selects a color, \\fBtk_chooseColor\\fR will return the\nname of the color in a form acceptable to \\fBTk_GetColor\\fR.  If the\nuser cancels the operation, both commands will return the empty\nstring.\n.SH EXAMPLE\n.PP\n.CS\nbutton .b -bg [tk_chooseColor -initialcolor gray -title \"Choose color\"]\n.CE\n.SH KEYWORDS\ncolor, color selection, dialog\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/chooseDirectory.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH tk_chooseDirectory n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_chooseDirectory \\- pops up a dialog box for the user to select a directory.\n.SH SYNOPSIS\n\\fBtk_chooseDirectory \\fR?\\fIoption value ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe procedure \\fBtk_chooseDirectory\\fR pops up a dialog box for the\nuser to select a directory. The following \\fIoption\\-value\\fR pairs are\npossible as command line arguments:\n.\\\" OPTION: -command\n.TP\n\\fB\\-command\\fI string\\fR\n.\nSpecifies the prefix of a Tcl command to invoke when the user closes the\ndialog after having selected an item. This callback is not called if the\nuser cancelled the dialog. The actual command consists of \\fIstring\\fR\nfollowed by a space and the value selected by the user in the dialog. This\nis only available on macOS.\n.\\\" OPTION: -initialdir\n.TP\n\\fB\\-initialdir\\fI dirname\\fR\n.\nSpecifies that the directories in \\fIdirectory\\fR should be displayed\nwhen the dialog pops up. If this parameter is not specified,\nthe initial directory defaults to the current working directory\non non-Windows systems and on Windows systems prior to Vista.\nOn Vista and later systems, the initial directory defaults to the last\nuser-selected directory for the application. If the\nparameter specifies a relative path, the return value will convert the\nrelative path to an absolute path.\n.\\\" OPTION: -message\n.TP\n\\fB\\-message\\fI string\\fR\n.\nSpecifies a message to include in the client area of the dialog.\nThis is only available on macOS.\n.\\\" OPTION: -mustexist\n.TP\n\\fB\\-mustexist\\fI boolean\\fR\n.\nSpecifies whether the user may specify non-existent directories.  If\nthis parameter is true, then the user may only select directories that\nalready exist.  The default value is \\fIfalse\\fR.\n.\\\" OPTION: -parent\n.TP\n\\fB\\-parent\\fI window\\fR\n.\nMakes \\fIwindow\\fR the logical parent of the dialog. The dialog\nis displayed on top of its parent window. On macOS, this\nturns the file dialog into a sheet attached to the parent window.\n.\\\" OPTION: -title\n.TP\n\\fB\\-title\\fI titleString\\fR\n.\nSpecifies a string to display as the title of the dialog box. If this\noption is not specified, then a default title will be displayed.\n.SH EXAMPLE\n.PP\n.CS\nset dir [\\fBtk_chooseDirectory\\fR \\e\n        -initialdir ~ -title \"Choose a directory\"]\nif {$dir eq \"\"} {\n   label .l -text \"No directory selected\"\n} else {\n   label .l -text \"Selected $dir\"\n}\n.CE\n.SH \"SEE ALSO\"\ntk_getOpenFile(n), tk_getSaveFile(n)\n.SH KEYWORDS\ndirectory, selection, dialog, platform-specific\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/clipboard.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH clipboard n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nclipboard \\- Manipulate Tk clipboard\n.SH SYNOPSIS\n\\fBclipboard \\fIoption\\fR ?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis command provides a Tcl interface to the Tk clipboard,\nwhich stores data for later retrieval using the selection mechanism\n(via the \\fB\\-selection CLIPBOARD\\fR option).\nIn order to copy data into the clipboard, \\fBclipboard clear\\fR must\nbe called, followed by a sequence of one or more calls to \\fBclipboard\nappend\\fR.  To ensure that the clipboard is updated atomically, all\nappends should be completed before returning to the event loop.\n.PP\nThe first argument to \\fBclipboard\\fR determines the format of the\nrest of the arguments and the behavior of the command.  The following\nforms are currently supported:\n.\\\" METHOD: append\n.TP\n\\fBclipboard append\\fR ?\\fB\\-displayof\\fI window\\fR? ?\\fB\\-format\\fI format\\fR? ?\\fB\\-type\\fI type\\fR? ?\\fB\\-\\|\\-\\fR? \\fIdata\\fR\n.\nAppends \\fIdata\\fR to the clipboard on \\fIwindow\\fR's\ndisplay in the form given by \\fItype\\fR with the representation given\nby \\fIformat\\fR and claims ownership of the clipboard on \\fIwindow\\fR's\ndisplay.\n.RS\n.PP\n\\fIType\\fR specifies the form in which the selection is to be returned\n(the desired\n.QW target\nfor conversion, in ICCCM terminology), and\nshould be an atom name such as \\fBSTRING\\fR or \\fBFILE_NAME\\fR; see the\nInter-Client Communication Conventions Manual for complete details.\n\\fIType\\fR defaults to \\fBSTRING\\fR.\n.PP\nThe \\fIformat\\fR argument specifies the representation that should be\nused to transmit the selection to the requester (the second column of\nTable 2 of the ICCCM), and defaults to \\fBSTRING\\fR.  If \\fIformat\\fR is\n\\fBSTRING\\fR, the selection is transmitted as 8-bit ASCII characters.  If\n\\fIformat\\fR is \\fBATOM\\fR, then the \\fIdata\\fR is\ndivided into fields separated by white space; each field is converted\nto its atom value, and the 32-bit atom value is transmitted instead of\nthe atom name.  For any other \\fIformat\\fR,  \\fIdata\\fR is divided\ninto fields separated by white space and each\nfield is converted to a 32-bit integer; an array of integers is\ntransmitted to the selection requester.  Note that strings passed to\n\\fBclipboard append\\fR are concatenated before conversion, so the\ncaller must take care to ensure appropriate spacing across string\nboundaries.  All items appended to the clipboard with the same\n\\fItype\\fR must have the same \\fIformat\\fR.\n.PP\nThe \\fIformat\\fR argument is needed only for compatibility with\nclipboard requesters that do not use Tk.  If the Tk toolkit is being\nused to retrieve the \\fBCLIPBOARD\\fR selection then the value is\nconverted back to a string at the requesting end, so \\fIformat\\fR is\nirrelevant.\n.PP\nA \\fB\\-\\|\\-\\fR argument may be specified to mark the end of options:  the\nnext argument will always be used as \\fIdata\\fR.\nThis feature may be convenient if, for example, \\fIdata\\fR starts\nwith a \\fB\\-\\fR.\n.RE\n.\\\" METHOD: clear\n.TP\n\\fBclipboard clear\\fR ?\\fB\\-displayof\\fI window\\fR?\n.\nClaims ownership of the clipboard on \\fIwindow\\fR's display and removes\nany previous contents.  \\fIWindow\\fR defaults to\n.QW . .\nReturns an empty string.\n.\\\" METHOD: get\n.TP\n\\fBclipboard get\\fR ?\\fB\\-displayof\\fI window\\fR? ?\\fB\\-type\\fI type\\fR?\n.\nRetrieve data from the clipboard on \\fIwindow\\fR's display.\n\\fIWindow\\fR defaults to\n.QW . .\n\\fIType\\fR specifies the form in which\nthe data is to be returned and should be an atom name such as \\fBSTRING\\fR\nor \\fBFILE_NAME\\fR.  \\fIType\\fR defaults to \\fBSTRING\\fR.  This command is\nequivalent to\n.QW \"\\fBselection get\\fR \\fB\\-selection CLIPBOARD\\fR\" .\n.RS\n.PP\nNote that on modern X11 systems, the most useful type to retrieve for\ntransferred strings is not \\fBSTRING\\fR, but rather \\fBUTF8_STRING\\fR.\n.RE\n.SH EXAMPLES\n.PP\nGet the current contents of the clipboard.\n.CS\nif {[catch {\\fBclipboard get\\fR} contents]} {\n    # There were no clipboard contents at all\n}\n.CE\n.PP\nSet the clipboard to contain a fixed string.\n.CS\n\\fBclipboard clear\\fR\n\\fBclipboard append\\fR \"some fixed string\"\n.CE\n.PP\nYou can put custom data into the clipboard by using a custom \\fB\\-type\\fR\noption. This is not necessarily portable, but can be very useful. The\nmethod of passing Tcl scripts this way is effective, but should be mixed\nwith safe interpreters in production code.\n.CS\n# This is a very simple canvas serializer;\n# it produces a script that recreates the item(s) when executed\nproc getItemConfig {canvas tag} {\n   set script {}\n   foreach item [$canvas find withtag $tag] {\n      append script {$canvas create } [$canvas type $item]\n      append script { } [$canvas coords $item] { }\n      foreach config [$canvas itemconf $item] {\n         lassign $config name - - - value\n         append script [list $name $value] { }\n      }\n      append script \\en\n   }\n   return [string trim $script]\n}\n\n# Set up a binding on a canvas to cut and paste an item\nset c [canvas .c]\npack $c\n$c create text 150 30 -text \"cut and paste me\"\nbind $c <<Cut>> {\n   \\fBclipboard clear\\fR\n   \\fBclipboard append -type\\fR TkCanvasItem \\e\n         [getItemConfig %W current]\n   # Delete because this is cut, not copy.\n   %W delete current\n}\nbind $c <<Paste>> {\n   catch {\n      set canvas %W\n      eval [\\fBclipboard get -type\\fR TkCanvasItem]\n   }\n}\n.CE\n.SH \"SEE ALSO\"\ninterp(n), selection(n)\n.SH KEYWORDS\nclear, format, clipboard, append, selection, type\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/colors.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" Copyright (c) 2003 ActiveState Corporation.\n'\\\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>\n'\\\" Copyright (c) 2008 Donal K. Fellows\n'\\\"\n.TH colors n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n.\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ncolors \\- symbolic color names recognized by Tk\n.BE\n.SH DESCRIPTION\n.PP\nTk recognizes many symbolic color names (e.g., \\fBred\\fR) when\nspecifying colors.  The symbolic names recognized by Tk and their\n8-bit-per-channel RGB values are:\n.DS\n.ta 7.2cR 9.5cR 11cR\n\\fBName\\fR\t\\fBRed\\fR\t\\fBGreen\\fR\t\\fBBlue\\fR\nalice blue\t240\t248 \t255\nAliceBlue\t240\t248 \t255\nantique white\t250\t235 \t215\nAntiqueWhite\t250\t235 \t215\nAntiqueWhite1\t255\t239 \t219\nAntiqueWhite2\t238\t223 \t204\nAntiqueWhite3\t205\t192 \t176\nAntiqueWhite4\t139\t131 \t120\naqua\t0\t255\t255\naquamarine\t127\t255 \t212\naquamarine1\t127\t255 \t212\naquamarine2\t118\t238 \t198\naquamarine3\t102\t205 \t170\naquamarine4\t69\t139 \t116\nazure\t240\t255 \t255\nazure1\t240\t255 \t255\nazure2\t224\t238 \t238\nazure3\t193\t205 \t205\nazure4\t131\t139 \t139\nbeige\t245\t245 \t220\nbisque\t255\t228 \t196\nbisque1\t255\t228 \t196\nbisque2\t238\t213 \t183\nbisque3\t205\t183 \t158\nbisque4\t139\t125 \t107\nblack\t0\t0 \t0\nblanched almond\t255\t235 \t205\nBlanchedAlmond\t255\t235 \t205\nblue\t0\t0 \t255\nblue violet\t138\t43 \t226\nblue1\t0\t0 \t255\nblue2\t0\t0 \t238\nblue3\t0\t0 \t205\nblue4\t0\t0 \t139\nBlueViolet\t138\t43 \t226\nbrown\t165\t42 \t42\nbrown1\t255\t64 \t64\nbrown2\t238\t59 \t59\nbrown3\t205\t51 \t51\nbrown4\t139\t35 \t35\nburlywood\t222\t184 \t135\nburlywood1\t255\t211 \t155\nburlywood2\t238\t197 \t145\nburlywood3\t205\t170 \t125\nburlywood4\t139\t115 \t85\ncadet blue\t95\t158 \t160\nCadetBlue\t95\t158 \t160\nCadetBlue1\t152\t245 \t255\nCadetBlue2\t142\t229 \t238\nCadetBlue3\t122\t197 \t205\nCadetBlue4\t83\t134 \t139\nchartreuse\t127\t255 \t0\nchartreuse1\t127\t255 \t0\nchartreuse2\t118\t238 \t0\nchartreuse3\t102\t205 \t0\nchartreuse4\t69\t139 \t0\nchocolate\t210\t105 \t30\nchocolate1\t255\t127 \t36\nchocolate2\t238\t118 \t33\nchocolate3\t205\t102 \t29\nchocolate4\t139\t69 \t19\ncoral\t255\t127 \t80\ncoral1\t255\t114 \t86\ncoral2\t238\t106 \t80\ncoral3\t205\t91 \t69\ncoral4\t139\t62 \t47\ncornflower blue\t100\t149 \t237\nCornflowerBlue\t100\t149 \t237\ncornsilk\t255\t248 \t220\ncornsilk1\t255\t248 \t220\ncornsilk2\t238\t232 \t205\ncornsilk3\t205\t200 \t177\ncornsilk4\t139\t136 \t120\ncrimson\t220\t20\t60\ncyan\t0\t255 \t255\ncyan1\t0\t255 \t255\ncyan2\t0\t238 \t238\ncyan3\t0\t205 \t205\ncyan4\t0\t139 \t139\ndark blue\t0\t0 \t139\ndark cyan\t0\t139 \t139\ndark goldenrod\t184\t134 \t11\ndark gray\t169\t169 \t169\ndark green\t0\t100 \t0\ndark grey\t169\t169 \t169\ndark khaki\t189\t183 \t107\ndark magenta\t139\t0 \t139\ndark olive green\t85\t107 \t47\ndark orange\t255\t140 \t0\ndark orchid\t153\t50 \t204\ndark red\t139\t0 \t0\ndark salmon\t233\t150 \t122\ndark sea green\t143\t188 \t143\ndark slate blue\t72\t61 \t139\ndark slate gray\t47\t79 \t79\ndark slate grey\t47\t79 \t79\ndark turquoise\t0\t206 \t209\ndark violet\t148\t0 \t211\nDarkBlue\t0\t0 \t139\nDarkCyan\t0\t139 \t139\nDarkGoldenrod\t184\t134 \t11\nDarkGoldenrod1\t255\t185 \t15\nDarkGoldenrod2\t238\t173 \t14\nDarkGoldenrod3\t205\t149 \t12\nDarkGoldenrod4\t139\t101 \t8\nDarkGray\t169\t169 \t169\nDarkGreen\t0\t100 \t0\nDarkGrey\t169\t169 \t169\nDarkKhaki\t189\t183 \t107\nDarkMagenta\t139\t0 \t139\nDarkOliveGreen\t85\t107 \t47\nDarkOliveGreen1\t202\t255 \t112\nDarkOliveGreen2\t188\t238 \t104\nDarkOliveGreen3\t162\t205 \t90\nDarkOliveGreen4\t110\t139 \t61\nDarkOrange\t255\t140 \t0\nDarkOrange1\t255\t127 \t0\nDarkOrange2\t238\t118 \t0\nDarkOrange3\t205\t102 \t0\nDarkOrange4\t139\t69 \t0\nDarkOrchid\t153\t50 \t204\nDarkOrchid1\t191\t62 \t255\nDarkOrchid2\t178\t58 \t238\nDarkOrchid3\t154\t50 \t205\nDarkOrchid4\t104\t34 \t139\nDarkRed\t139\t0 \t0\nDarkSalmon\t233\t150 \t122\nDarkSeaGreen\t143\t188 \t143\nDarkSeaGreen1\t193\t255 \t193\nDarkSeaGreen2\t180\t238 \t180\nDarkSeaGreen3\t155\t205 \t155\nDarkSeaGreen4\t105\t139 \t105\nDarkSlateBlue\t72\t61 \t139\nDarkSlateGray\t47\t79 \t79\nDarkSlateGray1\t151\t255 \t255\nDarkSlateGray2\t141\t238 \t238\nDarkSlateGray3\t121\t205 \t205\nDarkSlateGray4\t82\t139 \t139\nDarkSlateGrey\t47\t79 \t79\nDarkTurquoise\t0\t206 \t209\nDarkViolet\t148\t0 \t211\ndeep pink\t255\t20 \t147\ndeep sky blue\t0\t191 \t255\nDeepPink\t255\t20 \t147\nDeepPink1\t255\t20 \t147\nDeepPink2\t238\t18 \t137\nDeepPink3\t205\t16 \t118\nDeepPink4\t139\t10 \t80\nDeepSkyBlue\t0\t191 \t255\nDeepSkyBlue1\t0\t191 \t255\nDeepSkyBlue2\t0\t178 \t238\nDeepSkyBlue3\t0\t154 \t205\nDeepSkyBlue4\t0\t104 \t139\ndim gray\t105\t105 \t105\ndim grey\t105\t105 \t105\nDimGray\t105\t105 \t105\nDimGrey\t105\t105 \t105\ndodger blue\t30\t144 \t255\nDodgerBlue\t30\t144 \t255\nDodgerBlue1\t30\t144 \t255\nDodgerBlue2\t28\t134 \t238\nDodgerBlue3\t24\t116 \t205\nDodgerBlue4\t16\t78 \t139\nfirebrick\t178\t34 \t34\nfirebrick1\t255\t48 \t48\nfirebrick2\t238\t44 \t44\nfirebrick3\t205\t38 \t38\nfirebrick4\t139\t26 \t26\nfloral white\t255\t250 \t240\nFloralWhite\t255\t250 \t240\nforest green\t34\t139 \t34\nForestGreen\t34\t139 \t34\nfuchsia\t255\t0\t255\ngainsboro\t220\t220 \t220\nghost white\t248\t248 \t255\nGhostWhite\t248\t248 \t255\ngold\t255\t215 \t0\ngold1\t255\t215 \t0\ngold2\t238\t201 \t0\ngold3\t205\t173 \t0\ngold4\t139\t117 \t0\ngoldenrod\t218\t165 \t32\ngoldenrod1\t255\t193 \t37\ngoldenrod2\t238\t180 \t34\ngoldenrod3\t205\t155 \t29\ngoldenrod4\t139\t105 \t20\ngray\t128\t128\t128\ngray0\t0\t0 \t0\ngray1\t3\t3 \t3\ngray2\t5\t5 \t5\ngray3\t8\t8 \t8\ngray4\t10\t10 \t10\ngray5\t13\t13 \t13\ngray6\t15\t15 \t15\ngray7\t18\t18 \t18\ngray8\t20\t20 \t20\ngray9\t23\t23 \t23\ngray10\t26\t26 \t26\ngray11\t28\t28 \t28\ngray12\t31\t31 \t31\ngray13\t33\t33 \t33\ngray14\t36\t36 \t36\ngray15\t38\t38 \t38\ngray16\t41\t41 \t41\ngray17\t43\t43 \t43\ngray18\t46\t46 \t46\ngray19\t48\t48 \t48\ngray20\t51\t51 \t51\ngray21\t54\t54 \t54\ngray22\t56\t56 \t56\ngray23\t59\t59 \t59\ngray24\t61\t61 \t61\ngray25\t64\t64 \t64\ngray26\t66\t66 \t66\ngray27\t69\t69 \t69\ngray28\t71\t71 \t71\ngray29\t74\t74 \t74\ngray30\t77\t77 \t77\ngray31\t79\t79 \t79\ngray32\t82\t82 \t82\ngray33\t84\t84 \t84\ngray34\t87\t87 \t87\ngray35\t89\t89 \t89\ngray36\t92\t92 \t92\ngray37\t94\t94 \t94\ngray38\t97\t97 \t97\ngray39\t99\t99 \t99\ngray40\t102\t102 \t102\ngray41\t105\t105 \t105\ngray42\t107\t107 \t107\ngray43\t110\t110 \t110\ngray44\t112\t112 \t112\ngray45\t115\t115 \t115\ngray46\t117\t117 \t117\ngray47\t120\t120 \t120\ngray48\t122\t122 \t122\ngray49\t125\t125 \t125\ngray50\t127\t127 \t127\ngray51\t130\t130 \t130\ngray52\t133\t133 \t133\ngray53\t135\t135 \t135\ngray54\t138\t138 \t138\ngray55\t140\t140 \t140\ngray56\t143\t143 \t143\ngray57\t145\t145 \t145\ngray58\t148\t148 \t148\ngray59\t150\t150 \t150\ngray60\t153\t153 \t153\ngray61\t156\t156 \t156\ngray62\t158\t158 \t158\ngray63\t161\t161 \t161\ngray64\t163\t163 \t163\ngray65\t166\t166 \t166\ngray66\t168\t168 \t168\ngray67\t171\t171 \t171\ngray68\t173\t173 \t173\ngray69\t176\t176 \t176\ngray70\t179\t179 \t179\ngray71\t181\t181 \t181\ngray72\t184\t184 \t184\ngray73\t186\t186 \t186\ngray74\t189\t189 \t189\ngray75\t191\t191 \t191\ngray76\t194\t194 \t194\ngray77\t196\t196 \t196\ngray78\t199\t199 \t199\ngray79\t201\t201 \t201\ngray80\t204\t204 \t204\ngray81\t207\t207 \t207\ngray82\t209\t209 \t209\ngray83\t212\t212 \t212\ngray84\t214\t214 \t214\ngray85\t217\t217 \t217\ngray86\t219\t219 \t219\ngray87\t222\t222 \t222\ngray88\t224\t224 \t224\ngray89\t227\t227 \t227\ngray90\t229\t229 \t229\ngray91\t232\t232 \t232\ngray92\t235\t235 \t235\ngray93\t237\t237 \t237\ngray94\t240\t240 \t240\ngray95\t242\t242 \t242\ngray96\t245\t245 \t245\ngray97\t247\t247 \t247\ngray98\t250\t250 \t250\ngray99\t252\t252 \t252\ngray100\t255\t255 \t255\ngreen\t0\t128 \t0\ngreen yellow\t173\t255 \t47\ngreen1\t0\t255 \t0\ngreen2\t0\t238 \t0\ngreen3\t0\t205 \t0\ngreen4\t0\t139 \t0\nGreenYellow\t173\t255 \t47\ngrey\t128\t128\t128\ngrey0\t0\t0 \t0\ngrey1\t3\t3 \t3\ngrey2\t5\t5 \t5\ngrey3\t8\t8 \t8\ngrey4\t10\t10 \t10\ngrey5\t13\t13 \t13\ngrey6\t15\t15 \t15\ngrey7\t18\t18 \t18\ngrey8\t20\t20 \t20\ngrey9\t23\t23 \t23\ngrey10\t26\t26 \t26\ngrey11\t28\t28 \t28\ngrey12\t31\t31 \t31\ngrey13\t33\t33 \t33\ngrey14\t36\t36 \t36\ngrey15\t38\t38 \t38\ngrey16\t41\t41 \t41\ngrey17\t43\t43 \t43\ngrey18\t46\t46 \t46\ngrey19\t48\t48 \t48\ngrey20\t51\t51 \t51\ngrey21\t54\t54 \t54\ngrey22\t56\t56 \t56\ngrey23\t59\t59 \t59\ngrey24\t61\t61 \t61\ngrey25\t64\t64 \t64\ngrey26\t66\t66 \t66\ngrey27\t69\t69 \t69\ngrey28\t71\t71 \t71\ngrey29\t74\t74 \t74\ngrey30\t77\t77 \t77\ngrey31\t79\t79 \t79\ngrey32\t82\t82 \t82\ngrey33\t84\t84 \t84\ngrey34\t87\t87 \t87\ngrey35\t89\t89 \t89\ngrey36\t92\t92 \t92\ngrey37\t94\t94 \t94\ngrey38\t97\t97 \t97\ngrey39\t99\t99 \t99\ngrey40\t102\t102 \t102\ngrey41\t105\t105 \t105\ngrey42\t107\t107 \t107\ngrey43\t110\t110 \t110\ngrey44\t112\t112 \t112\ngrey45\t115\t115 \t115\ngrey46\t117\t117 \t117\ngrey47\t120\t120 \t120\ngrey48\t122\t122 \t122\ngrey49\t125\t125 \t125\ngrey50\t127\t127 \t127\ngrey51\t130\t130 \t130\ngrey52\t133\t133 \t133\ngrey53\t135\t135 \t135\ngrey54\t138\t138 \t138\ngrey55\t140\t140 \t140\ngrey56\t143\t143 \t143\ngrey57\t145\t145 \t145\ngrey58\t148\t148 \t148\ngrey59\t150\t150 \t150\ngrey60\t153\t153 \t153\ngrey61\t156\t156 \t156\ngrey62\t158\t158 \t158\ngrey63\t161\t161 \t161\ngrey64\t163\t163 \t163\ngrey65\t166\t166 \t166\ngrey66\t168\t168 \t168\ngrey67\t171\t171 \t171\ngrey68\t173\t173 \t173\ngrey69\t176\t176 \t176\ngrey70\t179\t179 \t179\ngrey71\t181\t181 \t181\ngrey72\t184\t184 \t184\ngrey73\t186\t186 \t186\ngrey74\t189\t189 \t189\ngrey75\t191\t191 \t191\ngrey76\t194\t194 \t194\ngrey77\t196\t196 \t196\ngrey78\t199\t199 \t199\ngrey79\t201\t201 \t201\ngrey80\t204\t204 \t204\ngrey81\t207\t207 \t207\ngrey82\t209\t209 \t209\ngrey83\t212\t212 \t212\ngrey84\t214\t214 \t214\ngrey85\t217\t217 \t217\ngrey86\t219\t219 \t219\ngrey87\t222\t222 \t222\ngrey88\t224\t224 \t224\ngrey89\t227\t227 \t227\ngrey90\t229\t229 \t229\ngrey91\t232\t232 \t232\ngrey92\t235\t235 \t235\ngrey93\t237\t237 \t237\ngrey94\t240\t240 \t240\ngrey95\t242\t242 \t242\ngrey96\t245\t245 \t245\ngrey97\t247\t247 \t247\ngrey98\t250\t250 \t250\ngrey99\t252\t252 \t252\ngrey100\t255\t255 \t255\nhoneydew\t240\t255 \t240\nhoneydew1\t240\t255 \t240\nhoneydew2\t224\t238 \t224\nhoneydew3\t193\t205 \t193\nhoneydew4\t131\t139 \t131\nhot pink\t255\t105 \t180\nHotPink\t255\t105 \t180\nHotPink1\t255\t110 \t180\nHotPink2\t238\t106 \t167\nHotPink3\t205\t96 \t144\nHotPink4\t139\t58 \t98\nindian red\t205\t92 \t92\nIndianRed\t205\t92 \t92\nIndianRed1\t255\t106 \t106\nIndianRed2\t238\t99 \t99\nIndianRed3\t205\t85 \t85\nIndianRed4\t139\t58 \t58\nindigo\t75\t0\t130\nivory\t255\t255 \t240\nivory1\t255\t255 \t240\nivory2\t238\t238 \t224\nivory3\t205\t205 \t193\nivory4\t139\t139 \t131\nkhaki\t240\t230 \t140\nkhaki1\t255\t246 \t143\nkhaki2\t238\t230 \t133\nkhaki3\t205\t198 \t115\nkhaki4\t139\t134 \t78\nlavender\t230\t230 \t250\nlavender blush\t255\t240 \t245\nLavenderBlush\t255\t240 \t245\nLavenderBlush1\t255\t240 \t245\nLavenderBlush2\t238\t224 \t229\nLavenderBlush3\t205\t193 \t197\nLavenderBlush4\t139\t131 \t134\nlawn green\t124\t252 \t0\nLawnGreen\t124\t252 \t0\nlemon chiffon\t255\t250 \t205\nLemonChiffon\t255\t250 \t205\nLemonChiffon1\t255\t250 \t205\nLemonChiffon2\t238\t233 \t191\nLemonChiffon3\t205\t201 \t165\nLemonChiffon4\t139\t137 \t112\nlight blue\t173\t216 \t230\nlight coral\t240\t128 \t128\nlight cyan\t224\t255 \t255\nlight goldenrod\t238\t221 \t130\nlight goldenrod yellow\t250\t250 \t210\nlight gray\t211\t211 \t211\nlight green\t144\t238 \t144\nlight grey\t211\t211 \t211\nlight pink\t255\t182 \t193\nlight salmon\t255\t160 \t122\nlight sea green\t32\t178 \t170\nlight sky blue\t135\t206 \t250\nlight slate blue\t132\t112 \t255\nlight slate gray\t119\t136 \t153\nlight slate grey\t119\t136 \t153\nlight steel blue\t176\t196 \t222\nlight yellow\t255\t255 \t224\nLightBlue\t173\t216 \t230\nLightBlue1\t191\t239 \t255\nLightBlue2\t178\t223 \t238\nLightBlue3\t154\t192 \t205\nLightBlue4\t104\t131 \t139\nLightCoral\t240\t128 \t128\nLightCyan\t224\t255 \t255\nLightCyan1\t224\t255 \t255\nLightCyan2\t209\t238 \t238\nLightCyan3\t180\t205 \t205\nLightCyan4\t122\t139 \t139\nLightGoldenrod\t238\t221 \t130\nLightGoldenrod1\t255\t236 \t139\nLightGoldenrod2\t238\t220 \t130\nLightGoldenrod3\t205\t190 \t112\nLightGoldenrod4\t139\t129 \t76\nLightGoldenrodYellow\t250\t250 \t210\nLightGray\t211\t211 \t211\nLightGreen\t144\t238 \t144\nLightGrey\t211\t211 \t211\nLightPink\t255\t182 \t193\nLightPink1\t255\t174 \t185\nLightPink2\t238\t162 \t173\nLightPink3\t205\t140 \t149\nLightPink4\t139\t95 \t101\nLightSalmon\t255\t160 \t122\nLightSalmon1\t255\t160 \t122\nLightSalmon2\t238\t149 \t114\nLightSalmon3\t205\t129 \t98\nLightSalmon4\t139\t87 \t66\nLightSeaGreen\t32\t178 \t170\nLightSkyBlue\t135\t206 \t250\nLightSkyBlue1\t176\t226 \t255\nLightSkyBlue2\t164\t211 \t238\nLightSkyBlue3\t141\t182 \t205\nLightSkyBlue4\t96\t123 \t139\nLightSlateBlue\t132\t112 \t255\nLightSlateGray\t119\t136 \t153\nLightSlateGrey\t119\t136 \t153\nLightSteelBlue\t176\t196 \t222\nLightSteelBlue1\t202\t225 \t255\nLightSteelBlue2\t188\t210 \t238\nLightSteelBlue3\t162\t181 \t205\nLightSteelBlue4\t110\t123 \t139\nLightYellow\t255\t255 \t224\nLightYellow1\t255\t255 \t224\nLightYellow2\t238\t238 \t209\nLightYellow3\t205\t205 \t180\nLightYellow4\t139\t139 \t122\nlime\t0\t255\t0\nlime green\t50\t205 \t50\nLimeGreen\t50\t205 \t50\nlinen\t250\t240 \t230\nmagenta\t255\t0 \t255\nmagenta1\t255\t0 \t255\nmagenta2\t238\t0 \t238\nmagenta3\t205\t0 \t205\nmagenta4\t139\t0 \t139\nmaroon\t128\t0 \t0\nmaroon1\t255\t52 \t179\nmaroon2\t238\t48 \t167\nmaroon3\t205\t41 \t144\nmaroon4\t139\t28 \t98\nmedium aquamarine\t102\t205 \t170\nmedium blue\t0\t0 \t205\nmedium orchid\t186\t85 \t211\nmedium purple\t147\t112 \t219\nmedium sea green\t60\t179 \t113\nmedium slate blue\t123\t104 \t238\nmedium spring green\t0\t250 \t154\nmedium turquoise\t72\t209 \t204\nmedium violet red\t199\t21 \t133\nMediumAquamarine\t102\t205 \t170\nMediumBlue\t0\t0 \t205\nMediumOrchid\t186\t85 \t211\nMediumOrchid1\t224\t102 \t255\nMediumOrchid2\t209\t95 \t238\nMediumOrchid3\t180\t82 \t205\nMediumOrchid4\t122\t55 \t139\nMediumPurple\t147\t112 \t219\nMediumPurple1\t171\t130 \t255\nMediumPurple2\t159\t121 \t238\nMediumPurple3\t137\t104 \t205\nMediumPurple4\t93\t71 \t139\nMediumSeaGreen\t60\t179 \t113\nMediumSlateBlue\t123\t104 \t238\nMediumSpringGreen\t0\t250 \t154\nMediumTurquoise\t72\t209 \t204\nMediumVioletRed\t199\t21 \t133\nmidnight blue\t25\t25 \t112\nMidnightBlue\t25\t25 \t112\nmint cream\t245\t255 \t250\nMintCream\t245\t255 \t250\nmisty rose\t255\t228 \t225\nMistyRose\t255\t228 \t225\nMistyRose1\t255\t228 \t225\nMistyRose2\t238\t213 \t210\nMistyRose3\t205\t183 \t181\nMistyRose4\t139\t125 \t123\nmoccasin\t255\t228 \t181\nnavajo white\t255\t222 \t173\nNavajoWhite\t255\t222 \t173\nNavajoWhite1\t255\t222 \t173\nNavajoWhite2\t238\t207 \t161\nNavajoWhite3\t205\t179 \t139\nNavajoWhite4\t139\t121 \t94\nnavy\t0\t0 \t128\nnavy blue\t0\t0 \t128\nNavyBlue\t0\t0 \t128\nold lace\t253\t245 \t230\nOldLace\t253\t245 \t230\nolive\t128\t128\t0\nolive drab\t107\t142 \t35\nOliveDrab\t107\t142 \t35\nOliveDrab1\t192\t255 \t62\nOliveDrab2\t179\t238 \t58\nOliveDrab3\t154\t205 \t50\nOliveDrab4\t105\t139 \t34\norange\t255\t165 \t0\norange red\t255\t69 \t0\norange1\t255\t165 \t0\norange2\t238\t154 \t0\norange3\t205\t133 \t0\norange4\t139\t90 \t0\nOrangeRed\t255\t69 \t0\nOrangeRed1\t255\t69 \t0\nOrangeRed2\t238\t64 \t0\nOrangeRed3\t205\t55 \t0\nOrangeRed4\t139\t37 \t0\norchid\t218\t112 \t214\norchid1\t255\t131 \t250\norchid2\t238\t122 \t233\norchid3\t205\t105 \t201\norchid4\t139\t71 \t137\npale goldenrod\t238\t232 \t170\npale green\t152\t251 \t152\npale turquoise\t175\t238 \t238\npale violet red\t219\t112 \t147\nPaleGoldenrod\t238\t232 \t170\nPaleGreen\t152\t251 \t152\nPaleGreen1\t154\t255 \t154\nPaleGreen2\t144\t238 \t144\nPaleGreen3\t124\t205 \t124\nPaleGreen4\t84\t139 \t84\nPaleTurquoise\t175\t238 \t238\nPaleTurquoise1\t187\t255 \t255\nPaleTurquoise2\t174\t238 \t238\nPaleTurquoise3\t150\t205 \t205\nPaleTurquoise4\t102\t139 \t139\nPaleVioletRed\t219\t112 \t147\nPaleVioletRed1\t255\t130 \t171\nPaleVioletRed2\t238\t121 \t159\nPaleVioletRed3\t205\t104 \t127\nPaleVioletRed4\t139\t71 \t93\npapaya whip\t255\t239 \t213\nPapayaWhip\t255\t239 \t213\npeach puff\t255\t218 \t185\nPeachPuff\t255\t218 \t185\nPeachPuff1\t255\t218 \t185\nPeachPuff2\t238\t203 \t173\nPeachPuff3\t205\t175 \t149\nPeachPuff4\t139\t119 \t101\nperu\t205\t133 \t63\npink\t255\t192 \t203\npink1\t255\t181 \t197\npink2\t238\t169 \t184\npink3\t205\t145 \t158\npink4\t139\t99 \t108\nplum\t221\t160 \t221\nplum1\t255\t187 \t255\nplum2\t238\t174 \t238\nplum3\t205\t150 \t205\nplum4\t139\t102 \t139\npowder blue\t176\t224 \t230\nPowderBlue\t176\t224 \t230\npurple\t128\t0 \t128\npurple1\t155\t48 \t255\npurple2\t145\t44 \t238\npurple3\t125\t38 \t205\npurple4\t85\t26 \t139\nred\t255\t0 \t0\nred1\t255\t0 \t0\nred2\t238\t0 \t0\nred3\t205\t0 \t0\nred4\t139\t0 \t0\nrosy brown\t188\t143 \t143\nRosyBrown\t188\t143 \t143\nRosyBrown1\t255\t193 \t193\nRosyBrown2\t238\t180 \t180\nRosyBrown3\t205\t155 \t155\nRosyBrown4\t139\t105 \t105\nroyal blue\t65\t105 \t225\nRoyalBlue\t65\t105 \t225\nRoyalBlue1\t72\t118 \t255\nRoyalBlue2\t67\t110 \t238\nRoyalBlue3\t58\t95 \t205\nRoyalBlue4\t39\t64 \t139\nsaddle brown\t139\t69 \t19\nSaddleBrown\t139\t69 \t19\nsalmon\t250\t128 \t114\nsalmon1\t255\t140 \t105\nsalmon2\t238\t130 \t98\nsalmon3\t205\t112 \t84\nsalmon4\t139\t76 \t57\nsandy brown\t244\t164 \t96\nSandyBrown\t244\t164 \t96\nsea green\t46\t139 \t87\nSeaGreen\t46\t139 \t87\nSeaGreen1\t84\t255 \t159\nSeaGreen2\t78\t238 \t148\nSeaGreen3\t67\t205 \t128\nSeaGreen4\t46\t139 \t87\nseashell\t255\t245 \t238\nseashell1\t255\t245 \t238\nseashell2\t238\t229 \t222\nseashell3\t205\t197 \t191\nseashell4\t139\t134 \t130\nsienna\t160\t82 \t45\nsienna1\t255\t130 \t71\nsienna2\t238\t121 \t66\nsienna3\t205\t104 \t57\nsienna4\t139\t71 \t38\nsilver\t192\t192\t192\nsky blue\t135\t206 \t235\nSkyBlue\t135\t206 \t235\nSkyBlue1\t135\t206 \t255\nSkyBlue2\t126\t192 \t238\nSkyBlue3\t108\t166 \t205\nSkyBlue4\t74\t112 \t139\nslate blue\t106\t90 \t205\nslate gray\t112\t128 \t144\nslate grey\t112\t128 \t144\nSlateBlue\t106\t90 \t205\nSlateBlue1\t131\t111 \t255\nSlateBlue2\t122\t103 \t238\nSlateBlue3\t105\t89 \t205\nSlateBlue4\t71\t60 \t139\nSlateGray\t112\t128 \t144\nSlateGray1\t198\t226 \t255\nSlateGray2\t185\t211 \t238\nSlateGray3\t159\t182 \t205\nSlateGray4\t108\t123 \t139\nSlateGrey\t112\t128 \t144\nsnow\t255\t250 \t250\nsnow1\t255\t250 \t250\nsnow2\t238\t233 \t233\nsnow3\t205\t201 \t201\nsnow4\t139\t137 \t137\nspring green\t0\t255 \t127\nSpringGreen\t0\t255 \t127\nSpringGreen1\t0\t255 \t127\nSpringGreen2\t0\t238 \t118\nSpringGreen3\t0\t205 \t102\nSpringGreen4\t0\t139 \t69\nsteel blue\t70\t130 \t180\nSteelBlue\t70\t130 \t180\nSteelBlue1\t99\t184 \t255\nSteelBlue2\t92\t172 \t238\nSteelBlue3\t79\t148 \t205\nSteelBlue4\t54\t100 \t139\ntan\t210\t180 \t140\ntan1\t255\t165 \t79\ntan2\t238\t154 \t73\ntan3\t205\t133 \t63\ntan4\t139\t90 \t43\nteal\t0\t128\t128\nthistle\t216\t191 \t216\nthistle1\t255\t225 \t255\nthistle2\t238\t210 \t238\nthistle3\t205\t181 \t205\nthistle4\t139\t123 \t139\ntomato\t255\t99 \t71\ntomato1\t255\t99 \t71\ntomato2\t238\t92 \t66\ntomato3\t205\t79 \t57\ntomato4\t139\t54 \t38\nturquoise\t64\t224 \t208\nturquoise1\t0\t245 \t255\nturquoise2\t0\t229 \t238\nturquoise3\t0\t197 \t205\nturquoise4\t0\t134 \t139\nviolet\t238\t130 \t238\nviolet red\t208\t32 \t144\nVioletRed\t208\t32 \t144\nVioletRed1\t255\t62 \t150\nVioletRed2\t238\t58 \t140\nVioletRed3\t205\t50 \t120\nVioletRed4\t139\t34 \t82\nwheat\t245\t222 \t179\nwheat1\t255\t231 \t186\nwheat2\t238\t216 \t174\nwheat3\t205\t186 \t150\nwheat4\t139\t126 \t102\nwhite\t255\t255 \t255\nwhite smoke\t245\t245 \t245\nWhiteSmoke\t245\t245 \t245\nyellow\t255\t255 \t0\nyellow green\t154\t205 \t50\nyellow1\t255\t255 \t0\nyellow2\t238\t238 \t0\nyellow3\t205\t205 \t0\nyellow4\t139\t139 \t0\nYellowGreen\t154\t205 \t50\n.DE\n.SH \"PORTABILITY ISSUES\"\n.TP\n\\fBmacOS\\fR\n.\nOn macOS, the following additional system colors are available.  This\nfirst group contains all of the HIBrush colors available in the\nHIToolbox library. Note that on macOS 10.14 (Mojave) and later these\ncolors are unlikely to match the color actually used for the purpose\nsuggested by the color name.\n.RS\n.DS\nsystemActiveAreaFill\nsystemAlertBackgroundActive\nsystemAlertBackgroundInactive\nsystemAlternatePrimaryHighlightColor\nsystemAppleGuideCoachmark\nsystemBevelActiveDark\nsystemBevelActiveLight\nsystemBevelInactiveDark\nsystemBevelInactiveLight\nsystemBlack\nsystemButtonActiveDarkHighlight\nsystemButtonActiveDarkShadow\nsystemButtonActiveLightHighlight\nsystemButtonActiveLightShadow\nsystemButtonFace\nsystemButtonFaceActive\nsystemButtonFaceInactive\nsystemButtonFacePressed\nsystemButtonFrame\nsystemButtonFrameActive\nsystemButtonFrameInactive\nsystemButtonInactiveDarkHighlight\nsystemButtonInactiveDarkShadow\nsystemButtonInactiveLightHighlight\nsystemButtonInactiveLightShadow\nsystemButtonPressedDarkHighlight\nsystemButtonPressedDarkShadow\nsystemButtonPressedLightHighlight\nsystemButtonPressedLightShadow\nsystemChasingArrows\nsystemDialogBackgroundActive\nsystemDialogBackgroundInactive\nsystemDocumentWindowBackground\nsystemDragHilite\nsystemDrawerBackground\nsystemFinderWindowBackground\nsystemFocusHighlight\nsystemHighlight\nsystemHighlightAlternate\nsystemHighlightSecondary\nsystemIconLabelBackground\nsystemIconLabelBackgroundSelected\nsystemListViewBackground\nsystemListViewColumnDivider\nsystemListViewEvenRowBackground\nsystemListViewOddRowBackground\nsystemListViewSeparator\nsystemListViewSortColumnBackground\nsystemMenu\nsystemMenuActive\nsystemMenuBackground\nsystemMenuBackgroundSelected\nsystemModelessDialogBackgroundActive\nsystemModelessDialogBackgroundInactive\nsystemMovableModalBackground\nsystemNotificationWindowBackground\nsystemPopupArrowActive\nsystemPopupArrowInactive\nsystemPopupArrowPressed\nsystemPrimaryHighlightColor\nsystemScrollBarDelimiterActive\nsystemScrollBarDelimiterInactive\nsystemSecondaryHighlightColor\nsystemSelectedTabTextColor\nsystemSheetBackground\nsystemSheetBackgroundOpaque\nsystemSheetBackgroundTransparent\nsystemStaticAreaFill\nsystemToolbarBackground\nsystemTransparent\nsystemUtilityWindowBackgroundActive\nsystemUtilityWindowBackgroundInactive\nsystemWhite\nsystemWindowBody\n.DE\n.RE\n.\nTk supports all of the NSColors in the macOS System ColorList.  The\nconvention for naming these colors is that the Tk name is generated by\ncapitalizing the macOS name and adding the prefix \"system\".  On macOS\n10.14 (Mojave) and later many of these \"semantic\" colors will appear\ndifferently depending on whether the NSWindow in which they are used has\nthe Aqua or DarkAqua appearance.  The System ColorList differs between\nreleases of macOS and some colors, such as systemLinkColor and\nsystemControlAccentColor, are simulated on older systems which did not\nprovide them.  All of the colors below are available on all supported\nmacOS releases, but newer systems will support additional colors.\n.RS\n.DS\nsystemControlAccentColor\nsystemControlTextColor\nsystemDisabledControlTextColor\nsystemLabelColor\nsystemLinkColor\nsystemPlaceholderTextColor\nsystemSelectedTextBackgroundColor\nsystemSelectedTextColor\nsystemSeparatorColor\nsystemTextBackgroundColor\nsystemTextColor\n.DE\n.RE\n.\nThe numbered systemWindowBackgroundColors below\nare used in the \\fBttk::notebook\\fR and \\fBttk::labelframe\\fR widgets\nto provide a contrasting background.  Each numbered color contrasts\nwith its predecessor.\n.RS\n.DS\nsystemWindowBackgroundColor\nsystemWindowBackgroundColor1\nsystemWindowBackgroundColor2\nsystemWindowBackgroundColor3\nsystemWindowBackgroundColor4\nsystemWindowBackgroundColor5\nsystemWindowBackgroundColor6\nsystemWindowBackgroundColor7\n.DE\n.RE\n.TP\n\\fBWindows\\fR\n.\nOn Windows, the following additional system colors are available\n(note that the actual color values depend on the currently active OS theme):\n.RS\n.DS\n.ta 6c\nsystem3dDarkShadow\tsystemHighlightText\nsystem3dLight\tsystemInactiveBorder\nsystemActiveBorder\tsystemInactiveCaption\nsystemActiveCaption\tsystemInactiveCaptionText\nsystemAppWorkspace\tsystemInfoBackground\nsystemBackground\tsystemInfoText\nsystemButtonFace\tsystemMenu\nsystemButtonHighlight\tsystemMenuText\nsystemButtonShadow\tsystemPlaceholderText\nsystemButtonText\tsystemScrollbar\nsystemCaptionText\tsystemWindow\nsystemDisabledText\tsystemWindowFrame\nsystemGrayText\tsystemWindowText\nsystemHighlight\n.DE\n.RE\n.SH \"SEE ALSO\"\noptions(n), Tk_GetColor(3)\n.SH KEYWORDS\ncolor, option\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/console.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2001 Donal K. Fellows\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH console n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nconsole \\- Control the console on systems without a real console\n.SH SYNOPSIS\n\\fBconsole\\fI subcommand\\fR ?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe console window is a replacement for a real console to allow input\nand output on the standard I/O channels on platforms that do not have\na real console.  It is implemented as a separate interpreter with the\nTk toolkit loaded, and control over this interpreter is given through\nthe \\fBconsole\\fR command.  The behaviour of the console window is\ndefined mainly through the contents of the \\fIconsole.tcl\\fR file in\nthe Tk library. Except for TkAqua, this command is not available when\nTk is loaded into a tclsh interpreter with\n.QW \"\\fBpackage require tk\\fR\" ,\nas a conventional terminal is expected to be present in that case.\nIn TkAqua, this command is disabled when there is a startup script\nand stdin is \\fB/dev/null\\fR (as is the case e.g. when a bundled application\nembedding Tk is started by the macOS Launcher).  To enable the command\nin that case, define the environment variable \\fBTK_CONSOLE\\fR.  This can be\ndone by modifying the Info.plist file by adding the LSEnvironment key\nto the main dict and setting its value to be a dict with the key\n\\fBTK_CONSOLE\\fR.\n.PP\n.\\\" METHOD: eval\n.TP\n\\fBconsole eval \\fIscript\\fR\n.\nEvaluate the \\fIscript\\fR argument as a Tcl script in the console\ninterpreter.  The normal interpreter is accessed through the\n\\fBconsoleinterp\\fR command in the console interpreter.\n.\\\" METHOD: hide\n.TP\n\\fBconsole hide\\fR\n.\nHide the console window from view.  Precisely equivalent to\nwithdrawing the \\fB.\\fR window in the console interpreter.\n.\\\" METHOD: show\n.TP\n\\fBconsole show\\fR\n.\nDisplay the console window.  Precisely equivalent to deiconifying the\n\\fB.\\fR window in the console interpreter.\n.\\\" METHOD: title\n.TP\n\\fBconsole title \\fR?\\fIstring\\fR?\n.\nQuery or modify the title of the console window.  If \\fIstring\\fR is\nnot specified, queries the title of the console window, and sets the\ntitle of the console window to \\fIstring\\fR otherwise.  Precisely\nequivalent to using the \\fBwm title\\fR command in the console\ninterpreter.\n.SH \"ACCESS TO THE MAIN INTERPRETER\"\n.PP\nThe \\fBconsoleinterp\\fR command in the console interpreter allows\nscripts to be evaluated in the main interpreter.  It supports two\nsubcommands: \\fBeval\\fR and \\fBrecord\\fR.\n.PP\n.\\\" METHOD: eval\n.TP\n\\fBconsoleinterp eval \\fIscript\\fR\n.\nEvaluates \\fIscript\\fR as a Tcl script at the global level in the main\ninterpreter.\n.\\\" METHOD: record\n.TP\n\\fBconsoleinterp record \\fIscript\\fR\n.\nRecords and evaluates \\fIscript\\fR as a Tcl script at the global level\nin the main interpreter as if \\fIscript\\fR had been typed in at the\nconsole.\n.SH \"ADDITIONAL TRAP CALLS\"\n.PP\nThere are several additional commands in the console interpreter that\nare called in response to activity in the main interpreter.\n\\fIThese are documented here for completeness only; they form part of\nthe internal implementation of the console and are likely to change or\nbe modified without warning.\\fR\n.PP\nOutput to the console from the main interpreter via the stdout and\nstderr channels is handled by invoking the \\fBtk::ConsoleOutput\\fR\ncommand in the console interpreter with two arguments.  The first\nargument is the name of the channel being written to, and the second\nargument is the string being written to the channel (after encoding\nand end-of-line translation processing has been performed.)\n.PP\nWhen the \\fB.\\fR window of the main interpreter is destroyed, the\n\\fBtk::ConsoleExit\\fR command in the console interpreter is called\n(assuming the console interpreter has not already been deleted itself,\nthat is.)\n.SH \"DEFAULT BINDINGS\"\n.PP\nThe default script creates a console window (implemented using a text\nwidget) that has the following behaviour:\n.IP [1]\nPressing the tab key inserts a TAB character (as defined by the Tcl\n\\et escape.)\n.IP [2]\nPressing the return key causes the current line (if complete by the\nrules of \\fBinfo complete\\fR) to be passed to the main interpreter for\nevaluation.\n.IP [3]\nPressing the delete key deletes the selected text (if any text is\nselected) or the character to the right of the cursor (if not at the\nend of the line.)\n.IP [4]\nPressing the backspace key deletes the selected text (if any text is\nselected) or the character to the left of the cursor (of not at the\nstart of the line.)\n.IP [5]\nPressing either Control+A or the home key causes the cursor to go to\nthe start of the line (but after the prompt, if a prompt is present on\nthe line.)\n.IP [6]\nPressing either Control+E or the end key causes the cursor to go to\nthe end of the line.\n.IP [7]\nPressing either Control+P or the up key causes the previous entry in\nthe command history to be selected.\n.IP [8]\nPressing either Control+N or the down key causes the next entry in the\ncommand history to be selected.\n.IP [9]\nPressing either Control+B or the left key causes the cursor to move\none character backward as long as the cursor is not at the prompt.\n.IP [10]\nPressing either Control+F or the right key causes the cursor to move\none character forward.\n.IP [11]\nPressing F9 rebuilds the console window by destroying all its children\nand reloading the Tcl script that defined the console's behaviour.\n.IP [12]\nScrolling the mouse wheel while holding Cmd (macOS) or Ctrl (other platforms)\nincreases (scroll up) or decreases (scroll down) the console font size.\n.PP\nMost other behaviour is the same as a conventional text widget except\nfor the way that the \\fI<<Cut>>\\fR event is handled identically to the\n\\fI<<Copy>>\\fR event.\n.SH EXAMPLE\n.PP\nNot all platforms have the \\fBconsole\\fR command, so debugging code\noften has the following code fragment in it so output produced by\n\\fBputs\\fR can be seen while during development:\n.CS\ncatch {\\fBconsole show\\fR}\n.CE\n.SH \"SEE ALSO\"\ndestroy(n), fconfigure(n), history(n), interp(n), puts(n), text(n), wm(n)\n.SH KEYWORDS\nconsole, interpreter, window, interactive, output channels\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/cursors.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n'\\\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>\n'\\\"\n.TH cursors n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ncursors \\- mouse cursors available in Tk\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fB\\-cursor\\fR widget option allows a Tk programmer to change the\nmouse cursor for a particular widget.  The cursor names recognized by\nTk on all platforms are:\n.CS\nX_cursor\narrow\nbased_arrow_down\nbased_arrow_up\nboat\nbogosity\nbottom_left_corner\nbottom_right_corner\nbottom_side\nbottom_tee\nbox_spiral\ncenter_ptr\ncircle\nclock\ncoffee_mug\ncross\ncross_reverse\ncrosshair\ndiamond_cross\ndot\ndotbox\ndouble_arrow\ndraft_large\ndraft_small\ndraped_box\nexchange\nfleur\ngobbler\ngumby\nhand1\nhand2\nheart\nicon\niron_cross\nleft_ptr\nleft_side\nleft_tee\nleftbutton\nll_angle\nlr_angle\nman\nmiddlebutton\nmouse\nnone\npencil\npirate\nplus\nquestion_arrow\nright_ptr\nright_side\nright_tee\nrightbutton\nrtl_logo\nsailboat\nsb_down_arrow\nsb_h_double_arrow\nsb_left_arrow\nsb_right_arrow\nsb_up_arrow\nsb_v_double_arrow\nshuttle\nsizing\nspider\nspraycan\nstar\ntarget\ntcross\ntop_left_arrow\ntop_left_corner\ntop_right_corner\ntop_side\ntop_tee\ntrek\nul_angle\numbrella\nur_angle\nwatch\nxterm\n.CE\n.PP\nThe \\fBnone\\fR cursor can be specified to eliminate the cursor.\n.SH \"PORTABILITY ISSUES\"\n.TP\n\\fBWindows\\fR\n.\nOn Windows systems, the following cursors are mapped to native cursors:\n.RS\n.CS\narrow\ncenter_ptr\ncrosshair\nfleur\nibeam\nicon\nnone\nsb_h_double_arrow\nsb_v_double_arrow\nwatch\nxterm\n.CE\nAnd the following additional cursors are available:\n.CS\nno\nstarting\nsize\nsize_ne_sw\nsize_ns\nsize_nw_se\nsize_we\nuparrow\nwait\n.CE\n.RE\n.TP\n\\fBmacOS\\fR\n.\nOn macOS, the following cursors are mapped to native cursors:\n.RS\n.CS\narrow\ntop_left_arrow\nleft_ptr\ncross\ncrosshair\ntcross\nibeam\nnone\nxterm\n.CE\nAnd the following additional native cursors are available:\n.CS\ncopyarrow\naliasarrow\ncontextualmenuarrow\nmovearrow\ntext\ncross-hair\nhand\nopenhand\nclosedhand\nfist\npointinghand\nresize\nresizeleft\nresizeright\nresizeleftright\nresizeup\nresizedown\nresizeupdown\nresizebottomleft\nresizetopleft\nresizebottomright\nresizetopright\nnotallowed\npoof\nwait\ncountinguphand\ncountingdownhand\ncountingupanddownhand\nspinning\nhelp\nbucket\ncancel\neyedrop\neyedrop-full\nzoom-in\nzoom-out\n.CE\n.RE\n.SH KEYWORDS\ncursor, option\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/destroy.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH destroy n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ndestroy \\- Destroy one or more windows\n.SH SYNOPSIS\n\\fBdestroy \\fR?\\fIwindow window ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis command deletes the windows given by the\n\\fIwindow\\fR arguments, plus all of their descendants.\nIf a \\fIwindow\\fR\n.QW .\nis deleted then all windows will be destroyed and the application will\n(normally) exit.\nThe \\fIwindow\\fRs are destroyed in order, and if an error occurs\nin destroying a window the command aborts without destroying the\nremaining windows.\nNo error is returned if \\fIwindow\\fR does not exist.\n.SH EXAMPLE\n.PP\nDestroy all checkbuttons that are direct children of the given widget:\n.CS\nproc killCheckbuttonChildren {parent} {\n   foreach w [winfo children $parent] {\n      if {[winfo class $w] eq \"Checkbutton\"} {\n         \\fBdestroy\\fR $w\n      }\n   }\n}\n.CE\n.SH KEYWORDS\napplication, destroy, window\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/dialog.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_dialog n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_dialog \\- Create modal dialog and wait for response\n.SH SYNOPSIS\n\\fBtk_dialog \\fIwindow title text bitmap default string string ...\\fR\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure is part of the Tk script library.\nIt is largely \\fIdeprecated\\fR by the \\fBtk_messageBox\\fR.\nIts arguments describe a dialog box:\n.IP \\fIwindow\\fR\nName of top-level window to use for dialog.  Any existing window\nby this name is destroyed.\n.IP \\fItitle\\fR\nText to appear in the window manager's title bar for the dialog.\n.IP \\fItext\\fR\nMessage to appear in the top portion of the dialog box.\n.IP \\fIbitmap\\fR\nIf non-empty, specifies a bitmap (in a form suitable for Tk_GetBitmap)\nto display in the top portion of\nthe dialog, to the left of the text.\nIf this is an empty string then no bitmap is displayed in the dialog.\n.IP \\fIdefault\\fR\nIf this is an integer greater than or equal to zero, then it gives\nthe index of the button that is to be the default button for the dialog\n(0 for the leftmost button, and so on).\nIf negative or an empty string then there will not be any default\nbutton.\n.IP \\fIstring\\fR\nThere will be one button for each of these arguments.\nEach \\fIstring\\fR specifies text to display in a button,\nin order from left to right.\n.PP\nAfter creating a dialog box, \\fBtk_dialog\\fR waits for the user to\nselect one of the buttons either by clicking on the button with the\nmouse or by typing return to invoke the default button (if any).\nThen it returns the index of the selected button:  0 for the leftmost\nbutton, 1 for the button next to it, and so on.\nIf the dialog's window is destroyed before the user selects one\nof the buttons, then \\-1 is returned.\n.PP\nWhile waiting for the user to respond, \\fBtk_dialog\\fR sets a local\ngrab.  This prevents the user from interacting with the application\nin any way except to invoke the dialog box.\n.SH EXAMPLE\n.PP\n.CS\nset reply [\\fBtk_dialog\\fR .foo \"The Title\" \"Do you want to say yes?\" \\e\n        questhead 0 Yes No \"I'm not sure\"]\n.CE\n.SH \"SEE ALSO\"\ntk_messageBox(n)\n.SH KEYWORDS\nbitmap, dialog, modal\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/entry.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH entry n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nentry \\- Create and manipulate 'entry' one-line text entry widgets\n.SH SYNOPSIS\n\\fBentry\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-background\t\\-highlightthickness\t\\-selectbackground\n\\-borderwidth\t\\-insertbackground\t\\-selectborderwidth\n\\-cursor\t\\-insertborderwidth\t\\-selectforeground\n\\-exportselection\t\\-insertofftime\t\\-takefocus\n\\-font\t\\-insertontime\t\\-textvariable\n\\-foreground\t\\-insertwidth\t\\-xscrollcommand\n\\-highlightbackground\t\\-justify\n\\-highlightcolor\t\\-relief\n\\-placeholder\t\\-placeholderforeground\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-disabledbackground disabledBackground DisabledBackground\nSpecifies the background color to use when the entry is disabled.  If\nthis option is the empty string, the normal background color is used.\n.OP \\-disabledforeground disabledForeground DisabledForeground\nSpecifies the foreground color to use when the entry is disabled.  If\nthis option is the empty string, the normal foreground color is used.\n.OP \"\\-invalidcommand or \\-invcmd\" invalidCommand InvalidCommand\nSpecifies a script to eval when \\fB\\-validatecommand\\fR returns 0.\nSetting it to {} disables this feature (the default).  The best use\nof this option is to set it to \\fIbell\\fR.  See \\fBVALIDATION\\fR\nbelow for more information.\n.OP \\-readonlybackground readonlyBackground ReadonlyBackground\nSpecifies the background color to use when the entry is readonly.  If\nthis option is the empty string, the normal background color is used.\n.OP \\-show show Show\nIf this option is specified, then the true contents of the entry\nare not displayed in the window.\nInstead, each character in the entry's value will be displayed as\nthe first character in the value of this option, such as\n.QW * .\nThis is useful, for example, if the entry is to be used to enter\na password.\nIf characters in the entry are selected and copied elsewhere, the\ninformation copied will be what is displayed, not the true contents\nof the entry.\n.OP \\-state state State\nSpecifies one of three states for the entry:  \\fBnormal\\fR,\n\\fBdisabled\\fR, or \\fBreadonly\\fR.  If the entry is readonly, then the\nvalue may not be changed using widget commands and no insertion cursor\nwill be displayed, even if the input focus is in the widget; the\ncontents of the widget may still be selected.  If the entry is\ndisabled, the value may not be changed, no insertion cursor will be\ndisplayed, the contents will not be selectable, and the entry may\nbe displayed in a different color, depending on the values of the\n\\fB\\-disabledforeground\\fR and \\fB\\-disabledbackground\\fR options.\n.OP \\-validate validate Validate\nSpecifies the mode in which validation should operate: \\fBnone\\fR,\n\\fBfocus\\fR, \\fBfocusin\\fR, \\fBfocusout\\fR, \\fBkey\\fR, or \\fBall\\fR.\nIt defaults to \\fBnone\\fR.  When you want validation, you must explicitly\nstate which mode you wish to use.  See \\fBVALIDATION\\fR below for more.\n.OP \"\\-validatecommand or \\-vcmd\" validateCommand ValidateCommand\nSpecifies a script to eval when you want to validate the input into\nthe entry widget.  Setting it to {} disables this feature (the default).\nThis command must return a valid Tcl boolean value.  If it returns 0 (or\nthe valid Tcl boolean equivalent) then it means you reject the new edition\nand it will not occur and the \\fB\\-invalidcommand\\fR will be evaluated if it\nis set. If it returns 1, then the new edition occurs.\nSee \\fBVALIDATION\\fR below for more information.\n.OP \\-width width Width\nSpecifies an integer value indicating the desired width of the entry window,\nin average-size characters of the widget's font.\nIf the value is negative or zero, the widget picks a\nsize just large enough to hold its current text.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBentry\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into an entry widget.\nAdditional options, described above, may be specified on the\ncommand line or in the option database\nto configure aspects of the entry such as its colors, font,\nand relief.  The \\fBentry\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nAn entry is a widget that displays a one-line text string and\nallows that string to be edited using widget commands described below, which\nare typically bound to keystrokes and mouse actions.\nWhen first created, an entry's string is empty.\nA portion of the entry may be selected as described below.\nIf an entry is exporting its selection (see the \\fB\\-exportselection\\fR\noption), then it will observe the standard X11 protocols for handling the\nselection;  entry selections are available as type \\fBSTRING\\fR.\nEntries also observe the standard Tk rules for dealing with the\ninput focus.  When an entry has the input focus it displays an\n\\fIinsertion cursor\\fR to indicate where new characters will be\ninserted.\n.PP\nEntries are capable of displaying strings that are too long to\nfit entirely within the widget's window.  In this case, only a\nportion of the string will be displayed;  commands described below\nmay be used to change the view in the window.  Entries use\nthe standard \\fB\\-xscrollcommand\\fR mechanism for interacting with\nscrollbars (see the description of the \\fB\\-xscrollcommand\\fR option\nfor details).  They also support scanning, as described below.\n.SH VALIDATION\n.PP\nValidation works by setting the \\fB\\-validatecommand\\fR option to a\nscript (\\fIvalidateCommand\\fR) which will be evaluated according to\nthe \\fB\\-validate\\fR option as follows:\n.PP\n.IP \\fBnone\\fR 10\nDefault.  This means no validation will occur.\n.IP \\fBfocus\\fR 10\n\\fIvalidateCommand\\fR will be called when the entry receives or\nloses focus.\n.IP \\fBfocusin\\fR 10\n\\fIvalidateCommand\\fR will be called when the entry receives focus.\n.IP \\fBfocusout\\fR 10\n\\fIvalidateCommand\\fR will be called when the entry loses focus.\n.IP \\fBkey\\fR 10\n\\fIvalidateCommand\\fR will be called when the entry is edited.\n.IP \\fBall\\fR 10\n\\fIvalidateCommand\\fR will be called for all above conditions.\n.PP\nIt is possible to perform percent substitutions on the value of the\n\\fB\\-validatecommand\\fR and \\fB\\-invalidcommand\\fR options,\njust as you would in a \\fBbind\\fR script.  The following substitutions\nare recognized:\n.PP\n.IP \\fB%d\\fR 5\nType of action: 1 for \\fBinsert\\fR, 0 for \\fBdelete\\fR,\nor \\-1 for focus, forced or textvariable validation.\n.IP \\fB%i\\fR 5\nIndex of char string to be inserted/deleted, if any, otherwise \\-1.\n.IP \\fB%P\\fR 5\nThe value of the entry if the edit is allowed.  If you are configuring the\nentry widget to have a new textvariable, this will be the value of that\ntextvariable.\n.IP \\fB%s\\fR 5\nThe current value of entry prior to editing.\n.IP \\fB%S\\fR 5\nThe text string being inserted/deleted, if any, {} otherwise.\n.IP \\fB%v\\fR 5\nThe type of validation currently set.\n.IP \\fB%V\\fR 5\nThe type of validation that triggered the callback\n(key, focusin, focusout, forced).\n.IP \\fB%W\\fR 5\nThe name of the entry widget.\n.PP\nIn general, the \\fB\\-textvariable\\fR and \\fB\\-validatecommand\\fR options can be\ndangerous to mix.  Any problems have been overcome so that using the\n\\fB\\-validatecommand\\fR will not interfere with the traditional behavior of\nthe entry widget.  Using the \\fB\\-textvariable\\fR for read-only purposes will\nnever cause problems.  The danger comes when you try set the\n\\fB\\-textvariable\\fR to something that the \\fB\\-validatecommand\\fR would not\naccept, which causes \\fB\\-validate\\fR to become \\fInone\\fR (the\n\\fB\\-invalidcommand\\fR will not be triggered).  The same happens\nwhen an error occurs evaluating the \\fB\\-validatecommand\\fR.\n.PP\nPrimarily, an error will occur when the \\fB\\-validatecommand\\fR or\n\\fB\\-invalidcommand\\fR encounters an error in its script while evaluating or\n\\fB\\-validatecommand\\fR does not return a valid Tcl boolean value.  The\n\\fB\\-validate\\fR option will also set itself to \\fBnone\\fR when you edit the\nentry widget from within either the \\fB\\-validatecommand\\fR or the\n\\fB\\-invalidcommand\\fR.  Such editions will override the one that was being\nvalidated.  If you wish to edit the entry widget (for example set it to {})\nduring validation and still have the \\fB\\-validate\\fR option set, you should\ninclude the command:\n.CS\nafter idle {%W config -validate %v}\n.CE\nin the \\fB\\-validatecommand\\fR or \\fB\\-invalidcommand\\fR (whichever one you\nwere editing the entry widget from).  It is also recommended to not set an\nassociated \\fB\\-textvariable\\fR during validation, as that can cause the\nentry widget to become out of sync with the \\fB\\-textvariable\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBentry\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This command may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName subcommand \\fR?\\fIarg ...\\fR?\n.CE\n\\fISubcommand\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.\n.SS INDICES\n.PP\nMany of the widget commands for entries take one or more indices as\narguments.  An index specifies a particular character in the entry's\nstring, in any of the following ways:\n.TP 12\n\\fInumber\\fR\n.\nSpecifies the character as a numerical index, where 0 corresponds\nto the first character in the string.\n.TP 12\n\\fBanchor\\fR\n.\nIndicates the anchor point for the selection, which is set with the\n\\fBselect from\\fR and \\fBselect adjust\\fR widget commands.\n.TP 12\n\\fBend\\fR\n.\nIndicates the character just after the last one in the entry's string.\nThis is equivalent to specifying a numerical index equal to the length\nof the entry's string.\n.TP 12\n\\fBinsert\\fR\n.\nIndicates the character adjacent to and immediately following the\ninsertion cursor.\n.TP 12\n\\fBsel.first\\fR\n.\nIndicates the first character in the selection.  It is an error to\nuse this form if the selection is not in the entry window.\n.TP 12\n\\fBsel.last\\fR\n.\nIndicates the character just after the last one in the selection.\nIt is an error to use this form if the selection is not in the\nentry window.\n.TP 12\n\\fB@\\fInumber\\fR\n.\nIn this form, \\fInumber\\fR is treated as an x-coordinate in the\nentry's window;  the character spanning that x-coordinate is used.\nFor example,\n.QW \\fB@0\\fR\nindicates the left-most character in the window.\n.LP\nAbbreviations may be used for any of the forms above, e.g.\n.QW \\fBe\\fR\nor\n.QW \\fBsel.f\\fR .\nIn general, out-of-range indices are automatically rounded to the\nnearest legal value.\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.SS SUBCOMMANDS\n.PP\nThe following commands are possible for entry widgets:\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox \\fIindex\\fR\n.\nReturns a list of four numbers describing the bounding box of the\ncharacter given by \\fIindex\\fR.\nThe first two elements of the list give the x and y coordinates of\nthe upper-left corner of the screen area covered by the character\n(in pixels relative to the widget) and the last two elements give\nthe width and height of the character, in pixels.\nThe bounding box may refer to a region outside the visible area\nof the window.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBentry\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBentry\\fR\ncommand.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIfirst \\fR?\\fIlast\\fR?\n.\nDelete one or more elements of the entry.\n\\fIFirst\\fR is the index of the first character to delete, and\n\\fIlast\\fR is the index of the character just after the last\none to delete.\nIf \\fIlast\\fR is not specified it defaults to \\fIfirst\\fR+1,\ni.e. a single character is deleted.\nThis command returns an empty string.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the entry's string.\n.\\\" METHOD: icursor\n.TP\n\\fIpathName \\fBicursor \\fIindex\\fR\n.\nArrange for the insertion cursor to be displayed just before the character\ngiven by \\fIindex\\fR.  Returns an empty string.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex\\fI index\\fR\n.\nReturns the numerical index corresponding to \\fIindex\\fR.\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex string\\fR\n.\nInsert the characters of \\fIstring\\fR just before the character\nindicated by \\fIindex\\fR.  Returns an empty string.\n.\\\" METHOD: scan\n.TP\n\\fIpathName \\fBscan\\fI option args\\fR\n.\nThis command is used to implement scanning on entries.  It has\ntwo forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBscan mark \\fIx\\fR\n.\nRecords \\fIx\\fR and the current view in the entry window;  used in\nconjunction with later \\fBscan dragto\\fR commands.  Typically this\ncommand is associated with a mouse button press in the widget.  It\nreturns an empty string.\n.TP\n\\fIpathName \\fBscan dragto \\fIx\\fR\n.\nThis command computes the difference between its \\fIx\\fR argument\nand the \\fIx\\fR argument to the last \\fBscan mark\\fR command for\nthe widget.  It then adjusts the view left or right by 10 times the\ndifference in x-coordinates.  This command is typically associated\nwith mouse motion events in the widget, to produce the effect of\ndragging the entry at high speed through the window.  The return\nvalue is an empty string.\n.RE\n.\\\" METHOD: selection\n.TP\n\\fIpathName \\fBselection \\fIoption arg\\fR\n.\nThis command is used to adjust the selection within an entry.  It\nhas several forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBselection adjust \\fIindex\\fR\n.\nLocate the end of the selection nearest to the character given by\n\\fIindex\\fR, and adjust that end of the selection to be at \\fIindex\\fR\n(i.e. including but not going beyond \\fIindex\\fR).  The other\nend of the selection is made the anchor point for future\n\\fBselect to\\fR commands.  If the selection\nis not currently in the entry, then a new selection is created to\ninclude the characters between \\fIindex\\fR and the most recent\nselection anchor point, inclusive.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection clear\\fR\n.\nClear the selection if it is currently in this widget.  If the\nselection is not in this widget then the command has no effect.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection from \\fIindex\\fR\n.\nSet the selection anchor point to just before the character\ngiven by \\fIindex\\fR.  Does not change the selection.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection present\\fR\n.\nReturns 1 if there is are characters selected in the entry,\n0 if nothing is selected.\n.TP\n\\fIpathName \\fBselection range \\fIstart end\\fR\n.\nSets the selection to include the characters starting with\nthe one indexed by \\fIstart\\fR and ending with the one just\nbefore \\fIend\\fR.\nIf \\fIend\\fR refers to the same character as \\fIstart\\fR or an\nearlier one, then the entry's selection is cleared.\n.TP\n\\fIpathName \\fBselection to \\fIindex\\fR\n.\nIf \\fIindex\\fR is before the anchor point, set the selection\nto the characters from \\fIindex\\fR up to but not including\nthe anchor point.\nIf \\fIindex\\fR is the same as the anchor point, do nothing.\nIf \\fIindex\\fR is after the anchor point, set the selection\nto the characters from the anchor point up to but not including\n\\fIindex\\fR.\nThe anchor point is determined by the most recent \\fBselect from\\fR\nor \\fBselect adjust\\fR command in this widget.\nIf the selection is not in this widget then a new selection is\ncreated using the most recent anchor point specified for the widget.\nReturns an empty string.\n.RE\n.\\\" METHOD: validate\n.TP\n\\fIpathName \\fBvalidate\\fR\n.\nThis command is used to force an evaluation of the \\fB\\-validatecommand\\fR\nindependent of the conditions specified by the \\fB\\-validate\\fR option.\nThis is done by temporarily setting the \\fB\\-validate\\fR option to \\fBall\\fR.\nIt returns 0 or 1.\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fIargs\\fR\n.\nThis command is used to query and change the horizontal position of the\ntext in the widget's window.  It can take any of the following\nforms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1;  together they describe\nthe horizontal span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the entry's text is off-screen to the left, the middle 40% is visible\nin the window, and 40% of the text is off-screen to the right.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview\\fI index\\fR\n.\nAdjusts the view in the window so that the character given by \\fIindex\\fR\nis displayed at the left edge of the window.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the character \\fIfraction\\fR of the\nway through the text appears at the left edge of the window.\n\\fIFraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR or an abbreviation\nof one of these.\nIf \\fIwhat\\fR is \\fBpages\\fR then the view adjusts by \\fInumber\\fR screenfuls.\nIf \\fInumber\\fR is negative then characters farther to the left become\nvisible;  if it is positive then characters farther to the right\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts left or right by\n\\fInumber\\fR average-width characters on the display.\n.RE\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for entries that give them\nthe following default behavior. In the descriptions below,\n.QW word\nrefers to a contiguous group of letters, digits, or\n.QW _\ncharacters, or any single character other than these.\n.IP [1]\nClicking mouse button 1 positions the insertion cursor\njust before the character underneath the mouse cursor, sets the\ninput focus to this widget, and clears any selection in the widget.\nDragging with mouse button 1 strokes out a selection between\nthe insertion cursor and the character under the mouse.\n.IP [2]\nDouble-clicking with mouse button 1 selects the word under the mouse\nand positions the insertion cursor at the end of the word.\nDragging after a double click will stroke out a selection consisting\nof whole words.\n.IP [3]\nTriple-clicking with mouse button 1 selects all of the text in the\nentry and positions the insertion cursor at the end of the line.\n.IP [4]\nThe ends of the selection can be adjusted by dragging with mouse\nbutton 1 while the Shift key is down;  this will adjust the end\nof the selection that was nearest to the mouse cursor when button\n1 was pressed.\nIf the button is double-clicked before dragging then the selection\nwill be adjusted in units of whole words.\n.IP [5]\nClicking mouse button 1 with the Control key down will position the\ninsertion cursor in the entry without affecting the selection.\n.IP [6]\nIf any normal printing characters are typed in an entry, they are\ninserted at the point of the insertion cursor.\n.IP [7]\nThe view in the entry can be adjusted by dragging with the middle\nmouse button (button 2, or button 3 in TkAqua). If the middle mouse\nbutton is clicked without moving the mouse, the selection is copied\ninto the entry at the position of the mouse cursor.\n.IP [8]\nIf the mouse is dragged out of the entry on the left or right sides\nwhile button 1 is pressed, the entry will automatically scroll to\nmake more text visible (if there is more text off-screen on the side\nwhere the mouse left the window).\n.IP [9]\nThe Left and Right keys move the insertion cursor one character to the\nleft or right;  they also clear any selection in the entry and set\nthe selection anchor.\nIf Left or Right is typed with the Shift key down, then the insertion\ncursor moves and the selection is extended to include the new character.\nControl-Left and Control-Right move the insertion cursor by words, and\nControl-Shift-Left and Control-Shift-Right move the insertion cursor\nby words and also extend the selection.\nControl-b and Control-f behave the same as Left and Right, respectively.\nMeta-b and Meta-f behave the same as Control-Left and Control-Right,\nrespectively.\n.IP [10]\nThe Home key, or Control-a, will move the insertion cursor to the\nbeginning of the entry and clear any selection in the entry.\nShift-Home moves the insertion cursor to the beginning of the entry\nand also extends the selection to that point.\n.IP [11]\nThe End key, or Control-e, will move the insertion cursor to the\nend of the entry and clear any selection in the entry.\nShift-End moves the cursor to the end and extends the selection\nto that point.\n.IP [12]\nThe Select key and Control-Space set the selection anchor to the position\nof the insertion cursor.  They do not affect the current selection.\nShift-Select and Control-Shift-Space adjust the selection to the\ncurrent position of the insertion cursor, selecting from the anchor\nto the insertion cursor if there was not any selection previously.\n.IP [13]\nControl-/ selects all the text in the entry.\n.IP [14]\nControl-\\e clears any selection in the entry.\n.IP [15]\nThe F16 key (labelled Copy on many Sun workstations) or Meta-w\ncopies the selection in the widget to the clipboard, if there is a selection.\n.IP [16]\nThe F20 key (labelled Cut on many Sun workstations) or Control-w\ncopies the selection in the widget to the clipboard and deletes\nthe selection.\nIf there is no selection in the widget then these keys have no effect.\n.IP [17]\nThe F18 key (labelled Paste on many Sun workstations) or Control-y\ninserts the contents of the clipboard at the position of the\ninsertion cursor.\n.IP [18]\nThe Delete key deletes the selection, if there is one in the entry.\nIf there is no selection, it deletes the character to the right of\nthe insertion cursor.\n.IP [19]\nThe BackSpace key and Control-h delete the selection, if there is one\nin the entry.\nIf there is no selection, it deletes the character to the left of\nthe insertion cursor.\n.IP [20]\nControl-d deletes the character to the right of the insertion cursor.\n.IP [21]\nMeta-d deletes the word to the right of the insertion cursor.\n.IP [22]\nControl-k deletes all the characters to the right of the insertion\ncursor.\n.IP [23]\nControl-t reverses the order of the two characters to the right of\nthe insertion cursor.\n.PP\nIf the entry is disabled using the \\fB\\-state\\fR option, then the entry's\nview can still be adjusted and text in the entry can still be selected,\nbut no insertion cursor will be displayed and no text modifications will\ntake place\nexcept if the entry is linked to a variable using the \\fB\\-textvariable\\fR\noption, in which case any changes to the variable are reflected by the\nentry whatever the value of its \\fB\\-state\\fR option.\n.PP\nThe behavior of entries can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\nttk::entry(n)\n.SH KEYWORDS\nentry, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/event.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 1998-2000 Ajuba Solutions.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH event n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nevent \\- Miscellaneous event facilities: define virtual events and generate events\n.SH SYNOPSIS\n\\fBevent\\fI option \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBevent\\fR command provides several facilities for dealing with\nwindow system events, such as defining virtual events and synthesizing\nevents.  The command has several different forms, determined by the\nfirst argument.  The following forms are currently supported:\n.\\\" METHOD: add\n.TP\n\\fBevent add <<\\fIvirtual\\fB>>\\fI sequence \\fR?\\fIsequence ...\\fR?\n.\nAssociates the virtual event \\fIvirtual\\fR with the physical\nevent sequence(s) given by the \\fIsequence\\fR arguments, so that\nthe virtual event will trigger whenever any one of the \\fIsequence\\fRs\noccurs.\n\\fIVirtual\\fR may be any string value and \\fIsequence\\fR may have\nany of the values allowed for the \\fIsequence\\fR argument to the\n\\fBbind\\fR command.\nIf \\fIvirtual\\fR is already defined, the new physical event sequences\nadd to the existing sequences for the event.\n.\\\" METHOD: delete\n.TP\n\\fBevent delete <<\\fIvirtual\\fB>> \\fR?\\fIsequence sequence ...\\fR?\n.\nDeletes each of the \\fIsequence\\fRs from those associated with\nthe virtual event given by \\fIvirtual\\fR.\n\\fIVirtual\\fR may be any string value and \\fIsequence\\fR may have\nany of the values allowed for the \\fIsequence\\fR argument to the\n\\fBbind\\fR command.\nAny \\fIsequence\\fRs not currently associated with \\fIvirtual\\fR\nare ignored.\nIf no \\fIsequence\\fR argument is provided, all physical event sequences\nare removed for \\fIvirtual\\fR, so that the virtual event will not\ntrigger anymore.\n.\\\" METHOD: generate\n.TP\n\\fBevent generate \\fIwindow event \\fR?\\fIoption value option value ...\\fR?\n.\nGenerates a window event and arranges for it to be processed just as if\nit had come from the window system.\n\\fIWindow\\fR gives the path name of the window for which the event\nwill be generated; it may also be an identifier (such as returned by\n\\fBwinfo id\\fR) as long as it is for a window in the current application.\n\\fIEvent\\fR provides a basic description of\nthe event, such as \\fB<Shift-Button-2>\\fR or \\fB<<Paste>>\\fR.\nIf \\fIWindow\\fR is empty the whole screen is meant, and coordinates\nare relative to the screen.\n\\fIEvent\\fR may have any of the forms allowed for the \\fIsequence\\fR\nargument of the \\fBbind\\fR command except that it must consist\nof a single event pattern, not a sequence.\n\\fIOption-value\\fR pairs may be used to specify additional\nattributes of the event, such as the x and y mouse position;  see\n\\fBEVENT FIELDS\\fR below.  If the \\fB\\-when\\fR option is not specified, the\nevent is processed immediately:  all of the handlers for the event\nwill complete before the \\fBevent generate\\fR command returns.\nIf the \\fB\\-when\\fR option is specified then it determines when the\nevent is processed.  Certain events, such as key events, require\nthat the window has focus to receive the event properly.\n.\\\" METHOD: info\n.TP\n\\fBevent info \\fR?\\fB<<\\fIvirtual\\fB>>\\fR?\n.\nReturns information about virtual events.\nIf the \\fB<<\\fIvirtual\\fB>>\\fR argument is omitted, the return value\nis a list of all the virtual events that are currently defined.\nIf \\fB<<\\fIvirtual\\fB>>\\fR is specified then the return value is\na list whose elements are the physical event sequences currently\ndefined for the given virtual event;  if the virtual event is\nnot defined then an empty string is returned.\n.RS\n.PP\nNote that virtual events that are not bound to physical event\nsequences are \\fInot\\fR returned by \\fBevent info\\fR.\n.RE\n.SH \"EVENT FIELDS\"\n.PP\nThe following options are supported for the \\fBevent generate\\fR\ncommand.  These correspond to the\n.QW %\nexpansions allowed in binding scripts for the \\fBbind\\fR command.\n.\\\" OPTION: -above\n.TP\n\\fB\\-above\\fI window\\fR\n.\n\\fIWindow\\fR specifies the \\fIabove\\fR field for the event,\neither as a window path name or as an integer window id.\nValid for \\fBConfigure\\fR events.\nCorresponds to the \\fB%a\\fR substitution for binding scripts.\n.\\\" OPTION: -borderwidth\n.TP\n\\fB\\-borderwidth\\fI size\\fR\n.\n\\fISize\\fR must be a screen distance;  it specifies the\n\\fIborder_width\\fR field for the event.\nValid for \\fBConfigure\\fR events.\nCorresponds to the \\fB%B\\fR substitution for binding scripts.\n.\\\" OPTION: -button\n.TP\n\\fB\\-button\\fI number\\fR\n.\n\\fINumber\\fR must be an integer;  it specifies the \\fIdetail\\fR field\nfor a \\fBButton\\fR or \\fBButtonRelease\\fR event, overriding\nany button  number provided in the base \\fIevent\\fR argument.\nCorresponds to the \\fB%b\\fR substitution for binding scripts.\n.\\\" OPTION: -count\n.TP\n\\fB\\-count\\fI number\\fR\n.\n\\fINumber\\fR must be an integer;  it specifies the \\fIcount\\fR field\nfor the event.  Valid for \\fBExpose\\fR events.\nCorresponds to the \\fB%c\\fR substitution for binding scripts.\n.\\\" OPTION: -data\n.TP\n\\fB\\-data\\fI string\\fR\n.\n\\fIString\\fR may be any value; it specifies the \\fIuser_data\\fR field\nfor the event.  Only valid for virtual events.  Corresponds to the\n\\fB%d\\fR substitution for virtual events in binding scripts.\n.\\\" OPTION: -delta\n.TP\n\\fB\\-delta\\fI number\\fR\n.\n\\fINumber\\fR must be an integer;  it specifies the \\fIdelta\\fR field\nfor the \\fBMouseWheel\\fR event.  The \\fIdelta\\fR refers to the\ndirection and magnitude the mouse wheel was rotated.  Note the value\nis not a screen distance but are units of motion in the mouse wheel.\nTypically these values are multiples of 120.  For example, 120 should\nscroll the text widget up 4 lines and \\-240 would scroll the text\nwidget down 8 lines.  Of course, other widgets may define different\nbehaviors for mouse wheel motion.  This field corresponds to the\n\\fB%D\\fR substitution for binding scripts.\n.\\\" OPTION: -detail\n.TP\n\\fB\\-detail\\fI detail\\fR\n.\n\\fIDetail\\fR specifies the \\fIdetail\\fR field for the event\nand must be one of the following:\n.RS\n.DS\n.ta 6c\n\\fBNotifyAncestor\\fR\t\\fBNotifyNonlinearVirtual\\fR\n\\fBNotifyDetailNone\\fR\t\\fBNotifyPointer\\fR\n\\fBNotifyInferior\\fR\t\\fBNotifyPointerRoot\\fR\n\\fBNotifyNonlinear\\fR\t\\fBNotifyVirtual\\fR\n.DE\nValid for \\fBEnter\\fR, \\fBLeave\\fR, \\fBFocusIn\\fR and\n\\fBFocusOut\\fR events.\nCorresponds to the \\fB%d\\fR substitution for binding scripts.\n.RE\n.\\\" OPTION: -focus\n.TP\n\\fB\\-focus\\fI boolean\\fR\n.\n\\fIBoolean\\fR must be a boolean value;  it specifies the \\fIfocus\\fR\nfield for the event.\nValid for \\fBEnter\\fR and \\fBLeave\\fR events.\nCorresponds to the \\fB%f\\fR substitution for binding scripts.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height\\fI size\\fR\n.\n\\fISize\\fR must be a screen distance;  it specifies the \\fIheight\\fR\nfield for the event.  Valid for \\fBConfigure\\fR events.\nCorresponds to the \\fB%h\\fR substitution for binding scripts.\n.\\\" OPTION: -keycode\n.TP\n\\fB\\-keycode\\fI number\\fR\n.\n\\fINumber\\fR  must be an integer;  it specifies the \\fIkeycode\\fR\nfield for the event.\nValid for \\fBKey\\fR and \\fBKeyRelease\\fR events.\nCorresponds to the \\fB%k\\fR substitution for binding scripts.\n.\\\" OPTION: -keysym\n.TP\n\\fB\\-keysym\\fI name\\fR\n.\n\\fIName\\fR must be the name of a valid keysym, such as \\fBg\\fR,\n\\fBspace\\fR, or \\fBReturn\\fR;  its corresponding\nkeycode value is used as the \\fIkeycode\\fR field for event, overriding\nany detail specified in the base \\fIevent\\fR argument.\nValid for \\fBKey\\fR and \\fBKeyRelease\\fR events.\nCorresponds to the \\fB%K\\fR substitution for binding scripts.\n.\\\" OPTION: -mode\n.TP\n\\fB\\-mode\\fI notify\\fR\n.\n\\fINotify\\fR specifies the \\fImode\\fR field for the event and must be\none of \\fBNotifyNormal\\fR, \\fBNotifyGrab\\fR, \\fBNotifyUngrab\\fR, or\n\\fBNotifyWhileGrabbed\\fR.\nValid for \\fBEnter\\fR, \\fBLeave\\fR, \\fBFocusIn\\fR, and\n\\fBFocusOut\\fR events.\nCorresponds to the \\fB%m\\fR substitution for binding scripts.\n.\\\" OPTION: -override\n.TP\n\\fB\\-override\\fI boolean\\fR\n.\n\\fIBoolean\\fR must be a boolean value;  it specifies the\n\\fIoverride_redirect\\fR field for the event.\nValid for \\fBMap\\fR, \\fBReparent\\fR, and \\fBConfigure\\fR events.\nCorresponds to the \\fB%o\\fR substitution for binding scripts.\n.\\\" OPTION: -place\n.TP\n\\fB\\-place\\fI where\\fR\n.\n\\fIWhere\\fR specifies the \\fIplace\\fR field for the event;  it must be\neither \\fBPlaceOnTop\\fR or \\fBPlaceOnBottom\\fR.\nValid for \\fBCirculate\\fR events.\nCorresponds to the \\fB%p\\fR substitution for binding scripts.\n.\\\" OPTION: -root\n.TP\n\\fB\\-root\\fI window\\fR\n.\n\\fIWindow\\fR must be either a window path name or an integer window\nidentifier;  it specifies the \\fIroot\\fR field for the event.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, and \\fBMotion\\fR\nevents.\nCorresponds to the \\fB%R\\fR substitution for binding scripts.\n.\\\" OPTION: -rootx\n.TP\n\\fB\\-rootx\\fI coord\\fR\n.\n\\fICoord\\fR must be a screen distance;  it specifies the \\fIx_root\\fR\nfield for the event.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, and \\fBMotion\\fR\nevents.  Corresponds to the \\fB%X\\fR substitution for binding scripts.\n.\\\" OPTION: -rooty\n.TP\n\\fB\\-rooty\\fI coord\\fR\n.\n\\fICoord\\fR must be a screen distance;  it specifies the \\fIy_root\\fR\nfield for the event.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, and \\fBMotion\\fR\nevents.\nCorresponds to the \\fB%Y\\fR substitution for binding scripts.\n.\\\" OPTION: -sendevent\n.TP\n\\fB\\-sendevent\\fI boolean\\fR\n.\n\\fIBoolean\\fR must be a boolean value;  it specifies the \\fIsend_event\\fR\nfield for the event.  Valid for all events.  Corresponds to the\n\\fB%E\\fR substitution for binding scripts.\n.\\\" OPTION: -serial\n.TP\n\\fB\\-serial\\fI number\\fR\n.\n\\fINumber\\fR must be an integer;  it specifies the \\fIserial\\fR field\nfor the event.  Valid for all events.\nCorresponds to the \\fB%#\\fR substitution for binding scripts.\n.\\\" OPTION: -state\n.TP\n\\fB\\-state\\fI state\\fR\n.\n\\fIState\\fR specifies the \\fIstate\\fR field for the event.\nFor \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButtons\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, and \\fBMotion\\fR events\nit must be an integer value.\nFor \\fBVisibility\\fR events it must be one of \\fBVisibilityUnobscured\\fR,\n\\fBVisibilityPartiallyObscured\\fR, or \\fBVisibilityFullyObscured\\fR.\nThis option overrides any modifiers such as \\fBMeta\\fR or \\fBControl\\fR\nspecified in the base \\fIevent\\fR.\nCorresponds to the \\fB%s\\fR substitution for binding scripts.\n.\\\" OPTION: -subwindow\n.TP\n\\fB\\-subwindow\\fI window\\fR\n.\n\\fIWindow\\fR specifies the \\fIsubwindow\\fR field for the event, either\nas a path name for a Tk widget or as an integer window identifier.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, and \\fBMotion\\fR events.\nSimilar to \\fB%S\\fR substitution for binding scripts.\n.\\\" OPTION: -time\n.TP\n\\fB\\-time\\fI integer\\fR\n.\n\\fIInteger\\fR must be an integer value;  it specifies the \\fItime\\fR field\nfor the event. Additionally, the special value \\fBcurrent\\fR is allowed;\nthis value will be substituted by the current event time.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBEnter\\fR, \\fBLeave\\fR, \\fBMotion\\fR,\nand \\fBProperty\\fR events.\nCorresponds to the \\fB%t\\fR substitution for binding scripts.\n.\\\" OPTION: -warp\n.TP\n\\fB\\-warp\\fI boolean\\fR\n.\n\\fIboolean\\fR must be a boolean value;  it specifies whether\nthe screen pointer should be warped as well.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, and \\fBMotion\\fR events.  Tk supports pointer warping\nrelative to the screen's root window, and relative to a Tk window. In the\nlatter case, the pointer will only warp if the window is mapped.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width\\fI size\\fR\n.\n\\fISize\\fR must be a screen distance;  it specifies the \\fIwidth\\fR field\nfor the event.\nValid for \\fBConfigure\\fR events.\nCorresponds to the \\fB%w\\fR substitution for binding scripts.\n.\\\" OPTION: -when\n.TP\n\\fB\\-when\\fI when\\fR\n.\n\\fIWhen\\fR determines when the event will be processed;  it must have one\nof the following values:\n.RS\n.IP \\fBnow\\fR 10\nProcess the event immediately, before the command returns.\nThis also happens if the \\fB\\-when\\fR option is omitted.\n.IP \\fBtail\\fR 10\nPlace the event on Tcl's event queue behind any events already\nqueued for this application.\n.IP \\fBhead\\fR 10\nPlace the event at the front of Tcl's event queue, so that it\nwill be handled before any other events already queued.\n.IP \\fBmark\\fR 10\nPlace the event at the front of Tcl's event queue but behind any\nother events already queued with \\fB\\-when mark\\fR.\nThis option is useful when generating a series of events that should\nbe processed in order but at the front of the queue.\n.RE\n.\\\" OPTION: -x\n.TP\n\\fB\\-x\\fI coord\\fR\n.\n\\fICoord\\fR must be a screen distance;  it specifies the \\fIx\\fR field\nfor the event.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBMotion\\fR, \\fBEnter\\fR, \\fBLeave\\fR,\n\\fBExpose\\fR, \\fBConfigure\\fR, \\fBGravity\\fR, and \\fBReparent\\fR\nevents.\nCorresponds to the \\fB%x\\fR substitution for binding scripts.\nIf \\fIWindow\\fR is empty the coordinate is relative to the\nscreen, and this option corresponds to the \\fB%X\\fR substitution\nfor binding scripts.\n.\\\" OPTION: -y\n.TP\n\\fB\\-y\\fI coord\\fR\n.\n\\fICoord\\fR must be a screen distance;  it specifies the \\fIy\\fR\nfield for the event.\nValid for \\fBKey\\fR, \\fBKeyRelease\\fR, \\fBButton\\fR,\n\\fBButtonRelease\\fR, \\fBMotion\\fR, \\fBEnter\\fR, \\fBLeave\\fR,\n\\fBExpose\\fR, \\fBConfigure\\fR, \\fBGravity\\fR, and \\fBReparent\\fR\nevents.\nCorresponds to the \\fB%y\\fR substitution for binding scripts.\nIf \\fIWindow\\fR is empty the coordinate is relative to the\nscreen, and this option corresponds to the \\fB%Y\\fR substitution\nfor binding scripts.\n.PP\nAny options that are not specified when generating an event are filled\nwith the value 0, except for \\fIserial\\fR, which is filled with the\nnext X event serial number.\n.SH \"PREDEFINED VIRTUAL EVENTS\"\n.PP\nTk defines the following virtual events for the purposes of\nnotification:\n.TP\n\\fB<<AltUnderlined>>\\fR\n.\nThis is sent to widget to notify it that the letter it has underlined\n(as an accelerator indicator) with the \\fB\\-underline\\fR option has\nbeen pressed in combination with the Alt key. The usual response to\nthis is to either focus into the widget (or some related widget) or to\ninvoke the widget.\n.TP\n\\fB<<Invoke>>\\fR\n.\nThis can be sent to some widgets (e.g. button, listbox, menu) as an\nalternative to <space>.\n.TP\n\\fB<<ListboxSelect>>\\fR\n.\nThis is sent to a listbox when the set of selected item(s) in the\nlistbox is updated.\n.TP\n\\fB<<MenuSelect>>\\fR\n.\nThis is sent to a menu when the currently selected item in the menu\nchanges. It is intended for use with context-sensitive help systems.\n.TP\n\\fB<<Modified>>\\fR\n.\nThis is sent to a text widget when the contents of the widget are\nchanged.\n.TP\n\\fB<<Selection>>\\fR\n.\nThis is sent to a text widget when the selection in the widget is\nchanged.\n.TP\n\\fB<<ThemeChanged>>\\fR\n.\nThis is sent to all widgets when the ttk theme changed. The ttk\nwidgets listen to this event and redisplay themselves when it fires.\nThe legacy widgets ignore this event.\n.TP\n\\fB<<TkWorldChanged>>\\fR\n.\nThis event is sent to all widgets when a font is changed, for example,\nby the use of [font configure].  The user_data field (%d) will have the\nvalue \"FontChanged\".  For other system wide changes, this event will\nbe sent to all widgets, and the user_data field will indicate the\ncause of the change.  NOTE: all tk and ttk widgets already handle this\nevent internally.\n.TP\n\\fB<<TraverseIn>>\\fR\n.\nThis is sent to a widget when the focus enters the widget because of a\nuser-driven\n.QW \"tab to widget\"\naction.\n.TP\n\\fB<<TraverseOut>>\\fR\n.\nThis is sent to a widget when the focus leaves the widget because of a\nuser-driven\n.QW \"tab to widget\"\naction.\n.TP\n\\fB<<UndoStack>>\\fR\n.\nThis is sent to a text widget when its undo stack or redo stack becomes\nempty or unempty.\n.TP\n\\fB<<WidgetViewSync>>\\fR\n.\nThis is sent to a text widget when its internal data become obsolete,\nand again when these internal data are back in sync with the widget\nview. The detail field (%d substitution) is either true (when the\nwidget is in sync) or false (when it is not).\n.PP\nTk defines the following virtual events for the purposes of unifying\nbindings across multiple platforms. Users expect them to behave in the\nfollowing way:\n.TP\n\\fB<<Clear>>\\fR\n.\nDelete the currently selected widget contents.\n.TP\n\\fB<<Copy>>\\fR\n.\nCopy the currently selected widget contents to the clipboard.\n.TP\n\\fB<<Cut>>\\fR\n.\nMove the currently selected widget contents to the clipboard.\n.TP\n\\fB<<LineEnd>>\\fR\n.\nMove to the end of the line in the current widget while deselecting any\nselected contents.\n.TP\n\\fB<<LineStart>>\\fR\n.\nMove to the start of the line in the current widget while deselecting any\nselected contents.\n.TP\n\\fB<<NextChar>>\\fR\n.\nMove to the next item (i.e., visible character) in the current widget while\ndeselecting any selected contents.\n.TP\n\\fB<<NextLine>>\\fR\n.\nMove to the next line in the current widget while deselecting any selected\ncontents.\n.TP\n\\fB<<NextPara>>\\fR\n.\nMove to the next paragraph in the current widget while deselecting any\nselected contents.\n.TP\n\\fB<<NextWord>>\\fR\n.\nMove to the next group of items (i.e., visible word) in the current widget\nwhile deselecting any selected contents.\n.TP\n\\fB<<Paste>>\\fR\n.\nReplace the currently selected widget contents with the contents of\nthe clipboard.\n.TP\n\\fB<<PasteSelection>>\\fR\n.\nInsert the contents of the selection at the mouse location. (This\nevent has meaningful \\fB%x\\fR and \\fB%y\\fR substitutions).\n.TP\n\\fB<<PrevChar>>\\fR\n.\nMove to the previous item (i.e., visible character) in the current widget\nwhile deselecting any selected contents.\n.TP\n\\fB<<PrevLine>>\\fR\n.\nMove to the previous line in the current widget while deselecting any selected\ncontents.\n.TP\n\\fB<<PrevPara>>\\fR\n.\nMove to the previous paragraph in the current widget while deselecting any\nselected contents.\n.TP\n\\fB<<PrevWindow>>\\fR\n.\nTraverse to the previous window.\n.TP\n\\fB<<PrevWord>>\\fR\n.\nMove to the previous group of items (i.e., visible word) in the current widget\nwhile deselecting any selected contents.\n.TP\n\\fB<<Redo>>\\fR\n.\nRedo one undone action.\n.TP\n\\fB<<SelectAll>>\\fR\n.\nSet the range of selected contents to the complete widget.\n.TP\n\\fB<<SelectLineEnd>>\\fR\n.\nMove to the end of the line in the current widget while extending the range\nof selected contents.\n.TP\n\\fB<<SelectLineStart>>\\fR\n.\nMove to the start of the line in the current widget while extending the range\nof selected contents.\n.TP\n\\fB<<SelectNextChar>>\\fR\n.\nMove to the next item (i.e., visible character) in the current widget while\nextending the range of selected contents.\n.TP\n\\fB<<SelectNextLine>>\\fR\n.\nMove to the next line in the current widget while extending the range of\nselected contents.\n.TP\n\\fB<<SelectNextPara>>\\fR\n.\nMove to the next paragraph in the current widget while extending the range\nof selected contents.\n.TP\n\\fB<<SelectNextWord>>\\fR\n.\nMove to the next group of items (i.e., visible word) in the current widget\nwhile extending the range of selected contents.\n.TP\n\\fB<<SelectNone>>\\fR\n.\nReset the range of selected contents to be empty.\n.TP\n\\fB<<SelectPrevChar>>\\fR\n.\nMove to the previous item (i.e., visible character) in the current widget\nwhile extending the range of selected contents.\n.TP\n\\fB<<SelectPrevLine>>\\fR\n.\nMove to the previous line in the current widget while extending the range of\nselected contents.\n.TP\n\\fB<<SelectPrevPara>>\\fR\n.\nMove to the previous paragraph in the current widget while extending the\nrange of selected contents.\n.TP\n\\fB<<SelectPrevWord>>\\fR\n.\nMove to the previous group of items (i.e., visible word) in the current widget\nwhile extending the range of selected contents.\n.TP\n\\fB<<ToggleSelection>>\\fR\n.\nToggle the selection.\n.TP\n\\fB<<Undo>>\\fR\n.\nUndo the last action.\n.SH EXAMPLES\n.SS \"MAPPING KEYS TO VIRTUAL EVENTS\"\n.PP\nIn order for a virtual event binding to trigger, two things must\nhappen.  First, the virtual event must be defined with the\n\\fBevent add\\fR command.  Second, a binding must be created for\nthe virtual event with the \\fBbind\\fR command.\nConsider the following virtual event definitions:\n.PP\n.CS\n\\fBevent add\\fR <<Paste>> <Control-y>\n\\fBevent add\\fR <<Paste>> <Button-2>\n\\fBevent add\\fR <<Save>> <Control-X><Control-S>\n\\fBevent add\\fR <<Save>> <Shift-F12>\nif {[tk windowingsystem] eq \"aqua\"} {\n    \\fBevent add\\fR <<Save>> <Command-s>\n}\n.CE\n.PP\nIn the \\fBbind\\fR command, a virtual event can be bound like any other\nbuiltin event type as follows:\n.PP\n.CS\nbind Entry <<Paste>> {%W insert [selection get]}\n.CE\n.PP\nThe double angle brackets are used to specify that a virtual event is being\nbound.  If the user types Control-y or presses button 2, or if\na \\fB<<Paste>>\\fR virtual event is synthesized with \\fBevent generate\\fR,\nthen the \\fB<<Paste>>\\fR binding will be invoked.\n.PP\nIf a virtual binding has the exact same sequence as a separate\nphysical binding, then the physical binding will take precedence.\nConsider the following example:\n.PP\n.CS\n\\fBevent add\\fR <<Paste>> <Control-y> <Meta-Control-y>\nbind Entry <Control-y> {puts Control-y}\nbind Entry <<Paste>> {puts Paste}\n.CE\n.PP\nWhen the user types Control-y the \\fB<Control-y>\\fR binding\nwill be invoked, because a physical event is considered\nmore specific than a virtual event, all other things being equal.\nHowever, when the user types Meta-Control-y the\n\\fB<<Paste>>\\fR binding will be invoked, because the\n\\fBMeta\\fR modifier in the physical pattern associated with the\nvirtual binding is more specific than the \\fB<Control-y\\fR> sequence for\nthe physical event.\n.PP\nBindings on a virtual event may be created before the virtual event exists.\nIndeed, the virtual event never actually needs to be defined, for instance,\non platforms where the specific virtual event would be meaningless or\nungeneratable.\n.PP\nWhen a definition of a virtual event changes at run time, all windows\nwill respond immediately to the new definition.\nStarting from the preceding example, if the following code is executed:\n.PP\n.CS\nbind Entry <Control-y> {}\n\\fBevent add\\fR <<Paste>> <F6>\n.CE\n.PP\nthe behavior will change such in two ways.  First, the shadowed\n\\fB<<Paste>>\\fR binding will emerge.\nTyping Control-y will no longer invoke the \\fB<Control-y>\\fR binding,\nbut instead invoke the virtual event \\fB<<Paste>>\\fR.  Second,\npressing the F6 key will now also invoke the \\fB<<Paste>>\\fR binding.\n.SS \"MOVING THE MOUSE POINTER\"\n.PP\nSometimes it is useful to be able to really move the mouse pointer. For\nexample, if you have some software that is capable of demonstrating directly\nto the user how to use the program. To do this, you need to\n.QW warp\nthe mouse around by using \\fBevent generate\\fR, like this:\n.PP\n.CS\nfor {set xy 0} {$xy < 200} {incr xy} {\n    \\fBevent generate\\fR . <Motion> -x $xy -y $xy -warp 1\n    update\n    after 50\n}\n.CE\n.PP\nNote that it is usually considered bad style to move the mouse pointer for the\nuser because it removes control from them. Therefore this technique should be\nused with caution. Also note that it is not guaranteed to function on all\nplatforms.\n.SH \"SEE ALSO\"\nbind(n)\n.SH KEYWORDS\nevent, binding, define, handle, virtual event\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/fileicon.n",
    "content": ".\\\" Text automatically generated by txt2man\n'\\\"\n'\\\" Copyright (c) 2025 Kevin Walzer.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk fileicon n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n.SH NAME\nfileicon \\- Platform-native icon image for file type/extension.\n.SH SYNOPSIS\n\\fBtk fileicon\\fI file size\\fR\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk fileicon\\fR command creates a platform-specific file icon. Its intent is to provide a visual representation of a file type that is expected by users on that platform. The command takes two arguments -  an aboslute file path and an icon size, which be any size (on Windows these map to the closest of 16, 32, 48 or 256 pixels because of API constraints).\n.SH EXAMPLE\n.PP\nHere is an example of the \\fBtk fileicon\\fR code:\n.PP\n.CS\nset img [tk fileicon [file normalize text.txt] 32]\npack [label .l -text \"text.txt\" -image $img -compound top]\n.CE\n.SH PLATFORM NOTES\n.PP\nOn Windows and macOS, system API's are used; on X11, icons from the Tango project - the default icon theme for the Gnome desktop - are used.\n.\n.SH KEYWORDS\nimage, icon\n"
  },
  {
    "path": "doc/focus.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH focus n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nfocus \\- Manage the input focus\n.SH SYNOPSIS\n.nf\n\\fBfocus\\fR\n\\fBfocus \\fIwindow\\fR\n\\fBfocus \\fIoption\\fR ?\\fIarg ...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBfocus\\fR command is used to manage the Tk input focus.\nAt any given time, one window on each display is designated as\nthe \\fIfocus window\\fR;  any key press or key release events for the\ndisplay are sent to that window.\nIt is normally up to the window manager to redirect the focus among the\ntop-level windows of a display.  For example, some window managers\nautomatically set the input focus to a top-level window whenever\nthe mouse enters it;  others redirect the input focus only when\nthe user clicks on a window.\nUsually the window manager will set the focus\nonly to top-level windows, leaving it up to the application to\nredirect the focus among the children of the top-level.\n.PP\nTk remembers one focus window for each top-level (the most recent\ndescendant of that top-level to receive the focus);  when the window\nmanager gives the focus\nto a top-level, Tk automatically redirects it to the remembered\nwindow.  Within a top-level Tk uses an \\fIexplicit\\fR focus model\nby default.  Moving the mouse within a top-level does not normally\nchange the focus;  the focus changes only when a widget\ndecides explicitly to claim the focus (e.g., because of a button\nclick), or when the user types a key such as Tab that moves the\nfocus.\n.PP\nThe Tcl procedure \\fBtk_focusFollowsMouse\\fR may be invoked to\ncreate an \\fIimplicit\\fR focus model:  it reconfigures Tk so that\nthe focus is set to a window whenever the mouse enters it.\nThe Tcl procedures \\fBtk_focusNext\\fR and \\fBtk_focusPrev\\fR\nimplement a focus order among the windows of a top-level;  they\nare used in the default bindings for Tab and Shift-Tab, among other\nthings.\n.PP\nThe \\fBfocus\\fR command can take any of the following forms:\n.TP\n\\fBfocus\\fR\n.\nReturns the path name of the focus window on the display containing\nthe application's main window,  or an empty string if no window in\nthis application has the focus on that display.   Note:  it is\nbetter to specify the display explicitly using \\fB\\-displayof\\fR\n(see below) so that the code will work in applications using multiple\ndisplays.\n.TP\n\\fBfocus \\fIwindow\\fR\n.\nIf the application currently has the input focus on \\fIwindow\\fR's\ndisplay, this command resets the input focus for \\fIwindow\\fR's display\nto \\fIwindow\\fR and returns an empty string.\nIf the application does not currently have the input focus on\n\\fIwindow\\fR's display, \\fIwindow\\fR will be remembered as the focus\nfor its top-level;  the next time the focus arrives at the top-level,\nTk will redirect it to \\fIwindow\\fR.\nIf \\fIwindow\\fR is an empty string then the command does nothing.\n.TP\n\\fBfocus \\-displayof \\fIwindow\\fR\n.\nReturns the name of the focus window on the display containing \\fIwindow\\fR.\nIf the focus window for \\fIwindow\\fR's display is not in this\napplication, the return value is an empty string.\n.TP\n\\fBfocus \\-force \\fIwindow\\fR\n.\nSets the focus of \\fIwindow\\fR's display to \\fIwindow\\fR, even if\nthe application does not currently have the input focus for the display.\nThis command should be used sparingly, if at all.\nIn normal usage, an application should not claim the focus for\nitself;  instead, it should wait for the window manager to give it\nthe focus.\nIf \\fIwindow\\fR is an empty string then the command does nothing.\n.TP\n\\fBfocus \\-lastfor \\fIwindow\\fR\n.\nReturns the name of the most recent window to have the input focus\namong all the windows in the same top-level as \\fIwindow\\fR.\nIf no window in that top-level has ever had the input focus, or\nif the most recent focus window has been deleted, then the name\nof the top-level is returned.  The return value is the window that\nwill receive the input focus the next time the window manager gives\nthe focus to the top-level.\n.SH \"QUIRKS\"\n.PP\nWhen an internal window receives the input focus, Tk does not actually\nset the X focus to that window;  as far as X is concerned, the focus\nwill stay on the top-level window containing the window with the focus.\nHowever, Tk generates FocusIn and FocusOut events just as if the X\nfocus were on the internal window.   This approach gets around a\nnumber of problems that would occur if the X focus were actually moved;\nthe fact that the X focus is on the top-level is invisible unless\nyou use C code to query the X server directly.\n.SH \"EXAMPLE\"\n.PP\nTo make a window that only participates in the focus traversal ring\nwhen a variable is set, add the following bindings to the widgets\n\\fIbefore\\fR and \\fIafter\\fR it in that focus ring:\n.PP\n.CS\nbutton .before -text \"Before\"\nbutton .middle -text \"Middle\"\nbutton .after  -text \"After\"\ncheckbutton .flag -variable traverseToMiddle -takefocus 0\npack .flag -side left\npack .before .middle .after\nbind .before <Tab> {\n   if {!$traverseToMiddle} {\n      \\fBfocus\\fR .after\n      break\n   }\n}\nbind .after <Shift-Tab> {\n   if {!$traverseToMiddle} {\n      \\fBfocus\\fR .before\n      break\n   }\n}\n\\fBfocus\\fR .before\n.CE\n.SH KEYWORDS\nevents, focus, keyboard, top-level, window manager\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/focusNext.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_focusNext n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_focusNext, tk_focusPrev, tk_focusFollowsMouse \\- Utility procedures for managing the input focus.\n.SH SYNOPSIS\n.nf\n\\fBtk_focusNext \\fIwindow\\fR\n\\fBtk_focusPrev \\fIwindow\\fR\n\\fBtk_focusFollowsMouse\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\n\\fBtk_focusNext\\fR is a utility procedure used for keyboard traversal.\nIt returns the\n.QW next\nwindow after \\fIwindow\\fR in focus order. The focus order is determined by\nthe stacking order of windows and the structure of the window hierarchy.\nAmong siblings, the focus order is the same as the stacking order, with the\nlowest window being first.\nIf a window has children, the window is visited first, followed by\nits children (recursively), followed by its next sibling.\nTop-level windows other than \\fIwindow\\fR are skipped, so that\n\\fBtk_focusNext\\fR never returns a window in a different top-level\nfrom \\fIwindow\\fR.\n.PP\nAfter computing the next window, \\fBtk_focusNext\\fR examines the\nwindow's \\fB\\-takefocus\\fR option to see whether it should be skipped.\nIf so, \\fBtk_focusNext\\fR continues on to the next window in the focus\norder, until it eventually finds a window that will accept the focus\nor returns back to \\fIwindow\\fR.\n.PP\n\\fBtk_focusPrev\\fR is similar to \\fBtk_focusNext\\fR except that it\nreturns the window just before \\fIwindow\\fR in the focus order.\n.PP\n\\fBtk_focusFollowsMouse\\fR changes the focus model for the application\nto an implicit one where the window under the mouse gets the focus.\nAfter this procedure is called, whenever the mouse enters a window\nTk will automatically give it the input focus.\nThe \\fBfocus\\fR command may be used to move the focus to a window\nother than the one under the mouse, but as soon as the mouse moves\ninto a new window the focus will jump to that window.\n.PP\nNote that at present there is no built-in support for returning the\napplication to an explicit focus model;  to do this you will have\nto write a script that deletes the bindings created by\n\\fBtk_focusFollowsMouse\\fR.\n.SH KEYWORDS\nfocus, keyboard traversal, top-level\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/font.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH font n 8.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nfont \\- Create and inspect fonts.\n.SH SYNOPSIS\n\\fBfont\\fI option \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBfont\\fR command provides several facilities for dealing with\nfonts, such as defining named fonts and inspecting the actual attributes of\na font.  The command has several different forms, determined by the\nfirst argument.  The following forms are currently supported:\n.\\\" METHOD: actual\n.TP\n\\fBfont actual \\fIfont\\fR ?\\fB\\-displayof \\fIwindow\\fR? ?\\fIoption\\fR? ?\\fB\\-\\|\\-\\fR? ?\\fIchar\\fR?\n.\nReturns information about the actual attributes that are obtained when\n\\fIfont\\fR is used on \\fIwindow\\fR's display; the actual attributes obtained\nmay differ from the attributes requested due to platform-dependent\nlimitations, such as the availability of font families and point sizes.\n\\fIfont\\fR is a font description; see \\fBFONT DESCRIPTIONS\\fR below.  If the\n\\fIwindow\\fR argument is omitted, it defaults to the main window.  If\n\\fIoption\\fR is specified, returns the value of that attribute; if it is\nomitted, the return value is a list of all the attributes and their values.\nSee \\fBFONT OPTIONS\\fR below for a list of the possible attributes.  If the\n\\fIchar\\fR argument is supplied, it must be a single character. The font\nattributes returned will be those of the specific font used to render\nthat character, which will be different from the base font if the base\nfont does not contain the given character.  If \\fIchar\\fR may be a hyphen, it\nshould be preceded by \\fB\\-\\|\\-\\fR to distinguish it from a misspelled\n\\fIoption\\fR.\n.\\\" METHOD: configure\n.TP\n\\fBfont configure \\fIfontname\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the desired attributes for the named font called\n\\fIfontname\\fR.  If no \\fIoption\\fR is specified, returns a list describing\nall the options and their values for \\fIfontname\\fR.  If a single \\fIoption\\fR\nis specified with no \\fIvalue\\fR, then returns the current value of that\nattribute.  If one or more \\fIoption\\fR\\-\\fIvalue\\fR pairs are specified,\nthen the command modifies the given named font to have the given values; in\nthis case, all widgets using that font will redisplay themselves using the\nnew attributes for the font.  See \\fBFONT OPTIONS\\fR below for a list of the\npossible attributes.\n.RS\n.PP\nNote that on Aqua/macOS, the system fonts (see\n\\fBPLATFORM SPECIFIC FONTS\\fR below) may not be actually altered because they\nare implemented by the system theme. To achieve the effect of modification,\nuse \\fBfont actual\\fR to get their configuration and \\fBfont create\\fR to\nsynthesize a copy of the font which can be modified.\n.RE\n.\\\" METHOD: create\n.TP\n\\fBfont create\\fR ?\\fIfontname\\fR? ?\\fIoption value ...\\fR?\n.\nCreates a new named font and returns its name.  \\fIfontname\\fR specifies the\nname for the font; if it is omitted, then Tk generates a new name of the\nform \\fBfont\\fIx\\fR, where \\fIx\\fR is an integer.  There may be any number\nof \\fIoption\\fR\\-\\fIvalue\\fR pairs, which provide the desired attributes for\nthe new named font.  See \\fBFONT OPTIONS\\fR below for a list of the possible\nattributes.\n.\\\" METHOD: delete\n.TP\n\\fBfont delete\\fI fontname\\fR ?\\fIfontname ...\\fR?\n.\nDelete the specified named fonts.  If there are widgets using the named font,\nthe named font will not actually be deleted until all the instances are\nreleased.  Those widgets will continue to display using the last known values\nfor the named font.  If a deleted named font is subsequently recreated with\nanother call to \\fBfont create\\fR, the widgets will use the new named font\nand redisplay themselves using the new attributes of that font.\n.\\\" METHOD: families\n.TP\n\\fBfont families\\fR ?\\fB\\-displayof \\fIwindow\\fR?\n.\nThe return value is a list of the case-insensitive names of all font families\nthat exist on \\fIwindow\\fR's display.  If the \\fIwindow\\fR argument is\nomitted, it defaults to the main window.\n.\\\" METHOD: measure\n.TP\n\\fBfont measure \\fIfont\\fR ?\\fB\\-displayof \\fIwindow\\fR? \\fItext\\fR\n.\nMeasures the amount of space the string \\fItext\\fR would use in the given\n\\fIfont\\fR when displayed in \\fIwindow\\fR.  \\fIfont\\fR is a font description;\nsee \\fBFONT DESCRIPTIONS\\fR below.  If the \\fIwindow\\fR argument is\nomitted, it\ndefaults to the main window.  The return value is the total width in pixels\nof \\fItext\\fR, not including the extra pixels used by highly exaggerated\ncharacters such as cursive\n.QW f .\nIf the string contains newlines or tabs,\nthose characters are not expanded or treated specially when measuring the\nstring.\n.\\\" METHOD: metrics\n.TP\n\\fBfont metrics \\fIfont\\fR ?\\fB\\-displayof \\fIwindow\\fR? ?\\fIoption\\fR?\n.\nReturns information about the metrics (the font-specific data), for\n\\fIfont\\fR when it is used on \\fIwindow\\fR's display.  \\fIfont\\fR is a font\ndescription; see \\fBFONT DESCRIPTIONS\\fR below.  If the \\fIwindow\\fR\nargument is\nomitted, it defaults to the main window.  If \\fIoption\\fR is specified,\nreturns the value of that metric; if it is omitted, the return value is a\nlist of all the metrics and their values.  See \\fBFONT METRICS\\fR\nbelow for a list of the possible metrics.\n.\\\" METHOD: names\n.TP\n\\fBfont names\\fR\n.\nThe return value is a list of all the named fonts that are currently defined.\n.SH \"FONT DESCRIPTIONS\"\n.PP\nThe following formats are accepted as a font description anywhere\n\\fIfont\\fR is specified as an argument above; these same forms are also\npermitted when specifying the \\fB\\-font\\fR option for widgets.\n.TP\n[1] \\fIfontname\\fR\n.\nThe name of a named font, created using the \\fBfont create\\fR command.  When\na widget uses a named font, it is guaranteed that this will never cause an\nerror, as long as the named font exists, no matter what potentially invalid\nor meaningless set of attributes the named font has.  If the named font\ncannot be displayed with exactly the specified attributes, some other close\nfont will be substituted automatically.\n.TP\n[2] \\fIsystemfont\\fR\n.\nThe platform-specific name of a font, interpreted by the graphics server.\nThis also includes, under X, an XLFD (see [4]) for which a single\n.QW \\fB*\\fR\ncharacter was used to elide more than one field in the middle of the\nname.  See \\fBPLATFORM SPECIFIC FONTS\\fR for a list of the system fonts.\n.TP\n[3] \\fIfamily \\fR?\\fIsize\\fR? ?\\fIstyle\\fR? ?\\fIstyle ...\\fR?\n.\nA properly formed list whose first element is the desired font\n\\fIfamily\\fR and whose optional second element is the desired \\fIsize\\fR.\nThe interpretation of the \\fIsize\\fR attribute follows the same rules\ndescribed for \\fB\\-size\\fR in \\fBFONT OPTIONS\\fR below.  Any\nadditional optional\narguments following the \\fIsize\\fR are font \\fIstyle\\fRs.  Possible values\nfor the \\fIstyle\\fR arguments are as follows:\n.RS\n.DS\n.ta 3c 6c 9c\n\\fBnormal\\fR\t\\fBbold\\fR\t\\fBroman\\fR\t\\fBitalic\\fR\n\\fBunderline\\fR\t\\fBoverstrike\\fR\n.DE\n.RE\n.TP\n[4] X-font names (XLFD)\n.\nA Unix-centric font name of the form\n\\fI\\-foundry\\-family\\-weight\\-slant\\-setwidth\\-addstyle\\-pixel\\-point\\-resx\\-resy\\-spacing\\-width\\-charset\\-encoding\\fR.\nThe\n.QW \\fB*\\fR\ncharacter may be used to skip individual fields that the\nuser does not care about.  There must be exactly one\n.QW \\fB*\\fR\nfor each field skipped, except that a\n.QW \\fB*\\fR\nat the end of the XLFD skips any\nremaining fields; the shortest valid XLFD is simply\n.QW \\fB*\\fR ,\nsignifying all fields as defaults.  Any fields that were skipped are\ngiven default\nvalues.  For compatibility, an XLFD always chooses a font of the specified\npixel size (not point size); although this interpretation is not strictly\ncorrect, all existing applications using XLFDs assumed that one\n.QW point\nwas in fact one pixel and would display incorrectly (generally larger) if\nthe correct size font were actually used.\n.TP\n[5] \\fIoption value \\fR?\\fIoption value ...\\fR?\n.\nA properly formed list of \\fIoption\\fR\\-\\fIvalue\\fR pairs that specify\nthe desired attributes of the font, in the same format used when defining\na named font; see \\fBFONT OPTIONS\\fR below.\n.LP\nWhen font description \\fIfont\\fR is used, the system attempts to parse the\ndescription according to each of the above five rules, in the order specified.\nCases [1] and [2] must match the name of an existing named font or of a\nsystem font.  Cases [3], [4], and [5] are accepted on all\nplatforms and the closest available font will be used.  In some situations\nit may not be possible to find any close font (e.g., the font family was\na garbage value); in that case, some system-dependent default font is\nchosen.  If the font description does not match any of the above patterns,\nan error is generated.\n.SH \"FONT METRICS\"\n.PP\nThe following options are used by the \\fBfont metrics\\fR command to query\nfont-specific data determined when the font was created.  These properties are\nfor the whole font itself and not for individual characters drawn in that\nfont.  In the following definitions, the\n.QW baseline\nof a font is the\nhorizontal line where the bottom of most letters line up; certain letters,\nsuch as lower-case\n.QW g\nstick below the baseline.\n.\\\" OPTION: -ascent\n.TP\n\\fB\\-ascent\\fR\n.\nThe amount in pixels that the tallest letter sticks up above the baseline of\nthe font, plus any extra blank space added by the designer of the font.\n.\\\" OPTION: -descent\n.TP\n\\fB\\-descent\\fR\n.\nThe largest amount in pixels that any letter sticks down below the baseline\nof the font, plus any extra blank space added by the designer of the font.\n.\\\" OPTION: -linespace\n.TP\n\\fB\\-linespace\\fR\n.\nReturns how far apart vertically in pixels two lines of text using the same\nfont should be placed so that none of the characters in one line overlap any\nof the characters in the other line.  This is generally the sum of the ascent\nabove the baseline line plus the descent below the baseline.\n.\\\" OPTION: -fixed\n.TP\n\\fB\\-fixed\\fR\n.\nReturns a boolean flag that is\n.QW \\fB1\\fR\nif this is a fixed-width font,\nwhere each normal character is the same width as all the other\ncharacters, or is\n.QW \\fB0\\fR\nif this is a proportionally-spaced font, where\nindividual characters have different widths.  The widths of control\ncharacters, tab characters, and other non-printing characters are not\nincluded when calculating this value.\n.SH \"FONT OPTIONS\"\n.PP\nThe following options are supported on all platforms, and are used when\nconstructing a named font or when specifying a font using style [5] as\nabove:\n.\\\" OPTION: -family\n.TP\n\\fB\\-family \\fIname\\fR\n.\nThe case-insensitive font family name.  Tk guarantees to support the font\nfamilies named \\fBCourier\\fR (a monospaced\n.QW typewriter\nfont), \\fBTimes\\fR (a serifed\n.QW newspaper\nfont), and \\fBHelvetica\\fR (a sans-serif\n.QW European\nfont).  The most closely matching native font family will\nautomatically be substituted when one of the above font families is used.\nThe \\fIname\\fR may also be the name of a native, platform-specific font\nfamily; in that case it will work as desired on one platform but may not\ndisplay correctly on other platforms.  If the family is unspecified or\nunrecognized, a platform-specific default font will be chosen.\n.\\\" OPTION: -size\n.TP\n\\fB\\-size \\fIsize\\fR\n.\nThe desired size of the font.  If the \\fIsize\\fR argument is a positive\nnumber, it is interpreted as a size in points.  If \\fIsize\\fR is a negative\nnumber, its absolute value is interpreted as a size in pixels.  If a\nfont cannot be displayed at the specified size, a nearby size will be\nchosen.  If \\fIsize\\fR is unspecified or zero, a platform-dependent default\nsize will be chosen.\n.RS\n.PP\nSizes should normally be specified in points so the application will remain\nthe same ruler size on the screen, even when changing screen resolutions or\nmoving scripts across platforms.  However, specifying pixels is useful in\ncertain circumstances such as when a piece of text must line up with respect\nto a fixed-size bitmap.  The mapping between points and pixels is set when\nthe application starts, based on properties of the installed monitor, but it\ncan be overridden by calling the \\fBtk scaling\\fR command.\n.RE\n.\\\" OPTION: -weight\n.TP\n\\fB\\-weight \\fIweight\\fR\n.\nThe nominal thickness of the characters in the font.  The value\n\\fBnormal\\fR specifies a normal weight font, while \\fBbold\\fR specifies a\nbold font.  The closest available weight to the one specified will\nbe chosen.  The default weight is \\fBnormal\\fR.\n.\\\" OPTION: -slant\n.TP\n\\fB\\-slant \\fIslant\\fR\n.\nThe amount the characters in the font are slanted away from the\nvertical.  Valid values for slant are \\fBroman\\fR and \\fBitalic\\fR.\nA roman font is the normal, upright appearance of a font, while\nan italic font is one that is tilted some number of degrees from upright.\nThe closest available slant to the one specified will be chosen.\nThe default slant is \\fBroman\\fR.\n.\\\" OPTION: -underline\n.TP\n\\fB\\-underline \\fIboolean\\fR\n.\nThe value is a boolean flag that specifies whether characters in this\nfont should be underlined.  The default value for underline is \\fBfalse\\fR.\n.\\\" OPTION: -overstrike\n.TP\n\\fB\\-overstrike \\fIboolean\\fR\n.\nThe value is a boolean flag that specifies whether a horizontal line should\nbe drawn through the middle of characters in this font.  The default value\nfor overstrike is \\fBfalse\\fR.\n.SH \"STANDARD FONTS\"\n.PP\nThe following named fonts are supported on all systems, and default to values\nthat match appropriate system defaults.\n.IP \\fBTkDefaultFont\\fR\nThis font is the default for all GUI items not otherwise specified.\n.IP \\fBTkTextFont\\fR\nThis font should be used for user text in entry widgets, listboxes etc.\n.IP \\fBTkFixedFont\\fR\nThis font is the standard fixed-width font.\n.IP \\fBTkMenuFont\\fR\nThis font is used for menu items.\n.IP \\fBTkHeadingFont\\fR\nThis font should be used for column headings in lists and tables.\n.IP \\fBTkCaptionFont\\fR\nThis font should be used for window and dialog caption bars.\n.IP \\fBTkSmallCaptionFont\\fR\nThis font should be used for captions on contained windows or tool dialogs.\n.IP \\fBTkIconFont\\fR\nThis font should be used for icon captions.\n.IP \\fBTkTooltipFont\\fR\nThis font should be used for tooltip windows (transient information windows).\n.LP\nIt is \\fInot\\fR advised to change these fonts, as they may be modified by Tk\nitself in response to system changes. Instead, make a copy of the font and\nmodify that.\n.SH \"PLATFORM SPECIFIC FONTS\"\n.PP\nThe following system fonts are supported:\n.TP\n\\fBX Windows\\fR\n.\nAll valid X font names, including those listed by xlsfonts(1), are available.\n.TP\n\\fBMS Windows\\fR\n.\nThe following fonts are supported, and are mapped to the user's\nstyle defaults.\n.RS\n.DS\n.ta 3c 6c\n\\fBsystem\\fR\t\\fBansi\\fR\t\\fBdevice\\fR\n\\fBsystemfixed\\fR\t\\fBansifixed\\fR\t\\fBoemfixed\\fR\n.DE\n.RE\n.TP\n\\fBmacOS\\fR\n.\nThe following fonts are supported, and are mapped to the user's\nstyle defaults.\n.RS\n.DS\n.ta 3c 6c\n\\fBsystem\\fR\t\\fBapplication\\fR\t\\fBmenu\\fR\n.DE\n.PP\nAdditionally, the following named fonts provide access to the Aqua\ntheme fonts:\n.DS\n.ta 5c\n\\fBsystemSystemFont\\fR\t\\fBsystemEmphasizedSystemFont\\fR\n\\fBsystemSmallSystemFont\\fR\t\\fBsystemSmallEmphasizedSystemFont\\fR\n\\fBsystemApplicationFont\\fR\t\\fBsystemLabelFont\\fR\n\\fBsystemViewsFont\\fR\t\\fBsystemMenuTitleFont\\fR\n\\fBsystemMenuItemFont\\fR\t\\fBsystemMenuItemMarkFont\\fR\n\\fBsystemMenuItemCmdKeyFont\\fR\t\\fBsystemWindowTitleFont\\fR\n\\fBsystemPushButtonFont\\fR\t\\fBsystemUtilityWindowTitleFont\\fR\n\\fBsystemAlertHeaderFont\\fR\t\\fBsystemToolbarFont\\fR\n\\fBsystemMiniSystemFont\\fR\t\\fBsystemDetailSystemFont\\fR\n\\fBsystemDetailEmphasizedSystemFont\\fR\n.DE\n.RE\n.SH EXAMPLE\n.PP\nFill a text widget with lots of font demonstrators, one for every font\nfamily installed on your system:\n.CS\npack [text .t -wrap none] -fill both -expand 1\nset count 0\nset tabwidth 0\nforeach family [lsort -dictionary [\\fBfont families\\fR]] {\n    .t tag configure f[incr count] -font [list $family 10]\n    .t insert end ${family}:\\et {} \\e\n            \"This is a simple sampler\\en\" f$count\n    set w [\\fBfont measure\\fR [.t cget -font] ${family}:]\n    if {$w + 5 > $tabwidth} {\n        set tabwidth [expr {$w + 5}]\n        .t configure -tabs $tabwidth\n    }\n}\n.CE\n.SH \"SEE ALSO\"\noptions(n)\n.SH KEYWORDS\nfont\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/fontchooser.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2008 Daniel A. Steffen <das@users.sourceforge.net>\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH fontchooser n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nfontchooser \\- control font selection dialog\n.SH SYNOPSIS\n.nf\n\\fBtk fontchooser\\fR \\fBconfigure\\fR ?\\fI\\-option value ...\\fR?\n\\fBtk fontchooser\\fR \\fBshow\\fR\n\\fBtk fontchooser\\fR \\fBhide\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk fontchooser\\fR command controls the Tk font selection dialog. It uses\nthe native platform font selection dialog where available, or a dialog\nimplemented in Tcl otherwise.\n.PP\nUnlike most of the other Tk dialog commands, \\fBtk fontchooser\\fR does not\nreturn an immediate result, as on some platforms (macOS) the standard font\ndialog is modeless while on others (Windows) it is modal. To accommodate this\ndifference, all user interaction with the dialog will be communicated to the\ncaller via callbacks or virtual events.\n.PP\nThe \\fBtk fontchooser\\fR command can have one of the following forms:\n.\\\" METHOD: configure\n.TP\n\\fBtk fontchooser\\fR \\fBconfigure \\fR?\\fI\\-option value ...\\fR?\n.\nSet or query one or more of the configurations options below (analogous to Tk\nwidget configuration).\n.\\\" METHOD: show\n.TP\n\\fBtk fontchooser\\fR \\fBshow\\fR\n.\nShow the font selection dialog. Depending on the platform, may return\nimmediately or only once the dialog has been withdrawn.\n.\\\" METHOD: hide\n.TP\n\\fBtk fontchooser\\fR \\fBhide\\fR\n.\nHide the font selection dialog if it is visible and cause any pending\n\\fBtk fontchooser\\fR \\fBshow\\fR command to return.\n.PP\n.SH \"CONFIGURATION OPTIONS\"\n.\\\" OPTION: -parent\n.TP\n\\fB\\-parent\\fR\n.\nSpecifies/returns the logical parent window of the font selection dialog\n(similar to the \\fB\\-parent\\fR option to other dialogs). The font selection\ndialog is hidden if it is visible when the parent window is destroyed.\n.\\\" OPTION: -title\n.TP\n\\fB\\-title\\fR\n.\nSpecifies/returns the title of the dialog. Has no effect on platforms where the\nfont selection dialog does not support titles.\n.\\\" OPTION: -font\n.TP\n\\fB\\-font\\fR\n.\nSpecifies/returns the font that is currently selected in the dialog if it is\nvisible, or that will be initially selected when the dialog is shown (if\nsupported by the platform). Can be set to the empty string to indicate that no\nfont should be selected. Fonts can be specified in any form given by the \"FONT\nDESCRIPTION\" section in the \\fBfont\\fR manual page.\n.\\\" OPTION: -command\n.TP\n\\fB\\-command\\fR\n.\nSpecifies/returns the command prefix to be called when a font selection has\nbeen made by the user. The command prefix is evaluated at the global level\nafter having the specification of the selected font appended. On platforms\nwhere the font selection dialog offers the user control of further font\nattributes (such as color), additional key/value pairs may be appended before\nevaluation. Can be set to the empty string to indicate that no callback should\nbe invoked. Fonts are specified by a list of form [3] of the \"FONT DESCRIPTION\"\nsection in the \\fBfont\\fR manual page (i.e. a list of the form\n\\fI{family size style ?style ...?}\\fR).\n.\\\" OPTION: -visible\n.TP\n\\fB\\-visible\\fR\n.\nRead-only option that returns a boolean indicating whether the font selection\ndialog is currently visible. Attempting to set this option results in an error.\n\n.PP\n.SH \"VIRTUAL EVENTS\"\n.TP\n\\fB<<TkFontchooserVisibility>>\\fR\n.\nSent to the dialog parent whenever the visibility of the font selection dialog\nchanges, both as a result of user action (e.g. disposing of the dialog via\nOK/Cancel button or close box) and of the \\fBtk fontchooser\\fR\n\\fBshow\\fR/\\fBhide\\fR commands being called. Binding scripts can determine the\ncurrent visibility of the dialog by querying the \\fB\\-visible\\fR configuration\noption.\n.TP\n\\fB<<TkFontchooserFontChanged>>\\fR\n.\nSent to the dialog parent whenever the font selection dialog is visible and the\nselected font changes, both as a result of user action and of the \\fB\\-font\\fR\nconfiguration option being set. Binding scripts can determine the currently\nselected font by querying the \\fB\\-font\\fR configuration option.\n.PP\n.SH NOTES\n.PP\nCallers should not expect a result from \\fBtk fontchooser\\fR \\fBshow\\fR and may\nnot assume that the dialog has been withdrawn or closed when the command\nreturns. All user interaction with the dialog is communicated to the caller via\nthe \\fB\\-command\\fR callback and the \\fB<<TkFontchooser*>>\\fR virtual events.\nIt is implementation dependent which exact user actions result in the callback\nbeing called resp. the virtual events being sent. Where an Apply or OK button\nis present in the dialog, that button will trigger the \\fB\\-command\\fR callback\nand \\fB<<TkFontchooserFontChanged>>\\fR virtual event. On some implementations\nother user actions may also have that effect; on macOS for instance, the\nstandard font selection dialog immediately reflects all user choices to the\ncaller.\n.PP\nIn the presence of multiple widgets intended to be influenced by the font\nselection dialog, care needs to be taken to correctly handle focus changes: the\nfont selected in the dialog should always match the current font of the widget\nwith the focus, and the \\fB\\-command\\fR callback should only act on the widget\nwith the focus. The recommended practice is to set font dialog \\fB\\-font\\fR and\n\\fB\\-command\\fR configuration options in per\\-widget \\fB<FocusIn>\\fR handlers\n(and if necessary to unset them \\- i.e. set to the empty string \\- in\ncorresponding \\fB<FocusOut>\\fR handlers). This is particularly important for\nimplementers of library code using the font selection dialog, to avoid\nconflicting with application code that may also want to use the dialog.\n.PP\nBecause the font selection dialog is application-global, in the presence of\nmultiple interpreters calling \\fBtk fontchooser\\fR, only the \\fB\\-command\\fR\ncallback set by the interpreter that most recently called \\fBtk fontchooser\\fR\n\\fBconfigure\\fR or \\fBtk fontchooser\\fR \\fBshow\\fR will be invoked in response\nto user action and only the \\fB\\-parent\\fR set by that interpreter will receive\n\\fB<<TkFontchooser*>>\\fR virtual events.\n.PP\nThe font dialog implementation may only store (and return) \\fBfont\\fR\n\\fBactual\\fR data as the value of the \\fB\\-font\\fR configuration option. This\ncan be an issue when \\fB\\-font\\fR is set to a named font, if that font is\nsubsequently changed, the font dialog \\fB\\-font\\fR option needs to be set again\nto ensure its selected font matches the new value of the named font.\n.PP\n.SH EXAMPLE\n.PP\n.CS\nproc fontchooserDemo {} {\n    wm title . \"Font Chooser Demo\"\n    \\fBtk fontchooser\\fR \\fBconfigure\\fR -parent .\n    button .b -command fontchooserToggle -takefocus 0\n    fontchooserVisibility .b\n    bind . \\fB<<TkFontchooserVisibility>>\\fR \\e\n            [list fontchooserVisibility .b]\n    foreach w {.t1 .t2} {\n        text $w -width 20 -height 4 -borderwidth 1 -relief solid\n        bind $w <FocusIn> [list fontchooserFocus $w]\n        $w insert end \"Text Widget $w\"\n    }\n    .t1 configure -font {Courier 14}\n    .t2 configure -font {Times 16}\n    pack .b .t1 .t2; focus .t1\n}\nproc fontchooserToggle {} {\n    \\fBtk fontchooser\\fR [expr {\n            [\\fBtk fontchooser\\fR \\fBconfigure\\fR -visible] ?\n            \"\\fBhide\\fR\" : \"\\fBshow\\fR\"}]\n}\nproc fontchooserVisibility {w} {\n    $w configure -text [expr {\n            [\\fBtk fontchooser\\fR \\fBconfigure\\fR -visible] ?\n            \"Hide Font Dialog\" : \"Show Font Dialog\"}]\n}\nproc fontchooserFocus {w} {\n    \\fBtk fontchooser\\fR \\fBconfigure\\fR -font [$w cget -font] \\e\n            -command [list fontchooserFontSelection $w]\n}\nproc fontchooserFontSelection {w font args} {\n    $w configure -font [font actual $font]\n}\nfontchooserDemo\n.CE\n.SH \"SEE ALSO\"\nfont(n), tk(n)\n.SH KEYWORDS\ndialog, font, font selection, font chooser, font panel\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/frame.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH frame n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nframe \\- Create and manipulate 'frame' simple container widgets\n.SH SYNOPSIS\n\\fBframe\\fI pathName\\fR ?\\fIoptions\\fR?\n.SO\n\\-borderwidth\t\\-highlightcolor\t\\-pady\n\\-cursor\t\\-highlightthickness\t\\-relief\n\\-highlightbackground\t\\-padx\t\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-background background Background\nThis option is the same as the standard \\fB\\-background\\fR option\nexcept that its value may also be specified as an empty string.\nIn this case, the widget will display no background or border, and\nno colors will be consumed from its colormap for its background\nand border.\n.VS \"9.0, TIP262\"\nAn empty background will disable drawing the background image.\n.OP \\-backgroundimage backgroundImage BackgroundImage\nThis specifies an image to display on the frame's background within\nthe border of the frame (i.e., the image will be clipped by the\nframe's highlight ring and border, if either are present); subwidgets\nof the frame will be drawn on top. The image must have been created\nwith the \\fBimage create\\fR command. If specified as the empty string,\nno image will be displayed.\n.VE \"9.0, TIP262\"\n.OP \\-class class Class\nSpecifies a class for the window.\nThis class will be used when querying the option database for\nthe window's other options, and it will also be used later for\nother purposes such as bindings.\nThe \\fB\\-class\\fR option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-colormap colormap Colormap\nSpecifies a colormap to use for the window.\nThe value may be either \\fBnew\\fR, in which case a new colormap is\ncreated for the window and its children, or the name of another\nwindow (which must be on the same screen and have the same visual\nas \\fIpathName\\fR), in which case the new window will use the colormap\nfrom the specified window.\nIf the \\fB\\-colormap\\fR option is not specified, the new window\nuses the same colormap as its parent.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-container container Container\nThe value must be a boolean.  If true, it means that this window will\nbe used as a container in which some other application will be embedded\n(for example, a Tk toplevel can be embedded using the \\fB\\-use\\fR option).\nThe window will support the appropriate window manager protocols for\nthings like geometry requests.  The window should not have any\nchildren of its own in this application.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\nNote that \\fB\\-borderwidth\\fR, \\fB\\-padx\\fR and \\fB\\-pady\\fR are ignored when\nconfigured as a container since a container has no border.\n.OP \\-height height Height\nSpecifies the desired height for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.  If this option is negative or\nzero then the window will not request any size at all.  Note that this\nsets the total height of the frame, any \\fB\\-borderwidth\\fR or similar is\nnot added.  Normally \\fB\\-height\\fR should not be used if a propagating\ngeometry manager, such as \\fBgrid\\fR or \\fBpack\\fR, is used within the\nframe since the geometry manager will override the height of the frame.\n.OP \\-tile tile Tile\n.VS \"9.0, TIP262\"\nThis specifies how to draw the background image (see\n\\fB\\-backgroundimage\\fR) on the frame.\nIf true (according to \\fBTcl_GetBoolean\\fR), the image will be tiled\nto fill the whole frame, with the origin of the first copy of the\nimage being the top left of the interior of the frame.\nIf false (the default), the image will be centered within the frame.\n.VE \"9.0, TIP262\"\n.OP \\-visual visual Visual\nSpecifies visual information for the new window in any of the\nforms accepted by \\fBTk_GetVisual\\fR.\nIf this option is not specified, the new window will use the same\nvisual as its parent.\nThe \\fB\\-visual\\fR option may not be modified with the \\fBconfigure\\fR\nwidget command.\n.OP \\-width width Width\nSpecifies the desired width for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.  If this option is negative or\nzero then the window will not request any size at all.  Note that this\nsets the total width of the frame, any \\fB\\-borderwidth\\fR or similar is\nnot added.  Normally \\fB\\-width\\fR should not be used if a propagating\ngeometry manager, such as \\fBgrid\\fR or \\fBpack\\fR, is used within the\nframe since the geometry manager will override the width of the frame.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBframe\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a frame widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the frame such as its background color\nand relief.  The \\fBframe\\fR command returns the\npath name of the new window.\n.PP\nA frame is a simple widget.  Its primary purpose is to act as a\nspacer or container for complex window layouts.  The only features\nof a frame are its background and an optional 3-D border to make the\nframe appear raised or sunken.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBframe\\fR command creates a new Tcl command whose\nname is the same as the path name of the frame's window.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.PP\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n.PP\n\\fIPathName\\fR is the name of the command, which is the same as\nthe frame widget's path name.  \\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for frame widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBframe\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBframe\\fR\ncommand.\n.SH BINDINGS\n.PP\nWhen a new frame is created, it has no default event bindings:\nframes are not intended to be interactive.\n.SH \"SEE ALSO\"\nlabelframe(n), toplevel(n), ttk::frame(n)\n.SH KEYWORDS\nframe, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/getOpenFile.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_getOpenFile n 4.2 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_getOpenFile, tk_getSaveFile \\- pop up a dialog box for the user to select a file to open or save.\n.SH SYNOPSIS\n.nf\n\\fBtk_getOpenFile \\fR?\\fIoption value ...\\fR?\n\\fBtk_getSaveFile \\fR?\\fIoption value ...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe procedures \\fBtk_getOpenFile\\fR and \\fBtk_getSaveFile\\fR pop up a\ndialog box for the user to select a file to open or save. The\n\\fBtk_getOpenFile\\fR command is usually associated with the \\fBOpen\\fR\ncommand in the \\fBFile\\fR menu. Its purpose is for the user to select an\nexisting file \\fIonly\\fR. If the user enters a non-existent file, the\ndialog box gives the user an error prompt and requires the user to give\nan alternative selection. If an application allows the user to create\nnew files, it should do so by providing a separate \\fBNew\\fR menu command.\n.PP\nThe \\fBtk_getSaveFile\\fR command is usually associated with the \\fBSave\nas\\fR command in the \\fBFile\\fR menu. If the user enters a file that\nalready exists, the dialog box prompts the user for confirmation\nwhether the existing file should be overwritten or not.\n.PP\nThe following \\fIoption\\-value\\fR pairs are possible as command line\narguments to these two commands:\n.\\\" OPTION: -command\n.TP\n\\fB\\-command\\fI string\\fR\n.\nSpecifies the prefix of a Tcl command to invoke when the user closes the\ndialog after having selected an item. This callback is not called if the\nuser cancelled the dialog. The actual command consists of \\fIstring\\fR\nfollowed by a space and the value selected by the user in the dialog. This\nis only available on macOS.\n.\\\" OPTION: -confirmoverwrite\n.TP\n\\fB\\-confirmoverwrite\\fI boolean\\fR\n.\nConfigures how the Save dialog reacts when the selected file already\nexists, and saving would overwrite it.  A true value requests a\nconfirmation dialog be presented to the user.  A false value requests\nthat the overwrite take place without confirmation.  Default value is true.\n.\\\" OPTION: -defaultextension\n.TP\n\\fB\\-defaultextension\\fI extension\\fR\n.\nSpecifies a string that will be appended to the filename if the user\nenters a filename without an extension. The default value is the empty\nstring, which means no extension will be appended to the filename in\nany case. This option is ignored on macOS, which\ndoes not require extensions to filenames,\nand the UNIX implementation guesses reasonable values for this from\nthe \\fB\\-filetypes\\fR option when this is not supplied.\n.\\\" OPTION: -filetypes\n.TP\n\\fB\\-filetypes\\fI filePatternList\\fR\n.\nIf a \\fBFile types\\fR listbox exists in the file dialog on the particular\nplatform, this option gives the \\fIfiletype\\fRs in this listbox. When\nthe user choose a filetype in the listbox, only the files of that type\nare listed. If this option is unspecified, or if it is set to the\nempty list, or if the \\fBFile types\\fR listbox is not supported by the\nparticular platform then all files are listed regardless of their\ntypes. See the section \\fBSPECIFYING FILE PATTERNS\\fR below for a\ndiscussion on the contents of \\fIfilePatternList\\fR.\n.\\\" OPTION: -initialdir\n.TP\n\\fB\\-initialdir\\fI directory\\fR\n.\nSpecifies that the files in \\fIdirectory\\fR should be displayed\nwhen the dialog pops up. If this parameter is not specified,\nthe initial directory defaults to the current working directory\non non-Windows systems and on Windows systems prior to Vista.\nOn Vista and later systems, the initial directory defaults to the last\nuser-selected directory for the application. If the\nparameter specifies a relative path, the return value will convert the\nrelative path to an absolute path.\n.\\\" OPTION: -initialfile\n.TP\n\\fB\\-initialfile\\fI filename\\fR\n.\nSpecifies a filename to be displayed in the dialog when it pops up.\n.\\\" OPTION: -message\n.TP\n\\fB\\-message\\fI string\\fR\n.\nSpecifies a message to include in the client area of the dialog.\nThis is only available on macOS.\n.\\\" OPTION: -multiple\n.TP\n\\fB\\-multiple\\fI boolean\\fR\n.\nAllows the user to choose multiple files from the Open dialog.\n.\\\" OPTION: -parent\n.TP\n\\fB\\-parent\\fI window\\fR\n.\nMakes \\fIwindow\\fR the logical parent of the file dialog. The file\ndialog is displayed on top of its parent window. On macOS, this\nturns the file dialog into a sheet attached to the parent window.\n.\\\" OPTION: -title\n.TP\n\\fB\\-title\\fI titleString\\fR\n.\nSpecifies a string to display as the title of the dialog box. If this\noption is not specified, then a default title is displayed.\n.\\\" OPTION: -typevariable\n.TP\n\\fB\\-typevariable\\fI variableName\\fR\n.\nThe global variable \\fIvariableName\\fR is used to preselect which filter is\nused from \\fIfilterList\\fR when the dialog box is opened and is\nupdated when the dialog box is closed, to the last selected\nfilter. The variable is read once at the beginning to select the\nappropriate filter. If the variable does not exist, or its value does\nnot match any filter typename, or is empty (\\fB{}\\fR), the dialog box\nwill revert to the default behavior of selecting the first filter in\nthe list. If the dialog is canceled, the variable is not modified.\n.PP\nIf the user selects a file, both \\fBtk_getOpenFile\\fR and\n\\fBtk_getSaveFile\\fR return the full pathname of this file. If the\nuser cancels the operation, both commands return the empty string.\n.SH \"SPECIFYING FILE PATTERNS\"\n.PP\nThe \\fIfilePatternList\\fR value given by the \\fB\\-filetypes\\fR option\nis a list of file patterns. Each file pattern is a list of the\nform\n.CS\n\\fItypeName\\fR {\\fIextension\\fR ?\\fIextension ...\\fR?} ?{\\fImacType\\fR ?\\fImacType ...\\fR?}?\n.CE\n\\fItypeName\\fR is the name of the file type described by this\nfile pattern and is the text string that appears in the \\fBFile types\\fR\nlistbox. \\fIextension\\fR is a file extension for this file pattern.\n\\fImacType\\fR is a four-character Macintosh file type. The list of\n\\fImacType\\fRs is optional and may be omitted for applications that do\nnot need to execute on the Macintosh platform.\n.PP\nSeveral file patterns may have the same \\fItypeName,\\fR in which case\nthey refer to the same file type and share the same entry in the\nlistbox. When the user selects an entry in the listbox, all the files\nthat match at least one of the file patterns corresponding\nto that entry are listed. Usually, each file pattern corresponds to a\ndistinct type of file. The use of more than one file pattern for one\ntype of file is only necessary on the Macintosh platform.\n.PP\nOn the Macintosh platform, a file matches a file pattern if its\nname matches at least one of the \\fIextension\\fR(s) AND it\nbelongs to at least one of the \\fImacType\\fR(s) of the\nfile pattern. For example, the \\fBC Source Files\\fR file pattern in the\nsample code matches with files that have a \\fB\\.c\\fR extension AND\nbelong to the \\fImacType\\fR \\fBTEXT\\fR. To use the OR rule instead,\nyou can use two file patterns, one with the \\fIextensions\\fR only and\nthe other with the \\fImacType\\fR only. The \\fBGIF Files\\fR file type\nin the sample code matches files that \\fIeither\\fR have a \\fB\\.gif\\fR\nextension OR belong to the \\fImacType\\fR \\fBGIFF\\fR.\n.PP\nOn the Unix and Windows platforms, a file matches a file pattern\nif its name matches at least one of the \\fIextension\\fR(s) of\nthe file pattern. The \\fImacType\\fRs are ignored.\n.SH \"SPECIFYING EXTENSIONS\"\n.PP\nOn the Unix and Macintosh platforms, extensions are matched using\nglob-style pattern matching. On the Windows platform, extensions are\nmatched by the underlying operating system. The types of possible\nextensions are:\n.IP (1)\nthe special extension\n.QW *\nmatches any file;\n.IP (2)\nthe special extension\n.MT\nmatches any files that do not have an extension (i.e., the filename\ncontains no full stop character);\n.IP (3)\nany character string that does not contain any wild card characters (*\nand ?).\n.PP\nDue to the different pattern matching rules on the various platforms,\nto ensure portability, wild card characters are not allowed in the\nextensions, except as in the special extension\n.QW * .\nExtensions without a full stop character (e.g.\n.QW ~ )\nare allowed but may not work on all platforms.\n.SH EXAMPLE\n.PP\n.CS\nset types {\n    {{Text Files}       {.txt}        }\n    {{TCL Scripts}      {.tcl}        }\n    {{C Source Files}   {.c}      TEXT}\n    {{GIF Files}        {.gif}        }\n    {{GIF Files}        {}        GIFF}\n    {{All Files}        *             }\n}\nset filename [\\fBtk_getOpenFile\\fR -filetypes $types]\n\nif {$filename ne \"\"} {\n    # Open the file ...\n}\n.CE\n.SH \"SEE ALSO\"\ntk_chooseDirectory\n.SH KEYWORDS\nfile selection dialog\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/grab.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH grab n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ngrab \\- Confine pointer and keyboard events to a window sub-tree\n.SH SYNOPSIS\n.nf\n\\fBgrab \\fR?\\fB\\-global\\fR? \\fIwindow\\fR\n\\fBgrab \\fIoption \\fR?\\fIarg \\fR...?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThis command implements simple pointer and keyboard grabs for Tk.\nTk's grabs are different than the grabs\ndescribed in the Xlib documentation.\nWhen a grab is set for a particular window, Tk restricts all pointer\nevents to the grab window and its descendants in Tk's window hierarchy.\nWhenever the pointer is within the grab window's subtree, the pointer\nwill behave exactly the same as if there had been no grab at all\nand all events will be reported in the normal fashion.\nWhen the pointer is outside \\fIwindow\\fR's tree, button presses and\nreleases and\nmouse motion events are reported to \\fIwindow\\fR, and window entry\nand window exit events are ignored. The grab subtree\n.QW owns\nthe pointer:\nwindows outside the grab subtree will be visible on the screen\nbut they will be insensitive until the grab is released.\nThe tree of windows underneath the grab window can include top-level\nwindows, in which case all of those top-level windows\nand their descendants will continue to receive mouse events\nduring the grab.\n.PP\nTwo forms of grabs are possible:  local and global.\nA local grab affects only the grabbing application:  events will\nbe reported to other applications as if the grab had never occurred.\nGrabs are local by default.\nA global grab locks out all applications on the screen,\nso that only the given subtree of the grabbing application will be\nsensitive to pointer events (mouse button presses, mouse button releases,\npointer motions, window entries, and window exits).\nDuring global grabs the window manager will not receive pointer\nevents either.\n.PP\nDuring local grabs, keyboard events (key presses and key releases)\nare delivered as usual:  the window\nmanager controls which application receives keyboard events, and\nif they are sent to any window in the grabbing application then they are\nredirected to the focus window.\nDuring a global grab Tk grabs the keyboard so that all keyboard events\nare always sent to the grabbing application.\nThe \\fBfocus\\fR command is still used to determine which window in the\napplication receives the keyboard events.\nThe keyboard grab is released when the grab is released.\n.PP\nOn macOS a global grab affects all windows created by one Tk process.\nNo window in that process other than the grab window can even be\nfocused, hence no other window receives key or mouse events.  A local\ngrab on macOS affects all windows created by one Tcl interpreter.  It\nis possible to focus any window belonging to the Tk process during a\nlocal grab but the grab window is the only window created by its\ninterpreter which receives key or mouse events.  Windows belonging to the\nsame process but created by different interpreters continue to receive\nkey and mouse events normally.\n.PP\nGrabs apply to particular displays.  If an application has windows\non multiple displays then it can establish a separate grab on each\ndisplay.\nThe grab on a particular display affects only the windows on\nthat display.\nIt is possible for different applications on a single display to have\nsimultaneous local grabs, but only one application can have a global\ngrab on a given display at once.\n.PP\nThe \\fBgrab\\fR command can take any of the following forms:\n.TP\n\\fBgrab \\fR?\\fB\\-global\\fR? \\fIwindow\\fR\n.\nSame as \\fBgrab set\\fR, described below.\n.\\\" METHOD: current\n.TP\n\\fBgrab current \\fR?\\fIwindow\\fR?\n.\nIf \\fIwindow\\fR is specified, returns the name of the current grab\nwindow in this application for \\fIwindow\\fR's display, or an empty\nstring if there is no such window.\nIf \\fIwindow\\fR is omitted, the command returns a list whose elements\nare all of the windows grabbed by this application for all displays,\nor an empty string if the application has no grabs.\n.\\\" METHOD: release\n.TP\n\\fBgrab release \\fIwindow\\fR\n.\nReleases the grab on \\fIwindow\\fR if there is one, otherwise does\nnothing.  Returns an empty string.\n.\\\" METHOD: set\n.TP\n\\fBgrab set \\fR?\\fB\\-global\\fR? \\fIwindow\\fR\n.\nSets a grab on \\fIwindow\\fR.  If \\fB\\-global\\fR is specified then the\ngrab is global, otherwise it is local.\nIf a grab was already in effect for this application on\n\\fIwindow\\fR's display then it is automatically released.\nIf there is already a grab on \\fIwindow\\fR and it has the same\nglobal/local form as the requested grab, then the command\ndoes nothing.  Returns an empty string.\n.\\\" METHOD: status\n.TP\n\\fBgrab status \\fIwindow\\fR\n.\nReturns \\fBnone\\fR if no grab is currently set on \\fIwindow\\fR,\n\\fBlocal\\fR if a local grab is set on \\fIwindow\\fR, and\n\\fBglobal\\fR if a global grab is set.\n.SH WARNING\n.PP\nIt is very easy to use global grabs to render a display completely\nunusable (e.g. by setting a grab on a widget which does not respond to\nevents and not providing any mechanism for releasing the grab).  Take\n\\fIextreme\\fR care when using them!\n.SH BUGS\n.PP\nIt took an incredibly complex and gross implementation to produce\nthe simple grab effect described above.\nGiven the current implementation, it is not safe for applications\nto use the Xlib grab facilities at all except through the Tk grab\nprocedures.\nIf applications try to manipulate X's grab mechanisms directly,\nthings will probably break.\n.PP\nIf a single process is managing several different Tk applications,\nonly one of those applications can have a local grab for a given\ndisplay at any given time.  If the applications are in different\nprocesses, this restriction does not exist.\n.SH EXAMPLE\n.PP\nSet a grab so that only one button may be clicked out of a group.  The\nother buttons are unresponsive to the mouse until the middle button is\nclicked.\n.CS\npack [button .b1 -text \"Click me! #1\" -command {destroy .b1}]\npack [button .b2 -text \"Click me! #2\" -command {destroy .b2}]\npack [button .b3 -text \"Click me! #3\" -command {destroy .b3}]\n\\fBgrab\\fR .b2\n.CE\n.SH \"SEE ALSO\"\nbusy(n)\n.SH KEYWORDS\ngrab, keyboard events, pointer events, window\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/grid.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH grid n 8.5 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ngrid \\- Geometry manager that arranges widgets in a grid\n.SH SYNOPSIS\n\\fBgrid \\fIoption arg \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBgrid\\fR command is used to communicate with the grid\ngeometry manager that arranges widgets in rows and columns inside\nof another window, called the geometry container (or container window).\nThe \\fBgrid\\fR command can have any of several forms, depending\non the \\fIoption\\fR argument:\n.TP\n\\fBgrid \\fIwindow \\fR?\\fIwindow ...\\fR? ?\\fIoptions\\fR?\n.\nIf the first argument to \\fBgrid\\fR is suitable as the first window\nargument to \\fBgrid configure\\fR, either a window name (any value\nstarting with \\fB.\\fR) or one of the characters \\fBx\\fR or \\fB^\\fR\n(see the \\fBRELATIVE PLACEMENT\\fR section below), then the command is\nprocessed in the same way as \\fBgrid configure\\fR.\n.\\\" METHOD: anchor\n.TP\n\\fBgrid anchor \\fIwindow\\fR ?\\fIanchor\\fR?\n.\nThe anchor value controls how to place the grid within the container window\nwhen no row/column has any weight.  See \\fBTHE GRID ALGORITHM\\fR below\nfor further details.  The default \\fIanchor\\fR is \\fInw\\fR.\n.\\\" METHOD: bbox\n.TP\n\\fBgrid bbox \\fIwindow\\fR ?\\fIcolumn row\\fR? ?\\fIcolumn2 row2\\fR?\n.\nWith no arguments,\nthe bounding box (in pixels) of the grid is returned.\nThe return value consists of 4 integers.  The first two are the pixel\noffset from the container window (x then y) of the top-left corner of the\ngrid, and the second two integers are the width and height of the grid,\nalso in pixels.  If a single \\fIcolumn\\fR and \\fIrow\\fR is specified on\nthe command line, then the bounding box for that cell is returned, where the\ntop left cell is numbered from zero.  If both \\fIcolumn\\fR and \\fIrow\\fR\narguments are specified, then the bounding box spanning the rows and columns\nindicated is returned.\n.\\\" METHOD: columnconfigure\n.TP\n\\fBgrid columnconfigure \\fIwindow index \\fR?\\fI\\-option value...\\fR?\n.\nQuery or set the column properties of the \\fIindex\\fR column of the\ngeometry container, \\fIwindow\\fR.\nThe valid options are \\fB\\-minsize\\fR, \\fB\\-weight\\fR, \\fB\\-uniform\\fR\nand \\fB\\-pad\\fR.\nIf one or more options are provided, then \\fIindex\\fR may be given as\na list of column indices to which the configuration options will operate on.\nIndices may be integers, window names or the keyword \\fIall\\fR. For \\fIall\\fR\nthe options apply to all columns currently occupied be content windows. For\na window name, that window must be a content of this container and the options\napply to all columns currently occupied be the content.\nThe \\fB\\-minsize\\fR option sets the minimum size, in screen units,\nthat will be permitted for this column.\nThe \\fB\\-weight\\fR option (an integer value)\nsets the relative weight for apportioning\nany extra spaces among\ncolumns.\nA weight of zero (0) indicates the column will not deviate from its requested\nsize.  A column whose weight is two will grow at twice the rate as a column\nof weight one when extra space is allocated to the layout.\nThe \\fB\\-uniform\\fR option, when a non-empty value is supplied, places\nthe column in a \\fIuniform group\\fR with other columns that have the\nsame value for \\fB\\-uniform\\fR.  The space for columns belonging to a\nuniform group is allocated so that their sizes are always in strict\nproportion to their \\fB\\-weight\\fR values.  See\n\\fBTHE GRID ALGORITHM\\fR below for further details.\nThe \\fB\\-pad\\fR option specifies the number of screen units that will be\nadded to the largest window contained completely in that column when the\ngrid geometry manager requests a size from the containing window.\nIf only an option is specified, with no value,\nthe current value of that option is returned.\nIf only the container window and index is specified, all the current settings\nare returned in a list of\n.QW \"\\fI\\-option value\\fR\"\npairs.\n.\\\" METHOD: configure\n.TP\n\\fBgrid configure \\fIwindow \\fR?\\fIwindow ...\\fR? ?\\fIoptions\\fR?\n.\nThe arguments consist of the names of one or more content windows\nfollowed by pairs of arguments that specify how\nto manage the content.\nThe characters \\fB\\-\\fR,  \\fBx\\fR and \\fB^\\fR,\ncan be specified instead of a window name to alter the default\nlocation of a \\fIwindow\\fR, as described in the \\fBRELATIVE PLACEMENT\\fR\nsection, below.\nThe following options are supported:\n.RS\n.\\\" OPTION: -column\n.TP\n\\fB\\-column \\fIn\\fR\n.\nInsert the window so that it occupies the \\fIn\\fRth column in the grid.\nColumn numbers start with 0.  If this option is not supplied, then the\nwindow is arranged just to the right of previous window specified on this\ncall to \\fBgrid\\fR, or column\n.QW 0\nif it is the first window.  For each\n\\fBx\\fR that immediately precedes the \\fIwindow\\fR, the column position\nis incremented by one.  Thus the \\fBx\\fR represents a blank column\nfor this row in the grid.\n.\\\" OPTION: -columnspan\n.TP\n\\fB\\-columnspan \\fIn\\fR\n.\nInsert the window so that it occupies \\fIn\\fR columns in the grid.\nThe default is one column, unless the window name is followed by a\n\\fB\\-\\fR, in which case the columnspan is incremented once for each immediately\nfollowing \\fB\\-\\fR.\n.\\\" OPTION: -in\n.TP\n\\fB\\-in \\fIcontainer\\fR\n.\nInsert the window(s) in the container\nwindow given by \\fIcontainer\\fR.  The default is the first window's\nparent window.\n.\\\" OPTION: -ipadx\n.TP\n\\fB\\-ipadx \\fIamount\\fR\n.\nThe \\fIamount\\fR specifies how much horizontal internal padding to\nleave on each side of the content.  This is space is added\ninside the content border.\nThe \\fIamount\\fR must be a valid screen distance, such as \\fB2\\fR or \\fB.5c\\fR.\nIt defaults to 0.\n.\\\" OPTION: -ipady\n.TP\n\\fB\\-ipady \\fIamount\\fR\n.\nThe \\fIamount\\fR specifies how much vertical internal padding to\nleave on the top and bottom of the content.\nThis space is added inside the content border.\nThe \\fIamount\\fR  defaults to 0.\n.\\\" OPTION: -padx\n.TP\n\\fB\\-padx \\fIamount\\fR\n.\nThe \\fIamount\\fR specifies how much horizontal external padding to\nleave on each side of the content, in screen units.\n\\fIAmount\\fR may be a list\nof two values to specify padding for left and right separately.\nThe \\fIamount\\fR defaults to 0.\nThis space is added outside the content border.\n.\\\" OPTION: -pady\n.TP\n\\fB\\-pady \\fIamount\\fR\n.\nThe \\fIamount\\fR specifies how much vertical external padding to\nleave on the top and bottom of the content, in screen units.\n\\fIAmount\\fR may be a list\nof two values to specify padding for top and bottom separately.\nThe \\fIamount\\fR defaults to 0.\nThis space is added outside the content border.\n.\\\" OPTION: -row\n.TP\n\\fB\\-row \\fIn\\fR\n.\nInsert the content so that it occupies the \\fIn\\fRth row in the grid.\nRow numbers start with 0.  If this option is not supplied, then the\ncontent is arranged on the same row as the previous content specified on this\ncall to \\fBgrid\\fR, or the next row after the highest occupied row\nif this is the first content.\n.\\\" OPTION: -rowspan\n.TP\n\\fB\\-rowspan \\fIn\\fR\n.\nInsert the content so that it occupies \\fIn\\fR rows in the grid.\nThe default is one row.  If the next \\fBgrid\\fR command contains\n\\fB^\\fR characters instead of \\fIcontent\\fR that line up with the columns\nof this \\fIcontent\\fR, then the \\fBrowspan\\fR of this \\fIcontent\\fR is\nextended by one.\n.\\\" OPTION: -sticky\n.TP\n\\fB\\-sticky \\fIstyle\\fR\n.\nIf a content's cell is larger than its requested dimensions, this\noption may be used to position (or stretch) the content within its cell.\n\\fIStyle\\fR  is a string that contains zero or more of the characters\n\\fBn\\fR, \\fBs\\fR, \\fBe\\fR or \\fBw\\fR.\nThe string can optionally contain spaces or\ncommas, but they are ignored.  Each letter refers to a side (north, south,\neast, or west) that the content will\n.QW stick\nto.  If both \\fBn\\fR and \\fBs\\fR (or \\fBe\\fR and \\fBw\\fR) are\nspecified, the content will be stretched to fill the entire\nheight (or width) of its cavity.  The \\fB\\-sticky\\fR option subsumes the\ncombination of \\fB\\-anchor\\fR and \\fB\\-fill\\fR that is used by \\fBpack\\fR.\nThe default is\n.QW \"\" ,\nwhich causes the content to be centered in its cavity, at its requested size.\n.LP\nIf any of the content is already managed by the geometry manager\nthen any unspecified options for them retain their previous values rather\nthan receiving default values.\n.RE\n.\\\" METHOD: content\n.TP\n\\fBgrid content \\fIwindow\\fR ?\\fI\\-option value\\fR?\n.\nIf no options are supplied, a list of all of the content in \\fIwindow\\fR\nis returned, most recently managed first.\n\\fIOption\\fR can be either \\fB\\-row\\fR or \\fB\\-column\\fR which\ncauses only the content in the row (or column) specified by \\fIvalue\\fR\nto be returned.\n.\\\" METHOD: forget\n.TP\n\\fBgrid forget \\fIwindow \\fR?\\fIwindow ...\\fR?\n.\nRemoves each of the \\fIwindow\\fRs from grid for its\ncontainer and unmaps their windows.\nThe content will no longer be managed by the grid geometry manager.\nThe configuration options for that window are forgotten, so that if the\nwindow is managed once more by the grid geometry manager, the initial\ndefault settings are used.\n.RS\n.PP\n.VS \"TIP 518\"\nIf the last content window of the container becomes unmanaged, this will also\nsend the virtual event \\fB<<NoManagedChild>>\\fR to the container; the container\nmay choose to resize itself (or otherwise respond) to such a change.\n.VE \"TIP 518\"\n.RE\n.\\\" METHOD: info\n.TP\n\\fBgrid info \\fIwindow\\fR\n.\nReturns a list whose elements are the current configuration state of\nthe content given by \\fIwindow\\fR in the same option-value form that\nmight be specified to \\fBgrid configure\\fR.\nThe first two elements of the list are\n.QW \"\\fB\\-in \\fIcontainer\\fR\"\nwhere \\fIcontainer\\fR is the windows's container window.\n.\\\" METHOD: location\n.TP\n\\fBgrid location \\fIwindow x y\\fR\n.\nGiven  \\fIx\\fR and \\fIy\\fR values in screen units relative to the container\nwindow, the column and row number at that \\fIx\\fR and \\fIy\\fR location is\nreturned. For locations that are above or to the left of the grid, \\fB\\-1\\fR\nis returned.\n.\\\" METHOD: propagate\n.TP\n\\fBgrid propagate \\fIwindow\\fR ?\\fIboolean\\fR?\n.\nIf \\fIboolean\\fR has a true boolean value such as \\fB1\\fR or \\fBon\\fR\nthen propagation is enabled for \\fIwindow\\fR, which must be a window\nname (see \\fBGEOMETRY PROPAGATION\\fR below).\nIf \\fIboolean\\fR has a false boolean value then propagation is\ndisabled for \\fIwindow\\fR.\nIn either of these cases an empty string is returned.\nIf \\fIboolean\\fR is omitted then the command returns \\fB0\\fR or\n\\fB1\\fR to indicate whether propagation is currently enabled\nfor \\fIwindow\\fR.\n.RS\n.PP\nPropagation is enabled by default.\n.RE\n.\\\" METHOD: rowconfigure\n.TP\n\\fBgrid rowconfigure \\fIwindow index \\fR?\\fI\\-option value...\\fR?\n.\nQuery or set the row properties of the \\fIindex\\fR row of the\ngeometry container, \\fIwindow\\fR.\nThe valid options are \\fB\\-minsize\\fR, \\fB\\-weight\\fR, \\fB\\-uniform\\fR\nand \\fB\\-pad\\fR.\nIf one or more options are provided, then \\fIindex\\fR may be given as\na list of row indices to which the configuration options will operate on.\nIndices may be integers, window names or the keyword \\fIall\\fR. For \\fIall\\fR\nthe options apply to all rows currently occupied by content windows. For a\nwindow name, that window must be a content window of this container and the\noptions apply to all rows currently occupied by the container window.\nThe \\fB\\-minsize\\fR option sets the minimum size, in screen units,\nthat will be permitted for this row.\nThe \\fB\\-weight\\fR option (an integer value)\nsets the relative weight for apportioning\nany extra spaces among\nrows.\nA weight of zero (0) indicates the row will not deviate from its requested\nsize.  A row whose weight is two will grow at twice the rate as a row\nof weight one when extra space is allocated to the layout.\nThe \\fB\\-uniform\\fR option, when a non-empty value is supplied, places\nthe row in a \\fIuniform group\\fR with other rows that have the\nsame value for \\fB\\-uniform\\fR.  The space for rows belonging to a\nuniform group is allocated so that their sizes are always in strict\nproportion to their \\fB\\-weight\\fR values.  See\n\\fBTHE GRID ALGORITHM\\fR below for further details.\nThe \\fB\\-pad\\fR option specifies the number of screen units that will be\nadded to the largest window contained completely in that row when the\ngrid geometry manager requests a size from the containing window.\nIf only an option is specified, with no value,\nthe current value of that option is returned.\nIf only the container window and index is specified, all the current settings\nare returned in a list of\n.QW \"-option value\"\npairs.\n.\\\" METHOD: remove\n.TP\n\\fBgrid remove \\fIwindow \\fR?\\fIwindow ...\\fR?\n.\nRemoves each of the \\fIwindow\\fRs from grid for its\ncontainer and unmaps their windows.\nThe content will no longer be managed by the grid geometry manager.\nHowever, the configuration options for that window are remembered,\nso that if the content window is managed once more by the grid\ngeometry manager, the previous values are retained.\n.RS\n.PP\n.VS \"TIP 518\"\nIf the last content window of the container becomes unmanaged, this will also\nsend the virtual event \\fB<<NoManagedChild>>\\fR to the container; the\ncontainer may choose to resize itself (or otherwise respond) to such a change.\n.VE \"TIP 518\"\n.RE\n.\\\" METHOD: size\n.TP\n\\fBgrid size \\fIcontainer\\fR\n.\nReturns the size of the grid (in columns then rows) for \\fIcontainer\\fR.\nThe size is determined either by the \\fIcontent\\fR occupying the largest\nrow or column, or the largest column or row with a \\fB\\-minsize\\fR,\n\\fB\\-weight\\fR, or \\fB\\-pad\\fR that is non-zero.\n.\\\" METHOD: slaves\n.TP\n\\fBgrid slaves \\fIwindow\\fR ?\\fI\\-option value\\fR?\n.\nSynonym for \\fBgrid content \\fIwindow\\fR ?\\fI\\-option value\\fR?.\n.SH \"RELATIVE PLACEMENT\"\n.PP\nThe \\fBgrid\\fR command contains a limited set of capabilities that\npermit layouts to be created without specifying the row and column\ninformation for each content.  This permits content to be rearranged,\nadded, or removed without the need to explicitly specify row and\ncolumn information.\nWhen no column or row information is specified for a \\fIcontent\\fR,\ndefault values are chosen for\n\\fB\\-column\\fR, \\fB\\-row\\fR, \\fB\\-columnspan\\fR and \\fB\\-rowspan\\fR\nat the time the \\fIcontent\\fR is managed. The values are chosen\nbased upon the current layout of the grid, the position of the \\fIcontent\\fR\nrelative to other \\fIcontent\\fRs in the same grid command, and the presence\nof the characters \\fB\\-\\fR, \\fBx\\fR, and \\fB^\\fR in \\fBgrid\\fR\ncommand where \\fIcontent\\fR names are normally expected.\n.RS\n.IP \\fB\\-\\fR\nThis increases the \\fB\\-columnspan\\fR of the \\fIcontent\\fR to the left.  Several\n\\fB\\-\\fR's in a row will successively increase the number of columns spanned.\nA \\fB\\-\\fR may not follow a \\fB^\\fR or a \\fBx\\fR, nor may it be the first\n\\fIcontent\\fR argument to \\fBgrid configure\\fR.\n.IP \\fBx\\fR\nThis leaves an empty column between the \\fIcontent\\fR on the left and\nthe \\fIcontent\\fR on the right.\n.IP \\fB^\\fR\nThis extends the \\fB\\-rowspan\\fR of the \\fIcontent\\fR above the \\fB^\\fR's\nin the grid.  The number of \\fB^\\fR's in a row must match the number of\ncolumns spanned by the \\fIcontent\\fR above it.\n.RE\n.SH \"THE GRID ALGORITHM\"\n.PP\nThe grid geometry manager lays out its content in three steps.\nIn the first step, the minimum size needed to fit all of the content\nis computed, then (if propagation is turned on), a request is made\nof the container window to become that size.\nIn the second step, the requested size is compared against the actual size\nof the container.  If the sizes are different, then spaces is added to or taken\naway from the layout as needed.\nFor the final step, each content is positioned in its row(s) and column(s)\nbased on the setting of its \\fIsticky\\fR flag.\n.PP\nTo compute the minimum size of a layout, the grid geometry manager first looks\nat all content whose \\fB\\-columnspan\\fR and \\fB\\-rowspan\\fR values are one,\nand computes the nominal size of each row or column to be either the\n\\fIminsize\\fR for that row or column, or the sum of the \\fIpad\\fRding\nplus the size of the largest content, whichever is greater.  After that\nthe rows or columns in each uniform group adapt to each other.  Then\nthe content whose row-spans or column-spans are greater than one are\nexamined.  If a group of rows or columns need to be increased in size\nin order to accommodate these content, then extra space is added to each\nrow or column in the group according to its \\fIweight\\fR.  For each\ngroup whose weights are all zero, the additional space is apportioned\nequally.\n.PP\nWhen multiple rows or columns belong to a uniform group, the space\nallocated to them is always in proportion to their weights. (A weight\nof zero is considered to be 1.)  In other words, a row or column\nconfigured with \\fB\\-weight 1 \\-uniform a\\fR will have exactly the same\nsize as any other row or column configured with \\fB\\-weight 1 \\-uniform\na\\fR.  A row or column configured with \\fB\\-weight 2 \\-uniform b\\fR will\nbe exactly twice as large as one that is configured with \\fB\\-weight 1\n\\-uniform b\\fR.\n.PP\nMore technically, each row or column in the group will have a size\nequal to \\fIk*weight\\fR for some constant \\fIk\\fR.  The constant\n\\fIk\\fR is chosen so that no row or column becomes smaller than its\nminimum size.  For example, if all rows or columns in a group have the\nsame weight, then each row or column will have the same size as the\nlargest row or column in the group.\n.PP\nFor containers whose size is larger than the requested layout, the additional\nspace is apportioned according to the row and column weights.  If all of\nthe weights are zero, the layout is placed within its container according to\nthe \\fIanchor\\fR value.\nFor containers whose size is smaller than the requested layout, space is taken\naway from columns and rows according to their weights.  However, once a\ncolumn or row shrinks to its minsize, its weight is taken to be zero.\nIf more space needs to be removed from a layout than would be permitted, as\nwhen all the rows or columns are at their minimum sizes, the layout is\nplaced and clipped according to the \\fIanchor\\fR value.\n.SH \"GEOMETRY PROPAGATION\"\n.PP\nThe grid geometry manager normally computes how large a container must be to\njust exactly meet the needs of its content, and it sets the\nrequested width and height of the container to these dimensions.\nThis causes geometry information to propagate up through a\nwindow hierarchy to a top-level window so that the entire\nsub-tree sizes itself to fit the needs of the leaf windows.\nHowever, the \\fBgrid propagate\\fR command may be used to\nturn off propagation for one or more containers.\nIf propagation is disabled then grid will not set\nthe requested width and height of the container window.\nThis may be useful if, for example, you wish for a container\nwindow to have a fixed size that you specify.\n.SH \"RESTRICTIONS ON CONTAINER WINDOWS\"\n.PP\nThe container for each content must either be the content's parent\n(the default) or a descendant of the content's parent.\nThis restriction is necessary to guarantee that the\ncontent can be placed over any part of its container that is\nvisible without danger of the content being clipped by its parent.\nIn addition, all content in one call to \\fBgrid\\fR must have the same container.\n.SH \"STACKING ORDER\"\n.PP\nIf the container for a content is not its parent then you must make sure\nthat the content is higher in the stacking order than the container.\nOtherwise the container will obscure the content and it will appear as\nif the content has not been managed correctly.\nThe easiest way to make sure the content is higher than the container is\nto create the container window first:  the most recently created window\nwill be highest in the stacking order.\n.SH CREDITS\n.PP\nThe \\fBgrid\\fR command is based on ideas taken from the \\fIGridBag\\fR\ngeometry manager written by Doug. Stein, and the \\fBblt_table\\fR geometry\nmanager, written by George Howlett.\n.SH EXAMPLES\n.PP\nA toplevel window containing a text widget and two scrollbars:\n.PP\n.CS\n# Make the widgets\ntoplevel .t\ntext .t.txt -wrap none -xscroll {.t.h set} -yscroll {.t.v set}\nscrollbar .t.v -orient vertical   -command {.t.txt yview}\nscrollbar .t.h -orient horizontal -command {.t.txt xview}\n\n# Lay them out\n\\fBgrid\\fR .t.txt .t.v -sticky nsew\n\\fBgrid\\fR .t.h        -sticky nsew\n\n# Tell the text widget to take all the extra room\n\\fBgrid rowconfigure\\fR    .t .t.txt -weight 1\n\\fBgrid columnconfigure\\fR .t .t.txt -weight 1\n.CE\n.PP\nThree widgets of equal width, despite their different\n.QW natural\nwidths:\n.PP\n.CS\nbutton .b -text \"Foo\"\nentry .e -textvariable foo ; set foo \"Hello World!\"\nlabel .l -text \"This is a fairly long piece of text\"\n\n\\fBgrid\\fR .b .e .l -sticky ew\n\\fBgrid columnconfigure\\fR . \"all\" -uniform allTheSame\n.CE\n.SH \"SEE ALSO\"\npack(n), place(n)\n.SH KEYWORDS\ngeometry manager, location, grid, cell, propagation, size, pack\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/image.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH image n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nimage \\- Create and manipulate images\n.SH SYNOPSIS\n\\fBimage\\fI option \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBimage\\fR command is used to create, delete, and query images.\nIt can take several different forms, depending on the\n\\fIoption\\fR argument.  The legal forms are:\n.\\\" METHOD: create\n.TP\n\\fBimage create \\fItype \\fR?\\fIname\\fR? ?\\fIoption value ...\\fR?\n.\nCreates a new image and a command with the same name and returns its name.\n\\fItype\\fR specifies the type of the image, which must be one of\nthe types currently defined (e.g., \\fBbitmap\\fR).\n\\fIname\\fR specifies the name for the image;  if it is omitted then\nTk picks a name of the form \\fBimage\\fIx\\fR, where \\fIx\\fR is\nan integer.\nThere may be any number of \\fIoption\\fR\\-\\fIvalue\\fR pairs,\nwhich provide configuration options for the new image.\nThe legal set of options is defined separately for each image\ntype;  see below for details on the options for built-in image types.\nIf an image already exists by the given name then it is replaced\nwith the new image and any instances of that image will redisplay\nwith the new contents.\nIt is important to note that the image command will silently overwrite any\nprocedure that may currently be defined by the given name, so choose the\nname wisely.  It is recommended to use a separate namespace for image names\n(e.g., \\fB::img::logo\\fR, \\fB::img::large\\fR).\n.\\\" METHOD: delete\n.TP\n\\fBimage delete \\fR?\\fIname name\\fR ...?\n.\nDeletes each of the named images and returns an empty string.\nIf there are instances of the images displayed in widgets,\nthe images will not actually be deleted until all of the instances\nare released.\nHowever, the association between the instances and the image\nmanager will be dropped.\nExisting instances will retain their sizes but redisplay as\nempty areas.\nIf a deleted image is recreated with another call to \\fBimage create\\fR,\nthe existing instances will use the new image.\n.\\\" METHOD: height\n.TP\n\\fBimage height \\fIname\\fR\n.\nReturns a decimal string giving the height of image \\fIname\\fR\nin pixels.\n.\\\" METHOD: inuse\n.TP\n\\fBimage inuse \\fIname\\fR\n.\nReturns a boolean value indicating whether or not the image given by\n\\fIname\\fR is in use by any widgets.\n.\\\" METHOD: names\n.TP\n\\fBimage names\\fR\n.\nReturns a list containing the names of all existing images.\n.\\\" METHOD: type\n.TP\n\\fBimage type \\fIname\\fR\n.\nReturns the type of image \\fIname\\fR (the value of the \\fItype\\fR\nargument to \\fBimage create\\fR when the image was created).\n.\\\" METHOD: types\n.TP\n\\fBimage types\\fR\n.\nReturns a list whose elements are all of the valid image types\n(i.e., all of the values that may be supplied for the \\fItype\\fR\nargument to \\fBimage create\\fR).\n.\\\" METHOD: width\n.TP\n\\fBimage width \\fIname\\fR\n.\nReturns a decimal string giving the width of image \\fIname\\fR\nin pixels.\n.PP\nAdditional operations (e.g. writing the image to a file) may be\navailable as subcommands of the image instance command. See the manual\npage for the particular image type for details.\n.SH \"BUILT-IN IMAGE TYPES\"\n.PP\nThe following image types are defined by Tk so they will be available\nin any Tk application.\nIndividual applications or extensions may define additional types.\n.IP \\fBbitmap\\fR\nEach pixel in the image displays a foreground color, a background\ncolor, or nothing.\nSee the \\fBbitmap\\fR manual entry for more information.\n.IP \\fBphoto\\fR\nDisplays a variety of full-color images, using dithering to\napproximate colors on displays with limited color capabilities.\nSee the \\fBphoto\\fR manual entry for more information.\n.IP \\fBnsimage\\fR\nThis type is only available in the Aqua platform.  It is a full-color\nimage which may be created from a named system image.  It has options\ndesigned to facilitate the use of these images in buttons.  An\n\\fBnsimage\\fR can be based on an a \\fItemplate image\\fR, which is an\nanti-aliased 2-color image format that automatically interchanges\nblack and white in response to changes between the light and dark\nmodes on macOS.  An \\fBnsimage\\fR can also generate an alternate\n\\fIpressed\\fR variant which is lighter in dark mode and darker in\nlight mode.  These are for use in image buttons. See the \\fBnsimage\\fR\nmanual entry for more information.\n.SH \"SEE ALSO\"\nbitmap(n), options(n), photo(n), nsimage(n)\n.SH KEYWORDS\nheight, image, types of images, width\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/keysyms.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" All rights reserved.\n'\\\"\n.TH keysyms n 8.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nkeysyms \\- keysyms recognized by Tk\n.BE\n.SH DESCRIPTION\n.PP\nTk recognizes many keysyms when specifying key bindings (e.g.,\n.QW \"\\fBbind\\fR \\fB. <\\fR\\fIkeysym\\fR\\fB>\\fR\" ).\nThe following list enumerates the\nkeysyms that will be recognized by Tk.  Note that not all keysyms will\nbe valid on all platforms, and some keysyms are also available on\nplatforms that have a different native name for that key.\nFor example, on Unix systems, the presence\nof a particular keysym is dependent on the configuration of the\nkeyboard modifier map.  This list shows keysyms along with their\ndecimal and hexadecimal values.\n.PP\n.CS\nspace                               32     0x20\n! (exclam)                          33     0x21\nquotedbl                            34     0x22\nnumbersign                          35     0x23\ndollar                              36     0x24\n% (percent)                         37     0x25\n& (ampersand)                       38     0x26\n' (apostrophe)                      39     0x27\n( (parenleft)                       40     0x28\n) (parenright)                      41     0x29\n* (asterisk)                        42     0x2A\n+ (plus)                            43     0x2B\n, (comma)                           44     0x2C\nminus                               45     0x2D\n. (period)                          46     0x2E\n/ (slash)                           47     0x2F\n0                                   48     0x30\n1                                   49     0x31\n2                                   50     0x32\n3                                   51     0x33\n4                                   52     0x34\n5                                   53     0x35\n6                                   54     0x36\n7                                   55     0x37\n8                                   56     0x38\n9                                   57     0x39\n: (colon)                           58     0x3A\nsemicolon                           59     0x3B\nless                                60     0x3C\n= (equal)                           61     0x3D\ngreater                             62     0x3E\n? (question)                        63     0x3F\n@ (at)                              64     0x40\nA                                   65     0x41\nB                                   66     0x42\nC                                   67     0x43\nD                                   68     0x44\nE                                   69     0x45\nF                                   70     0x46\nG                                   71     0x47\nH                                   72     0x48\nI                                   73     0x49\nJ                                   74     0x4A\nK                                   75     0x4B\nL                                   76     0x4C\nM                                   77     0x4D\nN                                   78     0x4E\nO                                   79     0x4F\nP                                   80     0x50\nQ                                   81     0x51\nR                                   82     0x52\nS                                   83     0x53\nT                                   84     0x54\nU                                   85     0x55\nV                                   86     0x56\nW                                   87     0x57\nX                                   88     0x58\nY                                   89     0x59\nZ                                   90     0x5A\nbracketleft                         91     0x5B\nbackslash                           92     0x5C\nbracketright                        93     0x5D\n^ (asciicircum)                     94     0x5E\n_ (underscore)                      95     0x5F\n` (grave)                           96     0x60\na                                   97     0x61\nb                                   98     0x62\nc                                   99     0x63\nd                                  100     0x64\ne                                  101     0x65\nf                                  102     0x66\ng                                  103     0x67\nh                                  104     0x68\ni                                  105     0x69\nj                                  106     0x6A\nk                                  107     0x6B\nl                                  108     0x6C\nm                                  109     0x6D\nn                                  110     0x6E\no                                  111     0x6F\np                                  112     0x70\nq                                  113     0x71\nr                                  114     0x72\ns                                  115     0x73\nt                                  116     0x74\nu                                  117     0x75\nv                                  118     0x76\nw                                  119     0x77\nx                                  120     0x78\ny                                  121     0x79\nz                                  122     0x7A\nbraceleft                          123     0x7B\n| (bar)                            124     0x7C\nbraceright                         125     0x7D\n~ (asciitilde)                     126     0x7E\nnobreakspace                       160     0xA0\n\\(r! (exclamdown)                     161     0xA1\n\\(ct (cent)                           162     0xA2\n\\(Po (sterling)                       163     0xA3\n\\(Cs (currency)                       164     0xA4\n\\(Ye (yen)                            165     0xA5\n\\(bb (brokenbar)                      166     0xA6\n\\(sc (section)                        167     0xA7\n\\(ad (diaeresis)                      168     0xA8\n\\(co (copyright)                      169     0xA9\n\\(Of (ordfeminine)                    170     0xAA\n\\(Fo (guillemetleft)                  171     0xAB\n\\(no (notsign)                        172     0xAC\nhyphen                             173     0xAD\n\\(rg (registered)                     174     0xAE\n\\(a- (macron)                         175     0xAF\n\\(de (degree)                         176     0xB0\n\\(+- (plusminus)                      177     0xB1\n\\(S2 (twosuperior)                    178     0xB2\n\\(S3 (threesuperior)                  179     0xB3\n\\(aa (acute)                          180     0xB4\n\\(mc (mu)                             181     0xB5\n\\(ps (paragraph)                      182     0xB6\n\\(pc (periodcentered)                 183     0xB7\n\\(ac (cedilla)                        184     0xB8\n\\(S1 (onesuperior)                    185     0xB9\n\\(Om (ordmasculine)                   186     0xBA\n\\(Fc (guillemetright)                 187     0xBB\n\\(14 (onequarter)                     188     0xBC\n\\(12 (onehalf)                        189     0xBD\n\\(34 (threequarters)                  190     0xBE\n\\(r? (questiondown)                   191     0xBF\n\\(`A (Agrave)                         192     0xC0\n\\('A (Aacute)                         193     0xC1\n\\(^A (Acircumflex)                    194     0xC2\n\\(~A (Atilde)                         195     0xC3\n\\(:A (Adiaeresis)                     196     0xC4\n\\(oA (Aring)                          197     0xC5\n\\(AE (AE)                             198     0xC6\n\\(,C (Ccedilla)                       199     0xC7\n\\(`E (Egrave)                         200     0xC8\n\\('E (Eacute)                         201     0xC9\n\\(^E (Ecircumflex)                    202     0xCA\n\\(:E (Ediaeresis)                     203     0xCB\n\\(`I (Igrave)                         204     0xCC\n\\('I (Iacute)                         205     0xCD\n\\(^I (Icircumflex)                    206     0xCE\n\\(:I (Idiaeresis)                     207     0xCF\n\\(-D (ETH)                            208     0xD0\n\\(~N (Ntilde)                         209     0xD1\n\\(`O (Ograve)                         210     0xD2\n\\('O (Oacute)                         211     0xD3\n\\(^O (Ocircumflex)                    212     0xD4\n\\(~O (Otilde)                         213     0xD5\n\\(:O (Odiaeresis)                     214     0xD6\n\\(mu (multiply)                       215     0xD7\n\\(/O (Oslash)                         216     0xD8\n\\(`U (Ugrave)                         217     0xD9\n\\('U (Uacute)                         218     0xDA\n\\(^U (Ucircumflex)                    219     0xDB\n\\(:U (Udiaeresis)                     220     0xDC\n\\('Y (Yacute)                         221     0xDD\n\\(TP (THORN)                          222     0xDE\n\\(ss (ssharp)                         223     0xDF\n\\(`a (agrave)                         224     0xE0\n\\('a (aacute)                         225     0xE1\n\\(^a (acircumflex)                    226     0xE2\n\\(~a (atilde)                         227     0xE3\n\\(:a (adiaeresis)                     228     0xE4\n\\(oa (aring)                          229     0xE5\n\\(ae (ae)                             230     0xE6\n\\(,c (ccedilla)                       231     0xE7\n\\(`e (egrave)                         232     0xE8\n\\('e (eacute)                         233     0xE9\n\\(^e (ecircumflex)                    234     0xEA\n\\(:e (ediaeresis)                     235     0xEB\n\\(`i (igrave)                         236     0xEC\n\\('i (iacute)                         237     0xED\n\\(^i (icircumflex)                    238     0xEE\n\\(:i (idiaeresis)                     239     0xEF\n\\(Sd (eth)                            240     0xF0\n\\(~n (ntilde)                         241     0xF1\n\\(`o (ograve)                         242     0xF2\n\\('o (oacute)                         243     0xF3\n\\(^o (ocircumflex)                    244     0xF4\n\\(~o (otilde)                         245     0xF5\n\\(:o (odiaeresis)                     246     0xF6\n\\(di (division)                       247     0xF7\n\\(/o (oslash)                         248     0xF8\n\\(`u (ugrave)                         249     0xF9\n\\('u (uacute)                         250     0xFA\n\\(^u (ucircumflex)                    251     0xFB\n\\(:u (udiaeresis)                     252     0xFC\n\\('y (yacute)                         253     0xFD\n\\(Tp (thorn)                          254     0xFE\n\\(:y (ydiaeresis)                     255     0xFF\n.CE\n.CS\nAogonek                            417     0x1A1\nbreve                              418     0x1A2\nLstroke                            419     0x1A3\nLcaron                             421     0x1A5\nSacute                             422     0x1A6\nScaron                             425     0x1A9\nScedilla                           426     0x1AA\nTcaron                             427     0x1AB\nZacute                             428     0x1AC\nZcaron                             430     0x1AE\nZabovedot                          431     0x1AF\naogonek                            433     0x1B1\nogonek                             434     0x1B2\nlstroke                            435     0x1B3\nlcaron                             437     0x1B5\nsacute                             438     0x1B6\ncaron                              439     0x1B7\nscaron                             441     0x1B9\nscedilla                           442     0x1BA\ntcaron                             443     0x1BB\nzacute                             444     0x1BC\ndoubleacute                        445     0x1BD\nzcaron                             446     0x1BE\nzabovedot                          447     0x1BF\nRacute                             448     0x1C0\nAbreve                             451     0x1C3\nLacute                             453     0x1C5\nCacute                             454     0x1C6\nCcaron                             456     0x1C8\nEogonek                            458     0x1CA\nEcaron                             460     0x1CC\nDcaron                             463     0x1CF\nDstroke                            464     0x1D0\nNacute                             465     0x1D1\nNcaron                             466     0x1D2\nOdoubleacute                       469     0x1D5\nRcaron                             472     0x1D8\nUring                              473     0x1D9\nUdoubleacute                       475     0x1DB\nTcedilla                           478     0x1DE\nracute                             480     0x1E0\nabreve                             483     0x1E3\nlacute                             485     0x1E5\ncacute                             486     0x1E6\nccaron                             488     0x1E8\neogonek                            490     0x1EA\necaron                             492     0x1EC\ndcaron                             495     0x1EF\ndstroke                            496     0x1F0\nnacute                             497     0x1F1\nncaron                             498     0x1F2\nodoubleacute                       501     0x1F5\nrcaron                             504     0x1F8\nuring                              505     0x1F9\nudoubleacute                       507     0x1FB\ntcedilla                           510     0x1FE\nabovedot                           511     0x1FF\nHstroke                            673     0x2A1\nHcircumflex                        678     0x2A6\nIabovedot                          681     0x2A9\nGbreve                             683     0x2AB\nJcircumflex                        684     0x2AC\nhstroke                            689     0x2B1\nhcircumflex                        694     0x2B6\nidotless                           697     0x2B9\ngbreve                             699     0x2BB\njcircumflex                        700     0x2BC\nCabovedot                          709     0x2C5\nCcircumflex                        710     0x2C6\nGabovedot                          725     0x2D5\nGcircumflex                        728     0x2D8\nUbreve                             733     0x2DD\nScircumflex                        734     0x2DE\ncabovedot                          741     0x2E5\nccircumflex                        742     0x2E6\ngabovedot                          757     0x2F5\ngcircumflex                        760     0x2F8\nubreve                             765     0x2FD\nscircumflex                        766     0x2FE\nkra                                930     0x3A2\nRcedilla                           931     0x3A3\nItilde                             933     0x3A5\nLcedilla                           934     0x3A6\nEmacron                            938     0x3AA\nGcedilla                           939     0x3AB\nTslash                             940     0x3AC\nrcedilla                           947     0x3B3\nitilde                             949     0x3B5\nlcedilla                           950     0x3B6\nemacron                            954     0x3BA\ngcedilla                           955     0x3BB\ntslash                             956     0x3BC\nENG                                957     0x3BD\neng                                959     0x3BF\nAmacron                            960     0x3C0\nIogonek                            967     0x3C7\nEabovedot                          972     0x3CC\nImacron                            975     0x3CF\nNcedilla                           977     0x3D1\nOmacron                            978     0x3D2\nKcedilla                           979     0x3D3\nUogonek                            985     0x3D9\nUtilde                             989     0x3DD\nUmacron                            990     0x3DE\namacron                            992     0x3E0\niogonek                            999     0x3E7\neabovedot                         1004     0x3EC\nimacron                           1007     0x3EF\nncedilla                          1009     0x3F1\nomacron                           1010     0x3F2\nkcedilla                          1011     0x3F3\nuogonek                           1017     0x3F9\nutilde                            1021     0x3FD\numacron                           1022     0x3FE\noverline                          1150     0x47E\nkana_fullstop                     1185     0x4A1\nkana_openingbracket               1186     0x4A2\nkana_closingbracket               1187     0x4A3\nkana_comma                        1188     0x4A4\nkana_conjunctive                  1189     0x4A5\nkana_WO                           1190     0x4A6\nkana_a                            1191     0x4A7\nkana_i                            1192     0x4A8\nkana_u                            1193     0x4A9\nkana_e                            1194     0x4AA\nkana_o                            1195     0x4AB\nkana_ya                           1196     0x4AC\nkana_yu                           1197     0x4AD\nkana_yo                           1198     0x4AE\nkana_tsu                          1199     0x4AF\nprolongedsound                    1200     0x4B0\nkana_A                            1201     0x4B1\nkana_I                            1202     0x4B2\nkana_U                            1203     0x4B3\nkana_E                            1204     0x4B4\nkana_O                            1205     0x4B5\nkana_KA                           1206     0x4B6\nkana_KI                           1207     0x4B7\nkana_KU                           1208     0x4B8\nkana_KE                           1209     0x4B9\nkana_KO                           1210     0x4BA\nkana_SA                           1211     0x4BB\nkana_SHI                          1212     0x4BC\nkana_SU                           1213     0x4BD\nkana_SE                           1214     0x4BE\nkana_SO                           1215     0x4BF\nkana_TA                           1216     0x4C0\nkana_CHI                          1217     0x4C1\nkana_TSU                          1218     0x4C2\nkana_TE                           1219     0x4C3\nkana_TO                           1220     0x4C4\nkana_NA                           1221     0x4C5\nkana_NI                           1222     0x4C6\nkana_NU                           1223     0x4C7\nkana_NE                           1224     0x4C8\nkana_NO                           1225     0x4C9\nkana_HA                           1226     0x4CA\nkana_HI                           1227     0x4CB\nkana_FU                           1228     0x4CC\nkana_HE                           1229     0x4CD\nkana_HO                           1230     0x4CE\nkana_MA                           1231     0x4CF\nkana_MI                           1232     0x4D0\nkana_MU                           1233     0x4D1\nkana_ME                           1234     0x4D2\nkana_MO                           1235     0x4D3\nkana_YA                           1236     0x4D4\nkana_YU                           1237     0x4D5\nkana_YO                           1238     0x4D6\nkana_RA                           1239     0x4D7\nkana_RI                           1240     0x4D8\nkana_RU                           1241     0x4D9\nkana_RE                           1242     0x4DA\nkana_RO                           1243     0x4DB\nkana_WA                           1244     0x4DC\nkana_N                            1245     0x4DD\nvoicedsound                       1246     0x4DE\nsemivoicedsound                   1247     0x4DF\n.CE\n.CS\nArabic_comma                      1452     0x5AC\nArabic_semicolon                  1467     0x5BB\nArabic_question_mark              1471     0x5BF\nArabic_hamza                      1473     0x5C1\nArabic_maddaonalef                1474     0x5C2\nArabic_hamzaonalef                1475     0x5C3\nArabic_hamzaonwaw                 1476     0x5C4\nArabic_hamzaunderalef             1477     0x5C5\nArabic_hamzaonyeh                 1478     0x5C6\nArabic_alef                       1479     0x5C7\nArabic_beh                        1480     0x5C8\nArabic_tehmarbuta                 1481     0x5C9\nArabic_teh                        1482     0x5CA\nArabic_theh                       1483     0x5CB\nArabic_jeem                       1484     0x5CC\nArabic_hah                        1485     0x5CD\nArabic_khah                       1486     0x5CE\nArabic_dal                        1487     0x5CF\nArabic_thal                       1488     0x5D0\nArabic_ra                         1489     0x5D1\nArabic_zain                       1490     0x5D2\nArabic_seen                       1491     0x5D3\nArabic_sheen                      1492     0x5D4\nArabic_sad                        1493     0x5D5\nArabic_dad                        1494     0x5D6\nArabic_tah                        1495     0x5D7\nArabic_zah                        1496     0x5D8\nArabic_ain                        1497     0x5D9\nArabic_ghain                      1498     0x5DA\nArabic_tatweel                    1504     0x5E0\nArabic_feh                        1505     0x5E1\nArabic_qaf                        1506     0x5E2\nArabic_kaf                        1507     0x5E3\nArabic_lam                        1508     0x5E4\nArabic_meem                       1509     0x5E5\nArabic_noon                       1510     0x5E6\nArabic_ha                         1511     0x5E7\nArabic_waw                        1512     0x5E8\nArabic_alefmaksura                1513     0x5E9\nArabic_yeh                        1514     0x5EA\nArabic_fathatan                   1515     0x5EB\nArabic_dammatan                   1516     0x5EC\nArabic_kasratan                   1517     0x5ED\nArabic_fatha                      1518     0x5EE\nArabic_damma                      1519     0x5EF\nArabic_kasra                      1520     0x5F0\nArabic_shadda                     1521     0x5F1\nArabic_sukun                      1522     0x5F2\nSerbian_dje                       1697     0x6A1\nMacedonia_gje                     1698     0x6A2\nCyrillic_io                       1699     0x6A3\nUkrainian_ie                      1700     0x6A4\nMacedonia_dse                     1701     0x6A5\nUkrainian_i                       1702     0x6A6\nUkrainian_yi                      1703     0x6A7\nCyrillic_je                       1704     0x6A8\nCyrillic_lje                      1705     0x6A9\nCyrillic_nje                      1706     0x6AA\nSerbian_tshe                      1707     0x6AB\nMacedonia_kje                     1708     0x6AC\nUkrainian_ghe_with_upturn         1709     0x6AD\nByelorussian_shortu               1710     0x6AE\nCyrillic_dzhe                     1711     0x6AF\nnumerosign                        1712     0x6B0\nSerbian_DJE                       1713     0x6B1\nMacedonia_GJE                     1714     0x6B2\nCyrillic_IO                       1715     0x6B3\nUkrainian_IE                      1716     0x6B4\nMacedonia_DSE                     1717     0x6B5\nUkrainian_I                       1718     0x6B6\nUkrainian_YI                      1719     0x6B7\nCyrillic_JE                       1720     0x6B8\nCyrillic_LJE                      1721     0x6B9\nCyrillic_NJE                      1722     0x6BA\nSerbian_TSHE                      1723     0x6BB\nMacedonia_KJE                     1724     0x6BC\nUkrainian_GHE_WITH_UPTURN         1725     0x6BD\nByelorussian_SHORTU               1726     0x6BE\nCyrillic_DZHE                     1727     0x6BF\nCyrillic_yu                       1728     0x6C0\nCyrillic_a                        1729     0x6C1\nCyrillic_be                       1730     0x6C2\nCyrillic_tse                      1731     0x6C3\nCyrillic_de                       1732     0x6C4\nCyrillic_ie                       1733     0x6C5\nCyrillic_ef                       1734     0x6C6\nCyrillic_ghe                      1735     0x6C7\nCyrillic_ha                       1736     0x6C8\nCyrillic_i                        1737     0x6C9\nCyrillic_shorti                   1738     0x6CA\nCyrillic_ka                       1739     0x6CB\nCyrillic_el                       1740     0x6CC\nCyrillic_em                       1741     0x6CD\nCyrillic_en                       1742     0x6CE\nCyrillic_o                        1743     0x6CF\nCyrillic_pe                       1744     0x6D0\nCyrillic_ya                       1745     0x6D1\nCyrillic_er                       1746     0x6D2\nCyrillic_es                       1747     0x6D3\nCyrillic_te                       1748     0x6D4\nCyrillic_u                        1749     0x6D5\nCyrillic_zhe                      1750     0x6D6\nCyrillic_ve                       1751     0x6D7\nCyrillic_softsign                 1752     0x6D8\nCyrillic_yeru                     1753     0x6D9\nCyrillic_ze                       1754     0x6DA\nCyrillic_sha                      1755     0x6DB\nCyrillic_e                        1756     0x6DC\nCyrillic_shcha                    1757     0x6DD\nCyrillic_che                      1758     0x6DE\nCyrillic_hardsign                 1759     0x6DF\nCyrillic_YU                       1760     0x6E0\nCyrillic_A                        1761     0x6E1\nCyrillic_BE                       1762     0x6E2\nCyrillic_TSE                      1763     0x6E3\nCyrillic_DE                       1764     0x6E4\nCyrillic_IE                       1765     0x6E5\nCyrillic_EF                       1766     0x6E6\nCyrillic_GHE                      1767     0x6E7\nCyrillic_HA                       1768     0x6E8\nCyrillic_I                        1769     0x6E9\nCyrillic_SHORTI                   1770     0x6EA\nCyrillic_KA                       1771     0x6EB\nCyrillic_EL                       1772     0x6EC\nCyrillic_EM                       1773     0x6ED\nCyrillic_EN                       1774     0x6EE\nCyrillic_O                        1775     0x6EF\nCyrillic_PE                       1776     0x6F0\nCyrillic_YA                       1777     0x6F1\nCyrillic_ER                       1778     0x6F2\nCyrillic_ES                       1779     0x6F3\nCyrillic_TE                       1780     0x6F4\nCyrillic_U                        1781     0x6F5\nCyrillic_ZHE                      1782     0x6F6\nCyrillic_VE                       1783     0x6F7\nCyrillic_SOFTSIGN                 1784     0x6F8\nCyrillic_YERU                     1785     0x6F9\nCyrillic_ZE                       1786     0x6FA\nCyrillic_SHA                      1787     0x6FB\nCyrillic_E                        1788     0x6FC\nCyrillic_SHCHA                    1789     0x6FD\nCyrillic_CHE                      1790     0x6FE\nCyrillic_HARDSIGN                 1791     0x6FF\nGreek_ALPHAaccent                 1953     0x7A1\nGreek_EPSILONaccent               1954     0x7A2\nGreek_ETAaccent                   1955     0x7A3\nGreek_IOTAaccent                  1956     0x7A4\nGreek_IOTAdieresis                1957     0x7A5\nGreek_IOTAaccentdiaeresis         1958     0x7A6\nGreek_OMICRONaccent               1959     0x7A7\nGreek_UPSILONaccent               1960     0x7A8\nGreek_UPSILONdieresis             1961     0x7A9\nGreek_UPSILONaccentdieresis       1962     0x7AA\nGreek_OMEGAaccent                 1963     0x7AB\nGreek_accentdieresis              1966     0x7AE\nGreek_horizbar                    1967     0x7AF\nGreek_alphaaccent                 1969     0x7B1\nGreek_epsilonaccent               1970     0x7B2\nGreek_etaaccent                   1971     0x7B3\nGreek_iotaaccent                  1972     0x7B4\nGreek_iotadieresis                1973     0x7B5\nGreek_iotaaccentdieresis          1974     0x7B6\nGreek_omicronaccent               1975     0x7B7\nGreek_upsilonaccent               1976     0x7B8\nGreek_upsilondieresis             1977     0x7B9\nGreek_upsilonaccentdieresis       1978     0x7BA\nGreek_omegaaccent                 1979     0x7BB\nGreek_ALPHA                       1985     0x7C1\nGreek_BETA                        1986     0x7C2\nGreek_GAMMA                       1987     0x7C3\nGreek_DELTA                       1988     0x7C4\nGreek_EPSILON                     1989     0x7C5\nGreek_ZETA                        1990     0x7C6\nGreek_ETA                         1991     0x7C7\nGreek_THETA                       1992     0x7C8\nGreek_IOTA                        1993     0x7C9\nGreek_KAPPA                       1994     0x7CA\nGreek_LAMBDA                      1995     0x7CB\nGreek_MU                          1996     0x7CC\nGreek_NU                          1997     0x7CD\nGreek_XI                          1998     0x7CE\nGreek_OMICRON                     1999     0x7CF\nGreek_PI                          2000     0x7D0\nGreek_RHO                         2001     0x7D1\nGreek_SIGMA                       2002     0x7D2\nGreek_TAU                         2004     0x7D4\nGreek_UPSILON                     2005     0x7D5\nGreek_PHI                         2006     0x7D6\nGreek_CHI                         2007     0x7D7\nGreek_PSI                         2008     0x7D8\nGreek_OMEGA                       2009     0x7D9\nGreek_alpha                       2017     0x7E1\nGreek_beta                        2018     0x7E2\nGreek_gamma                       2019     0x7E3\nGreek_delta                       2020     0x7E4\nGreek_epsilon                     2021     0x7E5\nGreek_zeta                        2022     0x7E6\nGreek_eta                         2023     0x7E7\nGreek_theta                       2024     0x7E8\nGreek_iota                        2025     0x7E9\nGreek_kappa                       2026     0x7EA\nGreek_lambda                      2027     0x7EB\nGreek_mu                          2028     0x7EC\nGreek_nu                          2029     0x7ED\nGreek_xi                          2030     0x7EE\nGreek_omicron                     2031     0x7EF\nGreek_pi                          2032     0x7F0\nGreek_rho                         2033     0x7F1\nGreek_sigma                       2034     0x7F2\nGreek_finalsmallsigma             2035     0x7F3\nGreek_tau                         2036     0x7F4\nGreek_upsilon                     2037     0x7F5\nGreek_phi                         2038     0x7F6\nGreek_chi                         2039     0x7F7\nGreek_psi                         2040     0x7F8\nGreek_omega                       2041     0x7F9\n.CE\n.CS\nleftradical                       2209     0x8A1\ntopleftradical                    2210     0x8A2\nhorizconnector                    2211     0x8A3\ntopintegral                       2212     0x8A4\nbotintegral                       2213     0x8A5\nvertconnector                     2214     0x8A6\ntopleftsqbracket                  2215     0x8A7\nbotleftsqbracket                  2216     0x8A8\ntoprightsqbracket                 2217     0x8A9\nbotrightsqbracket                 2218     0x8AA\ntopleftparens                     2219     0x8AB\nbotleftparens                     2220     0x8AC\ntoprightparens                    2221     0x8AD\nbotrightparens                    2222     0x8AE\nleftmiddlecurlybrace              2223     0x8AF\nrightmiddlecurlybrace             2224     0x8B0\ntopleftsummation                  2225     0x8B1\nbotleftsummation                  2226     0x8B2\ntopvertsummationconnector         2227     0x8B3\nbotvertsummationconnector         2228     0x8B4\ntoprightsummation                 2229     0x8B5\nbotrightsummation                 2230     0x8B6\nrightmiddlesummation              2231     0x8B7\nlessthanequal                     2236     0x8BC\nnotequal                          2237     0x8BD\ngreaterthanequal                  2238     0x8BE\nintegral                          2239     0x8BF\ntherefore                         2240     0x8C0\nvariation                         2241     0x8C1\ninfinity                          2242     0x8C2\nnabla                             2245     0x8C5\napproximate                       2248     0x8C8\nsimilarequal                      2249     0x8C9\nifonlyif                          2253     0x8CD\nimplies                           2254     0x8CE\nidentical                         2255     0x8CF\nradical                           2262     0x8D6\nincludedin                        2266     0x8DA\nincludes                          2267     0x8DB\nintersection                      2268     0x8DC\nunion                             2269     0x8DD\nlogicaland                        2270     0x8DE\nlogicalor                         2271     0x8DF\npartialderivative                 2287     0x8EF\nfunction                          2294     0x8F6\nleftarrow                         2299     0x8FB\nuparrow                           2300     0x8FC\nrightarrow                        2301     0x8FD\ndownarrow                         2302     0x8FE\nblank                             2527     0x9DF\nsoliddiamond                      2528     0x9E0\ncheckerboard                      2529     0x9E1\nht                                2530     0x9E2\nff                                2531     0x9E3\ncr                                2532     0x9E4\nlf                                2533     0x9E5\nnl                                2536     0x9E8\nvt                                2537     0x9E9\nlowrightcorner                    2538     0x9EA\nuprightcorner                     2539     0x9EB\nupleftcorner                      2540     0x9EC\nlowleftcorner                     2541     0x9ED\ncrossinglines                     2542     0x9EE\nhorizlinescan1                    2543     0x9EF\nhorizlinescan3                    2544     0x9F0\nhorizlinescan5                    2545     0x9F1\nhorizlinescan7                    2546     0x9F2\nhorizlinescan9                    2547     0x9F3\nleftt                             2548     0x9F4\nrightt                            2549     0x9F5\nbott                              2550     0x9F6\ntopt                              2551     0x9F7\nvertbar                           2552     0x9F8\nemspace                           2721     0xAA1\nenspace                           2722     0xAA2\nem3space                          2723     0xAA3\nem4space                          2724     0xAA4\ndigitspace                        2725     0xAA5\npunctspace                        2726     0xAA6\nthinspace                         2727     0xAA7\nhairspace                         2728     0xAA8\nemdash                            2729     0xAA9\nendash                            2730     0xAAA\nsignifblank                       2732     0xAAC\nellipsis                          2734     0xAAE\ndoubbaselinedot                   2735     0xAAF\nonethird                          2736     0xAB0\ntwothirds                         2737     0xAB1\nonefifth                          2738     0xAB2\ntwofifths                         2739     0xAB3\nthreefifths                       2740     0xAB4\nfourfifths                        2741     0xAB5\nonesixth                          2742     0xAB6\nfivesixths                        2743     0xAB7\ncareof                            2744     0xAB8\nfigdash                           2747     0xABB\nleftanglebracket                  2748     0xABC\ndecimalpoint                      2749     0xABD\nrightanglebracket                 2750     0xABE\nmarker                            2751     0xABF\noneeighth                         2755     0xAC3\nthreeeighths                      2756     0xAC4\nfiveeighths                       2757     0xAC5\nseveneighths                      2758     0xAC6\ntrademark                         2761     0xAC9\nsignaturemark                     2762     0xACA\ntrademarkincircle                 2763     0xACB\nleftopentriangle                  2764     0xACC\nrightopentriangle                 2765     0xACD\nemopencircle                      2766     0xACE\nemopenrectangle                   2767     0xACF\nleftsinglequotemark               2768     0xAD0\nrightsinglequotemark              2769     0xAD1\nleftdoublequotemark               2770     0xAD2\nrightdoublequotemark              2771     0xAD3\nprescription                      2772     0xAD4\npermille                          2773     0xAD5\nminutes                           2774     0xAD6\nseconds                           2775     0xAD7\nlatincross                        2777     0xAD9\nhexagram                          2778     0xADA\nfilledrectbullet                  2779     0xADB\nfilledlefttribullet               2780     0xADC\nfilledrighttribullet              2781     0xADD\nemfilledcircle                    2782     0xADE\nemfilledrect                      2783     0xADF\nenopencircbullet                  2784     0xAE0\nenopensquarebullet                2785     0xAE1\nopenrectbullet                    2786     0xAE2\nopentribulletup                   2787     0xAE3\nopentribulletdown                 2788     0xAE4\nopenstar                          2789     0xAE5\nenfilledcircbullet                2790     0xAE6\nenfilledsqbullet                  2791     0xAE7\nfilledtribulletup                 2792     0xAE8\nfilledtribulletdown               2793     0xAE9\nleftpointer                       2794     0xAEA\nrightpointer                      2795     0xAEB\nclub                              2796     0xAEC\ndiamond                           2797     0xAED\nheart                             2798     0xAEE\nmaltesecross                      2800     0xAF0\ndagger                            2801     0xAF1\ndoubledagger                      2802     0xAF2\ncheckmark                         2803     0xAF3\nballotcross                       2804     0xAF4\nmusicalsharp                      2805     0xAF5\nmusicalflat                       2806     0xAF6\nmalesymbol                        2807     0xAF7\nfemalesymbol                      2808     0xAF8\ntelephone                         2809     0xAF9\ntelephonerecorder                 2810     0xAFA\nphonographcopyright               2811     0xAFB\ncaret                             2812     0xAFC\nsinglelowquotemark                2813     0xAFD\ndoublelowquotemark                2814     0xAFE\ncursor                            2815     0xAFF\nleftcaret                         2979     0xBA3\nrightcaret                        2982     0xBA6\ndowncaret                         2984     0xBA8\nupcaret                           2985     0xBA9\noverbar                           3008     0xBC0\ndowntack                          3010     0xBC2\nupshoe                            3011     0xBC3\ndownstile                         3012     0xBC4\nunderbar                          3014     0xBC6\njot                               3018     0xBCA\nquad                              3020     0xBCC\nuptack                            3022     0xBCE\ncircle                            3023     0xBCF\nupstile                           3027     0xBD3\ndownshoe                          3030     0xBD6\nrightshoe                         3032     0xBD8\nleftshoe                          3034     0xBDA\nlefttack                          3036     0xBDC\nrighttack                         3068     0xBFC\nhebrew_doublelowline              3295     0xCDF\nhebrew_aleph                      3296     0xCE0\nhebrew_bet                        3297     0xCE1\nhebrew_gimel                      3298     0xCE2\nhebrew_dalet                      3299     0xCE3\nhebrew_he                         3300     0xCE4\nhebrew_waw                        3301     0xCE5\nhebrew_zain                       3302     0xCE6\nhebrew_chet                       3303     0xCE7\nhebrew_tet                        3304     0xCE8\nhebrew_yod                        3305     0xCE9\nhebrew_finalkaph                  3306     0xCEA\nhebrew_kaph                       3307     0xCEB\nhebrew_lamed                      3308     0xCEC\nhebrew_finalmem                   3309     0xCED\nhebrew_mem                        3310     0xCEE\nhebrew_finalnun                   3311     0xCEF\nhebrew_nun                        3312     0xCF0\nhebrew_samech                     3313     0xCF1\nhebrew_ayin                       3314     0xCF2\nhebrew_finalpe                    3315     0xCF3\nhebrew_pe                         3316     0xCF4\nhebrew_finalzade                  3317     0xCF5\nhebrew_zade                       3318     0xCF6\nhebrew_qoph                       3319     0xCF7\nhebrew_resh                       3320     0xCF8\nhebrew_shin                       3321     0xCF9\nhebrew_taw                        3322     0xCFA\n.CE\n.CS\nThai_kokai                        3489     0xDA1\nThai_khokhai                      3490     0xDA2\nThai_khokhuat                     3491     0xDA3\nThai_khokhwai                     3492     0xDA4\nThai_khokhon                      3493     0xDA5\nThai_khorakhang                   3494     0xDA6\nThai_ngongu                       3495     0xDA7\nThai_chochan                      3496     0xDA8\nThai_choching                     3497     0xDA9\nThai_chochang                     3498     0xDAA\nThai_soso                         3499     0xDAB\nThai_chochoe                      3500     0xDAC\nThai_yoying                       3501     0xDAD\nThai_dochada                      3502     0xDAE\nThai_topatak                      3503     0xDAF\nThai_thothan                      3504     0xDB0\nThai_thonangmontho                3505     0xDB1\nThai_thophuthao                   3506     0xDB2\nThai_nonen                        3507     0xDB3\nThai_dodek                        3508     0xDB4\nThai_totao                        3509     0xDB5\nThai_thothung                     3510     0xDB6\nThai_thothahan                    3511     0xDB7\nThai_thothong                     3512     0xDB8\nThai_nonu                         3513     0xDB9\nThai_bobaimai                     3514     0xDBA\nThai_popla                        3515     0xDBB\nThai_phophung                     3516     0xDBC\nThai_fofa                         3517     0xDBD\nThai_phophan                      3518     0xDBE\nThai_fofan                        3519     0xDBF\nThai_phosamphao                   3520     0xDC0\nThai_moma                         3521     0xDC1\nThai_yoyak                        3522     0xDC2\nThai_rorua                        3523     0xDC3\nThai_ru                           3524     0xDC4\nThai_loling                       3525     0xDC5\nThai_lu                           3526     0xDC6\nThai_wowaen                       3527     0xDC7\nThai_sosala                       3528     0xDC8\nThai_sorusi                       3529     0xDC9\nThai_sosua                        3530     0xDCA\nThai_hohip                        3531     0xDCB\nThai_lochula                      3532     0xDCC\nThai_oang                         3533     0xDCD\nThai_honokhuk                     3534     0xDCE\nThai_paiyannoi                    3535     0xDCF\nThai_saraa                        3536     0xDD0\nThai_maihanakat                   3537     0xDD1\nThai_saraaa                       3538     0xDD2\nThai_saraam                       3539     0xDD3\nThai_sarai                        3540     0xDD4\nThai_saraii                       3541     0xDD5\nThai_saraue                       3542     0xDD6\nThai_sarauee                      3543     0xDD7\nThai_sarau                        3544     0xDD8\nThai_sarauu                       3545     0xDD9\nThai_phinthu                      3546     0xDDA\nThai_maihanakat_maitho            3550     0xDDE\nThai_baht                         3551     0xDDF\nThai_sarae                        3552     0xDE0\nThai_saraae                       3553     0xDE1\nThai_sarao                        3554     0xDE2\nThai_saraaimaimuan                3555     0xDE3\nThai_saraaimaimalai               3556     0xDE4\nThai_lakkhangyao                  3557     0xDE5\nThai_maiyamok                     3558     0xDE6\nThai_maitaikhu                    3559     0xDE7\nThai_maiek                        3560     0xDE8\nThai_maitho                       3561     0xDE9\nThai_maitri                       3562     0xDEA\nThai_maichattawa                  3563     0xDEB\nThai_thanthakhat                  3564     0xDEC\nThai_nikhahit                     3565     0xDED\nThai_leksun                       3568     0xDF0\nThai_leknung                      3569     0xDF1\nThai_leksong                      3570     0xDF2\nThai_leksam                       3571     0xDF3\nThai_leksi                        3572     0xDF4\nThai_lekha                        3573     0xDF5\nThai_lekhok                       3574     0xDF6\nThai_lekchet                      3575     0xDF7\nThai_lekpaet                      3576     0xDF8\nThai_lekkao                       3577     0xDF9\nHangul_Kiyeog                     3745     0xEA1\nHangul_SsangKiyeog                3746     0xEA2\nHangul_KiyeogSios                 3747     0xEA3\nHangul_Nieun                      3748     0xEA4\nHangul_NieunJieuj                 3749     0xEA5\nHangul_NieunHieuh                 3750     0xEA6\nHangul_Dikeud                     3751     0xEA7\nHangul_SsangDikeud                3752     0xEA8\nHangul_Rieul                      3753     0xEA9\nHangul_RieulKiyeog                3754     0xEAA\nHangul_RieulMieum                 3755     0xEAB\nHangul_RieulPieub                 3756     0xEAC\nHangul_RieulSios                  3757     0xEAD\nHangul_RieulTieut                 3758     0xEAE\nHangul_RieulPhieuf                3759     0xEAF\nHangul_RieulHieuh                 3760     0xEB0\nHangul_Mieum                      3761     0xEB1\nHangul_Pieub                      3762     0xEB2\nHangul_SsangPieub                 3763     0xEB3\nHangul_PieubSios                  3764     0xEB4\nHangul_Sios                       3765     0xEB5\nHangul_SsangSios                  3766     0xEB6\nHangul_Ieung                      3767     0xEB7\nHangul_Jieuj                      3768     0xEB8\nHangul_SsangJieuj                 3769     0xEB9\nHangul_Cieuc                      3770     0xEBA\nHangul_Khieuq                     3771     0xEBB\nHangul_Tieut                      3772     0xEBC\nHangul_Phieuf                     3773     0xEBD\nHangul_Hieuh                      3774     0xEBE\nHangul_A                          3775     0xEBF\nHangul_AE                         3776     0xEC0\nHangul_YA                         3777     0xEC1\nHangul_YAE                        3778     0xEC2\nHangul_EO                         3779     0xEC3\nHangul_E                          3780     0xEC4\nHangul_YEO                        3781     0xEC5\nHangul_YE                         3782     0xEC6\nHangul_O                          3783     0xEC7\nHangul_WA                         3784     0xEC8\nHangul_WAE                        3785     0xEC9\nHangul_OE                         3786     0xECA\nHangul_YO                         3787     0xECB\nHangul_U                          3788     0xECC\nHangul_WEO                        3789     0xECD\nHangul_WE                         3790     0xECE\nHangul_WI                         3791     0xECF\nHangul_YU                         3792     0xED0\nHangul_EU                         3793     0xED1\nHangul_YI                         3794     0xED2\nHangul_I                          3795     0xED3\nHangul_J_Kiyeog                   3796     0xED4\nHangul_J_SsangKiyeog              3797     0xED5\nHangul_J_KiyeogSios               3798     0xED6\nHangul_J_Nieun                    3799     0xED7\nHangul_J_NieunJieuj               3800     0xED8\nHangul_J_NieunHieuh               3801     0xED9\nHangul_J_Dikeud                   3802     0xEDA\nHangul_J_Rieul                    3803     0xEDB\nHangul_J_RieulKiyeog              3804     0xEDC\nHangul_J_RieulMieum               3805     0xEDD\nHangul_J_RieulPieub               3806     0xEDE\nHangul_J_RieulSios                3807     0xEDF\nHangul_J_RieulTieut               3808     0xEE0\nHangul_J_RieulPhieuf              3809     0xEE1\nHangul_J_RieulHieuh               3810     0xEE2\nHangul_J_Mieum                    3811     0xEE3\nHangul_J_Pieub                    3812     0xEE4\nHangul_J_PieubSios                3813     0xEE5\nHangul_J_Sios                     3814     0xEE6\nHangul_J_SsangSios                3815     0xEE7\nHangul_J_Ieung                    3816     0xEE8\nHangul_J_Jieuj                    3817     0xEE9\nHangul_J_Cieuc                    3818     0xEEA\nHangul_J_Khieuq                   3819     0xEEB\nHangul_J_Tieut                    3820     0xEEC\nHangul_J_Phieuf                   3821     0xEED\nHangul_J_Hieuh                    3822     0xEEE\nHangul_RieulYeorinHieuh           3823     0xEEF\nHangul_SunkyeongeumMieum          3824     0xEF0\nHangul_SunkyeongeumPieub          3825     0xEF1\nHangul_PanSios                    3826     0xEF2\nHangul_KkogjiDalrinIeung          3827     0xEF3\nHangul_SunkyeongeumPhieuf         3828     0xEF4\nHangul_YeorinHieuh                3829     0xEF5\nHangul_AraeA                      3830     0xEF6\nHangul_AraeAE                     3831     0xEF7\nHangul_J_PanSios                  3832     0xEF8\nHangul_J_KkogjiDalrinIeung        3833     0xEF9\nHangul_J_YeorinHieuh              3834     0xEFA\nKorean_Won                        3839     0xEFF\nOE                                5052     0x13BC\noe                                5053     0x13BD\nYdiaeresis                        5054     0x13BE\n\\(eu (EuroSign)                      8364     0x20AC\n.CE\n.CS\nISO_Lock                         65025     0xFE01\nISO_Level2_Latch                 65026     0xFE02\nISO_Level3_Shift                 65027     0xFE03\nISO_Level3_Latch                 65028     0xFE04\nISO_Level3_Lock                  65029     0xFE05\nISO_Group_Latch                  65030     0xFE06\nISO_Group_Lock                   65031     0xFE07\nISO_Next_Group                   65032     0xFE08\nISO_Next_Group_Lock              65033     0xFE09\nISO_Prev_Group                   65034     0xFE0A\nISO_Prev_Group_Lock              65035     0xFE0B\nISO_First_Group                  65036     0xFE0C\nISO_First_Group_Lock             65037     0xFE0D\nISO_Last_Group                   65038     0xFE0E\nISO_Last_Group_Lock              65039     0xFE0F\nISO_Level5_Shift                 65041     0xFE11\nISO_Level5_Latch                 65042     0xFE12\nISO_Level5_Lock                  65043     0xFE13\nISO_Left_Tab                     65056     0xFE20\nISO_Move_Line_Up                 65057     0xFE21\nISO_Move_Line_Down               65058     0xFE22\nISO_Partial_Line_Up              65059     0xFE23\nISO_Partial_Line_Down            65060     0xFE24\nISO_Partial_Space_Left           65061     0xFE25\nISO_Partial_Space_Right          65062     0xFE26\nISO_Set_Margin_Left              65063     0xFE27\nISO_Set_Margin_Right             65064     0xFE28\nISO_Release_Margin_Left          65065     0xFE29\nISO_Release_Margin_Right         65066     0xFE2A\nISO_Release_Both_Margins         65067     0xFE2B\nISO_Fast_Cursor_Left             65068     0xFE2C\nISO_Fast_Cursor_Right            65069     0xFE2D\nISO_Fast_Cursor_Up               65070     0xFE2E\nISO_Fast_Cursor_Down             65071     0xFE2F\nISO_Continuous_Underline         65072     0xFE30\nISO_Discontinuous_Underline      65073     0xFE31\nISO_Emphasize                    65074     0xFE32\nISO_Center_Object                65075     0xFE33\nISO_Enter                        65076     0xFE34\ndead_grave                       65104     0xFE50\ndead_acute                       65105     0xFE51\ndead_circumflex                  65106     0xFE52\ndead_tilde                       65107     0xFE53\ndead_macron                      65108     0xFE54\ndead_breve                       65109     0xFE55\ndead_abovedot                    65110     0xFE56\ndead_diaeresis                   65111     0xFE57\ndead_abovering                   65112     0xFE58\ndead_doubleacute                 65113     0xFE59\ndead_caron                       65114     0xFE5A\ndead_cedilla                     65115     0xFE5B\ndead_ogonek                      65116     0xFE5C\ndead_iota                        65117     0xFE5D\ndead_voiced_sound                65118     0xFE5E\ndead_semivoiced_sound            65119     0xFE5F\ndead_belowdot                    65120     0xFE60\ndead_hook                        65121     0xFE61\ndead_horn                        65122     0xFE62\ndead_stroke                      65123     0xFE63\ndead_abovecomma                  65124     0xFE64\ndead_abovereversedcomma          65125     0xFE65\ndead_doublegrave                 65126     0xFE66\ndead_belowring                   65127     0xFE67\ndead_belowmacron                 65128     0xFE68\ndead_belowcircumflex             65129     0xFE69\ndead_belowtilde                  65130     0xFE6A\ndead_belowbreve                  65131     0xFE6B\ndead_belowdiaeresis              65132     0xFE6C\ndead_invertedbreve               65133     0xFE6D\ndead_belowcomma                  65134     0xFE6E\ndead_currency                    65135     0xFE6F\nAccessX_Enable                   65136     0xFE70\nAccessX_Feedback_Enable          65137     0xFE71\nRepeatKeys_Enable                65138     0xFE72\nSlowKeys_Enable                  65139     0xFE73\nBounceKeys_Enable                65140     0xFE74\nStickyKeys_Enable                65141     0xFE75\nMouseKeys_Enable                 65142     0xFE76\nMouseKeys_Accel_Enable           65143     0xFE77\nOverlay1_Enable                  65144     0xFE78\nOverlay2_Enable                  65145     0xFE79\nAudibleBell_Enable               65146     0xFE7A\ndead_a                           65152     0xFE80\ndead_A                           65153     0xFE81\ndead_e                           65154     0xFE82\ndead_E                           65155     0xFE83\ndead_i                           65156     0xFE84\ndead_I                           65157     0xFE85\ndead_o                           65158     0xFE86\ndead_O                           65159     0xFE87\ndead_u                           65160     0xFE88\ndead_U                           65161     0xFE89\ndead_schwa                       65162     0xFE8A\ndead_SCHWA                       65163     0xFE8B\ndead_greek                       65164     0xFE8C\ndead_hamza                       65165     0xFE8D\ndead_lowline                     65168     0xFE90\ndead_aboveverticalline           65169     0xFE91\ndead_belowverticalline           65170     0xFE92\ndead_longsolidusoverlay          65171     0xFE93\nch                               65184     0xFEA0\nCh                               65185     0xFEA1\nCH                               65186     0xFEA2\nc_h                              65187     0xFEA3\nC_h                              65188     0xFEA4\nC_H                              65189     0xFEA5\nFirst_Virtual_Screen             65232     0xFED0\nPrev_Virtual_Screen              65233     0xFED1\nNext_Virtual_Screen              65234     0xFED2\nLast_Virtual_Screen              65236     0xFED4\nTerminate_Server                 65237     0xFED5\nPointer_Left                     65248     0xFEE0\nPointer_Right                    65249     0xFEE1\nPointer_Up                       65250     0xFEE2\nPointer_Down                     65251     0xFEE3\nPointer_UpLeft                   65252     0xFEE4\nPointer_UpRight                  65253     0xFEE5\nPointer_DownLeft                 65254     0xFEE6\nPointer_DownRight                65255     0xFEE7\nPointer_Button_Dflt              65256     0xFEE8\nPointer_Button1                  65257     0xFEE9\nPointer_Button2                  65258     0xFEEA\nPointer_Button3                  65259     0xFEEB\nPointer_Button4                  65260     0xFEEC\nPointer_Button5                  65261     0xFEED\nPointer_DblClick_Dflt            65262     0xFEEE\nPointer_DblClick1                65263     0xFEEF\nPointer_DblClick2                65264     0xFEF0\nPointer_DblClick3                65265     0xFEF1\nPointer_DblClick4                65266     0xFEF2\nPointer_DblClick5                65267     0xFEF3\nPointer_Drag_Dflt                65268     0xFEF4\nPointer_Drag1                    65269     0xFEF5\nPointer_Drag2                    65270     0xFEF6\nPointer_Drag3                    65271     0xFEF7\nPointer_Drag4                    65272     0xFEF8\nPointer_EnableKeys               65273     0xFEF9\nPointer_Accelerate               65274     0xFEFA\nPointer_DfltBtnNext              65275     0xFEFB\nPointer_DfltBtnPrev              65276     0xFEFC\nPointer_Drag5                    65277     0xFEFD\n.CE\n.CS\nBackSpace                        65288     0xFF08\nTab                              65289     0xFF09\nLinefeed                         65290     0xFF0A\nClear                            65291     0xFF0B\nReturn                           65293     0xFF0D\nPause                            65299     0xFF13\nScroll_Lock                      65300     0xFF14\nSys_Req                          65301     0xFF15\nEscape                           65307     0xFF1B\nMulti_key                        65312     0xFF20\nKanji                            65313     0xFF21\nMuhenkan                         65314     0xFF22\nHenkan                           65315     0xFF23\nRomaji                           65316     0xFF24\nHiragana                         65317     0xFF25\nKatakana                         65318     0xFF26\nHiragana_Katakana                65319     0xFF27\nZenkaku                          65320     0xFF28\nHankaku                          65321     0xFF29\nZenkaku_Hankaku                  65322     0xFF2A\nTouroku                          65323     0xFF2B\nMassyo                           65324     0xFF2C\nKana_Lock                        65325     0xFF2D\nKana_Shift                       65326     0xFF2E\nEisu_Shift                       65327     0xFF2F\nEisu_toggle                      65328     0xFF30\nHangul                           65329     0xFF31\nHangul_Start                     65330     0xFF32\nHangul_End                       65331     0xFF33\nHangul_Hanja                     65332     0xFF34\nHangul_Jamo                      65333     0xFF35\nHangul_Romaja                    65334     0xFF36\nCodeinput                        65335     0xFF37\nHangul_Jeonja                    65336     0xFF38\nHangul_Banja                     65337     0xFF39\nHangul_PreHanja                  65338     0xFF3A\nHangul_PostHanja                 65339     0xFF3B\nSingleCandidate                  65340     0xFF3C\nMultipleCandidate                65341     0xFF3D\nPreviousCandidate                65342     0xFF3E\nHangul_Special                   65343     0xFF3F\nHome                             65360     0xFF50\nLeft                             65361     0xFF51\nUp                               65362     0xFF52\nRight                            65363     0xFF53\nDown                             65364     0xFF54\nPrior                            65365     0xFF55\nNext                             65366     0xFF56\nEnd                              65367     0xFF57\nBegin                            65368     0xFF58\nSelect                           65376     0xFF60\nPrint                            65377     0xFF61\nExecute                          65378     0xFF62\nInsert                           65379     0xFF63\nUndo                             65381     0xFF65\nRedo                             65382     0xFF66\nMenu (App)                       65383     0xFF67\nFind                             65384     0xFF68\nCancel                           65385     0xFF69\nHelp                             65386     0xFF6A\nBreak                            65387     0xFF6B\nMode_switch                      65406     0xFF7E\nNum_Lock                         65407     0xFF7F\nKP_Space                         65408     0xFF80\nKP_Tab                           65417     0xFF89\nKP_Enter                         65421     0xFF8D\nKP_F1                            65425     0xFF91\nKP_F2                            65426     0xFF92\nKP_F3                            65427     0xFF93\nKP_F4                            65428     0xFF94\nKP_Home                          65429     0xFF95\nKP_Left                          65430     0xFF96\nKP_Up                            65431     0xFF97\nKP_Right                         65432     0xFF98\nKP_Down                          65433     0xFF99\nKP_Prior                         65434     0xFF9A\nKP_Next                          65435     0xFF9B\nKP_End                           65436     0xFF9C\nKP_Begin                         65437     0xFF9D\nKP_Insert                        65438     0xFF9E\nKP_Delete                        65439     0xFF9F\nKP_Multiply                      65450     0xFFAA\nKP_Add                           65451     0xFFAB\nKP_Separator                     65452     0xFFAC\nKP_Subtract                      65453     0xFFAD\nKP_Decimal                       65454     0xFFAE\nKP_Divide                        65455     0xFFAF\nKP_0                             65456     0xFFB0\nKP_1                             65457     0xFFB1\nKP_2                             65458     0xFFB2\nKP_3                             65459     0xFFB3\nKP_4                             65460     0xFFB4\nKP_5                             65461     0xFFB5\nKP_6                             65462     0xFFB6\nKP_7                             65463     0xFFB7\nKP_8                             65464     0xFFB8\nKP_9                             65465     0xFFB9\nKP_Equal                         65469     0xFFBD\nF1                               65470     0xFFBE\nF2                               65471     0xFFBF\nF3                               65472     0xFFC0\nF4                               65473     0xFFC1\nF5                               65474     0xFFC2\nF6                               65475     0xFFC3\nF7                               65476     0xFFC4\nF8                               65477     0xFFC5\nF9                               65478     0xFFC6\nF10                              65479     0xFFC7\nF11                              65480     0xFFC8\nF12                              65481     0xFFC9\nF13                              65482     0xFFCA\nF14                              65483     0xFFCB\nF15                              65484     0xFFCC\nF16                              65485     0xFFCD\nF17                              65486     0xFFCE\nF18                              65487     0xFFCF\nF19                              65488     0xFFD0\nF20                              65489     0xFFD1\nF21                              65490     0xFFD2\nF22                              65491     0xFFD3\nF23                              65492     0xFFD4\nF24                              65493     0xFFD5\nF25                              65494     0xFFD6\nF26                              65495     0xFFD7\nF27                              65496     0xFFD8\nF28                              65497     0xFFD9\nF29                              65498     0xFFDA\nF30                              65499     0xFFDB\nF31                              65500     0xFFDC\nF32                              65501     0xFFDD\nF33                              65502     0xFFDE\nF34                              65503     0xFFDF\nF35                              65504     0xFFE0\nShift_L                          65505     0xFFE1\nShift_R                          65506     0xFFE2\nControl_L                        65507     0xFFE3\nControl_R                        65508     0xFFE4\nCaps_Lock                        65509     0xFFE5\nShift_Lock                       65510     0xFFE6\nMeta_L                           65511     0xFFE7\nMeta_R                           65512     0xFFE8\nAlt_L                            65513     0xFFE9\nAlt_R                            65514     0xFFEA\nSuper_L (Win_L)                  65515     0xFFEB\nSuper_R (Win_R)                  65516     0xFFEC\nHyper_L                          65517     0xFFED\nHyper_R                          65518     0xFFEE\nbraille_dot_1                    65521     0xFFF1\nbraille_dot_2                    65522     0xFFF2\nbraille_dot_3                    65523     0xFFF3\nbraille_dot_4                    65524     0xFFF4\nbraille_dot_5                    65525     0xFFF5\nbraille_dot_6                    65526     0xFFF6\nbraille_dot_7                    65527     0xFFF7\nbraille_dot_8                    65528     0xFFF8\nbraille_dot_9                    65529     0xFFF9\nbraille_dot_10                   65530     0xFFFA\nDelete                           65535     0xFFFF\n.CE\n.CS\nSunFA_Grave                  268828416     0x1005FF00\nSunFA_Circum                 268828417     0x1005FF01\nSunFA_Tilde                  268828418     0x1005FF02\nSunFA_Acute                  268828419     0x1005FF03\nSunFA_Diaeresis              268828420     0x1005FF04\nSunFA_Cedilla                268828421     0x1005FF05\nSunF36                       268828432     0x1005FF10\nSunF37                       268828433     0x1005FF11\nSunSys_Req                   268828512     0x1005FF60\nSunProps                     268828528     0x1005FF70\nSunFront                     268828529     0x1005FF71\nSunCopy                      268828530     0x1005FF72\nSunOpen                      268828531     0x1005FF73\nSunPaste                     268828532     0x1005FF74\nSunCut                       268828533     0x1005FF75\nSunPowerSwitch               268828534     0x1005FF76\nSunAudioLowerVolume          268828535     0x1005FF77\nSunAudioMute                 268828536     0x1005FF78\nSunAudioRaiseVolume          268828537     0x1005FF79\nSunVideoDegauss              268828538     0x1005FF7A\nSunVideoLowerBrightness      268828539     0x1005FF7B\nSunVideoRaiseBrightness      268828540     0x1005FF7C\nSunPowerSwitchShift          268828541     0x1005FF7D\nXF86BrightnessAuto           268964084     0x100810F4\nXF86DisplayOff               268964085     0x100810F5\nXF86Info                     268964198     0x10081166\nXF86AspectRatio              268964215     0x10081177\nXF86DVD                      268964229     0x10081185\nXF86Audio                    268964232     0x10081188\nXF86ChannelUp                268964242     0x10081192\nXF86ChannelDown              268964243     0x10081193\nXF86Break                    268964251     0x1008119B\nXF86VideoPhone               268964256     0x100811A0\nXF86ZoomReset                268964260     0x100811A4\nXF86Editor                   268964262     0x100811A6\nXF86GraphicsEditor           268964264     0x100811A8\nXF86Presentation             268964265     0x100811A9\nXF86Database                 268964266     0x100811AA\nXF86Voicemail                268964268     0x100811AC\nXF86Addressbook              268964269     0x100811AD\nXF86DisplayToggle            268964271     0x100811AF\nXF86SpellCheck               268964272     0x100811B0\nXF86ContextMenu              268964278     0x100811B6\nXF86MediaRepeat              268964279     0x100811B7\nXF8610ChannelsUp             268964280     0x100811B8\nXF8610ChannelsDown           268964281     0x100811B9\nXF86Images                   268964282     0x100811BA\nXF86NotificationCenter       268964284     0x100811BC\nXF86PickupPhone              268964285     0x100811BD\nXF86HangupPhone              268964286     0x100811BE\nXF86Fn                       268964304     0x100811D0\nXF86Fn_Esc                   268964305     0x100811D1\nXF86FnRightShift             268964325     0x100811E5\nXF86Numeric0                 268964352     0x10081200\nXF86Numeric1                 268964353     0x10081201\nXF86Numeric2                 268964354     0x10081202\nXF86Numeric3                 268964355     0x10081203\nXF86Numeric4                 268964356     0x10081204\nXF86Numeric5                 268964357     0x10081205\nXF86Numeric6                 268964358     0x10081206\nXF86Numeric7                 268964359     0x10081207\nXF86Numeric8                 268964360     0x10081208\nXF86Numeric9                 268964361     0x10081209\nXF86NumericStar              268964362     0x1008120A\nXF86NumericPound             268964363     0x1008120B\nXF86NumericA                 268964364     0x1008120C\nXF86NumericB                 268964365     0x1008120D\nXF86NumericC                 268964366     0x1008120E\nXF86NumericD                 268964367     0x1008120F\nXF86CameraFocus              268964368     0x10081210\nXF86WPSButton                268964369     0x10081211\nXF86CameraZoomIn             268964373     0x10081215\nXF86CameraZoomOut            268964374     0x10081216\nXF86CameraUp                 268964375     0x10081217\nXF86CameraDown               268964376     0x10081218\nXF86CameraLeft               268964377     0x10081219\nXF86CameraRight              268964378     0x1008121A\nXF86AttendantOn              268964379     0x1008121B\nXF86AttendantOff             268964380     0x1008121C\nXF86AttendantToggle          268964381     0x1008121D\nXF86LightsToggle             268964382     0x1008121E\nXF86ALSToggle                268964400     0x10081230\nXF86Buttonconfig             268964416     0x10081240\nXF86Taskmanager              268964417     0x10081241\nXF86Journal                  268964418     0x10081242\nXF86ControlPanel             268964419     0x10081243\nXF86AppSelect                268964420     0x10081244\nXF86Screensaver              268964421     0x10081245\nXF86VoiceCommand             268964422     0x10081246\nXF86Assistant                268964423     0x10081247\nXF86EmojiPicker              268964425     0x10081249\nXF86Dictate                  268964426     0x1008124A\nXF86BrightnessMin            268964432     0x10081250\nXF86BrightnessMax            268964433     0x10081251\nXF86KbdInputAssistPrev       268964448     0x10081260\nXF86KbdInputAssistNext       268964449     0x10081261\nXF86KbdInputAssistPrevgroup  268964450     0x10081262\nXF86KbdInputAssistNextgroup  268964451     0x10081263\nXF86KbdInputAssistAccept     268964452     0x10081264\nXF86KbdInputAssistCancel     268964453     0x10081265\nXF86RightUp                  268964454     0x10081266\nXF86RightDown                268964455     0x10081267\nXF86LeftUp                   268964456     0x10081268\nXF86LeftDown                 268964457     0x10081269\nXF86RootMenu                 268964458     0x1008126A\nXF86MediaTopMenu             268964459     0x1008126B\nXF86Numeric11                268964460     0x1008126C\nXF86Numeric12                268964461     0x1008126D\nXF86AudioDesc                268964462     0x1008126E\nXF863DMode                   268964463     0x1008126F\nXF86NextFavorite             268964464     0x10081270\nXF86StopRecord               268964465     0x10081271\nXF86PauseRecord              268964466     0x10081272\nXF86VOD                      268964467     0x10081273\nXF86Unmute                   268964468     0x10081274\nXF86FastReverse              268964469     0x10081275\nXF86SlowReverse              268964470     0x10081276\nXF86Data                     268964471     0x10081277\nXF86OnScreenKeyboard         268964472     0x10081278\nXF86PrivacyScreenToggle      268964473     0x10081279\nXF86SelectiveScreenshot      268964474     0x1008127A\nXF86Macro1                   268964496     0x10081290\nXF86Macro2                   268964497     0x10081291\nXF86Macro3                   268964498     0x10081292\nXF86Macro4                   268964499     0x10081293\nXF86Macro5                   268964500     0x10081294\nXF86Macro6                   268964501     0x10081295\nXF86Macro7                   268964502     0x10081296\nXF86Macro8                   268964503     0x10081297\nXF86Macro9                   268964504     0x10081298\nXF86Macro10                  268964505     0x10081299\nXF86Macro11                  268964506     0x1008129A\nXF86Macro12                  268964507     0x1008129B\nXF86Macro13                  268964508     0x1008129C\nXF86Macro14                  268964509     0x1008129D\nXF86Macro15                  268964510     0x1008129E\nXF86Macro16                  268964511     0x1008129F\nXF86Macro17                  268964512     0x100812A0\nXF86Macro18                  268964513     0x100812A1\nXF86Macro19                  268964514     0x100812A2\nXF86Macro20                  268964515     0x100812A3\nXF86Macro21                  268964516     0x100812A4\nXF86Macro22                  268964517     0x100812A5\nXF86Macro23                  268964518     0x100812A6\nXF86Macro24                  268964519     0x100812A7\nXF86Macro25                  268964520     0x100812A8\nXF86Macro26                  268964521     0x100812A9\nXF86Macro27                  268964522     0x100812AA\nXF86Macro28                  268964523     0x100812AB\nXF86Macro29                  268964524     0x100812AC\nXF86Macro30                  268964525     0x100812AD\nXF86MacroRecordStart         268964528     0x100812B0\nXF86MacroRecordStop          268964529     0x100812B1\nXF86MacroPresetCycle         268964530     0x100812B2\nXF86MacroPreset1             268964531     0x100812B3\nXF86MacroPreset2             268964532     0x100812B4\nXF86MacroPreset3             268964533     0x100812B5\nXF86KbdLcdMenu1              268964536     0x100812B8\nXF86KbdLcdMenu2              268964537     0x100812B9\nXF86KbdLcdMenu3              268964538     0x100812BA\nXF86KbdLcdMenu4              268964539     0x100812BB\nXF86KbdLcdMenu5              268964540     0x100812BC\nXF86Switch_VT_1              269024769     0x1008FE01\nXF86Switch_VT_2              269024770     0x1008FE02\nXF86Switch_VT_3              269024771     0x1008FE03\nXF86Switch_VT_4              269024772     0x1008FE04\nXF86Switch_VT_5              269024773     0x1008FE05\nXF86Switch_VT_6              269024774     0x1008FE06\nXF86Switch_VT_7              269024775     0x1008FE07\nXF86Switch_VT_8              269024776     0x1008FE08\nXF86Switch_VT_9              269024777     0x1008FE09\nXF86Switch_VT_10             269024778     0x1008FE0A\nXF86Switch_VT_11             269024779     0x1008FE0B\nXF86Switch_VT_12             269024780     0x1008FE0C\n.CE\n.CS\nXF86Ungrab                   269024800     0x1008FE20\nXF86ClearGrab                269024801     0x1008FE21\nXF86Next_VMode               269024802     0x1008FE22\nXF86Prev_VMode               269024803     0x1008FE23\nXF86LogWindowTree            269024804     0x1008FE24\nXF86LogGrabInfo              269024805     0x1008FE25\nXF86ModeLock                 269025025     0x1008FF01\nXF86MonBrightnessUp          269025026     0x1008FF02\nXF86MonBrightnessDown        269025027     0x1008FF03\nXF86KbdLightOnOff            269025028     0x1008FF04\nXF86KbdBrightnessUp          269025029     0x1008FF05\nXF86KbdBrightnessDown        269025030     0x1008FF06\nXF86MonBrightnessCycle       269025031     0x1008FF07\nXF86Standby                  269025040     0x1008FF10\nXF86AudioLowerVolume         269025041     0x1008FF11\nXF86AudioMute                269025042     0x1008FF12\nXF86AudioRaiseVolume         269025043     0x1008FF13\nXF86AudioPlay                269025044     0x1008FF14\nXF86AudioStop                269025045     0x1008FF15\nXF86AudioPrev                269025046     0x1008FF16\nXF86AudioNext                269025047     0x1008FF17\nXF86HomePage                 269025048     0x1008FF18\nXF86Mail                     269025049     0x1008FF19\nXF86Start                    269025050     0x1008FF1A\nXF86Search                   269025051     0x1008FF1B\nXF86AudioRecord              269025052     0x1008FF1C\nXF86Calculator               269025053     0x1008FF1D\nXF86Memo                     269025054     0x1008FF1E\nXF86ToDoList                 269025055     0x1008FF1F\nXF86Calendar                 269025056     0x1008FF20\nXF86PowerDown                269025057     0x1008FF21\nXF86ContrastAdjust           269025058     0x1008FF22\nXF86RockerUp                 269025059     0x1008FF23\nXF86RockerDown               269025060     0x1008FF24\nXF86RockerEnter              269025061     0x1008FF25\nXF86Back                     269025062     0x1008FF26\nXF86Forward                  269025063     0x1008FF27\nXF86Stop                     269025064     0x1008FF28\nXF86Refresh                  269025065     0x1008FF29\nXF86PowerOff                 269025066     0x1008FF2A\nXF86WakeUp                   269025067     0x1008FF2B\nXF86Eject                    269025068     0x1008FF2C\nXF86ScreenSaver              269025069     0x1008FF2D\nXF86WWW                      269025070     0x1008FF2E\nXF86Sleep                    269025071     0x1008FF2F\nXF86Favorites                269025072     0x1008FF30\nXF86AudioPause               269025073     0x1008FF31\nXF86AudioMedia               269025074     0x1008FF32\nXF86MyComputer               269025075     0x1008FF33\nXF86VendorHome               269025076     0x1008FF34\nXF86LightBulb                269025077     0x1008FF35\nXF86Shop                     269025078     0x1008FF36\nXF86History                  269025079     0x1008FF37\nXF86OpenURL                  269025080     0x1008FF38\nXF86AddFavorite              269025081     0x1008FF39\nXF86HotLinks                 269025082     0x1008FF3A\nXF86BrightnessAdjust         269025083     0x1008FF3B\nXF86Finance                  269025084     0x1008FF3C\nXF86Community                269025085     0x1008FF3D\nXF86AudioRewind              269025086     0x1008FF3E\nXF86BackForward              269025087     0x1008FF3F\nXF86Launch0                  269025088     0x1008FF40\nXF86Launch1                  269025089     0x1008FF41\nXF86Launch2                  269025090     0x1008FF42\nXF86Launch3                  269025091     0x1008FF43\nXF86Launch4                  269025092     0x1008FF44\nXF86Launch5                  269025093     0x1008FF45\nXF86Launch6                  269025094     0x1008FF46\nXF86Launch7                  269025095     0x1008FF47\nXF86Launch8                  269025096     0x1008FF48\nXF86Launch9                  269025097     0x1008FF49\nXF86LaunchA                  269025098     0x1008FF4A\nXF86LaunchB                  269025099     0x1008FF4B\nXF86LaunchC                  269025100     0x1008FF4C\nXF86LaunchD                  269025101     0x1008FF4D\nXF86LaunchE                  269025102     0x1008FF4E\nXF86LaunchF                  269025103     0x1008FF4F\nXF86ApplicationLeft          269025104     0x1008FF50\nXF86ApplicationRight         269025105     0x1008FF51\nXF86Book                     269025106     0x1008FF52\nXF86CD                       269025107     0x1008FF53\nXF86Calculater               269025108     0x1008FF54\nXF86Clear                    269025109     0x1008FF55\nXF86Close                    269025110     0x1008FF56\nXF86Copy                     269025111     0x1008FF57\nXF86Cut                      269025112     0x1008FF58\nXF86Display                  269025113     0x1008FF59\nXF86DOS                      269025114     0x1008FF5A\nXF86Documents                269025115     0x1008FF5B\nXF86Excel                    269025116     0x1008FF5C\nXF86Explorer                 269025117     0x1008FF5D\nXF86Game                     269025118     0x1008FF5E\nXF86Go                       269025119     0x1008FF5F\nXF86iTouch                   269025120     0x1008FF60\nXF86LogOff                   269025121     0x1008FF61\nXF86Market                   269025122     0x1008FF62\nXF86Meeting                  269025123     0x1008FF63\nXF86MenuKB                   269025125     0x1008FF65\nXF86MenuPB                   269025126     0x1008FF66\nXF86MySites                  269025127     0x1008FF67\nXF86New                      269025128     0x1008FF68\nXF86News                     269025129     0x1008FF69\nXF86OfficeHome               269025130     0x1008FF6A\nXF86Open                     269025131     0x1008FF6B\nXF86Option                   269025132     0x1008FF6C\nXF86Paste                    269025133     0x1008FF6D\nXF86Phone                    269025134     0x1008FF6E\nXF86Q                        269025136     0x1008FF70\nXF86Reply                    269025138     0x1008FF72\nXF86Reload                   269025139     0x1008FF73\nXF86RotateWindows            269025140     0x1008FF74\nXF86RotationPB               269025141     0x1008FF75\nXF86RotationKB               269025142     0x1008FF76\nXF86Save                     269025143     0x1008FF77\nXF86ScrollUp                 269025144     0x1008FF78\nXF86ScrollDown               269025145     0x1008FF79\nXF86ScrollClick              269025146     0x1008FF7A\nXF86Send                     269025147     0x1008FF7B\nXF86Spell                    269025148     0x1008FF7C\nXF86SplitScreen              269025149     0x1008FF7D\nXF86Support                  269025150     0x1008FF7E\nXF86TaskPane                 269025151     0x1008FF7F\nXF86Terminal                 269025152     0x1008FF80\nXF86Tools                    269025153     0x1008FF81\nXF86Travel                   269025154     0x1008FF82\nXF86UserPB                   269025156     0x1008FF84\nXF86User1KB                  269025157     0x1008FF85\nXF86User2KB                  269025158     0x1008FF86\nXF86Video                    269025159     0x1008FF87\nXF86WheelButton              269025160     0x1008FF88\nXF86Word                     269025161     0x1008FF89\nXF86Xfer                     269025162     0x1008FF8A\nXF86ZoomIn                   269025163     0x1008FF8B\nXF86ZoomOut                  269025164     0x1008FF8C\nXF86Away                     269025165     0x1008FF8D\nXF86Messenger                269025166     0x1008FF8E\nXF86WebCam                   269025167     0x1008FF8F\nXF86MailForward              269025168     0x1008FF90\nXF86Pictures                 269025169     0x1008FF91\nXF86Music                    269025170     0x1008FF92\nXF86Battery                  269025171     0x1008FF93\nXF86Bluetooth                269025172     0x1008FF94\nXF86WLAN                     269025173     0x1008FF95\nXF86UWB                      269025174     0x1008FF96\nXF86AudioForward             269025175     0x1008FF97\nXF86AudioRepeat              269025176     0x1008FF98\nXF86AudioRandomPlay          269025177     0x1008FF99\nXF86Subtitle                 269025178     0x1008FF9A\nXF86AudioCycleTrack          269025179     0x1008FF9B\nXF86CycleAngle               269025180     0x1008FF9C\nXF86FrameBack                269025181     0x1008FF9D\nXF86FrameForward             269025182     0x1008FF9E\nXF86Time                     269025183     0x1008FF9F\nXF86Select                   269025184     0x1008FFA0\nXF86View                     269025185     0x1008FFA1\nXF86TopMenu                  269025186     0x1008FFA2\nXF86Red                      269025187     0x1008FFA3\nXF86Green                    269025188     0x1008FFA4\nXF86Yellow                   269025189     0x1008FFA5\nXF86Blue                     269025190     0x1008FFA6\nXF86Suspend                  269025191     0x1008FFA7\nXF86Hibernate                269025192     0x1008FFA8\nXF86TouchpadToggle           269025193     0x1008FFA9\nXF86TouchpadOn               269025200     0x1008FFB0\nXF86TouchpadOff              269025201     0x1008FFB1\nXF86AudioMicMute             269025202     0x1008FFB2\nXF86Keyboard                 269025203     0x1008FFB3\nXF86WWAN                     269025204     0x1008FFB4\nXF86RFKill                   269025205     0x1008FFB5\nXF86AudioPreset              269025206     0x1008FFB6\nXF86RotationLockToggle       269025207     0x1008FFB7\nXF86FullScreen               269025208     0x1008FFB8\n.CE\n.SH \"SEE ALSO\"\nbind(n), event(n)\n.SH KEYWORDS\nbind, binding, event, keysym\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/label.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH label n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nlabel \\- Create and manipulate 'label' non-interactive text or image widgets\n.SH SYNOPSIS\n\\fBlabel\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-disabledforeground\t\\-padx\n\\-activeforeground\t\\-font\t\\-pady\n\\-anchor\t\\-foreground\t\\-relief\n\\-background\t\\-highlightbackground\t\\-takefocus\n\\-bitmap\t\\-highlightcolor\t\\-text\n\\-borderwidth\t\\-highlightthickness\t\\-textvariable\n\\-compound\t\\-image\t\\-underline\n\\-cursor\t\\-justify\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-height height Height\nSpecifies a desired height for the label.\nIf an image or bitmap is being displayed in the label then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in lines of text.\nIf this option is not specified, the label's desired height is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.OP \\-state state State\nSpecifies one of three states for the label:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the button is displayed using the\n\\fB\\-foreground\\fR and \\fB\\-background\\fR options.  In active state\nthe label is displayed using the \\fB\\-activeforeground\\fR and\n\\fB\\-activebackground\\fR options.  In the disabled state the\n\\fB\\-disabledforeground\\fR and \\fB\\-background\\fR options determine how\nthe button is displayed.\n.OP \\-width width Width\nSpecifies a desired width for the label.\nIf an image or bitmap is being displayed in the label then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in characters.\nIf this option is not specified, the label's desired width is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBlabel\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a label widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the label such as its colors, font,\ntext, and initial relief.  The \\fBlabel\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA label is a widget that displays a textual string, bitmap or image.\nIf text is displayed, it must all be in a single font, but it\ncan occupy multiple lines on the screen (if it contains newlines\nor if wrapping occurs because of the \\fB\\-wraplength\\fR option) and\none of the characters may optionally be underlined using the\n\\fB\\-underline\\fR option.\nThe label can be manipulated in a few simple ways, such as\nchanging its relief or text, using the commands described below.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBlabel\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for label widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBlabel\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBlabel\\fR\ncommand.\n.SH BINDINGS\n.PP\nWhen a new label is created, it has no default event bindings:\nlabels are not intended to be interactive.\n.SH EXAMPLE\n.PP\n.CS\n# Make the widgets\n\\fBlabel\\fR .t -text \"This widget is at the top\"    -bg red\n\\fBlabel\\fR .b -text \"This widget is at the bottom\" -bg green\n\\fBlabel\\fR .l -text \"Left\\enHand\\enSide\"\n\\fBlabel\\fR .r -text \"Right\\enHand\\enSide\"\ntext .mid\n\\&.mid insert end \"This layout is like Java's BorderLayout\"\n# Lay them out\npack .t   -side top    -fill x\npack .b   -side bottom -fill x\npack .l   -side left   -fill y\npack .r   -side right  -fill y\npack .mid -expand 1    -fill both\n.CE\n.SH \"SEE ALSO\"\nlabelframe(n), button(n), ttk::label(n)\n.SH KEYWORDS\nlabel, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/labelframe.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH labelframe n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nlabelframe \\- Create and manipulate 'labelframe' labelled container widgets\n.SH SYNOPSIS\n\\fBlabelframe\\fI pathName\\fR ?\\fIoptions\\fR?\n.SO\n\\-borderwidth\t\\-highlightbackground\t\\-pady\n\\-cursor\t\\-highlightcolor\t\\-relief\n\\-font\t\\-highlightthickness\t\\-takefocus\n\\-foreground\t\\-padx\t\\-text\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-background background Background\nThis option is the same as the standard \\fB\\-background\\fR option\nexcept that its value may also be specified as an empty string.\nIn this case, the widget will display no background or border, and\nno colors will be consumed from its colormap for its background\nand border.\n.OP \\-class class Class\nSpecifies a class for the window.\nThis class will be used when querying the option database for\nthe window's other options, and it will also be used later for\nother purposes such as bindings.\nThe \\fB\\-class\\fR option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-colormap colormap Colormap\nSpecifies a colormap to use for the window.\nThe value may be either \\fBnew\\fR, in which case a new colormap is\ncreated for the window and its children, or the name of another\nwindow (which must be on the same screen and have the same visual\nas \\fIpathName\\fR), in which case the new window will use the colormap\nfrom the specified window.\nIf the \\fB\\-colormap\\fR option is not specified, the new window\nuses the same colormap as its parent.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-height height Height\nSpecifies the desired height for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.\nIf this option is negative or zero then the window will\nnot request any size at all.\n.OP \\-labelanchor labelAnchor LabelAnchor\nSpecifies where to place the label. A label is only displayed if the\n\\fB\\-text\\fR option is not the empty string.\nValid values for this option are (listing them clockwise)\n\\fBnw\\fR, \\fBn\\fR, \\fBne\\fR, \\fBen\\fR, \\fBe\\fR, \\fBes\\fR,\n\\fBse\\fR, \\fBs\\fR,\\fBsw\\fR, \\fBws\\fR, \\fBw\\fR and \\fBwn\\fR.\nThe default value is \\fBnw\\fR.\n.OP \\-labelwidget labelWidget LabelWidget\nSpecifies a widget to use as label. This overrides any \\fB\\-text\\fR\noption. The widget must exist before being used as \\fB\\-labelwidget\\fR\nand if it is not a descendant of this window, it will be raised\nabove it in the stacking order.\n.OP \\-visual visual Visual\nSpecifies visual information for the new window in any of the\nforms accepted by \\fBTk_GetVisual\\fR.\nIf this option is not specified, the new window will use the same\nvisual as its parent.\nThe \\fB\\-visual\\fR option may not be modified with the \\fBconfigure\\fR\nwidget command.\n.OP \\-width width Width\nSpecifies the desired width for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.\nIf this option is negative or zero then the window will\nnot request any size at all.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBlabelframe\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a labelframe widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the labelframe such as its background color\nand relief.  The \\fBlabelframe\\fR command returns the\npath name of the new window.\n.PP\nA labelframe is a simple widget.  Its primary purpose is to act as a\nspacer or container for complex window layouts.  It has the features\nof a \\fBframe\\fR plus the ability to display a label.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBlabelframe\\fR command creates a new Tcl command whose\nname is the same as the path name of the labelframe's window.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIPathName\\fR is the name of the command, which is the same as\nthe labelframe widget's path name.  \\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for frame widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBlabelframe\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBlabelframe\\fR\ncommand.\n.SH BINDINGS\n.PP\nWhen a new labelframe is created, it has no default event bindings:\nlabelframes are not intended to be interactive.\n.SH EXAMPLE\n.PP\nThis shows how to build part of a GUI for a hamburger vendor. The\n\\fBlabelframe\\fR widgets are used to organize the available choices by\nthe kinds of things that the choices are being made over.\n.PP\n.CS\ngrid [\\fBlabelframe\\fR .burger -text \"Burger\"] \\e\n     [\\fBlabelframe\\fR .bun    -text \"Bun\"] -sticky news\ngrid [\\fBlabelframe\\fR .cheese -text \"Cheese Option\"] \\e\n     [\\fBlabelframe\\fR .pickle -text \"Pickle Option\"] -sticky news\nforeach {type name val} {\n    burger Beef    beef\n    burger Lamb    lamb\n    burger Vegetarian beans\n\n    bun    Plain   white\n    bun    Sesame  seeds\n    bun    Wholemeal brown\n\n    cheese None    none\n    cheese Cheddar cheddar\n    cheese Edam    edam\n    cheese Brie    brie\n    cheese Gruy\\eu00e8re gruyere\n    cheese \"Monterey Jack\" jack\n\n    pickle None    none\n    pickle Gherkins gherkins\n    pickle Onions  onion\n    pickle Chili   chili\n} {\n    set w [radiobutton .$type.$val -text $name -anchor w \\e\n            -variable $type -value $val]\n    pack $w -side top -fill x\n}\nset burger beef\nset bun    white\nset cheese none\nset pickle none\n.CE\n.SH \"SEE ALSO\"\nframe(n), label(n), ttk::labelframe(n)\n.SH KEYWORDS\nlabelframe, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/listbox.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH listbox n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nlistbox \\- Create and manipulate 'listbox' item list widgets\n.SH SYNOPSIS\n\\fBlistbox\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-background\t\\-highlightbackground\t\\-selectforeground\n\\-borderwidth\t\\-highlightcolor\t\\-setgrid\n\\-cursor\t\\-highlightthickness\t\\-takefocus\n\\-disabledforeground\t\\-justify\t\\-xscrollcommand\n\\-exportselection\t\\-relief\t\\-yscrollcommand\n\\-font\t\\-selectbackground\n\\-foreground\t\\-selectborderwidth\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-activestyle activeStyle ActiveStyle\nSpecifies the style in which to draw the active element.  This must be\none of \\fBdotbox\\fR (show a focus ring around the active element),\n\\fBnone\\fR (no special indication of active element) or\n\\fBunderline\\fR (underline the active element).\nThe default is \\fBunderline\\fR on Windows, and \\fBdotbox\\fR elsewhere.\n.OP \\-height height Height\nSpecifies the desired height for the window, in lines.\nIf zero or less, then the desired height for the window is made just\nlarge enough to hold all the elements in the listbox.\n.OP \\-inactiveselectbackground inactiveSelectBackground Foreground\nSpecifies the background color to use for the selection when the window does\nnot have the input focus.  The option's value may be an empty string or have\nany of the forms accepted by \\fBTk_GetColor\\fR.  If empty then the value of the\n\\fB-selectbackground\\fR widget or item configuration option is used when the\nwindow does not have the focus.  The default value depends on the windowing\nsystem: it is non-empty on \\fBaqua\\fR and \\fBwin32\\fR, and an empty string on\n\\fBx11\\fR.\n.OP \\-inactiveselectforeground inactiveSelectForeground Background\nSpecifies the foreground color to use for the selection when the window does\nnot have the input focus.  The option's value may be an empty string or have\nany of the forms accepted by \\fBTk_GetColor\\fR.  This option is only relevant\nif the value of the \\fB-inactiveselectbackground\\fR option is non-empty, in\nwhich case, if the value of this option is an empty string then the value of\nthe \\fB-selectforeground\\fR widget configuration option is used when the window\ndoes not have the focus.  The default value depends on the windowing system: it\nis non-empty on \\fBaqua\\fR and \\fBwin32\\fR, and an empty string on \\fBx11\\fR.\n.OP \\-listvariable listVariable Variable\nSpecifies the name of a global variable.  The value of the variable is a list to\nbe displayed inside the widget; if the variable value changes then the\nwidget will automatically update itself to reflect the new value.  Attempts\nto assign a variable with an invalid list value to \\fB\\-listvariable\\fR\nwill cause an error.  Attempts to unset a variable in use as a\n\\fB\\-listvariable\\fR will fail but will not generate an error.\n.OP \\-selectmode selectMode SelectMode\nSpecifies one of several styles for manipulating the selection.\nThe value of the option may be arbitrary, but the default bindings\nexpect it to be either \\fBsingle\\fR, \\fBbrowse\\fR, \\fBmultiple\\fR,\nor \\fBextended\\fR;  the default value is \\fBbrowse\\fR.\n.OP \\-state state State\nSpecifies one of two states for the listbox:  \\fBnormal\\fR or \\fBdisabled\\fR.\nIf the listbox is disabled then items may not be inserted or deleted,\nitems are drawn in the \\fB\\-disabledforeground\\fR color, and selection\ncannot be modified and is not shown (though selection information is retained).\n.OP \\-width width Width\nSpecifies the desired width for the window in characters.\nIf the font does not have a uniform width then the width of the character\n.QW 0\nis used in translating from character units to screen units.\nIf zero or less, then the desired width for the window is made just\nlarge enough to hold all the elements in the listbox.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBlistbox\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a listbox widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the listbox such as its colors, font,\ntext, and relief.  The \\fBlistbox\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA listbox is a widget that displays a list of strings, one per line.\nWhen first created, a new listbox has no elements.\nElements may be added or deleted using widget commands described\nbelow.  In addition, one or more elements may be selected as described\nbelow.\nIf a listbox is exporting its selection (see \\fB\\-exportselection\\fR\noption), then it will observe the standard X11 protocols\nfor handling the selection.\nListbox selections are available as type \\fBSTRING\\fR;\nthe value of the selection will be the text of the selected elements, with\nnewlines separating the elements.\n.PP\nIt is not necessary for all the elements to be\ndisplayed in the listbox window at once;  commands described below\nmay be used to change the view in the window.  Listboxes allow\nscrolling in both directions using the standard \\fB\\-xscrollcommand\\fR\nand \\fB\\-yscrollcommand\\fR options.\nThey also support scanning, as described below.\n.SH \"INDICES\"\n.PP\nMany of the widget commands for listboxes take one or more indices\nas arguments.\nAn index specifies a particular element of the listbox, in any of\nthe following ways:\n.IP \\fInumber\\fR 12\nSpecifies the element as a numerical index, where 0 corresponds\nto the first element in the listbox.\n.IP \\fBactive\\fR 12\nIndicates the element that has the location cursor.  This element\nwill be displayed as specified by \\fB\\-activestyle\\fR when the listbox\nhas the keyboard focus, and it is specified with the \\fBactivate\\fR\nwidget command.\n.IP \\fBanchor\\fR 12\nIndicates the anchor point for the selection, which is set with the\n\\fBselection anchor\\fR widget command.\n.IP \\fBend\\fR 12\nIndicates the end of the listbox.\nFor most commands this refers to the last element in the listbox,\nbut for a few commands such as \\fBindex\\fR and \\fBinsert\\fR\nit refers to the element just after the last one.\n.IP \\fB@\\fIx\\fB,\\fIy\\fR 12\nIndicates the element that covers the point in the listbox window\nspecified by \\fIx\\fR and \\fIy\\fR (in pixel coordinates).  If no\nelement covers that point, then the closest element to that\npoint is used.\n.PP\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\nIn the widget command descriptions below, arguments named \\fIindex\\fR,\n\\fIfirst\\fR, and \\fIlast\\fR always contain text indices in one of\nthe above forms.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBlistbox\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for listbox widgets:\n.\\\" METHOD: activate\n.TP\n\\fIpathName \\fBactivate\\fI index\\fR\n.\nSets the active element to the one indicated by \\fIindex\\fR.\nIf \\fIindex\\fR is outside the range of elements in the listbox\nthen the closest element is activated.\nThe active element is drawn as specified by \\fB\\-activestyle\\fR when the\nwidget has the input focus, and its index may be retrieved with the\nindex \\fBactive\\fR.\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox\\fI index\\fR\n.\nReturns a list of four numbers describing the bounding box of\nthe text in the element given by \\fIindex\\fR.\nThe first two elements of the list give the x and y coordinates\nof the upper-left corner of the screen area covered by the text\n(specified in pixels relative to the widget) and the last two\nelements give the width and height of the area, in pixels.\nIf no part of the element given by \\fIindex\\fR is visible on the\nscreen,\nor if \\fIindex\\fR refers to a non-existent element,\nthen the result is an empty string;  if the element is\npartially visible, the result gives the full area of the element,\nincluding any parts that are not visible.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBlistbox\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBlistbox\\fR\ncommand.\n.\\\" METHOD: curselection\n.TP\n\\fIpathName \\fBcurselection\\fR\n.\nReturns a list containing the numerical indices of\nall of the elements in the listbox that are currently selected.\nIf there are no elements selected in the listbox then an empty\nstring is returned.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIfirst \\fR?\\fIlast\\fR?\n.\nDeletes one or more elements of the listbox.  \\fIFirst\\fR and \\fIlast\\fR\nare indices specifying the first and last elements in the range\nto delete.  If \\fIlast\\fR is not specified it defaults to\n\\fIfirst\\fR, i.e. a single element is deleted.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget \\fIfirst\\fR ?\\fIlast\\fR?\n.\nIf \\fIlast\\fR is omitted, returns the contents of the listbox\nelement indicated by \\fIfirst\\fR,\nor an empty string if \\fIfirst\\fR refers to a non-existent element.\nIf \\fIlast\\fR is specified, the command returns a list whose elements\nare all of the listbox elements between \\fIfirst\\fR and \\fIlast\\fR,\ninclusive.\nBoth \\fIfirst\\fR and \\fIlast\\fR may have any of the standard\nforms for indices.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex \\fIindex\\fR\n.\nReturns the integer index value that corresponds to \\fIindex\\fR.\nIf \\fIindex\\fR is \\fBend\\fR the return value is a count of the number\nof elements in the listbox (not the index of the last element).\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex \\fR?\\fIelement element ...\\fR?\n.\nInserts zero or more new elements in the list just before the\nelement given by \\fIindex\\fR.  If \\fIindex\\fR is specified as\n\\fBend\\fR then the new elements are added to the end of the\nlist.  Returns an empty string.\n.\\\" METHOD: itemcget\n.TP\n\\fIpathName \\fBitemcget \\fIindex option\\fR\n.\nReturns the current value of the item configuration option given\nby \\fIoption\\fR. \\fIOption\\fR may have any of the values accepted\nby the \\fBitemconfigure\\fR command.\n.\\\" METHOD: itemconfigure\n.TP\n\\fIpathName \\fBitemconfigure \\fIindex\\fR ?\\fIoption\\fR? ?\\fIvalue\\fR? ?\\fIoption value ...\\fR?\n.\nQuery or modify the configuration options of an item in the listbox.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for the item (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string. The following options\nare currently supported for items:\n.RS\n.\\\" OPTION: -background\n.TP\n\\fB\\-background \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the background color to use when displaying the\nitem. It may have any of the forms accepted by \\fBTk_GetColor\\fR.\n.\\\" OPTION: -foreground\n.TP\n\\fB\\-foreground \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the foreground color to use when displaying the\nitem. It may have any of the forms accepted by \\fBTk_GetColor\\fR.\n.\\\" OPTION: -selectbackground\n.TP\n\\fB\\-selectbackground \\fIcolor\\fR\n.\n\\fIcolor\\fR specifies the background color to use when displaying the\nitem while it is selected. It may have any of the forms accepted by\n\\fBTk_GetColor\\fR.\n.\\\" OPTION: -selectforeground\n.TP\n\\fB\\-selectforeground \\fIcolor\\fR\n.\n\\fIcolor\\fR specifies the foreground color to use when displaying the\nitem while it is selected. It may have any of the forms accepted by\n\\fBTk_GetColor\\fR.\n.RE\n.\\\" METHOD: nearest\n.TP\n\\fIpathName \\fBnearest \\fIy\\fR\n.\nGiven a y-coordinate within the listbox window, this command returns\nthe index of the (visible) listbox element nearest to that y-coordinate.\n.\\\" METHOD: scan\n.TP\n\\fIpathName \\fBscan\\fI option args\\fR\n.\nThis command is used to implement scanning on listboxes.  It has\ntwo forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBscan mark \\fIx y\\fR\n.\nRecords \\fIx\\fR and \\fIy\\fR and the current view in the listbox\nwindow;  used in conjunction with later \\fBscan dragto\\fR commands.\nTypically this command is associated with a mouse button press in\nthe widget.  It returns an empty string.\n.TP\n\\fIpathName \\fBscan dragto \\fIx y\\fR.\n.\nThis command computes the difference between its \\fIx\\fR and \\fIy\\fR\narguments and the \\fIx\\fR and \\fIy\\fR arguments to the last\n\\fBscan mark\\fR command for the widget.\nIt then adjusts the view by 10 times the\ndifference in coordinates.  This command is typically associated\nwith mouse motion events in the widget, to produce the effect of\ndragging the list at high speed through the window.  The return\nvalue is an empty string.\n.RE\n.\\\" METHOD: see\n.TP\n\\fIpathName \\fBsee \\fIindex\\fR\n.\nAdjust the view in the listbox so that the element given by \\fIindex\\fR\nis visible.\nIf the element is already visible then the command has no effect;\nif the element is near one edge of the window then the listbox\nscrolls to bring the element into view at the edge;  otherwise\nthe listbox scrolls to center the element.\n.\\\" METHOD: selection\n.TP\n\\fIpathName \\fBselection \\fIoption arg\\fR\n.\nThis command is used to adjust the selection within a listbox.  It\nhas several forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBselection anchor \\fIindex\\fR\n.\nSets the selection anchor to the element given by \\fIindex\\fR.\nIf \\fIindex\\fR refers to a non-existent element, then the closest\nelement is used.\nThe selection anchor is the end of the selection that is fixed\nwhile dragging out a selection with the mouse.\nThe index \\fBanchor\\fR may be used to refer to the anchor\nelement.\n.TP\n\\fIpathName \\fBselection clear \\fIfirst \\fR?\\fIlast\\fR?\n.\nIf any of the elements between \\fIfirst\\fR and \\fIlast\\fR\n(inclusive) are selected, they are deselected.\nThe selection state is not changed for elements outside\nthis range.\n.TP\n\\fIpathName \\fBselection includes \\fIindex\\fR\n.\nReturns 1 if the element indicated by \\fIindex\\fR is currently\nselected, 0 if it is not.\n.TP\n\\fIpathName \\fBselection set \\fIfirst \\fR?\\fIlast\\fR?\n.\nSelects all of the elements in the range between\n\\fIfirst\\fR and \\fIlast\\fR, inclusive, without affecting\nthe selection state of elements outside that range.\n.RE\n.\\\" METHOD: size\n.TP\n\\fIpathName \\fBsize\\fR\n.\nReturns a decimal string indicating the total number of elements\nin the listbox.\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fR?\\fIargs\\fR\n.\nThis command is used to query and change the horizontal position of the\ninformation in the widget's window.  It can take any of the following\nforms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1;  together they describe\nthe horizontal span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the listbox's text is off-screen to the left, the middle 40% is visible\nin the window, and 40% of the text is off-screen to the right.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview \\fIindex\\fR\n.\nAdjusts the view in the window so that the character position given by\n\\fIindex\\fR is displayed at the left edge of the window.\nCharacter positions are defined by the width of the character \\fB0\\fR.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that \\fIfraction\\fR of the\ntotal width of the listbox text is off-screen to the left.\n\\fIfraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR or an abbreviation\nof one of these.\nIf \\fIwhat\\fR is \\fBpages\\fR then the view adjusts by\n\\fInumber\\fR screenfuls.\nIf \\fInumber\\fR is negative then characters farther to the left\nbecome visible;  if it is positive then characters farther to the right\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts left or right by\n\\fInumber\\fR character units (the width of the \\fB0\\fR character)\non the display.\n.RE\n.\\\" METHOD: yview\n.TP\n\\fIpathName \\fByview \\fR?\\fIargs\\fR?\n.\nThis command is used to query and change the vertical position of the\ntext in the widget's window.\nIt can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fByview\\fR\n.\nReturns a list containing two elements, both of which are real fractions\nbetween 0 and 1.\nThe first element gives the position of the listbox element at the\ntop of the window, relative to the listbox as a whole (0.5 means\nit is halfway through the listbox, for example).\nThe second element gives the position of the listbox element just after\nthe last one in the window, relative to the listbox as a whole.\nThese are the same values passed to scrollbars via the \\fB\\-yscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fByview \\fIindex\\fR\n.\nAdjusts the view in the window so that the element given by\n\\fIindex\\fR is displayed at the top of the window.\n.TP\n\\fIpathName \\fByview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the element given by \\fIfraction\\fR\nappears at the top of the window.\n\\fIFraction\\fR is a fraction between 0 and 1;  0 indicates the first\nelement in the listbox, 0.33 indicates the element one-third the\nway through the listbox, and so on.\n.TP\n\\fIpathName \\fByview scroll \\fInumber what\\fR\n.\nThis command adjusts the view in the window up or down according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR.\nIf \\fIwhat\\fR is \\fBpages\\fR then\nthe view adjusts by \\fInumber\\fR screenfuls.\nIf \\fInumber\\fR is negative then earlier elements\nbecome visible;  if it is positive then later elements\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts up or down by\n\\fInumber\\fR lines.\n.RE\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for listboxes that give them\nMotif-like behavior.  Much of the behavior of a listbox is determined\nby its \\fB\\-selectmode\\fR option, which selects one of four ways\nof dealing with the selection.\n.PP\nIf the selection mode is \\fBsingle\\fR or \\fBbrowse\\fR, at most one\nelement can be selected in the listbox at once.\nIn both modes, clicking button 1 on an element selects\nit and deselects any other selected item.\nIn \\fBbrowse\\fR mode it is also possible to drag the selection\nwith button 1.\nOn button 1, the listbox will also take focus if it has a \\fBnormal\\fR\nstate.\n.PP\nIf the selection mode is \\fBmultiple\\fR or \\fBextended\\fR,\nany number of elements may be selected at once, including discontiguous\nranges.  In \\fBmultiple\\fR mode, clicking button 1 on an element\ntoggles its selection state without affecting any other elements.\nIn \\fBextended\\fR mode, pressing button 1 on an element selects\nit, deselects everything else, and sets the anchor to the element\nunder the mouse;  dragging the mouse with button 1\ndown extends the selection to include all the elements between\nthe anchor and the element under the mouse, inclusive.\n.PP\nMost people will probably want to use \\fBbrowse\\fR mode for\nsingle selections and \\fBextended\\fR mode for multiple selections;\nthe other modes appear to be useful only in special situations.\n.PP\nAny time the set of selected item(s) in the listbox is updated by the\nuser through the keyboard or mouse, the virtual event\n\\fB<<ListboxSelect>>\\fR will be generated. This virtual event will not\nbe generated when adjusting the selection with the \\fIpathName\n\\fBselection\\fR  command. It is easiest to bind to this event to be\nmade aware of any user changes to listbox selection.\n.PP\nIn addition to the above behavior, the following additional behavior\nis defined by the default bindings:\n.IP [1]\nIn \\fBextended\\fR mode, the selected range can be adjusted by pressing\nbutton 1 with the Shift key down:  this modifies the selection to\nconsist of the elements between the anchor and the element under\nthe mouse, inclusive.\nThe un-anchored end of this new selection can also be dragged with\nthe button down.\n.IP [2]\nIn \\fBextended\\fR mode, pressing button 1 with the Control key down\nstarts a toggle operation: the anchor is set to the element under\nthe mouse, and its selection state is reversed.  The selection state\nof other elements is not changed.\nIf the mouse is dragged with button 1 down, then the selection state\nof all elements between the anchor and the element under the mouse\nis set to match that of the anchor element;  the selection state of\nall other elements remains what it was before the toggle operation\nbegan.\n.IP [3]\nIf the mouse leaves the listbox window with button 1 down, the window\nscrolls away from the mouse, making information visible that used\nto be off-screen on the side of the mouse.\nThe scrolling continues until the mouse re-enters the window, the\nbutton is released, or the end of the listbox is reached.\n.IP [4]\nMouse button 2 may be used for scanning.\nIf it is pressed and dragged over the listbox, the contents of\nthe listbox drag at high speed in the direction the mouse moves.\n.IP [5]\nIf the Up or Down key is pressed, the location cursor (active\nelement) moves up or down one element.\nIf the selection mode is \\fBbrowse\\fR or \\fBextended\\fR then the\nnew active element is also selected and all other elements are\ndeselected.\nIn \\fBextended\\fR mode the new active element becomes the\nselection anchor.\n.IP [6]\nIn \\fBextended\\fR mode, Shift-Up and Shift-Down move the location\ncursor (active element) up or down one element and also extend\nthe selection to that element in a fashion similar to dragging\nwith mouse button 1.\n.IP [7]\nThe Left and Right keys scroll the listbox view left and right\nby the width of the character \\fB0\\fR.\nControl-Left and Control-Right scroll the listbox view left and\nright by the width of the window.\nControl-Prior and Control-Next also scroll left and right by\nthe width of the window.\n.IP [8]\nThe Prior and Next keys scroll the listbox view up and down\nby one page (the height of the window).\n.IP [9]\nThe Home and End keys scroll the listbox horizontally to\nthe left and right edges, respectively.\n.IP [10]\nControl-Home sets the location cursor to the first element in\nthe listbox, selects that element, and deselects everything else\nin the listbox.\n.IP [11]\nControl-End sets the location cursor to the last element in\nthe listbox, selects that element, and deselects everything else\nin the listbox.\n.IP [12]\nIn \\fBextended\\fR mode, Control-Shift-Home extends the selection\nto the first element in the listbox and Control-Shift-End extends\nthe selection to the last element.\n.IP [13]\nIn \\fBmultiple\\fR mode, Control-Shift-Home moves the location cursor\nto the first element in the listbox and Control-Shift-End moves\nthe location cursor to the last element.\n.IP [14]\nThe space and Select keys make a selection at the location cursor\n(active element) just as if mouse button 1 had been pressed over\nthis element.\n.IP [15]\nIn \\fBextended\\fR mode, Control-Shift-space and Shift-Select\nextend the selection to the active element just as if button 1\nhad been pressed with the Shift key down.\n.IP [16]\nIn \\fBextended\\fR mode, the Escape key cancels the most recent\nselection and restores all the elements in the selected range\nto their previous selection state.\n.IP [17]\nControl-/ selects everything in the widget, except in\n\\fBsingle\\fR and \\fBbrowse\\fR modes, in which case it selects\nthe active element and deselects everything else.\n.IP [18]\nControl-backslash deselects everything in the widget, except in\n\\fBbrowse\\fR mode where it has no effect.\n.IP [19]\nThe F16 key (labelled Copy on many Sun workstations) or Meta-w\ncopies the selection in the widget to the clipboard, if there is\na selection.\n.PP\nThe behavior of listboxes can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\nttk::treeview(n)\n.SH KEYWORDS\nlistbox, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/loadTk.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH \"Safe Tk\" n 8.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nsafe::loadTk \\- Load Tk into a safe interpreter.\n.SH SYNOPSIS\n\\fBsafe::loadTk \\fIchild\\fR ?\\fB\\-use\\fI windowId\\fR? ?\\fB\\-display\\fI displayName\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nSafe Tk is based on Safe Tcl, which provides a mechanism that allows\nrestricted and mediated access to auto-loading and packages for safe\ninterpreters.  Safe Tk adds the ability to configure the interpreter for safe\nTk operations and load Tk into safe interpreters.\n.PP\nThe \\fBsafe::loadTk\\fR command initializes the required data structures in\nthe named safe interpreter and then loads Tk into it.  The interpreter must\nhave been created with \\fBsafe::interpCreate\\fR or have been initialized\nwith \\fBsafe::interpInit\\fR.  The command returns the name of the safe\ninterpreter.  If \\fB\\-use\\fR is specified, the window identified by the\nspecified system dependent identifier \\fIwindowId\\fR is used to contain the\n.QW .\nwindow of the safe interpreter; it can be any valid id, eventually referencing\na window belonging to another application. As a convenience, if the window you\nplan to use is a Tk Window of the application you can use the window name\n(e.g.,\n.QW \\fB.x.y\\fR )\ninstead of its window Id (e.g., from \\fBwinfo id\\fI .x.y\\fR).\nWhen \\fB\\-use\\fR is not specified, a new toplevel window is created for the\n.QW .\nwindow of the safe interpreter. On X11 if you want the embedded window to use\nanother display than the default one, specify it with \\fB\\-display\\fR.  See\nthe \\fBSECURITY ISSUES\\fR section below for implementation details.\n.SH \"SECURITY ISSUES\"\n.PP\nPlease read the \\fBsafe\\fR manual page for Tcl to learn about the basic\nsecurity considerations for Safe Tcl.\n.PP\n\\fBsafe::loadTk\\fR adds the value of \\fBtk_library\\fR taken from the parent\ninterpreter to the virtual access path of the safe interpreter so that\nauto-loading will work in the safe interpreter.\n.PP\nTk initialization is now safe with respect to not trusting the child's state\nfor startup. \\fBsafe::loadTk\\fR registers the child's name so when the Tk\ninitialization (\\fBTk_SafeInit\\fR) is called and in turn calls the parent's\n\\fBsafe::InitTk\\fR it will return the desired \\fBargv\\fR equivalent\n(\\fB\\-use\\fI windowId\\fR, correct \\fB\\-display\\fR, etc.)\n.PP\nWhen \\fB\\-use\\fR is not used, the new toplevel created is specially decorated\nso the user is always aware that the user interface presented comes from a\npotentially unsafe code and can easily delete the corresponding interpreter.\n.PP\nOn X11, conflicting \\fB\\-use\\fR and \\fB\\-display\\fR are likely to generate a\nfatal X error.\n.SH \"SEE ALSO\"\nsafe(n), interp(n), library(n), load(n), package(n), source(n), unknown(n)\n.SH KEYWORDS\nalias, auto-loading, auto_mkindex, load, parent interpreter, safe\ninterpreter, child interpreter, source\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/lower.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH lower n 3.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nlower \\- Change a window's position in the stacking order\n.SH SYNOPSIS\n\\fBlower \\fIwindow \\fR?\\fIbelowThis\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nIf the \\fIbelowThis\\fR argument is omitted then the command lowers\n\\fIwindow\\fR so that it is below all of its siblings in the stacking\norder (it will be obscured by any siblings that overlap it and\nwill not obscure any siblings).\nIf \\fIbelowThis\\fR is specified then it must be the path name of\na window that is either a sibling of \\fIwindow\\fR or the descendant\nof a sibling of \\fIwindow\\fR.\nIn this case the \\fBlower\\fR command will insert\n\\fIwindow\\fR into the stacking order just below \\fIbelowThis\\fR\n(or the ancestor of \\fIbelowThis\\fR that is a sibling of \\fIwindow\\fR);\nthis could end up either raising or lowering \\fIwindow\\fR.\n.PP\nAll \\fBtoplevel\\fR windows may be restacked with respect to each\nother, whatever their relative path names, but the window manager is\nnot obligated to strictly honor requests to restack.\n.SH \"SEE ALSO\"\nraise\n.SH KEYWORDS\nlower, obscure, stacking order\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/man.macros",
    "content": ".\\\" The -*- nroff -*- definitions below are for supplemental macros used\n.\\\" in Tcl/Tk manual entries.\n.\\\"\n.\\\" .AP type name in/out ?indent?\n.\\\"\tStart paragraph describing an argument to a library procedure.\n.\\\"\ttype is type of argument (int, etc.), in/out is either \"in\", \"out\",\n.\\\"\tor \"in/out\" to describe whether procedure reads or modifies arg,\n.\\\"\tand indent is equivalent to second arg of .IP (shouldn't ever be\n.\\\"\tneeded;  use .AS below instead)\n.\\\"\n.\\\" .AS ?type? ?name?\n.\\\"\tGive maximum sizes of arguments for setting tab stops.  Type and\n.\\\"\tname are examples of largest possible arguments that will be passed\n.\\\"\tto .AP later.  If args are omitted, default tab stops are used.\n.\\\"\n.\\\" .BS\n.\\\"\tStart box enclosure.  From here until next .BE, everything will be\n.\\\"\tenclosed in one large box.\n.\\\"\n.\\\" .BE\n.\\\"\tEnd of box enclosure.\n.\\\"\n.\\\" .CS\n.\\\"\tBegin code excerpt.\n.\\\"\n.\\\" .CE\n.\\\"\tEnd code excerpt.\n.\\\"\n.\\\" .VS ?version? ?br?\n.\\\"\tBegin vertical sidebar, for use in marking newly-changed parts\n.\\\"\tof man pages.  The first argument is ignored and used for recording\n.\\\"\tthe version when the .VS was added, so that the sidebars can be\n.\\\"\tfound and removed when they reach a certain age.  If another argument\n.\\\"\tis present, then a line break is forced before starting the sidebar.\n.\\\"\n.\\\" .VE\n.\\\"\tEnd of vertical sidebar.\n.\\\"\n.\\\" .DS\n.\\\"\tBegin an indented unfilled display.\n.\\\"\n.\\\" .DE\n.\\\"\tEnd of indented unfilled display.\n.\\\"\n.\\\" .SO ?manpage?\n.\\\"\tStart of list of standard options for a Tk widget. The manpage\n.\\\"\targument defines where to look up the standard options; if\n.\\\"\tomitted, defaults to \"options\". The options follow on successive\n.\\\"\tlines, in three columns separated by tabs.\n.\\\"\n.\\\" .SE\n.\\\"\tEnd of list of standard options for a Tk widget.\n.\\\"\n.\\\" .OP cmdName dbName dbClass\n.\\\"\tStart of description of a specific option.  cmdName gives the\n.\\\"\toption's name as specified in the class command, dbName gives\n.\\\"\tthe option's name in the option database, and dbClass gives\n.\\\"\tthe option's class in the option database.\n.\\\"\n.\\\" .UL arg1 arg2\n.\\\"\tPrint arg1 underlined, then print arg2 normally.\n.\\\"\n.\\\" .QW arg1 ?arg2?\n.\\\"\tPrint arg1 in quotes, then arg2 normally (for trailing punctuation).\n.\\\"\n.\\\" .PQ arg1 ?arg2?\n.\\\"\tPrint an open parenthesis, arg1 in quotes, then arg2 normally\n.\\\"\t(for trailing punctuation) and then a closing parenthesis.\n.\\\"\n.\\\"\t# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.\n.if t .wh -1.3i ^B\n.nr ^l \\n(.l\n.ad b\n.\\\"\t# Start an argument description\n.de AP\n.ie !\"\\\\$4\"\" .TP \\\\$4\n.el \\{\\\n.   ie !\"\\\\$2\"\" .TP \\\\n()Cu\n.   el          .TP 15\n.\\}\n.ta \\\\n()Au \\\\n()Bu\n.ie !\"\\\\$3\"\" \\{\\\n\\&\\\\$1 \\\\fI\\\\$2\\\\fP (\\\\$3)\n.\\\".b\n.\\}\n.el \\{\\\n.br\n.ie !\"\\\\$2\"\" \\{\\\n\\&\\\\$1\t\\\\fI\\\\$2\\\\fP\n.\\}\n.el \\{\\\n\\&\\\\fI\\\\$1\\\\fP\n.\\}\n.\\}\n..\n.\\\"\t# define tabbing values for .AP\n.de AS\n.nr )A 10n\n.if !\"\\\\$1\"\" .nr )A \\\\w'\\\\$1'u+3n\n.nr )B \\\\n()Au+15n\n.\\\"\n.if !\"\\\\$2\"\" .nr )B \\\\w'\\\\$2'u+\\\\n()Au+3n\n.nr )C \\\\n()Bu+\\\\w'(in/out)'u+2n\n..\n.AS Tcl_Interp Tcl_CreateInterp in/out\n.\\\"\t# BS - start boxed text\n.\\\"\t# ^y = starting y location\n.\\\"\t# ^b = 1\n.de BS\n.br\n.mk ^y\n.nr ^b 1u\n.if n .nf\n.if n .ti 0\n.if n \\l'\\\\n(.lu\\(ul'\n.if n .fi\n..\n.\\\"\t# BE - end boxed text (draw box now)\n.de BE\n.nf\n.ti 0\n.mk ^t\n.ie n \\l'\\\\n(^lu\\(ul'\n.el \\{\\\n.\\\"\tDraw four-sided box normally, but don't draw top of\n.\\\"\tbox if the box started on an earlier page.\n.ie !\\\\n(^b-1 \\{\\\n\\h'-1.5n'\\L'|\\\\n(^yu-1v'\\l'\\\\n(^lu+3n\\(ul'\\L'\\\\n(^tu+1v-\\\\n(^yu'\\l'|0u-1.5n\\(ul'\n.\\}\n.el \\}\\\n\\h'-1.5n'\\L'|\\\\n(^yu-1v'\\h'\\\\n(^lu+3n'\\L'\\\\n(^tu+1v-\\\\n(^yu'\\l'|0u-1.5n\\(ul'\n.\\}\n.\\}\n.fi\n.br\n.nr ^b 0\n..\n.\\\"\t# VS - start vertical sidebar\n.\\\"\t# ^Y = starting y location\n.\\\"\t# ^v = 1 (for troff;  for nroff this doesn't matter)\n.de VS\n.if !\"\\\\$2\"\" .br\n.mk ^Y\n.ie n 'mc \\s12\\(br\\s0\n.el .nr ^v 1u\n..\n.\\\"\t# VE - end of vertical sidebar\n.de VE\n.ie n 'mc\n.el \\{\\\n.ev 2\n.nf\n.ti 0\n.mk ^t\n\\h'|\\\\n(^lu+3n'\\L'|\\\\n(^Yu-1v\\(bv'\\v'\\\\n(^tu+1v-\\\\n(^Yu'\\h'-|\\\\n(^lu+3n'\n.sp -1\n.fi\n.ev\n.\\}\n.nr ^v 0\n..\n.\\\"\t# Special macro to handle page bottom:  finish off current\n.\\\"\t# box/sidebar if in box/sidebar mode, then invoked standard\n.\\\"\t# page bottom macro.\n.de ^B\n.ev 2\n'ti 0\n'nf\n.mk ^t\n.if \\\\n(^b \\{\\\n.\\\"\tDraw three-sided box if this is the box's first page,\n.\\\"\tdraw two sides but no top otherwise.\n.ie !\\\\n(^b-1 \\h'-1.5n'\\L'|\\\\n(^yu-1v'\\l'\\\\n(^lu+3n\\(ul'\\L'\\\\n(^tu+1v-\\\\n(^yu'\\h'|0u'\\c\n.el \\h'-1.5n'\\L'|\\\\n(^yu-1v'\\h'\\\\n(^lu+3n'\\L'\\\\n(^tu+1v-\\\\n(^yu'\\h'|0u'\\c\n.\\}\n.if \\\\n(^v \\{\\\n.nr ^x \\\\n(^tu+1v-\\\\n(^Yu\n\\kx\\h'-\\\\nxu'\\h'|\\\\n(^lu+3n'\\ky\\L'-\\\\n(^xu'\\v'\\\\n(^xu'\\h'|0u'\\c\n.\\}\n.bp\n'fi\n.ev\n.if \\\\n(^b \\{\\\n.mk ^y\n.nr ^b 2\n.\\}\n.if \\\\n(^v \\{\\\n.mk ^Y\n.\\}\n..\n.\\\"\t# DS - begin display\n.de DS\n.RS\n.nf\n.sp\n..\n.\\\"\t# DE - end display\n.de DE\n.fi\n.RE\n.sp\n..\n.\\\"\t# SO - start of list of standard options\n.de SO\n'ie '\\\\$1'' .ds So \\\\fBoptions\\\\fR\n'el .ds So \\\\fB\\\\$1\\\\fR\n.SH \"STANDARD OPTIONS\"\n.LP\n.nf\n.ta 5.5c 11c\n.ft B\n..\n.\\\"\t# SE - end of list of standard options\n.de SE\n.fi\n.ft R\n.LP\nSee the \\\\*(So manual entry for details on the standard options.\n..\n.\\\"\t# OP - start of full description for a single option\n.de OP\n.LP\n.nf\n.ta 4c\nCommand-Line Name:\t\\\\fB\\\\$1\\\\fR\nDatabase Name:\t\\\\fB\\\\$2\\\\fR\nDatabase Class:\t\\\\fB\\\\$3\\\\fR\n.fi\n.IP\n..\n.\\\"\t# CS - begin code excerpt\n.de CS\n.RS\n.nf\n.ta .25i .5i .75i 1i\n..\n.\\\"\t# CE - end code excerpt\n.de CE\n.fi\n.RE\n..\n.\\\"\t# UL - underline word\n.de UL\n\\\\$1\\l'|0\\(ul'\\\\$2\n..\n.\\\"\t# QW - apply quotation marks to word\n.de QW\n.ie '\\\\*(lq'\"' ``\\\\$1''\\\\$2\n.\\\"\" fix emacs highlighting\n.el \\\\*(lq\\\\$1\\\\*(rq\\\\$2\n..\n.\\\"\t# PQ - apply parens and quotation marks to word\n.de PQ\n.ie '\\\\*(lq'\"' (``\\\\$1''\\\\$2)\\\\$3\n.\\\"\" fix emacs highlighting\n.el (\\\\*(lq\\\\$1\\\\*(rq\\\\$2)\\\\$3\n..\n.\\\"\t# QR - quoted range\n.de QR\n.ie '\\\\*(lq'\"' ``\\\\$1''\\\\-``\\\\$2''\\\\$3\n.\\\"\" fix emacs highlighting\n.el \\\\*(lq\\\\$1\\\\*(rq\\\\-\\\\*(lq\\\\$2\\\\*(rq\\\\$3\n..\n.\\\"\t# MT - \"empty\" string\n.de MT\n.QW \"\"\n..\n"
  },
  {
    "path": "doc/menu.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH menu n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nmenu, tk_menuSetFocus \\- Create and manipulate 'menu' widgets and menubars\n.SH SYNOPSIS\n.nf\n\\fBmenu\\fI pathName \\fR?\\fIoptions\\fR?\n\\fBtk_menuSetFocus\\fI pathName\\fR\n.fi\n.SO\n\\-activebackground\t\\-borderwidth\t\\-foreground\n\\-activeborderwidth\t\\-cursor\t\\-relief\n\\-activeforeground\t\\-disabledforeground\t\\-takefocus\n\\-background\t\\-font\t\\-activerelief\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-postcommand postCommand Command\nIf this option is specified then it provides a Tcl command to execute\neach time the menu is posted.  The command is invoked by the \\fBpost\\fR\nwidget command before posting the menu. Note that in Tk 8.0 on Macintosh\nand Windows, all post-commands in a system of menus are executed before any\nof those menus are posted.\nThis is due to the limitations in the individual platforms' menu managers.\n.OP \\-selectcolor selectColor Background\nFor menu entries that are check buttons or radio buttons, this option\nspecifies the color to display in the indicator when the check button\nor radio button is selected.\n.OP \\-tearoff tearOff TearOff\nThis option must have a proper boolean value (default is false),\nwhich specifies whether or not the menu should include a tear-off\nentry at the top.  If so, it will exist as entry 0 of the menu and\nthe other entries will number starting at 1.  The default menu\nbindings arrange for the menu to be torn off when the tear-off entry\nis invoked.\nThis option is ignored under Aqua/macOS, where menus cannot\nbe torn off.\n.OP \\-tearoffcommand tearOffCommand TearOffCommand\nIf this option has a non-empty value, then it specifies a Tcl command\nto invoke whenever the menu is torn off.  The actual command will\nconsist of the value of this option, followed by a space, followed\nby the name of the menu window, followed by a space, followed by\nthe name of the name of the torn off menu window.  For example, if\nthe option's value is\n.QW \"\\fBa b\\fR\"\nand menu \\fB.x.y\\fR is torn off to\ncreate a new menu \\fB.x.tearoff1\\fR, then the command\n.QW \"\\fBa b .x.y .x.tearoff1\\fR\"\nwill be invoked.\nThis option is ignored under Aqua/macOS, where menus cannot\nbe torn off.\n.OP \\-title title Title\nThe string will be used to title the window created when this menu is\ntorn off. If the title is NULL, then the window will have the title\nof the menubutton or the text of the cascade item from which this menu\nwas invoked.\n.OP \\-type type Type\nThis option can be one of \\fBmenubar\\fR, \\fBtearoff\\fR, or\n\\fBnormal\\fR, and is set when the menu is created. While the string\nreturned by the configuration database will change if this option is\nchanged, this does not affect the menu widget's behavior. This is used\nby the cloning mechanism and is not normally set outside of the Tk\nlibrary.\n.BE\n.SH INTRODUCTION\n.PP\nThe \\fBmenu\\fR command creates a new top-level window (given\nby the \\fIpathName\\fR argument) and makes it into a menu widget.\nThat menu widget can either be used as a pop-up window or applied to a\n\\fBtoplevel\\fR (with its \\fB\\-menu\\fR option) to make it into the menubar for\nthat toplevel.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the menu such as its colors and font.\nThe \\fBmenu\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA menu is a widget that displays a collection of one-line entries arranged\nin one or more columns.  There exist several different types of entries,\neach with different properties.  Entries of different types may be\ncombined in a single menu.  Menu entries are not the same as\nentry widgets.  In fact, menu entries are not even distinct widgets;\nthe entire menu is one widget.\n.PP\nMenu entries are displayed with up to three separate fields.\nThe main field is a label in the form of a text string,\na bitmap, or an image, controlled by the \\fB\\-label\\fR,\n\\fB\\-bitmap\\fR, and \\fB\\-image\\fR options for the entry.\nIf the  \\fB\\-accelerator\\fR option is specified for an entry then a second\ntextual field is displayed to the right of the label.  The accelerator\ntypically describes a keystroke sequence that may be used in the\napplication to cause the same result as invoking the menu entry.\nThis is a display option, it does not actually set the corresponding\nbinding (which can be achieved using the \\fBbind\\fR command).\nThe third field is an \\fIindicator\\fR.  The indicator is present only for\ncheckbutton or radiobutton entries.  It indicates whether the entry\nis selected or not, and is displayed to the left of the entry's\nstring.\n.PP\nIn normal use, an entry becomes active (displays itself differently)\nwhenever the mouse pointer is over the entry.  If a mouse\nbutton is released over the entry then the entry is \\fIinvoked\\fR.\nThe effect of invocation is different for each type of entry;\nthese effects are described below in the sections on individual\nentries.\n.PP\nEntries may be \\fIdisabled\\fR, which causes their labels\nand accelerators to be displayed\nwith dimmer colors.\nThe default menu bindings will not allow\na disabled entry to be activated or invoked.\nDisabled entries may be re-enabled, at which point it becomes\npossible to activate and invoke them again.\n.PP\nWhenever a menu's active entry is changed, a <<MenuSelect>> virtual\nevent is send to the menu. The active item can then be queried from\nthe menu, and an action can be taken, such as setting\ncontext-sensitive help text for the entry.\n.SH \"TYPES OF ENTRIES\"\n.SS \"COMMAND ENTRIES\"\n.PP\nThe most common kind of menu entry is a command entry, which\nbehaves much like a button widget.  When a command entry is\ninvoked, a Tcl command is executed.  The Tcl\ncommand is specified with the \\fB\\-command\\fR option.\n.SS \"SEPARATOR ENTRIES\"\n.PP\nA separator is an entry that is displayed as a horizontal dividing\nline.  A separator may not be activated or invoked, and it has\nno behavior other than its display appearance.\n.SS \"CHECKBUTTON ENTRIES\"\n.PP\nA checkbutton menu entry behaves much like a checkbutton widget.\nWhen it is invoked it toggles back and forth between the selected\nand deselected states.  When the entry is selected, a particular\nvalue is stored in a particular global variable (as determined by\nthe \\fB\\-onvalue\\fR and \\fB\\-variable\\fR options for the entry);  when\nthe entry is deselected another value (determined by the\n\\fB\\-offvalue\\fR option) is stored in the global variable.\nAn indicator box is displayed to the left of the label in a checkbutton\nentry.  If the entry is selected then the indicator's center is displayed\nin the color given by the \\fB\\-selectcolor\\fR option for the entry;\notherwise the indicator's center is displayed in the background color for\nthe menu.  If a \\fB\\-command\\fR option is specified for a checkbutton\nentry, then its value is evaluated as a Tcl command each time the entry\nis invoked;  this happens after toggling the entry's\nselected state.\n.SS \"RADIOBUTTON ENTRIES\"\n.PP\nA radiobutton menu entry behaves much like a radiobutton widget.\nRadiobutton entries are organized in groups of which only one\nentry may be selected at a time.  Whenever a particular entry\nbecomes selected it stores a particular value into a particular\nglobal variable (as determined by the \\fB\\-value\\fR and\n\\fB\\-variable\\fR options for the entry).  This action\ncauses any previously-selected entry in the same group\nto deselect itself.\nOnce an entry has become selected, any change to the entry's\nassociated variable will cause the entry to deselect itself.\nGrouping of radiobutton entries is determined by their\nassociated variables:  if two entries have the same associated\nvariable then they are in the same group.\nAn indicator diamond is displayed to the left of the label in each\nradiobutton entry.  If the entry is selected then the indicator's\ncenter is displayed in the color given by the \\fB\\-selectcolor\\fR option\nfor the entry;\notherwise the indicator's center is displayed in the background color for\nthe menu.  If a \\fB\\-command\\fR option is specified for a radiobutton\nentry, then its value is evaluated as a Tcl command each time the entry\nis invoked;  this happens after selecting the entry.\n.SS \"CASCADE ENTRIES\"\n.PP\nA cascade entry is one with an associated menu (determined\nby the \\fB\\-menu\\fR option).  Cascade entries allow the construction\nof cascading menus.\nThe \\fBpostcascade\\fR widget command can be used to post and unpost\nthe associated menu just next to of the cascade entry.\nThe associated menu must be a child of the menu containing\nthe cascade entry (this is needed in order for menu traversal to\nwork correctly).\n.PP\nA cascade entry posts its associated menu by invoking a\nTcl command of the form\n.CS\n\\fImenu\\fB post \\fIx y\\fR\n.CE\nwhere \\fImenu\\fR is the path name of the associated menu, and \\fIx\\fR\nand \\fIy\\fR are the root-window coordinates of the upper-right\ncorner of the cascade entry.\nOn Unix, the lower-level menu is unposted by executing a Tcl command with\nthe form\n.CS\n\\fImenu\\fB unpost\\fR\n.CE\nwhere \\fImenu\\fR is the name of the associated menu.\nOn other platforms, the platform's native code takes care of unposting the\nmenu.\n.PP\nIf a \\fB\\-command\\fR option is specified for a cascade entry then it is\nevaluated as a Tcl command whenever the entry is invoked. This is not\nsupported on Windows.\n.SS \"TEAR-OFF ENTRIES\"\n.PP\nA tear-off entry appears at the top of the menu if enabled with the\n\\fB\\-tearoff\\fR option.  It is not like other menu entries in that\nit cannot be created with the \\fBadd\\fR widget command and\ncannot be deleted with the \\fBdelete\\fR widget command.\nWhen a tear-off entry is created it appears as a dashed line at\nthe top of the menu.  Under the default bindings, invoking the\ntear-off entry causes a torn-off copy to be made of the menu and\nall of its submenus.\n.SH \"MENUBARS\"\n.PP\nAny menu can be set as a menubar for a toplevel window (see\n\\fBtoplevel\\fR command for syntax). On the Macintosh, whenever the\ntoplevel is in front, this menu's cascade items will appear in the\nmenubar across the top of the main screen. On Windows and Unix, this\nmenu's items will be displayed in a menubar across the top of the\nwindow. These menus will behave according to the interface guidelines\nof their platforms. In particular, since macOS requires that a\nmenubar always be displayed for the active app, if no menu is assigned\nby a \\fBconfigure -menu\\fR for a certain toplevel then a standard default\nmenu will be displayed whenever that toplevel has focus.\n\nFor every menu set as a menubar, a clone menu is\nmade. See the \\fBCLONES\\fR section for more information.\n.PP\nAs noted, menubars may behave differently on different platforms.  One\nexample of this concerns the handling of checkbuttons and radiobuttons\nwithin the menu.  While it is permitted to put these menu elements on\nmenubars, they may not be drawn with indicators on some platforms, due\nto system restrictions.\n.SS \"SPECIAL MENUS IN MENUBARS\"\n.PP\nCertain menus in a menubar will be treated specially.  On the Macintosh,\naccess to the special Application, Window and Help menus is provided. On\nWindows, access to the Windows System menu in each window is provided.\nOn X Windows, a special right-justified help menu may be provided if\nMotif menu compatibility is enabled. In all cases, these menus must be\ncreated with the command name of the menubar menu concatenated with the\nspecial name. So for a menubar named .menubar, on the Macintosh, the\nspecial menus would be .menubar.apple, .menubar.window and .menubar.help;\non Windows, the special menu would be .menubar.system; on X Windows,\nthe help menu would be .menubar.help.\n.PP\nWhen Tk sees a .menubar.apple menu as the first menu in a menubar on the\nMacintosh, that menu's contents make up the first items of the\nApplication menu whenever the window containing the menubar is in front.\nAfter all of the Tk-defined items, the menu will have a separator,\nfollowed by all standard Application menu items.\nSuch a .apple menu must be present in a menu when that menu is first\nconfigured as a toplevel's menubar, otherwise a default application menu\n(hidden from Tk) will be inserted into the menubar at that time and\nsubsequent addition of a .apple menu will no longer result in it\nbecoming the Application menu.\n.PP\nWhen Tk sees a .menubar.window menu on the Macintosh, the menu's\ncontents are inserted into the standard Window menu of the user's\nmenubar whenever the window's menubar is in front. The first items in\nthe menu are provided by macOS, and the names of the current\ntoplevels are automatically appended after all the Tk-defined items and\na separator. The Window menu on the Mac also allows toggling the\nwindow into a fullscreen state, and managing a tabbed window interface\n(multiple windows grouped into a single window) if supported by that\nversion of the operating system.\n.PP\nWhen Tk sees a .menubar.help menu on the Macintosh, the menu's contents\nare appended to the standard Help menu of the user's menubar whenever\nthe window's menubar is in front. The first items in the menu\nare provided by macOS.\n.PP\nWhen Tk sees a System menu on Windows, its items are appended to the\nsystem menu that the menubar is attached to. This menu is tied to the\napplication icon and can be invoked with the mouse or by typing\nAlt+Spacebar.  Due to limitations in the Windows API, any font changes,\ncolors, images, bitmaps, or tearoff images will not appear in the\nsystem menu.\n.PP\nWhen Tk sees a Help menu on X Windows and Motif menu compatibility is\nenabled the menu is moved to be last in the menubar and is right\njustified. Motif menu compatibility is enabled by setting the Tk option\n\\fB*Menu.useMotifHelp\\fR to true.\n.SH \"CLONES\"\n.PP\nWhen a menu is set as a menubar for a toplevel window, or when a menu\nis torn off, a clone of the menu is made. This clone is a menu widget\nin its own right, but it is a child of the original. Changes in the\nconfiguration of the original are reflected in the\nclone. Additionally, any cascades that are pointed to are also cloned\nso that menu traversal will work right. Clones are destroyed when\neither the tearoff or menubar goes away, or when the original menu is\ndestroyed.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBmenu\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.\n.PP\nMany of the widget commands for a menu take as one argument an\nindicator of which entry of the menu to operate on. These\nindicators are called \\fIindex\\fRes and may be specified in\nany of the following forms:\n.IP \\fBactive\\fR 12\nIndicates the entry that is currently active.  If no entry is\nactive then this form is equivalent to \\fB{}\\fR.  This form may\nnot be abbreviated.\n.IP \\fBend\\fR 12\nIndicates the bottommost entry in the menu.  If there are no\nentries in the menu then this form is equivalent to \\fB{}\\fR.\nThis form may not be abbreviated.\n.IP \\fBlast\\fR 12\nSame as \\fBend\\fR.\n.IP \\fB{}\\fR 12\nIndicates\n.QW \"no entry at all\" ;\nthis is used most commonly with\nthe \\fBactivate\\fR option to deactivate all the entries in the\nmenu.  In most cases the specification of \\fB{}\\fR causes\nnothing to happen in the widget command.\n.IP \\fB@\\fIx\\fB,\\fIy\\fR 12\nIndicates the entry that covers the point in the menu's window specified\nby \\fIx\\fR and \\fIy\\fR (in pixel coordinates).\nIf no entry covers that point, then this form is equivalent to \\fB{}\\fR.\nIf only a single number is specified, it is treated as the y-coordinate.\n.IP \\fInumber\\fR 12\nSpecifies the entry numerically, where 0 corresponds\nto the top-most entry of the menu, 1 to the entry below it, and\nso on.\n.IP \\fIid\\fR 12\nIf the index does not satisfy one of the above forms then the menu is\nsearched for an entry with the specified id.\n.IP \\fIpattern\\fR 12\nIf all of the above methods for finding an entry fail, this\nform is used.  \\fIPattern\\fR is pattern-matched against the label of\neach entry in the menu, in order from the top down, until a\nmatching entry is found.  The rules of \\fBstring match\\fR\nare used.\n.PP\nIf the index could match more than one of the above forms, then\nthe form earlier in the above list takes precedence.\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.PP\nThe following widget commands are possible for menu widgets:\n.\\\" METHOD: activate\n.TP\n\\fIpathName \\fBactivate \\fIindex\\fR\n.\nChange the state of the entry indicated by \\fIindex\\fR to \\fBactive\\fR\nand redisplay it using its active colors.\nAny previously-active entry is deactivated.  If \\fIindex\\fR\nis specified as \\fB{}\\fR, or if the specified entry is\ndisabled, then the menu ends up with no active entry.\nReturns an empty string.\n.\\\" METHOD: add\n.TP\n\\fIpathName \\fBadd \\fItype \\fR?\\fIid\\fR? ?\\fIoption value option value ...\\fR?\n.\nAdd a new entry to the bottom of the menu.  The new entry's type\nis given by \\fItype\\fR and must be one of \\fBcascade\\fR,\n\\fBcheckbutton\\fR, \\fBcommand\\fR, \\fBradiobutton\\fR, or \\fBseparator\\fR,\nor a unique abbreviation of one of the above.\nIf the \\fIid\\fR argument is specified, it is used as the entry identifier;\n\\fIid\\fR must not already exist in the menu. Otherwise, a new unique\nidentifier is generated.\nIf additional arguments are present, they specify the options listed in the\n\\fBMENU ENTRY OPTIONS\\fR section below.\nThe \\fBadd\\fR widget command returns the id of the new entry.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBmenu\\fR\ncommand.\n.\\\" METHOD: clone\n.TP\n\\fIpathName \\fBclone \\fInewPathname\\fR ?\\fIcloneType\\fR?\n.\nMakes a clone of the current menu named \\fInewPathName\\fR. This clone\nis a menu in its own right, but any changes to the clone are\npropagated to the original menu and vice versa. \\fIcloneType\\fR can be\n\\fBnormal\\fR, \\fBmenubar\\fR, or \\fBtearoff\\fR. Should not normally be\ncalled outside of the Tk library. See the \\fBCLONES\\fR section for\nmore information.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBmenu\\fR\ncommand.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIindex1\\fR ?\\fIindex2\\fR?\n.\nDelete all of the menu entries between \\fIindex1\\fR and\n\\fIindex2\\fR inclusive.\nIf \\fIindex2\\fR is omitted then it defaults to \\fIindex1\\fR.\nAttempts to delete a tear-off menu entry are ignored (instead, you\nshould change the \\fB\\-tearoff\\fR option to remove the tear-off entry).\n.\\\" METHOD: entrycget\n.TP\n\\fIpathName \\fBentrycget \\fIindex option\\fR\n.\nReturns the current value of a configuration option for\nthe entry given by \\fIindex\\fR.\n\\fIOption\\fR may have any of the names described in the\n\\fBMENU ENTRY OPTIONS\\fR section below.\n.\\\" METHOD: entryconfigure\n.TP\n\\fIpathName \\fBentryconfigure \\fIindex \\fR?\\fIoptions...\\fR?\n.\nThis command is similar to the \\fBconfigure\\fR command, except that\nit applies to the options for an individual entry, whereas \\fBconfigure\\fR\napplies to the options for the menu as a whole.\n\\fIOptions\\fR may have any of the values described in the\n\\fBMENU ENTRY OPTIONS\\fR\nsection below.  If \\fIoptions\\fR are specified, options are\nmodified as indicated in the command and the command returns an empty string.\nIf no \\fIoptions\\fR are specified, returns a list describing\nthe current options for entry \\fIindex\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).\n.\\\" METHOD: id\n.TP\n\\fIpathName \\fBid \\fIindex\\fR\n.\nReturns the id of the menu entry given by \\fIindex\\fR.\nThis is the identifier that was assigned to the entry when it was created\nusing the \\fBadd\\fR or \\fBinsert\\fR widget command.\nReturns an empty string for the tear-off entry, or if \\fIindex\\fR is\nequivalent to \\fB{}\\fR.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex \\fIindex\\fR\n.\nReturns the numerical index corresponding to \\fIindex\\fR, or\n\\fB{}\\fR if \\fIindex\\fR was specified as \\fB{}\\fR.\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex type \\fR?\\fIid\\fR? ?\\fIoption value option value ...\\fR?\n.\nSame as the \\fBadd\\fR widget command except that it inserts the new\nentry just before the entry given by \\fIindex\\fR, instead of appending\nto the end of the menu.  The \\fItype\\fR, \\fIid\\fR, \\fIoption\\fR, and\n\\fIvalue\\fR arguments have the same interpretation as for the \\fBadd\\fR\nwidget command.  It is not possible to insert new menu entries before the\ntear-off entry, if the menu has one.\nThe \\fBinsert\\fR widget command returns the id of the new entry.\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke \\fIindex\\fR\n.\nInvoke the action of the menu entry.  See the sections on the\nindividual entries above for details on what happens.  If the\nmenu entry is disabled then nothing happens.  If the\nentry has a command associated with it then the result of that\ncommand is returned as the result of the \\fBinvoke\\fR widget\ncommand.  Otherwise the result is an empty string.  Note:  invoking\na menu entry does not automatically unpost the menu;  the default\nbindings normally take care of this before invoking the \\fBinvoke\\fR\nwidget command.\n.\\\" METHOD: post\n.TP\n\\fIpathName \\fBpost \\fIx y\\fR ?\\fIindex\\fR?\n.\nArrange for the menu to be displayed on the screen at the root-window\ncoordinates given by \\fIx\\fR and \\fIy\\fR.  If an index is specified\nthe menu will be located so that the entry with that index is\ndisplayed at the point.  These coordinates are adjusted if necessary to\nguarantee that the entire menu is visible on the screen.  This command\nnormally returns an empty string.  If the \\fB\\-postcommand\\fR option\nhas been specified, then its value is executed as a Tcl script before\nposting the menu and the result of that script is returned as the\nresult of the \\fBpost\\fR widget command.  If an error returns while\nexecuting the command, then the error is returned without posting the\nmenu.\n.\\\" METHOD: postcascade\n.TP\n\\fIpathName \\fBpostcascade \\fIindex\\fR\n.\nPosts the submenu associated with the cascade entry given by\n\\fIindex\\fR, and unposts any previously posted submenu.\nIf \\fIindex\\fR does not correspond to a cascade entry,\nor if \\fIpathName\\fR is not posted,\nthe command has no effect except to unpost any currently posted\nsubmenu.\n.\\\" METHOD: type\n.TP\n\\fIpathName \\fBtype \\fIindex\\fR\n.\nReturns the type of the menu entry given by \\fIindex\\fR.\nThis is the \\fItype\\fR argument passed to the \\fBadd\\fR or \\fBinsert\\fR widget\ncommand when the entry was created, such as \\fBcommand\\fR\nor \\fBseparator\\fR, or \\fBtearoff\\fR for a tear-off entry.\n.\\\" METHOD: unpost\n.TP\n\\fIpathName \\fBunpost\\fR\n.\nUnmap the window so that it is no longer displayed.  If a\nlower-level cascaded menu is posted, unpost that menu.  Returns an\nempty string. This subcommand does not work on Windows and the\nMacintosh, as those platforms have their own way of unposting menus.\n.\\\" METHOD: xposition\n.TP\n\\fIpathName \\fBxposition \\fIindex\\fR\n.\nReturns a decimal string giving the x-coordinate within the menu\nwindow of the leftmost pixel in the entry specified by \\fIindex\\fR.\n.\\\" METHOD: yposition\n.TP\n\\fIpathName \\fByposition \\fIindex\\fR\n.\nReturns a decimal string giving the y-coordinate within the menu\nwindow of the topmost pixel in the entry specified by \\fIindex\\fR.\n.SH \"MENU ENTRY OPTIONS\"\nThe following options are allowed on menu entries. Most options are not\nsupported by all entry types.\n.\\\" OPTION: -activebackground\n.TP\n\\fB\\-activebackground \\fIvalue\\fR\n.\nSpecifies a background color to use for displaying this entry when it\nis active. This option is ignored on Aqua/macOS.\nIf it is specified as an empty string (the default), then the\n\\fB\\-activebackground\\fR option for the overall menu is used.\nIf the \\fBtk_strictMotif\\fR variable has been set to request strict\nMotif compliance, then this option is ignored and the \\fB\\-background\\fR\noption is used in its place.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -activeforeground\n.TP\n\\fB\\-activeforeground \\fIvalue\\fR\n.\nSpecifies a foreground color to use for displaying this entry when it\nis active.   This option is ignored on Aqua/macOS.\nIf this option is specified as an empty string (the default), then the\n\\fB\\-activeforeground\\fR option for the overall menu is used.\n.\\\" OPTION: -accelerator\n.TP\n\\fB\\-accelerator \\fIvalue\\fR\n.\nSpecifies a string to display at the right side of the menu entry.\nNormally describes an accelerator keystroke sequence that may be\nused to invoke the same function as the menu entry. This is a display\noption, it does not actually set the corresponding binding (which can\nbe achieved using the \\fBbind\\fR command). This option is not available\nfor separator or tear-off entries.\n.\\\" OPTION: -background\n.TP\n\\fB\\-background \\fIvalue\\fR\n.\nSpecifies a background color to use for displaying this entry when it\nis in the normal state (neither active nor disabled).\nThis option is ignored on Aqua/macOS.\nIf it is specified as an empty string (the default), then the\n\\fB\\-background\\fR option for the overall menu is used.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -bitmap\n.TP\n\\fB\\-bitmap \\fIvalue\\fR\n.\nSpecifies a bitmap to display in the menu instead of a textual\nlabel, in any of the forms accepted by \\fBTk_GetBitmap\\fR.\nThis option overrides the \\fB\\-label\\fR option\n(as controlled by the \\fB\\-compound\\fR option)\nbut may be reset\nto an empty string to enable a textual label to be displayed.\nIf a \\fB\\-image\\fR option has been specified, it overrides\n\\fB\\-bitmap\\fR.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -columnbreak\n.TP\n\\fB\\-columnbreak \\fIvalue\\fR\n.\nWhen this option is zero, the entry appears below the previous entry. When\nthis option is one, the entry appears at the top of a new column in the\nmenu.\nThis option is ignored on Aqua/macOS, where menus are always a single\ncolumn.\n.\\\" OPTION: -command\n.TP\n\\fB\\-command \\fIvalue\\fR\n.\nSpecifies a Tcl command to execute when the menu entry is invoked.\nNot available for separator or tear-off entries.\n.\\\" OPTION: -compound\n.TP\n\\fB\\-compound \\fIvalue\\fR\n.\nSpecifies whether the menu entry should display both an image and text,\nand if so, where the image should be placed relative to the text.\nValid values for this option are \\fBbottom\\fR, \\fBcenter\\fR,\n\\fBleft\\fR, \\fBnone\\fR, \\fBright\\fR and \\fBtop\\fR.  The default value\nis \\fBnone\\fR, meaning that the button will display either an image or\ntext, depending on the values of the \\fB\\-image\\fR and \\fB\\-bitmap\\fR\noptions.\n.\\\" OPTION: -font\n.TP\n\\fB\\-font \\fIvalue\\fR\n.\nSpecifies the font to use when drawing the label or accelerator\nstring in this entry.\nIf this option is specified as an empty string (the default) then\nthe \\fB\\-font\\fR option for the overall menu is used.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -foreground\n.TP\n\\fB\\-foreground \\fIvalue\\fR\n.\nSpecifies a foreground color to use for displaying this entry when it\nis in the normal state (neither active nor disabled).\nThis option is ignored on Aqua/macOS.\nIf it is specified as an empty string (the default), then the\n\\fB\\-foreground\\fR option for the overall menu is used.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -hidemargin\n.TP\n\\fB\\-hidemargin \\fIvalue\\fR\n.\nSpecifies whether the standard margins should be drawn for this menu\nentry. This is useful when creating palette with images in them, i.e.,\ncolor palettes, pattern palettes, etc. 1 indicates that the margin for\nthe entry is hidden; 0 means that the margin is used.\n.\\\" OPTION: -image\n.TP\n\\fB\\-image \\fIvalue\\fR\n.\nSpecifies an image to display in the menu instead of a text string\nor bitmap.\nThe image must have been created by some previous invocation of\n\\fBimage create\\fR.\nThis option overrides the \\fB\\-label\\fR and \\fB\\-bitmap\\fR options\n(as controlled by the \\fB\\-compound\\fR option)\nbut may be reset to an empty string to enable a textual or\nbitmap label to be displayed.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -indicatoron\n.TP\n\\fB\\-indicatoron \\fIvalue\\fR\n.\nAvailable only for checkbutton and radiobutton entries.\n\\fIValue\\fR is a boolean that determines whether or not the\nindicator should be displayed.\n.\\\" OPTION: -label\n.TP\n\\fB\\-label \\fIvalue\\fR\n.\nSpecifies a string to display as an identifying label in the menu\nentry.  Not available for separator or tear-off entries.\n.\\\" OPTION: -menu\n.TP\n\\fB\\-menu \\fIvalue\\fR\n.\nAvailable only for cascade entries.  Specifies the path name of\nthe submenu associated with this entry.\nThe submenu must be a child of the menu.\n.\\\" OPTION: -offvalue\n.TP\n\\fB\\-offvalue \\fIvalue\\fR\n.\nAvailable only for checkbutton entries.  Specifies the value to\nstore in the entry's associated variable when the entry is\ndeselected.\n.\\\" OPTION: -onvalue\n.TP\n\\fB\\-onvalue \\fIvalue\\fR\n.\nAvailable only for checkbutton entries.  Specifies the value to\nstore in the entry's associated variable when the entry is selected.\n.\\\" OPTION: -selectcolor\n.TP\n\\fB\\-selectcolor \\fIvalue\\fR\n.\nAvailable only for checkbutton and radiobutton entries.\nSpecifies the color to display in the indicator when the entry is\nselected.\nIf the value is an empty string (the default) then the \\fB\\-selectcolor\\fR\noption for the menu determines the indicator color.\n.\\\" OPTION: -selectimage\n.TP\n\\fB\\-selectimage \\fIvalue\\fR\n.\nAvailable only for checkbutton and radiobutton entries.\nSpecifies an image to display in the entry (in place of\nthe \\fB\\-image\\fR option) when it is selected.\n\\fIValue\\fR is the name of an image, which must have been created\nby some previous invocation of \\fBimage create\\fR.\nThis option is ignored unless the \\fB\\-image\\fR option has\nbeen specified.\n.\\\" OPTION: -state\n.TP\n\\fB\\-state \\fIvalue\\fR\n.\nSpecifies one of three states for the entry:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the entry is displayed using the\n\\fB\\-foreground\\fR option for the menu and the \\fB\\-background\\fR\noption from the entry or the menu.\nThe active state is typically used when the pointer is over the entry.\nIn active state the entry is displayed using the \\fB\\-activeforeground\\fR\noption for the menu along with the \\fB\\-activebackground\\fR option from\nthe entry.  Disabled state means that the entry\nshould be insensitive:  the default bindings will refuse to activate\nor invoke the entry.\nIn this state the entry is displayed according to the\n\\fB\\-disabledforeground\\fR option for the menu and the\n\\fB\\-background\\fR option from the entry.\nThis option is not available for separator entries.\n.\\\" OPTION: -underline\n.TP\n\\fB\\-underline \\fIvalue\\fR\n.\nSpecifies the integer index of a character to underline in the entry.\nThis option is also queried by the default bindings and used to\nimplement keyboard traversal.\n0 corresponds to the first character of the text displayed in the entry,\n1 to the next character, and so on.\nIf a bitmap or image is displayed in the entry then this option is ignored.\nThis option is not available for separator or tear-off entries.\n.\\\" OPTION: -value\n.TP\n\\fB\\-value \\fIvalue\\fR\n.\nAvailable only for radiobutton entries.  Specifies the value to\nstore in the entry's associated variable when the entry is selected.\nIf an empty string is specified, then the \\fB\\-label\\fR option\nfor the entry as the value to store in the variable.\n.\\\" OPTION: -variable\n.TP\n\\fB\\-variable \\fIvalue\\fR\n.\nAvailable only for checkbutton and radiobutton entries.  Specifies\nthe name of a global variable to set when the entry is selected.\nFor checkbutton entries the variable is also set when the entry\nis deselected.  For radiobutton entries, changing the variable\ncauses the currently-selected entry to deselect itself.\n.RS\n.PP\nFor checkbutton entries, the default value of this option is taken from the\n\\fB\\-label\\fR option, and for radiobutton entries a single fixed value is\nused. It is recommended that you always set the \\fB\\-variable\\fR option when\ncreating either a checkbutton or a radiobutton.\n.RE\n.SH \"MENU CONFIGURATIONS\"\n.PP\nThe default bindings support four different ways of using menus:\n.TP\n\\fBPulldown Menus in Menubar\\fR\n.\nThis is the most common case. You create a menu widget that will become the\nmenu bar. You then add cascade entries to this menu, specifying the\npull down menus you wish to use in your menu bar. You then create all\nof the pulldowns. Once you have done this, specify the menu using the\n\\fB\\-menu\\fR option of the toplevel's widget command. See the\n\\fBtoplevel\\fR manual entry for details.\n.TP\n\\fBPulldown Menus in Menu Buttons\\fR\n.\nThis is the compatible way to do menu bars.  You create one menubutton\nwidget for each top-level menu, and typically you arrange a series of\nmenubuttons in a row in a menubar window.  You also create the top-level menus\nand any cascaded submenus, and tie them together with \\fB\\-menu\\fR\noptions in menubuttons and cascade menu entries.  The top-level menu must\nbe a child of the menubutton, and each submenu must be a child of the\nmenu that refers to it.  Once you have done this, the default bindings\nwill allow users to traverse and invoke the tree of menus via its\nmenubutton;  see the \\fBmenubutton\\fR manual entry for details.\n.TP\n\\fBPopup Menus\\fR\n.\nPopup menus typically post in response to a mouse button press or\nkeystroke.  You create the popup menus and any cascaded submenus,\nthen you call the \\fBtk_popup\\fR procedure at the appropriate time\nto post the top-level menu.\n.TP\n\\fBOption Menus\\fR\n.\nAn option menu consists of a menubutton with an associated menu\nthat allows you to select one of several values.  The current value\nis displayed in the menubutton and is also stored in a global\nvariable.  Use the \\fBtk_optionMenu\\fR procedure to create option\nmenubuttons and their menus.\n.TP\n\\fBTorn-off Menus\\fR\n.\nYou create a torn-off menu by invoking the tear-off entry at\nthe top of an existing menu.  The default bindings will create a new menu\nthat is a copy of the original menu and leave it permanently\nposted as a top-level window.  The torn-off menu behaves just\nthe same as the original menu.\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for menus that give them\nthe following default behavior:\n.IP [1]\nWhen the mouse enters a menu, the entry underneath the mouse\ncursor activates;  as the mouse moves around the menu, the active\nentry changes to track the mouse.\n.IP [2]\nWhen the mouse leaves a menu all of the entries in the menu\ndeactivate, except in the special case where the mouse moves from\na menu to a cascaded submenu.\n.IP [3]\nWhen a button is released over a menu, the active entry (if any) is invoked.\nThe menu also unposts unless it is a torn-off menu.\n.IP [4]\nThe Space and Return keys invoke the active entry and\nunpost the menu.\n.IP [5]\nIf any of the entries in a menu have letters underlined with\nthe \\fB\\-underline\\fR option, then pressing one of the underlined\nletters (or its upper-case or lower-case equivalent) invokes that\nentry and unposts the menu.\n.IP [6]\nThe Escape key aborts a menu selection in progress without invoking any\nentry.  It also unposts the menu unless it is a torn-off menu.\n.IP [7]\nThe Up and Down keys activate the next higher or lower entry\nin the menu.  When one end of the menu is reached, the active\nentry wraps around to the other end.\n.IP [8]\nThe Left key moves to the next menu to the left.\nIf the current menu is a cascaded submenu, then the submenu is\nunposted and the current menu entry becomes the cascade entry\nin the parent.\nIf the current menu is a top-level menu posted from a\nmenubutton, then the current menubutton is unposted and the\nnext menubutton to the left is posted.\nOtherwise the key has no effect.\nThe left-right order of menubuttons is determined by their stacking\norder:  Tk assumes that the lowest menubutton (which by default\nis the first one created) is on the left.\n.IP [9]\nThe Right key moves to the next menu to the right.\nIf the current entry is a cascade entry, then the submenu is\nposted and the  current menu entry becomes the first entry\nin the submenu.\nOtherwise, if the current menu was posted from a\nmenubutton, then the current menubutton is unposted and the\nnext menubutton to the right is posted.\n.PP\nDisabled menu entries are non-responsive:  they do not activate and\nthey ignore mouse button presses and releases.\n.PP\nSeveral of the bindings make use of the command \\fBtk_menuSetFocus\\fR.\nIt saves the current focus and sets the focus to its \\fIpathName\\fR\nargument, which is a menu widget.\n.PP\nThe behavior of menus can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH BUGS\n.PP\nAt present it is not possible to use the\noption database to specify values for the options to individual\nentries.\n.SH \"SEE ALSO\"\nbind(n), menubutton(n), ttk::menubutton(n), toplevel(n)\n.SH KEYWORDS\nmenu, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/menubutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH menubutton n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nmenubutton \\- Create and manipulate 'menubutton' pop-up menu indicator widgets\n.SH SYNOPSIS\n\\fBmenubutton\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-disabledforeground\t\\-padx\n\\-activeforeground\t\\-font\t\\-pady\n\\-anchor\t\\-foreground\t\\-relief\n\\-background\t\\-highlightbackground\t\\-takefocus\n\\-bitmap\t\\-highlightcolor\t\\-text\n\\-borderwidth\t\\-highlightthickness\t\\-textvariable\n\\-cursor\t\\-image\t\\-underline\n\\-compound\t\\-justify\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-direction direction Direction\nSpecifies where the menu is going to be popup up. \\fBabove\\fR tries to\npop the menu above the menubutton. \\fBbelow\\fR tries to pop the menu\nbelow the menubutton. \\fBleft\\fR tries to pop the menu to the left of\nthe menubutton. \\fBright\\fR tries to pop the menu to the right of the\nmenu button. \\fBflush\\fR pops the menu directly over the menubutton.\nIn the case of \\fBabove\\fR or \\fBbelow\\fR, the direction will be\nreversed if the menu would show offscreen.\n.OP \\-height height Height\nSpecifies a desired height for the menubutton.\nIf an image or bitmap is being displayed in the menubutton then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in lines of text.\nIf this option is not specified, the menubutton's desired height is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.OP \\-indicatoron indicatorOn IndicatorOn\nThe value must be a proper boolean value.  If it is true then\na small indicator rectangle will be displayed on the right side\nof the menubutton and the default menu bindings will treat this\nas an option menubutton.  If false then no indicator will be\ndisplayed.\n.OP \\-menu menu MenuName\nSpecifies the path name of the menu associated with this menubutton.\nThe menu must be a child of the menubutton.\n.OP \\-state state State\nSpecifies one of three states for the menubutton:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the menubutton is displayed using the\n\\fBforeground\\fR and \\fBbackground\\fR options.  The active state is\ntypically used when the pointer is over the menubutton.  In active state\nthe menubutton is displayed using the \\fB\\-activeforeground\\fR and\n\\fB\\-activebackground\\fR options.  Disabled state means that the menubutton\nshould be insensitive:  the default bindings will refuse to activate\nthe widget and will ignore mouse button presses.\nIn this state the \\fB\\-disabledforeground\\fR and\n\\fB\\-background\\fR options determine how the button is displayed.\n.OP \\-width width Width\nSpecifies a desired width for the menubutton.\nIf an image or bitmap is being displayed in the menubutton then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in characters.\nIf this option is not specified, the menubutton's desired width is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.BE\n.SH INTRODUCTION\n.PP\nThe \\fBmenubutton\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a menubutton widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the menubutton such as its colors, font,\ntext, and initial relief.  The \\fBmenubutton\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA menubutton is a widget that displays a textual string, bitmap, or image\nand is associated with a menu widget.\nIf text is displayed, it must all be in a single font, but it\ncan occupy multiple lines on the screen (if it contains newlines\nor if wrapping occurs because of the \\fB\\-wraplength\\fR option) and\none of the characters may optionally be underlined using the\n\\fB\\-underline\\fR option.  In normal usage, pressing\nmouse button 1 over the menubutton causes the associated menu to\nbe posted just underneath the menubutton.  If the mouse is moved over\nthe menu before releasing the mouse button, the button release\ncauses the underlying menu entry to be invoked.  When the button\nis released, the menu is unposted.\n.PP\nMenubuttons are used to construct a \\fBtk_optionMenu\\fR, which is the\npreferred mechanism for allowing a user to select one item from a list\non macOS.\n.PP\nMenubuttons were also typically organized into groups called menu bars\nthat allow scanning:\nif the mouse button is pressed over one menubutton (causing it\nto post its menu) and the mouse is moved over another menubutton\nin the same menu bar without releasing the mouse button, then the\nmenu of the first menubutton is unposted and the menu of the\nnew menubutton is posted instead.\n\\fIThis use is deprecated\\fR in favor of setting a \\fBmenu\\fR directly as a\nmenubar; see the \\fBtoplevel\\fR's \\fB\\-menu\\fR option for how to do that.\n.PP\nThere are several interactions between menubuttons and menus;  see\nthe \\fBmenu\\fR manual entry for information on various menu configurations,\nsuch as pulldown menus and option menus.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBmenubutton\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for menubutton widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBmenubutton\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBmenubutton\\fR\ncommand.\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for menubuttons that give them\nthe following default behavior:\n.IP [1]\nA menubutton activates whenever the mouse passes over it and deactivates\nwhenever the mouse leaves it.\n.IP [2]\nPressing mouse button 1 over a menubutton posts the menubutton:\nits relief changes to raised and its associated menu is posted\nunder the menubutton.  If the mouse is dragged down into the menu\nwith the button still down, and if the mouse button is then\nreleased over an entry in the menu, the menubutton is unposted\nand the menu entry is invoked.\n.IP [3]\nIf button 1 is pressed over a menubutton and then released over that\nmenubutton, the menubutton stays posted: you can still move the mouse\nover the menu and click button 1 on an entry to invoke it.\nOnce a menu entry has been invoked, the menubutton unposts itself.\n.IP [4]\nIf button 1 is pressed over a menubutton and then dragged over some\nother menubutton, the original menubutton unposts itself and the\nnew menubutton posts.\n.IP [5]\nIf button 1 is pressed over a menubutton and released outside\nany menubutton or menu, the menubutton unposts without invoking\nany menu entry.\n.IP [6]\nWhen a menubutton is posted, its associated menu claims the input\nfocus to allow keyboard traversal of the menu and its submenus.\nSee the \\fBmenu\\fR manual entry for details on these bindings.\n.IP [7]\nIf the \\fB\\-underline\\fR option has been specified for a menubutton\nthen keyboard traversal may be used to post the menubutton:\nAlt+\\fIx\\fR, where \\fIx\\fR is the underlined character (or its\nlower-case or upper-case equivalent), may be typed in any window\nunder the menubutton's toplevel to post the menubutton.\n.IP [8]\nThe F10 key may be typed in any window to post the first menubutton\nunder its toplevel window that is not disabled.\n.IP [9]\nIf a menubutton has the input focus, the space and return keys\npost the menubutton.\n.PP\nIf the menubutton's state is \\fBdisabled\\fR then none of the above\nactions occur:  the menubutton is completely non-responsive.\n.PP\nThe behavior of menubuttons can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\nttk::menubutton(n), menu(n)\n.SH KEYWORDS\nmenubutton, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/message.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH message n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nmessage \\- Create and manipulate 'message' non-interactive text widgets\n.SH SYNOPSIS\n\\fBmessage\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-anchor\t\\-background\t\\-borderwidth\n\\-cursor\t\\-font\t\\-foreground\n\\-highlightbackground\t\\-highlightcolor\t\\-highlightthickness\n\\-padx\t\\-pady\t\\-relief\n\\-takefocus\t\\-text\t\\-textvariable\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-aspect aspect Aspect\nSpecifies a non-negative integer value indicating desired\naspect ratio for the text.  The aspect ratio is specified as\n100*width/height.  100 means the text should\nbe as wide as it is tall, 200 means the text should\nbe twice as wide as it is tall, 50 means the text should\nbe twice as tall as it is wide, and so on.\nUsed to choose line length for text if \\fB\\-width\\fR option\nis not specified.\nDefaults to 150.\n.OP \\-justify justify Justify\nSpecifies how to justify lines of text.\nMust be one of \\fBleft\\fR, \\fBcenter\\fR, or \\fBright\\fR.  Defaults\nto \\fBleft\\fR.\nThis option works together with the \\fB\\-anchor\\fR, \\fB\\-aspect\\fR,\n\\fB\\-padx\\fR, \\fB\\-pady\\fR, and \\fB\\-width\\fR options to provide a variety\nof arrangements of the text within the window.\nThe \\fB\\-aspect\\fR and \\fB\\-width\\fR options determine the amount of\nscreen space needed to display the text.\nThe \\fB\\-anchor\\fR, \\fB\\-padx\\fR, and \\fB\\-pady\\fR options determine where this\nrectangular area is displayed within the widget's window, and the\n\\fB\\-justify\\fR option determines how each line is displayed within that\nrectangular region.\nFor example, suppose \\fB\\-anchor\\fR is \\fBe\\fR and \\fB\\-justify\\fR is\n\\fBleft\\fR, and that the message window is much larger than needed\nfor the text.\nThe text will be displayed so that the left edges of all the lines\nline up and the right edge of the longest line is \\fB\\-padx\\fR from\nthe right side of the window;  the entire text block will be centered\nin the vertical span of the window.\n.OP \\-width width Width\nSpecifies the length of lines in the window.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nIf this option has a value greater than zero then the \\fB\\-aspect\\fR\noption is ignored and the \\fB\\-width\\fR option determines the line\nlength.\nIf this option value is negative or zero, then\nthe \\fB\\-aspect\\fR option determines the line length.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBmessage\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a message widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the message such as its colors, font,\ntext, and initial relief.  The \\fBmessage\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA message is a widget that displays a textual string.  A message\nwidget has three special features that differentiate it from a\n\\fBlabel\\fR widget.  First, it breaks up\nits string into lines in order to produce a given aspect ratio\nfor the window.  The line breaks are chosen at word boundaries\nwherever possible (if not even a single word would fit on a\nline, then the word will be split across lines).  Newline characters\nin the string will force line breaks;  they can be used, for example,\nto leave blank lines in the display.\n.PP\nThe second feature of a message widget is justification.  The text\nmay be displayed left-justified (each line starts at the left side of\nthe window), centered on a line-by-line basis, or right-justified\n(each line ends at the right side of the window).\n.PP\nThe third feature of a message widget is that it handles control\ncharacters and non-printing characters specially.  Tab characters\nare replaced with enough blank space to line up on the next\n8-character boundary.  Newlines cause line breaks.  Other control\ncharacters (ASCII code less than 0x20) and characters not defined\nin the font are displayed as a four-character sequence \\fB\\ex\\fIhh\\fR where\n\\fIhh\\fR is the two-digit hexadecimal number corresponding to\nthe character.  In the unusual case where the font does not contain\nall of the characters in\n.QW 0123456789abcdef\\ex\nthen control characters and undefined characters are not displayed at all.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBmessage\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for message widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBmessage\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBmessage\\fR\ncommand.\n.SH \"DEFAULT BINDINGS\"\n.PP\nWhen a new message is created, it has no default event bindings:\nmessages are intended for output purposes only.\n.SH BUGS\n.PP\nTabs do not work very well with text that is centered or right-justified.\nThe most common result is that the line is justified wrong.\n.SH \"SEE ALSO\"\nlabel(n)\n.SH KEYWORDS\nmessage, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/messageBox.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_messageBox n 4.2 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_messageBox \\- pops up a message window and waits for user response.\n.SH SYNOPSIS\n\\fBtk_messageBox \\fR?\\fIoption value ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure creates and displays a message window with an\napplication-specified message, an icon and a set of buttons.  Each of\nthe buttons in the message window is identified by a unique symbolic\nname (see the \\fB\\-type\\fR options).  After the message window is\npopped up, \\fBtk_messageBox\\fR waits for the user to select one of the\nbuttons. Then it returns the symbolic name of the selected button.\n.PP\nThe following option-value pairs are supported:\n.\\\" OPTION: -command\n.TP\n\\fB\\-command\\fI string\\fR\n.\nSpecifies the prefix of a Tcl command to invoke when the user closes the\ndialog. The actual command consists of \\fIstring\\fR followed by a space\nand the name of the button clicked by the user to close the dialog. This\nis only available on macOS.\n.\\\" OPTION: -default\n.TP\n\\fB\\-default\\fI name\\fR\n.\n\\fIName\\fR gives the symbolic name of the default button for\nthis message window (\n.QW ok ,\n.QW cancel ,\nand so on). See \\fB\\-type\\fR\nfor a list of the symbolic names.  If this option is not specified,\nthe first button in the dialog will be made the default.\n.\\\" OPTION: -detail\n.TP\n\\fB\\-detail\\fI string\\fR\n.\nSpecifies an auxiliary message to the main message given by the\n\\fB\\-message\\fR option. The message detail will be presented beneath the main\nmessage and, where supported by the OS, in a less emphasized font than the\nmain message.\n.\\\" OPTION: -icon\n.TP\n\\fB\\-icon\\fI iconImage\\fR\n.\nSpecifies an icon to display. \\fIIconImage\\fR must be one of the\nfollowing: \\fBerror\\fR, \\fBinfo\\fR, \\fBquestion\\fR or\n\\fBwarning\\fR. If this option is not specified, then the info icon will be\ndisplayed.\n.\\\" OPTION: -message\n.TP\n\\fB\\-message\\fI string\\fR\n.\nSpecifies the message to display in this message box. The\ndefault value is an empty string.\n.\\\" OPTION: -parent\n.TP\n\\fB\\-parent\\fI window\\fR\n.\nMakes \\fIwindow\\fR the logical parent of the message box. The message\nbox is displayed on top of its parent window.\n.\\\" OPTION: -title\n.TP\n\\fB\\-title\\fI titleString\\fR\n.\nSpecifies a string to display as the title of the message box. The\ndefault value is an empty string.\n.\\\" OPTION: -type\n.TP\n\\fB\\-type\\fI predefinedType\\fR\n.\nArranges for a predefined set of buttons to be displayed. The\nfollowing values are possible for \\fIpredefinedType\\fR:\n.RS\n.IP \\fBabortretryignore\\fR 18\nDisplays three buttons whose symbolic names are \\fBabort\\fR,\n\\fBretry\\fR and \\fBignore\\fR.\n.IP \\fBok\\fR 18\nDisplays one button whose symbolic name is \\fBok\\fR. This is the default.\n.IP \\fBokcancel\\fR 18\nDisplays two buttons whose symbolic names are \\fBok\\fR and \\fBcancel\\fR.\n.IP \\fBretrycancel\\fR 18\nDisplays two buttons whose symbolic names are \\fBretry\\fR and \\fBcancel\\fR.\n.IP \\fByesno\\fR 18\nDisplays two buttons whose symbolic names are \\fByes\\fR and \\fBno\\fR.\n.IP \\fByesnocancel\\fR 18\nDisplays three buttons whose symbolic names are \\fByes\\fR, \\fBno\\fR\nand \\fBcancel\\fR.\n.RE\n.PP\n.SH EXAMPLE\n.PP\n.CS\nset answer [\\fBtk_messageBox\\fR -message \"Really quit?\" \\e\n        -icon question -type yesno \\e\n        -detail \"Select \\e\"Yes\\e\" to make the application exit\"]\nswitch -- $answer {\n    yes exit\n    no {\\fBtk_messageBox\\fR -message \"I know you like this application!\" \\e\n            -type ok}\n}\n.CE\n.SH KEYWORDS\nmessage box\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/nsimage.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2022 Marc Culler\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH nsimage n 9.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nnsimage \\- A Tk image type for macOS based on the NSImage class.\n.BE\n.SH DESCRIPTION\nThe nsimage is implemented as a Tk image type.  The \\fBimage\\fR\ncommand is used to create, delete, and query all images, including\nimages of type \\fBnsimage\\fR.  The options that are available are\nspecific to the nsimage type and are described below.\n.PP\nThe command to create an \\fBnsimage\\fR:\n.TP\n\\fBimage create nsimage \\fR?\\fIname\\fR? ?\\fIoption value ...\\fR?\n.PP\ncreates a new nsimage and a command with the same name and returns its\nname.\n.SH OPTIONS\n.PP\nValid \\fIoptions\\fR are:\n.\\\" OPTION: -source\n.TP\n\\fB\\-source\\fI string\\fR\n.PP\nThe value of the \\fB\\-source\\fR option is a string describing an\nNSimage.  There are several ways to interpret this string, and the\ninterpretation is determined by the value of the \\fB\\-as\\fR option.\nThis option is required.\n.PP\n.\\\" OPTION: -as\n.TP\n\\fB\\-as\\fI type\\fR\n.PP\nThere are four possible values for the \\fB\\-as\\fR option which specify\nhow the source string should be interpreted.  The allowed values and\ntheir meanings are:\n.RS\n.IP \\fBname\\fR\nThe source should be interpreted as the name of a named NSImage\nprovided by the system.\nThis is the default if the \\fB\\-as\\fR option is not specified.\n.IP \\fBfile\\fR\nThe source should be interpreted as a path to an image\nfile in one of the formats understood by the NSImage class.\n.IP \\fBpath\\fR\nThe source should be interpreted as a path to an arbitrary\nfile. The type of the file will be examined and the resulting image\nwill be the system icon for files of that type.\n.IP \\fBfiletype\\fR\nThe source is interpreted as a string identifying a\nparticular file type.  It may be a filename extension, an Apple Uniform Type\nIdentifier or a 4-character OSType value as used in the HFS filesystem.\n.RE\n.\\\" OPTION: -width\n.TP\n\\fB\\-width\\fI pixels\\fR\n.PP\nThe value of the \\fIwidth\\fR option is an integer specifying the width\nin pixels of the nsimage.  If the width is not specified it will be\ncomputed from the height so as to preserve the aspect ration.  If\nneither width nor height are specified then the width and height of\nthe underlying NSImage will be used.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height\\fI pixels\\fR\n.PP\nThe value of the \\fIheight\\fR option is an integer specifying the\nheight in pixels of the nsimage. If the height is not specified it\nwill be computed from the height so as to preserve the aspect ration.\nIf neither width nor height are specified then the width and height of\nthe underlying NSImage will be used.\n.\\\" OPTION: -radius\n.TP\n\\fB\\-radius\\fI pixels\\fR\n.PP\nThe value of the \\fIradius\\fR option is an integer.  If non-zero the\nimage will be clipped to a rounded rectangle with the same width and\nheight as the image, but with circular arcs of the specified radius\ncutting off the corners of the rectangle.\n.\\\" OPTION: -ring\n.TP\n\\fB\\-ring\\fI pixels\\fR\n.PP\nThe value of the \\fIring\\fR option is an integer.  If non-zero then it\nspecifies the thickness of a focus ring which will be drawn around the\nimage using the control accent color specified in the System\nPreferences.  The image is resized to reduce its width and height by\ntwice the thickness of the ring.  Note that this may create a small\namount of distortion.  The aspect ration of a non-square image will\nchange slightly.\n.\\\" OPTION: -alpha\n.TP\n\\fB\\-alpha\\fI float\\fR\n.PP\nThe value of the \\fIalpha\\fR option should be a floating point number\nbetween 0.0 and 1.0.  This alpha value will be applied to each pixel\nof the nsimage, producing a partially transparent image.  The default value\nis 1.0, which makes the image opaque.\n.\\\" OPTION: -pressed\n.TP\n\\fB\\-pressed\\fI boolean\\fR\n.PP\nThe \\fIpressed\\fR option takes a boolean value.  If the value is true\nor 1 then the image will be algorithmically modified to become darker\nin light mode or lighter in dark mode.  The default is false.  For an\nimage button, the primary image should use the value false while the\npressed image should be the same image but with the \\fIpressed\\fR\noption set to true.\n.\\\" OPTION: -template\n.TP\n\\fB\\-template\\fI boolean\\fR\n.PP\nThe \\fItemplate\\fR option takes a boolean value.  If the value is true\nor 1 then the image will be marked as being a template image.  This\nmeans that the system will algorithmically convert the image to a\nlight colored image when in dark mode.  For the algorithm to work\ncorrectly the image must consist only of black pixels with alpha\nvalues.\n.SH \"SEE ALSO\"\nimage(n), options(n), photo(n)\n.SH KEYWORDS\nheight, image, types of images, width\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/option.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH option n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\noption \\- Add/retrieve window options to/from the option database\n.SH SYNOPSIS\n.nf\n\\fBoption add \\fIpattern value \\fR?\\fIpriority\\fR?\n\\fBoption clear\\fR\n\\fBoption get \\fIwindow name class\\fR\n\\fBoption readfile \\fIfileName \\fR?\\fIpriority\\fR?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBoption\\fR command allows you to add entries to the Tk option\ndatabase or to retrieve options from the database.\n.\\\" METHOD: add\nThe \\fBadd\\fR form of the command adds a new option to the database.\n\\fIPattern\\fR contains\nthe option being specified, and consists of names and/or classes\nseparated by asterisks or dots, in the usual X format (see\n\\fBPATTERN FORMAT\\fR).  \\fIValue\\fR\ncontains a text string to associate with \\fIpattern\\fR;  this is the\nvalue that will be returned in calls to \\fBTk_GetOption\\fR or by\ninvocations of the \\fBoption get\\fR command.  If \\fIpriority\\fR\nis specified, it indicates the priority level for this option (see\nbelow for legal values);  it defaults to \\fBinteractive\\fR.\nThis command always returns an empty string.\n.PP\n.\\\" METHOD: clear\nThe \\fBoption clear\\fR command clears the option database.  Default\noptions (from the\n\\fBRESOURCE_MANAGER\\fR property or the \\fB.Xdefaults\\fR\nfile) will be reloaded automatically the next time an\noption is added to the database or removed from it.  This command\nalways returns an empty string.\n.PP\n.\\\" METHOD: get\nThe \\fBoption get\\fR command returns the value of the option\nspecified for \\fIwindow\\fR\nunder \\fIname\\fR and \\fIclass\\fR.  If several entries in the option\ndatabase match \\fIwindow\\fR, \\fIname\\fR, and \\fIclass\\fR, then\nthe command returns whichever was created with highest\n\\fIpriority\\fR level.  If there are several matching\nentries at the same priority level, then it returns whichever entry\nwas most recently entered into the option database.  If there are\nno matching entries, then the empty string is returned.\n.PP\n.\\\" METHOD: readfile\nThe \\fBreadfile\\fR form of the command reads \\fIfileName\\fR,\nwhich should have the standard format for an\nX resource database such as \\fB.Xdefaults\\fR, and adds all the\noptions specified in that file to the option database.  If \\fIpriority\\fR\nis specified, it indicates the priority level at which to enter the\noptions;  \\fIpriority\\fR defaults to \\fBinteractive\\fR.\n.PP\nThe file is read through a channel which is in \"utf-8\" encoding,\ninvalid byte sequences are automatically converted to valid ones.\nThis means that encodings like ISO 8859-1 or cp1252 with high\nprobability will work as well, but this cannot be guaranteed.\nThis cannot be changed, setting the [encoding system] has no effect.\n.PP\nThe \\fIpriority\\fR arguments to the \\fBoption\\fR command are\nnormally specified symbolically using one of the following values:\n.IP \\fBwidgetDefault\\fR\nLevel 20.  Used for default values hard-coded into widgets.\n.IP \\fBstartupFile\\fR\nLevel 40.  Used for options specified in application-specific\nstartup files.\n.IP \\fBuserDefault\\fR\nLevel 60.  Used for options specified in user-specific defaults\nfiles, such as \\fB.Xdefaults\\fR, resource databases loaded into\nthe X server, or user-specific startup files.\n.IP \\fBinteractive\\fR\nLevel 80.  Used for options specified interactively after the application\nstarts running.  If \\fIpriority\\fR is not specified, it defaults to\nthis level.\n.PP\nAny of the above keywords may be abbreviated.  In addition, priorities\nmay be specified numerically using integers between 0 and 100,\ninclusive.  The numeric form is probably a bad idea except for new priority\nlevels other than the ones given above.\n.SH \"PATTERN FORMAT\"\n.PP\nPatterns consist of a sequence of words separated by either periods,\n.QW . ,\nor asterisks\n.QW * .\nThe overall pattern may also be optionally preceded by an asterisk.\n.PP\nEach word in the pattern conventionally starts with either an upper-case\nletter (in which case it denotes the class of either a widget or an option) or\nany other character, when it denotes the name of a widget or option. The last\nword in the pattern always indicates the option; the preceding ones constrain\nwhich widgets that option will be looked for in.\n.PP\nWhen two words are separated by a period, the latter widget must be a direct\nchild of the former (or the option must apply to only the indicated widgets).\nWhen two words are separated by an asterisk, any depth of widgets may lie\nbetween the former and latter widgets (and the option applies to all widgets\nthat are children of the former widget).\n.PP\nIf the overall pattern is preceded by an asterisk, then the overall pattern\napplies anywhere it can throughout the whole widget hierarchy. Otherwise the\nfirst word of the pattern is matched against the name and class of the\n.QW \\fB.\\fR\n\\fBtoplevel\\fR, which are usually set by options to \\fBwish\\fR.\n.SH EXAMPLES\n.PP\nInstruct every button in the application to have red text on it unless\nexplicitly overridden, by setting the \\fBforeground\\fR for the \\fBButton\\fR\nclass (note that on some platforms the option is ignored):\n.CS\n\\fBoption add\\fR *Button.foreground red startupFile\n.CE\n.PP\nAllow users to control what happens in an entry widget when the Return\nkey is pressed by specifying a script in the option database and add a\ndefault option for that which rings the bell:\n.CS\nentry .e\nbind .e <Return> [\\fBoption get\\fR .e returnCommand Command]\n\\fBoption add\\fR *.e.returnCommand bell widgetDefault\n.CE\n.SH \"SEE ALSO\"\noptions(n), wish(1)\n.SH KEYWORDS\ndatabase, option, priority, retrieve\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/optionMenu.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_optionMenu n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_optionMenu \\- Create an option menubutton and its menu\n.SH SYNOPSIS\n\\fBtk_optionMenu \\fIpathName varName value \\fR?\\fIvalue value ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure creates an option menubutton whose name is \\fIpathName\\fR,\nplus an associated menu.\nTogether they allow the user to select one of the values\ngiven by the \\fIvalue\\fR arguments.\nThe current value will be stored in the global variable whose\nname is given by \\fIvarName\\fR and it will also be displayed as the label\nin the option menubutton.\nThe user can click on the menubutton to display a menu containing\nall of the \\fIvalue\\fRs and thereby select a new value.\nOnce a new value is selected, it will be stored in the variable\nand appear in the option menubutton.\nThe current value can also be changed by setting the variable.\n.PP\nThe return value from \\fBtk_optionMenu\\fR is the name of the menu\nassociated with \\fIpathName\\fR, so that the caller can change its\nconfiguration options or manipulate it in other ways.\n.SH EXAMPLE\n.PP\n.CS\ntk_optionMenu .foo myVar Foo Bar Boo Spong Wibble\npack .foo\n.CE\n.SH KEYWORDS\noption menu\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/options.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH options n 4.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\noptions \\- Standard options supported by widgets\n.BE\n.SH DESCRIPTION\n.PP\nThis manual entry describes the common configuration options supported\nby widgets in the Tk toolkit.  Every widget does not necessarily support\nevery option (see the manual entries for individual widgets for a list\nof the standard options supported by that widget), but if a widget does\nsupport an option with one of the names listed below, then the option\nhas exactly the effect described below.\n.PP\nIn the descriptions below,\n.QW \"Command-Line Name\"\nrefers to the\nswitch used in class commands and \\fBconfigure\\fR widget commands to\nset this value.  For example, if an option's command-line switch is\n\\fB\\-foreground\\fR and there exists a widget \\fB.a.b.c\\fR, then the\ncommand\n.CS\n\\&\\fB.a.b.c\\0\\0configure\\0\\0\\-foreground black\\fR\n.CE\nmay be used to specify the value \\fBblack\\fR for the option in\nthe widget \\fB.a.b.c\\fR.  Command-line switches may be abbreviated,\nas long as the abbreviation is unambiguous.\n.QW \"Database Name\"\nrefers to the option's name in the option database (e.g. in .Xdefaults files).\n.QW \"Database Class\"\nrefers to the option's class value in the option database.\n.OP \\-activebackground activeBackground Foreground\nSpecifies background color to use when drawing active elements.\nAn element (a widget or portion of a widget) is active if the\nmouse cursor is positioned over the element and pressing a mouse button\nwill cause some action to occur.\nIf strict Motif compliance has been requested by setting the\n\\fBtk_strictMotif\\fR variable, this option will normally be\nignored;  the normal background color will be used instead.\nFor some elements on Windows and Macintosh systems, the active color\nwill only be used while mouse button 1 is pressed over the element.\n.OP \\-activeborderwidth activeBorderWidth BorderWidth\nSpecifies a non-negative value indicating\nthe width of the 3-D border drawn around active elements.  See above for\ndefinition of active elements.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nThis option is typically only available in widgets displaying more\nthan one element at a time (e.g. menus but not buttons).\n.OP \\-activeforeground activeForeground Background\nSpecifies foreground color to use when drawing active elements.\nSee above for definition of active elements.\n.OP \\-activerelief activeRelief Relief\nSpecifies the 3-D effect desired for the active item of the widget.\nSee the \\fB\\-relief\\fR option for details.\n.OP \\-anchor anchor Anchor\nSpecifies how the information in a widget (e.g. text or a bitmap)\nis to be displayed in the widget.\nMust be one of the values \\fBn\\fR, \\fBne\\fR, \\fBe\\fR, \\fBse\\fR,\n\\fBs\\fR, \\fBsw\\fR, \\fBw\\fR, \\fBnw\\fR, or \\fBcenter\\fR.\nFor example, \\fBnw\\fR means display the information such that its\ntop-left corner is at the top-left corner of the widget.\n.OP \"\\-background or \\-bg\" background Background\nSpecifies the normal background color to use when displaying the\nwidget.\n.OP \\-bitmap bitmap Bitmap\nSpecifies a bitmap to display in the widget, in any of the forms\nacceptable to \\fBTk_GetBitmap\\fR.\nThe exact way in which the bitmap is displayed may be affected by\nother options such as \\fB\\-anchor\\fR or \\fB\\-justify\\fR.\nTypically, if this option is specified then it overrides other\noptions that specify a textual value to display in the widget\nbut this is controlled by the \\fB\\-compound\\fR option;\nthe \\fB\\-bitmap\\fR option may be reset to an empty string to re-enable\na text display.\nIn widgets that support both \\fB\\-bitmap\\fR and \\fB\\-image\\fR options,\n\\fB\\-image\\fR will usually override \\fB\\-bitmap\\fR.\n.OP \"\\-borderwidth or \\-bd\" borderWidth BorderWidth\nSpecifies a non-negative value indicating the width\nof the 3-D border to draw around the outside of the widget (if such a\nborder is being drawn;  the \\fB\\-relief\\fR option typically determines\nthis).  The value may also be used when drawing 3-D effects in the\ninterior of the widget.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.OP \\-cursor cursor Cursor\nSpecifies the mouse cursor to be used for the widget.\nThe value may have any of the forms acceptable to \\fBTk_GetCursor\\fR.\nIn addition, if an empty string is specified, it indicates that the\nwidget should defer to its parent for cursor specification.\n.OP \\-compound compound Compound\nSpecifies if the widget should display text and bitmaps/images at the\nsame time, and if so, where the bitmap/image should be placed relative\nto the text.  Must be one of the values \\fBnone\\fR, \\fBbottom\\fR,\n\\fBtop\\fR, \\fBleft\\fR, \\fBright\\fR, or \\fBcenter\\fR.  For example, the\n(default) value \\fBnone\\fR specifies that the bitmap or image should\n(if defined) be displayed instead of the text, the value \\fBleft\\fR\nspecifies that the bitmap or image should be displayed to the left of\nthe text, and the value \\fBcenter\\fR specifies that the bitmap or\nimage should be displayed on top of the text.\n.OP \\-disabledforeground disabledForeground DisabledForeground\nSpecifies foreground color to use when drawing a disabled element.\nIf the option is specified as an empty string (which is typically the\ncase on monochrome displays), disabled elements are drawn with the\nnormal foreground color but they are dimmed by drawing them\nwith a stippled fill pattern.\n.OP \\-exportselection exportSelection ExportSelection\nSpecifies whether or not a selection in the widget should also be\nthe X selection.\nThe value may have any of the forms accepted by \\fBTcl_GetBoolean\\fR,\nsuch as \\fBtrue\\fR, \\fBfalse\\fR, \\fB0\\fR, \\fB1\\fR, \\fByes\\fR, or \\fBno\\fR.\nIf the selection is exported, then selecting in the widget deselects\nthe current X selection, selecting outside the widget deselects any\nwidget selection, and the widget will respond to selection retrieval\nrequests when it has a selection.  The default is usually for widgets\nto export selections.\n.OP \\-font font Font\nSpecifies the font to use when drawing text inside the widget.\nThe value may have any of the forms described in the \\fBfont\\fR manual\npage under \\fBFONT DESCRIPTION\\fR.\n.OP \"\\-foreground or \\-fg\" foreground Foreground\nSpecifies the normal foreground color to use when displaying the widget.\n.OP \\-highlightbackground highlightBackground HighlightBackground\nSpecifies the color to display in the traversal highlight region when\nthe widget does not have the input focus.\n.OP \\-highlightcolor highlightColor HighlightColor\nSpecifies the color to use for the traversal highlight rectangle that is\ndrawn around the widget when it has the input focus.\n.OP \\-highlightthickness highlightThickness HighlightThickness\nSpecifies a non-negative value indicating the width of the highlight\nrectangle to draw around the outside of the widget when it has the\ninput focus.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nIf the value is zero, no focus highlight is drawn around the widget.\n.OP \\-image image Image\nSpecifies an image to display in the widget, which must have been\ncreated with the \\fBimage create\\fR command.\nTypically, if the \\fB\\-image\\fR option is specified then it overrides other\noptions that specify a bitmap or textual value to display in the\nwidget, though this is controlled by the \\fB\\-compound\\fR option;\nthe \\fB\\-image\\fR option may be reset to an empty string to re-enable\na bitmap or text display.\n.OP \\-insertbackground insertBackground Foreground\nSpecifies the color to use as background in the area covered by the\ninsertion cursor.  This color will normally override either the normal\nbackground for the widget (or the selection background if the insertion\ncursor happens to fall in the selection).\n.OP \\-insertborderwidth insertBorderWidth BorderWidth\nSpecifies a non-negative value indicating the width\nof the 3-D border to draw around the insertion cursor.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.OP \\-insertofftime insertOffTime OffTime\nSpecifies a non-negative integer value indicating the number of\nmilliseconds the insertion cursor should remain\n.QW off\nin each blink cycle.\nIf this option is zero then the cursor does not blink:  it is on\nall the time.\n.OP \\-insertontime insertOnTime OnTime\nSpecifies a non-negative integer value indicating the number of\nmilliseconds the insertion cursor should remain\n.QW on\nin each blink cycle.\n.OP \\-insertwidth insertWidth InsertWidth\nSpecifies a non-negative value indicating the total width of the insertion cursor.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nIf a border has been specified for the insertion\ncursor (using the \\fB\\-insertborderwidth\\fR option), the border\nwill be drawn inside the width specified by the \\fB\\-insertwidth\\fR\noption.\n.OP \\-jump jump Jump\nFor widgets with a slider that can be dragged to adjust a value,\nsuch as scrollbars, this option determines when\nnotifications are made about changes in the value.\nThe option's value must be a boolean of the form accepted by\n\\fBTcl_GetBoolean\\fR.\nIf the value is false, updates are made continuously as the\nslider is dragged.\nIf the value is true, updates are delayed until the mouse button\nis released to end the drag;  at that point a single notification\nis made (the value\n.QW jumps\nrather than changing smoothly).\n.OP \\-justify justify Justify\nWhen there are multiple lines of text displayed in a widget, this\noption determines how the lines line up with each other.\nMust be one of \\fBleft\\fR, \\fBcenter\\fR, or \\fBright\\fR.\n\\fBLeft\\fR means that the lines' left edges all line up, \\fBcenter\\fR\nmeans that the lines' centers are aligned, and \\fBright\\fR means\nthat the lines' right edges line up.\n.OP \\-orient orient Orient\nFor widgets that can lay themselves out with either a horizontal\nor vertical orientation, such as scrollbars, this option specifies\nwhich orientation should be used.  Must be either \\fBhorizontal\\fR\nor \\fBvertical\\fR or an abbreviation of one of these.\n.OP \\-padx padX Pad\nSpecifies a non-negative value indicating how much extra space\nto request for the widget in the X-direction.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nWhen computing how large a window it needs, the widget will\nadd this amount to the width it would normally need (as determined\nby the width of the things displayed in the widget);  if the geometry\nmanager can satisfy this request, the widget will end up with extra\ninternal space to the left and/or right of what it displays inside.\nMost widgets only use this option for padding text:  if they are\ndisplaying a bitmap or image, then they usually ignore padding\noptions.\n.OP \\-pady padY Pad\nSpecifies a non-negative value indicating how much extra space\nto request for the widget in the Y-direction.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nWhen computing how large a window it needs, the widget will add\nthis amount to the height it would normally need (as determined by\nthe height of the things displayed in the widget);  if the geometry\nmanager can satisfy this request, the widget will end up with extra\ninternal space above and/or below what it displays inside.\nMost widgets only use this option for padding text:  if they are\ndisplaying a bitmap or image, then they usually ignore padding\noptions.\n.OP \\-placeholder placeHolder PlaceHolder\nSpecifies a help text string to display if no text is otherwise displayed,\nthat is when the widget is empty. The placeholder text is displayed using\nthe values of the \\fB\\-font\\fR and \\fB\\-justify\\fR options.\n.OP \\-placeholderforeground placeholderForeground PlaceholderForeground\nSpecifies the foreground color to use when the placeholder text is\ndisplayed. The default color is platform-specific.\n.OP \\-relief relief Relief\nSpecifies the 3-D effect desired for the widget.  Acceptable\nvalues are \\fBraised\\fR, \\fBsunken\\fR, \\fBflat\\fR, \\fBridge\\fR,\n\\fBsolid\\fR, and \\fBgroove\\fR.\nThe value\nindicates how the interior of the widget should appear relative\nto its exterior;  for example, \\fBraised\\fR means the interior of\nthe widget should appear to protrude from the screen, relative to\nthe exterior of the widget.\n.OP \\-repeatdelay repeatDelay RepeatDelay\nSpecifies the number of milliseconds a button or key must be held\ndown before it begins to auto-repeat.  Used, for example, on the\nup- and down-arrows in scrollbars.\n.OP \\-repeatinterval repeatInterval RepeatInterval\nUsed in conjunction with \\fB\\-repeatdelay\\fR:  once auto-repeat\nbegins, this option determines the number of milliseconds between\nauto-repeats.\n.OP \\-selectbackground selectBackground Foreground\nSpecifies the background color to use when displaying selected\nitems.\n.OP \\-selectborderwidth selectBorderWidth BorderWidth\nSpecifies a non-negative value indicating the width\nof the 3-D border to draw around selected items.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.OP \\-selectforeground selectForeground Background\nSpecifies the foreground color to use when displaying selected\nitems.\n.OP \\-setgrid setGrid SetGrid\nSpecifies a boolean value that determines whether this widget controls the\nresizing grid for its top-level window.\nThis option is typically used in text widgets, where the information\nin the widget has a natural size (the size of a character) and it makes\nsense for the window's dimensions to be integral numbers of these units.\nThese natural window sizes form a grid.\nIf the \\fB\\-setgrid\\fR option is set to true then the widget will\ncommunicate with the window manager so that when the user interactively\nresizes the top-level window that contains the widget, the dimensions of\nthe window will be displayed to the user in grid units and the window\nsize will be constrained to integral numbers of grid units.\nSee the section \\fBGRIDDED GEOMETRY MANAGEMENT\\fR in the \\fBwm\\fR manual\nentry for more details.\n.OP \\-takefocus takeFocus TakeFocus\nDetermines whether the window accepts the focus during keyboard\ntraversal (e.g., Tab and Shift-Tab).\nBefore setting the focus to a window, the traversal scripts\nconsult the value of the \\fB\\-takefocus\\fR option.\nA value of \\fB0\\fR means that the window should be skipped entirely\nduring keyboard traversal.\n\\fB1\\fR means that the window should receive the input\nfocus as long as it is viewable (it and all of its ancestors are mapped).\nAn empty value for the option means that the traversal scripts make\nthe decision about whether or not to focus on the window:  the current\nalgorithm is to skip the window if it is\ndisabled, if it has no key bindings, or if it is not viewable.\nIf the value has any other form, then the traversal scripts take\nthe value, append the name of the window to it (with a separator space),\nand evaluate the resulting string as a Tcl script.\nThe script must return \\fB0\\fR, \\fB1\\fR, or an empty string:  a\n\\fB0\\fR or \\fB1\\fR value specifies whether the window will receive\nthe input focus, and an empty string results in the default decision\ndescribed above.\nNote that this interpretation of the option is defined entirely by\nthe Tcl scripts that implement traversal:  the widget implementations\nignore the option entirely, so you can change its meaning if you\nredefine the keyboard traversal scripts.\n.OP \\-text text Text\nSpecifies a string to be displayed inside the widget.  The way in which\nthe string is displayed depends on the particular widget and may be\ndetermined by other options, such as \\fB\\-anchor\\fR or \\fB\\-justify\\fR.\n.OP \\-textvariable textVariable Variable\nSpecifies the name of a global variable.  The value of the variable is a text\nstring to be displayed inside the widget;  if the variable value changes\nthen the widget will automatically update itself to reflect the new value.\nThe way in which the string is displayed in the widget depends on the\nparticular widget and may be determined by other options, such as\n\\fB\\-anchor\\fR or \\fB\\-justify\\fR.\n.OP \\-troughcolor troughColor Background\nSpecifies the color to use for the rectangular trough areas\nin widgets such as scrollbars and scales.  This option is ignored for\nscrollbars on Windows (native widget does not recognize this option).\n.OP \\-underline underline Underline\nSpecifies the integer index of a character to underline in the widget.\nThis option is used by the default bindings to implement keyboard\ntraversal for menu buttons and menu entries.\n0 corresponds to the first character of the text displayed in the\nwidget, 1 to the next character, and so on. \\fBend\\fR corresponds to the\nlast character, \\fBend\\fR-1 to the before last character, and so on.\n.OP \\-wraplength wrapLength WrapLength\nFor widgets that can perform word-wrapping, this option specifies\nthe maximum line length.\nLines that would exceed this length are wrapped onto the next line,\nso that no line is longer than the specified length.\nThe value may be specified in any of the standard forms for\nscreen distances.\nIf this value is negative or zero then no wrapping is done:  lines\nwill break only at newline characters in the text.\n.OP \\-xscrollcommand xScrollCommand ScrollCommand\nSpecifies the prefix for a command used to communicate with horizontal\nscrollbars.\nWhen the view in the widget's window changes (or\nwhenever anything else occurs that could change the display in a\nscrollbar, such as a change in the total size of the widget's\ncontents), the widget will\ngenerate a Tcl command by concatenating the scroll command and\ntwo numbers.\nEach of the numbers is a fraction between 0 and 1, which indicates\na position in the document.  0 indicates the beginning of the document,\n1 indicates the end, .333 indicates a position one third the way through\nthe document, and so on.\nThe first fraction indicates the first information in the document\nthat is visible in the window, and the second fraction indicates\nthe information just after the last portion that is visible.\nThe command is\nthen passed to the Tcl interpreter for execution.  Typically the\n\\fB\\-xscrollcommand\\fR option consists of the path name of a scrollbar\nwidget followed by\n.QW set ,\ne.g.\n.QW \".x.scrollbar set\" :\nthis will cause\nthe scrollbar to be updated whenever the view in the window changes.\nIf this option is not specified, then no command will be executed.\n.OP \\-yscrollcommand yScrollCommand ScrollCommand\nSpecifies the prefix for a command used to communicate with vertical\nscrollbars.  This option is treated in the same way as the\n\\fB\\-xscrollcommand\\fR option, except that it is used for vertical\nscrollbars and is provided by widgets that support vertical scrolling.\nSee the description of \\fB\\-xscrollcommand\\fR for details\non how this option is used.\n.SH \"SEE ALSO\"\ncolors, cursors, font\n.SH KEYWORDS\nclass, name, standard option, switch\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/pack.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH pack n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\npack \\- Geometry manager that packs around edges of cavity\n.SH SYNOPSIS\n\\fBpack \\fIoption arg \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBpack\\fR command is used to communicate with the packer,\na geometry manager that arranges the children of a parent by\npacking them in order around the edges of the parent.\nThe \\fBpack\\fR command can have any of several forms, depending\non the \\fIoption\\fR argument:\n.TP\n\\fBpack \\fIwindow \\fR?\\fIwindow ...\\fR? ?\\fIoptions\\fR?\n.\nIf the first argument to \\fBpack\\fR is a window name (any value\nstarting with\n.QW . ),\nthen the command is processed in the same way as \\fBpack configure\\fR.\n.\\\" METHOD: configure\n.TP\n\\fBpack configure \\fIwindow \\fR?\\fIwindow ...\\fR? ?\\fIoptions\\fR?\n.\nThe arguments consist of the names of one or more content windows\nfollowed by pairs of arguments that specify how\nto manage the content.\nSee \\fBTHE PACKER ALGORITHM\\fR below for details on how the options\nare used by the packer.\nThe following options are supported:\n.RS\n.\\\" OPTION: -after\n.TP\n\\fB\\-after \\fIother\\fR\n.\n\\fIOther\\fR must the name of another window.\nUse its container as the container for the content, and insert\nthe content just after \\fIother\\fR in the packing order.\n.\\\" OPTION: -anchor\n.TP\n\\fB\\-anchor \\fIanchor\\fR\n.\n\\fIAnchor\\fR must be a valid anchor position such as \\fBn\\fR\nor \\fBsw\\fR; it specifies where to position each content in its\nparcel.\nDefaults to \\fBcenter\\fR.\n.\\\" OPTION: -before\n.TP\n\\fB\\-before \\fIother\\fR\n.\n\\fIOther\\fR must the name of another window.\nUse its container as the container for the content, and insert\nthe content just before \\fIother\\fR in the packing order.\n.\\\" OPTION: -expand\n.TP\n\\fB\\-expand \\fIboolean\\fR\n.\nSpecifies whether the content should be expanded to consume\nextra space in their container.\n\\fIBoolean\\fR may have any proper boolean value, such as \\fB1\\fR\nor \\fBno\\fR.\nDefaults to 0.\n.\\\" OPTION: -fill\n.TP\n\\fB\\-fill \\fIstyle\\fR\n.\nIf a content's parcel is larger than its requested dimensions, this\noption may be used to stretch the content.\n\\fIStyle\\fR must have one of the following values:\n.RS\n.IP \\fBnone\\fR\nGive the content its requested dimensions plus any internal padding\nrequested with \\fB\\-ipadx\\fR or \\fB\\-ipady\\fR.  This is the default.\n.IP \\fBx\\fR\nStretch the content horizontally to fill the entire width of its\nparcel (except leave external padding as specified by \\fB\\-padx\\fR).\n.IP \\fBy\\fR\nStretch the content vertically to fill the entire height of its\nparcel (except leave external padding as specified by \\fB\\-pady\\fR).\n.IP \\fBboth\\fR\nStretch the content both horizontally and vertically.\n.RE\n.\\\" OPTION: -in\n.TP\n\\fB\\-in \\fIcontainer\\fR\n.\nInsert the window at the end of the packing order for the container\nwindow given by \\fIcontainer\\fR.\n.\\\" OPTION: -ipadx\n.TP\n\\fB\\-ipadx \\fIamount\\fR\n.\n\\fIAmount\\fR specifies how much horizontal internal padding to\nleave on each side of the content.\n\\fIAmount\\fR must be a valid screen distance, such as \\fB2\\fR or \\fB.5c\\fR.\nIt defaults to 0.\n.\\\" OPTION: -ipady\n.TP\n\\fB\\-ipady \\fIamount\\fR\n.\n\\fIAmount\\fR specifies how much vertical internal padding to\nleave on each side of the content.\n\\fIAmount\\fR  defaults to 0.\n.\\\" OPTION: -padx\n.TP\n\\fB\\-padx \\fIamount\\fR\n.\n\\fIAmount\\fR specifies how much horizontal external padding to\nleave on each side of the content.  \\fIAmount\\fR may be a list\nof two values to specify padding for left and right separately.\n\\fIAmount\\fR defaults to 0.\n.\\\" OPTION: -pady\n.TP\n\\fB\\-pady \\fIamount\\fR\n.\n\\fIAmount\\fR specifies how much vertical external padding to\nleave on each side of the content.  \\fIAmount\\fR may be a list\nof two values to specify padding for top and bottom separately.\n\\fIAmount\\fR defaults to 0.\n.\\\" OPTION: -side\n.TP\n\\fB\\-side \\fIside\\fR\n.\nSpecifies which side of the container the content will be packed against.\nMust be \\fBleft\\fR, \\fBright\\fR, \\fBtop\\fR, or \\fBbottom\\fR.\nDefaults to \\fBtop\\fR.\n.LP\nIf no \\fB\\-in\\fR, \\fB\\-after\\fR or \\fB\\-before\\fR option is specified\nthen each of the content will be inserted at the end of the packing list\nfor its parent unless it is already managed by the packer (in which\ncase it will be left where it is).\nIf one of these options is specified then all the content will be\ninserted at the specified point.\nIf any of the content are already managed by the geometry manager\nthen any unspecified options for them retain their previous values rather\nthan receiving default values.\n.RE\n.\\\" METHOD: content\n.TP\n\\fBpack content \\fIwindow\\fR\n.\nReturns a list of all of the content windows in the packing order for\n\\fIwindow\\fR. The order of the content windows in the list is the same as\ntheir order in the packing order.\nIf \\fIwindow\\fR has no content then an empty string is returned.\n.\\\" METHOD: forget\n.TP\n\\fBpack forget \\fIwindow \\fR?\\fIwindow ...\\fR?\n.\nRemoves each of the \\fIwindow\\fRs from the packing order for its\ncontainer and unmaps their windows.\nThe content will no longer be managed by the packer.\n.RS\n.PP\n.VS \"TIP 518\"\nIf the last content window of the container becomes unmanaged, this will\nalso send the virtual event \\fB<<NoManagedChild>>\\fR to the container; the\ncontainer may choose to resize itself (or otherwise respond) to such a change.\n.VE \"TIP 518\"\n.RE\n.\\\" METHOD: info\n.TP\n\\fBpack info \\fIwindow\\fR\n.\nReturns a list whose elements are the current configuration state of\nthe window given by \\fIwindow\\fR in the same option-value form that\nmight be specified to \\fBpack configure\\fR.\nThe first two elements of the list are\n.QW \"\\fB\\-in \\fIcontainer\\fR\"\nwhere \\fIcontainer\\fR is the window's container.\n.\\\" METHOD: propagate\n.TP\n\\fBpack propagate \\fIcontainer\\fR ?\\fIboolean\\fR?\n.\nIf \\fIboolean\\fR has a true boolean value such as \\fB1\\fR or \\fBon\\fR\nthen propagation is enabled for \\fIcontainer\\fR, which must be a window\nname (see \\fBGEOMETRY PROPAGATION\\fR below).\nIf \\fIboolean\\fR has a false boolean value then propagation is\ndisabled for \\fIcontainer\\fR.\nIn either of these cases an empty string is returned.\nIf \\fIboolean\\fR is omitted then the command returns \\fB0\\fR or\n\\fB1\\fR to indicate whether propagation is currently enabled\nfor \\fIcontainer\\fR.\nPropagation is enabled by default.\n.\\\" METHOD: slaves\n.TP\n\\fBpack slaves \\fIwindow\\fR\n.\nSynonym for \\fBpack content \\fIwindow\\fR.\n.SH \"THE PACKER ALGORITHM\"\n.PP\nFor each container the packer maintains an ordered list of content\nwindows called the \\fIpacking list\\fR.\nThe \\fB\\-in\\fR, \\fB\\-after\\fR, and \\fB\\-before\\fR configuration\noptions are used to specify the container for each content and the content's\nposition in the packing list.\nIf none of these options is given for a content then the content\nis added to the end of the packing list for its parent.\n.PP\nThe packer arranges the content windows for a container by scanning the\npacking list in order.\nAt the time it processes each content, a rectangular area within\nthe container is still unallocated.\nThis area is called the \\fIcavity\\fR;  for the first content it\nis the entire area of the container.\n.PP\nFor each content the packer carries out the following steps:\n.IP [1]\nThe packer allocates a rectangular \\fIparcel\\fR for the content\nalong the side of the cavity given by the content's \\fB\\-side\\fR option.\nIf the side is top or bottom then the width of the parcel is\nthe width of the cavity and its height is the requested height\nof the content plus the \\fB\\-ipady\\fR and \\fB\\-pady\\fR options.\nFor the left or right side the height of the parcel is\nthe height of the cavity and the width is the requested width\nof the content plus the \\fB\\-ipadx\\fR and \\fB\\-padx\\fR options.\nThe parcel may be enlarged further because of the \\fB\\-expand\\fR\noption (see \\fBEXPANSION\\fR below)\n.IP [2]\nThe packer chooses the dimensions of the content.\nThe width will normally be the content's requested width plus\ntwice its \\fB\\-ipadx\\fR option and the height will normally be\nthe content's requested height plus twice its \\fB\\-ipady\\fR\noption.\nHowever, if the \\fB\\-fill\\fR option is \\fBx\\fR or \\fBboth\\fR\nthen the width of the content is expanded to fill the width of the parcel,\nminus twice the \\fB\\-padx\\fR option.\nIf the \\fB\\-fill\\fR option is \\fBy\\fR or \\fBboth\\fR\nthen the height of the content is expanded to fill the height of the parcel,\nminus twice the \\fB\\-pady\\fR option.\n.IP [3]\nThe packer positions the content over its parcel.\nIf the content is smaller than the parcel then the \\fB\\-anchor\\fR\noption determines where in the parcel the content will be placed.\nIf \\fB\\-padx\\fR or \\fB\\-pady\\fR is non-zero, then the given\namount of external padding will always be left between the\ncontent and the edges of the parcel.\n.PP\nOnce a given content has been packed, the area of its parcel\nis subtracted from the cavity, leaving a smaller rectangular\ncavity for the next content.\nIf a content does not use all of its parcel, the unused space\nin the parcel will not be used by subsequent content.\nIf the cavity should become too small to meet the needs of\na content then the content will be given whatever space is\nleft in the cavity.\nIf the cavity shrinks to zero size, then all remaining content\non the packing list will be unmapped from the screen until\nthe container window becomes large enough to hold them again.\n.SS \"EXPANSION\"\n.PP\nIf a container window is so large that there will be extra space\nleft over after all of its content have been packed, then the\nextra space is distributed uniformly among all of the content\nfor which the \\fB\\-expand\\fR option is set.\nExtra horizontal space is distributed among the expandable\ncontent whose \\fB\\-side\\fR is \\fBleft\\fR or \\fBright\\fR,\nand extra vertical space is distributed among the expandable\ncontent whose \\fB\\-side\\fR is \\fBtop\\fR or \\fBbottom\\fR.\n.SS \"GEOMETRY PROPAGATION\"\n.PP\nThe packer normally computes how large a container must be to\njust exactly meet the needs of its content, and it sets the\nrequested width and height of the container to these dimensions.\nThis causes geometry information to propagate up through a\nwindow hierarchy to a top-level window so that the entire\nsub-tree sizes itself to fit the needs of the leaf windows.\nHowever, the \\fBpack propagate\\fR command may be used to\nturn off propagation for one or more containers.\nIf propagation is disabled then the packer will not set\nthe requested width and height of the packer.\nThis may be useful if, for example, you wish for a container\nwindow to have a fixed size that you specify.\n.SH \"RESTRICTIONS ON CONTAINER WINDOWS\"\n.PP\nThe container for each content must either be the content's parent\n(the default) or a descendant of the content's parent.\nThis restriction is necessary to guarantee that the\ncontent can be placed over any part of its container that is\nvisible without danger of the content being clipped by its parent.\n.SH \"PACKING ORDER\"\n.PP\nIf the container for a content is not its parent then you must make sure\nthat the content is higher in the stacking order than the container.\nOtherwise the container will obscure the content and it will appear as\nif the content has not been packed correctly.\nThe easiest way to make sure the content is higher than the container is\nto create the container window first:  the most recently created window\nwill be highest in the stacking order.\nOr, you can use the \\fBraise\\fR and \\fBlower\\fR commands to change\nthe stacking order of either the container or the content.\n.SH EXAMPLE\n.PP\n.CS\n# Make the widgets\nlabel .t -text \"This widget is at the top\"    -bg red\nlabel .b -text \"This widget is at the bottom\" -bg green\nlabel .l -text \"Left\\enHand\\enSide\"\nlabel .r -text \"Right\\enHand\\enSide\"\ntext .mid\n\\&.mid insert end \"This layout is like Java's BorderLayout\"\n# Lay them out\n\\fBpack\\fR .t   -side top    -fill x\n\\fBpack\\fR .b   -side bottom -fill x\n\\fBpack\\fR .l   -side left   -fill y\n\\fBpack\\fR .r   -side right  -fill y\n\\fBpack\\fR .mid -expand 1    -fill both\n.CE\n.SH \"SEE ALSO\"\ngrid(n), place(n)\n.SH KEYWORDS\ngeometry manager, location, packer, parcel, propagation, size\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/palette.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1995-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_setPalette n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_setPalette, tk_bisque \\- Modify the Tk color palette\n.SH SYNOPSIS\n.nf\n\\fBtk_setPalette \\fIbackground\\fR\n\\fBtk_setPalette \\fIname value \\fR?\\fIname value ...\\fR?\n\\fBtk_bisque\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk_setPalette\\fR procedure changes the color scheme for Tk.\nIt does this by modifying the colors of existing widgets and by changing\nthe option database so that future widgets will use the new color scheme.\nIf \\fBtk_setPalette\\fR is invoked with a single argument, the\nargument is the name of a color to use as the normal background\ncolor;  \\fBtk_setPalette\\fR will compute a complete color palette\nfrom this background color.\nAlternatively, the arguments to \\fBtk_setPalette\\fR may consist of any number\nof \\fIname\\fR\\-\\fIvalue\\fR pairs, where the first argument of the pair\nis the name of an option in the Tk option database and the second\nargument is the new value to use for that option.  The following\ndatabase names are currently supported:\n.DS\n.ta 4c 8c\n\\fBactiveBackground\\fR\t\\fBforeground\\fR\t\\fBselectColor\\fR\n\\fBactiveForeground\\fR\t\\fBhighlightBackground\\fR\t\\fBselectBackground\\fR\n\\fBbackground\\fR\t\\fBhighlightColor\\fR\t\\fBselectForeground\\fR\n\\fBdisabledForeground\\fR\t\\fBinsertBackground\\fR\t\\fBtroughColor\\fR\n.DE\n\\fBtk_setPalette\\fR tries to compute reasonable defaults for any\noptions that you do not specify.  You can specify options other\nthan the above ones and Tk will change those options on widgets as\nwell.  This feature may be useful if you are using custom widgets with\nadditional color options.\n.PP\nOnce it has computed the new value to use for each of the color options,\n\\fBtk_setPalette\\fR scans the widget hierarchy to modify the options\nof all existing widgets.  For each widget, it checks to see if any\nof the above options is defined for the widget.  If so, and if the\noption's current value is the default, then the value is changed;  if\nthe option has a value other than the default, \\fBtk_setPalette\\fR\nwill not change it.  The default for an option is the one provided by\nthe widget (\\fB[lindex [$w configure $option] 3]\\fR) unless\n\\fBtk_setPalette\\fR has been run previously, in which case it is the\nvalue specified in the previous invocation of \\fBtk_setPalette\\fR.\n.PP\nAfter modifying all the widgets in the application, \\fBtk_setPalette\\fR\nadds options to the option database to change the defaults for\nwidgets created in the future.  The new options are added at\npriority \\fBwidgetDefault\\fR, so they will be overridden by options\nfrom the .Xdefaults file or options specified on the command-line\nthat creates a widget.\n.PP\nThe procedure \\fBtk_bisque\\fR is provided for backward compatibility:\nit restores the application's colors to the light brown\n.PQ bisque\ncolor scheme used in Tk 3.6 and earlier versions.\n.SH KEYWORDS\nbisque, color, palette\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/panedwindow.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH panedwindow n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\npanedwindow \\- Create and manipulate 'panedwindow' split container widgets\n.SH SYNOPSIS\n\\fBpanedwindow\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-background\t\\-borderwidth\t\\-cursor\n\\-orient\t\\-relief\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-handlepad handlePad HandlePad\nWhen sash handles are drawn, specifies the distance from the top or\nleft end of the sash (depending on the orientation of the widget) at\nwhich to draw the handle.  May be any value accepted by \\fBTk_GetPixels\\fR.\n.OP \\-handlesize handleSize HandleSize\nSpecifies the side length of a sash handle.  Handles are always\ndrawn as squares.  May be any value accepted by \\fBTk_GetPixels\\fR.\n.OP \\-height height Height\nSpecifies a desired height for the overall panedwindow widget. May be any\nvalue accepted by \\fBTk_GetPixels\\fR. If an empty string, the widget will be\nmade high enough to allow all contained widgets to have their natural height.\n.OP \\-opaqueresize opaqueResize OpaqueResize\nSpecifies whether panes should be resized as a sash is moved (true),\nor if resizing should be deferred until the sash is placed (false).\nIn the latter case, a\n.QW ghost\nversion of the sash is displayed during the resizing to show where the\npanes will be resized to when releasing the mouse button. This\n.QW ghost\nversion of the sash is the proxy. It's rendering can be configured\nusing the \\fB\\-proxybackground\\fR, \\fB\\-proxyborderwidth\\fR and\n\\fB\\-proxyrelief\\fR options.\n.OP \\-proxybackground proxyBackground ProxyBackground\nBackground color to use when drawing the proxy. If an empty string, the\nvalue of the \\fB\\-background\\fR option will be used.\n.OP \\-proxyborderwidth proxyBorderWidth ProxyBorderWidth\nSpecifies the borderwidth of the proxy. May be any value accepted by\n\\fBTk_GetPixels\\fR.\n.OP \\-proxyrelief proxyRelief ProxyRelief\nRelief to use when drawing the proxy. May be any of the standard Tk\nrelief values. If an empty string, the value of the \\fB\\-sashrelief\\fR\noption will be used.\n.OP \\-sashcursor sashCursor SashCursor\nMouse cursor to use when over a sash.  If null,\n\\fBsb_h_double_arrow\\fR will be used for horizontal panedwindows, and\n\\fBsb_v_double_arrow\\fR will be used for vertical panedwindows.\n.OP \\-sashpad sashPad SashPad\nSpecifies the amount of padding to leave of each side of a sash.  May\nbe any value accepted by \\fBTk_GetPixels\\fR.\n.OP \\-sashrelief sashRelief SashRelief\nRelief to use when drawing a sash.  May be any of the standard Tk\nrelief values.\n.OP \\-sashwidth sashWidth SashWidth\nSpecifies the width of each sash.  May be any value accepted by\n\\fBTk_GetPixels\\fR.\n.OP \\-showhandle showHandle ShowHandle\nSpecifies whether sash handles should be shown.  May be any valid Tcl\nboolean value.\n.OP \\-width width Width\nSpecifies a desired width for the overall panedwindow widget. May be any\nvalue accepted by \\fBTk_GetPixels\\fR. If an empty string, the widget will be\nmade wide enough to allow all contained widgets to have their natural width.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBpanedwindow\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a panedwindow widget.\nAdditional options, described above, may be specified on the command\nline or in the option database to configure aspects of the panedwindow\nsuch as its default background color and relief.  The\n\\fBpanedwindow\\fR command returns the path name of the new window.\n.PP\nA panedwindow widget contains any number of panes, arranged\nhorizontally or vertically, according to the value of the\n\\fB\\-orient\\fR option.  Each pane contains one widget, and each pair of\npanes is separated by a moveable (via mouse movements) sash.  Moving a\nsash causes the widgets on either side of the sash to be resized.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBpanedwindow\\fR command creates a new Tcl command whose name is\nthe same as the path name of the panedwindow's window.  This command\nmay be used to invoke various operations on the widget.  It has the\nfollowing general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIPathName\\fR is the name of the command, which is the same as\nthe panedwindow widget's path name.  \\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for panedwindow widgets:\n.\\\" METHOD: add\n.TP\n\\fIpathName \\fBadd \\fIwindow \\fR?\\fIwindow ...\\fR? ?\\fIoption value ...\\fR?\n.\nAdd one or more windows to the panedwindow, each in a separate pane.\nThe arguments consist of the names of one or more windows\nfollowed by pairs of arguments that specify how to manage the windows.\n\\fIOption\\fR may have any of the values accepted by the\n\\fBconfigure\\fR subcommand.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given by\n\\fIoption\\fR.  \\fIOption\\fR may have any of the values accepted by the\n\\fBpanedwindow\\fR command.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure \\fR?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.  If no\n\\fIoption\\fR is specified, returns a list describing all of the\navailable options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string. \\fIOption\\fR may have\nany of the values accepted by the \\fBpanedwindow\\fR command.\n.\\\" METHOD: forget\n.TP\n\\fIpathName \\fBforget \\fIwindow \\fR?\\fIwindow ...\\fR?\n.\nRemove the pane containing \\fIwindow\\fR from the panedwindow.  All\ngeometry management options for \\fIwindow\\fR will be forgotten.\n.\\\" METHOD: identify\n.TP\n\\fIpathName \\fBidentify \\fIx y\\fR\n.\nIdentify the panedwindow component underneath the point given by\n\\fIx\\fR and \\fIy\\fR, in window coordinates.  If the point is over a\nsash or a sash handle, the result is a two element list containing the\nindex of the sash or handle, and a word indicating whether it is over\na sash or a handle, such as {0 sash} or {2 handle}.  If the point is\nover any other part of the panedwindow, the result is an empty list.\n.\\\" METHOD: panecget\n.TP\n\\fIpathName \\fBpanecget \\fIwindow option\\fR\n.\nQuery a management option for \\fIwindow\\fR.  \\fIOption\\fR may be any\nvalue allowed by the \\fBpaneconfigure\\fR subcommand.\n.\\\" METHOD: paneconfigure\n.TP\n\\fIpathName \\fBpaneconfigure \\fIwindow \\fR?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the management options for \\fIwindow\\fR.  If no\n\\fIoption\\fR is specified, returns a list describing all of the\navailable options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.  The following options\nare supported:\n.RS\n.\\\" OPTION: -after\n.TP\n\\fB\\-after \\fIwindow\\fR\n.\nInsert the window after the window specified.  \\fIwindow\\fR should be the\nname of a window already managed by \\fIpathName\\fR.\n.\\\" OPTION: -before\n.TP\n\\fB\\-before \\fIwindow\\fR\n.\nInsert the window before the window specified.  \\fIwindow\\fR should be\nthe name of a window already managed by \\fIpathName\\fR.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIsize\\fR\n.\nSpecify a height for the window.  The height will be the outer\ndimension of the window including its border, if any.  If \\fIsize\\fR\nis an empty string, or if \\fB\\-height\\fR is not specified, then the\nheight requested internally by the window will be used initially; the\nheight may later be adjusted by the movement of sashes in the\npanedwindow.  \\fISize\\fR may be any value accepted by \\fBTk_GetPixels\\fR.\n.\\\" OPTION: -hide\n.TP\n\\fB\\-hide \\fIboolean\\fR\n.\nControls the visibility of a pane.  When the \\fIboolean\\fR is true\n(according to \\fBTcl_GetBoolean\\fR) the pane will not be visible, but\nit will still be maintained in the list of panes.\n.\\\" OPTION: -minsize\n.TP\n\\fB\\-minsize \\fIn\\fR\n.\nSpecifies that the size of the window cannot be made less than\n\\fIn\\fR.  This constraint only affects the size of the widget in the\npaned dimension \\(em the x dimension for horizontal panedwindows, the y\ndimension for vertical panedwindows.  May be any value accepted by\n\\fBTk_GetPixels\\fR.\n.\\\" OPTION: -padx\n.TP\n\\fB\\-padx \\fIn\\fR\n.\nSpecifies a non-negative value indicating how much extra space to\nleave on each side of the window in the X-direction.  The value may\nhave any of the forms accepted by \\fBTk_GetPixels\\fR.\n.\\\" OPTION: -pady\n.TP\n\\fB\\-pady \\fIn\\fR\n.\nSpecifies a non-negative value indicating how much extra space to\nleave on each side of the window in the Y-direction.  The value may\nhave any of the forms accepted by \\fBTk_GetPixels\\fR.\n.\\\" OPTION: -sticky\n.TP\n\\fB\\-sticky \\fIstyle\\fR\n.\nIf a window's pane is larger than the requested dimensions of the\nwindow, this option may be used to position (or stretch) the window\nwithin its pane.  \\fIStyle\\fR  is a string that contains zero or more\nof the characters \\fBn\\fR, \\fBs\\fR, \\fBe\\fR or \\fBw\\fR.  The string\ncan optionally contains spaces or commas, but they are ignored.  Each\nletter refers to a side (north, south, east, or west) that the window\nwill\n.QW stick\nto.  If both \\fBn\\fR and \\fBs\\fR (or \\fBe\\fR and \\fBw\\fR)\nare specified, the window will be stretched to fill the entire height\n(or width) of its cavity.\n.\\\" OPTION: -stretch\n.TP\n\\fB\\-stretch \\fIwhen\\fR\n.\nControls how extra space is allocated to each of the panes.\n\\fIWhen\\fR is one of \\fBalways\\fR, \\fBfirst\\fR, \\fBlast\\fR,\n\\fBmiddle\\fR, and \\fBnever\\fR.\nThe panedwindow will calculate the required size of all its panes. Any\nremaining (or deficit) space will be distributed to those panes marked\nfor stretching. The space will be distributed based on each panes\ncurrent ratio of the whole.  The \\fIwhen\\fR values have the following\ndefinition:\n.RS\n.IP \\fBalways\\fR\nThis pane will always stretch.\n.IP \\fBfirst\\fR\nOnly if this pane is the first pane (left-most or top-most) will it\nstretch.\n.IP \\fBlast\\fR\nOnly if this pane is the last pane (right-most or bottom-most) will it\nstretch.  This is the default value.\n.IP \\fBmiddle\\fR\nOnly if this pane is not the first or last pane will it stretch.\n.IP \\fBnever\\fR\nThis pane will never stretch.\n.RE\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIsize\\fR\n.\nSpecify a width for the window.  The width will be the outer\ndimension of the window including its border, if any.  If \\fIsize\\fR\nis an empty string, or if \\fB\\-width\\fR is not specified, then the\nwidth requested internally by the window will be used initially; the\nwidth may later be adjusted by the movement of sashes in the\npanedwindow.  \\fISize\\fR may be any value accepted by \\fBTk_GetPixels\\fR.\n.RE\n.\\\" METHOD: panes\n.TP\n\\fIpathName \\fBpanes\\fR\n.\nReturns an ordered list of the widgets managed by \\fIpathName\\fR.\n.\\\" METHOD: proxy\n.TP\n\\fIpathName \\fBproxy \\fR?\\fIargs\\fR?\n.\nThis command is used to query and change the position of the sash\nproxy, used for rubberband-style pane resizing. It can take any of\nthe following forms:\n.RS\n.TP\n\\fIpathName \\fBproxy coord\\fR\n.\nReturn a list containing the x and y coordinates of the most recent\nproxy location.\n.TP\n\\fIpathName \\fBproxy forget\\fR\n.\nRemove the proxy from the display.\n.TP\n\\fIpathName \\fBproxy place \\fIx y\\fR\n.\nPlace the proxy at the given \\fIx\\fR and \\fIy\\fR coordinates.\n.RE\n.\\\" METHOD: sash\n.TP\n\\fIpathName \\fBsash \\fR?\\fIargs\\fR?\n.\nThis command is used to query and change the position of sashes in the\npanedwindow.  It can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fBsash coord \\fIindex\\fR\n.\nReturn the current x and y coordinate pair for the sash given by\n\\fIindex\\fR.  \\fIIndex\\fR must be an integer between 0 and 1 less than\nthe number of panes in the panedwindow.  The coordinates given are\nthose of the top left corner of the region containing the sash.\n.TP\n\\fIpathName \\fBsash dragto \\fIindex x y\\fR\n.\nThis command computes the difference between the given coordinates and the\ncoordinates given to the last \\fBsash mark\\fR command for the given\nsash.  It then moves that sash the computed difference.  The return\nvalue is the empty string.\n.TP\n\\fIpathName \\fBsash mark \\fIindex x y\\fR\n.\nRecords \\fIx\\fR and \\fIy\\fR for the sash given by \\fIindex\\fR; used in\nconjunction with later \\fBsash dragto\\fR commands to move the sash.\n.TP\n\\fIpathName \\fBsash place \\fIindex x y\\fR\n.\nPlace the sash given by \\fIindex\\fR at the given coordinates.\n.RE\n.SH \"RESIZING PANES\"\n.PP\nA pane is resized by grabbing the sash (or sash handle if present) and\ndragging with the mouse.  This is accomplished via mouse motion\nbindings on the widget.  When a sash is moved, the sizes of the panes\non each side of the sash, and thus the widgets in those panes, are\nadjusted.\n.PP\nWhen a pane is resized from outside (e.g. it is packed to expand and\nfill, and the containing toplevel is resized), space is added to the final\n(rightmost or bottommost) pane in the window.\n.PP\nUnlike child windows managed by e.g. pack or grid, the panes managed by a\npanedwindow do not change width or height to accommodate changes in the\nrequested widths or heights of the panes, once these have become mapped.\nTherefore it may be advisable, particularly when creating layouts\ninteractively, to not add a pane to the panedwindow widget until after the\ngeometry requests of that pane has been finalized (i.e., all components of\nthe pane inserted, all options affecting geometry set to their proper\nvalues, etc.).\n.SH \"SEE ALSO\"\nttk::panedwindow(n)\n.SH KEYWORDS\npanedwindow, widget, geometry management\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/photo.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994 The Australian National University\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n'\\\" Author: Paul Mackerras (paulus@cs.anu.edu.au),\n'\\\"\t    Department of Computer Science,\n'\\\"\t    Australian National University.\n'\\\"\n.TH photo n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nphoto \\- Full-color images\n.SH SYNOPSIS\n.nf\n\\fBimage create photo \\fR?\\fIname\\fR? ?\\fIoptions\\fR?\n\n\\fIimageName \\fBblank\\fR\n\\fIimageName \\fBcget \\fIoption\\fR\n\\fIimageName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n\\fIimageName \\fBcopy \\fIsourceImage\\fR ?\\fIoption value(s) ...\\fR?\n\\fIimageName \\fBdata\\fR ?\\fIoption value(s) ...\\fR?\n\\fIimageName \\fBget \\fIx y\\fR ?\\fIoption\\fR?\n\\fIimageName \\fBput \\fIdata\\fR ?\\fIoption value(s) ...\\fR?\n\\fIimageName \\fBread \\fIfilename\\fR ?\\fIoption value(s) ...\\fR?\n\\fIimageName \\fBredither\\fR\n\\fIimageName \\fBtransparency \\fIsubcommand \\fR?\\fIarg ...\\fR?\n\\fIimageName \\fBwrite \\fIfilename\\fR ?\\fIoption value(s) ...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nA photo is an image whose pixels can display any color with a varying\ndegree of transparency (the alpha channel). A photo image is stored\ninternally in full color (32 bits per pixel), and is displayed using\ndithering if necessary.  Image data for a photo image can be obtained\nfrom a file or a string, or it can be supplied from C code through a\nprocedural interface.  At present, only\n.VS 8.6\nPNG,\n.VE 8.6\nGIF, PPM/PGM,\n.VS 9.0\nand (read-only) SVG\n.VE 9.0\nformats are supported, but an interface exists to\nallow additional image file formats to be added easily.  A photo image\nis (semi)transparent if the image data it was obtained from had\ntransparency information. In regions where no image data has been\nsupplied, it is fully transparent. Transparency may also be modified\nwith the \\fBtransparency set\\fR subcommand.\n.SH \"CREATING PHOTOS\"\n.PP\nLike all images, photos are created using the \\fBimage create\\fR\ncommand.\nPhotos support the following \\fIoptions\\fR:\n.\\\" OPTION: -data\n.TP\n\\fB\\-data \\fIstring\\fR\n.\nSpecifies the contents of the image as a string.\n.VS 9.0\nThe string should\ncontain data in the default list-of-lists form,\n.VE 9.0\nbinary data or, for some formats, base64-encoded data (this is\ncurrently guaranteed to be supported for PNG and GIF images). The\nformat of the string must be one of those for which there is an image\nfile format handler that will accept string data.  If both the\n\\fB\\-data\\fR and \\fB\\-file\\fR options are specified, the \\fB\\-file\\fR\noption takes precedence.\n.\\\" OPTION: -format\n.TP\n\\fB\\-format\\fR {\\fIformat-name\\fR ?\\fIoption value ...\\fR?}\n.\nSpecifies the name of the file format for the data specified with the\n\\fB\\-data\\fR or \\fB\\-file\\fR option and optional arguments passed to\nthe format handler. Note that the value of this option must be a Tcl list.\nThis means that the braces may be omitted if the argument has only one\nword. Also, instead of braces, double quotes may be used for quoting.\n.\\\" OPTION: -file\n.TP\n\\fB\\-file \\fIname\\fR\n.\n\\fIname\\fR gives the name of a file that is to be read to supply data\nfor the photo image.  The file format must be one of those for which\nthere is an image file format handler that can read data.\n.\\\" OPTION: -gamma\n.TP\n\\fB\\-gamma \\fIvalue\\fR\n.\nSpecifies that the colors allocated for displaying this image in a\nwindow should be corrected for a non-linear display with the specified\ngamma exponent value.  (The intensity produced by most\nCRT displays is a power function of the input value, to a good\napproximation; gamma is the exponent and is typically around 2).\nThe value specified must be greater than zero.  The default\nvalue is one (no correction).  In general, values greater than one\nwill make the image lighter, and values less than one will make it\ndarker.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fInumber\\fR\n.\nSpecifies the height of the image, in pixels.  This option is useful\nprimarily in situations where the user wishes to build up the contents\nof the image piece by piece.  A value of zero (the default) allows the\nimage to expand or shrink vertically to fit the data stored in it.\n.VS 9.0\n.\\\" OPTION: -metadata\n.TP\n\\fB\\-metadata \\fImetadata\\fR\n.\nSet the metadata dictionary of the image.\nAdditional keys may be set within the metadata dictionary of the image,\nif image data is processed due to a \\fB\\-file\\fR or \\fB\\-data\\fR options\nand the driver outputs any metadata keys.\nSee section \\fBMETADATA DICTIONARY\\fR below.\n.VE 9.0\n.\\\" OPTION: -palette\n.TP\n\\fB\\-palette \\fIpalette-spec\\fR\n.\nSpecifies the resolution of the color cube to be allocated for\ndisplaying this image, and thus the number of colors used from the\ncolormaps of the windows where it is displayed.  The\n\\fIpalette-spec\\fR string may be either a single decimal number,\nspecifying the number of shades of gray to use, or three decimal\nnumbers separated by slashes (/), specifying the number of shades of\nred, green and blue to use, respectively.  If the first form (a single\nnumber) is used, the image will be displayed in monochrome (i.e.,\ngrayscale).\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fInumber\\fR\n.\nSpecifies the width of the image, in pixels.    This option is useful\nprimarily in situations where the user wishes to build up the contents\nof the image piece by piece.  A value of zero (the default) allows the\nimage to expand or shrink horizontally to fit the data stored in it.\n.SH \"IMAGE COMMAND\"\n.PP\nWhen a photo image is created, Tk also creates a new command\nwhose name is the same as the image.\nThis command may be used to invoke various operations\non the image.\nIt has the following general form:\n.CS\n\\fIimageName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.\n.PP\nThose options that write data to the image generally expand the size\nof the image, if necessary, to accommodate the data written to the\nimage, unless the user has specified non-zero values for the\n\\fB\\-width\\fR and/or \\fB\\-height\\fR configuration options, in which\ncase the width and/or height, respectively, of the image will not be\nchanged.\n.PP\nThe following commands are possible for photo images:\n.\\\" METHOD: blank\n.TP\n\\fIimageName \\fBblank\\fR\n.\nBlank the image; that is, set the entire image to have no data, so it\nwill be displayed as transparent, and the background of whatever\nwindow it is displayed in will show through. The metadata dict of the\nimage is not changed.\n.\\\" METHOD: cget\n.TP\n\\fIimageName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the\n\\fBimage create\\fR \\fBphoto\\fR command.\n.\\\" METHOD: configure\n.TP\n\\fIimageName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options for the image.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIimageName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the\n\\fBimage create\\fR \\fBphoto\\fR command.\n.VS 9.0\nNote that setting the \\fB\\-metadata\\fR option without any other option\nwill not invoke the image format driver to recreate the bitmap.\n.VE 9.0\n.\\\" METHOD: copy\n.TP\n\\fIimageName \\fBcopy\\fI sourceImage\\fR ?\\fIoption value(s) ...\\fR?\n.\nCopies a region from the image called \\fIsourceImage\\fR (which must\nbe a photo image) to the image called \\fIimageName\\fR, possibly with\npixel zooming and/or subsampling.  If no options are specified, this\ncommand copies the whole of \\fIsourceImage\\fR into \\fIimageName\\fR,\nstarting at coordinates (0,0) in \\fIimageName\\fR.  The following\noptions may be specified:\n.RS\n.\\\" OPTION: -from\n.TP\n\\fB\\-from \\fIx1 y1 x2 y2\\fR\n.\nSpecifies a rectangular sub-region of the source image to be copied.\n(\\fIx1,y1\\fR) and (\\fIx2,y2\\fR) specify diagonally opposite corners of\nthe rectangle.  If \\fIx2\\fR and \\fIy2\\fR are not specified, the\ndefault value is the bottom-right corner of the source image.  The\npixels copied will include the left and top edges of the specified\nrectangle but not the bottom or right edges.  If the \\fB\\-from\\fR\noption is not given, the default is the whole source image.\n.\\\" OPTION: -to\n.TP\n\\fB\\-to \\fIx1 y1 x2 y2\\fR\n.\nSpecifies a rectangular sub-region of the destination image to be\naffected.  (\\fIx1,y1\\fR) and (\\fIx2,y2\\fR) specify diagonally opposite\ncorners of the rectangle.  If \\fIx2\\fR and \\fIy2\\fR are not specified,\nthe default value is (\\fIx1,y1\\fR) plus the size of the source\nregion (after subsampling and zooming, if specified).  If \\fIx2\\fR and\n\\fIy2\\fR are specified, the source region will be replicated if\nnecessary to fill the destination region in a tiled fashion.\n.\\\" OPTION: -shrink\n.TP\n\\fB\\-shrink\\fR\n.\nSpecifies that the size of the destination image should be reduced, if\nnecessary, so that the region being copied into is at the bottom-right\ncorner of the image.  This option will not affect the width or height\nof the image if the user has specified a non-zero value for the\n\\fB\\-width\\fR or \\fB\\-height\\fR configuration option, respectively.\n.\\\" OPTION: -zoom\n.TP\n\\fB\\-zoom \\fIx y\\fR\n.\nSpecifies that the source region should be magnified by a factor of\n\\fIx\\fR in the X direction and \\fIy\\fR in the Y direction.  If \\fIy\\fR\nis not given, the default value is the same as \\fIx\\fR.  With this\noption, each pixel in the source image will be expanded into a block\nof \\fIx\\fR x \\fIy\\fR pixels in the destination image, all the same\ncolor.  \\fIx\\fR and \\fIy\\fR must be greater than 0.\n.\\\" OPTION: -subsample\n.TP\n\\fB\\-subsample \\fIx y\\fR\n.\nSpecifies that the source image should be reduced in size by using\nonly every \\fIx\\fRth pixel in the X direction and \\fIy\\fRth pixel in\nthe Y direction.  Negative values will cause the image to be flipped\nabout the Y or X axes, respectively.  If \\fIy\\fR is not given, the\ndefault value is the same as \\fIx\\fR.\n.\\\" OPTION: -compositingrule\n.TP\n\\fB\\-compositingrule \\fIrule\\fR\n.\nSpecifies how transparent pixels in the source image are combined with\nthe destination image.  When a compositing rule of \\fIoverlay\\fR is\nset, the old contents of the destination image are visible, as if the\nsource image were printed on a piece of transparent film and placed\nover the top of the destination.  When a compositing rule of \\fIset\\fR\nis set, the old contents of the destination image are discarded and\nthe source image is used as-is.  The default compositing rule is\n\\fIoverlay\\fR.\n.RE\n.\\\" METHOD: data\n.TP\n\\fIimageName \\fBdata\\fR ?\\fIoption value(s) ...\\fR?\n.\nReturns image data in the form of a string.\n.VS 9.0\nThe format of the string depends on the format handler. By default, a\nhuman readable format as a list of lists of pixel data is used, other\nformats can be chosen with the \\fB\\-format\\fR option.\nSee \\fBIMAGE FORMATS\\fR below for details.\n.VE 9.0\nThe following options may be specified:\n.RS\n.\\\" OPTION: -background\n.TP\n\\fB\\-background\\fI color\\fR\n.\nIf the color is specified, the data will not contain any transparency\ninformation. In all transparent pixels the color will be replaced by\nthe specified color.\n.\\\" OPTION: -format\n.TP\n\\fB\\-format\\fR {\\fIformat-name\\fR ?\\fIoption value ...\\fR?}\n.\nSpecifies the name of the image file format handler to use and,\noptionally, arguments to the format handler.  Specifically, this\nsubcommand searches for the first handler whose name matches an\ninitial substring of \\fIformat-name\\fR and which has the capability to\nwrite a string containing this image data.\n.VS 9.0\nIf this option is not given, this subcommand uses the default format\nthat consists of a list (one element per row) of lists (one element\nper pixel/column) of colors in\n.QW \\fB#\\fIrrggbb\\fR\nformat (see \\fBIMAGE FORMATS\\fR below).\n.VE 9.0\nNote that the value of this option must be a Tcl list.\nThis means that the braces may be omitted if the argument has only one\nword. Also, instead of braces, double quotes may be used for quoting.\n.\\\" OPTION: -from\n.TP\n\\fB\\-from \\fIx1 y1 x2 y2\\fR\n.\nSpecifies a rectangular region of \\fIimageName\\fR to be returned.\nIf only \\fIx1\\fR and \\fIy1\\fR are specified, the region\nextends from \\fI(x1,y1)\\fR to the bottom-right corner of\n\\fIimageName\\fR.  If all four coordinates are given, they specify\ndiagonally opposite corners of the rectangular region, including x1,y1\nand excluding x2,y2.  The default, if this option is not given, is the\nwhole image.\n.\\\" OPTION: -grayscale\n.TP\n\\fB\\-grayscale\\fR\n.\nIf this options is specified, the data will not contain color\ninformation. All pixel data will be transformed into grayscale.\n.VS 9.0\n.\\\" OPTION: -metadata\n.TP\n\\fB\\-metadata\\fI metadata\\fR\n.\nImage format handler may use metadata to be included in the returned\ndata string.\nThe specified \\fImetadata\\fR is passed to the driver for inclusion in the\ndata.\nIf no \\fB\\-metadata\\fR option is given, the current metadata of the\nimage is used.\n.VE 9.0\n.RE\n.\\\" METHOD: get\n.TP\n\\fIimageName \\fBget\\fI x y\\fR ?\\fB\\-withalpha\\fR?\n.\nReturns the color of the pixel at coordinates (\\fIx\\fR,\\fIy\\fR) in the\nimage as a list of three integers between 0 and 255, representing the\nred, green and blue components respectively. If the \\fB\\-withalpha\\fR\noption is specified, the returned list will have a fourth element\nrepresenting the alpha value of the pixel as an integer between 0 and\n255.\n.\\\" METHOD: put\n.TP\n\\fIimageName \\fBput\\fI data\\fR ?\\fIoption value(s) ...\\fR?\n.\nSets pixels in \\fI imageName\\fR to the data specified in \\fIdata\\fR.\n.VS 9.0\nThis command searches the list of image file format handlers for\na handler that can interpret the data in \\fIdata\\fR, and then reads\nthe image encoded within into \\fIimageName\\fR (the destination image).\nSee \\fBIMAGE FORMATS\\fR below for details on formats for image data.\n.VE 9.0\nThe following options may be specified:\n.RS\n.\\\" OPTION: -format\n.TP\n\\fB\\-format\\fR {\\fIformat-name\\fR ?\\fIoption value ..\\fR?}\n.\nSpecifies the format of the image data in \\fIdata\\fR and, optionally,\narguments to be passed to the format handler.\nSpecifically, only image file format handlers whose names begin with\n\\fIformat-name\\fR will be used while searching for an image data\nformat handler to read the data.\nNote that the value of this option must be a Tcl list.\nThis means that the braces may be omitted if the argument has only one\nword. Also, instead of braces, double quotes may be used for quoting.\n.VS 9.0\n.\\\" OPTION: -metadata\n.TP\n\\fB\\-metadata\\fI metadata\\fR\n.\nA specified \\fImetadata\\fR is passed to the image format driver when interpreting\nthe data.\nNote that the current metadata of the image is not passed to the format driver\nand is not changed by the command.\n.VE 9.0\n.\\\" OPTION: -to\n.TP\n\\fB\\-to \\fIx1 y1\\fR ?\\fIx2 y2\\fR?\n.\nSpecifies the coordinates of the top-left corner (\\fIx1\\fR,\\fIy1\\fR)\nof the region of \\fIimageName\\fR into which the image data will be\ncopied.  The default position is (0,0).  If \\fIx2\\fR,\\fIy2\\fR is given\nand \\fIdata\\fR is not large enough to cover the rectangle specified by\nthis option, the image data extracted will be tiled so it covers the\nentire destination rectangle. If the region specified with this option\nis smaller than the supplied \\fIdata\\fR, the exceeding data is silently\ndiscarded. Note that if \\fIdata\\fR specifies a\nsingle color value, then a region extending to the bottom-right corner\nrepresented by (\\fIx2\\fR,\\fIy2\\fR) will be filled with that color.\n.RE\n.\\\" METHOD: read\n.TP\n\\fIimageName \\fBread\\fI filename\\fR ?\\fIoption value(s) ...\\fR?\n.\nReads image data from the file named \\fIfilename\\fR into the image.\nThis command first searches the list of\nimage file format handlers for a handler that can interpret the data\nin \\fIfilename\\fR, and then reads the image in \\fIfilename\\fR into\n\\fIimageName\\fR (the destination image).  The following options may be\nspecified:\n.RS\n.\\\" OPTION: -format\n.TP\n\\fB\\-format {\\fIformat-name\\fR ?\\fIoption value ..\\fR?}\n.\nSpecifies the format of the image data in \\fIfilename\\fR and,\noptionally, additional options to the format handler.\nSpecifically, only image file format handlers whose names begin with\n\\fIformat-name\\fR will be used while searching for an image data\nformat handler to read the data.\nNote that the value of this option must be a Tcl list.\nThis means that the braces may be omitted if the argument has only one\nword. Also, instead of braces, double quotes may be used for quoting.\n.\\\" OPTION: -from\n.TP\n\\fB\\-from \\fIx1 y1 x2 y2\\fR\n.\nSpecifies a rectangular sub-region of the image file data to be copied\nto the destination image.  If only \\fIx1\\fR and \\fIy1\\fR are\nspecified, the region extends from (\\fIx1,y1\\fR) to the bottom-right\ncorner of the image in the image file.  If all four coordinates are\nspecified, they specify diagonally opposite corners or the region.\nThe default, if this option is not specified, is the whole of the\nimage in the image file.\n.VS 9.0\n.\\\" OPTION: -metadata\n.TP\n\\fB\\-metadata\\fI metadata\\fR\n.\nA specified \\fImetadata\\fR is passed to the image format driver when interpreting\nthe data.\nNote that the current metadata of the image is not passed to the format driver\nand is not changed by the command.\n.VE 9.0\n.\\\" OPTION: -shrink\n.TP\n\\fB\\-shrink\\fR\n.\nIf this option, the size of \\fIimageName\\fR will be reduced, if\nnecessary, so that the region into which the image file data are read\nis at the bottom-right corner of the \\fIimageName\\fR.  This option\nwill not affect the width or height of the image if the user has\nspecified a non-zero value for the \\fB\\-width\\fR or \\fB\\-height\\fR\nconfiguration option, respectively.\n.\\\" OPTION: -to\n.TP\n\\fB\\-to \\fIx y\\fR\n.\nSpecifies the coordinates of the top-left corner of the region of\n\\fIimageName\\fR into which data from \\fIfilename\\fR are to be read.\nThe default is (0,0).\n.RE\n.\\\" METHOD: redither\n.TP\n\\fIimageName \\fBredither\\fR\n.\nThe dithering algorithm used in displaying photo images propagates\nquantization errors from one pixel to its neighbors.\nIf the image data for \\fIimageName\\fR is supplied in pieces, the\ndithered image may not be exactly correct.  Normally the difference is\nnot noticeable, but if it is a problem, this command can be used to\nrecalculate the dithered image in each window where the image is\ndisplayed.\n.\\\" METHOD: transparency\n.TP\n\\fIimageName \\fBtransparency \\fIsubcommand \\fR?\\fIarg ...\\fR?\n.\nAllows examination and manipulation of the transparency information in\nthe photo image.  Several subcommands are available:\n.RS\n.TP\n\\fIimageName \\fBtransparency get \\fIx y\\fR ?\\fB\\-alpha\\fR?\n.VS 9.0\nReturns true if the pixel at (\\fIx\\fR,\\fIy\\fR) is fully transparent,\nfalse otherwise.  If the option \\fB\\-alpha\\fR is passed, returns the\nalpha value of the pixel instead, as an integer in the range 0 to 255.\n.VE 9.0\n.TP\n\\fIimageName \\fBtransparency set \\fIx y newVal\\fR ?\\fB\\-alpha\\fR?\n.VS 9.0\nChange the transparency of the pixel at (\\fIx\\fR,\\fIy\\fR) to\n\\fInewVal.\\fR If no additional option is passed, \\fInewVal\\fR is\ninterpreted as a boolean and the pixel is made fully transparent if\nthat value is true, fully opaque otherwise.  If the \\fB\\-alpha\\fR\noption is passed, \\fInewVal\\fR is interpreted as an integral alpha\nvalue for the pixel, which must be in the range 0 to 255.\n.VE 9.0\n.RE\n.\\\" METHOD: write\n.TP\n\\fIimageName \\fBwrite \\fIfilename\\fR ?\\fIoption value(s) ...\\fR?\n.\nWrites image data from \\fIimageName\\fR to a file named \\fIfilename\\fR.\nThe following options may be specified:\n.RS\n.\\\" OPTION: -background\n.TP\n\\fB\\-background\\fI color\\fR\n.\nIf the color is specified, the data will not contain any transparency\ninformation. In all transparent pixels the color will be replaced by\nthe specified color.\n.\\\" OPTION: -format\n.TP\n\\fB\\-format\\fR {\\fIformat-name\\fR ?\\fIoption value ...\\fR?}\n.\nSpecifies the name of the image file format handler to be used to\nwrite the data to the file and, optionally, options to pass to the\nformat handler.  Specifically, this subcommand searches for the first\nhandler whose name matches an initial substring of \\fIformat-name\\fR\nand which has the capability to write an image file.  If this option\nis not given, the format is guessed from the file extension. If that\ncannot be determined, this subcommand uses the first handler that has\nthe capability to write an image file.\nNote that the value of this option must be a Tcl list.\nThis means that the braces may be omitted if the argument has only one\nword. Also, instead of braces, double quotes may be used for quoting.\n.\\\" OPTION: -from\n.TP\n\\fB\\-from \\fIx1 y1 x2 y2\\fR\n.\nSpecifies a rectangular region of \\fIimageName\\fR to be written to the\nimage file.  If only \\fIx1\\fR and \\fIy1\\fR are specified, the region\nextends from \\fI(x1,y1)\\fR to the bottom-right corner of\n\\fIimageName\\fR.  If all four coordinates are given, they specify\ndiagonally opposite corners of the rectangular region.  The default,\nif this option is not given, is the whole image.\n.\\\" OPTION: -grayscale\n.TP\n\\fB\\-grayscale\\fR\n.\nIf this options is specified, the data will not contain color\ninformation. All pixel data will be transformed into grayscale.\n.VS 9.0\n.\\\" OPTION: -metadata\n.TP\n\\fB\\-metadata\\fI metadata\\fR\n.\nImage format handler may use metadata to be included in the written file.\nThe specified \\fImetadata\\fR is passed to the driver for inclusion in the\nfile.\nIf no \\fB\\-metadata\\fR option is given, the current metadata of the\nimage is used.\n.VE 9.0\n.RE\n.SH \"IMAGE FORMATS\"\n.PP\nThe photo image code is structured to allow handlers for additional\nimage file formats to be added easily.  The photo image code maintains\na list of these handlers.  Handlers are added to the list by\nregistering them with a call to \\fBTk_CreatePhotoImageFormat\\fR.  The\nstandard Tk distribution comes with handlers for PPM/PGM, PNG, GIF and\n(read-only) SVG formats,\n.VS 9.0\nas well as the \\fBdefault\\fR handler to encode/decode image\ndata in a human readable form.\n.VE 9.0\nThese handlers are automatically registered on initialization.\n.PP\nWhen reading an image file or processing string data specified with\nthe \\fB\\-data\\fR configuration option, the photo image code invokes\neach handler in turn until one is found that claims to be able to read\nthe data in the file or string.  Usually this will find the correct\nhandler, but if it does not, the user may give a format name with the\n\\fB\\-format\\fR option to specify which handler to use.  In this case,\nthe photo image code will try those handlers whose names begin with\nthe string specified for the \\fB\\-format\\fR option (the comparison is\ncase-insensitive).  For example, if the user specifies \\fB\\-format\ngif\\fR, then a handler named GIF87 or GIF89 may be invoked, but a\nhandler named JPEG may not (assuming that such handlers had been\nregistered).\n.PP\nWhen writing image data to a file, the processing of the\n\\fB\\-format\\fR option is slightly different: the string value given\nfor the \\fB\\-format\\fR option must begin with the complete name of the\nrequested handler, and may contain additional information following\nthat, which the handler can use, for example, to specify which variant\nto use of the formats supported by the handler.\nNote that not all image handlers may support writing transparency data\nto a file, even where the target image format does.\n.VS 9.0\n.SS \"THE DEFAULT IMAGE HANDLER\"\n.PP\nThe \\fBdefault\\fR image handler cannot be used to read or write data\nfrom/to a file. Its sole purpose is to encode and decode image data in\nstring form in a clear text, human readable, form. The \\fIimageName\\fR\n\\fBdata\\fR subcommand uses this handler when no other format is\nspecified. When reading image data from a string with \\fIimageName\\fR\n\\fBput\\fR or the \\fB\\-data\\fR option, the default handler is treated\nas the other handlers.\n.PP\nImage data in the \\fBdefault\\fR string format is a (top-to-bottom)\nlist of scan-lines, with each scan-line being a (left-to-right) list\nof pixel data. Every scan-line has the same length. The color\nand, optionally, alpha value of each pixel is specified in any of\nthe forms described in the \\fBCOLOR FORMATS\\fR section below.\n.VE 9.0\n\n.SS \"FORMAT SUBOPTIONS\"\n.PP\n.VS 8.6\nImage formats may support sub-options, which are specified using\nadditional words in the value to the \\fB\\-format\\fR option. These\nsuboptions can affect how image data is read or written to file or\nstring. The nature and values of these options is up to the format\nhandler.\nThe built-in handlers support these suboptions:\n.\\\" OPTION -colorformat\n.VS 9.0\n.TP\n\\fBdefault \\-colorformat\\fI formatType\\fR\n.\nThe option is allowed when writing image data to a string with\n\\fIimageName \\fBdata\\fR. Specifies the format to use for the color\nstring of each pixel. \\fIformatType\\fR may be one of: \\fBrgb\\fR to\nencode pixel data in the form \\fB#\\fIRRGGBB\\fR, \\fBrgba\\fR to encode\npixel data in the form \\fB#\\fIRRGGBBAA\\fR or \\fBlist\\fR to encode\npixel data as a list with four elements. See \\fBCOLOR FORMATS\\fR\nbelow for details. The default is \\fBrgb\\fR.\n.VE 9.0\n.\\\" OPTION -index\n.TP\n\\fBgif \\-index\\fI indexValue\\fR\n.\nThe option has effect when reading image data from a file. When\nparsing a multi-part GIF image, Tk normally only accesses the first\nimage. By giving the \\fB\\-index\\fR sub-option, the \\fIindexValue\\fR'th\nvalue may be used instead. The \\fIindexValue\\fR must be an integer\nfrom 0 up to the number of image parts in the GIF data.\n.\\\" OPTION -alpha\n.TP\n\\fBpng \\-alpha\\fI alphaValue\\fR\n.\nThe option has effect when reading image data from a file. Specifies\nan additional alpha filtering for the overall image, which allows the\nbackground on which the image is displayed to show through.  This\nusually also has the effect of desaturating the image.  The\n\\fIalphaValue\\fR must be between 0.0 and 1.0.\n.\\\" OPTION -dpi\n.\\\" OPTION -scale\n.\\\" OPTION -scaletowidth\n.\\\" OPTION -scaletoheight\n.TP\n\\fBsvg \\-dpi\\fI dpiValue \\fB\\-scale\\fI scaleValue \\fB\\-scaletowidth\\fI width \\fB\\-scaletoheight\\fI height\\fR\n.\n\\fIdpiValue\\fR is used in conversion between given coordinates and\nscreen resolution. The value must be greater than 0 and the default\nvalue is 96.\n.PP\n.RS\n\\fIscaleValue\\fR is used to scale the resulting image. The value must\nbe greater than 0 and the default value is 1.\n\\fIwidth\\fR and \\fIheight\\fR are the width or height that the image\nwill be adjusted to. Only one parameter among \\fB\\-scale\\fR,\n\\fB\\-scaletowidth\\fR and \\fB\\-scaletoheight\\fR can be given at a time\nand the aspect ratio of the original image is always preserved.\nThe \\fBsvg\\fR format supports a wide range of SVG features, but the\nfull SVG standard is not available, for instance the 'text' feature\nis missing and silently ignored when reading the SVG data.\nThe supported SVG features are:\n.TP\n\\fBelements:\\fR\n.\ng, path, rect, circle, ellipse, line, polyline, polygon,\nlinearGradient, radialGradient, stop, defs, svg, style\n.TP\n\\fBattributes:\\fR\n.\nwidth, height, viewBox,\npreserveAspectRatio with none, xMin, xMid, xMax, yMin, yMid, yMax, slice\n.TP\n\\fBgradient attributes:\\fR\n.\ngradientUnits with objectBoundingBox,\ngradientTransform, cx, cy, r fx, fy x1, y1, x2, y2\nspreadMethod with pad, reflect or repeat,\nxlink:href\n.TP\n\\fBpoly attributes:\\fR\n.\npoints\n.TP\n\\fBline attributes:\\fR\n.\nx1, y1, x2, y2\n.TP\n\\fBellipse attributes:\\fR\n.\ncx, cy, rx, ry\n.TP\n\\fBcircle attributes:\\fR\n.\ncx, cy, r\n.TP\n\\fBrectangle attributes:\\fR\n.\nx, y, width, height, rx, ry\n.TP\n\\fBpath attributes:\\fR\n.\nd with m, M, l, L, h, H, v, V, c, C, s, S, q, Q, t, T, a, A, z, Z\n.TP\n\\fBstyle attributes:\\fR\n.\ndisplay with none, visibility, hidden, visible,\nfill with nonzero and evenodd, opacity, fill-opacity,\nstroke, stroke-width, stroke-dasharray, stroke-dashoffset, stroke-opacity,\nstroke-linecap with butt, round and square,\nstroke-linejoin with miter, round and  bevel, stroke-miterlimit\nfill-rule, font-size,\ntransform with matrix, translate, scale, rotate, skewX and  skewY,\nstop-color, stop-opacity, offset, id, class\n.RE\n.PP\n.RS\nCurrently only SVG images reading and conversion into (pixel-based\nformat) photos is supported: Tk does not (yet) support bundling photo\nimages in SVG vector graphics.\n.RE\n.VE 8.6\n.VS 9.0\n.SH \"COLOR FORMATS\"\n.PP\nThe default image handler can represent/parse color and alpha values\nof a pixel in one of the formats listed below. If a color format does\nnot contain transparency information, full opacity is assumed.  The\navailable color formats are:\n.IP \\(bu 3\nThe empty string - interpreted as full transparency, the color value\nis undefined.\n.IP \\(bu 3\nAny value accepted by \\fBTk_GetColor\\fR, optionally followed by an\nalpha suffix. The alpha suffix may be one of:\n.RS\n.TP\n\\fB@\\fR\\fIA\\fR\n.\nThe alpha value \\fIA\\fR must be a fractional value in the range  0.0\n(fully transparent) to 1.0 (fully opaque).\n.TP\n\\fB#\\fR\\fIX\\fR\n.\nThe alpha value \\fIX\\fR is a hexadecimal digit that specifies an integer\nalpha value in the range 0 (fully transparent) to 255 (fully opaque).\nThis is expanded in range from 4 bits wide to 8 bits wide by\nmultiplication by 0x11.\n.TP\n\\fB#\\fR\\fIXX\\fR\n.\nThe alpha value \\fIXX\\fR is passed as two hexadecimal digits that\nspecify an integer alpha value in the range 0 (fully transparent) to 255\n(fully opaque).\n.RE\n.IP \\(bu 3\nA Tcl list with three or four integers in the range 0 to 255,\nspecifying the values for the red, green, blue and (optionally)\nalpha channels respectively.\n.IP \\(bu 3\n\\fB#\\fR\\fIRGBA\\fR format: a \\fB#\\fR followed by four hexadecimal digits,\nwhere each digit is the value for the red, green, blue and alpha\nchannels respectively. Each digit will be expanded internally to\n8 bits by multiplication by 0x11.\n.IP \\(bu 3\n\\fB#\\fR\\fIRRGGBBAA\\fR format: \\fB#\\fR followed by eight hexadecimal digits,\nwhere each pair of  subsequent digits represents the value for the red,\ngreen, blue and alpha channels respectively.\n.VE 9.0\n.SH \"COLOR ALLOCATION\"\n.PP\nWhen a photo image is displayed in a window, the photo image code\nallocates colors to use to display the image and dithers the image, if\nnecessary, to display a reasonable approximation to the image using\nthe colors that are available.  The colors are allocated as a color\ncube, that is, the number of colors allocated is the product of the\nnumber of shades of red, green and blue.\n.PP\nNormally, the number of\ncolors allocated is chosen based on the depth of the window.  For\nexample, in an 8-bit PseudoColor window, the photo image code will\nattempt to allocate seven shades of red, seven shades of green and\nfour shades of blue, for a total of 198 colors.  In a 1-bit StaticGray\n(monochrome) window, it will allocate two colors, black and white.  In\na 24-bit DirectColor or TrueColor window, it will allocate 256 shades\neach of red, green and blue.  Fortunately, because of the way that\npixel values can be combined in DirectColor and TrueColor windows,\nthis only requires 256 colors to be allocated.  If not all of the\ncolors can be allocated, the photo image code reduces the number of\nshades of each primary color and tries again.\n.PP\nThe user can exercise some control over the number of colors that a\nphoto image uses with the \\fB\\-palette\\fR configuration option.  If\nthis option is used, it specifies the maximum number of shades of\neach primary color to try to allocate.  It can also be used to force\nthe image to be displayed in shades of gray, even on a color display,\nby giving a single number rather than three numbers separated by\nslashes.\n.VS 9.0\n.SH \"METADATA DICTIONARY\"\n.PP\nEach image has a metadata dictionary property.\nThis dictionary is not relevant to the bitmap representation of the\nimage, but may contain additional information like resolution or\ncomments.\nImage format drivers may output metadata when image data is\nparsed, or may use metadata to be included in image files or formats.\n.SS \"METADATA KEYS (MULTIPLE FORMATS)\"\n.PP\nEach image format driver supports an individual set of metadata dictionary\nkeys. Predefined keys are:\n.IP \\fBDPI\\fR\nHorizontal image resolution in DPI as a double value.\nSupported by format \\fBpng\\fR.\n.IP \\fBaspect\\fR\nAspect ratio horizontal divided by vertical as double value.\nSupported by formats \\fBgif\\fR and \\fBpng\\fR.\n.IP \\fBcomment\\fR\nImage text comment.\nSupported by formats \\fBgif\\fR and \\fBpng\\fR.\n.PP\nIt is valid to set any key in the metadata dict.\nA format driver will ignore keys that it does not handle.\n.SS \"METADATA KEYS FOR ANIMATED GIF INFORMATION\"\n.PP\nThe following metadata keys are reported when reading a \\fBgif\\fR format file.\nThey are typically used in conjunction with the \\fB\\-index\\fR option of an\nanimated \\fBgif\\fR file to properly display the subimage sequence.\nThe options are linked to each subimage selected by \\fB\\-index\\fR.\n.TP\n\\fBdelay time\\fI time\\fR\n.\nUpdate delay time in 10ms units.\nThis key is only present if the delay time is not 0.\n.TP\n\\fBdisposal method\\fI method\\fR\n.\nDisposal method of the preceeding image, if given for the current image.\nPossible values are: \\fBdo not dispose\\fR, \\fBrestore to background color\\fR,\n\\fBrestore to previous\\fR.\n.TP\n\\fBuser interaction\\fI bool\\fR\n.\nThe key is present with a value of 1, if user interaction is specified.\nOtherwise, the key is not present.\n.TP\n\\fBupdate region\\fI X0\\fR, \\fIY0\\fR, \\fIwidth\\fR, \\fIheight\\fR\n.\nUpdate region of the current subimage, if subimage has not the same size as\nthe full image. The pixel outside of this box are all fully transparent.\n.PP\n.VE 9.0\n.SH CREDITS\n.PP\nThe photo image type was designed and implemented by Paul Mackerras,\nbased on his earlier photo widget and some suggestions from\nJohn Ousterhout.\n.SH EXAMPLE\n.PP\nLoad an image from a file and tile it to the size of a window, which\nis useful for producing a tiled background:\n.PP\n.CS\n# These lines should be called once\n\\fBimage create photo\\fR untiled -file \"theFile.ppm\"\n\\fBimage create photo\\fR tiled\n\n# These lines should be called whenever .someWidget changes\n# size; a <Configure> binding is useful here\nset width  [winfo width .someWidget]\nset height [winfo height .someWidget]\ntiled \\fBcopy\\fR untiled -to 0 0 $width $height -shrink\n.CE\n.PP\n.VS 8.6\nThe PNG image loader allows the application of an additional alpha factor\nduring loading, which is useful for generating images suitable for disabled\nbuttons:\n.PP\n.CS\n\\fBimage create photo\\fR icon -file \"icon.png\"\n\\fBimage create photo\\fR iconDisabled -file \"icon.png\" \\e\n        -format \"png -alpha 0.5\"\nbutton .b -image icon -disabledimage iconDisabled\n.CE\n.VE 8.6\n.PP\n.VS 9.0\nCreate a green box with a simple shadow effect\n.PP\n.CS\n\\fBimage create photo\\fR foo\n\n# Make a simple graduated fill varying in alpha for the shadow\nfor {set i 14} {$i > 0} {incr i -1} {\n   set i2 [expr {$i + 30}]\n   foo \\fBput\\fR [format black#%x [expr {15-$i}]] -to $i $i $i2 $i2\n}\n\n# Put a solid green rectangle on top\nfoo \\fBput\\fR #F080 -to 0 0 30 30\n.VE 9.0\n.CE\n.SH \"SEE ALSO\"\nimage(n)\n.SH KEYWORDS\nphoto, image, color\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/place.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH place n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nplace \\- Geometry manager for fixed or rubber-sheet placement\n.SH SYNOPSIS\n\\fBplace \\fIoption arg \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe placer is a geometry manager for Tk.\nIt provides simple fixed placement of windows, where you specify\nthe exact size and location of one window, called the \\fIcontent\\fR,\nwithin another window, called the \\fIcontainer\\fR.\nThe placer also provides rubber-sheet placement, where you specify the\nsize and location of the content in terms of the dimensions of\nthe container, so that the content changes size and location\nin response to changes in the size of the container.\nLastly, the placer allows you to mix these styles of placement so\nthat, for example, the content has a fixed width and height but is\ncentered inside the container.\n.PP\n.TP\n\\fBplace \\fIwindow option value \\fR?\\fIoption value ...\\fR?\n.\nArrange for the placer to manage the geometry of a content whose\npathName is \\fIwindow\\fR.  The remaining arguments consist of one or\nmore \\fIoption\\-value\\fR pairs that specify the way in which\n\\fIwindow\\fR's geometry is managed.  \\fIOption\\fR may have any of the\nvalues accepted by the \\fBplace configure\\fR command.\n.\\\" METHOD: configure\n.TP\n\\fBplace configure \\fIwindow \\fR?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the geometry options of the content given by\n\\fIwindow\\fR.  If no \\fIoption\\fR is specified, this command returns a\nlist describing the available options (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given option(s) to have the given value(s); in this case\nthe command returns an empty string.\n.RS\n.PP\nThe following \\fIoption\\-value\\fR pairs are supported:\n.\\\" OPTION: -anchor\n.TP\n\\fB\\-anchor \\fIwhere\\fR\n.\n\\fIWhere\\fR specifies which point of \\fIwindow\\fR is to be positioned\nat the (x,y) location selected by the \\fB\\-x\\fR, \\fB\\-y\\fR,\n\\fB\\-relx\\fR, and \\fB\\-rely\\fR options.\nThe anchor point is in terms of the outer area of \\fIwindow\\fR\nincluding its border, if any.\nThus if \\fIwhere\\fR is \\fBse\\fR then the lower-right corner of\n\\fIwindow\\fR's border will appear at the given (x,y) location\nin the container.\nThe anchor position defaults to \\fBnw\\fR.\n.\\\" OPTION: -bordermode\n.TP\n\\fB\\-bordermode \\fImode\\fR\n.\n\\fIMode\\fR determines the degree to which borders within the\ncontainer are used in determining the placement of the content.\nThe default and most common value is \\fBinside\\fR.\nIn this case the placer considers the area of the container to\nbe the innermost area of the container, inside any border:\nan option of \\fB\\-x 0\\fR corresponds to an x-coordinate just\ninside the border and an option of \\fB\\-relwidth 1.0\\fR\nmeans \\fIwindow\\fR will fill the area inside the container's\nborder.\n.RS\n.PP\nIf \\fImode\\fR is \\fBoutside\\fR then the placer considers\nthe area of the container to include its border;\nthis mode is typically used when placing \\fIwindow\\fR\noutside its container, as with the options \\fB\\-x 0 \\-y 0 \\-anchor ne\\fR.\nLastly, \\fImode\\fR may be specified as \\fBignore\\fR, in which\ncase borders are ignored:  the area of the container is considered\nto be its official X area, which includes any internal border but\nno external border.  A bordermode of \\fBignore\\fR is probably\nnot very useful.\n.RE\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIsize\\fR\n.\n\\fISize\\fR specifies the height for \\fIwindow\\fR in screen units\n(i.e. any of the forms accepted by \\fBTk_GetPixels\\fR).\nThe height will be the outer dimension of \\fIwindow\\fR including its\nborder, if any.\nIf \\fIsize\\fR is an empty string, or if no \\fB\\-height\\fR or\n\\fB\\-relheight\\fR option is specified, then the height requested\ninternally by the window will be used.\n.\\\" OPTION: -in\n.TP\n\\fB\\-in \\fIcontainer\\fR\n.\n\\fIContainer\\fR specifies the path name of the window relative\nto which \\fIwindow\\fR is to be placed.\n\\fIContainer\\fR must either be \\fIwindow\\fR's parent or a descendant\nof \\fIwindow\\fR's parent.\nIn addition, \\fIcontainer\\fR and \\fIwindow\\fR must both be descendants\nof the same top-level window.\nThese restrictions are necessary to guarantee\nthat \\fIwindow\\fR is visible whenever \\fIcontainer\\fR is visible.\nIf this option is not specified then the other window defaults to\n\\fIwindow\\fR's parent.\n.\\\" OPTION: -relheight\n.TP\n\\fB\\-relheight \\fIsize\\fR\n.\n\\fISize\\fR specifies the height for \\fIwindow\\fR.\nIn this case the height is specified as a floating-point number\nrelative to the height of the container: 0.5 means \\fIwindow\\fR will\nbe half as high as the container, 1.0 means \\fIwindow\\fR will have\nthe same height as the container, and so on.\nIf both \\fB\\-height\\fR and \\fB\\-relheight\\fR are specified for a content,\ntheir values are summed.  For example, \\fB\\-relheight 1.0 \\-height \\-2\\fR\nmakes the content 2 pixels shorter than the container.\n.\\\" OPTION: -relwidth\n.TP\n\\fB\\-relwidth \\fIsize\\fR\n.\n\\fISize\\fR specifies the width for \\fIwindow\\fR.\nIn this case the width is specified as a floating-point number\nrelative to the width of the container: 0.5 means \\fIwindow\\fR will\nbe half as wide as the container, 1.0 means \\fIwindow\\fR will have\nthe same width as the container, and so on.\nIf both \\fB\\-width\\fR and \\fB\\-relwidth\\fR are specified for a content,\ntheir values are summed.  For example, \\fB\\-relwidth 1.0 \\-width 5\\fR\nmakes the content 5 pixels wider than the container.\n.\\\" OPTION: -relx\n.TP\n\\fB\\-relx \\fIlocation\\fR\n.\n\\fILocation\\fR specifies the x-coordinate within the container window\nof the anchor point for \\fIwindow\\fR.\nIn this case the location is specified in a relative fashion\nas a floating-point number:  0.0 corresponds to the left edge\nof the container and 1.0 corresponds to the right edge of the container.\n\\fILocation\\fR need not be in the range 0.0\\-1.0.\nIf both \\fB\\-x\\fR and \\fB\\-relx\\fR are specified for a content\nthen their values are summed.  For example, \\fB\\-relx 0.5 \\-x \\-2\\fR\npositions the left edge of the content 2 pixels to the left of the\ncenter of its container.\n.\\\" OPTION: -rely\n.TP\n\\fB\\-rely \\fIlocation\\fR\n.\n\\fILocation\\fR specifies the y-coordinate within the container window\nof the anchor point for \\fIwindow\\fR.\nIn this case the value is specified in a relative fashion\nas a floating-point number:  0.0 corresponds to the top edge\nof the container and 1.0 corresponds to the bottom edge of the container.\n\\fILocation\\fR need not be in the range 0.0\\-1.0.\nIf both \\fB\\-y\\fR and \\fB\\-rely\\fR are specified for a content\nthen their values are summed.  For example, \\fB\\-rely 0.5 \\-x 3\\fR\npositions the top edge of the content 3 pixels below the\ncenter of its container.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIsize\\fR\n.\n\\fISize\\fR specifies the width for \\fIwindow\\fR in screen units\n(i.e. any of the forms accepted by \\fBTk_GetPixels\\fR).\nThe width will be the outer width of \\fIwindow\\fR including its\nborder, if any.\nIf \\fIsize\\fR is an empty string, or if no \\fB\\-width\\fR\nor \\fB\\-relwidth\\fR option is specified, then the width requested\ninternally by the window will be used.\n.\\\" OPTION: -x\n.TP\n\\fB\\-x \\fIlocation\\fR\n.\n\\fILocation\\fR specifies the x-coordinate within the container window\nof the anchor point for \\fIwindow\\fR.\nThe location is specified in screen units (i.e. any of the forms\naccepted by \\fBTk_GetPixels\\fR) and need not lie within the bounds\nof the container window.\n.\\\" OPTION: -y\n.TP\n\\fB\\-y \\fIlocation\\fR\n.\n\\fILocation\\fR specifies the y-coordinate within the container window\nof the anchor point for \\fIwindow\\fR.\nThe location is specified in screen units (i.e. any of the forms\naccepted by \\fBTk_GetPixels\\fR) and need not lie within the bounds\nof the container window.\n.PP\nIf the same value is specified separately with\ntwo different options, such as \\fB\\-x\\fR and \\fB\\-relx\\fR, then\nthe most recent option is used and the older one is ignored.\n.RE\n.\\\" METHOD: content\n.TP\n\\fBplace content \\fIwindow\\fR\n.\nReturns a list of all the content windows for which \\fIwindow\\fR is the\ncontainer. If there is no content for \\fIwindow\\fR then an empty string\nis returned.\n.\\\" METHOD: forget\n.TP\n\\fBplace forget \\fIwindow\\fR\n.\nCauses the placer to stop managing the geometry of \\fIwindow\\fR.  As a\nside effect of this command \\fIwindow\\fR will be unmapped so that it\ndoes not appear on the screen.  If \\fIwindow\\fR is not currently managed\nby the placer then the command has no effect.  This command returns an\nempty string.\n.\\\" METHOD: info\n.TP\n\\fBplace info \\fIwindow\\fR\n.\nReturns a list giving the current configuration of \\fIwindow\\fR.\nThe list consists of \\fIoption\\-value\\fR pairs in exactly the\nsame form as might be specified to the \\fBplace configure\\fR\ncommand.\n.\\\" METHOD: slaves\n.TP\n\\fBplace slaves \\fIwindow\\fR\n.\nSynonym for \\fBplace content \\fIwindow\\fR.\n.PP\nIf the configuration of a window has been retrieved with\n\\fBplace info\\fR, that configuration can be restored later by\nfirst using \\fBplace forget\\fR to erase any existing information\nfor the window and then invoking \\fBplace configure\\fR with\nthe saved information.\n.SH \"FINE POINTS\"\n.PP\nIt is not necessary for the container window to be the parent\nof the content window.\nThis feature is useful in at least two situations.\nFirst, for complex window layouts it means you can create a\nhierarchy of subwindows whose only purpose\nis to assist in the layout of the parent.\nThe\n.QW \"real children\"\nof the parent (i.e. the windows that\nare significant for the application's user interface) can be\nchildren of the parent yet be placed inside the windows\nof the geometry-management hierarchy.\nThis means that the path names of the\n.QW \"real children\"\ndo not reflect the geometry-management hierarchy and users\ncan specify options for the real children\nwithout being aware of the structure of the geometry-management\nhierarchy.\n.PP\nA second reason for having a container different than the content's\nparent is to tie two siblings together.\nFor example, the placer can be used to force a window always to\nbe positioned centered just below one of its\nsiblings by specifying the configuration\n.CS\n\\fB\\-in \\fIsibling\\fB \\-relx 0.5 \\-rely 1.0 \\-anchor n \\-bordermode outside\\fR\n.CE\nWhenever the sibling is repositioned in the future, the content\nwill be repositioned as well.\n.PP\nUnlike many other geometry managers (such as the packer)\nthe placer does not make any attempt to manipulate the geometry of\nthe container windows or the parents of content windows (i.e. it does not\nset their requested sizes).\nTo control the sizes of these windows, make them windows like\nframes and canvases that provide configuration options for this purpose.\n.SH EXAMPLE\n.PP\nMake the label occupy the middle bit of the toplevel, no matter how it\nis resized:\n.CS\nlabel .l -text \"In the\\enMiddle!\" -bg black -fg white\n\\fBplace\\fR .l -relwidth .3 -relx .35 -relheight .3 -rely .35\n.CE\n.SH \"SEE ALSO\"\ngrid(n), pack(n)\n.SH KEYWORDS\ngeometry manager, height, location, container, place, rubber sheet,\ncontent, width\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/popup.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk_popup n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk_popup \\- Post a popup menu\n.SH SYNOPSIS\n\\fBtk_popup \\fImenu x y \\fR?\\fIentry\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis procedure posts a menu at a given position on the screen and\nconfigures Tk so that the menu and its cascaded children can be\ntraversed with the mouse or the keyboard.\n\\fIMenu\\fR is the name of a menu widget and \\fIx\\fR and \\fIy\\fR\nare the root coordinates at which to display the menu.\nIf \\fIentry\\fR is omitted or an empty string, the\nmenu's upper left corner is positioned at the given point.\nOtherwise \\fIentry\\fR gives the index of an entry in \\fImenu\\fR and\nthe menu will be positioned so that the entry is positioned over\nthe given point.\n.SH EXAMPLE\n.PP\nHow to attach a simple popup menu to a widget.\n.CS\n# Create a menu\nset m [menu .popupMenu]\n$m add command -label \"Example 1\" -command bell\n$m add command -label \"Example 2\" -command bell\n\n# Create something to attach it to\npack [label .l -text \"Click me!\"]\n\n# Arrange for the menu to pop up when the label is clicked\nbind .l <Button-1> {\\fBtk_popup\\fR .popupMenu %X %Y}\n.CE\n.SH \"SEE ALSO\"\nbind(n), menu(n), tk_optionMenu(n)\n.SH KEYWORDS\nmenu, popup\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/print.n",
    "content": ".\\\" Text automatically generated by txt2man\n'\\\"\n'\\\" Copyright (c) 2021 Kevin Walzer\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n.TH tk print n \"\" Tk \"Tk Built-in Commands\"\n.so man.macros\n.SH NAME\nprint \\- Print canvas and text widgets using native dialogs and APIs.\n.SH SYNOPSIS\n\\fBtk print \\fIwindow\\fR\n.\n.SH DESCRIPTION\n.PP\nThe \\fBtk print\\fR command posts a dialog that allows users to print output\nfrom the \\fBcanvas\\fR and \\fBtext\\fR widgets. The printing will be done using\nplatform-native APIs and dialogs where available.\n.PP\nThe \\fBcanvas\\fR widget has long supported PostScript export and both\nPostScript and text files can be sent directly to a printer on Unix-like\nsystems using the\n.QW \"lp\"\nand\n.QW \"lpr\"\nUnix commands, and the \\fBtk print\\fR command does not supersede that\nfunctionality; it builds on it. The \\fBtk print\\fR command is a fuller\nimplementation that uses native dialogs on macOS and Windows, and a Tk-based\ndialog that provides parallel functionality on X11.\n.SH PLATFORM NOTES\n.TP\n\\fBmacOS\\fR\n.\nThe Mac implementation uses native print dialogs and relies on the underlying\nCommon Unix Printing System (CUPS) to render text output from the text widget\nand PDF conversion of the canvas data to the printer or to a PDF file.\n.TP\n\\fBWindows\\fR\n.\nThe Windows implementation is based on the GDI (Graphics Device Interface)\nAPI. Because there are slight differences in how GDI and Tk's \\fBcanvas\\fR\nwidget display graphics, printed output from the \\fBcanvas\\fR on Windows may\nnot be identical to screen rendering.\n.TP\n\\fBX11\\fR\n.\nThe X11 implementation uses a Tk GUI to configure print jobs for sending to a\nprinter via the\n.QW \"lpr\"\nor\n.QW \"lp\"\ncommands or via the Common Unix Printing System (CUPS) API if libcups is installed. While these commands have a large number of parameters for\nconfiguring print jobs, printers vary widely in how they support these\nparameters. As a result, only printer selection and number of copies are\nconfigured as arguments to the print command; many aspects of print rendering,\nsuch as grayscale or color for the canvas, are instead configured when\nPostScript is generated.\n.SH \"SEE ALSO\"\ncanvas(n), text(n), tk(n)\n.SH KEYWORDS\nprint, output, graphics, text, canvas\n"
  },
  {
    "path": "doc/radiobutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH radiobutton n 4.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nradiobutton \\- Create and manipulate 'radiobutton' pick-one widgets\n.SH SYNOPSIS\n\\fBradiobutton\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-disabledforeground\t\\-padx\n\\-activeforeground\t\\-font\t\\-pady\n\\-anchor\t\\-foreground\t\\-relief\n\\-background\t\\-highlightbackground\t\\-takefocus\n\\-bitmap\t\\-highlightcolor\t\\-text\n\\-borderwidth\t\\-highlightthickness\t\\-textvariable\n\\-compound\t\\-image\t\\-underline\n\\-cursor\t\\-justify\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies a Tcl command to associate with the button.  This command\nis typically invoked when mouse button 1 is released over the button\nwindow.  The button's global variable (\\fB\\-variable\\fR option) will\nbe updated before the command is invoked.\n.OP \\-height height Height\nSpecifies a desired height for the button.\nIf an image or bitmap is being displayed in the button then the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in lines of text.\nIf this option is not specified, the button's desired height is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.OP \\-indicatoron indicatorOn IndicatorOn\nSpecifies whether or not the indicator should be drawn.  Must be a\nproper boolean value.  If false, the \\fB\\-relief\\fR option is\nignored and the widget's relief is always sunken if the widget is\nselected and raised otherwise.\n.OP \\-offrelief offRelief OffRelief\nSpecifies the relief for the checkbutton when the indicator is not drawn and\nthe checkbutton is off.  The default value is\n.QW raised .\nBy setting this option to\n.QW flat\nand setting \\fB\\-indicatoron\\fR to false and \\fB\\-overrelief\\fR to\n.QW raised ,\nthe effect is achieved\nof having a flat button that raises on mouse-over and which is\ndepressed when activated.  This is the behavior typically exhibited by\nthe Align-Left, Align-Right, and Center radiobuttons on the toolbar of a\nword-processor, for example.\n.OP \\-overrelief overRelief OverRelief\nSpecifies an alternative relief for the radiobutton, to be used when the\nmouse cursor is over the widget.  This option can be used to make\ntoolbar buttons, by configuring \\fB\\-relief flat \\-overrelief\nraised\\fR.  If the value of this option is the empty string, then no\nalternative relief is used when the mouse cursor is over the radiobutton.\nThe empty string is the default value.\n.OP \\-selectcolor selectColor Background\nSpecifies a background color to use when the button is selected.\nIf \\fBindicatorOn\\fR is true then the color is used as the background for\nthe indicator regardless of the select state.\nIf \\fB\\-indicatoron\\fR is false, this color is used as the background for the\nentire widget, in place of \\fB\\-background\\fR or \\fB\\-activeBackground\\fR,\nwhenever the widget is selected.\nIf specified as an empty string then no special color is used for\ndisplaying when the widget is selected.\n.OP \\-selectimage selectImage SelectImage\nSpecifies an image to display (in place of the \\fB\\-image\\fR option)\nwhen the radiobutton is selected.\nThis option is ignored unless the \\fB\\-image\\fR option has been\nspecified.\n.OP \\-state state State\nSpecifies one of three states for the radiobutton:  \\fBnormal\\fR, \\fBactive\\fR,\nor \\fBdisabled\\fR.  In normal state the radiobutton is displayed using the\n\\fB\\-foreground\\fR and \\fB\\-background\\fR options.  The active state is\ntypically used when the pointer is over the radiobutton.  In active state\nthe radiobutton is displayed using the \\fB\\-activeforeground\\fR and\n\\fB\\-activebackground\\fR options.  Disabled state means that the radiobutton\nshould be insensitive:  the default bindings will refuse to activate\nthe widget and will ignore mouse button presses.\nIn this state the \\fB\\-disabledforeground\\fR and\n\\fB\\-background\\fR options determine how the radiobutton is displayed.\n.OP \\-tristateimage tristateImage TristateImage\nSpecifies an image to display (in place of the \\fB\\-image\\fR option)\nwhen the radiobutton is selected.\nThis option is ignored unless the \\fB\\-image\\fR option has been\nspecified.\n.OP \\-tristatevalue tristateValue Value\nSpecifies the value that causes the radiobutton to display the multi-value\nselection, also known as the tri-state mode.  Defaults to\n.QW \"\" .\n.OP \\-value value Value\nSpecifies value to store in the button's associated variable whenever\nthis button is selected.\n.OP \\-variable variable Variable\nSpecifies the name of a global variable to set whenever this button is\nselected.  Changes in this variable also cause the button to select\nor deselect itself.\nDefaults to the value \\fBselectedButton\\fR.\n.OP \\-width width Width\nSpecifies a desired width for the button.\nIf an image or bitmap is being displayed in the button, the value is in\nscreen units (i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR);\nfor text it is in characters.\nIf this option is not specified, the button's desired width is computed\nfrom the size of the image or bitmap or text being displayed in it.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBradiobutton\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a radiobutton widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the radiobutton such as its colors, font,\ntext, and initial relief.  The \\fBradiobutton\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA radiobutton is a widget that displays a textual string, bitmap or image\nand a diamond or circle called an \\fIindicator\\fR.\nIf text is displayed, it must all be in a single font, but it\ncan occupy multiple lines on the screen (if it contains newlines\nor if wrapping occurs because of the \\fB\\-wraplength\\fR option) and\none of the characters may optionally be underlined using the\n\\fB\\-underline\\fR option.  A radiobutton has\nall of the behavior of a simple button: it can display itself in either\nof three different ways, according to the \\fB\\-state\\fR option;\nit can be made to appear\nraised, sunken, or flat; it can be made to flash; and it invokes\na Tcl command whenever mouse button 1 is clicked over the\ncheck button.\n.PP\nIn addition, radiobuttons can be \\fIselected\\fR.\nIf a radiobutton is selected, the indicator is normally\ndrawn with a selected appearance, and\na Tcl variable associated with the radiobutton is set to a particular\nvalue (normally 1).\nUnder Unix, the indicator is drawn with a sunken relief and a special\ncolor.  Under Windows, the indicator is drawn with a round mark inside.\nIf the radiobutton is not selected, then the indicator is drawn with a\ndeselected appearance, and the associated variable is\nset to a different value (typically 0).\nThe indicator is drawn without a round mark inside.\nTypically, several radiobuttons share a single variable and the\nvalue of the variable indicates which radiobutton is to be selected.\nWhen a radiobutton is selected it sets the value of the variable to\nindicate that fact;  each radiobutton also monitors the value of\nthe variable and automatically selects and deselects itself when the\nvariable's value changes.\nIf the variable's value matches the \\fB\\-tristatevalue\\fR, then the radiobutton\nis drawn using the tri-state mode.  This mode is used to indicate mixed or\nmultiple values.  (This is used when the radiobutton represents the state\nof multiple items.)\nBy default the variable \\fBselectedButton\\fR\nis used;  its contents give the name of the button that is\nselected, or the empty string if no button associated with that\nvariable is selected.\nThe name of the variable for a radiobutton,\nplus the variable to be stored into it, may be modified with options\non the command line or in the option database.\nConfiguration options may also be used to modify the way the\nindicator is displayed (or whether it is displayed at all).\nBy default a radiobutton is configured to select itself on button clicks.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBradiobutton\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for radiobutton widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBradiobutton\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBradiobutton\\fR\ncommand.\n.\\\" METHOD: deselect\n.TP\n\\fIpathName \\fBdeselect\\fR\n.\nDeselects the radiobutton and sets the associated variable to an\nempty string.\nIf this radiobutton was not currently selected, the command has\nno effect.\n.\\\" METHOD: flash\n.TP\n\\fIpathName \\fBflash\\fR\n.\nFlashes the radiobutton.  This is accomplished by redisplaying the radiobutton\nseveral times, alternating between active and normal colors.  At\nthe end of the flash the radiobutton is left in the same normal/active\nstate as when the command was invoked.\nThis command is ignored if the radiobutton's state is \\fBdisabled\\fR.\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke\\fR\n.\nDoes just what would have happened if the user invoked the radiobutton\nwith the mouse: selects the button and invokes\nits associated Tcl command, if there is one.\nThe return value is the return value from the Tcl command, or an\nempty string if there is no command associated with the radiobutton.\nThis command is ignored if the radiobutton's state is \\fBdisabled\\fR.\n.\\\" METHOD: select\n.TP\n\\fIpathName \\fBselect\\fR\n.\nSelects the radiobutton and sets the associated variable to the\nvalue corresponding to this widget.\n.SH BINDINGS\n.PP\nTk automatically creates class bindings for radiobuttons that give them\nthe following default behavior:\n.IP [1]\nOn Unix systems, a radiobutton activates whenever the mouse passes\nover it and deactivates whenever the mouse leaves the radiobutton.  On\nMac and Windows systems, when mouse button 1 is pressed over a\nradiobutton, the button activates whenever the mouse pointer is inside\nthe button, and deactivates whenever the mouse pointer leaves the\nbutton.\n.IP [2]\nWhen mouse button 1 is pressed over a radiobutton it is invoked (it\nbecomes selected and the command associated with the button is\ninvoked, if there is one).\n.IP [3]\nWhen a radiobutton has the input focus, the space key causes the radiobutton\nto be invoked.\n.PP\nIf the radiobutton's state is \\fBdisabled\\fR then none of the above\nactions occur:  the radiobutton is completely non-responsive.\n.PP\nThe behavior of radiobuttons can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\ncheckbutton(n), labelframe(n), listbox(n), options(n), scale(n),\nttk::radiobutton(n)\n.SH KEYWORDS\nradiobutton, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/raise.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH raise n 3.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nraise \\- Change a window's position in the stacking order\n.SH SYNOPSIS\n\\fBraise \\fIwindow \\fR?\\fIaboveThis\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nIf the \\fIaboveThis\\fR argument is omitted then the command raises\n\\fIwindow\\fR so that it is above all of its siblings in the stacking\norder (it will not be obscured by any siblings and will obscure\nany siblings that overlap it).\nIf \\fIaboveThis\\fR is specified then it must be the path name of\na window that is either a sibling of \\fIwindow\\fR or the descendant\nof a sibling of \\fIwindow\\fR.\nIn this case the \\fBraise\\fR command will insert\n\\fIwindow\\fR into the stacking order just above \\fIaboveThis\\fR\n(or the ancestor of \\fIaboveThis\\fR that is a sibling of \\fIwindow\\fR);\nthis could end up either raising or lowering \\fIwindow\\fR.\n.PP\nAll \\fBtoplevel\\fR windows may be restacked with respect to each\nother, whatever their relative path names, but the window manager is\nnot obligated to strictly honor requests to restack.\n.PP\nOn macOS raising an iconified \\fBtoplevel\\fR window causes it to be\ndeiconified.\n.SH EXAMPLE\n.PP\nMake a button appear to be in a sibling frame that was created after\nit. This is is often necessary when building GUIs in the style where\nyou create your activity widgets first before laying them out on the\ndisplay:\n.CS\nbutton .b -text \"Hi there!\"\npack [frame .f -background blue]\npack [label .f.l1 -text \"This is above\"]\npack .b -in .f\npack [label .f.l2 -text \"This is below\"]\n\\fBraise\\fR .b\n.CE\n.SH \"SEE ALSO\"\nlower(n)\n.SH KEYWORDS\nobscure, raise, stacking order\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/scale.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH scale n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nscale \\- Create and manipulate 'scale' value-controlled slider widgets\n.SH SYNOPSIS\n\\fBscale\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-foreground\t\\-relief\n\\-background\t\\-highlightbackground\t\\-repeatdelay\n\\-borderwidth\t\\-highlightcolor\t\\-repeatinterval\n\\-cursor\t\\-highlightthickness\t\\-takefocus\n\\-font\t\\-orient\t\\-troughcolor\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-bigincrement bigIncrement BigIncrement\nSome interactions with the scale cause its value to change by\n.QW large\nincrements;  this option specifies the size of the\nlarge increments.  If specified as 0, the large increments default\nto 1/10 the range of the scale.\n.OP \\-command command Command\nSpecifies the prefix of a Tcl command to invoke whenever the scale's\nvalue is changed via a widget command.\nThe actual command consists\nof this option followed by a space and a real number indicating the\nnew value of the scale.\n.OP \\-digits digits Digits\nAn integer specifying how many significant digits should be retained\nwhen converting the value of the scale to a string.\nIf the number is negative or zero, then the scale picks\nthe smallest value that guarantees that every possible slider\nposition prints as a different string.\n.OP \\-from from From\nA real value corresponding to the left or top end of the scale.\n.OP \\-label label Label\nA string to display as a label for the scale.  For\nvertical scales the label is displayed just to the right of the\ntop end of the scale.  For horizontal scales the label is displayed\njust above the left end of the scale.  If the option is specified\nas an empty string, no label is displayed.\n.OP \\-length length Length\nSpecifies the desired long dimension of the scale in screen units\n(i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR).\nFor vertical scales this is the scale's height;  for horizontal scales\nit is the scale's width.\n.OP \\-resolution resolution Resolution\nA real value specifying the resolution for the scale.\nIf this value is greater than zero then the scale's value will always be\nrounded to an even multiple of this value, as will\nthe endpoints of the scale.  If the value is negative then no\nrounding occurs.  Defaults to 1 (i.e., the value will be integral).\n.OP \\-showvalue showValue ShowValue\nSpecifies a boolean value indicating whether or not the current\nvalue of the scale is to be displayed.\n.OP \\-sliderlength sliderLength SliderLength\nSpecifies the size of the slider, measured in screen units along the slider's\nlong dimension.  The value may be specified in any of the forms acceptable\nto \\fBTk_GetPixels\\fR.\n.OP \\-sliderrelief sliderRelief SliderRelief\nSpecifies the relief to use when drawing the slider, such as \\fBraised\\fR\nor \\fBsunken\\fR.\n.OP \\-state state State\nSpecifies one of three states for the scale:  \\fBnormal\\fR,\n\\fBactive\\fR, or \\fBdisabled\\fR.\nIf the scale is disabled then the value may not be changed and the scale\nwill not activate.\nIf the scale is active, the slider is displayed using the color\nspecified by the \\fB\\-activebackground\\fR option.\n.OP \\-tickinterval tickInterval TickInterval\nMust be a real value.\nDetermines the spacing between numerical\ntick marks displayed below or to the left of the slider. The values will all\nbe displayed with the same number of decimal places, which will be enough to\nensure they are all accurate to within 20% of a tick interval.\nIf 0, no tick marks will be displayed.\n.OP \\-to to To\nSpecifies a real value corresponding\nto the right or bottom end of the scale.\nThis value may be either less than or greater than the \\fB\\-from\\fR option.\n.OP \\-variable variable Variable\nSpecifies the name of a global variable to link to the scale.  Whenever the\nvalue of the variable changes, the scale will update to reflect this\nvalue.\nWhenever the scale is manipulated interactively, the variable\nwill be modified to reflect the scale's new value.\n.OP \\-width width Width\nSpecifies the desired narrow dimension of the scale in screen units\n(i.e. any of the forms acceptable to \\fBTk_GetPixels\\fR).\nFor vertical scales this is the scale's width;  for horizontal scales\nthis is the scale's height.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBscale\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a scale widget.\nAdditional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the scale such as its colors, orientation,\nand relief.  The \\fBscale\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA scale is a widget that displays a rectangular \\fItrough\\fR and a\nsmall \\fIslider\\fR.  The trough corresponds to a range\nof real values (determined by the \\fB\\-from\\fR, \\fB\\-to\\fR, and\n\\fB\\-resolution\\fR options),\nand the position of the slider selects a particular real value.\nThe slider's position (and hence the scale's value) may be adjusted\nwith the mouse or keyboard as described in the \\fBBINDINGS\\fR\nsection below.  Whenever the scale's value is changed, a Tcl\ncommand is invoked (using the \\fB\\-command\\fR option) to notify\nother interested widgets of the change.\nIn addition, the value\nof the scale can be linked to a Tcl variable (using the \\fB\\-variable\\fR\noption), so that changes in either are reflected in the other.\n.PP\nThree annotations may be displayed in a scale widget:  a label\nappearing at the top right of the widget (top left for horizontal\nscales), a number displayed just to the left of the slider\n(just above the slider for horizontal scales), and a collection\nof numerical tick marks just to the left of the current value\n(just below the trough for horizontal scales).  Each of these three\nannotations may be enabled or disabled using the\nconfiguration options.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBscale\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for scale widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBscale\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBscale\\fR\ncommand.\n.\\\" METHOD: coords\n.TP\n\\fIpathName \\fBcoords \\fR?\\fIvalue\\fR?\n.\nReturns a list whose elements are the x and y coordinates of\nthe point along the centerline of the trough that corresponds\nto \\fIvalue\\fR.\nIf \\fIvalue\\fR is omitted then the scale's current value is used.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR ?\\fIx y\\fR?\n.\nIf \\fIx\\fR and \\fIy\\fR are omitted, returns the current value\nof the scale.  If \\fIx\\fR and \\fIy\\fR are specified, they give\npixel coordinates within the widget;  the command returns\nthe scale value corresponding to the given pixel.\nOnly one of \\fIx\\fR or \\fIy\\fR is used:  for horizontal scales\n\\fIy\\fR is ignored, and for vertical scales \\fIx\\fR is ignored.\n.\\\" METHOD: identify\n.TP\n\\fIpathName \\fBidentify \\fIx y\\fR\n.\nReturns a string indicating what part of the scale lies under\nthe coordinates given by \\fIx\\fR and \\fIy\\fR.\nA return value of \\fBslider\\fR means that the point is over\nthe slider;  \\fBtrough1\\fR means that the point is over the\nportion of the slider above  or to the left of the slider;\nand \\fBtrough2\\fR means that the point is over the portion\nof the slider below or to the right of the slider.\nIf the point is not over one of these elements, an empty string\nis returned.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset \\fIvalue\\fR\n.\nThis command is invoked to change the current value of the scale,\nand hence the position at which the slider is displayed.  \\fIValue\\fR\ngives the new value for the scale.\nThe command has no effect if the scale is disabled.\n.SH BINDINGS\n.PP\nTk automatically creates class bindings for scales that give them\nthe following default behavior.\nWhere the behavior is different for vertical and horizontal scales,\nthe horizontal behavior is described in parentheses.\n.IP [1]\nIf button 1 is pressed in the trough, the scale's value will\nbe incremented or decremented by the value of the \\fB\\-resolution\\fR\noption so that the slider moves in the direction of the cursor.\nIf the button is held down, the action auto-repeats.\n.IP [2]\nIf button 1 is pressed over the slider, the slider can be dragged\nwith the mouse.\n.IP [3]\nIf button 1 is pressed in the trough with the Control key down,\nthe slider moves all the way to the end of its range, in the\ndirection towards the mouse cursor.\n.IP [4]\nIf button 2 is pressed, the scale's value is set to the mouse\nposition.  If the mouse is dragged with button 2 down, the scale's\nvalue changes with the drag.\n.IP [5]\nThe Up and Left keys move the slider up (left) by the value\nof the \\fB\\-resolution\\fR option.\n.IP [6]\nThe Down and Right keys move the slider down (right) by the value\nof the \\fB\\-resolution\\fR option.\n.IP [7]\nControl-Up and Control-Left move the slider up (left) by the\nvalue of the \\fB\\-bigincrement\\fR option.\n.IP [8]\nControl-Down and Control-Right move the slider down (right) by the\nvalue of the \\fB\\-bigincrement\\fR option.\n.IP [9]\nHome moves the slider to the top (left) end of its range.\n.IP [10]\nEnd moves the slider to the bottom (right) end of its range.\n.PP\nIf the scale is disabled using the \\fB\\-state\\fR option then\nnone of the above bindings have any effect.\n.PP\nThe behavior of scales can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\nttk::scale(n)\n.SH KEYWORDS\nscale, slider, trough, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/scrollbar.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH scrollbar n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nscrollbar \\- Create and manipulate 'scrollbar' scrolling control and indicator widgets\n.SH SYNOPSIS\n\\fBscrollbar\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-highlightcolor\t\\-repeatdelay\n\\-background\t\\-highlightthickness\t\\-repeatinterval\n\\-borderwidth\t\\-jump\t\\-takefocus\n\\-cursor\t\\-orient\t\\-troughcolor\n\\-highlightbackground\t\\-relief\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-activerelief activeRelief ActiveRelief\nSpecifies the relief to use when displaying the element that is\nactive, if any.\nElements other than the active element are always displayed with\na raised relief.\n.OP \\-command command Command\nSpecifies the prefix of a Tcl command to invoke to change the view\nin the widget associated with the scrollbar.  When a user requests\na view change by manipulating the scrollbar, a Tcl command is\ninvoked.  The actual command consists of this option followed by\nadditional information as described later.  This option almost always has\na value such as \\fB.t xview\\fR or \\fB.t yview\\fR, consisting of the\nname of a widget and either \\fBxview\\fR (if the scrollbar is for\nhorizontal scrolling) or \\fByview\\fR (for vertical scrolling).\nAll scrollable widgets have \\fBxview\\fR and \\fByview\\fR commands\nthat take exactly the additional arguments appended by the scrollbar\nas described in \\fBSCROLLING COMMANDS\\fR below.\n.OP \\-elementborderwidth elementBorderWidth BorderWidth\nSpecifies the width of borders drawn around the internal elements\nof the scrollbar (the two arrows and the slider).  The value may\nhave any of the forms acceptable to \\fBTk_GetPixels\\fR.\nIf this value is the empty string (the default), the value of\nthe \\fB\\-borderwidth\\fR option is used in its place.\n.OP \\-width width Width\nSpecifies the desired narrow dimension of the scrollbar window,\nnot including 3-D border, if any.  For vertical\nscrollbars this will be the width and for horizontal scrollbars\nthis will be the height.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBscrollbar\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a scrollbar widget.\nAdditional options, described above, may be specified on the command\nline or in the option database to configure aspects of the scrollbar\nsuch as its colors, orientation, and relief.\nThe \\fBscrollbar\\fR command returns its \\fIpathName\\fR argument.\nAt the time this command is invoked, there must not exist a window\nnamed \\fIpathName\\fR, but \\fIpathName\\fR's parent must exist.\n.PP\nA scrollbar is a widget that displays two arrows, one at each end of\nthe scrollbar, and a \\fIslider\\fR in the middle portion of the\nscrollbar.\nIt provides information about what is visible in an \\fIassociated window\\fR\nthat displays a document of some sort (such as a file being edited or\na drawing).\nThe position and size of the slider indicate which portion of the\ndocument is visible in the associated window.  For example, if the\nslider in a vertical scrollbar covers the top third of the area\nbetween the two arrows, it means that the associated window displays\nthe top third of its document.\n.PP\nScrollbars can be used to adjust the view in the associated window\nby clicking or dragging with the mouse.  See the \\fBBINDINGS\\fR section\nbelow for details.\n.SH \"ELEMENTS\"\n.PP\nA scrollbar displays five elements, which are referred to in the\nwidget commands for the scrollbar:\n.IP \\fBarrow1\\fR 10\nThe top or left arrow in the scrollbar.\n.IP \\fBtrough1\\fR 10\nThe region between the slider and \\fBarrow1\\fR.\n.IP \\fBslider\\fR 10\nThe rectangle that indicates what is visible in the associated widget.\n.IP \\fBtrough2\\fR 10\nThe region between the slider and \\fBarrow2\\fR.\n.IP \\fBarrow2\\fR 10\nThe bottom or right arrow in the scrollbar.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBscrollbar\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for scrollbar widgets:\n.\\\" METHOD: activate\n.TP\n\\fIpathName \\fBactivate \\fR?\\fIelement\\fR?\n.\nMarks the element indicated by \\fIelement\\fR as active, which\ncauses it to be displayed as specified by the \\fB\\-activebackground\\fR\nand \\fB\\-activerelief\\fR options.\nThe only element values understood by this command are \\fBarrow1\\fR,\n\\fBslider\\fR, or \\fBarrow2\\fR.\nIf any other value is specified then no element of the scrollbar\nwill be active.\nIf \\fIelement\\fR is not specified, the command returns\nthe name of the element that is currently active, or an empty string\nif no element is active.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBscrollbar\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBscrollbar\\fR\ncommand.\n.\\\" METHOD: delta\n.TP\n\\fIpathName \\fBdelta \\fIdeltaX deltaY\\fR\n.\nReturns a real number indicating the fractional change in\nthe scrollbar setting that corresponds to a given change\nin slider position.  For example, if the scrollbar is horizontal,\nthe result indicates how much the scrollbar setting must change\nto move the slider \\fIdeltaX\\fR pixels to the right (\\fIdeltaY\\fR is\nignored in this case).\nIf the scrollbar is vertical, the result indicates how much the\nscrollbar setting must change to move the slider \\fIdeltaY\\fR pixels\ndown.  The arguments and the result may be zero or negative.\n.\\\" METHOD: fraction\n.TP\n\\fIpathName \\fBfraction \\fIx y\\fR\n.\nReturns a real number between 0 and 1 indicating where the point\ngiven by \\fIx\\fR and \\fIy\\fR lies in the trough area of the scrollbar.\nThe value 0 corresponds to the top or left of the trough, the\nvalue 1 corresponds to the bottom or right, 0.5 corresponds to\nthe middle, and so on.\n\\fIX\\fR and \\fIy\\fR must be pixel coordinates relative to the scrollbar\nwidget.\nIf \\fIx\\fR and \\fIy\\fR refer to a point outside the trough, the closest\npoint in the trough is used.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the scrollbar settings in the form of a list whose\nelements are the arguments to the most recent \\fBset\\fR widget command.\n.\\\" METHOD: identify\n.TP\n\\fIpathName \\fBidentify \\fIx y\\fR\n.\nReturns the name of the element under the point given by \\fIx\\fR and\n\\fIy\\fR (such as \\fBarrow1\\fR), or an empty string if the point does\nnot lie in any element of the scrollbar.\n\\fIX\\fR and \\fIy\\fR must be pixel coordinates relative to the scrollbar\nwidget.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset \\fIfirst last\\fR\n.\nThis command is invoked by the scrollbar's associated widget to\ntell the scrollbar about the current view in the widget.\nThe command takes two arguments, each of which is a real fraction\nbetween 0 and 1.\nThe fractions describe the range of the document that is visible in\nthe associated widget.\nFor example, if \\fIfirst\\fR is 0.2 and \\fIlast\\fR is 0.4, it means\nthat the first part of the document visible in the window is 20%\nof the way through the document, and the last visible part is 40%\nof the way through.\n.SH \"SCROLLING COMMANDS\"\n.PP\nWhen the user interacts with the scrollbar, for example by dragging\nthe slider, the scrollbar notifies the associated widget that it\nmust change its view.\nThe scrollbar makes the notification by evaluating a Tcl command\ngenerated from the scrollbar's \\fB\\-command\\fR option.\nThe command may take any of the following forms.\nIn each case, \\fIprefix\\fR is the contents of the\n\\fB\\-command\\fR option, which usually has a form like\n.QW \"\\fB.t yview\\fR\" .\n.\\\" METHOD: moveto\n.TP\n\\fIprefix \\fBmoveto \\fIfraction\\fR\n.\n\\fIFraction\\fR is a real number between 0 and 1.\nThe widget should adjust its view so that the point given\nby \\fIfraction\\fR appears at the beginning of the widget.\nIf \\fIfraction\\fR is 0 it refers to the beginning of the\ndocument.  1.0 refers to the end of the document, 0.333\nrefers to a point one-third of the way through the document,\nand so on.\n.\\\" METHOD: scroll\n.TP\n\\fIprefix \\fBscroll \\fInumber \\fBpages\\fR\n.\nThe widget should adjust its view by \\fInumber\\fR pages.\nIt is up to the widget to define the meaning of a page;  typically\nit is slightly less than what fits in the window, so that there\nis a slight overlap between the old and new views.\n\\fINumber\\fR is either 1, which means the next page should\nbecome visible, or \\-1, which means that the previous page should\nbecome visible. Fractional numbers are rounded away from 0, so\nscrolling 0.001 pages has the same effect as scrolling 1 page.\n.TP\n\\fIprefix \\fBscroll \\fInumber \\fBunits\\fR\n.\nThe widget should adjust its view by \\fInumber\\fR units.\nThe units are defined in whatever way makes sense for the widget,\nsuch as characters or lines in a text widget.\n\\fINumber\\fR is either 1, which means one unit should scroll off\nthe top or left of the window, or \\-1, which means that one unit\nshould scroll off the bottom or right of the window. Fractional\nnumbers are rounded away from 0, so scrolling 0.001 units has\nthe same effect as scrolling 1 unit.\n.SH BINDINGS\n.PP\nTk automatically creates class bindings for scrollbars that give them\nthe following default behavior.\nIf the behavior is different for vertical and horizontal scrollbars,\nthe horizontal behavior is described in parentheses.\n.IP [1]\nPressing button 1 over \\fBarrow1\\fR causes the view in the\nassociated widget to shift up (left) by one unit so that the\ndocument appears to move down (right) one unit.\nIf the button is held down, the action auto-repeats.\n.IP [2]\nPressing button 1 over \\fBtrough1\\fR causes the view in the\nassociated widget to shift up (left) by one screenful so that the\ndocument appears to move down (right) one screenful.\nIf the button is held down, the action auto-repeats.\n.IP [3]\nPressing button 1 over the slider and dragging causes the view\nto drag with the slider.\nIf the \\fBjump\\fR option is true, then the view does not drag along\nwith the slider;  it changes only when the mouse button is released.\n.IP [4]\nPressing button 1 over \\fBtrough2\\fR causes the view in the\nassociated widget to shift down (right) by one screenful so that the\ndocument appears to move up (left) one screenful.\nIf the button is held down, the action auto-repeats.\n.IP [5]\nPressing button 1 over \\fBarrow2\\fR causes the view in the\nassociated widget to shift down (right) by one unit so that the\ndocument appears to move up (left) one unit.\nIf the button is held down, the action auto-repeats.\n.IP [6]\nIf button 2 is pressed over the trough or the slider, it sets\nthe view to correspond to the mouse position;  dragging the\nmouse with button 2 down causes the view to drag with the mouse.\nIf button 2 is pressed over one of the arrows, it causes the\nsame behavior as pressing button 1.\n.IP [7]\nIf button 1 is pressed with the Control key down, then if the\nmouse is over \\fBarrow1\\fR or \\fBtrough1\\fR the view changes\nto the very top (left) of the document;  if the mouse is over\n\\fBarrow2\\fR or \\fBtrough2\\fR the view changes\nto the very bottom (right) of the document;  if the mouse is\nanywhere else then the button press has no effect.\n.IP [8]\nIn vertical scrollbars the Up and Down keys have the same behavior\nas mouse clicks over \\fBarrow1\\fR and \\fBarrow2\\fR, respectively.\nIn horizontal scrollbars these keys have no effect.\n.IP [9]\nIn vertical scrollbars Control-Up and Control-Down have the same\nbehavior as mouse clicks over \\fBtrough1\\fR and \\fBtrough2\\fR, respectively.\nIn horizontal scrollbars these keys have no effect.\n.IP [10]\nIn horizontal scrollbars the Up and Down keys have the same behavior\nas mouse clicks over \\fBarrow1\\fR and \\fBarrow2\\fR, respectively.\nIn vertical scrollbars these keys have no effect.\n.IP [11]\nIn horizontal scrollbars Control-Up and Control-Down have the same\nbehavior as mouse clicks over \\fBtrough1\\fR and \\fBtrough2\\fR, respectively.\nIn vertical scrollbars these keys have no effect.\n.IP [12]\nThe Prior and Next keys have the same behavior\nas mouse clicks over \\fBtrough1\\fR and \\fBtrough2\\fR, respectively.\n.IP [13]\nThe Home key adjusts the view to the top (left edge) of the document.\n.IP [14]\nThe End key adjusts the view to the bottom (right edge) of the document.\n.SH EXAMPLE\n.PP\nCreate a window with a scrollable \\fBtext\\fR widget:\n.CS\ntoplevel .tl\ntext .tl.t -yscrollcommand {.tl.s set}\n\\fBscrollbar\\fR .tl.s -command {.tl.t yview}\ngrid .tl.t .tl.s -sticky nsew\ngrid columnconfigure .tl 0 -weight 1\ngrid rowconfigure .tl 0 -weight 1\n.CE\n.SH \"SEE ALSO\"\nttk::scrollbar(n)\n.SH KEYWORDS\nscrollbar, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/selection.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH selection n 8.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nselection \\- Manipulate the X selection\n.SH SYNOPSIS\n\\fBselection \\fIoption\\fR ?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis command provides a Tcl interface to the X selection mechanism and\nimplements the full selection functionality described in the\nX Inter-Client Communication Conventions Manual (ICCCM).\n.PP\nNote that for management of the \\fBCLIPBOARD\\fR selection (see below), the\n\\fBclipboard\\fR command may also be used.\n.PP\nThe first argument to \\fBselection\\fR determines the format of the\nrest of the arguments and the behavior of the command.  The following\nforms are currently supported:\n.\\\" METHOD: clear\n.TP\n\\fBselection clear\\fR ?\\fB\\-displayof\\fI window\\fR? ?\\fB\\-selection\\fI selection\\fR?\n.\nIf \\fIselection\\fR exists anywhere on \\fIwindow\\fR's display, clear it\nso that no window owns the selection anymore.  \\fISelection\\fR\nspecifies the X selection that should be cleared, and should be an\natom name such as \\fBPRIMARY\\fR or \\fBCLIPBOARD\\fR; see the Inter-Client\nCommunication Conventions Manual for complete details.\n\\fISelection\\fR defaults to \\fBPRIMARY\\fR and \\fIwindow\\fR defaults to\n.QW . .\nReturns an empty string.\n.\\\" METHOD: get\n.TP\n\\fBselection get\\fR ?\\fB\\-displayof\\fI window\\fR? ?\\fB\\-selection\\fI selection\\fR? ?\\fB\\-type\\fI type\\fR?\n.\nRetrieves the value of \\fIselection\\fR from \\fIwindow\\fR's display and\nreturns it as a result.  \\fISelection\\fR defaults to \\fBPRIMARY\\fR and\n\\fIwindow\\fR defaults to\n.QW . .\n\\fIType\\fR specifies the form in which the selection is to be returned\n(the desired\n.QW target\nfor conversion, in ICCCM terminology), and\nshould be an atom name such as \\fBSTRING\\fR or \\fBFILE_NAME\\fR; see the\nInter-Client Communication Conventions Manual for complete details.\n\\fIType\\fR defaults to \\fBSTRING\\fR.  The selection owner may choose to\nreturn the selection in any of several different representation\nformats, such as \\fBSTRING\\fR, \\fBUTF8_STRING\\fR, \\fBATOM\\fR,\n\\fBINTEGER\\fR, etc. (this format is different\nthan the selection type; see the ICCCM for all the confusing details).\nIf the selection is returned in a non-string format, such as \\fBINTEGER\\fR\nor \\fBATOM\\fR, the \\fBselection\\fR command converts it to string format as a\ncollection of fields separated by spaces: atoms are converted to their\ntextual names, and anything else is converted to hexadecimal integers.\nNote that \\fBselection get\\fR does not retrieve the selection in the\n\\fBUTF8_STRING\\fR format unless told to.\n.\\\" METHOD: handle\n.TP\n\\fBselection handle\\fR ?\\fB\\-selection\\fI s\\fR? ?\\fB\\-type\\fI t\\fR? ?\\fB\\-format\\fI f\\fR? \\fIwindow command\\fR\n.\nCreates a handler for selection requests, such that \\fIcommand\\fR will\nbe executed whenever selection \\fIs\\fR is owned by \\fIwindow\\fR and\nsomeone attempts to retrieve it in the form given by type \\fIt\\fR\n(e.g. \\fIt\\fR is specified in the \\fBselection get\\fR command).\n\\fIS\\fR defaults to \\fBPRIMARY\\fR, \\fIt\\fR defaults to \\fBSTRING\\fR, and\n\\fIf\\fR defaults to \\fBSTRING\\fR.  If \\fIcommand\\fR is an empty string\nthen any existing handler for \\fIwindow\\fR, \\fIt\\fR, and\n\\fIs\\fR is removed.\nNote that when the selection is handled as type \\fBSTRING\\fR it is also\nautomatically handled as type \\fBUTF8_STRING\\fR as well.\n.RS\n.PP\nWhen \\fIselection\\fR is requested, \\fIwindow\\fR is the selection owner,\nand \\fItype\\fR is the requested type, \\fIcommand\\fR will be executed\nas a Tcl command with two additional numbers appended to it\n(with space separators).\nThe two additional numbers\nare \\fIoffset\\fR and \\fImaxChars\\fR:  \\fIoffset\\fR specifies a starting\ncharacter position in the selection and \\fImaxChars\\fR gives the maximum\nnumber of characters to retrieve.  The command should return a value consisting\nof at most \\fImaxChars\\fR of the selection, starting at position\n\\fIoffset\\fR.  For very large selections (larger than \\fImaxChars\\fR)\nthe selection will be retrieved using several invocations of \\fIcommand\\fR\nwith increasing \\fIoffset\\fR values.  If \\fIcommand\\fR returns a string\nwhose length is less than \\fImaxChars\\fR, the return value is assumed to\ninclude all of the remainder of the selection;  if the length of\n\\fIcommand\\fR's result is equal to \\fImaxChars\\fR then\n\\fIcommand\\fR will be invoked again, until it eventually\nreturns a result shorter than \\fImaxChars\\fR.  The value of \\fImaxChars\\fR\nwill always be relatively large (thousands of characters).\n.PP\nIf \\fIcommand\\fR returns an error then the selection retrieval is rejected\njust as if the selection did not exist at all.\n.PP\nThe \\fIformat\\fR argument specifies the representation that should be\nused to transmit the selection to the requester (the second column of\nTable 2 of the ICCCM), and defaults to \\fBSTRING\\fR.  If \\fIformat\\fR is\n\\fBSTRING\\fR, the selection is transmitted as 8-bit ASCII characters (i.e.\njust in the form returned by \\fIcommand\\fR, in the system \\fBencoding\\fR;\nthe \\fBUTF8_STRING\\fR format always uses UTF-8 as its encoding).\nIf \\fIformat\\fR is\n\\fBATOM\\fR, then the return value from \\fIcommand\\fR is divided into fields\nseparated by white space;  each field is converted to its atom value,\nand the 32-bit atom value is transmitted instead of the atom name.\nFor any other \\fIformat\\fR, the return value from \\fIcommand\\fR is\ndivided into fields separated by white space and each field is\nconverted to a 32-bit integer;  an array of integers is transmitted\nto the selection requester.\n.PP\nThe \\fIformat\\fR argument is needed only for compatibility with\nselection requesters that do not use Tk.  If Tk is being\nused to retrieve the selection then the value is converted back to\na string at the requesting end, so \\fIformat\\fR is\nirrelevant.\n.RE\n.\\\" METHOD: own\n.TP\n\\fBselection own\\fR ?\\fB\\-displayof\\fI window\\fR? ?\\fB\\-selection\\fI selection\\fR?\n.TP\n\\fBselection own\\fR ?\\fB\\-command\\fI command\\fR? ?\\fB\\-selection\\fI selection\\fR? \\fIwindow\\fR\n.\nThe first form of \\fBselection own\\fR returns the path name of the\nwindow in this application that owns \\fIselection\\fR on the display\ncontaining \\fIwindow\\fR, or an empty string if no window in this\napplication owns the selection.  \\fISelection\\fR defaults to \\fBPRIMARY\\fR and\n\\fIwindow\\fR defaults to\n.QW . .\n.RS\n.PP\nThe second form of \\fBselection own\\fR causes \\fIwindow\\fR to become\nthe new owner of \\fIselection\\fR on \\fIwindow\\fR's display, returning\nan empty string as result. The existing owner, if any, is notified\nthat it has lost the selection.\nIf \\fIcommand\\fR is specified, it is a Tcl script to execute when\nsome other window claims ownership of the selection away from\n\\fIwindow\\fR.  \\fISelection\\fR defaults to PRIMARY.\n.RE\n.SH WIDGET FACILITIES\n.PP\nThe \\fBtext\\fR, \\fBentry\\fR, \\fBttk::entry\\fR, \\fBlistbox\\fR, \\fBspinbox\\fR\nand \\fBttk::spinbox\\fR widgets have the option \\fB\\-exportselection\\fR.  If a\nwidget has this option set to boolean \\fBtrue\\fR, then (in an unsafe\ninterpreter) a selection made in the widget is automatically written to the\n\\fBPRIMARY\\fR selection.\n.PP\nA GUI event, for example \\fB<<PasteSelection>>\\fR, can copy the \\fBPRIMARY\\fR\nselection to certain widgets.  This copy is implemented by a widget binding to\nthe event.  The binding script makes appropriate calls to the \\fBselection\\fR\ncommand.\n.PP\n.SH PORTABILITY ISSUES\n.PP\nOn X11, the \\fBPRIMARY\\fR selection is a system-wide feature of the X server,\nallowing communication between different processes that are X11 clients.\n.PP\nOn Windows, the \\fBPRIMARY\\fR selection is not provided by the system, but\nonly by Tk, and so it is shared only between windows of a parent interpreter\nand its child interpreters.  It is not shared between interpreters in\ndifferent processes or different threads.  Each parent interpreter has a\nseparate \\fBPRIMARY\\fR selection that is shared only with its child\ninterpreters which are not safe interpreters.\n.PP\n.SH SECURITY\n.PP\nA safe interpreter cannot read from the \\fBPRIMARY\\fR selection because its\n\\fBselection\\fR command is hidden.  For this reason the \\fBPRIMARY\\fR\nselection cannot be written to the Tk widgets of a safe interpreter.\n.PP\nA Tk widget can have its option \\fB\\-exportselection\\fR set to boolean\n\\fBtrue\\fR, but in a safe interpreter this option has no effect: writing\nfrom the widget to the \\fBPRIMARY\\fR selection is disabled.\n.PP\nThese are security features.  A safe interpreter may run untrusted code, and\nit is a security risk if this untrusted code can read or write the\n\\fBPRIMARY\\fR selection used by other interpreters.\n.PP\n.SH EXAMPLES\n.PP\nOn X11 platforms, one of the standard selections available is the\n\\fBSECONDARY\\fR selection. Hardly anything uses it, but here is how to read\nit using Tk:\n.PP\n.CS\nset selContents [\\fBselection get\\fR -selection SECONDARY]\n.CE\n.PP\nMany different types of data may be available for a selection; the\nspecial type \\fBTARGETS\\fR allows you to get a list of available types:\n.PP\n.CS\nforeach type [\\fBselection get\\fR -type TARGETS] {\n   puts \"Selection PRIMARY supports type $type\"\n}\n.CE\n.PP\nTo claim the selection, you must first set up a handler to supply the\ndata for the selection. Then you have to claim the selection...\n.CS\n# Set up the data handler ready for incoming requests\nset foo \"This is a string with some data in it... blah blah\"\n\\fBselection handle\\fR -selection SECONDARY . getData\nproc getData {offset maxChars} {\n   puts \"Retrieving selection starting at $offset\"\n   return [string range $::foo $offset [expr {$offset+$maxChars-1}]]\n}\n\n# Now we grab the selection itself\nputs \"Claiming selection\"\n\\fBselection own\\fR -command lost -selection SECONDARY .\nproc lost {} {\n   puts \"Lost selection\"\n}\n.CE\n.SH \"SEE ALSO\"\nclipboard(n)\n.SH KEYWORDS\nclear, format, handler, ICCCM, own, selection, target, type\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/send.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH send n 4.0 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nsend \\- Execute a command in a different application\n.SH SYNOPSIS\n\\fBsend ?\\fIoptions\\fR? \\fIapp cmd \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThis command arranges for \\fIcmd\\fR (and \\fIarg\\fRs) to be executed in the\napplication named by \\fIapp\\fR.  It returns the result or\nerror from that command execution.\n\\fIApp\\fR may be the name of any application whose main window is\non the display containing the sender's main window;  it need not\nbe within the same process.\nIf no \\fIarg\\fR arguments are present, then the command to be executed is\ncontained entirely within the \\fIcmd\\fR argument.  If one or\nmore \\fIarg\\fRs are present, they are concatenated to form the\ncommand to be executed, just as for the \\fBeval\\fR command.\n.PP\nIf the initial arguments of the command begin with\n.QW \\-\nthey are treated as options.  The following options are currently defined:\n.\\\" OPTION: -async\n.TP\n\\fB\\-async\\fR\n.\nRequests asynchronous invocation.  In this case the \\fBsend\\fR\ncommand will complete immediately without waiting for \\fIcmd\\fR\nto complete in the target application;  no result will be available\nand errors in the sent command will be ignored.\nIf the target application is in the same process as the sending\napplication then the \\fB\\-async\\fR option is ignored.\n.\\\" OPTION: -displayof\n.TP\n\\fB\\-displayof\\fI pathName\\fR\n.\nSpecifies that the target application's main window is on the display\nof the window given by \\fIpathName\\fR, instead of the display containing\nthe application's main window.\n.\\\" OPTION: --\n.TP\n\\fB\\-\\|\\-\\fR\n.\nServes no purpose except to terminate the list of options.  This\noption is needed only if \\fIapp\\fR could contain a leading\n.QW \\-\ncharacter.\n.SH \"APPLICATION NAMES\"\n.PP\nThe name of an application is set initially from the name of the\nprogram or script that created the application.\nYou can query and change the name of an application with the\n\\fBtk appname\\fR command.\n.SH \"DISABLING SENDS\"\n.PP\nIf the \\fBsend\\fR command is removed from an application (e.g.\nwith the command \\fBrename\\fR \\fBsend {}\\fR) then the application\nwill not respond to incoming send requests anymore,  nor will it\nbe able to issue outgoing requests.\nCommunication can be reenabled by invoking the \\fBtk appname\\fR\ncommand.\n.SH SECURITY\n.PP\nThe \\fBsend\\fR command is potentially a serious security loophole. On Unix,\nany application that can connect to your X server can send\nscripts to your applications.\nThese incoming scripts can use Tcl to read and\nwrite your files and invoke subprocesses under your name.\nHost-based access control such as that provided by \\fBxhost\\fR\nis particularly insecure, since it allows anyone with an account\non particular hosts to connect to your server, and if disabled it\nallows anyone anywhere to connect to your server.\nIn order to provide at least a small amount of\nsecurity, Tk checks the access control being used by the server\nand rejects incoming sends unless (a) \\fBxhost\\fR-style access control\nis enabled (i.e. only certain hosts can establish connections) and (b) the\nlist of enabled hosts is empty.\nThis means that applications cannot connect to your server unless\nthey use some other form of authorization\nsuch as that provide by \\fBxauth\\fR.\n.PP\nUnder macOS/aqua, the \\fBsend\\fR command can target an interpreter\nrunning in a different process, but only if the target process is\nowned by the same user and is running on the same host system as the\nsender's process.  The \"winfo interps\" command shows exactly which\ninterpreters are valid targets for the \\fBsend\\fR command.\n.PP\nUnder Windows, \\fBsend\\fR is currently disabled.  Most of the\nfunctionality is provided by the \\fBdde\\fR command instead.\n.SH EXAMPLE\n.PP\nThis script fragment can be used to make an application that only runs\nonce on a particular display.\n.CS\nif {[tk appname FoobarApp] ne \"FoobarApp\"} {\n    \\fBsend\\fR -async FoobarApp RemoteStart $argv\n    exit\n}\n# The command that will be called remotely, which raises\n# the application main window and opens the requested files\nproc RemoteStart args {\n    raise .\n    foreach filename $args {\n        OpenFile $filename\n    }\n}\n.CE\n.SH KEYWORDS\napplication, dde, name, remote execution, security, send\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/spinbox.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2000 Jeffrey Hobbs.\n'\\\" Copyright (c) 2000 Ajuba Solutions.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH spinbox n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nspinbox \\- Create and manipulate 'spinbox' value spinner widgets\n.SH SYNOPSIS\n\\fBspinbox\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-activebackground\t\\-highlightthickness\t\\-repeatinterval\n\\-background\t\\-insertbackground\t\\-selectbackground\n\\-borderwidth\t\\-insertborderwidth\t\\-selectborderwidth\n\\-cursor\t\\-insertontime\t\\-selectforeground\n\\-exportselection\t\\-insertwidth\t\\-takefocus\n\\-font\t\\-insertofftime\t\\-textvariable\n\\-foreground\t\\-justify\t\\-xscrollcommand\n\\-highlightbackground\t\\-relief\n\\-highlightcolor\t\\-repeatdelay\n\\-placeholder\t\\-placeholderforeground\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-buttonbackground buttonBackground Background\nThe background color to be used for the spin buttons.\n.OP \\-buttoncursor buttonCursor Cursor\nThe cursor to be used when over the spin buttons.  If this is empty\n(the default), a default cursor will be used.\n.OP \\-buttondownrelief buttonDownRelief Relief\nThe relief to be used for the upper spin button.\n.OP \\-buttonuprelief buttonUpRelief Relief\nThe relief to be used for the lower spin button.\n.OP \\-command command Command\nSpecifies a Tcl command to invoke whenever a spinbutton is invoked.\nThe command recognizes several percent substitutions: \\fB%W\\fR for\nthe widget path, \\fB%s\\fR for the current value of the widget, and\n\\fB%d\\fR for the direction of the button pressed (\\fBup\\fR or \\fBdown\\fR).\n.OP \\-disabledbackground disabledBackground DisabledBackground\nSpecifies the background color to use when the spinbox is disabled.  If\nthis option is the empty string, the normal background color is used.\n.OP \\-disabledforeground disabledForeground DisabledForeground\nSpecifies the foreground color to use when the spinbox is disabled.  If\nthis option is the empty string, the normal foreground color is used.\n.OP \\-format format Format\nSpecifies an alternate format to use when setting the string value\nwhen using the \\fB\\-from\\fR and \\fB\\-to\\fR range.\nThis must be a format specifier of the form \\fB%<pad>.<pad>f\\fR,\nas it will format a floating-point number.\n.OP \\-from from From\nA floating-point value corresponding to the lowest value for a spinbox, to\nbe used in conjunction with \\fB\\-to\\fR and \\fB\\-increment\\fR.  When all\nare specified correctly, the spinbox will use these values to control its\ncontents. If this value is greater than the \\fB\\-to\\fR option, then\n\\fB\\-from\\fR and \\fB\\-to\\fR values are automatically swapped.\nIf \\fB\\-values\\fR is specified, it supersedes this option.\n.OP \"\\-invalidcommand or \\-invcmd\" invalidCommand InvalidCommand\nSpecifies a script to eval when \\fB\\-validatecommand\\fR returns 0.  Setting\nit to an empty string disables this feature (the default).  The best use of\nthis option is to set it to \\fIbell\\fR.  See \\fBVALIDATION\\fR below for\nmore information.\n.OP \\-increment increment Increment\nA floating-point value specifying the increment.  When used with\n\\fB\\-from\\fR and \\fB\\-to\\fR, the value in the widget will be adjusted by\n\\fB\\-increment\\fR when a spin button is pressed (up adds the value,\ndown subtracts the value).\n.OP \\-readonlybackground readonlyBackground ReadonlyBackground\nSpecifies the background color to use when the spinbox is readonly.  If\nthis option is the empty string, the normal background color is used.\n.OP \\-state state State\nSpecifies one of three states for the spinbox:  \\fBnormal\\fR,\n\\fBdisabled\\fR, or \\fBreadonly\\fR.  If the spinbox is readonly, then the\nvalue may not be changed using widget commands and no insertion cursor\nwill be displayed, even if the input focus is in the widget; the\ncontents of the widget may still be selected.  If the spinbox is\ndisabled, the value may not be changed, no insertion cursor will be\ndisplayed, the contents will not be selectable, and the spinbox may\nbe displayed in a different color, depending on the values of the\n\\fB\\-disabledforeground\\fR and \\fB\\-disabledbackground\\fR options.\n.OP \\-to to To\nA floating-point value corresponding to the highest value for the spinbox,\nto be used in conjunction with \\fB\\-from\\fR and \\fB\\-increment\\fR.  When\nall are specified correctly, the spinbox will use these values to control\nits contents. If this value is less than the \\fB\\-from\\fR option, then\n\\fB\\-from\\fR and \\fB\\-to\\fR values are automatically swapped.\nIf \\fB\\-values\\fR is specified, it supersedes this option.\n.OP \\-validate validate Validate\nSpecifies the mode in which validation should operate: \\fBnone\\fR,\n\\fBfocus\\fR, \\fBfocusin\\fR, \\fBfocusout\\fR, \\fBkey\\fR, or \\fBall\\fR.\nIt defaults to \\fBnone\\fR.  When you want validation, you must explicitly\nstate which mode you wish to use.  See \\fBVALIDATION\\fR below for more.\n.OP \"\\-validatecommand or \\-vcmd\" validateCommand ValidateCommand\nSpecifies a script to evaluate when you want to validate the input in the\nwidget.  Setting it to an empty string disables this feature (the default).\nValidation occurs according to the value of \\fB\\-validate\\fR.\nThis command must return a valid Tcl boolean value.  If it returns 0 (or\nthe valid Tcl boolean equivalent) then the value of the widget will not\nchange and the \\fB\\-invalidcommand\\fR will be evaluated if it is set.  If it\nreturns 1, then value will be changed.\nSee \\fBVALIDATION\\fR below for more information.\n.OP \\-values values Values\nMust be a proper list value.  If specified, the spinbox will use these\nvalues as to control its contents, starting with the first value.  This\noption has precedence over the \\fB\\-from\\fR and \\fB\\-to\\fR range.\n.OP \\-width width Width\nSpecifies an integer value indicating the desired width of the spinbox window,\nin average-size characters of the widget's font.\nIf the value is negative or zero, the widget picks a\nsize just large enough to hold its current text.\n.OP \\-wrap wrap wrap\nMust be a proper boolean value.  If on, the spinbox will wrap around the\nvalues of data in the widget.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBspinbox\\fR command creates a new window (given by the\n\\fIpathName\\fR argument) and makes it into a spinbox widget.\nAdditional options, described above, may be specified on the\ncommand line or in the option database\nto configure aspects of the spinbox such as its colors, font,\nand relief.  The \\fBspinbox\\fR command returns its\n\\fIpathName\\fR argument.  At the time this command is invoked,\nthere must not exist a window named \\fIpathName\\fR, but\n\\fIpathName\\fR's parent must exist.\n.PP\nA \\fBspinbox\\fR is an extended \\fBentry\\fR widget that allows he user\nto move, or spin, through a fixed set of ascending or descending values\nsuch as times or dates in addition to editing the value as in an\n\\fBentry\\fR.  When first created, a spinbox's string is empty.\nA portion of the spinbox may be selected as described below.\nIf a spinbox is exporting its selection (see the \\fB\\-exportselection\\fR\noption), then it will observe the standard protocols for handling the\nselection;  spinbox selections are available as type \\fBSTRING\\fR.\nSpinboxes also observe the standard Tk rules for dealing with the\ninput focus.  When a spinbox has the input focus it displays an\n\\fIinsertion cursor\\fR to indicate where new characters will be\ninserted.\n.PP\nSpinboxes are capable of displaying strings that are too long to\nfit entirely within the widget's window.  In this case, only a\nportion of the string will be displayed; commands described below\nmay be used to change the view in the window.  Spinboxes use\nthe standard \\fB\\-xscrollcommand\\fR mechanism for interacting with\nscrollbars (see the description of the \\fB\\-xscrollcommand\\fR option\nfor details).  They also support scanning, as described below.\n.SH VALIDATION\n.PP\nValidation works by setting the \\fB\\-validatecommand\\fR\noption to a script which will be evaluated according to the \\fB\\-validate\\fR\noption as follows:\n.PP\n.IP \\fBnone\\fR 10\nDefault.  This means no validation will occur.\n.IP \\fBfocus\\fR 10\nThe \\fB\\-validatecommand\\fR will be called when the spinbox receives or\nloses focus.\n.IP \\fBfocusin\\fR 10\nThe \\fB\\-validatecommand\\fR will be called when the spinbox receives focus.\n.IP \\fBfocusout\\fR 10\nThe \\fB\\-validatecommand\\fR will be called when the spinbox loses focus.\n.IP \\fBkey\\fR 10\nThe \\fB\\-validatecommand\\fR will be called when the spinbox is edited.\n.IP \\fBall\\fR 10\nThe \\fB\\-validatecommand\\fR will be called for all above conditions.\n.PP\nIt is possible to perform percent substitutions on the \\fB\\-validatecommand\\fR\nand \\fB\\-invalidcommand\\fR scripts, just as you would in a \\fBbind\\fR script.\nThe following substitutions are recognized:\n.PP\n.IP \\fB%d\\fR 5\nType of action: 1 for \\fBinsert\\fR, 0 for \\fBdelete\\fR,\nor \\-1 for focus, forced or textvariable validation.\n.IP \\fB%i\\fR 5\nIndex of char string to be inserted/deleted, if any, otherwise \\-1.\n.IP \\fB%P\\fR 5\nThe value of the spinbox should edition occur.  If you are configuring the\nspinbox widget to have a new textvariable, this will be the value of that\ntextvariable.\n.IP \\fB%s\\fR 5\nThe current value of spinbox before edition.\n.IP \\fB%S\\fR 5\nThe text string being inserted/deleted, if any.\nOtherwise it is an empty string.\n.IP \\fB%v\\fR 5\nThe type of validation currently set.\n.IP \\fB%V\\fR 5\nThe type of validation that triggered the callback\n(key, focusin, focusout, forced).\n.IP \\fB%W\\fR 5\nThe name of the spinbox widget.\n.PP\nIn general, the \\fB\\-textvariable\\fR and \\fB\\-validatecommand\\fR can be\ndangerous to mix.  Any problems have been overcome so that using the\n\\fB\\-validatecommand\\fR will not interfere with the traditional behavior of\nthe spinbox widget.  Using the \\fB\\-textvariable\\fR for read-only purposes will\nnever cause problems.  The danger comes when you try set the\n\\fB\\-textvariable\\fR to something that the \\fB\\-validatecommand\\fR would not\naccept, which causes \\fB\\-validate\\fR to become \\fBnone\\fR (the\n\\fB\\-invalidcommand\\fR will not be triggered).  The same happens\nwhen an error occurs evaluating the \\fB\\-validatecommand\\fR.\n.PP\nPrimarily, an error will occur when the \\fB\\-validatecommand\\fR or\n\\fB\\-invalidcommand\\fR encounters an error in its script while evaluating or\n\\fB\\-validatecommand\\fR does not return a valid Tcl boolean value.  The\n\\fB\\-validate\\fR option will also set itself to \\fBnone\\fR when you edit the\nspinbox widget from within either the \\fB\\-validatecommand\\fR or the\n\\fB\\-invalidcommand\\fR.  Such editions will override the one that was being\nvalidated.  If you wish to edit the value of the widget\nduring validation and still have the \\fB\\-validate\\fR option set, you should\ninclude the command\n.CS\n     \\fI%W config -validate %v\\fR\n.CE\nin the \\fB\\-validatecommand\\fR or \\fB\\-invalidcommand\\fR (whichever one you\nwere editing the spinbox widget from).  It is also recommended to not set an\nassociated \\fB\\-textvariable\\fR during validation, as that can cause the\nspinbox widget to become out of sync with the \\fB\\-textvariable\\fR.\n.PP\nAlso, the \\fB\\-validate\\fR option will set itself to \\fBnone\\fR when the\nspinbox value gets changed because of adjustment of \\fB\\-from\\fR or \\fB\\-to\\fR\nand the \\fB\\-validatecommand\\fR returns false. For instance\n.CS\n     \\fIspinbox pathName -from 1 -to 10 -validate all -validatecommand {return 0}\\fR\n.CE\nwill in fact set the \\fB\\-validate\\fR option to \\fBnone\\fR because the default\nvalue for the spinbox gets changed (due to the \\fB\\-from\\fR and \\fB\\-to\\fR\noptions) to a value not accepted by the validation script.\n.PP\nMoreover, forced validation is performed when invoking any spinbutton of\nthe spinbox. If the validation script returns false in this situation,\nthen the \\fB\\-validate\\fR option will be automatically set to \\fBnone\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBspinbox\\fR command creates a new Tcl command whose\nname is \\fIpathName\\fR.  This command may be used to invoke various\noperations on the widget.  It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.\n.SS INDICES\n.PP\nMany of the widget commands for spinboxes take one or more indices as\narguments.  An index specifies a particular character in the spinbox's\nstring, in any of the following ways:\n.TP 12\n\\fInumber\\fR\n.\nSpecifies the character as a numerical index, where 0 corresponds\nto the first character in the string.\n.TP 12\n\\fBanchor\\fR\n.\nIndicates the anchor point for the selection, which is set with the\n\\fBselect from\\fR and \\fBselect adjust\\fR widget commands.\n.TP 12\n\\fBend\\fR\n.\nIndicates the character just after the last one in the spinbox's string.\nThis is equivalent to specifying a numerical index equal to the length\nof the spinbox's string.\n.TP 12\n\\fBinsert\\fR\n.\nIndicates the character adjacent to and immediately following the\ninsertion cursor.\n.TP 12\n\\fBsel.first\\fR\n.\nIndicates the first character in the selection.  It is an error to\nuse this form if the selection is not in the spinbox window.\n.TP 12\n\\fBsel.last\\fR\n.\nIndicates the character just after the last one in the selection.\nIt is an error to use this form if the selection is not in the\nspinbox window.\n.TP 12\n\\fB@\\fInumber\\fR\n.\nIn this form, \\fInumber\\fR is treated as an x-coordinate in the\nspinbox's window;  the character spanning that x-coordinate is used.\nFor example,\n.QW \\fB@0\\fR\nindicates the left-most character in the window.\n.LP\nAbbreviations may be used for any of the forms above, e.g.\n.QW \\fBe\\fR\nor\n.QW \\fBsel.f\\fR .\nIn general, out-of-range indices are automatically rounded to the\nnearest legal value.\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.SS SUBCOMMANDS\n.PP\nThe following commands are possible for spinbox widgets:\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox \\fIindex\\fR\n.\nReturns a list of four numbers describing the bounding box of the\ncharacter given by \\fIindex\\fR.\nThe first two elements of the list give the x and y coordinates of\nthe upper-left corner of the screen area covered by the character\n(in pixels relative to the widget) and the last two elements give\nthe width and height of the character, in pixels.\nThe bounding box may refer to a region outside the visible area\nof the window.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBspinbox\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBspinbox\\fR\ncommand.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIfirst \\fR?\\fIlast\\fR?\n.\nDelete one or more elements of the spinbox.\n\\fIFirst\\fR is the index of the first character to delete, and\n\\fIlast\\fR is the index of the character just after the last\none to delete.\nIf \\fIlast\\fR is not specified it defaults to \\fIfirst\\fR+1,\ni.e. a single character is deleted.\nThis command returns an empty string.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the spinbox's string.\n.\\\" METHOD: icursor\n.TP\n\\fIpathName \\fBicursor \\fIindex\\fR\n.\nArrange for the insertion cursor to be displayed just before the character\ngiven by \\fIindex\\fR.  Returns an empty string.\n.\\\" METHOD: identify\n.TP\n\\fIpathName \\fBidentify\\fI x y\\fR\n.\nReturns the name of the window element corresponding to coordinates\n\\fIx\\fR and \\fIy\\fR in the spinbox.  Return value is one of:\n\\fBnone\\fR, \\fBbuttondown\\fR, \\fBbuttonup\\fR, \\fBentry\\fR.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex\\fI index\\fR\n.\nReturns the numerical index corresponding to \\fIindex\\fR.\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex string\\fR\n.\nInsert the characters of \\fIstring\\fR just before the character\nindicated by \\fIindex\\fR.  Returns an empty string.\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke\\fI element\\fR\n.\nCauses the specified element, either \\fBbuttondown\\fR or \\fBbuttonup\\fR,\nto be invoked, triggering the action associated with it.\n.\\\" METHOD: scan\n.TP\n\\fIpathName \\fBscan\\fI option args\\fR\n.\nThis command is used to implement scanning on spinboxes.  It has\ntwo forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBscan mark \\fIx\\fR\n.\nRecords \\fIx\\fR and the current view in the spinbox window;  used in\nconjunction with later \\fBscan dragto\\fR commands.  Typically this\ncommand is associated with a mouse button press in the widget.  It\nreturns an empty string.\n.TP\n\\fIpathName \\fBscan dragto \\fIx\\fR\n.\nThis command computes the difference between its \\fIx\\fR argument\nand the \\fIx\\fR argument to the last \\fBscan mark\\fR command for\nthe widget.  It then adjusts the view left or right by 10 times the\ndifference in x-coordinates.  This command is typically associated\nwith mouse motion events in the widget, to produce the effect of\ndragging the spinbox at high speed through the window.  The return\nvalue is an empty string.\n.RE\n.\\\" METHOD: selection\n.TP\n\\fIpathName \\fBselection \\fIoption arg\\fR\n.\nThis command is used to adjust the selection within a spinbox.  It\nhas several forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBselection adjust \\fIindex\\fR\n.\nLocate the end of the selection nearest to the character given by\n\\fIindex\\fR, and adjust that end of the selection to be at \\fIindex\\fR\n(i.e. including but not going beyond \\fIindex\\fR).  The other\nend of the selection is made the anchor point for future\n\\fBselect to\\fR commands.  If the selection\nis not currently in the spinbox, then a new selection is created to\ninclude the characters between \\fIindex\\fR and the most recent\nselection anchor point, inclusive.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection clear\\fR\n.\nClear the selection if it is currently in this widget.  If the\nselection is not in this widget then the command has no effect.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection element\\fR ?\\fIelement\\fR?\n.\nSets or gets the currently selected element.  If a spinbutton element\nis specified, it will be displayed depressed.\n.TP\n\\fIpathName \\fBselection from \\fIindex\\fR\n.\nSet the selection anchor point to just before the character\ngiven by \\fIindex\\fR.  Does not change the selection.\nReturns an empty string.\n.TP\n\\fIpathName \\fBselection present\\fR\n.\nReturns 1 if there is are characters selected in the spinbox,\n0 if nothing is selected.\n.TP\n\\fIpathName \\fBselection range \\fIstart end\\fR\n.\nSets the selection to include the characters starting with\nthe one indexed by \\fIstart\\fR and ending with the one just\nbefore \\fIend\\fR.\nIf \\fIend\\fR refers to the same character as \\fIstart\\fR or an\nearlier one, then the spinbox's selection is cleared.\n.TP\n\\fIpathName \\fBselection to \\fIindex\\fR\n.\nIf \\fIindex\\fR is before the anchor point, set the selection\nto the characters from \\fIindex\\fR up to but not including\nthe anchor point.\nIf \\fIindex\\fR is the same as the anchor point, do nothing.\nIf \\fIindex\\fR is after the anchor point, set the selection\nto the characters from the anchor point up to but not including\n\\fIindex\\fR.\nThe anchor point is determined by the most recent \\fBselect from\\fR\nor \\fBselect adjust\\fR command in this widget.\nIf the selection is not in this widget then a new selection is\ncreated using the most recent anchor point specified for the widget.\nReturns an empty string.\n.RE\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset\\fR ?\\fIstring\\fR?\n.\nIf \\fIstring\\fR is specified, the spinbox will try and set it to this\nvalue, otherwise it just returns the spinbox's string.\nIf validation is on, it will occur when setting the string.\n.\\\" METHOD: validate\n.TP\n\\fIpathName \\fBvalidate\\fR\n.\nThis command is used to force an evaluation of the \\fB\\-validatecommand\\fR\nindependent of the conditions specified by the \\fB\\-validate\\fR option.\nThis is done by temporarily setting the \\fB\\-validate\\fR option to \\fBall\\fR.\nIt returns 0 or 1.\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fIargs\\fR\n.\nThis command is used to query and change the horizontal position of the\ntext in the widget's window.  It can take any of the following\nforms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1;  together they describe\nthe horizontal span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the spinbox's text is off-screen to the left, the middle 40% is visible\nin the window, and 40% of the text is off-screen to the right.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview \\fIindex\\fR\n.\nAdjusts the view in the window so that the character given by \\fIindex\\fR\nis displayed at the left edge of the window.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the character \\fIfraction\\fR of the\nway through the text appears at the left edge of the window.\n\\fIFraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR or an abbreviation\nof one of these.\nIf \\fIwhat\\fR is \\fBpages\\fR then the view adjusts by \\fInumber\\fR\nscreenfuls. If \\fInumber\\fR is negative then characters farther to the left\nbecome visible;  if it is positive then characters farther to the right\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts left or right by\n\\fInumber\\fR average-width characters on the display.\n.RE\n.SH \"DEFAULT BINDINGS\"\n.PP\nTk automatically creates class bindings for spinboxes that give them\nthe following default behavior.\nIn the descriptions below,\n.QW word\nrefers to a contiguous group of letters, digits, or\n.QW _\ncharacters, or any single character other than these.\n.IP [1]\nClicking mouse button 1 positions the insertion cursor\njust before the character underneath the mouse cursor, sets the\ninput focus to this widget, and clears any selection in the widget.\nDragging with mouse button 1 strokes out a selection between\nthe insertion cursor and the character under the mouse.\n.IP [2]\nDouble-clicking with mouse button 1 selects the word under the mouse\nand positions the insertion cursor at the beginning of the word.\nDragging after a double click will stroke out a selection consisting\nof whole words.\n.IP [3]\nTriple-clicking with mouse button 1 selects all of the text in the\nspinbox and positions the insertion cursor before the first character.\n.IP [4]\nThe ends of the selection can be adjusted by dragging with mouse\nbutton 1 while the Shift key is down;  this will adjust the end\nof the selection that was nearest to the mouse cursor when button\n1 was pressed.\nIf the button is double-clicked before dragging then the selection\nwill be adjusted in units of whole words.\n.IP [5]\nClicking mouse button 1 with the Control key down will position the\ninsertion cursor in the spinbox without affecting the selection.\n.IP [6]\nIf any normal printing characters are typed in a spinbox, they are\ninserted at the point of the insertion cursor.\n.IP [7]\nThe view in the spinbox can be adjusted by dragging with the middle\nmouse button (button 2, or button 3 in TkAqua). If the middle mouse\nbutton is clicked without moving the mouse, the selection is copied\ninto the spinbox at the position of the mouse cursor.\n.IP [8]\nIf the mouse is dragged out of the spinbox on the left or right sides\nwhile button 1 is pressed, the spinbox will automatically scroll to\nmake more text visible (if there is more text off-screen on the side\nwhere the mouse left the window).\n.IP [9]\nThe Left and Right keys move the insertion cursor one character to the\nleft or right;  they also clear any selection in the spinbox and set\nthe selection anchor.\nIf Left or Right is typed with the Shift key down, then the insertion\ncursor moves and the selection is extended to include the new character.\nControl-Left and Control-Right move the insertion cursor by words, and\nControl-Shift-Left and Control-Shift-Right move the insertion cursor\nby words and also extend the selection.\nControl-b and Control-f behave the same as Left and Right, respectively.\nMeta-b and Meta-f behave the same as Control-Left and Control-Right,\nrespectively.\n.IP [10]\nThe Home key, or Control-a, will move the insertion cursor to the\nbeginning of the spinbox and clear any selection in the spinbox.\nShift-Home moves the insertion cursor to the beginning of the spinbox\nand also extends the selection to that point.\n.IP [11]\nThe End key, or Control-e, will move the insertion cursor to the\nend of the spinbox and clear any selection in the spinbox.\nShift-End moves the cursor to the end and extends the selection\nto that point.\n.IP [12]\nThe Select key and Control-Space set the selection anchor to the position\nof the insertion cursor.  They do not affect the current selection.\nShift-Select and Control-Shift-Space adjust the selection to the\ncurrent position of the insertion cursor, selecting from the anchor\nto the insertion cursor if there was not any selection previously.\n.IP [13]\nControl-/ selects all the text in the spinbox.\n.IP [14]\nControl-\\e clears any selection in the spinbox.\n.IP [15]\nThe F16 key (labelled Copy on many Sun workstations) or Meta-w\ncopies the selection in the widget to the clipboard, if there is a selection.\n.IP [16]\nThe F20 key (labelled Cut on many Sun workstations) or Control-w\ncopies the selection in the widget to the clipboard and deletes\nthe selection.\nIf there is no selection in the widget then these keys have no effect.\n.IP [17]\nThe F18 key (labelled Paste on many Sun workstations) or Control-y\ninserts the contents of the clipboard at the position of the\ninsertion cursor.\n.IP [18]\nThe Delete key deletes the selection, if there is one in the spinbox.\nIf there is no selection, it deletes the character to the right of\nthe insertion cursor.\n.IP [19]\nThe BackSpace key and Control-h delete the selection, if there is one\nin the spinbox.\nIf there is no selection, it deletes the character to the left of\nthe insertion cursor.\n.IP [20]\nControl-d deletes the character to the right of the insertion cursor.\n.IP [21]\nMeta-d deletes the word to the right of the insertion cursor.\n.IP [22]\nControl-k deletes all the characters to the right of the insertion\ncursor.\n.IP [23]\nControl-t reverses the order of the two characters to the right of\nthe insertion cursor.\n.PP\nIf the spinbox is disabled using the \\fB\\-state\\fR option, then the spinbox's\nview can still be adjusted and text in the spinbox can still be selected,\nbut no insertion cursor will be displayed and no text modifications will\ntake place.\n.PP\nThe behavior of spinboxes can be changed by defining new bindings for\nindividual widgets or by redefining the class bindings.\n.SH \"SEE ALSO\"\nttk::spinbox(n)\n.SH KEYWORDS\nspinbox, entry, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/sysnotify.n",
    "content": ".\\\" Text automatically generated by txt2man\n'\\\"\n'\\\" Copyright (c) 2020 Kevin Walzer\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk sysnotify n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n.SH NAME\nsysnotify \\- Creates a notification window with a title and message.\n.SH SYNOPSIS\n\\fBtk sysnotify\\fI title message\\fR\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk sysnotify\\fR command creates a platform-specific system notification\nalert. Its intent is to provide a brief, unobtrusive notification to the user\nby popping up a window that briefly appears in a corner of the screen.\n.SH EXAMPLE\n.PP\nHere is an example of the \\fBtk sysnotify\\fR code:\n.PP\n.CS\ntk sysnotify \"Alert\" \\e\n      \"This is just a test of the Tk System Notification Code.\"\n.CE\n.SH PLATFORM NOTES\n.PP\nThe macOS and Windows versions are native implementations using system\nAPI's. The X11 version has a conditional dependency on libnotify, and\nfalls back to a Tcl-only implementation if libnotify is not installed. On\nmacOS and Linux, the notification includes a platform-specific default image to\naccompany the text. On Windows, the notification displays the same image as the one\nin the system tray; Windows images will display best if they are 32x32 pixels.\n.TP\n\\fBmacOS\\fR\n.\nThe macOS version will request permission from the user to authorize\nnotifications. This must be activated in Apple's System Preferences\nNotifications section.\n.RS\n.PP\nIf deploying an application using the standalone version of Wish.app,\nsetting the bundle ID in the applications Info.plist file to begin with\n.QW \\fBcom\\fR\nseems necessary for notifications to work. Using a different prefix\nfor the bundle ID, such as something like\n.QW \\fBtk.tcl.tkchat\\fR ,\nwill cause notifications to silently fail.\n.RE\n.TP\n\\fBWindows\\fR\n.\nThe image is taken from the system tray, i.e., \\fBsysnotify\\fR can only be\ncalled when a \\fBsystray\\fR was installed.\n.\n.SH KEYWORDS\nnotify, alert\n"
  },
  {
    "path": "doc/systray.n",
    "content": ".\\\" Text automatically generated by txt2man\n'\\\"\n'\\\" Copyright (c) 2020 Kevin Walzer\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk systray n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n.SH NAME\nsystray \\- Creates an icon display in the platform-specific system tray.\n.SH SYNOPSIS\n.nf\n\\fBtk systray create \\-image \\fIimage\\fR ?\\fB\\-text \\fItext\\fR? ?\\fB\\-button1 \\fIcallback\\fR? ?\\fB\\-button3 \\fIcallback\\fR?\n\\fBtk systray configure \\fI?option? ?value option value ...?\\fR\n\\fBtk systray exists\\fR\n\\fBtk systray destroy\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\n.\\\" METHOD: create\nThe \\fBtk systray create\\fR command creates an icon in the platform-specific\ntray. The widget is configured with a Tk image for the icon display, an\noptional string for display in a tooltip, and optional callbacks that are\nbound to <Button-1> and <Button-3>.\n.PP\n.\\\" METHOD: configure\nThe \\fBtk systray configure\\fR command sets one or more options of the systray\nicon. Configurable options are the same as for the \\fBcreate\\fR subcommand. When\na single option name is given, the command returns the current value of this\noption. When no option is given this command returns the list of all options and\ntheir current value.\n.PP\n.\\\" METHOD: exists\nThe \\fBtk systray exists\\fR command checks whether a systray icon was created.\nIt returns a boolean.\n.PP\n.\\\" METHOD: destroy\nThe \\fBtk systray destroy\\fR command removes the icon from display and\ndeallocates it.\n.PP\nFrom a user-interface standpoint, only one icon per interpreter is\nsupported; attempts to create additional icons will return an error. The\nexisting tray icon can be modified with different images and\nstrings to indicate app state. Loading additional interpreters into a\nrunning instance of Wish will allow additional icons to be displayed.\n.SH EXAMPLE\n.PP\nHere is an example of the \\fBtk systray\\fR code:\n.CS\nimage create photo book -data \\e\n        R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\ntk systray create -image book -text \"tk systray sample\" \\e\n        -button1 {puts \"Here is the tk systray output\"} \\e\n        -button3 {puts \"here is alternate output\"}\n.CE\n.PP\nHere is an example of modifying the \\fBtk systray\\fR icon:\n.CS\nimage create photo book_page -data \\e\n        R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7\ntk systray configure -image book_page -text \"Updated sample\" \\e\n        -button1 {puts \"Different output from the tk systray\"} \\e\n        -button3 {puts \"and more different output from the tk systray\"}\n.CE\n.SH PLATFORM NOTES\n.PP\nThe X11 implementation is supported on a \"best efforts\" basis because it is\ndependent on the window manager. The \"text\" flag, which is implemented as\na tooltip, does not always display if the WM does not support such features;\nthe systray icon itself may not even display with some window managers.\n.PP\nOn Windows, the Tk image provided in the \\fB\\-image\\fR option must be a\nphoto image. On other platforms either a bitmap image or a photo image\nmay be provided.\n.SH KEYWORDS\nimage, callback\n"
  },
  {
    "path": "doc/text.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH text n 8.5 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note: do not modify the .SH NAME line immediately below!\n.SH NAME\ntext, tk_textCopy, tk_textCut, tk_textPaste \\- Create and manipulate 'text' hypertext editing widgets\n.SH SYNOPSIS\n.nf\n\\fBtext\\fI pathName \\fR?\\fIoptions\\fR?\n\\fBtk_textCopy\\fI pathName\\fR\n\\fBtk_textCut\\fI pathName\\fR\n\\fBtk_textPaste\\fI pathName\\fR\n.fi\n.SO\n\\-background\t\\-highlightthickness\t\\-relief\n\\-borderwidth\t\\-insertbackground\t\\-selectbackground\n\\-cursor\t\\-insertborderwidth\t\\-selectborderwidth\n\\-exportselection\t\\-insertofftime\t\\-selectforeground\n\\-font\t\\-insertontime\t\\-setgrid\n\\-foreground\t\\-insertwidth\t\\-takefocus\n\\-highlightbackground\t\\-padx\t\\-xscrollcommand\n\\-highlightcolor\t\\-pady\t\\-yscrollcommand\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-autoseparators autoSeparators AutoSeparators\nSpecifies a boolean that says whether separators are automatically inserted in\nthe undo stack. Only meaningful when the \\fB\\-undo\\fR option is true.\n.OP \\-blockcursor blockCursor BlockCursor\nSpecifies a boolean that says whether the blinking insertion cursor should be\ndrawn as a character-sized rectangular block. If false (the default) a thin\nvertical line is used for the insertion cursor.\n.OP \\-endline endLine EndLine\nSpecifies an integer line index representing the line of the underlying\ntextual data store that should be just after the last line contained in\nthe widget. This allows a text widget to reflect only a portion of a\nlarger piece of text. Instead of an integer, the empty string can be\nprovided to this configuration option, which will configure the widget\nto end at the very last line in the textual data store.\n.OP \\-height height Height\nSpecifies the desired height for the window, in units of characters in the\nfont given by the \\fB\\-font\\fR option. Must be at least one.\n.OP \\-inactiveselectbackground inactiveSelectBackground Foreground\nSpecifies the colour to use for the selection (the \\fBsel\\fR tag) when the\nwindow does not have the input focus. If empty, \\fB{}\\fR, then no selection is\nshown when the window does not have the focus.\n.OP \\-insertunfocussed insertUnfocussed InsertUnfocussed\n.VS 8.6\nSpecifies how to display the insertion cursor when the widget does not have\nthe focus. Must be \\fBnone\\fR (the default) which means to not display the\ncursor, \\fBhollow\\fR which means to display a hollow box, or \\fBsolid\\fR which\nmeans to display a solid box. Note that \\fBhollow\\fR and \\fBsolid\\fR will\nappear very similar when the \\fB\\-blockcursor\\fR option is false.\n.VE 8.6\n.OP \\-maxundo maxUndo MaxUndo\nSpecifies the maximum number of compound undo actions on the undo stack. A\nzero or a negative value imply an unlimited undo stack.\n.OP \\-spacing1 spacing1 Spacing1\nRequests additional space above each text line in the widget, using any of the\nstandard forms for screen distances. If a line wraps, this option only applies\nto the first line on the display. This option may be overridden with\n\\fB\\-spacing1\\fR options in tags.\n.OP \\-spacing2 spacing2 Spacing2\nFor lines that wrap (so that they cover more than one line on the display)\nthis option specifies additional space to provide between the display lines\nthat represent a single line of text. The value may have any of the standard\nforms for screen distances. This option may be overridden with\n\\fB\\-spacing2\\fR options in tags.\n.OP \\-spacing3 spacing3 Spacing3\nRequests additional space below each text line in the widget, using any of the\nstandard forms for screen distances. If a line wraps, this option only applies\nto the last line on the display. This option may be overridden with\n\\fB\\-spacing3\\fR options in tags.\n.OP \\-startline startLine StartLine\nSpecifies an integer line index representing the first line of the underlying\ntextual data store that should be contained in the widget. This allows a text\nwidget to reflect only a portion of a larger piece of text. Instead of an\ninteger, the empty string can be provided to this configuration option, which\nwill configure the widget to start at the very first line in the textual data\nstore.\n.OP \\-state state State\nSpecifies one of two states for the text: \\fBnormal\\fR or \\fBdisabled\\fR. If\nthe text is disabled then characters may not be inserted or deleted and no\ninsertion cursor will be displayed, even if the input focus is in the widget.\n.OP \\-tabs tabs Tabs\nSpecifies a set of tab stops for the window. The option's value consists of a\nlist of screen distances giving the positions of the tab stops, each of which\nis a distance relative to the left edge of the widget (excluding borders,\npadding, etc). Each position may optionally be followed in the next list\nelement by one of the keywords \\fBleft\\fR, \\fBright\\fR, \\fBcenter\\fR, or\n\\fBnumeric\\fR, which specifies how to justify text relative to the tab stop.\n\\fBLeft\\fR is the default; it causes the text following the tab character to\nbe positioned with its left edge at the tab position. \\fBRight\\fR means that\nthe right edge of the text following the tab character is positioned at the\ntab position, and \\fBcenter\\fR means that the text is centered at the tab\nposition. \\fBNumeric\\fR means that the decimal point in the text is positioned\nat the tab position; if there is no decimal point then the least significant\ndigit of the number is positioned just to the left of the tab position; if\nthere is no number in the text then the text is right-justified at the tab\nposition. For example,\n.QW \"\\fB\\-tabs {2c left 4c 6c center}\\fR\"\ncreates three tab stops at two-centimeter intervals; the first two use left\njustification and the third uses center justification.\n.RS\n.PP\nIf the list of tab stops does not have enough elements to cover all of the\ntabs in a text line, then Tk extrapolates new tab stops using the spacing and\nalignment from the last tab stop in the list. Tab distances must be strictly\npositive, and must always increase from one tab stop to the next (if not, an\nerror is thrown). The value of the \\fB\\-tabs\\fR option may be overridden by\n\\fB\\-tabs\\fR options in tags.\n.PP\nIf no \\fB\\-tabs\\fR option is specified, or if it is specified as an empty\nlist, then Tk uses default tabs spaced every eight (average size) characters.\nTo achieve a different standard spacing, for example every 4 characters,\nsimply configure the widget with\n.QW \"\\fB\\-tabs \\N'34'[expr {4 * [font measure $font 0]}] left\\N'34' \\-tabstyle wordprocessor\\fR\" .\n.RE\n.OP \\-tabstyle tabStyle TabStyle\nSpecifies how to interpret the relationship between tab stops on a line and\ntabs in the text of that line. The value must be \\fBtabular\\fR (the default)\nor \\fBwordprocessor\\fR. Note that tabs are interpreted as they are encountered\nin the text. If the tab style is \\fBtabular\\fR then the \\fIn\\fR'th tab\ncharacter in the line's text will be associated with the \\fIn\\fR'th tab stop\ndefined for that line. If the tab character's x coordinate falls to the right\nof the \\fIn\\fR'th tab stop, then a gap of a single space will be inserted as a\nfallback. If the tab style is \\fBwordprocessor\\fR then any tab character being\nlaid out will use (and be defined by) the first tab stop to the right of the\npreceding characters already laid out on that line. The value of the\n\\fB\\-tabstyle\\fR option may be overridden by \\fB\\-tabstyle\\fR options in tags.\n.OP \\-undo undo Undo\nSpecifies a boolean that says whether the undo mechanism is active or not.\n.OP \\-width width Width\nSpecifies the desired width for the window in units of characters in the font\ngiven by the \\fB\\-font\\fR option. If the font does not have a uniform width\nthen the width of the character\n.QW 0\nis used in translating from character units to screen units.\n.OP \\-wrap wrap Wrap\nSpecifies how to handle lines in the text that are too long to be displayed in\na single line of the text's window. The value must be \\fBnone\\fR or \\fBchar\\fR\nor \\fBword\\fR. A wrap mode of \\fBnone\\fR means that each line of text appears\nas exactly one line on the screen; extra characters that do not fit on the\nscreen are not displayed. In the other modes each line of text will be broken\nup into several screen lines if necessary to keep all the characters visible.\nIn \\fBchar\\fR mode a screen line break may occur after any character; in\n\\fBword\\fR mode a line break will only be made at word boundaries.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtext\\fR command creates a new window (given by the \\fIpathName\\fR\nargument) and makes it into a text widget. Additional options, described\nabove, may be specified on the command line or in the option database to\nconfigure aspects of the text such as its default background color and relief.\nThe \\fBtext\\fR command returns the path name of the new window.\n.PP\nA text widget displays one or more lines of text and allows that text to be\nedited. Text widgets support four different kinds of annotations on the text,\ncalled tags, marks, embedded windows or embedded images. Tags allow different\nportions of the text to be displayed with different fonts and colors. In\naddition, Tcl commands can be associated with tags so that scripts are invoked\nwhen particular actions such as keystrokes and mouse button presses occur in\nparticular ranges of the text. See \\fBTAGS\\fR below for more details.\n.PP\nThe second form of annotation consists of floating markers in the text called\n.QW marks .\nMarks are used to keep track of various interesting positions in the text as\nit is edited. See \\fBMARKS\\fR below for more details.\n.PP\nThe third form of annotation allows arbitrary windows to be embedded in a text\nwidget. See \\fBEMBEDDED WINDOWS\\fR below for more details.\n.PP\nThe fourth form of annotation allows Tk images to be embedded in a text\nwidget. See \\fBEMBEDDED IMAGES\\fR below for more details.\n.PP\nThe text widget also has a built-in undo/redo mechanism. See\n\\fBTHE UNDO MECHANISM\\fR below for more details.\n.PP\nThe text widget allows for the creation of peer widgets. These are other text\nwidgets which share the same underlying data (text, marks, tags, images, etc).\nSee \\fBPEER WIDGETS\\fR below for more details.\n.SH INDICES\n.PP\nMany of the widget commands for texts take one or more indices as arguments.\nAn index is a string used to indicate a particular place within a text, such\nas a place to insert characters or one endpoint of a range of characters to\ndelete. Indices have the syntax\n.CS\n\\fIbase modifier modifier modifier ...\\fR\n.CE\nWhere \\fIbase\\fR gives a starting point and the \\fImodifier\\fRs adjust the\nindex from the starting point (e.g. move forward or backward one character).\nEvery index must contain a \\fIbase\\fR, but the \\fImodifier\\fRs are optional.\nMost modifiers (as documented below) allow an optional submodifier. Valid\nsubmodifiers are \\fBany\\fR and \\fBdisplay\\fR. If the submodifier is\nabbreviated, then it must be followed by whitespace, but otherwise there need\nbe no space between the submodifier and the following \\fImodifier\\fR.\nTypically the \\fBdisplay\\fR submodifier adjusts the meaning of the following\n\\fImodifier\\fR to make it refer to visual or non-elided units rather than\nlogical units, but this is explained for each relevant case below. Lastly,\nwhere \\fIcount\\fR is used as part of a modifier, it can be positive or\nnegative, so\n.QW \"\\fIbase\\fR \\- \\-3 lines\"\nis perfectly valid (and equivalent to\n.QW \"\\fIbase\\fR +3lines\" ).\n.PP\nThe \\fIbase\\fR for an index must have one of the following forms:\n.TP 12\n\\fIline\\fB.\\fIchar\\fR\n.\nIndicates \\fIchar\\fR'th character on line \\fIline\\fR. Lines are numbered from\n1 for consistency with other UNIX programs that use this numbering scheme.\nWithin a line, characters are numbered from 0. If \\fIchar\\fR is \\fBend\\fR then\nit refers to the newline character that ends the line.\n.TP 12\n\\fB@\\fIx\\fB,\\fIy\\fR\n.\nIndicates the character that covers the pixel whose x and y coordinates within\nthe text's window are \\fIx\\fR and \\fIy\\fR.\n.TP 12\n\\fBend\\fR\n.\nIndicates the end of the text (the character just after the last newline).\n.TP 12\n\\fImark\\fR\n.\nIndicates the character just after the mark whose name is \\fImark\\fR (see\n\\fBMARKS\\fR for details).\n.TP 12\n\\fItag\\fB.first\\fR\n.\nIndicates the first character in the text that has been tagged with \\fItag\\fR.\nThis form generates an error if no characters are currently tagged with\n\\fItag\\fR.\n.TP 12\n\\fItag\\fB.last\\fR\n.\nIndicates the character just after the last one in the text that has been\ntagged with \\fItag\\fR. This form generates an error if no characters are\ncurrently tagged with \\fItag\\fR.\n.TP 12\n\\fIpathName\\fR\n.\nIndicates the position of the embedded window whose name is \\fIpathName\\fR.\nThis form generates an error if there is no embedded window by the given name.\n.TP 12\n\\fIimageName\\fR\n.\nIndicates the position of the embedded image whose name is \\fIimageName\\fR.\nThis form generates an error if there is no embedded image by the given name.\n.PP\nIf the \\fIbase\\fR could match more than one of the above forms, such as a\n\\fImark\\fR and \\fIimageName\\fR both having the same value, then the form\nearlier in the above list takes precedence. If modifiers follow the base\nindex, each one of them must have one of the forms listed below. Keywords such\nas \\fBchars\\fR and \\fBwordend\\fR may be abbreviated as long as the\nabbreviation is unambiguous.\n.TP\n\\fB+ \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBchars\\fR\n.\nAdjust the index forward by \\fIcount\\fR characters, moving to later lines in\nthe text if necessary. If there are fewer than \\fIcount\\fR characters in the\ntext after the current index, then set the index to the last index in the\ntext. Spaces on either side of \\fIcount\\fR are optional. If the \\fBdisplay\\fR\nsubmodifier is given, elided characters are skipped over without being\ncounted. If \\fBany\\fR is given, then all characters are counted. For\nhistorical reasons, if neither modifier is given then the count actually takes\nplace in units of index positions (see \\fBINDICES\\fR for details). This\nbehaviour may be changed in a future major release, so if you need an index\ncount, you are encouraged to use \\fBindices\\fR instead wherever possible.\n.TP\n\\fB\\- \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBchars\\fR\n.\nAdjust the index backward by \\fIcount\\fR characters, moving to earlier lines\nin the text if necessary. If there are fewer than \\fIcount\\fR characters in\nthe text before the current index, then set the index to the first index in\nthe text (1.0). Spaces on either side of \\fIcount\\fR are optional. If the\n\\fBdisplay\\fR submodifier is given, elided characters are skipped over without\nbeing counted. If \\fBany\\fR is given, then all characters are counted. For\nhistorical reasons, if neither modifier is given then the count actually takes\nplace in units of index positions (see \\fBINDICES\\fR for details). This\nbehavior may be changed in a future major release, so if you need an index\ncount, you are encouraged to use \\fBindices\\fR instead wherever possible.\n.TP\n\\fB+ \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBindices\\fR\n.\nAdjust the index forward by \\fIcount\\fR index positions, moving to later lines\nin the text if necessary. If there are fewer than \\fIcount\\fR index positions\nin the text after the current index, then set the index to the last index\nposition in the text. Spaces on either side of \\fIcount\\fR are optional. Note\nthat an index position is either a single character or a single embedded image\nor embedded window. If the \\fBdisplay\\fR submodifier is given, elided indices\nare skipped over without being counted. If \\fBany\\fR is given, then all\nindices are counted; this is also the default behaviour if no modifier is\ngiven.\n.TP\n\\fB\\- \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBindices\\fR\n.\nAdjust the index backward by \\fIcount\\fR index positions, moving to earlier\nlines in the text if necessary. If there are fewer than \\fIcount\\fR index\npositions in the text before the current index, then set the index to the\nfirst index position (1.0) in the text. Spaces on either side of \\fIcount\\fR\nare optional. If the \\fBdisplay\\fR submodifier is given, elided indices are\nskipped over without being counted. If \\fBany\\fR is given, then all indices\nare counted; this is also the default behaviour if no modifier is given.\n.TP\n\\fB+ \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBlines\\fR\n.\nAdjust the index forward by \\fIcount\\fR lines, retaining the same character\nposition within the line. If there are fewer than \\fIcount\\fR lines after the\nline containing the current index, then set the index to refer to the same\ncharacter position on the last line of the text. Then, if the line is not long\nenough to contain a character at the indicated character position, adjust the\ncharacter position to refer to the last character of the line (the newline).\nSpaces on either side of \\fIcount\\fR are optional. If the \\fBdisplay\\fR\nsubmodifier is given, then each visual display line is counted separately.\nOtherwise, if \\fBany\\fR (or no modifier) is given, then each logical line (no\nmatter how many times it is visually wrapped) counts just once. If the\nrelevant lines are not wrapped, then these two methods of counting are\nequivalent.\n.TP\n\\fB\\- \\fIcount\\fR ?\\fIsubmodifier\\fR? \\fBlines\\fR\n.\nAdjust the index backward by \\fIcount\\fR logical lines, retaining the same\ncharacter position within the line. If there are fewer than \\fIcount\\fR lines\nbefore the line containing the current index, then set the index to refer to\nthe same character position on the first line of the text. Then, if the line\nis not long enough to contain a character at the indicated character position,\nadjust the character position to refer to the last character of the line (the\nnewline). Spaces on either side of \\fIcount\\fR are optional. If the\n\\fBdisplay\\fR submodifier is given, then each visual display line is counted\nseparately. Otherwise, if \\fBany\\fR (or no modifier) is given, then each\nlogical line (no matter how many times it is visually wrapped) counts just\nonce. If the relevant lines are not wrapped, then these two methods of\ncounting are equivalent.\n.TP\n?\\fIsubmodifier\\fR? \\fBlinestart\\fR\n.\nAdjust the index to refer to the first index on the line. If the \\fBdisplay\\fR\nsubmodifier is given, this is the first index on the display line, otherwise\non the logical line.\n.TP\n?\\fIsubmodifier\\fR? \\fBlineend\\fR\n.\nAdjust the index to refer to the last index on the line (the newline). If the\n\\fBdisplay\\fR submodifier is given, this is the last index on the display\nline, otherwise on the logical line.\n.TP\n?\\fIsubmodifier\\fR? \\fBwordstart\\fR\n.\nAdjust the index to refer to the first character of the word containing the\ncurrent index. A word consists of any number of adjacent characters that are\nletters, digits, or underscores, or a single character that is not one of\nthese. If the \\fBdisplay\\fR submodifier is given, this only examines\nnon-elided characters, otherwise all characters (elided or not) are examined.\n.TP\n?\\fIsubmodifier\\fR? \\fBwordend\\fR\n.\nAdjust the index to refer to the character just after the last one of the word\ncontaining the current index. If the current index refers to the last\ncharacter of the text then it is not modified. If the \\fBdisplay\\fR\nsubmodifier is given, this only examines non-elided characters, otherwise all\ncharacters (elided or not) are examined.\n.PP\nIf more than one modifier is present then they are applied in left-to-right\norder. For example, the index\n.QW \"\\fBend \\- 1 chars\\fR\"\nrefers to the next-to-last character in the text and\n.QW \"\\fBinsert wordstart \\- 1 c\\fR\"\nrefers to the character just before the first one in the word containing the\ninsertion cursor. Modifiers are applied one by one in this left to right\norder, and after each step the resulting index is constrained to be a valid\nindex in the text widget. So, for example, the index\n.QW \"\\fB1.0 \\-1c +1c\\fR\"\nrefers to the index\n.QW \\fB2.0\\fR .\n.PP\nWhere modifiers result in index changes by display lines, display chars or\ndisplay indices, and the \\fIbase\\fR refers to an index inside an elided tag,\nthat base index is considered to be equivalent to the first following\nnon-elided index.\n.SH TAGS\n.PP\nThe first form of annotation in text widgets is a tag. A tag is a textual\nstring that is associated with some of the characters in a text. Tags may\ncontain arbitrary characters, but it is probably best to avoid using the\ncharacters\n.QW \" \"\n(space), \\fB+\\fR, or \\fB\\-\\fR: these characters have special meaning in\nindices, so tags containing them cannot be used as indices. There may be any\nnumber of tags associated with characters in a text. Each tag may refer to a\nsingle character, a range of characters, or several ranges of characters. An\nindividual character may have any number of tags associated with it.\n.PP\nA priority order is defined among tags, and this order is used in implementing\nsome of the tag-related functions described below. When a tag is defined (by\nassociating it with characters or setting its display options or binding\ncommands to it), it is given a priority higher than any existing tag. The\npriority order of tags may be redefined using the\n.QW \"\\fIpathName \\fBtag raise\\fR\"\nand\n.QW \"\\fIpathName \\fBtag lower\\fR\"\nwidget commands.\n.PP\nTags serve three purposes in text widgets. First, they control the way\ninformation is displayed on the screen. By default, characters are displayed\nas determined by the \\fB\\-background\\fR, \\fB\\-font\\fR, and \\fB\\-foreground\\fR\noptions for the text widget. However, display options may be associated with\nindividual tags using the\n.QW \"\\fIpathName \\fBtag configure\\fR\"\nwidget command. If a character has been tagged, then the display options\nassociated with the tag override the default display style. The following\noptions are currently supported for tags:\n.\\\" OPTION: -background\n.TP\n\\fB\\-background \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the background color to use for characters associated\nwith the tag. It may have any of the forms accepted by \\fBTk_GetColor\\fR.\n.\\\" OPTION: -bgstipple\n.TP\n\\fB\\-bgstipple \\fIbitmap\\fR\n.\n\\fIBitmap\\fR specifies a bitmap that is used as a stipple pattern for the\nbackground. It may have any of the forms accepted by \\fBTk_GetBitmap\\fR. If\n\\fIbitmap\\fR has not been specified, or if it is specified as an empty string,\nthen a solid fill will be used for the background.\n.\\\" OPTION: -borderwidth\n.TP\n\\fB\\-borderwidth \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies the width of a border to draw around the tag using any\nof the forms accepted by \\fBTk_GetPixels\\fR. This option should be used in\nconjunction with the \\fB\\-relief\\fR option to provide the desired border.\n.\\\" OPTION: -elide\n.TP\n\\fB\\-elide \\fIboolean\\fR\n.\n\\fIElide\\fR specifies whether the data should be elided. Elided data\n(characters, images, embedded windows, etc.) is not displayed and takes no\nspace on screen, but further on behaves just as normal data.\n.\\\" OPTION: -fgstipple\n.TP\n\\fB\\-fgstipple \\fIbitmap\\fR\n.\n\\fIBitmap\\fR specifies a bitmap that is used as a stipple pattern when drawing\ntext and other foreground information such as underlines. It may have any of\nthe forms accepted by \\fBTk_GetBitmap\\fR. If \\fIbitmap\\fR has not been\nspecified, or if it is specified as an empty string, then a solid fill will be\nused.\n.\\\" OPTION: -font\n.TP\n\\fB\\-font \\fIfontName\\fR\n.\n\\fIFontName\\fR is the name of a font to use for drawing characters. It may\nhave any of the forms accepted by \\fBTk_GetFont\\fR.\n.\\\" OPTION: -foreground\n.TP\n\\fB\\-foreground \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the color to use when drawing text and other foreground\ninformation such as underlines. It may have any of the forms accepted by\n\\fBTk_GetColor\\fR.\n.\\\" OPTION: -justify\n.TP\n\\fB\\-justify \\fIjustify\\fR\n.\nIf the first non-elided character of a display line has a tag for which this\noption has been specified, then \\fIjustify\\fR determines how to justify the\nline. It must be one of \\fBleft\\fR, \\fBright\\fR, or \\fBcenter\\fR. If a line\nwraps, then the justification for each line on the display is determined by\nthe first non-elided character of that display line.\n.\\\" OPTION: -lmargin1\n.TP\n\\fB\\-lmargin1 \\fIpixels\\fR\n.\nIf the first non-elided character of a text line has a tag for which this\noption has been specified, then \\fIpixels\\fR specifies how much the line\nshould be indented from the left edge of the window. \\fIPixels\\fR may have any\nof the standard forms for screen distances. If a line of text wraps, this\noption only applies to the first line on the display; the \\fB\\-lmargin2\\fR\noption controls the indentation for subsequent lines.\n.\\\" OPTION: -lmargin2\n.TP\n\\fB\\-lmargin2 \\fIpixels\\fR\n.\nIf the first non-elided character of a display line has a tag for which this\noption has been specified, and if the display line is not the first for its\ntext line (i.e., the text line has wrapped), then \\fIpixels\\fR specifies how\nmuch the line should be indented from the left edge of the window.\n\\fIPixels\\fR may have any of the standard forms for screen distances. This\noption is only used when wrapping is enabled, and it only applies to the\nsecond and later display lines for a text line.\n.\\\" OPTION: -lmargincolor\n.TP\n\\fB\\-lmargincolor \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the background color to use in regions that do not\ncontain characters because they are indented by \\fB\\-lmargin1\\fR or\n\\fB\\-lmargin2\\fR. It may have any of the forms accepted by\n\\fBTk_GetColor\\fR. If \\fIcolor\\fR has not been specified, or if it is\nspecified as an empty string, then the color used is specified by the\n\\fB\\-background\\fR tag option (or, if this is also unspecified, by the\n\\fB\\-background\\fR widget option).\n.\\\" OPTION: -offset\n.TP\n\\fB\\-offset \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies an amount by which the text's baseline should be offset\nvertically from the baseline of the overall line, in pixels. For example, a\npositive offset can be used for superscripts and a negative offset can be used\nfor subscripts. \\fIPixels\\fR may have any of the standard forms for screen\ndistances.\n.\\\" OPTION: -overstrike\n.TP\n\\fB\\-overstrike \\fIboolean\\fR\n.\nSpecifies whether or not to draw a horizontal rule through the middle of\ncharacters. \\fIBoolean\\fR may have any of the forms accepted by\n\\fBTcl_GetBoolean\\fR.\n.\\\" OPTION: -overstrikefg\n.TP\n\\fB\\-overstrikefg \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the color to use when displaying the overstrike. It may\nhave any of the forms accepted by \\fBTk_GetColor\\fR. If \\fIcolor\\fR has not\nbeen specified, or if it is specified as an empty string, then the color\nspecified by the \\fB\\-foreground\\fR tag option is used.\n.\\\" OPTION: -relief\n.TP\n\\fB\\-relief \\fIrelief\\fR\n.\n\\fIRelief\\fR specifies the relief style to use for drawing the border, in any\nof the forms accepted by \\fBTk_GetRelief\\fR. This option is used in\nconjunction with the \\fB\\-borderwidth\\fR option to enable to the desired\nborder appearance.\n.\\\" OPTION: -rmargin\n.TP\n\\fB\\-rmargin \\fIpixels\\fR\n.\nIf the first non-elided character of a display line has a tag for which this\noption has been specified, then \\fIpixels\\fR specifies how wide a margin to\nleave between the end of the line and the right edge of the window.\n\\fIPixels\\fR may have any of the standard forms for screen distances. This\noption is only used when wrapping is enabled. If a text line wraps, the right\nmargin for each line on the display is determined by the first non-elided\ncharacter of that display line.\n.\\\" OPTION: -rmargincolor\n.TP\n\\fB\\-rmargincolor \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the background color to use in regions that do not\ncontain characters because they are indented by \\fB\\-rmargin\\fR. It may\nhave any of the forms accepted by \\fBTk_GetColor\\fR. If \\fIcolor\\fR has not\nbeen specified, or if it is specified as an empty string, then the color\nused is specified by the \\fB\\-background\\fR tag option (or, if this is also\nunspecified, by the \\fB\\-background\\fR widget option).\n.\\\" OPTION: -selectbackground\n.TP\n\\fB\\-selectbackground \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the background color to use when displaying selected\nitems. It may have any of the forms accepted by \\fBTk_GetColor\\fR. If\n\\fIcolor\\fR has not been specified, or if it is specified as an empty\nstring, then the color specified by the \\fB\\-background\\fR tag option is\nused.\n.\\\" OPTION: -selectforeground\n.TP\n\\fB\\-selectforeground \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the foreground color to use when displaying selected\nitems. It may have any of the forms accepted by \\fBTk_GetColor\\fR. If\n\\fIcolor\\fR has not been specified, or if it is specified as an empty\nstring, then the color specified by the \\fB\\-foreground\\fR tag option is\nused.\n.\\\" OPTION: -spacing1\n.TP\n\\fB\\-spacing1 \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies how much additional space should be left above each\ntext line, using any of the standard forms for screen distances. If a line\nwraps, this option only applies to the first line on the display.\n.\\\" OPTION: -spacing2\n.TP\n\\fB\\-spacing2 \\fIpixels\\fR\n.\nFor lines that wrap, this option specifies how much additional space to leave\nbetween the display lines for a single text line. \\fIPixels\\fR may have any of\nthe standard forms for screen distances.\n.\\\" OPTION: -spacing3\n.TP\n\\fB\\-spacing3 \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies how much additional space should be left below each\ntext line, using any of the standard forms for screen distances. If a line\nwraps, this option only applies to the last line on the display.\n.\\\" OPTION: -tabs\n.TP\n\\fB\\-tabs \\fItabList\\fR\n.\n\\fITabList\\fR specifies a set of tab stops in the same form as for the\n\\fB\\-tabs\\fR option for the text widget. This option only applies to a display\nline if it applies to the first non-elided character on that display line. If\nthis option is specified as an empty string, it cancels the option, leaving it\nunspecified for the tag (the default). If the option is specified as a\nnon-empty string that is an empty list, such as \\fB\\-tags\\0{\\0}\\fR, then it\nrequests default 8-character tabs as described for the \\fB\\-tags\\fR widget\noption.\n.\\\" OPTION: -tabstyle\n.TP\n\\fB\\-tabstyle \\fIstyle\\fR\n.\n\\fIStyle\\fR specifies either the \\fItabular\\fR or \\fIwordprocessor\\fR style of\ntabbing to use for the text widget. This option only applies to a display line\nif it applies to the first non-elided character on that display line. If this\noption is specified as an empty string, it cancels the option, leaving it\nunspecified for the tag (the default).\n.\\\" OPTION: -underline\n.TP\n\\fB\\-underline \\fIboolean\\fR\n.\n\\fIBoolean\\fR specifies whether or not to draw an underline underneath\ncharacters. It may have any of the forms accepted by \\fBTcl_GetBoolean\\fR.\n.\\\" OPTION: -underlinefg\n.TP\n\\fB\\-underlinefg \\fIcolor\\fR\n.\n\\fIColor\\fR specifies the color to use when displaying the underline. It may\nhave any of the forms accepted by \\fBTk_GetColor\\fR. If \\fIcolor\\fR has not\nbeen specified, or if it is specified as an empty string, then the color\nspecified by the \\fB\\-foreground\\fR tag option is used.\n.\\\" OPTION: -wrap\n.TP\n\\fB\\-wrap \\fImode\\fR\n.\n\\fIMode\\fR specifies how to handle lines that are wider than the text's\nwindow. This option only applies to a display line if it applies to the\nfirst non-elided character on that display line. It has the same legal\nvalues as the \\fB\\-wrap\\fR option for the text widget: \\fBnone\\fR,\n\\fBchar\\fR, or \\fBword\\fR. If this tag option is specified, it\noverrides the \\fB\\-wrap\\fR option for the text widget.\n.PP\nIf a character has several tags associated with it, and if their display\noptions conflict, then the options of the highest priority tag are used. If a\nparticular display option has not been specified for a particular tag, or if\nit is specified as an empty string, then that option will never be used; the\nnext-highest-priority tag's option will used instead. If no tag specifies a\nparticular display option, then the default style for the widget will be used.\n.PP\nThe second purpose for tags is event bindings. You can associate bindings with\na tag in much the same way you can associate bindings with a widget class:\nwhenever particular X events occur on characters with the given tag, a given\nTcl command will be executed. Tag bindings can be used to give behaviors to\nranges of characters; among other things, this allows hypertext-like features\nto be implemented. For details, see the description of the\n.QW \"\\fIpathName \\fBtag bind\\fR\"\nwidget command below. Tag bindings are shared between all peer widgets\n(including any bindings for the special \\fBsel\\fR tag).\n.PP\nThe third use for tags is in managing the selection. See \\fBTHE SELECTION\\fR\nbelow. With the exception of the special \\fBsel\\fR tag, all tags are shared\nbetween peer text widgets, and may be manipulated on an equal basis from any\nsuch widget. The \\fBsel\\fR tag exists separately and independently in each\npeer text widget (but any tag bindings to \\fBsel\\fR are shared).\n.SH MARKS\n.PP\nThe second form of annotation in text widgets is a mark. Marks are used for\nremembering particular places in a text. They are something like tags, in that\nthey have names and they refer to places in the file, but a mark is not\nassociated with particular characters. Instead, a mark is associated with the\ngap between two characters. Only a single position may be associated with a\nmark at any given time. If the characters around a mark are deleted the mark\nwill still remain; it will just have new neighbor characters. In contrast, if\nthe characters containing a tag are deleted then the tag will no longer have\nan association with characters in the file. Marks may be manipulated with the\n.QW \"\\fIpathName \\fBmark\\fR\"\nwidget command, and their current locations may be determined by using the\nmark name as an index in widget commands.\n.PP\nEach mark also has a\n.QW gravity ,\nwhich is either \\fBleft\\fR or \\fBright\\fR. The gravity for a mark specifies\nwhat happens to the mark when text is inserted at the point of the mark. If a\nmark has left gravity, then the mark is treated as if it were attached to the\ncharacter on its left, so the mark will remain to the left of any text\ninserted at the mark position. If the mark has right gravity, new text\ninserted at the mark position will appear to the left of the mark (so that the\nmark remains rightmost). The gravity for a mark defaults to \\fBright\\fR.\n.PP\nThe name space for marks is different from that for tags: the same name may be\nused for both a mark and a tag, but they will refer to different things.\n.PP\nTwo marks have special significance. First, the mark \\fBinsert\\fR is\nassociated with the insertion cursor, as described under\n\\fBTHE INSERTION CURSOR\\fR\nbelow. Second, the mark \\fBcurrent\\fR is associated with the\ncharacter closest to the mouse and is adjusted automatically to track the\nmouse position and any changes to the text in the widget (one exception:\n\\fBcurrent\\fR is not updated in response to mouse motions if a mouse button is\ndown; the update will be deferred until all mouse buttons have been released).\nNeither of these special marks may be deleted. With the exception of these two\nspecial marks, all marks are shared between peer text widgets, and may be\nmanipulated on an equal basis from any peer.\n.SH \"EMBEDDED WINDOWS\"\n.PP\nThe third form of annotation in text widgets is an embedded window. Each\nembedded window annotation causes a window to be displayed at a particular\npoint in the text. There may be any number of embedded windows in a text\nwidget, and any widget may be used as an embedded window (subject to the usual\nrules for geometry management, which require the text window to be the parent\nof the embedded window or a descendant of its parent).\n.PP\nThe embedded window's position on the screen will be updated as the text is\nmodified or scrolled, and it will be mapped and unmapped as it moves into and\nout of the visible area of the text widget. Each embedded window occupies one\nunit's worth of index space in the text widget, and it may be referred to\neither by the name of its embedded window or by its position in the widget's\nindex space. If the range of text containing the embedded window is deleted\nthen the window is destroyed. Similarly if the text widget as a whole is\ndeleted, then the window is destroyed.\n.PP\nEliding an embedded window immediately after scheduling it for creation via\n\\fIpathName \\fBwindow create \\fIindex \\fB\\-create\\fR will prevent it from being\neffectively created. Uneliding an elided embedded window scheduled for creation\nvia \\fIpathName \\fBwindow create \\fIindex \\fB\\-create\\fR will automatically\ntrigger the associated creation script. After destroying an elided embedded\nwindow, the latter won't get automatically recreated.\n.PP\nWhen an embedded window is added to a text widget with the \\fIpathName\n\\fBwindow create\\fR widget command, several configuration options may be\nassociated with it. These options may be modified later with the \\fIpathName\n\\fBwindow configure\\fR widget command. The following options are currently\nsupported:\n.\\\" OPTION: -align\n.TP\n\\fB\\-align \\fIwhere\\fR\n.\nIf the window is not as tall as the line in which it is displayed, this option\ndetermines where the window is displayed in the line. \\fIWhere\\fR must have\none of the values \\fBtop\\fR (align the top of the window with the top of the\nline), \\fBcenter\\fR (center the window within the range of the line),\n\\fBbottom\\fR (align the bottom of the window with the bottom of the line's\narea), or \\fBbaseline\\fR (align the bottom of the window with the baseline of\nthe line).\n.\\\" OPTION: -create\n.TP\n\\fB\\-create \\fIscript\\fR\n.\nSpecifies a Tcl script that may be evaluated to create the window for the\nannotation. If no \\fB\\-window\\fR option has been specified for the annotation\nthis script will be evaluated when the annotation is about to be displayed on\nthe screen. \\fIScript\\fR must create a window for the annotation and return\nthe name of that window as its result. Two substitutions will be performed in\n\\fIscript\\fR before evaluation. \\fI%W\\fR will be substituted by the name of\nthe parent text widget, and \\fI%%\\fR will be substituted by a single \\fI%\\fR.\nIf the annotation's window should ever be deleted, \\fIscript\\fR will be\nevaluated again the next time the annotation is displayed.\n.\\\" OPTION: -padx\n.TP\n\\fB\\-padx \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies the amount of extra space to leave on each side of the\nembedded window. It may have any of the usual forms defined for a screen\ndistance.\n.\\\" OPTION: -pady\n.TP\n\\fB\\-pady \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies the amount of extra space to leave on the top and on\nthe bottom of the embedded window. It may have any of the usual forms defined\nfor a screen distance.\n.\\\" OPTION: -stretch\n.TP\n\\fB\\-stretch \\fIboolean\\fR\n.\nIf the requested height of the embedded window is less than the height of the\nline in which it is displayed, this option can be used to specify whether the\nwindow should be stretched vertically to fill its line. If the \\fB\\-pady\\fR\noption has been specified as well, then the requested padding will be retained\neven if the window is stretched.\n.\\\" OPTION: -window\n.TP\n\\fB\\-window \\fIpathName\\fR\n.\nSpecifies the name of a window to display in the annotation. Note that if a\n\\fIpathName\\fR has been set, then later configuring a window to the empty\nstring will not delete the widget corresponding to the old \\fIpathName\\fR.\nRather it will remove the association between the old \\fIpathName\\fR and the\ntext widget. If multiple peer widgets are in use, it is usually simpler to use\nthe \\fB\\-create\\fR option if embedded windows are desired in each peer.\n.SH \"EMBEDDED IMAGES\"\n.PP\nThe final form of annotation in text widgets is an embedded image. Each\nembedded image annotation causes an image to be displayed at a particular\npoint in the text. There may be any number of embedded images in a text\nwidget, and a particular image may be embedded in multiple places in the same\ntext widget.\n.PP\nThe embedded image's position on the screen will be updated as the text is\nmodified or scrolled. Each embedded image occupies one unit's worth of index\nspace in the text widget, and it may be referred to either by its position in\nthe widget's index space, or the name it is assigned when the image is inserted\ninto the text widget with \\fIpathName \\fBimage create\\fR. If the range of text\ncontaining the embedded image is deleted then that copy of the image is removed\nfrom the screen.\n.PP\nEliding an embedded image immediately after scheduling it for creation via\n\\fIpathName \\fBimage create \\fIindex \\fB\\-create\\fR will prevent it from being\neffectively created. Uneliding an elided embedded image scheduled for creation\nvia \\fIpathName \\fBimage create \\fIindex \\fB\\-create\\fR will automatically\ntrigger the associated creation script. After destroying an elided embedded\nimage, the latter won't get automatically recreated.\n.PP\nWhen an embedded image is added to a text widget with the \\fIpathName \\fBimage\ncreate\\fR widget command, a name unique to this instance of the image is\nreturned. This name may then be used to refer to this image instance. The name\nis taken to be the value of the \\fB\\-name\\fR option (described below). If the\n\\fB\\-name\\fR option is not provided, the \\fB\\-image\\fR name is used instead.\nIf the \\fIimageName\\fR is already in use in the text widget, then \\fB#\\fInn\\fR\nis added to the end of the \\fIimageName\\fR, where \\fInn\\fR is an arbitrary\ninteger. This insures the \\fIimageName\\fR is unique. Once this name is\nassigned to this instance of the image, it does not change, even though the\n\\fB\\-image\\fR or \\fB\\-name\\fR values can be changed with \\fIpathName \\fBimage\nconfigure\\fR.\n.PP\nWhen an embedded image is added to a text widget with the \\fIpathName \\fBimage\ncreate\\fR widget command, several configuration options may be associated with\nit. These options may be modified later with the \\fIpathName \\fBimage\nconfigure\\fR widget command. The following options are currently supported:\n.\\\" OPTION: -align\n.TP\n\\fB\\-align \\fIwhere\\fR\n.\nIf the image is not as tall as the line in which it is displayed, this option\ndetermines where the image is displayed in the line. \\fIWhere\\fR must have one\nof the values \\fBtop\\fR (align the top of the image with the top of the line),\n\\fBcenter\\fR (center the image within the range of the line), \\fBbottom\\fR\n(align the bottom of the image with the bottom of the line's area), or\n\\fBbaseline\\fR (align the bottom of the image with the baseline of the line).\n.\\\" OPTION: -image\n.TP\n\\fB\\-image \\fIimage\\fR\n.\nSpecifies the name of the Tk image to display in the annotation. If\n\\fIimage\\fR is not a valid Tk image, then an error is returned.\n.\\\" OPTION: -name\n.TP\n\\fB\\-name \\fIImageName\\fR\n.\nSpecifies the name by which this image instance may be referenced in the text\nwidget. If \\fIImageName\\fR is not supplied, then the name of the Tk image is\nused instead. If the \\fIimageName\\fR is already in use, \\fI#nn\\fR is appended\nto the end of the name as described above.\n.\\\" OPTION: -padx\n.TP\n\\fB\\-padx \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies the amount of extra space to leave on each side of the\nembedded image. It may have any of the usual forms defined for a screen\ndistance.\n.\\\" OPTION: -pady\n.TP\n\\fB\\-pady \\fIpixels\\fR\n.\n\\fIPixels\\fR specifies the amount of extra space to leave on the top and on\nthe bottom of the embedded image. It may have any of the usual forms defined\nfor a screen distance.\n.SH \"THE SELECTION\"\n.PP\nSelection support is implemented via tags. If the \\fB\\-exportselection\\fR option\nfor the text widget is true then the \\fBsel\\fR tag will be associated with the\nselection:\n.IP [1]\nWhenever characters are tagged with \\fBsel\\fR the text widget will claim\nownership of the selection.\n.IP [2]\nAttempts to retrieve the selection will be serviced by the text widget,\nreturning all the characters with the \\fBsel\\fR tag.\n.IP [3]\nIf the selection is claimed away by another application or by another window\nwithin this application, then the \\fBsel\\fR tag will be removed from all\ncharacters in the text.\n.IP [4]\nWhenever the \\fBsel\\fR tag range changes a virtual event \\fB<<Selection>>\\fR\nis generated.\nIt might also be generated when selection is affected but not actually changed.\nFurther, multiple selection changes could happen before events can be processed\nleading to multiple events with the same visible selection.\n.PP\nThe \\fBsel\\fR tag is automatically defined when a text widget is created, and\nit may not be deleted with the\n.QW \"\\fIpathName \\fBtag delete\\fR\"\nwidget command. Furthermore, the \\fB\\-selectbackground\\fR,\n\\fB\\-selectborderwidth\\fR, and \\fB\\-selectforeground\\fR options for the text\nwidget are tied to the \\fB\\-background\\fR, \\fB\\-borderwidth\\fR, and\n\\fB\\-foreground\\fR options for the \\fBsel\\fR tag: changes in either will\nautomatically be reflected in the other. Also the\n\\fB\\-inactiveselectbackground\\fR option for the text widget is used instead of\n\\fB\\-selectbackground\\fR when the text widget does not have the focus. This\nallows programmatic control over the visualization of the \\fBsel\\fR tag for\nforeground and background windows, or to have \\fBsel\\fR not shown at all (when\n\\fB\\-inactiveselectbackground\\fR is empty) for background windows. Each peer\ntext widget has its own \\fBsel\\fR tag which can be separately configured and\nset.\n.SH \"THE INSERTION CURSOR\"\n.PP\nThe mark named \\fBinsert\\fR has special significance in text widgets. It is\ndefined automatically when a text widget is created and it may not be unset\nwith the\n.QW \"\\fIpathName \\fBmark unset\\fR\"\nwidget command. The \\fBinsert\\fR mark represents the position of the insertion\ncursor, and the insertion cursor will automatically be drawn at this point\nwhenever the text widget has the input focus.\n.SH \"THE MODIFIED FLAG\"\n.PP\nThe text widget can keep track of changes to the content of the widget by\nmeans of the modified flag. Inserting or deleting text will set this flag. The\nflag can be queried, set and cleared programmatically as well. Whenever the\nflag changes state a \\fB<<Modified>>\\fR virtual event is generated. See the\n\\fIpathName \\fBedit modified\\fR widget command for more details.\n.SH \"THE UNDO MECHANISM\"\n.PP\nThe text widget has an unlimited undo and redo mechanism (when the\n\\fB\\-undo\\fR widget option is true) which records every insert and delete\naction on a stack.\n.PP\nBoundaries (called\n.QW separators )\nare inserted between edit actions. The purpose of these separators is to group\ninserts, deletes and replaces into one compound edit action. When undoing a\nchange everything between two separators will be undone. The undone changes\nare then moved to the redo stack, so that an undone edit can be redone again.\nThe redo stack is cleared whenever new edit actions are recorded on the undo\nstack. The undo and redo stacks can be cleared to keep their depth under\ncontrol.\n.PP\nSeparators are inserted automatically when the \\fB\\-autoseparators\\fR widget\noption is true. You can insert separators programmatically as well. If a\nseparator is already present at the top of the undo stack no other will be\ninserted. That means that two separators on the undo stack are always\nseparated by at least one insert or delete action.\n.PP\nThe \\fB<<UndoStack>>\\fR virtual event is generated every time the undo stack\nor the redo stack becomes empty or unempty.\n.PP\nThe undo mechanism is also linked to the modified flag. This means that\nundoing or redoing changes can take a modified text widget back to the\nunmodified state or vice versa. The modified flag will be set automatically to\nthe appropriate state. This automatic coupling does not work when the modified\nflag has been set by the user, until the flag has been reset again.\n.PP\nSee below for the \\fIpathName \\fBedit\\fR widget command that controls the undo\nmechanism.\n.SH \"PEER WIDGETS\"\n.PP\nThe text widget has a separate store of all its data concerning each line's\ntextual contents, marks, tags, images and windows, and the undo stack.\n.PP\nWhile this data store cannot be accessed directly (i.e. without a text widget\nas an intermediary), multiple text widgets can be created, each of which\npresent different views on the same underlying data. Such text widgets are\nknown as peer text widgets.\n.PP\nAs text is added, deleted, edited and coloured in any one widget, and as\nimages, marks, tags are adjusted, all such changes will be reflected in all\npeers.\n.PP\nAll data and markup is shared, except for a few small details. First, the\n\\fBsel\\fR tag may be set and configured (in its display style) differently for\neach peer. Second, each peer has its own \\fBinsert\\fR and \\fBcurrent\\fR mark\npositions (but all other marks are shared). Third, embedded windows, which are\narbitrary other widgets, cannot be shared between peers. This means the\n\\fB\\-window\\fR option of embedded windows is independently set for each peer\n(it is advisable to use the \\fB\\-create\\fR script capabilities to allow each\npeer to create its own embedded windows as needed). Fourth, all of the\nconfiguration options of each peer (e.g. \\fB\\-font\\fR, etc) can be set\nindependently, with the exception of \\fB\\-undo\\fR, \\fB\\-maxundo\\fR,\n\\fB\\-autoseparators\\fR (i.e. all undo, redo and modified state issues are\nshared).\n.PP\nFinally any single peer need not contain all lines from the underlying data\nstore. When creating a peer, a contiguous range of lines (e.g. only lines 52\nthrough 125) may be specified. This allows a peer to contain just a small\nportion of the overall text. The range of lines will expand and contract as\ntext is inserted or deleted. The peer will only ever display complete lines of\ntext (one cannot share just part of a line). If the peer's contents contracts\nto nothing (i.e. all complete lines in the peer widget have been deleted from\nanother widget), then it is impossible for new lines to be inserted. The peer\nwill simply become an empty shell on which the background can be configured,\nbut which will never show any content (without manual reconfiguration of the\nstart and end lines). Note that a peer which does not contain all of the\nunderlying data store still has indices numbered from\n.QW 1.0\nto\n.QW end .\nIt is simply that those indices reflect a subset of the total data, and data\noutside the contained range is not accessible to the peer. This means that the\ncommand \\fIpeerName \\fBindex end\\fR may return quite different values in\ndifferent peers. Similarly, commands like \\fIpeerName \\fBtag ranges\\fR will\nnot return index ranges outside that which is meaningful to the peer. The\nconfiguration options \\fB\\-startline\\fR and \\fB\\-endline\\fR may be used to\ncontrol how much of the underlying data is contained in any given text widget.\n.PP\nNote that peers are really peers. Deleting the\n.QW original\ntext widget will not cause any other peers to be deleted, or otherwise\naffected.\n.PP\nSee below for the \\fIpathName \\fBpeer\\fR widget command that controls the\ncreation of peer widgets.\n.SH \"ASYNCHRONOUS UPDATE OF LINE HEIGHTS\"\n.PP\nIn order to maintain a responsive user-experience, the text widget calculates\nlines metrics (line heights in pixels) asynchronously. Because of this, some\ncommands of the text widget may return wrong results if the asynchronous\ncalculations are not finished at the time of calling. This applies to\n\\fIpathName \\fBcount \\-ypixels\\fR and \\fIpathName \\fByview\\fR.\n.PP\nAgain for performance reasons, it would not be appropriate to let these\ncommands always wait for the end of the update calculation each time they are\ncalled. In most use cases of these commands a more or less inaccurate result\ndoes not really matter compared to execution speed.\n.PP\nIn case accurate result is needed (and if the text widget is managed by a\ngeometry manager), one can resort to \\fIpathName \\fBsync\\fR and \\fIpathName\n\\fBpendingsync\\fR to control the synchronization of the view of text widgets.\n.PP\nThe \\fB<<WidgetViewSync>>\\fR virtual event fires when the line heights of the\ntext widget become obsolete (due to some editing command or configuration\nchange), and again when the internal data of the text widget are back in sync\nwith the widget view. The detail field (%d substitution) is either true (when\nthe widget is in sync) or false (when it is not).\n.PP\n\\fIpathName \\fBsync\\fR, \\fIpathName \\fBpendingsync\\fR and\n\\fB<<WidgetViewSync>>\\fR apply to each text widget independently of its peers.\n.PP\nExamples of use:\n.CS\n## Example 1:\n# immediately complete line metrics at any cost (GUI unresponsive)\n$w sync\n$w yview moveto $fraction\n\n## Example 2:\n# synchronously wait for up-to-date line metrics (GUI responsive)\n# before executing the scheduled command, but don't block execution flow\n$w sync -command [list $w yview moveto $fraction]\n\n## Example 3:\n# init\nset yud($w) 0\nproc updateaction w {\n\\&set ::yud($w) 1\n\\&# any other update action here...\n}\n# runtime, synchronously wait for up-to-date line metrics (GUI responsive)\n$w sync -command [list updateaction $w]\nvwait yud($w)\n$w yview moveto $fraction\n\n## Example 4:\n# init\nset todo($w) {}\nproc updateaction w {\n\\&foreach cmd $::todo($w) {uplevel #0 $cmd}\n\\&set todo($w) {}\n}\n# runtime\nlappend todo($w) [list $w yview moveto $fraction]\n$w sync -command [list updateaction $w]\n\n## Example 5:\n# init\nset todo($w) {}\nbind $w <<WidgetViewSync>> {\n\\&if {%d} {\n\\&\\&foreach cmd $todo(%W) {eval $cmd}\n\\&\\&set todo(%W) {}\n\\&}\n}\n# runtime\nif {![$w pendingsync]} {\n\\&$w yview moveto $fraction\n} else {\n\\&lappend todo($w) [list $w yview moveto $fraction]\n}\n.CE\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBtext\\fR command creates a new Tcl command whose name is the same as the\npath name of the text's window. This command may be used to invoke various\noperations on the widget. It has the following general form:\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n\\fIPathName\\fR is the name of the command, which is the same as the text\nwidget's path name. \\fIOption\\fR and the \\fIarg\\fRs determine the exact\nbehavior of the command. The following commands are possible for text widgets:\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox \\fIindex\\fR\n.\nReturns a list of four elements describing the screen area of the character\ngiven by \\fIindex\\fR. The first two elements of the list give the x and y\ncoordinates of the upper-left corner of the area occupied by the character,\nand the last two elements give the width and height of the area. If the\ncharacter is only partially visible on the screen, then the return value\nreflects just the visible part. If the character is not visible on the screen\nthen the return value is an empty list.\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget\\fI option\\fR\n.\nReturns the current value of the configuration option given by \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBtext\\fR command.\n.\\\" METHOD: compare\n.TP\n\\fIpathName \\fBcompare\\fI index1 op index2\\fR\n.\nCompares the indices given by \\fIindex1\\fR and \\fIindex2\\fR according to the\nrelational operator given by \\fIop\\fR, and returns 1 if the relationship is\nsatisfied and 0 if it is not. \\fIOp\\fR must be one of the operators <, <=, ==,\n>=, >, or !=. If \\fIop\\fR is == then 1 is returned if the two indices refer to\nthe same character, if \\fIop\\fR is < then 1 is returned if \\fIindex1\\fR refers\nto an earlier character in the text than \\fIindex2\\fR, and so on.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget. If no \\fIoption\\fR is\nspecified, returns a list describing all of the available options for\n\\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for information on the format of\nthis list). If \\fIoption\\fR is specified with no \\fIvalue\\fR, then the command\nreturns a list describing the one named option (this list will be identical to\nthe corresponding sublist of the value returned if no \\fIoption\\fR is\nspecified). If one or more \\fIoption\\-value\\fR pairs are specified, then the\ncommand modifies the given widget option(s) to have the given value(s); in\nthis case the command returns an empty string. \\fIOption\\fR may have any of\nthe values accepted by the \\fBtext\\fR command.\n.\\\" METHOD: count\n.TP\n\\fIpathName \\fBcount\\fR ?\\fIoptions\\fR? \\fIindex1 index2\\fR\n.\nCounts the number of relevant things between the two indices. If \\fIindex1\\fR\nis after \\fIindex2\\fR, the result will be a negative number (and this holds\nfor each of the possible options). The actual items which are counted depend\non the options given. The result is a list of integers, one for the result of\neach counting option given. Valid counting options are \\fB\\-chars\\fR,\n\\fB\\-displaychars\\fR, \\fB\\-displayindices\\fR, \\fB\\-displaylines\\fR,\n\\fB\\-indices\\fR, \\fB\\-lines\\fR, \\fB\\-xpixels\\fR and \\fB\\-ypixels\\fR. The\ndefault value, if no option is specified, is \\fB\\-indices\\fR. There is an\nadditional possible option \\fB\\-update\\fR which is a modifier. If given (and\nif the text widget is managed by a geometry manager), then all subsequent\noptions ensure that any possible out of date information is recalculated.\nThis currently only has any effect for the \\fB\\-ypixels\\fR count (which, if\n\\fB\\-update\\fR is not given, will use the text widget's current cached value\nfor each line). This \\fB\\-update\\fR option is obsoleted by \\fIpathName\n\\fBsync\\fR, \\fIpathName \\fBpendingsync\\fR and \\fB<<WidgetViewSync>>\\fR.  The\ncount options are interpreted as follows:\n.RS\n.IP \\fB\\-chars\\fR\ncount all characters, whether elided or not. Do not count embedded windows or\nimages.\n.IP \\fB\\-displaychars\\fR\ncount all non-elided characters.\n.IP \\fB\\-displayindices\\fR\ncount all non-elided characters, windows and images.\n.IP \\fB\\-displaylines\\fR\ncount all display lines (i.e. counting one for each time a line wraps) from\nthe line of the first index up to, but not including the display line of the\nsecond index. Therefore if they are both on the same display line, zero will\nbe returned. By definition displaylines are visible and therefore this only\ncounts portions of actual visible lines.\n.IP \\fB\\-indices\\fR\ncount all characters and embedded windows or images (i.e. everything which\ncounts in text-widget index space), whether they are elided or not.\n.IP \\fB\\-lines\\fR\ncount all logical lines (irrespective of wrapping) from the line of the first\nindex up to, but not including the line of the second index. Therefore if they\nare both on the same line, zero will be returned. Logical lines are counted\nwhether they are currently visible (non-elided) or not.\n.IP \\fB\\-xpixels\\fR\ncount the number of horizontal pixels from the first pixel of the first index\nto (but not including) the first pixel of the second index. To count the total\ndesired width of the text widget (assuming wrapping is not enabled), first\nfind the longest line and then use\n.QW \".text count \\-xpixels \\N'34'${line}.0\\N'34' \\N'34'${line}.0 lineend\\N'34'\" .\n.IP \\fB\\-ypixels\\fR\ncount the number of vertical pixels from the first pixel of the first index to\n(but not including) the first pixel of the second index. If both indices are\non the same display line, zero will be returned. To count the total number of\nvertical pixels in the text widget, use\n.QW \".text count \\-ypixels 1.0 end\" ,\nand to ensure this is up to date, use\n.QW \".text count \\-update \\-ypixels 1.0 end\" .\n.PP\nThe command returns a positive or negative integer corresponding to the number\nof items counted between the two indices. One such integer is returned for\neach counting option given, so a list is returned if more than one option was\nsupplied. For example\n.QW \".text count \\-xpixels \\-ypixels 1.3 4.5\"\nis perfectly valid and will return a list of two elements.\n.RE\n.\\\" METHOD: debug\n.TP\n\\fIpathName \\fBdebug \\fR?\\fIboolean\\fR?\n.\nIf \\fIboolean\\fR is specified, then it must have one of the true or false\nvalues accepted by Tcl_GetBoolean. If the value is a true one then internal\nconsistency checks will be turned on in the B-tree code associated with text\nwidgets. If \\fIboolean\\fR has a false value then the debugging checks will be\nturned off. In either case the command returns an empty string. If\n\\fIboolean\\fR is not specified then the command returns \\fBon\\fR or \\fBoff\\fR\nto indicate whether or not debugging is turned on. There is a single debugging\nswitch shared by all text widgets: turning debugging on or off in any widget\nturns it on or off for all widgets. For widgets with large amounts of text,\nthe consistency checks may cause a noticeable slow-down.\n.RS\n.PP\nWhen debugging is turned on, the drawing routines of the text widget set the\nglobal variables \\fBtk_textRedraw\\fR and \\fBtk_textRelayout\\fR to the lists of\nindices that are redrawn. The values of these variables are tested by Tk's\ntest suite.\n.RE\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIindex1 \\fR?\\fIindex2 ...\\fR?\n.\nDelete a range of characters from the text.\nIf both \\fIindex1\\fR and \\fIindex2\\fR are specified, then delete\nall the characters starting with the one given by \\fIindex1\\fR\nand stopping just before \\fIindex2\\fR (i.e. the character at\n\\fIindex2\\fR is not deleted).\nIf \\fIindex2\\fR does not specify a position later in the text\nthan \\fIindex1\\fR then no characters are deleted.\nIf \\fIindex2\\fR is not specified then the single character at\n\\fIindex1\\fR is deleted.\nAttempts to delete characters in a way that would leave\nthe text without a newline as the last character will be tweaked by the\ntext widget to avoid this. In particular, deletion of complete lines of\ntext up to the end of the text will also delete the newline character just\nbefore the deleted block so that it is replaced by the new final newline\nof the text widget.\nThe command returns an empty string.\nIf more indices are given, multiple ranges of text will be deleted.\nAll indices are first checked for validity before any deletions are made.\nThey are sorted and the text is removed from the last range to the\nfirst range so deleted text does not cause an undesired index shifting\nside-effects.  If multiple ranges with the same start index are given,\nthen the longest range is used.  If overlapping ranges are given, then\nthey will be merged into spans that do not cause deletion of text\noutside the given ranges due to text shifted during deletion.\n.\\\" METHOD: dlineinfo\n.TP\n\\fIpathName \\fBdlineinfo \\fIindex\\fR\n.\nReturns a list with five elements describing the area occupied by the display\nline containing \\fIindex\\fR. The first two elements of the list give the x and\ny coordinates of the upper-left corner of the area occupied by the line, the\nthird and fourth elements give the width and height of the area, and the fifth\nelement gives the position of the baseline for the line, measured down from\nthe top of the area. All of this information is measured in pixels. If the\ncurrent wrap mode is \\fBnone\\fR and the line extends beyond the boundaries of\nthe window, the area returned reflects the entire area of the line, including\nthe portions that are out of the window. If the line is shorter than the full\nwidth of the window then the area returned reflects just the portion of the\nline that is occupied by characters and embedded windows. If the display line\ncontaining \\fIindex\\fR is not visible on the screen then the return value is\nan empty list.\n.\\\" METHOD: dump\n.TP\n\\fIpathName \\fBdump \\fR?\\fIswitches\\fR? \\fIindex1 \\fR?\\fIindex2\\fR?\n.\nReturn the contents of the text widget from \\fIindex1\\fR up to, but not\nincluding \\fIindex2\\fR, including the text and information about marks, tags,\nand embedded windows. If \\fIindex2\\fR is not specified, then it defaults to\none character past \\fIindex1\\fR. The information is returned in the following\nformat:\n.RS\n.LP\n\\fIkey1 value1 index1 key2 value2 index2\\fR ...\n.LP\nThe possible \\fIkey\\fR values are \\fBtext\\fR, \\fBmark\\fR, \\fBtagon\\fR,\n\\fBtagoff\\fR, \\fBimage\\fR, and \\fBwindow\\fR. The corresponding \\fIvalue\\fR is\nthe text, mark name, tag name, image name, or window name. The \\fIindex\\fR\ninformation is the index of the start of the text, mark, tag transition, image\nor window. One or more of the following switches (or abbreviations thereof)\nmay be specified to control the dump:\n.\\\" OPTION: -all\n.TP\n\\fB\\-all\\fR\n.\nReturn information about all elements: text, marks, tags, images and windows.\nThis is the default.\n.\\\" OPTION: -command\n.TP\n\\fB\\-command \\fIcommand\\fR\n.\nInstead of returning the information as the result of the dump operation,\ninvoke the \\fIcommand\\fR on each element of the text widget within the range.\nThe command has three arguments appended to it before it is evaluated: the\n\\fIkey\\fR, \\fIvalue\\fR, and \\fIindex\\fR.\n.\\\" OPTION: -image\n.TP\n\\fB\\-image\\fR\n.\nInclude information about images in the dump results.\n.\\\" OPTION: -mark\n.TP\n\\fB\\-mark\\fR\n.\nInclude information about marks in the dump results.\n.\\\" OPTION: -tag\n.TP\n\\fB\\-tag\\fR\n.\nInclude information about tag transitions in the dump results. Tag information\nis returned as \\fBtagon\\fR and \\fBtagoff\\fR elements that indicate the begin\nand end of each range of each tag, respectively.\n.\\\" OPTION: -text\n.TP\n\\fB\\-text\\fR\n.\nInclude information about text in the dump results. The value is the text up\nto the next element or the end of range indicated by \\fIindex2\\fR. A text\nelement does not span newlines. A multi-line block of text that contains no\nmarks or tag transitions will still be dumped as a set of text segments that\neach end with a newline. The newline is part of the value.\n.\\\" OPTION: -window\n.TP\n\\fB\\-window\\fR\n.\nInclude information about embedded windows in the dump results. The value of a\nwindow is its Tk pathname, unless the window has not been created yet. (It\nmust have a create script.) In this case an empty string is returned, and you\nmust query the window by its index position to get more information.\n.RE\n.\\\" METHOD: edit\n.TP\n\\fIpathName \\fBedit \\fIoption \\fR?\\fIarg ...\\fR?\n.\nThis command controls the undo mechanism and the modified flag. The exact\nbehavior of the command depends on the \\fIoption\\fR argument that follows the\n\\fBedit\\fR argument. The following forms of the command are currently\nsupported:\n.RS\n.TP\n\\fIpathName \\fBedit canredo\\fR\n.\nReturns a boolean true if redo is possible, i.e. when the redo stack is not\nempty. Otherwise returns false.\n.TP\n\\fIpathName \\fBedit canundo\\fR\n.\nReturns a boolean true if undo is possible, i.e. when the undo stack is not\nempty. Otherwise returns false.\n.TP\n\\fIpathName \\fBedit modified \\fR?\\fIboolean\\fR?\n.\nIf \\fIboolean\\fR is not specified, returns the modified flag of the widget.\nThe insert, delete, edit undo and edit redo commands or the user can set or\nclear the modified flag. If \\fIboolean\\fR is specified, sets the modified flag\nof the widget to \\fIboolean\\fR.\n.TP\n\\fIpathName \\fBedit redo\\fR\n.\nWhen the \\fB\\-undo\\fR option is true, reapplies the last undone edits provided\nno other edits were done since then, and returns a list of indices indicating\nwhat ranges were changed by the redo operation. Generates an error when the\nredo stack is empty. Does nothing when the \\fB\\-undo\\fR option is false.\n.TP\n\\fIpathName \\fBedit reset\\fR\n.\nClears the undo and redo stacks.\n.TP\n\\fIpathName \\fBedit separator\\fR\n.\nInserts a separator (boundary) on the undo stack. Does nothing when the\n\\fB\\-undo\\fR option is false.\n.TP\n\\fIpathName \\fBedit undo\\fR\n.\nUndoes the last edit action when the \\fB\\-undo\\fR option is true, and returns a\nlist of indices indicating what ranges were changed by the undo operation. An\nedit action is defined as all the insert and delete commands that are recorded\non the undo stack in between two separators. Generates an error when the undo\nstack is empty. Does nothing when the \\fB\\-undo\\fR option is false.\n.RE\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR ?\\fB\\-displaychars\\fR? ?\\fB\\-\\-\\fR? \\fIindex1\\fR ?\\fIindex2 ...\\fR?\n.\nReturn a range of characters from the text. The return value will be all the\ncharacters in the text starting with the one whose index is \\fIindex1\\fR and\nending just before the one whose index is \\fIindex2\\fR (the character at\n\\fIindex2\\fR will not be returned). If \\fIindex2\\fR is omitted then the single\ncharacter at \\fIindex1\\fR is returned. If there are no characters in the\nspecified range (e.g. \\fIindex1\\fR is past the end of the file or \\fIindex2\\fR\nis less than or equal to \\fIindex1\\fR) then an empty string is returned. If\nthe specified range contains embedded windows, no information about them is\nincluded in the returned string. If multiple index pairs are given, multiple\nranges of text will be returned in a list. Invalid ranges will not be\nrepresented with empty strings in the list. The ranges are returned in the\norder passed to \\fIpathName \\fBget\\fR. If the \\fB\\-displaychars\\fR option is\ngiven, then, within each range, only those characters which are not elided\nwill be returned. This may have the effect that some of the returned ranges\nare empty strings.\n.\\\" METHOD: image\n.TP\n\\fIpathName \\fBimage \\fIoption \\fR?\\fIarg ...\\fR?\n.\nThis command is used to manipulate embedded images. The behavior of the\ncommand depends on the \\fIoption\\fR argument that follows the \\fBimage\\fR\nargument. The following forms of the command are currently supported:\n.RS\n.TP\n\\fIpathName \\fBimage cget \\fIindex option\\fR\n.\nReturns the value of a configuration option for an embedded image. \\fIIndex\\fR\nidentifies the embedded image, and \\fIoption\\fR specifies a particular\nconfiguration option, which must be one of the ones listed in the section\n\\fBEMBEDDED IMAGES\\fR.\n.TP\n\\fIpathName \\fBimage configure \\fIindex\\fR ?\\fIoption value ...\\fR?\n.\nQuery or modify the configuration options for an embedded image. If no\n\\fIoption\\fR is specified, returns a list describing all of the available\noptions for the embedded image at \\fIindex\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list). If \\fIoption\\fR is specified with no\n\\fIvalue\\fR, then the command returns a list describing the one named option\n(this list will be identical to the corresponding sublist of the value\nreturned if no \\fIoption\\fR is specified). If one or more \\fIoption\\-value\\fR\npairs are specified, then the command modifies the given option(s) to have the\ngiven value(s); in this case the command returns an empty string. See\n\\fBEMBEDDED IMAGES\\fR for information on the options that are supported.\n.TP\n\\fIpathName \\fBimage create \\fIindex\\fR ?\\fIoption value ...\\fR?\n.\nThis command creates a new image annotation, which will appear in the text at\nthe position given by \\fIindex\\fR. Any number of \\fIoption\\-value\\fR pairs may\nbe specified to configure the annotation. Returns a unique identifier that may\nbe used as an index to refer to this image. See \\fBEMBEDDED IMAGES\\fR for\ninformation on the options that are supported, and a description of the\nidentifier returned.\n.TP\n\\fIpathName \\fBimage names\\fR\n.\nReturns a list whose elements are the names of all image instances currently\nembedded in \\fIwindow\\fR.\n.RE\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex \\fIindex\\fR\n.\nReturns the position corresponding to \\fIindex\\fR in the form \\fIline.char\\fR\nwhere \\fIline\\fR is the line number and \\fIchar\\fR is the character number.\n\\fIIndex\\fR may have any of the forms described under \\fBINDICES\\fR above.\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex chars \\fR?\\fItagList chars tagList ...\\fR?\n.\nInserts all of the \\fIchars\\fR arguments just before the character at\n\\fIindex\\fR. If \\fIindex\\fR refers to the end of the text (the character after\nthe last newline) then the new text is inserted just before the last newline\ninstead. If there is a single \\fIchars\\fR argument and no \\fItagList\\fR, then\nthe new text will receive any tags that are present on both the character\nbefore and the character after the insertion point; if a tag is present on\nonly one of these characters then it will not be applied to the new text. If\n\\fItagList\\fR is specified then it consists of a list of tag names; the new\ncharacters will receive all of the tags in this list and no others, regardless\nof the tags present around the insertion point. If multiple\n\\fIchars\\fR\\-\\fItagList\\fR argument pairs are present, they produce the same\neffect as if a separate \\fIpathName \\fBinsert\\fR widget command had been\nissued for each pair, in order. The last \\fItagList\\fR argument may be\nomitted.\n.\\\" METHOD: mark\n.TP\n\\fIpathName \\fBmark \\fIoption \\fR?\\fIarg ...\\fR?\n.\nThis command is used to manipulate marks. The exact behavior of the command\ndepends on the \\fIoption\\fR argument that follows the \\fBmark\\fR argument. The\nfollowing forms of the command are currently supported:\n.RS\n.TP\n\\fIpathName \\fBmark gravity \\fImarkName\\fR ?\\fIdirection\\fR?\n.\nIf \\fIdirection\\fR is not specified, returns \\fBleft\\fR or \\fBright\\fR to\nindicate which of its adjacent characters \\fImarkName\\fR is attached to. If\n\\fIdirection\\fR is specified, it must be \\fBleft\\fR or \\fBright\\fR; the\ngravity of \\fImarkName\\fR is set to the given value.\n.TP\n\\fIpathName \\fBmark names\\fR\n.\nReturns a list whose elements are the names of all the marks that are\ncurrently set.\n.TP\n\\fIpathName \\fBmark next \\fIindex\\fR\n.\nReturns the name of the next mark at or after \\fIindex\\fR. If \\fIindex\\fR is\nspecified in numerical form, then the search for the next mark begins at that\nindex. If \\fIindex\\fR is the name of a mark, then the search for the next mark\nbegins immediately after that mark. This can still return a mark at the same\nposition if there are multiple marks at the same index. These semantics mean\nthat the \\fBmark next\\fR operation can be used to step through all the marks\nin a text widget in the same order as the mark information returned by the\n\\fIpathName \\fBdump\\fR operation. If a mark has been set to the special\n\\fBend\\fR index, then it appears to be \\fIafter \\fBend\\fR with respect to\nthe \\fIpathName \\fBmark next\\fR operation. An empty string is returned if\nthere are no marks after \\fIindex\\fR.\n.TP\n\\fIpathName \\fBmark previous \\fIindex\\fR\n.\nReturns the name of the mark at or before \\fIindex\\fR. If \\fIindex\\fR is\nspecified in numerical form, then the search for the previous mark begins with\nthe character just before that index. If \\fIindex\\fR is the name of a mark,\nthen the search for the next mark begins immediately before that mark. This\ncan still return a mark at the same position if there are multiple marks at\nthe same index. These semantics mean that the \\fIpathName \\fBmark previous\\fR\noperation can be used to step through all the marks in a text widget in the\nreverse order as the mark information returned by the \\fIpathName \\fBdump\\fR\noperation. An empty string is returned if there are no marks before\n\\fIindex\\fR.\n.TP\n\\fIpathName \\fBmark set \\fImarkName index\\fR\n.\nSets the mark named \\fImarkName\\fR to a position just before the character at\n\\fIindex\\fR. If \\fImarkName\\fR already exists, it is moved from its old\nposition; if it does not exist, a new mark is created. This command returns an\nempty string.\n.TP\n\\fIpathName \\fBmark unset \\fImarkName \\fR?\\fImarkName markName ...\\fR?\n.\nRemove the mark corresponding to each of the \\fImarkName\\fR arguments. The\nremoved marks will not be usable in indices and will not be returned by future\ncalls to\n.QW \"\\fIpathName \\fBmark names\\fR\" .\nThis command returns an empty string.\n.RE\n.\\\" METHOD: peer\n.TP\n\\fIpathName \\fBpeer \\fIoption args\\fR\n.\nThis command is used to create and query widget peers. It has two forms,\ndepending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBpeer create \\fInewPathName\\fR ?\\fIoptions\\fR?\n.\nCreates a peer text widget with the given \\fInewPathName\\fR, and any optional\nstandard configuration options (as for the \\fItext\\fR command). By default the\npeer will have the same start and end line as the parent widget, but these can\nbe overridden with the standard configuration options.\n.TP\n\\fIpathName \\fBpeer names\\fR\n.\nReturns a list of peers of this widget (this does not include the widget\nitself). The order within this list is undefined.\n.RE\n.\\\" METHOD: pendingsync\n.TP\n\\fIpathName \\fBpendingsync\\fR\n.\nReturns 1 if the line heights calculations are not up-to-date, 0 otherwise.\n.\\\" METHOD: replace\n.TP\n\\fIpathName \\fBreplace\\fI index1 index2 chars\\fR ?\\fItagList chars tagList ...\\fR?\n.\nReplaces the range of characters between \\fIindex1\\fR and \\fIindex2\\fR\nwith the given characters and tags.  See the section on \\fIpathName\n\\fBinsert\\fR for an explanation of the handling of the \\fItagList...\\fR\narguments, and the section on \\fIpathName\n\\fBdelete\\fR for an explanation of the handling of the indices.  If\n\\fIindex2\\fR corresponds to an index earlier in the text than\n\\fIindex1\\fR, an error will be generated.\n.RS\n.PP\nThe deletion and insertion are arranged so that no unnecessary scrolling of\nthe window or movement of insertion cursor occurs. In addition the undo/redo\nstack are correctly modified, if undo operations are active in the text\nwidget. The command returns an empty string.\n.RE\n.\\\" METHOD: scan\n.TP\n\\fIpathName \\fBscan \\fIoption args\\fR\n.\nThis command is used to implement scanning on texts. It has two forms,\ndepending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBscan mark \\fIx y\\fR\n.\nRecords \\fIx\\fR and \\fIy\\fR and the current view in the text window, for use\nin conjunction with later \\fIpathName \\fBscan dragto\\fR commands. Typically\nthis command is associated with a mouse button press in the widget. It returns\nan empty string.\n.TP\n\\fIpathName \\fBscan dragto \\fIx y\\fR\n.\nThis command computes the difference between its \\fIx\\fR and \\fIy\\fR arguments\nand the \\fIx\\fR and \\fIy\\fR arguments to the last \\fIpathName \\fBscan mark\\fR\ncommand for the widget. It then adjusts the view by 10 times the difference in\ncoordinates. This command is typically associated with mouse motion events in\nthe widget, to produce the effect of dragging the text at high speed through\nthe window. The return value is an empty string.\n.RE\n.\\\" METHOD: search\n.TP\n\\fIpathName \\fBsearch \\fR?\\fIswitches\\fR? \\fIpattern index \\fR?\\fIstopIndex\\fR?\n.\nSearches the text in \\fIpathName\\fR starting at \\fIindex\\fR for a range of\ncharacters that matches \\fIpattern\\fR. If a match is found, the index of the\nfirst character in the match is returned as result; otherwise an empty string\nis returned. One or more of the following switches (or abbreviations thereof)\nmay be specified to control the search:\n.RS\n.\\\" OPTION: -forwards\n.TP\n\\fB\\-forwards\\fR\n.\nThe search will proceed forward through the text, finding the first matching\nrange starting at or after the position given by \\fIindex\\fR. This is the\ndefault.\n.\\\" OPTION: -backwards\n.TP\n\\fB\\-backwards\\fR\n.\nThe search will proceed backward through the text, finding the matching range\nclosest to \\fIindex\\fR whose first character is before \\fIindex\\fR (it is not\nallowed to be at \\fIindex\\fR). Note that, for a variety of reasons, backwards\nsearches can be substantially slower than forwards searches (particularly when\nusing \\fB\\-regexp\\fR), so it is recommended that performance-critical code use\nforward searches.\n.\\\" OPTION: -exact\n.TP\n\\fB\\-exact\\fR\n.\nUse exact matching: the characters in the matching range must be identical to\nthose in \\fIpattern\\fR. This is the default.\n.\\\" OPTION: -regexp\n.TP\n\\fB\\-regexp\\fR\n.\nTreat \\fIpattern\\fR as a regular expression and match it against the text\nusing the rules for regular expressions (see the \\fBregexp\\fR command\nand the \\fBre_syntax\\fR page for\ndetails). The default matching automatically passes both the\n\\fB\\-lineanchor\\fR and \\fB\\-linestop\\fR options to the regexp engine (unless\n\\fB\\-nolinestop\\fR is used), so that \\fI^$\\fR match beginning and end of line,\nand \\fI.\\fR, \\fI[^\\fR sequences will never match the newline character\n\\fI\\en\\fR.\n.\\\" OPTION: -nolinestop\n.TP\n\\fB\\-nolinestop\\fR\n.\nThis allows \\fI.\\fR and \\fI[^\\fR sequences to match the newline character\n\\fI\\en\\fR, which they will otherwise not do (see the \\fBregexp\\fR command for\ndetails). This option is only meaningful if \\fB\\-regexp\\fR is also given, and\nan error will be thrown otherwise. For example, to match the entire text, use\n.QW \"\\fIpathName \\fBsearch \\-nolinestop \\-regexp\\fR \\N'34'.*\\N'34' 1.0\" .\n.\\\" OPTION: -nocase\n.TP\n\\fB\\-nocase\\fR\n.\nIgnore case differences between the pattern and the text.\n.\\\" OPTION: -count\n.TP\n\\fB\\-count\\fI varName\\fR\n.\nThe argument following \\fB\\-count\\fR gives the name of a variable; if a match\nis found, the number of index positions between beginning and end of the\nmatching range will be stored in the variable. If there are no embedded images\nor windows in the matching range (and there are no elided characters if\n\\fB\\-elide\\fR is not given), this is equivalent to the number of characters\nmatched. In either case, the range \\fImatchIdx\\fR to \\fImatchIdx + $count\nchars\\fR will return the entire matched text.\n.\\\" OPTION: -all\n.TP\n\\fB\\-all\\fR\n.\nFind all matches in the given range and return a list of the indices of the\nfirst character of each match. If a \\fB\\-count\\fI varName\\fR switch is given,\nthen \\fIvarName\\fR is also set to a list containing one element for each\nsuccessful match. Note that, even for exact searches, the elements of this\nlist may be different, if there are embedded images, windows or hidden text.\nSearches with \\fB\\-all\\fR behave very similarly to the Tcl command \\fBregexp\n\\-all\\fR, in that overlapping matches are not normally returned. For example,\napplying an \\fB\\-all\\fR search of the pattern\n.QW \\ew+\nagainst\n.QW \"hello there\"\nwill just match twice, once for each word, and matching\n.QW \"Z[a\\-z]+Z\"\nagainst\n.QW ZooZooZoo\nwill just match once.\n.\\\" OPTION: -overlap\n.TP\n\\fB\\-overlap\\fR\n.\nWhen performing \\fB\\-all\\fR searches, the normal behaviour is that matches\nwhich overlap an already-found match will not be returned. This switch changes\nthat behaviour so that all matches which are not totally enclosed within\nanother match are returned. For example, applying an \\fB\\-overlap\\fR search of\nthe pattern\n.QW \\ew+\nagainst\n.QW \"hello there\"\nwill just match twice (i.e. no different to just \\fB\\-all\\fR), but matching\n.QW Z[a\\-z]+Z\nagainst\n.QW ZooZooZoo\nwill now match twice. An error will be thrown if this switch is used without\n\\fB\\-all\\fR.\n.\\\" OPTION: -strictlimits\n.TP\n\\fB\\-strictlimits\\fR\n.\nWhen performing any search, the normal behaviour is that the start and stop\nlimits are checked with respect to the start of the matching text. With the\n\\fB\\-strictlimits\\fR flag, the entire matching range must lie inside the start\nand stop limits specified for the match to be valid.\n.\\\" OPTION: -elide\n.TP\n\\fB\\-elide\\fR\n.\nFind elided (hidden) text as well. By default only displayed text is searched.\n.\\\" OPTION: --\n.TP\n\\fB\\-\\|\\-\\fR\n.\nThis switch has no effect except to terminate the list of switches: the next\nargument will be treated as \\fIpattern\\fR even if it starts with \\fB\\-\\fR.\n.PP\nThe matching range may be within a single line of text, or run across multiple\nlines (if parts of the pattern can match a new-line). For regular expression\nmatching one can use the various newline-matching features such as \\fB$\\fR to\nmatch the end of a line, \\fB^\\fR to match the beginning of a line, and to\ncontrol whether \\fB.\\fR is allowed to match a new-line. If \\fIstopIndex\\fR is\nspecified, the search stops at that index: for forward searches, no match at\nor after \\fIstopIndex\\fR will be considered; for backward searches, no match\nearlier in the text than \\fIstopIndex\\fR will be considered. If\n\\fIstopIndex\\fR is omitted, the entire text will be searched: when the\nbeginning or end of the text is reached, the search continues at the other end\nuntil the starting location is reached again; if \\fIstopIndex\\fR is specified,\nno wrap-around will occur. This means that, for example, if the search is\n\\fB\\-forwards\\fR but \\fIstopIndex\\fR is earlier in the text than\n\\fIstartIndex\\fR, nothing will ever be found. See \\fBKNOWN BUGS\\fR below for a\nnumber of minor limitations of the \\fIpathName \\fBsearch\\fR command.\n.RE\n.\\\" METHOD: see\n.TP\n\\fIpathName \\fBsee \\fIindex\\fR\n.\nAdjusts the view in the window so that the character given by \\fIindex\\fR is\ncompletely visible. If \\fIindex\\fR is already visible then the command does\nnothing. If \\fIindex\\fR is a short distance out of view, the command adjusts\nthe view just enough to make \\fIindex\\fR visible at the edge of the window.\nIf \\fIindex\\fR is far out of view, then the command centers \\fIindex\\fR in the\nwindow.\n.\\\" METHOD: sync\n.TP\n\\fIpathName \\fBsync\\fR ?\\fB\\-command \\fIcommand\\fR?\n.\nControls the synchronization of the view of the text widget.\n.RS\n.TP\n\\fIpathName \\fBsync\\fR\n.\nImmediately brings the line metrics up-to-date by forcing computation of any\noutdated line heights. The command returns immediately if there is no such\noutdated line heights, otherwise it returns only at the end of the computation.\nThe command returns an empty string.\n.TP\n\\fIpathName \\fBsync \\-command \\fIcommand\\fR\n.\nSchedules \\fIcommand\\fR to be executed (by the event loop) exactly once as soon\nas all line heights are up-to-date. If there are no pending line metrics\ncalculations, the scheduling is immediate. The command returns the empty\nstring. \\fBbgerror\\fR is called on \\fIcommand\\fR failure.\n.RE\n.\\\" METHOD: tag\n.TP\n\\fIpathName \\fBtag \\fIoption \\fR?\\fIarg ...\\fR?\n.\nThis command is used to manipulate tags. The exact behavior of the command\ndepends on the \\fIoption\\fR argument that follows the \\fBtag\\fR argument. The\nfollowing forms of the command are currently supported:\n.RS\n.TP\n\\fIpathName \\fBtag add \\fItagName index1 \\fR?\\fIindex2 index1 index2 ...\\fR?\n.\nAssociate the tag \\fItagName\\fR with all of the characters starting with\n\\fIindex1\\fR and ending just before \\fIindex2\\fR (the character at\n\\fIindex2\\fR is not tagged). A single command may contain any number of\n\\fIindex1\\fR\\-\\fIindex2\\fR pairs. If the last \\fIindex2\\fR is omitted then the\nsingle character at \\fIindex1\\fR is tagged. If there are no characters in the\nspecified range (e.g. \\fIindex1\\fR is past the end of the file or \\fIindex2\\fR\nis less than or equal to \\fIindex1\\fR) then the command has no effect.\n.TP\n\\fIpathName \\fBtag bind \\fItagName\\fR ?\\fIsequence\\fR? ?\\fIscript\\fR?\n.\nThis command associates \\fIscript\\fR with the tag given by \\fItagName\\fR.\nWhenever the event sequence given by \\fIsequence\\fR occurs for a character\nthat has been tagged with \\fItagName\\fR, the script will be invoked. This\nwidget command is similar to the \\fBbind\\fR command except that it operates on\ncharacters in a text rather than entire widgets. See the \\fBbind\\fR manual\nentry for complete details on the syntax of \\fIsequence\\fR and the\nsubstitutions performed on \\fIscript\\fR before invoking it. If all arguments\nare specified then a new binding is created, replacing any existing binding\nfor the same \\fIsequence\\fR and \\fItagName\\fR (if the first character of\n\\fIscript\\fR is\n.QW +\nthen \\fIscript\\fR augments an existing binding rather than replacing it). In\nthis case the return value is an empty string. If \\fIscript\\fR is omitted then\nthe command returns the \\fIscript\\fR associated with \\fItagName\\fR and\n\\fIsequence\\fR (an error occurs if there is no such binding). If both\n\\fIscript\\fR and \\fIsequence\\fR are omitted then the command returns a list of\nall the sequences for which bindings have been defined for \\fItagName\\fR.\n.RS\n.PP\nThe only events for which bindings may be specified are those related to the\nmouse and keyboard (such as \\fBEnter\\fR, \\fBLeave\\fR, \\fBButton\\fR,\n\\fBMotion\\fR, and \\fBKey\\fR) or virtual events. Mouse and keyboard event\nbindings for a text widget respectively use the \\fBcurrent\\fR and \\fBinsert\\fR\nmarks described under \\fBMARKS\\fR above. An\n\\fBEnter\\fR event triggers for a tag when the tag first becomes present on the\ncurrent character, and a \\fBLeave\\fR event triggers for a tag when it ceases\nto be present on the current character. \\fBEnter\\fR and \\fBLeave\\fR events can\nhappen either because the \\fBcurrent\\fR mark moved or because the character at\nthat position changed. Note that these events are different than \\fBEnter\\fR\nand \\fBLeave\\fR events for windows. Mouse events are directed to the current\ncharacter, while keyboard events are directed to the insert character.\nIf a virtual event is used in a binding, that binding\ncan trigger only if the virtual event is defined by an underlying\nmouse-related or keyboard-related event.\n.PP\nIt is possible for the current character to have multiple tags, and for each\nof them to have a binding for a particular event sequence. When this occurs,\none binding is invoked for each tag, in order from lowest-priority to highest\npriority. If there are multiple matching bindings for a single tag, then the\nmost specific binding is chosen (see the manual entry for the \\fBbind\\fR\ncommand for details). \\fBcontinue\\fR and \\fBbreak\\fR commands within binding\nscripts are processed in the same way as for bindings created with the\n\\fBbind\\fR command.\n.PP\nIf bindings are created for the widget as a whole using the \\fBbind\\fR\ncommand, then those bindings will supplement the tag bindings. The tag\nbindings will be invoked first, followed by bindings for the window as a\nwhole.\n.RE\n.TP\n\\fIpathName \\fBtag cget \\fItagName option\\fR\n.\nThis command returns the current value of the option named \\fIoption\\fR\nassociated with the tag given by \\fItagName\\fR. \\fIOption\\fR may have any of\nthe values accepted by the \\fIpathName \\fBtag configure\\fR widget command.\n.TP\n\\fIpathName \\fBtag configure \\fItagName\\fR ?\\fIoption\\fR? ?\\fIvalue\\fR? ?\\fIoption value ...\\fR?\n.\nThis command is similar to the \\fIpathName \\fBconfigure\\fR widget command\nexcept that it modifies options associated with the tag given by \\fItagName\\fR\ninstead of modifying options for the overall text widget. If no \\fIoption\\fR\nis specified, the command returns a list describing all of the available\noptions for \\fItagName\\fR (see \\fBTk_ConfigureInfo\\fR for information on the\nformat of this list). If \\fIoption\\fR is specified with no \\fIvalue\\fR, then\nthe command returns a list describing the one named option (this list will be\nidentical to the corresponding sublist of the value returned if no\n\\fIoption\\fR is specified). If one or more \\fIoption\\-value\\fR pairs are\nspecified, then the command modifies the given option(s) to have the given\nvalue(s) in \\fItagName\\fR; in this case the command returns an empty string.\nSee \\fBTAGS\\fR above for details on the options available for tags.\n.TP\n\\fIpathName \\fBtag delete \\fItagName \\fR?\\fItagName ...\\fR?\n.\nDeletes all tag information for each of the \\fItagName\\fR arguments. The\ncommand removes the tags from all characters in the file and also deletes any\nother information associated with the tags, such as bindings and display\ninformation. The command returns an empty string.\n.TP\n\\fIpathName\\fB tag lower \\fItagName \\fR?\\fIbelowThis\\fR?\n.\nChanges the priority of tag \\fItagName\\fR so that it is just lower in priority\nthan the tag whose name is \\fIbelowThis\\fR. If \\fIbelowThis\\fR is omitted,\nthen \\fItagName\\fR's priority is changed to make it lowest priority of all\ntags.\n.TP\n\\fIpathName \\fBtag names \\fR?\\fIindex\\fR?\n.\nReturns a list whose elements are the names of all the tags that are active at\nthe character position given by \\fIindex\\fR. If \\fIindex\\fR is omitted, then\nthe return value will describe all of the tags that exist for the text (this\nincludes all tags that have been named in a\n.QW \"\\fIpathName \\fBtag\\fR\"\nwidget command but have not been deleted by a\n.QW \"\\fIpathName \\fBtag delete\\fR\"\nwidget command, even if no characters are currently marked with the tag). The\nlist will be sorted in order from lowest priority to highest priority.\n.TP\n\\fIpathName \\fBtag nextrange \\fItagName index1 \\fR?\\fIindex2\\fR?\n.\nThis command searches the text for a range of characters tagged with\n\\fItagName\\fR where the first character of the range is no earlier than the\ncharacter at \\fIindex1\\fR and no later than the character just before\n\\fIindex2\\fR (a range starting at \\fIindex2\\fR will not be considered). If\nseveral matching ranges exist, the first one is chosen. The command's return\nvalue is a list containing two elements, which are the index of the first\ncharacter of the range and the index of the character just after the last one\nin the range. If no matching range is found then the return value is an empty\nstring. If \\fIindex2\\fR is not given then it defaults to the end of the text.\n.TP\n\\fIpathName \\fBtag prevrange \\fItagName index1 \\fR?\\fIindex2\\fR?\n.\nThis command searches the text for a range of characters tagged with\n\\fItagName\\fR where the first character of the range is before the character\nat \\fIindex1\\fR and no earlier than the character at \\fIindex2\\fR (a range\nstarting at \\fIindex2\\fR will be considered). If several matching ranges\nexist, the one closest to \\fIindex1\\fR is chosen. The command's return value\nis a list containing two elements, which are the index of the first character\nof the range and the index of the character just after the last one in the\nrange. If no matching range is found then the return value is an empty string.\nIf \\fIindex2\\fR is not given then it defaults to the beginning of the text.\n.TP\n\\fIpathName \\fBtag raise \\fItagName \\fR?\\fIaboveThis\\fR?\n.\nChanges the priority of tag \\fItagName\\fR so that it is just higher in\npriority than the tag whose name is \\fIaboveThis\\fR. If \\fIaboveThis\\fR is\nomitted, then \\fItagName\\fR's priority is changed to make it highest priority\nof all tags.\n.TP\n\\fIpathName \\fBtag ranges \\fItagName\\fR\n.\nReturns a list describing all of the ranges of text that have been tagged with\n\\fItagName\\fR. The first two elements of the list describe the first tagged\nrange in the text, the next two elements describe the second range, and so on.\nThe first element of each pair contains the index of the first character of\nthe range, and the second element of the pair contains the index of the\ncharacter just after the last one in the range. If there are no characters\ntagged with \\fItag\\fR then an empty string is returned.\n.TP\n\\fIpathName \\fBtag remove \\fItagName index1 \\fR?\\fIindex2 index1 index2 ...\\fR?\n.\nRemove the tag \\fItagName\\fR from all of the characters starting at\n\\fIindex1\\fR and ending just before \\fIindex2\\fR (the character at\n\\fIindex2\\fR is not affected). A single command may contain any number of\n\\fIindex1\\fR\\-\\fIindex2\\fR pairs. If the last \\fIindex2\\fR is omitted then the\ntag is removed from the single character at \\fIindex1\\fR. If there are no\ncharacters in the specified range (e.g. \\fIindex1\\fR is past the end of the\nfile or \\fIindex2\\fR is less than or equal to \\fIindex1\\fR) then the command\nhas no effect. This command returns an empty string.\n.RE\n.\\\" METHOD: window\n.TP\n\\fIpathName \\fBwindow \\fIoption \\fR?\\fIarg ...\\fR?\n.\nThis command is used to manipulate embedded windows. The behavior of the\ncommand depends on the \\fIoption\\fR argument that follows the \\fBwindow\\fR\nargument. The following forms of the command are currently supported:\n.RS\n.TP\n\\fIpathName \\fBwindow cget \\fIindex option\\fR\n.\nReturns the value of a configuration option for an embedded window.\n\\fIIndex\\fR identifies the embedded window, and \\fIoption\\fR specifies a\nparticular configuration option, which must be one of the ones listed in the\nsection \\fBEMBEDDED WINDOWS\\fR.\n.TP\n\\fIpathName \\fBwindow configure \\fIindex\\fR ?\\fIoption value ...\\fR?\n.\nQuery or modify the configuration options for an embedded window. If no\n\\fIoption\\fR is specified, returns a list describing all of the available\noptions for the embedded window at \\fIindex\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list). If \\fIoption\\fR is specified with no\n\\fIvalue\\fR, then the command returns a list describing the one named option\n(this list will be identical to the corresponding sublist of the value\nreturned if no \\fIoption\\fR is specified). If one or more \\fIoption\\-value\\fR\npairs are specified, then the command modifies the given option(s) to have the\ngiven value(s); in this case the command returns an empty string. See\n\\fBEMBEDDED WINDOWS\\fR for information on the options that are supported.\n.TP\n\\fIpathName \\fBwindow create \\fIindex\\fR ?\\fIoption value ...\\fR?\n.\nThis command creates a new window annotation, which will appear in the text at\nthe position given by \\fIindex\\fR. Any number of \\fIoption\\-value\\fR pairs may\nbe specified to configure the annotation. See \\fBEMBEDDED WINDOWS\\fR for\ninformation on the options that are supported. Returns an empty string.\n.TP\n\\fIpathName \\fBwindow names\\fR\n.\nReturns a list whose elements are the names of all windows currently embedded\nin \\fIwindow\\fR.\n.RE\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fIoption args\\fR\n.\nThis command is used to query and change the horizontal position of the text\nin the widget's window. It can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements. Each element is a real fraction\nbetween 0 and 1; together they describe the portion of the document's\nhorizontal span that is visible in the window. For example, if the first\nelement is .2 and the second element is .6, 20% of the text is off-screen to\nthe left, the middle 40% is visible in the window, and 40% of the text is\noff-screen to the right. The fractions refer only to the lines that are\nactually visible in the window: if the lines in the window are all very short,\nso that they are entirely visible, the returned fractions will be 0 and 1,\neven if there are other lines in the text that are much wider than the window.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that \\fIfraction\\fR of the horizontal span\nof the text is off-screen to the left. \\fIFraction\\fR is a fraction between 0\nand 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR. \\fIWhat\\fR must be \\fBpages\\fR,\n\\fBpixels\\fR, or \\fBunits\\fR. If \\fIwhat\\fR is \\fBpages\\fR or\n\\fBunits\\fR then \\fInumber\\fR must be an integer, otherwise number may be\nspecified in any of the forms acceptable to \\fBTk_GetPixels\\fR, such as\n.QW 2.0c\nor\n.QW 1i\n(the result is rounded to the nearest integer value. If no units are given,\npixels are assumed). If \\fIwhat\\fR is \\fBpages\\fR then the view adjusts by\n\\fInumber\\fR screenfuls; if it is \\fBpixels\\fR then the view adjusts by\n\\fInumber\\fR pixels; if it is \\fBunits\\fR, the view adjusts left or\nright by \\fInumber\\fR average-width characters on the display. If \\fInumber\\fR is\nnegative then characters farther to the left become visible; if it is positive\nthen characters farther to the right become visible.\n.RE\n.\\\" METHOD: yview\n.TP\n\\fIpathName \\fByview \\fR?\\fIargs\\fR?\n.\nThis command is used to query and change the vertical position of the text in\nthe widget's window. It can take any of the following forms:\n.RS\n.TP\n\\fIpathName \\fByview\\fR\n.\nReturns a list containing two elements, both of which are real fractions\nbetween 0 and 1. The first element gives the position of the first visible\npixel of the first character (or image, etc) in the top line in the window,\nrelative to the text as a whole (0.5 means it is halfway through the text, for\nexample). The second element gives the position of the first pixel just after\nthe last visible one in the bottom line of the window, relative to the text as\na whole. These are the same values passed to scrollbars via the\n\\fB\\-yscrollcommand\\fR option.\n.TP\n\\fIpathName \\fByview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the pixel given by \\fIfraction\\fR\nappears at the top of the top line of the window. \\fIFraction\\fR is a fraction\nbetween 0 and 1; 0 indicates the first pixel of the first character in the\ntext, 0.33 indicates the pixel that is one-third the way through the text; and\nso on. Values close to 1 will indicate values close to the last pixel in the\ntext (1 actually refers to one pixel beyond the last pixel), but in such cases\nthe widget will never scroll beyond the last pixel, and so a value of 1 will\neffectively be rounded back to whatever fraction ensures the last pixel is at\nthe bottom of the window, and some other pixel is at the top.\n.TP\n\\fIpathName \\fByview scroll \\fInumber what\\fR\n.\nThis command adjust the view in the window up or down according to\n\\fInumber\\fR and \\fIwhat\\fR. \\fIWhat\\fR must be \\fBpages\\fR,\n\\fBpixels\\fR, or \\fBunits\\fR. If \\fIwhat\\fR is \\fBunits\\fR or \\fBpages\\fR then\n\\fInumber\\fR must be an integer, otherwise number may be specified in any of\nthe forms acceptable to \\fBTk_GetPixels\\fR, such as\n.QW 2.0c\nor\n.QW 1i\n(the result is rounded to the nearest integer value. If no units are given,\npixels are assumed). If \\fIwhat\\fR is \\fBunits\\fR, the view adjusts up or down\nby \\fInumber\\fR lines on the display; if it is \\fBpages\\fR then the view\nadjusts by \\fInumber\\fR screenfuls; if it is \\fBpixels\\fR then the view\nadjusts by \\fInumber\\fR pixels. If \\fInumber\\fR is negative then earlier\npositions in the text become visible; if it is positive then later positions\nin the text become visible.\n.TP\n\\fIpathName \\fByview \\fR?\\fB\\-pickplace\\fR? \\fIindex\\fR\n.\nChanges the view in the widget's window to make \\fIindex\\fR visible. If the\n\\fB\\-pickplace\\fR option is not specified then \\fIindex\\fR will appear at the\ntop of the window. If \\fB\\-pickplace\\fR is specified then the widget chooses\nwhere \\fIindex\\fR appears in the window:\n.RS\n.IP [1]\nIf \\fIindex\\fR is already visible somewhere in the window then the command\ndoes nothing.\n.IP [2]\nIf \\fIindex\\fR is only a few lines off-screen above the window then it will be\npositioned at the top of the window.\n.IP [3]\nIf \\fIindex\\fR is only a few lines off-screen below the window then it will be\npositioned at the bottom of the window.\n.IP [4]\nOtherwise, \\fIindex\\fR will be centered in the window.\n.PP\nThe \\fB\\-pickplace\\fR option has been obsoleted by the \\fIpathName \\fBsee\\fR\nwidget command (\\fIpathName \\fBsee\\fR handles both x- and y-motion to make a\nlocation visible, whereas the \\fB\\-pickplace\\fR mode only handles motion in\ny).\n.RE\n.TP\n\\fIpathName \\fByview \\fInumber\\fR\n.\nThis command makes the first character on the line after the one given by\n\\fInumber\\fR visible at the top of the window. \\fINumber\\fR must be an\ninteger. This command used to be used for scrolling, but now it is obsolete.\n.RE\n.SH BINDINGS\n.PP\nTk automatically creates class bindings for texts that give them the following\ndefault behavior.\nIn the descriptions below,\n.QW word\nis dependent on the value of\nthe \\fBtcl_wordchars\\fR variable.  See \\fBtclvars\\fR(n).\n.IP [1]\nClicking mouse button 1 positions the insertion cursor at the closest edge of the\ncharacter underneath the mouse cursor, sets the input focus to this widget,\nand clears any selection in the widget. Dragging with mouse button 1 strokes\nout a selection between the insertion cursor and the character under the\nmouse.\n.IP [2]\nDouble-clicking with mouse button 1 selects the word under the mouse and\npositions the insertion cursor at the start of the word. Dragging after a\ndouble click will stroke out a selection consisting of whole words.\n.IP [3]\nTriple-clicking with mouse button 1 selects the line under the mouse and\npositions the insertion cursor at the start of the line. Dragging after a\ntriple click will stroke out a selection consisting of whole lines.\n.IP [4]\nThe ends of the selection can be adjusted by dragging with mouse button 1\nwhile the Shift key is down; this will adjust the end of the selection that\nwas nearest to the mouse cursor when button 1 was pressed. If the button is\ndouble-clicked before dragging then the selection will be adjusted in units of\nwhole words; if it is triple-clicked then the selection will be adjusted in\nunits of whole lines.\n.IP [5]\nClicking mouse button 1 with the Control key down will reposition the\ninsertion cursor without affecting the selection.\n.IP [6]\nIf any normal printing characters are typed, they are inserted at the point of\nthe insertion cursor.\n.IP [7]\nThe view in the widget can be adjusted by dragging with the middle mouse\nbutton (button 2, or button 3 in TkAqua). If the middle mouse button is\nclicked without moving the mouse, the selection is copied into the text at the\nposition of the mouse cursor. The Insert key also inserts the selection,\nbut at the position of the insertion cursor.\n.IP [8]\nIf the mouse is dragged out of the widget while button 1 is pressed, the entry\nwill automatically scroll to make more text visible (if there is more text\noff-screen on the side where the mouse left the window).\n.IP [9]\nThe Left and Right keys move the insertion cursor one character to the left or\nright; they also clear any selection in the text. If Left or Right is typed\nwith the Shift key down, then the insertion cursor moves and the selection is\nextended to include the new character. Control-Left and Control-Right move the\ninsertion cursor by words, and Control-Shift-Left and Control-Shift-Right move\nthe insertion cursor by words and also extend the selection. Control-b and\nControl-f behave the same as Left and Right, respectively. Meta-b and Meta-f\nbehave the same as Control-Left and Control-Right, respectively.\n.IP [10]\nThe Up and Down keys move the insertion cursor one line up or down and clear\nany selection in the text. If Up or Right is typed with the Shift key down,\nthen the insertion cursor moves and the selection is extended to include the\nnew character. Control-Up and Control-Down move the insertion cursor by\nparagraphs (groups of lines separated by blank lines), and Control-Shift-Up\nand Control-Shift-Down move the insertion cursor by paragraphs and also extend\nthe selection. Control-p and Control-n behave the same as Up and Down,\nrespectively.\n.IP [11]\nThe Next and Prior keys move the insertion cursor forward or backwards by one\nscreenful and clear any selection in the text. If the Shift key is held down\nwhile Next or Prior is typed, then the selection is extended to include the\nnew character.\n.IP [12]\nControl-Next and Control-Prior scroll the view right or left by one page\nwithout moving the insertion cursor or affecting the selection.\n.IP [13]\nHome and Control-a move the insertion cursor to the beginning of its display\nline and clear any selection in the widget. Shift-Home moves the insertion\ncursor to the beginning of the display line and also extends the selection to\nthat point.\n.IP [14]\nEnd and Control-e move the insertion cursor to the end of the display line and\nclear any selection in the widget. Shift-End moves the cursor to the end of\nthe display line and extends the selection to that point.\n.IP [15]\nControl-Home and Meta-< move the insertion cursor to the beginning of the text\nand clear any selection in the widget. Control-Shift-Home moves the insertion\ncursor to the beginning of the text and also extends the selection to that\npoint.\n.IP [16]\nControl-End and Meta-> move the insertion cursor to the end of the text and\nclear any selection in the widget. Control-Shift-End moves the cursor to the\nend of the text and extends the selection to that point.\n.IP [17]\nThe Select key and Control-Space set the selection anchor to the position of\nthe insertion cursor. They do not affect the current selection. Shift-Select\nand Control-Shift-Space adjust the selection to the current position of the\ninsertion cursor, selecting from the anchor to the insertion cursor if there\nwas not any selection previously.\n.IP [18]\nControl-/ selects the entire contents of the widget.\n.IP [19]\nControl-\\e clears any selection in the widget.\n.IP [20]\nThe F16 key (labelled Copy on many Sun workstations) or Meta-w copies the\nselection in the widget to the clipboard, if there is a selection. This\naction is carried out by the command \\fBtk_textCopy\\fR.\n.IP [21]\nThe F20 key (labelled Cut on many Sun workstations) or Control-w copies the\nselection in the widget to the clipboard and deletes the selection. This\naction is carried out by the command \\fBtk_textCut\\fR. If there is no\nselection in the widget then these keys have no effect.\n.IP [22]\nThe F18 key (labelled Paste on many Sun workstations) or Control-y inserts the\ncontents of the clipboard at the position of the insertion cursor. This action\nis carried out by the command \\fBtk_textPaste\\fR.\n.IP [23]\nThe Delete key deletes the selection, if there is one in the widget. If there\nis no selection, it deletes the character to the right of the insertion\ncursor.\n.IP [24]\nBackspace and Control-h delete the selection, if there is one in the widget.\nIf there is no selection, they delete the character to the left of the\ninsertion cursor.\n.IP [25]\nControl-d deletes the character to the right of the insertion cursor.\n.IP [26]\nMeta-d deletes the word to the right of the insertion cursor.\n.IP [27]\nControl-k deletes from the insertion cursor to the end of its line; if the\ninsertion cursor is already at the end of a line, then Control-k deletes the\nnewline character.\n.IP [28]\nControl-o opens a new line by inserting a newline character in front of the\ninsertion cursor without moving the insertion cursor.\n.IP [29]\nMeta-backspace and Meta-Delete delete the word to the left of the insertion\ncursor.\n.IP [30]\nControl-t reverses the order of the two characters to the right of the\ninsertion cursor.\n.IP [31]\nControl-x deletes whatever is selected in the text widget after copying it to\nthe clipboard.\n.IP [32]\nControl-z undoes the last edit action if the \\fB\\-undo\\fR option is true.\nDoes nothing otherwise.\n.IP [33]\nControl-Z (or Control-y on Windows) reapplies the last undone edit action if\nthe \\fB\\-undo\\fR option is true. Does nothing otherwise.\n.PP\nIf the widget is disabled using the \\fB\\-state\\fR option, then its view can\nstill be adjusted and text can still be selected, but no insertion cursor will\nbe displayed and no text modifications will take place.\n.PP\nThe behavior of texts can be changed by defining new bindings for individual\nwidgets or by redefining the class bindings.\n.SH \"KNOWN ISSUES\"\n.SS \"ISSUES CONCERNING CHARS AND INDICES\"\n.PP\nBefore Tk 8.5, the widget used the string\n.QW chars\nto refer to index positions (which included characters, embedded windows and\nembedded images). As of Tk 8.5 the text widget deals separately and correctly\nwith\n.QW chars\nand\n.QW indices .\nFor backwards compatibility, however, the index modifiers\n.QW \"+N chars\"\nand\n.QW \"\\-N chars\"\ncontinue to refer to indices. One must use any of the full forms\n.QW \"+N any chars\"\nor\n.QW \"\\-N any chars\"\netc. to refer to actual character indices. This confusion may be fixed in a\nfuture release by making the widget correctly interpret\n.QW \"+N chars\"\nas a synonym for\n.QW \"+N any chars\" .\n.SS \"PERFORMANCE ISSUES\"\n.PP\nText widgets should run efficiently under a variety of conditions. The text\nwidget uses about 2-3 bytes of main memory for each byte of text, so texts\ncontaining a megabyte or more should be practical on most workstations. Text\nis represented internally with a modified B-tree structure that makes\noperations relatively efficient even with large texts. Tags are included in\nthe B-tree structure in a way that allows tags to span large ranges or have\nmany disjoint smaller ranges without loss of efficiency. Marks are also\nimplemented in a way that allows large numbers of marks. In most cases it is\nfine to have large numbers of unique tags, or a tag that has many distinct\nranges.\n.PP\nOne performance problem can arise if you have hundreds or thousands of\ndifferent tags that all have the following characteristics: the first and last\nranges of each tag are near the beginning and end of the text, respectively,\nor a single tag range covers most of the text widget. The cost of adding and\ndeleting tags like this is proportional to the number of other tags with the\nsame properties. In contrast, there is no problem with having thousands of\ndistinct tags if their overall ranges are localized and spread uniformly\nthroughout the text.\n.PP\nVery long text lines can be expensive, especially if they have many marks and\ntags within them.\n.PP\nThe display line with the insert cursor is redrawn each time the cursor\nblinks, which causes a steady stream of graphics traffic. Set the\n\\fB\\-insertofftime\\fR attribute to 0 avoid this.\n.SS \"KNOWN BUGS\"\n.PP\nThe \\fIpathName \\fBsearch \\-regexp\\fR sub-command attempts to perform\nsophisticated regexp matching across multiple lines in an efficient fashion\n(since Tk 8.5), examining each line individually, and then in small groups of\nlines, whether searching forwards or backwards. Under certain conditions the\nsearch result might differ from that obtained by applying the same regexp to\nthe entire text from the widget in one go. For example, when searching with a\ngreedy regexp, the widget will continue to attempt to add extra lines to the\nmatch as long as one of two conditions are true: either Tcl's regexp library\nreturns a code to indicate a longer match is possible (but there are known\nbugs in Tcl which mean this code is not always correctly returned); or if each\nextra line added results in at least a partial match with the pattern. This\nmeans in the case where the first extra line added results in no match and\nTcl's regexp system returns the incorrect code and adding a second extra line\nwould actually match, the text widget will return the wrong result. In\npractice this is a rare problem, but it can occur, for example:\n.CS\npack [\\fBtext\\fR .t]\n\\&.t insert 1.0 \"aaaa\\enbbbb\\encccc\\enbbbb\\enaaaa\\en\"\n\\&.t search -regexp -- {(a+|b+\\enc+\\enb+)+\\ena+} 1.0\n.CE\nwill not find a match when one exists of 19 characters starting from the first\n.QW b .\n.PP\nWhenever one possible match is fully enclosed in another, the search command\nwill attempt to ensure only the larger match is returned. When performing\nbackwards regexp searches it is possible that Tcl will not always achieve\nthis, in the case where a match is preceded by one or more short,\nnon-overlapping matches, all of which are preceded by a large match which\nactually encompasses all of them. The search algorithm used by the widget does\nnot look back arbitrarily far for a possible match which might cover large\nportions of the widget. For example:\n.CS\npack [\\fBtext\\fR .t]\n\\&.t insert 1.0 \"aaaa\\enbbbb\\enbbbb\\enbbbb\\enbbbb\\\\n\"\n\\&.t search -regexp -backward -- {b+\\en|a+\\en(b+\\en)+} end\n.CE\nmatches at\n.QW 5.0\nwhen a true greedy match would match at\n.QW 1.0 .\nSimilarly if we add \\fB\\-all\\fR to this case, it matches at all of\n.QW 5.0 ,\n.QW 4.0 ,\n.QW 3.0\nand\n.QW 1.0 ,\nwhen really it should only match at\n.QW 1.0\nsince that match encloses all the others.\n.SH \"SEE ALSO\"\nentry(n), scrollbar(n)\n.SH KEYWORDS\ntext, widget, tkvars\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/tk.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk \\- Manipulate Tk internal state\n.SH SYNOPSIS\n\\fBtk\\fI option \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtk\\fR command provides access to miscellaneous\nelements of Tk's internal state.\nMost of the information manipulated by this command pertains to the\napplication as a whole, or to a screen or display, rather than to a\nparticular window.\nThe command can take any of a number of different forms\ndepending on the \\fIoption\\fR argument.  The legal forms are:\n.\\\" METHOD: accessible\n.TP\n\\fBtk accessible \\fIsubcommand\\fR ...\n.\nThis command makes Tk widgets accessible to screen readers.\nFor\nmore details see the \\fBaccessible\\fR manual page.\n.\\\" METHOD: appname\n.TP\n\\fBtk appname \\fR?\\fInewName\\fR?\n.\nIf \\fInewName\\fR is not specified, this command returns the name\nof the application (the name that may be used in \\fBsend\\fR\ncommands to communicate with the application).\nIf \\fInewName\\fR is specified, then the name of the application\nis changed to \\fInewName\\fR.\nIf the given name is already in use, then a suffix of the form\n.QW \"\\fB #2\\fR\"\nor\n.QW \"\\fB #3\\fR\"\nis appended in order to make the name unique.\nThe command's result is the name actually chosen.\n\\fInewName\\fR should not start with a capital letter.\nThis will interfere with option processing, since names starting with\ncapitals are assumed to be classes;  as a result, Tk may not\nbe able to find some options for the application.\nIf sends have been disabled by deleting the \\fBsend\\fR command,\nthis command will reenable them and recreate the \\fBsend\\fR\ncommand.\n.\\\" METHOD: attribtable\n.TP\n\\fBtk attribtable \\fItableName\\fR\n.\nThis command creates an attribute table of the name \\fItableName\\fR as a\ncommand in the namespace of the calling context if not fully qualified.  An\nattribute table is used to query and modify arbitrary data attached to any\nwidget.  For more details see the \\fBattribtable\\fR manual page.\n.\\\" METHOD: busy\n.TP\n\\fBtk busy \\fIsubcommand\\fR ...\n.\nThis command controls the marking of window hierarchies as\n.QW busy ,\nrendering them non-interactive while some other operation is proceeding.  For\nmore details see the \\fBbusy\\fR manual page.\n.\\\" METHOD: caret\n.TP\n\\fBtk caret \\fIwindow \\fR?\\fB\\-x \\fIx\\fR? ?\\fB\\-y \\fIy\\fR? ?\\fB\\-height \\fIheight\\fR?\n.\nSets and queries the caret location for the display of the specified\nTk window \\fIwindow\\fR.  The caret is the per-display cursor location\nused for indicating global focus (e.g. to comply with Microsoft\nAccessibility guidelines), as well as for location of the over-the-spot\nXIM (X Input Methods) or Windows IME windows.  If no options are specified,\nthe last values used for setting the caret are return in option-value pair\nformat.  \\fB\\-x\\fR and \\fB\\-y\\fR represent window-relative coordinates, and\n\\fB\\-height\\fR is the height of the current cursor location, or the height\nof the specified \\fIwindow\\fR if none is given.\n.\\\" METHOD: inactive\n.TP\n\\fBtk inactive \\fR?\\fB\\-displayof \\fIwindow\\fR? ?\\fBreset\\fR?\n.\nReturns a positive integer, the number of milliseconds since the last\ntime the user interacted with the system.  If the \\fB\\-displayof\\fR\noption is given then the return value refers to the display of\n\\fIwindow\\fR; otherwise it refers to the display of the application's\nmain window.\n.RS\n.PP\n\\fBtk inactive\\fR will return \\-1, if querying the user inactive time\nis not supported by the system, and in safe interpreters.\n.PP\nIf the literal string \\fBreset\\fR is given as an additional argument,\nthe timer is reset and an empty string is returned.  Resetting the\ninactivity time is forbidden in safe interpreters and will throw an\nerror if tried.\n.RE\n.\\\" METHOD: fileicon\n.TP\n\\fBtk fileicon \\fIfile size\\fR\n.\nDisplays a system-native file icon.  For more details see the\n\\fBfileicon\\fR manual page.\n.\\\" METHOD: fontchooser\n.TP\n\\fBtk fontchooser \\fIsubcommand\\fR ...\n.\nControls the Tk font selection dialog.  For more details see the\n\\fBfontchooser\\fR manual page.\n.\\\" METHOD: print\n.TP\n\\fBtk print \\fIwindow\\fR\n.\nThe \\fBtk print\\fR command posts a dialog that allows users to print output\nfrom the \\fBcanvas\\fR and \\fBtext\\fR widgets.  The printing will be done using\nplatform-native APIs and dialogs where available.  For more details see the\n\\fBprint\\fR manual page.\n.\\\" METHOD: scaling\n.TP\n\\fBtk scaling \\fR?\\fB\\-displayof \\fIwindow\\fR? ?\\fInumber\\fR?\n.\nSets and queries the current scaling factor used by Tk to convert between\nphysical units (for example, points, inches, or millimeters) and pixels.  The\n\\fInumber\\fR argument is a floating point number that specifies the number of\npixels per point on \\fIwindow\\fR's display.  If the \\fIwindow\\fR argument is\nomitted, it defaults to the main window.  If the \\fInumber\\fR argument is\nomitted, the current value of the scaling factor is returned.\n.RS\n.PP\nA\n.QW point\nis a unit of measurement equal to 1/72 inch.  A scaling factor\nof 1.0 corresponds to 1 pixel per point, which is equivalent to a standard\n72 dpi monitor.  A scaling factor of 1.25 would mean 1.25 pixels per point,\nwhich is the setting for a 90 dpi monitor; setting the scaling factor to\n1.25 on a 72 dpi monitor would cause everything in the application to be\ndisplayed 1.25 times as large as normal.  The initial value for the scaling\nfactor is set when the application starts, based on properties of the\ninstalled monitor, but it can be changed at any time.  Measurements made\nafter the scaling factor is changed will use the new scaling factor, but it\nis undefined whether existing widgets will resize themselves dynamically to\naccommodate the new scaling factor.\n.RE\n.\\\" METHOD: sysnotify\n.TP\n\\fBtk sysnotify \\fItitle message\\fR\n.\nThe \\fBtk sysnotify\\fP  command creates a platform-specific system\nnotification alert.  Its intent is to provide a brief, unobtrusive\nnotification to the user by popping up a window that briefly appears in a\ncorner of the screen.  For more details see the \\fBsysnotify\\fR manual page.\n.\\\" METHOD: systray\n.TP\n\\fBtk systray \\fIsubcommand\\fR ...\n.\nThe \\fBtk systray\\fP command creates an icon in the platform-specific\ntray.  For more details see the \\fBsystray\\fR manual page.\n.\\\" METHOD: useinputmethods\n.TP\n\\fBtk useinputmethods \\fR?\\fB\\-displayof \\fIwindow\\fR? ?\\fIboolean\\fR?\n.\nSets and queries the state of whether Tk should use XIM (X Input Methods)\nfor filtering events.  The resulting state is returned.  XIM is used in\nsome locales (i.e., Japanese, Korean), to handle special input devices.  This\nfeature is only significant on X.  If XIM support is not available, this\nwill always return 0.  If the \\fIwindow\\fR argument is omitted, it defaults\nto the main window.  If the \\fIboolean\\fR argument is omitted, the current\nstate is returned.  This is turned on by default for the main display.\n.\\\" METHOD: windowingsystem\n.TP\n\\fBtk windowingsystem\\fR\n.\nReturns the current Tk windowing system, one of\n\\fBx11\\fR (X11-based), \\fBwin32\\fR (MS Windows),\nor \\fBaqua\\fR (macOS Aqua).\n.SH \"SEE ALSO\"\nattribtable(n), busy(n), fontchooser(n), print(n), send(n), sysnotify(n),\nsystray(n), winfo(n)\n.SH KEYWORDS\napplication name, attribute, print, send, sysnotify, systray\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/tk_mac.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2011 Kevin Walzer\n'\\\" Copyright (c) 2011 Donal K. Fellows\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tk::mac n 8.6 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntk::mac \\- Access Mac-Specific Functionality on macOS from Tk\n.SH SYNOPSIS\n.nf\n\\fB::tk::mac::DoScriptFile\\fR\n\\fB::tk::mac::DoScriptText\\fR\n\\fB::tk::mac::ShowPreferences\\fR\n\\fB::tk::mac::OpenApplication\\fR\n\\fB::tk::mac::ReopenApplication\\fR\n\\fB::tk::mac::OpenDocument \\fIfile...\\fR\n\\fB::tk::mac::PrintDocument \\fIfile...\\fR\n\\fB::tk::mac::Quit\\fR\n\\fB::tk::mac::OnHide\\fR\n\\fB::tk::mac::OnShow\\fR\n\\fB::tk::mac::ShowHelp\\fR\n\\fB::tk::mac::PerformService\\fR\n\\fB::tk::mac::LaunchURL \\fIURL...\\fR\n\\fB::tk::mac::GetAppPath\\fR\n\\fB::tk::mac::GetInfoAsJSON\\fR\n\n\\fB::tk::mac::standardAboutPanel\\fR\n\n\\fB::tk::mac::useCompatibilityMetrics \\fIboolean\\fR\n\\fB::tk::mac::CGAntialiasLimit \\fIlimit\\fR\n\\fB::tk::mac::antialiasedtext \\fInumber\\fR\n\\fB::tk::mac::useThemedToplevel \\fIboolean\\fR\n\n\\fB::tk::mac::iconBitmap \\fIname width height \\-kind value\\fR\n\n.fi\n.BE\n.SH \"EVENT HANDLER CALLBACKS\"\n.PP\nThe Aqua/macOS application environment defines a number of additional\nevents that applications should respond to. These events are mapped by Tk to\ncalls to commands in the \\fB::tk::mac\\fR namespace; unless otherwise noted, if\nthe command is absent, no action will be taken.\n.\\\" COMMAND: DoScriptFile\n.TP\n\\fB::tk::mac::DoScriptFile\\fR\n.\nThe default Apple Event handler for AEDoScriptHandler. This command\nexecutes a Tcl file when an AppleScript sends a\n.QW \"do script\"\ncommand to Wish with a file path as a parameter.\n.\\\" COMMAND: DoScriptText\n.TP\n\\fB::tk::mac::DoScriptText\\fR\n.\nThe default Apple Event handler for AEDoScriptHandler. This command\nexecutes Tcl code when an AppleScript sends a\n.QW \"do script\"\ncommand to Wish with Tcl code or a Tcl procedure as a parameter.\n.\\\" COMMAND: ShowPreferences\n.TP\n\\fB::tk::mac::ShowPreferences\\fR\n.\nThe default Apple Event handler for kAEShowPreferences,\n.QW pref .\nThe application menu\n.QW \"Preferences\"\nmenu item is only enabled when this proc is defined. Typically this command is\nused to wrap a specific own preferences command, which pops up a preferences\nwindow. Something like:\n.RS\n.PP\n.CS\nproc ::tk::mac::ShowPreferences {} {\n    setPref\n}\n.CE\n.RE\n.\\\" COMMAND: OpenApplication\n.TP\n\\fB::tk::mac::OpenApplication\\fR\n.\nIf a proc of this name is defined, this proc fill fire when your application\nis initially opened. It is the default Apple Event handler for\nkAEOpenApplication,\n.QW oapp .\n.\\\" COMMAND: ReopenApplication\n.TP\n\\fB::tk::mac::ReopenApplication\\fR\n.\nIf a proc of this name is defined it is the default Apple Event handler for\nkAEReopenApplication,\n.QW rapp ,\nthe Apple Event sent when your application is opened when it is already\nrunning (e.g. by clicking its icon in the Dock). Here is a sample that raises\na minimized window when the Dock icon is clicked:\n.RS\n.PP\n.CS\nproc ::tk::mac::ReopenApplication {} {\n    if {[wm state .] eq \"withdrawn\"} {\n        wm state . normal\n    } else {\n        wm deiconify .\n    }\n    raise .\n}\n.CE\n.RE\n.\\\" COMMAND: OpenDocument\n.TP\n\\fB::tk::mac::OpenDocument \\fIfile...\\fR\n.\nIf a proc of this name is defined it is the default Apple Event handler for\nkAEOpenDocuments,\n.QW odoc ,\nthe Apple Event sent when your application is asked to open one or more\ndocuments (e.g., by drag & drop onto the app or by opening a document of a\ntype associated to the app). The proc should take as arguments paths to the\nfiles to be opened, like so:\n.RS\n.PP\n.CS\nproc ::tk::mac::OpenDocument {args} {\n    foreach f $args {my_open_document $f}\n}\n.CE\n.RE\n.\\\" COMMAND: PrintDocument\n.TP\n\\fB::tk::mac::PrintDocument \\fIfile...\\fR\n.\nIf a proc of this name is defined it is the default Apple Event handler for\nkAEPrintDocuments,\n.QW pdoc ,\nthe Apple Event sent when your application is asked to print a\ndocument.  It takes a single absolute file path as an argument.\n.\\\" COMMAND: Quit\n.TP\n\\fB::tk::mac::Quit\\fR\n.\nIf a proc of this name is defined it is the default Apple Event handler for\nkAEQuitApplication,\n.QW quit ,\nthe Apple Event sent when your application is asked to be quit, e.g. via the\nquit menu item in the application menu, the quit menu item in the Dock menu,\nor during a logout/restart/shutdown etc. If this is not defined, \\fBexit\\fR is\ncalled instead.\n.\\\" COMMAND: OnHide\n.TP\n\\fB::tk::mac::OnHide\\fR\n.\nIf defined, this is called when your application receives a kEventAppHidden\nevent, e.g. via the hide menu item in the application or Dock menus.\n.\\\" COMMAND: OnShow\n.TP\n\\fB::tk::mac::OnShow\\fR\n.\nIf defined, this is called when your application receives a kEventAppShown\nevent, e.g. via the show all menu item in the application menu, or by clicking\nthe Dock icon of a hidden application.\n.\\\" COMMAND: ShowHelp\n.TP\n\\fB::tk::mac::ShowHelp\\fR\n.\nCustomizes behavior of Apple Help menu; if this procedure is not defined, the\nplatform-specific standard Help menu item\n.QW \"YourApp Help\"\nperforms the default Cocoa action of showing the Help Book configured in the\napplication's Info.plist (or displaying an alert if no Help Book is\nset).\n.\\\" COMMAND: PerformService\n.TP\n\\fB::tk::mac::PerformService\\fR\n.\nExecutes a Tcl procedure called from the macOS\n.QW Services\nmenu in the Application menu item. The\n.QW Services\nmenu item allows for inter-application communication; data from one\napplication, such as selected text, can be sent to another application\nfor processing, for example to Safari as a search item for Google, or\nto TextEdit to be appended to a file. An example of the proc is below,\nand should be rewritten in an application script for customization:\n.RS\n.PP\n.CS\nproc ::tk::mac::PerformService {} {\n    set data [clipboard get]\n    $w insert end $data\n}\n.CE\n.RE\nNote that the mechanism for retrieving the data is from the clipboard;\nthere is no other supported way to obtain the data.  If the Services\nprocess is not desired, the NSServices keys can be deleted from\nthe application's Info.plist file. The underlying code supporting this\ncommand also allows the text, entry and ttk::entry widgets to access\nservices from other applications via the Services menu. The NSPortName\nkey in Wish's Info.plist file is currently set as\n.QW \"Wish\"\n; if a developer changes the name of the Wish executable to something\n  else, this key should be modified with the same name.\n.\\\" COMMAND: LaunchURL\n.TP\n\\fB::tk::mac::LaunchURL \\fIURL...\\fR\n.\nIf defined, launches a URL within Tk. This would be used if a Tk\napplication wants to handle a URL itself, such as displaying data from\nan RSS feed, rather than launching a default application to handle the\nURL, although it can defined as such. Wish includes a stub URL scheme\nof\n.QW foo://\nin the CFBundleURLSchemes key of its Info.plist file; this should be\ncustomized for the specific URL scheme the developer wants to support.\n.TP\n\\fB::tk::mac::GetAppPath\\fR\n.\nReturns the current applications's file path.\n.TP\n\\fB::tk::mac::GetInfoAsJSON\\fR\n.\nReturns a JSON-encoded Tcl string which serializes the application's\n\\fBmainBundle.infoDictionary\\fR (defined by its \\fIInfo.plist\\fR file).\n.PP\n.SH \"ADDITIONAL DIALOGS\"\n.PP\nAqua/macOS defines additional dialogs that applications should\nsupport.\n.\\\" COMMAND: standardAboutPanel\n.TP\n\\fB::tk::mac::standardAboutPanel\\fR\n.\nBrings the standard Cocoa about panel to the front with information filled in\nfrom the application bundle files. The panel displays the application icon and\nthe values associated to the info.plist keys named CFBundleName,\nCFBundleShortVersionString, NSAboutPanelOptionVersion and\nNSHumanReadableCopyright.  If a file named \\fICredits.html\\fR or\n\\fICredits.rtf\\fR exists in the bundle's Resources directory then its contents\nwill be displayed in a scrolling text box at the bottom of the dialog. See the\ndocumentation for -[NSApplication orderFrontStandardAboutPanelWithOptions:]\nfor more details. A hook is also provided for a custom About dialog.  If a Tcl\nproc named tkAboutDialog is defined in the main interpreter then that\nprocedure will be called instead of opening the standardAboutPanel.\n.SH \"SYSTEM CONFIGURATION\"\n.PP\nThere are a number of additional global configuration options that control the\ndetails of how Tk renders by default.\n.\\\" COMMAND: useCompatibilityMetrics\n.TP\n\\fB::tk::mac::useCompatibilityMetrics \\fIboolean\\fR\n.\nPreserves compatibility with older Tk/Aqua metrics; set to \\fBfalse\\fR for\nmore native spacing.\n.\\\" COMMAND: CGAntialiasLimit\n.TP\n\\fB::tk::mac::CGAntialiasLimit \\fIlimit\\fR\n.\nSets the antialiasing limit; lines thinner that \\fIlimit\\fR pixels will not be\nantialiased. Integer, set to 0 by default, making all lines be antialiased.\n.\\\" COMMAND: antialiasedtext\n.TP\n\\fB::tk::mac::antialiasedtext \\fInumber\\fR\n.\nSets anti-aliased text.  Controls text antialiasing, possible values for\n\\fInumber\\fR are -1 (default, use system default for text AA), 0 (no text AA),\n1 (use text AA).\n.\\\" COMMAND: useThemedToplevel\n.TP\n\\fB::tk::mac::useThemedToplevel \\fIboolean\\fR\n.\nSets toplevel windows to draw with the modern grayish/ pinstripe Mac\nbackground. Equivalent to configuring the toplevel with\n.QW \"\\fB\\-background systemWindowHeaderBackground\\fR\" ,\nor to using a \\fBttk::frame\\fR.\n.SH \"SUPPORT COMMANDS\"\n.\\\" COMMAND: iconBitmap\n.TP\n\\fB::tk::mac::iconBitmap \\fIname width height \\-kind value\\fR\n.\nRenders native icons and bitmaps in Tk applications (including any image file\nreadable by NSImage). A native bitmap name is interpreted as follows (in\norder):\n.RS\n.IP \\(bu 3\npredefined builtin 32x32 icon name (\\fBstop\\fR, \\fBcaution\\fR, \\fBdocument\\fR,\netc.)\n.IP \\(bu 3\n\\fIname\\fR, as defined by \\fBtk::mac::iconBitmap\\fR\n.IP \\(bu 3\nNSImage named image name\n.IP \\(bu 3\nNSImage url string\n.IP \\(bu 3\n4-char OSType of IconServices icon\n.PP\nThe \\fIwidth\\fR and \\fIheight\\fR arguments to \\fBtk::mac::iconBitmap\\fR define\nthe dimensions of the image to create, and \\fI\\-kind\\fR must be one of:\n.\\\" OPTION: -file\n.TP\n\\fB\\-file\\fR\n.\nicon of file at given path\n.\\\" OPTION: -fileType\n.TP\n\\fB\\-fileType\\fR\n.\nicon of given file type\n.\\\" OPTION: -osType\n.TP\n\\fB\\-osType\\fR\n.\nicon of given 4-char OSType file type\n.\\\" OPTION: -systemType\n.TP\n\\fB\\-systemType\\fR\n.\nicon for given IconServices 4-char OSType\n.\\\" OPTION: -namedImage\n.TP\n\\fB\\-namedImage\\fR\n.\nnamed NSImage for given name\n.\\\" OPTION: -imageFile\n.TP\n\\fB\\-imageFile\\fR\n.\nimage at given path\n.RE\n.SH \"SEE ALSO\"\nbind(n), wm(n)\n.SH KEYWORDS\nabout dialog, antialiasing, Apple event, icon, NSImage\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/tkerror.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tkerror n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntkerror \\- Command invoked to process background errors\n.SH SYNOPSIS\n\\fBtkerror \\fImessage\\fR\n.BE\n.SH DESCRIPTION\n.PP\nNote: as of Tk 4.1 the \\fBtkerror\\fR command has been renamed to\n\\fBbgerror\\fR because the event loop (which is what usually invokes\nit) is now part of Tcl.  Using the \\fBtkerror\\fR name is deprecated.\n.PP\nFor backward compatibility\nthe \\fBbgerror\\fR provided by the current Tk version still\ntries to call \\fBtkerror\\fR if there is one (or an auto loadable one),\nso old script defining that error handler should still work, but you\nshould anyhow modify your scripts to use \\fBbgerror\\fR instead\nof \\fBtkerror\\fR because that support for the old name might vanish\nin the future. If that call fails, \\fBbgerror\\fR\nposts a dialog showing the error and offering to see the stack trace\nto the user. If you want your own error management you should\ndirectly override \\fBbgerror\\fR instead of \\fBtkerror\\fR.\nDocumentation for \\fBbgerror\\fR is available as part of Tcl's\ndocumentation.\n.SH KEYWORDS\nbackground error, reporting\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/tkvars.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tkvars n 4.1 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ngeometry, tk_library, tk_patchLevel, tk::scalingPct, tk_strictMotif, tk::svgFmt, tk_version \\- Variables used or set by Tk\n.BE\n.SH DESCRIPTION\n.PP\nThe following Tcl variables are either set or used by Tk at various times\nin its execution:\n.\\\" VARIABLE: tk_library\n.TP 15\n\\fBtk_library\\fR\n.\nThis variable holds the file name for a directory containing a library\nof Tcl scripts related to Tk.  These scripts include an initialization\nfile that is normally processed whenever a Tk application starts up,\nplus other files containing procedures that implement default behaviors\nfor widgets.\n.RS\n.PP\nThe initial value of \\fBtk_library\\fR is set when Tk is added to\nan interpreter;  this is done by searching several different directories\nuntil one is found that contains an appropriate Tk startup script.\nIf the \\fBTK_LIBRARY\\fR environment variable exists, then\nthe directory it names is checked first.\nIf \\fBTK_LIBRARY\\fR is not set or does not refer to an appropriate\ndirectory, then Tk checks several other directories based on a\ncompiled-in default location, the location of the Tcl library directory,\nthe location of the binary containing the application, and the current\nworking directory.\n.PP\nThe variable can be modified by an application to switch to a different\nlibrary.\n.RE\n.\\\" VARIABLE: tk_patchLevel\n.TP\n\\fBtk_patchLevel\\fR\n.\nContains a dot-separated sequence of decimal integers giving the\ncurrent patch level for Tk.\nThe patch level is incremented for each new release or patch, and\nit uniquely identifies an official version of Tk.\n.RS\n.PP\nThis value is normally the same as the result of\n.QW \"\\fBpackage require\\fR \\fBtk\\fR\" .\n.RE\n.\\\" VARIABLE: scalingPct\n.TP\n\\fBtk::scalingPct\\fR\n.\nTk sets this variable at initialization time to the scaling percentage\ncorresponding to the display's DPI scaling level.  This value is at least\n100 and is restricted to multiples of 25 (100, 125, 150, 175, 200,\n225, ...).  The sizes and various attributes of the Tk core and Ttk\nwidgets and their components, as well as the sizes of the images used by\nTk are chosen according to the scaling percentage, and this is\nrecommended for applications and library packages, too.\n.RS\n.PP\nNote that any access to this variable is supposed to be strictly\nread-only!  Note also that whenever the scaling factor used to convert\nbetween physical units and pixels is changed via \\fBtk scaling\\fR, the\nvalue of the variable \\fBtk::scalingPct\\fR is automatically updated.\n.PP\nOn the windowing systems \\fBwin32\\fR and \\fBaqua\\fR the scaling\npercentage is computed by rounding [\\fBtk scaling\\fR] * 75 to the\nnearest multiple of 25 that is at least 100.  (On \\fBaqua\\fR the result\nis always 100, and the desktop engine automatically scales everything as\nneeded.)  On \\fBx11\\fR, deriving the scaling percentage from\n[\\fBtk scaling\\fR] is done as fallback method only, because the\nimplementation of display scaling is highly dependent on the desktop\nenvironment and it mostly manipulates system resources that are resident\noutside of Xlib, which Tk is based on.  Moreover, for technical reasons,\nthe value assigned to the variable \\fBtk::scalingPct\\fR can be different\nfrom the one selected in the system settings (e.g., 200 rather than 125,\n150, or 175 when running GNOME on Xorg or the Cinnamon desktop).  On\n\\fBx11\\fR the scaling percentage is computed mostly (but not\nexclusively) from the value of the X resource Xft.dpi, and, as an\nadditional step, Tk synchronizes the scaling factor used to convert\nbetween physical units and pixels with the scaling percentage, with the\naid of the \\fBtk scaling\\fR command.\n.RE\n.\\\" VARIABLE: tk_strictMotif\n.TP\n\\fBtk_strictMotif\\fR\n.\nThis variable is set to zero by default.\nIf an application sets it to one, then Tk attempts to adhere as\nclosely as possible to Motif look-and-feel standards.\nFor example, active elements such as buttons and scrollbar\nsliders will not change color when the pointer passes over them.\nModern applications should not normally set this variable.\n.\\\" VARIABLE: svgFmt\n.TP\n\\fBtk::svgFmt\\fR\n.\nThis variable is set at Tk initialization time to\n.RS\n.RS 4\n.PP\n[\\fBlist svg \\-scale\\fR [\\fBexpr\\fR {$\\fBtk::scalingPct\\fR / 100.0}]]\n.RE\n.PP\nTypical values are {\\fBsvg \\-scale\\fR 1.0}, {\\fBsvg \\-scale\\fR 1.25},\n{\\fBsvg \\-scale\\fR 2.0}, etc.  It is recommended to pass the value of\nthis variable to the commands \\fBimage create photo\\fR, \\fIimageName\\fB\nconfigure\\fR, \\fIimageName\\fB put\\fR, and \\fIimageName\\fB read\\fR as the\nvalue of their \\fB\\-format\\fR option when creating or manipulating SVG\nimages, to make sure that their sizes will correspond to the display's\nDPI scaling level.\n.PP\nNote that any access to this variable is supposed to be strictly\nread-only!  Note also that whenever the scaling factor used to convert\nbetween physical units and pixels is changed via \\fBtk scaling\\fR, the\nvalue of the variable \\fBtk::svgFmt\\fR is automatically updated.\n.RE\n.\\\" VARIABLE: tk_version\n.TP\n\\fBtk_version\\fR\n.\nTk sets this variable in the interpreter for each application.\nThe variable holds the current version number of the Tk\nlibrary in the form \\fImajor\\fR.\\fIminor\\fR.  \\fIMajor\\fR and\n\\fIminor\\fR are integers.  The major version number increases in\nany Tk release that includes changes that are not backward compatible\n(i.e. whenever existing Tk applications and scripts may have to change to\nwork with the new release).  The minor version number increases with\neach new release of Tk, except that it resets to zero whenever the\nmajor version number changes.\n.SS \"INTERNAL AND DEBUGGING VARIABLES\"\n.PP\nThese variables should not normally be set by user code.\n.\\\" VARIABLE: Priv\n.TP\n\\fBtk::Priv\\fR\n.\nThis variable is an array containing several pieces of information\nthat are private to Tk.  The elements of \\fBtk::Priv\\fR are used by\nTk library procedures and default bindings.\nThey should not be accessed by any code outside Tk.\n.\\\" VARIABLE: tk_textRedraw\n.\\\" VARIABLE: tk_textRelayout\n.TP\n\\fBtk_textRedraw\\fR\n.TP\n\\fBtk_textRelayout\\fR\n.\nThese variables are set by text widgets when they have debugging\nturned on.  The values written to these variables can be used to\ntest or debug text widget operations.  These variables are mostly\nused by Tk's test suite.\n.SH \"OTHER GLOBAL VARIABLES\"\nThe following variables are only guaranteed to exist in \\fBwish\\fR\nexecutables; the Tk library does not define them itself but many Tk\nenvironments do.\n.\\\" VARIABLE: geometry\n.TP\n\\fBgeometry\\fR\n.\nIf set, contains the user-supplied geometry specification to use for\nthe main Tk window.\n.SH \"SEE ALSO\"\npackage(n), tclvars(n), wish(1)\n.SH KEYWORDS\nenvironment, text, variables, version\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/tkwait.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1992 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH tkwait n \"\" Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntkwait \\- Wait for variable to change or window to be destroyed\n.SH SYNOPSIS\n.nf\n\\fBtkwait variable \\fIname\\fR\n\\fBtkwait visibility \\fIname\\fR\n\\fBtkwait window \\fIname\\fR\n.fi\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtkwait\\fR command waits for one of several things to happen,\nthen it returns without taking any other actions.\nThe return value is always an empty string.\n.\\\" METHOD: variable\nIf the first argument is \\fBvariable\\fR (or any abbreviation of\nit) then the second argument is the name of a global variable and the\ncommand waits for that variable to be modified.\n.\\\" METHOD: visibility\nIf the first argument is \\fBvisibility\\fR (or any abbreviation\nof it) then the second argument is the name of a window and the\n\\fBtkwait\\fR command waits for a change in its\nvisibility state (as indicated by the arrival of a VisibilityNotify\nevent).  This form is typically used to wait for a newly-created\nwindow to appear on the screen before taking some action.\n.\\\" METHOD: window\nIf the first argument is \\fBwindow\\fR (or any abbreviation\nof it) then the second argument is the name of a window and the\n\\fBtkwait\\fR command waits for that window to be destroyed.\nThis form is typically used to wait for a user to finish interacting\nwith a dialog box before using the result of that interaction.\n.PP\nWhile the \\fBtkwait\\fR command is waiting it processes events in\nthe normal fashion, so the application will continue to respond\nto user interactions.\nIf an event handler invokes \\fBtkwait\\fR again, the nested call\nto \\fBtkwait\\fR must complete before the outer call can complete.\n.SH \"SEE ALSO\"\nbind(n), vwait(n)\n.SH KEYWORDS\nvariable, visibility, wait, window\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/toplevel.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH toplevel n 8.4 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\ntoplevel \\- Create and manipulate 'toplevel' main and popup window widgets\n.SH SYNOPSIS\n\\fBtoplevel\\fI pathName \\fR?\\fIoptions\\fR?\n.SO\n\\-borderwidth\t\\-highlightcolor\t\\-pady\n\\-cursor\t\\-highlightthickness\t\\-relief\n\\-highlightbackground\t\\-padx\t\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-background background Background\nThis option is the same as the standard \\fB\\-background\\fR option\nexcept that its value may also be specified as an empty string.\nIn this case, the widget will display no background or border, and\nno colors will be consumed from its colormap for its background\nand border.\n.VS \"9.0, TIP262\"\nAn empty background will disable drawing the background image.\n.OP \\-backgroundimage backgroundImage BackgroundImage\nThis specifies an image to display on the toplevel's background within\nthe border of the toplevel (i.e., the image will be clipped by the\ntoplevel's highlight ring and border, if either are present) on top of\nthe background;\nsubwidgets of the toplevel will be drawn on top. The image must have\nbeen created with the \\fBimage create\\fR command. If specified as the\nempty string, no image will be displayed.\n.VE \"9.0, TIP262\"\n.OP \\-class class Class\nSpecifies a class for the window.\nThis class will be used when querying the option database for\nthe window's other options, and it will also be used later for\nother purposes such as bindings. Some window managers display the\nclass name for windows in their dock while some others display the\nwindow title.\nThe \\fB\\-class\\fR option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-colormap colormap Colormap\nSpecifies a colormap to use for the window.\nThe value may be either \\fBnew\\fR, in which case a new colormap is\ncreated for the window and its children, or the name of another\nwindow (which must be on the same screen and have the same visual\nas \\fIpathName\\fR), in which case the new window will use the colormap\nfrom the specified window.\nIf the \\fB\\-colormap\\fR option is not specified, the new window\nuses the default colormap of its screen.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-container container Container\nThe value must be a boolean.  If true, it means that this window will\nbe used as a container in which some other application will be embedded\n(for example, a Tk toplevel can be embedded using the \\fB\\-use\\fR option).\nThe window will support the appropriate window manager protocols for\nthings like geometry requests.  The window should not have any\nchildren of its own in this application.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-height height Height\nSpecifies the desired height for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.\nIf this option is negative or zero then the window will\nnot request any size at all.\n.OP \\-menu menu Menu\nSpecifies a menu widget to be used as a menubar. On the Macintosh, the\nmenubar will be displayed across the top of the main monitor. On\nMicrosoft Windows and all UNIX platforms, the menu will appear across\nthe toplevel window as part of the window dressing maintained by the\nwindow manager.\n.OP \\-screen \"\" \"\"\nSpecifies the screen on which to place the new window.\nAny valid screen name may be used, even one associated with a\ndifferent display.\nDefaults to the same screen as its parent.\nThis option is special in that it may not be specified via the option\ndatabase, and it may not be modified with the \\fBconfigure\\fR\nwidget command.\n.OP \\-tile tile Tile\n.VS \"9.0, TIP262\"\nThis specifies how to draw the background image (see\n\\fB\\-backgroundimage\\fR) on the toplevel.\nIf true (according to \\fBTcl_GetBoolean\\fR), the image will be tiled\nto fill the whole toplevel, with the origin of the first copy of the\nimage being the top left of the interior of the toplevel.\nIf false (the default), the image will be centered within the toplevel.\n.VE \"9.0, TIP262\"\n.OP \\-use use Use\nThis option is used for embedding. If the value is not an empty string,\nit must be the window identifier of a container window, specified as\na hexadecimal string like the ones returned by the \\fBwinfo id\\fR\ncommand. The toplevel widget will be created as a child of the given\ncontainer instead of the root window for the screen.  If the container\nwindow is in a Tk application, it must be a frame or toplevel widget for\nwhich the \\fB\\-container\\fR option was specified.\nThis option may not be changed with the \\fBconfigure\\fR\nwidget command.\n.OP \\-visual visual Visual\nSpecifies visual information for the new window in any of the\nforms accepted by \\fBTk_GetVisual\\fR.\nIf this option is not specified, the new window will use the default\nvisual for its screen.\nThe \\fB\\-visual\\fR option may not be modified with the \\fBconfigure\\fR\nwidget command.\n.OP \\-width width Width\nSpecifies the desired width for the window in any of the forms\nacceptable to \\fBTk_GetPixels\\fR.\nIf this option is negative or zero then the window will\nnot request any size at all.\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBtoplevel\\fR command creates a new toplevel widget (given\nby the \\fIpathName\\fR argument).  Additional\noptions, described above, may be specified on the command line\nor in the option database\nto configure aspects of the toplevel such as its background color\nand relief.  The \\fBtoplevel\\fR command returns the\npath name of the new window.\n.PP\nA toplevel is similar to a \\fBframe\\fR except that it is created as a\ntop-level window:  its X parent is the root window of a screen\nrather than the logical parent from its Tk path name.  The primary\npurpose of a toplevel is to serve as a container for dialog boxes\nand other collections of widgets.  The only visible features\nof a toplevel are its background and an optional 3-D border\nto make the toplevel appear raised or sunken.\n.SH \"WIDGET COMMAND\"\n.PP\nThe \\fBtoplevel\\fR command creates a new Tcl command whose\nname is the same as the path name of the toplevel's window.  This\ncommand may be used to invoke various\noperations on the widget.  It has the following general form:\n.PP\n.CS\n\\fIpathName option \\fR?\\fIarg ...\\fR?\n.CE\n.PP\n\\fIPathName\\fR is the name of the command, which is the same as\nthe toplevel widget's path name.  \\fIOption\\fR and the \\fIarg\\fRs\ndetermine the exact behavior of the command.  The following\ncommands are possible for toplevel widgets:\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n\\fIOption\\fR may have any of the values accepted by the \\fBtoplevel\\fR\ncommand.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR (see \\fBTk_ConfigureInfo\\fR for\ninformation on the format of this list).  If \\fIoption\\fR is specified\nwith no \\fIvalue\\fR, then the command returns a list describing the\none named option (this list will be identical to the corresponding\nsublist of the value returned if no \\fIoption\\fR is specified).  If\none or more \\fIoption\\-value\\fR pairs are specified, then the command\nmodifies the given widget option(s) to have the given value(s);  in\nthis case the command returns an empty string.\n\\fIOption\\fR may have any of the values accepted by the \\fBtoplevel\\fR\ncommand.\n.SH BINDINGS\n.PP\nWhen a new toplevel is created, it has no default event bindings:\ntoplevels are not intended to be interactive.\n.PP\nBe aware that bindings on toplevels may receive events from subwidgets.\n.SH \"SEE ALSO\"\nbind(n), bindtags(n), frame(n), wm(n)\n.SH KEYWORDS\ntoplevel, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_Geometry.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n.TH Geometry 3 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nTtk_MakeBox, Ttk_PadBox, Ttk_ExpandBox, Ttk_PackBox, Ttk_StickBox, Ttk_PlaceBox, Ttk_BoxContains, Ttk_MakePadding, Ttk_UniformPadding, Ttk_AddPadding, Ttk_RelievePadding, Ttk_GetPaddingFromObj, Ttk_GetBorderFromObj, Ttk_GetStickyFromObj \\- Tk themed geometry utilities\n.SH SYNOPSIS\n.nf\n\\fB#include <tkTheme.h>\\fR\n\nTtk_Box\n\\fBTtk_MakeBox\\fR(int \\fIx\\fR, int \\fIy\\fR, int \\fIwidth\\fR, int \\fIheight\\fR);\n\nTtk_Box\n\\fBTtk_PadBox\\fR(Ttk_Box \\fIparcel\\fR, Ttk_Padding \\fIpadding\\fR);\n\nTtk_Box\n\\fBTtk_ExpandBox\\fR(Ttk_Box \\fIparcel\\fR, Ttk_Padding \\fIpadding\\fR);\n\nTtk_Box\n\\fBTtk_PackBox\\fR(Ttk_Box *\\fIcavity\\fR, int \\fIwidth\\fR, int \\fIheight\\fR, Ttk_Side \\fIside\\fR);\n\nTtk_Box\n\\fBTtk_StickBox\\fR(Ttk_Box \\fIparcel\\fR, int \\fIwidth\\fR, int \\fIheight\\fR, unsigned \\fIsticky\\fR);\n\nTtk_Box\n\\fBTtk_PlaceBox\\fR(Ttk_Box *\\fIcavity\\fR, int \\fIwidth\\fR, int \\fIheight\\fR, Ttk_Side \\fIside\\fR, unsigned \\fIsticky\\fR);\n\nTtk_Box\n\\fBTtk_AnchorBox\\fR(Ttk_Box \\fIparcel\\fR, int \\fIwidth\\fR, int \\fIheight\\fR, Tk_Anchor \\fIanchor\\fR);\n\nTtk_Padding\n\\fBTtk_MakePadding\\fR(short \\fIleft\\fR, short \\fItop\\fR, short \\fIright\\fR, short \\fIbottom\\fR);\n\nTtk_Padding\n\\fBTtk_UniformPadding\\fR(short \\fIborder\\fR);\n\nTtk_Padding\n\\fBTtk_AddPadding\\fR(Ttk_Padding \\fIpadding1\\fR, Ttk_Padding \\fIpadding2\\fR;\n\nTtk_Padding\n\\fBTtk_RelievePadding\\fR(Ttk_Padding \\fIpadding\\fR, int \\fIrelief\\fR);\n\nint\n\\fBTtk_BoxContains\\fR(Ttk_Box \\fIbox\\fR, int \\fIx\\fR, int \\fIy\\fR);\n\nint\n\\fBTtk_GetPaddingFromObj\\fR(Tcl_Interp *\\fIinterp\\fR, Tk_Window \\fItkwin\\fR, Tcl_Obj *\\fIobjPtr\\fR, Ttk_Padding *\\fIpadding_rtn\\fR);\n\nint\n\\fBTtk_GetBorderFromObj\\fR(Tcl_Interp *\\fIinterp\\fR, Tcl_Obj *\\fIobjPtr\\fR, Ttk_Padding *\\fIpadding_rtn\\fR);\n\nint\n\\fBTtk_GetStickyFromObj\\fR(Tcl_Interp *\\fIinterp\\fR, Tcl_Obj *\\fIobjPtr\\fR, int *\\fIsticky_rtn\\fR);\n.fi\n.SH ARGUMENTS\n.AP Tk_Anchor anchor in\nOne of the symbolic constants \\fBTK_ANCHOR_N\\fR, \\fBTK_ANCHOR_NE\\fR,\netc.  See \\fITk_GetAnchorFromObj(3)\\fR.\n.AP \"Ttk_Box *\" cavity in/out\nA rectangular region from which a parcel is allocated.\n.AP short border in\nExtra padding (in pixels) to add uniformly to each side of a region.\n.AP short bottom in\nExtra padding (in pixels) to add to the bottom of a region.\n.AP Ttk_Box box in\nSpecifies a rectangular region.\n.AP \"Ttk_Box *\" box_rtn out\nA rectangular region.\n.AP int height in\nThe height in pixels of a region.\n.AP \"Tcl_Interp *\" interp in\nUsed to store error messages.\n.AP int left in\nExtra padding (in pixels) to add to the left side of a region.\n.AP \"Tcl_Obj *\" objPtr in\nString value contains a symbolic name\nto be converted to an enumerated value or bitmask.\nInternal rep may be be modified to cache corresponding value.\n.AP Ttk_Padding padding in\nExtra padding to add on the inside of a region.\n.AP \"Ttk_Padding *\" padding_rtn out\nPadding present in the inside of a region.\n.AP Ttk_Box parcel in\nA rectangular region, allocated from a cavity.\n.AP int relief in\nOne of the standard Tk relief options\n(\\fBTK_RELIEF_RAISED\\fR, \\fBTK_RELIEF_SUNKEN\\fR, etc.).\nSee \\fBTk_GetReliefFromObj\\fR.\n.AP short right in\nExtra padding (in pixels) to add to the right side of a region.\n.AP Ttk_Side side in\nOne of \\fBTTK_SIDE_LEFT\\fR, \\fBTTK_SIDE_TOP\\fR,\n\\fBTTK_SIDE_RIGHT\\fR, or \\fBTTK_SIDE_BOTTOM\\fR.\n.AP unsigned sticky in\nA bitmask containing one or more of the bits\n\\fBTTK_STICK_W\\fR (west, or left),\n\\fBTTK_STICK_E\\fR (east, or right),\n\\fBTTK_STICK_N\\fR (north, or top), and\n\\fBTTK_STICK_S\\fR (south, or bottom).\n\\fBTTK_FILL_X\\fR is defined as a synonym for\n(\\fBTTK_STICK_W\\fR|\\fBTTK_STICK_E\\fR),\n\\fBTTK_FILL_Y\\fR is a synonym for (\\fBTTK_STICK_N\\fR|\\fBTTK_STICK_S\\fR),\nand  \\fBTTK_FILL_BOTH\\fR\nis a synonym for (\\fBTTK_FILL_X\\fR|\\fBTTK_FILL_Y\\fR).\nSee also: \\fIgrid(n)\\fR.\n.AP Tk_Window tkwin in\nWindow whose screen geometry determines\nthe conversion between absolute units and pixels.\n.AP short top in\nExtra padding at the top of a region.\n.AP int width in\nThe width in pixels of a region.\n.AP int x in\nX coordinate of upper-left corner of region.\n.AP int y in\nY coordinate of upper-left corner of region.\n.BE\n.SH \"BOXES\"\n.PP\nThe \\fBTtk_Box\\fR structure represents a rectangular region of a window:\n.CS\ntypedef struct {\n    int \\fIx\\fR;\n    int \\fIy\\fR;\n    int \\fIwidth\\fR;\n    int \\fIheight\\fR;\n} \\fBTtk_Box\\fR;\n.CE\nAll coordinates are relative to the window.\n.PP\n\\fBTtk_MakeBox\\fR is a convenience routine that constructs\na \\fBTtk_Box\\fR structure representing a region \\fIwidth\\fR pixels\nwide, \\fIheight\\fR pixels tall, at the specified \\fIx, y\\fR coordinates.\n.PP\n\\fBTtk_PadBox\\fR returns a new box located inside the specified \\fIparcel\\fR,\nshrunken according to the left, top, right, and bottom margins\nspecified by \\fIpadding\\fR.\n.PP\n\\fBTtk_ExpandBox\\fR is the inverse of \\fBTtk_PadBox\\fR:\nit returns a new box surrounding the specified \\fIparcel\\fR,\nexpanded  according to the left, top, right, and bottom margins\nspecified by \\fIpadding\\fR.\n.PP\n\\fBTtk_PackBox\\fR allocates a parcel \\fIwidth\\fR by \\fIheight\\fR\npixels wide on the specified \\fIside\\fR of the \\fIcavity\\fR,\nand shrinks the \\fIcavity\\fR accordingly.\n.PP\n\\fBTtk_StickBox\\fR places a box with the requested \\fIwidth\\fR\nand \\fIheight\\fR inside the \\fIparcel\\fR according to the\n\\fIsticky\\fR bits.\n.PP\n\\fBTtk_PlaceBox\\fR combines \\fBTtk_PackBox\\fR and \\fBTtk_StickBox\\fR:\nit allocates a parcel on the specified \\fIside\\fR of the \\fIcavity\\fR,\nplaces a box of the requested size inside the parcel according to \\fIsticky\\fR,\nand shrinks the \\fIcavity\\fR.\n.PP\n\\fBTtk_AnchorBox\\fR places a box with the requested \\fIwidth\\fR\nand \\fIheight\\fR inside the \\fIparcel\\fR according to the\nspecified \\fIanchor\\fR option.\n.PP\n\\fBTtk_BoxContains\\fR tests if the specified \\fIx, y\\fR coordinate\nlies within the rectangular region \\fIbox\\fR.\n.SH \"PADDDING\"\n.PP\nThe \\fBTtk_Padding\\fR structure is used to represent\nborders, internal padding, and external margins:\n.CS\ntypedef struct {\n    short \\fIleft\\fR;\n    short \\fItop\\fR;\n    short \\fIright\\fR;\n    short \\fIbottom\\fR;\n} \\fBTtk_Padding\\fR;\n.CE\n.PP\n\\fBTtk_MakePadding\\fR is a convenience routine that constructs\na \\fBTtk_Padding\\fR structure with the specified left, top, right, and bottom\ncomponents.\n.PP\n\\fBTtk_UniformPadding\\fR constructs a \\fBTtk_Padding\\fR structure\nwith all components equal to the specified \\fIborder\\fR.\n.PP\n\\fBTtk_AddPadding\\fR adds two \\fBTtk_Padding\\fRs together\nand returns a combined padding containing the sum of the\nindividual padding components.\n.PP\n\\fBTtk_RelievePadding\\fR\nadds an extra 2 pixels of padding to \\fIpadding\\fR\naccording to the specified \\fIrelief\\fR.\nIf \\fIrelief\\fR is \\fBTK_RELIEF_SUNKEN\\fR,\nadds two pixels at the top and left\nso the inner region is shifted down and to the left.\nIf it is \\fBTK_RELIEF_RAISED\\fR, adds two pixels\nat the bottom and right so\nthe inner region is shifted up and to the right.\nOtherwise, adds 1 pixel on all sides.\nThis is typically used in element geometry procedures to simulate a\n.QW pressed-in\nlook for pushbuttons.\n.SH \"CONVERSION ROUTINES\"\n.PP\n\\fBTtk_GetPaddingFromObj\\fR converts the string in \\fIobjPtr\\fR\nto a \\fBTtk_Padding\\fR structure.\nThe string representation is a list of\nup to four length specifications\n.QW \"\\fIleft top right bottom\\fR\" .\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nSee \\fBTk_GetPixelsFromObj(3)\\fR for the syntax of length specifications.\n.PP\n\\fBTtk_GetBorderFromObj\\fR is the same as \\fBTtk_GetPaddingFromObj\\fR\nexcept that the lengths are specified as integers\n(i.e., resolution-dependent values like \\fI3m\\fR are not allowed).\n.PP\n\\fBTtk_GetStickyFromObj\\fR converts the string in \\fIobjPtr\\fR\nto a \\fIsticky\\fR bitmask.  The string contains zero or more\nof the characters \\fBn\\fR, \\fBs\\fR, \\fBe\\fR, or \\fBw\\fR.\n.SH \"SEE ALSO\"\nTk_GetReliefFromObj(3), Tk_GetPixelsFromObj(3), Tk_GetAnchorFromObj(3)\n.SH \"KEYWORDS\"\ngeometry, padding, margins, box, region, sticky, relief\n"
  },
  {
    "path": "doc/ttk_Theme.3",
    "content": "'\\\"\n'\\\" Copyright (c) 2003 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH Ttk_CreateTheme 3 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nTtk_CreateTheme, Ttk_GetTheme, Ttk_GetDefaultTheme, Ttk_GetCurrentTheme \\- create and use Tk themes.\n.SH SYNOPSIS\n.nf\nTtk_Theme Ttk_CreateTheme(\\fIinterp\\fR, \\fIname\\fR, \\fIparentTheme\\fR);\nTtk_Theme Ttk_GetTheme(\\fIinterp\\fR, \\fIname\\fR);\nTtk_Theme Ttk_GetDefaultTheme(\\fIinterp\\fR);\nTtk_Theme Ttk_GetCurrentTheme(\\fIinterp\\fR);\n.fi\n.SH ARGUMENTS\n.AP \"Tcl_Interp *\" interp in\nThe Tcl interpreter in which to register/query available themes.\n.AP \"Ttk_Theme\" parentTheme in\nFallback or parent theme from which the new theme will\ninherit elements and layouts.\n.AP \"const char *\" name in\nThe name of the theme.\n.BE\n.SH DESCRIPTION\n.\\\" TODO - Document these functions better!\n.SH \"SEE ALSO\"\nTtk_RegisterLayout, Ttk_BuildLayout\n.\\\" .SH KEYWORDS\n"
  },
  {
    "path": "doc/ttk_button.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::button n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::button \\- Widget that issues a command when pressed\n.SH SYNOPSIS\n\\fBttk::button\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\nA \\fBttk::button\\fR widget displays a textual label and/or image,\nand evaluates a command when pressed.\n.SO ttk_widget\n\\-class\t\\-compound\t\\-cursor\n\\-image\t\\-justify\t\\-state\t\\-style\n\\-takefocus\t\\-text\t\\-textvariable\n\\-underline\t\\-width\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nA script to evaluate when the widget is invoked.\n.OP \\-default default Default\nMay be set to one of  \\fBnormal\\fR, \\fBactive\\fR, or \\fBdisabled\\fR.\nIn a dialog box, one button may be designated the\n.QW default\nbutton (meaning, roughly,\n.QW \"the one that gets invoked when the user presses <Enter>\" ).\n\\fBactive\\fR indicates that this is currently the default button;\n\\fBnormal\\fR means that it may become the default button, and\n\\fBdisabled\\fR means that it is not defaultable.\nThe default is \\fBnormal\\fR.\n.RS\n.PP\nDepending on the theme, the default button may be displayed\nwith an extra highlight ring, or with a different border color.\n.RE\n.\\\" Not documented -- may go away\n.\\\" .OP \\-padding padding Padding\n.\\\" .OP \\-foreground foreground Foreground\n.\\\" .OP \\-font font Font\n.\\\" .OP \\-anchor anchor Anchor\n.\\\" .OP \\-relief relief Relief\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nbutton widgets support the following additional commands:\n.\\\" METHOD: invoke\n.TP\n\\fIpathName \\fBinvoke\\fR\n.\nInvokes the command associated with the button.\n.SH \"STANDARD STYLES\"\n.PP\n\\fBTtk::button\\fR widgets support the \\fBToolbutton\\fR style in all standard\nthemes, which is useful for creating widgets for toolbars.\n.PP\nIn the Aqua theme there are several other styles which can be used to\nproduce replicas of many of the different button types that are\ndiscussed in Apple's Human Interface Guidelines.  These include\n\\fBDisclosureButton\\fR, \\fBDisclosureTriangle\\fR, \\fBHelpButton\\fR,\n\\fBImageButton\\fR, \\fBInlineButton\\fR, \\fBGradientButton\\fR,\n\\fBRoundedRectButton\\fR, and \\fBRecessedButton\\fR.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::button\\fP is \\fBTButton\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBdisabled\\fP, \\fBpressed\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTButton\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-anchor\\fP \\fIanchor\\fP\n.br\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-highlightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-highlightthickness\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.br\n\\fB\\-shiftrelief\\fP \\fIamount\\fP\n.RS\n\\fB\\-shiftrelief\\fP specifies how far the button contents are\nshifted down and right in the \\fIpressed\\fP state.\nThis action provides additional skeuomorphic feedback.\n.RE\n\\fB\\-width\\fP \\fIamount\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), button(n)\n.SH \"KEYWORDS\"\nwidget, button, default, command\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_checkbutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::checkbutton n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::checkbutton \\- On/off widget\n.SH SYNOPSIS\n\\fBttk::checkbutton\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\nA \\fBttk::checkbutton\\fR widget is used to show or change a setting.\nIt has two states, selected and deselected.\nThe state of the checkbutton may be linked to a Tcl variable.\n.SO ttk_widget\n\\-class\t\\-compound\t\\-cursor\n\\-image\t\\-state\t\\-style\n\\-takefocus\t\\-text\t\\-textvariable\n\\-underline\t\\-width\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nA Tcl script to execute whenever the widget is invoked.\n.OP \\-offvalue offValue OffValue\nThe value to store in the associated \\fB\\-variable\\fR\nwhen the widget is deselected.  Defaults to \\fB0\\fR.\n.OP \\-onvalue onValue OnValue\nThe value to store in the associated \\fB\\-variable\\fR\nwhen the widget is selected.  Defaults to \\fB1\\fR.\n.OP \\-variable variable Variable\nThe name of a global variable whose value is linked to the widget.\nDefaults to the widget pathname if not specified.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\ncheckbutton widgets support the following additional commands:\n.\\\" METHOD: invoke\n.TP\n\\fIpathname\\fB invoke\\fR\n.\nToggles between the selected and deselected states\nand evaluates the associated \\fB\\-command\\fR.\nIf the widget is currently selected, sets the \\fB\\-variable\\fR\nto the \\fB\\-offvalue\\fR and deselects the widget;\notherwise, sets the \\fB\\-variable\\fR to the \\fB\\-onvalue\\fR\nReturns the result of the \\fB\\-command\\fR.\n.\\\" Missing: select, deselect, toggle\n.\\\" Are these useful?  They don't invoke the -command\n.\\\" Missing: flash.  This is definitely not useful.\n.SH \"WIDGET STATES\"\n.PP\nThe widget does not respond to user input if the \\fBdisabled\\fR state is set.\nThe widget sets the \\fBselected\\fR state whenever\nthe linked \\fB\\-variable\\fR is set to the widget's \\fB\\-onvalue\\fR,\nand clears it otherwise.\nThe widget sets the \\fBalternate\\fR state whenever the\nlinked \\fB\\-variable\\fR is unset.\n(The \\fBalternate\\fR state may be used to indicate a\n.QW tri-state\nor\n.QW indeterminate\nselection.)\n.SH \"STANDARD STYLES\"\n.PP\n\\fBTtk::checkbutton\\fR widgets support the \\fBToolbutton\\fR style in all\nstandard themes, which is useful for creating widgets for toolbars.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::checkbutton\\fP is \\fBTCheckbutton\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBalternate\\fP, \\fBdisabled\\fP,\n\\fBpressed\\fP, \\fBselected\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTCheckbutton\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatorbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatorcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatormargin\\fP \\fIpadding\\fP\n.br\n\\fB\\-indicatorrelief\\fP \\fIrelief\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::radiobutton(n), checkbutton(n)\n.SH \"KEYWORDS\"\nwidget, button, toggle, check, option\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_combobox.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::combobox n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::combobox \\- text field with popdown selection list\n.SH SYNOPSIS\n\\fBttk::combobox\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::combobox\\fR combines a text field with a pop-down list of values;\nthe user may select the value of the text field from among the\nvalues in the list.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-takefocus\n\\-style\t\\-placeholder\t\\-placeholderforeground\n.SE\n.\\\" ALSO: Other entry widget options\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-exportselection exportSelection ExportSelection\nBoolean value.\nIf set, the widget selection is linked to the X selection.\n.OP \\-justify justify Justify\nSpecifies how the text is aligned within the widget.\nMust be one of \\fBleft\\fR, \\fBcenter\\fR, or \\fBright\\fR.\n.OP \\-height height Height\nSpecifies the height of the pop-down listbox, in rows.\n.OP \\-postcommand postCommand PostCommand\nA Tcl script to evaluate immediately before displaying the listbox.\nThe \\fB\\-postcommand\\fR script may specify the \\fB\\-values\\fR to display.\n.OP \\-state state State\nOne of \\fBnormal\\fR, \\fBreadonly\\fR, or \\fBdisabled\\fR.\nIn the \\fBreadonly\\fR state,\nthe value may not be edited directly, and\nthe user can only select one of the \\fB\\-values\\fR from the\ndropdown list.\nIn the \\fBnormal\\fR state,\nthe text field is directly editable.\nIn the \\fBdisabled\\fR state, no interaction is possible.\n.OP \\-textvariable textVariable TextVariable\nSpecifies the name of a global variable whose value is linked\nto the widget value.\nWhenever the variable changes value the widget value is updated,\nand vice versa.\n.OP \\-values values Values\nSpecifies the list of values to display in the drop-down listbox.\n.OP \\-width width Width\nSpecifies an integer value indicating the desired width of the entry window,\nin average-size characters of the widget's font.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\ncombobox widgets support the following additional commands:\n.\\\" METHOD: current\n.TP\n\\fIpathName \\fBcurrent\\fR ?\\fInewIndex\\fR?\n.\nIf \\fInewIndex\\fR is supplied, sets the combobox value\nto the element at position \\fInewIndex\\fR in the list of \\fB\\-values\\fR\n(in addition to integers, the \\fBend\\fR index is supported and indicates\nthe last element of the list, moreover the same simple interpretation as\nfor the command \\fBstring index\\fR is supported, with simple integer index\narithmetic and indexing relative to \\fBend\\fR).\nOtherwise, returns the index of the current value in the list of\n\\fB\\-values\\fR or \\fB{}\\fR if the current value does not appear in the list.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the current value of the combobox.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset\\fI value\\fR\n.\nSets the value of the combobox to \\fIvalue\\fR.\n.PP\nThe combobox widget also supports the following \\fBttk::entry\\fR\nwidget commands:\n.DS\n.ta 5.5c 11c\n\\fBbbox\\fR\t\\fBdelete\\fR\t\\fBicursor\\fR\n\\fBindex\\fR\t\\fBinsert\\fR\t\\fBselection\\fR\n\\fBxview\\fR\n.DE\n.SH \"VIRTUAL EVENTS\"\n.PP\nThe combobox widget generates a \\fB<<ComboboxSelected>>\\fR virtual event\nwhen the user selects an element from the list of values.\nIf the selection action unposts the listbox,\nthis event is delivered after the listbox is unposted.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::combobox\\fP is \\fBTCombobox\\fP.\nThe \\fBttk::combobox\\fP uses the \\fBentry\\fP and\n\\fBlistbox\\fP widgets internally.\nThe listbox frame has a class name of \\fBComboboxPopdownFrame\\fP.\n.PP\nDynamic states: \\fBdisabled\\fP, \\fBfocus\\fP, \\fBpressed\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTCombobox\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-arrowcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-arrowsize\\fP \\fIamount\\fP\n.br\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-focusfill\\fP \\fIcolor\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-fieldbackground\\fP \\fIcolor\\fP\n.RS\nCan only be changed when using non-native and non-graphical themes.\n.RE\n\\fB\\-insertcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-insertwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-placeholderforeground\\fP \\fIcolor\\fP\n.br\n\\fB\\-postoffset\\fP \\fIpadding\\fP\n.br\n\\fB\\-selectbackground\\fP \\fIcolor\\fP\n.RS\nText entry select background.\n.RE\n\\fB\\-selectforeground\\fP \\fIcolor\\fP\n.RS\nText entry select foreground.\n.RE\n.PP\nThe \\fBttk::combobox\\fP popdown listbox cannot be configured using\n\\fBttk::style\\fP nor via the widget \\fBconfigure\\fP command.  The listbox\ncan be configured using the option database.\n.PP\noption add *TCombobox*Listbox.background \\fIcolor\\fP\n.br\noption add *TCombobox*Listbox.font \\fIfont\\fP\n.br\noption add *TCombobox*Listbox.foreground \\fIcolor\\fP\n.br\noption add *TCombobox*Listbox.selectBackground \\fIcolor\\fP\n.br\noption add *TCombobox*Listbox.selectForeground \\fIcolor\\fP\n.PP\nTo configure a specific listbox (subject to future change):\n.CS\nset popdown [ttk::combobox::PopdownWindow .mycombobox]\n$popdown.f.l configure \\-font \\fIfont\\fP\n.CE\n.PP\n\\fBComboboxPopdownFrame\\fP\nstyling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-borderwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::entry(n)\n.SH KEYWORDS\nchoice, entry, list box, text box, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_entry.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 1998-2000 Scriptics Corporation.\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::entry n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::entry \\- Editable text field widget\n.SH SYNOPSIS\n\\fBttk::entry\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nAn \\fBttk::entry\\fR widget displays a one-line text string and\nallows that string to be edited by the user.\nThe value of the string may be linked to a Tcl variable\nwith the \\fB\\-textvariable\\fR option.\nEntry widgets support horizontal scrolling with the\nstandard \\fB\\-xscrollcommand\\fR option and \\fBxview\\fR widget command.\n.SO ttk_widget\n\\-class\t\\-cursor\n\\-font\t\\-foreground\n\\-style\n\\-takefocus\t\\-xscrollcommand\t\\-placeholder\t\\-placeholderforeground\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-exportselection exportSelection ExportSelection\nA boolean value specifying whether or not\na selection in the widget should be linked to the X selection.\nIf the selection is exported, then selecting in the widget deselects\nthe current X selection, selecting outside the widget deselects any\nwidget selection, and the widget will respond to selection retrieval\nrequests when it has a selection.\n.\\\" MAYBE: .OP \\-insertbackground insertBackground Foreground\n.\\\" MAYBE: .OP \\-insertwidth insertWidth InsertWidth\n.OP \\-invalidcommand invalidCommand InvalidCommand\nA script template to evaluate whenever the \\fB\\-validatecommand\\fR returns 0.\nSee \\fBVALIDATION\\fR below for more information.\n.OP \\-justify justify Justify\nSpecifies how the text is aligned within the entry widget.\nOne of \\fBleft\\fR, \\fBcenter\\fR, or \\fBright\\fR.\n.\\\" MAYBE: .OP \\-selectbackground selectBackground Foreground\n.\\\" MAYBE: .OP \\-selectborderwidth selectBorderWidth BorderWidth\n.\\\" MAYBE: .OP \\-selectforeground selectForeground Background\n.OP \\-show show Show\nIf this option is specified, then the true contents of the entry\nare not displayed in the window.\nInstead, each character in the entry's value will be displayed as\nthe first character in the value of this option, such as\n.QW *\nor a bullet.\nThis is useful, for example, if the entry is to be used to enter\na password.\nIf characters in the entry are selected and copied elsewhere, the\ninformation copied will be what is displayed, not the true contents\nof the entry.\n.OP \\-state state State\nCompatibility option; see \\fIttk::widget(n)\\fR for details.\nSpecifies one of three states for the entry,\n\\fBnormal\\fR, \\fBdisabled\\fR, or \\fBreadonly\\fR.\nSee \\fBWIDGET STATES\\fR, below.\n.OP \\-textvariable textVariable Variable\nSpecifies the name of a global variable whose value is linked\nto the entry widget's contents.\nWhenever the variable changes value, the widget's contents are updated,\nand vice versa.\n.OP \\-validate validate Validate\nSpecifies the mode in which validation should operate:\n\\fBnone\\fR, \\fBfocus\\fR, \\fBfocusin\\fR, \\fBfocusout\\fR, \\fBkey\\fR, or \\fBall\\fR.\nDefault is \\fBnone\\fR, meaning that validation is disabled.\nSee \\fBVALIDATION\\fR below.\n.OP \\-validatecommand validateCommand ValidateCommand\nA script template to evaluate whenever validation is triggered.\nIf set to the empty string (the default), validation is disabled.\nThe script must return a boolean value.\nSee \\fBVALIDATION\\fR below.\n.OP \\-width width Width\nSpecifies an integer value indicating the desired width of the entry window,\nin average-size characters of the widget's font.\n.\\\" Not in ttk: If the value is negative or zero, the widget picks a\n.\\\" Not in ttk: size just large enough to hold its current text.\n.SH NOTES\n.PP\nA portion of the entry may be selected as described below.\nIf an entry is exporting its selection (see the \\fB\\-exportselection\\fR\noption), then it will observe the standard X11 protocols for handling the\nselection;  entry selections are available as type \\fBSTRING\\fR.\nEntries also observe the standard Tk rules for dealing with the\ninput focus.  When an entry has the input focus it displays an\n\\fIinsert cursor\\fR to indicate where new characters will be\ninserted.\n.PP\nEntries are capable of displaying strings that are too long to\nfit entirely within the widget's window.  In this case, only a\nportion of the string will be displayed;  commands described below\nmay be used to change the view in the window.  Entries use\nthe standard \\fB\\-xscrollcommand\\fR mechanism for interacting with\nscrollbars (see the description of the \\fB\\-xscrollcommand\\fR option\nfor details).\n.SH \"INDICES\"\n.PP\nMany of the \\fBentry\\fR widget commands take one or more indices as\narguments.  An index specifies a particular character in the entry's\nstring, in any of the following ways:\n.IP \\fInumber\\fR\nSpecifies the character as a numerical index, where 0 corresponds\nto the first character in the string.\n.IP \\fB@\\fInumber\\fR\nIn this form, \\fInumber\\fR is treated as an x-coordinate in the\nentry's window;  the character spanning that x-coordinate is used.\nFor example,\n.QW \\fB@0\\fR\nindicates the left-most character in the window.\n.IP \\fBend\\fR\nIndicates the character just after the last one in the entry's string.\nThis is equivalent to specifying a numerical index equal to the length\nof the entry's string.\n.IP \\fBinsert\\fR\nIndicates the character adjacent to and immediately following the\ninsert cursor.\n.IP \\fBsel.first\\fR\nIndicates the first character in the selection.  It is an error to\nuse this form if the selection is not in the entry window.\n.IP \\fBsel.last\\fR\nIndicates the character just after the last one in the selection.\nIt is an error to use this form if the selection is not in the\nentry window.\n.LP\nAbbreviations may be used for any of the forms above, e.g.\\|\n.QW \\fBe\\fR\nor\n.QW \\fBsel.l\\fR .\nIn general, out-of-range indices are automatically rounded to the\nnearest legal value.\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR, \\fBstyle\\fR and \\fBxview\\fR\ncommands (see \\fBttk::widget\\fR),\nentry widgets support the following additional commands:\n.\\\" METHOD: bbox\n.TP\n\\fIpathName \\fBbbox \\fIindex\\fR\n.\nReturns a list of four numbers describing the bounding box of the\ncharacter given by \\fIindex\\fR.\nThe first two elements of the list give the x and y coordinates of\nthe upper-left corner of the screen area covered by the character\n(in pixels relative to the widget) and the last two elements give\nthe width and height of the character, in pixels.\nThe bounding box may refer to a region outside the visible area\nof the window.\n.\\\" METHOD: delete\n.TP\n\\fIpathName \\fBdelete \\fIfirst \\fR?\\fIlast\\fR?\n.\nDelete one or more elements of the entry.\n\\fIFirst\\fR is the index of the first character to delete, and\n\\fIlast\\fR is the index of the character just after the last\none to delete.\nIf \\fIlast\\fR is not specified it defaults to \\fIfirst\\fR+1,\ni.e. a single character is deleted.\nThis command returns the empty string.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the entry's string.\n.\\\" METHOD: icursor\n.TP\n\\fIpathName \\fBicursor \\fIindex\\fR\n.\nArrange for the insert cursor to be displayed just before the character\ngiven by \\fIindex\\fR.  Returns the empty string.\n.\\\" METHOD: index\n.TP\n\\fIpathName \\fBindex\\fI index\\fR\n.\nReturns the numerical index corresponding to \\fIindex\\fR.\n.\\\" METHOD: insert\n.TP\n\\fIpathName \\fBinsert \\fIindex string\\fR\n.\nInsert \\fIstring\\fR just before the character\nindicated by \\fIindex\\fR.  Returns the empty string.\n.\\\" METHOD: selection\n.TP\n\\fIpathName \\fBselection \\fIoption arg\\fR\n.\nThis command is used to adjust the selection within an entry.  It\nhas several forms, depending on \\fIoption\\fR:\n.RS\n.TP\n\\fIpathName \\fBselection clear\\fR\n.\nClear the selection if it is currently in this widget.\nIf the selection is not in this widget then the command has no effect.\nReturns the empty string.\n.TP\n\\fIpathName \\fBselection present\\fR\n.\nReturns 1 if there is are characters selected in the entry,\n0 if nothing is selected.\n.TP\n\\fIpathName \\fBselection range \\fIstart end\\fR\n.\nSets the selection to include the characters starting with\nthe one indexed by \\fIstart\\fR and ending with the one just\nbefore \\fIend\\fR.\nIf \\fIend\\fR refers to the same character as \\fIstart\\fR or an\nearlier one, then the entry's selection is cleared.\n.RE\n.\\\" METHOD: validate\n.TP\n\\fIpathName \\fBvalidate\\fR\n.\nForce revalidation, independent of the conditions specified\nby the \\fB\\-validate\\fR option.\nReturns 0 if validation fails, 1 if it succeeds.\nSets or clears the \\fBinvalid\\fR state accordingly.\nSee \\fBVALIDATION\\fR below for more details.\n.SH VALIDATION\n.PP\nThe \\fB\\-validate\\fR, \\fB\\-validatecommand\\fR, and \\fB\\-invalidcommand\\fR\noptions are used to enable entry widget validation.\n.SS \"VALIDATION MODES\"\n.PP\nThere are two main validation modes: \\fIprevalidation\\fR,\nin which the \\fB\\-validatecommand\\fR is evaluated prior to each edit\nand the return value is used to determine whether to accept\nor reject the change;\nand \\fIrevalidation\\fR, in which the \\fB\\-validatecommand\\fR is\nevaluated to determine whether the current value is valid.\n.PP\nThe \\fB\\-validate\\fR option determines when validation occurs;\nit may be set to any of the following values:\n.RS\n.IP \\fBnone\\fR\nDefault.  This means validation will only occur when\nspecifically requested by the \\fBvalidate\\fR widget command.\n.IP \\fBkey\\fR\nThe entry will be prevalidated prior to each edit\n(specifically, whenever the \\fBinsert\\fR or \\fBdelete\\fR\nwidget commands are called).\nIf prevalidation fails, the edit is rejected.\n.IP \\fBfocus\\fR\nThe entry is revalidated when the entry receives or loses focus.\n.IP \\fBfocusin\\fR\nThe entry is revalidated when the entry receives focus.\n.IP \\fBfocusout\\fR\nThe entry is revalidated when the entry loses focus.\n.IP \\fBall\\fR\nValidation is performed for all above conditions.\n.RE\n.PP\nThe \\fB\\-invalidcommand\\fR is evaluated whenever\nthe \\fB\\-validatecommand\\fR returns a false value.\n.PP\nThe \\fB\\-validatecommand\\fR and \\fB\\-invalidcommand\\fR\nmay modify the entry widget's value\nvia the widget \\fBinsert\\fR or \\fBdelete\\fR commands,\nor by setting the linked \\fB\\-textvariable\\fR.\nIf either does so during prevalidation,\nthen the edit is rejected\nregardless of the value returned by the \\fB\\-validatecommand\\fR.\n.PP\nIf \\fB\\-validatecommand\\fR is empty (the default),\nvalidation always succeeds.\n.SS \"VALIDATION SCRIPT SUBSTITUTIONS\"\n.PP\nIt is possible to perform percent substitutions on the\n\\fB\\-validatecommand\\fR and \\fB\\-invalidcommand\\fR,\njust as in a \\fBbind\\fR script.\nThe following substitutions are recognized:\n.RS\n.IP \\fB%d\\fR\nType of action: 1 for \\fBinsert\\fR prevalidation,\n0 for \\fBdelete\\fR prevalidation,\nor \\-1 for revalidation.\n.IP \\fB%i\\fR\nIndex of character string to be inserted/deleted, if any, otherwise \\-1.\n.IP \\fB%P\\fR\nIn prevalidation, the new value of the entry if the edit is accepted.\nIn revalidation, the current value of the entry.\n.IP \\fB%s\\fR\nThe current value of entry prior to editing.\n.IP \\fB%S\\fR\nThe text string being inserted/deleted, if any, {} otherwise.\n.IP \\fB%v\\fR\nThe current value of the \\fB\\-validate\\fR option.\n.IP \\fB%V\\fR\nThe validation condition that triggered the callback\n(\\fBkey\\fR, \\fBfocusin\\fR, \\fBfocusout\\fR, or \\fBforced\\fR).\n.IP \\fB%W\\fR\nThe name of the entry widget.\n.RE\n.SS \"DIFFERENCES FROM TK ENTRY WIDGET VALIDATION\"\n.PP\nThe standard Tk entry widget automatically disables validation\n(by setting \\fB\\-validate\\fR to \\fBnone\\fR)\nif the \\fB\\-validatecommand\\fR or \\fB\\-invalidcommand\\fR modifies\nthe entry's value.\nThe Tk themed entry widget only disables validation if one\nof the validation scripts raises an error, or if \\fB\\-validatecommand\\fR\ndoes not return a valid boolean value.\n(Thus, it is not necessary to re-enable validation after\nmodifying the entry value in a validation script).\n.PP\nIn addition, the standard entry widget invokes validation whenever the linked\n\\fB\\-textvariable\\fR is modified; the Tk themed entry widget does not.\n.SH \"DEFAULT BINDINGS\"\n.PP\nThe entry widget's default bindings enable the following behavior.\nIn the descriptions below,\n.QW word\nrefers to a contiguous group of letters, digits, or\n.QW _\ncharacters, or any single character other than these.\n.IP \\0\\(bu 4\nClicking mouse button 1 positions the insert cursor\njust before the character underneath the mouse cursor, sets the\ninput focus to this widget, and clears any selection in the widget.\nDragging with mouse button 1 down strokes out a selection between\nthe insert cursor and the character under the mouse.\n.IP \\0\\(bu 4\nDouble-clicking with mouse button 1 selects the word under the mouse\nand positions the insert cursor at the end of the word.\nDragging after a double click strokes out a selection consisting\nof whole words.\n.IP \\0\\(bu 4\nTriple-clicking with mouse button 1 selects all of the text in the\nentry and positions the insert cursor at the end of the line.\n.IP \\0\\(bu 4\nThe ends of the selection can be adjusted by dragging with mouse\nbutton 1 while the Shift key is down.\nIf the button is double-clicked before dragging then the selection\nwill be adjusted in units of whole words.\n.IP \\0\\(bu 4\nClicking mouse button 1 with the Control key down will position the\ninsert cursor in the entry without affecting the selection.\n.IP \\0\\(bu 4\nIf any normal printing characters are typed in an entry, they are\ninserted at the point of the insert cursor.\n.IP \\0\\(bu 4\nThe view in the entry can be adjusted by dragging with the middle\nmouse button (button 2, or button 3 in TkAqua). If the middle mouse\nbutton is clicked without moving the mouse, the selection is copied\ninto the entry at the position of the mouse cursor.\n.IP \\0\\(bu 4\nIf the mouse is dragged out of the entry on the left or right sides\nwhile button 1 is pressed, the entry will automatically scroll to\nmake more text visible (if there is more text off-screen on the side\nwhere the mouse left the window).\n.IP \\0\\(bu 4\nThe Left and Right keys move the insert cursor one character to the\nleft or right;  they also clear any selection in the entry.\nIf Left or Right is typed with the Shift key down, then the insertion\ncursor moves and the selection is extended to include the new character.\nControl-Left and Control-Right move the insert cursor by words, and\nControl-Shift-Left and Control-Shift-Right move the insert cursor\nby words and also extend the selection.\nControl-b and Control-f behave the same as Left and Right, respectively.\n.IP \\0\\(bu 4\nThe Home key and Control-a move the insert cursor to the\nbeginning of the entry and clear any selection in the entry.\nShift-Home moves the insert cursor to the beginning of the entry\nand extends the selection to that point.\n.IP \\0\\(bu 4\nThe End key and Control-e move the insert cursor to the\nend of the entry and clear any selection in the entry.\nShift-End moves the cursor to the end and extends the selection\nto that point.\n.IP \\0\\(bu 4\nControl-/ selects all the text in the entry.\n.IP \\0\\(bu 4\nControl-\\e clears any selection in the entry.\n.IP \\0\\(bu 4\nThe standard Tk <<Cut>>, <<Copy>>, <<Paste>>, and <<Clear>>\nvirtual events operate on the selection in the expected manner.\n.IP \\0\\(bu 4\nThe Delete key deletes the selection, if there is one in the entry.\nIf there is no selection, it deletes the character to the right of\nthe insert cursor.\n.IP \\0\\(bu 4\nThe BackSpace key and Control-h delete the selection, if there is one\nin the entry.\nIf there is no selection, it deletes the character to the left of\nthe insert cursor.\n.IP \\0\\(bu 4\nControl-d deletes the character to the right of the insert cursor.\n.IP \\0\\(bu 4\nControl-k deletes all the characters to the right of the insertion\ncursor.\n.SH \"WIDGET STATES\"\n.PP\nIn the \\fBdisabled\\fR state,\nthe entry cannot be edited and the text cannot be selected.\nIn the \\fBreadonly\\fR state,\nno insert cursor is displayed and\nthe entry cannot be edited\n(specifically: the \\fBinsert\\fR and \\fBdelete\\fR commands have no effect).\nThe \\fBdisabled\\fR state is the same as \\fBreadonly\\fR,\nand in addition text cannot be selected.\n.PP\nNote that changes to the linked \\fB\\-textvariable\\fR will\nstill be reflected in the entry, even if it is disabled or readonly.\n.PP\nTypically, the text is\n.QW grayed-out\nin the \\fBdisabled\\fR state,\nand a different background is used in the \\fBreadonly\\fR state.\n.PP\nThe entry widget sets the \\fBinvalid\\fR state if revalidation fails,\nand clears it whenever validation succeeds.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::entry\\fP is \\fBTEntry\\fP.\n.PP\nDynamic states: \\fBdisabled\\fP, \\fBfocus\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTEntry\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.RS\nFor backwards compatibility, when using the aqua theme (for macOS), this\noption behaves as an alias for the \\fB\\-fieldbackground\\fP provided that no\nvalue is specified for \\fB\\-fieldbackground\\fP. Otherwise it is ignored.\n.RE\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-fieldbackground\\fP \\fIcolor\\fP\n.RS\nSome themes use a graphical background and their field background colors\ncannot be changed.\n.RE\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-insertcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-insertwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-placeholderforeground\\fP \\fIcolor\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.br\n\\fB\\-selectbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-selectborderwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-selectforeground\\fP \\fIcolor\\fP\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), entry(n)\n.SH KEYWORDS\nentry, widget, text field\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_frame.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2005 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::frame n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::frame \\- Simple container widget\n.SH SYNOPSIS\n\\fBttk::frame\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::frame\\fR widget is a container, used to group other widgets\ntogether.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-padding\n\\-style\t\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-borderwidth borderWidth BorderWidth\nThe desired width of the widget border.  Defaults to 0.\nMay be ignored depending on the theme used.\n.OP \\-relief relief Relief\nOne of the standard Tk border styles:\n\\fBflat\\fR, \\fBgroove\\fR, \\fBraised\\fR, \\fBridge\\fR,\n\\fBsolid\\fR, or \\fBsunken\\fR.\nDefaults to \\fBflat\\fR.\n.OP \\-width width Width\nIf specified, the widget's requested width in pixels.\n.OP \\-height height Height\nIf specified, the widget's requested height in pixels.\n.SH \"WIDGET COMMAND\"\n.PP\nFrame widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.SH \"NOTES\"\n.PP\nNote that if the \\fBpack\\fR, \\fBgrid\\fR, or other geometry managers\nare used to manage the children of the \\fBframe\\fR,\nby the GM's requested size will normally take precedence\nover the \\fBframe\\fR widget's \\fB\\-width\\fR and \\fB\\-height\\fR options.\n\\fBpack propagate\\fR and \\fBgrid propagate\\fR can be used\nto change this.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::frame\\fP is \\fBTFrame\\fP.\n.PP\n\\fBTFrame\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH BINDINGS\n.PP\nWhen a new \\fBttk::frame\\fR is created, it has no default event bindings;\n\\fBttk::frame\\fRs are not intended to be interactive.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::labelframe(n), frame(n)\n.SH \"KEYWORDS\"\nwidget, frame, container\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_image.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk_image n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk_image \\- Define an element based on an image\n.SH SYNOPSIS\n\\fBttk::style element create \\fIname \\fBimage\\fI imageSpec\\fR ?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fIimage\\fR element factory creates a new element\nin the current theme whose visual appearance is determined\nby Tk images.\n\\fIimageSpec\\fP is a list of one or more elements.\nThe first element is the default image name.\nThe rest of the list is a sequence of \\fIstatespec / value\\fR\npairs specifying other images to use when the element is\nin a particular state or combination of states.\n.SH OPTIONS\n.PP\nValid \\fIoptions\\fR are:\n.\\\" OPTION: -border\n.TP\n\\fB\\-border\\fI padding\\fR\n.\n\\fIpadding\\fR is a list of up to four integers, specifying\nthe left, top, right, and bottom borders, respectively.\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nIn other words, a list of three numbers specify the left, vertical, and right\nborder; a list of two numbers specify the horizontal and the vertical border;\na single number specifies the same border all the way around the element.\nSee \\fBIMAGE STRETCHING\\fR, below.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIheight\\fR\n.\nSpecifies a minimum height for the element.\nIf negative, the base image's height is used as a default.\n.\\\" OPTION: -padding\n.TP\n\\fB\\-padding\\fI padding\\fR\n.\nSpecifies the element's interior padding.\nThe padding is a list of up to four length specifications\n\\fIleft top right bottom\\fR.\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nIn other words, a list of three numbers specify the left, vertical, and right\npadding; a list of two numbers specify the horizontal and the vertical padding;\na single number specifies the same padding all the way around the widget.\nDefaults to \\fB\\-border\\fR if not specified.\n.\\\" OPTION: -sticky\n.TP\n\\fB\\-sticky\\fI spec\\fR\n.\nSpecifies how the image is placed within the final parcel.\n\\fIspec\\fR contains zero or more characters\n.QW n ,\n.QW s ,\n.QW w ,\nor\n.QW e .\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIwidth\\fR\n.\nSpecifies a minimum width for the element.\nIf negative, the base image's width is used as a default.\n.SH \"IMAGE STRETCHING\"\n.PP\nIf the element's allocated parcel is larger than the image,\nthe image will be placed in the parcel based on the \\fB\\-sticky\\fR option.\nIf the image needs to stretch horizontally (i.e., \\fB\\-sticky ew\\fR)\nor vertically (\\fB\\-sticky ns\\fR),\nsubregions of the image are replicated to fill the parcel\nbased on the \\fB\\-border\\fR option.\nThe \\fB\\-border\\fR divides the image into 9 regions:\nfour fixed corners, top and left edges (which may be tiled horizontally),\nleft and right edges (which may be tiled vertically),\nand the central area (which may be tiled in both directions).\n.PP\nAn image element that is not meant to claim any space (for example when used\nas a background image) should use \\fB\\-width 0\\fR and \\fB\\-height 0\\fR.\n.SH \"EXAMPLE\"\n.PP\n.CS\nset img1 [image create photo -file button.png]\nset img2 [image create photo -file button-pressed.png]\nset img3 [image create photo -file button-active.png]\nttk::style element create Button.button image \\e\n    [list $img1  pressed $img2  active $img3] \\e\n    -border {2 4} -sticky we\n.CE\n.SH \"SEE ALSO\"\nttk::intro(n), ttk::style(n), ttk_vsapi(n), image(n), photo(n)\n.SH KEYWORDS\nstyle, theme, appearance, pixmap theme, image\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_intro.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::intro n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::intro \\- Introduction to the Tk theme engine\n.BE\n.SH \"OVERVIEW\"\n.PP\nThe Tk themed widget set is based on a revised and enhanced version\nof TIP #48 (https://tip.tcl-lang.org/48) specified style engine.\nThe main concepts are described below.\nThe basic idea is to separate, to the extent possible,\nthe code implementing a widget's behavior from\nthe code implementing its appearance.\nWidget class bindings are primarily responsible for\nmaintaining the widget state and invoking callbacks;\nall aspects of the widget's appearance are controlled by the style of\nthe widget (i.e. the style of the elements of the widget).\n.SH \"THEMES\"\n.PP\nA \\fItheme\\fR is a collection of elements and styles\nthat determine the look and feel of the widget set.\nThemes can be used to:\n.IP \\(bu\nisolate platform differences (X11 vs. classic Windows vs. XP vs. Aqua ...)\n.IP \\(bu\nadapt to display limitations (low-color, grayscale, monochrome, tiny screens)\n.IP \\(bu\naccessibility (high contrast, large type)\n.IP \\(bu\napplication suite branding\n.IP \\(bu\nblend in with the rest of the desktop (Gnome, KDE, Java)\n.IP \\(bu\nand, of course: eye candy.\n.SH \"ELEMENTS\"\n.PP\nAn \\fIelement\\fR displays an individual part of a widget.\nFor example, a vertical scrollbar widget contains \\fBuparrow\\fR,\n\\fBdownarrow\\fR, \\fBtrough\\fR and \\fBslider\\fR elements.\n.PP\nElement names use a recursive dotted notation.\nFor example, \\fBuparrow\\fR identifies a generic arrow element,\nand \\fBScrollbar.uparrow\\fR and \\fBCombobox.uparrow\\fR identify\nwidget-specific elements.\nWhen looking for an element, the style engine looks for\nthe specific name first, and if an element of that name is\nnot found it looks for generic elements by stripping off\nsuccessive leading components of the element name.\n.PP\nLike widgets, elements have \\fIoptions\\fR which\nspecify what to display and how to display it.\nFor example, the \\fBtext\\fR element\n(which displays a text string) has\n\\fB\\-text\\fR, \\fB\\-font\\fR, \\fB\\-foreground\\fR, \\fB\\-background\\fR,\n\\fB\\-underline\\fR, and \\fB\\-width\\fR options.\nThe value of an element option is taken from (in precedence order):\n.IP \\(bu\nan option of the same name and type in the widget containing the element;\n.IP \\(bu\na dynamic setting specified by \\fBstyle map\\fR and the current state;\n.IP \\(bu\nthe default setting specified by \\fBstyle configure\\fR; or\n.IP \\(bu\nthe element's built-in default value for the option.\n.SH \"LAYOUTS\"\n.PP\nA \\fIlayout\\fR specifies which elements make up a widget\nand how they are arranged.\nThe layout engine uses a simplified version of the \\fBpack\\fR\nalgorithm: starting with an initial cavity equal to the size\nof the widget, elements are allocated a parcel within the cavity along\nthe side specified by the \\fB\\-side\\fR option,\nand placed within the parcel according to the \\fB\\-sticky\\fR\noption.\nFor example, the layout for a horizontal scrollbar is:\n.PP\n.CS\nttk::\\fBstyle layout\\fR Horizontal.TScrollbar {\n    Scrollbar.trough -children {\n\tScrollbar.leftarrow  -side left  -sticky w\n\tScrollbar.rightarrow -side right -sticky e\n\tScrollbar.thumb -sticky ew\n    }\n}\n.CE\n.PP\nBy default, the layout for a widget is the same as its class name.\nSome widgets may override this (for example, the \\fBttk::scrollbar\\fR\nwidget chooses different layouts based on the \\fB\\-orient\\fR option).\n.SH \"STATES\"\n.PP\nIn standard Tk, many widgets have a \\fB\\-state\\fR option\nwhich (in most cases) is either \\fBnormal\\fR or \\fBdisabled\\fR.\nSome widgets support additional states, such\nas the \\fBentry\\fR widget which has a \\fBreadonly\\fR state\nand the various flavors of buttons which have \\fBactive\\fR state.\n.PP\nThe themed Tk widgets generalizes this idea:\nevery widget has a bitmap of independent state flags.\nWidget state flags include \\fBactive\\fR, \\fBdisabled\\fR,\n\\fBpressed\\fR, \\fBfocus\\fR, etc.,\n(see \\fIttk::widget(n)\\fR for the full list of state flags).\n.PP\nInstead of a \\fB\\-state\\fR option, every widget now has\na \\fBstate\\fR widget command which is used to set or query\nthe state.\nA \\fIstate specification\\fR is a list of symbolic state names\nindicating which bits are set, each optionally prefixed with an\nexclamation point indicating that the bit is cleared instead.\n.PP\nFor example, the class bindings for the \\fBttk::button\\fR\nwidget are:\n.PP\n.CS\nbind TButton <Enter>\t\t{ %W state active }\nbind TButton <Leave>\t\t{ %W state !active }\nbind TButton <Button-1>\t\t{ %W state pressed }\nbind TButton <Button1-Leave>\t{ %W state !pressed }\nbind TButton <Button1-Enter>\t{ %W state pressed }\nbind TButton <ButtonRelease-1>\t\\e\n    { %W instate {pressed} { %W state !pressed ; %W invoke } }\n.CE\n.PP\nThis specifies that the widget becomes \\fBactive\\fR when\nthe pointer enters the widget, and inactive when it leaves.\nSimilarly it becomes \\fBpressed\\fR when the mouse button is pressed,\nand \\fB!pressed\\fR on the ButtonRelease event.\nIn addition, the button unpresses if\npointer is dragged outside the widget while Button-1 is held down,\nand represses if it's dragged back in.\nFinally, when the mouse button is released, the widget's\n\\fB\\-command\\fR is invoked, but only if the button is currently\nin the \\fBpressed\\fR state.\n(The actual bindings are a little more complicated than the above,\nbut not by much).\n'\\\" Note to self: rewrite that paragraph.  It's horrible.\n.SH \"STYLES\"\n.PP\nEach widget is associated with a \\fIstyle\\fR,\nwhich specifies values for element options.\nStyle names use a recursive dotted notation like layouts and elements;\nby default, widgets use the class name to look up a style in the current theme.\nFor example:\n.PP\n.CS\nttk::\\fBstyle configure\\fR TButton \\e\n\t-background #d9d9d9 \\e\n\t-foreground black \\e\n\t-relief raised \\e\n\t;\n.CE\n.PP\nMany elements are displayed differently depending on the widget state.\nFor example, buttons have a different background when they are active,\na different foreground when disabled, and a different relief when pressed.\nThe \\fBstyle map\\fR command specifies dynamic option settings\nfor a particular style:\n.PP\n.CS\nttk::\\fBstyle map\\fR TButton \\e\n\t-background [list disabled #d9d9d9  active #ececec] \\e\n\t-foreground [list disabled #a3a3a3] \\e\n\t-relief [list {pressed !disabled} sunken] \\e\n\t;\n.CE\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::style(n)\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_label.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::label n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::label \\- Display a text string and/or image\n.SH SYNOPSIS\n\\fBttk::label\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::label\\fR widget displays a textual label and/or image.\nThe label may be linked to a Tcl variable\nto automatically change the displayed text.\n.SO ttk_widget\n\\-anchor\t\\-class\t\\-compound\n\\-cursor\t\\-font\t\\-foreground\n\\-image\t\\-justify\t\\-padding\n\\-state\t\\-style\t\\-takefocus\n\\-text\t\\-textvariable\t\\-underline\n\\-width\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-background frameColor FrameColor\nThe widget's background color.\nIf unspecified, the theme default is used.\n.OP \\-relief relief Relief\n.\\\" Rewrite this:\nSpecifies the 3-D effect desired for the widget border.\nValid values are\n\\fBflat\\fR, \\fBgroove\\fR, \\fBraised\\fR, \\fBridge\\fR, \\fBsolid\\fR,\nand \\fBsunken\\fR.\n.OP \\-wraplength wrapLength WrapLength\nSpecifies the maximum line length (in pixels).\nIf this option is negative or zero,\nthen automatic wrapping is not performed; otherwise\nthe text is split into lines such that no line is longer\nthan the specified value.\n.SH \"WIDGET COMMAND\"\n.PP\nLabel widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::label\\fP is \\fBTLabel\\fP.\n.PP\nDynamic states: \\fBdisabled\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTLabel\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), label(n)\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_labelframe.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2005 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::labelframe n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::labelframe \\- Container widget with optional label\n.SH SYNOPSIS\n\\fBttk::labelframe\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::labelframe\\fR widget is a container used to group other widgets\ntogether.  It has an optional label, which may be a plain text string or\nanother widget.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-padding\n\\-style\t\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.\\\" XXX: Currently included, but may go away:\n.\\\" XXX: .OP -borderwidth borderWidth BorderWidth\n.\\\" XXX: The desired width of the widget border.  Default is theme-dependent.\n.\\\" XXX: .OP -relief relief Relief\n.\\\" XXX: One of the standard Tk border styles:\n.\\\" XXX: \\fBflat\\fR, \\fBgroove\\fR, \\fBraised\\fR, \\fBridge\\fR,\n.\\\" XXX: \\fBsolid\\fR, or \\fBsunken\\fR.\n.\\\" XXX: Default is theme-dependent.\n.OP \\-height height Height\nIf specified, the widget's requested height in pixels.\n(See \\fIttk::frame(n)\\fR for further notes on \\fB\\-width\\fR and\n\\fB\\-height\\fR).\n.OP \\-labelanchor labelAnchor LabelAnchor\nSpecifies where to place the label.\nAllowed values are (clockwise from the top upper left corner):\n\\fBnw\\fR, \\fBn\\fR, \\fBne\\fR, \\fBen\\fR, \\fBe\\fR, \\fBes\\fR,\n\\fBse\\fR, \\fBs\\fR,\\fBsw\\fR, \\fBws\\fR, \\fBw\\fR and \\fBwn\\fR.\nThe default value is theme-dependent.\n.\\\" Alternate explanation: The first character must be one of n, s, e, or w\n.\\\" and specifies which side the label should be placed on;\n.\\\" the remaining characters specify how the label is aligned on that side.\n.\\\" NOTE: Now allows other values as well; leave this undocumented for now\n.OP \\-labelwidget labelWidget LabelWidget\nThe name of a widget to use for the label.\nIf set, overrides the \\fB\\-text\\fR option.\nThe \\fB\\-labelwidget\\fR must be a child of the \\fBlabelframe\\fR widget\nor one of the \\fBlabelframe\\fR's ancestors, and must belong to the\nsame top-level widget as the \\fBlabelframe\\fR.\n.OP \\-text text Text\nSpecifies the text of the label.\n.OP \\-underline underline Underline\nIf set, specifies the integer index (0-based) of a character to\nunderline in the text string.\nThe underlined character is used for mnemonic activation.\nMnemonic activation for a \\fBttk::labelframe\\fR\nsets the keyboard focus to the first child of the \\fBttk::labelframe\\fR widget.\n.OP \\-width width Width\nIf specified, the widget's requested width in pixels.\n.SH \"WIDGET COMMAND\"\n.PP\nLabelframe widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::labelframe\\fP is \\fBTLabelframe\\fP.\nThe text label\nhas a class of \\fBTLabelframe.Label\\fP.\n.PP\nDynamic states: \\fBdisabled\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTLabelframe\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-borderwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-labelmargins\\fP \\fIamount\\fP\n.br\n\\fB\\-labeloutside\\fP \\fIboolean\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.PP\n\\fBTLabelframe.Label\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::frame(n), labelframe(n)\n.SH \"KEYWORDS\"\nwidget, frame, container, label, groupbox\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_menubutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::menubutton n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::menubutton \\- Widget that pops down a menu when pressed\n.SH SYNOPSIS\n\\fBttk::menubutton\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::menubutton\\fR widget displays a textual label and/or image,\nand displays a menu when pressed.\n.SO ttk_widget\n\\-class\t\\-compound\t\\-cursor\n\\-image\t\\-state\t\\-style\n\\-takefocus\t\\-text\t\\-textvariable\n\\-underline\t\\-width\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-direction direction Direction\nSpecifies where the menu is to be popped up relative\nto the menubutton.\nOne of: \\fBabove\\fR, \\fBbelow\\fR, \\fBleft\\fR, \\fBright\\fR,\nor \\fBflush\\fR.  The default is \\fBbelow\\fR.\n\\fBflush\\fR pops the menu up directly over the menubutton.\n.OP \\-menu menu Menu\nSpecifies the path name of the menu associated with the menubutton.\nTo be on the safe side, the menu ought to be a direct child of the\nmenubutton.\n.\\\" not documented: may go away:\n.\\\" .OP \\-anchor anchor Anchor\n.\\\" .OP \\-padding padding Pad\n.SH \"WIDGET COMMAND\"\n.PP\nMenubutton widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.SH \"STANDARD STYLES\"\n.PP\n\\fBTtk::menubutton\\fR widgets support the \\fBToolbutton\\fR style in all\nstandard themes, which is useful for creating widgets for toolbars.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::menubutton\\fP is \\fBTMenubutton\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBdisabled\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTMenubutton\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-arrowsize\\fP \\fIamount\\fP\n.br\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.br\n\\fB\\-width\\fP \\fIamount\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), menu(n), menubutton(n)\n.SH \"KEYWORDS\"\nwidget, button, menu\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_notebook.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::notebook n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::notebook \\- Multi-paned container widget\n.SH SYNOPSIS\n.nf\n\\fBttk::notebook\\fI pathname \\fR?\\fIoptions...\\fR?\n.br\n\\fIpathname \\fBadd\\fI window\\fR ?\\fIoptions...\\fR?\n\\fIpathname \\fBinsert\\fI index window\\fR ?\\fIoptions...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\nA \\fBttk::notebook\\fR widget manages a collection of windows\nand displays a single one at a time.\nEach content window is associated with a \\fItab\\fR,\nwhich the user may select to change the currently-displayed window.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-takefocus\n\\-style\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-height height Height\nIf present and greater than zero,\nspecifies the desired height of the pane area\n(not including internal padding or tabs).\nOtherwise, the maximum height of all panes is used.\n.OP \\-padding padding Padding\nSpecifies the amount of extra space to add around the outside\nof the notebook.\nThe padding is a list of up to four length specifications\n\\fIleft top right bottom\\fR.\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nIn other words, a list of three numbers specify the left, vertical, and right\npadding; a list of two numbers specify the horizontal and the vertical padding;\na single number specifies the same padding all the way around the widget.\n.OP \\-width width Width\nIf present and greater than zero,\nspecifies the desired width of the pane area\n(not including internal padding).\nOtherwise, the maximum width of all panes is used.\n.SH \"TAB OPTIONS\"\nThe following options may be specified for individual notebook panes:\n.OP \\-state state State\nEither \\fBnormal\\fR, \\fBdisabled\\fR or \\fBhidden\\fR.\nIf \\fBdisabled\\fR, then the tab is not selectable.\nIf \\fBhidden\\fR, then the tab is not shown.\n.OP \\-sticky sticky Sticky\nSpecifies how the content window is positioned within the pane area.\nValue is a string containing zero or more of the characters\n\\fBn, s, e,\\fR or \\fBw\\fR.\nEach letter refers to a side (north, south, east, or west)\nthat the content window will\n.QW stick\nto, as per the \\fBgrid\\fR geometry manager.\n.OP \\-padding padding Padding\nSpecifies the amount of extra space to add between the notebook and this pane.\nSyntax is the same as for the widget \\fB\\-padding\\fR option.\n.OP \\-text text Text\nSpecifies a string to be displayed in the tab.\n.OP \\-image image Image\nSpecifies an image to display in the tab.\nSee \\fIttk_widget(n)\\fR for details.\n.OP \\-compound compound Compound\nSpecifies how to display the image relative to the text,\nin the case both \\fB\\-text\\fR and \\fB\\-image\\fR are present.\nSee \\fIlabel(n)\\fR for legal values.\n.OP \\-underline underline Underline\nSpecifies the integer index (0-based) of a character to underline\nin the text string.\nThe underlined character is used for mnemonic activation\nif \\fBttk::notebook::enableTraversal\\fR is called.\n.SH \"TAB IDENTIFIERS\"\nThe \\fItabid\\fR argument to the following commands may take\nany of the following forms:\n.IP \\(bu\nAn integer between zero and the number of tabs;\n.IP \\(bu\nThe name of a content window;\n.IP \\(bu\nA positional specification of the form\n.QW @\\fIx\\fR,\\fIy\\fR ,\nwhich identifies the tab\n.IP \\(bu\nThe literal string\n.QW \\fBcurrent\\fR ,\nwhich identifies the currently-selected tab; or:\n.IP \\(bu\nThe literal string\n.QW \\fBend\\fR ,\nwhich returns the number of tabs\n(only valid for\n.QW \"\\fIpathname \\fBindex\\fR\" ).\n.PP\nIndexes support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nnotebook widgets support the following additional commands:\n.\\\" METHOD: add\n.TP\n\\fIpathname \\fBadd \\fIwindow\\fR ?\\fIoptions...\\fR?\n.\nAdds a new tab to the notebook.\nSee \\fBTAB OPTIONS\\fR for the list of available \\fIoptions\\fR.\nIf \\fIwindow\\fR is currently managed by the notebook but hidden,\nit is restored to its previous position.\n.\\\" METHOD: forget\n.TP\n\\fIpathname \\fBforget \\fItabid\\fR\n.\nRemoves the tab specified by \\fItabid\\fR,\nunmaps and unmanages the associated window.\n.\\\" METHOD: hide\n.TP\n\\fIpathname \\fBhide \\fItabid\\fR\n.\nHides the tab specified by \\fItabid\\fR.\nThe tab will not be displayed, but the associated window\nremains managed by the notebook and its configuration remembered.\nHidden tabs may be restored with the \\fBadd\\fR command.\n.\\\" METHOD: identify\n.TP\n\\fIpathname \\fBidentify\\fI component x y\\fR\n.\nReturns the name of the element under the point given by \\fIx\\fR and \\fIy\\fR,\nor the empty string if no component is present at that location.\nThe following subcommands are supported:\n.RS\n.TP\n\\fIpathname \\fBidentify element\\fI x y\\fR\n.\nReturns the name of the element at the specified location.\n.TP\n\\fIpathname \\fBidentify tab\\fI x y\\fR\n.\nReturns the index of the tab at the specified location.\n.RE\n.\\\" METHOD: index\n.TP\n\\fIpathname \\fBindex \\fItabid\\fR\n.\nReturns the numeric index of the tab specified by \\fItabid\\fR,\nor the total number of tabs if \\fItabid\\fR is the string\n.QW \\fBend\\fR .\n.\\\" METHOD: insert\n.TP\n\\fIpathname \\fBinsert \\fIpos subwindow options...\\fR\n.\nInserts a pane at the specified position.\n\\fIpos\\fR is either the string \\fBend\\fR, an integer index,\nor the name of a managed subwindow.\nIf \\fIsubwindow\\fR is already managed by the notebook,\nmoves it to the specified position.\nSee \\fBTAB OPTIONS\\fR for the list of available options.\n.\\\" METHOD: select\n.TP\n\\fIpathname \\fBselect\\fR ?\\fItabid\\fR?\n.\nSelects the specified tab.\nThe associated content window will be displayed,\nand the previously-selected window (if different) is unmapped.\nIf \\fItabid\\fR is omitted, returns the widget name of the\ncurrently selected pane.\n.\\\" METHOD: tab\n.TP\n\\fIpathname \\fBtab \\fItabid\\fR ?\\fI\\-option \\fR?\\fIvalue ...\\fR\n.\nQuery or modify the options of the specific tab.\nIf no \\fI\\-option\\fR is specified,\nreturns a dictionary of the tab option values.\nIf one \\fI\\-option\\fR is specified,\nreturns the value of that \\fIoption\\fR.\nOtherwise, sets the \\fI\\-option\\fRs to the corresponding \\fIvalue\\fRs.\nSee \\fBTAB OPTIONS\\fR for the available options.\n.\\\" METHOD: tabs\n.TP\n\\fIpathname \\fBtabs\\fR\n.\nReturns the list of windows managed by the notebook, in the index order of\ntheir associated tabs.\n.SH \"KEYBOARD TRAVERSAL\"\nTo enable keyboard traversal for a toplevel window\ncontaining a notebook widget \\fI$nb\\fR, call:\n.CS\nttk::notebook::enableTraversal $nb\n.CE\n.PP\nThis will extend the bindings for the toplevel window\ncontaining the notebook as follows:\n.IP \\(bu\n\\fBControl-Tab\\fR selects the tab following the currently selected one.\n.IP \\(bu\n\\fBControl-Shift-Tab\\fR selects the tab preceding the currently selected one.\n.IP \\(bu\n\\fBAlt-\\fIK\\fR, where \\fIK\\fR is the mnemonic (underlined) character\nof any tab, will select that tab.\n.PP\nMultiple notebooks in a single toplevel may be enabled for traversal,\nincluding nested notebooks.\nHowever, notebook traversal only works properly if all panes\nare direct children of the notebook.\n.SH \"VIRTUAL EVENTS\"\nThe notebook widget generates a \\fB<<NotebookTabChanged>>\\fR\nvirtual event after a new tab is selected.\n.SH \"EXAMPLE\"\n.CS\npack [\\fBttk::notebook\\fR .nb]\n\\&.nb add [frame .nb.f1] -text \"First tab\"\n\\&.nb add [frame .nb.f2] -text \"Second tab\"\n\\&.nb select .nb.f2\nttk::notebook::enableTraversal .nb\n.CE\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::notebook\\fP is \\fBTNotebook\\fP.  The tab has\na class name of \\fBTNotebook.Tab\\fP\n.PP\nDynamic states: \\fBactive\\fP, \\fBdisabled\\fP, \\fBselected\\fP.\n.PP\n\\fBTNotebook\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-tabmargins\\fP \\fIpadding\\fP\n.br\n\\fB\\-tabposition\\fP \\fIposition\\fP\n.RS\nSpecifies the position of the tab row or column as a string of length\n1 or 2.  The first character indicates the side as \\fBn\\fP, \\fBs\\fP,\n\\fBw\\fP, or \\fBe\\fP, while the second character (if present) is the\nsticky bit (specified as \\fBw\\fP, \\fBe\\fP, \\fBn\\fP, or \\fBs\\fP) within\nthe tab position.  The default position is \\fBn\\fP for the \\fBaqua\\fP\ntheme and \\fBnw\\fP for all the other built-in themes.\n.RE\n.br\n\\fB\\-tabplacement\\fP \\fIplacement\\fP\n.RS\nSpecifies the placement (anchor) of the tabs within the tab row or column\nas a string of length 1 or 2.  The first character indicates the side as\n\\fBw\\fP, \\fBe\\fP, \\fBn\\fP, or \\fBs\\fP, while the second character (if\npresent) is the sticky bit (specified as \\fBs\\fP, \\fBn\\fP, \\fBe\\fP, or\n\\fBw\\fP) within the tab placement.  For example, the tab placement \\fBws\\fP\nmeans: attach the west (left) side of each tab to the previous one and\nalign the south (bottom) edges with each other.  Similarly, the tab\nplacement \\fBse\\fP specifies to attach the south (bottom) side of each tab\nto the previous one and align the east (right) edges with each other.  The\ndefault placement depends on the first character of the tab position:\n\\fBws\\fP for \\fBn*\\fP, \\fBwn\\fP for \\fBs*\\fP, \\fBne\\fP for \\fBw*\\fP, and \n\\fBnw\\fP for \\fBe*\\fP.\n.RE\n.br\n.PP\n\\fBTNotebook.Tab\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-expand\\fP \\fIpadding\\fP\n.RS\nDefines how much the tab grows in size.  Usually used with the\n\\fBselected\\fP dynamic state.  \\fB\\-tabmargins\\fP should be\nset appropriately so that there is room for the tab growth.\nFor example, the Ttk library file \\fBvistaTheme.tcl\\fP contains\nthe lines\n.CS\nttk::style configure TNotebook -tabmargins {2 2 2 0}\nttk::style map TNotebook.Tab -expand {selected {2 2 2 2}}\n.CE\nwhich are valid for the default value \\fBnw\\fP of the \\fB\\-tabposition\\fP\nstyle option.  For a \\fBttk::notebook\\fP style \\fBnbStyle\\fP defined by\n.CS\nset nbStyle SW.TNotebook\nttk::style configure $nbStyle -tabposition sw\n.CE\nyou will have to adapt the above settings as follows:\n.CS\nttk::style configure $nbStyle -tabmargins {2 0 2 2}\nttk::style map $nbStyle.Tab -expand {selected {2 2 2 2}}\n.CE\nThe easiest way to do this is to invoke the library procedure\n\\fBttk::configureNotebookStyle\\fP with \\fB$nbStyle\\fP as argument, after\nsetting the style's \\fB\\-tabposition\\fP option.\n.RE\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.RS\nSome themes use a different \\fIpadding\\fP for the selected tab.  For example,\nthe Ttk library file \\fBclamTheme.tcl\\fP contains the lines\n.CS\nttk::style configure TNotebook.Tab \\\\\n    -padding {4.5p 1.5p 4.5p 1.5p}\nttk::style map TNotebook.Tab \\\\\n    -padding {selected {4.5p 3p 4.5p 1.5p}}\n.CE\nwhich are valid for the default value \\fBnw\\fP of the \\fB\\-tabposition\\fP\nstyle option.  For a \\fBttk::notebook\\fP style having a different tab position\nyou will have to adapt the above settings accordingly.  Again, the easiest way\nto do this is to invoke the library procedure \\fBttk::configureNotebookStyle\\fP\nwith the style name as argument, after setting the style's \\fB\\-tabposition\\fP\noption.\n.RE\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), grid(n)\n.SH \"KEYWORDS\"\npane, tab\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_panedwindow.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2005 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::panedwindow n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::panedwindow \\- Multi-pane container window\n.SH SYNOPSIS\n.nf\n\\fBttk::panedwindow\\fI pathname \\fR?\\fIoptions\\fR?\n.br\n\\fIpathname \\fBadd\\fI window\\fR ?\\fIoptions...\\fR?\n\\fIpathname \\fBinsert\\fI index window\\fR ?\\fIoptions...\\fR?\n.fi\n.BE\n.SH DESCRIPTION\nA \\fBttk::panedwindow\\fR widget displays a number of subwindows,\nstacked either vertically or horizontally.\nThe user may adjust the relative sizes of the subwindows\nby dragging the sash between panes.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-takefocus\n\\-style\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-orient orient Orient\nSpecifies the orientation of the window.\nIf \\fBvertical\\fR, subpanes are stacked top-to-bottom;\nif \\fBhorizontal\\fR, subpanes are stacked left-to-right.\n.OP \\-width width Width\nIf present and greater than zero,\nspecifies the desired width of the widget in pixels.\nOtherwise, the requested width is determined by the width\nof the managed windows.\n.OP \\-height height Height\nIf present and greater than zero,\nspecifies the desired height of the widget in pixels.\nOtherwise, the requested height is determined by the height\nof the managed windows.\n.SH \"PANE OPTIONS\"\nThe following options may be specified for each pane:\n.OP \\-weight weight Weight\nAn integer specifying the relative stretchability of the pane.\nWhen the paned window is resized, the extra space is added\nor subtracted to each pane proportionally to its \\fB\\-weight\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\npanedwindow widgets support the following additional commands:\n.\\\" METHOD: add\n.TP\n\\fIpathname \\fBadd \\fIsubwindow options...\\fR\n.\nAdds a new pane to the window.\nSee \\fBPANE OPTIONS\\fR for the list of available options.\n.\\\" METHOD: forget\n.TP\n\\fIpathname \\fBforget \\fIpane\\fR\n.\nRemoves the specified subpane from the widget.\n\\fIpane\\fR is either an integer index or the name of a managed subwindow.\n.\\\" METHOD: identify\n.TP\n\\fIpathname \\fBidentify \\fIcomponent x y\\fR\n.\nReturns the name of the element under the point given by \\fIx\\fR and \\fIy\\fR,\nor the empty string if no component is present at that location.\nIf \\fIcomponent\\fR is omitted, it defaults to \\fBsash\\fR.\nThe following subcommands are supported:\n.RS\n.TP\n\\fIpathname \\fBidentify element \\fIx y\\fR\n.\nReturns the name of the element at the specified location.\n.TP\n\\fIpathname \\fBidentify sash \\fIx y\\fR\n.\nReturns the index of the sash at the specified location.\n.RE\n.\\\" METHOD: insert\n.TP\n\\fIpathname \\fBinsert \\fIpos subwindow options...\\fR\n.\nInserts a pane at the specified position.\n\\fIpos\\fR is either the string \\fBend\\fR, an integer index,\nor the name of a managed subwindow.\nIf \\fIsubwindow\\fR is already managed by the paned window,\nmoves it to the specified position.\nSee \\fBPANE OPTIONS\\fR for the list of available options.\n.\\\" METHOD: pane\n.TP\n\\fIpathname \\fBpane \\fIpane \\-option \\fR?\\fIvalue \\fR?\\fI\\-option value...\\fR\n.\nQuery or modify the options of the specified \\fIpane\\fR,\nwhere \\fIpane\\fR is either an integer index or the name of a managed subwindow.\nIf no \\fI\\-option\\fR is specified, returns a dictionary of the pane\noption values.\nIf one \\fI\\-option\\fR is specified, returns the value of that \\fIoption\\fR.\nOtherwise, sets the \\fI\\-option\\fRs to the corresponding \\fIvalue\\fRs.\n.\\\" METHOD: panes\n.TP\n\\fIpathname \\fBpanes\\fR\n.\nReturns the list of all windows managed by the widget, in the index order of\ntheir associated panes.\n.\\\" METHOD: sashpos\n.TP\n\\fIpathname \\fBsashpos \\fIindex\\fR ?\\fInewpos\\fR?\n.\nIf \\fInewpos\\fR is specified, sets the position\nof sash number \\fIindex\\fR.\nMay adjust the positions of adjacent sashes\nto ensure that positions are monotonically increasing.\nSash positions are further constrained to be between 0\nand the total size of the widget.\n.\\\" Full story: \"total size\" is either the -height (resp -width),\n.\\\" or the actual window height (resp actual window width),\n.\\\" depending on which changed most recently.\nReturns the new position of sash number \\fIindex\\fR.\n.\\\" Full story: new position may be different than the requested position.\n.SH \"VIRTUAL EVENTS\"\n.PP\nThe panedwindow widget generates an \\fB<<EnteredChild>>\\fR virtual event on\nLeaveNotify/NotifyInferior events.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::panedwindow\\fP is \\fBTPanedwindow\\fP.  The\nsash has a class name of \\fBSash\\fP.\n.PP\n\\fBTPanedwindow\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.PP\n\\fBSash\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-gripsize\\fP \\fIsize\\fP (number of screen units)\n.br\n\\fB\\-handlepad\\fP \\fIamount\\fP\n.br\n\\fB\\-handlesize\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-sashpad\\fP \\fIamount\\fP\n.br\n\\fB\\-sashrelief\\fP \\fIrelief\\fP\n.br\n\\fB\\-sashthickness\\fP \\fIamount\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::notebook(n), panedwindow(n)\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_progressbar.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2005 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::progressbar n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::progressbar \\- Provide progress feedback\n.SH SYNOPSIS\n\\fBttk::progressbar\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::progressbar\\fR widget shows the status of a long-running\noperation.  They can operate in two modes: \\fIdeterminate\\fR mode shows the\namount completed relative to the total amount of work to be done, and\n\\fIindeterminate\\fR mode provides an animated display to let the user know\nthat something is happening.\n.PP\nIf the value of \\fB\\-orient\\fR is \\fBhorizontal\\fR a text string can be\ndisplayed inside the progressbar. This string can be configured using\nthe \\fB\\-anchor\\fR, \\fB\\-font\\fR, \\fB\\-foreground\\fR, \\fB\\-justify\\fR,\n\\fB\\-text\\fR and \\fB\\-wraplength\\fR options. If the value of \\fB\\-orient\\fR\nis \\fBvertical\\fR then these options are ignored.\n.SO ttk_widget\n\\-anchor\t\\-class\t\\-cursor\n\\-font\t\\-foreground\t\\-justify\t\\-style\n\\-takefocus\t\\-text\t\\-wraplength\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-length length Length\nSpecifies the length of the long axis of the progress bar\n(width if horizontal, height if vertical). The value may have any of the forms\nacceptable to \\fBTk_GetPixels\\fR.\n.OP \\-maximum maximum Maximum\nA floating point number specifying the maximum \\fB\\-value\\fR.\nDefaults to 100.\n.OP \\-mode mode Mode\nOne of \\fBdeterminate\\fR or \\fBindeterminate\\fR.\n.OP \\-orient orient Orient\nOne of \\fBhorizontal\\fR or \\fBvertical\\fR.\nSpecifies the orientation of the progress bar.\n.OP \\-phase phase Phase\nRead-only option.\nThe widget periodically increments the value of this option\nwhenever the \\fB\\-value\\fR is greater than 0 and,\nin \\fIdeterminate\\fR mode, less than \\fB\\-maximum\\fR.\nThis option may be used by the current theme\nto provide additional animation effects.\n.OP \\-value value Value\nThe current value of the progress bar.\nIn \\fIdeterminate\\fR mode, this represents the amount of work completed.\nIn \\fIindeterminate\\fR mode, it is interpreted modulo \\fB\\-maximum\\fR;\nthat is, the progress bar completes one\n.QW cycle\nwhen the \\fB\\-value\\fR increases by \\fB\\-maximum\\fR.\nIf \\fB\\-variable\\fR is set to an existing variable, specifying \\fB\\-value\\fR\nhas no effect (the variable value takes precedence).\n.OP \\-variable variable Variable\nThe name of a global Tcl variable which is linked to the \\fB\\-value\\fR.\nIf specified to an existing variable, the \\fB\\-value\\fR of the progress bar is\nautomatically set to the value of the variable whenever\nthe latter is modified.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nprogressbar widgets support the following additional commands:\n.\\\" METHOD: start\n.TP\n\\fIpathName \\fBstart\\fR ?\\fIinterval\\fR?\n.\nBegin autoincrement mode:\nschedules a recurring timer event that calls \\fBstep\\fR\nevery \\fIinterval\\fR milliseconds.\nIf omitted, \\fIinterval\\fR defaults to 50 milliseconds (20 steps/second).\n.\\\" METHOD: step\n.TP\n\\fIpathName \\fBstep\\fR ?\\fIamount\\fR?\n.\nIncrements the \\fB\\-value\\fR by \\fIamount\\fR.\n\\fIamount\\fR defaults to 1.0 if omitted.\n.\\\" METHOD: stop\n.TP\n\\fIpathName \\fBstop\\fR\n.\nStop autoincrement mode:\ncancels any recurring timer event initiated by \\fIpathName \\fBstart\\fR.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::progressbar\\fP is \\fBTProgressbar\\fP.\n.PP\n\\fBTProgressbar\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-maxphase\\fP\n.RS\nFor the aqua theme.\n.RE\n\\fB\\-period\\fP\n.RS\nFor the aqua theme.\n.RE\n\\fB\\-troughcolor\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n)\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_radiobutton.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::radiobutton n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::radiobutton \\- Mutually exclusive option widget\n.SH SYNOPSIS\n\\fBttk::radiobutton\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\n\\fBttk::radiobutton\\fR widgets are used in groups to show or change\na set of mutually-exclusive options.\nRadiobuttons are linked to a Tcl variable,\nand have an associated value; when a radiobutton is clicked,\nit sets the variable to its associated value.\n.SO ttk_widget\n\\-class\t\\-compound\t\\-cursor\n\\-image\t\\-state\t\\-style\n\\-takefocus\t\\-text\t\\-textvariable\n\\-underline\t\\-width\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nA Tcl script to evaluate whenever the widget is invoked.\n.OP \\-value Value Value\nThe value to store in the associated \\fB\\-variable\\fR\nwhen the widget is selected.\n.OP \\-variable variable Variable\nThe name of a global variable whose value is linked to the widget.\nDefault value is \\fB::selectedButton\\fR.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nradiobutton widgets support the following additional commands:\n.\\\" METHOD: invoke\n.TP\n\\fIpathname\\fB invoke\\fR\n.\nSets the \\fB\\-variable\\fR to the \\fB\\-value\\fR, selects the widget,\nand evaluates the associated \\fB\\-command\\fR.\nReturns the result of the \\fB\\-command\\fR, or the empty\nstring if no \\fB\\-command\\fR is specified.\n.\\\" Missing: select, deselect.  Useful?\n.\\\" Missing: flash.  This is definitely not useful.\n.SH \"WIDGET STATES\"\n.PP\nThe widget does not respond to user input if the \\fBdisabled\\fR state is set.\nThe widget sets the \\fBselected\\fR state whenever\nthe linked \\fB\\-variable\\fR is set to the widget's \\fB\\-value\\fR,\nand clears it otherwise.\nThe widget sets the \\fBalternate\\fR state whenever the\nlinked \\fB\\-variable\\fR is unset.\n(The \\fBalternate\\fR state may be used to indicate a\n.QW tri-state\nor\n.QW indeterminate\nselection.)\n.SH \"STANDARD STYLES\"\n.PP\n\\fBTtk::radiobutton\\fR widgets support the \\fBToolbutton\\fR style in all\nstandard themes, which is useful for creating widgets for toolbars.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::radiobutton\\fP is \\fBTRadiobutton\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBalternate\\fP, \\fBdisabled\\fP,\n\\fBpressed\\fP, \\fBreadonly\\fP, \\fBselected\\fP.\n.PP\n\\fBTRadiobutton\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-compound\\fP \\fIcompound\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatorbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatorcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatormargin\\fP \\fIpadding\\fP\n.br\n\\fB\\-indicatorrelief\\fP \\fIrelief\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::checkbutton(n), radiobutton(n)\n.SH \"KEYWORDS\"\nwidget, button, option\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_scale.n",
    "content": ".\\\"\n.\\\" Copyright (c) 2008 Donal Fellows\n.\\\"\n.\\\" See the file \"license.terms\" for information on usage and redistribution\n.\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n.\\\"\n.TH ttk::scale n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::scale \\- Create and manipulate a scale widget\n.SH SYNOPSIS\n\\fBttk::scale \\fIpathName \\fR?\\fIoptions...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::scale\\fR widget is typically used to control the numeric value of a\nlinked variable that varies uniformly over some range. A scale displays a\n\\fIslider\\fR that can be moved along over a \\fItrough\\fR, with the relative\nposition of the slider over the trough indicating the value of the variable.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-style\n\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies the prefix of a Tcl command to invoke whenever the scale's value is\nchanged via a widget command. The actual command consists of this option\nfollowed by a space and a real number indicating the new value of the scale.\n.OP \\-from from From\nA real value corresponding to the left or top end of the scale.\n.OP \\-length length Length\nSpecifies the desired long dimension of the scale in screen units (i.e. any of\nthe forms acceptable to \\fBTk_GetPixels\\fR). For vertical scales this is the\nscale's height; for horizontal scales it is the scale's width.\n.OP \\-orient orient Orient\nSpecifies which orientation whether the widget should be laid out horizontally\nor vertically. Must be either \\fBhorizontal\\fR or \\fBvertical\\fR or an\nabbreviation of one of these.\n.OP \\-to to To\nSpecifies a real value corresponding to the right or bottom end of the scale.\nThis value may be either less than or greater than the \\fB\\-from\\fR option.\n.OP \\-value value Value\nSpecifies the current floating-point value of the variable.\nIf \\fB\\-variable\\fR is set to an existing variable, specifying \\fB\\-value\\fR\nhas no effect (the variable value takes precedence).\n.OP \\-variable variable Variable\nSpecifies the name of a global variable to link to the scale. Whenever the\nvalue of the variable changes, the scale will update to reflect this value.\nWhenever the scale is manipulated interactively, the variable will be modified\nto reflect the scale's new value.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nscale widgets support the following additional commands:\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget \\fR?\\fIx y\\fR?\n.\nGet the current value of the \\fB\\-value\\fR option, or the value corresponding\nto the coordinates \\fIx,y\\fR if they are specified. \\fIX\\fR and \\fIy\\fR are\npixel coordinates relative to the scale widget origin.\n.\\\" METHOD: see\n.TP\n\\fIpathName \\fBset \\fIvalue\\fR\n.\nSet the value of the widget (i.e. the \\fB\\-value\\fR option) to \\fIvalue\\fR.\nThe value will be clipped to the range given by the \\fB\\-from\\fR and\n\\fB\\-to\\fR options. Note that setting the linked variable (i.e. the variable\nnamed in the \\fB\\-variable\\fR option) does not cause such clipping.\n.SH \"INTERNAL COMMANDS\"\n.PP\n.\\\" METHOD: coords\n.TP\n\\fIpathName \\fBcoords \\fR?\\fIvalue\\fR?\n.\nGet the coordinates corresponding to \\fIvalue\\fR, or the coordinates\ncorresponding to the current value of the \\fB\\-value\\fR option if \\fIvalue\\fR\nis omitted.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::scale\\fP is \\fBTScale\\fP.\n.PP\nDynamic states: \\fBactive\\fP.\n.PP\n\\fBTScale\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-borderwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-groovewidth\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-sliderwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-troughcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-troughrelief\\fP \\fIrelief\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), scale(n)\n.SH KEYWORDS\nscale, slider, trough, widget\n.\\\" Local Variables:\n.\\\" mode: nroff\n.\\\" fill-column: 78\n.\\\" End:\n"
  },
  {
    "path": "doc/ttk_scrollbar.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::scrollbar n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::scrollbar \\- Control the viewport of a scrollable widget\n.SH SYNOPSIS\n\\fBttk::scrollbar\\fI pathName \\fR?\\fIoptions...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\n\\fBttk::scrollbar\\fR widgets are typically linked to an associated window\nthat displays a document of some sort, such as a file being edited or a\ndrawing.\nA scrollbar displays a \\fIthumb\\fR in the middle portion of the scrollbar,\nwhose position and size provides information about the portion of the\ndocument visible in the associated window.\nThe thumb may be dragged by the user to control the visible region.\nDepending on the theme, two or more arrow buttons may also be present;\nthese are used to scroll the visible region in discrete units.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-style\n\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nA Tcl script prefix to evaluate\nto change the view in the widget associated with the scrollbar.\nAdditional arguments are appended to the value of this option,\nas described in \\fBSCROLLING COMMANDS\\fR below,\nwhenever the user requests a view change by manipulating the scrollbar.\n.RS\n.PP\nThis option typically consists of a two-element list,\ncontaining the name of a scrollable widget followed by\neither \\fBxview\\fR (for horizontal scrollbars)\nor \\fByview\\fR (for vertical scrollbars).\n.RE\n.OP \\-orient orient Orient\nOne of \\fBhorizontal\\fR or \\fBvertical\\fR.\nSpecifies the orientation of the scrollbar.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\ncommands (see \\fBttk::widget\\fR),\nscrollbar widgets support the following additional commands:\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the scrollbar settings in the form of a list whose\nelements are the arguments to the most recent \\fBset\\fR widget command.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset \\fIfirst last\\fR\n.\nThis command is normally invoked by the scrollbar's associated widget\nfrom an \\fB\\-xscrollcommand\\fR or \\fB\\-yscrollcommand\\fR callback.\nSpecifies the visible range to be displayed.\n\\fIfirst\\fR and \\fIlast\\fR are real fractions between 0 and 1.\n.SH \"INTERNAL COMMANDS\"\n.PP\nThe following widget commands are used internally\nby the \\fBTScrollbar\\fP widget class bindings.\n.\\\" METHOD: delta\n.TP\n\\fIpathName \\fBdelta \\fIdeltaX deltaY\\fR\n.\nReturns a real number indicating the fractional change in\nthe scrollbar setting that corresponds to a given change\nin thumb position.  For example, if the scrollbar is horizontal,\nthe result indicates how much the scrollbar setting must change\nto move the thumb \\fIdeltaX\\fR pixels to the right (\\fIdeltaY\\fR is\nignored in this case).\nIf the scrollbar is vertical, the result indicates how much the\nscrollbar setting must change to move the thumb \\fIdeltaY\\fR pixels\ndown.  The arguments and the result may be zero or negative.\n.\\\" METHOD: fraction\n.TP\n\\fIpathName \\fBfraction \\fIx y\\fR\n.\nReturns a real number between 0 and 1 indicating where the point\ngiven by \\fIx\\fR and \\fIy\\fR lies in the trough area of the scrollbar,\nwhere 0.0 corresponds to the top or left of the trough\nand 1.0 corresponds to the bottom or right.\n\\fIX\\fR and \\fIy\\fR are pixel coordinates relative to the scrollbar\nwidget.\nIf \\fIx\\fR and \\fIy\\fR refer to a point outside the trough, the closest\npoint in the trough is used.\n.SH \"SCROLLING COMMANDS\"\n.PP\nWhen the user interacts with the scrollbar, for example by dragging\nthe thumb, the scrollbar notifies the associated widget that it\nmust change its view.\nThe scrollbar makes the notification by evaluating a Tcl command\ngenerated from the scrollbar's \\fB\\-command\\fR option.\nThe command may take any of the following forms.\nIn each case, \\fIprefix\\fR is the contents of the\n\\fB\\-command\\fR option, which usually has a form like \\fB.t yview\\fR\n.TP\n\\fIprefix \\fBmoveto \\fIfraction\\fR\n.\n\\fIFraction\\fR is a real number between 0 and 1.\nThe widget should adjust its view so that the point given\nby \\fIfraction\\fR appears at the beginning of the widget.\nIf \\fIfraction\\fR is 0 it refers to the beginning of the\ndocument.  1.0 refers to the end of the document, 0.333\nrefers to a point one-third of the way through the document,\nand so on.\n.TP\n\\fIprefix \\fBscroll \\fInumber \\fBpages\\fR\n.\nThe widget should adjust its view by \\fInumber\\fR pages.\nIt is up to the widget to define the meaning of a page;  typically\nit is slightly less than what fits in the window, so that there\nis a slight overlap between the old and new views.\n\\fINumber\\fR is either 1, which means the next page should\nbecome visible, or \\-1, which means that the previous page should\nbecome visible.\n.TP\n\\fIprefix \\fBscroll \\fInumber \\fBunits\\fR\n.\nThe widget should adjust its view by \\fInumber\\fR units.\nThe units are defined in whatever way makes sense for the widget,\nsuch as characters or lines in a text widget.\n\\fINumber\\fR is either 1, which means one unit should scroll off\nthe top or left of the window, or \\-1, which means that one unit\nshould scroll off the bottom or right of the window.\n.SH \"WIDGET STATES\"\n.PP\nThe scrollbar automatically sets the \\fBdisabled\\fR state bit.\nwhen the entire range is visible (range is 0.0 to 1.0),\nand clears it otherwise.\nIt also sets the \\fBactive\\fR and \\fBpressed\\fR state flags\nof individual elements, based on the position and state of the mouse pointer.\n.SH EXAMPLE\n.PP\n.CS\nset f [frame .f]\n\\fBttk::scrollbar\\fR $f.hsb -orient horizontal -command [list $f.t xview]\n\\fBttk::scrollbar\\fR $f.vsb -orient vertical -command [list $f.t yview]\ntext $f.t -xscrollcommand [list $f.hsb set] -yscrollcommand [list $f.vsb set]\ngrid $f.t -row 0 -column 0 -sticky nsew\ngrid $f.vsb -row 0 -column 1 -sticky nsew\ngrid $f.hsb -row 1 -column 0 -sticky nsew\ngrid columnconfigure $f 0 -weight 1\ngrid rowconfigure $f 0 -weight 1\npack $f\n.CE\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::scrollbar\\fP is \\fBTScrollbar\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBdisabled\\fP.\n.PP\n\\fBTScrollbar\\fP (or more specifically \\fBVertical.TScrollbar\\fP and\n\\fBHorizontal.TScrollbar\\fP) styling options that are configurable with\n\\fBttk::style\\fP are:\n.PP\n\\fB\\-arrowcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-arrowsize\\fP \\fIamount\\fP\n.br\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP (color of the dark part of the 3D relief)\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-gripsize\\fP \\fIsize\\fP (number of screen units)\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP (color of the light part of the 3D relief)\n.br\n\\fB\\-troughcolor\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), scrollbar(n)\n.SH KEYWORDS\nscrollbar, widget\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_separator.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::separator n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::separator \\- Separator bar\n.SH SYNOPSIS\n\\fBttk::separator\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::separator\\fR widget displays a horizontal or vertical separator\nbar.\n.SO ttk_widget\n\\-class\t\\-cursor\n\\-style\t\\-takefocus\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-orient orient Orient\nOne of \\fBhorizontal\\fR or \\fBvertical\\fR.\nSpecifies the orientation of the separator.\n.SH \"WIDGET COMMAND\"\n.PP\nSeparator widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.PP\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::separator\\fP is \\fBTSeparator\\fP.\n.PP\n\\fBTSeparator\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n)\n.SH \"KEYWORDS\"\nwidget, separator\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_sizegrip.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2006 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::sizegrip n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::sizegrip \\- Bottom-right corner resize widget\n.SH SYNOPSIS\n\\fBttk::sizegrip\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::sizegrip\\fR widget (also known as a \\fIgrow box\\fR)\nallows the user to resize the containing toplevel window\nby pressing and dragging the grip.\n.SO ttk_widget\n\\-class\t\\-cursor\n\\-style\t\\-takefocus\n.SE\n.SH \"WIDGET COMMAND\"\n.PP\nSizegrip widgets support the standard commands\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR and \\fBstyle\\fR\n(see \\fBttk::widget\\fR).\n.SH \"PLATFORM-SPECIFIC NOTES\"\n.PP\nOn macOS, toplevel windows automatically include a built-in\nsize grip by default.\nAdding a \\fBttk::sizegrip\\fR there is harmless, since\nthe built-in grip will just mask the widget.\n.SH EXAMPLES\n.PP\nUsing pack:\n.CS\npack [ttk::frame $top.statusbar] -side bottom -fill x\npack [\\fBttk::sizegrip\\fR $top.statusbar.grip] -side right -anchor se\n.CE\n.PP\nUsing grid:\n.CS\ngrid [\\fBttk::sizegrip\\fR $top.statusbar.grip] \\e\n    -row $lastRow -column $lastColumn -sticky se\n# ... optional: add vertical scrollbar in $lastColumn,\n# ... optional: add horizontal scrollbar in $lastRow\n.CE\n.SH \"BUGS\"\n.PP\nIf the containing toplevel's position was specified\nrelative to the right or bottom of the screen\n(e.g.,\n.QW \"\\fBwm geometry ... \\fIw\\fBx\\fIh\\fB\\-\\fIx\\fB\\-\\fIy\\fR\"\ninstead of\n.QW \"\\fBwm geometry ... \\fIw\\fBx\\fIh\\fB+\\fIx\\fB+\\fIy\\fR\" ),\nthe sizegrip widget will not resize the window.\n.PP\n\\fBttk::sizegrip\\fR widgets only support\n.QW southeast\nresizing.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::sizegrip\\fP is \\fBTSizegrip\\fP.\n.PP\n\\fBTSizegrip\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n)\n.SH \"KEYWORDS\"\nwidget, sizegrip, grow box\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_spinbox.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2008 Pat Thoyts\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::spinbox n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::spinbox \\- Selecting text field widget\n.SH SYNOPSIS\n\\fBttk::spinbox\\fI pathName \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::spinbox\\fR widget is a \\fBttk::entry\\fR widget with built-in\nup and down buttons that are used to either modify a numeric value or\nto select among a set of values. The widget implements all the features\nof the \\fBttk::entry\\fR widget including support of the\n\\fB\\-textvariable\\fR option to link the value displayed by the widget\nto a Tcl variable.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-state\n\\-style\t\\-takefocus\t\\-xscrollcommand\n\\-placeholder\t\\-placeholderforeground\n.SE\n.SO ttk_entry\n\\-validate\t\\-validatecommand\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies a Tcl command to be invoked whenever a spinbutton is invoked.\n.OP \\-format format Format\nSpecifies an alternate format to use when setting the string value\nwhen using the \\fB\\-from\\fR and \\fB\\-to\\fR range.\nThis must be a format specifier of the form \\fB%<pad>.<pad>f\\fR,\nas it will format a floating-point number.\n.OP \\-from from From\nA floating-point value specifying the lowest value for the spinbox. This is\nused in conjunction with \\fB\\-to\\fR and \\fB\\-increment\\fR to set a numerical\nrange.\n.OP \\-increment increment Increment\nA floating-point value specifying the change in value to be applied each\ntime one of the widget spin buttons is pressed. The up button applies a\npositive increment, the down button applies a negative increment.\n.OP \\-to to To\nA floating-point value specifying the highest permissible value for the\nwidget. See also \\fB\\-from\\fR and \\fB\\-increment\\fR.\nrange.\n.OP \\-values values Values\nThis must be a Tcl list of values. If this option is set then this will\noverride any range set using the \\fB\\-from\\fR, \\fB\\-to\\fR and\n\\fB\\-increment\\fR options. The widget will instead use the values\nspecified beginning with the first value.\n.OP \\-wrap wrap Wrap\nMust be a proper boolean value.  If on, the spinbox will wrap around the\nvalues of data in the widget.\n.SH \"INDICES\"\n.PP\nSee the \\fBttk::entry\\fR manual for information about indexing characters.\n.SH \"VALIDATION\"\n.PP\nSee the \\fBttk::entry\\fR manual for information about using the\n\\fB\\-validate\\fR and \\fB\\-validatecommand\\fR options.\n.SH \"WIDGET COMMAND\"\n.PP\nThe following subcommands are possible for spinbox widgets in addition to\nthe commands described for the \\fBttk::entry\\fR widget:\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget\\fR\n.\nReturns the spinbox's current value.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset \\fIvalue\\fR\n.\nSet the spinbox string to \\fIvalue\\fR. If a \\fB\\-format\\fR option has\nbeen configured then this format will be applied. If formatting fails\nor is not set or the \\fB\\-values\\fR option has been used then the value\nis set directly.\n.SH \"VIRTUAL EVENTS\"\n.PP\nThe spinbox widget generates a \\fB<<Increment>>\\fR virtual event when\nthe user presses <Up>, and a \\fB<<Decrement>>\\fR virtual event when the\nuser presses <Down>.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::spinbox\\fP is \\fBTSpinbox\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBdisabled\\fP, \\fBfocus\\fP, \\fBreadonly\\fP.\n.PP\n\\fBTSpinbox\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-arrowcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-arrowsize\\fP \\fIamount\\fP\n.br\n\\fB\\-background\\fP \\fIcolor\\fP\n.RS\nFor backwards compatibility, when using the aqua theme (for macOS), this\noption behaves as an alias for the \\fB\\-fieldbackground\\fP provided that no\nvalue is specified for \\fB\\-fieldbackground\\fP. Otherwise it is ignored.\n.RE\n\\fB\\-bordercolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-darkcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-fieldbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-insertcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-insertwidth\\fP \\fIamount\\fP\n.br\n\\fB\\-lightcolor\\fP \\fIcolor\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.br\n\\fB\\-placeholderforeground\\fP \\fIcolor\\fP\n.br\n\\fB\\-selectbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-selectforeground\\fP \\fIcolor\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.PP\nBesides the standard \\fBTSpinbox\\fP layout with small arrow buttons, in\nwhich the up arrow is placed above the down arrow, \\fBttk::spinbox\\fP\nwidgets support the \\fBWide.TSpinbox\\fP style, whose up and down arrows\nare of a more user-friendly size and in which the up arrow is placed to\nthe right of the down arrow.  The size of these arrows depends on the\ndisplay's scaling level and Tk's scaling factor given by \\fB[tk scaling]\\fP\nat the time the first themed spinbox widget is created.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::entry(n), spinbox(n)\n.SH KEYWORDS\nentry, spinbox, widget, text field\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_style.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::style n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::style \\- Manipulate style database\n.SH SYNOPSIS\n\\fBttk::style\\fI option\\fR ?\\fIargs\\fR?\n.BE\n.SH NOTES\n.PP\nSee also the Tcl'2004 conference presentation,\navailable at https://tktable.sourceforge.net/tile/tile-tcl2004.pdf\n.SH DEFINITIONS\n.PP\nEach widget is assigned a \\fIstyle\\fR,\nwhich specifies the set of elements making up the widget\nand how they are arranged, along with dynamic and default\nsettings for element options.\nBy default, the style name is the same as the widget's class;\nthis may be overridden by the \\fB\\-style\\fR option.\n.PP\nA \\fItheme\\fR is a collection of elements and styles\nwhich controls the overall look and feel of an application.\nThe\n.QW .\nstyle is the theme root style on which derived styles are based.\n.SH DESCRIPTION\n.PP\nThe \\fBttk::style\\fR command takes the following arguments:\n.\\\" METHOD: configure\n.TP\n\\fBttk::style configure \\fIstyle\\fR ?\\fI\\-option\\fR ?\\fIvalue option value...\\fR? ?\n.\nSets the default value of the specified option(s) in \\fIstyle\\fR.\nIf \\fIstyle\\fR does not exist, it is created.\nIf only \\fIstyle\\fR and \\fI\\-option\\fR are specified, get the default value\nfor option \\fI\\-option\\fR of style \\fIstyle\\fR.\nIf only \\fIstyle\\fR is specified, get the default value for all options\nof style \\fIstyle\\fR.\n.\\\" METHOD: element\n.TP\n\\fBttk::style element\\fI args\\fR\n.RS\n.TP\n\\fBttk::style element create\\fI elementName type\\fR ?\\fIargs...\\fR?\n.\nCreates a new element in the current theme of type \\fItype\\fR.\nThe only cross-platform built-in element type is \\fIimage\\fR\n(see \\fBttk_image\\fR(n)) but themes may define other element types\n(see \\fBTtk_RegisterElementFactory\\fR). On suitable versions of Windows\nan element factory is registered to create Windows theme elements\n(see \\fBttk_vsapi\\fR(n)).\n.TP\n\\fBttk::style element names\\fR\n.\nReturns the list of elements defined in the current theme.\n.TP\n\\fBttk::style element options \\fIelement\\fR\n.\nReturns the list of \\fIelement\\fR's options.\n.RE\n.\\\" METHOD: layout\n.TP\n\\fBttk::style layout \\fIstyle\\fR ?\\fIlayoutSpec\\fR?\n.\nDefine the widget layout for style \\fIstyle\\fR.\nSee \\fBLAYOUTS\\fR below for the format of \\fIlayoutSpec\\fR.\nIf \\fIlayoutSpec\\fR is omitted, return the layout specification\nfor style \\fIstyle\\fR.\n.\\\" METHOD: lookup\n.TP\n\\fBttk::style lookup \\fIstyle \\-option \\fR?\\fIstate \\fR?\\fIdefault\\fR??\n.\nReturns the value specified for \\fI\\-option\\fR in style \\fIstyle\\fR\nin state \\fIstate\\fR, using the standard lookup rules for element options.\n\\fIstate\\fR is a list of state names; if omitted,\nit defaults to all bits off (the\n.QW normal\nstate).\nIf the \\fIdefault\\fR argument is present, it is used as a fallback\nvalue in case no specification for \\fI\\-option\\fR is found.\n.\\\" Otherwise -- signal error? return empty string? Leave unspecified for now.\nIf \\fIstyle\\fR does not exist, it is created.\n.\\\" METHOD: map\n.TP\n\\fBttk::style map \\fIstyle\\fR ?\\fI\\-option\\fB { \\fIstatespec value...\\fB }\\fR?\n.\nSets dynamic (state dependent) values of the specified option(s) in \\fIstyle\\fR.\nEach \\fIstatespec / value\\fR pair is examined in order;\nthe value corresponding to the first matching \\fIstatespec\\fR\nis used.\nIf \\fIstyle\\fR does not exist, it is created.\nIf only \\fIstyle\\fR and \\fI\\-option\\fR are specified, get the dynamic values\nfor option \\fI\\-option\\fR of style \\fIstyle\\fR.\nIf only \\fIstyle\\fR is specified, get the dynamic values for all options\nof style \\fIstyle\\fR.\n.\\\" METHOD: theme\n.TP\n\\fBttk::style theme\\fI args\\fR\n.RS\n.TP\n\\fBttk::style theme create\\fI themeName\\fR ?\\fB\\-parent \\fIbasedon\\fR? ?\\fB\\-settings \\fIscript...\\fR ?\n.\nCreates a new theme.  It is an error if \\fIthemeName\\fR already exists.\nIf \\fB\\-parent\\fR is specified, the new theme will inherit\nstyles, elements, and layouts from the parent theme \\fIbasedon\\fR.\nIf \\fB\\-settings\\fR is present, \\fIscript\\fR is evaluated in the\ncontext of the new theme as per \\fBttk::style theme settings\\fR.\n.TP\n\\fBttk::style theme names\\fR\n.\nReturns a list of all known themes.\n.TP\n\\fBttk::style theme settings \\fIthemeName script\\fR\n.\nTemporarily sets the current theme to \\fIthemeName\\fR,\nevaluate \\fIscript\\fR, then restore the previous theme.\nTypically \\fIscript\\fR simply defines styles and elements,\nthough arbitrary Tcl code may appear.\n.TP\n\\fBttk::style theme styles\\fR ?\\fIthemeName\\fR?\n.\nReturns a list of all styles in \\fIthemeName\\fR. If \\fIthemeName\\fR\nis omitted, the current theme is used.\n.TP\n\\fBttk::style theme use\\fR ?\\fIthemeName\\fR?\n.\nWithout an argument the result is the name of the current theme.\nOtherwise this command sets the current theme to \\fIthemeName\\fR,\nand refreshes all widgets.\n.RE\n.SH LAYOUTS\n.PP\nA \\fIlayout\\fR specifies a list of elements, each followed\nby one or more options specifying how to arrange the element.\nThe layout mechanism uses a simplified version of the \\fBpack\\fR\ngeometry manager: given an initial cavity,\neach element is allocated a parcel.\nThen the parcel actually used by the element is adjusted within\nthe allocated parcel.\nValid options are:\n.\\\" -border should remain undocumented for now (dubious usefulness)\n.\\\" .TP\n.\\\" \\fB\\-border\\fI boolean\\fR\n.\\\" .\n.\\\" Specifies whether the element is drawn after its children. Defaults to 0.\n.\\\" OPTION: -children\n.TP\n\\fB\\-children { \\fIsublayout...\\fB }\\fR\n.\nSpecifies a list of elements to place inside the element.\n.\\\" OPTION: -expand\n.TP\n\\fB\\-expand\\fI boolean\\fR\n.\nSpecifies whether the allocated parcel is the entire cavity. If so,\nsimultaneous specification of \\fB\\-side\\fR is ignored.\nDefaults to 0.\n.\\\" OPTION: -side\n.TP\n\\fB\\-side \\fIside\\fR\n.\nSpecifies which side of the cavity to place the element;\none of \\fBleft\\fR, \\fBright\\fR, \\fBtop\\fR, or \\fBbottom\\fR.\nFor instance, \\fB\\-side top\\fR allocates the parcel along the top of\nthe cavity having width and height respectively the width of the cavity\nand the height of the element.\nIf omitted, the allocated parcel is the entire cavity (same effect\nas \\fB\\-expand\\fR 1).\n.\\\" OPTION: -sticky\n.TP\n\\fB\\-sticky\\fR \\fB[\\fInswe\\fB]\\fR\n.\nSpecifies the actual parcel position and size inside the allocated parcel.\nIf specified as an empty string then the actual parcel is centered in\nthe allocated parcel. Default is \\fBnswe\\fR.\n.\\\" -unit should remain undocumented for now (dubious usefulness)\n.\\\" .TP\n.\\\" \\fB\\-unit\\fI boolean\\fR\n.\\\" .\n.\\\" Specifies whether the element propagates its state to its children.\n.\\\" Defaults to 0.\n.PP\nFor example:\n.CS\nttk::style layout Horizontal.TScrollbar {\n    Scrollbar.trough -children {\n        Scrollbar.leftarrow -side left\n        Scrollbar.rightarrow -side right\n        Horizontal.Scrollbar.thumb -side left -sticky ew\n    }\n}\n.CE\n.SH ROOT STYLE\n.PP\nThe\n.QW .\ntheme root style can be configured like any other style, providing defaults\nfor its derived styles. In addition to the usual options,\n.QW .\nstyling options configurable with \\fBttk::style\\fP are:\n.PP\n\\fB\\-insertofftime\\fP \\fIamount\\fP\n.RS\nSpecifies a non-negative integer value indicating the number of milliseconds\nthe insertion cursor should remain\n.QW off\nin each blink cycle. If this option is zero then the cursor does not blink:\nit is on all the time. Defaults to 300 ms, unless overriden with a\n\\fBRESOURCE_MANAGER\\fR property or \\fB.Xdefaults\\fR file.\n.RE\n.PP\n\\fB\\-insertontime\\fP \\fIamount\\fP\n.RS\nSpecifies a non-negative integer value indicating the number of milliseconds\nthe insertion cursor should remain\n.QW on\nin each blink cycle. Defaults to 600 ms, unless overriden with a\n\\fBRESOURCE_MANAGER\\fR property or \\fB.Xdefaults\\fR file.\n.RE\n.SH \"SEE ALSO\"\nttk::intro(n), ttk::widget(n), photo(n), ttk_image(n)\n.SH KEYWORDS\nstyle, theme, appearance\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_toggleswitch.n",
    "content": ".\\\"\n.\\\" Copyright (c) 2025 Csaba Nemethi\n.\\\"\n.\\\" See the file \"license.terms\" for information on usage and redistribution\n.\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n.\\\"\n.TH ttk::toggleswitch n 9.1 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::toggleswitch \\- Create and manipulate a toggleswitch widget\n.SH SYNOPSIS\n\\fBttk::toggleswitch \\fIpathName \\fR?\\fIoptions...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nA \\fBttk::toggleswitch\\fR widget is used to show or change a binary setting.\nIt consists of a horizontal \\fItrough\\fR (a fully rounded filled rectangle)\nand a \\fIslider\\fR (a filled circle or fully rounded filled rectangle\ncontained in the trough).  Their dimensions depend on the value of the\n\\fB-size\\fR configuration option, the current theme, the display's scaling\nlevel, and Tk's scaling factor given by \\fB[tk scaling]\\fR at the time the\nfirst toggleswitch widget is created.\n.PP\nJust like a light switch, a toggleswitch widget can have one of two possible\n\\fIswitch state\\fRs: on or off.  In the on state the slider is placed at the\nend of the trough, and in the off state at its beginning.  The user can toggle\nbetween these two states with the mouse or the space key.\n.PP\nThe colors used when drawing the trough and slider in the various widget\nstates depend on the current theme.  If the theme is \\fBaqua\\fR then they also\ndepend on the system appearance (light mode or dark mode) and the accent\ncolor, and are automatically adapted whenever one of these global system\nsettings changes.\n.PP\nThe implementation creates these elements when needed with the aid of generic\ncode for arbitrary themes and theme-specific one for a few built-in themes.\nApplications can add \\fIexplicit\\fR support for any theme \\fItheme\\fR by\nproviding an appropriate command of the name\n\\fBttk::toggleswitch::CreateElements_\\fR\\fItheme\\fR.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-style\n\\-takefocus\n.SE\n.PP\nThe default value of the \\fB-class\\fR option is \\fBToggleswitch\\fR.  The value\nof the \\fB-style\\fR option defaults to \\fBToggleswitch2\\fR, corresponding to\nthe \\fB-size\\fR option's default value \\fB2\\fR (see below).\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-command command Command\nSpecifies a Tcl script to be evaluated at global scope whenever the switch\nstate of the widget is toggled (programmatically, by invoking the\n\\fBswitchstate\\fR or \\fBtoggle\\fR subcommand, or interactively).  The default\nis an empty string.\n.OP \\-offvalue offValue OffValue\nThe value to store in the associated \\fB\\-variable\\fR\nwhen the widget's switch state is set to off.  Defaults to \\fB0\\fR.\n.OP \\-onvalue onValue OnValue\nThe value to store in the associated \\fB\\-variable\\fR\nwhen the widget's switch state is set to on.  Defaults to \\fB1\\fR.\n.OP \\-size size Size\nSpecifies the size identifier of the toggleswitch widget.  The supported\nvalues are the strings \\fB1\\fR, \\fB2\\fR (the default), and \\fB3\\fR.  In the\ncase of the \\fBaqua\\fR theme, these size IDs correspond to the control sizes\n\"mini\", \"small\", and \"large\" of the native toggle switches on macOS.\n.RS\n.PP\nNote that by setting this option to a value \\fIsize\\fR, the \\fB-style\\fR\noption's value will automatically change to \\fBToggleswitch\\fR\\fIsize\\fR if\nits previous or requested value was \\fBToggleswitch1\\fR, \\fBToggleswitch2\\fR,\nor \\fBToggleswitch3\\fR, and to \\fIprefix\\fR.\\fBToggleswitch\\fR\\fIsize\\fR if\nits previous or requested value was \\fIprefix\\fR.\\fBToggleswitch1\\fR,\n\\fIprefix\\fR.\\fBToggleswitch2\\fR, or \\fIprefix\\fR.\\fBToggleswitch3\\fR.\nConversely, by setting the \\fB-style\\fR option to a value of the form\n\\fBToggleswitch\\fR\\fIsize\\fR or \\fIprefix\\fR.\\fBToggleswitch\\fR\\fIsize\\fR\n(where \\fIsize\\fR is one of \\fB1\\fR, \\fB2\\fR, or \\fB3\\fR), the \\fB-size\\fR\noption will automatically be set to \\fIsize\\fR.  When configuring both options\n\\fB-size\\fR and \\fB-style\\fR, the former will take precedence over the latter,\nregardless of the order in which they were specified.\n.PP\nFor example, if you create the widget with\n.PP\n.CS\n\\fBttk::toggleswitch\\fR \\fIpathName\\fR \\fB-size 3 -style\\fR My.\\fBToggleswitch3\\fR\n.CE\n.PP\nor invoke\n.PP\n.CS\n\\fIpathName\\fR \\fBconfigure -style\\fR My.\\fBToggleswitch3\\fR\n.CE\n.PP\nthen the \\fB-style\\fR option will be set to My.\\fBToggleswitch3\\fR (and the\n\\fB-size\\fR option will have the value \\fB3\\fR).  On the other hand, if you\ncreate the widget with\n.PP\n.CS\n\\fBttk::toggleswitch\\fR \\fIpathName\\fR \\fB-style\\fR My.\\fBToggleswitch3\\fR\n.CE\n.PP\nthen the \\fB-style\\fR option will have the value My.\\fBToggleswitch2\\fR rather\nthan My.\\fBToggleswitch3\\fR, because the widget creation triggers the default\n\\fB-size 2\\fR setting, which takes precedence over \\fB-style\\fR\nMy.\\fBToggleswitch3\\fR.\n.RE\n.OP \\-variable variable Variable\nThe name of a global variable whose value is linked to the toggleswitch.  The\nwidget's switch state changes to on when this variable is set to the value\nspecified by the \\fB-onvalue\\fR option and to off otherwise.  Defaults to the\nwidget's pathname if not specified.\n.RS\n.PP\nNote that, just like in the case of the (ttk::)checkbutton, toggling the\nwidget's switch state by changing the value of this variable will \\fInot\\fR\ncause the script specified by the \\fB-command\\fR option to get executed.\n.RE\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBidentify element\\fR, \\fBinstate\\fR,\n\\fBstate\\fR, and \\fBstyle\\fR commands (see \\fBttk::widget\\fR), toggleswitch\nwidgets support the following additional commands:\n.\\\" METHOD: switchstate\n.TP\n\\fIpathName \\fBswitchstate \\fR?\\fIboolean\\fR?\n.\nModifies or inquires the widget's switch state.  If the optional argument is\npresent then it must be a boolean (a numeric value, where 0 is false and\nanything else is true, or a string such as \\fBtrue\\fR/\\fByes\\fR/\\fBon\\fR or\n\\fBfalse\\fR/\\fBno\\fR/\\fBoff\\fR).  If the widget's \\fBdisabled\\fR state flag is\nset then the command returns an empty string immediately after checking the\nargument.  Otherwise, if the argument is true then the command sets the\nwidget's switch state to on by setting its \\fBselected\\fR flag, moving the\nslider to the end of the trough, and setting the associated \\fB-variable\\fR to\nthe value specified by the \\fB-onvalue\\fR option; if the argument is false\nthen the command sets the widget's switch state to off by clearing the\n\\fBselected\\fR flag, moving the slider to the beginning of the trough, and\nsetting the associated variable to the value specified by the \\fB-offvalue\\fR\noption.\n.RS\n.PP\nIf the argument's value causes the widget's switch state to get toggled and\nthe script specified as the value of the \\fB-command\\fR option is a nonempty\nstring then the command evaluates that script at global scope and returns its\nresult; otherwise the return value is an empty string.\n.PP\nIf the optional argument is not present then the command returns the widget's\ncurrent switch state as \\fB0\\fR (off) or \\fB1\\fR (on).  When a toggleswitch\nwidget is created, its switch state is initialized with \\fB0\\fR.\n.RE\n.\\\" METHOD: toggle\n.TP\n\\fIpathName \\fBtoggle\\fR\n.\nThis convenience subcommand toggles the widget's switch state.  It is\nlogically equivalent to invoking the \\fBswitchstate\\fR command with the\nargument \\fB0\\fR if the current switch state is on and with the argument\n\\fB1\\fR otherwise.\n.SH \"INTERNAL COMMANDS\"\n.PP\nThe following widget commands are used internally by the \\fBToggleswitch\\fR\nwidget class bindings.  They provide a means to access the widget's internal\nvalue, which is a real number within a certain invariant interval.\n.\\\" METHOD: get\n.TP\n\\fIpathName \\fBget \\fR?\\fBmin\\fR|\\fBmax\\fR|\\fIx\\fR?\n.\nReturns the current/minimum/maximum internal value, or the one corresponding\nto the coordinate \\fIx\\fR relative to the widget origin if it is specified.\n.\\\" METHOD: set\n.TP\n\\fIpathName \\fBset \\fIvalue\\fR\n.\nSets the widget's internal value to \\fIvalue\\fR.  The value will be clipped to\nthe range given by the minimum and maximum values, as returned by\n\\fBget min\\fR and \\fBget max\\fR.\n.PP\n.\\\" METHOD: xcoord\n.TP\n\\fIpathName \\fBxcoord \\fR?\\fIvalue\\fR?\n.\nReturns the x coordinate corresponding to \\fIvalue\\fR, or to the current\ninternal value if \\fIvalue\\fR is omitted.\n.SH \"DEFAULT BINDINGS\"\n.PP\nThe toggleswitch widget's default bindings enable the following behavior.\n.PP\nIf the current theme is \\fBaqua\\fR:\n.IP \\0\\(bu 4\nBy pressing mouse button 1 over the slider and then dragging the mouse with\nbutton 1 down until the pointer enters the trough, the slider moves smoothly\nto the opposite edge of the trough and the widget's switch state gets\ntoggled.  The same happens if mouse button 1 is pressed outside the slider and\nthen the pointer leaves the widget horizontally with button 1 down.\n.IP \\0\\(bu 4\nBy pressing mouse button 1 anywhere within the widget and then releasing it\nover the widget without previously moving the slider, the latter moves\nsmoothly to the opposite edge of the trough and the widget's switch state gets\ntoggled.\n.IP \\0\\(bu 4\nWhen the widget has the input focus, the space key causes its switch state to\nget toggled.\n.PP\nIf the current theme is different from \\fBaqua\\fR:\n.IP \\0\\(bu 4\nBy pressing mouse button 1 anywhere within the widget and then dragging the\nmouse with button 1 down, the slider moves in the same (horizontal) direction\nas the pointer.  By releasing the button, the switch state is set to off or\non, depending on the slider's position relative to the middle of the widget.\n.IP \\0\\(bu 4\nBy pressing mouse button 1 anywhere within the widget and then releasing it\nover the widget without previously dragging the mouse horizontally, the\nwidget's switch state gets toggled.\n.IP \\0\\(bu 4\nWhen the widget has the input focus, the space key causes its switch state to\nget toggled.\n.PP\nIf the widget's \\fBdisabled\\fR state flag is set then none of the above\nactions occur.\n.SH \"WIDGET STATES\"\n.PP\nThe widget sets the \\fBselected\\fR state whenever the switch state changes to\non and clears it otherwise.  The widget sets the \\fBinvalid\\fR state whenever\nthe linked \\fB\\-variable\\fR is unset.  The defalt bindings set and clear the\n\\fBactive\\fR and \\fBpressed\\fR state flags.\n.SH \"STYLING OPTIONS\"\n.PP\nThe default class name for a \\fBttk::toggleswitch\\fP is \\fBToggleswitch\\fP.\n.PP\nDynamic states: \\fBactive\\fP, \\fBbackground\\fP, \\fBdisabled\\fP, \\fBinvalid\\fP,\n\\fBpressed\\fP, \\fBselected\\fP.\n.PP\n\\fBToggleswitch1\\fP, \\fBToggleswitch2\\fP, and \\fBToggleswitch3\\fP styling\noptions configurable with \\fBttk::style\\fP are:\n.PP\n\\fB\\-focuscolor\\fP \\fIcolor\\fP\n.RS\nThe default is theme-specific.\n.RE\n.br\n\\fB\\-focussolid\\fP \\fIboolean\\fP\n.RS\nDefaults to true for the \\fBclassic\\fP theme and false for all the others.\n.RE\n.br\n\\fB\\-focusthickness\\fP \\fIamount\\fP\n.RS\nThe default is 1.  The value may have any of the forms acceptable to\n\\fBTk_GetPixels\\fP.\n.RE\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.RS\nDefaults to 1.5p for the \\fBaqua\\fP theme (for which the three above-mentioned\nstyles have no \\fBfocus\\fP element) and 0.75p for all the other themes.\n.RE\n.PP\nFor the \\fBaqua\\fP theme only the \\fB\\-padding\\fP option is available, the\nothers are simply ignored.\n.PP\nSee the \\fBttk_style\\fP manual page for information on how to configure ttk\nstyles.\n.SH \"SEE ALSO\"\nttk::widget(n), ttk::style(n), ttk::checkbutton(n), checkbutton(n).\n.SH KEYWORDS\ntoggleswitch, trough, slider, widget\n.\\\" Local Variables:\n.\\\" mode: nroff\n.\\\" fill-column: 78\n.\\\" End:\n"
  },
  {
    "path": "doc/ttk_treeview.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::treeview n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::treeview \\- hierarchical multicolumn data display widget\n.SH SYNOPSIS\n\\fBttk::treeview \\fIpathname \\fR?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBttk::treeview\\fR widget displays a hierarchical collection of items.\nEach item has a textual label, an optional image,\nand an optional list of data values.\nThe data values are displayed in successive columns after\nthe tree label.\n.PP\nThe order in which data values are displayed may be controlled\nby setting the \\fB\\-displaycolumns\\fR widget option.\nThe tree widget can also display column headings.\nColumns may be accessed by number or by symbolic names\nlisted in the \\fB\\-columns\\fR widget option;\nsee \\fBCOLUMN IDENTIFIERS\\fR.\n.PP\nEach item is identified by a unique name.\nThe widget will generate item IDs if they are not supplied by the caller.\nThere is a distinguished root item, named \\fB{}\\fR.\nThe root item itself is not displayed;\nits children appear at the top level of the hierarchy.\n.PP\nEach item also has a list of \\fItags\\fR,\nwhich can be used to associate event bindings with individual items\nand control the appearance of the item.\n.\\\" .PP\n.\\\" @@@HERE: describe selection, focus item\n.PP\nTreeview widgets support horizontal and vertical scrolling with the\nstandard \\fB\\-\\fR[\\fBxy\\fR]\\fBscrollcommand\\fR options\nand [\\fBxy\\fR]\\fBview\\fR widget commands.\n.SO ttk_widget\n\\-class\t\\-cursor\t\\-takefocus\n\\-style\t\\-xscrollcommand\t\\-yscrollcommand\n\\-padding\n.SE\n.SH \"WIDGET-SPECIFIC OPTIONS\"\n.OP \\-columns columns Columns\nA list of column identifiers,\nspecifying the number of columns and their names.\n.\\\"X: This is a read-only option; it may only be set when the widget is created.\n.OP \\-displaycolumns displayColumns DisplayColumns\nA list of column identifiers\n(either symbolic names or integer indices)\nspecifying which data columns are displayed\nand the order in which they appear,\nor the string \\fB#all\\fP.\nIf set to \\fB#all\\fP (the default),\nall columns are shown in the order given.\n.OP \\-height height Height\nSpecifies the number of rows which should be visible.\nNote that\nthe requested width is determined from the sum of the column widths.\n.OP \\-selectmode selectMode SelectMode\nControls how the built-in class bindings manage the selection.\nOne of \\fBextended\\fR, \\fBbrowse\\fR, or \\fBnone\\fR.\n.RS\n.PP\nIf set to \\fBextended\\fR (the default), multiple items may be selected.\nIf \\fBbrowse\\fR, only a single item will be selected at a time.\nIf \\fBnone\\fR, the selection will not be changed.\n.PP\nNote that application code and tag bindings can set the selection\nhowever they wish, regardless of the value of \\fB\\-selectmode\\fR.\n.RE\n.OP \\-selecttype selectType SelectType\nControls how the built-in class bindings manage the selection.\nOne of \\fBitem\\fR or \\fBcell\\fR.\n.OP \\-show show Show\nA list containing zero or more of the following values, specifying\nwhich elements of the tree to display.\n.RS\n.IP \\fBtree\\fR\nDisplay tree labels in column #0.\n.IP \\fBheadings\\fR\nDisplay the heading row.\n.PP\nThe default is \\fBtree headings\\fR.\n.PP\n\\fBNOTE:\\fR Column #0 always refers to the tree column,\neven if \\fB\\-show tree\\fR is not specified.\n.RE\n.OP \\-striped striped Striped\nBoolean specifying zebra striped item coloring.\nNote that\nstriped items uses the \\fB\\-stripedbackground\\fR option if set by the theme or\na tag. If not supported by the current theme, it will not show.\n.OP \\-titlecolumns titleColumns TitleColumns\nNumber of display columns at the left that should not be scrolled. The tree\ncolumn counts, even if \\fB\\-show tree\\fR is not specified. Thus for value N of\nthis option, column #N is the first one that is scrollable. Default is 0.\n.OP \\-titleitems titleItems TitleItems\nNumber of items at the top that should not be vertically scrolled. Default is 0.\n.SH \"WIDGET COMMAND\"\n.PP\nIn addition to the standard\n\\fBcget\\fR, \\fBconfigure\\fR, \\fBinstate\\fR,\n\\fBstate\\fR, \\fBstyle\\fR, \\fBxview\\fR and \\fByview\\fR\ncommands (see \\fBttk::widget\\fR),\ntreeview widgets support the following additional commands:\n.\\\" METHOD: bbox\n.TP\n\\fIpathname \\fBbbox \\fIitem\\fR ?\\fIcolumn\\fR?\n.\nReturns the bounding box (relative to the treeview widget's window)\nof the specified \\fIitem\\fR in the form \\fIx y width height\\fR.\nIf the \\fIitem\\fR is not visible\n(i.e., if it is a descendant of a closed item or is vertically scrolled\noffscreen), returns the empty list.\nIf \\fIcolumn\\fR is specified and is not hidden (by the \\fB\\-displaycolumns\\fR\noption), returns the bounding box of that cell within \\fIitem\\fR\n(even if the cell is horizontally scrolled offscreen).\n.\\\" METHOD: cellselection\n.TP\n\\fIpathname \\fBcellselection\\fR ?\\fIselop arg ...\\fR?\n.\nManages cell selection. Cell selection is independent from item selection\nhandled by the \\fBselection\\fR command. A cell is given by a list of two\nelements, item and column.\nFor the rectangle versions of commands, the cells must be in displayed columns.\nAny change to \\fB\\-columns\\fR clears the cell selection.\nA \\fIcellList\\fR argument may be a single cell or a list of cells.\nIf \\fIselop\\fR is not specified, returns the list of selected cells.\nOtherwise, \\fIselop\\fR is one of the following:\n.RS\n.TP\n\\fIpathname \\fBcellselection set \\fIcellList\\fR\n.\n\\fIcellList\\fR becomes the new cell selection.\n.TP\n\\fIpathname \\fBcellselection set \\fIfirstCell lastCell\\fR\n.\nThe rectangle defined becomes the new cell selection.\n.TP\n\\fIpathname \\fBcellselection add \\fIcellList\\fR\n.\nAdd \\fIcellList\\fR to the cell selection.\n.TP\n\\fIpathname \\fBcellselection add \\fIfirstCell lastCell\\fR\n.\nThe rectangle defined is added to the cell selection.\n.TP\n\\fIpathname \\fBcellselection remove \\fIcellList\\fR\n.\nRemove \\fIcellList\\fR from the cell selection.\n.TP\n\\fIpathname \\fBcellselection remove \\fIfirstCell lastCell\\fR\n.\nThe rectangle defined is removed from the cell selection.\n.TP\n\\fIpathname \\fBcellselection toggle \\fIcellList\\fR\n.\nToggle the cell selection state of each cell in \\fIcellList\\fR.\nIf the element is partially visible, the result gives the full area of the\nelement, including any parts that are not visible.\n.TP\n\\fIpathname \\fBcellselection toggle \\fIfirstCell lastCell\\fR\n.\nToggle the cell selection state of each cell in the rectangle defined.\n.RE\n.\\\" METHOD: children\n.TP\n\\fIpathname \\fBchildren \\fIitem\\fR ?\\fInewchildren\\fR?\n.\nIf \\fInewchildren\\fR is not specified,\nreturns the list of children belonging to \\fIitem\\fR.\n.RS\n.PP\nIf \\fInewchildren\\fR is specified, replaces \\fIitem\\fR's child list\nwith \\fInewchildren\\fR.\nItems in the old child list not present in the new child list\nare detached from the tree.\nNone of the items in \\fInewchildren\\fR may be an ancestor\nof \\fIitem\\fR.\n.RE\n.\\\" METHOD: column\n.TP\n\\fIpathname \\fBcolumn \\fIcolumn\\fR ?\\fI\\-option \\fR?\\fIvalue \\-option value...\\fR?\n.\nQuery or modify the options for the specified \\fIcolumn\\fR.\nIf no \\fI\\-option\\fR is specified,\nreturns a dictionary of option/value pairs.\nIf a single \\fI\\-option\\fR is specified,\nreturns the value of that option.\nOtherwise, the options are updated with the specified values.\nThe following options may be set on each column:\n.RS\n.\\\" OPTION: -id\n.TP\n\\fB\\-id \\fIname\\fR\n.\nThe column name.  This is a read-only option.\nFor example, [\\fI$pathname \\fBcolumn #\\fIn \\fB\\-id\\fR]\nreturns the data column associated with display column \\fIn\\fR.\nThe tree column has \\fB\\-id #0\\fR.\n.\\\" OPTION: -anchor\n.TP\n\\fB\\-anchor \\fIanchor\\fR\n.\nSpecifies how the text in this column should be aligned\nwith respect to the cell. \\fIAnchor\\fR is one of\n\\fBn\\fR, \\fBne\\fR, \\fBe\\fR, \\fBse\\fR,\n\\fBs\\fR, \\fBsw\\fR, \\fBw\\fR, \\fBnw\\fR, or \\fBcenter\\fR.\n.\\\" OPTION: -minwidth\n.TP\n\\fB\\-minwidth \\fIminwidth\\fR\n.\nThe minimum width of the column in pixels.\nThe treeview widget will not make the column any smaller than\n\\fB\\-minwidth\\fR when the widget is resized or the user drags a\nheading column separator.  Default is 20 pixels.\n.\\\" OPTION: -separator\n.TP\n\\fB\\-separator \\fIboolean\\fR\n.\nSpecifies whether or not a column separator should be drawn to the right\nof the column.  Default is false.\n.\\\" OPTION: -stretch\n.TP\n\\fB\\-stretch \\fIboolean\\fR\n.\nSpecifies whether or not the column width should be adjusted\nwhen the widget is resized or the user drags a heading column separator.\n\\fIBoolean\\fR may have any of the forms accepted by \\fBTcl_GetBoolean\\fR.\nBy default columns are stretchable.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIwidth\\fR\n.\nThe width of the column in pixels.  Default is 200 pixels. The specified\ncolumn width may be changed by Tk in order to honor \\fB\\-stretch\\fR\nand/or \\fB\\-minwidth\\fR, or when the widget is resized or the user drags a\nheading column separator.\n.PP\nUse \\fIpathname fBcolumn #0\\fR to configure the tree column.\n.RE\n.\\\" METHOD: delete\n.TP\n\\fIpathname \\fBdelete \\fIitemList\\fR\n.\nDeletes each of the items in \\fIitemList\\fR and all of their descendants.\nThe root item may not be deleted.\nSee also: \\fBdetach\\fR.\n.\\\" METHOD: detach\n.TP\n\\fIpathname \\fBdetach \\fIitemList\\fR\n.\nUnlinks all of the specified items in \\fIitemList\\fR from the tree.\nThe items and all of their descendants are still present\nand may be reinserted at another point in the tree\nwith the \\fBmove\\fR operation,\nbut will not be displayed until that is done.\nThe root item may not be detached.\nSee also: \\fBdelete\\fR.\n.\\\" METHOD: detached\n.TP\n\\fIpathname \\fBdetached \\fR?\\fIitem\\fR?\n.\nIf \\fIitem\\fR is provided, returns a boolean value indicating whether it is\nthe name of a detached item (see \\fBdetach\\fR). Otherwise, returns a list of\nall the detached items (in an arbitrary order). The root item is never\ndetached.\n.\\\" METHOD: exists\n.TP\n\\fIpathname \\fBexists \\fIitem\\fR\n.\nReturns 1 if the specified \\fIitem\\fR is present in the tree,\n0 otherwise.\n.\\\" METHOD: focus\n.TP\n\\fIpathname \\fBfocus \\fR?\\fIitem\\fR?\n.\nIf \\fIitem\\fR is specified, sets the focus item to \\fIitem\\fR.\nOtherwise, returns the current focus item, or \\fB{}\\fR if there is none.\n.\\\" Need: way to clear the focus item.  {} works for this...\n.\\\"\n.\\\" METHOD: heading\n.TP\n\\fIpathname \\fBheading \\fIcolumn\\fR ?\\fI\\-option \\fR?\\fIvalue \\-option value...\\fR?\n.\nQuery or modify the heading options for the specified \\fIcolumn\\fR.\nValid options are:\n.RS\n.\\\" OPTION: -text\n.TP\n\\fB\\-text \\fItext\\fR\n.\nThe text to display in the column heading.\n.\\\" OPTION: -image\n.TP\n\\fB\\-image \\fIimageName\\fR\n.\nSpecifies an image to display to the right of the column heading.\n.\\\" OPTION: -anchor\n.TP\n\\fB\\-anchor \\fIanchor\\fR\n.\nSpecifies how the heading text should be aligned.\nOne of the standard Tk anchor values.\n.\\\" OPTION: -command\n.TP\n\\fB\\-command \\fIscript\\fR\n.\nA script to evaluate when the heading label is pressed.\n.PP\nUse \\fIpathname heading #0\\fR to configure the tree column heading.\n.RE\n.\\\" METHOD: identify\n.TP\n\\fIpathname \\fBidentify \\fIcomponent x y\\fR\n.\nReturns a description of the specified \\fIcomponent\\fR\nunder the point given by \\fIx\\fR and \\fIy\\fR,\nor the empty string if no such \\fIcomponent\\fR is present at that position.\nThe values \\fIx\\fR and \\fIy\\fR may have any of the forms acceptable to\n\\fBTk_GetPixels\\fR.\nThe following subcommands are supported:\n.RS\n.TP\n\\fIpathname \\fBidentify region \\fIx y\\fR\n.RS\nReturns one of:\n.IP heading\nTree heading area;\nuse [\\fBpathname identify column \\fIx y\\fR]\nto determine the heading number.\n.IP separator\nSpace between two column headings;\n[\\fBpathname identify column \\fIx y\\fR]\nwill return the display column identifier\nof the heading to left of the separator.\n.IP tree\nThe tree area.\n.IP cell\nA data cell.\n.RE\n.TP\n\\fIpathname \\fBidentify item \\fIx y\\fR\n.\nReturns the item ID of the item at position \\fIy\\fR.\n.TP\n\\fIpathname \\fBidentify column \\fIx y\\fR\n.\nReturns the display column identifier of the cell at position \\fIx\\fR.\nThe tree column has ID \\fB#0\\fR.\n.TP\n\\fIpathname \\fBidentify cell \\fIx y\\fR\n.\nReturns the cell identifier of the cell at position \\fIx y\\fR.\nA cell identifier is a list of item ID and column ID.\n.TP\n\\fIpathname \\fBidentify element \\fIx y\\fR\n.\nThe element at position \\fIx,y\\fR.\n.TP\n\\fIpathname \\fBidentify row \\fIx y\\fR\n.\nObsolescent synonym for \\fIpathname \\fBidentify item\\fR.\n.PP\nSee \\fBCOLUMN IDENTIFIERS\\fR for a discussion of display columns\nand data columns.\n.RE\n.\\\" METHOD: index\n.TP\n\\fIpathname \\fBindex \\fIitem\\fR\n.\nReturns the integer index of \\fIitem\\fR within its parent's list of children.\n.\\\" METHOD: insert\n.TP\n\\fIpathname \\fBinsert \\fIparent index\\fR ?\\fB\\-id \\fIid\\fR? \\fIoptions...\\fR\n.\nCreates a new item.\n\\fIparent\\fR is the item ID of the parent item,\nor the empty string \\fB{}\\fR\nto create a new top-level item.\n\\fIindex\\fR is an integer, or the value \\fBend\\fR, specifying where in the\nlist of \\fIparent\\fR's children to insert the new item.\nIf \\fIindex\\fR is negative or zero,\nthe new node is inserted at the beginning;\nif \\fIindex\\fR is greater than or equal to the current number of children,\nit is inserted at the end.\nIf \\fB\\-id\\fR is specified, it is used as the item identifier;\n\\fIid\\fR must not already exist in the tree.\nOtherwise, a new unique identifier is generated.\n.RS\n.PP\n\\fIpathname \\fBinsert\\fR returns the item identifier of the\nnewly created item.\nSee \\fBITEM OPTIONS\\fR for the list of available options.\n.RE\n.\\\" METHOD: item\n.TP\n\\fIpathname \\fBitem \\fIitem\\fR ?\\fI\\-option \\fR?\\fIvalue \\-option value...\\fR?\n.\nQuery or modify the options for the specified \\fIitem\\fR.\nIf no \\fI\\-option\\fR is specified,\nreturns a dictionary of option/value pairs.\nIf a single \\fI\\-option\\fR is specified,\nreturns the value of that option.\nOtherwise, the item's options are updated with the specified values.\nSee \\fBITEM OPTIONS\\fR for the list of available options.\n.\\\" METHOD: move\n.TP\n\\fIpathname \\fBmove \\fIitem parent index\\fR\n.\nMoves \\fIitem\\fR to position \\fIindex\\fR in \\fIparent\\fR's list of children.\nIt is illegal to move an item under one of its descendants.\n.RS\n.PP\nIf \\fIindex\\fR is negative or zero, \\fIitem\\fR is moved\nto the beginning; if greater than or equal to the number of children,\nit is moved to the end.\n.RE\n.\\\" METHOD: next\n.TP\n\\fIpathname \\fBnext \\fIitem\\fR\n.\nReturns the identifier of \\fIitem\\fR's next sibling,\nor \\fB{}\\fR if \\fIitem\\fR is the last child of its parent.\n.\\\" METHOD: parent\n.TP\n\\fIpathname \\fBparent \\fIitem\\fR\n.\nReturns the ID of the parent of \\fIitem\\fR,\nor \\fB{}\\fR if \\fIitem\\fR is at the top level of the hierarchy.\n.\\\" METHOD: prev\n.TP\n\\fIpathname \\fBprev \\fIitem\\fR\n.\nReturns the identifier of \\fIitem\\fR's previous sibling,\nor \\fB{}\\fR if \\fIitem\\fR is the first child of its parent.\n.\\\" METHOD: see\n.TP\n\\fIpathname \\fBsee \\fIitem\\fR\n.\nEnsure that \\fIitem\\fR is visible:\nsets all of \\fIitem\\fR's ancestors to \\fB\\-open true\\fR,\nand scrolls the widget if necessary so that \\fIitem\\fR is\nwithin the visible portion of the tree.\n.\\\" METHOD: selection\n.TP\n\\fIpathname \\fBselection\\fR ?\\fIselop itemList\\fR?\n.\nManages item selection. Item selection is independent from cell selection\nhandled by the \\fBcellselection\\fR command.\nIf \\fIselop\\fR is not specified, returns the list of selected items.\nOtherwise, \\fIselop\\fR is one of the following:\n.RS\n.TP\n\\fIpathname \\fBselection set \\fIitemList\\fR\n.\n\\fIitemList\\fR becomes the new selection.\n.TP\n\\fIpathname \\fBselection add \\fIitemList\\fR\n.\nAdd \\fIitemList\\fR to the selection.\n.TP\n\\fIpathname \\fBselection remove \\fIitemList\\fR\n.\nRemove \\fIitemList\\fR from the selection.\n.TP\n\\fIpathname \\fBselection toggle \\fIitemList\\fR\n.\nToggle the selection state of each item in \\fIitemList\\fR.\n.RE\n.\\\" METHOD: set\n.TP\n\\fIpathname \\fBset \\fIitem\\fR ?\\fIcolumn\\fR? ?\\fIvalue\\fR?\n.\nWith one argument, returns a dictionary of column/value pairs\nfor the specified \\fIitem\\fR.\nWith two arguments, returns the current value of the specified \\fIcolumn\\fR.\nWith three arguments, sets the value of column \\fIcolumn\\fR\nin item \\fIitem\\fR to the specified \\fIvalue\\fR.\nSee also \\fBCOLUMN IDENTIFIERS\\fR.\n.\\\" METHOD: tag\n.TP\n\\fIpathName \\fBtag \\fIargs...\\fR\n.\nManages tags. Tags can be set on items as well as on cells.\nThe set of tags is shared between items and cells. However item tagging is\nindependent from cell tagging (for instance adding a tag on an item does\nnot also add this tag on the cells in that item). Cell tags take precedence\nover item tags when drawing.\nThe following subcommands are supported:\n.RS\n.TP\n\\fIpathName \\fBtag add \\fItag items\\fR\n.\nAdds the specified \\fItag\\fR to each of the listed \\fIitems\\fR.\nIf \\fItag\\fR is already present for a particular item,\nthen the \\fB\\-tags\\fR for that item are unchanged.\n.TP\n\\fIpathName \\fBtag bind \\fItagName \\fR?\\fIsequence\\fR? ?\\fIscript\\fR?\n.\nAdd a Tk binding script for the event sequence \\fIsequence\\fR\nto the tag \\fItagName\\fR.  When an X event is delivered to an item,\nbinding scripts for each of the item's \\fB\\-tags\\fR are evaluated\nin order as per \\fIbindtags(n)\\fR.\nIf the event can be associated with a cell (i.e. mouse events) any\nbindings for the cell's \\fB\\-tags\\fR are evaluated as well.\n.RS\n.PP\n\\fB<Key>\\fR, \\fB<KeyRelease>\\fR, and virtual events\nare sent to the focus item.\n\\fB<Button>\\fR, \\fB<ButtonRelease>\\fR, and \\fB<Motion>\\fR events\nare sent to the item under the mouse pointer.\nNo other event types are supported.\n.PP\nThe binding \\fIscript\\fR undergoes \\fB%\\fR-substitutions before\nevaluation; see \\fBbind\\fR(n) for details.\n.RE\n.TP\n\\fIpathName \\fBtag cell \\fIsubcommand...\\fR\n.\nManages tags on individual cells.\nA \\fIcellList\\fR argument may be a single cell or a list of cells.\n.RS\n.TP\n\\fIpathName \\fBtag cell add \\fItag cellList\\fR\n.\nAdds the specified \\fItag\\fR to each of the listed \\fIcellList\\fR.\nIf \\fItag\\fR is already present for a particular cell,\nthen the tag list for that cell is unchanged.\n.TP\n\\fIpathName \\fBtag cell has \\fItagName\\fR ?\\fIcell\\fR?\n.\nIf \\fIcell\\fR is specified, returns 1 or 0\ndepending on whether the specified cell has the named tag.\nOtherwise, returns a list of all cells which have\nthe specified tag.\n.TP\n\\fIpathName \\fBtag cell remove \\fItag\\fR ?\\fIcellList\\fR?\n.\nRemoves the specified \\fItag\\fR from each of the listed \\fIcellList\\fR.\nIf \\fIcellList\\fR is omitted, removes \\fItag\\fR from each cell in the tree.\n.RE\n.TP\n\\fIpathName \\fBtag configure \\fItagName\\fR ?\\fIoption\\fR? ?\\fIvalue option value...\\fR?\n.\nQuery or modify the options for the specified \\fItagName\\fR.\nIf one or more \\fIoption/value\\fR pairs are specified,\nsets the value of those options for the specified tag.\nIf a single \\fIoption\\fR is specified,\nreturns the value of that option\n(or the empty string if the option has not been specified for \\fItagName\\fR).\nWith no additional arguments,\nreturns a dictionary of the option settings for \\fItagName\\fR.\nSee \\fBTAG OPTIONS\\fR for the list of available options.\n.TP\n\\fIpathName \\fBtag delete \\fItagName\\fR\n.\nDeletes all tag information for the \\fItagName\\fR argument. The command\nremoves the tag from all items and cells in the widget and also deletes any\nother information associated with the tag, such as bindings and display\ninformation. The command returns an empty string.\n.TP\n\\fIpathName \\fBtag has \\fItagName\\fR ?\\fIitem\\fR?\n.\nIf \\fIitem\\fR is specified, returns 1 or 0\ndepending on whether the specified item has the named tag.\nOtherwise, returns a list of all items which have\nthe specified tag.\n.TP\n\\fIpathName \\fBtag names\\fR\n.\nReturns a list of all tags used by the widget.\n.TP\n\\fIpathName \\fBtag remove \\fItag\\fR ?\\fIitems\\fR?\n.\nRemoves the specified \\fItag\\fR from each of the listed \\fIitems\\fR.\nIf \\fIitems\\fR is omitted, removes \\fItag\\fR from each item in the tree.\nIf \\fItag\\fR is not present for a particular item,\nthen the \\fB\\-tags\\fR for that item are unchanged.\n.RE\n.SH \"ITEM OPTIONS\"\n.PP\nThe following item options may be specified for items\nin the \\fBinsert\\fR and \\fBitem\\fR widget commands.\n.IP \\fB\\-text\\fR\nThe textual label to display for the item in the tree column.\n.IP \\fB\\-height\\fR\nThe height for the item, in integer multiples of \\fB\\-rowheight\\fP. Default is 1.\n.IP \\fB\\-image\\fR\nA Tk image, displayed next to the label in the tree column, placed according\nto \\fB\\-imageanchor\\fR.\n.IP \\fB\\-imageanchor\\fR\nSpecifies how the \\fB\\-image\\fR is displayed relative to the text.\nDefault is \\fBw\\fR. One of the standard Tk anchor values.\n.IP \\fB\\-values\\fR\nThe list of values associated with the item.\n.RS\n.PP\nEach item should have the same number of values as\nthe \\fB\\-columns\\fR widget option.\nIf there are fewer values than columns,\nthe remaining values are assumed empty.\nIf there are more values than columns,\nthe extra values are ignored.\n.RE\n.IP \\fB\\-hidden\\fR\nA boolean value indicating whether this item\nshould be displayed (\\fB\\-hidden false\\fR) or hidden (\\fB\\-hidden true\\fR).\nIf a parent is hidden, all its decendants are hidden too.\n.IP \\fB\\-open\\fR\nA boolean value indicating whether the item's children\nshould be displayed (\\fB\\-open true\\fR) or hidden (\\fB\\-open false\\fR).\n.IP \\fB\\-tags\\fR\nA list of tags associated with this item.\n.SH \"TAG OPTIONS\"\n.PP\nThe following options may be specified on tags:\n.IP \\fB\\-foreground\\fR\nSpecifies the text foreground color.\n.IP \\fB\\-background\\fR\nSpecifies the cell or item background color.\n.IP \\fB\\-font\\fR\nSpecifies the font to use when drawing text.\n.IP \\fB\\-image\\fR\nSpecifies the cell or item image.\n.IP \\fB\\-imageanchor\\fR\nSpecifies the cell or item image anchor.\n.IP \\fB\\-padding\\fR\nSpecifies the cell padding. A data cell will have a default padding of {4 0}\n.IP \\fB\\-stripedbackground\\fR\nSpecifies the cell or item background color for alternate lines,\nif \\fB\\-striped\\fR is true.\n.PP\n.\\\" .PP\n.\\\" \\fI(@@@ TODO: sort out order of precedence for options)\\fR\n.PP\nTags on cells have precedence over tags on items. Then, tag priority is\ndecided by the creation order: tags created first receive higher priority.\nAn item's options, like \\fB\\-image\\fR and \\fB\\-imageanchor\\fR, have priority\nover tags.\n.SH \"IMAGES\"\nThe -image option on an item, and on an item tag, controls the image next to\nthe label in the tree column.\nOther cells can have images through the cell tag -image option.\n.SH \"COLUMN IDENTIFIERS\"\n.PP\nColumn identifiers take any of the following forms:\n.IP \\(bu\nA symbolic name from the list of \\fB\\-columns\\fR.\n.IP \\(bu\nAn integer \\fIn\\fR, specifying the \\fIn\\fRth data column.\n.IP \\(bu\nA string of the form \\fB#\\fIn\\fR, where \\fIn\\fR is an integer,\nspecifying the \\fIn\\fRth display column.\n.PP\nColumn identifiers support the same simple interpretation as\nfor the command \\fBstring index\\fR, with simple integer index\narithmetic and indexing relative to \\fBend\\fR.\n.PP\n\\fBNOTE:\\fR\nItem \\fB\\-values\\fR may be displayed in a different order than\nthe order in which they are stored.\n.PP\n\\fBNOTE:\\fR Column #0 always refers to the tree column,\neven if \\fB\\-show tree\\fR is not specified.\n.PP\nA \\fIdata column number\\fR is an index into an item's \\fB\\-values\\fR list;\na \\fIdisplay column number\\fR is the column number in the tree\nwhere the values are displayed.\nTree labels are displayed in column #0.\nIf \\fB\\-displaycolumns\\fR is not set,\nthen data column \\fIn\\fR is displayed in display column \\fB#\\fIn+1\\fR.\nAgain, \\fBcolumn #0 always refers to the tree column\\fR.\n.SH \"VIRTUAL EVENTS\"\n.PP\nThe treeview widget generates the following virtual events.\n.IP <<TreeviewSelect>>\nGenerated whenever the selection or cellselection changes.\nIt might also be generated when selection is affected but not actually changed.\nFurther, multiple selection changes could happen before events can be processed\nleading to multiple events with the same visible selection.\n.IP <<TreeviewOpen>>\nGenerated just before setting the focus item to \\fB\\-open true\\fR.\n.IP <<TreeviewClose>>\nGenerated just after setting the focus item to \\fB\\-open false\\fR.\n.PP\nThe \\fBfocus\\fR and \\fBselection\\fR widget commands can be used\nto determine the affected item or items.\n'\\\" Not yet:\n'\\\" In Tk 8.5, the affected item is also passed as the \\fB\\-detail\\fR field\n'\\\" of the virtual event.\n.SH \"STYLING OPTIONS\"\n.PP\nThe class name for a \\fBttk::treeview\\fP is \\fBTreeview\\fP.\nThe treeview header class name is \\fBHeading\\fP.\nThe treeview item class name is \\fBItem\\fP.\nThe treeview cell class name is \\fBCell\\fP.\n.PP\nDynamic states: \\fBdisabled\\fP, \\fBselected\\fP.\n.PP\n\\fBTreeview\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-fieldbackground\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indent\\fP \\fIamount\\fP\n.RS\nSpecifies how far items are indented from their parents. Defaults to 20 pixels.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.RE\n.br\n\\fB\\-columnseparatorwidth\\fP \\fIamount\\fP\n.RS\nSpecifies the width of column separators. Defaults to 1 pixel.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\n.RE\n.br\n\\fB\\-rowheight\\fP \\fIamount\\fP\n.RS\nThis is the standard height for an item. Defaults to 20 pixels.\nThe value may have any of the forms acceptable to \\fBTk_GetPixels\\fR.\nIf \\fB\\-rowheight\\fP is not set by the style, it is set by measuring an\nitem and a cell layout with the style's settings.\nThis thus picks up the font and\nany focus ring or padding from the theme's layout.\nThe \\fB\\-rowheight\\fP may need to be set to make sure that a row\nis large enough to contain any images.\n.PP\nExample of how to set \\fB\\-rowheight\\fP, adapting to a font in a similar\nway to how the default value is set:\n.RE\n.PP\n.CS\nttk::style configure Treeview \\\\\n     -rowheight [expr {[font metrics \\fIfont\\fP -linespace] + 2}]\n.CE\n.br\n\\fB\\-stripedbackground\\fP \\fIcolor\\fP\n.PP\n\\fBHeading\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-background\\fP \\fIcolor\\fP\n.br\n\\fB\\-font\\fP \\fIfont\\fP\n.br\n\\fB\\-relief\\fP \\fIrelief\\fP\n.PP\n\\fBItem\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-foreground\\fP \\fIcolor\\fP\n.br\n\\fB\\-indicatormargins\\fP \\fIpadding\\fP\n.br\n\\fB\\-indicatorsize\\fP \\fIamount\\fP\n.br\n\\fB\\-padding\\fP \\fIpadding\\fP\n.PP\n\\fBCell\\fP styling options configurable with \\fBttk::style\\fP\nare:\n.PP\n\\fB\\-padding\\fP \\fIpadding\\fP\n.PP\nSome options are only available for specific themes.\n.PP\nSee the \\fBttk::style\\fP manual page for information on how to configure\nttk styles.\n.SH \"SEE ALSO\"\nttk::widget(n), listbox(n), image(n), bind(n)\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_vsapi.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2008 Pat Thoyts\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk_vsapi n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk_vsapi \\- Define a Microsoft Visual Styles element\n.SH SYNOPSIS\n\\fBttk::style element create \\fIname \\fBvsapi\\fI className partId\\fR ?\\fIstateMap\\fR? ?\\fIoptions\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBvsapi\\fR element factory creates a new element\nin the current theme whose visual appearance is drawn using the\nMicrosoft Visual Styles API which is used in ttk for the MS-Windows\nnative styles. This factory permits any of the Visual\nStyles parts to be declared as Ttk elements that can then be\nincluded in a style layout to modify the appearance of Ttk widgets.\n.PP\nThe \\fIclassName\\fR and \\fIpartId\\fR are required parameters and specify\nthe Visual Styles class and part as given in the Microsoft\ndocumentation. The \\fIstateMap\\fR may be provided to map Ttk states to\nVisual Styles API states (see \\fBSTATE MAP\\fR).\n.SH \"OPTIONS\"\n.PP\nValid \\fIoptions\\fR are:\n.\\\" OPTION: -padding\n.TP\n\\fB\\-padding \\fIpadding\\fR\n.\nSpecify the element's interior padding.\n\\fIpadding\\fR is a list of up to four integers specifying\nthe left, top, right and bottom padding quantities respectively.\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nIn other words, a list of three numbers specify the left, vertical, and right\npadding; a list of two numbers specify the horizontal and the vertical padding;\na single number specifies the same padding all the way around the widget.\nThis option may not be mixed with any other options.\n.\\\" OPTION: -margins\n.TP\n\\fB\\-margins \\fIpadding\\fR\n.\nSpecifies the elements exterior padding.\n\\fIpadding\\fR is a list of up to four integers specifying\nthe left, top, right and bottom padding quantities respectively.\nThis option may not be mixed with any other options.\n.\\\" OPTION: -width\n.TP\n\\fB\\-width \\fIwidth\\fR\n.\nSpecifies the height for the element. If this option is set then\nthe Visual Styles API will not be queried for the recommended\nsize or the part. If this option is set then \\fB\\-height\\fR should\nalso be set. The \\fB\\-width\\fR and \\fB\\-height\\fR options cannot\nbe mixed with the \\fB\\-padding\\fR or \\fB\\-margins\\fR options.\n.\\\" OPTION: -height\n.TP\n\\fB\\-height \\fIheight\\fR\n.\nSpecifies the height of the element. See the comments for \\fB\\-width\\fR.\n.SH \"STATE MAP\"\n.PP\nThe \\fIstateMap\\fR parameter is a list of ttk states and the\ncorresponding Visual Styles API state value.\nThis permits the element appearance to respond to changes in the\nwidget state such as becoming active or being pressed. The list should\nbe as described for the \\fBttk::style map\\fR command but note that the\nlast pair in the list should be the default state and is typically an\nempty list and 1. Unfortunately all the Visual Styles parts have\ndifferent state values and these must be looked up either in the\nMicrosoft documentation or more likely in the header files. The\noriginal header to use was \\fItmschema.h\\fR, but in more recent\nversions of the Windows Development Kit this is \\fIvssym32.h\\fR.\n.PP\nIf no \\fIstateMap\\fR parameter is given there is an implicit default\nmap of {{} 1}\n.SH \"EXAMPLE\"\n.PP\nCreate a correctly themed close button by changing the layout of\na \\fBttk::button\\fR(n). This uses the WINDOW part WP_SMALLCLOSEBUTTON\nand as documented the states CBS_DISABLED, CBS_HOT, CBS_NORMAL and\nCBS_PUSHED are mapped from ttk states.\n.CS\nttk::style element create smallclose \\fBvsapi\\fR WINDOW 19 \\\\\n    {disabled 4 pressed 3 active 2 {} 1}\nttk::style layout CloseButton {CloseButton.smallclose -sticky news}\npack [ttk::button .close -style CloseButton]\n.CE\n.PP\nChange the appearance of a \\fBttk::checkbutton\\fR(n) to use the\nExplorer pin part EBP_HEADERPIN.\n.CS\nttk::style element create pin \\fBvsapi\\fR EXPLORERBAR 3 {\n    {pressed !selected} 3\n    {active !selected} 2\n    {pressed selected} 6\n    {active selected} 5\n    {selected} 4\n    {} 1\n}\nttk::style layout Explorer.Pin {Explorer.Pin.pin -sticky news}\npack [ttk::checkbutton .pin -style Explorer.Pin]\n.CE\n.SH \"SEE ALSO\"\nttk::intro(n), ttk::widget(n), ttk::style(n), ttk_image(n)\n.SH \"KEYWORDS\"\nstyle, theme, appearance, windows\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/ttk_widget.n",
    "content": "'\\\"\n'\\\" Copyright (c) 2004 Joe English\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH ttk::widget n 8.5 Tk \"Tk Themed Widget\"\n.so man.macros\n.BS\n.SH NAME\nttk::widget \\- Standard options and commands supported by Tk themed widgets\n.BE\n.SH DESCRIPTION\nThis manual describes common widget options and commands.\n.SH \"STANDARD OPTIONS\"\nThe following options are supported by all Tk themed widgets:\n.OP \\-class undefined undefined\nSpecifies the window class.\nThe class is used when querying the option database\nfor the window's other options, to determine the default\nbindtags for the window, and to select the widget's default\nlayout and style.\nThis is a read-only option:\nit may only be specified when the window is created,\nand may not be changed with the \\fBconfigure\\fR widget command.\n.OP \\-cursor cursor Cursor\nSpecifies the mouse cursor to be used for the widget.\nSee \\fBTk_GetCursor\\fR and \\fIcursors(n)\\fR in the Tk reference manual\nfor the legal values.\nIf set to the empty string (the default),\nthe cursor is inherited from the parent widget.\n.OP \\-takefocus takeFocus TakeFocus\nDetermines whether the window accepts the focus during keyboard traversal.\nEither \\fB0\\fR, \\fB1\\fR, a command prefix (to which the widget path\nis appended, and which should return \\fB0\\fR or \\fB1\\fR),\nor the empty string.\nSee \\fIoptions(n)\\fR in the Tk reference manual for the full description.\n.OP \\-style style Style\nMay be used to specify a custom widget style.\n.SH \"SCROLLABLE WIDGET OPTIONS\"\nThe following options are supported by widgets that\nare controllable by a scrollbar.\nSee \\fIscrollbar(n)\\fR for more information\n.OP \\-xscrollcommand xScrollCommand ScrollCommand\nA command prefix, used to communicate with horizontal scrollbars.\n.RS\nWhen the view in the widget's window changes, the widget will\ngenerate a Tcl command by concatenating the scroll command and\ntwo numbers.\nEach of the numbers is a fraction between 0 and 1 indicating\na position in the document; 0 indicates the beginning,\nand 1 indicates the end.\nThe first fraction indicates the first information in the widget\nthat is visible in the window, and the second fraction indicates\nthe information just after the last portion that is visible.\n.PP\nTypically the \\fB\\-xscrollcommand\\fR option consists of the path name\nof a \\fBscrollbar\\fR widget followed by\n.QW set ,\ne.g.\n.QW \".x.scrollbar set\" .\nThis will cause the scrollbar to be updated whenever the view in the\nwindow changes.\n.PP\nIf this option is set to the empty string (the default),\nthen no command will be executed.\n.RE\n.OP \\-yscrollcommand yScrollCommand ScrollCommand\nA command prefix, used to communicate with vertical scrollbars.\nSee the description of \\fB\\-xscrollcommand\\fR above for details.\n.SH \"LABEL OPTIONS\"\nThe following options are supported by labels, buttons,\nand other button-like widgets:\n.OP \\-anchor anchor Anchor\nSpecifies how the information in the widget is positioned\nrelative to the inner margins.  Legal values are\n\\fBn\\fR, \\fBne\\fR, \\fBe\\fR, \\fBse\\fR,\n\\fBs\\fR, \\fBsw\\fR, \\fBw\\fR, \\fBnw\\fR, and \\fBcenter\\fR.\nSee also \\fB\\-justify\\fR (for widgets supporting this option).\n.OP \\-compound compound Compound\nSpecifies how to display the image relative to the text,\nin the case both \\fB\\-text\\fR and \\fB\\-image\\fR are present.\nIf set to the empty string (the default), the rules described in the\n\"Elements\" section of \\fIttk::intro(n)\\fR explain which value is actually\nused.\nThe other valid values are:\n.RS\n.IP text\nDisplay text only.\n.IP image\nDisplay image only.\n.IP center\nDisplay text centered on top of image.\n.IP top\n.IP bottom\n.IP left\n.IP right\nDisplay image above, below, left of, or right of the text, respectively.\n.IP none\nDisplay the image if present, otherwise the text.\n.RE\n.OP \\-font font Font\nFont to use for the text displayed by the widget.\n.OP \\-foreground textColor TextColor\nThe widget's foreground color.\nIf unspecified, the theme default is used.\n.OP \\-image image Image\nSpecifies an image to display.\nThis is a list of 1 or more elements.\nThe first element is the default image name.\nThe rest of the list is a sequence of \\fIstatespec / value\\fR pairs\nas per \\fBstyle map\\fR, specifying different images to use when\nthe widget is in a particular state or combination of states.\nAll images in the list should have the same size.\n.OP \\-justify justify Justify\nIf there are multiple lines of text, specifies how\nthe lines are laid out relative to one another.\nOne of \\fBleft\\fR, \\fBcenter\\fR, or \\fBright\\fR.\nSee also \\fB\\-anchor\\fR (for widgets supporting this option).\n.OP \\-padding padding Padding\nSpecifies the internal padding for the widget.\nThe padding is a list of up to four length specifications\n\\fIleft top right bottom\\fR.\nIf fewer than four elements are specified,\n\\fIbottom\\fR defaults to \\fItop\\fR,\n\\fIright\\fR defaults to \\fIleft\\fR, and\n\\fItop\\fR defaults to \\fIleft\\fR.\nIn other words, a list of three numbers specify the left, vertical, and right\npadding; a list of two numbers specify the horizontal and the vertical padding;\na single number specifies the same padding all the way around the widget.\n.OP \\-text text Text\nSpecifies a text string to be displayed inside the widget (unless overridden\nby \\fB\\-textvariable\\fR for the widgets supporting this option).\n.OP \\-textvariable textVariable Variable\nSpecifies the name of a global variable whose value will be used\nin place of the \\fB\\-text\\fR resource.\n.OP \\-underline underline Underline\nIf set, specifies the integer index (0-based) of a character to underline\nin the text string. \\fBend\\fR corresponds to the last character,\n\\fBend\\fR-1 to the before last character, and so on.\nThe underlined character is used for mnemonic activation.\n.OP \\-width width Width\nIf greater than zero, specifies how much space, in character widths,\nto allocate for the text label.\nIf less than zero, specifies a minimum width.\nIf zero or unspecified, the natural width of the text label is used.\nNote that some themes may specify a non-zero \\fB\\-width\\fR\nin the style.\n.OP \\-wraplength wrapLength WrapLength\nSpecifies the maximum line length. The value may have any of the forms\nacceptable to \\fBTk_GetPixels\\fR. If this option is less than or equal\nto zero, then automatic wrapping is not performed; otherwise\nthe text is split into lines such that no line is longer\nthan the specified value.\n.SH \"ENTRY OPTIONS\"\nThe following options are supported by entry, spinbox and combobox:\n.OP \\-placeholder placeHolder PlaceHolder\nSpecifies a help text string to display if no text is otherwise displayed,\nthat is when the widget is empty. The placeholder text is displayed using\nthe values of the \\fB\\-font\\fR, \\fB\\-justify\\fR and\n\\fB\\-placeholderforeground\\fR options.\n.OP \\-placeholderforeground placeHolderForeground PlaceHolderForeground\nSpecifies the foreground color of the placeholder text.\n.SH \"COMPATIBILITY OPTIONS\"\nThis option is only available for themed widgets that have\n.QW corresponding\ntraditional Tk widgets.\n.OP \\-state state State\nMay be set to \\fBnormal\\fR or \\fBdisabled\\fR\nto control the \\fBdisabled\\fR state bit.\nThis is a write-only option:\nsetting it changes the widget state,\nbut the \\fBstate\\fR widget command\ndoes not affect the \\fB\\-state\\fR option.\n.SH COMMANDS\n.\\\" METHOD: cget\n.TP\n\\fIpathName \\fBcget \\fIoption\\fR\n.\nReturns the current value of the configuration option given\nby \\fIoption\\fR.\n.\\\" METHOD: configure\n.TP\n\\fIpathName \\fBconfigure\\fR ?\\fIoption\\fR? ?\\fIvalue option value ...\\fR?\n.\nQuery or modify the configuration options of the widget.\nIf one or more \\fIoption\\-value\\fR pairs are specified,\nthen the command modifies the given widget option(s)\nto have the given value(s);\nin this case the command returns an empty string.\nIf \\fIoption\\fR is specified with no \\fIvalue\\fR,\nthen the command returns a list describing the named option:\nthe elements of the list are the\noption name, database name, database class, default value,\nand current value.\n.\\\" Note: Ttk widgets don't use TK_OPTION_SYNONYM.\nIf no \\fIoption\\fR is specified, returns a list describing all of\nthe available options for \\fIpathName\\fR.\n.\\\" METHOD: identify\n.TP\n\\fIpathName \\fBidentify element \\fIx y\\fR\n.\nReturns the name of the element under the point given\nby \\fIx\\fR and \\fIy\\fR, or an empty string if the point does\nnot lie within any element.\n\\fIx\\fR and \\fIy\\fR are pixel coordinates relative to the widget.\nSome widgets accept other \\fBidentify\\fR subcommands described\nin these widgets documentation.\n.\\\" METHOD: instate\n.TP\n\\fIpathName \\fBinstate \\fIstatespec\\fR ?\\fIscript\\fR?\n.\nTest the widget's state.\nIf \\fIscript\\fR is not specified, returns 1 if\nthe widget state matches \\fIstatespec\\fR and 0 otherwise.\nIf \\fIscript\\fR is specified, equivalent to\n.CS\nif {[\\fIpathName\\fR instate \\fIstateSpec\\fR]} \\fIscript\\fR\n.CE\n.\\\" METHOD: state\n.TP\n\\fIpathName \\fBstate\\fR ?\\fIstateSpec\\fR?\n.\nModify or inquire widget state.\nIf \\fIstateSpec\\fR is present, sets the widget state:\nfor each flag in \\fIstateSpec\\fR, sets the corresponding flag\nor clears it if prefixed by an exclamation point.\n.RS\nReturns a new state spec indicating which flags were changed:\n.CS\nset changes [\\fIpathName \\fRstate \\fIspec\\fR]\n\\fIpathName \\fRstate $changes\n.CE\nwill restore \\fIpathName\\fR to the original state.\nIf \\fIstateSpec\\fR is not specified,\nreturns a list of the currently-enabled state flags.\n.RE\n.\\\" METHOD: style\n.TP\n\\fIpathName \\fBstyle\\fR\n.\nReturn the style used by the widget.\n.\\\" METHOD: xview\n.TP\n\\fIpathName \\fBxview \\fIargs\\fR\n.\nThis command is used to query and change the horizontal position of the\ncontent in the widget's window.  It can take any of the following\nforms:\n.RS\n.TP\n\\fIpathName \\fBxview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1; together they describe\nthe horizontal span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the widget's content is off-screen to the left, the middle 40% is visible\nin the window, and 40% of the content is off-screen to the right.\nThese are the same values passed to scrollbars via the \\fB\\-xscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fBxview\\fI index\\fR\n.\nAdjusts the view in the window so that the content given by \\fIindex\\fR\nis displayed at the left edge of the window.\n.TP\n\\fIpathName \\fBxview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the character \\fIfraction\\fR of the\nway through the content appears at the left edge of the window.\n\\fIFraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fBxview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window left or right according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR.\n'\\\" or an abbreviation of one of these, but we don't document that.\nIf \\fIwhat\\fR is\n\\fBpages\\fR then the view adjusts by \\fInumber\\fR screenfuls.\nIf \\fInumber\\fR is negative then characters farther to the left\nbecome visible;  if it is positive then characters farther to the right\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts left or right by\n\\fInumber\\fR average-width characters on the display.\n.RE\n.\\\" METHOD: yview\n.TP\n\\fIpathName \\fByview \\fIargs\\fR\n.\nThis command is used to query and change the vertical position of the\ncontent in the widget's window.  It can take any of the following\nforms:\n.RS\n.TP\n\\fIpathName \\fByview\\fR\n.\nReturns a list containing two elements.\nEach element is a real fraction between 0 and 1; together they describe\nthe vertical span that is visible in the window.\nFor example, if the first element is .2 and the second element is .6,\n20% of the widget's content is off-screen to the top, the middle 40% is visible\nin the window, and 40% of the content is off-screen to the bottom.\nThese are the same values passed to scrollbars via the \\fB\\-yscrollcommand\\fR\noption.\n.TP\n\\fIpathName \\fByview\\fI index\\fR\n.\nAdjusts the view in the window so that the content given by \\fIindex\\fR\nis displayed at the top edge of the window.\n.TP\n\\fIpathName \\fByview moveto\\fI fraction\\fR\n.\nAdjusts the view in the window so that the item \\fIfraction\\fR of the\nway through the content appears at the top edge of the window.\n\\fIFraction\\fR must be a fraction between 0 and 1.\n.TP\n\\fIpathName \\fByview scroll \\fInumber what\\fR\n.\nThis command shifts the view in the window up or down according to\n\\fInumber\\fR and \\fIwhat\\fR.\n\\fINumber\\fR must be an integer or a float, but if it is a float then\nit is converted to an integer, rounded away from 0.\n\\fIWhat\\fR must be either \\fBpages\\fR or \\fBunits\\fR.\n'\\\" or an abbreviation of one of these, but we don't document that.\nIf \\fIwhat\\fR is\n\\fBpages\\fR then the view adjusts by \\fInumber\\fR screenfuls.\nIf \\fInumber\\fR is negative then items farther to the top\nbecome visible;  if it is positive then items farther to the bottom\nbecome visible.\nIf \\fIwhat\\fR is \\fBunits\\fR, the view adjusts up or down by\n\\fInumber\\fR average-width characters on the display.\n.RE\n.SH \"WIDGET STATES\"\nThe widget state is a bitmap of independent state flags.\nWidget state flags include:\n.IP \\fBactive\\fR\nThe mouse cursor is over the widget\nand pressing a mouse button will cause some action to occur. (aka\n.QW prelight\n(Gnome),\n.QW hot\n(Windows),\n.QW hover ).\n.IP \\fBalternate\\fR\nA widget-specific alternate display format.\nFor example, used for checkbuttons and radiobuttons in the\n.QW tristate\nor\n.QW mixed\nstate, and for buttons with \\fB\\-default active\\fR.\n.IP \\fBbackground\\fR\nWindows and the Mac have a notion of an\n.QW active\nor foreground window.\nThe \\fBbackground\\fR state is set for widgets in a background window,\nand cleared for those in the foreground window.\n.IP \\fBdisabled\\fR\nWidget is disabled under program control (aka\n.QW unavailable ,\n.QW inactive ).\n.IP \\fBfirst\\fR\nWidget is the first one in a container. Used for tab elements in a notebook.\n.IP \\fBfocus\\fR\nWidget has keyboard focus.\n.IP \\fBhover\\fR\nThe mouse cursor is within the widget.\nThis is similar to the \\fBactive\\fP state;\nit is used in some themes for widgets that\nprovide distinct visual feedback for\nthe active widget in addition to the active element\nwithin the widget.\n.IP \\fBinvalid\\fR\nThe widget's value is invalid.\n(Potential uses: scale widget value out of bounds,\nentry widget value failed validation.)\n.IP \\fBlast\\fR\nWidget is the last one in a container. Used for tab elements in a notebook.\n.IP \\fBleaf\\fR\nWidget is a leaf. Used in a treeview widget.\n.IP \\fBopen\\fR\nWidget is in the open state. Used in a treeview widget.\n.IP \\fBpressed\\fR\nWidget is being pressed (aka\n.QW armed\nin Motif).\n.IP \\fBreadonly\\fR\nWidget should not allow user modification.\n.IP \\fBselected\\fR\n.QW On ,\n.QW true ,\nor\n.QW current\nfor things like checkbuttons and radiobuttons.\n.IP \\fBuser1\\fR-\\fBuser6\\fR\nFreely usable for other purposes\n.PP\nA \\fIstate specification\\fR or \\fIstateSpec\\fR is a list\nof state names, optionally prefixed with an exclamation point (!)\nindicating that the bit is off.\n.SH EXAMPLES\n.CS\nset b [ttk::button .b]\n\n# Disable the widget:\n$b \\fBstate\\fR disabled\n\n# Invoke the widget only if it is currently pressed and enabled:\n$b \\fBinstate\\fR {pressed !disabled} { .b invoke }\n\n# Reenable widget:\n$b \\fBstate\\fR !disabled\n.CE\n.SH \"SEE ALSO\"\nttk::intro(n), ttk::style(n)\n.SH KEYWORDS\nstate, configure, option\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/winfo.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1990-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1997 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH winfo n 4.3 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nwinfo \\- Return window-related information\n.SH SYNOPSIS\n\\fBwinfo\\fI option \\fR?\\fIarg ...\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBwinfo\\fR command is used to retrieve information about windows\nmanaged by Tk.  It can take any of a number of different forms,\ndepending on the \\fIoption\\fR argument.  The legal forms are:\n.\\\" METHOD: atom\n.TP\n\\fBwinfo atom \\fR?\\fB\\-displayof \\fIwindow\\fR? \\fIname\\fR\n.\nReturns a decimal string giving the integer identifier for the\natom whose name is \\fIname\\fR.  If no atom exists with the name\n\\fIname\\fR then a new one is created.\nIf the \\fB\\-displayof\\fR option is given then the atom is looked\nup on the display of \\fIwindow\\fR;  otherwise it is looked up on\nthe display of the application's main window.\n.\\\" METHOD: atomname\n.TP\n\\fBwinfo atomname \\fR?\\fB\\-displayof \\fIwindow\\fR? \\fIid\\fR\n.\nReturns the textual name for the atom whose integer identifier is\n\\fIid\\fR.\nIf the \\fB\\-displayof\\fR option is given then the identifier is looked\nup on the display of \\fIwindow\\fR;  otherwise it is looked up on\nthe display of the application's main window.\nThis command is the inverse of the \\fBwinfo atom\\fR command.\nIt generates an error if no such atom exists.\n.\\\" METHOD: cells\n.TP\n\\fBwinfo cells \\fIwindow\\fR\n.\nReturns a decimal string giving the number of cells in the\ncolor map for \\fIwindow\\fR.\n.\\\" METHOD: children\n.TP\n\\fBwinfo children \\fIwindow\\fR\n.\nReturns a list containing the path names of all the children\nof \\fIwindow\\fR. Top-level windows are returned as children\nof their logical parents. The list is in stacking order, with\nthe lowest window first, except for Top-level windows which\nare not returned in stacking order. Use the \\fBwm stackorder\\fR\ncommand to query the stacking order of Top-level windows.\n.\\\" METHOD: class\n.TP\n\\fBwinfo class \\fIwindow\\fR\n.\nReturns the class name for \\fIwindow\\fR.\n.\\\" METHOD: colormapfull\n.TP\n\\fBwinfo colormapfull \\fIwindow\\fR\n.\nReturns 1 if the colormap for \\fIwindow\\fR is known to be full, 0\notherwise.  The colormap for a window is\n.QW known\nto be full if the last\nattempt to allocate a new color on that window failed and this\napplication has not freed any colors in the colormap since the\nfailed allocation.\n.\\\" METHOD: containing\n.TP\n\\fBwinfo containing \\fR?\\fB\\-displayof \\fIwindow\\fR? \\fIrootX rootY\\fR\n.\nReturns the path name for the window containing the point given\nby \\fIrootX\\fR and \\fIrootY\\fR.\n\\fIRootX\\fR and \\fIrootY\\fR are specified in screen units (i.e.\nany form acceptable to \\fBTk_GetPixels\\fR) in the coordinate\nsystem of the root window (if a virtual-root window manager is in\nuse then the coordinate system of the virtual root window is used).\nIf the \\fB\\-displayof\\fR option is given then the coordinates refer\nto the screen containing \\fIwindow\\fR;  otherwise they refer to the\nscreen of the application's main window.\nIf no window in this application contains the point then an empty\nstring is returned.\nAn empty string is also returned if the point lies in the title bar\nor border of its highest containing toplevel in this application.\n(Note that with some window managers the borders may be invisible.)\nIn selecting the containing window, children are given higher priority\nthan parents and among siblings the highest one in the stacking order is\nchosen.\n.\\\" METHOD: depth\n.TP\n\\fBwinfo depth \\fIwindow\\fR\n.\nReturns a decimal string giving the depth of \\fIwindow\\fR (number\nof bits per pixel).\n.\\\" METHOD: exists\n.TP\n\\fBwinfo exists \\fIwindow\\fR\n.\nReturns 1 if there exists a window named \\fIwindow\\fR, 0 if no such\nwindow exists.\n.\\\" METHOD: fpixels\n.TP\n\\fBwinfo fpixels \\fIwindow number\\fR\n.\nReturns a floating-point value giving the number of pixels\nin \\fIwindow\\fR corresponding to the distance given by \\fInumber\\fR.\n\\fINumber\\fR may be specified in any of the forms acceptable\nto \\fBTk_GetScreenMM\\fR, such as\n.QW 2.0c\nor\n.QW 1i .\nThe return value may be fractional;  for an integer value, use\n\\fBwinfo pixels\\fR.\n.\\\" METHOD: geometry\n.TP\n\\fBwinfo geometry \\fIwindow\\fR\n.\nReturns the geometry for \\fIwindow\\fR, in the form\n\\fIwidth\\fBx\\fIheight\\fB+\\fIx\\fB+\\fIy\\fR.  All dimensions are\nin pixels.\n.\\\" METHOD: height\n.TP\n\\fBwinfo height \\fIwindow\\fR\n.\nReturns a decimal string giving \\fIwindow\\fR's height in pixels.\nWhen a window is first created its height will be 1 pixel;  the\nheight will eventually be changed by a geometry manager to fulfil\nthe window's needs.\nIf you need the true height immediately after creating a widget,\ninvoke \\fBupdate\\fR to force the geometry manager to arrange it,\nor use \\fBwinfo reqheight\\fR to get the window's requested height\ninstead of its actual height.\n.\\\" METHOD: id\n.TP\n\\fBwinfo id \\fIwindow\\fR\n.\nReturns a hexadecimal string giving a low-level platform-specific\nidentifier for \\fIwindow\\fR.  On Unix platforms, this is the X\nwindow identifier.  Under Windows, this is the Windows\nHWND.  On the Macintosh the value has no meaning outside Tk.\n.\\\" METHOD: interps\n.TP\n\\fBwinfo interps \\fR?\\fB\\-displayof \\fIwindow\\fR?\n.\nReturns a list whose members are the names of all Tcl interpreters\n(e.g. all Tk-based applications) currently registered for a particular display.\nIf the \\fB\\-displayof\\fR option is given then the return value refers\nto the display of \\fIwindow\\fR;  otherwise it refers to\nthe display of the application's main window.\n.\\\" METHOD: ismapped\n.TP\n\\fBwinfo ismapped \\fIwindow\\fR\n.\nReturns \\fB1\\fR if \\fIwindow\\fR is currently mapped, \\fB0\\fR otherwise.\n.\\\" METHOD: manager\n.TP\n\\fBwinfo manager \\fIwindow\\fR\n.\nReturns the name of the geometry manager currently\nresponsible for \\fIwindow\\fR, or an empty string if \\fIwindow\\fR\nis not managed by any geometry manager.\nThe name is usually the name of the Tcl command for the geometry\nmanager, such as \\fBpack\\fR or \\fBplace\\fR.\nIf the geometry manager is a widget, such as canvases or text, the\nname is the widget's class command, such as \\fBcanvas\\fR.\n.\\\" METHOD: name\n.TP\n\\fBwinfo name \\fIwindow\\fR\n.\nReturns \\fIwindow\\fR's name (i.e. its name within its parent, as opposed\nto its full path name).\nThe command \\fBwinfo name .\\fR will return the name of the application.\n.\\\" METHOD: parent\n.TP\n\\fBwinfo parent \\fIwindow\\fR\n.\nReturns the path name of \\fIwindow\\fR's parent, or an empty string\nif \\fIwindow\\fR is the main window of the application.\n.\\\" METHOD: pathname\n.TP\n\\fBwinfo pathname \\fR?\\fB\\-displayof \\fIwindow\\fR? \\fIid\\fR\n.\nReturns the path name of the window whose X identifier is \\fIid\\fR.\n\\fIId\\fR must be a decimal, hexadecimal, or octal integer and must\ncorrespond to a window in the invoking application.\nIf the \\fB\\-displayof\\fR option is given then the identifier is looked\nup on the display of \\fIwindow\\fR;  otherwise it is looked up on\nthe display of the application's main window.\n.\\\" METHOD: pixels\n.TP\n\\fBwinfo pixels \\fIwindow number\\fR\n.\nReturns the number of pixels in \\fIwindow\\fR corresponding\nto the distance given by \\fInumber\\fR.\n\\fINumber\\fR may be specified in any of the forms acceptable\nto \\fBTk_GetPixels\\fR, such as\n.QW 2.0c\nor\n.QW 1i .\nThe result is rounded to the nearest integer value;  for a\nfractional result, use \\fBwinfo fpixels\\fR.\n.\\\" METHOD: pointerx\n.TP\n\\fBwinfo pointerx \\fIwindow\\fR\n.\nIf the mouse pointer is on the same screen as \\fIwindow\\fR, returns the\npointer's x coordinate, measured in pixels in the screen's root window.\nIf a virtual root window is in use on the screen, the position is\nmeasured in the virtual root.\nIf the mouse pointer is not on the same screen as \\fIwindow\\fR then\n-1 is returned.\n.\\\" METHOD: pointerxy\n.TP\n\\fBwinfo pointerxy \\fIwindow\\fR\n.\nIf the mouse pointer is on the same screen as \\fIwindow\\fR, returns a list\nwith two elements, which are the pointer's x and y coordinates measured\nin pixels in the screen's root window.\nIf a virtual root window is in use on the screen, the position\nis computed in the virtual root.\nIf the mouse pointer is not on the same screen as \\fIwindow\\fR then\nboth of the returned coordinates are \\-1.\n.\\\" METHOD: pointery\n.TP\n\\fBwinfo pointery \\fIwindow\\fR\n.\nIf the mouse pointer is on the same screen as \\fIwindow\\fR, returns the\npointer's y coordinate, measured in pixels in the screen's root window.\nIf a virtual root window is in use on the screen, the position\nis computed in the virtual root.\nIf the mouse pointer is not on the same screen as \\fIwindow\\fR then\n-1 is returned.\n.\\\" METHOD: reqheight\n.TP\n\\fBwinfo reqheight \\fIwindow\\fR\n.\nReturns a decimal string giving \\fIwindow\\fR's requested height,\nin pixels.  This is the value used by \\fIwindow\\fR's geometry\nmanager to compute its geometry.\n.\\\" METHOD: reqwidth\n.TP\n\\fBwinfo reqwidth \\fIwindow\\fR\n.\nReturns a decimal string giving \\fIwindow\\fR's requested width,\nin pixels.  This is the value used by \\fIwindow\\fR's geometry\nmanager to compute its geometry.\n.\\\" METHOD: rgb\n.TP\n\\fBwinfo rgb \\fIwindow color\\fR\n.\nReturns a list containing three decimal values in the range 0 to\n65535, which are the\nred, green, and blue intensities that correspond to \\fIcolor\\fR in\nthe window given by \\fIwindow\\fR.  \\fIColor\\fR\nmay be specified in any of the forms acceptable for a color\noption.\n.\\\" METHOD: rootx\n.TP\n\\fBwinfo rootx \\fIwindow\\fR\n.\nReturns a decimal string giving the x-coordinate, in the root\nwindow of the screen, of the\nupper-left corner of \\fIwindow\\fR's border (or \\fIwindow\\fR if it\nhas no border).\n.\\\" METHOD: rooty\n.TP\n\\fBwinfo rooty \\fIwindow\\fR\n.\nReturns a decimal string giving the y-coordinate, in the root\nwindow of the screen, of the\nupper-left corner of \\fIwindow\\fR's border (or \\fIwindow\\fR if it\nhas no border).\n.\\\" METHOD: screen\n.TP\n\\fBwinfo screen \\fIwindow\\fR\n.\nReturns the name of the screen associated with \\fIwindow\\fR, in\nthe form \\fIdisplayName\\fR.\\fIscreenIndex\\fR.\n.\\\" METHOD: screencells\n.TP\n\\fBwinfo screencells \\fIwindow\\fR\n.\nReturns a decimal string giving the number of cells in the default\ncolor map for \\fIwindow\\fR's screen.\n.\\\" METHOD: screendepth\n.TP\n\\fBwinfo screendepth \\fIwindow\\fR\n.\nReturns a decimal string giving the depth of the root window\nof \\fIwindow\\fR's screen (number of bits per pixel).\n.\\\" METHOD: screenheight\n.TP\n\\fBwinfo screenheight \\fIwindow\\fR\n.\nReturns a decimal string giving the height of \\fIwindow\\fR's screen,\nin pixels.\n.\\\" METHOD: screenmmheight\n.TP\n\\fBwinfo screenmmheight \\fIwindow\\fR\n.\nReturns a decimal string giving the height of \\fIwindow\\fR's screen,\nin millimeters.\n.\\\" METHOD: screenmmwidth\n.TP\n\\fBwinfo screenmmwidth \\fIwindow\\fR\n.\nReturns a decimal string giving the width of \\fIwindow\\fR's screen,\nin millimeters.\n.\\\" METHOD: screenvisual\n.TP\n\\fBwinfo screenvisual \\fIwindow\\fR\n.\nReturns one of the following strings to indicate the default visual\nclass for \\fIwindow\\fR's screen: \\fBdirectcolor\\fR, \\fBgrayscale\\fR,\n\\fBpseudocolor\\fR, \\fBstaticcolor\\fR, \\fBstaticgray\\fR, or\n\\fBtruecolor\\fR.\n.\\\" METHOD: screenwidth\n.TP\n\\fBwinfo screenwidth \\fIwindow\\fR\n.\nReturns a decimal string giving the width of \\fIwindow\\fR's screen,\nin pixels.\n.\\\" METHOD: server\n.TP\n\\fBwinfo server \\fIwindow\\fR\n.\nReturns a string containing information about the server for\n\\fIwindow\\fR's display.  The exact format of this string may vary\nfrom platform to platform.  For X servers the string\nhas the form\n.QW \"\\fBX\\fImajor\\fBR\\fIminor vendor vendorVersion\\fR\"\nwhere \\fImajor\\fR and \\fIminor\\fR are the version and revision\nnumbers provided by the server (e.g., \\fBX11R5\\fR), \\fIvendor\\fR\nis the name of the vendor for the server, and \\fIvendorRelease\\fR\nis an integer release number provided by the server.\n.\\\" METHOD: toplevel\n.TP\n\\fBwinfo toplevel \\fIwindow\\fR\n.\nReturns the path name of the top-of-hierarchy window containing \\fIwindow\\fR.\nIn standard Tk this will always be a \\fBtoplevel\\fR widget, but extensions may\ncreate other kinds of top-of-hierarchy widgets.\n.\\\" METHOD: viewable\n.TP\n\\fBwinfo viewable \\fIwindow\\fR\n.\nReturns 1 if \\fIwindow\\fR and all of its ancestors up through the\nnearest toplevel window are mapped.  Returns 0 if any of these\nwindows are not mapped.\n.\\\" METHOD: visual\n.TP\n\\fBwinfo visual \\fIwindow\\fR\n.\nReturns one of the following strings to indicate the visual\nclass for \\fIwindow\\fR: \\fBdirectcolor\\fR, \\fBgrayscale\\fR,\n\\fBpseudocolor\\fR, \\fBstaticcolor\\fR, \\fBstaticgray\\fR, or\n\\fBtruecolor\\fR.\n.\\\" METHOD: visualid\n.TP\n\\fBwinfo visualid \\fIwindow\\fR\n.\nReturns the X identifier for the visual for \\fIwindow\\fR.\n.\\\" METHOD: visualsavailable\n.TP\n\\fBwinfo visualsavailable \\fIwindow\\fR ?\\fBincludeids\\fR?\n.\nReturns a list whose elements describe the visuals available for\n\\fIwindow\\fR's screen.\nEach element consists of a visual class followed by an integer depth.\nThe class has the same form as returned by \\fBwinfo visual\\fR.\nThe depth gives the number of bits per pixel in the visual.\nIn addition, if the \\fBincludeids\\fR argument is provided, then the\ndepth is followed by the X identifier for the visual.\n.\\\" METHOD: vrootheight\n.TP\n\\fBwinfo vrootheight \\fIwindow\\fR\n.\nReturns the height of the virtual root window associated with \\fIwindow\\fR\nif there is one;  otherwise returns the height of \\fIwindow\\fR's screen.\n.\\\" METHOD: vrootwidth\n.TP\n\\fBwinfo vrootwidth \\fIwindow\\fR\n.\nReturns the width of the virtual root window associated with \\fIwindow\\fR\nif there is one;  otherwise returns the width of \\fIwindow\\fR's screen.\n.\\\" METHOD: vrootx\n.TP\n\\fBwinfo vrootx \\fIwindow\\fR\n.\nReturns the x-offset of the virtual root window associated with \\fIwindow\\fR,\nrelative to the root window of its screen.\nThis is normally either zero or negative.\nReturns 0 if there is no virtual root window for \\fIwindow\\fR.\n.\\\" METHOD: vrooty\n.TP\n\\fBwinfo vrooty \\fIwindow\\fR\n.\nReturns the y-offset of the virtual root window associated with \\fIwindow\\fR,\nrelative to the root window of its screen.\nThis is normally either zero or negative.\nReturns 0 if there is no virtual root window for \\fIwindow\\fR.\n.\\\" METHOD: width\n.TP\n\\fBwinfo width \\fIwindow\\fR\n.\nReturns a decimal string giving \\fIwindow\\fR's width in pixels.\nWhen a window is first created its width will be 1 pixel;  the\nwidth will eventually be changed by a geometry manager to fulfil\nthe window's needs.\nIf you need the true width immediately after creating a widget,\ninvoke \\fBupdate\\fR to force the geometry manager to arrange it,\nor use \\fBwinfo reqwidth\\fR to get the window's requested width\ninstead of its actual width.\n.\\\" METHOD: x\n.TP\n\\fBwinfo x \\fIwindow\\fR\n.\nReturns a decimal string giving the x-coordinate, in \\fIwindow\\fR's\nparent, of the\nupper-left corner of \\fIwindow\\fR's border (or \\fIwindow\\fR if it\nhas no border).\n.\\\" METHOD: y\n.TP\n\\fBwinfo y \\fIwindow\\fR\n.\nReturns a decimal string giving the y-coordinate, in \\fIwindow\\fR's\nparent, of the\nupper-left corner of \\fIwindow\\fR's border (or \\fIwindow\\fR if it\nhas no border).\n.SH EXAMPLE\n.PP\nPrint where the mouse pointer is and what window it is currently over:\n.CS\nlassign [\\fBwinfo pointerxy\\fR .] x y\nputs -nonewline \"Mouse pointer at ($x,$y) which is \"\nset win [\\fBwinfo containing\\fR $x $y]\nif {$win eq \"\"} {\n    puts \"over no window\"\n} else {\n    puts \"over $win\"\n}\n.CE\n.SH KEYWORDS\natom, children, class, geometry, height, identifier, information, interpreters,\nmapped, parent, path name, screen, virtual root, width, window\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "doc/wish.1",
    "content": "'\\\"\n'\\\" Copyright (c) 1991-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH wish 1 8.0 Tk \"Tk Applications\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nwish \\- Simple windowing shell\n.SH SYNOPSIS\n\\fBwish\\fR ?\\fBoptions\\fR? ?\\fIfileName arg ...\\fR?\n.SH OPTIONS\n.\\\" OPTION: -encoding\n.IP \"\\fB\\-encoding \\fIname\\fR\" 20\nSpecifies the encoding of the text stored in \\fIfileName\\fR.\nThis option is only recognized prior to the \\fIfileName\\fR argument.\n.\\\" OPTION: -colormap\n.IP \"\\fB\\-colormap \\fInew\\fR\" 20\nSpecifies that the window should have a new private colormap instead of\nusing the default colormap for the screen.\n.\\\" OPTION: -display\n.IP \"\\fB\\-display \\fIdisplay\\fR\" 20\nDisplay (and screen) on which to display window.\n.\\\" OPTION: -geometry\n.IP \"\\fB\\-geometry \\fIgeometry\\fR\" 20\nInitial geometry to use for window.  If this option is specified, its\nvalue is stored in the \\fBgeometry\\fR global variable of the application's\nTcl interpreter.\n.\\\" OPTION: -name\n.IP \"\\fB\\-name \\fIname\\fR\" 20\nUse \\fIname\\fR as the title to be displayed in the window, and\nas the name of the interpreter for \\fBsend\\fR commands.\n.\\\" OPTION: -sync\n.IP \"\\fB\\-sync\\fR\" 20\nExecute all X server commands synchronously, so that errors\nare reported immediately.  This will result in much slower\nexecution, but it is useful for debugging.\n.\\\" OPTION: -use\n.IP \"\\fB\\-use\\fR \\fIid\\fR\" 20\nSpecifies that the main window for the application is to be embedded in\nthe window whose identifier is \\fIid\\fR, instead of being created as an\nindependent toplevel window.  \\fIId\\fR must be specified in the same\nway as the value for the \\fB\\-use\\fR option for toplevel widgets (i.e.\nit has a form like that returned by the \\fBwinfo id\\fR command).\n.RS\nNote that on some platforms this will only work correctly if \\fIid\\fR\nrefers to a Tk \\fBframe\\fR or \\fBtoplevel\\fR that has its\n\\fB\\-container\\fR option enabled.\n.RE\n.\\\" OPTION: -visual\n.IP \"\\fB\\-visual \\fIvisual\\fR\" 20\nSpecifies the visual to use for the window.\n\\fIVisual\\fR may have any of the forms supported by the \\fBTk_GetVisual\\fR\nprocedure.\n.\\\" OPTION: --\n.IP \"\\fB\\-\\|\\-\\fR\" 20\nPass all remaining arguments through to the script's \\fBargv\\fR\nvariable without interpreting them.\nThis provides a mechanism for passing arguments such as \\fB\\-name\\fR\nto a script instead of having \\fBwish\\fR interpret them.\n.BE\n.SH DESCRIPTION\n.PP\n\\fBWish\\fR is a simple program consisting of the Tcl command\nlanguage, the Tk toolkit, and a main program that reads commands\nfrom standard input or from a file.\nIt creates a main window and then processes Tcl commands.\nIf \\fBwish\\fR is invoked with arguments, then the first few\narguments, ?\\fB\\-encoding \\fIname\\fR? ?\\fIfileName\\fR?, specify the\nname of a script file, and, optionally, the\nencoding of the text data stored in that script file.  A value\nfor \\fIfileName\\fR is recognized if the appropriate argument\ndoes not start with\n.QW \\- .\n.PP\nIf there are no arguments, or the arguments do not specify a \\fIfileName\\fR,\nthen wish reads Tcl commands interactively from standard input.\nIt will continue processing commands until all windows have been\ndeleted or until end-of-file is reached on standard input.\nIf there exists a file\n.QW \\fB.wishrc\\fR\nin the home directory of the user, \\fBwish\\fR evaluates the file as a\nTcl script just before reading the first command from standard input.\n.PP\nIf arguments to \\fBwish\\fR do specify a \\fIfileName\\fR, then\n\\fIfileName\\fR is treated as the name of a script file.\n\\fBWish\\fR will evaluate the script in \\fIfileName\\fR (which\npresumably creates a user interface), then it will respond to events\nuntil all windows have been deleted.\nCommands will not be read from standard input.\nThere is no automatic evaluation of\n.QW \\fB.wishrc\\fR\nwhen the name of a script file is presented on the \\fBwish\\fR command line,\nbut the script file can always \\fBsource\\fR it if desired.\n.PP\nNote that on Windows, the \\fBwish\\fIversion\\fB.exe\\fR program varies\nfrom the \\fBtclsh\\fIversion\\fB.exe\\fR program in an additional\nimportant way: it does not connect to a standard Windows console and\nis instead a windowed program. Because of this, it additionally\nprovides access to its own \\fBconsole\\fR command.\n.SH \"OPTION PROCESSING\"\n.PP\n\\fBWish\\fR automatically processes all of the command-line options\ndescribed in the \\fBOPTIONS\\fR summary above.\nAny other command-line arguments besides these are passed through\nto the application using the \\fBargc\\fR and \\fBargv\\fR variables\ndescribed later.\n.SH \"APPLICATION NAME AND CLASS\"\n.PP\nThe name of the application, which is used for purposes such as\n\\fBsend\\fR commands, is taken from the \\fB\\-name\\fR option,\nif it is specified;  otherwise it is taken from \\fIfileName\\fR,\nif it is specified, or from the command name by which\n\\fBwish\\fR was invoked.  In the last two cases, if the name contains a\n.QW /\ncharacter, then only the characters after the last slash are used\nas the application name.\n.PP\nThe class of the application, which is used for purposes such as\nspecifying options with a \\fBRESOURCE_MANAGER\\fR property or .Xdefaults\nfile, is the same as its name except that the first letter is\ncapitalized.\n.SH \"VARIABLES\"\n.PP\n\\fBWish\\fR sets the following global Tcl variables:\n.\\\" VARIABLE: argc\n.TP 15\n\\fBargc\\fR\n.\nContains a count of the number of \\fIarg\\fR arguments (0 if none),\nnot including the options described above.\n.\\\" VARIABLE: argv\n.TP 15\n\\fBargv\\fR\n.\nContains a Tcl list whose elements are the \\fIarg\\fR arguments\nthat follow a \\fB\\-\\|\\-\\fR option or do not match any of the\noptions described in \\fBOPTIONS\\fR above, in order, or an empty string\nif there are no such arguments.\n.\\\" VARIABLE: argv0\n.TP 15\n\\fBargv0\\fR\n.\nContains \\fIfileName\\fR if it was specified.\nOtherwise, contains the name by which \\fBwish\\fR was invoked.\n.\\\" VARIABLE: geometry\n.TP 15\n\\fBgeometry\\fR\n.\nIf the \\fB\\-geometry\\fR option is specified, \\fBwish\\fR copies its\nvalue into this variable.  If the variable still exists after\n\\fIfileName\\fR has been evaluated, \\fBwish\\fR uses the value of\nthe variable in a \\fBwm geometry\\fR command to set the main\nwindow's geometry.\n.\\\" VARIABLE: tcl_interactive\n.TP 15\n\\fBtcl_interactive\\fR\n.\nContains 1 if \\fBwish\\fR is reading commands interactively (\\fIfileName\\fR\nwas not specified and standard input is a terminal-like\ndevice), 0 otherwise.\n.SH \"SCRIPT FILES\"\n.PP\nIf you create a Tcl script in a file whose first line is\n.CS\n\\fB#!/usr/local/bin/wish\\fR\n.CE\nthen you can invoke the script file directly from your shell if\nyou mark it as executable.\nThis assumes that \\fBwish\\fR has been installed in the default\nlocation in /usr/local/bin;  if it is installed somewhere else\nthen you will have to modify the above line to match.\nMany UNIX systems do not allow the \\fB#!\\fR line to exceed about\n30 characters in length, so be sure that the \\fBwish\\fR executable\ncan be accessed with a short file name.\n.PP\nAn even better approach is to start your script files with the\nfollowing three lines:\n.CS\n\\fB#!/bin/sh\n# the next line restarts using wish \\e\nexec wish \"$0\" ${1+\"$@\"}\\fR\n.CE\nThis approach has three advantages over the approach in the previous\nparagraph.  First, the location of the \\fBwish\\fR binary does not have\nto be hard-wired into the script:  it can be anywhere in your shell\nsearch path.  Second, it gets around the 30-character file name limit\nin the previous approach.\nThird, this approach will work even if \\fBwish\\fR is\nitself a shell script (this is done on some systems in order to\nhandle multiple architectures or operating systems:  the \\fBwish\\fR\nscript selects one of several binaries to run).  The three lines\ncause both \\fBsh\\fR and \\fBwish\\fR to process the script, but the\n\\fBexec\\fR is only executed by \\fBsh\\fR.\n\\fBsh\\fR processes the script first;  it treats the second\nline as a comment and executes the third line.\nThe \\fBexec\\fR statement cause the shell to stop processing and\ninstead to start up \\fBwish\\fR to reprocess the entire script.\nWhen \\fBwish\\fR starts up, it treats all three lines as comments,\nsince the backslash at the end of the second line causes the third\nline to be treated as part of the comment on the second line.\n.PP\nThe end of a script file may be marked either by the physical end of\nthe medium, or by the character,\n.QW \\e032\n.PQ \\eu001a \", control-Z\" .\nIf this character is present in the file, the \\fBwish\\fR application\nwill read text up to but not including the character.  An application\nthat requires this character in the file may encode it as\n.QW \\e032 ,\n.QW \\ex1a ,\nor\n.QW \\eu001a ;\nor may generate it by use of commands such as \\fBformat\\fR or \\fBbinary\\fR.\n.SH PROMPTS\n.PP\nWhen \\fBwish\\fR is invoked interactively it normally prompts for each\ncommand with\n.QW \"\\fB% \\fR\" .\nYou can change the prompt by setting the\nvariables \\fBtcl_prompt1\\fR and \\fBtcl_prompt2\\fR.  If variable\n\\fBtcl_prompt1\\fR exists then it must consist of a Tcl script\nto output a prompt;  instead of outputting a prompt \\fBwish\\fR\nwill evaluate the script in \\fBtcl_prompt1\\fR.\nThe variable \\fBtcl_prompt2\\fR is used in a similar way when\na newline is typed but the current command is not yet complete;\nif \\fBtcl_prompt2\\fR is not set then no prompt is output for\nincomplete commands.\n.SH ZIPVFS\n.PP\nWhen a zipfile is concatenated to the end of \\fBwish\\fR, on startup\nthe contents of the zip archive will be mounted under the virtual file\nsystem \\fB//zipfs:/\\fR. If a top level directory \\fBtk_library\\fR is\npresent in the zip archive, it will become the directory loaded as\nenv(TK_LIBRARY). If a file named \\fBmain.tcl\\fR is present in the top\nlevel directory of the zip archive, it will be sourced instead of the\nshell's normal command line handing.\n.PP\nOnly one zipfile can be concatenated to the end of executable image\n(tclsh, or wish). However, if multiple zipfiles are\nconcatenated, only the last one is used.\n\nThis filesystem is read-only. Files cannot be added or modified within\nthis mounted file system.  See zipfs(n) for complete details.\n.SH \"SEE ALSO\"\ntclsh(1), toplevel(n), zipfs(n), Tk_Main(3), Tk_MainLoop(3), Tk_MainWindow(3)\n.SH KEYWORDS\napplication, argument, interpreter, prompt, script file, shell,\ntoolkit, toplevel\n"
  },
  {
    "path": "doc/wm.n",
    "content": "'\\\"\n'\\\" Copyright (c) 1991-1994 The Regents of the University of California.\n'\\\" Copyright (c) 1994-1996 Sun Microsystems, Inc.\n'\\\"\n'\\\" See the file \"license.terms\" for information on usage and redistribution\n'\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n'\\\"\n.TH wm n 8.5 Tk \"Tk Built-In Commands\"\n.so man.macros\n.BS\n'\\\" Note:  do not modify the .SH NAME line immediately below!\n.SH NAME\nwm \\- Communicate with window manager\n.SH SYNOPSIS\n\\fBwm\\fI option window \\fR?\\fIargs\\fR?\n.BE\n.SH DESCRIPTION\n.PP\nThe \\fBwm\\fR command is used to interact with window managers in\norder to control such things as the title for a window, its geometry,\nor the increments in terms of which it may be resized.  The \\fBwm\\fR\ncommand can take any of a number of different forms, depending on\nthe \\fIoption\\fR argument.  All of the forms expect at least one\nadditional argument, \\fIwindow\\fR, which must be the path name of a\ntop-level window.\n.PP\nThe legal forms for the \\fBwm\\fR command are:\n.\\\" METHOD: aspect\n.TP\n\\fBwm aspect \\fIwindow\\fR ?\\fIminNumer minDenom maxNumer maxDenom\\fR?\n.\nIf \\fIminNumer\\fR, \\fIminDenom\\fR, \\fImaxNumer\\fR, and \\fImaxDenom\\fR\nare all specified, then they will be passed to the window manager\nand the window manager should use them to enforce a range of\nacceptable aspect ratios for \\fIwindow\\fR.  The aspect ratio of\n\\fIwindow\\fR (width/length) will be constrained to lie\nbetween \\fIminNumer\\fR/\\fIminDenom\\fR and \\fImaxNumer\\fR/\\fImaxDenom\\fR.\nIf \\fIminNumer\\fR etc. are all specified as empty strings, then\nany existing aspect ratio restrictions are removed.\nIf \\fIminNumer\\fR etc. are specified, then the command returns an\nempty string.  Otherwise, it returns\na Tcl list containing four elements, which are the current values\nof \\fIminNumer\\fR, \\fIminDenom\\fR, \\fImaxNumer\\fR, and \\fImaxDenom\\fR\n(if no aspect restrictions are in effect, then an empty string is\nreturned).\n.\\\" METHOD: attributes\n.TP\n\\fBwm attributes \\fIwindow\\fR\n.TP\n\\fBwm attributes \\fIwindow\\fR ?\\fBoption\\fR?\n.TP\n\\fBwm attributes \\fIwindow\\fR ?\\fBoption value option value...\\fR?\n.\nThis subcommand returns or sets platform specific attributes associated\nwith a window. The first form returns a list of the platform specific\nflags and their values. The second form returns the value for the\nspecific option. The third form sets one or more of the values. The\nvalues are as follows:\n.RS\n.PP\nAll platforms support the following attributes (though X11 users\nshould see the notes below):\n.\\\" OPTION: -alpha\n.TP\n\\fB\\-alpha\\fR\n.\nSpecifies the alpha transparency level of the toplevel. It accepts a value\nfrom \\fB0.0\\fR (fully transparent) to \\fB1.0\\fR (opaque).  Values outside that\nrange will be constrained.  Where not supported, the \\fB\\-alpha\\fR value\nremains at \\fB1.0\\fR.\n.\\\" OPTION: -fullscreen\n.TP\n\\fB\\-fullscreen\\fR\n.\nPlaces the window in a mode that takes up the entire screen, has no\nborders, and covers the general use area (i.e. Start menu and taskbar on\nWindows, dock and menubar on macOS, general window decorations on X11).\n.\\\" OPTION: -topmost\n.TP\n\\fB\\-topmost\\fR\n.\nSpecifies whether this is a topmost window (displays above all other windows).\n.PP\nOn Windows, the following attributes may be set.\n.\\\" OPTION: -disabled\n.TP\n\\fB\\-disabled\\fR\n.\nSpecifies whether the window is in a disabled state.\n.\\\" OPTION: -toolwindow\n.TP\n\\fB\\-toolwindow\\fR\n.\nSpecifies a toolwindow style window (as defined in the MSDN).\n.\\\" OPTION: -transparentcolor\n.TP\n\\fB\\-transparentcolor\\fR\n.\nSpecifies the transparent color index of the toplevel.  It takes any color\nvalue accepted by \\fBTk_GetColor\\fR.  If the empty string is specified\n(default), no transparent color is used.  This is supported on Windows\n2000/XP+.  Where not supported, the \\fB\\-transparentcolor\\fR value remains\nat \\fB{}\\fR.\n.PP\nOn macOS, the following attributes may be set.\n.\\\" OPTION: -appearance\n.TP\n\\fB\\-appearance\\fR\n.\nSpecifies whether the window is rendered in \"dark mode\".  Allowed\nvalues are \\fBauto\\fR, \\fBaqua\\fR and \\fBdarkaqua\\fR.  If the setting\nis auto then the appearance of the window is controlled by the\nSystem Settings.\n.\\\" OPTION: -class\n.TP\n\\fB\\-class\\fR\n.\nSpecifies whether the underlying Aqua window for a toplevel is an\nobject of the NSWindow class or the NSPanel class.  The two allowed\nvalues for this option are \\fBnswindow\\fR and \\fBnspanel\\fR.  It is\nnot possible to change the class of the underlying Aqua window once\nthat window has been instantiated, and attempting to do that is an\nerror.  However it is allowed to set this option for a pathname that\ndoes not correspond to an existing window.  Doing that causes the\nclass name to be cached for later use.  When a toplevel with that\npathname is eventually created, the cached class name will determine which\nclass is used for the underlying Aqua window.\n.\\\" OPTION: -isdark\n.TP\n\\fB\\-isdark\\fR\n.\nReturns a boolean value which is true if the window is currently in\ndark mode.\n.\\\" OPTION: -modified\n.TP\n\\fB\\-modified\\fR\n.\nSpecifies the modification state of the window (determines whether the\nwindow close widget contains the modification indicator and whether the\nproxy icon is draggable).\n.\\\" OPTION: -notify\n.TP\n\\fB\\-notify\\fR\n.\nSpecifies process notification state (bouncing of the application dock icon).\n.\\\" OPTION: -stylemask\n.TP\n\\fB\\-stylemask\\fR\n.\nSpecifies an integer to be assigned as the styleMask of the underlying\nAqua window.  (See the Apple documentation for styleMask property of\nthe NSWindow class.) The value of this option should be a list of\nbitnames.  Each bit named in the list will be set to 1, and all other\nbits will be set to 0.  The allowed bitnames are: \\fBtitled\\fR,\n\\fBclosable\\fR, \\fBminiaturizable\\fR, \\fBresizable\\fR,\n\\fBfullsizecontentview\\fR, \\fBdocmodal\\fR, \\fButility\\fR,\n\\fBnonactivatingpanel\\fR, and \\fBHUDwindow\\fR.  Note that a side\neffect of setting the fullsizecontentview bit is that the window title\nbar becomes transparent.\n.\\\" OPTION: -tabbingid\n.TP\n\\fB\\-tabbingid\\fR\n.\nControls how tabbed toplevel windows are grouped together.  Two tabs\nin the same group must correspond to toplevels with the same\ntabbingid, which can be an arbitrary UTF8 string.  In the Tk\nimplementation, changing the tabbingid of a toplevel in a tab group\nwill cause it to be moved into a different group, in which all tabs\nhave the new tabbingid or, if the new tabbingid is unique, to become\na normal non-tabbed toplevel.   It is allowed to set the tabbingid before the\ntoplevel is created.  If the pathname provided in the command does not\ncorrespond to a toplevel, the value will be cached and used later when\nthe toplevel is actually created.\n.\\\" OPTION: -tabbingmode\n.TP\n\\fB\\-tabbingmode\\fR\n.\nControls whether a toplevel can be opened as a tab within a tab group.\nThe allowed values are \\fBauto\\fR, \\fBpreferred\\fR or\n\\fBdisallowed\\fR.  A toplevel can be opened as a tab in exactly two\nsituations: if its tabbingmode is \\fBpreferred\\fR; or if its\ntabbingmode is \\fBauto\\fR and the user has selected \"prefer tabs when\nopening documents\" in the Desktop and Dock panel of the System\nSettings application.  It is allowed to set the tabbingmode before the\ntoplevel is created.  If the pathname provided in the command does not\ncorrespond to a toplevel, the value will be cached and used later when\nthe toplevel is actually created.\n.\\\" OPTION: -titlepath\n.TP\n\\fB\\-titlepath\\fR\n.\nSpecifies the path of the file referenced as the window proxy icon\n(which can be dragged and dropped in lieu of the file's finder icon).\n.\\\" OPTION: -transparent\n.TP\n\\fB\\-transparent\\fR\n.\nMakes the window content area transparent and turns off the window shadow. For\nthe transparency to be effective, the toplevel background needs to be set to a\ncolor with some alpha, e.g.\n.QW systemTransparent .\n.PP\nOn X11, the following attributes may be set. These are not supported by all\nwindow managers, and will have no effect under older WMs.\n.\\\" See https://www.freedesktop.org/wiki/Specifications/wm-spec/\n.\\\" OPTION: -type\n.TP\n\\fB\\-type\\fR\n.VS 8.6\nRequests that the window should be interpreted by the window manager as being\nof the specified type(s). This may cause the window to be decorated in a\ndifferent way or otherwise managed differently, though exactly what happens is\nentirely up to the window manager. A list of types may be used, in order of\npreference. The following values are mapped to constants defined in the EWMH\nspecification (using others is possible, but not advised):\n.RS\n.IP \\fBdesktop\\fR\nindicates a desktop feature,\n.IP \\fBdock\\fR\nindicates a dock/panel feature,\n.IP \\fBtoolbar\\fR\nindicates a toolbar window that should be acting on behalf of another window,\nas indicated with \\fBwm transient\\fR,\n.IP \\fBmenu\\fR\nindicates a torn-off menu that should be acting on behalf of another window,\nas indicated with \\fBwm transient\\fR,\n.IP \\fButility\\fR\nindicates a utility window (e.g., palette or toolbox) that should be acting on\nbehalf of another window, as indicated with \\fBwm transient\\fR,\n.IP \\fBsplash\\fR\nindicates a splash screen, displayed during application start up,\n.IP \\fBdialog\\fR\nindicates a general dialog window, that should be acting on behalf of another\nwindow, as indicated with \\fBwm transient\\fR,\n.IP \\fBdropdown_menu\\fR\nindicates a menu summoned from a menu bar, which should usually also be set to\nbe override-redirected (with \\fBwm overrideredirect\\fR),\n.IP \\fBpopup_menu\\fR\nindicates a popup menu, which should usually also be set to be\noverride-redirected (with \\fBwm overrideredirect\\fR),\n.IP \\fBtooltip\\fR\nindicates a tooltip window, which should usually also be set to be\noverride-redirected (with \\fBwm overrideredirect\\fR),\n.IP \\fBnotification\\fR\nindicates a window that provides a background notification of some event,\nwhich should usually also be set to be override-redirected (with \\fBwm\noverrideredirect\\fR),\n.IP \\fBcombo\\fR\nindicates the drop-down list of a combobox widget, which should usually also\nbe set to be override-redirected (with \\fBwm overrideredirect\\fR),\n.IP \\fBdnd\\fR\nindicates a window that represents something being dragged, which should\nusually also be set to be override-redirected (with\n\\fBwm overrideredirect\\fR),\n.IP \\fBnormal\\fR\nindicates a window that has no special interpretation.\n.RE\n.VE 8.6\n.\\\" OPTION: -zoomed\n.TP\n\\fB\\-zoomed\\fR\n.\nRequests that the window should be maximized. This is the same as \\fBwm state\nzoomed\\fR on Windows and macOS.\n.PP\nOn X11, changes to window attributes are performed asynchronously. Querying\nthe value of an attribute returns the current state, which will not be the\nsame as the value most recently set if the window manager has not yet\nprocessed the request or if it does not support the attribute.\n.RE\n.\\\" METHOD: client\n.TP\n\\fBwm client \\fIwindow\\fR ?\\fIname\\fR?\n.\nIf \\fIname\\fR is specified, this command stores \\fIname\\fR (which\nshould be the name of\nthe host on which the application is executing) in \\fIwindow\\fR's\n\\fBWM_CLIENT_MACHINE\\fR property for use by the window manager or\nsession manager.\nThe command returns an empty string in this case.\nIf \\fIname\\fR is not specified, the command returns the last name\nset in a \\fBwm client\\fR command for \\fIwindow\\fR.\nIf \\fIname\\fR is specified as an empty string, the command deletes the\n\\fBWM_CLIENT_MACHINE\\fR property from \\fIwindow\\fR.\n.\\\" METHOD: colormapwindows\n.TP\n\\fBwm colormapwindows \\fIwindow\\fR ?\\fIwindowList\\fR?\n.\nThis command is used to manipulate the \\fBWM_COLORMAP_WINDOWS\\fR\nproperty, which provides information to the window managers about\nwindows that have private colormaps.\n.RS\n.PP\nIf \\fIwindowList\\fR is not specified, the command returns a list\nwhose elements are the names of the windows in the \\fBWM_COLORMAP_WINDOWS\\fR\nproperty.\nIf \\fIwindowList\\fR is specified, it consists of a list of window\npath names;  the command overwrites the \\fBWM_COLORMAP_WINDOWS\\fR\nproperty with the given windows and returns an empty string.\nThe \\fBWM_COLORMAP_WINDOWS\\fR property should normally contain a\nlist of the internal windows within \\fIwindow\\fR whose colormaps differ\nfrom their parents.\n.PP\nThe order of the windows in the property indicates a priority order:\nthe window manager will attempt to install as many colormaps as possible\nfrom the head of this list when \\fIwindow\\fR gets the colormap focus.\nIf \\fIwindow\\fR is not included among the windows in \\fIwindowList\\fR,\nTk implicitly adds it at the end of the \\fBWM_COLORMAP_WINDOWS\\fR\nproperty, so that its colormap is lowest in priority.\nIf \\fBwm colormapwindows\\fR is not invoked, Tk will automatically set\nthe property for each top-level window to all the internal windows\nwhose colormaps differ from their parents, followed by the top-level\nitself;  the order of the internal windows is undefined.\nSee the ICCCM documentation for more information on the\n\\fBWM_COLORMAP_WINDOWS\\fR property.\n.RE\n.\\\" METHOD: command\n.TP\n\\fBwm command \\fIwindow\\fR ?\\fIvalue\\fR?\n.\nIf \\fIvalue\\fR is specified, this command stores \\fIvalue\\fR in \\fIwindow\\fR's\n\\fBWM_COMMAND\\fR property for use by the window manager or\nsession manager and returns an empty string.\n\\fIValue\\fR must have proper list structure;  the elements should\ncontain the words of the command used to invoke the application.\nIf \\fIvalue\\fR is not specified then the command returns the last value\nset in a \\fBwm command\\fR command for \\fIwindow\\fR.\nIf \\fIvalue\\fR is specified as an empty string, the command\ndeletes the \\fBWM_COMMAND\\fR property from \\fIwindow\\fR.\n.\\\" METHOD: deiconify\n.TP\n\\fBwm deiconify \\fIwindow\\fR\n.\nArrange for \\fIwindow\\fR to be displayed in normal (non-iconified) form.\nThis is done by mapping the window.  If the window has never been\nmapped then this command will not map the window, but it will ensure\nthat when the window is first mapped it will be displayed\nin de-iconified form.  On Windows, a deiconified window will also be\nraised and be given the focus (made the active window).\nReturns an empty string.\n.\\\" METHOD: focusmodel\n.TP\n\\fBwm focusmodel \\fIwindow\\fR ?\\fBactive\\fR|\\fBpassive\\fR?\n.\nIf \\fBactive\\fR or \\fBpassive\\fR is supplied as an optional argument\nto the command, then it specifies the focus model for \\fIwindow\\fR.\nIn this case the command returns an empty string.  If no additional\nargument is supplied, then the command returns the current focus\nmodel for \\fIwindow\\fR.\n.RS\n.PP\nAn \\fBactive\\fR focus model means that \\fIwindow\\fR will claim the\ninput focus for itself or its descendants, even at times when\nthe focus is currently in some other application.  \\fBPassive\\fR means that\n\\fIwindow\\fR will never claim the focus for itself:  the window manager\nshould give the focus to \\fIwindow\\fR at appropriate times.  However,\nonce the focus has been given to \\fIwindow\\fR or one of its descendants,\nthe application may re-assign the focus among \\fIwindow\\fR's descendants.\nThe focus model defaults to \\fBpassive\\fR, and Tk's \\fBfocus\\fR command\nassumes a passive model of focusing.\n.RE\n.\\\" METHOD: forget\n.TP\n\\fBwm forget \\fIwindow\\fR\n.\nThe \\fIwindow\\fR will be unmapped from the screen and will no longer\nbe managed by \\fBwm\\fR.  Windows created with the \\fBtoplevel\\fR\ncommand will be treated like \\fBframe\\fR windows once they are no\nlonger managed by \\fBwm\\fR, however, the \\fB\\-menu\\fR configuration will be\nremembered and the menus will return once the widget is managed again.\n.\\\" METHOD: frame\n.TP\n\\fBwm frame \\fIwindow\\fR\n.\nIf \\fIwindow\\fR has been reparented by the window manager into a\ndecorative frame, the command returns the platform specific window\nidentifier for the outermost frame that contains \\fIwindow\\fR (the\nwindow whose parent is the root or virtual root).  If \\fIwindow\\fR\nhas not been reparented by the window manager then the command returns\nthe platform specific window identifier for \\fIwindow\\fR.\n.\\\" METHOD: geometry\n.TP\n\\fBwm geometry \\fIwindow\\fR ?\\fInewGeometry\\fR?\n.\nIf \\fInewGeometry\\fR is specified, then the geometry of \\fIwindow\\fR\nis changed and an empty string is returned.  Otherwise the current\ngeometry for \\fIwindow\\fR is returned (this is the most recent\ngeometry specified either by manual resizing or\nin a \\fBwm geometry\\fR command).  \\fINewGeometry\\fR has\nthe form \\fB=\\fIwidth\\fBx\\fIheight\\fB\\(+-\\fIx\\fB\\(+-\\fIy\\fR, where\nany of \\fB=\\fR, \\fIwidth\\fBx\\fIheight\\fR, or \\fB\\(+-\\fIx\\fB\\(+-\\fIy\\fR\nmay be omitted.  \\fIWidth\\fR and \\fIheight\\fR are positive integers\nspecifying the desired dimensions of \\fIwindow\\fR.  If \\fIwindow\\fR\nis gridded (see \\fBGRIDDED GEOMETRY MANAGEMENT\\fR below) then the dimensions\nare specified in grid units;  otherwise they are specified in pixel\nunits.\n.RS\n.PP\n\\fIX\\fR and \\fIy\\fR specify the desired location of\n\\fIwindow\\fR on the screen, in pixels.\nIf \\fIx\\fR is preceded by \\fB+\\fR, it specifies\nthe number of pixels between the left edge of the screen and the left\nedge of \\fIwindow\\fR's border;  if preceded by \\fB\\-\\fR then\n\\fIx\\fR specifies the number of pixels\nbetween the right edge of the screen and the right edge of \\fIwindow\\fR's\nborder.  If \\fIy\\fR is preceded by \\fB+\\fR then it specifies the\nnumber of pixels between the top of the screen and the top\nof \\fIwindow\\fR's border;  if \\fIy\\fR is preceded by \\fB\\-\\fR then\nit specifies the number of pixels between the bottom of \\fIwindow\\fR's\nborder and the bottom of the screen.\n.PP\nIf \\fInewGeometry\\fR is specified as an empty string then any\nexisting user-specified geometry for \\fIwindow\\fR is cancelled, and\nthe window will revert to the size requested internally by its\nwidgets.\n.PP\nNote that this is related to \\fBwinfo geometry\\fR, but not the same. That can\nonly query the geometry, and always reflects Tk's current understanding of the\nactual size and location of \\fIwindow\\fR, whereas \\fBwm geometry\\fR allows\nboth setting and querying of the \\fIwindow manager\\fR's understanding of the\nsize and location of the window. This can vary significantly, for example to\nreflect the addition of decorative elements to \\fIwindow\\fR such as title\nbars, and window managers are not required to precisely follow the requests\nmade through this command.\n.RE\n.\\\" METHOD: grid\n.TP\n\\fBwm grid \\fIwindow\\fR ?\\fIbaseWidth baseHeight widthInc heightInc\\fR?\n.\nThis command indicates that \\fIwindow\\fR is to be managed as a\ngridded window.\nIt also specifies the relationship between grid units and pixel units.\n\\fIBaseWidth\\fR and \\fIbaseHeight\\fR specify the number of grid\nunits corresponding to the pixel dimensions requested internally\nby \\fIwindow\\fR using \\fBTk_GeometryRequest\\fR.  \\fIWidthInc\\fR\nand \\fIheightInc\\fR specify the number of pixels in each horizontal\nand vertical grid unit.\nThese four values determine a range of acceptable sizes for\n\\fIwindow\\fR, corresponding to grid-based widths and heights\nthat are non-negative integers.\nTk will pass this information to the window manager;  during\nmanual resizing, the window manager will restrict the window's size\nto one of these acceptable sizes.\n.RS\n.PP\nFurthermore, during manual resizing the window manager will display\nthe window's current size in terms of grid units rather than pixels.\nIf \\fIbaseWidth\\fR etc. are all specified as empty strings, then\n\\fIwindow\\fR will no longer be managed as a gridded window.  If\n\\fIbaseWidth\\fR etc. are specified then the return value is an\nempty string.\n.PP\nOtherwise the return value is a Tcl list containing\nfour elements corresponding to the current \\fIbaseWidth\\fR,\n\\fIbaseHeight\\fR, \\fIwidthInc\\fR, and \\fIheightInc\\fR;  if\n\\fIwindow\\fR is not currently gridded, then an empty string\nis returned.\n.PP\nNote that this command should not be needed very often, since the\n\\fBTk_SetGrid\\fR library procedure and the \\fBsetGrid\\fR option\nprovide easier access to the same functionality.\n.RE\n.\\\" METHOD: group\n.TP\n\\fBwm group \\fIwindow\\fR ?\\fIpathName\\fR?\n.\nIf \\fIpathName\\fR is specified, it gives the path name for the leader of\na group of related windows.  The window manager may use this information,\nfor example, to unmap all of the windows in a group when the group's\nleader is iconified.  \\fIPathName\\fR may be specified as an empty string to\nremove \\fIwindow\\fR from any group association.  If \\fIpathName\\fR is\nspecified then the command returns an empty string;  otherwise it\nreturns the path name of \\fIwindow\\fR's current group leader, or an empty\nstring if \\fIwindow\\fR is not part of any group.\n.\\\" METHOD: iconbadge\n.TP\n\\fBwm iconbadge \\fIwindow badge\\fR\n.\nSets a badge for the icon of the \\fIwindow\\fR. The badge can be a positive\ninteger number, for instance the number of new or unread messages, or\nan exclamation point denoting attention needed. If the badge is an empty\nstring, the badge image is removed from the application icon. Managing\nthese changes through bindings, such as <FocusIn>, is the responsibility\nof the developer.\n.RS\n.PP\nOn X11, for this command to work,\nthe variable \\fB::tk::icons::base_icon($window)\\fR must be set to the image\nthat is being used for the window icon of $window. On Windows and X11, the\niconphoto images work best at 32x32 or a similar dimension, as\nthe badge images are provided by Tk and drawn to overlay the icon images\nusing native (Windows) API's or Tk rendering. On macOS, the icon badge is\nrendered by a system API and is not provided by Tk. The icon image itself\nshould be higher-resolution, preferably 512 pixels, to avoid being blurry.\n.PP\nThe icon badge is intended for display in the Dock (macOS), taskbar\n(Windows) or app panel (X11). On macOS, the last badge called will be\ndisplayed in the Dock, regardless of how many different icon badges may be\nassigned to different windows. On Windows, the taskbar display depends on\nwhether the taskbar buttons are combined or not (this is an OS setting\navailable to the user): if combined, the behavior is the same as on macOS,\notherwise each button in the taskbar shows the badge it was assigned.\nBadge display on macOS is configured in the system preferences. App\npanel display behavior on X11 will depend on the window manager and/or\ndesktop environment.\n.RE\n.\\\" METHOD: iconbitmap\n.TP\n\\fBwm iconbitmap \\fIwindow\\fR ?\\fIbitmap\\fR?\n.\nIf \\fIbitmap\\fR is specified, then it names a bitmap in the standard\nforms accepted by Tk (see the \\fBTk_GetBitmap\\fR manual entry for details).\nThis bitmap is passed to the window manager to be displayed in\n\\fIwindow\\fR's icon, and the command returns an empty string.  If\nan empty string is specified for \\fIbitmap\\fR, then any current icon\nbitmap is cancelled for \\fIwindow\\fR.\nIf \\fIbitmap\\fR is specified then the command returns an empty string.\nOtherwise it returns the name of\nthe current icon bitmap associated with \\fIwindow\\fR, or an empty\nstring if \\fIwindow\\fR has no icon bitmap.  On the Windows operating\nsystem, an additional flag is supported:\n.RS\n.TP\n\\fBwm iconbitmap \\fIwindow\\fR ?\\fB\\-default\\fR? ?\\fIimage\\fR?\n.\nIf the \\fB\\-default\\fR\nflag is given, the icon is applied to all toplevel windows (existing\nand future) to which no other specific icon has yet been applied.\nIn addition to bitmap image types, a full path specification to\nany file which contains a valid\nWindows icon is also accepted (usually .ico or .icr files), or any\nfile for which the shell has assigned an icon.  Tcl will\nfirst test if the file contains an icon, then if it has an assigned\nicon, and finally, if that fails, test for\na bitmap.\n.RE\n.\\\" METHOD: iconify\n.TP\n\\fBwm iconify \\fIwindow\\fR\n.\nArrange for \\fIwindow\\fR to be iconified.  It \\fIwindow\\fR has not\nyet been mapped for the first time, this command will arrange for\nit to appear in the iconified state when it is eventually mapped.\n.\\\" METHOD: iconmask\n.TP\n\\fBwm iconmask \\fIwindow\\fR ?\\fIbitmap\\fR?\n.\nIf \\fIbitmap\\fR is specified, then it names a bitmap in the standard\nforms accepted by Tk (see the \\fBTk_GetBitmap\\fR manual entry for details).\nThis bitmap is passed to the window manager to be used as a mask\nin conjunction with the \\fBiconbitmap\\fR option:  where the mask\nhas zeroes no icon will be displayed;  where it has ones, the bits\nfrom the icon bitmap will be displayed.  If\nan empty string is specified for \\fIbitmap\\fR then any current icon\nmask is cancelled for \\fIwindow\\fR (this is equivalent to specifying\na bitmap of all ones).  If \\fIbitmap\\fR is specified\nthen the command returns an empty string.  Otherwise it\nreturns the name of the current icon mask associated with\n\\fIwindow\\fR, or an empty string if no mask is in effect.\n.\\\" METHOD: iconname\n.TP\n\\fBwm iconname \\fIwindow\\fR ?\\fInewName\\fR?\n.\nIf \\fInewName\\fR is specified, then it is passed to the window\nmanager;  the window manager should display \\fInewName\\fR inside\nthe icon associated with \\fIwindow\\fR.  In this case an empty\nstring is returned as result.  If \\fInewName\\fR is not specified\nthen the command returns the current icon name for \\fIwindow\\fR,\nor an empty string if no icon name has been specified (in this\ncase the window manager will normally display the window's title,\nas specified with the \\fBwm title\\fR command).\n.\\\" METHOD: iconphoto\n.TP\n\\fBwm iconphoto \\fIwindow\\fR ?\\fB\\-default\\fR? \\fIimage1\\fR ?\\fIimage2 ...\\fR?\n.\nSets the titlebar icon for \\fIwindow\\fR based on the named photo images.\nIf \\fB\\-default\\fR is specified, this is applied to all future created\ntoplevels as well.  The data in the images is taken as a snapshot at the\ntime of invocation.  If the images are later changed, this is not\nreflected to the titlebar icons.  Multiple images are accepted to allow\ndifferent images sizes (e.g., 16x16 and 32x32) to be provided. The window\nmanager may scale provided icons to an appropriate size.\n.RS\n.PP\nOn Windows, the images are packed into a Windows icon structure.\nThis will override an ico specified to \\fBwm iconbitmap\\fR, and\nvice versa. This command sets the taskbar icon for the window.\n.PP\nOn X, the images are arranged into the _NET_WM_ICON X property, which\nmost modern window managers support.  A \\fBwm iconbitmap\\fR may exist\nsimultaneously.  It is recommended to use not more than 2 icons, placing\nthe larger icon first. This command also sets the panel icon for the\napplication if the window manager or desktop environment supports it.\n.PP\nOn Macintosh, the first image called is loaded into an OS-native icon\nformat, and becomes the application icon in dialogs, the Dock, and\nother contexts. At the\nscript level the command will accept only the first image passed in the\nparameters as support for multiple sizes/resolutions on macOS is outside Tk's\nscope. Developers should use the largest icon they can support\n(preferably 512 pixels) to ensure smooth rendering on the Mac.\n.RE\n.\\\" METHOD: iconposition\n.TP\n\\fBwm iconposition \\fIwindow\\fR ?\\fIx y\\fR?\n.\nIf \\fIx\\fR and \\fIy\\fR are specified, they are passed to the window\nmanager as a hint about where to position the icon for \\fIwindow\\fR.\nIn this case an empty string is returned.  If \\fIx\\fR and \\fIy\\fR are\nspecified as empty strings then any existing icon position hint is cancelled.\nIf neither \\fIx\\fR nor \\fIy\\fR is specified, then the command returns\na Tcl list containing two values, which are the current icon position\nhints (if no hints are in effect then an empty string is returned).\n.\\\" METHOD: iconwindow\n.TP\n\\fBwm iconwindow \\fIwindow\\fR ?\\fIpathName\\fR?\n.\nIf \\fIpathName\\fR is specified, it is the path name for a window to\nuse as icon for \\fIwindow\\fR: when \\fIwindow\\fR is iconified then\n\\fIpathName\\fR will be mapped to serve as icon, and when \\fIwindow\\fR\nis de-iconified then \\fIpathName\\fR will be unmapped again.  If\n\\fIpathName\\fR is specified as an empty string then any existing\nicon window association for \\fIwindow\\fR will be cancelled.  If\nthe \\fIpathName\\fR argument is specified then an empty string is\nreturned.  Otherwise the command returns the path name of the\ncurrent icon window for \\fIwindow\\fR, or an empty string if there\nis no icon window currently specified for \\fIwindow\\fR.\nButton press events are disabled for \\fIwindow\\fR as long as it is\nan icon window;  this is needed in order to allow window managers to\n.QW own\nthose events.\nNote that not all window managers support the notion of an icon window, and\nthe concept is entirely meaningless on non-X11 platforms.\n.\\\" METHOD: manage\n.TP\n\\fBwm manage \\fIwidget\\fR\n.\nThe \\fIwidget\\fR specified will become a stand alone top-level window.  The\nwindow will be decorated with the window managers title bar, etc. Only\n\\fIframe\\fR, \\fIlabelframe\\fR and \\fItoplevel\\fR widgets can be used\nwith this command. Attempting to pass any other widget type will raise\nan error. Attempting to manage a \\fItoplevel\\fR widget is benign and\nachieves nothing. See also \\fBGEOMETRY MANAGEMENT\\fR.\n.\\\" METHOD: maxsize\n.TP\n\\fBwm maxsize \\fIwindow\\fR ?\\fIwidth height\\fR?\n.\nIf \\fIwidth\\fR and \\fIheight\\fR are specified, they give\nthe maximum permissible dimensions for \\fIwindow\\fR.\nFor gridded windows the dimensions are specified in\ngrid units;  otherwise they are specified in pixel units.\nThe window manager will restrict the window's dimensions to be\nless than or equal to \\fIwidth\\fR and \\fIheight\\fR.\nIf \\fIwidth\\fR and \\fIheight\\fR are\nspecified, then the command returns an empty string.  Otherwise\nit returns a Tcl list with two elements, which are the\nmaximum width and height currently in effect.\nThe maximum size defaults to the size of the screen.\nSee the sections on geometry management below for more information.\n.\\\" METHOD: minsize\n.TP\n\\fBwm minsize \\fIwindow\\fR ?\\fIwidth height\\fR?\n.\nIf \\fIwidth\\fR and \\fIheight\\fR are specified, they give the\nminimum permissible dimensions for \\fIwindow\\fR.\nFor gridded windows the dimensions are specified in\ngrid units;  otherwise they are specified in pixel units.\nThe window manager will restrict the window's dimensions to be\ngreater than or equal to \\fIwidth\\fR and \\fIheight\\fR.\nIf \\fIwidth\\fR and \\fIheight\\fR are\nspecified, then the command returns an empty string.  Otherwise\nit returns a Tcl list with two elements, which are the\nminimum width and height currently in effect.\nThe minimum size defaults to one pixel in each dimension.\nSee the sections on geometry management below for more information.\n.\\\" METHOD: overrideredirect\n.TP\n\\fBwm overrideredirect \\fIwindow\\fR ?\\fIboolean\\fR?\n.\nIf \\fIboolean\\fR is specified, it must have a proper boolean form and\nthe override-redirect flag for \\fIwindow\\fR is set to that value.\nIf \\fIboolean\\fR is not specified then \\fB1\\fR or \\fB0\\fR is\nreturned to indicate whether or not the override-redirect flag\nis currently set for \\fIwindow\\fR.\nSetting the override-redirect flag for a window causes\nit to be ignored by the window manager;  among other things, this means\nthat the window will not be reparented from the root window into a\ndecorative frame and the user will not be able to manipulate the\nwindow using the normal window manager mechanisms.\n.RS\n.PP\nNote that the override-redirect flag is only guaranteed to be taken notice of\nwhen the window is first mapped or when mapped after the state is changed from\nwithdrawn to normal. Some, but not all, platforms will take notice at\nadditional times.\n.RE\n.\\\" METHOD: positionfrom\n.TP\n\\fBwm positionfrom \\fIwindow\\fR ?\\fIwho\\fR?\n.\nIf \\fIwho\\fR is specified, it must be either \\fBprogram\\fR or\n\\fBuser\\fR, or an abbreviation of one of these two.  It indicates\nwhether \\fIwindow\\fR's current position was requested by the\nprogram or by the user.  Many window managers ignore program-requested\ninitial positions and ask the user to manually position the window;  if\n\\fBuser\\fR is specified then the window manager should position the\nwindow at the given place without asking the user for assistance.\nIf \\fIwho\\fR is specified as an empty string, then the current position\nsource is cancelled.\nIf \\fIwho\\fR is specified, then the command returns an empty string.\nOtherwise it returns \\fBuser\\fR or \\fBprogram\\fR to indicate the\nsource of the window's current position, or an empty string if\nno source has been specified yet.  Most window managers interpret\n.QW \"no source\"\nas equivalent to \\fBprogram\\fR.\nTk will automatically set the position source to \\fBuser\\fR\nwhen a \\fBwm geometry\\fR command is invoked, unless the source has\nbeen set explicitly to \\fBprogram\\fR.\n.\\\" METHOD: protocol\n.TP\n\\fBwm protocol \\fIwindow\\fR ?\\fIname\\fR? ?\\fIcommand\\fR?\n.\nThis command is used to manage window manager protocols. The \\fIname\\fR\nargument in the \\fBwm protocol\\fR command is the name of an atom corresponding\nto a window manager protocol.  Examples include \\fBWM_DELETE_WINDOW\\fR or\n\\fBWM_SAVE_YOURSELF\\fR or \\fBWM_TAKE_FOCUS\\fR.\n.RS\n.PP\nA \\fIwindow manager protocol\\fR is a class of messages sent from a window\nmanager to a Tk application outside of the normal event processing system. The\nmain example is the \\fBWM_DELETE_WINDOW\\fR protocol; these messages are sent\nwhen the user clicks the close widget in the title bar of a window.  Handlers\nfor window manager protocols are installed with the \\fBwm protocol\\fR\ncommand. As a rule, if no handler has been installed for a protocol by the\n\\fBwm protocol\\fR command then all messages of that protocol are ignored. The\n\\fBWM_DELETE_WINDOW\\fR protocol is an exception to this rule. At start-up Tk\ninstalls a handler for this protocol, which responds by destroying the\nwindow. The \\fBwm protocol\\fR command can be used to replace this default\nhandler by one which responds differently.\n.RE\n.RS\n.PP\nThe list of available window manager protocols depends on the window manager,\nbut all window managers supported by Tk provide \\fBWM_DELETE_WINDOW\\fR. On the\nWindows platform, a \\fBWM_SAVE_YOURSELF\\fR message is sent on user logout\nor system restart.\n.RE\n.RS\n.PP\nIf both \\fIname\\fR and \\fIcommand\\fR are specified, then \\fIcommand\\fR becomes\nthe handler for the protocol specified by \\fIname\\fR. The atom for \\fIname\\fR\nwill be added to \\fIwindow\\fR's \\fBWM_PROTOCOLS\\fR property to tell the window\nmanager that the application has a handler for the protocol specified by\n\\fIname\\fR, and \\fIcommand\\fR will be invoked in the future whenever the\nwindow manager sends a message of that protocol to the Tk application.  In\nthis case the \\fBwm protocol\\fR command returns an empty string.  If\n\\fIname\\fR is specified but \\fIcommand\\fR is not, then the current handler for\n\\fIname\\fR is returned, or an empty string if there is no handler defined for\n\\fIname\\fR (as a special case, the default handler for \\fBWM_DELETE_WINDOW\\fR\nis not returned).  If \\fIcommand\\fR is specified as an empty string then the\natom for \\fIname\\fR is removed from the \\fBWM_PROTOCOLS\\fR property of\n\\fIwindow\\fR and the handler is destroyed; an empty string is returned.\nLastly, if neither \\fIname\\fR nor \\fIcommand\\fR is specified, the\n\\fBwm protocol\\fR command returns a list of all of the protocols for which\nhandlers are currently defined for \\fIwindow\\fR.\n.RE\n.\\\" METHOD: resizable\n.TP\n\\fBwm resizable \\fIwindow\\fR ?\\fIwidth height\\fR?\n.\nThis command controls whether or not the user may interactively\nresize a top-level window.  If \\fIwidth\\fR and \\fIheight\\fR are\nspecified, they are boolean values that determine whether the\nwidth and height of \\fIwindow\\fR may be modified by the user.\nIn this case the command returns an empty string.\nIf \\fIwidth\\fR and \\fIheight\\fR are omitted then the command\nreturns a list with two 0/1 elements that indicate whether the\nwidth and height of \\fIwindow\\fR are currently resizable.\nBy default, windows are resizable in both dimensions.\nIf resizing is disabled, then the window's size will be the size\nfrom the most recent interactive resize or \\fBwm geometry\\fR\ncommand.  If there has been no such operation then\nthe window's natural size will be used.\n.\\\" METHOD: sizefrom\n.TP\n\\fBwm sizefrom \\fIwindow\\fR ?\\fIwho\\fR?\n.\nIf \\fIwho\\fR is specified, it must be either \\fBprogram\\fR or\n\\fBuser\\fR, or an abbreviation of one of these two.  It indicates\nwhether \\fIwindow\\fR's current size was requested by the\nprogram or by the user.  Some window managers ignore program-requested\nsizes and ask the user to manually size the window;  if\n\\fBuser\\fR is specified then the window manager should give the\nwindow its specified size without asking the user for assistance.\nIf \\fIwho\\fR is specified as an empty string, then the current size\nsource is cancelled.\nIf \\fIwho\\fR is specified, then the command returns an empty string.\nOtherwise it returns \\fBuser\\fR or \\fBwindow\\fR to indicate the\nsource of the window's current size, or an empty string if\nno source has been specified yet.  Most window managers interpret\n.QW \"no source\"\nas equivalent to \\fBprogram\\fR.\n.\\\" METHOD: stackorder\n.TP\n\\fBwm stackorder \\fIwindow\\fR ?\\fBisabove\\fR|\\fBisbelow \\fIwindow\\fR?\n.\nThe \\fBstackorder\\fR command returns a list of toplevel windows\nin stacking order, from lowest to highest. When a single toplevel\nwindow is passed, the returned list recursively includes all of the\nwindow's children that are toplevels. Only those toplevels\nthat are currently mapped to the screen are returned.\nThe \\fBstackorder\\fR command can also be used to determine if one\ntoplevel is positioned above or below a second toplevel.\nWhen two window arguments separated by either \\fBisabove\\fR or\n\\fBisbelow\\fR are passed, a boolean result indicates whether\nor not the first window is currently above or below the second\nwindow in the stacking order.\n.\\\" METHOD: state\n.TP\n\\fBwm state \\fIwindow\\fR ?newstate?\n.\nIf \\fInewstate\\fR is specified, the window will be set to the new state,\notherwise it returns the current state of \\fIwindow\\fR: either\n\\fBnormal\\fR, \\fBiconic\\fR, \\fBwithdrawn\\fR, \\fBicon\\fR, or (Windows and macOS\nonly) \\fBzoomed\\fR.\nThe difference between \\fBiconic\\fR and \\fBicon\\fR is that\n\\fBiconic\\fR refers to a window that has been iconified (e.g., with the\n\\fBwm iconify\\fR command) while \\fBicon\\fR refers to a window whose only\npurpose is to serve as the icon for some other window (via the \\fBwm\niconwindow\\fR command).  The \\fBicon\\fR state cannot be set.\n.\\\" METHOD: title\n.TP\n\\fBwm title \\fIwindow\\fR ?\\fIstring\\fR?\n.\nIf \\fIstring\\fR is specified, then it will be passed to the window\nmanager for use as the title for \\fIwindow\\fR (the window manager\nshould display this string in \\fIwindow\\fR's title bar).  In this\ncase the command returns an empty string.  If \\fIstring\\fR is not\nspecified then the command returns the current title for the\n\\fIwindow\\fR.  The title for a window defaults to its name.\n.\\\" METHOD: transient\n.TP\n\\fBwm transient \\fIwindow\\fR ?\\fIcontainer\\fR?\n.\nIf \\fIcontainer\\fR is specified, then the window manager is informed that\n\\fIwindow\\fR is a transient window (e.g. pull-down menu) working on\nbehalf of \\fIcontainer\\fR (where \\fIcontainer\\fR is the path name for a\ntop-level window).  If \\fIcontainer\\fR is specified as an empty string\nthen \\fIwindow\\fR is marked as not being a transient window any more.\nOtherwise the command returns the path name of \\fIwindow\\fR's current\ncontainer, or an empty string if \\fIwindow\\fR is not currently a\ntransient window.  A transient window will mirror state changes in the\ncontainer and inherit the state of the container when initially mapped. The\ndirected graph with an edge from each transient to its container must be\nacyclic.  In particular, it is an error to attempt to make a window a\ntransient of itself.  The window manager may also decorate a transient\nwindow differently, removing some features normally present (e.g.,\nminimize and maximize buttons) though this is entirely at the\ndiscretion of the window manager.\n.\\\" METHOD: widthdraw\n.TP\n\\fBwm withdraw \\fIwindow\\fR\n.\nArranges for \\fIwindow\\fR to be withdrawn from the screen.  This\ncauses the window to be unmapped and forgotten about by the window\nmanager.  If the window\nhas never been mapped, then this command\ncauses the window to be mapped in the withdrawn state.  Not all\nwindow managers appear to know how to handle windows that are\nmapped in the withdrawn state.\nNote that it sometimes seems to be necessary to withdraw a\nwindow and then re-map it (e.g. with \\fBwm deiconify\\fR) to get some\nwindow managers to pay attention to changes in window attributes\nsuch as group.\n.SH \"GEOMETRY MANAGEMENT\"\n.PP\nBy default a top-level window appears on the screen in its\n\\fInatural size\\fR, which is the one determined internally by its\nwidgets and geometry managers.\nIf the natural size of a top-level window changes, then the window's size\nchanges to match.\nA top-level window can be given a size other than its natural size in two ways.\nFirst, the user can resize the window manually using the facilities\nof the window manager, such as resize handles.\nSecond, the application can request a particular size for a\ntop-level window using the \\fBwm geometry\\fR command.\nThese two cases are handled identically by Tk;  in either case,\nthe requested size overrides the natural size.\nYou can return the window to its natural by invoking \\fBwm geometry\\fR\nwith an empty \\fIgeometry\\fR string.\n.PP\nNormally a top-level window can have any size from one pixel in each\ndimension up to the size of its screen.\nHowever, you can use the \\fBwm minsize\\fR and \\fBwm maxsize\\fR commands\nto limit the range of allowable sizes.\nThe range set by \\fBwm minsize\\fR and \\fBwm maxsize\\fR applies to\nall forms of resizing, including the window's natural size as\nwell as manual resizes and the \\fBwm geometry\\fR command.  You\ncan use any value accepted by \\fBTk_GetPixels\\fR.\nYou can also use the command \\fBwm resizable\\fR to completely\ndisable interactive resizing in one or both dimensions.\n.PP\nThe \\fBwm manage\\fR and \\fBwm forget\\fR commands may be used to\nperform undocking and docking of windows.  After a widget is managed\nby \\fBwm manage\\fR command, all other \\fBwm\\fR subcommands may be used\nwith the widget.  Only widgets created using the toplevel command may\nhave an attached menu via the \\fB\\-menu\\fR configure option.  A toplevel\nwidget may be used as a frame and managed with any of the other\ngeometry managers after using the \\fBwm forget\\fR command.  Any menu\nassociated with a toplevel widget will be hidden when managed by\nanother geometry managers.  The menus will reappear once the window is\nmanaged by \\fBwm\\fR.  All custom bindtags for widgets in a subtree\nthat have their top-level widget changed via a \\fBwm manage\\fR or\n\\fBwm forget\\fR command, must be redone to adjust any top-level widget\npath in the bindtags. Bindtags that have not been customized do not\nhave to be redone.\n.SH \"GRIDDED GEOMETRY MANAGEMENT\"\n.PP\nGridded geometry management occurs when one of the widgets of an\napplication supports a range of useful sizes.\nThis occurs, for example, in a text editor where the scrollbars,\nmenus, and other adornments are fixed in size but the edit widget\ncan support any number of lines of text or characters per line.\nIn this case, it is usually desirable to let the user specify the\nnumber of lines or characters-per-line, either with the\n\\fBwm geometry\\fR command or by interactively resizing the window.\nIn the case of text, and in other interesting cases also, only\ndiscrete sizes of the window make sense, such as integral numbers\nof lines and characters-per-line;  arbitrary pixel sizes are not useful.\n.PP\nGridded geometry management provides support for this kind of\napplication.\nTk (and the window manager) assume that there is a grid of some\nsort within the application and that the application should be\nresized in terms of \\fIgrid units\\fR rather than pixels.\nGridded geometry management is typically invoked by turning on\nthe \\fBsetGrid\\fR option for a widget;  it can also be invoked\nwith the \\fBwm grid\\fR command or by calling \\fBTk_SetGrid\\fR.\nIn each of these approaches the particular widget (or sometimes\ncode in the application as a whole) specifies the relationship between\nintegral grid sizes for the window and pixel sizes.\nTo return to non-gridded geometry management, invoke\n\\fBwm grid\\fR with empty argument strings.\n.PP\nWhen gridded geometry management is enabled then all the dimensions specified\nin \\fBwm minsize\\fR, \\fBwm maxsize\\fR, and \\fBwm geometry\\fR commands\nare treated as grid units rather than pixel units.\nInteractive resizing is also carried out in even numbers of grid units\nrather than pixels.\n.SH BUGS\n.PP\nMost existing window managers appear to have bugs that affect the\noperation of the \\fBwm\\fR command.  For example, some changes will not\ntake effect if the window is already active:  the window will have\nto be withdrawn and de-iconified in order to make the change happen.\n.SH EXAMPLES\n.PP\nA fixed-size window that says that it is fixed-size too:\n.CS\ntoplevel .fixed\n\\fBwm title\\fR     .fixed \"Fixed-size Window\"\n\\fBwm resizable\\fR .fixed 0 0\n.CE\n.PP\nA simple dialog-like window, centred on the screen:\n.CS\n# Create and arrange the dialog contents.\ntoplevel .msg\nlabel  .msg.l  -text \"This is a very simple dialog demo.\"\nbutton .msg.ok -text OK -default active -command {destroy .msg}\npack .msg.ok -side bottom -fill x\npack .msg.l  -expand 1    -fill both\n\n# Now set the widget up as a centred dialog.\n\n# But first, we need the geometry managers to finish setting\n# up the interior of the dialog, for which we need to run the\n# event loop with the widget hidden completely...\n\\fBwm withdraw\\fR .msg\nupdate\nset x [expr {([winfo screenwidth .] - [winfo width .msg]) / 2}]\nset y [expr {([winfo screenheight .] - [winfo height .msg]) / 2}]\n\\fBwm geometry\\fR  .msg +$x+$y\n\\fBwm transient\\fR .msg .\n\\fBwm title\\fR     .msg \"Dialog demo\"\n\\fBwm deiconify\\fR .msg\n.CE\n.SH \"SEE ALSO\"\ntoplevel(n), winfo(n)\n.SH KEYWORDS\naspect ratio, deiconify, focus model, geometry, grid, group, icon, iconify,\nincrements, position, size, title, top-level window, units, window manager\n'\\\" Local Variables:\n'\\\" mode: nroff\n'\\\" End:\n"
  },
  {
    "path": "generic/README",
    "content": "This directory contains Tk source files that work on all the platforms\nwhere Tk runs (e.g. UNIX, PCs, and MacOSX).  Platform-specific\nsources are in the directories ../unix, ../win, and ../macosx.\n"
  },
  {
    "path": "generic/default.h",
    "content": "/*\n * default.h --\n *\n *\tThis file defines the defaults for all options for all of\n *\tthe Tk widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _DEFAULT\n#define _DEFAULT\n\n#ifdef _WIN32\n#   include \"tkWinDefault.h\"\n#else\n#   if defined(MAC_OSX_TK)\n#\tinclude \"tkMacOSXDefault.h\"\n#   else\n#\tinclude \"tkUnixDefault.h\"\n#   endif\n#endif\n\n#endif /* _DEFAULT */\n"
  },
  {
    "path": "generic/ks_names.h",
    "content": "/*\n * This file should be maintained in sync with xlib/X11/keysymdefs.h\n *\n * Note that this should be done manually only, because in some cases\n * keysymdefs.h defines the same integer for multiple keysyms, e.g.:\n *\n *    #define XK_Greek_LAMDA                         0x7CB\n *    #define XK_Greek_LAMBDA                        0x7CB\n *\n *    #define XK_Cyrillic_DZHE                       0x6BF\n *    #define XK_Serbian_DZE                         0x6BF  (deprecated)\n *\n */\n{ \"BackSpace\", 0xFF08 },\n{ \"Tab\", 0xFF09 },\n{ \"Linefeed\", 0xFF0A },\n{ \"Clear\", 0xFF0B },\n{ \"Return\", 0xFF0D },\n{ \"Pause\", 0xFF13 },\n{ \"Scroll_Lock\", 0xFF14 },\n{ \"Sys_Req\", 0xFF15 },\n{ \"Escape\", 0xFF1B },\n{ \"Multi_key\", 0xFF20 },\n{ \"Kanji\", 0xFF21 },\n{ \"Muhenkan\", 0xFF22 },\n{ \"Henkan\", 0xFF23 },\n{ \"Henkan_Mode\", 0xFF23 },\n{ \"Romaji\", 0xFF24 },\n{ \"Hiragana\", 0xFF25 },\n{ \"Katakana\", 0xFF26 },\n{ \"Hiragana_Katakana\", 0xFF27 },\n{ \"Zenkaku\", 0xFF28 },\n{ \"Hankaku\", 0xFF29 },\n{ \"Zenkaku_Hankaku\", 0xFF2A },\n{ \"Touroku\", 0xFF2B },\n{ \"Massyo\", 0xFF2C },\n{ \"Kana_Lock\", 0xFF2D },\n{ \"Kana_Shift\", 0xFF2E },\n{ \"Eisu_Shift\", 0xFF2F },\n{ \"Eisu_toggle\", 0xFF30 },\n{ \"Hangul\", 0xFF31 },\n{ \"Hangul_Start\", 0xFF32 },\n{ \"Hangul_End\", 0xFF33 },\n{ \"Hangul_Hanja\", 0xFF34 },\n{ \"Hangul_Jamo\", 0xFF35 },\n{ \"Hangul_Romaja\", 0xFF36 },\n{ \"Codeinput\", 0xFF37 },\n{ \"Hangul_Jeonja\", 0xFF38 },\n{ \"Hangul_Banja\", 0xFF39 },\n{ \"Hangul_PreHanja\", 0xFF3A },\n{ \"Hangul_PostHanja\", 0xFF3B },\n{ \"SingleCandidate\", 0xFF3C },\n{ \"MultipleCandidate\", 0xFF3D },\n{ \"PreviousCandidate\", 0xFF3E },\n{ \"Hangul_Special\", 0xFF3F },\n{ \"Home\", 0xFF50 },\n{ \"Left\", 0xFF51 },\n{ \"Up\", 0xFF52 },\n{ \"Right\", 0xFF53 },\n{ \"Down\", 0xFF54 },\n{ \"Prior\", 0xFF55 },\n#ifndef TK_NO_DEPRECATED\n{ \"Page_Up\", 0xFF55 },\n#endif\n{ \"Next\", 0xFF56 },\n#ifndef TK_NO_DEPRECATED\n{ \"Page_Down\", 0xFF56 },\n#endif\n{ \"End\", 0xFF57 },\n{ \"Begin\", 0xFF58 },\n{ \"Select\", 0xFF60 },\n{ \"Print\", 0xFF61 },\n{ \"Execute\", 0xFF62 },\n{ \"Insert\", 0xFF63 },\n{ \"Undo\", 0xFF65 },\n{ \"Redo\", 0xFF66 },\n{ \"Menu\", 0xFF67 },\n#ifndef TK_NO_DEPRECATED\n{ \"App\", 0xFF67 },\n#endif\n{ \"Find\", 0xFF68 },\n{ \"Cancel\", 0xFF69 },\n{ \"Help\", 0xFF6A },\n{ \"Break\", 0xFF6B },\n{ \"Mode_switch\", 0xFF7E },\n{ \"script_switch\", 0xFF7E },\n{ \"kana_switch\", 0xFF7E },\n{ \"Arabic_switch\", 0xFF7E },\n{ \"Greek_switch\", 0xFF7E },\n{ \"Hebrew_switch\", 0xFF7E },\n{ \"Num_Lock\", 0xFF7F },\n{ \"KP_Space\", 0xFF80 },\n{ \"KP_Tab\", 0xFF89 },\n{ \"KP_Enter\", 0xFF8D },\n{ \"KP_F1\", 0xFF91 },\n{ \"KP_F2\", 0xFF92 },\n{ \"KP_F3\", 0xFF93 },\n{ \"KP_F4\", 0xFF94 },\n{ \"KP_Home\", 0xFF95 },\n{ \"KP_Left\", 0xFF96 },\n{ \"KP_Up\", 0xFF97 },\n{ \"KP_Right\", 0xFF98 },\n{ \"KP_Down\", 0xFF99 },\n{ \"KP_Prior\", 0xFF9A },\n{ \"KP_Page_Up\", 0xFF9A },\n{ \"KP_Next\", 0xFF9B },\n{ \"KP_Page_Down\", 0xFF9B },\n{ \"KP_End\", 0xFF9C },\n{ \"KP_Begin\", 0xFF9D },\n{ \"KP_Insert\", 0xFF9E },\n{ \"KP_Delete\", 0xFF9F },\n{ \"KP_Multiply\", 0xFFAA },\n{ \"KP_Add\", 0xFFAB },\n{ \"KP_Separator\", 0xFFAC },\n{ \"KP_Subtract\", 0xFFAD },\n{ \"KP_Decimal\", 0xFFAE },\n{ \"KP_Divide\", 0xFFAF },\n{ \"KP_0\", 0xFFB0 },\n{ \"KP_1\", 0xFFB1 },\n{ \"KP_2\", 0xFFB2 },\n{ \"KP_3\", 0xFFB3 },\n{ \"KP_4\", 0xFFB4 },\n{ \"KP_5\", 0xFFB5 },\n{ \"KP_6\", 0xFFB6 },\n{ \"KP_7\", 0xFFB7 },\n{ \"KP_8\", 0xFFB8 },\n{ \"KP_9\", 0xFFB9 },\n{ \"KP_Equal\", 0xFFBD },\n{ \"F1\", 0xFFBE },\n{ \"F2\", 0xFFBF },\n{ \"F3\", 0xFFC0 },\n{ \"F4\", 0xFFC1 },\n{ \"F5\", 0xFFC2 },\n{ \"F6\", 0xFFC3 },\n{ \"F7\", 0xFFC4 },\n{ \"F8\", 0xFFC5 },\n{ \"F9\", 0xFFC6 },\n{ \"F10\", 0xFFC7 },\n{ \"F11\", 0xFFC8 },\n#ifndef TK_NO_DEPRECATED\n{ \"L1\", 0xFFC8 },\n#endif\n{ \"F12\", 0xFFC9 },\n#ifndef TK_NO_DEPRECATED\n{ \"L2\", 0xFFC9 },\n#endif\n{ \"F13\", 0xFFCA },\n#ifndef TK_NO_DEPRECATED\n{ \"L3\", 0xFFCA },\n#endif\n{ \"F14\", 0xFFCB },\n#ifndef TK_NO_DEPRECATED\n{ \"L4\", 0xFFCB },\n#endif\n{ \"F15\", 0xFFCC },\n#ifndef TK_NO_DEPRECATED\n{ \"L5\", 0xFFCC },\n#endif\n{ \"F16\", 0xFFCD },\n#ifndef TK_NO_DEPRECATED\n{ \"L6\", 0xFFCD },\n#endif\n{ \"F17\", 0xFFCE },\n#ifndef TK_NO_DEPRECATED\n{ \"L7\", 0xFFCE },\n#endif\n{ \"F18\", 0xFFCF },\n#ifndef TK_NO_DEPRECATED\n{ \"L8\", 0xFFCF },\n#endif\n{ \"F19\", 0xFFD0 },\n#ifndef TK_NO_DEPRECATED\n{ \"L9\", 0xFFD0 },\n#endif\n{ \"F20\", 0xFFD1 },\n#ifndef TK_NO_DEPRECATED\n{ \"L10\", 0xFFD1 },\n#endif\n{ \"F21\", 0xFFD2 },\n#ifndef TK_NO_DEPRECATED\n{ \"R1\", 0xFFD2 },\n#endif\n{ \"F22\", 0xFFD3 },\n#ifndef TK_NO_DEPRECATED\n{ \"R2\", 0xFFD3 },\n#endif\n{ \"F23\", 0xFFD4 },\n#ifndef TK_NO_DEPRECATED\n{ \"R3\", 0xFFD4 },\n#endif\n{ \"F24\", 0xFFD5 },\n#ifndef TK_NO_DEPRECATED\n{ \"R4\", 0xFFD5 },\n#endif\n{ \"F25\", 0xFFD6 },\n#ifndef TK_NO_DEPRECATED\n{ \"R5\", 0xFFD6 },\n#endif\n{ \"F26\", 0xFFD7 },\n#ifndef TK_NO_DEPRECATED\n{ \"R6\", 0xFFD7 },\n#endif\n{ \"F27\", 0xFFD8 },\n#ifndef TK_NO_DEPRECATED\n{ \"R7\", 0xFFD8 },\n#endif\n{ \"F28\", 0xFFD9 },\n#ifndef TK_NO_DEPRECATED\n{ \"R8\", 0xFFD9 },\n#endif\n{ \"F29\", 0xFFDA },\n#ifndef TK_NO_DEPRECATED\n{ \"R9\", 0xFFDA },\n#endif\n{ \"F30\", 0xFFDB },\n#ifndef TK_NO_DEPRECATED\n{ \"R10\", 0xFFDB },\n#endif\n{ \"F31\", 0xFFDC },\n#ifndef TK_NO_DEPRECATED\n{ \"R11\", 0xFFDC },\n#endif\n{ \"F32\", 0xFFDD },\n#ifndef TK_NO_DEPRECATED\n{ \"R12\", 0xFFDD },\n#endif\n{ \"F33\", 0xFFDE },\n#ifndef TK_NO_DEPRECATED\n{ \"R13\", 0xFFDE },\n#endif\n{ \"F34\", 0xFFDF },\n#ifndef TK_NO_DEPRECATED\n{ \"R14\", 0xFFDF },\n#endif\n{ \"F35\", 0xFFE0 },\n#ifndef TK_NO_DEPRECATED\n{ \"R15\", 0xFFE0 },\n#endif\n{ \"Shift_L\", 0xFFE1 },\n{ \"Shift_R\", 0xFFE2 },\n{ \"Control_L\", 0xFFE3 },\n{ \"Control_R\", 0xFFE4 },\n{ \"Caps_Lock\", 0xFFE5 },\n{ \"Shift_Lock\", 0xFFE6 },\n{ \"Meta_L\", 0xFFE7 },\n{ \"Meta_R\", 0xFFE8 },\n{ \"Alt_L\", 0xFFE9 },\n{ \"Alt_R\", 0xFFEA },\n{ \"Super_L\", 0xFFEB },\n#ifndef TK_NO_DEPRECATED\n{ \"Win_L\", 0xFFEB },\n#endif\n{ \"Super_R\", 0xFFEC },\n#ifndef TK_NO_DEPRECATED\n{ \"Win_R\", 0xFFEC },\n#endif\n{ \"Hyper_L\", 0xFFED },\n{ \"Hyper_R\", 0xFFEE },\n{ \"braille_dot_1\", 0xFFF1 },\n{ \"braille_dot_2\", 0xFFF2 },\n{ \"braille_dot_3\", 0xFFF3 },\n{ \"braille_dot_4\", 0xFFF4 },\n{ \"braille_dot_5\", 0xFFF5 },\n{ \"braille_dot_6\", 0xFFF6 },\n{ \"braille_dot_7\", 0xFFF7 },\n{ \"braille_dot_8\", 0xFFF8 },\n{ \"braille_dot_9\", 0xFFF9 },\n{ \"braille_dot_10\", 0xFFFA },\n{ \"Delete\", 0xFFFF },\n{ \"ISO_Lock\", 0xFE01 },\n{ \"ISO_Level2_Latch\", 0xFE02 },\n{ \"ISO_Level3_Shift\", 0xFE03 },\n{ \"ISO_Level3_Latch\", 0xFE04 },\n{ \"ISO_Level3_Lock\", 0xFE05 },\n{ \"ISO_Group_Shift\", 0xFF7E },\n{ \"ISO_Group_Latch\", 0xFE06 },\n{ \"ISO_Group_Lock\", 0xFE07 },\n{ \"ISO_Next_Group\", 0xFE08 },\n{ \"ISO_Next_Group_Lock\", 0xFE09 },\n{ \"ISO_Prev_Group\", 0xFE0A },\n{ \"ISO_Prev_Group_Lock\", 0xFE0B },\n{ \"ISO_First_Group\", 0xFE0C },\n{ \"ISO_First_Group_Lock\", 0xFE0D },\n{ \"ISO_Last_Group\", 0xFE0E },\n{ \"ISO_Last_Group_Lock\", 0xFE0F },\n{ \"ISO_Level5_Shift\", 0xFE11 },\n{ \"ISO_Level5_Latch\", 0xFE12 },\n{ \"ISO_Level5_Lock\", 0xFE13 },\n{ \"ISO_Left_Tab\", 0xFE20 },\n{ \"ISO_Move_Line_Up\", 0xFE21 },\n{ \"ISO_Move_Line_Down\", 0xFE22 },\n{ \"ISO_Partial_Line_Up\", 0xFE23 },\n{ \"ISO_Partial_Line_Down\", 0xFE24 },\n{ \"ISO_Partial_Space_Left\", 0xFE25 },\n{ \"ISO_Partial_Space_Right\", 0xFE26 },\n{ \"ISO_Set_Margin_Left\", 0xFE27 },\n{ \"ISO_Set_Margin_Right\", 0xFE28 },\n{ \"ISO_Release_Margin_Left\", 0xFE29 },\n{ \"ISO_Release_Margin_Right\", 0xFE2A },\n{ \"ISO_Release_Both_Margins\", 0xFE2B },\n{ \"ISO_Fast_Cursor_Left\", 0xFE2C },\n{ \"ISO_Fast_Cursor_Right\", 0xFE2D },\n{ \"ISO_Fast_Cursor_Up\", 0xFE2E },\n{ \"ISO_Fast_Cursor_Down\", 0xFE2F },\n{ \"ISO_Continuous_Underline\", 0xFE30 },\n{ \"ISO_Discontinuous_Underline\", 0xFE31 },\n{ \"ISO_Emphasize\", 0xFE32 },\n{ \"ISO_Center_Object\", 0xFE33 },\n{ \"ISO_Enter\", 0xFE34 },\n{ \"dead_grave\", 0xFE50 },\n{ \"dead_acute\", 0xFE51 },\n{ \"dead_circumflex\", 0xFE52 },\n{ \"dead_tilde\", 0xFE53 },\n{ \"dead_perispomeni\", 0xFE53 },\n{ \"dead_macron\", 0xFE54 },\n{ \"dead_breve\", 0xFE55 },\n{ \"dead_abovedot\", 0xFE56 },\n{ \"dead_diaeresis\", 0xFE57 },\n{ \"dead_abovering\", 0xFE58 },\n{ \"dead_doubleacute\", 0xFE59 },\n{ \"dead_caron\", 0xFE5A },\n{ \"dead_cedilla\", 0xFE5B },\n{ \"dead_ogonek\", 0xFE5C },\n{ \"dead_iota\", 0xFE5D },\n{ \"dead_voiced_sound\", 0xFE5E },\n{ \"dead_semivoiced_sound\", 0xFE5F },\n{ \"dead_belowdot\", 0xFE60 },\n{ \"dead_hook\", 0xFE61 },\n{ \"dead_horn\", 0xFE62 },\n{ \"dead_stroke\", 0xFE63 },\n{ \"dead_abovecomma\", 0xFE64 },\n{ \"dead_psili\", 0xFE64 },\n{ \"dead_abovereversedcomma\", 0xFE65 },\n{ \"dead_dasia\", 0xFE65 },\n{ \"dead_doublegrave\", 0xFE66 },\n{ \"dead_belowring\", 0xFE67 },\n{ \"dead_belowmacron\", 0xFE68 },\n{ \"dead_belowcircumflex\", 0xFE69 },\n{ \"dead_belowtilde\", 0xFE6A },\n{ \"dead_belowbreve\", 0xFE6B },\n{ \"dead_belowdiaeresis\", 0xFE6C },\n{ \"dead_invertedbreve\", 0xFE6D },\n{ \"dead_belowcomma\", 0xFE6E },\n{ \"dead_currency\", 0xFE6F },\n{ \"AccessX_Enable\", 0xFE70 },\n{ \"AccessX_Feedback_Enable\", 0xFE71 },\n{ \"RepeatKeys_Enable\", 0xFE72 },\n{ \"SlowKeys_Enable\", 0xFE73 },\n{ \"BounceKeys_Enable\", 0xFE74 },\n{ \"StickyKeys_Enable\", 0xFE75 },\n{ \"MouseKeys_Enable\", 0xFE76 },\n{ \"MouseKeys_Accel_Enable\", 0xFE77 },\n{ \"Overlay1_Enable\", 0xFE78 },\n{ \"Overlay2_Enable\", 0xFE79 },\n{ \"AudibleBell_Enable\", 0xFE7A },\n{ \"dead_a\", 0xFE80 },\n{ \"dead_A\", 0xFE81 },\n{ \"dead_e\", 0xFE82 },\n{ \"dead_E\", 0xFE83 },\n{ \"dead_i\", 0xFE84 },\n{ \"dead_I\", 0xFE85 },\n{ \"dead_o\", 0xFE86 },\n{ \"dead_O\", 0xFE87 },\n{ \"dead_u\", 0xFE88 },\n{ \"dead_U\", 0xFE89 },\n{ \"dead_schwa\", 0xFE8A },\n#ifndef TK_NO_DEPRECATED\n{ \"dead_small_schwa\", 0xFE8A },\n#endif\n{ \"dead_SCHWA\", 0xFE8B },\n#ifndef TK_NO_DEPRECATED\n{ \"dead_capital_schwa\", 0xFE8B },\n#endif\n{ \"dead_greek\", 0xFE8C },\n{ \"dead_hamza\", 0xFE8D },\n{ \"dead_lowline\", 0xFE90 },\n{ \"dead_aboveverticalline\", 0xFE91 },\n{ \"dead_belowverticalline\", 0xFE92 },\n{ \"dead_longsolidusoverlay\", 0xFE93 },\n{ \"ch\", 0xFEA0 },\n{ \"Ch\", 0xFEA1 },\n{ \"CH\", 0xFEA2 },\n{ \"c_h\", 0xFEA3 },\n{ \"C_h\", 0xFEA4 },\n{ \"C_H\", 0xFEA5 },\n{ \"First_Virtual_Screen\", 0xFED0 },\n{ \"Prev_Virtual_Screen\", 0xFED1 },\n{ \"Next_Virtual_Screen\", 0xFED2 },\n{ \"Last_Virtual_Screen\", 0xFED4 },\n{ \"Terminate_Server\", 0xFED5 },\n{ \"Pointer_Left\", 0xFEE0 },\n{ \"Pointer_Right\", 0xFEE1 },\n{ \"Pointer_Up\", 0xFEE2 },\n{ \"Pointer_Down\", 0xFEE3 },\n{ \"Pointer_UpLeft\", 0xFEE4 },\n{ \"Pointer_UpRight\", 0xFEE5 },\n{ \"Pointer_DownLeft\", 0xFEE6 },\n{ \"Pointer_DownRight\", 0xFEE7 },\n{ \"Pointer_Button_Dflt\", 0xFEE8 },\n{ \"Pointer_Button1\", 0xFEE9 },\n{ \"Pointer_Button2\", 0xFEEA },\n{ \"Pointer_Button3\", 0xFEEB },\n{ \"Pointer_Button4\", 0xFEEC },\n{ \"Pointer_Button5\", 0xFEED },\n{ \"Pointer_DblClick_Dflt\", 0xFEEE },\n{ \"Pointer_DblClick1\", 0xFEEF },\n{ \"Pointer_DblClick2\", 0xFEF0 },\n{ \"Pointer_DblClick3\", 0xFEF1 },\n{ \"Pointer_DblClick4\", 0xFEF2 },\n{ \"Pointer_DblClick5\", 0xFEF3 },\n{ \"Pointer_Drag_Dflt\", 0xFEF4 },\n{ \"Pointer_Drag1\", 0xFEF5 },\n{ \"Pointer_Drag2\", 0xFEF6 },\n{ \"Pointer_Drag3\", 0xFEF7 },\n{ \"Pointer_Drag4\", 0xFEF8 },\n{ \"Pointer_EnableKeys\", 0xFEF9 },\n{ \"Pointer_Accelerate\", 0xFEFA },\n{ \"Pointer_DfltBtnNext\", 0xFEFB },\n{ \"Pointer_DfltBtnPrev\", 0xFEFC },\n{ \"Pointer_Drag5\", 0xFEFD },\n{ \"space\", 0x20 },\n#ifndef TK_NO_DEPRECATED\n{ \"exclam\", 0x21 },\n#endif\n{ \"quotedbl\", 0x22 },\n{ \"numbersign\", 0x23 },\n{ \"dollar\", 0x24 },\n#ifndef TK_NO_DEPRECATED\n{ \"percent\", 0x25 },\n{ \"ampersand\", 0x26 },\n{ \"apostrophe\", 0x27 },\n{ \"quoteright\", 0x27 },\n{ \"parenleft\", 0x28 },\n{ \"parenright\", 0x29 },\n{ \"asterisk\", 0x2A },\n{ \"plus\", 0x2B },\n{ \"comma\", 0x2C },\n#endif\n{ \"minus\", 0x2D },\n#ifndef TK_NO_DEPRECATED\n{ \"period\", 0x2E },\n{ \"slash\", 0x2F },\n{ \"0\", 0x30 },\n{ \"1\", 0x31 },\n{ \"2\", 0x32 },\n{ \"3\", 0x33 },\n{ \"4\", 0x34 },\n{ \"5\", 0x35 },\n{ \"6\", 0x36 },\n{ \"7\", 0x37 },\n{ \"8\", 0x38 },\n{ \"9\", 0x39 },\n{ \"colon\", 0x3A },\n#endif\n{ \"semicolon\", 0x3B },\n{ \"less\", 0x3C },\n#ifndef TK_NO_DEPRECATED\n{ \"equal\", 0x3D },\n#endif\n{ \"greater\", 0x3E },\n#ifndef TK_NO_DEPRECATED\n{ \"question\", 0x3F },\n{ \"at\", 0x40 },\n{ \"A\", 0x41 },\n{ \"B\", 0x42 },\n{ \"C\", 0x43 },\n{ \"D\", 0x44 },\n{ \"E\", 0x45 },\n{ \"F\", 0x46 },\n{ \"G\", 0x47 },\n{ \"H\", 0x48 },\n{ \"I\", 0x49 },\n{ \"J\", 0x4A },\n{ \"K\", 0x4B },\n{ \"L\", 0x4C },\n{ \"M\", 0x4D },\n{ \"N\", 0x4E },\n{ \"O\", 0x4F },\n{ \"P\", 0x50 },\n{ \"Q\", 0x51 },\n{ \"R\", 0x52 },\n{ \"S\", 0x53 },\n{ \"T\", 0x54 },\n{ \"U\", 0x55 },\n{ \"V\", 0x56 },\n{ \"W\", 0x57 },\n{ \"X\", 0x58 },\n{ \"Y\", 0x59 },\n{ \"Z\", 0x5A },\n#endif\n{ \"bracketleft\", 0x5B },\n{ \"backslash\", 0x5C },\n{ \"bracketright\", 0x5D },\n#ifndef TK_NO_DEPRECATED\n{ \"asciicircum\", 0x5E },\n{ \"underscore\", 0x5F },\n{ \"grave\", 0x60 },\n{ \"quoteleft\", 0x60 },\n{ \"a\", 0x61 },\n{ \"b\", 0x62 },\n{ \"c\", 0x63 },\n{ \"d\", 0x64 },\n{ \"e\", 0x65 },\n{ \"f\", 0x66 },\n{ \"g\", 0x67 },\n{ \"h\", 0x68 },\n{ \"i\", 0x69 },\n{ \"j\", 0x6A },\n{ \"k\", 0x6B },\n{ \"l\", 0x6C },\n{ \"m\", 0x6D },\n{ \"n\", 0x6E },\n{ \"o\", 0x6F },\n{ \"p\", 0x70 },\n{ \"q\", 0x71 },\n{ \"r\", 0x72 },\n{ \"s\", 0x73 },\n{ \"t\", 0x74 },\n{ \"u\", 0x75 },\n{ \"v\", 0x76 },\n{ \"w\", 0x77 },\n{ \"x\", 0x78 },\n{ \"y\", 0x79 },\n{ \"z\", 0x7A },\n#endif\n{ \"braceleft\", 0x7B },\n#ifndef TK_NO_DEPRECATED\n{ \"bar\", 0x7C },\n#endif\n{ \"braceright\", 0x7D },\n#ifndef TK_NO_DEPRECATED\n{ \"asciitilde\", 0x7E },\n#endif\n{ \"nobreakspace\", 0xA0 },\n#ifndef TK_NO_DEPRECATED\n{ \"exclamdown\", 0xA1 },\n{ \"cent\", 0xA2 },\n{ \"sterling\", 0xA3 },\n{ \"currency\", 0xA4 },\n{ \"yen\", 0xA5 },\n{ \"brokenbar\", 0xA6 },\n{ \"section\", 0xA7 },\n{ \"diaeresis\", 0xA8 },\n{ \"copyright\", 0xA9 },\n{ \"ordfeminine\", 0xAA },\n{ \"guillemetleft\", 0xAB },\n{ \"guillemotleft\", 0xAB },\n{ \"notsign\", 0xAC },\n{ \"hyphen\", 0xAD },\n{ \"registered\", 0xAE },\n{ \"macron\", 0xAF },\n{ \"degree\", 0xB0 },\n{ \"plusminus\", 0xB1 },\n{ \"twosuperior\", 0xB2 },\n{ \"threesuperior\", 0xB3 },\n{ \"acute\", 0xB4 },\n{ \"mu\", 0xB5 },\n{ \"paragraph\", 0xB6 },\n{ \"periodcentered\", 0xB7 },\n{ \"cedilla\", 0xB8 },\n{ \"onesuperior\", 0xB9 },\n{ \"ordmasculine\", 0xBA },\n{ \"masculine\", 0xBA },\n{ \"guillemetright\", 0xBB },\n{ \"guillemotright\", 0xBB },\n{ \"onequarter\", 0xBC },\n{ \"onehalf\", 0xBD },\n{ \"threequarters\", 0xBE },\n{ \"questiondown\", 0xBF },\n{ \"Agrave\", 0xC0 },\n{ \"Aacute\", 0xC1 },\n{ \"Acircumflex\", 0xC2 },\n{ \"Atilde\", 0xC3 },\n{ \"Adiaeresis\", 0xC4 },\n{ \"Aring\", 0xC5 },\n{ \"AE\", 0xC6 },\n{ \"Ccedilla\", 0xC7 },\n{ \"Egrave\", 0xC8 },\n{ \"Eacute\", 0xC9 },\n{ \"Ecircumflex\", 0xCA },\n{ \"Ediaeresis\", 0xCB },\n{ \"Igrave\", 0xCC },\n{ \"Iacute\", 0xCD },\n{ \"Icircumflex\", 0xCE },\n{ \"Idiaeresis\", 0xCF },\n{ \"ETH\", 0xD0 },\n{ \"Eth\", 0xD0 },\n{ \"Ntilde\", 0xD1 },\n{ \"Ograve\", 0xD2 },\n{ \"Oacute\", 0xD3 },\n{ \"Ocircumflex\", 0xD4 },\n{ \"Otilde\", 0xD5 },\n{ \"Odiaeresis\", 0xD6 },\n{ \"multiply\", 0xD7 },\n{ \"Oslash\", 0xD8 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ooblique\", 0xD8 },\n#endif\n{ \"Ugrave\", 0xD9 },\n{ \"Uacute\", 0xDA },\n{ \"Ucircumflex\", 0xDB },\n{ \"Udiaeresis\", 0xDC },\n{ \"Yacute\", 0xDD },\n{ \"THORN\", 0xDE },\n{ \"Thorn\", 0xDE },\n{ \"ssharp\", 0xDF },\n{ \"agrave\", 0xE0 },\n{ \"aacute\", 0xE1 },\n{ \"acircumflex\", 0xE2 },\n{ \"atilde\", 0xE3 },\n{ \"adiaeresis\", 0xE4 },\n{ \"aring\", 0xE5 },\n{ \"ae\", 0xE6 },\n{ \"ccedilla\", 0xE7 },\n{ \"egrave\", 0xE8 },\n{ \"eacute\", 0xE9 },\n{ \"ecircumflex\", 0xEA },\n{ \"ediaeresis\", 0xEB },\n{ \"igrave\", 0xEC },\n{ \"iacute\", 0xED },\n{ \"icircumflex\", 0xEE },\n{ \"idiaeresis\", 0xEF },\n{ \"eth\", 0xF0 },\n{ \"ntilde\", 0xF1 },\n{ \"ograve\", 0xF2 },\n{ \"oacute\", 0xF3 },\n{ \"ocircumflex\", 0xF4 },\n{ \"otilde\", 0xF5 },\n{ \"odiaeresis\", 0xF6 },\n{ \"division\", 0xF7 },\n{ \"oslash\", 0xF8 },\n#ifndef TK_NO_DEPRECATED\n{ \"ooblique\", 0xF8 },\n#endif\n{ \"ugrave\", 0xF9 },\n{ \"uacute\", 0xFA },\n{ \"ucircumflex\", 0xFB },\n{ \"udiaeresis\", 0xFC },\n{ \"yacute\", 0xFD },\n{ \"thorn\", 0xFE },\n{ \"ydiaeresis\", 0xFF },\n#endif\n{ \"Aogonek\", 0x1A1 },\n{ \"breve\", 0x1A2 },\n{ \"Lstroke\", 0x1A3 },\n{ \"Lcaron\", 0x1A5 },\n{ \"Sacute\", 0x1A6 },\n{ \"Scaron\", 0x1A9 },\n{ \"Scedilla\", 0x1AA },\n{ \"Tcaron\", 0x1AB },\n{ \"Zacute\", 0x1AC },\n{ \"Zcaron\", 0x1AE },\n{ \"Zabovedot\", 0x1AF },\n{ \"aogonek\", 0x1B1 },\n{ \"ogonek\", 0x1B2 },\n{ \"lstroke\", 0x1B3 },\n{ \"lcaron\", 0x1B5 },\n{ \"sacute\", 0x1B6 },\n{ \"caron\", 0x1B7 },\n{ \"scaron\", 0x1B9 },\n{ \"scedilla\", 0x1BA },\n{ \"tcaron\", 0x1BB },\n{ \"zacute\", 0x1BC },\n{ \"doubleacute\", 0x1BD },\n{ \"zcaron\", 0x1BE },\n{ \"zabovedot\", 0x1BF },\n{ \"Racute\", 0x1C0 },\n{ \"Abreve\", 0x1C3 },\n{ \"Lacute\", 0x1C5 },\n{ \"Cacute\", 0x1C6 },\n{ \"Ccaron\", 0x1C8 },\n{ \"Eogonek\", 0x1CA },\n{ \"Ecaron\", 0x1CC },\n{ \"Dcaron\", 0x1CF },\n{ \"Dstroke\", 0x1D0 },\n{ \"Nacute\", 0x1D1 },\n{ \"Ncaron\", 0x1D2 },\n{ \"Odoubleacute\", 0x1D5 },\n{ \"Rcaron\", 0x1D8 },\n{ \"Uring\", 0x1D9 },\n{ \"Udoubleacute\", 0x1DB },\n{ \"Tcedilla\", 0x1DE },\n{ \"racute\", 0x1E0 },\n{ \"abreve\", 0x1E3 },\n{ \"lacute\", 0x1E5 },\n{ \"cacute\", 0x1E6 },\n{ \"ccaron\", 0x1E8 },\n{ \"eogonek\", 0x1EA },\n{ \"ecaron\", 0x1EC },\n{ \"dcaron\", 0x1EF },\n{ \"dstroke\", 0x1F0 },\n{ \"nacute\", 0x1F1 },\n{ \"ncaron\", 0x1F2 },\n{ \"odoubleacute\", 0x1F5 },\n{ \"rcaron\", 0x1F8 },\n{ \"uring\", 0x1F9 },\n{ \"udoubleacute\", 0x1FB },\n{ \"tcedilla\", 0x1FE },\n{ \"abovedot\", 0x1FF },\n{ \"Hstroke\", 0x2A1 },\n{ \"Hcircumflex\", 0x2A6 },\n{ \"Iabovedot\", 0x2A9 },\n{ \"Gbreve\", 0x2AB },\n{ \"Jcircumflex\", 0x2AC },\n{ \"hstroke\", 0x2B1 },\n{ \"hcircumflex\", 0x2B6 },\n{ \"idotless\", 0x2B9 },\n{ \"gbreve\", 0x2BB },\n{ \"jcircumflex\", 0x2BC },\n{ \"Cabovedot\", 0x2C5 },\n{ \"Ccircumflex\", 0x2C6 },\n{ \"Gabovedot\", 0x2D5 },\n{ \"Gcircumflex\", 0x2D8 },\n{ \"Ubreve\", 0x2DD },\n{ \"Scircumflex\", 0x2DE },\n{ \"cabovedot\", 0x2E5 },\n{ \"ccircumflex\", 0x2E6 },\n{ \"gabovedot\", 0x2F5 },\n{ \"gcircumflex\", 0x2F8 },\n{ \"ubreve\", 0x2FD },\n{ \"scircumflex\", 0x2FE },\n{ \"kra\", 0x3A2 },\n#ifndef TK_NO_DEPRECATED\n{ \"kappa\", 0x3A2 },\n#endif\n{ \"Rcedilla\", 0x3A3 },\n{ \"Itilde\", 0x3A5 },\n{ \"Lcedilla\", 0x3A6 },\n{ \"Emacron\", 0x3AA },\n{ \"Gcedilla\", 0x3AB },\n{ \"Tslash\", 0x3AC },\n{ \"rcedilla\", 0x3B3 },\n{ \"itilde\", 0x3B5 },\n{ \"lcedilla\", 0x3B6 },\n{ \"emacron\", 0x3BA },\n{ \"gcedilla\", 0x3BB },\n#ifndef TK_NO_DEPRECATED\n{ \"gacute\", 0x3BB },\n#endif\n{ \"tslash\", 0x3BC },\n{ \"ENG\", 0x3BD },\n{ \"eng\", 0x3BF },\n{ \"Amacron\", 0x3C0 },\n{ \"Iogonek\", 0x3C7 },\n{ \"Eabovedot\", 0x3CC },\n{ \"Imacron\", 0x3CF },\n{ \"Ncedilla\", 0x3D1 },\n{ \"Omacron\", 0x3D2 },\n{ \"Kcedilla\", 0x3D3 },\n{ \"Uogonek\", 0x3D9 },\n{ \"Utilde\", 0x3DD },\n{ \"Umacron\", 0x3DE },\n{ \"amacron\", 0x3E0 },\n{ \"iogonek\", 0x3E7 },\n{ \"eabovedot\", 0x3EC },\n{ \"imacron\", 0x3EF },\n{ \"ncedilla\", 0x3F1 },\n{ \"omacron\", 0x3F2 },\n{ \"kcedilla\", 0x3F3 },\n{ \"uogonek\", 0x3F9 },\n{ \"utilde\", 0x3FD },\n{ \"umacron\", 0x3FE },\n{ \"OE\", 0x13BC },\n{ \"oe\", 0x13BD },\n{ \"Ydiaeresis\", 0x13BE },\n{ \"overline\", 0x47E },\n{ \"kana_fullstop\", 0x4A1 },\n{ \"kana_openingbracket\", 0x4A2 },\n{ \"kana_closingbracket\", 0x4A3 },\n{ \"kana_comma\", 0x4A4 },\n{ \"kana_conjunctive\", 0x4A5 },\n#ifndef TK_NO_DEPRECATED\n{ \"kana_middledot\", 0x4A5 },\n#endif\n{ \"kana_WO\", 0x4A6 },\n{ \"kana_a\", 0x4A7 },\n{ \"kana_i\", 0x4A8 },\n{ \"kana_u\", 0x4A9 },\n{ \"kana_e\", 0x4AA },\n{ \"kana_o\", 0x4AB },\n{ \"kana_ya\", 0x4AC },\n{ \"kana_yu\", 0x4AD },\n{ \"kana_yo\", 0x4AE },\n{ \"kana_tsu\", 0x4AF },\n#ifndef TK_NO_DEPRECATED\n{ \"kana_tu\", 0x4AF },\n#endif\n{ \"prolongedsound\", 0x4B0 },\n{ \"kana_A\", 0x4B1 },\n{ \"kana_I\", 0x4B2 },\n{ \"kana_U\", 0x4B3 },\n{ \"kana_E\", 0x4B4 },\n{ \"kana_O\", 0x4B5 },\n{ \"kana_KA\", 0x4B6 },\n{ \"kana_KI\", 0x4B7 },\n{ \"kana_KU\", 0x4B8 },\n{ \"kana_KE\", 0x4B9 },\n{ \"kana_KO\", 0x4BA },\n{ \"kana_SA\", 0x4BB },\n{ \"kana_SHI\", 0x4BC },\n{ \"kana_SU\", 0x4BD },\n{ \"kana_SE\", 0x4BE },\n{ \"kana_SO\", 0x4BF },\n{ \"kana_TA\", 0x4C0 },\n{ \"kana_CHI\", 0x4C1 },\n#ifndef TK_NO_DEPRECATED\n{ \"kana_TI\", 0x4C1 },\n#endif\n{ \"kana_TSU\", 0x4C2 },\n#ifndef TK_NO_DEPRECATED\n{ \"kana_TU\", 0x4C2 },\n#endif\n{ \"kana_TE\", 0x4C3 },\n{ \"kana_TO\", 0x4C4 },\n{ \"kana_NA\", 0x4C5 },\n{ \"kana_NI\", 0x4C6 },\n{ \"kana_NU\", 0x4C7 },\n{ \"kana_NE\", 0x4C8 },\n{ \"kana_NO\", 0x4C9 },\n{ \"kana_HA\", 0x4CA },\n{ \"kana_HI\", 0x4CB },\n{ \"kana_FU\", 0x4CC },\n#ifndef TK_NO_DEPRECATED\n{ \"kana_HU\", 0x4CC },\n#endif\n{ \"kana_HE\", 0x4CD },\n{ \"kana_HO\", 0x4CE },\n{ \"kana_MA\", 0x4CF },\n{ \"kana_MI\", 0x4D0 },\n{ \"kana_MU\", 0x4D1 },\n{ \"kana_ME\", 0x4D2 },\n{ \"kana_MO\", 0x4D3 },\n{ \"kana_YA\", 0x4D4 },\n{ \"kana_YU\", 0x4D5 },\n{ \"kana_YO\", 0x4D6 },\n{ \"kana_RA\", 0x4D7 },\n{ \"kana_RI\", 0x4D8 },\n{ \"kana_RU\", 0x4D9 },\n{ \"kana_RE\", 0x4DA },\n{ \"kana_RO\", 0x4DB },\n{ \"kana_WA\", 0x4DC },\n{ \"kana_N\", 0x4DD },\n{ \"voicedsound\", 0x4DE },\n{ \"semivoicedsound\", 0x4DF },\n{ \"Arabic_comma\", 0x5AC },\n{ \"Arabic_semicolon\", 0x5BB },\n{ \"Arabic_question_mark\", 0x5BF },\n{ \"Arabic_hamza\", 0x5C1 },\n{ \"Arabic_maddaonalef\", 0x5C2 },\n{ \"Arabic_hamzaonalef\", 0x5C3 },\n{ \"Arabic_hamzaonwaw\", 0x5C4 },\n{ \"Arabic_hamzaunderalef\", 0x5C5 },\n{ \"Arabic_hamzaonyeh\", 0x5C6 },\n{ \"Arabic_alef\", 0x5C7 },\n{ \"Arabic_beh\", 0x5C8 },\n{ \"Arabic_tehmarbuta\", 0x5C9 },\n{ \"Arabic_teh\", 0x5CA },\n{ \"Arabic_theh\", 0x5CB },\n{ \"Arabic_jeem\", 0x5CC },\n{ \"Arabic_hah\", 0x5CD },\n{ \"Arabic_khah\", 0x5CE },\n{ \"Arabic_dal\", 0x5CF },\n{ \"Arabic_thal\", 0x5D0 },\n{ \"Arabic_ra\", 0x5D1 },\n{ \"Arabic_zain\", 0x5D2 },\n{ \"Arabic_seen\", 0x5D3 },\n{ \"Arabic_sheen\", 0x5D4 },\n{ \"Arabic_sad\", 0x5D5 },\n{ \"Arabic_dad\", 0x5D6 },\n{ \"Arabic_tah\", 0x5D7 },\n{ \"Arabic_zah\", 0x5D8 },\n{ \"Arabic_ain\", 0x5D9 },\n{ \"Arabic_ghain\", 0x5DA },\n{ \"Arabic_tatweel\", 0x5E0 },\n{ \"Arabic_feh\", 0x5E1 },\n{ \"Arabic_qaf\", 0x5E2 },\n{ \"Arabic_kaf\", 0x5E3 },\n{ \"Arabic_lam\", 0x5E4 },\n{ \"Arabic_meem\", 0x5E5 },\n{ \"Arabic_noon\", 0x5E6 },\n{ \"Arabic_ha\", 0x5E7 },\n#ifndef TK_NO_DEPRECATED\n{ \"Arabic_heh\", 0x5E7 },\n#endif\n{ \"Arabic_waw\", 0x5E8 },\n{ \"Arabic_alefmaksura\", 0x5E9 },\n{ \"Arabic_yeh\", 0x5EA },\n{ \"Arabic_fathatan\", 0x5EB },\n{ \"Arabic_dammatan\", 0x5EC },\n{ \"Arabic_kasratan\", 0x5ED },\n{ \"Arabic_fatha\", 0x5EE },\n{ \"Arabic_damma\", 0x5EF },\n{ \"Arabic_kasra\", 0x5F0 },\n{ \"Arabic_shadda\", 0x5F1 },\n{ \"Arabic_sukun\", 0x5F2 },\n{ \"Serbian_dje\", 0x6A1 },\n{ \"Macedonia_gje\", 0x6A2 },\n{ \"Cyrillic_io\", 0x6A3 },\n{ \"Ukrainian_ie\", 0x6A4 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_je\", 0x6A4 },\n#endif\n{ \"Macedonia_dse\", 0x6A5 },\n{ \"Ukrainian_i\", 0x6A6 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_i\", 0x6A6 },\n#endif\n{ \"Ukrainian_yi\", 0x6A7 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_yi\", 0x6A7 },\n#endif\n{ \"Cyrillic_je\", 0x6A8 },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_je\", 0x6A8 },\n#endif\n{ \"Cyrillic_lje\", 0x6A9 },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_lje\", 0x6A9 },\n#endif\n{ \"Cyrillic_nje\", 0x6AA },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_nje\", 0x6AA },\n#endif\n{ \"Serbian_tshe\", 0x6AB },\n{ \"Macedonia_kje\", 0x6AC },\n{ \"Ukrainian_ghe_with_upturn\", 0x6AD },\n{ \"Byelorussian_shortu\", 0x6AE },\n{ \"Cyrillic_dzhe\", 0x6AF },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_dze\", 0x6AF },\n#endif\n{ \"numerosign\", 0x6B0 },\n{ \"Serbian_DJE\", 0x6B1 },\n{ \"Macedonia_GJE\", 0x6B2 },\n{ \"Cyrillic_IO\", 0x6B3 },\n{ \"Ukrainian_IE\", 0x6B4 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_JE\", 0x6B4 },\n#endif\n{ \"Macedonia_DSE\", 0x6B5 },\n{ \"Ukrainian_I\", 0x6B6 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_I\", 0x6B6 },\n#endif\n{ \"Ukrainian_YI\", 0x6B7 },\n#ifndef TK_NO_DEPRECATED\n{ \"Ukranian_YI\", 0x6B7 },\n#endif\n{ \"Cyrillic_JE\", 0x6B8 },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_JE\", 0x6B8 },\n#endif\n{ \"Cyrillic_LJE\", 0x6B9 },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_LJE\", 0x6B9 },\n#endif\n{ \"Cyrillic_NJE\", 0x6BA },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_NJE\", 0x6BA },\n#endif\n{ \"Serbian_TSHE\", 0x6BB },\n{ \"Macedonia_KJE\", 0x6BC },\n{ \"Ukrainian_GHE_WITH_UPTURN\", 0x6BD },\n{ \"Byelorussian_SHORTU\", 0x6BE },\n{ \"Cyrillic_DZHE\", 0x6BF },\n#ifndef TK_NO_DEPRECATED\n{ \"Serbian_DZE\", 0x6BF },\n#endif\n{ \"Cyrillic_yu\", 0x6C0 },\n{ \"Cyrillic_a\", 0x6C1 },\n{ \"Cyrillic_be\", 0x6C2 },\n{ \"Cyrillic_tse\", 0x6C3 },\n{ \"Cyrillic_de\", 0x6C4 },\n{ \"Cyrillic_ie\", 0x6C5 },\n{ \"Cyrillic_ef\", 0x6C6 },\n{ \"Cyrillic_ghe\", 0x6C7 },\n{ \"Cyrillic_ha\", 0x6C8 },\n{ \"Cyrillic_i\", 0x6C9 },\n{ \"Cyrillic_shorti\", 0x6CA },\n{ \"Cyrillic_ka\", 0x6CB },\n{ \"Cyrillic_el\", 0x6CC },\n{ \"Cyrillic_em\", 0x6CD },\n{ \"Cyrillic_en\", 0x6CE },\n{ \"Cyrillic_o\", 0x6CF },\n{ \"Cyrillic_pe\", 0x6D0 },\n{ \"Cyrillic_ya\", 0x6D1 },\n{ \"Cyrillic_er\", 0x6D2 },\n{ \"Cyrillic_es\", 0x6D3 },\n{ \"Cyrillic_te\", 0x6D4 },\n{ \"Cyrillic_u\", 0x6D5 },\n{ \"Cyrillic_zhe\", 0x6D6 },\n{ \"Cyrillic_ve\", 0x6D7 },\n{ \"Cyrillic_softsign\", 0x6D8 },\n{ \"Cyrillic_yeru\", 0x6D9 },\n{ \"Cyrillic_ze\", 0x6DA },\n{ \"Cyrillic_sha\", 0x6DB },\n{ \"Cyrillic_e\", 0x6DC },\n{ \"Cyrillic_shcha\", 0x6DD },\n{ \"Cyrillic_che\", 0x6DE },\n{ \"Cyrillic_hardsign\", 0x6DF },\n{ \"Cyrillic_YU\", 0x6E0 },\n{ \"Cyrillic_A\", 0x6E1 },\n{ \"Cyrillic_BE\", 0x6E2 },\n{ \"Cyrillic_TSE\", 0x6E3 },\n{ \"Cyrillic_DE\", 0x6E4 },\n{ \"Cyrillic_IE\", 0x6E5 },\n{ \"Cyrillic_EF\", 0x6E6 },\n{ \"Cyrillic_GHE\", 0x6E7 },\n{ \"Cyrillic_HA\", 0x6E8 },\n{ \"Cyrillic_I\", 0x6E9 },\n{ \"Cyrillic_SHORTI\", 0x6EA },\n{ \"Cyrillic_KA\", 0x6EB },\n{ \"Cyrillic_EL\", 0x6EC },\n{ \"Cyrillic_EM\", 0x6ED },\n{ \"Cyrillic_EN\", 0x6EE },\n{ \"Cyrillic_O\", 0x6EF },\n{ \"Cyrillic_PE\", 0x6F0 },\n{ \"Cyrillic_YA\", 0x6F1 },\n{ \"Cyrillic_ER\", 0x6F2 },\n{ \"Cyrillic_ES\", 0x6F3 },\n{ \"Cyrillic_TE\", 0x6F4 },\n{ \"Cyrillic_U\", 0x6F5 },\n{ \"Cyrillic_ZHE\", 0x6F6 },\n{ \"Cyrillic_VE\", 0x6F7 },\n{ \"Cyrillic_SOFTSIGN\", 0x6F8 },\n{ \"Cyrillic_YERU\", 0x6F9 },\n{ \"Cyrillic_ZE\", 0x6FA },\n{ \"Cyrillic_SHA\", 0x6FB },\n{ \"Cyrillic_E\", 0x6FC },\n{ \"Cyrillic_SHCHA\", 0x6FD },\n{ \"Cyrillic_CHE\", 0x6FE },\n{ \"Cyrillic_HARDSIGN\", 0x6FF },\n{ \"Greek_ALPHAaccent\", 0x7A1 },\n{ \"Greek_EPSILONaccent\", 0x7A2 },\n{ \"Greek_ETAaccent\", 0x7A3 },\n{ \"Greek_IOTAaccent\", 0x7A4 },\n{ \"Greek_IOTAdieresis\", 0x7A5 },\n#ifndef TK_NO_DEPRECATED\n{ \"Greek_IOTAdiaeresis\", 0x7A5 },\n#endif\n{ \"Greek_IOTAaccentdiaeresis\", 0x7A6 },\n{ \"Greek_OMICRONaccent\", 0x7A7 },\n{ \"Greek_UPSILONaccent\", 0x7A8 },\n{ \"Greek_UPSILONdieresis\", 0x7A9 },\n{ \"Greek_UPSILONaccentdieresis\", 0x7AA },\n{ \"Greek_OMEGAaccent\", 0x7AB },\n{ \"Greek_accentdieresis\", 0x7AE },\n{ \"Greek_horizbar\", 0x7AF },\n{ \"Greek_alphaaccent\", 0x7B1 },\n{ \"Greek_epsilonaccent\", 0x7B2 },\n{ \"Greek_etaaccent\", 0x7B3 },\n{ \"Greek_iotaaccent\", 0x7B4 },\n{ \"Greek_iotadieresis\", 0x7B5 },\n{ \"Greek_iotaaccentdieresis\", 0x7B6 },\n{ \"Greek_omicronaccent\", 0x7B7 },\n{ \"Greek_upsilonaccent\", 0x7B8 },\n{ \"Greek_upsilondieresis\", 0x7B9 },\n{ \"Greek_upsilonaccentdieresis\", 0x7BA },\n{ \"Greek_omegaaccent\", 0x7BB },\n{ \"Greek_ALPHA\", 0x7C1 },\n{ \"Greek_BETA\", 0x7C2 },\n{ \"Greek_GAMMA\", 0x7C3 },\n{ \"Greek_DELTA\", 0x7C4 },\n{ \"Greek_EPSILON\", 0x7C5 },\n{ \"Greek_ZETA\", 0x7C6 },\n{ \"Greek_ETA\", 0x7C7 },\n{ \"Greek_THETA\", 0x7C8 },\n{ \"Greek_IOTA\", 0x7C9 },\n{ \"Greek_KAPPA\", 0x7CA },\n{ \"Greek_LAMBDA\", 0x7CB },\n{ \"Greek_LAMDA\", 0x7CB },\n{ \"Greek_MU\", 0x7CC },\n{ \"Greek_NU\", 0x7CD },\n{ \"Greek_XI\", 0x7CE },\n{ \"Greek_OMICRON\", 0x7CF },\n{ \"Greek_PI\", 0x7D0 },\n{ \"Greek_RHO\", 0x7D1 },\n{ \"Greek_SIGMA\", 0x7D2 },\n{ \"Greek_TAU\", 0x7D4 },\n{ \"Greek_UPSILON\", 0x7D5 },\n{ \"Greek_PHI\", 0x7D6 },\n{ \"Greek_CHI\", 0x7D7 },\n{ \"Greek_PSI\", 0x7D8 },\n{ \"Greek_OMEGA\", 0x7D9 },\n{ \"Greek_alpha\", 0x7E1 },\n{ \"Greek_beta\", 0x7E2 },\n{ \"Greek_gamma\", 0x7E3 },\n{ \"Greek_delta\", 0x7E4 },\n{ \"Greek_epsilon\", 0x7E5 },\n{ \"Greek_zeta\", 0x7E6 },\n{ \"Greek_eta\", 0x7E7 },\n{ \"Greek_theta\", 0x7E8 },\n{ \"Greek_iota\", 0x7E9 },\n{ \"Greek_kappa\", 0x7EA },\n{ \"Greek_lambda\", 0x7EB },\n{ \"Greek_lamda\", 0x7EB },\n{ \"Greek_mu\", 0x7EC },\n{ \"Greek_nu\", 0x7ED },\n{ \"Greek_xi\", 0x7EE },\n{ \"Greek_omicron\", 0x7EF },\n{ \"Greek_pi\", 0x7F0 },\n{ \"Greek_rho\", 0x7F1 },\n{ \"Greek_sigma\", 0x7F2 },\n{ \"Greek_finalsmallsigma\", 0x7F3 },\n{ \"Greek_tau\", 0x7F4 },\n{ \"Greek_upsilon\", 0x7F5 },\n{ \"Greek_phi\", 0x7F6 },\n{ \"Greek_chi\", 0x7F7 },\n{ \"Greek_psi\", 0x7F8 },\n{ \"Greek_omega\", 0x7F9 },\n{ \"leftradical\", 0x8A1 },\n{ \"topleftradical\", 0x8A2 },\n{ \"horizconnector\", 0x8A3 },\n{ \"topintegral\", 0x8A4 },\n{ \"botintegral\", 0x8A5 },\n{ \"vertconnector\", 0x8A6 },\n{ \"topleftsqbracket\", 0x8A7 },\n{ \"botleftsqbracket\", 0x8A8 },\n{ \"toprightsqbracket\", 0x8A9 },\n{ \"botrightsqbracket\", 0x8AA },\n{ \"topleftparens\", 0x8AB },\n{ \"botleftparens\", 0x8AC },\n{ \"toprightparens\", 0x8AD },\n{ \"botrightparens\", 0x8AE },\n{ \"leftmiddlecurlybrace\", 0x8AF },\n{ \"rightmiddlecurlybrace\", 0x8B0 },\n{ \"topleftsummation\", 0x8B1 },\n{ \"botleftsummation\", 0x8B2 },\n{ \"topvertsummationconnector\", 0x8B3 },\n{ \"botvertsummationconnector\", 0x8B4 },\n{ \"toprightsummation\", 0x8B5 },\n{ \"botrightsummation\", 0x8B6 },\n{ \"rightmiddlesummation\", 0x8B7 },\n{ \"lessthanequal\", 0x8BC },\n{ \"notequal\", 0x8BD },\n{ \"greaterthanequal\", 0x8BE },\n{ \"integral\", 0x8BF },\n{ \"therefore\", 0x8C0 },\n{ \"variation\", 0x8C1 },\n{ \"infinity\", 0x8C2 },\n{ \"nabla\", 0x8C5 },\n{ \"approximate\", 0x8C8 },\n{ \"similarequal\", 0x8C9 },\n{ \"ifonlyif\", 0x8CD },\n{ \"implies\", 0x8CE },\n{ \"identical\", 0x8CF },\n{ \"radical\", 0x8D6 },\n{ \"includedin\", 0x8DA },\n{ \"includes\", 0x8DB },\n{ \"intersection\", 0x8DC },\n{ \"union\", 0x8DD },\n{ \"logicaland\", 0x8DE },\n{ \"logicalor\", 0x8DF },\n{ \"partialderivative\", 0x8EF },\n{ \"function\", 0x8F6 },\n{ \"leftarrow\", 0x8FB },\n{ \"uparrow\", 0x8FC },\n{ \"rightarrow\", 0x8FD },\n{ \"downarrow\", 0x8FE },\n{ \"blank\", 0x9DF },\n{ \"soliddiamond\", 0x9E0 },\n{ \"checkerboard\", 0x9E1 },\n{ \"ht\", 0x9E2 },\n{ \"ff\", 0x9E3 },\n{ \"cr\", 0x9E4 },\n{ \"lf\", 0x9E5 },\n{ \"nl\", 0x9E8 },\n{ \"vt\", 0x9E9 },\n{ \"lowrightcorner\", 0x9EA },\n{ \"uprightcorner\", 0x9EB },\n{ \"upleftcorner\", 0x9EC },\n{ \"lowleftcorner\", 0x9ED },\n{ \"crossinglines\", 0x9EE },\n{ \"horizlinescan1\", 0x9EF },\n{ \"horizlinescan3\", 0x9F0 },\n{ \"horizlinescan5\", 0x9F1 },\n{ \"horizlinescan7\", 0x9F2 },\n{ \"horizlinescan9\", 0x9F3 },\n{ \"leftt\", 0x9F4 },\n{ \"rightt\", 0x9F5 },\n{ \"bott\", 0x9F6 },\n{ \"topt\", 0x9F7 },\n{ \"vertbar\", 0x9F8 },\n{ \"emspace\", 0xAA1 },\n{ \"enspace\", 0xAA2 },\n{ \"em3space\", 0xAA3 },\n{ \"em4space\", 0xAA4 },\n{ \"digitspace\", 0xAA5 },\n{ \"punctspace\", 0xAA6 },\n{ \"thinspace\", 0xAA7 },\n{ \"hairspace\", 0xAA8 },\n{ \"emdash\", 0xAA9 },\n{ \"endash\", 0xAAA },\n{ \"signifblank\", 0xAAC },\n{ \"ellipsis\", 0xAAE },\n{ \"doubbaselinedot\", 0xAAF },\n{ \"onethird\", 0xAB0 },\n{ \"twothirds\", 0xAB1 },\n{ \"onefifth\", 0xAB2 },\n{ \"twofifths\", 0xAB3 },\n{ \"threefifths\", 0xAB4 },\n{ \"fourfifths\", 0xAB5 },\n{ \"onesixth\", 0xAB6 },\n{ \"fivesixths\", 0xAB7 },\n{ \"careof\", 0xAB8 },\n{ \"figdash\", 0xABB },\n{ \"leftanglebracket\", 0xABC },\n{ \"decimalpoint\", 0xABD },\n{ \"rightanglebracket\", 0xABE },\n{ \"marker\", 0xABF },\n{ \"oneeighth\", 0xAC3 },\n{ \"threeeighths\", 0xAC4 },\n{ \"fiveeighths\", 0xAC5 },\n{ \"seveneighths\", 0xAC6 },\n{ \"trademark\", 0xAC9 },\n{ \"signaturemark\", 0xACA },\n{ \"trademarkincircle\", 0xACB },\n{ \"leftopentriangle\", 0xACC },\n{ \"rightopentriangle\", 0xACD },\n{ \"emopencircle\", 0xACE },\n{ \"emopenrectangle\", 0xACF },\n{ \"leftsinglequotemark\", 0xAD0 },\n{ \"rightsinglequotemark\", 0xAD1 },\n{ \"leftdoublequotemark\", 0xAD2 },\n{ \"rightdoublequotemark\", 0xAD3 },\n{ \"prescription\", 0xAD4 },\n{ \"permille\", 0xAD5 },\n{ \"minutes\", 0xAD6 },\n{ \"seconds\", 0xAD7 },\n{ \"latincross\", 0xAD9 },\n{ \"hexagram\", 0xADA },\n{ \"filledrectbullet\", 0xADB },\n{ \"filledlefttribullet\", 0xADC },\n{ \"filledrighttribullet\", 0xADD },\n{ \"emfilledcircle\", 0xADE },\n{ \"emfilledrect\", 0xADF },\n{ \"enopencircbullet\", 0xAE0 },\n{ \"enopensquarebullet\", 0xAE1 },\n{ \"openrectbullet\", 0xAE2 },\n{ \"opentribulletup\", 0xAE3 },\n{ \"opentribulletdown\", 0xAE4 },\n{ \"openstar\", 0xAE5 },\n{ \"enfilledcircbullet\", 0xAE6 },\n{ \"enfilledsqbullet\", 0xAE7 },\n{ \"filledtribulletup\", 0xAE8 },\n{ \"filledtribulletdown\", 0xAE9 },\n{ \"leftpointer\", 0xAEA },\n{ \"rightpointer\", 0xAEB },\n{ \"club\", 0xAEC },\n{ \"diamond\", 0xAED },\n{ \"heart\", 0xAEE },\n{ \"maltesecross\", 0xAF0 },\n{ \"dagger\", 0xAF1 },\n{ \"doubledagger\", 0xAF2 },\n{ \"checkmark\", 0xAF3 },\n{ \"ballotcross\", 0xAF4 },\n{ \"musicalsharp\", 0xAF5 },\n{ \"musicalflat\", 0xAF6 },\n{ \"malesymbol\", 0xAF7 },\n{ \"femalesymbol\", 0xAF8 },\n{ \"telephone\", 0xAF9 },\n{ \"telephonerecorder\", 0xAFA },\n{ \"phonographcopyright\", 0xAFB },\n{ \"caret\", 0xAFC },\n{ \"singlelowquotemark\", 0xAFD },\n{ \"doublelowquotemark\", 0xAFE },\n{ \"cursor\", 0xAFF },\n{ \"leftcaret\", 0xBA3 },\n{ \"rightcaret\", 0xBA6 },\n{ \"downcaret\", 0xBA8 },\n{ \"upcaret\", 0xBA9 },\n{ \"overbar\", 0xBC0 },\n{ \"downtack\", 0xBC2 },\n{ \"upshoe\", 0xBC3 },\n{ \"downstile\", 0xBC4 },\n{ \"underbar\", 0xBC6 },\n{ \"jot\", 0xBCA },\n{ \"quad\", 0xBCC },\n{ \"uptack\", 0xBCE },\n{ \"circle\", 0xBCF },\n{ \"upstile\", 0xBD3 },\n{ \"downshoe\", 0xBD6 },\n{ \"rightshoe\", 0xBD8 },\n{ \"leftshoe\", 0xBDA },\n{ \"lefttack\", 0xBDC },\n{ \"righttack\", 0xBFC },\n{ \"hebrew_doublelowline\", 0xCDF },\n{ \"hebrew_aleph\", 0xCE0 },\n{ \"hebrew_bet\", 0xCE1 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_beth\", 0xCE1 },\n#endif\n{ \"hebrew_gimel\", 0xCE2 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_gimmel\", 0xCE2 },\n#endif\n{ \"hebrew_dalet\", 0xCE3 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_daleth\", 0xCE3 },\n#endif\n{ \"hebrew_he\", 0xCE4 },\n{ \"hebrew_waw\", 0xCE5 },\n{ \"hebrew_zain\", 0xCE6 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_zayin\", 0xCE6 },\n#endif\n{ \"hebrew_chet\", 0xCE7 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_het\", 0xCE7 },\n#endif\n{ \"hebrew_tet\", 0xCE8 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_teth\", 0xCE8 },\n#endif\n{ \"hebrew_yod\", 0xCE9 },\n{ \"hebrew_finalkaph\", 0xCEA },\n{ \"hebrew_kaph\", 0xCEB },\n{ \"hebrew_lamed\", 0xCEC },\n{ \"hebrew_finalmem\", 0xCED },\n{ \"hebrew_mem\", 0xCEE },\n{ \"hebrew_finalnun\", 0xCEF },\n{ \"hebrew_nun\", 0xCF0 },\n{ \"hebrew_samech\", 0xCF1 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_samekh\", 0xCF1 },\n#endif\n{ \"hebrew_ayin\", 0xCF2 },\n{ \"hebrew_finalpe\", 0xCF3 },\n{ \"hebrew_pe\", 0xCF4 },\n{ \"hebrew_finalzade\", 0xCF5 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_finalzadi\", 0xCF5 },\n#endif\n{ \"hebrew_zade\", 0xCF6 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_zadi\", 0xCF6 },\n#endif\n{ \"hebrew_qoph\", 0xCF7 },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_kuf\", 0xCF7 },\n#endif\n{ \"hebrew_resh\", 0xCF8 },\n{ \"hebrew_shin\", 0xCF9 },\n{ \"hebrew_taw\", 0xCFA },\n#ifndef TK_NO_DEPRECATED\n{ \"hebrew_taf\", 0xCFA },\n#endif\n{ \"Thai_kokai\", 0xDA1 },\n{ \"Thai_khokhai\", 0xDA2 },\n{ \"Thai_khokhuat\", 0xDA3 },\n{ \"Thai_khokhwai\", 0xDA4 },\n{ \"Thai_khokhon\", 0xDA5 },\n{ \"Thai_khorakhang\", 0xDA6 },\n{ \"Thai_ngongu\", 0xDA7 },\n{ \"Thai_chochan\", 0xDA8 },\n{ \"Thai_choching\", 0xDA9 },\n{ \"Thai_chochang\", 0xDAA },\n{ \"Thai_soso\", 0xDAB },\n{ \"Thai_chochoe\", 0xDAC },\n{ \"Thai_yoying\", 0xDAD },\n{ \"Thai_dochada\", 0xDAE },\n{ \"Thai_topatak\", 0xDAF },\n{ \"Thai_thothan\", 0xDB0 },\n{ \"Thai_thonangmontho\", 0xDB1 },\n{ \"Thai_thophuthao\", 0xDB2 },\n{ \"Thai_nonen\", 0xDB3 },\n{ \"Thai_dodek\", 0xDB4 },\n{ \"Thai_totao\", 0xDB5 },\n{ \"Thai_thothung\", 0xDB6 },\n{ \"Thai_thothahan\", 0xDB7 },\n{ \"Thai_thothong\", 0xDB8 },\n{ \"Thai_nonu\", 0xDB9 },\n{ \"Thai_bobaimai\", 0xDBA },\n{ \"Thai_popla\", 0xDBB },\n{ \"Thai_phophung\", 0xDBC },\n{ \"Thai_fofa\", 0xDBD },\n{ \"Thai_phophan\", 0xDBE },\n{ \"Thai_fofan\", 0xDBF },\n{ \"Thai_phosamphao\", 0xDC0 },\n{ \"Thai_moma\", 0xDC1 },\n{ \"Thai_yoyak\", 0xDC2 },\n{ \"Thai_rorua\", 0xDC3 },\n{ \"Thai_ru\", 0xDC4 },\n{ \"Thai_loling\", 0xDC5 },\n{ \"Thai_lu\", 0xDC6 },\n{ \"Thai_wowaen\", 0xDC7 },\n{ \"Thai_sosala\", 0xDC8 },\n{ \"Thai_sorusi\", 0xDC9 },\n{ \"Thai_sosua\", 0xDCA },\n{ \"Thai_hohip\", 0xDCB },\n{ \"Thai_lochula\", 0xDCC },\n{ \"Thai_oang\", 0xDCD },\n{ \"Thai_honokhuk\", 0xDCE },\n{ \"Thai_paiyannoi\", 0xDCF },\n{ \"Thai_saraa\", 0xDD0 },\n{ \"Thai_maihanakat\", 0xDD1 },\n{ \"Thai_saraaa\", 0xDD2 },\n{ \"Thai_saraam\", 0xDD3 },\n{ \"Thai_sarai\", 0xDD4 },\n{ \"Thai_saraii\", 0xDD5 },\n{ \"Thai_saraue\", 0xDD6 },\n{ \"Thai_sarauee\", 0xDD7 },\n{ \"Thai_sarau\", 0xDD8 },\n{ \"Thai_sarauu\", 0xDD9 },\n{ \"Thai_phinthu\", 0xDDA },\n{ \"Thai_maihanakat_maitho\", 0xDDE },\n{ \"Thai_baht\", 0xDDF },\n{ \"Thai_sarae\", 0xDE0 },\n{ \"Thai_saraae\", 0xDE1 },\n{ \"Thai_sarao\", 0xDE2 },\n{ \"Thai_saraaimaimuan\", 0xDE3 },\n{ \"Thai_saraaimaimalai\", 0xDE4 },\n{ \"Thai_lakkhangyao\", 0xDE5 },\n{ \"Thai_maiyamok\", 0xDE6 },\n{ \"Thai_maitaikhu\", 0xDE7 },\n{ \"Thai_maiek\", 0xDE8 },\n{ \"Thai_maitho\", 0xDE9 },\n{ \"Thai_maitri\", 0xDEA },\n{ \"Thai_maichattawa\", 0xDEB },\n{ \"Thai_thanthakhat\", 0xDEC },\n{ \"Thai_nikhahit\", 0xDED },\n{ \"Thai_leksun\", 0xDF0 },\n{ \"Thai_leknung\", 0xDF1 },\n{ \"Thai_leksong\", 0xDF2 },\n{ \"Thai_leksam\", 0xDF3 },\n{ \"Thai_leksi\", 0xDF4 },\n{ \"Thai_lekha\", 0xDF5 },\n{ \"Thai_lekhok\", 0xDF6 },\n{ \"Thai_lekchet\", 0xDF7 },\n{ \"Thai_lekpaet\", 0xDF8 },\n{ \"Thai_lekkao\", 0xDF9 },\n{ \"Hangul_Kiyeog\", 0xEA1 },\n{ \"Hangul_SsangKiyeog\", 0xEA2 },\n{ \"Hangul_KiyeogSios\", 0xEA3 },\n{ \"Hangul_Nieun\", 0xEA4 },\n{ \"Hangul_NieunJieuj\", 0xEA5 },\n{ \"Hangul_NieunHieuh\", 0xEA6 },\n{ \"Hangul_Dikeud\", 0xEA7 },\n{ \"Hangul_SsangDikeud\", 0xEA8 },\n{ \"Hangul_Rieul\", 0xEA9 },\n{ \"Hangul_RieulKiyeog\", 0xEAA },\n{ \"Hangul_RieulMieum\", 0xEAB },\n{ \"Hangul_RieulPieub\", 0xEAC },\n{ \"Hangul_RieulSios\", 0xEAD },\n{ \"Hangul_RieulTieut\", 0xEAE },\n{ \"Hangul_RieulPhieuf\", 0xEAF },\n{ \"Hangul_RieulHieuh\", 0xEB0 },\n{ \"Hangul_Mieum\", 0xEB1 },\n{ \"Hangul_Pieub\", 0xEB2 },\n{ \"Hangul_SsangPieub\", 0xEB3 },\n{ \"Hangul_PieubSios\", 0xEB4 },\n{ \"Hangul_Sios\", 0xEB5 },\n{ \"Hangul_SsangSios\", 0xEB6 },\n{ \"Hangul_Ieung\", 0xEB7 },\n{ \"Hangul_Jieuj\", 0xEB8 },\n{ \"Hangul_SsangJieuj\", 0xEB9 },\n{ \"Hangul_Cieuc\", 0xEBA },\n{ \"Hangul_Khieuq\", 0xEBB },\n{ \"Hangul_Tieut\", 0xEBC },\n{ \"Hangul_Phieuf\", 0xEBD },\n{ \"Hangul_Hieuh\", 0xEBE },\n{ \"Hangul_A\", 0xEBF },\n{ \"Hangul_AE\", 0xEC0 },\n{ \"Hangul_YA\", 0xEC1 },\n{ \"Hangul_YAE\", 0xEC2 },\n{ \"Hangul_EO\", 0xEC3 },\n{ \"Hangul_E\", 0xEC4 },\n{ \"Hangul_YEO\", 0xEC5 },\n{ \"Hangul_YE\", 0xEC6 },\n{ \"Hangul_O\", 0xEC7 },\n{ \"Hangul_WA\", 0xEC8 },\n{ \"Hangul_WAE\", 0xEC9 },\n{ \"Hangul_OE\", 0xECA },\n{ \"Hangul_YO\", 0xECB },\n{ \"Hangul_U\", 0xECC },\n{ \"Hangul_WEO\", 0xECD },\n{ \"Hangul_WE\", 0xECE },\n{ \"Hangul_WI\", 0xECF },\n{ \"Hangul_YU\", 0xED0 },\n{ \"Hangul_EU\", 0xED1 },\n{ \"Hangul_YI\", 0xED2 },\n{ \"Hangul_I\", 0xED3 },\n{ \"Hangul_J_Kiyeog\", 0xED4 },\n{ \"Hangul_J_SsangKiyeog\", 0xED5 },\n{ \"Hangul_J_KiyeogSios\", 0xED6 },\n{ \"Hangul_J_Nieun\", 0xED7 },\n{ \"Hangul_J_NieunJieuj\", 0xED8 },\n{ \"Hangul_J_NieunHieuh\", 0xED9 },\n{ \"Hangul_J_Dikeud\", 0xEDA },\n{ \"Hangul_J_Rieul\", 0xEDB },\n{ \"Hangul_J_RieulKiyeog\", 0xEDC },\n{ \"Hangul_J_RieulMieum\", 0xEDD },\n{ \"Hangul_J_RieulPieub\", 0xEDE },\n{ \"Hangul_J_RieulSios\", 0xEDF },\n{ \"Hangul_J_RieulTieut\", 0xEE0 },\n{ \"Hangul_J_RieulPhieuf\", 0xEE1 },\n{ \"Hangul_J_RieulHieuh\", 0xEE2 },\n{ \"Hangul_J_Mieum\", 0xEE3 },\n{ \"Hangul_J_Pieub\", 0xEE4 },\n{ \"Hangul_J_PieubSios\", 0xEE5 },\n{ \"Hangul_J_Sios\", 0xEE6 },\n{ \"Hangul_J_SsangSios\", 0xEE7 },\n{ \"Hangul_J_Ieung\", 0xEE8 },\n{ \"Hangul_J_Jieuj\", 0xEE9 },\n{ \"Hangul_J_Cieuc\", 0xEEA },\n{ \"Hangul_J_Khieuq\", 0xEEB },\n{ \"Hangul_J_Tieut\", 0xEEC },\n{ \"Hangul_J_Phieuf\", 0xEED },\n{ \"Hangul_J_Hieuh\", 0xEEE },\n{ \"Hangul_RieulYeorinHieuh\", 0xEEF },\n{ \"Hangul_SunkyeongeumMieum\", 0xEF0 },\n{ \"Hangul_SunkyeongeumPieub\", 0xEF1 },\n{ \"Hangul_PanSios\", 0xEF2 },\n{ \"Hangul_KkogjiDalrinIeung\", 0xEF3 },\n{ \"Hangul_SunkyeongeumPhieuf\", 0xEF4 },\n{ \"Hangul_YeorinHieuh\", 0xEF5 },\n{ \"Hangul_AraeA\", 0xEF6 },\n{ \"Hangul_AraeAE\", 0xEF7 },\n{ \"Hangul_J_PanSios\", 0xEF8 },\n{ \"Hangul_J_KkogjiDalrinIeung\", 0xEF9 },\n{ \"Hangul_J_YeorinHieuh\", 0xEFA },\n{ \"Korean_Won\", 0xEFF },\n{ \"XF86ModeLock\", 0x1008FF01 },\n{ \"XF86MonBrightnessUp\", 0x1008FF02 },\n{ \"XF86MonBrightnessDown\", 0x1008FF03 },\n{ \"XF86KbdLightOnOff\", 0x1008FF04 },\n{ \"XF86KbdBrightnessUp\", 0x1008FF05 },\n{ \"XF86KbdBrightnessDown\", 0x1008FF06 },\n{ \"XF86MonBrightnessCycle\", 0x1008FF07 },\n{ \"XF86Standby\", 0x1008FF10 },\n{ \"XF86AudioLowerVolume\", 0x1008FF11 },\n{ \"XF86AudioMute\", 0x1008FF12 },\n{ \"XF86AudioRaiseVolume\", 0x1008FF13 },\n{ \"XF86AudioPlay\", 0x1008FF14 },\n{ \"XF86AudioStop\", 0x1008FF15 },\n{ \"XF86AudioPrev\", 0x1008FF16 },\n{ \"XF86AudioNext\", 0x1008FF17 },\n{ \"XF86HomePage\", 0x1008FF18 },\n{ \"XF86Mail\", 0x1008FF19 },\n{ \"XF86Start\", 0x1008FF1A },\n{ \"XF86Search\", 0x1008FF1B },\n{ \"XF86AudioRecord\", 0x1008FF1C },\n{ \"XF86Calculator\", 0x1008FF1D },\n{ \"XF86Memo\", 0x1008FF1E },\n{ \"XF86ToDoList\", 0x1008FF1F },\n{ \"XF86Calendar\", 0x1008FF20 },\n{ \"XF86PowerDown\", 0x1008FF21 },\n{ \"XF86ContrastAdjust\", 0x1008FF22 },\n{ \"XF86RockerUp\", 0x1008FF23 },\n{ \"XF86RockerDown\", 0x1008FF24 },\n{ \"XF86RockerEnter\", 0x1008FF25 },\n{ \"XF86Back\", 0x1008FF26 },\n{ \"XF86Forward\", 0x1008FF27 },\n{ \"XF86Stop\", 0x1008FF28 },\n{ \"XF86Refresh\", 0x1008FF29 },\n{ \"XF86PowerOff\", 0x1008FF2A },\n{ \"XF86WakeUp\", 0x1008FF2B },\n{ \"XF86Eject\", 0x1008FF2C },\n{ \"XF86ScreenSaver\", 0x1008FF2D },\n{ \"XF86WWW\", 0x1008FF2E },\n{ \"XF86Sleep\", 0x1008FF2F },\n{ \"XF86Favorites\", 0x1008FF30 },\n{ \"XF86AudioPause\", 0x1008FF31 },\n{ \"XF86AudioMedia\", 0x1008FF32 },\n{ \"XF86MyComputer\", 0x1008FF33 },\n{ \"XF86VendorHome\", 0x1008FF34 },\n{ \"XF86LightBulb\", 0x1008FF35 },\n{ \"XF86Shop\", 0x1008FF36 },\n{ \"XF86History\", 0x1008FF37 },\n{ \"XF86OpenURL\", 0x1008FF38 },\n{ \"XF86AddFavorite\", 0x1008FF39 },\n{ \"XF86HotLinks\", 0x1008FF3A },\n{ \"XF86BrightnessAdjust\", 0x1008FF3B },\n{ \"XF86Finance\", 0x1008FF3C },\n{ \"XF86Community\", 0x1008FF3D },\n{ \"XF86AudioRewind\", 0x1008FF3E },\n{ \"XF86BackForward\", 0x1008FF3F },\n{ \"XF86Launch0\", 0x1008FF40 },\n{ \"XF86Launch1\", 0x1008FF41 },\n{ \"XF86Launch2\", 0x1008FF42 },\n{ \"XF86Launch3\", 0x1008FF43 },\n{ \"XF86Launch4\", 0x1008FF44 },\n{ \"XF86Launch5\", 0x1008FF45 },\n{ \"XF86Launch6\", 0x1008FF46 },\n{ \"XF86Launch7\", 0x1008FF47 },\n{ \"XF86Launch8\", 0x1008FF48 },\n{ \"XF86Launch9\", 0x1008FF49 },\n{ \"XF86LaunchA\", 0x1008FF4A },\n{ \"XF86LaunchB\", 0x1008FF4B },\n{ \"XF86LaunchC\", 0x1008FF4C },\n{ \"XF86LaunchD\", 0x1008FF4D },\n{ \"XF86LaunchE\", 0x1008FF4E },\n{ \"XF86LaunchF\", 0x1008FF4F },\n{ \"XF86ApplicationLeft\", 0x1008FF50 },\n{ \"XF86ApplicationRight\", 0x1008FF51 },\n{ \"XF86Book\", 0x1008FF52 },\n{ \"XF86CD\", 0x1008FF53 },\n{ \"XF86Calculater\", 0x1008FF54 },\n{ \"XF86Clear\", 0x1008FF55 },\n{ \"XF86Close\", 0x1008FF56 },\n{ \"XF86Copy\", 0x1008FF57 },\n{ \"XF86Cut\", 0x1008FF58 },\n{ \"XF86Display\", 0x1008FF59 },\n{ \"XF86DOS\", 0x1008FF5A },\n{ \"XF86Documents\", 0x1008FF5B },\n{ \"XF86Excel\", 0x1008FF5C },\n{ \"XF86Explorer\", 0x1008FF5D },\n{ \"XF86Game\", 0x1008FF5E },\n{ \"XF86Go\", 0x1008FF5F },\n{ \"XF86iTouch\", 0x1008FF60 },\n{ \"XF86LogOff\", 0x1008FF61 },\n{ \"XF86Market\", 0x1008FF62 },\n{ \"XF86Meeting\", 0x1008FF63 },\n{ \"XF86MenuKB\", 0x1008FF65 },\n{ \"XF86MenuPB\", 0x1008FF66 },\n{ \"XF86MySites\", 0x1008FF67 },\n{ \"XF86New\", 0x1008FF68 },\n{ \"XF86News\", 0x1008FF69 },\n{ \"XF86OfficeHome\", 0x1008FF6A },\n{ \"XF86Open\", 0x1008FF6B },\n{ \"XF86Option\", 0x1008FF6C },\n{ \"XF86Paste\", 0x1008FF6D },\n{ \"XF86Phone\", 0x1008FF6E },\n{ \"XF86Q\", 0x1008FF70 },\n{ \"XF86Reply\", 0x1008FF72 },\n{ \"XF86Reload\", 0x1008FF73 },\n{ \"XF86RotateWindows\", 0x1008FF74 },\n{ \"XF86RotationPB\", 0x1008FF75 },\n{ \"XF86RotationKB\", 0x1008FF76 },\n{ \"XF86Save\", 0x1008FF77 },\n{ \"XF86ScrollUp\", 0x1008FF78 },\n{ \"XF86ScrollDown\", 0x1008FF79 },\n{ \"XF86ScrollClick\", 0x1008FF7A },\n{ \"XF86Send\", 0x1008FF7B },\n{ \"XF86Spell\", 0x1008FF7C },\n{ \"XF86SplitScreen\", 0x1008FF7D },\n{ \"XF86Support\", 0x1008FF7E },\n{ \"XF86TaskPane\", 0x1008FF7F },\n{ \"XF86Terminal\", 0x1008FF80 },\n{ \"XF86Tools\", 0x1008FF81 },\n{ \"XF86Travel\", 0x1008FF82 },\n{ \"XF86UserPB\", 0x1008FF84 },\n{ \"XF86User1KB\", 0x1008FF85 },\n{ \"XF86User2KB\", 0x1008FF86 },\n{ \"XF86Video\", 0x1008FF87 },\n{ \"XF86WheelButton\", 0x1008FF88 },\n{ \"XF86Word\", 0x1008FF89 },\n{ \"XF86Xfer\", 0x1008FF8A },\n{ \"XF86ZoomIn\", 0x1008FF8B },\n{ \"XF86ZoomOut\", 0x1008FF8C },\n{ \"XF86Away\", 0x1008FF8D },\n{ \"XF86Messenger\", 0x1008FF8E },\n{ \"XF86WebCam\", 0x1008FF8F },\n{ \"XF86MailForward\", 0x1008FF90 },\n{ \"XF86Pictures\", 0x1008FF91 },\n{ \"XF86Music\", 0x1008FF92 },\n{ \"XF86Battery\", 0x1008FF93 },\n{ \"XF86Bluetooth\", 0x1008FF94 },\n{ \"XF86WLAN\", 0x1008FF95 },\n{ \"XF86UWB\", 0x1008FF96 },\n{ \"XF86AudioForward\", 0x1008FF97 },\n{ \"XF86AudioRepeat\", 0x1008FF98 },\n{ \"XF86AudioRandomPlay\", 0x1008FF99 },\n{ \"XF86Subtitle\", 0x1008FF9A },\n{ \"XF86AudioCycleTrack\", 0x1008FF9B },\n{ \"XF86CycleAngle\", 0x1008FF9C },\n{ \"XF86FrameBack\", 0x1008FF9D },\n{ \"XF86FrameForward\", 0x1008FF9E },\n{ \"XF86Time\", 0x1008FF9F },\n{ \"XF86Select\", 0x1008FFA0 },\n{ \"XF86View\", 0x1008FFA1 },\n{ \"XF86TopMenu\", 0x1008FFA2 },\n{ \"XF86Red\", 0x1008FFA3 },\n{ \"XF86Green\", 0x1008FFA4 },\n{ \"XF86Yellow\", 0x1008FFA5 },\n{ \"XF86Blue\", 0x1008FFA6 },\n{ \"XF86Suspend\", 0x1008FFA7 },\n{ \"XF86Hibernate\", 0x1008FFA8 },\n{ \"XF86TouchpadToggle\", 0x1008FFA9 },\n{ \"XF86TouchpadOn\", 0x1008FFB0 },\n{ \"XF86TouchpadOff\", 0x1008FFB1 },\n{ \"XF86AudioMicMute\", 0x1008FFB2 },\n{ \"XF86Keyboard\", 0x1008FFB3 },\n{ \"XF86WWAN\", 0x1008FFB4 },\n{ \"XF86RFKill\", 0x1008FFB5 },\n{ \"XF86AudioPreset\", 0x1008FFB6 },\n{ \"XF86RotationLockToggle\", 0x1008FFB7 },\n{ \"XF86FullScreen\", 0x1008FFB8 },\n{ \"XF86Switch_VT_1\", 0x1008FE01 },\n{ \"XF86Switch_VT_2\", 0x1008FE02 },\n{ \"XF86Switch_VT_3\", 0x1008FE03 },\n{ \"XF86Switch_VT_4\", 0x1008FE04 },\n{ \"XF86Switch_VT_5\", 0x1008FE05 },\n{ \"XF86Switch_VT_6\", 0x1008FE06 },\n{ \"XF86Switch_VT_7\", 0x1008FE07 },\n{ \"XF86Switch_VT_8\", 0x1008FE08 },\n{ \"XF86Switch_VT_9\", 0x1008FE09 },\n{ \"XF86Switch_VT_10\", 0x1008FE0A },\n{ \"XF86Switch_VT_11\", 0x1008FE0B },\n{ \"XF86Switch_VT_12\", 0x1008FE0C },\n{ \"XF86Ungrab\", 0x1008FE20 },\n{ \"XF86ClearGrab\", 0x1008FE21 },\n{ \"XF86Next_VMode\", 0x1008FE22 },\n{ \"XF86Prev_VMode\", 0x1008FE23 },\n{ \"XF86LogWindowTree\", 0x1008FE24 },\n{ \"XF86LogGrabInfo\", 0x1008FE25 },\n{ \"XF86BrightnessAuto\", 0x100810F4 },\n{ \"XF86DisplayOff\", 0x100810F5 },\n{ \"XF86Info\", 0x10081166 },\n{ \"XF86AspectRatio\", 0x10081177 },\n{ \"XF86DVD\", 0x10081185 },\n{ \"XF86Audio\", 0x10081188 },\n{ \"XF86ChannelUp\", 0x10081192 },\n{ \"XF86ChannelDown\", 0x10081193 },\n{ \"XF86Break\", 0x1008119B },\n{ \"XF86VideoPhone\", 0x100811A0 },\n{ \"XF86ZoomReset\", 0x100811A4 },\n{ \"XF86Editor\", 0x100811A6 },\n{ \"XF86GraphicsEditor\", 0x100811A8 },\n{ \"XF86Presentation\", 0x100811A9 },\n{ \"XF86Database\", 0x100811AA },\n{ \"XF86Voicemail\", 0x100811AC },\n{ \"XF86Addressbook\", 0x100811AD },\n{ \"XF86DisplayToggle\", 0x100811AF },\n{ \"XF86SpellCheck\", 0x100811B0 },\n{ \"XF86ContextMenu\", 0x100811B6 },\n{ \"XF86MediaRepeat\", 0x100811B7 },\n{ \"XF8610ChannelsUp\", 0x100811B8 },\n{ \"XF8610ChannelsDown\", 0x100811B9 },\n{ \"XF86Images\", 0x100811BA },\n{ \"XF86NotificationCenter\", 0x100811BC },\n{ \"XF86PickupPhone\", 0x100811BD },\n{ \"XF86HangupPhone\", 0x100811BE },\n{ \"XF86Fn\", 0x100811D0 },\n{ \"XF86Fn_Esc\", 0x100811D1 },\n{ \"XF86FnRightShift\", 0x100811E5 },\n{ \"XF86Numeric0\", 0x10081200 },\n{ \"XF86Numeric1\", 0x10081201 },\n{ \"XF86Numeric2\", 0x10081202 },\n{ \"XF86Numeric3\", 0x10081203 },\n{ \"XF86Numeric4\", 0x10081204 },\n{ \"XF86Numeric5\", 0x10081205 },\n{ \"XF86Numeric6\", 0x10081206 },\n{ \"XF86Numeric7\", 0x10081207 },\n{ \"XF86Numeric8\", 0x10081208 },\n{ \"XF86Numeric9\", 0x10081209 },\n{ \"XF86NumericStar\", 0x1008120A },\n{ \"XF86NumericPound\", 0x1008120B },\n{ \"XF86NumericA\", 0x1008120C },\n{ \"XF86NumericB\", 0x1008120D },\n{ \"XF86NumericC\", 0x1008120E },\n{ \"XF86NumericD\", 0x1008120F },\n{ \"XF86CameraFocus\", 0x10081210 },\n{ \"XF86WPSButton\", 0x10081211 },\n{ \"XF86CameraZoomIn\", 0x10081215 },\n{ \"XF86CameraZoomOut\", 0x10081216 },\n{ \"XF86CameraUp\", 0x10081217 },\n{ \"XF86CameraDown\", 0x10081218 },\n{ \"XF86CameraLeft\", 0x10081219 },\n{ \"XF86CameraRight\", 0x1008121A },\n{ \"XF86AttendantOn\", 0x1008121B },\n{ \"XF86AttendantOff\", 0x1008121C },\n{ \"XF86AttendantToggle\", 0x1008121D },\n{ \"XF86LightsToggle\", 0x1008121E },\n{ \"XF86ALSToggle\", 0x10081230 },\n{ \"XF86Buttonconfig\", 0x10081240 },\n{ \"XF86Taskmanager\", 0x10081241 },\n{ \"XF86Journal\", 0x10081242 },\n{ \"XF86ControlPanel\", 0x10081243 },\n{ \"XF86AppSelect\", 0x10081244 },\n{ \"XF86Screensaver\", 0x10081245 },\n{ \"XF86VoiceCommand\", 0x10081246 },\n{ \"XF86Assistant\", 0x10081247 },\n{ \"XF86EmojiPicker\", 0x10081249 },\n{ \"XF86Dictate\", 0x1008124A },\n{ \"XF86BrightnessMin\", 0x10081250 },\n{ \"XF86BrightnessMax\", 0x10081251 },\n{ \"XF86KbdInputAssistPrev\", 0x10081260 },\n{ \"XF86KbdInputAssistNext\", 0x10081261 },\n{ \"XF86KbdInputAssistPrevgroup\", 0x10081262 },\n{ \"XF86KbdInputAssistNextgroup\", 0x10081263 },\n{ \"XF86KbdInputAssistAccept\", 0x10081264 },\n{ \"XF86KbdInputAssistCancel\", 0x10081265 },\n{ \"XF86RightUp\", 0x10081266 },\n{ \"XF86RightDown\", 0x10081267 },\n{ \"XF86LeftUp\", 0x10081268 },\n{ \"XF86LeftDown\", 0x10081269 },\n{ \"XF86RootMenu\", 0x1008126A },\n{ \"XF86MediaTopMenu\", 0x1008126B },\n{ \"XF86Numeric11\", 0x1008126C },\n{ \"XF86Numeric12\", 0x1008126D },\n{ \"XF86AudioDesc\", 0x1008126E },\n{ \"XF863DMode\", 0x1008126F },\n{ \"XF86NextFavorite\", 0x10081270 },\n{ \"XF86StopRecord\", 0x10081271 },\n{ \"XF86PauseRecord\", 0x10081272 },\n{ \"XF86VOD\", 0x10081273 },\n{ \"XF86Unmute\", 0x10081274 },\n{ \"XF86FastReverse\", 0x10081275 },\n{ \"XF86SlowReverse\", 0x10081276 },\n{ \"XF86Data\", 0x10081277 },\n{ \"XF86OnScreenKeyboard\", 0x10081278 },\n{ \"XF86PrivacyScreenToggle\", 0x10081279 },\n{ \"XF86SelectiveScreenshot\", 0x1008127A },\n{ \"XF86Macro1\", 0x10081290 },\n{ \"XF86Macro2\", 0x10081291 },\n{ \"XF86Macro3\", 0x10081292 },\n{ \"XF86Macro4\", 0x10081293 },\n{ \"XF86Macro5\", 0x10081294 },\n{ \"XF86Macro6\", 0x10081295 },\n{ \"XF86Macro7\", 0x10081296 },\n{ \"XF86Macro8\", 0x10081297 },\n{ \"XF86Macro9\", 0x10081298 },\n{ \"XF86Macro10\", 0x10081299 },\n{ \"XF86Macro11\", 0x1008129A },\n{ \"XF86Macro12\", 0x1008129B },\n{ \"XF86Macro13\", 0x1008129C },\n{ \"XF86Macro14\", 0x1008129D },\n{ \"XF86Macro15\", 0x1008129E },\n{ \"XF86Macro16\", 0x1008129F },\n{ \"XF86Macro17\", 0x100812A0 },\n{ \"XF86Macro18\", 0x100812A1 },\n{ \"XF86Macro19\", 0x100812A2 },\n{ \"XF86Macro20\", 0x100812A3 },\n{ \"XF86Macro21\", 0x100812A4 },\n{ \"XF86Macro22\", 0x100812A5 },\n{ \"XF86Macro23\", 0x100812A6 },\n{ \"XF86Macro24\", 0x100812A7 },\n{ \"XF86Macro25\", 0x100812A8 },\n{ \"XF86Macro26\", 0x100812A9 },\n{ \"XF86Macro27\", 0x100812AA },\n{ \"XF86Macro28\", 0x100812AB },\n{ \"XF86Macro29\", 0x100812AC },\n{ \"XF86Macro30\", 0x100812AD },\n{ \"XF86MacroRecordStart\", 0x100812B0 },\n{ \"XF86MacroRecordStop\", 0x100812B1 },\n{ \"XF86MacroPresetCycle\", 0x100812B2 },\n{ \"XF86MacroPreset1\", 0x100812B3 },\n{ \"XF86MacroPreset2\", 0x100812B4 },\n{ \"XF86MacroPreset3\", 0x100812B5 },\n{ \"XF86KbdLcdMenu1\", 0x100812B8 },\n{ \"XF86KbdLcdMenu2\", 0x100812B9 },\n{ \"XF86KbdLcdMenu3\", 0x100812BA },\n{ \"XF86KbdLcdMenu4\", 0x100812BB },\n{ \"XF86KbdLcdMenu5\", 0x100812BC },\n{ \"SunFA_Grave\", 0x1005FF00 },\n{ \"SunFA_Circum\", 0x1005FF01 },\n{ \"SunFA_Tilde\", 0x1005FF02 },\n{ \"SunFA_Acute\", 0x1005FF03 },\n{ \"SunFA_Diaeresis\", 0x1005FF04 },\n{ \"SunFA_Cedilla\", 0x1005FF05 },\n{ \"SunF36\", 0x1005FF10 },\n{ \"SunF37\", 0x1005FF11 },\n{ \"SunSys_Req\", 0x1005FF60 },\n{ \"SunProps\", 0x1005FF70 },\n{ \"SunFront\", 0x1005FF71 },\n{ \"SunCopy\", 0x1005FF72 },\n{ \"SunOpen\", 0x1005FF73 },\n{ \"SunPaste\", 0x1005FF74 },\n{ \"SunCut\", 0x1005FF75 },\n{ \"SunPowerSwitch\", 0x1005FF76 },\n{ \"SunAudioLowerVolume\", 0x1005FF77 },\n{ \"SunAudioMute\", 0x1005FF78 },\n{ \"SunAudioRaiseVolume\", 0x1005FF79 },\n{ \"SunVideoDegauss\", 0x1005FF7A },\n{ \"SunVideoLowerBrightness\", 0x1005FF7B },\n{ \"SunVideoRaiseBrightness\", 0x1005FF7C },\n{ \"SunPowerSwitchShift\", 0x1005FF7D },\n"
  },
  {
    "path": "generic/nanosvg.h",
    "content": "/*\n * Copyright (c) 2013-14 Mikko Mononen memon@inside.org\n *\n * This software is provided 'as-is', without any express or implied\n * warranty.  In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you must not\n * claim that you wrote the original software. If you use this software\n * in a product, an acknowledgment in the product documentation would be\n * appreciated but is not required.\n * 2. Altered source versions must be plainly marked as such, and must not be\n * misrepresented as being the original software.\n * 3. This notice may not be removed or altered from any source distribution.\n *\n * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example\n * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)\n *\n * Arc calculation code based on canvg (https://code.google.com/p/canvg/)\n *\n * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html\n *\n */\n\n#ifndef NANOSVG_H\n#define NANOSVG_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.\n *\n * The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.\n *\n * NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!\n *\n * The shapes in the SVG images are transformed by the viewBox and converted to specified units.\n * That is, you should get the same looking data as your designed in your favorite app.\n *\n * NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose\n * to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.\n *\n * The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.\n * DPI (dots-per-inch) controls how the unit conversion is done.\n *\n * If you don't know or care about the units stuff, \"px\" and 96 should get you going.\n */\n\n\n/* Example Usage:\n\t// Load SVG\n\tNSVGimage* image;\n\timage = nsvgParseFromFile(\"test.svg\", \"px\", 96);\n\tprintf(\"size: %f x %f\\n\", image->width, image->height);\n\t// Use...\n\tfor (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {\n\t\tfor (NSVGpath *path = shape->paths; path != NULL; path = path->next) {\n\t\t\tfor (int i = 0; i < path->npts-1; i += 3) {\n\t\t\t\tfloat* p = &path->pts[i*2];\n\t\t\t\tdrawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);\n\t\t\t}\n\t\t}\n\t}\n\t// Delete\n\tnsvgDelete(image);\n*/\n\n#ifndef NANOSVG_SCOPE\n#define NANOSVG_SCOPE\n#endif\n\n#ifndef NANOSVG_malloc\n#define NANOSVG_malloc malloc\n#endif\n\n#ifndef NANOSVG_realloc\n#define NANOSVG_realloc realloc\n#endif\n\n#ifndef NANOSVG_free\n#define NANOSVG_free free\n#endif\n\n/* float emulation for MS VC6++ compiler */\n#if defined(_MSC_VER) && (_MSC_VER == 1200)\n#define tanf(a) (float)tan(a)\n#define cosf(a) (float)cos(a)\n#define sinf(a) (float)sin(a)\n#define sqrtf(a) (float)sqrt(a)\n#define fabsf(a) (float)fabs(a)\n#define acosf(a) (float)acos(a)\n#define atan2f(a,b) (float)atan2(a,b)\n#define ceilf(a) (float)ceil(a)\n#define fmodf(a,b) (float)fmod(a,b)\n#define floorf(a) (float)floor(a)\n#endif\n/* float emulation for MS VC8++ compiler */\n#if defined(_MSC_VER) && (_MSC_VER == 1400)\n#define fabsf(a) (float)fabs(a)\n#endif\n\nenum NSVGpaintType {\n\tNSVG_PAINT_UNDEF = -1,\n\tNSVG_PAINT_NONE = 0,\n\tNSVG_PAINT_COLOR = 1,\n\tNSVG_PAINT_LINEAR_GRADIENT = 2,\n\tNSVG_PAINT_RADIAL_GRADIENT = 3\n};\n\nenum NSVGspreadType {\n\tNSVG_SPREAD_PAD = 0,\n\tNSVG_SPREAD_REFLECT = 1,\n\tNSVG_SPREAD_REPEAT = 2\n};\n\nenum NSVGlineJoin {\n\tNSVG_JOIN_MITER = 0,\n\tNSVG_JOIN_ROUND = 1,\n\tNSVG_JOIN_BEVEL = 2\n};\n\nenum NSVGlineCap {\n\tNSVG_CAP_BUTT = 0,\n\tNSVG_CAP_ROUND = 1,\n\tNSVG_CAP_SQUARE = 2\n};\n\nenum NSVGfillRule {\n\tNSVG_FILLRULE_NONZERO = 0,\n\tNSVG_FILLRULE_EVENODD = 1\n};\n\nenum NSVGflags {\n\tNSVG_FLAGS_VISIBLE = 0x01\n};\n\nenum NSVGpaintOrder {\n\tNSVG_PAINT_FILL = 0x00,\n\tNSVG_PAINT_MARKERS = 0x01,\n\tNSVG_PAINT_STROKE = 0x02\n};\n\ntypedef struct NSVGgradientStop {\n\tunsigned int color;\n\tfloat offset;\n} NSVGgradientStop;\n\ntypedef struct NSVGgradient {\n\tfloat xform[6];\n\tchar spread;\n\tfloat fx, fy;\n\tint nstops;\n\tNSVGgradientStop stops[1];\n} NSVGgradient;\n\ntypedef struct NSVGpaint {\n\tsigned char type;\n\tunion {\n\t\tunsigned int color;\n\t\tNSVGgradient* gradient;\n\t};\n} NSVGpaint;\n\ntypedef struct NSVGpath\n{\n\tfloat* pts;\t\t\t\t\t/* Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... */\n\tint npts;\t\t\t\t\t/* Total number of bezier points. */\n\tchar closed;\t\t\t\t/* Flag indicating if shapes should be treated as closed. */\n\tfloat bounds[4];\t\t\t/* Tight bounding box of the shape [minx,miny,maxx,maxy]. */\n\tstruct NSVGpath* next;\t\t/* Pointer to next path, or NULL if last element. */\n} NSVGpath;\n\ntypedef struct NSVGshape\n{\n\tchar id[64];\t\t\t\t/* Optional 'id' attr of the shape or its group */\n\tNSVGpaint fill;\t\t\t\t/* Fill paint */\n\tNSVGpaint stroke;\t\t\t/* Stroke paint */\n\tfloat opacity;\t\t\t\t/* Opacity of the shape. */\n\tfloat strokeWidth;\t\t\t/* Stroke width (scaled). */\n\tfloat strokeDashOffset;\t\t/* Stroke dash offset (scaled). */\n\tfloat strokeDashArray[8];\t/* Stroke dash array (scaled). */\n\tchar strokeDashCount;\t\t/* Number of dash values in dash array. */\n\tchar strokeLineJoin;\t\t/* Stroke join type. */\n\tchar strokeLineCap;\t\t\t/* Stroke cap type. */\n\tfloat miterLimit;\t\t\t/* Miter limit */\n\tchar fillRule;\t\t\t\t/* Fill rule, see NSVGfillRule. */\n\tunsigned char paintOrder;\t/* Encoded paint order (3×2-bit fields) see NSVGpaintOrder */\n\tunsigned char flags;\t\t/* Logical or of NSVG_FLAGS_* flags */\n\tfloat bounds[4];\t\t\t/* Tight bounding box of the shape [minx,miny,maxx,maxy]. */\n\tchar fillGradient[64];\t\t// Optional 'id' of fill gradient\n\tchar strokeGradient[64];\t// Optional 'id' of stroke gradient\n\tfloat xform[6];\t\t\t\t// Root transformation for fill/stroke gradient\n\tNSVGpath* paths;\t\t\t/* Linked list of paths in the image. */\n\tstruct NSVGshape* next;\t\t/* Pointer to next shape, or NULL if last element. */\n} NSVGshape;\n\ntypedef struct NSVGimage\n{\n\tfloat width;\t\t\t\t/* Width of the image. */\n\tfloat height;\t\t\t\t/* Height of the image. */\n\tNSVGshape* shapes;\t\t\t/* Linked list of shapes in the image. */\n} NSVGimage;\n\n/* Parses SVG file from a file, returns SVG image as paths. */\nNANOSVG_SCOPE NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);\n\n/* Parses SVG file from a null terminated string, returns SVG image as paths. */\n/* Important note: changes the string. */\nNANOSVG_SCOPE NSVGimage* nsvgParse(char* input, const char* units, float dpi);\n\n/* Deletes list of paths. */\nNANOSVG_SCOPE void nsvgDelete(NSVGimage* image);\n\n#ifdef __cplusplus\n}\n#endif\n\n#ifdef NANOSVG_IMPLEMENTATION\n\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <math.h>\n\n#define NSVG_PI (3.14159265358979323846264338327f)\n#define NSVG_KAPPA90 (0.5522847493f)\t/* Length proportional to radius of a cubic bezier handle for 90deg arcs. */\n\n#define NSVG_ALIGN_MIN 0\n#define NSVG_ALIGN_MID 1\n#define NSVG_ALIGN_MAX 2\n#define NSVG_ALIGN_NONE 0\n#define NSVG_ALIGN_MEET 1\n#define NSVG_ALIGN_SLICE 2\n\n#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)\n#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))\n\n#ifdef _MSC_VER\n\t#pragma warning (disable: 4996) /* Switch off security warnings */\n\t#pragma warning (disable: 4100) /* Switch off unreferenced formal parameter warnings */\n\t#ifdef __cplusplus\n\t#define NSVG_INLINE inline\n\t#else\n\t#define NSVG_INLINE\n\t#endif\n\t#if !defined(strtoll)           /* old MSVC versions do not have strtoll() */\n\t\t#define strtoll _strtoi64\n\t#endif\n#else\n\t#define NSVG_INLINE inline\n#endif\n\n\nstatic int nsvg__isspace(char c)\n{\n\treturn strchr(\" \\t\\n\\v\\f\\r\", c) != 0;\n}\n\nstatic int nsvg__isdigit(char c)\n{\n\treturn c >= '0' && c <= '9';\n}\n\nstatic NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }\nstatic NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }\n\n\n/* Simple XML parser */\n\n#define NSVG_XML_TAG 1\n#define NSVG_XML_CONTENT 2\n#define NSVG_XML_MAX_ATTRIBS 256\n\nstatic void nsvg__parseContent(char* s,\n\t\t\t\t\t\t\t   void (*contentCb)(void* ud, const char* s),\n\t\t\t\t\t\t\t   void* ud)\n{\n\t/* Trim start white spaces */\n\twhile (*s && nsvg__isspace(*s)) s++;\n\tif (!*s) return;\n\n\tif (contentCb)\n\t\t(*contentCb)(ud, s);\n}\n\nstatic void nsvg__parseElement(char* s,\n\t\t\t\t\t\t\t   void (*startelCb)(void* ud, const char* el, const char** attr),\n\t\t\t\t\t\t\t   void (*endelCb)(void* ud, const char* el),\n\t\t\t\t\t\t\t   void* ud)\n{\n\tconst char* attr[NSVG_XML_MAX_ATTRIBS];\n\tint nattr = 0;\n\tchar* cbname;\n\tint start = 0;\n\tint end = 0;\n\tchar quote;\n\n\t/* Skip white space after the '<' */\n\twhile (*s && nsvg__isspace(*s)) s++;\n\n\t/* Check if the tag is end tag */\n\tif (*s == '/') {\n\t\ts++;\n\t\tend = 1;\n\t} else {\n\t\tstart = 1;\n\t}\n\n\t/* Skip comments, data and preprocessor stuff. */\n\tif (!*s || *s == '?' || *s == '!')\n\t\treturn;\n\n\t/* Get tag name */\n\tcbname = s;\n\twhile (*s && !nsvg__isspace(*s)) s++;\n\tif (*s) { *s++ = '\\0'; }\n\n\t/* Get attribs */\n\twhile (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {\n\t\tchar* name = NULL;\n\t\tchar* value = NULL;\n\n\t\t/* Skip white space before the attrib name */\n\t\twhile (*s && nsvg__isspace(*s)) s++;\n\t\tif (!*s) break;\n\t\tif (*s == '/') {\n\t\t\tend = 1;\n\t\t\tbreak;\n\t\t}\n\t\tname = s;\n\t\t/* Find end of the attrib name. */\n\t\twhile (*s && !nsvg__isspace(*s) && *s != '=') s++;\n\t\tif (*s) { *s++ = '\\0'; }\n\t\t/* Skip until the beginning of the value. */\n\t\twhile (*s && *s != '\\\"' && *s != '\\'') s++;\n\t\tif (!*s) break;\n\t\tquote = *s;\n\t\ts++;\n\t\t/* Store value and find the end of it. */\n\t\tvalue = s;\n\t\twhile (*s && *s != quote) s++;\n\t\tif (*s) { *s++ = '\\0'; }\n\n\t\t/* Store only well formed attributes */\n\t\tif (name && value) {\n\t\t\tattr[nattr++] = name;\n\t\t\tattr[nattr++] = value;\n\t\t}\n\t}\n\n\t/* List terminator */\n\tattr[nattr++] = 0;\n\tattr[nattr++] = 0;\n\n\t/* Call callbacks. */\n\tif (start && startelCb)\n\t\t(*startelCb)(ud, cbname, attr);\n\tif (end && endelCb)\n\t\t(*endelCb)(ud, cbname);\n}\n\nNANOSVG_SCOPE\nint nsvg__parseXML(char* input,\n\t\t\t\t   void (*startelCb)(void* ud, const char* el, const char** attr),\n\t\t\t\t   void (*endelCb)(void* ud, const char* el),\n\t\t\t\t   void (*contentCb)(void* ud, const char* s),\n\t\t\t\t   void* ud)\n{\n\tchar* s = input;\n\tchar* mark = s;\n\tint state = NSVG_XML_CONTENT;\n\twhile (*s) {\n\t\tif (*s == '<' && state == NSVG_XML_CONTENT) {\n\t\t\t/* Start of a tag */\n\t\t\t*s++ = '\\0';\n\t\t\tnsvg__parseContent(mark, contentCb, ud);\n\t\t\tmark = s;\n\t\t\tstate = NSVG_XML_TAG;\n\t\t} else if (*s == '>' && state == NSVG_XML_TAG) {\n\t\t\t/* Start of a content or new tag. */\n\t\t\t*s++ = '\\0';\n\t\t\tnsvg__parseContent(mark, contentCb, ud);\n\t\t\tnsvg__parseElement(mark, startelCb, endelCb, ud);\n\t\t\tmark = s;\n\t\t\tstate = NSVG_XML_CONTENT;\n\t\t} else {\n\t\t\ts++;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\n\n/* Simple SVG parser. */\n\n#define NSVG_MAX_ATTR 128\n\nenum NSVGgradientUnits {\n\tNSVG_USER_SPACE = 0,\n\tNSVG_OBJECT_SPACE = 1\n};\n\n#define NSVG_MAX_DASHES 8\n\nenum NSVGunits {\n\tNSVG_UNITS_USER,\n\tNSVG_UNITS_PX,\n\tNSVG_UNITS_PT,\n\tNSVG_UNITS_PC,\n\tNSVG_UNITS_MM,\n\tNSVG_UNITS_CM,\n\tNSVG_UNITS_IN,\n\tNSVG_UNITS_PERCENT,\n\tNSVG_UNITS_EM,\n\tNSVG_UNITS_EX\n};\n\nenum NSVGvisible {\n\tNSVG_VIS_DISPLAY = 1,\n\tNSVG_VIS_VISIBLE = 2\n};\n\ntypedef struct NSVGcoordinate {\n\tfloat value;\n\tint units;\n} NSVGcoordinate;\n\ntypedef struct NSVGlinearData {\n\tNSVGcoordinate x1, y1, x2, y2;\n} NSVGlinearData;\n\ntypedef struct NSVGradialData {\n\tNSVGcoordinate cx, cy, r, fx, fy;\n} NSVGradialData;\n\ntypedef struct NSVGgradientData\n{\n\tchar id[64];\n\tchar ref[64];\n\tsigned char type;\n\tunion {\n\t\tNSVGlinearData linear;\n\t\tNSVGradialData radial;\n\t};\n\tchar spread;\n\tchar units;\n\tfloat xform[6];\n\tint nstops;\n\tNSVGgradientStop* stops;\n\tstruct NSVGgradientData* next;\n} NSVGgradientData;\n\ntypedef struct NSVGattrib\n{\n\tchar id[64];\n\tfloat xform[6];\n\tunsigned int fillColor;\n\tunsigned int strokeColor;\n\tfloat opacity;\n\tfloat fillOpacity;\n\tfloat strokeOpacity;\n\tchar fillGradient[64];\n\tchar strokeGradient[64];\n\tfloat strokeWidth;\n\tfloat strokeDashOffset;\n\tfloat strokeDashArray[NSVG_MAX_DASHES];\n\tint strokeDashCount;\n\tchar strokeLineJoin;\n\tchar strokeLineCap;\n\tfloat miterLimit;\n\tchar fillRule;\n\tfloat fontSize;\n\tunsigned int stopColor;\n\tfloat stopOpacity;\n\tfloat stopOffset;\n\tchar hasFill;\n\tchar hasStroke;\n\tchar visible;\n\tunsigned char paintOrder;\n} NSVGattrib;\n\ntypedef struct NSVGstyles\n{\n\tchar*\tname;\n\tchar* description;\n\tstruct NSVGstyles* next;\n} NSVGstyles;\n\ntypedef struct NSVGparser\n{\n\tNSVGattrib attr[NSVG_MAX_ATTR];\n\tint attrHead;\n\tfloat* pts;\n\tint npts;\n\tint cpts;\n\tNSVGpath* plist;\n\tNSVGimage* image;\n\tNSVGstyles* styles;\n\tNSVGgradientData* gradients;\n\tNSVGshape* shapesTail;\n\tfloat viewMinx, viewMiny, viewWidth, viewHeight;\n\tint alignX, alignY, alignType;\n\tfloat dpi;\n\tchar pathFlag;\n\tchar defsFlag;\n\tchar styleFlag;\n} NSVGparser;\n\nstatic void nsvg__xformIdentity(float* t)\n{\n\tt[0] = 1.0f; t[1] = 0.0f;\n\tt[2] = 0.0f; t[3] = 1.0f;\n\tt[4] = 0.0f; t[5] = 0.0f;\n}\n\nstatic void nsvg__xformSetTranslation(float* t, float tx, float ty)\n{\n\tt[0] = 1.0f; t[1] = 0.0f;\n\tt[2] = 0.0f; t[3] = 1.0f;\n\tt[4] = tx; t[5] = ty;\n}\n\nstatic void nsvg__xformSetScale(float* t, float sx, float sy)\n{\n\tt[0] = sx; t[1] = 0.0f;\n\tt[2] = 0.0f; t[3] = sy;\n\tt[4] = 0.0f; t[5] = 0.0f;\n}\n\nstatic void nsvg__xformSetSkewX(float* t, float a)\n{\n\tt[0] = 1.0f; t[1] = 0.0f;\n\tt[2] = tanf(a); t[3] = 1.0f;\n\tt[4] = 0.0f; t[5] = 0.0f;\n}\n\nstatic void nsvg__xformSetSkewY(float* t, float a)\n{\n\tt[0] = 1.0f; t[1] = tanf(a);\n\tt[2] = 0.0f; t[3] = 1.0f;\n\tt[4] = 0.0f; t[5] = 0.0f;\n}\n\nstatic void nsvg__xformSetRotation(float* t, float a)\n{\n\tfloat cs = cosf(a), sn = sinf(a);\n\tt[0] = cs; t[1] = sn;\n\tt[2] = -sn; t[3] = cs;\n\tt[4] = 0.0f; t[5] = 0.0f;\n}\n\nstatic void nsvg__xformMultiply(float* t, float* s)\n{\n\tfloat t0 = t[0] * s[0] + t[1] * s[2];\n\tfloat t2 = t[2] * s[0] + t[3] * s[2];\n\tfloat t4 = t[4] * s[0] + t[5] * s[2] + s[4];\n\tt[1] = t[0] * s[1] + t[1] * s[3];\n\tt[3] = t[2] * s[1] + t[3] * s[3];\n\tt[5] = t[4] * s[1] + t[5] * s[3] + s[5];\n\tt[0] = t0;\n\tt[2] = t2;\n\tt[4] = t4;\n}\n\nstatic void nsvg__xformInverse(float* inv, float* t)\n{\n\tdouble invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];\n\tif (det > -1e-6 && det < 1e-6) {\n\t\tnsvg__xformIdentity(t);\n\t\treturn;\n\t}\n\tinvdet = 1.0 / det;\n\tinv[0] = (float)(t[3] * invdet);\n\tinv[2] = (float)(-t[2] * invdet);\n\tinv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);\n\tinv[1] = (float)(-t[1] * invdet);\n\tinv[3] = (float)(t[0] * invdet);\n\tinv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);\n}\n\nstatic void nsvg__xformPremultiply(float* t, float* s)\n{\n\tfloat s2[6];\n\tmemcpy(s2, s, sizeof(float)*6);\n\tnsvg__xformMultiply(s2, t);\n\tmemcpy(t, s2, sizeof(float)*6);\n}\n\nstatic void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)\n{\n\t*dx = x*t[0] + y*t[2] + t[4];\n\t*dy = x*t[1] + y*t[3] + t[5];\n}\n\nstatic void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)\n{\n\t*dx = x*t[0] + y*t[2];\n\t*dy = x*t[1] + y*t[3];\n}\n\n#define NSVG_EPSILON (1e-12)\n\nstatic int nsvg__ptInBounds(float* pt, float* bounds)\n{\n\treturn pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];\n}\n\n\nstatic double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)\n{\n\tdouble it = 1.0-t;\n\treturn it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;\n}\n\nstatic void nsvg__curveBounds(float* bounds, float* curve)\n{\n\tint i, j, count;\n\tdouble roots[2], a, b, c, b2ac, t, v;\n\tfloat* v0 = &curve[0];\n\tfloat* v1 = &curve[2];\n\tfloat* v2 = &curve[4];\n\tfloat* v3 = &curve[6];\n\n\t/* Start the bounding box by end points */\n\tbounds[0] = nsvg__minf(v0[0], v3[0]);\n\tbounds[1] = nsvg__minf(v0[1], v3[1]);\n\tbounds[2] = nsvg__maxf(v0[0], v3[0]);\n\tbounds[3] = nsvg__maxf(v0[1], v3[1]);\n\n\t/* Bezier curve fits inside the convex hull of it's control points. */\n\t/* If control points are inside the bounds, we're done. */\n\tif (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))\n\t\treturn;\n\n\t/* Add bezier curve inflection points in X and Y. */\n\tfor (i = 0; i < 2; i++) {\n\t\ta = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];\n\t\tb = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];\n\t\tc = 3.0 * v1[i] - 3.0 * v0[i];\n\t\tcount = 0;\n\t\tif (fabs(a) < NSVG_EPSILON) {\n\t\t\tif (fabs(b) > NSVG_EPSILON) {\n\t\t\t\tt = -c / b;\n\t\t\t\tif (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)\n\t\t\t\t\troots[count++] = t;\n\t\t\t}\n\t\t} else {\n\t\t\tb2ac = b*b - 4.0*c*a;\n\t\t\tif (b2ac > NSVG_EPSILON) {\n\t\t\t\tt = (-b + sqrt(b2ac)) / (2.0 * a);\n\t\t\t\tif (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)\n\t\t\t\t\troots[count++] = t;\n\t\t\t\tt = (-b - sqrt(b2ac)) / (2.0 * a);\n\t\t\t\tif (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)\n\t\t\t\t\troots[count++] = t;\n\t\t\t}\n\t\t}\n\t\tfor (j = 0; j < count; j++) {\n\t\t\tv = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);\n\t\t\tbounds[0+i] = nsvg__minf(bounds[0+i], (float)v);\n\t\t\tbounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);\n\t\t}\n\t}\n}\n\nstatic unsigned char nsvg__encodePaintOrder(enum NSVGpaintOrder a, enum NSVGpaintOrder b, enum NSVGpaintOrder c) {\n\treturn (a & 0x03) | ((b & 0x03) << 2) | ((c & 0x03) << 4);\n}\n\nstatic NSVGparser* nsvg__createParser(void)\n{\n\tNSVGparser* p;\n\tp = (NSVGparser*)NANOSVG_malloc(sizeof(NSVGparser));\n\tif (p == NULL) goto error;\n\tmemset(p, 0, sizeof(NSVGparser));\n\n\tp->image = (NSVGimage*)NANOSVG_malloc(sizeof(NSVGimage));\n\tif (p->image == NULL) goto error;\n\tmemset(p->image, 0, sizeof(NSVGimage));\n\n\t/* Init style */\n\tnsvg__xformIdentity(p->attr[0].xform);\n\tmemset(p->attr[0].id, 0, sizeof p->attr[0].id);\n\tp->attr[0].fillColor = NSVG_RGB(0,0,0);\n\tp->attr[0].strokeColor = NSVG_RGB(0,0,0);\n\tp->attr[0].opacity = 1;\n\tp->attr[0].fillOpacity = 1;\n\tp->attr[0].strokeOpacity = 1;\n\tp->attr[0].stopOpacity = 1;\n\tp->attr[0].strokeWidth = 1;\n\tp->attr[0].strokeLineJoin = NSVG_JOIN_MITER;\n\tp->attr[0].strokeLineCap = NSVG_CAP_BUTT;\n\tp->attr[0].miterLimit = 4;\n\tp->attr[0].fillRule = NSVG_FILLRULE_NONZERO;\n\tp->attr[0].hasFill = 1;\n\tp->attr[0].visible = NSVG_VIS_DISPLAY | NSVG_VIS_VISIBLE;\n\tp->attr[0].paintOrder = nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);\n\n\treturn p;\n\nerror:\n\tif (p) {\n\t\tif (p->image) NANOSVG_free(p->image);\n\t\tNANOSVG_free(p);\n\t}\n\treturn NULL;\n}\n\nstatic void nsvg__deleteStyles(NSVGstyles* style) {\n\twhile (style) {\n\t\tNSVGstyles *next = style->next;\n\t\tif (style->name!= NULL)\n\t\t\tNANOSVG_free(style->name);\n\t\tif (style->description != NULL)\n\t\t\tNANOSVG_free(style->description);\n\t\tNANOSVG_free(style);\n\t\tstyle = next;\n\t}\n}\n\nstatic void nsvg__deletePaths(NSVGpath* path)\n{\n\twhile (path) {\n\t\tNSVGpath *next = path->next;\n\t\tif (path->pts != NULL)\n\t\t\tNANOSVG_free(path->pts);\n\t\tNANOSVG_free(path);\n\t\tpath = next;\n\t}\n}\n\nstatic void nsvg__deletePaint(NSVGpaint* paint)\n{\n\tif (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)\n\t\tNANOSVG_free(paint->gradient);\n}\n\nstatic void nsvg__deleteGradientData(NSVGgradientData* grad)\n{\n\tNSVGgradientData* next;\n\twhile (grad != NULL) {\n\t\tnext = grad->next;\n\t\tNANOSVG_free(grad->stops);\n\t\tNANOSVG_free(grad);\n\t\tgrad = next;\n\t}\n}\n\nstatic void nsvg__deleteParser(NSVGparser* p)\n{\n\tif (p != NULL) {\n\t\tnsvg__deleteStyles(p->styles);\n\t\tnsvg__deletePaths(p->plist);\n\t\tnsvg__deleteGradientData(p->gradients);\n\t\tnsvgDelete(p->image);\n\t\tNANOSVG_free(p->pts);\n\t\tNANOSVG_free(p);\n\t}\n}\n\nstatic void nsvg__resetPath(NSVGparser* p)\n{\n\tp->npts = 0;\n}\n\nstatic void nsvg__addPoint(NSVGparser* p, float x, float y)\n{\n\tif (p->npts+1 > p->cpts) {\n\t\tp->cpts = p->cpts ? p->cpts*2 : 8;\n\t\tp->pts = (float*)NANOSVG_realloc(p->pts, p->cpts*2*sizeof(float));\n\t\tif (!p->pts) return;\n\t}\n\tp->pts[p->npts*2+0] = x;\n\tp->pts[p->npts*2+1] = y;\n\tp->npts++;\n}\n\nstatic void nsvg__moveTo(NSVGparser* p, float x, float y)\n{\n\tif (p->npts > 0) {\n\t\tp->pts[(p->npts-1)*2+0] = x;\n\t\tp->pts[(p->npts-1)*2+1] = y;\n\t} else {\n\t\tnsvg__addPoint(p, x, y);\n\t}\n}\n\nstatic void nsvg__lineTo(NSVGparser* p, float x, float y)\n{\n\tfloat px,py, dx,dy;\n\tif (p->npts > 0) {\n\t\tpx = p->pts[(p->npts-1)*2+0];\n\t\tpy = p->pts[(p->npts-1)*2+1];\n\t\tdx = x - px;\n\t\tdy = y - py;\n\t\tnsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);\n\t\tnsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);\n\t\tnsvg__addPoint(p, x, y);\n\t}\n}\n\nstatic void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)\n{\n\tif (p->npts > 0) {\n\t\tnsvg__addPoint(p, cpx1, cpy1);\n\t\tnsvg__addPoint(p, cpx2, cpy2);\n\t\tnsvg__addPoint(p, x, y);\n\t}\n}\n\nstatic NSVGattrib* nsvg__getAttr(NSVGparser* p)\n{\n\treturn &p->attr[p->attrHead];\n}\n\nstatic void nsvg__pushAttr(NSVGparser* p)\n{\n\tif (p->attrHead < NSVG_MAX_ATTR-1) {\n\t\tp->attrHead++;\n\t\tmemcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));\n\t}\n}\n\nstatic void nsvg__popAttr(NSVGparser* p)\n{\n\tif (p->attrHead > 0)\n\t\tp->attrHead--;\n}\n\nstatic float nsvg__actualOrigX(NSVGparser* p)\n{\n\treturn p->viewMinx;\n}\n\nstatic float nsvg__actualOrigY(NSVGparser* p)\n{\n\treturn p->viewMiny;\n}\n\nstatic float nsvg__actualWidth(NSVGparser* p)\n{\n\treturn p->viewWidth;\n}\n\nstatic float nsvg__actualHeight(NSVGparser* p)\n{\n\treturn p->viewHeight;\n}\n\nstatic float nsvg__actualLength(NSVGparser* p)\n{\n\tfloat w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);\n\treturn sqrtf(w*w + h*h) / sqrtf(2.0f);\n}\n\nstatic float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)\n{\n\tNSVGattrib* attr = nsvg__getAttr(p);\n\tswitch (c.units) {\n\t\tcase NSVG_UNITS_USER:\t\treturn c.value;\n\t\tcase NSVG_UNITS_PX:\t\t\treturn c.value;\n\t\tcase NSVG_UNITS_PT:\t\t\treturn c.value / 72.0f * p->dpi;\n\t\tcase NSVG_UNITS_PC:\t\t\treturn c.value / 6.0f * p->dpi;\n\t\tcase NSVG_UNITS_MM:\t\t\treturn c.value / 25.4f * p->dpi;\n\t\tcase NSVG_UNITS_CM:\t\t\treturn c.value / 2.54f * p->dpi;\n\t\tcase NSVG_UNITS_IN:\t\t\treturn c.value * p->dpi;\n\t\tcase NSVG_UNITS_EM:\t\t\treturn c.value * attr->fontSize;\n\t\tcase NSVG_UNITS_EX:\t\t\treturn c.value * attr->fontSize * 0.52f; /* x-height of Helvetica. */\n\t\tcase NSVG_UNITS_PERCENT:\treturn orig + c.value / 100.0f * length;\n\t\tdefault:\t\t\t\t\treturn c.value;\n\t}\n\treturn c.value;\n}\n\nstatic NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)\n{\n\tNSVGgradientData* grad = p->gradients;\n\tif (id == NULL || *id == '\\0')\n\t\treturn NULL;\n\twhile (grad != NULL) {\n\t\tif (strcmp(grad->id, id) == 0)\n\t\t\treturn grad;\n\t\tgrad = grad->next;\n\t}\n\treturn NULL;\n}\n\nstatic NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType)\n{\n\tNSVGgradientData* data = NULL;\n\tNSVGgradientData* ref = NULL;\n\tNSVGgradientStop* stops = NULL;\n\tNSVGgradient* grad;\n\tfloat ox, oy, sw, sh, sl;\n\tint nstops = 0;\n\tint refIter;\n\n\tdata = nsvg__findGradientData(p, id);\n\tif (data == NULL) return NULL;\n\n\t/* TODO: use ref to fill in all unset values too. */\n\tref = data;\n\trefIter = 0;\n\twhile (ref != NULL) {\n\t\tNSVGgradientData* nextRef = NULL;\n\t\tif (stops == NULL && ref->stops != NULL) {\n\t\t\tstops = ref->stops;\n\t\t\tnstops = ref->nstops;\n\t\t\tbreak;\n\t\t}\n\t\tnextRef = nsvg__findGradientData(p, ref->ref);\n\t\tif (nextRef == ref) break; /* prevent infite loops on malformed data */\n\t\tref = nextRef;\n\t\trefIter++;\n\t\tif (refIter > 32) break; /* prevent infite loops on malformed data */\n\t}\n\tif (stops == NULL) return NULL;\n\n\tgrad = (NSVGgradient*)NANOSVG_malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));\n\tif (grad == NULL) return NULL;\n\n\t/* The shape width and height. */\n\tif (data->units == NSVG_OBJECT_SPACE) {\n\t\tox = localBounds[0];\n\t\toy = localBounds[1];\n\t\tsw = localBounds[2] - localBounds[0];\n\t\tsh = localBounds[3] - localBounds[1];\n\t} else {\n\t\tox = nsvg__actualOrigX(p);\n\t\toy = nsvg__actualOrigY(p);\n\t\tsw = nsvg__actualWidth(p);\n\t\tsh = nsvg__actualHeight(p);\n\t}\n\tsl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);\n\n\tif (data->type == NSVG_PAINT_LINEAR_GRADIENT) {\n\t\tfloat x1, y1, x2, y2, dx, dy;\n\t\tx1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);\n\t\ty1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);\n\t\tx2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);\n\t\ty2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);\n\t\t/* Calculate transform aligned to the line */\n\t\tdx = x2 - x1;\n\t\tdy = y2 - y1;\n\t\tgrad->xform[0] = dy; grad->xform[1] = -dx;\n\t\tgrad->xform[2] = dx; grad->xform[3] = dy;\n\t\tgrad->xform[4] = x1; grad->xform[5] = y1;\n\t} else {\n\t\tfloat cx, cy, fx, fy, r;\n\t\tcx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);\n\t\tcy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);\n\t\tfx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);\n\t\tfy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);\n\t\tr = nsvg__convertToPixels(p, data->radial.r, 0, sl);\n\t\t/* Calculate transform aligned to the circle */\n\t\tgrad->xform[0] = r; grad->xform[1] = 0;\n\t\tgrad->xform[2] = 0; grad->xform[3] = r;\n\t\tgrad->xform[4] = cx; grad->xform[5] = cy;\n\t\tgrad->fx = fx / r;\n\t\tgrad->fy = fy / r;\n\t}\n\n\tnsvg__xformMultiply(grad->xform, data->xform);\n\tnsvg__xformMultiply(grad->xform, xform);\n\n\tgrad->spread = data->spread;\n\tmemcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));\n\tgrad->nstops = nstops;\n\n\t*paintType = data->type;\n\n\treturn grad;\n}\n\nstatic float nsvg__getAverageScale(float* t)\n{\n\tfloat sx = sqrtf(t[0]*t[0] + t[2]*t[2]);\n\tfloat sy = sqrtf(t[1]*t[1] + t[3]*t[3]);\n\treturn (sx + sy) * 0.5f;\n}\n\nstatic void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)\n{\n\tNSVGpath* path;\n\tfloat curve[4*2], curveBounds[4];\n\tint i, first = 1;\n\tfor (path = shape->paths; path != NULL; path = path->next) {\n\t\tnsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);\n\t\tfor (i = 0; i < path->npts-1; i += 3) {\n\t\t\tnsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);\n\t\t\tnsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);\n\t\t\tnsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);\n\t\t\tnsvg__curveBounds(curveBounds, curve);\n\t\t\tif (first) {\n\t\t\t\tbounds[0] = curveBounds[0];\n\t\t\t\tbounds[1] = curveBounds[1];\n\t\t\t\tbounds[2] = curveBounds[2];\n\t\t\t\tbounds[3] = curveBounds[3];\n\t\t\t\tfirst = 0;\n\t\t\t} else {\n\t\t\t\tbounds[0] = nsvg__minf(bounds[0], curveBounds[0]);\n\t\t\t\tbounds[1] = nsvg__minf(bounds[1], curveBounds[1]);\n\t\t\t\tbounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);\n\t\t\t\tbounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);\n\t\t\t}\n\t\t\tcurve[0] = curve[6];\n\t\t\tcurve[1] = curve[7];\n\t\t}\n\t}\n}\n\nstatic void nsvg__addShape(NSVGparser* p)\n{\n\tNSVGattrib* attr = nsvg__getAttr(p);\n\tfloat scale = 1.0f;\n\tNSVGshape* shape;\n\tNSVGpath* path;\n\tint i;\n\n\tif (p->plist == NULL)\n\t\treturn;\n\n\tshape = (NSVGshape*)NANOSVG_malloc(sizeof(NSVGshape));\n\tif (shape == NULL) goto error;\n\tmemset(shape, 0, sizeof(NSVGshape));\n\n\tmemcpy(shape->id, attr->id, sizeof shape->id);\n\tmemcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient);\n\tmemcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient);\n\tmemcpy(shape->xform, attr->xform, sizeof shape->xform);\n\tscale = nsvg__getAverageScale(attr->xform);\n\tshape->strokeWidth = attr->strokeWidth * scale;\n\tshape->strokeDashOffset = attr->strokeDashOffset * scale;\n\tshape->strokeDashCount = (char)attr->strokeDashCount;\n\tfor (i = 0; i < attr->strokeDashCount; i++)\n\t\tshape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;\n\tshape->strokeLineJoin = attr->strokeLineJoin;\n\tshape->strokeLineCap = attr->strokeLineCap;\n\tshape->miterLimit = attr->miterLimit;\n\tshape->fillRule = attr->fillRule;\n\tshape->opacity = attr->opacity;\n\tshape->paintOrder = attr->paintOrder;\n\n\tshape->paths = p->plist;\n\tp->plist = NULL;\n\n\t/* Calculate shape bounds */\n\tshape->bounds[0] = shape->paths->bounds[0];\n\tshape->bounds[1] = shape->paths->bounds[1];\n\tshape->bounds[2] = shape->paths->bounds[2];\n\tshape->bounds[3] = shape->paths->bounds[3];\n\tfor (path = shape->paths->next; path != NULL; path = path->next) {\n\t\tshape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);\n\t\tshape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);\n\t\tshape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);\n\t\tshape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);\n\t}\n\n\t/* Set fill */\n\tif (attr->hasFill == 0) {\n\t\tshape->fill.type = NSVG_PAINT_NONE;\n\t} else if (attr->hasFill == 1) {\n\t\tshape->fill.type = NSVG_PAINT_COLOR;\n\t\tshape->fill.color = attr->fillColor;\n\t\tshape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;\n\t} else if (attr->hasFill == 2) {\n\t\tshape->fill.type = NSVG_PAINT_UNDEF;\n\t}\n\n\t/* Set stroke */\n\tif (attr->hasStroke == 0) {\n\t\tshape->stroke.type = NSVG_PAINT_NONE;\n\t} else if (attr->hasStroke == 1) {\n\t\tshape->stroke.type = NSVG_PAINT_COLOR;\n\t\tshape->stroke.color = attr->strokeColor;\n\t\tshape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;\n\t} else if (attr->hasStroke == 2) {\n\t\tshape->stroke.type = NSVG_PAINT_UNDEF;\n\t}\n\n\t/* Set flags */\n\tshape->flags = ((attr->visible & NSVG_VIS_DISPLAY) && (attr->visible & NSVG_VIS_VISIBLE) ? NSVG_FLAGS_VISIBLE : 0x00);\n\n\t/* Add to tail */\n\tif (p->image->shapes == NULL)\n\t\tp->image->shapes = shape;\n\telse\n\t\tp->shapesTail->next = shape;\n\tp->shapesTail = shape;\n\n\treturn;\n\nerror:\n\tif (shape) NANOSVG_free(shape);\n}\n\nstatic void nsvg__addPath(NSVGparser* p, char closed)\n{\n\tNSVGattrib* attr = nsvg__getAttr(p);\n\tNSVGpath* path = NULL;\n\tfloat bounds[4];\n\tfloat* curve;\n\tint i;\n\n\tif (p->npts < 4)\n\t\treturn;\n\n\tif (closed)\n\t\tnsvg__lineTo(p, p->pts[0], p->pts[1]);\n\n\t/* Expect 1 + N*3 points (N = number of cubic bezier segments). */\n\tif ((p->npts % 3) != 1)\n\t\treturn;\n\n\tpath = (NSVGpath*)NANOSVG_malloc(sizeof(NSVGpath));\n\tif (path == NULL) goto error;\n\tmemset(path, 0, sizeof(NSVGpath));\n\n\tpath->pts = (float*)NANOSVG_malloc(p->npts*2*sizeof(float));\n\tif (path->pts == NULL) goto error;\n\tpath->closed = closed;\n\tpath->npts = p->npts;\n\n\t/* Transform path. */\n\tfor (i = 0; i < p->npts; ++i)\n\t\tnsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);\n\n\t/* Find bounds */\n\tfor (i = 0; i < path->npts-1; i += 3) {\n\t\tcurve = &path->pts[i*2];\n\t\tnsvg__curveBounds(bounds, curve);\n\t\tif (i == 0) {\n\t\t\tpath->bounds[0] = bounds[0];\n\t\t\tpath->bounds[1] = bounds[1];\n\t\t\tpath->bounds[2] = bounds[2];\n\t\t\tpath->bounds[3] = bounds[3];\n\t\t} else {\n\t\t\tpath->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);\n\t\t\tpath->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);\n\t\t\tpath->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);\n\t\t\tpath->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);\n\t\t}\n\t}\n\n\tpath->next = p->plist;\n\tp->plist = path;\n\n\treturn;\n\nerror:\n\tif (path != NULL) {\n\t\tif (path->pts != NULL) NANOSVG_free(path->pts);\n\t\tNANOSVG_free(path);\n\t}\n}\n\n/* We roll our own string to float because the std library one uses locale and messes things up. */\nstatic double nsvg__atof(const char* s)\n{\n\tchar* cur = (char*)s;\n\tchar* end = NULL;\n\tdouble res = 0.0, sign = 1.0;\n#if defined(_MSC_VER) && (_MSC_VER == 1200)\n\t__int64 intPart = 0, fracPart = 0;\n#else\n\tlong long intPart = 0, fracPart = 0;\n#endif\n\tchar hasIntPart = 0, hasFracPart = 0;\n\n\t/* Parse optional sign */\n\tif (*cur == '+') {\n\t\tcur++;\n\t} else if (*cur == '-') {\n\t\tsign = -1;\n\t\tcur++;\n\t}\n\n\t/* Parse integer part */\n\tif (nsvg__isdigit(*cur)) {\n\t\t/* Parse digit sequence */\n#if defined(_MSC_VER) && (_MSC_VER == 1200)\n\t\tintPart = strtol(cur, &end, 10);\n#else\n\t\tintPart = strtoll(cur, &end, 10);\n#endif\n\t\tif (cur != end) {\n\t\t\tres = (double)intPart;\n\t\t\thasIntPart = 1;\n\t\t\tcur = end;\n\t\t}\n\t}\n\n\t/* Parse fractional part. */\n\tif (*cur == '.') {\n\t\tcur++; /* Skip '.' */\n\t\tif (nsvg__isdigit(*cur)) {\n\t\t\t/* Parse digit sequence */\n#if defined(_MSC_VER) && (_MSC_VER == 1200)\n\t\t\tfracPart = strtol(cur, &end, 10);\n#else\n\t\t\tfracPart = strtoll(cur, &end, 10);\n#endif\n\t\t\tif (cur != end) {\n\t\t\t\tres += (double)fracPart / pow(10.0, (double)(end - cur));\n\t\t\t\thasFracPart = 1;\n\t\t\t\tcur = end;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* A valid number should have integer or fractional part. */\n\tif (!hasIntPart && !hasFracPart)\n\t\treturn 0.0;\n\n\t/* Parse optional exponent */\n\tif (*cur == 'e' || *cur == 'E') {\n\t\tint expPart = 0;\n\t\tcur++; /* skip 'E' */\n\t\texpPart = strtol(cur, &end, 10); /* Parse digit sequence with sign */\n\t\tif (cur != end) {\n\t\t\tres *= pow(10.0, (double)expPart);\n\t\t}\n\t}\n\n\treturn res * sign;\n}\n\n\nstatic const char* nsvg__parseNumber(const char* s, char* it, const int size)\n{\n\tconst int last = size-1;\n\tint i = 0;\n\n\t/* sign */\n\tif (*s == '-' || *s == '+') {\n\t\tif (i < last) it[i++] = *s;\n\t\ts++;\n\t}\n\t/* integer part */\n\twhile (*s && nsvg__isdigit(*s)) {\n\t\tif (i < last) it[i++] = *s;\n\t\ts++;\n\t}\n\tif (*s == '.') {\n\t\t/* decimal point */\n\t\tif (i < last) it[i++] = *s;\n\t\ts++;\n\t\t/* fraction part */\n\t\twhile (*s && nsvg__isdigit(*s)) {\n\t\t\tif (i < last) it[i++] = *s;\n\t\t\ts++;\n\t\t}\n\t}\n\t/* exponent */\n\tif (*s == 'e' || *s == 'E') {\n\t\tif (i < last) it[i++] = *s;\n\t\ts++;\n\t\tif (*s == '-' || *s == '+') {\n\t\t\tif (i < last) it[i++] = *s;\n\t\t\ts++;\n\t\t}\n\t\twhile (*s && nsvg__isdigit(*s)) {\n\t\t\tif (i < last) it[i++] = *s;\n\t\t\ts++;\n\t\t}\n\t}\n\tit[i] = '\\0';\n\n\treturn s;\n}\n\nstatic const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it)\n{\n\tit[0] = '\\0';\n\twhile (*s && (nsvg__isspace(*s) || *s == ',')) s++;\n\tif (!*s) return s;\n\tif (*s == '0' || *s == '1') {\n\t\tit[0] = *s++;\n\t\tit[1] = '\\0';\n\t\treturn s;\n\t}\n\treturn s;\n}\n\nstatic const char* nsvg__getNextPathItem(const char* s, char* it)\n{\n\tit[0] = '\\0';\n\t/* Skip white spaces and commas */\n\twhile (*s && (nsvg__isspace(*s) || *s == ',')) s++;\n\tif (!*s) return s;\n\tif (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {\n\t\ts = nsvg__parseNumber(s, it, 64);\n\t} else {\n\t\t/* Parse command */\n\t\tit[0] = *s++;\n\t\tit[1] = '\\0';\n\t\treturn s;\n\t}\n\n\treturn s;\n}\n\nstatic unsigned int nsvg__parseColorHex(const char* str)\n{\n\tunsigned int r=0, g=0, b=0;\n\tif (sscanf(str, \"#%2x%2x%2x\", &r, &g, &b) == 3 )\t\t/* 2 digit hex */\n\t\treturn NSVG_RGB(r, g, b);\n\tif (sscanf(str, \"#%1x%1x%1x\", &r, &g, &b) == 3 )\t\t/* 1 digit hex, e.g. #abc -> 0xccbbaa */\n\t\treturn NSVG_RGB(r*17, g*17, b*17);\t\t\t/* same effect as (r<<4|r), (g<<4|g), .. */\n\treturn NSVG_RGB(128, 128, 128);\n}\n\n/*\n * Parse rgb color. The pointer 'str' must point at \"rgb(\" (4+ characters).\n * This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors\n * for backwards compatibility. Note: other image viewers return black instead.\n */\n\nstatic unsigned int nsvg__parseColorRGB(const char* str)\n{\n\tint i;\n\tunsigned int rgbi[3];\n\tfloat rgbf[3];\n\t/* try decimal integers first */\n\tif (sscanf(str, \"rgb(%u, %u, %u)\", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) {\n\t\t/* integers failed, try percent values (float, locale independent) */\n\t\tconst char delimiter[3] = {',', ',', ')'};\n\t\tstr += 4; /* skip \"rgb(\" */\n\t\tfor (i = 0; i < 3; i++) {\n\t\t\twhile (*str && (nsvg__isspace(*str))) str++; \t/* skip leading spaces */\n\t\t\tif (*str == '+') str++;\t\t\t\t/* skip '+' (don't allow '-') */\n\t\t\tif (!*str) break;\n\t\t\trgbf[i] = nsvg__atof(str);\n\n\t\t\t/*\n\t\t\t * Note 1: it would be great if nsvg__atof() returned how many\n\t\t\t * bytes it consumed but it doesn't. We need to skip the number,\n\t\t\t * the '%' character, spaces, and the delimiter ',' or ')'.\n\t\t\t *\n\t\t\t * Note 2: The following code does not allow values like \"33.%\",\n\t\t\t * i.e. a decimal point w/o fractional part, but this is consistent\n\t\t\t * with other image viewers, e.g. firefox, chrome, eog, gimp.\n\t\t\t */\n\n\t\t\twhile (*str && nsvg__isdigit(*str)) str++;\t\t/* skip integer part */\n\t\t\tif (*str == '.') {\n\t\t\t\tstr++;\n\t\t\t\tif (!nsvg__isdigit(*str)) break;\t\t/* error: no digit after '.' */\n\t\t\t\twhile (*str && nsvg__isdigit(*str)) str++;\t/* skip fractional part */\n\t\t\t}\n\t\t\tif (*str == '%') str++; else break;\n\t\t\twhile (*str && nsvg__isspace(*str)) str++;\n\t\t\tif (*str == delimiter[i]) str++;\n\t\t\telse break;\n\t\t}\n\t\tif (i == 3) {\n\t\t\trgbi[0] = roundf(rgbf[0] * 2.55f);\n\t\t\trgbi[1] = roundf(rgbf[1] * 2.55f);\n\t\t\trgbi[2] = roundf(rgbf[2] * 2.55f);\n\t\t} else {\n\t\t\trgbi[0] = rgbi[1] = rgbi[2] = 128;\n\t\t}\n\t}\n\t/* clip values as the CSS spec requires */\n\tfor (i = 0; i < 3; i++) {\n\t\tif (rgbi[i] > 255) rgbi[i] = 255;\n\t}\n\treturn NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]);\n}\n\ntypedef struct NSVGNamedColor {\n\tconst char* name;\n\tunsigned int color;\n} NSVGNamedColor;\n\nNSVGNamedColor nsvg__colors[] = {\n\n\t{ \"red\", NSVG_RGB(255, 0, 0) },\n\t{ \"green\", NSVG_RGB( 0, 128, 0) },\n\t{ \"blue\", NSVG_RGB( 0, 0, 255) },\n\t{ \"yellow\", NSVG_RGB(255, 255, 0) },\n\t{ \"cyan\", NSVG_RGB( 0, 255, 255) },\n\t{ \"magenta\", NSVG_RGB(255, 0, 255) },\n\t{ \"black\", NSVG_RGB( 0, 0, 0) },\n\t{ \"grey\", NSVG_RGB(128, 128, 128) },\n\t{ \"gray\", NSVG_RGB(128, 128, 128) },\n\t{ \"white\", NSVG_RGB(255, 255, 255) },\n\n#ifdef NANOSVG_ALL_COLOR_KEYWORDS\n\t{ \"aliceblue\", NSVG_RGB(240, 248, 255) },\n\t{ \"antiquewhite\", NSVG_RGB(250, 235, 215) },\n\t{ \"aqua\", NSVG_RGB( 0, 255, 255) },\n\t{ \"aquamarine\", NSVG_RGB(127, 255, 212) },\n\t{ \"azure\", NSVG_RGB(240, 255, 255) },\n\t{ \"beige\", NSVG_RGB(245, 245, 220) },\n\t{ \"bisque\", NSVG_RGB(255, 228, 196) },\n\t{ \"blanchedalmond\", NSVG_RGB(255, 235, 205) },\n\t{ \"blueviolet\", NSVG_RGB(138, 43, 226) },\n\t{ \"brown\", NSVG_RGB(165, 42, 42) },\n\t{ \"burlywood\", NSVG_RGB(222, 184, 135) },\n\t{ \"cadetblue\", NSVG_RGB( 95, 158, 160) },\n\t{ \"chartreuse\", NSVG_RGB(127, 255, 0) },\n\t{ \"chocolate\", NSVG_RGB(210, 105, 30) },\n\t{ \"coral\", NSVG_RGB(255, 127, 80) },\n\t{ \"cornflowerblue\", NSVG_RGB(100, 149, 237) },\n\t{ \"cornsilk\", NSVG_RGB(255, 248, 220) },\n\t{ \"crimson\", NSVG_RGB(220, 20, 60) },\n\t{ \"darkblue\", NSVG_RGB( 0, 0, 139) },\n\t{ \"darkcyan\", NSVG_RGB( 0, 139, 139) },\n\t{ \"darkgoldenrod\", NSVG_RGB(184, 134, 11) },\n\t{ \"darkgray\", NSVG_RGB(169, 169, 169) },\n\t{ \"darkgreen\", NSVG_RGB( 0, 100, 0) },\n\t{ \"darkgrey\", NSVG_RGB(169, 169, 169) },\n\t{ \"darkkhaki\", NSVG_RGB(189, 183, 107) },\n\t{ \"darkmagenta\", NSVG_RGB(139, 0, 139) },\n\t{ \"darkolivegreen\", NSVG_RGB( 85, 107, 47) },\n\t{ \"darkorange\", NSVG_RGB(255, 140, 0) },\n\t{ \"darkorchid\", NSVG_RGB(153, 50, 204) },\n\t{ \"darkred\", NSVG_RGB(139, 0, 0) },\n\t{ \"darksalmon\", NSVG_RGB(233, 150, 122) },\n\t{ \"darkseagreen\", NSVG_RGB(143, 188, 143) },\n\t{ \"darkslateblue\", NSVG_RGB( 72, 61, 139) },\n\t{ \"darkslategray\", NSVG_RGB( 47, 79, 79) },\n\t{ \"darkslategrey\", NSVG_RGB( 47, 79, 79) },\n\t{ \"darkturquoise\", NSVG_RGB( 0, 206, 209) },\n\t{ \"darkviolet\", NSVG_RGB(148, 0, 211) },\n\t{ \"deeppink\", NSVG_RGB(255, 20, 147) },\n\t{ \"deepskyblue\", NSVG_RGB( 0, 191, 255) },\n\t{ \"dimgray\", NSVG_RGB(105, 105, 105) },\n\t{ \"dimgrey\", NSVG_RGB(105, 105, 105) },\n\t{ \"dodgerblue\", NSVG_RGB( 30, 144, 255) },\n\t{ \"firebrick\", NSVG_RGB(178, 34, 34) },\n\t{ \"floralwhite\", NSVG_RGB(255, 250, 240) },\n\t{ \"forestgreen\", NSVG_RGB( 34, 139, 34) },\n\t{ \"fuchsia\", NSVG_RGB(255, 0, 255) },\n\t{ \"gainsboro\", NSVG_RGB(220, 220, 220) },\n\t{ \"ghostwhite\", NSVG_RGB(248, 248, 255) },\n\t{ \"gold\", NSVG_RGB(255, 215, 0) },\n\t{ \"goldenrod\", NSVG_RGB(218, 165, 32) },\n\t{ \"greenyellow\", NSVG_RGB(173, 255, 47) },\n\t{ \"honeydew\", NSVG_RGB(240, 255, 240) },\n\t{ \"hotpink\", NSVG_RGB(255, 105, 180) },\n\t{ \"indianred\", NSVG_RGB(205, 92, 92) },\n\t{ \"indigo\", NSVG_RGB( 75, 0, 130) },\n\t{ \"ivory\", NSVG_RGB(255, 255, 240) },\n\t{ \"khaki\", NSVG_RGB(240, 230, 140) },\n\t{ \"lavender\", NSVG_RGB(230, 230, 250) },\n\t{ \"lavenderblush\", NSVG_RGB(255, 240, 245) },\n\t{ \"lawngreen\", NSVG_RGB(124, 252, 0) },\n\t{ \"lemonchiffon\", NSVG_RGB(255, 250, 205) },\n\t{ \"lightblue\", NSVG_RGB(173, 216, 230) },\n\t{ \"lightcoral\", NSVG_RGB(240, 128, 128) },\n\t{ \"lightcyan\", NSVG_RGB(224, 255, 255) },\n\t{ \"lightgoldenrodyellow\", NSVG_RGB(250, 250, 210) },\n\t{ \"lightgray\", NSVG_RGB(211, 211, 211) },\n\t{ \"lightgreen\", NSVG_RGB(144, 238, 144) },\n\t{ \"lightgrey\", NSVG_RGB(211, 211, 211) },\n\t{ \"lightpink\", NSVG_RGB(255, 182, 193) },\n\t{ \"lightsalmon\", NSVG_RGB(255, 160, 122) },\n\t{ \"lightseagreen\", NSVG_RGB( 32, 178, 170) },\n\t{ \"lightskyblue\", NSVG_RGB(135, 206, 250) },\n\t{ \"lightslategray\", NSVG_RGB(119, 136, 153) },\n\t{ \"lightslategrey\", NSVG_RGB(119, 136, 153) },\n\t{ \"lightsteelblue\", NSVG_RGB(176, 196, 222) },\n\t{ \"lightyellow\", NSVG_RGB(255, 255, 224) },\n\t{ \"lime\", NSVG_RGB( 0, 255, 0) },\n\t{ \"limegreen\", NSVG_RGB( 50, 205, 50) },\n\t{ \"linen\", NSVG_RGB(250, 240, 230) },\n\t{ \"maroon\", NSVG_RGB(128, 0, 0) },\n\t{ \"mediumaquamarine\", NSVG_RGB(102, 205, 170) },\n\t{ \"mediumblue\", NSVG_RGB( 0, 0, 205) },\n\t{ \"mediumorchid\", NSVG_RGB(186, 85, 211) },\n\t{ \"mediumpurple\", NSVG_RGB(147, 112, 219) },\n\t{ \"mediumseagreen\", NSVG_RGB( 60, 179, 113) },\n\t{ \"mediumslateblue\", NSVG_RGB(123, 104, 238) },\n\t{ \"mediumspringgreen\", NSVG_RGB( 0, 250, 154) },\n\t{ \"mediumturquoise\", NSVG_RGB( 72, 209, 204) },\n\t{ \"mediumvioletred\", NSVG_RGB(199, 21, 133) },\n\t{ \"midnightblue\", NSVG_RGB( 25, 25, 112) },\n\t{ \"mintcream\", NSVG_RGB(245, 255, 250) },\n\t{ \"mistyrose\", NSVG_RGB(255, 228, 225) },\n\t{ \"moccasin\", NSVG_RGB(255, 228, 181) },\n\t{ \"navajowhite\", NSVG_RGB(255, 222, 173) },\n\t{ \"navy\", NSVG_RGB( 0, 0, 128) },\n\t{ \"oldlace\", NSVG_RGB(253, 245, 230) },\n\t{ \"olive\", NSVG_RGB(128, 128, 0) },\n\t{ \"olivedrab\", NSVG_RGB(107, 142, 35) },\n\t{ \"orange\", NSVG_RGB(255, 165, 0) },\n\t{ \"orangered\", NSVG_RGB(255, 69, 0) },\n\t{ \"orchid\", NSVG_RGB(218, 112, 214) },\n\t{ \"palegoldenrod\", NSVG_RGB(238, 232, 170) },\n\t{ \"palegreen\", NSVG_RGB(152, 251, 152) },\n\t{ \"paleturquoise\", NSVG_RGB(175, 238, 238) },\n\t{ \"palevioletred\", NSVG_RGB(219, 112, 147) },\n\t{ \"papayawhip\", NSVG_RGB(255, 239, 213) },\n\t{ \"peachpuff\", NSVG_RGB(255, 218, 185) },\n\t{ \"peru\", NSVG_RGB(205, 133, 63) },\n\t{ \"pink\", NSVG_RGB(255, 192, 203) },\n\t{ \"plum\", NSVG_RGB(221, 160, 221) },\n\t{ \"powderblue\", NSVG_RGB(176, 224, 230) },\n\t{ \"purple\", NSVG_RGB(128, 0, 128) },\n\t{ \"rosybrown\", NSVG_RGB(188, 143, 143) },\n\t{ \"royalblue\", NSVG_RGB( 65, 105, 225) },\n\t{ \"saddlebrown\", NSVG_RGB(139, 69, 19) },\n\t{ \"salmon\", NSVG_RGB(250, 128, 114) },\n\t{ \"sandybrown\", NSVG_RGB(244, 164, 96) },\n\t{ \"seagreen\", NSVG_RGB( 46, 139, 87) },\n\t{ \"seashell\", NSVG_RGB(255, 245, 238) },\n\t{ \"sienna\", NSVG_RGB(160, 82, 45) },\n\t{ \"silver\", NSVG_RGB(192, 192, 192) },\n\t{ \"skyblue\", NSVG_RGB(135, 206, 235) },\n\t{ \"slateblue\", NSVG_RGB(106, 90, 205) },\n\t{ \"slategray\", NSVG_RGB(112, 128, 144) },\n\t{ \"slategrey\", NSVG_RGB(112, 128, 144) },\n\t{ \"snow\", NSVG_RGB(255, 250, 250) },\n\t{ \"springgreen\", NSVG_RGB( 0, 255, 127) },\n\t{ \"steelblue\", NSVG_RGB( 70, 130, 180) },\n\t{ \"tan\", NSVG_RGB(210, 180, 140) },\n\t{ \"teal\", NSVG_RGB( 0, 128, 128) },\n\t{ \"thistle\", NSVG_RGB(216, 191, 216) },\n\t{ \"tomato\", NSVG_RGB(255, 99, 71) },\n\t{ \"turquoise\", NSVG_RGB( 64, 224, 208) },\n\t{ \"violet\", NSVG_RGB(238, 130, 238) },\n\t{ \"wheat\", NSVG_RGB(245, 222, 179) },\n\t{ \"whitesmoke\", NSVG_RGB(245, 245, 245) },\n\t{ \"yellowgreen\", NSVG_RGB(154, 205, 50) },\n#endif\n};\n\nstatic unsigned int nsvg__parseColorName(const char* str)\n{\n\tint i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);\n\n\tfor (i = 0; i < ncolors; i++) {\n\t\tif (strcmp(nsvg__colors[i].name, str) == 0) {\n\t\t\treturn nsvg__colors[i].color;\n\t\t}\n\t}\n\n\treturn NSVG_RGB(128, 128, 128);\n}\n\nstatic unsigned int nsvg__parseColor(const char* str)\n{\n\tsize_t len = 0;\n\twhile(*str == ' ') ++str;\n\tlen = strlen(str);\n\tif (len >= 1 && *str == '#')\n\t\treturn nsvg__parseColorHex(str);\n\telse if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')\n\t\treturn nsvg__parseColorRGB(str);\n\treturn nsvg__parseColorName(str);\n}\n\nstatic float nsvg__parseOpacity(const char* str)\n{\n\tfloat val = 0;\n\tsscanf(str, \"%f\", &val);\n\tif (val < 0.0f) val = 0.0f;\n\tif (val > 1.0f) val = 1.0f;\n\treturn val;\n}\n\nstatic float nsvg__parseMiterLimit(const char* str)\n{\n\tfloat val = 0;\n\tsscanf(str, \"%f\", &val);\n\tif (val < 0.0f) val = 0.0f;\n\treturn val;\n}\n\nstatic int nsvg__parseUnits(const char* units)\n{\n\tif (units[0] == 'p' && units[1] == 'x')\n\t\treturn NSVG_UNITS_PX;\n\telse if (units[0] == 'p' && units[1] == 't')\n\t\treturn NSVG_UNITS_PT;\n\telse if (units[0] == 'p' && units[1] == 'c')\n\t\treturn NSVG_UNITS_PC;\n\telse if (units[0] == 'm' && units[1] == 'm')\n\t\treturn NSVG_UNITS_MM;\n\telse if (units[0] == 'c' && units[1] == 'm')\n\t\treturn NSVG_UNITS_CM;\n\telse if (units[0] == 'i' && units[1] == 'n')\n\t\treturn NSVG_UNITS_IN;\n\telse if (units[0] == '%')\n\t\treturn NSVG_UNITS_PERCENT;\n\telse if (units[0] == 'e' && units[1] == 'm')\n\t\treturn NSVG_UNITS_EM;\n\telse if (units[0] == 'e' && units[1] == 'x')\n\t\treturn NSVG_UNITS_EX;\n\treturn NSVG_UNITS_USER;\n}\n\nstatic int nsvg__isCoordinate(const char* s)\n{\n\t/* optional sign */\n\tif (*s == '-' || *s == '+')\n\t\ts++;\n\t/* must have at least one digit, or start by a dot */\n\treturn (nsvg__isdigit(*s) || *s == '.');\n}\n\nstatic NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)\n{\n\tNSVGcoordinate coord = {0, NSVG_UNITS_USER};\n\tchar units[32]=\"\";\n\tsscanf(str, \"%f%s\", &coord.value, units);\n\tcoord.units = nsvg__parseUnits(units);\n\treturn coord;\n}\n\nstatic NSVGcoordinate nsvg__coord(float v, int units)\n{\n\tNSVGcoordinate coord = {v, units};\n\treturn coord;\n}\n\nstatic float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)\n{\n\tNSVGcoordinate coord = nsvg__parseCoordinateRaw(str);\n\treturn nsvg__convertToPixels(p, coord, orig, length);\n}\n\nstatic int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)\n{\n\tconst char* end;\n\tconst char* ptr;\n\tchar it[64];\n\n\t*na = 0;\n\tptr = str;\n\twhile (*ptr && *ptr != '(') ++ptr;\n\tif (*ptr == 0)\n\t\treturn 1;\n\tend = ptr;\n\twhile (*end && *end != ')') ++end;\n\tif (*end == 0)\n\t\treturn 1;\n\n\twhile (ptr < end) {\n\t\tif (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {\n\t\t\tif (*na >= maxNa) return 0;\n\t\t\tptr = nsvg__parseNumber(ptr, it, 64);\n\t\t\targs[(*na)++] = (float)nsvg__atof(it);\n\t\t} else {\n\t\t\t++ptr;\n\t\t}\n\t}\n\treturn (int)(end - str);\n}\n\n\nstatic int nsvg__parseMatrix(float* xform, const char* str)\n{\n\tfloat t[6];\n\tint na = 0;\n\tint len = nsvg__parseTransformArgs(str, t, 6, &na);\n\tif (na != 6) return len;\n\tmemcpy(xform, t, sizeof(float)*6);\n\treturn len;\n}\n\nstatic int nsvg__parseTranslate(float* xform, const char* str)\n{\n\tfloat args[2];\n\tfloat t[6];\n\tint na = 0;\n\tint len = nsvg__parseTransformArgs(str, args, 2, &na);\n\tif (na == 1) args[1] = 0.0;\n\n\tnsvg__xformSetTranslation(t, args[0], args[1]);\n\tmemcpy(xform, t, sizeof(float)*6);\n\treturn len;\n}\n\nstatic int nsvg__parseScale(float* xform, const char* str)\n{\n\tfloat args[2];\n\tint na = 0;\n\tfloat t[6];\n\tint len = nsvg__parseTransformArgs(str, args, 2, &na);\n\tif (na == 1) args[1] = args[0];\n\tnsvg__xformSetScale(t, args[0], args[1]);\n\tmemcpy(xform, t, sizeof(float)*6);\n\treturn len;\n}\n\nstatic int nsvg__parseSkewX(float* xform, const char* str)\n{\n\tfloat args[1];\n\tint na = 0;\n\tfloat t[6];\n\tint len = nsvg__parseTransformArgs(str, args, 1, &na);\n\tnsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);\n\tmemcpy(xform, t, sizeof(float)*6);\n\treturn len;\n}\n\nstatic int nsvg__parseSkewY(float* xform, const char* str)\n{\n\tfloat args[1];\n\tint na = 0;\n\tfloat t[6];\n\tint len = nsvg__parseTransformArgs(str, args, 1, &na);\n\tnsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);\n\tmemcpy(xform, t, sizeof(float)*6);\n\treturn len;\n}\n\nstatic int nsvg__parseRotate(float* xform, const char* str)\n{\n\tfloat args[3];\n\tint na = 0;\n\tfloat m[6];\n\tfloat t[6];\n\tint len = nsvg__parseTransformArgs(str, args, 3, &na);\n\tif (na == 1)\n\t\targs[1] = args[2] = 0.0f;\n\tnsvg__xformIdentity(m);\n\n\tif (na > 1) {\n\t\tnsvg__xformSetTranslation(t, -args[1], -args[2]);\n\t\tnsvg__xformMultiply(m, t);\n\t}\n\n\tnsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);\n\tnsvg__xformMultiply(m, t);\n\n\tif (na > 1) {\n\t\tnsvg__xformSetTranslation(t, args[1], args[2]);\n\t\tnsvg__xformMultiply(m, t);\n\t}\n\n\tmemcpy(xform, m, sizeof(float)*6);\n\n\treturn len;\n}\n\nstatic void nsvg__parseTransform(float* xform, const char* str)\n{\n\tfloat t[6];\n        int len;\n\tnsvg__xformIdentity(xform);\n\twhile (*str)\n\t{\n\t\tif (strncmp(str, \"matrix\", 6) == 0)\n\t\t\tlen = nsvg__parseMatrix(t, str);\n\t\telse if (strncmp(str, \"translate\", 9) == 0)\n\t\t\tlen = nsvg__parseTranslate(t, str);\n\t\telse if (strncmp(str, \"scale\", 5) == 0)\n\t\t\tlen = nsvg__parseScale(t, str);\n\t\telse if (strncmp(str, \"rotate\", 6) == 0)\n\t\t\tlen = nsvg__parseRotate(t, str);\n\t\telse if (strncmp(str, \"skewX\", 5) == 0)\n\t\t\tlen = nsvg__parseSkewX(t, str);\n\t\telse if (strncmp(str, \"skewY\", 5) == 0)\n\t\t\tlen = nsvg__parseSkewY(t, str);\n\t\telse{\n\t\t\t++str;\n\t\t\tcontinue;\n\t\t}\n                if (len != 0) {\n\t\t\tstr += len;\n                } else {\n\t\t\t++str;\n\t\t\tcontinue;\n                }\n\n\t\tnsvg__xformPremultiply(xform, t);\n\t}\n}\n\nstatic void nsvg__parseUrl(char* id, const char* str)\n{\n\tint i = 0;\n\tstr += 4; /* \"url(\"; */\n\tif (*str && *str == '#')\n\t\tstr++;\n\twhile (i < 63 && *str && *str != ')') {\n\t\tid[i] = *str++;\n\t\ti++;\n\t}\n\tid[i] = '\\0';\n}\n\nstatic char nsvg__parseLineCap(const char* str)\n{\n\tif (strcmp(str, \"butt\") == 0)\n\t\treturn NSVG_CAP_BUTT;\n\telse if (strcmp(str, \"round\") == 0)\n\t\treturn NSVG_CAP_ROUND;\n\telse if (strcmp(str, \"square\") == 0)\n\t\treturn NSVG_CAP_SQUARE;\n\t/* TODO: handle inherit. */\n\treturn NSVG_CAP_BUTT;\n}\n\nstatic char nsvg__parseLineJoin(const char* str)\n{\n\tif (strcmp(str, \"miter\") == 0)\n\t\treturn NSVG_JOIN_MITER;\n\telse if (strcmp(str, \"round\") == 0)\n\t\treturn NSVG_JOIN_ROUND;\n\telse if (strcmp(str, \"bevel\") == 0)\n\t\treturn NSVG_JOIN_BEVEL;\n\t/* TODO: handle inherit. */\n\treturn NSVG_JOIN_MITER;\n}\n\nstatic char nsvg__parseFillRule(const char* str)\n{\n\tif (strcmp(str, \"nonzero\") == 0)\n\t\treturn NSVG_FILLRULE_NONZERO;\n\telse if (strcmp(str, \"evenodd\") == 0)\n\t\treturn NSVG_FILLRULE_EVENODD;\n\t/* TODO: handle inherit. */\n\treturn NSVG_FILLRULE_NONZERO;\n}\n\nstatic unsigned char nsvg__parsePaintOrder(const char* str)\n{\n\tif (strcmp(str, \"normal\") == 0 || strcmp(str, \"fill stroke markers\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);\n\telse if (strcmp(str, \"fill markers stroke\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE);\n\telse if (strcmp(str, \"markers fill stroke\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_FILL, NSVG_PAINT_STROKE);\n\telse if (strcmp(str, \"markers stroke fill\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE, NSVG_PAINT_FILL);\n\telse if (strcmp(str, \"stroke fill markers\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_FILL, NSVG_PAINT_MARKERS);\n\telse if (strcmp(str, \"stroke markers fill\") == 0)\n\t\treturn nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS, NSVG_PAINT_FILL);\n\t/* TODO: handle inherit. */\n\treturn nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);\n}\n\nstatic const char* nsvg__getNextDashItem(const char* s, char* it)\n{\n\tint n = 0;\n\tit[0] = '\\0';\n\t/* Skip white spaces and commas */\n\twhile (*s && (nsvg__isspace(*s) || *s == ',')) s++;\n\t/* Advance until whitespace, comma or end. */\n\twhile (*s && (!nsvg__isspace(*s) && *s != ',')) {\n\t\tif (n < 63)\n\t\t\tit[n++] = *s;\n\t\ts++;\n\t}\n\tit[n++] = '\\0';\n\treturn s;\n}\n\nstatic int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)\n{\n\tchar item[64];\n\tint count = 0, i;\n\tfloat sum = 0.0f;\n\n\t/* Handle \"none\" */\n\tif (str[0] == 'n')\n\t\treturn 0;\n\n\t/* Parse dashes */\n\twhile (*str) {\n\t\tstr = nsvg__getNextDashItem(str, item);\n\t\tif (!*item) break;\n\t\tif (count < NSVG_MAX_DASHES)\n\t\t\tstrokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));\n\t}\n\n\tfor (i = 0; i < count; i++)\n\t\tsum += strokeDashArray[i];\n\tif (sum <= 1e-6f)\n\t\tcount = 0;\n\n\treturn count;\n}\n\nstatic void nsvg__parseStyle(NSVGparser* p, const char* str);\n\nstatic int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)\n{\n\tfloat xform[6];\n\tNSVGattrib* attr = nsvg__getAttr(p);\n\tif (!attr) return 0;\n\n\tif (strcmp(name, \"style\") == 0) {\n\t\tnsvg__parseStyle(p, value);\n\t} else if (strcmp(name, \"display\") == 0) {\n\t\tif (strcmp(value, \"none\") == 0)\n\t\t\tattr->visible &= ~NSVG_VIS_DISPLAY;\n\t\t/* Don't reset ->visible on display:inline, one display:none hides the whole subtree */\n\n\t} else if (strcmp(name, \"visibility\") == 0) {\n\t\tif (strcmp(value, \"hidden\") == 0) {\n\t\t\tattr->visible &= ~NSVG_VIS_VISIBLE;\n\t\t} else if (strcmp(value, \"visible\") == 0) {\n\t\t\tattr->visible |= NSVG_VIS_VISIBLE;\n\t\t}\n\t} else if (strcmp(name, \"fill\") == 0) {\n\t\tif (strcmp(value, \"none\") == 0) {\n\t\t\tattr->hasFill = 0;\n\t\t} else if (strncmp(value, \"url(\", 4) == 0) {\n\t\t\tattr->hasFill = 2;\n\t\t\tnsvg__parseUrl(attr->fillGradient, value);\n\t\t} else {\n\t\t\tattr->hasFill = 1;\n\t\t\tattr->fillColor = nsvg__parseColor(value);\n\t\t}\n\t} else if (strcmp(name, \"opacity\") == 0) {\n\t\tattr->opacity = nsvg__parseOpacity(value);\n\t} else if (strcmp(name, \"fill-opacity\") == 0) {\n\t\tattr->fillOpacity = nsvg__parseOpacity(value);\n\t} else if (strcmp(name, \"stroke\") == 0) {\n\t\tif (strcmp(value, \"none\") == 0) {\n\t\t\tattr->hasStroke = 0;\n\t\t} else if (strncmp(value, \"url(\", 4) == 0) {\n\t\t\tattr->hasStroke = 2;\n\t\t\tnsvg__parseUrl(attr->strokeGradient, value);\n\t\t} else {\n\t\t\tattr->hasStroke = 1;\n\t\t\tattr->strokeColor = nsvg__parseColor(value);\n\t\t}\n\t} else if (strcmp(name, \"stroke-width\") == 0) {\n\t\tattr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));\n\t} else if (strcmp(name, \"stroke-dasharray\") == 0) {\n\t\tattr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);\n\t} else if (strcmp(name, \"stroke-dashoffset\") == 0) {\n\t\tattr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));\n\t} else if (strcmp(name, \"stroke-opacity\") == 0) {\n\t\tattr->strokeOpacity = nsvg__parseOpacity(value);\n\t} else if (strcmp(name, \"stroke-linecap\") == 0) {\n\t\tattr->strokeLineCap = nsvg__parseLineCap(value);\n\t} else if (strcmp(name, \"stroke-linejoin\") == 0) {\n\t\tattr->strokeLineJoin = nsvg__parseLineJoin(value);\n\t} else if (strcmp(name, \"stroke-miterlimit\") == 0) {\n\t\tattr->miterLimit = nsvg__parseMiterLimit(value);\n\t} else if (strcmp(name, \"fill-rule\") == 0) {\n\t\tattr->fillRule = nsvg__parseFillRule(value);\n\t} else if (strcmp(name, \"font-size\") == 0) {\n\t\tattr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));\n\t} else if (strcmp(name, \"transform\") == 0) {\n\t\tnsvg__parseTransform(xform, value);\n\t\tnsvg__xformPremultiply(attr->xform, xform);\n\t} else if (strcmp(name, \"stop-color\") == 0) {\n\t\tattr->stopColor = nsvg__parseColor(value);\n\t} else if (strcmp(name, \"stop-opacity\") == 0) {\n\t\tattr->stopOpacity = nsvg__parseOpacity(value);\n\t} else if (strcmp(name, \"offset\") == 0) {\n\t\tattr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);\n\t} else if (strcmp(name, \"paint-order\") == 0) {\n\t\tattr->paintOrder = nsvg__parsePaintOrder(value);\n\t} else if (strcmp(name, \"id\") == 0) {\n\t\tstrncpy(attr->id, value, 63);\n\t\tattr->id[63] = '\\0';\n\t} else if (strcmp(name, \"class\") == 0) {\n\t\tNSVGstyles* style = p->styles;\n\t\twhile (style) {\n\t\t\tif (strcmp(style->name + 1, value) == 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstyle = style->next;\n\t\t}\n\t\tif (style) {\n\t\t\tnsvg__parseStyle(p, style->description);\n\t\t}\n\t} else {\n\t\treturn 0;\n\t}\n\treturn 1;\n}\n\nstatic int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)\n{\n\tconst char* str;\n\tconst char* val;\n\tchar name[512];\n\tchar value[512];\n\tint n;\n\n\tstr = start;\n\twhile (str < end && *str != ':') ++str;\n\n\tval = str;\n\n\t/* Right Trim */\n\twhile (str > start &&  (*str == ':' || nsvg__isspace(*str))) --str;\n\t++str;\n\n\tn = (int)(str - start);\n\tif (n > 511) n = 511;\n\tif (n) memcpy(name, start, n);\n\tname[n] = 0;\n\n\twhile (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;\n\n\tn = (int)(end - val);\n\tif (n > 511) n = 511;\n\tif (n) memcpy(value, val, n);\n\tvalue[n] = 0;\n\n\treturn nsvg__parseAttr(p, name, value);\n}\n\nstatic void nsvg__parseStyle(NSVGparser* p, const char* str)\n{\n\tconst char* start;\n\tconst char* end;\n\n\twhile (*str) {\n\t\t/* Left Trim */\n\t\twhile(*str && nsvg__isspace(*str)) ++str;\n\t\tstart = str;\n\t\twhile(*str && *str != ';') ++str;\n\t\tend = str;\n\n\t\t/* Right Trim */\n\t\twhile (end > start &&  (*end == ';' || nsvg__isspace(*end))) --end;\n\t\t++end;\n\n\t\tnsvg__parseNameValue(p, start, end);\n\t\tif (*str) ++str;\n\t}\n}\n\nstatic void nsvg__parseAttribs(NSVGparser* p, const char** attr)\n{\n\tint i;\n\tfor (i = 0; attr[i]; i += 2)\n\t{\n\t\tif (strcmp(attr[i], \"style\") == 0)\n\t\t\tnsvg__parseStyle(p, attr[i + 1]);\n\t\telse\n\t\t\tnsvg__parseAttr(p, attr[i], attr[i + 1]);\n\t}\n}\n\nstatic int nsvg__getArgsPerElement(char cmd)\n{\n\tswitch (cmd) {\n\t\tcase 'v':\n\t\tcase 'V':\n\t\tcase 'h':\n\t\tcase 'H':\n\t\t\treturn 1;\n\t\tcase 'm':\n\t\tcase 'M':\n\t\tcase 'l':\n\t\tcase 'L':\n\t\tcase 't':\n\t\tcase 'T':\n\t\t\treturn 2;\n\t\tcase 'q':\n\t\tcase 'Q':\n\t\tcase 's':\n\t\tcase 'S':\n\t\t\treturn 4;\n\t\tcase 'c':\n\t\tcase 'C':\n\t\t\treturn 6;\n\t\tcase 'a':\n\t\tcase 'A':\n\t\t\treturn 7;\n\t\tcase 'z':\n\t\tcase 'Z':\n\t\t\treturn 0;\n\t}\n\treturn -1;\n}\n\nstatic void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)\n{\n\tif (rel) {\n\t\t*cpx += args[0];\n\t\t*cpy += args[1];\n\t} else {\n\t\t*cpx = args[0];\n\t\t*cpy = args[1];\n\t}\n\tnsvg__moveTo(p, *cpx, *cpy);\n}\n\nstatic void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)\n{\n\tif (rel) {\n\t\t*cpx += args[0];\n\t\t*cpy += args[1];\n\t} else {\n\t\t*cpx = args[0];\n\t\t*cpy = args[1];\n\t}\n\tnsvg__lineTo(p, *cpx, *cpy);\n}\n\nstatic void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)\n{\n\tif (rel)\n\t\t*cpx += args[0];\n\telse\n\t\t*cpx = args[0];\n\tnsvg__lineTo(p, *cpx, *cpy);\n}\n\nstatic void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)\n{\n\tif (rel)\n\t\t*cpy += args[0];\n\telse\n\t\t*cpy = args[0];\n\tnsvg__lineTo(p, *cpx, *cpy);\n}\n\nstatic void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,\n\t\t\t\t\t\t\t\t float* cpx2, float* cpy2, float* args, int rel)\n{\n\tfloat x2, y2, cx1, cy1, cx2, cy2;\n\n\tif (rel) {\n\t\tcx1 = *cpx + args[0];\n\t\tcy1 = *cpy + args[1];\n\t\tcx2 = *cpx + args[2];\n\t\tcy2 = *cpy + args[3];\n\t\tx2 = *cpx + args[4];\n\t\ty2 = *cpy + args[5];\n\t} else {\n\t\tcx1 = args[0];\n\t\tcy1 = args[1];\n\t\tcx2 = args[2];\n\t\tcy2 = args[3];\n\t\tx2 = args[4];\n\t\ty2 = args[5];\n\t}\n\n\tnsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);\n\n\t*cpx2 = cx2;\n\t*cpy2 = cy2;\n\t*cpx = x2;\n\t*cpy = y2;\n}\n\nstatic void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,\n\t\t\t\t\t\t\t\t\t  float* cpx2, float* cpy2, float* args, int rel)\n{\n\tfloat x1, y1, x2, y2, cx1, cy1, cx2, cy2;\n\n\tx1 = *cpx;\n\ty1 = *cpy;\n\tif (rel) {\n\t\tcx2 = *cpx + args[0];\n\t\tcy2 = *cpy + args[1];\n\t\tx2 = *cpx + args[2];\n\t\ty2 = *cpy + args[3];\n\t} else {\n\t\tcx2 = args[0];\n\t\tcy2 = args[1];\n\t\tx2 = args[2];\n\t\ty2 = args[3];\n\t}\n\n\tcx1 = 2*x1 - *cpx2;\n\tcy1 = 2*y1 - *cpy2;\n\n\tnsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);\n\n\t*cpx2 = cx2;\n\t*cpy2 = cy2;\n\t*cpx = x2;\n\t*cpy = y2;\n}\n\nstatic void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,\n\t\t\t\t\t\t\t\tfloat* cpx2, float* cpy2, float* args, int rel)\n{\n\tfloat x1, y1, x2, y2, cx, cy;\n\tfloat cx1, cy1, cx2, cy2;\n\n\tx1 = *cpx;\n\ty1 = *cpy;\n\tif (rel) {\n\t\tcx = *cpx + args[0];\n\t\tcy = *cpy + args[1];\n\t\tx2 = *cpx + args[2];\n\t\ty2 = *cpy + args[3];\n\t} else {\n\t\tcx = args[0];\n\t\tcy = args[1];\n\t\tx2 = args[2];\n\t\ty2 = args[3];\n\t}\n\n\t/* Convert to cubic bezier */\n\tcx1 = x1 + 2.0f/3.0f*(cx - x1);\n\tcy1 = y1 + 2.0f/3.0f*(cy - y1);\n\tcx2 = x2 + 2.0f/3.0f*(cx - x2);\n\tcy2 = y2 + 2.0f/3.0f*(cy - y2);\n\n\tnsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);\n\n\t*cpx2 = cx;\n\t*cpy2 = cy;\n\t*cpx = x2;\n\t*cpy = y2;\n}\n\nstatic void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,\n\t\t\t\t\t\t\t\t\t float* cpx2, float* cpy2, float* args, int rel)\n{\n\tfloat x1, y1, x2, y2, cx, cy;\n\tfloat cx1, cy1, cx2, cy2;\n\n\tx1 = *cpx;\n\ty1 = *cpy;\n\tif (rel) {\n\t\tx2 = *cpx + args[0];\n\t\ty2 = *cpy + args[1];\n\t} else {\n\t\tx2 = args[0];\n\t\ty2 = args[1];\n\t}\n\n\tcx = 2*x1 - *cpx2;\n\tcy = 2*y1 - *cpy2;\n\n\t/* Convert to cubix bezier */\n\tcx1 = x1 + 2.0f/3.0f*(cx - x1);\n\tcy1 = y1 + 2.0f/3.0f*(cy - y1);\n\tcx2 = x2 + 2.0f/3.0f*(cx - x2);\n\tcy2 = y2 + 2.0f/3.0f*(cy - y2);\n\n\tnsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);\n\n\t*cpx2 = cx;\n\t*cpy2 = cy;\n\t*cpx = x2;\n\t*cpy = y2;\n}\n\nstatic float nsvg__sqr(float x) { return x*x; }\nstatic float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }\n\nstatic float nsvg__vecrat(float ux, float uy, float vx, float vy)\n{\n\treturn (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));\n}\n\nstatic float nsvg__vecang(float ux, float uy, float vx, float vy)\n{\n\tfloat r = nsvg__vecrat(ux,uy, vx,vy);\n\tif (r < -1.0f) r = -1.0f;\n\tif (r > 1.0f) r = 1.0f;\n\treturn ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);\n}\n\nstatic void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)\n{\n\t/* Ported from canvg (https://code.google.com/p/canvg/) */\n\tfloat rx, ry, rotx;\n\tfloat x1, y1, x2, y2, cx, cy, dx, dy, d;\n\tfloat x1p, y1p, cxp, cyp, s, sa, sb;\n\tfloat ux, uy, vx, vy, a1, da;\n\tfloat x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];\n\tfloat sinrx, cosrx;\n\tint fa, fs;\n\tint i, ndivs;\n\tfloat hda, kappa;\n\n\trx = fabsf(args[0]);\t\t\t\t/* y radius */\n\try = fabsf(args[1]);\t\t\t\t/* x radius */\n\trotx = args[2] / 180.0f * NSVG_PI;\t\t/* x rotation angle */\n\tfa = fabsf(args[3]) > 1e-6 ? 1 : 0;\t/* Large arc */\n\tfs = fabsf(args[4]) > 1e-6 ? 1 : 0;\t/* Sweep direction */\n\tx1 = *cpx;\t\t\t\t\t\t\t/* start point */\n\ty1 = *cpy;\n\tif (rel) {\t\t\t\t\t\t\t/* end point */\n\t\tx2 = *cpx + args[5];\n\t\ty2 = *cpy + args[6];\n\t} else {\n\t\tx2 = args[5];\n\t\ty2 = args[6];\n\t}\n\n\tdx = x1 - x2;\n\tdy = y1 - y2;\n\td = sqrtf(dx*dx + dy*dy);\n\tif (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {\n\t\t/* The arc degenerates to a line */\n\t\tnsvg__lineTo(p, x2, y2);\n\t\t*cpx = x2;\n\t\t*cpy = y2;\n\t\treturn;\n\t}\n\n\tsinrx = sinf(rotx);\n\tcosrx = cosf(rotx);\n\n\t/* Convert to center point parameterization. */\n\t/* http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes */\n\t/* 1) Compute x1', y1' */\n\tx1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;\n\ty1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;\n\td = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);\n\tif (d > 1) {\n\t\td = sqrtf(d);\n\t\trx *= d;\n\t\try *= d;\n\t}\n\t/* 2) Compute cx', cy' */\n\ts = 0.0f;\n\tsa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);\n\tsb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);\n\tif (sa < 0.0f) sa = 0.0f;\n\tif (sb > 0.0f)\n\t\ts = sqrtf(sa / sb);\n\tif (fa == fs)\n\t\ts = -s;\n\tcxp = s * rx * y1p / ry;\n\tcyp = s * -ry * x1p / rx;\n\n\t/* 3) Compute cx,cy from cx',cy' */\n\tcx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;\n\tcy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;\n\n\t/* 4) Calculate theta1, and delta theta. */\n\tux = (x1p - cxp) / rx;\n\tuy = (y1p - cyp) / ry;\n\tvx = (-x1p - cxp) / rx;\n\tvy = (-y1p - cyp) / ry;\n\ta1 = nsvg__vecang(1.0f,0.0f, ux,uy);\t/* Initial angle */\n\tda = nsvg__vecang(ux,uy, vx,vy);\t\t/* Delta angle */\n\n/*\tif (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; */\n/*\tif (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; */\n\n\tif (fs == 0 && da > 0)\n\t\tda -= 2 * NSVG_PI;\n\telse if (fs == 1 && da < 0)\n\t\tda += 2 * NSVG_PI;\n\n\t/* Approximate the arc using cubic spline segments. */\n\tt[0] = cosrx; t[1] = sinrx;\n\tt[2] = -sinrx; t[3] = cosrx;\n\tt[4] = cx; t[5] = cy;\n\n\t/* Split arc into max 90 degree segments. */\n\t/* The loop assumes an iteration per end point (including start and end), this +1. */\n\tndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);\n\thda = (da / (float)ndivs) / 2.0f;\n\t/* Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) */\n\tif ((hda < 1e-3f) && (hda > -1e-3f))\n\t\thda *= 0.5f;\n\telse\n\t\thda = (1.0f - cosf(hda)) / sinf(hda);\n\tkappa = fabsf(4.0f / 3.0f * hda);\n\tif (da < 0.0f)\n\t\tkappa = -kappa;\n\n\tfor (i = 0; i <= ndivs; i++) {\n\t\ta = a1 + da * ((float)i/(float)ndivs);\n\t\tdx = cosf(a);\n\t\tdy = sinf(a);\n\t\tnsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); /* position */\n\t\tnsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); /* tangent */\n\t\tif (i > 0)\n\t\t\tnsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);\n\t\tpx = x;\n\t\tpy = y;\n\t\tptanx = tanx;\n\t\tptany = tany;\n\t}\n\n\t*cpx = x2;\n\t*cpy = y2;\n}\n\nstatic void nsvg__parsePath(NSVGparser* p, const char** attr)\n{\n\tconst char* s = NULL;\n\tchar cmd = '\\0';\n\tfloat args[10];\n\tint nargs;\n\tint rargs = 0;\n\tchar initPoint;\n\tfloat cpx, cpy, cpx2, cpy2;\n\tconst char* tmp[4];\n\tchar closedFlag;\n\tint i;\n\tchar item[64];\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (strcmp(attr[i], \"d\") == 0) {\n\t\t\ts = attr[i + 1];\n\t\t} else {\n\t\t\ttmp[0] = attr[i];\n\t\t\ttmp[1] = attr[i + 1];\n\t\t\ttmp[2] = 0;\n\t\t\ttmp[3] = 0;\n\t\t\tnsvg__parseAttribs(p, tmp);\n\t\t}\n\t}\n\n\tif (s) {\n\t\tnsvg__resetPath(p);\n\t\tcpx = 0; cpy = 0;\n\t\tcpx2 = 0; cpy2 = 0;\n\t\tinitPoint = 0;\n\t\tclosedFlag = 0;\n\t\tnargs = 0;\n\n\t\twhile (*s) {\n\t\t\titem[0] = '\\0';\n\t\t\tif ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))\n\t\t\t\ts = nsvg__getNextPathItemWhenArcFlag(s, item);\n\t\t\tif (!*item)\n\t\t\t\ts = nsvg__getNextPathItem(s, item);\n\t\t\tif (!*item) break;\n\t\t\tif (cmd != '\\0' && nsvg__isCoordinate(item)) {\n\t\t\t\tif (nargs < 10)\n\t\t\t\t\targs[nargs++] = (float)nsvg__atof(item);\n\t\t\t\tif (nargs >= rargs) {\n\t\t\t\t\tswitch (cmd) {\n\t\t\t\t\t\tcase 'm':\n\t\t\t\t\t\tcase 'M':\n\t\t\t\t\t\t\tnsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);\n\t\t\t\t\t\t\t/* Moveto can be followed by multiple coordinate pairs, */\n\t\t\t\t\t\t\t/* which should be treated as linetos. */\n\t\t\t\t\t\t\tcmd = (cmd == 'm') ? 'l' : 'L';\n\t\t\t\t\t\t\trargs = nsvg__getArgsPerElement(cmd);\n\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\tinitPoint = 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'l':\n\t\t\t\t\t\tcase 'L':\n\t\t\t\t\t\t\tnsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);\n\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'H':\n\t\t\t\t\t\tcase 'h':\n\t\t\t\t\t\t\tnsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);\n\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'V':\n\t\t\t\t\t\tcase 'v':\n\t\t\t\t\t\t\tnsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);\n\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'C':\n\t\t\t\t\t\tcase 'c':\n\t\t\t\t\t\t\tnsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'S':\n\t\t\t\t\t\tcase 's':\n\t\t\t\t\t\t\tnsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\tcase 'q':\n\t\t\t\t\t\t\tnsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'T':\n\t\t\t\t\t\tcase 't':\n\t\t\t\t\t\t\tnsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'A':\n\t\t\t\t\t\tcase 'a':\n\t\t\t\t\t\t\tnsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);\n\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tif (nargs >= 2) {\n\t\t\t\t\t\t\t\tcpx = args[nargs-2];\n\t\t\t\t\t\t\t\tcpy = args[nargs-1];\n\t\t\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tnargs = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcmd = item[0];\n\t\t\t\tif (cmd == 'M' || cmd == 'm') {\n\t\t\t\t\t/* Commit path. */\n\t\t\t\t\tif (p->npts > 0)\n\t\t\t\t\t\tnsvg__addPath(p, closedFlag);\n\t\t\t\t\t/* Start new subpath. */\n\t\t\t\t\tnsvg__resetPath(p);\n\t\t\t\t\tclosedFlag = 0;\n\t\t\t\t\tnargs = 0;\n\t\t\t\t} else if (initPoint == 0) {\n\t\t\t\t\t/* Do not allow other commands until initial point has been set (moveTo called once). */\n\t\t\t\t\tcmd = '\\0';\n\t\t\t\t}\n\t\t\t\tif (cmd == 'Z' || cmd == 'z') {\n\t\t\t\t\tclosedFlag = 1;\n\t\t\t\t\t/* Commit path. */\n\t\t\t\t\tif (p->npts > 0) {\n\t\t\t\t\t\t/* Move current point to first point */\n\t\t\t\t\t\tcpx = p->pts[0];\n\t\t\t\t\t\tcpy = p->pts[1];\n\t\t\t\t\t\tcpx2 = cpx; cpy2 = cpy;\n\t\t\t\t\t\tnsvg__addPath(p, closedFlag);\n\t\t\t\t\t}\n\t\t\t\t\t/* Start new subpath. */\n\t\t\t\t\tnsvg__resetPath(p);\n\t\t\t\t\tnsvg__moveTo(p, cpx, cpy);\n\t\t\t\t\tclosedFlag = 0;\n\t\t\t\t\tnargs = 0;\n\t\t\t\t}\n\t\t\t\trargs = nsvg__getArgsPerElement(cmd);\n\t\t\t\tif (rargs == -1) {\n\t\t\t\t\t/* Command not recognized */\n\t\t\t\t\tcmd = '\\0';\n\t\t\t\t\trargs = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/* Commit path. */\n\t\tif (p->npts)\n\t\t\tnsvg__addPath(p, closedFlag);\n\t}\n\n\tnsvg__addShape(p);\n}\n\nstatic void nsvg__parseRect(NSVGparser* p, const char** attr)\n{\n\tfloat x = 0.0f;\n\tfloat y = 0.0f;\n\tfloat w = 0.0f;\n\tfloat h = 0.0f;\n\tfloat rx = -1.0f; /* marks not set */\n\tfloat ry = -1.0f;\n\tint i;\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"x\") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"y\") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));\n\t\t\tif (strcmp(attr[i], \"width\") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"height\") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));\n\t\t\tif (strcmp(attr[i], \"rx\") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));\n\t\t\tif (strcmp(attr[i], \"ry\") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));\n\t\t}\n\t}\n\n\tif (rx < 0.0f && ry > 0.0f) rx = ry;\n\tif (ry < 0.0f && rx > 0.0f) ry = rx;\n\tif (rx < 0.0f) rx = 0.0f;\n\tif (ry < 0.0f) ry = 0.0f;\n\tif (rx > w/2.0f) rx = w/2.0f;\n\tif (ry > h/2.0f) ry = h/2.0f;\n\n\tif (w != 0.0f && h != 0.0f) {\n\t\tnsvg__resetPath(p);\n\n\t\tif (rx < 0.00001f || ry < 0.0001f) {\n\t\t\tnsvg__moveTo(p, x, y);\n\t\t\tnsvg__lineTo(p, x+w, y);\n\t\t\tnsvg__lineTo(p, x+w, y+h);\n\t\t\tnsvg__lineTo(p, x, y+h);\n\t\t} else {\n\t\t\t/* Rounded rectangle */\n\t\t\tnsvg__moveTo(p, x+rx, y);\n\t\t\tnsvg__lineTo(p, x+w-rx, y);\n\t\t\tnsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);\n\t\t\tnsvg__lineTo(p, x+w, y+h-ry);\n\t\t\tnsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);\n\t\t\tnsvg__lineTo(p, x+rx, y+h);\n\t\t\tnsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);\n\t\t\tnsvg__lineTo(p, x, y+ry);\n\t\t\tnsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);\n\t\t}\n\n\t\tnsvg__addPath(p, 1);\n\n\t\tnsvg__addShape(p);\n\t}\n}\n\nstatic void nsvg__parseCircle(NSVGparser* p, const char** attr)\n{\n\tfloat cx = 0.0f;\n\tfloat cy = 0.0f;\n\tfloat r = 0.0f;\n\tint i;\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"cx\") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"cy\") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));\n\t\t\tif (strcmp(attr[i], \"r\") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));\n\t\t}\n\t}\n\n\tif (r > 0.0f) {\n\t\tnsvg__resetPath(p);\n\n\t\tnsvg__moveTo(p, cx+r, cy);\n\t\tnsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);\n\t\tnsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);\n\t\tnsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);\n\t\tnsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);\n\n\t\tnsvg__addPath(p, 1);\n\n\t\tnsvg__addShape(p);\n\t}\n}\n\nstatic void nsvg__parseEllipse(NSVGparser* p, const char** attr)\n{\n\tfloat cx = 0.0f;\n\tfloat cy = 0.0f;\n\tfloat rx = 0.0f;\n\tfloat ry = 0.0f;\n\tint i;\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"cx\") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"cy\") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));\n\t\t\tif (strcmp(attr[i], \"rx\") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));\n\t\t\tif (strcmp(attr[i], \"ry\") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));\n\t\t}\n\t}\n\n\tif (rx > 0.0f && ry > 0.0f) {\n\n\t\tnsvg__resetPath(p);\n\n\t\tnsvg__moveTo(p, cx+rx, cy);\n\t\tnsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);\n\t\tnsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);\n\t\tnsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);\n\t\tnsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);\n\n\t\tnsvg__addPath(p, 1);\n\n\t\tnsvg__addShape(p);\n\t}\n}\n\nstatic void nsvg__parseLine(NSVGparser* p, const char** attr)\n{\n\tfloat x1 = 0.0;\n\tfloat y1 = 0.0;\n\tfloat x2 = 0.0;\n\tfloat y2 = 0.0;\n\tint i;\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"x1\") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"y1\") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));\n\t\t\tif (strcmp(attr[i], \"x2\") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));\n\t\t\tif (strcmp(attr[i], \"y2\") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));\n\t\t}\n\t}\n\n\tnsvg__resetPath(p);\n\n\tnsvg__moveTo(p, x1, y1);\n\tnsvg__lineTo(p, x2, y2);\n\n\tnsvg__addPath(p, 0);\n\n\tnsvg__addShape(p);\n}\n\nstatic void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)\n{\n\tint i;\n\tconst char* s;\n\tfloat args[2];\n\tint nargs, npts = 0;\n\tchar item[64];\n\n\tnsvg__resetPath(p);\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"points\") == 0) {\n\t\t\t\ts = attr[i + 1];\n\t\t\t\tnargs = 0;\n\t\t\t\twhile (*s) {\n\t\t\t\t\ts = nsvg__getNextPathItem(s, item);\n\t\t\t\t\targs[nargs++] = (float)nsvg__atof(item);\n\t\t\t\t\tif (nargs >= 2) {\n\t\t\t\t\t\tif (npts == 0)\n\t\t\t\t\t\t\tnsvg__moveTo(p, args[0], args[1]);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tnsvg__lineTo(p, args[0], args[1]);\n\t\t\t\t\t\tnargs = 0;\n\t\t\t\t\t\tnpts++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tnsvg__addPath(p, (char)closeFlag);\n\n\tnsvg__addShape(p);\n}\n\nstatic void nsvg__parseSVG(NSVGparser* p, const char** attr)\n{\n\tint i;\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"width\") == 0) {\n\t\t\t\tp->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);\n\t\t\t} else if (strcmp(attr[i], \"height\") == 0) {\n\t\t\t\tp->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);\n\t\t\t} else if (strcmp(attr[i], \"viewBox\") == 0) {\n\t\t\t\tsscanf(attr[i + 1], \"%f%*[%%, \\t]%f%*[%%, \\t]%f%*[%%, \\t]%f\", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight);\n\t\t\t} else if (strcmp(attr[i], \"preserveAspectRatio\") == 0) {\n\t\t\t\tif (strstr(attr[i + 1], \"none\") != 0) {\n\t\t\t\t\t/* No uniform scaling */\n\t\t\t\t\tp->alignType = NSVG_ALIGN_NONE;\n\t\t\t\t} else {\n\t\t\t\t\t/* Parse X align */\n\t\t\t\t\tif (strstr(attr[i + 1], \"xMin\") != 0)\n\t\t\t\t\t\tp->alignX = NSVG_ALIGN_MIN;\n\t\t\t\t\telse if (strstr(attr[i + 1], \"xMid\") != 0)\n\t\t\t\t\t\tp->alignX = NSVG_ALIGN_MID;\n\t\t\t\t\telse if (strstr(attr[i + 1], \"xMax\") != 0)\n\t\t\t\t\t\tp->alignX = NSVG_ALIGN_MAX;\n\t\t\t\t\t/* Parse X align */\n\t\t\t\t\tif (strstr(attr[i + 1], \"yMin\") != 0)\n\t\t\t\t\t\tp->alignY = NSVG_ALIGN_MIN;\n\t\t\t\t\telse if (strstr(attr[i + 1], \"yMid\") != 0)\n\t\t\t\t\t\tp->alignY = NSVG_ALIGN_MID;\n\t\t\t\t\telse if (strstr(attr[i + 1], \"yMax\") != 0)\n\t\t\t\t\t\tp->alignY = NSVG_ALIGN_MAX;\n\t\t\t\t\t/* Parse meet/slice */\n\t\t\t\t\tp->alignType = NSVG_ALIGN_MEET;\n\t\t\t\t\tif (strstr(attr[i + 1], \"slice\") != 0)\n\t\t\t\t\t\tp->alignType = NSVG_ALIGN_SLICE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nstatic void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type)\n{\n\tint i;\n\tNSVGgradientData* grad = (NSVGgradientData*)NANOSVG_malloc(sizeof(NSVGgradientData));\n\tif (grad == NULL) return;\n\tmemset(grad, 0, sizeof(NSVGgradientData));\n\tgrad->units = NSVG_OBJECT_SPACE;\n\tgrad->type = type;\n\tif (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {\n\t\tgrad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);\n\t\tgrad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);\n\t\tgrad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);\n\t\tgrad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);\n\t} else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {\n\t\tgrad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);\n\t\tgrad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);\n\t\tgrad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);\n\t}\n\n\tnsvg__xformIdentity(grad->xform);\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tif (strcmp(attr[i], \"id\") == 0) {\n\t\t\tstrncpy(grad->id, attr[i+1], 63);\n\t\t\tgrad->id[63] = '\\0';\n\t\t} else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {\n\t\t\tif (strcmp(attr[i], \"gradientUnits\") == 0) {\n\t\t\t\tif (strcmp(attr[i+1], \"objectBoundingBox\") == 0)\n\t\t\t\t\tgrad->units = NSVG_OBJECT_SPACE;\n\t\t\t\telse\n\t\t\t\t\tgrad->units = NSVG_USER_SPACE;\n\t\t\t} else if (strcmp(attr[i], \"gradientTransform\") == 0) {\n\t\t\t\tnsvg__parseTransform(grad->xform, attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"cx\") == 0) {\n\t\t\t\tgrad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"cy\") == 0) {\n\t\t\t\tgrad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"r\") == 0) {\n\t\t\t\tgrad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"fx\") == 0) {\n\t\t\t\tgrad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"fy\") == 0) {\n\t\t\t\tgrad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"x1\") == 0) {\n\t\t\t\tgrad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"y1\") == 0) {\n\t\t\t\tgrad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"x2\") == 0) {\n\t\t\t\tgrad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"y2\") == 0) {\n\t\t\t\tgrad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);\n\t\t\t} else if (strcmp(attr[i], \"spreadMethod\") == 0) {\n\t\t\t\tif (strcmp(attr[i+1], \"pad\") == 0)\n\t\t\t\t\tgrad->spread = NSVG_SPREAD_PAD;\n\t\t\t\telse if (strcmp(attr[i+1], \"reflect\") == 0)\n\t\t\t\t\tgrad->spread = NSVG_SPREAD_REFLECT;\n\t\t\t\telse if (strcmp(attr[i+1], \"repeat\") == 0)\n\t\t\t\t\tgrad->spread = NSVG_SPREAD_REPEAT;\n\t\t\t} else if (strcmp(attr[i], \"xlink:href\") == 0) {\n\t\t\t\tconst char *href = attr[i+1];\n\t\t\t\tstrncpy(grad->ref, href+1, 62);\n\t\t\t\tgrad->ref[62] = '\\0';\n\t\t\t}\n\t\t}\n\t}\n\n\tgrad->next = p->gradients;\n\tp->gradients = grad;\n}\n\nstatic void nsvg__parseGradientStop(NSVGparser* p, const char** attr)\n{\n\tNSVGattrib* curAttr = nsvg__getAttr(p);\n\tNSVGgradientData* grad;\n\tNSVGgradientStop* stop;\n\tint i, idx;\n\n\tcurAttr->stopOffset = 0;\n\tcurAttr->stopColor = 0;\n\tcurAttr->stopOpacity = 1.0f;\n\n\tfor (i = 0; attr[i]; i += 2) {\n\t\tnsvg__parseAttr(p, attr[i], attr[i + 1]);\n\t}\n\n\t/* Add stop to the last gradient. */\n\tgrad = p->gradients;\n\tif (grad == NULL) return;\n\n\tgrad->nstops++;\n\tgrad->stops = (NSVGgradientStop*)NANOSVG_realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);\n\tif (grad->stops == NULL) return;\n\n\t/* Insert */\n\tidx = grad->nstops-1;\n\tfor (i = 0; i < grad->nstops-1; i++) {\n\t\tif (curAttr->stopOffset < grad->stops[i].offset) {\n\t\t\tidx = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (idx != grad->nstops-1) {\n\t\tfor (i = grad->nstops-1; i > idx; i--)\n\t\t\tgrad->stops[i] = grad->stops[i-1];\n\t}\n\n\tstop = &grad->stops[idx];\n\tstop->color = curAttr->stopColor;\n\tstop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;\n\tstop->offset = curAttr->stopOffset;\n}\n\nstatic void nsvg__startElement(void* ud, const char* el, const char** attr)\n{\n\tNSVGparser* p = (NSVGparser*)ud;\n\n\tif (p->defsFlag) {\n\t\t/* Skip everything but gradients in defs */\n\t\tif (strcmp(el, \"linearGradient\") == 0) {\n\t\t\tnsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);\n\t\t} else if (strcmp(el, \"radialGradient\") == 0) {\n\t\t\tnsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);\n\t\t} else if (strcmp(el, \"stop\") == 0) {\n\t\t\tnsvg__parseGradientStop(p, attr);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (strcmp(el, \"g\") == 0) {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parseAttribs(p, attr);\n\t} else if (strcmp(el, \"path\") == 0) {\n\t\tif (p->pathFlag)\t/* Do not allow nested paths. */\n\t\t\treturn;\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parsePath(p, attr);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"rect\") == 0) {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parseRect(p, attr);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"circle\") == 0) {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parseCircle(p, attr);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"ellipse\") == 0) {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parseEllipse(p, attr);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"line\") == 0)  {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parseLine(p, attr);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"polyline\") == 0)  {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parsePoly(p, attr, 0);\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"polygon\") == 0)  {\n\t\tnsvg__pushAttr(p);\n\t\tnsvg__parsePoly(p, attr, 1);\n\t\tnsvg__popAttr(p);\n\t} else  if (strcmp(el, \"linearGradient\") == 0) {\n\t\tnsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);\n\t} else if (strcmp(el, \"radialGradient\") == 0) {\n\t\tnsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);\n\t} else if (strcmp(el, \"stop\") == 0) {\n\t\tnsvg__parseGradientStop(p, attr);\n\t} else if (strcmp(el, \"defs\") == 0) {\n\t\tp->defsFlag = 1;\n\t} else if (strcmp(el, \"svg\") == 0) {\n\t\tnsvg__parseSVG(p, attr);\n\t} else if (strcmp(el, \"style\") == 0) {\n\t\tp->styleFlag = 1;\n\t}\n}\n\nstatic void nsvg__endElement(void* ud, const char* el)\n{\n\tNSVGparser* p = (NSVGparser*)ud;\n\n\tif (strcmp(el, \"g\") == 0) {\n\t\tnsvg__popAttr(p);\n\t} else if (strcmp(el, \"path\") == 0) {\n\t\tp->pathFlag = 0;\n\t} else if (strcmp(el, \"defs\") == 0) {\n\t\tp->defsFlag = 0;\n\t} else if (strcmp(el, \"style\") == 0) {\n\t\tp->styleFlag = 0;\n\t}\n}\n\nstatic char *nsvg__strndup(const char *s, size_t n)\n{\n\tchar *result;\n\tsize_t len = strlen(s);\n\n\tif (n < len)\n\t\tlen = n;\n\n\tresult = (char*)NANOSVG_malloc(len+1);\n\tif (!result)\n\t\treturn 0;\n\n\tresult[len] = '\\0';\n\treturn (char *)memcpy(result, s, len);\n}\n\nstatic void nsvg__content(void* ud, const char* s)\n{\n\tNSVGparser* p = (NSVGparser*)ud;\n\tif (p->styleFlag) {\n\n\t\tint state = 0;\n\t\tconst char* start = NULL;\n\t\twhile (*s) {\n\t\t\tchar c = *s;\n\t\t\tif (nsvg__isspace(c) || c == '{') {\n\t\t\t\tif (state == 1) {\n\t\t\t\t\tNSVGstyles* next = p->styles;\n\n\t\t\t\t\tp->styles = (NSVGstyles*)NANOSVG_malloc(sizeof(NSVGstyles));\n\t\t\t\t\tp->styles->next = next;\n\t\t\t\t\tp->styles->name = nsvg__strndup(start, (size_t)(s - start));\n\t\t\t\t\tstart = s + 1;\n\t\t\t\t\tstate = 2;\n\t\t\t\t}\n\t\t\t} else if (state == 2 && c == '}') {\n\t\t\t\tp->styles->description = nsvg__strndup(start, (size_t)(s - start));\n\t\t\t\tstate = 0;\n\t\t\t}\n\t\t\telse if (state == 0) {\n\t\t\t\tstart = s;\n\t\t\t\tstate = 1;\n\t\t\t}\n\t\t\ts++;\n\t\t/*\n\t\t\tif (*s == '{' && state == NSVG_XML_CONTENT) {\n\t\t\t\t// Start of a tag\n\t\t\t\t*s++ = '\\0';\n\t\t\t\tnsvg__parseContent(mark, contentCb, ud);\n\t\t\t\tmark = s;\n\t\t\t\tstate = NSVG_XML_TAG;\n\t\t\t}\n\t\t\telse if (*s == '>' && state == NSVG_XML_TAG) {\n\t\t\t\t// Start of a content or new tag.\n\t\t\t\t*s++ = '\\0';\n\t\t\t\tnsvg__parseElement(mark, startelCb, endelCb, ud);\n\t\t\t\tmark = s;\n\t\t\t\tstate = NSVG_XML_CONTENT;\n\t\t\t}\n\t\t\telse {\n\t\t\t\ts++;\n\t\t\t}\n\t\t*/\n\t\t}\n\n\t}\n}\n\nstatic void nsvg__imageBounds(NSVGparser* p, float* bounds)\n{\n\tNSVGshape* shape;\n\tshape = p->image->shapes;\n\tif (shape == NULL) {\n\t\tbounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;\n\t\treturn;\n\t}\n\tbounds[0] = shape->bounds[0];\n\tbounds[1] = shape->bounds[1];\n\tbounds[2] = shape->bounds[2];\n\tbounds[3] = shape->bounds[3];\n\tfor (shape = shape->next; shape != NULL; shape = shape->next) {\n\t\tbounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);\n\t\tbounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);\n\t\tbounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);\n\t\tbounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);\n\t}\n}\n\nstatic float nsvg__viewAlign(float content, float container, int type)\n{\n\tif (type == NSVG_ALIGN_MIN)\n\t\treturn 0;\n\telse if (type == NSVG_ALIGN_MAX)\n\t\treturn container - content;\n\t/* mid */\n\treturn (container - content) * 0.5f;\n}\n\nstatic void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)\n{\n\tfloat t[6];\n\tnsvg__xformSetTranslation(t, tx, ty);\n\tnsvg__xformMultiply (grad->xform, t);\n\n\tnsvg__xformSetScale(t, sx, sy);\n\tnsvg__xformMultiply (grad->xform, t);\n}\n\nstatic void nsvg__scaleToViewbox(NSVGparser* p, const char* units)\n{\n\tNSVGshape* shape;\n\tNSVGpath* path;\n\tfloat tx, ty, sx, sy, us, bounds[4], t[6], avgs;\n\tint i;\n\tfloat* pt;\n\n\t/* Guess image size if not set completely. */\n\tnsvg__imageBounds(p, bounds);\n\n\tif (p->viewWidth == 0) {\n\t\tif (p->image->width > 0) {\n\t\t\tp->viewWidth = p->image->width;\n\t\t} else {\n\t\t\tp->viewMinx = bounds[0];\n\t\t\tp->viewWidth = bounds[2] - bounds[0];\n\t\t}\n\t}\n\tif (p->viewHeight == 0) {\n\t\tif (p->image->height > 0) {\n\t\t\tp->viewHeight = p->image->height;\n\t\t} else {\n\t\t\tp->viewMiny = bounds[1];\n\t\t\tp->viewHeight = bounds[3] - bounds[1];\n\t\t}\n\t}\n\tif (p->image->width == 0)\n\t\tp->image->width = p->viewWidth;\n\tif (p->image->height == 0)\n\t\tp->image->height = p->viewHeight;\n\n\ttx = -p->viewMinx;\n\tty = -p->viewMiny;\n\tsx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;\n\tsy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;\n\t/* Unit scaling */\n\tus = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);\n\n\t/* Fix aspect ratio */\n\tif (p->alignType == NSVG_ALIGN_MEET) {\n\t\t/* fit whole image into viewbox */\n\t\tsx = sy = nsvg__minf(sx, sy);\n\t\ttx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;\n\t\tty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;\n\t} else if (p->alignType == NSVG_ALIGN_SLICE) {\n\t\t/* fill whole viewbox with image */\n\t\tsx = sy = nsvg__maxf(sx, sy);\n\t\ttx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;\n\t\tty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;\n\t}\n\n\t/* Transform */\n\tsx *= us;\n\tsy *= us;\n\tavgs = (sx+sy) / 2.0f;\n\tfor (shape = p->image->shapes; shape != NULL; shape = shape->next) {\n\t\tshape->bounds[0] = (shape->bounds[0] + tx) * sx;\n\t\tshape->bounds[1] = (shape->bounds[1] + ty) * sy;\n\t\tshape->bounds[2] = (shape->bounds[2] + tx) * sx;\n\t\tshape->bounds[3] = (shape->bounds[3] + ty) * sy;\n\t\tfor (path = shape->paths; path != NULL; path = path->next) {\n\t\t\tpath->bounds[0] = (path->bounds[0] + tx) * sx;\n\t\t\tpath->bounds[1] = (path->bounds[1] + ty) * sy;\n\t\t\tpath->bounds[2] = (path->bounds[2] + tx) * sx;\n\t\t\tpath->bounds[3] = (path->bounds[3] + ty) * sy;\n\t\t\tfor (i =0; i < path->npts; i++) {\n\t\t\t\tpt = &path->pts[i*2];\n\t\t\t\tpt[0] = (pt[0] + tx) * sx;\n\t\t\t\tpt[1] = (pt[1] + ty) * sy;\n\t\t\t}\n\t\t}\n\n\t\tif (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {\n\t\t\tnsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);\n\t\t\tmemcpy(t, shape->fill.gradient->xform, sizeof(float)*6);\n\t\t\tnsvg__xformInverse(shape->fill.gradient->xform, t);\n\t\t}\n\t\tif (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {\n\t\t\tnsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);\n\t\t\tmemcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);\n\t\t\tnsvg__xformInverse(shape->stroke.gradient->xform, t);\n\t\t}\n\n\t\tshape->strokeWidth *= avgs;\n\t\tshape->strokeDashOffset *= avgs;\n\t\tfor (i = 0; i < shape->strokeDashCount; i++)\n\t\t\tshape->strokeDashArray[i] *= avgs;\n\t}\n}\n\nstatic void nsvg__createGradients(NSVGparser* p)\n{\n\tNSVGshape* shape;\n\n\tfor (shape = p->image->shapes; shape != NULL; shape = shape->next) {\n\t\tif (shape->fill.type == NSVG_PAINT_UNDEF) {\n\t\t\tif (shape->fillGradient[0] != '\\0') {\n\t\t\t\tfloat inv[6], localBounds[4];\n\t\t\t\tnsvg__xformInverse(inv, shape->xform);\n\t\t\t\tnsvg__getLocalBounds(localBounds, shape, inv);\n\t\t\t\tshape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type);\n\t\t\t}\n\t\t\tif (shape->fill.type == NSVG_PAINT_UNDEF) {\n\t\t\t\tshape->fill.type = NSVG_PAINT_NONE;\n\t\t\t}\n\t\t}\n\t\tif (shape->stroke.type == NSVG_PAINT_UNDEF) {\n\t\t\tif (shape->strokeGradient[0] != '\\0') {\n\t\t\t\tfloat inv[6], localBounds[4];\n\t\t\t\tnsvg__xformInverse(inv, shape->xform);\n\t\t\t\tnsvg__getLocalBounds(localBounds, shape, inv);\n\t\t\t\tshape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type);\n\t\t\t}\n\t\t\tif (shape->stroke.type == NSVG_PAINT_UNDEF) {\n\t\t\t\tshape->stroke.type = NSVG_PAINT_NONE;\n\t\t\t}\n\t\t}\n\t}\n}\n\nNANOSVG_SCOPE\nNSVGimage* nsvgParse(char* input, const char* units, float dpi)\n{\n\tNSVGparser* p;\n\tNSVGimage* ret = 0;\n\n\tp = nsvg__createParser();\n\tif (p == NULL) {\n\t\treturn NULL;\n\t}\n\tp->dpi = dpi;\n\n\tnsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);\n\n\t// Create gradients after all definitions have been parsed\n\tnsvg__createGradients(p);\n\n\t/* Scale to viewBox */\n\tnsvg__scaleToViewbox(p, units);\n\n\tret = p->image;\n\tp->image = NULL;\n\n\tnsvg__deleteParser(p);\n\n\treturn ret;\n}\n\nNANOSVG_SCOPE\nNSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)\n{\n\tFILE* fp = NULL;\n\tsize_t size;\n\tchar* data = NULL;\n\tNSVGimage* image = NULL;\n\n\tfp = fopen(filename, \"rb\");\n\tif (!fp) goto error;\n\tfseek(fp, 0, SEEK_END);\n\tsize = ftell(fp);\n\tfseek(fp, 0, SEEK_SET);\n\tdata = (char*)NANOSVG_malloc(size+1);\n\tif (data == NULL) goto error;\n\tif (fread(data, 1, size, fp) != size) goto error;\n\tdata[size] = '\\0';\t/* Must be null terminated. */\n\tfclose(fp);\n\timage = nsvgParse(data, units, dpi);\n\tNANOSVG_free(data);\n\n\treturn image;\n\nerror:\n\tif (fp) fclose(fp);\n\tif (data) NANOSVG_free(data);\n\tif (image) nsvgDelete(image);\n\treturn NULL;\n}\n\nNANOSVG_SCOPE\nvoid nsvgDelete(NSVGimage* image)\n{\n\tNSVGshape *snext, *shape;\n\tif (image == NULL) return;\n\tshape = image->shapes;\n\twhile (shape != NULL) {\n\t\tsnext = shape->next;\n\t\tnsvg__deletePaths(shape->paths);\n\t\tnsvg__deletePaint(&shape->fill);\n\t\tnsvg__deletePaint(&shape->stroke);\n\t\tNANOSVG_free(shape);\n\t\tshape = snext;\n\t}\n\tNANOSVG_free(image);\n}\n\n#endif\n\n#endif /* NANOSVG_H */\n"
  },
  {
    "path": "generic/nanosvgrast.h",
    "content": "/*\n * Copyright (c) 2013-14 Mikko Mononen memon@inside.org\n *\n * This software is provided 'as-is', without any express or implied\n * warranty.  In no event will the authors be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, subject to the following restrictions:\n *\n * 1. The origin of this software must not be misrepresented; you must not\n * claim that you wrote the original software. If you use this software\n * in a product, an acknowledgment in the product documentation would be\n * appreciated but is not required.\n * 2. Altered source versions must be plainly marked as such, and must not be\n * misrepresented as being the original software.\n * 3. This notice may not be removed or altered from any source distribution.\n *\n * The polygon rasterization is heavily based on stb_truetype rasterizer\n * by Sean Barrett - http://nothings.org/\n *\n */\n\n#ifndef NANOSVGRAST_H\n#define NANOSVGRAST_H\n\n#include \"nanosvg.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef NANOSVG_SCOPE\n#define NANOSVG_SCOPE\n#endif\n\n#ifndef NANOSVG_malloc\n#define NANOSVG_malloc malloc\n#endif\n\n#ifndef NANOSVG_realloc\n#define NANOSVG_realloc realloc\n#endif\n\n#ifndef NANOSVG_free\n#define NANOSVG_free free\n#endif\n\ntypedef struct NSVGrasterizer NSVGrasterizer;\n\n/* Example Usage:\n\t// Load SVG\n\tstruct SNVGImage* image = nsvgParseFromFile(\"test.svg.\");\n\n\t// Create rasterizer (can be used to render multiple images).\n\tstruct NSVGrasterizer* rast = nsvgCreateRasterizer();\n\t// Allocate memory for image\n\tunsigned char* img = malloc(w*h*4);\n\t// Rasterize\n\tnsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);\n*/\n\n/* Allocated rasterizer context. */\nNANOSVG_SCOPE NSVGrasterizer* nsvgCreateRasterizer(void);\n\n/* Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)\n *   r - pointer to rasterizer context\n *   image - pointer to image to rasterize\n *   tx,ty - image offset (applied after scaling)\n *   scale - image scale\n *   dst - pointer to destination image data, 4 bytes per pixel (RGBA)\n *   w - width of the image to render\n *   h - height of the image to render\n *   stride - number of bytes per scaleline in the destination buffer\n */\nNANOSVG_SCOPE void nsvgRasterize(NSVGrasterizer* r,\n\t\t\t\t   NSVGimage* image, float tx, float ty, float scale,\n\t\t\t\t   unsigned char* dst, int w, int h, int stride);\n\n/* Deletes rasterizer context. */\nNANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#ifdef NANOSVGRAST_IMPLEMENTATION\n\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define NSVG__SUBSAMPLES\t5\n#define NSVG__FIXSHIFT\t\t10\n#define NSVG__FIX\t\t\t(1 << NSVG__FIXSHIFT)\n#define NSVG__FIXMASK\t\t(NSVG__FIX-1)\n#define NSVG__MEMPAGE_SIZE\t1024\n\ntypedef struct NSVGedge {\n\tfloat x0,y0, x1,y1;\n\tint dir;\n\tstruct NSVGedge* next;\n} NSVGedge;\n\ntypedef struct NSVGpoint {\n\tfloat x, y;\n\tfloat dx, dy;\n\tfloat len;\n\tfloat dmx, dmy;\n\tunsigned char flags;\n} NSVGpoint;\n\ntypedef struct NSVGactiveEdge {\n\tint x,dx;\n\tfloat ey;\n\tint dir;\n\tstruct NSVGactiveEdge *next;\n} NSVGactiveEdge;\n\ntypedef struct NSVGmemPage {\n\tunsigned char mem[NSVG__MEMPAGE_SIZE];\n\tint size;\n\tstruct NSVGmemPage* next;\n} NSVGmemPage;\n\ntypedef struct NSVGcachedPaint {\n\tsigned char type;\n\tchar spread;\n\tfloat xform[6];\n\tunsigned int colors[256];\n} NSVGcachedPaint;\n\nstruct NSVGrasterizer\n{\n\tfloat px, py;\n\n\tfloat tessTol;\n\tfloat distTol;\n\n\tNSVGedge* edges;\n\tint nedges;\n\tint cedges;\n\n\tNSVGpoint* points;\n\tint npoints;\n\tint cpoints;\n\n\tNSVGpoint* points2;\n\tint npoints2;\n\tint cpoints2;\n\n\tNSVGactiveEdge* freelist;\n\tNSVGmemPage* pages;\n\tNSVGmemPage* curpage;\n\n\tunsigned char* scanline;\n\tint cscanline;\n\n\tunsigned char* bitmap;\n\tint width, height, stride;\n};\n\nNANOSVG_SCOPE\nNSVGrasterizer* nsvgCreateRasterizer(void)\n{\n\tNSVGrasterizer* r = (NSVGrasterizer*)NANOSVG_malloc(sizeof(NSVGrasterizer));\n\tif (r == NULL) goto error;\n\tmemset(r, 0, sizeof(NSVGrasterizer));\n\n\tr->tessTol = 0.25f;\n\tr->distTol = 0.01f;\n\n\treturn r;\n\nerror:\n\tnsvgDeleteRasterizer(r);\n\treturn NULL;\n}\n\nNANOSVG_SCOPE\nvoid nsvgDeleteRasterizer(NSVGrasterizer* r)\n{\n\tNSVGmemPage* p;\n\n\tif (r == NULL) return;\n\n\tp = r->pages;\n\twhile (p != NULL) {\n\t\tNSVGmemPage* next = p->next;\n\t\tNANOSVG_free(p);\n\t\tp = next;\n\t}\n\n\tif (r->edges) NANOSVG_free(r->edges);\n\tif (r->points) NANOSVG_free(r->points);\n\tif (r->points2) NANOSVG_free(r->points2);\n\tif (r->scanline) NANOSVG_free(r->scanline);\n\n\tNANOSVG_free(r);\n}\n\nstatic NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)\n{\n\tNSVGmemPage *newp;\n\n\t/* If using existing chain, return the next page in chain */\n\tif (cur != NULL && cur->next != NULL) {\n\t\treturn cur->next;\n\t}\n\n\t/* Alloc new page */\n\tnewp = (NSVGmemPage*)NANOSVG_malloc(sizeof(NSVGmemPage));\n\tif (newp == NULL) return NULL;\n\tmemset(newp, 0, sizeof(NSVGmemPage));\n\n\t/* Add to linked list */\n\tif (cur != NULL)\n\t\tcur->next = newp;\n\telse\n\t\tr->pages = newp;\n\n\treturn newp;\n}\n\nstatic void nsvg__resetPool(NSVGrasterizer* r)\n{\n\tNSVGmemPage* p = r->pages;\n\twhile (p != NULL) {\n\t\tp->size = 0;\n\t\tp = p->next;\n\t}\n\tr->curpage = r->pages;\n}\n\nstatic unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)\n{\n\tunsigned char* buf;\n\tif (size > NSVG__MEMPAGE_SIZE) return NULL;\n\tif (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {\n\t\tr->curpage = nsvg__nextPage(r, r->curpage);\n\t}\n\tbuf = &r->curpage->mem[r->curpage->size];\n\tr->curpage->size += size;\n\treturn buf;\n}\n\nstatic int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)\n{\n\tfloat dx = x2 - x1;\n\tfloat dy = y2 - y1;\n\treturn dx*dx + dy*dy < tol*tol;\n}\n\nstatic void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)\n{\n\tNSVGpoint* pt;\n\n\tif (r->npoints > 0) {\n\t\tpt = &r->points[r->npoints-1];\n\t\tif (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {\n\t\t\tpt->flags = (unsigned char)(pt->flags | flags);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (r->npoints+1 > r->cpoints) {\n\t\tr->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;\n\t\tr->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints);\n\t\tif (r->points == NULL) return;\n\t}\n\n\tpt = &r->points[r->npoints];\n\tpt->x = x;\n\tpt->y = y;\n\tpt->flags = (unsigned char)flags;\n\tr->npoints++;\n}\n\nstatic void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)\n{\n\tif (r->npoints+1 > r->cpoints) {\n\t\tr->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;\n\t\tr->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints);\n\t\tif (r->points == NULL) return;\n\t}\n\tr->points[r->npoints] = pt;\n\tr->npoints++;\n}\n\nstatic void nsvg__duplicatePoints(NSVGrasterizer* r)\n{\n\tif (r->npoints > r->cpoints2) {\n\t\tr->cpoints2 = r->npoints;\n\t\tr->points2 = (NSVGpoint*)NANOSVG_realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);\n\t\tif (r->points2 == NULL) return;\n\t}\n\n\tmemcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);\n\tr->npoints2 = r->npoints;\n}\n\nstatic void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)\n{\n\tNSVGedge* e;\n\n\t/* Skip horizontal edges */\n\tif (y0 == y1)\n\t\treturn;\n\n\tif (r->nedges+1 > r->cedges) {\n\t\tr->cedges = r->cedges > 0 ? r->cedges * 2 : 64;\n\t\tr->edges = (NSVGedge*)NANOSVG_realloc(r->edges, sizeof(NSVGedge) * r->cedges);\n\t\tif (r->edges == NULL) return;\n\t}\n\n\te = &r->edges[r->nedges];\n\tr->nedges++;\n\n\tif (y0 < y1) {\n\t\te->x0 = x0;\n\t\te->y0 = y0;\n\t\te->x1 = x1;\n\t\te->y1 = y1;\n\t\te->dir = 1;\n\t} else {\n\t\te->x0 = x1;\n\t\te->y0 = y1;\n\t\te->x1 = x0;\n\t\te->y1 = y0;\n\t\te->dir = -1;\n\t}\n}\n\nstatic float nsvg__normalize(float *x, float* y)\n{\n\tfloat d = sqrtf((*x)*(*x) + (*y)*(*y));\n\tif (d > 1e-6f) {\n\t\tfloat id = 1.0f / d;\n\t\t*x *= id;\n\t\t*y *= id;\n\t}\n\treturn d;\n}\n\nstatic float nsvg__absf(float x) { return x < 0 ? -x : x; }\nstatic float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); }\n\nstatic void nsvg__flattenCubicBez(NSVGrasterizer* r,\n\t\t\t\t\t\t\t\t  float x1, float y1, float x2, float y2,\n\t\t\t\t\t\t\t\t  float x3, float y3, float x4, float y4,\n\t\t\t\t\t\t\t\t  int level, int type)\n{\n\tfloat x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;\n\tfloat dx,dy,d2,d3;\n\n\tif (level > 10) return;\n\n\tx12 = (x1+x2)*0.5f;\n\ty12 = (y1+y2)*0.5f;\n\tx23 = (x2+x3)*0.5f;\n\ty23 = (y2+y3)*0.5f;\n\tx34 = (x3+x4)*0.5f;\n\ty34 = (y3+y4)*0.5f;\n\tx123 = (x12+x23)*0.5f;\n\ty123 = (y12+y23)*0.5f;\n\n\tdx = x4 - x1;\n\tdy = y4 - y1;\n\td2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx);\n\td3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx);\n\n\tif ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {\n\t\tnsvg__addPathPoint(r, x4, y4, type);\n\t\treturn;\n\t}\n\n\tx234 = (x23+x34)*0.5f;\n\ty234 = (y23+y34)*0.5f;\n\tx1234 = (x123+x234)*0.5f;\n\ty1234 = (y123+y234)*0.5f;\n\n\tnsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);\n\tnsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);\n}\n\nstatic void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale)\n{\n\tint i, j;\n\tNSVGpath* path;\n\n\tfor (path = shape->paths; path != NULL; path = path->next) {\n\t\tr->npoints = 0;\n\t\t/* Flatten path */\n\t\tnsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);\n\t\tfor (i = 0; i < path->npts-1; i += 3) {\n\t\t\tfloat* p = &path->pts[i*2];\n\t\t\tnsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0);\n\t\t}\n\t\t/* Close path */\n\t\tnsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);\n\t\t/* Build edges */\n\t\tfor (i = 0, j = r->npoints-1; i < r->npoints; j = i++)\n\t\t\tnsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);\n\t}\n}\n\nenum NSVGpointFlags\n{\n\tNSVG_PT_CORNER = 0x01,\n\tNSVG_PT_BEVEL = 0x02,\n\tNSVG_PT_LEFT = 0x04\n};\n\nstatic void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat dx = p1->x - p0->x;\n\tfloat dy = p1->y - p0->y;\n\tfloat len = nsvg__normalize(&dx, &dy);\n\tfloat px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;\n\tfloat dlx = dy, dly = -dx;\n\tfloat lx = px - dlx*w, ly = py - dly*w;\n\tfloat rx = px + dlx*w, ry = py + dly*w;\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\nstatic void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat px = p->x, py = p->y;\n\tfloat dlx = dy, dly = -dx;\n\tfloat lx = px - dlx*w, ly = py - dly*w;\n\tfloat rx = px + dlx*w, ry = py + dly*w;\n\n\tnsvg__addEdge(r, lx, ly, rx, ry);\n\n\tif (connect) {\n\t\tnsvg__addEdge(r, left->x, left->y, lx, ly);\n\t\tnsvg__addEdge(r, rx, ry, right->x, right->y);\n\t}\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\nstatic void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat px = p->x - dx*w, py = p->y - dy*w;\n\tfloat dlx = dy, dly = -dx;\n\tfloat lx = px - dlx*w, ly = py - dly*w;\n\tfloat rx = px + dlx*w, ry = py + dly*w;\n\n\tnsvg__addEdge(r, lx, ly, rx, ry);\n\n\tif (connect) {\n\t\tnsvg__addEdge(r, left->x, left->y, lx, ly);\n\t\tnsvg__addEdge(r, rx, ry, right->x, right->y);\n\t}\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\n#ifndef NSVG_PI\n#define NSVG_PI (3.14159265358979323846264338327f)\n#endif\n\nstatic void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)\n{\n\tint i;\n\tfloat w = lineWidth * 0.5f;\n\tfloat px = p->x, py = p->y;\n\tfloat dlx = dy, dly = -dx;\n\tfloat lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;\n\n\tfor (i = 0; i < ncap; i++) {\n\t\tfloat a = (float)i/(float)(ncap-1)*NSVG_PI;\n\t\tfloat ax = cosf(a) * w, ay = sinf(a) * w;\n\t\tfloat x = px - dlx*ax - dx*ay;\n\t\tfloat y = py - dly*ax - dy*ay;\n\n\t\tif (i > 0)\n\t\t\tnsvg__addEdge(r, prevx, prevy, x, y);\n\n\t\tprevx = x;\n\t\tprevy = y;\n\n\t\tif (i == 0) {\n\t\t\tlx = x; ly = y;\n\t\t} else if (i == ncap-1) {\n\t\t\trx = x; ry = y;\n\t\t}\n\t}\n\n\tif (connect) {\n\t\tnsvg__addEdge(r, left->x, left->y, lx, ly);\n\t\tnsvg__addEdge(r, rx, ry, right->x, right->y);\n\t}\n\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\nstatic void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat dlx0 = p0->dy, dly0 = -p0->dx;\n\tfloat dlx1 = p1->dy, dly1 = -p1->dx;\n\tfloat lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);\n\tfloat rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);\n\tfloat lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);\n\tfloat rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);\n\n\tnsvg__addEdge(r, lx0, ly0, left->x, left->y);\n\tnsvg__addEdge(r, lx1, ly1, lx0, ly0);\n\n\tnsvg__addEdge(r, right->x, right->y, rx0, ry0);\n\tnsvg__addEdge(r, rx0, ry0, rx1, ry1);\n\n\tleft->x = lx1; left->y = ly1;\n\tright->x = rx1; right->y = ry1;\n}\n\nstatic void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat dlx0 = p0->dy, dly0 = -p0->dx;\n\tfloat dlx1 = p1->dy, dly1 = -p1->dx;\n\tfloat lx0, rx0, lx1, rx1;\n\tfloat ly0, ry0, ly1, ry1;\n\n\tif (p1->flags & NSVG_PT_LEFT) {\n\t\tlx0 = lx1 = p1->x - p1->dmx * w;\n\t\tly0 = ly1 = p1->y - p1->dmy * w;\n\t\tnsvg__addEdge(r, lx1, ly1, left->x, left->y);\n\n\t\trx0 = p1->x + (dlx0 * w);\n\t\try0 = p1->y + (dly0 * w);\n\t\trx1 = p1->x + (dlx1 * w);\n\t\try1 = p1->y + (dly1 * w);\n\t\tnsvg__addEdge(r, right->x, right->y, rx0, ry0);\n\t\tnsvg__addEdge(r, rx0, ry0, rx1, ry1);\n\t} else {\n\t\tlx0 = p1->x - (dlx0 * w);\n\t\tly0 = p1->y - (dly0 * w);\n\t\tlx1 = p1->x - (dlx1 * w);\n\t\tly1 = p1->y - (dly1 * w);\n\t\tnsvg__addEdge(r, lx0, ly0, left->x, left->y);\n\t\tnsvg__addEdge(r, lx1, ly1, lx0, ly0);\n\n\t\trx0 = rx1 = p1->x + p1->dmx * w;\n\t\try0 = ry1 = p1->y + p1->dmy * w;\n\t\tnsvg__addEdge(r, right->x, right->y, rx1, ry1);\n\t}\n\n\tleft->x = lx1; left->y = ly1;\n\tright->x = rx1; right->y = ry1;\n}\n\nstatic void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)\n{\n\tint i, n;\n\tfloat w = lineWidth * 0.5f;\n\tfloat dlx0 = p0->dy, dly0 = -p0->dx;\n\tfloat dlx1 = p1->dy, dly1 = -p1->dx;\n\tfloat a0 = atan2f(dly0, dlx0);\n\tfloat a1 = atan2f(dly1, dlx1);\n\tfloat da = a1 - a0;\n\tfloat lx, ly, rx, ry;\n\n\tif (da < NSVG_PI) da += NSVG_PI*2;\n\tif (da > NSVG_PI) da -= NSVG_PI*2;\n\n\tn = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);\n\tif (n < 2) n = 2;\n\tif (n > ncap) n = ncap;\n\n\tlx = left->x;\n\tly = left->y;\n\trx = right->x;\n\try = right->y;\n\n\tfor (i = 0; i < n; i++) {\n\t\tfloat u = (float)i/(float)(n-1);\n\t\tfloat a = a0 + u*da;\n\t\tfloat ax = cosf(a) * w, ay = sinf(a) * w;\n\t\tfloat lx1 = p1->x - ax, ly1 = p1->y - ay;\n\t\tfloat rx1 = p1->x + ax, ry1 = p1->y + ay;\n\n\t\tnsvg__addEdge(r, lx1, ly1, lx, ly);\n\t\tnsvg__addEdge(r, rx, ry, rx1, ry1);\n\n\t\tlx = lx1; ly = ly1;\n\t\trx = rx1; ry = ry1;\n\t}\n\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\nstatic void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)\n{\n\tfloat w = lineWidth * 0.5f;\n\tfloat lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);\n\tfloat rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);\n\n\tnsvg__addEdge(r, lx, ly, left->x, left->y);\n\tnsvg__addEdge(r, right->x, right->y, rx, ry);\n\n\tleft->x = lx; left->y = ly;\n\tright->x = rx; right->y = ry;\n}\n\nstatic int nsvg__curveDivs(float r, float arc, float tol)\n{\n\tfloat da = acosf(r / (r + tol)) * 2.0f;\n\tint divs = (int)ceilf(arc / da);\n\tif (divs < 2) divs = 2;\n\treturn divs;\n}\n\nstatic void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth)\n{\n\tint ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol);\t/* Calculate divisions per half circle. */\n\tNSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0};\n\tNSVGpoint* p0, *p1;\n\tint j, s, e;\n\n\t/* Build stroke edges */\n\tif (closed) {\n\t\t/* Looping */\n\t\tp0 = &points[npoints-1];\n\t\tp1 = &points[0];\n\t\ts = 0;\n\t\te = npoints;\n\t} else {\n\t\t/* Add cap */\n\t\tp0 = &points[0];\n\t\tp1 = &points[1];\n\t\ts = 1;\n\t\te = npoints-1;\n\t}\n\n\tif (closed) {\n\t\tnsvg__initClosed(&left, &right, p0, p1, lineWidth);\n\t\tfirstLeft = left;\n\t\tfirstRight = right;\n\t} else {\n\t\t/* Add cap */\n\t\tfloat dx = p1->x - p0->x;\n\t\tfloat dy = p1->y - p0->y;\n\t\tnsvg__normalize(&dx, &dy);\n\t\tif (lineCap == NSVG_CAP_BUTT)\n\t\t\tnsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);\n\t\telse if (lineCap == NSVG_CAP_SQUARE)\n\t\t\tnsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);\n\t\telse if (lineCap == NSVG_CAP_ROUND)\n\t\t\tnsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);\n\t}\n\n\tfor (j = s; j < e; ++j) {\n\t\tif (p1->flags & NSVG_PT_CORNER) {\n\t\t\tif (lineJoin == NSVG_JOIN_ROUND)\n\t\t\t\tnsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);\n\t\t\telse if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))\n\t\t\t\tnsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);\n\t\t\telse\n\t\t\t\tnsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);\n\t\t} else {\n\t\t\tnsvg__straightJoin(r, &left, &right, p1, lineWidth);\n\t\t}\n\t\tp0 = p1++;\n\t}\n\n\tif (closed) {\n\t\t/* Loop it */\n\t\tnsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);\n\t\tnsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);\n\t} else {\n\t\t/* Add cap */\n\t\tfloat dx = p1->x - p0->x;\n\t\tfloat dy = p1->y - p0->y;\n\t\tnsvg__normalize(&dx, &dy);\n\t\tif (lineCap == NSVG_CAP_BUTT)\n\t\t\tnsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);\n\t\telse if (lineCap == NSVG_CAP_SQUARE)\n\t\t\tnsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);\n\t\telse if (lineCap == NSVG_CAP_ROUND)\n\t\t\tnsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);\n\t}\n}\n\nstatic void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)\n{\n\tint i, j;\n\tNSVGpoint* p0, *p1;\n\n\tp0 = &r->points[r->npoints-1];\n\tp1 = &r->points[0];\n\tfor (i = 0; i < r->npoints; i++) {\n\t\t/* Calculate segment direction and length */\n\t\tp0->dx = p1->x - p0->x;\n\t\tp0->dy = p1->y - p0->y;\n\t\tp0->len = nsvg__normalize(&p0->dx, &p0->dy);\n\t\t/* Advance */\n\t\tp0 = p1++;\n\t}\n\n\t/* calculate joins */\n\tp0 = &r->points[r->npoints-1];\n\tp1 = &r->points[0];\n\tfor (j = 0; j < r->npoints; j++) {\n\t\tfloat dlx0, dly0, dlx1, dly1, dmr2, cross;\n\t\tdlx0 = p0->dy;\n\t\tdly0 = -p0->dx;\n\t\tdlx1 = p1->dy;\n\t\tdly1 = -p1->dx;\n\t\t/* Calculate extrusions */\n\t\tp1->dmx = (dlx0 + dlx1) * 0.5f;\n\t\tp1->dmy = (dly0 + dly1) * 0.5f;\n\t\tdmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;\n\t\tif (dmr2 > 0.000001f) {\n\t\t\tfloat s2 = 1.0f / dmr2;\n\t\t\tif (s2 > 600.0f) {\n\t\t\t\ts2 = 600.0f;\n\t\t\t}\n\t\t\tp1->dmx *= s2;\n\t\t\tp1->dmy *= s2;\n\t\t}\n\n\t\t/* Clear flags, but keep the corner. */\n\t\tp1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;\n\n\t\t/* Keep track of left turns. */\n\t\tcross = p1->dx * p0->dy - p0->dx * p1->dy;\n\t\tif (cross > 0.0f)\n\t\t\tp1->flags |= NSVG_PT_LEFT;\n\n\t\t/* Check to see if the corner needs to be beveled. */\n\t\tif (p1->flags & NSVG_PT_CORNER) {\n\t\t\tif ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {\n\t\t\t\tp1->flags |= NSVG_PT_BEVEL;\n\t\t\t}\n\t\t}\n\n\t\tp0 = p1++;\n\t}\n}\n\nstatic void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale)\n{\n\tint i, j, closed;\n\tNSVGpath* path;\n\tNSVGpoint* p0, *p1;\n\tfloat miterLimit = shape->miterLimit;\n\tint lineJoin = shape->strokeLineJoin;\n\tint lineCap = shape->strokeLineCap;\n\tfloat lineWidth = shape->strokeWidth * scale;\n\n\tfor (path = shape->paths; path != NULL; path = path->next) {\n\t\t/* Flatten path */\n\t\tr->npoints = 0;\n\t\tnsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER);\n\t\tfor (i = 0; i < path->npts-1; i += 3) {\n\t\t\tfloat* p = &path->pts[i*2];\n\t\t\tnsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER);\n\t\t}\n\t\tif (r->npoints < 2)\n\t\t\tcontinue;\n\n\t\tclosed = path->closed;\n\n\t\t/* If the first and last points are the same, remove the last, mark as closed path. */\n\t\tp0 = &r->points[r->npoints-1];\n\t\tp1 = &r->points[0];\n\t\tif (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {\n\t\t\tr->npoints--;\n\t\t\tp0 = &r->points[r->npoints-1];\n\t\t\tclosed = 1;\n\t\t}\n\n\t\tif (shape->strokeDashCount > 0) {\n\t\t\tint idash = 0, dashState = 1;\n\t\t\tfloat totalDist = 0, dashLen, allDashLen, dashOffset;\n\t\t\tNSVGpoint cur;\n\n\t\t\tif (closed)\n\t\t\t\tnsvg__appendPathPoint(r, r->points[0]);\n\n\t\t\t/* Duplicate points -> points2. */\n\t\t\tnsvg__duplicatePoints(r);\n\n\t\t\tr->npoints = 0;\n \t\t\tcur = r->points2[0];\n\t\t\tnsvg__appendPathPoint(r, cur);\n\n\t\t\t/* Figure out dash offset. */\n\t\t\tallDashLen = 0;\n\t\t\tfor (j = 0; j < shape->strokeDashCount; j++)\n\t\t\t\tallDashLen += shape->strokeDashArray[j];\n\t\t\tif (shape->strokeDashCount & 1)\n\t\t\t\tallDashLen *= 2.0f;\n\t\t\t/* Find location inside pattern */\n\t\t\tdashOffset = fmodf(shape->strokeDashOffset, allDashLen);\n\t\t\tif (dashOffset < 0.0f)\n\t\t\t\tdashOffset += allDashLen;\n\n\t\t\twhile (dashOffset > shape->strokeDashArray[idash]) {\n\t\t\t\tdashOffset -= shape->strokeDashArray[idash];\n\t\t\t\tidash = (idash + 1) % shape->strokeDashCount;\n\t\t\t}\n\t\t\tdashLen = (shape->strokeDashArray[idash] - dashOffset) * scale;\n\n\t\t\tfor (j = 1; j < r->npoints2; ) {\n\t\t\t\tfloat dx = r->points2[j].x - cur.x;\n\t\t\t\tfloat dy = r->points2[j].y - cur.y;\n\t\t\t\tfloat dist = sqrtf(dx*dx + dy*dy);\n\n\t\t\t\tif ((totalDist + dist) > dashLen) {\n\t\t\t\t\t/* Calculate intermediate point */\n\t\t\t\t\tfloat d = (dashLen - totalDist) / dist;\n\t\t\t\t\tfloat x = cur.x + dx * d;\n\t\t\t\t\tfloat y = cur.y + dy * d;\n\t\t\t\t\tnsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);\n\n\t\t\t\t\t/* Stroke */\n\t\t\t\t\tif (r->npoints > 1 && dashState) {\n\t\t\t\t\t\tnsvg__prepareStroke(r, miterLimit, lineJoin);\n\t\t\t\t\t\tnsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);\n\t\t\t\t\t}\n\t\t\t\t\t/* Advance dash pattern */\n\t\t\t\t\tdashState = !dashState;\n\t\t\t\t\tidash = (idash+1) % shape->strokeDashCount;\n\t\t\t\t\tdashLen = shape->strokeDashArray[idash] * scale;\n\t\t\t\t\t/* Restart */\n\t\t\t\t\tcur.x = x;\n\t\t\t\t\tcur.y = y;\n\t\t\t\t\tcur.flags = NSVG_PT_CORNER;\n\t\t\t\t\ttotalDist = 0.0f;\n\t\t\t\t\tr->npoints = 0;\n\t\t\t\t\tnsvg__appendPathPoint(r, cur);\n\t\t\t\t} else {\n\t\t\t\t\ttotalDist += dist;\n\t\t\t\t\tcur = r->points2[j];\n\t\t\t\t\tnsvg__appendPathPoint(r, cur);\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* Stroke any leftover path */\n\t\t\tif (r->npoints > 1 && dashState) {\n\t\t\t\tnsvg__prepareStroke(r, miterLimit, lineJoin);\n\t\t\t\tnsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);\n\t\t\t}\n\t\t} else {\n\t\t\tnsvg__prepareStroke(r, miterLimit, lineJoin);\n\t\t\tnsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);\n\t\t}\n\t}\n}\n\nstatic int nsvg__cmpEdge(const void *p, const void *q)\n{\n\tconst NSVGedge* a = (const NSVGedge*)p;\n\tconst NSVGedge* b = (const NSVGedge*)q;\n\n\tif (a->y0 < b->y0) return -1;\n\tif (a->y0 > b->y0) return  1;\n\treturn 0;\n}\n\n\nstatic NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)\n{\n\t NSVGactiveEdge* z;\n\tfloat dxdy;\n\n\tif (r->freelist != NULL) {\n\t\t/* Restore from freelist. */\n\t\tz = r->freelist;\n\t\tr->freelist = z->next;\n\t} else {\n\t\t/* Alloc new edge. */\n\t\tz = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge));\n\t\tif (z == NULL) return NULL;\n\t}\n\n\tdxdy = (e->x1 - e->x0) / (e->y1 - e->y0);\n/*\tSTBTT_assert(e->y0 <= start_point); */\n\t/* round dx down to avoid going too far */\n\tif (dxdy < 0)\n\t\tz->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));\n\telse\n\t\tz->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);\n\tz->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));\n/*\tz->x -= off_x * FIX; */\n\tz->ey = e->y1;\n\tz->next = 0;\n\tz->dir = e->dir;\n\n\treturn z;\n}\n\nstatic void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)\n{\n\tz->next = r->freelist;\n\tr->freelist = z;\n}\n\nstatic void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)\n{\n\tint i = x0 >> NSVG__FIXSHIFT;\n\tint j = x1 >> NSVG__FIXSHIFT;\n\tif (i < *xmin) *xmin = i;\n\tif (j > *xmax) *xmax = j;\n\tif (i < len && j >= 0) {\n\t\tif (i == j) {\n\t\t\t/* x0,x1 are the same pixel, so compute combined coverage */\n\t\t\tscanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));\n\t\t} else {\n\t\t\tif (i >= 0) /* add antialiasing for x0 */\n\t\t\t\tscanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));\n\t\t\telse\n\t\t\t\ti = -1; /* clip */\n\n\t\t\tif (j < len) /* add antialiasing for x1 */\n\t\t\t\tscanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));\n\t\t\telse\n\t\t\t\tj = len; /* clip */\n\n\t\t\tfor (++i; i < j; ++i) /* fill pixels between x0 and x1 */\n\t\t\t\tscanline[i] = (unsigned char)(scanline[i] + maxWeight);\n\t\t}\n\t}\n}\n\n/* note: this routine clips fills that extend off the edges... ideally this\n * wouldn't happen, but it could happen if the truetype glyph bounding boxes\n * are wrong, or if the user supplies a too-small bitmap\n */\nstatic void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)\n{\n\t/* non-zero winding fill */\n\tint x0 = 0, w = 0;\n\n\tif (fillRule == NSVG_FILLRULE_NONZERO) {\n\t\t/* Non-zero */\n\t\twhile (e != NULL) {\n\t\t\tif (w == 0) {\n\t\t\t\t/* if we're currently at zero, we need to record the edge start point */\n\t\t\t\tx0 = e->x; w += e->dir;\n\t\t\t} else {\n\t\t\t\tint x1 = e->x; w += e->dir;\n\t\t\t\t/* if we went to zero, we need to draw */\n\t\t\t\tif (w == 0)\n\t\t\t\t\tnsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);\n\t\t\t}\n\t\t\te = e->next;\n\t\t}\n\t} else if (fillRule == NSVG_FILLRULE_EVENODD) {\n\t\t/* Even-odd */\n\t\twhile (e != NULL) {\n\t\t\tif (w == 0) {\n\t\t\t\t/* if we're currently at zero, we need to record the edge start point */\n\t\t\t\tx0 = e->x; w = 1;\n\t\t\t} else {\n\t\t\t\tint x1 = e->x; w = 0;\n\t\t\t\tnsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);\n\t\t\t}\n\t\t\te = e->next;\n\t\t}\n\t}\n}\n\nstatic float nsvg__clampf(float a, float mn, float mx) {\n\tif (isnan(a))\n\t\treturn mn;\n\treturn a < mn ? mn : (a > mx ? mx : a);\n}\n\nstatic unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n\treturn ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);\n}\n\nstatic unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)\n{\n\tint iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);\n\tint r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;\n\tint g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;\n\tint b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;\n\tint a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;\n\treturn nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);\n}\n\nstatic unsigned int nsvg__applyOpacity(unsigned int c, float u)\n{\n\tint iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);\n\tint r = (c) & 0xff;\n\tint g = (c>>8) & 0xff;\n\tint b = (c>>16) & 0xff;\n\tint a = (((c>>24) & 0xff)*iu) >> 8;\n\treturn nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);\n}\n\nstatic inline int nsvg__div255(int x)\n{\n    return ((x+1) * 257) >> 16;\n}\n\nstatic void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,\n\t\t\t\t\t\t\t\tfloat tx, float ty, float scale, NSVGcachedPaint* cache)\n{\n\n\tif (cache->type == NSVG_PAINT_COLOR) {\n\t\tint i, cr, cg, cb, ca;\n\t\tcr = cache->colors[0] & 0xff;\n\t\tcg = (cache->colors[0] >> 8) & 0xff;\n\t\tcb = (cache->colors[0] >> 16) & 0xff;\n\t\tca = (cache->colors[0] >> 24) & 0xff;\n\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tint r,g,b;\n\t\t\tint a = nsvg__div255((int)cover[0] * ca);\n\t\t\tint ia = 255 - a;\n\t\t\t/* Premultiply */\n\t\t\tr = nsvg__div255(cr * a);\n\t\t\tg = nsvg__div255(cg * a);\n\t\t\tb = nsvg__div255(cb * a);\n\n\t\t\t/* Blend over */\n\t\t\tr += nsvg__div255(ia * (int)dst[0]);\n\t\t\tg += nsvg__div255(ia * (int)dst[1]);\n\t\t\tb += nsvg__div255(ia * (int)dst[2]);\n\t\t\ta += nsvg__div255(ia * (int)dst[3]);\n\n\t\t\tdst[0] = (unsigned char)r;\n\t\t\tdst[1] = (unsigned char)g;\n\t\t\tdst[2] = (unsigned char)b;\n\t\t\tdst[3] = (unsigned char)a;\n\n\t\t\tcover++;\n\t\t\tdst += 4;\n\t\t}\n\t} else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {\n\t\t/* TODO: spread modes. */\n\t\t/* TODO: plenty of opportunities to optimize. */\n\t\tfloat fx, fy, dx, gy;\n\t\tfloat* t = cache->xform;\n\t\tint i, cr, cg, cb, ca;\n\t\tunsigned int c;\n\n\t\tfx = ((float)x - tx) / scale;\n\t\tfy = ((float)y - ty) / scale;\n\t\tdx = 1.0f / scale;\n\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tint r,g,b,a,ia;\n\t\t\tgy = fx*t[1] + fy*t[3] + t[5];\n\t\t\tc = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];\n\t\t\tcr = (c) & 0xff;\n\t\t\tcg = (c >> 8) & 0xff;\n\t\t\tcb = (c >> 16) & 0xff;\n\t\t\tca = (c >> 24) & 0xff;\n\n\t\t\ta = nsvg__div255((int)cover[0] * ca);\n\t\t\tia = 255 - a;\n\n\t\t\t/* Premultiply */\n\t\t\tr = nsvg__div255(cr * a);\n\t\t\tg = nsvg__div255(cg * a);\n\t\t\tb = nsvg__div255(cb * a);\n\n\t\t\t/* Blend over */\n\t\t\tr += nsvg__div255(ia * (int)dst[0]);\n\t\t\tg += nsvg__div255(ia * (int)dst[1]);\n\t\t\tb += nsvg__div255(ia * (int)dst[2]);\n\t\t\ta += nsvg__div255(ia * (int)dst[3]);\n\n\t\t\tdst[0] = (unsigned char)r;\n\t\t\tdst[1] = (unsigned char)g;\n\t\t\tdst[2] = (unsigned char)b;\n\t\t\tdst[3] = (unsigned char)a;\n\n\t\t\tcover++;\n\t\t\tdst += 4;\n\t\t\tfx += dx;\n\t\t}\n\t} else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {\n\t\t/* TODO: spread modes. */\n\t\t/* TODO: plenty of opportunities to optimize. */\n\t\t/* TODO: focus (fx,fy) */\n\t\tfloat fx, fy, dx, gx, gy, gd;\n\t\tfloat* t = cache->xform;\n\t\tint i, cr, cg, cb, ca;\n\t\tunsigned int c;\n\n\t\tfx = ((float)x - tx) / scale;\n\t\tfy = ((float)y - ty) / scale;\n\t\tdx = 1.0f / scale;\n\n\t\tfor (i = 0; i < count; i++) {\n\t\t\tint r,g,b,a,ia;\n\t\t\tgx = fx*t[0] + fy*t[2] + t[4];\n\t\t\tgy = fx*t[1] + fy*t[3] + t[5];\n\t\t\tgd = sqrtf(gx*gx + gy*gy);\n\t\t\tc = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];\n\t\t\tcr = (c) & 0xff;\n\t\t\tcg = (c >> 8) & 0xff;\n\t\t\tcb = (c >> 16) & 0xff;\n\t\t\tca = (c >> 24) & 0xff;\n\n\t\t\ta = nsvg__div255((int)cover[0] * ca);\n\t\t\tia = 255 - a;\n\n\t\t\t/* Premultiply */\n\t\t\tr = nsvg__div255(cr * a);\n\t\t\tg = nsvg__div255(cg * a);\n\t\t\tb = nsvg__div255(cb * a);\n\n\t\t\t/* Blend over */\n\t\t\tr += nsvg__div255(ia * (int)dst[0]);\n\t\t\tg += nsvg__div255(ia * (int)dst[1]);\n\t\t\tb += nsvg__div255(ia * (int)dst[2]);\n\t\t\ta += nsvg__div255(ia * (int)dst[3]);\n\n\t\t\tdst[0] = (unsigned char)r;\n\t\t\tdst[1] = (unsigned char)g;\n\t\t\tdst[2] = (unsigned char)b;\n\t\t\tdst[3] = (unsigned char)a;\n\n\t\t\tcover++;\n\t\t\tdst += 4;\n\t\t\tfx += dx;\n\t\t}\n\t}\n}\n\nstatic void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule)\n{\n\tNSVGactiveEdge *active = NULL;\n\tint y, s;\n\tint e = 0;\n\tint maxWeight = (255 / NSVG__SUBSAMPLES);  /* weight per vertical scanline */\n\tint xmin, xmax;\n\n\tfor (y = 0; y < r->height; y++) {\n\t\tmemset(r->scanline, 0, r->width);\n\t\txmin = r->width;\n\t\txmax = 0;\n\t\tfor (s = 0; s < NSVG__SUBSAMPLES; ++s) {\n\t\t\t/* find center of pixel for this scanline */\n\t\t\tfloat scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;\n\t\t\tNSVGactiveEdge **step = &active;\n\n\t\t\t/* update all active edges; */\n\t\t\t/* remove all active edges that terminate before the center of this scanline */\n\t\t\twhile (*step) {\n\t\t\t\tNSVGactiveEdge *z = *step;\n\t\t\t\tif (z->ey <= scany) {\n\t\t\t\t\t*step = z->next; /* delete from list */\n/*\t\t\t\t\tNSVG__assert(z->valid); */\n\t\t\t\t\tnsvg__freeActive(r, z);\n\t\t\t\t} else {\n\t\t\t\t\tz->x += z->dx; /* advance to position for current scanline */\n\t\t\t\t\tstep = &((*step)->next); /* advance through list */\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* resort the list if needed */\n\t\t\tfor (;;) {\n\t\t\t\tint changed = 0;\n\t\t\t\tstep = &active;\n\t\t\t\twhile (*step && (*step)->next) {\n\t\t\t\t\tif ((*step)->x > (*step)->next->x) {\n\t\t\t\t\t\tNSVGactiveEdge* t = *step;\n\t\t\t\t\t\tNSVGactiveEdge* q = t->next;\n\t\t\t\t\t\tt->next = q->next;\n\t\t\t\t\t\tq->next = t;\n\t\t\t\t\t\t*step = q;\n\t\t\t\t\t\tchanged = 1;\n\t\t\t\t\t}\n\t\t\t\t\tstep = &(*step)->next;\n\t\t\t\t}\n\t\t\t\tif (!changed) break;\n\t\t\t}\n\n\t\t\t/* insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */\n\t\t\twhile (e < r->nedges && r->edges[e].y0 <= scany) {\n\t\t\t\tif (r->edges[e].y1 > scany) {\n\t\t\t\t\tNSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);\n\t\t\t\t\tif (z == NULL) break;\n\t\t\t\t\t/* find insertion point */\n\t\t\t\t\tif (active == NULL) {\n\t\t\t\t\t\tactive = z;\n\t\t\t\t\t} else if (z->x < active->x) {\n\t\t\t\t\t\t/* insert at front */\n\t\t\t\t\t\tz->next = active;\n\t\t\t\t\t\tactive = z;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* find thing to insert AFTER */\n\t\t\t\t\t\tNSVGactiveEdge* p = active;\n\t\t\t\t\t\twhile (p->next && p->next->x < z->x)\n\t\t\t\t\t\t\tp = p->next;\n\t\t\t\t\t\t/* at this point, p->next->x is NOT < z->x */\n\t\t\t\t\t\tz->next = p->next;\n\t\t\t\t\t\tp->next = z;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\te++;\n\t\t\t}\n\n\t\t\t/* now process all active edges in non-zero fashion */\n\t\t\tif (active != NULL)\n\t\t\t\tnsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);\n\t\t}\n\t\t/* Blit */\n\t\tif (xmin < 0) xmin = 0;\n\t\tif (xmax > r->width-1) xmax = r->width-1;\n\t\tif (xmin <= xmax) {\n\t\t\tnsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);\n\t\t}\n\t}\n\n}\n\nstatic void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)\n{\n\tint x,y;\n\n\t/* Unpremultiply */\n\tfor (y = 0; y < h; y++) {\n\t\tunsigned char *row = &image[y*stride];\n\t\tfor (x = 0; x < w; x++) {\n\t\t\tint r = row[0], g = row[1], b = row[2], a = row[3];\n\t\t\tif (a != 0) {\n\t\t\t\trow[0] = (unsigned char)(r*255/a);\n\t\t\t\trow[1] = (unsigned char)(g*255/a);\n\t\t\t\trow[2] = (unsigned char)(b*255/a);\n\t\t\t}\n\t\t\trow += 4;\n\t\t}\n\t}\n\n\t/* Defringe */\n\tfor (y = 0; y < h; y++) {\n\t\tunsigned char *row = &image[y*stride];\n\t\tfor (x = 0; x < w; x++) {\n\t\t\tint r = 0, g = 0, b = 0, a = row[3], n = 0;\n\t\t\tif (a == 0) {\n\t\t\t\tif (x-1 > 0 && row[-1] != 0) {\n\t\t\t\t\tr += row[-4];\n\t\t\t\t\tg += row[-3];\n\t\t\t\t\tb += row[-2];\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t\tif (x+1 < w && row[7] != 0) {\n\t\t\t\t\tr += row[4];\n\t\t\t\t\tg += row[5];\n\t\t\t\t\tb += row[6];\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t\tif (y-1 > 0 && row[-stride+3] != 0) {\n\t\t\t\t\tr += row[-stride];\n\t\t\t\t\tg += row[-stride+1];\n\t\t\t\t\tb += row[-stride+2];\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t\tif (y+1 < h && row[stride+3] != 0) {\n\t\t\t\t\tr += row[stride];\n\t\t\t\t\tg += row[stride+1];\n\t\t\t\t\tb += row[stride+2];\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t\tif (n > 0) {\n\t\t\t\t\trow[0] = (unsigned char)(r/n);\n\t\t\t\t\trow[1] = (unsigned char)(g/n);\n\t\t\t\t\trow[2] = (unsigned char)(b/n);\n\t\t\t\t}\n\t\t\t}\n\t\t\trow += 4;\n\t\t}\n\t}\n}\n\n\nstatic void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)\n{\n\tint i, j;\n\tNSVGgradient* grad;\n\n\tcache->type = paint->type;\n\n\tif (paint->type == NSVG_PAINT_COLOR) {\n\t\tcache->colors[0] = nsvg__applyOpacity(paint->color, opacity);\n\t\treturn;\n\t}\n\n\tgrad = paint->gradient;\n\n\tcache->spread = grad->spread;\n\tmemcpy(cache->xform, grad->xform, sizeof(float)*6);\n\n\tif (grad->nstops == 0) {\n\t\tfor (i = 0; i < 256; i++)\n\t\t\tcache->colors[i] = 0;\n\t} else if (grad->nstops == 1) {\n\t\tunsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity);\n\t\tfor (i = 0; i < 256; i++)\n\t\t\tcache->colors[i] = color;\n\t} else {\n\t\tunsigned int ca, cb = 0;\n\t\tfloat ua, ub, du, u;\n\t\tint ia, ib, count;\n\n\t\tca = nsvg__applyOpacity(grad->stops[0].color, opacity);\n\t\tua = nsvg__clampf(grad->stops[0].offset, 0, 1);\n\t\tub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);\n\t\tia = (int)(ua * 255.0f);\n\t\tib = (int)(ub * 255.0f);\n\t\tfor (i = 0; i < ia; i++) {\n\t\t\tcache->colors[i] = ca;\n\t\t}\n\n\t\tfor (i = 0; i < grad->nstops-1; i++) {\n\t\t\tca = nsvg__applyOpacity(grad->stops[i].color, opacity);\n\t\t\tcb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);\n\t\t\tua = nsvg__clampf(grad->stops[i].offset, 0, 1);\n\t\t\tub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);\n\t\t\tia = (int)(ua * 255.0f);\n\t\t\tib = (int)(ub * 255.0f);\n\t\t\tcount = ib - ia;\n\t\t\tif (count <= 0) continue;\n\t\t\tu = 0;\n\t\t\tdu = 1.0f / (float)count;\n\t\t\tfor (j = 0; j < count; j++) {\n\t\t\t\tcache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);\n\t\t\t\tu += du;\n\t\t\t}\n\t\t}\n\n\t\tfor (i = ib; i < 256; i++)\n\t\t\tcache->colors[i] = cb;\n\t}\n\n}\n\n/*\nstatic void dumpEdges(NSVGrasterizer* r, const char* name)\n{\n\tfloat xmin = 0, xmax = 0, ymin = 0, ymax = 0;\n\tNSVGedge *e = NULL;\n\tint i;\n\tif (r->nedges == 0) return;\n\tFILE* fp = fopen(name, \"w\");\n\tif (fp == NULL) return;\n\n\txmin = xmax = r->edges[0].x0;\n\tymin = ymax = r->edges[0].y0;\n\tfor (i = 0; i < r->nedges; i++) {\n\t\te = &r->edges[i];\n\t\txmin = nsvg__minf(xmin, e->x0);\n\t\txmin = nsvg__minf(xmin, e->x1);\n\t\txmax = nsvg__maxf(xmax, e->x0);\n\t\txmax = nsvg__maxf(xmax, e->x1);\n\t\tymin = nsvg__minf(ymin, e->y0);\n\t\tymin = nsvg__minf(ymin, e->y1);\n\t\tymax = nsvg__maxf(ymax, e->y0);\n\t\tymax = nsvg__maxf(ymax, e->y1);\n\t}\n\n\tfprintf(fp, \"<svg viewBox=\\\"%f %f %f %f\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\", xmin, ymin, (xmax - xmin), (ymax - ymin));\n\n\tfor (i = 0; i < r->nedges; i++) {\n\t\te = &r->edges[i];\n\t\tfprintf(fp ,\"<line x1=\\\"%f\\\" y1=\\\"%f\\\" x2=\\\"%f\\\" y2=\\\"%f\\\" style=\\\"stroke:#000;\\\" />\", e->x0,e->y0, e->x1,e->y1);\n\t}\n\n\tfor (i = 0; i < r->npoints; i++) {\n\t\tif (i+1 < r->npoints)\n\t\t\tfprintf(fp ,\"<line x1=\\\"%f\\\" y1=\\\"%f\\\" x2=\\\"%f\\\" y2=\\\"%f\\\" style=\\\"stroke:#f00;\\\" />\", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);\n\t\tfprintf(fp ,\"<circle cx=\\\"%f\\\" cy=\\\"%f\\\" r=\\\"1\\\" style=\\\"fill:%s;\\\" />\", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? \"#f00\" : \"#0f0\");\n\t}\n\n\tfprintf(fp, \"</svg>\");\n\tfclose(fp);\n}\n*/\n\nNANOSVG_SCOPE\nvoid nsvgRasterize(NSVGrasterizer* r,\n\t\t\t\t   NSVGimage* image, float tx, float ty, float scale,\n\t\t\t\t   unsigned char* dst, int w, int h, int stride)\n{\n\tNSVGshape *shape = NULL;\n\tNSVGedge *e = NULL;\n\tNSVGcachedPaint cache;\n\tint i;\n\tint j;\n\tunsigned char paintOrder;\n\n\tr->bitmap = dst;\n\tr->width = w;\n\tr->height = h;\n\tr->stride = stride;\n\n\tif (w > r->cscanline) {\n\t\tr->cscanline = w;\n\t\tr->scanline = (unsigned char*)NANOSVG_realloc(r->scanline, w);\n\t\tif (r->scanline == NULL) return;\n\t}\n\n\tfor (i = 0; i < h; i++)\n\t\tmemset(&dst[i*stride], 0, w*4);\n\n\tfor (shape = image->shapes; shape != NULL; shape = shape->next) {\n\t\tif (!(shape->flags & NSVG_FLAGS_VISIBLE))\n\t\t\tcontinue;\n\t\tfor (j = 0; j < 3; j++) {\n\t\t\tpaintOrder = (shape->paintOrder >> (2 * j)) & 0x03;\n\n\t\t\tif (paintOrder == NSVG_PAINT_FILL && shape->fill.type != NSVG_PAINT_NONE) {\n\t\t\t\tnsvg__resetPool(r);\n\t\t\t\tr->freelist = NULL;\n\t\t\t\tr->nedges = 0;\n\n\t\t\t\tnsvg__flattenShape(r, shape, scale);\n\n\t\t\t\t/* Scale and translate edges */\n\t\t\t\tfor (i = 0; i < r->nedges; i++) {\n\t\t\t\t\te = &r->edges[i];\n\t\t\t\t\te->x0 = tx + e->x0;\n\t\t\t\t\te->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;\n\t\t\t\t\te->x1 = tx + e->x1;\n\t\t\t\t\te->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;\n\t\t\t\t}\n\n\t\t\t\t/* Rasterize edges */\n\t\t\t\tif (r->nedges != 0)\n\t\t\t\t\tqsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);\n\n\t\t\t\t/* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */\n\t\t\t\tnsvg__initPaint(&cache, &shape->fill, shape->opacity);\n\n\t\t\t\tnsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule);\n\t\t\t}\n\t\t\tif (paintOrder == NSVG_PAINT_STROKE && shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) {\n\t\t\t\tnsvg__resetPool(r);\n\t\t\t\tr->freelist = NULL;\n\t\t\t\tr->nedges = 0;\n\n\t\t\t\tnsvg__flattenShapeStroke(r, shape, scale);\n\n/*\t\t\t\tdumpEdges(r, \"edge.svg\"); */\n\n\t\t\t\t/* Scale and translate edges */\n\t\t\t\tfor (i = 0; i < r->nedges; i++) {\n\t\t\t\t\te = &r->edges[i];\n\t\t\t\t\te->x0 = tx + e->x0;\n\t\t\t\t\te->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;\n\t\t\t\t\te->x1 = tx + e->x1;\n\t\t\t\t\te->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;\n\t\t\t\t}\n\n\t\t\t\t/* Rasterize edges */\n\t\t\t\tif (r->nedges != 0)\n\t\t\t\t\tqsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);\n\n\t\t\t\t/* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */\n\t\t\t\tnsvg__initPaint(&cache, &shape->stroke, shape->opacity);\n\n\t\t\t\tnsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO);\n\t\t\t}\n\t\t}\n\t}\n\n\tnsvg__unpremultiplyAlpha(dst, w, h, stride);\n\n\tr->bitmap = NULL;\n\tr->width = 0;\n\tr->height = 0;\n\tr->stride = 0;\n}\n\n#endif\n\n#endif /* NANOSVGRAST_H */\n"
  },
  {
    "path": "generic/tk.decls",
    "content": "# tk.decls --\n#\n#\tThis file contains the declarations for all supported public\n#\tfunctions that are exported by the Tk library via the stubs table.\n#\tThis file is used to generate the tkDecls.h, tkPlatDecls.h,\n#\ttkStub.c, and tkPlatStub.c files.\n#\n# Copyright © 1998-2000 Ajuba Solutions.\n# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nlibrary tk\n\n# Define the tk interface with 3 sub interfaces:\n#     tkPlat\t - platform specific public\n#     tkInt\t - generic private\n#     tkPlatInt - platform specific private\n\ninterface tk\nhooks {tkPlat tkInt tkIntPlat tkIntXlib}\nscspec EXTERN\n\n# Declare each of the functions in the public Tk interface.  Note that\n# the an index should never be reused for a different function in order\n# to preserve backwards compatibility.\n\ndeclare 0 {\n    void Tk_MainLoop(void)\n}\ndeclare 1 {\n    XColor *Tk_3DBorderColor(Tk_3DBorder border)\n}\ndeclare 2 {\n    GC Tk_3DBorderGC(Tk_Window tkwin, Tk_3DBorder border,\n\t    int which)\n}\ndeclare 3 {\n    void Tk_3DHorizontalBevel(Tk_Window tkwin,\n\t    Drawable drawable, Tk_3DBorder border, int x,\n\t    int y, int width, int height, int leftIn,\n\t    int rightIn, int topBevel, int relief)\n}\ndeclare 4 {\n    void Tk_3DVerticalBevel(Tk_Window tkwin,\n\t    Drawable drawable, Tk_3DBorder border, int x,\n\t    int y, int width, int height, int leftBevel,\n\t    int relief)\n}\ndeclare 5 {\n    void Tk_AddOption(Tk_Window tkwin, const char *name,\n\t    const char *value, int priority)\n}\ndeclare 6 {\n    void Tk_BindEvent(Tk_BindingTable bindingTable,\n\t    XEvent *eventPtr, Tk_Window tkwin, Tcl_Size numObjects,\n\t    void **objectPtr)\n}\ndeclare 7 {\n    void Tk_CanvasDrawableCoords(Tk_Canvas canvas,\n\t    double x, double y, short *drawableXPtr,\n\t    short *drawableYPtr)\n}\ndeclare 8 {\n    void Tk_CanvasEventuallyRedraw(Tk_Canvas canvas, int x1, int y1,\n\t    int x2, int y2)\n}\ndeclare 9 {\n    int Tk_CanvasGetCoord(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, const char *str, double *doublePtr)\n}\ndeclare 10 {\n    Tk_CanvasTextInfo *Tk_CanvasGetTextInfo(Tk_Canvas canvas)\n}\ndeclare 11 {\n    int Tk_CanvasPsBitmap(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, Pixmap bitmap, int x, int y,\n\t    int width, int height)\n}\ndeclare 12 {\n    int Tk_CanvasPsColor(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, XColor *colorPtr)\n}\ndeclare 13 {\n    int Tk_CanvasPsFont(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, Tk_Font font)\n}\ndeclare 14 {\n    void Tk_CanvasPsPath(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, double *coordPtr, Tcl_Size numPoints)\n}\ndeclare 15 {\n    int Tk_CanvasPsStipple(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, Pixmap bitmap)\n}\ndeclare 16 {\n    double Tk_CanvasPsY(Tk_Canvas canvas, double y)\n}\ndeclare 17 {\n    void Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc)\n}\ndeclare 18 {\n    int Tk_CanvasTagsParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 19 {\n    const char *Tk_CanvasTagsPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 20 {\n    Tk_Window\tTk_CanvasTkwin(Tk_Canvas canvas)\n}\ndeclare 21 {\n    void Tk_CanvasWindowCoords(Tk_Canvas canvas, double x, double y,\n\t    short *screenXPtr, short *screenYPtr)\n}\ndeclare 22 {\n    void Tk_ChangeWindowAttributes(Tk_Window tkwin, unsigned long valueMask,\n\t    XSetWindowAttributes *attsPtr)\n}\ndeclare 23 {\n    int Tk_CharBbox(Tk_TextLayout layout, Tcl_Size index, int *xPtr,\n\t    int *yPtr, int *widthPtr, int *heightPtr)\n}\ndeclare 24 {\n    void Tk_ClearSelection(Tk_Window tkwin, Atom selection)\n}\ndeclare 25 {\n    int Tk_ClipboardAppend(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Atom target, Atom format, const char *buffer)\n}\ndeclare 26 {\n    int Tk_ClipboardClear(Tcl_Interp *interp, Tk_Window tkwin)\n}\ndeclare 27 {\n    int Tk_ConfigureInfo(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const Tk_ConfigSpec *specs,\n\t    void *widgRec, const char *argvName, int flags)\n}\ndeclare 28 {\n    int Tk_ConfigureValue(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const Tk_ConfigSpec *specs,\n\t    void *widgRec, const char *argvName, int flags)\n}\ndeclare 29 {\n    int Tk_ConfigureWidget(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const Tk_ConfigSpec *specs,\n\t    Tcl_Size objc, Tcl_Obj *const *objv, void *widgRec,\n\t    int flags)\n}\ndeclare 30 {\n    void Tk_ConfigureWindow(Tk_Window tkwin,\n\t    unsigned int valueMask, XWindowChanges *valuePtr)\n}\ndeclare 31 {\n    Tk_TextLayout Tk_ComputeTextLayout(Tk_Font font,\n\t    const char *str, Tcl_Size numChars, int wrapLength,\n\t    Tk_Justify justify, int flags, int *widthPtr,\n\t    int *heightPtr)\n}\ndeclare 32 {\n    Tk_Window Tk_CoordsToWindow(int rootX, int rootY, Tk_Window tkwin)\n}\ndeclare 33 {\n    unsigned long Tk_CreateBinding(Tcl_Interp *interp,\n\t    Tk_BindingTable bindingTable, void *object,\n\t    const char *eventStr, const char *script, int append)\n}\ndeclare 34 {\n    Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp)\n}\ndeclare 35 {\n    Tk_ErrorHandler Tk_CreateErrorHandler(Display *display,\n\t    int errNum, int request, int minorCode,\n\t    Tk_ErrorProc *errorProc, void *clientData)\n}\ndeclare 36 {\n    void Tk_CreateEventHandler(Tk_Window token,\n\t    unsigned long mask, Tk_EventProc *proc,\n\t    void *clientData)\n}\ndeclare 37 {\n    void Tk_CreateGenericHandler(Tk_GenericProc *proc, void *clientData)\n}\ndeclare 38 {\n    void Tk_CreateImageType(const Tk_ImageType *typePtr)\n}\ndeclare 39 {\n    void Tk_CreateItemType(Tk_ItemType *typePtr)\n}\ndeclare 40 {\n    void Tk_CreatePhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)\n}\ndeclare 41 {\n    void Tk_CreateSelHandler(Tk_Window tkwin,\n\t    Atom selection, Atom target,\n\t    Tk_SelectionProc *proc, void *clientData,\n\t    Atom format)\n}\ndeclare 42 {\n    Tk_Window Tk_CreateWindow(Tcl_Interp *interp,\n\t    Tk_Window parent, const char *name, const char *screenName)\n}\ndeclare 43 {\n    Tk_Window Tk_CreateWindowFromPath(Tcl_Interp *interp, Tk_Window tkwin,\n\t    const char *pathName, const char *screenName)\n}\ndeclare 44 {\n    int Tk_DefineBitmap(Tcl_Interp *interp, const char *name,\n\t    const void *source, int width, int height)\n}\ndeclare 45 {\n    void Tk_DefineCursor(Tk_Window window, Tk_Cursor cursor)\n}\ndeclare 46 {\n    void Tk_DeleteAllBindings(Tk_BindingTable bindingTable, void *object)\n}\ndeclare 47 {\n    int Tk_DeleteBinding(Tcl_Interp *interp,\n\t    Tk_BindingTable bindingTable, void *object,\n\t    const char *eventStr)\n}\ndeclare 48 {\n    void Tk_DeleteBindingTable(Tk_BindingTable bindingTable)\n}\ndeclare 49 {\n    void Tk_DeleteErrorHandler(Tk_ErrorHandler handler)\n}\ndeclare 50 {\n    void Tk_DeleteEventHandler(Tk_Window token,\n\t    unsigned long mask, Tk_EventProc *proc,\n\t    void *clientData)\n}\ndeclare 51 {\n    void Tk_DeleteGenericHandler(Tk_GenericProc *proc, void *clientData)\n}\ndeclare 52 {\n    void Tk_DeleteImage(Tcl_Interp *interp, const char *name)\n}\ndeclare 53 {\n    void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, Atom target)\n}\ndeclare 54 {\n    void Tk_DestroyWindow(Tk_Window tkwin)\n}\ndeclare 55 {\n    const char *Tk_DisplayName(Tk_Window tkwin)\n}\ndeclare 56 {\n    int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, int y)\n}\ndeclare 57 {\n    void Tk_Draw3DPolygon(Tk_Window tkwin,\n\t    Drawable drawable, Tk_3DBorder border,\n\t    XPoint *pointPtr, Tcl_Size numPoints, int borderWidth,\n\t    int leftRelief)\n}\ndeclare 58 {\n    void Tk_Draw3DRectangle(Tk_Window tkwin, Drawable drawable,\n\t    Tk_3DBorder border, int x, int y, int width, int height,\n\t    int borderWidth, int relief)\n}\ndeclare 59 {\n    void Tk_DrawChars(Display *display, Drawable drawable, GC gc,\n\t    Tk_Font tkfont, const char *source, Tcl_Size numBytes, int x, int y)\n}\ndeclare 60 {\n    void Tk_DrawFocusHighlight(Tk_Window tkwin, GC gc, int width,\n\t    Drawable drawable)\n}\ndeclare 61 {\n    void Tk_DrawTextLayout(Display *display,\n\t    Drawable drawable, GC gc, Tk_TextLayout layout,\n\t    int x, int y, Tcl_Size firstChar, Tcl_Size lastChar)\n}\ndeclare 62 {\n    void Tk_Fill3DPolygon(Tk_Window tkwin,\n\t    Drawable drawable, Tk_3DBorder border,\n\t    XPoint *pointPtr, Tcl_Size numPoints, int borderWidth,\n\t    int leftRelief)\n}\ndeclare 63 {\n    void Tk_Fill3DRectangle(Tk_Window tkwin,\n\t    Drawable drawable, Tk_3DBorder border, int x,\n\t    int y, int width, int height, int borderWidth,\n\t    int relief)\n}\ndeclare 64 {\n    Tk_PhotoHandle Tk_FindPhoto(Tcl_Interp *interp, const char *imageName)\n}\ndeclare 65 {\n    Font Tk_FontId(Tk_Font font)\n}\ndeclare 66 {\n    void Tk_Free3DBorder(Tk_3DBorder border)\n}\ndeclare 67 {\n    void Tk_FreeBitmap(Display *display, Pixmap bitmap)\n}\ndeclare 68 {\n    void Tk_FreeColor(XColor *colorPtr)\n}\ndeclare 69 {\n    void Tk_FreeColormap(Display *display, Colormap colormap)\n}\ndeclare 70 {\n    void Tk_FreeCursor(Display *display, Tk_Cursor cursor)\n}\ndeclare 71 {\n    void Tk_FreeFont(Tk_Font f)\n}\ndeclare 72 {\n    void Tk_FreeGC(Display *display, GC gc)\n}\ndeclare 73 {\n    void Tk_FreeImage(Tk_Image image)\n}\ndeclare 74 {\n    void Tk_FreeOptions(const Tk_ConfigSpec *specs,\n\t    void *widgRec, Display *display, int needFlags)\n}\ndeclare 75 {\n    void Tk_FreePixmap(Display *display, Pixmap pixmap)\n}\ndeclare 76 {\n    void Tk_FreeTextLayout(Tk_TextLayout textLayout)\n}\ndeclare 78 {\n    GC Tk_GCForColor(XColor *colorPtr, Drawable drawable)\n}\ndeclare 79 {\n    void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth,  int reqHeight)\n}\ndeclare 80 {\n    Tk_3DBorder\tTk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin,\n\t    const char *colorName)\n}\ndeclare 81 {\n    void Tk_GetAllBindings(Tcl_Interp *interp,\n\t    Tk_BindingTable bindingTable, void *object)\n}\ndeclare 82 {\n    int Tk_GetAnchor(Tcl_Interp *interp,\n\t    const char *str, Tk_Anchor *anchorPtr)\n}\ndeclare 83 {\n    const char *Tk_GetAtomName(Tk_Window tkwin, Atom atom)\n}\ndeclare 84 {\n    const char *Tk_GetBinding(Tcl_Interp *interp,\n\t    Tk_BindingTable bindingTable, void *object,\n\t    const char *eventStr)\n}\ndeclare 85 {\n    Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, const char *str)\n}\ndeclare 86 {\n    Pixmap Tk_GetBitmapFromData(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const void *source, int width, int height)\n}\ndeclare 87 {\n    int Tk_GetCapStyle(Tcl_Interp *interp, const char *str, int *capPtr)\n}\ndeclare 88 {\n    XColor *Tk_GetColor(Tcl_Interp *interp, Tk_Window tkwin, const char *name)\n}\ndeclare 89 {\n    XColor *Tk_GetColorByValue(Tk_Window tkwin, XColor *colorPtr)\n}\ndeclare 90 {\n    Colormap Tk_GetColormap(Tcl_Interp *interp, Tk_Window tkwin,\n\t    const char *str)\n}\ndeclare 91 {\n    Tk_Cursor Tk_GetCursor(Tcl_Interp *interp, Tk_Window tkwin,\n\t    const char *str)\n}\ndeclare 92 {\n    Tk_Cursor Tk_GetCursorFromData(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *source, const char *mask,\n\t    int width, int height, int xHot, int yHot,\n\t    const char *fg, const char *bg)\n}\ndeclare 93 {\n    Tk_Font Tk_GetFont(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *str)\n}\ndeclare 94 {\n    Tk_Font Tk_GetFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 95 {\n    void Tk_GetFontMetrics(Tk_Font font, Tk_FontMetrics *fmPtr)\n}\ndeclare 96 {\n    GC Tk_GetGC(Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr)\n}\ndeclare 97 {\n    Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, const char *name,\n\t    Tk_ImageChangedProc *changeProc, void *clientData)\n}\ndeclare 98 {\n    void *Tk_GetImageModelData(Tcl_Interp *interp,\n\t    const char *name, const Tk_ImageType **typePtrPtr)\n}\ndeclare 99 {\n    Tk_ItemType *Tk_GetItemTypes(void)\n}\ndeclare 100 {\n    int Tk_GetJoinStyle(Tcl_Interp *interp, const char *str, int *joinPtr)\n}\ndeclare 101 {\n    int Tk_GetJustify(Tcl_Interp *interp,\n\t    const char *str, Tk_Justify *justifyPtr)\n}\ndeclare 102 {\n    int Tk_GetNumMainWindows(void)\n}\ndeclare 103 {\n    Tk_Uid Tk_GetOption(Tk_Window tkwin, const char *name,\n\t    const char *className)\n}\ndeclare 104 {\n    int Tk_GetPixels(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *str, int *intPtr)\n}\ndeclare 105 {\n    Pixmap Tk_GetPixmap(Display *display, Drawable d,\n\t    int width, int height, int depth)\n}\ndeclare 106 {\n    int Tk_GetRelief(Tcl_Interp *interp, const char *name, int *reliefPtr)\n}\ndeclare 107 {\n    void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, int *yPtr)\n}\ndeclare 108 {\n    int Tk_GetScrollInfo(Tcl_Interp *interp,\n\t    Tcl_Size argc, const char **argv, double *dblPtr, int *intPtr)\n}\ndeclare 109 {\n    int Tk_GetScreenMM(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *str, double *doublePtr)\n}\ndeclare 110 {\n    int Tk_GetSelection(Tcl_Interp *interp,\n\t    Tk_Window tkwin, Atom selection, Atom target,\n\t    Tk_GetSelProc *proc, void *clientData)\n}\ndeclare 111 {\n    Tk_Uid Tk_GetUid(const char *str)\n}\ndeclare 112 {\n    Visual *Tk_GetVisual(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *str, int *depthPtr,\n\t    Colormap *colormapPtr)\n}\ndeclare 113 {\n    void Tk_GetVRootGeometry(Tk_Window tkwin,\n\t    int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)\n}\ndeclare 114 {\n    int Tk_Grab(Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal)\n}\ndeclare 115 {\n    void Tk_HandleEvent(XEvent *eventPtr)\n}\ndeclare 116 {\n    Tk_Window Tk_IdToWindow(Display *display, Window window)\n}\ndeclare 117 {\n    void Tk_ImageChanged(Tk_ImageModel model, int x, int y,\n\t    int width, int height, int imageWidth, int imageHeight)\n}\ndeclare 119 {\n    Atom Tk_InternAtom(Tk_Window tkwin, const char *name)\n}\ndeclare 120 {\n    int Tk_IntersectTextLayout(Tk_TextLayout layout, int x, int y,\n\t    int width, int height)\n}\ndeclare 121 {\n    void Tk_MaintainGeometry(Tk_Window window,\n\t    Tk_Window container, int x, int y, int width, int height)\n}\ndeclare 122 {\n    Tk_Window Tk_MainWindow(Tcl_Interp *interp)\n}\ndeclare 123 {\n    void Tk_MakeWindowExist(Tk_Window tkwin)\n}\ndeclare 124 {\n    void Tk_ManageGeometry(Tk_Window tkwin,\n\t    const Tk_GeomMgr *mgrPtr, void *clientData)\n}\ndeclare 125 {\n    void Tk_MapWindow(Tk_Window tkwin)\n}\ndeclare 126 {\n    int Tk_MeasureChars(Tk_Font tkfont,\n\t    const char *source, Tcl_Size numBytes, int maxPixels,\n\t    int flags, int *lengthPtr)\n}\ndeclare 127 {\n    void Tk_MoveResizeWindow(Tk_Window tkwin,\n\t    int x, int y, int width, int height)\n}\ndeclare 128 {\n    void Tk_MoveWindow(Tk_Window tkwin, int x, int y)\n}\ndeclare 129 {\n    void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y)\n}\ndeclare 130 {\n    const char *Tk_NameOf3DBorder(Tk_3DBorder border)\n}\ndeclare 131 {\n    const char *Tk_NameOfAnchor(Tk_Anchor anchor)\n}\ndeclare 132 {\n    const char *Tk_NameOfBitmap(Display *display, Pixmap bitmap)\n}\ndeclare 133 {\n    const char *Tk_NameOfCapStyle(int cap)\n}\ndeclare 134 {\n    const char *Tk_NameOfColor(XColor *colorPtr)\n}\ndeclare 135 {\n    const char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor)\n}\ndeclare 136 {\n    const char *Tk_NameOfFont(Tk_Font font)\n}\ndeclare 137 {\n    const char *Tk_NameOfImage(Tk_ImageModel model)\n}\ndeclare 138 {\n    const char *Tk_NameOfJoinStyle(int join)\n}\ndeclare 139 {\n    const char *Tk_NameOfJustify(Tk_Justify justify)\n}\ndeclare 140 {\n    const char *Tk_NameOfRelief(int relief)\n}\ndeclare 141 {\n    Tk_Window Tk_NameToWindow(Tcl_Interp *interp,\n\t    const char *pathName, Tk_Window tkwin)\n}\ndeclare 142 {\n    void Tk_OwnSelection(Tk_Window tkwin,\n\t    Atom selection, Tk_LostSelProc *proc,\n\t    void *clientData)\n}\ndeclare 143 {\n    int Tk_ParseArgv(Tcl_Interp *interp,\n\t    Tk_Window tkwin, int *argcPtr, const char **argv,\n\t    const Tk_ArgvInfo *argTable, int flags)\n}\ndeclare 146 {\n    int Tk_PhotoGetImage(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr)\n}\ndeclare 147 {\n    void Tk_PhotoBlank(Tk_PhotoHandle handle)\n}\ndeclare 149 {\n    void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, int *heightPtr)\n}\ndeclare 150 {\n    Tcl_Size Tk_PointToChar(Tk_TextLayout layout, int x, int y)\n}\n# Just a stub entry, for binary compatibility with Tk 9.0.\ndeclare 151 {\n    int TkPointToChar_(Tk_TextLayout layout, int x, int y)\n}\ndeclare 152 {\n    int Tk_PostscriptFontName(Tk_Font tkfont, Tcl_DString *dsPtr)\n}\ndeclare 153 {\n    void Tk_PreserveColormap(Display *display, Colormap colormap)\n}\ndeclare 154 {\n    void Tk_QueueWindowEvent(XEvent *eventPtr, Tcl_QueuePosition position)\n}\ndeclare 155 {\n    void Tk_RedrawImage(Tk_Image image, int imageX,\n\t    int imageY, int width, int height,\n\t    Drawable drawable, int drawableX, int drawableY)\n}\ndeclare 156 {\n    void Tk_ResizeWindow(Tk_Window tkwin, int width, int height)\n}\ndeclare 157 {\n    int Tk_RestackWindow(Tk_Window tkwin, int aboveBelow, Tk_Window other)\n}\ndeclare 158 {\n    Tk_RestrictProc *Tk_RestrictEvents(Tk_RestrictProc *proc,\n\t    void *arg, void **prevArgPtr)\n}\ndeclare 160 {\n    const char *Tk_SetAppName(Tk_Window tkwin, const char *name)\n}\ndeclare 161 {\n    void Tk_SetBackgroundFromBorder(Tk_Window tkwin, Tk_3DBorder border)\n}\ndeclare 162 {\n    void Tk_SetClass(Tk_Window tkwin, const char *className)\n}\ndeclare 163 {\n    void Tk_SetGrid(Tk_Window tkwin, int reqWidth, int reqHeight,\n\t    int gridWidth, int gridHeight)\n}\ndeclare 164 {\n    void Tk_SetInternalBorder(Tk_Window tkwin, int width)\n}\ndeclare 165 {\n    void Tk_SetWindowBackground(Tk_Window tkwin, unsigned long pixel)\n}\ndeclare 166 {\n    void Tk_SetWindowBackgroundPixmap(Tk_Window tkwin, Pixmap pixmap)\n}\ndeclare 167 {\n    void Tk_SetWindowBorder(Tk_Window tkwin, unsigned long pixel)\n}\ndeclare 168 {\n    void Tk_SetWindowBorderWidth(Tk_Window tkwin, int width)\n}\ndeclare 169 {\n    void Tk_SetWindowBorderPixmap(Tk_Window tkwin, Pixmap pixmap)\n}\ndeclare 170 {\n    void Tk_SetWindowColormap(Tk_Window tkwin, Colormap colormap)\n}\ndeclare 171 {\n    int Tk_SetWindowVisual(Tk_Window tkwin, Visual *visual, int depth,\n\t    Colormap colormap)\n}\ndeclare 172 {\n    void Tk_SizeOfBitmap(Display *display, Pixmap bitmap, int *widthPtr,\n\t    int *heightPtr)\n}\ndeclare 173 {\n    void Tk_SizeOfImage(Tk_Image image, int *widthPtr, int *heightPtr)\n}\ndeclare 174 {\n    int Tk_StrictMotif(Tk_Window tkwin)\n}\ndeclare 175 {\n    void Tk_TextLayoutToPostscript(Tcl_Interp *interp, Tk_TextLayout layout)\n}\ndeclare 176 {\n    int Tk_TextWidth(Tk_Font font, const char *str, Tcl_Size numBytes)\n}\ndeclare 177 {\n    void Tk_UndefineCursor(Tk_Window window)\n}\ndeclare 178 {\n    void Tk_UnderlineChars(Display *display,\n\t    Drawable drawable, GC gc, Tk_Font tkfont,\n\t    const char *source, int x, int y, Tcl_Size firstByte,\n\t    Tcl_Size lastByte)\n}\ndeclare 179 {\n    void Tk_UnderlineTextLayout(Display *display, Drawable drawable, GC gc,\n\t    Tk_TextLayout layout, int x, int y,\n\t    int underline)\n}\ndeclare 180 {\n    void Tk_Ungrab(Tk_Window tkwin)\n}\ndeclare 181 {\n    void Tk_UnmaintainGeometry(Tk_Window window, Tk_Window container)\n}\ndeclare 182 {\n    void Tk_UnmapWindow(Tk_Window tkwin)\n}\ndeclare 183 {\n    void Tk_UnsetGrid(Tk_Window tkwin)\n}\ndeclare 184 {\n    void Tk_UpdatePointer(Tk_Window tkwin, int x, int y, int state)\n}\n\n# new functions for 8.1\n\ndeclare 185 {\n    Pixmap  Tk_AllocBitmapFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n    Tcl_Obj *objPtr)\n}\ndeclare 186 {\n    Tk_3DBorder Tk_Alloc3DBorderFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr)\n}\ndeclare 187 {\n    XColor *Tk_AllocColorFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr)\n}\ndeclare 188 {\n    Tk_Cursor Tk_AllocCursorFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr)\n}\ndeclare 189 {\n    Tk_Font  Tk_AllocFontFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr)\n\n}\ndeclare 190 {\n    Tk_OptionTable Tk_CreateOptionTable(Tcl_Interp *interp,\n\t    const Tk_OptionSpec *templatePtr)\n}\ndeclare 191 {\n    void  Tk_DeleteOptionTable(Tk_OptionTable optionTable)\n}\ndeclare 192 {\n    void  Tk_Free3DBorderFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 193 {\n    void  Tk_FreeBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 194 {\n    void  Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 195 {\n    void  Tk_FreeConfigOptions(void *recordPtr, Tk_OptionTable optionToken,\n\t    Tk_Window tkwin)\n}\ndeclare 196 {\n    void  Tk_FreeSavedOptions(Tk_SavedOptions *savePtr)\n}\ndeclare 197 {\n    void  Tk_FreeCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 198 {\n    void  Tk_FreeFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 199 {\n    Tk_3DBorder Tk_Get3DBorderFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 200 {\n    int\t Tk_GetAnchorFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,\n\t    Tk_Anchor *anchorPtr)\n}\ndeclare 201 {\n    Pixmap  Tk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 202 {\n    XColor *Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 203 {\n    Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)\n}\ndeclare 204 {\n    Tcl_Obj *Tk_GetOptionInfo(Tcl_Interp *interp,\n\t    void *recordPtr, Tk_OptionTable optionTable,\n\t    Tcl_Obj *namePtr, Tk_Window tkwin)\n}\ndeclare 205 {\n    Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, void *recordPtr,\n\t    Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)\n}\ndeclare 206 {\n    int\t Tk_GetJustifyFromObj(Tcl_Interp *interp,\n\t    Tcl_Obj *objPtr, Tk_Justify *justifyPtr)\n}\ndeclare 207 {\n    int\t Tk_GetMMFromObj(Tcl_Interp *interp,\n\t    Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr)\n}\ndeclare 208 {\n    int\t Tk_GetPixelsFromObj(Tcl_Interp *interp,\n\t    Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr)\n}\ndeclare 209 {\n    int\t Tk_GetReliefFromObj(Tcl_Interp *interp,\n\t    Tcl_Obj *objPtr, int *resultPtr)\n}\ndeclare 210 {\n    int\t Tk_GetScrollInfoObj(Tcl_Interp *interp,\n\t    Tcl_Size objc, Tcl_Obj *const *objv, double *dblPtr, int *intPtr)\n}\ndeclare 211 {\n    int\t Tk_InitOptions(Tcl_Interp *interp, void *recordPtr,\n\t    Tk_OptionTable optionToken, Tk_Window tkwin)\n}\ndeclare 213 {\n    void  Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr)\n}\ndeclare 214 {\n    int\t Tk_SetOptions(Tcl_Interp *interp, void *recordPtr,\n\t    Tk_OptionTable optionTable, Tcl_Size objc,\n\t    Tcl_Obj *const *objv, Tk_Window tkwin,\n\t    Tk_SavedOptions *savePtr, int *maskPtr)\n}\ndeclare 215 {\n    void Tk_InitConsoleChannels(Tcl_Interp *interp)\n}\ndeclare 217 {\n    void Tk_CreateSmoothMethod(Tcl_Interp *interp, const Tk_SmoothMethod *method)\n}\n#declare 218 {\n#    void Tk_CreateCanvasVisitor(Tcl_Interp *interp, void *typePtr)\n#}\n#declare 219 {\n#    void *Tk_GetCanvasVisitor(Tcl_Interp *interp, const char *name)\n#}\ndeclare 220 {\n    int Tk_GetDash(Tcl_Interp *interp, const char *value, Tk_Dash *dash)\n}\ndeclare 221 {\n    void Tk_CreateOutline(Tk_Outline *outline)\n}\ndeclare 222 {\n    void Tk_DeleteOutline(Display *display, Tk_Outline *outline)\n}\ndeclare 223 {\n    int Tk_ConfigOutlineGC(XGCValues *gcValues, Tk_Canvas canvas,\n\t    Tk_Item *item, Tk_Outline *outline)\n}\ndeclare 224 {\n    int Tk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item,\n\t    Tk_Outline *outline)\n}\ndeclare 225 {\n    int Tk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item,\n\t    Tk_Outline *outline)\n}\ndeclare 226 {\n    int Tk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item,\n\t    Tk_Outline *outline)\n}\ndeclare 227 {\n    void Tk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y)\n}\ndeclare 228 {\n    int Tk_CanvasGetCoordFromObj(Tcl_Interp *interp, Tk_Canvas canvas,\n\t    Tcl_Obj *obj, double *doublePtr)\n}\ndeclare 229 {\n    void Tk_CanvasSetOffset(Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)\n}\ndeclare 230 {\n    void Tk_DitherPhoto(Tk_PhotoHandle handle, int x, int y, int width,\n\t    int height)\n}\ndeclare 231 {\n    int Tk_PostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX,\n\t    int startY, int width, int height)\n}\ndeclare 232 {\n    int Tk_PostscriptColor(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,\n\t    XColor *colorPtr)\n}\ndeclare 233 {\n    int Tk_PostscriptFont(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,\n\t    Tk_Font font)\n}\ndeclare 234 {\n    int Tk_PostscriptImage(Tk_Image image, Tcl_Interp *interp,\n\t    Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y,\n\t    int width, int height, int prepass)\n}\ndeclare 235 {\n    void Tk_PostscriptPath(Tcl_Interp *interp, Tk_PostscriptInfo psInfo,\n\t    double *coordPtr, Tcl_Size numPoints)\n}\ndeclare 236 {\n    int Tk_PostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tk_PostscriptInfo psInfo, Pixmap bitmap)\n}\ndeclare 237 {\n    double Tk_PostscriptY(double y, Tk_PostscriptInfo psInfo)\n}\ndeclare 238 {\n    int\tTk_PostscriptPhoto(Tcl_Interp *interp,\n\t    Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo,\n\t    int width, int height)\n}\n\n# New in 8.4a1\n#\ndeclare 239 {\n    void Tk_CreateClientMessageHandler(Tk_ClientMessageProc *proc)\n}\ndeclare 240 {\n    void Tk_DeleteClientMessageHandler(Tk_ClientMessageProc *proc)\n}\n\n# New in 8.4a2\n#\ndeclare 241 {\n    Tk_Window Tk_CreateAnonymousWindow(Tcl_Interp *interp,\n\t    Tk_Window parent, const char *screenName)\n}\ndeclare 242 {\n    void Tk_SetClassProcs(Tk_Window tkwin,\n\t    const Tk_ClassProcs *procs, void *instanceData)\n}\n\n# New in 8.4a4\n#\ndeclare 243 {\n    void Tk_SetInternalBorderEx(Tk_Window tkwin, int left, int right,\n\t    int top, int bottom)\n}\ndeclare 244 {\n    void Tk_SetMinimumRequestSize(Tk_Window tkwin,\n\t    int minWidth, int minHeight)\n}\n\n# New in 8.4a5\n#\ndeclare 245 {\n    void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)\n}\ndeclare 248 {\n    int Tk_CollapseMotionEvents(Display *display, int collapse)\n}\n\n# Style engine\ndeclare 249 {\n    Tk_StyleEngine Tk_RegisterStyleEngine(const char *name,\n\t    Tk_StyleEngine parent)\n}\ndeclare 250 {\n    Tk_StyleEngine Tk_GetStyleEngine(const char *name)\n}\ndeclare 251 {\n    int Tk_RegisterStyledElement(Tk_StyleEngine engine,\n\t    Tk_ElementSpec *templatePtr)\n}\ndeclare 252 {\n    int Tk_GetElementId(const char *name)\n}\ndeclare 253 {\n    Tk_Style Tk_CreateStyle(const char *name, Tk_StyleEngine engine,\n\t    void *clientData)\n}\ndeclare 254 {\n    Tk_Style Tk_GetStyle(Tcl_Interp *interp, const char *name)\n}\ndeclare 255 {\n    void Tk_FreeStyle(Tk_Style style)\n}\ndeclare 256 {\n    const char *Tk_NameOfStyle(Tk_Style style)\n}\ndeclare 257 {\n    Tk_Style  Tk_AllocStyleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr)\n}\ndeclare 260 {\n    Tk_StyledElement Tk_GetStyledElement(Tk_Style style, Tcl_Size elementId,\n\tTk_OptionTable optionTable)\n}\ndeclare 261 {\n    void Tk_GetElementSize(Tk_Style style, Tk_StyledElement element,\n\t    void *recordPtr, Tk_Window tkwin, int width, int height,\n\t    int inner, int *widthPtr, int *heightPtr)\n}\ndeclare 262 {\n    void Tk_GetElementBox(Tk_Style style, Tk_StyledElement element,\n\t    void *recordPtr, Tk_Window tkwin, int x, int y, int width,\n\t    int height, int inner, int *xPtr, int *yPtr, int *widthPtr,\n\t    int *heightPtr)\n}\ndeclare 263 {\n    int Tk_GetElementBorderWidth(Tk_Style style, Tk_StyledElement element,\n\t    void *recordPtr, Tk_Window tkwin)\n}\ndeclare 264 {\n    void Tk_DrawElement(Tk_Style style, Tk_StyledElement element,\n\t    void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y,\n\t    int width, int height, int state)\n}\n\n# TIP#116\ndeclare 265 {\n    int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle,\n\t    int width, int height)\n}\ndeclare 266 {\n    int Tk_PhotoPutBlock(Tcl_Interp *interp, Tk_PhotoHandle handle,\n\t    Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height,\n\t    int compRule)\n}\ndeclare 267 {\n    int Tk_PhotoPutZoomedBlock(Tcl_Interp *interp, Tk_PhotoHandle handle,\n\t    Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height,\n\t    int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule)\n}\ndeclare 268 {\n    int Tk_PhotoSetSize(Tcl_Interp *interp, Tk_PhotoHandle handle,\n\t    int width, int height)\n}\n# TIP#245\ndeclare 269 {\n    long Tk_GetUserInactiveTime(Display *dpy)\n}\ndeclare 270 {\n    void Tk_ResetUserInactiveTime(Display *dpy)\n}\n\n# TIP #264\ndeclare 271 {\n    Tcl_Interp *Tk_Interp(Tk_Window tkwin)\n}\n\n\n# ----- BASELINE -- FOR -- 8.6.0 ----- #\n\n\n# TIP#580\ndeclare 274 {\n    int Tk_AlwaysShowSelection(Tk_Window tkwin)\n}\ndeclare 275 {\n    unsigned Tk_GetButtonMask(unsigned button)\n}\ndeclare 276 {\n    int Tk_GetDoublePixelsFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr, double *doublePtr)\n}\ndeclare 277 {\n    Tcl_Obj *Tk_NewWindowObj(Tk_Window tkwin)\n}\ndeclare 278 {\n    void Tk_SendVirtualEvent(Tk_Window tkwin, const char *eventName,\n\t    Tcl_Obj *detail)\n}\ndeclare 279 {\n    Tcl_Obj *Tk_FontGetDescription(Tk_Font tkfont)\n}\n\n# TIP#529\ndeclare 280 {\n    void Tk_CreatePhotoImageFormatVersion3(\n\t    const Tk_PhotoImageFormatVersion3 *formatPtr)\n}\n\n# TIP#606\ndeclare 281 {\n    void Tk_DrawHighlightBorder(Tk_Window tkwin, GC fgGC, GC bgGC,\n\t    int highlightWidth, Drawable drawable)\n}\ndeclare 282 {\n    void Tk_SetMainMenubar(Tcl_Interp *interp, Tk_Window tkwin, const char *menuName)\n}\ndeclare 283 {\n    void Tk_SetWindowMenubar(Tcl_Interp *interp, Tk_Window tkwin,\n\t    const char *oldMenuName, const char *menuName)\n}\ndeclare 284 {\n    void Tk_ClipDrawableToRect(Display *display, Drawable d, int x,\n\t    int y, int width, int height)\n}\ndeclare 285 {\n    Tcl_Obj *Tk_GetSystemDefault(Tk_Window tkwin,\n\t    const char *dbName, const char *className)\n}\ndeclare 286 {\n    int Tk_UseWindow(Tcl_Interp *interp, Tk_Window tkwin, const char *string)\n}\ndeclare 287 {\n    void Tk_MakeContainer(Tk_Window tkwin)\n}\ndeclare 288 {\n    Tk_Window Tk_GetOtherWindow(Tk_Window tkwin)\n}\ndeclare 289 {\n    void Tk_Get3DBorderColors(Tk_3DBorder border, XColor *bgColorPtr, XColor *darkColorPtr,\n\t    XColor *lightColorPtr)\n}\ndeclare 290 {\n    Window Tk_MakeWindow(Tk_Window tkwin, Window parent)\n}\n\n# ----- BASELINE -- FOR -- 9.0.0 ----- #\n\n# TIP#706\ndeclare 291 {\n    void Tk_UnderlineCharsInContext(Display *display,\n\t   Drawable drawable, GC gc, Tk_Font tkfont,\n\t   const char *string, Tcl_Size numBytes, int x, int y,\n\t   Tcl_Size firstByte, Tcl_Size lastByte)\n}\ndeclare 292 {\n    void Tk_DrawCharsInContext(Display * display,\n\t   Drawable drawable, GC gc, Tk_Font tkfont,\n\t   const char *string, Tcl_Size numBytes, Tcl_Size rangeStart,\n\t   Tcl_Size rangeLength, int x, int y)\n}\ndeclare 293 {\n    int Tk_MeasureCharsInContext(Tk_Font tkfont,\n\t   const char *string, Tcl_Size numBytes, Tcl_Size rangeStart,\n\t   Tcl_Size rangeLength, int maxPixels, int flags,\n\t   int *lengthPtr)\n}\n\n# ----- BASELINE -- FOR -- 9.0.1 ----- #\n\ndeclare 294 {\n    void TkUnusedStubEntry(void)\n}\n\n# Define the platform specific public Tk interface.  These functions are\n# only available on the designated platform.\n\ninterface tkPlat\n\n################################\n# Windows specific functions\n\ndeclare 0 win {\n    Window Tk_AttachHWND(Tk_Window tkwin, HWND hwnd)\n}\ndeclare 1 win {\n    HINSTANCE Tk_GetHINSTANCE(void)\n}\ndeclare 2 win {\n    HWND Tk_GetHWND(Window window)\n}\ndeclare 3 win {\n    Tk_Window Tk_HWNDToWindow(HWND hwnd)\n}\n\n################################\n# Aqua specific functions\ndeclare 4 aqua {\n    void TkMacOSXInitAppleEvents(Tcl_Interp *interp)\n}\ndeclare 6 aqua {\n    void TkMacOSXInvalClipRgns(Tk_Window tkwin)\n}\n# Stub removed because it just returned NULL.\n#declare 7 aqua {\n#    void *TkMacOSXGetDrawablePort(Drawable drawable)\n#}\ndeclare 8 aqua {\n    void *TkMacOSXGetRootControl(Drawable drawable)\n}\ndeclare 9 aqua {\n    void Tk_MacOSXSetupTkNotifier(void)\n}\ndeclare 10 aqua {\n    int Tk_MacOSXIsAppInFront(void)\n}\ndeclare 11 aqua {\n    Tk_Window Tk_MacOSXGetTkWindow(void *w)\n}\ndeclare 12 aqua {\n    void *Tk_MacOSXGetCGContextForDrawable(Drawable drawable)\n}\n# Replaces TkMacOSXDrawable\ndeclare 13 aqua {\n    void *Tk_MacOSXGetNSWindowForDrawable(Drawable drawable)\n}\ndeclare 16 aqua {\n    void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, int width,\n\t    int height, int flags)\n}\n\n##############################################################################\n\n# Public functions that are not accessible via the stubs table.\n\nexport {\n    const char *Tk_PkgInitStubsCheck(Tcl_Interp *interp, const char *version,\n\t    int exact)\n}\nexport {\n    void Tk_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc,\n\t    Tcl_Interp *interp)\n}\nexport {\n    void Tk_MainExW(Tcl_Size argc, wchar_t **argv,\n\t    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);\n}\n\f\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "generic/tk.h",
    "content": "/*\n * tk.h --\n *\n *\tDeclarations for Tk-related things that are visible outside of the Tk\n *\tmodule itself.\n *\n * Copyright © 1989-1994 The Regents of the University of California.\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1998 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Ajuba Solutions.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TK\n#define _TK\n\n#include <tcl.h>\n#if (TCL_MAJOR_VERSION < 9)\n#\terror Tk 9.1 must be compiled with tcl.h from Tcl 9.0 or better\n#endif\n\n#ifndef EXTERN\n#   define EXTERN extern TCL_STORAGE_CLASS\n#endif\n\n/*\n * Utility macros: STRINGIFY takes an argument and wraps it in \"\" (double\n * quotation marks), JOIN joins two arguments.\n */\n\n#ifndef STRINGIFY\n#  define STRINGIFY(x) STRINGIFY1(x)\n#  define STRINGIFY1(x) #x\n#endif\n#ifndef JOIN\n#  define JOIN(a,b) JOIN1(a,b)\n#  define JOIN1(a,b) a##b\n#endif\n\n/*\n * For C++ compilers, use extern \"C\"\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * When version numbers change here, you must also go into the following files\n * and update the version numbers:\n *\n * library/tk.tcl\t(1 LOC patch)\n * unix/configure.ac\t(2 LOC Major, 2 LOC minor, 1 LOC patch)\n * win/configure.ac\t(as above)\n * README.md\t\t(sections 0 and 1)\n * win/README\t\t(not patchlevel)\n * unix/README\t\t(not patchlevel)\n * unix/tk.spec\t\t(1 LOC patch)\n * win/tcl.m4\t\t(not patchlevel)\n *\n * You may also need to update some of these files when the numbers change for\n * the version of Tcl that this release of Tk is compiled against.\n */\n\n#ifndef TK_MAJOR_VERSION\n#   define TK_MAJOR_VERSION 9\n#endif\n#if TK_MAJOR_VERSION != 9\n#   error \"This header-file is for Tk 9 only\"\n#endif\n#   define TK_MINOR_VERSION\t1\n#   define TK_RELEASE_LEVEL\tTCL_ALPHA_RELEASE\n#   define TK_RELEASE_SERIAL\t2\n\n#   define TK_VERSION\t\t\"9.1\"\n#   define TK_PATCH_LEVEL\t\t\"9.1a2\"\n\f\n/*\n * A special definition used to allow this header file to be included from\n * windows or mac resource files so that they can obtain version information.\n * RC_INVOKED is defined by default by the windows RC tool and manually set\n * for macintosh.\n *\n * Resource compilers don't like all the C stuff, like typedefs and procedure\n * declarations, that occur below, so block them out.\n */\n\n#ifndef RC_INVOKED\n\n#if !defined(_XLIB_H) && !defined(_X11_XLIB_H_)\n#if defined(__GNUC__) && !defined(__cplusplus)\n#   pragma GCC diagnostic ignored \"-Wc++-compat\"\n#endif\n#   define NeedWidePrototypes 1\n#   include <X11/Xlib.h>\n#   ifdef MAC_OSX_TK\n#\tinclude <X11/X.h>\n#   endif\n#endif\n#include <stddef.h>\n\n#ifdef BUILD_tk\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS\tDLLEXPORT\n#else\n# ifndef TCL_STORAGE_CLASS\n#   define TCL_STORAGE_CLASS DLLIMPORT\n# endif\n#endif\n\n/*\n *----------------------------------------------------------------------\n *\n * Decide whether or not to use input methods.\n */\n\n#if defined(XNQueryInputStyle) && !defined(_WIN32) && !defined(MAC_OSX_TK)\n#define TK_USE_INPUT_METHODS\n#endif\n\f\n/*\n * Dummy types that are used by clients:\n */\n\n#define Tk_ImageMaster Tk_ImageModel\ntypedef struct Tk_BindingTable_ *Tk_BindingTable;\ntypedef struct Tk_Canvas_ *Tk_Canvas;\ntypedef struct Tk_Cursor_ *Tk_Cursor;\ntypedef struct Tk_ErrorHandler_ *Tk_ErrorHandler;\ntypedef struct Tk_Font_ *Tk_Font;\ntypedef struct Tk_Image__ *Tk_Image;\ntypedef struct Tk_ImageModel_ *Tk_ImageModel;\ntypedef struct Tk_OptionTable_ *Tk_OptionTable;\ntypedef struct Tk_PostscriptInfo_ *Tk_PostscriptInfo;\ntypedef struct Tk_TextLayout_ *Tk_TextLayout;\ntypedef struct Tk_Window_ *Tk_Window;\ntypedef struct Tk_3DBorder_ *Tk_3DBorder;\ntypedef struct Tk_Style_ *Tk_Style;\ntypedef struct Tk_StyleEngine_ *Tk_StyleEngine;\ntypedef struct Tk_StyledElement_ *Tk_StyledElement;\n\n/*\n * Additional types exported to clients.\n */\n\ntypedef const char *Tk_Uid;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * The enum below defines the valid types for Tk configuration options as\n * implemented by Tk_InitOptions, Tk_SetOptions, etc.\n */\n\ntypedef enum {\n    TK_OPTION_BOOLEAN,\n    TK_OPTION_INT,\n    TK_OPTION_DOUBLE,\n    TK_OPTION_STRING,\n    TK_OPTION_STRING_TABLE,\n    TK_OPTION_COLOR,\n    TK_OPTION_FONT,\n    TK_OPTION_BITMAP,\n    TK_OPTION_BORDER,\n    TK_OPTION_RELIEF,\n    TK_OPTION_CURSOR,\n    TK_OPTION_JUSTIFY,\n    TK_OPTION_ANCHOR,\n    TK_OPTION_SYNONYM,\n    TK_OPTION_PIXELS,\n    TK_OPTION_WINDOW,\n    TK_OPTION_END,\n    TK_OPTION_CUSTOM,\n    TK_OPTION_STYLE,\n    TK_OPTION_INDEX\n} Tk_OptionType;\n\n/*\n * Structures of the following type are used by widgets to specify their\n * configuration options. Typically each widget has a static array of these\n * structures, where each element of the array describes a single\n * configuration option. The array is passed to Tk_CreateOptionTable.\n */\n\ntypedef struct Tk_OptionSpec {\n    Tk_OptionType type;\t\t/* Type of option, such as TK_OPTION_COLOR;\n\t\t\t\t * see definitions above. Last option in table\n\t\t\t\t * must have type TK_OPTION_END. */\n    const char *optionName;\t/* Name used to specify option in Tcl\n\t\t\t\t * commands. */\n    const char *dbName;\t\t/* Name for option in option database. */\n    const char *dbClass;\t/* Class for option in database. */\n    const char *defValue;\t/* Default value for option if not specified\n\t\t\t\t * in command line, the option database, or\n\t\t\t\t * the system. */\n    Tcl_Size objOffset;\t\t/* Where in record to store a Tcl_Obj * that\n\t\t\t\t * holds the value of this option, specified\n\t\t\t\t * as an offset in bytes from the start of the\n\t\t\t\t * record. Use the offsetof macro to generate\n\t\t\t\t * values for this. TCL_INDEX_NONE means don't\n\t\t\t\t * store the Tcl_Obj in the record. */\n    Tcl_Size internalOffset;\t\t/* Where in record to store the internal\n\t\t\t\t * representation of the value of this option,\n\t\t\t\t * such as an int or XColor *. This field is\n\t\t\t\t * specified as an offset in bytes from the\n\t\t\t\t * start of the record. Use the offsetof\n\t\t\t\t * macro to generate values for it.\n\t\t\t\t * TCL_INDEX_NONE means don't store the\n\t\t\t\t * internal representation in the record. */\n    int flags;\t\t\t/* Any combination of the values defined\n\t\t\t\t * below. */\n    const void *clientData;\t/* An alternate place to put option-specific\n\t\t\t\t * data. Used for the monochrome default value\n\t\t\t\t * for colors, etc. */\n    int typeMask;\t\t/* An arbitrary bit mask defined by the class\n\t\t\t\t * manager; typically bits correspond to\n\t\t\t\t * certain kinds of options such as all those\n\t\t\t\t * that require a redisplay when they change.\n\t\t\t\t * Tk_SetOptions returns the bit-wise OR of\n\t\t\t\t * the typeMasks of all options that were\n\t\t\t\t * changed. */\n} Tk_OptionSpec;\n\n/*\n * Flag values for Tk_OptionSpec structures. These flags are shared by\n * Tk_ConfigSpec structures, so be sure to coordinate any changes carefully.\n */\n\n#define TK_OPTION_DONT_SET_DEFAULT\t(1 << 3)\n#define TK_OPTION_NULL_OK\t\tTCL_NULL_OK\n#define TK_OPTION_NEG_OK\t\t(1 << 6) /* For TK_OPTION_PIXELS only, so no conflict with TK_OPTION_VAR */\n#define TK_OPTION_VAR(type)\t\t((sizeof(type) < 2 * sizeof(int)) ? ((int)(sizeof(type)&(sizeof(int)-1))<<6) : (3<<6))\n#define TK_OPTION_ENUM_VAR\t\tTK_OPTION_VAR(Tk_OptionType)\n\n/*\n * The following structure and function types are used by TK_OPTION_CUSTOM\n * options; the structure holds pointers to the functions needed by the Tk\n * option config code to handle a custom option.\n */\n\ntypedef int (Tk_CustomOptionSetProc) (void *clientData,\n\tTcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *widgRec,\n\tTcl_Size offset, char *saveInternalPtr, int flags);\ntypedef Tcl_Obj *(Tk_CustomOptionGetProc) (void *clientData,\n\tTk_Window tkwin, char *widgRec, Tcl_Size offset);\ntypedef void (Tk_CustomOptionRestoreProc) (void *clientData,\n\tTk_Window tkwin, char *internalPtr, char *saveInternalPtr);\ntypedef void (Tk_CustomOptionFreeProc) (void *clientData, Tk_Window tkwin,\n\tchar *internalPtr);\n\ntypedef struct Tk_ObjCustomOption {\n    const char *name;\t\t/* Name of the custom option. */\n    Tk_CustomOptionSetProc *setProc;\n\t\t\t\t/* Function to use to set a record's option\n\t\t\t\t * value from a Tcl_Obj */\n    Tk_CustomOptionGetProc *getProc;\n\t\t\t\t/* Function to use to get a Tcl_Obj\n\t\t\t\t * representation from an internal\n\t\t\t\t * representation of an option. */\n    Tk_CustomOptionRestoreProc *restoreProc;\n\t\t\t\t/* Function to use to restore a saved value\n\t\t\t\t * for the internal representation. */\n    Tk_CustomOptionFreeProc *freeProc;\n\t\t\t\t/* Function to use to free the internal\n\t\t\t\t * representation of an option. */\n    void *clientData;\t/* Arbitrary one-word value passed to the\n\t\t\t\t * handling procs. */\n} Tk_ObjCustomOption;\n\n/*\n * The following two structures are used for error handling. When config\n * options are being modified, the old values are saved in a Tk_SavedOptions\n * structure. If an error occurs, then the contents of the structure can be\n * used to restore all of the old values. The contents of this structure are\n * for the private use Tk. No-one outside Tk should ever read or write any of\n * the fields of these structures.\n */\n\ntypedef struct Tk_SavedOption {\n    struct TkOption *optionPtr;\t/* Points to information that describes the\n\t\t\t\t * option. */\n    Tcl_Obj *valuePtr;\t\t/* The old value of the option, in the form of\n\t\t\t\t * a Tcl object; may be NULL if the value was\n\t\t\t\t * not saved as an object. */\n    long double internalForm;\t/* The old value of the option, in some\n\t\t\t\t * internal representation such as an int or\n\t\t\t\t * (XColor *). Valid only if the field\n\t\t\t\t * optionPtr->specPtr->objOffset is -1. The\n\t\t\t\t * space must be large enough to accommodate a\n\t\t\t\t * long double, a double, a long, or a pointer;\n\t\t\t\t * right now it looks like a long double (i.e., 16\n\t\t\t\t * bytes) is big enough. Also, using a long double\n\t\t\t\t * guarantees that the field is properly aligned\n\t\t\t\t * for storing large values. */\n} Tk_SavedOption;\n\n#ifdef TCL_MEM_DEBUG\n#   define TK_NUM_SAVED_OPTIONS 2\n#else\n#   define TK_NUM_SAVED_OPTIONS 20\n#endif\n\ntypedef struct Tk_SavedOptions {\n    void *recordPtr;\t\t/* The data structure in which to restore\n\t\t\t\t * configuration options. */\n    Tk_Window tkwin;\t\t/* Window associated with recordPtr; needed to\n\t\t\t\t * restore certain options. */\n    Tcl_Size numItems;\t\t/* The number of valid items in items field. */\n    Tk_SavedOption items[TK_NUM_SAVED_OPTIONS];\n\t\t\t\t/* Items used to hold old values. */\n    struct Tk_SavedOptions *nextPtr;\n\t\t\t\t/* Points to next structure in list; needed if\n\t\t\t\t * too many options changed to hold all the\n\t\t\t\t * old values in a single structure. NULL\n\t\t\t\t * means no more structures. */\n} Tk_SavedOptions;\n\f\n/*\n * Structure used to describe application-specific configuration options:\n * indicates procedures to call to parse an option and to return a text string\n * describing an option. THESE ARE DEPRECATED; PLEASE USE THE NEW STRUCTURES\n * LISTED ABOVE.\n */\n\n/*\n * This is a temporary flag used while tkObjConfig and new widgets are in\n * development.\n */\n\n#ifndef __NO_OLD_CONFIG\n\ntypedef int (Tk_OptionParseProc) (void *clientData, Tcl_Interp *interp,\n\tTk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset);\ntypedef const char *(Tk_OptionPrintProc) (void *clientData,\n\tTk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr);\n\ntypedef struct Tk_CustomOption {\n    Tk_OptionParseProc *parseProc;\n\t\t\t\t/* Procedure to call to parse an option and\n\t\t\t\t * store it in converted form. */\n    Tk_OptionPrintProc *printProc;\n\t\t\t\t/* Procedure to return a printable string\n\t\t\t\t * describing an existing option. */\n    void *clientData;\t/* Arbitrary one-word value used by option\n\t\t\t\t * parser: passed to parseProc and\n\t\t\t\t * printProc. */\n} Tk_CustomOption;\n\n/*\n * Structure used to specify information for Tk_ConfigureWidget. Each\n * structure gives complete information for one option, including how the\n * option is specified on the command line, where it appears in the option\n * database, etc.\n */\n\ntypedef struct Tk_ConfigSpec {\n    int type;\t\t\t/* Type of option, such as TK_CONFIG_COLOR;\n\t\t\t\t * see definitions below. Last option in table\n\t\t\t\t * must have type TK_CONFIG_END. */\n    const char *argvName;\t/* Switch used to specify option in argv. NULL\n\t\t\t\t * means this spec is part of a group. */\n    Tk_Uid dbName;\t\t/* Name for option in option database. */\n    Tk_Uid dbClass;\t\t/* Class for option in database. */\n    Tk_Uid defValue;\t\t/* Default value for option if not specified\n\t\t\t\t * in command line or database. */\n    Tcl_Size offset;\t\t\t/* Where in widget record to store value; use\n\t\t\t\t * offsetof macro to generate values for\n\t\t\t\t * this. */\n    int specFlags;\t\t/* Any combination of the values defined\n\t\t\t\t * below; other bits are used internally by\n\t\t\t\t * tkConfig.c. */\n    const Tk_CustomOption *customPtr;\n\t\t\t\t/* If type is TK_CONFIG_CUSTOM then this is a\n\t\t\t\t * pointer to info about how to parse and\n\t\t\t\t * print the option. Otherwise it is\n\t\t\t\t * irrelevant. */\n} Tk_ConfigSpec;\n\n/*\n * Type values for Tk_ConfigSpec structures. See the user documentation for\n * details.\n */\n\ntypedef enum {\n    TK_CONFIG_BOOLEAN, TK_CONFIG_INT, TK_CONFIG_DOUBLE, TK_CONFIG_STRING,\n    TK_CONFIG_UID, TK_CONFIG_COLOR, TK_CONFIG_FONT, TK_CONFIG_BITMAP,\n    TK_CONFIG_BORDER, TK_CONFIG_RELIEF, TK_CONFIG_CURSOR,\n    TK_CONFIG_ACTIVE_CURSOR, TK_CONFIG_JUSTIFY, TK_CONFIG_ANCHOR,\n    TK_CONFIG_SYNONYM, TK_CONFIG_CAP_STYLE, TK_CONFIG_JOIN_STYLE,\n    TK_CONFIG_PIXELS, TK_CONFIG_MM, TK_CONFIG_WINDOW, TK_CONFIG_CUSTOM,\n    TK_CONFIG_END\n} Tk_ConfigTypes;\n\n/*\n * Possible values for flags argument to Tk_ConfigureWidget:\n */\n\n#define TK_CONFIG_ARGV_ONLY\t1\n#define TK_CONFIG_OBJS\t\t0x80\n\n/*\n * Possible flag values for Tk_ConfigSpec structures. Any bits at or above\n * TK_CONFIG_USER_BIT may be used by clients for selecting certain entries.\n * Before changing any values here, coordinate with tkOldConfig.c\n * (internal-use-only flags are defined there).\n */\n\n#define TK_CONFIG_COLOR_ONLY\t\t(1 << 1)\n#define TK_CONFIG_MONO_ONLY\t\t(1 << 2)\n#define TK_CONFIG_DONT_SET_DEFAULT\t(1 << 3)\n#define TK_CONFIG_NULL_OK\t\tTCL_NULL_OK\n#define TK_CONFIG_USER_BIT\t\t0x100\n#endif /* __NO_OLD_CONFIG */\n\f\n/*\n * Structure used to specify how to handle argv options.\n */\n\ntypedef struct {\n    const char *key;\t\t/* The key string that flags the option in the\n\t\t\t\t * argv array. */\n    int type;\t\t\t/* Indicates option type; see below. */\n    void *src;\t\t\t/* Value to be used in setting dst; usage\n\t\t\t\t * depends on type. */\n    void *dst;\t\t\t/* Address of value to be modified; usage\n\t\t\t\t * depends on type. */\n    const char *help;\t\t/* Documentation message describing this\n\t\t\t\t * option. */\n} Tk_ArgvInfo;\n\n/*\n * Legal values for the type field of a Tk_ArgvInfo: see the user\n * documentation for details.\n */\n\n#define TK_ARGV_CONSTANT\t\t15\n#define TK_ARGV_INT\t\t\t16\n#define TK_ARGV_STRING\t\t\t17\n#define TK_ARGV_UID\t\t\t18\n#define TK_ARGV_REST\t\t\t19\n#define TK_ARGV_FLOAT\t\t\t20\n#define TK_ARGV_FUNC\t\t\t21\n#define TK_ARGV_GENFUNC\t\t\t22\n#define TK_ARGV_HELP\t\t\t23\n#define TK_ARGV_CONST_OPTION\t\t24\n#define TK_ARGV_OPTION_VALUE\t\t25\n#define TK_ARGV_OPTION_NAME_VALUE\t26\n#define TK_ARGV_END\t\t\t27\n\n/*\n * Flag bits for passing to Tk_ParseArgv:\n */\n\n#define TK_ARGV_NO_DEFAULTS\t\t0x1\n#define TK_ARGV_NO_LEFTOVERS\t\t0x2\n#define TK_ARGV_NO_ABBREV\t\t0x4\n#define TK_ARGV_DONT_SKIP_FIRST_ARG\t0x8\n\f\n/*\n * Enumerated type for describing actions to be taken in response to a\n * restrictProc established by Tk_RestrictEvents.\n */\n\ntypedef enum {\n    TK_DEFER_EVENT, TK_PROCESS_EVENT, TK_DISCARD_EVENT\n} Tk_RestrictAction;\n\n/*\n * Priority levels to pass to Tk_AddOption:\n */\n\n#define TK_WIDGET_DEFAULT_PRIO\t20\n#define TK_STARTUP_FILE_PRIO\t40\n#define TK_USER_DEFAULT_PRIO\t60\n#define TK_INTERACTIVE_PRIO\t80\n#define TK_MAX_PRIO\t\t100\n\n/*\n * Relief values returned by Tk_GetRelief:\n */\n\n#define TK_RELIEF_NULL\t\t-1\n#define TK_RELIEF_FLAT\t\t0\n#define TK_RELIEF_GROOVE\t1\n#define TK_RELIEF_RAISED\t2\n#define TK_RELIEF_RIDGE\t\t3\n#define TK_RELIEF_SOLID\t\t4\n#define TK_RELIEF_SUNKEN\t5\n\n/*\n * \"Which\" argument values for Tk_3DBorderGC:\n */\n\n#define TK_3D_FLAT_GC\t\t1\n#define TK_3D_LIGHT_GC\t\t2\n#define TK_3D_DARK_GC\t\t3\n\n/*\n * Special EnterNotify/LeaveNotify \"mode\" for use in events generated by\n * tkShare.c. Pick a high enough value that it's unlikely to conflict with\n * existing values (like NotifyNormal) or any new values defined in the\n * future.\n */\n\n#define TK_NOTIFY_SHARE\t\t20\n\n/*\n * Enumerated type for describing a point by which to anchor something:\n */\n\ntypedef enum {\n    TK_ANCHOR_NULL = -1,\n    TK_ANCHOR_N, TK_ANCHOR_NE, TK_ANCHOR_E, TK_ANCHOR_SE,\n    TK_ANCHOR_S, TK_ANCHOR_SW, TK_ANCHOR_W, TK_ANCHOR_NW,\n    TK_ANCHOR_CENTER\n} Tk_Anchor;\n\f\n/*\n * Enumerated type for describing a style of justification:\n */\n\ntypedef enum {\n    TK_JUSTIFY_NULL = -1,\n    TK_JUSTIFY_LEFT, TK_JUSTIFY_RIGHT, TK_JUSTIFY_CENTER\n} Tk_Justify;\n\n/*\n * The following structure is used by Tk_GetFontMetrics() to return\n * information about the properties of a Tk_Font.\n */\n\ntypedef struct Tk_FontMetrics {\n    int ascent;\t\t\t/* The amount in pixels that the tallest\n\t\t\t\t * letter sticks up above the baseline, plus\n\t\t\t\t * any extra blank space added by the designer\n\t\t\t\t * of the font. */\n    int descent;\t\t/* The largest amount in pixels that any\n\t\t\t\t * letter sticks below the baseline, plus any\n\t\t\t\t * extra blank space added by the designer of\n\t\t\t\t * the font. */\n    int linespace;\t\t/* The sum of the ascent and descent. How far\n\t\t\t\t * apart two lines of text in the same font\n\t\t\t\t * should be placed so that none of the\n\t\t\t\t * characters in one line overlap any of the\n\t\t\t\t * characters in the other line. */\n} Tk_FontMetrics;\n\n/*\n * Flags passed to Tk_MeasureChars:\n */\n\n#define TK_WHOLE_WORDS\t\t1\n#define TK_AT_LEAST_ONE\t\t2\n#define TK_PARTIAL_OK\t\t4\n#define TK_ISOLATE_END\t\t32\n\n/*\n * Flags passed to Tk_ComputeTextLayout:\n */\n\n#define TK_IGNORE_TABS\t\t8\n#define TK_IGNORE_NEWLINES\t16\n\f\n/*\n * Widget class procedures used to implement platform specific widget\n * behavior.\n */\n\ntypedef Window (Tk_ClassCreateProc) (Tk_Window tkwin, Window parent,\n\tvoid *instanceData);\ntypedef void (Tk_ClassWorldChangedProc) (void *instanceData);\ntypedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr);\n\ntypedef struct Tk_ClassProcs {\n    Tcl_Size size;\n    Tk_ClassWorldChangedProc *worldChangedProc;\n\t\t\t\t/* Procedure to invoke when the widget needs\n\t\t\t\t * to respond in some way to a change in the\n\t\t\t\t * world (font changes, etc.) */\n    Tk_ClassCreateProc *createProc;\n\t\t\t\t/* Procedure to invoke when the platform-\n\t\t\t\t * dependent window needs to be created. */\n    Tk_ClassModalProc *modalProc;\n\t\t\t\t/* Procedure to invoke after all bindings on a\n\t\t\t\t * widget have been triggered in order to\n\t\t\t\t * handle a modal loop. */\n} Tk_ClassProcs;\n\n/*\n * Simple accessor for Tk_ClassProcs structure. Checks that the structure is\n * not NULL, then checks the size field and returns either the requested\n * field, if present, or NULL if the structure is too small to have the field\n * (or NULL if the structure is NULL).\n *\n * A more general version of this function may be useful if other\n * size-versioned structure pop up in the future:\n *\n *\t#define Tk_GetField(name, who, which) \\\n *\t    (((who) == NULL) ? NULL :\n *\t    (((size_t)(who)->size <= offsetof(name, which)) ? NULL :(name)->which))\n */\n\n#define Tk_GetClassProc(procs, which) \\\n    (((procs) == NULL) ? NULL : \\\n    (((size_t)(procs)->size <= offsetof(Tk_ClassProcs, which)) ? NULL:(procs)->which))\n\f\n/*\n * Each geometry manager (the packer, the placer, etc.) is represented by a\n * structure of the following form, which indicates procedures to invoke in\n * the geometry manager to carry out certain functions.\n */\n\n#define Tk_GeomLostSlaveProc Tk_GeomLostContentProc\ntypedef void (Tk_GeomRequestProc) (void *clientData, Tk_Window tkwin);\ntypedef void (Tk_GeomLostContentProc) (void *clientData, Tk_Window tkwin);\n\ntypedef struct Tk_GeomMgr {\n    const char *name;\t\t/* Name of the geometry manager (command used\n\t\t\t\t * to invoke it, or name of widget class that\n\t\t\t\t * allows embedded widgets). */\n    Tk_GeomRequestProc *requestProc;\n\t\t\t\t/* Procedure to invoke when a content's\n\t\t\t\t * requested geometry changes. */\n    Tk_GeomLostContentProc *lostContentProc;\n\t\t\t\t/* Procedure to invoke when content is taken\n\t\t\t\t * away from one geometry manager by another.\n\t\t\t\t * NULL means geometry manager doesn't care\n\t\t\t\t * when content lost. */\n} Tk_GeomMgr;\n\n/*\n * Result values returned by Tk_GetScrollInfo:\n */\n\n#define TK_SCROLL_MOVETO\t1\n#define TK_SCROLL_PAGES\t\t2\n#define TK_SCROLL_UNITS\t\t3\n#define TK_SCROLL_ERROR\t\t4\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Extensions to the X event set\n *\n *----------------------------------------------------------------------\n */\n\n#define VirtualEvent\t    (MappingNotify + 1)\n#define ActivateNotify\t    (MappingNotify + 2)\n#define DeactivateNotify    (MappingNotify + 3)\n#define MouseWheelEvent     (MappingNotify + 4)\n#define TouchpadScroll      (MappingNotify + 5)\n#define TK_LASTEVENT\t    (MappingNotify + 6)\n\n#define TouchpadScrollMask  (1L << 27)\n#define MouseWheelMask\t    (1L << 28)\n#define ActivateMask\t    (1L << 29)\n#define VirtualEventMask    (1L << 30)\n\n/*\n * A virtual event shares most of its fields with the XKeyEvent and\n * XButtonEvent structures. 99% of the time a virtual event will be an\n * abstraction of a key or button event, so this structure provides the most\n * information to the user. The only difference is the changing of the detail\n * field for a virtual event so that it holds the name of the virtual event\n * being triggered.\n *\n * When using this structure, you should ensure that you zero out all the\n * fields first using memset() or bzero().\n */\n\ntypedef struct {\n    int type;\n    unsigned long serial;\t/* # of last request processed by server. */\n    Bool send_event;\t\t/* True if this came from a SendEvent\n\t\t\t\t * request. */\n    Display *display;\t\t/* Display the event was read from. */\n    Window event;\t\t/* Window on which event was requested. */\n    Window root;\t\t/* Root window that the event occurred on. */\n    Window subwindow;\t\t/* Child window. */\n    Time time;\t\t\t/* Milliseconds. */\n    int x, y;\t\t\t/* Pointer x, y coordinates in event\n\t\t\t\t * window. */\n    int x_root, y_root;\t\t/* Coordinates relative to root. */\n    unsigned int state;\t\t/* Key or button mask */\n    Tk_Uid name;\t\t/* Name of virtual event. */\n    Bool same_screen;\t\t/* Same screen flag. */\n    Tcl_Obj *user_data;\t\t/* Application-specific data reference; Tk\n\t\t\t\t * will decrement the reference count *once*\n\t\t\t\t * when it has finished processing the\n\t\t\t\t * event. */\n} XVirtualEvent;\n\ntypedef struct {\n    int type;\n    unsigned long serial;\t/* # of last request processed by server. */\n    Bool send_event;\t\t/* True if this came from a SendEvent\n\t\t\t\t * request. */\n    Display *display;\t\t/* Display the event was read from. */\n    Window window;\t\t/* Window in which event occurred. */\n} XActivateDeactivateEvent;\ntypedef XActivateDeactivateEvent XActivateEvent;\ntypedef XActivateDeactivateEvent XDeactivateEvent;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Macros for querying Tk_Window structures. See the manual entries for\n * documentation.\n *\n *----------------------------------------------------------------------\n */\n\n#define Tk_Display(tkwin)\t(((Tk_FakeWin *) (tkwin))->display)\n#define Tk_ScreenNumber(tkwin)\t(((Tk_FakeWin *) (tkwin))->screenNum)\n#define Tk_Screen(tkwin) \\\n    (ScreenOfDisplay(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)))\n#define Tk_Depth(tkwin)\t\t(((Tk_FakeWin *) (tkwin))->depth)\n#define Tk_Visual(tkwin)\t(((Tk_FakeWin *) (tkwin))->visual)\n#define Tk_WindowId(tkwin)\t(((Tk_FakeWin *) (tkwin))->window)\n#define Tk_PathName(tkwin)\t(((Tk_FakeWin *) (tkwin))->pathName)\n#define Tk_Name(tkwin)\t\t(((Tk_FakeWin *) (tkwin))->nameUid)\n#define Tk_Class(tkwin)\t(((Tk_FakeWin *) (tkwin))->classUid)\n#define Tk_X(tkwin)\t\t(((Tk_FakeWin *) (tkwin))->changes.x)\n#define Tk_Y(tkwin)\t\t(((Tk_FakeWin *) (tkwin))->changes.y)\n#define Tk_Width(tkwin)\t\t(((Tk_FakeWin *) (tkwin))->changes.width)\n#define Tk_Height(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->changes.height)\n#define Tk_Changes(tkwin)\t(&((Tk_FakeWin *) (tkwin))->changes)\n#define Tk_Attributes(tkwin)\t(&((Tk_FakeWin *) (tkwin))->atts)\n#define Tk_IsEmbedded(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_EMBEDDED)\n#define Tk_IsContainer(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_CONTAINER)\n#define Tk_IsMapped(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_MAPPED)\n#define Tk_IsTopLevel(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_LEVEL)\n#define Tk_HasWrapper(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_HAS_WRAPPER)\n#define Tk_WinManaged(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_WIN_MANAGED)\n#define Tk_TopWinHierarchy(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY)\n#define Tk_IsManageable(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->flags & TK_WM_MANAGEABLE)\n#define Tk_ReqWidth(tkwin)\t(((Tk_FakeWin *) (tkwin))->reqWidth)\n#define Tk_ReqHeight(tkwin)\t(((Tk_FakeWin *) (tkwin))->reqHeight)\n#define Tk_InternalBorderLeft(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->internalBorderLeft)\n#define Tk_InternalBorderRight(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->internalBorderRight)\n#define Tk_InternalBorderTop(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->internalBorderTop)\n#define Tk_InternalBorderBottom(tkwin) \\\n    (((Tk_FakeWin *) (tkwin))->internalBorderBottom)\n#define Tk_MinReqWidth(tkwin)\t(((Tk_FakeWin *) (tkwin))->minReqWidth)\n#define Tk_MinReqHeight(tkwin)\t(((Tk_FakeWin *) (tkwin))->minReqHeight)\n#define Tk_Parent(tkwin)\t(((Tk_FakeWin *) (tkwin))->parentPtr)\n#define Tk_Colormap(tkwin)\t(((Tk_FakeWin *) (tkwin))->atts.colormap)\n\n/*\n * The structure below is needed by the macros above so that they can access\n * the fields of a Tk_Window. The fields not needed by the macros are declared\n * as \"dummyX\". The structure has its own type in order to prevent apps from\n * accessing Tk_Window fields except using official macros. WARNING!! The\n * structure definition must be kept consistent with the TkWindow structure in\n * tkInt.h. If you change one, then change the other. See the declaration in\n * tkInt.h for documentation on what the fields are used for internally.\n */\n\ntypedef struct Tk_FakeWin {\n    Display *display;\n    char *dummy1;\t\t/* dispPtr */\n    int screenNum;\n    Visual *visual;\n    int depth;\n    Window window;\n    char *dummy2;\t\t/* childList */\n    char *dummy3;\t\t/* lastChildPtr */\n    Tk_Window parentPtr;\t/* parentPtr */\n    char *dummy4;\t\t/* nextPtr */\n    char *dummy5;\t\t/* mainPtr */\n    char *pathName;\n    Tk_Uid nameUid;\n    Tk_Uid classUid;\n    XWindowChanges changes;\n    unsigned int dummy6;\t/* dirtyChanges */\n    XSetWindowAttributes atts;\n    unsigned long dummy7;\t/* dirtyAtts */\n    unsigned int flags;\n    char *dummy8;\t\t/* handlerList */\n    XIC dummy9;\t\t\t/* inputContext */\n    void **dummy10;\t/* tagPtr */\n    Tcl_Size dummy11;\t\t/* numTags */\n    Tcl_Size dummy12;\t\t/* optionLevel */\n    char *dummy13;\t\t/* selHandlerList */\n    char *dummy14;\t\t/* geomMgrPtr */\n    void *dummy15;\t\t/* geomData */\n    int reqWidth, reqHeight;\n    int internalBorderLeft;\n    char *dummy16;\t\t/* wmInfoPtr */\n    char *dummy17;\t\t/* classProcPtr */\n    void *dummy18;\t\t/* instanceData */\n    char *dummy19;\t\t/* privatePtr */\n    int internalBorderRight;\n    int internalBorderTop;\n    int internalBorderBottom;\n    int minReqWidth;\n    int minReqHeight;\n    int dummy20;\n    char *dummy21;\t\t/* geomMgrName */\n    Tk_Window dummy22;\t\t/* maintainerPtr */\n} Tk_FakeWin;\n\n/*\n * Flag values for TkWindow (and Tk_FakeWin) structures are:\n *\n * TK_MAPPED:\t\t\t1 means window is currently mapped,\n *\t\t\t\t0 means unmapped.\n * TK_TOP_LEVEL:\t\t1 means this is a top-level widget.\n * TK_ALREADY_DEAD:\t\t1 means the window is in the process of\n *\t\t\t\tbeing destroyed already.\n * TK_NEED_CONFIG_NOTIFY:\t1 means that the window has been reconfigured\n *\t\t\t\tbefore it was made to exist. At the time of\n *\t\t\t\tmaking it exist a ConfigureNotify event needs\n *\t\t\t\tto be generated.\n * TK_GRAB_FLAG:\t\tUsed to manage grabs. See tkGrab.c for details\n * TK_CHECKED_IC:\t\t1 means we've already tried to get an input\n *\t\t\t\tcontext for this window; if the ic field is\n *\t\t\t\tNULL it means that there isn't a context for\n *\t\t\t\tthe field.\n * TK_DONT_DESTROY_WINDOW:\t1 means that Tk_DestroyWindow should not\n *\t\t\t\tinvoke XDestroyWindow to destroy this widget's\n *\t\t\t\tX window. The flag is set when the window has\n *\t\t\t\talready been destroyed elsewhere (e.g. by\n *\t\t\t\tanother application) or when it will be\n *\t\t\t\tdestroyed later (e.g. by destroying its parent)\n * TK_WM_COLORMAP_WINDOW:\t1 means that this window has at some time\n *\t\t\t\tappeared in the WM_COLORMAP_WINDOWS property\n *\t\t\t\tfor its toplevel, so we have to remove it from\n *\t\t\t\tthat property if the window is deleted and the\n *\t\t\t\ttoplevel isn't.\n * TK_EMBEDDED:\t\t\t1 means that this window (which must be a\n *\t\t\t\ttoplevel) is not a free-standing window but\n *\t\t\t\trather is embedded in some other application.\n * TK_CONTAINER:\t\t1 means that this window is a container, and\n *\t\t\t\tthat some other application (either in this\n *\t\t\t\tprocess or elsewhere) may be embedding itself\n *\t\t\t\tinside the window.\n * TK_BOTH_HALVES:\t\t1 means that this window is used for\n *\t\t\t\tapplication embedding (either as container or\n *\t\t\t\tembedded application), and both the containing\n *\t\t\t\tand embedded halves are associated with\n *\t\t\t\twindows in this particular process.\n * TK_WRAPPER:\t\t\t1 means that this window is the extra wrapper\n *\t\t\t\twindow created around a toplevel to hold the\n *\t\t\t\tmenubar under Unix. See tkUnixWm.c for more\n *\t\t\t\tinformation.\n * TK_REPARENTED:\t\t1 means that this window has been reparented\n *\t\t\t\tso that as far as the window system is\n *\t\t\t\tconcerned it isn't a child of its Tk parent.\n *\t\t\t\tInitially this is used only for special Unix\n *\t\t\t\tmenubar windows.\n * TK_ANONYMOUS_WINDOW:\t\t1 means that this window has no name, and is\n *\t\t\t\tthus not accessible from Tk.\n * TK_HAS_WRAPPER\t\t1 means that this window has a wrapper window\n * TK_WIN_MANAGED\t\t1 means that this window is a child of the root\n *\t\t\t\twindow, and is managed by the window manager.\n * TK_TOP_HIERARCHY\t\t1 means this window is at the top of a physical\n *\t\t\t\twindow hierarchy within this process, i.e. the\n *\t\t\t\twindow's parent either doesn't exist or is not\n *\t\t\t\towned by this Tk application.\n * TK_PROP_PROPCHANGE\t\t1 means that PropertyNotify events in the\n *\t\t\t\twindow's children should propagate up to this\n *\t\t\t\twindow.\n * TK_WM_MANAGEABLE\t\t1 marks a window as capable of being converted\n *\t\t\t\tinto a toplevel using [wm manage].\n * TK_CAN_INPUT_TEXT            1 means that this window accepts text input.\n *                              Used on macOS to indicate that key events can be\n *                              processed with the NSTextInputClient protocol.\n *                              Not currently accessible through the public API.\n */\n\n#define TK_MAPPED\t\t1\n#define TK_TOP_LEVEL\t\t2\n#define TK_ALREADY_DEAD\t\t4\n#define TK_NEED_CONFIG_NOTIFY\t8\n#define TK_GRAB_FLAG\t\t0x10\n#define TK_CHECKED_IC\t\t0x20\n#define TK_DONT_DESTROY_WINDOW\t0x40\n#define TK_WM_COLORMAP_WINDOW\t0x80\n#define TK_EMBEDDED\t\t0x100\n#define TK_CONTAINER\t\t0x200\n#define TK_BOTH_HALVES\t\t0x400\n\n#define TK_WRAPPER\t\t0x1000\n#define TK_REPARENTED\t\t0x2000\n#define TK_ANONYMOUS_WINDOW\t0x4000\n#define TK_HAS_WRAPPER\t\t0x8000\n#define TK_WIN_MANAGED\t\t0x10000\n#define TK_TOP_HIERARCHY\t0x20000\n#define TK_PROP_PROPCHANGE\t0x40000\n#define TK_WM_MANAGEABLE\t0x80000\n#define TK_CAN_INPUT_TEXT       0x100000\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Procedure prototypes and structures used for defining new canvas items:\n *\n *----------------------------------------------------------------------\n */\n\ntypedef enum {\n    TK_STATE_NULL = -1, TK_STATE_ACTIVE, TK_STATE_DISABLED,\n    TK_STATE_NORMAL, TK_STATE_HIDDEN\n} Tk_State;\n\ntypedef struct Tk_SmoothMethod {\n    const char *name;\n    int (*coordProc) (Tk_Canvas canvas, double *pointPtr, int numPoints,\n\t    int numSteps, XPoint xPoints[], double dblPoints[]);\n    void (*postscriptProc) (Tcl_Interp *interp, Tk_Canvas canvas,\n\t    double *coordPtr, int numPoints, int numSteps);\n} Tk_SmoothMethod;\n\n/*\n * For each item in a canvas widget there exists one record with the following\n * structure. Each actual item is represented by a record with the following\n * stuff at its beginning, plus additional type-specific stuff after that.\n */\n\n#define TK_TAG_SPACE 3\n\ntypedef struct Tk_Item {\n    Tcl_Size id;\t\t/* Unique identifier for this item (also\n\t\t\t\t * serves as first tag for item). */\n    struct Tk_Item *nextPtr;\t/* Next in display list of all items in this\n\t\t\t\t * canvas. Later items in list are drawn on\n\t\t\t\t * top of earlier ones. */\n    Tk_Uid staticTagSpace[TK_TAG_SPACE];\n\t\t\t\t/* Built-in space for limited # of tags. */\n    Tk_Uid *tagPtr;\t\t/* Pointer to array of tags. Usually points to\n\t\t\t\t * staticTagSpace, but may point to malloc-ed\n\t\t\t\t * space if there are lots of tags. */\n    Tcl_Size tagSpace;\t\t/* Total amount of tag space available at\n\t\t\t\t * tagPtr. */\n    Tcl_Size numTags;\t\t/* Number of tag slots actually used at\n\t\t\t\t * *tagPtr. */\n    struct Tk_ItemType *typePtr;/* Table of procedures that implement this\n\t\t\t\t * type of item. */\n    int x1, y1, x2, y2;\t\t/* Bounding box for item, in integer canvas\n\t\t\t\t * units. Set by item-specific code and\n\t\t\t\t * guaranteed to contain every pixel drawn in\n\t\t\t\t * item. Item area includes x1 and y1 but not\n\t\t\t\t * x2 and y2. */\n    struct Tk_Item *prevPtr;\t/* Previous in display list of all items in\n\t\t\t\t * this canvas. Later items in list are drawn\n\t\t\t\t * just below earlier ones. */\n    Tk_State state;\t\t/* State of item. */\n    void *reserved1;\t\t/* reserved for future use */\n    int redraw_flags;\t\t/* Some flags used in the canvas */\n\n    /*\n     *------------------------------------------------------------------\n     * Starting here is additional type-specific stuff; see the declarations\n     * for individual types to see what is part of each type. The actual space\n     * below is determined by the \"itemInfoSize\" of the type's Tk_ItemType\n     * record.\n     *------------------------------------------------------------------\n     */\n} Tk_Item;\n\n/*\n * Flag bits for canvases (redraw_flags):\n *\n * TK_ITEM_STATE_DEPENDANT -\t1 means that object needs to be redrawn if the\n *\t\t\t\tcanvas state changes.\n * TK_ITEM_DONT_REDRAW -\t1 means that the object redraw is already been\n *\t\t\t\tprepared, so the general canvas code doesn't\n *\t\t\t\tneed to do that any more.\n */\n\n#define TK_ITEM_STATE_DEPENDANT\t\t1\n#define TK_ITEM_DONT_REDRAW\t\t2\n\n/*\n * Records of the following type are used to describe a type of item (e.g.\n * lines, circles, etc.) that can form part of a canvas widget.\n */\n\ntypedef int\t(Tk_ItemCreateProc)(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\ntypedef int\t(Tk_ItemConfigureProc)(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t    int flags);\ntypedef int\t(Tk_ItemCoordProc)(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\ntypedef void\t(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Tcl_Size beforeThis, Tcl_Obj *string);\ntypedef int\t(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t    Tk_Item *itemPtr, Tcl_Obj *indexString, Tcl_Size *indexPtr);\ntypedef void\t(Tk_ItemDeleteProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Display *display);\ntypedef void\t(Tk_ItemDisplayProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Display *display, Drawable dst, int x, int y, int width,\n\t\t    int height);\ntypedef double\t(Tk_ItemPointProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    double *pointPtr);\ntypedef int\t(Tk_ItemAreaProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    double *rectPtr);\ntypedef int\t(Tk_ItemPostscriptProc)(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t    Tk_Item *itemPtr, int prepass);\ntypedef void\t(Tk_ItemRotateProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    double originX, double originY, double angleRadians);\ntypedef void\t(Tk_ItemScaleProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    double originX, double originY, double scaleX,\n\t\t    double scaleY);\ntypedef void\t(Tk_ItemTranslateProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    double deltaX, double deltaY);\ntypedef void\t(Tk_ItemCursorProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Tcl_Size index);\ntypedef Tcl_Size (Tk_ItemSelectionProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\ntypedef void\t(Tk_ItemDCharsProc)(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t    Tcl_Size first, Tcl_Size last);\n\n#ifndef __NO_OLD_CONFIG\n\ntypedef struct Tk_ItemType {\n    const char *name;\t\t/* The name of this type of item, such as\n\t\t\t\t * \"line\". */\n    Tcl_Size itemSize;\t\t/* Total amount of space needed for item's\n\t\t\t\t * record. */\n    Tk_ItemCreateProc *createProc;\n\t\t\t\t/* Procedure to create a new item of this\n\t\t\t\t * type. */\n    const Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for\n\t\t\t\t * this type. Used for returning configuration\n\t\t\t\t * info. */\n    Tk_ItemConfigureProc *configProc;\n\t\t\t\t/* Procedure to call to change configuration\n\t\t\t\t * options. */\n    Tk_ItemCoordProc *coordProc;/* Procedure to call to get and set the item's\n\t\t\t\t * coordinates. */\n    Tk_ItemDeleteProc *deleteProc;\n\t\t\t\t/* Procedure to delete existing item of this\n\t\t\t\t * type. */\n    Tk_ItemDisplayProc *displayProc;\n\t\t\t\t/* Procedure to display items of this type. */\n    int flags;\t\t/* Combination of TK_ALWAYS_REDRAW/TK_MOVABLE_POINTS */\n    Tk_ItemPointProc *pointProc;/* Computes distance from item to a given\n\t\t\t\t * point. */\n    Tk_ItemAreaProc *areaProc;\t/* Computes whether item is inside, outside,\n\t\t\t\t * or overlapping an area. */\n    Tk_ItemPostscriptProc *postscriptProc;\n\t\t\t\t/* Procedure to write a Postscript description\n\t\t\t\t * for items of this type. */\n    Tk_ItemScaleProc *scaleProc;/* Procedure to rescale items of this type. */\n    Tk_ItemTranslateProc *translateProc;\n\t\t\t\t/* Procedure to translate items of this\n\t\t\t\t * type. */\n    Tk_ItemIndexProc *indexProc;/* Procedure to determine index of indicated\n\t\t\t\t * character. NULL if item doesn't support\n\t\t\t\t * indexing. */\n    Tk_ItemCursorProc *icursorProc;\n\t\t\t\t/* Procedure to set insert cursor posn to just\n\t\t\t\t * before a given position. */\n    Tk_ItemSelectionProc *selectionProc;\n\t\t\t\t/* Procedure to return selection (in STRING\n\t\t\t\t * format) when it is in this item. */\n    Tk_ItemInsertProc *insertProc;\n\t\t\t\t/* Procedure to insert something into an\n\t\t\t\t * item. */\n    Tk_ItemDCharsProc *dCharsProc;\n\t\t\t\t/* Procedure to delete characters from an\n\t\t\t\t * item. */\n    struct Tk_ItemType *nextPtr;/* Used to link types together into a list. */\n    Tk_ItemRotateProc *rotateProc;\n\t\t\t\t/* Procedure to rotate an item's coordinates\n\t\t\t\t * about a point. */\n    int reserved2;\t\t/* Carefully compatible with */\n    char *reserved3;\t\t/* Jan Nijtmans dash patch */\n    char *reserved4;\n} Tk_ItemType;\n\n/*\n * Possible flags for 'flags' field.\n */\n\n#define TK_ALWAYS_REDRAW\t1\t/* item should be redrawn always*/\n#define TK_MOVABLE_POINTS\t2\t/* item supports point-level manipulation */\n\n#endif /* __NO_OLD_CONFIG */\n\n/*\n * The following structure provides information about the selection and the\n * insertion cursor. It is needed by only a few items, such as those that\n * display text. It is shared by the generic canvas code and the item-specific\n * code, but most of the fields should be written only by the canvas generic\n * code.\n */\n\ntypedef struct Tk_CanvasTextInfo {\n    Tk_3DBorder selBorder;\t/* Border and background for selected\n\t\t\t\t * characters. Read-only to items.*/\n    int selBorderWidth;\t\t/* Width of border around selection. Read-only\n\t\t\t\t * to items. */\n    XColor *selFgColorPtr;\t/* Foreground color for selected text.\n\t\t\t\t * Read-only to items. */\n    Tk_Item *selItemPtr;\t/* Pointer to selected item. NULL means\n\t\t\t\t * selection isn't in this canvas. Writable by\n\t\t\t\t * items. */\n    Tcl_Size selectFirst;\t\t/* Character index of first selected\n\t\t\t\t * character. Writable by items. */\n    Tcl_Size selectLast;\t\t/* Character index of last selected character.\n\t\t\t\t * Writable by items. */\n    Tk_Item *anchorItemPtr;\t/* Item corresponding to \"selectAnchor\": not\n\t\t\t\t * necessarily selItemPtr. Read-only to\n\t\t\t\t * items. */\n    Tcl_Size selectAnchor;\t\t/* Character index of fixed end of selection\n\t\t\t\t * (i.e. \"select to\" operation will use this\n\t\t\t\t * as one end of the selection). Writable by\n\t\t\t\t * items. */\n    Tk_3DBorder insertBorder;\t/* Used to draw vertical bar for insertion\n\t\t\t\t * cursor. Read-only to items. */\n    int insertWidth;\t\t/* Total width of insertion cursor. Read-only\n\t\t\t\t * to items. */\n    int insertBorderWidth;\t/* Width of 3-D border around insert cursor.\n\t\t\t\t * Read-only to items. */\n    Tk_Item *focusItemPtr;\t/* Item that currently has the input focus, or\n\t\t\t\t * NULL if no such item. Read-only to items. */\n    int gotFocus;\t\t/* Non-zero means that the canvas widget has\n\t\t\t\t * the input focus. Read-only to items.*/\n    int cursorOn;\t\t/* Non-zero means that an insertion cursor\n\t\t\t\t * should be displayed in focusItemPtr.\n\t\t\t\t * Read-only to items.*/\n    Tcl_Obj *insertBorderWidthObj;\n    Tcl_Obj *insertWidthObj;\n    Tcl_Obj *selBorderWidthObj;\n} Tk_CanvasTextInfo;\n\n/*\n * Structures used for Dashing and Outline.\n */\n\ntypedef struct Tk_Dash {\n    int number;\n    union {\n\tchar *pt;\n\tchar array[sizeof(char *)];\n    } pattern;\n} Tk_Dash;\n\ntypedef struct Tk_TSOffset {\n    int flags;\t\t\t/* Flags; see below for possible values */\n    int xoffset;\t\t/* x offset */\n    int yoffset;\t\t/* y offset */\n} Tk_TSOffset;\n\n/*\n * Bit fields in Tk_TSOffset->flags:\n */\n\n#define TK_OFFSET_INDEX\t\t1\n#define TK_OFFSET_RELATIVE\t2\n#define TK_OFFSET_LEFT\t\t4\n#define TK_OFFSET_CENTER\t8\n#define TK_OFFSET_RIGHT\t\t16\n#define TK_OFFSET_TOP\t\t32\n#define TK_OFFSET_MIDDLE\t64\n#define TK_OFFSET_BOTTOM\t128\n\ntypedef struct Tk_Outline {\n    GC gc;\t\t\t/* Graphics context. */\n    double width;\t\t/* Width of outline. */\n    double activeWidth;\t\t/* Width of outline. */\n    double disabledWidth;\t/* Width of outline. */\n    int offset;\t\t\t/* Dash offset. */\n    Tk_Dash dash;\t\t/* Dash pattern. */\n    Tk_Dash activeDash;\t\t/* Dash pattern if state is active. */\n    Tk_Dash disabledDash;\t/* Dash pattern if state is disabled. */\n    Tcl_Obj *offsetObj;\t\t/* Dash offset. */\n    void *reserved2;\t\t/* Reserved for future expansion. */\n    void *reserved3;\n    Tk_TSOffset tsoffset;\t/* Stipple offset for outline. */\n    XColor *color;\t\t/* Outline color. */\n    XColor *activeColor;\t/* Outline color if state is active. */\n    XColor *disabledColor;\t/* Outline color if state is disabled. */\n    Pixmap stipple;\t\t/* Outline Stipple pattern. */\n    Pixmap activeStipple;\t/* Outline Stipple pattern if state is\n\t\t\t\t * active. */\n    Pixmap disabledStipple;\t/* Outline Stipple pattern if state is\n\t\t\t\t * disabled. */\n} Tk_Outline;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Procedure prototypes and structures used for managing images:\n *\n *----------------------------------------------------------------------\n */\n\ntypedef struct Tk_ImageType Tk_ImageType;\ntypedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, const char *name, Tcl_Size objc,\n\tTcl_Obj *const objv[], const Tk_ImageType *typePtr, Tk_ImageModel model,\n\tvoid **clientDataPtr);\ntypedef void *(Tk_ImageGetProc) (Tk_Window tkwin, void *clientData);\ntypedef void (Tk_ImageDisplayProc) (void *clientData, Display *display,\n\tDrawable drawable, int imageX, int imageY, int width, int height,\n\tint drawableX, int drawableY);\ntypedef void (Tk_ImageFreeProc) (void *clientData, Display *display);\ntypedef void (Tk_ImageDeleteProc) (void *clientData);\ntypedef void (Tk_ImageChangedProc) (void *clientData, int x, int y,\n\tint width, int height, int imageWidth, int imageHeight);\ntypedef int (Tk_ImagePostscriptProc) (void *clientData,\n\tTcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo,\n\tint x, int y, int width, int height, int prepass);\n\n/*\n * The following structure represents a particular type of image (bitmap, xpm\n * image, etc.). It provides information common to all images of that type,\n * such as the type name and a collection of procedures in the image manager\n * that respond to various events. Each image manager is represented by one of\n * these structures.\n */\n\nstruct Tk_ImageType {\n    const char *name;\t\t/* Name of image type. */\n    Tk_ImageCreateProc *createProc;\n\t\t\t\t/* Procedure to call to create a new image of\n\t\t\t\t * this type. */\n    Tk_ImageGetProc *getProc;\t/* Procedure to call the first time\n\t\t\t\t * Tk_GetImage is called in a new way (new\n\t\t\t\t * visual or screen). */\n    Tk_ImageDisplayProc *displayProc;\n\t\t\t\t/* Call to draw image, in response to\n\t\t\t\t * Tk_RedrawImage calls. */\n    Tk_ImageFreeProc *freeProc;\t/* Procedure to call whenever Tk_FreeImage is\n\t\t\t\t * called to release an instance of an\n\t\t\t\t * image. */\n    Tk_ImageDeleteProc *deleteProc;\n\t\t\t\t/* Procedure to call to delete image. It will\n\t\t\t\t * not be called until after freeProc has been\n\t\t\t\t * called for each instance of the image. */\n    Tk_ImagePostscriptProc *postscriptProc;\n\t\t\t\t/* Procedure to call to produce postscript\n\t\t\t\t * output for the image. */\n    struct Tk_ImageType *nextPtr;\n\t\t\t\t/* Next in list of all image types currently\n\t\t\t\t * known. Filled in by Tk, not by image\n\t\t\t\t * manager. */\n    char *reserved;\t\t/* reserved for future expansion */\n};\n\n/*\n *----------------------------------------------------------------------\n *\n * Additional definitions used to manage images of type \"photo\".\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * The following type is used to identify a particular photo image to be\n * manipulated:\n */\n\ntypedef void *Tk_PhotoHandle;\n\n/*\n * The following structure describes a block of pixels in memory:\n */\n\ntypedef struct Tk_PhotoImageBlock {\n    unsigned char *pixelPtr;\t/* Pointer to the first pixel. */\n    int width;\t\t\t/* Width of block, in pixels. */\n    int height;\t\t\t/* Height of block, in pixels. */\n    int pitch;\t\t\t/* Address difference between corresponding\n\t\t\t\t * pixels in successive lines. */\n    int pixelSize;\t\t/* Address difference between successive\n\t\t\t\t * pixels in the same line. */\n    int offset[4];\t\t/* Address differences between the red, green,\n\t\t\t\t * blue and alpha components of the pixel and\n\t\t\t\t * the pixel as a whole. */\n} Tk_PhotoImageBlock;\n\n/*\n * The following values control how blocks are combined into photo images when\n * the alpha component of a pixel is not 255, a.k.a. the compositing rule.\n */\n\n#define TK_PHOTO_COMPOSITE_OVERLAY\t0\n#define TK_PHOTO_COMPOSITE_SET\t\t1\n\n/*\n * Procedure prototypes and structures used in reading and writing photo\n * images:\n */\n\ntypedef struct Tk_PhotoImageFormat Tk_PhotoImageFormat;\ntypedef int (Tk_ImageFileMatchProc) (Tcl_Channel chan, const char *fileName,\n\tTcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp);\ntypedef int (Tk_ImageStringMatchProc) (Tcl_Obj *dataObj, Tcl_Obj *format,\n\tint *widthPtr, int *heightPtr, Tcl_Interp *interp);\ntypedef int (Tk_ImageFileReadProc) (Tcl_Interp *interp, Tcl_Channel chan,\n\tconst char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle,\n\tint destX, int destY, int width, int height, int srcX, int srcY);\ntypedef int (Tk_ImageStringReadProc) (Tcl_Interp *interp, Tcl_Obj *dataObj,\n\tTcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY,\n\tint width, int height, int srcX, int srcY);\ntypedef int (Tk_ImageFileWriteProc) (Tcl_Interp *interp, const char *fileName,\n\tTcl_Obj *format, Tk_PhotoImageBlock *blockPtr);\ntypedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp, Tcl_Obj *format,\n\tTk_PhotoImageBlock *blockPtr);\n\n/*\n * The following alternate definitions are used with the Tk9.0 file format\n * supporting a metadata dict, internal dstring and close file flag\n */\n\ntypedef struct Tk_PhotoImageFormatVersion3 Tk_PhotoImageFormatVersion3;\ntypedef int (Tk_ImageFileMatchProcVersion3) (Tcl_Interp *interp,\n\tTcl_Channel chan, const char *fileName, Tcl_Obj *format,\n\tTcl_Obj *metadataIn, int *widthPtr, int *heightPtr,\n\tTcl_Obj *metadataOut);\ntypedef int (Tk_ImageStringMatchProcVersion3) (Tcl_Interp *interp,\n\tTcl_Obj *dataObj, Tcl_Obj *format, Tcl_Obj *metadataIn, int *widthPtr,\n\tint *heightPtr, Tcl_Obj *metadataOut);\ntypedef int (Tk_ImageFileReadProcVersion3) (Tcl_Interp *interp,\n\tTcl_Channel chan,\n\tconst char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn,\n\tTk_PhotoHandle imageHandle,\n\tint destX, int destY, int width, int height, int srcX, int srcY,\n\tTcl_Obj *metadataOut);\ntypedef int (Tk_ImageStringReadProcVersion3) (Tcl_Interp *interp,\n\tTcl_Obj *dataObj, Tcl_Obj *format, Tcl_Obj *metadataIn,\n\tTk_PhotoHandle imageHandle, int destX, int destY, int width, int height,\n\tint srcX, int srcY, Tcl_Obj *metadataOut);\ntypedef int (Tk_ImageFileWriteProcVersion3) (Tcl_Interp *interp,\n\tconst char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn,\n\tTk_PhotoImageBlock *blockPtr);\ntypedef int (Tk_ImageStringWriteProcVersion3) (Tcl_Interp *interp,\n\tTcl_Obj *format, Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr);\n\n\n/*\n * The following structure represents a particular file format for storing\n * images (e.g., PPM, GIF, JPEG, etc.). It provides information to allow image\n * files of that format to be recognized and read into a photo image.\n */\n\nstruct Tk_PhotoImageFormat {\n    const char *name;\t\t/* Name of image file format */\n    Tk_ImageFileMatchProc *fileMatchProc;\n\t\t\t\t/* Procedure to call to determine whether an\n\t\t\t\t * image file matches this format. */\n    Tk_ImageStringMatchProc *stringMatchProc;\n\t\t\t\t/* Procedure to call to determine whether the\n\t\t\t\t * data in a string matches this format. */\n    Tk_ImageFileReadProc *fileReadProc;\n\t\t\t\t/* Procedure to call to read data from an\n\t\t\t\t * image file into a photo image. */\n    Tk_ImageStringReadProc *stringReadProc;\n\t\t\t\t/* Procedure to call to read data from a\n\t\t\t\t * string into a photo image. */\n    Tk_ImageFileWriteProc *fileWriteProc;\n\t\t\t\t/* Procedure to call to write data from a\n\t\t\t\t * photo image to a file. */\n    Tk_ImageStringWriteProc *stringWriteProc;\n\t\t\t\t/* Procedure to call to obtain a string\n\t\t\t\t * representation of the data in a photo\n\t\t\t\t * image.*/\n    struct Tk_PhotoImageFormat *nextPtr;\n\t\t\t\t/* Next in list of all photo image formats\n\t\t\t\t * currently known. Filled in by Tk, not by\n\t\t\t\t * image format handler. */\n};\n\n/*\n * The following structure is the same plus added support for the metadata\n * structure.\n */\n\nstruct Tk_PhotoImageFormatVersion3 {\n    const char *name;\t\t/* Name of image file format */\n    Tk_ImageFileMatchProcVersion3 *fileMatchProc;\n\t\t\t\t/* Procedure to call to determine whether an\n\t\t\t\t * image file matches this format. */\n    Tk_ImageStringMatchProcVersion3 *stringMatchProc;\n\t\t\t\t/* Procedure to call to determine whether the\n\t\t\t\t * data in a string matches this format. */\n    Tk_ImageFileReadProcVersion3 *fileReadProc;\n\t\t\t\t/* Procedure to call to read data from an\n\t\t\t\t * image file into a photo image. */\n    Tk_ImageStringReadProcVersion3 *stringReadProc;\n\t\t\t\t/* Procedure to call to read data from a\n\t\t\t\t * string into a photo image. */\n    Tk_ImageFileWriteProcVersion3 *fileWriteProc;\n\t\t\t\t/* Procedure to call to write data from a\n\t\t\t\t * photo image to a file. */\n    Tk_ImageStringWriteProcVersion3 *stringWriteProc;\n\t\t\t\t/* Procedure to call to obtain a string\n\t\t\t\t * representation of the data in a photo\n\t\t\t\t * image.*/\n    struct Tk_PhotoImageFormatVersion3 *nextPtr;\n\t\t\t\t/* Next in list of all photo image formats\n\t\t\t\t * currently known. Filled in by Tk, not by\n\t\t\t\t * image format handler. */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Procedure prototypes and structures used for managing styles:\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * Style support version tag.\n */\n\n#define TK_STYLE_VERSION_1      0x1\n#define TK_STYLE_VERSION        TK_STYLE_VERSION_1\n\n/*\n * The following structures and prototypes are used as static templates to\n * declare widget elements.\n */\n\ntypedef void (Tk_GetElementSizeProc) (void *clientData, char *recordPtr,\n\tconst Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int width,\n\tint height, int inner, int *widthPtr, int *heightPtr);\ntypedef void (Tk_GetElementBoxProc) (void *clientData, char *recordPtr,\n\tconst Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int x, int y,\n\tint width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr,\n\tint *heightPtr);\ntypedef int (Tk_GetElementBorderWidthProc) (void *clientData,\n\tchar *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin);\ntypedef void (Tk_DrawElementProc) (void *clientData, char *recordPtr,\n\tconst Tk_OptionSpec **optionsPtr, Tk_Window tkwin, Drawable d, int x,\n\tint y, int width, int height, int state);\n\ntypedef struct Tk_ElementOptionSpec {\n    char *name;\t\t\t/* Name of the required option. */\n    Tk_OptionType type;\t\t/* Accepted option type. TK_OPTION_END means\n\t\t\t\t * any. */\n} Tk_ElementOptionSpec;\n\ntypedef struct Tk_ElementSpec {\n    int version;\t\t/* Version of the style support. */\n    char *name;\t\t\t/* Name of element. */\n    Tk_ElementOptionSpec *options;\n\t\t\t\t/* List of required options. Last one's name\n\t\t\t\t * must be NULL. */\n    Tk_GetElementSizeProc *getSize;\n\t\t\t\t/* Compute the external (resp. internal) size\n\t\t\t\t * of the element from its desired internal\n\t\t\t\t * (resp. external) size. */\n    Tk_GetElementBoxProc *getBox;\n\t\t\t\t/* Compute the inscribed or bounding boxes\n\t\t\t\t * within a given area. */\n    Tk_GetElementBorderWidthProc *getBorderWidth;\n\t\t\t\t/* Return the element's internal border width.\n\t\t\t\t * Mostly useful for widgets. */\n    Tk_DrawElementProc *draw;\t/* Draw the element in the given bounding\n\t\t\t\t * box. */\n} Tk_ElementSpec;\n\n/*\n * Element state flags. Can be OR'ed.\n */\n\n#define TK_ELEMENT_STATE_ACTIVE         1<<0\n#define TK_ELEMENT_STATE_DISABLED       1<<1\n#define TK_ELEMENT_STATE_FOCUS          1<<2\n#define TK_ELEMENT_STATE_PRESSED        1<<3\n\f\n/*\n *----------------------------------------------------------------------\n *\n * The definitions below provide backward compatibility for functions and\n * types that used to be in Tk but have moved to Tcl.\n *\n *----------------------------------------------------------------------\n */\n\n/* Removed Tk_Main, use macro instead */\n#if defined(_WIN32) || defined(__CYGWIN__)\n#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \\\n\t(Tcl_FindExecutable(0), (Tcl_CreateInterp)()))\n#else\n#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \\\n\t(Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)()))\n#endif\nconst char *\t\tTk_InitStubs(Tcl_Interp *interp, const char *version,\n\t\t\t\tint exact);\nEXTERN const char *\tTk_PkgInitStubsCheck(Tcl_Interp *interp,\n\t\t\t\tconst char *version, int exact);\n\n#ifndef USE_TK_STUBS\n#define Tk_InitStubs(interp, version, exact) \\\n    Tk_PkgInitStubsCheck(interp, version, exact)\n#endif /* USE_TK_STUBS */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Additional procedure types defined by Tk.\n *\n *----------------------------------------------------------------------\n */\n\ntypedef int (Tk_ErrorProc) (void *clientData, XErrorEvent *errEventPtr);\ntypedef void (Tk_EventProc) (void *clientData, XEvent *eventPtr);\ntypedef int (Tk_GenericProc) (void *clientData, XEvent *eventPtr);\ntypedef int (Tk_ClientMessageProc) (Tk_Window tkwin, XEvent *eventPtr);\ntypedef int (Tk_GetSelProc) (void *clientData, Tcl_Interp *interp,\n\tconst char *portion);\ntypedef void (Tk_LostSelProc) (void *clientData);\ntypedef Tk_RestrictAction (Tk_RestrictProc) (void *clientData,\n\tXEvent *eventPtr);\ntypedef Tcl_Size (Tk_SelectionProc) (void *clientData, Tcl_Size offset,\n\tchar *buffer, Tcl_Size maxBytes);\n\n/*\n *----------------------------------------------------------------------\n *\n * Platform independent exported procedures and variables.\n *\n *----------------------------------------------------------------------\n */\n\n#include \"tkDecls.h\"  /* IWYU pragma: export */\n\f\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#endif /* RC_INVOKED */\n\n/*\n * end block for C++\n */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _TK */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tk3d.c",
    "content": "/*\n * tk3d.c --\n *\n *\tThis module provides procedures to draw borders in the\n *\tthree-dimensional Motif style.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tk3d.h\"\n\n/*\n * The following table defines the string values for reliefs, which are used\n * by Tk_GetReliefFromObj.\n */\n\nconst char *const tkReliefStrings[] = {\n    \"flat\", \"groove\", \"raised\", \"ridge\", \"solid\", \"sunken\", NULL\n};\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tBorderInit(TkDisplay *dispPtr);\nstatic void\t\tDupBorderObjProc(Tcl_Obj *srcObjPtr,\n\t\t\t    Tcl_Obj *dupObjPtr);\nstatic void\t\tFreeBorderObj(Tcl_Obj *objPtr);\nstatic void\t\tFreeBorderObjProc(Tcl_Obj *objPtr);\nstatic int\t\tIntersect(XPoint *a1Ptr, XPoint *a2Ptr,\n\t\t\t    XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr);\nstatic void\t\tInitBorderObj(Tcl_Obj *objPtr);\nstatic void\t\tShiftLine(XPoint *p1Ptr, XPoint *p2Ptr,\n\t\t\t    int distance, XPoint *p3Ptr);\n\n/*\n * The following structure defines the implementation of the \"border\" Tcl\n * object, used for drawing. The border object remembers the hash table entry\n * associated with a border. The actual allocation and deallocation of the\n * border should be done by the configuration package when the border option\n * is set.\n */\n\nconst Tcl_ObjType tkBorderObjType = {\n    \"border\",\t\t\t/* name */\n    FreeBorderObjProc,\t\t/* freeIntRepProc */\n    DupBorderObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Alloc3DBorderFromObj --\n *\n *\tGiven a Tcl_Obj *, map the value to a corresponding Tk_3DBorder\n *\tstructure based on the tkwin given.\n *\n * Results:\n *\tThe return value is a token for a data structure describing a 3-D\n *\tborder. This token may be passed to functions such as\n *\tTk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the\n *\tborder from being created then NULL is returned and an error message\n *\twill be left in the interp's result.\n *\n * Side effects:\n *\tThe border is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tFreeBorderObj so that the database is cleaned up when borders aren't\n *\tin use anymore.\n *\n *----------------------------------------------------------------------\n */\n\nTk_3DBorder\nTk_Alloc3DBorderFromObj(\n    Tcl_Interp *interp,\t\t/* Interp for error results. */\n    Tk_Window tkwin,\t\t/* Need the screen the border is used on.*/\n    Tcl_Obj *objPtr)\t\t/* Object giving name of color for window\n\t\t\t\t * background. */\n{\n    TkBorder *borderPtr;\n\n    if (objPtr->typePtr != &tkBorderObjType) {\n\tInitBorderObj(objPtr);\n    }\n    borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    /*\n     * If the object currently points to a TkBorder, see if it's the one we\n     * want. If so, increment its reference count and return.\n     */\n\n    if (borderPtr != NULL) {\n\tif (borderPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a border that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\n\t    FreeBorderObj(objPtr);\n\t    borderPtr = NULL;\n\t} else if ((Tk_Screen(tkwin) == borderPtr->screen)\n\t\t&& (Tk_Colormap(tkwin) == borderPtr->colormap)) {\n\t    borderPtr->resourceRefCount++;\n\t    return (Tk_3DBorder) borderPtr;\n\t}\n    }\n\n    /*\n     * The object didn't point to the border that we wanted. Search the list\n     * of borders with the same name to see if one of the others is the right\n     * one.\n     *\n     * If the cached value is NULL, either the object type was not a color\n     * going in, or the object is a color type but had previously been freed.\n     *\n     * If the value is not NULL, the internal rep is the value of the color\n     * the last time this object was accessed. Check the screen and colormap\n     * of the last access, and if they match, we are done.\n     */\n\n    if (borderPtr != NULL) {\n\tTkBorder *firstBorderPtr = (TkBorder *)Tcl_GetHashValue(borderPtr->hashPtr);\n\n\tFreeBorderObj(objPtr);\n\tfor (borderPtr = firstBorderPtr ; borderPtr != NULL;\n\t\tborderPtr = borderPtr->nextPtr) {\n\t    if ((Tk_Screen(tkwin) == borderPtr->screen)\n\t\t    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {\n\t\tborderPtr->resourceRefCount++;\n\t\tborderPtr->objRefCount++;\n\t\tobjPtr->internalRep.twoPtrValue.ptr1 = borderPtr;\n\t\treturn (Tk_3DBorder) borderPtr;\n\t    }\n\t}\n    }\n\n    /*\n     * Still no luck. Call Tk_Get3DBorder to allocate a new border.\n     */\n\n    borderPtr = (TkBorder *) Tk_Get3DBorder(interp, tkwin,\n\t    Tcl_GetString(objPtr));\n    objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;\n    if (borderPtr != NULL) {\n\tborderPtr->objRefCount++;\n    }\n    return (Tk_3DBorder) borderPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_Get3DBorder --\n *\n *\tCreate a data structure for displaying a 3-D border.\n *\n * Results:\n *\tThe return value is a token for a data structure describing a 3-D\n *\tborder. This token may be passed to functions such as\n *\tTk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the\n *\tborder from being created then NULL is returned and an error message\n *\twill be left in the interp's result.\n *\n * Side effects:\n *\tData structures, graphics contexts, etc. are allocated. It is the\n *\tcaller's responsibility to eventually call Tk_Free3DBorder to release\n *\tthe resources.\n *\n *--------------------------------------------------------------\n */\n\nTk_3DBorder\nTk_Get3DBorder(\n    Tcl_Interp *interp,\t\t/* Place to store an error message. */\n    Tk_Window tkwin,\t\t/* Token for window in which border will be\n\t\t\t\t * drawn. */\n    const char *colorName)\t/* String giving name of color for window\n\t\t\t\t * background. */\n{\n    Tcl_HashEntry *hashPtr;\n    TkBorder *borderPtr, *existingBorderPtr;\n    int isNew;\n    XGCValues gcValues;\n    XColor *bgColorPtr;\n    TkDisplay *dispPtr;\n\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (!dispPtr->borderInit) {\n\tBorderInit(dispPtr);\n    }\n\n    hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &isNew);\n    if (!isNew) {\n\texistingBorderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr);\n\tfor (borderPtr = existingBorderPtr; borderPtr != NULL;\n\t\tborderPtr = borderPtr->nextPtr) {\n\t    if ((Tk_Screen(tkwin) == borderPtr->screen)\n\t\t    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {\n\t\tborderPtr->resourceRefCount++;\n\t\treturn (Tk_3DBorder) borderPtr;\n\t    }\n\t}\n    } else {\n\texistingBorderPtr = NULL;\n    }\n\n    /*\n     * No satisfactory border exists yet. Initialize a new one.\n     */\n\n    bgColorPtr = Tk_GetColor(interp, tkwin, colorName);\n    if (bgColorPtr == NULL) {\n\tif (isNew) {\n\t    Tcl_DeleteHashEntry(hashPtr);\n\t}\n\treturn NULL;\n    }\n\n    borderPtr = TkpGetBorder();\n    borderPtr->screen = Tk_Screen(tkwin);\n    borderPtr->visual = Tk_Visual(tkwin);\n    borderPtr->depth = Tk_Depth(tkwin);\n    borderPtr->colormap = Tk_Colormap(tkwin);\n    borderPtr->resourceRefCount = 1;\n    borderPtr->objRefCount = 0;\n    borderPtr->bgColorPtr = bgColorPtr;\n    borderPtr->darkColorPtr = NULL;\n    borderPtr->lightColorPtr = NULL;\n    borderPtr->shadow = None;\n    borderPtr->bgGC = NULL;\n    borderPtr->darkGC = NULL;\n    borderPtr->lightGC = NULL;\n    borderPtr->hashPtr = hashPtr;\n    borderPtr->nextPtr = existingBorderPtr;\n    Tcl_SetHashValue(hashPtr, borderPtr);\n\n    /*\n     * Create the information for displaying the background color, but delay\n     * the allocation of shadows until they are actually needed for drawing.\n     */\n\n    gcValues.foreground = borderPtr->bgColorPtr->pixel;\n    borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    return (Tk_3DBorder) borderPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_Draw3DRectangle --\n *\n *\tDraw a 3-D border at a given place in a given window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA 3-D border will be drawn in the indicated drawable. The outside\n *\tedges of the border will be determined by x, y, width, and height. The\n *\tinside edges of the border will be determined by the borderWidth\n *\targument.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_Draw3DRectangle(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Outside area of region in which border will\n\t\t\t\t * be drawn. */\n    int borderWidth,\t\t/* Desired width for border, in pixels. */\n    int relief)\t\t\t/* Type of relief: TK_RELIEF_RAISED,\n\t\t\t\t * TK_RELIEF_SUNKEN, TK_RELIEF_GROOVE, etc. */\n{\n    if (width < 2*borderWidth) {\n\tborderWidth = width/2;\n    }\n    if (height < 2*borderWidth) {\n\tborderWidth = height/2;\n    }\n    Tk_3DVerticalBevel(tkwin, drawable, border, x, y, borderWidth, height,\n\t    1, relief);\n    Tk_3DVerticalBevel(tkwin, drawable, border, x+width-borderWidth, y,\n\t    borderWidth, height, 0, relief);\n    Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, borderWidth,\n\t    1, 1, 1, relief);\n    Tk_3DHorizontalBevel(tkwin, drawable, border, x, y+height-borderWidth,\n\t    width, borderWidth, 0, 0, 0, relief);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOf3DBorder --\n *\n *\tGiven a border, return a textual string identifying the border's\n *\tcolor.\n *\n * Results:\n *\tThe return value is the string that was used to create the border.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOf3DBorder(\n    Tk_3DBorder border)\t\t/* Token for border. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n\n    return borderPtr->hashPtr->key.string;\n}\n\f\n/*\n *--------------------------------------------------------------------\n *\n * Tk_3DBorderColor --\n *\n *\tGiven a 3D border, return the X color used for the \"flat\" surfaces.\n *\n * Results:\n *\tReturns the color used drawing flat surfaces with the border.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------------\n */\nXColor *\nTk_3DBorderColor(\n    Tk_3DBorder border)\t\t/* Border whose color is wanted. */\n{\n    return ((TkBorder *) border)->bgColorPtr;\n}\n\f\n/*\n *--------------------------------------------------------------------\n *\n * Tk_3DBorderGC --\n *\n *\tGiven a 3D border, returns one of the graphics contexts used to draw\n *\tthe border.\n *\n * Results:\n *\tReturns the graphics context given by the \"which\" argument.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------------\n */\nGC\nTk_3DBorderGC(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Tk_3DBorder border,\t\t/* Border whose GC is wanted. */\n    int which)\t\t\t/* Selects one of the border's 3 GC's:\n\t\t\t\t * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or\n\t\t\t\t * TK_3D_DARK_GC. */\n{\n    TkBorder * borderPtr = (TkBorder *) border;\n\n    if ((borderPtr->lightGC == NULL) && (which != TK_3D_FLAT_GC)) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n    if (which == TK_3D_FLAT_GC) {\n\treturn borderPtr->bgGC;\n    } else if (which == TK_3D_LIGHT_GC) {\n\treturn borderPtr->lightGC;\n    } else if (which == TK_3D_DARK_GC){\n\treturn borderPtr->darkGC;\n    }\n    Tcl_Panic(\"bogus \\\"which\\\" value in Tk_3DBorderGC\");\n\n    /*\n     * The code below will never be executed, but it's needed to keep\n     * compilers happy.\n     */\n\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_Free3DBorder --\n *\n *\tThis function is called when a 3D border is no longer needed. It frees\n *\tthe resources associated with the border. After this call, the caller\n *\tshould never again use the \"border\" token.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources are freed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_Free3DBorder(\n    Tk_3DBorder border)\t\t/* Token for border to be released. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    Display *display = DisplayOfScreen(borderPtr->screen);\n    TkBorder *prevPtr;\n\n    if (borderPtr->resourceRefCount-- > 1) {\n\treturn;\n    }\n\n    prevPtr = (TkBorder *)Tcl_GetHashValue(borderPtr->hashPtr);\n    TkpFreeBorder(borderPtr);\n    Tk_FreeColor(borderPtr->bgColorPtr);\n    if (borderPtr->darkColorPtr != NULL) {\n\tTk_FreeColor(borderPtr->darkColorPtr);\n    }\n    if (borderPtr->lightColorPtr != NULL) {\n\tTk_FreeColor(borderPtr->lightColorPtr);\n    }\n    if (borderPtr->shadow != None) {\n\tTk_FreeBitmap(display, borderPtr->shadow);\n    }\n    if (borderPtr->bgGC != NULL) {\n\tTk_FreeGC(display, borderPtr->bgGC);\n    }\n    if (borderPtr->darkGC != NULL) {\n\tTk_FreeGC(display, borderPtr->darkGC);\n    }\n    if (borderPtr->lightGC != NULL) {\n\tTk_FreeGC(display, borderPtr->lightGC);\n    }\n    if (prevPtr == borderPtr) {\n\tif (borderPtr->nextPtr == NULL) {\n\t    Tcl_DeleteHashEntry(borderPtr->hashPtr);\n\t} else {\n\t    Tcl_SetHashValue(borderPtr->hashPtr, borderPtr->nextPtr);\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != borderPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t}\n\tprevPtr->nextPtr = borderPtr->nextPtr;\n    }\n    if (borderPtr->objRefCount == 0) {\n\tTcl_Free(borderPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Free3DBorderFromObj --\n *\n *\tThis function is called to release a border allocated by\n *\tTk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *; it only\n *\tgets rid of the hash table entry for this border and clears the cached\n *\tvalue that is normally stored in the object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with the border represented by objPtr\n *\tis decremented, and the border's resources are released to X if there\n *\tare no remaining uses for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_Free3DBorderFromObj(\n    Tk_Window tkwin,\t\t/* The window this border lives in. Needed for\n\t\t\t\t * the screen and colormap values. */\n    Tcl_Obj *objPtr)\t\t/* The Tcl_Obj * to be freed. */\n{\n    Tk_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr));\n    FreeBorderObj(objPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeBorderObjProc, FreeBorderObj --\n *\n *\tThis proc is called to release an object reference to a border. Called\n *\twhen the object's internal rep is released or when the cached\n *\tborderPtr needs to be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object reference count is decremented. When both it and the hash\n *\tref count go to zero, the border's resources are released.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeBorderObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    FreeBorderObj(objPtr);\n    objPtr->typePtr = NULL;\n}\n\nstatic void\nFreeBorderObj(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    TkBorder *borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    if (borderPtr != NULL) {\n\tborderPtr->objRefCount--;\n\tif ((borderPtr->objRefCount == 0)\n\t\t&& (borderPtr->resourceRefCount == 0)) {\n\t    Tcl_Free(borderPtr);\n\t}\n\tobjPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupBorderObjProc --\n *\n *\tWhen a cached border object is duplicated, this is called to update\n *\tthe internal reps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe border's objRefCount is incremented and the internal rep of the\n *\tcopy is set to point to it.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupBorderObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    TkBorder *borderPtr = (TkBorder *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 = borderPtr;\n\n    if (borderPtr != NULL) {\n\tborderPtr->objRefCount++;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetBackgroundFromBorder --\n *\n *\tChange the background of a window to one appropriate for a given 3-D\n *\tborder.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTkwin's background gets modified.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetBackgroundFromBorder(\n    Tk_Window tkwin,\t\t/* Window whose background is to be set. */\n    Tk_3DBorder border)\t\t/* Token for border. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n\n    Tk_SetWindowBackground(tkwin, borderPtr->bgColorPtr->pixel);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetReliefFromObj --\n *\n *\tReturn an integer value based on the value of the objPtr.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tThe object gets converted by Tcl_GetIndexFromObj.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetReliefFromObj(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tcl_Obj *objPtr,\t\t/* The object we are trying to get the value\n\t\t\t\t * from. */\n    int *resultPtr)\t\t/* Where to place the answer. */\n{\n    return Tcl_GetIndexFromObjStruct(interp, objPtr, tkReliefStrings,\n\t    sizeof(char *), \"relief\", 0, resultPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetRelief --\n *\n *\tParse a relief description and return the corresponding relief value,\n *\tor an error.\n *\n * Results:\n *\tA standard Tcl return value. If all goes well then *reliefPtr is\n *\tfilled in with one of the values TK_RELIEF_*\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetRelief(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    const char *name,\t\t/* Name of a relief type. */\n    int *reliefPtr)\t\t/* Where to store converted relief. */\n{\n    char c;\n    size_t length;\n    int relief;\n\n    c = name[0];\n    length = strlen(name);\n    if ((c == 'f') && (strncmp(name, \"flat\", length) == 0)) {\n\trelief = TK_RELIEF_FLAT;\n    } else if ((c == 'g') && (strncmp(name, \"groove\", length) == 0)) {\n\trelief = TK_RELIEF_GROOVE;\n    } else if ((c == 'r') && (strncmp(name, \"raised\", length) == 0)\n\t    && (length >= 2)) {\n\trelief = TK_RELIEF_RAISED;\n    } else if ((c == 'r') && (strncmp(name, \"ridge\", length) == 0)\n\t    && (length >= 2)) {\n\trelief = TK_RELIEF_RIDGE;\n    } else if ((c == 's') && (strncmp(name, \"solid\", length) == 0)\n\t    && (length >= 2)) {\n\trelief = TK_RELIEF_SOLID;\n    } else if ((c == 's') && (strncmp(name, \"sunken\", length) == 0)\n\t    && (length >= 2)) {\n\trelief = TK_RELIEF_SUNKEN;\n    } else {\n\tif (interp) {\n\t    int ambigeous = (c == 'r' || c == 's') && (name[1] == '\\0');\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_ObjPrintf(\"%s relief \\\"%.50s\\\": must be %s\",\n\t\t    ambigeous ? \"ambigeous\" : \"bad\", name, \"flat, groove, raised, ridge, solid, or sunken\"));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"RELIEF\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    if (reliefPtr) {\n\t*reliefPtr = relief;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfRelief --\n *\n *\tGiven a relief value, produce a string describing that relief value.\n *\n * Results:\n *\tThe return value is a static string that is equivalent to relief.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfRelief(\n    int relief)\t\t/* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED, or\n\t\t\t * TK_RELIEF_SUNKEN. */\n{\n    if (relief == TK_RELIEF_FLAT) {\n\treturn \"flat\";\n    } else if (relief == TK_RELIEF_SUNKEN) {\n\treturn \"sunken\";\n    } else if (relief == TK_RELIEF_RAISED) {\n\treturn \"raised\";\n    } else if (relief == TK_RELIEF_GROOVE) {\n\treturn \"groove\";\n    } else if (relief == TK_RELIEF_RIDGE) {\n\treturn \"ridge\";\n    } else if (relief == TK_RELIEF_SOLID) {\n\treturn \"solid\";\n    } else if (relief == TK_RELIEF_NULL) {\n\treturn \"\";\n    } else {\n\treturn \"unknown relief\";\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_Draw3DPolygon --\n *\n *\tDraw a border with 3-D appearance around the edge of a given polygon.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation is drawn in \"drawable\" in the form of a 3-D border\n *\tborderWidth units width wide on the left of the trajectory given by\n *\tpointPtr and numPoints (or -borderWidth units wide on the right side,\n *\tif borderWidth is negative).\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_Draw3DPolygon(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    XPoint *pointPtr,\t\t/* Array of points describing polygon. All\n\t\t\t\t * points must be absolute\n\t\t\t\t * (CoordModeOrigin). */\n    Tcl_Size numPoints,\t\t/* Number of points at *pointPtr. */\n    int borderWidth,\t\t/* Width of border, measured in pixels to the\n\t\t\t\t * left of the polygon's trajectory. May be\n\t\t\t\t * negative. */\n    int leftRelief)\t\t/* TK_RELIEF_RAISED or TK_RELIEF_SUNKEN:\n\t\t\t\t * indicates how stuff to left of trajectory\n\t\t\t\t * looks relative to stuff on right. */\n{\n    XPoint poly[4], b1, b2, newB1, newB2;\n    XPoint perp, c, shift1, shift2;\t/* Used for handling parallel lines. */\n    XPoint *p1Ptr, *p2Ptr;\n    TkBorder *borderPtr = (TkBorder *) border;\n    GC gc;\n    Tcl_Size i;\n    int lightOnLeft, dx, dy, parallel, pointsSeen;\n    Display *display = Tk_Display(tkwin);\n\n    if (borderPtr->lightGC == NULL) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n\n    /*\n     * Handle grooves and ridges with recursive calls.\n     */\n\n    if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {\n\tint halfWidth = borderWidth/2;\n\n\tTk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,\n\t\thalfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED\n\t\t: TK_RELIEF_SUNKEN);\n\tTk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,\n\t\t-halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN\n\t\t: TK_RELIEF_RAISED);\n\treturn;\n    }\n\n    /*\n     * If the polygon is already closed, drop the last point from it (we'll\n     * close it automatically).\n     */\n\n    p1Ptr = &pointPtr[numPoints-1];\n    p2Ptr = &pointPtr[0];\n    if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) {\n\tnumPoints--;\n    }\n\n    /*\n     * The loop below is executed once for each vertex in the polgon. At the\n     * beginning of each iteration things look like this:\n     *\n     *          poly[1]       /\n     *             *        /\n     *             |      /\n     *             b1   * poly[0] (pointPtr[i-1])\n     *             |    |\n     *             |    |\n     *             |    |\n     *             |    |\n     *             |    |\n     *             |    | *p1Ptr            *p2Ptr\n     *             b2   *--------------------*\n     *             |\n     *             |\n     *             x-------------------------\n     *\n     * The job of this iteration is to do the following:\n     * (a) Compute x (the border corner corresponding to pointPtr[i]) and put\n     *\t   it in poly[2]. As part of this, compute a new b1 and b2 value for\n     *\t   the next side of the polygon.\n     * (b) Put pointPtr[i] into poly[3].\n     * (c) Draw the polygon given by poly[0..3].\n     * (d) Advance poly[0], poly[1], b1, and b2 for the next side of the\n     *     polygon.\n     */\n\n    /*\n     * The above situation doesn't first come into existence until two points\n     * have been processed; the first two points are used to \"prime the pump\",\n     * so some parts of the processing are ommitted for these points. The\n     * variable \"pointsSeen\" keeps track of the priming process; it has to be\n     * separate from i in order to be able to ignore duplicate points in the\n     * polygon.\n     */\n\n    pointsSeen = 0;\n    for (i = 0, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1;\n\t    i < numPoints + 2; i++, p1Ptr = p2Ptr, p2Ptr++) {\n\tif ((i == 1) || (i == numPoints + 1)) {\n\t    p2Ptr = pointPtr;\n\t}\n\tif ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) {\n\t    /*\n\t     * Ignore duplicate points (they'd cause core dumps in ShiftLine\n\t     * calls below).\n\t     */\n\n\t    continue;\n\t}\n\tShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1);\n\tnewB2.x = newB1.x + (p2Ptr->x - p1Ptr->x);\n\tnewB2.y = newB1.y + (p2Ptr->y - p1Ptr->y);\n\tpoly[3] = *p1Ptr;\n\tparallel = 0;\n\tif (pointsSeen >= 1) {\n\t    parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);\n\n\t    /*\n\t     * If two consecutive segments of the polygon are parallel, then\n\t     * things get more complex. Consider the following diagram:\n\t     *\n\t     * poly[1]\n\t     *    *----b1-----------b2------a\n\t     *                                \\\n\t     *                                  \\\n\t     *         *---------*----------*    b\n\t     *        poly[0]  *p2Ptr   *p1Ptr  /\n\t     *                                /\n\t     *              --*--------*----c\n\t     *              newB1    newB2\n\t     *\n\t     * Instead of using x and *p1Ptr for poly[2] and poly[3], as in\n\t     * the original diagram, use a and b as above. Then instead of\n\t     * using x and *p1Ptr for the new poly[0] and poly[1], use b and c\n\t     * as above.\n\t     *\n\t     * Do the computation in three stages:\n\t     * 1. Compute a point \"perp\" such that the line p1Ptr-perp is\n\t     *    perpendicular to p1Ptr-p2Ptr.\n\t     * 2. Compute the points a and c by intersecting the lines b1-b2\n\t     *    and newB1-newB2 with p1Ptr-perp.\n\t     * 3. Compute b by shifting p1Ptr-perp to the right and\n\t     *    intersecting it with p1Ptr-p2Ptr.\n\t     */\n\n\t    if (parallel) {\n\t\tperp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y);\n\t\tperp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x);\n\t\t(void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]);\n\t\t(void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c);\n\t\tShiftLine(p1Ptr, &perp, borderWidth, &shift1);\n\t\tshift2.x = shift1.x + (perp.x - p1Ptr->x);\n\t\tshift2.y = shift1.y + (perp.y - p1Ptr->y);\n\t\t(void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]);\n\t    }\n\t}\n\tif (pointsSeen >= 2) {\n\t    dx = poly[3].x - poly[0].x;\n\t    dy = poly[3].y - poly[0].y;\n\t    if (dx > 0) {\n\t\tlightOnLeft = (dy <= dx);\n\t    } else {\n\t\tlightOnLeft = (dy < dx);\n\t    }\n\t    if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {\n\t\tgc = borderPtr->lightGC;\n\t    } else {\n\t\tgc = borderPtr->darkGC;\n\t    }\n\t    XFillPolygon(display, drawable, gc, poly, 4, Convex,\n\t\t    CoordModeOrigin);\n\t}\n\tb1.x = newB1.x;\n\tb1.y = newB1.y;\n\tb2.x = newB2.x;\n\tb2.y = newB2.y;\n\tpoly[0].x = poly[3].x;\n\tpoly[0].y = poly[3].y;\n\tif (parallel) {\n\t    poly[1].x = c.x;\n\t    poly[1].y = c.y;\n\t} else if (pointsSeen >= 1) {\n\t    poly[1].x = poly[2].x;\n\t    poly[1].y = poly[2].y;\n\t}\n\tpointsSeen++;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Fill3DRectangle --\n *\n *\tFill a rectangular area, supplying a 3D border if desired.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_Fill3DRectangle(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Outside area of rectangular region. */\n    int borderWidth,\t\t/* Desired width for border, in pixels. Border\n\t\t\t\t * will be *inside* region. */\n    int relief)\t\t\t/* Indicates 3D effect: TK_RELIEF_FLAT,\n\t\t\t\t * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    int doubleBorder;\n\n    /*\n     * This code is slightly tricky because it only draws the background in\n     * areas not covered by the 3D border. This avoids flashing effects on the\n     * screen for the border region.\n     */\n\n    if (relief == TK_RELIEF_FLAT) {\n\tborderWidth = 0;\n    } else {\n\t/*\n\t * We need to make this extra check, otherwise we will leave garbage\n\t * in thin frames [Bug: 3596]\n\t */\n\n\tif (width < 2*borderWidth) {\n\t    borderWidth = width/2;\n\t}\n\tif (height < 2*borderWidth) {\n\t    borderWidth = height/2;\n\t}\n    }\n    doubleBorder = 2*borderWidth;\n\n    if ((width > doubleBorder) && (height > doubleBorder)) {\n\tXFillRectangle(Tk_Display(tkwin), drawable, borderPtr->bgGC,\n\t\tx + borderWidth, y + borderWidth,\n\t\t(unsigned) (width - doubleBorder),\n\t\t(unsigned) (height - doubleBorder));\n    }\n    if (borderWidth) {\n\tTk_Draw3DRectangle(tkwin, drawable, border, x, y, width,\n\t\theight, borderWidth, relief);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Fill3DPolygon --\n *\n *\tFill a polygonal area, supplying a 3D border if desired.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_Fill3DPolygon(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    XPoint *pointPtr,\t\t/* Array of points describing polygon. All\n\t\t\t\t * points must be absolute\n\t\t\t\t * (CoordModeOrigin). */\n    Tcl_Size numPoints,\t\t/* Number of points at *pointPtr. */\n    int borderWidth,\t\t/* Width of border, measured in pixels to the\n\t\t\t\t * left of the polygon's trajectory. May be\n\t\t\t\t * negative. */\n    int leftRelief)\t\t/* Indicates 3D effect of left side of\n\t\t\t\t * trajectory relative to right:\n\t\t\t\t * TK_RELIEF_FLAT, TK_RELIEF_RAISED, or\n\t\t\t\t * TK_RELIEF_SUNKEN. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n\n    XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,\n\t    pointPtr, (int)numPoints, Complex, CoordModeOrigin);\n    if (leftRelief != TK_RELIEF_FLAT) {\n\tTk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,\n\t\tborderWidth, leftRelief);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * BorderInit --\n *\n *\tInitialize the structures used for border management.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRead the code.\n *\n *-------------------------------------------------------------\n */\n\nstatic void\nBorderInit(\n     TkDisplay *dispPtr)\t/* Used to access thread-specific data. */\n{\n    dispPtr->borderInit = 1;\n    Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ShiftLine --\n *\n *\tGiven two points on a line, compute a point on a new line that is\n *\tparallel to the given line and a given distance away from it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nShiftLine(\n    XPoint *p1Ptr,\t\t/* First point on line. */\n    XPoint *p2Ptr,\t\t/* Second point on line. */\n    int distance,\t\t/* New line is to be this many units to the\n\t\t\t\t * left of original line, when looking from p1\n\t\t\t\t * to p2. May be negative. */\n    XPoint *p3Ptr)\t\t/* Store coords of point on new line here. */\n{\n    int dx, dy, dxNeg, dyNeg;\n    static int shiftTable[129];\t/* Used for a quick approximation in computing\n\t\t\t\t * the new point. An index into the table is\n\t\t\t\t * 128 times the slope of the original line\n\t\t\t\t * (the slope must always be between 0 and 1).\n\t\t\t\t * The value of the table entry is 128 times\n\t\t\t\t * the amount to displace the new line in y\n\t\t\t\t * for each unit of perpendicular distance. In\n\t\t\t\t * other words, the table maps from the\n\t\t\t\t * tangent of an angle to the inverse of its\n\t\t\t\t * cosine. If the slope of the original line\n\t\t\t\t * is greater than 1, then the displacement is\n\t\t\t\t * done in x rather than in y. */\n\n    /*\n     * Initialize the table if this is the first time it is used.\n     */\n\n    if (shiftTable[0] == 0) {\n\tint i;\n\tdouble tangent, cosine;\n\n\tfor (i = 0; i <= 128; i++) {\n\t    tangent = i/128.0;\n\t    cosine = 128/cos(atan(tangent)) + .5;\n\t    shiftTable[i] = (int) cosine;\n\t}\n    }\n\n    *p3Ptr = *p1Ptr;\n    dx = p2Ptr->x - p1Ptr->x;\n    dy = p2Ptr->y - p1Ptr->y;\n    if (dy < 0) {\n\tdyNeg = 1;\n\tdy = -dy;\n    } else {\n\tdyNeg = 0;\n    }\n    if (dx < 0) {\n\tdxNeg = 1;\n\tdx = -dx;\n    } else {\n\tdxNeg = 0;\n    }\n    if (dy <= dx) {\n\tdy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;\n\tif (!dxNeg) {\n\t    dy = -dy;\n\t}\n\tp3Ptr->y += dy;\n    } else {\n\tdx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;\n\tif (dyNeg) {\n\t    dx = -dx;\n\t}\n\tp3Ptr->x += dx;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Intersect --\n *\n *\tFind the intersection point between two lines.\n *\n * Results:\n *\tUnder normal conditions 0 is returned and the point at *iPtr is filled\n *\tin with the intersection between the two lines. If the two lines are\n *\tparallel, then -1 is returned and *iPtr isn't modified.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nIntersect(\n    XPoint *a1Ptr,\t\t/* First point of first line. */\n    XPoint *a2Ptr,\t\t/* Second point of first line. */\n    XPoint *b1Ptr,\t\t/* First point of second line. */\n    XPoint *b2Ptr,\t\t/* Second point of second line. */\n    XPoint *iPtr)\t\t/* Filled in with intersection point. */\n{\n    int dxadyb, dxbdya, dxadxb, dyadyb, p, q;\n\n    /*\n     * The code below is just a straightforward manipulation of two equations\n     * of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve for the\n     * x-coordinate of intersection, then the y-coordinate.\n     */\n\n    dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);\n    dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);\n    dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);\n    dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);\n\n    if (dxadyb == dxbdya) {\n\treturn -1;\n    }\n    p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);\n    q = dxbdya - dxadyb;\n    if (q < 0) {\n\tp = -p;\n\tq = -q;\n    }\n    if (p < 0) {\n\tiPtr->x = (short)(- ((-p + q/2)/q));\n    } else {\n\tiPtr->x = (short)((p + q/2)/q);\n    }\n    p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);\n    q = dxadyb - dxbdya;\n    if (q < 0) {\n\tp = -p;\n\tq = -q;\n    }\n    if (p < 0) {\n\tiPtr->y = (short)(- ((-p + q/2)/q));\n    } else {\n\tiPtr->y = (short)((p + q/2)/q);\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Get3DBorderFromObj --\n *\n *\tReturns the border referred to by a Tcl object. The border must\n *\talready have been allocated via a call to Tk_Alloc3DBorderFromObj or\n *\tTk_Get3DBorder.\n *\n * Results:\n *\tReturns the Tk_3DBorder that matches the tkwin and the string rep of\n *\tthe name of the border given in objPtr.\n *\n * Side effects:\n *\tIf the object is not already a border, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nTk_3DBorder\nTk_Get3DBorderFromObj(\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr)\t\t/* The object whose string value selects a\n\t\t\t\t * border. */\n{\n    TkBorder *borderPtr = NULL;\n    Tcl_HashEntry *hashPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objPtr->typePtr != &tkBorderObjType) {\n\tInitBorderObj(objPtr);\n    }\n\n    /*\n     * If we are lucky (and the user doesn't use too many different displays,\n     * screens, or colormaps...) then the TkBorder structure we need will be\n     * cached in the internal representation of the Tcl_Obj. Check it out...\n     */\n\n    borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;\n    if ((borderPtr != NULL)\n\t    && (borderPtr->resourceRefCount > 0)\n\t    && (Tk_Screen(tkwin) == borderPtr->screen)\n\t    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {\n\t/*\n\t * The object already points to the right border structure. Just\n\t * return it.\n\t */\n\n\treturn (Tk_3DBorder) borderPtr;\n    }\n\n    /*\n     * If we make it here, it means we aren't so lucky. Either there was no\n     * cached TkBorder in the Tcl_Obj, or the TkBorder that was there is for\n     * the wrong screen/colormap. Either way, we have to search for the right\n     * TkBorder. For each color name, there is linked list of TkBorder\n     * structures, one structure for each screen/colormap combination. The\n     * head of the linked list is recorded in a hash table (where the key is\n     * the color name) attached to the TkDisplay structure. Walk this list to\n     * find the right TkBorder structure.\n     */\n\n    hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, Tcl_GetString(objPtr));\n    if (hashPtr == NULL) {\n\tgoto error;\n    }\n    for (borderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr); borderPtr != NULL;\n\t    borderPtr = borderPtr->nextPtr) {\n\tif ((Tk_Screen(tkwin) == borderPtr->screen)\n\t\t&& (Tk_Colormap(tkwin) == borderPtr->colormap)) {\n\t    FreeBorderObj(objPtr);\n\t    objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;\n\t    borderPtr->objRefCount++;\n\t    return (Tk_3DBorder) borderPtr;\n\t}\n    }\n\n  error:\n    Tcl_Panic(\"Tk_Get3DBorderFromObj called with non-existent border!\");\n    /*\n     * The following code isn't reached; it's just there to please compilers.\n     */\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitBorderObj --\n *\n *\tAttempt to generate a border internal form for the Tcl object\n *\t\"objPtr\".\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf no error occurs, a blank internal format for a border value is\n *\tinitialized. The final form cannot be done without a Tk_Window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitBorderObj(\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->typePtr = &tkBorderObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugBorder --\n *\n *\tThis function returns debugging information about a border.\n *\n * Results:\n *\tThe return value is a list with one sublist for each TkBorder\n *\tcorresponding to \"name\". Each sublist has two elements that contain\n *\tthe resourceRefCount and objRefCount fields from the TkBorder\n *\tstructure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugBorder(\n    Tk_Window tkwin,\t\t/* The window in which the border will be used\n\t\t\t\t * (not currently used). */\n    const char *name)\t\t/* Name of the desired color. */\n{\n    Tcl_HashEntry *hashPtr;\n    Tcl_Obj *resultPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    resultPtr = Tcl_NewObj();\n    hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name);\n    if (hashPtr != NULL) {\n\tTkBorder *borderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr);\n\n\tif (borderPtr == NULL) {\n\t    Tcl_Panic(\"TkDebugBorder found empty hash table entry\");\n\t}\n\tfor ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {\n\t    Tcl_Obj *objPtr = Tcl_NewObj();\n\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(borderPtr->resourceRefCount));\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(borderPtr->objRefCount));\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);\n\t}\n    }\n    return resultPtr;\n}\n\n/*\n *--------------------------------------------------------------\n *\n * Tk_Get3BorderColors --\n *\n *\tGiven a Tk_3DBorder determine its 3 colors.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_Get3DBorderColors(\n    Tk_3DBorder border,\n    XColor *bgColorPtr,\n    XColor *darkColorPtr,\n    XColor *lightColorPtr)\n{\n    TkBorder *borderPtr = (TkBorder *)border;\n    const XColor *colorPtr = borderPtr->bgColorPtr ;\n\n    if (bgColorPtr) {\n\t*bgColorPtr = *colorPtr;\n    }\n    if (darkColorPtr) {\n\t*darkColorPtr = borderPtr->darkColorPtr ? *borderPtr->darkColorPtr : *colorPtr;\n    }\n    if (lightColorPtr) {\n\t*lightColorPtr = borderPtr->lightColorPtr ? *borderPtr->lightColorPtr : *colorPtr;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tk3d.h",
    "content": "/*\n * tk3d.h --\n *\n *\tDeclarations of types and functions shared by the 3d border module.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TK3D\n#define _TK3D\n\n#include \"tkInt.h\"\n\n/*\n * One of the following data structures is allocated for each 3-D border\n * currently in use. Structures of this type are indexed by borderTable, so\n * that a single structure can be shared for several uses.\n */\n\ntypedef struct TkBorder {\n    Screen *screen;\t\t/* Screen on which the border will be used. */\n    Visual *visual;\t\t/* Visual for all windows and pixmaps using\n\t\t\t\t * the border. */\n    int depth;\t\t\t/* Number of bits per pixel of drawables where\n\t\t\t\t * the border will be used. */\n    Colormap colormap;\t\t/* Colormap out of which pixels are\n\t\t\t\t * allocated. */\n    Tcl_Size resourceRefCount;\t/* Number of active uses of this color (each\n\t\t\t\t * active use corresponds to a call to\n\t\t\t\t * Tk_Alloc3DBorderFromObj or Tk_Get3DBorder).\n\t\t\t\t * If this count is 0, then this structure is\n\t\t\t\t * no longer valid and it isn't present in\n\t\t\t\t * borderTable: it is being kept around only\n\t\t\t\t * because there are objects referring to it.\n\t\t\t\t * The structure is freed when objRefCount and\n\t\t\t\t * resourceRefCount are both 0. */\n    Tcl_Size objRefCount;\t\t/* The number of Tcl objects that reference\n\t\t\t\t * this structure. */\n    XColor *bgColorPtr;\t\t/* Background color (intensity between\n\t\t\t\t * lightColorPtr and darkColorPtr). */\n    XColor *darkColorPtr;\t/* Color for darker areas (must free when\n\t\t\t\t * deleting structure). NULL means shadows\n\t\t\t\t * haven't been allocated yet.*/\n    XColor *lightColorPtr;\t/* Color used for lighter areas of border\n\t\t\t\t * (must free this when deleting structure).\n\t\t\t\t * NULL means shadows haven't been allocated\n\t\t\t\t * yet. */\n    Pixmap shadow;\t\t/* Stipple pattern to use for drawing shadows\n\t\t\t\t * areas. Used for displays with <= 64 colors\n\t\t\t\t * or where colormap has filled up. */\n    GC bgGC;\t\t\t/* Used (if necessary) to draw areas in the\n\t\t\t\t * background color. */\n    GC darkGC;\t\t\t/* Used to draw darker parts of the border.\n\t\t\t\t * NULL means the shadow colors haven't been\n\t\t\t\t * allocated yet.*/\n    GC lightGC;\t\t\t/* Used to draw lighter parts of the border.\n\t\t\t\t * NULL means the shadow colors haven't been\n\t\t\t\t * allocated yet. */\n    Tcl_HashEntry *hashPtr;\t/* Entry in borderTable (needed in order to\n\t\t\t\t * delete structure). */\n    struct TkBorder *nextPtr;\t/* Points to the next TkBorder structure with\n\t\t\t\t * the same color name. Borders with the same\n\t\t\t\t * name but different screens or colormaps are\n\t\t\t\t * chained together off a single entry in\n\t\t\t\t * borderTable. */\n} TkBorder;\n\n/*\n * Maximum intensity for a color:\n */\n\n#define MAX_INTENSITY 65535\n\n/*\n * Declarations for platform specific interfaces used by this module.\n */\n\nMODULE_SCOPE TkBorder\t*TkpGetBorder(void);\nMODULE_SCOPE void\tTkpGetShadows(TkBorder *borderPtr, Tk_Window tkwin);\nMODULE_SCOPE void\tTkpFreeBorder(TkBorder *borderPtr);\n\n#endif /* _TK3D */\n"
  },
  {
    "path": "generic/tkAccessibility.c",
    "content": "/*\n * tkAccessibility.c --\n *\n *\tThis file implements an accessibility API for Tk that can be accessed\n *\tfrom the script level. We are tracking accessible traits per Tk_Window\n *      in hash tables that can be accessed on any platform. This core Tk API\n *      is backed by platform-specific implementations.\n *\n * Copyright © 2024-2025 Kevin Walzer\n * Copyright © 2024 Emiliano Gavilan\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n */\n\n#include \"tkInt.h\"\n\n/* Data declarations and protoypes of functions used in this file. */\n\nTcl_HashTable *TkAccessibilityObject = NULL;\n\nint     Tk_SetAccessibleRole(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleName(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleDescription(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleState (TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t       Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleValue(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t      Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleAction(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t       Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_SetAccessibleHelp(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleRole(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleName(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleDescription(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleState(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t      Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleValue(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t      Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleAction(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t       Tcl_Size objc, Tcl_Obj *const objv[]);\nint     Tk_GetAccessibleHelp(TCL_UNUSED(void *),Tcl_Interp *ip,\n\t\t\t     Tcl_Size objc, Tcl_Obj *const objv[]);\nvoid    TkAccessibility_Cleanup(void *clientData);\n/* Cleanup proc when the window is destroyed. */\nstatic  Tk_EventProc WindowDestroyHandler;\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleRole --\n *\n *\tThis function assigns an accessibility role for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tAssigns an accessibility role.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleRole(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? role?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  int isNew;\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /*\n   * Create new hash table for widget attributes if none exists.\n   * Ensure it is unique to that widget.\n   */\n  hPtr=Tcl_CreateHashEntry(TkAccessibilityObject, win, &isNew);\n  if (isNew) {\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n    Tcl_InitHashTable(AccessibleAttributes,TCL_STRING_KEYS);\n    Tcl_SetHashValue(hPtr, AccessibleAttributes);\n    Tk_CreateEventHandler(win, StructureNotifyMask, WindowDestroyHandler, win);\n  } else {\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  }\n\n  /* Set accessible role for window.  */\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"role\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleName --\n *\n *\tThis function assigns an accessibility name for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tAssigns an accessibility name.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleName(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? name?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessible name for window.  */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"name\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleDescription --\n *\n *\tThis function assigns a platform-neutral accessibility descrption for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tAssigns an accessibility description.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleDescription(\n\t\t\t    TCL_UNUSED(void *),\n\t\t\t    Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t\t    Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t\t    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? description?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessibility description for window. */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"description\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleValue  --\n *\n *\tThis function sets the current value/data of the widget for\n *\tthe accessibility API.\n *\n *\n * Results:\n *\tAssigns  an accessibility value in string format.\n *      Platform-specific API's will convert to the required type, if needed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleValue(\n\t\t      TCL_UNUSED(void *),\n\t\t      Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t      Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t      Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? value?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessibility value for window. */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"value\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleState  --\n *\n *\tThis function reads the current state of the widget for\n *\tthe accessibility API.\n *\n *\n * Results:\n *\tReturns an accessibility state.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleState(\n\t\t      TCL_UNUSED(void *),\n\t\t      Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t      Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t      Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? state?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessibility state for window. */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"state\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleAction  --\n *\n *\tThis function sets the current accessibility action for the widget.\n *\n *\n * Results:\n *\tSets an accessibility action for the widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleAction(\n\t\t       TCL_UNUSED(void *),\n\t\t       Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t       Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t       Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? action?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessibility action for window. */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"action\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAccessibleHelp  --\n *\n *\tThis function sets the accessibility help text for the widget.\n *\n *\n * Results:\n *\tSets help text for the widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetAccessibleHelp(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 3) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window? help?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n  int isNew;\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Set accessibility help for window. */\n\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2 =  Tcl_CreateHashEntry(AccessibleAttributes, \"help\", &isNew);\n  if (!isNew) {\n    Tcl_DecrRefCount((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  }\n  Tcl_IncrRefCount(objv[2]);\n  Tcl_SetHashValue(hPtr2, objv[2]);\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleRole --\n *\n *\tThis function reads an accessibility role for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tGets an accessibility role.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleRole(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible role for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No role found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleName --\n *\n *\tThis function reads an accessibility name for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tGets an accessibility name.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleName(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible name for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"name\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No name found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleDescription --\n *\n *\tThis function reads a platform-neutral accessibility descrption for a\n *\tspecific widget.\n *\n *\n * Results:\n *\tGets an accessibility description.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleDescription(\n\t\t\t    TCL_UNUSED(void *),\n\t\t\t    Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t\t    Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t\t    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible description for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"description\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No description found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleValue  --\n *\n *\tThis function reads the current value/data of the widget for\n *\tthe accessibility API.\n *\n *\n * Results:\n *\tReturns an accessibility value in string format.\n *      Platform-specific API's will convert to the required type, if needed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleValue(\n\t\t      TCL_UNUSED(void *),\n\t\t      Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t      Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t      Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible value for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"value\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No value found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleState  --\n *\n *\tThis function reads the current state of the widget for\n *\tthe accessibility API.\n *\n *\n * Results:\n *\tReturns an accessibility state.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleState(\n\t\t      TCL_UNUSED(void *),\n\t\t      Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t      Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t      Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible state for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"state\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No state found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleAction  --\n *\n *\tThis function gets the current accessibility action for the widget.\n *\n *\n * Results:\n *\tReturns an accessibility action for the widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleAction(\n\t\t       TCL_UNUSED(void *),\n\t\t       Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t       Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t       Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible action for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"action\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No action found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAccessibleHelp  --\n *\n *\tThis function gets the current accessibility help for the widget.\n *\n *\n * Results:\n *\tReturns an accessibility help text for the widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAccessibleHelp(\n\t\t     TCL_UNUSED(void *),\n\t\t     Tcl_Interp *ip,\t\t/* Current interpreter. */\n\t\t     Tcl_Size objc,\t\t\t/* Number of arguments. */\n\t\t     Tcl_Obj *const objv[])\t/* Argument objects. */\n\n{\n  if (objc < 2) {\n    Tcl_WrongNumArgs(ip, 1, objv, \"window?\");\n    return TCL_ERROR;\n  }\n\n  Tk_Window win;\n  Tcl_HashEntry *hPtr, *hPtr2;\n\n  Tcl_HashTable *AccessibleAttributes;\n\n  win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n  if (win == NULL) {\n    return TCL_ERROR;\n  }\n\n  /* Get accessible help for window.  */\n  hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n  if (!hPtr) {\n    Tcl_AppendResult(ip, \"No table found. You must set the accessibility role first.\", (char *) NULL);\n    return TCL_ERROR;\n  }\n  AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n  hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"help\");\n  if (!hPtr2) {\n    Tcl_AppendResult(ip, \"No help found\", (char *) NULL);\n    return TCL_ERROR;\n  }\n\n  Tcl_SetObjResult(ip, (Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n  return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * WindowDestroyHandler --\n *\n *\tThis function cleans up accessibility hash tables on window\n *      destruction.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCleans up hash table structures.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void WindowDestroyHandler(\n    void *clientData,\n    XEvent *eventPtr)\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tcl_HashTable *AccessibleAttributes;\n    Tcl_HashEntry *hPtr, *hPtr2;\n    Tcl_HashSearch search;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n\n    hPtr = Tcl_FindHashEntry(TkAccessibilityObject, tkwin);\n    if (!hPtr) {\n\t/* shouldn't happen*/\n\treturn;\n    }\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    for (hPtr2 = Tcl_FirstHashEntry(AccessibleAttributes, &search);\n\t    hPtr2 != NULL; hPtr2 = Tcl_NextHashEntry(&search)) {\n\tTcl_Obj *objPtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr2);\n\tTcl_DecrRefCount(objPtr);\n\tTcl_DeleteHashEntry(hPtr2);\n    }\n    Tcl_DeleteHashTable(AccessibleAttributes);\n    Tcl_Free(AccessibleAttributes);\n    Tcl_DeleteHashEntry(hPtr);\n    return;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * TkAccessibility_Cleanup --\n *\n *\tThis function cleans up the global accessibility hash table and\n *\tall associated data structures. It should be called during Tk\n *\tfinalization to prevent memory leaks.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees all memory allocated for accessibility attributes.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkAccessibility_Cleanup(\n    TCL_UNUSED(void *))\n{\n    /* If nothing to do, return. */\n    if (TkAccessibilityObject == NULL) {\n\treturn;\n    }\n\n    /* Steal the pointer and immediately clear the global so other code can bail out. */\n    Tcl_HashTable *table = TkAccessibilityObject;\n    TkAccessibilityObject = NULL;\n\n    /* Iterate windows in the captured table. Use `table` (not the global). */\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    hPtr = Tcl_FirstHashEntry(table, &search);\n    while (hPtr != NULL) {\n\t/* GET THE KEY FROM 'table' (not the global). */\n\tTk_Window tkwin = (Tk_Window) Tcl_GetHashKey(table, hPtr);\n\tTcl_HashTable *perWin = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\n\tif (tkwin) {\n\t    /* Unregister the destroy handler so it cannot run later and touch freed data. */\n\t    Tk_DeleteEventHandler(tkwin, StructureNotifyMask,\n\t\t\t\t  WindowDestroyHandler, tkwin);\n\t}\n\n\tif (perWin) {\n\t    /* Decref any stored Tcl_Objs. */\n\t    Tcl_HashEntry *h2;\n\t    Tcl_HashSearch s2;\n\t    h2 = Tcl_FirstHashEntry(perWin, &s2);\n\t    while (h2) {\n\t\tTcl_Obj *obj = (Tcl_Obj *)Tcl_GetHashValue(h2);\n\t\tif (obj) {\n\t\t    Tcl_DecrRefCount(obj);\n\t\t}\n\t\th2 = Tcl_NextHashEntry(&s2);\n\t    }\n\n\t    /* Delete the per-window hash table and free its memory. */\n\t    Tcl_DeleteHashTable(perWin);\n\t    Tcl_Free(perWin);\n\t}\n\n\thPtr = Tcl_NextHashEntry(&search);\n    }\n\n    /* Now free the main table safely. */\n    Tcl_DeleteHashTable(table);\n    Tcl_Free(table);\n}\n\n\n\n/*\n * Register script-level commands to set accessibility attributes.\n */\n\nint\nTkAccessibility_Init(\n\t\t     Tcl_Interp *interp)\n{\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_role\", Tk_SetAccessibleRole, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_name\", Tk_SetAccessibleName, NULL,NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_description\", Tk_SetAccessibleDescription, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_value\", Tk_SetAccessibleValue, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_state\", Tk_SetAccessibleState, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_action\", Tk_SetAccessibleAction, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::set_acc_help\", Tk_SetAccessibleHelp, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_role\", Tk_GetAccessibleRole, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_name\", Tk_GetAccessibleName, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_description\", Tk_GetAccessibleDescription, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_value\", Tk_GetAccessibleValue, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_state\", Tk_GetAccessibleState, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_action\", Tk_GetAccessibleAction, NULL, NULL);\n  Tcl_CreateObjCommand2(interp, \"::tk::accessible::get_acc_help\", Tk_GetAccessibleHelp, NULL, NULL);\n\n  if (!TkAccessibilityObject) {\n      TkAccessibilityObject = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n      Tcl_InitHashTable(TkAccessibilityObject, TCL_ONE_WORD_KEYS);\n  }\n\n\n  /* Register cleanup function. */\n  TkCreateExitHandler(TkAccessibility_Cleanup, NULL);\n\n  return TCL_OK;\n}\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n\n\n"
  },
  {
    "path": "generic/tkArgv.c",
    "content": "/*\n * tkArgv.c --\n *\n *\tThis file contains a function that handles table-based argv-argc\n *\tparsing.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Default table of argument descriptors. These are normally available in\n * every application.\n */\n\nstatic const Tk_ArgvInfo defaultTable[] = {\n    {\"-help\",\tTK_ARGV_HELP, NULL, NULL,\n\t\"Print summary of command-line options and abort\"},\n    {NULL,\tTK_ARGV_END, NULL, NULL, NULL}\n};\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\tPrintUsage(Tcl_Interp *interp, const Tk_ArgvInfo *argTable,\n\t\t    int flags);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ParseArgv --\n *\n *\tProcess an argv array according to a table of expected command-line\n *\toptions. See the manual page for more details.\n *\n * Results:\n *\tThe return value is a standard Tcl return value. If an error occurs\n *\tthen an error message is left in the interp's result. Under normal\n *\tconditions, both *argcPtr and *argv are modified to return the\n *\targuments that couldn't be processed here (they didn't match the\n *\toption table, or followed an TK_ARGV_REST argument).\n *\n * Side effects:\n *\tVariables may be modified, resources may be entered for tkwin, or\n *\tfunctions may be called. It all depends on the arguments and their\n *\tentries in argTable. See the user documentation for details.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ParseArgv(\n    Tcl_Interp *interp,\t\t/* Place to store error message. */\n    Tk_Window tkwin,\t\t/* Window to use for setting Tk options. NULL\n\t\t\t\t * means ignore Tk option specs. */\n    int *argcPtr,\t\t/* Number of arguments in argv. Modified to\n\t\t\t\t * hold # args left in argv at end. */\n    const char **argv,\t\t/* Array of arguments. Modified to hold those\n\t\t\t\t * that couldn't be processed here. */\n    const Tk_ArgvInfo *argTable,\t/* Array of option descriptions */\n    int flags)\t\t\t/* Or'ed combination of various flag bits,\n\t\t\t\t * such as TK_ARGV_NO_DEFAULTS. */\n{\n    const Tk_ArgvInfo *infoPtr;\n\t\t\t\t/* Pointer to the current entry in the table\n\t\t\t\t * of argument descriptions. */\n    const Tk_ArgvInfo *matchPtr;/* Descriptor that matches current argument. */\n    const char *curArg;\t\t/* Current argument */\n    char c;\t\t/* Second character of current arg (used for\n\t\t\t\t * quick check for matching; use 2nd char.\n\t\t\t\t * because first char. will almost always be\n\t\t\t\t * '-'). */\n    int srcIndex;\t\t/* Location from which to read next argument\n\t\t\t\t * from argv. */\n    int dstIndex;\t\t/* Index into argv to which next unused\n\t\t\t\t * argument should be copied (never greater\n\t\t\t\t * than srcIndex). */\n    int argc;\t\t\t/* # arguments in argv still to process. */\n    size_t length;\t\t/* Number of characters in current argument. */\n    int i;\n\n    if (flags & TK_ARGV_DONT_SKIP_FIRST_ARG) {\n\tsrcIndex = dstIndex = 0;\n\targc = *argcPtr;\n    } else {\n\tsrcIndex = dstIndex = 1;\n\targc = *argcPtr-1;\n    }\n\n    while (argc > 0) {\n\tcurArg = argv[srcIndex];\n\tsrcIndex++;\n\targc--;\n\tlength = strlen(curArg);\n\tif (length > 0) {\n\t    c = curArg[1];\n\t} else {\n\t    c = 0;\n\t}\n\n\t/*\n\t * Loop through the argument descriptors searching for one with the\n\t * matching key string. If found, leave a pointer to it in matchPtr.\n\t */\n\n\tmatchPtr = NULL;\n\tfor (i = 0; i < 2; i++) {\n\t    if (i == 0) {\n\t\tinfoPtr = argTable;\n\t    } else {\n\t\tinfoPtr = defaultTable;\n\t    }\n\t    for (; (infoPtr != NULL) && (infoPtr->type != TK_ARGV_END);\n\t\t    infoPtr++) {\n\t\tif (infoPtr->key == NULL) {\n\t\t    continue;\n\t\t}\n\t\tif ((infoPtr->key[1] != c)\n\t\t\t|| (strncmp(infoPtr->key, curArg, length) != 0)) {\n\t\t    continue;\n\t\t}\n\t\tif ((tkwin == NULL)\n\t\t\t&& ((infoPtr->type == TK_ARGV_CONST_OPTION)\n\t\t\t|| (infoPtr->type == TK_ARGV_OPTION_VALUE)\n\t\t\t|| (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) {\n\t\t    continue;\n\t\t}\n\t\tif (infoPtr->key[length] == 0) {\n\t\t    matchPtr = infoPtr;\n\t\t    goto gotMatch;\n\t\t}\n\t\tif (flags & TK_ARGV_NO_ABBREV) {\n\t\t    continue;\n\t\t}\n\t\tif (matchPtr != NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"ambiguous option \\\"%s\\\"\", curArg));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"ARG\", \"AMBIGUOUS\", curArg,\n\t\t\t    (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tmatchPtr = infoPtr;\n\t    }\n\t}\n\tif (matchPtr == NULL) {\n\t    /*\n\t     * Unrecognized argument. Just copy it down, unless the caller\n\t     * prefers an error to be registered.\n\t     */\n\n\t    if (flags & TK_ARGV_NO_LEFTOVERS) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"unrecognized argument \\\"%s\\\"\", curArg));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"ARG\", \"UNRECOGNIZED\", curArg,\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    argv[dstIndex] = curArg;\n\t    dstIndex++;\n\t    continue;\n\t}\n\n\t/*\n\t * Take the appropriate action based on the option type\n\t */\n\n    gotMatch:\n\tinfoPtr = matchPtr;\n\tswitch (infoPtr->type) {\n\tcase TK_ARGV_CONSTANT:\n\t    *((int *) infoPtr->dst) = (int)PTR2INT(infoPtr->src);\n\t    break;\n\tcase TK_ARGV_INT:\n\t    if (argc == 0) {\n\t\tgoto missingArg;\n\t    }\n\t    if (Tcl_GetInt(interp, argv[srcIndex], (int *) infoPtr->dst) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    srcIndex++;\n\t    argc--;\n\t    break;\n\tcase TK_ARGV_STRING:\n\t    if (argc == 0) {\n\t\tgoto missingArg;\n\t    }\n\t    *((const char **) infoPtr->dst) = argv[srcIndex];\n\t    srcIndex++;\n\t    argc--;\n\t    break;\n\tcase TK_ARGV_UID:\n\t    if (argc == 0) {\n\t\tgoto missingArg;\n\t    }\n\t    *((Tk_Uid *) infoPtr->dst) = Tk_GetUid(argv[srcIndex]);\n\t    srcIndex++;\n\t    argc--;\n\t    break;\n\tcase TK_ARGV_REST:\n\t    *((int *) infoPtr->dst) = dstIndex;\n\t    goto argsDone;\n\tcase TK_ARGV_FLOAT:\n\t    if (argc == 0) {\n\t\tgoto missingArg;\n\t    }\n\t    if (Tcl_GetDouble(interp, argv[srcIndex], ((double *) infoPtr->dst)) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    srcIndex++;\n\t    argc--;\n\t    break;\n\tcase TK_ARGV_FUNC: {\n\t    typedef int (ArgvFunc)(char *, const char *, const char *);\n\t    ArgvFunc *handlerProc = (ArgvFunc *)infoPtr->src;\n\n\t    if (handlerProc((char *)infoPtr->dst, infoPtr->key, argv[srcIndex])) {\n\t\tsrcIndex++;\n\t\targc--;\n\t    }\n\t    break;\n\t}\n\tcase TK_ARGV_GENFUNC: {\n\t    typedef int (ArgvGenFunc)(char *, Tcl_Interp *, const char *, int,\n\t\t    const char **);\n\t    ArgvGenFunc *handlerProc = (ArgvGenFunc *)infoPtr->src;\n\n\t    argc = handlerProc((char *)infoPtr->dst, interp, infoPtr->key, argc,\n\t\t    argv+srcIndex);\n\t    if (argc < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\t}\n\tcase TK_ARGV_HELP:\n\t    PrintUsage(interp, argTable, flags);\n\t    Tcl_SetErrorCode(interp, \"TK\", \"ARG\", \"HELP\", (char *)NULL);\n\t    return TCL_ERROR;\n\tcase TK_ARGV_CONST_OPTION:\n\t    Tk_AddOption(tkwin, (char *)infoPtr->dst, (char *)infoPtr->src,\n\t\t    TK_INTERACTIVE_PRIO);\n\t    break;\n\tcase TK_ARGV_OPTION_VALUE:\n\t    if (argc < 1) {\n\t\tgoto missingArg;\n\t    }\n\t    Tk_AddOption(tkwin, (char *)infoPtr->dst, argv[srcIndex],\n\t\t    TK_INTERACTIVE_PRIO);\n\t    srcIndex++;\n\t    argc--;\n\t    break;\n\tcase TK_ARGV_OPTION_NAME_VALUE:\n\t    if (argc < 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"\\\"%s\\\" option requires two following arguments\",\n\t\t\tcurArg));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"ARG\", \"NAME_VALUE\", curArg,\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1],\n\t\t    TK_INTERACTIVE_PRIO);\n\t    srcIndex += 2;\n\t    argc -= 2;\n\t    break;\n\tdefault:\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad argument type %d in Tk_ArgvInfo\", infoPtr->type));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"API_ABUSE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * If we broke out of the loop because of an OPT_REST argument, copy the\n     * remaining arguments down.\n     */\n\n  argsDone:\n    while (argc) {\n\targv[dstIndex] = argv[srcIndex];\n\tsrcIndex++;\n\tdstIndex++;\n\targc--;\n    }\n    argv[dstIndex] = NULL;\n    *argcPtr = dstIndex;\n    return TCL_OK;\n\n  missingArg:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"\\\"%s\\\" option requires an additional argument\", curArg));\n    Tcl_SetErrorCode(interp, \"TK\", \"ARG\", \"MISSING\", curArg, (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PrintUsage --\n *\n *\tGenerate a help string describing command-line options.\n *\n * Results:\n *\tThe interp's result will be modified to hold a help string describing\n *\tall the options in argTable, plus all those in the default table\n *\tunless TK_ARGV_NO_DEFAULTS is specified in flags.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPrintUsage(\n    Tcl_Interp *interp,\t\t/* Place information in this interp's result\n\t\t\t\t * area. */\n    const Tk_ArgvInfo *argTable,/* Array of command-specific argument\n\t\t\t\t * descriptions. */\n    int flags)\t\t\t/* If the TK_ARGV_NO_DEFAULTS bit is set in\n\t\t\t\t * this word, then don't generate information\n\t\t\t\t * for default options. */\n{\n    const Tk_ArgvInfo *infoPtr;\n    size_t width, i, numSpaces;\n    Tcl_Obj *message;\n\n    /*\n     * First, compute the width of the widest option key, so that we can make\n     * everything line up.\n     */\n\n    width = 4;\n    for (i = 0; i < 2; i++) {\n\tfor (infoPtr = i ? defaultTable : argTable;\n\t\tinfoPtr->type != TK_ARGV_END; infoPtr++) {\n\t    size_t length;\n\n\t    if (infoPtr->key == NULL) {\n\t\tcontinue;\n\t    }\n\t    length = strlen(infoPtr->key);\n\t    if (length > width) {\n\t\twidth = length;\n\t    }\n\t}\n    }\n\n    message = Tcl_NewStringObj(\"Command-specific options:\", TCL_INDEX_NONE);\n    for (i = 0; ; i++) {\n\tfor (infoPtr = i ? defaultTable : argTable;\n\t\tinfoPtr->type != TK_ARGV_END; infoPtr++) {\n\t    if ((infoPtr->type == TK_ARGV_HELP) && (infoPtr->key == NULL)) {\n\t\tTcl_AppendPrintfToObj(message, \"\\n%s\", infoPtr->help);\n\t\tcontinue;\n\t    }\n\t    Tcl_AppendPrintfToObj(message, \"\\n %s:\", infoPtr->key);\n\t    numSpaces = width + 1 - strlen(infoPtr->key);\n\t    while (numSpaces-- > 0) {\n\t\tTcl_AppendToObj(message, \" \", 1);\n\t    }\n\t    Tcl_AppendToObj(message, infoPtr->help, TCL_INDEX_NONE);\n\t    switch (infoPtr->type) {\n\t    case TK_ARGV_INT:\n\t\tTcl_AppendPrintfToObj(message, \"\\n\\t\\tDefault value: %d\",\n\t\t\t*((int *) infoPtr->dst));\n\t\tbreak;\n\t    case TK_ARGV_FLOAT:\n\t\tTcl_AppendPrintfToObj(message, \"\\n\\t\\tDefault value: %f\",\n\t\t\t*((double *) infoPtr->dst));\n\t\tbreak;\n\t    case TK_ARGV_STRING: {\n\t\tchar *string = *((char **) infoPtr->dst);\n\n\t\tif (string != NULL) {\n\t\t    Tcl_AppendPrintfToObj(message,\n\t\t\t    \"\\n\\t\\tDefault value: \\\"%s\\\"\", string);\n\t\t}\n\t\tbreak;\n\t    }\n\t    default:\n\t\tbreak;\n\t    }\n\t}\n\n\tif ((flags & TK_ARGV_NO_DEFAULTS) || (i > 0)) {\n\t    break;\n\t}\n\tTcl_AppendToObj(message, \"\\nGeneric options for all commands:\", TCL_INDEX_NONE);\n    }\n    Tcl_SetObjResult(interp, message);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkArray.h",
    "content": "/*\n * tkArray.h --\n *\n * An array is a sequence of items, stored in a contiguous memory region.\n * Random access to any item is very fast. New items can be either appended\n * or prepended. An array may be traversed in the forward or backward direction.\n *\n * Copyright © 2018-2019 Gregor Cramer.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Note that this file will not be included in header files, it is the purpose\n * of this file to be included in source files only. Thus we are not using the\n * prefix \"Tk_\" here for functions, because all the functions have private scope.\n */\n\f\n/*\n * -------------------------------------------------------------------------------\n * Use the array in the following way:\n * -------------------------------------------------------------------------------\n * typedef struct { int key, value; } Pair;\n * TK_PTR_ARRAY_DEFINE(MyArray, Pair);\n * MyArray *arr = NULL;\n * if (MyArray_IsEmpty(arr)) {\n *     MyArray_Append(&arr, MakePair(1, 2));\n *     MyArray_Append(&arr, MakePair(2, 3));\n *     for (i = 0; i < MyArray_Size(arr); ++i) {\n *         Pair *p = MyArray_Get(arr, i);\n *         printf(\"%d -> %d\\n\", p->key, p->value);\n *         Tcl_Free(p);\n *     }\n *     MyArray_Free(&arr);\n *     assert(arr == NULL);\n * }\n * -------------------------------------------------------------------------------\n * Or with aggregated elements:\n * -------------------------------------------------------------------------------\n * typedef struct { int key, value; } Pair;\n * TK_ARRAY_DEFINE(MyArray, Pair);\n * Pair p1 = { 1, 2 };\n * Pair p2 = { 2, 3 };\n * MyArray *arr = NULL;\n * if (MyArray_IsEmpty(arr)) {\n *     MyArray_Append(&arr, p1);\n *     MyArray_Append(&arr, p2);\n *     for (i = 0; i < MyArray_Size(arr); ++i) {\n *         const Pair *p = MyArray_Get(arr, i);\n *         printf(\"%d -> %d\\n\", p->key, p->value);\n *     }\n *     MyArray_Free(&arr);\n *     assert(arr == NULL);\n * }\n * -------------------------------------------------------------------------------\n */\n\f\n/*************************************************************************/\n/*\n * Two array types will be provided:\n * Use TK_ARRAY_DEFINE if your array is aggregating the elements. Use\n * TK_PTR_ARRAY_DEFINE if your array contains pointers to elements. But\n * in latter case the array is not responsible for the lifetime of the\n * elements.\n */\n/*************************************************************************/\n/*\n * Array_ElemSize: Returns the memory size for one array element.\n */\n/*************************************************************************/\n/*\n * Array_BufferSize: Returns the memory size for given number of elements.\n */\n/*************************************************************************/\n/*\n * Array_IsEmpty: Array is empty?\n */\n/*************************************************************************/\n/*\n * Array_Size: Number of elements in array.\n */\n/*************************************************************************/\n/*\n * Array_Capacity: Capacity of given array. This is the maximal number of\n * elements fitting into current array memory without resizing the buffer.\n */\n/*************************************************************************/\n/*\n * Array_SetSize: Set array size, new size must not exceed the capacity of\n * the array. This function has to be used with care when increasing the\n * array size.\n */\n/*************************************************************************/\n/*\n * Array_First: Returns position of first element in array. Given array\n * may be NULL.\n */\n/*************************************************************************/\n/*\n * Array_Last: Returns position after last element in array. Given array\n * may be empty.\n */\n/*************************************************************************/\n/*\n * Array_Front: Returns first element in array. Given array must not be\n * empty.\n */\n/*************************************************************************/\n/*\n * Array_Back: Returns last element in array. Given array must not be\n * empty.\n */\n/*************************************************************************/\n/*\n * Array_Resize: Resize buffer of array for given number of elements. The\n * array may grow or shrink. Note that this function is not initializing\n * the increased buffer.\n */\n/*************************************************************************/\n/*\n * Array_ResizeAndClear: Resize buffer of array for given number of\n * elements. The array may grow or shrink. The increased memory will be\n * filled with zeroes.\n */\n/*************************************************************************/\n/*\n * Array_Clear: Fill specified range with zeroes.\n */\n/*************************************************************************/\n/*\n * Array_Free: Resize array to size zero. This function will release the\n * array buffer.\n */\n/*************************************************************************/\n/*\n * Array_Append: Insert given element after end of array.\n */\n/*************************************************************************/\n/*\n * Array_PopBack: Shrink array by one element. Given array must not be\n * empty.\n */\n/*************************************************************************/\n/*\n * Array_Get: Random access to array element at given position. The given\n * index must not exceed current array size.\n */\n/*************************************************************************/\n/*\n * Array_Set: Replace array element at given position with new value. The\n * given index must not exceed current array size.\n */\n/*************************************************************************/\n/*\n * Array_Find: Return index position of element which matches given\n * argument. If not found then -1 will be returned.\n */\n/*************************************************************************/\n\f\n#ifndef TK_ARRAY_DEFINED\n#define TK_ARRAY_DEFINED\n\n#include \"tkInt.h\"\n\n#if defined(__GNUC__) || defined(__clang__)\n# define __TK_ARRAY_UNUSED __attribute__((unused))\n#else\n# define __TK_ARRAY_UNUSED\n#endif\n\n#define TK_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */\t\t\t\\\n/* ------------------------------------------------------------------------- */\t\\\ntypedef struct AT {\t\t\t\t\t\t\t\t\\\n    size_t size;\t\t\t\t\t\t\t\t\\\n    size_t capacity;\t\t\t\t\t\t\t\t\\\n    ElemType buf[1];\t\t\t\t\t\t\t\t\\\n} AT;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Init(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    arr->size = 0;\t\t\t\t\t\t\t\t\\\n    arr->capacity = 0;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_ElemSize(void)\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return sizeof(ElemType);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_BufferSize(size_t numElems)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return numElems*sizeof(ElemType);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nAT##_IsEmpty(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return !arr || arr->size == 0u;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_Size(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->size : 0u;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_Capacity(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->capacity : 0u;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_First(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->buf : NULL;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Last(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->buf + arr->size : NULL;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Front(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return &arr->buf[0];\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Back(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return &arr->buf[arr->size - 1];\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Resize(AT **arrp, size_t newSize)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    assert(!*arrp || (*arrp)->size != 0xdeadbeef);\t\t\t\t\\\n    if (newSize == 0) {\t\t\t\t\t\t\t\t\\\n\tassert(!*arrp || ((*arrp)->size = 0xdeadbeef));\t\t\t\t\\\n\tTcl_Free(*arrp);\t\t\t\t\t\t\t\t\\\n\t*arrp = NULL;\t\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\t\\\n\tint init = *arrp == NULL;\t\t\t\t\t\t\\\n\tsize_t memSize = AT##_BufferSize(newSize - 1) + sizeof(AT);\t\t\\\n\t*arrp = (AT *)Tcl_Realloc(*arrp, memSize);\t\t\t\t\t\\\n\tif (init) {\t\t\t\t\t\t\t\t\\\n\t    (*arrp)->size = 0;\t\t\t\t\t\t\t\\\n\t} else if (newSize < (*arrp)->size) {\t\t\t\t\t\\\n\t    (*arrp)->size = newSize;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\t(*arrp)->capacity = newSize;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Clear(AT *arr, size_t from, size_t to)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(to <= AT##_Capacity(arr));\t\t\t\t\t\t\\\n    assert(from <= to);\t\t\t\t\t\t\t\t\\\n    memset(arr->buf + from, 0, AT##_BufferSize(to - from));\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_ResizeAndClear(AT **arrp, size_t newSize)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    size_t oldCapacity;\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    oldCapacity = *arrp ? (*arrp)->capacity : 0;\t\t\t\t\\\n    AT##_Resize(arrp, newSize);\t\t\t\t\t\t\t\\\n    if (newSize > oldCapacity) {\t\t\t\t\t\t\\\n\tAT##_Clear(*arrp, oldCapacity, newSize);\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_SetSize(AT *arr, size_t newSize)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(newSize <= AT##_Capacity(arr));\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    if (arr) {\t\t\t\t\t\t\t\t\t\\\n\tarr->size = newSize;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Append(AT **arrp, ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    if (!*arrp) {\t\t\t\t\t\t\t\t\\\n\tAT##_Resize(arrp, 1);\t\t\t\t\t\t\t\\\n    } else if ((*arrp)->size == (*arrp)->capacity) {\t\t\t\t\\\n\tAT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2);\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    (*arrp)->buf[(*arrp)->size++] = *elem;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_PopBack(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return arr->size -= 1;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Get(const AT *arr, size_t at)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(at < AT##_Size(arr));\t\t\t\t\t\t\\\n    return (ElemType *) &arr->buf[at];\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Set(AT *arr, size_t at, ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(at < AT##_Size(arr));\t\t\t\t\t\t\\\n    arr->buf[at] = *elem;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Free(AT **arrp)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    AT##_Resize(arrp, 0);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic Tcl_Size\t\t\t\t\t\t\t\t\t\\\nAT##_Find(const AT *arr, const ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    if (arr) {\t\t\t\t\t\t\t\t\t\\\n\tconst ElemType *buf = arr->buf;\t\t\t\t\t\t\\\n\tsize_t i;\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < arr->size; ++i) {\t\t\t\t\t\\\n\t    if (memcmp(&buf[i], elem, sizeof(ElemType)) == 0) {\t\t\t\\\n\t\treturn (Tcl_Size) i;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    return -1;\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nAT##_Contains(const AT *arr, const ElemType *elem)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return AT##_Find(arr, elem) != -1;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n/* ------------------------------------------------------------------------- */\n\f\n#define TK_PTR_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */\t\t\\\n/* ------------------------------------------------------------------------- */\t\\\ntypedef struct AT {\t\t\t\t\t\t\t\t\\\n    size_t size;\t\t\t\t\t\t\t\t\\\n    size_t capacity;\t\t\t\t\t\t\t\t\\\n    ElemType *buf[1];\t\t\t\t\t\t\t\t\\\n} AT;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_ElemSize(void)\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return sizeof(ElemType);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_BufferSize(size_t numElems)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return numElems*sizeof(ElemType *);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nAT##_IsEmpty(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return !arr || arr->size == 0;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType **\t\t\t\t\t\t\t\t\\\nAT##_First(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->buf : NULL;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType **\t\t\t\t\t\t\t\t\\\nAT##_Last(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->buf + arr->size : NULL;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Front(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return arr->buf[0];\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Back(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return arr->buf[arr->size - 1];\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_Size(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->size : 0;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_Capacity(const AT *arr)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    return arr ? arr->capacity : 0;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Resize(AT **arrp, size_t newCapacity)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    assert(!*arrp || (*arrp)->size != 0xdeadbeef);\t\t\t\t\\\n    if (newCapacity == 0) {\t\t\t\t\t\t\t\\\n\tassert(!*arrp || ((*arrp)->size = 0xdeadbeef));\t\t\t\t\\\n\tTcl_Free(*arrp);\t\t\t\t\t\t\t\t\\\n\t*arrp = NULL;\t\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\t\\\n\tint init = *arrp == NULL;\t\t\t\t\t\t\\\n\tsize_t memSize = AT##_BufferSize(newCapacity - 1) + sizeof(AT);\t\t\\\n\t*arrp = (AT *)Tcl_Realloc(*arrp, memSize);\t\t\t\t\t\\\n\tif (init) {\t\t\t\t\t\t\t\t\\\n\t    (*arrp)->size = 0;\t\t\t\t\t\t\t\\\n\t} else if (newCapacity < (*arrp)->size) {\t\t\t\t\\\n\t    (*arrp)->size = newCapacity;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\t(*arrp)->capacity = newCapacity;\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Clear(AT *arr, size_t from, size_t to)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(arr->size != 0xdeadbeef);\t\t\t\t\t\t\\\n    assert(to <= AT##_Capacity(arr));\t\t\t\t\t\t\\\n    assert(from <= to);\t\t\t\t\t\t\t\t\\\n    memset(arr->buf + from, 0, AT##_BufferSize(to - from));\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_ResizeAndClear(AT **arrp, size_t newCapacity)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    size_t oldCapacity;\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    oldCapacity = *arrp ? (*arrp)->capacity : 0;\t\t\t\t\\\n    AT##_Resize(arrp, newCapacity);\t\t\t\t\t\t\\\n    if (newCapacity > oldCapacity) {\t\t\t\t\t\t\\\n\tAT##_Clear(*arrp, oldCapacity, newCapacity);\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_SetSize(AT *arr, size_t newSize)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(newSize <= AT##_Capacity(arr));\t\t\t\t\t\\\n    arr->size = newSize;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Append(AT **arrp, ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arrp);\t\t\t\t\t\t\t\t\\\n    if (!*arrp) {\t\t\t\t\t\t\t\t\\\n\tAT##_Resize(arrp, 1);\t\t\t\t\t\t\t\\\n    } else if ((*arrp)->size == (*arrp)->capacity) {\t\t\t\t\\\n\tAT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2);\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    (*arrp)->buf[(*arrp)->size++] = elem;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nAT##_PopBack(AT *arr)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!AT##_IsEmpty(arr));\t\t\t\t\t\t\t\\\n    return arr->size -= 1;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic ElemType *\t\t\t\t\t\t\t\t\\\nAT##_Get(const AT *arr, size_t at)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(at < AT##_Size(arr));\t\t\t\t\t\t\\\n    return arr->buf[at];\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Set(AT *arr, size_t at, ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(arr);\t\t\t\t\t\t\t\t\\\n    assert(at < AT##_Size(arr));\t\t\t\t\t\t\\\n    arr->buf[at] = elem;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nAT##_Free(AT **arrp)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    AT##_Resize(arrp, 0);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic Tcl_Size\t\t\t\t\t\t\t\t\t\\\nAT##_Find(const AT *arr, const ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!arr || arr->size != 0xdeadbeef);\t\t\t\t\t\\\n    if (arr) {\t\t\t\t\t\t\t\t\t\\\n\tElemType *const *buf = arr->buf;\t\t\t\t\t\\\n\tsize_t i;\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < arr->size; ++i) {\t\t\t\t\t\\\n\t    if (buf[i] == elem) {\t\t\t\t\t\t\\\n\t\treturn (Tcl_Size) i;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    return -1;\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_ARRAY_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nAT##_Contains(const AT *arr, const ElemType *elem)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    return AT##_Find(arr, elem) != -1;\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n/* ------------------------------------------------------------------------- */\n\f\n#endif /* TK_ARRAY_DEFINED */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 105\n * End:\n * vi:set ts=8 sw=4:\n */\n"
  },
  {
    "path": "generic/tkAtom.c",
    "content": "/*\n * tkAtom.c --\n *\n *\tThis file manages a cache of X Atoms in order to avoid interactions\n *\twith the X server. It's much like the Xmu routines, except it has a\n *\tcleaner interface (caller doesn't have to provide permanent storage\n *\tfor atom names, for example).\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The following are a list of the predefined atom strings. They should match\n * those found in xatom.h\n */\n\nstatic const char *const atomNameArray[] = {\n    \"PRIMARY\",\t\t\"SECONDARY\",\t\t\"ARC\",\n    \"ATOM\",\t\t\"BITMAP\",\t\t\"CARDINAL\",\n    \"COLORMAP\",\t\t\"CURSOR\",\t\t\"CUT_BUFFER0\",\n    \"CUT_BUFFER1\",\t\"CUT_BUFFER2\",\t\t\"CUT_BUFFER3\",\n    \"CUT_BUFFER4\",\t\"CUT_BUFFER5\",\t\t\"CUT_BUFFER6\",\n    \"CUT_BUFFER7\",\t\"DRAWABLE\",\t\t\"FONT\",\n    \"INTEGER\",\t\t\"PIXMAP\",\t\t\"POINT\",\n    \"RECTANGLE\",\t\"RESOURCE_MANAGER\",\t\"RGB_COLOR_MAP\",\n    \"RGB_BEST_MAP\",\t\"RGB_BLUE_MAP\",\t\t\"RGB_DEFAULT_MAP\",\n    \"RGB_GRAY_MAP\",\t\"RGB_GREEN_MAP\",\t\"RGB_RED_MAP\",\n    \"STRING\",\t\t\"VISUALID\",\t\t\"WINDOW\",\n    \"WM_COMMAND\",\t\"WM_HINTS\",\t\t\"WM_CLIENT_MACHINE\",\n    \"WM_ICON_NAME\",\t\"WM_ICON_SIZE\",\t\t\"WM_NAME\",\n    \"WM_NORMAL_HINTS\",\t\"WM_SIZE_HINTS\",\t\"WM_ZOOM_HINTS\",\n    \"MIN_SPACE\",\t\"NORM_SPACE\",\t\t\"MAX_SPACE\",\n    \"END_SPACE\",\t\"SUPERSCRIPT_X\",\t\"SUPERSCRIPT_Y\",\n    \"SUBSCRIPT_X\",\t\"SUBSCRIPT_Y\",\t\t\"UNDERLINE_POSITION\",\n    \"UNDERLINE_THICKNESS\", \"STRIKEOUT_ASCENT\",\t\"STRIKEOUT_DESCENT\",\n    \"ITALIC_ANGLE\",\t\"X_HEIGHT\",\t\t\"QUAD_WIDTH\",\n    \"WEIGHT\",\t\t\"POINT_SIZE\",\t\t\"RESOLUTION\",\n    \"COPYRIGHT\",\t\"NOTICE\",\t\t\"FONT_NAME\",\n    \"FAMILY_NAME\",\t\"FULL_NAME\",\t\t\"CAP_HEIGHT\",\n    \"WM_CLASS\",\t\t\"WM_TRANSIENT_FOR\",\n    NULL\n};\n\n/*\n * Forward references to functions defined in this file:\n */\n\nstatic void\tAtomInit(TkDisplay *dispPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_InternAtom --\n *\n *\tGiven a string, produce the equivalent X atom. This function is\n *\tequivalent to XInternAtom, except that it keeps a local cache of\n *\tatoms. Once a name is known, the server need not be contacted again\n *\tfor that name.\n *\n * Results:\n *\tThe return value is the Atom corresponding to name.\n *\n * Side effects:\n *\tA new entry may be added to the local atom cache.\n *\n *--------------------------------------------------------------\n */\n\nAtom\nTk_InternAtom(\n    Tk_Window tkwin,\t\t/* Window token; map name to atom for this\n\t\t\t\t * window's display. */\n    const char *name)\t\t/* Name to turn into atom. */\n{\n    TkDisplay *dispPtr;\n    Tcl_HashEntry *hPtr;\n    int isNew;\n\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    if (!dispPtr->atomInit) {\n\tAtomInit(dispPtr);\n    }\n\n    hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);\n    if (isNew) {\n\tTcl_HashEntry *hPtr2;\n\tAtom atom;\n\n\tatom = XInternAtom(dispPtr->display, name, False);\n\tTcl_SetHashValue(hPtr, INT2PTR(atom));\n\thPtr2 = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);\n\tTcl_SetHashValue(hPtr2, Tcl_GetHashKey(&dispPtr->nameTable, hPtr));\n    }\n    return (Atom)PTR2INT(Tcl_GetHashValue(hPtr));\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetAtomName --\n *\n *\tThis function is equivalent to XGetAtomName except that it uses the\n *\tlocal atom cache to avoid contacting the server.\n *\n * Results:\n *\tThe return value is a character string corresponding to the atom given\n *\tby \"atom\". This string's storage space is static: it need not be freed\n *\tby the caller, and should not be modified by the caller. If \"atom\"\n *\tdoesn't exist on tkwin's display, then the string \"?bad atom?\"  is\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_GetAtomName(\n    Tk_Window tkwin,\t\t/* Window token; map atom to name relative to\n\t\t\t\t * this window's display. */\n    Atom atom)\t\t\t/* Atom whose name is wanted. */\n{\n    TkDisplay *dispPtr;\n    Tcl_HashEntry *hPtr;\n\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    if (!dispPtr->atomInit) {\n\tAtomInit(dispPtr);\n    }\n\n    hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom));\n    if (hPtr == NULL) {\n\tconst char *name;\n\tTk_ErrorHandler handler;\n\tint isNew;\n\tchar *mustFree = NULL;\n\n\thandler = Tk_CreateErrorHandler(dispPtr->display, BadAtom, -1, -1,\n\t\tNULL, NULL);\n\tname = mustFree = XGetAtomName(dispPtr->display, atom);\n\tif (name == NULL) {\n\t    name = \"?bad atom?\";\n\t}\n\tTk_DeleteErrorHandler(handler);\n\thPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);\n\tTcl_SetHashValue(hPtr, INT2PTR(atom));\n\tif (mustFree) {\n\t    XFree(mustFree);\n\t}\n\tname = (const char *)Tcl_GetHashKey(&dispPtr->nameTable, hPtr);\n\thPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);\n\tTcl_SetHashValue(hPtr, (char *)name);\n    }\n    return (const char *)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * AtomInit --\n *\n *\tInitialize atom-related information for a display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTables get initialized, etc. etc..\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nAtomInit(\n    TkDisplay *dispPtr)/* Display to initialize. */\n{\n    Tcl_HashEntry *hPtr;\n    Atom atom;\n\n    dispPtr->atomInit = 1;\n    Tcl_InitHashTable(&dispPtr->nameTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&dispPtr->atomTable, TCL_ONE_WORD_KEYS);\n\n    for (atom = 1; atom <= XA_LAST_PREDEFINED; atom++) {\n\tconst char *name;\n\tint isNew;\n\n\thPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom));\n\tif (hPtr != NULL) {\n\t    continue;\n\t}\n\n\tname = atomNameArray[atom - 1];\n\thPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);\n\tTcl_SetHashValue(hPtr, INT2PTR(atom));\n\tname = (const char *)Tcl_GetHashKey(&dispPtr->nameTable, hPtr);\n\thPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);\n\tTcl_SetHashValue(hPtr, (char *)name);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkBind.c",
    "content": "/*\n * tkBind.c --\n *\n *\tThis file provides functions that associate Tcl commands with X events\n *\tor sequences of X events.\n *\n * Copyright © 1989-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998 Scriptics Corporation.\n * Copyright © 2018-2019 Gregor Cramer.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkDList.h\"\n#include \"tkArray.h\"\n\n#if defined(_WIN32)\n#include \"tkWinInt.h\"\n#elif defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#else /* if defined(__unix__) */\n#include \"tkUnixInt.h\"\n#endif\n\n#ifdef NDEBUG\n# define DEBUG(expr)\n#else\n# define DEBUG(expr) expr\n#endif\n\n#define SIZE_OF_ARRAY(arr) (sizeof(arr)/sizeof(arr[0]))\n\n/*\n * File structure:\n *\n * Structure definitions and static variables.\n *\n * Init/Free this package.\n *\n * Tcl \"bind\" command (actually located in tkCmds.c) core implementation, plus helpers.\n *\n * Tcl \"event\" command implementation, plus helpers.\n *\n * Package-specific common helpers.\n *\n * Non-package-specific helpers.\n */\n\n/*\n * The output for motion events is of the type <B1-Motion>. This can be changed to become\n * <Motion-1> instead by setting PRINT_SHORT_MOTION_SYNTAX to 1, however this would be a\n * backwards incompatibility.\n */\n\n#ifndef PRINT_SHORT_MOTION_SYNTAX\n# define PRINT_SHORT_MOTION_SYNTAX 0 /* set to 1 if wanted */\n#endif\n\n/*\n * For debugging only, normally set to zero.\n */\n\n#ifdef SUPPORT_DEBUGGING\n# undef SUPPORT_DEBUGGING\n#endif\n#define SUPPORT_DEBUGGING 0\n\n/*\n * Test validity of PSEntry items.\n */\n\n# define TEST_PSENTRY(psPtr) psPtr->number != 0xdeadbeef\n# define MARK_PSENTRY(psPtr) psPtr->number = 0xdeadbeef\n\n/*\n * The following union is used to hold the detail information from an XEvent\n * (including Tk's XVirtualEvent extension).\n */\n\ntypedef KeySym Info;\n\ntypedef union {\n    Info info;\t\t/* This either corresponds to xkey.keycode, or to xbutton.button,\n\t\t\t * or is meaningless, depending on event type. */\n    Tk_Uid name;\t/* Tk_Uid of virtual event. */\n} Detail;\n\n/*\n * We need an extended event definition.\n */\n\ntypedef struct {\n    XEvent xev;\t\t/* The original event from server. */\n    Detail detail;\t/* Additional information (for hashing). */\n    unsigned countAny;\t/* Count of multi-events, like multi-clicks, or repeated key pressing,\n\t\t\t * this count does not depend on detail (keySym or button). */\n    unsigned countDetailed;\n\t\t\t/* Count of multi-events, like multi-clicks, or repeated key pressing,\n\t\t\t * this count considers the detail (keySym or button). */\n} Event;\n\nstruct PatSeq; /* forward declaration */\n\n/* We need this array for bookkeeping the last matching modifier mask per pattern. */\nTK_ARRAY_DEFINE(PSModMaskArr, unsigned);\n\ntypedef struct PSEntry {\n    TK_DLIST_LINKS(PSEntry);\t/* Makes this struct a doubly linked list; must be first entry. */\n    Window window;\t\t/* Window of last match. */\n    struct PatSeq* psPtr;\t/* Pointer to pattern sequence. */\n    PSModMaskArr *lastModMaskArr;\n\t\t\t\t/* Last matching modifier mask per pattern (except last pattern).\n\t\t\t\t * Only needed if pattern sequence is not single (more than one\n\t\t\t\t * pattern), and if one of these patterns contains a non-zero\n\t\t\t\t * modifier mask. */\n    unsigned count;\t\t/* Only promote to next level if this count has reached count of\n\t\t\t\t * pattern. */\n    unsigned expired:1;\t\t/* Whether this entry is expired, this means it has to be removed\n\t\t\t\t * from promotion list. */\n    unsigned keepIt:1;\t\t/* Whether to keep this entry, even if expired. */\n} PSEntry;\n\n/* Defining the whole PSList_* stuff (list of PSEntry items). */\nTK_DLIST_DEFINE(PSList, PSEntry);\n\n/* Don't keep larger arrays of modifier masks inside PSEntry. */\n#define MAX_MOD_MASK_ARR_SIZE 8\n\n/*\n * Maps and lookup tables from an event to a list of patterns that match that event.\n */\n\ntypedef struct {\n    Tcl_HashTable patternTable;\t/* Keys are PatternTableKey structs, values are (PatSeq *). */\n    Tcl_HashTable listTable;\t/* Keys are PatternTableKey structs, values are (PSList *). */\n    PSList entryPool;\t\t/* Contains free (unused) list items. */\n    unsigned number;\t\t/* Needed for enumeration of pattern sequences. */\n} LookupTables;\n\n/*\n * The structure below represents a binding table. A binding table represents\n * a domain in which event bindings may occur. It includes a space of objects\n * relative to which events occur (usually windows, but not always), a history\n * of recent events in the domain, and a set of mappings that associate\n * particular Tcl commands with sequences of events in the domain. Multiple\n * binding tables may exist at once, either because there are multiple\n * applications open, or because there are multiple domains within an\n * application with separate event bindings for each (for example, each canvas\n * widget has a separate binding table for associating events with the items\n * in the canvas).\n */\n\n/* Defining the whole PromArr_* stuff (array of PSList entries) */\nTK_ARRAY_DEFINE(PromArr, PSList);\n\ntypedef struct Tk_BindingTable_ {\n    Event eventInfo[TK_LASTEVENT];\n\t\t\t\t/* Containing the most recent event for every event type. */\n    PromArr *promArr;\t\t/* Contains the promoted pattern sequences. */\n    Event *curEvent;\t\t/* Pointing to most recent event. */\n    unsigned curModMask;\t\t/* Containing the current modifier mask. */\n    LookupTables lookupTables;\t/* Containing hash tables for fast lookup. */\n    Tcl_HashTable objectTable;\t/* Used to map from an object to a list of patterns associated with\n\t\t\t\t * that object. Keys are ClientData, values are (PatSeq *). */\n    Tcl_Interp *interp;\t\t/* Interpreter in which commands are executed. */\n} BindingTable;\n\n/*\n * The following structure represents virtual event table. A virtual event\n * table provides a way to map from platform-specific physical events such as\n * button clicks or key presses to virtual events such as <<Paste>>,\n * <<Close>>, or <<ScrollWindow>>.\n *\n * A virtual event is usually never part of the event stream, but instead is\n * synthesized inline by matching low-level events. However, a virtual event\n * may be generated by platform-specific code or by Tcl commands. In that case,\n * no lookup of the virtual event will need to be done using this table,\n * because the virtual event is actually in the event stream.\n */\n\ntypedef struct {\n    LookupTables lookupTables;\t/* Providing fast lookup tables to lists of pattern sequences. */\n    Tcl_HashTable nameTable;\t/* Used to map a virtual event name to the array of physical events\n\t\t\t\t * that can trigger it. Keys are the Tk_Uid names of the virtual\n\t\t\t\t * events, values are PhysOwned structs. */\n} VirtualEventTable;\n\n/*\n * The following structure is used as a key in a patternTable for both binding\n * tables and a virtual event tables.\n *\n * In a binding table, the object field corresponds to the binding tag for the\n * widget whose bindings are being accessed.\n *\n * In a virtual event table, the object field is always NULL. Virtual events\n * are a global definiton and are not tied to a particular binding tag.\n *\n * The same key is used for both types of pattern tables so that the helper\n * functions that traverse and match patterns will work for both binding\n * tables and virtual event tables.\n */\n\ntypedef struct {\n    void *object;\t\t/* For binding table, identifies the binding tag of the object\n\t\t\t\t * (or class of objects) relative to which the event occurred.\n\t\t\t\t * For virtual event table, always NULL. */\n    unsigned type;\t\t/* Type of event (from X). */\n    Detail detail;\t\t/* Additional information, such as keysym, button, Tk_Uid, or zero\n\t\t\t\t * if nothing additional. */\n} PatternTableKey;\n\n/*\n * The following structure defines a pattern, which is matched against X\n * events as part of the process of converting X events into Tcl commands.\n *\n * For technical reasons we do not use 'union Detail', although this would\n * be possible, instead 'info' and 'name' are both included.\n */\n\ntypedef struct {\n    unsigned eventType;\t\t/* Type of X event, e.g. ButtonPress. */\n    unsigned count;\t\t/* Multi-event count, e.g. double-clicks, triple-clicks, etc. */\n    unsigned modMask;\t\t/* Mask of modifiers that must be present (zero means no modifiers\n\t\t\t\t * are required). */\n    Info info;\t\t\t/* Additional information that must match event. Normally this is zero,\n\t\t\t\t * meaning no additional information must match. For KeyPress and\n\t\t\t\t * KeyRelease events, it may be specified to select a particular\n\t\t\t\t * keystroke (zero means any keystrokes). For button events, specifies\n\t\t\t\t * a particular button (zero means any buttons are OK). */\n    Tk_Uid name;\t\t/* Specifies the Tk_Uid of the virtual event name. NULL if not a\n\t\t\t\t * virtual event. */\n} TkPattern;\n\n/*\n * The following structure keeps track of all the virtual events that are\n * associated with a particular physical event. It is pointed to by the 'owners'\n * field in a PatSeq in the patternTable of a virtual event table.\n */\n\nTK_PTR_ARRAY_DEFINE(VirtOwners, Tcl_HashEntry); /* define array of hash entries */\n\n/*\n * The following structure defines a pattern sequence, which consists of one\n * or more patterns. In order to trigger, a pattern sequence must match the\n * most recent X events (first pattern to most recent event, next pattern to\n * next event, and so on). It is used as the hash value in a patternTable for\n * both binding tables and virtual event tables.\n *\n * In a binding table, it is the sequence of physical events that make up a\n * binding for an object.\n *\n * In a virtual event table, it is the sequence of physical events that define\n * a virtual event.\n *\n * The same structure is used for both types of pattern tables so that the\n * helper functions that traverse and match patterns will work for both\n * binding tables and virtual event tables.\n */\n\ntypedef struct PatSeq {\n    unsigned numPats;\t\t/* Number of patterns in sequence (usually 1). */\n    unsigned count;\t\t/* Total number of repetition counts, summed over count in TkPattern. */\n    unsigned number;\t\t/* Needed for the decision whether a binding is less recently defined\n\t\t\t\t * than another, it is guaranteed that the most recently bound event\n\t\t\t\t * has the highest number. */\n    unsigned added:1;\t\t/* Is this pattern sequence already added to lookup table? */\n    unsigned modMaskUsed:1;\t/* Does at least one pattern contain a non-zero modifier mask? */\n    DEBUG(unsigned owned:1;)\t/* For debugging purposes. */\n    char *script;\t\t/* Binding script to evaluate when sequence matches (Tcl_Alloc()ed) */\n    Tcl_Obj* object;\t\t/* Token for object with which binding is associated. For virtual\n\t\t\t\t * event table this is NULL. */\n    struct PatSeq *nextSeqPtr;\t/* Next in list of all pattern sequences that have the same initial\n\t\t\t\t * pattern. NULL means end of list. */\n    Tcl_HashEntry *hPtr;\t/* Pointer to hash table entry for the initial pattern. This is the\n\t\t\t\t * head of the list of which nextSeqPtr forms a part. */\n    union {\n\tVirtOwners *owners;\t/* In a binding table it has no meaning. In a virtual event table,\n\t\t\t\t * identifies the array of virtual events that can be triggered\n\t\t\t\t * by this event. */\n\tstruct PatSeq *nextObj;\t/* In a binding table, next in list of all pattern sequences for\n\t\t\t\t * the same object (NULL for end of list). Needed to implement\n\t\t\t\t * Tk_DeleteAllBindings. In a virtual event table it has no meaning. */\n    } ptr;\n    TkPattern pats[1];\t\t/* Array of \"numPats\" patterns. Only one element is declared here\n\t\t\t\t * but in actuality enough space will be allocated for \"numPats\"\n\t\t\t\t * patterns (but usually 1). */\n} PatSeq;\n\n/*\n * Compute memory size of struct PatSeq with given pattern size.\n * The caller must be sure that pattern size is greater than zero.\n */\n#define PATSEQ_MEMSIZE(numPats) (sizeof(PatSeq) + (numPats - 1)*sizeof(TkPattern))\n\n/*\n * Constants that define how close together two events must be in milliseconds\n * or pixels to be considered close in space or time.\n */\n\n#define NEARBY_PIXELS\t5\n#define NEARBY_MS\t500\n\n/*\n * The following structure is used in the nameTable of a virtual event table\n * to associate a virtual event with all the physical events that can trigger\n * it.\n */\n\nTK_PTR_ARRAY_DEFINE(PhysOwned, PatSeq); /* define array of pattern seqs */\n\n/*\n * One of the following structures exists for each interpreter. This structure\n * keeps track of the current display and screen in the interpreter, so that a\n * command can be invoked whenever the display/screen changes (the command does\n * things like point tk::Priv at a display-specific structure).\n */\n\ntypedef struct {\n    TkDisplay *curDispPtr;\t/* Display for last binding command invoked in this application. */\n    int curScreenIndex;\t\t/* Index of screen for last binding command */\n    unsigned bindingDepth;\t/* Number of active instances of Tk_BindEvent in this application. */\n} ScreenInfo;\n\n/*\n * The following structure keeps track of all the information local to the\n * binding package on a per interpreter basis.\n */\n\ntypedef struct TkBindInfo_ {\n    VirtualEventTable virtualEventTable;\n\t\t\t\t/* The virtual events that exist in this interpreter. */\n    ScreenInfo screenInfo;\t/* Keeps track of the current display and screen, so it can be\n\t\t\t\t * restored after a binding has executed. */\n    int deleted;\t\t/* 1 if the application has been deleted but the structure has been\n\t\t\t\t * preserved. */\n    Time lastEventTime;\t\t/* Needed for time measurement. */\n    Time lastCurrentTime;\t/* Needed for time measurement. */\n} BindInfo;\n\n/*\n * In X11R4 and earlier versions, XStringToKeysym is ridiculously slow. The\n * data structure and hash table below, along with the code that uses them,\n * implement a fast mapping from strings to keysyms. In X11R5 and later\n * releases XStringToKeysym is plenty fast so this stuff isn't needed. The\n * #define REDO_KEYSYM_LOOKUP is normally undefined, so that XStringToKeysym\n * gets used. It can be set in the Makefile to enable the use of the hash\n * table below.\n */\n\n#ifdef REDO_KEYSYM_LOOKUP\ntypedef struct {\n    const char *name;\t\t/* Name of keysym. */\n    KeySym value;\t\t/* Numeric identifier for keysym. */\n} KeySymInfo;\nstatic const KeySymInfo keyArray[] = {\n#ifndef lint\n#include \"ks_names.h\"\n#endif\n    {NULL, 0}\n};\nstatic Tcl_HashTable keySymTable;\t/* keyArray hashed by keysym value. */\nstatic Tcl_HashTable nameTable;\t\t/* keyArray hashed by keysym name. */\n#endif /* REDO_KEYSYM_LOOKUP */\n\n/*\n * A hash table is kept to map from the string names of event modifiers to\n * information about those modifiers. The structure for storing this\n * information, and the hash table built at initialization time, are defined\n * below.\n */\n\ntypedef struct {\n    const char *name;\t/* Name of modifier. */\n    unsigned mask;\t/* Button/modifier mask value, such as Button1Mask. */\n    unsigned flags;\t/* Various flags; see below for definitions. */\n} ModInfo;\n\n/*\n * Flags for ModInfo structures:\n *\n * DOUBLE -\t\tNon-zero means duplicate this event, e.g. for double-clicks.\n * TRIPLE -\t\tNon-zero means triplicate this event, e.g. for triple-clicks.\n * QUADRUPLE -\t\tNon-zero means quadruple this event, e.g. for 4-fold-clicks.\n * MULT_CLICKS -\tCombination of all the above.\n */\n\n#define DOUBLE\t\t(1<<0)\n#define TRIPLE\t\t(1<<1)\n#define QUADRUPLE\t(1<<2)\n#define MULT_CLICKS\t(DOUBLE|TRIPLE|QUADRUPLE)\n\nstatic const ModInfo modArray[] = {\n    {\"Control\",\t\tControlMask,\t0},\n    {\"Shift\",\t\tShiftMask,\t0},\n    {\"Lock\",\t\tLockMask,\t0},\n    {\"Meta\",\t\tMETA_MASK,\t0},\n#ifndef TK_NO_DEPRECATED\n    {\"M\",\t\tMETA_MASK,\t0},\n#endif\n    {\"Alt\",\t\tALT_MASK,\t0},\n    {\"Extended\",\tEXTENDED_MASK,\t0},\n    {\"B1\",\t\tButton1Mask,\t0},\n    {\"Button1\",\t\tButton1Mask,\t0},\n    {\"B2\",\t\tButton2Mask,\t0},\n    {\"Button2\",\t\tButton2Mask,\t0},\n    {\"B3\",\t\tButton3Mask,\t0},\n    {\"Button3\",\t\tButton3Mask,\t0},\n    {\"B4\",\t\tButton4Mask,\t0},\n    {\"Button4\",\t\tButton4Mask,\t0},\n    {\"B5\",\t\tButton5Mask,\t0},\n    {\"Button5\",\t\tButton5Mask,\t0},\n    {\"B6\",\t\tButton6Mask,\t0},\n    {\"Button6\",\t\tButton6Mask,\t0},\n    {\"B7\",\t\tButton7Mask,\t0},\n    {\"Button7\",\t\tButton7Mask,\t0},\n    {\"B8\",\t\tButton8Mask,\t0},\n    {\"Button8\",\t\tButton8Mask,\t0},\n    {\"B9\",\t\tButton9Mask,\t0},\n    {\"Button9\",\t\tButton9Mask,\t0},\n    {\"Mod1\",\t\tMod1Mask,\t0},\n    {\"M1\",\t\tMod1Mask,\t0},\n#ifdef MAC_OSX_TK\n    {\"Command\",\t\tMod1Mask,\t0},\n#elif defined (_WIN32)\n    {\"Command\",\t\tControlMask,\t0},\n#else\n    {\"Command\",\t\tMETA_MASK,\t0},\n#endif\n    {\"Mod2\",\t\tMod2Mask,\t0},\n    {\"M2\",\t\tMod2Mask,\t0},\n#ifdef MAC_OSX_TK\n    {\"Option\",\t\tMod2Mask,\t0},\n#else\n    {\"Option\",\t\tALT_MASK,\t0},\n#endif\n    {\"Mod3\",\t\tMod3Mask,\t0},\n    {\"M3\",\t\tMod3Mask,\t0},\n    {\"Num\",\t\tMod3Mask,\t0},\n    {\"Mod4\",\t\tMod4Mask,\t0},\n    {\"Fn\",\t\tMod4Mask,\t0},\n    {\"M4\",\t\tMod4Mask,\t0},\n    {\"Mod5\",\t\tMod5Mask,\t0},\n    {\"M5\",\t\tMod5Mask,\t0},\n    {\"Double\",\t\t0,\t\tDOUBLE},\n    {\"Triple\",\t\t0,\t\tTRIPLE},\n    {\"Quadruple\",\t0,\t\tQUADRUPLE},\n    {\"Any\",\t\t0,\t\t0},\t/* Ignored: historical relic */\n    {NULL,\t\t0,\t\t0}\n};\nstatic Tcl_HashTable modTable;\n\n/*\n * This module also keeps a hash table mapping from event names to information\n * about those events. The structure, an array to use to initialize the hash\n * table, and the hash table are all defined below.\n */\n\ntypedef struct {\n    const char *name;\t/* Name of event. */\n    unsigned type;\t/* Event type for X, such as ButtonPress. */\n    unsigned eventMask;\t/* Mask bits (for XSelectInput) for this event type. */\n} EventInfo;\n\n/*\n * Note: some of the masks below are an OR-ed combination of several masks.\n * This is necessary because X doesn't report up events unless you also ask\n * for down events. Also, X doesn't report button state in motion events\n * unless you've asked about button events.\n */\n\nstatic const EventInfo eventArray[] = {\n    {\"Key\",\t\tKeyPress,\t\tKeyPressMask},\n#ifndef TK_NO_DEPRECATED\n    {\"KeyPress\",\tKeyPress,\t\tKeyPressMask},\n#endif\n    {\"KeyRelease\",\tKeyRelease,\t\tKeyPressMask|KeyReleaseMask},\n    {\"Button\",\t\tButtonPress,\t\tButtonPressMask},\n#ifndef TK_NO_DEPRECATED\n    {\"ButtonPress\",\tButtonPress,\t\tButtonPressMask},\n#endif\n    {\"ButtonRelease\",\tButtonRelease,\t\tButtonPressMask|ButtonReleaseMask},\n    {\"Motion\",\t\tMotionNotify,\t\tButtonPressMask|PointerMotionMask},\n    {\"Enter\",\t\tEnterNotify,\t\tEnterWindowMask},\n    {\"Leave\",\t\tLeaveNotify,\t\tLeaveWindowMask},\n    {\"FocusIn\",\t\tFocusIn,\t\tFocusChangeMask},\n    {\"FocusOut\",\tFocusOut,\t\tFocusChangeMask},\n    {\"Expose\",\t\tExpose,\t\t\tExposureMask},\n    {\"Visibility\",\tVisibilityNotify,\tVisibilityChangeMask},\n    {\"Destroy\",\t\tDestroyNotify,\t\tStructureNotifyMask},\n    {\"Unmap\",\t\tUnmapNotify,\t\tStructureNotifyMask},\n    {\"Map\",\t\tMapNotify,\t\tStructureNotifyMask},\n    {\"Reparent\",\tReparentNotify,\t\tStructureNotifyMask},\n    {\"Configure\",\tConfigureNotify,\tStructureNotifyMask},\n    {\"Gravity\",\t\tGravityNotify,\t\tStructureNotifyMask},\n    {\"Circulate\",\tCirculateNotify,\tStructureNotifyMask},\n    {\"Property\",\tPropertyNotify,\t\tPropertyChangeMask},\n    {\"Colormap\",\tColormapNotify,\t\tColormapChangeMask},\n    {\"Activate\",\tActivateNotify,\t\tActivateMask},\n    {\"Deactivate\",\tDeactivateNotify,\tActivateMask},\n    {\"MouseWheel\",\tMouseWheelEvent,\tMouseWheelMask},\n    {\"TouchpadScroll\",  TouchpadScroll,\t TouchpadScrollMask},\n    {\"CirculateRequest\", CirculateRequest,\tSubstructureRedirectMask},\n    {\"ConfigureRequest\", ConfigureRequest,\tSubstructureRedirectMask},\n    {\"Create\",\t\tCreateNotify,\t\tSubstructureNotifyMask},\n    {\"MapRequest\",\tMapRequest,\t\tSubstructureRedirectMask},\n    {\"ResizeRequest\",\tResizeRequest,\t\tResizeRedirectMask},\n    {NULL,\t\t0,\t\t\t0}\n};\nstatic Tcl_HashTable eventTable;\n\nstatic int eventArrayIndex[TK_LASTEVENT];\n\n/*\n * The defines and table below are used to classify events into various\n * groups. The reason for this is that logically identical fields (e.g.\n * \"state\") appear at different places in different types of events. The\n * classification masks can be used to figure out quickly where to extract\n * information from events.\n */\n\n#define KEY\t\t\t(1<<0)\n#define BUTTON\t\t\t(1<<1)\n#define MOTION\t\t\t(1<<2)\n#define CROSSING\t\t(1<<3)\n#define FOCUS\t\t\t(1<<4)\n#define EXPOSE\t\t\t(1<<5)\n#define VISIBILITY\t\t(1<<6)\n#define CREATE\t\t\t(1<<7)\n#define DESTROY\t\t\t(1<<8)\n#define UNMAP\t\t\t(1<<9)\n#define MAP\t\t\t(1<<10)\n#define REPARENT\t\t(1<<11)\n#define CONFIG\t\t\t(1<<12)\n#define GRAVITY\t\t\t(1<<13)\n#define CIRC\t\t\t(1<<14)\n#define PROP\t\t\t(1<<15)\n#define COLORMAP\t\t(1<<16)\n#define VIRTUAL\t\t\t(1<<17)\n#define ACTIVATE\t\t(1<<18)\n#define WHEEL\t\t\t(1<<19)\n#define\tMAPREQ\t\t\t(1<<20)\n#define\tCONFIGREQ\t\t(1<<21)\n#define\tRESIZEREQ\t\t(1<<22)\n#define CIRCREQ\t\t\t(1<<23)\n\n/*\n * These structs agree with xkey for the fields type, serial, send_event, display,\n * window, root, subwindow, time, x, y, x_root, and y_root. So when accessing\n * these fields we may pretend that we are using a struct xkey.\n */\n\n#define HAS_XKEY_HEAD (KEY|BUTTON|MOTION|VIRTUAL|CROSSING|WHEEL)\n\n/*\n * The xcrossing struct puts the state field in a different location, but the other\n * events above agree on where state is located.\n */\n\n#define HAS_XKEY_HEAD_AND_STATE (KEY|BUTTON|MOTION|VIRTUAL|WHEEL)\n\n/*\n * Event types which support -warp.\n */\n\n#define CAN_WARP (KEY|BUTTON|MOTION|WHEEL)\n\nstatic const int flagArray[TK_LASTEVENT] = {\n   /* Not used */\t\t0,\n   /* Not used */\t\t0,\n   /* KeyPress */\t\tKEY,\n   /* KeyRelease */\t\tKEY,\n   /* ButtonPress */\t\tBUTTON,\n   /* ButtonRelease */\t\tBUTTON,\n   /* MotionNotify */\t\tMOTION,\n   /* EnterNotify */\t\tCROSSING,\n   /* LeaveNotify */\t\tCROSSING,\n   /* FocusIn */\t\tFOCUS,\n   /* FocusOut */\t\tFOCUS,\n   /* KeymapNotify */\t\t0,\n   /* Expose */\t\t\tEXPOSE,\n   /* GraphicsExpose */\t\tEXPOSE,\n   /* NoExpose */\t\t0,\n   /* VisibilityNotify */\tVISIBILITY,\n   /* CreateNotify */\t\tCREATE,\n   /* DestroyNotify */\t\tDESTROY,\n   /* UnmapNotify */\t\tUNMAP,\n   /* MapNotify */\t\tMAP,\n   /* MapRequest */\t\tMAPREQ,\n   /* ReparentNotify */\t\tREPARENT,\n   /* ConfigureNotify */\tCONFIG,\n   /* ConfigureRequest */\tCONFIGREQ,\n   /* GravityNotify */\t\tGRAVITY,\n   /* ResizeRequest */\t\tRESIZEREQ,\n   /* CirculateNotify */\tCIRC,\n   /* CirculateRequest */\t0,\n   /* PropertyNotify */\t\tPROP,\n   /* SelectionClear */\t\t0,\n   /* SelectionRequest */\t0,\n   /* SelectionNotify */\t0,\n   /* ColormapNotify */\t\tCOLORMAP,\n   /* ClientMessage */\t\t0,\n   /* MappingNotify */\t\t0,\n   /* VirtualEvent */\t\tVIRTUAL,\n   /* Activate */\t\tACTIVATE,\n   /* Deactivate */\t\tACTIVATE,\n   /* MouseWheel */\t\tWHEEL,\n   /* TouchpadScroll */\t\tWHEEL\n};\n\n/*\n * The following table is used to map between the location where an generated\n * event should be queued and the string used to specify the location.\n */\n\nstatic const TkStateMap queuePosition[] = {\n    {-1,\t\t\"now\"},\n    {TCL_QUEUE_HEAD,\t\"head\"},\n    {TCL_QUEUE_MARK,\t\"mark\"},\n    {TCL_QUEUE_TAIL,\t\"tail\"},\n    {-2,\t\tNULL}\n};\n\n/*\n * The following tables are used as a two-way map between X's internal numeric\n * values for fields in an XEvent and the strings used in Tcl. The tables are\n * used both when constructing an XEvent from user input and when providing\n * data from an XEvent to the user.\n */\n\nstatic const TkStateMap notifyMode[] = {\n    {NotifyNormal,\t\t\"NotifyNormal\"},\n    {NotifyGrab,\t\t\"NotifyGrab\"},\n    {NotifyUngrab,\t\t\"NotifyUngrab\"},\n    {NotifyWhileGrabbed,\t\"NotifyWhileGrabbed\"},\n    {-1, NULL}\n};\n\nstatic const TkStateMap notifyDetail[] = {\n    {NotifyAncestor,\t\t\"NotifyAncestor\"},\n    {NotifyVirtual,\t\t\"NotifyVirtual\"},\n    {NotifyInferior,\t\t\"NotifyInferior\"},\n    {NotifyNonlinear,\t\t\"NotifyNonlinear\"},\n    {NotifyNonlinearVirtual,\t\"NotifyNonlinearVirtual\"},\n    {NotifyPointer,\t\t\"NotifyPointer\"},\n    {NotifyPointerRoot,\t\t\"NotifyPointerRoot\"},\n    {NotifyDetailNone,\t\t\"NotifyDetailNone\"},\n    {-1, NULL}\n};\n\nstatic const TkStateMap circPlace[] = {\n    {PlaceOnTop,\t\"PlaceOnTop\"},\n    {PlaceOnBottom,\t\"PlaceOnBottom\"},\n    {-1, NULL}\n};\n\nstatic const TkStateMap visNotify[] = {\n    {VisibilityUnobscured,\t  \"VisibilityUnobscured\"},\n    {VisibilityPartiallyObscured, \"VisibilityPartiallyObscured\"},\n    {VisibilityFullyObscured,\t  \"VisibilityFullyObscured\"},\n    {-1, NULL}\n};\n\nstatic const TkStateMap configureRequestDetail[] = {\n    {None,\t\"None\"},\n    {Above,\t\"Above\"},\n    {Below,\t\"Below\"},\n    {BottomIf,\t\"BottomIf\"},\n    {TopIf,\t\"TopIf\"},\n    {Opposite,\t\"Opposite\"},\n    {-1, NULL}\n};\n\nstatic const TkStateMap propNotify[] = {\n    {PropertyNewValue,\t\"NewValue\"},\n    {PropertyDelete,\t\"Delete\"},\n    {-1, NULL}\n};\n\nDEBUG(static int countTableItems = 0;)\nDEBUG(static int countEntryItems = 0;)\nDEBUG(static int countListItems = 0;)\nDEBUG(static int countBindItems = 0;)\nDEBUG(static int countSeqItems = 0;)\n\n/*\n * Prototypes for local functions defined in this file:\n */\n\nstatic void\t\tChangeScreen(Tcl_Interp *interp, char *dispName, int screenIndex);\nstatic bool\t\tCreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,\n\t\t\t    char *virtString, const char *eventString);\nstatic int\t\tDeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,\n\t\t\t    char *virtString, const char *eventString);\nstatic void\t\tDeleteVirtualEventTable(VirtualEventTable *vetPtr);\nstatic void\t\tExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr,\n\t\t\t    unsigned scriptCount, Tcl_DString *dsPtr);\nstatic PatSeq *\t\tFindSequence(Tcl_Interp *interp, LookupTables *lookupTables,\n\t\t\t    void *object, const char *eventString, int create,\n\t\t\t    int allowVirtual, unsigned *maskPtr);\nstatic void\t\tGetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr);\nstatic const char *\tGetField(const char *p, char *copy, unsigned size);\nstatic Tcl_Obj *\tGetPatternObj(const PatSeq *psPtr);\nstatic int\t\tGetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,\n\t\t\t    Tcl_Obj *virtName);\nstatic Tk_Uid\t\tGetVirtualEventUid(Tcl_Interp *interp, char *virtString);\nstatic int\t\tHandleEventGenerate(Tcl_Interp *interp, Tk_Window main,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tInitVirtualEventTable(VirtualEventTable *vetPtr);\nstatic PatSeq *\t\tMatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList,\n\t\t\t    PSList *psSuccList, unsigned patIndex, const Event *eventPtr,\n\t\t\t    void *object, PatSeq **physPtrPtr);\nstatic bool\t\tNameToWindow(Tcl_Interp *interp, Tk_Window main,\n\t\t\t    Tcl_Obj *objPtr, Tk_Window *tkwinPtr);\nstatic unsigned\t\tParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,\n\t\t\t    TkPattern *patPtr, unsigned *eventMaskPtr);\nstatic PSList *\t\tGetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,\n\t\t\t    Tcl_Obj *object, int onlyConsiderDetailedEvents);\nstatic void\t\tClearLookupTable(LookupTables *lookupTables, void *object);\nstatic void\t\tClearPromotionLists(Tk_BindingTable bindPtr, void *object);\nstatic PSEntry *\tMakeListEntry(PSList *pool, PatSeq *psPtr, int needModMasks);\nstatic void\t\tRemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr);\nstatic void\t\tRemovePatSeqFromPromotionLists(Tk_BindingTable bindPtr, PatSeq *psPtr);\nstatic PatSeq *\t\tDeletePatSeq(PatSeq *psPtr);\nstatic void\t\tInsertPatSeq(LookupTables *lookupTables, PatSeq *psPtr);\n#if SUPPORT_DEBUGGING\nvoid\t\t\tTkpDumpPS(const PatSeq *psPtr);\nvoid\t\t\tTkpDumpPSList(const PSList *psList);\n#endif\n\f\n/*\n * Some useful helper functions.\n */\n#if SUPPORT_DEBUGGING\nstatic int BindCount = 0;  /* Can be set or queried from Tcl through 'event debug' subcommand. Otherwise not used. */\n#endif\n\nstatic Tcl_Size Max(Tcl_Size a, Tcl_Size b) { return a < b ? b : a; }\nstatic int Abs(int n) { return n < 0 ? -n : n; }\nstatic int IsOdd(int n) { return n & 1; }\n\nstatic int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; }\nstatic int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; }\n\nstatic int\nIsSubsetOf(\n    unsigned lhsMask,\t/* Is this a subset... */\n    unsigned rhsMask)\t/* ...of this bit field? */\n{\n    return (lhsMask & rhsMask) == lhsMask;\n}\n\nstatic const char*\nSkipSpaces(\n    const char* s)\n{\n    assert(s);\n    while (isspace(UCHAR(*s)))\n\t++s;\n    return s;\n}\n\nstatic const char*\nSkipFieldDelims(\n    const char* s)\n{\n    assert(s);\n    while (*s == '-' || isspace(UCHAR(*s))) {\n\t++s;\n    }\n    return s;\n}\n\nstatic unsigned\nGetButtonNumber(\n    const char *field)\n{\n    unsigned button;\n    assert(field);\n    button = (field[0] >= '1' && field[0] <= '9' && field[1] == '\\0') ? (unsigned)(field[0] - '0') : 0;\n    return (button > 3) ? (button + 4) : button;\n}\n\nstatic Time\nCurrentTimeInMilliSecs(void)\n{\n    Tcl_Time now;\n\n    Tcl_GetTime(&now);\n    return ((Time) now.sec)*1000 + ((Time) now.usec)/1000;\n}\n\nstatic Info\nGetInfo(\n    const PatSeq *psPtr,\n    unsigned index)\n{\n    assert(psPtr);\n    assert(index < psPtr->numPats);\n\n    return psPtr->pats[index].info;\n}\n\nstatic unsigned\nGetCount(\n    const PatSeq *psPtr,\n    unsigned index)\n{\n    assert(psPtr);\n    assert(index < psPtr->numPats);\n\n    return psPtr->pats[index].count;\n}\n\nstatic int\nCountSpecialized(\n    const PatSeq *fstMatchPtr,\n    const PatSeq *sndMatchPtr)\n{\n    int fstCount = 0;\n    int sndCount = 0;\n    unsigned i;\n\n    assert(fstMatchPtr);\n    assert(sndMatchPtr);\n\n    for (i = 0; i < fstMatchPtr->numPats; ++i) {\n\tif (GetInfo(fstMatchPtr, i)) { fstCount += GetCount(fstMatchPtr, i); }\n    }\n    for (i = 0; i < sndMatchPtr->numPats; ++i) {\n\tif (GetInfo(sndMatchPtr, i)) { sndCount += GetCount(sndMatchPtr, i); }\n    }\n\n    return sndCount - fstCount;\n}\n\nstatic int\nIsKeyEventType(\n    int eventType)\n{\n    return eventType == KeyPress || eventType == KeyRelease;\n}\n\nstatic int\nIsButtonEventType(\n    unsigned eventType)\n{\n    return eventType == ButtonPress || eventType == ButtonRelease;\n}\n\nstatic int\nMatchEventNearby(\n    const XEvent *lhs,\t/* Previous button event */\n    const XEvent *rhs)\t/* Current button event */\n{\n    assert(lhs);\n    assert(rhs);\n    assert(IsButtonEventType(lhs->type));\n    assert(lhs->type == rhs->type);\n\n    /* assert: lhs->xbutton.time <= rhs->xbutton.time */\n\n    return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time)\n\t    && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root)\n\t    && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root);\n}\n\nstatic int\nMatchEventRepeat(\n    const XKeyEvent *lhs,\t/* Previous key event */\n    const XKeyEvent *rhs)\t/* Current key event */\n{\n    assert(lhs);\n    assert(rhs);\n    assert(IsKeyEventType(lhs->type));\n    assert(lhs->type == rhs->type);\n\n    /* assert: lhs->time <= rhs->time */\n    return lhs->keycode == rhs->keycode && TestNearbyTime(lhs->time, rhs->time);\n}\n\nstatic void\nFreePatSeq(\n    PatSeq *psPtr)\n{\n    assert(psPtr);\n    assert(!psPtr->owned);\n    DEBUG(MARK_PSENTRY(psPtr);)\n    Tcl_Free(psPtr->script);\n    if (!psPtr->object) {\n\tVirtOwners_Free(&psPtr->ptr.owners);\n    }\n    Tcl_Free(psPtr);\n    DEBUG(countSeqItems -= 1;)\n}\n\nstatic void\nRemoveListEntry(\n    PSList *pool,\n    PSEntry *psEntry)\n{\n    assert(pool);\n    assert(psEntry);\n\n    if (PSModMaskArr_Capacity(psEntry->lastModMaskArr) > MAX_MOD_MASK_ARR_SIZE) {\n\tPSModMaskArr_Free(&psEntry->lastModMaskArr);\n    }\n    PSList_Remove(psEntry);\n    PSList_Append(pool, psEntry);\n}\n\nstatic void\nClearList(\n    PSList *psList,\n    PSList *pool,\n    void *object)\n{\n    assert(psList);\n    assert(pool);\n\n    if (object) {\n\tPSEntry *psEntry;\n\tPSEntry *psNext;\n\n\tfor (psEntry = PSList_First(psList); psEntry; psEntry = psNext) {\n\t    psNext = PSList_Next(psEntry);\n\t    if (psEntry->psPtr->object == object) {\n\t\tRemoveListEntry(pool, psEntry);\n\t    }\n\t}\n    } else {\n\tPSList_Move(pool, psList);\n    }\n}\n\nstatic PSEntry *\nFreePatSeqEntry(\n    TCL_UNUSED(PSList *),\n    PSEntry *entry)\n{\n    PSEntry *next = PSList_Next(entry);\n\n    PSModMaskArr_Free(&entry->lastModMaskArr);\n    Tcl_Free(entry);\n    return next;\n}\n\nstatic unsigned\nResolveModifiers(\n    TkDisplay *dispPtr,\n    unsigned modMask)\n{\n    assert(dispPtr);\n\n    if (dispPtr->metaModMask) {\n\tif (modMask & META_MASK) {\n\t    modMask &= ~META_MASK;\n\t    modMask |= dispPtr->metaModMask;\n\t}\n    }\n    if (dispPtr->altModMask) {\n\tif (modMask & ALT_MASK) {\n\t    modMask &= ~ALT_MASK;\n\t    modMask |= dispPtr->altModMask;\n\t}\n    }\n\n    return modMask;\n}\n\nstatic int\nButtonNumberFromState(\n    unsigned state)\n{\n    if (!(state & ALL_BUTTONS)) { return 0; }\n    if (state & Button1Mask) { return 1; }\n    if (state & Button2Mask) { return 2; }\n    if (state & Button3Mask) { return 3; }\n    if (state & Button4Mask) { return 4; }\n    if (state & Button5Mask) { return 5; }\n    if (state & Button6Mask) { return 6; }\n    if (state & Button7Mask) { return 7; }\n    if (state & Button8Mask) { return 8; }\n    return 9;\n}\n\nstatic void\nSetupPatternKey(\n    PatternTableKey *key,\n    const PatSeq *psPtr)\n{\n    const TkPattern *patPtr;\n\n    assert(key);\n    assert(psPtr);\n\n    /* otherwise on some systems the key contains uninitialized bytes */\n    memset(key, 0, sizeof(PatternTableKey));\n\n    patPtr = psPtr->pats;\n    assert(!patPtr->info || !patPtr->name);\n\n    key->object = psPtr->object;\n    key->type = patPtr->eventType;\n    if (patPtr->info) {\n\tkey->detail.info = patPtr->info;\n    } else {\n\tkey->detail.name = patPtr->name;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MakeListEntry --\n *\n *\tMakes new entry item for lookup table. We are using a\n *\tpool of items, this avoids superfluous memory allocation/\n *\tdeallocation.\n *\n * Results:\n *\tNew entry item.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *--------------------------------------------------------------\n */\n\nstatic PSEntry *\nMakeListEntry(\n    PSList *pool,\n    PatSeq *psPtr,\n    int needModMasks)\n{\n    PSEntry *newEntry = NULL;\n\n    assert(pool);\n    assert(psPtr);\n    assert(psPtr->numPats > 0);\n    assert(TEST_PSENTRY(psPtr));\n\n    if (PSList_IsEmpty(pool)) {\n\tnewEntry = (PSEntry *)Tcl_Alloc(sizeof(PSEntry));\n\tnewEntry->lastModMaskArr = NULL;\n\tDEBUG(countEntryItems += 1;)\n    } else {\n\tnewEntry = PSList_First(pool);\n\tPSList_RemoveHead(pool);\n    }\n\n    if (!needModMasks) {\n\tPSModMaskArr_SetSize(newEntry->lastModMaskArr, 0);\n    } else {\n\tif (PSModMaskArr_Capacity(newEntry->lastModMaskArr) < psPtr->numPats - 1) {\n\t    PSModMaskArr_Resize(&newEntry->lastModMaskArr, psPtr->numPats - 1);\n\t}\n\tPSModMaskArr_SetSize(newEntry->lastModMaskArr, psPtr->numPats - 1);\n    }\n\n    newEntry->psPtr = psPtr;\n    newEntry->window = None;\n    newEntry->expired = 0;\n    newEntry->keepIt = 1;\n    newEntry->count = 1;\n    DEBUG(psPtr->owned = 0;)\n\n    return newEntry;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetLookupForEvent --\n *\n *\tGet specific pattern sequence table for given event.\n *\n * Results:\n *\tSpecific pattern sequence table for given event.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic PSList *\nGetLookupForEvent(\n    LookupTables* lookupTables,\n    const Event *eventPtr,\n    Tcl_Obj *object,\n    int onlyConsiderDetailedEvents)\n{\n    PatternTableKey key;\n    Tcl_HashEntry *hPtr;\n\n    assert(lookupTables);\n    assert(eventPtr);\n\n    /* Otherwise on some systems the key contains uninitialized bytes. */\n    memset(&key, 0, sizeof(PatternTableKey));\n\n    if (onlyConsiderDetailedEvents) {\n\tswitch (eventPtr->xev.type) {\n\tcase ButtonPress:   /* fallthru */\n\tcase ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break;\n\tcase MotionNotify:  key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break;\n\tcase KeyPress:      /* fallthru */\n\tcase KeyRelease:    key.detail.info = eventPtr->detail.info; break;\n\tcase VirtualEvent:  key.detail.name = eventPtr->detail.name; break;\n\t}\n\tif (!key.detail.name) {\n\t    assert(!key.detail.info);\n\t    return NULL;\n\t}\n    }\n\n    key.object = object;\n    key.type = eventPtr->xev.type;\n    hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key);\n    return hPtr ? (PSList *)Tcl_GetHashValue(hPtr) : NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ClearLookupTable --\n *\n *\tClear lookup table in given binding table, but only those\n *\tbindings associated to given object. If object is NULL\n *\tthen remove all entries.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\nstatic void\nClearLookupTable(\n    LookupTables *lookupTables,\n    void *object)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashEntry *nextPtr;\n    PSList *pool = &lookupTables->entryPool;\n\n    assert(lookupTables);\n\n    for (hPtr = Tcl_FirstHashEntry(&lookupTables->listTable, &search); hPtr; hPtr = nextPtr) {\n\tPSList *psList;\n\n\tnextPtr = Tcl_NextHashEntry(&search);\n\n\tif (object) {\n\t    const PatternTableKey *key = (const PatternTableKey *)Tcl_GetHashKey(&lookupTables->listTable, hPtr);\n\t    if (key->object != object) {\n\t\tcontinue;\n\t    }\n\t}\n\n\tpsList = (PSList *)Tcl_GetHashValue(hPtr);\n\tPSList_Move(pool, psList);\n\tTcl_Free(psList);\n\tDEBUG(countListItems -= 1;)\n\tTcl_DeleteHashEntry(hPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ClearPromotionLists --\n *\n *\tClear all the lists holding the promoted pattern\n *\tsequences, which belongs to given object. If object\n *\tis NULL then remove all patterns.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nClearPromotionLists(\n    Tk_BindingTable bindPtr,\n    void *object)\n{\n    size_t i, newArraySize = 0;\n\n    assert(bindPtr);\n\n    for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {\n\tPSList *psList = PromArr_Get(bindPtr->promArr, i);\n\tClearList(psList, &bindPtr->lookupTables.entryPool, object);\n\tif (!PSList_IsEmpty(psList)) {\n\t    newArraySize = i + 1;\n\t}\n    }\n\n    PromArr_SetSize(bindPtr->promArr, newArraySize);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkBindInit --\n *\n *\tThis function is called when an application is created. It initializes\n *\tall the structures used by bindings and virtual events. It must be\n *\tcalled before any other functions in this file are called.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\n/*\n * Windows compiler does not allow the definition of these static variables inside a function,\n * otherwise this should belong to function TkBindInit().\n */\nTCL_DECLARE_MUTEX(bindMutex);\nstatic bool initialized = false;\n\nvoid\nTkBindInit(\n    TkMainInfo *mainPtr)\t/* The newly created application. */\n{\n    BindInfo *bindInfoPtr;\n\n    assert(mainPtr);\n\n    /* Otherwise virtual events can't be supported. */\n    assert(sizeof(XEvent) >= sizeof(XVirtualEvent));\n\n    /* Is type of TkPattern.info well defined? */\n    assert(sizeof(Info) >= sizeof(KeySym));\n    assert(sizeof(Info) >= sizeof(unsigned));\n\n    /* Ensure that our matching algorithm is working (when testing detail). */\n    assert(sizeof(Detail) == sizeof(Tk_Uid));\n\n    /* Test expected indices of Button1..Button5, otherwise our button handling is not working. */\n    assert(Button1 == 1 && Button2 == 2 && Button3 == 3 && Button4 == 4 && Button5 == 5);\n    assert(Button2Mask == (Button1Mask << 1));\n    assert(Button3Mask == (Button1Mask << 2));\n    assert(Button4Mask == (Button1Mask << 3));\n    assert(Button5Mask == (Button1Mask << 4));\n\n    /* Test expected values of button motion masks, otherwise our button handling is not working. */\n    assert(Button1MotionMask == Button1Mask);\n    assert(Button2MotionMask == Button2Mask);\n    assert(Button3MotionMask == Button3Mask);\n    assert(Button4MotionMask == Button4Mask);\n    assert(Button5MotionMask == Button5Mask);\n\n    /* Because we expect zero if keySym is empty. */\n    assert(NoSymbol == 0L);\n\n    /* This must be a union, not a struct, otherwise comparison with NULL will not work. */\n    assert(offsetof(Detail, name) == offsetof(Detail, info));\n\n    /* We use some constraints about X*Event. */\n    assert(offsetof(XButtonEvent, time) == offsetof(XMotionEvent, time));\n    assert(offsetof(XButtonEvent, x_root) == offsetof(XMotionEvent, x_root));\n    assert(offsetof(XButtonEvent, y_root) == offsetof(XMotionEvent, y_root));\n    assert(offsetof(XCreateWindowEvent, border_width) == offsetof(XConfigureEvent, border_width));\n    assert(offsetof(XCreateWindowEvent, width) == offsetof(XConfigureEvent, width));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XCirculateRequestEvent, window));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XConfigureEvent, window));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XGravityEvent, window));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XMapEvent, window));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XReparentEvent, window));\n    assert(offsetof(XCreateWindowEvent, window) == offsetof(XUnmapEvent, window));\n    assert(offsetof(XCreateWindowEvent, x) == offsetof(XConfigureEvent, x));\n    assert(offsetof(XCreateWindowEvent, x) == offsetof(XGravityEvent, x));\n    assert(offsetof(XCreateWindowEvent, y) == offsetof(XConfigureEvent, y));\n    assert(offsetof(XCreateWindowEvent, y) == offsetof(XGravityEvent, y));\n    assert(offsetof(XCrossingEvent, time) == offsetof(XEnterWindowEvent, time));\n    assert(offsetof(XCrossingEvent, time) == offsetof(XLeaveWindowEvent, time));\n    assert(offsetof(XCrossingEvent, time) == offsetof(XKeyEvent, time));\n    assert(offsetof(XKeyEvent, root) == offsetof(XButtonEvent, root));\n    assert(offsetof(XKeyEvent, root) == offsetof(XCrossingEvent, root));\n    assert(offsetof(XKeyEvent, root) == offsetof(XMotionEvent, root));\n    assert(offsetof(XKeyEvent, state) == offsetof(XButtonEvent, state));\n    assert(offsetof(XKeyEvent, state) == offsetof(XMotionEvent, state));\n    assert(offsetof(XKeyEvent, subwindow) == offsetof(XButtonEvent, subwindow));\n    assert(offsetof(XKeyEvent, subwindow) == offsetof(XCrossingEvent, subwindow));\n    assert(offsetof(XKeyEvent, subwindow) == offsetof(XMotionEvent, subwindow));\n    assert(offsetof(XKeyEvent, time) == offsetof(XButtonEvent, time));\n    assert(offsetof(XKeyEvent, time) == offsetof(XMotionEvent, time));\n    assert(offsetof(XKeyEvent, x) == offsetof(XButtonEvent, x));\n    assert(offsetof(XKeyEvent, x) == offsetof(XCrossingEvent, x));\n    assert(offsetof(XKeyEvent, x) == offsetof(XMotionEvent, x));\n    assert(offsetof(XKeyEvent, x_root) == offsetof(XButtonEvent, x_root));\n    assert(offsetof(XKeyEvent, x_root) == offsetof(XCrossingEvent, x_root));\n    assert(offsetof(XKeyEvent, x_root) == offsetof(XMotionEvent, x_root));\n    assert(offsetof(XKeyEvent, y) == offsetof(XButtonEvent, y));\n    assert(offsetof(XKeyEvent, y) == offsetof(XCrossingEvent, y));\n    assert(offsetof(XKeyEvent, y) == offsetof(XMotionEvent, y));\n    assert(offsetof(XKeyEvent, y_root) == offsetof(XButtonEvent, y_root));\n    assert(offsetof(XKeyEvent, y_root) == offsetof(XCrossingEvent, y_root));\n    assert(offsetof(XKeyEvent, y_root) == offsetof(XMotionEvent, y_root));\n\n    /*\n     * Initialize the static data structures used by the binding package. They\n     * are only initialized once, no matter how many interps are created.\n     */\n\n    if (!initialized) {\n\tTcl_MutexLock(&bindMutex);\n\tif (!initialized) {\n\t    Tcl_HashEntry *hPtr;\n\t    const ModInfo *modPtr;\n\t    const EventInfo *eiPtr;\n\t    int newEntry;\n\t    unsigned i;\n#ifdef REDO_KEYSYM_LOOKUP\n\t    const KeySymInfo *kPtr;\n\n\t    Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS);\n\t    Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS);\n\t    for (kPtr = keyArray; kPtr->name; ++kPtr) {\n\t\thPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry);\n\t\tTcl_SetHashValue(hPtr, kPtr->value);\n\t\thPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, &newEntry);\n\t\tif (newEntry) {\n\t\t    Tcl_SetHashValue(hPtr, kPtr->name);\n\t\t}\n\t    }\n#endif /* REDO_KEYSYM_LOOKUP */\n\n\t    for (i = 0; i < SIZE_OF_ARRAY(eventArrayIndex); ++i) {\n\t\teventArrayIndex[i] = -1;\n\t    }\n\t    for (i = 0; i < SIZE_OF_ARRAY(eventArray); ++i) {\n\t\tunsigned type = eventArray[i].type;\n\t\tassert(type < TK_LASTEVENT);\n\t\tassert(type > 0 || i == SIZE_OF_ARRAY(eventArray) - 1);\n\t\tif (type > 0 && eventArrayIndex[type] == -1) {\n\t\t    eventArrayIndex[type] = i;\n\t\t}\n\t    }\n\n\t    Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);\n\t    for (modPtr = modArray; modPtr->name; ++modPtr) {\n\t\thPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry);\n\t\tTcl_SetHashValue(hPtr, modPtr);\n\t    }\n\n\t    Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS);\n\t    for (eiPtr = eventArray; eiPtr->name; ++eiPtr) {\n\t\thPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry);\n\t\tTcl_SetHashValue(hPtr, eiPtr);\n\t    }\n\n\t    initialized = true;\n\t}\n\tTcl_MutexUnlock(&bindMutex);\n    }\n\n    mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp);\n\n    bindInfoPtr = (BindInfo *)Tcl_Alloc(sizeof(BindInfo));\n    InitVirtualEventTable(&bindInfoPtr->virtualEventTable);\n    bindInfoPtr->screenInfo.curDispPtr = NULL;\n    bindInfoPtr->screenInfo.curScreenIndex = -1;\n    bindInfoPtr->screenInfo.bindingDepth = 0;\n    bindInfoPtr->deleted = 0;\n    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();\n    bindInfoPtr->lastEventTime = 0;\n    mainPtr->bindInfo = bindInfoPtr;\n    DEBUG(countBindItems += 1;)\n\n    TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkBindFree --\n *\n *\tThis function is called when an application is deleted. It deletes all\n *\tthe structures used by bindings and virtual events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkBindFree(\n    TkMainInfo *mainPtr)\t/* The newly created application. */\n{\n    BindInfo *bindInfoPtr;\n\n    assert(mainPtr);\n\n    Tk_DeleteBindingTable(mainPtr->bindingTable);\n    mainPtr->bindingTable = NULL;\n    bindInfoPtr = mainPtr->bindInfo;\n    DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable);\n    bindInfoPtr->deleted = 1;\n    Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC);\n    mainPtr->bindInfo = NULL;\n\n    DEBUG(countBindItems -= 1;)\n    assert(countBindItems > 0 || countTableItems == 0);\n    assert(countBindItems > 0 || countEntryItems == 0);\n    assert(countBindItems > 0 || countListItems == 0);\n    assert(countBindItems > 0 || countSeqItems == 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateBindingTable --\n *\n *\tSet up a new domain in which event bindings may be created.\n *\n * Results:\n *\tThe return value is a token for the new table, which must be passed to\n *\tfunctions like Tk_CreateBinding.\n *\n * Side effects:\n *\tMemory is allocated for the new table.\n *\n *--------------------------------------------------------------\n */\n\nTk_BindingTable\nTk_CreateBindingTable(\n    Tcl_Interp *interp)\t\t/* Interpreter to associate with the binding table: commands are\n\t\t\t\t * executed in this interpreter. */\n{\n    BindingTable *bindPtr = (BindingTable *)Tcl_Alloc(sizeof(BindingTable));\n    unsigned i;\n\n    assert(interp);\n    DEBUG(countTableItems += 1;)\n\n    /*\n     * Create and initialize a new binding table.\n     */\n\n    memset(bindPtr, 0, sizeof(BindingTable));\n    for (i = 0; i < SIZE_OF_ARRAY(bindPtr->eventInfo); ++i) {\n\tbindPtr->eventInfo[i].xev.type = -1;\n    }\n    bindPtr->curEvent = bindPtr->eventInfo; /* do not assign NULL */\n    bindPtr->lookupTables.number = 0;\n    PromArr_ResizeAndClear(&bindPtr->promArr, 2);\n    Tcl_InitHashTable(&bindPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int));\n    Tcl_InitHashTable(&bindPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int));\n    Tcl_InitHashTable(&bindPtr->objectTable, TCL_ONE_WORD_KEYS);\n    bindPtr->interp = interp;\n    return bindPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DeleteBindingTable --\n *\n *\tDestroy a binding table and free up all its memory. The caller should\n *\tnot use bindingTable again after this function returns.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_DeleteBindingTable(\n    Tk_BindingTable bindPtr)\t/* Token for the binding table to destroy. */\n{\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    assert(bindPtr);\n\n    /*\n     * Find and delete all of the patterns associated with the binding table.\n     */\n\n    hPtr = Tcl_FirstHashEntry(&bindPtr->lookupTables.patternTable, &search);\n    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {\n\tPatSeq *nextPtr;\n\tPatSeq *psPtr;\n\n\tfor (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {\n\t    assert(TEST_PSENTRY(psPtr));\n\t    nextPtr = psPtr->nextSeqPtr;\n\t    FreePatSeq(psPtr);\n\t}\n    }\n\n    /*\n     * Don't forget to release lookup elements.\n     */\n\n    ClearLookupTable(&bindPtr->lookupTables, NULL);\n    ClearPromotionLists(bindPtr, NULL);\n    PromArr_Free(&bindPtr->promArr);\n    DEBUG(countEntryItems -= PSList_Size(&bindPtr->lookupTables.entryPool);)\n    PSList_Traverse(&bindPtr->lookupTables.entryPool, FreePatSeqEntry);\n\n    /*\n     * Clean up the rest of the information associated with the binding table.\n     */\n\n    Tcl_DeleteHashTable(&bindPtr->lookupTables.patternTable);\n    Tcl_DeleteHashTable(&bindPtr->lookupTables.listTable);\n    Tcl_DeleteHashTable(&bindPtr->objectTable);\n\n    Tcl_Free(bindPtr);\n    DEBUG(countTableItems -= 1;)\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * InsertPatSeq --\n *\n *\tInsert given pattern sequence into lookup table for fast\n *\taccess.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nInsertPatSeq(\n    LookupTables *lookupTables,\n    PatSeq *psPtr)\n{\n    assert(lookupTables);\n    assert(psPtr);\n    assert(TEST_PSENTRY(psPtr));\n    assert(psPtr->numPats >= 1u);\n\n    if (!(psPtr->added)) {\n\tPatternTableKey key;\n\tTcl_HashEntry *hPtr;\n\tint isNew;\n\tPSList *psList;\n\tPSEntry *psEntry;\n\n\tSetupPatternKey(&key, psPtr);\n\thPtr = Tcl_CreateHashEntry(&lookupTables->listTable, (char *) &key, &isNew);\n\n\tif (isNew) {\n\t    psList = (PSList *)Tcl_Alloc(sizeof(PSList));\n\t    PSList_Init(psList);\n\t    Tcl_SetHashValue(hPtr, psList);\n\t    DEBUG(countListItems += 1;)\n\t} else {\n\t    psList = (PSList *)Tcl_GetHashValue(hPtr);\n\t}\n\n\tpsEntry = MakeListEntry(&lookupTables->entryPool, psPtr, 0);\n\tPSList_Append(psList, psEntry);\n\tpsPtr->added = 1;\n    }\n}\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateBinding --\n *\n *\tAdd a binding to a binding table, so that future calls to Tk_BindEvent\n *\tmay execute the command in the binding.\n *\n * Results:\n *\tThe return value is 0 if an error occurred while setting up the\n *\tbinding. In this case, an error message will be left in the interp's\n *\tresult. If all went well then the return value is a mask of the event\n *\ttypes that must be made available to Tk_BindEvent in order to properly\n *\tdetect when this binding triggers. This value can be used to determine\n *\twhat events to select for in a window, for example.\n *\n * Side effects:\n *\tAn existing binding on the same event sequence may be replaced. The\n *\tnew binding may cause future calls to Tk_BindEvent to behave\n *\tdifferently than they did previously.\n *\n *--------------------------------------------------------------\n */\n\nunsigned long\nTk_CreateBinding(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_BindingTable bindPtr,\t/* Table in which to create binding. */\n    void *object,\t\t/* Token for object with which binding is associated. */\n    const char *eventString,\t/* String describing event sequence that triggers binding. */\n    const char *script,\t\t/* Contains Tcl script to execute when binding triggers. */\n    int append)\t\t\t/* 0 means replace any existing binding for eventString;\n\t\t\t\t * 1 means append to that binding. If the existing binding is\n\t\t\t\t * for a callback function and not a Tcl command string, the\n\t\t\t\t * existing binding will always be replaced. */\n{\n    PatSeq *psPtr;\n    unsigned eventMask;\n    char *oldStr;\n    char *newStr;\n\n    assert(bindPtr);\n    assert(object);\n    assert(eventString);\n    assert(script);\n\n    psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString,\n\t    !!*script, 1, &eventMask);\n\n    if (!*script) {\n\tassert(!psPtr || psPtr->added);\n\t/* Silently ignore empty scripts -- see SF#3006842 */\n\treturn eventMask;\n    }\n    if (!psPtr) {\n\treturn 0;\n    }\n    assert(TEST_PSENTRY(psPtr));\n\n    if (psPtr->numPats > PromArr_Capacity(bindPtr->promArr)) {\n\t/*\n\t * We have to increase the size of array containing the lists of promoted sequences.\n\t * Normally the maximal size is 1, only in very seldom cases a bigger size is needed.\n\t * Note that for technical reasons the capacity should be one higher than the expected\n\t * maximal size.\n\t */\n\tPromArr_ResizeAndClear(&bindPtr->promArr, psPtr->numPats);\n    }\n\n    if (!psPtr->script) {\n\tTcl_HashEntry *hPtr;\n\tint isNew;\n\n\t/*\n\t * This pattern sequence was just created. Link the pattern into the\n\t * list associated with the object, so that if the object goes away,\n\t * these bindings will all automatically be deleted.\n\t */\n\n\thPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, &isNew);\n\tpsPtr->ptr.nextObj = isNew ? NULL : (PatSeq *)Tcl_GetHashValue(hPtr);\n\tTcl_SetHashValue(hPtr, psPtr);\n\tInsertPatSeq(&bindPtr->lookupTables, psPtr);\n    }\n\n    oldStr = psPtr->script;\n    if (append && oldStr) {\n\tsize_t length1 = strlen(oldStr);\n\tsize_t length2 = strlen(script);\n\n\tnewStr = (char *)Tcl_Alloc(length1 + length2 + 2);\n\tmemcpy(newStr, oldStr, length1);\n\tnewStr[length1] = '\\n';\n\tmemcpy(newStr + length1 + 1, script, length2 + 1);\n    } else {\n\tsize_t length = strlen(script);\n\n\tnewStr = (char *)Tcl_Alloc(length + 1);\n\tmemcpy(newStr, script, length + 1);\n    }\n    Tcl_Free(oldStr);\n    psPtr->script = newStr;\n    return eventMask;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DeleteBinding --\n *\n *\tRemove an event binding from a binding table.\n *\n * Results:\n *\tThe result is a standard Tcl return value. If an error occurs then the\n *\tinterp's result will contain an error message.\n *\n * Side effects:\n *\tThe binding given by object and eventString is removed from\n *\tbindingTable.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_DeleteBinding(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_BindingTable bindPtr,\t/* Table in which to delete binding. */\n    void *object,\t\t/* Token for object with which binding is associated. */\n    const char *eventString)\t/* String describing event sequence that triggers binding. */\n{\n    PatSeq *psPtr;\n\n    assert(bindPtr);\n    assert(object);\n    assert(eventString);\n\n    psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL);\n    if (!psPtr) {\n\tTcl_ResetResult(interp);\n    } else {\n\tTcl_HashEntry *hPtr;\n\tPatSeq *prevPtr;\n\n\tassert(TEST_PSENTRY(psPtr));\n\n\t/*\n\t * Unlink the binding from the list for its object.\n\t */\n\n\tif (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {\n\t    Tcl_Panic(\"Tk_DeleteBinding couldn't find object table entry\");\n\t}\n\tprevPtr = (PatSeq *)Tcl_GetHashValue(hPtr);\n\tif (prevPtr == psPtr) {\n\t    Tcl_SetHashValue(hPtr, psPtr->ptr.nextObj);\n\t} else {\n\t    for ( ; ; prevPtr = prevPtr->ptr.nextObj) {\n\t\tif (!prevPtr) {\n\t\t    Tcl_Panic(\"Tk_DeleteBinding couldn't find on object list\");\n\t\t}\n\t\tif (prevPtr->ptr.nextObj == psPtr) {\n\t\t    prevPtr->ptr.nextObj = psPtr->ptr.nextObj;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\tRemovePatSeqFromLookup(&bindPtr->lookupTables, psPtr);\n\tRemovePatSeqFromPromotionLists(bindPtr, psPtr);\n\tDeletePatSeq(psPtr);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetBinding --\n *\n *\tReturn the script associated with a given event string.\n *\n * Results:\n *\tThe return value is a pointer to the script associated with\n *\teventString for object in the domain given by bindingTable. If there\n *\tis no binding for eventString, or if eventString is improperly formed,\n *\tthen NULL is returned and an error message is left in the interp's\n *\tresult. The return value is semi-static: it will persist until the\n *\tbinding is changed or deleted.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_GetBinding(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_BindingTable bindPtr,\t/* Table in which to look for binding. */\n    void *object,\t\t/* Token for object with which binding is associated. */\n    const char *eventString)\t/* String describing event sequence that triggers binding. */\n{\n    const PatSeq *psPtr;\n\n    assert(bindPtr);\n    assert(object);\n    assert(eventString);\n\n    psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL);\n    assert(!psPtr || TEST_PSENTRY(psPtr));\n    return psPtr ? psPtr->script : NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetAllBindings --\n *\n *\tReturn a list of event strings for all the bindings associated with a\n *\tgiven object.\n *\n * Results:\n *\tThere is no return value. The interp's result is modified to hold a\n *\tTcl list with one entry for each binding associated with object in\n *\tbindingTable. Each entry in the list contains the event string\n *\tassociated with one binding.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_GetAllBindings(\n    Tcl_Interp *interp,\t\t/* Interpreter returning result or error. */\n    Tk_BindingTable bindPtr,\t/* Table in which to look for bindings. */\n    void *object)\t\t/* Token for object. */\n{\n    Tcl_HashEntry *hPtr;\n\n    assert(bindPtr);\n    assert(object);\n\n    if ((hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {\n\tconst PatSeq *psPtr;\n\tTcl_Obj *resultObj = Tcl_NewObj();\n\n\t/*\n\t * For each binding, output information about each of the patterns in its sequence.\n\t */\n\n\tfor (psPtr = (const PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = psPtr->ptr.nextObj) {\n\t    assert(TEST_PSENTRY(psPtr));\n\t    Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RemovePatSeqFromLookup --\n *\n *\tRemove given pattern sequence from lookup tables. This\n *\tcan be required before deleting the pattern sequence.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRemovePatSeqFromLookup(\n    LookupTables *lookupTables,\t/* Remove from this lookup tables. */\n    PatSeq *psPtr)\t\t/* Remove this pattern sequence. */\n{\n    PatternTableKey key;\n    Tcl_HashEntry *hPtr;\n\n    assert(lookupTables);\n    assert(psPtr);\n\n    SetupPatternKey(&key, psPtr);\n\n    if ((hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key))) {\n\tPSList *psList = (PSList *)Tcl_GetHashValue(hPtr);\n\tPSEntry *psEntry;\n\n\tTK_DLIST_FOREACH(psEntry, psList) {\n\t    if (psEntry->psPtr == psPtr) {\n\t\tpsPtr->added = 0;\n\t\tRemoveListEntry(&lookupTables->entryPool, psEntry);\n\t\treturn;\n\t    }\n\t}\n    }\n\n    assert(!\"couldn't find pattern sequence in lookup\");\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RemovePatSeqFromPromotionLists --\n *\n *\tRemove given pattern sequence from promotion lists. This\n *\tcan be required before deleting the pattern sequence.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRemovePatSeqFromPromotionLists(\n    Tk_BindingTable bindPtr,\t/* Table in which to look for bindings. */\n    PatSeq *psPtr)\t\t/* Remove this pattern sequence. */\n{\n    size_t i;\n\n    assert(bindPtr);\n    assert(psPtr);\n\n    for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {\n\tPSList *psList = PromArr_Get(bindPtr->promArr, i);\n\tPSEntry *psEntry;\n\n\tTK_DLIST_FOREACH(psEntry, psList) {\n\t    if (psEntry->psPtr == psPtr) {\n\t\tRemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);\n\t\tbreak;\n\t    }\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeletePatSeq --\n *\n *\tDelete given pattern sequence. Possibly it is required\n *\tto invoke RemovePatSeqFromLookup(), and RemovePatSeqFromPromotionLists()\n *\tbefore.\n *\n * Results:\n *\tPointer to succeeding pattern sequence.\n *\n * Side effects:\n *\tDeallocation of memory.\n *\n *--------------------------------------------------------------\n */\n\nstatic PatSeq *\nDeletePatSeq(\n    PatSeq *psPtr)\t\t/* Delete this pattern sequence. */\n{\n    PatSeq *prevPtr;\n    PatSeq *nextPtr;\n\n    assert(psPtr);\n    assert(!psPtr->added);\n    assert(!psPtr->owned);\n\n    prevPtr = (PatSeq *)Tcl_GetHashValue(psPtr->hPtr);\n    nextPtr = psPtr->ptr.nextObj;\n\n    /*\n     * Be sure to remove each binding from its hash chain in the pattern\n     * table. If this is the last pattern in the chain, then delete the\n     * hash entry too.\n     */\n\n    if (prevPtr == psPtr) {\n\tif (!psPtr->nextSeqPtr) {\n\t    Tcl_DeleteHashEntry(psPtr->hPtr);\n\t} else {\n\t    Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);\n\t}\n    } else {\n\tfor ( ; ; prevPtr = prevPtr->nextSeqPtr) {\n\t    if (!prevPtr) {\n\t\tTcl_Panic(\"DeletePatSeq couldn't find on hash chain\");\n\t    }\n\t    if (prevPtr->nextSeqPtr == psPtr) {\n\t\tprevPtr->nextSeqPtr = psPtr->nextSeqPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    FreePatSeq(psPtr);\n    return nextPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DeleteAllBindings --\n *\n *\tRemove all bindings associated with a given object in a given binding\n *\ttable.\n *\n * Results:\n *\tAll bindings associated with object are removed from bindingTable.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_DeleteAllBindings(\n    Tk_BindingTable bindPtr,\t/* Table in which to delete bindings. */\n    void *object)\t\t/* Token for object. */\n{\n    PatSeq *psPtr;\n    PatSeq *nextPtr;\n    Tcl_HashEntry *hPtr;\n\n    assert(bindPtr);\n    assert(object);\n\n    if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {\n\treturn;\n    }\n\n    /*\n     * Don't forget to clear lookup tables.\n     */\n\n    ClearLookupTable(&bindPtr->lookupTables, object);\n    ClearPromotionLists(bindPtr, object);\n\n    for (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {\n\tassert(TEST_PSENTRY(psPtr));\n\tDEBUG(psPtr->added = 0;)\n\tnextPtr = DeletePatSeq(psPtr);\n    }\n\n    Tcl_DeleteHashEntry(hPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_BindEvent --\n *\n *\tThis function is invoked to process an X event. The event is added to\n *\tthose recorded for the binding table. Then each of the objects at\n *\t*objectPtr is checked in order to see if it has a binding that matches\n *\tthe recent events. If so, the most specific binding is invoked for\n *\teach object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the script associated with the matching binding.\n *\n *\tAll Tcl binding scripts for each object are accumulated before the\n *\tfirst binding is evaluated. If the action of a Tcl binding is to\n *\tchange or delete a binding, or delete the window associated with the\n *\tbinding, all the original Tcl binding scripts will still fire.\n *\n *---------------------------------------------------------------------------\n */\n\n/* helper function */\nstatic void\nResetCounters(\n    Event *eventInfo,\n    unsigned eventType,\n    Window window)\n{\n    Event *curEvent;\n\n    assert(eventInfo);\n    curEvent = eventInfo + eventType;\n\n    if (curEvent->xev.xany.window == window) {\n\tcurEvent->xev.xany.window = None;\n\teventInfo[eventType].countAny = 0;\n\teventInfo[eventType].countDetailed = 0;\n    }\n}\n\n/* helper function */\nstatic bool\nIsBetterMatch(\n    const PatSeq *fstMatchPtr,\n    const PatSeq *sndMatchPtr)\t/* this is a better match? */\n{\n    int diff;\n\n    if (!sndMatchPtr) { return false; }\n    if (!fstMatchPtr) { return true; }\n\n    diff = CountSpecialized(fstMatchPtr, sndMatchPtr);\n    if (diff > 0) { return true; }\n    if (diff < 0) { return false; }\n\n    {\t/* local scope */\n#define M 1000000ULL\n\tstatic const unsigned long long weight[5] = { 0, 1, M, M*M, M*M*M };\n#undef M\n\tunsigned long long fstCount = 0;\n\tunsigned long long sndCount = 0;\n\tunsigned i;\n\n\t/*\n\t * Count the most high-ordered patterns.\n\t *\n\t * (This computation assumes that a sequence does not contain more than\n\t * 1,000,000 single patterns. It can be precluded that in practice this\n\t * assumption will not be violated.)\n\t */\n\n\tfor (i = 0; i < fstMatchPtr->numPats; ++i) {\n\t    assert(GetCount(fstMatchPtr, i) < SIZE_OF_ARRAY(weight));\n\t    fstCount += weight[GetCount(fstMatchPtr, i)];\n\t}\n\tfor (i = 0; i < sndMatchPtr->numPats; ++i) {\n\t    assert(GetCount(sndMatchPtr, i) < SIZE_OF_ARRAY(weight));\n\t    sndCount += weight[GetCount(sndMatchPtr, i)];\n\t}\n\tif (sndCount > fstCount) { return true; }\n\tif (sndCount < fstCount) { return false; }\n    }\n\n    return sndMatchPtr->number > fstMatchPtr->number;\n}\n\nvoid\nTk_BindEvent(\n    Tk_BindingTable bindPtr,\t/* Table in which to look for bindings. */\n    XEvent *eventPtr,\t\t/* What actually happened. */\n    Tk_Window tkwin,\t\t/* Window on display where event occurred (needed in order to\n\t\t\t\t * locate display information). */\n    Tcl_Size numObjects,\t\t/* Number of objects at *objArr. */\n    void **objArr)\t\t/* Array of one or more objects to check for a matching binding. */\n{\n    Tcl_Interp *interp;\n    ScreenInfo *screenPtr;\n    TkDisplay *dispPtr;\n    TkDisplay *oldDispPtr;\n    Event *curEvent;\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    BindInfo *bindInfoPtr;\n    Tcl_InterpState interpState;\n    LookupTables *physTables;\n    PatSeq *psPtr[2];\n    PatSeq *matchPtrBuf[32];\n    PatSeq **matchPtrArr = matchPtrBuf;\n    PSList *psl[2];\n    Tcl_DString scripts;\n    const char *p;\n    const char *end;\n    unsigned scriptCount;\n    int oldScreen;\n    unsigned flags;\n    Tcl_Size arraySize;\n    unsigned newArraySize;\n    Tcl_Size i, k;\n\n    assert(bindPtr);\n    assert(eventPtr);\n    assert(tkwin);\n    assert(numObjects >= 0);\n\n    /*\n     * Ignore events on windows that don't have names: these are windows like\n     * wrapper windows that shouldn't be visible to the application.\n     */\n\n    if (!winPtr->pathName) {\n\treturn;\n    }\n\n    flags = flagArray[eventPtr->type];\n\n    /*\n     * Ignore event types which are not in flagArray and all zeroes there.\n     */\n\n    if (eventPtr->type >= TK_LASTEVENT || !flags) {\n\treturn;\n    }\n\n    if (flags & HAS_XKEY_HEAD_AND_STATE) {\n\tbindPtr->curModMask = eventPtr->xkey.state;\n    } else if (flags & CROSSING) {\n\tbindPtr->curModMask = eventPtr->xcrossing.state;\n    }\n\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    bindInfoPtr = winPtr->mainPtr->bindInfo;\n    curEvent = bindPtr->eventInfo + eventPtr->type;\n\n    /*\n     * Compute current time needed for \"event generate\",\n     * and reset counters for Key and Button events.\n     */\n\n    switch (eventPtr->type) {\n    case EnterNotify:\n    case LeaveNotify:\n\tif (eventPtr->xcrossing.time) {\n\t    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();\n\t    bindInfoPtr->lastEventTime = eventPtr->xcrossing.time;\n\t}\n\tbreak;\n    case KeyPress:\n    case KeyRelease: {\n\tint reset = 1;\n\n\tif (eventPtr->xkey.time) {\n\t    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();\n\t    bindInfoPtr->lastEventTime = eventPtr->xkey.time;\n\t}\n\t/* Modifier keys should not influence button events. */\n\tfor (i = 0; i < dispPtr->numModKeyCodes; ++i) {\n\t    if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {\n\t\treset = 0;\n\t    }\n\t}\n\tif (reset) {\n\t    /* Reset repetition count for button events. */\n\t    bindPtr->eventInfo[ButtonPress].countAny = 0;\n\t    bindPtr->eventInfo[ButtonPress].countDetailed = 0;\n\t    bindPtr->eventInfo[ButtonRelease].countAny = 0;\n\t    bindPtr->eventInfo[ButtonRelease].countDetailed = 0;\n\t}\n\tbreak;\n    }\n    case ButtonPress:\n    case ButtonRelease:\n\t/* Reset repetition count for key events. */\n\tbindPtr->eventInfo[KeyPress].countAny = 0;\n\tbindPtr->eventInfo[KeyPress].countDetailed = 0;\n\tbindPtr->eventInfo[KeyRelease].countAny = 0;\n\tbindPtr->eventInfo[KeyRelease].countDetailed = 0;\n\t/* fallthru */\n    case MotionNotify:\n\tif (eventPtr->xmotion.time) {\n\t    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();\n\t    bindInfoPtr->lastEventTime = eventPtr->xmotion.time;\n\t}\n\tbreak;\n    case PropertyNotify:\n\tif (eventPtr->xproperty.time) {\n\t    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();\n\t    bindInfoPtr->lastEventTime = eventPtr->xproperty.time;\n\t}\n\tbreak;\n    case DestroyNotify:\n\tResetCounters(bindPtr->eventInfo, KeyPress, eventPtr->xany.window);\n\tResetCounters(bindPtr->eventInfo, KeyRelease, eventPtr->xany.window);\n\tResetCounters(bindPtr->eventInfo, ButtonPress, eventPtr->xany.window);\n\tResetCounters(bindPtr->eventInfo, ButtonRelease, eventPtr->xany.window);\n\tbreak;\n    }\n\n    /*\n     * Now check whether this is a repeating event (multi-click, repeated key press, and so on).\n     */\n\n    /* NOTE: if curEvent is not yet set, then the following cannot match: */\n    if (curEvent->xev.xany.window == eventPtr->xany.window) {\n\tswitch (eventPtr->type) {\n\tcase KeyPress:\n\tcase KeyRelease:\n\t    if (MatchEventRepeat(&curEvent->xev.xkey, &eventPtr->xkey)) {\n\t\tif (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) {\n\t\t    ++curEvent->countDetailed;\n\t\t} else {\n\t\t    curEvent->countDetailed = 1;\n\t\t}\n\t\t++curEvent->countAny;\n\t    } else {\n\t\tcurEvent->countAny = curEvent->countDetailed = 1;\n\t    }\n\t    break;\n\tcase ButtonPress:\n\tcase ButtonRelease:\n\t    if (MatchEventNearby(&curEvent->xev, eventPtr)) {\n\t\tif (curEvent->xev.xbutton.button == eventPtr->xbutton.button) {\n\t\t    ++curEvent->countDetailed;\n\t\t} else {\n\t\t    curEvent->countDetailed = 1;\n\t\t}\n\t\t++curEvent->countAny;\n\t    } else {\n\t\tcurEvent->countAny = curEvent->countDetailed = 1;\n\t    }\n\t    break;\n\tcase EnterNotify:\n\tcase LeaveNotify:\n\t    if (TestNearbyTime(eventPtr->xcrossing.time, curEvent->xev.xcrossing.time)) {\n\t\t++curEvent->countAny;\n\t    } else {\n\t\tcurEvent->countAny = 1;\n\t    }\n\t    break;\n\tcase PropertyNotify:\n\t    if (TestNearbyTime(eventPtr->xproperty.time, curEvent->xev.xproperty.time)) {\n\t\t++curEvent->countAny;\n\t    } else {\n\t\tcurEvent->countAny = 1;\n\t    }\n\t    break;\n\tdefault:\n\t    ++curEvent->countAny;\n\t    break;\n\t}\n    } else {\n\tcurEvent->countAny = curEvent->countDetailed = 1;\n    }\n\n    /*\n     * Now update the details.\n     */\n\n    curEvent->xev = *eventPtr;\n    if (flags & KEY) {\n\tcurEvent->detail.info = TkpGetKeySym(dispPtr, eventPtr);\n    } else if (flags & BUTTON) {\n\tcurEvent->detail.info = eventPtr->xbutton.button;\n    } else if (flags & MOTION) {\n\tcurEvent->detail.info = ButtonNumberFromState(eventPtr->xmotion.state);\n    } else if (flags & VIRTUAL) {\n\tcurEvent->detail.name = ((XVirtualEvent *) eventPtr)->name;\n    }\n\n    bindPtr->curEvent = curEvent;\n    physTables = &bindPtr->lookupTables;\n    scriptCount = 0;\n    arraySize = 0;\n    Tcl_DStringInit(&scripts);\n\n    if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) {\n\t/* It's unrealistic that the buffer size is too small, but who knows? */\n\tmatchPtrArr = (PatSeq **)Tcl_Alloc(numObjects*sizeof(matchPtrArr[0]));\n    }\n    memset(matchPtrArr, 0, numObjects*sizeof(matchPtrArr[0]));\n\n    if (!PromArr_IsEmpty(bindPtr->promArr)) {\n\tfor (k = 0; k < numObjects; ++k) {\n\t    psl[1] = PromArr_Last(bindPtr->promArr);\n\t    psl[0] = psl[1] - 1;\n\n\t    /*\n\t     * Loop over all promoted bindings, finding the longest matching one.\n\t     *\n\t     * Note that we must process all lists, because all matching patterns\n\t     * have to be promoted. Normally at most one list will be processed, and\n\t     * usually this list only contains one or two patterns.\n\t     */\n\n\t    for (i = PromArr_Size(bindPtr->promArr); i > 0; --i, --psl[0], --psl[1]) {\n\t\tpsPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psl[1], i, curEvent, objArr[k], NULL);\n\n\t\tif (IsBetterMatch(matchPtrArr[k], psPtr[0])) {\n\t\t    /* We will process it later, because we still may find a pattern with better match. */\n\t\t    matchPtrArr[k] = psPtr[0];\n\t\t}\n\t\tif (!PSList_IsEmpty(psl[1])) {\n\t\t    /* We have promoted sequences, adjust array size. */\n\t\t    arraySize = Max(i + 1, arraySize);\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * 1. Look for bindings for the specific detail (button and key events).\n     * 2. Look for bindings without detail.\n     */\n\n    for (k = 0; k < numObjects; ++k) {\n\tPSList *psSuccList = PromArr_First(bindPtr->promArr);\n\tPatSeq *bestPtr;\n\n\tpsl[0] = GetLookupForEvent(physTables, curEvent, (Tcl_Obj *)objArr[k], 1);\n\tpsl[1] = GetLookupForEvent(physTables, curEvent, (Tcl_Obj *)objArr[k], 0);\n\n\tassert(psl[0] == NULL || psl[0] != psl[1]);\n\n\tpsPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL);\n\tpsPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL);\n\n\tif (!PSList_IsEmpty(psSuccList)) {\n\t    /* We have promoted sequences, adjust array size. */\n\t    arraySize = Max(1, arraySize);\n\t}\n\n\tbestPtr = psPtr[0] ? psPtr[0] : psPtr[1];\n\n\tif (matchPtrArr[k]) {\n\t    if (IsBetterMatch(matchPtrArr[k], bestPtr)) {\n\t\tmatchPtrArr[k] = bestPtr;\n\t    } else {\n\t\t/*\n\t\t * We've already found a higher level match, nevertheless it was required to\n\t\t * process the level zero patterns because of possible promotions.\n\t\t */\n\t    }\n\t    /*\n\t     * Now we have to catch up the processing of the script.\n\t     */\n\t} else {\n\t    /*\n\t     * We have to look whether we can find a better match in virtual table, provided that we\n\t     * don't have a higher level match.\n\t     */\n\n\t    matchPtrArr[k] = bestPtr;\n\n\t    if (eventPtr->type != VirtualEvent) {\n\t\tLookupTables *virtTables = &bindInfoPtr->virtualEventTable.lookupTables;\n\t\tPatSeq *matchPtr = matchPtrArr[k];\n\t\tPatSeq *mPtr;\n\n\t\t/*\n\t\t * Note that virtual events cannot promote.\n\t\t */\n\n\t\tpsl[0] = GetLookupForEvent(virtTables, curEvent, NULL, 1);\n\t\tpsl[1] = GetLookupForEvent(virtTables, curEvent, NULL, 0);\n\n\t\tassert(psl[0] == NULL || psl[0] != psl[1]);\n\n\t\tmPtr = MatchPatterns(dispPtr, bindPtr, psl[0], NULL, 0, curEvent, objArr[k], &matchPtr);\n\t\tif (mPtr) {\n\t\t    matchPtrArr[k] = matchPtr;\n\t\t    matchPtr = mPtr;\n\t\t}\n\t\tif (MatchPatterns(dispPtr, bindPtr, psl[1], NULL, 0, curEvent, objArr[k], &matchPtr)) {\n\t\t    matchPtrArr[k] = matchPtr;\n\t\t}\n\t    }\n\t}\n\n\tif (matchPtrArr[k]) {\n\t    ExpandPercents(winPtr, matchPtrArr[k]->script, curEvent, scriptCount++, &scripts);\n\t    /* Null is added to the scripts string to separate the various scripts. */\n\t    Tcl_DStringAppend(&scripts, \"\", 1);\n\t}\n    }\n\n    PromArr_SetSize(bindPtr->promArr, arraySize);\n\n    /*\n     * Remove expired pattern sequences.\n     */\n\n    for (i = 0, newArraySize = 0; i < arraySize; ++i) {\n\tPSList *psList = PromArr_Get(bindPtr->promArr, i);\n\tPSEntry *psEntry;\n\tPSEntry *psNext;\n\n\tfor (psEntry = PSList_First(psList); psEntry; psEntry = psNext) {\n\t    const TkPattern *patPtr;\n\n\t    assert(i + 1 < psEntry->psPtr->numPats);\n\n\t    psNext = PSList_Next(psEntry);\n\t    patPtr = &psEntry->psPtr->pats[i + 1];\n\n\t    /*\n\t     * We have to remove the following entries from promotion list (but\n\t     * only if we don't want to keep it):\n\t     * ------------------------------------------------------------------\n\t     * 1) It is marked as expired (see MatchPatterns()).\n\t     * 2) If we have a Key event, and current entry is matching a Button.\n\t     * 3) If we have a Button event, and current entry is matching a Key.\n\t     * 4) If we have a detailed event, current entry it is also detailed,\n\t     *    we have matching event types, but the details are different.\n\t     * 5) Current entry has been matched with a different window.\n\t     */\n\n\t    if (psEntry->keepIt) {\n\t\tassert(!psEntry->expired);\n\t\tpsEntry->keepIt = 0;\n\t    } else if (psEntry->expired\n\t\t    || psEntry->window != curEvent->xev.xany.window\n\t\t    || (patPtr->info\n\t\t\t&& curEvent->detail.info\n\t\t\t&& patPtr->eventType == (unsigned) curEvent->xev.type\n\t\t\t&& patPtr->info != curEvent->detail.info)) {\n\t\tRemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);\n\t    } else {\n\t\tswitch (patPtr->eventType) {\n\t\tcase ButtonPress:\n\t\tcase ButtonRelease:\n\t\t    if (IsKeyEventType(curEvent->xev.type)) {\n\t\t\tRemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);\n\t\t    }\n\t\t    break;\n\t\tcase KeyPress:\n\t\tcase KeyRelease:\n\t\t    if (IsButtonEventType(curEvent->xev.type)) {\n\t\t\tRemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\tif (!PSList_IsEmpty(psList)) {\n\t    /* We still have promoted sequences, adjust array size. */\n\t    newArraySize = Max(i + 1, newArraySize);\n\t}\n    }\n\n    PromArr_SetSize(bindPtr->promArr, newArraySize);\n\n    if (matchPtrArr != matchPtrBuf) {\n\tTcl_Free(matchPtrArr);\n    }\n\n    if (Tcl_DStringLength(&scripts) == 0) {\n\treturn; /* Nothing to do. */\n    }\n\n    /*\n     * Now go back through and evaluate the binding for each object, in order,\n     * dealing with \"break\" and \"continue\" exceptions appropriately.\n     *\n     * There are two tricks here:\n     * 1. Bindings can be invoked from in the middle of Tcl commands, where\n     *    the interp's result is significant (for example, a widget might be\n     *    deleted because of an error in creating it, so the result contains\n     *    an error message that is eventually going to be returned by the\n     *    creating command). To preserve the result, we save it in a dynamic\n     *    string.\n     * 2. The binding's action can potentially delete the binding, so bindPtr\n     *    may not point to anything valid once the action completes. Thus we\n     *    have to save bindPtr->interp in a local variable in order to restore\n     *    the result.\n     */\n\n    interp = bindPtr->interp;\n\n    /*\n     * Save information about the current screen, then invoke a script if the\n     * screen has changed.\n     */\n\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n    screenPtr = &bindInfoPtr->screenInfo;\n    oldDispPtr = screenPtr->curDispPtr;\n    oldScreen = screenPtr->curScreenIndex;\n\n    if (dispPtr != screenPtr->curDispPtr || Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex) {\n\tscreenPtr->curDispPtr = dispPtr;\n\tscreenPtr->curScreenIndex = Tk_ScreenNumber(tkwin);\n\tChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex);\n    }\n\n    /*\n     * Be careful when dereferencing screenPtr or bindInfoPtr. If we evaluate\n     * something that destroys \".\", bindInfoPtr would have been freed, but we\n     * can tell that by first checking to see if winPtr->mainPtr == NULL.\n     */\n\n    Tcl_Preserve(bindInfoPtr);\n\n    for (p = Tcl_DStringValue(&scripts), end = p + Tcl_DStringLength(&scripts); p < end; ) {\n\tTcl_Size len = strlen(p);\n\tint code;\n\n\tif (!bindInfoPtr->deleted) {\n\t    ++screenPtr->bindingDepth;\n\t}\n\tTcl_AllowExceptions(interp);\n\n\tcode = Tcl_EvalEx(interp, p, len, TCL_EVAL_GLOBAL);\n\tp += len + 1;\n\n\tif (!bindInfoPtr->deleted) {\n\t    --screenPtr->bindingDepth;\n\t}\n\tif (code != TCL_OK && code != TCL_CONTINUE) {\n\t    if (code != TCL_BREAK) {\n\t\tTcl_AddErrorInfo(interp, \"\\n    (command bound to event)\");\n\t\tTcl_BackgroundException(interp, code);\n\t    }\n\t    break;\n\t}\n    }\n\n    if (!bindInfoPtr->deleted\n\t    && screenPtr->bindingDepth > 0\n\t    && (oldDispPtr != screenPtr->curDispPtr || oldScreen != screenPtr->curScreenIndex)) {\n\t/*\n\t * Some other binding script is currently executing, but its screen is\n\t * no longer current. Change the current display back again.\n\t */\n\tscreenPtr->curDispPtr = oldDispPtr;\n\tscreenPtr->curScreenIndex = oldScreen;\n\tChangeScreen(interp, oldDispPtr->name, oldScreen);\n    }\n    Tcl_RestoreInterpState(interp, interpState);\n    Tcl_DStringFree(&scripts);\n    Tcl_Release(bindInfoPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MatchPatterns --\n *\n *\tGiven a list of pattern sequences and the recent event, return\n *\tthe pattern sequence that best matches this event, if there is\n *\tone.\n *\n * Results:\n *\n *\tThe return value is NULL if no match is found. Otherwise the\n *\treturn value is the most specific pattern sequence among all\n *\tthose that match the event table.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n/* helper function */\nstatic bool\nVirtPatIsBound(\n    Tk_BindingTable bindPtr,\t/* Table in which to look for bindings. */\n    PatSeq *psPtr,\t\t/* Test this pattern. */\n    void *object,\t\t/* Check for this binding tag. */\n    PatSeq **physPtrPtr)\t/* Input: the best physical event.\n\t\t\t\t * Output: the physical event associated with matching virtual event. */\n{\n    PatternTableKey key;\n    const struct VirtOwners *owners;\n    unsigned i;\n\n    assert(bindPtr);\n    assert(psPtr);\n    assert(!psPtr->object);\n    assert(physPtrPtr);\n\n    if (*physPtrPtr) {\n\tconst TkPattern *physPatPtr = (*physPtrPtr)->pats;\n\tconst TkPattern *virtPatPtr = psPtr->pats;\n\n\tif (physPatPtr->info || !virtPatPtr->info) {\n\t    if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) {\n\t\treturn false; /* We cannot surpass this match. */\n\t    }\n\t}\n    }\n\n    /* Otherwise on some systems the key contains uninitialized bytes. */\n    memset(&key, 0, sizeof(key));\n\n    key.object = object;\n    key.type = VirtualEvent;\n    owners = psPtr->ptr.owners;\n\n    for (i = 0; i < VirtOwners_Size(owners); ++i) {\n\tTcl_HashEntry *hPtr = VirtOwners_Get(owners, i);\n\n\tkey.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, hPtr);\n\n\tif ((hPtr = Tcl_FindHashEntry(&bindPtr->lookupTables.patternTable, (char *) &key))) {\n\t    /* The physical event matches this virtual event's definition. */\n\t    *physPtrPtr = (PatSeq *) Tcl_GetHashValue(hPtr);\n\t    return true;\n\t}\n    }\n\n    return false;\n}\n\n/* helper function */\nstatic int\nCompare(\n    const PatSeq *fstMatchPtr,\n    const PatSeq *sndMatchPtr) /* Most recent match. */\n{\n    int diff;\n\n    if (!fstMatchPtr) { return +1; }\n    assert(sndMatchPtr);\n    diff = CountSpecialized(fstMatchPtr, sndMatchPtr);\n    return diff ? diff : (int) sndMatchPtr->count - (int) fstMatchPtr->count;\n}\n\n/* helper function */\nstatic int\nCompareModMasks(\n    const PSModMaskArr *fstModMaskArr,\n    const PSModMaskArr *sndModMaskArr,\n    unsigned fstModMask,\n    unsigned sndModMask)\n{\n    int fstCount = 0;\n    int sndCount = 0;\n    int i;\n\n    if (PSModMaskArr_IsEmpty(fstModMaskArr)) {\n\tif (!PSModMaskArr_IsEmpty(sndModMaskArr)) {\n\t    for (i = PSModMaskArr_Size(sndModMaskArr) - 1; i >= 0; --i) {\n\t\tif (*PSModMaskArr_Get(sndModMaskArr, i)) {\n\t\t    ++sndCount;\n\t\t}\n\t    }\n\t}\n    } else if (PSModMaskArr_IsEmpty(sndModMaskArr)) {\n\tfor (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {\n\t    if (*PSModMaskArr_Get(fstModMaskArr, i)) {\n\t\t++fstCount;\n\t    }\n\t}\n    } else {\n\tassert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr));\n\n\tfor (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {\n\t    unsigned fstiModMask = *PSModMaskArr_Get(fstModMaskArr, i);\n\t    unsigned sndiModMask = *PSModMaskArr_Get(sndModMaskArr, i);\n\n\t    if (IsSubsetOf(fstiModMask, sndiModMask)) { ++sndCount; }\n\t    if (IsSubsetOf(sndiModMask, fstiModMask)) { ++fstCount; }\n\t}\n    }\n\n    /* Finally compare modifier masks of last pattern. */\n\n    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }\n    if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }\n\n    return fstCount - sndCount;\n}\n\n/* helper function */\nstatic bool\nIsPSInPSList(\n    const PatSeq *psPtr,   /* Is this pattern sequence... */\n    const PSList *psList)  /* ...an element of this list of patterns sequence? */\n{\n    PSEntry *psEntry;\n\n    TK_DLIST_FOREACH(psEntry, psList) {\n\tif (psEntry->psPtr == psPtr) {\n\t    return true;\n\t}\n    }\n    return false;\n}\n\nstatic PatSeq *\nMatchPatterns(\n    TkDisplay *dispPtr,\t\t/* Display from which the event came. */\n    Tk_BindingTable bindPtr,\t/* Table in which to look for bindings. */\n    PSList *psList,\t\t/* List of potentially matching patterns, can be NULL. */\n    PSList *psSuccList,\t\t/* Add all matching higher-level pattern sequences to this list.\n\t\t\t\t * Can be NULL. */\n    unsigned patIndex,\t\t/* Match only this tag in sequence. */\n    const Event *curEvent,\t/* Match this event. */\n    void *object,\t\t/* Check for this binding tag. */\n    PatSeq **physPtrPtr)\t/* Input: the best physical event; NULL if we test physical events.\n\t\t\t\t * Output: the associated physical event for the best matching virtual\n\t\t\t\t * event; NULL when we match physical events. */\n{\n    Window window;\n    PSEntry *psEntry;\n    PatSeq *bestPtr;\n    PatSeq *bestPhysPtr;\n    unsigned bestModMask;\n    const PSModMaskArr *bestModMaskArr = NULL;\n    bool isModKeyOnly = false;\n    Tcl_Size i;\n\n    assert(dispPtr);\n    assert(bindPtr);\n    assert(curEvent);\n\n    if (!psList) {\n\treturn NULL;\n    }\n\n    bestModMask = 0;\n    bestPtr = NULL;\n    bestPhysPtr = NULL;\n    window = curEvent->xev.xany.window;\n\n    /*\n     * Modifier key events interlaced between patterns parts of a\n     * sequence shall not prevent a sequence from ultimately\n     * matching. Example: when trying to trigger <a><Control-c>\n     * from the keyboard, the sequence of events actually seen is\n     * <a> then <Control_L> (possibly repeating if the key is hold\n     * down), and finally <Control-c>. At the time <Control_L> is\n     * seen, we shall keep the <a><Control-c> pattern sequence in\n     * the promotion list, otherwise it is impossible to trigger\n     * it from the keyboard. See bug [16ef161925].\n     */\n    if (IsKeyEventType(curEvent->xev.type)) {\n\tfor (i = 0; i < dispPtr->numModKeyCodes; ++i) {\n\t    if (dispPtr->modKeyCodes[i] == curEvent->xev.xkey.keycode) {\n\t\tisModKeyOnly = true;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    for (psEntry = PSList_First(psList); psEntry; psEntry = PSList_Next(psEntry)) {\n\tif (patIndex == 0 || psEntry->window == window) {\n\t    PatSeq* psPtr = psEntry->psPtr;\n\n\t    assert(TEST_PSENTRY(psPtr));\n\t    assert((psPtr->object == NULL) == (physPtrPtr != NULL));\n\t    assert(psPtr->object || patIndex == 0);\n\t    assert(psPtr->numPats > patIndex);\n\n\t    if (psPtr->object\n\t\t    ? psPtr->object == object\n\t\t    : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) {\n\t\tTkPattern *patPtr = psPtr->pats + patIndex;\n\n\t\t/* Ignore modifier key events, and KeyRelease events if the current event\n\t\t * is of a different type (e.g. a Button event)\n\t\t */\n\t\tpsEntry->keepIt = isModKeyOnly || \\\n\t\t\t((patPtr->eventType != (unsigned) curEvent->xev.type) && curEvent->xev.type == KeyRelease);\n\n\t\tif (patPtr->eventType == (unsigned) curEvent->xev.type\n\t\t\t&& (curEvent->xev.type != CreateNotify\n\t\t\t\t|| curEvent->xev.xcreatewindow.parent == window)\n\t\t\t&& (!patPtr->name || patPtr->name == curEvent->detail.name)\n\t\t\t&& (!patPtr->info || patPtr->info == curEvent->detail.info)) {\n\t\t    /*\n\t\t     * Resolve the modifier mask for Alt and Mod keys. Unfortunately this\n\t\t     * cannot be done in ParseEventDescription, otherwise this function would\n\t\t     * be the better place.\n\t\t     */\n\t\t    unsigned modMask = ResolveModifiers(dispPtr, patPtr->modMask);\n\t\t    unsigned curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);\n\n\t\t    psEntry->expired = 1; /* Remove it from promotion list. */\n\t\t    psEntry->keepIt = 0;  /* Don't keep matching patterns. */\n\n\t\t    if (IsSubsetOf(modMask, curModMask)) {\n\t\t\tunsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny;\n\n\t\t\tif (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) {\n\t\t\t    PSModMaskArr_Set(psEntry->lastModMaskArr, patIndex, &modMask);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * This pattern is finally matching.\n\t\t\t */\n\n\t\t\tif (psPtr->numPats == patIndex + 1) {\n\t\t\t    if (patPtr->count <= count) {\n\t\t\t\t/*\n\t\t\t\t * This is also a final pattern (i.e. the pattern sequence is complete).\n\t\t\t\t * We always prefer the pattern with better match.\n\t\t\t\t * If completely equal than prefer most recently defined pattern.\n\t\t\t\t */\n\n\t\t\t\tint cmp = Compare(bestPtr, psPtr);\n\n\t\t\t\tif (cmp == 0) {\n\t\t\t\t    cmp = CompareModMasks(psEntry->lastModMaskArr, bestModMaskArr,\n\t\t\t\t\t    modMask, bestModMask);\n\t\t\t\t}\n\n\t\t\t\tif (cmp > 0 || (cmp == 0 && bestPtr->number < psPtr->number)) {\n\t\t\t\t    bestPtr = psPtr;\n\t\t\t\t    bestModMask = modMask;\n\t\t\t\t    bestModMaskArr = psEntry->lastModMaskArr;\n\t\t\t\t    if (physPtrPtr) {\n\t\t\t\t\tbestPhysPtr = *physPtrPtr;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    } else {\n\t\t\t\tDEBUG(psEntry->expired = 0;)\n\t\t\t\tpsEntry->keepIt = 1; /* Don't remove it from promotion list. */\n\t\t\t    }\n\t\t\t} else if (psSuccList) {\n\t\t\t    /*\n\t\t\t     * Not a final pattern, but matching (i.e. successive patterns match the pattern sequence so far),\n\t\t\t     * so promote the pattern sequence to next level if not already promoted in the success list.\n\t\t\t     * But do not promote if count of current pattern is not yet reached.\n\t\t\t     */\n\t\t\t    if (!IsPSInPSList(psPtr, psSuccList)) {\n\t\t\t\tif (patPtr->count == psEntry->count) {\n\t\t\t\t    PSEntry *psNewEntry;\n\n\t\t\t\t    assert(!patPtr->name);\n\t\t\t\t    psNewEntry = MakeListEntry(\n\t\t\t\t\t&bindPtr->lookupTables.entryPool, psPtr, psPtr->modMaskUsed);\n\t\t\t\t    if (!PSModMaskArr_IsEmpty(psNewEntry->lastModMaskArr)) {\n\t\t\t\t\tPSModMaskArr_Set(psNewEntry->lastModMaskArr, patIndex, &modMask);\n\t\t\t\t    }\n\t\t\t\t    assert(psNewEntry->keepIt);\n\t\t\t\t    assert(psNewEntry->count == 1u);\n\t\t\t\t    PSList_Append(psSuccList, psNewEntry);\n\t\t\t\t    psNewEntry->window = window; /* Bind to current window. */\n\t\t\t\t} else {\n\t\t\t\t    assert(psEntry->count < patPtr->count);\n\t\t\t\t    DEBUG(psEntry->expired = 0;)\n\t\t\t\t    psEntry->count += 1;\n\t\t\t\t    psEntry->keepIt = 1; /* Don't remove it from promotion list. */\n\t\t\t\t}\n\t\t\t    } else {\n\t\t\t\t/*\n\t\t\t\t * Pattern sequence is already present in the success list.\n\t\t\t\t */\n\n\t\t\t\tDEBUG(psEntry->expired = 0;)\n\t\t\t\tpsEntry->keepIt = 1; /* Don't remove it from promotion list. */\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    if (bestPhysPtr) {\n\tassert(physPtrPtr);\n\t*physPtrPtr = bestPhysPtr;\n    }\n    return bestPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ExpandPercents --\n *\n *\tGiven a command and an event, produce a new command by replacing %\n *\tconstructs in the original command with information from the X event.\n *\n * Results:\n *\tThe new expanded command is appended to the dynamic string given by\n *\tdsPtr.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nExpandPercents(\n    TkWindow *winPtr,\t\t/* Window where event occurred: needed to get input context. */\n    const char *before,\t\t/* Command containing percent expressions to be replaced. */\n    Event *eventPtr,\t\t/* Event containing information to be used in % replacements. */\n    unsigned scriptCount,\t/* The number of script-based binding patterns matched so far for\n\t\t\t\t * this event. */\n    Tcl_DString *dsPtr)\t\t/* Dynamic string in which to append new command. */\n{\n    unsigned flags;\n    Tcl_DString buf;\n    XEvent *evPtr;\n\n    assert(winPtr);\n    assert(before);\n    assert(eventPtr);\n    assert(dsPtr);\n\n    Tcl_DStringInit(&buf);\n    evPtr = &eventPtr->xev;\n    flags = (evPtr->type < TK_LASTEVENT) ? flagArray[evPtr->type] : 0;\n\n#define SET_NUMBER(value)   { number = (value);\t\t\t     \\\n    snprintf(numStorage, sizeof(numStorage), \"%\" TCL_LL_MODIFIER \"d\", number);\t     \\\n    string = numStorage;\t\t\t\t\t     \\\n    }\n\n#define SET_UNUMBER(value)  { unumber = (value);\t\t\t\t\\\n\tsnprintf(numStorage, sizeof(numStorage), \"%\" TCL_LL_MODIFIER \"u\", unumber);\t\\\n\tstring = numStorage;\t\t\t\t\t\t\\\n    }\n\n    while (1) {\n\tchar numStorage[TCL_INTEGER_SPACE];\n\tconst char *string;\n\tlong long number;     /* signed */\n\tunsigned long long unumber;   /* unsigned */\n\n\t/*\n\t * Find everything up to the next % character and append it to the\n\t * result string.\n\t */\n\n\tfor (string = before; *string && *string != '%'; ++string)\n\t    ;\n\tif (string != before) {\n\t    Tcl_DStringAppend(dsPtr, before, string - before);\n\t    before = string;\n\t}\n\tif (!*before) {\n\t    break;\n\t}\n\n\t/*\n\t * There's a percent sequence here. Process it.\n\t */\n\n\tstring = \"??\";\n\tswitch (before[1]) {\n\tcase '#':\n\t    SET_UNUMBER(evPtr->xany.serial);\n\t    break;\n\tcase 'a':\n\t    if (flags & CONFIG) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xconfigure.above);\n\t\tstring = numStorage;\n\t    }\n\t    break;\n\tcase 'b':\n\t    if (flags & BUTTON) {\n\t\tSET_UNUMBER(evPtr->xbutton.button);\n\t    }\n\t    break;\n\tcase 'c':\n\t    if (flags & EXPOSE) {\n\t\tSET_NUMBER(evPtr->xexpose.count);\n\t    }\n\t    break;\n\tcase 'd':\n\t    if (flags & (CROSSING|FOCUS)) {\n\t\tint detail = (flags & FOCUS) ? evPtr->xfocus.detail : evPtr->xcrossing.detail;\n\t\tstring = TkFindStateString(notifyDetail, detail);\n\t    } else if (flags & CONFIGREQ) {\n\t\tif (evPtr->xconfigurerequest.value_mask & CWStackMode) {\n\t\t    string = TkFindStateString(configureRequestDetail, evPtr->xconfigurerequest.detail);\n\t\t} else {\n\t\t    string = \"\";\n\t\t}\n\t    } else if (flags & VIRTUAL) {\n\t\tXVirtualEvent *vePtr = (XVirtualEvent *) evPtr;\n\t\tstring = vePtr->user_data ? Tcl_GetString(vePtr->user_data) : \"\";\n\t    }\n\t    break;\n\tcase 'f':\n\t    if (flags & CROSSING) {\n\t\tSET_NUMBER(evPtr->xcrossing.focus != 0);\n\t    }\n\t    break;\n\tcase 'h':\n\t    if (flags & EXPOSE) {\n\t\tSET_NUMBER(evPtr->xexpose.height);\n\t    } else if (flags & CONFIG) {\n\t\tSET_NUMBER(evPtr->xconfigure.height);\n\t    } else if (flags & CREATE) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.height);\n\t    } else if (flags & CONFIGREQ) {\n\t\tSET_NUMBER(evPtr->xconfigurerequest.height);\n\t    } else if (flags & RESIZEREQ) {\n\t\tSET_NUMBER(evPtr->xresizerequest.height);\n\t    }\n\t    break;\n\tcase 'i':\n\t    if (flags & CREATE) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xcreatewindow.window);\n\t    } else if (flags & CONFIGREQ) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xconfigurerequest.window);\n\t    } else if (flags & MAPREQ) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xmaprequest.window);\n\t    } else {\n\t\tTkpPrintWindowId(numStorage, evPtr->xany.window);\n\t    }\n\t    string = numStorage;\n\t    break;\n\tcase 'k':\n\t    if (flags & KEY) {\n\t\tSET_UNUMBER(evPtr->xkey.keycode);\n\t    }\n\t    break;\n\tcase 'm':\n\t    if (flags & CROSSING) {\n\t\tstring = TkFindStateString(notifyMode, evPtr->xcrossing.mode);\n\t    } else if (flags & FOCUS) {\n\t\tstring = TkFindStateString(notifyMode, evPtr->xfocus.mode);\n\t    }\n\t    break;\n\tcase 'o':\n\t    if (flags & CREATE) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.override_redirect != 0);\n\t    } else if (flags & MAP) {\n\t\tSET_NUMBER(evPtr->xmap.override_redirect != 0);\n\t    } else if (flags & REPARENT) {\n\t\tSET_NUMBER(evPtr->xreparent.override_redirect != 0);\n\t    } else if (flags & CONFIG) {\n\t\tSET_NUMBER(evPtr->xconfigure.override_redirect != 0);\n\t    }\n\t    break;\n\tcase 'p':\n\t    if (flags & CIRC) {\n\t\tstring = TkFindStateString(circPlace, evPtr->xcirculate.place);\n\t    } else if (flags & CIRCREQ) {\n\t\tstring = TkFindStateString(circPlace, evPtr->xcirculaterequest.place);\n\t    }\n\t    break;\n\tcase 's':\n\t    if (flags & HAS_XKEY_HEAD_AND_STATE) {\n\t\tSET_UNUMBER(evPtr->xkey.state);\n\t    } else if (flags & CROSSING) {\n\t\tSET_UNUMBER(evPtr->xcrossing.state);\n\t    } else if (flags & PROP) {\n\t\tstring = TkFindStateString(propNotify, evPtr->xproperty.state);\n\t    } else if (flags & VISIBILITY) {\n\t\tstring = TkFindStateString(visNotify, evPtr->xvisibility.state);\n\t    }\n\t    break;\n\tcase 't':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tSET_UNUMBER(evPtr->xkey.time);\n\t    } else if (flags & PROP) {\n\t\tSET_UNUMBER(evPtr->xproperty.time);\n\t    }\n\t    break;\n\tcase 'v':\n\t    SET_UNUMBER(evPtr->xconfigurerequest.value_mask);\n\t    break;\n\tcase 'w':\n\t    if (flags & EXPOSE) {\n\t\tSET_NUMBER(evPtr->xexpose.width);\n\t    } else if (flags & CONFIG) {\n\t\tSET_NUMBER(evPtr->xconfigure.width);\n\t    } else if (flags & CREATE) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.width);\n\t    } else if (flags & CONFIGREQ) {\n\t\tSET_NUMBER(evPtr->xconfigurerequest.width);\n\t    } else if (flags & RESIZEREQ) {\n\t\tSET_NUMBER(evPtr->xresizerequest.width);\n\t    }\n\t    break;\n\tcase 'x':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tSET_NUMBER(evPtr->xkey.x);\n\t    } else if (flags & EXPOSE) {\n\t\tSET_NUMBER(evPtr->xexpose.x);\n\t    } else if (flags & (CREATE|CONFIG|GRAVITY)) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.x);\n\t    } else if (flags & REPARENT) {\n\t\tSET_NUMBER(evPtr->xreparent.x);\n\t    } else if (flags & CONFIGREQ) {\n\t\tSET_NUMBER(evPtr->xconfigurerequest.x);\n\t    }\n\t    break;\n\tcase 'y':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tSET_NUMBER(evPtr->xkey.y);\n\t    } else if (flags & EXPOSE) {\n\t\tSET_NUMBER(evPtr->xexpose.y);\n\t    } else if (flags & (CREATE|CONFIG|GRAVITY)) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.y);\n\t    } else if (flags & REPARENT) {\n\t\tSET_NUMBER(evPtr->xreparent.y);\n\t    } else if (flags & CONFIGREQ) {\n\t\tSET_NUMBER(evPtr->xconfigurerequest.y);\n\t    }\n\t    break;\n\tcase 'A':\n\t    if (flags & KEY) {\n\t\tTcl_DStringFree(&buf);\n\t\tstring = TkpGetString(winPtr, evPtr, &buf);\n\t    }\n\t    break;\n\tcase 'B':\n\t    if (flags & CREATE) {\n\t\tSET_NUMBER(evPtr->xcreatewindow.border_width);\n\t    } else if (flags & CONFIGREQ) {\n\t\tSET_NUMBER(evPtr->xconfigurerequest.border_width);\n\t    } else if (flags & CONFIG) {\n\t\tSET_NUMBER(evPtr->xconfigure.border_width);\n\t    }\n\t    break;\n\tcase 'D':\n\t    if (flags & WHEEL) {\n\t\tSET_NUMBER((int)evPtr->xbutton.button); /* mis-use button field for this */\n\t    }\n\t    break;\n\tcase 'E':\n\t    SET_NUMBER(evPtr->xany.send_event != 0);\n\t    break;\n\tcase 'K':\n\t    if (flags & KEY) {\n\t\tconst char *name = TkKeysymToString(eventPtr->detail.info);\n\t\tif (name) {\n\t\t    string = name;\n\t\t}\n\t    }\n\t    break;\n\tcase 'M':\n\t    SET_UNUMBER(scriptCount);\n\t    break;\n\tcase 'N':\n\t    if (flags & KEY) {\n\t\tSET_UNUMBER(eventPtr->detail.info);\n\t    }\n\t    break;\n\tcase 'P':\n\t    if (flags & PROP) {\n\t\tstring = Tk_GetAtomName((Tk_Window) winPtr, evPtr->xproperty.atom);\n\t    }\n\t    break;\n\tcase 'R':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xkey.root);\n\t\tstring = numStorage;\n\t    }\n\t    break;\n\tcase 'S':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tTkpPrintWindowId(numStorage, evPtr->xkey.subwindow);\n\t\tstring = numStorage;\n\t    }\n\t    break;\n\tcase 'T':\n\t    SET_NUMBER(evPtr->type);\n\t    break;\n\tcase 'W': {\n\t    Tk_Window tkwin = Tk_IdToWindow(evPtr->xany.display, evPtr->xany.window);\n\t    if (tkwin) {\n\t\tstring = Tk_PathName(tkwin);\n\t    }\n\t    break;\n\t}\n\tcase 'X':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tSET_NUMBER(evPtr->xkey.x_root);\n\t    }\n\t    break;\n\tcase 'Y':\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tSET_NUMBER(evPtr->xkey.y_root);\n\t    }\n\t    break;\n\tdefault:\n\t    numStorage[0] = before[1];\n\t    numStorage[1] = '\\0';\n\t    string = numStorage;\n\t    break;\n\t}\n\t{   /* local scope */\n\t    int cvtFlags;\n\t    Tcl_Size spaceNeeded = Tcl_ScanElement(string, &cvtFlags);\n\t    Tcl_Size length = Tcl_DStringLength(dsPtr);\n\n\t    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\t    spaceNeeded = Tcl_ConvertElement(\n\t\t    string, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES);\n\t    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\t    before += 2;\n\t}\n    }\n\n#undef SET_NUMBER\n#undef SET_UNUMBER\n\n    Tcl_DStringFree(&buf);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ChangeScreen --\n *\n *\tThis function is invoked whenever the current screen changes in an\n *\tapplication. It invokes a Tcl command named \"tk::ScreenChanged\",\n *\tpassing it the screen name as argument. tk::ScreenChanged does things\n *\tlike making the tk::Priv variable point to an array for the current\n *\tdisplay.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what tk::ScreenChanged does. If an error occurs then\n *\tbgerror will be invoked.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nChangeScreen(\n    Tcl_Interp *interp,\t\t/* Interpreter in which to invoke command. */\n    char *dispName,\t\t/* Name of new display. */\n    int screenIndex)\t\t/* Index of new screen. */\n{\n    Tcl_Obj *cmdObj = Tcl_ObjPrintf(\"::tk::ScreenChanged %s.%d\", dispName, screenIndex);\n    int code;\n\n    Tcl_IncrRefCount(cmdObj);\n    code = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_AddErrorInfo(interp, \"\\n    (changing screen in event binding)\");\n\tTcl_BackgroundException(interp, code);\n    }\n    Tcl_DecrRefCount(cmdObj);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_EventCmd --\n *\n *\tThis function is invoked to process the \"event\" Tcl command. It is\n *\tused to define and generate events.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_EventObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int index;\n    Tcl_Size i;\n    char *name;\n    const char *event;\n    Tk_Window tkwin;\n    TkBindInfo bindInfo;\n    VirtualEventTable *vetPtr;\n\n    static const char *const optionStrings[] = { \"add\",\n#if SUPPORT_DEBUGGING\n\t\"debug\",\n#endif\n\t\"delete\", \"generate\", \"info\", NULL\n    };\n    enum options { EVENT_ADD,\n#if SUPPORT_DEBUGGING\n\tEVENT_DEBUG,\n#endif\n\tEVENT_DELETE, EVENT_GENERATE, EVENT_INFO\n    };\n\n    assert(clientData);\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(\n\t    interp, objv[1], optionStrings, sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    tkwin = (Tk_Window) clientData;\n    bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo;\n    vetPtr = &bindInfo->virtualEventTable;\n\n    switch ((enum options) index) {\n    case EVENT_ADD:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"virtual sequence ?sequence ...?\");\n\t    return TCL_ERROR;\n\t}\n\tname = Tcl_GetString(objv[2]);\n\tfor (i = 3; i < objc; ++i) {\n\t    event = Tcl_GetString(objv[i]);\n\t    if (!CreateVirtualEvent(interp, vetPtr, name, event)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tbreak;\n#if SUPPORT_DEBUGGING\n    case EVENT_DEBUG:\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"debug number\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc < 3) {\n\t    Tcl_SetObjResult(interp,\n\t\tTcl_NewIntObj(BindCount));\n\t    return TCL_OK;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[2], &BindCount) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\treturn TCL_OK;\n#endif\n    case EVENT_DELETE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"virtual ?sequence ...?\");\n\t    return TCL_ERROR;\n\t}\n\tname = Tcl_GetString(objv[2]);\n\tif (objc == 3) {\n\t    return DeleteVirtualEvent(interp, vetPtr, name, NULL);\n\t}\n\tfor (i = 3; i < objc; ++i) {\n\t    event = Tcl_GetString(objv[i]);\n\t    if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tbreak;\n    case EVENT_GENERATE:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window event ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\treturn HandleEventGenerate(interp, tkwin, objc - 2, objv + 2);\n    case EVENT_INFO:\n\tif (objc == 2) {\n\t    GetAllVirtualEvents(interp, vetPtr);\n\t    return TCL_OK;\n\t}\n\tif (objc == 3) {\n\t    return GetVirtualEvent(interp, vetPtr, objv[2]);\n\t}\n\tTcl_WrongNumArgs(interp, 2, objv, \"?virtual?\");\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitVirtualEventTable --\n *\n *\tGiven storage for a virtual event table, set up the fields to prepare\n *\ta new domain in which virtual events may be defined.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\t*vetPtr is now initialized.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitVirtualEventTable(\n    VirtualEventTable *vetPtr)\t/* Pointer to virtual event table. Memory is supplied by the caller. */\n{\n    assert(vetPtr);\n    memset(vetPtr, 0, sizeof(*vetPtr));\n    Tcl_InitHashTable(&vetPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int));\n    Tcl_InitHashTable(&vetPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int));\n    Tcl_InitHashTable(&vetPtr->nameTable, TCL_ONE_WORD_KEYS);\n    PSList_Init(&vetPtr->lookupTables.entryPool);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DeleteVirtualEventTable --\n *\n *\tDelete the contents of a virtual event table. The caller is\n *\tresponsible for freeing any memory used by the table itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDeleteVirtualEventTable(\n    VirtualEventTable *vetPtr)\t/* The virtual event table to delete. */\n{\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    assert(vetPtr);\n\n    hPtr = Tcl_FirstHashEntry(&vetPtr->lookupTables.patternTable, &search);\n    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {\n\tPatSeq *nextPtr;\n\tPatSeq *psPtr;\n\n\tfor (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {\n\t    assert(TEST_PSENTRY(psPtr));\n\t    nextPtr = psPtr->nextSeqPtr;\n\t    DEBUG(psPtr->owned = 0;)\n\t    FreePatSeq(psPtr);\n\t}\n    }\n    Tcl_DeleteHashTable(&vetPtr->lookupTables.patternTable);\n\n    hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);\n    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {\n\tTcl_Free(Tcl_GetHashValue(hPtr));\n    }\n    Tcl_DeleteHashTable(&vetPtr->nameTable);\n\n    ClearLookupTable(&vetPtr->lookupTables, NULL);\n    Tcl_DeleteHashTable(&vetPtr->lookupTables.listTable);\n\n    DEBUG(countEntryItems -= PSList_Size(&vetPtr->lookupTables.entryPool);)\n    PSList_Traverse(&vetPtr->lookupTables.entryPool, FreePatSeqEntry);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateVirtualEvent --\n *\n *\tAdd a new definition for a virtual event. If the virtual event is\n *\talready defined, the new definition augments those that already exist.\n *\n * Results:\n *\tThe return value is TCL_ERROR if an error occurred while creating the\n *\tvirtual binding. In this case, an error message will be left in the\n *\tinterp's result. If all went well then the return value is TCL_OK.\n *\n * Side effects:\n *\tThe virtual event may cause future calls to Tk_BindEvent to behave\n *\tdifferently than they did previously.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nCreateVirtualEvent(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    VirtualEventTable *vetPtr,\t/* Table in which to augment virtual event. */\n    char *virtString,\t\t/* Name of new virtual event. */\n    const char *eventString)\t/* String describing physical event that triggers virtual event. */\n{\n    PatSeq *psPtr;\n    int dummy;\n    Tcl_HashEntry *vhPtr;\n    PhysOwned *owned;\n    Tk_Uid virtUid;\n\n    assert(vetPtr);\n    assert(virtString);\n    assert(eventString);\n\n    if (!(virtUid = GetVirtualEventUid(interp, virtString))) {\n\treturn false;\n    }\n\n    /*\n     * Find/create physical event.\n     */\n\n    if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, 1, 0, NULL))) {\n\treturn false;\n    }\n    assert(TEST_PSENTRY(psPtr));\n\n    /*\n     * Find/create virtual event.\n     */\n\n    vhPtr = Tcl_CreateHashEntry(&vetPtr->nameTable, virtUid, &dummy);\n\n    /*\n     * Make virtual event own the physical event.\n     */\n\n    owned = (PhysOwned *)Tcl_GetHashValue(vhPtr);\n\n    if (!PhysOwned_Contains(owned, psPtr)) {\n\tPhysOwned_Append(&owned, psPtr);\n\tTcl_SetHashValue(vhPtr, owned);\n\tDEBUG(psPtr->owned = 1;)\n\tInsertPatSeq(&vetPtr->lookupTables, psPtr);\n\t/* Make physical event so it can trigger the virtual event. */\n\tVirtOwners_Append(&psPtr->ptr.owners, vhPtr);\n    }\n\n    return true;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteVirtualEvent --\n *\n *\tRemove the definition of a given virtual event. If the event string is\n *\tNULL, all definitions of the virtual event will be removed.\n *\tOtherwise, just the specified definition of the virtual event will be\n *\tremoved.\n *\n * Results:\n *\tThe result is a standard Tcl return value. If an error occurs then the\n *\tinterp's result will contain an error message. It is not an error to\n *\tattempt to delete a virtual event that does not exist or a definition\n *\tthat does not exist.\n *\n * Side effects:\n *\tThe virtual event given by virtString may be removed from the virtual\n *\tevent table.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nDeleteVirtualEvent(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    VirtualEventTable *vetPtr,\t/* Table in which to delete event. */\n    char *virtString,\t\t/* String describing event sequence that triggers binding. */\n    const char *eventString)\t/* The event sequence that should be deleted, or NULL to delete\n\t\t\t\t * all event sequences for the entire virtual event. */\n{\n    int iPhys;\n    Tk_Uid virtUid;\n    Tcl_HashEntry *vhPtr;\n    PhysOwned *owned;\n    const PatSeq *eventPSPtr;\n    PatSeq *lastElemPtr;\n\n    assert(vetPtr);\n    assert(virtString);\n\n    if (!(virtUid = GetVirtualEventUid(interp, virtString))) {\n\treturn TCL_ERROR;\n    }\n\n    if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {\n\treturn TCL_OK;\n    }\n    owned = (PhysOwned *)Tcl_GetHashValue(vhPtr);\n\n    eventPSPtr = NULL;\n    if (eventString) {\n\tLookupTables *lookupTables = &vetPtr->lookupTables;\n\n\t/*\n\t * Delete only the specific physical event associated with the virtual\n\t * event. If the physical event doesn't already exist, or the virtual\n\t * event doesn't own that physical event, return w/o doing anything.\n\t */\n\n\teventPSPtr = FindSequence(interp, lookupTables, NULL, eventString, 0, 0, NULL);\n\tif (!eventPSPtr) {\n\t    const char *string = Tcl_GetString(Tcl_GetObjResult(interp));\n\t    return string[0] ? TCL_ERROR : TCL_OK;\n\t}\n    }\n\n    for (iPhys = PhysOwned_Size(owned); --iPhys >= 0; ) {\n\tPatSeq *psPtr = PhysOwned_Get(owned, iPhys);\n\n\tassert(TEST_PSENTRY(psPtr));\n\n\tif (!eventPSPtr || psPtr == eventPSPtr) {\n\t    VirtOwners *owners = psPtr->ptr.owners;\n\t    int iVirt = VirtOwners_Find(owners, vhPtr);\n\n\t    assert(iVirt != -1); /* Otherwise we couldn't find owner, and this should not happen. */\n\n\t    /*\n\t     * Remove association between this physical event and the given\n\t     * virtual event that it triggers.\n\t     */\n\n\t    if (VirtOwners_Size(owners) > 1) {\n\t\t/*\n\t\t * This physical event still triggers some other virtual\n\t\t * event(s). Consolidate the list of virtual owners for this\n\t\t * physical event so it no longer triggers the given virtual\n\t\t * event.\n\t\t */\n\t\tVirtOwners_Set(owners, iVirt, VirtOwners_Back(owners));\n\t\tVirtOwners_PopBack(owners);\n\t    } else {\n\t\t/*\n\t\t * Removed last reference to this physical event, so remove it\n\t\t * from lookup table.\n\t\t */\n\t\tDEBUG(psPtr->owned = 0;)\n\t\tRemovePatSeqFromLookup(&vetPtr->lookupTables, psPtr);\n\t\tDeletePatSeq(psPtr);\n\t    }\n\n\t    /*\n\t     * Now delete the virtual event's reference to the physical event.\n\t     */\n\n\t    lastElemPtr = PhysOwned_Back(owned);\n\n\t    if (PhysOwned_PopBack(owned) > 0 && eventPSPtr) {\n\t\t/*\n\t\t * Just deleting this one physical event. Consolidate list of\n\t\t * owned physical events and return.\n\t\t */\n\t\tif ((size_t) iPhys < PhysOwned_Size(owned)) {\n\t\t    PhysOwned_Set(owned, iPhys, lastElemPtr);\n\t\t}\n\t\treturn TCL_OK;\n\t    }\n\t}\n    }\n\n    if (PhysOwned_IsEmpty(owned)) {\n\t/*\n\t * All the physical events for this virtual event were deleted, either\n\t * because there was only one associated physical event or because the\n\t * caller was deleting the entire virtual event. Now the virtual event\n\t * itself should be deleted.\n\t */\n\tPhysOwned_Free(&owned);\n\tTcl_DeleteHashEntry(vhPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetVirtualEvent --\n *\n *\tReturn the list of physical events that can invoke the given virtual\n *\tevent.\n *\n * Results:\n *\tThe return value is TCL_OK and the interp's result is filled with the\n *\tstring representation of the physical events associated with the\n *\tvirtual event; if there are no physical events for the given virtual\n *\tevent, the interp's result is filled with and empty string. If the\n *\tvirtual event string is improperly formed, then TCL_ERROR is returned\n *\tand an error message is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetVirtualEvent(\n    Tcl_Interp *interp,\t\t/* Interpreter for reporting. */\n    VirtualEventTable *vetPtr,\t/* Table in which to look for event. */\n    Tcl_Obj *virtName)\t\t/* String describing virtual event. */\n{\n    Tcl_HashEntry *vhPtr;\n    unsigned iPhys;\n    const PhysOwned *owned;\n    Tk_Uid virtUid;\n    Tcl_Obj *resultObj;\n\n    assert(vetPtr);\n    assert(virtName);\n\n    if (!(virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName)))) {\n\treturn TCL_ERROR;\n    }\n\n    if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {\n\treturn TCL_OK;\n    }\n\n    resultObj = Tcl_NewObj();\n    owned = (const PhysOwned *)Tcl_GetHashValue(vhPtr);\n    for (iPhys = 0; iPhys < PhysOwned_Size(owned); ++iPhys) {\n\tTcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(PhysOwned_Get(owned, iPhys)));\n    }\n    Tcl_SetObjResult(interp, resultObj);\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetAllVirtualEvents --\n *\n *\tReturn a list that contains the names of all the virtual event\n *\tdefined.\n *\n * Results:\n *\tThere is no return value. The interp's result is modified to hold a\n *\tTcl list with one entry for each virtual event in nameTable.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nGetAllVirtualEvents(\n    Tcl_Interp *interp,\t\t/* Interpreter returning result. */\n    VirtualEventTable *vetPtr)\t/* Table containing events. */\n{\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n    Tcl_Obj *resultObj;\n\n    assert(vetPtr);\n\n    resultObj = Tcl_NewObj();\n    hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);\n    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {\n\tTcl_Obj* msg = Tcl_ObjPrintf(\"<<%s>>\", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr));\n\tTcl_ListObjAppendElement(NULL, resultObj, msg);\n    }\n    Tcl_SetObjResult(interp, resultObj);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * HandleEventGenerate --\n *\n *\tHelper function for the \"event generate\" command. Generate and process\n *\tan XEvent, constructed from information parsed from the event\n *\tdescription string and its optional arguments.\n *\n *\tobjv[0] contains name of the target window.\n *\tobjv[1] contains pattern string for one event (e.g, <Control-v>).\n *\tobjv[2..objc-1] contains -field/option pairs for specifying additional\n *\t\t\tdetail in the generated event.\n *\n *\tEither virtual or physical events can be generated this way. The event\n *\tdescription string must contain the specification for only one event.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen constructing the event,\n *\t    event.xany.serial is filled with the current X serial number.\n *\t    event.xany.window is filled with the target window.\n *\t    event.xany.display is filled with the target window's display.\n *\tAny other fields in eventPtr which are not specified by the pattern\n *\tstring or the optional arguments, are set to 0.\n *\n *\tThe event may be handled synchronously or asynchronously, depending on\n *\tthe value specified by the optional \"-when\" option. The default\n *\tsetting is synchronous.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nHandleEventGenerate(\n    Tcl_Interp *interp,\t\t/* Interp for errors return and name lookup. */\n    Tk_Window mainWin,\t\t/* Main window associated with interp. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    union { XEvent general; XVirtualEvent virt; } event;\n\n    const char *p;\n    const char *name;\n    const char *windowName;\n    Tcl_QueuePosition pos;\n    TkPattern pat;\n    Tk_Window tkwin;\n    Tk_Window tkwin2;\n    TkWindow *mainPtr;\n    unsigned eventMask;\n    Tcl_Obj *userDataObj;\n    int synch;\n    int warp;\n    unsigned count;\n    unsigned flags;\n    int number;\n    Tcl_Size i;\n\n    static const char *const fieldStrings[] = {\n\t\"-when\",\t\"-above\",\t\"-borderwidth\",\t\"-button\",\n\t\"-count\",\t\"-data\",\t\"-delta\",\t\"-detail\",\n\t\"-focus\",\t\"-height\",\n\t\"-keycode\",\t\"-keysym\",\t\"-mode\",\t\"-override\",\n\t\"-place\",\t\"-root\",\t\"-rootx\",\t\"-rooty\",\n\t\"-sendevent\",\t\"-serial\",\t\"-state\",\t\"-subwindow\",\n\t\"-time\",\t\"-warp\",\t\"-width\",\t\"-window\",\n\t\"-x\",\t\t\"-y\",\t\tNULL\n    };\n    enum field {\n\tEVENT_WHEN,\tEVENT_ABOVE,\tEVENT_BORDER,\tEVENT_BUTTON,\n\tEVENT_COUNT,\tEVENT_DATA,\tEVENT_DELTA,\tEVENT_DETAIL,\n\tEVENT_FOCUS,\tEVENT_HEIGHT,\n\tEVENT_KEYCODE,\tEVENT_KEYSYM,\tEVENT_MODE,\tEVENT_OVERRIDE,\n\tEVENT_PLACE,\tEVENT_ROOT,\tEVENT_ROOTX,\tEVENT_ROOTY,\n\tEVENT_SEND,\tEVENT_SERIAL,\tEVENT_STATE,\tEVENT_SUBWINDOW,\n\tEVENT_TIME,\tEVENT_WARP,\tEVENT_WIDTH,\tEVENT_WINDOW,\n\tEVENT_X,\tEVENT_Y\n    };\n\n    assert(mainWin);\n\n    windowName = Tcl_GetString(objv[0]);\n    if (!windowName[0]) {\n\ttkwin = mainWin;\n    } else if (!NameToWindow(interp, mainWin, objv[0], &tkwin)) {\n\treturn TCL_ERROR;\n    }\n\n    mainPtr = (TkWindow *) mainWin;\n    if (!tkwin || mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window id \\\"%s\\\" does not exist in this application\",\n\t\tTcl_GetString(objv[0])));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"WINDOW\", Tcl_GetString(objv[0]), (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    name = Tcl_GetString(objv[1]);\n    p = name;\n    eventMask = 0;\n    userDataObj = NULL;\n    if ((count = ParseEventDescription(interp, &p, &pat, &eventMask)) == 0) {\n\treturn TCL_ERROR;\n    }\n    if (count != 1u) {\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewStringObj(\"Double, Triple, or Quadruple modifier not allowed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"BAD_MODIFIER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (*p) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"only one event specification allowed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"MULTIPLE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    memset(&event, 0, sizeof(event));\n    event.general.xany.type = pat.eventType;\n    event.general.xany.serial = NextRequest(Tk_Display(tkwin));\n    event.general.xany.send_event = 0;\n    if (windowName[0]) {\n\tevent.general.xany.window = Tk_WindowId(tkwin);\n    } else {\n\tevent.general.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));\n    }\n    event.general.xany.display = Tk_Display(tkwin);\n\n    flags = flagArray[event.general.xany.type];\n    if (flags & DESTROY) {\n\t/*\n\t * Event DestroyNotify should be generated by destroying the window.\n\t */\n\tTk_DestroyWindow(tkwin);\n\treturn TCL_OK;\n    }\n    if (flags & HAS_XKEY_HEAD_AND_STATE) {\n\tevent.general.xkey.state = pat.modMask;\n\tif (flags & KEY) {\n\t    TkpSetKeycodeAndState(tkwin, pat.info, &event.general);\n\t} else if (flags & BUTTON) {\n\t    event.general.xbutton.button = pat.info;\n\t} else if (flags & VIRTUAL) {\n\t    event.virt.name = pat.name;\n\t}\n    }\n    if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {\n\tevent.general.xcreatewindow.window = event.general.xany.window;\n    }\n\n    if (flags & HAS_XKEY_HEAD) {\n\tevent.general.xkey.x_root = -1;\n\tevent.general.xkey.y_root = -1;\n    }\n\n    if (event.general.xany.type == FocusIn || event.general.xany.type == FocusOut) {\n\tevent.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC;\n    }\n\n    /*\n     * Process the remaining arguments to fill in additional fields of the event.\n     */\n\n    synch = 1;\n    warp = 0;\n    pos = TCL_QUEUE_TAIL;\n\n    for (i = 2; i < objc; i += 2) {\n\tTcl_Obj *optionPtr, *valuePtr;\n#if defined(_MSC_VER)\n\t/* Work around MSVC compiler optimization bug, see [d93c8175fd]. */\n\tvolatile int badOpt = 0;\n#else\n\tint badOpt = 0;\n#endif\n\tint index;\n\n\toptionPtr = objv[i];\n\tvaluePtr = objv[i + 1];\n\n\tif (Tcl_GetIndexFromObjStruct(interp, optionPtr, fieldStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (IsOdd(objc)) {\n\t    /*\n\t     * This test occurs after Tcl_GetIndexFromObj() so that \"event\n\t     * generate <Button> -xyz\" will return the error message that\n\t     * \"-xyz\" is a bad option, rather than that the value for \"-xyz\"\n\t     * is missing.\n\t     */\n\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(optionPtr)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"MISSING_VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tswitch ((enum field) index) {\n\tcase EVENT_WARP:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (!(flags & CAN_WARP)) {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_WHEN:\n\t    pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, queuePosition, valuePtr);\n\t    if ((int) pos < -1) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    synch = ((int) pos == -1);\n\t    break;\n\tcase EVENT_ABOVE:\n\t    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & CONFIG) {\n\t\tevent.general.xconfigure.above = Tk_WindowId(tkwin2);\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_BORDER:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & (CREATE|CONFIG)) {\n\t\tevent.general.xcreatewindow.border_width = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_BUTTON:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & BUTTON) {\n\t\tif (number >= Button4) {\n\t\t    number += (Button8 - Button4);\n\t\t}\n\t\tevent.general.xbutton.button = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_COUNT:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & EXPOSE) {\n\t\tevent.general.xexpose.count = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_DATA:\n\t    if (flags & VIRTUAL) {\n\t\t/*\n\t\t * Do not increment reference count until after parsing\n\t\t * completes and we know that the event generation is really\n\t\t * going to happen.\n\t\t */\n\t\tuserDataObj = valuePtr;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_DELTA:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & WHEEL) {\n\t\tevent.general.xbutton.button = (unsigned)number; /* mis-use button field for this */\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_DETAIL:\n\t    number = TkFindStateNumObj(interp, optionPtr, notifyDetail, valuePtr);\n\t    if (number < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & FOCUS) {\n\t\tevent.general.xfocus.detail = number;\n\t    } else if (flags & CROSSING) {\n\t\tevent.general.xcrossing.detail = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_FOCUS:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & CROSSING) {\n\t\tevent.general.xcrossing.focus = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_HEIGHT:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & EXPOSE) {\n\t\tevent.general.xexpose.height = number;\n\t    } else if (flags & CONFIG) {\n\t\tevent.general.xconfigure.height = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_KEYCODE:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & KEY) {\n\t\tevent.general.xkey.keycode = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_KEYSYM: {\n\t    KeySym keysym;\n\t    const char *value;\n\n\t    value = Tcl_GetString(valuePtr);\n\t    keysym = TkStringToKeysym(value);\n\t    if (keysym == NoSymbol) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"unknown keysym \\\"%s\\\"\", value));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"KEYSYM\", value, (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    TkpSetKeycodeAndState(tkwin, keysym, &event.general);\n\t    if (event.general.xkey.keycode == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"no keycode for keysym \\\"%s\\\"\", value));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"KEYCODE\", value, (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (!(flags & KEY)) {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\t}\n\tcase EVENT_MODE:\n\t    if ((number = TkFindStateNumObj(interp, optionPtr, notifyMode, valuePtr)) < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & CROSSING) {\n\t\tevent.general.xcrossing.mode = number;\n\t    } else if (flags & FOCUS) {\n\t\tevent.general.xfocus.mode = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_OVERRIDE:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & CREATE) {\n\t\tevent.general.xcreatewindow.override_redirect = number;\n\t    } else if (flags & MAP) {\n\t\tevent.general.xmap.override_redirect = number;\n\t    } else if (flags & REPARENT) {\n\t\tevent.general.xreparent.override_redirect = number;\n\t    } else if (flags & CONFIG) {\n\t\tevent.general.xconfigure.override_redirect = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_PLACE:\n\t    if ((number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr)) < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & CIRC) {\n\t\tevent.general.xcirculate.place = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_ROOT:\n\t    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.root = Tk_WindowId(tkwin2);\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_ROOTX:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.x_root = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_ROOTY:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.y_root = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_SEND: {\n\t    const char *value;\n\n\t    value = Tcl_GetString(valuePtr);\n\t    if (isdigit(UCHAR(value[0]))) {\n\t\t/*\n\t\t * Allow arbitrary integer values for the field; they are\n\t\t * needed by a few of the tests in the Tk test suite.\n\t\t */\n\t\tif (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (number) {\n\t\t    /*\n\t\t     * send_event only expects 1 or 0. We cannot allow arbitrary non-zero\n\t\t     * values, otherwise the thing with GENERATED_FOCUS_EVENT_MAGIC will not\n\t\t     * work.\n\t\t     */\n\t\t    number = 1;\n\t\t}\n\t    } else if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    event.general.xany.send_event |= number;\n\t    break;\n\t}\n\tcase EVENT_SERIAL:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    event.general.xany.serial = number;\n\t    break;\n\tcase EVENT_STATE:\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tif (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (flags & HAS_XKEY_HEAD_AND_STATE) {\n\t\t    event.general.xkey.state = number;\n\t\t} else {\n\t\t    event.general.xcrossing.state = number;\n\t\t}\n\t    } else if (flags & VISIBILITY) {\n\t\tif ((number = TkFindStateNumObj(interp, optionPtr, visNotify, valuePtr)) < 0) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tevent.general.xvisibility.state = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_SUBWINDOW:\n\t    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.subwindow = Tk_WindowId(tkwin2);\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_TIME: {\n\t    if (strcmp(Tcl_GetString(valuePtr), \"current\") == 0) {\n\t\tTkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\t\tBindInfo *biPtr = mainPtr->mainPtr->bindInfo;\n\t\tnumber = dispPtr->lastEventTime + (CurrentTimeInMilliSecs() - biPtr->lastCurrentTime);\n\t    } else if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.time = number;\n\t    } else if (flags & PROP) {\n\t\tevent.general.xproperty.time = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\t}\n\tcase EVENT_WIDTH:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & EXPOSE) {\n\t\tevent.general.xexpose.width = number;\n\t    } else if (flags & (CREATE|CONFIG)) {\n\t\tevent.general.xcreatewindow.width = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_WINDOW:\n\t    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {\n\t\tevent.general.xcreatewindow.window = Tk_WindowId(tkwin2);\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_X:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.x = number;\n\n\t\t/*\n\t\t * Only modify rootx as well if it hasn't been changed.\n\t\t */\n\n\t\tif (event.general.xkey.x_root == -1) {\n\t\t    int rootX, rootY;\n\n\t\t    Tk_GetRootCoords(tkwin, &rootX, &rootY);\n\t\t    event.general.xkey.x_root = rootX + number;\n\t\t}\n\t    } else if (flags & EXPOSE) {\n\t\tevent.general.xexpose.x = number;\n\t    } else if (flags & (CREATE|CONFIG|GRAVITY)) {\n\t\tevent.general.xcreatewindow.x = number;\n\t    } else if (flags & REPARENT) {\n\t\tevent.general.xreparent.x = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\tcase EVENT_Y:\n\t    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (flags & HAS_XKEY_HEAD) {\n\t\tevent.general.xkey.y = number;\n\n\t\t/*\n\t\t * Only modify rooty as well if it hasn't been changed.\n\t\t */\n\n\t\tif (event.general.xkey.y_root == -1) {\n\t\t    int rootX, rootY;\n\n\t\t    Tk_GetRootCoords(tkwin, &rootX, &rootY);\n\t\t    event.general.xkey.y_root = rootY + number;\n\t\t}\n\t    } else if (flags & EXPOSE) {\n\t\tevent.general.xexpose.y = number;\n\t    } else if (flags & (CREATE|CONFIG|GRAVITY)) {\n\t\tevent.general.xcreatewindow.y = number;\n\t    } else if (flags & REPARENT) {\n\t\tevent.general.xreparent.y = number;\n\t    } else {\n\t\tbadOpt = 1;\n\t    }\n\t    break;\n\t}\n\n\tif (badOpt) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s event doesn't accept \\\"%s\\\" option\", name, Tcl_GetString(optionPtr)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"BAD_OPTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Don't generate events for windows that don't exist yet.\n     */\n\n    if (event.general.xany.window) {\n\tif (userDataObj) {\n\t    /*\n\t     * Must be virtual event to set that variable to non-NULL. Now we want\n\t     * to install the object into the event. Note that we must incr the\n\t     * refcount before firing it into the low-level event subsystem; the\n\t     * refcount will be decremented once the event has been processed.\n\t     */\n\t    event.virt.user_data = userDataObj;\n\t    Tcl_IncrRefCount(userDataObj);\n\t}\n\n\t/*\n\t * We allow warping relative to the screen's root window, or relative to a\n\t * Tk window provided that it is mapped.\n\t */\n\n\tif (warp && (! windowName[0] || Tk_IsMapped(tkwin))) {\n\t    TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display);\n\n\t    Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, event.general.xmotion.window);\n\n\t    if (warpWindow != dispPtr->warpWindow) {\n\t\tif (warpWindow) {\n\t\t    Tcl_Preserve(warpWindow);\n\t\t}\n\t\tif (dispPtr->warpWindow) {\n\t\t    Tcl_Release(dispPtr->warpWindow);\n\t\t}\n\t\tdispPtr->warpWindow = warpWindow;\n\t    }\n\t    dispPtr->warpMainwin = mainWin;\n\t    dispPtr->warpX = event.general.xmotion.x;\n\t    dispPtr->warpY = event.general.xmotion.y;\n\n\t    /*\n\t     * Warping with respect to a window will be done when Tk_handleEvent\n\t     * below will run the event handlers and in particular TkPointerEvent.\n\t     * This allows to make grabs and warping work together robustly, that\n\t     * is without depending on a precise sequence of events.\n\t     * Warping with respect to the whole screen (i.e. dispPtr->warpWindow\n\t     * is NULL) is run directly here.\n\t     */\n\n\t    if (!dispPtr->warpWindow) {\n\t\tTkpWarpPointer(dispPtr);\n\t\tXForceScreenSaver(dispPtr->display, ScreenSaverReset);\n\t    }\n\t}\n\n\t/*\n\t * Now we have constructed the event, inject it into the event handling\n\t * code.\n\t */\n\n\tif (synch) {\n\t    Tk_HandleEvent(&event.general);\n\t} else {\n\t    Tk_QueueWindowEvent(&event.general, pos);\n\t}\n    }\n\n    Tcl_ResetResult(interp);\n    return TCL_OK;\n}\n/*\n *---------------------------------------------------------------------------\n *\n * NameToWindow --\n *\n *\tHelper function for lookup of a window given its path name. Our\n *\tversion is able to handle window id's.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic bool\nNameToWindow(\n    Tcl_Interp *interp,\t\t/* Interp for error return and name lookup. */\n    Tk_Window mainWin,\t\t/* Main window of application. */\n    Tcl_Obj *objPtr,\t\t/* Contains name or id string of window. */\n    Tk_Window *tkwinPtr)\t/* Filled with token for window. */\n{\n    const char *name;\n    Tk_Window tkwin;\n\n    assert(mainWin);\n    assert(objPtr);\n    assert(tkwinPtr);\n\n    name = Tcl_GetString(objPtr);\n\n    if (name[0] == '.') {\n\tif (!(tkwin = Tk_NameToWindow(interp, name, mainWin))) {\n\t    return false;\n\t}\n    } else {\n\tWindow id;\n\n\ttkwin = NULL;\n\n\t/*\n\t * Check for the winPtr being valid, even if it looks okay to\n\t * TkpScanWindowId. [Bug #411307]\n\t */\n\n\tif (TkpScanWindowId(NULL, name, &id) == TCL_OK) {\n\t    tkwin = Tk_IdToWindow(Tk_Display(mainWin), id);\n\t}\n\n\tif (!tkwin) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad window name/identifier \\\"%s\\\"\", name));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"WINDOW_ID\", name, (char *)NULL);\n\t    return false;\n\t}\n    }\n\n    assert(tkwin);\n    *tkwinPtr = tkwin;\n    return true;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkDoWarpWrtWin --\n *\n *\tPerform warping of mouse pointer with respect to a window.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMouse pointer moves to a new location.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkDoWarpWrtWin(\n    TkDisplay *dispPtr)\n{\n    assert(dispPtr);\n\n    /*\n     * A NULL warpWindow means warping with respect to the whole screen.\n     * We want to warp here only if we're warping with respect to a window.\n     */\n\n    if (dispPtr->warpWindow) {\n\n\t/*\n\t * Warping with respect to a window can only be done if the window is\n\t * mapped. This was checked in HandleEvent. The window needs to be\n\t * still mapped at the time the present code is executed. Also\n\t * one needs to guard against window destruction in the meantime,\n\t * which could have happened as a side effect of an event handler.\n\t */\n\n\tif (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None) {\n\t    TkpWarpPointer(dispPtr);\n\t    XForceScreenSaver(dispPtr->display, ScreenSaverReset);\n\t}\n\tTcl_Release(dispPtr->warpWindow);\n\tdispPtr->warpWindow = NULL;\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * GetVirtualEventUid --\n *\n *\tDetermine if the given string is in the proper format for a virtual\n *\tevent.\n *\n * Results:\n *\tThe return value is NULL if the virtual event string was not in the\n *\tproper format. In this case, an error message will be left in the\n *\tinterp's result. Otherwise the return value is a Tk_Uid that\n *\trepresents the virtual event.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic Tk_Uid\nGetVirtualEventUid(\n    Tcl_Interp *interp,\n    char *virtString)\n{\n    Tk_Uid uid;\n    size_t length;\n\n    assert(virtString);\n\n    length = strlen(virtString);\n\n    if (length < 5\n\t    || virtString[0] != '<'\n\t    || virtString[1] != '<'\n\t    || virtString[length - 2] != '>'\n\t    || virtString[length - 1] != '>') {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"virtual event \\\"%s\\\" is badly formed\", virtString));\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"VIRTUAL\", \"MALFORMED\", (char *)NULL);\n\treturn NULL;\n    }\n    virtString[length - 2] = '\\0';\n    uid = Tk_GetUid(virtString + 2);\n    virtString[length - 2] = '>';\n\n    return uid;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindSequence --\n *\n *\tFind the entry in the pattern table that corresponds to a particular\n *\tpattern string, and return a pointer to that entry.\n *\n * Results:\n *\tThe return value is normally a pointer to the PatSeq in patternTable\n *\tthat corresponds to eventString. If an error was found while parsing\n *\teventString, or if \"create\" is 0 and no pattern sequence previously\n *\texisted, then NULL is returned and the interp's result contains a\n *\tmessage describing the problem. If no pattern sequence previously\n *\texisted for eventString, then a new one is created with a NULL command\n *\tfield. In a successful return, *maskPtr is filled in with a mask of\n *\tthe event types on which the pattern sequence depends.\n *\n * Side effects:\n *\tA new pattern sequence may be allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic PatSeq *\nFindSequence(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    LookupTables *lookupTables,\t/* Tables used for lookup. */\n    void *object,\t\t/* For binding table, token for object with which binding is\n\t\t\t\t * associated. For virtual event table, NULL. */\n    const char *eventString,\t/* String description of pattern to match on. See user\n\t\t\t\t * documentation for details. */\n    int create,\t\t\t/* 0 means don't create the entry if it doesn't already exist.\n\t\t\t\t * 1 means create. */\n    int allowVirtual,\t\t/* 0 means that virtual events are not allowed in the sequence.\n\t\t\t\t * 1 otherwise. */\n    unsigned *maskPtr)\t\t/* *maskPtr is filled in with the event types on which this\n\t\t\t\t * pattern sequence depends. */\n{\n    unsigned patsBufSize = 1;\n    unsigned numPats;\n    unsigned totalCount = 0;\n    int virtualFound = 0;\n    const char *p = eventString;\n    TkPattern *patPtr;\n    PatSeq *psPtr;\n    Tcl_HashEntry *hPtr;\n    int isNew;\n    unsigned count;\n    unsigned maxCount = 0;\n    unsigned eventMask = 0;\n    unsigned modMask = 0;\n    PatternTableKey key;\n\n    assert(lookupTables);\n    assert(eventString);\n\n    psPtr = (PatSeq *)Tcl_Alloc(PATSEQ_MEMSIZE(patsBufSize));\n\n    /*\n     *------------------------------------------------------------------\n     * Step 1: parse the pattern string to produce an array of Patterns.\n     *------------------------------------------------------------------\n     */\n\n    for (patPtr = psPtr->pats, numPats = 0; *(p = SkipSpaces(p)); ++patPtr, ++numPats) {\n\tif (numPats >= patsBufSize) {\n\t    unsigned pos = patPtr - psPtr->pats;\n\t    patsBufSize += patsBufSize;\n\t    psPtr = (PatSeq *)Tcl_Realloc(psPtr, PATSEQ_MEMSIZE(patsBufSize));\n\t    patPtr = psPtr->pats + pos;\n\t}\n\n\tif ((count = ParseEventDescription(interp, &p, patPtr, &eventMask)) == 0) {\n\t    /* error encountered */\n\t    Tcl_Free(psPtr);\n\t    return NULL;\n\t}\n\n\tif (eventMask & VirtualEventMask) {\n\t    if (!allowVirtual) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"virtual event not allowed in definition of another virtual event\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"VIRTUAL\", \"INNER\", (char *)NULL);\n\t\tTcl_Free(psPtr);\n\t\treturn NULL;\n\t    }\n\t    virtualFound = 1;\n\t}\n\n\tif (count > 1u) {\n\t    maxCount = Max(count, maxCount);\n\t}\n\n\ttotalCount += count;\n\tmodMask |= patPtr->modMask;\n    }\n\n    /*\n     *------------------------------------------------------------------\n     * Step 2: find the sequence in the binding table if it exists, and\n     * add a new sequence to the table if it doesn't.\n     *------------------------------------------------------------------\n     */\n\n    if (numPats == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"no events specified in binding\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"NO_EVENTS\", (char *)NULL);\n\tTcl_Free(psPtr);\n\treturn NULL;\n    }\n    if (numPats > 1u && virtualFound) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"virtual events may not be composed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", \"VIRTUAL\", \"COMPOSITION\", (char *)NULL);\n\tTcl_Free(psPtr);\n\treturn NULL;\n    }\n    if (patsBufSize > numPats) {\n\tpsPtr = (PatSeq *)Tcl_Realloc(psPtr, PATSEQ_MEMSIZE(numPats));\n    }\n\n    patPtr = psPtr->pats;\n    psPtr->object = (Tcl_Obj *)object;\n    SetupPatternKey(&key, psPtr);\n    hPtr = Tcl_CreateHashEntry(&lookupTables->patternTable, (char *) &key, &isNew);\n    if (!isNew) {\n\tunsigned sequenceSize = numPats*sizeof(TkPattern);\n\tPatSeq *psPtr2;\n\n\tfor (psPtr2 = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {\n\t    assert(TEST_PSENTRY(psPtr2));\n\t    if (numPats == psPtr2->numPats && memcmp(patPtr, psPtr2->pats, sequenceSize) == 0) {\n\t\tTcl_Free(psPtr);\n\t\tif (maskPtr) {\n\t\t    *maskPtr = eventMask;\n\t\t}\n\t\treturn psPtr2;\n\t    }\n\t}\n    }\n    if (!create) {\n\tif (isNew) {\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n\n\t/*\n\t * No binding exists for the sequence, so return an empty error. This\n\t * is a special error that the caller will check for in order to\n\t * silently ignore this case. This is a hack that maintains backward\n\t * compatibility for Tk_GetBinding but the various \"bind\" commands\n\t * silently ignore missing bindings.\n\t */\n\n\tTcl_Free(psPtr);\n\treturn NULL;\n    }\n\n    DEBUG(countSeqItems += 1;)\n\n    psPtr->numPats = numPats;\n    psPtr->count = totalCount;\n    psPtr->number = lookupTables->number++;\n    psPtr->added = 0;\n    psPtr->modMaskUsed = (modMask != 0);\n    psPtr->script = NULL;\n    psPtr->nextSeqPtr = (PatSeq *)Tcl_GetHashValue(hPtr);\n    psPtr->hPtr = hPtr;\n    psPtr->ptr.nextObj = NULL;\n    assert(psPtr->ptr.owners == NULL);\n    DEBUG(psPtr->owned = 0;)\n    Tcl_SetHashValue(hPtr, psPtr);\n\n    if (maskPtr) {\n\t*maskPtr = eventMask;\n    }\n    return psPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ParseEventDescription --\n *\n *\tFill Pattern buffer with information about event from event string.\n *\n * Results:\n *\tLeaves error message in interp and returns 0 if there was an error due\n *\tto a badly formed event string. Returns 1 if proper event was\n *\tspecified, 2 if Double modifier was used in event string, or 3 if\n *\tTriple was used.\n *\n * Side effects:\n *\tOn exit, eventStringPtr points to rest of event string (after the\n *\tclosing '>', so that this function can be called repeatedly to parse\n *\tall the events in the entire sequence.\n *\n *---------------------------------------------------------------------------\n */\n\n/* helper function */\nstatic unsigned\nFinalizeParseEventDescription(\n    Tcl_Interp *interp,\n    TkPattern *patPtr,\n    unsigned count,\n    Tcl_Obj* errorObj,\n    const char* errCode)\n{\n    assert(patPtr);\n    assert(!errorObj == (count > 0));\n\n    if (errorObj) {\n\tTcl_SetObjResult(interp, errorObj);\n\tTcl_SetErrorCode(interp, \"TK\", \"EVENT\", errCode, (char *)NULL);\n    }\n    patPtr->count = count;\n    return count;\n}\n\nstatic unsigned\nParseEventDescription(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    const char **eventStringPtr,/* On input, holds a pointer to start of event string. On exit,\n\t\t\t\t * gets pointer to rest of string after parsed event. */\n    TkPattern *patPtr,\t\t/* Filled with the pattern parsed from the event string. */\n    unsigned *eventMaskPtr)\t/* Filled with event mask of matched event. */\n{\n    const char *p;\n    unsigned eventMask = 0;\n    unsigned count = 1;\n\n    assert(eventStringPtr);\n    assert(patPtr);\n    assert(eventMaskPtr);\n\n    p = *eventStringPtr;\n    memset(patPtr, 0, sizeof(TkPattern)); /* Otherwise memcmp doesn't work. */\n\n    /*\n     * Handle simple ASCII characters.\n     */\n\n    if (*p != '<') {\n\tchar string[2];\n\n\tpatPtr->eventType = KeyPress;\n\teventMask = KeyPressMask;\n\tstring[0] = *p;\n\tstring[1] = '\\0';\n\tpatPtr->info = TkStringToKeysym(string);\n\tif (patPtr->info == NoSymbol) {\n\t    if (!isprint(UCHAR(*p))) {\n\t\treturn FinalizeParseEventDescription(\n\t\t\tinterp,\n\t\t\tpatPtr, 0,\n\t\t\tTcl_ObjPrintf(\"bad ASCII character 0x%x\", UCHAR(*p)), \"BAD_CHAR\");\n\t    }\n\t    patPtr->info = *p;\n\t}\n\t++p;\n    } else {\n\t/*\n\t * A fancier event description. This can be either a virtual event or a physical event.\n\t *\n\t * A virtual event description consists of:\n\t *\n\t * 1. double open angle brackets.\n\t * 2. virtual event name.\n\t * 3. double close angle brackets.\n\t *\n\t * A physical event description consists of:\n\t *\n\t * 1. open angle bracket.\n\t * 2. any number of modifiers, each followed by spaces or dashes.\n\t * 3. an optional event name.\n\t * 4. an option button or keysym name. Either this or item 3 *must* be present; if both\n\t *    are present then they are separated by spaces or dashes.\n\t * 5. a close angle bracket.\n\t */\n\n\t++p;\n\tif (*p == '<') {\n\t    /*\n\t     * This is a virtual event: soak up all the characters up to the next '>'.\n\t     */\n\n\t    const char *field = p + 1;\n\t    char buf[256];\n\t    char* bufPtr = buf;\n\t    unsigned size;\n\n\t    p = strchr(field, '>');\n\t    if (p == field) {\n\t\treturn FinalizeParseEventDescription(\n\t\t\tinterp,\n\t\t\tpatPtr, 0,\n\t\t\tTcl_NewStringObj(\"virtual event \\\"<<>>\\\" is badly formed\", TCL_INDEX_NONE), \"MALFORMED\");\n\t    }\n\t    if (!p || p[1] != '>') {\n\t\treturn FinalizeParseEventDescription(\n\t\t\tinterp,\n\t\t\tpatPtr, 0,\n\t\t\tTcl_NewStringObj(\"missing \\\">\\\" in virtual binding\", TCL_INDEX_NONE), \"MALFORMED\");\n\t    }\n\n\t    size = p - field;\n\t    if (size >= sizeof(buf)) {\n\t\tbufPtr = (char *)Tcl_Alloc(size + 1);\n\t    }\n\t    strncpy(bufPtr, field, size);\n\t    bufPtr[size] = '\\0';\n\t    eventMask = VirtualEventMask;\n\t    patPtr->eventType = VirtualEvent;\n\t    patPtr->name = Tk_GetUid(bufPtr);\n\t    if (bufPtr != buf) {\n\t\tTcl_Free(bufPtr);\n\t    }\n\t    p += 2;\n\t} else {\n\t    unsigned eventFlags;\n\t    char field[512];\n\t    Tcl_HashEntry *hPtr;\n\n\t    while (1) {\n\t\tModInfo *modPtr;\n\n\t\tp = GetField(p, field, sizeof(field));\n\t\tif (*p == '>') {\n\t\t    /*\n\t\t     * This solves the problem of, e.g., <Control-M> being\n\t\t     * misinterpreted as Control + Meta + missing keysym instead of\n\t\t     * Control + KeyPress + M.\n\t\t     */\n\n\t\t     break;\n\t\t}\n\t\tif (!(hPtr = Tcl_FindHashEntry(&modTable, field))) {\n\t\t    break;\n\t\t}\n\t\tmodPtr = (ModInfo *)Tcl_GetHashValue(hPtr);\n\t\tpatPtr->modMask |= modPtr->mask;\n\t\tif (modPtr->flags & MULT_CLICKS) {\n\t\t    unsigned i = modPtr->flags & MULT_CLICKS;\n\n\t\t    count = 2;\n\t\t    while (i >>= 1) {\n\t\t\t++count;\n\t\t    }\n\t\t}\n\t\tp = SkipFieldDelims(p);\n\t    }\n\n\t    eventFlags = 0;\n\t    if ((hPtr = Tcl_FindHashEntry(&eventTable, field))) {\n\t\tconst EventInfo *eiPtr = (const EventInfo *)Tcl_GetHashValue(hPtr);\n\n\t\tpatPtr->eventType = eiPtr->type;\n\t\teventFlags = flagArray[eiPtr->type];\n\t\teventMask = eiPtr->eventMask;\n\t\tp = GetField(SkipFieldDelims(p), field, sizeof(field));\n\t    }\n\t    if (*field) {\n\t\tunsigned button = GetButtonNumber(field);\n\n\t\tif ((eventFlags & BUTTON)\n\t\t\t|| (button && eventFlags == 0)\n\t\t\t|| ((eventFlags & MOTION) && button == 0)) {\n\t\t    /* This must be a button (or bad motion) event. */\n\t\t    if (button == 0) {\n\t\t\treturn FinalizeParseEventDescription(\n\t\t\t\tinterp,\n\t\t\t\tpatPtr, 0,\n\t\t\t\tTcl_ObjPrintf(\"bad button number \\\"%s\\\"\", field), \"BUTTON\");\n\t\t    }\n\t\t    patPtr->info = button;\n\t\t    if (!(eventFlags & BUTTON)) {\n\t\t\tpatPtr->eventType = ButtonPress;\n\t\t\teventMask = ButtonPressMask;\n\t\t    }\n\t\t} else if ((eventFlags & KEY) || eventFlags == 0) {\n\t\t    /* This must be a key event */\n\t\t    patPtr->info = TkStringToKeysym(field);\n\t\t    if (patPtr->info == NoSymbol) {\n\t\t\treturn FinalizeParseEventDescription(\n\t\t\t\tinterp,\n\t\t\t\tpatPtr, 0,\n\t\t\t\tTcl_ObjPrintf(\"bad event type or keysym \\\"%s\\\"\", field), \"KEYSYM\");\n\t\t    }\n\t\t    if (!(eventFlags & KEY)) {\n\t\t\tpatPtr->eventType = KeyPress;\n\t\t\teventMask = KeyPressMask;\n\t\t    }\n\t\t} else if (button) {\n\t\t    if (patPtr->eventType != MotionNotify) {\n\t\t\treturn FinalizeParseEventDescription(\n\t\t\t\tinterp,\n\t\t\t\tpatPtr, 0,\n\t\t\t\tTcl_ObjPrintf(\"specified button \\\"%s\\\" for non-button event\", field),\n\t\t\t\t\"NON_BUTTON\");\n\t\t    }\n\t\t    patPtr->modMask |= Tk_GetButtonMask(button);\n\t\t    p = SkipFieldDelims(p);\n\t\t    while (*p && *p != '>') {\n\t\t\tp = SkipFieldDelims(GetField(p, field, sizeof(field)));\n\t\t\tif ((button = GetButtonNumber(field)) == 0) {\n\t\t\t    return FinalizeParseEventDescription(\n\t\t\t\t    interp,\n\t\t\t\t    patPtr, 0,\n\t\t\t\t    Tcl_ObjPrintf(\"bad button number \\\"%s\\\"\", field), \"BUTTON\");\n\t\t\t}\n\t\t\tpatPtr->modMask |= Tk_GetButtonMask(button);\n\t\t    }\n\t\t    patPtr->info = ButtonNumberFromState(patPtr->modMask);\n\t\t} else {\n\t\t    return FinalizeParseEventDescription(\n\t\t\t    interp,\n\t\t\t    patPtr, 0,\n\t\t\t    Tcl_ObjPrintf(\"specified keysym \\\"%s\\\" for non-key event\", field),\n\t\t\t    \"NON_KEY\");\n\t\t}\n\t    } else if (eventFlags == 0) {\n\t\treturn FinalizeParseEventDescription(\n\t\t\tinterp,\n\t\t\tpatPtr, 0,\n\t\t\tTcl_NewStringObj(\"no event type or button # or keysym\", TCL_INDEX_NONE), \"UNMODIFIABLE\");\n\t    } else if (patPtr->eventType == MotionNotify) {\n\t\tpatPtr->info = ButtonNumberFromState(patPtr->modMask);\n\t    }\n\t    p = SkipFieldDelims(p);\n\n\t    if (*p != '>') {\n\t\twhile (*p) {\n\t\t    ++p;\n\t\t    if (*p == '>') {\n\t\t\treturn FinalizeParseEventDescription(\n\t\t\t\tinterp,\n\t\t\t\tpatPtr, 0,\n\t\t\t\tTcl_NewStringObj(\"extra characters after detail in binding\", TCL_INDEX_NONE),\n\t\t\t\t\"PAST_DETAIL\");\n\t\t    }\n\t\t}\n\t\treturn FinalizeParseEventDescription(\n\t\t\tinterp,\n\t\t\tpatPtr, 0,\n\t\t\tTcl_NewStringObj(\"missing \\\">\\\" in binding\", TCL_INDEX_NONE), \"MALFORMED\");\n\t    }\n\t    ++p;\n\t}\n    }\n\n    *eventStringPtr = p;\n    *eventMaskPtr |= eventMask;\n    return FinalizeParseEventDescription(interp, patPtr, count, NULL, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetField --\n *\n *\tUsed to parse pattern descriptions. Copies up to size characters from\n *\tp to copy, stopping at end of string, space, \"-\", \">\", or whenever\n *\tsize is exceeded.\n *\n * Results:\n *\tThe return value is a pointer to the character just after the last one\n *\tcopied (usually \"-\" or space or \">\", but could be anything if size was\n *\texceeded). Also places NULL-terminated string (up to size character,\n *\tincluding NULL), at copy.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const char *\nGetField(\n    const char *p,\t/* Pointer to part of pattern. */\n    char *copy,\t\t/* Place to copy field. */\n    unsigned size)\t/* Maximum number of characters to copy. */\n{\n    assert(p);\n    assert(copy);\n\n    for ( ; *p && !isspace(UCHAR(*p)) && *p != '>' && *p != '-' && size > 1u; --size) {\n\t*copy++ = *p++;\n    }\n    *copy = '\\0';\n    return p;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetPatternObj --\n *\n *\tProduce a string version of the given event, for displaying to the\n *\tuser.\n *\n * Results:\n *\tThe string is returned as a Tcl_Obj.\n *\n * Side effects:\n *\tIt is the caller's responsibility to arrange for the object to be\n *\treleased; it starts with a refCount of zero.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetPatternObj(\n    const PatSeq *psPtr)\n{\n    Tcl_Obj *patternObj = Tcl_NewObj();\n    unsigned i;\n\n    assert(psPtr);\n\n    for (i = 0; i < psPtr->numPats; ++i) {\n\tconst TkPattern *patPtr = psPtr->pats + i;\n\n\t/*\n\t * Check for simple case of an ASCII character.\n\t */\n\tif (patPtr->eventType == KeyPress\n\t\t&& patPtr->count == 1\n\t\t&& patPtr->modMask == 0\n\t\t&& patPtr->info < 128\n\t\t&& isprint(UCHAR(patPtr->info))\n\t\t&& patPtr->info != '<'\n\t\t&& patPtr->info != ' ') {\n\t    char c = (char) patPtr->info;\n\t    Tcl_AppendToObj(patternObj, &c, 1);\n\t} else if (patPtr->eventType == VirtualEvent) {\n\t    assert(patPtr->name);\n\t    Tcl_AppendPrintfToObj(patternObj, \"<<%s>>\", patPtr->name);\n\t} else {\n\t    unsigned modMask;\n\t    const ModInfo *modPtr;\n\n\t    /*\n\t     * It's a more general event specification. First check for \"Double\",\n\t     * \"Triple\", \"Quadruple\", then modifiers, then event type, then keysym\n\t     * or button detail.\n\t     */\n\n\t    Tcl_AppendToObj(patternObj, \"<\", 1);\n\n\t    switch (patPtr->count) {\n\t    case 2: Tcl_AppendToObj(patternObj, \"Double-\", 7); break;\n\t    case 3: Tcl_AppendToObj(patternObj, \"Triple-\", 7); break;\n\t    case 4: Tcl_AppendToObj(patternObj, \"Quadruple-\", 10); break;\n\t    }\n\n\t    modMask = patPtr->modMask;\n#if PRINT_SHORT_MOTION_SYNTAX\n\t    if (patPtr->eventType == MotionNotify) {\n\t\tmodMask &= ~(unsigned)ALL_BUTTONS;\n\t    }\n#endif\n\n\t    for (modPtr = modArray; modMask; ++modPtr) {\n\t\tif (modPtr->mask & modMask) {\n\t\t    modMask &= ~modPtr->mask;\n\t\t    Tcl_AppendPrintfToObj(patternObj, \"%s-\", modPtr->name);\n\t\t}\n\t    }\n\n\t    assert(patPtr->eventType < TK_LASTEVENT);\n\t    assert(((size_t) eventArrayIndex[patPtr->eventType]) < SIZE_OF_ARRAY(eventArray));\n\t    Tcl_AppendToObj(patternObj, eventArray[eventArrayIndex[patPtr->eventType]].name, TCL_INDEX_NONE);\n\n\t    if (patPtr->info) {\n\t\tswitch (patPtr->eventType) {\n\t\tcase KeyPress:\n\t\tcase KeyRelease: {\n\t\t    const char *string = TkKeysymToString(patPtr->info);\n\t\t    if (string) {\n\t\t\tTcl_AppendToObj(patternObj, \"-\", 1);\n\t\t\tTcl_AppendToObj(patternObj, string, TCL_INDEX_NONE);\n\t\t    }\n\t\t    break;\n\t\t}\n\t\tcase ButtonPress:\n\t\tcase ButtonRelease:\n\t\t    assert(patPtr->info <= 13);\n\t\t    Tcl_AppendPrintfToObj(patternObj, \"-%u\", (unsigned) ((patPtr->info > 7) ? (patPtr->info - 4) : patPtr->info));\n\t\t    break;\n#if PRINT_SHORT_MOTION_SYNTAX\n\t\tcase MotionNotify: {\n\t\t    unsigned mask = patPtr->modMask;\n\t\t    while (mask & ALL_BUTTONS) {\n\t\t\tunsigned button = ButtonNumberFromState(mask);\n\t\t\tTcl_AppendPrintfToObj(patternObj, \"-%u\", (button > 7) ? (button - 4) : button);\n\t\t\tmask &= ~Tk_GetButtonMask(button);\n\t\t    }\n\t\t    break;\n\t\t}\n#endif\n\t\t}\n\t    }\n\n\t    Tcl_AppendToObj(patternObj, \">\", 1);\n\t}\n    }\n\n    return patternObj;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkStringToKeysym --\n *\n *\tThis function finds the keysym associated with a given keysym name.\n *\n * Results:\n *\tThe return value is the keysym that corresponds to name, or NoSymbol\n *\tif there is no such keysym.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nTkStringToKeysym(\n    const char *name)\t\t/* Name of a keysym. */\n{\n#ifdef REDO_KEYSYM_LOOKUP\n    Tcl_HashEntry *hPtr;\n#endif /* REDO_KEYSYM_LOOKUP */\n    int keysym;\n\n    size_t len = Tcl_UtfToUniChar(name, &keysym);\n    if (name[len] == '\\0') {\n\tif (!Tcl_UniCharIsPrint(keysym)) {\n\t/* This form not supported */\n\t} else if ((unsigned)(keysym - 0x21) <= 0x5D) {\n\t\treturn (KeySym)keysym;\n\t    } else if ((unsigned)(keysym - 0xA1) <= 0x5E) {\n\t\treturn (KeySym)keysym;\n\t    } else if (keysym == 0x20AC) {\n\t\treturn 0x20AC;\n\t    } else {\n\t\treturn (KeySym)keysym + 0x1000000;\n\t    }\n    }\n#ifdef REDO_KEYSYM_LOOKUP\n    if ((name[0] == 'U') && ((unsigned)(name[1] - '0') <= 9)) {\n\tchar *p = (char *)name + 1;\n\tkeysym = strtol(p, &p, 16);\n\tif ((p >= name + 5) && (p <= name + 9) && !*p && (keysym >= 0x20)\n\t\t&& ((unsigned)(keysym - 0x7F) > 0x20)) {\n\t    if ((unsigned)(keysym - 0x21) <= 0x5D) {\n\t\treturn keysym;\n\t    } else if ((unsigned)(keysym - 0xA1) <= 0x5E) {\n\t\treturn keysym;\n\t    } else if (keysym == 0x20AC) {\n\t\treturn keysym;\n\t    }\n\t    return keysym + 0x1000000;\n\t}\n    }\n#endif\n#ifdef REDO_KEYSYM_LOOKUP\n    hPtr = Tcl_FindHashEntry(&keySymTable, name);\n    if (hPtr) {\n\treturn (KeySym) Tcl_GetHashValue(hPtr);\n    }\n    if (((unsigned)(name[0]-1) < 0x7F) && !name[1]) {\n\tkeysym = (unsigned char) name[0];\n\n\tif (TkKeysymToString(keysym)) {\n\t    return keysym;\n\t}\n    }\n#endif /* REDO_KEYSYM_LOOKUP */\n    assert(name);\n    return XStringToKeysym(name);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkKeysymToString --\n *\n *\tThis function finds the keysym name associated with a given keysym.\n *\n * Results:\n *\tThe return value is a pointer to a static string containing the name\n *\tof the given keysym, or NULL if there is no known name.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkKeysymToString(\n    KeySym keysym)\n{\n#ifdef REDO_KEYSYM_LOOKUP\n    Tcl_HashEntry *hPtr;\n#endif\n\n    if ((unsigned)(keysym - 0x21) <= 0x5D) {\n\tkeysym += 0x1000000;\n    } else if ((unsigned)(keysym - 0xA1) <= 0x5E) {\n\tkeysym += 0x1000000;\n    } else if (keysym == 0x20AC) {\n\tkeysym += 0x1000000;\n    }\n    if ((keysym >= 0x1000020) && (keysym <= 0x110FFFF)\n\t    && ((unsigned)(keysym - 0x100007F) > 0x20)) {\n\tchar buf[10];\n\tif (Tcl_UniCharIsPrint(keysym-0x1000000)) {\n\t    buf[Tcl_UniCharToUtf(keysym - 0x1000000, buf)] = '\\0';\n\t} else if (keysym >= 0x1010000) {\n\t    snprintf(buf, sizeof(buf), \"U%08X\", (int)(keysym - 0x1000000));\n\t} else {\n\t    snprintf(buf, sizeof(buf), \"U%04X\", (int)(keysym - 0x1000000));\n\t}\n\treturn Tk_GetUid(buf);\n    }\n\n#ifdef REDO_KEYSYM_LOOKUP\n    hPtr = Tcl_FindHashEntry(&nameTable, INT2PTR(keysym));\n\n    if (hPtr) {\n\treturn (const char *)Tcl_GetHashValue(hPtr);\n    }\n#endif /* REDO_KEYSYM_LOOKUP */\n\n    return XKeysymToString(keysym);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetBindingXEvent --\n *\n *\tThis function returns the XEvent associated with the currently\n *\texecuting binding. This function can only be invoked while a binding\n *\tis executing.\n *\n * Results:\n *\tReturns a pointer to the XEvent that caused the current binding code\n *\tto be run.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nXEvent *\nTkpGetBindingXEvent(\n    Tcl_Interp *interp)\t\t/* Interpreter. */\n{\n    TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);\n    BindingTable *bindPtr = winPtr->mainPtr->bindingTable;\n\n    return &bindPtr->curEvent->xev;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDumpPS --\n *\n *\tDump given pattern sequence to stdout.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n#if SUPPORT_DEBUGGING\nvoid\nTkpDumpPS(\n    const PatSeq *psPtr)\n{\n    if (!psPtr) {\n\tfprintf(stdout, \"<null>\\n\");\n    } else {\n\tTcl_Obj* result = GetPatternObj(psPtr);\n\tTcl_IncrRefCount(result);\n\tfprintf(stdout, \"%s\", Tcl_GetString(result));\n\tif (psPtr->object) {\n\t    fprintf(stdout, \" (%s)\", (char *) psPtr->object);\n\t}\n\tfprintf(stdout, \"\\n\");\n\tTcl_DecrRefCount(result);\n    }\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDumpPSList --\n *\n *\tDump given pattern sequence list to stdout.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n#if SUPPORT_DEBUGGING\nvoid\nTkpDumpPSList(\n    const PSList *psList)\n{\n    if (!psList) {\n\tfprintf(stdout, \"<null>\\n\");\n    } else {\n\tconst PSEntry *psEntry;\n\n\tfprintf(stdout, \"Dump PSList ========================================\\n\");\n\tTK_DLIST_FOREACH(psEntry, psList) {\n\t    TkpDumpPS(psEntry->psPtr);\n\t}\n\tfprintf(stdout, \"====================================================\\n\");\n    }\n}\n#endif\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 105\n * End:\n * vi:set ts=8 sw=4:\n */\n"
  },
  {
    "path": "generic/tkBitmap.c",
    "content": "/*\n * tkBitmap.c --\n *\n *\tThis file maintains a database of read-only bitmaps for the Tk\n *\ttoolkit. This allows bitmaps to be shared between widgets and also\n *\tavoids interactions with the X server.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The includes below are for pre-defined bitmaps.\n *\n * Platform-specific issue: Windows complains when the bitmaps are included,\n * because an array of characters is being initialized with integers as\n * elements. For lint purposes, the following pragmas temporarily turn off\n * that warning message.\n */\n\n#if defined(_MSC_VER)\n#pragma warning (disable : 4305)\n#endif\n\n#include \"error.xbm\"\n#include \"gray12.xbm\"\n#include \"gray25.xbm\"\n#include \"gray50.xbm\"\n#include \"gray75.xbm\"\n#include \"hourglass.xbm\"\n#include \"info.xbm\"\n#include \"questhead.xbm\"\n#include \"question.xbm\"\n#include \"warning.xbm\"\n\n#if defined(_MSC_VER)\n#pragma warning (default : 4305)\n#endif\n\n/*\n * One of the following data structures exists for each bitmap that is\n * currently in use. Each structure is indexed with both \"idTable\" and\n * \"nameTable\".\n */\n\ntypedef struct TkBitmap {\n    Pixmap bitmap;\t\t/* X identifier for bitmap. None means this\n\t\t\t\t * bitmap was created by Tk_DefineBitmap and\n\t\t\t\t * it isn't currently in use. */\n    int width, height;\t\t/* Dimensions of bitmap. */\n    Display *display;\t\t/* Display for which bitmap is valid. */\n    int screenNum;\t\t/* Screen on which bitmap is valid. */\n    int resourceRefCount;\t/* Number of active uses of this bitmap (each\n\t\t\t\t * active use corresponds to a call to\n\t\t\t\t * Tk_AllocBitmapFromObj or Tk_GetBitmap). If\n\t\t\t\t * this count is 0, then this TkBitmap\n\t\t\t\t * structure is no longer valid and it isn't\n\t\t\t\t * present in nameTable: it is being kept\n\t\t\t\t * around only because there are objects\n\t\t\t\t * referring to it. The structure is freed\n\t\t\t\t * when resourceRefCount and objRefCount are\n\t\t\t\t * both 0. */\n    int objRefCount;\t\t/* Number of Tcl_Obj's that reference this\n\t\t\t\t * structure. */\n    Tcl_HashEntry *nameHashPtr;\t/* Entry in nameTable for this structure\n\t\t\t\t * (needed when deleting). */\n    Tcl_HashEntry *idHashPtr;\t/* Entry in idTable for this structure (needed\n\t\t\t\t * when deleting). */\n    struct TkBitmap *nextPtr;\t/* Points to the next TkBitmap structure with\n\t\t\t\t * the same name. All bitmaps with the same\n\t\t\t\t * name (but different displays or screens)\n\t\t\t\t * are chained together off a single entry in\n\t\t\t\t * nameTable. */\n} TkBitmap;\n\n/*\n * Used in bitmapDataTable, stored in the TkDisplay structure, to map between\n * in-core data about a bitmap to its TkBitmap structure.\n */\n\ntypedef struct {\n    const char *source;\t\t/* Bitmap bits. */\n    int width, height;\t\t/* Dimensions of bitmap. */\n} DataKey;\n\ntypedef struct {\n    bool initialized;\t\t/* 0 means table below needs initializing. */\n    Tcl_HashTable predefBitmapTable;\n\t\t\t\t/* Hash table created by Tk_DefineBitmap to\n\t\t\t\t * map from a name to a collection of in-core\n\t\t\t\t * data about a bitmap. The table is indexed\n\t\t\t\t * by the address of the data for the bitmap,\n\t\t\t\t * and the entries contain pointers to\n\t\t\t\t * TkPredefBitmap structures. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tBitmapInit(TkDisplay *dispPtr);\nstatic void\t\tDupBitmapObjProc(Tcl_Obj *srcObjPtr,\n\t\t\t    Tcl_Obj *dupObjPtr);\nstatic void\t\tFreeBitmap(TkBitmap *bitmapPtr);\nstatic void\t\tFreeBitmapObj(Tcl_Obj *objPtr);\nstatic void\t\tFreeBitmapObjProc(Tcl_Obj *objPtr);\nstatic TkBitmap *\tGetBitmap(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *name);\nstatic TkBitmap *\tGetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\nstatic void\t\tInitBitmapObj(Tcl_Obj *objPtr);\n\n/*\n * The following structure defines the implementation of the \"bitmap\" Tcl\n * object, which maps a string bitmap name to a TkBitmap object. The ptr1\n * field of the Tcl_Obj points to a TkBitmap object.\n */\n\nconst Tcl_ObjType tkBitmapObjType = {\n    \"bitmap\",\t\t\t/* name */\n    FreeBitmapObjProc,\t\t/* freeIntRepProc */\n    DupBitmapObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_AllocBitmapFromObj --\n *\n *\tGiven a Tcl_Obj *, map the value to a corresponding Pixmap structure\n *\tbased on the tkwin given.\n *\n * Results:\n *\tThe return value is the X identifer for the desired bitmap (i.e. a\n *\tPixmap with a single plane), unless string couldn't be parsed\n *\tcorrectly. In this case, None is returned and an error message is left\n *\tin the interp's result. The caller should never modify the bitmap that\n *\tis returned, and should eventually call Tk_FreeBitmapFromObj when the\n *\tbitmap is no longer needed.\n *\n * Side effects:\n *\tThe bitmap is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeBitmapFromObj, so that the database can be cleaned up when\n *\tbitmaps aren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_AllocBitmapFromObj(\n    Tcl_Interp *interp,\t\t/* Interp for error results. This may be\n\t\t\t\t * NULL. */\n    Tk_Window tkwin,\t\t/* Need the screen the bitmap is used on.*/\n    Tcl_Obj *objPtr)\t\t/* Object describing bitmap; see manual entry\n\t\t\t\t * for legal syntax of string value. */\n{\n    TkBitmap *bitmapPtr;\n\n    if (objPtr->typePtr != &tkBitmapObjType) {\n\tInitBitmapObj(objPtr);\n    }\n    bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    /*\n     * If the object currently points to a TkBitmap, see if it's the one we\n     * want. If so, increment its reference count and return.\n     */\n\n    if (bitmapPtr != NULL) {\n\tif (bitmapPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a TkBitmap that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\n\t    FreeBitmapObj(objPtr);\n\t    bitmapPtr = NULL;\n\t} else if ((Tk_Display(tkwin) == bitmapPtr->display)\n\t\t&& (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {\n\t    bitmapPtr->resourceRefCount++;\n\t    return bitmapPtr->bitmap;\n\t}\n    }\n\n    /*\n     * The object didn't point to the TkBitmap that we wanted. Search the list\n     * of TkBitmaps with the same name to see if one of the others is the\n     * right one.\n     */\n\n    if (bitmapPtr != NULL) {\n\tTkBitmap *firstBitmapPtr = (TkBitmap *)Tcl_GetHashValue(bitmapPtr->nameHashPtr);\n\n\tFreeBitmapObj(objPtr);\n\tfor (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL;\n\t\tbitmapPtr = bitmapPtr->nextPtr) {\n\t    if ((Tk_Display(tkwin) == bitmapPtr->display) &&\n\t\t    (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {\n\t\tbitmapPtr->resourceRefCount++;\n\t\tbitmapPtr->objRefCount++;\n\t\tobjPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;\n\t\treturn bitmapPtr->bitmap;\n\t    }\n\t}\n    }\n\n    /*\n     * Still no luck. Call GetBitmap to allocate a new TkBitmap object.\n     */\n\n    bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr));\n    objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;\n    if (bitmapPtr == NULL) {\n\treturn None;\n    }\n    bitmapPtr->objRefCount++;\n    return bitmapPtr->bitmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetBitmap --\n *\n *\tGiven a string describing a bitmap, locate (or create if necessary) a\n *\tbitmap that fits the description.\n *\n * Results:\n *\tThe return value is the X identifer for the desired bitmap (i.e. a\n *\tPixmap with a single plane), unless string couldn't be parsed\n *\tcorrectly. In this case, None is returned and an error message is left\n *\tin the interp's result. The caller should never modify the bitmap that\n *\tis returned, and should eventually call Tk_FreeBitmap when the bitmap\n *\tis no longer needed.\n *\n * Side effects:\n *\tThe bitmap is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeBitmap, so that the database can be cleaned up when bitmaps\n *\taren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetBitmap(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting,\n\t\t\t\t * this may be NULL. */\n    Tk_Window tkwin,\t\t/* Window in which bitmap will be used. */\n    const char *string)\t\t/* Description of bitmap. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string);\n\n    if (bitmapPtr == NULL) {\n\treturn None;\n    }\n    return bitmapPtr->bitmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetBitmap --\n *\n *\tGiven a string describing a bitmap, locate (or create if necessary) a\n *\tbitmap that fits the description. This routine returns the internal\n *\tdata structure for the bitmap. This avoids extra hash table lookups in\n *\tTk_AllocBitmapFromObj.\n *\n * Results:\n *\tThe return value is the X identifer for the desired bitmap (i.e. a\n *\tPixmap with a single plane), unless string couldn't be parsed\n *\tcorrectly. In this case, None is returned and an error message is left\n *\tin the interp's result. The caller should never modify the bitmap that\n *\tis returned, and should eventually call Tk_FreeBitmap when the bitmap\n *\tis no longer needed.\n *\n * Side effects:\n *\tThe bitmap is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can be\n *\tcleaned up when bitmaps aren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkBitmap *\nGetBitmap(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting,\n\t\t\t\t * this may be NULL. */\n    Tk_Window tkwin,\t\t/* Window in which bitmap will be used. */\n    const char *string)\t\t/* Description of bitmap. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    Tcl_HashEntry *nameHashPtr, *predefHashPtr;\n    TkBitmap *bitmapPtr, *existingBitmapPtr;\n    TkPredefBitmap *predefPtr;\n    Pixmap bitmap;\n    int isNew, width = 0, height = 0, dummy2;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!dispPtr->bitmapInit) {\n\tBitmapInit(dispPtr);\n    }\n\n    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string,\n\t    &isNew);\n    if (!isNew) {\n\texistingBitmapPtr = (TkBitmap *)Tcl_GetHashValue(nameHashPtr);\n\tfor (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL;\n\t\tbitmapPtr = bitmapPtr->nextPtr) {\n\t    if ((Tk_Display(tkwin) == bitmapPtr->display) &&\n\t\t    (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {\n\t\tbitmapPtr->resourceRefCount++;\n\t\treturn bitmapPtr;\n\t    }\n\t}\n    } else {\n\texistingBitmapPtr = NULL;\n    }\n\n    /*\n     * No suitable bitmap exists. Create a new bitmap from the information\n     * contained in the string. If the string starts with \"@\" then the rest of\n     * the string is a file name containing the bitmap. Otherwise the string\n     * must refer to a bitmap defined by a call to Tk_DefineBitmap.\n     */\n\n    if (*string == '@') {\t/* INTL: ISO char */\n\tTcl_DString buffer;\n\tint result;\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't specify bitmap with '@' in a safe interpreter\",\n\t\t    TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"BITMAP_FILE\", (char *)NULL);\n\t    goto error;\n\t}\n\n\t/*\n\t * Note that we need to cast away the const from the string because\n\t * Tcl_TranslateFileName is non-const, even though it doesn't modify\n\t * the string.\n\t */\n\n\tstring = Tcl_TranslateFileName(interp, (char *) string + 1, &buffer);\n\tif (string == NULL) {\n\t    goto error;\n\t}\n\tresult = TkReadBitmapFile(Tk_Display(tkwin),\n\t\tRootWindowOfScreen(Tk_Screen(tkwin)), string,\n\t\t(unsigned int *) &width, (unsigned int *) &height,\n\t\t&bitmap, &dummy2, &dummy2);\n\tif (result != BitmapSuccess) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"error reading bitmap file \\\"%s\\\"\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"BITMAP\", \"FILE_ERROR\", (char *)NULL);\n\t    }\n\t    Tcl_DStringFree(&buffer);\n\t    goto error;\n\t}\n\tTcl_DStringFree(&buffer);\n    } else {\n\tpredefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, string);\n\tif (predefHashPtr == NULL) {\n\t    /*\n\t     * The following platform specific call allows the user to define\n\t     * bitmaps that may only exist during run time. If it returns None\n\t     * nothing was found and we return the error.\n\t     */\n\n\t    bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string,\n\t\t    &width, &height);\n\n\t    if (bitmap == None) {\n\t\tif (interp != NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bitmap \\\"%s\\\" not defined\", string));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"BITMAP\", string,\n\t\t\t    (char *)NULL);\n\t\t}\n\t\tgoto error;\n\t    }\n\t} else {\n\t    predefPtr = (TkPredefBitmap *)Tcl_GetHashValue(predefHashPtr);\n\t    width = predefPtr->width;\n\t    height = predefPtr->height;\n\t    if (predefPtr->native) {\n\t\tbitmap = TkpCreateNativeBitmap(Tk_Display(tkwin),\n\t\t    predefPtr->source);\n\t\tif (bitmap == None) {\n\t\t    Tcl_Panic(\"native bitmap creation failed\");\n\t\t}\n\t    } else {\n\t\tbitmap = XCreateBitmapFromData(Tk_Display(tkwin),\n\t\t\tRootWindowOfScreen(Tk_Screen(tkwin)),\n\t\t\t(const char *)predefPtr->source, (unsigned)width, (unsigned)height);\n\t    }\n\t}\n    }\n\n    /*\n     * Add information about this bitmap to our database.\n     */\n\n    bitmapPtr = (TkBitmap *)Tcl_Alloc(sizeof(TkBitmap));\n    bitmapPtr->bitmap = bitmap;\n    bitmapPtr->width = width;\n    bitmapPtr->height = height;\n    bitmapPtr->display = Tk_Display(tkwin);\n    bitmapPtr->screenNum = Tk_ScreenNumber(tkwin);\n    bitmapPtr->resourceRefCount = 1;\n    bitmapPtr->objRefCount = 0;\n    bitmapPtr->nameHashPtr = nameHashPtr;\n    bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable,\n\t    (char *) bitmap, &isNew);\n    if (!isNew) {\n\tTcl_Panic(\"bitmap already registered in Tk_GetBitmap\");\n    }\n    bitmapPtr->nextPtr = existingBitmapPtr;\n    Tcl_SetHashValue(nameHashPtr, bitmapPtr);\n    Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr);\n    return bitmapPtr;\n\n  error:\n    if (isNew) {\n\tTcl_DeleteHashEntry(nameHashPtr);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DefineBitmap --\n *\n *\tThis function associates a textual name with a binary bitmap\n *\tdescription, so that the name may be used to refer to the bitmap in\n *\tfuture calls to Tk_GetBitmap.\n *\n * Results:\n *\tA standard Tcl result. If an error occurs then TCL_ERROR is returned\n *\tand a message is left in the interp's result.\n *\n * Side effects:\n *\t\"Name\" is entered into the bitmap table and may be used from here on\n *\tto refer to the given bitmap.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_DefineBitmap(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    const char *name,\t\t/* Name to use for bitmap. Must not already be\n\t\t\t\t * defined as a bitmap. */\n    const void *source,\t\t/* Address of bits for bitmap. */\n    int width,\t\t\t/* Width of bitmap. */\n    int height)\t\t\t/* Height of bitmap. */\n{\n    int isNew;\n    Tcl_HashEntry *predefHashPtr;\n    TkPredefBitmap *predefPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Initialize the Bitmap module if not initialized already for this\n     * thread. Since the current TkDisplay structure cannot be introspected\n     * from here, pass a NULL pointer to BitmapInit, which will know to\n     * initialize only the data in the ThreadSpecificData structure for the\n     * current thread.\n     */\n\n    if (!tsdPtr->initialized) {\n\tBitmapInit(NULL);\n    }\n\n    predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable,\n\t    name, &isNew);\n    if (!isNew) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bitmap \\\"%s\\\" is already defined\", name));\n\tTcl_SetErrorCode(interp, \"TK\", \"BITMAP\", \"EXISTS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    predefPtr = (TkPredefBitmap *)Tcl_Alloc(sizeof(TkPredefBitmap));\n    predefPtr->source = source;\n    predefPtr->width = width;\n    predefPtr->height = height;\n    predefPtr->native = 0;\n    Tcl_SetHashValue(predefHashPtr, predefPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfBitmap --\n *\n *\tGiven a bitmap, return a textual string identifying the bitmap.\n *\n * Results:\n *\tThe return value is the string name associated with bitmap.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfBitmap(\n    Display *display,\t\t/* Display for which bitmap was allocated. */\n    Pixmap bitmap)\t\t/* Bitmap whose name is wanted. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkBitmap *bitmapPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (dispPtr == NULL || !dispPtr->bitmapInit) {\n    unknown:\n\tTcl_Panic(\"Tk_NameOfBitmap received unknown bitmap argument\");\n    }\n\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);\n    if (idHashPtr == NULL) {\n\tgoto unknown;\n    }\n    bitmapPtr = (TkBitmap *)Tcl_GetHashValue(idHashPtr);\n    return bitmapPtr->nameHashPtr->key.string;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SizeOfBitmap --\n *\n *\tGiven a bitmap managed by this module, returns the width and height of\n *\tthe bitmap.\n *\n * Results:\n *\tThe words at *widthPtr and *heightPtr are filled in with the\n *\tdimenstions of bitmap.\n *\n * Side effects:\n *\tIf bitmap isn't managed by this module then the function panics..\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_SizeOfBitmap(\n    Display *display,\t\t/* Display for which bitmap was allocated. */\n    Pixmap bitmap,\t\t/* Bitmap whose size is wanted. */\n    int *widthPtr,\t\t/* Store bitmap width here. */\n    int *heightPtr)\t\t/* Store bitmap height here. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkBitmap *bitmapPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->bitmapInit) {\n    unknownBitmap:\n\tTcl_Panic(\"Tk_SizeOfBitmap received unknown bitmap argument\");\n    }\n\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);\n    if (idHashPtr == NULL) {\n\tgoto unknownBitmap;\n    }\n    bitmapPtr = (TkBitmap *)Tcl_GetHashValue(idHashPtr);\n    *widthPtr = bitmapPtr->width;\n    *heightPtr = bitmapPtr->height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeBitmap --\n *\n *\tThis function does all the work of releasing a bitmap allocated by\n *\tTk_GetBitmap or TkGetBitmapFromData. It is invoked by both\n *\tTk_FreeBitmap and Tk_FreeBitmapFromObj\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with bitmap is decremented, and it is\n *\tofficially deallocated if no-one is using it anymore.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeBitmap(\n    TkBitmap *bitmapPtr)\t/* Bitmap to be released. */\n{\n    TkBitmap *prevPtr;\n\n    if (bitmapPtr->resourceRefCount-- > 1) {\n\treturn;\n    }\n\n    Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);\n    Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);\n    prevPtr = (TkBitmap *)Tcl_GetHashValue(bitmapPtr->nameHashPtr);\n    if (prevPtr == bitmapPtr) {\n\tif (bitmapPtr->nextPtr == NULL) {\n\t    Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);\n\t} else {\n\t    Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != bitmapPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t}\n\tprevPtr->nextPtr = bitmapPtr->nextPtr;\n    }\n    if (bitmapPtr->objRefCount == 0) {\n\tTcl_Free(bitmapPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeBitmap --\n *\n *\tThis function is called to release a bitmap allocated by Tk_GetBitmap\n *\tor TkGetBitmapFromData.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with bitmap is decremented, and it is\n *\tofficially deallocated if no-one is using it anymore.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeBitmap(\n    Display *display,\t\t/* Display for which bitmap was allocated. */\n    Pixmap bitmap)\t\t/* Bitmap to be released. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->bitmapInit) {\n\tTcl_Panic(\"Tk_FreeBitmap called before Tk_GetBitmap\");\n    }\n\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);\n    if (idHashPtr == NULL) {\n\tTcl_Panic(\"Tk_FreeBitmap received unknown bitmap argument\");\n    }\n    FreeBitmap((TkBitmap *)Tcl_GetHashValue(idHashPtr));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeBitmapFromObj --\n *\n *\tThis function is called to release a bitmap allocated by\n *\tTk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *; it only\n *\tgets rid of the hash table entry for this bitmap and clears the cached\n *\tvalue that is normally stored in the object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with the bitmap represented by objPtr\n *\tis decremented, and the bitmap is released to X if there are no\n *\tremaining uses for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeBitmapFromObj(\n    Tk_Window tkwin,\t\t/* The window this bitmap lives in. Needed for\n\t\t\t\t * the display value. */\n    Tcl_Obj *objPtr)\t\t/* The Tcl_Obj * to be freed. */\n{\n    FreeBitmap(GetBitmapFromObj(tkwin, objPtr));\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeBitmapObjProc, FreeBitmapObj --\n *\n *\tThis proc is called to release an object reference to a bitmap.\n *\tCalled when the object's internal rep is released or when the cached\n *\tbitmapPtr needs to be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object reference count is decremented. When both it and the hash\n *\tref count go to zero, the color's resources are released.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeBitmapObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    FreeBitmapObj(objPtr);\n    objPtr->typePtr = NULL;\n}\n\nstatic void\nFreeBitmapObj(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    TkBitmap *bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    if (bitmapPtr != NULL) {\n\tbitmapPtr->objRefCount--;\n\tif ((bitmapPtr->objRefCount == 0)\n\t\t&& (bitmapPtr->resourceRefCount == 0)) {\n\t    Tcl_Free(bitmapPtr);\n\t}\n\tobjPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupBitmapObjProc --\n *\n *\tWhen a cached bitmap object is duplicated, this is called to update\n *\tthe internal reps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe color's objRefCount is incremented and the internal rep of the\n *\tcopy is set to point to it.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupBitmapObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    TkBitmap *bitmapPtr = (TkBitmap *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;\n\n    if (bitmapPtr != NULL) {\n\tbitmapPtr->objRefCount++;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetBitmapFromData --\n *\n *\tGiven a description of the bits for a bitmap, make a bitmap that has\n *\tthe given properties. *** NOTE: this function is obsolete and really\n *\tshouldn't be used anymore. ***\n *\n * Results:\n *\tThe return value is the X identifer for the desired bitmap (a\n *\tone-plane Pixmap), unless it couldn't be created properly. In this\n *\tcase, None is returned and an error message is left in the interp's\n *\tresult. The caller should never modify the bitmap that is returned,\n *\tand should eventually call Tk_FreeBitmap when the bitmap is no longer\n *\tneeded.\n *\n * Side effects:\n *\tThe bitmap is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeBitmap, so that the database can be cleaned up when bitmaps\n *\taren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetBitmapFromData(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which bitmap will be used. */\n    const void *source,\t\t/* Bitmap data for bitmap shape. */\n    int width, int height)\t/* Dimensions of bitmap. */\n{\n    DataKey nameKey;\n    Tcl_HashEntry *dataHashPtr;\n    int isNew;\n    char string[16 + TCL_INTEGER_SPACE];\n    char *name;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\tBitmapInit(dispPtr);\n    }\n\n    nameKey.source = (const char *)source;\n    nameKey.width = width;\n    nameKey.height = height;\n    dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable,\n\t    (char *) &nameKey, &isNew);\n    if (!isNew) {\n\tname = (char *)Tcl_GetHashValue(dataHashPtr);\n    } else {\n\tdispPtr->bitmapAutoNumber++;\n\tsnprintf(string, sizeof(string), \"_tk%d\", dispPtr->bitmapAutoNumber);\n\tname = string;\n\tTcl_SetHashValue(dataHashPtr, name);\n\tif (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {\n\t    Tcl_DeleteHashEntry(dataHashPtr);\n\t    return TCL_ERROR;\n\t}\n    }\n    return Tk_GetBitmap(interp, tkwin, name);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetBitmapFromObj --\n *\n *\tReturns the bitmap referred to by a Tcl object. The bitmap must\n *\talready have been allocated via a call to Tk_AllocBitmapFromObj or\n *\tTk_GetBitmap.\n *\n * Results:\n *\tReturns the Pixmap that matches the tkwin and the string rep of\n *\tobjPtr.\n *\n * Side effects:\n *\tIf the object is not already a bitmap, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetBitmapFromObj(\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr)\t\t/* The object from which to get pixels. */\n{\n    TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr);\n\n    return bitmapPtr->bitmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetBitmapFromObj --\n *\n *\tReturns the bitmap referred to by a Tcl object. The bitmap must\n *\talready have been allocated via a call to Tk_AllocBitmapFromObj or\n *\tTk_GetBitmap.\n *\n * Results:\n *\tReturns the TkBitmap * that matches the tkwin and the string rep of\n *\tobjPtr.\n *\n * Side effects:\n *\tIf the object is not already a bitmap, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkBitmap *\nGetBitmapFromObj(\n    Tk_Window tkwin,\t\t/* Window in which the bitmap will be used. */\n    Tcl_Obj *objPtr)\t\t/* The object that describes the desired\n\t\t\t\t * bitmap. */\n{\n    TkBitmap *bitmapPtr;\n    Tcl_HashEntry *hashPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objPtr->typePtr != &tkBitmapObjType) {\n\tInitBitmapObj(objPtr);\n    }\n\n    bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;\n    if (bitmapPtr != NULL) {\n\tif ((bitmapPtr->resourceRefCount > 0)\n\t\t&& (Tk_Display(tkwin) == bitmapPtr->display)) {\n\t    return bitmapPtr;\n\t}\n\thashPtr = bitmapPtr->nameHashPtr;\n\tFreeBitmapObj(objPtr);\n    } else {\n\thashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable,\n\t\tTcl_GetString(objPtr));\n\tif (hashPtr == NULL) {\n\t    goto error;\n\t}\n    }\n\n    /*\n     * At this point we've got a hash table entry, off of which hang one or\n     * more TkBitmap structures. See if any of them will work.\n     */\n\n    for (bitmapPtr = (TkBitmap *)Tcl_GetHashValue(hashPtr); bitmapPtr != NULL;\n\t    bitmapPtr = bitmapPtr->nextPtr) {\n\tif (Tk_Display(tkwin) == bitmapPtr->display) {\n\t    objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;\n\t    bitmapPtr->objRefCount++;\n\t    return bitmapPtr;\n\t}\n    }\n\n  error:\n    Tcl_Panic(\"GetBitmapFromObj called with non-existent bitmap!\");\n    /*\n     * The following code isn't reached; it's just there to please compilers.\n     */\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitBitmapObj --\n *\n *\tBookeeping function to change an objPtr to a bitmap type.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe old internal rep of the object is freed. The internal rep is\n *\tcleared. The final form of the object is set by either\n *\tTk_AllocBitmapFromObj or GetBitmapFromObj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitBitmapObj(\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->typePtr = &tkBitmapObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BitmapInit --\n *\n *\tInitializes hash tables used by this module. Initializes tables stored\n *\tin TkDisplay structure if a TkDisplay pointer is passed in. Also\n *\tinitializes the thread-local data in the current thread's\n *\tThreadSpecificData structure.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRead the code.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nBitmapInit(\n    TkDisplay *dispPtr)\t\t/* TkDisplay structure encapsulating\n\t\t\t\t * thread-specific data used by this module,\n\t\t\t\t * or NULL if unavailable. */\n{\n    Tcl_Interp *dummy;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * First initialize the data in the ThreadSpecificData structure, if\n     * needed.\n     */\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\tdummy = Tcl_CreateInterp();\n\tTcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS);\n\n\tTk_DefineBitmap(dummy, \"error\", error_bits,\n\t\terror_width, error_height);\n\tTk_DefineBitmap(dummy, \"gray75\", gray75_bits,\n\t\tgray75_width, gray75_height);\n\tTk_DefineBitmap(dummy, \"gray50\", gray50_bits,\n\t\tgray50_width, gray50_height);\n\tTk_DefineBitmap(dummy, \"gray25\", gray25_bits,\n\t\tgray25_width, gray25_height);\n\tTk_DefineBitmap(dummy, \"gray12\", gray12_bits,\n\t\tgray12_width, gray12_height);\n\tTk_DefineBitmap(dummy, \"hourglass\", hourglass_bits,\n\t\thourglass_width, hourglass_height);\n\tTk_DefineBitmap(dummy, \"info\", info_bits,\n\t\tinfo_width, info_height);\n\tTk_DefineBitmap(dummy, \"questhead\", questhead_bits,\n\t\tquesthead_width, questhead_height);\n\tTk_DefineBitmap(dummy, \"question\", question_bits,\n\t\tquestion_width, question_height);\n\tTk_DefineBitmap(dummy, \"warning\", warning_bits,\n\t\twarning_width, warning_height);\n\n\tTkpDefineNativeBitmaps();\n\tTcl_DeleteInterp(dummy);\n    }\n\n    /*\n     * Was a valid TkDisplay pointer passed? If so, initialize the Bitmap\n     * module tables in that structure.\n     */\n\n    if (dispPtr != NULL) {\n\tdispPtr->bitmapInit = 1;\n\tTcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS);\n\tTcl_InitHashTable(&dispPtr->bitmapDataTable,\n\t\tsizeof(DataKey) / sizeof(int));\n\n\t/*\n\t * The call below is tricky: can't use sizeof(IdKey) because it gets\n\t * padded with extra unpredictable bytes on some 64-bit machines.\n\t */\n\n\t/*\n\t * The comment above doesn't make sense...\n\t */\n\n\tTcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkReadBitmapFile --\n *\n *\tLoads a bitmap image in X bitmap format into the specified drawable.\n *\tThis is equivalent to the XReadBitmapFile in X.\n *\n * Results:\n *\tSets the size, hotspot, and bitmap on success.\n *\n * Side effects:\n *\tCreates a new bitmap from the file data.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkReadBitmapFile(\n    Display *display,\n    Drawable d,\n    const char *filename,\n    unsigned int *width_return,\n    unsigned int *height_return,\n    Pixmap *bitmap_return,\n    int *x_hot_return,\n    int *y_hot_return)\n{\n    char *data;\n\n    data = TkGetBitmapData(NULL, NULL, filename,\n\t    (int *) width_return, (int *) height_return, x_hot_return,\n\t    y_hot_return);\n    if (data == NULL) {\n\treturn BitmapFileInvalid;\n    }\n\n    *bitmap_return = XCreateBitmapFromData(display, d, data, *width_return,\n\t    *height_return);\n    Tcl_Free(data);\n    return BitmapSuccess;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugBitmap --\n *\n *\tThis function returns debugging information about a bitmap.\n *\n * Results:\n *\tThe return value is a list with one sublist for each TkBitmap\n *\tcorresponding to \"name\". Each sublist has two elements that contain\n *\tthe resourceRefCount and objRefCount fields from the TkBitmap\n *\tstructure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugBitmap(\n    Tk_Window tkwin,\t\t/* The window in which the bitmap will be used\n\t\t\t\t * (not currently used). */\n    const char *name)\t\t/* Name of the desired color. */\n{\n    TkBitmap *bitmapPtr;\n    Tcl_HashEntry *hashPtr;\n    Tcl_Obj *resultPtr, *objPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    resultPtr = Tcl_NewObj();\n    hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name);\n    if (hashPtr != NULL) {\n\tbitmapPtr = (TkBitmap *)Tcl_GetHashValue(hashPtr);\n\tif (bitmapPtr == NULL) {\n\t    Tcl_Panic(\"TkDebugBitmap found empty hash table entry\");\n\t}\n\tfor ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) {\n\t    objPtr = Tcl_NewObj();\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(bitmapPtr->resourceRefCount));\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(bitmapPtr->objRefCount));\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);\n\t}\n    }\n    return resultPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetBitmapPredefTable --\n *\n *\tThis function is used by tkMacOSXBitmap.c to access the thread-specific\n *\tpredefBitmap table that maps from the names of the predefined bitmaps\n *\tto data associated with those bitmaps. It is required because the\n *\ttable is allocated in thread-local storage and is not visible outside\n *\tthis file.\n\n * Results:\n *\tReturns a pointer to the predefined bitmap hash table for the current\n *\tthread.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_HashTable *\nTkGetBitmapPredefTable(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return &tsdPtr->predefBitmapTable;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkBusy.c",
    "content": "/*\n * tkBusy.c --\n *\n *\tThis file provides functions that implement busy for Tk.\n *\n * Copyright 1993-1998 Lucent Technologies, Inc.\n *\n *\tThe \"busy\" command was created by George Howlett. Adapted for\n *\tintegration into Tk by Jos Decoster and Donal K. Fellows.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkBusy.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Things about the busy system that may be configured. Note that on some\n * platforms this may or may not have an effect.\n */\n\nstatic const Tk_OptionSpec busyOptionSpecs[] = {\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_BUSY_CURSOR, TCL_INDEX_NONE, offsetof(Busy, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\n/*\n * Forward declarations of functions defined in this file.\n */\n\nstatic void\t\tBusyEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tBusyGeometryProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tBusyCustodyProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic int\t\tConfigureBusy(Tcl_Interp *interp, Busy *busyPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic Busy *\t\tCreateBusy(Tcl_Interp *interp, Tk_Window tkRef);\nstatic Tcl_FreeProc\tDestroyBusy;\nstatic void\t\tDoConfigureNotify(Tk_FakeWin *winPtr);\nstatic inline Tk_Window\tFirstChild(Tk_Window parent);\nstatic Busy *\t\tGetBusy(Tcl_Interp *interp,\n\t\t\t    Tcl_HashTable *busyTablePtr,\n\t\t\t    Tcl_Obj *const windowObj);\nstatic int\t\tHoldBusy(Tcl_HashTable *busyTablePtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Obj *const windowObj,\n\t\t\t    Tcl_Size configObjc, Tcl_Obj *const configObjv[]);\nstatic void\t\tMakeTransparentWindowExist(Tk_Window tkwin,\n\t\t\t    Window parent);\nstatic inline Tk_Window\tNextChild(Tk_Window tkwin);\nstatic void\t\tRefWinEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic inline void\tSetWindowInstanceData(Tk_Window tkwin,\n\t\t\t    void *instanceData);\n\n/*\n * The \"busy\" geometry manager definition.\n */\n\nstatic Tk_GeomMgr busyMgrInfo = {\n    \"busy\",\t\t\t/* Name of geometry manager used by winfo */\n    BusyGeometryProc,\t\t/* Procedure to for new geometry requests */\n    BusyCustodyProc,\t\t/* Procedure when window is taken away */\n};\n\f\n/*\n * Helper functions, need to check if a Tcl/Tk alternative already exists.\n */\n\nstatic inline Tk_Window\nFirstChild(\n    Tk_Window parent)\n{\n    struct TkWindow *parentPtr = (struct TkWindow *) parent;\n\n    return (Tk_Window) parentPtr->childList;\n}\n\nstatic inline Tk_Window\nNextChild(\n    Tk_Window tkwin)\n{\n    struct TkWindow *winPtr = (struct TkWindow *) tkwin;\n\n    if (winPtr == NULL) {\n\treturn NULL;\n    }\n    return (Tk_Window) winPtr->nextPtr;\n}\n\nstatic inline void\nSetWindowInstanceData(\n    Tk_Window tkwin,\n    void *instanceData)\n{\n    struct TkWindow *winPtr = (struct TkWindow *) tkwin;\n\n    winPtr->instanceData = instanceData;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BusyCustodyProc --\n *\n *\tThis procedure is invoked when the busy window has been stolen by\n *\tanother geometry manager. The information and memory associated with\n *\tthe busy window is released. I don't know why anyone would try to pack\n *\ta busy window, but this should keep everything sane, if it is.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe Busy structure is freed at the next idle point.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nBusyCustodyProc(\n    void *clientData,\t/* Information about the busy window. */\n    TCL_UNUSED(Tk_Window))\t\t/* Not used. */\n{\n    Busy *busyPtr = (Busy *)clientData;\n\n    Tk_DeleteEventHandler(busyPtr->tkBusy, StructureNotifyMask, BusyEventProc,\n\t    busyPtr);\n    TkpHideBusyWindow(busyPtr);\n    busyPtr->tkBusy = NULL;\n    Tcl_EventuallyFree(busyPtr, DestroyBusy);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BusyGeometryProc --\n *\n *\tThis procedure is invoked by Tk_GeometryRequest for busy windows.\n *\tBusy windows never request geometry, so it's unlikely that this\n *\tfunction will ever be called;it exists simply as a place holder for\n *\tthe GeomProc in the Geometry Manager structure.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nBusyGeometryProc(\n    TCL_UNUSED(void *),\t/* Information about window that got new\n\t\t\t\t * preferred geometry. */\n    TCL_UNUSED(Tk_Window))\t\t/* Other Tk-related information about the\n\t\t\t\t * window. */\n{\n    /* Should never get here */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DoConfigureNotify --\n *\n *\tGenerate a ConfigureNotify event describing the current configuration\n *\tof a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn event is generated and processed by Tk_HandleEvent.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDoConfigureNotify(\n    Tk_FakeWin *winPtr)\t\t/* Window whose configuration was just\n\t\t\t\t * changed. */\n{\n    XEvent event;\n\n    event.type = ConfigureNotify;\n    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xconfigure.send_event = False;\n    event.xconfigure.display = winPtr->display;\n    event.xconfigure.event = winPtr->window;\n    event.xconfigure.window = winPtr->window;\n    event.xconfigure.x = winPtr->changes.x;\n    event.xconfigure.y = winPtr->changes.y;\n    event.xconfigure.width = winPtr->changes.width;\n    event.xconfigure.height = winPtr->changes.height;\n    event.xconfigure.border_width = winPtr->changes.border_width;\n    if (winPtr->changes.stack_mode == Above) {\n\tevent.xconfigure.above = winPtr->changes.sibling;\n    } else {\n\tevent.xconfigure.above = None;\n    }\n    event.xconfigure.override_redirect = winPtr->atts.override_redirect;\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RefWinEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for the following\n *\tevents on the reference window. If the reference and parent windows\n *\tare the same, only the first event is important.\n *\n *\t1) ConfigureNotify\tThe reference window has been resized or\n *\t\t\t\tmoved. Move and resize the busy window to be\n *\t\t\t\tthe same size and position of the reference\n *\t\t\t\twindow.\n *\n *\t2) DestroyNotify\tThe reference window was destroyed. Destroy\n *\t\t\t\tthe busy window and the free resources used.\n *\n *\t3) MapNotify\t\tThe reference window was (re)shown. Map the\n *\t\t\t\tbusy window again.\n *\n *\t4) UnmapNotify\t\tThe reference window was hidden. Unmap the\n *\t\t\t\tbusy window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the reference window gets deleted, internal structures get\n *\tcleaned up. When it gets resized, the busy window is resized\n *\taccordingly. If it's displayed, the busy window is displayed. And when\n *\tit's hidden, the busy window is unmapped.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRefWinEventProc(\n    void *clientData,\t/* Busy window record */\n    XEvent *eventPtr)\t/* Event which triggered call to routine */\n{\n    Busy *busyPtr = (Busy *)clientData;\n\n    switch (eventPtr->type) {\n    case ReparentNotify:\n    case DestroyNotify:\n\t/*\n\t * Arrange for the busy structure to be removed at a proper time.\n\t */\n\n\tTcl_EventuallyFree(busyPtr, DestroyBusy);\n\tbreak;\n\n    case ConfigureNotify:\n\tif ((busyPtr->width != Tk_Width(busyPtr->tkRef)) ||\n\t\t(busyPtr->height != Tk_Height(busyPtr->tkRef)) ||\n\t\t(busyPtr->x != Tk_X(busyPtr->tkRef)) ||\n\t\t(busyPtr->y != Tk_Y(busyPtr->tkRef))) {\n\t    int x, y;\n\n\t    busyPtr->width = Tk_Width(busyPtr->tkRef);\n\t    busyPtr->height = Tk_Height(busyPtr->tkRef);\n\t    busyPtr->x = Tk_X(busyPtr->tkRef);\n\t    busyPtr->y = Tk_Y(busyPtr->tkRef);\n\n\t    x = y = 0;\n\n\t    if (busyPtr->tkParent != busyPtr->tkRef) {\n\t\tTk_Window tkwin;\n\n\t\tfor (tkwin = busyPtr->tkRef; (tkwin != NULL) &&\n\t\t\t (!Tk_IsTopLevel(tkwin)); tkwin = Tk_Parent(tkwin)) {\n\t\t    if (tkwin == busyPtr->tkParent) {\n\t\t\tbreak;\n\t\t    }\n\t\t    x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;\n\t\t    y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;\n\t\t}\n\t    }\n\t    if (busyPtr->tkBusy != NULL) {\n\t\tTk_MoveResizeWindow(busyPtr->tkBusy, x, y, busyPtr->width,\n\t\t\tbusyPtr->height);\n\t\tTkpShowBusyWindow(busyPtr);\n\t    }\n\t}\n\tbreak;\n\n    case MapNotify:\n\tif (busyPtr->tkParent != busyPtr->tkRef) {\n\t    TkpShowBusyWindow(busyPtr);\n\t}\n\tbreak;\n\n    case UnmapNotify:\n\tif (busyPtr->tkParent != busyPtr->tkRef) {\n\t    TkpHideBusyWindow(busyPtr);\n\t}\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyBusy --\n *\n *\tThis procedure is called from the Tk event dispatcher. It releases X\n *\tresources and memory used by the busy window and updates the internal\n *\thash table.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and resources are released and the Tk event handler is removed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyBusy(\n    void *data)\t\t\t/* Busy window structure record */\n{\n    Busy *busyPtr = (Busy *)data;\n\n    if (busyPtr->hashPtr != NULL) {\n\tTcl_DeleteHashEntry(busyPtr->hashPtr);\n    }\n    Tk_DeleteEventHandler(busyPtr->tkRef, StructureNotifyMask,\n\t    RefWinEventProc, busyPtr);\n\n    if (busyPtr->tkBusy != NULL) {\n\tTk_FreeConfigOptions(data, busyPtr->optionTable, busyPtr->tkBusy);\n\tTk_DeleteEventHandler(busyPtr->tkBusy, StructureNotifyMask,\n\t\tBusyEventProc, busyPtr);\n\tTk_ManageGeometry(busyPtr->tkBusy, NULL, busyPtr);\n\tTk_DestroyWindow(busyPtr->tkBusy);\n    }\n    Tcl_Free(data);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BusyEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for events on the busy\n *\twindow itself. We're only concerned with destroy events.\n *\n *\tIt might be necessary (someday) to watch resize events. Right now, I\n *\tdon't think there's any point in it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen a busy window is destroyed, all internal structures associated\n *\twith it released at the next idle point.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nBusyEventProc(\n    void *clientData,\t/* Busy window record */\n    XEvent *eventPtr)\t\t/* Event which triggered call to routine */\n{\n    Busy *busyPtr = (Busy *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tbusyPtr->tkBusy = NULL;\n\tTcl_EventuallyFree(busyPtr, DestroyBusy);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MakeTransparentWindowExist --\n *\n *\tSimilar to Tk_MakeWindowExist but instead creates a transparent window\n *\tto block for user events from sibling windows.\n *\n *\tDifferences from Tk_MakeWindowExist.\n *\n *\t1. This is always a \"busy\" window. There's never a platform-specific\n *\t   class procedure to execute instead.\n *\t2. The window is transparent and never will contain children, so\n *\t   colormap information is irrelevant.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the procedure returns, the internal window associated with tkwin\n *\tis guaranteed to exist. This may require the window's ancestors to be\n *\tcreated too.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMakeTransparentWindowExist(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Window parent)\t\t/* Parent window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    Tcl_HashEntry *hPtr;\n    int notUsed;\n    TkDisplay *dispPtr;\n\n    if (winPtr->window != None) {\n\treturn;\t\t\t/* Window already exists. */\n    }\n\n    /*\n     * Create a transparent window and put it on top.\n     */\n\n    TkpMakeTransparentWindowExist(tkwin, parent);\n\n    if (winPtr->window == None) {\n\treturn;\t\t\t/* Platform didn't make Window. */\n    }\n\n    dispPtr = winPtr->dispPtr;\n    hPtr = Tcl_CreateHashEntry(&dispPtr->winTable, (char *) winPtr->window,\n\t    &notUsed);\n    Tcl_SetHashValue(hPtr, winPtr);\n    winPtr->dirtyAtts = 0;\n    winPtr->dirtyChanges = 0;\n\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\tTkWindow *winPtr2;\n\n\t/*\n\t * If any siblings higher up in the stacking order have already been\n\t * created then move this window to its rightful position in the\n\t * stacking order.\n\t *\n\t * NOTE: this code ignores any changes anyone might have made to the\n\t * sibling and stack_mode field of the window's attributes, so it\n\t * really isn't safe for these to be manipulated except by calling\n\t * Tk_RestackWindow.\n\t */\n\n\tfor (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;\n\t\twinPtr2 = winPtr2->nextPtr) {\n\t    if ((winPtr2->window != None) &&\n\t\t    !(winPtr2->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))) {\n\t\tXWindowChanges changes;\n\n\t\tchanges.sibling = winPtr2->window;\n\t\tchanges.stack_mode = Below;\n\t\tXConfigureWindow(winPtr->display, winPtr->window,\n\t\t\tCWSibling | CWStackMode, &changes);\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * Issue a ConfigureNotify event if there were deferred configuration\n     * changes (but skip it if the window is being deleted; the\n     * ConfigureNotify event could cause problems if we're being called from\n     * Tk_DestroyWindow under some conditions).\n     */\n\n    if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)\n\t    && !(winPtr->flags & TK_ALREADY_DEAD)) {\n\twinPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;\n\tDoConfigureNotify((Tk_FakeWin *) tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateBusy --\n *\n *\tCreates a child transparent window that obscures its parent window\n *\tthereby effectively blocking device events. The size and position of\n *\tthe busy window is exactly that of the reference window.\n *\n *\tWe want to create sibling to the window to be blocked. If the busy\n *\twindow is a child of the window to be blocked, Enter/Leave events can\n *\tsneak through. Futhermore under WIN32, messages of transparent windows\n *\tare sent directly to the parent. The only exception to this are\n *\ttoplevels, since we can't make a sibling. Fortunately, toplevel\n *\twindows rarely receive events that need blocking.\n *\n * Results:\n *\tReturns a pointer to the new busy window structure.\n *\n * Side effects:\n *\tWhen the busy window is eventually displayed, it will screen device\n *\tevents (in the area of the reference window) from reaching its parent\n *\twindow and its children. User feed back can be achieved by changing\n *\tthe cursor.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Busy *\nCreateBusy(\n    Tcl_Interp *interp,\t\t/* Interpreter to report error to */\n    Tk_Window tkRef)\t\t/* Window hosting the busy window */\n{\n    Busy *busyPtr;\n    size_t length;\n    int x, y;\n    const char *fmt;\n    char *name;\n    Tk_Window tkBusy, tkChild, tkParent;\n    Window parent;\n    Tk_FakeWin *winPtr;\n\n    busyPtr = (Busy *)Tcl_Alloc(sizeof(Busy));\n    x = y = 0;\n    length = strlen(Tk_Name(tkRef));\n    name = (char *)Tcl_Alloc(length + 6);\n    if (Tk_IsTopLevel(tkRef)) {\n\tfmt = \"_Busy\";\t\t/* Child */\n\ttkParent = tkRef;\n    } else {\n\tTk_Window tkwin;\n\n\tfmt = \"%s_Busy\";\t/* Sibling */\n\ttkParent = Tk_Parent(tkRef);\n\tfor (tkwin = tkRef; (tkwin != NULL) && !Tk_IsTopLevel(tkwin);\n\t\ttkwin = Tk_Parent(tkwin)) {\n\t    if (tkwin == tkParent) {\n\t\tbreak;\n\t    }\n\t    x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;\n\t    y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;\n\t}\n    }\n    for (tkChild = FirstChild(tkParent); tkChild != NULL;\n\t    tkChild = NextChild(tkChild)) {\n\tTk_MakeWindowExist(tkChild);\n    }\n    snprintf(name, length + 6, fmt, Tk_Name(tkRef));\n    tkBusy = Tk_CreateWindow(interp, tkParent, name, NULL);\n    Tcl_Free(name);\n\n    if (tkBusy == NULL) {\n\treturn NULL;\n    }\n    Tk_MakeWindowExist(tkRef);\n    busyPtr->display = Tk_Display(tkRef);\n    busyPtr->interp = interp;\n    busyPtr->tkRef = tkRef;\n    busyPtr->tkParent = tkParent;\n    busyPtr->tkBusy = tkBusy;\n    busyPtr->width = Tk_Width(tkRef);\n    busyPtr->height = Tk_Height(tkRef);\n    busyPtr->x = Tk_X(tkRef);\n    busyPtr->y = Tk_Y(tkRef);\n    busyPtr->cursor = NULL;\n    Tk_SetClass(tkBusy, \"Busy\");\n    busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs);\n    if (Tk_InitOptions(interp, busyPtr, busyPtr->optionTable,\n\t    tkBusy) != TCL_OK) {\n\tTk_DestroyWindow(tkBusy);\n\treturn NULL;\n    }\n    SetWindowInstanceData(tkBusy, busyPtr);\n    winPtr = (Tk_FakeWin *) tkRef;\n\n    TkpCreateBusy(winPtr, tkRef, &parent, tkParent, busyPtr);\n\n    MakeTransparentWindowExist(tkBusy, parent);\n\n    Tk_MoveResizeWindow(tkBusy, x, y, busyPtr->width, busyPtr->height);\n\n    /*\n     * Only worry if the busy window is destroyed.\n     */\n\n    Tk_CreateEventHandler(tkBusy, StructureNotifyMask, BusyEventProc,\n\t    busyPtr);\n\n    /*\n     * Indicate that the busy window's geometry is being managed. This will\n     * also notify us if the busy window is ever packed.\n     */\n\n    Tk_ManageGeometry(tkBusy, &busyMgrInfo, busyPtr);\n    if (busyPtr->cursor != NULL) {\n\tTk_DefineCursor(tkBusy, busyPtr->cursor);\n    }\n\n    /*\n     * Track the reference window to see if it is resized or destroyed.\n     */\n\n    Tk_CreateEventHandler(tkRef, StructureNotifyMask, RefWinEventProc,\n\t    busyPtr);\n    return busyPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureBusy --\n *\n *\tThis procedure is called from the Tk event dispatcher. It releases X\n *\tresources and memory used by the busy window and updates the internal\n *\thash table.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and resources are released and the Tk event handler is removed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureBusy(\n    Tcl_Interp *interp,\n    Busy *busyPtr,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tk_Cursor oldCursor = busyPtr->cursor;\n\n    if (Tk_SetOptions(interp, busyPtr, busyPtr->optionTable, objc,\n\t    objv, busyPtr->tkBusy, NULL, NULL) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (busyPtr->cursor != oldCursor) {\n\tif (busyPtr->cursor == NULL) {\n\t    Tk_UndefineCursor(busyPtr->tkBusy);\n\t} else {\n\t    Tk_DefineCursor(busyPtr->tkBusy, busyPtr->cursor);\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetBusy --\n *\n *\tReturns the busy window structure associated with the reference\n *\twindow, keyed by its path name. The clientData argument is the main\n *\twindow of the interpreter, used to search for the reference window in\n *\tits own window hierarchy.\n *\n * Results:\n *\tIf path name represents a reference window with a busy window, a\n *\tpointer to the busy window structure is returned. Otherwise, NULL is\n *\treturned and an error message is left in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Busy *\nGetBusy(\n    Tcl_Interp *interp,\t\t/* Interpreter to look up main window of. */\n    Tcl_HashTable *busyTablePtr,/* Busy hash table */\n    Tcl_Obj *const windowObj)\t/* Path name of parent window */\n{\n    Tcl_HashEntry *hPtr;\n    Tk_Window tkwin;\n\n    tkwin = Tk_MainWindow(interp);\n    if (!tkwin || (TkGetWindowFromObj(interp, tkwin, windowObj, &tkwin) != TCL_OK)) {\n\treturn NULL;\n    }\n    hPtr = Tcl_FindHashEntry(busyTablePtr, tkwin);\n    if (hPtr == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"cannot find busy window \\\"%s\\\"\", Tcl_GetString(windowObj)));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"BUSY\",\n\t\tTcl_GetString(windowObj), (char *)NULL);\n\treturn NULL;\n    }\n    return (Busy *)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * HoldBusy --\n *\n *\tCreates (if necessary) and maps a busy window, thereby preventing\n *\tdevice events from being be received by the parent window and its\n *\tchildren.\n *\n * Results:\n *\tReturns a standard TCL result. If path name represents a busy window,\n *\tit is unmapped and TCL_OK is returned. Otherwise, TCL_ERROR is\n *\treturned and an error message is left in interp->result.\n *\n * Side effects:\n *\tThe busy window is created and displayed, blocking events from the\n *\tparent window and its children.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nHoldBusy(\n    Tcl_HashTable *busyTablePtr,/* Busy hash table. */\n    Tcl_Interp *interp,\t\t/* Interpreter to report errors to. */\n    Tcl_Obj *const windowObj,\t/* Window name. */\n    Tcl_Size configObjc,\t\t/* Option pairs. */\n    Tcl_Obj *const configObjv[])\n{\n    Tk_Window tkwin;\n    Tcl_HashEntry *hPtr;\n    Busy *busyPtr;\n    int isNew, result;\n\n    if (TkGetWindowFromObj(interp, Tk_MainWindow(interp), windowObj,\n\t    &tkwin) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    hPtr = Tcl_CreateHashEntry(busyTablePtr, (char *) tkwin, &isNew);\n    if (isNew) {\n\tbusyPtr = CreateBusy(interp, tkwin);\n\tif (busyPtr == NULL) {\n\t    Tcl_DeleteHashEntry(hPtr);\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetHashValue(hPtr, busyPtr);\n\tbusyPtr->hashPtr = hPtr;\n    } else {\n\tbusyPtr = (Busy *)Tcl_GetHashValue(hPtr);\n    }\n\n    busyPtr->tablePtr = busyTablePtr;\n    result = ConfigureBusy(interp, busyPtr, configObjc, configObjv);\n\n    /*\n     * Don't map the busy window unless the reference window is also currently\n     * displayed.\n     */\n\n    if (Tk_IsMapped(busyPtr->tkRef)) {\n\tTkpShowBusyWindow(busyPtr);\n    } else {\n\tTkpHideBusyWindow(busyPtr);\n    }\n    if (result == TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), TCL_INDEX_NONE));\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_BusyObjCmd --\n *\n *\tThis function is invoked to process the \"tk busy\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_BusyObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tcl_HashTable *busyTablePtr = &((TkWindow *) tkwin)->mainPtr->busyTable;\n    Busy *busyPtr;\n    Tcl_Obj *objPtr;\n    int index, result = TCL_OK;\n    static const char *const optionStrings[] = {\n\t\"busywindow\", \"cget\", \"configure\", \"current\", \"forget\", \"hold\",\n\t\"status\", NULL\n    };\n    enum options {\n\tBUSY_BUSYWINDOW, BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET,\n\tBUSY_HOLD, BUSY_STATUS\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"options ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * [tk busy <window>] command shortcut.\n     */\n\n    if (Tcl_GetString(objv[1])[0] == '.') {\n\tif (objc%2 == 1) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"window ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\treturn HoldBusy(busyTablePtr, interp, objv[1], objc-2, objv+2);\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch ((enum options) index) {\n    case BUSY_BUSYWINDOW:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tbusyPtr = GetBusy(interp, busyTablePtr, objv[2]);\n\tif (busyPtr == NULL) {\n\t    Tcl_ResetResult(interp);\n\t    return TCL_OK;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), TCL_INDEX_NONE));\n\treturn TCL_OK;\n\n    case BUSY_CGET:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window option\");\n\t    return TCL_ERROR;\n\t}\n\tbusyPtr = GetBusy(interp, busyTablePtr, objv[2]);\n\tif (busyPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_Preserve(busyPtr);\n\tobjPtr = Tk_GetOptionValue(interp, busyPtr,\n\t\tbusyPtr->optionTable, objv[3], busyPtr->tkBusy);\n\tif (objPtr == NULL) {\n\t    result = TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, objPtr);\n\t}\n\tTcl_Release(busyPtr);\n\treturn result;\n\n    case BUSY_CONFIGURE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tbusyPtr = GetBusy(interp, busyTablePtr, objv[2]);\n\tif (busyPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_Preserve(busyPtr);\n\tif (objc <= 4) {\n\t    objPtr = Tk_GetOptionInfo(interp, busyPtr,\n\t\t    busyPtr->optionTable, (objc == 4) ? objv[3] : NULL,\n\t\t    busyPtr->tkBusy);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, objPtr);\n\t    }\n\t} else {\n\t    result = ConfigureBusy(interp, busyPtr, objc-3, objv+3);\n\t}\n\tTcl_Release(busyPtr);\n\treturn result;\n\n    case BUSY_CURRENT: {\n\tTcl_HashEntry *hPtr;\n\tTcl_HashSearch cursor;\n\tconst char *pattern = (objc == 3 ? Tcl_GetString(objv[2]) : NULL);\n\n\tobjPtr = Tcl_NewObj();\n\tfor (hPtr = Tcl_FirstHashEntry(busyTablePtr, &cursor); hPtr != NULL;\n\t\thPtr = Tcl_NextHashEntry(&cursor)) {\n\t    busyPtr = (Busy *)Tcl_GetHashValue(hPtr);\n\t    if (pattern == NULL ||\n\t\t    Tcl_StringCaseMatch(Tk_PathName(busyPtr->tkRef), pattern, 0)) {\n\t\tTcl_ListObjAppendElement(interp, objPtr,\n\t\t\tTk_NewWindowObj(busyPtr->tkRef));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\treturn TCL_OK;\n    }\n\n    case BUSY_FORGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tbusyPtr = GetBusy(interp, busyTablePtr, objv[2]);\n\tif (busyPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTkpHideBusyWindow(busyPtr);\n\tTcl_EventuallyFree(busyPtr, DestroyBusy);\n\treturn TCL_OK;\n\n    case BUSY_HOLD:\n\tif (objc < 3 || objc%2 != 1) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\treturn HoldBusy(busyTablePtr, interp, objv[2], objc-3, objv+3);\n\n    case BUSY_STATUS:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\tGetBusy(interp, busyTablePtr, objv[2]) != NULL));\n\treturn TCL_OK;\n    }\n\n    Tcl_Panic(\"unhandled option: %d\", index);\n    return TCL_ERROR;\t\t/* Unreachable */\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkBusy.h",
    "content": "/*\n * tkBusy.h --\n *\n *\tThis file defines the type of the structure describing a busy window.\n *\n * Copyright 1993-1998 Lucent Technologies, Inc.\n *\n *\tThe \"busy\" command was created by George Howlett. Adapted for\n *\tintegration into Tk by Jos Decoster and Donal K. Fellows.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\ntypedef struct Busy {\n    Display *display;\t\t/* Display of busy window */\n    Tcl_Interp *interp;\t\t/* Interpreter where \"busy\" command was\n\t\t\t\t * created. It's used to key the searches in\n\t\t\t\t * the window hierarchy. See the \"windows\"\n\t\t\t\t * command. */\n    Tk_Window tkBusy;\t\t/* Busy window: Transparent window used to\n\t\t\t\t * block delivery of events to windows\n\t\t\t\t * underneath it. */\n    Tk_Window tkParent;\t\t/* Parent window of the busy window. It may be\n\t\t\t\t * the reference window (if the reference is a\n\t\t\t\t * toplevel) or a mutual ancestor of the\n\t\t\t\t * reference window */\n    Tk_Window tkRef;\t\t/* Reference window of the busy window. It is\n\t\t\t\t * used to manage the size and position of the\n\t\t\t\t * busy window. */\n    int x, y;\t\t\t/* Position of the reference window */\n    int width, height;\t\t/* Size of the reference window. Retained to\n\t\t\t\t * know if the reference window has been\n\t\t\t\t * reconfigured to a new size. */\n    int menuBar;\t\t/* Menu bar flag. */\n    Tk_Cursor cursor;\t\t/* Cursor for the busy window. */\n    Tcl_HashEntry *hashPtr;\t/* Used the delete the busy window entry out\n\t\t\t\t * of the global hash table. */\n    Tcl_HashTable *tablePtr;\n    Tk_OptionTable optionTable;\n} Busy;\n"
  },
  {
    "path": "generic/tkButton.c",
    "content": "/*\n * tkButton.c --\n *\n *\tThis module implements a collection of button-like widgets for the Tk\n *\ttoolkit. The widgets implemented include buttons, checkbuttons,\n *\tradiobuttons, and labels.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkButton.h\"\n#include \"default.h\"\n\ntypedef struct {\n    bool defaultsInitialized;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Class names for buttons, indexed by one of the type values defined in\n * tkButton.h.\n */\n\nstatic const char *const classNames[] = {\"Label\", \"Button\", \"Checkbutton\", \"Radiobutton\"};\n\n/*\n * The following table defines the legal values for the -default/-state options.\n * It is used together with the \"enum defaultValue/state\" declarations in tkButton.h.\n */\n\nconst char *const tkStateStrings[] = {\n    \"active\", \"disabled\", \"normal\", NULL\n};\n\n/*\n * The following table defines the legal values for the -compound option.\n * It is used with the \"enum compound\" declaration in tkButton.h\n */\n\nconst char *const tkCompoundStrings[] = {\n    \"bottom\", \"center\", \"left\", \"none\", \"right\", \"top\", NULL\n};\n\nchar tkDefButtonHighlightWidth[TCL_INTEGER_SPACE] = DEF_BUTTON_HIGHLIGHT_WIDTH;\nchar tkDefButtonPadx[TCL_INTEGER_SPACE] = DEF_BUTTON_PADX;\nchar tkDefButtonPady[TCL_INTEGER_SPACE] = DEF_BUTTON_PADY;\nchar tkDefButtonBorderWidth[TCL_INTEGER_SPACE] = DEF_BUTTON_BORDER_WIDTH;\nchar tkDefLabelHighlightWidth[TCL_INTEGER_SPACE] = DEF_LABEL_HIGHLIGHT_WIDTH;\nchar tkDefLabelPadx[TCL_INTEGER_SPACE] = DEF_LABCHKRAD_PADX;\nchar tkDefLabelPady[TCL_INTEGER_SPACE] = DEF_LABCHKRAD_PADY;\n\n/*\n * Information used for parsing configuration options.  There is a\n * separate table for each of the four widget classes.\n */\n\nstatic const Tk_OptionSpec labelOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),\n\t0, DEF_BUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\", \"Background\",\n\tDEF_BUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\tDEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),\n\t0, DEF_BUTTON_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\",\n\tDEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\ttkDefButtonBorderWidth, offsetof(TkButton, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound),\n\t0, tkCompoundStrings, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_BUTTON_DISABLED_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,\n\tDEF_BUTTON_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_LABEL_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_BUTTON_HEIGHT, offsetof(TkButton, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_BUTTON_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,\n\tDEF_BUTTON_HIGHLIGHT_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", tkDefLabelHighlightWidth,\n\toffsetof(TkButton, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\ttkDefLabelPadx, offsetof(TkButton, padXObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\ttkDefLabelPady, offsetof(TkButton, padYObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_LABEL_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTK_OPTION_UNDERLINE_DEF(TkButton, underline), 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tDEF_BUTTON_WIDTH, offsetof(TkButton, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tDEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\nstatic const Tk_OptionSpec buttonOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),\n\t0, DEF_BUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\", \"Background\",\n\tDEF_BUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\tDEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),\n\t0, DEF_BUTTON_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\",\n\tDEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\ttkDefButtonBorderWidth, offsetof(TkButton, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound),\n\t0, tkCompoundStrings, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-default\", \"default\", \"Default\",\n\tDEF_BUTTON_DEFAULT, TCL_INDEX_NONE, offsetof(TkButton, defaultState),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_BUTTON_DISABLED_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,\n\tDEF_BUTTON_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_BUTTON_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_BUTTON_HEIGHT, offsetof(TkButton, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_BUTTON_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,\n\tDEF_BUTTON_HIGHLIGHT_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", tkDefButtonHighlightWidth,\n\toffsetof(TkButton, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_RELIEF, \"-overrelief\", \"overRelief\", \"OverRelief\",\n\t DEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\ttkDefButtonPadx, offsetof(TkButton, padXObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\ttkDefButtonPady, offsetof(TkButton, padYObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief),\n\t 0, 0, 0},\n    {TK_OPTION_INT, \"-repeatdelay\", \"repeatDelay\", \"RepeatDelay\",\n\t DEF_BUTTON_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(TkButton, repeatDelay),\n\t 0, 0, 0},\n    {TK_OPTION_INT, \"-repeatinterval\", \"repeatInterval\", \"RepeatInterval\",\n\t DEF_BUTTON_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(TkButton, repeatInterval),\n\t 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTK_OPTION_UNDERLINE_DEF(TkButton, underline), 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tDEF_BUTTON_WIDTH, offsetof(TkButton, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tDEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\nstatic const Tk_OptionSpec checkbuttonOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),\n\t0, DEF_BUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\", \"Background\",\n\tDEF_CHKRAD_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\tDEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),\n\t0, DEF_BUTTON_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\",\n\tDEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\ttkDefButtonBorderWidth, offsetof(TkButton, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound),\n\t0, tkCompoundStrings, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_BUTTON_DISABLED_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,\n\tDEF_BUTTON_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_CHKRAD_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_BUTTON_HEIGHT, offsetof(TkButton, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_BUTTON_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,\n\tDEF_BUTTON_HIGHLIGHT_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", tkDefButtonHighlightWidth,\n\toffsetof(TkButton, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-indicatoron\", \"indicatorOn\", \"IndicatorOn\",\n\tDEF_BUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkButton, indicatorOn), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_RELIEF, \"-offrelief\", \"offRelief\", \"OffRelief\",\n\tDEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, offRelief), 0, 0, 0},\n    {TK_OPTION_STRING, \"-offvalue\", \"offValue\", \"Value\",\n\tDEF_BUTTON_OFF_VALUE, offsetof(TkButton, offValuePtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-onvalue\", \"onValue\", \"Value\",\n\tDEF_BUTTON_ON_VALUE, offsetof(TkButton, onValuePtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-overrelief\", \"overRelief\", \"OverRelief\",\n\tDEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\ttkDefLabelPadx, offsetof(TkButton, padXObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\ttkDefLabelPady, offsetof(TkButton, padYObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectcolor\", \"selectColor\", \"Background\",\n\tDEF_BUTTON_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkButton, selectBorder),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},\n    {TK_OPTION_STRING, \"-selectimage\", \"selectImage\", \"SelectImage\",\n\tDEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-tristateimage\", \"tristateImage\", \"TristateImage\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-tristatevalue\", \"tristateValue\", \"TristateValue\",\n\tDEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTK_OPTION_UNDERLINE_DEF(TkButton, underline), 0},\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\tDEF_CHECKBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tDEF_BUTTON_WIDTH, offsetof(TkButton, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tDEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\nstatic const Tk_OptionSpec radiobuttonOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),\n\t0, DEF_BUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\", \"Background\",\n\tDEF_CHKRAD_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\tDEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),\n\t0, DEF_BUTTON_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\",\n\tDEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\ttkDefButtonBorderWidth, offsetof(TkButton, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound),\n\t0, tkCompoundStrings, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_BUTTON_DISABLED_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,\n\tDEF_BUTTON_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_CHKRAD_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_BUTTON_HEIGHT, offsetof(TkButton, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_BUTTON_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,\n\tDEF_BUTTON_HIGHLIGHT_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", tkDefButtonHighlightWidth,\n\toffsetof(TkButton, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-indicatoron\", \"indicatorOn\", \"IndicatorOn\",\n\tDEF_BUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkButton, indicatorOn),\n\tTK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_RELIEF, \"-offrelief\", \"offRelief\", \"OffRelief\",\n\t DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, offRelief), 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-overrelief\", \"overRelief\", \"OverRelief\",\n\t DEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\ttkDefLabelPadx, offsetof(TkButton, padXObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\ttkDefLabelPady, offsetof(TkButton, padYObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectcolor\", \"selectColor\", \"Background\",\n\tDEF_BUTTON_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkButton, selectBorder),\n\tTK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},\n    {TK_OPTION_STRING, \"-selectimage\", \"selectImage\", \"SelectImage\",\n\tDEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-tristateimage\", \"tristateImage\", \"TristateImage\",\n\tDEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-tristatevalue\", \"tristateValue\", \"TristateValue\",\n\tDEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTK_OPTION_UNDERLINE_DEF(TkButton, underline), 0},\n    {TK_OPTION_STRING, \"-value\", \"value\", \"Value\",\n\tDEF_BUTTON_VALUE, offsetof(TkButton, onValuePtr), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\tDEF_RADIOBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tDEF_BUTTON_WIDTH, offsetof(TkButton, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tDEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * The following table maps from one of the type values defined in tkButton.h,\n * such as TYPE_LABEL, to the option template for that class of widgets.\n */\n\nstatic const Tk_OptionSpec *const optionSpecs[] = {\n    labelOptionSpecs,\n    buttonOptionSpecs,\n    checkbuttonOptionSpecs,\n    radiobuttonOptionSpecs\n};\n\n/*\n * The following tables define the widget commands supported by each of the\n * classes, and map the indexes into the string tables into a single\n * enumerated type used to dispatch the widget command.\n */\n\nstatic const char *const commandNames[][8] = {\n    {\"cget\", \"configure\", NULL},\n    {\"cget\", \"configure\", \"flash\", \"invoke\", NULL},\n    {\"cget\", \"configure\", \"deselect\", \"flash\", \"invoke\", \"select\",\n\t    \"toggle\", NULL},\n    {\"cget\", \"configure\", \"deselect\", \"flash\", \"invoke\", \"select\", NULL}\n};\nenum command {\n    COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,\n    COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE\n};\nstatic const enum command map[][8] = {\n    {COMMAND_CGET, COMMAND_CONFIGURE},\n    {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},\n    {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,\n\t    COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},\n    {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,\n\t    COMMAND_INVOKE, COMMAND_SELECT}\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tButtonCmdDeletedProc(void *clientData);\nstatic int\t\tButtonCreate(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int type);\nstatic void\t\tButtonEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tButtonImageProc(void *clientData,\n\t\t\t    int x, int y, int width, int height,\n\t\t\t    int imgWidth, int imgHeight);\nstatic void\t\tButtonSelectImageProc(void *clientData,\n\t\t\t    int x, int y, int width, int height,\n\t\t\t    int imgWidth, int imgHeight);\nstatic void\t\tButtonTristateImageProc(void *clientData,\n\t\t\t    int x, int y, int width, int height,\n\t\t\t    int imgWidth, int imgHeight);\nstatic char *\t\tButtonTextVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic char *\t\tButtonVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic Tcl_ObjCmdProc2 ButtonWidgetObjCmd;\nstatic int\t\tConfigureButton(Tcl_Interp *interp, TkButton *butPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDestroyButton(TkButton *butPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd --\n *\n *\tThese functions are invoked to process the \"button\", \"label\",\n *\t\"radiobutton\", and \"checkbutton\" Tcl commands. See the user\n *\tdocumentation for details on what they do.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation. These functions are just wrappers; they\n *\tcall ButtonCreate to do all of the real work.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ButtonObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);\n}\n\nint\nTk_CheckbuttonObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);\n}\n\nint\nTk_LabelObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);\n}\n\nint\nTk_RadiobuttonObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonCreate --\n *\n *\tThis function does all the real work of implementing the \"button\",\n *\t\"label\", \"radiobutton\", and \"checkbutton\" Tcl commands. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nButtonCreate(\n    TCL_UNUSED(void *),\t/* NULL. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument values. */\n    int type)\t\t\t/* Type of button to create: TYPE_LABEL,\n\t\t\t\t * TYPE_BUTTON, TYPE_CHECK_BUTTON, or\n\t\t\t\t * TYPE_RADIO_BUTTON. */\n{\n    TkButton *butPtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->defaultsInitialized) {\n\tTkpButtonSetDefaults();\n\ttsdPtr->defaultsInitialized = true;\n    }\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the new window.\n     */\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), (char *)NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);\n\n    Tk_SetClass(tkwin, classNames[type]);\n    butPtr = TkpCreateButton(tkwin);\n\n    Tk_SetClassProcs(tkwin, &tkpButtonProcs, butPtr);\n\n    /*\n     * Initialize the data structure for the button.\n     */\n\n    butPtr->tkwin = tkwin;\n    butPtr->display = Tk_Display(tkwin);\n    butPtr->interp = interp;\n    butPtr->widgetCmd = Tcl_CreateObjCommand2(interp, Tk_PathName(tkwin),\n\t    ButtonWidgetObjCmd, butPtr, ButtonCmdDeletedProc);\n    butPtr->type = type;\n    butPtr->optionTable = optionTable;\n    butPtr->textPtr = NULL;\n    butPtr->underline = INT_MIN;\n    butPtr->textVarNamePtr = NULL;\n    butPtr->bitmap = None;\n    butPtr->imagePtr = NULL;\n    butPtr->image = NULL;\n    butPtr->selectImagePtr = NULL;\n    butPtr->selectImage = NULL;\n    butPtr->tristateImagePtr = NULL;\n    butPtr->tristateImage = NULL;\n    butPtr->state = STATE_NORMAL;\n    butPtr->normalBorder = NULL;\n    butPtr->activeBorder = NULL;\n    butPtr->borderWidthObj = NULL;\n    butPtr->relief = TK_RELIEF_FLAT;\n    butPtr->highlightWidthObj = NULL;\n    butPtr->highlightBorder = NULL;\n    butPtr->highlightColorPtr = NULL;\n    butPtr->inset = 0;\n    butPtr->tkfont = NULL;\n    butPtr->normalFg = NULL;\n    butPtr->activeFg = NULL;\n    butPtr->disabledFg = NULL;\n    butPtr->normalTextGC = NULL;\n    butPtr->activeTextGC = NULL;\n    butPtr->disabledGC = NULL;\n    butPtr->stippleGC = NULL;\n    butPtr->gray = None;\n    butPtr->copyGC = NULL;\n    butPtr->widthObj = NULL;\n    butPtr->heightObj = NULL;\n    butPtr->wrapLengthObj = NULL;\n    butPtr->padXObj = NULL;\n    butPtr->padYObj = NULL;\n    butPtr->anchor = TK_ANCHOR_CENTER;\n    butPtr->justify = TK_JUSTIFY_CENTER;\n    butPtr->indicatorOn = false;\n    butPtr->selectBorder = NULL;\n    butPtr->textWidth = 0;\n    butPtr->textHeight = 0;\n    butPtr->textLayout = NULL;\n    butPtr->indicatorSpace = 0;\n    butPtr->indicatorDiameter = 0;\n    butPtr->defaultState = DEFAULT_DISABLED;\n    butPtr->selVarNamePtr = NULL;\n    butPtr->onValuePtr = NULL;\n    butPtr->offValuePtr = NULL;\n    butPtr->tristateValuePtr = NULL;\n    butPtr->cursor = NULL;\n    butPtr->takeFocusPtr = NULL;\n    butPtr->commandPtr = NULL;\n    butPtr->flags = 0;\n\n    Tk_CreateEventHandler(butPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    ButtonEventProc, butPtr);\n\n    if (Tk_InitOptions(interp, butPtr, optionTable, tkwin)\n\t    != TCL_OK) {\n\tTk_DestroyWindow(butPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n    if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {\n\tTk_DestroyWindow(butPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(butPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonWidgetCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nButtonWidgetObjCmd(\n    void *clientData,\t/* Information about button widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n    int index;\n    int result;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames[butPtr->type],\n\t    sizeof(char *), \"option\", 0, &index);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    Tcl_Preserve(butPtr);\n\n    switch (map[butPtr->type][index]) {\n    case COMMAND_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"cget option\");\n\t    goto error;\n\t}\n\tobjPtr = Tk_GetOptionValue(interp, butPtr,\n\t\tbutPtr->optionTable, objv[2], butPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n\n    case COMMAND_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, butPtr,\n\t\t    butPtr->optionTable, (objc == 3) ? objv[2] : NULL,\n\t\t    butPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureButton(interp, butPtr, objc-2, objv+2);\n\t}\n\tbreak;\n\n    case COMMAND_DESELECT:\n\tif (objc > 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"deselect\");\n\t    goto error;\n\t}\n\tif (butPtr->type == TYPE_CHECK_BUTTON) {\n\t    if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,\n\t\t    butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t    == NULL) {\n\t\tgoto error;\n\t    }\n\t} else if (butPtr->flags & SELECTED) {\n\t    if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,\n\t\t     Tcl_NewObj(), TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL){\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n\n    case COMMAND_FLASH:\n\tif (objc > 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"flash\");\n\t    goto error;\n\t}\n\tif (butPtr->state != STATE_DISABLED) {\n\t    int i;\n\n\t    for (i = 0; i < 4; i++) {\n\t\tif (butPtr->state == STATE_NORMAL) {\n\t\t    butPtr->state = STATE_ACTIVE;\n\t\t    Tk_SetBackgroundFromBorder(butPtr->tkwin,\n\t\t\t    butPtr->activeBorder);\n\t\t} else {\n\t\t    butPtr->state = STATE_NORMAL;\n\t\t    Tk_SetBackgroundFromBorder(butPtr->tkwin,\n\t\t\t    butPtr->normalBorder);\n\t\t}\n\t\tTkpDisplayButton(butPtr);\n\n\t\t/*\n\t\t * Special note: must cancel any existing idle handler for\n\t\t * TkpDisplayButton; it's no longer needed, and\n\t\t * TkpDisplayButton cleared the REDRAW_PENDING flag.\n\t\t */\n\n\t\tTcl_CancelIdleCall(TkpDisplayButton, butPtr);\n\t\t(void)XFlush(butPtr->display);\n\t\t#ifndef MAC_OSX_TK\n\t\t/*\n\t\t * On the mac you can not sleep in a display proc, and the\n\t\t * flash command doesn't do anything anyway.\n\t\t */\n\t\tTcl_Sleep(50);\n\t\t#endif\n\t    }\n\t}\n\tbreak;\n\n    case COMMAND_INVOKE:\n\tif (objc > 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"invoke\");\n\t    goto error;\n\t}\n\tif (butPtr->state != STATE_DISABLED) {\n\t    result = TkInvokeButton(butPtr);\n\t}\n\tbreak;\n\n    case COMMAND_SELECT:\n\tif (objc > 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"select\");\n\t    goto error;\n\t}\n\tif (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,\n\t\tbutPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t== NULL) {\n\t    goto error;\n\t}\n\tbreak;\n\n    case COMMAND_TOGGLE:\n\tif (objc > 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"toggle\");\n\t    goto error;\n\t}\n\tif (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,\n\t\t(butPtr->flags & SELECTED) ? butPtr->offValuePtr\n\t\t: butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t== NULL) {\n\t    goto error;\n\t}\n\tbreak;\n    }\n    Tcl_Release(butPtr);\n    return result;\n\n  error:\n    Tcl_Release(butPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyButton --\n *\n *\tThis function is invoked by ButtonEventProc to free all the resources\n *\tof a button and clean up its state.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the widget is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyButton(\n    TkButton *butPtr)\t\t/* Info about button widget. */\n{\n    butPtr->flags |= BUTTON_DELETED;\n    TkpDestroyButton(butPtr);\n\n    if (butPtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(TkpDisplayButton, butPtr);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);\n    if (butPtr->textVarNamePtr != NULL) {\n\tTcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonTextVarProc, butPtr);\n    }\n    if (butPtr->image != NULL) {\n\tTk_FreeImage(butPtr->image);\n    }\n    if (butPtr->selectImage != NULL) {\n\tTk_FreeImage(butPtr->selectImage);\n    }\n    if (butPtr->tristateImage != NULL) {\n\tTk_FreeImage(butPtr->tristateImage);\n    }\n    if (butPtr->normalTextGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->normalTextGC);\n    }\n    if (butPtr->activeTextGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->activeTextGC);\n    }\n    if (butPtr->disabledGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->disabledGC);\n    }\n    if (butPtr->stippleGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->stippleGC);\n    }\n    if (butPtr->gray != None) {\n\tTk_FreeBitmap(butPtr->display, butPtr->gray);\n    }\n    if (butPtr->copyGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->copyGC);\n    }\n    if (butPtr->textLayout != NULL) {\n\tTk_FreeTextLayout(butPtr->textLayout);\n    }\n    if (butPtr->selVarNamePtr != NULL) {\n\tTcl_UntraceVar2(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonVarProc, butPtr);\n    }\n    Tk_FreeConfigOptions(butPtr, butPtr->optionTable,\n\t    butPtr->tkwin);\n    butPtr->tkwin = NULL;\n    Tcl_EventuallyFree(butPtr, TCL_DYNAMIC);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureButton --\n *\n *\tThis function is called to process an objc/objv list to set\n *\tconfiguration options for a button widget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen an error message is left in interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as text string, colors, font, etc. get\n *\tset for butPtr; old resources get freed, if there were any. The button\n *\tis redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureButton(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkButton *butPtr,\t/* Information about widget;  may or may\n\t\t\t\t * not already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    Tk_SavedOptions savedOptions;\n    Tcl_Obj *errorResult = NULL;\n    int error, haveImage;\n    Tk_Image image;\n    int width, height;\n\n    /*\n     * Eliminate any existing trace on variables monitored by the button.\n     */\n\n    if (butPtr->textVarNamePtr != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonTextVarProc, butPtr);\n    }\n    if (butPtr->selVarNamePtr != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonVarProc, butPtr);\n    }\n\n    /*\n     * The following loop is potentially executed twice. During the first pass\n     * configuration options get set to their new values. If there is an error\n     * in this pass, we execute a second pass to restore all the options to\n     * their previous values.\n     */\n\n    for (error = 0; error <= 1; error++) {\n\tif (!error) {\n\t    /*\n\t     * First pass: set options to new values.\n\t     */\n\n\t    if (Tk_SetOptions(interp, butPtr,\n\t\t    butPtr->optionTable, objc, objv,\n\t\t    butPtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * Second pass: restore options to old values.\n\t     */\n\n\t    errorResult = Tcl_GetObjResult(interp);\n\t    Tcl_IncrRefCount(errorResult);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t}\n\n\tif ((butPtr->flags & BUTTON_DELETED)) {\n\t    /*\n\t     * Somehow button was deleted - just abort now. [Bug #824479]\n\t     */\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * A few options need special processing, such as setting the\n\t * background from a 3-D border, or filling in complicated defaults\n\t * that couldn't be specified to Tk_SetOptions.\n\t */\n\n\tif ((butPtr->state == STATE_ACTIVE)\n\t\t&& !Tk_StrictMotif(butPtr->tkwin)) {\n\t    Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);\n\t} else {\n\t    Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);\n\t}\n\n\tif (butPtr->type >= TYPE_CHECK_BUTTON) {\n\t    Tcl_Obj *valuePtr, *namePtr;\n\n\t    if (butPtr->selVarNamePtr == NULL) {\n\t\tbutPtr->selVarNamePtr = Tcl_NewStringObj(\n\t\t\tTk_Name(butPtr->tkwin), TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(butPtr->selVarNamePtr);\n\t    }\n\t    namePtr = butPtr->selVarNamePtr;\n\n\t    /*\n\t     * Select the button if the associated variable has the\n\t     * appropriate value, initialize the variable if it doesn't exist,\n\t     * then set a trace on the variable to monitor future changes to\n\t     * its value.\n\t     */\n\n\t    valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);\n\t    butPtr->flags &= ~SELECTED;\n\t    butPtr->flags &= ~TRISTATED;\n\t    if (valuePtr != NULL) {\n\t\tconst char *value = Tcl_GetString(valuePtr);\n\t\tif (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {\n\t\t    butPtr->flags |= SELECTED;\n\t\t} else if (strcmp(value,\n\t\t\tTcl_GetString(butPtr->tristateValuePtr)) == 0) {\n\t\t    butPtr->flags |= TRISTATED;\n\n\t\t    /*\n\t\t     * For checkbuttons if the tristate value is the\n\t\t     * same as the offvalue then prefer off to tristate\n\t\t     */\n\n\t\t    if (butPtr->offValuePtr\n\t\t\t&& strcmp(value,\n\t\t\t    Tcl_GetString(butPtr->offValuePtr)) == 0) {\n\t\t\tbutPtr->flags &= ~TRISTATED;\n\t\t    }\n\t\t}\n\t    } else {\n\t\tif (Tcl_ObjSetVar2(interp, namePtr, NULL,\n\t\t\t(butPtr->type == TYPE_CHECK_BUTTON)\n\t\t\t? butPtr->offValuePtr : Tcl_NewObj(),\n\t\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t\t== NULL) {\n\t\t    continue;\n\t\t}\n\n\t\t/*\n\t\t * If a radiobutton has the empty string as value it should be\n\t\t * selected.\n\t\t */\n\n\t\tif ((butPtr->type == TYPE_RADIO_BUTTON) &&\n\t\t\t(TkObjIsEmpty(butPtr->onValuePtr))) {\n\t\t    butPtr->flags |= SELECTED;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Get the images for the widget, if there are any. Allocate the new\n\t * images before freeing the old ones, so that the reference counts\n\t * don't go to zero and cause image data to be discarded.\n\t */\n\n\tif (butPtr->imagePtr != NULL) {\n\t    image = Tk_GetImage(butPtr->interp, butPtr->tkwin,\n\t\t    Tcl_GetString(butPtr->imagePtr), ButtonImageProc,\n\t\t    butPtr);\n\t    if (image == NULL) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    image = NULL;\n\t}\n\tif (butPtr->image != NULL) {\n\t    Tk_FreeImage(butPtr->image);\n\t}\n\tbutPtr->image = image;\n\tif (butPtr->selectImagePtr != NULL) {\n\t    image = Tk_GetImage(butPtr->interp, butPtr->tkwin,\n\t\t    Tcl_GetString(butPtr->selectImagePtr),\n\t\t    ButtonSelectImageProc, butPtr);\n\t    if (image == NULL) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    image = NULL;\n\t}\n\tif (butPtr->selectImage != NULL) {\n\t    Tk_FreeImage(butPtr->selectImage);\n\t}\n\tbutPtr->selectImage = image;\n\tif (butPtr->tristateImagePtr != NULL) {\n\t    image = Tk_GetImage(butPtr->interp, butPtr->tkwin,\n\t\t    Tcl_GetString(butPtr->tristateImagePtr),\n\t\t    ButtonTristateImageProc, butPtr);\n\t    if (image == NULL) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    image = NULL;\n\t}\n\tif (butPtr->tristateImage != NULL) {\n\t    Tk_FreeImage(butPtr->tristateImage);\n\t}\n\tbutPtr->tristateImage = image;\n\n\thaveImage = 0;\n\tif (butPtr->imagePtr != NULL || butPtr->bitmap != None) {\n\t    haveImage = 1;\n\t}\n\tif ((!haveImage || butPtr->compound != COMPOUND_NONE)\n\t\t&& (butPtr->textVarNamePtr != NULL)) {\n\t    /*\n\t     * The button must display the value of a variable: set up a trace\n\t     * on the variable's value, create the variable if it doesn't\n\t     * exist, and fetch its current value.\n\t     */\n\n\t    Tcl_Obj *valuePtr, *namePtr;\n\n\t    namePtr = butPtr->textVarNamePtr;\n\t    valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);\n\t    if (valuePtr == NULL) {\n\t\tif (Tcl_ObjSetVar2(interp, namePtr, NULL, butPtr->textPtr,\n\t\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t\t== NULL) {\n\t\t    continue;\n\t\t}\n\t    } else {\n\t\tif (butPtr->textPtr != NULL) {\n\t\t    Tcl_DecrRefCount(butPtr->textPtr);\n\t\t}\n\t\tbutPtr->textPtr = valuePtr;\n\t\tTcl_IncrRefCount(butPtr->textPtr);\n\t    }\n\t}\n\n\tif ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {\n\t    /*\n\t     * The button must display the contents of an image or bitmap.\n\t     */\n\n\t    if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthObj,\n\t\t    &width) != TCL_OK) {\n\t    widthError:\n\t\tTcl_AddErrorInfo(interp, \"\\n    (processing \\\"-width\\\" option)\");\n\t\tcontinue;\n\t    }\n\t    if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightObj,\n\t\t    &height) != TCL_OK) {\n\t    heightError:\n\t\tTcl_AddErrorInfo(interp, \"\\n    (processing \\\"-height\\\" option)\");\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * The button displays an ordinary text string.\n\t     */\n\n\t    if (Tcl_GetIntFromObj(interp, butPtr->widthObj, &width)\n\t\t    != TCL_OK) {\n\t\tgoto widthError;\n\t    }\n\t    if (Tcl_GetIntFromObj(interp, butPtr->heightObj, &height)\n\t\t    != TCL_OK) {\n\t\tgoto heightError;\n\t    }\n\t}\n\tif (width < 0) {\n\t    Tcl_DecrRefCount(butPtr->widthObj);\n\t    butPtr->widthObj = Tcl_NewIntObj(0);\n\t    Tcl_IncrRefCount(butPtr->widthObj);\n\t}\n\tif (height < 0) {\n\t    Tcl_DecrRefCount(butPtr->heightObj);\n\t    butPtr->heightObj = Tcl_NewIntObj(0);\n\t    Tcl_IncrRefCount(butPtr->heightObj);\n\t}\n\tbreak;\n    }\n    if (!error) {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n\n    /*\n     * Reestablish the variable traces, if they're needed.\n     */\n\n    if (butPtr->textVarNamePtr != NULL) {\n\tTcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonTextVarProc, butPtr);\n    }\n    if (butPtr->selVarNamePtr != NULL) {\n\tTcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tButtonVarProc, butPtr);\n    }\n\n    TkButtonWorldChanged(butPtr);\n    if (error) {\n\tTcl_SetObjResult(interp, errorResult);\n\tTcl_DecrRefCount(errorResult);\n\treturn TCL_ERROR;\n    } else {\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkButtonWorldChanged --\n *\n *      This function is called when the world has changed in some way and the\n *      widget needs to recompute all its graphics contexts and determine its\n *      new geometry.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      Button will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkButtonWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC newGC;\n    unsigned long mask;\n    TkButton *butPtr = (TkButton *)instanceData;\n\n    /*\n     * Recompute GCs.\n     */\n\n    gcValues.font = Tk_FontId(butPtr->tkfont);\n    gcValues.foreground = butPtr->normalFg->pixel;\n    gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;\n\n    /*\n     * Note: GraphicsExpose events are disabled in normalTextGC because it's\n     * used to copy stuff from an off-screen pixmap onto the screen (we know\n     * that there's no problem with obscured areas).\n     */\n\n    gcValues.graphics_exposures = False;\n    mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;\n    newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);\n    if (butPtr->normalTextGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->normalTextGC);\n    }\n    butPtr->normalTextGC = newGC;\n\n    if (butPtr->activeFg != NULL) {\n\tgcValues.foreground = butPtr->activeFg->pixel;\n\tgcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;\n\tmask = GCForeground | GCBackground | GCFont;\n\tnewGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);\n\tif (butPtr->activeTextGC != NULL) {\n\t    Tk_FreeGC(butPtr->display, butPtr->activeTextGC);\n\t}\n\tbutPtr->activeTextGC = newGC;\n    }\n\n    gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;\n\n    /*\n     * Create the GC that can be used for stippling\n     */\n\n    if (butPtr->stippleGC == NULL) {\n\tgcValues.foreground = gcValues.background;\n\tmask = GCForeground;\n\tif (butPtr->gray == None) {\n\t    butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, \"gray50\");\n\t}\n\tif (butPtr->gray != None) {\n\t    gcValues.fill_style = FillStippled;\n\t    gcValues.stipple = butPtr->gray;\n\t    mask |= GCFillStyle | GCStipple;\n\t}\n\tbutPtr->stippleGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);\n    }\n\n    /*\n     * Allocate the disabled graphics context, for drawing text in its\n     * disabled state.\n     */\n\n    mask = GCForeground | GCBackground | GCFont;\n    if (butPtr->disabledFg != NULL) {\n\tgcValues.foreground = butPtr->disabledFg->pixel;\n    } else {\n\tgcValues.foreground = gcValues.background;\n    }\n    newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);\n    if (butPtr->disabledGC != NULL) {\n\tTk_FreeGC(butPtr->display, butPtr->disabledGC);\n    }\n    butPtr->disabledGC = newGC;\n\n    if (butPtr->copyGC == NULL) {\n\tbutPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);\n    }\n\n    TkpComputeButtonGeometry(butPtr);\n\n    /*\n     * Lastly, arrange for the button to be redisplayed.\n     */\n\n    if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tbuttons.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nButtonEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n    int highlightWidth;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tgoto redraw;\n    } else if (eventPtr->type == ConfigureNotify) {\n\t/*\n\t * Must redraw after size changes, since layout could have changed and\n\t * borders will need to be redrawn.\n\t */\n\n\tgoto redraw;\n    } else if (eventPtr->type == DestroyNotify) {\n\tDestroyButton(butPtr);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    butPtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    butPtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    }\n    return;\n\n  redraw:\n    if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ButtonCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nButtonCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted or because the command was deleted,\n     * and then this function destroys the widget. The BUTTON_DELETED flag\n     * distinguishes these cases.\n     */\n\n    if (!(butPtr->flags & BUTTON_DELETED)) {\n\tTk_DestroyWindow(butPtr->tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkInvokeButton --\n *\n *\tThis function is called to carry out the actions associated with a\n *\tbutton, such as invoking a Tcl command or setting a variable. This\n *\tfunction is invoked, for example, when the button is invoked via the\n *\tmouse.\n *\n * Results:\n *\tA standard Tcl return value. Information is also left in the interp's\n *\tresult.\n *\n * Side effects:\n *\tDepends on the button and its associated command.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkInvokeButton(\n    TkButton *butPtr)\t\t/* Information about button. */\n{\n    Tcl_Obj *namePtr = butPtr->selVarNamePtr;\n\n    if (butPtr->type == TYPE_CHECK_BUTTON) {\n\tif (butPtr->flags & SELECTED) {\n\t    if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,\n\t\t    butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t    == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    if (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL,\n\t\t    butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t    == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    } else if (butPtr->type == TYPE_RADIO_BUTTON) {\n\tif (Tcl_ObjSetVar2(butPtr->interp, namePtr, NULL, butPtr->onValuePtr,\n\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t== NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {\n\treturn Tcl_EvalObjEx(butPtr->interp, butPtr->commandPtr,\n\t\tTCL_EVAL_GLOBAL);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonVarProc --\n *\n *\tThis function is invoked when someone changes the state variable\n *\tassociated with a radio button. Depending on the new value of the\n *\tbutton's variable, the button may be selected or deselected.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe button may become selected or deselected.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nButtonVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t/* Name of variable. */\n    TCL_UNUSED(const char *),\t/* Second part of variable name. */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n    const char *value;\n    Tcl_Obj *valuePtr;\n\n    /*\n     * If the variable is being unset, then just re-establish the trace unless\n     * the whole interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tbutPtr->flags &= ~(SELECTED | TRISTATED);\n\tif (!Tcl_InterpDeleted(interp)) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(butPtr->selVarNamePtr),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tButtonVarProc, probe);\n\t\tif (probe == (void *)butPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * selVarNamePtr, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\tgoto redisplay;\n\t    }\n\t    Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    ButtonVarProc, clientData);\n\t}\n\tgoto redisplay;\n    }\n\n    /*\n     * Use the value of the variable to update the selected status of the\n     * button.\n     */\n\n    valuePtr = Tcl_ObjGetVar2(interp, butPtr->selVarNamePtr, NULL,\n\t    TCL_GLOBAL_ONLY);\n    if (valuePtr == NULL) {\n\tvalue = Tcl_GetString(butPtr->tristateValuePtr);\n    } else {\n\tvalue = Tcl_GetString(valuePtr);\n    }\n    if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {\n\tif (butPtr->flags & SELECTED) {\n\t    return NULL;\n\t}\n\tbutPtr->flags |= SELECTED;\n\tbutPtr->flags &= ~TRISTATED;\n    } else if (butPtr->offValuePtr\n\t&& strcmp(value, Tcl_GetString(butPtr->offValuePtr)) == 0) {\n\tif (!(butPtr->flags & (SELECTED | TRISTATED))) {\n\t    return NULL;\n\t}\n\tbutPtr->flags &= ~(SELECTED | TRISTATED);\n    } else if (strcmp(value, Tcl_GetString(butPtr->tristateValuePtr)) == 0) {\n\tif (butPtr->flags & TRISTATED) {\n\t    return NULL;\n\t}\n\tbutPtr->flags |= TRISTATED;\n\tbutPtr->flags &= ~SELECTED;\n    } else if (butPtr->flags & (SELECTED | TRISTATED)) {\n\tbutPtr->flags &= ~(SELECTED | TRISTATED);\n    } else {\n\treturn NULL;\n    }\n\n  redisplay:\n    if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)\n\t    && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonTextVarProc --\n *\n *\tThis function is invoked when someone changes the variable whose\n *\tcontents are to be displayed in a button.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe text displayed in the button will change to match the variable.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nButtonTextVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t\t/* name1 */\n    TCL_UNUSED(const char *),\t\t/* name2 */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n    Tcl_Obj *valuePtr;\n\n    if (butPtr->flags & BUTTON_DELETED) {\n\treturn NULL;\n    }\n\n    /*\n     * If the variable is unset, then immediately recreate it unless the whole\n     * interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tif (!Tcl_InterpDeleted(interp) && butPtr->textVarNamePtr != NULL) {\n\n\t    /*\n\t     * An unset trace on some variable brought us here, but is it\n\t     * the variable we have stored in butPtr->textVarNamePtr ?\n\t     */\n\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(butPtr->textVarNamePtr),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tButtonTextVarProc, probe);\n\t\tif (probe == (void *)butPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * textVarNamePtr, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former textvariable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\n\t    Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL,\n\t\t    butPtr->textPtr, TCL_GLOBAL_ONLY);\n\t    Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    ButtonTextVarProc, clientData);\n\t}\n\treturn NULL;\n    }\n\n    valuePtr = Tcl_ObjGetVar2(interp, butPtr->textVarNamePtr, NULL,\n\t    TCL_GLOBAL_ONLY);\n    if (valuePtr == NULL) {\n\tvaluePtr = Tcl_NewObj();\n    }\n    Tcl_DecrRefCount(butPtr->textPtr);\n    butPtr->textPtr = valuePtr;\n    Tcl_IncrRefCount(butPtr->textPtr);\n    TkpComputeButtonGeometry(butPtr);\n\n    if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)\n\t    && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ButtonImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size or contents of an image\n *\tdisplayed in a button.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the button to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nButtonImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int),\t/* x, Upper left pixel (within image) that must */\n    TCL_UNUSED(int),\t/* y, be redisplayed. */\n    TCL_UNUSED(int),\t/* width, Dimensions of area to redisplay (might be */\n    TCL_UNUSED(int),\t/* height, <= 0). */\n    TCL_UNUSED(int),\t/* imgWidth, New dimensions of image. */\n    TCL_UNUSED(int))\t/* imgHeight */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n\n    if (butPtr->tkwin != NULL) {\n\tTkpComputeButtonGeometry(butPtr);\n\tif (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\t    butPtr->flags |= REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ButtonSelectImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size or contents of the image\n *\tdisplayed in a button when it is selected.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay arrange for the button to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nButtonSelectImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int),\t/* x, Upper left pixel (within image) that must */\n    TCL_UNUSED(int),\t/* y, be redisplayed. */\n    TCL_UNUSED(int),\t/* width, Dimensions of area to redisplay (might be */\n    TCL_UNUSED(int),\t/* height, <= 0). */\n    TCL_UNUSED(int),\t/* imgWidth, New dimensions of image. */\n    TCL_UNUSED(int))\t/* imgHeight */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n\n#ifdef MAC_OSX_TK\n    if (butPtr->tkwin != NULL) {\n\tTkpComputeButtonGeometry(butPtr);\n    }\n#else\n    /*\n     * Don't recompute geometry: it's controlled by the primary image.\n     */\n#endif\n\n    if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL)\n\t    && Tk_IsMapped(butPtr->tkwin)\n\t    && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ButtonTristateImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size or contents of the image\n *\tdisplayed in a button when it is selected.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay arrange for the button to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nButtonTristateImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int),\t/* x, Upper left pixel (within image) that must */\n    TCL_UNUSED(int),\t/* y, be redisplayed. */\n    TCL_UNUSED(int),\t/* width, Dimensions of area to redisplay (might be */\n    TCL_UNUSED(int),\t/* height, <= 0). */\n    TCL_UNUSED(int),\t/* imgWidth, New dimensions of image. */\n    TCL_UNUSED(int))\t/* imgHeight */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n\n#ifdef MAC_OSX_TK\n    if (butPtr->tkwin != NULL) {\n\tTkpComputeButtonGeometry(butPtr);\n    }\n#else\n    /*\n     * Don't recompute geometry: it's controlled by the primary image.\n     */\n#endif\n\n    if ((butPtr->flags & TRISTATED) && (butPtr->tkwin != NULL)\n\t    && Tk_IsMapped(butPtr->tkwin)\n\t    && !(butPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayButton, butPtr);\n\tbutPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkButton.h",
    "content": "/*\n * tkButton.h --\n *\n *\tDeclarations of types and functions used to implement button-like\n *\twidgets.\n *\n * Copyright © 1996-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKBUTTON\n#define _TKBUTTON\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Legal values for the \"compound\" field of TkButton records.\n */\n\nenum compound {\n    COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE,\n\tCOMPOUND_RIGHT, COMPOUND_TOP\n};\n\n/*\n * Legal values for the \"state\" field of TkButton records.\n */\n\nenum state {\n    STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL\n};\n\n/*\n * Legal values for the \"defaultState\" field of TkButton records.\n */\n\nenum defaultState {\n    DEFAULT_ACTIVE, DEFAULT_DISABLED, DEFAULT_NORMAL\n};\n\n/*\n * A data structure of the following type is kept for each widget managed by\n * this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the button. NULL means\n\t\t\t\t * that the window has been destroyed. */\n    Display *display;\t\t/* Display containing widget. Needed to free\n\t\t\t\t * up resources after tkwin is gone. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with button. */\n    Tcl_Command widgetCmd;\t/* Token for button's widget command. */\n    int type;\t\t\t/* Type of widget, such as TYPE_LABEL:\n\t\t\t\t * restricts operations that may be performed\n\t\t\t\t * on widget. See below for legal values. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n\n    /*\n     * Information about what's in the button.\n     */\n\n    Tcl_Obj *textPtr;\t\t/* Value of -text option: specifies text to\n\t\t\t\t * display in button. */\n    int underline;\t\t/* Value of -underline option: specifies index\n\t\t\t\t * of character to underline. INT_MIN means don't\n\t\t\t\t * underline anything. */\n    Tcl_Obj *textVarNamePtr;\t/* Value of -textvariable option: specifies\n\t\t\t\t * name of variable or NULL. If non-NULL,\n\t\t\t\t * button displays the contents of this\n\t\t\t\t * variable. */\n    Pixmap bitmap;\t\t/* Value of -bitmap option. If not None,\n\t\t\t\t * specifies bitmap to display and text and\n\t\t\t\t * textVar are ignored. */\n    Tcl_Obj *imagePtr;\t\t/* Value of -image option: specifies image to\n\t\t\t\t * display in window, or NULL if none. If\n\t\t\t\t * non-NULL, bitmap, text, and textVarName are\n\t\t\t\t * ignored.*/\n    Tk_Image image;\t\t/* Derived from imagePtr by calling\n\t\t\t\t * Tk_GetImage, or NULL if imagePtr is\n\t\t\t\t * NULL. */\n    Tcl_Obj *selectImagePtr;\t/* Value of -selectimage option: specifies\n\t\t\t\t * image to display in window when selected,\n\t\t\t\t * or NULL if none. Ignored if imagePtr is\n\t\t\t\t * NULL. */\n    Tk_Image selectImage;\t/* Derived from selectImagePtr by calling\n\t\t\t\t * Tk_GetImage, or NULL if selectImagePtr is\n\t\t\t\t * NULL. */\n    Tcl_Obj *tristateImagePtr;\t/* Value of -tristateimage option: specifies\n\t\t\t\t * image to display in window when selected,\n\t\t\t\t * or NULL if none. Ignored if imagePtr is\n\t\t\t\t * NULL. */\n    Tk_Image tristateImage;\t/* Derived from tristateImagePtr by calling\n\t\t\t\t * Tk_GetImage, or NULL if tristateImagePtr is\n\t\t\t\t * NULL. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    enum state state;\t\t/* Value of -state option: specifies state of\n\t\t\t\t * button for display purposes.*/\n    Tk_3DBorder normalBorder;\t/* Value of -background option: specifies\n\t\t\t\t * color for background (and border) when\n\t\t\t\t * window isn't active. */\n    Tk_3DBorder activeBorder;\t/* Value of -activebackground option: this is\n\t\t\t\t * the color used to draw 3-D border and\n\t\t\t\t * background when widget is active. */\n    Tcl_Obj *borderWidthObj;\t/* Value of -borderWidth option: specifies\n\t\t\t\t * width of border in pixels. Always >= 0. */\n    int relief;\t\t\t/* Value of -relief option: specifies 3-d\n\t\t\t\t * effect for border, such as\n\t\t\t\t * TK_RELIEF_RAISED. */\n    int overRelief;\t\t/* Value of -overrelief option: specifies a\n\t\t\t\t * 3-d effect for the border, such as\n\t\t\t\t * TK_RELIEF_RAISED, to be used when the mouse\n\t\t\t\t * is over the button. */\n    int offRelief;\t\t/* Value of -offrelief option: specifies a 3-d\n\t\t\t\t * effect for the border, such as\n\t\t\t\t * TK_RELIEF_RAISED, to be used when a\n\t\t\t\t * checkbutton or radiobutton without\n\t\t\t\t * indicator is off. */\n    Tcl_Obj *highlightWidthObj;\t/* Value of -highlightthickness option:\n\t\t\t\t * specifies width in pixels of highlight to\n\t\t\t\t * draw around widget when it has the focus.\n\t\t\t\t * 0 means don't draw a highlight. Always >= 0. */\n    Tk_3DBorder highlightBorder;/* Value of -highlightbackground option:\n\t\t\t\t * specifies background with which to draw 3-D\n\t\t\t\t * default ring and focus highlight area when\n\t\t\t\t * highlight is off. */\n    XColor *highlightColorPtr;\t/* Value of -highlightcolor option: specifies\n\t\t\t\t * color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    Tk_Font tkfont;\t\t/* Value of -font option: specifies font to\n\t\t\t\t * use for display text. */\n    XColor *normalFg;\t\t/* Value of -font option: specifies foreground\n\t\t\t\t * color in normal mode. */\n    XColor *activeFg;\t\t/* Value of -activeforeground option:\n\t\t\t\t * foreground color in active mode. NULL means\n\t\t\t\t * use -foreground instead. */\n    XColor *disabledFg;\t\t/* Value of -disabledforeground option:\n\t\t\t\t * foreground color when disabled. NULL means\n\t\t\t\t * use normalFg with a 50% stipple instead. */\n    GC normalTextGC;\t\t/* GC for drawing text in normal mode. Also\n\t\t\t\t * used to copy from off-screen pixmap onto\n\t\t\t\t * screen. */\n    GC activeTextGC;\t\t/* GC for drawing text in active mode (NULL\n\t\t\t\t * means use normalTextGC). */\n    GC disabledGC;\t\t/* Used to produce disabled effect for text\n\t\t\t\t * and check/radio marks. */\n    GC stippleGC;\t\t/* Used to produce disabled stipple effect for\n\t\t\t\t * images when disabled. */\n    Pixmap gray;\t\t/* Pixmap for displaying disabled text if\n\t\t\t\t * disabledFg is NULL. */\n    GC copyGC;\t\t\t/* Used for copying information from an\n\t\t\t\t * off-screen pixmap to the screen. */\n    Tcl_Obj *widthObj;\t\t/* Value of -width option. */\n    Tcl_Obj *heightObj;\t\t/* Value of -height option. */\n    Tcl_Obj *wrapLengthObj;\t/* Value of -wraplength option: specifies line\n\t\t\t\t * length (in pixels) at which to wrap onto\n\t\t\t\t * next line. <= 0 means don't wrap except at\n\t\t\t\t * newlines. */\n    Tcl_Obj *padXObj;\t\t/* Value of -padx option: specifies how many\n\t\t\t\t * pixels of extra space to leave on left and\n\t\t\t\t * right of text. Ignored for bitmaps and\n\t\t\t\t * images. */\n    Tcl_Obj *padYObj;\t\t/* Value of -padx option: specifies how many\n\t\t\t\t * pixels of extra space to leave above and\n\t\t\t\t * below text. Ignored for bitmaps and\n\t\t\t\t * images. */\n    Tk_Anchor anchor;\t\t/* Value of -anchor option: specifies where\n\t\t\t\t * text/bitmap should be displayed inside\n\t\t\t\t * button region. */\n    Tk_Justify justify;\t\t/* Value of -justify option: specifies how to\n\t\t\t\t * align lines of multi-line text. */\n    bool indicatorOn;\t\t/* Value of -indicatoron option: true means draw\n\t\t\t\t * indicator in checkbuttons and radiobuttons,\n\t\t\t\t * false means don't draw it. */\n    Tk_3DBorder selectBorder;\t/* Value of -selectcolor option: specifies\n\t\t\t\t * color for drawing indicator background, or\n\t\t\t\t * perhaps widget background, when\n\t\t\t\t * selected. */\n    int textWidth;\t\t/* Width needed to display text as requested,\n\t\t\t\t * in pixels. */\n    int textHeight;\t\t/* Height needed to display text as requested,\n\t\t\t\t * in pixels. */\n    Tk_TextLayout textLayout;\t/* Saved text layout information. */\n    int indicatorSpace;\t\t/* Horizontal space (in pixels) allocated for\n\t\t\t\t * display of indicator. */\n    int indicatorDiameter;\t/* Diameter of indicator, in pixels. */\n    enum defaultState defaultState;\n\t\t\t\t/* Value of -default option, such as\n\t\t\t\t * DEFAULT_NORMAL: specifies state of default\n\t\t\t\t * ring for buttons (normal, active, or\n\t\t\t\t * disabled). NULL for other classes. */\n\n    /*\n     * For check and radio buttons, the fields below are used to manage the\n     * variable indicating the button's state.\n     */\n\n    Tcl_Obj *selVarNamePtr;\t/* Value of -variable option: specifies name\n\t\t\t\t * of variable used to control selected state\n\t\t\t\t * of button. */\n    Tcl_Obj *onValuePtr;\t/* Value of -offvalue option: specifies value\n\t\t\t\t * to store in variable when this button is\n\t\t\t\t * selected. */\n    Tcl_Obj *offValuePtr;\t/* Value of -offvalue option: specifies value\n\t\t\t\t * to store in variable when this button isn't\n\t\t\t\t * selected. Used only by checkbuttons. */\n    Tcl_Obj *tristateValuePtr;\t/* Value of -tristatevalue option: specifies\n\t\t\t\t * value to display Tristate or Multivalue\n\t\t\t\t * mode when variable matches this value.\n\t\t\t\t * Used by check- buttons. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    Tk_Cursor cursor;\t\t/* Value of -cursor option: if not NULL,\n\t\t\t\t * specifies current cursor for window. */\n    Tcl_Obj *takeFocusPtr;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. */\n    Tcl_Obj *commandPtr;\t/* Value of -command option: specifies script\n\t\t\t\t * to execute when button is invoked. If\n\t\t\t\t * widget is label or has no command, this is\n\t\t\t\t * NULL. */\n    int compound;\t\t/* Value of -compound option; specifies\n\t\t\t\t * whether the button should show both an\n\t\t\t\t * image and text, and, if so, how. */\n    int repeatDelay;\t\t/* Value of -repeatdelay option; specifies the\n\t\t\t\t * number of ms after which the button will\n\t\t\t\t * start to auto-repeat its command. */\n    int repeatInterval;\t\t/* Value of -repeatinterval option; specifies\n\t\t\t\t * the number of ms between auto-repeat\n\t\t\t\t * invocataions of the button command. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n} TkButton;\n\n/*\n * Possible \"type\" values for buttons. These are the kinds of widgets\n * supported by this file. The ordering of the type numbers is significant:\n * greater means more features and is used in the code.\n */\n\n#define TYPE_LABEL\t\t0\n#define TYPE_BUTTON\t\t1\n#define TYPE_CHECK_BUTTON\t2\n#define TYPE_RADIO_BUTTON\t3\n\n/*\n * Flag bits for buttons:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * SELECTED:\t\t\tNon-zero means this button is selected, so\n *\t\t\t\tspecial highlight should be drawn.\n * GOT_FOCUS:\t\t\tNon-zero means this button currently has the\n *\t\t\t\tinput focus.\n * BUTTON_DELETED:\t\tNon-zero needs that this button has been\n *\t\t\t\tdeleted, or is in the process of being deleted\n */\n\n#define REDRAW_PENDING\t\t(1 << 0)\n#define SELECTED\t\t(1 << 1)\n#define GOT_FOCUS\t\t(1 << 2)\n#define BUTTON_DELETED\t\t(1 << 3)\n#define TRISTATED\t\t(1 << 4)\n\n/*\n * Declaration of button class functions structure\n * and button/label defaults, for use in optionSpecs.\n */\n\nMODULE_SCOPE const Tk_ClassProcs tkpButtonProcs;\nMODULE_SCOPE char tkDefButtonHighlightWidth[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefButtonPadx[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefButtonPady[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefButtonBorderWidth[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefLabelHighlightWidth[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefLabelPadx[TCL_INTEGER_SPACE];\nMODULE_SCOPE char tkDefLabelPady[TCL_INTEGER_SPACE];\n\n/*\n * Declaration of functions used in the implementation of the button widget.\n */\n\n#ifndef TkpButtonSetDefaults\nMODULE_SCOPE void\tTkpButtonSetDefaults(void);\n#endif\nMODULE_SCOPE void\tTkButtonWorldChanged(void *instanceData);\nMODULE_SCOPE void\tTkpComputeButtonGeometry(TkButton *butPtr);\nMODULE_SCOPE TkButton\t*TkpCreateButton(Tk_Window tkwin);\n#ifndef TkpDestroyButton\nMODULE_SCOPE void\tTkpDestroyButton(TkButton *butPtr);\n#endif\n#ifndef TkpDisplayButton\nMODULE_SCOPE void\tTkpDisplayButton(void *clientData);\n#endif\nMODULE_SCOPE int\tTkInvokeButton(TkButton *butPtr);\n\n#endif /* _TKBUTTON */\n"
  },
  {
    "path": "generic/tkCanvArc.c",
    "content": "/*\n * tkCanvArc.c --\n *\n *\tThis file implements arc items for canvas widgets.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n#include \"float.h\"\n\n/*\n * The structure below defines the record for each arc item.\n */\n\ntypedef enum {\n    PIESLICE_STYLE, CHORD_STYLE, ARC_STYLE\n} Style;\n\ntypedef struct ArcItem {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_Outline outline;\t\t/* Outline structure */\n    double bbox[4];\t\t/* Coordinates (x1, y1, x2, y2) of bounding\n\t\t\t\t * box for oval of which arc is a piece. */\n    double start;\t\t/* Angle at which arc begins, in degrees\n\t\t\t\t * between 0 and 360. */\n    double extent;\t\t/* Extent of arc (angular distance from start\n\t\t\t\t * to end of arc) in degrees between -360 and\n\t\t\t\t * 360. */\n    double *outlinePtr;\t\t/* Points to (x,y) coordinates for points that\n\t\t\t\t * define one or two closed polygons\n\t\t\t\t * representing the portion of the outline\n\t\t\t\t * that isn't part of the arc (the V-shape for\n\t\t\t\t * a pie slice or a line-like segment for a\n\t\t\t\t * chord). Malloc'ed. */\n    int numOutlinePoints;\t/* Number of points at outlinePtr. Zero means\n\t\t\t\t * no space allocated. */\n    Tk_TSOffset tsoffset;\n    XColor *fillColor;\t\t/* Color for filling arc (used for drawing\n\t\t\t\t * outline too when style is \"arc\"). NULL\n\t\t\t\t * means don't fill arc. */\n    XColor *activeFillColor;\t/* Color for filling arc (used for drawing\n\t\t\t\t * outline too when style is \"arc\" and state\n\t\t\t\t * is \"active\"). NULL means use fillColor. */\n    XColor *disabledFillColor;\t/* Color for filling arc (used for drawing\n\t\t\t\t * outline too when style is \"arc\" and state\n\t\t\t\t * is \"disabled\". NULL means use fillColor */\n    Pixmap fillStipple;\t\t/* Stipple bitmap for filling item. */\n    Pixmap activeFillStipple;\t/* Stipple bitmap for filling item if state is\n\t\t\t\t * active. */\n    Pixmap disabledFillStipple;\t/* Stipple bitmap for filling item if state is\n\t\t\t\t * disabled. */\n    Style style;\t\t/* How to draw arc: arc, chord, or\n\t\t\t\t * pieslice. */\n    GC fillGC;\t\t\t/* Graphics context for filling item. */\n    double center1[2];\t\t/* Coordinates of center of arc outline at\n\t\t\t\t * start (see ComputeArcOutline). */\n    double center2[2];\t\t/* Coordinates of center of arc outline at\n\t\t\t\t * start+extent (see ComputeArcOutline). */\n    double height;              /* Distance from the arc's chord to its\n\t\t\t\t * mid-point. */\n    double startPoint[2];       /* Start point of arc used when specifying\n\t\t\t\t * height. */\n    double endPoint[2];         /* End point of arc used when specifying\n\t\t\t\t * height. */\n} ArcItem;\n\n/*\n * The definitions below define the sizes of the polygons used to display\n * outline information for various styles of arcs:\n */\n\n#define CHORD_OUTLINE_PTS\t7\n#define PIE_OUTLINE1_PTS\t6\n#define PIE_OUTLINE2_PTS\t7\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic int\tStyleParseProc(void *clientData, Tcl_Interp *interp,\n\t\t    Tk_Window tkwin, const char *value,\n\t\t    char *widgRec, Tcl_Size offset);\nstatic const char * StylePrintProc(void *clientData, Tk_Window tkwin,\n\t\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr);\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption styleOption = {\n    StyleParseProc, StylePrintProc, NULL\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\nstatic const Tk_CustomOption dashOption = {\n    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL\n};\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)\n};\nstatic const Tk_CustomOption pixelOption = {\n    TkPixelParseProc, TkPixelPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_CUSTOM, \"-activedash\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.activeDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-activefill\", NULL, NULL,\n\tNULL, offsetof(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-activeoutline\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activeoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activestipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-activewidth\", NULL, NULL,\n\t\"0.0\", offsetof(ArcItem, outline.activeWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_CUSTOM, \"-dash\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.dash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_PIXELS, \"-dashoffset\", NULL, NULL,\n\t\"0\", offsetof(ArcItem, outline.offsetObj), TK_CONFIG_OBJS|TK_OPTION_NEG_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disableddash\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.disabledDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-disabledfill\", NULL, NULL,\n\tNULL, offsetof(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-disabledoutline\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledstipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disabledwidth\", NULL, NULL,\n\t\"0.0\", offsetof(ArcItem, outline.disabledWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_DOUBLE, \"-extent\", NULL, NULL,\n\t\"90\", offsetof(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_COLOR, \"-fill\", NULL, NULL,\n\tNULL, offsetof(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_DOUBLE, \"-height\", NULL, NULL,\n\t0, offsetof(ArcItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", NULL, NULL,\n\t\"0,0\", offsetof(ArcItem, tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_COLOR, \"-outline\", NULL, NULL,\n\tDEF_CANVITEM_OUTLINE, offsetof(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-outlineoffset\", NULL, NULL,\n\t\"0,0\", offsetof(ArcItem, outline.tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_BITMAP, \"-outlinestipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_DOUBLE, \"-start\", NULL, NULL,\n\t\"0\", offsetof(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_BITMAP, \"-stipple\", NULL, NULL,\n\tNULL, offsetof(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-style\", NULL, NULL,\n\tNULL, offsetof(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT,\n\t&styleOption},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_CUSTOM, \"-width\", NULL, NULL,\n\t\"1.0\", offsetof(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT,\n\t&pixelOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tComputeArcBbox(Tk_Canvas canvas, ArcItem *arcPtr);\nstatic int\t\tConfigureArc(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic void\t\tComputeArcParametersFromHeight(ArcItem *arcPtr);\nstatic int\t\tCreateArc(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteArc(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayArc(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic int\t\tArcCoords(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tArcToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tArcToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *coordPtr);\nstatic int\t\tArcToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic void\t\tScaleArc(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateArc(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\nstatic int\t\tAngleInRange(double x, double y,\n\t\t\t    double start, double extent);\nstatic void\t\tComputeArcOutline(Tk_Canvas canvas, ArcItem *arcPtr);\nstatic int\t\tHorizLineToArc(double x1, double x2,\n\t\t\t    double y, double rx, double ry,\n\t\t\t    double start, double extent);\nstatic int\t\tVertLineToArc(double x, double y1,\n\t\t\t    double y2, double rx, double ry,\n\t\t\t    double start, double extent);\nstatic void\t\tRotateArc(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\n\n/*\n * The structures below defines the arc item types by means of functions that\n * can be invoked by generic item code.\n */\n\nTk_ItemType tkArcType = {\n    \"arc\",\t\t\t/* name */\n    sizeof(ArcItem),\t\t/* itemSize */\n    CreateArc,\t\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureArc,\t\t/* configureProc */\n    ArcCoords,\t\t\t/* coordProc */\n    DeleteArc,\t\t\t/* deleteProc */\n    DisplayArc,\t\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    ArcToPoint,\t\t\t/* pointProc */\n    ArcToArea,\t\t\t/* areaProc */\n    ArcToPostscript,\t\t/* postscriptProc */\n    ScaleArc,\t\t\t/* scaleProc */\n    TranslateArc,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* icursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateArc,\t\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateArc --\n *\n *\tThis function is invoked to create a new arc item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new arc item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateArc(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing arc. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Carry out initialization that is needed in order to clean up after\n     * errors during the the remainder of this function.\n     */\n\n    Tk_CreateOutline(&(arcPtr->outline));\n    arcPtr->start = 0;\n    arcPtr->extent = 90;\n    arcPtr->outlinePtr = NULL;\n    arcPtr->numOutlinePoints = 0;\n    arcPtr->tsoffset.flags = 0;\n    arcPtr->tsoffset.xoffset = 0;\n    arcPtr->tsoffset.yoffset = 0;\n    arcPtr->fillColor = NULL;\n    arcPtr->activeFillColor = NULL;\n    arcPtr->disabledFillColor = NULL;\n    arcPtr->fillStipple = None;\n    arcPtr->activeFillStipple = None;\n    arcPtr->disabledFillStipple = None;\n    arcPtr->style = PIESLICE_STYLE;\n    arcPtr->fillGC = NULL;\n    arcPtr->height = 0;\n\n    /*\n     * Process the arguments to fill in the item record.\n     */\n\n    for (i = 1; i < objc; i++) {\n\tconst char *arg = Tcl_GetString(objv[i]);\n\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    break;\n\t}\n    }\n    if (ArcCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {\n\tgoto error;\n    }\n    if (ConfigureArc(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArcCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\tarcs. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nArcCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n\n    if (objc == 0) {\n\tTcl_Obj *objs[4];\n\n\tobjs[0] = Tcl_NewDoubleObj(arcPtr->bbox[0]);\n\tobjs[1] = Tcl_NewDoubleObj(arcPtr->bbox[1]);\n\tobjs[2] = Tcl_NewDoubleObj(arcPtr->bbox[2]);\n\tobjs[3] = Tcl_NewDoubleObj(arcPtr->bbox[3]);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(4, objs));\n    } else if ((objc == 1) || (objc == 4)) {\n\tif (objc == 1) {\n\t    if (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t    (Tcl_Obj ***) &objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    } else if (objc != 4) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"wrong # coordinates: expected 4, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"ARC\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],\n\t\t    &arcPtr->bbox[0]) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t    &arcPtr->bbox[1]) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2],\n\t\t\t&arcPtr->bbox[2]) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3],\n\t\t\t&arcPtr->bbox[3]) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Store bbox as start and end points so they can be used if either\n\t * radius or height is specified.\n\t */\n\n\tarcPtr->startPoint[0] = arcPtr->bbox[0];\n\tarcPtr->startPoint[1] = arcPtr->bbox[1];\n\tarcPtr->endPoint[0] = arcPtr->bbox[2];\n\tarcPtr->endPoint[1] = arcPtr->bbox[3];\n\n\tComputeArcBbox(canvas, arcPtr);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 4, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"ARC\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureArc --\n *\n *\tThis function is invoked to configure various aspects of a arc item,\n *\tsuch as its outline and fill colors.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as colors and stipple patterns, may be\n *\tset for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureArc(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Arc item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC;\n    unsigned long mask;\n    int i;\n    Tk_Window tkwin;\n    Tk_TSOffset *tsoffset;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, arcPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    state = itemPtr->state;\n\n    /*\n     * A few of the options require additional processing, such as style and\n     * graphics contexts.\n     */\n\n    if (arcPtr->outline.activeWidth > arcPtr->outline.width ||\n\t    arcPtr->outline.activeDash.number != 0 ||\n\t    arcPtr->outline.activeColor != NULL ||\n\t    arcPtr->outline.activeStipple != None ||\n\t    arcPtr->activeFillColor != NULL ||\n\t    arcPtr->activeFillStipple != None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n\n    /*\n     * Override the start and extent if the height is given.\n     */\n\n    ComputeArcParametersFromHeight(arcPtr);\n\n    ComputeArcBbox(canvas, arcPtr);\n\n    i = (int) (arcPtr->start/360.0);\n    arcPtr->start -= i*360.0;\n    if (arcPtr->start < 0) {\n\tarcPtr->start += 360.0;\n    }\n    i = (int) (arcPtr->extent/360.0);\n    arcPtr->extent -= i*360.0;\n\n    tsoffset = &arcPtr->outline.tsoffset;\n    flags = tsoffset->flags;\n    if (flags & TK_OFFSET_LEFT) {\n\ttsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);\n    } else if (flags & TK_OFFSET_CENTER) {\n\ttsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);\n    } else if (flags & TK_OFFSET_RIGHT) {\n\ttsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);\n    }\n    if (flags & TK_OFFSET_TOP) {\n\ttsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);\n    } else if (flags & TK_OFFSET_MIDDLE) {\n\ttsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);\n    } else if (flags & TK_OFFSET_BOTTOM) {\n\ttsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5);\n    }\n\n    mask = (unsigned long)Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline));\n    if (mask) {\n\tgcValues.cap_style = CapButt;\n\tmask |= GCCapStyle;\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    } else {\n\tnewGC = NULL;\n    }\n    if (arcPtr->outline.gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), arcPtr->outline.gc);\n    }\n    arcPtr->outline.gc = newGC;\n\n    if(state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (state==TK_STATE_HIDDEN) {\n\tComputeArcBbox(canvas, arcPtr);\n\treturn TCL_OK;\n    }\n\n    color = arcPtr->fillColor;\n    stipple = arcPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (arcPtr->activeFillColor!=NULL) {\n\t    color = arcPtr->activeFillColor;\n\t}\n\tif (arcPtr->activeFillStipple!=None) {\n\t    stipple = arcPtr->activeFillStipple;\n\t}\n    } else if (state==TK_STATE_DISABLED) {\n\tif (arcPtr->disabledFillColor!=NULL) {\n\t    color = arcPtr->disabledFillColor;\n\t}\n\tif (arcPtr->disabledFillStipple!=None) {\n\t    stipple = arcPtr->disabledFillStipple;\n\t}\n    }\n\n    if (arcPtr->style == ARC_STYLE) {\n\tnewGC = NULL;\n    } else if (color == NULL) {\n\tnewGC = NULL;\n    } else {\n\tgcValues.foreground = color->pixel;\n\tif (arcPtr->style == CHORD_STYLE) {\n\t    gcValues.arc_mode = ArcChord;\n\t} else {\n\t    gcValues.arc_mode = ArcPieSlice;\n\t}\n\tmask = GCForeground|GCArcMode;\n\tif (stipple != None) {\n\t    gcValues.stipple = stipple;\n\t    gcValues.fill_style = FillStippled;\n\t    mask |= GCStipple|GCFillStyle;\n\t}\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    }\n    if (arcPtr->fillGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC);\n    }\n    arcPtr->fillGC = newGC;\n\n    tsoffset = &arcPtr->tsoffset;\n    flags = tsoffset->flags;\n    if (flags & TK_OFFSET_LEFT) {\n\ttsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);\n    } else if (flags & TK_OFFSET_CENTER) {\n\ttsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);\n    } else if (flags & TK_OFFSET_RIGHT) {\n\ttsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);\n    }\n    if (flags & TK_OFFSET_TOP) {\n\ttsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);\n    } else if (flags & TK_OFFSET_MIDDLE) {\n\ttsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);\n    } else if (flags & TK_OFFSET_BOTTOM) {\n\ttsoffset->yoffset = (int) (arcPtr->bbox[3] + 0.5);\n    }\n\n    ComputeArcBbox(canvas, arcPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeArcParametersFromHeight --\n *\n *\tThis function calculates the arc parameters given start-point,\n *\tend-point and height (!= 0).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe height parameter is set to 0 on exit.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeArcParametersFromHeight(\n    ArcItem* arcPtr)\n{\n    double chordLen, chordDir[2], chordCen[2], arcCen[2], d, radToDeg, radius;\n\n    /*\n     * Do nothing if no height has been specified.\n     */\n\n    if (arcPtr->height == 0)\n\treturn;\n\n    /*\n     * Calculate the chord length, return early if it is too small.\n     */\n\n    chordLen = hypot(arcPtr->endPoint[1] - arcPtr->startPoint[1],\n\t    arcPtr->startPoint[0] - arcPtr->endPoint[0]);\n\n    if (chordLen < DBL_EPSILON) {\n\tarcPtr->start = arcPtr->extent = arcPtr->height = 0;\n\treturn;\n    }\n\n    chordDir[0] = (arcPtr->endPoint[0] - arcPtr->startPoint[0]) / chordLen;\n    chordDir[1] = (arcPtr->endPoint[1] - arcPtr->startPoint[1]) / chordLen;\n    chordCen[0] = (arcPtr->startPoint[0] + arcPtr->endPoint[0]) / 2;\n    chordCen[1] = (arcPtr->startPoint[1] + arcPtr->endPoint[1]) / 2;\n\n    /*\n     * Calculate the radius (assumes height != 0).\n     */\n\n    radius = (4*pow(arcPtr->height, 2) + pow(chordLen, 2))\n\t    / (8 * arcPtr->height);\n\n    /*\n     * The arc centre.\n     */\n\n    d = radius - arcPtr->height;\n    arcCen[0] = chordCen[0] - d * chordDir[1];\n    arcCen[1] = chordCen[1] + d * chordDir[0];\n\n    /*\n     * The arc start and span. Angles are negated because the coordinate\n     * system is left-handed.\n     */\n\n    radToDeg = 45 / atan(1);\n    arcPtr->start = atan2(arcCen[1] - arcPtr->startPoint[1],\n\t    arcPtr->startPoint[0] - arcCen[0]) * radToDeg;\n    arcPtr->extent = -2 * asin(chordLen / (2 * radius)) * radToDeg;\n\n    /*\n     * Handle spans > 180.\n     */\n\n    if (fabs(2 * arcPtr->height) > chordLen) {\n\tarcPtr->extent = arcPtr->extent > 0 ? (360 - arcPtr->extent)\n\t\t: -(360 + arcPtr->extent);\n    }\n\n    /*\n     * Create the bounding box.\n     */\n\n    arcPtr->bbox[0] = arcCen[0] - radius;\n    arcPtr->bbox[1] = arcCen[1] - radius;\n    arcPtr->bbox[2] = arcCen[0] + radius;\n    arcPtr->bbox[3] = arcCen[1] + radius;\n\n    /*\n     * Set the height to 0 so that itemcget -height returns 0.\n     */\n\n    arcPtr->height = 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteArc --\n *\n *\tThis function is called to clean up the data structure associated with\n *\tan arc item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteArc(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Info about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    ArcItem *arcPtr = (ArcItem *)itemPtr;\n\n    Tk_DeleteOutline(display, &(arcPtr->outline));\n    if (arcPtr->numOutlinePoints != 0) {\n\tTcl_Free(arcPtr->outlinePtr);\n    }\n    if (arcPtr->fillColor != NULL) {\n\tTk_FreeColor(arcPtr->fillColor);\n    }\n    if (arcPtr->activeFillColor != NULL) {\n\tTk_FreeColor(arcPtr->activeFillColor);\n    }\n    if (arcPtr->disabledFillColor != NULL) {\n\tTk_FreeColor(arcPtr->disabledFillColor);\n    }\n    if (arcPtr->fillStipple != None) {\n\tTk_FreeBitmap(display, arcPtr->fillStipple);\n    }\n    if (arcPtr->activeFillStipple != None) {\n\tTk_FreeBitmap(display, arcPtr->activeFillStipple);\n    }\n    if (arcPtr->disabledFillStipple != None) {\n\tTk_FreeBitmap(display, arcPtr->disabledFillStipple);\n    }\n    if (arcPtr->fillGC != NULL) {\n\tTk_FreeGC(display, arcPtr->fillGC);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeArcBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of an arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeArcBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    ArcItem *arcPtr)\t\t/* Item whose bbox is to be recomputed. */\n{\n    double tmp, center[2], point[2];\n    double width;\n    Tk_State state = arcPtr->header.state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = arcPtr->outline.width;\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n    if (state==TK_STATE_HIDDEN) {\n\tarcPtr->header.x1 = arcPtr->header.x2 =\n\tarcPtr->header.y1 = arcPtr->header.y2 = -1;\n\treturn;\n    } else if (Canvas(canvas)->currentItemPtr == (Tk_Item *) arcPtr) {\n\tif (arcPtr->outline.activeWidth>width) {\n\t    width = arcPtr->outline.activeWidth;\n\t}\n    } else if (state==TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledWidth>0) {\n\t    width = arcPtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * Make sure that the first coordinates are the lowest ones.\n     */\n\n    if (arcPtr->bbox[1] > arcPtr->bbox[3]) {\n\ttmp = arcPtr->bbox[3];\n\n\tarcPtr->bbox[3] = arcPtr->bbox[1];\n\tarcPtr->bbox[1] = tmp;\n    }\n    if (arcPtr->bbox[0] > arcPtr->bbox[2]) {\n\ttmp = arcPtr->bbox[2];\n\n\tarcPtr->bbox[2] = arcPtr->bbox[0];\n\tarcPtr->bbox[0] = tmp;\n    }\n\n    ComputeArcOutline(canvas,arcPtr);\n\n    /*\n     * To compute the bounding box, start with the bbox formed by the two\n     * endpoints of the arc. Then add in the center of the arc's oval (if\n     * relevant) and the 3-o'clock, 6-o'clock, 9-o'clock, and 12-o'clock\n     * positions, if they are relevant.\n     */\n\n    arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0];\n    arcPtr->header.y1 = arcPtr->header.y2 = (int) arcPtr->center1[1];\n    TkIncludePoint((Tk_Item *) arcPtr, arcPtr->center2);\n    center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2;\n    center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2;\n    if (arcPtr->style == PIESLICE_STYLE) {\n\tTkIncludePoint((Tk_Item *) arcPtr, center);\n    }\n\n    tmp = -arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpoint[0] = arcPtr->bbox[2];\n\tpoint[1] = center[1];\n\tTkIncludePoint((Tk_Item *) arcPtr, point);\n    }\n    tmp = 90.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpoint[0] = center[0];\n\tpoint[1] = arcPtr->bbox[1];\n\tTkIncludePoint((Tk_Item *) arcPtr, point);\n    }\n    tmp = 180.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpoint[0] = arcPtr->bbox[0];\n\tpoint[1] = center[1];\n\tTkIncludePoint((Tk_Item *) arcPtr, point);\n    }\n    tmp = 270.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpoint[0] = center[0];\n\tpoint[1] = arcPtr->bbox[3];\n\tTkIncludePoint((Tk_Item *) arcPtr, point);\n    }\n\n    /*\n     * Lastly, expand by the width of the arc (if the arc's outline is being\n     * drawn) and add one extra pixel just for safety.\n     */\n\n    if (arcPtr->outline.gc == NULL) {\n\ttmp = 1;\n    } else {\n\ttmp = (int) ((width + 1.0)/2.0 + 1);\n    }\n    arcPtr->header.x1 -= (int) tmp;\n    arcPtr->header.y1 -= (int) tmp;\n    arcPtr->header.x2 += (int) tmp;\n    arcPtr->header.y2 += (int) tmp;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayArc --\n *\n *\tThis function is invoked to draw an arc item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayArc(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    TCL_UNUSED(int),\t\t/* Describes region of canvas that must be */\n    TCL_UNUSED(int),\t/* redisplayed (not used). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    short x1, y1, x2, y2;\n    int start, extent, dashnumber;\n    double lineWidth;\n    Tk_State state = itemPtr->state;\n    Pixmap stipple;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    lineWidth = arcPtr->outline.width;\n    if (lineWidth < 1.0) {\n\tlineWidth = 1.0;\n    }\n    dashnumber = arcPtr->outline.dash.number;\n    stipple = arcPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (arcPtr->outline.activeWidth>lineWidth) {\n\t    lineWidth = arcPtr->outline.activeWidth;\n\t}\n\tif (arcPtr->outline.activeDash.number != 0) {\n\t    dashnumber = arcPtr->outline.activeDash.number;\n\t}\n\tif (arcPtr->activeFillStipple != None) {\n\t    stipple = arcPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledWidth > 0) {\n\t    lineWidth = arcPtr->outline.disabledWidth;\n\t}\n\tif (arcPtr->outline.disabledDash.number != 0) {\n\t    dashnumber = arcPtr->outline.disabledDash.number;\n\t}\n\tif (arcPtr->disabledFillStipple != None) {\n\t    stipple = arcPtr->disabledFillStipple;\n\t}\n    }\n\n    /*\n     * Compute the screen coordinates of the bounding box for the item, plus\n     * integer values for the angles.\n     */\n\n    Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[0], arcPtr->bbox[1],\n\t    &x1, &y1);\n    Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[2], arcPtr->bbox[3],\n\t    &x2, &y2);\n    if (x2 <= x1) {\n\tx2 = x1+1;\n    }\n    if (y2 <= y1) {\n\ty2 = y1+1;\n    }\n    start = (int) ((64*arcPtr->start) + 0.5);\n    extent = (int) ((64*arcPtr->extent) + 0.5);\n\n    /*\n     * Display filled arc first (if wanted), then outline. If the extent is\n     * zero then don't invoke XFillArc or XDrawArc, since this causes some\n     * window servers to crash and should be a no-op anyway.\n     */\n\n    if ((arcPtr->fillGC != NULL) && (extent != 0)) {\n\tif (stipple != None) {\n\t    int w = 0;\n\t    int h = 0;\n\t    Tk_TSOffset *tsoffset = &arcPtr->tsoffset;\n\t    int flags = tsoffset->flags;\n\n\t    if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {\n\t\tTk_SizeOfBitmap(display, stipple, &w, &h);\n\t\tif (flags & TK_OFFSET_CENTER) {\n\t\t    w /= 2;\n\t\t} else {\n\t\t    w = 0;\n\t\t}\n\t\tif (flags & TK_OFFSET_MIDDLE) {\n\t\t    h /= 2;\n\t\t} else {\n\t\t    h = 0;\n\t\t}\n\t    }\n\t    tsoffset->xoffset -= w;\n\t    tsoffset->yoffset -= h;\n\t    Tk_CanvasSetOffset(canvas, arcPtr->fillGC, tsoffset);\n\t    if (tsoffset) {\n\t\ttsoffset->xoffset += w;\n\t\ttsoffset->yoffset += h;\n\t    }\n\t}\n\tXFillArc(display, drawable, arcPtr->fillGC, x1, y1, (unsigned) (x2-x1),\n\t\t(unsigned) (y2-y1), start, extent);\n\tif (stipple != None) {\n\t    XSetTSOrigin(display, arcPtr->fillGC, 0, 0);\n\t}\n    }\n    if (arcPtr->outline.gc != NULL) {\n\tTk_ChangeOutlineGC(canvas, itemPtr, &(arcPtr->outline));\n\n\tif (extent != 0) {\n\t    XDrawArc(display, drawable, arcPtr->outline.gc, x1, y1,\n\t\t    (unsigned) (x2-x1), (unsigned) (y2-y1), start, extent);\n\t}\n\n\t/*\n\t * If the outline width is very thin, don't use polygons to draw the\n\t * linear parts of the outline (this often results in nothing being\n\t * displayed); just draw lines instead. The same is done if the\n\t * outline is dashed, because then polygons don't work.\n\t */\n\n\tif (lineWidth < 1.5 || dashnumber != 0) {\n\t    Tk_CanvasDrawableCoords(canvas, arcPtr->center1[0],\n\t\t    arcPtr->center1[1], &x1, &y1);\n\t    Tk_CanvasDrawableCoords(canvas, arcPtr->center2[0],\n\t\t    arcPtr->center2[1], &x2, &y2);\n\n\t    if (arcPtr->style == CHORD_STYLE) {\n\t\tXDrawLine(display, drawable, arcPtr->outline.gc,\n\t\t\tx1, y1, x2, y2);\n\t    } else if (arcPtr->style == PIESLICE_STYLE) {\n\t\tshort cx, cy;\n\n\t\tTk_CanvasDrawableCoords(canvas,\n\t\t\t(arcPtr->bbox[0] + arcPtr->bbox[2])/2.0,\n\t\t\t(arcPtr->bbox[1] + arcPtr->bbox[3])/2.0, &cx, &cy);\n\t\tXDrawLine(display, drawable, arcPtr->outline.gc,\n\t\t\tcx, cy, x1, y1);\n\t\tXDrawLine(display, drawable, arcPtr->outline.gc,\n\t\t\tcx, cy, x2, y2);\n\t    }\n\t} else {\n\t    if (arcPtr->style == CHORD_STYLE) {\n\t\tTkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,\n\t\t\tdisplay, drawable, arcPtr->outline.gc, NULL);\n\t    } else if (arcPtr->style == PIESLICE_STYLE) {\n\t\tTkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS,\n\t\t\tdisplay, drawable, arcPtr->outline.gc, NULL);\n\t\tTkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,\n\t\t\tPIE_OUTLINE2_PTS, display, drawable,\n\t\t\tarcPtr->outline.gc, NULL);\n\t    }\n\t}\n\n\tTk_ResetOutlineGC(canvas, itemPtr, &(arcPtr->outline));\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArcToPoint --\n *\n *\tComputes the distance from a given point to a given arc, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the arc. If the point isn't\n *\tinside the arc then the return value is the distance from the point to\n *\tthe arc. If itemPtr is filled, then anywhere in the interior is\n *\tconsidered \"inside\"; if itemPtr isn't filled, then \"inside\" means only\n *\tthe area occupied by the outline.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nArcToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    double vertex[2], pointAngle, diff, dist, newDist;\n    double poly[8], polyDist, width, t1, t2;\n    int filled, angleInRange;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = (double) arcPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (arcPtr->outline.activeWidth>width) {\n\t    width = (double) arcPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledWidth>0) {\n\t    width = (double) arcPtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * See if the point is within the angular range of the arc. Remember, X\n     * angles are backwards from the way we'd normally think of them. Also,\n     * compensate for any eccentricity of the oval.\n     */\n\n    vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;\n    vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;\n    t1 = arcPtr->bbox[3] - arcPtr->bbox[1];\n    if (t1 != 0.0) {\n\tt1 = (pointPtr[1] - vertex[1]) / t1;\n    }\n    t2 = arcPtr->bbox[2] - arcPtr->bbox[0];\n    if (t2 != 0.0) {\n\tt2 = (pointPtr[0] - vertex[0]) / t2;\n    }\n    if ((t1 == 0.0) && (t2 == 0.0)) {\n\tpointAngle = 0;\n    } else {\n\tpointAngle = -atan2(t1, t2)*180/PI;\n    }\n    diff = pointAngle - arcPtr->start;\n    diff -= ((int) (diff/360.0) * 360.0);\n    if (diff < 0) {\n\tdiff += 360.0;\n    }\n    angleInRange = (diff <= arcPtr->extent) ||\n\t    ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent));\n\n    /*\n     * Now perform different tests depending on what kind of arc we're dealing\n     * with.\n     */\n\n    if (arcPtr->style == ARC_STYLE) {\n\tif (angleInRange) {\n\t    return TkOvalToPoint(arcPtr->bbox, width, 0, pointPtr);\n\t}\n\tdist = hypot(pointPtr[0] - arcPtr->center1[0],\n\t\tpointPtr[1] - arcPtr->center1[1]);\n\tnewDist = hypot(pointPtr[0] - arcPtr->center2[0],\n\t\tpointPtr[1] - arcPtr->center2[1]);\n\tif (newDist < dist) {\n\t    return newDist;\n\t}\n\treturn dist;\n    }\n\n    if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {\n\tfilled = 1;\n    } else {\n\tfilled = 0;\n    }\n    if (arcPtr->outline.gc == NULL) {\n\twidth = 0.0;\n    }\n\n    if (arcPtr->style == PIESLICE_STYLE) {\n\tif (width > 1.0) {\n\t    dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,\n\t\t    pointPtr);\n\t    newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,\n\t\t    PIE_OUTLINE2_PTS, pointPtr);\n\t} else {\n\t    dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr);\n\t    newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr);\n\t}\n\tif (newDist < dist) {\n\t    dist = newDist;\n\t}\n\tif (angleInRange) {\n\t    newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);\n\t    if (newDist < dist) {\n\t\tdist = newDist;\n\t    }\n\t}\n\treturn dist;\n    }\n\n    /*\n     * This is a chord-style arc. We have to deal specially with the\n     * triangular piece that represents the difference between a chord-style\n     * arc and a pie-slice arc (for small angles this piece is excluded here\n     * where it would be included for pie slices; for large angles the piece\n     * is included here but would be excluded for pie slices).\n     */\n\n    if (width > 1.0) {\n\tdist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,\n\t\tpointPtr);\n    } else {\n\tdist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr);\n    }\n    poly[0] = poly[6] = vertex[0];\n    poly[1] = poly[7] = vertex[1];\n    poly[2] = arcPtr->center1[0];\n    poly[3] = arcPtr->center1[1];\n    poly[4] = arcPtr->center2[0];\n    poly[5] = arcPtr->center2[1];\n    polyDist = TkPolygonToPoint(poly, 4, pointPtr);\n    if (angleInRange) {\n\tif ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)\n\t\t|| (polyDist > 0.0)) {\n\t    newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);\n\t    if (newDist < dist) {\n\t\tdist = newDist;\n\t    }\n\t}\n    } else {\n\tif ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)) {\n\t    if (filled && (polyDist < dist)) {\n\t\tdist = polyDist;\n\t    }\n\t}\n    }\n    return dist;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArcToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given area.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nArcToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against arc. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates (x1,\n\t\t\t\t * y1, x2, y2) describing rectangular area. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    double rx, ry;\t\t/* Radii for transformed oval: these define an\n\t\t\t\t * oval centered at the origin. */\n    double tRect[4];\t\t/* Transformed version of x1, y1, x2, y2, for\n\t\t\t\t * coord. system where arc is centered on the\n\t\t\t\t * origin. */\n    double center[2], width, angle, tmp;\n    double points[20], *pointPtr;\n    int numPoints, filled;\n    int inside;\t\t\t/* Non-zero means every test so far suggests\n\t\t\t\t * that arc is inside rectangle. 0 means every\n\t\t\t\t * test so far shows arc to be outside of\n\t\t\t\t * rectangle. */\n    int newInside;\n    Tk_State state = itemPtr->state;\n\n    if(state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    width = (double) arcPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (arcPtr->outline.activeWidth>width) {\n\t    width = (double) arcPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledWidth>0) {\n\t    width = (double) arcPtr->outline.disabledWidth;\n\t}\n    }\n\n    if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {\n\tfilled = 1;\n    } else {\n\tfilled = 0;\n    }\n    if (arcPtr->outline.gc == NULL) {\n\twidth = 0.0;\n    }\n\n    /*\n     * Transform both the arc and the rectangle so that the arc's oval is\n     * centered on the origin.\n     */\n\n    center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;\n    center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;\n    tRect[0] = rectPtr[0] - center[0];\n    tRect[1] = rectPtr[1] - center[1];\n    tRect[2] = rectPtr[2] - center[0];\n    tRect[3] = rectPtr[3] - center[1];\n    rx = arcPtr->bbox[2] - center[0] + width/2.0;\n    ry = arcPtr->bbox[3] - center[1] + width/2.0;\n\n    /*\n     * Find the extreme points of the arc and see whether these are all inside\n     * the rectangle (in which case we're done), partly in and partly out (in\n     * which case we're done), or all outside (in which case we have more work\n     * to do). The extreme points include the following, which are checked in\n     * order:\n     *\n     * 1. The outside points of the arc, corresponding to start and extent.\n     * 2. The center of the arc (but only in pie-slice mode).\n     * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc includes\n     *\t  those angles).\n     */\n\n    pointPtr = points;\n    angle = -arcPtr->start*(PI/180.0);\n    pointPtr[0] = rx*cos(angle);\n    pointPtr[1] = ry*sin(angle);\n    angle += -arcPtr->extent*(PI/180.0);\n    pointPtr[2] = rx*cos(angle);\n    pointPtr[3] = ry*sin(angle);\n    numPoints = 2;\n    pointPtr += 4;\n\n    if ((arcPtr->style == PIESLICE_STYLE) && (arcPtr->extent < 180.0)) {\n\tpointPtr[0] = 0.0;\n\tpointPtr[1] = 0.0;\n\tnumPoints++;\n\tpointPtr += 2;\n    }\n\n    tmp = -arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpointPtr[0] = rx;\n\tpointPtr[1] = 0.0;\n\tnumPoints++;\n\tpointPtr += 2;\n    }\n    tmp = 90.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpointPtr[0] = 0.0;\n\tpointPtr[1] = -ry;\n\tnumPoints++;\n\tpointPtr += 2;\n    }\n    tmp = 180.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpointPtr[0] = -rx;\n\tpointPtr[1] = 0.0;\n\tnumPoints++;\n\tpointPtr += 2;\n    }\n    tmp = 270.0 - arcPtr->start;\n    if (tmp < 0) {\n\ttmp += 360.0;\n    }\n    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {\n\tpointPtr[0] = 0.0;\n\tpointPtr[1] = ry;\n\tnumPoints++;\n    }\n\n    /*\n     * Now that we've located the extreme points, loop through them all to see\n     * which are inside the rectangle.\n     */\n\n    inside = (points[0] > tRect[0]) && (points[0] < tRect[2])\n\t    && (points[1] > tRect[1]) && (points[1] < tRect[3]);\n    for (pointPtr = points+2; numPoints > 1; pointPtr += 2, numPoints--) {\n\tnewInside = (pointPtr[0] > tRect[0]) && (pointPtr[0] < tRect[2])\n\t\t&& (pointPtr[1] > tRect[1]) && (pointPtr[1] < tRect[3]);\n\tif (newInside != inside) {\n\t    return 0;\n\t}\n    }\n\n    if (inside) {\n\treturn 1;\n    }\n\n    /*\n     * So far, oval appears to be outside rectangle, but can't yet tell for\n     * sure. Next, test each of the four sides of the rectangle against the\n     * bounding region for the arc. If any intersections are found, then\n     * return \"overlapping\". First, test against the polygon(s) forming the\n     * sides of a chord or pie-slice.\n     */\n\n    if (arcPtr->style == PIESLICE_STYLE) {\n\tif (width >= 1.0) {\n\t    if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,\n\t\t    rectPtr) != -1) {\n\t\treturn 0;\n\t    }\n\t    if (TkPolygonToArea(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,\n\t\t    PIE_OUTLINE2_PTS, rectPtr) != -1) {\n\t\treturn 0;\n\t    }\n\t} else {\n\t    if ((TkLineToArea(center, arcPtr->center1, rectPtr) != -1) ||\n\t\t    (TkLineToArea(center, arcPtr->center2, rectPtr) != -1)) {\n\t\treturn 0;\n\t    }\n\t}\n    } else if (arcPtr->style == CHORD_STYLE) {\n\tif (width >= 1.0) {\n\t    if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,\n\t\t    rectPtr) != -1) {\n\t\treturn 0;\n\t    }\n\t} else {\n\t    if (TkLineToArea(arcPtr->center1, arcPtr->center2,\n\t\t    rectPtr) != -1) {\n\t\treturn 0;\n\t    }\n\t}\n    }\n\n    /*\n     * Next check for overlap between each of the four sides and the outer\n     * perimiter of the arc. If the arc isn't filled, then also check the\n     * inner perimeter of the arc.\n     */\n\n    if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,\n\t\tarcPtr->extent)\n\t    || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,\n\t\tarcPtr->start, arcPtr->extent)\n\t    || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,\n\t\tarcPtr->start, arcPtr->extent)\n\t    || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,\n\t\tarcPtr->start, arcPtr->extent)) {\n\treturn 0;\n    }\n    if ((width > 1.0) && !filled) {\n\trx -= width;\n\try -= width;\n\tif (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,\n\t\t    arcPtr->extent)\n\t\t|| HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,\n\t\t    arcPtr->start, arcPtr->extent)\n\t\t|| VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,\n\t\t    arcPtr->start, arcPtr->extent)\n\t\t|| VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,\n\t\t    arcPtr->start, arcPtr->extent)) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * The arc still appears to be totally disjoint from the rectangle, but\n     * it's also possible that the rectangle is totally inside the arc. Do one\n     * last check, which is to check one point of the rectangle to see if it's\n     * inside the arc. If it is, we've got overlap. If it isn't, the arc's\n     * really outside the rectangle.\n     */\n\n    if (ArcToPoint(canvas, itemPtr, rectPtr) == 0.0) {\n\treturn 0;\n    }\n    return -1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleArc --\n *\n *\tThis function is invoked to rescale an arc item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe arc referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleArc(\n    Tk_Canvas canvas,\t\t/* Canvas containing arc. */\n    Tk_Item *itemPtr,\t\t/* Arc to be scaled. */\n    double originX,\t\t/* Origin about which to scale rect. */\n    double originY,\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n\n    arcPtr->bbox[0] = originX + scaleX*(arcPtr->bbox[0] - originX);\n    arcPtr->bbox[1] = originY + scaleY*(arcPtr->bbox[1] - originY);\n    arcPtr->bbox[2] = originX + scaleX*(arcPtr->bbox[2] - originX);\n    arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY);\n    ComputeArcBbox(canvas, arcPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateArc --\n *\n *\tThis function is called to rotate an arc by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the arc is rotated by angleRad radians about (originX,\n *\toriginY), and the bounding box is updated in the generic part of the\n *\titem structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateArc(\n    Tk_Canvas canvas,\n    Tk_Item *itemPtr,\n    double originX,\n    double originY,\n    double angleRad)\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    double newX, newY, oldX, oldY;\n\n    /*\n     * Compute the centre of the box, then rotate that about the origin.\n     */\n\n    newX = oldX = (arcPtr->bbox[0] + arcPtr->bbox[2]) / 2.0;\n    newY = oldY = (arcPtr->bbox[1] + arcPtr->bbox[3]) / 2.0;\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &newX, &newY);\n\n    /*\n     * Apply the translation to the box.\n     */\n\n    arcPtr->bbox[0] += newX - oldX;\n    arcPtr->bbox[1] += newY - oldY;\n    arcPtr->bbox[2] += newX - oldX;\n    arcPtr->bbox[3] += newY - oldY;\n\n    /*\n     * TODO: update the arc endpoints?\n     */\n\n    ComputeArcBbox(canvas, arcPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateArc --\n *\n *\tThis function is called to move an arc by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the arc is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateArc(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX,\t\t/* Amount by which item is to be moved. */\n    double deltaY)\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n\n    arcPtr->bbox[0] += deltaX;\n    arcPtr->bbox[1] += deltaY;\n    arcPtr->bbox[2] += deltaX;\n    arcPtr->bbox[3] += deltaY;\n    ComputeArcBbox(canvas, arcPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeArcOutline --\n *\n *\tThis function creates a polygon describing everything in the outline\n *\tfor an arc except what's in the curved part. For a \"pie slice\" arc\n *\tthis is a V-shaped chunk, and for a \"chord\" arc this is a linear chunk\n *\t(with cutaway corners). For \"arc\" arcs, this stuff isn't relevant.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe information at arcPtr->outlinePtr gets modified, and storage for\n *\tarcPtr->outlinePtr may be allocated or freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeArcOutline(\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    ArcItem *arcPtr)\t\t/* Information about arc. */\n{\n    double sin1, cos1, sin2, cos2, angle, width, halfWidth;\n    double boxWidth, boxHeight;\n    double vertex[2], corner1[2], corner2[2];\n    double *outlinePtr;\n    Tk_State state = arcPtr->header.state;\n\n    /*\n     * Make sure that the outlinePtr array is large enough to hold either a\n     * chord or pie-slice outline.\n     */\n\n    if (arcPtr->numOutlinePoints == 0) {\n\tarcPtr->outlinePtr = (double *)Tcl_Alloc(26 * sizeof(double));\n\tarcPtr->numOutlinePoints = 22;\n    }\n    outlinePtr = arcPtr->outlinePtr;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    /*\n     * First compute the two points that lie at the centers of the ends of the\n     * curved arc segment, which are marked with X's in the figure below:\n     *\n     *\n     *\t\t\t          * * *\n     *\t\t\t      *          *\n     *\t\t\t   *      * *      *\n     *\t\t\t *    *         *    *\n     *\t\t\t*   *             *   *\n     *\t\t\t X *               * X\n     *\n     * The code is tricky because the arc can be ovular in shape. It computes\n     * the position for a unit circle, and then scales to fit the shape of the\n     * arc's bounding box.\n     *\n     * Also, watch out because angles go counter-clockwise like you might\n     * expect, but the y-coordinate system is inverted. To handle this, just\n     * negate the angles in all the computations.\n     */\n\n    boxWidth = arcPtr->bbox[2] - arcPtr->bbox[0];\n    boxHeight = arcPtr->bbox[3] - arcPtr->bbox[1];\n    angle = -arcPtr->start*PI/180.0;\n    sin1 = sin(angle);\n    cos1 = cos(angle);\n    angle -= arcPtr->extent*PI/180.0;\n    sin2 = sin(angle);\n    cos2 = cos(angle);\n    vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;\n    vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;\n    arcPtr->center1[0] = vertex[0] + cos1*boxWidth/2.0;\n    arcPtr->center1[1] = vertex[1] + sin1*boxHeight/2.0;\n    arcPtr->center2[0] = vertex[0] + cos2*boxWidth/2.0;\n    arcPtr->center2[1] = vertex[1] + sin2*boxHeight/2.0;\n\n    /*\n     * Next compute the \"outermost corners\" of the arc, which are marked with\n     * X's in the figure below:\n     *\n     *\t\t\t\t  * * *\n     *\t\t\t      *          *\n     *\t\t\t   *      * *      *\n     *\t\t\t *    *         *    *\n     *\t\t\tX   *             *   X\n     *\t\t\t   *               *\n     *\n     * The code below is tricky because it has to handle eccentricity in the\n     * shape of the oval. The key in the code below is to realize that the\n     * slope of the line from arcPtr->center1 to corner1 is (boxWidth*sin1)\n     * divided by (boxHeight*cos1), and similarly for arcPtr->center2 and\n     * corner2. These formulas can be computed from the formula for the oval.\n     */\n\n    width = arcPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) arcPtr) {\n\tif (arcPtr->outline.activeWidth>arcPtr->outline.width) {\n\t    width = arcPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledWidth>arcPtr->outline.width) {\n\t    width = arcPtr->outline.disabledWidth;\n\t}\n    }\n    halfWidth = width/2.0;\n\n    if (((boxWidth*sin1) == 0.0) && ((boxHeight*cos1) == 0.0)) {\n\tangle = 0.0;\n    } else {\n\tangle = atan2(boxWidth*sin1, boxHeight*cos1);\n    }\n    corner1[0] = arcPtr->center1[0] + cos(angle)*halfWidth;\n    corner1[1] = arcPtr->center1[1] + sin(angle)*halfWidth;\n    if (((boxWidth*sin2) == 0.0) && ((boxHeight*cos2) == 0.0)) {\n\tangle = 0.0;\n    } else {\n\tangle = atan2(boxWidth*sin2, boxHeight*cos2);\n    }\n    corner2[0] = arcPtr->center2[0] + cos(angle)*halfWidth;\n    corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth;\n\n    /*\n     * For a chord outline, generate a six-sided polygon with three points for\n     * each end of the chord. The first and third points for each end are butt\n     * points generated on either side of the center point. The second point\n     * is the corner point.\n     */\n\n    if (arcPtr->style == CHORD_STYLE) {\n\toutlinePtr[0] = outlinePtr[12] = corner1[0];\n\toutlinePtr[1] = outlinePtr[13] = corner1[1];\n\tTkGetButtPoints(arcPtr->center2, arcPtr->center1,\n\t\twidth, 0, outlinePtr+10, outlinePtr+2);\n\toutlinePtr[4] = arcPtr->center2[0] + outlinePtr[2]\n\t\t- arcPtr->center1[0];\n\toutlinePtr[5] = arcPtr->center2[1] + outlinePtr[3]\n\t\t- arcPtr->center1[1];\n\toutlinePtr[6] = corner2[0];\n\toutlinePtr[7] = corner2[1];\n\toutlinePtr[8] = arcPtr->center2[0] + outlinePtr[10]\n\t\t- arcPtr->center1[0];\n\toutlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]\n\t\t- arcPtr->center1[1];\n    } else if (arcPtr->style == PIESLICE_STYLE) {\n\t/*\n\t * For pie slices, generate two polygons, one for each side of the pie\n\t * slice. The first arm has a shape like this, where the center of the\n\t * oval is X, arcPtr->center1 is at Y, and corner1 is at Z:\n\t *\n\t *\t _____________________\n\t *\t|\t\t      \\\n\t *\t|\t\t       \\\n\t *\tX\t\t     Y  Z\n\t *\t|\t\t       /\n\t *\t|_____________________/\n\t */\n\n\tTkGetButtPoints(arcPtr->center1, vertex, width, 0,\n\t\toutlinePtr, outlinePtr+2);\n\toutlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0];\n\toutlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1];\n\toutlinePtr[6] = corner1[0];\n\toutlinePtr[7] = corner1[1];\n\toutlinePtr[8] = arcPtr->center1[0] + outlinePtr[0] - vertex[0];\n\toutlinePtr[9] = arcPtr->center1[1] + outlinePtr[1] - vertex[1];\n\toutlinePtr[10] = outlinePtr[0];\n\toutlinePtr[11] = outlinePtr[1];\n\n\t/*\n\t * The second arm has a shape like this:\n\t *\n\t *\t   ______________________\n\t *\t  /\t\t\t  \\\n\t *\t /\t\t\t   \\\n\t *\tZ  Y\t\t\tX  /\n\t *\t \\\t\t\t  /\n\t *\t  \\______________________/\n\t *\n\t * Similar to above X is the center of the oval/circle, Y is\n\t * arcPtr->center2, and Z is corner2. The extra jog out to the left of\n\t * X is needed in or to produce a butted joint with the first arm; the\n\t * corner to the right of X is one of the first two points of the\n\t * first arm, depending on extent.\n\t */\n\n\tTkGetButtPoints(arcPtr->center2, vertex, width, 0,\n\t\toutlinePtr+12, outlinePtr+16);\n\tif ((arcPtr->extent > 180) ||\n\t\t((arcPtr->extent < 0) && (arcPtr->extent > -180))) {\n\t    outlinePtr[14] = outlinePtr[0];\n\t    outlinePtr[15] = outlinePtr[1];\n\t} else {\n\t    outlinePtr[14] = outlinePtr[2];\n\t    outlinePtr[15] = outlinePtr[3];\n\t}\n\toutlinePtr[18] = arcPtr->center2[0] + outlinePtr[16] - vertex[0];\n\toutlinePtr[19] = arcPtr->center2[1] + outlinePtr[17] - vertex[1];\n\toutlinePtr[20] = corner2[0];\n\toutlinePtr[21] = corner2[1];\n\toutlinePtr[22] = arcPtr->center2[0] + outlinePtr[12] - vertex[0];\n\toutlinePtr[23] = arcPtr->center2[1] + outlinePtr[13] - vertex[1];\n\toutlinePtr[24] = outlinePtr[12];\n\toutlinePtr[25] = outlinePtr[13];\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * HorizLineToArc --\n *\n *\tDetermines whether a horizontal line segment intersects a given arc.\n *\n * Results:\n *\tThe return value is 1 if the given line intersects the infinitely-thin\n *\tarc section defined by rx, ry, start, and extent, and 0 otherwise.\n *\tOnly the perimeter of the arc is checked: interior areas (e.g. chord\n *\tor pie-slice) are not checked.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nHorizLineToArc(\n    double x1, double x2,\t/* X-coords of endpoints of line segment. X1\n\t\t\t\t * must be <= x2. */\n    double y,\t\t\t/* Y-coordinate of line segment. */\n    double rx, double ry,\t/* These x- and y-radii define an oval\n\t\t\t\t * centered at the origin. */\n    double start, double extent)/* Angles that define extent of arc, in the\n\t\t\t\t * standard fashion for this module. */\n{\n    double tmp, x;\n    double tx, ty;\t\t/* Coordinates of intersection point in\n\t\t\t\t * transformed coordinate system. */\n\n    /*\n     * Compute the x-coordinate of one possible intersection point between the\n     * arc and the line. Use a transformed coordinate system where the oval is\n     * a unit circle centered at the origin. Then scale back to get actual\n     * x-coordinate.\n     */\n\n    ty = y/ry;\n    tmp = 1 - ty*ty;\n    if (tmp < 0) {\n\treturn 0;\n    }\n    tx = sqrt(tmp);\n    x = tx*rx;\n\n    /*\n     * Test both intersection points.\n     */\n\n    if ((x >= x1) && (x <= x2) && AngleInRange(tx, ty, start, extent)) {\n\treturn 1;\n    }\n    if ((-x >= x1) && (-x <= x2) && AngleInRange(-tx, ty, start, extent)) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * VertLineToArc --\n *\n *\tDetermines whether a vertical line segment intersects a given arc.\n *\n * Results:\n *\tThe return value is 1 if the given line intersects the infinitely-thin\n *\tarc section defined by rx, ry, start, and extent, and 0 otherwise.\n *\tOnly the perimeter of the arc is checked: interior areas (e.g. chord\n *\tor pie-slice) are not checked.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nVertLineToArc(\n    double x,\t\t\t/* X-coordinate of line segment. */\n    double y1, double y2,\t/* Y-coords of endpoints of line segment. Y1\n\t\t\t\t * must be <= y2. */\n    double rx, double ry,\t/* These x- and y-radii define an oval\n\t\t\t\t * centered at the origin. */\n    double start, double extent)/* Angles that define extent of arc, in the\n\t\t\t\t * standard fashion for this module. */\n{\n    double tmp, y;\n    double tx, ty;\t\t/* Coordinates of intersection point in\n\t\t\t\t * transformed coordinate system. */\n\n    /*\n     * Compute the y-coordinate of one possible intersection point between the\n     * arc and the line. Use a transformed coordinate system where the oval is\n     * a unit circle centered at the origin. Then scale back to get actual\n     * y-coordinate.\n     */\n\n    tx = x/rx;\n    tmp = 1 - tx*tx;\n    if (tmp < 0) {\n\treturn 0;\n    }\n    ty = sqrt(tmp);\n    y = ty*ry;\n\n    /*\n     * Test both intersection points.\n     */\n\n    if ((y > y1) && (y < y2) && AngleInRange(tx, ty, start, extent)) {\n\treturn 1;\n    }\n    if ((-y > y1) && (-y < y2) && AngleInRange(tx, -ty, start, extent)) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * AngleInRange --\n *\n *\tDetermine whether the angle from the origin to a given point is within\n *\ta given range.\n *\n * Results:\n *\tThe return value is 1 if the angle from (0,0) to (x,y) is in the range\n *\tgiven by start and extent, where angles are interpreted in the\n *\tstandard way for ovals (meaning backwards from normal interpretation).\n *\tOtherwise the return value is 0.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nAngleInRange(\n    double x, double y,\t\t/* Coordinate of point; angle measured from\n\t\t\t\t * origin to here, relative to x-axis. */\n    double start,\t\t/* First angle, degrees, >=0, <=360. */\n    double extent)\t\t/* Size of arc in degrees >=-360, <=360. */\n{\n    double diff;\n\n    if ((x == 0.0) && (y == 0.0)) {\n\treturn 1;\n    }\n    diff = -atan2(y, x);\n    diff = diff*(180.0/PI) - start;\n    while (diff > 360.0) {\n\tdiff -= 360.0;\n    }\n    while (diff < 0.0) {\n\tdiff += 360.0;\n    }\n    if (extent >= 0) {\n\treturn diff <= extent;\n    }\n    return (diff-360.0) >= extent;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArcToPostscript --\n *\n *\tThis function is called to generate Postscript for arc items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nArcToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    TCL_UNUSED(int))\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    ArcItem *arcPtr = (ArcItem *) itemPtr;\n    double y1, y2, ang1, ang2;\n    XColor *color;\n    Pixmap stipple;\n    XColor *fillColor;\n    Pixmap fillStipple;\n    Tk_State state = itemPtr->state;\n    Tcl_Obj *psObj;\n    Tcl_InterpState interpState;\n\n    y1 = Tk_CanvasPsY(canvas, arcPtr->bbox[1]);\n    y2 = Tk_CanvasPsY(canvas, arcPtr->bbox[3]);\n    ang1 = arcPtr->start;\n    ang2 = ang1 + arcPtr->extent;\n    if (ang2 < ang1) {\n\tang1 = ang2;\n\tang2 = arcPtr->start;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    color = arcPtr->outline.color;\n    stipple = arcPtr->outline.stipple;\n    fillColor = arcPtr->fillColor;\n    fillStipple = arcPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (arcPtr->outline.activeColor!=NULL) {\n\t    color = arcPtr->outline.activeColor;\n\t}\n\tif (arcPtr->outline.activeStipple!=None) {\n\t    stipple = arcPtr->outline.activeStipple;\n\t}\n\tif (arcPtr->activeFillColor!=NULL) {\n\t    fillColor = arcPtr->activeFillColor;\n\t}\n\tif (arcPtr->activeFillStipple!=None) {\n\t    fillStipple = arcPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (arcPtr->outline.disabledColor!=NULL) {\n\t    color = arcPtr->outline.disabledColor;\n\t}\n\tif (arcPtr->outline.disabledStipple!=None) {\n\t    stipple = arcPtr->outline.disabledStipple;\n\t}\n\tif (arcPtr->disabledFillColor!=NULL) {\n\t    fillColor = arcPtr->disabledFillColor;\n\t}\n\tif (arcPtr->disabledFillStipple!=None) {\n\t    fillStipple = arcPtr->disabledFillStipple;\n\t}\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * If the arc is filled, output Postscript for the interior region of the\n     * arc.\n     */\n\n    if (arcPtr->fillGC != NULL) {\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"matrix currentmatrix\\n\"\n\t\t\"%.15g %.15g translate %.15g %.15g scale\\n\",\n\t\t(arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,\n\t\t(arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);\n\n\tif (arcPtr->style != CHORD_STYLE) {\n\t    Tcl_AppendToObj(psObj, \"0 0 moveto \", TCL_INDEX_NONE);\n\t}\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"0 0 1 %.15g %.15g arc closepath\\nsetmatrix\\n\",\n\t\tang1, ang2);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, fillColor);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (fillStipple != None) {\n\t    Tcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsStipple(interp, canvas, fillStipple);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\t    if (arcPtr->outline.gc != NULL) {\n\t\tTcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\t    }\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t}\n    }\n\n    /*\n     * If there's an outline for the arc, draw it.\n     */\n\n    if (arcPtr->outline.gc != NULL) {\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"matrix currentmatrix\\n\"\n\t\t\"%.15g %.15g translate %.15g %.15g scale\\n\",\n\t\t(arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,\n\t\t(arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"0 0 1 %.15g %.15g arc\\nsetmatrix\\n0 setlinecap\\n\",\n\t\tang1, ang2);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsOutline(canvas, itemPtr, &arcPtr->outline);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (arcPtr->style != ARC_STYLE) {\n\t    Tcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\n\t    Tcl_ResetResult(interp);\n\t    if (arcPtr->style == CHORD_STYLE) {\n\t\tTk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,\n\t\t\tCHORD_OUTLINE_PTS);\n\t    } else {\n\t\tTk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,\n\t\t\tPIE_OUTLINE1_PTS);\n\t\tTk_CanvasPsColor(interp, canvas, color);\n\t\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\t\tif (stipple != None) {\n\t\t    Tcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\t\t    Tcl_ResetResult(interp);\n\t\t    Tk_CanvasPsStipple(interp, canvas, stipple);\n\t\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\t\t} else {\n\t\t    Tcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t\t}\n\t\tTcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\n\t\tTcl_ResetResult(interp);\n\t\tTk_CanvasPsPath(interp, canvas,\n\t\t\tarcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,\n\t\t\tPIE_OUTLINE2_PTS);\n\t    }\n\t    Tk_CanvasPsColor(interp, canvas, color);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\t    if (stipple != None) {\n\t\tTcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\t\tTcl_ResetResult(interp);\n\t\tTk_CanvasPsStipple(interp, canvas, stipple);\n\t\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\t    } else {\n\t\tTcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t    }\n\t}\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * StyleParseProc --\n *\n *\tThis function is invoked during option processing to handle the\n *\t\"-style\" option.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe state for a given item gets replaced by the state indicated in the\n *\tvalue argument.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nStyleParseProc(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    int c;\n    size_t length;\n    Style *stylePtr = (Style *) (widgRec + offset);\n\n    if (value == NULL || *value == 0) {\n\t*stylePtr = PIESLICE_STYLE;\n\treturn TCL_OK;\n    }\n\n    c = value[0];\n    length = strlen(value);\n\n    if ((c == 'a') && (strncmp(value, \"arc\", length) == 0)) {\n\t*stylePtr = ARC_STYLE;\n\treturn TCL_OK;\n    }\n    if ((c == 'c') && (strncmp(value, \"chord\", length) == 0)) {\n\t*stylePtr = CHORD_STYLE;\n\treturn TCL_OK;\n    }\n    if ((c == 'p') && (strncmp(value, \"pieslice\", length) == 0)) {\n\t*stylePtr = PIESLICE_STYLE;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad -style option \\\"%s\\\": must be arc, chord, or pieslice\",\n\t    value));\n    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ARC_STYLE\", (char *)NULL);\n    *stylePtr = PIESLICE_STYLE;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * StylePrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-style\" configuration option.\n *\n * Results:\n *\tThe return value is a string describing the state for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic const char *\nStylePrintProc(\n    TCL_UNUSED(void *),\t/* Ignored. */\n    TCL_UNUSED(Tk_Window),\t\t/* Ignored. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset into item. */\n    TCL_UNUSED(Tcl_FreeProc **))\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    Style *stylePtr = (Style *) (widgRec + offset);\n\n    if (*stylePtr == ARC_STYLE) {\n\treturn \"arc\";\n    } else if (*stylePtr == CHORD_STYLE) {\n\treturn \"chord\";\n    } else {\n\treturn \"pieslice\";\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvBmap.c",
    "content": "/*\n * tkCanvBmap.c --\n *\n *\tThis file implements bitmap items for canvas widgets.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n/*\n * The structure below defines the record for each bitmap item.\n */\n\ntypedef struct BitmapItem  {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    double x, y;\t\t/* Coordinates of positioning point for\n\t\t\t\t * bitmap. */\n    Tk_Anchor anchor;\t\t/* Where to anchor bitmap relative to (x,y) */\n    Pixmap bitmap;\t\t/* Bitmap to display in window. */\n    Pixmap activeBitmap;\t/* Bitmap to display in window. */\n    Pixmap disabledBitmap;\t/* Bitmap to display in window. */\n    XColor *fgColor;\t\t/* Foreground color to use for bitmap. */\n    XColor *activeFgColor;\t/* Foreground color to use for bitmap. */\n    XColor *disabledFgColor;\t/* Foreground color to use for bitmap. */\n    XColor *bgColor;\t\t/* Background color to use for bitmap. */\n    XColor *activeBgColor;\t/* Background color to use for bitmap. */\n    XColor *disabledBgColor;\t/* Background color to use for bitmap. */\n    GC gc;\t\t\t/* Graphics context to use for drawing bitmap\n\t\t\t\t * on screen. */\n} BitmapItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_COLOR, \"-activebackground\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activebitmap\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-activeforeground\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_ANCHOR, \"-anchor\", NULL, NULL,\n\t\"center\", offsetof(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_COLOR, \"-background\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-bitmap\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-disabledbackground\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, disabledBgColor),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledbitmap\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, disabledBitmap),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-disabledforeground\", NULL, NULL,\n\tNULL, offsetof(BitmapItem, disabledFgColor),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-foreground\", NULL, NULL,\n\tDEF_CANVBMAP_FG, offsetof(BitmapItem, fgColor), 0, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK,\n\t&stateOption},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic int\t\tBitmapCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tBitmapToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tBitmapToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *coordPtr);\nstatic int\t\tBitmapToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic void\t\tComputeBitmapBbox(Tk_Canvas canvas,\n\t\t\t    BitmapItem *bmapPtr);\nstatic int\t\tConfigureBitmap(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tTkcCreateBitmap(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteBitmap(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayBitmap(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tRotateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScaleBitmap(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double deltaX, double deltaY);\n\n/*\n * The structures below defines the bitmap item type in terms of functions\n * that can be invoked by generic item code.\n */\n\nTk_ItemType tkBitmapType = {\n    \"bitmap\",\t\t\t/* name */\n    sizeof(BitmapItem),\t\t/* itemSize */\n    TkcCreateBitmap,\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureBitmap,\t\t/* configureProc */\n    BitmapCoords,\t\t/* coordProc */\n    DeleteBitmap,\t\t/* deleteProc */\n    DisplayBitmap,\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    BitmapToPoint,\t\t/* pointProc */\n    BitmapToArea,\t\t/* areaProc */\n    BitmapToPostscript,\t\t/* postscriptProc */\n    ScaleBitmap,\t\t/* scaleProc */\n    TranslateBitmap,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* icursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateBitmap,\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkcCreateBitmap --\n *\n *\tThis function is invoked to create a new bitmap item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new bitmap item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTkcCreateBitmap(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing rectangle. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Initialize item's record.\n     */\n\n    bmapPtr->anchor = TK_ANCHOR_CENTER;\n    bmapPtr->bitmap = None;\n    bmapPtr->activeBitmap = None;\n    bmapPtr->disabledBitmap = None;\n    bmapPtr->fgColor = NULL;\n    bmapPtr->activeFgColor = NULL;\n    bmapPtr->disabledFgColor = NULL;\n    bmapPtr->bgColor = NULL;\n    bmapPtr->activeBgColor = NULL;\n    bmapPtr->disabledBgColor = NULL;\n    bmapPtr->gc = NULL;\n\n    /*\n     * Process the arguments to fill in the item record. Only 1 (list) or 2 (x\n     * y) coords are allowed.\n     */\n\n    if (objc == 1) {\n\ti = 1;\n    } else {\n\tconst char *arg = Tcl_GetString(objv[1]);\n\ti = 2;\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    i = 1;\n\t}\n    }\n    if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {\n\tgoto error;\n    }\n    if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0)\n\t    == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * BitmapCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\tbitmap items. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nBitmapCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    if (objc == 0) {\n\tTcl_Obj *obj = Tcl_NewObj();\n\n\tTcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->x));\n\tTcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->y));\n\tTcl_SetObjResult(interp, obj);\n    } else if (objc < 3) {\n\tif (objc == 1) {\n\t    if (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t    (Tcl_Obj ***) &objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    } else if (objc != 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"wrong # coordinates: expected 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"BITMAP\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],\n\t\t&bmapPtr->x) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t\t&bmapPtr->y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tComputeBitmapBbox(canvas, bmapPtr);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"BITMAP\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureBitmap --\n *\n *\tThis function is invoked to configure various aspects of a bitmap\n *\titem, such as its anchor position.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information may be set for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureBitmap(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Bitmap item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv.  */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC;\n    Tk_Window tkwin;\n    unsigned long mask;\n    XColor *fgColor;\n    XColor *bgColor;\n    Pixmap bitmap;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, bmapPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few of the options require additional processing, such as those that\n     * determine the graphics context.\n     */\n\n    state = itemPtr->state;\n\n    if (bmapPtr->activeFgColor!=NULL ||\n\t    bmapPtr->activeBgColor!=NULL ||\n\t    bmapPtr->activeBitmap!=None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (state == TK_STATE_HIDDEN) {\n\tComputeBitmapBbox(canvas, bmapPtr);\n\treturn TCL_OK;\n    }\n    fgColor = bmapPtr->fgColor;\n    bgColor = bmapPtr->bgColor;\n    bitmap = bmapPtr->bitmap;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (bmapPtr->activeFgColor!=NULL) {\n\t    fgColor = bmapPtr->activeFgColor;\n\t}\n\tif (bmapPtr->activeBgColor!=NULL) {\n\t    bgColor = bmapPtr->activeBgColor;\n\t}\n\tif (bmapPtr->activeBitmap!=None) {\n\t    bitmap = bmapPtr->activeBitmap;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (bmapPtr->disabledFgColor!=NULL) {\n\t    fgColor = bmapPtr->disabledFgColor;\n\t}\n\tif (bmapPtr->disabledBgColor!=NULL) {\n\t    bgColor = bmapPtr->disabledBgColor;\n\t}\n\tif (bmapPtr->disabledBitmap!=None) {\n\t    bitmap = bmapPtr->disabledBitmap;\n\t}\n    }\n\n    if (bitmap == None) {\n\tnewGC = NULL;\n    } else {\n\tgcValues.foreground = fgColor->pixel;\n\tmask = GCForeground;\n\tif (bgColor != NULL) {\n\t    gcValues.background = bgColor->pixel;\n\t    mask |= GCBackground;\n\t} else {\n\t    gcValues.clip_mask = bitmap;\n\t    mask |= GCClipMask;\n\t}\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    }\n    if (bmapPtr->gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);\n    }\n    bmapPtr->gc = newGC;\n\n    ComputeBitmapBbox(canvas, bmapPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteBitmap --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta bitmap item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteBitmap(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Info about overall canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    if (bmapPtr->bitmap != None) {\n\tTk_FreeBitmap(display, bmapPtr->bitmap);\n    }\n    if (bmapPtr->activeBitmap != None) {\n\tTk_FreeBitmap(display, bmapPtr->activeBitmap);\n    }\n    if (bmapPtr->disabledBitmap != None) {\n\tTk_FreeBitmap(display, bmapPtr->disabledBitmap);\n    }\n    if (bmapPtr->fgColor != NULL) {\n\tTk_FreeColor(bmapPtr->fgColor);\n    }\n    if (bmapPtr->activeFgColor != NULL) {\n\tTk_FreeColor(bmapPtr->activeFgColor);\n    }\n    if (bmapPtr->disabledFgColor != NULL) {\n\tTk_FreeColor(bmapPtr->disabledFgColor);\n    }\n    if (bmapPtr->bgColor != NULL) {\n\tTk_FreeColor(bmapPtr->bgColor);\n    }\n    if (bmapPtr->activeBgColor != NULL) {\n\tTk_FreeColor(bmapPtr->activeBgColor);\n    }\n    if (bmapPtr->disabledBgColor != NULL) {\n\tTk_FreeColor(bmapPtr->disabledBgColor);\n    }\n    if (bmapPtr->gc != NULL) {\n\tTk_FreeGC(display, bmapPtr->gc);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeBitmapBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a bitmap item. This function is where the\n *\tchild bitmap's placement is computed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeBitmapBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    BitmapItem *bmapPtr)\t/* Item whose bbox is to be recomputed. */\n{\n    int width, height;\n    int x, y;\n    Pixmap bitmap;\n    Tk_State state = bmapPtr->header.state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    bitmap = bmapPtr->bitmap;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {\n\tif (bmapPtr->activeBitmap!=None) {\n\t    bitmap = bmapPtr->activeBitmap;\n\t}\n    } else if (state==TK_STATE_DISABLED) {\n\tif (bmapPtr->disabledBitmap!=None) {\n\t    bitmap = bmapPtr->disabledBitmap;\n\t}\n    }\n\n    x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));\n    y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));\n\n    if (state==TK_STATE_HIDDEN || bitmap == None) {\n\tbmapPtr->header.x1 = bmapPtr->header.x2 = x;\n\tbmapPtr->header.y1 = bmapPtr->header.y2 = y;\n\treturn;\n    }\n\n    /*\n     * Compute location and size of bitmap, using anchor information.\n     */\n\n    Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,\n\t    &width, &height);\n    switch (bmapPtr->anchor) {\n    case TK_ANCHOR_N:\n\tx -= width/2;\n\tbreak;\n    case TK_ANCHOR_NE:\n\tx -= width;\n\tbreak;\n    case TK_ANCHOR_E:\n\tx -= width;\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_SE:\n\tx -= width;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_S:\n\tx -= width/2;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_SW:\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_W:\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_NW:\n\tbreak;\n    default:\n\tx -= width/2;\n\ty -= height/2;\n\tbreak;\n    }\n\n    /*\n     * Store the information in the item header.\n     */\n\n    bmapPtr->header.x1 = x;\n    bmapPtr->header.y1 = y;\n    bmapPtr->header.x2 = x + width;\n    bmapPtr->header.y2 = y + height;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayBitmap --\n *\n *\tThis function is invoked to draw a bitmap item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayBitmap(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    int x, int y, int width, int height)\n\t\t\t\t/* Describes region of canvas that must be\n\t\t\t\t * redisplayed (not used). */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n    int bmapX, bmapY, bmapWidth, bmapHeight;\n    short drawableX, drawableY;\n    Pixmap bitmap;\n    Tk_State state = itemPtr->state;\n\n    /*\n     * If the area being displayed doesn't cover the whole bitmap, then only\n     * redisplay the part of the bitmap that needs redisplay.\n     */\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    bitmap = bmapPtr->bitmap;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (bmapPtr->activeBitmap!=None) {\n\t    bitmap = bmapPtr->activeBitmap;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (bmapPtr->disabledBitmap!=None) {\n\t    bitmap = bmapPtr->disabledBitmap;\n\t}\n    }\n\n    if (bitmap != None) {\n\tif (x > bmapPtr->header.x1) {\n\t    bmapX = x - bmapPtr->header.x1;\n\t    bmapWidth = bmapPtr->header.x2 - x;\n\t} else {\n\t    bmapX = 0;\n\t    if ((x+width) < bmapPtr->header.x2) {\n\t\tbmapWidth = x + width - bmapPtr->header.x1;\n\t    } else {\n\t\tbmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;\n\t    }\n\t}\n\tif (y > bmapPtr->header.y1) {\n\t    bmapY = y - bmapPtr->header.y1;\n\t    bmapHeight = bmapPtr->header.y2 - y;\n\t} else {\n\t    bmapY = 0;\n\t    if ((y+height) < bmapPtr->header.y2) {\n\t\tbmapHeight = y + height - bmapPtr->header.y1;\n\t    } else {\n\t\tbmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;\n\t    }\n\t}\n\tTk_CanvasDrawableCoords(canvas,\n\t\t(double) (bmapPtr->header.x1 + bmapX),\n\t\t(double) (bmapPtr->header.y1 + bmapY),\n\t\t&drawableX, &drawableY);\n\n\t/*\n\t * Must modify the mask origin within the graphics context to line up\n\t * with the bitmap's origin (in order to make bitmaps with\n\t * \"-background {}\" work right).\n\t */\n\n\tXSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,\n\t\tdrawableY - bmapY);\n\tXCopyPlane(display, bitmap, drawable,\n\t\tbmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,\n\t\t(unsigned int) bmapHeight, drawableX, drawableY, 1);\n\tXSetClipOrigin(display, bmapPtr->gc, 0, 0);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * BitmapToPoint --\n *\n *\tComputes the distance from a given point to a given rectangle, in\n *\tcanvas units.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the bitmap. If the point isn't\n *\tinside the bitmap then the return value is the distance from the point\n *\tto the bitmap.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nBitmapToPoint(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *coordPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n    double x1, x2, y1, y2, xDiff, yDiff;\n\n    x1 = bmapPtr->header.x1;\n    y1 = bmapPtr->header.y1;\n    x2 = bmapPtr->header.x2;\n    y2 = bmapPtr->header.y2;\n\n    /*\n     * Point is outside rectangle.\n     */\n\n    if (coordPtr[0] < x1) {\n\txDiff = x1 - coordPtr[0];\n    } else if (coordPtr[0] > x2)  {\n\txDiff = coordPtr[0] - x2;\n    } else {\n\txDiff = 0;\n    }\n\n    if (coordPtr[1] < y1) {\n\tyDiff = y1 - coordPtr[1];\n    } else if (coordPtr[1] > y2)  {\n\tyDiff = coordPtr[1] - y2;\n    } else {\n\tyDiff = 0;\n    }\n\n    return hypot(xDiff, yDiff);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * BitmapToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangle.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nBitmapToArea(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against rectangle. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates\n\t\t\t\t * (x1,y1,x2,y2) describing rectangular\n\t\t\t\t * area. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    if ((rectPtr[2] <= bmapPtr->header.x1)\n\t    || (rectPtr[0] >= bmapPtr->header.x2)\n\t    || (rectPtr[3] <= bmapPtr->header.y1)\n\t    || (rectPtr[1] >= bmapPtr->header.y2)) {\n\treturn -1;\n    }\n    if ((rectPtr[0] <= bmapPtr->header.x1)\n\t    && (rectPtr[1] <= bmapPtr->header.y1)\n\t    && (rectPtr[2] >= bmapPtr->header.x2)\n\t    && (rectPtr[3] >= bmapPtr->header.y2)) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleBitmap --\n *\n *\tThis function is invoked to rescale a bitmap item in a canvas. It is\n *\tone of the standard item functions for bitmap items, and is invoked by\n *\tthe generic canvas code.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe item referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleBitmap(\n    Tk_Canvas canvas,\t\t/* Canvas containing rectangle. */\n    Tk_Item *itemPtr,\t\t/* Rectangle to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale item. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);\n    bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);\n    ComputeBitmapBbox(canvas, bmapPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateBitmap --\n *\n *\tThis function is called to rotate a bitmap's origin by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the bitmap is rotated by angleRad radians about\n *\t(originX, originY), and the bounding box is updated in the generic\n *\tpart of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateBitmap(\n    Tk_Canvas canvas,\n    Tk_Item *itemPtr,\n    double originX,\n    double originY,\n    double angleRad)\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &bmapPtr->x, &bmapPtr->y);\n    ComputeBitmapBbox(canvas, bmapPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateBitmap --\n *\n *\tThis function is called to move an item by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the item is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateBitmap(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n\n    bmapPtr->x += deltaX;\n    bmapPtr->y += deltaY;\n    ComputeBitmapBbox(canvas, bmapPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * BitmapToPostscript --\n *\n *\tThis function is called to generate Postscript for bitmap items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nBitmapToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    TCL_UNUSED(int))\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;\n    double x, y;\n    int width, height, rowsAtOnce, rowsThisTime;\n    int curRow;\n    XColor *fgColor;\n    XColor *bgColor;\n    Pixmap bitmap;\n    Tk_State state = itemPtr->state;\n    Tcl_Obj *psObj;\n    Tcl_InterpState interpState;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    fgColor = bmapPtr->fgColor;\n    bgColor = bmapPtr->bgColor;\n    bitmap = bmapPtr->bitmap;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (bmapPtr->activeFgColor!=NULL) {\n\t    fgColor = bmapPtr->activeFgColor;\n\t}\n\tif (bmapPtr->activeBgColor!=NULL) {\n\t    bgColor = bmapPtr->activeBgColor;\n\t}\n\tif (bmapPtr->activeBitmap!=None) {\n\t    bitmap = bmapPtr->activeBitmap;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (bmapPtr->disabledFgColor!=NULL) {\n\t    fgColor = bmapPtr->disabledFgColor;\n\t}\n\tif (bmapPtr->disabledBgColor!=NULL) {\n\t    bgColor = bmapPtr->disabledBgColor;\n\t}\n\tif (bmapPtr->disabledBitmap!=None) {\n\t    bitmap = bmapPtr->disabledBitmap;\n\t}\n    }\n\n    if (bitmap == None) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Compute the coordinates of the lower-left corner of the bitmap, taking\n     * into account the anchor position for the bitmp.\n     */\n\n    x = bmapPtr->x;\n    y = Tk_CanvasPsY(canvas, bmapPtr->y);\n    Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,\n\t    &width, &height);\n    switch (bmapPtr->anchor) {\n    case TK_ANCHOR_NW:\t\t\t   y -= height;\t\tbreak;\n    case TK_ANCHOR_N:\t   x -= width/2.0; y -= height;\t\tbreak;\n    case TK_ANCHOR_NE:\t   x -= width;\t   y -= height;\t\tbreak;\n    case TK_ANCHOR_E:\t   x -= width;\t   y -= height/2.0;\tbreak;\n    case TK_ANCHOR_SE:\t   x -= width;\t\t\t\tbreak;\n    case TK_ANCHOR_S:\t   x -= width/2.0;\t\t\tbreak;\n    case TK_ANCHOR_SW:\t\t\t\t\t\tbreak;\n    case TK_ANCHOR_W:\t\t\t   y -= height/2.0;\tbreak;\n    default: x -= width/2.0; y -= height/2.0;\tbreak;\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Color the background, if there is one.\n     */\n\n    if (bgColor != NULL) {\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%.15g %.15g moveto %d 0 rlineto 0 %d rlineto \"\n\t\t\"%d 0 rlineto closepath\\n\",\n\t\tx, y, width, height, -width);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, bgColor);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tTcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n    }\n\n    /*\n     * Draw the bitmap, if there is a foreground color. If the bitmap is very\n     * large, then chop it up into multiple bitmaps, each consisting of one or\n     * more rows. This is needed because Postscript can't handle single\n     * strings longer than 64 KBytes long.\n     */\n\n    if (fgColor != NULL) {\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, fgColor);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (width > 60000) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't generate Postscript for bitmaps more than 60000\"\n\t\t    \" pixels wide\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"MEMLIMIT\", (char *)NULL);\n\t    goto error;\n\t}\n\n\trowsAtOnce = 60000/width;\n\tif (rowsAtOnce < 1) {\n\t    rowsAtOnce = 1;\n\t}\n\n\tTcl_AppendPrintfToObj(psObj, \"%.15g %.15g translate\\n\", x, y+height);\n\n\tfor (curRow = 0; curRow < height; curRow += rowsAtOnce) {\n\t    rowsThisTime = rowsAtOnce;\n\t    if (rowsThisTime > (height - curRow)) {\n\t\trowsThisTime = height - curRow;\n\t    }\n\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"0 -%.15g translate\\n%d %d true matrix {\\n\",\n\t\t    (double) rowsThisTime, width, rowsThisTime);\n\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsBitmap(interp, canvas, bitmap, 0, curRow, width,\n\t\t    rowsThisTime);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\t    Tcl_AppendToObj(psObj, \"\\n} imagemask\\n\", TCL_INDEX_NONE);\n\t}\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n\n  error:\n    Tcl_DiscardInterpState(interpState);\n    Tcl_DecrRefCount(psObj);\n    return TCL_ERROR;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvImg.c",
    "content": "/*\n * tkCanvImg.c --\n *\n *\tThis file implements image items for canvas widgets.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n\n/*\n * The structure below defines the record for each image item.\n */\n\ntypedef struct ImageItem  {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_Canvas canvas;\t\t/* Canvas containing the image. */\n    double x, y;\t\t/* Coordinates of positioning point for\n\t\t\t\t * image. */\n    Tk_Anchor anchor;\t\t/* Where to anchor image relative to (x,y). */\n    Tcl_Obj *imageObj;\t\t/* -image option.\n\t\t\t\t * NULL means no image right now. */\n    Tcl_Obj *activeImageObj;\t/* -activeimage option.\n\t\t\t\t * NULL means no image right now. */\n    Tcl_Obj *disabledImageObj;\t/* -disabledimage option.\n\t\t\t\t * NULL means no image right now. */\n    Tk_Image image;\t\t/* Image to display in window, or NULL if no\n\t\t\t\t * image at present. */\n    Tk_Image activeImage;\t/* Image to display in window, or NULL if no\n\t\t\t\t * image at present. */\n    Tk_Image disabledImage;\t/* Image to display in window, or NULL if no\n\t\t\t\t * image at present. */\n} ImageItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_STRING, \"-activeimage\", NULL, NULL,\n\tNULL, offsetof(ImageItem, activeImageObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_ANCHOR, \"-anchor\", NULL, NULL,\n\t\"center\", offsetof(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_STRING, \"-disabledimage\", NULL, NULL,\n\tNULL, offsetof(ImageItem, disabledImageObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_STRING, \"-image\", NULL, NULL,\n\tNULL, offsetof(ImageItem, imageObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tImageChangedProc(void *clientData,\n\t\t\t    int x, int y, int width, int height, int imgWidth,\n\t\t\t    int imgHeight);\nstatic int\t\tImageCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tImageToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tImageToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *coordPtr);\nstatic int\t\tImageToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic void\t\tComputeImageBbox(Tk_Canvas canvas, ImageItem *imgPtr);\nstatic int\t\tConfigureImage(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tCreateImage(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteImage(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayImage(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tRotateImage(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScaleImage(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateImage(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\n\n/*\n * The structures below defines the image item type in terms of functions that\n * can be invoked by generic item code.\n */\n\nTk_ItemType tkImageType = {\n    \"image\",\t\t\t/* name */\n    sizeof(ImageItem),\t\t/* itemSize */\n    CreateImage,\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureImage,\t\t/* configureProc */\n    ImageCoords,\t\t/* coordProc */\n    DeleteImage,\t\t/* deleteProc */\n    DisplayImage,\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    ImageToPoint,\t\t/* pointProc */\n    ImageToArea,\t\t/* areaProc */\n    ImageToPostscript,\t\t/* postscriptProc */\n    ScaleImage,\t\t\t/* scaleProc */\n    TranslateImage,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* icursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateImage,\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateImage --\n *\n *\tThis function is invoked to create a new image item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new image item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateImage(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing rectangle. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Initialize item's record.\n     */\n\n    imgPtr->canvas = canvas;\n    imgPtr->anchor = TK_ANCHOR_CENTER;\n    imgPtr->imageObj = NULL;\n    imgPtr->activeImageObj = NULL;\n    imgPtr->disabledImageObj = NULL;\n    imgPtr->image = NULL;\n    imgPtr->activeImage = NULL;\n    imgPtr->disabledImage = NULL;\n\n    /*\n     * Process the arguments to fill in the item record. Only 1 (list) or 2 (x\n     * y) coords are allowed.\n     */\n\n    if (objc == 1) {\n\ti = 1;\n    } else {\n\tconst char *arg = Tcl_GetString(objv[1]);\n\ti = 2;\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    i = 1;\n\t}\n    }\n    if ((ImageCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {\n\tgoto error;\n    }\n    if (ConfigureImage(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImageCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\timage items. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nImageCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    if (objc == 0) {\n\tTcl_Obj *objs[2];\n\n\tobjs[0] = Tcl_NewDoubleObj(imgPtr->x);\n\tobjs[1] = Tcl_NewDoubleObj(imgPtr->y);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, objs));\n    } else if (objc < 3) {\n\tif (objc==1) {\n\t    if (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t    (Tcl_Obj ***) &objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    } else if (objc != 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"wrong # coordinates: expected 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"IMAGE\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],\n\t\t    &imgPtr->x) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t    &imgPtr->y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tComputeImageBbox(canvas, imgPtr);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"IMAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureImage --\n *\n *\tThis function is invoked to configure various aspects of an image\n *\titem, such as its anchor position.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information may be set for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureImage(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Image item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv.  */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n    Tk_Window tkwin;\n    Tk_Image image;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, imgPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the image. Save the old image around and don't free it until\n     * after the new one is allocated. This keeps the reference count from\n     * going to zero so the image doesn't have to be recreated if it hasn't\n     * changed.\n     */\n\n    if (imgPtr->activeImageObj != NULL) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n    if (imgPtr->imageObj != NULL) {\n\timage = Tk_GetImage(interp, tkwin, Tcl_GetString(imgPtr->imageObj),\n\t\tImageChangedProc, imgPtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (imgPtr->image != NULL) {\n\tTk_FreeImage(imgPtr->image);\n    }\n    imgPtr->image = image;\n    if (imgPtr->activeImageObj != NULL) {\n\timage = Tk_GetImage(interp, tkwin, Tcl_GetString(imgPtr->activeImageObj),\n\t\tImageChangedProc, imgPtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (imgPtr->activeImage != NULL) {\n\tTk_FreeImage(imgPtr->activeImage);\n    }\n    imgPtr->activeImage = image;\n    if (imgPtr->disabledImageObj != NULL) {\n\timage = Tk_GetImage(interp, tkwin, Tcl_GetString(imgPtr->disabledImageObj),\n\t\tImageChangedProc, imgPtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (imgPtr->disabledImage != NULL) {\n\tTk_FreeImage(imgPtr->disabledImage);\n    }\n    imgPtr->disabledImage = image;\n    ComputeImageBbox(canvas, imgPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteImage --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta image item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteImage(\n    TCL_UNUSED(Tk_Canvas),\t/* Info about overall canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    TCL_UNUSED(Display *))\t/* Display containing window for canvas. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    if (imgPtr->imageObj != NULL) {\n\tTcl_DecrRefCount(imgPtr->imageObj);\n    }\n    if (imgPtr->activeImageObj != NULL) {\n\tTcl_DecrRefCount(imgPtr->activeImageObj);\n    }\n    if (imgPtr->disabledImageObj != NULL) {\n\tTcl_DecrRefCount(imgPtr->disabledImageObj);\n    }\n    if (imgPtr->image != NULL) {\n\tTk_FreeImage(imgPtr->image);\n    }\n    if (imgPtr->activeImage != NULL) {\n\tTk_FreeImage(imgPtr->activeImage);\n    }\n    if (imgPtr->disabledImage != NULL) {\n\tTk_FreeImage(imgPtr->disabledImage);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeImageBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a image item. This function is where the\n *\tchild image's placement is computed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeImageBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    ImageItem *imgPtr)\t\t/* Item whose bbox is to be recomputed. */\n{\n    int width, height;\n    int x, y;\n    Tk_Image image;\n    Tk_State state = imgPtr->header.state;\n\n    if(state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    image = imgPtr->image;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *)imgPtr) {\n\tif (imgPtr->activeImage != NULL) {\n\t    image = imgPtr->activeImage;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (imgPtr->disabledImage != NULL) {\n\t    image = imgPtr->disabledImage;\n\t}\n    }\n\n    x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5));\n    y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5));\n\n    if ((state == TK_STATE_HIDDEN) || (image == NULL)) {\n\timgPtr->header.x1 = imgPtr->header.x2 = x;\n\timgPtr->header.y1 = imgPtr->header.y2 = y;\n\treturn;\n    }\n\n    /*\n     * Compute location and size of image, using anchor information.\n     */\n\n    Tk_SizeOfImage(image, &width, &height);\n    switch (imgPtr->anchor) {\n    case TK_ANCHOR_N:\n\tx -= width/2;\n\tbreak;\n    case TK_ANCHOR_NE:\n\tx -= width;\n\tbreak;\n    case TK_ANCHOR_E:\n\tx -= width;\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_SE:\n\tx -= width;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_S:\n\tx -= width/2;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_SW:\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_W:\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_NW:\n\tbreak;\n    default:\n\tx -= width/2;\n\ty -= height/2;\n\tbreak;\n    }\n\n    /*\n     * Store the information in the item header.\n     */\n\n    imgPtr->header.x1 = x;\n    imgPtr->header.y1 = y;\n    imgPtr->header.x2 = x + width;\n    imgPtr->header.y2 = y + height;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayImage --\n *\n *\tThis function is invoked to draw a image item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayImage(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    TCL_UNUSED(Display *),\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    int x, int y, int width, int height)\n\t\t\t\t/* Describes region of canvas that must be\n\t\t\t\t * redisplayed (not used). */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n    short drawableX, drawableY;\n    Tk_Image image;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    image = imgPtr->image;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (imgPtr->activeImage != NULL) {\n\t    image = imgPtr->activeImage;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (imgPtr->disabledImage != NULL) {\n\t    image = imgPtr->disabledImage;\n\t}\n    }\n\n    if (image == NULL) {\n\treturn;\n    }\n\n    /*\n     * Translate the coordinates to those of the image, then redisplay it.\n     */\n\n    Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,\n\t    &drawableX, &drawableY);\n    Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1,\n\t    width, height, drawable, drawableX, drawableY);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImageToPoint --\n *\n *\tComputes the distance from a given point to a given rectangle, in\n *\tcanvas units.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the image. If the point isn't\n *\tinside the image then the return value is the distance from the point\n *\tto the image.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nImageToPoint(\n    TCL_UNUSED(Tk_Canvas),\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *coordPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n    double x1, x2, y1, y2, xDiff, yDiff;\n\n    x1 = imgPtr->header.x1;\n    y1 = imgPtr->header.y1;\n    x2 = imgPtr->header.x2;\n    y2 = imgPtr->header.y2;\n\n    /*\n     * Point is outside rectangle.\n     */\n\n    if (coordPtr[0] < x1) {\n\txDiff = x1 - coordPtr[0];\n    } else if (coordPtr[0] > x2)  {\n\txDiff = coordPtr[0] - x2;\n    } else {\n\txDiff = 0;\n    }\n\n    if (coordPtr[1] < y1) {\n\tyDiff = y1 - coordPtr[1];\n    } else if (coordPtr[1] > y2)  {\n\tyDiff = coordPtr[1] - y2;\n    } else {\n\tyDiff = 0;\n    }\n\n    return hypot(xDiff, yDiff);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImageToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangle.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nImageToArea(\n    TCL_UNUSED(Tk_Canvas),\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against rectangle. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates\n\t\t\t\t * (x1,y1,x2,y2) describing rectangular\n\t\t\t\t * area. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    if ((rectPtr[2] <= imgPtr->header.x1)\n\t    || (rectPtr[0] >= imgPtr->header.x2)\n\t    || (rectPtr[3] <= imgPtr->header.y1)\n\t    || (rectPtr[1] >= imgPtr->header.y2)) {\n\treturn -1;\n    }\n    if ((rectPtr[0] <= imgPtr->header.x1)\n\t    && (rectPtr[1] <= imgPtr->header.y1)\n\t    && (rectPtr[2] >= imgPtr->header.x2)\n\t    && (rectPtr[3] >= imgPtr->header.y2)) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImageToPostscript --\n *\n *\tThis function is called to generate Postscript for image items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in interp->result,\n *\treplacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nImageToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    int prepass)\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created.*/\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n    Tk_Window canvasWin = Tk_CanvasTkwin(canvas);\n    double x, y;\n    int width, height;\n    Tk_Image image;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    image = imgPtr->image;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (imgPtr->activeImage != NULL) {\n\t    image = imgPtr->activeImage;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (imgPtr->disabledImage != NULL) {\n\t    image = imgPtr->disabledImage;\n\t}\n    }\n    if (image == NULL) {\n\t/*\n\t * Image item without actual image specified.\n\t */\n\n\treturn TCL_OK;\n    }\n    Tk_SizeOfImage(image, &width, &height);\n\n    /*\n     * Compute the coordinates of the lower-left corner of the image, taking\n     * into account the anchor position for the image.\n     */\n\n    x = imgPtr->x;\n    y = Tk_CanvasPsY(canvas, imgPtr->y);\n\n    switch (imgPtr->anchor) {\n    case TK_ANCHOR_NW:\t\t\t   y -= height;\t\tbreak;\n    case TK_ANCHOR_N:\t   x -= width/2.0; y -= height;\t\tbreak;\n    case TK_ANCHOR_NE:\t   x -= width;\t   y -= height;\t\tbreak;\n    case TK_ANCHOR_E:\t   x -= width;\t   y -= height/2.0;\tbreak;\n    case TK_ANCHOR_SE:\t   x -= width;\t\t\t\tbreak;\n    case TK_ANCHOR_S:\t   x -= width/2.0;\t\t\tbreak;\n    case TK_ANCHOR_SW:\t\t\t\t\t\tbreak;\n    case TK_ANCHOR_W:\t\t\t   y -= height/2.0;\tbreak;\n    default: x -= width/2.0; y -= height/2.0;\tbreak;\n    }\n\n    if (!prepass) {\n\tTcl_Obj *psObj = Tcl_GetObjResult(interp);\n\n\tif (Tcl_IsShared(psObj)) {\n\t    psObj = Tcl_DuplicateObj(psObj);\n\t    Tcl_SetObjResult(interp, psObj);\n\t}\n\n\tTcl_AppendPrintfToObj(psObj, \"%.15g %.15g translate\\n\", x, y);\n    }\n\n    return Tk_PostscriptImage(image, interp, canvasWin,\n\t    ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateImage --\n *\n *\tThis function is called to rotate an image's origin by a given amount.\n *\tThis does *not* rotate the contents of the image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the image anchor is rotated by angleRad radians about\n *\t(originX, originY), and the bounding box is updated in the generic\n *\tpart of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateImage(\n    Tk_Canvas canvas,\n    Tk_Item *itemPtr,\n    double originX,\n    double originY,\n    double angleRad)\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &imgPtr->x, &imgPtr->y);\n    ComputeImageBbox(canvas, imgPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleImage --\n *\n *\tThis function is invoked to rescale an item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe item referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleImage(\n    Tk_Canvas canvas,\t\t/* Canvas containing rectangle. */\n    Tk_Item *itemPtr,\t\t/* Rectangle to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale rect. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    imgPtr->x = originX + scaleX*(imgPtr->x - originX);\n    imgPtr->y = originY + scaleY*(imgPtr->y - originY);\n    ComputeImageBbox(canvas, imgPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateImage --\n *\n *\tThis function is called to move an item by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the item is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateImage(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    ImageItem *imgPtr = (ImageItem *) itemPtr;\n\n    imgPtr->x += deltaX;\n    imgPtr->y += deltaY;\n    ComputeImageBbox(canvas, imgPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageChangedProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the image's size or how it is\n *\tdisplayed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the canvas to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageChangedProc(\n    void *clientData,\t/* Pointer to canvas item for image. */\n    int x, int y,\t\t/* Upper left pixel (within image) that must\n\t\t\t\t * be redisplayed. */\n    int width, int height,\t/* Dimensions of area to redisplay (may be <=\n\t\t\t\t * 0). */\n    int imgWidth, int imgHeight)/* New dimensions of image. */\n{\n    ImageItem *imgPtr = (ImageItem *)clientData;\n\n    /*\n     * If the image's size changed and it's not anchored at its northwest\n     * corner then just redisplay the entire area of the image. This is a bit\n     * over-conservative, but we need to do something because a size change\n     * also means a position change.\n     */\n\n    if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth)\n\t    || ((imgPtr->header.y2 - imgPtr->header.y1) != imgHeight)) {\n\tx = y = 0;\n\twidth = imgWidth;\n\theight = imgHeight;\n\tTk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,\n\t\timgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);\n    }\n    ComputeImageBbox(imgPtr->canvas, imgPtr);\n    Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,\n\t    imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),\n\t    (int) (imgPtr->header.y1 + y + height));\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvLine.c",
    "content": "/*\n * tkCanvLine.c --\n *\n *\tThis file implements line items for canvas widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The structure below defines the record for each line item.\n */\n\ntypedef enum {\n    ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH\n} Arrows;\n\ntypedef struct LineItem {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_Outline outline;\t\t/* Outline structure */\n    Tk_Canvas canvas;\t\t/* Canvas containing item. Needed for parsing\n\t\t\t\t * arrow shapes. */\n    Tcl_Size numPoints;\t\t/* Number of points in line (always >= 0). */\n    double *coordPtr;\t\t/* Pointer to malloc-ed array containing x-\n\t\t\t\t * and y-coords of all points in line.\n\t\t\t\t * X-coords are even-valued indices, y-coords\n\t\t\t\t * are corresponding odd-valued indices. If\n\t\t\t\t * the line has arrowheads then the first and\n\t\t\t\t * last points have been adjusted to refer to\n\t\t\t\t * the necks of the arrowheads rather than\n\t\t\t\t * their tips. The actual endpoints are stored\n\t\t\t\t * in the *firstArrowPtr and *lastArrowPtr, if\n\t\t\t\t * they exist. */\n    int capStyle;\t\t/* Cap style for line. */\n    int joinStyle;\t\t/* Join style for line. */\n    GC arrowGC;\t\t\t/* Graphics context for drawing arrowheads. */\n    Arrows arrow;\t\t/* Indicates whether or not to draw arrowheads:\n\t\t\t\t * \"none\", \"first\", \"last\", or \"both\". */\n    float arrowShapeA;\t\t/* Distance from tip of arrowhead to center. */\n    float arrowShapeB;\t\t/* Distance from tip of arrowhead to trailing\n\t\t\t\t * point, measured along shaft. */\n    float arrowShapeC;\t\t/* Distance of trailing points from outside\n\t\t\t\t * edge of shaft. */\n    double *firstArrowPtr;\t/* Points to array of PTS_IN_ARROW points\n\t\t\t\t * describing polygon for arrowhead at first\n\t\t\t\t * point in line. First point of arrowhead is\n\t\t\t\t * tip. Malloc'ed. NULL means no arrowhead at\n\t\t\t\t * first point. */\n    double *lastArrowPtr;\t/* Points to polygon for arrowhead at last\n\t\t\t\t * point in line (PTS_IN_ARROW points, first\n\t\t\t\t * of which is tip). Malloc'ed. NULL means no\n\t\t\t\t * arrowhead at last point. */\n    const Tk_SmoothMethod *smooth; /* Non-zero means draw line smoothed (i.e.\n\t\t\t\t * with Bezier splines). */\n    int splineSteps;\t\t/* Number of steps in each spline segment. */\n} LineItem;\n\n/*\n * Number of points in an arrowHead:\n */\n\n#define PTS_IN_ARROW 6\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic int\t\tArrowheadPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, LineItem *linePtr,\n\t\t\t    double *arrowPtr, Tcl_Obj *psObj);\nstatic void\t\tComputeLineBbox(Tk_Canvas canvas, LineItem *linePtr);\nstatic int\t\tConfigureLine(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tConfigureArrows(Tk_Canvas canvas, LineItem *linePtr);\nstatic int\t\tCreateLine(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteLine(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayLine(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic int\t\tGetLineIndex(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Obj *obj, Tcl_Size *indexPtr);\nstatic int\t\tLineCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tLineDeleteCoords(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size first, Tcl_Size last);\nstatic void\t\tLineInsert(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size beforeThis, Tcl_Obj *obj);\nstatic int\t\tLineToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tLineToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *coordPtr);\nstatic int\t\tLineToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic int\t\tArrowParseProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *value, char *recordPtr, Tcl_Size offset);\nstatic const char * ArrowPrintProc(void *clientData,\n\t\t\t    Tk_Window tkwin, char *recordPtr, Tcl_Size offset,\n\t\t\t    Tcl_FreeProc **freeProcPtr);\nstatic int\t\tParseArrowShape(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *value, char *recordPtr, Tcl_Size offset);\nstatic const char * PrintArrowShape(void *clientData,\n\t\t\t    Tk_Window tkwin, char *recordPtr, Tcl_Size offset,\n\t\t\t    Tcl_FreeProc **freeProcPtr);\nstatic void\t\tRotateLine(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScaleLine(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateLine(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\n\f\n/*\n * Information used for parsing configuration specs. If you change any of the\n * default strings, be sure to change the corresponding default values in\n * CreateLine.\n */\n\nstatic const Tk_CustomOption arrowShapeOption = {\n    ParseArrowShape, PrintArrowShape, NULL\n};\nstatic const Tk_CustomOption arrowOption = {\n    ArrowParseProc, ArrowPrintProc, NULL\n};\nstatic const Tk_CustomOption smoothOption = {\n    TkSmoothParseProc, TkSmoothPrintProc, NULL\n};\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\nstatic const Tk_CustomOption dashOption = {\n    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL\n};\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc,\n    INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)\n};\nstatic const Tk_CustomOption pixelOption = {\n    TkPixelParseProc, TkPixelPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_CUSTOM, \"-activedash\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.activeDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-activefill\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activestipple\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-activewidth\", NULL, NULL,\n\t\"0.0\", offsetof(LineItem, outline.activeWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_CUSTOM, \"-arrow\", NULL, NULL,\n\t\"none\", offsetof(LineItem, arrow),\n\tTK_CONFIG_DONT_SET_DEFAULT, &arrowOption},\n    {TK_CONFIG_CUSTOM, \"-arrowshape\", NULL, NULL,\n\t\"8 10 3\", offsetof(LineItem, arrowShapeA),\n\tTK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},\n    {TK_CONFIG_CAP_STYLE, \"-capstyle\", NULL, NULL,\n\t\"butt\", offsetof(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_COLOR, \"-fill\", NULL, NULL,\n\tDEF_CANVITEM_OUTLINE, offsetof(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-dash\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.dash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_PIXELS, \"-dashoffset\", NULL, NULL,\n\t\"0\", offsetof(LineItem, outline.offsetObj), TK_CONFIG_OBJS|TK_OPTION_NEG_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disableddash\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.disabledDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-disabledfill\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledstipple\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disabledwidth\", NULL, NULL,\n\t\"0.0\", offsetof(LineItem, outline.disabledWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_JOIN_STYLE, \"-joinstyle\", NULL, NULL,\n\t\"round\", offsetof(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", NULL, NULL,\n\t\"0,0\", offsetof(LineItem, outline.tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_CUSTOM, \"-smooth\", NULL, NULL,\n\t\"0\", offsetof(LineItem, smooth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &smoothOption},\n    {TK_CONFIG_INT, \"-splinesteps\", NULL, NULL,\n\t\"12\", offsetof(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_BITMAP, \"-stipple\", NULL, NULL,\n\tNULL, offsetof(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_CUSTOM, \"-width\", NULL, NULL,\n\t\"1.0\", offsetof(LineItem, outline.width),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * The structures below defines the line item type by means of functions that\n * can be invoked by generic item code.\n */\n\nTk_ItemType tkLineType = {\n    \"line\",\t\t\t\t/* name */\n    sizeof(LineItem),\t\t\t/* itemSize */\n    CreateLine,\t\t\t\t/* createProc */\n    configSpecs,\t\t\t/* configSpecs */\n    ConfigureLine,\t\t\t/* configureProc */\n    LineCoords,\t\t\t\t/* coordProc */\n    DeleteLine,\t\t\t\t/* deleteProc */\n    DisplayLine,\t\t\t/* displayProc */\n    TK_MOVABLE_POINTS,\t\t/* flags */\n    LineToPoint,\t\t\t/* pointProc */\n    LineToArea,\t\t\t\t/* areaProc */\n    LineToPostscript,\t\t\t/* postscriptProc */\n    ScaleLine,\t\t\t\t/* scaleProc */\n    TranslateLine,\t\t\t/* translateProc */\n    GetLineIndex,\t\t\t/* indexProc */\n    NULL,\t\t\t\t/* icursorProc */\n    NULL,\t\t\t\t/* selectionProc */\n    LineInsert,\t\t\t\t/* insertProc */\n    LineDeleteCoords,\t\t\t/* dTextProc */\n    NULL,\t\t\t\t/* nextPtr */\n    RotateLine,\t\t\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\n/*\n * The definition below determines how large are static arrays used to hold\n * spline points (splines larger than this have to have their arrays\n * malloc-ed).\n */\n\n#define MAX_STATIC_POINTS 200\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateLine --\n *\n *\tThis function is invoked to create a new line item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new line item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateLine(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing line. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Carry out initialization that is needed to set defaults and to allow\n     * proper cleanup after errors during the the remainder of this function.\n     */\n\n    Tk_CreateOutline(&linePtr->outline);\n    linePtr->canvas = canvas;\n    linePtr->numPoints = 0;\n    linePtr->coordPtr = NULL;\n    linePtr->capStyle = CapButt;\n    linePtr->joinStyle = JoinRound;\n    linePtr->arrowGC = NULL;\n    linePtr->arrow = ARROWS_NONE;\n    linePtr->arrowShapeA = (float)8.0;\n    linePtr->arrowShapeB = (float)10.0;\n    linePtr->arrowShapeC = (float)3.0;\n    linePtr->firstArrowPtr = NULL;\n    linePtr->lastArrowPtr = NULL;\n    linePtr->smooth = NULL;\n    linePtr->splineSteps = 12;\n\n    /*\n     * Count the number of points and then parse them into a point array.\n     * Leading arguments are assumed to be points if they start with a digit\n     * or a minus sign followed by a digit.\n     */\n\n    for (i = 1; i < objc; i++) {\n\tconst char *arg = Tcl_GetString(objv[i]);\n\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    break;\n\t}\n    }\n    if (LineCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {\n\tgoto error;\n    }\n    if (ConfigureLine(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\tlines. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nLineCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    Tcl_Size i, numPoints;\n    double *coordPtr;\n\n    if (objc == 0) {\n\tTcl_Size numCoords;\n\tTcl_Obj *subobj, *obj = Tcl_NewObj();\n\n\tnumCoords = 2*linePtr->numPoints;\n\tif (linePtr->firstArrowPtr != NULL) {\n\t    coordPtr = linePtr->firstArrowPtr;\n\t} else {\n\t    coordPtr = linePtr->coordPtr;\n\t}\n\tfor (i = 0; i < numCoords; i++, coordPtr++) {\n\t    if (i == 2) {\n\t\tcoordPtr = linePtr->coordPtr+2;\n\t    }\n\t    if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {\n\t\tcoordPtr = linePtr->lastArrowPtr;\n\t    }\n\t    subobj = Tcl_NewDoubleObj(*coordPtr);\n\t    Tcl_ListObjAppendElement(interp, obj, subobj);\n\t}\n\tTcl_SetObjResult(interp, obj);\n\treturn TCL_OK;\n    }\n    if (objc == 1) {\n\tif (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t(Tcl_Obj ***) &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (objc & 1) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected an even number, got %\" TCL_SIZE_MODIFIER \"d\",\n\t\tobjc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"LINE\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (objc < 4) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected at least 4, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"LINE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    numPoints = objc/2;\n    if (linePtr->numPoints != numPoints) {\n\tcoordPtr = (double *)Tcl_Alloc(sizeof(double) * objc);\n\tif (linePtr->coordPtr != NULL) {\n\t    Tcl_Free(linePtr->coordPtr);\n\t}\n\tlinePtr->coordPtr = coordPtr;\n\tlinePtr->numPoints = numPoints;\n    }\n    coordPtr = linePtr->coordPtr;\n    for (i = 0; i < objc ; i++) {\n\tif (Tk_CanvasGetCoordFromObj(interp, canvas, objv[i],\n\t\tcoordPtr++) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Update arrowheads by throwing away any existing arrow-head information\n     * and calling ConfigureArrows to recompute it.\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tTcl_Free(linePtr->firstArrowPtr);\n\tlinePtr->firstArrowPtr = NULL;\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tTcl_Free(linePtr->lastArrowPtr);\n\tlinePtr->lastArrowPtr = NULL;\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tConfigureArrows(canvas, linePtr);\n    }\n    ComputeLineBbox(canvas, linePtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureLine --\n *\n *\tThis function is invoked to configure various aspects of a line item\n *\tsuch as its background color.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as colors and stipple patterns, may be\n *\tset for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureLine(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Line item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC, arrowGC;\n    unsigned long mask;\n    Tk_Window tkwin;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, linePtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few of the options require additional processing, such as graphics\n     * contexts.\n     */\n\n    state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    if (linePtr->outline.activeWidth > linePtr->outline.width ||\n\t    linePtr->outline.activeDash.number != 0 ||\n\t    linePtr->outline.activeColor != NULL ||\n\t    linePtr->outline.activeStipple != None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n    mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &linePtr->outline);\n    if (mask) {\n\tif (linePtr->arrow == ARROWS_NONE) {\n\t    gcValues.cap_style = linePtr->capStyle;\n\t    mask |= GCCapStyle;\n\t}\n\tgcValues.join_style = linePtr->joinStyle;\n\tmask |= GCJoinStyle;\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n#ifdef MAC_OSX_TK\n\t/*\n\t * Mac OS X CG drawing needs access to linewidth even for arrow fills\n\t * (as linewidth controls antialiasing).\n\t */\n\n\tmask |= GCLineWidth;\n#else\n\tgcValues.line_width = 0;\n#endif\n\tarrowGC = Tk_GetGC(tkwin, mask, &gcValues);\n    } else {\n\tnewGC = arrowGC = NULL;\n    }\n    if (linePtr->outline.gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);\n    }\n    if (linePtr->arrowGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);\n    }\n    linePtr->outline.gc = newGC;\n    linePtr->arrowGC = arrowGC;\n\n    /*\n     * Keep spline parameters within reasonable limits.\n     */\n\n    if (linePtr->splineSteps < 1) {\n\tlinePtr->splineSteps = 1;\n    } else if (linePtr->splineSteps > 100) {\n\tlinePtr->splineSteps = 100;\n    }\n\n    if ((!linePtr->numPoints) || (state == TK_STATE_HIDDEN)) {\n\tComputeLineBbox(canvas, linePtr);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Setup arrowheads, if needed. If arrowheads are turned off, restore the\n     * line's endpoints (they were shortened when the arrowheads were added).\n     */\n\n    if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)\n\t    && (linePtr->arrow != ARROWS_BOTH)) {\n\tlinePtr->coordPtr[0] = linePtr->firstArrowPtr[0];\n\tlinePtr->coordPtr[1] = linePtr->firstArrowPtr[1];\n\tTcl_Free(linePtr->firstArrowPtr);\n\tlinePtr->firstArrowPtr = NULL;\n    }\n    if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)\n\t    && (linePtr->arrow != ARROWS_BOTH)) {\n\tTcl_Size i;\n\n\ti = 2*(linePtr->numPoints-1);\n\tlinePtr->coordPtr[i] = linePtr->lastArrowPtr[0];\n\tlinePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];\n\tTcl_Free(linePtr->lastArrowPtr);\n\tlinePtr->lastArrowPtr = NULL;\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tConfigureArrows(canvas, linePtr);\n    }\n\n    /*\n     * Recompute bounding box for line.\n     */\n\n    ComputeLineBbox(canvas, linePtr);\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteLine --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta line item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteLine(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Info about overall canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n\n    Tk_DeleteOutline(display, &linePtr->outline);\n    if (linePtr->coordPtr != NULL) {\n\tTcl_Free(linePtr->coordPtr);\n    }\n    if (linePtr->arrowGC != NULL) {\n\tTk_FreeGC(display, linePtr->arrowGC);\n    }\n    if (linePtr->firstArrowPtr != NULL) {\n\tTcl_Free(linePtr->firstArrowPtr);\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tTcl_Free(linePtr->lastArrowPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeLineBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a line.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeLineBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    LineItem *linePtr)\t\t/* Item whose bbos is to be recomputed. */\n{\n    double *coordPtr;\n    Tcl_Size i;\n    int intWidth;\n    double width;\n    Tk_State state = linePtr->header.state;\n    Tk_TSOffset *tsoffset;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    if (!(linePtr->numPoints) || (state == TK_STATE_HIDDEN)) {\n\tlinePtr->header.x1 = -1;\n\tlinePtr->header.x2 = -1;\n\tlinePtr->header.y1 = -1;\n\tlinePtr->header.y2 = -1;\n\treturn;\n    }\n\n    width = linePtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *)linePtr) {\n\tif (linePtr->outline.activeWidth > width) {\n\t    width = linePtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth > 0) {\n\t    width = linePtr->outline.disabledWidth;\n\t}\n    }\n\n    coordPtr = linePtr->coordPtr;\n    linePtr->header.x1 = linePtr->header.x2 = (int) coordPtr[0];\n    linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1];\n\n    /*\n     * Compute the bounding box of all the points in the line, then expand in\n     * all directions by the line's width to take care of butting or rounded\n     * corners and projecting or rounded caps. This expansion is an\n     * overestimate (worst-case is square root of two over two) but it's\n     * simple. Don't do anything special for curves. This causes an additional\n     * overestimate in the bounding box, but is faster.\n     */\n\n    for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints;\n\t    i++, coordPtr += 2) {\n\tTkIncludePoint((Tk_Item *) linePtr, coordPtr);\n    }\n    width = linePtr->outline.width;\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tif (linePtr->arrow != ARROWS_LAST && linePtr->firstArrowPtr) {\n\t    TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);\n\t}\n\tif (linePtr->arrow != ARROWS_FIRST && linePtr->lastArrowPtr) {\n\t    TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);\n\t}\n    }\n\n    tsoffset = &linePtr->outline.tsoffset;\n    if (tsoffset->flags & TK_OFFSET_INDEX) {\n\tcoordPtr = linePtr->coordPtr\n\t\t+ (tsoffset->flags & ~TK_OFFSET_INDEX);\n\n\tif (tsoffset->flags <= 0) {\n\t    coordPtr = linePtr->coordPtr;\n\t    if ((linePtr->arrow == ARROWS_FIRST)\n\t\t    || (linePtr->arrow == ARROWS_BOTH)) {\n\t\tcoordPtr = linePtr->firstArrowPtr;\n\t    }\n\t}\n\tif (tsoffset->flags > (int)(linePtr->numPoints * 2)) {\n\t    coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);\n\t    if ((linePtr->arrow == ARROWS_LAST)\n\t\t    || (linePtr->arrow == ARROWS_BOTH)) {\n\t\tcoordPtr = linePtr->lastArrowPtr;\n\t    }\n\t}\n\ttsoffset->xoffset = (int) (coordPtr[0] + 0.5);\n\ttsoffset->yoffset = (int) (coordPtr[1] + 0.5);\n    } else {\n\tif (tsoffset->flags & TK_OFFSET_LEFT) {\n\t    tsoffset->xoffset = linePtr->header.x1;\n\t} else if (tsoffset->flags & TK_OFFSET_CENTER) {\n\t    tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;\n\t} else if (tsoffset->flags & TK_OFFSET_RIGHT) {\n\t    tsoffset->xoffset = linePtr->header.x2;\n\t}\n\tif (tsoffset->flags & TK_OFFSET_TOP) {\n\t    tsoffset->yoffset = linePtr->header.y1;\n\t} else if (tsoffset->flags & TK_OFFSET_MIDDLE) {\n\t    tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;\n\t} else if (tsoffset->flags & TK_OFFSET_BOTTOM) {\n\t    tsoffset->yoffset = linePtr->header.y2;\n\t}\n    }\n\n    intWidth = (int) (width + 0.5);\n    linePtr->header.x1 -= intWidth;\n    linePtr->header.x2 += intWidth;\n    linePtr->header.y1 -= intWidth;\n    linePtr->header.y2 += intWidth;\n\n    if (linePtr->numPoints == 1) {\n\tlinePtr->header.x1 -= 1;\n\tlinePtr->header.x2 += 1;\n\tlinePtr->header.y1 -= 1;\n\tlinePtr->header.y2 += 1;\n\treturn;\n    }\n\n    /*\n     * For mitered lines, make a second pass through all the points. Compute\n     * the locations of the two miter vertex points and add those into the\n     * bounding box.\n     */\n\n    if (linePtr->joinStyle == JoinMiter) {\n\tfor (i = linePtr->numPoints, coordPtr = linePtr->coordPtr; i >= 3;\n\t\ti--, coordPtr += 2) {\n\t    double miter[4];\n\t    int j;\n\n\t    if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,\n\t\t    width, miter, miter+2)) {\n\t\tfor (j = 0; j < 4; j += 2) {\n\t\t    TkIncludePoint((Tk_Item *) linePtr, miter+j);\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Add in the sizes of arrowheads, if any.\n     */\n\n    if (linePtr->arrow != ARROWS_NONE) {\n\tif (linePtr->arrow != ARROWS_LAST) {\n\t    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint((Tk_Item *) linePtr, coordPtr);\n\t    }\n\t}\n\tif (linePtr->arrow != ARROWS_FIRST) {\n\t    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint((Tk_Item *) linePtr, coordPtr);\n\t    }\n\t}\n    }\n\n    /*\n     * Add one more pixel of fudge factor just to be safe (e.g. X may round\n     * differently than we do).\n     */\n\n    linePtr->header.x1 -= 1;\n    linePtr->header.x2 += 1;\n    linePtr->header.y1 -= 1;\n    linePtr->header.y2 += 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayLine --\n *\n *\tThis function is invoked to draw a line item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayLine(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    TCL_UNUSED(int),\t\t/* Describes region of canvas that must be */\n    TCL_UNUSED(int),\t\t/* redisplayed (not used). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    LineItem *linePtr = (LineItem *)itemPtr;\n    XPoint staticPoints[MAX_STATIC_POINTS*3];\n    XPoint *pointPtr;\n    double linewidth;\n    Tcl_Size numPoints;\n    Tk_State state = itemPtr->state;\n\n    if (!linePtr->numPoints || (linePtr->outline.gc == NULL)) {\n\treturn;\n    }\n\n    if (state == TK_STATE_NULL) {\n\t    state = Canvas(canvas)->canvas_state;\n    }\n    linewidth = linePtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (linePtr->outline.activeWidth != linewidth) {\n\t    linewidth = linePtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth != linewidth) {\n\t    linewidth = linePtr->outline.disabledWidth;\n\t}\n    }\n    /*\n     * Build up an array of points in screen coordinates. Use a static array\n     * unless the line has an enormous number of points; in this case,\n     * dynamically allocate an array. For smoothed lines, generate the curve\n     * points on each redisplay.\n     */\n\n    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {\n\tnumPoints = linePtr->smooth->coordProc(canvas, NULL,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, NULL);\n    } else {\n\tnumPoints = linePtr->numPoints;\n    }\n\n    if (numPoints <= MAX_STATIC_POINTS) {\n\tpointPtr = staticPoints;\n    } else {\n\tpointPtr = (XPoint *)Tcl_Alloc(numPoints * 3 * sizeof(XPoint));\n    }\n\n    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {\n\tnumPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, pointPtr, NULL);\n    } else {\n\tnumPoints = TkCanvTranslatePath((TkCanvas *) canvas, numPoints,\n\t\tlinePtr->coordPtr, 0, pointPtr);\n    }\n\n    /*\n     * Display line, the free up line storage if it was dynamically allocated.\n     * If we're stippling, then modify the stipple offset in the GC. Be sure\n     * to reset the offset when done, since the GC is supposed to be\n     * read-only.\n     */\n\n    if (Tk_ChangeOutlineGC(canvas, itemPtr, &linePtr->outline)) {\n\tTk_CanvasSetOffset(canvas, linePtr->arrowGC,\n\t\t&linePtr->outline.tsoffset);\n    }\n    if (numPoints > 1) {\n\tXDrawLines(display, drawable, linePtr->outline.gc, pointPtr, (int)numPoints,\n\t\tCoordModeOrigin);\n    } else {\n\tint intwidth = (int) (linewidth + 0.5);\n\n\tif (intwidth < 1) {\n\t    intwidth = 1;\n\t}\n\tXFillArc(display, drawable, linePtr->outline.gc,\n\t\tpointPtr->x - intwidth/2, pointPtr->y - intwidth/2,\n\t\t(unsigned) intwidth+1, (unsigned) intwidth+1, 0, 64*360);\n    }\n    if (pointPtr != staticPoints) {\n\tTcl_Free(pointPtr);\n    }\n\n    /*\n     * Display arrowheads, if they are wanted.\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tTkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,\n\t\tdisplay, drawable, linePtr->arrowGC, NULL);\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tTkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,\n\t\tdisplay, drawable, linePtr->arrowGC, NULL);\n    }\n    if (Tk_ResetOutlineGC(canvas, itemPtr, &linePtr->outline)) {\n\tXSetTSOrigin(display, linePtr->arrowGC, 0, 0);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineInsert --\n *\n *\tInsert coords into a line item at a given index.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe coords in the given item is modified.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nLineInsert(\n    Tk_Canvas canvas,\t\t/* Canvas containing text item. */\n    Tk_Item *itemPtr,\t\t/* Line item to be modified. */\n    Tcl_Size beforeThis,\t\t/* Index before which new coordinates are to\n\t\t\t\t * be inserted. */\n    Tcl_Obj *obj)\t\t/* New coordinates to be inserted. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    Tcl_Size length, oriNumPoints, objc, nbInsPoints, i;\n    double *newCoordPtr, *coordPtr;\n    Tk_State state = itemPtr->state;\n    Tcl_Obj **objv;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)\n\t    || !objc || objc&1) {\n\treturn;\n    }\n    oriNumPoints = linePtr->numPoints;\n    length = 2*linePtr->numPoints;\n    nbInsPoints = objc / 2;\n    if (beforeThis < 0) {\n\tbeforeThis = 0;\n    }\n    if (beforeThis > length) {\n\tbeforeThis = length;\n    }\n\n    /*\n     * With arrows, the end points of the line are adjusted so that a thick\n     * line doesn't stick out past the arrowheads (see ConfigureArrows).\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tlinePtr->coordPtr[0] = linePtr->firstArrowPtr[0];\n\tlinePtr->coordPtr[1] = linePtr->firstArrowPtr[1];\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tlinePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];\n\tlinePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];\n    }\n    newCoordPtr = (double *)Tcl_Alloc(sizeof(double) * (length + objc));\n    for (i=0; i<beforeThis; i++) {\n\tnewCoordPtr[i] = linePtr->coordPtr[i];\n    }\n    for (i=0; i<objc; i++) {\n\tif (Tcl_GetDoubleFromObj(NULL, objv[i],\n\t\t&newCoordPtr[i + beforeThis]) != TCL_OK) {\n\t    Tcl_ResetResult(Canvas(canvas)->interp);\n\t    Tcl_Free(newCoordPtr);\n\t    return;\n\t}\n    }\n\n    for (i=beforeThis; i<length; i++) {\n\tnewCoordPtr[i+objc] = linePtr->coordPtr[i];\n    }\n    if (linePtr->coordPtr) {\n\tTcl_Free(linePtr->coordPtr);\n    }\n    linePtr->coordPtr = newCoordPtr;\n    length += objc ;\n    linePtr->numPoints = length / 2;\n\n    if ((length > 3) && (state != TK_STATE_HIDDEN)) {\n\t/*\n\t * This is some optimizing code that will result that only the part of\n\t * the line that changed (and the objects that are overlapping with\n\t * that part) need to be redrawn. A special flag is set that instructs\n\t * the general canvas code not to redraw the whole object. If this\n\t * flag is not set, the canvas will do the redrawing, otherwise I have\n\t * to do it here.\n\t * Rationale for the optimization code can be found in Tk ticket\n\t * [5fb8145997].\n\t */\n\n\titemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;\n\n\t/*\n\t * Include one point at left of the left insert position, and one\n\t * point at right of the right insert position.\n\t */\n\n\tbeforeThis -= 2;\n\tobjc += 4;\n\n\tif (linePtr->smooth) {\n\t    if (!strcmp(linePtr->smooth->name, \"true\")) {\n\t\t/*\n\t\t * Quadratic Bezier splines. A second point must be included at\n\t\t * each side of the insert position.\n\t\t */\n\n\t\tbeforeThis -= 2;\n\t\tobjc += 4;\n\n\t\t/*\n\t\t * Moreover, if the insert position is the first or last point\n\t\t * of the line, include a third point.\n\t\t */\n\n\t\tif (beforeThis == -4) {\n\t\t    objc += 2;\n\t\t}\n\t\tif (beforeThis + 4 == length - (objc - 8)) {\n\t\t    beforeThis -= 2;\n\t\t    objc += 2;\n\t\t}\n\n\t    } else if (!strcmp(linePtr->smooth->name, \"raw\")) {\n\t\t/*\n\t\t * Cubic Bezier splines. See details in ticket [5fb8145997].\n\t\t */\n\n\t\tif (((oriNumPoints - 1) % 3) || (nbInsPoints % 3)) {\n\t\t    /*\n\t\t     * No optimization for \"degenerate\" lines or when inserting\n\t\t     * something else than a multiple of 3 points.\n\t\t     */\n\n\t\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t\t} else {\n\t\t    beforeThis -= beforeThis % 6;\n\t\t    objc += 4;\n\t\t}\n\n\t    } else {\n\t\t/*\n\t\t * Custom smoothing method. No optimization is possible.\n\t\t */\n\n\t\titemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    }\n\t}\n\n\tif (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {\n\t    if (beforeThis < 0) {\n\t\tbeforeThis = 0;\n\t    }\n\t    if (beforeThis + objc > length) {\n\t\tobjc = length - beforeThis;\n\t    }\n\n\t    itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];\n\t    itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];\n\t    if ((linePtr->firstArrowPtr != NULL) && (beforeThis < 2)) {\n\t\t/*\n\t\t * Include old first arrow.\n\t\t */\n\n\t\tfor (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\t\ti++, coordPtr += 2) {\n\t\t    TkIncludePoint(itemPtr, coordPtr);\n\t\t}\n\t    }\n\t    if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc >= length)) {\n\t\t/*\n\t\t * Include old last arrow.\n\t\t */\n\n\t\tfor (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\t\ti++, coordPtr += 2) {\n\t\t    TkIncludePoint(itemPtr, coordPtr);\n\t\t}\n\t    }\n\t    coordPtr = linePtr->coordPtr + beforeThis;\n\t    for (i=0; i<objc; i+=2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t\tcoordPtr += 2;\n\t    }\n\t}\n    }\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tTcl_Free(linePtr->firstArrowPtr);\n\tlinePtr->firstArrowPtr = NULL;\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tTcl_Free(linePtr->lastArrowPtr);\n\tlinePtr->lastArrowPtr = NULL;\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tConfigureArrows(canvas, linePtr);\n    }\n\n    if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {\n\tdouble width;\n\tint intWidth;\n\n\tif ((linePtr->firstArrowPtr != NULL) && (beforeThis < 2)) {\n\t    /*\n\t     * Include new first arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\tif ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc >= length)) {\n\t    /*\n\t     * Include new last arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\twidth = linePtr->outline.width;\n\tif (Canvas(canvas)->currentItemPtr == itemPtr) {\n\t    if (linePtr->outline.activeWidth > width) {\n\t\twidth = linePtr->outline.activeWidth;\n\t    }\n\t} else if (state == TK_STATE_DISABLED) {\n\t    if (linePtr->outline.disabledWidth > 0) {\n\t\twidth = linePtr->outline.disabledWidth;\n\t    }\n\t}\n\tintWidth = (int) (width + 0.5);\n\tif (intWidth < 1) {\n\t    intWidth = 1;\n\t}\n\titemPtr->x1 -= intWidth;\n\titemPtr->y1 -= intWidth;\n\titemPtr->x2 += intWidth;\n\titemPtr->y2 += intWidth;\n\tTk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,\n\t\titemPtr->x2, itemPtr->y2);\n    }\n\n    ComputeLineBbox(canvas, linePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineDeleteCoords --\n *\n *\tDelete one or more coordinates from a line item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCharacters between \"first\" and \"last\", inclusive, get deleted from\n *\titemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nLineDeleteCoords(\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Item in which to delete characters. */\n    Tcl_Size first,\t\t\t/* Index of first character to delete. */\n    Tcl_Size last)\t\t\t/* Index of last character to delete. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    Tcl_Size count, i, first1, last1, nbDelPoints;\n    Tcl_Size oriNumPoints = linePtr->numPoints;\n    bool canOptimize = true;\n    Tcl_Size length = 2*linePtr->numPoints;\n    double *coordPtr;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    first &= -2;\t/* If odd, make it even. */\n    last &= -2;\n\n    if (first < 0) {\n\tfirst = 0;\n    }\n    if (last >= length) {\n\tlast = length - 2;\n    }\n    if (first > last) {\n\treturn;\n    }\n\n    /*\n     * With arrows, the end points of the line are adjusted so that a thick\n     * line doesn't stick out past the arrowheads (see ConfigureArrows).\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tlinePtr->coordPtr[0] = linePtr->firstArrowPtr[0];\n\tlinePtr->coordPtr[1] = linePtr->firstArrowPtr[1];\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tlinePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];\n\tlinePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];\n    }\n    first1 = first;\n    last1 = last;\n    nbDelPoints = (last - first) / 2 + 1;\n\n    /*\n     * Include one point at left of the left delete position, and one\n     * point at right of the right delete position.\n     */\n\n    first1 -= 2;\n    last1 += 2;\n\n    if (linePtr->smooth) {\n\n\tif (!strcmp(linePtr->smooth->name, \"true\")) {\n\t    /*\n\t     * Quadratic Bezier splines. A second point must be included at\n\t     * each side of the delete position.\n\t     */\n\n\t    first1 -= 2;\n\t    last1 += 2;\n\n\t    /*\n\t     * If the delete position is the first or last point of the line,\n\t     * include a third point.\n\t     */\n\n\t    if (first1 == -4) {\n\t\tlast1 += 2;\n\t    }\n\t    if (last1 - 4 == length - 2) {\n\t\tfirst1 -= 2;\n\t    }\n\n\t} else if (!strcmp(linePtr->smooth->name, \"raw\")) {\n\t    /*\n\t     * Cubic Bezier splines. See details in ticket [5fb8145997].\n\t     */\n\n\t    if (((oriNumPoints - 1) % 3) || (nbDelPoints % 3)) {\n\t\t/*\n\t\t * No optimization for \"degenerate\" lines or when deleting\n\t\t * something else than a multiple of 3 points.\n\t\t */\n\n\t\tcanOptimize = false;\n\t    }\n\t    else {\n\t\tfirst1 -= first1 % 6;\n\t\tlast1 = last + 6 - last % 6;\n\t    }\n\n\t} else {\n\t    /*\n\t     * Custom smoothing method. No optimization is possible.\n\t     */\n\n\t    canOptimize = false;\n\t}\n    }\n\n    if (first1 < 0) {\n\tfirst1 = 0;\n    }\n    if (last1 >= length) {\n\tlast1 = length - 2;\n    }\n\n    if (canOptimize && ((first1 >= 2) || (last1 < length-2))) {\n\t/*\n\t * This is some optimizing code that will result that only the part of\n\t * the line that changed (and the objects that are overlapping with\n\t * that part) need to be redrawn. A special flag is set that instructs\n\t * the general canvas code not to redraw the whole object. If this\n\t * flag is set, the redrawing has to be done here, otherwise the\n\t * general Canvas code will take care of it.\n\t * Rationale for the optimization code can be found in Tk ticket\n\t * [5fb8145997].\n\t */\n\n\titemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;\n\titemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];\n\titemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];\n\tif ((linePtr->firstArrowPtr != NULL) && (first1 < 2)) {\n\t    /*\n\t     * Include old first arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\tif ((linePtr->lastArrowPtr != NULL) && (last1 >= length - 2)) {\n\t    /*\n\t     * Include old last arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\tcoordPtr = linePtr->coordPtr+first1+2;\n\tfor (i=first1+2; i<=last1; i+=2) {\n\t    TkIncludePoint(itemPtr, coordPtr);\n\t    coordPtr += 2;\n\t}\n    }\n\n    count = last + 2 - first;\n    for (i=last+2; i<length; i++) {\n\tlinePtr->coordPtr[i-count] = linePtr->coordPtr[i];\n    }\n    linePtr->numPoints -= count/2;\n    if (linePtr->firstArrowPtr != NULL) {\n\tTcl_Free(linePtr->firstArrowPtr);\n\tlinePtr->firstArrowPtr = NULL;\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tTcl_Free(linePtr->lastArrowPtr);\n\tlinePtr->lastArrowPtr = NULL;\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tConfigureArrows(canvas, linePtr);\n    }\n    if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {\n\tdouble width;\n\tint intWidth;\n\n\tif ((linePtr->firstArrowPtr != NULL) && (first1 < 2)) {\n\t    /*\n\t     * Include new first arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\tif ((linePtr->lastArrowPtr != NULL) && (last1 >= length - 2)) {\n\t    /*\n\t     * Include new last arrow.\n\t     */\n\n\t    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\t    i++, coordPtr += 2) {\n\t\tTkIncludePoint(itemPtr, coordPtr);\n\t    }\n\t}\n\twidth = linePtr->outline.width;\n\tif (Canvas(canvas)->currentItemPtr == itemPtr) {\n\t    if (linePtr->outline.activeWidth > width) {\n\t\twidth = linePtr->outline.activeWidth;\n\t    }\n\t} else if (state == TK_STATE_DISABLED) {\n\t    if (linePtr->outline.disabledWidth > 0) {\n\t\twidth = linePtr->outline.disabledWidth;\n\t    }\n\t}\n\tintWidth = (int) (width + 0.5);\n\tif (intWidth < 1) {\n\t    intWidth = 1;\n\t}\n\titemPtr->x1 -= intWidth;\n\titemPtr->y1 -= intWidth;\n\titemPtr->x2 += intWidth;\n\titemPtr->y2 += intWidth;\n\tTk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,\n\t\titemPtr->x2, itemPtr->y2);\n    }\n    ComputeLineBbox(canvas, linePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineToPoint --\n *\n *\tComputes the distance from a given point to a given line, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tpointPtr[0] and pointPtr[1] is inside the line. If the point isn't\n *\tinside the line then the return value is the distance from the point\n *\tto the line.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nLineToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    Tk_State state = itemPtr->state;\n    LineItem *linePtr = (LineItem *) itemPtr;\n    double *coordPtr, *linePoints;\n    double staticSpace[2*MAX_STATIC_POINTS];\n    double poly[10];\n    double bestDist, dist, width;\n    Tcl_Size numPoints, count;\n    bool changedMiterToBevel;\t/* true means that a mitered corner had to\n\t\t\t\t * be treated as beveled after all because the\n\t\t\t\t * angle was < 11 degrees. */\n\n    bestDist = 1.0e36;\n\n    /*\n     * Handle smoothed lines by generating an expanded set of points against\n     * which to do the check.\n     */\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = linePtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (linePtr->outline.activeWidth > width) {\n\t    width = linePtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth > 0) {\n\t    width = linePtr->outline.disabledWidth;\n\t}\n    }\n\n    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {\n\tnumPoints = linePtr->smooth->coordProc(canvas, NULL,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, NULL);\n\tif (numPoints <= MAX_STATIC_POINTS) {\n\t    linePoints = staticSpace;\n\t} else {\n\t    linePoints = (double *)Tcl_Alloc(2 * numPoints * sizeof(double));\n\t}\n\tnumPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);\n    } else {\n\tnumPoints = linePtr->numPoints;\n\tlinePoints = linePtr->coordPtr;\n    }\n\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n\n    if (!numPoints || itemPtr->state == TK_STATE_HIDDEN) {\n\treturn bestDist;\n    } else if (numPoints == 1) {\n\tbestDist = hypot(linePoints[0]-pointPtr[0], linePoints[1]-pointPtr[1])\n\t\t- width/2.0;\n\tif (bestDist < 0) {\n\t    bestDist = 0;\n\t}\n\treturn bestDist;\n    }\n\n    /*\n     * The overall idea is to iterate through all of the edges of the line,\n     * computing a polygon for each edge and testing the point against that\n     * polygon. In addition, there are additional tests to deal with rounded\n     * joints and caps.\n     */\n\n    changedMiterToBevel = false;\n    for (count = numPoints, coordPtr = linePoints; count >= 2;\n\t    count--, coordPtr += 2) {\n\t/*\n\t * If rounding is done around the first point then compute the\n\t * distance between the point and the point.\n\t */\n\n\tif (((linePtr->capStyle == CapRound) && (count == numPoints))\n\t\t|| ((linePtr->joinStyle == JoinRound)\n\t\t\t&& (count != numPoints))) {\n\t    dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])\n\t\t    - width/2.0;\n\t    if (dist <= 0.0) {\n\t\tbestDist = 0.0;\n\t\tgoto done;\n\t    } else if (dist < bestDist) {\n\t\tbestDist = dist;\n\t    }\n\t}\n\n\t/*\n\t * Compute the polygonal shape corresponding to this edge, consisting\n\t * of two points for the first point of the edge and two points for\n\t * the last point of the edge.\n\t */\n\n\tif (count == numPoints) {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width,\n\t\t    linePtr->capStyle == CapProjecting, poly, poly+2);\n\t} else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {\n\t    poly[0] = poly[6];\n\t    poly[1] = poly[7];\n\t    poly[2] = poly[4];\n\t    poly[3] = poly[5];\n\t} else {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);\n\n\t    /*\n\t     * If this line uses beveled joints, then check the distance to a\n\t     * polygon comprising the last two points of the previous polygon\n\t     * and the first two from this polygon; this checks the wedges\n\t     * that fill the mitered joint.\n\t     */\n\n\t    if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) {\n\t\tpoly[8] = poly[0];\n\t\tpoly[9] = poly[1];\n\t\tdist = TkPolygonToPoint(poly, 5, pointPtr);\n\t\tif (dist <= 0.0) {\n\t\t    bestDist = 0.0;\n\t\t    goto done;\n\t\t} else if (dist < bestDist) {\n\t\t    bestDist = dist;\n\t\t}\n\t\tchangedMiterToBevel = false;\n\t    }\n\t}\n\tif (count == 2) {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width,\n\t\t    linePtr->capStyle == CapProjecting, poly+4, poly+6);\n\t} else if (linePtr->joinStyle == JoinMiter) {\n\t    if (!TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,\n\t\t    width, poly+4, poly+6)) {\n\t\tchangedMiterToBevel = true;\n\t\tTkGetButtPoints(coordPtr, coordPtr+2, width, 0,\n\t\t\tpoly+4, poly+6);\n\t    }\n\t} else {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width, 0,\n\t\t    poly+4, poly+6);\n\t}\n\tpoly[8] = poly[0];\n\tpoly[9] = poly[1];\n\tdist = TkPolygonToPoint(poly, 5, pointPtr);\n\tif (dist <= 0.0) {\n\t    bestDist = 0.0;\n\t    goto done;\n\t} else if (dist < bestDist) {\n\t    bestDist = dist;\n\t}\n    }\n\n    /*\n     * If caps are rounded, check the distance to the cap around the final end\n     * point of the line.\n     */\n\n    if (linePtr->capStyle == CapRound) {\n\tdist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])\n\t\t- width/2.0;\n\tif (dist <= 0.0) {\n\t    bestDist = 0.0;\n\t    goto done;\n\t} else if (dist < bestDist) {\n\t    bestDist = dist;\n\t}\n    }\n\n    /*\n     * If there are arrowheads, check the distance to the arrowheads.\n     */\n\n    if (linePtr->arrow != ARROWS_NONE) {\n\tif (linePtr->arrow != ARROWS_LAST) {\n\t    dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,\n\t\t    pointPtr);\n\t    if (dist <= 0.0) {\n\t\tbestDist = 0.0;\n\t\tgoto done;\n\t    } else if (dist < bestDist) {\n\t\tbestDist = dist;\n\t    }\n\t}\n\tif (linePtr->arrow != ARROWS_FIRST) {\n\t    dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,\n\t\t    pointPtr);\n\t    if (dist <= 0.0) {\n\t\tbestDist = 0.0;\n\t\tgoto done;\n\t    } else if (dist < bestDist) {\n\t\tbestDist = dist;\n\t    }\n\t}\n    }\n\n  done:\n    if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {\n\tTcl_Free(linePoints);\n    }\n    return bestDist;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area, 0 if it\n *\toverlaps, and 1 if it is entirely inside the given area.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nLineToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against line. */\n    double *rectPtr)\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    double staticSpace[2*MAX_STATIC_POINTS];\n    double *linePoints;\n    Tcl_Size numPoints;\n\tint result;\n    double radius, width;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    width = linePtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (linePtr->outline.activeWidth > width) {\n\t    width = linePtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth > 0) {\n\t    width = linePtr->outline.disabledWidth;\n\t}\n    }\n\n    radius = (width+1.0)/2.0;\n\n    if ((state == TK_STATE_HIDDEN) || !linePtr->numPoints) {\n\treturn -1;\n    } else if (linePtr->numPoints == 1) {\n\tdouble oval[4];\n\n\toval[0] = linePtr->coordPtr[0]-radius;\n\toval[1] = linePtr->coordPtr[1]-radius;\n\toval[2] = linePtr->coordPtr[0]+radius;\n\toval[3] = linePtr->coordPtr[1]+radius;\n\treturn TkOvalToArea(oval, rectPtr);\n    }\n\n    /*\n     * Handle smoothed lines by generating an expanded set of points against\n     * which to do the check.\n     */\n\n    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {\n\tnumPoints = linePtr->smooth->coordProc(canvas, NULL,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, NULL);\n\tif (numPoints <= MAX_STATIC_POINTS) {\n\t    linePoints = staticSpace;\n\t} else {\n\t    linePoints = (double *)Tcl_Alloc(2 * numPoints * sizeof(double));\n\t}\n\tnumPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);\n    } else {\n\tnumPoints = linePtr->numPoints;\n\tlinePoints = linePtr->coordPtr;\n    }\n\n    /*\n     * Check the segments of the line.\n     */\n\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n\n    result = TkThickPolyLineToArea(linePoints, numPoints, width,\n\t    linePtr->capStyle, linePtr->joinStyle, rectPtr);\n    if (result == 0) {\n\tgoto done;\n    }\n\n    /*\n     * Check arrowheads, if any.\n     */\n\n    if (linePtr->arrow != ARROWS_NONE) {\n\tif (linePtr->arrow != ARROWS_LAST) {\n\t    if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,\n\t\t    rectPtr) != result) {\n\t\tresult = 0;\n\t\tgoto done;\n\t    }\n\t}\n\tif (linePtr->arrow != ARROWS_FIRST) {\n\t    if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,\n\t\t    rectPtr) != result) {\n\t\tresult = 0;\n\t\tgoto done;\n\t    }\n\t}\n    }\n\n  done:\n    if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {\n\tTcl_Free(linePoints);\n    }\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleLine --\n *\n *\tThis function is invoked to rescale a line item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe line referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleLine(\n    Tk_Canvas canvas,\t\t/* Canvas containing line. */\n    Tk_Item *itemPtr,\t\t/* Line to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale rect. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    double *coordPtr;\n    Tcl_Size i;\n\n    /*\n     * Delete any arrowheads before scaling all the points (so that the\n     * end-points of the line get restored).\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tlinePtr->coordPtr[0] = linePtr->firstArrowPtr[0];\n\tlinePtr->coordPtr[1] = linePtr->firstArrowPtr[1];\n\tTcl_Free(linePtr->firstArrowPtr);\n\tlinePtr->firstArrowPtr = NULL;\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\ti = 2*(linePtr->numPoints-1);\n\tlinePtr->coordPtr[i] = linePtr->lastArrowPtr[0];\n\tlinePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];\n\tTcl_Free(linePtr->lastArrowPtr);\n\tlinePtr->lastArrowPtr = NULL;\n    }\n    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;\n\t    i++, coordPtr += 2) {\n\tcoordPtr[0] = originX + scaleX*(*coordPtr - originX);\n\tcoordPtr[1] = originY + scaleY*(coordPtr[1] - originY);\n    }\n    if (linePtr->arrow != ARROWS_NONE) {\n\tConfigureArrows(canvas, linePtr);\n    }\n    ComputeLineBbox(canvas, linePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetLineIndex --\n *\n *\tParse an index into a line item and return either its value or an\n *\terror.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the index (into itemPtr) corresponding to string. Otherwise an\n *\terror message is left in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetLineIndex(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *obj,\t\t/* Specification of a particular coord in\n\t\t\t\t * itemPtr's line. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted index. */\n{\n    Tcl_Size idx, length;\n    LineItem *linePtr = (LineItem *) itemPtr;\n    char *string;\n\n    if (TCL_OK == TkGetIntForIndex(obj, 2*linePtr->numPoints - 1, 1, &idx)) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else if (idx > (2 * linePtr->numPoints)) {\n\t    idx = 2 * linePtr->numPoints;\n\t} else {\n\t    idx &= (Tcl_Size)-2;\t/* If index is odd, make it even. */\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetStringFromObj(obj, &length);\n\n    if (string[0] == '@') {\n\tTcl_Size i;\n\tdouble x, y, bestDist, dist, *coordPtr;\n\tchar savechar;\n\tchar *p, *sep;\n\n\tp = string+1;\n\tsep = strchr(p, ',');\n\tif (!sep) {\n\t    goto badIndex;\n\t}\n\tsavechar = *sep;\n\t*sep = '\\0';\n\ti = Tcl_GetDouble(NULL, p, &x);\n\t*sep = savechar;\n\tif (i != TCL_OK) {\n\t    goto badIndex;\n\t}\n\tp = sep+1;\n\ti = Tcl_GetDouble(NULL, p, &y);\n\tif (i != TCL_OK) {\n\t    goto badIndex;\n\t}\n\tbestDist = 1.0e36;\n\tcoordPtr = linePtr->coordPtr;\n\t*indexPtr = 0;\n\tfor (i=0; i<linePtr->numPoints; i++) {\n\t    dist = hypot(coordPtr[0] - x, coordPtr[1] - y);\n\t    if (dist < bestDist) {\n\t\tbestDist = dist;\n\t\t*indexPtr = 2*i;\n\t    }\n\t    coordPtr += 2;\n\t}\n    } else {\n    badIndex:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad index \\\"%s\\\"\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ITEM_INDEX\", \"LINE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateLine --\n *\n *\tThis function is called to move a line by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the line is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateLine(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    double *coordPtr;\n    Tcl_Size i;\n\n    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;\n\t    i++, coordPtr += 2) {\n\tcoordPtr[0] += deltaX;\n\tcoordPtr[1] += deltaY;\n    }\n    if (linePtr->firstArrowPtr != NULL) {\n\tfor (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\ti++, coordPtr += 2) {\n\t    coordPtr[0] += deltaX;\n\t    coordPtr[1] += deltaY;\n\t}\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tfor (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\ti++, coordPtr += 2) {\n\t    coordPtr[0] += deltaX;\n\t    coordPtr[1] += deltaY;\n\t}\n    }\n    ComputeLineBbox(canvas, linePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateLine --\n *\n *\tThis function is called to rotate a line by a given amount about a\n *\tpoint.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the line is rotated by angleRad about (originX,\n *\toriginY), and the bounding box is updated in the generic part of the\n *\titem structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateLine(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double originX, double originY,\n    double angleRad)\t\t/* Amount by which item is to be rotated. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    double *coordPtr;\n    Tcl_Size i;\n    double s = sin(angleRad), c = cos(angleRad);\n\n    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;\n\t    i++, coordPtr += 2) {\n\tTkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);\n    }\n    if (linePtr->firstArrowPtr != NULL) {\n\tfor (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;\n\t\ti++, coordPtr += 2) {\n\t    TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);\n\t}\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tfor (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;\n\t\ti++, coordPtr += 2) {\n\t    TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);\n\t}\n    }\n    ComputeLineBbox(canvas, linePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ParseArrowShape --\n *\n *\tThis function is called back during option parsing to parse arrow\n *\tshape information.\n *\n * Results:\n *\tThe return value is a standard Tcl result: TCL_OK means that the arrow\n *\tshape information was parsed ok, and TCL_ERROR means it couldn't be\n *\tparsed.\n *\n * Side effects:\n *\tArrow information in recordPtr is updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nParseArrowShape(\n    TCL_UNUSED(void *),\t/* Not used. */\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TCL_UNUSED(Tk_Window),\t\t/* Not used. */\n    const char *value,\t\t/* Textual specification of arrow shape. */\n    char *recordPtr,\t\t/* Pointer to item record in which to store\n\t\t\t\t * arrow information. */\n    Tcl_Size offset)\t\t\t/* Offset of shape information in widget\n\t\t\t\t * record. */\n{\n    LineItem *linePtr = (LineItem *) recordPtr;\n    double a, b, c;\n    Tcl_Size argc;\n    const char **argv = NULL;\n\n    if ((size_t)offset != offsetof(LineItem, arrowShapeA)) {\n\tTcl_Panic(\"ParseArrowShape received bogus offset\");\n    }\n\n    if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {\n\tgoto syntaxError;\n    } else if (argc != 3) {\n\tgoto syntaxError;\n    }\n    if ((Tk_CanvasGetCoord(interp, linePtr->canvas, argv[0], &a) != TCL_OK)\n\t    || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[1], &b)\n\t\t!= TCL_OK)\n\t    || (Tk_CanvasGetCoord(interp, linePtr->canvas, argv[2], &c)\n\t\t!= TCL_OK)) {\n\tgoto syntaxError;\n    }\n\n    linePtr->arrowShapeA = (float) a;\n    linePtr->arrowShapeB = (float) b;\n    linePtr->arrowShapeC = (float) c;\n    Tcl_Free(argv);\n    return TCL_OK;\n\n  syntaxError:\n    Tcl_ResetResult(interp);\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad arrow shape \\\"%s\\\": must be list with three numbers\",\n\t    value));\n    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ARROW_SHAPE\", (char *)NULL);\n    if (argv != NULL) {\n\tTcl_Free(argv);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PrintArrowShape --\n *\n *\tThis function is a callback invoked by the configuration code to\n *\treturn a printable value describing an arrow shape.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic const char *\nPrintArrowShape(\n    TCL_UNUSED(void *),\t/* Not used. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window associated with linePtr's widget. */\n    char *recordPtr,\t\t/* Pointer to item record containing current\n\t\t\t\t * shape information. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Offset of arrow information in record. */\n    Tcl_FreeProc **freeProcPtr)\t/* Store address of function to call to free\n\t\t\t\t * string here. */\n{\n    LineItem *linePtr = (LineItem *) recordPtr;\n    char *buffer = (char *)Tcl_Alloc(120);\n\n    snprintf(buffer, 120, \"%.5g %.5g %.5g\", linePtr->arrowShapeA,\n\t    linePtr->arrowShapeB, linePtr->arrowShapeC);\n    *freeProcPtr = TCL_DYNAMIC;\n    return buffer;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArrowParseProc --\n *\n *\tThis function is invoked during option processing to handle the\n *\t\"-arrow\" option.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe arrow for a given item gets replaced by the arrow indicated in the\n *\tvalue argument.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nArrowParseProc(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    int c;\n    size_t length;\n    Arrows *arrowPtr = (Arrows *) (widgRec + offset);\n\n    if (value == NULL || *value == 0) {\n\t*arrowPtr = ARROWS_NONE;\n\treturn TCL_OK;\n    }\n\n    c = value[0];\n    length = strlen(value);\n\n    if ((c == 'n') && (strncmp(value, \"none\", length) == 0)) {\n\t*arrowPtr = ARROWS_NONE;\n\treturn TCL_OK;\n    }\n    if ((c == 'f') && (strncmp(value, \"first\", length) == 0)) {\n\t*arrowPtr = ARROWS_FIRST;\n\treturn TCL_OK;\n    }\n    if ((c == 'l') && (strncmp(value, \"last\", length) == 0)) {\n\t*arrowPtr = ARROWS_LAST;\n\treturn TCL_OK;\n    }\n    if ((c == 'b') && (strncmp(value, \"both\", length) == 0)) {\n\t*arrowPtr = ARROWS_BOTH;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad arrow spec \\\"%s\\\": must be none, first, last, or both\",\n\t    value));\n    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ARROW\", (char *)NULL);\n    *arrowPtr = ARROWS_NONE;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArrowPrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-arrow\" configuration option.\n *\n * Results:\n *\tThe return value is a string describing the arrows for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic const char *\nArrowPrintProc(\n    TCL_UNUSED(void *),\t/* Ignored. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset into item. */\n    TCL_UNUSED(Tcl_FreeProc **))\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    Arrows *arrowPtr = (Arrows *) (widgRec + offset);\n\n    switch (*arrowPtr) {\n    case ARROWS_FIRST:\n\treturn \"first\";\n    case ARROWS_LAST:\n\treturn \"last\";\n    case ARROWS_BOTH:\n\treturn \"both\";\n    default:\n\treturn \"none\";\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureArrows --\n *\n *\tIf arrowheads have been requested for a line, this function makes\n *\tarrangements for the arrowheads.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tInformation in linePtr is set up for one or two arrowheads. The\n *\tfirstArrowPtr and lastArrowPtr polygons are allocated and initialized,\n *\tif need be, and the end points of the line are adjusted so that a\n *\tthick line doesn't stick out past the arrowheads.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureArrows(\n    Tk_Canvas canvas,\t\t/* Canvas in which arrows will be displayed\n\t\t\t\t * (interp and tkwin fields are needed). */\n    LineItem *linePtr)\t\t/* Item to configure for arrows. */\n{\n    double *poly, *coordPtr;\n    double dx, dy, length, sinTheta, cosTheta, temp;\n    double fracHeight;\t\t/* Line width as fraction of arrowhead\n\t\t\t\t * width. */\n    double backup;\t\t/* Distance to backup end points so the line\n\t\t\t\t * ends in the middle of the arrowhead. */\n    double vertX, vertY;\t/* Position of arrowhead vertex. */\n    double shapeA, shapeB, shapeC;\n\t\t\t\t/* Adjusted coordinates (see explanation\n\t\t\t\t * below). */\n    double width;\n    Tk_State state = linePtr->header.state;\n\n    if (linePtr->numPoints < 2) {\n\treturn TCL_OK;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = linePtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *)linePtr) {\n\tif (linePtr->outline.activeWidth > width) {\n\t    width = linePtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth > 0) {\n\t    width = linePtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * The code below makes a tiny increase in the shape parameters for the\n     * line. This is a bit of a hack, but it seems to result in displays that\n     * more closely approximate the specified parameters. Without the\n     * adjustment, the arrows come out smaller than expected.\n     */\n\n    shapeA = linePtr->arrowShapeA + 0.001;\n    shapeB = linePtr->arrowShapeB + 0.001;\n    shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;\n\n    /*\n     * If there's an arrowhead on the first point of the line, compute its\n     * polygon and adjust the first point of the line so that the line doesn't\n     * stick out past the leading edge of the arrowhead.\n     */\n\n    fracHeight = (width/2.0)/shapeC;\n    backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;\n    if (linePtr->arrow != ARROWS_LAST) {\n\tpoly = linePtr->firstArrowPtr;\n\tif (poly == NULL) {\n\t    poly = (double *)Tcl_Alloc(2 * PTS_IN_ARROW * sizeof(double));\n\t    poly[0] = poly[10] = linePtr->coordPtr[0];\n\t    poly[1] = poly[11] = linePtr->coordPtr[1];\n\t    linePtr->firstArrowPtr = poly;\n\t}\n\tdx = poly[0] - linePtr->coordPtr[2];\n\tdy = poly[1] - linePtr->coordPtr[3];\n\tlength = hypot(dx, dy);\n\tif (length == 0) {\n\t    sinTheta = cosTheta = 0.0;\n\t} else {\n\t    sinTheta = dy/length;\n\t    cosTheta = dx/length;\n\t}\n\tvertX = poly[0] - shapeA*cosTheta;\n\tvertY = poly[1] - shapeA*sinTheta;\n\ttemp = shapeC*sinTheta;\n\tpoly[2] = poly[0] - shapeB*cosTheta + temp;\n\tpoly[8] = poly[2] - 2*temp;\n\ttemp = shapeC*cosTheta;\n\tpoly[3] = poly[1] - shapeB*sinTheta - temp;\n\tpoly[9] = poly[3] + 2*temp;\n\tpoly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);\n\tpoly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);\n\tpoly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);\n\tpoly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);\n\n\t/*\n\t * Polygon done. Now move the first point towards the second so that\n\t * the corners at the end of the line are inside the arrowhead.\n\t */\n\n\tlinePtr->coordPtr[0] = poly[0] - backup*cosTheta;\n\tlinePtr->coordPtr[1] = poly[1] - backup*sinTheta;\n    }\n\n    /*\n     * Similar arrowhead calculation for the last point of the line.\n     */\n\n    if (linePtr->arrow != ARROWS_FIRST) {\n\tcoordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);\n\tpoly = linePtr->lastArrowPtr;\n\tif (poly == NULL) {\n\t    poly = (double *)Tcl_Alloc(2 * PTS_IN_ARROW * sizeof(double));\n\t    poly[0] = poly[10] = coordPtr[2];\n\t    poly[1] = poly[11] = coordPtr[3];\n\t    linePtr->lastArrowPtr = poly;\n\t}\n\tdx = poly[0] - coordPtr[0];\n\tdy = poly[1] - coordPtr[1];\n\tlength = hypot(dx, dy);\n\tif (length == 0) {\n\t    sinTheta = cosTheta = 0.0;\n\t} else {\n\t    sinTheta = dy/length;\n\t    cosTheta = dx/length;\n\t}\n\tvertX = poly[0] - shapeA*cosTheta;\n\tvertY = poly[1] - shapeA*sinTheta;\n\ttemp = shapeC * sinTheta;\n\tpoly[2] = poly[0] - shapeB*cosTheta + temp;\n\tpoly[8] = poly[2] - 2*temp;\n\ttemp = shapeC * cosTheta;\n\tpoly[3] = poly[1] - shapeB*sinTheta - temp;\n\tpoly[9] = poly[3] + 2*temp;\n\tpoly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);\n\tpoly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight);\n\tpoly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight);\n\tpoly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight);\n\tcoordPtr[2] = poly[0] - backup*cosTheta;\n\tcoordPtr[3] = poly[1] - backup*sinTheta;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * LineToPostscript --\n *\n *\tThis function is called to generate Postscript for line items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nLineToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    TCL_UNUSED(int))\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    LineItem *linePtr = (LineItem *) itemPtr;\n    int style;\n    double width;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state = itemPtr->state;\n    Tcl_Obj *psObj;\n    Tcl_InterpState interpState;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = linePtr->outline.width;\n    color = linePtr->outline.color;\n    stipple = linePtr->outline.stipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (linePtr->outline.activeWidth > width) {\n\t    width = linePtr->outline.activeWidth;\n\t}\n\tif (linePtr->outline.activeColor != NULL) {\n\t    color = linePtr->outline.activeColor;\n\t}\n\tif (linePtr->outline.activeStipple != None) {\n\t    stipple = linePtr->outline.activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.disabledWidth > 0) {\n\t    width = linePtr->outline.disabledWidth;\n\t}\n\tif (linePtr->outline.disabledColor != NULL) {\n\t    color = linePtr->outline.disabledColor;\n\t}\n\tif (linePtr->outline.disabledStipple != None) {\n\t    stipple = linePtr->outline.disabledStipple;\n\t}\n    }\n\n    if (color == NULL || linePtr->numPoints < 1 || linePtr->coordPtr == NULL){\n\treturn TCL_OK;\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Check if we're just doing a \"pixel\".\n     */\n\n    if (linePtr->numPoints == 1) {\n\tTcl_AppendToObj(psObj, \"matrix currentmatrix\\n\", TCL_INDEX_NONE);\n\tTcl_AppendPrintfToObj(psObj, \"%.15g %.15g translate %.15g %.15g\",\n\t\tlinePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),\n\t\twidth/2.0, width/2.0);\n\tTcl_AppendToObj(psObj,\n\t\t\" scale 1 0 moveto 0 0 1 0 360 arc\\nsetmatrix\\n\", TCL_INDEX_NONE);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, color);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (stipple != None) {\n\t    Tcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsStipple(interp, canvas, stipple);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t}\n\tgoto done;\n    }\n\n    /*\n     * Generate a path for the line's center-line (do this differently for\n     * straight lines and smoothed lines).\n     */\n\n    Tcl_ResetResult(interp);\n    if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {\n\tTk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);\n    } else if ((stipple == None) && linePtr->smooth->postscriptProc) {\n\tlinePtr->smooth->postscriptProc(interp, canvas, linePtr->coordPtr,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps);\n    } else {\n\t/*\n\t * Special hack: Postscript printers don't appear to be able to turn a\n\t * path drawn with \"curveto\"s into a clipping path without exceeding\n\t * resource limits, so TkMakeBezierPostscript won't work for stippled\n\t * curves. Instead, generate all of the intermediate points here and\n\t * output them into the Postscript file with \"lineto\"s instead.\n\t */\n\n\tdouble staticPoints[2*MAX_STATIC_POINTS];\n\tdouble *pointPtr;\n\tint numPoints;\n\n\tnumPoints = linePtr->smooth->coordProc(canvas, NULL,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, NULL);\n\tpointPtr = staticPoints;\n\tif (numPoints > MAX_STATIC_POINTS) {\n\t    pointPtr = (double *)Tcl_Alloc(numPoints * 2 * sizeof(double));\n\t}\n\tnumPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,\n\t\t(int)linePtr->numPoints, linePtr->splineSteps, NULL, pointPtr);\n\tTk_CanvasPsPath(interp, canvas, pointPtr, numPoints);\n\tif (pointPtr != staticPoints) {\n\t    Tcl_Free(pointPtr);\n\t}\n    }\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n    /*\n     * Set other line-drawing parameters and stroke out the line.\n     */\n\n    if (linePtr->capStyle == CapRound) {\n\tstyle = 1;\n    } else if (linePtr->capStyle == CapProjecting) {\n\tstyle = 2;\n    } else {\n\tstyle = 0;\n    }\n    Tcl_AppendPrintfToObj(psObj, \"%d setlinecap\\n\", style);\n    if (linePtr->joinStyle == JoinRound) {\n\tstyle = 1;\n    } else if (linePtr->joinStyle == JoinBevel) {\n\tstyle = 2;\n    } else {\n\tstyle = 0;\n    }\n    Tcl_AppendPrintfToObj(psObj, \"%d setlinejoin\\n\", style);\n\n    Tcl_ResetResult(interp);\n    Tk_CanvasPsOutline(canvas, itemPtr, &linePtr->outline);\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n    /*\n     * Output polygons for the arrowheads, if there are any.\n     */\n\n    if (linePtr->firstArrowPtr != NULL) {\n\tif (stipple != None) {\n\t    Tcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\t}\n\tArrowheadPostscript(interp, canvas, linePtr,\n\t\tlinePtr->firstArrowPtr, psObj);\n    }\n    if (linePtr->lastArrowPtr != NULL) {\n\tif (stipple != None) {\n\t    Tcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\t}\n\tArrowheadPostscript(interp, canvas, linePtr,\n\t\tlinePtr->lastArrowPtr, psObj);\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n  done:\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArrowheadPostscript --\n *\n *\tThis function is called to generate Postscript for an arrowhead for a\n *\tline item.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the arrowhead is appended to the given object.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nArrowheadPostscript(\n    Tcl_Interp *interp,\t\t/* Leave error message here; non-error results\n\t\t\t\t * will be discarded by caller. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    LineItem *linePtr,\t\t/* Line item for which Postscript is being\n\t\t\t\t * generated. */\n    double *arrowPtr,\t\t/* Pointer to first of five points describing\n\t\t\t\t * arrowhead polygon. */\n    Tcl_Obj *psObj)\t\t/* Append postscript to this object. */\n{\n    Pixmap stipple;\n    Tk_State state = linePtr->header.state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    stipple = linePtr->outline.stipple;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) linePtr) {\n\tif (linePtr->outline.activeStipple!=None) {\n\t    stipple = linePtr->outline.activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (linePtr->outline.activeStipple!=None) {\n\t    stipple = linePtr->outline.disabledStipple;\n\t}\n    }\n\n    Tcl_ResetResult(interp);\n    Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n    if (stipple != None) {\n\tTcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsStipple(interp, canvas, stipple);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n    } else {\n\tTcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvPoly.c",
    "content": "/*\n * tkCanvPoly.c --\n *\n *\tThis file implements polygon items for canvas widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Ajuba Solutions.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n/*\n * The structure below defines the record for each polygon item.\n */\n\ntypedef struct PolygonItem  {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_Outline outline;\t\t/* Outline structure */\n    Tcl_Size numPoints;\t\t/* Number of points in polygon. Polygon is\n\t\t\t\t * always closed. */\n    Tcl_Size pointsAllocated;\t/* Number of points for which space is\n\t\t\t\t * allocated at *coordPtr. */\n    double *coordPtr;\t\t/* Pointer to malloc-ed array containing x-\n\t\t\t\t * and y-coords of all points in polygon.\n\t\t\t\t * X-coords are even-valued indices, y-coords\n\t\t\t\t * are corresponding odd-valued indices. */\n    int joinStyle;\t\t/* Join style for outline */\n    Tk_TSOffset tsoffset;\n    XColor *fillColor;\t\t/* Foreground color for polygon. */\n    XColor *activeFillColor;\t/* Foreground color for polygon if state is\n\t\t\t\t * active. */\n    XColor *disabledFillColor;\t/* Foreground color for polygon if state is\n\t\t\t\t * disabled. */\n    Pixmap fillStipple;\t\t/* Stipple bitmap for filling polygon. */\n    Pixmap activeFillStipple;\t/* Stipple bitmap for filling polygon if state\n\t\t\t\t * is active. */\n    Pixmap disabledFillStipple;\t/* Stipple bitmap for filling polygon if state\n\t\t\t\t * is disabled. */\n    GC fillGC;\t\t\t/* Graphics context for filling polygon. */\n    const Tk_SmoothMethod *smooth; /* Non-zero means draw shape smoothed (i.e.\n\t\t\t\t * with Bezier splines). */\n    int splineSteps;\t\t/* Number of steps in each spline segment. */\n    int autoClosed;\t\t/* Zero means the given polygon was closed,\n\t\t\t\t   one means that we auto closed it. */\n} PolygonItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption smoothOption = {\n    TkSmoothParseProc, TkSmoothPrintProc, NULL\n};\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\nstatic const Tk_CustomOption dashOption = {\n    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL\n};\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc,\n    INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)\n};\nstatic const Tk_CustomOption pixelOption = {\n    TkPixelParseProc, TkPixelPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_CUSTOM, \"-activedash\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.activeDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-activefill\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-activeoutline\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activeoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.activeStipple),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activestipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-activewidth\", NULL, NULL,\n\t\"0.0\", offsetof(PolygonItem, outline.activeWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_CUSTOM, \"-dash\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.dash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_PIXELS, \"-dashoffset\", NULL, NULL,\n\t\"0\", offsetof(PolygonItem, outline.offsetObj), TK_CONFIG_OBJS|TK_OPTION_NEG_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disableddash\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.disabledDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-disabledfill\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-disabledoutline\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.disabledColor),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.disabledStipple),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledstipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disabledwidth\", NULL, NULL,\n\t\"0.0\", offsetof(PolygonItem, outline.disabledWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_COLOR, \"-fill\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_JOIN_STYLE, \"-joinstyle\", NULL, NULL,\n\t\"round\", offsetof(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", NULL, NULL,\n\t\"0,0\", offsetof(PolygonItem, tsoffset),\n\tTK_CONFIG_NULL_OK, &offsetOption},\n    {TK_CONFIG_COLOR, \"-outline\", NULL, NULL,\n\tDEF_CANVITEM_OUTLINE, offsetof(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-outlineoffset\", NULL, NULL,\n\t\"0,0\", offsetof(PolygonItem, outline.tsoffset),\n\tTK_CONFIG_NULL_OK, &offsetOption},\n    {TK_CONFIG_BITMAP, \"-outlinestipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-smooth\", NULL, NULL,\n\t\"0\", offsetof(PolygonItem, smooth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &smoothOption},\n    {TK_CONFIG_INT, \"-splinesteps\", NULL, NULL,\n\t\"12\", offsetof(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_BITMAP, \"-stipple\", NULL, NULL,\n\tNULL, offsetof(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_CUSTOM, \"-width\", NULL, NULL,\n\t\"1.0\", offsetof(PolygonItem, outline.width),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tComputePolygonBbox(Tk_Canvas canvas,\n\t\t\t    PolygonItem *polyPtr);\nstatic int\t\tConfigurePolygon(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tCreatePolygon(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeletePolygon(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr,  Display *display);\nstatic void\t\tDisplayPolygon(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic int\t\tGetPolygonIndex(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Obj *obj, Tcl_Size *indexPtr);\nstatic int\t\tPolygonCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tPolygonDeleteCoords(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size first, Tcl_Size last);\nstatic void\t\tPolygonInsert(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size beforeThis, Tcl_Obj *obj);\nstatic int\t\tPolygonToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tPolygonToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *pointPtr);\nstatic int\t\tPolygonToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic void\t\tRotatePolygon(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScalePolygon(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslatePolygon(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\n\n/*\n * The structures below defines the polygon item type by means of functions\n * that can be invoked by generic item code.\n */\n\nTk_ItemType tkPolygonType = {\n    \"polygon\",\t\t\t\t/* name */\n    sizeof(PolygonItem),\t\t/* itemSize */\n    CreatePolygon,\t\t\t/* createProc */\n    configSpecs,\t\t\t/* configSpecs */\n    ConfigurePolygon,\t\t\t/* configureProc */\n    PolygonCoords,\t\t\t/* coordProc */\n    DeletePolygon,\t\t\t/* deleteProc */\n    DisplayPolygon,\t\t\t/* displayProc */\n    TK_MOVABLE_POINTS,\t\t/* flags */\n    PolygonToPoint,\t\t\t/* pointProc */\n    PolygonToArea,\t\t\t/* areaProc */\n    PolygonToPostscript,\t\t/* postscriptProc */\n    ScalePolygon,\t\t\t/* scaleProc */\n    TranslatePolygon,\t\t\t/* translateProc */\n    GetPolygonIndex,\t/* indexProc */\n    NULL,\t\t\t\t/* icursorProc */\n    NULL,\t\t\t\t/* selectionProc */\n    PolygonInsert,\t\t/* insertProc */\n    PolygonDeleteCoords,\t\t/* dTextProc */\n    NULL,\t\t\t\t/* nextPtr */\n    RotatePolygon,\t\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\n/*\n * The definition below determines how large are static arrays used to hold\n * spline points (splines larger than this have to have their arrays\n * malloc-ed).\n */\n\n#define MAX_STATIC_POINTS 200\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreatePolygon --\n *\n *\tThis function is invoked to create a new polygon item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new polygon item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreatePolygon(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing polygon. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Carry out initialization that is needed in order to clean up after\n     * errors during the the remainder of this function.\n     */\n\n    Tk_CreateOutline(&polyPtr->outline);\n    polyPtr->numPoints = 0;\n    polyPtr->pointsAllocated = 0;\n    polyPtr->coordPtr = NULL;\n    polyPtr->joinStyle = JoinRound;\n    polyPtr->tsoffset.flags = 0;\n    polyPtr->tsoffset.xoffset = 0;\n    polyPtr->tsoffset.yoffset = 0;\n    polyPtr->fillColor = NULL;\n    polyPtr->activeFillColor = NULL;\n    polyPtr->disabledFillColor = NULL;\n    polyPtr->fillStipple = None;\n    polyPtr->activeFillStipple = None;\n    polyPtr->disabledFillStipple = None;\n    polyPtr->fillGC = NULL;\n    polyPtr->smooth = NULL;\n    polyPtr->splineSteps = 12;\n    polyPtr->autoClosed = 0;\n\n    /*\n     * Count the number of points and then parse them into a point array.\n     * Leading arguments are assumed to be points if they start with a digit\n     * or a minus sign followed by a digit.\n     */\n\n    for (i = 0; i < objc; i++) {\n\tconst char *arg = Tcl_GetString(objv[i]);\n\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    break;\n\t}\n    }\n    if (i && PolygonCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {\n\tgoto error;\n    }\n\n    if (ConfigurePolygon(interp, canvas, itemPtr, objc-i, objv+i, 0)\n\t    == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeletePolygon(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\tpolygons. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nPolygonCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    Tcl_Size i, numPoints;\n\n    if (objc == 0) {\n\t/*\n\t * Print the coords used to create the polygon. If we auto closed the\n\t * polygon then we don't report the last point.\n\t */\n\n\tTcl_Obj *subobj, *obj = Tcl_NewObj();\n\n\tfor (i = 0; i < 2*(polyPtr->numPoints - polyPtr->autoClosed); i++) {\n\t    subobj = Tcl_NewDoubleObj(polyPtr->coordPtr[i]);\n\t    Tcl_ListObjAppendElement(interp, obj, subobj);\n\t}\n\tTcl_SetObjResult(interp, obj);\n\treturn TCL_OK;\n    }\n    if (objc == 1) {\n\tif (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t(Tcl_Obj ***) &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (objc & 1) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected an even number, got %\" TCL_SIZE_MODIFIER \"d\",\n\t\tobjc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"POLYGON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    numPoints = objc/2;\n    if (polyPtr->pointsAllocated <= numPoints) {\n\tif (polyPtr->coordPtr != NULL) {\n\t    Tcl_Free(polyPtr->coordPtr);\n\t}\n\n\t/*\n\t * One extra point gets allocated here, because we always add\n\t * another point to close the polygon.\n\t */\n\n\tpolyPtr->coordPtr = (double *)Tcl_Alloc(sizeof(double) * (objc+2));\n\tpolyPtr->pointsAllocated = numPoints+1;\n    }\n    for (i = objc-1; i >= 0; i--) {\n\tif (Tk_CanvasGetCoordFromObj(interp, canvas, objv[i],\n\t\t&polyPtr->coordPtr[i]) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    polyPtr->numPoints = numPoints;\n    polyPtr->autoClosed = 0;\n\n    /*\n     * Close the polygon if it isn't already closed.\n     */\n\n    if (objc>2 && ((polyPtr->coordPtr[objc-2] != polyPtr->coordPtr[0])\n\t    || (polyPtr->coordPtr[objc-1] != polyPtr->coordPtr[1]))) {\n\tpolyPtr->autoClosed = 1;\n\tpolyPtr->numPoints++;\n\tpolyPtr->coordPtr[objc] = polyPtr->coordPtr[0];\n\tpolyPtr->coordPtr[objc+1] = polyPtr->coordPtr[1];\n    }\n\n    ComputePolygonBbox(canvas, polyPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigurePolygon --\n *\n *\tThis function is invoked to configure various aspects of a polygon\n *\titem such as its background color.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as colors and stipple patterns, may be\n *\tset for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigurePolygon(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Polygon item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv.  */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC;\n    unsigned long mask;\n    Tk_Window tkwin;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, polyPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few of the options require additional processing, such as graphics\n     * contexts.\n     */\n\n    state = itemPtr->state;\n\n    if (polyPtr->outline.activeWidth > polyPtr->outline.width ||\n\t    polyPtr->outline.activeDash.number != 0 ||\n\t    polyPtr->outline.activeColor != NULL ||\n\t    polyPtr->outline.activeStipple != None ||\n\t    polyPtr->activeFillColor != NULL ||\n\t    polyPtr->activeFillStipple != None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (state == TK_STATE_HIDDEN) {\n\tComputePolygonBbox(canvas, polyPtr);\n\treturn TCL_OK;\n    }\n\n    mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &polyPtr->outline);\n    if (mask) {\n\tgcValues.cap_style = CapRound;\n\tgcValues.join_style = polyPtr->joinStyle;\n\tmask |= GCCapStyle|GCJoinStyle;\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    } else {\n\tnewGC = NULL;\n    }\n    if (polyPtr->outline.gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), polyPtr->outline.gc);\n    }\n    polyPtr->outline.gc = newGC;\n\n    color = polyPtr->fillColor;\n    stipple = polyPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (polyPtr->activeFillColor != NULL) {\n\t    color = polyPtr->activeFillColor;\n\t}\n\tif (polyPtr->activeFillStipple != None) {\n\t    stipple = polyPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->disabledFillColor != NULL) {\n\t    color = polyPtr->disabledFillColor;\n\t}\n\tif (polyPtr->disabledFillStipple != None) {\n\t    stipple = polyPtr->disabledFillStipple;\n\t}\n    }\n\n    if (color == NULL) {\n\tnewGC = NULL;\n    } else {\n\tgcValues.foreground = color->pixel;\n\tmask = GCForeground;\n\tif (stipple != None) {\n\t    gcValues.stipple = stipple;\n\t    gcValues.fill_style = FillStippled;\n\t    mask |= GCStipple|GCFillStyle;\n\t}\n#ifdef MAC_OSX_TK\n\t/*\n\t * Mac OS X CG drawing needs access to the outline linewidth\n\t * even for fills (as linewidth controls antialiasing).\n\t */\n\tgcValues.line_width = polyPtr->outline.gc != NULL ?\n\t\tpolyPtr->outline.gc->line_width : 0;\n\tmask |= GCLineWidth;\n#endif\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    }\n    if (polyPtr->fillGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), polyPtr->fillGC);\n    }\n    polyPtr->fillGC = newGC;\n\n    /*\n     * Keep spline parameters within reasonable limits.\n     */\n\n    if (polyPtr->splineSteps < 1) {\n\tpolyPtr->splineSteps = 1;\n    } else if (polyPtr->splineSteps > 100) {\n\tpolyPtr->splineSteps = 100;\n    }\n\n    ComputePolygonBbox(canvas, polyPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeletePolygon --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta polygon item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeletePolygon(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Info about overall canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n\n    Tk_DeleteOutline(display, &polyPtr->outline);\n    if (polyPtr->coordPtr != NULL) {\n\tTcl_Free(polyPtr->coordPtr);\n    }\n    if (polyPtr->fillColor != NULL) {\n\tTk_FreeColor(polyPtr->fillColor);\n    }\n    if (polyPtr->activeFillColor != NULL) {\n\tTk_FreeColor(polyPtr->activeFillColor);\n    }\n    if (polyPtr->disabledFillColor != NULL) {\n\tTk_FreeColor(polyPtr->disabledFillColor);\n    }\n    if (polyPtr->fillStipple != None) {\n\tTk_FreeBitmap(display, polyPtr->fillStipple);\n    }\n    if (polyPtr->activeFillStipple != None) {\n\tTk_FreeBitmap(display, polyPtr->activeFillStipple);\n    }\n    if (polyPtr->disabledFillStipple != None) {\n\tTk_FreeBitmap(display, polyPtr->disabledFillStipple);\n    }\n    if (polyPtr->fillGC != NULL) {\n\tTk_FreeGC(display, polyPtr->fillGC);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputePolygonBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a polygon.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputePolygonBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    PolygonItem *polyPtr)\t/* Item whose bbox is to be recomputed. */\n{\n    double *coordPtr;\n    Tcl_Size i;\n    double width;\n    Tk_State state = polyPtr->header.state;\n    Tk_TSOffset *tsoffset;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    width = polyPtr->outline.width;\n    if (polyPtr->coordPtr == NULL || (polyPtr->numPoints < 1)\n\t    || (state == TK_STATE_HIDDEN)) {\n\tpolyPtr->header.x1 = polyPtr->header.x2 =\n\t\tpolyPtr->header.y1 = polyPtr->header.y2 = -1;\n\treturn;\n    }\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) polyPtr) {\n\tif (polyPtr->outline.activeWidth > width) {\n\t    width = polyPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t    width = polyPtr->outline.disabledWidth;\n\t}\n    }\n\n    coordPtr = polyPtr->coordPtr;\n    polyPtr->header.x1 = polyPtr->header.x2 = (int) *coordPtr;\n    polyPtr->header.y1 = polyPtr->header.y2 = (int) coordPtr[1];\n\n    /*\n     * Compute the bounding box of all the points in the polygon, then expand\n     * in all directions by the outline's width to take care of butting or\n     * rounded corners and projecting or rounded caps. This expansion is an\n     * overestimate (worst-case is square root of two over two) but it's\n     * simple. Don't do anything special for curves. This causes an additional\n     * overestimate in the bounding box, but is faster.\n     */\n\n    for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints-1;\n\t    i++, coordPtr += 2) {\n\tTkIncludePoint((Tk_Item *) polyPtr, coordPtr);\n    }\n\n    tsoffset = &polyPtr->tsoffset;\n    if (tsoffset->flags & TK_OFFSET_INDEX) {\n\tTcl_Size index = tsoffset->flags & ~TK_OFFSET_INDEX;\n\n\tif (tsoffset->flags == INT_MAX) {\n\t    index = (polyPtr->numPoints - polyPtr->autoClosed) * 2;\n\t    if (index < 0) {\n\t\tindex = 0;\n\t    }\n\t}\n\tindex %= (polyPtr->numPoints - polyPtr->autoClosed) * 2;\n\tif (index < 0) {\n\t    index += (polyPtr->numPoints - polyPtr->autoClosed) * 2;\n\t}\n\ttsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);\n\ttsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);\n    } else {\n\tif (tsoffset->flags & TK_OFFSET_LEFT) {\n\t    tsoffset->xoffset = polyPtr->header.x1;\n\t} else if (tsoffset->flags & TK_OFFSET_CENTER) {\n\t    tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;\n\t} else if (tsoffset->flags & TK_OFFSET_RIGHT) {\n\t    tsoffset->xoffset = polyPtr->header.x2;\n\t}\n\tif (tsoffset->flags & TK_OFFSET_TOP) {\n\t    tsoffset->yoffset = polyPtr->header.y1;\n\t} else if (tsoffset->flags & TK_OFFSET_MIDDLE) {\n\t    tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;\n\t} else if (tsoffset->flags & TK_OFFSET_BOTTOM) {\n\t    tsoffset->yoffset = polyPtr->header.y2;\n\t}\n    }\n\n    if (polyPtr->outline.gc != NULL) {\n\ttsoffset = &polyPtr->outline.tsoffset;\n\tif (tsoffset) {\n\t    if (tsoffset->flags & TK_OFFSET_INDEX) {\n\t\tTcl_Size index = tsoffset->flags & ~TK_OFFSET_INDEX;\n\n\t\tif (tsoffset->flags == INT_MAX) {\n\t\t    index = (polyPtr->numPoints - 1) * 2;\n\t\t}\n\t\tindex %= (polyPtr->numPoints - 1) * 2;\n\t\tif (index < 0) {\n\t\t    index += (polyPtr->numPoints - 1) * 2;\n\t\t}\n\t\ttsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);\n\t\ttsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);\n\t    } else {\n\t\tif (tsoffset->flags & TK_OFFSET_LEFT) {\n\t\t    tsoffset->xoffset = polyPtr->header.x1;\n\t\t} else if (tsoffset->flags & TK_OFFSET_CENTER) {\n\t\t    tsoffset->xoffset =\n\t\t\t    (polyPtr->header.x1 + polyPtr->header.x2) / 2;\n\t\t} else if (tsoffset->flags & TK_OFFSET_RIGHT) {\n\t\t    tsoffset->xoffset = polyPtr->header.x2;\n\t\t}\n\t\tif (tsoffset->flags & TK_OFFSET_TOP) {\n\t\t    tsoffset->yoffset = polyPtr->header.y1;\n\t\t} else if (tsoffset->flags & TK_OFFSET_MIDDLE) {\n\t\t    tsoffset->yoffset =\n\t\t\t    (polyPtr->header.y1 + polyPtr->header.y2) / 2;\n\t\t} else if (tsoffset->flags & TK_OFFSET_BOTTOM) {\n\t\t    tsoffset->yoffset = polyPtr->header.y2;\n\t\t}\n\t    }\n\t}\n\n\ti = (int) ((width+1.5) / 2.0);\n\tpolyPtr->header.x1 -= (int)i;\n\tpolyPtr->header.x2 += (int)i;\n\tpolyPtr->header.y1 -= (int)i;\n\tpolyPtr->header.y2 += (int)i;\n\n\t/*\n\t * For mitered lines, make a second pass through all the points.\n\t * Compute the locations of the two miter vertex points and add those\n\t * into the bounding box.\n\t */\n\n\tif (polyPtr->joinStyle == JoinMiter) {\n\t    double miter[4];\n\t    int j;\n\n\t    coordPtr = polyPtr->coordPtr;\n\t    if (polyPtr->numPoints > 3) {\n\t\tif (TkGetMiterPoints(coordPtr+2*(polyPtr->numPoints-2),\n\t\t\tcoordPtr, coordPtr+2, width, miter, miter+2)) {\n\t\t    for (j = 0; j < 4; j += 2) {\n\t\t\tTkIncludePoint((Tk_Item *) polyPtr, miter+j);\n\t\t    }\n\t\t}\n\t    }\n\t    for (i = polyPtr->numPoints ; i >= 3; i--, coordPtr += 2) {\n\t\tif (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width,\n\t\t\tmiter, miter+2)) {\n\t\t    for (j = 0; j < 4; j += 2) {\n\t\t\tTkIncludePoint((Tk_Item *) polyPtr, miter+j);\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Add one more pixel of fudge factor just to be safe (e.g. X may round\n     * differently than we do).\n     */\n\n    polyPtr->header.x1 -= 1;\n    polyPtr->header.x2 += 1;\n    polyPtr->header.y1 -= 1;\n    polyPtr->header.y2 += 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkFillPolygon --\n *\n *\tThis function is invoked to convert a polygon to screen coordinates\n *\tand display it using a particular GC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkFillPolygon(\n    Tk_Canvas canvas,\t\t/* Canvas whose coordinate system is to be\n\t\t\t\t * used for drawing. */\n    double *coordPtr,\t\t/* Array of coordinates for polygon: x1, y1,\n\t\t\t\t * x2, y2, .... */\n    Tcl_Size numPoints,\t\t/* Twice this many coordinates are present at\n\t\t\t\t * *coordPtr. */\n    Display *display,\t\t/* Display on which to draw polygon. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw\n\t\t\t\t * polygon. */\n    GC gc,\t\t\t/* Graphics context for drawing. */\n    GC outlineGC)\t\t/* If not None, use this to draw an outline\n\t\t\t\t * around the polygon after filling it. */\n{\n    XPoint staticPoints[MAX_STATIC_POINTS];\n    XPoint *pointPtr;\n    XPoint *pPtr;\n    Tcl_Size i;\n\n    /*\n     * Build up an array of points in screen coordinates. Use a static array\n     * unless the polygon has an enormous number of points; in this case,\n     * dynamically allocate an array.\n     */\n\n    if (numPoints <= MAX_STATIC_POINTS) {\n\tpointPtr = staticPoints;\n    } else {\n\tpointPtr = (XPoint *)Tcl_Alloc(numPoints * sizeof(XPoint));\n    }\n\n    for (i=0, pPtr=pointPtr ; i<numPoints; i+=1, coordPtr+=2, pPtr++) {\n\tTk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x,\n\t\t&pPtr->y);\n    }\n\n    /*\n     * Display polygon, then free up polygon storage if it was dynamically\n     * allocated.\n     */\n\n    if (gc != NULL && numPoints > 3) {\n\tXFillPolygon(display, drawable, gc, pointPtr, (int)numPoints, Complex,\n\t\tCoordModeOrigin);\n    }\n    if (outlineGC != NULL) {\n\tXDrawLines(display, drawable, outlineGC, pointPtr, (int)numPoints,\n\t\tCoordModeOrigin);\n    }\n    if (pointPtr != staticPoints) {\n\tTcl_Free(pointPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayPolygon --\n *\n *\tThis function is invoked to draw a polygon item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayPolygon(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    TCL_UNUSED(int),\t/* Describes region of canvas that must be */\n    TCL_UNUSED(int),\t/* redisplayed (not used). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    Tk_State state = itemPtr->state;\n    Pixmap stipple = polyPtr->fillStipple;\n    double linewidth = polyPtr->outline.width;\n\n    if (((polyPtr->fillGC == NULL) && (polyPtr->outline.gc == NULL)) ||\n\t    (polyPtr->numPoints < 1) ||\n\t    (polyPtr->numPoints < 3 && polyPtr->outline.gc == NULL)) {\n\treturn;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (polyPtr->outline.activeWidth > linewidth) {\n\t    linewidth = polyPtr->outline.activeWidth;\n\t}\n\tif (polyPtr->activeFillStipple != None) {\n\t    stipple = polyPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t    linewidth = polyPtr->outline.disabledWidth;\n\t}\n\tif (polyPtr->disabledFillStipple != None) {\n\t    stipple = polyPtr->disabledFillStipple;\n\t}\n    }\n\n    /*\n     * If we're stippling then modify the stipple offset in the GC. Be sure to\n     * reset the offset when done, since the GC is supposed to be read-only.\n     */\n\n    if ((stipple != None) && (polyPtr->fillGC != NULL)) {\n\tTk_TSOffset *tsoffset = &polyPtr->tsoffset;\n\tint w = 0, h = 0;\n\tint flags = tsoffset->flags;\n\n\tif (!(flags & TK_OFFSET_INDEX)\n\t\t&& (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {\n\t    Tk_SizeOfBitmap(display, stipple, &w, &h);\n\t    if (flags & TK_OFFSET_CENTER) {\n\t\tw /= 2;\n\t    } else {\n\t\tw = 0;\n\t    }\n\t    if (flags & TK_OFFSET_MIDDLE) {\n\t\th /= 2;\n\t    } else {\n\t\th = 0;\n\t    }\n\t}\n\ttsoffset->xoffset -= w;\n\ttsoffset->yoffset -= h;\n\tTk_CanvasSetOffset(canvas, polyPtr->fillGC, tsoffset);\n\ttsoffset->xoffset += w;\n\ttsoffset->yoffset += h;\n    }\n    Tk_ChangeOutlineGC(canvas, itemPtr, &polyPtr->outline);\n\n    if (polyPtr->numPoints < 3) {\n\tshort x, y;\n\tint intLineWidth = (int) (linewidth + 0.5);\n\n\tif (intLineWidth < 1) {\n\t    intLineWidth = 1;\n\t}\n\tTk_CanvasDrawableCoords(canvas, polyPtr->coordPtr[0],\n\t\tpolyPtr->coordPtr[1], &x, &y);\n\tXFillArc(display, drawable, polyPtr->outline.gc,\n\t\tx - intLineWidth/2, y - intLineWidth/2,\n\t\t(unsigned) intLineWidth+1, (unsigned) intLineWidth+1,\n\t\t0, 64*360);\n    } else if (!polyPtr->smooth || polyPtr->numPoints < 4) {\n\tTkFillPolygon(canvas, polyPtr->coordPtr, polyPtr->numPoints,\n\t\t    display, drawable, polyPtr->fillGC, polyPtr->outline.gc);\n    } else {\n\tint numPoints;\n\tXPoint staticPoints[MAX_STATIC_POINTS];\n\tXPoint *pointPtr;\n\n\t/*\n\t * This is a smoothed polygon. Display using a set of generated spline\n\t * points rather than the original points.\n\t */\n\n\tnumPoints = polyPtr->smooth->coordProc(canvas, NULL,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);\n\tif (numPoints <= MAX_STATIC_POINTS) {\n\t    pointPtr = staticPoints;\n\t} else {\n\t    pointPtr = (XPoint *)Tcl_Alloc(numPoints * sizeof(XPoint));\n\t}\n\tnumPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, pointPtr, NULL);\n\tif (polyPtr->fillGC != NULL) {\n\t    XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,\n\t\t    numPoints, Complex, CoordModeOrigin);\n\t}\n\tif (polyPtr->outline.gc != NULL) {\n\t    XDrawLines(display, drawable, polyPtr->outline.gc, pointPtr,\n\t\t    numPoints, CoordModeOrigin);\n\t}\n\tif (pointPtr != staticPoints) {\n\t    Tcl_Free(pointPtr);\n\t}\n    }\n    Tk_ResetOutlineGC(canvas, itemPtr, &polyPtr->outline);\n    if ((stipple != None) && (polyPtr->fillGC != NULL)) {\n\tXSetTSOrigin(display, polyPtr->fillGC, 0, 0);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonInsert --\n *\n *\tInsert coords into a polygon item at a given index.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe coords in the given item is modified.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPolygonInsert(\n    Tk_Canvas canvas,\t\t/* Canvas containing text item. */\n    Tk_Item *itemPtr,\t\t/* Line item to be modified. */\n    Tcl_Size beforeThis,\t\t/* Index before which new coordinates are to\n\t\t\t\t * be inserted. */\n    Tcl_Obj *obj)\t\t/* New coordinates to be inserted. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    Tcl_Size objc, i, length, oriNumPoints, nbInsPoints;\n    Tcl_Obj **objv;\n    double *newCoordPtr;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)\n\t    || !objc || objc&1) {\n\treturn;\n    }\n    oriNumPoints = polyPtr->numPoints - polyPtr->autoClosed;\n    length = 2*(polyPtr->numPoints - polyPtr->autoClosed);\n    nbInsPoints = objc / 2;\n    while (beforeThis > length) {\n\tbeforeThis -= length;\n    }\n    while (beforeThis < 0) {\n\tbeforeThis += length;\n    }\n    newCoordPtr = (double *)Tcl_Alloc(sizeof(double) * (length + 2 + objc));\n    for (i=0; i<beforeThis; i++) {\n\tnewCoordPtr[i] = polyPtr->coordPtr[i];\n    }\n    for (i=0; i<objc; i++) {\n\tif (Tcl_GetDoubleFromObj(NULL, objv[i],\n\t\t&newCoordPtr[i+beforeThis]) != TCL_OK){\n\t    Tcl_Free(newCoordPtr);\n\t    return;\n\t}\n    }\n\n    for (i=beforeThis; i<length; i++) {\n\tnewCoordPtr[i+objc] = polyPtr->coordPtr[i];\n    }\n    if (polyPtr->coordPtr) {\n\tTcl_Free(polyPtr->coordPtr);\n    }\n    length += objc;\n    polyPtr->coordPtr = newCoordPtr;\n    polyPtr->numPoints = (length/2) + polyPtr->autoClosed;\n\n    /*\n     * Close the polygon if it isn't already closed, or remove autoclosing if\n     * the user's coordinates are now closed.\n     */\n\n    if (polyPtr->autoClosed) {\n\tif ((newCoordPtr[length-2] == newCoordPtr[0])\n\t\t&& (newCoordPtr[length-1] == newCoordPtr[1])) {\n\t    polyPtr->autoClosed = 0;\n\t    polyPtr->numPoints--;\n\t}\n    } else {\n\tif ((newCoordPtr[length-2] != newCoordPtr[0])\n\t\t|| (newCoordPtr[length-1] != newCoordPtr[1])) {\n\t    polyPtr->autoClosed = 1;\n\t    polyPtr->numPoints++;\n\t}\n    }\n\n    newCoordPtr[length] = newCoordPtr[0];\n    newCoordPtr[length+1] = newCoordPtr[1];\n    if ((length-objc > 3) && (state != TK_STATE_HIDDEN)) {\n\t/*\n\t * This is some optimizing code that will result that only the part of\n\t * the polygon that changed (and the objects that are overlapping with\n\t * that part) need to be redrawn. A special flag is set that instructs\n\t * the general canvas code not to redraw the whole object. If this\n\t * flag is not set, the canvas will do the redrawing, otherwise I have\n\t * to do it here.\n\t * Rationale for the optimization code can be found in Tk ticket\n\t * [5fb8145997].\n\t */\n\n\tdouble width;\n\tTcl_Size j;\n\n\titemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;\n\n\t/*\n\t * The header elements that normally are used for the bounding box,\n\t * are now used to calculate the bounding box for only the part that\n\t * has to be redrawn. That doesn't matter, because afterwards the\n\t * bounding box has to be re-calculated anyway.\n\t */\n\n\titemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis];\n\titemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1];\n\n\tbeforeThis -= 2;\n\tobjc += 4;\n\n\tif (polyPtr->smooth) {\n\t    if (!strcmp(polyPtr->smooth->name, \"true\")) {\n\t\t/*\n\t\t * Quadratic Bezier splines.\n\t\t */\n\n\t\tbeforeThis -= 2;\n\t\tobjc += 4;\n\n\t    } else if (!strcmp(polyPtr->smooth->name, \"raw\")) {\n\t\t/*\n\t\t * Cubic Bezier splines.\n\t\t */\n\n\t\tif ((oriNumPoints % 3) || (nbInsPoints % 3)) {\n\t\t    /*\n\t\t     * No optimization for \"degenerate\" polygons or when inserting\n\t\t     * something else than a multiple of 3 points.\n\t\t     */\n\n\t\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t\t} else {\n\t\t    beforeThis -= abs((int)beforeThis) % 6;\n\t\t    objc += 4;\n\t\t}\n\n\t    } else {\n\t\t/*\n\t\t * Custom smoothing method. No optimization is possible.\n\t\t */\n\n\t\titemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    }\n\t}\n\n\tif (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {\n\t    /*\n\t     * Be careful; beforeThis could now be negative\n\t     */\n\n\t    for (i=beforeThis; i<beforeThis+objc; i+=2) {\n\t\tj = i;\n\t\tif (j < 0) {\n\t\t    j += length;\n\t\t} else if (j >= length) {\n\t\t    j -= length;\n\t\t}\n\t\tTkIncludePoint(itemPtr, polyPtr->coordPtr+j);\n\t    }\n\t    width = polyPtr->outline.width;\n\t    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\t\tif (polyPtr->outline.activeWidth > width) {\n\t\t    width = polyPtr->outline.activeWidth;\n\t\t}\n\t    } else if (state == TK_STATE_DISABLED) {\n\t\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t\t    width = polyPtr->outline.disabledWidth;\n\t\t}\n\t    }\n\t    itemPtr->x1 -= (int) width;\n\t    itemPtr->y1 -= (int) width;\n\t    itemPtr->x2 += (int) width;\n\t    itemPtr->y2 += (int) width;\n\t    Tk_CanvasEventuallyRedraw(canvas,\n\t\t    itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);\n\t}\n    }\n\n    ComputePolygonBbox(canvas, polyPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonDeleteCoords --\n *\n *\tDelete one or more coordinates from a polygon item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCharacters between \"first\" and \"last\", inclusive, get deleted from\n *\titemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPolygonDeleteCoords(\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Item in which to delete characters. */\n    Tcl_Size first,\t\t\t/* Index of first character to delete. */\n    Tcl_Size last)\t\t\t/* Index of last character to delete. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    Tcl_Size count, i;\n    Tcl_Size length = 2*(polyPtr->numPoints - polyPtr->autoClosed);\n\n    while (first >= length) {\n\tfirst -= length;\n    }\n    while (first < 0) {\n\tfirst += length;\n    }\n    while (last >= length) {\n\tlast -= length;\n    }\n    while (last < 0) {\n\tlast += length;\n    }\n\n    first &= -2;\n    last &= -2;\n\n    count = last + 2 - first;\n    if (count <= 0) {\n\tcount += length;\n    }\n\n    if (count >= length) {\n\tpolyPtr->numPoints = 0;\n\tif (polyPtr->coordPtr != NULL) {\n\t    Tcl_Free(polyPtr->coordPtr);\n\t    polyPtr->coordPtr = NULL;\n\t}\n\tComputePolygonBbox(canvas, polyPtr);\n\treturn;\n    }\n\n    if (last >= first) {\n\tfor (i=last+2; i<length; i++) {\n\t    polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i];\n\t}\n    } else {\n\tfor (i=last; i<=(int)first; i++) {\n\t    polyPtr->coordPtr[i-last] = polyPtr->coordPtr[i];\n\t}\n    }\n    polyPtr->coordPtr[length-count] = polyPtr->coordPtr[0];\n    polyPtr->coordPtr[length-count+1] = polyPtr->coordPtr[1];\n    polyPtr->numPoints -= count/2;\n    ComputePolygonBbox(canvas, polyPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonToPoint --\n *\n *\tComputes the distance from a given point to a given polygon, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tpointPtr[0] and pointPtr[1] is inside the polygon. If the point isn't\n *\tinside the polygon then the return value is the distance from the\n *\tpoint to the polygon.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nPolygonToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    double *coordPtr, *polyPoints;\n    double staticSpace[2*MAX_STATIC_POINTS];\n    double poly[10];\n    double radius;\n    double bestDist, dist;\n    Tcl_Size numPoints, count;\n    bool changedMiterToBevel;\t/* True means that a mitered corner had to\n\t\t\t\t * be treated as beveled after all because the\n\t\t\t\t * angle was < 11 degrees. */\n    double width;\n    Tk_State state = itemPtr->state;\n\n    bestDist = 1.0e36;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    width = polyPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (polyPtr->outline.activeWidth > width) {\n\t    width = polyPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t    width = polyPtr->outline.disabledWidth;\n\t}\n    }\n    radius = width/2.0;\n\n    /*\n     * Handle smoothed polygons by generating an expanded set of points\n     * against which to do the check.\n     */\n\n    if ((polyPtr->smooth) && (polyPtr->numPoints > 2)) {\n\tnumPoints = polyPtr->smooth->coordProc(canvas, NULL,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);\n\tif (numPoints <= MAX_STATIC_POINTS) {\n\t    polyPoints = staticSpace;\n\t} else {\n\t    polyPoints = (double *)Tcl_Alloc(2 * numPoints * sizeof(double));\n\t}\n\tnumPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);\n    } else {\n\tnumPoints = polyPtr->numPoints;\n\tpolyPoints = polyPtr->coordPtr;\n    }\n\n    bestDist = TkPolygonToPoint(polyPoints, numPoints, pointPtr);\n    if (bestDist <= 0.0) {\n\tgoto donepoint;\n    }\n    if ((polyPtr->outline.gc != NULL) && (polyPtr->joinStyle == JoinRound)) {\n\tdist = bestDist - radius;\n\tif (dist <= 0.0) {\n\t    bestDist = 0.0;\n\t    goto donepoint;\n\t} else {\n\t    bestDist = dist;\n\t}\n    }\n\n    if ((polyPtr->outline.gc == NULL) || (width <= 1)) {\n\tgoto donepoint;\n    }\n\n    /*\n     * The overall idea is to iterate through all of the edges of the line,\n     * computing a polygon for each edge and testing the point against that\n     * polygon. In addition, there are additional tests to deal with rounded\n     * joints and caps.\n     */\n\n    changedMiterToBevel = false;\n    for (count = numPoints, coordPtr = polyPoints; count >= 2;\n\t    count--, coordPtr += 2) {\n\t/*\n\t * If rounding is done around the first point then compute the\n\t * distance between the point and the point.\n\t */\n\n\tif (polyPtr->joinStyle == JoinRound) {\n\t    dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])\n\t\t    - radius;\n\t    if (dist <= 0.0) {\n\t\tbestDist = 0.0;\n\t\tgoto donepoint;\n\t    } else if (dist < bestDist) {\n\t\tbestDist = dist;\n\t    }\n\t}\n\n\t/*\n\t * Compute the polygonal shape corresponding to this edge, consisting\n\t * of two points for the first point of the edge and two points for\n\t * the last point of the edge.\n\t */\n\n\tif (count == numPoints) {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0, poly,\n\t\t    poly+2);\n\t} else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {\n\t    poly[0] = poly[6];\n\t    poly[1] = poly[7];\n\t    poly[2] = poly[4];\n\t    poly[3] = poly[5];\n\t} else {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0, poly,\n\t\t    poly+2);\n\n\t    /*\n\t     * If this line uses beveled joints, then check the distance to a\n\t     * polygon comprising the last two points of the previous polygon\n\t     * and the first two from this polygon; this checks the wedges\n\t     * that fill the mitered joint.\n\t     */\n\n\t    if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {\n\t\tpoly[8] = poly[0];\n\t\tpoly[9] = poly[1];\n\t\tdist = TkPolygonToPoint(poly, 5, pointPtr);\n\t\tif (dist <= 0.0) {\n\t\t    bestDist = 0.0;\n\t\t    goto donepoint;\n\t\t} else if (dist < bestDist) {\n\t\t    bestDist = dist;\n\t\t}\n\t\tchangedMiterToBevel = false;\n\t    }\n\t}\n\tif (count == 2) {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, poly+4,\n\t\t    poly+6);\n\t} else if (polyPtr->joinStyle == JoinMiter) {\n\t    if (!TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,\n\t\t    (double) width, poly+4, poly+6)) {\n\t\tchangedMiterToBevel = true;\n\t\tTkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0,\n\t\t\tpoly+4, poly+6);\n\t    }\n\t} else {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, poly+4,\n\t\t    poly+6);\n\t}\n\tpoly[8] = poly[0];\n\tpoly[9] = poly[1];\n\tdist = TkPolygonToPoint(poly, 5, pointPtr);\n\tif (dist <= 0.0) {\n\t    bestDist = 0.0;\n\t    goto donepoint;\n\t} else if (dist < bestDist) {\n\t    bestDist = dist;\n\t}\n    }\n\n  donepoint:\n    if (polyPoints != staticSpace && polyPoints != polyPtr->coordPtr) {\n\tTcl_Free(polyPoints);\n    }\n    return bestDist;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nPolygonToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against polygon. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates\n\t\t\t\t * (x1,y1,x2,y2) describing rectangular\n\t\t\t\t * area. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    double *coordPtr;\n    double staticSpace[2*MAX_STATIC_POINTS];\n    double *polyPoints, poly[10];\n    double radius;\n    Tcl_Size numPoints, count;\n    bool changedMiterToBevel;\t/* True means that a mitered corner had to\n\t\t\t\t * be treated as beveled after all because the\n\t\t\t\t * angle was < 11 degrees. */\n    int inside;\t\t\t/* Tentative guess about what to return, based\n\t\t\t\t * on all points seen so far: one means\n\t\t\t\t * everything seen so far was inside the area;\n\t\t\t\t * -1 means everything was outside the area. 0\n\t\t\t\t * means overlap has been found. */\n    double width;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = polyPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (polyPtr->outline.activeWidth > width) {\n\t    width = polyPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t    width = polyPtr->outline.disabledWidth;\n\t}\n    }\n\n    radius = width/2.0;\n    inside = -1;\n\n    if ((state == TK_STATE_HIDDEN) || polyPtr->numPoints < 2) {\n\treturn -1;\n    } else if (polyPtr->numPoints < 3) {\n\tdouble oval[4];\n\n\toval[0] = polyPtr->coordPtr[0]-radius;\n\toval[1] = polyPtr->coordPtr[1]-radius;\n\toval[2] = polyPtr->coordPtr[0]+radius;\n\toval[3] = polyPtr->coordPtr[1]+radius;\n\treturn TkOvalToArea(oval, rectPtr);\n    }\n\n    /*\n     * Handle smoothed polygons by generating an expanded set of points\n     * against which to do the check.\n     */\n\n    if (polyPtr->smooth) {\n\tnumPoints = polyPtr->smooth->coordProc(canvas, NULL,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);\n\tif (numPoints <= MAX_STATIC_POINTS) {\n\t    polyPoints = staticSpace;\n\t} else {\n\t    polyPoints = (double *)Tcl_Alloc(2 * numPoints * sizeof(double));\n\t}\n\tnumPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,\n\t\t(int)polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);\n    } else {\n\tnumPoints = polyPtr->numPoints;\n\tpolyPoints = polyPtr->coordPtr;\n    }\n\n    /*\n     * Simple test to see if we are in the polygon. Polygons are different\n     * from othe canvas items in that they register points being inside even\n     * if it isn't filled.\n     */\n\n    inside = TkPolygonToArea(polyPoints, numPoints, rectPtr);\n    if (inside == 0) {\n\tgoto donearea;\n    }\n\n    if (polyPtr->outline.gc == NULL) {\n\tgoto donearea;\n    }\n\n    /*\n     * Iterate through all of the edges of the line, computing a polygon for\n     * each edge and testing the area against that polygon. In addition, there\n     * are additional tests to deal with rounded joints and caps.\n     */\n\n    changedMiterToBevel = false;\n    for (count = numPoints, coordPtr = polyPoints; count >= 2;\n\t    count--, coordPtr += 2) {\n\t/*\n\t * If rounding is done around the first point of the edge then test a\n\t * circular region around the point with the area.\n\t */\n\n\tif (polyPtr->joinStyle == JoinRound) {\n\t    poly[0] = coordPtr[0] - radius;\n\t    poly[1] = coordPtr[1] - radius;\n\t    poly[2] = coordPtr[0] + radius;\n\t    poly[3] = coordPtr[1] + radius;\n\t    if (TkOvalToArea(poly, rectPtr) != inside) {\n\t\tinside = 0;\n\t\tgoto donearea;\n\t    }\n\t}\n\n\t/*\n\t * Compute the polygonal shape corresponding to this edge, consisting\n\t * of two points for the first point of the edge and two points for\n\t * the last point of the edge.\n\t */\n\n\tif (count == numPoints) {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);\n\t} else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {\n\t    poly[0] = poly[6];\n\t    poly[1] = poly[7];\n\t    poly[2] = poly[4];\n\t    poly[3] = poly[5];\n\t} else {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);\n\n\t    /*\n\t     * If the last joint was beveled, then also check a polygon\n\t     * comprising the last two points of the previous polygon and the\n\t     * first two from this polygon; this checks the wedges that fill\n\t     * the beveled joint.\n\t     */\n\n\t    if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {\n\t\tpoly[8] = poly[0];\n\t\tpoly[9] = poly[1];\n\t\tif (TkPolygonToArea(poly, 5, rectPtr) != inside) {\n\t\t    inside = 0;\n\t\t    goto donearea;\n\t\t}\n\t\tchangedMiterToBevel = false;\n\t    }\n\t}\n\tif (count == 2) {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);\n\t} else if (polyPtr->joinStyle == JoinMiter) {\n\t    if (!TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width,\n\t\t    poly+4, poly+6)) {\n\t\tchangedMiterToBevel = true;\n\t\tTkGetButtPoints(coordPtr, coordPtr+2, width,0, poly+4, poly+6);\n\t    }\n\t} else {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);\n\t}\n\tpoly[8] = poly[0];\n\tpoly[9] = poly[1];\n\tif (TkPolygonToArea(poly, 5, rectPtr) != inside) {\n\t    inside = 0;\n\t    goto donearea;\n\t}\n    }\n\n  donearea:\n    if ((polyPoints != staticSpace) && (polyPoints != polyPtr->coordPtr)) {\n\tTcl_Free(polyPoints);\n    }\n    return inside;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScalePolygon --\n *\n *\tThis function is invoked to rescale a polygon item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe polygon referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScalePolygon(\n    Tk_Canvas canvas,\t\t/* Canvas containing polygon. */\n    Tk_Item *itemPtr,\t\t/* Polygon to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale rect. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    double *coordPtr;\n    int i;\n\n    for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;\n\t    i++, coordPtr += 2) {\n\t*coordPtr = originX + scaleX*(*coordPtr - originX);\n\tcoordPtr[1] = originY + scaleY*(coordPtr[1] - originY);\n    }\n    ComputePolygonBbox(canvas, polyPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetPolygonIndex --\n *\n *\tParse an index into a polygon item and return either its value or an\n *\terror.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the index (into itemPtr) corresponding to string. Otherwise an\n *\terror message is left in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetPolygonIndex(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *obj,\t\t/* Specification of a particular coord in\n\t\t\t\t * itemPtr's line. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted index. */\n{\n    Tcl_Size length, idx;\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    const char *string;\n    Tcl_Size count = 2*(polyPtr->numPoints - polyPtr->autoClosed);\n\n    if (TCL_OK == TkGetIntForIndex(obj,  (INT_MAX - 1) - ((INT_MAX) % count), 1, &idx)) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else if (idx >= INT_MAX - ((INT_MAX) % count)) {\n\t    idx = count;\n\t} else {\n\t    idx = (idx & (Tcl_Size)-2) % count;\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetStringFromObj(obj, &length);\n\n    if (string[0] == '@') {\n\tint i;\n\tdouble x, y, bestDist, dist, *coordPtr;\n\tchar *rest;\n\tconst char *p;\n\n\tp = string+1;\n\trest = strchr((char *)p, ',');\n\t*rest = '\\0';\n\tif (Tcl_GetDouble(NULL, p, &x) != TCL_OK) {\n\t    *rest = ',';\n\t    goto badIndex;\n\t}\n\t*rest = ',';\n\tp = rest+1;\n\tif (Tcl_GetDouble(NULL, p, &y) != TCL_OK) {\n\t    goto badIndex;\n\t}\n\tbestDist = 1.0e36;\n\tcoordPtr = polyPtr->coordPtr;\n\t*indexPtr = 0;\n\tfor (i=0; i<polyPtr->numPoints-1; i++) {\n\t    dist = hypot(coordPtr[0] - x, coordPtr[1] - y);\n\t    if (dist < bestDist) {\n\t\tbestDist = dist;\n\t\t*indexPtr = 2*i;\n\t    }\n\t    coordPtr += 2;\n\t}\n    } else {\n    badIndex:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad index \\\"%s\\\"\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ITEM_INDEX\", \"POLY\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotatePolygon --\n *\n *\tThis function is called to rotate a polygon by a given amount about a\n *\tpoint.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the polygon is rotated by angleRad about (originX,\n *\toriginY), and the bounding box is updated in the generic part of the\n *\titem structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotatePolygon(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double originX, double originY,\n    double angleRad)\t\t/* Amount by which item is to be rotated. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    double *coordPtr;\n    int i;\n    double s = sin(angleRad), c = cos(angleRad);\n\n    for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;\n\t    i++, coordPtr += 2) {\n\tTkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);\n    }\n    ComputePolygonBbox(canvas, polyPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslatePolygon --\n *\n *\tThis function is called to move a polygon by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the polygon is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslatePolygon(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    double *coordPtr;\n    int i;\n\n    for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;\n\t    i++, coordPtr += 2) {\n\t*coordPtr += deltaX;\n\tcoordPtr[1] += deltaY;\n    }\n    ComputePolygonBbox(canvas, polyPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PolygonToPostscript --\n *\n *\tThis function is called to generate Postscript for polygon items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nPolygonToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    TCL_UNUSED(int))\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    PolygonItem *polyPtr = (PolygonItem *) itemPtr;\n    int style;\n    XColor *color;\n    XColor *fillColor;\n    Pixmap stipple;\n    Pixmap fillStipple;\n    Tk_State state = itemPtr->state;\n    double width;\n    Tcl_Obj *psObj;\n    Tcl_InterpState interpState;\n\n    if (polyPtr->numPoints < 2 || polyPtr->coordPtr == NULL) {\n\treturn TCL_OK;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    width = polyPtr->outline.width;\n    color = polyPtr->outline.color;\n    stipple = polyPtr->fillStipple;\n    fillColor = polyPtr->fillColor;\n    fillStipple = polyPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (polyPtr->outline.activeWidth > width) {\n\t    width = polyPtr->outline.activeWidth;\n\t}\n\tif (polyPtr->outline.activeColor != NULL) {\n\t    color = polyPtr->outline.activeColor;\n\t}\n\tif (polyPtr->outline.activeStipple != None) {\n\t    stipple = polyPtr->outline.activeStipple;\n\t}\n\tif (polyPtr->activeFillColor != NULL) {\n\t    fillColor = polyPtr->activeFillColor;\n\t}\n\tif (polyPtr->activeFillStipple != None) {\n\t    fillStipple = polyPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (polyPtr->outline.disabledWidth > 0.0) {\n\t    width = polyPtr->outline.disabledWidth;\n\t}\n\tif (polyPtr->outline.disabledColor != NULL) {\n\t    color = polyPtr->outline.disabledColor;\n\t}\n\tif (polyPtr->outline.disabledStipple != None) {\n\t    stipple = polyPtr->outline.disabledStipple;\n\t}\n\tif (polyPtr->disabledFillColor != NULL) {\n\t    fillColor = polyPtr->disabledFillColor;\n\t}\n\tif (polyPtr->disabledFillStipple != None) {\n\t    fillStipple = polyPtr->disabledFillStipple;\n\t}\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    if (polyPtr->numPoints == 2) {\n\tif (color == NULL) {\n\t    goto done;\n\t}\n\n\t/*\n\t * Create a point by using a small circle. (Printer pixels are too\n\t * tiny to be used directly...)\n\t */\n\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"matrix currentmatrix\\n\"\t/* save state */\n\t\t\"%.15g %.15g translate \"\t/* go to drawing location */\n\t\t\"%.15g %.15g scale \"\t\t/* scale the drawing */\n\t\t\"1 0 moveto \"\t\t\t/* correct for origin */\n\t\t\"0 0 1 0 360 arc\\n\"\t\t/* make the circle */\n\t\t\"setmatrix\\n\",\t\t\t/* restore state */\n\t\tpolyPtr->coordPtr[0],\n\t\tTk_CanvasPsY(canvas, polyPtr->coordPtr[1]),\n\t\twidth/2.0, width/2.0);\n\n\t/*\n\t * Color it in.\n\t */\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, color);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (stipple != None) {\n\t    Tcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsStipple(interp, canvas, stipple);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t}\n\tgoto done;\n    }\n\n    /*\n     * Fill the area of the polygon.\n     */\n\n    if (fillColor != NULL && polyPtr->numPoints > 3) {\n\tTcl_ResetResult(interp);\n\tif (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {\n\t    Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,\n\t\t    polyPtr->numPoints);\n\t} else {\n\t    polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,\n\t\t    (int)polyPtr->numPoints, polyPtr->splineSteps);\n\t}\n\tTk_CanvasPsColor(interp, canvas, fillColor);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (fillStipple != None) {\n\t    Tcl_AppendToObj(psObj, \"eoclip \", TCL_INDEX_NONE);\n\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsStipple(interp, canvas, fillStipple);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\t    if (color != NULL) {\n\t\tTcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\t    }\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"eofill\\n\", TCL_INDEX_NONE);\n\t}\n    }\n\n    /*\n     * Now draw the outline, if there is one.\n     */\n\n    if (color != NULL) {\n\tTcl_ResetResult(interp);\n\tif (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {\n\t    Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,\n\t\t    polyPtr->numPoints);\n\t} else {\n\t    polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,\n\t\t    (int)polyPtr->numPoints, polyPtr->splineSteps);\n\t}\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (polyPtr->joinStyle == JoinRound) {\n\t    style = 1;\n\t} else if (polyPtr->joinStyle == JoinBevel) {\n\t    style = 2;\n\t} else {\n\t    style = 0;\n\t}\n\tTcl_AppendPrintfToObj(psObj, \"%d setlinejoin 1 setlinecap\\n\", style);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsOutline(canvas, itemPtr, &polyPtr->outline);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n  done:\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvPs.c",
    "content": "/*\n * tkCanvPs.c --\n *\n *\tThis module provides Postscript output support for canvases, including\n *\tthe \"postscript\" widget command plus a few utility functions used for\n *\tgenerating Postscript.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"tkFont.h\"\n\n/*\n * See tkCanvas.h for key data structures used to implement canvases.\n */\n\n/*\n * The following definition is used in generating postscript for images and\n * windows.\n */\n\ntypedef struct TkColormapData {\t/* Hold color information for a window */\n    int separated;\t\t/* Whether to use separate color bands */\n    int color;\t\t\t/* Whether window is color or black/white */\n    int ncolors;\t\t/* Number of color values stored */\n    XColor *colors;\t\t/* Pixel value -> RGB mappings */\n    int red_mask, green_mask, blue_mask;\t/* Masks and shifts for each */\n    int red_shift, green_shift, blue_shift;\t/* color band */\n} TkColormapData;\n\n/*\n * One of the following structures is created to keep track of Postscript\n * output being generated. It consists mostly of information provided on the\n * widget command line.\n */\n\ntypedef struct TkPostscriptInfo {\n    int x, y, width, height;\t/* Area to print, in canvas pixel\n\t\t\t\t * coordinates. */\n    int x2, y2;\t\t\t/* x+width and y+height. */\n    Tcl_Obj *pageXObj;\t\t/* Value of \"-pagex\" option or NULL. */\n    Tcl_Obj *pageYObj;\t\t/* Value of \"-pagey\" option or NULL. */\n    double pageX, pageY;\t/* Postscript coordinates (in points)\n\t\t\t\t * corresponding to pageXString and\n\t\t\t\t * pageYString. Don't forget that y-values\n\t\t\t\t * grow upwards for Postscript! */\n    Tcl_Obj *pageWidthObj;\t/* Printed width of output. */\n    Tcl_Obj *pageHeightObj;\t/* Printed height of output. */\n    double scale;\t\t/* Scale factor for conversion: each pixel\n\t\t\t\t * maps into this many points. */\n    Tk_Anchor pageAnchor;\t/* How to anchor bbox on Postscript page. */\n    int rotate;\t\t\t/* Non-zero means output should be rotated on\n\t\t\t\t * page (landscape mode). */\n    Tcl_Obj *fontVarObj;\t/* If non-NULL, gives name of global variable\n\t\t\t\t * containing font mapping information. */\n    Tcl_Obj *colorVarObj;\t/* If non-NULL, give name of global variable\n\t\t\t\t * containing color mapping information. */\n    Tcl_Obj *colorModeObj;\t/* Mode for handling colors: \"monochrome\",\n\t\t\t\t * \"gray\", or \"color\". */\n    int colorLevel;\t\t/* Numeric value corresponding to colorMode: 0\n\t\t\t\t * for mono, 1 for gray, 2 for color. */\n    Tcl_Obj *fileNameObj;\t\t/* Name of file in which to write Postscript;\n\t\t\t\t * NULL means return Postscript info as result. */\n    Tcl_Obj *channelNameObj;\t/* If -channel is specified, the name of the\n\t\t\t\t * channel to use. */\n    Tcl_Channel chan;\t\t/* Open channel corresponding to fileName. */\n    Tcl_HashTable fontTable;\t/* Hash table containing names of all font\n\t\t\t\t * families used in output. The hash table\n\t\t\t\t * values are not used. */\n    int prepass;\t\t/* Non-zero means that we're currently in the\n\t\t\t\t * pre-pass that collects font information, so\n\t\t\t\t * the Postscript generated isn't relevant. */\n    int prolog;\t\t\t/* Non-zero means output should contain the\n\t\t\t\t * standard prolog in the header. Generated in\n\t\t\t\t * library/mkpsenc.tcl, stored in the variable\n\t\t\t\t * ::tk::ps_preamable [sic]. */\n    Tk_Window tkwin;\t\t/* Window to get font pixel/point transform\n\t\t\t\t * from. */\n} TkPostscriptInfo;\n\n/*\n * The table below provides a template that's used to process arguments to the\n * canvas \"postscript\" command and fill in TkPostscriptInfo structures.\n */\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_STRING, \"-colormap\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, colorVarObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-colormode\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, colorModeObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-file\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, fileNameObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-channel\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, channelNameObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-fontmap\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, fontVarObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_PIXELS, \"-height\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, height), 0, NULL},\n    {TK_CONFIG_ANCHOR, \"-pageanchor\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, pageAnchor), 0, NULL},\n    {TK_CONFIG_STRING, \"-pageheight\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, pageHeightObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-pagewidth\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, pageWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-pagex\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, pageXObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-pagey\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, pageYObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_BOOLEAN, \"-prolog\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, prolog), 0, NULL},\n    {TK_CONFIG_BOOLEAN, \"-rotate\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, rotate), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-width\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, width), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-x\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, x), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-y\", NULL, NULL,\n\t\"\", offsetof(TkPostscriptInfo, y), 0, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tGetPostscriptPoints(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *value, double *doublePtr);\nstatic void\t\tPostscriptBitmap(Tk_Window tkwin, Pixmap bitmap,\n\t\t\t    int startX, int startY, int width, int height,\n\t\t\t    Tcl_Obj *psObj);\nstatic inline Tcl_Obj *\tGetPostscriptBuffer(Tcl_Interp *interp);\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkCanvPostscriptObjCmd --\n *\n *\tThis function is invoked to process the \"postscript\" options of the\n *\twidget command for canvas widgets. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkCanvPostscriptObjCmd(\n    TkCanvas *canvasPtr,\t/* Information about canvas widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n\tTcl_Obj *const objv[])\t\t/* Argument strings. Caller has already parsed\n\t\t\t\t * this command enough to know that objv[1] is\n\t\t\t\t * \"postscript\". */\n{\n    TkPostscriptInfo psInfo, *psInfoPtr = &psInfo;\n    Tk_PostscriptInfo oldInfoPtr;\n    int result;\n    Tk_Item *itemPtr;\n#define STRING_LENGTH 400\n    const char *p;\n    time_t now;\n    size_t length;\n    Tk_Window tkwin = canvasPtr->tkwin;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n    Tcl_DString buffer;\n    Tcl_Obj *preambleObj;\n    Tcl_Obj *psObj;\n    int deltaX = 0, deltaY = 0;\t/* Offset of lower-left corner of area to be\n\t\t\t\t * marked up, measured in canvas units from\n\t\t\t\t * the positioning point on the page (reflects\n\t\t\t\t * anchor position). Initial values needed\n\t\t\t\t * only to stop compiler warnings. */\n\n    /*\n     * Get the generic preamble. We only ever bother with the ASCII encoding;\n     * the others just make life too complicated and never actually worked as\n     * such.\n     */\n\n    result = Tcl_EvalEx(interp, \"::tk::ensure_psenc_is_loaded\", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    preambleObj = Tcl_GetVar2Ex(interp, \"::tk::ps_preamble\", NULL,\n\t    TCL_LEAVE_ERR_MSG);\n    if (preambleObj == NULL) {\n\treturn TCL_ERROR;\n    }\n    Tcl_IncrRefCount(preambleObj);\n    Tcl_ResetResult(interp);\n    psObj = Tcl_NewObj();\n\n    /*\n     * Initialize the data structure describing Postscript generation, then\n     * process all the arguments to fill the data structure in.\n     */\n\n    oldInfoPtr = canvasPtr->psInfo;\n    canvasPtr->psInfo = (Tk_PostscriptInfo) psInfoPtr;\n    psInfo.x = canvasPtr->xOrigin;\n    psInfo.y = canvasPtr->yOrigin;\n    psInfo.width = -1;\n    psInfo.height = -1;\n    psInfo.pageXObj = NULL;\n    psInfo.pageYObj = NULL;\n    psInfo.pageX = 72*4.25;\n    psInfo.pageY = 72*5.5;\n    psInfo.pageWidthObj = NULL;\n    psInfo.pageHeightObj = NULL;\n    psInfo.scale = 1.0;\n    psInfo.pageAnchor = TK_ANCHOR_CENTER;\n    psInfo.rotate = 0;\n    psInfo.fontVarObj = NULL;\n    psInfo.colorVarObj = NULL;\n    psInfo.colorModeObj = NULL;\n    psInfo.colorLevel = 0;\n    psInfo.fileNameObj = NULL;\n    psInfo.channelNameObj = NULL;\n    psInfo.chan = NULL;\n    psInfo.prepass = 0;\n    psInfo.prolog = 1;\n    psInfo.tkwin = tkwin;\n    Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS);\n    result = Tk_ConfigureWidget(interp, tkwin, configSpecs, objc-2, objv+2,\n\t    &psInfo, TK_CONFIG_ARGV_ONLY);\n    if (result != TCL_OK) {\n\tgoto cleanup;\n    }\n\n    if (psInfo.width == -1) {\n\tpsInfo.width = Tk_Width(tkwin);\n    }\n    if (psInfo.height == -1) {\n\tpsInfo.height = Tk_Height(tkwin);\n    }\n    psInfo.x2 = psInfo.x + psInfo.width;\n    psInfo.y2 = psInfo.y + psInfo.height;\n\n    if (psInfo.pageXObj != NULL) {\n\tif (GetPostscriptPoints(interp, psInfo.pageXObj,\n\t\t&psInfo.pageX) != TCL_OK) {\n\t    goto cleanup;\n\t}\n    }\n    if (psInfo.pageYObj != NULL) {\n\tif (GetPostscriptPoints(interp, psInfo.pageYObj,\n\t\t&psInfo.pageY) != TCL_OK) {\n\t    goto cleanup;\n\t}\n    }\n    if (psInfo.pageWidthObj != NULL) {\n\tif (GetPostscriptPoints(interp, psInfo.pageWidthObj,\n\t\t&psInfo.scale) != TCL_OK) {\n\t    goto cleanup;\n\t}\n\tpsInfo.scale /= psInfo.width;\n    } else if (psInfo.pageHeightObj != NULL) {\n\tif (GetPostscriptPoints(interp, psInfo.pageHeightObj,\n\t\t&psInfo.scale) != TCL_OK) {\n\t    goto cleanup;\n\t}\n\tpsInfo.scale /= psInfo.height;\n    } else {\n\tpsInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));\n\tpsInfo.scale /= WidthOfScreen(Tk_Screen(tkwin));\n    }\n    switch (psInfo.pageAnchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_W:\n    case TK_ANCHOR_SW:\n\tdeltaX = 0;\n\tbreak;\n    case TK_ANCHOR_NE:\n    case TK_ANCHOR_E:\n    case TK_ANCHOR_SE:\n\tdeltaX = -psInfo.width;\n\tbreak;\n    default:\n\tdeltaX = -psInfo.width/2;\n\tbreak;\n    }\n    switch (psInfo.pageAnchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_N:\n    case TK_ANCHOR_NE:\n\tdeltaY = - psInfo.height;\n\tbreak;\n    case TK_ANCHOR_SW:\n    case TK_ANCHOR_S:\n    case TK_ANCHOR_SE:\n\tdeltaY = 0;\n\tbreak;\n    default:\n\tdeltaY = -psInfo.height/2;\n\tbreak;\n    }\n\n    if (psInfo.colorModeObj == NULL) {\n\tpsInfo.colorLevel = 2;\n    } else {\n\tlength = strlen(Tcl_GetString(psInfo.colorModeObj));\n\tif (strncmp(Tcl_GetString(psInfo.colorModeObj), \"monochrome\", length) == 0) {\n\t    psInfo.colorLevel = 0;\n\t} else if (strncmp(Tcl_GetString(psInfo.colorModeObj), \"gray\", length) == 0) {\n\t    psInfo.colorLevel = 1;\n\t} else if (strncmp(Tcl_GetString(psInfo.colorModeObj), \"color\", length) == 0) {\n\t    psInfo.colorLevel = 2;\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad color mode \\\"%s\\\": must be monochrome, gray, or color\",\n\t\t    Tcl_GetString(psInfo.colorModeObj)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"COLORMODE\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto cleanup;\n\t}\n    }\n\n    if (psInfo.fileNameObj != NULL) {\n\t/*\n\t * Check that -file and -channel are not both specified.\n\t */\n\n\tif (psInfo.channelNameObj != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't specify both -file and -channel\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"USAGE\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto cleanup;\n\t}\n\n\t/*\n\t * Check that we are not in a safe interpreter. If we are, disallow\n\t * the -file specification.\n\t */\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't specify -file in a safe interpreter\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"PS_FILE\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto cleanup;\n\t}\n\n\tp = Tcl_TranslateFileName(interp, Tcl_GetString(psInfo.fileNameObj), &buffer);\n\tif (p == NULL) {\n\t    goto cleanup;\n\t}\n\tpsInfo.chan = Tcl_OpenFileChannel(interp, p, \"w\", 0666);\n\tTcl_DStringFree(&buffer);\n\tif (psInfo.chan == NULL) {\n\t    goto cleanup;\n\t}\n    }\n\n    if (psInfo.channelNameObj != NULL) {\n\tint mode;\n\n\t/*\n\t * Check that the channel is found in this interpreter and that it is\n\t * open for writing.\n\t */\n\n\tpsInfo.chan = Tcl_GetChannel(interp, Tcl_GetString(psInfo.channelNameObj), &mode);\n\tif (psInfo.chan == NULL) {\n\t    result = TCL_ERROR;\n\t    goto cleanup;\n\t}\n\tif (!(mode & TCL_WRITABLE)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"channel \\\"%s\\\" wasn't opened for writing\",\n\t\t    Tcl_GetString(psInfo.channelNameObj)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"UNWRITABLE\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto cleanup;\n\t}\n    }\n\n    /*\n     * Make a pre-pass over all of the items, generating Postscript and then\n     * throwing it away. The purpose of this pass is just to collect\n     * information about all the fonts in use, so that we can output font\n     * information in the proper form required by the Document Structuring\n     * Conventions.\n     */\n\n    psInfo.prepass = 1;\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif ((itemPtr->x1 >= psInfo.x2) || (itemPtr->x2 < psInfo.x)\n\t\t|| (itemPtr->y1 >= psInfo.y2) || (itemPtr->y2 < psInfo.y)) {\n\t    continue;\n\t}\n\tif (itemPtr->typePtr->postscriptProc == NULL) {\n\t    continue;\n\t}\n\tresult = itemPtr->typePtr->postscriptProc(interp,\n\t\t(Tk_Canvas) canvasPtr, itemPtr, 1);\n\tTcl_ResetResult(interp);\n\tif (result != TCL_OK) {\n\t    /*\n\t     * An error just occurred. Just skip out of this loop. There's no\n\t     * need to report the error now; it can be reported later (errors\n\t     * can happen later that don't happen now, so we still have to\n\t     * check for errors later anyway).\n\t     */\n\n\t    break;\n\t}\n    }\n    psInfo.prepass = 0;\n\n    /*\n     * Generate the header and prolog for the Postscript.\n     */\n\n    if (psInfo.prolog) {\n\tTcl_AppendToObj(psObj,\n\t\t\"%!PS-Adobe-3.0 EPSF-3.0\\n\"\n\t\t\"%%Creator: Tk Canvas Widget\\n\", TCL_INDEX_NONE);\n\n#ifdef HAVE_PW_GECOS\n\tif (!Tcl_IsSafe(interp)) {\n\t    struct passwd *pwPtr = getpwuid(getuid());\t/* INTL: Native. */\n\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%%%%For: %s\\n\", (pwPtr ? pwPtr->pw_gecos : \"Unknown\"));\n\t    endpwent();\n\t}\n#endif /* HAVE_PW_GECOS */\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%%%%Title: Window %s\\n\", Tk_PathName(tkwin));\n\ttime(&now);\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%%%%CreationDate: %s\", ctime(&now));\t/* INTL: Native. */\n\tif (!psInfo.rotate) {\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%%%%BoundingBox: %d %d %d %d\\n\",\n\t\t    (int) (psInfo.pageX + psInfo.scale*deltaX),\n\t\t    (int) (psInfo.pageY + psInfo.scale*deltaY),\n\t\t    (int) (psInfo.pageX + psInfo.scale*(deltaX + psInfo.width)\n\t\t\t    + 1.0),\n\t\t    (int) (psInfo.pageY + psInfo.scale*(deltaY + psInfo.height)\n\t\t\t    + 1.0));\n\t} else {\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%%%%BoundingBox: %d %d %d %d\\n\",\n\t\t    (int) (psInfo.pageX - psInfo.scale*(deltaY+psInfo.height)),\n\t\t    (int) (psInfo.pageY + psInfo.scale*deltaX),\n\t\t    (int) (psInfo.pageX - psInfo.scale*deltaY + 1.0),\n\t\t    (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width)\n\t\t\t    + 1.0));\n\t}\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%%%%Pages: 1\\n\"\n\t\t\"%%%%DocumentData: Clean7Bit\\n\"\n\t\t\"%%%%Orientation: %s\\n\",\n\t\tpsInfo.rotate ? \"Landscape\" : \"Portrait\");\n\tp = \"%%%%DocumentNeededResources: font %s\\n\";\n\tfor (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);\n\t\thPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_AppendPrintfToObj(psObj, p,\n\t\t    Tcl_GetHashKey(&psInfo.fontTable, hPtr));\n\t    p = \"%%%%+ font %s\\n\";\n\t}\n\tTcl_AppendToObj(psObj, \"%%EndComments\\n\\n\", TCL_INDEX_NONE);\n\n\t/*\n\t * Insert the prolog\n\t */\n\n\tTcl_AppendObjToObj(psObj, preambleObj);\n\n\tif (psInfo.chan != NULL) {\n\t    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {\n\t    channelWriteFailed:\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"problem writing postscript data to channel: %s\",\n\t\t\tTcl_PosixError(interp)));\n\t\tresult = TCL_ERROR;\n\t\tgoto cleanup;\n\t    }\n\t    Tcl_DecrRefCount(psObj);\n\t    psObj = Tcl_NewObj();\n\t}\n\n\t/*\n\t * Document setup:  set the color level and include fonts.\n\t */\n\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%%%%BeginSetup\\n/CL %d def\\n\", psInfo.colorLevel);\n\tfor (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);\n\t\thPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%%%%IncludeResource: font %s\\n\",\n\t\t    (char *) Tcl_GetHashKey(&psInfo.fontTable, hPtr));\n\t}\n\tTcl_AppendToObj(psObj, \"%%EndSetup\\n\\n\", TCL_INDEX_NONE);\n\n\t/*\n\t * Page setup: move to page positioning point, rotate if needed, set\n\t * scale factor, offset for proper anchor position, and set clip\n\t * region.\n\t */\n\n\tTcl_AppendToObj(psObj, \"%%Page: 1 1\\nsave\\n\", TCL_INDEX_NONE);\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%.1f %.1f translate\\n\", psInfo.pageX, psInfo.pageY);\n\tif (psInfo.rotate) {\n\t    Tcl_AppendToObj(psObj, \"90 rotate\\n\", TCL_INDEX_NONE);\n\t}\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%.4g %.4g scale\\n\", psInfo.scale, psInfo.scale);\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%d %d translate\\n\", deltaX - psInfo.x, deltaY);\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g \"\n\t\t\"lineto closepath clip newpath\\n\",\n\t\tpsInfo.x, Tk_PostscriptY((double)psInfo.y,\n\t\t\t(Tk_PostscriptInfo)psInfoPtr),\n\t\tpsInfo.x2, Tk_PostscriptY((double)psInfo.y,\n\t\t\t(Tk_PostscriptInfo)psInfoPtr),\n\t\tpsInfo.x2, Tk_PostscriptY((double)psInfo.y2,\n\t\t\t(Tk_PostscriptInfo)psInfoPtr),\n\t\tpsInfo.x, Tk_PostscriptY((double)psInfo.y2,\n\t\t\t(Tk_PostscriptInfo)psInfoPtr));\n\tif (psInfo.chan != NULL) {\n\t    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {\n\t\tgoto channelWriteFailed;\n\t    }\n\t    Tcl_DecrRefCount(psObj);\n\t    psObj = Tcl_NewObj();\n\t}\n    }\n\n    /*\n     * Iterate through all the items, having each relevant one draw itself.\n     * Quit if any of the items returns an error.\n     */\n\n    result = TCL_OK;\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif ((itemPtr->x1 >= psInfo.x2) || (itemPtr->x2 < psInfo.x)\n\t\t|| (itemPtr->y1 >= psInfo.y2) || (itemPtr->y2 < psInfo.y)) {\n\t    continue;\n\t}\n\tif (itemPtr->typePtr->postscriptProc == NULL) {\n\t    continue;\n\t}\n\tif (itemPtr->state == TK_STATE_HIDDEN) {\n\t    continue;\n\t}\n\n\tresult = itemPtr->typePtr->postscriptProc(interp,\n\t\t(Tk_Canvas) canvasPtr, itemPtr, 0);\n\tif (result != TCL_OK) {\n\t    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t    \"\\n    (generating Postscript for item %d)\",\n\t\t    (int)itemPtr->id));\n\t    goto cleanup;\n\t}\n\n\tTcl_AppendToObj(psObj, \"gsave\\n\", TCL_INDEX_NONE);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\tTcl_AppendToObj(psObj, \"grestore\\n\", TCL_INDEX_NONE);\n\tTcl_ResetResult(interp);\n\n\tif (psInfo.chan != NULL) {\n\t    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {\n\t\tgoto channelWriteFailed;\n\t    }\n\t    Tcl_DecrRefCount(psObj);\n\t    psObj = Tcl_NewObj();\n\t}\n    }\n\n    /*\n     * Output page-end information, such as commands to print the page and\n     * document trailer stuff.\n     */\n\n    if (psInfo.prolog) {\n\tTcl_AppendToObj(psObj,\n\t\t\"restore showpage\\n\\n\"\n\t\t\"%%Trailer\\n\"\n\t\t\"end\\n\"\n\t\t\"%%EOF\\n\", TCL_INDEX_NONE);\n\n\tif (psInfo.chan != NULL) {\n\t    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {\n\t\tgoto channelWriteFailed;\n\t    }\n\t}\n    }\n\n    if (psInfo.chan == NULL) {\n\tTcl_SetObjResult(interp, psObj);\n\tpsObj = Tcl_NewObj();\n    }\n\n    /*\n     * Clean up psInfo to release malloc'ed stuff.\n     */\n\n  cleanup:\n    if (psInfo.pageXObj != NULL) {\n\tTcl_DecrRefCount(psInfo.pageXObj);\n    }\n    if (psInfo.pageYObj != NULL) {\n\tTcl_DecrRefCount(psInfo.pageYObj);\n    }\n    if (psInfo.pageWidthObj != NULL) {\n\tTcl_DecrRefCount(psInfo.pageWidthObj);\n    }\n    if (psInfo.pageHeightObj != NULL) {\n\tTcl_DecrRefCount(psInfo.pageHeightObj);\n    }\n    if (psInfo.fontVarObj != NULL) {\n\tTcl_DecrRefCount(psInfo.fontVarObj);\n    }\n    if (psInfo.colorVarObj != NULL) {\n\tTcl_DecrRefCount(psInfo.colorVarObj);\n    }\n    if (psInfo.colorModeObj != NULL) {\n\tTcl_DecrRefCount(psInfo.colorModeObj);\n    }\n    if (psInfo.fileNameObj != NULL) {\n\tTcl_DecrRefCount(psInfo.fileNameObj);\n    }\n    if ((psInfo.chan != NULL) && (psInfo.channelNameObj == NULL)) {\n\tTcl_Close(interp, psInfo.chan);\n    }\n    if (psInfo.channelNameObj != NULL) {\n\tTcl_DecrRefCount(psInfo.channelNameObj);\n    }\n    Tcl_DeleteHashTable(&psInfo.fontTable);\n    canvasPtr->psInfo = (Tk_PostscriptInfo) oldInfoPtr;\n    Tcl_DecrRefCount(preambleObj);\n    Tcl_DecrRefCount(psObj);\n    return result;\n}\n\f\nstatic inline Tcl_Obj *\nGetPostscriptBuffer(\n    Tcl_Interp *interp)\n{\n    Tcl_Obj *psObj = Tcl_GetObjResult(interp);\n\n    if (Tcl_IsShared(psObj)) {\n\tpsObj = Tcl_DuplicateObj(psObj);\n\tTcl_SetObjResult(interp, psObj);\n    }\n    return psObj;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptColor --\n *\n *\tThis function is called by individual canvas items when they want to\n *\tset a color value for output. Given information about an X color, this\n *\tfunction will generate Postscript commands to set up an appropriate\n *\tcolor in Postscript.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in the interp's result. If no error occurs, then\n *\tadditional Postscript will be appended to the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PostscriptColor(\n    Tcl_Interp *interp,\n    Tk_PostscriptInfo psInfo,\t/* Postscript info. */\n    XColor *colorPtr)\t\t/* Information about color. */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    double red, green, blue;\n\n    if (psInfoPtr->prepass) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * If there is a color map defined, then look up the color's name in the\n     * map and use the Postscript commands found there, if there are any.\n     */\n\n    if (psInfoPtr->colorVarObj != NULL) {\n\tconst char *cmdString = Tcl_GetVar2(interp, Tcl_GetString(psInfoPtr->colorVarObj),\n\t\tTk_NameOfColor(colorPtr), 0);\n\n\tif (cmdString != NULL) {\n\t    Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),\n\t\t    \"%s\\n\", cmdString);\n\t    return TCL_OK;\n\t}\n    }\n\n    /*\n     * No color map entry for this color. Grab the color's intensities and\n     * output Postscript commands for them. Special note: X uses a range of\n     * 0-65535 for intensities, but most displays only use a range of 0-255,\n     * which maps to (0, 256, 512, ... 65280) in the X scale. This means that\n     * there's no way to get perfect white, since the highest intensity is\n     * only 65280 out of 65535. To work around this problem, rescale the X\n     * intensity to a 0-255 scale and use that as the basis for the Postscript\n     * colors. This scheme still won't work if the display only uses 4 bits\n     * per color, but most diplays use at least 8 bits.\n     */\n\n    red = ((double) (((int) colorPtr->red) >> 8))/255.0;\n    green = ((double) (((int) colorPtr->green) >> 8))/255.0;\n    blue = ((double) (((int) colorPtr->blue) >> 8))/255.0;\n    Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),\n\t    \"%.3f %.3f %.3f setrgbcolor AdjustColor\\n\",\n\t    red, green, blue);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptFont --\n *\n *\tThis function is called by individual canvas items when they want to\n *\toutput text. Given information about an X font, this function will\n *\tgenerate Postscript commands to set up an appropriate font in\n *\tPostscript.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in the interp's result. If no error occurs, then\n *\tadditional Postscript will be appended to the interp's result.\n *\n * Side effects:\n *\tThe Postscript font name is entered into psInfoPtr->fontTable if it\n *\twasn't already there.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PostscriptFont(\n    Tcl_Interp *interp,\n    Tk_PostscriptInfo psInfo,\t/* Postscript Info. */\n    Tk_Font tkfont)\t\t/* Information about font in which text is to\n\t\t\t\t * be printed. */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    Tcl_DString ds;\n    int i, points;\n    const char *fontname;\n\n    /*\n     * First, look up the font's name in the font map, if there is one. If\n     * there is an entry for this font, it consists of a list containing font\n     * name and size. Use this information.\n     */\n\n    if (psInfoPtr->fontVarObj != NULL) {\n\tconst char *name = Tk_NameOfFont(tkfont);\n\tTcl_Obj **objv;\n\tTcl_Size objc;\n\tdouble size;\n\tTcl_Obj *list = Tcl_GetVar2Ex(interp, Tcl_GetString(psInfoPtr->fontVarObj), name, 0);\n\n\tif (list != NULL) {\n\t    if (Tcl_ListObjGetElements(interp, list, &objc, &objv) != TCL_OK\n\t\t    || objc != 2\n\t\t    || (fontname = Tcl_GetString(objv[0]))[0] == '\\0'\n\t\t    || strchr(fontname, ' ') != NULL\n\t\t    || Tcl_GetDoubleFromObj(interp, objv[1], &size) != TCL_OK\n\t\t    || size <= 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"bad font map entry for \\\"%s\\\": \\\"%s\\\"\",\n\t\t\tname, Tcl_GetString(list)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"FONTMAP\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),\n\t\t    \"/%s findfont %d scalefont%s setfont\\n\",\n\t\t    fontname, (int) size,\n\t\t    strncasecmp(fontname, \"Symbol\", 7) ? \" ISOEncode\" : \"\");\n\t    Tcl_CreateHashEntry(&psInfoPtr->fontTable, fontname, &i);\n\t    return TCL_OK;\n\t}\n    }\n\n    /*\n     * Nothing in the font map, so fall back to the old guessing technique.\n     */\n\n    Tcl_DStringInit(&ds);\n    points = Tk_PostscriptFontName(tkfont, &ds);\n    fontname = Tcl_DStringValue(&ds);\n    Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp),\n\t    \"/%s findfont %d scalefont%s setfont\\n\",\n\t    fontname, (int)(TkFontGetPoints(psInfoPtr->tkwin, points) + 0.5),\n\t    strncasecmp(fontname, \"Symbol\", 7) ? \" ISOEncode\" : \"\");\n    Tcl_CreateHashEntry(&psInfoPtr->fontTable, Tcl_DStringValue(&ds), &i);\n    Tcl_DStringFree(&ds);\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptBitmap --\n *\n *\tThis function is called to output the contents of a sub-region of a\n *\tbitmap in proper image data format for Postscript (i.e. data between\n *\tangle brackets, one bit per pixel).\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in the interp's result. If no error occurs, then\n *\tadditional Postscript will be appended to the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PostscriptBitmap(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tk_PostscriptInfo psInfo,\t/* Postscript info. */\n    Pixmap bitmap,\t\t/* Bitmap for which to generate Postscript. */\n    int startX, int startY,\t/* Coordinates of upper-left corner of\n\t\t\t\t * rectangular region to output. */\n    int width, int height)\t/* Height of rectangular region. */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n\n    if (psInfoPtr->prepass) {\n\treturn TCL_OK;\n    }\n\n    PostscriptBitmap(tkwin, bitmap, startX, startY, width, height,\n\t    GetPostscriptBuffer(interp));\n    return TCL_OK;\n}\n\nstatic void\nPostscriptBitmap(\n    Tk_Window tkwin,\n    Pixmap bitmap,\t\t/* Bitmap for which to generate Postscript. */\n    int startX, int startY,\t/* Coordinates of upper-left corner of\n\t\t\t\t * rectangular region to output. */\n    int width, int height,\t/* Height of rectangular region. */\n    Tcl_Obj *psObj)\t\t/* Where to append the postscript. */\n{\n    XImage *imagePtr;\n    int charsInLine, x, y, lastX, lastY, value, mask;\n    unsigned int totalWidth, totalHeight;\n    Window dummyRoot;\n    int dummyX, dummyY;\n    unsigned dummyBorderwidth, dummyDepth;\n\n    /*\n     * The following call should probably be a call to Tk_SizeOfBitmap\n     * instead, but it seems that we are occasionally invoked by custom item\n     * types that create their own bitmaps without registering them with Tk.\n     * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't\n     * matter here.\n     */\n\n    XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,\n\t    (int *) &dummyX, (int *) &dummyY, (unsigned int *) &totalWidth,\n\t    (unsigned int *) &totalHeight, &dummyBorderwidth, &dummyDepth);\n    imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0,\n\t    totalWidth, totalHeight, 1, XYPixmap);\n\n\n    if (!imagePtr) {\n\t/*\n\t * The XGetImage() function is apparently not implemented on this\n\t * system. Just skip the pixels, the Postscript will still be\n\t * syntactically correct.\n\t */\n\n\tTcl_AppendToObj(psObj, \"<>\", TCL_INDEX_NONE);\n\treturn;\n    }\n\n    Tcl_AppendToObj(psObj, \"<\", TCL_INDEX_NONE);\n    mask = 0x80;\n    value = 0;\n    charsInLine = 0;\n    lastX = startX + width - 1;\n    lastY = startY + height - 1;\n    for (y = lastY; y >= startY; y--) {\n\tfor (x = startX; x <= lastX; x++) {\n\t    if (XGetPixel(imagePtr, x, y)) {\n\t\tvalue |= mask;\n\t    }\n\t    mask >>= 1;\n\t    if (mask == 0) {\n\t\tTcl_AppendPrintfToObj(psObj, \"%02x\", value);\n\t\tmask = 0x80;\n\t\tvalue = 0;\n\t\tcharsInLine += 2;\n\t\tif (charsInLine >= 60) {\n\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t    charsInLine = 0;\n\t\t}\n\t    }\n\t}\n\tif (mask != 0x80) {\n\t    Tcl_AppendPrintfToObj(psObj, \"%02x\", value);\n\t    mask = 0x80;\n\t    value = 0;\n\t    charsInLine += 2;\n\t}\n    }\n    Tcl_AppendToObj(psObj, \">\", TCL_INDEX_NONE);\n\n    XDestroyImage(imagePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptStipple --\n *\n *\tThis function is called by individual canvas items when they have\n *\tcreated a path that they'd like to be filled with a stipple pattern.\n *\tGiven information about an X bitmap, this function will generate\n *\tPostscript commands to fill the current clip region using a stipple\n *\tpattern defined by the bitmap.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in the interp's result. If no error occurs, then\n *\tadditional Postscript will be appended to the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PostscriptStipple(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tk_PostscriptInfo psInfo,\t/* Interpreter for returning Postscript or\n\t\t\t\t * error message. */\n    Pixmap bitmap)\t\t/* Bitmap to use for stippling. */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    int width, height;\n    Window dummyRoot;\n    int dummyX, dummyY;\n    unsigned dummyBorderwidth, dummyDepth;\n    Tcl_Obj *psObj;\n\n    if (psInfoPtr->prepass) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * The following call should probably be a call to Tk_SizeOfBitmap\n     * instead, but it seems that we are occasionally invoked by custom item\n     * types that create their own bitmaps without registering them with Tk.\n     * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't\n     * matter here.\n     */\n\n    XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,\n\t    (int *) &dummyX, (int *) &dummyY, (unsigned *) &width,\n\t    (unsigned *) &height, &dummyBorderwidth, &dummyDepth);\n\n    psObj = GetPostscriptBuffer(interp);\n    Tcl_AppendPrintfToObj(psObj, \"%d %d \", width, height);\n    PostscriptBitmap(tkwin, bitmap, 0, 0, width, height, psObj);\n    Tcl_AppendToObj(psObj, \" StippleFill\\n\", TCL_INDEX_NONE);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptY --\n *\n *\tGiven a y-coordinate in local coordinates, this function returns a\n *\ty-coordinate to use for Postscript output. Required because canvases\n *\thave their origin in the top-left, but postscript pages have their\n *\torigin in the bottom left.\n *\n * Results:\n *\tReturns the Postscript coordinate that corresponds to \"y\".\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTk_PostscriptY(\n    double y,\t\t\t/* Y-coordinate in canvas coords. */\n    Tk_PostscriptInfo psInfo)\t/* Postscript info */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n\n    return psInfoPtr->y2 - y;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptPath --\n *\n *\tGiven an array of points for a path, generate Postscript commands to\n *\tcreate the path.\n *\n * Results:\n *\tPostscript commands get appended to what's in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_PostscriptPath(\n    Tcl_Interp *interp,\n    Tk_PostscriptInfo psInfo,\t/* Canvas on whose behalf Postscript is being\n\t\t\t\t * generated. */\n    double *coordPtr,\t\t/* Pointer to first in array of 2*numPoints\n\t\t\t\t * coordinates giving points for path. */\n    Tcl_Size numPoints)\t\t/* Number of points at *coordPtr. */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    Tcl_Obj *psObj;\n\n    if (psInfoPtr->prepass) {\n\treturn;\n    }\n\n    psObj = GetPostscriptBuffer(interp);\n    Tcl_AppendPrintfToObj(psObj, \"%.15g %.15g moveto\\n\",\n\t    coordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo));\n    for (numPoints--, coordPtr += 2; numPoints > 0;\n\t    numPoints--, coordPtr += 2) {\n\tTcl_AppendPrintfToObj(psObj, \"%.15g %.15g lineto\\n\",\n\t\tcoordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo));\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetPostscriptPoints --\n *\n *\tGiven a string, returns the number of Postscript points corresponding\n *\tto that string.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the screen distance is stored\n *\tat *doublePtr; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetPostscriptPoints(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    Tcl_Obj *value,\t\t\t/* Describing a screen distance. */\n    double *doublePtr)\t\t/* Place to store converted result. */\n{\n    const char *rest, *string = Tcl_GetString(value);\n    double d;\n    Tcl_DString ds;\n\n    if (Tcl_GetDoubleFromObj(NULL, value, &d) == TCL_OK) {\n\t*doublePtr = d;\n\treturn TCL_OK;\n    }\n    rest = string + strlen(string);\n    while ((rest > string) && isspace(UCHAR(rest[-1]))) {\n\t--rest; /* skip all spaces at the end */\n    }\n    if (rest > string) {\n\t--rest; /* point to the character just before the last space */\n    }\n\tif (rest == string) {\n\terror:\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"bad distance \\\"%s\\\"\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"POINTS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, string, rest-string);\n    if (Tcl_GetDouble(NULL, Tcl_DStringValue(&ds), &d) != TCL_OK) {\n\tTcl_DStringFree(&ds);\n\tgoto error;\n    }\n    Tcl_DStringFree(&ds);\n    switch (*rest) {\n    case 'c':\n\td *= 72.0/2.54;\n\tbreak;\n    case 'i':\n\td *= 72.0;\n\tbreak;\n    case 'm':\n\td *= 72.0/25.4;\n\tbreak;\n    case 'p':\n\tbreak;\n    default:\n\tgoto error;\n    }\n    *doublePtr = d;\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkImageGetColor --\n *\n *\tThis function converts a pixel value to three floating point numbers,\n *\trepresenting the amount of red, green, and blue in that pixel on the\n *\tscreen. It makes use of colormap data passed as an argument, and\n *\tshould work for all Visual types.\n *\n *\tThis implementation is bogus on Windows because the colormap data is\n *\tnever filled in. Instead all postscript generated data coming through\n *\there is expected to be RGB color data. To handle lower bit-depth\n *\timages properly, XQueryColors must be implemented for Windows.\n *\n * Results:\n *\tReturns red, green, and blue color values in the range 0 to 1. There\n *\tare no error returns.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\n#ifdef _WIN32\n#include <windows.h>\n\n/*\n * We could just define these instead of pulling in windows.h.\n #define GetRValue(rgb)\t((BYTE)(rgb))\n #define GetGValue(rgb)\t((BYTE)(((WORD)(rgb)) >> 8))\n #define GetBValue(rgb)\t((BYTE)((rgb)>>16))\n */\n\n#else /* !_WIN32 */\n\n#define GetRValue(rgb)\t((rgb & cdata->red_mask) >> cdata->red_shift)\n#define GetGValue(rgb)\t((rgb & cdata->green_mask) >> cdata->green_shift)\n#define GetBValue(rgb)\t((rgb & cdata->blue_mask) >> cdata->blue_shift)\n\n#endif /* _WIN32 */\n\n#if defined(_WIN32) || defined(MAC_OSX_TK)\nstatic void\nTkImageGetColor(\n    TkColormapData *cdata,\n    unsigned long pixel,\t/* Pixel value to look up */\n    double *red, double *green, double *blue)\n\t\t\t\t/* Color data to return */\n{\n\t(void)cdata;\n\n    *red   = (double) GetRValue(pixel) / 255.0;\n    *green = (double) GetGValue(pixel) / 255.0;\n    *blue  = (double) GetBValue(pixel) / 255.0;\n}\n#else /* ! (_WIN32 || MAC_OSX_TK) */\nstatic void\nTkImageGetColor(\n    TkColormapData *cdata,\t/* Colormap data */\n    unsigned long pixel,\t/* Pixel value to look up */\n    double *red, double *green, double *blue)\n\t\t\t\t/* Color data to return */\n{\n    if (cdata->separated) {\n\tint r = GetRValue(pixel);\n\tint g = GetGValue(pixel);\n\tint b = GetBValue(pixel);\n\n\t*red   = cdata->colors[r].red / 65535.0;\n\t*green = cdata->colors[g].green / 65535.0;\n\t*blue  = cdata->colors[b].blue / 65535.0;\n    } else {\n\t*red   = cdata->colors[pixel].red / 65535.0;\n\t*green = cdata->colors[pixel].green / 65535.0;\n\t*blue  = cdata->colors[pixel].blue / 65535.0;\n    }\n}\n#endif /* _WIN32 || MAC_OSX_TK */\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkPostscriptImage --\n *\n *\tThis function is called to output the contents of an image in\n *\tPostscript, using a format appropriate for the current color mode\n *\t(i.e. one bit per pixel in monochrome, one byte per pixel in gray, and\n *\tthree bytes per pixel in color).\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkPostscriptImage(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tk_PostscriptInfo psInfo,\t/* postscript info */\n    XImage *ximage,\t\t/* Image to draw */\n    int x, TCL_UNUSED(int),\t\t/* First pixel to output */\n    int width, int height)\t/* Width and height of area */\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    int xx, yy, band, maxRows;\n    double red, green, blue;\n    int bytesPerLine = 0, maxWidth = 0;\n    int level = psInfoPtr->colorLevel;\n    Colormap cmap;\n    int i, ncolors;\n    Visual *visual;\n    TkColormapData cdata;\n    Tcl_Obj *psObj;\n\n    if (psInfoPtr->prepass) {\n\treturn TCL_OK;\n    }\n\n    cmap = Tk_Colormap(tkwin);\n    visual = Tk_Visual(tkwin);\n\n    /*\n     * Obtain information about the colormap, ie the mapping between pixel\n     * values and RGB values. The code below should work for all Visual types.\n     */\n\n    ncolors = visual->map_entries;\n    cdata.colors = (XColor *)Tcl_Alloc(sizeof(XColor) * ncolors);\n    cdata.ncolors = ncolors;\n\n    if (visual->c_class == DirectColor || visual->c_class == TrueColor) {\n\tcdata.separated = 1;\n\tcdata.red_mask = visual->red_mask;\n\tcdata.green_mask = visual->green_mask;\n\tcdata.blue_mask = visual->blue_mask;\n\tcdata.red_shift = 0;\n\tcdata.green_shift = 0;\n\tcdata.blue_shift = 0;\n\n\twhile ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) {\n\t    cdata.red_shift ++;\n\t}\n\twhile ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) {\n\t    cdata.green_shift ++;\n\t}\n\twhile ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) {\n\t    cdata.blue_shift ++;\n\t}\n\n\tfor (i = 0; i < ncolors; i ++) {\n\t    cdata.colors[i].pixel =\n\t\t    ((i << cdata.red_shift) & cdata.red_mask) |\n\t\t    ((i << cdata.green_shift) & cdata.green_mask) |\n\t\t    ((i << cdata.blue_shift) & cdata.blue_mask);\n\t}\n    } else {\n\tcdata.separated=0;\n\tfor (i = 0; i < ncolors; i ++) {\n\t    cdata.colors[i].pixel = i;\n\t}\n    }\n\n    if (visual->c_class == StaticGray || visual->c_class == GrayScale) {\n\tcdata.color = 0;\n    } else {\n\tcdata.color = 1;\n    }\n\n    XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);\n\n    /*\n     * Figure out which color level to use (possibly lower than the one\n     * specified by the user). For example, if the user specifies color with\n     * monochrome screen, use gray or monochrome mode instead.\n     */\n\n    if (!cdata.color && level >= 2) {\n\tlevel = 1;\n    }\n\n    if (!cdata.color && cdata.ncolors == 2) {\n\tlevel = 0;\n    }\n\n    /*\n     * Check that at least one row of the image can be represented with a\n     * string less than 64 KB long (this is a limit in the Postscript\n     * interpreter).\n     */\n\n    switch (level) {\n    case 0: bytesPerLine = (width + 7) / 8;  maxWidth = 240000; break;\n    case 1: bytesPerLine = width;\t     maxWidth = 60000;  break;\n    default: bytesPerLine = 3 * width;\t     maxWidth = 20000;  break;\n    }\n\n    if (bytesPerLine > 60000) {\n\tTcl_ResetResult(interp);\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't generate Postscript for images more than %d pixels wide\",\n\t\tmaxWidth));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"MEMLIMIT\", (char *)NULL);\n\tTcl_Free(cdata.colors);\n\treturn TCL_ERROR;\n    }\n\n    maxRows = 60000 / bytesPerLine;\n    psObj = GetPostscriptBuffer(interp);\n\n    for (band = height-1; band >= 0; band -= maxRows) {\n\tint rows = (band >= maxRows) ? maxRows : band + 1;\n\tint lineLen = 0;\n\n\tswitch (level) {\n\tcase 0:\n\t    Tcl_AppendPrintfToObj(psObj, \"%d %d 1 matrix {\\n<\", width, rows);\n\t    break;\n\tcase 1:\n\t    Tcl_AppendPrintfToObj(psObj, \"%d %d 8 matrix {\\n<\", width, rows);\n\t    break;\n\tdefault:\n\t    Tcl_AppendPrintfToObj(psObj, \"%d %d 8 matrix {\\n<\", width, rows);\n\t    break;\n\t}\n\tfor (yy = band; yy > band - rows; yy--) {\n\t    switch (level) {\n\t    case 0: {\n\t\t/*\n\t\t * Generate data for image in monochrome mode. No attempt at\n\t\t * dithering is made--instead, just set a threshold.\n\t\t */\n\n\t\tunsigned char mask = 0x80;\n\t\tunsigned char data = 0x00;\n\n\t\tfor (xx = x; xx< x+width; xx++) {\n\t\t    TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),\n\t\t\t    &red, &green, &blue);\n\t\t    if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5) {\n\t\t\tdata |= mask;\n\t\t    }\n\t\t    mask >>= 1;\n\t\t    if (mask == 0) {\n\t\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\t\tlineLen += 2;\n\t\t\tif (lineLen > 60) {\n\t\t\t    lineLen = 0;\n\t\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t\t}\n\t\t\tmask = 0x80;\n\t\t\tdata = 0x00;\n\t\t    }\n\t\t}\n\t\tif ((width % 8) != 0) {\n\t\t    Tcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\t    mask = 0x80;\n\t\t    data = 0x00;\n\t\t}\n\t\tbreak;\n\t    }\n\t    case 1:\n\t\t/*\n\t\t * Generate data in gray mode; in this case, take a weighted\n\t\t * sum of the red, green, and blue values.\n\t\t */\n\n\t\tfor (xx = x; xx < x+width; xx ++) {\n\t\t    TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),\n\t\t\t    &red, &green, &blue);\n\t\t    Tcl_AppendPrintfToObj(psObj, \"%02X\",\n\t\t\t    (int) floor(0.5 + 255.0 *\n\t\t\t    (0.30 * red + 0.59 * green + 0.11 * blue)));\n\t\t    lineLen += 2;\n\t\t    if (lineLen > 60) {\n\t\t\tlineLen = 0;\n\t\t\tTcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t    }\n\t\t}\n\t\tbreak;\n\t    default:\n\t\t/*\n\t\t * Finally, color mode. Here, just output the red, green, and\n\t\t * blue values directly.\n\t\t */\n\n\t\tfor (xx = x; xx < x+width; xx++) {\n\t\t    TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),\n\t\t\t    &red, &green, &blue);\n\t\t    Tcl_AppendPrintfToObj(psObj, \"%02X%02X%02X\",\n\t\t\t    (int) floor(0.5 + 255.0 * red),\n\t\t\t    (int) floor(0.5 + 255.0 * green),\n\t\t\t    (int) floor(0.5 + 255.0 * blue));\n\t\t    lineLen += 6;\n\t\t    if (lineLen > 60) {\n\t\t\tlineLen = 0;\n\t\t\tTcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t    }\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\tswitch (level) {\n\tcase 0: case 1:\n\t    Tcl_AppendToObj(psObj, \">\\n} image\\n\", TCL_INDEX_NONE); break;\n\tdefault:\n\t    Tcl_AppendToObj(psObj, \">\\n} false 3 colorimage\\n\", TCL_INDEX_NONE); break;\n\t}\n\tTcl_AppendPrintfToObj(psObj, \"0 %d translate\\n\", rows);\n    }\n    Tcl_Free(cdata.colors);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PostscriptPhoto --\n *\n *\tThis function is called to output the contents of a photo image in\n *\tPostscript, using a format appropriate for the requested postscript\n *\tcolor mode (i.e. one byte per pixel in gray, and three bytes per pixel\n *\tin color).\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to the interpreter's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PostscriptPhoto(\n    Tcl_Interp *interp,\n    Tk_PhotoImageBlock *blockPtr,\n    Tk_PostscriptInfo psInfo,\n    int width, int height)\n{\n    TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;\n    int colorLevel = psInfoPtr->colorLevel;\n    const char *displayOperation, *decode;\n    unsigned char *pixelPtr;\n    int bpc, xx, yy, lineLen, alpha;\n    float red, green, blue;\n    int bytesPerLine = 0, maxWidth = 0;\n    unsigned char opaque = 255;\n    unsigned char *alphaPtr;\n    int alphaOffset, alphaPitch, alphaIncr;\n    Tcl_Obj *psObj;\n\n    if (psInfoPtr->prepass) {\n\treturn TCL_OK;\n    }\n\n    if (colorLevel != 0) {\n\t/*\n\t * Color and gray-scale code.\n\t */\n\n\tdisplayOperation = \"TkPhotoColor\";\n    } else {\n\t/*\n\t * Monochrome-only code\n\t */\n\n\tdisplayOperation = \"TkPhotoMono\";\n    }\n\n    /*\n     * Check that at least one row of the image can be represented with a\n     * string less than 64 KB long (this is a limit in the Postscript\n     * interpreter).\n     */\n\n    switch (colorLevel) {\n    case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;\n    case 1: bytesPerLine = width;\t    maxWidth = 60000;  break;\n    default: bytesPerLine = 3 * width;\t    maxWidth = 20000;  break;\n    }\n    if (bytesPerLine > 60000) {\n\tTcl_ResetResult(interp);\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't generate Postscript for images more than %d pixels wide\",\n\t\tmaxWidth));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"MEMLIMIT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Set up the postscript code except for the image-data stream.\n     */\n\n    psObj = GetPostscriptBuffer(interp);\n    switch (colorLevel) {\n    case 0:\n\tTcl_AppendToObj(psObj, \"/DeviceGray setcolorspace\\n\\n\", TCL_INDEX_NONE);\n\tdecode = \"1 0\";\n\tbpc = 1;\n\tbreak;\n    case 1:\n\tTcl_AppendToObj(psObj, \"/DeviceGray setcolorspace\\n\\n\", TCL_INDEX_NONE);\n\tdecode = \"0 1\";\n\tbpc = 8;\n\tbreak;\n    default:\n\tTcl_AppendToObj(psObj, \"/DeviceRGB setcolorspace\\n\\n\", TCL_INDEX_NONE);\n\tdecode = \"0 1 0 1 0 1\";\n\tbpc = 8;\n\tbreak;\n    }\n\n    Tcl_AppendPrintfToObj(psObj,\n\t    \"<<\\n  /ImageType 1\\n\"\n\t    \"  /Width %d\\n  /Height %d\\n  /BitsPerComponent %d\\n\"\n\t    \"  /DataSource currentfile\\n  /ASCIIHexDecode filter\\n\"\n\t    \"  /ImageMatrix [1 0 0 -1 0 %d]\\n  /Decode [%s]\\n>>\\n\"\n\t    \"1 %s\\n\",\n\t    width, height, bpc, height, decode, displayOperation);\n\n    /*\n     * Check the PhotoImageBlock information. We assume that:\n     *     if pixelSize is 1,2 or 4, the image is R,G,B,A;\n     *     if pixelSize is 3, the image is R,G,B and offset[3] is bogus.\n     */\n\n    if (blockPtr->pixelSize == 3) {\n\t/*\n\t * No alpha information: the whole image is opaque.\n\t */\n\n\talphaPtr = &opaque;\n\talphaPitch = alphaIncr = alphaOffset = 0;\n    } else {\n\t/*\n\t * Set up alpha handling.\n\t */\n\n\talphaPtr = blockPtr->pixelPtr;\n\talphaPitch = blockPtr->pitch;\n\talphaIncr = blockPtr->pixelSize;\n\talphaOffset = blockPtr->offset[3];\n    }\n\n    for (yy = 0, lineLen=0; yy < height; yy++) {\n\tswitch (colorLevel) {\n\tcase 0: {\n\t    /*\n\t     * Generate data for image in monochrome mode. No attempt at\n\t     * dithering is made--instead, just set a threshold. To handle\n\t     * transparencies we need to output two lines: one for the black\n\t     * pixels, one for the white ones.\n\t     */\n\n\t    unsigned char mask = 0x80;\n\t    unsigned char data = 0x00;\n\n\t    for (xx = 0; xx< width; xx ++) {\n\t\tpixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)\n\t\t\t+ (xx *blockPtr->pixelSize);\n\n\t\tred = pixelPtr[blockPtr->offset[0]];\n\t\tgreen = pixelPtr[blockPtr->offset[1]];\n\t\tblue = pixelPtr[blockPtr->offset[2]];\n\n\t\talpha = *(alphaPtr + (yy * alphaPitch)\n\t\t\t+ (xx * alphaIncr) + alphaOffset);\n\n\t\t/*\n\t\t * If pixel is less than threshold, then it is black.\n\t\t */\n\n\t\tif ((alpha != 0) &&\n\t\t\t(0.3086*red + 0.6094*green + 0.082*blue < 128)) {\n\t\t    data |= mask;\n\t\t}\n\t\tmask >>= 1;\n\t\tif (mask == 0) {\n\t\t    Tcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\t    lineLen += 2;\n\t\t    if (lineLen >= 60) {\n\t\t\tlineLen = 0;\n\t\t\tTcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t    }\n\t\t    mask = 0x80;\n\t\t    data = 0x00;\n\t\t}\n\t    }\n\t    if ((width % 8) != 0) {\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\tmask = 0x80;\n\t\tdata = 0x00;\n\t    }\n\n\t    mask = 0x80;\n\t    data = 0x00;\n\t    for (xx=0 ; xx<width ; xx++) {\n\t\tpixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)\n\t\t\t+ (xx *blockPtr->pixelSize);\n\n\t\tred = pixelPtr[blockPtr->offset[0]];\n\t\tgreen = pixelPtr[blockPtr->offset[1]];\n\t\tblue = pixelPtr[blockPtr->offset[2]];\n\n\t\talpha = *(alphaPtr + (yy * alphaPitch)\n\t\t\t+ (xx * alphaIncr) + alphaOffset);\n\n\t\t/*\n\t\t * If pixel is greater than threshold, then it is white.\n\t\t */\n\n\t\tif ((alpha != 0) &&\n\t\t\t(0.3086*red + 0.6094*green + 0.082*blue >= 128)) {\n\t\t    data |= mask;\n\t\t}\n\t\tmask >>= 1;\n\t\tif (mask == 0) {\n\t\t    Tcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\t    lineLen += 2;\n\t\t    if (lineLen >= 60) {\n\t\t\tlineLen = 0;\n\t\t\tTcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t    }\n\t\t    mask = 0x80;\n\t\t    data = 0x00;\n\t\t}\n\t    }\n\t    if ((width % 8) != 0) {\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", data);\n\t\tmask = 0x80;\n\t\tdata = 0x00;\n\t    }\n\t    break;\n\t}\n\tcase 1: {\n\t    /*\n\t     * Generate transparency data. We must prevent a transparent value\n\t     * of 0 because of a bug in some HP printers.\n\t     */\n\n\t    for (xx = 0; xx < width; xx ++) {\n\t\talpha = *(alphaPtr + (yy * alphaPitch)\n\t\t\t+ (xx * alphaIncr) + alphaOffset);\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", alpha | 0x01);\n\t\tlineLen += 2;\n\t\tif (lineLen >= 60) {\n\t\t    lineLen = 0;\n\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t}\n\t    }\n\n\t    /*\n\t     * Generate data in gray mode; in this case, take a weighted sum\n\t     * of the red, green, and blue values.\n\t     */\n\n\t    for (xx = 0; xx < width; xx ++) {\n\t\tpixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)\n\t\t\t+ (xx *blockPtr->pixelSize);\n\n\t\tred = pixelPtr[blockPtr->offset[0]];\n\t\tgreen = pixelPtr[blockPtr->offset[1]];\n\t\tblue = pixelPtr[blockPtr->offset[2]];\n\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", (int) floor(0.5 +\n\t\t\t( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));\n\t\tlineLen += 2;\n\t\tif (lineLen >= 60) {\n\t\t    lineLen = 0;\n\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t}\n\t    }\n\t    break;\n\t}\n\tdefault:\n\t    /*\n\t     * Generate transparency data. We must prevent a transparent value\n\t     * of 0 because of a bug in some HP printers.\n\t     */\n\n\t    for (xx = 0; xx < width; xx ++) {\n\t\talpha = *(alphaPtr + (yy * alphaPitch)\n\t\t\t+ (xx * alphaIncr) + alphaOffset);\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X\", alpha | 0x01);\n\t\tlineLen += 2;\n\t\tif (lineLen >= 60) {\n\t\t    lineLen = 0;\n\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t}\n\t    }\n\n\t    /*\n\t     * Finally, color mode. Here, just output the red, green, and blue\n\t     * values directly.\n\t     */\n\n\t    for (xx = 0; xx < width; xx ++) {\n\t\tpixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch)\n\t\t\t+ (xx * blockPtr->pixelSize);\n\n\t\tTcl_AppendPrintfToObj(psObj, \"%02X%02X%02X\",\n\t\t\tpixelPtr[blockPtr->offset[0]],\n\t\t\tpixelPtr[blockPtr->offset[1]],\n\t\t\tpixelPtr[blockPtr->offset[2]]);\n\t\tlineLen += 6;\n\t\tif (lineLen >= 60) {\n\t\t    lineLen = 0;\n\t\t    Tcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n\t\t}\n\t    }\n\t    break;\n\t}\n    }\n\n    /*\n     * The end-of-data marker.\n     */\n\n    Tcl_AppendToObj(psObj, \">\\n\", TCL_INDEX_NONE);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvText.c",
    "content": "/*\n * tkCanvText.c --\n *\n *\tThis file implements text items for canvas widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The structure below defines the record for each text item.\n */\n\ntypedef struct TextItem {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_CanvasTextInfo *textInfoPtr;\n\t\t\t\t/* Pointer to a structure containing\n\t\t\t\t * information about the selection and\n\t\t\t\t * insertion cursor. The structure is owned by\n\t\t\t\t * (and shared with) the generic canvas\n\t\t\t\t * code. */\n    /*\n     * Fields that are set by widget commands other than \"configure\".\n     */\n\n    double x, y;\t\t/* Positioning point for text. */\n    Tcl_Size insertPos;\t\t/* Character index of character just before\n\t\t\t\t * which the insertion cursor is displayed. */\n\n    /*\n     * Configuration settings that are updated by Tk_ConfigureWidget.\n     */\n\n    Tk_Anchor anchor;\t\t/* Where to anchor text relative to (x,y). */\n    Tk_TSOffset tsoffset;\n    XColor *color;\t\t/* Color for text. */\n    XColor *activeColor;\t/* Color for text. */\n    XColor *disabledColor;\t/* Color for text. */\n    Tk_Font tkfont;\t\t/* Font for drawing text. */\n    Tk_Justify justify;\t\t/* Justification mode for text. */\n    Pixmap stipple;\t\t/* Stipple bitmap for text, or None. */\n    Pixmap activeStipple;\t/* Stipple bitmap for text, or None. */\n    Pixmap disabledStipple;\t/* Stipple bitmap for text, or None. */\n    Tcl_Obj *textObj;\t\t/* Text for item (malloc-ed). */\n    Tcl_Obj *widthObj;\t\t/* Width of lines for word-wrap, pixels. Zero\n\t\t\t\t * means no word-wrap. */\n    int underline;\t\t/* Index of character to put underline beneath\n\t\t\t\t * or INT_MIN for no underlining. */\n    double angle;\t\t/* What angle, in degrees, to draw the text\n\t\t\t\t * at. */\n\n    /*\n     * Fields whose values are derived from the current values of the\n     * configuration settings above.\n     */\n\n    Tk_TextLayout textLayout;\t/* Cached text layout information. */\n    int actualWidth;\t\t/* Width of text as computed. Used to make\n\t\t\t\t * selections of wrapped text display\n\t\t\t\t * right. */\n    double drawOrigin[2];\t/* Where we start drawing from. */\n    GC gc;\t\t\t/* Graphics context for drawing text. */\n    GC selTextGC;\t\t/* Graphics context for selected text. */\n    GC cursorOffGC;\t\t/* If not None, this gives a graphics context\n\t\t\t\t * to use to draw the insertion cursor when\n\t\t\t\t * it's off. Used if the selection and\n\t\t\t\t * insertion cursor colors are the same. */\n    double sine;\t\t/* Sine of angle field. */\n    double cosine;\t\t/* Cosine of angle field. */\n} TextItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)\n};\n\nstatic int\nUnderlineParseProc(\n    TCL_UNUSED(void *),\t/* Not used.*/\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item (ignored). */\n{\n    int *underlinePtr = (int *) (widgRec + offset);\n    Tcl_Obj obj;\n    int code;\n    Tcl_Size underline;\n\n    if (value == NULL || *value == 0) {\n\t*underlinePtr = INT_MIN; /* No underline */\n\treturn TCL_OK;\n    }\n\n    obj.refCount = 1;\n    obj.bytes = (char *)value;\n    obj.length = strlen(value);\n    obj.typePtr = NULL;\n    code = TkGetIntForIndex(&obj, TCL_INDEX_NONE, 0, &underline);\n    if (code == TCL_OK) {\n\tif (underline < INT_MIN) {\n\t    underline = INT_MIN;\n\t} else if (underline > INT_MAX) {\n\t    underline = INT_MAX;\n\t}\n\t*underlinePtr = (int)underline;\n\n    } else {\n\tTcl_AppendResult(interp, \"bad index \\\"\", value,\n\t\t\"\\\": must be integer?[+-]integer?, end?[+-]integer?, or \\\"\\\"\", (char *)NULL);\n    }\n\treturn code;\n}\n\nstatic const char *\nUnderlinePrintProc(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Pointer to record for item. */\n    Tcl_FreeProc **freeProcPtr)\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    int underline = *(int *)(widgRec + offset);\n    char *p;\n\n    if (underline == INT_MIN) {\n\tp = (char *)\"\";\n\t*freeProcPtr = TCL_STATIC;\n\treturn p;\n    } else if (underline == INT_MAX) {\n\tp = (char *)\"end+1\";\n\t*freeProcPtr = TCL_STATIC;\n\treturn p;\n    } else if (underline == -1) {\n\tp = (char *)\"end\";\n\t*freeProcPtr = TCL_STATIC;\n\treturn p;\n    }\n    p = (char *)Tcl_Alloc(32);\n    if (underline < 0) {\n\tsnprintf(p, 32, \"end%d\", 1 + underline);\n    } else {\n\tsnprintf(p, 32, \"%d\", underline);\n    }\n    *freeProcPtr = TCL_DYNAMIC;\n    return p;\n}\n\nstatic const Tk_CustomOption underlineOption = {\n    UnderlineParseProc, UnderlinePrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_COLOR, \"-activefill\", NULL, NULL,\n\tNULL, offsetof(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activestipple\", NULL, NULL,\n\tNULL, offsetof(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_ANCHOR, \"-anchor\", NULL, NULL,\n\t\"center\", offsetof(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_DOUBLE, \"-angle\", NULL, NULL,\n\t\"0.0\", offsetof(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_COLOR, \"-disabledfill\", NULL, NULL,\n\tNULL, offsetof(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledstipple\", NULL, NULL,\n\tNULL, offsetof(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-fill\", NULL, NULL,\n\tDEF_CANVITEM_OUTLINE, offsetof(TextItem, color), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_FONT, \"-font\", NULL, NULL,\n\tDEF_CANVTEXT_FONT, offsetof(TextItem, tkfont), 0, NULL},\n    {TK_CONFIG_JUSTIFY, \"-justify\", NULL, NULL,\n\t\"left\", offsetof(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", NULL, NULL,\n\t\"0,0\", offsetof(TextItem, tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_BITMAP, \"-stipple\", NULL, NULL,\n\tNULL, offsetof(TextItem, stipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_STRING, \"-text\", NULL, NULL,\n\t\"\", offsetof(TextItem, textObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-underline\", NULL, NULL, NULL,\n\toffsetof(TextItem, underline), TK_CONFIG_NULL_OK, &underlineOption},\n    {TK_CONFIG_PIXELS, \"-width\", NULL, NULL,\n\t\"0\", offsetof(TextItem, widthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tComputeTextBbox(Tk_Canvas canvas, TextItem *textPtr);\nstatic int\t\tConfigureText(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tCreateText(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteText(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayCanvText(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic Tcl_Size\tGetSelText(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size offset, char *buffer,\n\t\t\t    Tcl_Size maxBytes);\nstatic int\t\tGetTextIndex(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Obj *obj, Tcl_Size *indexPtr);\nstatic void\t\tScaleText(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tSetTextCursor(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size index);\nstatic int\t\tTextCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tTextDeleteChars(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size first, Tcl_Size last);\nstatic void\t\tTextInsert(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size beforeThis, Tcl_Obj *obj);\nstatic int\t\tTextToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic double\t\tTextToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *pointPtr);\nstatic int\t\tTextToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic void\t\tRotateText(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tTranslateText(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\n\n/*\n * The structures below defines the rectangle and oval item types by means of\n * functions that can be invoked by generic item code.\n */\n\nTk_ItemType tkTextType = {\n    \"text\",\t\t\t/* name */\n    sizeof(TextItem),\t\t/* itemSize */\n    CreateText,\t\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureText,\t\t/* configureProc */\n    TextCoords,\t\t\t/* coordProc */\n    DeleteText,\t\t\t/* deleteProc */\n    DisplayCanvText,\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    TextToPoint,\t\t/* pointProc */\n    TextToArea,\t\t\t/* areaProc */\n    TextToPostscript,\t\t/* postscriptProc */\n    ScaleText,\t\t\t/* scaleProc */\n    TranslateText,\t\t/* translateProc */\n    GetTextIndex,\t\t/* indexProc */\n    SetTextCursor,\t\t/* icursorProc */\n    GetSelText,\t\t\t/* selectionProc */\n    TextInsert,\t\t\t/* insertProc */\n    TextDeleteChars,\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateText,\t\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\n#define ROUND(d) ((int) floor((d) + 0.5))\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateText --\n *\n *\tThis function is invoked to create a new text item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the item\n *\tthen an error message is left in the interp's result; in this case\n *\titemPtr is left uninitialized so it can be safely freed by the caller.\n *\n * Side effects:\n *\tA new text item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateText(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing rectangle. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Carry out initialization that is needed in order to clean up after\n     * errors during the the remainder of this function.\n     */\n\n    textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);\n\n    textPtr->insertPos\t= 0;\n\n    textPtr->anchor\t= TK_ANCHOR_CENTER;\n    textPtr->tsoffset.flags = 0;\n    textPtr->tsoffset.xoffset = 0;\n    textPtr->tsoffset.yoffset = 0;\n    textPtr->color\t= NULL;\n    textPtr->activeColor = NULL;\n    textPtr->disabledColor = NULL;\n    textPtr->tkfont\t= NULL;\n    textPtr->justify\t= TK_JUSTIFY_LEFT;\n    textPtr->stipple\t= None;\n    textPtr->activeStipple = None;\n    textPtr->disabledStipple = None;\n    textPtr->textObj\t= NULL;\n    textPtr->widthObj\t= NULL;\n    textPtr->underline\t= INT_MIN;\n    textPtr->angle\t= 0.0;\n\n    textPtr->textLayout = NULL;\n    textPtr->actualWidth = 0;\n    textPtr->drawOrigin[0] = textPtr->drawOrigin[1] = 0.0;\n    textPtr->gc\t\t= NULL;\n    textPtr->selTextGC\t= NULL;\n    textPtr->cursorOffGC = NULL;\n    textPtr->sine\t= 0.0;\n    textPtr->cosine\t= 1.0;\n\n    /*\n     * Process the arguments to fill in the item record. Only 1 (list) or 2 (x\n     * y) coords are allowed.\n     */\n\n    if (objc == 1) {\n\ti = 1;\n    } else {\n\tconst char *arg = Tcl_GetString(objv[1]);\n\n\ti = 2;\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    i = 1;\n\t}\n    }\n    if ((TextCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {\n\tgoto error;\n    }\n    if (ConfigureText(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\ttext items. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTextCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    if (objc == 0) {\n\tTcl_Obj *obj = Tcl_NewObj();\n\tTcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);\n\n\tTcl_ListObjAppendElement(interp, obj, subobj);\n\tsubobj = Tcl_NewDoubleObj(textPtr->y);\n\tTcl_ListObjAppendElement(interp, obj, subobj);\n\tTcl_SetObjResult(interp, obj);\n\treturn TCL_OK;\n    } else if (objc > 2) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"TEXT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 1) {\n\tif (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t(Tcl_Obj ***) &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t} else if (objc != 2) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"wrong # coordinates: expected 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"TEXT\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n    if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],\n\t\t&textPtr->x) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t&textPtr->y) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    ComputeTextBbox(canvas, textPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureText --\n *\n *\tThis function is invoked to configure various aspects of a text item,\n *\tsuch as its border and background colors.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as colors and stipple patterns, may be\n *\tset for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureText(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Rectangle item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC, newSelGC;\n    unsigned long mask;\n    Tk_Window tkwin;\n    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;\n    XColor *selBgColorPtr;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, textPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few of the options require additional processing, such as graphics\n     * contexts.\n     */\n\n    state = itemPtr->state;\n\n    if (textPtr->activeColor != NULL || textPtr->activeStipple != None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    color = textPtr->color;\n    stipple = textPtr->stipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (textPtr->activeColor != NULL) {\n\t    color = textPtr->activeColor;\n\t}\n\tif (textPtr->activeStipple != None) {\n\t    stipple = textPtr->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (textPtr->disabledColor != NULL) {\n\t    color = textPtr->disabledColor;\n\t}\n\tif (textPtr->disabledStipple != None) {\n\t    stipple = textPtr->disabledStipple;\n\t}\n    }\n\n    newGC = newSelGC = NULL;\n    if (textPtr->tkfont != NULL) {\n\tgcValues.font = Tk_FontId(textPtr->tkfont);\n\tmask = GCFont;\n\tif (color != NULL) {\n\t    gcValues.foreground = color->pixel;\n\t    mask |= GCForeground;\n\t    if (stipple != None) {\n\t\tgcValues.stipple = stipple;\n\t\tgcValues.fill_style = FillStippled;\n\t\tmask |= GCStipple|GCFillStyle;\n\t    }\n\t    newGC = Tk_GetGC(tkwin, mask, &gcValues);\n\t}\n\tmask &= ~(GCTile|GCFillStyle|GCStipple);\n\tif (stipple != None) {\n\t    gcValues.stipple = stipple;\n\t    gcValues.fill_style = FillStippled;\n\t    mask |= GCStipple|GCFillStyle;\n\t}\n\tif (textInfoPtr->selFgColorPtr != NULL) {\n\t    gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;\n\t}\n\tnewSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);\n    }\n    if (textPtr->gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), textPtr->gc);\n    }\n    textPtr->gc = newGC;\n    if (textPtr->selTextGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);\n    }\n    textPtr->selTextGC = newSelGC;\n\n    selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder);\n    if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel\n\t    == selBgColorPtr->pixel) {\n\tif (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) {\n\t    gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));\n\t} else {\n\t    gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin));\n\t}\n\tnewGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    } else {\n\tnewGC = NULL;\n    }\n    if (textPtr->cursorOffGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);\n    }\n    textPtr->cursorOffGC = newGC;\n\n    /*\n     * If the text was changed, move the selection and insertion indices to\n     * keep them inside the item.\n     */\n\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    if (textInfoPtr->selItemPtr == itemPtr) {\n\n\tif (textInfoPtr->selectFirst >= numChars) {\n\t    textInfoPtr->selItemPtr = NULL;\n\t} else {\n\t    if (textInfoPtr->selectLast >= numChars) {\n\t\ttextInfoPtr->selectLast = numChars - 1;\n\t    }\n\t    if ((textInfoPtr->anchorItemPtr == itemPtr)\n\t\t    && (textInfoPtr->selectAnchor >= numChars)) {\n\t\ttextInfoPtr->selectAnchor = numChars - 1;\n\t    }\n\t}\n    }\n    if (textPtr->insertPos >= numChars) {\n\ttextPtr->insertPos = numChars;\n    }\n\n    /*\n     * Restrict so that 0.0 <= angle < 360.0, and then recompute the cached\n     * sine and cosine of the angle. Note that fmod() can produce negative\n     * results, and we try to avoid negative zero as well.\n     */\n\n    textPtr->angle = fmod(textPtr->angle, 360.0);\n    if (textPtr->angle < 0.0) {\n\ttextPtr->angle += 360.0;\n    }\n    if (textPtr->angle == 0.0) {\n\ttextPtr->angle = 0.0;\n    }\n    textPtr->sine = sin(textPtr->angle * PI/180.0);\n    textPtr->cosine = cos(textPtr->angle * PI/180.0);\n\n    ComputeTextBbox(canvas, textPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteText --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta text item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteText(\n    TCL_UNUSED(Tk_Canvas),\t/* Info about overall canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    if (textPtr->color != NULL) {\n\tTk_FreeColor(textPtr->color);\n    }\n    if (textPtr->activeColor != NULL) {\n\tTk_FreeColor(textPtr->activeColor);\n    }\n    if (textPtr->disabledColor != NULL) {\n\tTk_FreeColor(textPtr->disabledColor);\n    }\n    Tk_FreeFont(textPtr->tkfont);\n    if (textPtr->stipple != None) {\n\tTk_FreeBitmap(display, textPtr->stipple);\n    }\n    if (textPtr->activeStipple != None) {\n\tTk_FreeBitmap(display, textPtr->activeStipple);\n    }\n    if (textPtr->disabledStipple != None) {\n\tTk_FreeBitmap(display, textPtr->disabledStipple);\n    }\n    if (textPtr->textObj != NULL) {\n\tTcl_DecrRefCount(textPtr->textObj);\n    }\n\n    Tk_FreeTextLayout(textPtr->textLayout);\n    if (textPtr->gc != NULL) {\n\tTk_FreeGC(display, textPtr->gc);\n    }\n    if (textPtr->selTextGC != NULL) {\n\tTk_FreeGC(display, textPtr->selTextGC);\n    }\n    if (textPtr->cursorOffGC != NULL) {\n\tTk_FreeGC(display, textPtr->cursorOffGC);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeTextBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a text item. In addition, it recomputes\n *\tall of the geometry information used to display a text item or check\n *\tfor mouse hits.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr,\n *\tand the linePtr structure is regenerated for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeTextBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    TextItem *textPtr)\t\t/* Item whose bbox is to be recomputed. */\n{\n    Tk_CanvasTextInfo *textInfoPtr;\n    int width, height, fudge, i;\n    Tk_State state = textPtr->header.state;\n    double x[4], y[4], dx[4], dy[4], sinA, cosA, tmp;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    Tk_FreeTextLayout(textPtr->textLayout);\n    width = 0;\n    if (textPtr->widthObj) {\n\tTk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textPtr->widthObj, &width);\n    }\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,\n\t    (textPtr->textObj ? Tcl_GetString(textPtr->textObj) : \"\"), numChars, width,\n\t    textPtr->justify, 0, &width, &height);\n\n    if (state == TK_STATE_HIDDEN || textPtr->color == NULL) {\n\twidth = height = 0;\n    }\n\n    /*\n     * Use overall geometry information to compute the top-left corner of the\n     * bounding box for the text item.\n     */\n\n    for (i=0 ; i<4 ; i++) {\n\tdx[i] = dy[i] = 0.0;\n    }\n    switch (textPtr->anchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_N:\n    case TK_ANCHOR_NE:\n\tbreak;\n\n    case TK_ANCHOR_SW:\n    case TK_ANCHOR_S:\n    case TK_ANCHOR_SE:\n\tfor (i=0 ; i<4 ; i++) {\n\t    dy[i] = -height;\n\t}\n\tbreak;\n\n    default:\n\tfor (i=0 ; i<4 ; i++) {\n\t    dy[i] = -height / 2;\n\t}\n\tbreak;\n    }\n    switch (textPtr->anchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_W:\n    case TK_ANCHOR_SW:\n\tbreak;\n\n    case TK_ANCHOR_NE:\n    case TK_ANCHOR_E:\n    case TK_ANCHOR_SE:\n\tfor (i=0 ; i<4 ; i++) {\n\t    dx[i] = -width;\n\t}\n\tbreak;\n\n    default:\n\tfor (i=0 ; i<4 ; i++) {\n\t    dx[i] = -width / 2;\n\t}\n\tbreak;\n    }\n\n    textPtr->actualWidth = width;\n\n    sinA = textPtr->sine;\n    cosA = textPtr->cosine;\n    textPtr->drawOrigin[0] = textPtr->x + dx[0]*cosA + dy[0]*sinA;\n    textPtr->drawOrigin[1] = textPtr->y + dy[0]*cosA - dx[0]*sinA;\n\n    /*\n     * Last of all, update the bounding box for the item. The item's bounding\n     * box includes the bounding box of all its lines, plus an extra fudge\n     * factor for the cursor border (which could potentially be quite large).\n     */\n\n    textInfoPtr = textPtr->textInfoPtr;\n    Tk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textInfoPtr->insertWidthObj, &textInfoPtr->insertWidth);\n    Tk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textInfoPtr->selBorderWidthObj, &textInfoPtr->selBorderWidth);\n    fudge = (textInfoPtr->insertWidth + 1) / 2;\n    if (textInfoPtr->selBorderWidth > fudge) {\n\tfudge = textInfoPtr->selBorderWidth;\n    }\n\n    /*\n     * Apply the rotation before computing the bounding box.\n     */\n\n    dx[0] -= fudge;\n    dx[1] += width + fudge;\n    dx[2] += width + fudge;\n    dy[2] += height;\n    dx[3] -= fudge;\n    dy[3] += height;\n    for (i=0 ; i<4 ; i++) {\n\tx[i] = textPtr->x + dx[i] * cosA + dy[i] * sinA;\n\ty[i] = textPtr->y + dy[i] * cosA - dx[i] * sinA;\n    }\n\n    /*\n     * Convert to a rectilinear bounding box.\n     */\n\n    for (i=1,tmp=x[0] ; i<4 ; i++) {\n\tif (x[i] < tmp) {\n\t    tmp = x[i];\n\t}\n    }\n    textPtr->header.x1 = ROUND(tmp);\n    for (i=1,tmp=y[0] ; i<4 ; i++) {\n\tif (y[i] < tmp) {\n\t    tmp = y[i];\n\t}\n    }\n    textPtr->header.y1 = ROUND(tmp);\n    for (i=1,tmp=x[0] ; i<4 ; i++) {\n\tif (x[i] > tmp) {\n\t    tmp = x[i];\n\t}\n    }\n    textPtr->header.x2 = ROUND(tmp);\n    for (i=1,tmp=y[0] ; i<4 ; i++) {\n\tif (y[i] > tmp) {\n\t    tmp = y[i];\n\t}\n    }\n    textPtr->header.y2 = ROUND(tmp);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayCanvText --\n *\n *\tThis function is invoked to draw a text item in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayCanvText(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    int x, int y, int width, int height)\n\t\t\t\t/* Describes region of canvas that must be\n\t\t\t\t * redisplayed (not used). */\n{\n    TextItem *textPtr;\n    Tk_CanvasTextInfo *textInfoPtr;\n    Tcl_Size selFirstChar, selLastChar;\n    short drawableX, drawableY;\n    Pixmap stipple;\n    Tk_State state = itemPtr->state;\n\n    textPtr = (TextItem *) itemPtr;\n    textInfoPtr = textPtr->textInfoPtr;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    stipple = textPtr->stipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (textPtr->activeStipple != None) {\n\t    stipple = textPtr->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (textPtr->disabledStipple != None) {\n\t    stipple = textPtr->disabledStipple;\n\t}\n    }\n\n    if (textPtr->gc == NULL) {\n\treturn;\n    }\n\n    /*\n     * If we're stippling, then modify the stipple offset in the GC. Be sure\n     * to reset the offset when done, since the GC is supposed to be\n     * read-only.\n     */\n\n    if (stipple != None) {\n\tTk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);\n    }\n\n    selFirstChar = TCL_INDEX_NONE;\n    selLastChar = 0;\n    Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0],\n\t    textPtr->drawOrigin[1], &drawableX, &drawableY);\n\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    if (textInfoPtr->selItemPtr == itemPtr) {\n\tselFirstChar = textInfoPtr->selectFirst;\n\tselLastChar = textInfoPtr->selectLast;\n\tif (selLastChar > numChars) {\n\t    selLastChar = numChars - 1;\n\t}\n\tif ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {\n\t    int xFirst, yFirst, hFirst;\n\t    int xLast, yLast, wLast;\n\n\t    /*\n\t     * Draw a special background under the selection.\n\t     */\n\n\t    Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,\n\t\t    NULL, &hFirst);\n\t    Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,\n\t\t    &wLast, NULL);\n\n\t    /*\n\t     * If the selection spans the end of this line, then display\n\t     * selection background all the way to the end of the line.\n\t     * However, for the last line we only want to display up to the\n\t     * last character, not the end of the line.\n\t     */\n\n\t    x = xFirst;\n\t    height = hFirst;\n\t    Tk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textInfoPtr->selBorderWidthObj, &textInfoPtr->selBorderWidth);\n\t    for (y = yFirst ; y <= yLast; y += height) {\n\t\tint dx1, dy1, dx2, dy2;\n\t\tdouble s = textPtr->sine, c = textPtr->cosine;\n\t\tXPoint points[4];\n\n\t\tif (y == yLast) {\n\t\t    width = xLast + wLast - x;\n\t\t} else {\n\t\t    width = textPtr->actualWidth - x;\n\t\t}\n\t\tdx1 = x - textInfoPtr->selBorderWidth;\n\t\tdy1 = y;\n\t\tdx2 = width + 2 * textInfoPtr->selBorderWidth;\n\t\tdy2 = height;\n\t\tpoints[0].x = (short)(drawableX + dx1*c + dy1*s);\n\t\tpoints[0].y = (short)(drawableY + dy1*c - dx1*s);\n\t\tpoints[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);\n\t\tpoints[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);\n\t\tpoints[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);\n\t\tpoints[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);\n\t\tpoints[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);\n\t\tpoints[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);\n\t\tTk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,\n\t\t\ttextInfoPtr->selBorder, points, 4,\n\t\t\ttextInfoPtr->selBorderWidth, TK_RELIEF_RAISED);\n\t\tx = 0;\n\t    }\n\t}\n    }\n\n    /*\n     * If the insertion point should be displayed, then draw a special\n     * background for the cursor before drawing the text. Note: if we're the\n     * cursor item but the cursor is turned off, then redraw background over\n     * the area of the cursor. This guarantees that the selection won't make\n     * the cursor invisible on mono displays, where both are drawn in the same\n     * color.\n     */\n\n    if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {\n\tif (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,\n\t\t&x, &y, NULL, &height)) {\n\t    int dx1, dy1, dx2, dy2;\n\t    double s = textPtr->sine, c = textPtr->cosine;\n\t    XPoint points[4];\n\n\t    Tk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textInfoPtr->insertWidthObj, &textInfoPtr->insertWidth);\n\t    dx1 = x - (textInfoPtr->insertWidth / 2);\n\t    dy1 = y;\n\t    dx2 = textInfoPtr->insertWidth;\n\t    dy2 = height;\n\t    points[0].x = (short)(drawableX + dx1*c + dy1*s);\n\t    points[0].y = (short)(drawableY + dy1*c - dx1*s);\n\t    points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);\n\t    points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);\n\t    points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);\n\t    points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);\n\t    points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);\n\t    points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);\n\n\t    Tk_SetCaretPos(Tk_CanvasTkwin(canvas), points[0].x, points[0].y,\n\t\t    height);\n\t    if (textInfoPtr->cursorOn) {\n\t\tTk_GetPixelsFromObj(NULL, Tk_CanvasTkwin(canvas), textInfoPtr->insertBorderWidthObj, &textInfoPtr->insertBorderWidth);\n\t\tTk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,\n\t\t\ttextInfoPtr->insertBorder, points, 4,\n\t\t\ttextInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);\n\t    } else if (textPtr->cursorOffGC != NULL) {\n\t\t/*\n\t\t * Redraw the background over the area of the cursor, even\n\t\t * though the cursor is turned off. This guarantees that the\n\t\t * selection won't make the cursor invisible on mono displays,\n\t\t * where both may be drawn in the same color.\n\t\t */\n\n\t\tXFillPolygon(display, drawable, textPtr->cursorOffGC,\n\t\t\tpoints, 4, Convex, CoordModeOrigin);\n\t    }\n\t}\n    }\n\n    /*\n     * If there is no selected text or the selected text foreground is the\n     * same as the regular text foreground, then draw one text string. If\n     * there is selected text and the foregrounds differ, draw the regular\n     * text up to the selection, draw the selection, then draw the rest of the\n     * regular text. Drawing the regular text and then the selected text over\n     * it would causes problems with anti-aliased text because the two\n     * anti-aliasing colors would blend together.\n     */\n\n    if ((selFirstChar != TCL_INDEX_NONE) && (textPtr->selTextGC != textPtr->gc)) {\n\tif (0 < selFirstChar) {\n\t    TkDrawAngledTextLayout(display, drawable, textPtr->gc,\n\t\t    textPtr->textLayout, drawableX, drawableY, textPtr->angle,\n\t\t    0, selFirstChar);\n\t}\n\tTkDrawAngledTextLayout(display, drawable, textPtr->selTextGC,\n\t\ttextPtr->textLayout, drawableX, drawableY, textPtr->angle,\n\t\tselFirstChar, selLastChar + 1);\n\tif (selLastChar + 1 < numChars) {\n\t    TkDrawAngledTextLayout(display, drawable, textPtr->gc,\n\t\t    textPtr->textLayout, drawableX, drawableY, textPtr->angle,\n\t\t    selLastChar + 1, numChars);\n\t}\n    } else {\n\tTkDrawAngledTextLayout(display, drawable, textPtr->gc,\n\t\ttextPtr->textLayout, drawableX, drawableY, textPtr->angle,\n\t\t0, numChars);\n    }\n    TkUnderlineAngledTextLayout(display, drawable, textPtr->gc,\n\t    textPtr->textLayout, drawableX, drawableY, textPtr->angle,\n\t    textPtr->underline);\n\n    if (stipple != None) {\n\tXSetTSOrigin(display, textPtr->gc, 0, 0);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextInsert --\n *\n *\tInsert characters into a text item at a given position.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe text in the given item is modified. The cursor and selection\n *\tpositions are also modified to reflect the insertion.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTextInsert(\n    Tk_Canvas canvas,\t\t/* Canvas containing text item. */\n    Tk_Item *itemPtr,\t\t/* Text item to be modified. */\n    Tcl_Size index,\t\t\t/* Character index before which string is to\n\t\t\t\t * be inserted. */\n    Tcl_Obj *obj)\t\t/* New characters to be inserted. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    Tcl_Size byteIndex, charsAdded;\n    Tcl_Size byteCount;\n    const char *string, *text;\n    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;\n\n    string = Tcl_GetStringFromObj(obj, &byteCount);\n\n    if (index < 0) {\n\tindex = 0;\n    }\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    text = textPtr->textObj ? Tcl_GetString(textPtr->textObj) : \"\";\n    if (index > numChars) {\n\tindex = numChars;\n    }\n    byteIndex = Tcl_UtfAtIndex(text, index) - text;\n    byteCount = strlen(string);\n    if (byteCount == 0) {\n\treturn;\n    }\n\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n    Tcl_DStringAppend(&ds, text, byteIndex);\n    Tcl_DStringAppend(&ds, string, byteCount);\n    Tcl_DStringAppend(&ds, text + byteIndex, TCL_INDEX_NONE);\n    if (textPtr->textObj) {\n\tTcl_DecrRefCount(textPtr->textObj);\n    }\n    textPtr->textObj = Tcl_DStringToObj(&ds);\n    Tcl_IncrRefCount(textPtr->textObj);\n    charsAdded = Tcl_GetCharLength(obj);\n\n    /*\n     * Inserting characters invalidates indices such as those for the\n     * selection and cursor. Update the indices appropriately.\n     */\n\n    if (textInfoPtr->selItemPtr == itemPtr) {\n\tif (textInfoPtr->selectFirst >= index) {\n\t    textInfoPtr->selectFirst += charsAdded;\n\t}\n\tif (textInfoPtr->selectLast >= index) {\n\t    textInfoPtr->selectLast += charsAdded;\n\t}\n\tif ((textInfoPtr->anchorItemPtr == itemPtr)\n\t\t&& (textInfoPtr->selectAnchor >= index)) {\n\t    textInfoPtr->selectAnchor += charsAdded;\n\t}\n    }\n    if (textPtr->insertPos >= index) {\n\ttextPtr->insertPos += charsAdded;\n    }\n    ComputeTextBbox(canvas, textPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextDeleteChars --\n *\n *\tDelete one or more characters from a text item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCharacters between \"first\" and \"last\", inclusive, get deleted from\n *\titemPtr, and things like the selection position get updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTextDeleteChars(\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Item in which to delete characters. */\n    Tcl_Size first,\t\t\t/* Character index of first character to\n\t\t\t\t * delete. */\n    Tcl_Size last)\t\t\t/* Character index of last character to delete\n\t\t\t\t * (inclusive). */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    Tcl_Size byteIndex, byteCount, charsRemoved;\n    const char *text;\n    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;\n\n    if (first < 0) {\n\tfirst = 0;\n    }\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    if (last >= numChars) {\n\tlast = numChars - 1;\n    }\n    if (first > last) {\n\treturn;\n    }\n    charsRemoved = last + 1 - first;\n\n    text = Tcl_GetString(textPtr->textObj);\n    byteIndex = Tcl_UtfAtIndex(text, first) - text;\n    byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved) - (text + byteIndex);\n\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n    Tcl_DStringAppend(&ds, text, byteIndex);\n    Tcl_DStringAppend(&ds, text + byteIndex + byteCount, TCL_INDEX_NONE);\n    Tcl_DecrRefCount(textPtr->textObj);\n    textPtr->textObj = Tcl_DStringToObj(&ds);\n    Tcl_IncrRefCount(textPtr->textObj);\n\n    /*\n     * Update indexes for the selection and cursor to reflect the renumbering\n     * of the remaining characters.\n     */\n\n    if (textInfoPtr->selItemPtr == itemPtr) {\n\tif (textInfoPtr->selectFirst > first) {\n\t    textInfoPtr->selectFirst -= charsRemoved;\n\t    if (textInfoPtr->selectFirst < first) {\n\t\ttextInfoPtr->selectFirst = first;\n\t    }\n\t}\n\tif (textInfoPtr->selectLast >= first) {\n\t    textInfoPtr->selectLast -= charsRemoved;\n\t    if (textInfoPtr->selectLast < first - 1) {\n\t\ttextInfoPtr->selectLast = first - 1;\n\t    }\n\t}\n\tif (textInfoPtr->selectFirst > textInfoPtr->selectLast) {\n\t    textInfoPtr->selItemPtr = NULL;\n\t}\n\tif ((textInfoPtr->anchorItemPtr == itemPtr)\n\t\t&& (textInfoPtr->selectAnchor > first)) {\n\t    textInfoPtr->selectAnchor -= charsRemoved;\n\t    if (textInfoPtr->selectAnchor < first) {\n\t\ttextInfoPtr->selectAnchor = first;\n\t    }\n\t}\n    }\n    if (textPtr->insertPos > first) {\n\ttextPtr->insertPos -= charsRemoved;\n\tif (textPtr->insertPos < first) {\n\t    textPtr->insertPos = first;\n\t}\n    }\n    ComputeTextBbox(canvas, textPtr);\n    return;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextToPoint --\n *\n *\tComputes the distance from a given point to a given text item, in\n *\tcanvas units.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tpointPtr[0] and pointPtr[1] is inside the text item. If the point\n *\tisn't inside the text item then the return value is the distance from\n *\tthe point to the text item.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nTextToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    TextItem *textPtr;\n    Tk_State state = itemPtr->state;\n    double value, px, py;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    textPtr = (TextItem *) itemPtr;\n    px = pointPtr[0] - textPtr->drawOrigin[0];\n    py = pointPtr[1] - textPtr->drawOrigin[1];\n    value = (double) Tk_DistanceToTextLayout(textPtr->textLayout,\n\t    (int) (px*textPtr->cosine - py*textPtr->sine),\n\t    (int) (py*textPtr->cosine + px*textPtr->sine));\n\n    if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||\n\t    (textPtr->textObj == NULL)) {\n\tvalue = 1.0e36;\n    }\n    return value;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangle.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTextToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Item to check against rectangle. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates\n\t\t\t\t * (x1,y1,x2,y2) describing rectangular\n\t\t\t\t * area. */\n{\n    TextItem *textPtr;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    textPtr = (TextItem *) itemPtr;\n    return TkIntersectAngledTextLayout(textPtr->textLayout,\n\t    (int) ((rectPtr[0] + 0.5) - textPtr->drawOrigin[0]),\n\t    (int) ((rectPtr[1] + 0.5) - textPtr->drawOrigin[1]),\n\t    (int) (rectPtr[2] - rectPtr[0] + 0.5),\n\t    (int) (rectPtr[3] - rectPtr[1] + 0.5),\n\t    textPtr->angle);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateText --\n *\n *\tThis function is called to rotate a text item by a given amount about a\n *\tpoint. Note that this does *not* rotate the text of the item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the text anchor is rotated by angleRad about (originX,\n *\toriginY), and the bounding box is updated in the generic part of the\n *\titem structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateText(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being rotated. */\n    double originX, double originY,\n    double angleRad)\t\t/* Amount by which item is to be rotated. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &textPtr->x, &textPtr->y);\n    ComputeTextBbox(canvas, textPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleText --\n *\n *\tThis function is invoked to rescale a text item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tScales the position of the text, but not the size of the font for the\n *\ttext.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleText(\n    Tk_Canvas canvas,\t\t/* Canvas containing rectangle. */\n    Tk_Item *itemPtr,\t\t/* Rectangle to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale rect. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    textPtr->x = originX + scaleX*(textPtr->x - originX);\n    textPtr->y = originY + scaleY*(textPtr->y - originY);\n    ComputeTextBbox(canvas, textPtr);\n    return;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateText --\n *\n *\tThis function is called to move a text item by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the text item is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateText(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    textPtr->x += deltaX;\n    textPtr->y += deltaY;\n    ComputeTextBbox(canvas, textPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetTextIndex --\n *\n *\tParse an index into a text item and return either its value or an\n *\terror.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the index (into itemPtr) corresponding to string. Otherwise an\n *\terror message is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetTextIndex(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *obj,\t\t/* Specification of a particular character in\n\t\t\t\t * itemPtr's text. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted character\n\t\t\t\t * index. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    Tcl_Size length, idx;\n    int c;\n    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;\n    const char *string;\n\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    if (TCL_OK == TkGetIntForIndex(obj, numChars - 1, 1, &idx)) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else if (idx > numChars) {\n\t    idx = numChars;\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetStringFromObj(obj, &length);\n    c = string[0];\n\n    if ((c == 'i')\n\t    && (strncmp(string, \"insert\", length) == 0)) {\n\t*indexPtr = textPtr->insertPos;\n    } else if ((c == 's') && (length >= 5)\n\t    && (strncmp(string, \"sel.first\", length) == 0)) {\n\tif (textInfoPtr->selItemPtr != itemPtr) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"selection isn't in item\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"UNSELECTED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\t*indexPtr = textInfoPtr->selectFirst;\n    } else if ((c == 's') && (length >= 5)\n\t    && (strncmp(string, \"sel.last\", length) == 0)) {\n\tif (textInfoPtr->selItemPtr != itemPtr) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"selection isn't in item\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"UNSELECTED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\t*indexPtr = textInfoPtr->selectLast;\n    } else if (c == '@') {\n\tint x, y;\n\tdouble tmp, cs = textPtr->cosine, s = textPtr->sine;\n\tchar *rest;\n\tconst char *p;\n\n\tp = string+1;\n\trest = strchr((char *)p, ',');\n\tif (!rest) {\n\t    goto badIndex;\n\t}\n\t*rest = '\\0';\n\tif (Tcl_GetDouble(NULL, p, &tmp) != TCL_OK) {\n\t    *rest = ',';\n\t    goto badIndex;\n\t}\n\t*rest = ',';\n\tx = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);\n\tp = rest+1;\n\tif (Tcl_GetDouble(NULL, p, &tmp) != TCL_OK) {\n\t    goto badIndex;\n\t}\n\ty = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);\n\tx -= (int) textPtr->drawOrigin[0];\n\ty -= (int) textPtr->drawOrigin[1];\n\t*indexPtr = Tk_PointToChar(textPtr->textLayout,\n\t\t(int) (x*cs - y*s), (int) (y*cs + x*s));\n    } else {\n    badIndex:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad index \\\"%s\\\"\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"ITEM_INDEX\", \"TEXT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SetTextCursor --\n *\n *\tSet the position of the insertion cursor in this item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor position will change.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nSetTextCursor(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Record describing canvas widget. */\n    Tk_Item *itemPtr,\t\t/* Text item in which cursor position is to be\n\t\t\t\t * set. */\n    Tcl_Size index)\t\t\t/* Character index of character just before\n\t\t\t\t * which cursor is to be positioned. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n\n    Tcl_Size numChars = textPtr->textObj ? Tcl_GetCharLength(textPtr->textObj) : 0;\n    if (index < 0) {\n\ttextPtr->insertPos = 0;\n    } else if (index > numChars) {\n\ttextPtr->insertPos = numChars;\n    } else {\n\ttextPtr->insertPos = index;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetSelText --\n *\n *\tThis function is invoked to return the selected portion of a text\n *\titem. It is only called when this item has the selection.\n *\n * Results:\n *\tThe return value is the number of non-NULL bytes stored at buffer.\n *\tBuffer is filled (or partially filled) with a NULL-terminated string\n *\tcontaining part or all of the selection, as given by offset and\n *\tmaxBytes.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Size\nGetSelText(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing selection. */\n    Tk_Item *itemPtr,\t\t/* Text item containing selection. */\n    Tcl_Size offset,\t\t\t/* Byte offset within selection of first\n\t\t\t\t * character to be returned. */\n    char *buffer,\t\t/* Location in which to place selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum number of bytes to place at buffer,\n\t\t\t\t * not including terminating NULL\n\t\t\t\t * character. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    Tcl_Size byteCount;\n    const char *selStart, *selEnd;\n    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;\n\n    if ((textInfoPtr->selectFirst < 0) ||\n\t    (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {\n\treturn 0;\n    }\n    selStart = Tcl_UtfAtIndex(textPtr->textObj ? Tcl_GetString(textPtr->textObj) : \"\", textInfoPtr->selectFirst);\n    selEnd = Tcl_UtfAtIndex(selStart,\n\t    textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);\n    if (selEnd  <= selStart + offset) {\n\treturn 0;\n    }\n    byteCount = selEnd - selStart - offset;\n    if (byteCount > maxBytes) {\n\tbyteCount = maxBytes;\n    }\n    memcpy(buffer, selStart + offset, byteCount);\n    buffer[byteCount] = '\\0';\n    return byteCount;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextToPostscript --\n *\n *\tThis function is called to generate Postscript for text items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTextToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    int prepass)\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    TextItem *textPtr = (TextItem *) itemPtr;\n    double x, y;\n    Tk_FontMetrics fm;\n    const char *justify;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state = itemPtr->state;\n    Tcl_Obj *psObj;\n    Tcl_InterpState interpState;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    color = textPtr->color;\n    stipple = textPtr->stipple;\n    if (state == TK_STATE_HIDDEN || textPtr->color == NULL ||\n\t    textPtr->textObj == NULL) {\n\treturn TCL_OK;\n    } else if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (textPtr->activeColor != NULL) {\n\t    color = textPtr->activeColor;\n\t}\n\tif (textPtr->activeStipple != None) {\n\t    stipple = textPtr->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (textPtr->disabledColor != NULL) {\n\t    color = textPtr->disabledColor;\n\t}\n\tif (textPtr->disabledStipple != None) {\n\t    stipple = textPtr->disabledStipple;\n\t}\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Generate postscript.\n     */\n\n    Tcl_ResetResult(interp);\n    if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {\n\tgoto error;\n    }\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n    if (prepass != 0) {\n\tgoto done;\n    }\n\n    Tcl_ResetResult(interp);\n    Tk_CanvasPsColor(interp, canvas, color);\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n    if (stipple != None) {\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsStipple(interp, canvas, stipple);\n\tTcl_AppendPrintfToObj(psObj, \"/StippleText {\\n    %s} bind def\\n\",\n\t\tTcl_GetString(Tcl_GetObjResult(interp)));\n    }\n\n    switch (textPtr->anchor) {\n    case TK_ANCHOR_NW:\t   x = 0; y = 0; break;\n    case TK_ANCHOR_N:\t   x = 1; y = 0; break;\n    case TK_ANCHOR_NE:\t   x = 2; y = 0; break;\n    case TK_ANCHOR_E:\t   x = 2; y = 1; break;\n    case TK_ANCHOR_SE:\t   x = 2; y = 2; break;\n    case TK_ANCHOR_S:\t   x = 1; y = 2; break;\n    case TK_ANCHOR_SW:\t   x = 0; y = 2; break;\n    case TK_ANCHOR_W:\t   x = 0; y = 1; break;\n    default: x = 1; y = 1; break;\n    }\n    switch (textPtr->justify) {\n    case TK_JUSTIFY_CENTER: justify = \"0.5\"; break;\n    case TK_JUSTIFY_RIGHT:  justify = \"1\";   break;\n    default:                justify = \"0\";   break;\n    }\n\n    Tk_GetFontMetrics(textPtr->tkfont, &fm);\n\n    Tcl_AppendPrintfToObj(psObj, \"%.15g %.15g %.15g [\\n\",\n\t    textPtr->angle, textPtr->x, Tk_CanvasPsY(canvas, textPtr->y));\n    Tcl_ResetResult(interp);\n    Tk_TextLayoutToPostscript(interp, textPtr->textLayout);\n    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n    Tcl_AppendPrintfToObj(psObj,\n\t    \"] %d %g %g %s %s DrawText\\n\",\n\t    fm.linespace, x / -2.0, y / 2.0, justify,\n\t    ((stipple == None) ? \"false\" : \"true\"));\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n  done:\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n\n  error:\n    Tcl_DiscardInterpState(interpState);\n    Tcl_DecrRefCount(psObj);\n    return TCL_ERROR;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvUtil.c",
    "content": "/*\n * tkCanvUtil.c --\n *\n *\tThis file contains a collection of utility functions used by the\n *\timplementations of various canvas item types.\n *\n * Copyright © 1994 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Structures defined only in this file.\n */\n\ntypedef struct SmoothAssocData {\n    struct SmoothAssocData *nextPtr;\n\t\t\t\t/* Pointer to next SmoothAssocData. */\n    Tk_SmoothMethod smooth;\t/* Name and functions associated with this\n\t\t\t\t * option. */\n} SmoothAssocData;\n\nconst Tk_SmoothMethod tkBezierSmoothMethod = {\n    \"true\",\n    TkMakeBezierCurve,\n    (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,\n\t    int numPoints, int numSteps))(void *)TkMakeBezierPostscript,\n};\nstatic const Tk_SmoothMethod tkRawSmoothMethod = {\n    \"raw\",\n    TkMakeRawCurve,\n    (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,\n\t    int numPoints, int numSteps))(void *)TkMakeRawCurvePostscript,\n};\n\n\n/*\n * Function forward-declarations.\n */\n\nstatic void\t\tSmoothMethodCleanupProc(void *clientData,\n\t\t\t    Tcl_Interp *interp);\nstatic SmoothAssocData *InitSmoothMethods(Tcl_Interp *interp);\nstatic int\t\tDashConvert(char *l, const char *p, Tcl_Size n,\n\t\t\t    double width);\nstatic void\t\tTranslateAndAppendCoords(TkCanvas *canvPtr,\n\t\t\t    double x, double y, XPoint *outArr, Tcl_Size numOut);\nstatic inline Tcl_Obj *\tGetPostscriptBuffer(Tcl_Interp *interp);\n\n#define ABS(a) ((a>=0)?(a):(-(a)))\n\f\nstatic inline Tcl_Obj *\nGetPostscriptBuffer(\n    Tcl_Interp *interp)\n{\n    Tcl_Obj *psObj = Tcl_GetObjResult(interp);\n\n    if (Tcl_IsShared(psObj)) {\n\tpsObj = Tcl_DuplicateObj(psObj);\n\tTcl_SetObjResult(interp, psObj);\n    }\n    return psObj;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasTkwin --\n *\n *\tGiven a token for a canvas, this function returns the widget that\n *\trepresents the canvas.\n *\n * Results:\n *\tThe return value is a handle for the widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_CanvasTkwin(\n    Tk_Canvas canvas)\t\t/* Token for the canvas. */\n{\n    return Canvas(canvas)->tkwin;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasDrawableCoords --\n *\n *\tGiven an (x,y) coordinate pair within a canvas, this function\n *\treturns the corresponding coordinates at which the point should\n *\tbe drawn in the drawable used for display.\n *\n * Results:\n *\tThere is no return value. The values at *drawableXPtr and\n *\t*drawableYPtr are filled in with the coordinates at which x and y\n *\tshould be drawn. These coordinates are clipped to fit within a\n *\t\"short\", since this is what X uses in most cases for drawing.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CanvasDrawableCoords(\n    Tk_Canvas canvas,\t\t/* Token for the canvas. */\n    double x,\t\t\t/* Coordinates in canvas space. */\n    double y,\n    short *drawableXPtr,\t/* Screen coordinates are stored here. */\n    short *drawableYPtr)\n{\n    double tmp;\n\n    tmp = x - Canvas(canvas)->drawableXOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    if (tmp > 32767) {\n\t*drawableXPtr = 32767;\n    } else if (tmp < -32768) {\n\t*drawableXPtr = -32768;\n    } else {\n\t*drawableXPtr = (short) tmp;\n    }\n\n    tmp = y - Canvas(canvas)->drawableYOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    if (tmp > 32767) {\n\t*drawableYPtr = 32767;\n    } else if (tmp < -32768) {\n\t*drawableYPtr = -32768;\n    } else {\n\t*drawableYPtr = (short) tmp;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasWindowCoords --\n *\n *\tGiven an (x,y) coordinate pair within a canvas, this function returns\n *\tthe corresponding coordinates in the canvas's window.\n *\n * Results:\n *\tThere is no return value. The values at *screenXPtr and *screenYPtr\n *\tare filled in with the coordinates at which (x,y) appears in the\n *\tcanvas's window. These coordinates are clipped to fit within a\n *\t\"short\", since this is what X uses in most cases for drawing.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CanvasWindowCoords(\n    Tk_Canvas canvas,\t\t/* Token for the canvas. */\n    double x,\t\t\t/* Coordinates in canvas space. */\n    double y,\n    short *screenXPtr,\t\t/* Screen coordinates are stored here. */\n    short *screenYPtr)\n{\n    double tmp;\n\n    tmp = x - Canvas(canvas)->xOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    if (tmp > 32767) {\n\t*screenXPtr = 32767;\n    } else if (tmp < -32768) {\n\t*screenXPtr = -32768;\n    } else {\n\t*screenXPtr = (short) tmp;\n    }\n\n    tmp = y - Canvas(canvas)->yOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    if (tmp > 32767) {\n\t*screenYPtr = 32767;\n    } else if (tmp < -32768) {\n\t*screenYPtr = -32768;\n    } else {\n\t*screenYPtr = (short) tmp;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasGetCoord --\n *\n *\tGiven a string, returns a floating-point canvas coordinate\n *\tcorresponding to that string.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the canvas coordinate is\n *\tstored at *doublePtr; otherwise TCL_ERROR is returned and an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasGetCoord(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to which coordinate applies. */\n    const char *string,\t\t/* Describes coordinate (any screen coordinate\n\t\t\t\t * form may be used here). */\n    double *doublePtr)\t\t/* Place to store converted coordinate. */\n{\n    if (Tk_GetScreenMM(Canvas(canvas)->interp, Canvas(canvas)->tkwin, string,\n\t    doublePtr) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    *doublePtr *= Canvas(canvas)->pixelsPerMM;\n    return TCL_OK;\n}\n\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasGetCoordFromObj --\n *\n *\tGiven a string, returns a floating-point canvas coordinate\n *\tcorresponding to that string.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the canvas coordinate is\n *\tstored at *doublePtr; otherwise TCL_ERROR is returned and an error\n *\tmessage is left in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasGetCoordFromObj(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to which coordinate applies. */\n    Tcl_Obj *obj,\t\t/* Describes coordinate (any screen coordinate\n\t\t\t\t * form may be used here). */\n    double *doublePtr)\t\t/* Place to store converted coordinate. */\n{\n    return Tk_GetDoublePixelsFromObj(Canvas(canvas)->interp, Canvas(canvas)->tkwin, obj, doublePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasSetStippleOrigin --\n *\n *\tThis function sets the stipple origin in a graphics context so that\n *\tstipples drawn with the GC will line up with other stipples previously\n *\tdrawn in the canvas.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe graphics context is modified.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CanvasSetStippleOrigin(\n    Tk_Canvas canvas,\t\t/* Token for a canvas. */\n    GC gc)\t\t\t/* Graphics context that is about to be used\n\t\t\t\t * to draw a stippled pattern as part of\n\t\t\t\t * redisplaying the canvas. */\n{\n    XSetTSOrigin(Canvas(canvas)->display, gc,\n\t    -Canvas(canvas)->drawableXOrigin,\n\t    -Canvas(canvas)->drawableYOrigin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasSetOffset--\n *\n *\tThis function sets the stipple offset in a graphics context so that\n *\tstipples drawn with the GC will line up with other stipples with the\n *\tsame offset.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe graphics context is modified.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CanvasSetOffset(\n    Tk_Canvas canvas,\t\t/* Token for a canvas. */\n    GC gc,\t\t\t/* Graphics context that is about to be used\n\t\t\t\t * to draw a stippled pattern as part of\n\t\t\t\t * redisplaying the canvas. */\n    Tk_TSOffset *offset)\t/* Offset (may be NULL pointer)*/\n{\n    TkCanvas *canvasPtr = Canvas(canvas);\n    int flags = 0;\n    int x = - canvasPtr->drawableXOrigin;\n    int y = - canvasPtr->drawableYOrigin;\n\n    if (offset != NULL) {\n\tflags = offset->flags;\n\tx += offset->xoffset;\n\ty += offset->yoffset;\n    }\n    if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {\n\tTk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,\n\t\ty - canvasPtr->yOrigin);\n    } else {\n\tXSetTSOrigin(canvasPtr->display, gc, x, y);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasGetTextInfo --\n *\n *\tThis function returns a pointer to a structure containing information\n *\tabout the selection and insertion cursor for a canvas widget. Items\n *\tsuch as text items save the pointer and use it to share access to the\n *\tinformation with the generic canvas code.\n *\n * Results:\n *\tThe return value is a pointer to the structure holding text\n *\tinformation for the canvas. Most of the fields should not be modified\n *\toutside the generic canvas code; see the user documentation for\n *\tdetails.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_CanvasTextInfo *\nTk_CanvasGetTextInfo(\n    Tk_Canvas canvas)\t\t/* Token for the canvas widget. */\n{\n    return &Canvas(canvas)->textInfo;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasTagsParseProc --\n *\n *\tThis function is invoked during option processing to handle \"-tags\"\n *\toptions for canvas items.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe tags for a given item get replaced by those indicated in the value\n *\targument.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasTagsParseProc(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option (list of tag names). */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    TCL_UNUSED(Tcl_Size))\t\t\t/* Offset into item (ignored). */\n{\n    Tk_Item *itemPtr = (Tk_Item *) widgRec;\n    Tcl_Size argc, i;\n    const char **argv;\n    Tk_Uid *newPtr;\n\n    /*\n     * Break the value up into the individual tag names.\n     */\n\n    if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Make sure that there's enough space in the item to hold the tag names.\n     */\n\n    if (itemPtr->tagSpace < argc) {\n\tnewPtr = (Tk_Uid *)Tcl_Alloc(argc * sizeof(Tk_Uid));\n\tfor (i = itemPtr->numTags - 1; i != TCL_INDEX_NONE; i--) {\n\t    newPtr[i] = itemPtr->tagPtr[i];\n\t}\n\tif (itemPtr->tagPtr != itemPtr->staticTagSpace) {\n\t    Tcl_Free(itemPtr->tagPtr);\n\t}\n\titemPtr->tagPtr = newPtr;\n\titemPtr->tagSpace = argc;\n    }\n    itemPtr->numTags = argc;\n    for (i = 0; i < argc; i++) {\n\titemPtr->tagPtr[i] = Tk_GetUid(argv[i]);\n    }\n    Tcl_Free(argv);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasTagsPrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-tags\" configuration option for canvas\n *\titems.\n *\n * Results:\n *\tThe return value is a string describing all the tags for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_CanvasTagsPrintProc(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Ignored. */\n    Tcl_FreeProc **freeProcPtr)\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    Tk_Item *itemPtr = (Tk_Item *) widgRec;\n\n    if (itemPtr->numTags == 0) {\n\t*freeProcPtr = NULL;\n\treturn \"\";\n    }\n    if (itemPtr->numTags == 1) {\n\t*freeProcPtr = NULL;\n\treturn (const char *) itemPtr->tagPtr[0];\n    }\n    *freeProcPtr = TCL_DYNAMIC;\n    return Tcl_Merge(itemPtr->numTags, (const char **) itemPtr->tagPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkCanvasDashParseProc --\n *\n *\tThis function is invoked during option processing to handle \"-dash\",\n *\t\"-activedash\" and \"-disableddash\" options for canvas objects.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe dash list for a given canvas object gets replaced by those\n *\tindicated in the value argument.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkCanvasDashParseProc(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    return Tk_GetDash(interp, value, (Tk_Dash *) (widgRec+offset));\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkCanvasDashPrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-dash\", \"-activedash\" and \"-disableddash\"\n *\tconfiguration options for canvas items.\n *\n * Results:\n *\tThe return value is a string describing all the dash list for the item\n *\treferred to by \"widgRec\"and \"offset\". In addition, *freeProcPtr is\n *\tfilled in with the address of a function to call to free the result\n *\tstring when it's no longer needed (or NULL to indicate that the string\n *\tdoesn't need to be freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTkCanvasDashPrintProc(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset in record for item. */\n    Tcl_FreeProc **freeProcPtr)\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);\n    char *buffer, *p;\n    int i = dash->number;\n\n    if (i < 0) {\n\ti = -i;\n\t*freeProcPtr = TCL_DYNAMIC;\n\tbuffer = (char *)Tcl_Alloc((size_t)i + 1);\n\tp = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;\n\tmemcpy(buffer, p, (unsigned int) i);\n\tbuffer[i] = 0;\n\treturn buffer;\n    } else if (!i) {\n\t*freeProcPtr = NULL;\n\treturn \"\";\n    }\n    buffer = (char *)Tcl_Alloc(4 * (size_t)i);\n    *freeProcPtr = TCL_DYNAMIC;\n\n    p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;\n    snprintf(buffer, 4 * (size_t)i, \"%d\", *p++ & 0xff);\n    while (--i) {\n\tsnprintf(buffer + strlen(buffer), 4 * (size_t)i - strlen(buffer), \" %d\", *p++ & 0xff);\n    }\n    return buffer;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * InitSmoothMethods --\n *\n *\tThis function is invoked to set up the initial state of the list of\n *\t\"-smooth\" methods. It should only be called when the list installed\n *\tin the interpreter is NULL.\n *\n * Results:\n *\tPointer to the start of the list of default smooth methods.\n *\n * Side effects:\n *\tA linked list of smooth methods is created and attached to the\n *\tinterpreter's association key \"smoothMethod\"\n *\n *--------------------------------------------------------------\n */\n\nstatic SmoothAssocData *\nInitSmoothMethods(\n    Tcl_Interp *interp)\n{\n    SmoothAssocData *methods, *ptr;\n\n    methods = (SmoothAssocData *)Tcl_Alloc(sizeof(SmoothAssocData));\n    methods->smooth.name = tkRawSmoothMethod.name;\n    methods->smooth.coordProc = tkRawSmoothMethod.coordProc;\n    methods->smooth.postscriptProc = tkRawSmoothMethod.postscriptProc;\n\n    ptr = methods->nextPtr = (SmoothAssocData *)Tcl_Alloc(sizeof(SmoothAssocData));\n    ptr->smooth.name = tkBezierSmoothMethod.name;\n    ptr->smooth.coordProc = tkBezierSmoothMethod.coordProc;\n    ptr->smooth.postscriptProc = tkBezierSmoothMethod.postscriptProc;\n    ptr->nextPtr = NULL;\n\n    Tcl_SetAssocData(interp, \"smoothMethod\", SmoothMethodCleanupProc,methods);\n    return methods;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateSmoothMethod --\n *\n *\tThis function is invoked to add additional values for the \"-smooth\"\n *\toption to the list.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tIn the future \"-smooth <name>\" will be accepted as smooth method for\n *\tthe line and polygon.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_CreateSmoothMethod(\n    Tcl_Interp *interp,\n    const Tk_SmoothMethod *smooth)\n{\n    SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;\n    methods = (SmoothAssocData *)Tcl_GetAssocData(interp, \"smoothMethod\", NULL);\n\n    /*\n     * Initialize if we were not previously initialized.\n     */\n\n    if (methods == NULL) {\n\tmethods = InitSmoothMethods(interp);\n    }\n\n    /*\n     * If there's already a smooth method with the given name, remove it.\n     */\n\n    for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;\n\t    prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {\n\tif (!strcmp(typePtr2->smooth.name, smooth->name)) {\n\t    if (prevPtr == NULL) {\n\t\tmethods = typePtr2->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = typePtr2->nextPtr;\n\t    }\n\t    Tcl_Free(typePtr2);\n\t    break;\n\t}\n    }\n    ptr = (SmoothAssocData *)Tcl_Alloc(sizeof(SmoothAssocData));\n    ptr->smooth.name = smooth->name;\n    ptr->smooth.coordProc = smooth->coordProc;\n    ptr->smooth.postscriptProc = smooth->postscriptProc;\n    ptr->nextPtr = methods;\n    Tcl_SetAssocData(interp, \"smoothMethod\", SmoothMethodCleanupProc, ptr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SmoothMethodCleanupProc --\n *\n *\tThis function is invoked whenever an interpreter is deleted to\n *\tcleanup the smooth methods.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSmooth methods are removed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSmoothMethodCleanupProc(\n    void *clientData,\t/* Points to \"smoothMethod\" AssocData for the\n\t\t\t\t * interpreter. */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* Interpreter that is being deleted. */\n{\n    SmoothAssocData *ptr, *methods = (SmoothAssocData *)clientData;\n\n    while (methods != NULL) {\n\tptr = methods;\n\tmethods = methods->nextPtr;\n\tTcl_Free(ptr);\n    }\n}\n/*\n *--------------------------------------------------------------\n *\n * TkSmoothParseProc --\n *\n *\tThis function is invoked during option processing to handle the\n *\t\"-smooth\" option.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe smooth option for a given item gets replaced by the value\n *\tindicated in the value argument.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkSmoothParseProc(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    const Tk_SmoothMethod **smoothPtr =\n\t    (const Tk_SmoothMethod **) (widgRec + offset);\n    const Tk_SmoothMethod *smooth = NULL;\n    int b;\n    size_t length;\n    SmoothAssocData *methods;\n\n    if (value == NULL || *value == 0) {\n\t*smoothPtr = NULL;\n\treturn TCL_OK;\n    }\n    length = strlen(value);\n    methods = (SmoothAssocData *)Tcl_GetAssocData(interp, \"smoothMethod\", NULL);\n\n    /*\n     * Not initialized yet; fix that now.\n     */\n\n    if (methods == NULL) {\n\tmethods = InitSmoothMethods(interp);\n    }\n\n    /*\n     * Backward compatibility hack.\n     */\n\n    if (strncmp(value, \"bezier\", length) == 0) {\n\tsmooth = &tkBezierSmoothMethod;\n    }\n\n    /*\n     * Search the list of installed smooth methods.\n     */\n\n    while (methods != NULL) {\n\tif (strncmp(value, methods->smooth.name, length) == 0) {\n\t    if (smooth != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"ambiguous smooth method \\\"%s\\\"\", value));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"SMOOTH\", value,\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    smooth = &methods->smooth;\n\t}\n\tmethods = methods->nextPtr;\n    }\n    if (smooth) {\n\t*smoothPtr = smooth;\n\treturn TCL_OK;\n    }\n\n    /*\n     * Did not find it. Try parsing as a boolean instead.\n     */\n\n    if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    *smoothPtr = b ? &tkBezierSmoothMethod : NULL;\n    return TCL_OK;\n}\n/*\n *--------------------------------------------------------------\n *\n * TkSmoothPrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-smooth\" configuration option.\n *\n * Results:\n *\tThe return value is a string describing the smooth option for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTkSmoothPrintProc(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset into item. */\n    TCL_UNUSED(Tcl_FreeProc **))\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    const Tk_SmoothMethod *smoothPtr =\n\t    * (Tk_SmoothMethod **) (widgRec + offset);\n\n    return smoothPtr ? smoothPtr->name : \"0\";\n}\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetDash\n *\n *\tThis function is used to parse a string, assuming it is dash\n *\tinformation.\n *\n * Results:\n *\tThe return value is a standard Tcl result: TCL_OK means that the dash\n *\tinformation was parsed ok, and TCL_ERROR means it couldn't be parsed.\n *\n * Side effects:\n *\tDash information in the dash structure is updated.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetDash(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    const char *value,\t\t/* Textual specification of dash list. */\n    Tk_Dash *dash)\t\t/* Pointer to record in which to store dash\n\t\t\t\t * information. */\n{\n    Tcl_Size argc;\n    int i;\n    const char **largv, **argv = NULL;\n    char *pt;\n\n    if ((value == NULL) || (*value == '\\0')) {\n\tdash->number = 0;\n\treturn TCL_OK;\n    }\n\n    /*\n     * switch is usually compiled more efficiently than a chain of conditions.\n     */\n\n    switch (*value) {\n    case '.': case ',': case '-': case '_':\n\ti = DashConvert(NULL, value, -1, 0.0);\n\tif (i <= 0) {\n\t    goto badDashList;\n\t}\n\ti = (int)strlen(value);\n\tif (i > (int) sizeof(char *)) {\n\t    dash->pattern.pt = pt = (char *)Tcl_Alloc(strlen(value));\n\t} else {\n\t    pt = dash->pattern.array;\n\t}\n\tmemcpy(pt, value, (unsigned) i);\n\tdash->number = -i;\n\treturn TCL_OK;\n    }\n\n    if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {\n\tTcl_ResetResult(interp);\n\tgoto badDashList;\n    }\n\n    if ((unsigned) ABS(dash->number) > sizeof(char *)) {\n\tTcl_Free(dash->pattern.pt);\n    }\n    if (argc > (int)sizeof(char *)) {\n\tdash->pattern.pt = pt = (char *)Tcl_Alloc(argc);\n    } else {\n\tpt = dash->pattern.array;\n    }\n    dash->number = (int)argc;\n\n    largv = argv;\n    while (argc > 0) {\n\tif (Tcl_GetInt(interp, *largv, &i) != TCL_OK || i < 1 || i>255) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"expected integer in the range 1..255 but got \\\"%s\\\"\",\n\t\t    *largv));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"DASH\", (char *)NULL);\n\t    goto syntaxError;\n\t}\n\t*pt++ = (char)i;\n\targc--;\n\tlargv++;\n    }\n\n    if (argv != NULL) {\n\tTcl_Free(argv);\n    }\n    return TCL_OK;\n\n    /*\n     * Something went wrong. Generate error message, clean up and return.\n     */\n\n  badDashList:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad dash list \\\"%s\\\": must be a list of integers or a format like \\\"-..\\\"\",\n\t    value));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"DASH\", (char *)NULL);\n  syntaxError:\n    if (argv != NULL) {\n\tTcl_Free(argv);\n    }\n    if ((unsigned) ABS(dash->number) > sizeof(char *)) {\n\tTcl_Free(dash->pattern.pt);\n    }\n    dash->number = 0;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateOutline\n *\n *\tThis function initializes the Tk_Outline structure with default\n *\tvalues.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tNone\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_CreateOutline(\n    Tk_Outline *outline)\t/* Outline structure to be filled in. */\n{\n    outline->gc = NULL;\n    outline->width = 1.0;\n    outline->activeWidth = 0.0;\n    outline->disabledWidth = 0.0;\n    outline->offset = 0;\n    outline->offsetObj = NULL;\n    outline->reserved2 = NULL;\n    outline->reserved3 = NULL;\n    outline->dash.number = 0;\n    outline->activeDash.number = 0;\n    outline->disabledDash.number = 0;\n    outline->tsoffset.flags = 0;\n    outline->tsoffset.xoffset = 0;\n    outline->tsoffset.yoffset = 0;\n    outline->color = NULL;\n    outline->activeColor = NULL;\n    outline->disabledColor = NULL;\n    outline->stipple = None;\n    outline->activeStipple = None;\n    outline->disabledStipple = None;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DeleteOutline\n *\n *\tThis function frees all memory that might be allocated and referenced\n *\tin the Tk_Outline structure.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tNone\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_DeleteOutline(\n    Display *display,\t\t/* Display containing window. */\n    Tk_Outline *outline)\n{\n    if (outline->gc != NULL) {\n\tTk_FreeGC(display, outline->gc);\n    }\n    if ((unsigned) ABS(outline->dash.number) > sizeof(char *)) {\n\tTcl_Free(outline->dash.pattern.pt);\n    }\n    if ((unsigned) ABS(outline->activeDash.number) > sizeof(char *)) {\n\tTcl_Free(outline->activeDash.pattern.pt);\n    }\n    if ((unsigned) ABS(outline->disabledDash.number) > sizeof(char *)) {\n\tTcl_Free(outline->disabledDash.pattern.pt);\n    }\n    if (outline->color != NULL) {\n\tTk_FreeColor(outline->color);\n    }\n    if (outline->activeColor != NULL) {\n\tTk_FreeColor(outline->activeColor);\n    }\n    if (outline->disabledColor != NULL) {\n\tTk_FreeColor(outline->disabledColor);\n    }\n    if (outline->stipple != None) {\n\tTk_FreeBitmap(display, outline->stipple);\n    }\n    if (outline->activeStipple != None) {\n\tTk_FreeBitmap(display, outline->activeStipple);\n    }\n    if (outline->disabledStipple != None) {\n\tTk_FreeBitmap(display, outline->disabledStipple);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ConfigOutlineGC\n *\n *\tThis function should be called in the canvas object during the\n *\tconfigure command. The graphics context description in gcValues is\n *\tupdated according to the information in the dash structure, as far as\n *\tpossible.\n *\n * Results:\n *\tThe return-value is a mask, indicating which elements of gcValues have\n *\tbeen updated. 0 means there is no outline.\n *\n * Side effects:\n *\tGC information in gcValues is updated.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ConfigOutlineGC(\n    XGCValues *gcValues,\n    Tk_Canvas canvas,\n    Tk_Item *item,\n    Tk_Outline *outline)\n{\n    int mask = 0;\n    double width;\n    Tk_Dash *dash;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state = item->state;\n\n    if (outline->width < 0.0) {\n\toutline->width = 0.0;\n    }\n    if (outline->activeWidth < 0.0) {\n\toutline->activeWidth = 0.0;\n    }\n    if (outline->disabledWidth < 0) {\n\toutline->disabledWidth = 0.0;\n    }\n    if (state==TK_STATE_HIDDEN) {\n\treturn 0;\n    }\n\n    width = outline->width;\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n    dash = &(outline->dash);\n    color = outline->color;\n    stipple = outline->stipple;\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (Canvas(canvas)->currentItemPtr == item) {\n\tif (outline->activeWidth>width) {\n\t    width = outline->activeWidth;\n\t}\n\tif (outline->activeDash.number != 0) {\n\t    dash = &(outline->activeDash);\n\t}\n\tif (outline->activeColor!=NULL) {\n\t    color = outline->activeColor;\n\t}\n\tif (outline->activeStipple!=None) {\n\t    stipple = outline->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (outline->disabledWidth>0) {\n\t    width = outline->disabledWidth;\n\t}\n\tif (outline->disabledDash.number != 0) {\n\t    dash = &(outline->disabledDash);\n\t}\n\tif (outline->disabledColor!=NULL) {\n\t    color = outline->disabledColor;\n\t}\n\tif (outline->disabledStipple!=None) {\n\t    stipple = outline->disabledStipple;\n\t}\n    }\n\n    if (color==NULL) {\n\treturn 0;\n    }\n\n    gcValues->line_width = (int) (width + 0.5);\n    if (color != NULL) {\n\tgcValues->foreground = color->pixel;\n\tmask = GCForeground|GCLineWidth;\n\tif (stipple != None) {\n\t    gcValues->stipple = stipple;\n\t    gcValues->fill_style = FillStippled;\n\t    mask |= GCStipple|GCFillStyle;\n\t}\n    }\n    if (mask && (dash->number != 0)) {\n\tgcValues->line_style = LineOnOffDash;\n\tif (outline->offsetObj && Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,\n\t\toutline->offsetObj, &outline->offset) != TCL_OK) {\n\t    outline->offset = 0;\n\t}\n\tgcValues->dash_offset = outline->offset;\n\tif ((unsigned int)ABS(dash->number) > sizeof(char *)) {\n\t    gcValues->dashes = dash->pattern.pt[0];\n\t} else if (dash->number != 0) {\n\t    gcValues->dashes = dash->pattern.array[0];\n\t} else {\n\t    gcValues->dashes = (char) (4 * width + 0.5);\n\t}\n\tmask |= GCLineStyle|GCDashList|GCDashOffset;\n    }\n    return mask;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ChangeOutlineGC\n *\n *\tUpdates the GC to represent the full information of the dash\n *\tstructure. Partly this is already done in Tk_ConfigOutlineGC(). This\n *\tfunction should be called just before drawing the dashed item.\n *\n * Results:\n *\t1 if there is a stipple pattern, and 0 otherwise.\n *\n * Side effects:\n *\tGC is updated.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ChangeOutlineGC(\n    Tk_Canvas canvas,\n    Tk_Item *item,\n    Tk_Outline *outline)\n{\n    const char *p;\n    double width;\n    Tk_Dash *dash;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state = item->state;\n\n    width = outline->width;\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n    if (outline->offsetObj && Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,\n\t    outline->offsetObj, &outline->offset) != TCL_OK) {\n\toutline->offset = 0;\n    }\n    dash = &(outline->dash);\n    color = outline->color;\n    stipple = outline->stipple;\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (Canvas(canvas)->currentItemPtr == item) {\n\tif (outline->activeWidth > width) {\n\t    width = outline->activeWidth;\n\t}\n\tif (outline->activeDash.number != 0) {\n\t    dash = &(outline->activeDash);\n\t}\n\tif (outline->activeColor != NULL) {\n\t    color = outline->activeColor;\n\t}\n\tif (outline->activeStipple != None) {\n\t    stipple = outline->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (outline->disabledWidth > width) {\n\t    width = outline->disabledWidth;\n\t}\n\tif (outline->disabledDash.number != 0) {\n\t    dash = &(outline->disabledDash);\n\t}\n\tif (outline->disabledColor != NULL) {\n\t    color = outline->disabledColor;\n\t}\n\tif (outline->disabledStipple != None) {\n\t    stipple = outline->disabledStipple;\n\t}\n    }\n    if (color==NULL) {\n\treturn 0;\n    }\n\n    if ((dash->number<-1) ||\n\t    ((dash->number == -1) && (dash->pattern.array[0] != ','))) {\n\tchar *q;\n\tint i = -dash->number;\n\n\tp = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;\n\tq = (char *)Tcl_Alloc(2 * i);\n\ti = DashConvert(q, p, i, width);\n\tXSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, q,i);\n\tTcl_Free(q);\n    } else if (dash->number>2 || (dash->number==2 &&\n\t    (dash->pattern.array[0]!=dash->pattern.array[1]))) {\n\tp = (dash->number > (int) sizeof(char *))\n\t\t? dash->pattern.pt : dash->pattern.array;\n\tXSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, p,\n\t\tdash->number);\n    }\n    if (stipple!=None) {\n\tint w = 0; int h = 0;\n\tTk_TSOffset *tsoffset = &outline->tsoffset;\n\tint flags = tsoffset->flags;\n\n\tif (!(flags & TK_OFFSET_INDEX) &&\n\t\t(flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {\n\t    Tk_SizeOfBitmap(Canvas(canvas)->display, stipple, &w, &h);\n\t    if (flags & TK_OFFSET_CENTER) {\n\t\tw /= 2;\n\t    } else {\n\t\tw = 0;\n\t    }\n\t    if (flags & TK_OFFSET_MIDDLE) {\n\t\th /= 2;\n\t    } else {\n\t\th = 0;\n\t    }\n\t}\n\ttsoffset->xoffset -= w;\n\ttsoffset->yoffset -= h;\n\tTk_CanvasSetOffset(canvas, outline->gc, tsoffset);\n\ttsoffset->xoffset += w;\n\ttsoffset->yoffset += h;\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ResetOutlineGC\n *\n *\tRestores the GC to the situation before Tk_ChangeOutlineGC() was\n *\tcalled. This function should be called just after the dashed item is\n *\tdrawn, because the GC is supposed to be read-only.\n *\n * Results:\n *\t1 if there is a stipple pattern, and 0 otherwise.\n *\n * Side effects:\n *\tGC is updated.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ResetOutlineGC(\n    Tk_Canvas canvas,\n    Tk_Item *item,\n    Tk_Outline *outline)\n{\n    char dashList;\n    double width;\n    Tk_Dash *dash;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state = item->state;\n\n    width = outline->width;\n    if (width < 1.0) {\n\twidth = 1.0;\n    }\n    if (outline->offsetObj && Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,\n\t    outline->offsetObj, &outline->offset) != TCL_OK) {\n\toutline->offset = 0;\n    }\n    dash = &(outline->dash);\n    color = outline->color;\n    stipple = outline->stipple;\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (Canvas(canvas)->currentItemPtr == item) {\n\tif (outline->activeWidth>width) {\n\t    width = outline->activeWidth;\n\t}\n\tif (outline->activeDash.number != 0) {\n\t    dash = &(outline->activeDash);\n\t}\n\tif (outline->activeColor!=NULL) {\n\t    color = outline->activeColor;\n\t}\n\tif (outline->activeStipple!=None) {\n\t    stipple = outline->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (outline->disabledWidth>width) {\n\t    width = outline->disabledWidth;\n\t}\n\tif (outline->disabledDash.number != 0) {\n\t    dash = &(outline->disabledDash);\n\t}\n\tif (outline->disabledColor!=NULL) {\n\t    color = outline->disabledColor;\n\t}\n\tif (outline->disabledStipple!=None) {\n\t    stipple = outline->disabledStipple;\n\t}\n    }\n    if (color==NULL) {\n\treturn 0;\n    }\n\n    if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&\n\t    (dash->pattern.array[0] != dash->pattern.array[1])) ||\n\t    ((dash->number == -1) && (dash->pattern.array[0] != ','))) {\n\tif ((unsigned int)ABS(dash->number) > sizeof(char *)) {\n\t    dashList = dash->pattern.pt[0];\n\t} else if (dash->number != 0) {\n\t    dashList = dash->pattern.array[0];\n\t} else {\n\t    dashList = (char) (4 * width + 0.5);\n\t}\n\tXSetDashes(Canvas(canvas)->display, outline->gc, outline->offset,\n\t\t&dashList , 1);\n    }\n    if (stipple != None) {\n\tXSetTSOrigin(Canvas(canvas)->display, outline->gc, 0, 0);\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsOutline\n *\n *\tCreates the postscript command for the correct Outline-information\n *\t(width, dash, color and stipple).\n *\n * Results:\n *\tTCL_OK if succeeded, otherwise TCL_ERROR.\n *\n * Side effects:\n *\tcanvas->interp->result contains the postscript string, or an error\n *\tmessage if the result was TCL_ERROR.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasPsOutline(\n    Tk_Canvas canvas,\n    Tk_Item *item,\n    Tk_Outline *outline)\n{\n    char pattern[11];\n    int i;\n    char *ptr, *lptr = pattern;\n    Tcl_Interp *interp = Canvas(canvas)->interp;\n    double width = outline->width;\n    Tk_Dash *dash = &outline->dash;\n    XColor *color = outline->color;\n    Pixmap stipple = outline->stipple;\n    Tk_State state = item->state;\n    Tcl_Obj *psObj = GetPostscriptBuffer(interp);\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    if (Canvas(canvas)->currentItemPtr == item) {\n\tif (outline->activeWidth > width) {\n\t    width = outline->activeWidth;\n\t}\n\tif (outline->activeDash.number > 0) {\n\t    dash = &outline->activeDash;\n\t}\n\tif (outline->activeColor != NULL) {\n\t    color = outline->activeColor;\n\t}\n\tif (outline->activeStipple != None) {\n\t    stipple = outline->activeStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (outline->disabledWidth > 0) {\n\t    width = outline->disabledWidth;\n\t}\n\tif (outline->disabledDash.number > 0) {\n\t    dash = &outline->disabledDash;\n\t}\n\tif (outline->disabledColor != NULL) {\n\t    color = outline->disabledColor;\n\t}\n\tif (outline->disabledStipple != None) {\n\t    stipple = outline->disabledStipple;\n\t}\n    }\n\n    if (outline->offsetObj && Tk_GetPixelsFromObj(NULL, Canvas(canvas)->tkwin,\n\t    outline->offsetObj, &outline->offset) != TCL_OK) {\n\toutline->offset = 0;\n    }\n    Tcl_AppendPrintfToObj(psObj, \"%.15g setlinewidth\\n\", width);\n\n    ptr = ((unsigned) ABS(dash->number) > sizeof(char *)) ?\n\t    dash->pattern.pt : dash->pattern.array;\n    Tcl_AppendToObj(psObj, \"[\", TCL_INDEX_NONE);\n    if (dash->number > 0) {\n\tTcl_Obj *converted;\n\tchar *p = ptr;\n\n\tconverted = Tcl_ObjPrintf(\"%d\", *p++ & 0xff);\n\tfor (i = dash->number-1 ; i>0 ; i--) {\n\t    Tcl_AppendPrintfToObj(converted, \" %d\", *p++ & 0xff);\n\t}\n\tTcl_AppendObjToObj(psObj, converted);\n\tif (dash->number & 1) {\n\t    Tcl_AppendToObj(psObj, \" \", TCL_INDEX_NONE);\n\t    Tcl_AppendObjToObj(psObj, converted);\n\t}\n\tTcl_DecrRefCount(converted);\n\tTcl_AppendPrintfToObj(psObj, \"] %d setdash\\n\", outline->offset);\n    } else if (dash->number < 0) {\n\tif (dash->number < -5) {\n\t    lptr = (char *)Tcl_Alloc(1 - 2*dash->number);\n\t}\n\ti = DashConvert(lptr, ptr, -dash->number, width);\n\tif (i > 0) {\n\t    char *p = lptr;\n\n\t    Tcl_AppendPrintfToObj(psObj, \"%d\", *p++ & 0xff);\n\t    for (; --i>0 ;) {\n\t\tTcl_AppendPrintfToObj(psObj, \" %d\", *p++ & 0xff);\n\t    }\n\t    Tcl_AppendPrintfToObj(psObj, \"] %d setdash\\n\", outline->offset);\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"] 0 setdash\\n\", TCL_INDEX_NONE);\n\t}\n\tif (lptr != pattern) {\n\t    Tcl_Free(lptr);\n\t}\n    } else {\n\tTcl_AppendToObj(psObj, \"] 0 setdash\\n\", TCL_INDEX_NONE);\n    }\n\n    Tk_CanvasPsColor(interp, canvas, color);\n\n    if (stipple != None) {\n\tTcl_AppendToObj(GetPostscriptBuffer(interp), \"StrokeClip \", TCL_INDEX_NONE);\n\tTk_CanvasPsStipple(interp, canvas, stipple);\n    } else {\n\tTcl_AppendToObj(GetPostscriptBuffer(interp), \"stroke\\n\", TCL_INDEX_NONE);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DashConvert\n *\n *\tConverts a character-like dash-list (e.g. \"-..\") into an X11-style. l\n *\tmust point to a string that holds room to at least 2*n characters. If\n *\tl == NULL, this function can be used for syntax checking only.\n *\n * Results:\n *\tThe length of the resulting X11 compatible dash-list. -1 if failed.\n *\n * Side effects:\n *\tNone\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nDashConvert(\n    char *l,\t\t\t/* Must be at least 2*n chars long, or NULL to\n\t\t\t\t * indicate \"just check syntax\". */\n    const char *p,\t\t/* String to parse. */\n    Tcl_Size n,\t\t\t/* Length of string to parse, or -1 to\n\t\t\t\t * indicate that strlen() should be used. */\n    double width)\t\t/* Width of line. */\n{\n    int result = 0;\n    int size, intWidth;\n\n    if (n < 0) {\n\tn = strlen(p);\n    }\n    intWidth = (int) (width + 0.5);\n    if (intWidth < 1) {\n\tintWidth = 1;\n    }\n    while (n-- && *p) {\n\tswitch (*p++) {\n\tcase ' ':\n\t    if (result) {\n\t\tif (l) {\n\t\t    l[-1] += (char)(intWidth + 1);\n\t\t}\n\t\tcontinue;\n\t    }\n\t    return 0;\n\tcase '_':\n\t    size = 8;\n\t    break;\n\tcase '-':\n\t    size = 6;\n\t    break;\n\tcase ',':\n\t    size = 4;\n\t    break;\n\tcase '.':\n\t    size = 2;\n\t    break;\n\tdefault:\n\t    return -1;\n\t}\n\tif (l) {\n\t    *l++ = (char)(size * intWidth);\n\t    *l++ = (char)(4 * intWidth);\n\t}\n\tresult += 2;\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TranslateAndAppendCoords --\n *\n *\tThis is a helper routine for TkCanvTranslatePath() below.\n *\n *\tGiven an (x,y) coordinate pair within a canvas, this function computes\n *\tthe corresponding coordinates at which the point should be drawn in\n *\tthe drawable used for display. Those coordinates are then written into\n *\toutArr[numOut*2] and outArr[numOut*2+1].\n *\n * Results:\n *\tThere is no return value.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTranslateAndAppendCoords(\n    TkCanvas *canvPtr,\t\t/* The canvas. */\n    double x,\t\t\t/* Coordinates in canvas space. */\n    double y,\n    XPoint *outArr,\t\t/* Write results into this array */\n    Tcl_Size numOut)\t\t\t/* Num of prior entries in outArr[] */\n{\n    double tmp;\n\n    tmp = x - canvPtr->drawableXOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    outArr[numOut].x = (short) tmp;\n\n    tmp = y - canvPtr->drawableYOrigin;\n    if (tmp > 0) {\n\ttmp += 0.5;\n    } else {\n\ttmp -= 0.5;\n    }\n    outArr[numOut].y = (short) tmp;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkCanvTranslatePath\n *\n *\tTranslate a line or polygon path so that all vertices are within a\n *\trectangle that is 1000 pixels larger than the total size of the canvas\n *\twindow. This will prevent pixel coordinates from overflowing the\n *\t16-bit integer size limitation imposed by most windowing systems.\n *\n *\tcoordPtr must point to an array of doubles, two doubles per vertex.\n *\tThere are a total of numVertex vertices, or 2*numVertex entries in\n *\tcoordPtr. The result vertices written into outArr have their\n *\tcoordinate origin shifted to canvPtr->drawableXOrigin by\n *\tcanvPtr->drawableYOrigin. There might be as many as 3 times more\n *\toutput vertices than there are input vertices. The calling function\n *\tshould allocate space accordingly.\n *\n *\tThis routine limits the width and height of a canvas window to 31767\n *\tpixels. At the highest resolution display devices available today (210\n *\tppi in Jan 2003) that's a window that is over 13 feet wide and tall.\n *\tShould be enough for the near future.\n *\n * Results:\n *\tClipped and translated path vertices are written into outArr[]. There\n *\tmight be as many as twice the vertices in outArr[] as there are in\n *\tcoordPtr[]. The return value is the number of vertices actually\n *\twritten into outArr[].\n *\n * Side effects:\n *\tNone\n *\n *--------------------------------------------------------------\n */\n\nTcl_Size\nTkCanvTranslatePath(\n    TkCanvas *canvPtr,\t\t/* The canvas */\n    Tcl_Size numVertex,\t\t/* Number of vertices specified by\n\t\t\t\t * coordArr[] */\n    double *coordArr,\t\t/* X and Y coordinates for each vertex */\n    TCL_UNUSED(int),\t\t/* True if this is a closed polygon */\n    XPoint *outArr)\t\t/* Write results here, if not NULL */\n{\n    Tcl_Size numOutput = 0;\t\t/* Number of output coordinates */\n    double lft, rgh;\t\t/* Left and right sides of the bounding box */\n    double top, btm;\t\t/* Top and bottom sizes of the bounding box */\n    double *tempArr;\t\t/* Temporary storage used by the clipper */\n    double *a, *b, *t;\t\t/* Pointers to parts of the temporary\n\t\t\t\t * storage */\n    Tcl_Size i, j;\t\t\t/* Loop counters */\n    double limit[4];\t\t/* Boundries at which clipping occurs */\n    double staticSpace[480];\t/* Temp space from the stack */\n\n    /*\n     * Constrain all vertices of the path to be within a box that is no larger\n     * than 32000 pixels wide or height. The top-left corner of this clipping\n     * box is 1000 pixels above and to the left of the top left corner of the\n     * window on which the canvas is displayed.\n     *\n     * This means that a canvas will not display properly on a canvas window\n     * that is larger than 31000 pixels wide or high. That is not a problem\n     * today, but might someday become a factor for ultra-high resolutions\n     * displays.\n     *\n     * The X11 protocol allows us (in theory) to expand the size of the\n     * clipping box to 32767 pixels. But we have found experimentally that\n     * XFree86 sometimes fails to draw lines correctly if they are longer than\n     * about 32500 pixels. So we have left a little margin in the size to mask\n     * that bug.\n     */\n\n    lft = canvPtr->xOrigin - 1000.0;\n    top = canvPtr->yOrigin - 1000.0;\n    rgh = lft + 32000.0;\n    btm = top + 32000.0;\n\n    /*\n     * Try the common case first - no clipping. Loop over the input\n     * coordinates and translate them into appropriate output coordinates.\n     * But if a vertex outside of the bounding box is seen, break out of the\n     * loop.\n     *\n     * Most of the time, no clipping is needed, so this one loop is sufficient\n     * to do the translation.\n     */\n\n    for (i=0; i<numVertex; i++){\n\tdouble x, y;\n\n\tx = coordArr[i*2];\n\ty = coordArr[i*2 + 1];\n\tif (x<lft || x>rgh || y<top || y>btm) {\n\t    break;\n\t}\n\tTranslateAndAppendCoords(canvPtr, x, y, outArr, numOutput++);\n    }\n    if (i == numVertex){\n\tassert(numOutput == numVertex);\n\treturn numOutput;\n    }\n\n    /*\n     * If we reach this point, it means that some clipping is required. Begin\n     * by allocating some working storage - at least 6 times as much space as\n     * coordArr[] requires. Divide this space into two separate arrays a[] and\n     * b[]. Initialize a[] to be equal to coordArr[].\n     */\n\n    if (numVertex*12 <= (int) (sizeof(staticSpace) / sizeof(double))) {\n\ttempArr = staticSpace;\n    } else {\n\ttempArr = (double *)Tcl_Alloc(numVertex * 12 * sizeof(double));\n    }\n    for (i=0; i<numVertex*2; i++){\n\ttempArr[i] = coordArr[i];\n    }\n    a = tempArr;\n    b = &tempArr[numVertex*6];\n\n    /*\n     * We will make four passes through the input data. On each pass, we copy\n     * the contents of a[] over into b[]. As we copy, we clip any line\n     * segments that extend to the right past xClip then we rotate the\n     * coordinate system 90 degrees clockwise. After each pass is complete, we\n     * interchange a[] and b[] in preparation for the next pass.\n     *\n     * Each pass clips line segments that extend beyond a single side of the\n     * bounding box, and four passes rotate the coordinate system back to its\n     * original value. I'm not an expert on graphics algorithms, but I think\n     * this is called Cohen-Sutherland polygon clipping.\n     *\n     * The limit[] array contains the xClip value used for each of the four\n     * passes.\n     */\n\n    limit[0] = rgh;\n    limit[1] = -top;\n    limit[2] = -lft;\n    limit[3] = btm;\n\n    /*\n     * This is the loop that makes the four passes through the data.\n     */\n\n    for (j=0; j<4; j++) {\n\tdouble xClip = limit[j];\n\tint inside = a[0] < xClip;\n\tdouble priorY = a[1];\n\tnumOutput = 0;\n\n\t/*\n\t * Clip everything to the right of xClip. Store the results in b[]\n\t * rotated by 90 degrees clockwise.\n\t */\n\n\tfor (i=0; i<numVertex; i++) {\n\t    double x = a[i*2];\n\t    double y = a[i*2 + 1];\n\n\t    if (x >= xClip) {\n\t\t/*\n\t\t * The current vertex is to the right of xClip.\n\t\t */\n\n\t\tif (inside) {\n\t\t    /*\n\t\t     * If the current vertex is to the right of xClip but the\n\t\t     * previous vertex was left of xClip, then draw a line\n\t\t     * segment from the previous vertex to until it intersects\n\t\t     * the vertical at xClip.\n\t\t     */\n\n\t\t    double x0, y0, yN;\n\n\t\t    assert(i > 0);\n\t\t    x0 = a[i*2 - 2];\n\t\t    y0 = a[i*2 - 1];\n\t\t    yN = y0 + (y - y0)*(xClip-x0)/(x-x0);\n\t\t    b[numOutput*2] = -yN;\n\t\t    b[numOutput*2 + 1] = xClip;\n\t\t    numOutput++;\n\t\t    assert(numOutput <= numVertex*3);\n\t\t    priorY = yN;\n\t\t    inside = 0;\n\t\t} else if (i == 0) {\n\t\t    /*\n\t\t     * If the first vertex is to the right of xClip, add a\n\t\t     * vertex that is the projection of the first vertex onto\n\t\t     * the vertical xClip line.\n\t\t     */\n\n\t\t    b[0] = -y;\n\t\t    b[1] = xClip;\n\t\t    numOutput = 1;\n\t\t    priorY = y;\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * The current vertex is to the left of xClip\n\t\t */\n\n\t\tif (!inside) {\n\t\t    /*\n\t\t     * If the current vertex is on the left of xClip and one\n\t\t     * or more prior vertices where to the right, then we have\n\t\t     * to draw a line segment along xClip that extends from\n\t\t     * the spot where we first crossed from left to right to\n\t\t     * the spot where we cross back from right to left.\n\t\t     */\n\n\t\t    double x0, y0, yN;\n\n\t\t    assert(i > 0);\n\t\t    x0 = a[i*2 - 2];\n\t\t    y0 = a[i*2 - 1];\n\t\t    yN = y0 + (y - y0)*(xClip-x0)/(x-x0);\n\t\t    if (yN != priorY) {\n\t\t\tb[numOutput*2] = -yN;\n\t\t\tb[numOutput*2 + 1] = xClip;\n\t\t\tnumOutput++;\n\t\t\tassert(numOutput <= numVertex*3);\n\t\t    }\n\t\t    inside = 1;\n\t\t}\n\t\tb[numOutput*2] = -y;\n\t\tb[numOutput*2 + 1] = x;\n\t\tnumOutput++;\n\t\tassert(numOutput <= numVertex*3);\n\t    }\n\t}\n\n\t/*\n\t * Interchange a[] and b[] in preparation for the next pass.\n\t */\n\n\tt = a;\n\ta = b;\n\tb = t;\n\tnumVertex = numOutput;\n    }\n\n    /*\n     * All clipping is now finished. Convert the coordinates from doubles into\n     * XPoints and translate the origin for the drawable.\n     */\n\n    for (i=0; i<numVertex; i++) {\n\tTranslateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i);\n    }\n    if (tempArr != staticSpace) {\n\tTcl_Free(tempArr);\n    }\n    return numOutput;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkRotatePoint --\n *\n *\tRotate a point about another point. The angle should be converted into\n *\tits sine and cosine before calling this function.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe point in (*xPtr,*yPtr) is updated to be rotated about\n *\t(originX,originY) by the amount given by the sine and cosine of the\n *\tangle to rotate.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkRotatePoint(\n    double originX, double originY,\t/* The point about which to rotate. */\n    double sine, double cosine,\t\t/* How much to rotate? */\n    double *xPtr, double *yPtr)\t\t/* The point to be rotated. (INOUT) */\n{\n    double x = *xPtr - originX;\n    double y = *yPtr - originY;\n\n    /*\n     * Beware! The canvas coordinate space is flipped vertically, so rotations\n     * go the \"wrong\" way with respect to mathematics.\n     */\n\n    *xPtr = originX + x * cosine + y * sine;\n    *yPtr = originY - x * sine + y * cosine;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvWind.c",
    "content": "/*\n * tkCanvWind.c --\n *\n *\tThis file implements window items for canvas widgets.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n\n/*\n * The structure below defines the record for each window item.\n */\n\ntypedef struct WindowItem  {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types.  MUST BE FIRST IN STRUCTURE. */\n    double x, y;\t\t/* Coordinates of positioning point for\n\t\t\t\t * window. */\n    Tk_Window tkwin;\t\t/* Window associated with item.  NULL means\n\t\t\t\t * window has been destroyed. */\n    int width;\t\t\t/* Width to use for window (<= 0 means use\n\t\t\t\t * window's requested width). */\n    int height;\t\t\t/* Width to use for window (<= 0 means use\n\t\t\t\t * window's requested width). */\n    Tk_Anchor anchor;\t\t/* Where to anchor window relative to\n\t\t\t\t * (x,y). */\n    Tk_Canvas canvas;\t\t/* Canvas containing this item. */\n} WindowItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_ANCHOR, \"-anchor\", NULL, NULL,\n\t\"center\", offsetof(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_PIXELS, \"-height\", NULL, NULL,\n\t\"0\", offsetof(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_PIXELS, \"-width\", NULL, NULL,\n\t\"0\", offsetof(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},\n    {TK_CONFIG_WINDOW, \"-window\", NULL, NULL,\n\tNULL, offsetof(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tComputeWindowBbox(Tk_Canvas canvas,\n\t\t\t    WindowItem *winItemPtr);\nstatic int\t\tConfigureWinItem(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tCreateWinItem(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, struct Tk_Item *itemPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteWinItem(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display);\nstatic void\t\tDisplayWinItem(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Display *display, Drawable dst,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tRotateWinItem(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScaleWinItem(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateWinItem(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double deltaX, double deltaY);\nstatic int\t\tWinItemCoords(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tWinItemLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tWinItemRequestProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tWinItemStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tWinItemToArea(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *rectPtr);\nstatic int\t\tWinItemToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic double\t\tWinItemToPoint(Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, double *pointPtr);\n#ifdef X_GetImage\nstatic int\t\txerrorhandler(void *clientData, XErrorEvent *e);\n#endif\nstatic int\t\tCanvasPsWindow(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tk_Canvas canvas, double x,\n\t\t\t    double y, int width, int height);\n\n/*\n * The structure below defines the window item type by means of functions\n * that can be invoked by generic item code.\n */\n\nTk_ItemType tkWindowType = {\n    \"window\",\t\t\t/* name */\n    sizeof(WindowItem),\t\t/* itemSize */\n    CreateWinItem,\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureWinItem,\t\t/* configureProc */\n    WinItemCoords,\t\t/* coordProc */\n    DeleteWinItem,\t\t/* deleteProc */\n    DisplayWinItem,\t\t/* displayProc */\n    TK_ALWAYS_REDRAW,\t\t/* flags */\n    WinItemToPoint,\t\t/* pointProc */\n    WinItemToArea,\t\t/* areaProc */\n    WinItemToPostscript,\t/* postscriptProc */\n    ScaleWinItem,\t\t/* scaleProc */\n    TranslateWinItem,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* cursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateWinItem,\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\n/*\n * The structure below defines the official type record for the canvas (as\n * geometry manager):\n */\n\nstatic const Tk_GeomMgr canvasGeomType = {\n    \"canvas\",\t\t\t\t/* name */\n    WinItemRequestProc,\t\t\t/* requestProc */\n    WinItemLostContentProc,\t\t/* lostContentProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateWinItem --\n *\n *\tThis function is invoked to create a new window item in a canvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new window item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateWinItem(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing window. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Initialize item's record.\n     */\n\n    winItemPtr->tkwin = NULL;\n    winItemPtr->width = 0;\n    winItemPtr->height = 0;\n    winItemPtr->anchor = TK_ANCHOR_CENTER;\n    winItemPtr->canvas = canvas;\n\n    /*\n     * Process the arguments to fill in the item record. Only 1 (list) or 2 (x\n     * y) coords are allowed.\n     */\n\n    if (objc == 1) {\n\ti = 1;\n    } else {\n\tconst char *arg = Tcl_GetString(objv[1]);\n\n\ti = 2;\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    i = 1;\n\t}\n    }\n    if (WinItemCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {\n\tgoto error;\n    }\n    if (ConfigureWinItem(interp, canvas, itemPtr, objc - i, objv + i, 0)\n\t    == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\twindow items. See the user documentation for details on what it does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nWinItemCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1, y1, x2, y2, ... */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n\n    if (objc == 0) {\n\tTcl_Obj *objs[2];\n\n\tobjs[0] = Tcl_NewDoubleObj(winItemPtr->x);\n\tobjs[1] = Tcl_NewDoubleObj(winItemPtr->y);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, objs));\n    } else if (objc < 3) {\n\tif (objc==1) {\n\t    if (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t    (Tcl_Obj ***) &objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    } else if (objc != 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"wrong # coordinates: expected 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"WINDOW\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &winItemPtr->x)\n\t\t!= TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t&winItemPtr->y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tComputeWindowBbox(canvas, winItemPtr);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 2, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\", \"WINDOW\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureWinItem --\n *\n *\tThis function is invoked to configure various aspects of a window\n *\titem, such as its anchor position.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information may be set for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureWinItem(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Window item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv.  */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    Tk_Window oldWindow;\n    Tk_Window canvasTkwin;\n\n    oldWindow = winItemPtr->tkwin;\n    canvasTkwin = Tk_CanvasTkwin(canvas);\n    if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc,\n\t    objv, winItemPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few of the options require additional processing.\n     */\n\n    if (oldWindow != winItemPtr->tkwin) {\n\tif (oldWindow != NULL) {\n\t    Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,\n\t\t    WinItemStructureProc, winItemPtr);\n\t    Tk_ManageGeometry(oldWindow, NULL, NULL);\n\t    Tk_UnmaintainGeometry(oldWindow, canvasTkwin);\n\t    Tk_UnmapWindow(oldWindow);\n\t}\n\tif (winItemPtr->tkwin != NULL) {\n\t    Tk_Window ancestor, parent;\n\n\t    /*\n\t     * Make sure that the canvas is either the parent of the window\n\t     * associated with the item or a descendant of that parent. Also,\n\t     * don't allow a top-of-hierarchy window to be managed inside a\n\t     * canvas.\n\t     */\n\n\t    parent = Tk_Parent(winItemPtr->tkwin);\n\t    for (ancestor = canvasTkwin ;; ancestor = Tk_Parent(ancestor)) {\n\t\tif (ancestor == parent) {\n\t\t    break;\n\t\t}\n\t\tif (((Tk_FakeWin *) ancestor)->flags & TK_TOP_HIERARCHY) {\n\t\t    goto badWindow;\n\t\t}\n\t    }\n\t    if (((Tk_FakeWin *) winItemPtr->tkwin)->flags & TK_TOP_HIERARCHY){\n\t\tgoto badWindow;\n\t    }\n\t    if (winItemPtr->tkwin == canvasTkwin) {\n\t\tgoto badWindow;\n\t    }\n\t    Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,\n\t\t    WinItemStructureProc, winItemPtr);\n\t    Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, winItemPtr);\n\t}\n    }\n    if ((winItemPtr->tkwin != NULL)\n\t    && (itemPtr->state == TK_STATE_HIDDEN)) {\n\tif (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {\n\t    Tk_UnmapWindow(winItemPtr->tkwin);\n\t} else {\n\t    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);\n\t}\n    }\n\n    ComputeWindowBbox(canvas, winItemPtr);\n    return TCL_OK;\n\n  badWindow:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"can't use %s in a window item of this canvas\",\n\t    Tk_PathName(winItemPtr->tkwin)));\n    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\", (char *)NULL);\n    winItemPtr->tkwin = NULL;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteWinItem --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta window item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteWinItem(\n    Tk_Canvas canvas,\t\t/* Overall info about widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    TCL_UNUSED(Display *))\t/* Display containing window for canvas. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);\n\n    if (winItemPtr->tkwin != NULL) {\n\tTk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,\n\t\tWinItemStructureProc, winItemPtr);\n\tTk_ManageGeometry(winItemPtr->tkwin, NULL, NULL);\n\tif (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {\n\t    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);\n\t}\n\tTk_UnmapWindow(winItemPtr->tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeWindowBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a window item. This function is where the\n *\tchild window's placement is computed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeWindowBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    WindowItem *winItemPtr)\t/* Item whose bbox is to be recomputed. */\n{\n    int width, height, x, y;\n    Tk_State state = winItemPtr->header.state;\n\n    x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));\n    y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {\n\t/*\n\t * There is no window for this item yet. Just give it a 1x1 bounding\n\t * box. Don't give it a 0x0 bounding box; there are strange cases\n\t * where this bounding box might be used as the dimensions of the\n\t * window, and 0x0 causes problems under X.\n\t */\n\n\twinItemPtr->header.x1 = x;\n\twinItemPtr->header.x2 = winItemPtr->header.x1 + 1;\n\twinItemPtr->header.y1 = y;\n\twinItemPtr->header.y2 = winItemPtr->header.y1 + 1;\n\treturn;\n    }\n\n    /*\n     * Compute dimensions of window.\n     */\n\n    width = winItemPtr->width;\n    if (width <= 0) {\n\twidth = Tk_ReqWidth(winItemPtr->tkwin);\n\tif (width <= 0) {\n\t    width = 1;\n\t}\n    }\n    height = winItemPtr->height;\n    if (height <= 0) {\n\theight = Tk_ReqHeight(winItemPtr->tkwin);\n\tif (height <= 0) {\n\t    height = 1;\n\t}\n    }\n\n    /*\n     * Compute location of window, using anchor information.\n     */\n\n    switch (winItemPtr->anchor) {\n    case TK_ANCHOR_N:\n\tx -= width/2;\n\tbreak;\n    case TK_ANCHOR_NE:\n\tx -= width;\n\tbreak;\n    case TK_ANCHOR_E:\n\tx -= width;\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_SE:\n\tx -= width;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_S:\n\tx -= width/2;\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_SW:\n\ty -= height;\n\tbreak;\n    case TK_ANCHOR_W:\n\ty -= height/2;\n\tbreak;\n    case TK_ANCHOR_NW:\n\tbreak;\n    default:\n\tx -= width/2;\n\ty -= height/2;\n\tbreak;\n    }\n\n    /*\n     * Store the information in the item header.\n     */\n\n    winItemPtr->header.x1 = x;\n    winItemPtr->header.y1 = y;\n    winItemPtr->header.x2 = x + width;\n    winItemPtr->header.y2 = y + height;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayWinItem --\n *\n *\tThis function is invoked to \"draw\" a window item in a given drawable.\n *\tSince the window draws itself, we needn't do any actual redisplay\n *\there. However, this function takes care of actually repositioning the\n *\tchild window so that it occupies the correct screen position.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe child window's position may get changed. Note: this function gets\n *\tcalled both when a window needs to be displayed and when it ceases to\n *\tbe visible on the screen (e.g. it was scrolled or moved off-screen or\n *\tthe enclosing canvas is unmapped).\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayWinItem(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    TCL_UNUSED(Display *),\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    TCL_UNUSED(int), /* Describes region of canvas that must be */\n    TCL_UNUSED(int), /* redisplayed (not used). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    int width, height;\n    short x, y;\n    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);\n    Tk_State state = itemPtr->state;\n\n    if (winItemPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    Tcl_Preserve(canvas);\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    /*\n     * A drawable of None is used by the canvas UnmapNotify handler\n     * to indicate that we should no longer display ourselves.\n     */\n    if (state == TK_STATE_HIDDEN || drawable == None) {\n\tif (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {\n\t    Tk_UnmapWindow(winItemPtr->tkwin);\n\t} else {\n\t    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);\n\t}\n\tTcl_Release(canvas);\n\treturn;\n    }\n    Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,\n\t    (double) winItemPtr->header.y1, &x, &y);\n    width = winItemPtr->header.x2 - winItemPtr->header.x1;\n    height = winItemPtr->header.y2 - winItemPtr->header.y1;\n\n    /*\n     * If the window is completely out of the visible area of the canvas then\n     * unmap it. This code used not to be present (why unmap the window if it\n     * isn't visible anyway?) but this could cause the window to suddenly\n     * reappear if the canvas window got resized.\n     */\n\n    if (((x + width) <= 0) || ((y + height) <= 0)\n\t    || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {\n\tif (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {\n\t    Tk_UnmapWindow(winItemPtr->tkwin);\n\t} else {\n\t    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);\n\t}\n\tTcl_Release(canvas);\n\treturn;\n    }\n\n    /*\n     * Reposition and map the window (but in different ways depending on\n     * whether the canvas is the window's parent).\n     */\n\n    if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {\n\tif ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))\n\t\t|| (width != Tk_Width(winItemPtr->tkwin))\n\t\t|| (height != Tk_Height(winItemPtr->tkwin))) {\n\t    Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);\n\t}\n\n\tif (winItemPtr->tkwin) {\n\t    Tk_MapWindow(winItemPtr->tkwin);\n\t}\n\n    } else {\n\tTk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,\n\t\twidth, height);\n    }\n    Tcl_Release(canvas);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemToPoint --\n *\n *\tComputes the distance from a given point to a given window, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the window. If the point isn't\n *\tinside the window then the return value is the distance from the point\n *\tto the window.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nWinItemToPoint(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    double x1, x2, y1, y2, xDiff, yDiff;\n\n    x1 = winItemPtr->header.x1;\n    y1 = winItemPtr->header.y1;\n    x2 = winItemPtr->header.x2;\n    y2 = winItemPtr->header.y2;\n\n    /*\n     * Point is outside window.\n     */\n\n    if (pointPtr[0] < x1) {\n\txDiff = x1 - pointPtr[0];\n    } else if (pointPtr[0] >= x2)  {\n\txDiff = pointPtr[0] + 1 - x2;\n    } else {\n\txDiff = 0;\n    }\n\n    if (pointPtr[1] < y1) {\n\tyDiff = y1 - pointPtr[1];\n    } else if (pointPtr[1] >= y2)  {\n\tyDiff = pointPtr[1] + 1 - y2;\n    } else {\n\tyDiff = 0;\n    }\n\n    return hypot(xDiff, yDiff);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangle.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nWinItemToArea(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against rectangle. */\n    double *rectPtr)\t\t/* Pointer to array of four coordinates\n\t\t\t\t * (x1,y1,x2,y2) describing rectangular\n\t\t\t\t * area.  */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n\n    if ((rectPtr[2] <= winItemPtr->header.x1)\n\t    || (rectPtr[0] >= winItemPtr->header.x2)\n\t    || (rectPtr[3] <= winItemPtr->header.y1)\n\t    || (rectPtr[1] >= winItemPtr->header.y2)) {\n\treturn -1;\n    }\n    if ((rectPtr[0] <= winItemPtr->header.x1)\n\t    && (rectPtr[1] <= winItemPtr->header.y1)\n\t    && (rectPtr[2] >= winItemPtr->header.x2)\n\t    && (rectPtr[3] >= winItemPtr->header.y2)) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * xerrorhandler --\n *\n *\tThis is a dummy function to catch X11 errors during an attempt to\n *\tprint a canvas window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\n#ifdef X_GetImage\nstatic int\nxerrorhandler(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(XErrorEvent *))\n{\n    return 0;\n}\n#endif /* X_GetImage */\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemToPostscript --\n *\n *\tThis function is called to generate Postscript for window items.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in interp->result,\n *\treplacing whatever used to be there. If no error occurs, then\n *\tPostscript for the item is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nWinItemToPostscript(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    int prepass)\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n    double x, y;\n    int width, height;\n    Tk_Window tkwin = winItemPtr->tkwin;\n\n    if (prepass || winItemPtr->tkwin == NULL) {\n\treturn TCL_OK;\n    }\n\n    width = Tk_Width(tkwin);\n    height = Tk_Height(tkwin);\n\n    /*\n     * Compute the coordinates of the lower-left corner of the window, taking\n     * into account the anchor position for the window.\n     */\n\n    x = winItemPtr->x;\n    y = Tk_CanvasPsY(canvas, winItemPtr->y);\n\n    switch (winItemPtr->anchor) {\n    case TK_ANCHOR_NW:\t\t\t    y -= height;\t    break;\n    case TK_ANCHOR_N:\t    x -= width/2.0; y -= height;\t    break;\n    case TK_ANCHOR_NE:\t    x -= width;\t    y -= height;\t    break;\n    case TK_ANCHOR_E:\t    x -= width;\t    y -= height/2.0;\t    break;\n    case TK_ANCHOR_SE:\t    x -= width;\t\t\t\t    break;\n    case TK_ANCHOR_S:\t    x -= width/2.0;\t\t\t    break;\n    case TK_ANCHOR_SW:\t\t\t\t\t\t    break;\n    case TK_ANCHOR_W:\t\t\t    y -= height/2.0;\t    break;\n    default:  x -= width/2.0; y -= height/2.0;\t    break;\n    }\n\n    return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);\n}\n\f\nstatic int\nCanvasPsWindow(\n    Tcl_Interp *interp,\t\t/* Leave Postscript or error message here. */\n    Tk_Window tkwin,\t\t/* window to be printed */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    double x, double y,\t\t/* origin of window. */\n    int width, int height)\t/* width/height of window. */\n{\n    XImage *ximage;\n    int result;\n#ifdef X_GetImage\n    Tk_ErrorHandler handle;\n#endif\n    Tcl_Obj *cmdObj, *psObj;\n    Tcl_InterpState interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Locate the subwindow within the wider window.\n     */\n\n    psObj = Tcl_ObjPrintf(\n\t    \"\\n%%%% %s item (%s, %d x %d)\\n\"\t/* Comment */\n\t    \"%.15g %.15g translate\\n\",\t\t/* Position */\n\t    Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);\n\n    /*\n     * First try if the widget has its own \"postscript\" command. If it exists,\n     * this will produce much better postscript than when a pixmap is used.\n     */\n\n    Tcl_ResetResult(interp);\n    cmdObj = Tcl_ObjPrintf(\"%s postscript -prolog 0\", Tk_PathName(tkwin));\n    Tcl_IncrRefCount(cmdObj);\n    result = Tcl_EvalObjEx(interp, cmdObj, 0);\n    Tcl_DecrRefCount(cmdObj);\n\n    if (result == TCL_OK) {\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"50 dict begin\\nsave\\ngsave\\n\"\n\t\t\"0 %d moveto %d 0 rlineto 0 -%d rlineto -%d 0 rlineto closepath\\n\"\n\t\t\"1.000 1.000 1.000 setrgbcolor AdjustColor\\nfill\\ngrestore\\n\",\n\t\theight, width, height, width);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\tTcl_AppendToObj(psObj, \"\\nrestore\\nend\\n\\n\\n\", TCL_INDEX_NONE);\n\tgoto done;\n    }\n\n    /*\n     * If the window is off the screen it will generate a BadMatch/XError. We\n     * catch any BadMatch errors here\n     */\n\n#ifdef X_GetImage\n    handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,\n\t    X_GetImage, -1, xerrorhandler, tkwin);\n#endif\n\n    /*\n     * Generate an XImage from the window. We can then read pixel values out\n     * of the XImage.\n     */\n\n    ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,\n\t    (unsigned) width, (unsigned) height, AllPlanes, ZPixmap);\n\n#ifdef X_GetImage\n    Tk_DeleteErrorHandler(handle);\n#endif\n\n    if (ximage == NULL) {\n\tresult = TCL_OK;\n    } else {\n\tTcl_ResetResult(interp);\n\tresult = TkPostscriptImage(interp, tkwin, Canvas(canvas)->psInfo,\n\t\tximage, 0, 0, width, height);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\tXDestroyImage(ximage);\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n  done:\n    if (result == TCL_OK) {\n\t(void) Tcl_RestoreInterpState(interp, interpState);\n\tTcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    } else {\n\tTcl_DiscardInterpState(interpState);\n    }\n    Tcl_DecrRefCount(psObj);\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateWinItem --\n *\n *\tThis function is called to rotate a window item by a given amount\n *\tabout a point. Note that this does *not* rotate the window of the\n *\titem.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the window anchor is rotated by angleRad about (originX,\n *\toriginY), and the bounding box is updated in the generic part of the\n *\titem structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateWinItem(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being rotated. */\n    double originX, double originY,\n    double angleRad)\t\t/* Amount by which item is to be rotated. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &winItemPtr->x, &winItemPtr->y);\n    ComputeWindowBbox(canvas, winItemPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleWinItem --\n *\n *\tThis function is invoked to rescale a window item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window referred to by itemPtr is rescaled so that the following\n *\ttransformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleWinItem(\n    Tk_Canvas canvas,\t\t/* Canvas containing window. */\n    Tk_Item *itemPtr,\t\t/* Window to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale window. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n\n    winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);\n    winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);\n    if (winItemPtr->width > 0) {\n\twinItemPtr->width = (int) (scaleX*winItemPtr->width);\n    }\n    if (winItemPtr->height > 0) {\n\twinItemPtr->height = (int) (scaleY*winItemPtr->height);\n    }\n    ComputeWindowBbox(canvas, winItemPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateWinItem --\n *\n *\tThis function is called to move a window by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the window is offset by (xDelta, yDelta), and the\n *\tbounding box is updated in the generic part of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateWinItem(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    WindowItem *winItemPtr = (WindowItem *) itemPtr;\n\n    winItemPtr->x += deltaX;\n    winItemPtr->y += deltaY;\n    ComputeWindowBbox(canvas, winItemPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemStructureProc --\n *\n *\tThis function is invoked whenever StructureNotify events occur for a\n *\twindow that's managed as part of a canvas window item. This function's\n *\tonly purpose is to clean up when windows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is disassociated from the window item when it is deleted.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nWinItemStructureProc(\n    void *clientData,\t/* Pointer to record describing window item. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    WindowItem *winItemPtr = (WindowItem *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\twinItemPtr->tkwin = NULL;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemRequestProc --\n *\n *\tThis function is invoked whenever a window that's associated with a\n *\twindow canvas item changes its requested dimensions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size and location on the screen of the window may change,\n *\tdepending on the options specified for the window item.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nWinItemRequestProc(\n    void *clientData,\t/* Pointer to record for window item. */\n    TCL_UNUSED(Tk_Window))\t\t/* Window that changed its desired size. */\n{\n    WindowItem *winItemPtr = (WindowItem *)clientData;\n\n    ComputeWindowBbox(winItemPtr->canvas, winItemPtr);\n\n    /*\n     * A drawable argument of None to DisplayWinItem is used by the canvas\n     * UnmapNotify handler to indicate that we should no longer display\n     * ourselves, so need to pass a (bogus) non-zero drawable value here.\n     */\n    DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr, NULL,\n\t    (Drawable) -1, 0, 0, 0, 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * WinItemLostContentProc --\n *\n *\tThis function is invoked by Tk whenever some other geometry claims\n *\tcontrol over a content window that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all canvas-related information about the content window.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nWinItemLostContentProc(\n    void *clientData,\t/* WindowItem structure for content window window that\n\t\t\t\t * was stolen away. */\n    TCL_UNUSED(Tk_Window))\t\t/* Tk's handle for the content window. */\n{\n    WindowItem *winItemPtr = (WindowItem *)clientData;\n    Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);\n\n    Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,\n\t    WinItemStructureProc, winItemPtr);\n    if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {\n\tTk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);\n    }\n    Tk_UnmapWindow(winItemPtr->tkwin);\n    winItemPtr->tkwin = NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvas.c",
    "content": "/*\n * tkCanvas.c --\n *\n *\tThis module implements canvas widgets for the Tk toolkit. A canvas\n *\tdisplays a background and a collection of graphical objects such as\n *\trectangles, lines, and texts.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n#include \"tkPort.h\"\n#ifdef MAC_OSX_TK\n#include \"tkMacOSXInt.h\"\n#endif\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * See tkCanvas.h for key data structures used to implement canvases.\n */\n\n/*\n * The structure defined below is used to keep track of a tag search in\n * progress. No field should be accessed by anyone other than TagSearchScan,\n * TagSearchFirst, TagSearchNext, TagSearchScanExpr, TagSearchEvalExpr,\n * TagSearchExprInit, TagSearchExprDestroy, TagSearchDestroy.\n * (\n *   Not quite accurate: the TagSearch structure is also accessed from:\n *    CanvasWidgetCmd, FindItems, RelinkItems\n *   The only instances of the structure are owned by:\n *    CanvasWidgetCmd\n *   CanvasWidgetCmd is the only function that calls:\n *    FindItems, RelinkItems\n *   CanvasWidgetCmd, FindItems, RelinkItems, are the only functions that call\n *    TagSearch*\n * )\n */\n\ntypedef struct TagSearch {\n    TkCanvas *canvasPtr;\t/* Canvas widget being searched. */\n    Tk_Item *currentPtr;\t/* Pointer to last item returned. */\n    Tk_Item *lastPtr;\t\t/* The item right before the currentPtr is\n\t\t\t\t * tracked so if the currentPtr is deleted we\n\t\t\t\t * don't have to start from the beginning. */\n    int searchOver;\t\t/* Non-zero means NextItem should always\n\t\t\t\t * return NULL. */\n    int type;\t\t\t/* Search type (see #defs below) */\n    Tcl_Size id;\t\t\t/* Item id for searches by id */\n    const char *string;\t\t/* Tag expression string */\n    Tcl_Size stringIndex;\t\t/* Current position in string scan */\n    Tcl_Size stringLength;\t\t/* Length of tag expression string */\n    char *rewritebuffer;\t/* Tag string (after removing escapes) */\n    size_t rewritebufferAllocated;\n\t\t\t\t/* Available space for rewrites. */\n    TagSearchExpr *expr;\t/* Compiled tag expression. */\n} TagSearch;\n\n/*\n * Values for the TagSearch type field.\n */\n\n#define SEARCH_TYPE_EMPTY\t0\t/* Looking for empty tag */\n#define SEARCH_TYPE_ID\t\t1\t/* Looking for an item by id */\n#define SEARCH_TYPE_ALL\t\t2\t/* Looking for all items */\n#define SEARCH_TYPE_TAG\t\t3\t/* Looking for an item by simple tag */\n#define SEARCH_TYPE_EXPR\t4\t/* Compound search */\n\n/*\n * Custom option for handling \"-state\" and \"-offset\"\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc,\n    NULL\t\t/* Only \"normal\" and \"disabled\". */\n};\n\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)\n};\n\n/*\n * Information used for argv parsing.\n */\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_CANVAS_BG_COLOR, offsetof(TkCanvas, bgBorder),\n\tTK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_CANVAS_BG_MONO, offsetof(TkCanvas, bgBorder),\n\tTK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_SYNONYM, \"-bd\", \"borderWidth\", NULL, NULL, 0, 0, NULL},\n    {TK_CONFIG_SYNONYM, \"-bg\", \"background\", NULL, NULL, 0, 0, NULL},\n    {TK_CONFIG_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_CANVAS_BORDER_WIDTH, offsetof(TkCanvas, borderWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_DOUBLE, \"-closeenough\", \"closeEnough\", \"CloseEnough\",\n\tDEF_CANVAS_CLOSE_ENOUGH, offsetof(TkCanvas, closeEnough), 0, NULL},\n    {TK_CONFIG_BOOLEAN, \"-confine\", \"confine\", \"Confine\",\n\tDEF_CANVAS_CONFINE, offsetof(TkCanvas, confine), 0, NULL},\n    {TK_CONFIG_ACTIVE_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_CANVAS_CURSOR, offsetof(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_PIXELS, \"-height\", \"height\", \"Height\",\n\tDEF_CANVAS_HEIGHT, offsetof(TkCanvas, heightObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_CANVAS_HIGHLIGHT_BG,\n\toffsetof(TkCanvas, highlightBgColorPtr), 0, NULL},\n    {TK_CONFIG_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_CANVAS_HIGHLIGHT, offsetof(TkCanvas, highlightColorPtr), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\",\n\tDEF_CANVAS_HIGHLIGHT_WIDTH, offsetof(TkCanvas, highlightWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_BORDER, \"-insertbackground\", \"insertBackground\", \"Foreground\",\n\tDEF_CANVAS_INSERT_BG, offsetof(TkCanvas, textInfo.insertBorder), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-insertborderwidth\", \"insertBorderWidth\", \"BorderWidth\",\n\tDEF_CANVAS_INSERT_BD_COLOR, offsetof(TkCanvas, textInfo.insertBorderWidthObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_PIXELS, \"-insertborderwidth\", \"insertBorderWidth\", \"BorderWidth\",\n\tDEF_CANVAS_INSERT_BD_MONO, offsetof(TkCanvas, textInfo.insertBorderWidthObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_INT, \"-insertofftime\", \"insertOffTime\", \"OffTime\",\n\tDEF_CANVAS_INSERT_OFF_TIME, offsetof(TkCanvas, insertOffTime), 0, NULL},\n    {TK_CONFIG_INT, \"-insertontime\", \"insertOnTime\", \"OnTime\",\n\tDEF_CANVAS_INSERT_ON_TIME, offsetof(TkCanvas, insertOnTime), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-insertwidth\", \"insertWidth\", \"InsertWidth\",\n\tDEF_CANVAS_INSERT_WIDTH, offsetof(TkCanvas, textInfo.insertWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", \"offset\", \"Offset\", \"0,0\",\n\toffsetof(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT,\n\t&offsetOption},\n    {TK_CONFIG_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_CANVAS_RELIEF, offsetof(TkCanvas, relief), 0, NULL},\n    {TK_CONFIG_STRING, \"-scrollregion\", \"scrollRegion\", \"ScrollRegion\",\n\tDEF_CANVAS_SCROLL_REGION, offsetof(TkCanvas, regionObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\tDEF_CANVAS_SELECT_COLOR, offsetof(TkCanvas, textInfo.selBorder),\n\tTK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\tDEF_CANVAS_SELECT_MONO, offsetof(TkCanvas, textInfo.selBorder),\n\tTK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\", \"BorderWidth\",\n\tDEF_CANVAS_SELECT_BD_COLOR, offsetof(TkCanvas, textInfo.selBorderWidthObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\", \"BorderWidth\",\n\tDEF_CANVAS_SELECT_BD_MONO, offsetof(TkCanvas, textInfo.selBorderWidthObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\tDEF_CANVAS_SELECT_FG_COLOR, offsetof(TkCanvas, textInfo.selFgColorPtr),\n\tTK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\tDEF_CANVAS_SELECT_FG_MONO, offsetof(TkCanvas, textInfo.selFgColorPtr),\n\tTK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", \"state\", \"State\",\n\t\"normal\", offsetof(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT,\n\t&stateOption},\n    {TK_CONFIG_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_CANVAS_TAKE_FOCUS, offsetof(TkCanvas, takeFocusObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_PIXELS, \"-width\", \"width\", \"Width\",\n\tDEF_CANVAS_WIDTH, offsetof(TkCanvas, widthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tDEF_CANVAS_X_SCROLL_CMD, offsetof(TkCanvas, xScrollCmdObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_PIXELS, \"-xscrollincrement\", \"xScrollIncrement\",\n\t\"ScrollIncrement\",\n\tDEF_CANVAS_X_SCROLL_INCREMENT, offsetof(TkCanvas, xScrollIncrementObj),\n\tTK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-yscrollcommand\", \"yScrollCommand\", \"ScrollCommand\",\n\tDEF_CANVAS_Y_SCROLL_CMD, offsetof(TkCanvas, yScrollCmdObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_PIXELS, \"-yscrollincrement\", \"yScrollIncrement\",\n\t\"ScrollIncrement\",\n\tDEF_CANVAS_Y_SCROLL_INCREMENT, offsetof(TkCanvas, yScrollIncrementObj),\n\tTK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * List of all the item types known at present. This is *global* and is\n * protected by typeListMutex.\n */\n\nstatic Tk_ItemType *typeList = NULL;\n\t\t\t\t/* NULL means initialization hasn't been done\n\t\t\t\t * yet. */\nTCL_DECLARE_MUTEX(typeListMutex)\n\n/*\n * Uids for operands in compiled advanced tag search expressions.\n * Initialization is done by GetStaticUids()\n */\n\ntypedef struct {\n    Tk_Uid allUid;\n    Tk_Uid currentUid;\n    Tk_Uid andUid;\n    Tk_Uid orUid;\n    Tk_Uid xorUid;\n    Tk_Uid parenUid;\n    Tk_Uid negparenUid;\n    Tk_Uid endparenUid;\n    Tk_Uid tagvalUid;\n    Tk_Uid negtagvalUid;\n} SearchUids;\n\nstatic Tcl_ThreadDataKey dataKey;\nstatic SearchUids *\tGetStaticUids(void);\n\n/*\n * Prototypes for functions defined later in this file:\n */\n\nstatic void\t\tCanvasBindProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tCanvasBlinkProc(void *clientData);\nstatic void\t\tCanvasCmdDeletedProc(void *clientData);\nstatic void\t\tCanvasDoEvent(TkCanvas *canvasPtr, XEvent *eventPtr);\nstatic void\t\tCanvasEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_Size\tCanvasFetchSelection(void *clientData, Tcl_Size offset,\n\t\t\t    char *buffer, Tcl_Size maxBytes);\nstatic Tk_Item *\tCanvasFindClosest(TkCanvas *canvasPtr,\n\t\t\t    double coords[2]);\nstatic void\t\tCanvasFocusProc(TkCanvas *canvasPtr, int gotFocus);\nstatic void\t\tCanvasLostSelection(void *clientData);\nstatic void\t\tCanvasSelectTo(TkCanvas *canvasPtr,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size index);\nstatic void\t\tCanvasSetOrigin(TkCanvas *canvasPtr,\n\t\t\t    int xOrigin, int yOrigin);\nstatic void\t\tCanvasUpdateScrollbars(TkCanvas *canvasPtr);\nstatic int\t\tCanvasWidgetCmd(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const *objv);\nstatic void\t\tCanvasWorldChanged(void *instanceData);\nstatic int\t\tConfigureCanvas(Tcl_Interp *interp,\n\t\t\t    TkCanvas *canvasPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const *objv, int flags);\nstatic void\t\tDefaultRotateImplementation(TkCanvas *canvasPtr,\n\t\t\t    Tk_Item *itemPtr, double x, double y,\n\t\t\t    double angleRadians);\nstatic Tcl_FreeProc\tDestroyCanvas;\nstatic int\t\tDrawCanvas(Tcl_Interp *interp, void *clientData, Tk_PhotoHandle photohandle, int subsample, int zoom);\nstatic void\t\tDisplayCanvas(void *clientData);\nstatic void\t\tDoItem(Tcl_Obj *accumObj,\n\t\t\t    Tk_Item *itemPtr, Tk_Uid tag);\nstatic void\t\tEventuallyRedrawItem(TkCanvas *canvasPtr,\n\t\t\t    Tk_Item *itemPtr);\nstatic int\t\tFindItems(Tcl_Interp *interp, TkCanvas *canvasPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv,\n\t\t\t    Tcl_Obj *newTagObj, Tcl_Size first,\n\t\t\t    TagSearch **searchPtrPtr);\nstatic int\t\tFindArea(Tcl_Interp *interp, TkCanvas *canvasPtr,\n\t\t\t    Tcl_Obj *const *objv, Tk_Uid uid, int enclosed);\nstatic double\t\tGridAlign(double coord, double spacing);\nstatic void\t\tInitCanvas(void);\nstatic void\t\tPickCurrentItem(TkCanvas *canvasPtr, XEvent *eventPtr);\nstatic Tcl_Obj *\tScrollFractions(int screen1,\n\t\t\t    int screen2, int object1, int object2);\nstatic int\t\tRelinkItems(TkCanvas *canvasPtr, Tcl_Obj *tag,\n\t\t\t    Tk_Item *prevPtr, TagSearch **searchPtrPtr);\nstatic void\t\tTagSearchExprInit(TagSearchExpr **exprPtrPtr);\nstatic void\t\tTagSearchExprDestroy(TagSearchExpr *expr);\nstatic void\t\tTagSearchDestroy(TagSearch *searchPtr);\nstatic int\t\tTagSearchScan(TkCanvas *canvasPtr,\n\t\t\t    Tcl_Obj *tag, TagSearch **searchPtrPtr);\nstatic int\t\tTagSearchScanExpr(Tcl_Interp *interp,\n\t\t\t    TagSearch *searchPtr, TagSearchExpr *expr);\nstatic int\t\tTagSearchEvalExpr(TagSearchExpr *expr,\n\t\t\t    Tk_Item *itemPtr);\nstatic Tk_Item *\tTagSearchFirst(TagSearch *searchPtr);\nstatic Tk_Item *\tTagSearchNext(TagSearch *searchPtr);\n\n/*\n * The structure below defines canvas class behavior by means of functions\n * that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs canvasClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    CanvasWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t\t\t/* createProc */\n    NULL\t\t\t\t\t/* modalProc */\n};\n\n/*\n * Macros that significantly simplify all code that finds items.\n */\n\n#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \\\n    if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \\\n\terrorExitClause; \\\n    } \\\n    itemPtr = TagSearchFirst(*(searchPtrPtr));\n#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \\\n    if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \\\n\terrorExitClause; \\\n    } \\\n    for (itemPtr = TagSearchFirst(*(searchPtrPtr)); \\\n\t    itemPtr != NULL; itemPtr = TagSearchNext(*(searchPtrPtr)))\n#define FIND_ITEMS(objPtr, n) \\\n    FindItems(interp, canvasPtr, objc, objv, (objPtr), (n), &searchPtr)\n#define RELINK_ITEMS(objPtr, itemPtr) \\\n    result = RelinkItems(canvasPtr, (objPtr), (itemPtr), &searchPtr)\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * AlwaysRedraw, ItemConfigure, ItemCoords, etc. --\n *\n *\tHelper functions that make access to canvas item functions simpler.\n *\tNote that these are all inline functions.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic inline int\nAlwaysRedraw(\n    Tk_Item *itemPtr)\n{\n    return itemPtr->typePtr->flags & TK_ALWAYS_REDRAW;\n}\n\nstatic inline int\nItemConfigure(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tcl_Interp *interp = canvasPtr->interp;\n\n    return itemPtr->typePtr->configProc(interp, (Tk_Canvas) canvasPtr,\n\t    itemPtr, objc, objv, TK_CONFIG_ARGV_ONLY);\n}\n\nstatic inline int\nItemConfigInfo(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Obj *fieldName)\n{\n    return Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,\n\t    itemPtr->typePtr->configSpecs, itemPtr,\n\t    (fieldName ? Tcl_GetString(fieldName) : NULL), 0);\n}\n\nstatic inline int\nItemConfigValue(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Obj *fieldName)\n{\n    return Tk_ConfigureValue(canvasPtr->interp, canvasPtr->tkwin,\n\t    itemPtr->typePtr->configSpecs, itemPtr,\n\t    Tcl_GetString(fieldName), 0);\n}\n\nstatic inline int\nItemCoords(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tcl_Interp *interp = canvasPtr->interp;\n    int result;\n\n    if (itemPtr->typePtr->coordProc == NULL) {\n\tresult = TCL_OK;\n    } else {\n\tresult = itemPtr->typePtr->coordProc(interp, (Tk_Canvas) canvasPtr,\n\t\titemPtr, objc, objv);\n    }\n    return result;\n}\n\nstatic inline int\nItemCreate(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\t\t/* Warning: incomplete! typePtr field must be\n\t\t\t\t * set by this point. */\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tcl_Interp *interp = canvasPtr->interp;\n\n\treturn itemPtr->typePtr->createProc(interp, (Tk_Canvas) canvasPtr,\n\t\titemPtr, objc-3, objv+3);\n}\n\nstatic inline void\nItemCursor(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size index)\n{\n    itemPtr->typePtr->icursorProc((Tk_Canvas) canvasPtr, itemPtr, index);\n}\n\nstatic inline void\nItemDelChars(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size first,\n    Tcl_Size last)\n{\n    itemPtr->typePtr->dCharsProc((Tk_Canvas) canvasPtr, itemPtr, first, last);\n}\n\nstatic inline void\nItemDelete(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr)\n{\n    itemPtr->typePtr->deleteProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    canvasPtr->display);\n}\n\nstatic inline void\nItemDisplay(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Pixmap pixmap,\n    int screenX1, int screenY1,\n    int width, int height)\n{\n    itemPtr->typePtr->displayProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    canvasPtr->display, pixmap, screenX1, screenY1, width, height);\n}\n\nstatic int\nItemIndex(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Obj *objPtr,\n    Tcl_Size *indexPtr)\n{\n    Tcl_Interp *interp = canvasPtr->interp;\n\n    if (itemPtr->typePtr->indexProc == NULL) {\n\treturn TCL_OK;\n    }\n    return itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,\n\t    itemPtr, objPtr, indexPtr);\n}\n\nstatic inline void\nItemInsert(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size beforeThis,\n    Tcl_Obj *toInsert)\n{\n    itemPtr->typePtr->insertProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    beforeThis, toInsert);\n}\n\nstatic inline int\nItemOverlap(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double rect[])\n{\n    return itemPtr->typePtr->areaProc((Tk_Canvas) canvasPtr, itemPtr, rect);\n}\n\nstatic inline double\nItemPoint(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double coords[],\n    double halo)\n{\n    double dist;\n\n    dist = itemPtr->typePtr->pointProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    coords) - halo;\n    return (dist < 0.0) ? 0.0 : dist;\n}\n\nstatic inline void\nItemScale(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double xOrigin, double yOrigin,\n    double xScale, double yScale)\n{\n    itemPtr->typePtr->scaleProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    xOrigin, yOrigin, xScale, yScale);\n}\n\nstatic inline Tcl_Size\nItemSelection(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    Tcl_Size offset,\n    char *buffer,\n    Tcl_Size maxBytes)\n{\n    if (itemPtr == NULL || itemPtr->typePtr->selectionProc == NULL) {\n\treturn TCL_INDEX_NONE;\n    }\n\n    return itemPtr->typePtr->selectionProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    offset, buffer, maxBytes);\n}\n\nstatic inline void\nItemTranslate(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double xDelta,\n    double yDelta)\n{\n    itemPtr->typePtr->translateProc((Tk_Canvas) canvasPtr, itemPtr,\n\t    xDelta, yDelta);\n}\n\nstatic inline void\nItemRotate(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double x,\n    double y,\n    double angleRadians)\n{\n    if (itemPtr->typePtr->rotateProc != NULL) {\n\titemPtr->typePtr->rotateProc((Tk_Canvas) canvasPtr,\n\t\titemPtr, x, y, angleRadians);\n    } else {\n\tDefaultRotateImplementation(canvasPtr, itemPtr, x, y, angleRadians);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DefaultRotateImplementation --\n *\n *\tThe default implementation of the rotation operation, used when items\n *\tdo not provide their own version.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDefaultRotateImplementation(\n    TkCanvas *canvasPtr,\n    Tk_Item *itemPtr,\n    double x,\n    double y,\n    double angleRadians)\n{\n    Tcl_Size i, objc;\n    int ok = 1;\n    Tcl_Obj **objv, **newObjv;\n    double *coordv;\n    double s = sin(angleRadians);\n    double c = cos(angleRadians);\n    Tcl_Interp *interp = canvasPtr->interp;\n\n    /*\n     * Get the coordinates out of the item.\n     */\n\n    if (ItemCoords(canvasPtr, itemPtr, 0, NULL) == TCL_OK &&\n\t    Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp),\n\t\t    &objc, &objv) == TCL_OK) {\n\tcoordv = (double *)Tcl_Alloc(sizeof(double) * objc);\n\tfor (i=0 ; i<objc ; i++) {\n\t    if (Tcl_GetDoubleFromObj(NULL, objv[i], &coordv[i]) != TCL_OK) {\n\t\tok = 0;\n\t\tbreak;\n\t    }\n\t}\n\tif (ok) {\n\t    /*\n\t     * Apply the rotation.\n\t     */\n\n\t    for (i=0 ; i<objc ; i+=2) {\n\t\tdouble px = coordv[i+0] - x;\n\t\tdouble py = coordv[i+1] - y;\n\t\tdouble nx = px * c - py * s;\n\t\tdouble ny = px * s + py * c;\n\n\t\tcoordv[i+0] = nx + x;\n\t\tcoordv[i+1] = ny + y;\n\t    }\n\n\t    /*\n\t     * Write the coordinates back into the item.\n\t     */\n\n\t    newObjv = (Tcl_Obj **) Tcl_Alloc(sizeof(Tcl_Obj *) * objc);\n\t    for (i=0 ; i<objc ; i++) {\n\t\tnewObjv[i] = Tcl_NewDoubleObj(coordv[i]);\n\t\tTcl_IncrRefCount(newObjv[i]);\n\t    }\n\t    ItemCoords(canvasPtr, itemPtr, objc, newObjv);\n\t    for (i=0 ; i<objc ; i++) {\n\t\tTcl_DecrRefCount(newObjv[i]);\n\t    }\n\t    Tcl_Free(newObjv);\n\t}\n\tTcl_Free(coordv);\n    }\n\n    /*\n     * The interpreter result was (probably) modified above; reset it.\n     */\n\n    Tcl_ResetResult(interp);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasObjCmd --\n *\n *\tThis function is invoked to process the \"canvas\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkCanvas *canvasPtr;\n    Tk_Window newWin;\n\n    if (typeList == NULL) {\n\tInitCanvas();\n    }\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    newWin = Tk_CreateWindowFromPath(interp,tkwin,Tcl_GetString(objv[1]),NULL);\n    if (newWin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Initialize fields that won't be initialized by ConfigureCanvas, or\n     * which ConfigureCanvas expects to have reasonable values (e.g. resource\n     * pointers).\n     */\n\n    canvasPtr = (TkCanvas *)Tcl_Alloc(sizeof(TkCanvas));\n    canvasPtr->tkwin = newWin;\n    canvasPtr->display = Tk_Display(newWin);\n    canvasPtr->interp = interp;\n    canvasPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd, canvasPtr,\n\t    CanvasCmdDeletedProc);\n    canvasPtr->firstItemPtr = NULL;\n    canvasPtr->lastItemPtr = NULL;\n    canvasPtr->borderWidthObj = NULL;\n    canvasPtr->bgBorder = NULL;\n    canvasPtr->relief = TK_RELIEF_FLAT;\n    canvasPtr->highlightWidthObj = NULL;\n    canvasPtr->highlightBgColorPtr = NULL;\n    canvasPtr->highlightColorPtr = NULL;\n    canvasPtr->inset = 0;\n    canvasPtr->pixmapGC = NULL;\n    canvasPtr->widthObj = NULL;\n    canvasPtr->heightObj = NULL;\n    canvasPtr->confine = 0;\n    canvasPtr->textInfo.selBorder = NULL;\n    canvasPtr->textInfo.selBorderWidth = 0;\n    canvasPtr->textInfo.selBorderWidthObj = NULL;\n    canvasPtr->textInfo.selFgColorPtr = NULL;\n    canvasPtr->textInfo.selItemPtr = NULL;\n    canvasPtr->textInfo.selectFirst = TCL_INDEX_NONE;\n    canvasPtr->textInfo.selectLast = TCL_INDEX_NONE;\n    canvasPtr->textInfo.anchorItemPtr = NULL;\n    canvasPtr->textInfo.selectAnchor = 0;\n    canvasPtr->textInfo.insertBorder = NULL;\n    canvasPtr->textInfo.insertWidth = 0;\n    canvasPtr->textInfo.insertWidthObj = NULL;\n    canvasPtr->textInfo.insertBorderWidth = 0;\n    canvasPtr->textInfo.insertBorderWidthObj = NULL;\n    canvasPtr->textInfo.focusItemPtr = NULL;\n    canvasPtr->textInfo.gotFocus = 0;\n    canvasPtr->textInfo.cursorOn = 0;\n    canvasPtr->insertOnTime = 0;\n    canvasPtr->insertOffTime = 0;\n    canvasPtr->insertBlinkHandler = NULL;\n    canvasPtr->xOrigin = canvasPtr->yOrigin = 0;\n    canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0;\n    canvasPtr->bindingTable = NULL;\n    canvasPtr->currentItemPtr = NULL;\n    canvasPtr->newCurrentPtr = NULL;\n    canvasPtr->closeEnough = 0.0;\n    canvasPtr->pickEvent.type = LeaveNotify;\n    canvasPtr->pickEvent.xcrossing.x = 0;\n    canvasPtr->pickEvent.xcrossing.y = 0;\n    canvasPtr->state = 0;\n    canvasPtr->xScrollCmdObj = NULL;\n    canvasPtr->yScrollCmdObj = NULL;\n    canvasPtr->scrollX1 = 0;\n    canvasPtr->scrollY1 = 0;\n    canvasPtr->scrollX2 = 0;\n    canvasPtr->scrollY2 = 0;\n    canvasPtr->regionObj = NULL;\n    canvasPtr->xScrollIncrementObj = NULL;\n    canvasPtr->yScrollIncrementObj = NULL;\n    canvasPtr->scanX = 0;\n    canvasPtr->scanXOrigin = 0;\n    canvasPtr->scanY = 0;\n    canvasPtr->scanYOrigin = 0;\n    canvasPtr->hotPtr = NULL;\n    canvasPtr->hotPrevPtr = NULL;\n    canvasPtr->cursor = NULL;\n    canvasPtr->takeFocusObj = NULL;\n    canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(newWin));\n    canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(newWin));\n    canvasPtr->flags = 0;\n    canvasPtr->nextId = 1;\n    canvasPtr->psInfo = NULL;\n    canvasPtr->canvas_state = TK_STATE_NORMAL;\n    canvasPtr->tsoffset.flags = 0;\n    canvasPtr->tsoffset.xoffset = 0;\n    canvasPtr->tsoffset.yoffset = 0;\n    canvasPtr->bindTagExprs = NULL;\n    Tcl_InitHashTable(&canvasPtr->idTable, TCL_ONE_WORD_KEYS);\n\n    Tk_SetClass(canvasPtr->tkwin, \"Canvas\");\n    Tk_SetClassProcs(canvasPtr->tkwin, &canvasClass, canvasPtr);\n    Tk_CreateEventHandler(canvasPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    CanvasEventProc, canvasPtr);\n    Tk_CreateEventHandler(canvasPtr->tkwin, KeyPressMask|KeyReleaseMask\n\t    |ButtonPressMask|ButtonReleaseMask|EnterWindowMask\n\t    |LeaveWindowMask|PointerMotionMask|VirtualEventMask,\n\t    CanvasBindProc, canvasPtr);\n    Tk_CreateSelHandler(canvasPtr->tkwin, XA_PRIMARY, XA_STRING,\n\t    CanvasFetchSelection, canvasPtr, XA_STRING);\n    if (ConfigureCanvas(interp, canvasPtr, objc-2, objv+2, 0) != TCL_OK) {\n\tgoto error;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(canvasPtr->tkwin));\n    return TCL_OK;\n\n  error:\n    Tk_DestroyWindow(canvasPtr->tkwin);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasWidgetCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCanvasWidgetCmd(\n    void *clientData,\t/* Information about canvas widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n    int c, result;\n    Tk_Item *itemPtr = NULL;\t/* Initialization needed only to prevent\n\t\t\t\t * compiler warning. */\n    TagSearch *searchPtr = NULL;/* Allocated by first TagSearchScan, freed by\n\t\t\t\t * TagSearchDestroy */\n\n    int idx;\n    static const char *const canvasOptionStrings[] = {\n\t\"addtag\",\t\"bbox\",\t\t\"bind\",\t\t\"canvasx\",\n\t\"canvasy\",\t\"cget\",\t\t\"configure\",\t\"coords\",\n\t\"create\",\t\"dchars\",\t\"delete\",\t\"dtag\",\n\t\"find\",\t\t\"focus\",\t\"gettags\",\t\"icursor\",\n\t\"image\",\t\"imove\",\t\"index\",\t\"insert\",\n\t\"itemcget\",\t\"itemconfigure\",\n\t\"lower\",\t\"move\",\t\t\"moveto\",\t\"postscript\",\n\t\"raise\",\t\"rchars\",\t\"rotate\",\t\"scale\",\n\t\"scan\",\t\t\"select\",\t\"type\",\t\t\"xview\",\n\t\"yview\",\tNULL\n    };\n    enum canvasOptionStringsEnum {\n\tCANV_ADDTAG,\tCANV_BBOX,\tCANV_BIND,\tCANV_CANVASX,\n\tCANV_CANVASY,\tCANV_CGET,\tCANV_CONFIGURE,\tCANV_COORDS,\n\tCANV_CREATE,\tCANV_DCHARS,\tCANV_DELETE,\tCANV_DTAG,\n\tCANV_FIND,\tCANV_FOCUS,\tCANV_GETTAGS,\tCANV_ICURSOR,\n\tCANV_IMAGE,\tCANV_IMOVE,\tCANV_INDEX,\tCANV_INSERT,\n\tCANV_ITEMCGET,\tCANV_ITEMCONFIGURE,\n\tCANV_LOWER,\tCANV_MOVE,\tCANV_MOVETO,\tCANV_POSTSCRIPT,\n\tCANV_RAISE,\tCANV_RCHARS,\tCANV_ROTATE,\tCANV_SCALE,\n\tCANV_SCAN,\tCANV_SELECT,\tCANV_TYPE,\tCANV_XVIEW,\n\tCANV_YVIEW\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[1], canvasOptionStrings, \"option\", 0,\n\t    &idx) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Preserve(canvasPtr);\n\n    result = TCL_OK;\n    switch ((enum canvasOptionStringsEnum)idx) {\n    case CANV_ADDTAG:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tag searchCommand ?arg ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tresult = FIND_ITEMS(objv[2], 3);\n\tbreak;\n\n    case CANV_BBOX: {\n\tint gotAny;\n\tTcl_Size i;\n\tint x1 = 0, y1 = 0, x2 = 0, y2 = 0;\t/* Initializations needed only\n\t\t\t\t\t\t * to prevent overcautious\n\t\t\t\t\t\t * compiler warnings. */\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?tagOrId ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tgotAny = 0;\n\tfor (i = 2; i < objc; i++) {\n\t    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) {\n\t\tif ((itemPtr->x1 >= itemPtr->x2)\n\t\t\t|| (itemPtr->y1 >= itemPtr->y2)) {\n\t\t    continue;\n\t\t}\n\t\tif (!gotAny) {\n\t\t    x1 = itemPtr->x1;\n\t\t    y1 = itemPtr->y1;\n\t\t    x2 = itemPtr->x2;\n\t\t    y2 = itemPtr->y2;\n\t\t    gotAny = 1;\n\t\t} else {\n\t\t    if (itemPtr->x1 < x1) {\n\t\t\tx1 = itemPtr->x1;\n\t\t    }\n\t\t    if (itemPtr->y1 < y1) {\n\t\t\ty1 = itemPtr->y1;\n\t\t    }\n\t\t    if (itemPtr->x2 > x2) {\n\t\t\tx2 = itemPtr->x2;\n\t\t    }\n\t\t    if (itemPtr->y2 > y2) {\n\t\t\ty2 = itemPtr->y2;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tif (gotAny) {\n\t    Tcl_Obj *resultObjs[4];\n\n\t    resultObjs[0] = Tcl_NewWideIntObj(x1);\n\t    resultObjs[1] = Tcl_NewWideIntObj(y1);\n\t    resultObjs[2] = Tcl_NewWideIntObj(x2);\n\t    resultObjs[3] = Tcl_NewWideIntObj(y2);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, resultObjs));\n\t}\n\tbreak;\n    }\n    case CANV_BIND: {\n\tvoid *object;\n\n\tif ((objc < 3) || (objc > 5)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?sequence? ?command?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * Figure out what object to use for the binding (individual item vs.\n\t * tag).\n\t */\n\n\tobject = NULL;\n\tresult = TagSearchScan(canvasPtr, objv[2], &searchPtr);\n\tif (result != TCL_OK) {\n\t    goto done;\n\t}\n\tif (searchPtr->type == SEARCH_TYPE_ID) {\n\t    Tcl_HashEntry *entryPtr;\n\n\t    entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,\n\t\t    INT2PTR(searchPtr->id));\n\t    if (entryPtr != NULL) {\n\t\titemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);\n\t\tobject = itemPtr;\n\t    }\n\n\t    if (object == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"item \\\"%s\\\" doesn't exist\", Tcl_GetString(objv[2])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"CANVAS_ITEM\",\n\t\t\tTcl_GetString(objv[2]), (char *)NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t} else {\n\t    object = (char *)searchPtr->expr->uid;\n\t}\n\n\t/*\n\t * Make a binding table if the canvas doesn't already have one.\n\t */\n\n\tif (canvasPtr->bindingTable == NULL) {\n\t    canvasPtr->bindingTable = Tk_CreateBindingTable(interp);\n\t}\n\n\tif (objc == 5) {\n\t    int append = 0;\n\t    unsigned int mask;\n\t    const char *argv4 = Tcl_GetString(objv[4]);\n\n\t    if (argv4[0] == 0) {\n\t\tresult = Tk_DeleteBinding(interp, canvasPtr->bindingTable,\n\t\t\tobject, Tcl_GetString(objv[3]));\n\t\tgoto done;\n\t    }\n\t    if (searchPtr->type == SEARCH_TYPE_EXPR) {\n\t\t/*\n\t\t * If new tag expression, then insert in linked list.\n\t\t */\n\n\t\tTagSearchExpr *expr, **lastPtr;\n\n\t\tlastPtr = &(canvasPtr->bindTagExprs);\n\t\twhile ((expr = *lastPtr) != NULL) {\n\t\t    if (expr->uid == searchPtr->expr->uid) {\n\t\t\tbreak;\n\t\t    }\n\t\t    lastPtr = &(expr->next);\n\t\t}\n\t\tif (!expr) {\n\t\t    /*\n\t\t     * Transfer ownership of expr to bindTagExprs list.\n\t\t     */\n\n\t\t    *lastPtr = searchPtr->expr;\n\t\t    searchPtr->expr->next = NULL;\n\n\t\t    /*\n\t\t     * Flag in TagSearch that expr has changed ownership so\n\t\t     * that TagSearchDestroy doesn't try to free it.\n\t\t     */\n\n\t\t    searchPtr->expr = NULL;\n\t\t}\n\t    }\n\t    if (argv4[0] == '+') {\n\t\targv4++;\n\t\tappend = 1;\n\t    }\n\t    mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,\n\t\t    object, Tcl_GetString(objv[3]), argv4, append);\n\t    if (mask == 0) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    if (mask & ~(ButtonMotionMask|Button1MotionMask\n\t\t    |Button2MotionMask|Button3MotionMask|Button4MotionMask\n\t\t    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask\n\t\t    |EnterWindowMask|LeaveWindowMask|KeyPressMask\n\t\t    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {\n\t\tTk_DeleteBinding(interp, canvasPtr->bindingTable,\n\t\t\tobject, Tcl_GetString(objv[3]));\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"requested illegal events; only key, button, motion,\"\n\t\t\t\" enter, leave, and virtual events may be used\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"BAD_EVENTS\", (char *)NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t} else if (objc == 4) {\n\t    const char *command;\n\n\t    command = Tk_GetBinding(interp, canvasPtr->bindingTable,\n\t\t    object, Tcl_GetString(objv[3]));\n\t    if (command == NULL) {\n\t\tconst char *string = Tcl_GetString(Tcl_GetObjResult(interp));\n\n\t\t/*\n\t\t * Ignore missing binding errors. This is a special hack that\n\t\t * relies on the error message returned by FindSequence in\n\t\t * tkBind.c.\n\t\t */\n\n\t\tif (string[0] != '\\0') {\n\t\t    result = TCL_ERROR;\n\t\t    goto done;\n\t\t}\n\t\tTcl_ResetResult(interp);\n\t    } else {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(command, TCL_INDEX_NONE));\n\t    }\n\t} else {\n\t    Tk_GetAllBindings(interp, canvasPtr->bindingTable, object);\n\t}\n\tbreak;\n    }\n    case CANV_CANVASX: {\n\tint x;\n\tdouble grid;\n\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"screenx ?gridspacing?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2],\n\t\t&x) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc == 4) {\n\t    if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[3], &grid) != TCL_OK) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t} else {\n\t    grid = 0.0;\n\t}\n\tx += canvasPtr->xOrigin;\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(GridAlign((double)x,grid)));\n\tbreak;\n    }\n    case CANV_CANVASY: {\n\tint y;\n\tdouble grid;\n\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"screeny ?gridspacing?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2],\n\t\t&y) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc == 4) {\n\t    if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[3], &grid) != TCL_OK) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t} else {\n\t    grid = 0.0;\n\t}\n\ty += canvasPtr->yOrigin;\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(GridAlign((double)y,grid)));\n\tbreak;\n    }\n    case CANV_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tresult = Tk_ConfigureValue(interp, canvasPtr->tkwin, configSpecs,\n\t\tcanvasPtr, Tcl_GetString(objv[2]), 0);\n\tbreak;\n    case CANV_CONFIGURE:\n\tif (objc == 2) {\n\t    result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,\n\t\t    canvasPtr, NULL, 0);\n\t} else if (objc == 3) {\n\t    result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,\n\t\t    canvasPtr, Tcl_GetString(objv[2]), 0);\n\t} else {\n\t    result = ConfigureCanvas(interp, canvasPtr, objc-2, objv+2,\n\t\t    TK_CONFIG_ARGV_ONLY);\n\t}\n\tbreak;\n    case CANV_COORDS:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?x y x y ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);\n\tif (itemPtr != NULL) {\n\t    if (objc != 3) {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t    result = ItemCoords(canvasPtr, itemPtr, objc-3, objv+3);\n\t    if (objc != 3) {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t}\n\tbreak;\n    case CANV_IMOVE: {\n\tdouble ignored;\n\tTcl_Obj *tmpObj;\n\n\tif (objc != 6) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId index x y\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[4], &ignored) != TCL_OK\n\t\t|| Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[5], &ignored) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * Make a temporary object here that we can reuse for all the\n\t * modifications in the loop.\n\t */\n\n\ttmpObj = Tcl_NewListObj(2, objv+4);\n\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto doneImove) {\n\t    Tcl_Size index;\n\t    int x1, x2, y1, y2;\n\t    int dontRedraw1, dontRedraw2;\n\n\t    /*\n\t     * The TK_MOVABLE_POINTS flag should only be set for types that\n\t     * support the same semantics of index, dChars and insert methods\n\t     * as lines and canvases.\n\t     */\n\n\t    if (itemPtr == NULL ||\n\t\t    !(itemPtr->typePtr->flags & TK_MOVABLE_POINTS)) {\n\t\tcontinue;\n\t    }\n\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);\n\t    if (result != TCL_OK) {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * Redraw both item's old and new areas: it's possible that a\n\t     * replace could result in a new area larger than the old area.\n\t     * Except if the dCharsProc or insertProc sets the\n\t     * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.\n\t     */\n\n\t    x1 = itemPtr->x1; y1 = itemPtr->y1;\n\t    x2 = itemPtr->x2; y2 = itemPtr->y2;\n\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemDelChars(canvasPtr, itemPtr, index, index);\n\t    dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;\n\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemInsert(canvasPtr, itemPtr, index, tmpObj);\n\t    dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;\n\n\t    if (!(dontRedraw1 && dontRedraw2)) {\n\t\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t\t\tx1, y1, x2, y2);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t}\n\n    doneImove:\n\tTcl_DecrRefCount(tmpObj);\n\tbreak;\n    }\n    case CANV_CREATE: {\n\tTk_ItemType *typePtr;\n\tTk_ItemType *matchPtr = NULL;\n\tint isNew = 0;\n\tTcl_HashEntry *entryPtr;\n\tconst char *arg;\n\tTcl_Size length;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"type coords ?arg ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\targ = Tcl_GetStringFromObj(objv[2], &length);\n\tc = arg[0];\n\n\t/*\n\t * Lock because the list of types is a global resource that could be\n\t * updated by another thread. That's fairly unlikely, but not\n\t * impossible.\n\t */\n\n\tTcl_MutexLock(&typeListMutex);\n\tfor (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr){\n\t    if ((c == typePtr->name[0])\n\t\t    && (!strncmp(arg, typePtr->name, length))) {\n\t\tif (matchPtr != NULL) {\n\t\t    Tcl_MutexUnlock(&typeListMutex);\n\t\t    goto badType;\n\t\t}\n\t\tmatchPtr = typePtr;\n\t    }\n\t}\n\n\t/*\n\t * Can unlock now because we no longer look at the fields of the\n\t * matched item type that are potentially modified by other threads.\n\t */\n\n\tTcl_MutexUnlock(&typeListMutex);\n\tif (matchPtr == NULL) {\n\tbadType:\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"unknown or ambiguous item type \\\"%s\\\"\", arg));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"CANVAS_ITEM_TYPE\", arg,\n\t\t    (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc < 4) {\n\t    /*\n\t     * Allow more specific error return.\n\t     */\n\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"coords ?arg ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\ttypePtr = matchPtr;\n\titemPtr = (Tk_Item *)Tcl_Alloc(typePtr->itemSize);\n\titemPtr->id = canvasPtr->nextId++;\n\titemPtr->tagPtr = itemPtr->staticTagSpace;\n\titemPtr->tagSpace = TK_TAG_SPACE;\n\titemPtr->numTags = 0;\n\titemPtr->typePtr = typePtr;\n\titemPtr->state = TK_STATE_NULL;\n\titemPtr->redraw_flags = 0;\n\n\tif (ItemCreate(canvasPtr, itemPtr, objc, objv) != TCL_OK) {\n\t    Tcl_Free(itemPtr);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\titemPtr->nextPtr = NULL;\n\tentryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable,\n\t\tINT2PTR(itemPtr->id), &isNew);\n\tTcl_SetHashValue(entryPtr, itemPtr);\n\titemPtr->prevPtr = canvasPtr->lastItemPtr;\n\tcanvasPtr->hotPtr = itemPtr;\n\tcanvasPtr->hotPrevPtr = canvasPtr->lastItemPtr;\n\tif (canvasPtr->lastItemPtr == NULL) {\n\t    canvasPtr->firstItemPtr = itemPtr;\n\t} else {\n\t    canvasPtr->lastItemPtr->nextPtr = itemPtr;\n\t}\n\tcanvasPtr->lastItemPtr = itemPtr;\n\titemPtr->redraw_flags |= FORCE_REDRAW;\n\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\tcanvasPtr->flags |= REPICK_NEEDED;\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id));\n\tbreak;\n    }\n    case CANV_DCHARS: {\n\tTcl_Size first, last;\n\tint x1, x2, y1, y2;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId first ?last?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if ((itemPtr->typePtr->indexProc == NULL)\n\t\t    || (itemPtr->typePtr->dCharsProc == NULL)) {\n\t\tcontinue;\n\t    }\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[3], &first);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\t    if (objc == 5) {\n\t\tresult = ItemIndex(canvasPtr, itemPtr, objv[4], &last);\n\t\tif (result != TCL_OK) {\n\t\t    goto done;\n\t\t}\n\t    } else {\n\t\tlast = first;\n\t    }\n\n\t    /*\n\t     * Redraw both item's old and new areas: it's possible that a\n\t     * delete could result in a new area larger than the old area.\n\t     * Except if the dCharsProc sets the TK_ITEM_DONT_REDRAW flag,\n\t     * nothing more needs to be done.\n\t     */\n\n\t    x1 = itemPtr->x1; y1 = itemPtr->y1;\n\t    x2 = itemPtr->x2; y2 = itemPtr->y2;\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemDelChars(canvasPtr, itemPtr, first, last);\n\t    if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {\n\t\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t\t\tx1, y1, x2, y2);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t}\n\tbreak;\n    }\n    case CANV_DELETE: {\n\tTcl_Size i;\n\tTcl_HashEntry *entryPtr;\n\n\tfor (i = 2; i < objc; i++) {\n\t    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t\tif (canvasPtr->bindingTable != NULL) {\n\t\t    Tk_DeleteAllBindings(canvasPtr->bindingTable, itemPtr);\n\t\t}\n\t\tItemDelete(canvasPtr, itemPtr);\n\t\tif (itemPtr->tagPtr != itemPtr->staticTagSpace) {\n\t\t    Tcl_Free(itemPtr->tagPtr);\n\t\t}\n\t\tentryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,\n\t\t\tINT2PTR(itemPtr->id));\n\t\tTcl_DeleteHashEntry(entryPtr);\n\t\tif (itemPtr->nextPtr != NULL) {\n\t\t    itemPtr->nextPtr->prevPtr = itemPtr->prevPtr;\n\t\t}\n\t\tif (itemPtr->prevPtr != NULL) {\n\t\t    itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;\n\t\t}\n\t\tif (canvasPtr->firstItemPtr == itemPtr) {\n\t\t    canvasPtr->firstItemPtr = itemPtr->nextPtr;\n\t\t    if (canvasPtr->firstItemPtr == NULL) {\n\t\t\tcanvasPtr->lastItemPtr = NULL;\n\t\t    }\n\t\t}\n\t\tif (canvasPtr->lastItemPtr == itemPtr) {\n\t\t    canvasPtr->lastItemPtr = itemPtr->prevPtr;\n\t\t}\n\t\tTcl_Free(itemPtr);\n\t\tif (itemPtr == canvasPtr->currentItemPtr) {\n\t\t    canvasPtr->currentItemPtr = NULL;\n\t\t    canvasPtr->flags |= REPICK_NEEDED;\n\t\t}\n\t\tif (itemPtr == canvasPtr->newCurrentPtr) {\n\t\t    canvasPtr->newCurrentPtr = NULL;\n\t\t    canvasPtr->flags |= REPICK_NEEDED;\n\t\t}\n\t\tif (itemPtr == canvasPtr->textInfo.focusItemPtr) {\n\t\t    canvasPtr->textInfo.focusItemPtr = NULL;\n\t\t}\n\t\tif (itemPtr == canvasPtr->textInfo.selItemPtr) {\n\t\t    canvasPtr->textInfo.selItemPtr = NULL;\n\t\t}\n\t\tif ((itemPtr == canvasPtr->hotPtr)\n\t\t\t|| (itemPtr == canvasPtr->hotPrevPtr)) {\n\t\t    canvasPtr->hotPtr = NULL;\n\t\t}\n\t    }\n\t}\n\tbreak;\n    }\n    case CANV_DTAG: {\n\tTk_Uid tag;\n\tTcl_Size i;\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?tagToDelete?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc == 4) {\n\t    tag = Tk_GetUid(Tcl_GetString(objv[3]));\n\t} else {\n\t    tag = Tk_GetUid(Tcl_GetString(objv[2]));\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    for (i = itemPtr->numTags-1; i != TCL_INDEX_NONE; i--) {\n\t\tif (itemPtr->tagPtr[i] == tag) {\n\n\t\t    /*\n\t\t     * Don't shuffle the tags sequence: memmove the tags.\n\t\t     */\n\n\t\t    memmove((void *)(itemPtr->tagPtr + i),\n\t\t\t    itemPtr->tagPtr + i + 1,\n\t\t\t    (itemPtr->numTags - (i+1)) * sizeof(Tk_Uid));\n\t\t    itemPtr->numTags--;\n\n\t\t    /*\n\t\t     * There must be no break here: all tags with the same name must\n\t\t     * be deleted.\n\t\t     */\n\n\t\t}\n\t    }\n\t}\n\tbreak;\n    }\n    case CANV_FIND:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"searchCommand ?arg ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tresult = FIND_ITEMS(NULL, 2);\n\tbreak;\n    case CANV_FOCUS:\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?tagOrId?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\titemPtr = canvasPtr->textInfo.focusItemPtr;\n\tif (objc == 2) {\n\t    if (itemPtr != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id));\n\t    }\n\t    goto done;\n\t}\n\tif (canvasPtr->textInfo.gotFocus) {\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t}\n\tif (Tcl_GetString(objv[2])[0] == 0) {\n\t    canvasPtr->textInfo.focusItemPtr = NULL;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if (itemPtr->typePtr->icursorProc != NULL) {\n\t\tbreak;\n\t    }\n\t}\n\tif (itemPtr == NULL) {\n\t    goto done;\n\t}\n\tcanvasPtr->textInfo.focusItemPtr = itemPtr;\n\tif (canvasPtr->textInfo.gotFocus) {\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t}\n\tbreak;\n    case CANV_GETTAGS:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);\n\tif (itemPtr != NULL) {\n\t    Tcl_Size i;\n\t    Tcl_Obj *resultObj = Tcl_NewObj();\n\n\t    for (i = 0; i < itemPtr->numTags; i++) {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTcl_NewStringObj(itemPtr->tagPtr[i], TCL_INDEX_NONE));\n\t    }\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\tbreak;\n    case CANV_ICURSOR: {\n\tTcl_Size index;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId index\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if ((itemPtr->typePtr->indexProc == NULL)\n\t\t    || (itemPtr->typePtr->icursorProc == NULL)) {\n\t\tgoto done;\n\t    }\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\t    ItemCursor(canvasPtr, itemPtr, index);\n\t    if ((itemPtr == canvasPtr->textInfo.focusItemPtr)\n\t\t    && (canvasPtr->textInfo.cursorOn)) {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t}\n\tbreak;\n    }\n    case CANV_INDEX: {\n\tTcl_Size index;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId string\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if (itemPtr->typePtr->indexProc != NULL) {\n\t\tbreak;\n\t    }\n\t}\n\tif (itemPtr == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't find an indexable item \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"INDEXABLE_ITEM\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tresult = ItemIndex(canvasPtr, itemPtr, objv[3], &index);\n\tif (result != TCL_OK) {\n\t    goto done;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(index));\n\tbreak;\n    }\n    case CANV_INSERT: {\n\tTcl_Size beforeThis;\n\tint x1, x2, y1, y2;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId beforeThis string\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if ((itemPtr->typePtr->indexProc == NULL)\n\t\t    || (itemPtr->typePtr->insertProc == NULL)) {\n\t\tcontinue;\n\t    }\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[3], &beforeThis);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\n\t    /*\n\t     * Redraw both item's old and new areas: it's possible that an\n\t     * insertion could result in a new area either larger or smaller\n\t     * than the old area. Except if the insertProc sets the\n\t     * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.\n\t     */\n\n\t    x1 = itemPtr->x1; y1 = itemPtr->y1;\n\t    x2 = itemPtr->x2; y2 = itemPtr->y2;\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemInsert(canvasPtr, itemPtr, beforeThis, objv[4]);\n\t    if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {\n\t\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t\t\tx1, y1, x2, y2);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t}\n\tbreak;\n    }\n    case CANV_ITEMCGET:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId option\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);\n\tif (itemPtr != NULL) {\n\t    result = ItemConfigValue(canvasPtr, itemPtr, objv[3]);\n\t}\n\tbreak;\n    case CANV_ITEMCONFIGURE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?-option value ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if (objc == 3) {\n\t\tresult = ItemConfigInfo(canvasPtr, itemPtr, NULL);\n\t    } else if (objc == 4) {\n\t\tresult = ItemConfigInfo(canvasPtr, itemPtr, objv[3]);\n\t    } else {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t\tresult = ItemConfigure(canvasPtr, itemPtr, objc-3, objv+3);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t\tcanvasPtr->flags |= REPICK_NEEDED;\n\t    }\n\t    if ((result != TCL_OK) || (objc < 5)) {\n\t\tbreak;\n\t    }\n\t}\n\tbreak;\n    case CANV_LOWER: {\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?belowThis?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * First find the item just after which we'll insert the named items.\n\t */\n\n\tif (objc == 3) {\n\t    itemPtr = NULL;\n\t} else {\n\t    FIRST_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done);\n\t    if (itemPtr == NULL) {\n\t\tgoto done;\n\t    }\n\t    itemPtr = itemPtr->prevPtr;\n\t}\n\tRELINK_ITEMS(objv[2], itemPtr);\n\tbreak;\n    }\n    case CANV_MOVE: {\n\tdouble xAmount, yAmount;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId xAmount yAmount\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[3],\n\t\t&xAmount) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp,\n\t\t(Tk_Canvas) canvasPtr, objv[4], &yAmount) != TCL_OK)) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    ItemTranslate(canvasPtr, itemPtr, xAmount, yAmount);\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    canvasPtr->flags |= REPICK_NEEDED;\n\t}\n\tbreak;\n    }\n    case CANV_MOVETO: {\n\tint xBlank, yBlank;\n\tdouble xAmount, yAmount;\n\tdouble oldX = 0, oldY = 0, newX, newY;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId x y\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\txBlank = 0;\n\tif (Tcl_GetString(objv[3])[0] == '\\0') {\n\t    xBlank = 1;\n\t} else if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\tobjv[3], &newX) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tyBlank = 0;\n\tif (Tcl_GetString(objv[4])[0] == '\\0') {\n\t    yBlank = 1;\n\t} else if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\tobjv[4], &newY) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tFIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);\n\tif (itemPtr != NULL) {\n\t    oldX = itemPtr->x1;\n\t    oldY = itemPtr->y1;\n\n\t    /*\n\t     * Calculate the displacement.\n\t     */\n\n\t    if (xBlank) {\n\t\txAmount = 0;\n\t    } else {\n\t\txAmount = newX - oldX;\n\t    }\n\n\t    if (yBlank) {\n\t\tyAmount = 0;\n\t    } else {\n\t\tyAmount = newY - oldY;\n\t    }\n\n\t    /*\n\t     * Move the object(s).\n\t     */\n\n\t    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t\tItemTranslate(canvasPtr, itemPtr, xAmount, yAmount);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t\tcanvasPtr->flags |= REPICK_NEEDED;\n\t    }\n\t}\n\tbreak;\n    }\n    case CANV_POSTSCRIPT: {\n\tresult = TkCanvPostscriptObjCmd(canvasPtr, interp, objc, objv);\n\tbreak;\n    }\n    case CANV_RAISE: {\n\tTk_Item *prevPtr;\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId ?aboveThis?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * First find the item just after which we'll insert the named items.\n\t */\n\n\tif (objc == 3) {\n\t    prevPtr = canvasPtr->lastItemPtr;\n\t} else {\n\t    prevPtr = NULL;\n\t    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) {\n\t\tprevPtr = itemPtr;\n\t    }\n\t    if (prevPtr == NULL) {\n\t\tgoto done;\n\t    }\n\t}\n\tRELINK_ITEMS(objv[2], prevPtr);\n\tbreak;\n    }\n    case CANV_RCHARS: {\n\tTcl_Size first, last;\n\tint x1, x2, y1, y2;\n\tint dontRedraw1, dontRedraw2;\n\n\tif (objc != 6) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId first last string\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    if ((itemPtr->typePtr->indexProc == NULL)\n\t\t    || (itemPtr->typePtr->dCharsProc == NULL)\n\t\t    || (itemPtr->typePtr->insertProc == NULL)) {\n\t\tcontinue;\n\t    }\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[3], &first);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[4], &last);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\n\t    /*\n\t     * Redraw both item's old and new areas: it's possible that a\n\t     * replace could result in a new area larger than the old area.\n\t     * Except if the dCharsProc or insertProc sets the\n\t     * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.\n\t     */\n\n\t    x1 = itemPtr->x1; y1 = itemPtr->y1;\n\t    x2 = itemPtr->x2; y2 = itemPtr->y2;\n\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemDelChars(canvasPtr, itemPtr, first, last);\n\t    dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;\n\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t    ItemInsert(canvasPtr, itemPtr, first, objv[5]);\n\t    dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW;\n\n\t    if (!(dontRedraw1 && dontRedraw2)) {\n\t\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t\t\tx1, y1, x2, y2);\n\t\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\t    }\n\t    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;\n\t}\n\tbreak;\n    }\n    case CANV_ROTATE: {\n\tdouble x, y, angle;\n\tTk_Canvas canvas = (Tk_Canvas) canvasPtr;\n\n\tif (objc != 6) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tagOrId x y angle\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], &x) != TCL_OK ||\n\t\tTk_CanvasGetCoordFromObj(interp, canvas, objv[4], &y) != TCL_OK ||\n\t\tTcl_GetDoubleFromObj(interp, objv[5], &angle) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tangle = angle * 3.1415927 / 180.0;\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    ItemRotate(canvasPtr, itemPtr, x, y, angle);\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    canvasPtr->flags |= REPICK_NEEDED;\n\t}\n\tbreak;\n    }\n    case CANV_SCALE: {\n\tdouble xOrigin, yOrigin, xScale, yScale;\n\n\tif (objc != 7) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"tagOrId xOrigin yOrigin xScale yScale\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[3], &xOrigin) != TCL_OK)\n\t\t|| (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[4], &yOrigin) != TCL_OK)\n\t\t|| (Tcl_GetDoubleFromObj(interp, objv[5], &xScale)!=TCL_OK)\n\t\t|| (Tcl_GetDoubleFromObj(interp, objv[6], &yScale)!=TCL_OK)) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif ((xScale == 0.0) || (yScale == 0.0)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"scale factor cannot be zero\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"BAD_SCALE\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    ItemScale(canvasPtr, itemPtr, xOrigin, yOrigin, xScale, yScale);\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    canvasPtr->flags |= REPICK_NEEDED;\n\t}\n\tbreak;\n    }\n    case CANV_SCAN: {\n\tint x, y, gain = 10;\n\tstatic const char *const optionStrings[] = {\n\t    \"dragto\", \"mark\", NULL\n\t};\n\n\tif (objc < 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"mark|dragto x y ?dragGain?\");\n\t    result = TCL_ERROR;\n\t} else if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,\n\t\t\"scan option\", 0, &idx) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t} else if ((objc != 5) && (objc + idx != 6)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, idx?\"x y\":\"x y ?gain?\");\n\t    result = TCL_ERROR;\n\t} else if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){\n\t    result = TCL_ERROR;\n\t} else if ((objc == 6) &&\n\t\t(Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {\n\t    result = TCL_ERROR;\n\t} else if (idx) {\n\t    canvasPtr->scanX = x;\n\t    canvasPtr->scanXOrigin = canvasPtr->xOrigin;\n\t    canvasPtr->scanY = y;\n\t    canvasPtr->scanYOrigin = canvasPtr->yOrigin;\n\t} else {\n\t    int newXOrigin, newYOrigin, tmp;\n\n\t    /*\n\t     * Compute a new view origin for the canvas, amplifying the\n\t     * mouse motion.\n\t     */\n\n\t    tmp = canvasPtr->scanXOrigin - gain*(x - canvasPtr->scanX)\n\t\t    - canvasPtr->scrollX1;\n\t    newXOrigin = canvasPtr->scrollX1 + tmp;\n\t    tmp = canvasPtr->scanYOrigin - gain*(y - canvasPtr->scanY)\n\t\t    - canvasPtr->scrollY1;\n\t    newYOrigin = canvasPtr->scrollY1 + tmp;\n\t    CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin);\n\t}\n\tbreak;\n    }\n    case CANV_SELECT: {\n\tTcl_Size index;\n\tint optionindex;\n\tstatic const char *const optionStrings[] = {\n\t    \"adjust\", \"clear\", \"from\", \"item\", \"to\", NULL\n\t};\n\tenum options {\n\t    CANV_ADJUST, CANV_CLEAR, CANV_FROM, CANV_ITEM, CANV_TO\n\t};\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option ?tagOrId? ?arg?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc >= 4) {\n\t    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) {\n\t\tif ((itemPtr->typePtr->indexProc != NULL)\n\t\t\t&& (itemPtr->typePtr->selectionProc != NULL)){\n\t\t    break;\n\t\t}\n\t    }\n\t    if (itemPtr == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't find an indexable and selectable item \\\"%s\\\"\",\n\t\t\tTcl_GetString(objv[3])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SELECTABLE_ITEM\",\n\t\t\t(char *)NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t}\n\tif (objc == 5) {\n\t    result = ItemIndex(canvasPtr, itemPtr, objv[4], &index);\n\t    if (result != TCL_OK) {\n\t\tgoto done;\n\t    }\n\t}\n\tif (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,\n\t\t\"select option\", 0, &optionindex) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tswitch ((enum options) optionindex) {\n\tcase CANV_ADJUST:\n\t    if (objc != 5) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"tagOrId index\");\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    if (canvasPtr->textInfo.selItemPtr == itemPtr) {\n\t\tif (index + 1 <= ((canvasPtr->textInfo.selectFirst\n\t\t\t+ canvasPtr->textInfo.selectLast)/2)) {\n\t\t    canvasPtr->textInfo.selectAnchor =\n\t\t\t    canvasPtr->textInfo.selectLast + 1;\n\t\t} else {\n\t\t    canvasPtr->textInfo.selectAnchor =\n\t\t\t    canvasPtr->textInfo.selectFirst;\n\t\t}\n\t    }\n\t    CanvasSelectTo(canvasPtr, itemPtr, index);\n\t    break;\n\tcase CANV_CLEAR:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);\n\t    canvasPtr->textInfo.selItemPtr = NULL;\n\t    break;\n\tcase CANV_FROM:\n\t    if (objc != 5) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"tagOrId index\");\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    canvasPtr->textInfo.anchorItemPtr = itemPtr;\n\t    canvasPtr->textInfo.selectAnchor = index;\n\t    break;\n\tcase CANV_ITEM:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    if (canvasPtr->textInfo.selItemPtr != NULL) {\n\t\tTcl_SetObjResult(interp,\n\t\t\tTcl_NewWideIntObj(canvasPtr->textInfo.selItemPtr->id));\n\t    }\n\t    break;\n\tcase CANV_TO:\n\t    if (objc != 5) {\n\t\tTcl_WrongNumArgs(interp, 2, objv, \"tagOrId index\");\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    CanvasSelectTo(canvasPtr, itemPtr, index);\n\t    break;\n\t}\n\tbreak;\n    }\n    case CANV_TYPE:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tag\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tFIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);\n\tif (itemPtr != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(itemPtr->typePtr->name, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    case CANV_XVIEW: {\n\tint count, type;\n\tint newX = 0;\t\t/* Initialization needed only to prevent gcc\n\t\t\t\t * warnings. */\n\tdouble fraction;\n\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, ScrollFractions(\n\t\t    canvasPtr->xOrigin + canvasPtr->inset,\n\t\t    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)\n\t\t    - canvasPtr->inset, canvasPtr->scrollX1,\n\t\t    canvasPtr->scrollX2));\n\t    break;\n\t}\n\n\ttype = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);\n\tswitch (type) {\n\tcase TK_SCROLL_MOVETO:\n\t    newX = canvasPtr->scrollX1 - canvasPtr->inset\n\t\t    + (int) (fraction * (canvasPtr->scrollX2\n\t\t\t    - canvasPtr->scrollX1) + 0.5);\n\t    break;\n\tcase TK_SCROLL_PAGES:\n\t    newX = (int) (canvasPtr->xOrigin + count * .9\n\t\t    * (Tk_Width(canvasPtr->tkwin) - 2 * canvasPtr->inset));\n\t    break;\n\tcase TK_SCROLL_UNITS: {\n\t    int xScrollIncrement;\n\t    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->xScrollIncrementObj, &xScrollIncrement);\n\t    if (xScrollIncrement > 0) {\n\t\tnewX = canvasPtr->xOrigin + count * xScrollIncrement;\n\t    } else {\n\t\tnewX = (int) (canvasPtr->xOrigin + count * .1\n\t\t\t* (Tk_Width(canvasPtr->tkwin) - 2 * canvasPtr->inset));\n\t    }\n\t    break;\n\t}\n\tdefault:\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tCanvasSetOrigin(canvasPtr, newX, canvasPtr->yOrigin);\n\tbreak;\n    }\n    case CANV_YVIEW: {\n\tint count, type;\n\tint newY = 0;\t\t/* Initialization needed only to prevent gcc\n\t\t\t\t * warnings. */\n\tdouble fraction;\n\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, ScrollFractions(\n\t\t    canvasPtr->yOrigin + canvasPtr->inset,\n\t\t    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)\n\t\t    - canvasPtr->inset,\n\t\t    canvasPtr->scrollY1, canvasPtr->scrollY2));\n\t    break;\n\t}\n\n\ttype = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);\n\tswitch (type) {\n\tcase TK_SCROLL_MOVETO:\n\t    newY = canvasPtr->scrollY1 - canvasPtr->inset + (int) (\n\t\t    fraction*(canvasPtr->scrollY2-canvasPtr->scrollY1) + 0.5);\n\t    break;\n\tcase TK_SCROLL_PAGES:\n\t    newY = (int) (canvasPtr->yOrigin + count * .9\n\t\t    * (Tk_Height(canvasPtr->tkwin) - 2 * canvasPtr->inset));\n\t    break;\n\tcase TK_SCROLL_UNITS: {\n\t    int yScrollIncrement;\n\t    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->yScrollIncrementObj, &yScrollIncrement);\n\t    if (yScrollIncrement > 0) {\n\t\tnewY = canvasPtr->yOrigin + count * yScrollIncrement;\n\t    } else {\n\t\tnewY = (int) (canvasPtr->yOrigin + count * .1\n\t\t\t* (Tk_Height(canvasPtr->tkwin) - 2 * canvasPtr->inset));\n\t    }\n\t    break;\n\t}\n\tdefault:\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tCanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY);\n\tbreak;\n    }\n    case CANV_IMAGE: {\n\tTk_PhotoHandle photohandle;\n\tint subsample = 1, zoom = 1;\n\n\tif (objc < 3 || objc > 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"imagename ?subsample? ?zoom?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tif ((photohandle = Tk_FindPhoto(interp, Tcl_GetString(objv[2]) )) == 0) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * If we are given a subsample or a zoom then grab them.\n\t */\n\n\tif (objc >= 4 && Tcl_GetIntFromObj(interp, objv[3], &subsample) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc >= 5 && Tcl_GetIntFromObj(interp, objv[4], &zoom) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * Set the image size to zero, which allows the DrawCanvas() function\n\t * to expand the image automatically when it copies the pixmap into it.\n\t */\n\n\tif (Tk_PhotoSetSize(interp, photohandle, 0, 0) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tresult = DrawCanvas(interp, clientData, photohandle, subsample, zoom);\n    }\n    }\n\n  done:\n    TagSearchDestroy(searchPtr);\n    Tcl_Release(canvasPtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyCanvas --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of a canvas at a safe time (when no-one is\n *\tusing it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the canvas is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyCanvas(\n    void *memPtr)\t\t/* Info about canvas widget. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)memPtr;\n    Tk_Item *itemPtr;\n    TagSearchExpr *expr, *next;\n\n    /*\n     * Free up all of the items in the canvas.\n     */\n\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = canvasPtr->firstItemPtr) {\n\tcanvasPtr->firstItemPtr = itemPtr->nextPtr;\n\tItemDelete(canvasPtr, itemPtr);\n\tif (itemPtr->tagPtr != itemPtr->staticTagSpace) {\n\t    Tcl_Free(itemPtr->tagPtr);\n\t}\n\tTcl_Free(itemPtr);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    Tcl_DeleteHashTable(&canvasPtr->idTable);\n    if (canvasPtr->pixmapGC != NULL) {\n\tTk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);\n    }\n    expr = canvasPtr->bindTagExprs;\n    while (expr) {\n\tnext = expr->next;\n\tTagSearchExprDestroy(expr);\n\texpr = next;\n    }\n    Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);\n    if (canvasPtr->bindingTable != NULL) {\n\tTk_DeleteBindingTable(canvasPtr->bindingTable);\n    }\n    Tk_FreeOptions(configSpecs, canvasPtr, canvasPtr->display, 0);\n    canvasPtr->tkwin = NULL;\n    Tcl_Free(canvasPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureCanvas --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a canvas\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor canvasPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureCanvas(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkCanvas *canvasPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in objv. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    XGCValues gcValues;\n    GC newGC;\n    Tk_State old_canvas_state=canvasPtr->canvas_state;\n    int width, height, borderWidth, highlightWidth;\n    int xScrollIncrement, yScrollIncrement;\n\n    if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,\n\t    objc, objv, canvasPtr,\n\t    flags) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A few options need special processing, such as setting the background\n     * from a 3-D border and creating a GC for copying bits to the screen.\n     */\n\n    Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder);\n\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->heightObj, &height);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.insertBorderWidthObj, &canvasPtr->textInfo.insertBorderWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.insertWidthObj, &canvasPtr->textInfo.insertWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.selBorderWidthObj, &canvasPtr->textInfo.selBorderWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->widthObj, &width);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->xScrollIncrementObj, &xScrollIncrement);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->yScrollIncrementObj, &yScrollIncrement);\n    canvasPtr->inset = borderWidth + highlightWidth;\n\n    gcValues.function = GXcopy;\n    gcValues.graphics_exposures = False;\n    gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;\n    newGC = Tk_GetGC(canvasPtr->tkwin,\n\t    GCFunction|GCGraphicsExposures|GCForeground, &gcValues);\n    if (canvasPtr->pixmapGC != NULL) {\n\tTk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);\n    }\n    canvasPtr->pixmapGC = newGC;\n\n    /*\n     * Reconfigure items to reflect changed state disabled/normal.\n     */\n\n    if ( old_canvas_state != canvasPtr->canvas_state ) {\n\tTk_Item *itemPtr;\n\tint result;\n\n\tfor ( itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t\titemPtr = itemPtr->nextPtr) {\n\t    if ( itemPtr->state == TK_STATE_NULL ) {\n\t\tresult = (*itemPtr->typePtr->configProc)(canvasPtr->interp,\n\t\t\t(Tk_Canvas) canvasPtr, itemPtr, 0, NULL,\n\t\t\tTK_CONFIG_ARGV_ONLY);\n\t\tif (result != TCL_OK) {\n\t\t    Tcl_ResetResult(canvasPtr->interp);\n\t\t}\n\t    }\n\t}\n    }\n\n     /*\n     * Reset the desired dimensions for the window.\n     */\n\n    Tk_GeometryRequest(canvasPtr->tkwin, width + 2 * canvasPtr->inset,\n\t    height + 2 * canvasPtr->inset);\n\n    /*\n     * Restart the cursor timing sequence in case the on-time or off-time just\n     * changed.\n     */\n\n    if (canvasPtr->textInfo.gotFocus) {\n\tCanvasFocusProc(canvasPtr, 1);\n    }\n\n    /*\n     * Recompute the scroll region.\n     */\n\n    canvasPtr->scrollX1 = 0;\n    canvasPtr->scrollY1 = 0;\n    canvasPtr->scrollX2 = 0;\n    canvasPtr->scrollY2 = 0;\n    if (canvasPtr->regionObj != NULL) {\n\tTcl_Size argc2;\n\tconst char **argv2;\n\n\tif (Tcl_SplitList(canvasPtr->interp, Tcl_GetString(canvasPtr->regionObj),\n\t\t&argc2, &argv2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (argc2 != 4) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad scrollRegion \\\"%s\\\"\", Tcl_GetString(canvasPtr->regionObj)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SCROLL_REGION\", (char *)NULL);\n\tbadRegion:\n\t    Tcl_DecrRefCount(canvasPtr->regionObj);\n\t    Tcl_Free(argv2);\n\t    canvasPtr->regionObj = NULL;\n\t    return TCL_ERROR;\n\t}\n\tif ((Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,\n\t\t    argv2[0], &canvasPtr->scrollX1) != TCL_OK)\n\t\t|| (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,\n\t\t    argv2[1], &canvasPtr->scrollY1) != TCL_OK)\n\t\t|| (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,\n\t\t    argv2[2], &canvasPtr->scrollX2) != TCL_OK)\n\t\t|| (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,\n\t\t    argv2[3], &canvasPtr->scrollY2) != TCL_OK)) {\n\t    goto badRegion;\n\t}\n\tTcl_Free(argv2);\n    }\n\n    flags = canvasPtr->tsoffset.flags;\n    if (flags & TK_OFFSET_LEFT) {\n\tcanvasPtr->tsoffset.xoffset = 0;\n    } else if (flags & TK_OFFSET_CENTER) {\n\tcanvasPtr->tsoffset.xoffset = width / 2;\n    } else if (flags & TK_OFFSET_RIGHT) {\n\tcanvasPtr->tsoffset.xoffset = width;\n    }\n    if (flags & TK_OFFSET_TOP) {\n\tcanvasPtr->tsoffset.yoffset = 0;\n    } else if (flags & TK_OFFSET_MIDDLE) {\n\tcanvasPtr->tsoffset.yoffset = height / 2;\n    } else if (flags & TK_OFFSET_BOTTOM) {\n\tcanvasPtr->tsoffset.yoffset = height;\n    }\n\n    /*\n     * Reset the canvas's origin (this is a no-op unless confine mode has just\n     * been turned on or the scroll region has changed).\n     */\n\n    CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);\n    canvasPtr->flags |= UPDATE_SCROLLBARS|REDRAW_BORDERS;\n    Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t    canvasPtr->xOrigin, canvasPtr->yOrigin,\n\t    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),\n\t    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfigures all items in the canvas with a empty argc/argv, for the\n *\tside effect of causing all the items to recompute their geometry and\n *\tto be redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)instanceData;\n    Tk_Item *itemPtr;\n\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.insertBorderWidthObj, &canvasPtr->textInfo.insertBorderWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.insertWidthObj, &canvasPtr->textInfo.insertWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->textInfo.selBorderWidthObj, &canvasPtr->textInfo.selBorderWidth);\n\n    itemPtr = canvasPtr->firstItemPtr;\n    for ( ; itemPtr != NULL; itemPtr = itemPtr->nextPtr) {\n\tif (ItemConfigure(canvasPtr, itemPtr, 0, NULL) != TCL_OK) {\n\t    Tcl_ResetResult(canvasPtr->interp);\n\t}\n    }\n    canvasPtr->flags |= REPICK_NEEDED;\n    Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t    canvasPtr->xOrigin, canvasPtr->yOrigin,\n\t    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),\n\t    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DecomposeMaskToShiftAndBits --\n *\n *      Given a 32 bit pixel mask, we find the position of the lowest bit and the\n *      width of the mask bits.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n*       None.\n *\n *----------------------------------------------------------------------\n */\nstatic void\nDecomposeMaskToShiftAndBits(\n    unsigned int mask,     /* The pixel mask to examine */\n    int *shift,             /* Where to put the shift count (position of lowest bit) */\n    int *bits)              /* Where to put the bit count (width of the pixel mask) */\n{\n    int i;\n\n    *shift = 0;\n    *bits = 0;\n\n    /*\n     * Find the lowest '1' bit in the mask.\n     */\n\n    for (i = 0; i < 32; ++i) {\n\tif (mask & 1 << i)\n\t    break;\n    }\n    if (i < 32) {\n\t*shift = i;\n\n\t/*\n\t* Now find the next '0' bit and the width of the mask.\n\t*/\n\n\tfor ( ; i < 32; ++i) {\n\t    if ((mask & 1 << i) == 0)\n\t\tbreak;\n\t    else\n\t\t++*bits;\n\t}\n\n\t/*\n\t* Limit to the top 8 bits if the mask was wider than 8.\n\t*/\n\n\tif (*bits > 8) {\n\t    *shift += *bits - 8;\n\t    *bits = 8;\n\t}\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * DrawCanvas --\n *\n *      This function draws the contents of a canvas into the given Photo image.\n *      This function is called from the widget \"image\" subcommand.\n *      The canvas does not need to be mapped (one of it's ancestors must be)\n *      in order for this function to work.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *      Canvas contents from within the -scrollregion or widget size are rendered\n *      into the Photo. Any errors are left in the result.\n *\n *----------------------------------------------------------------------\n */\n\n#define OVERDRAW_PIXELS 32        /* How much larger we make the pixmap\n\t\t\t\t   * that the canvas objects are drawn into */\n\n#ifdef WORDS_BIGENDIAN\n#define IS_BIG_ENDIAN 1\n#else\n#define IS_BIG_ENDIAN 0\n#endif\n\n#define BYTE_SWAP16(n) ((((unsigned short)n)>>8) | (((unsigned short)n)<<8))\n#define BYTE_SWAP32(n) (((n>>24)&0x000000FF) | ((n<<8)&0x00FF0000) | ((n>>8)&0x0000FF00) | ((n<<24)&0xFF000000))\n\nstatic int\nDrawCanvas(\n    Tcl_Interp *interp,           /* As passed to the widget command, and we will leave errors here */\n    void *clientData,\n    Tk_PhotoHandle photohandle,   /* The photo we are rendering into */\n    int subsample,                /* If either subsample or zoom are not 1 then we call Tk_PhotoPutZoomedBlock() */\n    int zoom)\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n    Tk_Window tkwin;\n    Display *displayPtr;\n    Tk_PhotoImageBlock blockPtr = {0,0,0,0,0,{0,0,0,0}};\n    Window wid;\n    Tk_Item *itemPtr;\n    Pixmap pixmap = 0;\n    XImage *ximagePtr = NULL;\n    Visual *visualPtr;\n    GC xgc = 0;\n    XGCValues xgcValues;\n    int canvasX1, canvasY1, canvasX2, canvasY2, cWidth, cHeight,\n\tpixmapX1, pixmapY1, pixmapX2, pixmapY2, pmWidth, pmHeight,\n\tbitsPerPixel, bytesPerPixel, x, y, result = TCL_OK,\n\trshift, gshift, bshift, rbits, gbits, bbits;\n\n#ifdef DEBUG_DRAWCANVAS\n    char buffer[128];\n#endif\n\n    if ((tkwin = canvasPtr->tkwin) == NULL) {\n\tTcl_AppendResult(interp, \"canvas tkwin is NULL!\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n\n    /*\n     * If this canvas is unmapped, then we won't have a window id, so we will\n     * try the ancestors of the canvas until we find a window that has a\n     * valid window id. The Tk_GetPixmap() call requires a valid window id.\n     */\n\n    do {\n\n\tif ((displayPtr = Tk_Display(tkwin)) == NULL) {\n\t    Tcl_AppendResult(interp, \"canvas (or parent) display is NULL!\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tif ((wid = Tk_WindowId(tkwin)) != 0) {\n\t    continue;\n\t}\n\n\tif ((tkwin = Tk_Parent(tkwin)) == NULL) {\n\t    Tcl_AppendResult(interp, \"canvas has no parent with a valid window id! Is the toplevel window mapped?\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n    } while (wid == 0);\n\n    bitsPerPixel = Tk_Depth(tkwin);\n    visualPtr = Tk_Visual(tkwin);\n\n    if (subsample == 0) {\n\tTcl_AppendResult(interp, \"subsample cannot be zero\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n\n    /*\n    * Scan through the item list, registering the bounding box for all items\n    * that didn't do that for the final coordinates yet. This can be\n    * determined by the FORCE_REDRAW flag.\n    */\n\n    for (itemPtr = canvasPtr -> firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr -> nextPtr) {\n\tif (itemPtr -> redraw_flags & FORCE_REDRAW) {\n\t    itemPtr -> redraw_flags &= ~FORCE_REDRAW;\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    itemPtr -> redraw_flags &= ~FORCE_REDRAW;\n\t}\n    }\n\n    /*\n     * The DisplayCanvas() function works out the region that needs redrawing,\n     * but we don't do this. We grab the whole scrollregion or canvas window\n     * area. If we have a defined -scrollregion we use that as the drawing\n     * region, otherwise use the canvas window height and width with an origin\n     * of 0,0.\n     */\n    if (canvasPtr->scrollX1 != 0 || canvasPtr->scrollY1 != 0 ||\n\t    canvasPtr->scrollX2 != 0 || canvasPtr->scrollY2 != 0) {\n\n\tcanvasX1 = canvasPtr->scrollX1;\n\tcanvasY1 = canvasPtr->scrollY1;\n\tcanvasX2 = canvasPtr->scrollX2;\n\tcanvasY2 = canvasPtr->scrollY2;\n\tcWidth = canvasX2 - canvasX1 + 1;\n\tcHeight = canvasY2 - canvasY1 + 1;\n\n    } else {\n\n\tcWidth = Tk_Width(tkwin);\n\tcHeight = Tk_Height(tkwin);\n\tcanvasX1 = 0;\n\tcanvasY1 = 0;\n\tcanvasX2 = canvasX1 + cWidth - 1;\n\tcanvasY2 = canvasY1 + cHeight - 1;\n    }\n\n    /*\n     * Allocate a pixmap to draw into. We add OVERDRAW_PIXELS in the same way\n     * that DisplayCanvas() does to avoid problems on some systems when objects\n     * are being drawn too close to the edge.\n     */\n\n    pixmapX1 = canvasX1 - OVERDRAW_PIXELS;\n    pixmapY1 = canvasY1 - OVERDRAW_PIXELS;\n    pixmapX2 = canvasX2 + OVERDRAW_PIXELS;\n    pixmapY2 = canvasY2 + OVERDRAW_PIXELS;\n    pmWidth = pixmapX2 - pixmapX1 + 1;\n    pmHeight = pixmapY2 - pixmapY1 + 1;\n    if ((pixmap = Tk_GetPixmap(displayPtr, Tk_WindowId(tkwin), pmWidth, pmHeight,\n\t    bitsPerPixel)) == 0) {\n\tTcl_AppendResult(interp, \"failed to create drawing Pixmap\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n\n    /*\n     * Before we can draw the canvas objects into the pixmap it's background\n     * should be filled with canvas background colour.\n     */\n\n    xgcValues.function = GXcopy;\n    xgcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;\n    xgc = XCreateGC(displayPtr, pixmap, GCFunction|GCForeground, &xgcValues);\n    XFillRectangle(displayPtr,pixmap,xgc,0,0,pmWidth,pmHeight);\n\n    /*\n     * Draw all the cavas items into the pixmap\n     */\n\n    canvasPtr->drawableXOrigin = pixmapX1;\n    canvasPtr->drawableYOrigin = pixmapY1;\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif ((itemPtr->x1 >= pixmapX2) || (itemPtr->y1 >= pixmapY2) ||\n\t\t(itemPtr->x2 < pixmapX1) || (itemPtr->y2 < pixmapY1)) {\n\t    if (!AlwaysRedraw(itemPtr)) {\n\t\tcontinue;\n\t    }\n\t}\n\tif (itemPtr->state == TK_STATE_HIDDEN ||\n\t\t(itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state\n\t\t== TK_STATE_HIDDEN)) {\n\t    continue;\n\t}\n\tItemDisplay(canvasPtr, itemPtr, pixmap, pixmapX1, pixmapY1, pmWidth,\n\t\tpmHeight);\n    }\n\n    /*\n     * Copy the Pixmap into an ZPixmap format XImage so we can copy it across\n     * to the photo image. This seems to be the only way to get Pixmap image\n     * data out of an image. Note we have to account for the OVERDRAW_PIXELS\n     * border width.\n     */\n\n    if ((ximagePtr = XGetImage(displayPtr, pixmap, -pixmapX1, -pixmapY1, cWidth,\n\t    cHeight, AllPlanes, ZPixmap)) == NULL) {\n\tTcl_AppendResult(interp, \"failed to copy Pixmap to XImage\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n\n#ifdef DEBUG_DRAWCANVAS\n    Tcl_AppendResult(interp, \"ximagePtr {\", (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->width);   Tcl_AppendResult(interp, \" width \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->height);  Tcl_AppendResult(interp, \" height \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->xoffset); Tcl_AppendResult(interp, \" xoffset \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->format);  Tcl_AppendResult(interp, \" format \", buffer, (char *)NULL);\n    Tcl_AppendResult(interp, \" ximagePtr->data\", (char *)NULL);\n    if (ximagePtr->data != NULL) {\n\tint ix, iy;\n\n\tTcl_AppendResult(interp, \" {\", (char *)NULL);\n\tfor (iy = 0; iy < ximagePtr->height; ++ iy) {\n\t    Tcl_AppendResult(interp, \" {\", (char *)NULL);\n\t    for (ix = 0; ix < ximagePtr->bytes_per_line; ++ ix) {\n\t\tif (ix > 0) {\n\t\t    if (ix % 4 == 0)\n\t\t\tTcl_AppendResult(interp, \"-\", (char *)NULL);\n\t\t    else\n\t\t\tTcl_AppendResult(interp, \" \", (char *)NULL);\n\t\t}\n\t\tsnprintf(buffer,sizeof(buffer),\"%2.2x\",ximagePtr->data[ximagePtr->bytes_per_line * iy + ix]&0xFF);\n\t\tTcl_AppendResult(interp, buffer, (char *)NULL);\n\t    }\n\t    Tcl_AppendResult(interp, \" }\", (char *)NULL);\n\t}\n\tTcl_AppendResult(interp, \" }\", (char *)NULL);\n    } else\n\tsnprintf(buffer,sizeof(buffer),\" NULL\");\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->byte_order);       Tcl_AppendResult(interp, \" byte_order \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->bitmap_unit);      Tcl_AppendResult(interp, \" bitmap_unit \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->bitmap_bit_order); Tcl_AppendResult(interp, \" bitmap_bit_order \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->bitmap_pad);       Tcl_AppendResult(interp, \" bitmap_pad \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->depth);            Tcl_AppendResult(interp, \" depth \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->bytes_per_line);   Tcl_AppendResult(interp, \" bytes_per_line \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",ximagePtr->bits_per_pixel);   Tcl_AppendResult(interp, \" bits_per_pixel \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",ximagePtr->red_mask);   Tcl_AppendResult(interp, \" red_mask \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",ximagePtr->green_mask); Tcl_AppendResult(interp, \" green_mask \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",ximagePtr->blue_mask);  Tcl_AppendResult(interp, \" blue_mask \", buffer, (char *)NULL);\n    Tcl_AppendResult(interp, \" }\", (char *)NULL);\n\n    Tcl_AppendResult(interp, \"\\nvisualPtr {\", (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",visualPtr->red_mask);   Tcl_AppendResult(interp, \" red_mask \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",visualPtr->green_mask); Tcl_AppendResult(interp, \" green_mask \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"0x%8.8lx\",visualPtr->blue_mask);  Tcl_AppendResult(interp, \" blue_mask \", buffer, (char *)NULL);\n    Tcl_AppendResult(interp, \" }\", (char *)NULL);\n\n#endif\n\n    /*\n     * Fill in the PhotoImageBlock structure abd allocate a block of memory\n     * for the converted image data. Note we allocate an alpha channel even\n     * though we don't use one, because this layout helps Tk_PhotoPutBlock()\n     * use memcpy() instead of the slow pixel or line copy.\n     */\n\n    blockPtr.width = cWidth;\n    blockPtr.height = cHeight;\n    blockPtr.pixelSize = 4;\n    blockPtr.pitch = blockPtr.pixelSize * blockPtr.width;\n\n#ifdef TK_XGETIMAGE_USES_ABGR32\n    blockPtr.offset[0] = 1;\n    blockPtr.offset[1] = 2;\n    blockPtr.offset[2] = 3;\n    blockPtr.offset[3] = 0;\n#else\n    blockPtr.offset[0] = 0;\n    blockPtr.offset[1] = 1;\n    blockPtr.offset[2] = 2;\n    blockPtr.offset[3] = 3;\n#endif\n\n    blockPtr.pixelPtr = (unsigned char *)Tcl_Alloc(blockPtr.pixelSize * blockPtr.height * blockPtr.width);\n\n    /*\n     * Now convert the image data pixel by pixel from XImage to 32bit RGBA\n     * format suitable for Tk_PhotoPutBlock().\n     */\n\n    DecomposeMaskToShiftAndBits(visualPtr->red_mask,&rshift,&rbits);\n    DecomposeMaskToShiftAndBits(visualPtr->green_mask,&gshift,&gbits);\n    DecomposeMaskToShiftAndBits(visualPtr->blue_mask,&bshift,&bbits);\n\n#ifdef DEBUG_DRAWCANVAS\n    snprintf(buffer,sizeof(buffer),\"%d\",rshift); Tcl_AppendResult(interp, \"\\nbits { rshift \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",gshift); Tcl_AppendResult(interp, \" gshift \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",bshift); Tcl_AppendResult(interp, \" bshift \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",rbits);  Tcl_AppendResult(interp, \" rbits \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",gbits);  Tcl_AppendResult(interp, \" gbits \", buffer, (char *)NULL);\n    snprintf(buffer,sizeof(buffer),\"%d\",bbits);  Tcl_AppendResult(interp, \" bbits \", buffer, \" }\", (char *)NULL);\n    Tcl_AppendResult(interp, \"\\nConverted_image {\", (char *)NULL);\n#endif\n\n    /* Ok, had to use ximagePtr->bits_per_pixel here and in the switch (...)\n     * below to get this to work on Windows. X11 correctly sets the bitmap\n     *_pad and bitmap_unit fields to 32, but on Windows they are 0 and 8\n     * respectively!\n     */\n\n    bytesPerPixel = ximagePtr->bits_per_pixel/8;\n    for (y = 0; y < blockPtr.height; ++y) {\n\n#ifdef DEBUG_DRAWCANVAS\n\tTcl_AppendResult(interp, \" {\", (char *)NULL);\n#endif\n\n\tfor(x = 0; x < blockPtr.width; ++x) {\n\t    unsigned int pixel = 0;\n\t    int pixel_offset = blockPtr.pitch * y + blockPtr.pixelSize * x;\n\t    switch (ximagePtr->bits_per_pixel) {\n\n\t\t/*\n\t\t * Get an 8 bit pixel from the XImage.\n\t\t */\n\n\t\tcase 8 :\n\t\t    pixel = *((unsigned char *)(ximagePtr->data + bytesPerPixel * x\n\t\t\t    + ximagePtr->bytes_per_line * y));\n\t\t    break;\n\n\t\t/*\n\t\t * Get a 16 bit pixel from the XImage, and correct the\n\t\t * byte order as necessary.\n\t\t */\n\n\t\tcase 16 :\n\t\t    pixel = *((unsigned short *)(ximagePtr->data + bytesPerPixel * x\n\t\t\t    + ximagePtr->bytes_per_line * y));\n\t\t    if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst)\n\t\t\t    || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst))\n\t\t\tpixel = BYTE_SWAP16(pixel);\n\t\t    break;\n\n\t\t/*\n\t\t * Grab a 32 bit pixel from the XImage, and correct the\n\t\t * byte order as necessary.\n\t\t */\n\n\t\tcase 32 :\n\t\t    pixel = *((unsigned int *)(ximagePtr->data + bytesPerPixel * x\n\t\t\t    + ximagePtr->bytes_per_line * y));\n\t\t    if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst)\n\t\t\t    || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst))\n\t\t\tpixel = BYTE_SWAP32(pixel);\n\t\t    break;\n\t    }\n\n\t    /*\n\t     * We have a pixel with the correct byte order, so pull out the\n\t     * colours and place them in the photo block. Perhaps we could\n\t     * just not bother with the alpha byte because we are using\n\t     * TK_PHOTO_COMPOSITE_SET later?\n\t     * ***Windows: We have to swap the red and blue values. The\n\t     * XImage storage is B - G - R - A which becomes a 32bit ARGB\n\t     * quad. However the visual mask is a 32bit ABGR quad. And\n\t     * Tk_PhotoPutBlock() wants R-G-B-A which is a 32bit ABGR quad.\n\t     * If the visual mask was correct there would be no need to\n\t     * swap anything here.\n\t     */\n\n#ifdef _WIN32\n#define   R_OFFSET blockPtr.offset[2]\n#define   G_OFFSET blockPtr.offset[1]\n#define   B_OFFSET blockPtr.offset[0]\n#define   A_OFFSET blockPtr.offset[3]\n#else\n#define   R_OFFSET blockPtr.offset[0]\n#define   G_OFFSET blockPtr.offset[1]\n#define   B_OFFSET blockPtr.offset[2]\n#define   A_OFFSET blockPtr.offset[3]\n#endif\n#ifdef TK_XGETIMAGE_USES_ABGR32\n#define COPY_PIXEL (ximagePtr->bits_per_pixel == 32)\n#else\n#define COPY_PIXEL 0\n#endif\n\n\t    if (COPY_PIXEL) {\n\t\t/*\n\t\t * This platform packs pixels in RGBA byte order, as expected\n\t\t * by Tk_PhotoPutBlock() so we can just copy the pixel as an int.\n\t\t */\n\t\t*((unsigned int *) (blockPtr.pixelPtr + pixel_offset)) = pixel;\n\t    } else {\n\t\tblockPtr.pixelPtr[pixel_offset + R_OFFSET] =\n\t\t    (unsigned char)((pixel & visualPtr->red_mask) >> rshift);\n\t\tblockPtr.pixelPtr[pixel_offset + G_OFFSET] =\n\t\t    (unsigned char)((pixel & visualPtr->green_mask) >> gshift);\n\t\tblockPtr.pixelPtr[pixel_offset + B_OFFSET] =\n\t\t    (unsigned char)((pixel & visualPtr->blue_mask) >> bshift);\n\t\tblockPtr.pixelPtr[pixel_offset + A_OFFSET] = 0xFF;\n\t    }\n\n#ifdef DEBUG_DRAWCANVAS\n\t    fprintf(stderr, \"Converted pixel %x to %hhx %hhx %hhx %hhx \\n\",\n\t\t    pixel,\n\t\t    blockPtr.pixelPtr[pixel_offset + 0],\n\t\t    blockPtr.pixelPtr[pixel_offset + 1],\n\t\t    blockPtr.pixelPtr[pixel_offset + 2],\n\t\t    blockPtr.pixelPtr[pixel_offset + 3]);\n\t    {\n\t\tint ix;\n\t\tif (x > 0)\n\t\t    Tcl_AppendResult(interp, \"-\", (char *)NULL);\n\t\tfor (ix = 0; ix < 4; ++ix) {\n\t\t    if (ix > 0)\n\t\t\tTcl_AppendResult(interp, \" \", (char *)NULL);\n\t\t    snprintf(buffer,sizeof(buffer),\"%2.2x\",\n\t\t\t    blockPtr.pixelPtr[blockPtr.pitch * y\n\t\t\t    + blockPtr.pixelSize * x + ix]&0xFF);\n\t\t    Tcl_AppendResult(interp, buffer, (char *)NULL);\n\t\t}\n\t    }\n#endif\n\n\t}\n\n#ifdef DEBUG_DRAWCANVAS\n\tTcl_AppendResult(interp, \" }\", (char *)NULL);\n#endif\n\n    }\n\n#ifdef DEBUG_DRAWCANVAS\n    Tcl_AppendResult(interp, \" }\", (char *)NULL);\n#endif\n\n    /*\n     * Now put the copied pixmap into the photo.\n     * If either zoom or subsample are not 1, we use the zoom function.\n     */\n\n    if (subsample != 1 || zoom != 1) {\n\tif ((result = Tk_PhotoPutZoomedBlock(interp, photohandle, &blockPtr,\n\t\t0, 0, cWidth * zoom / subsample, cHeight * zoom / subsample,\n\t\tzoom, zoom, subsample, subsample, TK_PHOTO_COMPOSITE_SET))\n\t\t!= TCL_OK) {\n\t    goto done;\n\t}\n    } else {\n\tif ((result = Tk_PhotoPutBlock(interp, photohandle, &blockPtr, 0, 0,\n\t    cWidth, cHeight, TK_PHOTO_COMPOSITE_SET)) != TCL_OK) {\n\t    goto done;\n\t}\n    }\n\n    /*\n     * Clean up anything we have allocated and exit.\n     */\n\ndone:\n    if (blockPtr.pixelPtr)\n\tTcl_Free(blockPtr.pixelPtr);\n    if (pixmap)\n\tTk_FreePixmap(Tk_Display(tkwin), pixmap);\n    if (ximagePtr)\n\tXDestroyImage(ximagePtr);\n    if (xgc)\n\tXFreeGC(displayPtr,xgc);\n    return result;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * DisplayCanvas --\n *\n *\tThis function redraws the contents of a canvas window. It is invoked\n *\tas a do-when-idle handler, so it only runs when there's nothing else\n *\tfor the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayCanvas(\n    void *clientData)\t/* Information about widget. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n    Tk_Window tkwin = canvasPtr->tkwin;\n    Tk_Item *itemPtr;\n    Pixmap pixmap;\n    int screenX1, screenX2, screenY1, screenY2, width, height;\n    int borderWidth, highlightWidth;\n\n    if (canvasPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    if (!Tk_IsMapped(tkwin)) {\n\tgoto done;\n    }\n\n    /*\n     * Choose a new current item if that is needed (this could cause event\n     * handlers to be invoked).\n     */\n\n    while (canvasPtr->flags & REPICK_NEEDED) {\n\tTcl_Preserve(canvasPtr);\n\tcanvasPtr->flags &= ~REPICK_NEEDED;\n\tPickCurrentItem(canvasPtr, &canvasPtr->pickEvent);\n\ttkwin = canvasPtr->tkwin;\n\tTcl_Release(canvasPtr);\n\tif (tkwin == NULL) {\n\t    return;\n\t}\n    }\n\n    /*\n     * Scan through the item list, registering the bounding box for all items\n     * that didn't do that for the final coordinates yet. This can be\n     * determined by the FORCE_REDRAW flag.\n     */\n\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif (itemPtr->redraw_flags & FORCE_REDRAW) {\n\t    itemPtr->redraw_flags &= ~FORCE_REDRAW;\n\t    EventuallyRedrawItem(canvasPtr, itemPtr);\n\t    itemPtr->redraw_flags &= ~FORCE_REDRAW;\n\t}\n    }\n\n    /*\n     * Compute the intersection between the area that needs redrawing and the\n     * area that's visible on the screen.\n     */\n\n    if ((canvasPtr->redrawX1 < canvasPtr->redrawX2)\n\t    && (canvasPtr->redrawY1 < canvasPtr->redrawY2)) {\n\tscreenX1 = canvasPtr->xOrigin + canvasPtr->inset;\n\tscreenY1 = canvasPtr->yOrigin + canvasPtr->inset;\n\tscreenX2 = canvasPtr->xOrigin + Tk_Width(tkwin) - canvasPtr->inset;\n\tscreenY2 = canvasPtr->yOrigin + Tk_Height(tkwin) - canvasPtr->inset;\n\tif (canvasPtr->redrawX1 > screenX1) {\n\t    screenX1 = canvasPtr->redrawX1;\n\t}\n\tif (canvasPtr->redrawY1 > screenY1) {\n\t    screenY1 = canvasPtr->redrawY1;\n\t}\n\tif (canvasPtr->redrawX2 < screenX2) {\n\t    screenX2 = canvasPtr->redrawX2;\n\t}\n\tif (canvasPtr->redrawY2 < screenY2) {\n\t    screenY2 = canvasPtr->redrawY2;\n\t}\n\tif ((screenX1 >= screenX2) || (screenY1 >= screenY2)) {\n\t    goto borders;\n\t}\n\n\twidth = screenX2 - screenX1;\n\theight = screenY2 - screenY1;\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n\t/*\n\t * Redrawing is done in a temporary pixmap that is allocated here and\n\t * freed at the end of the function. All drawing is done to the\n\t * pixmap, and the pixmap is copied to the screen at the end of the\n\t * function. The temporary pixmap serves two purposes:\n\t *\n\t * 1. It provides a smoother visual effect (no clearing and gradual\n\t *    redraw will be visible to users).\n\t * 2. It allows us to redraw only the objects that overlap the redraw\n\t *    area. Otherwise incorrect results could occur from redrawing\n\t *    things that stick outside of the redraw area (we'd have to\n\t *    redraw everything in order to make the overlaps look right).\n\t *\n\t * Some tricky points about the pixmap:\n\t *\n\t * 1. We only allocate a large enough pixmap to hold the area that has\n\t *    to be redisplayed. This saves time in in the X server for large\n\t *    objects that cover much more than the area being redisplayed:\n\t *    only the area of the pixmap will actually have to be redrawn.\n\t * 2. Some X servers (e.g. the one for DECstations) have troubles with\n\t *    with characters that overlap an edge of the pixmap (on the DEC\n\t *    servers, as of 8/18/92, such characters are drawn one pixel too\n\t *    far to the right). To handle this problem, make the pixmap a bit\n\t *    larger than is absolutely needed so that for normal-sized fonts\n\t *    the characters that overlap the edge of the pixmap will be\n\t *    outside the area we care about.\n\t */\n\n\tcanvasPtr->drawableXOrigin = screenX1 - 30;\n\tcanvasPtr->drawableYOrigin = screenY1 - 30;\n\tpixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t    (screenX2 + 30 - canvasPtr->drawableXOrigin),\n\t    (screenY2 + 30 - canvasPtr->drawableYOrigin),\n\t    Tk_Depth(tkwin));\n#else\n\tcanvasPtr->drawableXOrigin = canvasPtr->xOrigin;\n\tcanvasPtr->drawableYOrigin = canvasPtr->yOrigin;\n\tpixmap = Tk_WindowId(tkwin);\n\tTk_ClipDrawableToRect(Tk_Display(tkwin), pixmap,\n\t\tscreenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin,\n\t\twidth, height);\n\t/*\n\t * Call ItemDisplay for all window items.  This does not redraw the\n\t * windows, but sets their position within the canvas, which ensures\n\t * for macOS (the only platform which defines TK_NO_DOUBLE_BUFFERING)\n\t * that the clipping region for the canvas gets updated before the\n\t * background is painted by XFillRectangle.  Otherwise, when the\n\t * background is filled the old locations of the window items will be\n\t * clipped away, rather than the new locations, causing \"ghost\"\n\t * windows to appear at the old locations.  Now that updateLayer is\n\t * being used for macOS drawing it should be possible to stop\n\t * maintaining clipping regions for all widgets.  When that happens\n\t * this code can probably be removed.\n\t */\n\n\tfor (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t\titemPtr = itemPtr->nextPtr) {\n\t    if (AlwaysRedraw(itemPtr)) {\n\t\tItemDisplay(canvasPtr, itemPtr, pixmap,\n\t\t\t    screenX1, screenY1, width, height);\n\t    }\n\t}\n\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n\t/*\n\t * Clear the area to be redrawn.\n\t */\n\n\tXFillRectangle(Tk_Display(tkwin), pixmap, canvasPtr->pixmapGC,\n\t\tscreenX1 - canvasPtr->drawableXOrigin,\n\t\tscreenY1 - canvasPtr->drawableYOrigin, (unsigned int) width,\n\t\t(unsigned int) height);\n\n\t/*\n\t * Scan through the item list, redrawing those items that need it. An\n\t * item must be redraw if either (a) it intersects the smaller\n\t * on-screen area or (b) it intersects the full canvas area and its\n\t * type requests that it be redrawn always (e.g. so subwindows can be\n\t * unmapped when they move off-screen).\n\t */\n\n\tfor (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t\titemPtr = itemPtr->nextPtr) {\n\t    if ((itemPtr->x1 >= screenX2)\n\t\t    || (itemPtr->y1 >= screenY2)\n\t\t    || (itemPtr->x2 < screenX1)\n\t\t    || (itemPtr->y2 < screenY1)) {\n\t\tif (!AlwaysRedraw(itemPtr)\n\t\t\t|| (itemPtr->x1 >= canvasPtr->redrawX2)\n\t\t\t|| (itemPtr->y1 >= canvasPtr->redrawY2)\n\t\t\t|| (itemPtr->x2 < canvasPtr->redrawX1)\n\t\t\t|| (itemPtr->y2 < canvasPtr->redrawY1)) {\n\t\t    continue;\n\t\t}\n\t    }\n\t    if (itemPtr->state == TK_STATE_HIDDEN ||\n\t\t    (itemPtr->state == TK_STATE_NULL &&\n\t\t    canvasPtr->canvas_state == TK_STATE_HIDDEN)) {\n\t\tcontinue;\n\t    }\n\t    ItemDisplay(canvasPtr, itemPtr, pixmap, screenX1, screenY1, width,\n\t\t    height);\n\t}\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n\t/*\n\t * Copy from the temporary pixmap to the screen, then free up the\n\t * temporary pixmap.\n\t */\n\n\tXCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin),\n\t\tcanvasPtr->pixmapGC,\n\t\tscreenX1 - canvasPtr->drawableXOrigin,\n\t\tscreenY1 - canvasPtr->drawableYOrigin,\n\t\t(unsigned int) width, (unsigned int) height,\n\t\tscreenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin);\n\tTk_FreePixmap(Tk_Display(tkwin), pixmap);\n#else\n\tTk_ClipDrawableToRect(Tk_Display(tkwin), pixmap, 0, 0, -1, -1);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    }\n\n    /*\n     * Draw the window borders, if needed.\n     */\n\n  borders:\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);\n    if (canvasPtr->flags & REDRAW_BORDERS) {\n\tcanvasPtr->flags &= ~REDRAW_BORDERS;\n\tif (borderWidth > 0) {\n\t    Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),\n\t\t    canvasPtr->bgBorder, highlightWidth, highlightWidth,\n\t\t    Tk_Width(tkwin) - 2 * highlightWidth,\n\t\t    Tk_Height(tkwin) - 2 * highlightWidth,\n\t\t    borderWidth, canvasPtr->relief);\n\t}\n\tif (highlightWidth > 0) {\n\t    GC fgGC, bgGC;\n\n\t    bgGC = Tk_GCForColor(canvasPtr->highlightBgColorPtr,\n\t\t    Tk_WindowId(tkwin));\n\t    if (canvasPtr->textInfo.gotFocus) {\n\t\tfgGC = Tk_GCForColor(canvasPtr->highlightColorPtr,\n\t\t\tTk_WindowId(tkwin));\n\t\tTk_DrawHighlightBorder(tkwin, fgGC, bgGC,\n\t\t\thighlightWidth, Tk_WindowId(tkwin));\n\t    } else {\n\t\tTk_DrawHighlightBorder(tkwin, bgGC, bgGC,\n\t\t\thighlightWidth, Tk_WindowId(tkwin));\n\t    }\n\t}\n    }\n\n  done:\n    canvasPtr->flags &= ~(REDRAW_PENDING|BBOX_NOT_EMPTY);\n    canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0;\n    canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0;\n    if (canvasPtr->flags & UPDATE_SCROLLBARS) {\n\tCanvasUpdateScrollbars(canvasPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tcanvases.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n\n    if (eventPtr->type == Expose) {\n\tint x, y;\n\n\tx = eventPtr->xexpose.x + canvasPtr->xOrigin;\n\ty = eventPtr->xexpose.y + canvasPtr->yOrigin;\n\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x, y,\n\t\tx + eventPtr->xexpose.width,\n\t\ty + eventPtr->xexpose.height);\n\tif ((eventPtr->xexpose.x < canvasPtr->inset)\n\t\t|| (eventPtr->xexpose.y < canvasPtr->inset)\n\t\t|| ((eventPtr->xexpose.x + eventPtr->xexpose.width)\n\t\t    > (Tk_Width(canvasPtr->tkwin) - canvasPtr->inset))\n\t\t|| ((eventPtr->xexpose.y + eventPtr->xexpose.height)\n\t\t    > (Tk_Height(canvasPtr->tkwin) - canvasPtr->inset))) {\n\t    canvasPtr->flags |= REDRAW_BORDERS;\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tif (canvasPtr->tkwin != NULL) {\n\t    canvasPtr->tkwin = NULL;\n\t    Tcl_DeleteCommandFromToken(canvasPtr->interp,\n\t\t    canvasPtr->widgetCmd);\n\t}\n\tif (canvasPtr->flags & REDRAW_PENDING) {\n\t    Tcl_CancelIdleCall(DisplayCanvas, canvasPtr);\n\t}\n\tTcl_EventuallyFree(canvasPtr, DestroyCanvas);\n    } else if (eventPtr->type == ConfigureNotify) {\n\tcanvasPtr->flags |= UPDATE_SCROLLBARS;\n\n\t/*\n\t * The call below is needed in order to recenter the canvas if it's\n\t * confined and its scroll region is smaller than the window.\n\t */\n\n\tCanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);\n\tTk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, canvasPtr->xOrigin,\n\t\tcanvasPtr->yOrigin,\n\t\tcanvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),\n\t\tcanvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));\n\tcanvasPtr->flags |= REDRAW_BORDERS;\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    CanvasFocusProc(canvasPtr, 1);\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    CanvasFocusProc(canvasPtr, 0);\n\t}\n    } else if (eventPtr->type == UnmapNotify) {\n\tTk_Item *itemPtr;\n\n\t/*\n\t * Special hack: if the canvas is unmapped, then must notify all items\n\t * with flag TK_ALWAYS_REDRAW set, so that they know that they are no\n\t * longer displayed.\n\t */\n\n\tfor (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t\titemPtr = itemPtr->nextPtr) {\n\t    if (AlwaysRedraw(itemPtr)) {\n\t\tItemDisplay(canvasPtr, itemPtr, None, 0, 0, 0, 0);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n    Tk_Window tkwin = canvasPtr->tkwin;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\tcanvasPtr->tkwin = NULL;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CanvasEventuallyRedraw --\n *\n *\tArrange for part or all of a canvas widget to redrawn at some\n *\tconvenient time in the future.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe screen will eventually be refreshed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CanvasEventuallyRedraw(\n    Tk_Canvas canvas,\t\t/* Information about widget. */\n    int x1, int y1,\t\t/* Upper left corner of area to redraw. Pixels\n\t\t\t\t * on edge are redrawn. */\n    int x2, int y2)\t\t/* Lower right corner of area to redraw.\n\t\t\t\t * Pixels on edge are not redrawn. */\n{\n    TkCanvas *canvasPtr = Canvas(canvas);\n\n    /*\n     * If tkwin is NULL, the canvas has been destroyed, so we can't really\n     * redraw it.\n     */\n\n    if (canvasPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    if ((x1 >= x2) || (y1 >= y2) ||\n\t    (x2 < canvasPtr->xOrigin) || (y2 < canvasPtr->yOrigin) ||\n\t    (x1 >= canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)) ||\n\t    (y1 >= canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin))) {\n\treturn;\n    }\n    if (canvasPtr->flags & BBOX_NOT_EMPTY) {\n\tif (x1 <= canvasPtr->redrawX1) {\n\t    canvasPtr->redrawX1 = x1;\n\t}\n\tif (y1 <= canvasPtr->redrawY1) {\n\t    canvasPtr->redrawY1 = y1;\n\t}\n\tif (x2 >= canvasPtr->redrawX2) {\n\t    canvasPtr->redrawX2 = x2;\n\t}\n\tif (y2 >= canvasPtr->redrawY2) {\n\t    canvasPtr->redrawY2 = y2;\n\t}\n    } else {\n\tcanvasPtr->redrawX1 = x1;\n\tcanvasPtr->redrawY1 = y1;\n\tcanvasPtr->redrawX2 = x2;\n\tcanvasPtr->redrawY2 = y2;\n\tcanvasPtr->flags |= BBOX_NOT_EMPTY;\n    }\n    if (!(canvasPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayCanvas, canvasPtr);\n\tcanvasPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EventuallyRedrawItem --\n *\n *\tArrange for part or all of a canvas widget to redrawn at some\n *\tconvenient time in the future.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe screen will eventually be refreshed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEventuallyRedrawItem(\n    TkCanvas *canvasPtr,\t/* Information about widget. */\n    Tk_Item *itemPtr)\t\t/* Item to be redrawn. May be NULL, in which\n\t\t\t\t * case nothing happens. */\n{\n    if (itemPtr == NULL || canvasPtr->tkwin == NULL) {\n\treturn;\n    }\n    if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2) ||\n\t    (itemPtr->x2 < canvasPtr->xOrigin) ||\n\t    (itemPtr->y2 < canvasPtr->yOrigin) ||\n\t    (itemPtr->x1 >= canvasPtr->xOrigin+Tk_Width(canvasPtr->tkwin)) ||\n\t    (itemPtr->y1 >= canvasPtr->yOrigin+Tk_Height(canvasPtr->tkwin))) {\n\tif (!AlwaysRedraw(itemPtr)) {\n\t    return;\n\t}\n    }\n    if (!(itemPtr->redraw_flags & FORCE_REDRAW)) {\n\tif (canvasPtr->flags & BBOX_NOT_EMPTY) {\n\t    if (itemPtr->x1 <= canvasPtr->redrawX1) {\n\t\tcanvasPtr->redrawX1 = itemPtr->x1;\n\t    }\n\t    if (itemPtr->y1 <= canvasPtr->redrawY1) {\n\t\tcanvasPtr->redrawY1 = itemPtr->y1;\n\t    }\n\t    if (itemPtr->x2 >= canvasPtr->redrawX2) {\n\t\tcanvasPtr->redrawX2 = itemPtr->x2;\n\t    }\n\t    if (itemPtr->y2 >= canvasPtr->redrawY2) {\n\t\tcanvasPtr->redrawY2 = itemPtr->y2;\n\t    }\n\t} else {\n\t    canvasPtr->redrawX1 = itemPtr->x1;\n\t    canvasPtr->redrawY1 = itemPtr->y1;\n\t    canvasPtr->redrawX2 = itemPtr->x2;\n\t    canvasPtr->redrawY2 = itemPtr->y2;\n\t    canvasPtr->flags |= BBOX_NOT_EMPTY;\n\t}\n\titemPtr->redraw_flags |= FORCE_REDRAW;\n    }\n    if (!(canvasPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayCanvas, canvasPtr);\n\tcanvasPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreateItemType --\n *\n *\tThis function may be invoked to add a new kind of canvas element to\n *\tthe core item types supported by Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrom now on, the new item type will be useable in canvas widgets\n *\t(e.g. typePtr->name can be used as the item type in \"create\" widget\n *\tcommands). If there was already a type with the same name as in\n *\ttypePtr, it is replaced with the new type.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreateItemType(\n    Tk_ItemType *typePtr)\t/* Information about item type; storage must\n\t\t\t\t * be statically allocated (must live\n\t\t\t\t * forever). */\n{\n    Tk_ItemType *typePtr2, *prevPtr;\n\n    if (typeList == NULL) {\n\tInitCanvas();\n    }\n\n    /*\n     * If there's already an item type with the given name, remove it.\n     */\n\n    Tcl_MutexLock(&typeListMutex);\n    for (typePtr2 = typeList, prevPtr = NULL; typePtr2 != NULL;\n\t    prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {\n\tif (strcmp(typePtr2->name, typePtr->name) == 0) {\n\t    if (prevPtr == NULL) {\n\t\ttypeList = typePtr2->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = typePtr2->nextPtr;\n\t    }\n\t    break;\n\t}\n    }\n    typePtr->nextPtr = typeList;\n    typeList = typePtr;\n    Tcl_MutexUnlock(&typeListMutex);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetItemTypes --\n *\n *\tThis function returns a pointer to the list of all item types. Note\n *\tthat this is inherently thread-unsafe, but since item types are only\n *\tever registered very rarely this is unlikely to be a problem in\n *\tpractice.\n *\n * Results:\n *\tThe return value is a pointer to the first in the list of item types\n *\tcurrently supported by canvases.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_ItemType *\nTk_GetItemTypes(void)\n{\n    if (typeList == NULL) {\n\tInitCanvas();\n    }\n    return typeList;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitCanvas --\n *\n *\tThis function is invoked to perform once-only-ever initialization for\n *\tthe module, such as setting up the type table.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitCanvas(void)\n{\n    Tcl_MutexLock(&typeListMutex);\n    if (typeList != NULL) {\n\tTcl_MutexUnlock(&typeListMutex);\n\treturn;\n    }\n    typeList = &tkRectangleType;\n    tkRectangleType.nextPtr = &tkTextType;\n    tkTextType.nextPtr = &tkLineType;\n    tkLineType.nextPtr = &tkPolygonType;\n    tkPolygonType.nextPtr = &tkImageType;\n    tkImageType.nextPtr = &tkOvalType;\n    tkOvalType.nextPtr = &tkBitmapType;\n    tkBitmapType.nextPtr = &tkArcType;\n    tkArcType.nextPtr = &tkWindowType;\n    tkWindowType.nextPtr = NULL;\n    Tcl_MutexUnlock(&typeListMutex);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetStaticUids --\n *\n *\tThis function is invoked to return a structure filled with the Uids\n *\tused when doing tag searching. If it was never before called in the\n *\tcurrent thread, it initializes the structure for that thread (uids are\n *\tonly ever local to one thread [Bug 1114977]).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic SearchUids *\nGetStaticUids(void)\n{\n    SearchUids *searchUids = (SearchUids *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(SearchUids));\n\n    if (searchUids->allUid == NULL) {\n\tsearchUids->allUid       = Tk_GetUid(\"all\");\n\tsearchUids->currentUid   = Tk_GetUid(\"current\");\n\tsearchUids->andUid       = Tk_GetUid(\"&&\");\n\tsearchUids->orUid        = Tk_GetUid(\"||\");\n\tsearchUids->xorUid       = Tk_GetUid(\"^\");\n\tsearchUids->parenUid     = Tk_GetUid(\"(\");\n\tsearchUids->endparenUid  = Tk_GetUid(\")\");\n\tsearchUids->negparenUid  = Tk_GetUid(\"!(\");\n\tsearchUids->tagvalUid    = Tk_GetUid(\"!!\");\n\tsearchUids->negtagvalUid = Tk_GetUid(\"!\");\n    }\n    return searchUids;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchExprInit --\n *\n *\tThis function allocates and initializes one TagSearchExpr struct.\n *\n * Results:\n *\n * Side effects:\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTagSearchExprInit(\n    TagSearchExpr **exprPtrPtr)\n{\n    TagSearchExpr *expr = *exprPtrPtr;\n\n    if (expr == NULL) {\n\texpr = (TagSearchExpr *)Tcl_Alloc(sizeof(TagSearchExpr));\n\texpr->allocated = 0;\n\texpr->uids = NULL;\n\texpr->next = NULL;\n    }\n    expr->uid = NULL;\n    expr->index = 0;\n    expr->length = 0;\n    *exprPtrPtr = expr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchExprDestroy --\n *\n *\tThis function destroys one TagSearchExpr structure.\n *\n * Results:\n *\n * Side effects:\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTagSearchExprDestroy(\n    TagSearchExpr *expr)\n{\n    if (expr != NULL) {\n\tif (expr->uids) {\n\t    Tcl_Free(expr->uids);\n\t}\n\tTcl_Free(expr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchScan --\n *\n *\tThis function is called to initiate an enumeration of all items in a\n *\tgiven canvas that contain a tag that matches the tagOrId expression.\n *\n * Results:\n *\tThe return value indicates if the tagOrId expression was successfully\n *\tscanned (syntax). The information at *searchPtr is initialized such\n *\tthat a call to TagSearchFirst, followed by successive calls to\n *\tTagSearchNext will return items that match tag.\n *\n * Side effects:\n *\tSearchPtr is linked into a list of searches in progress on canvasPtr,\n *\tso that elements can safely be deleted while the search is in\n *\tprogress.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTagSearchScan(\n    TkCanvas *canvasPtr,\t/* Canvas whose items are to be searched. */\n    Tcl_Obj *tagObj,\t\t/* Object giving tag value. */\n    TagSearch **searchPtrPtr)\t/* Record describing tag search; will be\n\t\t\t\t * initialized here. */\n{\n    const char *tag = Tcl_GetString(tagObj);\n    int i;\n    TagSearch *searchPtr;\n\n    /*\n     * Initialize the search.\n     */\n\n    if (*searchPtrPtr != NULL) {\n\tsearchPtr = *searchPtrPtr;\n    } else {\n\t/*\n\t * Allocate primary search struct on first call.\n\t */\n\n\t*searchPtrPtr = searchPtr = (TagSearch *)Tcl_Alloc(sizeof(TagSearch));\n\tsearchPtr->expr = NULL;\n\n\t/*\n\t * Allocate buffer for rewritten tags (after de-escaping).\n\t */\n\n\tsearchPtr->rewritebufferAllocated = 100;\n\tsearchPtr->rewritebuffer = (char *)Tcl_Alloc(searchPtr->rewritebufferAllocated);\n    }\n    TagSearchExprInit(&searchPtr->expr);\n\n    /*\n     * How long is the tagOrId?\n     */\n\n    searchPtr->stringLength = strlen(tag);\n\n    /*\n     * Make sure there is enough buffer to hold rewritten tags.\n     */\n\n    if ((unsigned) searchPtr->stringLength >=\n\t    searchPtr->rewritebufferAllocated) {\n\tsearchPtr->rewritebufferAllocated = searchPtr->stringLength + 100;\n\tsearchPtr->rewritebuffer = (char *)\n\t\tTcl_Realloc(searchPtr->rewritebuffer,\n\t\tsearchPtr->rewritebufferAllocated);\n    }\n\n    /*\n     * Initialize search.\n     */\n\n    searchPtr->canvasPtr = canvasPtr;\n    searchPtr->searchOver = 0;\n    searchPtr->type = SEARCH_TYPE_EMPTY;\n\n    /*\n     * Find the first matching item in one of several ways. If the tag is a\n     * number then it selects the single item with the matching identifier.\n     * In this case see if the item being requested is the hot item, in which\n     * case the search can be skipped.\n     */\n\n    if (searchPtr->stringLength && isdigit(UCHAR(*tag))) {\n\tchar *end;\n\n\tsearchPtr->id = strtoul(tag, &end, 0);\n\tif (*end == 0) {\n\t    searchPtr->type = SEARCH_TYPE_ID;\n\t    return TCL_OK;\n\t}\n    }\n\n    /*\n     * For all other tags and tag expressions convert to a UID. This UID is\n     * kept forever, but this should be thought of as a cache rather than as a\n     * memory leak.\n     */\n\n    searchPtr->expr->uid = Tk_GetUid(tag);\n\n    /*\n     * Short circuit impossible searches for null tags.\n     */\n\n    if (searchPtr->stringLength == 0) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Pre-scan tag for at least one unquoted \"&&\" \"||\" \"^\" \"!\"; if not found\n     * then use string as simple tag.\n     */\n\n    for (i = 0; i < searchPtr->stringLength ; i++) {\n\tif (tag[i] == '\"') {\n\t    i++;\n\t    for ( ; i < searchPtr->stringLength; i++) {\n\t\tif (tag[i] == '\\\\') {\n\t\t    i++;\n\t\t    continue;\n\t\t}\n\t\tif (tag[i] == '\"') {\n\t\t    break;\n\t\t}\n\t    }\n\t} else if ((tag[i] == '&' && tag[i+1] == '&')\n\t\t|| (tag[i] == '|' && tag[i+1] == '|')\n\t\t|| (tag[i] == '^')\n\t\t|| (tag[i] == '!')) {\n\t    searchPtr->type = SEARCH_TYPE_EXPR;\n\t    break;\n\t}\n    }\n\n    searchPtr->string = tag;\n    searchPtr->stringIndex = 0;\n    if (searchPtr->type == SEARCH_TYPE_EXPR) {\n\t/*\n\t * An operator was found in the prescan, so now compile the tag\n\t * expression into array of Tk_Uid flagging any syntax errors found.\n\t */\n\n\tif (TagSearchScanExpr(canvasPtr->interp, searchPtr,\n\t\tsearchPtr->expr) != TCL_OK) {\n\t    /*\n\t     * Syntax error in tag expression. The result message was set by\n\t     * TagSearchScanExpr.\n\t     */\n\n\t    return TCL_ERROR;\n\t}\n\tsearchPtr->expr->length = searchPtr->expr->index;\n    } else if (searchPtr->expr->uid == GetStaticUids()->allUid) {\n\t/*\n\t * All items match.\n\t */\n\n\tsearchPtr->type = SEARCH_TYPE_ALL;\n    } else {\n\t/*\n\t * Optimized single-tag search\n\t */\n\n\tsearchPtr->type = SEARCH_TYPE_TAG;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchDestroy --\n *\n *\tThis function destroys any dynamic structures that may have been\n *\tallocated by TagSearchScan.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tDeallocates memory.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTagSearchDestroy(\n    TagSearch *searchPtr)\t/* Record describing tag search. */\n{\n    if (searchPtr) {\n\tTagSearchExprDestroy(searchPtr->expr);\n\tTcl_Free(searchPtr->rewritebuffer);\n\tTcl_Free(searchPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchScanExpr --\n *\n *\tThis recursive function is called to scan a tag expression and compile\n *\tit into an array of Tk_Uids.\n *\n * Results:\n *\tThe return value indicates if the tagOrId expression was successfully\n *\tscanned (syntax). The information at *searchPtr is initialized such\n *\tthat a call to TagSearchFirst, followed by successive calls to\n *\tTagSearchNext will return items that match tag.\n *\n * Side effects:\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTagSearchScanExpr(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TagSearch *searchPtr,\t/* Search data. */\n    TagSearchExpr *expr)\t/* Compiled expression result. */\n{\n    int looking_for_tag;\t/* When true, scanner expects next char(s) to\n\t\t\t\t * be a tag, else operand expected. */\n    int found_tag;\t\t/* One or more tags found. */\n    int found_endquote;\t\t/* For quoted tag string parsing. */\n    int negate_result;\t\t/* Pending negation of next tag value. */\n    char *tag;\t\t\t/* Tag from tag expression string. */\n    char c;\n    SearchUids *searchUids;\t/* Collection of uids for basic search\n\t\t\t\t * expression terms. */\n\n    searchUids = GetStaticUids();\n    negate_result = 0;\n    found_tag = 0;\n    looking_for_tag = 1;\n    while (searchPtr->stringIndex < searchPtr->stringLength) {\n\tc = searchPtr->string[searchPtr->stringIndex++];\n\n\t/*\n\t * Need two slots free at this point, not one. [Bug 2931374]\n\t */\n\n\tif (expr->index >= expr->allocated-1) {\n\t    expr->allocated += 15;\n\t    if (expr->uids) {\n\t\texpr->uids = (Tk_Uid *)Tcl_Realloc(expr->uids,\n\t\t\texpr->allocated * sizeof(Tk_Uid));\n\t    } else {\n\t\texpr->uids = (Tk_Uid *)Tcl_Alloc(expr->allocated * sizeof(Tk_Uid));\n\t    }\n\t}\n\n\tif (looking_for_tag) {\n\t    switch (c) {\n\t    case ' ':\t\t/* Ignore unquoted whitespace */\n\t    case '\\t':\n\t    case '\\n':\n\t    case '\\r':\n\t\tbreak;\n\n\t    case '!':\t\t/* Negate next tag or subexpr */\n\t\tif (looking_for_tag > 1) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"too many '!' in tag search expression\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t    \"COMPLEXITY\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tlooking_for_tag++;\n\t\tnegate_result = 1;\n\t\tbreak;\n\n\t    case '(':\t\t/* Scan (negated) subexpr recursively */\n\t\tif (negate_result) {\n\t\t    expr->uids[expr->index++] = searchUids->negparenUid;\n\t\t    negate_result = 0;\n\t\t} else {\n\t\t    expr->uids[expr->index++] = searchUids->parenUid;\n\t\t}\n\t\tif (TagSearchScanExpr(interp, searchPtr, expr) != TCL_OK) {\n\t\t    /*\n\t\t     * Result string should be already set by nested call to\n\t\t     * tag_expr_scan()\n\t\t     */\n\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tlooking_for_tag = 0;\n\t\tfound_tag = 1;\n\t\tbreak;\n\n\t    case '\"':\t\t/* Quoted tag string */\n\t\tif (negate_result) {\n\t\t    expr->uids[expr->index++] = searchUids->negtagvalUid;\n\t\t    negate_result = 0;\n\t\t} else {\n\t\t    expr->uids[expr->index++] = searchUids->tagvalUid;\n\t\t}\n\t\ttag = searchPtr->rewritebuffer;\n\t\tfound_endquote = 0;\n\t\twhile (searchPtr->stringIndex < searchPtr->stringLength) {\n\t\t    c = searchPtr->string[searchPtr->stringIndex++];\n\t\t    if (c == '\\\\') {\n\t\t\tc = searchPtr->string[searchPtr->stringIndex++];\n\t\t    }\n\t\t    if (c == '\"') {\n\t\t\tfound_endquote = 1;\n\t\t\tbreak;\n\t\t    }\n\t\t    *tag++ = c;\n\t\t}\n\t\tif (!found_endquote) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"missing endquote in tag search expression\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t    \"ENDQUOTE\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (!(tag - searchPtr->rewritebuffer)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"null quoted tag string in tag search expression\",\n\t\t\t    TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t    \"EMPTY\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\t*tag++ = '\\0';\n\t\texpr->uids[expr->index++] =\n\t\t\tTk_GetUid(searchPtr->rewritebuffer);\n\t\tlooking_for_tag = 0;\n\t\tfound_tag = 1;\n\t\tbreak;\n\n\t    case '&':\t\t/* Illegal chars when looking for tag */\n\t    case '|':\n\t    case '^':\n\t    case ')':\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"unexpected operator in tag search expression\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t\"UNEXPECTED\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\n\t    default:\t\t/* Unquoted tag string */\n\t\tif (negate_result) {\n\t\t    expr->uids[expr->index++] = searchUids->negtagvalUid;\n\t\t    negate_result = 0;\n\t\t} else {\n\t\t    expr->uids[expr->index++] = searchUids->tagvalUid;\n\t\t}\n\t\ttag = searchPtr->rewritebuffer;\n\t\t*tag++ = c;\n\n\t\t/*\n\t\t * Copy rest of tag, including any embedded whitespace.\n\t\t */\n\n\t\twhile (searchPtr->stringIndex < searchPtr->stringLength) {\n\t\t    c = searchPtr->string[searchPtr->stringIndex];\n\t\t    if (c == '!' || c == '&' || c == '|' || c == '^'\n\t\t\t    || c == '(' || c == ')' || c == '\"') {\n\t\t\tbreak;\n\t\t    }\n\t\t    *tag++ = c;\n\t\t    searchPtr->stringIndex++;\n\t\t}\n\n\t\t/*\n\t\t * Remove trailing whitespace.\n\t\t */\n\n\t\twhile (1) {\n\t\t    c = *--tag;\n\n\t\t    /*\n\t\t     * There must have been one non-whitespace char, so this\n\t\t     * will terminate.\n\t\t     */\n\n\t\t    if (c != ' ' && c != '\\t' && c != '\\n' && c != '\\r') {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\t*++tag = '\\0';\n\t\texpr->uids[expr->index++] =\n\t\t\tTk_GetUid(searchPtr->rewritebuffer);\n\t\tlooking_for_tag = 0;\n\t\tfound_tag = 1;\n\t    }\n\n\t} else {\t\t/* ! looking_for_tag */\n\t    switch (c) {\n\t    case ' ':\t\t/* Ignore whitespace */\n\t    case '\\t':\n\t    case '\\n':\n\t    case '\\r':\n\t\tbreak;\n\n\t    case '&':\t\t/* AND operator */\n\t\tc = searchPtr->string[searchPtr->stringIndex++];\n\t\tif (c != '&') {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"singleton '&' in tag search expression\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t    \"INCOMPLETE_OP\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\texpr->uids[expr->index++] = searchUids->andUid;\n\t\tlooking_for_tag = 1;\n\t\tbreak;\n\n\t    case '|':\t\t/* OR operator */\n\t\tc = searchPtr->string[searchPtr->stringIndex++];\n\t\tif (c != '|') {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"singleton '|' in tag search expression\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\",\n\t\t\t    \"INCOMPLETE_OP\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\texpr->uids[expr->index++] = searchUids->orUid;\n\t\tlooking_for_tag = 1;\n\t\tbreak;\n\n\t    case '^':\t\t/* XOR operator */\n\t\texpr->uids[expr->index++] = searchUids->xorUid;\n\t\tlooking_for_tag = 1;\n\t\tbreak;\n\n\t    case ')':\t\t/* End subexpression */\n\t\texpr->uids[expr->index++] = searchUids->endparenUid;\n\t\tgoto breakwhile;\n\n\t    default:\t\t/* syntax error */\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"invalid boolean operator in tag search expression\",\n\t\t\tTCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\", \"BAD_OP\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n\n  breakwhile:\n    if (found_tag && !looking_for_tag) {\n\treturn TCL_OK;\n    }\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    \"missing tag in tag search expression\", TCL_INDEX_NONE));\n    Tcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"SEARCH\", \"NO_TAG\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchEvalExpr --\n *\n *\tThis recursive function is called to eval a tag expression.\n *\n * Results:\n *\tThe return value indicates if the tagOrId expression successfully\n *\tmatched the tags of the current item.\n *\n * Side effects:\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTagSearchEvalExpr(\n    TagSearchExpr *expr,\t/* Search expression */\n    Tk_Item *itemPtr)\t\t/* Item being test for match */\n{\n    int looking_for_tag;\t/* When true, scanner expects next char(s) to\n\t\t\t\t * be a tag, else operand expected. */\n    int negate_result;\t\t/* Pending negation of next tag value */\n    Tk_Uid uid;\n    Tk_Uid *tagPtr;\n    int count;\n    int result;\t\t\t/* Value of expr so far */\n    int parendepth;\n    SearchUids *searchUids;\t/* Collection of uids for basic search\n\t\t\t\t * expression terms. */\n\n    searchUids = GetStaticUids();\n    result = 0;\t\t\t/* Just to keep the compiler quiet. */\n\n    negate_result = 0;\n    looking_for_tag = 1;\n    while (expr->index < expr->length) {\n\tuid = expr->uids[expr->index++];\n\tif (looking_for_tag) {\n\t    if (uid == searchUids->tagvalUid) {\n/*\n *\t\tassert(expr->index < expr->length);\n */\n\t\tuid = expr->uids[expr->index++];\n\t\tresult = 0;\n\n\t\t/*\n\t\t * set result 1 if tag is found in item's tags\n\t\t */\n\n\t\tfor (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;\n\t\t\tcount > 0; tagPtr++, count--) {\n\t\t    if (*tagPtr == uid) {\n\t\t\tresult = 1;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\n\t    } else if (uid == searchUids->negtagvalUid) {\n\t\tnegate_result = ! negate_result;\n/*\n *\t\tassert(expr->index < expr->length);\n */\n\t\tuid = expr->uids[expr->index++];\n\t\tresult = 0;\n\n\t\t/*\n\t\t * set result 1 if tag is found in item's tags.\n\t\t */\n\n\t\tfor (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;\n\t\t\tcount > 0; tagPtr++, count--) {\n\t\t    if (*tagPtr == uid) {\n\t\t\tresult = 1;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\n\t    } else if (uid == searchUids->parenUid) {\n\t\t/*\n\t\t * Evaluate subexpressions with recursion.\n\t\t */\n\n\t\tresult = TagSearchEvalExpr(expr, itemPtr);\n\n\t    } else if (uid == searchUids->negparenUid) {\n\t\tnegate_result = !negate_result;\n\n\t\t/*\n\t\t * Evaluate subexpressions with recursion.\n\t\t */\n\n\t\tresult = TagSearchEvalExpr(expr, itemPtr);\n\t    }\n\t    if (negate_result) {\n\t\tresult = ! result;\n\t\tnegate_result = 0;\n\t    }\n\t    looking_for_tag = 0;\n\t} else {\t\t/* ! looking_for_tag */\n\t    if (((uid == searchUids->andUid) && (!result)) ||\n\t\t    ((uid == searchUids->orUid) && result)) {\n\t\t/*\n\t\t * Short circuit expression evaluation.\n\t\t *\n\t\t * if result before && is 0, or result before || is 1, then\n\t\t * the expression is decided and no further evaluation is\n\t\t * needed.\n\t\t */\n\n\t\tparendepth = 0;\n\t\twhile (expr->index < expr->length) {\n\t\t    uid = expr->uids[expr->index++];\n\t\t    if (uid == searchUids->tagvalUid ||\n\t\t\t    uid == searchUids->negtagvalUid) {\n\t\t\texpr->index++;\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (uid == searchUids->parenUid ||\n\t\t\t    uid == searchUids->negparenUid) {\n\t\t\tparendepth++;\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (uid == searchUids->endparenUid) {\n\t\t\tparendepth--;\n\t\t\tif (parendepth < 0) {\n\t\t\t    break;\n\t\t\t}\n\t\t    }\n\t\t}\n\t\treturn result;\n\n\t    } else if (uid == searchUids->xorUid) {\n\t\t/*\n\t\t * If the previous result was 1 then negate the next result.\n\t\t */\n\n\t\tnegate_result = result;\n\n\t    } else if (uid == searchUids->endparenUid) {\n\t\treturn result;\n\t    }\n\t    looking_for_tag = 1;\n\t}\n    }\n/*\n *  assert(!looking_for_tag);\n */\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchFirst --\n *\n *\tThis function is called to get the first item item that matches a\n *\tpreestablished search predicate that was set by TagSearchScan.\n *\n * Results:\n *\tThe return value is a pointer to the first item, or NULL if there is\n *\tno such item. The information at *searchPtr is updated such that\n *\tsuccessive calls to TagSearchNext will return successive items.\n *\n * Side effects:\n *\tSearchPtr is linked into a list of searches in progress on canvasPtr,\n *\tso that elements can safely be deleted while the search is in\n *\tprogress.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tk_Item *\nTagSearchFirst(\n    TagSearch *searchPtr)\t/* Record describing tag search */\n{\n    Tk_Item *itemPtr, *lastPtr;\n    Tk_Uid uid, *tagPtr;\n    int count;\n\n    /*\n     * Short circuit impossible searches for null tags.\n     */\n\n    if (searchPtr->stringLength == 0) {\n\treturn NULL;\n    }\n\n    /*\n     * Find the first matching item in one of several ways. If the tag is a\n     * number then it selects the single item with the matching identifier.\n     * In this case see if the item being requested is the hot item, in which\n     * case the search can be skipped.\n     */\n\n    if (searchPtr->type == SEARCH_TYPE_ID) {\n\tTcl_HashEntry *entryPtr;\n\n\titemPtr = searchPtr->canvasPtr->hotPtr;\n\tlastPtr = searchPtr->canvasPtr->hotPrevPtr;\n\tif ((itemPtr == NULL) || (itemPtr->id != searchPtr->id)\n\t\t|| (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) {\n\t    entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable,\n\t\t    INT2PTR(searchPtr->id));\n\t    if (entryPtr != NULL) {\n\t\titemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);\n\t\tlastPtr = itemPtr->prevPtr;\n\t    } else {\n\t\tlastPtr = itemPtr = NULL;\n\t    }\n\t}\n\tsearchPtr->lastPtr = lastPtr;\n\tsearchPtr->searchOver = 1;\n\tsearchPtr->canvasPtr->hotPtr = itemPtr;\n\tsearchPtr->canvasPtr->hotPrevPtr = lastPtr;\n\treturn itemPtr;\n    }\n\n    if (searchPtr->type == SEARCH_TYPE_ALL) {\n\t/*\n\t * All items match.\n\t */\n\n\tsearchPtr->lastPtr = NULL;\n\tsearchPtr->currentPtr = searchPtr->canvasPtr->firstItemPtr;\n\treturn searchPtr->canvasPtr->firstItemPtr;\n    }\n\n    if (searchPtr->type == SEARCH_TYPE_TAG) {\n\t/*\n\t * Optimized single-tag search\n\t */\n\n\tuid = searchPtr->expr->uid;\n\tfor (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;\n\t\titemPtr != NULL; lastPtr=itemPtr, itemPtr=itemPtr->nextPtr) {\n\t    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;\n\t\t    count > 0; tagPtr++, count--) {\n\t\tif (*tagPtr == uid) {\n\t\t    searchPtr->lastPtr = lastPtr;\n\t\t    searchPtr->currentPtr = itemPtr;\n\t\t    return itemPtr;\n\t\t}\n\t    }\n\t}\n    } else {\n\t/*\n\t * None of the above. Search for an item matching the tag expression.\n\t */\n\n\tfor (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;\n\t\titemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {\n\t    searchPtr->expr->index = 0;\n\t    if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {\n\t\tsearchPtr->lastPtr = lastPtr;\n\t\tsearchPtr->currentPtr = itemPtr;\n\t\treturn itemPtr;\n\t    }\n\t}\n    }\n    searchPtr->lastPtr = lastPtr;\n    searchPtr->searchOver = 1;\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagSearchNext --\n *\n *\tThis function returns successive items that match a given tag; it\n *\tshould be called only after TagSearchFirst has been used to begin a\n *\tsearch.\n *\n * Results:\n *\tThe return value is a pointer to the next item that matches the tag\n *\texpr specified to TagSearchScan, or NULL if no such item exists.\n *\t*SearchPtr is updated so that the next call to this function will\n *\treturn the next item.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tk_Item *\nTagSearchNext(\n    TagSearch *searchPtr)\t/* Record describing search in progress. */\n{\n    Tk_Item *itemPtr, *lastPtr;\n    Tk_Uid uid, *tagPtr;\n    int count;\n\n    /*\n     * Find next item in list (this may not actually be a suitable one to\n     * return), and return if there are no items left.\n     */\n\n    lastPtr = searchPtr->lastPtr;\n    if (lastPtr == NULL) {\n\titemPtr = searchPtr->canvasPtr->firstItemPtr;\n    } else {\n\titemPtr = lastPtr->nextPtr;\n    }\n    if ((itemPtr == NULL) || (searchPtr->searchOver)) {\n\tsearchPtr->searchOver = 1;\n\treturn NULL;\n    }\n    if (itemPtr != searchPtr->currentPtr) {\n\t/*\n\t * The structure of the list has changed. Probably the previously-\n\t * returned item was removed from the list. In this case, don't\n\t * advance lastPtr; just return its new successor (i.e. do nothing\n\t * here).\n\t */\n    } else {\n\tlastPtr = itemPtr;\n\titemPtr = lastPtr->nextPtr;\n    }\n\n    if (searchPtr->type == SEARCH_TYPE_ALL) {\n\t/*\n\t * All items match.\n\t */\n\n\tsearchPtr->lastPtr = lastPtr;\n\tsearchPtr->currentPtr = itemPtr;\n\treturn itemPtr;\n    }\n\n    if (searchPtr->type == SEARCH_TYPE_TAG) {\n\t/*\n\t * Optimized single-tag search\n\t */\n\n\tuid = searchPtr->expr->uid;\n\tfor (; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {\n\t    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;\n\t\t    count > 0; tagPtr++, count--) {\n\t\tif (*tagPtr == uid) {\n\t\t    searchPtr->lastPtr = lastPtr;\n\t\t    searchPtr->currentPtr = itemPtr;\n\t\t    return itemPtr;\n\t\t}\n\t    }\n\t}\n\tsearchPtr->lastPtr = lastPtr;\n\tsearchPtr->searchOver = 1;\n\treturn NULL;\n    }\n\n    /*\n     * Else.... evaluate tag expression\n     */\n\n    for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {\n\tsearchPtr->expr->index = 0;\n\tif (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {\n\t    searchPtr->lastPtr = lastPtr;\n\t    searchPtr->currentPtr = itemPtr;\n\t    return itemPtr;\n\t}\n    }\n    searchPtr->lastPtr = lastPtr;\n    searchPtr->searchOver = 1;\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DoItem --\n *\n *\tThis is a utility function called by FindItems. It either adds\n *\titemPtr's id to the list being constructed, or it adds a new tag to\n *\titemPtr, depending on the value of tag.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf tag is NULL then itemPtr's id is added as an element to the\n *\tsupplied object; otherwise tag is added to itemPtr's list of tags.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDoItem(\n    Tcl_Obj *accumObj,\t\t/* Object in which to (possibly) record item\n\t\t\t\t * id. */\n    Tk_Item *itemPtr,\t\t/* Item to (possibly) modify. */\n    Tk_Uid tag)\t\t\t/* Tag to add to those already present for\n\t\t\t\t * item, or NULL. */\n{\n    Tk_Uid *tagPtr;\n    int count;\n\n    /*\n     * Handle the \"add-to-result\" case and return, if appropriate.\n     */\n\n    if (tag == NULL) {\n\tTcl_ListObjAppendElement(NULL, accumObj, Tcl_NewWideIntObj(itemPtr->id));\n\treturn;\n    }\n\n    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;\n\t    count > 0; tagPtr++, count--) {\n\tif (tag == *tagPtr) {\n\t    return;\n\t}\n    }\n\n    /*\n     * Grow the tag space if there's no more room left in the current block.\n     */\n\n    if (itemPtr->tagSpace == itemPtr->numTags) {\n\tTk_Uid *newTagPtr;\n\n\titemPtr->tagSpace += 5;\n\tnewTagPtr = (Tk_Uid *)Tcl_Alloc(itemPtr->tagSpace * sizeof(Tk_Uid));\n\tmemcpy(newTagPtr, itemPtr->tagPtr,\n\t\titemPtr->numTags * sizeof(Tk_Uid));\n\tif (itemPtr->tagPtr != itemPtr->staticTagSpace) {\n\t    Tcl_Free(itemPtr->tagPtr);\n\t}\n\titemPtr->tagPtr = newTagPtr;\n\ttagPtr = &itemPtr->tagPtr[itemPtr->numTags];\n    }\n\n    /*\n     * Add in the new tag.\n     */\n\n    *tagPtr = tag;\n    itemPtr->numTags++;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FindItems --\n *\n *\tThis function does all the work of implementing the \"find\" and\n *\t\"addtag\" options of the canvas widget command, which locate items that\n *\thave certain features (location, tags, position in display list, etc.)\n *\n * Results:\n *\tA standard Tcl return value. If newTag is NULL, then a list of ids\n *\tfrom all the items that match objc/objv is returned in the interp's\n *\tresult. If newTag is NULL, then the normal the interp's result is an\n *\tempty string. If an error occurs, then the interp's result will hold\n *\tan error message.\n *\n * Side effects:\n *\tIf newTag is non-NULL, then all the items that match the information\n *\tin objc/objv have that tag added to their lists of tags.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nFindItems(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    TkCanvas *canvasPtr,\t/* Canvas whose items are to be searched. */\n    Tcl_Size objc,\t\t\t/* Number of entries in argv. Must be greater\n\t\t\t\t * than zero. */\n    Tcl_Obj *const *objv,\t/* Arguments that describe what items to\n\t\t\t\t * search for (see user doc on \"find\" and\n\t\t\t\t * \"addtag\" options). */\n    Tcl_Obj *newTag,\t\t/* If non-NULL, gives new tag to set on all\n\t\t\t\t * found items; if NULL, then ids of found\n\t\t\t\t * items are returned in the interp's\n\t\t\t\t * result. */\n    Tcl_Size first\t\t\t/* For error messages: gives number of\n\t\t\t\t * elements of objv which are already\n\t\t\t\t * handled. */\n    ,TagSearch **searchPtrPtr\t/* From CanvasWidgetCmd local vars*/\n    )\n{\n    Tk_Item *itemPtr;\n    Tk_Uid uid;\n    int index, result;\n    Tcl_Obj *resultObj;\n    static const char *const optionStrings[] = {\n\t\"above\", \"all\", \"below\", \"closest\",\n\t\"enclosed\", \"overlapping\", \"withtag\", NULL\n    };\n    enum options {\n\tCANV_ABOVE, CANV_ALL, CANV_BELOW, CANV_CLOSEST,\n\tCANV_ENCLOSED, CANV_OVERLAPPING, CANV_WITHTAG\n    };\n\n    if (newTag != NULL) {\n\tuid = Tk_GetUid(Tcl_GetString(newTag));\n    } else {\n\tuid = NULL;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[first], optionStrings,\n\t    \"search command\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch ((enum options) index) {\n    case CANV_ABOVE: {\n\tTk_Item *lastPtr = NULL;\n\n\tif (objc != first+2) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"tagOrId\");\n\t    return TCL_ERROR;\n\t}\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,\n\t\treturn TCL_ERROR) {\n\t    lastPtr = itemPtr;\n\t}\n\tif ((lastPtr != NULL) && (lastPtr->nextPtr != NULL)) {\n\t    resultObj = Tcl_NewObj();\n\t    DoItem(resultObj, lastPtr->nextPtr, uid);\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\tbreak;\n    }\n    case CANV_ALL:\n\tif (objc != first+1) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tresultObj = Tcl_NewObj();\n\tfor (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t\titemPtr = itemPtr->nextPtr) {\n\t    DoItem(resultObj, itemPtr, uid);\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n\n    case CANV_BELOW:\n\tif (objc != first+2) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"tagOrId\");\n\t    return TCL_ERROR;\n\t}\n\tFIRST_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,\n\t\treturn TCL_ERROR);\n\tif ((itemPtr != NULL) && (itemPtr->prevPtr != NULL)) {\n\t    resultObj = Tcl_NewObj();\n\t    DoItem(resultObj, itemPtr->prevPtr, uid);\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\tbreak;\n    case CANV_CLOSEST: {\n\tdouble closestDist;\n\tTk_Item *startPtr, *closestPtr;\n\tdouble coords[2], halo;\n\tint x1, y1, x2, y2;\n\n\tif ((objc < first+3) || (objc > first+5)) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"x y ?halo? ?start?\");\n\t    return TCL_ERROR;\n\t}\n\tif (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\tobjv[first+1], &coords[0]) != TCL_OK\n\t\t|| Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\tobjv[first+2], &coords[1]) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc > first+3) {\n\t    if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,\n\t\t    objv[first+3], &halo) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (halo < 0.0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't have negative halo value \\\"%f\\\"\", halo));\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    halo = 0.0;\n\t}\n\n\t/*\n\t * Find the item at which to start the search.\n\t */\n\n\tstartPtr = canvasPtr->firstItemPtr;\n\tif (objc == first+5) {\n\t    FIRST_CANVAS_ITEM_MATCHING(objv[first+4], searchPtrPtr,\n\t\t    return TCL_ERROR);\n\t    if (itemPtr != NULL) {\n\t\tstartPtr = itemPtr;\n\t    }\n\t}\n\n\t/*\n\t * The code below is optimized so that it can eliminate most items\n\t * without having to call their item-specific functions. This is done\n\t * by keeping a bounding box (x1, y1, x2, y2) that an item's bbox must\n\t * overlap if the item is to have any chance of being closer than the\n\t * closest so far.\n\t */\n\n\titemPtr = startPtr;\n\twhile(itemPtr && (itemPtr->state == TK_STATE_HIDDEN ||\n\t\t(itemPtr->state == TK_STATE_NULL &&\n\t\tcanvasPtr->canvas_state == TK_STATE_HIDDEN))) {\n\t    itemPtr = itemPtr->nextPtr;\n\t}\n\tif (itemPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tclosestDist = ItemPoint(canvasPtr, itemPtr, coords, halo);\n\twhile (1) {\n\t    double newDist;\n\n\t    /*\n\t     * Update the bounding box using itemPtr, which is the new closest\n\t     * item.\n\t     */\n\n\t    x1 = (int) (coords[0] - closestDist - halo - 1);\n\t    y1 = (int) (coords[1] - closestDist - halo - 1);\n\t    x2 = (int) (coords[0] + closestDist + halo + 1);\n\t    y2 = (int) (coords[1] + closestDist + halo + 1);\n\t    closestPtr = itemPtr;\n\n\t    /*\n\t     * Search for an item that beats the current closest one. Work\n\t     * circularly through the canvas's item list until getting back to\n\t     * the starting item.\n\t     */\n\n\t    while (1) {\n\t\titemPtr = itemPtr->nextPtr;\n\t\tif (itemPtr == NULL) {\n\t\t    itemPtr = canvasPtr->firstItemPtr;\n\t\t}\n\t\tif (itemPtr == startPtr) {\n\t\t    resultObj = Tcl_NewObj();\n\t\t    DoItem(resultObj, closestPtr, uid);\n\t\t    Tcl_SetObjResult(interp, resultObj);\n\t\t    return TCL_OK;\n\t\t}\n\t\tif (itemPtr->state == TK_STATE_HIDDEN ||\n\t\t\t(itemPtr->state == TK_STATE_NULL &&\n\t\t\tcanvasPtr->canvas_state == TK_STATE_HIDDEN)) {\n\t\t    continue;\n\t\t}\n\t\tif ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)\n\t\t\t|| (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {\n\t\t    continue;\n\t\t}\n\t\tnewDist = ItemPoint(canvasPtr, itemPtr, coords, halo);\n\t\tif (newDist <= closestDist) {\n\t\t    closestDist = newDist;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tbreak;\n    }\n    case CANV_ENCLOSED:\n\tif (objc != first+5) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"x1 y1 x2 y2\");\n\t    return TCL_ERROR;\n\t}\n\treturn FindArea(interp, canvasPtr, objv+first+1, uid, 1);\n    case CANV_OVERLAPPING:\n\tif (objc != first+5) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"x1 y1 x2 y2\");\n\t    return TCL_ERROR;\n\t}\n\treturn FindArea(interp, canvasPtr, objv+first+1, uid, 0);\n    case CANV_WITHTAG:\n\tif (objc != first+2) {\n\t    Tcl_WrongNumArgs(interp, first+1, objv, \"tagOrId\");\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tFOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr,\n\t\tgoto badWithTagSearch) {\n\t    DoItem(resultObj, itemPtr, uid);\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    badWithTagSearch:\n\tTcl_DecrRefCount(resultObj);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FindArea --\n *\n *\tThis function implements area searches for the \"find\" and \"addtag\"\n *\toptions.\n *\n * Results:\n *\tA standard Tcl return value. If newTag is NULL, then a list of ids\n *\tfrom all the items overlapping or enclosed by the rectangle given by\n *\tobjc is returned in the interp's result. If newTag is NULL, then the\n *\tnormal the interp's result is an empty string. If an error occurs,\n *\tthen the interp's result will hold an error message.\n *\n * Side effects:\n *\tIf uid is non-NULL, then all the items overlapping or enclosed by the\n *\tarea in objv have that tag added to their lists of tags.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nFindArea(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting and result\n\t\t\t\t * storing. */\n    TkCanvas *canvasPtr,\t/* Canvas whose items are to be searched. */\n    Tcl_Obj *const *objv,\t/* Array of four arguments that give the\n\t\t\t\t * coordinates of the rectangular area to\n\t\t\t\t * search. */\n    Tk_Uid uid,\t\t\t/* If non-NULL, gives new tag to set on all\n\t\t\t\t * found items; if NULL, then ids of found\n\t\t\t\t * items are returned in the interp's\n\t\t\t\t * result. */\n    int enclosed)\t\t/* 0 means overlapping or enclosed items are\n\t\t\t\t * OK, 1 means only enclosed items are OK. */\n{\n    double rect[4], tmp;\n    int x1, y1, x2, y2;\n    Tk_Item *itemPtr;\n    Tcl_Obj *resultObj;\n\n    if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[0],\n\t\t&rect[0]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[1],\n\t\t&rect[1]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[2],\n\t\t&rect[2]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp,(Tk_Canvas)canvasPtr,objv[3],\n\t\t&rect[3]) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (rect[0] > rect[2]) {\n\ttmp = rect[0]; rect[0] = rect[2]; rect[2] = tmp;\n    }\n    if (rect[1] > rect[3]) {\n\ttmp = rect[1]; rect[1] = rect[3]; rect[3] = tmp;\n    }\n\n    /*\n     * Use an integer bounding box for a quick test, to avoid calling\n     * item-specific code except for items that are close.\n     */\n\n    x1 = (int) (rect[0] - 1.0);\n    y1 = (int) (rect[1] - 1.0);\n    x2 = (int) (rect[2] + 1.0);\n    y2 = (int) (rect[3] + 1.0);\n    resultObj = Tcl_NewObj();\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif (itemPtr->state == TK_STATE_HIDDEN ||\n\t\t(itemPtr->state == TK_STATE_NULL\n\t\t&& canvasPtr->canvas_state == TK_STATE_HIDDEN)) {\n\t    continue;\n\t}\n\tif ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)\n\t\t|| (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {\n\t    continue;\n\t}\n\tif (ItemOverlap(canvasPtr, itemPtr, rect) >= enclosed) {\n\t    DoItem(resultObj, itemPtr, uid);\n\t}\n    }\n    Tcl_SetObjResult(interp, resultObj);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RelinkItems --\n *\n *\tMove one or more items to a different place in the display order for a\n *\tcanvas.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe items identified by \"tag\" are moved so that they are all together\n *\tin the display list and immediately after prevPtr. The order of the\n *\tmoved items relative to each other is not changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nRelinkItems(\n    TkCanvas *canvasPtr,\t/* Canvas to be modified. */\n    Tcl_Obj *tag,\t\t/* Tag identifying items to be moved in the\n\t\t\t\t * redisplay list. */\n    Tk_Item *prevPtr,\t\t/* Reposition the items so that they go just\n\t\t\t\t * after this item (NULL means put at\n\t\t\t\t * beginning of list). */\n    TagSearch **searchPtrPtr)\t/* From CanvasWidgetCmd local vars */\n{\n    Tk_Item *itemPtr;\n    Tk_Item *firstMovePtr, *lastMovePtr;\n    int result;\n\n    /*\n     * Find all of the items to be moved and remove them from the list, making\n     * an auxiliary list running from firstMovePtr to lastMovePtr. Record\n     * their areas for redisplay.\n     */\n\n    firstMovePtr = lastMovePtr = NULL;\n    FOR_EVERY_CANVAS_ITEM_MATCHING(tag, searchPtrPtr, return TCL_ERROR) {\n\tif (itemPtr == prevPtr) {\n\t    /*\n\t     * Item after which insertion is to occur is being moved! Switch\n\t     * to insert after its predecessor.\n\t     */\n\n\t    prevPtr = prevPtr->prevPtr;\n\t}\n\tif (itemPtr->prevPtr == NULL) {\n\t    if (itemPtr->nextPtr != NULL) {\n\t\titemPtr->nextPtr->prevPtr = NULL;\n\t    }\n\t    canvasPtr->firstItemPtr = itemPtr->nextPtr;\n\t} else {\n\t    if (itemPtr->nextPtr != NULL) {\n\t\titemPtr->nextPtr->prevPtr = itemPtr->prevPtr;\n\t    }\n\t    itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;\n\t}\n\tif (canvasPtr->lastItemPtr == itemPtr) {\n\t    canvasPtr->lastItemPtr = itemPtr->prevPtr;\n\t}\n\tif (firstMovePtr == NULL) {\n\t    itemPtr->prevPtr = NULL;\n\t    firstMovePtr = itemPtr;\n\t} else {\n\t    itemPtr->prevPtr = lastMovePtr;\n\t    lastMovePtr->nextPtr = itemPtr;\n\t}\n\tlastMovePtr = itemPtr;\n\tEventuallyRedrawItem(canvasPtr, itemPtr);\n\tcanvasPtr->flags |= REPICK_NEEDED;\n    }\n\n    /*\n     * Insert the list of to-be-moved items back into the canvas's at the\n     * desired position.\n     */\n\n    if (firstMovePtr == NULL) {\n\treturn TCL_OK;\n    }\n    if (prevPtr == NULL) {\n\tif (canvasPtr->firstItemPtr != NULL) {\n\t    canvasPtr->firstItemPtr->prevPtr = lastMovePtr;\n\t}\n\tlastMovePtr->nextPtr = canvasPtr->firstItemPtr;\n\tcanvasPtr->firstItemPtr = firstMovePtr;\n    } else {\n\tif (prevPtr->nextPtr != NULL) {\n\t    prevPtr->nextPtr->prevPtr = lastMovePtr;\n\t}\n\tlastMovePtr->nextPtr = prevPtr->nextPtr;\n\tif (firstMovePtr != NULL) {\n\t    firstMovePtr->prevPtr = prevPtr;\n\t}\n\tprevPtr->nextPtr = firstMovePtr;\n    }\n    if (canvasPtr->lastItemPtr == prevPtr) {\n\tcanvasPtr->lastItemPtr = lastMovePtr;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasBindProc --\n *\n *\tThis function is invoked by the Tk dispatcher to handle events\n *\tassociated with bindings on items.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the command invoked as part of the binding (if there was\n *\tany).\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCanvasBindProc(\n    void *clientData,\t/* Pointer to canvas structure. */\n    XEvent *eventPtr)\t\t/* Pointer to X event that just happened. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n    unsigned mask;\n\n    Tcl_Preserve(canvasPtr);\n\n    /*\n     * This code below keeps track of the current modifier state in\n     * canvasPtr>state. This information is used to defer repicks of the\n     * current item while buttons are down.\n     */\n\n    switch (eventPtr->type) {\n    case ButtonPress:\n    case ButtonRelease:\n\tmask = Tk_GetButtonMask(eventPtr->xbutton.button);\n\n\t/*\n\t * For button press events, repick the current item using the button\n\t * state before the event, then process the event. For button release\n\t * events, first process the event, then repick the current item using\n\t * the button state *after* the event (the button has logically gone\n\t * up before we change the current item).\n\t */\n\n\tif (eventPtr->type == ButtonPress) {\n\t    /*\n\t     * On a button press, first repick the current item using the\n\t     * button state before the event, the process the event.\n\t     */\n\n\t    canvasPtr->state = eventPtr->xbutton.state;\n\t    PickCurrentItem(canvasPtr, eventPtr);\n\t    canvasPtr->state ^= mask;\n\t    CanvasDoEvent(canvasPtr, eventPtr);\n\t} else {\n\t    /*\n\t     * Button release: first process the event, with the button still\n\t     * considered to be down. Then repick the current item under the\n\t     * assumption that the button is no longer down.\n\t     */\n\n\t    canvasPtr->state = eventPtr->xbutton.state;\n\t    CanvasDoEvent(canvasPtr, eventPtr);\n\t    eventPtr->xbutton.state ^= mask;\n\t    canvasPtr->state = eventPtr->xbutton.state;\n\t    PickCurrentItem(canvasPtr, eventPtr);\n\t    eventPtr->xbutton.state ^= mask;\n\t}\n\tbreak;\n    case EnterNotify:\n    case LeaveNotify:\n\tcanvasPtr->state = eventPtr->xcrossing.state;\n\tPickCurrentItem(canvasPtr, eventPtr);\n\tbreak;\n    case MotionNotify:\n\tcanvasPtr->state = eventPtr->xmotion.state;\n\tPickCurrentItem(canvasPtr, eventPtr);\n\t/* fallthrough */\n    default:\n\tCanvasDoEvent(canvasPtr, eventPtr);\n    }\n\n    Tcl_Release(canvasPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PickCurrentItem --\n *\n *\tFind the topmost item in a canvas that contains a given location and\n *\tmark the the current item. If the current item has changed, generate a\n *\tfake exit event on the old current item, a fake enter event on the new\n *\tcurrent item item and force a redraw of the two items. Canvas items\n *\tthat are hidden or disabled are ignored.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe current item for canvasPtr may change. If it does, then the\n *\tcommands associated with item entry and exit could do just about\n *\tanything. A binding script could delete the canvas, so callers should\n *\tprotect themselves with Tcl_Preserve and Tcl_Release.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPickCurrentItem(\n    TkCanvas *canvasPtr,\t/* Canvas widget in which to select current\n\t\t\t\t * item. */\n    XEvent *eventPtr)\t\t/* Event describing location of mouse cursor.\n\t\t\t\t * Must be EnterWindow, LeaveWindow,\n\t\t\t\t * ButtonRelease, or MotionNotify. */\n{\n    double coords[2];\n    unsigned int buttonDown;\n    Tk_Item *prevItemPtr;\n    SearchUids *searchUids = GetStaticUids();\n\n    /*\n     * Check whether or not a button is down. If so, we'll log entry and exit\n     * into and out of the current item, but not entry into any other item.\n     * This implements a form of grabbing equivalent to what the X server does\n     * for windows.\n     */\n\n    buttonDown = canvasPtr->state & ALL_BUTTONS;\n\n    /*\n     * Save information about this event in the canvas. The event in the\n     * canvas is used for two purposes:\n     *\n     * 1. Event bindings: if the current item changes, fake events are\n     *    generated to allow item-enter and item-leave bindings to trigger.\n     * 2. Reselection: if the current item gets deleted, can use the saved\n     *    event to find a new current item.\n     *\n     * Translate MotionNotify events into EnterNotify events, since that's\n     * what gets reported to item handlers.\n     */\n\n    if (eventPtr != &canvasPtr->pickEvent) {\n\tif ((eventPtr->type == MotionNotify)\n\t\t|| (eventPtr->type == ButtonRelease)) {\n\t    canvasPtr->pickEvent.xcrossing.type = EnterNotify;\n\t    canvasPtr->pickEvent.xcrossing.serial = eventPtr->xmotion.serial;\n\t    canvasPtr->pickEvent.xcrossing.send_event\n\t\t    = eventPtr->xmotion.send_event;\n\t    canvasPtr->pickEvent.xcrossing.display = eventPtr->xmotion.display;\n\t    canvasPtr->pickEvent.xcrossing.window = eventPtr->xmotion.window;\n\t    canvasPtr->pickEvent.xcrossing.root = eventPtr->xmotion.root;\n\t    canvasPtr->pickEvent.xcrossing.subwindow = None;\n\t    canvasPtr->pickEvent.xcrossing.time = eventPtr->xmotion.time;\n\t    canvasPtr->pickEvent.xcrossing.x = eventPtr->xmotion.x;\n\t    canvasPtr->pickEvent.xcrossing.y = eventPtr->xmotion.y;\n\t    canvasPtr->pickEvent.xcrossing.x_root = eventPtr->xmotion.x_root;\n\t    canvasPtr->pickEvent.xcrossing.y_root = eventPtr->xmotion.y_root;\n\t    canvasPtr->pickEvent.xcrossing.mode = NotifyNormal;\n\t    canvasPtr->pickEvent.xcrossing.detail = NotifyNonlinear;\n\t    canvasPtr->pickEvent.xcrossing.same_screen =\n\t\t    eventPtr->xmotion.same_screen;\n\t    canvasPtr->pickEvent.xcrossing.focus = False;\n\t    canvasPtr->pickEvent.xcrossing.state = eventPtr->xmotion.state;\n\t} else {\n\t    canvasPtr->pickEvent = *eventPtr;\n\t}\n    }\n\n    /*\n     * If this is a recursive call (there's already a partially completed call\n     * pending on the stack; it's in the middle of processing a Leave event\n     * handler for the old current item) then just return; the pending call\n     * will do everything that's needed.\n     */\n\n    if (canvasPtr->flags & REPICK_IN_PROGRESS) {\n\treturn;\n    }\n\n    /*\n     * A LeaveNotify event automatically means that there's no current object,\n     * so the check for closest item can be skipped.\n     */\n\n    coords[0] = canvasPtr->pickEvent.xcrossing.x + canvasPtr->xOrigin;\n    coords[1] = canvasPtr->pickEvent.xcrossing.y + canvasPtr->yOrigin;\n    if (canvasPtr->pickEvent.type != LeaveNotify) {\n\tcanvasPtr->newCurrentPtr = CanvasFindClosest(canvasPtr, coords);\n    } else {\n\tcanvasPtr->newCurrentPtr = NULL;\n    }\n\n    if ((canvasPtr->newCurrentPtr == canvasPtr->currentItemPtr)\n\t    && !(canvasPtr->flags & LEFT_GRABBED_ITEM)) {\n\t/*\n\t * Nothing to do: the current item hasn't changed.\n\t */\n\n\treturn;\n    }\n\n    if (!buttonDown) {\n\tcanvasPtr->flags &= ~LEFT_GRABBED_ITEM;\n    }\n\n    /*\n     * Simulate a LeaveNotify event on the previous current item and an\n     * EnterNotify event on the new current item. Remove the \"current\" tag\n     * from the previous current item and place it on the new current item.\n     */\n\n    if ((canvasPtr->newCurrentPtr != canvasPtr->currentItemPtr)\n\t    && (canvasPtr->currentItemPtr != NULL)\n\t    && !(canvasPtr->flags & LEFT_GRABBED_ITEM)) {\n\tXEvent event;\n\tTk_Item *itemPtr = canvasPtr->currentItemPtr;\n\tTcl_Size i;\n\n\tevent = canvasPtr->pickEvent;\n\tevent.type = LeaveNotify;\n\n\t/*\n\t * Behaviour before ticket #47d4f29159:\n\t *    If the event's detail happens to be NotifyInferior the binding\n\t *    mechanism will discard the event. To be consistent, always use\n\t *    NotifyAncestor.\n\t *\n\t * Behaviour after ticket #47d4f29159:\n\t *    The binding mechanism doesn't discard events with detail field\n\t *    NotifyInferior anymore. It would be best to base the detail\n\t *    field on the ancestry relationship between the old and new\n\t *    canvas items. For the time being, retain the choice from before\n\t *    ticket #47d4f29159, which doesn't harm.\n\t */\n\n\tevent.xcrossing.detail = NotifyAncestor;\n\tcanvasPtr->flags |= REPICK_IN_PROGRESS;\n\tCanvasDoEvent(canvasPtr, &event);\n\tcanvasPtr->flags &= ~REPICK_IN_PROGRESS;\n\n\t/*\n\t * The check below is needed because there could be an event handler\n\t * for <LeaveNotify> that deletes the current item.\n\t */\n\n\tif ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) {\n\t    for (i = itemPtr->numTags-1; i != TCL_INDEX_NONE; i--) {\n\t\tif (itemPtr->tagPtr[i] == searchUids->currentUid)\n\t\t    /* then */ {\n\t\t    memmove((void *)(itemPtr->tagPtr + i),\n\t\t\t    itemPtr->tagPtr + i + 1,\n\t\t\t    (itemPtr->numTags - (i+1)) * sizeof(Tk_Uid));\n\t\t    itemPtr->numTags--;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Note: during CanvasDoEvent above, it's possible that\n\t * canvasPtr->newCurrentPtr got reset to NULL because the item was\n\t * deleted.\n\t */\n    }\n    if ((canvasPtr->newCurrentPtr!=canvasPtr->currentItemPtr) && buttonDown) {\n\tcanvasPtr->flags |= LEFT_GRABBED_ITEM;\n\treturn;\n    }\n\n    /*\n     * Special note: it's possible that canvasPtr->newCurrentPtr ==\n     * canvasPtr->currentItemPtr here. This can happen, for example, if\n     * LEFT_GRABBED_ITEM was set.\n     */\n\n    prevItemPtr = canvasPtr->currentItemPtr;\n    canvasPtr->flags &= ~LEFT_GRABBED_ITEM;\n    canvasPtr->currentItemPtr = canvasPtr->newCurrentPtr;\n    if (prevItemPtr != NULL && prevItemPtr != canvasPtr->currentItemPtr &&\n\t    (prevItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT)) {\n\tEventuallyRedrawItem(canvasPtr, prevItemPtr);\n\tItemConfigure(canvasPtr, prevItemPtr, 0, NULL);\n    }\n    if (canvasPtr->currentItemPtr != NULL) {\n\tXEvent event;\n\n\tDoItem(NULL, canvasPtr->currentItemPtr, searchUids->currentUid);\n\tif ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT\n\t\t&& prevItemPtr != canvasPtr->currentItemPtr)) {\n\t    ItemConfigure(canvasPtr, canvasPtr->currentItemPtr, 0, NULL);\n\t    EventuallyRedrawItem(canvasPtr, canvasPtr->currentItemPtr);\n\t}\n\tevent = canvasPtr->pickEvent;\n\tevent.type = EnterNotify;\n\tevent.xcrossing.detail = NotifyAncestor;\n\tCanvasDoEvent(canvasPtr, &event);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasFindClosest --\n *\n *\tGiven x and y coordinates, find the topmost canvas item that is\n *\t\"close\" to the coordinates. Canvas items that are hidden or disabled\n *\tare ignored.\n *\n * Results:\n *\tThe return value is a pointer to the topmost item that is close to\n *\t(x,y), or NULL if no item is close.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_Item *\nCanvasFindClosest(\n    TkCanvas *canvasPtr,\t/* Canvas widget to search. */\n    double coords[2])\t\t/* Desired x,y position in canvas, not screen,\n\t\t\t\t * coordinates.) */\n{\n    Tk_Item *itemPtr;\n    Tk_Item *bestPtr;\n    int x1, y1, x2, y2;\n\n    x1 = (int) (coords[0] - canvasPtr->closeEnough);\n    y1 = (int) (coords[1] - canvasPtr->closeEnough);\n    x2 = (int) (coords[0] + canvasPtr->closeEnough);\n    y2 = (int) (coords[1] + canvasPtr->closeEnough);\n\n    bestPtr = NULL;\n    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;\n\t    itemPtr = itemPtr->nextPtr) {\n\tif (itemPtr->state == TK_STATE_HIDDEN ||\n\t\titemPtr->state==TK_STATE_DISABLED ||\n\t\t(itemPtr->state == TK_STATE_NULL &&\n\t\t(canvasPtr->canvas_state == TK_STATE_HIDDEN ||\n\t\tcanvasPtr->canvas_state == TK_STATE_DISABLED))) {\n\t    continue;\n\t}\n\tif ((itemPtr->x1 > x2) || (itemPtr->x2 < x1)\n\t\t|| (itemPtr->y1 > y2) || (itemPtr->y2 < y1)) {\n\t    continue;\n\t}\n\tif (ItemPoint(canvasPtr,itemPtr,coords,0) <= canvasPtr->closeEnough) {\n\t    bestPtr = itemPtr;\n\t}\n    }\n    return bestPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasDoEvent --\n *\n *\tThis function is called to invoke binding processing for a new event\n *\tthat is associated with the current item for a canvas.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the bindings for the canvas. A binding script could delete\n *\tthe canvas, so callers should protect themselves with Tcl_Preserve and\n *\tTcl_Release.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCanvasDoEvent(\n    TkCanvas *canvasPtr,\t/* Canvas widget in which event occurred. */\n    XEvent *eventPtr)\t\t/* Real or simulated X event that is to be\n\t\t\t\t * processed. */\n{\n#define NUM_STATIC 3\n    void *staticObjects[NUM_STATIC];\n    void **objectPtr;\n    Tcl_Size numObjects, i;\n    Tk_Item *itemPtr;\n    TagSearchExpr *expr;\n    Tcl_Size numExprs;\n    SearchUids *searchUids = GetStaticUids();\n\n    if (canvasPtr->bindingTable == NULL) {\n\treturn;\n    }\n\n    itemPtr = canvasPtr->currentItemPtr;\n    if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) {\n\titemPtr = canvasPtr->textInfo.focusItemPtr;\n    }\n    if (itemPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Set up an array with all the relevant objects for processing this\n     * event. The relevant objects are:\n     * (a) the event's item,\n     * (b) the tags associated with the event's item,\n     * (c) the expressions that are true for the event's item's tags, and\n     * (d) the tag \"all\".\n     *\n     * If there are a lot of tags then malloc an array to hold all of the\n     * objects.\n     */\n\n    /*\n     * Flag and count all expressions that match item's tags.\n     */\n\n    numExprs = 0;\n    expr = canvasPtr->bindTagExprs;\n    while (expr) {\n\texpr->index = 0;\n\texpr->match = TagSearchEvalExpr(expr, itemPtr);\n\tif (expr->match) {\n\t    numExprs++;\n\t}\n\texpr = expr->next;\n    }\n\n    numObjects = itemPtr->numTags + numExprs + 2;\n    if (numObjects <= NUM_STATIC) {\n\tobjectPtr = staticObjects;\n    } else {\n\tobjectPtr = (void **)Tcl_Alloc(numObjects * sizeof(void *));\n    }\n    objectPtr[0] = (char *)searchUids->allUid;\n    for (i = itemPtr->numTags - 1; i != TCL_INDEX_NONE; i--) {\n\tobjectPtr[i+1] = (char *)itemPtr->tagPtr[i];\n    }\n    objectPtr[itemPtr->numTags + 1] = itemPtr;\n\n    /*\n     * Copy uids of matching expressions into object array\n     */\n\n    i = itemPtr->numTags+2;\n    expr = canvasPtr->bindTagExprs;\n    while (expr) {\n\tif (expr->match) {\n\t    objectPtr[i++] = (int *) expr->uid;\n\t}\n\texpr = expr->next;\n    }\n\n    /*\n     * Invoke the binding system, then free up the object array if it was\n     * malloc-ed.\n     */\n\n    if (canvasPtr->tkwin != NULL) {\n\tTk_BindEvent(canvasPtr->bindingTable, eventPtr, canvasPtr->tkwin,\n\t\tnumObjects, objectPtr);\n    }\n    if (objectPtr != staticObjects) {\n\tTcl_Free(objectPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasBlinkProc --\n *\n *\tThis function is called as a timer handler to blink the insertion\n *\tcursor off and on.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor gets turned on or off, redisplay gets invoked, and this\n *\tfunction reschedules itself.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasBlinkProc(\n    void *clientData)\t/* Pointer to record describing entry. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n\n    if (!canvasPtr->textInfo.gotFocus || (canvasPtr->insertOffTime == 0)) {\n\treturn;\n    }\n    if (canvasPtr->textInfo.cursorOn) {\n\tcanvasPtr->textInfo.cursorOn = 0;\n\tcanvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\tcanvasPtr->insertOffTime, CanvasBlinkProc, canvasPtr);\n    } else {\n\tcanvasPtr->textInfo.cursorOn = 1;\n\tcanvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\tcanvasPtr->insertOnTime, CanvasBlinkProc, canvasPtr);\n    }\n    EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasFocusProc --\n *\n *\tThis function is called whenever a canvas gets or loses the input\n *\tfocus. It's also called whenever the window is reconfigured while it\n *\thas the focus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor gets turned on or off.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasFocusProc(\n    TkCanvas *canvasPtr,\t/* Canvas that just got or lost focus. */\n    int gotFocus)\t\t/* 1 means window is getting focus, 0 means\n\t\t\t\t * it's losing it. */\n{\n    int highlightWidth;\n\n    Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);\n    if (gotFocus) {\n\tcanvasPtr->textInfo.gotFocus = 1;\n\tcanvasPtr->textInfo.cursorOn = 1;\n\tif (canvasPtr->insertOffTime != 0) {\n\t    canvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\t    canvasPtr->insertOffTime, CanvasBlinkProc, canvasPtr);\n\t}\n    } else {\n\tcanvasPtr->textInfo.gotFocus = 0;\n\tcanvasPtr->textInfo.cursorOn = 0;\n\tcanvasPtr->insertBlinkHandler = NULL;\n    }\n    EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->highlightWidthObj, &highlightWidth);\n    if (highlightWidth > 0) {\n\tcanvasPtr->flags |= REDRAW_BORDERS;\n\tif (!(canvasPtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(DisplayCanvas, canvasPtr);\n\t    canvasPtr->flags |= REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasSelectTo --\n *\n *\tModify the selection by moving its un-anchored end. This could make\n *\tthe selection either larger or smaller.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe selection changes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasSelectTo(\n    TkCanvas *canvasPtr,\t/* Information about widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is to hold selection. */\n    Tcl_Size index)\t\t\t/* Index of element that is to become the\n\t\t\t\t * \"other\" end of the selection. */\n{\n    Tcl_Size oldFirst, oldLast;\n    Tk_Item *oldSelPtr;\n\n    oldFirst = canvasPtr->textInfo.selectFirst;\n    oldLast = canvasPtr->textInfo.selectLast;\n    oldSelPtr = canvasPtr->textInfo.selItemPtr;\n\n    /*\n     * Grab the selection if we don't own it already.\n     */\n\n    if (canvasPtr->textInfo.selItemPtr == NULL) {\n\tTk_OwnSelection(canvasPtr->tkwin, XA_PRIMARY, CanvasLostSelection,\n\t\tcanvasPtr);\n    } else if (canvasPtr->textInfo.selItemPtr != itemPtr) {\n\tEventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);\n    }\n    canvasPtr->textInfo.selItemPtr = itemPtr;\n\n    if (canvasPtr->textInfo.anchorItemPtr != itemPtr) {\n\tcanvasPtr->textInfo.anchorItemPtr = itemPtr;\n\tcanvasPtr->textInfo.selectAnchor = index;\n    }\n    if (canvasPtr->textInfo.selectAnchor <= index) {\n\tcanvasPtr->textInfo.selectFirst = canvasPtr->textInfo.selectAnchor;\n\tcanvasPtr->textInfo.selectLast = index;\n    } else {\n\tcanvasPtr->textInfo.selectFirst = ((int)index < 0) ? TCL_INDEX_NONE : index;\n\tcanvasPtr->textInfo.selectLast = canvasPtr->textInfo.selectAnchor - 1;\n    }\n    if ((canvasPtr->textInfo.selectFirst != oldFirst)\n\t    || (canvasPtr->textInfo.selectLast != oldLast)\n\t    || (itemPtr != oldSelPtr)) {\n\tEventuallyRedrawItem(canvasPtr, itemPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasFetchSelection --\n *\n *\tThis function is invoked by Tk to return part or all of the selection,\n *\twhen the selection is in a canvas widget. This function always returns\n *\tthe selection as a STRING.\n *\n * Results:\n *\tThe return value is the number of non-NULL bytes stored at buffer.\n *\tBuffer is filled (or partially filled) with a NULL-terminated string\n *\tcontaining part or all of the selection, as given by offset and\n *\tmaxBytes.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Size\nCanvasFetchSelection(\n    void *clientData,\t/* Information about canvas widget. */\n    Tcl_Size offset,\t\t\t/* Offset within selection of first character\n\t\t\t\t * to be returned. */\n    char *buffer,\t\t/* Location in which to place selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum number of bytes to place at buffer,\n\t\t\t\t * not including terminating NULL\n\t\t\t\t * character. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n\n    return ItemSelection(canvasPtr, canvasPtr->textInfo.selItemPtr, offset,\n\t    buffer, maxBytes);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CanvasLostSelection --\n *\n *\tThis function is called back by Tk when the selection is grabbed away\n *\tfrom a canvas widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe existing selection is unhighlighted, and the window is marked as\n *\tnot containing a selection.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCanvasLostSelection(\n    void *clientData)\t/* Information about entry widget. */\n{\n    TkCanvas *canvasPtr = (TkCanvas *)clientData;\n\n    EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);\n    canvasPtr->textInfo.selItemPtr = NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GridAlign --\n *\n *\tGiven a coordinate and a grid spacing, this function computes the\n *\tlocation of the nearest grid line to the coordinate.\n *\n * Results:\n *\tThe return value is the location of the grid line nearest to coord.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nGridAlign(\n    double coord,\t\t/* Coordinate to grid-align. */\n    double spacing)\t\t/* Spacing between grid lines. If <= 0 then no\n\t\t\t\t * alignment is done. */\n{\n    if (spacing <= 0.0) {\n\treturn coord;\n    }\n    if (coord < 0) {\n\treturn -((int) ((-coord)/spacing + 0.5)) * spacing;\n    }\n    return ((int) (coord/spacing + 0.5)) * spacing;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScrollFractions --\n *\n *\tGiven the range that's visible in the window and the \"100% range\" for\n *\twhat's in the canvas, return a list of two doubles representing the\n *\tscroll fractions. This function is used for both x and y scrolling.\n *\n * Results:\n *\tA List Tcl_Obj with two real numbers (Double Tcl_Objs) containing the\n *\tscroll fractions (between 0 and 1) corresponding to the other\n *\targuments.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nScrollFractions(\n    int screen1,\t\t/* Lowest coordinate visible in the window. */\n    int screen2,\t\t/* Highest coordinate visible in the window. */\n    int object1,\t\t/* Lowest coordinate in the object. */\n    int object2)\t\t/* Highest coordinate in the object. */\n{\n    Tcl_Obj *buffer[2];\n    double range, f1, f2;\n\n    range = object2 - object1;\n    if (range <= 0) {\n\tf1 = 0;\n\tf2 = 1.0;\n    } else {\n\tf1 = (screen1 - object1)/range;\n\tif (f1 < 0) {\n\t    f1 = 0.0;\n\t}\n\tf2 = (screen2 - object1)/range;\n\tif (f2 > 1.0) {\n\t    f2 = 1.0;\n\t}\n\tif (f2 < f1) {\n\t    f2 = f1;\n\t}\n    }\n    buffer[0] = Tcl_NewDoubleObj(f1);\n    buffer[1] = Tcl_NewDoubleObj(f2);\n    return Tcl_NewListObj(2, buffer);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasUpdateScrollbars --\n *\n *\tThis function is invoked whenever a canvas has changed in a way that\n *\trequires scrollbars to be redisplayed (e.g. the view in the canvas has\n *\tchanged).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there are scrollbars associated with the canvas, then their\n *\tscrolling commands are invoked to cause them to redisplay. If errors\n *\toccur, additional Tcl commands may be invoked to process the errors.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCanvasUpdateScrollbars(\n    TkCanvas *canvasPtr)\t\t/* Information about canvas. */\n{\n    int result;\n    Tcl_Interp *interp;\n    int xOrigin, yOrigin, inset, width, height;\n    int scrollX1, scrollX2, scrollY1, scrollY2;\n    Tcl_Obj *xScrollCmdObj, *yScrollCmdObj;\n    Tcl_DString buf;\n\n    /*\n     * Preserve the relevant values from the canvasPtr, because it might be\n     * deleted as part of either of the two calls to Tcl_EvalEx below.\n     */\n\n    interp = canvasPtr->interp;\n    Tcl_Preserve(interp);\n    xScrollCmdObj = canvasPtr->xScrollCmdObj;\n    if (xScrollCmdObj != NULL) {\n\tTcl_IncrRefCount(xScrollCmdObj);\n    }\n    yScrollCmdObj = canvasPtr->yScrollCmdObj;\n    if (yScrollCmdObj != NULL) {\n\tTcl_IncrRefCount(yScrollCmdObj);\n    }\n    xOrigin = canvasPtr->xOrigin;\n    yOrigin = canvasPtr->yOrigin;\n    inset = canvasPtr->inset;\n    width = Tk_Width(canvasPtr->tkwin);\n    height = Tk_Height(canvasPtr->tkwin);\n    scrollX1 = canvasPtr->scrollX1;\n    scrollX2 = canvasPtr->scrollX2;\n    scrollY1 = canvasPtr->scrollY1;\n    scrollY2 = canvasPtr->scrollY2;\n    canvasPtr->flags &= ~UPDATE_SCROLLBARS;\n    if (canvasPtr->xScrollCmdObj != NULL) {\n\tTcl_Obj *fractions = ScrollFractions(xOrigin + inset,\n\t\txOrigin + width - inset, scrollX1, scrollX2);\n\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(xScrollCmdObj), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, Tcl_GetString(fractions), TCL_INDEX_NONE);\n\tresult = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tTcl_DecrRefCount(fractions);\n\tif (result != TCL_OK) {\n\t    Tcl_BackgroundException(interp, result);\n\t}\n\tTcl_ResetResult(interp);\n\tTcl_DecrRefCount(xScrollCmdObj);\n    }\n\n    if (yScrollCmdObj != NULL) {\n\tTcl_Obj *fractions = ScrollFractions(yOrigin + inset,\n\t\tyOrigin + height - inset, scrollY1, scrollY2);\n\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(yScrollCmdObj), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, Tcl_GetString(fractions), TCL_INDEX_NONE);\n\tresult = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tTcl_DecrRefCount(fractions);\n\tif (result != TCL_OK) {\n\t    Tcl_BackgroundException(interp, result);\n\t}\n\tTcl_ResetResult(interp);\n\tTcl_DecrRefCount(yScrollCmdObj);\n    }\n    Tcl_Release(interp);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CanvasSetOrigin --\n *\n *\tThis function is invoked to change the mapping between canvas\n *\tcoordinates and screen coordinates in the canvas window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe canvas will be redisplayed to reflect the change in view. In\n *\taddition, scrollbars will be updated if there are any.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCanvasSetOrigin(\n    TkCanvas *canvasPtr,\t/* Information about canvas. */\n    int xOrigin,\t\t/* New X origin for canvas (canvas x-coord\n\t\t\t\t * corresponding to left edge of canvas\n\t\t\t\t * window). */\n    int yOrigin)\t\t/* New Y origin for canvas (canvas y-coord\n\t\t\t\t * corresponding to top edge of canvas\n\t\t\t\t * window). */\n{\n    int left, right, top, bottom, delta;\n    int xScrollIncrement, yScrollIncrement;\n\n    /*\n     * If scroll increments have been set, round the window origin to the\n     * nearest multiple of the increments. Remember, the origin is the place\n     * just inside the borders, not the upper left corner.\n     */\n\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->xScrollIncrementObj, &xScrollIncrement);\n    Tk_GetPixelsFromObj(NULL, canvasPtr->tkwin, canvasPtr->yScrollIncrementObj, &yScrollIncrement);\n    if (xScrollIncrement > 0) {\n\tif (xOrigin >= 0) {\n\t    xOrigin += xScrollIncrement/2;\n\t    xOrigin -= (xOrigin + canvasPtr->inset)\n\t\t    % xScrollIncrement;\n\t} else {\n\t    xOrigin = (-xOrigin) + xScrollIncrement/2;\n\t    xOrigin = -(xOrigin - (xOrigin - canvasPtr->inset)\n\t\t    % xScrollIncrement);\n\t}\n    }\n    if (yScrollIncrement > 0) {\n\tif (yOrigin >= 0) {\n\t    yOrigin += yScrollIncrement/2;\n\t    yOrigin -= (yOrigin + canvasPtr->inset)\n\t\t    % yScrollIncrement;\n\t} else {\n\t    yOrigin = (-yOrigin) + yScrollIncrement/2;\n\t    yOrigin = -(yOrigin - (yOrigin - canvasPtr->inset)\n\t\t    % yScrollIncrement);\n\t}\n    }\n\n    /*\n     * Adjust the origin if necessary to keep as much as possible of the\n     * canvas in the view. The variables left, right, etc. keep track of how\n     * much extra space there is on each side of the view before it will stick\n     * out past the scroll region. If one side sticks out past the edge of the\n     * scroll region, adjust the view to bring that side back to the edge of\n     * the scrollregion (but don't move it so much that the other side sticks\n     * out now). If scroll increments are in effect, be sure to adjust only by\n     * full increments.\n     */\n\n    if ((canvasPtr->confine) && (canvasPtr->regionObj != NULL)) {\n\tleft = xOrigin + canvasPtr->inset - canvasPtr->scrollX1;\n\tright = canvasPtr->scrollX2\n\t\t- (xOrigin + Tk_Width(canvasPtr->tkwin) - canvasPtr->inset);\n\ttop = yOrigin + canvasPtr->inset - canvasPtr->scrollY1;\n\tbottom = canvasPtr->scrollY2\n\t\t- (yOrigin + Tk_Height(canvasPtr->tkwin) - canvasPtr->inset);\n\tif ((left < 0) && (right > 0)) {\n\t    delta = (right > -left) ? -left : right;\n\t    if (xScrollIncrement > 0) {\n\t\tdelta -= delta % xScrollIncrement;\n\t    }\n\t    xOrigin += delta;\n\t} else if ((right < 0) && (left > 0)) {\n\t    delta = (left > -right) ? -right : left;\n\t    if (xScrollIncrement > 0) {\n\t\tdelta -= delta % xScrollIncrement;\n\t    }\n\t    xOrigin -= delta;\n\t}\n\tif ((top < 0) && (bottom > 0)) {\n\t    delta = (bottom > -top) ? -top : bottom;\n\t    if (yScrollIncrement > 0) {\n\t\tdelta -= delta % yScrollIncrement;\n\t    }\n\t    yOrigin += delta;\n\t} else if ((bottom < 0) && (top > 0)) {\n\t    delta = (top > -bottom) ? -bottom : top;\n\t    if (yScrollIncrement > 0) {\n\t\tdelta -= delta % yScrollIncrement;\n\t    }\n\t    yOrigin -= delta;\n\t}\n    }\n\n    if ((xOrigin == canvasPtr->xOrigin) && (yOrigin == canvasPtr->yOrigin)) {\n\treturn;\n    }\n\n    /*\n     * Tricky point: must redisplay not only everything that's visible in the\n     * window's final configuration, but also everything that was visible in\n     * the initial configuration. This is needed because some item types, like\n     * windows, need to know when they move off-screen so they can explicitly\n     * undisplay themselves.\n     */\n\n    Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t    canvasPtr->xOrigin, canvasPtr->yOrigin,\n\t    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),\n\t    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));\n    canvasPtr->xOrigin = xOrigin;\n    canvasPtr->yOrigin = yOrigin;\n    canvasPtr->flags |= UPDATE_SCROLLBARS;\n    Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,\n\t    canvasPtr->xOrigin, canvasPtr->yOrigin,\n\t    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),\n\t    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));\n}\n\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsColor --\n *\n *\tThis function is called by individual canvas items when they want to\n *\tset a color value for output. Given information about an X color, this\n *\tfunction will generate Postscript commands to set up an appropriate\n *\tcolor in Postscript.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasPsColor(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning Postscript or\n\t\t\t\t * error message. */\n    Tk_Canvas canvas,\t\t/* Information about canvas. */\n    XColor *colorPtr)\t\t/* Information about color. */\n{\n    return Tk_PostscriptColor(interp, Canvas(canvas)->psInfo, colorPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsFont --\n *\n *\tThis function is called by individual canvas items when they want to\n *\toutput text. Given information about an X font, this function will\n *\tgenerate Postscript commands to set up an appropriate font in\n *\tPostscript.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to the interp->result.\n *\n * Side effects:\n *\tThe Postscript font name is entered into psInfoPtr->fontTable if it\n *\twasn't already there.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasPsFont(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning Postscript or\n\t\t\t\t * error message. */\n    Tk_Canvas canvas,\t\t/* Information about canvas. */\n    Tk_Font tkfont)\t\t/* Information about font in which text is to\n\t\t\t\t * be printed. */\n{\n    return Tk_PostscriptFont(interp, Canvas(canvas)->psInfo, tkfont);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsBitmap --\n *\n *\tThis function is called to output the contents of a sub-region of a\n *\tbitmap in proper image data format for Postscript (i.e. data between\n *\tangle brackets, one bit per pixel).\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasPsBitmap(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning Postscript or\n\t\t\t\t * error message. */\n    Tk_Canvas canvas,\t\t/* Information about canvas. */\n    Pixmap bitmap,\t\t/* Bitmap for which to generate Postscript. */\n    int startX, int startY,\t/* Coordinates of upper-left corner of\n\t\t\t\t * rectangular region to output. */\n    int width, int height)\t/* Size of rectangular region. */\n{\n    return Tk_PostscriptBitmap(interp, Canvas(canvas)->tkwin,\n\t    Canvas(canvas)->psInfo, bitmap, startX, startY, width, height);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsStipple --\n *\n *\tThis function is called by individual canvas items when they have\n *\tcreated a path that they'd like to be filled with a stipple pattern.\n *\tGiven information about an X bitmap, this function will generate\n *\tPostscript commands to fill the current clip region using a stipple\n *\tpattern defined by the bitmap.\n *\n * Results:\n *\tReturns a standard Tcl return value. If an error occurs then an error\n *\tmessage will be left in interp->result. If no error occurs, then\n *\tadditional Postscript will be appended to interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_CanvasPsStipple(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning Postscript or\n\t\t\t\t * error message. */\n    Tk_Canvas canvas,\t\t/* Information about canvas. */\n    Pixmap bitmap)\t\t/* Bitmap to use for stippling. */\n{\n    return Tk_PostscriptStipple(interp, Canvas(canvas)->tkwin,\n\t    Canvas(canvas)->psInfo, bitmap);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsY --\n *\n *\tGiven a y-coordinate in canvas coordinates, this function returns a\n *\ty-coordinate to use for Postscript output.\n *\n * Results:\n *\tReturns the Postscript coordinate that corresponds to \"y\".\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTk_CanvasPsY(\n    Tk_Canvas canvas,\t\t/* Token for canvas on whose behalf Postscript\n\t\t\t\t * is being generated. */\n    double y)\t\t\t/* Y-coordinate in canvas coords. */\n{\n    return Tk_PostscriptY(y, Canvas(canvas)->psInfo);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CanvasPsPath --\n *\n *\tGiven an array of points for a path, generate Postscript commands to\n *\tcreate the path.\n *\n * Results:\n *\tPostscript commands get appended to what's in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_CanvasPsPath(\n    Tcl_Interp *interp,\t\t/* Put generated Postscript in this\n\t\t\t\t * interpreter's result field. */\n    Tk_Canvas canvas,\t\t/* Canvas on whose behalf Postscript is being\n\t\t\t\t * generated. */\n    double *coordPtr,\t\t/* Pointer to first in array of 2*numPoints\n\t\t\t\t * coordinates giving points for path. */\n    Tcl_Size numPoints)\t\t/* Number of points at *coordPtr. */\n{\n    Tk_PostscriptPath(interp, Canvas(canvas)->psInfo, coordPtr, numPoints);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCanvas.h",
    "content": "/*\n * tkCanvas.h --\n *\n *\tDeclarations shared among all the files that implement canvas widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n * Copyright © 1998 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKCANVAS\n#define _TKCANVAS\n\n#ifndef _TK\n#include \"tk.h\"\n#endif\n\n#ifndef USE_OLD_TAG_SEARCH\ntypedef struct TagSearchExpr_s TagSearchExpr;\n\nstruct TagSearchExpr_s {\n    TagSearchExpr *next;\t/* For linked lists of expressions - used in\n\t\t\t\t * bindings. */\n    Tk_Uid uid;\t\t\t/* The uid of the whole expression. */\n    Tk_Uid *uids;\t\t/* Expresion compiled to an array of uids. */\n    int allocated;\t\t/* Available space for array of uids. */\n    int length;\t\t\t/* Length of expression. */\n    int index;\t\t\t/* Current position in expression\n\t\t\t\t * evaluation. */\n    int match;\t\t\t/* This expression matches event's item's\n\t\t\t\t * tags. */\n};\n#endif /* not USE_OLD_TAG_SEARCH */\n\n/*\n * The record below describes a canvas widget. It is made available to the\n * item functions so they can access certain shared fields such as the overall\n * displacement and scale factor for the canvas.\n */\n\ntypedef struct TkCanvas {\n    Tk_Window tkwin;\t\t/* Window that embodies the canvas. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up.*/\n    Display *display;\t\t/* Display containing widget; needed, among\n\t\t\t\t * other things, to release resources after\n\t\t\t\t * tkwin has already gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with canvas. */\n    Tcl_Command widgetCmd;\t/* Token for canvas's widget command. */\n    Tk_Item *firstItemPtr;\t/* First in list of all items in canvas, or\n\t\t\t\t * NULL if canvas empty. */\n    Tk_Item *lastItemPtr;\t/* Last in list of all items in canvas, or\n\t\t\t\t * NULL if canvas empty. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border around window. */\n    Tk_3DBorder bgBorder;\t/* Used for canvas background. */\n    int relief;\t\t\t/* Indicates whether window as a whole is\n\t\t\t\t * raised, sunken, or flat. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. 0 means\n\t\t\t\t * don't draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    GC pixmapGC;\t\t/* Used to copy bits from a pixmap to the\n\t\t\t\t * screen and also to clear the pixmap. */\n    Tcl_Obj *widthObj, *heightObj;\t\t/* Dimensions to request for canvas window,\n\t\t\t\t * specified in pixels. */\n    int redrawX1, redrawY1;\t/* Upper left corner of area to redraw, in\n\t\t\t\t * pixel coordinates. Border pixels are\n\t\t\t\t * included. Only valid if REDRAW_PENDING flag\n\t\t\t\t * is set. */\n    int redrawX2, redrawY2;\t/* Lower right corner of area to redraw, in\n\t\t\t\t * integer canvas coordinates. Border pixels\n\t\t\t\t * will *not* be redrawn. */\n    int confine;\t\t/* Non-zero means constrain view to keep as\n\t\t\t\t * much of canvas visible as possible. */\n\n    /*\n     * Information used to manage the selection and insertion cursor:\n     */\n\n    Tk_CanvasTextInfo textInfo; /* Contains lots of fields; see tk.h for\n\t\t\t\t * details. This structure is shared with the\n\t\t\t\t * code that implements individual items. */\n    int insertOnTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"on\" state for each blink. */\n    int insertOffTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"off\" state for each blink. */\n    Tcl_TimerToken insertBlinkHandler;\n\t\t\t\t/* Timer handler used to blink cursor on and\n\t\t\t\t * off. */\n\n    /*\n     * Transformation applied to canvas as a whole: to compute screen\n     * coordinates (X,Y) from canvas coordinates (x,y), do the following:\n     *\n     * X = x - xOrigin;\n     * Y = y - yOrigin;\n     */\n\n    int xOrigin, yOrigin;\t/* Canvas coordinates corresponding to\n\t\t\t\t * upper-left corner of window, given in\n\t\t\t\t * canvas pixel units. */\n    int drawableXOrigin, drawableYOrigin;\n\t\t\t\t/* During redisplay, these fields give the\n\t\t\t\t * canvas coordinates corresponding to the\n\t\t\t\t * upper-left corner of the drawable where\n\t\t\t\t * items are actually being drawn (typically a\n\t\t\t\t * pixmap smaller than the whole window). */\n\n    /*\n     * Information used for event bindings associated with items.\n     */\n\n    Tk_BindingTable bindingTable;\n\t\t\t\t/* Table of all bindings currently defined for\n\t\t\t\t * this canvas. NULL means that no bindings\n\t\t\t\t * exist, so the table hasn't been created.\n\t\t\t\t * Each \"object\" used for this table is either\n\t\t\t\t * a Tk_Uid for a tag or the address of an\n\t\t\t\t * item named by id. */\n    Tk_Item *currentItemPtr;\t/* The item currently containing the mouse\n\t\t\t\t * pointer, or NULL if none. */\n    Tk_Item *newCurrentPtr;\t/* The item that is about to become the\n\t\t\t\t * current one, or NULL. This field is used to\n\t\t\t\t * detect deletions of the new current item\n\t\t\t\t * pointer that occur during Leave processing\n\t\t\t\t * of the previous current item. */\n    double closeEnough;\t\t/* The mouse is assumed to be inside an item\n\t\t\t\t * if it is this close to it. */\n    XEvent pickEvent;\t\t/* The event upon which the current choice of\n\t\t\t\t * currentItem is based. Must be saved so that\n\t\t\t\t * if the currentItem is deleted, can pick\n\t\t\t\t * another. */\n    unsigned int state;\t\t/* Last known modifier state. Used to defer\n\t\t\t\t * picking a new current object while buttons\n\t\t\t\t * are down. */\n\n    /*\n     * Information used for managing scrollbars:\n     */\n\n    Tcl_Obj *xScrollCmdObj;\t\t/* Command prefix for communicating with\n\t\t\t\t * horizontal scrollbar. NULL means no\n\t\t\t\t * horizontal scrollbar. */\n    Tcl_Obj *yScrollCmdObj;\t\t/* Command prefix for communicating with\n\t\t\t\t * vertical scrollbar. NULL means no vertical\n\t\t\t\t * scrollbar. */\n    int scrollX1, scrollY1, scrollX2, scrollY2;\n\t\t\t\t/* These four coordinates define the region\n\t\t\t\t * that is the 100% area for scrolling (i.e.\n\t\t\t\t * these numbers determine the size and\n\t\t\t\t * location of the sliders on scrollbars).\n\t\t\t\t * Units are pixels in canvas coords. */\n    Tcl_Obj *regionObj;\t\t/* The option string from which scrollX1 etc.\n\t\t\t\t * are derived. */\n    Tcl_Obj *xScrollIncrementObj;\t/* If >0, defines a grid for horizontal\n\t\t\t\t * scrolling. This is the size of the \"unit\",\n\t\t\t\t * and the left edge of the screen will always\n\t\t\t\t * lie on an even unit boundary. */\n    Tcl_Obj *yScrollIncrementObj;\t/* If >0, defines a grid for vertical\n\t\t\t\t * scrolling. This is the size of the \"unit\",\n\t\t\t\t * and the top edge of the screen will always\n\t\t\t\t * lie on an even unit boundary. */\n    /*\n     * Information used for scanning:\n     */\n\n    int scanX;\t\t\t/* X-position at which scan started (e.g.\n\t\t\t\t * button was pressed here). */\n    int scanXOrigin;\t\t/* Value of xOrigin field when scan started. */\n    int scanY;\t\t\t/* Y-position at which scan started (e.g.\n\t\t\t\t * button was pressed here). */\n    int scanYOrigin;\t\t/* Value of yOrigin field when scan started. */\n\n    /*\n     * Information used to speed up searches by remembering the last item\n     * created or found with an item id search.\n     */\n\n    Tk_Item *hotPtr;\t\t/* Pointer to \"hot\" item (one that's been\n\t\t\t\t * recently used. NULL means there's no hot\n\t\t\t\t * item. */\n    Tk_Item *hotPrevPtr;\t/* Pointer to predecessor to hotPtr (NULL\n\t\t\t\t * means item is first in list). This is only\n\t\t\t\t * a hint and may not really be hotPtr's\n\t\t\t\t * predecessor. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    Tcl_Obj *takeFocusObj;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    double pixelsPerMM;\t\t/* Scale factor between MM and pixels; used\n\t\t\t\t * when converting coordinates. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n    Tcl_Size nextId;\t\t\t/* Number to use as id for next item created\n\t\t\t\t * in widget. */\n    Tk_PostscriptInfo psInfo;\t/* Pointer to information used for generating\n\t\t\t\t * Postscript for the canvas. NULL means no\n\t\t\t\t * Postscript is currently being generated. */\n    Tcl_HashTable idTable;\t/* Table of integer indices. */\n\n    /*\n     * Additional information, added by the 'dash'-patch\n     */\n\n    void *reserved1;\n    Tk_State canvas_state;\t/* State of canvas. */\n    void *reserved2;\n    void *reserved3;\n    Tk_TSOffset tsoffset;\n#ifndef USE_OLD_TAG_SEARCH\n    TagSearchExpr *bindTagExprs;/* Linked list of tag expressions used in\n\t\t\t\t * bindings. */\n#endif\n} TkCanvas;\n\n/*\n * Flag bits for canvases:\n *\n * REDRAW_PENDING -\t\t1 means a DoWhenIdle handler has already been\n *\t\t\t\tcreated to redraw some or all of the canvas.\n * REDRAW_BORDERS -\t\t1 means that the borders need to be redrawn\n *\t\t\t\tduring the next redisplay operation.\n * REPICK_NEEDED -\t\t1 means DisplayCanvas should pick a new\n *\t\t\t\tcurrent item before redrawing the canvas.\n * GOT_FOCUS -\t\t\t1 means the focus is currently in this widget,\n *\t\t\t\tso should draw the insertion cursor and\n *\t\t\t\ttraversal highlight.\n * CURSOR_ON -\t\t\t1 means the insertion cursor is in the \"on\"\n *\t\t\t\tphase of its blink cycle. 0 means either we\n *\t\t\t\tdon't have the focus or the cursor is in the\n *\t\t\t\t\"off\" phase of its cycle.\n * UPDATE_SCROLLBARS -\t\t1 means the scrollbars should get updated as\n *\t\t\t\tpart of the next display operation.\n * LEFT_GRABBED_ITEM -\t\t1 means that the mouse left the current item\n *\t\t\t\twhile a grab was in effect, so we didn't\n *\t\t\t\tchange canvasPtr->currentItemPtr.\n * REPICK_IN_PROGRESS -\t\t1 means PickCurrentItem is currently\n *\t\t\t\texecuting. If it should be called recursively,\n *\t\t\t\tit should simply return immediately.\n * BBOX_NOT_EMPTY -\t\t1 means that the bounding box of the area that\n *\t\t\t\tshould be redrawn is not empty.\n */\n\n#define REDRAW_PENDING\t\t1\n#define REDRAW_BORDERS\t\t2\n#define REPICK_NEEDED\t\t4\n#define GOT_FOCUS\t\t8\n#define CURSOR_ON\t\t0x10\n#define UPDATE_SCROLLBARS\t0x20\n#define LEFT_GRABBED_ITEM\t0x40\n#define REPICK_IN_PROGRESS\t0x100\n#define BBOX_NOT_EMPTY\t\t0x200\n\n/*\n * Flag bits for canvas items (redraw_flags):\n *\n * FORCE_REDRAW -\t\t1 means that the new coordinates of some item\n *\t\t\t\tare not yet registered using\n *\t\t\t\tTk_CanvasEventuallyRedraw(). It should still\n *\t\t\t\tbe done by the general canvas code.\n */\n\n#define FORCE_REDRAW\t\t8\n\n/*\n * Canvas-related functions that are shared among Tk modules but not exported\n * to the outside world:\n */\n\nMODULE_SCOPE int\tTkCanvPostscriptObjCmd(TkCanvas *canvasPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE Tcl_Size\tTkCanvTranslatePath(TkCanvas *canvPtr,\n\t\t\t    Tcl_Size numVertex, double *coordPtr, int closed,\n\t\t\t    XPoint *outPtr);\n/*\n * Standard item types provided by Tk:\n */\n\nMODULE_SCOPE Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;\nMODULE_SCOPE Tk_ItemType tkOvalType, tkPolygonType;\nMODULE_SCOPE Tk_ItemType tkRectangleType, tkTextType, tkWindowType;\n\n/*\n * Convenience macro.\n */\n\n#define Canvas(canvas) ((TkCanvas *) (canvas))\n\n#endif /* _TKCANVAS */\n"
  },
  {
    "path": "generic/tkClipboard.c",
    "content": "/*\n * tkClipboard.c --\n *\n *\tThis file manages the clipboard for the Tk toolkit, maintaining a\n *\tcollection of data buffers that will be supplied on demand to\n *\trequesting applications.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkSelect.h\"\n\n/*\n * Prototypes for functions used only in this file:\n */\n\nstatic Tcl_Size\tClipboardAppHandler(void *clientData,\n\t\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\nstatic Tcl_Size\tClipboardHandler(void *clientData,\n\t\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\nstatic Tcl_Size\tClipboardWindowHandler(void *clientData,\n\t\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\nstatic void\t\tClipboardLostSel(void *clientData);\nstatic int\t\tClipboardGetProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *portion);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClipboardHandler --\n *\n *\tThis function acts as selection handler for the clipboard manager. It\n *\textracts the required chunk of data from the buffer chain for a given\n *\tselection target.\n *\n * Results:\n *\tThe return value is a count of the number of bytes actually stored at\n *\tbuffer.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nClipboardHandler(\n    void *clientData,\t/* Information about data to fetch. */\n    Tcl_Size offset,\t\t\t/* Return selection bytes starting at this\n\t\t\t\t * offset. */\n    char *buffer,\t\t/* Place to store converted selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum # of bytes to store at buffer. */\n{\n    TkClipboardTarget *targetPtr = (TkClipboardTarget *)clientData;\n    TkClipboardBuffer *cbPtr;\n    char *srcPtr, *destPtr;\n    Tcl_Size count = 0;\n    Tcl_Size scanned = 0;\n    Tcl_Size length, freeCount;\n\n    /*\n     * Skip to buffer containing offset byte\n     */\n\n    for (cbPtr = targetPtr->firstBufferPtr; ; cbPtr = cbPtr->nextPtr) {\n\tif (cbPtr == NULL) {\n\t    return 0;\n\t}\n\tif (scanned + cbPtr->length > offset) {\n\t    break;\n\t}\n\tscanned += cbPtr->length;\n    }\n\n    /*\n     * Copy up to maxBytes or end of list, switching buffers as needed.\n     */\n\n    freeCount = maxBytes;\n    srcPtr = cbPtr->buffer + (offset - scanned);\n    destPtr = buffer;\n    length = cbPtr->length - (offset - scanned);\n    while (1) {\n\tif (length > freeCount) {\n\t    strncpy(destPtr, srcPtr, freeCount);\n\t    return maxBytes;\n\t} else {\n\t    strncpy(destPtr, srcPtr, length);\n\t    destPtr += length;\n\t    count += length;\n\t    freeCount -= length;\n\t}\n\tcbPtr = cbPtr->nextPtr;\n\tif (cbPtr == NULL) {\n\t    break;\n\t}\n\tsrcPtr = cbPtr->buffer;\n\tlength = cbPtr->length;\n    }\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClipboardAppHandler --\n *\n *\tThis function acts as selection handler for retrievals of type\n *\tTK_APPLICATION. It returns the name of the application that owns the\n *\tclipboard. Note: we can't use the default Tk selection handler for\n *\tthis selection type, because the clipboard window isn't a \"real\"\n *\twindow and doesn't have the necessary information.\n *\n * Results:\n *\tThe return value is a count of the number of bytes actually stored at\n *\tbuffer.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nClipboardAppHandler(\n    void *clientData,\t/* Pointer to TkDisplay structure. */\n    Tcl_Size offset,\t\t\t/* Return selection bytes starting at this\n\t\t\t\t * offset. */\n    char *buffer,\t\t/* Place to store converted selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum # of bytes to store at buffer. */\n{\n    TkDisplay *dispPtr = (TkDisplay *)clientData;\n    Tcl_Size length;\n    const char *p;\n\n    p = dispPtr->clipboardAppPtr->winPtr->nameUid;\n    length = strlen(p);\n    if (length <= offset) {\n\treturn 0;\n    }\n    length -= offset;\n    if (length > maxBytes) {\n\tlength = maxBytes;\n    }\n    memcpy(buffer, p, length);\n    buffer[length] = 0;\n    return length;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClipboardWindowHandler --\n *\n *\tThis function acts as selection handler for retrievals of type\n *\tTK_WINDOW. Since the clipboard doesn't correspond to any particular\n *\twindow, we just return \".\". We can't use Tk's default handler for this\n *\tselection type, because the clipboard window isn't a valid window.\n *\n * Results:\n *\tThe return value is 1, the number of non-null bytes stored at buffer.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nClipboardWindowHandler(\n    TCL_UNUSED(void *),\t/* Not used. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Return selection bytes starting at this\n\t\t\t\t * offset. */\n    char *buffer,\t\t/* Place to store converted selection. */\n    TCL_UNUSED(Tcl_Size))\t\t/* Maximum # of bytes to store at buffer. */\n{\n    buffer[0] = '.';\n    buffer[1] = 0;\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClipboardLostSel --\n *\n *\tThis function is invoked whenever clipboard ownership is claimed by\n *\tanother window. It just sets a flag so that we know the clipboard was\n *\ttaken away.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe clipboard is marked as inactive.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nClipboardLostSel(\n    void *clientData)\t/* Pointer to TkDisplay structure. */\n{\n    TkDisplay *dispPtr = (TkDisplay *)clientData;\n\n    dispPtr->clipboardActive = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ClipboardClear --\n *\n *\tTake control of the clipboard and clear out the previous contents.\n *\tThis function must be invoked before any calls to Tk_ClipboardAppend.\n *\n * Results:\n *\tA standard Tcl result. If an error occurs, an error message is left in\n *\tthe interp's result.\n *\n * Side effects:\n *\tFrom now on, requests for the CLIPBOARD selection will be directed to\n *\tthe clipboard manager routines associated with clipWindow for the\n *\tdisplay of tkwin. In order to guarantee atomicity, no event handling\n *\tshould occur between Tk_ClipboardClear and the following\n *\tTk_ClipboardAppend calls. This function may cause a user-defined\n *\tLostSel command to be invoked when the CLIPBOARD is claimed, so any\n *\tcalling function should be reentrant at the point Tk_ClipboardClear is\n *\tinvoked.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ClipboardClear(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin)\t\t/* Window in application that is clearing\n\t\t\t\t * clipboard; identifies application and\n\t\t\t\t * display. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkClipboardTarget *targetPtr, *nextTargetPtr;\n    TkClipboardBuffer *cbPtr, *nextCbPtr;\n\n    if (dispPtr->clipWindow == NULL) {\n\tint result;\n\n\tresult = TkClipInit(interp, dispPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n\n    /*\n     * Discard any existing clipboard data and delete the selection handler(s)\n     * associated with that data.\n     */\n\n    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;\n\t    targetPtr = nextTargetPtr) {\n\tfor (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;\n\t\tcbPtr = nextCbPtr) {\n\t    Tcl_Free(cbPtr->buffer);\n\t    nextCbPtr = cbPtr->nextPtr;\n\t    Tcl_Free(cbPtr);\n\t}\n\tnextTargetPtr = targetPtr->nextPtr;\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\ttargetPtr->type);\n\tTcl_Free(targetPtr);\n    }\n    dispPtr->clipTargetPtr = NULL;\n\n    /*\n     * Reclaim the clipboard selection if we lost it.\n     */\n\n    if (!dispPtr->clipboardActive) {\n\tTk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tClipboardLostSel, dispPtr);\n\tdispPtr->clipboardActive = 1;\n    }\n    dispPtr->clipboardAppPtr = winPtr->mainPtr;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ClipboardAppend --\n *\n *\tAppend a buffer of data to the clipboard. The first buffer of a given\n *\ttype determines the format for that type. Any successive appends to\n *\tthat type must have the same format or an error will be returned.\n *\tTk_ClipboardClear must be called before a sequence of\n *\tTk_ClipboardAppend calls can be issued. In order to guarantee\n *\tatomicity, no event handling should occur between Tk_ClipboardClear\n *\tand the following Tk_ClipboardAppend calls.\n *\n * Results:\n *\tA standard Tcl result. If an error is returned, an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tThe specified buffer will be copied onto the end of the clipboard.\n *\tThe clipboard maintains a list of buffers which will be used to supply\n *\tthe data for a selection get request. The first time a given type is\n *\tappended, Tk_ClipboardAppend will register a selection handler of the\n *\tappropriate type.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ClipboardAppend(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Window tkwin,\t\t/* Window that selects a display. */\n    Atom type,\t\t\t/* The desired conversion type for this\n\t\t\t\t * clipboard item, e.g. STRING or LENGTH. */\n    Atom format,\t\t/* Format in which the selection information\n\t\t\t\t * should be returned to the requestor. */\n    const char *buffer)\t\t/* NULL terminated string containing the data\n\t\t\t\t * to be added to the clipboard. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkClipboardTarget *targetPtr;\n    TkClipboardBuffer *cbPtr;\n\n    /*\n     * If this application doesn't already own the clipboard, clear the\n     * clipboard. If we don't own the clipboard selection, claim it.\n     */\n\n    if (dispPtr->clipboardAppPtr != winPtr->mainPtr) {\n\tTk_ClipboardClear(interp, tkwin);\n    } else if (!dispPtr->clipboardActive) {\n\tTk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tClipboardLostSel, dispPtr);\n\tdispPtr->clipboardActive = 1;\n    }\n\n    /*\n     * Check to see if the specified target is already present on the\n     * clipboard. If it isn't, we need to create a new target; otherwise, we\n     * just append the new buffer to the clipboard list.\n     */\n\n    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;\n\t    targetPtr = targetPtr->nextPtr) {\n\tif (targetPtr->type == type) {\n\t    break;\n\t}\n    }\n    if (targetPtr == NULL) {\n\ttargetPtr = (TkClipboardTarget *)Tcl_Alloc(sizeof(TkClipboardTarget));\n\ttargetPtr->type = type;\n\ttargetPtr->format = format;\n\ttargetPtr->firstBufferPtr = targetPtr->lastBufferPtr = NULL;\n\ttargetPtr->nextPtr = dispPtr->clipTargetPtr;\n\tdispPtr->clipTargetPtr = targetPtr;\n\tTk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\ttype, ClipboardHandler, targetPtr, format);\n    } else if (targetPtr->format != format) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"format \\\"%s\\\" does not match current format \\\"%s\\\" for %s\",\n\t\tTk_GetAtomName(tkwin, format),\n\t\tTk_GetAtomName(tkwin, targetPtr->format),\n\t\tTk_GetAtomName(tkwin, type)));\n\tTcl_SetErrorCode(interp, \"TK\", \"CLIPBOARD\", \"FORMAT_MISMATCH\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Append a new buffer to the buffer chain.\n     */\n\n    cbPtr = (TkClipboardBuffer *)Tcl_Alloc(sizeof(TkClipboardBuffer));\n    cbPtr->nextPtr = NULL;\n    if (targetPtr->lastBufferPtr != NULL) {\n\ttargetPtr->lastBufferPtr->nextPtr = cbPtr;\n    } else {\n\ttargetPtr->firstBufferPtr = cbPtr;\n    }\n    targetPtr->lastBufferPtr = cbPtr;\n\n    cbPtr->length = strlen(buffer);\n    cbPtr->buffer = (char *)Tcl_Alloc(cbPtr->length + 1);\n    strcpy(cbPtr->buffer, buffer);\n\n    TkSelUpdateClipboard((TkWindow *) dispPtr->clipWindow, CLIPBOARD_APPEND);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ClipboardObjCmd --\n *\n *\tThis function is invoked to process the \"clipboard\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ClipboardObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    const char *path = NULL;\n    Atom selection;\n    static const char *const optionStrings[] = {\n\t\"append\", \"clear\", \"get\", NULL };\n    int index, result;\n    Tcl_Size i;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((clipboardOption) index) {\n    case CLIPBOARD_APPEND: {\n\tAtom target, format;\n\tconst char *targetName = NULL;\n\tconst char *formatName = NULL;\n\tconst char *string;\n\tstatic const char *const appendOptionStrings[] = {\n\t    \"-displayof\", \"-format\", \"-type\", NULL\n\t};\n\tenum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE };\n\tint subIndex;\n\tTcl_Size length;\n\n\tfor (i = 2; i < objc - 1; i++) {\n\t    string = Tcl_GetStringFromObj(objv[i], &length);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * If the argument is \"--\", it signifies the end of arguments.\n\t     */\n\t    if (string[1] == '-' && length == 2) {\n\t\ti++;\n\t\tbreak;\n\t    }\n\t    if (Tcl_GetIndexFromObj(interp, objv[i], appendOptionStrings,\n\t\t    \"option\", 0, &subIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Increment i so that it points to the value for the flag instead\n\t     * of the flag itself.\n\t     */\n\n\t    i++;\n\t    if (i >= objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CLIPBOARD\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    switch ((enum appendOptions) subIndex) {\n\t    case APPEND_DISPLAYOF:\n\t\tpath = Tcl_GetString(objv[i]);\n\t\tbreak;\n\t    case APPEND_FORMAT:\n\t\tformatName = Tcl_GetString(objv[i]);\n\t\tbreak;\n\t    case APPEND_TYPE:\n\t\ttargetName = Tcl_GetString(objv[i]);\n\t\tbreak;\n\t    }\n\t}\n\tif (objc - i != 1) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...? data\");\n\t    return TCL_ERROR;\n\t}\n\tif (path != NULL) {\n\t    tkwin = Tk_NameToWindow(interp, path, tkwin);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (targetName != NULL) {\n\t    target = Tk_InternAtom(tkwin, targetName);\n\t} else {\n\t    target = XA_STRING;\n\t}\n\tif (formatName != NULL) {\n\t    format = Tk_InternAtom(tkwin, formatName);\n\t} else {\n\t    format = XA_STRING;\n\t}\n\treturn Tk_ClipboardAppend(interp, tkwin, target, format,\n\t\tTcl_GetString(objv[i]));\n    }\n    case CLIPBOARD_CLEAR: {\n\tstatic const char *const clearOptionStrings[] = { \"-displayof\", NULL };\n\tenum clearOptions { CLEAR_DISPLAYOF };\n\tint subIndex;\n\n\tif (objc != 2 && objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (objc == 4) {\n\t    if (Tcl_GetIndexFromObj(interp, objv[2], clearOptionStrings,\n\t\t    \"option\", 0, &subIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if ((enum clearOptions) subIndex == CLEAR_DISPLAYOF) {\n\t\tpath = Tcl_GetString(objv[3]);\n\t    }\n\t}\n\tif (path != NULL) {\n\t    tkwin = Tk_NameToWindow(interp, path, tkwin);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tresult = Tk_ClipboardClear(interp, tkwin);\n\tif (result == TCL_OK) {\n\t    TkSelUpdateClipboard((TkWindow *) tkwin, CLIPBOARD_CLEAR);\n\t}\n\treturn result;\n    }\n    case CLIPBOARD_GET: {\n\tAtom target;\n\tconst char *targetName = NULL;\n\tTcl_DString selBytes;\n\tconst char *string;\n\tstatic const char *const getOptionStrings[] = {\n\t    \"-displayof\", \"-type\", NULL\n\t};\n\tenum getOptions { APPEND_DISPLAYOF, APPEND_TYPE };\n\tint subIndex;\n\n\tfor (i = 2; i < objc; i++) {\n\t    string = Tcl_GetString(objv[i]);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\t    if (Tcl_GetIndexFromObj(interp, objv[i], getOptionStrings,\n\t\t    \"option\", 0, &subIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    i++;\n\t    if (i >= objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CLIPBOARD\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    switch ((enum getOptions) subIndex) {\n\t    case APPEND_DISPLAYOF:\n\t\tpath = Tcl_GetString(objv[i]);\n\t\tbreak;\n\t    case APPEND_TYPE:\n\t\ttargetName = Tcl_GetString(objv[i]);\n\t\tbreak;\n\t    }\n\t}\n\tif (path != NULL) {\n\t    tkwin = Tk_NameToWindow(interp, path, tkwin);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tselection = Tk_InternAtom(tkwin, \"CLIPBOARD\");\n\n\tif (objc - i > 1) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...?\");\n\t    return TCL_ERROR;\n\t} else if (objc - i == 1) {\n\t    target = Tk_InternAtom(tkwin, Tcl_GetString(objv[i]));\n\t} else if (targetName != NULL) {\n\t    target = Tk_InternAtom(tkwin, targetName);\n\t} else {\n\t    target = XA_STRING;\n\t}\n\n\tTcl_DStringInit(&selBytes);\n\tresult = Tk_GetSelection(interp, tkwin, selection, target,\n\t\tClipboardGetProc, &selBytes);\n\tif (result == TCL_OK) {\n\t    Tcl_DStringResult(interp, &selBytes);\n\t} else {\n\t    Tcl_DStringFree(&selBytes);\n\t}\n\treturn result;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkClipInit --\n *\n *\tThis function is called to initialize the window for claiming\n *\tclipboard ownership and for receiving selection get results. This\n *\tfunction is called from tkSelect.c as well as tkClipboard.c.\n *\n * Results:\n *\tThe result is a standard Tcl return value, which is normally TCL_OK.\n *\tIf an error occurs then an error message is left in the interp's\n *\tresult and TCL_ERROR is returned.\n *\n * Side effects:\n *\tSets up the clipWindow and related data structures.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkClipInit(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Interpreter to use for error reporting. */\n    TkDisplay *dispPtr)/* Display to initialize. */\n{\n    XSetWindowAttributes atts;\n\n    dispPtr->clipTargetPtr = NULL;\n    dispPtr->clipboardActive = 0;\n    dispPtr->clipboardAppPtr = NULL;\n\n    /*\n     * Create the window used for clipboard ownership and selection retrieval,\n     * and set up an event handler for it.\n     */\n\n    dispPtr->clipWindow = (Tk_Window) TkAllocWindow(dispPtr,\n\tDefaultScreen(dispPtr->display), NULL);\n    Tcl_Preserve(dispPtr->clipWindow);\n    ((TkWindow *) dispPtr->clipWindow)->flags |=\n\t    TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;\n    TkWmNewWindow((TkWindow *) dispPtr->clipWindow);\n    atts.override_redirect = True;\n    Tk_ChangeWindowAttributes(dispPtr->clipWindow, CWOverrideRedirect, &atts);\n    Tk_MakeWindowExist(dispPtr->clipWindow);\n\n    if (dispPtr->multipleAtom == None) {\n\t/*\n\t * Need to invoke selection initialization to make sure that atoms we\n\t * depend on below are defined.\n\t */\n\n\tTkSelInit(dispPtr->clipWindow);\n    }\n\n    /*\n     * Create selection handlers for types TK_APPLICATION and TK_WINDOW on\n     * this window. Can't use the default handlers for these types because\n     * this isn't a full-fledged window.\n     */\n\n    Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t    dispPtr->applicationAtom, ClipboardAppHandler, dispPtr,XA_STRING);\n    Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t    dispPtr->windowAtom, ClipboardWindowHandler, dispPtr, XA_STRING);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ClipboardGetProc --\n *\n *\tThis function is invoked to process pieces of the selection as they\n *\tarrive during \"clipboard get\" commands.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tBytes get appended to the dynamic string pointed to by the clientData\n *\targument.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nClipboardGetProc(\n    void *clientData,\t/* Dynamic string holding partially assembled\n\t\t\t\t * selection. */\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Interpreter used for error reporting (not\n\t\t\t\t * used). */\n    const char *portion)\t/* New information to be appended. */\n{\n    Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, \"utf-8\");\n    Tcl_DString ds;\n\n    const char *str = Tcl_ExternalToUtfDString(utf8, portion, TCL_INDEX_NONE, &ds);\n    Tcl_DStringAppend((Tcl_DString *) clientData, str, Tcl_DStringLength(&ds));\n    Tcl_DStringFree(&ds);\n    Tcl_FreeEncoding(utf8);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCmds.c",
    "content": "/*\n * tkCmds.c --\n *\n *\tThis file contains a collection of Tk-related Tcl commands that didn't\n *\tfit in any particular file of the toolkit.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#if defined(_WIN32)\n#include \"tkWinInt.h\"\n#elif defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#else\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic TkWindow *\tGetTopHierarchy(Tk_Window tkwin);\nstatic char *\t\tWaitVariableProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic void\t\tWaitVisibilityProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tWaitWindowProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tAppnameCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tAttribtableCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tAttribTableProc(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic void\t\tAttribTableDeleteProc(void *dummy);\nstatic void\t\tAttribTableDestroyHandler(void *dummy,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tCaretCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tInactiveCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tScalingCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tUseinputmethodsCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int\t\tWindowingsystemCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv);\n\n#if defined(_WIN32) || defined(MAC_OSX_TK)\nMODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[];\n#else\n#define tkFontchooserEnsemble NULL\n#endif\n\n/*\n * Table of tk subcommand names and implementations.\n */\n\nstatic const TkEnsemble tkCmdMap[] = {\n    {\"fontchooser\",\tNULL, tkFontchooserEnsemble},\n    {\"appname\",\t\tAppnameCmd, NULL },\n    {\"attribtable\",\tAttribtableCmd, NULL },\n    {\"busy\",\t\tTk_BusyObjCmd, NULL },\n    {\"caret\",\t\tCaretCmd, NULL },\n    {\"inactive\",\tInactiveCmd, NULL },\n    {\"scaling\",\t\tScalingCmd, NULL },\n    {\"useinputmethods\",\tUseinputmethodsCmd, NULL },\n    {\"windowingsystem\",\tWindowingsystemCmd, NULL },\n    {NULL, NULL, NULL}\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_BellObjCmd --\n *\n *\tThis function is invoked to process the \"bell\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_BellObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const bellOptions[] = {\n\t\"-displayof\", \"-nice\", NULL\n    };\n    enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE };\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tcl_Size i;\n    int index, nice = 0;\n    Tk_ErrorHandler handler;\n\n    if (objc > 4) {\n    wrongArgs:\n\tTcl_WrongNumArgs(interp, 1, objv, \"?-displayof window? ?-nice?\");\n\treturn TCL_ERROR;\n    }\n\n    for (i = 1; i < objc; i++) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], bellOptions,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((enum options) index) {\n\tcase TK_BELL_DISPLAYOF:\n\t    if (++i >= objc) {\n\t\tgoto wrongArgs;\n\t    }\n\t    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);\n\t    if (tkwin == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_BELL_NICE:\n\t    nice = 1;\n\t    break;\n\t}\n    }\n    handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL);\n    XBell(Tk_Display(tkwin), 0);\n    if (!nice) {\n\tXForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);\n    }\n    (void)XFlush(Tk_Display(tkwin));\n    Tk_DeleteErrorHandler(handler);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_BindObjCmd --\n *\n *\tThis function is invoked to process the \"bind\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_BindObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkWindow *winPtr;\n    void *object;\n    const char *string;\n\n    if ((objc < 2) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window ?pattern? ?command?\");\n\treturn TCL_ERROR;\n    }\n    string = Tcl_GetString(objv[1]);\n\n    /*\n     * Bind tags either a window name or a tag name for the first argument.\n     * If the argument starts with \".\", assume it is a window; otherwise, it\n     * is a tag.\n     */\n\n    if (string[0] == '.') {\n\twinPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);\n\tif (winPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tobject = winPtr->pathName;\n    } else {\n\twinPtr = (TkWindow *)clientData;\n\tobject = (void *) Tk_GetUid(string);\n    }\n\n    /*\n     * If there are four arguments, the command is modifying a binding. If\n     * there are three arguments, the command is querying a binding. If there\n     * are only two arguments, the command is querying all the bindings for\n     * the given tag/window.\n     */\n\n    if (objc == 4) {\n\tint append = 0;\n\tunsigned long mask;\n\tconst char *sequence = Tcl_GetString(objv[2]);\n\tconst char *script = Tcl_GetString(objv[3]);\n\n\t/*\n\t * If the script is null, just delete the binding.\n\t */\n\n\tif (script[0] == 0) {\n\t    return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,\n\t\t    object, sequence);\n\t}\n\n\t/*\n\t * If the script begins with \"+\", append this script to the existing\n\t * binding.\n\t */\n\n\tif (script[0] == '+') {\n\t    script++;\n\t    append = 1;\n\t}\n\tmask = Tk_CreateBinding(interp, winPtr->mainPtr->bindingTable,\n\t\tobject, sequence, script, append);\n\tif (mask == 0) {\n\t    return TCL_ERROR;\n\t}\n    } else if (objc == 3) {\n\tconst char *command;\n\n\tcommand = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable,\n\t\tobject, Tcl_GetString(objv[2]));\n\tif (command == NULL) {\n\t    Tcl_ResetResult(interp);\n\t    return TCL_OK;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(command, TCL_INDEX_NONE));\n    } else {\n\tTk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBindEventProc --\n *\n *\tThis function is invoked by Tk_HandleEvent for each event; it causes\n *\tany appropriate bindings for that event to be invoked.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what bindings have been established with the \"bind\"\n *\tcommand.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBindEventProc(\n    TkWindow *winPtr,\t\t/* Pointer to info about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n#define MAX_OBJS 20\n    void *objects[MAX_OBJS], **objPtr;\n    TkWindow *topLevPtr;\n    Tcl_Size i, count;\n    char *p;\n    Tcl_HashEntry *hPtr;\n\n    if ((winPtr->mainPtr == NULL) || (winPtr->mainPtr->bindingTable == NULL)) {\n\treturn;\n    }\n\n    objPtr = objects;\n    if (winPtr->numTags != 0) {\n\t/*\n\t * Make a copy of the tags for the window, replacing window names with\n\t * pointers to the pathName from the appropriate window.\n\t */\n\n\tif (winPtr->numTags > MAX_OBJS) {\n\t    objPtr = (void **)Tcl_Alloc(winPtr->numTags * sizeof(void *));\n\t}\n\tfor (i = 0; i < winPtr->numTags; i++) {\n\t    p = (char *)winPtr->tagPtr[i];\n\t    if (*p == '.') {\n\t\thPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);\n\t\tif (hPtr != NULL) {\n\t\t    p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;\n\t\t} else {\n\t\t    p = NULL;\n\t\t}\n\t    }\n\t    objPtr[i] = p;\n\t}\n\tcount = winPtr->numTags;\n    } else {\n\tobjPtr[0] = winPtr->pathName;\n\tobjPtr[1] = (void *)winPtr->classUid;\n\tfor (topLevPtr = winPtr;\n\t\t(topLevPtr != NULL) && !(topLevPtr->flags & TK_TOP_HIERARCHY);\n\t\ttopLevPtr = topLevPtr->parentPtr) {\n\t    /* Empty loop body. */\n\t}\n\tif ((winPtr != topLevPtr) && (topLevPtr != NULL)) {\n\t    count = 4;\n\t    objPtr[2] = topLevPtr->pathName;\n\t} else {\n\t    count = 3;\n\t}\n\tobjPtr[count-1] = (void *) Tk_GetUid(\"all\");\n    }\n    Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,\n\t    count, objPtr);\n    if (objPtr != objects) {\n\tTcl_Free(objPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_BindtagsObjCmd --\n *\n *\tThis function is invoked to process the \"bindtags\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_BindtagsObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkWindow *winPtr, *winPtr2;\n    Tcl_Size i, length;\n    const char *p;\n    Tcl_Obj *listPtr, **tags;\n\n    if ((objc < 2) || (objc > 3)) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window ?taglist?\");\n\treturn TCL_ERROR;\n    }\n    winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]),\n\t    tkwin);\n    if (winPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n    if (objc == 2) {\n\tlistPtr = Tcl_NewObj();\n\tif (winPtr->numTags == 0) {\n\t    Tcl_ListObjAppendElement(NULL, listPtr,\n\t\t    Tcl_NewStringObj(winPtr->pathName, TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(NULL, listPtr,\n\t\t    Tcl_NewStringObj(winPtr->classUid, TCL_INDEX_NONE));\n\t    winPtr2 = winPtr;\n\t    while ((winPtr2 != NULL) && !(Tk_TopWinHierarchy(winPtr2))) {\n\t\twinPtr2 = winPtr2->parentPtr;\n\t    }\n\t    if ((winPtr != winPtr2) && (winPtr2 != NULL)) {\n\t\tTcl_ListObjAppendElement(NULL, listPtr,\n\t\t\tTcl_NewStringObj(winPtr2->pathName, TCL_INDEX_NONE));\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, listPtr,\n\t\t    Tcl_NewStringObj(\"all\", TCL_INDEX_NONE));\n\t} else {\n\t    for (i = 0; i < winPtr->numTags; i++) {\n\t\tTcl_ListObjAppendElement(NULL, listPtr,\n\t\t\tTcl_NewStringObj((const char *)winPtr->tagPtr[i], TCL_INDEX_NONE));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, listPtr);\n\treturn TCL_OK;\n    }\n    if (winPtr->tagPtr != NULL) {\n\tTkFreeBindingTags(winPtr);\n    }\n    if (Tcl_ListObjGetElements(interp, objv[2], &length, &tags) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (length == 0) {\n\treturn TCL_OK;\n    }\n\n    winPtr->numTags = length;\n    winPtr->tagPtr = (void **)Tcl_Alloc(length * sizeof(void *));\n    for (i = 0; i < length; i++) {\n\tp = Tcl_GetString(tags[i]);\n\tif (p[0] == '.') {\n\t    char *copy;\n\n\t    /*\n\t     * Handle names starting with \".\" specially: store a malloc'ed\n\t     * string, rather than a Uid; at event time we'll look up the name\n\t     * in the window table and use the corresponding window, if there\n\t     * is one.\n\t     */\n\n\t    copy = (char *)Tcl_Alloc(strlen(p) + 1);\n\t    strcpy(copy, p);\n\t    winPtr->tagPtr[i] = copy;\n\t} else {\n\t    winPtr->tagPtr[i] = (void *)Tk_GetUid(p);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFreeBindingTags --\n *\n *\tThis function is called to free all of the binding tags associated\n *\twith a window; typically it is only invoked where there are\n *\twindow-specific tags.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAny binding tags for winPtr are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFreeBindingTags(\n    TkWindow *winPtr)\t\t/* Window whose tags are to be released. */\n{\n    Tcl_Size i;\n    char *p;\n\n    for (i = 0; i < winPtr->numTags; i++) {\n\tp = (char *)winPtr->tagPtr[i];\n\tif (*p == '.') {\n\t    /*\n\t     * Names starting with \".\" are malloced rather than Uids, so they\n\t     * have to be freed.\n\t     */\n\n\t    Tcl_Free(p);\n\t}\n    }\n    Tcl_Free(winPtr->tagPtr);\n    winPtr->numTags = 0;\n    winPtr->tagPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DestroyObjCmd --\n *\n *\tThis function is invoked to process the \"destroy\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_DestroyObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window window;\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tcl_Size i;\n\n    for (i = 1; i < objc; i++) {\n\twindow = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);\n\tif (window == NULL) {\n\t    Tcl_ResetResult(interp);\n\t    continue;\n\t}\n\tTk_DestroyWindow(window);\n\tif (window == tkwin) {\n\t    /*\n\t     * We just deleted the main window for the application! This makes\n\t     * it impossible to do anything more (tkwin isn't valid anymore).\n\t     */\n\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_LowerObjCmd --\n *\n *\tThis function is invoked to process the \"lower\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_LowerObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window mainwin = (Tk_Window)clientData;\n    Tk_Window tkwin, other;\n\n    if ((objc != 2) && (objc != 3)) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window ?belowThis?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n    if (objc == 2) {\n\tother = NULL;\n    } else {\n\tother = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);\n\tif (other == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {\n\tif (other) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't lower \\\"%s\\\" below \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[1]), Tcl_GetString(objv[2])));\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't lower \\\"%s\\\" to bottom\", Tcl_GetString(objv[1])));\n\t}\n\tTcl_SetErrorCode(interp, \"TK\", \"RESTACK\", \"LOWER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_RaiseObjCmd --\n *\n *\tThis function is invoked to process the \"raise\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_RaiseObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window mainwin = (Tk_Window)clientData;\n    Tk_Window tkwin, other;\n\n    if ((objc != 2) && (objc != 3)) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window ?aboveThis?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n    if (objc == 2) {\n\tother = NULL;\n    } else {\n\tother = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);\n\tif (other == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {\n\tif (other) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't raise \\\"%s\\\" above \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[1]), Tcl_GetString(objv[2])));\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't raise \\\"%s\\\" to top\", Tcl_GetString(objv[1])));\n\t}\n\tTcl_SetErrorCode(interp, \"TK\", \"RESTACK\", \"RAISE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkInitTkCmd --\n *\n *\tSet up the tk ensemble.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n * ----------------------------------------------------------------------\n */\n\nint\nTkInitTkCmd(\n    Tcl_Interp *interp,\n    void *clientData)\n{\n    /* If the interp is safe, leave out \"fontchooser\" */\n    int isSafe = Tcl_IsSafe(interp);\n    TkMakeEnsemble(interp, \"::\", \"tk\", clientData, tkCmdMap + isSafe);\n#if defined(_WIN32) || defined(MAC_OSX_TK)\n    if (!isSafe) {\n\tTkInitFontchooser(interp, clientData);\n    }\n#endif\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AppnameCmd, AttribtableCmd, CaretCmd, InactiveCmd, ScalingCmd,\n * UseinputmethodsCmd, WindowingsystemCmd --\n *\n *\tThese functions are invoked to process the \"tk\" ensemble subcommands.\n *\tSee the user documentation for details on what they do.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nAppnameCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkWindow *winPtr;\n    const char *string;\n\n    if (Tcl_IsSafe(interp)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"appname not accessible in a safe interpreter\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"APPLICATION\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    winPtr = (TkWindow *) tkwin;\n\n    if (objc == 2) {\n\tstring = Tcl_GetString(objv[1]);\n\twinPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string));\n    } else if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"?newName?\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->nameUid, TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\ntypedef struct AttribTableData {\n    Tcl_HashTable *tablePtr;\n} AttribTableData;\n\ntypedef struct AttribTableValue {\n    Tk_Window tkwin;\n    Tcl_HashTable *tablePtr;\n    Tcl_Obj *dictPtr;\n} AttribTableValue;\n\nint\nAttribtableCmd(\n    TCL_UNUSED(void *),\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    const char *tableName;\n    Tcl_Size nameLen;\n    Tcl_DString dsCmdName;\n    const char *cmdName;\n    AttribTableData *tblData;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"tableName\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Get tableName and build the fully qualified name cmdName from it\n     */\n\n    tableName = Tcl_GetStringFromObj(objv[1], &nameLen);\n    Tcl_DStringInit(&dsCmdName);\n    if (nameLen < 2 || tableName[0] != ':' || tableName[1] != ':') {\n\tTcl_Namespace *curNs = Tcl_GetCurrentNamespace(interp);\n\n\tTcl_DStringAppend(&dsCmdName, curNs->fullName, TCL_INDEX_NONE);\n\tif (strlen(curNs->fullName) != 2) {\n\t    Tcl_DStringAppend(&dsCmdName, \"::\", TCL_INDEX_NONE);\n\t}\n    }\n    Tcl_DStringAppend(&dsCmdName, tableName, TCL_INDEX_NONE);\n    cmdName = Tcl_DStringValue(&dsCmdName);\n\n    /*\n     * Create an attribute table command of the name cmdName\n     */\n\n    tblData = (AttribTableData *)Tcl_Alloc(sizeof(AttribTableData));\n    tblData->tablePtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n    Tcl_InitHashTable(tblData->tablePtr, TCL_ONE_WORD_KEYS);\n\n    Tcl_CreateObjCommand2(interp, cmdName,\n\t    AttribTableProc, tblData, AttribTableDeleteProc);\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(cmdName, TCL_INDEX_NONE));\n    Tcl_DStringFree(&dsCmdName);\n\n    return TCL_OK;\n}\n\n/*\n * Called whenever the attribute table is invoked as command.\n */\n\nint\nAttribTableProc(\n    void *clientData,\t\t/* Pointer to an AttribTableData struct. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    AttribTableData *tblData = (AttribTableData *)clientData;\n    static const char *const optionStrings[] = {\n\t\"set\", \"get\", \"unset\", \"clear\", \"exists\", \"names\", \"pathnames\", NULL\n    };\n    enum options {\n\tTABLE_SET, TABLE_GET, TABLE_UNSET, TABLE_CLEAR,\n\tTABLE_EXISTS, TABLE_NAMES, TABLE_PATHNAMES\n    };\n    int index;\n    Tk_Window tkwin = NULL;\t/* Used in all subcommands except the last. */\n    Tcl_HashEntry *entryPtr;\t/* Used in all subcommands. */\n    AttribTableValue *value = NULL;\t/* Used in all subcommands. */\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"set|get|unset|clear|exists|names|pathnames args\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"subcommand\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc > 2) {\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),\n\t\tTk_MainWindow(interp));\n\tif (tkwin == NULL) {\n\t    if (index == TABLE_EXISTS || index == TABLE_PATHNAMES) {\n\t\t Tcl_ResetResult(interp);\n\t    } else {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n\n    switch ((enum options) index) {\n    case TABLE_SET: {\n\tint isNew;\n\tTcl_Size i;\n\n\tif (objc < 5 || objc % 2 == 0) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"pathName name value ?name value ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_CreateHashEntry(tblData->tablePtr, tkwin, &isNew);\n\tif (isNew) {\n\t    /*\n\t     * Create an AttribTableValue struct and insert it into the table.\n\t     */\n\n\t    value = (AttribTableValue *)Tcl_Alloc(sizeof(AttribTableValue));\n\t    value->tkwin = tkwin;\n\t    value->tablePtr = tblData->tablePtr;\n\t    value->dictPtr = Tcl_NewDictObj();\n\t    Tcl_IncrRefCount(value->dictPtr);\n\t    Tcl_SetHashValue(entryPtr, value);\n\n\t    /*\n\t     * Arrange for AttribTableDestroyHandler to be invoked\n\t     * when the window identified by tkwin gets destroyed.\n\t     */\n\n\t    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t    AttribTableDestroyHandler, value);\n\t} else {\n\t    value = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\t    if (Tcl_IsShared(value->dictPtr)) {\n\t\t/*\n\t\t * For Tcl_DictObjPut below the dictionary must not be shared.\n\t\t */\n\n\t\tTcl_DecrRefCount(value->dictPtr);\n\t\tvalue->dictPtr = Tcl_DuplicateObj(value->dictPtr);\n\t\tTcl_IncrRefCount(value->dictPtr);\n\t    }\n\t}\n\n\tfor (i = 3; i < objc; i += 2) {\n\t    Tcl_DictObjPut(NULL, value->dictPtr, objv[i], objv[i+1]);\n\t}\n\tbreak;\n    }\n\n    case TABLE_GET: {\n\tif (objc < 3 || objc > 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"pathName ?name ?defaultValue??\");\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_FindHashEntry(tblData->tablePtr, tkwin);\n\tif (entryPtr != NULL) {\n\t    value = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\t}\n\n\tif (objc == 3) {\n\t    if (entryPtr != NULL) {\n\t\tTcl_SetObjResult(interp, value->dictPtr);\n\t    }\n\t} else {\n\t    Tcl_Obj *defaultValuePtr = (objc == 5 ? objv[4] : Tcl_NewObj());\n\n\t    if (entryPtr == NULL) {\n\t\tTcl_SetObjResult(interp, defaultValuePtr);\n\t    } else {\n\t\tTcl_Obj *resultPtr;\n\n\t\tTcl_DictObjGet(NULL, value->dictPtr, objv[3], &resultPtr);\n\t\tif (resultPtr == NULL) {\n\t\t    resultPtr = defaultValuePtr;\n\t\t}\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t    }\n\t}\n\tbreak;\n    }\n\n    case TABLE_UNSET: {\n\tTcl_Size i;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName name ?name ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_FindHashEntry(tblData->tablePtr, tkwin);\n\tif (entryPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\n\tvalue = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\tif (Tcl_IsShared(value->dictPtr)) {\n\t    /*\n\t     * For Tcl_DictObjRemove below the dictionary must not be shared.\n\t     */\n\n\t    Tcl_DecrRefCount(value->dictPtr);\n\t    value->dictPtr = Tcl_DuplicateObj(value->dictPtr);\n\t    Tcl_IncrRefCount(value->dictPtr);\n\t}\n\n\tfor (i = 3; i < objc; i++) {\n\t    Tcl_DictObjRemove(NULL, value->dictPtr, objv[i]);\n\t}\n\tbreak;\n    }\n\n    case TABLE_CLEAR: {\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName\");\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_FindHashEntry(tblData->tablePtr, tkwin);\n\tif (entryPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * Delete the event handler associated with value->tkwin.\n\t */\n\n\tvalue = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\tTk_DeleteEventHandler(value->tkwin, StructureNotifyMask,\n\t\tAttribTableDestroyHandler, value);\n\n\t/*\n\t * Remove the entry from the hash table.\n\t */\n\n\tTcl_DecrRefCount(value->dictPtr);\n\tTcl_DeleteHashEntry(entryPtr);\n\tTcl_Free(value);\n\tbreak;\n    }\n\n    case TABLE_EXISTS: {\n\tTcl_Obj *resultPtr;\n\n\tif (objc != 3 && objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName ?name?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (tkwin == NULL) {\n\t    resultPtr = Tcl_NewIntObj(0);\n\t} else {\n\t    entryPtr = Tcl_FindHashEntry(tblData->tablePtr, tkwin);\n\t    if (entryPtr == NULL) {\n\t\tresultPtr = Tcl_NewIntObj(0);\n\t    } else {\n\t\tvalue = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\t\tif (objc == 3) {\n\t\t    Tcl_Size size;\n\n\t\t    Tcl_DictObjSize(interp, value->dictPtr, &size);\n\t\t    resultPtr = Tcl_NewIntObj(size != 0);\n\t\t} else {\n\t\t    Tcl_Obj *testObj;\n\n\t\t    Tcl_DictObjGet(NULL, value->dictPtr, objv[3], &testObj);\n\t\t    resultPtr = Tcl_NewIntObj(testObj != NULL);\n\t\t}\n\t    }\n\t}\n\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n\n    case TABLE_NAMES: {\n\tTcl_Obj *resultPtr;\n\tTcl_DictSearch search;\n\tTcl_Obj *key;\n\tint done;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName\");\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_FindHashEntry(tblData->tablePtr, tkwin);\n\tif (entryPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\n\tresultPtr = Tcl_NewObj();\n\tvalue = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\tTcl_DictObjFirst(interp, value->dictPtr, &search, &key, NULL, &done);\n\twhile (!done) {\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, key);\n\t    Tcl_DictObjNext(&search, &key, NULL, &done);\n\t}\n\tTcl_DictObjDone(&search);\n\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n\n    case TABLE_PATHNAMES: {\n\tTcl_Obj *resultPtr;\n\tTcl_HashSearch search;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tresultPtr = Tcl_NewObj();\n\tfor (entryPtr = Tcl_FirstHashEntry(tblData->tablePtr, &search);\n\t\tentryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_Size size;\n\n\t    value = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\t    Tcl_DictObjSize(interp, value->dictPtr, &size);\n\t    if (size != 0) {\n\t\tTcl_ListObjAppendElement(NULL, resultPtr,\n\t\t\tTcl_NewStringObj(Tk_PathName(value->tkwin), -1));\n\t    }\n\t}\n\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n    } /* switch */\n\n    return TCL_OK;\n}\n\n/*\n * Called before the attribute table command is deleted from the interpreter.\n */\n\nvoid\nAttribTableDeleteProc(\n    void *clientData)\t\t/* Pointer to an AttribTableData struct. */\n{\n    AttribTableData *tblData = (AttribTableData *)clientData;\n    Tcl_HashEntry *entryPtr;\n    Tcl_HashSearch search;\n\n    for (entryPtr = Tcl_FirstHashEntry(tblData->tablePtr, &search);\n\t    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {\n\tAttribTableValue *value = (AttribTableValue *)Tcl_GetHashValue(entryPtr);\n\n\t/*\n\t * Delete the event handler associated with value->tkwin.\n\t */\n\n\tTk_DeleteEventHandler(value->tkwin, StructureNotifyMask,\n\t\tAttribTableDestroyHandler, value);\n\n\t/*\n\t * Remove the entry from the hash table.\n\t */\n\n\tTcl_DecrRefCount(value->dictPtr);\n\tTcl_DeleteHashEntry(entryPtr);\n\tTcl_Free(value);\n    }\n\n    /*\n     * Free up the memory used by the hash table.\n     */\n\n    Tcl_DeleteHashTable(tblData->tablePtr);\n    Tcl_Free(tblData->tablePtr);\n    Tcl_Free(tblData);\n}\n\n/*\n * Called when the window identified by the first argument gets destroyed.\n */\n\nvoid\nAttribTableDestroyHandler(\n    void *clientData,\t\t/* Pointer to an AttribTableValue struct. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    AttribTableValue *value = (AttribTableValue *)clientData;\n    Tcl_HashEntry *entryPtr;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n\n    entryPtr = Tcl_FindHashEntry(value->tablePtr, value->tkwin);\n    if (entryPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Remove the entry from the hash table.\n     */\n\n    Tcl_DecrRefCount(value->dictPtr);\n    Tcl_DeleteHashEntry(entryPtr);\n    Tcl_Free(value);\n}\n\nint\nCaretCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    int index;\n    Tcl_Obj *objPtr;\n    TkCaret *caretPtr;\n    Tk_Window window;\n    static const char *const caretStrings[] = {\n\t\"-x\",\t\"-y\", \"-height\", NULL\n    };\n    enum caretOptions {\n\tTK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT\n    };\n\n    if ((objc < 2) || ((objc > 3) && !!(objc & 1))) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"window ?-x x? ?-y y? ?-height height?\");\n\treturn TCL_ERROR;\n    }\n    window = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);\n    if (window == NULL) {\n\treturn TCL_ERROR;\n    }\n    caretPtr = &(((TkWindow *) window)->dispPtr->caret);\n    if (objc == 2) {\n\t/*\n\t * Return all the current values\n\t */\n\n\tobjPtr = Tcl_NewObj();\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewStringObj(\"-height\", 7));\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewWideIntObj(caretPtr->height));\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewStringObj(\"-x\", 2));\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewWideIntObj(caretPtr->x));\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewStringObj(\"-y\", 2));\n\tTcl_ListObjAppendElement(interp, objPtr,\n\t\tTcl_NewWideIntObj(caretPtr->y));\n\tTcl_SetObjResult(interp, objPtr);\n    } else if (objc == 3) {\n\tint value;\n\n\t/*\n\t * Return the current value of the selected option\n\t */\n\n\tif (Tcl_GetIndexFromObj(interp, objv[2], caretStrings,\n\t\t\"caret option\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == TK_CARET_X) {\n\t    value = caretPtr->x;\n\t} else if (index == TK_CARET_Y) {\n\t    value = caretPtr->y;\n\t} else /* if (index == TK_CARET_HEIGHT) -- last case */ {\n\t    value = caretPtr->height;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(value));\n    } else {\n\tTcl_Size i;\n\tint value, x = 0, y = 0, height = -1;\n\n\tfor (i = 2; i < objc; i += 2) {\n\t    if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings,\n\t\t    \"caret option\", 0, &index) != TCL_OK) ||\n\t\t    Tcl_GetIntFromObj(interp,objv[i+1],&value) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (index == TK_CARET_X) {\n\t\tx = value;\n\t    } else if (index == TK_CARET_Y) {\n\t\ty = value;\n\t    } else /* if (index == TK_CARET_HEIGHT) -- last case */ {\n\t\theight = value;\n\t    }\n\t}\n\tif (height < 0) {\n\t    height = Tk_Height(window);\n\t}\n\tTk_SetCaretPos(window, x, y, height);\n    }\n    return TCL_OK;\n}\n\nint\nInactiveCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tcl_Size skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);\n\n    if (skip < 0) {\n\treturn TCL_ERROR;\n    }\n    if (objc == 1 + skip) {\n\tTcl_WideInt inactive;\n\n\tinactive = (Tcl_IsSafe(interp) ? -1 :\n\t\tTk_GetUserInactiveTime(Tk_Display(tkwin)));\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(inactive));\n    } else if (objc == 2 + skip) {\n\tconst char *string;\n\n\tstring = Tcl_GetString(objv[objc-1]);\n\tif (strcmp(string, \"reset\") != 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad option \\\"%s\\\": must be reset\", string));\n\t    Tcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"option\",\n\t\t    string, (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"resetting the user inactivity timer \"\n\t\t    \"is not allowed in a safe interpreter\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"INACTIVITY_TIMER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_ResetUserInactiveTime(Tk_Display(tkwin));\n\tTcl_ResetResult(interp);\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"?-displayof window? ?reset?\");\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\nint\nScalingCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Screen *screenPtr;\n    Tcl_Size skip;\n    int width, height, intPct;\n    double d, dblPct;\n\n    skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);\n    if (skip < 0) {\n\treturn TCL_ERROR;\n    }\n    screenPtr = Tk_Screen(tkwin);\n    if (objc == 1 + skip) {\n\td = 25.4 / 72;\n\td *= WidthOfScreen(screenPtr);\n\td /= WidthMMOfScreen(screenPtr);\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(d));\n    } else if (Tcl_IsSafe(interp)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"setting the scaling not accessible in a safe interpreter\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"SCALING\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (objc == 2 + skip) {\n\tif (Tcl_GetDoubleFromObj(interp, objv[1+skip], &d) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tdblPct = d * 75;\n\td = (25.4 / 72) / d;\n\twidth = (int) (d * WidthOfScreen(screenPtr) + 0.5);\n\tif (width <= 0) {\n\t    width = 1;\n\t}\n\theight = (int) (d * HeightOfScreen(screenPtr) + 0.5);\n\tif (height <= 0) {\n\t    height = 1;\n\t}\n\tWidthMMOfScreen(screenPtr) = width;\n\tHeightMMOfScreen(screenPtr) = height;\n\n\t/*\n\t * Keep the variables ::tk::scalingPct and ::tk::svgFmt\n\t * in sync with the new value of the scaling factor\n\t */\n\n\tfor (intPct = 100; 1; intPct += 25) {\n\t    if (dblPct < intPct + 12.5) {\n\t\tbreak;\n\t    }\n\t}\n\tTcl_SetVar2Ex(interp, \"::tk::scalingPct\", NULL, Tcl_NewIntObj(intPct),\n\t\tTCL_GLOBAL_ONLY);\n\n\tTcl_SetVar2Ex(interp, \"::tk::svgFmt\", NULL,\n\t\tTcl_NewStringObj(\"svg\", TCL_INDEX_NONE), TCL_GLOBAL_ONLY);\n\tTcl_SetVar2Ex(interp, \"::tk::svgFmt\", NULL,\n\t\tTcl_NewStringObj(\"-scale\", TCL_INDEX_NONE),\n\t\tTCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT);\n\tTcl_SetVar2Ex(interp, \"::tk::svgFmt\", NULL,\n\t\tTcl_NewDoubleObj(intPct / 100.0),\n\t\tTCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT);\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"?-displayof window? ?factor?\");\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\nint\nUseinputmethodsCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkDisplay *dispPtr;\n    Tcl_Size skip;\n\n    if (Tcl_IsSafe(interp)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"useinputmethods not accessible in a safe interpreter\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"INPUT_METHODS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);\n    if (skip < 0) {\n\treturn TCL_ERROR;\n    }\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    if (objc == 2 + skip) {\n\n\tint boolValue;\n\n\tif (Tcl_GetBooleanFromObj(interp, objv[1+skip],\n\t\t&boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue && (dispPtr->inputMethod != NULL)) {\n\t    dispPtr->flags |= TK_DISPLAY_USE_IM;\n\t} else {\n\t    dispPtr->flags &= ~TK_DISPLAY_USE_IM;\n\t}\n    } else if (objc != 1 + skip) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"?-displayof window? ?boolean?\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp,\n\t    Tcl_NewBooleanObj(dispPtr->flags & TK_DISPLAY_USE_IM));\n    return TCL_OK;\n}\n\nint\nWindowingsystemCmd(\n    TCL_UNUSED(void *),\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    const char *windowingsystem;\n\n    if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n#if defined(_WIN32)\n    windowingsystem = \"win32\";\n#elif defined(MAC_OSX_TK)\n    windowingsystem = \"aqua\";\n#elif defined(TK_USE_WAYLAND)\n    windowingsystem = \"wayland\";\n#else\n    windowingsystem = \"x11\";\n#endif\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(windowingsystem, TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_TkwaitObjCmd --\n *\n *\tThis function is invoked to process the \"tkwait\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_TkwaitObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    int done, index;\n    int code = TCL_OK;\n    static const char *const optionStrings[] = {\n\t\"variable\", \"visibility\", \"window\", NULL\n    };\n    enum options {\n\tTKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW\n    };\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"variable|visibility|window name\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case TKWAIT_VARIABLE:\n\tif (Tcl_TraceVar2(interp, Tcl_GetString(objv[2]),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tWaitVariableProc, &done) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tdone = 0;\n\twhile (!done) {\n\t    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {\n\t\tcode = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    Tcl_DoOneEvent(0);\n\t}\n\tTcl_UntraceVar2(interp, Tcl_GetString(objv[2]),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tWaitVariableProc, &done);\n\tbreak;\n\n    case TKWAIT_VISIBILITY: {\n\tTk_Window window;\n\n\twindow = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);\n\tif (window == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_CreateEventHandler(window,\n\t\tVisibilityChangeMask|StructureNotifyMask,\n\t\tWaitVisibilityProc, &done);\n\tdone = 0;\n\twhile (!done) {\n\t    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {\n\t\tcode = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    Tcl_DoOneEvent(0);\n\t}\n\tif ((done != 0) && (done != 1)) {\n\t    /*\n\t     * Note that we do not delete the event handler because it was\n\t     * deleted automatically when the window was destroyed.\n\t     */\n\n\t    Tcl_ResetResult(interp);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" was deleted before its visibility changed\",\n\t\t    Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WAIT\", \"PREMATURE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_DeleteEventHandler(window,\n\t\tVisibilityChangeMask|StructureNotifyMask,\n\t\tWaitVisibilityProc, &done);\n\tbreak;\n    }\n\n    case TKWAIT_WINDOW: {\n\tTk_Window window;\n\n\twindow = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);\n\tif (window == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_CreateEventHandler(window, StructureNotifyMask,\n\t\tWaitWindowProc, &done);\n\tdone = 0;\n\twhile (!done) {\n\t    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {\n\t\tcode = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    Tcl_DoOneEvent(0);\n\t}\n\n\t/*\n\t * Note: normally there's no need to delete the event handler. It was\n\t * deleted automatically when the window was destroyed; however, if\n\t * the wait operation was canceled, we need to delete it.\n\t */\n\n\tif (done == 0) {\n\t    Tk_DeleteEventHandler(window, StructureNotifyMask,\n\t\t    WaitWindowProc, &done);\n\t}\n\tbreak;\n    }\n    }\n\n    /*\n     * Clear out the interpreter's result, since it may have been set by event\n     * handlers. This is skipped if an error occurred above, such as the wait\n     * operation being canceled.\n     */\n\n    if (code == TCL_OK)\n    Tcl_ResetResult(interp);\n\n    return code;\n}\n\nstatic char *\nWaitVariableProc(\n    void *clientData,\t\t/* Pointer to integer to set to 1. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    const char *name1,\t\t/* Name of variable. */\n    TCL_UNUSED(const char *),\t/* Second part of variable name. */\n    TCL_UNUSED(int))\t\t/* Information about what happened. */\n{\n    int *donePtr = (int *)clientData;\n\n    *donePtr = 1;\n    Tcl_UntraceVar(interp, name1, TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t    WaitVariableProc, clientData);\n    return NULL;\n}\n\nstatic void\nWaitVisibilityProc(\n    void *clientData,\t\t/* Pointer to integer to set to 1. */\n    XEvent *eventPtr)\t\t/* Information about event (not used). */\n{\n    int *donePtr = (int *)clientData;\n\n    if (eventPtr->type == VisibilityNotify) {\n\t*donePtr = 1;\n    } else if (eventPtr->type == DestroyNotify) {\n\t*donePtr = 2;\n    }\n}\n\nstatic void\nWaitWindowProc(\n    void *clientData,\t\t/* Pointer to integer to set to 1. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    int *donePtr = (int *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\t*donePtr = 1;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UpdateObjCmd --\n *\n *\tThis function is invoked to process the \"update\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_UpdateObjCmd(\n    TCL_UNUSED(void *),\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const updateOptions[] = {\"idletasks\", NULL};\n    int flags, index;\n    TkDisplay *dispPtr;\n    int code = TCL_OK;\n\n    if (objc == 1) {\n\tflags = TCL_DONT_WAIT;\n    } else if (objc == 2) {\n\tif (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, \"option\", 0,\n\t\t&index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tflags = TCL_IDLE_EVENTS;\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"?idletasks?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Handle all pending events, sync all displays, and repeat over and over\n     * again until all pending events have been handled. Special note: it's\n     * possible that the entire application could be destroyed by an event\n     * handler that occurs during the update. Thus, don't use any information\n     * from tkwin after calling Tcl_DoOneEvent.\n     */\n\n    while (1) {\n\twhile (Tcl_DoOneEvent(flags) != 0) {\n\t    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {\n\t\tcode = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * If event processing was canceled proceed no further.\n\t */\n\n\tif (code == TCL_ERROR)\n\t    break;\n\n\tfor (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t\tdispPtr = dispPtr->nextPtr) {\n\t    XSync(dispPtr->display, False);\n\t}\n\n\t/*\n\t * Check again if event processing has been canceled because the inner\n\t * loop (above) may not have checked (i.e. no events were processed and\n\t * the loop body was skipped).\n\t */\n\n\tif (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {\n\t    code = TCL_ERROR;\n\t    break;\n\t}\n\n\tif (Tcl_DoOneEvent(flags) == 0) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Must clear the interpreter's result because event handlers could have\n     * executed commands. This is skipped if an error occurred above, such as\n     * the wait operation being canceled.\n     */\n\n    if (code == TCL_OK)\n    Tcl_ResetResult(interp);\n\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_WinfoObjCmd --\n *\n *\tThis function is invoked to process the \"winfo\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_WinfoObjCmd(\n    void *clientData,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int index, x, y, width, height, useX, useY, c_class;\n    Tcl_Size skip;\n    const char *string;\n    TkWindow *winPtr;\n    Tk_Window tkwin = (Tk_Window)clientData;\n\n    static const TkStateMap visualMap[] = {\n\t{PseudoColor,\t\"pseudocolor\"},\n\t{GrayScale,\t\"grayscale\"},\n\t{DirectColor,\t\"directcolor\"},\n\t{TrueColor,\t\"truecolor\"},\n\t{StaticColor,\t\"staticcolor\"},\n\t{StaticGray,\t\"staticgray\"},\n\t{-1,\t\tNULL}\n    };\n    static const char *const optionStrings[] = {\n\t\"cells\",\t\"children\",\t\"class\",\t\"colormapfull\",\n\t\"depth\",\t\"geometry\",\t\"height\",\t\"id\",\n\t\"ismapped\",\t\"manager\",\t\"name\",\t\t\"parent\",\n\t\"pointerx\",\t\"pointery\",\t\"pointerxy\",\t\"reqheight\",\n\t\"reqwidth\",\t\"rootx\",\t\"rooty\",\t\"screen\",\n\t\"screencells\",\t\"screendepth\",\t\"screenheight\",\t\"screenwidth\",\n\t\"screenmmheight\",\"screenmmwidth\",\"screenvisual\",\"server\",\n\t\"toplevel\",\t\"viewable\",\t\"visual\",\t\"visualid\",\n\t\"vrootheight\",\t\"vrootwidth\",\t\"vrootx\",\t\"vrooty\",\n\t\"width\",\t\"x\",\t\t\"y\",\n\n\t\"atom\",\t\t\"atomname\",\t\"containing\",\t\"interps\",\n\t\"pathname\",\n\n\t\"exists\",\t\"fpixels\",\t\"pixels\",\t\"rgb\",\n\t\"visualsavailable\",\n\n\tNULL\n    };\n    enum options {\n\tWIN_CELLS,\tWIN_CHILDREN,\tWIN_CLASS,\tWIN_COLORMAPFULL,\n\tWIN_DEPTH,\tWIN_GEOMETRY,\tWIN_HEIGHT,\tWIN_ID,\n\tWIN_ISMAPPED,\tWIN_MANAGER,\tWIN_NAME,\tWIN_PARENT,\n\tWIN_POINTERX,\tWIN_POINTERY,\tWIN_POINTERXY,\tWIN_REQHEIGHT,\n\tWIN_REQWIDTH,\tWIN_ROOTX,\tWIN_ROOTY,\tWIN_SCREEN,\n\tWIN_SCREENCELLS,WIN_SCREENDEPTH,WIN_SCREENHEIGHT,WIN_SCREENWIDTH,\n\tWIN_SCREENMMHEIGHT,WIN_SCREENMMWIDTH,WIN_SCREENVISUAL,WIN_SERVER,\n\tWIN_TOPLEVEL,\tWIN_VIEWABLE,\tWIN_VISUAL,\tWIN_VISUALID,\n\tWIN_VROOTHEIGHT,WIN_VROOTWIDTH,\tWIN_VROOTX,\tWIN_VROOTY,\n\tWIN_WIDTH,\tWIN_X,\t\tWIN_Y,\n\n\tWIN_ATOM,\tWIN_ATOMNAME,\tWIN_CONTAINING,\tWIN_INTERPS,\n\tWIN_PATHNAME,\n\n\tWIN_EXISTS,\tWIN_FPIXELS,\tWIN_PIXELS,\tWIN_RGB,\n\tWIN_VISUALSAVAILABLE\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (index < WIN_ATOM) {\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[2]);\n\ttkwin = Tk_NameToWindow(interp, string, tkwin);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    winPtr = (TkWindow *) tkwin;\n\n    switch ((enum options) index) {\n    case WIN_CELLS:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(Tk_Visual(tkwin)->map_entries));\n\tbreak;\n    case WIN_CHILDREN: {\n\tTcl_Obj *strPtr, *resultPtr = Tcl_NewObj();\n\n\twinPtr = winPtr->childList;\n\tfor ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {\n\t    if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) {\n\t\tstrPtr = Tcl_NewStringObj(winPtr->pathName, TCL_INDEX_NONE);\n\t\tTcl_ListObjAppendElement(NULL, resultPtr, strPtr);\n\t    }\n\t}\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n    case WIN_CLASS:\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(Tk_Class(tkwin), TCL_INDEX_NONE));\n\tbreak;\n    case WIN_COLORMAPFULL:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewBooleanObj(TkpCmapStressed(tkwin,Tk_Colormap(tkwin))));\n\tbreak;\n    case WIN_DEPTH:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Depth(tkwin)));\n\tbreak;\n    case WIN_GEOMETRY:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%dx%d+%d+%d\",\n\t\tTk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin)));\n\tbreak;\n    case WIN_HEIGHT:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Height(tkwin)));\n\tbreak;\n    case WIN_ID: {\n\tchar buf[TCL_INTEGER_SPACE];\n\n\tTk_MakeWindowExist(tkwin);\n\tTkpPrintWindowId(buf, Tk_WindowId(tkwin));\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case WIN_ISMAPPED:\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(Tk_IsMapped(tkwin)));\n\tbreak;\n    case WIN_MANAGER:\n\tif (winPtr->geomMgrPtr != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(winPtr->geomMgrPtr->name, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    case WIN_NAME:\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(Tk_Name(tkwin), TCL_INDEX_NONE));\n\tbreak;\n    case WIN_PARENT:\n\tif (winPtr->parentPtr != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(winPtr->parentPtr->pathName, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    case WIN_POINTERX:\n\tuseX = 1;\n\tuseY = 0;\n\tgoto pointerxy;\n    case WIN_POINTERY:\n\tuseX = 0;\n\tuseY = 1;\n\tgoto pointerxy;\n    case WIN_POINTERXY:\n\tuseX = 1;\n\tuseY = 1;\n\n    pointerxy:\n\twinPtr = GetTopHierarchy(tkwin);\n\tif (winPtr == NULL) {\n\t    x = -1;\n\t    y = -1;\n\t} else {\n\t    TkGetPointerCoords((Tk_Window) winPtr, &x, &y);\n\t}\n\tif (useX & useY) {\n\t    Tcl_Obj *xyObj[2];\n\n\t    xyObj[0] = Tcl_NewWideIntObj(x);\n\t    xyObj[1] = Tcl_NewWideIntObj(y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, xyObj));\n\t} else if (useX) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y));\n\t}\n\tbreak;\n    case WIN_REQHEIGHT:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqHeight(tkwin)));\n\tbreak;\n    case WIN_REQWIDTH:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqWidth(tkwin)));\n\tbreak;\n    case WIN_ROOTX:\n\tTk_GetRootCoords(tkwin, &x, &y);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(x));\n\tbreak;\n    case WIN_ROOTY:\n\tTk_GetRootCoords(tkwin, &x, &y);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(y));\n\tbreak;\n    case WIN_SCREEN:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%s.%d\",\n\t\tTk_DisplayName(tkwin), Tk_ScreenNumber(tkwin)));\n\tbreak;\n    case WIN_SCREENCELLS:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(CellsOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENDEPTH:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENHEIGHT:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(HeightOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENWIDTH:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(WidthOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENMMHEIGHT:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(HeightMMOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENMMWIDTH:\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(WidthMMOfScreen(Tk_Screen(tkwin))));\n\tbreak;\n    case WIN_SCREENVISUAL:\n\tc_class = DefaultVisualOfScreen(Tk_Screen(tkwin))->c_class;\n\tgoto visual;\n    case WIN_SERVER:\n\tTkGetServerInfo(interp, tkwin);\n\tbreak;\n    case WIN_TOPLEVEL:\n\twinPtr = GetTopHierarchy(tkwin);\n\tif (winPtr != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->pathName, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    case WIN_VIEWABLE: {\n\tint viewable = 0;\n\n\tfor ( ; ; winPtr = winPtr->parentPtr) {\n\t    if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {\n\t\tbreak;\n\t    }\n\t    if (winPtr->flags & TK_TOP_HIERARCHY) {\n\t\tviewable = 1;\n\t\tbreak;\n\t    }\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(viewable));\n\tbreak;\n    }\n    case WIN_VISUAL:\n\tc_class = Tk_Visual(tkwin)->c_class;\n\n    visual:\n\tstring = TkFindStateString(visualMap, c_class);\n\tif (string == NULL) {\n\t    string = \"unknown\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(string, TCL_INDEX_NONE));\n\tbreak;\n    case WIN_VISUALID:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"0x%x\", (unsigned)\n\t\tXVisualIDFromVisual(Tk_Visual(tkwin))));\n\tbreak;\n    case WIN_VROOTHEIGHT:\n\tTk_GetVRootGeometry(tkwin, &x, &y, &width, &height);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(height));\n\tbreak;\n    case WIN_VROOTWIDTH:\n\tTk_GetVRootGeometry(tkwin, &x, &y, &width, &height);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(width));\n\tbreak;\n    case WIN_VROOTX:\n\tTk_GetVRootGeometry(tkwin, &x, &y, &width, &height);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(x));\n\tbreak;\n    case WIN_VROOTY:\n\tTk_GetVRootGeometry(tkwin, &x, &y, &width, &height);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(y));\n\tbreak;\n    case WIN_WIDTH:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Width(tkwin)));\n\tbreak;\n    case WIN_X:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_X(tkwin)));\n\tbreak;\n    case WIN_Y:\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Y(tkwin)));\n\tbreak;\n\n\t/*\n\t * Uses -displayof.\n\t */\n\n    case WIN_ATOM:\n\tskip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 3 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window? name\");\n\t    return TCL_ERROR;\n\t}\n\tobjv += skip;\n\tstring = Tcl_GetString(objv[2]);\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewWideIntObj(Tk_InternAtom(tkwin, string)));\n\tbreak;\n    case WIN_ATOMNAME: {\n\tconst char *name;\n\tTcl_WideInt id;\n\n\tskip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 3 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window? id\");\n\t    return TCL_ERROR;\n\t}\n\tobjv += skip;\n\tif (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tname = Tk_GetAtomName(tkwin, (Atom) id);\n\tif (strcmp(name, \"?bad atom?\") == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no atom exists with id \\\"%s\\\"\", Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"ATOM\",\n\t\t    Tcl_GetString(objv[2]), (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(name, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case WIN_CONTAINING:\n\tskip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 4 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"?-displayof window? rootX rootY\");\n\t    return TCL_ERROR;\n\t}\n\tobjv += skip;\n\tstring = Tcl_GetString(objv[2]);\n\tif (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[3]);\n\tif (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_CoordsToWindow(x, y, tkwin);\n\tif (tkwin != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), TCL_INDEX_NONE));\n\t}\n\tbreak;\n    case WIN_INTERPS:\n\tskip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 2 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window?\");\n\t    return TCL_ERROR;\n\t}\n\treturn TkGetInterpNames(interp, tkwin);\n    case WIN_PATHNAME: {\n\tWindow id;\n\n\tskip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 3 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window? id\");\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[2 + skip]);\n\tif (TkpScanWindowId(interp, string, &id) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\twinPtr = (TkWindow *) Tk_IdToWindow(Tk_Display(tkwin), id);\n\tif ((winPtr == NULL) ||\n\t\t(winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window id \\\"%s\\\" does not exist in this application\",\n\t\t    string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"WINDOW\", string, (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * If the window is a utility window with no associated path (such as\n\t * a wrapper window or send communication window), just return an\n\t * empty string.\n\t */\n\n\ttkwin = (Tk_Window) winPtr;\n\tif (Tk_PathName(tkwin) != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), TCL_INDEX_NONE));\n\t}\n\tbreak;\n    }\n\n\t/*\n\t * objv[3] is window.\n\t */\n\n    case WIN_EXISTS: {\n\tint alive;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[2]);\n\twinPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);\n\tTcl_ResetResult(interp);\n\n\talive = 1;\n\tif ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) {\n\t    alive = 0;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(alive));\n\tbreak;\n    }\n    case WIN_FPIXELS: {\n\tdouble mm, pixels;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window number\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[3]);\n\tif (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tpixels = mm * WidthOfScreen(Tk_Screen(tkwin))\n\t\t/ WidthMMOfScreen(Tk_Screen(tkwin));\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(pixels));\n\tbreak;\n    }\n    case WIN_PIXELS: {\n\tint pixels;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window number\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[3]);\n\tif (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(pixels));\n\tbreak;\n    }\n    case WIN_RGB: {\n\tXColor *colorPtr;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window colorName\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n#ifdef TK_HAS_DYNAMIC_COLORS\n\n\t/*\n\t * Make sure that the TkColor used for the winfo rgb command is\n\t * destroyed when we are through with it, so we do not get stale RGB\n\t * values next time.\n\t */\n\n\t{\n\t    Colormap temp = Tk_Colormap(tkwin);\n\t    Tk_Colormap(tkwin) = TK_DYNAMIC_COLORMAP;\n\t    colorPtr = Tk_AllocColorFromObj(interp, tkwin, objv[3]);\n\t    Tk_Colormap(tkwin) = temp;\n\t}\n#else\n\tcolorPtr = Tk_AllocColorFromObj(interp, tkwin, objv[3]);\n#endif\n\tif (colorPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%d %d %d\",\n\t\tcolorPtr->red, colorPtr->green, colorPtr->blue));\n\tTk_FreeColor(colorPtr);\n\tbreak;\n    }\n    case WIN_VISUALSAVAILABLE: {\n\tXVisualInfo templ, *visInfoPtr;\n\tint count, i;\n\tint includeVisualId;\n\tTcl_Obj *strPtr, *resultPtr;\n\tchar buf[16 + TCL_INTEGER_SPACE];\n\tchar visualIdString[TCL_INTEGER_SPACE];\n\n\tif (objc == 3) {\n\t    includeVisualId = 0;\n\t} else if ((objc == 4)\n\t\t&& (strcmp(Tcl_GetString(objv[3]), \"includeids\") == 0)) {\n\t    includeVisualId = 1;\n\t} else {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?includeids?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\ttempl.screen = Tk_ScreenNumber(tkwin);\n\tvisInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,\n\t\t&templ, &count);\n\tif (visInfoPtr == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't find any visuals for screen\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VISUAL\", \"NONE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tresultPtr = Tcl_NewObj();\n\tfor (i = 0; i < count; i++) {\n\t    string = TkFindStateString(visualMap, visInfoPtr[i].c_class);\n\t    if (string == NULL) {\n\t\tstrcpy(buf, \"unknown\");\n\t    } else {\n\t\tsnprintf(buf, sizeof(buf), \"%s %d\", string, visInfoPtr[i].depth);\n\t    }\n\t    if (includeVisualId) {\n\t\tsnprintf(visualIdString, sizeof(visualIdString), \" 0x%lx\",\n\t\t\t(unsigned long) visInfoPtr[i].visualid);\n\t\tstrcat(buf, visualIdString);\n\t    }\n\t    strPtr = Tcl_NewStringObj(buf, TCL_INDEX_NONE);\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);\n\t}\n\tTcl_SetObjResult(interp, resultPtr);\n\tXFree(visInfoPtr);\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * TkGetDisplayOf --\n *\n *\tParses a \"-displayof window\" option for various commands. If present,\n *\tthe literal \"-displayof\" should be in objv[0] and the window name in\n *\tobjv[1].\n *\n * Results:\n *\tThe return value is 0 if the argument strings did not contain the\n *\t\"-displayof\" option. The return value is 2 if the argument strings\n *\tcontained both the \"-displayof\" option and a valid window name.\n *\tOtherwise, the return value is TCL_INDEX_NONE if the window name\n *\twas missing or did not specify a valid window.\n *\n *\tIf the return value was 2, *tkwinPtr is filled with the token for the\n *\twindow specified on the command line. If the return value was\n *\tTCL_INDEX_NONE, an error message is left in interp's result object.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkGetDisplayOf(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. If it is present,\n\t\t\t\t * \"-displayof\" should be in objv[0] and\n\t\t\t\t * objv[1] the name of a window. */\n    Tk_Window *tkwinPtr)\t/* On input, contains main window of\n\t\t\t\t * application associated with interp. On\n\t\t\t\t * output, filled with window specified as\n\t\t\t\t * option to \"-displayof\" argument, or\n\t\t\t\t * unmodified if \"-displayof\" argument was not\n\t\t\t\t * present. */\n{\n    const char *string;\n    Tcl_Size length;\n\n    if (objc + 1 < 2) {\n\treturn 0;\n    }\n    string = Tcl_GetStringFromObj(objv[0], &length);\n    if ((length >= 2) &&\n\t    (strncmp(string, \"-displayof\", length) == 0)) {\n\tif (objc < 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"value for \\\"-displayof\\\" missing\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"NO_VALUE\", \"DISPLAYOF\", (char *)NULL);\n\t    return TCL_INDEX_NONE;\n\t}\n\t*tkwinPtr = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), *tkwinPtr);\n\tif (*tkwinPtr == NULL) {\n\t    return TCL_INDEX_NONE;\n\t}\n\treturn 2;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDeadAppObjCmd --\n *\n *\tIf an application has been deleted then all Tk commands will be\n *\tre-bound to this function.\n *\n * Results:\n *\tA standard Tcl error is reported to let the user know that the\n *\tapplication is dead.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkDeadAppObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"cannot invoke \\\"%s\\\" command: application has been destroyed\",\n\t    Tcl_GetString(objv[0])));\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTopHierarchy --\n *\n *\tRetrieves the top-of-hierarchy window which is the nearest ancestor of\n *\tthe specified window.\n *\n * Results:\n *\tReturns the top-of-hierarchy window, or NULL if the window has no\n *\tancestor which is at the top of a physical window hierarchy.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkWindow *\nGetTopHierarchy(\n    Tk_Window tkwin)\t\t/* Window for which the top-of-hierarchy\n\t\t\t\t * ancestor should be determined. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    while ((winPtr != NULL) && !(winPtr->flags & TK_TOP_HIERARCHY)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    return winPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkColor.c",
    "content": "/*\n * tkColor.c --\n *\n *\tThis file maintains a database of color values for the Tk toolkit, in\n *\torder to avoid round-trips to the server to map color names to pixel\n *\tvalues.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkColor.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Structures of the following following type are used as keys for\n * colorValueTable (in TkDisplay).\n */\n\ntypedef struct {\n    int red, green, blue;\t/* Values for desired color. */\n    Colormap colormap;\t\t/* Colormap from which color will be\n\t\t\t\t * allocated. */\n    Display *display;\t\t/* Display for colormap. */\n} ValueKey;\n\n/*\n * The structure below is used to allocate thread-local data.\n */\n\ntypedef struct {\n    char rgbString[20];\t\t/* */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tColorInit(TkDisplay *dispPtr);\nstatic void\t\tDupColorObjProc(Tcl_Obj *srcObjPtr,Tcl_Obj *dupObjPtr);\nstatic void\t\tFreeColorObj(Tcl_Obj *objPtr);\nstatic void\t\tFreeColorObjProc(Tcl_Obj *objPtr);\nstatic void\t\tInitColorObj(Tcl_Obj *objPtr);\n\n/*\n * The following structure defines the implementation of the \"color\" Tcl\n * object, which maps a string color name to a TkColor object. The ptr1 field\n * of the Tcl_Obj points to a TkColor object.\n */\n\nconst Tcl_ObjType tkColorObjType = {\n    \"color\",\t\t\t/* name */\n    FreeColorObjProc,\t\t/* freeIntRepProc */\n    DupColorObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V1(TkLengthOne)\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_AllocColorFromObj --\n *\n *\tGiven a Tcl_Obj *, map the value to a corresponding XColor structure\n *\tbased on the tkwin given.\n *\n * Results:\n *\tThe return value is a pointer to an XColor structure that indicates\n *\tthe red, blue, and green intensities for the color given by the string\n *\tin objPtr, and also specifies a pixel value to use to draw in that\n *\tcolor. If an error occurs, NULL is returned and an error message will\n *\tbe left in interp's result (unless interp is NULL).\n *\n * Side effects:\n *\tThe color is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeColorFromObj so that the database is cleaned up when colors\n *\taren't in use anymore.\n *\n *----------------------------------------------------------------------\n */\n\nXColor *\nTk_AllocColorFromObj(\n    Tcl_Interp *interp,\t\t/* Used only for error reporting. If NULL,\n\t\t\t\t * then no messages are provided. */\n    Tk_Window tkwin,\t\t/* Window in which the color will be used.*/\n    Tcl_Obj *objPtr)\t\t/* Object that describes the color; string\n\t\t\t\t * value is a color name such as \"red\" or\n\t\t\t\t * \"#ff0000\".*/\n{\n    TkColor *tkColPtr;\n\n    if (objPtr->typePtr != &tkColorObjType) {\n\tInitColorObj(objPtr);\n    }\n    tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;\n\n    /*\n     * If the object currently points to a TkColor, see if it's the one we\n     * want. If so, increment its reference count and return.\n     */\n\n    if (tkColPtr != NULL) {\n\tif (tkColPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a TkColor that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\t    FreeColorObj(objPtr);\n\t    tkColPtr = NULL;\n\t} else if ((Tk_Screen(tkwin) == tkColPtr->screen)\n\t\t&& (Tk_Colormap(tkwin) == tkColPtr->colormap)) {\n\t    tkColPtr->resourceRefCount++;\n\t    return (XColor *) tkColPtr;\n\t}\n    }\n\n    /*\n     * The object didn't point to the TkColor that we wanted. Search the list\n     * of TkColors with the same name to see if one of the saved TkColors is\n     * the right one.\n     */\n\n    if (tkColPtr != NULL) {\n\tTkColor *firstColorPtr = (TkColor *)Tcl_GetHashValue(tkColPtr->hashPtr);\n\n\tFreeColorObj(objPtr);\n\tfor (tkColPtr = firstColorPtr; tkColPtr != NULL;\n\t\ttkColPtr = tkColPtr->nextPtr) {\n\t    if ((Tk_Screen(tkwin) == tkColPtr->screen)\n\t\t    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {\n\t\ttkColPtr->resourceRefCount++;\n\t\ttkColPtr->objRefCount++;\n\t\tobjPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;\n\t\treturn (XColor *) tkColPtr;\n\t    }\n\t}\n    }\n\n    /*\n     * Still no luck. Call Tk_GetColor to allocate a new TkColor object.\n     */\n\n    tkColPtr = (TkColor *) Tk_GetColor(interp, tkwin, Tcl_GetString(objPtr));\n    objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;\n    if (tkColPtr != NULL) {\n\t/* The resourceRefCount is incremented by Tk_GetColor. */\n\ttkColPtr->objRefCount++;\n    }\n    return (XColor *) tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetColor --\n *\n *\tGiven a string name for a color, map the name to a corresponding\n *\tXColor structure.\n *\n * Results:\n *\tThe return value is a pointer to an XColor structure that indicates\n *\tthe red, blue, and green intensities for the color given by \"name\",\n *\tand also specifies a pixel value to use to draw in that color. If an\n *\terror occurs, NULL is returned and an error message will be left in\n *\tthe interp's result.\n *\n * Side effects:\n *\tThe color is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeColor so that the database is cleaned up when colors aren't in\n *\tuse anymore.\n *\n *----------------------------------------------------------------------\n */\n\nXColor *\nTk_GetColor(\n    Tcl_Interp *interp,\t\t/* Place to leave error message if color can't\n\t\t\t\t * be found. */\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    const char *name)\t\t/* Name of color to be allocated (in form\n\t\t\t\t * suitable for passing to XParseColor). */\n{\n    Tcl_HashEntry *nameHashPtr;\n    int isNew;\n    TkColor *tkColPtr;\n    TkColor *existingColPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (!dispPtr->colorInit) {\n\tColorInit(dispPtr);\n    }\n\n    /*\n     * First, check to see if there's already a mapping for this color name.\n     */\n\n    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &isNew);\n    if (!isNew) {\n\texistingColPtr = (TkColor *)Tcl_GetHashValue(nameHashPtr);\n\tfor (tkColPtr = existingColPtr; tkColPtr != NULL;\n\t\ttkColPtr = tkColPtr->nextPtr) {\n\t    if ((tkColPtr->screen == Tk_Screen(tkwin))\n\t\t    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {\n\t\ttkColPtr->resourceRefCount++;\n\t\treturn &tkColPtr->color;\n\t    }\n\t}\n    } else {\n\texistingColPtr = NULL;\n    }\n\n    /*\n     * The name isn't currently known. Map from the name to a pixel value.\n     */\n\n    tkColPtr = TkpGetColor(tkwin, name);\n    if (tkColPtr == NULL) {\n\tif (interp != NULL) {\n\t    if (*name == '#') {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"invalid color name \\\"%s\\\"\", name));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"COLOR\", (char *)NULL);\n\t    } else {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"unknown color name \\\"%s\\\"\", name));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"COLOR\", name, (char *)NULL);\n\t    }\n\t}\n\tif (isNew) {\n\t    Tcl_DeleteHashEntry(nameHashPtr);\n\t}\n\treturn NULL;\n    }\n\n    /*\n     * Now create a new TkColor structure and add it to colorNameTable (in\n     * TkDisplay).\n     */\n\n    tkColPtr->magic = COLOR_MAGIC;\n    tkColPtr->gc = NULL;\n    tkColPtr->screen = Tk_Screen(tkwin);\n    tkColPtr->colormap = Tk_Colormap(tkwin);\n    tkColPtr->visual = Tk_Visual(tkwin);\n    tkColPtr->resourceRefCount = 1;\n    tkColPtr->objRefCount = 0;\n    tkColPtr->type = TK_COLOR_BY_NAME;\n    tkColPtr->hashPtr = nameHashPtr;\n    tkColPtr->nextPtr = existingColPtr;\n    Tcl_SetHashValue(nameHashPtr, tkColPtr);\n\n    return &tkColPtr->color;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetColorByValue --\n *\n *\tGiven a desired set of red-green-blue intensities for a color, locate\n *\ta pixel value to use to draw that color in a given window.\n *\n * Results:\n *\tThe return value is a pointer to an XColor structure that indicates\n *\tthe closest red, blue, and green intensities available to those\n *\tspecified in colorPtr, and also specifies a pixel value to use to draw\n *\tin that color.\n *\n * Side effects:\n *\tThe color is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeColor, so that the database is cleaned up when colors aren't in\n *\tuse anymore.\n *\n *----------------------------------------------------------------------\n */\n\nXColor *\nTk_GetColorByValue(\n    Tk_Window tkwin,\t\t/* Window where color will be used. */\n    XColor *colorPtr)\t\t/* Red, green, and blue fields indicate\n\t\t\t\t * desired color. */\n{\n    ValueKey valueKey;\n    Tcl_HashEntry *valueHashPtr;\n    int isNew;\n    TkColor *tkColPtr;\n    Display *display = Tk_Display(tkwin);\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->colorInit) {\n\tColorInit(dispPtr);\n    }\n\n    /*\n     * First, check to see if there's already a mapping for this color name.\n     * Must clear the structure first; it's not tightly packed on 64-bit\n     * systems. [Bug 2911570]\n     */\n\n    memset(&valueKey, 0, sizeof(ValueKey));\n    valueKey.red = colorPtr->red;\n    valueKey.green = colorPtr->green;\n    valueKey.blue = colorPtr->blue;\n    valueKey.colormap = Tk_Colormap(tkwin);\n    valueKey.display = display;\n    valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable,\n\t    (char *) &valueKey, &isNew);\n    if (!isNew) {\n\ttkColPtr = (TkColor *)Tcl_GetHashValue(valueHashPtr);\n\ttkColPtr->resourceRefCount++;\n\treturn &tkColPtr->color;\n    }\n\n    /*\n     * The name isn't currently known. Find a pixel value for this color and\n     * add a new structure to colorValueTable (in TkDisplay).\n     */\n\n    tkColPtr = TkpGetColorByValue(tkwin, colorPtr);\n    tkColPtr->magic = COLOR_MAGIC;\n    tkColPtr->gc = NULL;\n    tkColPtr->screen = Tk_Screen(tkwin);\n    tkColPtr->colormap = valueKey.colormap;\n    tkColPtr->visual = Tk_Visual(tkwin);\n    tkColPtr->resourceRefCount = 1;\n    tkColPtr->objRefCount = 0;\n    tkColPtr->type = TK_COLOR_BY_VALUE;\n    tkColPtr->hashPtr = valueHashPtr;\n    tkColPtr->nextPtr = NULL;\n    Tcl_SetHashValue(valueHashPtr, tkColPtr);\n    return &tkColPtr->color;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfColor --\n *\n *\tGiven a color, return a textual string identifying the color.\n *\n * Results:\n *\tIf colorPtr was created by Tk_GetColor, then the return value is the\n *\t\"string\" that was used to create it. Otherwise the return value is a\n *\tstring that could have been passed to Tk_GetColor to allocate that\n *\tcolor. The storage for the returned string is only guaranteed to\n *\tpersist up until the next call to this function.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfColor(\n    XColor *colorPtr)\t\t/* Color whose name is desired. */\n{\n    TkColor *tkColPtr = (TkColor *) colorPtr;\n\n    if (tkColPtr->magic==COLOR_MAGIC && tkColPtr->type==TK_COLOR_BY_NAME) {\n\treturn tkColPtr->hashPtr->key.string;\n    } else {\n\tThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t\tTcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n\tsnprintf(tsdPtr->rgbString, sizeof(tsdPtr->rgbString), \"#%04x%04x%04x\", colorPtr->red,\n\t\tcolorPtr->green, colorPtr->blue);\n\n\t/*\n\t * If the string has the form #RSRSTUTUVWVW (where equal letters\n\t * denote equal hexdigits) then this is equivalent to #RSTUVW. Then\n\t * output the shorter form.\n\t */\n\n\tif ((tsdPtr->rgbString[1] == tsdPtr->rgbString[3])\n\t\t&& (tsdPtr->rgbString[2] == tsdPtr->rgbString[4])\n\t\t&& (tsdPtr->rgbString[5] == tsdPtr->rgbString[7])\n\t\t&& (tsdPtr->rgbString[6] == tsdPtr->rgbString[8])\n\t\t&& (tsdPtr->rgbString[9] == tsdPtr->rgbString[11])\n\t\t&& (tsdPtr->rgbString[10] == tsdPtr->rgbString[12])) {\n\t    tsdPtr->rgbString[3] = tsdPtr->rgbString[5];\n\t    tsdPtr->rgbString[4] = tsdPtr->rgbString[6];\n\t    tsdPtr->rgbString[5] = tsdPtr->rgbString[9];\n\t    tsdPtr->rgbString[6] = tsdPtr->rgbString[10];\n\t    tsdPtr->rgbString[7] = '\\0';\n\t}\n\treturn tsdPtr->rgbString;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GCForColor --\n *\n *\tGiven a color allocated from this module, this function returns a GC\n *\tthat can be used for simple drawing with that color.\n *\n * Results:\n *\tThe return value is a GC with color set as its foreground color and\n *\tall other fields defaulted. This GC is only valid as long as the color\n *\texists; it is freed automatically when the last reference to the color\n *\tis freed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nGC\nTk_GCForColor(\n    XColor *colorPtr,\t\t/* Color for which a GC is desired. Must have\n\t\t\t\t * been allocated by Tk_GetColor. */\n    Drawable drawable)\t\t/* Drawable in which the color will be used\n\t\t\t\t * (must have same screen and depth as the one\n\t\t\t\t * for which the color was allocated). */\n{\n    TkColor *tkColPtr = (TkColor *) colorPtr;\n    XGCValues gcValues;\n\n    /*\n     * Do a quick sanity check to make sure this color was really allocated by\n     * Tk_GetColor.\n     */\n\n    if (tkColPtr->magic != COLOR_MAGIC) {\n\tTcl_Panic(\"Tk_GCForColor called with bogus color\");\n    }\n\n    if (tkColPtr->gc == NULL) {\n\tgcValues.foreground = tkColPtr->color.pixel;\n\ttkColPtr->gc = XCreateGC(DisplayOfScreen(tkColPtr->screen), drawable,\n\t\tGCForeground, &gcValues);\n    }\n    return tkColPtr->gc;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeColor --\n *\n *\tThis function is called to release a color allocated by Tk_GetColor.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with colorPtr is deleted, and the color\n *\tis released to X if there are no remaining uses for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeColor(\n    XColor *colorPtr)\t\t/* Color to be released. Must have been\n\t\t\t\t * allocated by Tk_GetColor or\n\t\t\t\t * Tk_GetColorByValue. */\n{\n    TkColor *tkColPtr = (TkColor *) colorPtr;\n    Screen *screen = tkColPtr->screen;\n    TkColor *prevPtr;\n\n    /*\n     * Do a quick sanity check to make sure this color was really allocated by\n     * Tk_GetColor.\n     */\n\n    if (tkColPtr->magic != COLOR_MAGIC) {\n\tTcl_Panic(\"Tk_FreeColor called with bogus color\");\n    }\n\n    if (tkColPtr->resourceRefCount-- > 1) {\n\treturn;\n    }\n\n    /*\n     * This color is no longer being actively used, so free the color\n     * resources associated with it and remove it from the hash table. No\n     * longer any objects referencing it.\n     */\n\n    if (tkColPtr->gc != NULL) {\n\tXFreeGC(DisplayOfScreen(screen), tkColPtr->gc);\n\ttkColPtr->gc = NULL;\n    }\n    TkpFreeColor(tkColPtr);\n\n    prevPtr = (TkColor *)Tcl_GetHashValue(tkColPtr->hashPtr);\n    if (prevPtr == tkColPtr) {\n\tif (tkColPtr->nextPtr == NULL) {\n\t    Tcl_DeleteHashEntry(tkColPtr->hashPtr);\n\t} else {\n\t    Tcl_SetHashValue(tkColPtr->hashPtr, tkColPtr->nextPtr);\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != tkColPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t}\n\tprevPtr->nextPtr = tkColPtr->nextPtr;\n    }\n\n    /*\n     * Free the TkColor structure if there are no objects referencing it.\n     * However, if there are objects referencing it then keep the structure\n     * around; it will get freed when the last reference is cleared\n     */\n\n    if (tkColPtr->objRefCount == 0) {\n\tTcl_Free(tkColPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeColorFromObj --\n *\n *\tThis function is called to release a color allocated by\n *\tTk_AllocColorFromObj. It does not throw away the Tcl_Obj *; it only\n *\tgets rid of the hash table entry for this color and clears the cached\n *\tvalue that is normally stored in the object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with the color represented by objPtr is\n *\tdecremented, and the color is released to X if there are no remaining\n *\tuses for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeColorFromObj(\n    Tk_Window tkwin,\t\t/* The window this color lives in. Needed for\n\t\t\t\t * the screen and colormap values. */\n    Tcl_Obj *objPtr)\t\t/* The Tcl_Obj * to be freed. */\n{\n    Tk_FreeColor(Tk_GetColorFromObj(tkwin, objPtr));\n    FreeColorObj(objPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeColorObjProc, FreeColorObj --\n *\n *\tThis proc is called to release an object reference to a color. Called\n *\twhen the object's internal rep is released or when the cached tkColPtr\n *\tneeds to be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object reference count is decremented. When both it and the hash\n *\tref count go to zero, the color's resources are released.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeColorObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    FreeColorObj(objPtr);\n    objPtr->typePtr = NULL;\n}\n\nstatic void\nFreeColorObj(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    TkColor *tkColPtr = (TkColor *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    if (tkColPtr != NULL) {\n\tif ((tkColPtr->objRefCount-- <= 1)\n\t\t&& (tkColPtr->resourceRefCount == 0)) {\n\t    Tcl_Free(tkColPtr);\n\t}\n\tobjPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupColorObjProc --\n *\n *\tWhen a cached color object is duplicated, this is called to update the\n *\tinternal reps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe color's objRefCount is incremented and the internal rep of the\n *\tcopy is set to point to it.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupColorObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    TkColor *tkColPtr = (TkColor *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;\n\n    if (tkColPtr != NULL) {\n\ttkColPtr->objRefCount++;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetColorFromObj --\n *\n *\tReturns the color referred to by a Tcl object. The color must already\n *\thave been allocated via a call to Tk_AllocColorFromObj or Tk_GetColor.\n *\n * Results:\n *\tReturns the XColor * that matches the tkwin and the string rep of\n *\tobjPtr.\n *\n * Side effects:\n *\tIf the object is not already a color, the conversion will free any old\n *\tinternal representation.\n *\n *----------------------------------------------------------------------\n */\n\nXColor *\nTk_GetColorFromObj(\n    Tk_Window tkwin,\t\t/* The window in which the color will be\n\t\t\t\t * used. */\n    Tcl_Obj *objPtr)\t\t/* String value contains the name of the\n\t\t\t\t * desired color. */\n{\n    TkColor *tkColPtr;\n    Tcl_HashEntry *hashPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objPtr->typePtr != &tkColorObjType) {\n\tInitColorObj(objPtr);\n    }\n\n    /*\n     * First check to see if the internal representation of the object is\n     * defined and is a color that is valid for the current screen and color\n     * map. If it is, we are done.\n     */\n\n    tkColPtr = (TkColor *)objPtr->internalRep.twoPtrValue.ptr1;\n    if ((tkColPtr != NULL)\n\t    && (tkColPtr->resourceRefCount > 0)\n\t    && (Tk_Screen(tkwin) == tkColPtr->screen)\n\t    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {\n\t/*\n\t * The object already points to the right TkColor structure. Just\n\t * return it.\n\t */\n\n\treturn (XColor *) tkColPtr;\n    }\n\n    /*\n     * If we reach this point, it means that the TkColor structure that we\n     * have cached in the internal representation is not valid for the current\n     * screen and colormap. But there is a list of other TkColor structures\n     * attached to the TkDisplay. Walk this list looking for the right TkColor\n     * structure.\n     */\n\n    hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable,\n\t    Tcl_GetString(objPtr));\n    if (hashPtr == NULL) {\n\tgoto error;\n    }\n    for (tkColPtr = (TkColor *)Tcl_GetHashValue(hashPtr);\n\t    (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {\n\tif ((Tk_Screen(tkwin) == tkColPtr->screen)\n\t\t&& (Tk_Colormap(tkwin) == tkColPtr->colormap)) {\n\t    FreeColorObj(objPtr);\n\t    objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;\n\t    tkColPtr->objRefCount++;\n\t    return (XColor *) tkColPtr;\n\t}\n    }\n\n  error:\n    Tcl_Panic(\"Tk_GetColorFromObj called with non-existent color!\");\n    /*\n     * The following code isn't reached; it's just there to please compilers.\n     */\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitColorObj --\n *\n *\tBookeeping function to change an objPtr to a color type.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe old internal rep of the object is freed. The object's type is set\n *\tto color with a NULL TkColor pointer (the pointer will be set later by\n *\teither Tk_AllocColorFromObj or Tk_GetColorFromObj).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitColorObj(\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->typePtr = &tkColorObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ColorInit --\n *\n *\tInitialize the structure used for color management.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRead the code.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nColorInit(\n    TkDisplay *dispPtr)\n{\n    if (!dispPtr->colorInit) {\n\tdispPtr->colorInit = 1;\n\tTcl_InitHashTable(&dispPtr->colorNameTable, TCL_STRING_KEYS);\n\tTcl_InitHashTable(&dispPtr->colorValueTable,\n\t\tsizeof(ValueKey)/sizeof(int));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugColor --\n *\n *\tThis function returns debugging information about a color.\n *\n * Results:\n *\tThe return value is a list with one sublist for each TkColor\n *\tcorresponding to \"name\". Each sublist has two elements that contain\n *\tthe resourceRefCount and objRefCount fields from the TkColor\n *\tstructure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugColor(\n    Tk_Window tkwin,\t\t/* The window in which the color will be used\n\t\t\t\t * (not currently used). */\n    const char *name)\t\t/* Name of the desired color. */\n{\n    Tcl_HashEntry *hashPtr;\n    Tcl_Obj *resultPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    resultPtr = Tcl_NewObj();\n    hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, name);\n    if (hashPtr != NULL) {\n\tTkColor *tkColPtr = (TkColor *)Tcl_GetHashValue(hashPtr);\n\n\tif (tkColPtr == NULL) {\n\t    Tcl_Panic(\"TkDebugColor found empty hash table entry\");\n\t}\n\tfor ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {\n\t    Tcl_Obj *objPtr = Tcl_NewObj();\n\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj((Tcl_WideInt)tkColPtr->resourceRefCount));\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj((Tcl_WideInt)tkColPtr->objRefCount));\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);\n\t}\n    }\n    return resultPtr;\n}\n\n#ifndef _WIN32\n\n/* This function is not necessary for Win32,\n * since XParseColor already does the right thing */\n\n#undef XParseColor\n\nconst char *const tkWebColors[20] = {\n    /* 'a' */ \"qua\\0#0000ffffffff\",\n    /* 'b' */ NULL,\n    /* 'c' */ \"rimson\\0#dcdc14143c3c\",\n    /* 'd' */ NULL,\n    /* 'e' */ NULL,\n    /* 'f' */ \"uchsia\\0#ffff0000ffff\",\n    /* 'g' */ \"reen\\0#000080800000\",\n    /* 'h' */ NULL,\n    /* 'i' */ \"ndigo\\0#4b4b00008282\",\n    /* 'j' */ NULL,\n    /* 'k' */ NULL,\n    /* 'l' */ \"ime\\0#0000ffff0000\",\n    /* 'm' */ \"aroon\\0#808000000000\",\n    /* 'n' */ NULL,\n    /* 'o' */ \"live\\0#808080800000\",\n    /* 'p' */ \"urple\\0#808000008080\",\n    /* 'q' */ NULL,\n    /* 'r' */ NULL,\n    /* 's' */ \"ilver\\0#c0c0c0c0c0c0\",\n    /* 't' */ \"eal\\0#000080808080\"\n};\n\nStatus\nTkParseColor(\n    Display *display,\t\t/* The display */\n    Colormap map,\t\t\t/* Color map */\n    const char *name,     /* String to be parsed */\n    XColor *color)\n{\n    char buf[14];\n    if (*name == '#') {\n\tbuf[0] = '#'; buf[13] = '\\0';\n\tif (!*(++name) || !*(++name) || !*(++name)) {\n\t    /* Not at least 3 hex digits, so invalid */\n\treturn 0;\n\t} else if (!*(++name)) {\n\t    /* Exactly 3 hex digits */\n\t    buf[9] = buf[10] = buf[11] = buf[12] = *(--name);\n\t    buf[5] = buf[6] = buf[7] = buf[8] = *(--name);\n\t    buf[1] = buf[2] = buf[3] = buf[4] = *(--name);\n\t    name = buf;\n\t} else if (!*(++name)\t|| !*(++name)) {\n\t    /* Not at least 6 hex digits, so invalid */\n\t    return 0;\n\t} else if (!*(++name)) {\n\t    /* Exactly 6 hex digits */\n\t    buf[10] = buf[12] = *(--name);\n\t    buf[9] = buf[11] = *(--name);\n\t    buf[6] = buf[8] = *(--name);\n\t    buf[5] = buf[7] = *(--name);\n\t    buf[2] = buf[4] = *(--name);\n\t    buf[1] = buf[3] = *(--name);\n\t    name = buf;\n\t} else if (!*(++name) || !*(++name)) {\n\t    /* Not at least 9 hex digits, so invalid */\n\t    return 0;\n\t} else if (!*(++name)) {\n\t    /* Exactly 9 hex digits */\n\t    buf[11] = *(--name);\n\t    buf[10] = *(--name);\n\t    buf[9] = buf[12] = *(--name);\n\t    buf[7] = *(--name);\n\t    buf[6] = *(--name);\n\t    buf[5] = buf[8] = *(--name);\n\t    buf[3] = *(--name);\n\t    buf[2] = *(--name);\n\t    buf[1] = buf[4] = *(--name);\n\t    name = buf;\n\t} else if (!*(++name) || !*(++name) || *(++name)) {\n\t    /* Not exactly 12 hex digits, so invalid */\n\t    return 0;\n\t} else {\n\t    name -= 13;\n\t}\n\tgoto done;\n    } else if (((*name - 'A') & 0xdf) < sizeof(tkWebColors)/sizeof(tkWebColors[0])) {\n\tif (!((name[0] - 'G') & 0xdf) && !((name[1] - 'R') & 0xdf)\n\t\t&& !((name[2] - 'A') & 0xdb) && !((name[3] - 'Y') & 0xdf)\n\t\t&& !name[4]) {\n\t    name = \"#808080808080\";\n\t    goto done;\n\t} else {\n\t    const char *p = tkWebColors[((*name - 'A') & 0x1f)];\n\t    if (p) {\n\t\tconst char *q = name;\n\t\twhile (!((*p - *(++q)) & 0xdf)) {\n\t\t    if (!*p++) {\n\t\t\tname = p;\n\t\t\tgoto done;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n    if (strlen(name) > 99) {\n\treturn 0;\n    }\ndone:\n    return XParseColor(display, map, name, color);\n}\n#endif /* _WIN32 */\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkColor.h",
    "content": "/*\n * tkColor.h --\n *\n *\tDeclarations of data types and functions used by the Tk color module.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKCOLOR\n#define _TKCOLOR\n\n#include \"tkInt.h\"\n\n/*\n * One of the following data structures is used to keep track of each color\n * that is being used by the application; typically there is a colormap entry\n * allocated for each of these colors.\n */\n\n#define TK_COLOR_BY_NAME\t1\n#define TK_COLOR_BY_VALUE\t2\n\n#define COLOR_MAGIC ((unsigned int) 0x46140277)\n\ntypedef struct TkColor {\n    XColor color;\t\t/* Information about this color. */\n    unsigned int magic;\t\t/* Used for quick integrity check on this\n\t\t\t\t * structure. Must always have the value\n\t\t\t\t * COLOR_MAGIC. */\n    GC gc;\t\t\t/* Simple gc with this color as foreground\n\t\t\t\t * color and all other fields defaulted. May\n\t\t\t\t * be NULL. */\n    Screen *screen;\t\t/* Screen where this color is valid. Used to\n\t\t\t\t * delete it, and to find its display. */\n    Colormap colormap;\t\t/* Colormap from which this entry was\n\t\t\t\t * allocated. */\n    Visual *visual;\t\t/* Visual associated with colormap. */\n    Tcl_Size resourceRefCount;\t/* Number of active uses of this color (each\n\t\t\t\t * active use corresponds to a call to\n\t\t\t\t * Tk_AllocColorFromObj or Tk_GetColor). If\n\t\t\t\t * this count is 0, then this TkColor\n\t\t\t\t * structure is no longer valid and it isn't\n\t\t\t\t * present in a hash table: it is being kept\n\t\t\t\t * around only because there are objects\n\t\t\t\t * referring to it. The structure is freed\n\t\t\t\t * when resourceRefCount and objRefCount are\n\t\t\t\t * both 0. */\n    Tcl_Size objRefCount;\t\t/* The number of Tcl objects that reference\n\t\t\t\t * this structure. */\n    int type;\t\t\t/* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE. */\n    Tcl_HashEntry *hashPtr;\t/* Pointer to hash table entry for this\n\t\t\t\t * structure. (for use in deleting entry). */\n    struct TkColor *nextPtr;\t/* Points to the next TkColor structure with\n\t\t\t\t * the same color name. Colors with the same\n\t\t\t\t * name but different screens or colormaps are\n\t\t\t\t * chained together off a single entry in\n\t\t\t\t * nameTable. For colors in valueTable (those\n\t\t\t\t * allocated by Tk_GetColorByValue) this field\n\t\t\t\t * is always NULL. */\n} TkColor;\n\n/*\n * Common APIs exported from all platform-specific implementations.\n */\n\n#ifndef TkpFreeColor\nMODULE_SCOPE void\tTkpFreeColor(TkColor *tkColPtr);\n#endif\nMODULE_SCOPE TkColor *\tTkpGetColor(Tk_Window tkwin, const char *name);\nMODULE_SCOPE TkColor *\tTkpGetColorByValue(Tk_Window tkwin, XColor *colorPtr);\n\n#endif /* _TKCOLOR */\n"
  },
  {
    "path": "generic/tkConfig.c",
    "content": "/*\n * tkConfig.c --\n *\n *\tThis file contains functions that manage configuration options for\n *\twidgets and other things.\n *\n * Copyright © 1997-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Temporary flag for working on new config package.\n */\n\n#if 0\n\n/*\n * used only for removing the old config code\n */\n\n#define __NO_OLD_CONFIG\n#endif\n\n#include \"tkInt.h\"\n#include \"tkFont.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The following encoding is used in TK_OPTION_VAR:\n *\n * if sizeof(type) == sizeof(int)        =>    TK_OPTION_VAR(type) = 0\n * if sizeof(type) == 1                  =>    TK_OPTION_VAR(type) = 64\n * if sizeof(type) == 2                  =>    TK_OPTION_VAR(type) = 128\n * if sizeof(type) == sizeof(long long)  =>    TK_OPTION_VAR(type) = 192\n */\n#define TYPE_MASK        (((((int)sizeof(int)-1))|3)<<6)\n\n/*\n * The following definition keeps track of all of\n * the option tables that have been created for a thread.\n */\n\ntypedef struct {\n    bool initialized;\t\t/* false means table below needs initializing. */\n    Tcl_HashTable hashTable;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n\n/*\n * The following two structures are used along with Tk_OptionSpec structures\n * to manage configuration options. Tk_OptionSpec is static templates that are\n * compiled into the code of a widget or other object manager. However, to\n * look up options efficiently we need to supplement the static information\n * with additional dynamic information, and this dynamic information may be\n * different for each application. Thus we create structures of the following\n * two types to hold all of the dynamic information; this is done by\n * Tk_CreateOptionTable.\n *\n * One of the following structures corresponds to each Tk_OptionSpec. These\n * structures exist as arrays inside TkOptionTable structures.\n */\n\ntypedef struct TkOption {\n    const Tk_OptionSpec *specPtr;\n\t\t\t\t/* The original spec from the template passed\n\t\t\t\t * to Tk_CreateOptionTable.*/\n    Tk_Uid dbNameUID;\t\t/* The Uid form of the option database\n\t\t\t\t * name. */\n    Tk_Uid dbClassUID;\t\t/* The Uid form of the option database class\n\t\t\t\t * name. */\n    Tcl_Obj *defaultPtr;\t/* Default value for this option. */\n    union {\n\tTcl_Obj *monoColorPtr;\t/* For color and border options, this is an\n\t\t\t\t * alternate default value to use on\n\t\t\t\t * monochrome displays. */\n\tstruct TkOption *synonymPtr;\n\t\t\t\t/* For synonym options, this points to the\n\t\t\t\t * original entry. */\n\tconst struct Tk_ObjCustomOption *custom;\n\t\t\t\t/* For TK_OPTION_CUSTOM. */\n    } extra;\n    int flags;\t\t\t/* Miscellaneous flag values; see below for\n\t\t\t\t * definitions. */\n} Option;\n\n/*\n * Flag bits defined for Option structures:\n *\n * OPTION_NEEDS_FREEING -\t1 means that FreeResources must be invoked to\n *\t\t\t\tfree resources associated with the option when\n *\t\t\t\tit is no longer needed.\n */\n\n#define OPTION_NEEDS_FREEING\t\t1\n\n/*\n * One of the following exists for each Tk_OptionSpec array that has been\n * passed to Tk_CreateOptionTable.\n */\n\ntypedef struct OptionTable {\n    size_t refCount;\t\t/* Counts the number of uses of this table\n\t\t\t\t * (the number of times Tk_CreateOptionTable\n\t\t\t\t * has returned it). This can be greater than\n\t\t\t\t * 1 if it is shared along several option\n\t\t\t\t * table chains, or if the same table is used\n\t\t\t\t * for multiple purposes. */\n    Tcl_HashEntry *hashEntryPtr;/* Hash table entry that refers to this table;\n\t\t\t\t * used to delete the entry. */\n    struct OptionTable *nextPtr;/* If templatePtr was part of a chain of\n\t\t\t\t * templates, this points to the table\n\t\t\t\t * corresponding to the next template in the\n\t\t\t\t * chain. */\n    size_t numOptions;\t\t/* The number of items in the options array\n\t\t\t\t * below. */\n    Option options[1];\t\t/* Information about the individual options in\n\t\t\t\t * the table. This must be the last field in\n\t\t\t\t * the structure: the actual size of the array\n\t\t\t\t * will be numOptions, not 1. */\n} OptionTable;\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tDoObjConfig(Tcl_Interp *interp, void *recordPtr,\n\t\t\t    Option *optionPtr, Tcl_Obj *valuePtr,\n\t\t\t    Tk_Window tkwin, Tk_SavedOption *savePtr);\nstatic void\t\tFreeResources(Option *optionPtr, Tcl_Obj *objPtr,\n\t\t\t    void *internalPtr, Tk_Window tkwin);\nstatic Tcl_Obj *\tGetConfigList(void *recordPtr,\n\t\t\t    Option *optionPtr, Tk_Window tkwin);\nstatic Tcl_Obj *\tGetObjectForOption(void *recordPtr,\n\t\t\t    Option *optionPtr, Tk_Window tkwin);\nstatic Option *\t\tGetOption(const char *name, OptionTable *tablePtr);\nstatic Option *\t\tGetOptionFromObj(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *objPtr, OptionTable *tablePtr);\nstatic void\t\tFreeOptionInternalRep(Tcl_Obj *objPtr);\nstatic void\t\tDupOptionInternalRep(Tcl_Obj *, Tcl_Obj *);\n\n/*\n * The structure below defines an object type that is used to cache the result\n * of looking up an option name. If an object has this type, then its\n * internalPtr1 field points to the OptionTable in which it was looked up, and\n * the internalPtr2 field points to the entry that matched.\n */\n\nstatic const Tcl_ObjType optionObjType = {\n    \"option\",\t\t\t/* name */\n    FreeOptionInternalRep,\t/* freeIntRepProc */\n    DupOptionInternalRep,\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateOptionTable --\n *\n *\tGiven a template for configuration options, this function creates a\n *\ttable that may be used to look up options efficiently.\n *\n * Results:\n *\tReturns a token to a structure that can be passed to functions such as\n *\tTk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions.\n *\n * Side effects:\n *\tStorage is allocated.\n *\n *--------------------------------------------------------------\n */\n\nTk_OptionTable\nTk_CreateOptionTable(\n    Tcl_Interp *interp,\t\t/* Interpreter associated with the application\n\t\t\t\t * in which this table will be used. */\n    const Tk_OptionSpec *templatePtr)\n\t\t\t\t/* Static information about the configuration\n\t\t\t\t * options. */\n{\n    Tcl_HashEntry *hashEntryPtr;\n    int newEntry;\n    OptionTable *tablePtr;\n    const Tk_OptionSpec *specPtr, *specPtr2;\n    Option *optionPtr;\n    size_t numOptions, i;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * We use an TSD in the thread to keep a hash table of\n     * all the option tables we've created for this application. This is\n     * used for allowing us to share the tables (e.g. in several chains).\n     * The code below finds the hash table or creates a new one if it\n     * doesn't already exist.\n     */\n\n    if (!tsdPtr->initialized) {\n\tTcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS);\n\ttsdPtr->initialized = true;\n    }\n\n    /*\n     * See if a table has already been created for this template. If so, just\n     * reuse the existing table.\n     */\n\n    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *)templatePtr,\n\t    &newEntry);\n    if (!newEntry) {\n\ttablePtr = (OptionTable *)Tcl_GetHashValue(hashEntryPtr);\n\ttablePtr->refCount++;\n\treturn (Tk_OptionTable)tablePtr;\n    }\n\n    /*\n     * Count the number of options in the template, then create the table\n     * structure.\n     */\n\n    numOptions = 0;\n    for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {\n\tnumOptions++;\n    }\n    tablePtr = (OptionTable *)Tcl_Alloc(sizeof(OptionTable) + (numOptions * sizeof(Option)));\n    tablePtr->refCount = 1;\n    tablePtr->hashEntryPtr = hashEntryPtr;\n    tablePtr->nextPtr = NULL;\n    tablePtr->numOptions = numOptions;\n\n    /*\n     * Initialize all of the Option structures in the table.\n     */\n\n    for (specPtr = templatePtr, optionPtr = tablePtr->options;\n\t    specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {\n\toptionPtr->specPtr = specPtr;\n\toptionPtr->dbNameUID = NULL;\n\toptionPtr->dbClassUID = NULL;\n\toptionPtr->defaultPtr = NULL;\n\toptionPtr->extra.monoColorPtr = NULL;\n\toptionPtr->flags = 0;\n\n\tif (specPtr->type == TK_OPTION_SYNONYM) {\n\t    /*\n\t     * This is a synonym option; find the original option that it refers\n\t     * to and create a pointer from the synonym to the origin.\n\t     */\n\n\t    for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {\n\t\tif (specPtr2->type == TK_OPTION_END) {\n\t\t    Tcl_Panic(\"Tk_CreateOptionTable couldn't find synonym\");\n\t\t}\n\t\tif (strcmp(specPtr2->optionName,\n\t\t\t(char *)specPtr->clientData) == 0) {\n\t\t    optionPtr->extra.synonymPtr = tablePtr->options + i;\n\t\t    break;\n\t\t}\n\t    }\n\t} else {\n\t    if (specPtr->dbName != NULL) {\n\t\toptionPtr->dbNameUID = Tk_GetUid(specPtr->dbName);\n\t    }\n\t    if (specPtr->dbClass != NULL) {\n\t\toptionPtr->dbClassUID = Tk_GetUid(specPtr->dbClass);\n\t    }\n\t    if (specPtr->defValue != NULL) {\n\t\toptionPtr->defaultPtr = Tcl_NewStringObj(specPtr->defValue, TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(optionPtr->defaultPtr);\n\t    }\n\t    if (((specPtr->type == TK_OPTION_COLOR)\n\t\t    || (specPtr->type == TK_OPTION_BORDER))\n\t\t    && (specPtr->clientData != NULL)) {\n\t\toptionPtr->extra.monoColorPtr =\n\t\t\tTcl_NewStringObj((const char *)specPtr->clientData, TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(optionPtr->extra.monoColorPtr);\n\t    }\n\n\t    if (specPtr->type == TK_OPTION_CUSTOM) {\n\t\t/*\n\t\t * Get the custom parsing, etc., functions.\n\t\t */\n\n\t\toptionPtr->extra.custom = (const Tk_ObjCustomOption *)specPtr->clientData;\n\t    }\n\t}\n\tif (((specPtr->type == TK_OPTION_STRING)\n\t\t&& (specPtr->internalOffset != TCL_INDEX_NONE))\n\t\t|| (specPtr->type == TK_OPTION_COLOR)\n\t\t|| (specPtr->type == TK_OPTION_FONT)\n\t\t|| (specPtr->type == TK_OPTION_BITMAP)\n\t\t|| (specPtr->type == TK_OPTION_BORDER)\n\t\t|| (specPtr->type == TK_OPTION_CURSOR)\n\t\t|| (specPtr->type == TK_OPTION_CUSTOM)) {\n\t    optionPtr->flags |= OPTION_NEEDS_FREEING;\n\t}\n    }\n    tablePtr->hashEntryPtr = hashEntryPtr;\n    Tcl_SetHashValue(hashEntryPtr, tablePtr);\n\n    /*\n     * Finally, check to see if this template chains to another template with\n     * additional options. If so, call ourselves recursively to create the\n     * next table(s).\n     */\n\n    if (specPtr->clientData != NULL) {\n\ttablePtr->nextPtr = (OptionTable *)\n\t\tTk_CreateOptionTable(interp, (Tk_OptionSpec *)specPtr->clientData);\n    }\n\n    return (Tk_OptionTable)tablePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteOptionTable --\n *\n *\tCalled to release resources used by an option table when the table is\n *\tno longer needed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe option table and associated resources (such as additional option\n *\ttables chained off it) are destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteOptionTable(\n    Tk_OptionTable optionTable)\t/* The option table to delete. */\n{\n    OptionTable *tablePtr = (OptionTable *)optionTable;\n    Option *optionPtr;\n    size_t count;\n\n    if (tablePtr->refCount-- > 1) {\n\treturn;\n    }\n\n    if (tablePtr->nextPtr != NULL) {\n\tTk_DeleteOptionTable((Tk_OptionTable)tablePtr->nextPtr);\n    }\n\n    for (count = tablePtr->numOptions, optionPtr = tablePtr->options;\n\t    count > 0;  count--, optionPtr++) {\n\tif (optionPtr->defaultPtr != NULL) {\n\t    Tcl_DecrRefCount(optionPtr->defaultPtr);\n\t}\n\tif (((optionPtr->specPtr->type == TK_OPTION_COLOR)\n\t\t|| (optionPtr->specPtr->type == TK_OPTION_BORDER))\n\t\t&& (optionPtr->extra.monoColorPtr != NULL)) {\n\t    Tcl_DecrRefCount(optionPtr->extra.monoColorPtr);\n\t}\n    }\n    Tcl_DeleteHashEntry(tablePtr->hashEntryPtr);\n    Tcl_Free(tablePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_InitOptions --\n *\n *\tThis function is invoked when an object such as a widget is created.\n *\tIt supplies an initial value for each configuration option (the value\n *\tmay come from the option database, a system default, or the default in\n *\tthe option table).\n *\n * Results:\n *\tThe return value is TCL_OK if the function completed successfully, and\n *\tTCL_ERROR if one of the initial values was bogus. If an error occurs\n *\tand interp isn't NULL, then an error message will be left in its\n *\tresult.\n *\n * Side effects:\n *\tFields of recordPtr are filled in with initial values.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_InitOptions(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. NULL means\n\t\t\t\t * don't leave an error message. */\n    void *recordPtr,\t\t/* Pointer to the record to configure. Note:\n\t\t\t\t * the caller should have properly initialized\n\t\t\t\t * the record with NULL pointers for each\n\t\t\t\t * option value. */\n    Tk_OptionTable optionTable,\t/* The token which matches the config specs\n\t\t\t\t * for the widget in question. */\n    Tk_Window tkwin)\t\t/* Certain options types (such as\n\t\t\t\t * TK_OPTION_COLOR) need fields out of the\n\t\t\t\t * window they are used in to be able to\n\t\t\t\t * calculate their values. Not needed unless\n\t\t\t\t * one of these options is in the configSpecs\n\t\t\t\t * record. */\n{\n    OptionTable *tablePtr = (OptionTable *)optionTable;\n    Option *optionPtr;\n    size_t count;\n    Tk_Uid value;\n    Tcl_Obj *valuePtr;\n    enum {\n\tOPTION_DATABASE, SYSTEM_DEFAULT, TABLE_DEFAULT\n    } source;\n\n    /*\n     * If this table chains to other tables, handle their initialization\n     * first. That way, if both tables refer to the same field of the record,\n     * the value in the first table will win.\n     */\n\n    if (tablePtr->nextPtr != NULL) {\n\tif (Tk_InitOptions(interp, recordPtr,\n\t\t(Tk_OptionTable)tablePtr->nextPtr, tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Iterate over all of the options in the table, initializing each in\n     * turn.\n     */\n\n    for (optionPtr = tablePtr->options, count = tablePtr->numOptions;\n\t    count > 0; optionPtr++, count--) {\n\t/*\n\t * If we specify TK_OPTION_DONT_SET_DEFAULT, then the user has\n\t * processed and set a default for this already.\n\t */\n\n\tif ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) ||\n\t\t(optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) {\n\t    continue;\n\t}\n\tsource = TABLE_DEFAULT;\n\n\t/*\n\t * We look in three places for the initial value, using the first\n\t * non-NULL value that we find. First, check the option database.\n\t */\n\n\tvaluePtr = NULL;\n\tif (optionPtr->dbNameUID != NULL) {\n\t    value = Tk_GetOption(tkwin, optionPtr->dbNameUID,\n\t\t    optionPtr->dbClassUID);\n\t    if (value != NULL) {\n\t\tvaluePtr = Tcl_NewStringObj(value, TCL_INDEX_NONE);\n\t\tsource = OPTION_DATABASE;\n\t    }\n\t}\n\n\t/*\n\t * Second, check for a system-specific default value.\n\t */\n\n\tif ((valuePtr == NULL)\n\t\t&& (optionPtr->dbNameUID != NULL)) {\n\t    valuePtr = Tk_GetSystemDefault(tkwin, optionPtr->dbNameUID,\n\t\t    optionPtr->dbClassUID);\n\t    if (valuePtr != NULL) {\n\t\tsource = SYSTEM_DEFAULT;\n\t    }\n\t}\n\n\t/*\n\t * Third and last, use the default value supplied by the option table.\n\t * In the case of color objects, we pick one of two values depending\n\t * on whether the screen is mono or color.\n\t */\n\n\tif (valuePtr == NULL) {\n\t    if ((tkwin != NULL)\n\t\t    && ((optionPtr->specPtr->type == TK_OPTION_COLOR)\n\t\t    || (optionPtr->specPtr->type == TK_OPTION_BORDER))\n\t\t    && (Tk_Depth(tkwin) <= 1)\n\t\t    && (optionPtr->extra.monoColorPtr != NULL)) {\n\t\tvaluePtr = optionPtr->extra.monoColorPtr;\n\t    } else {\n\t\tvaluePtr = optionPtr->defaultPtr;\n\t    }\n\t}\n\n\tif (valuePtr == NULL) {\n\t    continue;\n\t}\n\n\t/*\n\t * Bump the reference count on valuePtr, so that it is strongly\n\t * referenced here, and will be properly free'd when finished,\n\t * regardless of what DoObjConfig does.\n\t */\n\n\tTcl_IncrRefCount(valuePtr);\n\n\tif (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin,\n\t\tNULL) != TCL_OK) {\n\t    if (interp != NULL) {\n\t\tchar msg[200];\n\n\t\tswitch (source) {\n\t\tcase OPTION_DATABASE:\n\t\t    snprintf(msg, 200, \"\\n    (database entry for \\\"%.50s\\\")\",\n\t\t\t    optionPtr->specPtr->optionName);\n\t\t    break;\n\t\tcase SYSTEM_DEFAULT:\n\t\t    snprintf(msg, 200, \"\\n    (system default for \\\"%.50s\\\")\",\n\t\t\t    optionPtr->specPtr->optionName);\n\t\t    break;\n\t\tcase TABLE_DEFAULT:\n\t\t    snprintf(msg, 200, \"\\n    (default value for \\\"%.50s\\\")\",\n\t\t\t    optionPtr->specPtr->optionName);\n\t\t}\n\t\tif (tkwin != NULL) {\n\t\t    snprintf(msg + strlen(msg) - 1, 200 - (strlen(msg) - 1), \" in widget \\\"%.50s\\\")\",\n\t\t\t    Tk_PathName(tkwin));\n\t\t}\n\t\tTcl_AddErrorInfo(interp, msg);\n\t    }\n\t    Tcl_DecrRefCount(valuePtr);\n\t    return TCL_ERROR;\n\t}\n\tTcl_DecrRefCount(valuePtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DoObjConfig --\n *\n *\tThis function applies a new value for a configuration option to the\n *\trecord being configured.\n *\n * Results:\n *\tThe return value is TCL_OK if the function completed successfully. If\n *\tan error occurred then TCL_ERROR is returned and an error message is\n *\tleft in interp's result, if interp isn't NULL. In addition, if\n *\toldValuePtrPtr isn't NULL then it *oldValuePtrPtr is filled in with a\n *\tpointer to the option's old value.\n *\n * Side effects:\n *\tRecordPtr gets modified to hold the new value in the form of a\n *\tTcl_Obj, an internal representation, or both. The old value is freed\n *\tif oldValuePtrPtr is NULL.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nDoObjConfig(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. If NULL,\n\t\t\t\t * then no message is left if an error\n\t\t\t\t * occurs. */\n    void *recordPtr,\t\t/* The record to modify to hold the new option\n\t\t\t\t * value. */\n    Option *optionPtr,\t\t/* Pointer to information about the option. */\n    Tcl_Obj *valuePtr,\t\t/* New value for option. */\n    Tk_Window tkwin,\t\t/* Window in which option will be used (needed\n\t\t\t\t * to allocate resources for some options).\n\t\t\t\t * May be NULL if the option doesn't require\n\t\t\t\t * window-related resources. */\n    Tk_SavedOption *savedOptionPtr)\n\t\t\t\t/* If NULL, the old value for the option will\n\t\t\t\t * be freed. If non-NULL, the old value will\n\t\t\t\t * be stored here, and it becomes the property\n\t\t\t\t * of the caller (the caller must eventually\n\t\t\t\t * free the old value). */\n{\n    Tcl_Obj **slotPtrPtr, *oldPtr;\n    void *internalPtr;\t\t/* Points to location in record where internal\n\t\t\t\t * representation of value should be stored,\n\t\t\t\t * or NULL. */\n    void *oldInternalPtr;\t/* Points to location in which to save old\n\t\t\t\t * internal representation of value. */\n    Tk_SavedOption internal;\t/* Used to save the old internal\n\t\t\t\t * representation of the value if\n\t\t\t\t * savedOptionPtr is NULL. */\n    const Tk_OptionSpec *specPtr;\n\n    /*\n     * Save the old object form for the value, if there is one.\n     */\n\n    specPtr = optionPtr->specPtr;\n    if (specPtr->objOffset != TCL_INDEX_NONE) {\n\tslotPtrPtr = (Tcl_Obj **)((char *)recordPtr + specPtr->objOffset);\n\toldPtr = *slotPtrPtr;\n    } else {\n\tslotPtrPtr = NULL;\n\toldPtr = NULL;\n    }\n\n    /*\n     * Apply the new value in a type-specific way. Also remember the old\n     * object and internal forms, if they exist.\n     */\n\n    if (specPtr->internalOffset != TCL_INDEX_NONE) {\n\tinternalPtr = (char *)recordPtr + specPtr->internalOffset;\n    } else {\n\tinternalPtr = NULL;\n    }\n    if (savedOptionPtr != NULL) {\n\tsavedOptionPtr->optionPtr = optionPtr;\n\tsavedOptionPtr->valuePtr = oldPtr;\n\toldInternalPtr = (char *)&savedOptionPtr->internalForm;\n    } else {\n\toldInternalPtr = (char *)&internal.internalForm;\n    }\n    bool nullOK = (optionPtr->specPtr->flags & TCL_NULL_OK) != 0;\n    switch (optionPtr->specPtr->type) {\n    case TK_OPTION_BOOLEAN: {\n\tint newBool;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newBool = -1;\n\t} else if (Tcl_GetBooleanFromObj(nullOK ? NULL : interp, valuePtr, &newBool) != TCL_OK) {\n\t    if (nullOK && interp) {\n\t\tTcl_AppendResult(interp, \"expected boolean value or \\\"\\\" but got \\\"\",\n\t\t\tTcl_GetString(valuePtr), \"\\\"\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tif (internalPtr != NULL) {\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    *((char *)oldInternalPtr) = *((char *)internalPtr);\n\t\t    *((char *)internalPtr) = (char)newBool;\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    *((short *)oldInternalPtr) = *((short *)internalPtr);\n\t\t    *((short *)internalPtr) = (short)newBool;\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_BOOLEAN\");\n\t\t}\n\t    } else {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newBool;\n\t    }\n\t}\n\tbreak;\n    }\n    case TK_OPTION_INT: {\n\tint newInt;\n\n\tif ((optionPtr->specPtr->flags & TYPE_MASK) == 0) {\n\t    if (nullOK && TkObjIsEmpty(valuePtr)) {\n\t\tvaluePtr = NULL;\n\t\tnewInt = INT_MIN;\n\t    } else if (Tcl_GetIntFromObj(nullOK ? NULL : interp, valuePtr, &newInt) != TCL_OK) {\n\t    invalidIntValue:\n\t\tif (nullOK && interp) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"expected integer or \\\"\\\" but got \\\"%.50s\\\"\", Tcl_GetString(valuePtr)));\n\t\t    Tcl_SetErrorCode(interp, \"TCL\", \"VALUE\", \"NUMBER\", (char *)NULL);\n\t\t}\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (internalPtr != NULL) {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newInt;\n\t    }\n\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TYPE_MASK) {\n\t    Tcl_WideInt newWideInt;\n\t    if (nullOK && TkObjIsEmpty(valuePtr)) {\n\t\tvaluePtr = NULL;\n\t\tnewWideInt = (sizeof(long) > sizeof(int)) ? LONG_MIN : LLONG_MIN;\n\t    } else if (Tcl_GetWideIntFromObj(nullOK ? NULL : interp, valuePtr, &newWideInt) != TCL_OK) {\n\t\tgoto invalidIntValue;\n\t    }\n\t\tif (internalPtr != NULL) {\n\t\t\tif (sizeof(long) > sizeof(int)) {\n\t\t\t    *((long *)oldInternalPtr) = *((long *)internalPtr);\n\t\t\t    *((long *)internalPtr) = (long)newWideInt;\n\t\t\t} else {\n\t\t\t    *((long long *)oldInternalPtr) = *((long long *)internalPtr);\n\t\t\t    *((long long *)internalPtr) = (long long)newWideInt;\n\t\t\t}\n\t\t}\n\t} else {\n\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_INT\");\n\t}\n\tbreak;\n    }\n    case TK_OPTION_INDEX: {\n\tTcl_Size newIndex;\n\n\tif (TkGetIntForIndex(valuePtr, TCL_INDEX_NONE, 0, &newIndex) != TCL_OK) {\n\t    if (interp) {\n\t\tTcl_AppendResult(interp, \"bad index \\\"\", Tcl_GetString(valuePtr),\n\t\t\t\"\\\": must be integer?[+-]integer?, end?[+-]integer?, or \\\"\\\"\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tif (newIndex < INT_MIN) {\n\t    newIndex = INT_MIN;\n\t} else if (newIndex > INT_MAX) {\n\t    newIndex = INT_MAX;\n\t}\n\tif (internalPtr != NULL) {\n\t    *((int *)oldInternalPtr) = *((int *)internalPtr);\n\t    *((int *)internalPtr) = (int)newIndex;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_DOUBLE: {\n\tdouble newDbl;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n#if defined(NAN)\n\t    newDbl = NAN;\n#else\n\t    newDbl = 0.0;\n#endif\n\t} else {\n\t    if (Tcl_GetDoubleFromObj(nullOK ? NULL : interp, valuePtr, &newDbl) != TCL_OK) {\n\t\tif (nullOK && interp) {\n\t\t    Tcl_Obj *msg = Tcl_NewStringObj(\"expected floating-point number or \\\"\\\" but got \\\"\", TCL_INDEX_NONE);\n\n\t\t    Tcl_AppendLimitedToObj(msg, Tcl_GetString(valuePtr), TCL_INDEX_NONE, 50, \"\");\n\t\t    Tcl_AppendToObj(msg, \"\\\"\", TCL_INDEX_NONE);\n\t\t    Tcl_SetObjResult(interp, msg);\n\t\t    Tcl_SetErrorCode(interp, \"TCL\", \"VALUE\", \"NUMBER\", (char *)NULL);\n\t\t}\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\tif (internalPtr != NULL) {\n\t    *((double *)oldInternalPtr) = *((double *)internalPtr);\n\t    *((double *)internalPtr) = newDbl;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_STRING: {\n\tchar *newStr;\n\tconst char *value;\n\tTcl_Size length;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t}\n\tif (internalPtr != NULL) {\n\t    if (valuePtr != NULL) {\n\t\tvalue = Tcl_GetStringFromObj(valuePtr, &length);\n\t\tnewStr = (char *)Tcl_Alloc(length + 1);\n\t\tstrcpy(newStr, value);\n\t    } else {\n\t\tnewStr = NULL;\n\t    }\n\t    *((char **)oldInternalPtr) = *((char **)internalPtr);\n\t    *((char **)internalPtr) = newStr;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_STRING_TABLE: {\n\tint newValue;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newValue = -1;\n\t} else {\n\t    if (Tcl_GetIndexFromObjStruct(interp, valuePtr,\n\t\t    optionPtr->specPtr->clientData, sizeof(char *),\n\t\t    optionPtr->specPtr->optionName+1, (nullOK ? TCL_NULL_OK : 0), &newValue) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (slotPtrPtr != NULL && valuePtr != NULL) {\n\t\tvaluePtr = Tcl_DuplicateObj(valuePtr);\n\t\tTcl_InvalidateStringRep(valuePtr);\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    *((char *)oldInternalPtr) = *((char *)internalPtr);\n\t\t    *((char *)internalPtr) = (char)newValue;\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    *((short *)oldInternalPtr) = *((short *)internalPtr);\n\t\t    *((short *)internalPtr) = (short)newValue;\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_STRING_TABLE\");\n\t\t}\n\t    } else {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newValue;\n\t    }\n\t}\n\tbreak;\n    }\n    case TK_OPTION_COLOR: {\n\tXColor *newPtr;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newPtr = NULL;\n\t} else {\n\t    newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr);\n\t    if (newPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((XColor **)oldInternalPtr) = *((XColor **)internalPtr);\n\t    *((XColor **)internalPtr) = newPtr;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_FONT: {\n\tTk_Font newFont;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newFont = NULL;\n\t} else {\n\t    newFont = Tk_AllocFontFromObj(interp, tkwin, valuePtr);\n\t    if (newFont == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Tk_Font *)oldInternalPtr) = *((Tk_Font *)internalPtr);\n\t    *((Tk_Font *)internalPtr) = newFont;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_STYLE: {\n\tTk_Style newStyle;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newStyle = NULL;\n\t} else {\n\t    newStyle = Tk_AllocStyleFromObj(interp, valuePtr);\n\t    if (newStyle == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Tk_Style *)oldInternalPtr) = *((Tk_Style *)internalPtr);\n\t    *((Tk_Style *)internalPtr) = newStyle;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_BITMAP: {\n\tPixmap newBitmap;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newBitmap = None;\n\t} else {\n\t    newBitmap = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr);\n\t    if (newBitmap == None) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Pixmap *)oldInternalPtr) = *((Pixmap *)internalPtr);\n\t    *((Pixmap *)internalPtr) = newBitmap;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_BORDER: {\n\tTk_3DBorder newBorder;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newBorder = NULL;\n\t} else {\n\t    newBorder = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr);\n\t    if (newBorder == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Tk_3DBorder *)oldInternalPtr) = *((Tk_3DBorder *)internalPtr);\n\t    *((Tk_3DBorder *)internalPtr) = newBorder;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_RELIEF: {\n\tint newRelief;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newRelief = TK_RELIEF_NULL;\n\t} else if (Tcl_GetIndexFromObj(interp, valuePtr, tkReliefStrings,\n\t\t\"relief\", (nullOK ? TCL_NULL_OK : 0), &newRelief) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (internalPtr != NULL) {\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    *((char *)oldInternalPtr) = *((char *)internalPtr);\n\t\t    *((char *)internalPtr) = (char)newRelief;\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    *((short *)oldInternalPtr) = *((short *)internalPtr);\n\t\t    *((short *)internalPtr) = (short)newRelief;\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_RELIEF\");\n\t\t}\n\t    } else {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newRelief;\n\t    }\n\t}\n\tif (slotPtrPtr != NULL && valuePtr != NULL) {\n\t    valuePtr = Tcl_DuplicateObj(valuePtr);\n\t    Tcl_InvalidateStringRep(valuePtr);\n\t}\n\tbreak;\n    }\n    case TK_OPTION_CURSOR: {\n\tTk_Cursor newCursor;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    newCursor = NULL;\n\t    valuePtr = NULL;\n\t} else {\n\t    newCursor = Tk_AllocCursorFromObj(interp, tkwin, valuePtr);\n\t    if (newCursor == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Tk_Cursor *)oldInternalPtr) = *((Tk_Cursor *)internalPtr);\n\t    *((Tk_Cursor *)internalPtr) = newCursor;\n\t}\n\tTk_DefineCursor(tkwin, newCursor);\n\tbreak;\n    }\n    case TK_OPTION_JUSTIFY: {\n\tint newJustify;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newJustify = -1;\n\t} else if (Tcl_GetIndexFromObj(interp, valuePtr, tkJustifyStrings,\n\t\t\"justification\", (nullOK ? TCL_NULL_OK : 0), &newJustify) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (internalPtr != NULL) {\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    *((char *)oldInternalPtr) = *((char *)internalPtr);\n\t\t    *((char *)internalPtr) = (char)newJustify;\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    *((short *)oldInternalPtr) = *((short *)internalPtr);\n\t\t    *((short *)internalPtr) = (short)newJustify;\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_JUSTIFY\");\n\t\t}\n\t    } else {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newJustify;\n\t    }\n\t}\n\tif (slotPtrPtr != NULL && valuePtr != NULL) {\n\t    valuePtr = Tcl_DuplicateObj(valuePtr);\n\t    Tcl_InvalidateStringRep(valuePtr);\n\t}\n\tbreak;\n    }\n    case TK_OPTION_ANCHOR: {\n\tint newAnchor;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newAnchor = -1;\n\t} else if (Tcl_GetIndexFromObj(interp, valuePtr, tkAnchorStrings,\n\t\t\"anchor\", (nullOK ? TCL_NULL_OK : 0), &newAnchor) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (internalPtr != NULL) {\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    *((char *)oldInternalPtr) = *((char *)internalPtr);\n\t\t    *((char *)internalPtr) = (char)newAnchor;\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    *((short *)oldInternalPtr) = *((short *)internalPtr);\n\t\t    *((short *)internalPtr) = (short)newAnchor;\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_JUSTIFY\");\n\t\t}\n\t    } else {\n\t\t*((int *)oldInternalPtr) = *((int *)internalPtr);\n\t\t*((int *)internalPtr) = newAnchor;\n\t    }\n\t}\n\tif (slotPtrPtr != NULL && valuePtr != NULL) {\n\t    valuePtr = Tcl_DuplicateObj(valuePtr);\n\t    Tcl_InvalidateStringRep(valuePtr);\n\t}\n\tbreak;\n    }\n    case TK_OPTION_PIXELS: {\n\tint newPixels;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newPixels = INT_MIN;\n\t} else if (Tk_GetPixelsFromObj(nullOK ? NULL : interp, tkwin, valuePtr,\n\t\t&newPixels) != TCL_OK) {\n\t    if (nullOK) {\n\t    wrongPixel:\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"expected screen distance%s but got \\\"%.50s\\\"\",\n\t\t\t(nullOK ? \" or \\\"\\\"\": \"\"), Tcl_GetString(valuePtr)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t} else if (!(optionPtr->specPtr->flags & TK_OPTION_NEG_OK) && (newPixels < 0)) {\n\t    goto wrongPixel;\n\t}\n\tif (internalPtr != NULL) {\n\t    *((int *)oldInternalPtr) = *((int *)internalPtr);\n\t    *((int *)internalPtr) = newPixels;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_WINDOW: {\n\tTk_Window newWin;\n\n\tif (nullOK && TkObjIsEmpty(valuePtr)) {\n\t    valuePtr = NULL;\n\t    newWin = NULL;\n\t} else if (TkGetWindowFromObj(interp, tkwin, valuePtr,\n\t\t&newWin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (internalPtr != NULL) {\n\t    *((Tk_Window *)oldInternalPtr) = *((Tk_Window *)internalPtr);\n\t    *((Tk_Window *)internalPtr) = newWin;\n\t}\n\tbreak;\n    }\n    case TK_OPTION_CUSTOM: {\n\tconst Tk_ObjCustomOption *custom = optionPtr->extra.custom;\n\n\tif (custom->setProc(custom->clientData, interp, tkwin,\n\t\t&valuePtr, (char *)recordPtr, optionPtr->specPtr->internalOffset,\n\t\t(char *)oldInternalPtr, optionPtr->specPtr->flags) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tbreak;\n    }\n\n    default:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad config table: unknown type %d\",\n\t\toptionPtr->specPtr->type));\n\tTcl_SetErrorCode(interp, \"TK\", \"BAD_CONFIG\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Install the new object value into the record, then release resources\n     * associated with the old value, if we're not returning it to the caller.\n     */\n\n    if (slotPtrPtr != NULL) {\n\t*slotPtrPtr = valuePtr;\n\tif (valuePtr != NULL) {\n\t    Tcl_IncrRefCount(valuePtr);\n\t}\n    }\n    if (savedOptionPtr == NULL) {\n\tif (optionPtr->flags & OPTION_NEEDS_FREEING) {\n\t    FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);\n\t}\n\tif (oldPtr != NULL) {\n\t    Tcl_DecrRefCount(oldPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkObjIsEmpty --\n *\n *\tThis function tests whether the string value of an object is empty.\n *\n * Results:\n *\tThe return value is 1 if the string value of objPtr has length zero,\n *\tand 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n#if defined(USE_TCL_STUBS)\n# undef Tcl_IsEmpty\n# define Tcl_IsEmpty \\\n    ((bool (*)(Tcl_Obj *))(void *)((&(tclStubsPtr->tcl_PkgProvideEx))[690]))\n#endif\n\nbool\nTkObjIsEmpty(\n    Tcl_Obj *objPtr)\t\t/* Object to test. May be NULL. */\n{\n    if (objPtr == NULL) {\n\treturn true;\n    }\n    if (objPtr->bytes == NULL) {\n#if defined(USE_TCL_STUBS)\n\tif (Tcl_IsEmpty) {\n\t    return Tcl_IsEmpty(objPtr);\n\t}\n#endif\n\tTcl_GetString(objPtr);\n    }\n    return (objPtr->length == 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetOption --\n *\n *\tThis function searches through a chained option table to find the\n *\tentry for a particular option name.\n *\n * Results:\n *\tThe return value is a pointer to the matching entry, or NULL if no\n *\tmatching entry could be found. Note: if the matching entry is a\n *\tsynonym then this function returns a pointer to the synonym entry,\n *\t*not* the \"real\" entry that the synonym refers to.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Option *\nGetOption(\n    const char *name,\t\t/* String balue to be looked up in the option\n\t\t\t\t * table. */\n    OptionTable *tablePtr)\t/* Table in which to look up name. */\n{\n    Option *bestPtr, *optionPtr;\n    OptionTable *tablePtr2;\n    const char *p1, *p2;\n    size_t count;\n\n    /*\n     * Search through all of the option tables in the chain to find the best\n     * match. Some tricky aspects:\n     *\n     * 1. We have to accept unique abbreviations.\n     * 2. The same name could appear in different tables in the chain. If this\n     *    happens, we use the entry from the first table. We have to be\n     *    careful to distinguish this case from an ambiguous abbreviation.\n     */\n\n    bestPtr = NULL;\n    for (tablePtr2 = tablePtr; tablePtr2 != NULL;\n\t    tablePtr2 = tablePtr2->nextPtr) {\n\tfor (optionPtr = tablePtr2->options, count = tablePtr2->numOptions;\n\t\tcount > 0; optionPtr++, count--) {\n\t    for (p1 = name, p2 = optionPtr->specPtr->optionName;\n\t\t    *p1 == *p2; p1++, p2++) {\n\t\tif (*p1 == 0) {\n\t\t    /*\n\t\t     * This is an exact match. We're done.\n\t\t     */\n\n\t\t    return optionPtr;\n\t\t}\n\t    }\n\t    if (*p1 == 0) {\n\t\t/*\n\t\t * The name is an abbreviation for this option. Keep to make\n\t\t * sure that the abbreviation only matches one option name.\n\t\t * If we've already found a match in the past, then it is an\n\t\t * error unless the full names for the two options are\n\t\t * identical; in this case, the first option overrides the\n\t\t * second.\n\t\t */\n\n\t\tif (bestPtr == NULL) {\n\t\t    bestPtr = optionPtr;\n\t\t} else if (strcmp(bestPtr->specPtr->optionName,\n\t\t\toptionPtr->specPtr->optionName) != 0) {\n\t\t    return NULL;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Return whatever we have found, which could be NULL if nothing\n     * matched. The multiple-matching case is handled above.\n     */\n\n    return bestPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetOptionFromObj --\n *\n *\tThis function searches through a chained option table to find the\n *\tentry for a particular option name.\n *\n * Results:\n *\tThe return value is a pointer to the matching entry, or NULL if no\n *\tmatching entry could be found. If NULL is returned and interp is not\n *\tNULL than an error message is left in its result. Note: if the\n *\tmatching entry is a synonym then this function returns a pointer to\n *\tthe synonym entry, *not* the \"real\" entry that the synonym refers to.\n *\n * Side effects:\n *\tInformation about the matching entry is cached in the object\n *\tcontaining the name, so that future lookups can proceed more quickly.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Option *\nGetOptionFromObj(\n    Tcl_Interp *interp,\t\t/* Used only for error reporting; if NULL no\n\t\t\t\t * message is left after an error. */\n    Tcl_Obj *objPtr,\t\t/* Object whose string value is to be looked\n\t\t\t\t * up in the option table. */\n    OptionTable *tablePtr)\t/* Table in which to look up objPtr. */\n{\n    Option *bestPtr;\n    const char *name;\n\n    /*\n     * First, check to see if the object already has the answer cached.\n     */\n\n    if (objPtr->typePtr == &optionObjType) {\n\tif (objPtr->internalRep.twoPtrValue.ptr1 == (void *)tablePtr) {\n\t    return (Option *)objPtr->internalRep.twoPtrValue.ptr2;\n\t}\n    }\n\n    /*\n     * The answer isn't cached.\n     */\n\n    name = Tcl_GetString(objPtr);\n    bestPtr = GetOption(name, tablePtr);\n    if (bestPtr == NULL) {\n\tgoto error;\n    }\n\n    if ((objPtr->typePtr != NULL)\n\t    && (objPtr->typePtr->freeIntRepProc != NULL)) {\n\tobjPtr->typePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->internalRep.twoPtrValue.ptr1 = (void *)tablePtr;\n    objPtr->internalRep.twoPtrValue.ptr2 = (void *)bestPtr;\n    objPtr->typePtr = &optionObjType;\n    tablePtr->refCount++;\n    return bestPtr;\n\n  error:\n    if (interp != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown option \\\"%s\\\"\", name));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"OPTION\", name, (char *)NULL);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetOptionSpec --\n *\n *\tThis function searches through a chained option table to find the\n *\toption spec for a particular option name.\n *\n * Results:\n *\tThe return value is a pointer to the option spec of the matching\n *\tentry, or NULL if no matching entry could be found. Note: if the\n *\tmatching entry is a synonym then this function returns a pointer to\n *\tthe option spec of the synonym entry, *not* the \"real\" entry that the\n *\tsynonym refers to. Note: this call is primarily used by the style\n *\tmanagement code (tkStyle.c) to look up an element's option spec into a\n *\twidget's option table.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst Tk_OptionSpec *\nTkGetOptionSpec(\n    const char *name,\t\t/* String value to be looked up. */\n    Tk_OptionTable optionTable)\t/* Table in which to look up name. */\n{\n    Option *optionPtr;\n\n    optionPtr = GetOption(name, (OptionTable *)optionTable);\n    if (optionPtr == NULL) {\n\treturn NULL;\n    }\n    return optionPtr->specPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeOptionInternalRep --\n *\n *\tPart of the option Tcl object type implementation. Frees the storage\n *\tassociated with a option object's internal representation unless it\n *\tis still in use.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe option object's internal rep is marked invalid and its memory\n *\tgets freed unless it is still in use somewhere. In that case the\n *\tcleanup is delayed until the last reference goes away.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeOptionInternalRep(\n    Tcl_Obj *objPtr)\t/* Object whose internal rep to free. */\n{\n    Tk_OptionTable tablePtr = (Tk_OptionTable)objPtr->internalRep.twoPtrValue.ptr1;\n\n    Tk_DeleteOptionTable(tablePtr);\n    objPtr->typePtr = NULL;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    objPtr->internalRep.twoPtrValue.ptr2 = NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupOptionInternalRep --\n *\n *\tWhen a cached option object is duplicated, this is called to update the\n *\tinternal reps.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupOptionInternalRep(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    OptionTable *tablePtr = (OptionTable *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n    tablePtr->refCount++;\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep = srcObjPtr->internalRep;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SetOptions --\n *\n *\tProcess one or more name-value pairs for configuration options and\n *\tfill in fields of a record with new values.\n *\n * Results:\n *\tIf all goes well then TCL_OK is returned and the old values of any\n *\tmodified objects are saved in *savePtr, if it isn't NULL (the caller\n *\tmust eventually call Tk_RestoreSavedOptions or Tk_FreeSavedOptions to\n *\tfree the contents of *savePtr). In addition, if maskPtr isn't NULL\n *\tthen *maskPtr is filled in with the OR of the typeMask bits from all\n *\tmodified options. If an error occurs then TCL_ERROR is returned and a\n *\tmessage is left in interp's result unless interp is NULL; nothing is\n *\tsaved in *savePtr or *maskPtr in this case.\n *\n * Side effects:\n *\tThe fields of recordPtr get filled in with object pointers from\n *\tobjc/objv. Old information in widgRec's fields gets recycled.\n *\tInformation may be left at *savePtr.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SetOptions(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. If NULL,\n\t\t\t\t * then no error message is returned.*/\n    void *recordPtr,\t\t/* The record to configure. */\n    Tk_OptionTable optionTable,\t/* Describes valid options. */\n    Tcl_Size objc,\t\t\t/* The number of elements in objv. */\n    Tcl_Obj *const objv[],\t/* Contains one or more name-value pairs. */\n    Tk_Window tkwin,\t\t/* Window associated with the thing being\n\t\t\t\t * configured; needed for some options (such\n\t\t\t\t * as colors). */\n    Tk_SavedOptions *savePtr,\t/* If non-NULL, the old values of modified\n\t\t\t\t * options are saved here so that they can be\n\t\t\t\t * restored after an error. */\n    int *maskPtr)\t\t/* It non-NULL, this word is modified on a\n\t\t\t\t * successful return to hold the bit-wise OR\n\t\t\t\t * of the typeMask fields of all options that\n\t\t\t\t * were modified by this call. Used by the\n\t\t\t\t * caller to figure out which options actually\n\t\t\t\t * changed. */\n{\n    OptionTable *tablePtr = (OptionTable *)optionTable;\n    Option *optionPtr;\n    Tk_SavedOptions *lastSavePtr, *newSavePtr;\n    int mask;\n\n    if (savePtr != NULL) {\n\tsavePtr->recordPtr = recordPtr;\n\tsavePtr->tkwin = tkwin;\n\tsavePtr->numItems = 0;\n\tsavePtr->nextPtr = NULL;\n    }\n    lastSavePtr = savePtr;\n\n    /*\n     * Scan through all of the arguments, processing those that match entries\n     * in the option table.\n     */\n\n    mask = 0;\n    for ( ; objc > 0; objc -= 2, objv += 2) {\n\toptionPtr = GetOptionFromObj(interp, objv[0], tablePtr);\n\tif (optionPtr == NULL) {\n\t    goto error;\n\t}\n\tif (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {\n\t    optionPtr = optionPtr->extra.synonymPtr;\n\t}\n\n\tif (objc < 2) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\",\n\t\t\tTcl_GetString(*objv)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE_MISSING\", (char *)NULL);\n\t\tgoto error;\n\t    }\n\t}\n\tif ((savePtr != NULL)\n\t\t&& (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {\n\t    /*\n\t     * We've run out of space for saving old option values. Allocate\n\t     * more space.\n\t     */\n\n\t    newSavePtr = (Tk_SavedOptions *)Tcl_Alloc(sizeof(Tk_SavedOptions));\n\t    newSavePtr->recordPtr = recordPtr;\n\t    newSavePtr->tkwin = tkwin;\n\t    newSavePtr->numItems = 0;\n\t    newSavePtr->nextPtr = NULL;\n\t    lastSavePtr->nextPtr = newSavePtr;\n\t    lastSavePtr = newSavePtr;\n\t}\n\tif (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin,\n\t\t(savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems]\n\t\t: NULL) != TCL_OK) {\n\t    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t    \"\\n    (processing \\\"%.40s\\\" option)\",\n\t\t    Tcl_GetString(*objv)));\n\t    goto error;\n\t}\n\tif (savePtr != NULL) {\n\t    lastSavePtr->numItems++;\n\t}\n\tmask |= optionPtr->specPtr->typeMask;\n    }\n    if (maskPtr != NULL) {\n\t*maskPtr = mask;\n    }\n    return TCL_OK;\n\n  error:\n    if (savePtr != NULL) {\n\tTk_RestoreSavedOptions(savePtr);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_RestoreSavedOptions --\n *\n *\tThis function undoes the effect of a previous call to Tk_SetOptions by\n *\trestoring all of the options to their value before the call to\n *\tTk_SetOptions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe configutation record is restored and all the information stored in\n *\tsavePtr is freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_RestoreSavedOptions(\n    Tk_SavedOptions *savePtr)\t/* Holds saved option information; must have\n\t\t\t\t * been passed to Tk_SetOptions. */\n{\n    Tcl_Size i;\n    Option *optionPtr;\n    Tcl_Obj *newPtr;\t\t/* New object value of option, which we\n\t\t\t\t * replace with old value and free. Taken from\n\t\t\t\t * record. */\n    void *internalPtr;\t\t/* Points to internal value of option in\n\t\t\t\t * record. */\n    const Tk_OptionSpec *specPtr;\n\n    /*\n     * Be sure to restore the options in the opposite order they were set.\n     * This is important because it's possible that the same option name was\n     * used twice in a single call to Tk_SetOptions.\n     */\n\n    if (savePtr->nextPtr != NULL) {\n\tTk_RestoreSavedOptions(savePtr->nextPtr);\n\tTcl_Free(savePtr->nextPtr);\n\tsavePtr->nextPtr = NULL;\n    }\n    for (i = savePtr->numItems - 1; i >= 0; i--) {\n\toptionPtr = savePtr->items[i].optionPtr;\n\tspecPtr = optionPtr->specPtr;\n\n\t/*\n\t * First free the new value of the option, which is currently in the\n\t * record.\n\t */\n\n\tif (specPtr->objOffset >= 0) {\n\t    newPtr = *((Tcl_Obj **)((char *)savePtr->recordPtr + specPtr->objOffset));\n\t} else {\n\t    newPtr = NULL;\n\t}\n\tif (specPtr->internalOffset >= 0) {\n\t    internalPtr = (char *)savePtr->recordPtr + specPtr->internalOffset;\n\t} else {\n\t    internalPtr = NULL;\n\t}\n\tif (optionPtr->flags & OPTION_NEEDS_FREEING) {\n\t    FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);\n\t}\n\tif (newPtr != NULL) {\n\t    Tcl_DecrRefCount(newPtr);\n\t}\n\n\t/*\n\t * Now restore the old value of the option.\n\t */\n\n\tif (specPtr->objOffset != TCL_INDEX_NONE) {\n\t    *((Tcl_Obj **)((char *)savePtr->recordPtr + specPtr->objOffset))\n\t\t    = savePtr->items[i].valuePtr;\n\t}\n\tif (specPtr->internalOffset != TCL_INDEX_NONE) {\n\t    char *ptr = (char *)&savePtr->items[i].internalForm;\n\n\t    CLANG_ASSERT(internalPtr);\n\t    switch (specPtr->type) {\n\t    case TK_OPTION_BOOLEAN:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t\t*((char *)internalPtr) = *((char *)ptr);\n\t\t    } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t\t*((short *)internalPtr) = *((short *)ptr);\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_BOOLEAN\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_INT:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TYPE_MASK) {\n\t\t\tif (sizeof(long) > sizeof(int)) {\n\t\t\t    *((long *)internalPtr) = *((long *)ptr);\n\t\t\t} else {\n\t\t\t    *((long long *)internalPtr) = *((long long *)ptr);\n\t\t\t}\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_INT\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_INDEX:\n\t\t*((int *)internalPtr) = *((int *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_DOUBLE:\n\t\t*((double *)internalPtr) = *((double *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_STRING:\n\t\t*((char **)internalPtr) = *((char **)ptr);\n\t\tbreak;\n\t    case TK_OPTION_STRING_TABLE:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t\t*((char *)internalPtr) = *((char *)ptr);\n\t\t    } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t\t*((short *)internalPtr) = *((short *)ptr);\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_STRING_TABLE\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_COLOR:\n\t\t*((XColor **)internalPtr) = *((XColor **)ptr);\n\t\tbreak;\n\t    case TK_OPTION_FONT:\n\t\t*((Tk_Font *)internalPtr) = *((Tk_Font *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_STYLE:\n\t\t*((Tk_Style *)internalPtr) = *((Tk_Style *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_BITMAP:\n\t\t*((Pixmap *)internalPtr) = *((Pixmap *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_BORDER:\n\t\t*((Tk_3DBorder *)internalPtr) = *((Tk_3DBorder *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_RELIEF:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t\t*((char *)internalPtr) = *((char *)ptr);\n\t\t    } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t\t*((short *)internalPtr) = *((short *)ptr);\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_RELIEF\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_CURSOR:\n\t\t*((Tk_Cursor *)internalPtr) = *((Tk_Cursor *)ptr);\n\t\tTk_DefineCursor(savePtr->tkwin, *((Tk_Cursor *)internalPtr));\n\t\tbreak;\n\t    case TK_OPTION_JUSTIFY:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t\t*((char *)internalPtr) = *((char *)ptr);\n\t\t    } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t\t*((short *)internalPtr) = *((short *)ptr);\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_JUSTIFY\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_ANCHOR:\n\t\tif (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\t    if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t\t*((char *)internalPtr) = *((char *)ptr);\n\t\t    } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t\t*((short *)internalPtr) = *((short *)ptr);\n\t\t    } else {\n\t\t\tTcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_ANCHOR\");\n\t\t    }\n\t\t} else {\n\t\t    *((int *)internalPtr) = *((int *)ptr);\n\t\t}\n\t\tbreak;\n\t    case TK_OPTION_PIXELS:\n\t\t*((int *)internalPtr) = *((int *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_WINDOW:\n\t\t*((Tk_Window *)internalPtr) = *((Tk_Window *)ptr);\n\t\tbreak;\n\t    case TK_OPTION_CUSTOM: {\n\t\tconst Tk_ObjCustomOption *custom = optionPtr->extra.custom;\n\n\t\tif (custom->restoreProc != NULL) {\n\t\t    custom->restoreProc(custom->clientData, savePtr->tkwin,\n\t\t\t    (char *)internalPtr, ptr);\n\t\t}\n\t\tbreak;\n\t    }\n\t    default:\n\t\tTcl_Panic(\"bad option type in Tk_RestoreSavedOptions\");\n\t    }\n\t}\n    }\n    savePtr->numItems = 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_FreeSavedOptions --\n *\n *\tFree all of the saved configuration option values from a previous call\n *\tto Tk_SetOptions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStorage and system resources are freed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_FreeSavedOptions(\n    Tk_SavedOptions *savePtr)\t/* Contains options saved in a previous call\n\t\t\t\t * to Tk_SetOptions. */\n{\n    size_t count;\n    Tk_SavedOption *savedOptionPtr;\n\n    if (savePtr->nextPtr != NULL) {\n\tTk_FreeSavedOptions(savePtr->nextPtr);\n\tTcl_Free(savePtr->nextPtr);\n    }\n    for (count = savePtr->numItems; count > 0; count--) {\n\tsavedOptionPtr = &savePtr->items[count-1];\n\tif (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {\n\t    FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,\n\t\t    (char *)&savedOptionPtr->internalForm, savePtr->tkwin);\n\t}\n\tif (savedOptionPtr->valuePtr != NULL) {\n\t    Tcl_DecrRefCount(savedOptionPtr->valuePtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeConfigOptions --\n *\n *\tFree all resources associated with configuration options.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll of the Tcl_Obj's in recordPtr that are controlled by configuration\n *\toptions in optionTable are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeConfigOptions(\n    void *recordPtr,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    Tk_OptionTable optionTable,\t/* Describes legal options. */\n    Tk_Window tkwin)\t\t/* Window associated with recordPtr; needed\n\t\t\t\t * for freeing some options. */\n{\n    OptionTable *tablePtr;\n    Option *optionPtr;\n    size_t count;\n    Tcl_Obj **oldPtrPtr, *oldPtr;\n    void *oldInternalPtr;\n    const Tk_OptionSpec *specPtr;\n\n    for (tablePtr = (OptionTable *)optionTable; tablePtr != NULL;\n\t    tablePtr = tablePtr->nextPtr) {\n\tfor (optionPtr = tablePtr->options, count = tablePtr->numOptions;\n\t\tcount > 0; optionPtr++, count--) {\n\t    specPtr = optionPtr->specPtr;\n\t    if (specPtr->type == TK_OPTION_SYNONYM) {\n\t\tcontinue;\n\t    }\n\t    if (specPtr->objOffset != TCL_INDEX_NONE) {\n\t\toldPtrPtr = (Tcl_Obj **)((char *)recordPtr + specPtr->objOffset);\n\t\toldPtr = *oldPtrPtr;\n\t\t*oldPtrPtr = NULL;\n\t    } else {\n\t\toldPtr = NULL;\n\t    }\n\t    if (specPtr->internalOffset != TCL_INDEX_NONE) {\n\t\toldInternalPtr = (char *)recordPtr + specPtr->internalOffset;\n\t    } else {\n\t\toldInternalPtr = NULL;\n\t    }\n\t    if (optionPtr->flags & OPTION_NEEDS_FREEING) {\n\t\tFreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);\n\t    }\n\t    if (oldPtr != NULL) {\n\t\tTcl_DecrRefCount(oldPtr);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeResources --\n *\n *\tFree system resources associated with a configuration option, such as\n *\tcolors or fonts.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAny system resources associated with objPtr are released. However,\n *\tobjPtr itself is not freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeResources(\n    Option *optionPtr,\t\t/* Description of the configuration option. */\n    Tcl_Obj *objPtr,\t\t/* The current value of the option, specified\n\t\t\t\t * as an object. */\n    void *internalPtr,\t\t/* A pointer to an internal representation for\n\t\t\t\t * the option's value, such as an int or\n\t\t\t\t * (XColor *). Only valid if\n\t\t\t\t * optionPtr->specPtr->internalOffset != -1. */\n    Tk_Window tkwin)\t\t/* The window in which this option is used. */\n{\n    int internalFormExists;\n\n    /*\n     * If there exists an internal form for the value, use it to free\n     * resources (also zero out the internal form). If there is no internal\n     * form, then use the object form.\n     */\n\n    internalFormExists = optionPtr->specPtr->internalOffset != TCL_INDEX_NONE;\n    switch (optionPtr->specPtr->type) {\n    case TK_OPTION_STRING:\n\tif (internalFormExists) {\n\t    if (*((char **)internalPtr) != NULL) {\n\t\tTcl_Free(*((char **)internalPtr));\n\t\t*((char **)internalPtr) = NULL;\n\t    }\n\t}\n\tbreak;\n    case TK_OPTION_COLOR:\n\tif (internalFormExists) {\n\t    if (*((XColor **)internalPtr) != NULL) {\n\t\tTk_FreeColor(*((XColor **)internalPtr));\n\t\t*((XColor **)internalPtr) = NULL;\n\t    }\n\t} else if (objPtr != NULL) {\n\t    Tk_FreeColorFromObj(tkwin, objPtr);\n\t}\n\tbreak;\n    case TK_OPTION_FONT:\n\tif (internalFormExists) {\n\t    Tk_FreeFont(*((Tk_Font *)internalPtr));\n\t    *((Tk_Font *)internalPtr) = NULL;\n\t} else if (objPtr != NULL) {\n\t    Tk_FreeFontFromObj(tkwin, objPtr);\n\t}\n\tbreak;\n    case TK_OPTION_STYLE:\n\tif (internalFormExists) {\n\t    Tk_FreeStyle(*((Tk_Style *)internalPtr));\n\t    *((Tk_Style *)internalPtr) = NULL;\n\t}\n\tbreak;\n    case TK_OPTION_BITMAP:\n\tif (internalFormExists) {\n\t    if (*((Pixmap *)internalPtr) != None) {\n\t\tTk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *)internalPtr));\n\t\t*((Pixmap *)internalPtr) = None;\n\t    }\n\t} else if (objPtr != NULL) {\n\t    Tk_FreeBitmapFromObj(tkwin, objPtr);\n\t}\n\tbreak;\n    case TK_OPTION_BORDER:\n\tif (internalFormExists) {\n\t    if (*((Tk_3DBorder *)internalPtr) != NULL) {\n\t\tTk_Free3DBorder(*((Tk_3DBorder *)internalPtr));\n\t\t*((Tk_3DBorder *)internalPtr) = NULL;\n\t    }\n\t} else if (objPtr != NULL) {\n\t    Tk_Free3DBorderFromObj(tkwin, objPtr);\n\t}\n\tbreak;\n    case TK_OPTION_CURSOR:\n\tif (internalFormExists) {\n\t    if (*((Tk_Cursor *)internalPtr) != NULL) {\n\t\tTk_FreeCursor(Tk_Display(tkwin), *((Tk_Cursor *)internalPtr));\n\t\t*((Tk_Cursor *)internalPtr) = NULL;\n\t    }\n\t} else if (objPtr != NULL) {\n\t    Tk_FreeCursorFromObj(tkwin, objPtr);\n\t}\n\tbreak;\n    case TK_OPTION_CUSTOM: {\n\tconst Tk_ObjCustomOption *custom = optionPtr->extra.custom;\n\tif (internalFormExists && custom->freeProc != NULL) {\n\t    custom->freeProc(custom->clientData, tkwin, (char *)internalPtr);\n\t}\n\tbreak;\n    }\n    default:\n\tbreak;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetOptionInfo --\n *\n *\tReturns a list object containing complete information about either a\n *\tsingle option or all the configuration options in a table.\n *\n * Results:\n *\tThis function normally returns a pointer to an object. If namePtr\n *\tisn't NULL, then the result object is a list with five elements: the\n *\toption's name, its database name, database class, default value, and\n *\tcurrent value. If the option is a synonym then the list will contain\n *\tonly two values: the option name and the name of the option it refers\n *\tto. If namePtr is NULL, then information is returned for every option\n *\tin the option table: the result will have one sub-list (in the form\n *\tdescribed above) for each option in the table. If an error occurs\n *\t(e.g. because namePtr isn't valid) then NULL is returned and an error\n *\tmessage will be left in interp's result unless interp is NULL.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_GetOptionInfo(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. If NULL,\n\t\t\t\t * then no error message is created. */\n    void *recordPtr,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    Tk_OptionTable optionTable,\t/* Describes all the legal options. */\n    Tcl_Obj *namePtr,\t\t/* If non-NULL, the string value selects a\n\t\t\t\t * single option whose info is to be returned.\n\t\t\t\t * Otherwise info is returned for all options\n\t\t\t\t * in optionTable. */\n    Tk_Window tkwin)\t\t/* Window associated with recordPtr; needed to\n\t\t\t\t * compute correct default value for some\n\t\t\t\t * options. */\n{\n    Tcl_Obj *resultPtr;\n    OptionTable *tablePtr = (OptionTable *)optionTable;\n    Option *optionPtr;\n    size_t count;\n\n    /*\n     * If information is only wanted for a single configuration spec, then\n     * handle that one spec specially.\n     */\n\n    if (namePtr != NULL) {\n\toptionPtr = GetOptionFromObj(interp, namePtr, tablePtr);\n\tif (optionPtr == NULL) {\n\t    return NULL;\n\t}\n\tif (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {\n\t    optionPtr = optionPtr->extra.synonymPtr;\n\t}\n\treturn GetConfigList(recordPtr, optionPtr, tkwin);\n    }\n\n    /*\n     * Loop through all the specs, creating a big list with all their\n     * information.\n     */\n\n    resultPtr = Tcl_NewListObj(0, NULL);\n    for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {\n\tfor (optionPtr = tablePtr->options, count = tablePtr->numOptions;\n\t\tcount > 0; optionPtr++, count--) {\n\t    Tcl_ListObjAppendElement(interp, resultPtr,\n\t\t    GetConfigList(recordPtr, optionPtr, tkwin));\n\t}\n    }\n    return resultPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetConfigList --\n *\n *\tCreate a valid Tcl list holding the configuration information for a\n *\tsingle configuration option.\n *\n * Results:\n *\tA Tcl list, dynamically allocated. The caller is expected to arrange\n *\tfor this list to be freed eventually.\n *\n * Side effects:\n *\tMemory is allocated.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetConfigList(\n    void *recordPtr,\t\t/* Pointer to record holding current values of\n\t\t\t\t * configuration options. */\n    Option *optionPtr,\t\t/* Pointer to information describing a\n\t\t\t\t * particular option. */\n    Tk_Window tkwin)\t\t/* Window corresponding to recordPtr. */\n{\n    Tcl_Obj *listPtr, *elementPtr;\n\n    listPtr = Tcl_NewListObj(0, NULL);\n    Tcl_ListObjAppendElement(NULL, listPtr,\n\t    Tcl_NewStringObj(optionPtr->specPtr->optionName, TCL_INDEX_NONE));\n\n    if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {\n\telementPtr = Tcl_NewStringObj(\n\t\toptionPtr->extra.synonymPtr->specPtr->optionName, TCL_INDEX_NONE);\n\tTcl_ListObjAppendElement(NULL, listPtr, elementPtr);\n    } else {\n\tif (optionPtr->dbNameUID == NULL) {\n\t    elementPtr = Tcl_NewObj();\n\t} else {\n\t    elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, TCL_INDEX_NONE);\n\t}\n\tTcl_ListObjAppendElement(NULL, listPtr, elementPtr);\n\n\tif (optionPtr->dbClassUID == NULL) {\n\t    elementPtr = Tcl_NewObj();\n\t} else {\n\t    elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, TCL_INDEX_NONE);\n\t}\n\tTcl_ListObjAppendElement(NULL, listPtr, elementPtr);\n\n\tif ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR)\n\t\t|| (optionPtr->specPtr->type == TK_OPTION_BORDER))\n\t\t&& (Tk_Depth(tkwin) <= 1)\n\t\t&& (optionPtr->extra.monoColorPtr != NULL)) {\n\t    elementPtr = optionPtr->extra.monoColorPtr;\n\t} else if (optionPtr->defaultPtr != NULL) {\n\t    elementPtr = optionPtr->defaultPtr;\n\t} else {\n\t    elementPtr = Tcl_NewObj();\n\t}\n\tTcl_ListObjAppendElement(NULL, listPtr, elementPtr);\n\n\tif (optionPtr->specPtr->objOffset != TCL_INDEX_NONE) {\n\t    elementPtr = *((Tcl_Obj **)((char *)recordPtr\n\t\t    + optionPtr->specPtr->objOffset));\n\t    if (elementPtr == NULL) {\n\t\telementPtr = Tcl_NewObj();\n\t    }\n\t} else {\n\t    elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);\n\t}\n\tTcl_ListObjAppendElement(NULL, listPtr, elementPtr);\n    }\n    return listPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetObjectForOption --\n *\n *\tThis function is called to create an object that contains the value\n *\tfor an option. It is invoked by GetConfigList and Tk_GetOptionValue\n *\twhen only the internal form of an option is stored in the record.\n *\n * Results:\n *\tThe return value is a pointer to a Tcl object. The caller must call\n *\tTcl_IncrRefCount on this object to preserve it.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetObjectForOption(\n    void *recordPtr,\t\t/* Pointer to record holding current values of\n\t\t\t\t * configuration options. */\n    Option *optionPtr,\t\t/* Pointer to information describing an option\n\t\t\t\t * whose internal value is stored in\n\t\t\t\t * *recordPtr. */\n    Tk_Window tkwin)\t\t/* Window corresponding to recordPtr. */\n{\n    Tcl_Obj *objPtr = NULL;\n    void *internalPtr;\t\t/* Points to internal value of option in record. */\n\n    if (optionPtr->specPtr->internalOffset != TCL_INDEX_NONE) {\n\tinternalPtr = (char *)recordPtr + optionPtr->specPtr->internalOffset;\n\tswitch (optionPtr->specPtr->type) {\n\tcase TK_OPTION_BOOLEAN: {\n\t    int value = -1;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    value = *((signed char *)internalPtr);\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    value = *((short *)internalPtr);\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_BOOLEAN\");\n\t\t}\n\t    } else {\n\t\tvalue = *((int *)internalPtr);\n\t    }\n\t    if (value != -1) {\n\t\tobjPtr = Tcl_NewBooleanObj(value);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_INT: {\n\t    Tcl_WideInt value = LLONG_MIN;\n\t    bool nullOK = (optionPtr->specPtr->flags & TCL_NULL_OK) != 0;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TYPE_MASK) {\n\t\t    if (sizeof(long) > sizeof(int)) {\n\t\t\tvalue = *((long *)internalPtr);\n\t\t\tif (nullOK && (value == LONG_MIN)) {break;}\n\t\t    } else {\n\t\t\tvalue = *((long long *)internalPtr);\n\t\t\tif (nullOK && (value == LLONG_MIN)) {break;}\n\t\t    }\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_INT\");\n\t\t}\n\t    } else {\n\t\tvalue = *((int *)internalPtr);\n\t\tif (nullOK && (value == INT_MIN)) {break;}\n\t    }\n\t\tobjPtr = Tcl_NewWideIntObj(value);\n\t    break;\n\t}\n\tcase TK_OPTION_INDEX:\n\t    if (!(optionPtr->specPtr->flags & TCL_NULL_OK) || *((int *)internalPtr) != INT_MIN) {\n\t\tif (*((int *)internalPtr) == INT_MIN) {\n\t\t    objPtr = TkNewIndexObj(TCL_INDEX_NONE);\n\t\t} else if (*((int *)internalPtr) == INT_MAX) {\n\t\t    objPtr = Tcl_NewStringObj(\"end+1\", TCL_INDEX_NONE);\n\t\t} else if (*((int *)internalPtr) == -1) {\n\t\t    objPtr = Tcl_NewStringObj(\"end\", TCL_INDEX_NONE);\n\t\t} else if (*((int *)internalPtr) < 0) {\n\t\t    char buf[32];\n\t\t    snprintf(buf, 32, \"end%d\", 1 + *((int *)internalPtr));\n\t\t    objPtr = Tcl_NewStringObj(buf, TCL_INDEX_NONE);\n\t\t} else {\n\t\t    objPtr = Tcl_NewWideIntObj(*((int *)internalPtr));\n\t\t}\n\t    }\n\t    break;\n\tcase TK_OPTION_DOUBLE:\n\t    if (!(optionPtr->specPtr->flags & TCL_NULL_OK) || !isnan(*((double *)internalPtr))) {\n\t\tobjPtr = Tcl_NewDoubleObj(*((double *)internalPtr));\n\t    }\n\t    break;\n\tcase TK_OPTION_STRING:\n\t    objPtr = Tcl_NewStringObj(*((char **)internalPtr), TCL_INDEX_NONE);\n\t    break;\n\tcase TK_OPTION_STRING_TABLE: {\n\t    int value = 0;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    value = *((signed char *)internalPtr);\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    value = *((short *)internalPtr);\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_STRING_TABLE\");\n\t\t}\n\t    } else {\n\t\tvalue = *((int *)internalPtr);\n\t    }\n\t    if (value >= 0) {\n\t\tobjPtr = Tcl_NewStringObj(((char **)optionPtr->specPtr->clientData)[\n\t\t\tvalue], TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_COLOR: {\n\t    XColor *colorPtr = *((XColor **)internalPtr);\n\n\t    if (colorPtr != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_FONT: {\n\t    Tk_Font tkfont = *((Tk_Font *)internalPtr);\n\n\t    if (tkfont != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_STYLE: {\n\t    Tk_Style style = *((Tk_Style *)internalPtr);\n\n\t    if (style != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_BITMAP: {\n\t    Pixmap pixmap = *((Pixmap *)internalPtr);\n\n\t    if (pixmap != None) {\n\t\tobjPtr = Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(Tk_Display(tkwin), pixmap), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_BORDER: {\n\t    Tk_3DBorder border = *((Tk_3DBorder *)internalPtr);\n\n\t    if (border != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_RELIEF: {\n\t    int value = TK_RELIEF_NULL;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    value = *((signed char *)internalPtr);\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    value = *((short *)internalPtr);\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_RELIEF\");\n\t\t}\n\t    } else {\n\t\tvalue = *((int *)internalPtr);\n\t    }\n\t    if (value != TK_RELIEF_NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfRelief(value), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_CURSOR: {\n\t    Tk_Cursor cursor = *((Tk_Cursor *)internalPtr);\n\n\t    if (cursor != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(\n\t\tTk_NameOfCursor(Tk_Display(tkwin), cursor), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_JUSTIFY: {\n\t    Tk_Justify value = TK_JUSTIFY_NULL;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    value = (Tk_Justify)*((signed char *)internalPtr);\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    value = (Tk_Justify)*((short *)internalPtr);\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_JUSTIFY\");\n\t\t}\n\t    } else {\n\t\tvalue = (Tk_Justify)*((int *)internalPtr);\n\t    }\n\t    if (value != TK_JUSTIFY_NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfJustify(value), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_ANCHOR: {\n\t    Tk_Anchor value = TK_ANCHOR_NULL;\n\t    if (optionPtr->specPtr->flags & TYPE_MASK) {\n\t\tif ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(char)) {\n\t\t    value = (Tk_Anchor)*((signed char *)internalPtr);\n\t\t} else if ((optionPtr->specPtr->flags & TYPE_MASK) == TK_OPTION_VAR(short)) {\n\t\t    value = (Tk_Anchor)*((short *)internalPtr);\n\t\t} else {\n\t\t    Tcl_Panic(\"Invalid flags for %s\", \"TK_OPTION_ANCHOR\");\n\t\t}\n\t    } else {\n\t\tvalue = (Tk_Anchor)*((int *)internalPtr);\n\t    }\n\t    if (value != TK_ANCHOR_NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_NameOfAnchor(value), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_PIXELS:\n\t    if (!(optionPtr->specPtr->flags & TCL_NULL_OK) || *((int *)internalPtr) != INT_MIN) {\n\t\tobjPtr = Tcl_NewWideIntObj(*((int *)internalPtr));\n\t    }\n\t    break;\n\tcase TK_OPTION_WINDOW: {\n\t    tkwin = *((Tk_Window *)internalPtr);\n\n\t    if (tkwin != NULL) {\n\t\tobjPtr = Tcl_NewStringObj(Tk_PathName(tkwin), TCL_INDEX_NONE);\n\t    }\n\t    break;\n\t}\n\tcase TK_OPTION_CUSTOM: {\n\t    const Tk_ObjCustomOption *custom = optionPtr->extra.custom;\n\n\t    objPtr = custom->getProc(custom->clientData, tkwin, (char *)recordPtr,\n\t\t    optionPtr->specPtr->internalOffset);\n\t    break;\n\t}\n\tdefault:\n\t    Tcl_Panic(\"bad option type in GetObjectForOption\");\n\t}\n    }\n    if (objPtr == NULL) {\n\tobjPtr = Tcl_NewObj();\n    }\n    return objPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOptionValue --\n *\n *\tThis function returns the current value of a configuration option.\n *\n * Results:\n *\tThe return value is the object holding the current value of the option\n *\tgiven by namePtr. If no such option exists, then the return value is\n *\tNULL and an error message is left in interp's result (if interp isn't\n *\tNULL).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_GetOptionValue(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. If NULL\n\t\t\t\t * then no messages are provided for\n\t\t\t\t * errors. */\n    void *recordPtr,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    Tk_OptionTable optionTable,\t/* Describes legal options. */\n    Tcl_Obj *namePtr,\t\t/* Gives the command-line name for the option\n\t\t\t\t * whose value is to be returned. */\n    Tk_Window tkwin)\t\t/* Window corresponding to recordPtr. */\n{\n    OptionTable *tablePtr = (OptionTable *)optionTable;\n    Option *optionPtr;\n    Tcl_Obj *resultPtr;\n\n    optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);\n    if (optionPtr == NULL) {\n\treturn NULL;\n    }\n    if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {\n\toptionPtr = optionPtr->extra.synonymPtr;\n    }\n    if (optionPtr->specPtr->objOffset != TCL_INDEX_NONE) {\n\tresultPtr = *((Tcl_Obj **)((char *)recordPtr+optionPtr->specPtr->objOffset));\n\tif (resultPtr == NULL) {\n\t    /*\n\t     * This option has a null value and is represented by a null\n\t     * object pointer. We can't return the null pointer, since that\n\t     * would indicate an error. Instead, return a new empty object.\n\t     */\n\n\t    resultPtr = Tcl_NewObj();\n\t}\n    } else {\n\tresultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);\n    }\n    return resultPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugConfig --\n *\n *\tThis is a debugging function that returns information about one of the\n *\tconfiguration tables that currently exists for an interpreter.\n *\n * Results:\n *\tIf the specified table exists in the given interpreter, then a list is\n *\treturned describing the table and any other tables that it chains to:\n *\tfor each table there will be three list elements giving the reference\n *\tcount for the table, the number of elements in the table, and the\n *\tcommand-line name for the first option in the table. If the table\n *\tdoesn't exist in the interpreter then an empty object is returned.\n *\tThe reference count for the returned object is 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugConfig(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Interpreter in which the table is\n\t\t\t\t * defined. */\n    Tk_OptionTable table)\t/* Table about which information is to be\n\t\t\t\t * returned. May not necessarily exist in the\n\t\t\t\t * interpreter anymore. */\n{\n    OptionTable *tablePtr = (OptionTable *)table;\n    Tcl_HashEntry *hashEntryPtr;\n    Tcl_HashSearch search;\n    Tcl_Obj *objPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    objPtr = Tcl_NewObj();\n    if (!tablePtr || !tsdPtr->initialized) {\n\treturn objPtr;\n    }\n\n    /*\n     * Scan all the tables for this interpreter to make sure that the one we\n     * want still is valid.\n     */\n\n    for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search);\n\t    hashEntryPtr != NULL;\n\t    hashEntryPtr = Tcl_NextHashEntry(&search)) {\n\tif (tablePtr == (OptionTable *)Tcl_GetHashValue(hashEntryPtr)) {\n\t    for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {\n\t\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\t\tTcl_NewWideIntObj((Tcl_WideInt)tablePtr->refCount));\n\t\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\t\tTcl_NewWideIntObj((Tcl_WideInt)tablePtr->numOptions));\n\t\tTcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(\n\t\t\ttablePtr->options[0].specPtr->optionName, TCL_INDEX_NONE));\n\t    }\n\t    break;\n\t}\n    }\n    return objPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkConsole.c",
    "content": "/*\n * tkConsole.c --\n *\n *\tThis file implements a Tcl console for systems that may not otherwise\n *\thave access to a console. It uses the Text widget and provides special\n *\taccess via a console command.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Each console is associated with an instance of the ConsoleInfo struct.\n * It keeps track of what interp holds the Tk application that displays\n * the console, and what interp is controlled by the interactions in that\n * console.  A refCount permits the struct to be shared as instance data\n * by commands and by channels.\n */\n\ntypedef struct ConsoleInfo {\n    Tcl_Interp *consoleInterp;\t/* Interpreter displaying the console. */\n    Tcl_Interp *interp;\t\t/* Interpreter controlled by console. */\n    size_t refCount;\n} ConsoleInfo;\n\n/*\n * Each console channel holds an instance of the ChannelData struct as\n * its instance data.  It contains ConsoleInfo, so the channel can work\n * with the appropriate console window, and a type value to distinguish\n * the stdout channel from the stderr channel.\n */\n\ntypedef struct ChannelData {\n    ConsoleInfo *info;\n    int type;\t\t\t/* TCL_STDOUT or TCL_STDERR */\n} ChannelData;\n\n/*\n * Prototypes for local procedures defined in this file:\n */\n\nstatic int\tConsoleClose(void *instanceData, Tcl_Interp *interp);\nstatic int\tConsole2Close(void *instanceData, Tcl_Interp *interp, int flags);\nstatic void\tConsoleDeleteProc(void *clientData);\nstatic void\tConsoleEventProc(void *clientData, XEvent *eventPtr);\nstatic int\tConsoleHandle(void *instanceData, int direction,\n\t\t    void **handlePtr);\nstatic int\tConsoleInput(void *instanceData, char *buf, int toRead,\n\t\t    int *errorCode);\nstatic Tcl_ObjCmdProc2 ConsoleObjCmd;\nstatic int\tConsoleOutput(void *instanceData, const char *buf,\n\t\t    int toWrite, int *errorCode);\nstatic void\tConsoleWatch(void *instanceData, int mask);\nstatic void\tDeleteConsoleInterp(void *clientData);\nstatic void\tInterpDeleteProc(void *clientData, Tcl_Interp *interp);\nstatic Tcl_ObjCmdProc2 InterpreterObjCmd;\n\n/*\n * This structure describes the channel type structure for file based IO:\n */\n\nstatic const Tcl_ChannelType consoleChannelType = {\n    \"console\",\t\t\t/* Type name. */\n    TCL_CHANNEL_VERSION_5,\t/* v5 channel */\n    (Tcl_DriverCloseProc *)ConsoleClose,\t\t/* Close proc. */\n    ConsoleInput,\t\t/* Input proc. */\n    ConsoleOutput,\t\t/* Output proc. */\n    NULL,\t\t\t/* Seek proc. */\n    NULL,\t\t\t/* Set option proc. */\n    NULL,\t\t\t/* Get option proc. */\n    ConsoleWatch,\t\t/* Watch for events on console. */\n    ConsoleHandle,\t\t/* Get a handle from the device. */\n    Console2Close,\t\t\t/* close2proc. */\n    NULL,\t\t\t/* Always non-blocking.*/\n    NULL,\t\t\t/* flush proc. */\n    NULL,\t\t\t/* handler proc. */\n    NULL,\t\t\t/* wide seek proc */\n    NULL,\t\t\t/* thread action proc */\n    NULL\n};\n\f\n#ifdef _WIN32\n#include <windows.h>\n\n/*\n *----------------------------------------------------------------------\n *\n * ShouldUseConsoleChannel\n *\n *\tCheck to see if console window should be used for a given standard\n *\tchannel.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCreates the console channel and installs it as the standard channels.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nShouldUseConsoleChannel(\n    int type)\n{\n    DWORD handleId;\t\t/* Standard handle to retrieve. */\n    DCB dcb;\n    DWORD consoleParams;\n    DWORD fileType;\n    HANDLE handle;\n\n    switch (type) {\n    case TCL_STDIN:\n\thandleId = STD_INPUT_HANDLE;\n\tbreak;\n    case TCL_STDOUT:\n\thandleId = STD_OUTPUT_HANDLE;\n\tbreak;\n    case TCL_STDERR:\n\thandleId = STD_ERROR_HANDLE;\n\tbreak;\n    default:\n\treturn 0;\n\tbreak;\n    }\n\n    handle = GetStdHandle(handleId);\n\n    /*\n     * Note that we need to check for 0 because Windows will return 0 if this\n     * is not a console mode application, even though this is not a valid\n     * handle.\n     */\n\n    if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {\n\treturn 1;\n    }\n\n    /*\n     * Win2K BUG: GetStdHandle(STD_OUTPUT_HANDLE) can return what appears to\n     * be a valid handle. See TclpGetDefaultStdChannel() for this change\n     * implemented. We didn't change it here because GetFileType() [below]\n     * will catch this with FILE_TYPE_UNKNOWN and appropriately return a value\n     * of 1, anyways.\n     *\n     *    char dummyBuff[1];\n     *    DWORD dummyWritten;\n     *\n     *    if ((type == TCL_STDOUT)\n     *\t\t&& !WriteFile(handle, dummyBuff, 0, &dummyWritten, NULL)) {\n     *\t     return 1;\n     *    }\n     */\n\n    fileType = GetFileType(handle);\n\n    /*\n     * If the file is a character device, we need to try to figure out whether\n     * it is a serial port, a console, or something else. We test for the\n     * console case first because this is more common.\n     */\n\n    if (fileType == FILE_TYPE_CHAR) {\n\tdcb.DCBlength = sizeof(DCB);\n\tif (!GetConsoleMode(handle, &consoleParams) &&\n\t\t!GetCommState(handle, &dcb)) {\n\t    /*\n\t     * Don't use a CHAR type channel for stdio, otherwise Tk runs into\n\t     * trouble with the MS DevStudio debugger.\n\t     */\n\n\t    return 1;\n\t}\n    } else if (fileType == FILE_TYPE_UNKNOWN) {\n\treturn 1;\n    } else if (Tcl_GetStdChannel(type) == NULL) {\n\treturn 1;\n    }\n\n    return 0;\n}\n#else\n/*\n * Mac should always use a console channel, Unix should if it's trying to\n */\n\n#define ShouldUseConsoleChannel(chan) (1)\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_InitConsoleChannels --\n *\n *\tCreate the console channels and install them as the standard channels.\n *\tAll I/O will be discarded until Tk_CreateConsoleWindow is called to\n *\tattach the console to a text widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCreates the console channel and installs it as the standard channels.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_InitConsoleChannels(\n    Tcl_Interp *interp)\n{\n    static Tcl_ThreadDataKey consoleInitKey;\n    int *consoleInitPtr, doIn, doOut, doErr;\n    ConsoleInfo *info;\n    Tcl_Channel consoleChannel;\n\n    /*\n     * Ensure that we are getting a compatible version of Tcl.\n     */\n\n    if (Tcl_InitStubs(interp, \"9.0\", 0) == NULL) {\n\treturn;\n    }\n\n    consoleInitPtr = (int *)Tcl_GetThreadData(&consoleInitKey, sizeof(int));\n    if (*consoleInitPtr) {\n\t/*\n\t * We've already initialized console channels in this thread.\n\t */\n\n\treturn;\n    }\n    *consoleInitPtr = 1;\n\n    doIn = ShouldUseConsoleChannel(TCL_STDIN);\n    doOut = ShouldUseConsoleChannel(TCL_STDOUT);\n    doErr = ShouldUseConsoleChannel(TCL_STDERR);\n\n    if (!(doIn || doOut || doErr)) {\n\t/*\n\t * No std channels should be tied to the console; thus, no need to\n\t * create the console.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * At least one std channel wants to be tied to the console, so create the\n     * interp for it to live in.\n     */\n\n    info = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));\n    info->consoleInterp = NULL;\n    info->interp = NULL;\n    info->refCount = 0;\n\n    if (doIn) {\n\tChannelData *data = (ChannelData *)Tcl_Alloc(sizeof(ChannelData));\n\n\tdata->info = info;\n\tdata->info->refCount++;\n\tdata->type = TCL_STDIN;\n\tconsoleChannel = Tcl_CreateChannel(&consoleChannelType, \"console0\",\n\t\tdata, TCL_READABLE);\n\tif (consoleChannel != NULL) {\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-translation\", \"lf\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-buffering\", \"none\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-encoding\", \"utf-8\");\n\t}\n\tTcl_SetStdChannel(consoleChannel, TCL_STDIN);\n\tTcl_RegisterChannel(NULL, consoleChannel);\n    }\n\n    if (doOut) {\n\tChannelData *data = (ChannelData *)Tcl_Alloc(sizeof(ChannelData));\n\n\tdata->info = info;\n\tdata->info->refCount++;\n\tdata->type = TCL_STDOUT;\n\tconsoleChannel = Tcl_CreateChannel(&consoleChannelType, \"console1\",\n\t\tdata, TCL_WRITABLE);\n\tif (consoleChannel != NULL) {\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-translation\", \"lf\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-buffering\", \"none\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-encoding\", \"utf-8\");\n\t}\n\tTcl_SetStdChannel(consoleChannel, TCL_STDOUT);\n\tTcl_RegisterChannel(NULL, consoleChannel);\n    }\n\n    if (doErr) {\n\tChannelData *data = (ChannelData *)Tcl_Alloc(sizeof(ChannelData));\n\n\tdata->info = info;\n\tdata->info->refCount++;\n\tdata->type = TCL_STDERR;\n\tconsoleChannel = Tcl_CreateChannel(&consoleChannelType, \"console2\",\n\t\tdata, TCL_WRITABLE);\n\tif (consoleChannel != NULL) {\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-translation\", \"lf\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-buffering\", \"none\");\n\t    Tcl_SetChannelOption(NULL, consoleChannel, \"-encoding\", \"utf-8\");\n\t}\n\tTcl_SetStdChannel(consoleChannel, TCL_STDERR);\n\tTcl_RegisterChannel(NULL, consoleChannel);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreateConsoleWindow --\n *\n *\tInitialize the console. This code actually creates a new application\n *\tand associated interpreter. This effectively hides the implementation\n *\tfrom the main application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new console it created.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_CreateConsoleWindow(\n    Tcl_Interp *interp)\t\t/* Interpreter to use for prompting. */\n{\n    Tcl_Channel chan;\n    ConsoleInfo *info;\n    Tk_Window mainWindow;\n    Tcl_Command token;\n    int result = TCL_OK;\n    int haveConsoleChannel = 1;\n\n    /* Init an interp with Tcl and Tk */\n    Tcl_Interp *consoleInterp = Tcl_CreateInterp();\n    if (Tcl_Init(consoleInterp) != TCL_OK) {\n\tTcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp);\n\tTcl_SetObjResult(interp, result_obj);\n\tgoto error;\n    }\n    if (Tk_Init(consoleInterp) != TCL_OK) {\n\tTcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp);\n\tTcl_SetObjResult(interp, result_obj);\n\tgoto error;\n    }\n\n    /*\n     * Fetch the instance data from whatever std channel is a\n     * console channel.  If none, create fresh instance data.\n     */\n\n    if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN))\n\t    == &consoleChannelType) {\n    } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT))\n\t    == &consoleChannelType) {\n    } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR))\n\t    == &consoleChannelType) {\n    } else {\n\thaveConsoleChannel = 0;\n    }\n\n    if (haveConsoleChannel) {\n\tChannelData *data = (ChannelData *) Tcl_GetChannelInstanceData(chan);\n\tinfo = data->info;\n\tif (info->consoleInterp) {\n\t    /*\n\t     * New ConsoleInfo for a new console window.\n\t     */\n\n\t    info = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));\n\t    info->refCount = 0;\n\n\t    /*\n\t     * Update any console channels to make use of the new console.\n\t     */\n\n\t    if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN))\n\t\t    == &consoleChannelType) {\n\t\tdata = (ChannelData *) Tcl_GetChannelInstanceData(chan);\n\t\tdata->info->refCount--;\n\t\tdata->info = info;\n\t\tdata->info->refCount++;\n\t    }\n\t    if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT))\n\t\t    == &consoleChannelType) {\n\t\tdata = (ChannelData *) Tcl_GetChannelInstanceData(chan);\n\t\tdata->info->refCount--;\n\t\tdata->info = info;\n\t\tdata->info->refCount++;\n\t    }\n\t    if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR))\n\t\t    == &consoleChannelType) {\n\t\tdata = (ChannelData *) Tcl_GetChannelInstanceData(chan);\n\t\tdata->info->refCount--;\n\t\tdata->info = info;\n\t\tdata->info->refCount++;\n\t    }\n\t}\n    } else {\n\tinfo = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));\n\tinfo->refCount = 0;\n    }\n\n    info->consoleInterp = consoleInterp;\n    info->interp = interp;\n\n    Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, info);\n    info->refCount++;\n    Tcl_CreateThreadExitHandler(DeleteConsoleInterp, consoleInterp);\n\n    /*\n     * Add console commands to the interp\n     */\n\n    token = Tcl_CreateObjCommand2(interp, \"console\", ConsoleObjCmd, info,\n\t    ConsoleDeleteProc);\n    info->refCount++;\n\n    /*\n     * We don't have to count the ref held by the [consoleinterp] command\n     * in the consoleInterp.  The ref held by the consoleInterp delete\n     * handler takes care of us.\n     */\n    Tcl_CreateObjCommand2(consoleInterp, \"consoleinterp\", InterpreterObjCmd,\n\t    info, NULL);\n\n    mainWindow = Tk_MainWindow(interp);\n    if (mainWindow) {\n\tTk_CreateEventHandler(mainWindow, StructureNotifyMask,\n\t\tConsoleEventProc, info);\n\tinfo->refCount++;\n    }\n\n    Tcl_Preserve(consoleInterp);\n    result = Tcl_EvalEx(consoleInterp, \"source $tk_library/console.tcl\",\n\t    TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (result == TCL_ERROR) {\n\tTcl_SetReturnOptions(interp,\n\t\tTcl_GetReturnOptions(consoleInterp, result));\n\tTcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp));\n    }\n    Tcl_Release(consoleInterp);\n    if (result == TCL_ERROR) {\n\tTcl_DeleteCommandFromToken(interp, token);\n\tmainWindow = Tk_MainWindow(interp);\n\tif (mainWindow) {\n\t    Tk_DeleteEventHandler(mainWindow, StructureNotifyMask,\n\t\t    ConsoleEventProc, info);\n\t    if (info->refCount-- <= 1) {\n\t\tTcl_Free(info);\n\t    }\n\t}\n\tgoto error;\n    }\n    return TCL_OK;\n\n  error:\n    Tcl_AddErrorInfo(interp, \"\\n    (creating console window)\");\n    if (!Tcl_InterpDeleted(consoleInterp)) {\n\tTcl_DeleteInterp(consoleInterp);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleOutput--\n *\n *\tWrites the given output on the IO channel. Returns count of how many\n *\tcharacters were actually written, and an error indication.\n *\n * Results:\n *\tA count of how many characters were written is returned and an error\n *\tindication is returned in an output argument.\n *\n * Side effects:\n *\tWrites output on the actual channel.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConsoleOutput(\n    void *instanceData,\t/* Indicates which device to use. */\n    const char *buf,\t\t/* The data buffer. */\n    int toWrite,\t\t/* How many bytes to write? */\n    int *errorCode)\t\t/* Where to store error code. */\n{\n    ChannelData *data = (ChannelData *)instanceData;\n    ConsoleInfo *info = data->info;\n\n    *errorCode = 0;\n    Tcl_SetErrno(0);\n\n    if (info) {\n\tTcl_Interp *consoleInterp = info->consoleInterp;\n\n\tif (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {\n\t    Tcl_DString ds;\n\t    Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, \"utf-8\");\n\n\t    /*\n\t     * Not checking for utf8 == NULL.  Did not check for TCL_ERROR\n\t     * from Tcl_SetChannelOption() in Tk_InitConsoleChannels() either.\n\t     * Assumption is utf-8 Tcl_Encoding is reliably present.\n\t     */\n\n\t    const char *bytes = Tcl_ExternalToUtfDString(utf8, buf, toWrite, &ds);\n\t    Tcl_Size numBytes = Tcl_DStringLength(&ds);\n\t    Tcl_Obj *cmd = Tcl_NewStringObj(\"tk::ConsoleOutput\", TCL_INDEX_NONE);\n\n\t    Tcl_FreeEncoding(utf8);\n\n\t    if (data->type == TCL_STDERR) {\n\t\tTcl_ListObjAppendElement(NULL, cmd,\n\t\t\tTcl_NewStringObj(\"stderr\", TCL_INDEX_NONE));\n\t    } else {\n\t\tTcl_ListObjAppendElement(NULL, cmd,\n\t\t\tTcl_NewStringObj(\"stdout\", TCL_INDEX_NONE));\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, cmd,\n\t\t    Tcl_NewStringObj(bytes, numBytes));\n\n\t    Tcl_DStringFree(&ds);\n\t    Tcl_IncrRefCount(cmd);\n\t    Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL);\n\t    Tcl_DecrRefCount(cmd);\n\t}\n    }\n    return toWrite;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleInput --\n *\n *\tRead input from the console. Not currently implemented.\n *\n * Results:\n *\tAlways returns EOF.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConsoleInput(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(char *),\t\t\t/* Where to store data read. */\n    TCL_UNUSED(int),\t\t/* How much space is available in the\n\t\t\t\t * buffer? */\n    TCL_UNUSED(int *))\t\t/* Where to store error code. */\n{\n    return 0;\t\t\t/* Always return EOF. */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleClose/Console2Close --\n *\n *\tCloses the IO channel.\n *\n * Results:\n *\tAlways returns 0 (success).\n *\n * Side effects:\n *\tFrees the dummy file associated with the channel.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConsoleClose(\n    void *instanceData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    ChannelData *data = (ChannelData *)instanceData;\n    ConsoleInfo *info = data->info;\n\n    if (info) {\n\tif (info->refCount-- <= 1) {\n\t    /*\n\t     * Assuming the Tcl_Interp * fields must already be NULL.\n\t     */\n\n\t    Tcl_Free(info);\n\t}\n    }\n    Tcl_Free(data);\n    return 0;\n}\n\nstatic int\nConsole2Close(\n    void *instanceData,\t/* Unused. */\n    Tcl_Interp *interp,\t\t/* Unused. */\n    int flags)\n{\n    if ((flags&(TCL_CLOSE_READ|TCL_CLOSE_WRITE))==0) {\n\treturn ConsoleClose(instanceData, interp);\n    }\n    return EINVAL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleWatch --\n *\n *\tCalled by the notifier to set up the console device so that events\n *\twill be noticed. Since there are no events on the console, this\n *\troutine just returns without doing anything.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConsoleWatch(\n    TCL_UNUSED(void *),\t/* Device ID for the channel. */\n    TCL_UNUSED(int))\t\t\t/* OR-ed combination of TCL_READABLE,\n\t\t\t\t * TCL_WRITABLE and TCL_EXCEPTION, for the\n\t\t\t\t * events we are interested in. */\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleHandle --\n *\n *\tInvoked by the generic IO layer to get a handle from a channel.\n *\tBecause console channels are not devices, this function always fails.\n *\n * Results:\n *\tAlways returns TCL_ERROR.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConsoleHandle(\n    TCL_UNUSED(void *),\t/* Device ID for the channel. */\n    TCL_UNUSED(int),\t\t/* TCL_READABLE or TCL_WRITABLE to indicate\n\t\t\t\t * which direction of the channel is being\n\t\t\t\t * requested. */\n    TCL_UNUSED(void **))\t/* Where to store handle */\n{\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleObjCmd --\n *\n *\tThe console command implements a Tcl interface to the various console\n *\toptions.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConsoleObjCmd(\n    void *clientData,\t/* Access to the console interp */\n    Tcl_Interp *interp,\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t/* Argument objects */\n{\n    int index, result;\n    static const char *const options[] = {\n\t\"eval\", \"hide\", \"show\", \"title\", NULL};\n    enum option {CON_EVAL, CON_HIDE, CON_SHOW, CON_TITLE};\n    Tcl_Obj *cmd = NULL;\n    ConsoleInfo *info = (ConsoleInfo *)clientData;\n    Tcl_Interp *consoleInterp = info->consoleInterp;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum option) index) {\n    case CON_EVAL:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"script\");\n\t    return TCL_ERROR;\n\t}\n\tcmd = objv[2];\n\tbreak;\n    case CON_HIDE:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tcmd = Tcl_NewStringObj(\"wm withdraw .\", TCL_INDEX_NONE);\n\tbreak;\n    case CON_SHOW:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tcmd = Tcl_NewStringObj(\"wm deiconify .\", TCL_INDEX_NONE);\n\tbreak;\n    case CON_TITLE:\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?title?\");\n\t    return TCL_ERROR;\n\t}\n\tcmd = Tcl_NewStringObj(\"wm title .\", TCL_INDEX_NONE);\n\tif (objc == 3) {\n\t    Tcl_ListObjAppendElement(NULL, cmd, objv[2]);\n\t}\n\tbreak;\n    default:\n\tCLANG_ASSERT(0);\n    }\n\n    Tcl_IncrRefCount(cmd);\n    if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {\n\tTcl_Preserve(consoleInterp);\n\tresult = Tcl_EvalObjEx(consoleInterp, cmd, TCL_EVAL_GLOBAL);\n\tTcl_SetReturnOptions(interp,\n\t\tTcl_GetReturnOptions(consoleInterp, result));\n\tTcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp));\n\tTcl_Release(consoleInterp);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"no active console interp\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CONSOLE\", \"NONE\", (char *)NULL);\n\tresult = TCL_ERROR;\n    }\n    Tcl_DecrRefCount(cmd);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InterpreterObjCmd --\n *\n *\tThis command allows the console interp to communicate with the main\n *\tinterpreter.\n *\n * Results:\n *\tA standard Tcl result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInterpreterObjCmd(\n    void *clientData,\t/* */\n    Tcl_Interp *interp,\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t/* Argument objects */\n{\n    int index, result = TCL_OK;\n    static const char *const options[] = {\"eval\", \"record\", NULL};\n    enum option {OTHER_EVAL, OTHER_RECORD};\n    ConsoleInfo *info = (ConsoleInfo *)clientData;\n    Tcl_Interp *otherInterp = info->interp;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option arg\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"script\");\n\treturn TCL_ERROR;\n    }\n\n    if ((otherInterp == NULL) || Tcl_InterpDeleted(otherInterp)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"no active parent interp\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CONSOLE\", \"NO_INTERP\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_Preserve(otherInterp);\n    switch ((enum option) index) {\n    case OTHER_EVAL:\n\tresult = Tcl_EvalObjEx(otherInterp, objv[2], TCL_EVAL_GLOBAL);\n\n\t/*\n\t * TODO: Should exceptions be filtered here?\n\t */\n\n\tTcl_SetReturnOptions(interp,\n\t\tTcl_GetReturnOptions(otherInterp, result));\n\tTcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp));\n\tbreak;\n    case OTHER_RECORD:\n\tTcl_RecordAndEvalObj(otherInterp, objv[2], TCL_EVAL_GLOBAL);\n\n\t/*\n\t * By not setting result, we discard any exceptions or errors here and\n\t * always return TCL_OK. All the caller wants is the interp result to\n\t * display, whether that's result or error message.\n\t */\n\n\tTcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp));\n\tbreak;\n    }\n    Tcl_Release(otherInterp);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteConsoleInterp --\n *\n *\tThread exit handler to destroy a console interp when the thread it\n *\tlives in gets torn down.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteConsoleInterp(\n    void *clientData)\n{\n    Tcl_Interp *interp = (Tcl_Interp *)clientData;\n\n    Tcl_DeleteInterp(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InterpDeleteProc --\n *\n *\tReact when the interp in which the console is displayed is deleted for\n *\tany reason.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new console it created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInterpDeleteProc(\n    void *clientData,\n    Tcl_Interp *interp)\n{\n    ConsoleInfo *info = (ConsoleInfo *)clientData;\n\n    if (info->consoleInterp == interp) {\n\tTcl_DeleteThreadExitHandler(DeleteConsoleInterp, info->consoleInterp);\n\tinfo->consoleInterp = NULL;\n    }\n    if (info->refCount-- <= 1) {\n\tTcl_Free(info);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleDeleteProc --\n *\n *\tIf the console command is deleted we destroy the console window and\n *\tall associated data structures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new console it created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConsoleDeleteProc(\n    void *clientData)\n{\n    ConsoleInfo *info = (ConsoleInfo *)clientData;\n\n    if (info->consoleInterp) {\n\tTcl_DeleteInterp(info->consoleInterp);\n    }\n    if (info->refCount-- <= 1) {\n\tTcl_Free(info);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConsoleEventProc --\n *\n *\tThis event function is registered on the main window of the child\n *\tinterpreter. If the user or a running script causes the main window to\n *\tbe destroyed, then we need to inform the console interpreter by\n *\tinvoking \"::tk::ConsoleExit\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInvokes the \"::tk::ConsoleExit\" command in the console interp.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConsoleEventProc(\n    void *clientData,\n    XEvent *eventPtr)\n{\n    if (eventPtr->type == DestroyNotify) {\n\tConsoleInfo *info = (ConsoleInfo *)clientData;\n\tTcl_Interp *consoleInterp = info->consoleInterp;\n\n\tif (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {\n\t    Tcl_EvalEx(consoleInterp, \"tk::ConsoleExit\", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t}\n\n\tif (info->refCount-- <= 1) {\n\t    Tcl_Free(info);\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkCursor.c",
    "content": "/*\n * tkCursor.c --\n *\n *\tThis file maintains a database of read-only cursors for the Tk\n *\ttoolkit. This allows cursors to be shared between widgets and also\n *\tavoids round-trips to the X server.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * A TkCursor structure exists for each cursor that is currently active. Each\n * structure is indexed with two hash tables defined below. One of the tables\n * is cursorIdTable, and the other is either cursorNameTable or\n * cursorDataTable, each of which are stored in the TkDisplay structure for\n * the current thread.\n */\n\ntypedef struct {\n    const char *source;\t\t/* Cursor bits. */\n    const char *mask;\t\t/* Mask bits. */\n    int width, height;\t\t/* Dimensions of cursor (and data and\n\t\t\t\t * mask). */\n    int xHot, yHot;\t\t/* Location of cursor hot-spot. */\n    Tk_Uid fg, bg;\t\t/* Colors for cursor. */\n    Display *display;\t\t/* Display on which cursor will be used. */\n} DataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tCursorInit(TkDisplay *dispPtr);\nstatic void\t\tDupCursorObjProc(Tcl_Obj *srcObjPtr,\n\t\t\t    Tcl_Obj *dupObjPtr);\nstatic void\t\tFreeCursor(TkCursor *cursorPtr);\nstatic void\t\tFreeCursorObj(Tcl_Obj *objPtr);\nstatic void\t\tFreeCursorObjProc(Tcl_Obj *objPtr);\nstatic TkCursor *\tTkcGetCursor(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *name);\nstatic TkCursor *\tGetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\nstatic void\t\tInitCursorObj(Tcl_Obj *objPtr);\n\n/*\n * The following structure defines the implementation of the \"cursor\" Tcl\n * object, used for drawing. The color object remembers the hash table\n * entry associated with a color. The actual allocation and deallocation\n * of the color should be done by the configuration package when the cursor\n * option is set.\n */\n\nconst Tcl_ObjType tkCursorObjType = {\n    \"cursor\",\t\t\t/* name */\n    FreeCursorObjProc,\t\t/* freeIntRepProc */\n    DupCursorObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V1(TkLengthOne)\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_AllocCursorFromObj --\n *\n *\tGiven a Tcl_Obj *, map the value to a corresponding Tk_Cursor\n *\tstructure based on the tkwin given.\n *\n * Results:\n *\tThe return value is the X identifer for the desired cursor, unless\n *\tobjPtr couldn't be parsed correctly. In this case, None is returned\n *\tand an error message is left in the interp's result. The caller should\n *\tnever modify the cursor that is returned, and should eventually call\n *\tTk_FreeCursorFromObj when the cursor is no longer needed.\n *\n * Side effects:\n *\tThe cursor is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeCursorFromObj, so that the database can be cleaned up when\n *\tcursors aren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Cursor\nTk_AllocCursorFromObj(\n    Tcl_Interp *interp,\t\t/* Interp for error results. */\n    Tk_Window tkwin,\t\t/* Window in which the cursor will be used.*/\n    Tcl_Obj *objPtr)\t\t/* Object describing cursor; see manual entry\n\t\t\t\t * for description of legal syntax of this\n\t\t\t\t * obj's string rep. */\n{\n    TkCursor *cursorPtr;\n\n    if (objPtr->typePtr != &tkCursorObjType) {\n\tInitCursorObj(objPtr);\n    }\n    cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    /*\n     * If the object currently points to a TkCursor, see if it's the one we\n     * want. If so, increment its reference count and return.\n     */\n\n    if (cursorPtr != NULL) {\n\tif (cursorPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a TkCursor that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\n\t    FreeCursorObj(objPtr);\n\t    cursorPtr = NULL;\n\t} else if (Tk_Display(tkwin) == cursorPtr->display) {\n\t    cursorPtr->resourceRefCount++;\n\t    return cursorPtr->cursor;\n\t}\n    }\n\n    /*\n     * The object didn't point to the TkCursor that we wanted. Search the list\n     * of TkCursors with the same name to see if one of the other TkCursors is\n     * the right one.\n     */\n\n    if (cursorPtr != NULL) {\n\tTkCursor *firstCursorPtr = (TkCursor *)Tcl_GetHashValue(cursorPtr->hashPtr);\n\n\tFreeCursorObj(objPtr);\n\tfor (cursorPtr = firstCursorPtr;  cursorPtr != NULL;\n\t\tcursorPtr = cursorPtr->nextPtr) {\n\t    if (Tk_Display(tkwin) == cursorPtr->display) {\n\t\tcursorPtr->resourceRefCount++;\n\t\tcursorPtr->objRefCount++;\n\t\tobjPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;\n\t\treturn cursorPtr->cursor;\n\t    }\n\t}\n    }\n\n    /*\n     * Still no luck. Call TkcGetCursor to allocate a new TkCursor object.\n     */\n\n    cursorPtr = TkcGetCursor(interp, tkwin, Tcl_GetString(objPtr));\n    objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;\n    if (cursorPtr == NULL) {\n\treturn NULL;\n    }\n    cursorPtr->objRefCount++;\n    return cursorPtr->cursor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetCursor --\n *\n *\tGiven a string describing a cursor, locate (or create if necessary) a\n *\tcursor that fits the description.\n *\n * Results:\n *\tThe return value is the X identifer for the desired cursor, unless\n *\tstring couldn't be parsed correctly. In this case, None is returned\n *\tand an error message is left in the interp's result. The caller should\n *\tnever modify the cursor that is returned, and should eventually call\n *\tTk_FreeCursor when the cursor is no longer needed.\n *\n * Side effects:\n *\tThe cursor is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeCursor, so that the database can be cleaned up when cursors\n *\taren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Cursor\nTk_GetCursor(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *string)\t\t/* Description of cursor. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    TkCursor *cursorPtr = TkcGetCursor(interp, tkwin, string);\n\n    if (cursorPtr == NULL) {\n\treturn NULL;\n    }\n    return cursorPtr->cursor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkcGetCursor --\n *\n *\tGiven a string describing a cursor, locate (or create if necessary) a\n *\tcursor that fits the description. This routine returns the internal\n *\tdata structure for the cursor, which avoids extra hash table lookups\n *\tin Tk_AllocCursorFromObj.\n *\n * Results:\n *\tThe return value is a pointer to the TkCursor for the desired cursor,\n *\tunless string couldn't be parsed correctly. In this case, NULL is\n *\treturned and an error message is left in the interp's result. The\n *\tcaller should never modify the cursor that is returned, and should\n *\teventually call Tk_FreeCursor when the cursor is no longer needed.\n *\n * Side effects:\n *\tThe cursor is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeCursor, so that the database can be cleaned up when cursors\n *\taren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkCursor *\nTkcGetCursor(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *string)\t\t/* Description of cursor. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    Tcl_HashEntry *nameHashPtr;\n    TkCursor *cursorPtr;\n    TkCursor *existingCursorPtr = NULL;\n    int isNew;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (!dispPtr->cursorInit) {\n\tCursorInit(dispPtr);\n    }\n\n    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable,\n\t    string, &isNew);\n    if (!isNew) {\n\texistingCursorPtr = (TkCursor *)Tcl_GetHashValue(nameHashPtr);\n\tfor (cursorPtr = existingCursorPtr; cursorPtr != NULL;\n\t\tcursorPtr = cursorPtr->nextPtr) {\n\t    if (Tk_Display(tkwin) == cursorPtr->display) {\n\t\tcursorPtr->resourceRefCount++;\n\t\treturn cursorPtr;\n\t    }\n\t}\n    } else {\n\texistingCursorPtr = NULL;\n    }\n\n    cursorPtr = TkGetCursorByName(interp, tkwin, string);\n\n    if (cursorPtr == NULL) {\n\tif (isNew) {\n\t    Tcl_DeleteHashEntry(nameHashPtr);\n\t}\n\treturn NULL;\n    }\n\n    /*\n     * Add information about this cursor to our database.\n     */\n\n    cursorPtr->display = Tk_Display(tkwin);\n    cursorPtr->resourceRefCount = 1;\n    cursorPtr->objRefCount = 0;\n    cursorPtr->otherTable = &dispPtr->cursorNameTable;\n    cursorPtr->hashPtr = nameHashPtr;\n    cursorPtr->nextPtr = existingCursorPtr;\n    cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,\n\t    (char *) cursorPtr->cursor, &isNew);\n    if (!isNew) {\n\tTcl_Panic(\"cursor already registered in Tk_GetCursor\");\n    }\n    Tcl_SetHashValue(nameHashPtr, cursorPtr);\n    Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);\n\n    return cursorPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetCursorFromData --\n *\n *\tGiven a description of the bits and colors for a cursor, make a cursor\n *\tthat has the given properties.\n *\n * Results:\n *\tThe return value is the X identifer for the desired cursor, unless it\n *\tcouldn't be created properly. In this case, None is returned and an\n *\terror message is left in the interp's result. The caller should never\n *\tmodify the cursor that is returned, and should eventually call\n *\tTk_FreeCursor when the cursor is no longer needed.\n *\n * Side effects:\n *\tThe cursor is added to an internal database with a reference count.\n *\tFor each call to this function, there should eventually be a call to\n *\tTk_FreeCursor, so that the database can be cleaned up when cursors\n *\taren't needed anymore.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Cursor\nTk_GetCursorFromData(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *source,\t\t/* Bitmap data for cursor shape. */\n    const char *mask,\t\t/* Bitmap data for cursor mask. */\n    int width, int height,\t/* Dimensions of cursor. */\n    int xHot, int yHot,\t\t/* Location of hot-spot in cursor. */\n    const char *fg,\t\t\t/* Foreground color for cursor. */\n    const char *bg)\t\t\t/* Background color for cursor. */\n{\n    DataKey dataKey;\n    Tcl_HashEntry *dataHashPtr;\n    TkCursor *cursorPtr;\n    int isNew;\n    XColor fgColor, bgColor;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (!dispPtr->cursorInit) {\n\tCursorInit(dispPtr);\n    }\n\n    dataKey.source = source;\n    dataKey.mask = mask;\n    dataKey.width = width;\n    dataKey.height = height;\n    dataKey.xHot = xHot;\n    dataKey.yHot = yHot;\n    dataKey.fg = Tk_GetUid(fg);\n    dataKey.bg = Tk_GetUid(bg);\n    dataKey.display = Tk_Display(tkwin);\n    dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable,\n\t    (char *) &dataKey, &isNew);\n    if (!isNew) {\n\tcursorPtr = (TkCursor *)Tcl_GetHashValue(dataHashPtr);\n\tcursorPtr->resourceRefCount++;\n\treturn cursorPtr->cursor;\n    }\n\n    /*\n     * No suitable cursor exists yet. Make one using the data available and\n     * add it to the database.\n     */\n\n    if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"invalid color name \\\"%s\\\"\", fg));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\tgoto error;\n    }\n    if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"invalid color name \\\"%s\\\"\", bg));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\tgoto error;\n    }\n\n    cursorPtr = TkCreateCursorFromData(tkwin, source, mask, width, height,\n\t    xHot, yHot, fgColor, bgColor);\n\n    if (cursorPtr == NULL) {\n\tgoto error;\n    }\n\n    cursorPtr->resourceRefCount = 1;\n    cursorPtr->otherTable = &dispPtr->cursorDataTable;\n    cursorPtr->hashPtr = dataHashPtr;\n    cursorPtr->objRefCount = 0;\n    cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,\n\t    (char *) cursorPtr->cursor, &isNew);\n    cursorPtr->nextPtr = NULL;\n\n    if (!isNew) {\n\tTcl_Panic(\"cursor already registered in Tk_GetCursorFromData\");\n    }\n    Tcl_SetHashValue(dataHashPtr, cursorPtr);\n    Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);\n    return cursorPtr->cursor;\n\n  error:\n    Tcl_DeleteHashEntry(dataHashPtr);\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfCursor --\n *\n *\tGiven a cursor, return a textual string identifying it.\n *\n * Results:\n *\tIf cursor was created by Tk_GetCursor, then the return value is the\n *\t\"string\" that was used to create it. Otherwise the return value is a\n *\tstring giving the X identifier for the cursor. The storage for the\n *\treturned string is only guaranteed to persist up until the next call\n *\tto this function.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfCursor(\n    Display *display,\t\t/* Display for which cursor was allocated. */\n    Tk_Cursor cursor)\t\t/* Identifier for cursor whose name is\n\t\t\t\t * wanted. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkCursor *cursorPtr;\n    TkDisplay *dispPtr;\n\n    dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->cursorInit) {\n    printid:\n\tsnprintf(dispPtr->cursorString, sizeof(dispPtr->cursorString), \"cursor id 0x%\" TCL_Z_MODIFIER \"x\", PTR2INT(cursor));\n\treturn dispPtr->cursorString;\n    }\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor);\n    if (idHashPtr == NULL) {\n\tgoto printid;\n    }\n    cursorPtr = (TkCursor *)Tcl_GetHashValue(idHashPtr);\n    if (cursorPtr->otherTable != &dispPtr->cursorNameTable) {\n\tgoto printid;\n    }\n    return cursorPtr->hashPtr->key.string;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeCursor --\n *\n *\tThis function is invoked by both Tk_FreeCursorFromObj and\n *\tTk_FreeCursor; it does all the real work of deallocating a cursor.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with cursor is decremented, and it is\n *\tofficially deallocated if no-one is using it anymore.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeCursor(\n    TkCursor *cursorPtr)\t/* Cursor to be released. */\n{\n    TkCursor *prevPtr;\n\n    if (cursorPtr->resourceRefCount-- > 1) {\n\treturn;\n    }\n\n    Tcl_DeleteHashEntry(cursorPtr->idHashPtr);\n    prevPtr = (TkCursor *)Tcl_GetHashValue(cursorPtr->hashPtr);\n    if (prevPtr == cursorPtr) {\n\tif (cursorPtr->nextPtr == NULL) {\n\t    Tcl_DeleteHashEntry(cursorPtr->hashPtr);\n\t} else {\n\t    Tcl_SetHashValue(cursorPtr->hashPtr, cursorPtr->nextPtr);\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != cursorPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t}\n\tprevPtr->nextPtr = cursorPtr->nextPtr;\n    }\n    TkpFreeCursor(cursorPtr);\n    if (cursorPtr->objRefCount == 0) {\n\tTcl_Free(cursorPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeCursor --\n *\n *\tThis function is called to release a cursor allocated by Tk_GetCursor\n *\tor TkGetCursorFromData.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with cursor is decremented, and it is\n *\tofficially deallocated if no-one is using it anymore.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeCursor(\n    Display *display,\t\t/* Display for which cursor was allocated. */\n    Tk_Cursor cursor)\t\t/* Identifier for cursor to be released. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->cursorInit) {\n\tTcl_Panic(\"Tk_FreeCursor called before Tk_GetCursor\");\n    }\n\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor);\n    if (idHashPtr == NULL) {\n\tTcl_Panic(\"Tk_FreeCursor received unknown cursor argument\");\n    }\n    FreeCursor((TkCursor *)Tcl_GetHashValue(idHashPtr));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeCursorFromObj --\n *\n *\tThis function is called to release a cursor allocated by\n *\tTk_AllocCursorFromObj. It does not throw away the Tcl_Obj *; it only\n *\tgets rid of the hash table entry for this cursor and clears the cached\n *\tvalue that is normally stored in the object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with the cursor represented by objPtr\n *\tis decremented, and the cursor is released to X if there are no\n *\tremaining uses for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeCursorFromObj(\n    Tk_Window tkwin,\t\t/* The window this cursor lives in. Needed for\n\t\t\t\t * the display value. */\n    Tcl_Obj *objPtr)\t\t/* The Tcl_Obj * to be freed. */\n{\n    FreeCursor(GetCursorFromObj(tkwin, objPtr));\n    FreeCursorObj(objPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeCursorObjProc, FreeCursorObj --\n *\n *\tThis proc is called to release an object reference to a cursor.\n *\tCalled when the object's internal rep is released or when the cached\n *\ttkColPtr needs to be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object reference count is decremented. When both it and the hash\n *\tref count go to zero, the color's resources are released.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeCursorObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    FreeCursorObj(objPtr);\n    objPtr->typePtr = NULL;\n}\n\nstatic void\nFreeCursorObj(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    TkCursor *cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    if (cursorPtr != NULL) {\n\tif ((cursorPtr->objRefCount-- <= 1)\n\t\t&& (cursorPtr->resourceRefCount == 0)) {\n\t    Tcl_Free(cursorPtr);\n\t}\n\tobjPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupCursorObjProc --\n *\n *\tWhen a cached cursor object is duplicated, this is called to update\n *\tthe internal reps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe color's objRefCount is incremented and the internal rep of the\n *\tcopy is set to point to it.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupCursorObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    TkCursor *cursorPtr = (TkCursor *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;\n\n    if (cursorPtr != NULL) {\n\tcursorPtr->objRefCount++;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetCursorFromObj --\n *\n *\tReturns the cursor referred to buy a Tcl object. The cursor must\n *\talready have been allocated via a call to Tk_AllocCursorFromObj or\n *\tTk_GetCursor.\n *\n * Results:\n *\tReturns the Tk_Cursor that matches the tkwin and the string rep of the\n *\tname of the cursor given in objPtr.\n *\n * Side effects:\n *\tIf the object is not already a cursor, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Cursor\nTk_GetCursorFromObj(\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr)\t\t/* The object from which to get pixels. */\n{\n    TkCursor *cursorPtr = GetCursorFromObj(tkwin, objPtr);\n\n    /*\n     * GetCursorFromObj should never return NULL\n     */\n\n    return cursorPtr->cursor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetCursorFromObj --\n *\n *\tReturns the cursor referred to by a Tcl object. The cursor must\n *\talready have been allocated via a call to Tk_AllocCursorFromObj or\n *\tTk_GetCursor.\n *\n * Results:\n *\tReturns the TkCursor * that matches the tkwin and the string rep of\n *\tthe name of the cursor given in objPtr.\n *\n * Side effects:\n *\tIf the object is not already a cursor, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkCursor *\nGetCursorFromObj(\n    Tk_Window tkwin,\t\t/* Window in which the cursor will be used. */\n    Tcl_Obj *objPtr)\t\t/* The object that describes the desired\n\t\t\t\t * cursor. */\n{\n    TkCursor *cursorPtr;\n    Tcl_HashEntry *hashPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objPtr->typePtr != &tkCursorObjType) {\n\tInitCursorObj(objPtr);\n    }\n\n    /*\n     * The internal representation is a cache of the last cursor used with the\n     * given name. But there can be lots different cursors for each cursor\n     * name; one cursor for each display. Check to see if the cursor we have\n     * cached is the one that is needed.\n     */\n\n    cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;\n    if ((cursorPtr != NULL) && (Tk_Display(tkwin) == cursorPtr->display)) {\n\treturn cursorPtr;\n    }\n\n    /*\n     * If we get to here, it means the cursor we need is not in the cache.\n     * Try to look up the cursor in the TkDisplay structure of the window.\n     */\n\n    hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable,\n\t    Tcl_GetString(objPtr));\n    if (hashPtr == NULL) {\n\tgoto error;\n    }\n    for (cursorPtr = (TkCursor *)Tcl_GetHashValue(hashPtr);\n\t    cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) {\n\tif (Tk_Display(tkwin) == cursorPtr->display) {\n\t    FreeCursorObj(objPtr);\n\t    objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;\n\t    cursorPtr->objRefCount++;\n\t    return cursorPtr;\n\t}\n    }\n\n  error:\n    Tcl_Panic(\"GetCursorFromObj called with non-existent cursor!\");\n    /*\n     * The following code isn't reached; it's just there to please compilers.\n     */\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitCursorObj --\n *\n *\tBookeeping function to change an objPtr to a cursor type.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe old internal rep of the object is freed. The internal rep is\n *\tcleared. The final form of the object is set by either\n *\tTk_AllocCursorFromObj or GetCursorFromObj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitCursorObj(\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->typePtr = &tkCursorObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CursorInit --\n *\n *\tInitialize the structures used for cursor management.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRead the code.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCursorInit(\n    TkDisplay *dispPtr)\t\t/* Display used to store thread-specific\n\t\t\t\t * data. */\n{\n    Tcl_InitHashTable(&dispPtr->cursorNameTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&dispPtr->cursorDataTable, sizeof(DataKey)/sizeof(int));\n\n    /*\n     * The call below is tricky: can't use sizeof(IdKey) because it gets\n     * padded with extra unpredictable bytes on some 64-bit machines.\n     */\n\n    /*\n     * Old code....\n     *     Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *)\n     *                       /sizeof(int));\n     *\n     * The comment above doesn't make sense. However, XIDs should only be 32\n     * bits, by the definition of X, so the code above causes Tk to crash.\n     * Here is the real code:\n     */\n\n    Tcl_InitHashTable(&dispPtr->cursorIdTable, TCL_ONE_WORD_KEYS);\n\n    dispPtr->cursorInit = 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugCursor --\n *\n *\tThis function returns debugging information about a cursor.\n *\n * Results:\n *\tThe return value is a list with one sublist for each TkCursor\n *\tcorresponding to \"name\". Each sublist has two elements that contain\n *\tthe resourceRefCount and objRefCount fields from the TkCursor\n *\tstructure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugCursor(\n    Tk_Window tkwin,\t\t/* The window in which the cursor will be used\n\t\t\t\t * (not currently used). */\n    const char *name)\t\t/* Name of the desired color. */\n{\n    TkCursor *cursorPtr;\n    Tcl_HashEntry *hashPtr;\n    Tcl_Obj *resultPtr, *objPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (!dispPtr->cursorInit) {\n\tCursorInit(dispPtr);\n    }\n    resultPtr = Tcl_NewObj();\n    hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, name);\n    if (hashPtr != NULL) {\n\tcursorPtr = (TkCursor *)Tcl_GetHashValue(hashPtr);\n\tif (cursorPtr == NULL) {\n\t    Tcl_Panic(\"TkDebugCursor found empty hash table entry\");\n\t}\n\tfor ( ; (cursorPtr != NULL); cursorPtr = cursorPtr->nextPtr) {\n\t    objPtr = Tcl_NewObj();\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(cursorPtr->resourceRefCount));\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(cursorPtr->objRefCount));\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);\n\t}\n    }\n    return resultPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkDList.h",
    "content": "/*\n * tkDList.h --\n *\n * A list is headed by pointers to first and last element. The elements\n * are doubly linked so that an arbitrary element can be removed without\n * a need to traverse the list. New elements can be added to the list\n * before or after an existing element or at the head/tail of the list.\n * A list may be traversed in the forward or backward direction.\n *\n * Copyright © 2018 Gregor Cramer.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Note that this file will not be included in header files, it is the purpose\n * of this file to be included in source files only. Thus we are not using the\n * prefix \"Tk_\" here for functions, because all the functions have private scope.\n */\n\f\n/*\n * -------------------------------------------------------------------------------\n * Use the double linked list in the following way:\n * -------------------------------------------------------------------------------\n * typedef struct MyListEntry { TK_DLIST_LINKS(MyListEntry); int value; } MyListEntry;\n * TK_DLIST_DEFINE(MyList, MyListEntry);\n * MyList listHdr = TK_DLIST_LIST_INITIALIZER; // or MyList_Init(&listHdr)\n * MyListEntry *p;\n * int i = 0;\n * MyList_Append(&listHdr, (MyListEntry *)Tcl_Alloc(sizeof(MyListEntry)));\n * MyList_Append(&listHdr, (MyListEntry *)Tcl_Alloc(sizeof(MyListEntry)));\n * TK_DLIST_FOREACH(p, &listHdr) { p->value = i++; }\n * // ...\n * MyList_RemoveHead(&listHdr);\n * MyList_RemoveHead(&listHdr);\n * MyList_Clear(MyListEntry, &listHdr); // invokes Tcl_Free() for each element\n * -------------------------------------------------------------------------------\n * IMPORTANT NOTE: TK_DLIST_LINKS must be used at start of struct!\n */\n\f\n#ifndef TK_DLIST_DEFINED\n#define TK_DLIST_DEFINED\n\n#include \"tkInt.h\"\n\n/*\n * List definitions.\n */\n\n#define TK_DLIST_LINKS(ElemType)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\t\\\n    struct ElemType *prev;\t/* previous element */\t\t\t\t\\\n    struct ElemType *next;\t/* next element */\t\t\t\t\\\n} _dl_\n\n#define TK_DLIST_LIST_INITIALIZER { NULL, NULL }\n#define TK_DLIST_ELEM_INITIALIZER { NULL, NULL }\n\n/*************************************************************************/\n/*\n * DList_Init: Initialize list header. This can also be used to clear the\n * list.\n *\n * See also: DList_Clear()\n */\n/*************************************************************************/\n/*\n * DList_ElemInit: Initialize a list element.\n */\n/*************************************************************************/\n/*\n * DList_InsertAfter: Insert 'elem' after 'listElem'. 'elem' must not\n * be linked, but 'listElem' must be linked.\n */\n/*************************************************************************/\n/*\n * DList_InsertBefore: Insert 'elem' before 'listElem'. 'elem' must not\n * be linked, but 'listElem' must be linked.\n */\n/*************************************************************************/\n/*\n * DList_Prepend: Insert 'elem' at start of list. This element must not\n * be linked.\n *\n * See also: DList_Append()\n */\n/*************************************************************************/\n/*\n * DList_Append: Append 'elem' to end of list. This element must not\n * be linked.\n *\n * See also: DList_Prepend()\n */\n/*************************************************************************/\n/*\n * DList_Move: Append all list items of 'src' to end of 'dst'.\n */\n/*************************************************************************/\n/*\n * DList_Remove: Remove 'elem' from list. This element must be linked.\n *\n * See also: DList_Free()\n */\n/*************************************************************************/\n/*\n * DList_Free: Remove 'elem' from list and free it. This element must\n * be linked.\n *\n * See also: DList_Remove()\n */\n/*************************************************************************/\n/*\n * DList_RemoveHead: Remove first element from list. The list must\n * not be empty.\n *\n * See also: DList_FreeHead()\n */\n/*************************************************************************/\n/*\n * DList_RemoveTail: Remove last element from list. The list must\n * not be empty.\n *\n * See also: DList_FreeTail()\n */\n/*************************************************************************/\n/*\n * DList_FreeHead: Remove first element from list and free it.\n * The list must not be empty.\n *\n * See also: DList_RemoveHead()\n */\n/*************************************************************************/\n/*\n * DList_FreeTail: Remove last element from list and free it.\n * The list must not be empty.\n *\n * See also: DList_RemoveTail()\n */\n/*************************************************************************/\n/*\n * DList_SwapElems: Swap positions of given elements 'lhs' and 'rhs'.\n * Both elements must be linked, and must belong to same list.\n */\n/*************************************************************************/\n/*\n * DList_Clear: Clear whole list and free all elements.\n *\n * See also: DList_Init\n */\n/*************************************************************************/\n/*\n * DList_Traverse: Iterate over all elements in list from first to last.\n * Call given function func(head, elem) for each element. The function has\n * to return the next element in list to traverse, normally this is\n * DList_Next(elem).\n *\n * See also: TK_DLIST_FOREACH, TK_DLIST_FOREACH_REVERSE\n */\n/*************************************************************************/\n/*\n * DList_First: Return pointer of first element in list, maybe it's NULL.\n */\n/*************************************************************************/\n/*\n * DList_Last: Return pointer of last element in list, maybe it's NULL.\n */\n/*************************************************************************/\n/*\n * DList_Next: Return pointer of next element after 'elem', maybe it's NULL.\n *\n * See also: DList_Prev()\n */\n/*************************************************************************/\n/*\n * DList_Prev: Return pointer of previous element before 'elem', maybe it's\n * NULL.\n *\n * See also: DList_Next()\n */\n/*************************************************************************/\n/*\n * DList_IsEmpty: Test whether given list is empty.\n */\n/*************************************************************************/\n/*\n * DList_IsLinked: Test whether given element is linked.\n */\n/*************************************************************************/\n/*\n * DList_IsFirst: Test whether given element is first element in list.\n * Note that 'elem' must be linked.\n *\n * See also: DList_IsLast(), DList_IsLinked()\n */\n/*************************************************************************/\n/*\n * DList_IsLast: Test whether given element is last element in list.\n * Note that 'elem' must be linked.\n *\n * See also: DList_IsFirst(), DList_IsLinked()\n */\n/*************************************************************************/\n/*\n * DList_Size: Count number of elements in given list.\n */\n/*************************************************************************/\n/*\n * TK_DLIST_FOREACH: Iterate over all elements in list from first to last.\n * 'var' is the name of the variable which points to current element.\n *\n * See also: TK_DLIST_FOREACH_REVERSE, DList_Traverse()\n */\n/*************************************************************************/\n/*\n * TK_DLIST_FOREACH_REVERSE: Iterate over all elements in list from last\n * to first (backwards). 'var' is the name of the variable which points to\n * current element.\n */\n/*************************************************************************/\n\f\n#if defined(__GNUC__) || defined(__clang__)\n# define __TK_DLIST_UNUSED __attribute__((unused))\n#else\n# define __TK_DLIST_UNUSED\n#endif\n\n#define TK_DLIST_DEFINE(LT, ElemType) /* LT = type of head/list */\t\t\\\n/* ------------------------------------------------------------------------- */\t\\\ntypedef struct LT {\t\t\t\t\t\t\t\t\\\n    struct ElemType *first;\t/* first element */\t\t\t\t\\\n    struct ElemType *last;\t/* last element */\t\t\t\t\\\n} LT;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\ntypedef struct ElemType *(LT##_Func)(LT *head, struct ElemType *elem);\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Init(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    head->first = NULL;\t\t\t\t\t\t\t\t\\\n    head->last = NULL;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_ElemInit(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    elem->_dl_.next = NULL;\t\t\t\t\t\t\t\\\n    elem->_dl_.prev = NULL;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nLT##_IsEmpty(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    return head->first == NULL;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nLT##_IsLinked(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    return elem->_dl_.next && elem->_dl_.prev;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nLT##_IsFirst(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(LT##_IsLinked(elem));\t\t\t\t\t\t\\\n    return elem->_dl_.prev->_dl_.prev == elem;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic bool\t\t\t\t\t\t\t\t\t\\\nLT##_IsLast(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(LT##_IsLinked(elem));\t\t\t\t\t\t\\\n    return elem->_dl_.next->_dl_.next == elem;\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic struct ElemType *\t\t\t\t\t\t\t\\\nLT##_First(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    return head->first;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic struct ElemType *\t\t\t\t\t\t\t\\\nLT##_Last(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    return head->last;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic struct ElemType *\t\t\t\t\t\t\t\\\nLT##_Next(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    return LT##_IsLast(elem) ? NULL : elem->_dl_.next;\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic struct ElemType *\t\t\t\t\t\t\t\\\nLT##_Prev(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    return LT##_IsFirst(elem) ? NULL : elem->_dl_.prev;\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic size_t\t\t\t\t\t\t\t\t\t\\\nLT##_Size(const LT *head)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    const struct ElemType *elem;\t\t\t\t\t\t\\\n    size_t size = 0;\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    if ((elem = head->first)) {\t\t\t\t\t\t\t\\\n\tfor ( ; elem != (void *) head; elem = elem->_dl_.next) {\t\t\\\n\t    ++size;\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    return size;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_InsertAfter(struct ElemType *listElem, struct ElemType *elem)\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(listElem);\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    elem->_dl_.next = listElem->_dl_.next;\t\t\t\t\t\\\n    elem->_dl_.prev = listElem;\t\t\t\t\t\t\t\\\n    listElem->_dl_.next->_dl_.prev = elem;\t\t\t\t\t\\\n    listElem->_dl_.next = elem;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_InsertBefore(struct ElemType *listElem, struct ElemType *elem)\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(listElem);\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    elem->_dl_.next = listElem;\t\t\t\t\t\t\t\\\n    elem->_dl_.prev = listElem->_dl_.prev;;\t\t\t\t\t\\\n    listElem->_dl_.prev->_dl_.next = elem;\t\t\t\t\t\\\n    listElem->_dl_.prev = elem;\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Prepend(LT *head, struct ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    elem->_dl_.prev = (PSEntry *) head;\t\t\t\t\t\t\\\n    if (!head->first) {\t\t\t\t\t\t\t\t\\\n\telem->_dl_.next = (PSEntry *) head;\t\t\t\t\t\\\n\thead->last = elem;\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\t\\\n\telem->_dl_.next = head->first;\t\t\t\t\t\t\\\n\thead->first->_dl_.prev = elem;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    head->first = elem;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Append(LT *head, struct ElemType *elem)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    assert(elem);\t\t\t\t\t\t\t\t\\\n    elem->_dl_.next = (PSEntry *) head;\t\t\t\t\t\t\\\n    if (!head->first) {\t\t\t\t\t\t\t\t\\\n\telem->_dl_.prev = (PSEntry *) head;\t\t\t\t\t\\\n\thead->first = elem;\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\t\\\n\telem->_dl_.prev = head->last;\t\t\t\t\t\t\\\n\thead->last->_dl_.next = elem;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    head->last = elem;\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Move(LT *dst, LT *src)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(dst);\t\t\t\t\t\t\t\t\\\n    assert(src);\t\t\t\t\t\t\t\t\\\n    if (src->first) {\t\t\t\t\t\t\t\t\\\n\tif (dst->first) {\t\t\t\t\t\t\t\\\n\t    dst->last->_dl_.next = src->first;\t\t\t\t\t\\\n\t    src->first->_dl_.prev = dst->last;\t\t\t\t\t\\\n\t    dst->last = src->last;\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\t\\\n\t    *dst = *src;\t\t\t\t\t\t\t\\\n\t    dst->first->_dl_.prev = (PSEntry *) dst;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\tdst->last->_dl_.next = (PSEntry *) dst;\t\t\t\t\t\\\n\tLT##_Init(src);\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Remove(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    int isFirst, isLast;\t\t\t\t\t\t\t\\\n    assert(LT##_IsLinked(elem));\t\t\t\t\t\t\\\n    isFirst = LT##_IsFirst(elem);\t\t\t\t\t\t\\\n    isLast = LT##_IsLast(elem);\t\t\t\t\t\t\t\\\n    if (isFirst && isLast) {\t\t\t\t\t\t\t\\\n\t((LT *) elem->_dl_.prev)->first = NULL;\t\t\t\t\t\\\n\t((LT *) elem->_dl_.next)->last = NULL;\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\t\\\n\tif (isFirst) {\t\t\t\t\t\t\t\t\\\n\t    ((LT *) elem->_dl_.prev)->first = elem->_dl_.next;\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\t\\\n\t    elem->_dl_.prev->_dl_.next = elem->_dl_.next;\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\tif (isLast) {\t\t\t\t\t\t\t\t\\\n\t    ((LT *) elem->_dl_.next)->last = elem->_dl_.prev;\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\t\\\n\t    elem->_dl_.next->_dl_.prev = elem->_dl_.prev;\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    LT##_ElemInit(elem);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Free(struct ElemType *elem)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    LT##_Remove(elem);\t\t\t\t\t\t\t\t\\\n    Tcl_Free((void *)elem);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_RemoveHead(LT *head)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!LT##_IsEmpty(head));\t\t\t\t\t\t\\\n    LT##_Remove(head->first);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_RemoveTail(LT *head)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!LT##_IsEmpty(head));\t\t\t\t\t\t\\\n    LT##_Remove(head->last);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_FreeHead(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!LT##_IsEmpty(head));\t\t\t\t\t\t\\\n    LT##_Free(head->first);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_FreeTail(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(!LT##_IsEmpty(head));\t\t\t\t\t\t\\\n    LT##_Free(head->last);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_SwapElems(struct ElemType *lhs, struct ElemType *rhs)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    assert(lhs);\t\t\t\t\t\t\t\t\\\n    assert(rhs);\t\t\t\t\t\t\t\t\\\n    if (lhs != rhs) {\t\t\t\t\t\t\t\t\\\n\tstruct ElemType tmp;\t\t\t\t\t\t\t\\\n\tif (LT##_IsFirst(lhs))  {\t\t\t\t\t\t\\\n\t    ((LT *) lhs->_dl_.prev)->first = rhs;\t\t\t\t\\\n\t} else if (LT##_IsFirst(rhs)) {\t\t\t\t\t\t\\\n\t    ((LT *) rhs->_dl_.prev)->first = lhs;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\tif (LT##_IsLast(lhs))  {\t\t\t\t\t\t\\\n\t    ((LT *) lhs->_dl_.next)->last = rhs;\t\t\t\t\\\n\t} else if (LT##_IsLast(rhs)) {\t\t\t\t\t\t\\\n\t    ((LT *) rhs->_dl_.next)->last = lhs;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\\\n\ttmp._dl_ = lhs->_dl_;\t\t\t\t\t\t\t\\\n\tlhs->_dl_ = rhs->_dl_;\t\t\t\t\t\t\t\\\n\trhs->_dl_ = tmp._dl_;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Clear(LT *head)\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    struct ElemType *p;\t\t\t\t\t\t\t\t\\\n    struct ElemType *next;\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    for (p = head->first; p; p = next) {\t\t\t\t\t\\\n\tnext = LT##_Next(p);\t\t\t\t\t\t\t\\\n\tTcl_Free((void *)p);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n    LT##_Init(head);\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\\\n__TK_DLIST_UNUSED\t\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\t\\\nLT##_Traverse(LT *head, LT##_Func func)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\t\\\n    struct ElemType *next;\t\t\t\t\t\t\t\\\n    struct ElemType *p;\t\t\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    for (p = head->first; p; p = next) {\t\t\t\t\t\\\n\tnext = func(head, p);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\t\\\n/* ------------------------------------------------------------------------- */\n\n#define TK_DLIST_FOREACH(var, head)\t\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    for (var = head->first ? head->first : (PSEntry *) head; var != (PSEntry *) head; var = var->_dl_.next)\n\n#define TK_DLIST_FOREACH_REVERSE(var, head)\t\t\t\t\t\\\n    assert(head);\t\t\t\t\t\t\t\t\\\n    for (var = head->last ? head->last : (PSEntry *) head; var != (PSEntry *) head; var = var->_dl_.prev)\n\f\n#endif /* TK_DLIST_DEFINED */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 105\n * End:\n * vi:set ts=8 sw=4:\n */\n"
  },
  {
    "path": "generic/tkDecls.h",
    "content": "/*\n * tkDecls.h --\n *\n *\tDeclarations of functions in the platform independent public Tcl API.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKDECLS\n#define _TKDECLS\n\n#ifdef BUILD_tk\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n#endif\n\n#if !defined(BUILD_tk)\n# define TK_DEPRECATED(msg) EXTERN TCL_DEPRECATED_API(msg)\n#elif defined(TK_NO_DEPRECATED)\n# define TK_DEPRECATED(msg) MODULE_SCOPE\n#else\n# define TK_DEPRECATED(msg) EXTERN\n#endif\n\n/*\n * WARNING: This file is automatically generated by the tools/genStubs.tcl\n * script.  Any modifications to the function declarations below should be made\n * in the generic/tk.decls script.\n */\n\n/* !BEGIN!: Do not edit below this line. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n/* 0 */\nEXTERN void\t\tTk_MainLoop(void);\n/* 1 */\nEXTERN XColor *\t\tTk_3DBorderColor(Tk_3DBorder border);\n/* 2 */\nEXTERN GC\t\tTk_3DBorderGC(Tk_Window tkwin, Tk_3DBorder border,\n\t\t\t\tint which);\n/* 3 */\nEXTERN void\t\tTk_3DHorizontalBevel(Tk_Window tkwin,\n\t\t\t\tDrawable drawable, Tk_3DBorder border, int x,\n\t\t\t\tint y, int width, int height, int leftIn,\n\t\t\t\tint rightIn, int topBevel, int relief);\n/* 4 */\nEXTERN void\t\tTk_3DVerticalBevel(Tk_Window tkwin,\n\t\t\t\tDrawable drawable, Tk_3DBorder border, int x,\n\t\t\t\tint y, int width, int height, int leftBevel,\n\t\t\t\tint relief);\n/* 5 */\nEXTERN void\t\tTk_AddOption(Tk_Window tkwin, const char *name,\n\t\t\t\tconst char *value, int priority);\n/* 6 */\nEXTERN void\t\tTk_BindEvent(Tk_BindingTable bindingTable,\n\t\t\t\tXEvent *eventPtr, Tk_Window tkwin,\n\t\t\t\tTcl_Size numObjects, void **objectPtr);\n/* 7 */\nEXTERN void\t\tTk_CanvasDrawableCoords(Tk_Canvas canvas, double x,\n\t\t\t\tdouble y, short *drawableXPtr,\n\t\t\t\tshort *drawableYPtr);\n/* 8 */\nEXTERN void\t\tTk_CanvasEventuallyRedraw(Tk_Canvas canvas, int x1,\n\t\t\t\tint y1, int x2, int y2);\n/* 9 */\nEXTERN int\t\tTk_CanvasGetCoord(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, const char *str,\n\t\t\t\tdouble *doublePtr);\n/* 10 */\nEXTERN Tk_CanvasTextInfo * Tk_CanvasGetTextInfo(Tk_Canvas canvas);\n/* 11 */\nEXTERN int\t\tTk_CanvasPsBitmap(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, Pixmap bitmap, int x,\n\t\t\t\tint y, int width, int height);\n/* 12 */\nEXTERN int\t\tTk_CanvasPsColor(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, XColor *colorPtr);\n/* 13 */\nEXTERN int\t\tTk_CanvasPsFont(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t\tTk_Font font);\n/* 14 */\nEXTERN void\t\tTk_CanvasPsPath(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t\tdouble *coordPtr, Tcl_Size numPoints);\n/* 15 */\nEXTERN int\t\tTk_CanvasPsStipple(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, Pixmap bitmap);\n/* 16 */\nEXTERN double\t\tTk_CanvasPsY(Tk_Canvas canvas, double y);\n/* 17 */\nEXTERN void\t\tTk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc);\n/* 18 */\nEXTERN int\t\tTk_CanvasTagsParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 19 */\nEXTERN const char *\tTk_CanvasTagsPrintProc(void *clientData,\n\t\t\t\tTk_Window tkwin, char *widgRec,\n\t\t\t\tTcl_Size offset, Tcl_FreeProc **freeProcPtr);\n/* 20 */\nEXTERN Tk_Window\tTk_CanvasTkwin(Tk_Canvas canvas);\n/* 21 */\nEXTERN void\t\tTk_CanvasWindowCoords(Tk_Canvas canvas, double x,\n\t\t\t\tdouble y, short *screenXPtr,\n\t\t\t\tshort *screenYPtr);\n/* 22 */\nEXTERN void\t\tTk_ChangeWindowAttributes(Tk_Window tkwin,\n\t\t\t\tunsigned long valueMask,\n\t\t\t\tXSetWindowAttributes *attsPtr);\n/* 23 */\nEXTERN int\t\tTk_CharBbox(Tk_TextLayout layout, Tcl_Size index,\n\t\t\t\tint *xPtr, int *yPtr, int *widthPtr,\n\t\t\t\tint *heightPtr);\n/* 24 */\nEXTERN void\t\tTk_ClearSelection(Tk_Window tkwin, Atom selection);\n/* 25 */\nEXTERN int\t\tTk_ClipboardAppend(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Atom target, Atom format,\n\t\t\t\tconst char *buffer);\n/* 26 */\nEXTERN int\t\tTk_ClipboardClear(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin);\n/* 27 */\nEXTERN int\t\tTk_ConfigureInfo(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst Tk_ConfigSpec *specs, void *widgRec,\n\t\t\t\tconst char *argvName, int flags);\n/* 28 */\nEXTERN int\t\tTk_ConfigureValue(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const Tk_ConfigSpec *specs,\n\t\t\t\tvoid *widgRec, const char *argvName,\n\t\t\t\tint flags);\n/* 29 */\nEXTERN int\t\tTk_ConfigureWidget(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const Tk_ConfigSpec *specs,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv,\n\t\t\t\tvoid *widgRec, int flags);\n/* 30 */\nEXTERN void\t\tTk_ConfigureWindow(Tk_Window tkwin,\n\t\t\t\tunsigned int valueMask,\n\t\t\t\tXWindowChanges *valuePtr);\n/* 31 */\nEXTERN Tk_TextLayout\tTk_ComputeTextLayout(Tk_Font font, const char *str,\n\t\t\t\tTcl_Size numChars, int wrapLength,\n\t\t\t\tTk_Justify justify, int flags, int *widthPtr,\n\t\t\t\tint *heightPtr);\n/* 32 */\nEXTERN Tk_Window\tTk_CoordsToWindow(int rootX, int rootY,\n\t\t\t\tTk_Window tkwin);\n/* 33 */\nEXTERN unsigned long\tTk_CreateBinding(Tcl_Interp *interp,\n\t\t\t\tTk_BindingTable bindingTable, void *object,\n\t\t\t\tconst char *eventStr, const char *script,\n\t\t\t\tint append);\n/* 34 */\nEXTERN Tk_BindingTable\tTk_CreateBindingTable(Tcl_Interp *interp);\n/* 35 */\nEXTERN Tk_ErrorHandler\tTk_CreateErrorHandler(Display *display, int errNum,\n\t\t\t\tint request, int minorCode,\n\t\t\t\tTk_ErrorProc *errorProc, void *clientData);\n/* 36 */\nEXTERN void\t\tTk_CreateEventHandler(Tk_Window token,\n\t\t\t\tunsigned long mask, Tk_EventProc *proc,\n\t\t\t\tvoid *clientData);\n/* 37 */\nEXTERN void\t\tTk_CreateGenericHandler(Tk_GenericProc *proc,\n\t\t\t\tvoid *clientData);\n/* 38 */\nEXTERN void\t\tTk_CreateImageType(const Tk_ImageType *typePtr);\n/* 39 */\nEXTERN void\t\tTk_CreateItemType(Tk_ItemType *typePtr);\n/* 40 */\nEXTERN void\t\tTk_CreatePhotoImageFormat(\n\t\t\t\tconst Tk_PhotoImageFormat *formatPtr);\n/* 41 */\nEXTERN void\t\tTk_CreateSelHandler(Tk_Window tkwin, Atom selection,\n\t\t\t\tAtom target, Tk_SelectionProc *proc,\n\t\t\t\tvoid *clientData, Atom format);\n/* 42 */\nEXTERN Tk_Window\tTk_CreateWindow(Tcl_Interp *interp, Tk_Window parent,\n\t\t\t\tconst char *name, const char *screenName);\n/* 43 */\nEXTERN Tk_Window\tTk_CreateWindowFromPath(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const char *pathName,\n\t\t\t\tconst char *screenName);\n/* 44 */\nEXTERN int\t\tTk_DefineBitmap(Tcl_Interp *interp, const char *name,\n\t\t\t\tconst void *source, int width, int height);\n/* 45 */\nEXTERN void\t\tTk_DefineCursor(Tk_Window window, Tk_Cursor cursor);\n/* 46 */\nEXTERN void\t\tTk_DeleteAllBindings(Tk_BindingTable bindingTable,\n\t\t\t\tvoid *object);\n/* 47 */\nEXTERN int\t\tTk_DeleteBinding(Tcl_Interp *interp,\n\t\t\t\tTk_BindingTable bindingTable, void *object,\n\t\t\t\tconst char *eventStr);\n/* 48 */\nEXTERN void\t\tTk_DeleteBindingTable(Tk_BindingTable bindingTable);\n/* 49 */\nEXTERN void\t\tTk_DeleteErrorHandler(Tk_ErrorHandler handler);\n/* 50 */\nEXTERN void\t\tTk_DeleteEventHandler(Tk_Window token,\n\t\t\t\tunsigned long mask, Tk_EventProc *proc,\n\t\t\t\tvoid *clientData);\n/* 51 */\nEXTERN void\t\tTk_DeleteGenericHandler(Tk_GenericProc *proc,\n\t\t\t\tvoid *clientData);\n/* 52 */\nEXTERN void\t\tTk_DeleteImage(Tcl_Interp *interp, const char *name);\n/* 53 */\nEXTERN void\t\tTk_DeleteSelHandler(Tk_Window tkwin, Atom selection,\n\t\t\t\tAtom target);\n/* 54 */\nEXTERN void\t\tTk_DestroyWindow(Tk_Window tkwin);\n/* 55 */\nEXTERN const char *\tTk_DisplayName(Tk_Window tkwin);\n/* 56 */\nEXTERN int\t\tTk_DistanceToTextLayout(Tk_TextLayout layout, int x,\n\t\t\t\tint y);\n/* 57 */\nEXTERN void\t\tTk_Draw3DPolygon(Tk_Window tkwin, Drawable drawable,\n\t\t\t\tTk_3DBorder border, XPoint *pointPtr,\n\t\t\t\tTcl_Size numPoints, int borderWidth,\n\t\t\t\tint leftRelief);\n/* 58 */\nEXTERN void\t\tTk_Draw3DRectangle(Tk_Window tkwin,\n\t\t\t\tDrawable drawable, Tk_3DBorder border, int x,\n\t\t\t\tint y, int width, int height,\n\t\t\t\tint borderWidth, int relief);\n/* 59 */\nEXTERN void\t\tTk_DrawChars(Display *display, Drawable drawable,\n\t\t\t\tGC gc, Tk_Font tkfont, const char *source,\n\t\t\t\tTcl_Size numBytes, int x, int y);\n/* 60 */\nEXTERN void\t\tTk_DrawFocusHighlight(Tk_Window tkwin, GC gc,\n\t\t\t\tint width, Drawable drawable);\n/* 61 */\nEXTERN void\t\tTk_DrawTextLayout(Display *display,\n\t\t\t\tDrawable drawable, GC gc,\n\t\t\t\tTk_TextLayout layout, int x, int y,\n\t\t\t\tTcl_Size firstChar, Tcl_Size lastChar);\n/* 62 */\nEXTERN void\t\tTk_Fill3DPolygon(Tk_Window tkwin, Drawable drawable,\n\t\t\t\tTk_3DBorder border, XPoint *pointPtr,\n\t\t\t\tTcl_Size numPoints, int borderWidth,\n\t\t\t\tint leftRelief);\n/* 63 */\nEXTERN void\t\tTk_Fill3DRectangle(Tk_Window tkwin,\n\t\t\t\tDrawable drawable, Tk_3DBorder border, int x,\n\t\t\t\tint y, int width, int height,\n\t\t\t\tint borderWidth, int relief);\n/* 64 */\nEXTERN Tk_PhotoHandle\tTk_FindPhoto(Tcl_Interp *interp,\n\t\t\t\tconst char *imageName);\n/* 65 */\nEXTERN Font\t\tTk_FontId(Tk_Font font);\n/* 66 */\nEXTERN void\t\tTk_Free3DBorder(Tk_3DBorder border);\n/* 67 */\nEXTERN void\t\tTk_FreeBitmap(Display *display, Pixmap bitmap);\n/* 68 */\nEXTERN void\t\tTk_FreeColor(XColor *colorPtr);\n/* 69 */\nEXTERN void\t\tTk_FreeColormap(Display *display, Colormap colormap);\n/* 70 */\nEXTERN void\t\tTk_FreeCursor(Display *display, Tk_Cursor cursor);\n/* 71 */\nEXTERN void\t\tTk_FreeFont(Tk_Font f);\n/* 72 */\nEXTERN void\t\tTk_FreeGC(Display *display, GC gc);\n/* 73 */\nEXTERN void\t\tTk_FreeImage(Tk_Image image);\n/* 74 */\nEXTERN void\t\tTk_FreeOptions(const Tk_ConfigSpec *specs,\n\t\t\t\tvoid *widgRec, Display *display,\n\t\t\t\tint needFlags);\n/* 75 */\nEXTERN void\t\tTk_FreePixmap(Display *display, Pixmap pixmap);\n/* 76 */\nEXTERN void\t\tTk_FreeTextLayout(Tk_TextLayout textLayout);\n/* Slot 77 is reserved */\n/* 78 */\nEXTERN GC\t\tTk_GCForColor(XColor *colorPtr, Drawable drawable);\n/* 79 */\nEXTERN void\t\tTk_GeometryRequest(Tk_Window tkwin, int reqWidth,\n\t\t\t\tint reqHeight);\n/* 80 */\nEXTERN Tk_3DBorder\tTk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *colorName);\n/* 81 */\nEXTERN void\t\tTk_GetAllBindings(Tcl_Interp *interp,\n\t\t\t\tTk_BindingTable bindingTable, void *object);\n/* 82 */\nEXTERN int\t\tTk_GetAnchor(Tcl_Interp *interp, const char *str,\n\t\t\t\tTk_Anchor *anchorPtr);\n/* 83 */\nEXTERN const char *\tTk_GetAtomName(Tk_Window tkwin, Atom atom);\n/* 84 */\nEXTERN const char *\tTk_GetBinding(Tcl_Interp *interp,\n\t\t\t\tTk_BindingTable bindingTable, void *object,\n\t\t\t\tconst char *eventStr);\n/* 85 */\nEXTERN Pixmap\t\tTk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str);\n/* 86 */\nEXTERN Pixmap\t\tTk_GetBitmapFromData(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const void *source,\n\t\t\t\tint width, int height);\n/* 87 */\nEXTERN int\t\tTk_GetCapStyle(Tcl_Interp *interp, const char *str,\n\t\t\t\tint *capPtr);\n/* 88 */\nEXTERN XColor *\t\tTk_GetColor(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *name);\n/* 89 */\nEXTERN XColor *\t\tTk_GetColorByValue(Tk_Window tkwin, XColor *colorPtr);\n/* 90 */\nEXTERN Colormap\t\tTk_GetColormap(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str);\n/* 91 */\nEXTERN Tk_Cursor\tTk_GetCursor(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str);\n/* 92 */\nEXTERN Tk_Cursor\tTk_GetCursorFromData(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const char *source,\n\t\t\t\tconst char *mask, int width, int height,\n\t\t\t\tint xHot, int yHot, const char *fg,\n\t\t\t\tconst char *bg);\n/* 93 */\nEXTERN Tk_Font\t\tTk_GetFont(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str);\n/* 94 */\nEXTERN Tk_Font\t\tTk_GetFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 95 */\nEXTERN void\t\tTk_GetFontMetrics(Tk_Font font,\n\t\t\t\tTk_FontMetrics *fmPtr);\n/* 96 */\nEXTERN GC\t\tTk_GetGC(Tk_Window tkwin, unsigned long valueMask,\n\t\t\t\tXGCValues *valuePtr);\n/* 97 */\nEXTERN Tk_Image\t\tTk_GetImage(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *name,\n\t\t\t\tTk_ImageChangedProc *changeProc,\n\t\t\t\tvoid *clientData);\n/* 98 */\nEXTERN void *\t\tTk_GetImageModelData(Tcl_Interp *interp,\n\t\t\t\tconst char *name,\n\t\t\t\tconst Tk_ImageType **typePtrPtr);\n/* 99 */\nEXTERN Tk_ItemType *\tTk_GetItemTypes(void);\n/* 100 */\nEXTERN int\t\tTk_GetJoinStyle(Tcl_Interp *interp, const char *str,\n\t\t\t\tint *joinPtr);\n/* 101 */\nEXTERN int\t\tTk_GetJustify(Tcl_Interp *interp, const char *str,\n\t\t\t\tTk_Justify *justifyPtr);\n/* 102 */\nEXTERN int\t\tTk_GetNumMainWindows(void);\n/* 103 */\nEXTERN Tk_Uid\t\tTk_GetOption(Tk_Window tkwin, const char *name,\n\t\t\t\tconst char *className);\n/* 104 */\nEXTERN int\t\tTk_GetPixels(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str, int *intPtr);\n/* 105 */\nEXTERN Pixmap\t\tTk_GetPixmap(Display *display, Drawable d, int width,\n\t\t\t\tint height, int depth);\n/* 106 */\nEXTERN int\t\tTk_GetRelief(Tcl_Interp *interp, const char *name,\n\t\t\t\tint *reliefPtr);\n/* 107 */\nEXTERN void\t\tTk_GetRootCoords(Tk_Window tkwin, int *xPtr,\n\t\t\t\tint *yPtr);\n/* 108 */\nEXTERN int\t\tTk_GetScrollInfo(Tcl_Interp *interp, Tcl_Size argc,\n\t\t\t\tconst char **argv, double *dblPtr,\n\t\t\t\tint *intPtr);\n/* 109 */\nEXTERN int\t\tTk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str, double *doublePtr);\n/* 110 */\nEXTERN int\t\tTk_GetSelection(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tAtom selection, Atom target,\n\t\t\t\tTk_GetSelProc *proc, void *clientData);\n/* 111 */\nEXTERN Tk_Uid\t\tTk_GetUid(const char *str);\n/* 112 */\nEXTERN Visual *\t\tTk_GetVisual(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *str, int *depthPtr,\n\t\t\t\tColormap *colormapPtr);\n/* 113 */\nEXTERN void\t\tTk_GetVRootGeometry(Tk_Window tkwin, int *xPtr,\n\t\t\t\tint *yPtr, int *widthPtr, int *heightPtr);\n/* 114 */\nEXTERN int\t\tTk_Grab(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tint grabGlobal);\n/* 115 */\nEXTERN void\t\tTk_HandleEvent(XEvent *eventPtr);\n/* 116 */\nEXTERN Tk_Window\tTk_IdToWindow(Display *display, Window window);\n/* 117 */\nEXTERN void\t\tTk_ImageChanged(Tk_ImageModel model, int x, int y,\n\t\t\t\tint width, int height, int imageWidth,\n\t\t\t\tint imageHeight);\n/* Slot 118 is reserved */\n/* 119 */\nEXTERN Atom\t\tTk_InternAtom(Tk_Window tkwin, const char *name);\n/* 120 */\nEXTERN int\t\tTk_IntersectTextLayout(Tk_TextLayout layout, int x,\n\t\t\t\tint y, int width, int height);\n/* 121 */\nEXTERN void\t\tTk_MaintainGeometry(Tk_Window window,\n\t\t\t\tTk_Window container, int x, int y, int width,\n\t\t\t\tint height);\n/* 122 */\nEXTERN Tk_Window\tTk_MainWindow(Tcl_Interp *interp);\n/* 123 */\nEXTERN void\t\tTk_MakeWindowExist(Tk_Window tkwin);\n/* 124 */\nEXTERN void\t\tTk_ManageGeometry(Tk_Window tkwin,\n\t\t\t\tconst Tk_GeomMgr *mgrPtr, void *clientData);\n/* 125 */\nEXTERN void\t\tTk_MapWindow(Tk_Window tkwin);\n/* 126 */\nEXTERN int\t\tTk_MeasureChars(Tk_Font tkfont, const char *source,\n\t\t\t\tTcl_Size numBytes, int maxPixels, int flags,\n\t\t\t\tint *lengthPtr);\n/* 127 */\nEXTERN void\t\tTk_MoveResizeWindow(Tk_Window tkwin, int x, int y,\n\t\t\t\tint width, int height);\n/* 128 */\nEXTERN void\t\tTk_MoveWindow(Tk_Window tkwin, int x, int y);\n/* 129 */\nEXTERN void\t\tTk_MoveToplevelWindow(Tk_Window tkwin, int x, int y);\n/* 130 */\nEXTERN const char *\tTk_NameOf3DBorder(Tk_3DBorder border);\n/* 131 */\nEXTERN const char *\tTk_NameOfAnchor(Tk_Anchor anchor);\n/* 132 */\nEXTERN const char *\tTk_NameOfBitmap(Display *display, Pixmap bitmap);\n/* 133 */\nEXTERN const char *\tTk_NameOfCapStyle(int cap);\n/* 134 */\nEXTERN const char *\tTk_NameOfColor(XColor *colorPtr);\n/* 135 */\nEXTERN const char *\tTk_NameOfCursor(Display *display, Tk_Cursor cursor);\n/* 136 */\nEXTERN const char *\tTk_NameOfFont(Tk_Font font);\n/* 137 */\nEXTERN const char *\tTk_NameOfImage(Tk_ImageModel model);\n/* 138 */\nEXTERN const char *\tTk_NameOfJoinStyle(int join);\n/* 139 */\nEXTERN const char *\tTk_NameOfJustify(Tk_Justify justify);\n/* 140 */\nEXTERN const char *\tTk_NameOfRelief(int relief);\n/* 141 */\nEXTERN Tk_Window\tTk_NameToWindow(Tcl_Interp *interp,\n\t\t\t\tconst char *pathName, Tk_Window tkwin);\n/* 142 */\nEXTERN void\t\tTk_OwnSelection(Tk_Window tkwin, Atom selection,\n\t\t\t\tTk_LostSelProc *proc, void *clientData);\n/* 143 */\nEXTERN int\t\tTk_ParseArgv(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tint *argcPtr, const char **argv,\n\t\t\t\tconst Tk_ArgvInfo *argTable, int flags);\n/* Slot 144 is reserved */\n/* Slot 145 is reserved */\n/* 146 */\nEXTERN int\t\tTk_PhotoGetImage(Tk_PhotoHandle handle,\n\t\t\t\tTk_PhotoImageBlock *blockPtr);\n/* 147 */\nEXTERN void\t\tTk_PhotoBlank(Tk_PhotoHandle handle);\n/* Slot 148 is reserved */\n/* 149 */\nEXTERN void\t\tTk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr,\n\t\t\t\tint *heightPtr);\n/* 150 */\nEXTERN Tcl_Size\t\tTk_PointToChar(Tk_TextLayout layout, int x, int y);\n/* 151 */\nEXTERN int\t\tTkPointToChar_(Tk_TextLayout layout, int x, int y);\n/* 152 */\nEXTERN int\t\tTk_PostscriptFontName(Tk_Font tkfont,\n\t\t\t\tTcl_DString *dsPtr);\n/* 153 */\nEXTERN void\t\tTk_PreserveColormap(Display *display,\n\t\t\t\tColormap colormap);\n/* 154 */\nEXTERN void\t\tTk_QueueWindowEvent(XEvent *eventPtr,\n\t\t\t\tTcl_QueuePosition position);\n/* 155 */\nEXTERN void\t\tTk_RedrawImage(Tk_Image image, int imageX,\n\t\t\t\tint imageY, int width, int height,\n\t\t\t\tDrawable drawable, int drawableX,\n\t\t\t\tint drawableY);\n/* 156 */\nEXTERN void\t\tTk_ResizeWindow(Tk_Window tkwin, int width,\n\t\t\t\tint height);\n/* 157 */\nEXTERN int\t\tTk_RestackWindow(Tk_Window tkwin, int aboveBelow,\n\t\t\t\tTk_Window other);\n/* 158 */\nEXTERN Tk_RestrictProc * Tk_RestrictEvents(Tk_RestrictProc *proc, void *arg,\n\t\t\t\tvoid **prevArgPtr);\n/* Slot 159 is reserved */\n/* 160 */\nEXTERN const char *\tTk_SetAppName(Tk_Window tkwin, const char *name);\n/* 161 */\nEXTERN void\t\tTk_SetBackgroundFromBorder(Tk_Window tkwin,\n\t\t\t\tTk_3DBorder border);\n/* 162 */\nEXTERN void\t\tTk_SetClass(Tk_Window tkwin, const char *className);\n/* 163 */\nEXTERN void\t\tTk_SetGrid(Tk_Window tkwin, int reqWidth,\n\t\t\t\tint reqHeight, int gridWidth, int gridHeight);\n/* 164 */\nEXTERN void\t\tTk_SetInternalBorder(Tk_Window tkwin, int width);\n/* 165 */\nEXTERN void\t\tTk_SetWindowBackground(Tk_Window tkwin,\n\t\t\t\tunsigned long pixel);\n/* 166 */\nEXTERN void\t\tTk_SetWindowBackgroundPixmap(Tk_Window tkwin,\n\t\t\t\tPixmap pixmap);\n/* 167 */\nEXTERN void\t\tTk_SetWindowBorder(Tk_Window tkwin,\n\t\t\t\tunsigned long pixel);\n/* 168 */\nEXTERN void\t\tTk_SetWindowBorderWidth(Tk_Window tkwin, int width);\n/* 169 */\nEXTERN void\t\tTk_SetWindowBorderPixmap(Tk_Window tkwin,\n\t\t\t\tPixmap pixmap);\n/* 170 */\nEXTERN void\t\tTk_SetWindowColormap(Tk_Window tkwin,\n\t\t\t\tColormap colormap);\n/* 171 */\nEXTERN int\t\tTk_SetWindowVisual(Tk_Window tkwin, Visual *visual,\n\t\t\t\tint depth, Colormap colormap);\n/* 172 */\nEXTERN void\t\tTk_SizeOfBitmap(Display *display, Pixmap bitmap,\n\t\t\t\tint *widthPtr, int *heightPtr);\n/* 173 */\nEXTERN void\t\tTk_SizeOfImage(Tk_Image image, int *widthPtr,\n\t\t\t\tint *heightPtr);\n/* 174 */\nEXTERN int\t\tTk_StrictMotif(Tk_Window tkwin);\n/* 175 */\nEXTERN void\t\tTk_TextLayoutToPostscript(Tcl_Interp *interp,\n\t\t\t\tTk_TextLayout layout);\n/* 176 */\nEXTERN int\t\tTk_TextWidth(Tk_Font font, const char *str,\n\t\t\t\tTcl_Size numBytes);\n/* 177 */\nEXTERN void\t\tTk_UndefineCursor(Tk_Window window);\n/* 178 */\nEXTERN void\t\tTk_UnderlineChars(Display *display,\n\t\t\t\tDrawable drawable, GC gc, Tk_Font tkfont,\n\t\t\t\tconst char *source, int x, int y,\n\t\t\t\tTcl_Size firstByte, Tcl_Size lastByte);\n/* 179 */\nEXTERN void\t\tTk_UnderlineTextLayout(Display *display,\n\t\t\t\tDrawable drawable, GC gc,\n\t\t\t\tTk_TextLayout layout, int x, int y,\n\t\t\t\tint underline);\n/* 180 */\nEXTERN void\t\tTk_Ungrab(Tk_Window tkwin);\n/* 181 */\nEXTERN void\t\tTk_UnmaintainGeometry(Tk_Window window,\n\t\t\t\tTk_Window container);\n/* 182 */\nEXTERN void\t\tTk_UnmapWindow(Tk_Window tkwin);\n/* 183 */\nEXTERN void\t\tTk_UnsetGrid(Tk_Window tkwin);\n/* 184 */\nEXTERN void\t\tTk_UpdatePointer(Tk_Window tkwin, int x, int y,\n\t\t\t\tint state);\n/* 185 */\nEXTERN Pixmap\t\tTk_AllocBitmapFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr);\n/* 186 */\nEXTERN Tk_3DBorder\tTk_Alloc3DBorderFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr);\n/* 187 */\nEXTERN XColor *\t\tTk_AllocColorFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr);\n/* 188 */\nEXTERN Tk_Cursor\tTk_AllocCursorFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr);\n/* 189 */\nEXTERN Tk_Font\t\tTk_AllocFontFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr);\n/* 190 */\nEXTERN Tk_OptionTable\tTk_CreateOptionTable(Tcl_Interp *interp,\n\t\t\t\tconst Tk_OptionSpec *templatePtr);\n/* 191 */\nEXTERN void\t\tTk_DeleteOptionTable(Tk_OptionTable optionTable);\n/* 192 */\nEXTERN void\t\tTk_Free3DBorderFromObj(Tk_Window tkwin,\n\t\t\t\tTcl_Obj *objPtr);\n/* 193 */\nEXTERN void\t\tTk_FreeBitmapFromObj(Tk_Window tkwin,\n\t\t\t\tTcl_Obj *objPtr);\n/* 194 */\nEXTERN void\t\tTk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 195 */\nEXTERN void\t\tTk_FreeConfigOptions(void *recordPtr,\n\t\t\t\tTk_OptionTable optionToken, Tk_Window tkwin);\n/* 196 */\nEXTERN void\t\tTk_FreeSavedOptions(Tk_SavedOptions *savePtr);\n/* 197 */\nEXTERN void\t\tTk_FreeCursorFromObj(Tk_Window tkwin,\n\t\t\t\tTcl_Obj *objPtr);\n/* 198 */\nEXTERN void\t\tTk_FreeFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 199 */\nEXTERN Tk_3DBorder\tTk_Get3DBorderFromObj(Tk_Window tkwin,\n\t\t\t\tTcl_Obj *objPtr);\n/* 200 */\nEXTERN int\t\tTk_GetAnchorFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Tk_Anchor *anchorPtr);\n/* 201 */\nEXTERN Pixmap\t\tTk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 202 */\nEXTERN XColor *\t\tTk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 203 */\nEXTERN Tk_Cursor\tTk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);\n/* 204 */\nEXTERN Tcl_Obj *\tTk_GetOptionInfo(Tcl_Interp *interp, void *recordPtr,\n\t\t\t\tTk_OptionTable optionTable, Tcl_Obj *namePtr,\n\t\t\t\tTk_Window tkwin);\n/* 205 */\nEXTERN Tcl_Obj *\tTk_GetOptionValue(Tcl_Interp *interp,\n\t\t\t\tvoid *recordPtr, Tk_OptionTable optionTable,\n\t\t\t\tTcl_Obj *namePtr, Tk_Window tkwin);\n/* 206 */\nEXTERN int\t\tTk_GetJustifyFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Tk_Justify *justifyPtr);\n/* 207 */\nEXTERN int\t\tTk_GetMMFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tTcl_Obj *objPtr, double *doublePtr);\n/* 208 */\nEXTERN int\t\tTk_GetPixelsFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr,\n\t\t\t\tint *intPtr);\n/* 209 */\nEXTERN int\t\tTk_GetReliefFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, int *resultPtr);\n/* 210 */\nEXTERN int\t\tTk_GetScrollInfoObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv,\n\t\t\t\tdouble *dblPtr, int *intPtr);\n/* 211 */\nEXTERN int\t\tTk_InitOptions(Tcl_Interp *interp, void *recordPtr,\n\t\t\t\tTk_OptionTable optionToken, Tk_Window tkwin);\n/* Slot 212 is reserved */\n/* 213 */\nEXTERN void\t\tTk_RestoreSavedOptions(Tk_SavedOptions *savePtr);\n/* 214 */\nEXTERN int\t\tTk_SetOptions(Tcl_Interp *interp, void *recordPtr,\n\t\t\t\tTk_OptionTable optionTable, Tcl_Size objc,\n\t\t\t\tTcl_Obj *const *objv, Tk_Window tkwin,\n\t\t\t\tTk_SavedOptions *savePtr, int *maskPtr);\n/* 215 */\nEXTERN void\t\tTk_InitConsoleChannels(Tcl_Interp *interp);\n/* Slot 216 is reserved */\n/* 217 */\nEXTERN void\t\tTk_CreateSmoothMethod(Tcl_Interp *interp,\n\t\t\t\tconst Tk_SmoothMethod *method);\n/* Slot 218 is reserved */\n/* Slot 219 is reserved */\n/* 220 */\nEXTERN int\t\tTk_GetDash(Tcl_Interp *interp, const char *value,\n\t\t\t\tTk_Dash *dash);\n/* 221 */\nEXTERN void\t\tTk_CreateOutline(Tk_Outline *outline);\n/* 222 */\nEXTERN void\t\tTk_DeleteOutline(Display *display,\n\t\t\t\tTk_Outline *outline);\n/* 223 */\nEXTERN int\t\tTk_ConfigOutlineGC(XGCValues *gcValues,\n\t\t\t\tTk_Canvas canvas, Tk_Item *item,\n\t\t\t\tTk_Outline *outline);\n/* 224 */\nEXTERN int\t\tTk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item,\n\t\t\t\tTk_Outline *outline);\n/* 225 */\nEXTERN int\t\tTk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item,\n\t\t\t\tTk_Outline *outline);\n/* 226 */\nEXTERN int\t\tTk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item,\n\t\t\t\tTk_Outline *outline);\n/* 227 */\nEXTERN void\t\tTk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y);\n/* 228 */\nEXTERN int\t\tTk_CanvasGetCoordFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, Tcl_Obj *obj,\n\t\t\t\tdouble *doublePtr);\n/* 229 */\nEXTERN void\t\tTk_CanvasSetOffset(Tk_Canvas canvas, GC gc,\n\t\t\t\tTk_TSOffset *offset);\n/* 230 */\nEXTERN void\t\tTk_DitherPhoto(Tk_PhotoHandle handle, int x, int y,\n\t\t\t\tint width, int height);\n/* 231 */\nEXTERN int\t\tTk_PostscriptBitmap(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tk_PostscriptInfo psInfo,\n\t\t\t\tPixmap bitmap, int startX, int startY,\n\t\t\t\tint width, int height);\n/* 232 */\nEXTERN int\t\tTk_PostscriptColor(Tcl_Interp *interp,\n\t\t\t\tTk_PostscriptInfo psInfo, XColor *colorPtr);\n/* 233 */\nEXTERN int\t\tTk_PostscriptFont(Tcl_Interp *interp,\n\t\t\t\tTk_PostscriptInfo psInfo, Tk_Font font);\n/* 234 */\nEXTERN int\t\tTk_PostscriptImage(Tk_Image image,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tTk_PostscriptInfo psinfo, int x, int y,\n\t\t\t\tint width, int height, int prepass);\n/* 235 */\nEXTERN void\t\tTk_PostscriptPath(Tcl_Interp *interp,\n\t\t\t\tTk_PostscriptInfo psInfo, double *coordPtr,\n\t\t\t\tTcl_Size numPoints);\n/* 236 */\nEXTERN int\t\tTk_PostscriptStipple(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tk_PostscriptInfo psInfo,\n\t\t\t\tPixmap bitmap);\n/* 237 */\nEXTERN double\t\tTk_PostscriptY(double y, Tk_PostscriptInfo psInfo);\n/* 238 */\nEXTERN int\t\tTk_PostscriptPhoto(Tcl_Interp *interp,\n\t\t\t\tTk_PhotoImageBlock *blockPtr,\n\t\t\t\tTk_PostscriptInfo psInfo, int width,\n\t\t\t\tint height);\n/* 239 */\nEXTERN void\t\tTk_CreateClientMessageHandler(\n\t\t\t\tTk_ClientMessageProc *proc);\n/* 240 */\nEXTERN void\t\tTk_DeleteClientMessageHandler(\n\t\t\t\tTk_ClientMessageProc *proc);\n/* 241 */\nEXTERN Tk_Window\tTk_CreateAnonymousWindow(Tcl_Interp *interp,\n\t\t\t\tTk_Window parent, const char *screenName);\n/* 242 */\nEXTERN void\t\tTk_SetClassProcs(Tk_Window tkwin,\n\t\t\t\tconst Tk_ClassProcs *procs,\n\t\t\t\tvoid *instanceData);\n/* 243 */\nEXTERN void\t\tTk_SetInternalBorderEx(Tk_Window tkwin, int left,\n\t\t\t\tint right, int top, int bottom);\n/* 244 */\nEXTERN void\t\tTk_SetMinimumRequestSize(Tk_Window tkwin,\n\t\t\t\tint minWidth, int minHeight);\n/* 245 */\nEXTERN void\t\tTk_SetCaretPos(Tk_Window tkwin, int x, int y,\n\t\t\t\tint height);\n/* Slot 246 is reserved */\n/* Slot 247 is reserved */\n/* 248 */\nEXTERN int\t\tTk_CollapseMotionEvents(Display *display,\n\t\t\t\tint collapse);\n/* 249 */\nEXTERN Tk_StyleEngine\tTk_RegisterStyleEngine(const char *name,\n\t\t\t\tTk_StyleEngine parent);\n/* 250 */\nEXTERN Tk_StyleEngine\tTk_GetStyleEngine(const char *name);\n/* 251 */\nEXTERN int\t\tTk_RegisterStyledElement(Tk_StyleEngine engine,\n\t\t\t\tTk_ElementSpec *templatePtr);\n/* 252 */\nEXTERN int\t\tTk_GetElementId(const char *name);\n/* 253 */\nEXTERN Tk_Style\t\tTk_CreateStyle(const char *name,\n\t\t\t\tTk_StyleEngine engine, void *clientData);\n/* 254 */\nEXTERN Tk_Style\t\tTk_GetStyle(Tcl_Interp *interp, const char *name);\n/* 255 */\nEXTERN void\t\tTk_FreeStyle(Tk_Style style);\n/* 256 */\nEXTERN const char *\tTk_NameOfStyle(Tk_Style style);\n/* 257 */\nEXTERN Tk_Style\t\tTk_AllocStyleFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr);\n/* Slot 258 is reserved */\n/* Slot 259 is reserved */\n/* 260 */\nEXTERN Tk_StyledElement\t Tk_GetStyledElement(Tk_Style style,\n\t\t\t\tTcl_Size elementId,\n\t\t\t\tTk_OptionTable optionTable);\n/* 261 */\nEXTERN void\t\tTk_GetElementSize(Tk_Style style,\n\t\t\t\tTk_StyledElement element, void *recordPtr,\n\t\t\t\tTk_Window tkwin, int width, int height,\n\t\t\t\tint inner, int *widthPtr, int *heightPtr);\n/* 262 */\nEXTERN void\t\tTk_GetElementBox(Tk_Style style,\n\t\t\t\tTk_StyledElement element, void *recordPtr,\n\t\t\t\tTk_Window tkwin, int x, int y, int width,\n\t\t\t\tint height, int inner, int *xPtr, int *yPtr,\n\t\t\t\tint *widthPtr, int *heightPtr);\n/* 263 */\nEXTERN int\t\tTk_GetElementBorderWidth(Tk_Style style,\n\t\t\t\tTk_StyledElement element, void *recordPtr,\n\t\t\t\tTk_Window tkwin);\n/* 264 */\nEXTERN void\t\tTk_DrawElement(Tk_Style style,\n\t\t\t\tTk_StyledElement element, void *recordPtr,\n\t\t\t\tTk_Window tkwin, Drawable d, int x, int y,\n\t\t\t\tint width, int height, int state);\n/* 265 */\nEXTERN int\t\tTk_PhotoExpand(Tcl_Interp *interp,\n\t\t\t\tTk_PhotoHandle handle, int width, int height);\n/* 266 */\nEXTERN int\t\tTk_PhotoPutBlock(Tcl_Interp *interp,\n\t\t\t\tTk_PhotoHandle handle,\n\t\t\t\tTk_PhotoImageBlock *blockPtr, int x, int y,\n\t\t\t\tint width, int height, int compRule);\n/* 267 */\nEXTERN int\t\tTk_PhotoPutZoomedBlock(Tcl_Interp *interp,\n\t\t\t\tTk_PhotoHandle handle,\n\t\t\t\tTk_PhotoImageBlock *blockPtr, int x, int y,\n\t\t\t\tint width, int height, int zoomX, int zoomY,\n\t\t\t\tint subsampleX, int subsampleY, int compRule);\n/* 268 */\nEXTERN int\t\tTk_PhotoSetSize(Tcl_Interp *interp,\n\t\t\t\tTk_PhotoHandle handle, int width, int height);\n/* 269 */\nEXTERN long\t\tTk_GetUserInactiveTime(Display *dpy);\n/* 270 */\nEXTERN void\t\tTk_ResetUserInactiveTime(Display *dpy);\n/* 271 */\nEXTERN Tcl_Interp *\tTk_Interp(Tk_Window tkwin);\n/* Slot 272 is reserved */\n/* Slot 273 is reserved */\n/* 274 */\nEXTERN int\t\tTk_AlwaysShowSelection(Tk_Window tkwin);\n/* 275 */\nEXTERN unsigned\t\tTk_GetButtonMask(unsigned button);\n/* 276 */\nEXTERN int\t\tTk_GetDoublePixelsFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr,\n\t\t\t\tdouble *doublePtr);\n/* 277 */\nEXTERN Tcl_Obj *\tTk_NewWindowObj(Tk_Window tkwin);\n/* 278 */\nEXTERN void\t\tTk_SendVirtualEvent(Tk_Window tkwin,\n\t\t\t\tconst char *eventName, Tcl_Obj *detail);\n/* 279 */\nEXTERN Tcl_Obj *\tTk_FontGetDescription(Tk_Font tkfont);\n/* 280 */\nEXTERN void\t\tTk_CreatePhotoImageFormatVersion3(\n\t\t\t\tconst Tk_PhotoImageFormatVersion3 *formatPtr);\n/* 281 */\nEXTERN void\t\tTk_DrawHighlightBorder(Tk_Window tkwin, GC fgGC,\n\t\t\t\tGC bgGC, int highlightWidth,\n\t\t\t\tDrawable drawable);\n/* 282 */\nEXTERN void\t\tTk_SetMainMenubar(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const char *menuName);\n/* 283 */\nEXTERN void\t\tTk_SetWindowMenubar(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const char *oldMenuName,\n\t\t\t\tconst char *menuName);\n/* 284 */\nEXTERN void\t\tTk_ClipDrawableToRect(Display *display, Drawable d,\n\t\t\t\tint x, int y, int width, int height);\n/* 285 */\nEXTERN Tcl_Obj *\tTk_GetSystemDefault(Tk_Window tkwin,\n\t\t\t\tconst char *dbName, const char *className);\n/* 286 */\nEXTERN int\t\tTk_UseWindow(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *string);\n/* 287 */\nEXTERN void\t\tTk_MakeContainer(Tk_Window tkwin);\n/* 288 */\nEXTERN Tk_Window\tTk_GetOtherWindow(Tk_Window tkwin);\n/* 289 */\nEXTERN void\t\tTk_Get3DBorderColors(Tk_3DBorder border,\n\t\t\t\tXColor *bgColorPtr, XColor *darkColorPtr,\n\t\t\t\tXColor *lightColorPtr);\n/* 290 */\nEXTERN Window\t\tTk_MakeWindow(Tk_Window tkwin, Window parent);\n/* 291 */\nEXTERN void\t\tTk_UnderlineCharsInContext(Display *display,\n\t\t\t\tDrawable drawable, GC gc, Tk_Font tkfont,\n\t\t\t\tconst char *string, Tcl_Size numBytes, int x,\n\t\t\t\tint y, Tcl_Size firstByte, Tcl_Size lastByte);\n/* 292 */\nEXTERN void\t\tTk_DrawCharsInContext(Display *display,\n\t\t\t\tDrawable drawable, GC gc, Tk_Font tkfont,\n\t\t\t\tconst char *string, Tcl_Size numBytes,\n\t\t\t\tTcl_Size rangeStart, Tcl_Size rangeLength,\n\t\t\t\tint x, int y);\n/* 293 */\nEXTERN int\t\tTk_MeasureCharsInContext(Tk_Font tkfont,\n\t\t\t\tconst char *string, Tcl_Size numBytes,\n\t\t\t\tTcl_Size rangeStart, Tcl_Size rangeLength,\n\t\t\t\tint maxPixels, int flags, int *lengthPtr);\n/* 294 */\nEXTERN void\t\tTkUnusedStubEntry(void);\n\ntypedef struct {\n    const struct TkPlatStubs *tkPlatStubs;\n    const struct TkIntStubs *tkIntStubs;\n    const struct TkIntPlatStubs *tkIntPlatStubs;\n    const struct TkIntXlibStubs *tkIntXlibStubs;\n} TkStubHooks;\n\ntypedef struct TkStubs {\n    int magic;\n    const TkStubHooks *hooks;\n\n    void (*tk_MainLoop) (void); /* 0 */\n    XColor * (*tk_3DBorderColor) (Tk_3DBorder border); /* 1 */\n    GC (*tk_3DBorderGC) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 2 */\n    void (*tk_3DHorizontalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, int rightIn, int topBevel, int relief); /* 3 */\n    void (*tk_3DVerticalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, int relief); /* 4 */\n    void (*tk_AddOption) (Tk_Window tkwin, const char *name, const char *value, int priority); /* 5 */\n    void (*tk_BindEvent) (Tk_BindingTable bindingTable, XEvent *eventPtr, Tk_Window tkwin, Tcl_Size numObjects, void **objectPtr); /* 6 */\n    void (*tk_CanvasDrawableCoords) (Tk_Canvas canvas, double x, double y, short *drawableXPtr, short *drawableYPtr); /* 7 */\n    void (*tk_CanvasEventuallyRedraw) (Tk_Canvas canvas, int x1, int y1, int x2, int y2); /* 8 */\n    int (*tk_CanvasGetCoord) (Tcl_Interp *interp, Tk_Canvas canvas, const char *str, double *doublePtr); /* 9 */\n    Tk_CanvasTextInfo * (*tk_CanvasGetTextInfo) (Tk_Canvas canvas); /* 10 */\n    int (*tk_CanvasPsBitmap) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap, int x, int y, int width, int height); /* 11 */\n    int (*tk_CanvasPsColor) (Tcl_Interp *interp, Tk_Canvas canvas, XColor *colorPtr); /* 12 */\n    int (*tk_CanvasPsFont) (Tcl_Interp *interp, Tk_Canvas canvas, Tk_Font font); /* 13 */\n    void (*tk_CanvasPsPath) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, Tcl_Size numPoints); /* 14 */\n    int (*tk_CanvasPsStipple) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap); /* 15 */\n    double (*tk_CanvasPsY) (Tk_Canvas canvas, double y); /* 16 */\n    void (*tk_CanvasSetStippleOrigin) (Tk_Canvas canvas, GC gc); /* 17 */\n    int (*tk_CanvasTagsParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 18 */\n    const char * (*tk_CanvasTagsPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 19 */\n    Tk_Window (*tk_CanvasTkwin) (Tk_Canvas canvas); /* 20 */\n    void (*tk_CanvasWindowCoords) (Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr); /* 21 */\n    void (*tk_ChangeWindowAttributes) (Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr); /* 22 */\n    int (*tk_CharBbox) (Tk_TextLayout layout, Tcl_Size index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 23 */\n    void (*tk_ClearSelection) (Tk_Window tkwin, Atom selection); /* 24 */\n    int (*tk_ClipboardAppend) (Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, const char *buffer); /* 25 */\n    int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */\n    int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, void *widgRec, const char *argvName, int flags); /* 27 */\n    int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, void *widgRec, const char *argvName, int flags); /* 28 */\n    int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, Tcl_Size objc, Tcl_Obj *const *objv, void *widgRec, int flags); /* 29 */\n    void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */\n    Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, Tcl_Size numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */\n    Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */\n    unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, void *object, const char *eventStr, const char *script, int append); /* 33 */\n    Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */\n    Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, void *clientData); /* 35 */\n    void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, void *clientData); /* 36 */\n    void (*tk_CreateGenericHandler) (Tk_GenericProc *proc, void *clientData); /* 37 */\n    void (*tk_CreateImageType) (const Tk_ImageType *typePtr); /* 38 */\n    void (*tk_CreateItemType) (Tk_ItemType *typePtr); /* 39 */\n    void (*tk_CreatePhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 40 */\n    void (*tk_CreateSelHandler) (Tk_Window tkwin, Atom selection, Atom target, Tk_SelectionProc *proc, void *clientData, Atom format); /* 41 */\n    Tk_Window (*tk_CreateWindow) (Tcl_Interp *interp, Tk_Window parent, const char *name, const char *screenName); /* 42 */\n    Tk_Window (*tk_CreateWindowFromPath) (Tcl_Interp *interp, Tk_Window tkwin, const char *pathName, const char *screenName); /* 43 */\n    int (*tk_DefineBitmap) (Tcl_Interp *interp, const char *name, const void *source, int width, int height); /* 44 */\n    void (*tk_DefineCursor) (Tk_Window window, Tk_Cursor cursor); /* 45 */\n    void (*tk_DeleteAllBindings) (Tk_BindingTable bindingTable, void *object); /* 46 */\n    int (*tk_DeleteBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, void *object, const char *eventStr); /* 47 */\n    void (*tk_DeleteBindingTable) (Tk_BindingTable bindingTable); /* 48 */\n    void (*tk_DeleteErrorHandler) (Tk_ErrorHandler handler); /* 49 */\n    void (*tk_DeleteEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, void *clientData); /* 50 */\n    void (*tk_DeleteGenericHandler) (Tk_GenericProc *proc, void *clientData); /* 51 */\n    void (*tk_DeleteImage) (Tcl_Interp *interp, const char *name); /* 52 */\n    void (*tk_DeleteSelHandler) (Tk_Window tkwin, Atom selection, Atom target); /* 53 */\n    void (*tk_DestroyWindow) (Tk_Window tkwin); /* 54 */\n    const char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */\n    int (*tk_DistanceToTextLayout) (Tk_TextLayout layout, int x, int y); /* 56 */\n    void (*tk_Draw3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, Tcl_Size numPoints, int borderWidth, int leftRelief); /* 57 */\n    void (*tk_Draw3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 58 */\n    void (*tk_DrawChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, Tcl_Size numBytes, int x, int y); /* 59 */\n    void (*tk_DrawFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable); /* 60 */\n    void (*tk_DrawTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, Tcl_Size firstChar, Tcl_Size lastChar); /* 61 */\n    void (*tk_Fill3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, Tcl_Size numPoints, int borderWidth, int leftRelief); /* 62 */\n    void (*tk_Fill3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 63 */\n    Tk_PhotoHandle (*tk_FindPhoto) (Tcl_Interp *interp, const char *imageName); /* 64 */\n    Font (*tk_FontId) (Tk_Font font); /* 65 */\n    void (*tk_Free3DBorder) (Tk_3DBorder border); /* 66 */\n    void (*tk_FreeBitmap) (Display *display, Pixmap bitmap); /* 67 */\n    void (*tk_FreeColor) (XColor *colorPtr); /* 68 */\n    void (*tk_FreeColormap) (Display *display, Colormap colormap); /* 69 */\n    void (*tk_FreeCursor) (Display *display, Tk_Cursor cursor); /* 70 */\n    void (*tk_FreeFont) (Tk_Font f); /* 71 */\n    void (*tk_FreeGC) (Display *display, GC gc); /* 72 */\n    void (*tk_FreeImage) (Tk_Image image); /* 73 */\n    void (*tk_FreeOptions) (const Tk_ConfigSpec *specs, void *widgRec, Display *display, int needFlags); /* 74 */\n    void (*tk_FreePixmap) (Display *display, Pixmap pixmap); /* 75 */\n    void (*tk_FreeTextLayout) (Tk_TextLayout textLayout); /* 76 */\n    void (*reserved77)(void);\n    GC (*tk_GCForColor) (XColor *colorPtr, Drawable drawable); /* 78 */\n    void (*tk_GeometryRequest) (Tk_Window tkwin, int reqWidth, int reqHeight); /* 79 */\n    Tk_3DBorder (*tk_Get3DBorder) (Tcl_Interp *interp, Tk_Window tkwin, const char *colorName); /* 80 */\n    void (*tk_GetAllBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable, void *object); /* 81 */\n    int (*tk_GetAnchor) (Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr); /* 82 */\n    const char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */\n    const char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, void *object, const char *eventStr); /* 84 */\n    Pixmap (*tk_GetBitmap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 85 */\n    Pixmap (*tk_GetBitmapFromData) (Tcl_Interp *interp, Tk_Window tkwin, const void *source, int width, int height); /* 86 */\n    int (*tk_GetCapStyle) (Tcl_Interp *interp, const char *str, int *capPtr); /* 87 */\n    XColor * (*tk_GetColor) (Tcl_Interp *interp, Tk_Window tkwin, const char *name); /* 88 */\n    XColor * (*tk_GetColorByValue) (Tk_Window tkwin, XColor *colorPtr); /* 89 */\n    Colormap (*tk_GetColormap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 90 */\n    Tk_Cursor (*tk_GetCursor) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 91 */\n    Tk_Cursor (*tk_GetCursorFromData) (Tcl_Interp *interp, Tk_Window tkwin, const char *source, const char *mask, int width, int height, int xHot, int yHot, const char *fg, const char *bg); /* 92 */\n    Tk_Font (*tk_GetFont) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 93 */\n    Tk_Font (*tk_GetFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 94 */\n    void (*tk_GetFontMetrics) (Tk_Font font, Tk_FontMetrics *fmPtr); /* 95 */\n    GC (*tk_GetGC) (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr); /* 96 */\n    Tk_Image (*tk_GetImage) (Tcl_Interp *interp, Tk_Window tkwin, const char *name, Tk_ImageChangedProc *changeProc, void *clientData); /* 97 */\n    void * (*tk_GetImageModelData) (Tcl_Interp *interp, const char *name, const Tk_ImageType **typePtrPtr); /* 98 */\n    Tk_ItemType * (*tk_GetItemTypes) (void); /* 99 */\n    int (*tk_GetJoinStyle) (Tcl_Interp *interp, const char *str, int *joinPtr); /* 100 */\n    int (*tk_GetJustify) (Tcl_Interp *interp, const char *str, Tk_Justify *justifyPtr); /* 101 */\n    int (*tk_GetNumMainWindows) (void); /* 102 */\n    Tk_Uid (*tk_GetOption) (Tk_Window tkwin, const char *name, const char *className); /* 103 */\n    int (*tk_GetPixels) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *intPtr); /* 104 */\n    Pixmap (*tk_GetPixmap) (Display *display, Drawable d, int width, int height, int depth); /* 105 */\n    int (*tk_GetRelief) (Tcl_Interp *interp, const char *name, int *reliefPtr); /* 106 */\n    void (*tk_GetRootCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 107 */\n    int (*tk_GetScrollInfo) (Tcl_Interp *interp, Tcl_Size argc, const char **argv, double *dblPtr, int *intPtr); /* 108 */\n    int (*tk_GetScreenMM) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr); /* 109 */\n    int (*tk_GetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, void *clientData); /* 110 */\n    Tk_Uid (*tk_GetUid) (const char *str); /* 111 */\n    Visual * (*tk_GetVisual) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *depthPtr, Colormap *colormapPtr); /* 112 */\n    void (*tk_GetVRootGeometry) (Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 113 */\n    int (*tk_Grab) (Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal); /* 114 */\n    void (*tk_HandleEvent) (XEvent *eventPtr); /* 115 */\n    Tk_Window (*tk_IdToWindow) (Display *display, Window window); /* 116 */\n    void (*tk_ImageChanged) (Tk_ImageModel model, int x, int y, int width, int height, int imageWidth, int imageHeight); /* 117 */\n    void (*reserved118)(void);\n    Atom (*tk_InternAtom) (Tk_Window tkwin, const char *name); /* 119 */\n    int (*tk_IntersectTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height); /* 120 */\n    void (*tk_MaintainGeometry) (Tk_Window window, Tk_Window container, int x, int y, int width, int height); /* 121 */\n    Tk_Window (*tk_MainWindow) (Tcl_Interp *interp); /* 122 */\n    void (*tk_MakeWindowExist) (Tk_Window tkwin); /* 123 */\n    void (*tk_ManageGeometry) (Tk_Window tkwin, const Tk_GeomMgr *mgrPtr, void *clientData); /* 124 */\n    void (*tk_MapWindow) (Tk_Window tkwin); /* 125 */\n    int (*tk_MeasureChars) (Tk_Font tkfont, const char *source, Tcl_Size numBytes, int maxPixels, int flags, int *lengthPtr); /* 126 */\n    void (*tk_MoveResizeWindow) (Tk_Window tkwin, int x, int y, int width, int height); /* 127 */\n    void (*tk_MoveWindow) (Tk_Window tkwin, int x, int y); /* 128 */\n    void (*tk_MoveToplevelWindow) (Tk_Window tkwin, int x, int y); /* 129 */\n    const char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */\n    const char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */\n    const char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */\n    const char * (*tk_NameOfCapStyle) (int cap); /* 133 */\n    const char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */\n    const char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */\n    const char * (*tk_NameOfFont) (Tk_Font font); /* 136 */\n    const char * (*tk_NameOfImage) (Tk_ImageModel model); /* 137 */\n    const char * (*tk_NameOfJoinStyle) (int join); /* 138 */\n    const char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */\n    const char * (*tk_NameOfRelief) (int relief); /* 140 */\n    Tk_Window (*tk_NameToWindow) (Tcl_Interp *interp, const char *pathName, Tk_Window tkwin); /* 141 */\n    void (*tk_OwnSelection) (Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, void *clientData); /* 142 */\n    int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, const char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */\n    void (*reserved144)(void);\n    void (*reserved145)(void);\n    int (*tk_PhotoGetImage) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr); /* 146 */\n    void (*tk_PhotoBlank) (Tk_PhotoHandle handle); /* 147 */\n    void (*reserved148)(void);\n    void (*tk_PhotoGetSize) (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 149 */\n    Tcl_Size (*tk_PointToChar) (Tk_TextLayout layout, int x, int y); /* 150 */\n    int (*tkPointToChar_) (Tk_TextLayout layout, int x, int y); /* 151 */\n    int (*tk_PostscriptFontName) (Tk_Font tkfont, Tcl_DString *dsPtr); /* 152 */\n    void (*tk_PreserveColormap) (Display *display, Colormap colormap); /* 153 */\n    void (*tk_QueueWindowEvent) (XEvent *eventPtr, Tcl_QueuePosition position); /* 154 */\n    void (*tk_RedrawImage) (Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY); /* 155 */\n    void (*tk_ResizeWindow) (Tk_Window tkwin, int width, int height); /* 156 */\n    int (*tk_RestackWindow) (Tk_Window tkwin, int aboveBelow, Tk_Window other); /* 157 */\n    Tk_RestrictProc * (*tk_RestrictEvents) (Tk_RestrictProc *proc, void *arg, void **prevArgPtr); /* 158 */\n    void (*reserved159)(void);\n    const char * (*tk_SetAppName) (Tk_Window tkwin, const char *name); /* 160 */\n    void (*tk_SetBackgroundFromBorder) (Tk_Window tkwin, Tk_3DBorder border); /* 161 */\n    void (*tk_SetClass) (Tk_Window tkwin, const char *className); /* 162 */\n    void (*tk_SetGrid) (Tk_Window tkwin, int reqWidth, int reqHeight, int gridWidth, int gridHeight); /* 163 */\n    void (*tk_SetInternalBorder) (Tk_Window tkwin, int width); /* 164 */\n    void (*tk_SetWindowBackground) (Tk_Window tkwin, unsigned long pixel); /* 165 */\n    void (*tk_SetWindowBackgroundPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 166 */\n    void (*tk_SetWindowBorder) (Tk_Window tkwin, unsigned long pixel); /* 167 */\n    void (*tk_SetWindowBorderWidth) (Tk_Window tkwin, int width); /* 168 */\n    void (*tk_SetWindowBorderPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 169 */\n    void (*tk_SetWindowColormap) (Tk_Window tkwin, Colormap colormap); /* 170 */\n    int (*tk_SetWindowVisual) (Tk_Window tkwin, Visual *visual, int depth, Colormap colormap); /* 171 */\n    void (*tk_SizeOfBitmap) (Display *display, Pixmap bitmap, int *widthPtr, int *heightPtr); /* 172 */\n    void (*tk_SizeOfImage) (Tk_Image image, int *widthPtr, int *heightPtr); /* 173 */\n    int (*tk_StrictMotif) (Tk_Window tkwin); /* 174 */\n    void (*tk_TextLayoutToPostscript) (Tcl_Interp *interp, Tk_TextLayout layout); /* 175 */\n    int (*tk_TextWidth) (Tk_Font font, const char *str, Tcl_Size numBytes); /* 176 */\n    void (*tk_UndefineCursor) (Tk_Window window); /* 177 */\n    void (*tk_UnderlineChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int x, int y, Tcl_Size firstByte, Tcl_Size lastByte); /* 178 */\n    void (*tk_UnderlineTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline); /* 179 */\n    void (*tk_Ungrab) (Tk_Window tkwin); /* 180 */\n    void (*tk_UnmaintainGeometry) (Tk_Window window, Tk_Window container); /* 181 */\n    void (*tk_UnmapWindow) (Tk_Window tkwin); /* 182 */\n    void (*tk_UnsetGrid) (Tk_Window tkwin); /* 183 */\n    void (*tk_UpdatePointer) (Tk_Window tkwin, int x, int y, int state); /* 184 */\n    Pixmap (*tk_AllocBitmapFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 185 */\n    Tk_3DBorder (*tk_Alloc3DBorderFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 186 */\n    XColor * (*tk_AllocColorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 187 */\n    Tk_Cursor (*tk_AllocCursorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 188 */\n    Tk_Font (*tk_AllocFontFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 189 */\n    Tk_OptionTable (*tk_CreateOptionTable) (Tcl_Interp *interp, const Tk_OptionSpec *templatePtr); /* 190 */\n    void (*tk_DeleteOptionTable) (Tk_OptionTable optionTable); /* 191 */\n    void (*tk_Free3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 192 */\n    void (*tk_FreeBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 193 */\n    void (*tk_FreeColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */\n    void (*tk_FreeConfigOptions) (void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */\n    void (*tk_FreeSavedOptions) (Tk_SavedOptions *savePtr); /* 196 */\n    void (*tk_FreeCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 197 */\n    void (*tk_FreeFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 198 */\n    Tk_3DBorder (*tk_Get3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 199 */\n    int (*tk_GetAnchorFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); /* 200 */\n    Pixmap (*tk_GetBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 201 */\n    XColor * (*tk_GetColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 202 */\n    Tk_Cursor (*tk_GetCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */\n    Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */\n    Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */\n    int (*tk_GetJustifyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 206 */\n    int (*tk_GetMMFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 207 */\n    int (*tk_GetPixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr); /* 208 */\n    int (*tk_GetReliefFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr); /* 209 */\n    int (*tk_GetScrollInfoObj) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, double *dblPtr, int *intPtr); /* 210 */\n    int (*tk_InitOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */\n    void (*reserved212)(void);\n    void (*tk_RestoreSavedOptions) (Tk_SavedOptions *savePtr); /* 213 */\n    int (*tk_SetOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Size objc, Tcl_Obj *const *objv, Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */\n    void (*tk_InitConsoleChannels) (Tcl_Interp *interp); /* 215 */\n    void (*reserved216)(void);\n    void (*tk_CreateSmoothMethod) (Tcl_Interp *interp, const Tk_SmoothMethod *method); /* 217 */\n    void (*reserved218)(void);\n    void (*reserved219)(void);\n    int (*tk_GetDash) (Tcl_Interp *interp, const char *value, Tk_Dash *dash); /* 220 */\n    void (*tk_CreateOutline) (Tk_Outline *outline); /* 221 */\n    void (*tk_DeleteOutline) (Display *display, Tk_Outline *outline); /* 222 */\n    int (*tk_ConfigOutlineGC) (XGCValues *gcValues, Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 223 */\n    int (*tk_ChangeOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 224 */\n    int (*tk_ResetOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 225 */\n    int (*tk_CanvasPsOutline) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 226 */\n    void (*tk_SetTSOrigin) (Tk_Window tkwin, GC gc, int x, int y); /* 227 */\n    int (*tk_CanvasGetCoordFromObj) (Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr); /* 228 */\n    void (*tk_CanvasSetOffset) (Tk_Canvas canvas, GC gc, Tk_TSOffset *offset); /* 229 */\n    void (*tk_DitherPhoto) (Tk_PhotoHandle handle, int x, int y, int width, int height); /* 230 */\n    int (*tk_PostscriptBitmap) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, int width, int height); /* 231 */\n    int (*tk_PostscriptColor) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, XColor *colorPtr); /* 232 */\n    int (*tk_PostscriptFont) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, Tk_Font font); /* 233 */\n    int (*tk_PostscriptImage) (Tk_Image image, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, int width, int height, int prepass); /* 234 */\n    void (*tk_PostscriptPath) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, double *coordPtr, Tcl_Size numPoints); /* 235 */\n    int (*tk_PostscriptStipple) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap); /* 236 */\n    double (*tk_PostscriptY) (double y, Tk_PostscriptInfo psInfo); /* 237 */\n    int (*tk_PostscriptPhoto) (Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, int width, int height); /* 238 */\n    void (*tk_CreateClientMessageHandler) (Tk_ClientMessageProc *proc); /* 239 */\n    void (*tk_DeleteClientMessageHandler) (Tk_ClientMessageProc *proc); /* 240 */\n    Tk_Window (*tk_CreateAnonymousWindow) (Tcl_Interp *interp, Tk_Window parent, const char *screenName); /* 241 */\n    void (*tk_SetClassProcs) (Tk_Window tkwin, const Tk_ClassProcs *procs, void *instanceData); /* 242 */\n    void (*tk_SetInternalBorderEx) (Tk_Window tkwin, int left, int right, int top, int bottom); /* 243 */\n    void (*tk_SetMinimumRequestSize) (Tk_Window tkwin, int minWidth, int minHeight); /* 244 */\n    void (*tk_SetCaretPos) (Tk_Window tkwin, int x, int y, int height); /* 245 */\n    void (*reserved246)(void);\n    void (*reserved247)(void);\n    int (*tk_CollapseMotionEvents) (Display *display, int collapse); /* 248 */\n    Tk_StyleEngine (*tk_RegisterStyleEngine) (const char *name, Tk_StyleEngine parent); /* 249 */\n    Tk_StyleEngine (*tk_GetStyleEngine) (const char *name); /* 250 */\n    int (*tk_RegisterStyledElement) (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr); /* 251 */\n    int (*tk_GetElementId) (const char *name); /* 252 */\n    Tk_Style (*tk_CreateStyle) (const char *name, Tk_StyleEngine engine, void *clientData); /* 253 */\n    Tk_Style (*tk_GetStyle) (Tcl_Interp *interp, const char *name); /* 254 */\n    void (*tk_FreeStyle) (Tk_Style style); /* 255 */\n    const char * (*tk_NameOfStyle) (Tk_Style style); /* 256 */\n    Tk_Style (*tk_AllocStyleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 257 */\n    void (*reserved258)(void);\n    void (*reserved259)(void);\n    Tk_StyledElement (*tk_GetStyledElement) (Tk_Style style, Tcl_Size elementId, Tk_OptionTable optionTable); /* 260 */\n    void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */\n    void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */\n    int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin); /* 263 */\n    void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */\n    int (*tk_PhotoExpand) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 265 */\n    int (*tk_PhotoPutBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 266 */\n    int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */\n    int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */\n    long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */\n    void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */\n    Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */\n    void (*reserved272)(void);\n    void (*reserved273)(void);\n    int (*tk_AlwaysShowSelection) (Tk_Window tkwin); /* 274 */\n    unsigned (*tk_GetButtonMask) (unsigned button); /* 275 */\n    int (*tk_GetDoublePixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 276 */\n    Tcl_Obj * (*tk_NewWindowObj) (Tk_Window tkwin); /* 277 */\n    void (*tk_SendVirtualEvent) (Tk_Window tkwin, const char *eventName, Tcl_Obj *detail); /* 278 */\n    Tcl_Obj * (*tk_FontGetDescription) (Tk_Font tkfont); /* 279 */\n    void (*tk_CreatePhotoImageFormatVersion3) (const Tk_PhotoImageFormatVersion3 *formatPtr); /* 280 */\n    void (*tk_DrawHighlightBorder) (Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable); /* 281 */\n    void (*tk_SetMainMenubar) (Tcl_Interp *interp, Tk_Window tkwin, const char *menuName); /* 282 */\n    void (*tk_SetWindowMenubar) (Tcl_Interp *interp, Tk_Window tkwin, const char *oldMenuName, const char *menuName); /* 283 */\n    void (*tk_ClipDrawableToRect) (Display *display, Drawable d, int x, int y, int width, int height); /* 284 */\n    Tcl_Obj * (*tk_GetSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 285 */\n    int (*tk_UseWindow) (Tcl_Interp *interp, Tk_Window tkwin, const char *string); /* 286 */\n    void (*tk_MakeContainer) (Tk_Window tkwin); /* 287 */\n    Tk_Window (*tk_GetOtherWindow) (Tk_Window tkwin); /* 288 */\n    void (*tk_Get3DBorderColors) (Tk_3DBorder border, XColor *bgColorPtr, XColor *darkColorPtr, XColor *lightColorPtr); /* 289 */\n    Window (*tk_MakeWindow) (Tk_Window tkwin, Window parent); /* 290 */\n    void (*tk_UnderlineCharsInContext) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *string, Tcl_Size numBytes, int x, int y, Tcl_Size firstByte, Tcl_Size lastByte); /* 291 */\n    void (*tk_DrawCharsInContext) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *string, Tcl_Size numBytes, Tcl_Size rangeStart, Tcl_Size rangeLength, int x, int y); /* 292 */\n    int (*tk_MeasureCharsInContext) (Tk_Font tkfont, const char *string, Tcl_Size numBytes, Tcl_Size rangeStart, Tcl_Size rangeLength, int maxPixels, int flags, int *lengthPtr); /* 293 */\n    void (*tkUnusedStubEntry) (void); /* 294 */\n} TkStubs;\n\nextern const TkStubs *tkStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#define Tk_MainLoop \\\n\t(tkStubsPtr->tk_MainLoop) /* 0 */\n#define Tk_3DBorderColor \\\n\t(tkStubsPtr->tk_3DBorderColor) /* 1 */\n#define Tk_3DBorderGC \\\n\t(tkStubsPtr->tk_3DBorderGC) /* 2 */\n#define Tk_3DHorizontalBevel \\\n\t(tkStubsPtr->tk_3DHorizontalBevel) /* 3 */\n#define Tk_3DVerticalBevel \\\n\t(tkStubsPtr->tk_3DVerticalBevel) /* 4 */\n#define Tk_AddOption \\\n\t(tkStubsPtr->tk_AddOption) /* 5 */\n#define Tk_BindEvent \\\n\t(tkStubsPtr->tk_BindEvent) /* 6 */\n#define Tk_CanvasDrawableCoords \\\n\t(tkStubsPtr->tk_CanvasDrawableCoords) /* 7 */\n#define Tk_CanvasEventuallyRedraw \\\n\t(tkStubsPtr->tk_CanvasEventuallyRedraw) /* 8 */\n#define Tk_CanvasGetCoord \\\n\t(tkStubsPtr->tk_CanvasGetCoord) /* 9 */\n#define Tk_CanvasGetTextInfo \\\n\t(tkStubsPtr->tk_CanvasGetTextInfo) /* 10 */\n#define Tk_CanvasPsBitmap \\\n\t(tkStubsPtr->tk_CanvasPsBitmap) /* 11 */\n#define Tk_CanvasPsColor \\\n\t(tkStubsPtr->tk_CanvasPsColor) /* 12 */\n#define Tk_CanvasPsFont \\\n\t(tkStubsPtr->tk_CanvasPsFont) /* 13 */\n#define Tk_CanvasPsPath \\\n\t(tkStubsPtr->tk_CanvasPsPath) /* 14 */\n#define Tk_CanvasPsStipple \\\n\t(tkStubsPtr->tk_CanvasPsStipple) /* 15 */\n#define Tk_CanvasPsY \\\n\t(tkStubsPtr->tk_CanvasPsY) /* 16 */\n#define Tk_CanvasSetStippleOrigin \\\n\t(tkStubsPtr->tk_CanvasSetStippleOrigin) /* 17 */\n#define Tk_CanvasTagsParseProc \\\n\t(tkStubsPtr->tk_CanvasTagsParseProc) /* 18 */\n#define Tk_CanvasTagsPrintProc \\\n\t(tkStubsPtr->tk_CanvasTagsPrintProc) /* 19 */\n#define Tk_CanvasTkwin \\\n\t(tkStubsPtr->tk_CanvasTkwin) /* 20 */\n#define Tk_CanvasWindowCoords \\\n\t(tkStubsPtr->tk_CanvasWindowCoords) /* 21 */\n#define Tk_ChangeWindowAttributes \\\n\t(tkStubsPtr->tk_ChangeWindowAttributes) /* 22 */\n#define Tk_CharBbox \\\n\t(tkStubsPtr->tk_CharBbox) /* 23 */\n#define Tk_ClearSelection \\\n\t(tkStubsPtr->tk_ClearSelection) /* 24 */\n#define Tk_ClipboardAppend \\\n\t(tkStubsPtr->tk_ClipboardAppend) /* 25 */\n#define Tk_ClipboardClear \\\n\t(tkStubsPtr->tk_ClipboardClear) /* 26 */\n#define Tk_ConfigureInfo \\\n\t(tkStubsPtr->tk_ConfigureInfo) /* 27 */\n#define Tk_ConfigureValue \\\n\t(tkStubsPtr->tk_ConfigureValue) /* 28 */\n#define Tk_ConfigureWidget \\\n\t(tkStubsPtr->tk_ConfigureWidget) /* 29 */\n#define Tk_ConfigureWindow \\\n\t(tkStubsPtr->tk_ConfigureWindow) /* 30 */\n#define Tk_ComputeTextLayout \\\n\t(tkStubsPtr->tk_ComputeTextLayout) /* 31 */\n#define Tk_CoordsToWindow \\\n\t(tkStubsPtr->tk_CoordsToWindow) /* 32 */\n#define Tk_CreateBinding \\\n\t(tkStubsPtr->tk_CreateBinding) /* 33 */\n#define Tk_CreateBindingTable \\\n\t(tkStubsPtr->tk_CreateBindingTable) /* 34 */\n#define Tk_CreateErrorHandler \\\n\t(tkStubsPtr->tk_CreateErrorHandler) /* 35 */\n#define Tk_CreateEventHandler \\\n\t(tkStubsPtr->tk_CreateEventHandler) /* 36 */\n#define Tk_CreateGenericHandler \\\n\t(tkStubsPtr->tk_CreateGenericHandler) /* 37 */\n#define Tk_CreateImageType \\\n\t(tkStubsPtr->tk_CreateImageType) /* 38 */\n#define Tk_CreateItemType \\\n\t(tkStubsPtr->tk_CreateItemType) /* 39 */\n#define Tk_CreatePhotoImageFormat \\\n\t(tkStubsPtr->tk_CreatePhotoImageFormat) /* 40 */\n#define Tk_CreateSelHandler \\\n\t(tkStubsPtr->tk_CreateSelHandler) /* 41 */\n#define Tk_CreateWindow \\\n\t(tkStubsPtr->tk_CreateWindow) /* 42 */\n#define Tk_CreateWindowFromPath \\\n\t(tkStubsPtr->tk_CreateWindowFromPath) /* 43 */\n#define Tk_DefineBitmap \\\n\t(tkStubsPtr->tk_DefineBitmap) /* 44 */\n#define Tk_DefineCursor \\\n\t(tkStubsPtr->tk_DefineCursor) /* 45 */\n#define Tk_DeleteAllBindings \\\n\t(tkStubsPtr->tk_DeleteAllBindings) /* 46 */\n#define Tk_DeleteBinding \\\n\t(tkStubsPtr->tk_DeleteBinding) /* 47 */\n#define Tk_DeleteBindingTable \\\n\t(tkStubsPtr->tk_DeleteBindingTable) /* 48 */\n#define Tk_DeleteErrorHandler \\\n\t(tkStubsPtr->tk_DeleteErrorHandler) /* 49 */\n#define Tk_DeleteEventHandler \\\n\t(tkStubsPtr->tk_DeleteEventHandler) /* 50 */\n#define Tk_DeleteGenericHandler \\\n\t(tkStubsPtr->tk_DeleteGenericHandler) /* 51 */\n#define Tk_DeleteImage \\\n\t(tkStubsPtr->tk_DeleteImage) /* 52 */\n#define Tk_DeleteSelHandler \\\n\t(tkStubsPtr->tk_DeleteSelHandler) /* 53 */\n#define Tk_DestroyWindow \\\n\t(tkStubsPtr->tk_DestroyWindow) /* 54 */\n#define Tk_DisplayName \\\n\t(tkStubsPtr->tk_DisplayName) /* 55 */\n#define Tk_DistanceToTextLayout \\\n\t(tkStubsPtr->tk_DistanceToTextLayout) /* 56 */\n#define Tk_Draw3DPolygon \\\n\t(tkStubsPtr->tk_Draw3DPolygon) /* 57 */\n#define Tk_Draw3DRectangle \\\n\t(tkStubsPtr->tk_Draw3DRectangle) /* 58 */\n#define Tk_DrawChars \\\n\t(tkStubsPtr->tk_DrawChars) /* 59 */\n#define Tk_DrawFocusHighlight \\\n\t(tkStubsPtr->tk_DrawFocusHighlight) /* 60 */\n#define Tk_DrawTextLayout \\\n\t(tkStubsPtr->tk_DrawTextLayout) /* 61 */\n#define Tk_Fill3DPolygon \\\n\t(tkStubsPtr->tk_Fill3DPolygon) /* 62 */\n#define Tk_Fill3DRectangle \\\n\t(tkStubsPtr->tk_Fill3DRectangle) /* 63 */\n#define Tk_FindPhoto \\\n\t(tkStubsPtr->tk_FindPhoto) /* 64 */\n#define Tk_FontId \\\n\t(tkStubsPtr->tk_FontId) /* 65 */\n#define Tk_Free3DBorder \\\n\t(tkStubsPtr->tk_Free3DBorder) /* 66 */\n#define Tk_FreeBitmap \\\n\t(tkStubsPtr->tk_FreeBitmap) /* 67 */\n#define Tk_FreeColor \\\n\t(tkStubsPtr->tk_FreeColor) /* 68 */\n#define Tk_FreeColormap \\\n\t(tkStubsPtr->tk_FreeColormap) /* 69 */\n#define Tk_FreeCursor \\\n\t(tkStubsPtr->tk_FreeCursor) /* 70 */\n#define Tk_FreeFont \\\n\t(tkStubsPtr->tk_FreeFont) /* 71 */\n#define Tk_FreeGC \\\n\t(tkStubsPtr->tk_FreeGC) /* 72 */\n#define Tk_FreeImage \\\n\t(tkStubsPtr->tk_FreeImage) /* 73 */\n#define Tk_FreeOptions \\\n\t(tkStubsPtr->tk_FreeOptions) /* 74 */\n#define Tk_FreePixmap \\\n\t(tkStubsPtr->tk_FreePixmap) /* 75 */\n#define Tk_FreeTextLayout \\\n\t(tkStubsPtr->tk_FreeTextLayout) /* 76 */\n/* Slot 77 is reserved */\n#define Tk_GCForColor \\\n\t(tkStubsPtr->tk_GCForColor) /* 78 */\n#define Tk_GeometryRequest \\\n\t(tkStubsPtr->tk_GeometryRequest) /* 79 */\n#define Tk_Get3DBorder \\\n\t(tkStubsPtr->tk_Get3DBorder) /* 80 */\n#define Tk_GetAllBindings \\\n\t(tkStubsPtr->tk_GetAllBindings) /* 81 */\n#define Tk_GetAnchor \\\n\t(tkStubsPtr->tk_GetAnchor) /* 82 */\n#define Tk_GetAtomName \\\n\t(tkStubsPtr->tk_GetAtomName) /* 83 */\n#define Tk_GetBinding \\\n\t(tkStubsPtr->tk_GetBinding) /* 84 */\n#define Tk_GetBitmap \\\n\t(tkStubsPtr->tk_GetBitmap) /* 85 */\n#define Tk_GetBitmapFromData \\\n\t(tkStubsPtr->tk_GetBitmapFromData) /* 86 */\n#define Tk_GetCapStyle \\\n\t(tkStubsPtr->tk_GetCapStyle) /* 87 */\n#define Tk_GetColor \\\n\t(tkStubsPtr->tk_GetColor) /* 88 */\n#define Tk_GetColorByValue \\\n\t(tkStubsPtr->tk_GetColorByValue) /* 89 */\n#define Tk_GetColormap \\\n\t(tkStubsPtr->tk_GetColormap) /* 90 */\n#define Tk_GetCursor \\\n\t(tkStubsPtr->tk_GetCursor) /* 91 */\n#define Tk_GetCursorFromData \\\n\t(tkStubsPtr->tk_GetCursorFromData) /* 92 */\n#define Tk_GetFont \\\n\t(tkStubsPtr->tk_GetFont) /* 93 */\n#define Tk_GetFontFromObj \\\n\t(tkStubsPtr->tk_GetFontFromObj) /* 94 */\n#define Tk_GetFontMetrics \\\n\t(tkStubsPtr->tk_GetFontMetrics) /* 95 */\n#define Tk_GetGC \\\n\t(tkStubsPtr->tk_GetGC) /* 96 */\n#define Tk_GetImage \\\n\t(tkStubsPtr->tk_GetImage) /* 97 */\n#define Tk_GetImageModelData \\\n\t(tkStubsPtr->tk_GetImageModelData) /* 98 */\n#define Tk_GetItemTypes \\\n\t(tkStubsPtr->tk_GetItemTypes) /* 99 */\n#define Tk_GetJoinStyle \\\n\t(tkStubsPtr->tk_GetJoinStyle) /* 100 */\n#define Tk_GetJustify \\\n\t(tkStubsPtr->tk_GetJustify) /* 101 */\n#define Tk_GetNumMainWindows \\\n\t(tkStubsPtr->tk_GetNumMainWindows) /* 102 */\n#define Tk_GetOption \\\n\t(tkStubsPtr->tk_GetOption) /* 103 */\n#define Tk_GetPixels \\\n\t(tkStubsPtr->tk_GetPixels) /* 104 */\n#define Tk_GetPixmap \\\n\t(tkStubsPtr->tk_GetPixmap) /* 105 */\n#define Tk_GetRelief \\\n\t(tkStubsPtr->tk_GetRelief) /* 106 */\n#define Tk_GetRootCoords \\\n\t(tkStubsPtr->tk_GetRootCoords) /* 107 */\n#define Tk_GetScrollInfo \\\n\t(tkStubsPtr->tk_GetScrollInfo) /* 108 */\n#define Tk_GetScreenMM \\\n\t(tkStubsPtr->tk_GetScreenMM) /* 109 */\n#define Tk_GetSelection \\\n\t(tkStubsPtr->tk_GetSelection) /* 110 */\n#define Tk_GetUid \\\n\t(tkStubsPtr->tk_GetUid) /* 111 */\n#define Tk_GetVisual \\\n\t(tkStubsPtr->tk_GetVisual) /* 112 */\n#define Tk_GetVRootGeometry \\\n\t(tkStubsPtr->tk_GetVRootGeometry) /* 113 */\n#define Tk_Grab \\\n\t(tkStubsPtr->tk_Grab) /* 114 */\n#define Tk_HandleEvent \\\n\t(tkStubsPtr->tk_HandleEvent) /* 115 */\n#define Tk_IdToWindow \\\n\t(tkStubsPtr->tk_IdToWindow) /* 116 */\n#define Tk_ImageChanged \\\n\t(tkStubsPtr->tk_ImageChanged) /* 117 */\n/* Slot 118 is reserved */\n#define Tk_InternAtom \\\n\t(tkStubsPtr->tk_InternAtom) /* 119 */\n#define Tk_IntersectTextLayout \\\n\t(tkStubsPtr->tk_IntersectTextLayout) /* 120 */\n#define Tk_MaintainGeometry \\\n\t(tkStubsPtr->tk_MaintainGeometry) /* 121 */\n#define Tk_MainWindow \\\n\t(tkStubsPtr->tk_MainWindow) /* 122 */\n#define Tk_MakeWindowExist \\\n\t(tkStubsPtr->tk_MakeWindowExist) /* 123 */\n#define Tk_ManageGeometry \\\n\t(tkStubsPtr->tk_ManageGeometry) /* 124 */\n#define Tk_MapWindow \\\n\t(tkStubsPtr->tk_MapWindow) /* 125 */\n#define Tk_MeasureChars \\\n\t(tkStubsPtr->tk_MeasureChars) /* 126 */\n#define Tk_MoveResizeWindow \\\n\t(tkStubsPtr->tk_MoveResizeWindow) /* 127 */\n#define Tk_MoveWindow \\\n\t(tkStubsPtr->tk_MoveWindow) /* 128 */\n#define Tk_MoveToplevelWindow \\\n\t(tkStubsPtr->tk_MoveToplevelWindow) /* 129 */\n#define Tk_NameOf3DBorder \\\n\t(tkStubsPtr->tk_NameOf3DBorder) /* 130 */\n#define Tk_NameOfAnchor \\\n\t(tkStubsPtr->tk_NameOfAnchor) /* 131 */\n#define Tk_NameOfBitmap \\\n\t(tkStubsPtr->tk_NameOfBitmap) /* 132 */\n#define Tk_NameOfCapStyle \\\n\t(tkStubsPtr->tk_NameOfCapStyle) /* 133 */\n#define Tk_NameOfColor \\\n\t(tkStubsPtr->tk_NameOfColor) /* 134 */\n#define Tk_NameOfCursor \\\n\t(tkStubsPtr->tk_NameOfCursor) /* 135 */\n#define Tk_NameOfFont \\\n\t(tkStubsPtr->tk_NameOfFont) /* 136 */\n#define Tk_NameOfImage \\\n\t(tkStubsPtr->tk_NameOfImage) /* 137 */\n#define Tk_NameOfJoinStyle \\\n\t(tkStubsPtr->tk_NameOfJoinStyle) /* 138 */\n#define Tk_NameOfJustify \\\n\t(tkStubsPtr->tk_NameOfJustify) /* 139 */\n#define Tk_NameOfRelief \\\n\t(tkStubsPtr->tk_NameOfRelief) /* 140 */\n#define Tk_NameToWindow \\\n\t(tkStubsPtr->tk_NameToWindow) /* 141 */\n#define Tk_OwnSelection \\\n\t(tkStubsPtr->tk_OwnSelection) /* 142 */\n#define Tk_ParseArgv \\\n\t(tkStubsPtr->tk_ParseArgv) /* 143 */\n/* Slot 144 is reserved */\n/* Slot 145 is reserved */\n#define Tk_PhotoGetImage \\\n\t(tkStubsPtr->tk_PhotoGetImage) /* 146 */\n#define Tk_PhotoBlank \\\n\t(tkStubsPtr->tk_PhotoBlank) /* 147 */\n/* Slot 148 is reserved */\n#define Tk_PhotoGetSize \\\n\t(tkStubsPtr->tk_PhotoGetSize) /* 149 */\n#define Tk_PointToChar \\\n\t(tkStubsPtr->tk_PointToChar) /* 150 */\n#define TkPointToChar_ \\\n\t(tkStubsPtr->tkPointToChar_) /* 151 */\n#define Tk_PostscriptFontName \\\n\t(tkStubsPtr->tk_PostscriptFontName) /* 152 */\n#define Tk_PreserveColormap \\\n\t(tkStubsPtr->tk_PreserveColormap) /* 153 */\n#define Tk_QueueWindowEvent \\\n\t(tkStubsPtr->tk_QueueWindowEvent) /* 154 */\n#define Tk_RedrawImage \\\n\t(tkStubsPtr->tk_RedrawImage) /* 155 */\n#define Tk_ResizeWindow \\\n\t(tkStubsPtr->tk_ResizeWindow) /* 156 */\n#define Tk_RestackWindow \\\n\t(tkStubsPtr->tk_RestackWindow) /* 157 */\n#define Tk_RestrictEvents \\\n\t(tkStubsPtr->tk_RestrictEvents) /* 158 */\n/* Slot 159 is reserved */\n#define Tk_SetAppName \\\n\t(tkStubsPtr->tk_SetAppName) /* 160 */\n#define Tk_SetBackgroundFromBorder \\\n\t(tkStubsPtr->tk_SetBackgroundFromBorder) /* 161 */\n#define Tk_SetClass \\\n\t(tkStubsPtr->tk_SetClass) /* 162 */\n#define Tk_SetGrid \\\n\t(tkStubsPtr->tk_SetGrid) /* 163 */\n#define Tk_SetInternalBorder \\\n\t(tkStubsPtr->tk_SetInternalBorder) /* 164 */\n#define Tk_SetWindowBackground \\\n\t(tkStubsPtr->tk_SetWindowBackground) /* 165 */\n#define Tk_SetWindowBackgroundPixmap \\\n\t(tkStubsPtr->tk_SetWindowBackgroundPixmap) /* 166 */\n#define Tk_SetWindowBorder \\\n\t(tkStubsPtr->tk_SetWindowBorder) /* 167 */\n#define Tk_SetWindowBorderWidth \\\n\t(tkStubsPtr->tk_SetWindowBorderWidth) /* 168 */\n#define Tk_SetWindowBorderPixmap \\\n\t(tkStubsPtr->tk_SetWindowBorderPixmap) /* 169 */\n#define Tk_SetWindowColormap \\\n\t(tkStubsPtr->tk_SetWindowColormap) /* 170 */\n#define Tk_SetWindowVisual \\\n\t(tkStubsPtr->tk_SetWindowVisual) /* 171 */\n#define Tk_SizeOfBitmap \\\n\t(tkStubsPtr->tk_SizeOfBitmap) /* 172 */\n#define Tk_SizeOfImage \\\n\t(tkStubsPtr->tk_SizeOfImage) /* 173 */\n#define Tk_StrictMotif \\\n\t(tkStubsPtr->tk_StrictMotif) /* 174 */\n#define Tk_TextLayoutToPostscript \\\n\t(tkStubsPtr->tk_TextLayoutToPostscript) /* 175 */\n#define Tk_TextWidth \\\n\t(tkStubsPtr->tk_TextWidth) /* 176 */\n#define Tk_UndefineCursor \\\n\t(tkStubsPtr->tk_UndefineCursor) /* 177 */\n#define Tk_UnderlineChars \\\n\t(tkStubsPtr->tk_UnderlineChars) /* 178 */\n#define Tk_UnderlineTextLayout \\\n\t(tkStubsPtr->tk_UnderlineTextLayout) /* 179 */\n#define Tk_Ungrab \\\n\t(tkStubsPtr->tk_Ungrab) /* 180 */\n#define Tk_UnmaintainGeometry \\\n\t(tkStubsPtr->tk_UnmaintainGeometry) /* 181 */\n#define Tk_UnmapWindow \\\n\t(tkStubsPtr->tk_UnmapWindow) /* 182 */\n#define Tk_UnsetGrid \\\n\t(tkStubsPtr->tk_UnsetGrid) /* 183 */\n#define Tk_UpdatePointer \\\n\t(tkStubsPtr->tk_UpdatePointer) /* 184 */\n#define Tk_AllocBitmapFromObj \\\n\t(tkStubsPtr->tk_AllocBitmapFromObj) /* 185 */\n#define Tk_Alloc3DBorderFromObj \\\n\t(tkStubsPtr->tk_Alloc3DBorderFromObj) /* 186 */\n#define Tk_AllocColorFromObj \\\n\t(tkStubsPtr->tk_AllocColorFromObj) /* 187 */\n#define Tk_AllocCursorFromObj \\\n\t(tkStubsPtr->tk_AllocCursorFromObj) /* 188 */\n#define Tk_AllocFontFromObj \\\n\t(tkStubsPtr->tk_AllocFontFromObj) /* 189 */\n#define Tk_CreateOptionTable \\\n\t(tkStubsPtr->tk_CreateOptionTable) /* 190 */\n#define Tk_DeleteOptionTable \\\n\t(tkStubsPtr->tk_DeleteOptionTable) /* 191 */\n#define Tk_Free3DBorderFromObj \\\n\t(tkStubsPtr->tk_Free3DBorderFromObj) /* 192 */\n#define Tk_FreeBitmapFromObj \\\n\t(tkStubsPtr->tk_FreeBitmapFromObj) /* 193 */\n#define Tk_FreeColorFromObj \\\n\t(tkStubsPtr->tk_FreeColorFromObj) /* 194 */\n#define Tk_FreeConfigOptions \\\n\t(tkStubsPtr->tk_FreeConfigOptions) /* 195 */\n#define Tk_FreeSavedOptions \\\n\t(tkStubsPtr->tk_FreeSavedOptions) /* 196 */\n#define Tk_FreeCursorFromObj \\\n\t(tkStubsPtr->tk_FreeCursorFromObj) /* 197 */\n#define Tk_FreeFontFromObj \\\n\t(tkStubsPtr->tk_FreeFontFromObj) /* 198 */\n#define Tk_Get3DBorderFromObj \\\n\t(tkStubsPtr->tk_Get3DBorderFromObj) /* 199 */\n#define Tk_GetAnchorFromObj \\\n\t(tkStubsPtr->tk_GetAnchorFromObj) /* 200 */\n#define Tk_GetBitmapFromObj \\\n\t(tkStubsPtr->tk_GetBitmapFromObj) /* 201 */\n#define Tk_GetColorFromObj \\\n\t(tkStubsPtr->tk_GetColorFromObj) /* 202 */\n#define Tk_GetCursorFromObj \\\n\t(tkStubsPtr->tk_GetCursorFromObj) /* 203 */\n#define Tk_GetOptionInfo \\\n\t(tkStubsPtr->tk_GetOptionInfo) /* 204 */\n#define Tk_GetOptionValue \\\n\t(tkStubsPtr->tk_GetOptionValue) /* 205 */\n#define Tk_GetJustifyFromObj \\\n\t(tkStubsPtr->tk_GetJustifyFromObj) /* 206 */\n#define Tk_GetMMFromObj \\\n\t(tkStubsPtr->tk_GetMMFromObj) /* 207 */\n#define Tk_GetPixelsFromObj \\\n\t(tkStubsPtr->tk_GetPixelsFromObj) /* 208 */\n#define Tk_GetReliefFromObj \\\n\t(tkStubsPtr->tk_GetReliefFromObj) /* 209 */\n#define Tk_GetScrollInfoObj \\\n\t(tkStubsPtr->tk_GetScrollInfoObj) /* 210 */\n#define Tk_InitOptions \\\n\t(tkStubsPtr->tk_InitOptions) /* 211 */\n/* Slot 212 is reserved */\n#define Tk_RestoreSavedOptions \\\n\t(tkStubsPtr->tk_RestoreSavedOptions) /* 213 */\n#define Tk_SetOptions \\\n\t(tkStubsPtr->tk_SetOptions) /* 214 */\n#define Tk_InitConsoleChannels \\\n\t(tkStubsPtr->tk_InitConsoleChannels) /* 215 */\n/* Slot 216 is reserved */\n#define Tk_CreateSmoothMethod \\\n\t(tkStubsPtr->tk_CreateSmoothMethod) /* 217 */\n/* Slot 218 is reserved */\n/* Slot 219 is reserved */\n#define Tk_GetDash \\\n\t(tkStubsPtr->tk_GetDash) /* 220 */\n#define Tk_CreateOutline \\\n\t(tkStubsPtr->tk_CreateOutline) /* 221 */\n#define Tk_DeleteOutline \\\n\t(tkStubsPtr->tk_DeleteOutline) /* 222 */\n#define Tk_ConfigOutlineGC \\\n\t(tkStubsPtr->tk_ConfigOutlineGC) /* 223 */\n#define Tk_ChangeOutlineGC \\\n\t(tkStubsPtr->tk_ChangeOutlineGC) /* 224 */\n#define Tk_ResetOutlineGC \\\n\t(tkStubsPtr->tk_ResetOutlineGC) /* 225 */\n#define Tk_CanvasPsOutline \\\n\t(tkStubsPtr->tk_CanvasPsOutline) /* 226 */\n#define Tk_SetTSOrigin \\\n\t(tkStubsPtr->tk_SetTSOrigin) /* 227 */\n#define Tk_CanvasGetCoordFromObj \\\n\t(tkStubsPtr->tk_CanvasGetCoordFromObj) /* 228 */\n#define Tk_CanvasSetOffset \\\n\t(tkStubsPtr->tk_CanvasSetOffset) /* 229 */\n#define Tk_DitherPhoto \\\n\t(tkStubsPtr->tk_DitherPhoto) /* 230 */\n#define Tk_PostscriptBitmap \\\n\t(tkStubsPtr->tk_PostscriptBitmap) /* 231 */\n#define Tk_PostscriptColor \\\n\t(tkStubsPtr->tk_PostscriptColor) /* 232 */\n#define Tk_PostscriptFont \\\n\t(tkStubsPtr->tk_PostscriptFont) /* 233 */\n#define Tk_PostscriptImage \\\n\t(tkStubsPtr->tk_PostscriptImage) /* 234 */\n#define Tk_PostscriptPath \\\n\t(tkStubsPtr->tk_PostscriptPath) /* 235 */\n#define Tk_PostscriptStipple \\\n\t(tkStubsPtr->tk_PostscriptStipple) /* 236 */\n#define Tk_PostscriptY \\\n\t(tkStubsPtr->tk_PostscriptY) /* 237 */\n#define Tk_PostscriptPhoto \\\n\t(tkStubsPtr->tk_PostscriptPhoto) /* 238 */\n#define Tk_CreateClientMessageHandler \\\n\t(tkStubsPtr->tk_CreateClientMessageHandler) /* 239 */\n#define Tk_DeleteClientMessageHandler \\\n\t(tkStubsPtr->tk_DeleteClientMessageHandler) /* 240 */\n#define Tk_CreateAnonymousWindow \\\n\t(tkStubsPtr->tk_CreateAnonymousWindow) /* 241 */\n#define Tk_SetClassProcs \\\n\t(tkStubsPtr->tk_SetClassProcs) /* 242 */\n#define Tk_SetInternalBorderEx \\\n\t(tkStubsPtr->tk_SetInternalBorderEx) /* 243 */\n#define Tk_SetMinimumRequestSize \\\n\t(tkStubsPtr->tk_SetMinimumRequestSize) /* 244 */\n#define Tk_SetCaretPos \\\n\t(tkStubsPtr->tk_SetCaretPos) /* 245 */\n/* Slot 246 is reserved */\n/* Slot 247 is reserved */\n#define Tk_CollapseMotionEvents \\\n\t(tkStubsPtr->tk_CollapseMotionEvents) /* 248 */\n#define Tk_RegisterStyleEngine \\\n\t(tkStubsPtr->tk_RegisterStyleEngine) /* 249 */\n#define Tk_GetStyleEngine \\\n\t(tkStubsPtr->tk_GetStyleEngine) /* 250 */\n#define Tk_RegisterStyledElement \\\n\t(tkStubsPtr->tk_RegisterStyledElement) /* 251 */\n#define Tk_GetElementId \\\n\t(tkStubsPtr->tk_GetElementId) /* 252 */\n#define Tk_CreateStyle \\\n\t(tkStubsPtr->tk_CreateStyle) /* 253 */\n#define Tk_GetStyle \\\n\t(tkStubsPtr->tk_GetStyle) /* 254 */\n#define Tk_FreeStyle \\\n\t(tkStubsPtr->tk_FreeStyle) /* 255 */\n#define Tk_NameOfStyle \\\n\t(tkStubsPtr->tk_NameOfStyle) /* 256 */\n#define Tk_AllocStyleFromObj \\\n\t(tkStubsPtr->tk_AllocStyleFromObj) /* 257 */\n/* Slot 258 is reserved */\n/* Slot 259 is reserved */\n#define Tk_GetStyledElement \\\n\t(tkStubsPtr->tk_GetStyledElement) /* 260 */\n#define Tk_GetElementSize \\\n\t(tkStubsPtr->tk_GetElementSize) /* 261 */\n#define Tk_GetElementBox \\\n\t(tkStubsPtr->tk_GetElementBox) /* 262 */\n#define Tk_GetElementBorderWidth \\\n\t(tkStubsPtr->tk_GetElementBorderWidth) /* 263 */\n#define Tk_DrawElement \\\n\t(tkStubsPtr->tk_DrawElement) /* 264 */\n#define Tk_PhotoExpand \\\n\t(tkStubsPtr->tk_PhotoExpand) /* 265 */\n#define Tk_PhotoPutBlock \\\n\t(tkStubsPtr->tk_PhotoPutBlock) /* 266 */\n#define Tk_PhotoPutZoomedBlock \\\n\t(tkStubsPtr->tk_PhotoPutZoomedBlock) /* 267 */\n#define Tk_PhotoSetSize \\\n\t(tkStubsPtr->tk_PhotoSetSize) /* 268 */\n#define Tk_GetUserInactiveTime \\\n\t(tkStubsPtr->tk_GetUserInactiveTime) /* 269 */\n#define Tk_ResetUserInactiveTime \\\n\t(tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */\n#define Tk_Interp \\\n\t(tkStubsPtr->tk_Interp) /* 271 */\n/* Slot 272 is reserved */\n/* Slot 273 is reserved */\n#define Tk_AlwaysShowSelection \\\n\t(tkStubsPtr->tk_AlwaysShowSelection) /* 274 */\n#define Tk_GetButtonMask \\\n\t(tkStubsPtr->tk_GetButtonMask) /* 275 */\n#define Tk_GetDoublePixelsFromObj \\\n\t(tkStubsPtr->tk_GetDoublePixelsFromObj) /* 276 */\n#define Tk_NewWindowObj \\\n\t(tkStubsPtr->tk_NewWindowObj) /* 277 */\n#define Tk_SendVirtualEvent \\\n\t(tkStubsPtr->tk_SendVirtualEvent) /* 278 */\n#define Tk_FontGetDescription \\\n\t(tkStubsPtr->tk_FontGetDescription) /* 279 */\n#define Tk_CreatePhotoImageFormatVersion3 \\\n\t(tkStubsPtr->tk_CreatePhotoImageFormatVersion3) /* 280 */\n#define Tk_DrawHighlightBorder \\\n\t(tkStubsPtr->tk_DrawHighlightBorder) /* 281 */\n#define Tk_SetMainMenubar \\\n\t(tkStubsPtr->tk_SetMainMenubar) /* 282 */\n#define Tk_SetWindowMenubar \\\n\t(tkStubsPtr->tk_SetWindowMenubar) /* 283 */\n#define Tk_ClipDrawableToRect \\\n\t(tkStubsPtr->tk_ClipDrawableToRect) /* 284 */\n#define Tk_GetSystemDefault \\\n\t(tkStubsPtr->tk_GetSystemDefault) /* 285 */\n#define Tk_UseWindow \\\n\t(tkStubsPtr->tk_UseWindow) /* 286 */\n#define Tk_MakeContainer \\\n\t(tkStubsPtr->tk_MakeContainer) /* 287 */\n#define Tk_GetOtherWindow \\\n\t(tkStubsPtr->tk_GetOtherWindow) /* 288 */\n#define Tk_Get3DBorderColors \\\n\t(tkStubsPtr->tk_Get3DBorderColors) /* 289 */\n#define Tk_MakeWindow \\\n\t(tkStubsPtr->tk_MakeWindow) /* 290 */\n#define Tk_UnderlineCharsInContext \\\n\t(tkStubsPtr->tk_UnderlineCharsInContext) /* 291 */\n#define Tk_DrawCharsInContext \\\n\t(tkStubsPtr->tk_DrawCharsInContext) /* 292 */\n#define Tk_MeasureCharsInContext \\\n\t(tkStubsPtr->tk_MeasureCharsInContext) /* 293 */\n#define TkUnusedStubEntry \\\n\t(tkStubsPtr->tkUnusedStubEntry) /* 294 */\n\n#endif /* defined(USE_TK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#define Tk_GetImageMasterData Tk_GetImageModelData\n\n#undef TkPointToChar_\n#ifndef MAC_OSX_TK\n#   undef Tk_ClipDrawableToRect\n#endif\n\nEXTERN void  Tk_MainEx(Tcl_Size argc, char **argv,\n\tTcl_AppInitProc *appInitProc, Tcl_Interp *interp);\n#if defined(_WIN32) && defined(UNICODE)\n#   define Tk_MainEx Tk_MainExW\n    EXTERN void Tk_MainExW(Tcl_Size argc, wchar_t **argv,\n\t    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);\n#endif\nEXTERN int Tk_Init(Tcl_Interp *interp);\nEXTERN int Tk_SafeInit(Tcl_Interp *interp);\nEXTERN int Tk_CreateConsoleWindow(Tcl_Interp *interp);\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#undef TkUnusedStubEntry\n\n#endif /* _TKDECLS */\n"
  },
  {
    "path": "generic/tkEntry.c",
    "content": "/*\n * tkEntry.c --\n *\n *\tThis module implements entry and spinbox widgets for the Tk toolkit.\n *\tAn entry displays a string and allows the string to be edited. A\n *\tspinbox expands on the entry by adding up/down buttons that control\n *\tthe value of the entry widget.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2000 Ajuba Solutions.\n * Copyright © 2002 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkEntry.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The following macro defines how many extra pixels to leave on each side of\n * the text in the entry.\n */\n\n#define XPAD 1\n#define YPAD 1\n\n/*\n * A comparison function for double values. For Spinboxes.\n */\n\n#define MIN_DBL_VAL\t\t1E-9\n#define DOUBLES_EQ(d1, d2)\t(fabs((d1) - (d2)) < MIN_DBL_VAL)\n\n\nstatic const char *const stateStrings[] = {\n    \"disabled\", \"normal\", \"readonly\", NULL\n};\n\n/*\n * Definitions for -validate option values:\n */\n\nstatic const char *const validateStrings[] = {\n    \"all\", \"key\", \"focus\", \"focusin\", \"focusout\", \"none\", NULL\n};\nenum validateType {\n    VALIDATE_ALL, VALIDATE_KEY, VALIDATE_FOCUS,\n    VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT, VALIDATE_NONE,\n    /*\n     * These extra enums are for use with EntryValidateChange\n     */\n    VALIDATE_FORCED, VALIDATE_DELETE, VALIDATE_INSERT, VALIDATE_BUTTON\n};\n#define DEF_ENTRY_VALIDATE\t\"none\"\n#define DEF_ENTRY_INVALIDCMD\t\"\"\n\n/*\n * Information used for Entry objv parsing.\n */\n\nstatic const Tk_OptionSpec entryOptSpec[] = {\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_ENTRY_BG_COLOR, TCL_INDEX_NONE, offsetof(Entry, normalBorder),\n\t0, DEF_ENTRY_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_ENTRY_BORDER_WIDTH, offsetof(Entry, borderWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_ENTRY_CURSOR, TCL_INDEX_NONE, offsetof(Entry, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BORDER, \"-disabledbackground\", \"disabledBackground\",\n\t\"DisabledBackground\", DEF_ENTRY_DISABLED_BG_COLOR, TCL_INDEX_NONE,\n\toffsetof(Entry, disabledBorder), TK_OPTION_NULL_OK,\n\tDEF_ENTRY_DISABLED_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_ENTRY_DISABLED_FG, TCL_INDEX_NONE,\n\toffsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-exportselection\", \"exportSelection\",\n\t\"ExportSelection\", DEF_ENTRY_EXPORT_SELECTION, TCL_INDEX_NONE,\n\toffsetof(Entry, exportSelection), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_ENTRY_FONT, TCL_INDEX_NONE, offsetof(Entry, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_ENTRY_FG, TCL_INDEX_NONE, offsetof(Entry, fgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_ENTRY_HIGHLIGHT_BG,\n\tTCL_INDEX_NONE, offsetof(Entry, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_ENTRY_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Entry, highlightColorPtr), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_ENTRY_HIGHLIGHT_WIDTH, offsetof(Entry, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-insertbackground\", \"insertBackground\", \"Foreground\",\n\tDEF_ENTRY_INSERT_BG, TCL_INDEX_NONE, offsetof(Entry, insertBorder), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-insertborderwidth\", \"insertBorderWidth\",\n\t\"BorderWidth\", DEF_ENTRY_INSERT_BD_COLOR, offsetof(Entry, insertBorderWidthObj),\n\tTCL_INDEX_NONE, 0,\n\tDEF_ENTRY_INSERT_BD_MONO, 0},\n    {TK_OPTION_INT, \"-insertofftime\", \"insertOffTime\", \"OffTime\",\n\tDEF_ENTRY_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOffTime),\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-insertontime\", \"insertOnTime\", \"OnTime\",\n\tDEF_ENTRY_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOnTime), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-insertwidth\", \"insertWidth\", \"InsertWidth\",\n\tDEF_ENTRY_INSERT_WIDTH, offsetof(Entry, insertWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-invalidcommand\", \"invalidCommand\", \"InvalidCommand\",\n\tDEF_ENTRY_INVALIDCMD, offsetof(Entry, invalidCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-invcmd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-invalidcommand\", 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_ENTRY_JUSTIFY, TCL_INDEX_NONE, offsetof(Entry, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_STRING, \"-placeholder\", \"placeHolder\", \"PlaceHolder\",\n\tDEF_ENTRY_PLACEHOLDER, offsetof(Entry, placeholderObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-placeholderforeground\", \"placeholderForeground\",\n\t\"PlaceholderForeground\", DEF_ENTRY_PLACEHOLDERFG, TCL_INDEX_NONE,\n\toffsetof(Entry, placeholderColorPtr), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-readonlybackground\", \"readonlyBackground\",\n\t\"ReadonlyBackground\", DEF_ENTRY_READONLY_BG_COLOR, TCL_INDEX_NONE,\n\toffsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK,\n\tDEF_ENTRY_READONLY_BG_MONO, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_ENTRY_RELIEF, TCL_INDEX_NONE, offsetof(Entry, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\tDEF_ENTRY_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Entry, selBorder),\n\t0, DEF_ENTRY_SELECT_MONO, 0},\n    {TK_OPTION_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\",\n\t\"BorderWidth\", DEF_ENTRY_SELECT_BD_COLOR, offsetof(Entry, selBorderWidthObj),\n\tTCL_INDEX_NONE, 0, DEF_ENTRY_SELECT_BD_MONO, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\tDEF_ENTRY_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Entry, selFgColorPtr),\n\tTK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},\n    {TK_OPTION_STRING, \"-show\", \"show\", \"Show\",\n\tDEF_ENTRY_SHOW, offsetof(Entry, showCharObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_ENTRY_STATE, TCL_INDEX_NONE, offsetof(Entry, state),\n\t0, stateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_ENTRY_TAKE_FOCUS, offsetof(Entry, takeFocusObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_ENTRY_TEXT_VARIABLE, offsetof(Entry, textVarNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-validate\", \"validate\", \"Validate\",\n\tDEF_ENTRY_VALIDATE, TCL_INDEX_NONE, offsetof(Entry, validate),\n\t0, validateStrings, 0},\n    {TK_OPTION_STRING, \"-validatecommand\", \"validateCommand\",\"ValidateCommand\",\n\tNULL, offsetof(Entry, validateCmdObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-vcmd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-validatecommand\", 0},\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\tDEF_ENTRY_WIDTH, TCL_INDEX_NONE, offsetof(Entry, prefWidth), 0, 0, 0},\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tDEF_ENTRY_SCROLL_COMMAND, offsetof(Entry, scrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * Information used for Spinbox objv parsing.\n */\n\n#define DEF_SPINBOX_REPEAT_DELAY\t\"400\"\n#define DEF_SPINBOX_REPEAT_INTERVAL\t\"100\"\n\n#define DEF_SPINBOX_CMD\t\t\t\"\"\n\n#define DEF_SPINBOX_FROM\t\t\"0.0\"\n#define DEF_SPINBOX_TO\t\t\t\"0.0\"\n#define DEF_SPINBOX_INCREMENT\t\t\"1.0\"\n#define DEF_SPINBOX_FORMAT\t\t\"\"\n\n#define DEF_SPINBOX_VALUES\t\t\"\"\n#define DEF_SPINBOX_WRAP\t\t\"0\"\n\nstatic const Tk_OptionSpec sbOptSpec[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Background\",\n\tDEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(Spinbox, activeBorder),\n\t0, DEF_BUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_ENTRY_BG_COLOR, TCL_INDEX_NONE, offsetof(Entry, normalBorder),\n\t0, DEF_ENTRY_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_ENTRY_BORDER_WIDTH, offsetof(Entry, borderWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-buttonbackground\", \"buttonBackground\", \"Background\",\n\tDEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(Spinbox, buttonBorder),\n\t0, DEF_BUTTON_BG_MONO, 0},\n    {TK_OPTION_CURSOR, \"-buttoncursor\", \"buttonCursor\", \"Cursor\",\n\tDEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(Spinbox, bCursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-buttondownrelief\", \"buttonDownRelief\", \"Relief\",\n\tDEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(Spinbox, bdRelief), 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-buttonuprelief\", \"buttonUpRelief\", \"Relief\",\n\tDEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(Spinbox, buRelief), 0, 0, 0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_SPINBOX_CMD, offsetof(Spinbox, commandObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_ENTRY_CURSOR, TCL_INDEX_NONE, offsetof(Entry, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BORDER, \"-disabledbackground\", \"disabledBackground\",\n\t\"DisabledBackground\", DEF_ENTRY_DISABLED_BG_COLOR, TCL_INDEX_NONE,\n\toffsetof(Entry, disabledBorder), TK_OPTION_NULL_OK,\n\tDEF_ENTRY_DISABLED_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_ENTRY_DISABLED_FG, TCL_INDEX_NONE,\n\toffsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-exportselection\", \"exportSelection\",\n\t\"ExportSelection\", DEF_ENTRY_EXPORT_SELECTION, TCL_INDEX_NONE,\n\toffsetof(Entry, exportSelection), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_ENTRY_FONT, TCL_INDEX_NONE, offsetof(Entry, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_ENTRY_FG, TCL_INDEX_NONE, offsetof(Entry, fgColorPtr), 0, 0, 0},\n    {TK_OPTION_STRING, \"-format\", \"format\", \"Format\",\n\tDEF_SPINBOX_FORMAT, offsetof(Spinbox, reqFormatObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_DOUBLE, \"-from\", \"from\", \"From\",\n\tDEF_SPINBOX_FROM, TCL_INDEX_NONE, offsetof(Spinbox, fromValue), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_ENTRY_HIGHLIGHT_BG,\n\tTCL_INDEX_NONE, offsetof(Entry, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_ENTRY_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Entry, highlightColorPtr), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_ENTRY_HIGHLIGHT_WIDTH, offsetof(Entry, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-increment\", \"increment\", \"Increment\",\n\tDEF_SPINBOX_INCREMENT, TCL_INDEX_NONE, offsetof(Spinbox, increment), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-insertbackground\", \"insertBackground\", \"Foreground\",\n\tDEF_ENTRY_INSERT_BG, TCL_INDEX_NONE, offsetof(Entry, insertBorder), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-insertborderwidth\", \"insertBorderWidth\",\n\t\"BorderWidth\", DEF_ENTRY_INSERT_BD_COLOR, offsetof(Entry, insertBorderWidthObj),\n\tTCL_INDEX_NONE, 0, DEF_ENTRY_INSERT_BD_MONO, 0},\n    {TK_OPTION_INT, \"-insertofftime\", \"insertOffTime\", \"OffTime\",\n\tDEF_ENTRY_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOffTime),\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-insertontime\", \"insertOnTime\", \"OnTime\",\n\tDEF_ENTRY_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOnTime), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-insertwidth\", \"insertWidth\", \"InsertWidth\",\n\tDEF_ENTRY_INSERT_WIDTH, offsetof(Entry, insertWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-invalidcommand\", \"invalidCommand\", \"InvalidCommand\",\n\tDEF_ENTRY_INVALIDCMD, offsetof(Entry, invalidCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-invcmd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-invalidcommand\", 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_ENTRY_JUSTIFY, TCL_INDEX_NONE, offsetof(Entry, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_STRING, \"-placeholder\", \"placeHolder\", \"PlaceHolder\",\n\tDEF_ENTRY_PLACEHOLDER, offsetof(Entry, placeholderObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-placeholderforeground\", \"placeholderForeground\",\n\t\"PlaceholderForeground\", DEF_ENTRY_PLACEHOLDERFG, TCL_INDEX_NONE,\n\toffsetof(Entry, placeholderColorPtr), 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_ENTRY_RELIEF, TCL_INDEX_NONE, offsetof(Entry, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-readonlybackground\", \"readonlyBackground\",\n\t\"ReadonlyBackground\", DEF_ENTRY_READONLY_BG_COLOR, TCL_INDEX_NONE,\n\toffsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK,\n\tDEF_ENTRY_READONLY_BG_MONO, 0},\n    {TK_OPTION_INT, \"-repeatdelay\", \"repeatDelay\", \"RepeatDelay\",\n\tDEF_SPINBOX_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(Spinbox, repeatDelay),\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-repeatinterval\", \"repeatInterval\", \"RepeatInterval\",\n\tDEF_SPINBOX_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(Spinbox, repeatInterval),\n\t0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\tDEF_ENTRY_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Entry, selBorder),\n\t0, DEF_ENTRY_SELECT_MONO, 0},\n    {TK_OPTION_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\",\n\t\"BorderWidth\", DEF_ENTRY_SELECT_BD_COLOR, offsetof(Entry, selBorderWidthObj),\n\tTCL_INDEX_NONE, 0, DEF_ENTRY_SELECT_BD_MONO, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\tDEF_ENTRY_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Entry, selFgColorPtr),\n\tTK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_ENTRY_STATE, TCL_INDEX_NONE, offsetof(Entry, state),\n\t0, stateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_ENTRY_TAKE_FOCUS, offsetof(Entry, takeFocusObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_ENTRY_TEXT_VARIABLE, offsetof(Entry, textVarNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_DOUBLE, \"-to\", \"to\", \"To\",\n\tDEF_SPINBOX_TO, TCL_INDEX_NONE, offsetof(Spinbox, toValue), 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-validate\", \"validate\", \"Validate\",\n\tDEF_ENTRY_VALIDATE, TCL_INDEX_NONE, offsetof(Entry, validate),\n\t0, validateStrings, 0},\n    {TK_OPTION_STRING, \"-validatecommand\", \"validateCommand\",\"ValidateCommand\",\n\tNULL, offsetof(Entry, validateCmdObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-values\", \"values\", \"Values\",\n\tDEF_SPINBOX_VALUES, offsetof(Spinbox, valueObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-vcmd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-validatecommand\", 0},\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\tDEF_ENTRY_WIDTH, TCL_INDEX_NONE, offsetof(Entry, prefWidth), 0, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-wrap\", \"wrap\", \"Wrap\",\n\tDEF_SPINBOX_WRAP, TCL_INDEX_NONE, offsetof(Spinbox, wrap), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tDEF_ENTRY_SCROLL_COMMAND, offsetof(Entry, scrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * The following tables define the entry widget commands (and sub-commands)\n * and map the indexes into the string tables into enumerated types used to\n * dispatch the entry widget command.\n */\n\nstatic const char *const entryCmdNames[] = {\n    \"bbox\", \"cget\", \"configure\", \"delete\", \"get\", \"icursor\", \"index\",\n    \"insert\", \"scan\", \"selection\", \"validate\", \"xview\", NULL\n};\n\nenum entryCmd {\n    COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE,\n    COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT,\n    COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW\n};\n\nstatic const char *const selCmdNames[] = {\n    \"adjust\", \"clear\", \"from\", \"present\", \"range\", \"to\", NULL\n};\n\nenum selCmd {\n    SELECTION_ADJUST, SELECTION_CLEAR, SELECTION_FROM,\n    SELECTION_PRESENT, SELECTION_RANGE, SELECTION_TO\n};\n\n/*\n * The following tables define the spinbox widget commands (and sub-commands)\n * and map the indexes into the string tables into enumerated types used to\n * dispatch the spinbox widget command.\n */\n\nstatic const char *const sbCmdNames[] = {\n    \"bbox\", \"cget\", \"configure\", \"delete\", \"get\", \"icursor\", \"identify\",\n    \"index\", \"insert\", \"invoke\", \"scan\", \"selection\", \"set\",\n    \"validate\", \"xview\", NULL\n};\n\nenum sbCmd {\n    SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE,\n    SB_CMD_GET, SB_CMD_ICURSOR, SB_CMD_IDENTIFY, SB_CMD_INDEX,\n    SB_CMD_INSERT, SB_CMD_INVOKE, SB_CMD_SCAN, SB_CMD_SELECTION,\n    SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW\n};\n\nstatic const char *const sbSelCmdNames[] = {\n    \"adjust\", \"clear\", \"element\", \"from\", \"present\", \"range\", \"to\", NULL\n};\n\nenum sbselCmd {\n    SB_SEL_ADJUST, SB_SEL_CLEAR, SB_SEL_ELEMENT, SB_SEL_FROM,\n    SB_SEL_PRESENT, SB_SEL_RANGE, SB_SEL_TO\n};\n\n/*\n * Extra for selection of elements\n */\n\n/*\n * This is the string array corresponding to the enum in selelement. If you\n * modify them, you must modify the strings here.\n */\n\nstatic const char *const selElementNames[] = {\n    \"buttondown\", \"buttonup\", \"none\", NULL, \"entry\"\n};\n\n/*\n * Flags for GetEntryIndex function:\n */\n\n#define ZERO_OK\t\t\t1\n#define LAST_PLUS_ONE_OK\t2\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tConfigureEntry(Tcl_Interp *interp, Entry *entryPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tDeleteChars(Entry *entryPtr, Tcl_Size index, Tcl_Size count);\nstatic Tcl_FreeProc\tDestroyEntry;\nstatic void\t\tDisplayEntry(void *clientData);\nstatic void\t\tEntryBlinkProc(void *clientData);\nstatic void\t\tEntryCmdDeletedProc(void *clientData);\nstatic void\t\tEntryComputeGeometry(Entry *entryPtr);\nstatic void\t\tEntryEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEntryFocusProc(Entry *entryPtr, int gotFocus);\nstatic Tcl_Size\tEntryFetchSelection(void *clientData, Tcl_Size offset,\n\t\t\t    char *buffer, Tcl_Size maxBytes);\nstatic void\t\tEntryLostSelection(void *clientData);\nstatic void\t\tEventuallyRedraw(Entry *entryPtr);\nstatic void\t\tEntryScanTo(Entry *entryPtr, int y);\nstatic void\t\tEntrySetValue(Entry *entryPtr, const char *value);\nstatic void\t\tEntrySelectTo(Entry *entryPtr, Tcl_Size index);\nstatic char *\t\tEntryTextVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic void\t\tEntryUpdateScrollbar(Entry *entryPtr);\nstatic int\t\tEntryValidate(Entry *entryPtr, char *cmd);\nstatic int\t\tEntryValidateChange(Entry *entryPtr, const char *change,\n\t\t\t    const char *newStr, Tcl_Size index, int type);\nstatic void\t\tExpandPercents(Entry *entryPtr, const char *before,\n\t\t\t    const char *change, const char *newStr, Tcl_Size index,\n\t\t\t    int type, Tcl_DString *dsPtr);\nstatic int\t\tEntryValueChanged(Entry *entryPtr,\n\t\t\t    const char *newValue);\nstatic void\t\tEntryVisibleRange(Entry *entryPtr,\n\t\t\t    double *firstPtr, double *lastPtr);\nstatic Tcl_ObjCmdProc2 EntryWidgetObjCmd;\nstatic void\t\tEntryWorldChanged(void *instanceData);\nstatic int\t\tGetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,\n\t\t\t    Tcl_Obj *indexObj, Tcl_Size *indexPtr);\nstatic int\t\tInsertChars(Entry *entryPtr, Tcl_Size index, Tcl_Obj *obj);\n\n/*\n * These forward declarations are the spinbox specific ones:\n */\n\nstatic Tcl_ObjCmdProc2 SpinboxWidgetObjCmd;\nstatic int\t\tGetSpinboxElement(Spinbox *sbPtr, int x, int y);\nstatic int\t\tSpinboxInvoke(Tcl_Interp *interp, Spinbox *sbPtr,\n\t\t\t    int element);\nstatic int\t\tComputeFormat(Spinbox *sbPtr);\n\n/*\n * The structure below defines widget class behavior by means of functions\n * that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs entryClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    EntryWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_EntryObjCmd --\n *\n *\tThis function is invoked to process the \"entry\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_EntryObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Entry *entryPtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n    char *tmp;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, Tk will return the cached value.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, entryOptSpec);\n\n    /*\n     * Initialize the fields of the structure that won't be initialized by\n     * ConfigureEntry, or that ConfigureEntry requires to be initialized\n     * already (e.g. resource pointers). Only the non-NULL/0 data must be\n     * initialized as memset covers the rest.\n     */\n\n    entryPtr = (Entry *)Tcl_Alloc(sizeof(Entry));\n    memset(entryPtr, 0, sizeof(Entry));\n\n    entryPtr->tkwin\t\t= tkwin;\n    entryPtr->display\t\t= Tk_Display(tkwin);\n    entryPtr->interp\t\t= interp;\n    entryPtr->widgetCmd\t\t= Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(entryPtr->tkwin), EntryWidgetObjCmd, entryPtr,\n\t    EntryCmdDeletedProc);\n    entryPtr->optionTable\t= optionTable;\n    entryPtr->type\t\t= TK_ENTRY;\n    tmp\t\t\t\t= (char *)Tcl_Alloc(1);\n    tmp[0]\t\t\t= '\\0';\n    entryPtr->string\t\t= tmp;\n    entryPtr->selectFirst\t= TCL_INDEX_NONE;\n    entryPtr->selectLast\t= TCL_INDEX_NONE;\n\n    entryPtr->cursor\t\t= NULL;\n    entryPtr->exportSelection\t= true;\n    entryPtr->justify\t\t= TK_JUSTIFY_LEFT;\n    entryPtr->relief\t\t= TK_RELIEF_FLAT;\n    entryPtr->state\t\t= STATE_NORMAL;\n    entryPtr->displayString\t= entryPtr->string;\n    entryPtr->inset\t\t= XPAD;\n    entryPtr->textGC\t\t= NULL;\n    entryPtr->selTextGC\t\t= NULL;\n    entryPtr->highlightGC\t= NULL;\n    entryPtr->avgWidth\t\t= 1;\n    entryPtr->validate\t\t= VALIDATE_NONE;\n\n    entryPtr->placeholderGC\t= NULL;\n\n    /*\n     * Keep a hold of the associated tkwin until we destroy the entry,\n     * otherwise Tk might free it while we still need it.\n     */\n\n    Tcl_Preserve(entryPtr->tkwin);\n\n    Tk_SetClass(entryPtr->tkwin, \"Entry\");\n    Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);\n    Tk_CreateEventHandler(entryPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    EntryEventProc, entryPtr);\n    Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,\n\t    EntryFetchSelection, entryPtr, XA_STRING);\n\n    if ((Tk_InitOptions(interp, entryPtr, optionTable, tkwin)\n\t    != TCL_OK) ||\n\t    (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) {\n\tTk_DestroyWindow(entryPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(entryPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EntryWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEntryWidgetObjCmd(\n    void *clientData,\t/* Information about entry widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n    int cmdIndex, selIndex, result;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the widget command by looking up the second token in the list of\n     * valid command names.\n     */\n\n    result = Tcl_GetIndexFromObj(interp, objv[1], entryCmdNames, \"option\", 0,\n\t    &cmdIndex);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    Tcl_Preserve(entryPtr);\n    switch ((enum entryCmd) cmdIndex) {\n    case COMMAND_BBOX: {\n\tTcl_Size index;\n\tint x, y, width, height;\n\tTcl_Obj *bbox[4];\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif ((index == entryPtr->numChars) && (index + 1 > 1)) {\n\t    index--;\n\t}\n\tTk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);\n\tbbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX);\n\tbbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY);\n\tbbox[2] = Tcl_NewWideIntObj(width);\n\tbbox[3] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));\n\tbreak;\n    }\n\n    case COMMAND_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    goto error;\n\t}\n\n\tobjPtr = Tk_GetOptionValue(interp, entryPtr,\n\t\tentryPtr->optionTable, objv[2], entryPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n\n    case COMMAND_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, entryPtr,\n\t\t    entryPtr->optionTable,\n\t\t    (objc == 3) ? objv[2] : NULL,\n\t\t    entryPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);\n\t}\n\tbreak;\n\n    case COMMAND_DELETE: {\n\tTcl_Size first, last;\n\tint code;\n\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"firstIndex ?lastIndex?\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&first) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (objc == 3) {\n\t    last = first + 1;\n\t} else if (GetEntryIndex(interp, entryPtr, objv[3],\n\t\t&last) != TCL_OK) {\n\t    goto error;\n\t}\n\tif ((last >= first) && (entryPtr->state == STATE_NORMAL)) {\n\t    code = DeleteChars(entryPtr, first, last - first);\n\t    if (code != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n    }\n\n    case COMMAND_GET:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, TCL_INDEX_NONE));\n\tbreak;\n\n    case COMMAND_ICURSOR:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pos\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&entryPtr->insertPos) != TCL_OK) {\n\t    goto error;\n\t}\n\tEventuallyRedraw(entryPtr);\n\tbreak;\n\n    case COMMAND_INDEX: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"string\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(index));\n\tbreak;\n    }\n\n    case COMMAND_INSERT: {\n\tTcl_Size index;\n\tint code;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index text\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (entryPtr->state == STATE_NORMAL) {\n\t    code = InsertChars(entryPtr, index, objv[3]);\n\t    if (code != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n    }\n\n    case COMMAND_SCAN: {\n\tint x;\n\tconst char *minorCmd;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"mark|dragto x\");\n\t    goto error;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tminorCmd = Tcl_GetString(objv[2]);\n\tif (minorCmd[0] == 'm'\n\t\t&& (strncmp(minorCmd, \"mark\", strlen(minorCmd)) == 0)) {\n\t    entryPtr->scanMarkX = x;\n\t    entryPtr->scanMarkIndex = entryPtr->leftIndex;\n\t} else if ((minorCmd[0] == 'd')\n\t\t&& (strncmp(minorCmd, \"dragto\", strlen(minorCmd)) == 0)) {\n\t    EntryScanTo(entryPtr, x);\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad scan option \\\"%s\\\": must be dragto or mark\",\n\t\t    minorCmd));\n\t    Tcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"scan option\",\n\t\t    minorCmd, (char *)NULL);\n\t    goto error;\n\t}\n\tbreak;\n    }\n\n    case COMMAND_SELECTION: {\n\tTcl_Size index, index2;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option ?index?\");\n\t    goto error;\n\t}\n\n\t/*\n\t * Parse the selection sub-command, using the command table\n\t * \"selCmdNames\" defined above.\n\t */\n\n\tresult = Tcl_GetIndexFromObj(interp, objv[2], selCmdNames,\n\t\t\"selection option\", 0, &selIndex);\n\tif (result != TCL_OK) {\n\t    goto error;\n\t}\n\n\t/*\n\t * Disabled entries don't allow the selection to be modified, but\n\t * 'selection present' must return a boolean.\n\t */\n\n\tif ((entryPtr->state == STATE_DISABLED)\n\t\t&& (selIndex != SELECTION_PRESENT)) {\n\t    goto done;\n\t}\n\n\tswitch (selIndex) {\n\tcase SELECTION_ADJUST:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (entryPtr->selectFirst != TCL_INDEX_NONE) {\n\t\tTcl_Size half1, half2;\n\n\t\thalf1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;\n\t\thalf2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;\n\t\tif (index < half1) {\n\t\t    entryPtr->selectAnchor = entryPtr->selectLast;\n\t\t} else if (index > half2) {\n\t\t    entryPtr->selectAnchor = entryPtr->selectFirst;\n\t\t} else {\n\t\t    /*\n\t\t     * We're at about the halfway point in the selection; just\n\t\t     * keep the existing anchor.\n\t\t     */\n\t\t}\n\t    }\n\t    EntrySelectTo(entryPtr, index);\n\t    break;\n\n\tcase SELECTION_CLEAR:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tgoto error;\n\t    }\n\t    if (entryPtr->selectFirst != TCL_INDEX_NONE) {\n\t\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\t\tentryPtr->selectLast = TCL_INDEX_NONE;\n\t\tEventuallyRedraw(entryPtr);\n\t    }\n\t    goto done;\n\n\tcase SELECTION_FROM:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    entryPtr->selectAnchor = index;\n\t    break;\n\n\tcase SELECTION_PRESENT:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewBooleanObj(entryPtr->selectFirst != TCL_INDEX_NONE));\n\t    goto done;\n\n\tcase SELECTION_RANGE:\n\t    if (objc != 5) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"start end\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr, objv[3],\n\t\t    &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr, objv[4],\n\t\t    &index2) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (index >= index2) {\n\t\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\t\tentryPtr->selectLast = TCL_INDEX_NONE;\n\t    } else {\n\t\tentryPtr->selectFirst = index;\n\t\tentryPtr->selectLast = index2;\n\t    }\n\t    if (!(entryPtr->flags & GOT_SELECTION)\n\t\t    && (entryPtr->exportSelection)\n\t\t    && (!Tcl_IsSafe(entryPtr->interp))) {\n\t\tTk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,\n\t\t\tEntryLostSelection, entryPtr);\n\t\tentryPtr->flags |= GOT_SELECTION;\n\t    }\n\t    EventuallyRedraw(entryPtr);\n\t    break;\n\n\tcase SELECTION_TO:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    EntrySelectTo(entryPtr, index);\n\t    break;\n\t}\n\tbreak;\n    }\n\n    case COMMAND_VALIDATE: {\n\tint code;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    goto error;\n\t}\n\tselIndex = entryPtr->validate;\n\tentryPtr->validate = VALIDATE_ALL;\n\tcode = EntryValidateChange(entryPtr, NULL, entryPtr->string,\n\t\t-1, VALIDATE_FORCED);\n\tif (entryPtr->validate != VALIDATE_NONE) {\n\t    entryPtr->validate = selIndex;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));\n\tbreak;\n    }\n\n    case COMMAND_XVIEW: {\n\tTcl_Size index;\n\n\tif (objc == 2) {\n\t    double first, last;\n\t    Tcl_Obj *span[2];\n\n\t    EntryVisibleRange(entryPtr, &first, &last);\n\t    span[0] = Tcl_NewDoubleObj(first);\n\t    span[1] = Tcl_NewDoubleObj(last);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, span));\n\t    goto done;\n\t} else if (objc == 3) {\n\t    if (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t    &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t} else {\n\t    double fraction;\n\t    int count;\n\n\t    index = entryPtr->leftIndex;\n\t    switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,\n\t\t    &count)) {\n\t    case TK_SCROLL_MOVETO:\n\t\tindex = (int) ((fraction * (double)entryPtr->numChars) + 0.5);\n\t\tbreak;\n\t    case TK_SCROLL_PAGES: {\n\t\tint charsPerPage;\n\n\t\tcharsPerPage = ((Tk_Width(entryPtr->tkwin)\n\t\t\t- 2 * entryPtr->inset) / entryPtr->avgWidth) - 2;\n\t\tif (charsPerPage < 1) {\n\t\t    charsPerPage = 1;\n\t\t}\n\t\tindex += count * charsPerPage;\n\t\tbreak;\n\t    }\n\t    case TK_SCROLL_UNITS:\n\t\tindex += count;\n\t\tbreak;\n\t    default:\n\t\tgoto error;\n\t    }\n\t}\n\tif (index >= entryPtr->numChars) {\n\t    index = entryPtr->numChars - 1;\n\t}\n\tif ((int)index < 0) {\n\t    index = 0;\n\t}\n\tentryPtr->leftIndex = index;\n\tentryPtr->flags |= UPDATE_SCROLLBAR;\n\tEntryComputeGeometry(entryPtr);\n\tEventuallyRedraw(entryPtr);\n\tbreak;\n    }\n    }\n\n  done:\n    Tcl_Release(entryPtr);\n    return result;\n\n  error:\n    Tcl_Release(entryPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyEntry --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of an entry at a safe time (when no-one is\n *\tusing it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the entry is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyEntry(\n    void *memPtr)\t\t/* Info about entry widget. */\n{\n    Entry *entryPtr = (Entry *)memPtr;\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    Tcl_Free((void *)entryPtr->string);\n    if (entryPtr->textVarNameObj != NULL) {\n\tTcl_UntraceVar2(entryPtr->interp, Tcl_GetString(entryPtr->textVarNameObj),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tEntryTextVarProc, entryPtr);\n\tentryPtr->flags &= ~ENTRY_VAR_TRACED;\n    }\n    if (entryPtr->textGC != NULL) {\n\tTk_FreeGC(entryPtr->display, entryPtr->textGC);\n    }\n    if (entryPtr->selTextGC != NULL) {\n\tTk_FreeGC(entryPtr->display, entryPtr->selTextGC);\n    }\n    Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);\n    if (entryPtr->displayString != entryPtr->string) {\n\tTcl_Free((void *)entryPtr->displayString);\n    }\n    if (entryPtr->type == TK_SPINBOX) {\n\tSpinbox *sbPtr = (Spinbox *) entryPtr;\n\n\tif (sbPtr->listObj != NULL) {\n\t    Tcl_DecrRefCount(sbPtr->listObj);\n\t    sbPtr->listObj = NULL;\n\t}\n\tif (sbPtr->formatBuf) {\n\t    Tcl_Free(sbPtr->formatBuf);\n\t}\n    }\n    Tk_FreeTextLayout(entryPtr->textLayout);\n    Tk_FreeConfigOptions(entryPtr, entryPtr->optionTable,\n\t    entryPtr->tkwin);\n    Tcl_Release(entryPtr->tkwin);\n    entryPtr->tkwin = NULL;\n\n    Tcl_Free(entryPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureEntry --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) an entry\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor entryPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureEntry(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Entry *entryPtr,\t\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_SavedOptions savedOptions;\n    Tk_3DBorder border;\n    Tcl_Obj *errorResult = NULL;\n    Spinbox *sbPtr = (Spinbox *) entryPtr;\n\t\t\t\t/* Only used when this widget is of type\n\t\t\t\t * TK_SPINBOX */\n    Tcl_Obj *oldValues = NULL;\n    Tcl_Obj *oldFormat = NULL;\n    int error;\n    int oldExport = 0;\n    int valuesChanged = 0;\n    double oldFrom = 0.0;\n    double oldTo = 0.0;\n    int code;\n    size_t formatSpace = TCL_DOUBLE_SPACE;\n    int borderWidth, highlightWidth, insertWidth;\n    int insertBorderWidth, selBorderWidth;\n\n    /*\n     * Eliminate any existing trace on a variable monitored by the entry.\n     */\n\n    if ((entryPtr->textVarNameObj != NULL)\n\t    && (entryPtr->flags & ENTRY_VAR_TRACED)) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(entryPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tEntryTextVarProc, entryPtr);\n\tentryPtr->flags &= ~ENTRY_VAR_TRACED;\n    }\n\n    /*\n     * Store old values that we need to effect certain behavior if they change\n     * value.\n     */\n\n    oldExport = (entryPtr->exportSelection) && (!Tcl_IsSafe(entryPtr->interp));\n    if (entryPtr->type == TK_SPINBOX) {\n\toldValues = sbPtr->valueObj;\n\toldFormat = sbPtr->reqFormatObj;\n\toldFrom = sbPtr->fromValue;\n\toldTo = sbPtr->toValue;\n    }\n\n    for (error = 0; error <= 1; error++) {\n\tif (!error) {\n\t    /*\n\t     * First pass: set options to new values.\n\t     */\n\n\t    if (Tk_SetOptions(interp, entryPtr,\n\t\t    entryPtr->optionTable, objc, objv,\n\t\t    entryPtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * Second pass: restore options to old values.\n\t     */\n\n\t    errorResult = Tcl_GetObjResult(interp);\n\t    Tcl_IncrRefCount(errorResult);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t}\n\n\t/*\n\t * A few other options also need special processing, such as parsing\n\t * the geometry and setting the background from a 3-D border.\n\t */\n\n\tif ((entryPtr->state == STATE_DISABLED) &&\n\t\t(entryPtr->disabledBorder != NULL)) {\n\t    border = entryPtr->disabledBorder;\n\t} else if ((entryPtr->state == STATE_READONLY) &&\n\t\t(entryPtr->readonlyBorder != NULL)) {\n\t    border = entryPtr->readonlyBorder;\n\t} else {\n\t    border = entryPtr->normalBorder;\n\t}\n\tTk_SetBackgroundFromBorder(entryPtr->tkwin, border);\n\n\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->borderWidthObj, &borderWidth);\n\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->highlightWidthObj, &highlightWidth);\n\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->insertBorderWidthObj, &insertBorderWidth);\n\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->insertWidthObj, &insertWidth);\n\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->selBorderWidthObj, &selBorderWidth);\n\n\tif (entryPtr->type == TK_SPINBOX) {\n\t    if (sbPtr->fromValue > sbPtr->toValue) {\n\t\t/*\n\t\t * Swap -from and -to values.\n\t\t */\n\n\t\tdouble tmpFromTo = sbPtr->fromValue;\n\n\t\tsbPtr->fromValue = sbPtr->toValue;\n\t\tsbPtr->toValue = tmpFromTo;\n\t    }\n\n\t    if (sbPtr->reqFormatObj && (oldFormat != sbPtr->reqFormatObj)) {\n\t\t/*\n\t\t * Make sure that the given format is somewhat correct, and\n\t\t * calculate the minimum space we'll need for the values as\n\t\t * strings.\n\t\t */\n\n\t\tint min, max;\n\t\tsize_t formatLen;\n\t\tchar fbuf[4], *fmt = Tcl_GetString(sbPtr->reqFormatObj);\n\n\t\tformatLen = strlen(fmt);\n\t\tif ((fmt[0] != '%') || (fmt[formatLen-1] != 'f')) {\n\t\tbadFormatOpt:\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad spinbox format specifier \\\"%s\\\"\",\n\t\t\t    Tcl_GetString(sbPtr->reqFormatObj)));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"SPINBOX\", \"FORMAT_SANITY\",\n\t\t\t    (char *)NULL);\n\t\t    continue;\n\t\t}\n\t\tif ((sscanf(fmt, \"%%%d.%d%[f]\", &min, &max, fbuf) == 3)\n\t\t\t&& (max >= 0)) {\n\t\t    formatSpace = min + max + 1;\n\t\t} else if (((sscanf(fmt, \"%%.%d%[f]\", &min, fbuf) == 2)\n\t\t\t|| (sscanf(fmt, \"%%%d%[f]\", &min, fbuf) == 2)\n\t\t\t|| (sscanf(fmt, \"%%%d.%[f]\", &min, fbuf) == 2))\n\t\t\t&& (min >= 0)) {\n\t\t    formatSpace = min + 1;\n\t\t} else {\n\t\t    goto badFormatOpt;\n\t\t}\n\t\tif (formatSpace < TCL_DOUBLE_SPACE) {\n\t\t    formatSpace = TCL_DOUBLE_SPACE;\n\t\t}\n\t\tsbPtr->formatBuf = (char *)Tcl_Realloc(sbPtr->formatBuf, formatSpace);\n\n\t\t/*\n\t\t * We perturb the value of oldFrom to allow us to go into the\n\t\t * branch below that will reformat the displayed value.\n\t\t */\n\n\t\toldFrom = sbPtr->fromValue - 1;\n\t    }\n\n\t    /*\n\t     * See if we have to rearrange our listObj data.\n\t     */\n\n\t    if (oldValues != sbPtr->valueObj) {\n\t\tif (sbPtr->listObj != NULL) {\n\t\t    Tcl_DecrRefCount(sbPtr->listObj);\n\t\t}\n\t\tsbPtr->listObj = NULL;\n\t\tif (sbPtr->valueObj != NULL) {\n\t\t    Tcl_Obj *newObjPtr;\n\t\t    Tcl_Size nelems;\n\n\t\t    newObjPtr = sbPtr->valueObj;\n\t\t    if (Tcl_ListObjLength(interp, newObjPtr, &nelems)\n\t\t\t    != TCL_OK) {\n\t\t\tvaluesChanged = -1;\n\t\t\tcontinue;\n\t\t    }\n\t\t    sbPtr->listObj = newObjPtr;\n\t\t    Tcl_IncrRefCount(sbPtr->listObj);\n\t\t    sbPtr->nElements = nelems;\n\t\t    sbPtr->eIndex = 0;\n\t\t    valuesChanged++;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Restart the cursor timing sequence in case the on-time or off-time\n\t * just changed. Set validate temporarily to none, so the configure\n\t * doesn't cause it to be triggered.\n\t */\n\n\tif (entryPtr->flags & GOT_FOCUS) {\n\t    int validate = entryPtr->validate;\n\n\t    entryPtr->validate = VALIDATE_NONE;\n\t    EntryFocusProc(entryPtr, 1);\n\t    entryPtr->validate = validate;\n\t}\n\n\t/*\n\t * Claim the selection if we've suddenly started exporting it.\n\t */\n\n\tif (entryPtr->exportSelection && (!oldExport)\n\t\t&& (!Tcl_IsSafe(entryPtr->interp))\n\t\t&& (entryPtr->selectFirst != TCL_INDEX_NONE)\n\t\t&& !(entryPtr->flags & GOT_SELECTION)) {\n\t    Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,\n\t\t    entryPtr);\n\t    entryPtr->flags |= GOT_SELECTION;\n\t}\n\n\t/*\n\t * Recompute the window's geometry and arrange for it to be\n\t * redisplayed.\n\t */\n\n\tTk_SetInternalBorder(entryPtr->tkwin,\n\t\tborderWidth + highlightWidth);\n\tentryPtr->inset = highlightWidth\n\t\t+ borderWidth + XPAD;\n\tbreak;\n    }\n    if (!error) {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n\n    /*\n     * If the entry is tied to the value of a variable, create the variable if\n     * it doesn't exist, and set the entry's value from the variable's value.\n     */\n\n    if (entryPtr->textVarNameObj != NULL) {\n\tconst char *value;\n\n\tvalue = Tcl_GetVar2(interp, Tcl_GetString(entryPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n\tif (value == NULL) {\n\n\t    /*\n\t     * Since any trace on the textvariable was eliminated above,\n\t     * the only possible reason for EntryValueChanged to return\n\t     * an error is that the textvariable lives in a namespace\n\t     * that does not (yet) exist. Indeed, namespaces are not\n\t     * automatically created as needed. Don't trap this error\n\t     * here, better do it below when attempting to trace the\n\t     * variable.\n\t     */\n\n\t    EntryValueChanged(entryPtr, NULL);\n\t} else {\n\t    EntrySetValue(entryPtr, value);\n\t}\n    }\n\n    if (entryPtr->type == TK_SPINBOX) {\n\tComputeFormat(sbPtr);\n\n\tif (valuesChanged > 0) {\n\t    Tcl_Obj *objPtr;\n\n\t    /*\n\t     * No check for error return, because there shouldn't be one given\n\t     * the check for valid list above.\n\t     */\n\n\t    Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);\n\n\t    /*\n\t     * No check for error return here as well, because any possible\n\t     * error will be trapped below when attempting tracing.\n\t     */\n\n\t    EntryValueChanged(entryPtr, Tcl_GetString(objPtr));\n\t} else if ((sbPtr->valueObj == NULL)\n\t\t&& !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)\n\t\t&& (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)\n\t\t\t|| !DOUBLES_EQ(sbPtr->toValue, oldTo))) {\n\t    /*\n\t     * If the valueStr is empty and -from && -to are specified, check\n\t     * to see if the current string is within the range. If not, it\n\t     * will be constrained to the nearest edge. If the current string\n\t     * isn't a double value, we set it to -from.\n\t     */\n\n\t    double dvalue;\n\n\t    if (sscanf(entryPtr->string, \"%lf\", &dvalue) <= 0) {\n\t\t/* Scan failure */\n\t\tdvalue = sbPtr->fromValue;\n\t    } else if (dvalue > sbPtr->toValue) {\n\t\tdvalue = sbPtr->toValue;\n\t    } else if (dvalue < sbPtr->fromValue) {\n\t\tdvalue = sbPtr->fromValue;\n\t    }\n\t    snprintf(sbPtr->formatBuf, formatSpace, sbPtr->valueFormat, dvalue);\n\n\t    /*\n\t     * No check for error return here as well, because any possible\n\t     * error will be trapped below when attempting tracing.\n\t     */\n\n\t    EntryValueChanged(entryPtr, sbPtr->formatBuf);\n\t}\n    }\n\n    /*\n     * Set up a trace on the variable's value after we've possibly constrained\n     * the value according to new -from/-to values.\n     */\n\n    if ((entryPtr->textVarNameObj != NULL)\n\t    && !(entryPtr->flags & ENTRY_VAR_TRACED)) {\n\tcode = Tcl_TraceVar2(interp, Tcl_GetString(entryPtr->textVarNameObj),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tEntryTextVarProc, entryPtr);\n\tif (code != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tentryPtr->flags |= ENTRY_VAR_TRACED;\n    }\n\n    EntryWorldChanged(entryPtr);\n    if (error) {\n\tTcl_SetObjResult(interp, errorResult);\n\tTcl_DecrRefCount(errorResult);\n\treturn TCL_ERROR;\n    } else {\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * EntryWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEntry will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nEntryWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC gc = NULL;\n    unsigned long mask;\n    Tk_3DBorder border;\n    XColor *colorPtr;\n    Entry *entryPtr = (Entry *)instanceData;\n\n    entryPtr->avgWidth = Tk_TextWidth(entryPtr->tkfont, \"0\", 1);\n    if (entryPtr->avgWidth == 0) {\n\tentryPtr->avgWidth = 1;\n    }\n\n    if (entryPtr->type == TK_SPINBOX) {\n\t/*\n\t * Compute the button width for a spinbox\n\t */\n\n\tentryPtr->xWidth = entryPtr->avgWidth + 2 * (1+XPAD);\n\tif (entryPtr->xWidth < 11) {\n\t    entryPtr->xWidth = 11; /* we want a min visible size */\n\t}\n    }\n\n    /*\n     * Default background and foreground are from the normal state. In a\n     * disabled state, both of those may be overridden; in the readonly state,\n     * the background may be overridden.\n     */\n\n    border = entryPtr->normalBorder;\n    colorPtr = entryPtr->fgColorPtr;\n    switch (entryPtr->state) {\n    case STATE_DISABLED:\n\tif (entryPtr->disabledBorder != NULL) {\n\t    border = entryPtr->disabledBorder;\n\t}\n\tif (entryPtr->dfgColorPtr != NULL) {\n\t    colorPtr = entryPtr->dfgColorPtr;\n\t}\n\tbreak;\n    case STATE_READONLY:\n\tif (entryPtr->readonlyBorder != NULL) {\n\t    border = entryPtr->readonlyBorder;\n\t}\n\tbreak;\n    }\n\n    Tk_SetBackgroundFromBorder(entryPtr->tkwin, border);\n    gcValues.foreground = colorPtr->pixel;\n    gcValues.font = Tk_FontId(entryPtr->tkfont);\n    gcValues.graphics_exposures = False;\n    mask = GCForeground | GCFont | GCGraphicsExposures;\n    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);\n    if (entryPtr->textGC != NULL) {\n\tTk_FreeGC(entryPtr->display, entryPtr->textGC);\n    }\n    entryPtr->textGC = gc;\n\n    if (entryPtr->placeholderColorPtr != NULL) {\n\tgcValues.foreground = entryPtr->placeholderColorPtr->pixel;\n    }\n    mask = GCForeground | GCFont | GCGraphicsExposures;\n    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);\n    if (entryPtr->placeholderGC != NULL) {\n\tTk_FreeGC(entryPtr->display, entryPtr->placeholderGC);\n    }\n    entryPtr->placeholderGC = gc;\n\n    if (entryPtr->selFgColorPtr != NULL) {\n\tgcValues.foreground = entryPtr->selFgColorPtr->pixel;\n    } else {\n\tgcValues.foreground = colorPtr->pixel;\n    }\n    gcValues.font = Tk_FontId(entryPtr->tkfont);\n    mask = GCForeground | GCFont;\n    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);\n    if (entryPtr->selTextGC != NULL) {\n\tTk_FreeGC(entryPtr->display, entryPtr->selTextGC);\n    }\n    entryPtr->selTextGC = gc;\n\n    /*\n     * Recompute the window's geometry and arrange for it to be redisplayed.\n     */\n\n    EntryComputeGeometry(entryPtr);\n    entryPtr->flags |= UPDATE_SCROLLBAR;\n    EventuallyRedraw(entryPtr);\n}\n\f\n#ifndef MAC_OSX_TK\n/*\n *--------------------------------------------------------------\n *\n * TkpDrawEntryBorderAndFocus --\n *\n *\tStub function for Tk on platforms other than Aqua\n *\t(Windows and X11), which do not draw native entry borders.\n *\tSee macosx/tkMacOSXEntry.c for function definition in Tk Aqua.\n *\n * Results:\n *\tReturns 0.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nbool\nTkpDrawEntryBorderAndFocus(\n    TCL_UNUSED(Entry *),\n    TCL_UNUSED(Drawable),\n    TCL_UNUSED(bool))\n{\n    return false;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDrawSpinboxButtons --\n *\n *\tStub function for Tk on platforms other than Aqua\n *\t(Windows and X11), which do not draw native spinbox buttons.\n *\tSee macosx/tkMacOSXEntry.c for function definition in Tk Aqua.\n *\n * Results:\n *\tReturns 0.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkpDrawSpinboxButtons(\n    TCL_UNUSED(Spinbox *),\n    TCL_UNUSED(Pixmap))\n{\n    return 0;\n}\n#endif /* Not MAC_OSX_TK */\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayEntry --\n *\n *\tThis function redraws the contents of an entry window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayEntry(\n    void *clientData)\t/* Information about window. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n    Tk_Window tkwin = entryPtr->tkwin;\n    int baseY, selStartX, selEndX, cursorX;\n    int showSelection, xBound;\n    Tk_FontMetrics fm;\n    Pixmap pixmap;\n    Tk_3DBorder border;\n    int borderWidth, selBorderWidth, insertWidth, highlightWidth;\n\n    entryPtr->flags &= ~REDRAW_PENDING;\n    if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    Tk_GetFontMetrics(entryPtr->tkfont, &fm);\n\n    /*\n     * Update the scrollbar if that's needed.\n     */\n\n    if (entryPtr->flags & UPDATE_SCROLLBAR) {\n\tentryPtr->flags &= ~UPDATE_SCROLLBAR;\n\n\t/*\n\t * Preserve/Release because updating the scrollbar can have the\n\t * side-effect of destroying or unmapping the entry widget.\n\t */\n\n\tTcl_Preserve(entryPtr);\n\tEntryUpdateScrollbar(entryPtr);\n\n\tif ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {\n\t    Tcl_Release(entryPtr);\n\t    return;\n\t}\n\tTcl_Release(entryPtr);\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * In order to avoid screen flashes, this function redraws the textual\n     * area of the entry into off-screen memory, then copies it back on-screen\n     * in a single operation. This means there's no point in time where the\n     * on-screen image has been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(entryPtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n    /*\n     * Compute x-coordinate of the pixel just after last visible one, plus\n     * vertical position of baseline of text.\n     */\n\n    xBound = Tk_Width(tkwin) - entryPtr->inset - entryPtr->xWidth;\n    baseY = (Tk_Height(tkwin) + fm.ascent - fm.descent) / 2;\n\n    /*\n     * Hide the selection whenever we don't have the focus, unless we\n     * always want to show selection.\n     */\n    if (Tk_AlwaysShowSelection(entryPtr->tkwin)) {\n\tshowSelection = 1;\n    } else {\n\tshowSelection = (entryPtr->flags & GOT_FOCUS);\n    }\n\n    /*\n     * Draw the background in three layers. From bottom to top the layers are:\n     * normal background, selection background, and insertion cursor\n     * background.\n     */\n\n    if ((entryPtr->state == STATE_DISABLED) &&\n\t    (entryPtr->disabledBorder != NULL)) {\n\tborder = entryPtr->disabledBorder;\n    } else if ((entryPtr->state == STATE_READONLY) &&\n\t    (entryPtr->readonlyBorder != NULL)) {\n\tborder = entryPtr->readonlyBorder;\n    } else {\n\tborder = entryPtr->normalBorder;\n    }\n    Tk_Fill3DRectangle(tkwin, pixmap, border,\n\t    0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n    Tk_GetPixelsFromObj(NULL, tkwin, entryPtr->selBorderWidthObj, &selBorderWidth);\n\n    if (showSelection && (entryPtr->state != STATE_DISABLED)\n\t    && (entryPtr->selectLast > entryPtr->leftIndex)) {\n\tif (entryPtr->selectFirst <= entryPtr->leftIndex) {\n\t    selStartX = entryPtr->leftX;\n\t} else {\n\t    Tk_CharBbox(entryPtr->textLayout, entryPtr->selectFirst,\n\t\t    &selStartX, NULL, NULL, NULL);\n\t    selStartX += entryPtr->layoutX;\n\t}\n\tif ((selStartX - selBorderWidth) < xBound) {\n\t    Tk_CharBbox(entryPtr->textLayout, entryPtr->selectLast,\n\t\t    &selEndX, NULL, NULL, NULL);\n\t    selEndX += entryPtr->layoutX;\n\t    Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->selBorder,\n\t\t    selStartX - selBorderWidth,\n\t\t    baseY - fm.ascent - selBorderWidth,\n\t\t    (selEndX - selStartX) + 2 * selBorderWidth,\n\t\t    (fm.ascent + fm.descent) + 2 * selBorderWidth,\n\t\t    selBorderWidth,\n#ifndef MAC_OSX_TK\n\t\t    TK_RELIEF_RAISED\n#else\n\t\t    MAC_OSX_ENTRY_SELECT_RELIEF\n#endif\n\t\t    );\n\t}\n    }\n\n    /*\n     * Draw a special background for the insertion cursor, overriding even the\n     * selection background. As a special hack to keep the cursor visible when\n     * the insertion cursor color is the same as the color for selected text\n     * (e.g., on mono displays), write background in the cursor area (instead\n     * of nothing) when the cursor isn't on. Otherwise the selection would\n     * hide the cursor.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, entryPtr->insertWidthObj, &insertWidth);\n    if ((entryPtr->state == STATE_NORMAL) && (entryPtr->flags & GOT_FOCUS)) {\n\tTk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,\n\t\tNULL, NULL);\n\tcursorX += entryPtr->layoutX;\n\tcursorX -= (insertWidth <= 1) ? 1 : (insertWidth)/2;\n\tTk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,\n\t\tfm.ascent + fm.descent);\n\tif ((entryPtr->insertPos >= entryPtr->leftIndex) && cursorX < xBound) {\n\t    if (entryPtr->flags & CURSOR_ON) {\n\t\t/* Take minimum of given insertBorderWidth and insertWidth/2 */\n\t\tint insertBorderWidth;\n\t\tTk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->insertBorderWidthObj, &insertBorderWidth);\n\t\tif (insertBorderWidth > insertWidth/2) {\n\t\t    insertBorderWidth = insertWidth/2;\n\t\t}\n\t\tTk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder,\n\t\t\tcursorX, baseY - fm.ascent, insertWidth,\n\t\t\tfm.ascent + fm.descent, insertBorderWidth,\n\t\t\tTK_RELIEF_RAISED);\n\t    } else if (entryPtr->insertBorder == entryPtr->selBorder) {\n\t\tTk_Fill3DRectangle(tkwin, pixmap, border, cursorX,\n\t\t\tbaseY - fm.ascent, insertWidth,\n\t\t\tfm.ascent + fm.descent, 0, TK_RELIEF_FLAT);\n\t    }\n\t}\n    }\n\n    if ((entryPtr->numChars == 0) && (entryPtr->placeholderChars != 0)) {\n\n\t/*\n\t * Draw the placeholder text.\n\t */\n\n\tTk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->placeholderGC,\n\t    entryPtr->placeholderLayout, entryPtr->placeholderX, entryPtr->layoutY,\n\t    entryPtr->placeholderLeftIndex, entryPtr->placeholderChars);\n\n    } else {\n\n\tif (showSelection && (entryPtr->state != STATE_DISABLED)\n\t\t&& (entryPtr->selTextGC != entryPtr->textGC)\n\t\t&& (entryPtr->selectFirst < entryPtr->selectLast)) {\n\n\t    /*\n\t     * Draw the selected and unselected portions separately.\n\t     */\n\n\t    Tcl_Size selFirst;\n\n\t    if (entryPtr->selectFirst < entryPtr->leftIndex) {\n\t\tselFirst = entryPtr->leftIndex;\n\t    } else {\n\t\tselFirst = entryPtr->selectFirst;\n\t    }\n\t    if (entryPtr->leftIndex < selFirst) {\n\t\tTk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,\n\t\t\tentryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,\n\t\t\tentryPtr->leftIndex, selFirst);\n\t    }\n\t    Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,\n\t\t    entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,\n\t\t    selFirst, entryPtr->selectLast);\n\t    if (entryPtr->selectLast < entryPtr->numChars) {\n\t\tTk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,\n\t\t\tentryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,\n\t\t\tentryPtr->selectLast, entryPtr->numChars);\n\t    }\n\t} else {\n\n\t    /*\n\t     * Draw the entire visible text\n\t     */\n\n\t    Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,\n\t\t    entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,\n\t\t    entryPtr->leftIndex, entryPtr->numChars);\n\t}\n    }\n\n    if (entryPtr->type == TK_SPINBOX) {\n\tint startx, height, inset, pad, tHeight, xWidth;\n\tSpinbox *sbPtr = (Spinbox *) entryPtr;\n\n\t/*\n\t * Draw the spin button controls.\n\t */\n\n\tif (TkpDrawSpinboxButtons(sbPtr, pixmap) == 0) {\n\t    xWidth = entryPtr->xWidth;\n\t    pad = XPAD + 1;\n\t    inset = entryPtr->inset - XPAD;\n\t    startx = Tk_Width(tkwin) - (xWidth + inset);\n\t    height = (Tk_Height(tkwin) - 2*inset)/2;\n#if 0\n\t    Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,\n\t\t    startx, inset, xWidth, height, 1, sbPtr->buRelief);\n\t    Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,\n\t\t    startx, inset+height, xWidth, height, 1, sbPtr->bdRelief);\n#else\n\t    Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,\n\t\t    startx, inset, xWidth, height, 1,\n\t\t    (sbPtr->selElement == SEL_BUTTONUP) ?\n\t\t    TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);\n\t    Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,\n\t\t    startx, inset+height, xWidth, height, 1,\n\t\t    (sbPtr->selElement == SEL_BUTTONDOWN) ?\n\t\t    TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);\n#endif\n\n\t    xWidth -= 2*pad;\n\n\t    /*\n\t     * Only draw the triangles if we have enough display space\n\t     */\n\n\t    if ((xWidth > 1)) {\n\t\tXPoint points[3];\n\t\tint starty, space, offset;\n\n\t\tspace = height - 2*pad;\n\n\t\t/*\n\t\t * Ensure width of triangle is odd to guarantee a sharp tip\n\t\t */\n\n\t\tif (!(xWidth % 2)) {\n\t\t    xWidth++;\n\t\t}\n\t\ttHeight = (xWidth + 1) / 2;\n\t\tif (tHeight > space) {\n\t\t    tHeight = space;\n\t\t}\n\t\tspace\t= (space - tHeight) / 2;\n\t\tstartx += pad;\n\t\tstarty\t= inset + height - pad - space;\n\t\toffset\t= (sbPtr->selElement == SEL_BUTTONUP);\n\n\t\t/*\n\t\t * The points are slightly different for the up and down\n\t\t * arrows because (for *.x), we need to account for a bug in\n\t\t * the way XFillPolygon draws triangles, and we want to shift\n\t\t * the arrows differently when allowing for depressed\n\t\t * behavior.\n\t\t */\n\n\t\tpoints[0].x = (short)(startx + offset);\n\t\tpoints[0].y = (short)(starty + (offset ? 0 : -1));\n\t\tpoints[1].x = (short)(startx + xWidth/2 + offset);\n\t\tpoints[1].y = (short)(starty - tHeight + (offset ? 0 : -1));\n\t\tpoints[2].x = (short)(startx + xWidth + offset);\n\t\tpoints[2].y = points[0].y;\n\t\tXFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,\n\t\t\tpoints, 3, Convex, CoordModeOrigin);\n\n\t\tstarty = inset + height + pad + space;\n\t\toffset = (sbPtr->selElement == SEL_BUTTONDOWN);\n\t\tpoints[0].x = (short)(startx + 1 + offset);\n\t\tpoints[0].y = (short)(starty + (offset ? 1 : 0));\n\t\tpoints[1].x = (short)(startx + xWidth/2 + offset);\n\t\tpoints[1].y = (short)(starty + tHeight + (offset ? 0 : -1));\n\t\tpoints[2].x = (short)(startx - 1 + xWidth + offset);\n\t\tpoints[2].y = points[0].y;\n\t\tXFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,\n\t\t\tpoints, 3, Convex, CoordModeOrigin);\n\t    }\n\t}\n    }\n\n    /*\n     * Draw the border and focus highlight last, so they will overwrite any\n     * text that extends past the viewable part of the window.\n     */\n\n    Tk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, entryPtr->tkwin, entryPtr->highlightWidthObj, &highlightWidth);\n    if (!TkpDrawEntryBorderAndFocus(entryPtr, pixmap,\n\t    (entryPtr->type == TK_SPINBOX))) {\n\txBound = highlightWidth;\n\tif (entryPtr->relief != TK_RELIEF_FLAT) {\n\t    Tk_Draw3DRectangle(tkwin, pixmap, border, xBound, xBound,\n\t\t    Tk_Width(tkwin) - 2 * xBound,\n\t\t    Tk_Height(tkwin) - 2 * xBound,\n\t\t    borderWidth, entryPtr->relief);\n\t}\n\tif (xBound > 0) {\n\t    GC fgGC, bgGC;\n\n\t    bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap);\n\t    if (entryPtr->flags & GOT_FOCUS) {\n\t\tfgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap);\n\t\tTk_DrawHighlightBorder(tkwin, fgGC, bgGC, xBound, pixmap);\n\t    } else {\n\t\tTk_DrawHighlightBorder(tkwin, bgGC, bgGC, xBound, pixmap);\n\t    }\n\t}\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Everything's been redisplayed; now copy the pixmap onto the screen and\n     * free up the pixmap.\n     */\n\n    XCopyArea(entryPtr->display, pixmap, Tk_WindowId(tkwin), entryPtr->textGC,\n\t    0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),\n\t    0, 0);\n    Tk_FreePixmap(entryPtr->display, pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    entryPtr->flags &= ~BORDER_NEEDED;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryComputeGeometry --\n *\n *\tThis function is invoked to recompute information about where in its\n *\twindow an entry's string will be displayed. It also computes the\n *\trequested size for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe leftX and tabOrigin fields are recomputed for entryPtr, and\n *\tleftIndex may be adjusted. Tk_GeometryRequest is called to register\n *\tthe desired dimensions for the window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryComputeGeometry(\n    Entry *entryPtr)\t\t/* Widget record for entry. */\n{\n    int totalLength, overflow, rightX;\n    Tcl_Size i, maxOffScreen;\n    int height, width;\n    Tk_FontMetrics fm;\n    char *p;\n\n    if (entryPtr->displayString != entryPtr->string) {\n\tTcl_Free((void *)entryPtr->displayString);\n\tentryPtr->displayString = entryPtr->string;\n\tentryPtr->numDisplayBytes = entryPtr->numBytes;\n    }\n\n    /*\n     * If we're displaying a special character instead of the value of the\n     * entry, recompute the displayString.\n     */\n\n    if (entryPtr->showCharObj != NULL) {\n\tint ch;\n\tchar buf[6];\n\tTcl_Size size;\n\n\t/*\n\t * Normalize the special character so we can safely duplicate it in\n\t * the display string. If we didn't do this, then two malformed\n\t * characters might end up looking like one valid UTF character in the\n\t * resulting string.\n\t */\n\n\tTcl_UtfToUniChar(Tcl_GetString(entryPtr->showCharObj), &ch);\n\tsize = Tcl_UniCharToUtf(ch, buf);\n\n\tentryPtr->numDisplayBytes = entryPtr->numChars * size;\n\tp = (char *)Tcl_Alloc(entryPtr->numDisplayBytes + 1);\n\tentryPtr->displayString = p;\n\n\tfor (i = entryPtr->numChars; i-- > 0; ) {\n\t    memcpy(p, buf, size);\n\t    p += size;\n\t}\n\t*p = '\\0';\n    }\n\n    /* Recompute layout of placeholder text.\n     * Only the placeholderX and placeholderLeftIndex value is needed.\n     * We use the same font so we can use the layoutY value from below.\n     */\n\n    Tk_FreeTextLayout(entryPtr->placeholderLayout);\n    if (entryPtr->placeholderObj) {\n\tentryPtr->placeholderChars = Tcl_GetCharLength(entryPtr->placeholderObj);\n\tentryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont,\n\t\tTcl_GetString(entryPtr->placeholderObj), entryPtr->placeholderChars, 0,\n\t\tentryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, NULL);\n\toverflow = totalLength -\n\t\t(Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth);\n\tif (overflow <= 0) {\n\t    entryPtr->placeholderLeftIndex = 0;\n\t    if (entryPtr->justify == TK_JUSTIFY_LEFT) {\n\t\tentryPtr->placeholderX = entryPtr->inset;\n\t    } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) {\n\t\tentryPtr->placeholderX = Tk_Width(entryPtr->tkwin) - entryPtr->inset\n\t\t\t- entryPtr->xWidth - totalLength;\n\t    } else {\n\t\tentryPtr->placeholderX = (Tk_Width(entryPtr->tkwin)\n\t\t\t- entryPtr->xWidth - totalLength)/2;\n\t    }\n\t} else {\n\n\t    /*\n\t     * The whole string can't fit in the window. Compute the maximum\n\t     * number of characters that may be off-screen to the left without\n\t     * leaving empty space on the right of the window, then don't let\n\t     * placeholderLeftIndex be any greater than that.\n\t     */\n\n\t    maxOffScreen = Tk_PointToChar(entryPtr->placeholderLayout, overflow, 0);\n\t    Tk_CharBbox(entryPtr->placeholderLayout, maxOffScreen,\n\t\t&rightX, NULL, NULL, NULL);\n\t    if (rightX < overflow) {\n\t\tmaxOffScreen++;\n\t    }\n\t    entryPtr->placeholderLeftIndex = maxOffScreen;\n\t    Tk_CharBbox(entryPtr->placeholderLayout, entryPtr->placeholderLeftIndex, &rightX,\n\t\tNULL, NULL, NULL);\n\t    entryPtr->placeholderX = entryPtr->inset -rightX;\n\t}\n    } else {\n\tentryPtr->placeholderChars = 0;\n\tentryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont,\n\t\t(entryPtr->placeholderObj ? Tcl_GetString(entryPtr->placeholderObj) : NULL), 0, 0,\n\t\tentryPtr->justify, TK_IGNORE_NEWLINES, NULL, NULL);\n\tentryPtr->placeholderX = entryPtr->inset;\n    }\n\n    Tk_FreeTextLayout(entryPtr->textLayout);\n    entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont,\n\t    entryPtr->displayString, entryPtr->numChars, 0,\n\t    entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);\n\n    entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;\n\n    /*\n     * Recompute where the leftmost character on the display will be drawn\n     * (entryPtr->leftX) and adjust leftIndex if necessary so that we don't\n     * let characters hang off the edge of the window unless the entire window\n     * is full.\n     */\n\n    overflow = totalLength -\n\t    (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth);\n    if (overflow <= 0) {\n\tentryPtr->leftIndex = 0;\n\tif (entryPtr->justify == TK_JUSTIFY_LEFT) {\n\t    entryPtr->leftX = entryPtr->inset;\n\t} else if (entryPtr->justify == TK_JUSTIFY_RIGHT) {\n\t    entryPtr->leftX = Tk_Width(entryPtr->tkwin) - entryPtr->inset\n\t\t    - entryPtr->xWidth - totalLength;\n\t} else {\n\t    entryPtr->leftX = (Tk_Width(entryPtr->tkwin)\n\t\t    - entryPtr->xWidth - totalLength)/2;\n\t}\n\tentryPtr->layoutX = entryPtr->leftX;\n    } else {\n\t/*\n\t * The whole string can't fit in the window. Compute the maximum\n\t * number of characters that may be off-screen to the left without\n\t * leaving empty space on the right of the window, then don't let\n\t * leftIndex be any greater than that.\n\t */\n\n\tmaxOffScreen = Tk_PointToChar(entryPtr->textLayout, overflow, 0);\n\tTk_CharBbox(entryPtr->textLayout, maxOffScreen,\n\t\t&rightX, NULL, NULL, NULL);\n\tif (rightX < overflow) {\n\t    maxOffScreen++;\n\t}\n\tif (entryPtr->leftIndex > maxOffScreen) {\n\t    entryPtr->leftIndex = maxOffScreen;\n\t}\n\tTk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex, &rightX,\n\t\tNULL, NULL, NULL);\n\tentryPtr->leftX = entryPtr->inset;\n\tentryPtr->layoutX = entryPtr->leftX - rightX;\n    }\n\n    Tk_GetFontMetrics(entryPtr->tkfont, &fm);\n    height = fm.linespace + 2*entryPtr->inset + 2*(YPAD-XPAD);\n    if (entryPtr->prefWidth > 0) {\n\twidth = entryPtr->prefWidth*entryPtr->avgWidth + 2*entryPtr->inset;\n    } else if (totalLength == 0) {\n\twidth = entryPtr->avgWidth + 2*entryPtr->inset;\n    } else {\n\twidth = totalLength + 2*entryPtr->inset;\n    }\n\n    /*\n     * Add one extra length for the spin buttons\n     */\n    width += entryPtr->xWidth;\n\n    Tk_GeometryRequest(entryPtr->tkwin, width, height);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InsertChars --\n *\n *\tAdd new characters to an entry widget.\n *\n * Results:\n *\tA standard Tcl result. If an error occurred then an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNew information gets added to entryPtr; it will be redisplayed soon,\n *\tbut not necessarily immediately.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInsertChars(\n    Entry *entryPtr,\t\t/* Entry that is to get the new elements. */\n    Tcl_Size index,\t\t\t/* Add the new elements before this character\n\t\t\t\t * index. */\n    Tcl_Obj *obj)\t\t/* New characters to add. */\n{\n    size_t byteIndex, byteCount, newByteCount, oldChars, charsAdded;\n    const char *string;\n    const char *value = Tcl_GetString(obj);\n    char *newStr;\n\n    string = entryPtr->string;\n    byteIndex = Tcl_UtfAtIndex(string, index) - string;\n    byteCount = strlen(value);\n    if (byteCount == 0) {\n\treturn TCL_OK;\n    }\n\n    newByteCount = entryPtr->numBytes + byteCount + 1;\n    newStr = (char *)Tcl_Alloc(newByteCount);\n    memcpy(newStr, string, byteIndex);\n    strcpy(newStr + byteIndex, value);\n    strcpy(newStr + byteIndex + byteCount, string + byteIndex);\n\n    if ((entryPtr->validate == VALIDATE_KEY ||\n\t    entryPtr->validate == VALIDATE_ALL) &&\n\t    EntryValidateChange(entryPtr, value, newStr, index,\n\t\t    VALIDATE_INSERT) != TCL_OK) {\n\tTcl_Free(newStr);\n\treturn TCL_OK;\n    }\n\n    Tcl_Free((void *)string);\n    entryPtr->string = newStr;\n\n    /*\n     * The following construction is used because inserting improperly formed\n     * UTF-8 sequences between other improperly formed UTF-8 sequences could\n     * result in actually forming valid UTF-8 sequences; the number of\n     * characters added may not be Tcl_NumUtfChars(string, TCL_INDEX_NONE), because of\n     * context. The actual number of characters added is how many characters\n     * are in the string now minus the number that used to be there.\n     */\n\n    oldChars = entryPtr->numChars;\n    entryPtr->numChars = Tcl_NumUtfChars(newStr, TCL_INDEX_NONE);\n    charsAdded = entryPtr->numChars - oldChars;\n    entryPtr->numBytes += byteCount;\n\n    if (entryPtr->displayString == string) {\n\tentryPtr->displayString = newStr;\n\tentryPtr->numDisplayBytes = entryPtr->numBytes;\n    }\n\n    /*\n     * Inserting characters invalidates all indexes into the string. Touch up\n     * the indexes so that they still refer to the same characters (at new\n     * positions). When updating the selection end-points, don't include the\n     * new text in the selection unless it was completely surrounded by the\n     * selection.\n     */\n\n    if (entryPtr->selectFirst >= index) {\n\tentryPtr->selectFirst += charsAdded;\n    }\n    if (entryPtr->selectLast > index) {\n\tentryPtr->selectLast += charsAdded;\n    }\n    if ((entryPtr->selectAnchor > index) || (entryPtr->selectFirst >= index)) {\n\tentryPtr->selectAnchor += charsAdded;\n    }\n    if (entryPtr->leftIndex > index) {\n\tentryPtr->leftIndex += charsAdded;\n    }\n    if (entryPtr->insertPos >= index) {\n\tentryPtr->insertPos += charsAdded;\n    }\n    return EntryValueChanged(entryPtr, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteChars --\n *\n *\tRemove one or more characters from an entry widget.\n *\n * Results:\n *\tA standard Tcl result. If an error occurred then an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tMemory gets freed, the entry gets modified and (eventually)\n *\tredisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDeleteChars(\n    Entry *entryPtr,\t\t/* Entry widget to modify. */\n    Tcl_Size index,\t\t\t/* Index of first character to delete. */\n    Tcl_Size count)\t\t\t/* How many characters to delete. */\n{\n    Tcl_Size byteIndex, byteCount, newByteCount;\n    const char *string;\n    char *newStr, *toDelete;\n\n    if (index + count > entryPtr->numChars) {\n\tcount = entryPtr->numChars - index;\n    }\n    if ((int)count <= 0) {\n\treturn TCL_OK;\n    }\n\n    string = entryPtr->string;\n    byteIndex = Tcl_UtfAtIndex(string, index) - string;\n    byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string+byteIndex);\n\n    newByteCount = entryPtr->numBytes + 1 - byteCount;\n    newStr = (char *)Tcl_Alloc(newByteCount);\n    memcpy(newStr, string, (size_t) byteIndex);\n    strcpy(newStr + byteIndex, string + byteIndex + byteCount);\n\n    toDelete = (char *)Tcl_Alloc(byteCount + 1);\n    memcpy(toDelete, string + byteIndex, (size_t) byteCount);\n    toDelete[byteCount] = '\\0';\n\n    if ((entryPtr->validate == VALIDATE_KEY ||\n\t    entryPtr->validate == VALIDATE_ALL) &&\n\t    EntryValidateChange(entryPtr, toDelete, newStr, index,\n\t\t    VALIDATE_DELETE) != TCL_OK) {\n\tTcl_Free(newStr);\n\tTcl_Free(toDelete);\n\treturn TCL_OK;\n    }\n\n    Tcl_Free(toDelete);\n    Tcl_Free((void *)entryPtr->string);\n    entryPtr->string = newStr;\n    entryPtr->numChars -= count;\n    entryPtr->numBytes -= byteCount;\n\n    if (entryPtr->displayString == string) {\n\tentryPtr->displayString = newStr;\n\tentryPtr->numDisplayBytes = entryPtr->numBytes;\n    }\n\n    /*\n     * Deleting characters results in the remaining characters being\n     * renumbered. Update the various indexes into the string to reflect this\n     * change.\n     */\n\n    if (entryPtr->selectFirst >= index) {\n\tif (entryPtr->selectFirst >= index + count) {\n\t    entryPtr->selectFirst -= count;\n\t} else {\n\t    entryPtr->selectFirst = index;\n\t}\n    }\n    if (entryPtr->selectLast >= index) {\n\tif (entryPtr->selectLast >= index + count) {\n\t    entryPtr->selectLast -= count;\n\t} else {\n\t    entryPtr->selectLast = index;\n\t}\n    }\n    if (entryPtr->selectLast <= entryPtr->selectFirst) {\n\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\tentryPtr->selectLast = TCL_INDEX_NONE;\n    }\n    if (entryPtr->selectAnchor >= index) {\n\tif (entryPtr->selectAnchor >= index + count) {\n\t    entryPtr->selectAnchor -= count;\n\t} else {\n\t    entryPtr->selectAnchor = index;\n\t}\n    }\n    if (entryPtr->leftIndex > index) {\n\tif (entryPtr->leftIndex >= index + count) {\n\t    entryPtr->leftIndex -= count;\n\t} else {\n\t    entryPtr->leftIndex = index;\n\t}\n    }\n    if (entryPtr->insertPos >= index) {\n\tif (entryPtr->insertPos >= index + count) {\n\t    entryPtr->insertPos -= count;\n\t} else {\n\t    entryPtr->insertPos = index;\n\t}\n    }\n    return EntryValueChanged(entryPtr, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryValueChanged --\n *\n *\tThis function is invoked when characters are inserted into an entry or\n *\tdeleted from it. It updates the entry's associated variable, if there\n *\tis one, and does other bookkeeping such as arranging for redisplay.\n *\n * Results:\n *\tA standard Tcl result. If an error occurred then an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nEntryValueChanged(\n    Entry *entryPtr,\t\t/* Entry whose value just changed. */\n    const char *newValue)\t/* If this value is not NULL, we first force\n\t\t\t\t * the value of the entry to this. */\n{\n    if (newValue != NULL) {\n\tEntrySetValue(entryPtr, newValue);\n    }\n\n    if (entryPtr->textVarNameObj == NULL) {\n\tnewValue = NULL;\n    } else {\n\tnewValue = Tcl_SetVar2(entryPtr->interp, Tcl_GetString(entryPtr->textVarNameObj),\n\t\tNULL, entryPtr->string, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);\n    }\n\n    if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) {\n\t/*\n\t * The value of the variable is different than what we asked for.\n\t * This means that a trace on the variable modified it. In this case\n\t * our trace function wasn't invoked since the modification came while\n\t * a trace was already active on the variable. So, update our value to\n\t * reflect the variable's latest value.\n\t */\n\n\tEntrySetValue(entryPtr, newValue);\n    } else {\n\t/*\n\t * Arrange for redisplay.\n\t */\n\n\tentryPtr->flags |= UPDATE_SCROLLBAR;\n\tEntryComputeGeometry(entryPtr);\n\tEventuallyRedraw(entryPtr);\n    }\n\n    /*\n     * An error may have happened when setting the textvariable in case there\n     * is a trace on that variable and the trace proc triggered an error.\n     * Another possibility is that the textvariable is in a namespace that\n     * does not (yet) exist.\n     * Signal this error.\n     */\n\n    if ((entryPtr->textVarNameObj != NULL) && (newValue == NULL)) {\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntrySetValue --\n *\n *\tReplace the contents of a text entry with a given value. This function\n *\tis invoked when updating the entry from the entry's associated\n *\tvariable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe string displayed in the entry will change. The selection,\n *\tinsertion point, and view may have to be adjusted to keep them within\n *\tthe bounds of the new string. Note: this function does *not* update\n *\tthe entry's associated variable, since that could result in an\n *\tinfinite loop.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntrySetValue(\n    Entry *entryPtr,\t\t/* Entry whose value is to be changed. */\n    const char *value)\t\t/* New text to display in entry. */\n{\n    const char *oldSource;\n    size_t valueLen;\n    bool malloced = false;\n\n    if (strcmp(value, entryPtr->string) == 0) {\n\treturn;\n    }\n    valueLen = strlen(value);\n\n    if (entryPtr->flags & VALIDATE_VAR) {\n\tentryPtr->flags |= VALIDATE_ABORT;\n    } else {\n\t/*\n\t * If we validate, we create a copy of the value, as it may point to\n\t * volatile memory, like the value of the -textvar which may get freed\n\t * during validation\n\t */\n\n\tchar *tmp = (char *)Tcl_Alloc(valueLen + 1);\n\n\tstrcpy(tmp, value);\n\tvalue = tmp;\n\tmalloced = true;\n\n\tentryPtr->flags |= VALIDATE_VAR;\n\t(void) EntryValidateChange(entryPtr, NULL, value, TCL_INDEX_NONE,\n\t\tVALIDATE_FORCED);\n\tentryPtr->flags &= ~VALIDATE_VAR;\n\n\t/*\n\t * If VALIDATE_ABORT has been set, then this operation should be\n\t * aborted because the validatecommand did something else instead\n\t */\n\n\tif (entryPtr->flags & VALIDATE_ABORT) {\n\t    entryPtr->flags &= ~VALIDATE_ABORT;\n\t    Tcl_Free((void *)value);\n\t    return;\n\t}\n    }\n\n    oldSource = entryPtr->string;\n    Tcl_Free((void *)entryPtr->string);\n\n    if (malloced) {\n\tentryPtr->string = value;\n    } else {\n\tchar *tmp = (char *)Tcl_Alloc(valueLen + 1);\n\n\tstrcpy(tmp, value);\n\tentryPtr->string = tmp;\n    }\n    entryPtr->numBytes = valueLen;\n    entryPtr->numChars = Tcl_NumUtfChars(value, valueLen);\n\n    if (entryPtr->displayString == oldSource) {\n\tentryPtr->displayString = entryPtr->string;\n\tentryPtr->numDisplayBytes = entryPtr->numBytes;\n    }\n\n    if (entryPtr->selectFirst != TCL_INDEX_NONE) {\n\tif (entryPtr->selectFirst >= entryPtr->numChars) {\n\t    entryPtr->selectFirst = TCL_INDEX_NONE;\n\t    entryPtr->selectLast = TCL_INDEX_NONE;\n\t} else if (entryPtr->selectLast > entryPtr->numChars) {\n\t    entryPtr->selectLast = entryPtr->numChars;\n\t}\n    }\n    if (entryPtr->leftIndex >= entryPtr->numChars) {\n\tif (entryPtr->numChars > 0) {\n\t    entryPtr->leftIndex = entryPtr->numChars - 1;\n\t} else {\n\t    entryPtr->leftIndex = 0;\n\t}\n    }\n    if (entryPtr->insertPos > entryPtr->numChars) {\n\tentryPtr->insertPos = entryPtr->numChars;\n    }\n\n    entryPtr->flags |= UPDATE_SCROLLBAR;\n    EntryComputeGeometry(entryPtr);\n    EventuallyRedraw(entryPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EntryEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tentries.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEntryEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n\n    if ((entryPtr->type == TK_SPINBOX) && (eventPtr->type == MotionNotify)) {\n\tSpinbox *sbPtr = (Spinbox *)clientData;\n\tint elem;\n\n\telem = GetSpinboxElement(sbPtr, eventPtr->xmotion.x,\n\t\teventPtr->xmotion.y);\n\tif (elem != sbPtr->curElement) {\n\t    Tk_Cursor cursor;\n\n\t    sbPtr->curElement = elem;\n\t    if (elem == SEL_ENTRY) {\n\t\tcursor = entryPtr->cursor;\n\t    } else if ((elem == SEL_BUTTONDOWN) || (elem == SEL_BUTTONUP)) {\n\t\tcursor = sbPtr->bCursor;\n\t    } else {\n\t\tcursor = NULL;\n\t    }\n\t    if (cursor != NULL) {\n\t\tTk_DefineCursor(entryPtr->tkwin, cursor);\n\t    } else {\n\t\tTk_UndefineCursor(entryPtr->tkwin);\n\t    }\n\t}\n\treturn;\n    }\n\n    switch (eventPtr->type) {\n    case Expose:\n\tEventuallyRedraw(entryPtr);\n\tentryPtr->flags |= BORDER_NEEDED;\n\tbreak;\n    case DestroyNotify:\n\tif (!(entryPtr->flags & ENTRY_DELETED)) {\n\t    entryPtr->flags |= (ENTRY_DELETED | VALIDATE_ABORT);\n\t    Tcl_DeleteCommandFromToken(entryPtr->interp, entryPtr->widgetCmd);\n\t    if (entryPtr->flags & REDRAW_PENDING) {\n\t\tTcl_CancelIdleCall(DisplayEntry, clientData);\n\t    }\n\t    Tcl_EventuallyFree(clientData, DestroyEntry);\n\t}\n\tbreak;\n    case ConfigureNotify:\n\tTcl_Preserve(entryPtr);\n\tentryPtr->flags |= UPDATE_SCROLLBAR;\n\tEntryComputeGeometry(entryPtr);\n\tEventuallyRedraw(entryPtr);\n\tTcl_Release(entryPtr);\n\tbreak;\n    case FocusIn:\n    case FocusOut:\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    EntryFocusProc(entryPtr, (eventPtr->type == FocusIn));\n\t}\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (!(entryPtr->flags & ENTRY_DELETED)) {\n\tTk_DestroyWindow(entryPtr->tkwin);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetEntryIndex --\n *\n *\tParse an index into an entry and return either its value or an error.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the character index (into entryPtr) corresponding to string. The\n *\tindex value is guaranteed to lie between 0 and the number of\n *\tcharacters in the string, inclusive. If an error occurs then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetEntryIndex(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    Entry *entryPtr,\t\t/* Entry for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *indexObj,\t/* Specifies character in entryPtr. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted character index */\n{\n    Tcl_Size length, idx;\n    const char *string;\n\n    if (TCL_OK == TkGetIntForIndex(indexObj, entryPtr->numChars - 1, 1, &idx)) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else if (idx > entryPtr->numChars) {\n\t    idx = entryPtr->numChars;\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetStringFromObj(indexObj, &length);\n\n    switch (string[0]) {\n    case 'a':\n\tif (strncmp(string, \"anchor\", length) != 0) {\n\t    goto badIndex;\n\t}\n\t*indexPtr = entryPtr->selectAnchor;\n\tbreak;\n    case 'i':\n\tif (strncmp(string, \"insert\", length) != 0) {\n\t    goto badIndex;\n\t}\n\t*indexPtr = entryPtr->insertPos;\n\tbreak;\n    case 's':\n\tif (entryPtr->selectFirst < 0) {\n\t    Tcl_ResetResult(interp);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"selection isn't in widget %s\",\n\t\t    Tk_PathName(entryPtr->tkwin)));\n\t    Tcl_SetErrorCode(interp, \"TK\",\n\t\t    (entryPtr->type == TK_ENTRY) ? \"ENTRY\" : \"SPINBOX\",\n\t\t    \"NO_SELECTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (length < 5) {\n\t    goto badIndex;\n\t}\n\tif (strncmp(string, \"sel.first\", length) == 0) {\n\t    *indexPtr = entryPtr->selectFirst;\n\t} else if (strncmp(string, \"sel.last\", length) == 0) {\n\t    *indexPtr = entryPtr->selectLast;\n\t} else {\n\t    goto badIndex;\n\t}\n\tbreak;\n    case '@': {\n\tint x, roundUp, maxWidth;\n\n\tif (Tcl_GetInt(NULL, string + 1, &x) != TCL_OK) {\n\t    goto badIndex;\n\t}\n\tif (x < entryPtr->inset) {\n\t    x = entryPtr->inset;\n\t}\n\troundUp = 0;\n\tmaxWidth = Tk_Width(entryPtr->tkwin) - entryPtr->inset\n\t\t- entryPtr->xWidth - 1;\n\tif (x > maxWidth) {\n\t    x = maxWidth;\n\t    roundUp = 1;\n\t}\n\t*indexPtr = Tk_PointToChar(entryPtr->textLayout,\n\t\tx - entryPtr->layoutX, 0);\n\n\t/*\n\t * Special trick: if the x-position was off-screen to the right, round\n\t * the index up to refer to the character just after the last visible\n\t * one on the screen. This is needed to enable the last character to\n\t * be selected, for example.\n\t */\n\n\tif (roundUp && (*indexPtr < entryPtr->numChars)) {\n\t    *indexPtr += 1;\n\t}\n\tbreak;\n    }\n    default:\n\t  badIndex:\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad %s index \\\"%s\\\"\",\n\t\t    (entryPtr->type == TK_ENTRY) ? \"entry\" : \"spinbox\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\",\n\t\t    (entryPtr->type == TK_ENTRY) ? \"ENTRY\" : \"SPINBOX\",\n\t\t    \"BAD_INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryScanTo --\n *\n *\tGiven a y-coordinate (presumably of the curent mouse location) drag\n *\tthe view in the window to implement the scan operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe view in the window may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryScanTo(\n    Entry *entryPtr,\t\t/* Information about widget. */\n    int x)\t\t\t/* X-coordinate to use for scan operation. */\n{\n    Tcl_Size newLeftIndex;\n\n    /*\n     * Compute new leftIndex for entry by amplifying the difference between\n     * the current position and the place where the scan started (the \"mark\"\n     * position). If we run off the left or right side of the entry, then\n     * reset the mark point so that the current position continues to\n     * correspond to the edge of the window. This means that the picture will\n     * start dragging as soon as the mouse reverses direction (without this\n     * reset, might have to slide mouse a long ways back before the picture\n     * starts moving again).\n     */\n\n    newLeftIndex = entryPtr->scanMarkIndex\n\t    - (10 * (x - entryPtr->scanMarkX)) / entryPtr->avgWidth;\n    if (newLeftIndex >= entryPtr->numChars) {\n\tnewLeftIndex = entryPtr->scanMarkIndex = entryPtr->numChars - 1;\n\tentryPtr->scanMarkX = x;\n    }\n    if (newLeftIndex < 0) {\n\tnewLeftIndex = entryPtr->scanMarkIndex = 0;\n\tentryPtr->scanMarkX = x;\n    }\n\n    if (newLeftIndex != entryPtr->leftIndex) {\n\tentryPtr->leftIndex = newLeftIndex;\n\tentryPtr->flags |= UPDATE_SCROLLBAR;\n\tEntryComputeGeometry(entryPtr);\n\tif (newLeftIndex != entryPtr->leftIndex) {\n\t    entryPtr->scanMarkIndex = entryPtr->leftIndex;\n\t    entryPtr->scanMarkX = x;\n\t}\n\tEventuallyRedraw(entryPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntrySelectTo --\n *\n *\tModify the selection by moving its un-anchored end. This could make\n *\tthe selection either larger or smaller.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe selection changes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntrySelectTo(\n    Entry *entryPtr,\t\t/* Information about widget. */\n    Tcl_Size index)\t\t\t/* Character index of element that is to\n\t\t\t\t * become the \"other\" end of the selection. */\n{\n    Tcl_Size newFirst, newLast;\n\n    /*\n     * Grab the selection if we don't own it already.\n     */\n\n    if (!(entryPtr->flags & GOT_SELECTION) && (entryPtr->exportSelection)\n\t    && (!Tcl_IsSafe(entryPtr->interp))) {\n\tTk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,\n\t\tentryPtr);\n\tentryPtr->flags |= GOT_SELECTION;\n    }\n\n    /*\n     * Pick new starting and ending points for the selection.\n     */\n\n    if (entryPtr->selectAnchor > entryPtr->numChars) {\n\tentryPtr->selectAnchor = entryPtr->numChars;\n    }\n    if (entryPtr->selectAnchor <= index) {\n\tnewFirst = entryPtr->selectAnchor;\n\tnewLast = index;\n    } else {\n\tnewFirst = index;\n\tnewLast = entryPtr->selectAnchor;\n\tif (newLast < 0) {\n\t    newFirst = newLast = TCL_INDEX_NONE;\n\t}\n    }\n    if ((entryPtr->selectFirst == newFirst)\n\t    && (entryPtr->selectLast == newLast)) {\n\treturn;\n    }\n    entryPtr->selectFirst = newFirst;\n    entryPtr->selectLast = newLast;\n    EventuallyRedraw(entryPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryFetchSelection --\n *\n *\tThis function is called back by Tk when the selection is requested by\n *\tsomeone. It returns part or all of the selection in a buffer provided\n *\tby the caller.\n *\n * Results:\n *\tThe return value is the number of non-NULL bytes stored at buffer.\n *\tBuffer is filled (or partially filled) with a NULL-terminated string\n *\tcontaining part or all of the selection, as given by offset and\n *\tmaxBytes.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nEntryFetchSelection(\n    void *clientData,\t/* Information about entry widget. */\n    Tcl_Size offset,\t\t\t/* Byte offset within selection of first\n\t\t\t\t * character to be returned. */\n    char *buffer,\t\t/* Location in which to place selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum number of bytes to place at buffer,\n\t\t\t\t * not including terminating NUL character. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n    Tcl_Size byteCount;\n    const char *string;\n    const char *selStart, *selEnd;\n\n    if ((entryPtr->selectFirst < 0) || (!entryPtr->exportSelection)\n\t    || Tcl_IsSafe(entryPtr->interp)) {\n\treturn -1;\n    }\n    string = entryPtr->displayString;\n    selStart = Tcl_UtfAtIndex(string, entryPtr->selectFirst);\n    selEnd = Tcl_UtfAtIndex(selStart,\n\t    entryPtr->selectLast - entryPtr->selectFirst);\n    if (selEnd <= selStart + offset) {\n\treturn 0;\n    }\n    byteCount = selEnd - selStart - offset;\n    if (byteCount > maxBytes) {\n\tbyteCount = maxBytes;\n    }\n    memcpy(buffer, selStart + offset, byteCount);\n    buffer[byteCount] = '\\0';\n    return byteCount;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * EntryLostSelection --\n *\n *\tThis function is called back by Tk when the selection is grabbed away\n *\tfrom an entry widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe existing selection is unhighlighted, and the window is marked as\n *\tnot containing a selection.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryLostSelection(\n    void *clientData)\t/* Information about entry widget. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n\n    entryPtr->flags &= ~GOT_SELECTION;\n\n    /*\n     * On Windows and Mac systems, we want to remember the selection for the\n     * next time the focus enters the window. On Unix, we need to clear the\n     * selection since it is always visible.\n     * This is controlled by ::tk::AlwaysShowSelection.\n     */\n\n    if (Tk_AlwaysShowSelection(entryPtr->tkwin)\n\t    && (entryPtr->selectFirst != TCL_INDEX_NONE) && entryPtr->exportSelection\n\t    && (!Tcl_IsSafe(entryPtr->interp))) {\n\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\tentryPtr->selectLast = TCL_INDEX_NONE;\n\tEventuallyRedraw(entryPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EventuallyRedraw --\n *\n *\tEnsure that an entry is eventually redrawn on the display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets redisplayed. Right now we don't do selective\n *\tredisplays: the whole window will be redrawn. This doesn't seem to\n *\thurt performance noticeably, but if it does then this could be\n *\tchanged.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEventuallyRedraw(\n    Entry *entryPtr)\t\t/* Information about widget. */\n{\n    if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(entryPtr->tkwin)) {\n\treturn;\n    }\n\n    /*\n     * Right now we don't do selective redisplays: the whole window will be\n     * redrawn. This doesn't seem to hurt performance noticeably, but if it\n     * does then this could be changed.\n     */\n\n    if (!(entryPtr->flags & REDRAW_PENDING)) {\n\tentryPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayEntry, entryPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryVisibleRange --\n *\n *\tReturn information about the range of the entry that is currently\n *\tvisible.\n *\n * Results:\n *\t*firstPtr and *lastPtr are modified to hold fractions between 0 and 1\n *\tidentifying the range of characters visible in the entry.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryVisibleRange(\n    Entry *entryPtr,\t\t/* Information about widget. */\n    double *firstPtr,\t\t/* Return position of first visible character\n\t\t\t\t * in widget. */\n    double *lastPtr)\t\t/* Return position of char just after last\n\t\t\t\t * visible one. */\n{\n    Tcl_Size charsInWindow;\n\n    if (entryPtr->numChars == 0) {\n\t*firstPtr = 0.0;\n\t*lastPtr = 1.0;\n    } else {\n\tcharsInWindow = Tk_PointToChar(entryPtr->textLayout,\n\t\tTk_Width(entryPtr->tkwin) - entryPtr->inset\n\t\t- entryPtr->xWidth - entryPtr->layoutX - 1, 0);\n\tif (charsInWindow < entryPtr->numChars) {\n\t    charsInWindow++;\n\t}\n\tcharsInWindow -= entryPtr->leftIndex;\n\tif (charsInWindow == 0) {\n\t    charsInWindow = 1;\n\t}\n\n\t*firstPtr = (double) entryPtr->leftIndex / (double) entryPtr->numChars;\n\t*lastPtr = (double) (entryPtr->leftIndex + charsInWindow)\n\t\t/ (double) entryPtr->numChars;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryUpdateScrollbar --\n *\n *\tThis function is invoked whenever information has changed in an entry\n *\tin a way that would invalidate a scrollbar display. If there is an\n *\tassociated scrollbar, then this function updates it by invoking a Tcl\n *\tcommand.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Tcl command is invoked, and an additional command may be\n *\tinvoked to process errors in the command.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryUpdateScrollbar(\n    Entry *entryPtr)\t\t\t/* Information about widget. */\n{\n    char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];\n    int code;\n    double first, last;\n    Tcl_Interp *interp;\n    Tcl_DString buf;\n\n    if (entryPtr->scrollCmdObj == NULL) {\n\treturn;\n    }\n\n    interp = entryPtr->interp;\n    Tcl_Preserve(interp);\n    EntryVisibleRange(entryPtr, &first, &last);\n    Tcl_PrintDouble(NULL, first, firstStr);\n    Tcl_PrintDouble(NULL, last, lastStr);\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, Tcl_GetString(entryPtr->scrollCmdObj), TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, firstStr, TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, lastStr, TCL_INDEX_NONE);\n    code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    Tcl_DStringFree(&buf);\n    if (code != TCL_OK) {\n\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\"\\n    (horizontal scrolling command executed by %s)\",\n\t\tTk_PathName(entryPtr->tkwin)));\n\tTcl_BackgroundException(interp, code);\n    }\n    Tcl_ResetResult(interp);\n    Tcl_Release(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryBlinkProc --\n *\n *\tThis function is called as a timer handler to blink the insertion\n *\tcursor off and on.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor gets turned on or off, redisplay gets invoked, and this\n *\tfunction reschedules itself.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryBlinkProc(\n    void *clientData)\t/* Pointer to record describing entry. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n\n    if ((entryPtr->state == STATE_DISABLED) ||\n\t    (entryPtr->state == STATE_READONLY) ||\n\t    !(entryPtr->flags & GOT_FOCUS) || (entryPtr->insertOffTime == 0)) {\n\treturn;\n    }\n    if (entryPtr->flags & CURSOR_ON) {\n\tentryPtr->flags &= ~CURSOR_ON;\n\tentryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\tentryPtr->insertOffTime, EntryBlinkProc, entryPtr);\n    } else {\n\tentryPtr->flags |= CURSOR_ON;\n\tentryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\tentryPtr->insertOnTime, EntryBlinkProc, entryPtr);\n    }\n    EventuallyRedraw(entryPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EntryFocusProc --\n *\n *\tThis function is called whenever the entry gets or loses the input\n *\tfocus. It's also called whenever the window is reconfigured while it\n *\thas the focus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor gets turned on or off.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEntryFocusProc(\n    Entry *entryPtr,\t\t/* Entry that got or lost focus. */\n    int gotFocus)\t\t/* 1 means window is getting focus, 0 means\n\t\t\t\t * it's losing it. */\n{\n    Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);\n    if (gotFocus) {\n\tentryPtr->flags |= GOT_FOCUS | CURSOR_ON;\n\tif (entryPtr->insertOffTime != 0) {\n\t    entryPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\t    entryPtr->insertOnTime, EntryBlinkProc, entryPtr);\n\t}\n\tif (entryPtr->validate == VALIDATE_ALL ||\n\t\tentryPtr->validate == VALIDATE_FOCUS ||\n\t\tentryPtr->validate == VALIDATE_FOCUSIN) {\n\t    EntryValidateChange(entryPtr, NULL, entryPtr->string, TCL_INDEX_NONE,\n\t\t    VALIDATE_FOCUSIN);\n\t}\n    } else {\n\tentryPtr->flags &= ~(GOT_FOCUS | CURSOR_ON);\n\tentryPtr->insertBlinkHandler = NULL;\n\tif (entryPtr->validate == VALIDATE_ALL ||\n\t\tentryPtr->validate == VALIDATE_FOCUS ||\n\t\tentryPtr->validate == VALIDATE_FOCUSOUT) {\n\t    EntryValidateChange(entryPtr, NULL, entryPtr->string, TCL_INDEX_NONE,\n\t\t    VALIDATE_FOCUSOUT);\n\t}\n    }\n    EventuallyRedraw(entryPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EntryTextVarProc --\n *\n *\tThis function is invoked when someone changes the variable whose\n *\tcontents are to be displayed in an entry.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe text displayed in the entry will change to match the variable.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nEntryTextVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(const char *),\n    int flags)\t\t\t/* Information about what happened. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n    const char *value;\n\n    if (entryPtr->flags & ENTRY_DELETED) {\n\t/*\n\t * Just abort early if we entered here while being deleted.\n\t */\n\treturn NULL;\n    }\n\n    /*\n     * If the variable is unset, then immediately recreate it unless the whole\n     * interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tif (!Tcl_InterpDeleted(interp) && entryPtr->textVarNameObj) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(entryPtr->textVarNameObj),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tEntryTextVarProc, probe);\n\t\tif (probe == entryPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * textVarName, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t    Tcl_SetVar2(interp, Tcl_GetString(entryPtr->textVarNameObj), NULL,\n\t\t    entryPtr->string, TCL_GLOBAL_ONLY);\n\t    Tcl_TraceVar2(interp, Tcl_GetString(entryPtr->textVarNameObj), NULL,\n\t\t    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    EntryTextVarProc, clientData);\n\t    entryPtr->flags |= ENTRY_VAR_TRACED;\n\t}\n\treturn NULL;\n    }\n\n    /*\n     * Update the entry's text with the value of the variable, unless the\n     * entry already has that value (this happens when the variable changes\n     * value because we changed it because someone typed in the entry).\n     */\n\n    value = Tcl_GetVar2(interp, Tcl_GetString(entryPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n    if (value == NULL) {\n\tvalue = \"\";\n    }\n    EntrySetValue(entryPtr, value);\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EntryValidate --\n *\n *\tThis function is invoked when any character is added or removed from\n *\tthe entry widget, or a focus has trigerred validation.\n *\n * Results:\n\n *\tTCL_OK if the validatecommand passes the new string. TCL_BREAK if the\n *\tvcmd executed OK, but rejects the string. TCL_ERROR if an error\n *\toccurred while executing the vcmd or a valid Tcl_Bool is not returned.\n *\n * Side effects:\n *\tAn error condition may arise\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEntryValidate(\n     Entry *entryPtr,\t/* Entry that needs validation. */\n     char *cmd)\t/* Validation command (NULL-terminated\n\t\t\t\t * string). */\n{\n    Tcl_Interp *interp = entryPtr->interp;\n    int code, isOK;\n\n    code = Tcl_EvalEx(interp, cmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);\n\n    /*\n     * We accept TCL_OK and TCL_RETURN as valid return codes from the command\n     * callback.\n     */\n\n    if (code != TCL_OK && code != TCL_RETURN) {\n\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\"\\n    (in validation command executed by %s)\",\n\t\tTk_PathName(entryPtr->tkwin)));\n\tTcl_BackgroundException(interp, code);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * The command callback should return an acceptable Tcl boolean.\n     */\n\n    if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp),\n\t    &isOK) != TCL_OK) {\n\tTcl_AddErrorInfo(interp,\n\t\t \"\\n    (invalid boolean result from validation command)\");\n\tTcl_BackgroundException(interp, TCL_ERROR);\n\tTcl_ResetResult(interp);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_ResetResult(interp);\n    return (isOK ? TCL_OK : TCL_BREAK);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EntryValidateChange --\n *\n *\tThis function is invoked when any character is added or removed from\n *\tthe entry widget, or a focus has trigerred validation.\n *\n * Results:\n *\tTCL_OK if the validatecommand accepts the new string, TCL_ERROR if any\n *\tproblems occurred with validatecommand.\n *\n * Side effects:\n *\tThe insertion/deletion may be aborted, and the validatecommand might\n *\tturn itself off (if an error or loop condition arises).\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEntryValidateChange(\n     Entry *entryPtr,\t/* Entry that needs validation. */\n     const char *change,\t/* Characters to be added/deleted\n\t\t\t\t * (NUL-terminated string). */\n     const char *newValue,\t/* Potential new value of entry string */\n     Tcl_Size index,\t\t\t/* index of insert/delete, TCL_INDEX_NONE otherwise */\n     int type)\t\t\t/* forced, delete, insert, focusin or\n\t\t\t\t * focusout */\n{\n    int code, varValidate = (entryPtr->flags & VALIDATE_VAR);\n    char *p;\n    Tcl_DString script;\n\n    if (entryPtr->validateCmdObj == NULL ||\n\tentryPtr->validate == VALIDATE_NONE) {\n\tif (entryPtr->flags & VALIDATING) {\n\t    entryPtr->flags |= VALIDATE_ABORT;\n\t}\n\treturn (varValidate ? TCL_ERROR : TCL_OK);\n    }\n\n    /*\n     * If we're already validating, then we're hitting a loop condition. Set\n     * validate to none to disallow further validations, arrange for flags\n     * to prevent current validation from finishing, and return.\n     */\n\n    if (entryPtr->flags & VALIDATING) {\n\tentryPtr->validate = VALIDATE_NONE;\n\tentryPtr->flags |= VALIDATE_ABORT;\n\treturn (varValidate ? TCL_ERROR : TCL_OK);\n    }\n\n    entryPtr->flags |= VALIDATING;\n\n    /*\n     * Now form command string and run through the -validatecommand\n     */\n\n    Tcl_DStringInit(&script);\n    ExpandPercents(entryPtr, (entryPtr->validateCmdObj ? Tcl_GetString(entryPtr->validateCmdObj) : NULL),\n\t    change, newValue, index, type, &script);\n    Tcl_DStringAppend(&script, \"\", 1);\n\n    p = Tcl_DStringValue(&script);\n    code = EntryValidate(entryPtr, p);\n    Tcl_DStringFree(&script);\n\n    /*\n     * If e->validate has become VALIDATE_NONE during the validation, or we\n     * now have VALIDATE_VAR set (from EntrySetValue) and didn't before, it\n     * means that a loop condition almost occurred. Do not allow this\n     * validation result to finish.\n     */\n\n    if (entryPtr->validate == VALIDATE_NONE\n\t    || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) {\n\tcode = TCL_ERROR;\n    }\n\n    /*\n     * It's possible that the user deleted the entry during validation. In\n     * that case, abort future validation and return an error.\n     */\n\n    if (entryPtr->flags & ENTRY_DELETED) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If validate will return ERROR, then disallow further validations\n     * Otherwise, if it didn't accept the new string (returned TCL_BREAK) then\n     * eval the invalidCmd (if it's set)\n     */\n\n    if (code == TCL_ERROR) {\n\tentryPtr->validate = VALIDATE_NONE;\n    } else if (code == TCL_BREAK) {\n\t/*\n\t * If we were doing forced validation (like via a variable trace) and\n\t * the command returned 0, the we turn off validation because we\n\t * assume that textvariables have precedence in managing the value.\n\t * We also don't call the invcmd, as it may want to do entry\n\t * manipulation which the setting of the var will later wipe anyway.\n\t */\n\n\tif (varValidate) {\n\t    entryPtr->validate = VALIDATE_NONE;\n\t} else if (entryPtr->invalidCmdObj != NULL) {\n\t    int result;\n\n\t    Tcl_DStringInit(&script);\n\t    ExpandPercents(entryPtr, Tcl_GetString(entryPtr->invalidCmdObj),\n\t\t    change, newValue, index, type, &script);\n\t    Tcl_DStringAppend(&script, \"\", 1);\n\t    p = Tcl_DStringValue(&script);\n\t    result = Tcl_EvalEx(entryPtr->interp, p, TCL_INDEX_NONE,\n\t\t    TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);\n\t    if (result != TCL_OK) {\n\t\tTcl_AddErrorInfo(entryPtr->interp,\n\t\t\t\"\\n    (in invalidcommand executed by entry)\");\n\t\tTcl_BackgroundException(entryPtr->interp, result);\n\t\tcode = TCL_ERROR;\n\t\tentryPtr->validate = VALIDATE_NONE;\n\t    }\n\t    Tcl_DStringFree(&script);\n\n\t    /*\n\t     * It's possible that the user deleted the entry during\n\t     * validation. In that case, abort future validation and return an\n\t     * error.\n\t     */\n\n\t    if (entryPtr->flags & ENTRY_DELETED) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n\n    entryPtr->flags &= ~VALIDATING;\n\n    return code;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ExpandPercents --\n *\n *\tGiven a command and an event, produce a new command by replacing %\n *\tconstructs in the original command with information from the X event.\n *\n * Results:\n *\tThe new expanded command is appended to the dynamic string given by\n *\tdsPtr.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nExpandPercents(\n     Entry *entryPtr,\t/* Entry that needs validation. */\n     const char *before,\n\t\t\t\t/* Command containing percent expressions to\n\t\t\t\t * be replaced. */\n     const char *change,\t/* Characters to added/deleted (NUL-terminated\n\t\t\t\t * string). */\n     const char *newValue,\t/* Potential new value of entry string */\n     Tcl_Size index,\t\t\t/* index of insert/delete */\n     int type,\t\t\t/* INSERT or DELETE */\n     Tcl_DString *dsPtr)\t/* Dynamic string in which to append new\n\t\t\t\t * command. */\n{\n    Tcl_Size length, spaceNeeded;\n    int cvtFlags;\t/* Used to substitute string as proper Tcl\n\t\t\t\t * list element. */\n    int number, ch;\n    const char *string;\n    char numStorage[2*TCL_INTEGER_SPACE];\n\n    while (1) {\n\tif (*before == '\\0') {\n\t    break;\n\t}\n\t/*\n\t * Find everything up to the next % character and append it to the\n\t * result string.\n\t */\n\n\tstring = before;\n\n\t/*\n\t * No need to convert '%', as it is in ascii range.\n\t */\n\n\tstring = Tcl_UtfFindFirst(before, '%');\n\tif (string == NULL) {\n\t    Tcl_DStringAppend(dsPtr, before, TCL_INDEX_NONE);\n\t    break;\n\t} else if (string != before) {\n\t    Tcl_DStringAppend(dsPtr, before, string-before);\n\t    before = string;\n\t}\n\n\t/*\n\t * There's a percent sequence here. Process it.\n\t */\n\n\tbefore++; /* skip over % */\n\tif (*before != '\\0') {\n\t    before += Tcl_UtfToUniChar(before, &ch);\n\t} else {\n\t    ch = '%';\n\t}\n\tif (type == VALIDATE_BUTTON) {\n\t    /*\n\t     * -command %-substitution\n\t     */\n\n\t    switch (ch) {\n\t    case 's':\t\t/* Current string value of spinbox */\n\t\tstring = entryPtr->string;\n\t\tbreak;\n\t    case 'd':\t\t/* direction, up or down */\n\t\tstring = change;\n\t\tbreak;\n\t    case 'W':\t\t/* widget name */\n\t\tstring = Tk_PathName(entryPtr->tkwin);\n\t\tbreak;\n\t    default:\n\t\tlength = Tcl_UniCharToUtf(ch, numStorage);\n\t\tnumStorage[length] = '\\0';\n\t\tstring = numStorage;\n\t\tbreak;\n\t    }\n\t} else {\n\t    /*\n\t     * -validatecommand / -invalidcommand %-substitution\n\t     */\n\n\t    switch (ch) {\n\t    case 'd':\t\t/* Type of call that caused validation */\n\t\tswitch (type) {\n\t\tcase VALIDATE_INSERT:\n\t\t    number = 1;\n\t\t    break;\n\t\tcase VALIDATE_DELETE:\n\t\t    number = 0;\n\t\t    break;\n\t\tdefault:\n\t\t    number = -1;\n\t\t    break;\n\t\t}\n\t\tsnprintf(numStorage, sizeof(numStorage), \"%d\", number);\n\t\tstring = numStorage;\n\t\tbreak;\n\t    case 'i':\t\t/* index of insert/delete */\n\t\tsnprintf(numStorage, sizeof(numStorage), \"%d\", (int)index);\n\t\tstring = numStorage;\n\t\tbreak;\n\t    case 'P':\t\t/* 'Peeked' new value of the string */\n\t\tstring = newValue;\n\t\tbreak;\n\t    case 's':\t\t/* Current string value of spinbox */\n\t\tstring = entryPtr->string;\n\t\tbreak;\n\t    case 'S':\t\t/* string to be inserted/deleted, if any */\n\t\tstring = change;\n\t\tbreak;\n\t    case 'v':\t\t/* type of validation currently set */\n\t\tstring = validateStrings[entryPtr->validate];\n\t\tbreak;\n\t    case 'V':\t\t/* type of validation in effect */\n\t\tswitch (type) {\n\t\tcase VALIDATE_INSERT:\n\t\tcase VALIDATE_DELETE:\n\t\t    string = validateStrings[VALIDATE_KEY];\n\t\t    break;\n\t\tcase VALIDATE_FORCED:\n\t\t    string = \"forced\";\n\t\t    break;\n\t\tdefault:\n\t\t    string = validateStrings[type];\n\t\t    break;\n\t\t}\n\t\tbreak;\n\t    case 'W': /* widget name */\n\t\tstring = Tk_PathName(entryPtr->tkwin);\n\t\tbreak;\n\t    default:\n\t\tlength = Tcl_UniCharToUtf(ch, numStorage);\n\t\tnumStorage[length] = '\\0';\n\t\tstring = numStorage;\n\t\tbreak;\n\t    }\n\t}\n\n\tspaceNeeded = Tcl_ScanCountedElement(string, TCL_INDEX_NONE, &cvtFlags);\n\tlength = Tcl_DStringLength(dsPtr);\n\tTcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\tspaceNeeded = Tcl_ConvertCountedElement(string, TCL_INDEX_NONE,\n\t\tTcl_DStringValue(dsPtr) + length,\n\t\tcvtFlags | TCL_DONT_USE_BRACES);\n\tTcl_DStringSetLength(dsPtr, length + spaceNeeded);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SpinboxObjCmd --\n *\n *\tThis function is invoked to process the \"spinbox\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SpinboxObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Entry *entryPtr;\n    Spinbox *sbPtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n    char *tmp;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, Tk will return the cached value.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, sbOptSpec);\n\n    /*\n     * Initialize the fields of the structure that won't be initialized by\n     * ConfigureEntry, or that ConfigureEntry requires to be initialized\n     * already (e.g. resource pointers). Only the non-NULL/0 data must be\n     * initialized as memset covers the rest.\n     */\n\n    sbPtr = (Spinbox *)Tcl_Alloc(sizeof(Spinbox));\n    entryPtr\t\t\t= (Entry *) sbPtr;\n    memset(sbPtr, 0, sizeof(Spinbox));\n\n    entryPtr->tkwin\t\t= tkwin;\n    entryPtr->display\t\t= Tk_Display(tkwin);\n    entryPtr->interp\t\t= interp;\n    entryPtr->widgetCmd\t\t= Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(entryPtr->tkwin), SpinboxWidgetObjCmd, sbPtr,\n\t    EntryCmdDeletedProc);\n    entryPtr->optionTable\t= optionTable;\n    entryPtr->type\t\t= TK_SPINBOX;\n    tmp\t\t\t\t= (char *)Tcl_Alloc(1);\n    tmp[0]\t\t\t= '\\0';\n    entryPtr->string\t\t= tmp;\n    entryPtr->selectFirst\t= TCL_INDEX_NONE;\n    entryPtr->selectLast\t= TCL_INDEX_NONE;\n\n    entryPtr->cursor\t\t= NULL;\n    entryPtr->exportSelection\t= true;\n    entryPtr->justify\t\t= TK_JUSTIFY_LEFT;\n    entryPtr->relief\t\t= TK_RELIEF_FLAT;\n    entryPtr->state\t\t= STATE_NORMAL;\n    entryPtr->displayString\t= entryPtr->string;\n    entryPtr->inset\t\t= XPAD;\n    entryPtr->textGC\t\t= NULL;\n    entryPtr->selTextGC\t\t= NULL;\n    entryPtr->highlightGC\t= NULL;\n    entryPtr->avgWidth\t\t= 1;\n    entryPtr->validate\t\t= VALIDATE_NONE;\n\n    sbPtr->selElement\t\t= SEL_NONE;\n    sbPtr->curElement\t\t= SEL_NONE;\n    sbPtr->bCursor\t\t= NULL;\n    sbPtr->repeatDelay\t\t= 400;\n    sbPtr->repeatInterval\t= 100;\n    sbPtr->fromValue\t\t= 0.0;\n    sbPtr->toValue\t\t= 100.0;\n    sbPtr->increment\t\t= 1.0;\n    sbPtr->formatBuf\t\t= (char *)Tcl_Alloc(TCL_DOUBLE_SPACE);\n    sbPtr->bdRelief\t\t= TK_RELIEF_FLAT;\n    sbPtr->buRelief\t\t= TK_RELIEF_FLAT;\n\n    entryPtr->placeholderGC\t= NULL;\n\n    /*\n     * Keep a hold of the associated tkwin until we destroy the spinbox,\n     * otherwise Tk might free it while we still need it.\n     */\n\n    Tcl_Preserve(entryPtr->tkwin);\n\n    Tk_SetClass(entryPtr->tkwin, \"Spinbox\");\n    Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);\n    Tk_CreateEventHandler(entryPtr->tkwin,\n\t    PointerMotionMask|ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    EntryEventProc, entryPtr);\n    Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,\n\t    EntryFetchSelection, entryPtr, XA_STRING);\n\n    if (Tk_InitOptions(interp, sbPtr, optionTable, tkwin)\n\t    != TCL_OK) {\n\tTk_DestroyWindow(entryPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n    if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) {\n\tgoto error;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(entryPtr->tkwin));\n    return TCL_OK;\n\n  error:\n    Tk_DestroyWindow(entryPtr->tkwin);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SpinboxWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSpinboxWidgetObjCmd(\n    void *clientData,\t/* Information about spinbox widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Entry *entryPtr = (Entry *)clientData;\n    Spinbox *sbPtr = (Spinbox *)clientData;\n    int cmdIndex, selIndex, result;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the widget command by looking up the second token in the list of\n     * valid command names.\n     */\n\n    result = Tcl_GetIndexFromObj(interp, objv[1], sbCmdNames,\n\t    \"option\", 0, &cmdIndex);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    Tcl_Preserve(entryPtr);\n    switch ((enum sbCmd) cmdIndex) {\n    case SB_CMD_BBOX: {\n\tTcl_Size index;\n\tint x, y, width, height;\n\tTcl_Obj *bbox[4];\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif ((index == entryPtr->numChars) && (index > 0)) {\n\t    index--;\n\t}\n\tTk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);\n\tbbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX);\n\tbbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY);\n\tbbox[2] = Tcl_NewWideIntObj(width);\n\tbbox[3] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));\n\tbreak;\n    }\n\n    case SB_CMD_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    goto error;\n\t}\n\n\tobjPtr = Tk_GetOptionValue(interp, entryPtr,\n\t\tentryPtr->optionTable, objv[2], entryPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n\n    case SB_CMD_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, entryPtr,\n\t\t    entryPtr->optionTable, (objc == 3) ? objv[2] : NULL,\n\t\t    entryPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);\n\t}\n\tbreak;\n\n    case SB_CMD_DELETE: {\n\tTcl_Size first, last;\n\tint code;\n\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"firstIndex ?lastIndex?\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&first) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (objc == 3) {\n\t    last = first + 1;\n\t} else {\n\t    if (GetEntryIndex(interp, entryPtr, objv[3],\n\t\t    &last) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tif ((last >= first) && (entryPtr->state == STATE_NORMAL)) {\n\t    code = DeleteChars(entryPtr, first, last - first);\n\t    if (code != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n    }\n\n    case SB_CMD_GET:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, TCL_INDEX_NONE));\n\tbreak;\n\n    case SB_CMD_ICURSOR:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pos\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&entryPtr->insertPos) != TCL_OK) {\n\t    goto error;\n\t}\n\tEventuallyRedraw(entryPtr);\n\tbreak;\n\n    case SB_CMD_IDENTIFY: {\n\tint x, y, elem;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"x y\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) ||\n\t\t(Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    goto error;\n\t}\n\telem = GetSpinboxElement(sbPtr, x, y);\n\tif (elem != SEL_NONE) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(selElementNames[elem], TCL_INDEX_NONE));\n\t}\n\tbreak;\n    }\n\n    case SB_CMD_INDEX: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"string\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(index));\n\tbreak;\n    }\n\n    case SB_CMD_INSERT: {\n\tTcl_Size index;\n\tint code;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index text\");\n\t    goto error;\n\t}\n\tif (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t&index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (entryPtr->state == STATE_NORMAL) {\n\t    code = InsertChars(entryPtr, index, objv[3]);\n\t    if (code != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n    }\n\n    case SB_CMD_INVOKE:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"elemName\");\n\t    goto error;\n\t}\n\tresult = Tcl_GetIndexFromObj(interp, objv[2],\n\t\tselElementNames, \"element\", 0, &cmdIndex);\n\tif (result != TCL_OK) {\n\t    goto error;\n\t}\n\tif (entryPtr->state != STATE_DISABLED) {\n\t    if (SpinboxInvoke(interp, sbPtr, cmdIndex) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tbreak;\n\n    case SB_CMD_SCAN: {\n\tint x;\n\tconst char *minorCmd;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"mark|dragto x\");\n\t    goto error;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tminorCmd = Tcl_GetString(objv[2]);\n\tif (minorCmd[0] == 'm'\n\t\t&& (strncmp(minorCmd, \"mark\", strlen(minorCmd)) == 0)) {\n\t    entryPtr->scanMarkX = x;\n\t    entryPtr->scanMarkIndex = entryPtr->leftIndex;\n\t} else if ((minorCmd[0] == 'd')\n\t\t&& (strncmp(minorCmd, \"dragto\", strlen(minorCmd)) == 0)) {\n\t    EntryScanTo(entryPtr, x);\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad scan option \\\"%s\\\": must be dragto or mark\",\n\t\t    minorCmd));\n\t    Tcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"scan option\",\n\t\t    minorCmd, (char *)NULL);\n\t    goto error;\n\t}\n\tbreak;\n    }\n\n    case SB_CMD_SELECTION: {\n\tTcl_Size index, index2;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option ?index?\");\n\t    goto error;\n\t}\n\n\t/*\n\t * Parse the selection sub-command, using the command table\n\t * \"sbSelCmdNames\" defined above.\n\t */\n\n\tresult = Tcl_GetIndexFromObj(interp, objv[2], sbSelCmdNames,\n\t\t\"selection option\", 0, &selIndex);\n\tif (result != TCL_OK) {\n\t    goto error;\n\t}\n\n\t/*\n\t * Disabled entries don't allow the selection to be modified, but\n\t * 'selection present' must return a boolean.\n\t */\n\n\tif ((entryPtr->state == STATE_DISABLED)\n\t\t&& (selIndex != SB_SEL_PRESENT)) {\n\t    goto done;\n\t}\n\n\tswitch (selIndex) {\n\tcase SB_SEL_ADJUST:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (entryPtr->selectFirst != TCL_INDEX_NONE) {\n\t\tTcl_Size half1, half2;\n\n\t\thalf1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;\n\t\thalf2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;\n\t\tif (index < half1) {\n\t\t    entryPtr->selectAnchor = entryPtr->selectLast;\n\t\t} else if (index > half2) {\n\t\t    entryPtr->selectAnchor = entryPtr->selectFirst;\n\t\t} else {\n\t\t    /*\n\t\t     * We're at about the halfway point in the selection; just\n\t\t     * keep the existing anchor.\n\t\t     */\n\t\t}\n\t    }\n\t    EntrySelectTo(entryPtr, index);\n\t    break;\n\n\tcase SB_SEL_CLEAR:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tgoto error;\n\t    }\n\t    if (entryPtr->selectFirst != TCL_INDEX_NONE) {\n\t\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\t\tentryPtr->selectLast = TCL_INDEX_NONE;\n\t\tEventuallyRedraw(entryPtr);\n\t    }\n\t    goto done;\n\n\tcase SB_SEL_FROM:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    entryPtr->selectAnchor = index;\n\t    break;\n\n\tcase SB_SEL_PRESENT:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\t    entryPtr->selectFirst != TCL_INDEX_NONE));\n\t    goto done;\n\n\tcase SB_SEL_RANGE:\n\t    if (objc != 5) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"start end\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[4],& index2) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (index >= index2) {\n\t\tentryPtr->selectFirst = TCL_INDEX_NONE;\n\t\tentryPtr->selectLast = TCL_INDEX_NONE;\n\t    } else {\n\t\tentryPtr->selectFirst = index;\n\t\tentryPtr->selectLast = index2;\n\t    }\n\t    if (!(entryPtr->flags & GOT_SELECTION)\n\t\t    && entryPtr->exportSelection\n\t\t    && (!Tcl_IsSafe(entryPtr->interp))) {\n\t\tTk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,\n\t\t\tEntryLostSelection, entryPtr);\n\t\tentryPtr->flags |= GOT_SELECTION;\n\t    }\n\t    EventuallyRedraw(entryPtr);\n\t    break;\n\n\tcase SB_SEL_TO:\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t\tgoto error;\n\t    }\n\t    if (GetEntryIndex(interp, entryPtr,\n\t\t    objv[3], &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    EntrySelectTo(entryPtr, index);\n\t    break;\n\n\tcase SB_SEL_ELEMENT:\n\t    if ((objc < 3) || (objc > 4)) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"?elemName?\");\n\t\tgoto error;\n\t    }\n\t    if (objc == 3) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tselElementNames[sbPtr->selElement], TCL_INDEX_NONE));\n\t    } else {\n\t\tint lastElement = sbPtr->selElement;\n\n\t\tresult = Tcl_GetIndexFromObj(interp, objv[3], selElementNames,\n\t\t\t\"selection element\", 0, &(sbPtr->selElement));\n\t\tif (result != TCL_OK) {\n\t\t    goto error;\n\t\t}\n\t\tif (lastElement != sbPtr->selElement) {\n\t\t    EventuallyRedraw(entryPtr);\n\t\t}\n\t    }\n\t    break;\n\t}\n\tbreak;\n    }\n\n    case SB_CMD_SET: {\n\tint code = TCL_OK;\n\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?string?\");\n\t    goto error;\n\t}\n\tif (objc == 3) {\n\t    code = EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));\n\t    if (code != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, TCL_INDEX_NONE));\n\tbreak;\n    }\n\n    case SB_CMD_VALIDATE: {\n\tint code;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    goto error;\n\t}\n\tselIndex = entryPtr->validate;\n\tentryPtr->validate = VALIDATE_ALL;\n\tcode = EntryValidateChange(entryPtr, NULL, entryPtr->string,\n\t\tTCL_INDEX_NONE, VALIDATE_FORCED);\n\tif (entryPtr->validate != VALIDATE_NONE) {\n\t    entryPtr->validate = selIndex;\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));\n\tbreak;\n    }\n\n    case SB_CMD_XVIEW: {\n\tTcl_Size index;\n\n\tif (objc == 2) {\n\t    double first, last;\n\t    Tcl_Obj *span[2];\n\n\t    EntryVisibleRange(entryPtr, &first, &last);\n\t    span[0] = Tcl_NewDoubleObj(first);\n\t    span[1] = Tcl_NewDoubleObj(last);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, span));\n\t    goto done;\n\t} else if (objc == 3) {\n\t    if (GetEntryIndex(interp, entryPtr, objv[2],\n\t\t    &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t} else {\n\t    double fraction;\n\t    int count;\n\n\t    index = entryPtr->leftIndex;\n\t    switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,\n\t\t    &count)) {\n\t    case TK_SCROLL_MOVETO:\n\t\tindex = (Tcl_Size)((fraction * (double)entryPtr->numChars) + 0.5);\n\t\tbreak;\n\t    case TK_SCROLL_PAGES: {\n\t\tint charsPerPage;\n\n\t\tcharsPerPage = ((Tk_Width(entryPtr->tkwin)\n\t\t\t- 2 * entryPtr->inset - entryPtr->xWidth)\n\t\t\t/ entryPtr->avgWidth) - 2;\n\t\tif (charsPerPage < 1) {\n\t\t    charsPerPage = 1;\n\t\t}\n\t\tindex += count * charsPerPage;\n\t\tbreak;\n\t    }\n\t    case TK_SCROLL_UNITS:\n\t\tindex += count;\n\t\tbreak;\n\t    default:\n\t\tgoto error;\n\t    }\n\t}\n\tif (index >= entryPtr->numChars) {\n\t    index = entryPtr->numChars - 1;\n\t}\n\tif (index < 0) {\n\t    index = 0;\n\t}\n\tentryPtr->leftIndex = index;\n\tentryPtr->flags |= UPDATE_SCROLLBAR;\n\tEntryComputeGeometry(entryPtr);\n\tEventuallyRedraw(entryPtr);\n\tbreak;\n    }\n    }\n\n  done:\n    Tcl_Release(entryPtr);\n    return result;\n\n  error:\n    Tcl_Release(entryPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetSpinboxElement --\n *\n *\tReturn the element associated with an x,y coord.\n *\n * Results:\n *\tElement type as enum selelement.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetSpinboxElement(\n    Spinbox *sbPtr,\t\t/* Spinbox for which the index is being\n\t\t\t\t * specified. */\n    int x, int y)\t\t/* Widget-relative coordinates. */\n{\n    Entry *entryPtr = (Entry *) sbPtr;\n\n    if ((x < 0) || (y < 0) || (y > Tk_Height(entryPtr->tkwin))\n\t    || (x > Tk_Width(entryPtr->tkwin))) {\n\treturn SEL_NONE;\n    }\n\n    if (x > (Tk_Width(entryPtr->tkwin) - entryPtr->inset - entryPtr->xWidth)) {\n\tif (y > (Tk_Height(entryPtr->tkwin) / 2)) {\n\t    return SEL_BUTTONDOWN;\n\t} else {\n\t    return SEL_BUTTONUP;\n\t}\n    }\n    return SEL_ENTRY;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SpinboxInvoke --\n *\n *\tThis function is invoked when the invoke method for the widget is\n *\tcalled.\n *\n * Results:\n *\tTCL_OK.\n *\n * Side effects:\n *\tA background error condition may arise when invoking the callback.\n *\tThe widget value may change.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSpinboxInvoke(\n    Tcl_Interp *interp,/* Current interpreter. */\n    Spinbox *sbPtr,\t/* Spinbox to invoke. */\n    int element)\t\t/* Element to invoke, either the \"up\" or\n\t\t\t\t * \"down\" button. */\n{\n    Entry *entryPtr = (Entry *) sbPtr;\n    const char *type;\n    int code, up;\n    Tcl_DString script;\n\n    switch (element) {\n    case SEL_BUTTONUP:\n\ttype = \"up\";\n\tup = 1;\n\tbreak;\n    case SEL_BUTTONDOWN:\n\ttype = \"down\";\n\tup = 0;\n\tbreak;\n    default:\n\treturn TCL_OK;\n    }\n\n    code = TCL_OK;\n    if (fabs(sbPtr->increment) > MIN_DBL_VAL) {\n\tif (sbPtr->listObj != NULL) {\n\t    Tcl_Obj *objPtr;\n\n\t    Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);\n\t    if (strcmp(Tcl_GetString(objPtr), entryPtr->string)) {\n\t\t/*\n\t\t * Somehow the string changed from what we expected, so let's\n\t\t * do a search on the list to see if the current value is\n\t\t * there. If not, move to the first element of the list.\n\t\t */\n\n\t\tTcl_Size i, listc;\n\t\tTcl_Size elemLen, length = entryPtr->numChars;\n\t\tconst char *bytes;\n\t\tTcl_Obj **listv;\n\n\t\tTcl_ListObjGetElements(interp, sbPtr->listObj, &listc, &listv);\n\t\tfor (i = 0; i < listc; i++) {\n\t\t    bytes = Tcl_GetStringFromObj(listv[i], &elemLen);\n\t\t    if ((length == elemLen) &&\n\t\t\t    (memcmp(bytes, entryPtr->string,\n\t\t\t\t    length) == 0)) {\n\t\t\tsbPtr->eIndex = i;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t    if (up) {\n\t\tif (++sbPtr->eIndex >= sbPtr->nElements) {\n\t\t    if (sbPtr->wrap) {\n\t\t\tsbPtr->eIndex = 0;\n\t\t    } else {\n\t\t\tsbPtr->eIndex = sbPtr->nElements-1;\n\t\t    }\n\t\t}\n\t    } else {\n\t\tif (--sbPtr->eIndex < 0) {\n\t\t    if (sbPtr->wrap) {\n\t\t\tsbPtr->eIndex = sbPtr->nElements-1;\n\t\t    } else {\n\t\t\tsbPtr->eIndex = 0;\n\t\t    }\n\t\t}\n\t    }\n\t    Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);\n\t    code = EntryValueChanged(entryPtr, Tcl_GetString(objPtr));\n\t} else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) {\n\t    double dvalue;\n\n\t    if (sscanf(entryPtr->string, \"%lf\", &dvalue) <= 0) {\n\t\t/*\n\t\t * If the string doesn't scan as a double value, just\n\t\t * use the -from value\n\t\t */\n\n\t\tdvalue = sbPtr->fromValue;\n\t    } else if (up) {\n\t\tdvalue += sbPtr->increment;\n\t\tif (dvalue > sbPtr->toValue) {\n\t\t    if (sbPtr->wrap) {\n\t\t\tdvalue = sbPtr->fromValue;\n\t\t    } else {\n\t\t\tdvalue = sbPtr->toValue;\n\t\t    }\n\t\t} else if (dvalue < sbPtr->fromValue) {\n\t\t    /*\n\t\t     * It's possible that when pressing up, we are still less\n\t\t     * than the fromValue, because the user may have\n\t\t     * manipulated the value by hand.\n\t\t     */\n\n\t\t    dvalue = sbPtr->fromValue;\n\t\t}\n\t    } else {\n\t\tdvalue -= sbPtr->increment;\n\t\tif (dvalue < sbPtr->fromValue) {\n\t\t    if (sbPtr->wrap) {\n\t\t\tdvalue = sbPtr->toValue;\n\t\t    } else {\n\t\t\tdvalue = sbPtr->fromValue;\n\t\t    }\n\t\t} else if (dvalue > sbPtr->toValue) {\n\t\t    /*\n\t\t     * It's possible that when pressing down, we are still\n\t\t     * greater than the toValue, because the user may have\n\t\t     * manipulated the value by hand.\n\t\t     */\n\n\t\t    dvalue = sbPtr->toValue;\n\t\t}\n\t    }\n\t    snprintf(sbPtr->formatBuf, TCL_DOUBLE_SPACE, sbPtr->valueFormat, dvalue);\n\t    code = EntryValueChanged(entryPtr, sbPtr->formatBuf);\n\t}\n    }\n    if (code != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (sbPtr->commandObj != NULL) {\n\tTcl_DStringInit(&script);\n\tExpandPercents(entryPtr, Tcl_GetString(sbPtr->commandObj), type, \"\", 0,\n\t\tVALIDATE_BUTTON, &script);\n\tTcl_DStringAppend(&script, \"\", 1);\n\n\tcode = Tcl_EvalEx(interp, Tcl_DStringValue(&script), TCL_INDEX_NONE,\n\t\tTCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);\n\tTcl_DStringFree(&script);\n\n\tif (code != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (in command executed by spinbox)\");\n\t    Tcl_BackgroundException(interp, code);\n\n\t    /*\n\t     * Yes, it's an error, but a bg one, so we return OK\n\t     */\n\n\t    return TCL_OK;\n\t}\n\n\tTcl_ResetResult(interp);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeFormat --\n *\n *\tThis function is invoked to recompute the \"format\" fields of a\n *\tspinbox's widget record, which determines how the value of the dial is\n *\tconverted to a string.\n *\n * Results:\n *\tTcl result code.\n *\n * Side effects:\n *\tThe format fields of the spinbox are modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nComputeFormat(\n     Spinbox *sbPtr)\t\t/* Information about dial widget. */\n{\n    double maxValue, x;\n    int mostSigDigit, numDigits, leastSigDigit, afterDecimal;\n    int eDigits, fDigits;\n\n    /*\n     * Compute the displacement from the decimal of the most significant digit\n     * required for any number in the dial's range.\n     */\n\n    if (sbPtr->reqFormatObj) {\n\tsbPtr->valueFormat = Tcl_GetString(sbPtr->reqFormatObj);\n\treturn TCL_OK;\n    }\n\n    maxValue = fabs(sbPtr->fromValue);\n    x = fabs(sbPtr->toValue);\n    if (x > maxValue) {\n\tmaxValue = x;\n    }\n    if (maxValue == 0) {\n\tmaxValue = 1;\n    }\n    mostSigDigit = (int) floor(log10(maxValue));\n\n    if (fabs(sbPtr->increment) > MIN_DBL_VAL) {\n\t/*\n\t * A increment was specified, so use it.\n\t */\n\n\tleastSigDigit = (int) floor(log10(sbPtr->increment));\n    } else {\n\tleastSigDigit = 0;\n    }\n    numDigits = mostSigDigit - leastSigDigit + 1;\n    if (numDigits < 1) {\n\tnumDigits = 1;\n    }\n\n    /*\n     * Compute the number of characters required using \"e\" format and \"f\"\n     * format, and then choose whichever one takes fewer characters.\n     */\n\n    eDigits = numDigits + 4;\n    if (numDigits > 1) {\n\teDigits++;\t\t/* Decimal point. */\n    }\n    afterDecimal = numDigits - mostSigDigit - 1;\n    if (afterDecimal < 0) {\n\tafterDecimal = 0;\n    }\n    fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;\n    if (afterDecimal > 0) {\n\tfDigits++;\t\t/* Decimal point. */\n    }\n    if (mostSigDigit < 0) {\n\tfDigits++;\t\t/* Zero to left of decimal point. */\n    }\n    if (fDigits <= eDigits) {\n\tsnprintf(sbPtr->digitFormat, sizeof(sbPtr->digitFormat), \"%%.%df\", afterDecimal);\n    } else {\n\tsnprintf(sbPtr->digitFormat, sizeof(sbPtr->digitFormat), \"%%.%de\", numDigits-1);\n    }\n    sbPtr->valueFormat = sbPtr->digitFormat;\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkEntry.h",
    "content": "/*\n *  tkEntry.h --\n *\n * This module defined the structures for the Entry & SpinBox widgets.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Copyright © 2002 Apple Inc.\n */\n\n#ifndef _TKENTRY\n#define _TKENTRY\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\nenum EntryType {\n    TK_ENTRY, TK_SPINBOX\n};\n\n/*\n * A data structure of the following type is kept for each Entry widget\n * managed by this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the entry. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up.*/\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with entry. */\n    Tcl_Command widgetCmd;\t/* Token for entry's widget command. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n    enum EntryType type;\t/* Specialized type of Entry widget */\n\n    /*\n     * Fields that are set by widget commands other than \"configure\".\n     */\n\n    const char *string;\t\t/* Pointer to storage for string;\n\t\t\t\t * NULL-terminated; malloc-ed. */\n    Tcl_Size insertPos;\t\t/* Character index before which next typed\n\t\t\t\t * character will be inserted. */\n\n    /*\n     * Information about what's selected, if any.\n     */\n\n    Tcl_Size selectFirst;\t\t/* Character index of first selected character\n\t\t\t\t * (-1 means nothing selected. */\n    Tcl_Size selectLast;\t\t/* Character index just after last selected\n\t\t\t\t * character (-1 means nothing selected. */\n    Tcl_Size selectAnchor;\t\t/* Fixed end of selection (i.e. \"select to\"\n\t\t\t\t * operation will use this as one end of the\n\t\t\t\t * selection). */\n\n    /*\n     * Information for scanning:\n     */\n\n    int scanMarkX;\t\t/* X-position at which scan started (e.g.\n\t\t\t\t * button was pressed here). */\n    Tcl_Size scanMarkIndex;\t\t/* Character index of character that was at\n\t\t\t\t * left of window when scan started. */\n\n    /*\n     * Configuration settings that are updated by Tk_ConfigureWidget.\n     */\n\n    Tk_3DBorder normalBorder;\t/* Used for drawing border around whole\n\t\t\t\t * window, plus used for background. */\n    Tk_3DBorder disabledBorder;\t/* Used for drawing border around whole window\n\t\t\t\t * in disabled state, plus used for\n\t\t\t\t * background. */\n    Tk_3DBorder readonlyBorder;\t/* Used for drawing border around whole window\n\t\t\t\t * in readonly state, plus used for\n\t\t\t\t * background. */\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border around window. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    bool exportSelection;\t/* True means tie internal entry selection\n\t\t\t\t * to X selection. */\n    Tk_Font tkfont;\t\t/* Information about text font, or NULL. */\n    XColor *fgColorPtr;\t\t/* Text color in normal mode. */\n    XColor *dfgColorPtr;\t/* Text color in disabled mode. */\n    XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. <= 0 means\n\t\t\t\t * don't draw a highlight. */\n    Tk_3DBorder insertBorder;\t/* Used to draw vertical bar for insertion\n\t\t\t\t * cursor. */\n    Tcl_Obj *insertBorderWidthObj;\t/* Width of 3-D border around insert cursor. */\n    int insertOffTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"off\" state for each blink. */\n    int insertOnTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"on\" state for each blink. */\n    Tcl_Obj *insertWidthObj;\t/* Total width of insert cursor. */\n    Tk_Justify justify;\t\t/* Justification to use for text within\n\t\t\t\t * window. */\n    int relief;\t\t\t/* 3-D effect: TK_RELIEF_RAISED, etc. */\n    Tk_3DBorder selBorder;\t/* Border and background for selected\n\t\t\t\t * characters. */\n    Tcl_Obj *selBorderWidthObj;\t/* Width of border around selection. */\n    XColor *selFgColorPtr;\t/* Foreground color for selected text. */\n    int state;\t\t\t/* Normal or disabled. Entry is read-only when\n\t\t\t\t * disabled. */\n    Tcl_Obj *textVarNameObj;\t\t/* Name of variable (malloc'ed) or NULL. If\n\t\t\t\t * non-NULL, entry's string tracks the\n\t\t\t\t * contents of this variable and vice\n\t\t\t\t * versa. */\n    Tcl_Obj *takeFocusObj;\t\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    int prefWidth;\t\t/* Desired width of window, measured in\n\t\t\t\t * average characters. */\n    Tcl_Obj *scrollCmdObj;\t/* Command prefix for communicating with\n\t\t\t\t * scrollbar(s). NULL means no command to issue. */\n    Tcl_Obj *showCharObj;\t/* Value of -show option. If non-NULL, first\n\t\t\t\t * character is used for displaying all\n\t\t\t\t * characters in entry. This is\n\t\t\t\t * only used by the Entry widget. */\n\n    /*\n     * Fields whose values are derived from the current values of the\n     * configuration settings above.\n     */\n\n    const char *displayString;\t/* String to use when displaying. This may be\n\t\t\t\t * a pointer to string, or a pointer to\n\t\t\t\t * malloced memory with the same character\n\t\t\t\t * length as string but whose characters are\n\t\t\t\t * all equal to showChar. */\n    Tcl_Size numBytes;\t\t/* Length of string in bytes. */\n    Tcl_Size numChars;\t\t/* Length of string in characters. Both string\n\t\t\t\t * and displayString have the same character\n\t\t\t\t * length, but may have different byte lengths\n\t\t\t\t * due to being made from different UTF-8\n\t\t\t\t * characters. */\n    Tcl_Size numDisplayBytes;\t/* Length of displayString in bytes. */\n    int inset;\t\t\t/* Number of pixels on the left and right\n\t\t\t\t * sides that are taken up by XPAD,\n\t\t\t\t * borderWidth (if any), and highlightWidth\n\t\t\t\t * (if any). */\n    Tk_TextLayout textLayout;\t/* Cached text layout information. */\n    int layoutX, layoutY;\t/* Origin for layout. */\n    int leftX;\t\t\t/* X position at which character at leftIndex\n\t\t\t\t * is drawn (varies depending on justify). */\n    Tcl_Size leftIndex;\t\t/* Character index of left-most character\n\t\t\t\t * visible in window. */\n    Tcl_TimerToken insertBlinkHandler;\n\t\t\t\t/* Timer handler used to blink cursor on and\n\t\t\t\t * off. */\n    GC textGC;\t\t\t/* For drawing normal text. */\n    GC selTextGC;\t\t/* For drawing selected text. */\n    GC highlightGC;\t\t/* For drawing traversal highlight. */\n    int avgWidth;\t\t/* Width of average character. */\n    int xWidth;\t\t\t/* Extra width to reserve for widget. Used by\n\t\t\t\t * spinboxes for button space. */\n    int flags;\t\t\t/* Miscellaneous flags; see below for\n\t\t\t\t * definitions. */\n\n    int validate;\t\t/* Non-zero means try to validate */\n    Tcl_Obj *validateCmdObj;\t\t/* Command prefix to use when invoking\n\t\t\t\t * validate command. NULL means don't invoke commands. */\n    Tcl_Obj *invalidCmdObj;\t\t/* Command called when a validation returns 0\n\t\t\t\t * (successfully fails), defaults to {}. */\n    /*\n     * Fields used in displaying help text if entry value is empty\n     */\n\n    Tk_TextLayout placeholderLayout;/* Cached placeholder text layout information. */\n    Tcl_Obj *placeholderObj;\t/* String value of placeholder. */\n    Tcl_Size placeholderChars;\t/* Number of chars in placeholder. */\n    XColor *placeholderColorPtr;/* Color value of placeholder foreground. */\n    GC placeholderGC;\t\t/* For drawing placeholder text. */\n    int placeholderX;\t\t/* Origin for layout. */\n    Tcl_Size placeholderLeftIndex;\t/* Character index of left-most character\n\t\t\t\t * visible in window. */\n} Entry;\n\n/*\n * A data structure of the following type is kept for each spinbox widget\n * managed by this file:\n */\n\ntypedef struct {\n    Entry entry;\t\t/* A pointer to the generic entry structure.\n\t\t\t\t * This must be the first element of the\n\t\t\t\t * Spinbox. */\n\n    /*\n     * Spinbox specific configuration settings.\n     */\n\n    Tk_3DBorder activeBorder;\t/* Used for drawing border around active\n\t\t\t\t * buttons. */\n    Tk_3DBorder buttonBorder;\t/* Used for drawing border around buttons. */\n    Tk_Cursor bCursor;\t\t/* cursor for buttons, or NULL. */\n    int bdRelief;\t\t/* 3-D effect: TK_RELIEF_RAISED, etc. */\n    int buRelief;\t\t/* 3-D effect: TK_RELIEF_RAISED, etc. */\n    Tcl_Obj *commandObj;\t/* Command to invoke for spin buttons. NULL\n\t\t\t\t * means no command to issue. */\n\n    /*\n     * Spinbox specific fields for use with configuration settings above.\n     */\n\n    bool wrap;\t\t\t/* whether to wrap around when spinning */\n\n    int selElement;\t\t/* currently selected control */\n    int curElement;\t\t/* currently mouseover control */\n\n    int repeatDelay;\t\t/* repeat delay */\n    int repeatInterval;\t\t/* repeat interval */\n\n    double fromValue;\t\t/* Value corresponding to left/top of dial */\n    double toValue;\t\t/* Value corresponding to right/bottom of\n\t\t\t\t * dial */\n    double increment;\t\t/* If > 0, all values are rounded to an even\n\t\t\t\t * multiple of this value. */\n    char *formatBuf;\t\t/* string into which to format value.\n\t\t\t\t * Malloc'ed. */\n    Tcl_Obj *reqFormatObj;\t/* Snprintf conversion specifier used for the\n\t\t\t\t * value that the users requests. Malloc'ed */\n    char *valueFormat;\t\t/* Snprintf conversion specifier used for the\n\t\t\t\t * value. */\n    char digitFormat[16];\t/* Snprintf conversion specifier computed from\n\t\t\t\t * digits and other information; used for the\n\t\t\t\t * value. */\n\n    Tcl_Obj *valueObj;\t\t/* Values List. */\n    Tcl_Obj *listObj;\t\t/* Pointer to the list object being used */\n    Tcl_Size eIndex;\t\t\t/* Holds the current index into elements */\n    Tcl_Size nElements;\t\t/* Holds the current count of elements */\n} Spinbox;\n\n/*\n * Assigned bits of \"flags\" fields of Entry structures, and what those bits\n * mean:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redisplay the entry.\n * BORDER_NEEDED:\t\tNon-zero means 3-D border must be redrawn\n *\t\t\t\taround window during redisplay. Normally only\n *\t\t\t\ttext portion needs to be redrawn.\n * CURSOR_ON:\t\t\tNon-zero means insert cursor is displayed at\n *\t\t\t\tpresent. 0 means it isn't displayed.\n * GOT_FOCUS:\t\t\tNon-zero means this window has the input\n *\t\t\t\tfocus.\n * UPDATE_SCROLLBAR:\t\tNon-zero means scrollbar should be updated\n *\t\t\t\tduring next redisplay operation.\n * GOT_SELECTION:\t\tNon-zero means we've claimed the selection.\n * ENTRY_DELETED:\t\tThis entry has been effectively destroyed.\n * VALIDATING:\t\t\tNon-zero means we are in a validateCmd\n * VALIDATE_VAR:\t\tNon-zero means we are attempting to validate\n *\t\t\t\tthe entry's textvariable with validateCmd\n * VALIDATE_ABORT:\t\tNon-zero if validatecommand signals an abort\n *\t\t\t\tfor current procedure and make no changes\n * ENTRY_VAR_TRACED:\t\tNon-zero if a var trace is set.\n */\n\n#define REDRAW_PENDING\t\t1\n#define BORDER_NEEDED\t\t2\n#define CURSOR_ON\t\t4\n#define GOT_FOCUS\t\t8\n#define UPDATE_SCROLLBAR\t0x10\n#define GOT_SELECTION\t\t0x20\n#define ENTRY_DELETED\t\t0x40\n#define VALIDATING\t\t0x80\n#define VALIDATE_VAR\t\t0x100\n#define VALIDATE_ABORT\t\t0x200\n#define ENTRY_VAR_TRACED\t0x400\n\n/*\n * The following enum is used to define a type for the -state option of the\n * Entry widget. These values are used as indices into the string table below.\n */\n\nenum state {\n    STATE_DISABLED, STATE_NORMAL, STATE_READONLY\n};\n\n/*\n * This is the element index corresponding to the strings in selElementNames.\n * If you modify them, you must modify the numbers here.\n */\n\nenum selelement {\n    SEL_BUTTONDOWN, SEL_BUTTONUP, SEL_NONE, SEL_NULL, SEL_ENTRY\n};\n\n/*\n * Declaration of functions used in the implementation of the native side of\n * the Entry widget.\n */\n\nMODULE_SCOPE bool\tTkpDrawEntryBorderAndFocus(Entry *entryPtr,\n\t\t\t    Drawable d, bool isSpinbox);\nMODULE_SCOPE int\tTkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d);\n\n#endif /* _TKENTRY */\n"
  },
  {
    "path": "generic/tkError.c",
    "content": "/*\n * tkError.c --\n *\n *\tThis file provides a high-performance mechanism for selectively\n *\tdealing with errors that occur in talking to the X server. This is\n *\tuseful, for example, when communicating with a window that may not\n *\texist.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The default X error handler gets saved here, so that it can be invoked if\n * an error occurs that we can't handle.\n */\n\ntypedef int (*TkXErrorHandler)(Display *display, XErrorEvent *eventPtr);\nstatic TkXErrorHandler\tdefaultHandler = NULL;\n\n/*\n * Forward references to procedures declared later in this file:\n */\n\nstatic int\tErrorProc(Display *display, XErrorEvent *errEventPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateErrorHandler --\n *\n *\tArrange for all a given procedure to be invoked whenever certain\n *\terrors occur.\n *\n * Results:\n *\tThe return value is a token identifying the handler; it must be passed\n *\tto Tk_DeleteErrorHandler to delete the handler.\n *\n * Side effects:\n *\tIf an X error occurs that matches the error, request, and minor\n *\targuments, then errorProc will be invoked. ErrorProc should have the\n *\tfollowing structure:\n *\n *\tint\n *\terrorProc(caddr_t clientData, XErrorEvent *errorEventPtr) {\n *\t}\n *\n *\tThe clientData argument will be the same as the clientData argument to\n *\tthis procedure, and errorEvent will describe the error. If errorProc\n *\treturns 0, it means that it completely \"handled\" the error: no further\n *\tprocessing should be done. If errorProc returns 1, it means that it\n *\tdidn't know how to deal with the error, so we should look for other\n *\terror handlers, or invoke the default error handler if no other\n *\thandler returns zero. Handlers are invoked in order of age: youngest\n *\thandler first.\n *\n *\tNote: errorProc will only be called for errors associated with X\n *\trequests made AFTER this call, but BEFORE the handler is deleted by\n *\tcalling Tk_DeleteErrorHandler.\n *\n *--------------------------------------------------------------\n */\n\nTk_ErrorHandler\nTk_CreateErrorHandler(\n    Display *display,\t\t/* Display for which to handle errors. */\n    int error,\t\t\t/* Consider only errors with this error_code\n\t\t\t\t * (-1 means consider all errors). */\n    int request,\t\t/* Consider only errors with this major\n\t\t\t\t * request code (-1 means consider all major\n\t\t\t\t * codes). */\n    int minorCode,\t\t/* Consider only errors with this minor\n\t\t\t\t * request code (-1 means consider all minor\n\t\t\t\t * codes). */\n    Tk_ErrorProc *errorProc,\t/* Procedure to invoke when a matching error\n\t\t\t\t * occurs. NULL means just ignore matching\n\t\t\t\t * errors. */\n    void *clientData)\t/* Arbitrary value to pass to errorProc. */\n{\n    TkErrorHandler *errorPtr;\n    TkDisplay *dispPtr;\n\n    /*\n     * Find the display. If Tk doesn't know about this display then it's an\n     * error: panic.\n     */\n\n    dispPtr = TkGetDisplay(display);\n    if (dispPtr == NULL) {\n\tTcl_Panic(\"Unknown display passed to Tk_CreateErrorHandler\");\n    }\n\n    /*\n     * Make sure that X calls us whenever errors occur.\n     */\n\n    if (defaultHandler == NULL) {\n\tdefaultHandler = XSetErrorHandler(ErrorProc);\n    }\n\n    /*\n     * Create the handler record.\n     */\n\n    errorPtr = (TkErrorHandler *)Tcl_Alloc(sizeof(TkErrorHandler));\n    errorPtr->dispPtr = dispPtr;\n    errorPtr->firstRequest = NextRequest(display);\n    errorPtr->lastRequest = (unsigned long) -1;\n    errorPtr->error = error;\n    errorPtr->request = request;\n    errorPtr->minorCode = minorCode;\n    errorPtr->errorProc = errorProc;\n    errorPtr->clientData = clientData;\n    errorPtr->nextPtr = dispPtr->errorPtr;\n    dispPtr->errorPtr = errorPtr;\n\n    return (Tk_ErrorHandler) errorPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DeleteErrorHandler --\n *\n *\tDo not use an error handler anymore.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe handler denoted by the \"handler\" argument will not be invoked for\n *\tany X errors associated with requests made after this call. However,\n *\tif errors arrive later for requests made BEFORE this call, then the\n *\thandler will still be invoked. Call XSync if you want to be sure that\n *\tall outstanding errors have been received and processed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_DeleteErrorHandler(\n    Tk_ErrorHandler handler)\t/* Token for handler to delete; was previous\n\t\t\t\t * return value from Tk_CreateErrorHandler. */\n{\n    TkErrorHandler *errorPtr = (TkErrorHandler *) handler;\n    TkDisplay *dispPtr = errorPtr->dispPtr;\n\n    errorPtr->lastRequest = NextRequest(dispPtr->display) - 1;\n\n    /*\n     * Ensure that no user callback for this handler is invoked any further.\n     */\n    errorPtr->errorProc = NULL;\n\n    /*\n     * Every once-in-a-while, cleanup handlers that are no longer active. We\n     * probably won't be able to free the handler that was just deleted (need\n     * to wait for any outstanding requests to be processed by server), but\n     * there may be previously-deleted handlers that are now ready for garbage\n     * collection. To reduce the cost of the cleanup, let a few dead handlers\n     * pile up, then clean them all at once. This adds a bit of overhead to\n     * errors that might occur while the dead handlers are hanging around, but\n     * reduces the overhead of scanning the list to clean up (particularly if\n     * there are many handlers that stay around forever).\n     */\n\n    if (dispPtr->deleteCount++ >= 9) {\n\tTkErrorHandler *prevPtr;\n\tTkErrorHandler *nextPtr;\n\tunsigned long lastSerial = LastKnownRequestProcessed(dispPtr->display);\n\n\t/*\n\t * Last chance to catch errors for this handler: if no event/error\n\t * processing took place to follow up the end of this error handler\n\t * we need a round trip with the X server now.\n\t */\n\n\tif (errorPtr->lastRequest > lastSerial) {\n\t    XSync(dispPtr->display, False);\n\t}\n\tdispPtr->deleteCount = 0;\n\terrorPtr = dispPtr->errorPtr;\n\tfor (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) {\n\t    nextPtr = errorPtr->nextPtr;\n\t    if ((errorPtr->lastRequest != (unsigned long) -1)\n\t\t    && (errorPtr->lastRequest <= lastSerial)) {\n\t\tif (prevPtr == NULL) {\n\t\t    dispPtr->errorPtr = nextPtr;\n\t\t} else {\n\t\t    prevPtr->nextPtr = nextPtr;\n\t\t}\n\t\tTcl_Free(errorPtr);\n\t\tcontinue;\n\t    }\n\t    prevPtr = errorPtr;\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ErrorProc --\n *\n *\tThis procedure is invoked by the X system when error events arrive.\n *\n * Results:\n *\tIf it returns, the return value is zero. However, it is possible that\n *\tone of the error handlers may just exit.\n *\n * Side effects:\n *\tThis procedure does two things. First, it uses the serial # in the\n *\terror event to eliminate handlers whose expiration serials are now in\n *\tthe past. Second, it invokes any handlers that want to deal with the\n *\terror.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nErrorProc(\n    Display *display,\t\t/* Display for which error occurred. */\n    XErrorEvent *errEventPtr)\n\t\t\t\t/* Information about error. */\n{\n    TkDisplay *dispPtr;\n    TkErrorHandler *errorPtr;\n\n    /*\n     * See if we know anything about the display. If not, then invoke the\n     * default error handler.\n     */\n\n    dispPtr = TkGetDisplay(display);\n    if (dispPtr == NULL) {\n\tgoto couldntHandle;\n    }\n\n    /*\n     * Otherwise invoke any relevant handlers for the error, in order.\n     */\n\n    for (errorPtr = dispPtr->errorPtr; errorPtr != NULL;\n\t    errorPtr = errorPtr->nextPtr) {\n\tif ((errorPtr->firstRequest > errEventPtr->serial)\n\t\t|| ((errorPtr->error != -1)\n\t\t    && (errorPtr->error != errEventPtr->error_code))\n\t\t|| ((errorPtr->request != -1)\n\t\t    && (errorPtr->request != errEventPtr->request_code))\n\t\t|| ((errorPtr->minorCode != -1)\n\t\t    && (errorPtr->minorCode != errEventPtr->minor_code))\n\t\t|| ((errorPtr->lastRequest != (unsigned long) -1)\n\t\t    && (errorPtr->lastRequest < errEventPtr->serial))) {\n\t    continue;\n\t}\n\tif (errorPtr->errorProc == NULL ||\n\t\terrorPtr->errorProc(errorPtr->clientData, errEventPtr) == 0) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * See if the error is a BadWindow error. If so, and it refers to a window\n     * that still exists in our window table, then ignore the error. Errors\n     * like this can occur if a window owned by us is deleted by someone\n     * externally, like a window manager. We'll ignore the errors at least\n     * long enough to clean up internally and remove the entry from the window\n     * table.\n     *\n     * NOTE: For embedding, we must also check whether the window was recently\n     * deleted. If so, it may be that Tk generated operations on windows that\n     * were deleted by the container. Now we are getting the errors\n     * (BadWindow) after Tk already deleted the window itself.\n     */\n\n    if (errEventPtr->error_code == BadWindow) {\n\tWindow w = (Window) errEventPtr->resourceid;\n\n\tif (Tk_IdToWindow(display, w) != NULL) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * We couldn't handle the error. Use the default handler.\n     */\n\n  couldntHandle:\n    return defaultHandler(display, errEventPtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkEvent.c",
    "content": "/*\n * tkEvent.c --\n *\n *\tThis file provides basic low-level facilities for managing X events in\n *\tTk.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Ajuba Solutions.\n * Copyright © 2004 George Peter Staplin\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#else\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * There's a potential problem if a handler is deleted while it's current\n * (i.e. its function is executing), since Tk_HandleEvent will need to read\n * the handler's \"nextPtr\" field when the function returns. To handle this\n * problem, structures of the type below indicate the next handler to be\n * processed for any (recursively nested) dispatches in progress. The\n * nextHandler fields get updated if the handlers pointed to are deleted.\n * Tk_HandleEvent also needs to know if the entire window gets deleted; the\n * winPtr field is set to zero if that particular window gets deleted.\n */\n\ntypedef struct InProgress {\n    XEvent *eventPtr;\t\t/* Event currently being handled. */\n    TkWindow *winPtr;\t\t/* Window for event. Gets set to None if\n\t\t\t\t * window is deleted while event is being\n\t\t\t\t * handled. */\n    TkEventHandler *nextHandler;/* Next handler in search. */\n    struct InProgress *nextPtr;\t/* Next higher nested search. */\n} InProgress;\n\n/*\n * For each call to Tk_CreateGenericHandler or Tk_CreateClientMessageHandler,\n * an instance of the following structure will be created. All of the active\n * handlers are linked into a list.\n */\n\ntypedef struct GenericHandler {\n    Tk_GenericProc *proc;\t/* Function to dispatch on all X events. */\n    void *clientData;\t/* Client data to pass to function. */\n    int deleteFlag;\t\t/* Flag to set when this handler is\n\t\t\t\t * deleted. */\n    struct GenericHandler *nextPtr;\n\t\t\t\t/* Next handler in list of all generic\n\t\t\t\t * handlers, or NULL for end of list. */\n} GenericHandler;\n\n/*\n * There's a potential problem if Tk_HandleEvent is entered recursively. A\n * handler cannot be deleted physically until we have returned from calling\n * it. Otherwise, we're looking at unallocated memory in advancing to its\n * `next' entry. We deal with the problem by using the `delete flag' and\n * deleting handlers only when it's known that there's no handler active.\n */\n\n/*\n * The following structure is used for queueing X-style events on the Tcl\n * event queue.\n */\n\ntypedef struct TkWindowEvent {\n    Tcl_Event header;\t\t/* Standard information for all events. */\n    XEvent event;\t\t/* The X event. */\n} TkWindowEvent;\n\n/*\n * Array of event masks corresponding to each X event:\n */\n\nstatic const unsigned long eventMasks[TK_LASTEVENT] = {\n    0,\n    0,\n    KeyPressMask,\t\t\t/* KeyPress */\n    KeyReleaseMask,\t\t\t/* KeyRelease */\n    ButtonPressMask,\t\t\t/* ButtonPress */\n    ButtonReleaseMask,\t\t\t/* ButtonRelease */\n    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask\n\t    |Button1MotionMask|Button2MotionMask|Button3MotionMask\n\t    |Button4MotionMask|Button5MotionMask,\n\t\t\t\t\t/* MotionNotify */\n    EnterWindowMask,\t\t\t/* EnterNotify */\n    LeaveWindowMask,\t\t\t/* LeaveNotify */\n    FocusChangeMask,\t\t\t/* FocusIn */\n    FocusChangeMask,\t\t\t/* FocusOut */\n    KeymapStateMask,\t\t\t/* KeymapNotify */\n    ExposureMask,\t\t\t/* Expose */\n    ExposureMask,\t\t\t/* GraphicsExpose */\n    ExposureMask,\t\t\t/* NoExpose */\n    VisibilityChangeMask,\t\t/* VisibilityNotify */\n    SubstructureNotifyMask,\t\t/* CreateNotify */\n    StructureNotifyMask,\t\t/* DestroyNotify */\n    StructureNotifyMask,\t\t/* UnmapNotify */\n    StructureNotifyMask,\t\t/* MapNotify */\n    SubstructureRedirectMask,\t\t/* MapRequest */\n    StructureNotifyMask,\t\t/* ReparentNotify */\n    StructureNotifyMask,\t\t/* ConfigureNotify */\n    SubstructureRedirectMask,\t\t/* ConfigureRequest */\n    StructureNotifyMask,\t\t/* GravityNotify */\n    ResizeRedirectMask,\t\t\t/* ResizeRequest */\n    StructureNotifyMask,\t\t/* CirculateNotify */\n    SubstructureRedirectMask,\t\t/* CirculateRequest */\n    PropertyChangeMask,\t\t\t/* PropertyNotify */\n    0,\t\t\t\t\t/* SelectionClear */\n    0,\t\t\t\t\t/* SelectionRequest */\n    0,\t\t\t\t\t/* SelectionNotify */\n    ColormapChangeMask,\t\t\t/* ColormapNotify */\n    0,\t\t\t\t\t/* ClientMessage */\n    0,\t\t\t\t\t/* Mapping Notify */\n    VirtualEventMask,\t\t\t/* VirtualEvents */\n    ActivateMask,\t\t\t/* ActivateNotify */\n    ActivateMask,\t\t\t/* DeactivateNotify */\n    MouseWheelMask,\t\t\t/* MouseWheelEvent */\n    TouchpadScrollMask\t\t\t/* TouchpadScroll */\n};\n\n/*\n * For each exit handler created with a call to TkCreateExitHandler or\n * TkCreateThreadExitHandler there is a structure of the following type:\n */\n\ntypedef struct ExitHandler {\n    Tcl_ExitProc *proc;\t\t/* Function to call when process exits. */\n    void *clientData;\t/* One word of information to pass to proc. */\n    struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this\n\t\t\t\t * application, or NULL for end of list. */\n} ExitHandler;\n\n/*\n * The structure below is used to store Data for the Event module that must be\n * kept thread-local. The \"dataKey\" is used to fetch the thread-specific\n * storage for the current thread.\n */\n\ntypedef struct {\n    int handlersActive;\t\t/* The following variable has a non-zero value\n\t\t\t\t * when a handler is active. */\n    InProgress *pendingPtr;\t/* Topmost search in progress, or NULL if\n\t\t\t\t * none. */\n\n    /*\n     * List of generic handler records.\n     */\n\n    GenericHandler *genericList;/* First handler in the list, or NULL. */\n    GenericHandler *lastGenericPtr;\n\t\t\t\t/* Last handler in list. */\n\n    /*\n     * List of client message handler records.\n     */\n\n    GenericHandler *cmList;\t/* First handler in the list, or NULL. */\n    GenericHandler *lastCmPtr;\t/* Last handler in list. */\n\n    /*\n     * If someone has called Tk_RestrictEvents, the information below keeps\n     * track of it.\n     */\n\n    Tk_RestrictProc *restrictProc;\n\t\t\t\t/* Function to call. NULL means no\n\t\t\t\t * restrictProc is currently in effect. */\n    void *restrictArg;\t/* Argument to pass to restrictProc. */\n    ExitHandler *firstExitPtr;\t/* First in list of all exit handlers for this\n\t\t\t\t * thread. */\n    int inExit;\t\t\t/* True when this thread is exiting. This is\n\t\t\t\t * used as a hack to decide to close the\n\t\t\t\t * standard channels. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * There are both per-process and per-thread exit handlers. The first list is\n * controlled by a mutex. The other is in thread local storage.\n */\n\nstatic ExitHandler *firstExitPtr = NULL;\n\t\t\t\t/* First in list of all exit handlers for\n\t\t\t\t * application. */\nTCL_DECLARE_MUTEX(exitMutex)\n\n/*\n * Prototypes for functions that are only referenced locally within this file.\n */\n\nstatic void\t\tCleanUpTkEvent(XEvent *eventPtr);\nstatic void\t\tDelayedMotionProc(void *clientData);\nstatic unsigned long    GetEventMaskFromXEvent(XEvent *eventPtr);\nstatic TkWindow *\tGetTkWindowFromXEvent(XEvent *eventPtr);\nstatic void\t\tInvokeClientMessageHandlers(ThreadSpecificData *tsdPtr,\n\t\t\t    Tk_Window tkwin, XEvent *eventPtr);\nstatic int\t\tInvokeFocusHandlers(TkWindow **winPtrPtr,\n\t\t\t    unsigned long mask, XEvent *eventPtr);\nstatic int\t\tInvokeGenericHandlers(ThreadSpecificData *tsdPtr,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tInvokeMouseHandlers(TkWindow *winPtr,\n\t\t\t    unsigned long mask, XEvent *eventPtr);\nstatic Window\t\tParentXId(Display *display, Window w);\nstatic int\t\tRefreshKeyboardMappingIfNeeded(XEvent *eventPtr);\nstatic int\t\tTkXErrorHandler(void *clientData,\n\t\t\t    XErrorEvent *errEventPtr);\nstatic int\t\tWindowEventProc(Tcl_Event *evPtr, int flags);\nstatic void\t\tCreateXIC(TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvokeFocusHandlers --\n *\n *\tCall focus-related code to look at FocusIn, FocusOut, Enter, and Leave\n *\tevents; depending on its return value, ignore the event.\n *\n * Results:\n *\t0 further processing can be done on the event.\n *\t1 we are done with the event passed.\n *\n * Side effects:\n *\tThe *winPtrPtr in the caller may be changed to the TkWindow for the\n *\twindow with focus.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInvokeFocusHandlers(\n    TkWindow **winPtrPtr,\n    unsigned long mask,\n    XEvent *eventPtr)\n{\n    if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))\n\t    && (TkFocusFilterEvent(*winPtrPtr, eventPtr) == 0)) {\n\treturn 1;\n    }\n\n    /*\n     * Only key-related events are directed according to the focus.\n     */\n\n    if (mask & (KeyPressMask|KeyReleaseMask)) {\n\t(*winPtrPtr)->dispPtr->lastEventTime = eventPtr->xkey.time;\n\t*winPtrPtr = TkFocusKeyEvent(*winPtrPtr, eventPtr);\n\tif (*winPtrPtr == NULL) {\n\t    return 1;\n\t}\n    }\n\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvokeMouseHandlers --\n *\n *\tCall a grab-related function to do special processing on pointer\n *\tevents.\n *\n * Results:\n *\t0 further processing can be done on the event.\n *\t1 we are done with the event passed.\n *\n * Side effects:\n *\tNew events may be queued from TkPointerEvent and grabs may be added\n *\tand/or removed. The eventPtr may be changed by TkPointerEvent in some\n *\tcases.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInvokeMouseHandlers(\n    TkWindow *winPtr,\n    unsigned long mask,\n    XEvent *eventPtr)\n{\n    if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask\n\t    |EnterWindowMask|LeaveWindowMask)) {\n\n\tif (mask & (ButtonPressMask|ButtonReleaseMask)) {\n\t    winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;\n\t} else if (mask & PointerMotionMask) {\n\t    winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;\n\t} else {\n\t    winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;\n\t}\n\n\tif (TkPointerEvent(eventPtr, winPtr) == 0) {\n\t    /*\n\t     * The event should be ignored to make grab work correctly (as the\n\t     * comment for TkPointerEvent states).\n\t     */\n\n\t    return 1;\n\t}\n    }\n\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateXIC --\n *\n *\tCreate the X input context for our winPtr.\n *\tXIM is only ever enabled on Unix.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCreateXIC(\n    TkWindow *winPtr)\n{\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    long im_event_mask = 0L;\n    const char *preedit_attname = NULL;\n    XVaNestedList preedit_attlist = NULL;\n\n    if (dispPtr->inputStyle & XIMPreeditPosition) {\n\tXPoint spot = {0, 0};\n\n\tpreedit_attname = XNPreeditAttributes;\n\tpreedit_attlist = XVaCreateNestedList(0,\n\t\tXNSpotLocation, &spot,\n\t\tXNFontSet, dispPtr->inputXfs,\n\t\t(char *)NULL);\n    }\n\n    winPtr->inputContext = XCreateIC(dispPtr->inputMethod,\n\t    XNInputStyle, dispPtr->inputStyle,\n\t    XNClientWindow, winPtr->window,\n\t    XNFocusWindow, winPtr->window,\n\t    preedit_attname, preedit_attlist,\n\t    (char *)NULL);\n\n    if (preedit_attlist) {\n\tXFree(preedit_attlist);\n    }\n\n\n    if (winPtr->inputContext == NULL) {\n\t/* XCreateIC failed. */\n\treturn;\n    }\n    winPtr->ximGeneration = dispPtr->ximGeneration;\n\n    /*\n     * Adjust the window's event mask if the IM requires it.\n     */\n    XGetICValues(winPtr->inputContext, XNFilterEvents, &im_event_mask, (char *)NULL);\n    if ((winPtr->atts.event_mask & im_event_mask) != im_event_mask) {\n\twinPtr->atts.event_mask |= im_event_mask;\n\tXSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTkWindowFromXEvent --\n *\n *\tAttempt to find which TkWindow is associated with an event. If it\n *\tfails we attempt to get the TkWindow from the parent for a property\n *\tnotification.\n *\n * Results:\n *\tThe TkWindow associated with the event or NULL.\n *\n * Side effects:\n *\tTkSelPropProc may influence selection on windows not known to Tk.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkWindow *\nGetTkWindowFromXEvent(\n    XEvent *eventPtr)\n{\n    TkWindow *winPtr;\n    Window parentXId, handlerWindow = eventPtr->xany.window;\n\n    if ((eventPtr->xany.type == StructureNotifyMask)\n\t    && (eventPtr->xmap.event != eventPtr->xmap.window)) {\n\thandlerWindow = eventPtr->xmap.event;\n    }\n\n    winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);\n\n    if (winPtr == NULL) {\n\t/*\n\t * There isn't a TkWindow structure for this window. However, if the\n\t * event is a PropertyNotify event then call the selection manager (it\n\t * deals beneath-the-table with certain properties). Also, if the\n\t * window's parent is a Tk window that has the TK_PROP_PROPCHANGE flag\n\t * set, then we must propagate the PropertyNotify event up to the\n\t * parent.\n\t */\n\n\tif (eventPtr->type != PropertyNotify) {\n\t    return NULL;\n\t}\n\tTkSelPropProc(eventPtr);\n\tparentXId = ParentXId(eventPtr->xany.display, handlerWindow);\n\tif (parentXId == None) {\n\t    return NULL;\n\t}\n\twinPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId);\n\tif (winPtr == NULL) {\n\t    return NULL;\n\t}\n\tif (!(winPtr->flags & TK_PROP_PROPCHANGE)) {\n\t    return NULL;\n\t}\n    }\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetEventMaskFromXEvent --\n *\n *\tThe event type is looked up in our eventMasks tables, and may be\n *\tchanged to a different mask depending on the state of the event and\n *\twindow members.\n *\n * Results:\n *\tThe mask for the event.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic unsigned long\nGetEventMaskFromXEvent(\n    XEvent *eventPtr)\n{\n    unsigned long mask;\n\n    if (eventPtr->xany.type <TK_LASTEVENT) {\n\tmask = eventMasks[eventPtr->xany.type];\n    } else {\n\tmask = 0;\n    }\n\n    /*\n     * Events selected by StructureNotify require special handling. They look\n     * the same as those selected by SubstructureNotify. The only difference\n     * is whether the \"event\" and \"window\" fields are the same. Compare the\n     * two fields and convert StructureNotify to SubstructureNotify if\n     * necessary.\n     */\n\n    if (mask == StructureNotifyMask) {\n\tif (eventPtr->xmap.event != eventPtr->xmap.window) {\n\t    mask = SubstructureNotifyMask;\n\t}\n    }\n    return mask;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RefreshKeyboardMappingIfNeeded --\n *\n *\tIf the event is a MappingNotify event, find its display and refresh\n *\tthe keyboard mapping information for the display.\n *\n * Results:\n *\t0 if the event was not a MappingNotify event\n *\t1 if the event was a MappingNotify event\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nRefreshKeyboardMappingIfNeeded(\n    XEvent *eventPtr)\n{\n    TkDisplay *dispPtr;\n\n    if (eventPtr->type == MappingNotify) {\n\tdispPtr = TkGetDisplay(eventPtr->xmapping.display);\n\tif (dispPtr != NULL) {\n\t    XRefreshKeyboardMapping(&eventPtr->xmapping);\n\t    dispPtr->bindInfoStale = 1;\n\t}\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetButtonMask --\n *\n *\tReturn the proper Button${n}Mask for the button. Don't care about\n *\tButton4 - Button7, because those are not actually buttons: Those\n *\tare used for the horizontal or vertical mouse wheels. Button4Mask\n *\tand higher is actually used for Button 8 and higher.\n *\n * Results:\n *\tA button mask.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const unsigned buttonMasks[] = {\n    0, Button1Mask, Button2Mask, Button3Mask, 0, 0, 0, 0, Button4Mask, \\\n\t    Button5Mask, Button6Mask, Button7Mask, Button8Mask, Button9Mask\n};\n\nunsigned\nTk_GetButtonMask(\n    unsigned button)\n{\n    return (button > Button9) ? 0 : buttonMasks[button];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvokeClientMessageHandlers --\n *\n *\tIterate the list of handlers and invoke the function pointer for each.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tHandlers may be deleted and events may be sent to handlers.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInvokeClientMessageHandlers(\n    ThreadSpecificData *tsdPtr,\n    Tk_Window tkwin,\n    XEvent *eventPtr)\n{\n    GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->cmList;\n\n    for (prevPtr = NULL; curPtr != NULL; ) {\n\tif (curPtr->deleteFlag) {\n\t    if (!tsdPtr->handlersActive) {\n\t\t/*\n\t\t * This handler needs to be deleted and there are no calls\n\t\t * pending through any handlers, so now is a safe time to\n\t\t * delete it.\n\t\t */\n\n\t\ttmpPtr = curPtr->nextPtr;\n\t\tif (prevPtr == NULL) {\n\t\t    tsdPtr->cmList = tmpPtr;\n\t\t} else {\n\t\t    prevPtr->nextPtr = tmpPtr;\n\t\t}\n\t\tif (tmpPtr == NULL) {\n\t\t    tsdPtr->lastCmPtr = prevPtr;\n\t\t}\n\t\tTcl_Free(curPtr);\n\t\tcurPtr = tmpPtr;\n\t\tcontinue;\n\t    }\n\t} else {\n\t    int done;\n\n\t    tsdPtr->handlersActive++;\n\t    done = (*(Tk_ClientMessageProc *)curPtr->proc)(tkwin, eventPtr);\n\t    tsdPtr->handlersActive--;\n\t    if (done) {\n\t\tbreak;\n\t    }\n\t}\n\tprevPtr = curPtr;\n\tcurPtr = curPtr->nextPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvokeGenericHandlers --\n *\n *\tIterate the list of handlers and invoke the function pointer for each.\n *\tIf the handler invoked returns a non-zero value then we are done.\n *\n * Results:\n *\t0 when the event wasn't handled by a handler. Non-zero when it was\n *\tprocessed and handled by a handler.\n *\n * Side effects:\n *\tHandlers may be deleted and events may be sent to handlers.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInvokeGenericHandlers(\n    ThreadSpecificData *tsdPtr,\n    XEvent *eventPtr)\n{\n    GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->genericList;\n\n    for (prevPtr = NULL; curPtr != NULL; ) {\n\tif (curPtr->deleteFlag) {\n\t    if (!tsdPtr->handlersActive) {\n\t\t/*\n\t\t * This handler needs to be deleted and there are no calls\n\t\t * pending through the handler, so now is a safe time to\n\t\t * delete it.\n\t\t */\n\n\t\ttmpPtr = curPtr->nextPtr;\n\t\tif (prevPtr == NULL) {\n\t\t    tsdPtr->genericList = tmpPtr;\n\t\t} else {\n\t\t    prevPtr->nextPtr = tmpPtr;\n\t\t}\n\t\tif (tmpPtr == NULL) {\n\t\t    tsdPtr->lastGenericPtr = prevPtr;\n\t\t}\n\t\tTcl_Free(curPtr);\n\t\tcurPtr = tmpPtr;\n\t\tcontinue;\n\t    }\n\t} else {\n\t    int done;\n\n\t    tsdPtr->handlersActive++;\n\t    done = curPtr->proc(curPtr->clientData, eventPtr);\n\t    tsdPtr->handlersActive--;\n\t    if (done) {\n\t\treturn done;\n\t    }\n\t}\n\tprevPtr = curPtr;\n\tcurPtr = curPtr->nextPtr;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreateEventHandler --\n *\n *\tArrange for a given function to be invoked whenever events from a\n *\tgiven class occur in a given window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrom now on, whenever an event of the type given by mask occurs for\n *\ttoken and is processed by Tk_HandleEvent, proc will be called. See the\n *\tmanual entry for details of the calling sequence and return value for\n *\tproc.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreateEventHandler(\n    Tk_Window token,\t\t/* Token for window in which to create\n\t\t\t\t * handler. */\n    unsigned long mask,\t\t/* Events for which proc should be called. */\n    Tk_EventProc *proc,\t\t/* Function to call for each selected event */\n    void *clientData)\t/* Arbitrary data to pass to proc. */\n{\n    TkEventHandler *handlerPtr;\n    TkWindow *winPtr = (TkWindow *)token;\n\n    /*\n     * Skim through the list of existing handlers to (a) compute the overall\n     * event mask for the window (so we can pass this new value to the X\n     * system) and (b) see if there's already a handler declared with the same\n     * callback and clientData (if so, just change the mask). If no existing\n     * handler matches, then create a new handler.\n     */\n\n    if (winPtr->handlerList == NULL) {\n\t/*\n\t * No event handlers defined at all, so must create.\n\t */\n\n\thandlerPtr = (TkEventHandler *)Tcl_Alloc(sizeof(TkEventHandler));\n\twinPtr->handlerList = handlerPtr;\n    } else {\n\tint found = 0;\n\n\tfor (handlerPtr = winPtr->handlerList; ;\n\t\thandlerPtr = handlerPtr->nextPtr) {\n\t    if ((handlerPtr->proc == proc)\n\t\t    && (handlerPtr->clientData == clientData)) {\n\t\thandlerPtr->mask = mask;\n\t\tfound = 1;\n\t    }\n\t    if (handlerPtr->nextPtr == NULL) {\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * If we found anything, we're done because we do not need to use\n\t * XSelectInput; Tk always selects on all events anyway in order to\n\t * support binding on classes, 'all' and other bind-tags.\n\t */\n\n\tif (found) {\n\t    return;\n\t}\n\n\t/*\n\t * No event handler matched, so create a new one.\n\t */\n\n\thandlerPtr->nextPtr = (TkEventHandler *)Tcl_Alloc(sizeof(TkEventHandler));\n\thandlerPtr = handlerPtr->nextPtr;\n    }\n\n    /*\n     * Initialize the new event handler.\n     */\n\n    handlerPtr->mask = mask;\n    handlerPtr->proc = proc;\n    handlerPtr->clientData = clientData;\n    handlerPtr->nextPtr = NULL;\n\n    /*\n     * No need to call XSelectInput: Tk always selects on all events for all\n     * windows (needed to support bindings on classes and \"all\").\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteEventHandler --\n *\n *\tDelete a previously-created handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there existed a handler as described by the parameters, the handler\n *\tis deleted so that proc will not be invoked again.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteEventHandler(\n    Tk_Window token,\t\t/* Same as corresponding arguments passed */\n    unsigned long mask,\t\t/* previously to Tk_CreateEventHandler. */\n    Tk_EventProc *proc,\n    void *clientData)\n{\n    TkEventHandler *handlerPtr;\n    InProgress *ipPtr;\n    TkEventHandler *prevPtr;\n    TkWindow *winPtr = (TkWindow *) token;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Find the event handler to be deleted, or return immediately if it\n     * doesn't exist.\n     */\n\n    for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;\n\t    prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {\n\tif (handlerPtr == NULL) {\n\t    return;\n\t}\n\tif ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)\n\t\t&& (handlerPtr->clientData == clientData)) {\n\t    break;\n\t}\n    }\n\n    /*\n     * If Tk_HandleEvent is about to process this handler, tell it to process\n     * the next one instead.\n     */\n\n    for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {\n\tif (ipPtr->nextHandler == handlerPtr) {\n\t    ipPtr->nextHandler = handlerPtr->nextPtr;\n\t}\n    }\n\n    /*\n     * Free resources associated with the handler.\n     */\n\n    if (prevPtr == NULL) {\n\twinPtr->handlerList = handlerPtr->nextPtr;\n    } else {\n\tprevPtr->nextPtr = handlerPtr->nextPtr;\n    }\n    Tcl_Free(handlerPtr);\n\n    /*\n     * No need to call XSelectInput: Tk always selects on all events for all\n     * windows (needed to support bindings on classes and \"all\").\n     */\n}\n\f\n/*----------------------------------------------------------------------\n *\n * Tk_CreateGenericHandler --\n *\n *\tRegister a function to be called on each X event, regardless of\n *\tdisplay or window. Generic handlers are useful for capturing events\n *\tthat aren't associated with windows, or events for windows not managed\n *\tby Tk.\n *\n * Results:\n *\tNone.\n *\n * Side Effects:\n *\tFrom now on, whenever an X event is given to Tk_HandleEvent, invoke\n *\tproc, giving it clientData and the event as arguments.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreateGenericHandler(\n    Tk_GenericProc *proc,\t/* Function to call on every event. */\n    void *clientData)\t/* One-word value to pass to proc. */\n{\n    GenericHandler *handlerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    handlerPtr = (GenericHandler *)Tcl_Alloc(sizeof(GenericHandler));\n\n    handlerPtr->proc\t\t= proc;\n    handlerPtr->clientData\t= clientData;\n    handlerPtr->deleteFlag\t= 0;\n    handlerPtr->nextPtr\t\t= NULL;\n    if (tsdPtr->genericList == NULL) {\n\ttsdPtr->genericList\t= handlerPtr;\n    } else {\n\ttsdPtr->lastGenericPtr->nextPtr = handlerPtr;\n    }\n    tsdPtr->lastGenericPtr\t= handlerPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteGenericHandler --\n *\n *\tDelete a previously-created generic handler.\n *\n * Results:\n *\tNone.\n *\n * Side Effects:\n *\tIf there existed a handler as described by the parameters, that\n *\thandler is logically deleted so that proc will not be invoked again.\n *\tThe physical deletion happens in the event loop in Tk_HandleEvent.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteGenericHandler(\n    Tk_GenericProc *proc,\n    void *clientData)\n{\n    GenericHandler * handler;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (handler=tsdPtr->genericList ; handler ; handler=handler->nextPtr) {\n\tif ((handler->proc == proc) && (handler->clientData == clientData)) {\n\t    handler->deleteFlag = 1;\n\t}\n    }\n}\n\f\n/*----------------------------------------------------------------------\n *\n * Tk_CreateClientMessageHandler --\n *\n *\tRegister a function to be called on each ClientMessage event.\n *\tClientMessage handlers are useful for Drag&Drop extensions.\n *\n * Results:\n *\tNone.\n *\n * Side Effects:\n *\tFrom now on, whenever a ClientMessage event is received that isn't a\n *\tWM_PROTOCOL event or SelectionEvent, invoke proc, giving it tkwin and\n *\tthe event as arguments.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreateClientMessageHandler(\n    Tk_ClientMessageProc *proc)\t/* Function to call on event. */\n{\n    GenericHandler *handlerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * We use a GenericHandler struct, because it's basically the same, except\n     * with an extra clientData field we'll never use.\n     */\n\n    handlerPtr = (GenericHandler *)Tcl_Alloc(sizeof(GenericHandler));\n\n    handlerPtr->proc = (Tk_GenericProc *) proc;\n    handlerPtr->clientData = NULL;\t/* never used */\n    handlerPtr->deleteFlag = 0;\n    handlerPtr->nextPtr = NULL;\n    if (tsdPtr->cmList == NULL) {\n\ttsdPtr->cmList = handlerPtr;\n    } else {\n\ttsdPtr->lastCmPtr->nextPtr = handlerPtr;\n    }\n    tsdPtr->lastCmPtr = handlerPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteClientMessageHandler --\n *\n *\tDelete a previously-created ClientMessage handler.\n *\n * Results:\n *\tNone.\n *\n * Side Effects:\n *\tIf there existed a handler as described by the parameters, that\n *\thandler is logically deleted so that proc will not be invoked again.\n *\tThe physical deletion happens in the event loop in\n *\tTkClientMessageEventProc.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteClientMessageHandler(\n    Tk_ClientMessageProc *proc)\n{\n    GenericHandler * handler;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (handler=tsdPtr->cmList ; handler!=NULL ; handler=handler->nextPtr) {\n\tif (handler->proc == (Tk_GenericProc *) proc) {\n\t    handler->deleteFlag = 1;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkXErrorHandler --\n *\n *\tTkXErrorHandler is an error handler, to be installed via\n *\tTk_CreateErrorHandler, that will set a flag if an X error occurred.\n *\n * Results:\n *\tAlways returns 0, indicating that the X error was handled.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkXErrorHandler(\n    void *clientData,\t/* Pointer to flag we set. */\n    TCL_UNUSED(XErrorEvent *))\t/* X error info. */\n{\n    int *error = (int *)clientData;\n\n    *error = 1;\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParentXId --\n *\n *\tReturns the parent of the given window, or \"None\" if the window\n *\tdoesn't exist.\n *\n * Results:\n *\tReturns an X window ID.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Window\nParentXId(\n    Display *display,\n    Window w)\n{\n    Tk_ErrorHandler handler;\n    int gotXError;\n    Status status;\n    Window parent;\n    Window root;\n    Window *childList;\n    unsigned int nChildren;\n\n    /*\n     * Handle errors ourselves.\n     */\n\n    gotXError = 0;\n    handler = Tk_CreateErrorHandler(display, -1, -1, -1,\n\t    TkXErrorHandler, &gotXError);\n\n    /*\n     * Get the parent window.\n     */\n\n    status = XQueryTree(display, w, &root, &parent, &childList, &nChildren);\n\n    /*\n     * Do some cleanup; gotta return \"None\" if we got an error.\n     */\n\n    Tk_DeleteErrorHandler(handler);\n    XSync(display, False);\n    if (status != 0 && childList != NULL) {\n\tXFree(childList);\n    }\n    if (status == 0) {\n\tparent = None;\n    }\n\n    return parent;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_HandleEvent --\n *\n *\tGiven an event, invoke all the handlers that have been registered for\n *\tthe event.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the handlers.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_HandleEvent(\n    XEvent *eventPtr)\t/* Event to dispatch. */\n{\n    TkEventHandler *handlerPtr;\n    TkWindow *winPtr;\n    unsigned long mask;\n    InProgress ip;\n    Tcl_Interp *interp = NULL;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n\n#if !defined(_WIN32) && !defined(MAC_OSX_TK)\n    if ((eventPtr->type == ButtonRelease) || (eventPtr->type == ButtonPress)) {\n\tif ((eventPtr->xbutton.button >= Button4) && (eventPtr->xbutton.button < Button8)) {\n\t    if (eventPtr->type == ButtonRelease) {\n\t\treturn;\n\t    } else { /* eventPtr->type == ButtonPress */\n\t\tint but = eventPtr->xbutton.button;\n\t\teventPtr->type = MouseWheelEvent;\n\t\teventPtr->xany.send_event = -1;\n\t\teventPtr->xkey.keycode = (but & 1) ? -120 : 120;\n\t\tif (but > Button5) {\n\t\t    eventPtr->xkey.state |= ShiftMask;\n\t\t}\n\t    }\n\t}\n    }\n#endif\n\n    /*\n     * If the generic handler processed this event we are done and can return.\n     */\n\n    if (InvokeGenericHandlers(tsdPtr, eventPtr)) {\n\tgoto releaseEventResources;\n    }\n\n    if (RefreshKeyboardMappingIfNeeded(eventPtr)) {\n\t/*\n\t * We are done with a MappingNotify event.\n\t */\n\n\tgoto releaseEventResources;\n    }\n\n    mask = GetEventMaskFromXEvent(eventPtr);\n    winPtr = GetTkWindowFromXEvent(eventPtr);\n\n    if (winPtr == NULL) {\n\tgoto releaseEventResources;\n    }\n\n    /*\n     * Once a window has started getting deleted, don't process any more\n     * events for it except for the DestroyNotify event. This check is needed\n     * because a DestroyNotify handler could re-invoke the event loop, causing\n     * other pending events to be handled for the window (the window doesn't\n     * get totally expunged from our tables until after the DestroyNotify\n     * event has been completely handled).\n     */\n\n    if ((winPtr->flags & TK_ALREADY_DEAD)\n\t    && (eventPtr->type != DestroyNotify)) {\n\tgoto releaseEventResources;\n    }\n\n    if (winPtr->mainPtr != NULL) {\n\tint result;\n\n\tinterp = winPtr->mainPtr->interp;\n\n\t/*\n\t * Protect interpreter for this window from possible deletion while we\n\t * are dealing with the event for this window. Thus, widget writers do\n\t * not have to worry about protecting the interpreter in their own\n\t * code.\n\t */\n\n\tTcl_Preserve(interp);\n\n\tresult = ((InvokeFocusHandlers(&winPtr, mask, eventPtr))\n\t\t|| (InvokeMouseHandlers(winPtr, mask, eventPtr)));\n\n\tif (result) {\n\t    goto releaseInterpreter;\n\t}\n    }\n\n    /*\n     * Create the input context for the window if it hasn't already been done\n     * (XFilterEvent needs this context). When the event is a FocusIn event,\n     * set the input context focus to the receiving window. This code is only\n     * ever active for X11.\n     */\n\n    /*\n     * If the XIC has been invalidated, it must be recreated.\n     */\n    if (winPtr->dispPtr->ximGeneration != winPtr->ximGeneration) {\n\twinPtr->flags &= ~TK_CHECKED_IC;\n\twinPtr->inputContext = NULL;\n    }\n\n    if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) {\n\tif (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) {\n\t    winPtr->flags |= TK_CHECKED_IC;\n\t    if (winPtr->dispPtr->inputMethod != NULL) {\n\t\tCreateXIC(winPtr);\n\t    }\n\t}\n\tif ((eventPtr->type == FocusIn) &&\n\t\t(winPtr->dispPtr->inputMethod != NULL) &&\n\t\t(winPtr->inputContext != NULL)) {\n\t    XSetICFocus(winPtr->inputContext);\n\t}\n    }\n\n    /*\n     * For events where it hasn't already been done, update the current time\n     * in the display.\n     */\n\n    if (eventPtr->type == PropertyNotify) {\n\twinPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;\n    }\n\n    /*\n     * There's a potential interaction here with Tk_DeleteEventHandler. Read\n     * the documentation for pendingPtr.\n     */\n\n    ip.eventPtr = eventPtr;\n    ip.winPtr = winPtr;\n    ip.nextHandler = NULL;\n    ip.nextPtr = tsdPtr->pendingPtr;\n    tsdPtr->pendingPtr = &ip;\n    if (mask == 0) {\n\tif ((eventPtr->type == SelectionClear)\n\t\t|| (eventPtr->type == SelectionRequest)\n\t\t|| (eventPtr->type == SelectionNotify)) {\n\t    TkSelEventProc((Tk_Window) winPtr, eventPtr);\n\t} else if (eventPtr->type == ClientMessage) {\n\t    if (eventPtr->xclient.message_type ==\n\t\t    Tk_InternAtom((Tk_Window) winPtr, \"WM_PROTOCOLS\")) {\n\t\tTkWmProtocolEventProc(winPtr, eventPtr);\n\t    } else {\n\t\tInvokeClientMessageHandlers(tsdPtr, (Tk_Window) winPtr,\n\t\t\teventPtr);\n\t    }\n\t}\n    } else {\n\tfor (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {\n\t    if (handlerPtr->mask & mask) {\n\t\tip.nextHandler = handlerPtr->nextPtr;\n\t\thandlerPtr->proc(handlerPtr->clientData, eventPtr);\n\t\thandlerPtr = ip.nextHandler;\n\t    } else {\n\t\thandlerPtr = handlerPtr->nextPtr;\n\t    }\n\t}\n\n\t/*\n\t * Pass the event to the \"bind\" command mechanism. But, don't do this\n\t * for SubstructureNotify events. The \"bind\" command doesn't support\n\t * them anyway, and it's easier to filter out these events here than\n\t * in the lower-level functions.\n\t */\n\n\t/*\n\t * ...well, except when we use the tkwm patches, in which case we DO\n\t * handle CreateNotify events, so we gotta pass 'em through.\n\t */\n\n\tif ((ip.winPtr != NULL)\n\t\t&& ((mask != SubstructureNotifyMask)\n\t\t|| (eventPtr->type == CreateNotify))) {\n\t    TkBindEventProc(winPtr, eventPtr);\n\t}\n    }\n    tsdPtr->pendingPtr = ip.nextPtr;\n\n    /*\n     * Release the interpreter for this window so that it can be potentially\n     * deleted if requested.\n     */\n\n  releaseInterpreter:\n    if (interp != NULL) {\n\tTcl_Release(interp);\n    }\n\n    /*\n     * Release the user_data from the event (if it is a virtual event and the\n     * field was non-NULL in the first place.) Note that this is done using a\n     * Tcl_Obj interface, and we set the field back to NULL afterwards out of\n     * paranoia. Also clean up any cached %A substitutions from key events.\n     */\n\n  releaseEventResources:\n    CleanUpTkEvent(eventPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkEventDeadWindow --\n *\n *\tThis function is invoked when it is determined that a window is dead.\n *\tIt cleans up event-related information about the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tVarious things get cleaned up and recycled.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkEventDeadWindow(\n    TkWindow *winPtr)\t\t/* Information about the window that is being\n\t\t\t\t * deleted. */\n{\n    TkEventHandler *handlerPtr;\n    InProgress *ipPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * While deleting all the handlers, be careful to check for Tk_HandleEvent\n     * being about to process one of the deleted handlers. If it is, tell it\n     * to quit (all of the handlers are being deleted).\n     */\n\n    while (winPtr->handlerList != NULL) {\n\thandlerPtr = winPtr->handlerList;\n\twinPtr->handlerList = handlerPtr->nextPtr;\n\tfor (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;\n\t\tipPtr = ipPtr->nextPtr) {\n\t    if (ipPtr->nextHandler == handlerPtr) {\n\t\tipPtr->nextHandler = NULL;\n\t    }\n\t    if (ipPtr->winPtr == winPtr) {\n\t\tipPtr->winPtr = NULL;\n\t    }\n\t}\n\tTcl_Free(handlerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCurrentTime --\n *\n *\tTry to deduce the current time. \"Current time\" means the time of the\n *\tevent that led to the current code being executed, which means the\n *\ttime in the most recently-nested invocation of Tk_HandleEvent.\n *\n * Results:\n *\tThe return value is the time from the current event, or CurrentTime if\n *\tthere is no current event or if the current event contains no time.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTime\nTkCurrentTime(\n    TkDisplay *dispPtr)\t\t/* Display for which the time is desired. */\n{\n    XEvent *eventPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->pendingPtr == NULL) {\n\treturn dispPtr->lastEventTime;\n    }\n    eventPtr = tsdPtr->pendingPtr->eventPtr;\n    switch (eventPtr->type) {\n    case ButtonPress:\n    case ButtonRelease:\n\treturn eventPtr->xbutton.time;\n    case KeyPress:\n    case KeyRelease:\n\treturn eventPtr->xkey.time;\n    case MotionNotify:\n\treturn eventPtr->xmotion.time;\n    case EnterNotify:\n    case LeaveNotify:\n\treturn eventPtr->xcrossing.time;\n    case PropertyNotify:\n\treturn eventPtr->xproperty.time;\n    }\n    return dispPtr->lastEventTime;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_RestrictEvents --\n *\n *\tThis function is used to globally restrict the set of events that will\n *\tbe dispatched. The restriction is done by filtering all incoming X\n *\tevents through a function that determines whether they are to be\n *\tprocessed immediately, deferred, or discarded.\n *\n * Results:\n *\tThe return value is the previous restriction function in effect, if\n *\tthere was one, or NULL if there wasn't.\n *\n * Side effects:\n *\tFrom now on, proc will be called to determine whether to process,\n *\tdefer or discard each incoming X event.\n *\n *----------------------------------------------------------------------\n */\n\nTk_RestrictProc *\nTk_RestrictEvents(\n    Tk_RestrictProc *proc,\t/* Function to call for each incoming event */\n    void *arg,\t\t/* Arbitrary argument to pass to proc. */\n    void **prevArgPtr)\t/* Place to store information about previous\n\t\t\t\t * argument. */\n{\n    Tk_RestrictProc *prev;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    prev = tsdPtr->restrictProc;\n    *prevArgPtr = tsdPtr->restrictArg;\n    tsdPtr->restrictProc = proc;\n    tsdPtr->restrictArg = arg;\n    return prev;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CollapseMotionEvents --\n *\n *\tThis function controls whether we collapse motion events in a\n *\tparticular display or not.\n *\n * Results:\n *\tThe return value is the previous collapse value in effect.\n *\n * Side effects:\n *\tFiltering of motion events may be changed after calling this.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_CollapseMotionEvents(\n    Display *display,\t\t/* Display handling these events. */\n    int collapse)\t\t/* Boolean value that specifies whether motion\n\t\t\t\t * events should be collapsed. */\n{\n    TkDisplay *dispPtr = (TkDisplay *) display;\n    int prev = (dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS);\n\n    if (collapse) {\n\tdispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS;\n    } else {\n\tdispPtr->flags &= ~TK_DISPLAY_COLLAPSE_MOTION_EVENTS;\n    }\n    return prev;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_QueueWindowEvent --\n *\n *\tGiven an X-style window event, this function adds it to the Tcl event\n *\tqueue at the given position. This function also performs mouse motion\n *\tevent collapsing if possible.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAdds stuff to the event queue, which will eventually be processed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_QueueWindowEvent(\n    XEvent *eventPtr,\t\t/* Event to add to queue. This function copies\n\t\t\t\t * it before adding it to the queue. */\n    Tcl_QueuePosition position)\t/* Where to put it on the queue:\n\t\t\t\t * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, or\n\t\t\t\t * TCL_QUEUE_MARK. */\n{\n    TkWindowEvent *wevPtr;\n    TkDisplay *dispPtr;\n\n    /*\n     * Find our display structure for the event's display.\n     */\n\n    for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {\n\tif (dispPtr == NULL) {\n\t    return;\n\t}\n\tif (dispPtr->display == eventPtr->xany.display) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Don't filter motion events if the user defaulting to true (1), which\n     * could be set to false (0) when the user wishes to receive all the\n     * motion data)\n     */\n\n    if (!(dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS)) {\n\twevPtr = (TkWindowEvent *)Tcl_Alloc(sizeof(TkWindowEvent));\n\twevPtr->header.proc = WindowEventProc;\n\twevPtr->event = *eventPtr;\n\tTcl_QueueEvent(&wevPtr->header, position);\n\treturn;\n    }\n\n    if ((dispPtr->delayedMotionPtr != NULL) && (position == TCL_QUEUE_TAIL)) {\n\tif ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window\n\t\t== dispPtr->delayedMotionPtr->event.xmotion.window)) {\n\t    /*\n\t     * The new event is a motion event in the same window as the saved\n\t     * motion event. Just replace the saved event with the new one.\n\t     */\n\n\t    dispPtr->delayedMotionPtr->event = *eventPtr;\n\t    return;\n\t} else if ((eventPtr->type != GraphicsExpose)\n\t\t&& (eventPtr->type != NoExpose)\n\t\t&& (eventPtr->type != Expose)) {\n\t    /*\n\t     * The new event may conflict with the saved motion event. Queue\n\t     * the saved motion event now so that it will be processed before\n\t     * the new event.\n\t     */\n\n\t    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, position);\n\t    dispPtr->delayedMotionPtr = NULL;\n\t    Tcl_CancelIdleCall(DelayedMotionProc, dispPtr);\n\t}\n    }\n\n    wevPtr = (TkWindowEvent *)Tcl_Alloc(sizeof(TkWindowEvent));\n    wevPtr->header.proc = WindowEventProc;\n    wevPtr->event = *eventPtr;\n    if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {\n\t/*\n\t * The new event is a motion event so don't queue it immediately; save\n\t * it around in case another motion event arrives that it can be\n\t * collapsed with.\n\t */\n\n\tif (dispPtr->delayedMotionPtr != NULL) {\n\t    Tcl_Panic(\"Tk_QueueWindowEvent found unexpected delayed motion event\");\n\t}\n\tdispPtr->delayedMotionPtr = wevPtr;\n\tTcl_DoWhenIdle(DelayedMotionProc, dispPtr);\n    } else {\n\tTcl_QueueEvent(&wevPtr->header, position);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkQueueEventForAllChildren --\n *\n *\tGiven an XEvent, recursively queue the event for this window and all\n *\tnon-toplevel children of the given window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEvents queued.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkQueueEventForAllChildren(\n    TkWindow *winPtr,\t    /* Window to which event is sent. */\n    XEvent *eventPtr)\t    /* The event to be sent. */\n{\n    TkWindow *childPtr;\n\n    if (!Tk_IsMapped(winPtr)) {\n\treturn;\n    }\n\n    eventPtr->xany.window = winPtr->window;\n    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);\n\n    childPtr = winPtr->childList;\n    while (childPtr != NULL) {\n\tif (!Tk_TopWinHierarchy(childPtr)) {\n\t    TkQueueEventForAllChildren(childPtr, eventPtr);\n\t}\n\tchildPtr = childPtr->nextPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGenerateActivateEvents --\n *\n *\tThis function is called by the Mac and Windows window manager routines\n *\twhen a toplevel window is activated or deactivated.\n *\tActivate/Deactivate events will be sent to every subwindow of the\n *\ttoplevel followed by a FocusIn/FocusOut message.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates X events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGenerateActivateEvents(\n    TkWindow *winPtr,\t\t/* Toplevel to activate. */\n    int active)\t\t\t/* Non-zero if the window is being activated,\n\t\t\t\t * else 0.*/\n{\n    XEvent event;\n\n    /*\n     * Generate Activate and Deactivate events. This event is sent to every\n     * subwindow in a toplevel window.\n     */\n\n    event.xany.serial = NextRequest(winPtr->display);\n    event.xany.send_event = False;\n    event.xany.display = winPtr->display;\n    event.xany.window = winPtr->window;\n\n    event.xany.type = active ? ActivateNotify : DeactivateNotify;\n    TkQueueEventForAllChildren(winPtr, &event);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * WindowEventProc --\n *\n *\tThis function is called by Tcl_DoOneEvent when a window event reaches\n *\tthe front of the event queue. This function is responsible for\n *\tactually handling the event.\n *\n * Results:\n *\tReturns 1 if the event was handled, meaning it should be removed from\n *\tthe queue. Returns 0 if the event was not handled, meaning it should\n *\tstay on the queue. The event isn't handled if the TCL_WINDOW_EVENTS\n *\tbit isn't set in flags, if a restrict proc prevents the event from\n *\tbeing handled.\n *\n * Side effects:\n *\tWhatever the event handlers for the event do.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWindowEventProc(\n    Tcl_Event *evPtr,\t\t/* Event to service. */\n    int flags)\t\t\t/* Flags that indicate what events to handle,\n\t\t\t\t * such as TCL_WINDOW_EVENTS. */\n{\n    TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;\n    Tk_RestrictAction result;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn 0;\n    }\n    if (tsdPtr->restrictProc != NULL) {\n\tresult = tsdPtr->restrictProc(tsdPtr->restrictArg, &wevPtr->event);\n\tif (result != TK_PROCESS_EVENT) {\n\t    if (result == TK_DEFER_EVENT) {\n\t\treturn 0;\n\t    } else {\n\t\t/*\n\t\t * TK_DELETE_EVENT: return and say we processed the event,\n\t\t * even though we didn't do anything at all.\n\t\t */\n\n\t\tCleanUpTkEvent(&wevPtr->event);\n\t\treturn 1;\n\t    }\n\t}\n    }\n    Tk_HandleEvent(&wevPtr->event);\n    CleanUpTkEvent(&wevPtr->event);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CleanUpTkEvent --\n *\n *\tThis function is called to remove and deallocate any information in\n *\tthe event which is not directly in the event structure itself. It may\n *\tbe called multiple times per event, so it takes care to set the\n *\tcleared pointer fields to NULL afterwards.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMakes the event no longer have any external resources.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCleanUpTkEvent(\n    XEvent *eventPtr)\n{\n    switch (eventPtr->type) {\n    case KeyPress:\n    case KeyRelease: {\n\n#if !defined(_WIN32) && !defined(MAC_OSX_TK)\n\tTkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;\n\tif (kePtr->charValuePtr != NULL) {\n\t    Tcl_Free(kePtr->charValuePtr);\n\t    kePtr->charValuePtr = NULL;\n\t    kePtr->charValueLen = 0;\n\t}\n#endif\n\tbreak;\n    }\n\n    case VirtualEvent: {\n\tXVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;\n\n\tif (vePtr->user_data != NULL) {\n\t    Tcl_DecrRefCount(vePtr->user_data);\n\t    vePtr->user_data = NULL;\n\t}\n\tbreak;\n    }\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DelayedMotionProc --\n *\n *\tThis function is invoked as an idle handler when a mouse motion event\n *\thas been delayed. It queues the delayed event so that it will finally\n *\tbe serviced.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe delayed mouse motion event gets added to the Tcl event queue for\n *\tservicing.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDelayedMotionProc(\n    void *clientData)\t/* Pointer to display containing a delayed\n\t\t\t\t * motion event to be serviced. */\n{\n    TkDisplay *dispPtr = (TkDisplay *)clientData;\n\n    if (dispPtr->delayedMotionPtr == NULL) {\n\tTcl_Panic(\"DelayedMotionProc found no delayed mouse motion event\");\n    }\n    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL);\n    dispPtr->delayedMotionPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateExitHandler --\n *\n *\tSame as Tcl_CreateExitHandler, but private to Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects.\n *\tSets a handler with Tcl_CreateExitHandler if this is the first call.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkCreateExitHandler(\n    Tcl_ExitProc *proc,\t\t/* Function to invoke. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr;\n\n    exitPtr = (ExitHandler *)Tcl_Alloc(sizeof(ExitHandler));\n    exitPtr->proc = proc;\n    exitPtr->clientData = clientData;\n    Tcl_MutexLock(&exitMutex);\n\n    /*\n     * The call to TclInExit() is disabled here. That's a private Tcl routine,\n     * and calling it is causing some trouble with portability of building Tk.\n     * We should avoid private Tcl routines generally.\n     *\n     * In this case, the TclInExit() call is being used only to prevent a\n     * Tcl_CreateExitHandler() call when Tcl finalization is in progress.\n     * That's a situation that shouldn't happen anyway. Recent changes within\n     * Tcl_Finalize now cause a Tcl_Panic() to happen if exit handlers get\n     * added after exit handling is complete. By disabling the guard here,\n     * that panic will serve to help us find the buggy conditions and correct\n     * them.\n     *\n     * We can restore this guard if we find we must (hopefully getting public\n     * access to TclInExit() if we discover extensions really do need this),\n     * but during alpha development, this is a good time to dig in and find\n     * the root causes of finalization bugs.\n     */\n\n    if (firstExitPtr == NULL/* && !TclInExit()*/) {\n\tTcl_CreateExitHandler(TkFinalize, NULL);\n    }\n    exitPtr->nextPtr = firstExitPtr;\n    firstExitPtr = exitPtr;\n    Tcl_MutexUnlock(&exitMutex);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDeleteExitHandler --\n *\n *\tSame as Tcl_DeleteExitHandler, but private to Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects.\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDeleteExitHandler(\n    Tcl_ExitProc *proc,\t\t/* Function that was previously registered. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr, *prevPtr;\n\n    Tcl_MutexLock(&exitMutex);\n    for (prevPtr = NULL, exitPtr = firstExitPtr; exitPtr != NULL;\n\t    prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {\n\tif ((exitPtr->proc == proc)\n\t\t&& (exitPtr->clientData == clientData)) {\n\t    if (prevPtr == NULL) {\n\t\tfirstExitPtr = exitPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = exitPtr->nextPtr;\n\t    }\n\t    Tcl_Free(exitPtr);\n\t    break;\n\t}\n    }\n    Tcl_MutexUnlock(&exitMutex);\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateThreadExitHandler --\n *\n *\tSame as Tcl_CreateThreadExitHandler, but private to Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProc will be invoked with clientData as argument when the application\n *\texits.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkCreateThreadExitHandler(\n    Tcl_ExitProc *proc,\t\t/* Function to invoke. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    exitPtr = (ExitHandler *)Tcl_Alloc(sizeof(ExitHandler));\n    exitPtr->proc = proc;\n    exitPtr->clientData = clientData;\n\n    /*\n     * See comments in TkCreateExitHandler().\n     */\n\n    if (tsdPtr->firstExitPtr == NULL/* && !TclInExit()*/) {\n\tTcl_CreateThreadExitHandler(TkFinalizeThread, NULL);\n    }\n    exitPtr->nextPtr = tsdPtr->firstExitPtr;\n    tsdPtr->firstExitPtr = exitPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDeleteThreadExitHandler --\n *\n *\tSame as Tcl_DeleteThreadExitHandler, but private to Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there is an exit handler corresponding to proc and clientData then\n *\tit is cancelled; if no such handler exists then nothing happens.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDeleteThreadExitHandler(\n    Tcl_ExitProc *proc,\t\t/* Function that was previously registered. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr, *prevPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;\n\t    prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {\n\tif ((exitPtr->proc == proc)\n\t\t&& (exitPtr->clientData == clientData)) {\n\t    if (prevPtr == NULL) {\n\t\ttsdPtr->firstExitPtr = exitPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = exitPtr->nextPtr;\n\t    }\n\t    Tcl_Free(exitPtr);\n\t    return;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFinalize --\n *\n *\tRuns our private exit handlers and removes itself from Tcl. This is\n *\tbeneficial should we want to protect from dangling pointers should the\n *\tTk shared library be unloaded prior to Tcl which can happen on windows\n *\tshould the process be forcefully exiting from an exception handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects.\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFinalize(\n    TCL_UNUSED(void *))\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr;\n\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n    if (!tclStubsPtr) {\n\treturn;\n    }\n#endif\n\n    Tcl_DeleteExitHandler(TkFinalize, NULL);\n\n    Tcl_MutexLock(&exitMutex);\n    for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {\n\t/*\n\t * Be careful to remove the handler from the list before invoking its\n\t * callback. This protects us against double-freeing if the callback\n\t * should call TkDeleteExitHandler on itself.\n\t */\n\n\tfirstExitPtr = exitPtr->nextPtr;\n\tTcl_MutexUnlock(&exitMutex);\n\texitPtr->proc(exitPtr->clientData);\n\tTcl_Free(exitPtr);\n\tTcl_MutexLock(&exitMutex);\n    }\n    firstExitPtr = NULL;\n    Tcl_MutexUnlock(&exitMutex);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFinalizeThread --\n *\n *\tRuns our private thread exit handlers and removes itself from Tcl.\n *\tThis is beneficial should we want to protect from dangling pointers\n *\tshould the Tk shared library be unloaded prior to Tcl which can happen\n *\ton Windows should the process be forcefully exiting from an exception\n *\thandler.\n *\n * Results:\n *\tNone.\n *\n * Side effects.\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFinalizeThread(\n    TCL_UNUSED(void *))\t/* Arbitrary value to pass to proc. */\n{\n    ExitHandler *exitPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    Tcl_DeleteThreadExitHandler(TkFinalizeThread, NULL);\n\n    if (tsdPtr != NULL) {\n\ttsdPtr->inExit = 1;\n\n\tfor (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;\n\t\texitPtr = tsdPtr->firstExitPtr) {\n\t    /*\n\t     * Be careful to remove the handler from the list before invoking\n\t     * its callback. This protects us against double-freeing if the\n\t     * callback should call TkDeleteThreadExitHandler on itself.\n\t     */\n\n\t    tsdPtr->firstExitPtr = exitPtr->nextPtr;\n\t    exitPtr->proc(exitPtr->clientData);\n\t    Tcl_Free(exitPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MainLoop --\n *\n *\tCall Tcl_DoOneEvent over and over again in an infinite loop as long as\n *\tthere exist any main windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArbitrary; depends on handlers for events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MainLoop(void)\n{\n    while (Tk_GetNumMainWindows() > 0) {\n\tTcl_DoOneEvent(0);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkFileFilter.c",
    "content": "/*\n * tkFileFilter.c --\n *\n *\tProcess the -filetypes option for the file dialogs on Windows and the\n *\tMac.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkFileFilter.h\"\n\nstatic int\t\tAddClause(Tcl_Interp *interp, FileFilter *filterPtr,\n\t\t\t    Tcl_Obj *patternsObj, Tcl_Obj *ostypesObj,\n\t\t\t    bool isWindows);\nstatic FileFilter *\tGetFilter(FileFilterList *flistPtr, const char *name);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkInitFileFilters --\n *\n *\tInitializes a FileFilterList data structure. A FileFilterList must be\n *\tinitialized EXACTLY ONCE before any calls to TkGetFileFilters() is\n *\tmade. The usual flow of control is:\n *\t\tTkInitFileFilters(&flist);\n *\t\t    TkGetFileFilters(&flist, ...);\n *\t\t    TkGetFileFilters(&flist, ...);\n *\t\t    ...\n *\t\tTkFreeFileFilters(&flist);\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields in flistPtr are initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkInitFileFilters(\n    FileFilterList *flistPtr)\t/* The structure to be initialized. */\n{\n    flistPtr->filters = NULL;\n    flistPtr->filtersTail = NULL;\n    flistPtr->numFilters = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetFileFilters --\n *\n *\tThis function is called by the Mac and Windows implementation of\n *\ttk_getOpenFile and tk_getSaveFile to translate the string value of the\n *\t-filetypes option into an easy-to-parse C structure (flistPtr). The\n *\tcaller of this function will then use flistPtr to perform filetype\n *\tmatching in a platform specific way.\n *\n *\tflistPtr must be initialized (See comments in TkInitFileFilters).\n *\n * Results:\n *\tA standard TCL return value.\n *\n * Side effects:\n *\tThe fields in flistPtr are changed according to 'types'.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetFileFilters(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    FileFilterList *flistPtr,\t/* Stores the list of file filters. */\n    Tcl_Obj *types,\t\t/* Value of the -filetypes option. */\n    bool isWindows)\t\t/* True if we are running on Windows. */\n{\n    Tcl_Size i, listObjc;\n    Tcl_Obj ** listObjv = NULL;\n\n    if (types == NULL) {\n\treturn TCL_OK;\n    }\n\n    if (Tcl_ListObjGetElements(interp, types, &listObjc,\n\t    &listObjv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (listObjc == 0) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Free the filter information that have been allocated the previous time;\n     * the -filefilters option may have been used more than once in the\n     * command line.\n     */\n\n    TkFreeFileFilters(flistPtr);\n\n    for (i = 0; i<listObjc; i++) {\n\t/*\n\t * Each file type should have two or three elements: the first one is\n\t * the name of the type and the second is the filter of the type. The\n\t * third is the Mac OSType ID, but we don't care about them here.\n\t */\n\n\tTcl_Size count;\n\tFileFilter *filterPtr;\n\tTcl_Obj **typeInfo;\n\n\tif (Tcl_ListObjGetElements(interp, listObjv[i], &count,\n\t\t&typeInfo) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (count != 2 && count != 3) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad file type \\\"%s\\\", should be \"\n\t\t    \"\\\"typeName {extension ?extensions ...?} \"\n\t\t    \"?{macType ?macTypes ...?}?\\\"\",\n\t\t    Tcl_GetString(listObjv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"FILE_TYPE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfilterPtr = GetFilter(flistPtr, Tcl_GetString(typeInfo[0]));\n\n\tif (AddClause(interp, filterPtr, typeInfo[1],\n\t\t(count==2 ? NULL : typeInfo[2]), isWindows) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFreeFileFilters --\n *\n *\tFrees the malloc'ed file filter information.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields allocated by TkGetFileFilters() are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFreeFileFilters(\n    FileFilterList *flistPtr)\t/* List of file filters to free */\n{\n    FileFilter *filterPtr;\n    FileFilterClause *clausePtr;\n    GlobPattern *globPtr;\n    MacFileType *mfPtr;\n    void *toFree;\t/* A pointer that we are about to free. */\n\n    for (filterPtr = flistPtr->filters; filterPtr != NULL; ) {\n\tfor (clausePtr = filterPtr->clauses; clausePtr != NULL; ) {\n\t    /*\n\t     * Squelch each of the glob patterns.\n\t     */\n\n\t    for (globPtr = clausePtr->patterns; globPtr != NULL; ) {\n\t\tTcl_Free(globPtr->pattern);\n\t\ttoFree = globPtr;\n\t\tglobPtr = globPtr->next;\n\t\tTcl_Free(toFree);\n\t    }\n\n\t    /*\n\t     * Squelch each of the Mac file type codes.\n\t     */\n\n\t    for (mfPtr = clausePtr->macTypes; mfPtr != NULL; ) {\n\t\ttoFree = mfPtr;\n\t\tmfPtr = mfPtr->next;\n\t\tTcl_Free(toFree);\n\t    }\n\t    toFree = clausePtr;\n\t    clausePtr = clausePtr->next;\n\t    Tcl_Free(toFree);\n\t}\n\n\t/*\n\t * Squelch the name of the filter and the overall structure.\n\t */\n\n\tTcl_Free(filterPtr->name);\n\ttoFree = filterPtr;\n\tfilterPtr = filterPtr->next;\n\tTcl_Free(toFree);\n    }\n    flistPtr->filters = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AddClause --\n *\n *\tAdd one FileFilterClause to filterPtr.\n *\n * Results:\n *\tA standard TCL result.\n *\n * Side effects:\n *\tThe list of filter clauses are updated in filterPtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nAddClause(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    FileFilter *filterPtr,\t/* Stores the new filter clause */\n    Tcl_Obj *patternsObj,\t/* A Tcl list of glob patterns. */\n    Tcl_Obj *ostypesObj,\t/* A Tcl list of Mac OSType strings. */\n    bool isWindows)\t\t/* True if we are running on Windows; False if\n\t\t\t\t * we are running on the Mac; Glob patterns\n\t\t\t\t * need to be processed differently on these\n\t\t\t\t * two platforms */\n{\n    Tcl_Obj **globList = NULL, **ostypeList = NULL;\n    Tcl_Size globCount, ostypeCount, i;\n    int code = TCL_OK;\n    FileFilterClause *clausePtr;\n    Tcl_Encoding macRoman = NULL;\n\n    if (Tcl_ListObjGetElements(interp, patternsObj,\n\t    &globCount, &globList) != TCL_OK) {\n\tcode = TCL_ERROR;\n\tgoto done;\n    }\n    if (ostypesObj != NULL) {\n\tif (Tcl_ListObjGetElements(interp, ostypesObj,\n\t\t&ostypeCount, &ostypeList) != TCL_OK) {\n\t    code = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * We probably need this encoding now...\n\t */\n\n\tmacRoman = Tcl_GetEncoding(NULL, \"macRoman\");\n\n\t/*\n\t * Might be cleaner to use 'Tcl_GetOSTypeFromObj' but that is actually\n\t * static to the MacOS X/Darwin version of Tcl, and would therefore\n\t * require further code refactoring.\n\t */\n\n\tfor (i=0; i<ostypeCount; i++) {\n\t    Tcl_Size len;\n\t    const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);\n\n\t    /*\n\t     * If len is < 4, it is definitely an error. If equal or longer,\n\t     * we need to use the macRoman encoding to determine the correct\n\t     * length (assuming there may be non-ascii characters, e.g.,\n\t     * embedded nulls or accented characters in the string, the\n\t     * macRoman length will be different).\n\t     *\n\t     * If we couldn't load the encoding, then we can't actually check\n\t     * the correct length. But here we assume we're probably operating\n\t     * on unix/windows with a minimal set of encodings and so don't\n\t     * care about MacOS types. So we won't signal an error.\n\t     */\n\n\t    if (len >= 4 && macRoman != NULL) {\n\t\tTcl_DString osTypeDS;\n\n\t\t/*\n\t\t * Convert utf to macRoman, since MacOS types are defined to\n\t\t * be 4 macRoman characters long\n\t\t */\n\n\t\t(void)Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS);\n\t\tlen = Tcl_DStringLength(&osTypeDS);\n\t\tTcl_DStringFree(&osTypeDS);\n\t    }\n\t    if (len != 4) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"bad Macintosh file type \\\"%s\\\"\",\n\t\t\tTcl_GetString(ostypeList[i])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"MAC_TYPE\", (char *)NULL);\n\t\tcode = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t}\n    }\n\n    /*\n     * Add the clause into the list of clauses\n     */\n\n    clausePtr = (FileFilterClause *)Tcl_Alloc(sizeof(FileFilterClause));\n    clausePtr->patterns = NULL;\n    clausePtr->patternsTail = NULL;\n    clausePtr->macTypes = NULL;\n    clausePtr->macTypesTail = NULL;\n\n    if (filterPtr->clauses == NULL) {\n\tfilterPtr->clauses = filterPtr->clausesTail = clausePtr;\n    } else {\n\tfilterPtr->clausesTail->next = clausePtr;\n\tfilterPtr->clausesTail = clausePtr;\n    }\n    clausePtr->next = NULL;\n\n    if (globCount > 0 && globList != NULL) {\n\tfor (i=0; i<globCount; i++) {\n\t    GlobPattern *globPtr = (GlobPattern *)Tcl_Alloc(sizeof(GlobPattern));\n\t    Tcl_Size len;\n\t    const char *str = Tcl_GetStringFromObj(globList[i], &len);\n\n\t    len = (len + 1) * sizeof(char);\n\t    if (str[0] && str[0] != '*') {\n\t\t/*\n\t\t * Prepend a \"*\" to patterns that do not have a leading \"*\"\n\t\t */\n\n\t\tglobPtr->pattern = (char *)Tcl_Alloc(len + 1);\n\t\tglobPtr->pattern[0] = '*';\n\t\tstrcpy(globPtr->pattern+1, str);\n\t    } else if (isWindows) {\n\t\tif (strcmp(str, \"*\") == 0) {\n\t\t    globPtr->pattern = (char *)Tcl_Alloc(4);\n\t\t    strcpy(globPtr->pattern, \"*.*\");\n\t\t} else if (strcmp(str, \"\") == 0) {\n\t\t    /*\n\t\t     * An empty string means \"match all files with no\n\t\t     * extensions\"\n\t\t     * TODO: \"*.\" actually matches with all files on Win95\n\t\t     */\n\n\t\t    globPtr->pattern = (char *)Tcl_Alloc(3);\n\t\t    strcpy(globPtr->pattern, \"*.\");\n\t\t} else {\n\t\t    globPtr->pattern = (char *)Tcl_Alloc(len);\n\t\t    strcpy(globPtr->pattern, str);\n\t\t}\n\t    } else {\n\t\tglobPtr->pattern = (char *)Tcl_Alloc(len);\n\t\tstrcpy(globPtr->pattern, str);\n\t    }\n\n\t    /*\n\t     * Add the glob pattern into the list of patterns.\n\t     */\n\n\t    if (clausePtr->patterns == NULL) {\n\t\tclausePtr->patterns = clausePtr->patternsTail = globPtr;\n\t    } else {\n\t\tclausePtr->patternsTail->next = globPtr;\n\t\tclausePtr->patternsTail = globPtr;\n\t    }\n\t    globPtr->next = NULL;\n\t}\n    }\n    if (ostypeList != NULL && ostypeCount > 0) {\n\tif (macRoman == NULL) {\n\t    macRoman = Tcl_GetEncoding(NULL, \"macRoman\");\n\t}\n\tfor (i=0; i<ostypeCount; i++) {\n\t    Tcl_DString osTypeDS;\n\t    Tcl_Size len;\n\t    MacFileType *mfPtr = (MacFileType *)Tcl_Alloc(sizeof(MacFileType));\n\t    const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);\n\t    char *string;\n\n\t    /*\n\t     * Convert utf to macRoman, since MacOS types are defined to be 4\n\t     * macRoman characters long\n\t     */\n\n\t    string = Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS);\n\t    mfPtr->type = (OSType) string[0] << 24 | (OSType) string[1] << 16 |\n\t\t    (OSType) string[2] <<  8 | (OSType) string[3];\n\t    Tcl_DStringFree(&osTypeDS);\n\n\t    /*\n\t     * Add the Mac type pattern into the list of Mac types\n\t     */\n\n\t    if (clausePtr->macTypes == NULL) {\n\t\tclausePtr->macTypes = clausePtr->macTypesTail = mfPtr;\n\t    } else {\n\t\tclausePtr->macTypesTail->next = mfPtr;\n\t\tclausePtr->macTypesTail = mfPtr;\n\t    }\n\t    mfPtr->next = NULL;\n\t}\n    }\n\n  done:\n    if (macRoman != NULL) {\n\tTcl_FreeEncoding(macRoman);\n    }\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetFilter --\n *\n *\tAdd one FileFilter to flistPtr.\n *\n * Results:\n *\tA standard TCL result.\n *\n * Side effects:\n *\tThe list of filters are updated in flistPtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic FileFilter *\nGetFilter(\n    FileFilterList *flistPtr,\t/* The FileFilterList that contains the newly\n\t\t\t\t * created filter */\n    const char *name)\t\t/* Name of the filter. It is usually displayed\n\t\t\t\t * in the \"File Types\" listbox in the file\n\t\t\t\t * dialogs. */\n{\n    FileFilter *filterPtr = flistPtr->filters;\n    size_t len;\n\n    for (; filterPtr; filterPtr=filterPtr->next) {\n\tif (strcmp(filterPtr->name, name) == 0) {\n\t    return filterPtr;\n\t}\n    }\n\n    filterPtr = (FileFilter *)Tcl_Alloc(sizeof(FileFilter));\n    filterPtr->clauses = NULL;\n    filterPtr->clausesTail = NULL;\n    len = strlen(name) + 1;\n    filterPtr->name = (char *)Tcl_Alloc(len);\n    memcpy(filterPtr->name, name, len);\n\n    if (flistPtr->filters == NULL) {\n\tflistPtr->filters = flistPtr->filtersTail = filterPtr;\n    } else {\n\tflistPtr->filtersTail->next = filterPtr;\n\tflistPtr->filtersTail = filterPtr;\n    }\n    filterPtr->next = NULL;\n\n    ++flistPtr->numFilters;\n    return filterPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkFileFilter.h",
    "content": "/*\n * tkFileFilter.h --\n *\n *\tDeclarations for the file filter processing routines needed by the\n *\tfile selection dialogs.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TK_FILE_FILTER\n#define _TK_FILE_FILTER\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define OSType long\n\ntypedef struct GlobPattern {\n    struct GlobPattern *next;\t/* Chains to the next glob pattern in a glob\n\t\t\t\t * pattern list */\n    char *pattern;\t\t/* String value of the pattern, such as\n\t\t\t\t * \"*.txt\" or \"*.*\" */\n} GlobPattern;\n\ntypedef struct MacFileType {\n    struct MacFileType *next;\t/* Chains to the next mac file type in a mac\n\t\t\t\t * file type list */\n    OSType type;\t\t/* Mac file type, such as 'TEXT' or 'GIFF' */\n} MacFileType;\n\ntypedef struct FileFilterClause {\n    struct FileFilterClause *next;\n\t\t\t\t/* Chains to the next clause in a clause\n\t\t\t\t * list */\n    GlobPattern *patterns;\t/* Head of glob pattern type list */\n    GlobPattern *patternsTail;\t/* Tail of glob pattern type list */\n    MacFileType *macTypes;\t/* Head of mac file type list */\n    MacFileType *macTypesTail;\t/* Tail of mac file type list */\n} FileFilterClause;\n\ntypedef struct FileFilter {\n    struct FileFilter *next;\t/* Chains to the next filter in a filter\n\t\t\t\t * list */\n    char *name;\t\t\t/* Name of the file filter, such as \"Text\n\t\t\t\t * Documents\" */\n    FileFilterClause *clauses;\t/* Head of the clauses list */\n    FileFilterClause *clausesTail;\n\t\t\t\t/* Tail of the clauses list */\n} FileFilter;\n\n/*\n *----------------------------------------------------------------------\n *\n * FileFilterList --\n *\n *\tThe routine TkGetFileFilters() translates the string value of the\n *\t-filefilters option into a FileFilterList structure, which consists of\n *\ta list of file filters.\n *\n *\tEach file filter consists of one or more clauses. Each clause has one\n *\tor more glob patterns and/or one or more Mac file types\n *\n *----------------------------------------------------------------------\n */\n\ntypedef struct FileFilterList {\n    FileFilter *filters;\t/* Head of the filter list */\n    FileFilter *filtersTail;\t/* Tail of the filter list */\n    int numFilters;\t\t/* number of filters in the list */\n} FileFilterList;\n\nMODULE_SCOPE void\tTkFreeFileFilters(FileFilterList *flistPtr);\nMODULE_SCOPE void\tTkInitFileFilters(FileFilterList *flistPtr);\nMODULE_SCOPE int\tTkGetFileFilters(Tcl_Interp *interp,\n\t\t\t    FileFilterList *flistPtr, Tcl_Obj *valuePtr,\n\t\t\t    bool isWindows);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t/* _TK_FILE_FILTER */\n"
  },
  {
    "path": "generic/tkFocus.c",
    "content": "/*\n * tkFocus.c --\n *\n *\tThis file contains functions that manage the input focus for Tk.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * For each top-level window that has ever received the focus, there is a\n * record of the following type:\n */\n\ntypedef struct TkToplevelFocusInfo {\n    TkWindow *topLevelPtr;\t/* Information about top-level window. */\n    TkWindow *focusWinPtr;\t/* The next time the focus comes to this\n\t\t\t\t * top-level, it will be given to this\n\t\t\t\t * window. */\n    struct TkToplevelFocusInfo *nextPtr;\n\t\t\t\t/* Next in list of all toplevel focus records\n\t\t\t\t * for a given application. */\n} ToplevelFocusInfo;\n\n/*\n * One of the following structures exists for each display used by each\n * application. These are linked together from the TkMainInfo structure.\n * These structures are needed because it isn't sufficient to store a single\n * piece of focus information in each display or in each application: we need\n * the cross-product. There needs to be separate information for each display,\n * because it's possible to have multiple focus windows active simultaneously\n * on different displays. There also needs to be separate information for each\n * application, because of embedding: if an embedded application has the\n * focus, its container application also has the focus. Thus we keep a list of\n * structures for each application: the same display can appear in structures\n * for several applications at once.\n */\n\ntypedef struct TkDisplayFocusInfo {\n    TkDisplay *dispPtr;\t\t/* Display that this information pertains\n\t\t\t\t * to. */\n    struct TkWindow *focusWinPtr;\n\t\t\t\t/* Window that currently has the focus for\n\t\t\t\t * this application on this display, or NULL\n\t\t\t\t * if none. */\n    struct TkWindow *focusOnMapPtr;\n\t\t\t\t/* This points to a toplevel window that is\n\t\t\t\t * supposed to receive the X input focus as\n\t\t\t\t * soon as it is mapped (needed to handle the\n\t\t\t\t * fact that X won't allow the focus on an\n\t\t\t\t * unmapped window). NULL means no delayed\n\t\t\t\t * focus op in progress for this display. */\n    int forceFocus;\t\t/* Associated with focusOnMapPtr: non-zero\n\t\t\t\t * means claim the focus even if some other\n\t\t\t\t * application currently has it. */\n    size_t focusSerial;\t/* Serial number of last request this\n\t\t\t\t * application made to change the focus on\n\t\t\t\t * this display. Used to identify stale focus\n\t\t\t\t * notifications coming from the X server. */\n    struct TkDisplayFocusInfo *nextPtr;\n\t\t\t\t/* Next in list of all display focus records\n\t\t\t\t * for a given application. */\n} DisplayFocusInfo;\n\n/*\n * Debugging support...\n */\n\n#define DEBUG(dispPtr, arguments) \\\n    if ((dispPtr)->focusDebug) { \\\n\tprintf arguments; fflush(stdout); \\\n    }\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic DisplayFocusInfo*FindDisplayFocusInfo(TkMainInfo *mainPtr,\n\t\t\t    TkDisplay *dispPtr);\nstatic void\t\tFocusMapProc(void *clientData, XEvent *eventPtr);\nstatic void\t\tGenerateFocusEvents(TkWindow *sourcePtr,\n\t\t\t    TkWindow *destPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_FocusObjCmd --\n *\n *\tThis function is invoked to process the \"focus\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_FocusObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const focusOptions[] = {\n\t\"-displayof\", \"-force\", \"-lastfor\", NULL\n    };\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkWindow *winPtr = (TkWindow *)clientData;\n    TkWindow *newPtr, *topLevelPtr;\n    ToplevelFocusInfo *tlFocusPtr;\n    const char *windowName;\n    int index;\n\n    /*\n     * If invoked with no arguments, just return the current focus window.\n     */\n\n    if (objc == 1) {\n\tTk_Window focusWin = (Tk_Window) TkGetFocusWin(winPtr);\n\n\tif (focusWin != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj(focusWin));\n\t}\n\treturn TCL_OK;\n    }\n\n    /*\n     * If invoked with a single argument beginning with \".\" then focus on that\n     * window.\n     */\n\n    if (objc == 2) {\n\twindowName = Tcl_GetString(objv[1]);\n\n\t/*\n\t * The empty string case exists for backwards compatibility.\n\t */\n\n\tif (windowName[0] == '\\0') {\n\t    return TCL_OK;\n\t}\n\tif (windowName[0] == '.') {\n\t    newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);\n\t    if (newPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkSetFocusWin(newPtr, 0);\n\t    return TCL_OK;\n\t}\n    }\n\n    /*\n     * We have a subcommand to parse and act upon.\n     */\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], focusOptions,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    switch (index) {\n    case 0:\t\t\t/* -displayof */\n\twindowName = Tcl_GetString(objv[2]);\n\tnewPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);\n\tif (newPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tnewPtr = TkGetFocusWin(newPtr);\n\tif (newPtr != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) newPtr));\n\t}\n\tbreak;\n    case 1:\t\t\t/* -force */\n\twindowName = Tcl_GetString(objv[2]);\n\n\t/*\n\t * The empty string case exists for backwards compatibility.\n\t */\n\n\tif (windowName[0] == '\\0') {\n\t    return TCL_OK;\n\t}\n\tnewPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);\n\tif (newPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTkSetFocusWin(newPtr, 1);\n\tbreak;\n    case 2:\t\t\t/* -lastfor */\n\twindowName = Tcl_GetString(objv[2]);\n\tnewPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);\n\tif (newPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tfor (topLevelPtr = newPtr; topLevelPtr != NULL;\n\t\ttopLevelPtr = topLevelPtr->parentPtr) {\n\t    if (!(topLevelPtr->flags & TK_TOP_HIERARCHY)) {\n\t\tcontinue;\n\t    }\n\t    for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;\n\t\t    tlFocusPtr = tlFocusPtr->nextPtr) {\n\t\tif (tlFocusPtr->topLevelPtr == topLevelPtr) {\n\t\t    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window)\n\t\t\t    tlFocusPtr->focusWinPtr));\n\t\t    return TCL_OK;\n\t\t}\n\t    }\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) topLevelPtr));\n\t    return TCL_OK;\n\t}\n\tbreak;\n    default:\n\tTcl_Panic(\"bad const entries to focusOptions in focus command\");\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkFocusFilterEvent --\n *\n *\tThis function is invoked by Tk_HandleEvent when it encounters a\n *\tFocusIn, FocusOut, Enter, or Leave event.\n *\n * Results:\n *\tA return value of 1 means that Tk_HandleEvent should process the event\n *\tnormally (i.e. event handlers should be invoked). A return value of 0\n *\tmeans that this event should be ignored.\n *\n * Side effects:\n *\tAdditional events may be generated, and the focus may switch.\n *\n *--------------------------------------------------------------\n */\n\nbool\nTkFocusFilterEvent(\n    TkWindow *winPtr,\t\t/* Window that focus event is directed to. */\n    XEvent *eventPtr)\t\t/* FocusIn, FocusOut, Enter, or Leave\n\t\t\t\t * event. */\n{\n    /*\n     * Design notes: the window manager and X server work together to transfer\n     * the focus among top-level windows. This function takes care of\n     * transferring the focus from a top-level or wrapper window to the actual\n     * window within that top-level that has the focus. We do this by\n     * synthesizing X events to move the focus around. None of the FocusIn and\n     * FocusOut events generated by X are ever used outside of this function;\n     * only the synthesized events get through to the rest of the application.\n     * At one point (e.g. Tk4.0b1) Tk used to call X to move the focus from a\n     * top-level to one of its descendants, then just pass through the events\n     * generated by X. This approach didn't work very well, for a variety of\n     * reasons. For example, if X generates the events they go at the back of\n     * the event queue, which could cause problems if other things have\n     * already happened, such as moving the focus to yet another window.\n     */\n\n    ToplevelFocusInfo *tlFocusPtr;\n    DisplayFocusInfo *displayFocusPtr;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkWindow *newFocusPtr;\n    bool retValue;\n\n    /*\n     * If this was a generated event, just turn off the generated flag and\n     * pass the event through to Tk bindings.\n     */\n\n    if ((eventPtr->xfocus.send_event & GENERATED_FOCUS_EVENT_MAGIC) == GENERATED_FOCUS_EVENT_MAGIC) {\n\teventPtr->xfocus.send_event &= ~GENERATED_FOCUS_EVENT_MAGIC;\n\treturn true;\n    }\n\n    /*\n     * Check for special events generated by embedded applications to request\n     * the input focus. If this is one of those events, make the change in\n     * focus and return without any additional processing of the event (note:\n     * the \"detail\" field of the event indicates whether to claim the focus\n     * even if we don't already have it).\n     */\n\n    if ((eventPtr->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)\n\t    && (eventPtr->type == FocusIn)) {\n\tTkSetFocusWin(winPtr, eventPtr->xfocus.detail);\n\treturn false;\n    }\n\n    /*\n     * This was not a generated event. We'll return 1 (so that the event will\n     * be processed) if it's an Enter or Leave event, and 0 (so that the event\n     * won't be processed) if it's a FocusIn or FocusOut event.\n     */\n\n    retValue = false;\n    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n    if (eventPtr->type == FocusIn) {\n\t/*\n\t * Skip FocusIn events that cause confusion\n\t * NotifyVirtual and NotifyNonlinearVirtual - Virtual events occur on\n\t *\twindows in between the origin and destination of the focus\n\t *\tchange. For FocusIn we may see this when focus goes into an\n\t *\tembedded child. We don't care about this, although we may end\n\t *\tup getting a NotifyPointer later.\n\t * NotifyInferior - focus is coming to us from an embedded child. When\n\t *\tfocus is on an embedded focus, we still think we have the\n\t *\tfocus, too, so this message doesn't change our state.\n\t * NotifyPointerRoot - should never happen because this is sent to the\n\t *\troot window.\n\t *\n\t * Interesting FocusIn events are\n\t * NotifyAncestor - focus is coming from our parent, probably the root.\n\t * NotifyNonlinear - focus is coming from a different branch, probably\n\t *\tanother toplevel.\n\t * NotifyPointer - implicit focus because of the mouse position. This\n\t *\tis only interesting on toplevels, when it means that the focus\n\t *\thas been set to the root window but the mouse is over this\n\t *\ttoplevel. We take the focus implicitly (probably no window\n\t *\tmanager)\n\t */\n\n\tif ((eventPtr->xfocus.detail == NotifyVirtual)\n\t\t|| (eventPtr->xfocus.detail == NotifyNonlinearVirtual)\n\t\t|| (eventPtr->xfocus.detail == NotifyPointerRoot)\n\t\t|| (eventPtr->xfocus.detail == NotifyInferior)) {\n\t    return retValue;\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\t/*\n\t * Skip FocusOut events that cause confusion.\n\t * NotifyPointer - the pointer is in us or a child, and we are losing\n\t *\tfocus because of an XSetInputFocus. Other focus events will\n\t *\tset our state properly.\n\t * NotifyPointerRoot - should never happen because this is sent to the\n\t *\troot window.\n\t * NotifyInferior - focus leaving us for an embedded child. We retain\n\t *\ta notion of focus when an embedded child has focus.\n\t *\n\t * Interesting events are:\n\t * NotifyAncestor - focus is going to root.\n\t * NotifyNonlinear - focus is going to another branch, probably\n\t *\tanother toplevel.\n\t * NotifyVirtual, NotifyNonlinearVirtual - focus is passing through,\n\t *\tand we need to make sure we track this.\n\t */\n\n\tif ((eventPtr->xfocus.detail == NotifyPointer)\n\t\t|| (eventPtr->xfocus.detail == NotifyPointerRoot)\n\t\t|| (eventPtr->xfocus.detail == NotifyInferior)) {\n\t    return retValue;\n\t}\n    } else {\n\tretValue = true;\n\tif (eventPtr->xcrossing.detail == NotifyInferior) {\n\t    return retValue;\n\t}\n    }\n\n    /*\n     * If winPtr isn't a top-level window then just ignore the event.\n     */\n\n    winPtr = TkWmFocusToplevel(winPtr);\n    if (winPtr == NULL) {\n\treturn retValue;\n    }\n\n    /*\n     * If there is a grab in effect and this window is outside the grabbed\n     * tree, then ignore the event.\n     */\n\n    if (TkGrabState(winPtr) == TK_GRAB_EXCLUDED) {\n\treturn retValue;\n    }\n\n    /*\n     * It is possible that there were outstanding FocusIn and FocusOut events\n     * on their way to us at the time the focus was changed internally with\n     * the \"focus\" command. If so, these events could potentially cause us to\n     * lose the focus (switch it to the window of the last FocusIn event) even\n     * though the focus change occurred after those events. The following code\n     * detects this and ignores the stale events.\n     *\n     * Note: the focusSerial is only generated by TkpChangeFocus, whereas in\n     * Tk 4.2 there was always a nop marker generated.\n     */\n\n    if (eventPtr->xfocus.serial < displayFocusPtr->focusSerial) {\n\treturn retValue;\n    }\n\n    /*\n     * Find the ToplevelFocusInfo structure for the window, and make a new one\n     * if there isn't one already.\n     */\n\n    for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;\n\t    tlFocusPtr = tlFocusPtr->nextPtr) {\n\tif (tlFocusPtr->topLevelPtr == winPtr) {\n\t    break;\n\t}\n    }\n    if (tlFocusPtr == NULL) {\n\ttlFocusPtr = (ToplevelFocusInfo *)Tcl_Alloc(sizeof(ToplevelFocusInfo));\n\ttlFocusPtr->topLevelPtr = tlFocusPtr->focusWinPtr = winPtr;\n\ttlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;\n\twinPtr->mainPtr->tlFocusPtr = tlFocusPtr;\n    }\n    newFocusPtr = tlFocusPtr->focusWinPtr;\n\n    /*\n     * Ignore event if newFocus window is already dead!\n     */\n\n    if (newFocusPtr->flags & TK_ALREADY_DEAD) {\n\treturn retValue;\n    }\n\n    if (eventPtr->type == FocusIn) {\n\tGenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr);\n\tdisplayFocusPtr->focusWinPtr = newFocusPtr;\n\tdispPtr->focusPtr = newFocusPtr;\n\n\t/*\n\t * NotifyPointer gets set when the focus has been set to the root\n\t * window but we have the pointer. We'll treat this like an implicit\n\t * focus in event so that upon Leave events we release focus.\n\t */\n\n\tif (!(winPtr->flags & TK_EMBEDDED)) {\n\t    if (eventPtr->xfocus.detail == NotifyPointer) {\n\t\tdispPtr->implicitWinPtr = winPtr;\n\t    } else {\n\t\tdispPtr->implicitWinPtr = NULL;\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tGenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL);\n\n\t/*\n\t * Reset dispPtr->focusPtr, but only if it currently is the same as\n\t * this application's focusWinPtr: this check is needed to handle\n\t * embedded applications in the same process.\n\t */\n\n\tif (dispPtr->focusPtr == displayFocusPtr->focusWinPtr) {\n\t    dispPtr->focusPtr = NULL;\n\t}\n\tdisplayFocusPtr->focusWinPtr = NULL;\n    } else if (eventPtr->type == EnterNotify) {\n\t/*\n\t * If there is no window manager, or if the window manager isn't\n\t * moving the focus around (e.g. the disgusting \"NoTitleFocus\" option\n\t * has been selected in twm), then we won't get FocusIn or FocusOut\n\t * events. Instead, the \"focus\" field will be set in an Enter event to\n\t * indicate that we've already got the focus when the mouse enters the\n\t * window (even though we didn't get a FocusIn event). Watch for this\n\t * and grab the focus when it happens. Note: if this is an embedded\n\t * application then don't accept the focus implicitly like this; the\n\t * container application will give us the focus explicitly if it wants\n\t * us to have it.\n\t */\n\n\tif (eventPtr->xcrossing.focus &&\n\t\t(displayFocusPtr->focusWinPtr == NULL)\n\t\t&& !(winPtr->flags & TK_EMBEDDED)) {\n\t    DEBUG(dispPtr,\n\t\t    (\"Focussed implicitly on %s\\n\", newFocusPtr->pathName));\n\n\t    GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr);\n\t    displayFocusPtr->focusWinPtr = newFocusPtr;\n\t    dispPtr->implicitWinPtr = winPtr;\n\t    dispPtr->focusPtr = newFocusPtr;\n\t}\n    } else if (eventPtr->type == LeaveNotify) {\n\t/*\n\t * If the pointer just left a window for which we automatically\n\t * claimed the focus on enter, move the focus back to the root window,\n\t * where it was before we claimed it above. Note:\n\t * dispPtr->implicitWinPtr may not be the same as\n\t * displayFocusPtr->focusWinPtr (e.g. because the \"focus\" command was\n\t * used to redirect the focus after it arrived at\n\t * dispPtr->implicitWinPtr)!! In addition, we generate events because\n\t * the window manager won't give us a FocusOut event when we focus on\n\t * the root.\n\t */\n\n\tif ((dispPtr->implicitWinPtr != NULL)\n\t\t&& !(winPtr->flags & TK_EMBEDDED)) {\n\t    DEBUG(dispPtr, (\"Defocussed implicit Async from %s\\n\", displayFocusPtr->focusWinPtr->pathName));\n\t    GenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL);\n\t    XSetInputFocus(dispPtr->display, PointerRoot, RevertToPointerRoot,\n\t\t    CurrentTime);\n\t    displayFocusPtr->focusWinPtr = NULL;\n\t    dispPtr->implicitWinPtr = NULL;\n\t    dispPtr->focusPtr = NULL;\n\t}\n    }\n    return retValue;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetFocusWin --\n *\n *\tThis function is invoked to change the focus window for a given\n *\tdisplay in a given application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEvent handlers may be invoked to process the change of\n *\tfocus.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSetFocusWin(\n    TkWindow *winPtr,\t\t/* Window that is to be the new focus for its\n\t\t\t\t * display and application. */\n    int force)\t\t\t/* If non-zero, set the X focus to this window\n\t\t\t\t * even if the application doesn't currently\n\t\t\t\t * have the X focus. */\n{\n    ToplevelFocusInfo *tlFocusPtr;\n    DisplayFocusInfo *displayFocusPtr;\n    TkWindow *topLevelPtr;\n    size_t serial;\n    bool allMapped;\n\n    /*\n     * Don't set focus if window is already dead. [Bug 3574708]\n     */\n\n    if (winPtr->flags & TK_ALREADY_DEAD) {\n\treturn;\n    }\n\n    /*\n     * Get the current focus window with the same display and application\n     * as winPtr.\n     */\n\n    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n\n    /*\n     * Do nothing if the window already has focus and force is not set.  If\n     * force is set, we need to grab the focus, since under Windows or macOS\n     * this may involve taking control away from another application.\n     */\n\n    if (winPtr == displayFocusPtr->focusWinPtr && !force) {\n\treturn;\n    }\n\n    /*\n     * Find the toplevel window for winPtr, then find (or create) a record\n     * for the toplevel. Also see whether winPtr and all its ancestors are\n     * mapped.\n     */\n\n    allMapped = true;\n    for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {\n\tif (topLevelPtr == NULL) {\n\n\t    /*\n\t     * The window is being deleted. No point in worrying about giving\n\t     * it the focus.\n\t     */\n\n\t    return;\n\t}\n\tif (!(topLevelPtr->flags & TK_MAPPED)) {\n\t    allMapped = false;\n\t}\n\tif (topLevelPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n    }\n\n    /*\n     * If any ancestor of the new focus window isn't mapped, then we can't set\n     * focus for it (X will generate an error, for example). Instead, create\n     * an event handler that will set the focus to this window once it gets\n     * mapped. At the same time, delete any old handler that might be around;\n     * it's no longer relevant.\n     */\n\n    if (displayFocusPtr->focusOnMapPtr != NULL) {\n\tTk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr,\n\t\tVisibilityChangeMask, FocusMapProc,\n\t\tdisplayFocusPtr->focusOnMapPtr);\n\tdisplayFocusPtr->focusOnMapPtr = NULL;\n    }\n    if (!allMapped) {\n\tTk_CreateEventHandler((Tk_Window) winPtr, VisibilityChangeMask,\n\t\tFocusMapProc, winPtr);\n\tdisplayFocusPtr->focusOnMapPtr = winPtr;\n\tdisplayFocusPtr->forceFocus = force;\n\treturn;\n    }\n\n    for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;\n\t    tlFocusPtr = tlFocusPtr->nextPtr) {\n\tif (tlFocusPtr->topLevelPtr == topLevelPtr) {\n\t    break;\n\t}\n    }\n    if (tlFocusPtr == NULL) {\n\ttlFocusPtr = (ToplevelFocusInfo *)Tcl_Alloc(sizeof(ToplevelFocusInfo));\n\ttlFocusPtr->topLevelPtr = topLevelPtr;\n\ttlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;\n\twinPtr->mainPtr->tlFocusPtr = tlFocusPtr;\n    }\n    tlFocusPtr->focusWinPtr = winPtr;\n\n    if ((topLevelPtr->flags & TK_EMBEDDED) &&\n\t    (displayFocusPtr->focusWinPtr == NULL)) {\n\n\t/*\n\t * We are assigning focus to an embedded toplevel.  The platform\n\t * specific function TkpClaimFocus needs to handle the job of\n\t * assigning focus to the container, since we have no way to find the\n\t * container.\n\t */\n\n\tTkpClaimFocus(topLevelPtr, force);\n    } else if ((displayFocusPtr->focusWinPtr != NULL) || force) {\n\n\t/*\n\t * If we are forcing removal of focus from a container hosting a\n\t * toplevel from a different application, clear the focus in that\n\t * application.\n\t */\n\n\tif (force) {\n\t    TkWindow *focusPtr = winPtr->dispPtr->focusPtr;\n\t    if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) {\n\t\tDisplayFocusInfo *displayFocusPtr2 = FindDisplayFocusInfo(\n\t\t    focusPtr->mainPtr, focusPtr->dispPtr);\n\t\tdisplayFocusPtr2->focusWinPtr = NULL;\n\t    }\n\t}\n\n\t/*\n\t * Call the platform specific function TkpChangeFocus to move the\n\t * window manager's focus to a new toplevel.\n\t */\n\n\tserial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);\n\tif (serial != 0) {\n\t    displayFocusPtr->focusSerial = serial;\n\t}\n\tGenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr);\n\tdisplayFocusPtr->focusWinPtr = winPtr;\n\twinPtr->dispPtr->focusPtr = winPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetFocusWin --\n *\n *\tGiven a window, this function returns the current focus window for its\n *\tapplication and display.\n *\n * Results:\n *\tThe return value is a pointer to the window that currently has the\n *\tinput focus for the specified application and display, or NULL if\n *\tnone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkGetFocusWin(\n    TkWindow *winPtr)\t\t/* Window that selects an application and a\n\t\t\t\t * display. */\n{\n    DisplayFocusInfo *displayFocusPtr;\n\n    if (winPtr == NULL) {\n\treturn NULL;\n    }\n\n    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n    return displayFocusPtr->focusWinPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFocusKeyEvent --\n *\n *\tGiven a window and a key press or release event that arrived for the\n *\twindow, use information about the keyboard focus to compute which\n *\twindow should really get the event. In addition, update the event to\n *\trefer to its new window.\n *\n * Results:\n *\tThe return value is a pointer to the window that has the input focus\n *\tin winPtr's application, or NULL if winPtr's application doesn't have\n *\tthe input focus. If a non-NULL value is returned, eventPtr will be\n *\tupdated to refer properly to the focus window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkFocusKeyEvent(\n    TkWindow *winPtr,\t\t/* Window that selects an application and a\n\t\t\t\t * display. */\n    XEvent *eventPtr)\t\t/* X event to redirect (should be KeyPress or\n\t\t\t\t * KeyRelease). */\n{\n    DisplayFocusInfo *displayFocusPtr;\n    TkWindow *focusWinPtr;\n    int focusX, focusY;\n\n    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n    focusWinPtr = displayFocusPtr->focusWinPtr;\n\n    /*\n     * The code below is a debugging aid to make sure that dispPtr->focusPtr\n     * is kept properly in sync with the \"truth\", which is the value in\n     * displayFocusPtr->focusWinPtr.\n     */\n\n#ifdef TCL_MEM_DEBUG\n    if (focusWinPtr != winPtr->dispPtr->focusPtr) {\n\tprintf(\"TkFocusKeyEvent found dispPtr->focusPtr out of sync:\\n\");\n\tprintf(\"expected %s, got %s\\n\",\n\t\t(focusWinPtr != NULL) ? focusWinPtr->pathName : \"??\",\n\t\t(winPtr->dispPtr->focusPtr != NULL) ?\n\t\twinPtr->dispPtr->focusPtr->pathName : \"??\");\n    }\n#endif\n\n    if ((focusWinPtr != NULL) && (focusWinPtr->mainPtr == winPtr->mainPtr)) {\n\t/*\n\t * Map the x and y coordinates to make sense in the context of the\n\t * focus window, if possible (make both -1 if the map-from and map-to\n\t * windows don't share the same screen).\n\t */\n\n\tif ((focusWinPtr->display != winPtr->display)\n\t\t|| (focusWinPtr->screenNum != winPtr->screenNum)) {\n\t    eventPtr->xkey.x = -1;\n\t    eventPtr->xkey.y = -1;\n\t} else {\n\t    Tk_GetRootCoords((Tk_Window) focusWinPtr, &focusX, &focusY);\n\t    eventPtr->xkey.x = eventPtr->xkey.x_root - focusX;\n\t    eventPtr->xkey.y = eventPtr->xkey.y_root - focusY;\n\t}\n\teventPtr->xkey.window = focusWinPtr->window;\n\treturn focusWinPtr;\n    }\n\n    /*\n     * The event doesn't belong to us. Perhaps, due to embedding, it really\n     * belongs to someone else. Give the embedding code a chance to redirect\n     * the event.\n     */\n\n    TkpRedirectKeyEvent(winPtr, eventPtr);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFocusDeadWindow --\n *\n *\tThis function is invoked when it is determined that a window is dead.\n *\tIt cleans up focus-related information about the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tVarious things get cleaned up and recycled.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFocusDeadWindow(\n    TkWindow *winPtr)\t/* Information about the window that is being\n\t\t\t\t * deleted. */\n{\n    ToplevelFocusInfo *tlFocusPtr, *prevPtr;\n    DisplayFocusInfo *displayFocusPtr;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    int noMatch = 1;\n\n    /*\n     * Certain special windows like those used for send and clipboard have no\n     * mainPtr.\n     */\n\n    if (winPtr->mainPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Search for focus records that refer to this window either as the\n     * top-level window or the current focus window.\n     */\n\n    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n    for (prevPtr = NULL, tlFocusPtr = winPtr->mainPtr->tlFocusPtr;\n\t    tlFocusPtr != NULL;\n\t    prevPtr = tlFocusPtr, tlFocusPtr = tlFocusPtr->nextPtr) {\n\tif (winPtr == tlFocusPtr->topLevelPtr) {\n\t    /*\n\t     * The top-level window is the one being deleted: free the focus\n\t     * record and release the focus back to PointerRoot if we acquired\n\t     * it implicitly.\n\t     */\n\n\t    if (dispPtr->implicitWinPtr == winPtr) {\n\t\tDEBUG(dispPtr, (\"releasing focus to root after %s died\\n\",\n\t\t\ttlFocusPtr->topLevelPtr->pathName));\n\t\tdispPtr->implicitWinPtr = NULL;\n\t\tdisplayFocusPtr->focusWinPtr = NULL;\n\t\tdispPtr->focusPtr = NULL;\n\t    }\n\t    if (displayFocusPtr->focusWinPtr == tlFocusPtr->focusWinPtr) {\n\t\tdisplayFocusPtr->focusWinPtr = NULL;\n\t\tdispPtr->focusPtr = NULL;\n\t    }\n\t    if (prevPtr == NULL) {\n\t\twinPtr->mainPtr->tlFocusPtr = tlFocusPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = tlFocusPtr->nextPtr;\n\t    }\n\t    Tcl_Free(tlFocusPtr);\n\t    noMatch = 0;\n\t    break;\n\t} else if (winPtr == tlFocusPtr->focusWinPtr) {\n\t    /*\n\t     * The deleted window had the focus for its top-level: move the\n\t     * focus to the top-level itself.\n\t     */\n\n\t    tlFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr;\n\t    if ((displayFocusPtr->focusWinPtr == winPtr)\n\t\t    && !(tlFocusPtr->topLevelPtr->flags & TK_ALREADY_DEAD)) {\n\t\tDEBUG(dispPtr, (\"forwarding focus to %s after %s died\\n\",\n\t\t\ttlFocusPtr->topLevelPtr->pathName, winPtr->pathName));\n\t\tGenerateFocusEvents(displayFocusPtr->focusWinPtr,\n\t\t\ttlFocusPtr->topLevelPtr);\n\t\tdisplayFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr;\n\t\tdispPtr->focusPtr = tlFocusPtr->topLevelPtr;\n\t    }\n\t    noMatch = 0;\n\t    break;\n\t}\n    }\n\n    /*\n     * Occasionally, things can become unsynchronized. Move them back into\n     * synch now. [Bug 2496114]\n     */\n\n    if (displayFocusPtr->focusWinPtr == winPtr) {\n\tDEBUG(dispPtr, (\"focus cleared after %s died\\n\", winPtr->pathName));\n\tdisplayFocusPtr->focusWinPtr = NULL;\n    }\n\n    if (displayFocusPtr->focusOnMapPtr == winPtr) {\n\tdisplayFocusPtr->focusOnMapPtr = NULL;\n    }\n\n    /*\n     * It may happen that the search above for focus records that refer\n     * to this window did not find any match. In such a case, when the\n     * dead window had the focus, release it.\n     */\n    if (noMatch && (dispPtr->focusPtr == winPtr)) {\n\tdispPtr->focusPtr = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateFocusEvents --\n *\n *\tThis function is called to create FocusIn and FocusOut events to move\n *\tthe input focus from one window to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFocusIn and FocusOut events are generated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateFocusEvents(\n    TkWindow *sourcePtr,\t/* Window that used to have the focus (may be\n\t\t\t\t * NULL). */\n    TkWindow *destPtr)\t\t/* New window to have the focus (may be\n\t\t\t\t * NULL). */\n{\n    XEvent event;\n    TkWindow *winPtr;\n\n    winPtr = sourcePtr;\n    if (winPtr == NULL) {\n\twinPtr = destPtr;\n\tif (winPtr == NULL) {\n\t    return;\n\t}\n    }\n\n    event.xfocus.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xfocus.send_event = GENERATED_FOCUS_EVENT_MAGIC;\n    event.xfocus.display = winPtr->display;\n    event.xfocus.mode = NotifyNormal;\n    TkInOutEvents(&event, sourcePtr, destPtr, FocusOut, FocusIn,\n\t    TCL_QUEUE_MARK);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FocusMapProc --\n *\n *\tThis function is called as an event handler for VisibilityNotify\n *\tevents, if a window receives the focus at a time when its toplevel\n *\tisn't mapped. The function is needed because X won't allow the focus\n *\tto be set to an unmapped window; we detect when the toplevel is mapped\n *\tand set the focus to it then.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf this is a map event, the focus gets set to the toplevel given by\n *\tclientData.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFocusMapProc(\n    void *clientData,\t/* Toplevel window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    DisplayFocusInfo *displayFocusPtr;\n\n    if (eventPtr->type == VisibilityNotify) {\n\tdisplayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr,\n\t\twinPtr->dispPtr);\n\tDEBUG(winPtr->dispPtr, (\"auto-focussing on %s, force %d\\n\",\n\t\twinPtr->pathName, displayFocusPtr->forceFocus));\n\tTk_DeleteEventHandler((Tk_Window) winPtr, VisibilityChangeMask,\n\t\tFocusMapProc, clientData);\n\tdisplayFocusPtr->focusOnMapPtr = NULL;\n\tTkSetFocusWin(winPtr, displayFocusPtr->forceFocus);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindDisplayFocusInfo --\n *\n *\tGiven an application and a display, this function locate the focus\n *\trecord for that combination. If no such record exists, it creates a\n *\tnew record and initializes it.\n *\n * Results:\n *\tThe return value is a pointer to the record.\n *\n * Side effects:\n *\tA new record will be allocated if there wasn't one already.\n *\n *----------------------------------------------------------------------\n */\n\nstatic DisplayFocusInfo *\nFindDisplayFocusInfo(\n    TkMainInfo *mainPtr,\t/* Record that identifies a particular\n\t\t\t\t * application. */\n    TkDisplay *dispPtr)\t\t/* Display whose focus information is\n\t\t\t\t * needed. */\n{\n    DisplayFocusInfo *displayFocusPtr;\n\n    for (displayFocusPtr = mainPtr->displayFocusPtr;\n\t    displayFocusPtr != NULL;\n\t    displayFocusPtr = displayFocusPtr->nextPtr) {\n\tif (displayFocusPtr->dispPtr == dispPtr) {\n\t    return displayFocusPtr;\n\t}\n    }\n\n    /*\n     * The record doesn't exist yet. Make a new one.\n     */\n\n    displayFocusPtr = (DisplayFocusInfo *)Tcl_Alloc(sizeof(DisplayFocusInfo));\n    displayFocusPtr->dispPtr = dispPtr;\n    displayFocusPtr->focusWinPtr = NULL;\n    displayFocusPtr->focusOnMapPtr = NULL;\n    displayFocusPtr->forceFocus = 0;\n    displayFocusPtr->focusSerial = 0;\n    displayFocusPtr->nextPtr = mainPtr->displayFocusPtr;\n    mainPtr->displayFocusPtr = displayFocusPtr;\n    return displayFocusPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFocusFree --\n *\n *\tFree resources associated with maintaining the focus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThis mainPtr should no longer access focus information.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFocusFree(\n    TkMainInfo *mainPtr)\t/* Record that identifies a particular\n\t\t\t\t * application. */\n{\n    while (mainPtr->displayFocusPtr != NULL) {\n\tDisplayFocusInfo *displayFocusPtr = mainPtr->displayFocusPtr;\n\n\tmainPtr->displayFocusPtr = mainPtr->displayFocusPtr->nextPtr;\n\tTcl_Free(displayFocusPtr);\n    }\n    while (mainPtr->tlFocusPtr != NULL) {\n\tToplevelFocusInfo *tlFocusPtr = mainPtr->tlFocusPtr;\n\n\tmainPtr->tlFocusPtr = mainPtr->tlFocusPtr->nextPtr;\n\tTcl_Free(tlFocusPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFocusSplit --\n *\n *\tAdjust focus window for a newly managed toplevel, thus splitting the\n *\ttoplevel into two toplevels.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new record is allocated for the new toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFocusSplit(\n    TkWindow *winPtr)\t\t/* Window is the new toplevel. Any focus point\n\t\t\t\t * at or below window must be moved to this\n\t\t\t\t * new toplevel. */\n{\n    ToplevelFocusInfo *tlFocusPtr;\n    TkWindow *topLevelPtr, *subWinPtr;\n\n    FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);\n\n    /*\n     * Find the top-level window for winPtr, then find (or create) a record\n     * for the top-level. Also see whether winPtr and all its ancestors are\n     * mapped.\n     */\n\n    for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {\n\tif (topLevelPtr == NULL) {\n\t    /*\n\t     * The window is being deleted. No point in worrying about giving\n\t     * it the focus.\n\t     */\n\n\t    return;\n\t}\n\tif (topLevelPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Search all focus records to find child windows of winPtr.\n     */\n\n    for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;\n\t    tlFocusPtr = tlFocusPtr->nextPtr) {\n\tif (tlFocusPtr->topLevelPtr == topLevelPtr) {\n\t    break;\n\t}\n    }\n\n    if (tlFocusPtr == NULL) {\n\t/*\n\t * No focus record for this toplevel, nothing to do.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * See if current focusWin is child of the new toplevel.\n     */\n\n    for (subWinPtr = tlFocusPtr->focusWinPtr;\n\t    subWinPtr && subWinPtr != winPtr && subWinPtr != topLevelPtr;\n\t    subWinPtr = subWinPtr->parentPtr) {\n\t/* EMPTY */\n    }\n\n    if (subWinPtr == winPtr) {\n\t/*\n\t * Move focus to new toplevel.\n\t */\n\n\tToplevelFocusInfo *newTlFocusPtr = (ToplevelFocusInfo *)Tcl_Alloc(sizeof(ToplevelFocusInfo));\n\n\tnewTlFocusPtr->topLevelPtr = winPtr;\n\tnewTlFocusPtr->focusWinPtr = tlFocusPtr->focusWinPtr;\n\tnewTlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;\n\twinPtr->mainPtr->tlFocusPtr = newTlFocusPtr;\n\n\t/*\n\t * Move old toplevel's focus to the toplevel itself.\n\t */\n\n\ttlFocusPtr->focusWinPtr = topLevelPtr;\n    }\n\n    /*\n     * If it's not, then let focus progress naturally.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFocusJoin --\n *\n *\tRemove the focus record for this window that is no longer managed\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA tlFocusPtr record is removed\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFocusJoin(\n    TkWindow *winPtr)\t\t/* Window is no longer a toplevel. */\n{\n    ToplevelFocusInfo *tlFocusPtr, *tmpPtr;\n\n    /*\n     * Remove old toplevel record\n     */\n\n    if (winPtr && winPtr->mainPtr && winPtr->mainPtr->tlFocusPtr\n\t    && winPtr->mainPtr->tlFocusPtr->topLevelPtr == winPtr) {\n\ttmpPtr = winPtr->mainPtr->tlFocusPtr;\n\twinPtr->mainPtr->tlFocusPtr = tmpPtr->nextPtr;\n\tTcl_Free(tmpPtr);\n    } else if (winPtr && winPtr->mainPtr) {\n\tfor (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;\n\t\ttlFocusPtr = tlFocusPtr->nextPtr) {\n\t    if (tlFocusPtr->nextPtr &&\n\t\t    tlFocusPtr->nextPtr->topLevelPtr == winPtr) {\n\t\ttmpPtr = tlFocusPtr->nextPtr;\n\t\ttlFocusPtr->nextPtr = tmpPtr->nextPtr;\n\t\tTcl_Free(tmpPtr);\n\t\tbreak;\n\t    }\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkFont.c",
    "content": "/*\n * tkFont.c --\n *\n *\tThis file maintains a database of fonts for the Tk toolkit. It also\n *\tprovides several utility functions for measuring and displaying text.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkFont.h\"\n#if defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"    /* Defines TK_DRAW_IN_CONTEXT */\n#endif\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The following structure is used to keep track of all the fonts that exist\n * in the current application. It must be stored in the TkMainInfo for the\n * application.\n */\n\ntypedef struct TkFontInfo {\n    Tcl_HashTable fontCache;\t/* Map a string to an existing Tk_Font. Keys\n\t\t\t\t * are string font names, values are TkFont\n\t\t\t\t * pointers. */\n    Tcl_HashTable namedTable;\t/* Map a name to a set of attributes for a\n\t\t\t\t * font, used when constructing a Tk_Font from\n\t\t\t\t * a named font description. Keys are strings,\n\t\t\t\t * values are NamedFont pointers. */\n    TkMainInfo *mainPtr;\t/* Application that owns this structure. */\n    int updatePending;\t\t/* Non-zero when a World Changed event has\n\t\t\t\t * already been queued to handle a change to a\n\t\t\t\t * named font. */\n} TkFontInfo;\n\n/*\n * The following data structure is used to keep track of the font attributes\n * for each named font that has been defined. The named font is only deleted\n * when the last reference to it goes away.\n */\n\ntypedef struct NamedFont {\n    size_t refCount;\t\t/* Number of users of named font. */\n    int deletePending;\t\t/* Non-zero if font should be deleted when\n\t\t\t\t * last reference goes away. */\n    TkFontAttributes fa;\t/* Desired attributes for named font. */\n} NamedFont;\n\n/*\n * The following two structures are used to keep track of string measurement\n * information when using the text layout facilities.\n *\n * A LayoutChunk represents a contiguous range of text that can be measured\n * and displayed by low-level text calls. In general, chunks will be delimited\n * by newlines and tabs. Low-level, platform-specific things like kerning and\n * non-integer character widths may occur between the characters in a single\n * chunk, but not between characters in different chunks.\n *\n * A TextLayout is a collection of LayoutChunks. It can be displayed with\n * respect to any origin. It is the implementation of the Tk_TextLayout opaque\n * token.\n */\n\ntypedef struct LayoutChunk {\n    const char *start;\t\t/* Pointer to simple string to be displayed.\n\t\t\t\t * This is a pointer into the TkTextLayout's\n\t\t\t\t * string. */\n    Tcl_Size numBytes;\t\t/* The number of bytes in this chunk. */\n    Tcl_Size numChars;\t\t/* The number of characters in this chunk. */\n    Tcl_Size numDisplayChars;\t/* The number of characters to display when\n\t\t\t\t * this chunk is displayed. Can be less than\n\t\t\t\t * numChars if extra space characters were\n\t\t\t\t * absorbed by the end of the chunk. This will\n\t\t\t\t * be < 0 if this is a chunk that is holding a\n\t\t\t\t * tab or newline. */\n    int x, y;\t\t\t/* The origin of the first character in this\n\t\t\t\t * chunk with respect to the upper-left hand\n\t\t\t\t * corner of the TextLayout. */\n    int totalWidth;\t\t/* Width in pixels of this chunk. Used when\n\t\t\t\t * hit testing the invisible spaces at the end\n\t\t\t\t * of a chunk. */\n    int displayWidth;\t\t/* Width in pixels of the displayable\n\t\t\t\t * characters in this chunk. Can be less than\n\t\t\t\t * width if extra space characters were\n\t\t\t\t * absorbed by the end of the chunk. */\n} LayoutChunk;\n\ntypedef struct TextLayout {\n    Tk_Font tkfont;\t\t/* The font used when laying out the text. */\n    const char *string;\t\t/* The string that was layed out. */\n    int width;\t\t\t/* The maximum width of all lines in the text\n\t\t\t\t * layout. */\n    Tcl_Size numChunks;\t\t/* Number of chunks actually used in following\n\t\t\t\t * array. */\n    LayoutChunk chunks[TKFLEXARRAY];/* Array of chunks. The actual size will be\n\t\t\t\t * maxChunks. THIS FIELD MUST BE THE LAST IN\n\t\t\t\t * THE STRUCTURE. */\n} TextLayout;\n\n/*\n * The following structures are used as two-way maps between the values for\n * the fields in the TkFontAttributes structure and the strings used in Tcl,\n * when parsing both option-value format and style-list format font name\n * strings.\n */\n\nstatic const TkStateMap weightMap[] = {\n    {TK_FW_NORMAL,\t\"normal\"},\n    {TK_FW_BOLD,\t\"bold\"},\n    {TK_FW_UNKNOWN,\tNULL}\n};\n\nstatic const TkStateMap slantMap[] = {\n    {TK_FS_ROMAN,\t\"roman\"},\n    {TK_FS_ITALIC,\t\"italic\"},\n    {TK_FS_UNKNOWN,\tNULL}\n};\n\nstatic const TkStateMap underlineMap[] = {\n    {1,\t\t\t\"underline\"},\n    {0,\t\t\tNULL}\n};\n\nstatic const TkStateMap overstrikeMap[] = {\n    {1,\t\t\t\"overstrike\"},\n    {0,\t\t\tNULL}\n};\n\n/*\n * The following structures are used when parsing XLFD's into a set of\n * TkFontAttributes.\n */\n\nstatic const TkStateMap xlfdWeightMap[] = {\n    {TK_FW_NORMAL,\t\"normal\"},\n    {TK_FW_NORMAL,\t\"medium\"},\n    {TK_FW_NORMAL,\t\"book\"},\n    {TK_FW_NORMAL,\t\"light\"},\n    {TK_FW_BOLD,\t\"bold\"},\n    {TK_FW_BOLD,\t\"demi\"},\n    {TK_FW_BOLD,\t\"demibold\"},\n    {TK_FW_NORMAL,\tNULL}\t\t/* Assume anything else is \"normal\". */\n};\n\nstatic const TkStateMap xlfdSlantMap[] = {\n    {TK_FS_ROMAN,\t\"r\"},\n    {TK_FS_ITALIC,\t\"i\"},\n    {TK_FS_OBLIQUE,\t\"o\"},\n    {TK_FS_ROMAN,\tNULL}\t\t/* Assume anything else is \"roman\". */\n};\n\nstatic const TkStateMap xlfdSetwidthMap[] = {\n    {TK_SW_NORMAL,\t\"normal\"},\n    {TK_SW_CONDENSE,\t\"narrow\"},\n    {TK_SW_CONDENSE,\t\"semicondensed\"},\n    {TK_SW_CONDENSE,\t\"condensed\"},\n    {TK_SW_UNKNOWN,\tNULL}\n};\n\n/*\n * The following structure and defines specify the valid builtin options when\n * configuring a set of font attributes.\n */\n\nstatic const char *const fontOpt[] = {\n    \"-family\",\n    \"-size\",\n    \"-weight\",\n    \"-slant\",\n    \"-underline\",\n    \"-overstrike\",\n    NULL\n};\n\n#define FONT_FAMILY\t0\n#define FONT_SIZE\t1\n#define FONT_WEIGHT\t2\n#define FONT_SLANT\t3\n#define FONT_UNDERLINE\t4\n#define FONT_OVERSTRIKE\t5\n#define FONT_NUMFIELDS\t6\n\n/*\n * Hardcoded font aliases. These are used to describe (mostly) identical fonts\n * whose names differ from platform to platform. If the user-supplied font\n * name matches any of the names in one of the alias lists, the other names in\n * the alias list are also automatically tried.\n */\n\nstatic const char *const timesAliases[] = {\n    \"Times\",\t\t\t/* Unix. */\n    \"Times New Roman\",\t\t/* Windows. */\n    \"New York\",\t\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const helveticaAliases[] = {\n    \"Helvetica\",\t\t/* Unix. */\n    \"Arial\",\t\t\t/* Windows. */\n    \"Geneva\",\t\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const courierAliases[] = {\n    \"Courier\",\t\t\t/* Unix and Mac. */\n    \"Courier New\",\t\t/* Windows. */\n    NULL\n};\n\nstatic const char *const minchoAliases[] = {\n    \"mincho\",\t\t\t/* Unix. */\n    \"\\357\\274\\255\\357\\274\\263 \\346\\230\\216\\346\\234\\235\",\n\t\t\t\t/* Windows (MS mincho). */\n    \"\\346\\234\\254\\346\\230\\216\\346\\234\\235\\342\\210\\222\\357\\274\\255\",\n\t\t\t\t/* Mac (honmincho-M). */\n    NULL\n};\n\nstatic const char *const gothicAliases[] = {\n    \"gothic\",\t\t\t/* Unix. */\n    \"\\357\\274\\255\\357\\274\\263 \\343\\202\\264\\343\\202\\267\\343\\203\\203\\343\\202\\257\",\n\t\t\t\t/* Windows (MS goshikku). */\n    \"\\344\\270\\270\\343\\202\\264\\343\\202\\267\\343\\203\\203\\343\\202\\257\\342\\210\\222\\357\\274\\255\",\n\t\t\t\t/* Mac (goshikku-M). */\n    NULL\n};\n\nstatic const char *const dingbatsAliases[] = {\n    \"dingbats\", \"zapfdingbats\", \"itc zapfdingbats\",\n\t\t\t\t/* Unix. */\n\t\t\t\t/* Windows. */\n    \"zapf dingbats\",\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const *const fontAliases[] = {\n    timesAliases,\n    helveticaAliases,\n    courierAliases,\n    minchoAliases,\n    gothicAliases,\n    dingbatsAliases,\n    NULL\n};\n\n/*\n * Hardcoded font classes. If the character cannot be found in the base font,\n * the classes are examined in order to see if some other similar font should\n * be examined also.\n */\n\nstatic const char *const systemClass[] = {\n    \"fixed\",\t\t\t/* Unix. */\n\t\t\t\t/* Windows. */\n    \"chicago\", \"osaka\", \"sistemny\",\n\t\t\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const serifClass[] = {\n    \"times\", \"palatino\", \"mincho\",\n\t\t\t\t/* All platforms. */\n    \"song ti\",\t\t\t/* Unix. */\n    \"ms serif\", \"simplified arabic\",\n\t\t\t\t/* Windows. */\n    \"latinski\",\t\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const sansClass[] = {\n    \"helvetica\", \"gothic\",\t/* All platforms. */\n\t\t\t\t/* Unix. */\n    \"ms sans serif\", \"traditional arabic\",\n\t\t\t\t/* Windows. */\n    \"bastion\",\t\t\t/* Mac. */\n    NULL\n};\n\nstatic const char *const monoClass[] = {\n    \"courier\", \"gothic\",\t/* All platforms. */\n    \"fangsong ti\",\t\t/* Unix. */\n    \"simplified arabic fixed\",\t/* Windows. */\n    \"monaco\", \"pryamoy\",\t/* Mac. */\n    NULL\n};\n\nstatic const char *const symbolClass[] = {\n    \"symbol\", \"dingbats\", \"wingdings\", NULL\n};\n\nstatic const char *const *const fontFallbacks[] = {\n    systemClass,\n    serifClass,\n    sansClass,\n    monoClass,\n    symbolClass,\n    NULL\n};\n\n/*\n * Global fallbacks. If the character could not be found in the preferred\n * fallback list, this list is examined. If the character still cannot be\n * found, all font families in the system are examined.\n */\n\nstatic const char *const globalFontClass[] = {\n    \"symbol\",\t\t\t/* All platforms. */\n\t\t\t\t/* Unix. */\n    \"lucida sans unicode\",\t/* Windows. */\n    \"bitstream cyberbit\",\t/* Windows popular CJK font */\n    \"chicago\",\t\t\t/* Mac. */\n    NULL\n};\n\n#define GetFontAttributes(tkfont) \\\n\t((const TkFontAttributes *) &((TkFont *) (tkfont))->fa)\n\n#define GetFontMetrics(tkfont)    \\\n\t((const TkFontMetrics *) &((TkFont *) (tkfont))->fm)\n\n\nstatic int\t\tConfigAttributesObj(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    TkFontAttributes *faPtr);\nstatic void\t\tDupFontObjProc(Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr);\nstatic int\t\tFieldSpecified(const char *field);\nstatic void\t\tFreeFontObj(Tcl_Obj *objPtr);\nstatic void\t\tFreeFontObjProc(Tcl_Obj *objPtr);\nstatic int\t\tGetAttributeInfoObj(Tcl_Interp *interp,\n\t\t\t    const TkFontAttributes *faPtr, Tcl_Obj *objPtr);\nstatic LayoutChunk *\tNewChunk(TextLayout **layoutPtrPtr, Tcl_Size *maxPtr,\n\t\t\t    const char *start, Tcl_Size numChars, int curX,\n\t\t\t    int newX, int y);\nstatic int\t\tParseFontNameObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tcl_Obj *objPtr, TkFontAttributes *faPtr);\nstatic void\t\tRecomputeWidgets(TkWindow *winPtr);\nstatic int\t\tSetFontFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);\nstatic void\t\tTheWorldHasChanged(void *clientData);\nstatic void\t\tUpdateDependentFonts(TkFontInfo *fiPtr,\n\t\t\t    Tk_Window tkwin, Tcl_HashEntry *namedHashPtr);\n\n/*\n * The following structure defines the implementation of the \"font\" Tcl\n * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each\n * font object points to the TkFont structure for the font, or NULL.\n */\n\nconst Tcl_ObjType tkFontObjType = {\n    \"font\",\t\t\t/* name */\n    FreeFontObjProc,\t\t/* freeIntRepProc */\n    DupFontObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFontPkgInit --\n *\n *\tThis function is called when an application is created. It initializes\n *\tall the structures that are used by the font package on a per\n *\tapplication basis.\n *\n * Results:\n *\tStores a token in the mainPtr to hold information needed by this\n *\tpackage on a per application basis.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkFontPkgInit(\n    TkMainInfo *mainPtr)\t/* The application being created. */\n{\n    TkFontInfo *fiPtr = (TkFontInfo *)Tcl_Alloc(sizeof(TkFontInfo));\n\n    Tcl_InitHashTable(&fiPtr->fontCache, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&fiPtr->namedTable, TCL_STRING_KEYS);\n    fiPtr->mainPtr = mainPtr;\n    fiPtr->updatePending = 0;\n    mainPtr->fontInfoPtr = fiPtr;\n\n    TkpFontPkgInit(mainPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFontPkgFree --\n *\n *\tThis function is called when an application is deleted. It deletes all\n *\tthe structures that were used by the font package for this\n *\tapplication.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkFontPkgFree(\n    TkMainInfo *mainPtr)\t/* The application being deleted. */\n{\n    TkFontInfo *fiPtr = mainPtr->fontInfoPtr;\n    Tcl_HashEntry *hPtr, *searchPtr;\n    Tcl_HashSearch search;\n#ifdef PURIFY\n    int fontsLeft = 0;\n#endif\n\n    for (searchPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);\n\t    searchPtr != NULL;\n\t    searchPtr = Tcl_NextHashEntry(&search)) {\n#ifdef PURIFY\n\tfontsLeft++;\n#endif\n#ifdef DEBUG_FONTS\n\tfprintf(stderr, \"Font %s still in cache.\\n\",\n\t\t(char *) Tcl_GetHashKey(&fiPtr->fontCache, searchPtr));\n#endif\n    }\n\n#ifdef PURIFY\n    if (fontsLeft) {\n\tTcl_Panic(\"TkFontPkgFree: all fonts should have been freed already\");\n    }\n#endif\n\n    Tcl_DeleteHashTable(&fiPtr->fontCache);\n\n    hPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);\n    while (hPtr != NULL) {\n\tTcl_Free(Tcl_GetHashValue(hPtr));\n\thPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&fiPtr->namedTable);\n    if (fiPtr->updatePending) {\n\tTcl_CancelIdleCall(TheWorldHasChanged, fiPtr);\n    }\n    Tcl_Free(fiPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FontObjCmd --\n *\n *\tThis function is implemented to process the \"font\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_FontObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int index;\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"actual\",\t\"configure\",\t\"create\",\t\"delete\",\n\t\"families\",\t\"measure\",\t\"metrics\",\t\"names\",\n\tNULL\n    };\n    enum options {\n\tFONT_ACTUAL,\tFONT_CONFIGURE,\tFONT_CREATE,\tFONT_DELETE,\n\tFONT_FAMILIES,\tFONT_MEASURE,\tFONT_METRICS,\tFONT_NAMES\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case FONT_ACTUAL: {\n\tint result;\n\tTcl_Size skip, n;\n\tconst char *s;\n\tTk_Font tkfont;\n\tTcl_Obj *optPtr, *charPtr, *resultPtr;\n\tint uniChar = 0;\n\tconst TkFontAttributes *faPtr;\n\tTkFontAttributes fa;\n\n\t/*\n\t * Params 0 and 1 are 'font actual'. Param 2 is the font name. 3-4 may\n\t * be '-displayof $window'\n\t */\n\n\tskip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Next parameter may be an option.\n\t */\n\n\tn = 3 + skip;\n\toptPtr = NULL;\n\tcharPtr = NULL;\n\tif (n < objc) {\n\t    s = Tcl_GetString(objv[n]);\n\t    if (s[0] == '-' && s[1] != '-') {\n\t\toptPtr = objv[n];\n\t\tn++;\n\t    } else {\n\t\toptPtr = NULL;\n\t    }\n\t}\n\n\t/*\n\t * Next parameter may be '--' to mark end of options.\n\t */\n\n\tif (n < objc) {\n\t    if (!strcmp(Tcl_GetString(objv[n]), \"--\")) {\n\t\tn++;\n\t    }\n\t}\n\n\t/*\n\t * Next parameter is the character to get font information for.\n\t */\n\n\tif (n < objc) {\n\t    charPtr = objv[n];\n\t    n++;\n\t}\n\n\t/*\n\t * If there were fewer than 3 args, or args remain, that's an error.\n\t */\n\n\tif (objc < 3 || n < objc) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"font ?-displayof window? ?-option? ?--? ?char?\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * The 'charPtr' arg must be a single Unicode.\n\t */\n\n\tif (charPtr != NULL) {\n\t    const char *string = Tcl_GetString(charPtr);\n\t    Tcl_Size len = Tcl_UtfToUniChar(string, &uniChar);\n\n\t    if (len != charPtr->length) {\n\t\tresultPtr = Tcl_NewStringObj(\n\t\t\t\"expected a single character but got \\\"\", TCL_INDEX_NONE);\n\t\tTcl_AppendLimitedToObj(resultPtr, string,\n\t\t\tTCL_INDEX_NONE, 40, \"...\");\n\t\tTcl_AppendToObj(resultPtr, \"\\\"\", TCL_INDEX_NONE);\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"FONT_SAMPLE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * Find the font.\n\t */\n\n\ttkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);\n\tif (tkfont == NULL) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Determine the font attributes.\n\t */\n\n\tif (charPtr == NULL) {\n\t    faPtr = GetFontAttributes(tkfont);\n\t} else {\n\t    TkpGetFontAttrsForChar(tkwin, tkfont, uniChar, &fa);\n\t    faPtr = &fa;\n\t}\n\tresult = GetAttributeInfoObj(interp, faPtr, optPtr);\n\n\tTk_FreeFont(tkfont);\n\treturn result;\n    }\n    case FONT_CONFIGURE: {\n\tint result;\n\tconst char *string;\n\tTcl_Obj *objPtr;\n\tNamedFont *nfPtr;\n\tTcl_HashEntry *namedHashPtr;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"fontname ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetString(objv[2]);\n\tnamedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string);\n\tnfPtr = NULL;\n\tif (namedHashPtr != NULL) {\n\t    nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n\t}\n\tif ((namedHashPtr == NULL) || nfPtr->deletePending) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"named font \\\"%s\\\" does not exist\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"FONT\", string, (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 3) {\n\t    objPtr = NULL;\n\t} else if (objc == 4) {\n\t    objPtr = objv[3];\n\t} else {\n\t    result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3,\n\t\t    &nfPtr->fa);\n\t    UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);\n\t    return result;\n\t}\n\treturn GetAttributeInfoObj(interp, &nfPtr->fa, objPtr);\n    }\n    case FONT_CREATE: {\n\tint skip = 3, i;\n\tconst char *name;\n\tchar buf[16 + TCL_INTEGER_SPACE];\n\tTkFontAttributes fa;\n\tTcl_HashEntry *namedHashPtr;\n\n\tif (objc < 3) {\n\t    name = NULL;\n\t} else {\n\t    name = Tcl_GetString(objv[2]);\n\t    if (name[0] == '-') {\n\t\tname = NULL;\n\t    }\n\t}\n\tif (name == NULL) {\n\t    /*\n\t     * No font name specified. Generate one of the form \"fontX\".\n\t     */\n\n\t    for (i = 1; ; i++) {\n\t\tsnprintf(buf, sizeof(buf), \"font%d\", i);\n\t\tnamedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, buf);\n\t\tif (namedHashPtr == NULL) {\n\t\t    break;\n\t\t}\n\t    }\n\t    name = buf;\n\t    skip = 2;\n\t}\n\tTkInitFontAttributes(&fa);\n\tif (ConfigAttributesObj(interp, tkwin, objc - skip, objv + skip,\n\t\t&fa) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(name, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case FONT_DELETE: {\n\tTcl_Size i;\n\tint result = TCL_OK;\n\tconst char *string;\n\n\t/*\n\t * Delete the named font. If there are still widgets using this font,\n\t * then it isn't deleted right away.\n\t */\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"fontname ?fontname ...?\");\n\t    return TCL_ERROR;\n\t}\n\tfor (i = 2; (i < objc) && (result == TCL_OK); i++) {\n\t    string = Tcl_GetString(objv[i]);\n\t    result = TkDeleteNamedFont(interp, tkwin, string);\n\t}\n\treturn result;\n    }\n    case FONT_FAMILIES: {\n\tTcl_Size skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);\n\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc != 2 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-displayof window?\");\n\t    return TCL_ERROR;\n\t}\n\tTkpGetFontFamilies(interp, tkwin);\n\tbreak;\n    }\n    case FONT_MEASURE: {\n\tconst char *string;\n\tTk_Font tkfont;\n\tTcl_Size length = 0;\n\tTcl_Size skip = 0;\n\n\tif (objc > 4) {\n\t    skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);\n\t    if (skip == TCL_INDEX_NONE) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (objc != 4 + skip) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"font ?-displayof window? text\");\n\t    return TCL_ERROR;\n\t}\n\ttkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);\n\tif (tkfont == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tstring = Tcl_GetStringFromObj(objv[3 + skip], &length);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\tTk_TextWidth(tkfont, string, length)));\n\tTk_FreeFont(tkfont);\n\tbreak;\n    }\n    case FONT_METRICS: {\n\tTk_Font tkfont;\n\tTcl_Size skip;\n\tint i;\n\tconst TkFontMetrics *fmPtr;\n\tstatic const char *const switches[] = {\n\t    \"-ascent\", \"-descent\", \"-fixed\", \"-linespace\", NULL\n\t};\n\n\tskip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);\n\tif (skip == TCL_INDEX_NONE) {\n\t    return TCL_ERROR;\n\t}\n\tif ((objc < 3) || (objc > 4 + skip)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"font ?-displayof window? ?-option?\");\n\t    return TCL_ERROR;\n\t}\n\ttkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);\n\tif (tkfont == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tobjc -= skip;\n\tobjv += skip;\n\tfmPtr = GetFontMetrics(tkfont);\n\tif (objc == 3) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"-ascent %d -descent %d -linespace %d -fixed %d\",\n\t\t    fmPtr->ascent, fmPtr->descent,\n\t\t    fmPtr->ascent + fmPtr->descent, fmPtr->fixed));\n\t} else {\n\t    if (Tcl_GetIndexFromObj(interp, objv[3], switches, \"metric\", 0,\n\t\t    &index) != TCL_OK) {\n\t\tTk_FreeFont(tkfont);\n\t\treturn TCL_ERROR;\n\t    }\n\t    i = 0;\t\t/* Needed only to prevent compiler warning. */\n\t    switch (index) {\n\t    case 0: i = fmPtr->ascent;\t\t\tbreak;\n\t    case 1: i = fmPtr->descent;\t\t\tbreak;\n\t    case 2: i = fmPtr->fixed;\t\t\tbreak;\n\t    case 3: i = fmPtr->ascent + fmPtr->descent;\tbreak;\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));\n\t}\n\tTk_FreeFont(tkfont);\n\tbreak;\n    }\n    case FONT_NAMES: {\n\tTcl_HashSearch search;\n\tTcl_HashEntry *namedHashPtr;\n\tTcl_Obj *resultPtr;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"names\");\n\t    return TCL_ERROR;\n\t}\n\tresultPtr = Tcl_NewObj();\n\tnamedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);\n\twhile (namedHashPtr != NULL) {\n\t    NamedFont *nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n\n\t    if (!nfPtr->deletePending) {\n\t\tchar *string = (char *)Tcl_GetHashKey(&fiPtr->namedTable,\n\t\t\tnamedHashPtr);\n\n\t\tTcl_ListObjAppendElement(NULL, resultPtr,\n\t\t\tTcl_NewStringObj(string, TCL_INDEX_NONE));\n\t    }\n\t    namedHashPtr = Tcl_NextHashEntry(&search);\n\t}\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * UpdateDependentFonts, TheWorldHasChanged, RecomputeWidgets --\n *\n *\tCalled when the attributes of a named font changes. Updates all the\n *\tinstantiated fonts that depend on that named font and then uses the\n *\tbrute force approach and prepares every widget to recompute its\n *\tgeometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThings get queued for redisplay.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nUpdateDependentFonts(\n    TkFontInfo *fiPtr,\t\t/* Info about application's fonts. */\n    Tk_Window tkwin,\t\t/* A window in the application. */\n    Tcl_HashEntry *namedHashPtr)/* The named font that is changing. */\n{\n    Tcl_HashEntry *cacheHashPtr;\n    Tcl_HashSearch search;\n    TkFont *fontPtr;\n    NamedFont *nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n\n    if (nfPtr->refCount == 0) {\n\t/*\n\t * Well nobody's using this named font, so don't have to tell any\n\t * widgets to recompute themselves.\n\t */\n\n\treturn;\n    }\n\n    cacheHashPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);\n    while (cacheHashPtr != NULL) {\n\tfor (fontPtr = (TkFont *)Tcl_GetHashValue(cacheHashPtr);\n\t\tfontPtr != NULL; fontPtr = fontPtr->nextPtr) {\n\t    if (fontPtr->namedHashPtr == namedHashPtr) {\n\t\tTkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);\n\t\tif (!fiPtr->updatePending) {\n\t\t    fiPtr->updatePending = 1;\n\t\t    Tcl_DoWhenIdle(TheWorldHasChanged, fiPtr);\n\t\t}\n\t    }\n\t}\n\tcacheHashPtr = Tcl_NextHashEntry(&search);\n    }\n}\n\nstatic void\nTheWorldHasChanged(\n    void *clientData)\t/* Info about application's fonts. */\n{\n    TkFontInfo *fiPtr = (TkFontInfo *)clientData;\n\n    fiPtr->updatePending = 0;\n    RecomputeWidgets(fiPtr->mainPtr->winPtr);\n}\n\nstatic void\nRecomputeWidgets(\n    TkWindow *winPtr)\t\t/* Window to which command is sent. */\n{\n    Tk_ClassWorldChangedProc *proc =\n\t    Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc);\n    TkWindow *tkwinPtr;\n\n    if (proc != NULL) {\n\tproc(winPtr->instanceData);\n    }\n\n    /*\n     * Notify all the descendants of this window that the world has changed.\n     *\n     * This could be done recursively or iteratively. The recursive version is\n     * easier to implement and understand, and typically, windows with a -font\n     * option will be leaf nodes in the widget hierarchy (buttons, labels,\n     * etc.), so the recursion depth will be shallow.\n     *\n     * However, the additional overhead of the recursive calls may become a\n     * performance problem if typical usage alters such that -font'ed widgets\n     * appear high in the hierarchy, causing deep recursion. This could happen\n     * with text widgets, or more likely with the labelframe\n     * widget. With these widgets it is possible, even likely, that a\n     * -font'ed widget (text or labelframe) will not be a leaf node, but\n     * will instead have many descendants. If this is ever found to cause a\n     * performance problem, it may be worth investigating an iterative version\n     * of the code below.\n     */\n\n    for (tkwinPtr=winPtr->childList ; tkwinPtr!=NULL ; tkwinPtr=tkwinPtr->nextPtr) {\n\tRecomputeWidgets(tkwinPtr);\n    }\n\n    /*\n     * Broadcast font change virtually for mega-widget layout managers.\n     * Do this after the font change has been propagated to core widgets.\n    */\n    Tk_SendVirtualEvent((Tk_Window)winPtr, \"TkWorldChanged\",\n\t\t\tTcl_NewStringObj(\"FontChanged\",-1));\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkCreateNamedFont --\n *\n *\tCreate the specified named font with the given attributes in the named\n *\tfont table associated with the interp.\n *\n * Results:\n *\tReturns TCL_OK if the font was successfully created, or TCL_ERROR if\n *\tthe named font already existed. If TCL_ERROR is returned, an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tAssume there used to exist a named font by the specified name, and\n *\tthat the named font had been deleted, but there were still some\n *\twidgets using the named font at the time it was deleted. If a new\n *\tnamed font is created with the same name, all those widgets that were\n *\tusing the old named font will be redisplayed using the new named\n *\tfont's attributes.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkCreateNamedFont(\n    Tcl_Interp *interp,\t\t/* Interp for error return (can be NULL). */\n    Tk_Window tkwin,\t\t/* A window associated with interp. */\n    const char *name,\t\t/* Name for the new named font. */\n    TkFontAttributes *faPtr)\t/* Attributes for the new named font. */\n{\n    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;\n    Tcl_HashEntry *namedHashPtr;\n    int isNew;\n    NamedFont *nfPtr;\n\n    namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &isNew);\n    if (!isNew) {\n\tnfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n\tif (!nfPtr->deletePending) {\n\t    if (interp) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"named font \\\"%s\\\" already exists\", name));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"FONT\", \"EXISTS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Recreating a named font with the same name as a previous named\n\t * font. Some widgets were still using that named font, so they need\n\t * to get redisplayed.\n\t */\n\n\tnfPtr->fa = *faPtr;\n\tnfPtr->deletePending = 0;\n\tUpdateDependentFonts(fiPtr, tkwin, namedHashPtr);\n\treturn TCL_OK;\n    }\n\n    nfPtr = (NamedFont *)Tcl_Alloc(sizeof(NamedFont));\n    nfPtr->deletePending = 0;\n    Tcl_SetHashValue(namedHashPtr, nfPtr);\n    nfPtr->fa = *faPtr;\n    nfPtr->refCount = 0;\n    nfPtr->deletePending = 0;\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkDeleteNamedFont --\n *\n *\tDelete the named font. If there are still widgets using this font,\n *\tthen it isn't deleted right away.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkDeleteNamedFont(\n    Tcl_Interp *interp,\t\t/* Interp for error return (can be NULL). */\n    Tk_Window tkwin,\t\t/* A window associated with interp. */\n    const char *name)\t\t/* Name for the new named font. */\n{\n    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;\n    NamedFont *nfPtr;\n    Tcl_HashEntry *namedHashPtr;\n\n    namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, name);\n    if (namedHashPtr == NULL) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"named font \\\"%s\\\" does not exist\", name));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"FONT\", name, (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n    if (nfPtr->refCount != 0) {\n\tnfPtr->deletePending = 1;\n    } else {\n\tTcl_DeleteHashEntry(namedHashPtr);\n\tTcl_Free(nfPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetFont --\n *\n *\tGiven a string description of a font, map the description to a\n *\tcorresponding Tk_Font that represents the font.\n *\n * Results:\n *\tThe return value is token for the font, or NULL if an error prevented\n *\tthe font from being created. If NULL is returned, an error message\n *\twill be left in the interp's result.\n *\n * Side effects:\n *\tThe font is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned\n *\tup when fonts aren't in use anymore.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_Font\nTk_GetFont(\n    Tcl_Interp *interp,\t\t/* Interp for database and error return. */\n    Tk_Window tkwin,\t\t/* For display on which font will be used. */\n    const char *string)\t\t/* String describing font, as: named font,\n\t\t\t\t * native format, or parseable string. */\n{\n    Tk_Font tkfont;\n    Tcl_Obj *strPtr;\n\n    strPtr = Tcl_NewStringObj(string, TCL_INDEX_NONE);\n    Tcl_IncrRefCount(strPtr);\n    tkfont = Tk_AllocFontFromObj(interp, tkwin, strPtr);\n    Tcl_DecrRefCount(strPtr);\n    return tkfont;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_AllocFontFromObj --\n *\n *\tGiven a string description of a font, map the description to a\n *\tcorresponding Tk_Font that represents the font.\n *\n * Results:\n *\tThe return value is token for the font, or NULL if an error prevented\n *\tthe font from being created. If NULL is returned, an error message\n *\twill be left in interp's result object.\n *\n * Side effects:\n *\tThe font is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned\n *\tup when fonts aren't in use anymore.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_Font\nTk_AllocFontFromObj(\n    Tcl_Interp *interp,\t\t/* Interp for database and error return. */\n    Tk_Window tkwin,\t\t/* For screen on which font will be used. */\n    Tcl_Obj *objPtr)\t\t/* Object describing font, as: named font,\n\t\t\t\t * native format, or parseable string. */\n{\n    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;\n    Tcl_HashEntry *cacheHashPtr, *namedHashPtr;\n    TkFont *fontPtr, *firstFontPtr, *oldFontPtr;\n    int isNew, descent;\n    NamedFont *nfPtr;\n\n    if (objPtr->typePtr != &tkFontObjType\n\t    || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {\n\tSetFontFromAny(interp, objPtr);\n    }\n\n    oldFontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;\n    if (oldFontPtr != NULL) {\n\tif (oldFontPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a TkFont that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\n\t    FreeFontObj(objPtr);\n\t    oldFontPtr = NULL;\n\t} else if (Tk_Screen(tkwin) == oldFontPtr->screen\n#ifdef HAVE_XFT\n\t\t&& Tk_Colormap(tkwin) == oldFontPtr->colormap\n\t\t&& Tk_Visual(tkwin) == oldFontPtr->visual\n#endif\n\t) {\n\t    oldFontPtr->resourceRefCount++;\n\t    return (Tk_Font) oldFontPtr;\n\t}\n    }\n\n    /*\n     * Next, search the list of fonts that have the name we want, to see if\n     * one of them is for the right screen.\n     */\n\n    isNew = 0;\n    if (oldFontPtr != NULL) {\n\tcacheHashPtr = oldFontPtr->cacheHashPtr;\n\tFreeFontObj(objPtr);\n    } else {\n\tcacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache,\n\t\tTcl_GetString(objPtr), &isNew);\n    }\n    firstFontPtr = (TkFont *)Tcl_GetHashValue(cacheHashPtr);\n    for (fontPtr = firstFontPtr; (fontPtr != NULL);\n\t    fontPtr = fontPtr->nextPtr) {\n\tif (Tk_Screen(tkwin) == fontPtr->screen\n#ifdef HAVE_XFT\n\t\t&& Tk_Colormap(tkwin) == fontPtr->colormap\n\t\t&& Tk_Visual(tkwin) == fontPtr->visual\n#endif\n\t    ) {\n\t    fontPtr->resourceRefCount++;\n\t    fontPtr->objRefCount++;\n\t    objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;\n\t    objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;\n\t    return (Tk_Font) fontPtr;\n\t}\n    }\n\n    /*\n     * The desired font isn't in the table. Make a new one.\n     */\n\n    namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable,\n\t    Tcl_GetString(objPtr));\n    if (namedHashPtr != NULL) {\n\t/*\n\t * Construct a font based on a named font.\n\t */\n\n\tnfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);\n\tnfPtr->refCount++;\n\n\tfontPtr = TkpGetFontFromAttributes(NULL, tkwin, &nfPtr->fa);\n    } else {\n\t/*\n\t * Native font?\n\t */\n\n\tfontPtr = TkpGetNativeFont(tkwin, Tcl_GetString(objPtr));\n\tif (fontPtr == NULL) {\n\t    TkFontAttributes fa;\n\t    Tcl_Obj *dupObjPtr = Tcl_DuplicateObj(objPtr);\n\n\t    if (ParseFontNameObj(interp, tkwin, dupObjPtr, &fa) != TCL_OK) {\n\t\tif (isNew) {\n\t\t    Tcl_DeleteHashEntry(cacheHashPtr);\n\t\t}\n\t\tTcl_DecrRefCount(dupObjPtr);\n\t\treturn NULL;\n\t    }\n\t    Tcl_DecrRefCount(dupObjPtr);\n\n\t    /*\n\t     * String contained the attributes inline.\n\t     */\n\n\t    fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &fa);\n\t}\n    }\n\n    /*\n     * Detect the system font engine going wrong and fail more gracefully.\n     */\n\n    if (fontPtr == NULL) {\n\tif (isNew) {\n\t    Tcl_DeleteHashEntry(cacheHashPtr);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"failed to allocate font due to internal system font engine\"\n\t\t\" problem\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"FONT\", \"INTERNAL_PROBLEM\", (char *)NULL);\n\treturn NULL;\n    }\n\n    fontPtr->resourceRefCount = 1;\n    fontPtr->objRefCount = 1;\n    fontPtr->cacheHashPtr = cacheHashPtr;\n    fontPtr->namedHashPtr = namedHashPtr;\n    fontPtr->screen = Tk_Screen(tkwin);\n    fontPtr->colormap = Tk_Colormap(tkwin);\n    fontPtr->visual = Tk_Visual(tkwin);\n    fontPtr->nextPtr = firstFontPtr;\n    Tcl_SetHashValue(cacheHashPtr, fontPtr);\n\n    Tk_MeasureChars((Tk_Font) fontPtr, \"0\", 1, -1, 0, &fontPtr->tabWidth);\n    if (fontPtr->tabWidth == 0) {\n\tfontPtr->tabWidth = fontPtr->fm.maxWidth;\n    }\n    fontPtr->tabWidth *= 8;\n\n    /*\n     * Make sure the tab width isn't zero (some fonts may not have enough\n     * information to set a reasonable tab width).\n     */\n\n    if (fontPtr->tabWidth == 0) {\n\tfontPtr->tabWidth = 1;\n    }\n\n    /*\n     * Get information used for drawing underlines in generic code on a\n     * non-underlined font.\n     */\n\n    descent = fontPtr->fm.descent;\n    fontPtr->underlinePos = descent / 2;\n    fontPtr->underlineHeight = (int) (TkFontGetPixels(tkwin, fontPtr->fa.size) / 10 + 0.5);\n    if (fontPtr->underlineHeight == 0) {\n\tfontPtr->underlineHeight = 1;\n    }\n    if (fontPtr->underlinePos + fontPtr->underlineHeight > descent) {\n\t/*\n\t * If this set of values would cause the bottom of the underline bar\n\t * to stick below the descent of the font, jack the underline up a bit\n\t * higher.\n\t */\n\n\tfontPtr->underlineHeight = descent - fontPtr->underlinePos;\n\tif (fontPtr->underlineHeight == 0) {\n\t    fontPtr->underlinePos--;\n\t    fontPtr->underlineHeight = 1;\n\t}\n    }\n\n    objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;\n    objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;\n    return (Tk_Font) fontPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetFontFromObj --\n *\n *\tFind the font that corresponds to a given object. The font must have\n *\talready been created by Tk_GetFont or Tk_AllocFontFromObj.\n *\n * Results:\n *\tThe return value is a token for the font that matches objPtr and is\n *\tsuitable for use in tkwin.\n *\n * Side effects:\n *\tIf the object is not already a font ref, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Font\nTk_GetFontFromObj(\n    Tk_Window tkwin,\t\t/* The window that the font will be used\n\t\t\t\t * in. */\n    Tcl_Obj *objPtr)\t\t/* The object from which to get the font. */\n{\n    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;\n    TkFont *fontPtr;\n    Tcl_HashEntry *hashPtr;\n\n    if (objPtr->typePtr != &tkFontObjType\n\t    || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {\n\tSetFontFromAny(NULL, objPtr);\n    }\n\n    fontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;\n    if (fontPtr != NULL) {\n\tif (fontPtr->resourceRefCount == 0) {\n\t    /*\n\t     * This is a stale reference: it refers to a TkFont that's no\n\t     * longer in use. Clear the reference.\n\t     */\n\n\t    FreeFontObj(objPtr);\n\t    fontPtr = NULL;\n\t} else if (Tk_Screen(tkwin) == fontPtr->screen\n#ifdef HAVE_XFT\n\t\t&& Tk_Colormap(tkwin) == fontPtr->colormap\n\t\t&& Tk_Visual(tkwin) == fontPtr->visual\n#endif\n\t    ) {\n\t    return (Tk_Font) fontPtr;\n\t}\n    }\n\n    /*\n     * Next, search the list of fonts that have the name we want, to see if\n     * one of them is for the right screen.\n     */\n\n    if (fontPtr != NULL) {\n\thashPtr = fontPtr->cacheHashPtr;\n\tFreeFontObj(objPtr);\n    } else {\n\thashPtr = Tcl_FindHashEntry(&fiPtr->fontCache, Tcl_GetString(objPtr));\n    }\n    if (hashPtr != NULL) {\n\tfor (fontPtr = (TkFont *)Tcl_GetHashValue(hashPtr); fontPtr != NULL;\n\t\tfontPtr = fontPtr->nextPtr) {\n\t    if (Tk_Screen(tkwin) == fontPtr->screen\n#ifdef HAVE_XFT\n\t\t&& Tk_Colormap(tkwin) == fontPtr->colormap\n\t\t&& Tk_Visual(tkwin) == fontPtr->visual\n#endif\n\t    ) {\n\t\tfontPtr->objRefCount++;\n\t\tobjPtr->internalRep.twoPtrValue.ptr1 = fontPtr;\n\t\tobjPtr->internalRep.twoPtrValue.ptr2 = fiPtr;\n\t\treturn (Tk_Font) fontPtr;\n\t    }\n\t}\n    }\n\n    Tcl_Panic(\"Tk_GetFontFromObj called with non-existent font!\");\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetFontFromAny --\n *\n *\tConvert the internal representation of a Tcl object to the font\n *\tinternal form.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tThe object is left with its typePtr pointing to tkFontObjType. The\n *\tTkFont pointer is NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetFontFromAny(\n    TCL_UNUSED(Tcl_Interp *),\t/* Used for error reporting if not NULL. */\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n    objPtr->typePtr = &tkFontObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    objPtr->internalRep.twoPtrValue.ptr2 = NULL;\n\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_NameOfFont --\n *\n *\tGiven a font, return a textual string identifying it.\n *\n * Results:\n *\tThe return value is the description that was passed to Tk_GetFont() to\n *\tcreate the font. The storage for the returned string is only\n *\tguaranteed to persist until the font is deleted. The caller should not\n *\tmodify this string.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfFont(\n    Tk_Font tkfont)\t\t/* Font whose name is desired. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n\n    return fontPtr->cacheHashPtr->key.string;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FreeFont --\n *\n *\tCalled to release a font allocated by Tk_GetFont().\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with font is decremented, and only\n *\tdeallocated when no one is using it.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_FreeFont(\n    Tk_Font tkfont)\t\t/* Font to be released. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont, *prevPtr;\n    NamedFont *nfPtr;\n\n    if (fontPtr == NULL) {\n\treturn;\n    }\n    if (fontPtr->resourceRefCount-- > 1) {\n\treturn;\n    }\n    if (fontPtr->namedHashPtr != NULL) {\n\t/*\n\t * This font derived from a named font. Reduce the reference count on\n\t * the named font and free it if no-one else is using it.\n\t */\n\n\tnfPtr = (NamedFont *)Tcl_GetHashValue(fontPtr->namedHashPtr);\n\tif ((nfPtr->refCount-- <= 1) && nfPtr->deletePending) {\n\t    Tcl_DeleteHashEntry(fontPtr->namedHashPtr);\n\t    Tcl_Free(nfPtr);\n\t}\n    }\n\n    prevPtr = (TkFont *)Tcl_GetHashValue(fontPtr->cacheHashPtr);\n    if (prevPtr == fontPtr) {\n\tif (fontPtr->nextPtr == NULL) {\n\t    Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);\n\t} else {\n\t    Tcl_SetHashValue(fontPtr->cacheHashPtr, fontPtr->nextPtr);\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != fontPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t}\n\tprevPtr->nextPtr = fontPtr->nextPtr;\n    }\n\n    TkpDeleteFont(fontPtr);\n    if (fontPtr->objRefCount == 0) {\n\tTcl_Free(fontPtr);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FreeFontFromObj --\n *\n *\tCalled to release a font inside a Tcl_Obj *. Decrements the refCount\n *\tof the font and removes it from the hash tables if necessary.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with font is decremented, and only\n *\tdeallocated when no one is using it.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_FreeFontFromObj(\n    Tk_Window tkwin,\t\t/* The window this font lives in. Needed for\n\t\t\t\t * the screen value. */\n    Tcl_Obj *objPtr)\t\t/* The Tcl_Obj * to be freed. */\n{\n    Tk_FreeFont(Tk_GetFontFromObj(tkwin, objPtr));\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeFontObjProc, FreeFontObj --\n *\n *\tThis proc is called to release an object reference to a font. Called\n *\twhen the object's internal rep is released or when the cached fontPtr\n *\tneeds to be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object reference count is decremented. When both it and the hash\n *\tref count go to zero, the font's resources are released.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeFontObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    FreeFontObj(objPtr);\n    objPtr->typePtr = NULL;\n}\n\nstatic void\nFreeFontObj(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    TkFont *fontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;\n\n    if (fontPtr != NULL) {\n\tif ((fontPtr->objRefCount-- <= 1) && (fontPtr->resourceRefCount == 0)) {\n\t    Tcl_Free(fontPtr);\n\t}\n\tobjPtr->internalRep.twoPtrValue.ptr1 = NULL;\n\tobjPtr->internalRep.twoPtrValue.ptr2 = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupFontObjProc --\n *\n *\tWhen a cached font object is duplicated, this is called to update the\n *\tinternal reps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe font's objRefCount is incremented and the internal rep of the copy\n *\tis set to point to it.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupFontObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    TkFont *fontPtr = (TkFont *)srcObjPtr->internalRep.twoPtrValue.ptr1;\n\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 = fontPtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr2\n\t    = srcObjPtr->internalRep.twoPtrValue.ptr2;\n\n    if (fontPtr != NULL) {\n\tfontPtr->objRefCount++;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FontId --\n *\n *\tGiven a font, return an opaque handle that should be selected into the\n *\tXGCValues structure in order to get the constructed gc to use this\n *\tfont. This function would go away if the XGCValues structure were\n *\treplaced with a TkGCValues structure.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nFont\nTk_FontId(\n    Tk_Font tkfont)\t\t/* Font that is going to be selected into\n\t\t\t\t * GC. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n\n    return fontPtr->fid;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetFontMetrics --\n *\n *\tReturns overall ascent and descent metrics for the given font. These\n *\tvalues can be used to space multiple lines of text and to align the\n *\tbaselines of text in different fonts.\n *\n * Results:\n *\tIf *heightPtr is non-NULL, it is filled with the overall height of the\n *\tfont, which is the sum of the ascent and descent. If *ascentPtr or\n *\t*descentPtr is non-NULL, they are filled with the ascent and/or\n *\tdescent information for the font.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_GetFontMetrics(\n    Tk_Font tkfont,\t\t/* Font in which metrics are calculated. */\n    Tk_FontMetrics *fmPtr)\t/* Pointer to structure in which font metrics\n\t\t\t\t * for tkfont will be stored. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n\n    fmPtr->ascent = fontPtr->fm.ascent;\n    fmPtr->descent = fontPtr->fm.descent;\n    fmPtr->linespace = fontPtr->fm.ascent + fontPtr->fm.descent;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_PostscriptFontName --\n *\n *\tGiven a Tk_Font, return the name of the corresponding Postscript font.\n *\n * Results:\n *\tThe return value is the pointsize of the given Tk_Font. The name of\n *\tthe Postscript font is appended to dsPtr.\n *\n * Side effects:\n *\tIf the font does not exist on the printer, the print job will fail at\n *\tprint time. Given a \"reasonable\" Postscript printer, the following\n *\tTk_Font font families should print correctly:\n *\n *\t    Avant Garde, Arial, Bookman, Courier, Courier New, Geneva,\n *\t    Helvetica, Monaco, New Century Schoolbook, New York,\n *\t    Palatino, Symbol, Times, Times New Roman, Zapf Chancery,\n *\t    and Zapf Dingbats.\n *\n *\tAny other Tk_Font font families may not print correctly because the\n *\tcomputed Postscript font name may be incorrect.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_PostscriptFontName(\n    Tk_Font tkfont,\t\t/* Font in which text will be printed. */\n    Tcl_DString *dsPtr)\t\t/* Pointer to an initialized Tcl_DString to\n\t\t\t\t * which the name of the Postscript font that\n\t\t\t\t * corresponds to tkfont will be appended. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n    Tk_Uid family, weightString, slantString;\n    char *src, *dest;\n    Tcl_Size len;\n    int upper;\n\n    len = Tcl_DStringLength(dsPtr);\n\n    /*\n     * Convert the case-insensitive Tk_Font family name to the case-sensitive\n     * Postscript family name. Take out any spaces and capitalize the first\n     * letter of each word.\n     */\n\n    family = fontPtr->fa.family;\n    if (strncasecmp(family, \"itc \", 4) == 0) {\n\tfamily = family + 4;\n    }\n    if ((strcasecmp(family, \"Arial\") == 0)\n\t    || (strcasecmp(family, \"Geneva\") == 0)) {\n\tfamily = \"Helvetica\";\n    } else if ((strcasecmp(family, \"Times New Roman\") == 0)\n\t    || (strcasecmp(family, \"New York\") == 0)) {\n\tfamily = \"Times\";\n    } else if ((strcasecmp(family, \"Courier New\") == 0)\n\t    || (strcasecmp(family, \"Monaco\") == 0)) {\n\tfamily = \"Courier\";\n    } else if (strcasecmp(family, \"AvantGarde\") == 0) {\n\tfamily = \"AvantGarde\";\n    } else if (strcasecmp(family, \"ZapfChancery\") == 0) {\n\tfamily = \"ZapfChancery\";\n    } else if (strcasecmp(family, \"ZapfDingbats\") == 0) {\n\tfamily = \"ZapfDingbats\";\n    } else {\n\tint ch;\n\n\t/*\n\t * Inline, capitalize the first letter of each word, lowercase the\n\t * rest of the letters in each word, and then take out the spaces\n\t * between the words. This may make the DString shorter, which is safe\n\t * to do.\n\t */\n\n\tTcl_DStringAppend(dsPtr, family, TCL_INDEX_NONE);\n\n\tsrc = dest = Tcl_DStringValue(dsPtr) + len;\n\tupper = 1;\n\tfor (; *src != '\\0'; ) {\n\t    while (isspace(UCHAR(*src))) { /* INTL: ISO space */\n\t\tsrc++;\n\t\tupper = 1;\n\t    }\n\t    src += Tcl_UtfToUniChar(src, &ch);\n\t    if (upper) {\n\t\tch = Tcl_UniCharToUpper(ch);\n\t\tupper = 0;\n\t    } else {\n\t\tch = Tcl_UniCharToLower(ch);\n\t    }\n\t    dest += Tcl_UniCharToUtf(ch, dest);\n\t}\n\t*dest = '\\0';\n\tTcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr));\n\tfamily = Tcl_DStringValue(dsPtr) + len;\n    }\n    if (family != Tcl_DStringValue(dsPtr) + len) {\n\tTcl_DStringAppend(dsPtr, family, TCL_INDEX_NONE);\n\tfamily = Tcl_DStringValue(dsPtr) + len;\n    }\n\n    if (strcasecmp(family, \"NewCenturySchoolbook\") == 0) {\n\tTcl_DStringSetLength(dsPtr, len);\n\tTcl_DStringAppend(dsPtr, \"NewCenturySchlbk\", TCL_INDEX_NONE);\n\tfamily = Tcl_DStringValue(dsPtr) + len;\n    }\n\n    /*\n     * Get the string to use for the weight.\n     */\n\n    weightString = NULL;\n    if (fontPtr->fa.weight == TK_FW_NORMAL) {\n\tif (strcmp(family, \"Bookman\") == 0) {\n\t    weightString = \"Light\";\n\t} else if (strcmp(family, \"AvantGarde\") == 0) {\n\t    weightString = \"Book\";\n\t} else if (strcmp(family, \"ZapfChancery\") == 0) {\n\t    weightString = \"Medium\";\n\t}\n    } else {\n\tif ((strcmp(family, \"Bookman\") == 0)\n\t\t|| (strcmp(family, \"AvantGarde\") == 0)) {\n\t    weightString = \"Demi\";\n\t} else {\n\t    weightString = \"Bold\";\n\t}\n    }\n\n    /*\n     * Get the string to use for the slant.\n     */\n\n    slantString = NULL;\n    if (fontPtr->fa.slant == TK_FS_ROMAN) {\n\t/* Do nothing */\n    } else if ((strcmp(family, \"Helvetica\") == 0)\n\t    || (strcmp(family, \"Courier\") == 0)\n\t    || (strcmp(family, \"AvantGarde\") == 0)) {\n\tslantString = \"Oblique\";\n    } else {\n\tslantString = \"Italic\";\n    }\n\n    /*\n     * The string \"Roman\" needs to be added to some fonts that are not bold\n     * and not italic.\n     */\n\n    if ((slantString == NULL) && (weightString == NULL)) {\n\tif ((strcmp(family, \"Times\") == 0)\n\t\t|| (strcmp(family, \"NewCenturySchlbk\") == 0)\n\t\t|| (strcmp(family, \"Palatino\") == 0)) {\n\t    Tcl_DStringAppend(dsPtr, \"-Roman\", TCL_INDEX_NONE);\n\t}\n    } else {\n\tTcl_DStringAppend(dsPtr, \"-\", TCL_INDEX_NONE);\n\tif (weightString != NULL) {\n\t    Tcl_DStringAppend(dsPtr, weightString, TCL_INDEX_NONE);\n\t}\n\tif (slantString != NULL) {\n\t    Tcl_DStringAppend(dsPtr, slantString, TCL_INDEX_NONE);\n\t}\n    }\n\n    return (int)(fontPtr->fa.size + 0.5);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_TextWidth --\n *\n *\tA wrapper function for the more complicated interface of\n *\tTk_MeasureChars. Computes how much space the given simple string\n *\tneeds.\n *\n * Results:\n *\tThe return value is the width (in pixels) of the given string.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_TextWidth(\n    Tk_Font tkfont,\t\t/* Font in which text will be measured. */\n    const char *string,\t\t/* String whose width will be computed. */\n    Tcl_Size numBytes)\t\t/* Number of bytes to consider from string, or\n\t\t\t\t * TCL_INDEX_NONE for strlen(). */\n{\n    int width;\n\n    if (numBytes < 0) {\n\tnumBytes = (Tcl_Size)strlen(string);\n    }\n    Tk_MeasureChars(tkfont, string, numBytes, -1, 0, &width);\n    return width;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_UnderlineChars, Tk_UnderlineCharsInContext --\n *\n *\tThese procedures draw an underline for a given range of characters in\n *\ta given string. They don't draw the characters (which are assumed to\n *\thave been displayed previously); they just draw the underline. These\n *\tprocedures would mainly be used to quickly underline a few characters\n *\twithout having to construct an underlined font. To produce properly\n *\tunderlined text, the appropriate underlined font should be constructed\n *\tand used.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets displayed in \"drawable\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UnderlineChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for actually drawing\n\t\t\t\t * line. */\n    Tk_Font tkfont,\t\t/* Font used in GC; must have been allocated\n\t\t\t\t * by Tk_GetFont(). Used for character\n\t\t\t\t * dimensions, etc. */\n    const char *string,\t\t/* String containing characters to be\n\t\t\t\t * underlined or overstruck. */\n    int x, int y,\t\t/* Coordinates at which first character of\n\t\t\t\t * string is drawn. */\n    Tcl_Size firstByte,\t\t/* Index of first byte of first character. */\n    Tcl_Size lastByte)\t\t/* Index of first byte after the last\n\t\t\t\t * character. */\n{\n    Tk_UnderlineCharsInContext(display, drawable, gc, tkfont, string,\n\t    lastByte, x, y, firstByte, lastByte);\n}\n\nvoid\nTk_UnderlineCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for actually drawing\n\t\t\t\t * line. */\n    Tk_Font tkfont,\t\t/* Font used in GC; must have been allocated\n\t\t\t\t * by Tk_GetFont(). Used for character\n\t\t\t\t * dimensions, etc. */\n    const char *string,\t\t/* String containing characters to be\n\t\t\t\t * underlined or overstruck. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int x, int y,\t\t/* Coordinates at which the first character of\n\t\t\t\t * the whole string would be drawn. */\n    Tcl_Size firstByte,\t\t/* Index of first byte of first character. */\n    Tcl_Size lastByte)\t\t/* Index of first byte after the last\n\t\t\t\t * character. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n    int startX, endX;\n\n    Tk_MeasureCharsInContext(tkfont, string, numBytes, 0, firstByte, -1, 0,\n\t    &startX);\n    Tk_MeasureCharsInContext(tkfont, string, numBytes, 0, lastByte, -1, 0,\n\t    &endX);\n\n    XFillRectangle(display, drawable, gc, x + startX,\n\t    y + fontPtr->underlinePos, (unsigned) (endX - startX),\n\t    (unsigned) fontPtr->underlineHeight);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_ComputeTextLayout --\n *\n *\tComputes the amount of screen space needed to display a multi-line,\n *\tjustified string of text. Records all the measurements that were done\n *\tto determine to size and positioning of the individual lines of text;\n *\tthis information can be used by the Tk_DrawTextLayout() function to\n *\tdisplay the text quickly (without remeasuring it).\n *\n *\tThis function is useful for simple widgets that want to display\n *\tsingle-font, multi-line text and want Tk to handle the details.\n *\n * Results:\n *\tThe return value is a Tk_TextLayout token that holds the measurement\n *\tinformation for the given string. The token is only valid for the\n *\tgiven string. If the string is freed, the token is no longer valid and\n *\tmust also be freed. To free the token, call Tk_FreeTextLayout().\n *\n *\tThe dimensions of the screen area needed to display the text are\n *\tstored in *widthPtr and *heightPtr.\n *\n * Side effects:\n *\tMemory is allocated to hold the measurement information.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_TextLayout\nTk_ComputeTextLayout(\n    Tk_Font tkfont,\t\t/* Font that will be used to display text. */\n    const char *string,\t\t/* String whose dimensions are to be\n\t\t\t\t * computed. */\n    Tcl_Size numChars,\t\t/* Number of characters to consider from\n\t\t\t\t * string, or TCL_INDEX_NONE for strlen(). */\n    int wrapLength,\t\t/* Longest permissible line length, in pixels.\n\t\t\t\t * <= 0 means no automatic wrapping: just let\n\t\t\t\t * lines get as long as needed. */\n    Tk_Justify justify,\t\t/* How to justify lines. */\n    int flags,\t\t\t/* Flag bits OR-ed together. TK_IGNORE_TABS\n\t\t\t\t * means that tab characters should not be\n\t\t\t\t * expanded. TK_IGNORE_NEWLINES means that\n\t\t\t\t * newline characters should not cause a line\n\t\t\t\t * break. */\n    int *widthPtr,\t\t/* Filled with width of string. */\n    int *heightPtr)\t\t/* Filled with height of string. */\n{\n    TkFont *fontPtr = (TkFont *) tkfont;\n    const char *start, *endp, *special;\n    Tcl_Size n, maxChunks, bytesThisChunk;\n    int y, curLine, layoutHeight;\n    int baseline, height, curX, newX, maxWidth, *lineLengths;\n    TextLayout *layoutPtr;\n    LayoutChunk *chunkPtr;\n    const TkFontMetrics *fmPtr;\n    Tcl_DString lineBuffer;\n\n    Tcl_DStringInit(&lineBuffer);\n\n    if ((fontPtr == NULL) || (string == NULL)) {\n\tif (widthPtr != NULL) {\n\t    *widthPtr = 0;\n\t}\n\tif (heightPtr != NULL) {\n\t    *heightPtr = 0;\n\t}\n\treturn NULL;\n    }\n\n    fmPtr = &fontPtr->fm;\n\n    height = fmPtr->ascent + fmPtr->descent;\n\n    if (numChars < 0) {\n\tnumChars = Tcl_NumUtfChars(string, TCL_INDEX_NONE);\n    }\n    if (wrapLength == 0) {\n\twrapLength = -1;\n    }\n\n    maxChunks = 1;\n\n    layoutPtr = (TextLayout *)Tcl_Alloc(offsetof(TextLayout, chunks)\n\t    + (size_t)maxChunks * sizeof(LayoutChunk));\n    layoutPtr->tkfont = tkfont;\n    layoutPtr->string = string;\n    layoutPtr->numChunks = 0;\n\n    baseline = fmPtr->ascent;\n    maxWidth = 0;\n\n    /*\n     * Divide the string up into simple strings and measure each string.\n     */\n\n    curX = 0;\n\n    endp = Tcl_UtfAtIndex(string, numChars);\n    special = string;\n\n    flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES;\n    flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE;\n    for (start = string; start < endp; ) {\n\tif (start >= special) {\n\t    /*\n\t     * Find the next special character in the string.\n\t     *\n\t     * INTL: Note that it is safe to increment by byte, because we are\n\t     * looking for 7-bit characters that will appear unchanged in\n\t     * UTF-8. At some point we may need to support the full Unicode\n\t     * whitespace set.\n\t     */\n\n\t    for (special = start; special < endp; special++) {\n\t\tif (!(flags & TK_IGNORE_NEWLINES)) {\n\t\t    if ((*special == '\\n') || (*special == '\\r')) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tif (!(flags & TK_IGNORE_TABS)) {\n\t\t    if (*special == '\\t') {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Special points at the next special character (or the end of the\n\t * string). Process characters between start and special.\n\t */\n\n\tchunkPtr = NULL;\n\tif (start < special) {\n\t    bytesThisChunk = Tk_MeasureChars(tkfont, start, special - start,\n\t\t    wrapLength - curX, flags, &newX);\n\t    newX += curX;\n\t    flags &= ~TK_AT_LEAST_ONE;\n\t    if (bytesThisChunk > 0) {\n\t\tchunkPtr = NewChunk(&layoutPtr, &maxChunks, start,\n\t\t\tbytesThisChunk, curX, newX, baseline);\n\n\t\tstart += bytesThisChunk;\n\t\tcurX = newX;\n\t    }\n\t}\n\n\tif ((start == special) && (special < endp)) {\n\t    /*\n\t     * Handle the special character.\n\t     *\n\t     * INTL: Special will be pointing at a 7-bit character so we can\n\t     * safely treat it as a single byte.\n\t     */\n\n\t    chunkPtr = NULL;\n\t    if (*special == '\\t') {\n\t\tnewX = curX + fontPtr->tabWidth;\n\t\tnewX -= newX % fontPtr->tabWidth;\n\t\tNewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX,\n\t\t\tbaseline)->numDisplayChars = -1;\n\t\tstart++;\n\t\tcurX = newX;\n\t\tflags &= ~TK_AT_LEAST_ONE;\n\t\tif ((start < endp) &&\n\t\t\t((wrapLength <= 0) || (newX <= wrapLength))) {\n\t\t    /*\n\t\t     * More chars can still fit on this line.\n\t\t     */\n\n\t\t    continue;\n\t\t}\n\t    } else {\n\t\tNewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX,\n\t\t\tbaseline)->numDisplayChars = -1;\n\t\tstart++;\n\t\tgoto wrapLine;\n\t    }\n\t}\n\n\t/*\n\t * No more characters are going to go on this line, either because no\n\t * more characters can fit or there are no more characters left.\n\t * Consume all extra spaces at end of line.\n\t */\n\n\twhile ((start < endp) && isspace(UCHAR(*start))) { /* INTL: ISO space */\n\t    if (!(flags & TK_IGNORE_NEWLINES)) {\n\t\tif ((*start == '\\n') || (*start == '\\r')) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (!(flags & TK_IGNORE_TABS)) {\n\t\tif (*start == '\\t') {\n\t\t    break;\n\t\t}\n\t    }\n\t    start++;\n\t}\n\tif (chunkPtr != NULL) {\n\t    const char *end;\n\n\t    /*\n\t     * Append all the extra spaces on this line to the end of the last\n\t     * text chunk. This is a little tricky because we are switching\n\t     * back and forth between characters and bytes.\n\t     */\n\n\t    end = chunkPtr->start + chunkPtr->numBytes;\n\t    bytesThisChunk = start - end;\n\t    if (bytesThisChunk > 0) {\n\t\tbytesThisChunk = Tk_MeasureChars(tkfont, end, bytesThisChunk,\n\t\t\t-1, 0, &chunkPtr->totalWidth);\n\t\tchunkPtr->numBytes += bytesThisChunk;\n\t\tchunkPtr->numChars += Tcl_NumUtfChars(end, bytesThisChunk);\n\t\tchunkPtr->totalWidth += curX;\n\t    }\n\t}\n\n    wrapLine:\n\tflags |= TK_AT_LEAST_ONE;\n\n\t/*\n\t * Save current line length, then move current position to start of\n\t * next line.\n\t */\n\n\tif (curX > maxWidth) {\n\t    maxWidth = curX;\n\t}\n\n\t/*\n\t * Remember width of this line, so that all chunks on this line can be\n\t * centered or right justified, if necessary.\n\t */\n\n\tTcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));\n\n\tcurX = 0;\n\tbaseline += height;\n    }\n\n    /*\n     * If last line ends with a newline, then we need to make a 0 width chunk\n     * on the next line. Otherwise \"Hello\" and \"Hello\\n\" are the same height.\n     */\n\n    if ((layoutPtr->numChunks > 0) && !(flags & TK_IGNORE_NEWLINES)) {\n\tif (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\\n') {\n\t    chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX,\n\t\t    curX, baseline);\n\t    chunkPtr->numDisplayChars = -1;\n\t    Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));\n\t    baseline += height;\n\t}\n    }\n\n    layoutPtr->width = maxWidth;\n    layoutHeight = baseline - fmPtr->ascent;\n    if (layoutPtr->numChunks == 0) {\n\tlayoutHeight = height;\n\n\t/*\n\t * This fake chunk is used by the other functions so that they can\n\t * pretend that there is a chunk with no chars in it, which makes the\n\t * coding simpler.\n\t */\n\n\tlayoutPtr->numChunks = 1;\n\tlayoutPtr->chunks[0].start\t\t= string;\n\tlayoutPtr->chunks[0].numBytes\t\t= 0;\n\tlayoutPtr->chunks[0].numChars\t\t= 0;\n\tlayoutPtr->chunks[0].numDisplayChars\t= -1;\n\tlayoutPtr->chunks[0].x\t\t\t= 0;\n\tlayoutPtr->chunks[0].y\t\t\t= fmPtr->ascent;\n\tlayoutPtr->chunks[0].totalWidth\t\t= 0;\n\tlayoutPtr->chunks[0].displayWidth\t= 0;\n    } else {\n\t/*\n\t * Using maximum line length, shift all the chunks so that the lines\n\t * are all justified correctly.\n\t */\n\n\tcurLine = 0;\n\tchunkPtr = layoutPtr->chunks;\n\ty = chunkPtr->y;\n\tlineLengths = (int *) Tcl_DStringValue(&lineBuffer);\n\tfor (n = 0; n < layoutPtr->numChunks; n++) {\n\t    int extra;\n\n\t    if (chunkPtr->y != y) {\n\t\tcurLine++;\n\t\ty = chunkPtr->y;\n\t    }\n\t    extra = maxWidth - lineLengths[curLine];\n\t    if (justify == TK_JUSTIFY_CENTER) {\n\t\tchunkPtr->x += extra / 2;\n\t    } else if (justify == TK_JUSTIFY_RIGHT) {\n\t\tchunkPtr->x += extra;\n\t    }\n\t    chunkPtr++;\n\t}\n    }\n\n    if (widthPtr != NULL) {\n\t*widthPtr = layoutPtr->width;\n    }\n    if (heightPtr != NULL) {\n\t*heightPtr = layoutHeight;\n    }\n    Tcl_DStringFree(&lineBuffer);\n\n    return (Tk_TextLayout) layoutPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FreeTextLayout --\n *\n *\tThis function is called to release the storage associated with a\n *\tTk_TextLayout when it is no longer needed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_FreeTextLayout(\n    Tk_TextLayout textLayout)\t/* The text layout to be released. */\n{\n    TextLayout *layoutPtr = (TextLayout *) textLayout;\n\n    if (layoutPtr != NULL) {\n\tTcl_Free(layoutPtr);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawTextLayout --\n *\n *\tUse the information in the Tk_TextLayout token to display a\n *\tmulti-line, justified string of text.\n *\n *\tThis function is useful for simple widgets that need to display\n *\tsingle-font, multi-line text and want Tk to handle the details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tText drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawTextLayout(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context to use for drawing\n\t\t\t\t * text. */\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner of rectangle in\n\t\t\t\t * which to draw (pixels). */\n    Tcl_Size firstChar,\t\t/* The index of the first character to draw\n\t\t\t\t * from the given text item. 0 specifies the\n\t\t\t\t * beginning. */\n    Tcl_Size lastChar)\t\t/* The index just after the last character to\n\t\t\t\t * draw from the given text item. A number < 0\n\t\t\t\t * means to draw all characters. */\n{\n#if 0\n    /* Use TkDrawAngledTextLayout() implementation - testing purposes at this point */\n    TkDrawAngledTextLayout(display, drawable, gc, layout, x, y, 0.0, firstChar, lastChar);\n#else\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    int i, drawX;\n    Tcl_Size numDisplayChars;\n    const char *firstByte, *lastByte;\n    LayoutChunk *chunkPtr;\n\n    if (layoutPtr == NULL) {\n\treturn;\n    }\n\n    if (lastChar < 0) {\n\tlastChar = 100000000;\n    }\n    chunkPtr = layoutPtr->chunks;\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tnumDisplayChars = chunkPtr->numDisplayChars;\n\tif ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {\n\t    if (firstChar <= 0) {\n\t\tdrawX = 0;\n\t\tfirstChar = 0;\n\t\tfirstByte = chunkPtr->start;\n\t    } else {\n\t\tfirstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);\n\t\tTk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,\n\t\t\tfirstByte - chunkPtr->start, -1, 0, &drawX);\n\t    }\n\t    if (lastChar < numDisplayChars) {\n\t\tnumDisplayChars = lastChar;\n\t    }\n\t    lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);\n#ifdef TK_DRAW_IN_CONTEXT\n\t    Tk_DrawCharsInContext(display, drawable, gc, layoutPtr->tkfont,\n\t\t    chunkPtr->start, chunkPtr->numBytes,\n\t\t    firstByte - chunkPtr->start, lastByte - firstByte,\n\t\t    x+chunkPtr->x, y+chunkPtr->y);\n#else /* !TK_DRAW_IN_CONTEXT */\n\t    Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte,\n\t\t    lastByte - firstByte, x+chunkPtr->x+drawX, y+chunkPtr->y);\n#endif /* TK_DRAW_IN_CONTEXT */\n\t}\n\tfirstChar -= chunkPtr->numChars;\n\tlastChar -= chunkPtr->numChars;\n\tif (lastChar <= 0) {\n\t    break;\n\t}\n\tchunkPtr++;\n    }\n#endif /* Use TkDrawAngledTextLayout() implementation */\n}\n\f\nvoid\nTkDrawAngledTextLayout(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context to use for drawing\n\t\t\t\t * text. */\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner of rectangle in\n\t\t\t\t * which to draw (pixels). */\n    double angle,\n    Tcl_Size firstChar,\t\t/* The index of the first character to draw\n\t\t\t\t * from the given text item. 0 specifies the\n\t\t\t\t * beginning. */\n    Tcl_Size lastChar)\t\t/* The index just after the last character to\n\t\t\t\t * draw from the given text item. A number < 0\n\t\t\t\t * means to draw all characters. */\n{\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    Tcl_Size i, numDisplayChars;\n    int drawX;\n    const char *firstByte, *lastByte;\n    LayoutChunk *chunkPtr;\n    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\n    if (layoutPtr == NULL) {\n\treturn;\n    }\n\n    if (lastChar < 0) {\n\tlastChar = 100000000;\n    }\n    chunkPtr = layoutPtr->chunks;\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tnumDisplayChars = chunkPtr->numDisplayChars;\n\tif ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {\n\t    double dx, dy;\n\n\t    if (firstChar <= 0) {\n\t\tdrawX = 0;\n\t\tfirstChar = 0;\n\t\tfirstByte = chunkPtr->start;\n\t    } else {\n\t\tfirstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);\n\t\tTk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,\n\t\t\tfirstByte - chunkPtr->start, -1, 0, &drawX);\n\t    }\n\t    if (lastChar < numDisplayChars) {\n\t\tnumDisplayChars = lastChar;\n\t    }\n\t    lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);\n#ifdef TK_DRAW_IN_CONTEXT\n\t    dx = cosA * (chunkPtr->x) + sinA * (chunkPtr->y);\n\t    dy = -sinA * (chunkPtr->x) + cosA * (chunkPtr->y);\n\t    if (angle == 0.0) {\n\t\tTk_DrawCharsInContext(display, drawable, gc,\n\t\t\tlayoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes,\n\t\t\tfirstByte - chunkPtr->start, lastByte - firstByte,\n\t\t\t(int)(x + dx), (int)(y + dy));\n\t    } else {\n\t\tTkpDrawAngledCharsInContext(display, drawable, gc,\n\t\t\tlayoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes,\n\t\t\tfirstByte - chunkPtr->start, lastByte - firstByte,\n\t\t\tx+dx, y+dy, angle);\n\t    }\n#else /* !TK_DRAW_IN_CONTEXT */\n\t    dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y);\n\t    dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y);\n\t    if (angle == 0.0) {\n\t\tTk_DrawChars(display, drawable, gc, layoutPtr->tkfont,\n\t\t\tfirstByte, lastByte - firstByte,\n\t\t\t(int)(x + dx), (int)(y + dy));\n\t    } else {\n\t\tTkDrawAngledChars(display, drawable, gc, layoutPtr->tkfont,\n\t\t\tfirstByte, lastByte - firstByte, x+dx, y+dy, angle);\n\t    }\n#endif /* TK_DRAW_IN_CONTEXT */\n\t}\n\tfirstChar -= chunkPtr->numChars;\n\tlastChar -= chunkPtr->numChars;\n\tif (lastChar <= 0) {\n\t    break;\n\t}\n\tchunkPtr++;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_UnderlineTextLayout --\n *\n *\tUse the information in the Tk_TextLayout token to display an underline\n *\tbelow an individual character. This function does not draw the text,\n *\tjust the underline.\n *\n *\tThis function is useful for simple widgets that need to display\n *\tsingle-font, multi-line text with an individual character underlined\n *\tand want Tk to handle the details. To display larger amounts of\n *\tunderlined text, construct and use an underlined font.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUnderline drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_UnderlineTextLayout(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context to use for drawing text. */\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner of rectangle in\n\t\t\t\t * which to draw (pixels). */\n    int underline)\t\t/* Index of the single character to underline,\n\t\t\t\t * or INT_MIN for no underline. */\n{\n    int xx, yy, width, height;\n\n    if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)\n\t    && (width != 0)) {\n\tTextLayout *layoutPtr = (TextLayout *) layout;\n\tTkFont *fontPtr = (TkFont *) layoutPtr->tkfont;\n\n\tXFillRectangle(display, drawable, gc, x + xx,\n\t\ty + yy + fontPtr->fm.ascent + fontPtr->underlinePos,\n\t\t(unsigned) width, (unsigned) fontPtr->underlineHeight);\n    }\n}\n\f\nvoid\nTkUnderlineAngledTextLayout(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context to use for drawing\n\t\t\t\t * text. */\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner of rectangle in\n\t\t\t\t * which to draw (pixels). */\n    double angle,\n    int underline)\t\t/* Index of the single character to underline,\n\t\t\t\t * or INT_MIN for no underline. */\n{\n    int xx, yy, width, height;\n\n    if (angle == 0.0) {\n\tTk_UnderlineTextLayout(display, drawable, gc, layout, x,y, underline);\n\treturn;\n    }\n\n    if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)\n\t    && (width != 0)) {\n\tTextLayout *layoutPtr = (TextLayout *) layout;\n\tTkFont *fontPtr = (TkFont *) layoutPtr->tkfont;\n\tdouble sinA = sin(angle*PI/180), cosA = cos(angle*PI/180);\n\tdouble dy = yy + fontPtr->fm.ascent + fontPtr->underlinePos;\n\tXPoint points[5];\n\n\t/*\n\t * Note that we're careful to only round a double value once, which\n\t * minimizes roundoff errors.\n\t */\n\n\tpoints[0].x = (short)(x + ROUND16(xx*cosA + dy*sinA));\n\tpoints[0].y = (short)(y + ROUND16(dy*cosA - xx*sinA));\n\tpoints[1].x = (short)(x + ROUND16(xx*cosA + dy*sinA + width*cosA));\n\tpoints[1].y = (short)(y + ROUND16(dy*cosA - xx*sinA - width*sinA));\n\tif (fontPtr->underlineHeight == 1) {\n\t    /*\n\t     * Thin underlines look better when rotated when drawn as a line\n\t     * rather than a rectangle; the rasterizer copes better.\n\t     */\n\n\t    XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);\n\t} else {\n\t    points[2].x = (short)(x + ROUND16(xx*cosA + dy*sinA + width*cosA\n\t\t    + fontPtr->underlineHeight*sinA));\n\t    points[2].y = (short)(y + ROUND16(dy*cosA - xx*sinA - width*sinA\n\t\t    + fontPtr->underlineHeight*cosA));\n\t    points[3].x = (short)(x + ROUND16(xx*cosA + dy*sinA\n\t\t    + fontPtr->underlineHeight*sinA));\n\t    points[3].y = (short)(y + ROUND16(dy*cosA - xx*sinA\n\t\t    + fontPtr->underlineHeight*cosA));\n\t    points[4].x = points[0].x;\n\t    points[4].y = points[0].y;\n\t    XFillPolygon(display, drawable, gc, points, 5, Complex,\n\t\t    CoordModeOrigin);\n\t    XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);\n\t}\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_PointToChar --\n *\n *\tUse the information in the Tk_TextLayout token to determine the\n *\tcharacter closest to the given point. The point must be specified with\n *\trespect to the upper-left hand corner of the text layout, which is\n *\tconsidered to be located at (0, 0).\n *\n *\tAny point whose y-value is less that 0 will be considered closest to\n *\tthe first character in the text layout; any point whose y-value is\n *\tgreater than the height of the text layout will be considered closest\n *\tto the last character in the text layout.\n *\n *\tAny point whose x-value is less than 0 will be considered closest to\n *\tthe first character on that line; any point whose x-value is greater\n *\tthan the width of the text layout will be considered closest to the\n *\tlast character on that line.\n *\n * Results:\n *\tThe return value is the index of the character that was closest to the\n *\tpoint. Given a text layout with no characters, the value 0 will always\n *\tbe returned, referring to a hypothetical zero-width placeholder\n *\tcharacter.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Size\nTk_PointToChar(\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y)\t\t/* Coordinates of point to check, with respect\n\t\t\t\t * to the upper-left corner of the text\n\t\t\t\t * layout. */\n{\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    LayoutChunk *chunkPtr, *lastPtr;\n    TkFont *fontPtr;\n    Tcl_Size i, n, numChars, pos;\n    int dummy, baseline;\n\n    if (y < 0) {\n\t/*\n\t * Point lies above any line in this layout. Return the index of the\n\t * first char.\n\t */\n\n\treturn 0;\n    }\n\n    /*\n     * Find which line contains the point.\n     */\n\n    fontPtr = (TkFont *) layoutPtr->tkfont;\n    lastPtr = chunkPtr = layoutPtr->chunks;\n    numChars = 0;\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tbaseline = chunkPtr->y;\n\tif (y < baseline + fontPtr->fm.descent) {\n\t    if (x < chunkPtr->x) {\n\t\t/*\n\t\t * Point is to the left of all chunks on this line. Return the\n\t\t * index of the first character on this line.\n\t\t */\n\n\t\treturn numChars;\n\t    }\n\t    if (x >= layoutPtr->width) {\n\t\t/*\n\t\t * If point lies off right side of the text layout, return the\n\t\t * last char in the last chunk on this line. Without this, it\n\t\t * might return the index of the first char that was located\n\t\t * outside of the text layout.\n\t\t */\n\n\t\tx = INT_MAX;\n\t    }\n\n\t    /*\n\t     * Examine all chunks on this line to see which one contains the\n\t     * specified point.\n\t     */\n\n\t    lastPtr = chunkPtr;\n\t    while ((i < layoutPtr->numChunks) && (chunkPtr->y == baseline)) {\n\t\tif (x < chunkPtr->x + chunkPtr->totalWidth) {\n\t\t    /*\n\t\t     * Point falls on one of the characters in this chunk.\n\t\t     */\n\n\t\t    if (chunkPtr->numDisplayChars < 0) {\n\t\t\t/*\n\t\t\t * This is a special chunk that encapsulates a single\n\t\t\t * tab or newline char.\n\t\t\t */\n\n\t\t\treturn numChars;\n\t\t    }\n\t\t    n = Tk_MeasureChars((Tk_Font) fontPtr, chunkPtr->start,\n\t\t\t    chunkPtr->numBytes, x - chunkPtr->x, 0, &dummy);\n\t\t    return numChars + Tcl_NumUtfChars(chunkPtr->start, n);\n\t\t}\n\t\tnumChars += chunkPtr->numChars;\n\t\tlastPtr = chunkPtr;\n\t\tchunkPtr++;\n\t\ti++;\n\t    }\n\n\t    /*\n\t     * Point is to the right of all chars in all the chunks on this\n\t     * line. Return the index just past the last char in the last\n\t     * chunk on this line.\n\t     */\n\n\t    pos = numChars;\n\t    if (i < layoutPtr->numChunks) {\n\t\tpos--;\n\t    }\n\t    return pos;\n\t}\n\tnumChars += chunkPtr->numChars;\n\tlastPtr = chunkPtr;\n\tchunkPtr++;\n    }\n\n    /*\n     * Point lies below any line in this text layout. Return the index just\n     * past the last char.\n     */\n\n    return (lastPtr->start + lastPtr->numChars) - layoutPtr->string;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_CharBbox --\n *\n *\tUse the information in the Tk_TextLayout token to return the bounding\n *\tbox for the character specified by index.\n *\n *\tThe width of the bounding box is the advance width of the character,\n *\tand does not include and left- or right-bearing. Any character that\n *\textends partially outside of the text layout is considered to be\n *\ttruncated at the edge. Any character which is located completely\n *\toutside of the text layout is considered to be zero-width and pegged\n *\tagainst the edge.\n *\n *\tThe height of the bounding box is the line height for this font,\n *\textending from the top of the ascent to the bottom of the descent.\n *\tInformation about the actual height of the individual letter is not\n *\tavailable.\n *\n *\tA text layout that contains no characters is considered to contain a\n *\tsingle zero-width placeholder character.\n *\n * Results:\n *\tThe return value is 0 if the index did not specify a character in the\n *\ttext layout, or non-zero otherwise. In that case, *bbox is filled with\n *\tthe bounding box of the character.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_CharBbox(\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    Tcl_Size index,\t\t\t/* The index of the character whose bbox is\n\t\t\t\t * desired. Negative means count backwards. */\n    int *xPtr, int *yPtr,\t/* Filled with the upper-left hand corner, in\n\t\t\t\t * pixels, of the bounding box for the\n\t\t\t\t * character specified by index, if\n\t\t\t\t * non-NULL. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* Filled with the width and height of the\n\t\t\t\t * bounding box for the character specified by\n\t\t\t\t * index, if non-NULL. */\n{\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    LayoutChunk *chunkPtr = layoutPtr->chunks;\n    int i, x = 0, w;\n    Tk_Font tkfont;\n    TkFont *fontPtr;\n    const char *end;\n\n    if (index < 0) {\n\tfor (i = 0; i < layoutPtr->numChunks; i++) {\n\t    index += (chunkPtr + i)->numChars;\n\t}\n\tif (index < 0) {\n\t    return 0;\n\t}\n    }\n\n    tkfont = layoutPtr->tkfont;\n    fontPtr = (TkFont *) tkfont;\n\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tif (chunkPtr->numDisplayChars < 0) {\n\t    if (index == 0) {\n\t\tx = chunkPtr->x;\n\t\tw = chunkPtr->totalWidth;\n\t\tgoto check;\n\t    }\n\t} else if (index < chunkPtr->numChars) {\n\t    end = Tcl_UtfAtIndex(chunkPtr->start, index);\n\t    if (xPtr != NULL) {\n\t\tTk_MeasureChars(tkfont, chunkPtr->start,\n\t\t\tend - chunkPtr->start, -1, 0, &x);\n\t\tx += chunkPtr->x;\n\t    }\n\t    if (widthPtr != NULL) {\n\t\tint ch;\n\t\tTk_MeasureChars(tkfont, end, Tcl_UtfToUniChar(end, &ch), -1, 0, &w);\n\t    }\n\t    goto check;\n\t}\n\tindex -= chunkPtr->numChars;\n\tchunkPtr++;\n    }\n    if (index != 0) {\n\treturn 0;\n    }\n\n    /*\n     * Special case to get location just past last char in layout.\n     */\n\n    chunkPtr--;\n    x = chunkPtr->x + chunkPtr->totalWidth;\n    w = 0;\n\n    /*\n     * Ensure that the bbox lies within the text layout. This forces all chars\n     * that extend off the right edge of the text layout to have truncated\n     * widths, and all chars that are completely off the right edge of the\n     * text layout to peg to the edge and have 0 width.\n     */\n\n  check:\n    if (yPtr != NULL) {\n\t*yPtr = chunkPtr->y - fontPtr->fm.ascent;\n    }\n    if (heightPtr != NULL) {\n\t*heightPtr = fontPtr->fm.ascent + fontPtr->fm.descent;\n    }\n\n    if (x > layoutPtr->width) {\n\tx = layoutPtr->width;\n    }\n    if (xPtr != NULL) {\n\t*xPtr = x;\n    }\n    if (widthPtr != NULL) {\n\tif (x + w > layoutPtr->width) {\n\t    w = layoutPtr->width - x;\n\t}\n\t*widthPtr = w;\n    }\n\n    return 1;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DistanceToTextLayout --\n *\n *\tComputes the distance in pixels from the given point to the given text\n *\tlayout. Non-displaying space characters that occur at the end of\n *\tindividual lines in the text layout are ignored for hit detection\n *\tpurposes.\n *\n * Results:\n *\tThe return value is 0 if the point (x, y) is inside the text layout.\n *\tIf the point isn't inside the text layout then the return value is the\n *\tdistance in pixels from the point to the text item.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_DistanceToTextLayout(\n    Tk_TextLayout layout,\t/* Layout information, from a previous call\n\t\t\t\t * to Tk_ComputeTextLayout(). */\n    int x, int y)\t\t/* Coordinates of point to check, with respect\n\t\t\t\t * to the upper-left corner of the text layout\n\t\t\t\t * (in pixels). */\n{\n    int i, x1, x2, y1, y2, xDiff, yDiff, dist, minDist, ascent, descent;\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    LayoutChunk *chunkPtr;\n    TkFont *fontPtr;\n\n    fontPtr = (TkFont *) layoutPtr->tkfont;\n    ascent = fontPtr->fm.ascent;\n    descent = fontPtr->fm.descent;\n\n    minDist = 0;\n    chunkPtr = layoutPtr->chunks;\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tif (chunkPtr->start[0] == '\\n') {\n\t    /*\n\t     * Newline characters are not counted when computing distance (but\n\t     * tab characters would still be considered).\n\t     */\n\n\t    chunkPtr++;\n\t    continue;\n\t}\n\n\tx1 = chunkPtr->x;\n\ty1 = chunkPtr->y - ascent;\n\tx2 = chunkPtr->x + chunkPtr->displayWidth;\n\ty2 = chunkPtr->y + descent;\n\n\tif (x < x1) {\n\t    xDiff = x1 - x;\n\t} else if (x >= x2) {\n\t    xDiff = x - x2 + 1;\n\t} else {\n\t    xDiff = 0;\n\t}\n\n\tif (y < y1) {\n\t    yDiff = y1 - y;\n\t} else if (y >= y2) {\n\t    yDiff = y - y2 + 1;\n\t} else {\n\t    yDiff = 0;\n\t}\n\tif ((xDiff == 0) && (yDiff == 0)) {\n\t    return 0;\n\t}\n\tdist = (int) hypot((double) xDiff, (double) yDiff);\n\tif ((dist < minDist) || (minDist == 0)) {\n\t    minDist = dist;\n\t}\n\tchunkPtr++;\n    }\n    return minDist;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_IntersectTextLayout --\n *\n *\tDetermines whether a text layout lies entirely inside, entirely\n *\toutside, or overlaps a given rectangle. Non-displaying space\n *\tcharacters that occur at the end of individual lines in the text\n *\tlayout are ignored for intersection calculations.\n *\n * Results:\n *\tThe return value is -1 if the text layout is entirely outside of the\n *\trectangle, 0 if it overlaps, and 1 if it is entirely inside of the\n *\trectangle.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_IntersectTextLayout(\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner, in pixels, of\n\t\t\t\t * rectangular area to compare with text\n\t\t\t\t * layout. Coordinates are with respect to the\n\t\t\t\t * upper-left hand corner of the text layout\n\t\t\t\t * itself. */\n    int width, int height)\t/* The width and height of the above\n\t\t\t\t * rectangular area, in pixels. */\n{\n    int result, i, x1, y1, x2, y2;\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    LayoutChunk *chunkPtr;\n    TkFont *fontPtr;\n    int left, top, right, bottom;\n\n    /*\n     * Scan the chunks one at a time, seeing whether each is entirely in,\n     * entirely out, or overlapping the rectangle. If an overlap is detected,\n     * return immediately; otherwise wait until all chunks have been processed\n     * and see if they were all inside or all outside.\n     */\n\n    chunkPtr = layoutPtr->chunks;\n    fontPtr = (TkFont *) layoutPtr->tkfont;\n\n    left = x;\n    top = y;\n    right = x + width;\n    bottom = y + height;\n\n    result = 0;\n    for (i = 0; i < layoutPtr->numChunks; i++) {\n\tif ((chunkPtr->start[0] == '\\n') || (chunkPtr->numBytes == 0)) {\n\t    /*\n\t     * Newline characters and empty chunks are not counted when\n\t     * computing area intersection (but tab characters would still be\n\t     * considered).\n\t     */\n\n\t    chunkPtr++;\n\t    continue;\n\t}\n\n\tx1 = chunkPtr->x;\n\ty1 = chunkPtr->y - fontPtr->fm.ascent;\n\tx2 = chunkPtr->x + chunkPtr->displayWidth;\n\ty2 = chunkPtr->y + fontPtr->fm.descent;\n\n\tif ((right < x1) || (left >= x2)\n\t\t|| (bottom < y1) || (top >= y2)) {\n\t    if (result == 1) {\n\t\treturn 0;\n\t    }\n\t    result = -1;\n\t} else if ((x1 < left) || (x2 >= right)\n\t\t|| (y1 < top) || (y2 >= bottom)) {\n\t    return 0;\n\t} else if (result == -1) {\n\t    return 0;\n\t} else {\n\t    result = 1;\n\t}\n\tchunkPtr++;\n    }\n    return result;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkIntersectAngledTextLayout --\n *\n *\tDetermines whether a text layout that has been turned by an angle\n *\tabout its top-left coordinae lies entirely inside, entirely outside,\n *\tor overlaps a given rectangle. Non-displaying space characters that\n *\toccur at the end of individual lines in the text layout are ignored\n *\tfor intersection calculations.\n *\n * Results:\n *\tThe return value is -1 if the text layout is entirely outside of the\n *\trectangle, 0 if it overlaps, and 1 if it is entirely inside of the\n *\trectangle.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic inline int\nPointInQuadrilateral(\n    double qx[],\n    double qy[],\n    double x,\n    double y)\n{\n    int i;\n\n    for (i=0 ; i<4 ; i++) {\n\tdouble sideDX = qx[(i+1)%4] - qx[i];\n\tdouble sideDY = qy[(i+1)%4] - qy[i];\n\tdouble dx = x - qx[i];\n\tdouble dy = y - qy[i];\n\n\tif (sideDX*dy < sideDY*dx) {\n\t    return 0;\n\t}\n    }\n    return 1;\n}\n\nstatic inline int\nSidesIntersect(\n    double ax1, double ay1, double ax2, double ay2,\n    double bx1, double by1, double bx2, double by2)\n{\n#if 0\n/* http://www.freelunchdesign.com/cgi-bin/codwiki.pl?DiscussionTopics/CollideMeUpBaby */\n\n    double a1, b1, c1, a2, b2, c2, r1, r2, r3, r4, denom;\n\n    a1 = ay2 - ay1;\n    b1 = ax1 - ax2;\n    c1 = (ax2 * ay1) - (ax1 * ay2);\n    r3 = (a1 * bx1) + (b1 * by1) + c1;\n    r4 = (a1 * bx2) + (b1 * by2) + c1;\n    if ((r3 != 0.0) && (r4 != 0.0) && (r3*r4 > 0.0)) {\n\treturn 0;\n    }\n\n    a2 = by2 - by1;\n    b2 = bx1 - bx2;\n    c2 = (bx2 * by1) - (bx1 * by2);\n    r1 = (a2 * ax1) + (b2 * ay1) + c2;\n    r2 = (a2 * ax2) + (b2 * ay2) + c2;\n    if ((r1 != 0.0) && (r2 != 0.0) && (r1*r2 > 0.0)) {\n\treturn 0;\n    }\n\n    denom = (a1 * b2) - (a2 * b1);\n    return (denom != 0.0);\n#else\n    /*\n     * A more efficient version. Two line segments intersect if, when seen\n     * from the perspective of one line, the two endpoints of the other\n     * segment lie on opposite sides of the line, and vice versa. \"Lie on\n     * opposite sides\" is computed by taking the cross products and seeing if\n     * they are of opposite signs.\n     */\n\n    double dx, dy, dx1, dy1;\n\n    dx = ax2 - ax1;\n    dy = ay2 - ay1;\n    dx1 = bx1 - ax1;\n    dy1 = by1 - ay1;\n    if ((dx*dy1-dy*dx1 > 0.0) == (dx*(by2-ay1)-dy*(bx2-ax1) > 0.0)) {\n\treturn 0;\n    }\n    dx = bx2 - bx1;\n    dy = by2 - by1;\n    if ((dy*dx1-dx*dy1 > 0.0) == (dx*(ay2-by1)-dy*(ax2-bx1) > 0.0)) {\n\treturn 0;\n    }\n    return 1;\n#endif\n}\n\nint\nTkIntersectAngledTextLayout(\n    Tk_TextLayout layout,\t/* Layout information, from a previous call to\n\t\t\t\t * Tk_ComputeTextLayout(). */\n    int x, int y,\t\t/* Upper-left hand corner, in pixels, of\n\t\t\t\t * rectangular area to compare with text\n\t\t\t\t * layout. Coordinates are with respect to the\n\t\t\t\t * upper-left hand corner of the text layout\n\t\t\t\t * itself. */\n    int width, int height,\t/* The width and height of the above\n\t\t\t\t * rectangular area, in pixels. */\n    double angle)\n{\n    int i, x1, y1, x2, y2;\n    TextLayout *layoutPtr;\n    LayoutChunk *chunkPtr;\n    TkFont *fontPtr;\n    double c = cos(angle * PI/180.0), s = sin(angle * PI/180.0);\n    double rx[4], ry[4];\n\n    if (angle == 0.0) {\n\treturn Tk_IntersectTextLayout(layout, x, y, width, height);\n    }\n\n    /*\n     * Compute the coordinates of the rectangle, rotated into text layout\n     * space.\n     */\n\n    rx[0] = x*c - y*s;\n    ry[0] = y*c + x*s;\n    rx[1] = (x+width)*c - y*s;\n    ry[1] = y*c + (x+width)*s;\n    rx[2] = (x+width)*c - (y+height)*s;\n    ry[2] = (y+height)*c + (x+width)*s;\n    rx[3] = x*c - (y+height)*s;\n    ry[3] = (y+height)*c + x*s;\n\n    /*\n     * Want to know if all chunks are inside the rectangle, or if there is any\n     * overlap. First, we check to see if all chunks are inside; if and only\n     * if they are, we're in the \"inside\" case.\n     */\n\n    layoutPtr = (TextLayout *) layout;\n    chunkPtr = layoutPtr->chunks;\n    fontPtr = (TkFont *) layoutPtr->tkfont;\n\n    for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {\n\tif (chunkPtr->start[0] == '\\n') {\n\t    /*\n\t     * Newline characters are not counted when computing area\n\t     * intersection (but tab characters would still be considered).\n\t     */\n\n\t    continue;\n\t}\n\n\tx1 = chunkPtr->x;\n\ty1 = chunkPtr->y - fontPtr->fm.ascent;\n\tx2 = chunkPtr->x + chunkPtr->displayWidth;\n\ty2 = chunkPtr->y + fontPtr->fm.descent;\n\tif (\t!PointInQuadrilateral(rx, ry, x1, y1) ||\n\t\t!PointInQuadrilateral(rx, ry, x2, y1) ||\n\t\t!PointInQuadrilateral(rx, ry, x2, y2) ||\n\t\t!PointInQuadrilateral(rx, ry, x1, y2)) {\n\t    goto notInside;\n\t}\n    }\n    return 1;\n\n    /*\n     * Next, check to see if all the points of the rectangle are inside a\n     * single chunk; if they are, we're in an \"overlap\" case.\n     */\n\n  notInside:\n    chunkPtr = layoutPtr->chunks;\n\n    for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {\n\tdouble cx[4], cy[4];\n\n\tif (chunkPtr->start[0] == '\\n') {\n\t    /*\n\t     * Newline characters are not counted when computing area\n\t     * intersection (but tab characters would still be considered).\n\t     */\n\n\t    continue;\n\t}\n\n\tcx[0] = cx[3] = chunkPtr->x;\n\tcy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;\n\tcx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;\n\tcy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;\n\tif (\tPointInQuadrilateral(cx, cy, rx[0], ry[0]) &&\n\t\tPointInQuadrilateral(cx, cy, rx[1], ry[1]) &&\n\t\tPointInQuadrilateral(cx, cy, rx[2], ry[2]) &&\n\t\tPointInQuadrilateral(cx, cy, rx[3], ry[3])) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * If we're overlapping now, we must be partially in and out of at least\n     * one chunk. If that is the case, there must be one line segment of the\n     * rectangle that is touching or crossing a line segment of a chunk.\n     */\n\n    chunkPtr = layoutPtr->chunks;\n\n    for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {\n\tint j;\n\n\tif (chunkPtr->start[0] == '\\n') {\n\t    /*\n\t     * Newline characters are not counted when computing area\n\t     * intersection (but tab characters would still be considered).\n\t     */\n\n\t    continue;\n\t}\n\n\tx1 = chunkPtr->x;\n\ty1 = chunkPtr->y - fontPtr->fm.ascent;\n\tx2 = chunkPtr->x + chunkPtr->displayWidth;\n\ty2 = chunkPtr->y + fontPtr->fm.descent;\n\n\tfor (j=0 ; j<4 ; j++) {\n\t    int k = (j+1) % 4;\n\n\t    if (    SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y1, x2,y1) ||\n\t\t    SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y1, x2,y2) ||\n\t\t    SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y2, x1,y2) ||\n\t\t    SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y2, x1,y1)) {\n\t\treturn 0;\n\t    }\n\t}\n    }\n\n    /*\n     * They must be wholly non-overlapping.\n     */\n\n    return -1;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_TextLayoutToPostscript --\n *\n *\tOutputs the contents of a text layout in Postscript format. The set of\n *\tlines in the text layout will be rendered by the user supplied\n *\tPostscript function. The function should be of the form:\n *\n *\t    justify x y string function --\n *\n *\tJustify is -1, 0, or 1, depending on whether the following string\n *\tshould be left, center, or right justified, x and y is the location\n *\tfor the origin of the string, string is the sequence of characters to\n *\tbe printed, and function is the name of the caller-provided function;\n *\tthe function should leave nothing on the stack.\n *\n *\tThe meaning of the origin of the string (x and y) depends on the\n *\tjustification. For left justification, x is where the left edge of the\n *\tstring should appear. For center justification, x is where the center\n *\tof the string should appear. And for right justification, x is where\n *\tthe right edge of the string should appear. This behavior is necessary\n *\tbecause, for example, right justified text on the screen is justified\n *\twith screen metrics. The same string needs to be justified with\n *\tprinter metrics on the printer to appear in the correct place with\n *\trespect to other similarly justified strings. In all circumstances, y\n *\tis the location of the baseline for the string.\n *\n * Results:\n *\tThe interp's result is modified to hold the Postscript code that will\n *\trender the text layout.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_TextLayoutToPostscript(\n    Tcl_Interp *interp,\t\t/* Filled with Postscript code. */\n    Tk_TextLayout layout)\t/* The layout to be rendered. */\n{\n    TextLayout *layoutPtr = (TextLayout *) layout;\n    LayoutChunk *chunkPtr = layoutPtr->chunks;\n    int baseline = chunkPtr->y;\n    Tcl_Obj *psObj = Tcl_NewObj();\n    int i, j;\n    Tcl_Size len;\n    const char *p, *glyphname;\n    char uindex[5], c, *ps;\n    int ch;\n\n    Tcl_AppendToObj(psObj, \"[(\", TCL_INDEX_NONE);\n    for (i = 0; i < layoutPtr->numChunks; i++, chunkPtr++) {\n\tif (baseline != chunkPtr->y) {\n\t    Tcl_AppendToObj(psObj, \")]\\n[(\", TCL_INDEX_NONE);\n\t    baseline = chunkPtr->y;\n\t}\n\tif (chunkPtr->numDisplayChars <= 0) {\n\t    if (chunkPtr->start[0] == '\\t') {\n\t\tTcl_AppendToObj(psObj, \"\\\\t\", TCL_INDEX_NONE);\n\t    }\n\t    continue;\n\t}\n\n\tfor (p=chunkPtr->start, j=0; j<chunkPtr->numDisplayChars; j++) {\n\t    /*\n\t     * INTL: We only handle symbols that have an encoding as a glyph\n\t     * from the standard set defined by Adobe. The rest get punted.\n\t     * Eventually this should be revised to handle more sophsticiated\n\t     * international postscript fonts.\n\t     */\n\n\t    p += Tcl_UtfToUniChar(p, &ch);\n\t    if ((ch == '(') || (ch == ')') || (ch == '\\\\') || (ch < 0x20)) {\n\t\t/*\n\t\t * Tricky point: the \"03\" is necessary in the snprintf below,\n\t\t * so that a full three digits of octal are always generated.\n\t\t * Without the \"03\", a number following this sequence could be\n\t\t * interpreted by Postscript as part of this sequence.\n\t\t */\n\n\t\tTcl_AppendPrintfToObj(psObj, \"\\\\%03o\", ch);\n\t\tcontinue;\n\t    } else if (ch <= 0x7f) {\n\t\t/*\n\t\t * Normal ASCII character.\n\t\t */\n\n\t\tc = (char) ch;\n\t\tTcl_AppendToObj(psObj, &c, 1);\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * This character doesn't belong to the ASCII character set, so we\n\t     * use the full glyph name.\n\t     */\n\n\t    if (ch > 0xffff) {\n\t\tgoto noMapping;\n\t    }\n\t    snprintf(uindex, sizeof(uindex), \"%04X\", ch);\t\t/* endianness? */\n\t    glyphname = Tcl_GetVar2(interp, \"::tk::psglyphs\", uindex, 0);\n\t    if (glyphname) {\n\t\tps = Tcl_GetStringFromObj(psObj, &len);\n\t\tif (ps[len-1] == '(') {\n\t\t    /*\n\t\t     * In-place edit. Ewww!\n\t\t     */\n\n\t\t    ps[len-1] = '/';\n\t\t} else {\n\t\t    Tcl_AppendToObj(psObj, \")/\", TCL_INDEX_NONE);\n\t\t}\n\t\tTcl_AppendToObj(psObj, glyphname, TCL_INDEX_NONE);\n\t\tTcl_AppendToObj(psObj, \"(\", TCL_INDEX_NONE);\n\t    } else {\n\t\t/*\n\t\t * No known mapping for the character into the space of\n\t\t * PostScript glyphs. Ignore it. :-(\n\t\t */\nnoMapping:\t;\n\n#ifdef TK_DEBUG_POSTSCRIPT_OUTPUT\n\t\tfprintf(stderr, \"Warning: no mapping to PostScript \"\n\t\t\t\"glyphs for \\\\u%04x\\n\", ch);\n#endif\n\t    }\n\t}\n    }\n    Tcl_AppendToObj(psObj, \")]\\n\", TCL_INDEX_NONE);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ConfigAttributesObj --\n *\n *\tProcess command line options to fill in fields of a properly\n *\tinitialized font attributes structure.\n *\n * Results:\n *\tA standard Tcl return value. If TCL_ERROR is returned, an error\n *\tmessage will be left in interp's result object.\n *\n * Side effects:\n *\tThe fields of the font attributes structure get filled in with\n *\tinformation from objv/objc. If an error occurs while parsing, the font\n *\tattributes structure will contain all modifications specified in the\n *\tcommand line options up to the point of the error.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nConfigAttributesObj(\n    Tcl_Interp *interp,\t\t/* Interp for error return. */\n    TCL_UNUSED(Tk_Window),\t/* For display on which font will be used. */\n    Tcl_Size objc,\t\t\t/* Number of elements in argv. */\n    Tcl_Obj *const objv[],\t/* Command line options. */\n    TkFontAttributes *faPtr)\t/* Font attributes structure whose fields are\n\t\t\t\t * to be modified. Structure must already be\n\t\t\t\t * properly initialized. */\n{\n    Tcl_Size i;\n    int n, index;\n    Tcl_Obj *optionPtr, *valuePtr;\n    const char *value;\n\n    for (i = 0; i < objc; i += 2) {\n\toptionPtr = objv[i];\n\n\tif (Tcl_GetIndexFromObj(interp, optionPtr, fontOpt, \"option\", 1,\n\t\t&index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif ((i+2 >= objc) && (objc & 1)) {\n\t    /*\n\t     * This test occurs after Tcl_GetIndexFromObj() so that \"font\n\t     * create xyz -xyz\" will return the error message that \"-xyz\" is a\n\t     * bad option, rather than that the value for \"-xyz\" is missing.\n\t     */\n\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" option missing\",\n\t\t\tTcl_GetString(optionPtr)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"FONT\", \"NO_ATTRIBUTE\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tvaluePtr = objv[i + 1];\n\n\tswitch (index) {\n\tcase FONT_FAMILY:\n\t    value = Tcl_GetString(valuePtr);\n\t    faPtr->family = Tk_GetUid(value);\n\t    break;\n\tcase FONT_SIZE:\n\t    if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    faPtr->size = (double)n;\n\t    break;\n\tcase FONT_WEIGHT:\n\t    n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr);\n\t    if (n == TK_FW_UNKNOWN) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    faPtr->weight = n;\n\t    break;\n\tcase FONT_SLANT:\n\t    n = TkFindStateNumObj(interp, optionPtr, slantMap, valuePtr);\n\t    if (n == TK_FS_UNKNOWN) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    faPtr->slant = n;\n\t    break;\n\tcase FONT_UNDERLINE:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    faPtr->underline = n;\n\t    break;\n\tcase FONT_OVERSTRIKE:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    faPtr->overstrike = n;\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetAttributeInfoObj --\n *\n *\tReturn information about the font attributes as a Tcl list.\n *\n * Results:\n *\tThe return value is TCL_OK if the objPtr was non-NULL and specified a\n *\tvalid font attribute, TCL_ERROR otherwise. If TCL_OK is returned, the\n *\tinterp's result object is modified to hold a description of either the\n *\tcurrent value of a single option, or a list of all options and their\n *\tcurrent values for the given font attributes. If TCL_ERROR is\n *\treturned, the interp's result is set to an error message describing\n *\tthat the objPtr did not refer to a valid option.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetAttributeInfoObj(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    const TkFontAttributes *faPtr,\n\t\t\t\t/* The font attributes to inspect. */\n    Tcl_Obj *objPtr)\t\t/* If non-NULL, indicates the single option\n\t\t\t\t * whose value is to be returned. Otherwise\n\t\t\t\t * information is returned for all options. */\n{\n    int i, index, start, end;\n    const char *str;\n    Tcl_Obj *valuePtr, *resultPtr = NULL;\n\n    start = 0;\n    end = FONT_NUMFIELDS;\n    if (objPtr != NULL) {\n\tif (Tcl_GetIndexFromObj(interp, objPtr, fontOpt, \"option\", TCL_EXACT,\n\t\t&index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstart = index;\n\tend = index + 1;\n    }\n\n    valuePtr = NULL;\n    if (objPtr == NULL) {\n\tresultPtr = Tcl_NewObj();\n    }\n    for (i = start; i < end; i++) {\n\tswitch (i) {\n\tcase FONT_FAMILY:\n\t    str = faPtr->family;\n\t    valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1));\n\t    break;\n\n\tcase FONT_SIZE:\n\t    if (faPtr->size >= 0.0) {\n\t\tvaluePtr = Tcl_NewWideIntObj((Tcl_WideInt)(faPtr->size + 0.5));\n\t    } else {\n\t\tvaluePtr = Tcl_NewWideIntObj(-(Tcl_WideInt)(-faPtr->size + 0.5));\n\t    }\n\t    break;\n\n\tcase FONT_WEIGHT:\n\t    str = TkFindStateString(weightMap, faPtr->weight);\n\t    valuePtr = Tcl_NewStringObj(str, TCL_INDEX_NONE);\n\t    break;\n\n\tcase FONT_SLANT:\n\t    str = TkFindStateString(slantMap, faPtr->slant);\n\t    valuePtr = Tcl_NewStringObj(str, TCL_INDEX_NONE);\n\t    break;\n\n\tcase FONT_UNDERLINE:\n\t    valuePtr = Tcl_NewBooleanObj(faPtr->underline);\n\t    break;\n\n\tcase FONT_OVERSTRIKE:\n\t    valuePtr = Tcl_NewBooleanObj(faPtr->overstrike);\n\t    break;\n\t}\n\tif (objPtr != NULL) {\n\t    Tcl_SetObjResult(interp, valuePtr);\n\t    return TCL_OK;\n\t}\n\tTcl_ListObjAppendElement(NULL, resultPtr,\n\t\tTcl_NewStringObj(fontOpt[i], TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, resultPtr, valuePtr);\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FontGetDescription --\n *\n *\tReturn information about the font description as a Tcl list. One\n *\tpossible result is \"{{DejaVu Sans} -16 bold underline}\".\n *\n * Results:\n *\tThe list of descriptions.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_FontGetDescription(\n    Tk_Font tkfont)\t\t/* Font whose description is desired. */\n{\n    const TkFontAttributes *faPtr = GetFontAttributes(tkfont);\n    Tcl_Obj *resultPtr = Tcl_NewObj();\n    const char *str;\n\n    str = faPtr->family;\n    Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, str ? -1 : 0));\n    if (faPtr->size >= 0.0) {\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewWideIntObj((int)(faPtr->size + 0.5)));\n    } else {\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewWideIntObj(-(int)(-faPtr->size + 0.5)));\n    }\n    if (faPtr->weight != TK_FW_NORMAL) {\n\tstr = TkFindStateString(weightMap, faPtr->weight);\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, TCL_INDEX_NONE));\n    }\n    if (faPtr->slant != TK_FS_ROMAN) {\n\tstr = TkFindStateString(slantMap, faPtr->slant);\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, TCL_INDEX_NONE));\n    }\n    if (faPtr->underline) {\n\tstr = TkFindStateString(underlineMap, faPtr->underline);\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, TCL_INDEX_NONE));\n    }\n    if (faPtr->overstrike) {\n\tstr = TkFindStateString(overstrikeMap, faPtr->overstrike);\n\tTcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, TCL_INDEX_NONE));\n    }\n    return resultPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ParseFontNameObj --\n *\n *\tConverts a object into a set of font attributes that can be used to\n *\tconstruct a font.\n *\n *\tThe string rep of the object can be one of the following forms:\n *\t\tXLFD (see X documentation)\n *\t\t\"family [size] [style1 [style2 ...]\"\n *\t\t\"-option value [-option value ...]\"\n *\n * Results:\n *\tThe return value is TCL_ERROR if the object was syntactically invalid.\n *\tIn that case an error message is left in interp's result object.\n *\tOtherwise, fills the font attribute buffer with the values parsed from\n *\tthe string and returns TCL_OK;\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nParseFontNameObj(\n    Tcl_Interp *interp,\t\t/* Interp for error return. */\n    Tk_Window tkwin,\t\t/* For display on which font is used. */\n    Tcl_Obj *objPtr,\t\t/* Parseable font description object. */\n    TkFontAttributes *faPtr)\t/* Filled with attributes parsed from font\n\t\t\t\t * name. Any attributes that were not\n\t\t\t\t * specified in font name are filled with\n\t\t\t\t * default values. */\n{\n    const char *dash;\n    int result, n;\n    Tcl_Size objc, i;\n    Tcl_Obj **objv;\n    const char *string;\n\n    TkInitFontAttributes(faPtr);\n\n    string = Tcl_GetString(objPtr);\n    if (*string == '-') {\n\t/*\n\t * This may be an XLFD or an \"-option value\" string.\n\t *\n\t * If the string begins with \"-*\" or a \"-foundry-family-*\" pattern,\n\t * then consider it an XLFD.\n\t */\n\n\tif (string[1] == '*') {\n\t    goto xlfd;\n\t}\n\tdash = strchr(string + 1, '-');\n\tif ((dash != NULL)\n\t\t&& !isspace(UCHAR(dash[-1]))) {\t/* INTL: ISO space */\n\t    goto xlfd;\n\t}\n\n\tif (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\treturn ConfigAttributesObj(interp, tkwin, objc, objv, faPtr);\n    }\n\n    if (*string == '*') {\n\t/*\n\t * This is appears to be an XLFD. Under Unix, all valid XLFDs were\n\t * already handled by TkpGetNativeFont. If we are here, either we have\n\t * something that initially looks like an XLFD but isn't or we have\n\t * encountered an XLFD on Windows or Mac.\n\t */\n\n    xlfd:\n\tresult = TkFontParseXLFD(string, faPtr, NULL);\n\tif (result == TCL_OK) {\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * If the string failed to parse but was considered to be a XLFD\n\t * then it may be a \"-option value\" string with a hyphenated family\n\t * name as per bug 2791352\n\t */\n\n\tif (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) == TCL_OK) {\n\t    return TCL_OK;\n\t}\n    }\n\n    /*\n     * Wasn't an XLFD or \"-option value\" string. Try it as a \"font size style\"\n     * list.\n     */\n\n    if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK)\n\t    || (objc < 1)) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"font \\\"%s\\\" does not exist\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"FONT\", string, (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    faPtr->family = Tk_GetUid(Tcl_GetString(objv[0]));\n    if (objc > 1) {\n\tif (Tcl_GetIntFromObj(interp, objv[1], &n) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tfaPtr->size = (double)n;\n    }\n\n    i = 2;\n    if (objc == 3) {\n\tif (Tcl_ListObjGetElements(interp, objv[2], &objc, &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\ti = 0;\n    }\n    for ( ; i < objc; i++) {\n\tn = TkFindStateNumObj(NULL, NULL, weightMap, objv[i]);\n\tif (n != TK_FW_UNKNOWN) {\n\t    faPtr->weight = n;\n\t    continue;\n\t}\n\tn = TkFindStateNumObj(NULL, NULL, slantMap, objv[i]);\n\tif (n != TK_FS_UNKNOWN) {\n\t    faPtr->slant = n;\n\t    continue;\n\t}\n\tn = TkFindStateNumObj(NULL, NULL, underlineMap, objv[i]);\n\tif (n != 0) {\n\t    faPtr->underline = n;\n\t    continue;\n\t}\n\tn = TkFindStateNumObj(NULL, NULL, overstrikeMap, objv[i]);\n\tif (n != 0) {\n\t    faPtr->overstrike = n;\n\t    continue;\n\t}\n\n\t/*\n\t * Unknown style.\n\t */\n\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"unknown font style \\\"%s\\\"\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"FONT_STYLE\",\n\t\t    Tcl_GetString(objv[i]), (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * NewChunk --\n *\n *\tHelper function for Tk_ComputeTextLayout(). Encapsulates a measured\n *\tset of characters in a chunk that can be quickly drawn.\n *\n * Results:\n *\tA pointer to the new chunk in the text layout.\n *\n * Side effects:\n *\tThe text layout is reallocated to hold more chunks as necessary.\n *\n *\tCurrently, Tk_ComputeTextLayout() stores contiguous ranges of \"normal\"\n *\tcharacters in a chunk, along with individual tab and newline chars in\n *\ttheir own chunks. All characters in the text layout are accounted for.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic LayoutChunk *\nNewChunk(\n    TextLayout **layoutPtrPtr,\n    Tcl_Size *maxPtr,\n    const char *start,\n    Tcl_Size numBytes,\n    int curX,\n    int newX,\n    int y)\n{\n    TextLayout *layoutPtr;\n    LayoutChunk *chunkPtr;\n    Tcl_Size maxChunks, numChars;\n    size_t s;\n\n    layoutPtr = *layoutPtrPtr;\n    maxChunks = *maxPtr;\n    if (layoutPtr->numChunks == maxChunks) {\n\tmaxChunks *= 2;\n\ts = offsetof(TextLayout, chunks) + ((size_t)maxChunks * sizeof(LayoutChunk));\n\tlayoutPtr = (TextLayout *)Tcl_Realloc(layoutPtr, s);\n\n\t*layoutPtrPtr = layoutPtr;\n\t*maxPtr = maxChunks;\n    }\n    numChars = Tcl_NumUtfChars(start, numBytes);\n    chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];\n    chunkPtr->start\t\t= start;\n    chunkPtr->numBytes\t\t= numBytes;\n    chunkPtr->numChars\t\t= numChars;\n    chunkPtr->numDisplayChars\t= numChars;\n    chunkPtr->x\t\t\t= curX;\n    chunkPtr->y\t\t\t= y;\n    chunkPtr->totalWidth\t= newX - curX;\n    chunkPtr->displayWidth\t= newX - curX;\n    layoutPtr->numChunks++;\n\n    return chunkPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFontParseXLFD --\n *\n *\tBreak up a fully specified XLFD into a set of font attributes.\n *\n * Results:\n *\tReturn value is TCL_ERROR if string was not a fully specified XLFD.\n *\tOtherwise, fills font attribute buffer with the values parsed from the\n *\tXLFD and returns TCL_OK.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkFontParseXLFD(\n    const char *string,\t\t/* Parseable font description string. */\n    TkFontAttributes *faPtr,\t/* Filled with attributes parsed from font\n\t\t\t\t * name. Any attributes that were not\n\t\t\t\t * specified in font name are filled with\n\t\t\t\t * default values. */\n    TkXLFDAttributes *xaPtr)\t/* Filled with X-specific attributes parsed\n\t\t\t\t * from font name. Any attributes that were\n\t\t\t\t * not specified in font name are filled with\n\t\t\t\t * default values. May be NULL if such\n\t\t\t\t * information is not desired. */\n{\n    char *src;\n    const char *str;\n    int i, j;\n    char *field[XLFD_NUMFIELDS + 2];\n    Tcl_DString ds;\n    TkXLFDAttributes xa;\n\n    if (xaPtr == NULL) {\n\txaPtr = &xa;\n    }\n    TkInitFontAttributes(faPtr);\n    TkInitXLFDAttributes(xaPtr);\n\n    memset(field, '\\0', sizeof(field));\n\n    str = string;\n    if (*str == '-') {\n\tstr++;\n    }\n\n    Tcl_DStringInit(&ds);\n    Tcl_DStringAppend(&ds, str, TCL_INDEX_NONE);\n    src = Tcl_DStringValue(&ds);\n\n    field[0] = src;\n    for (i = 0; *src != '\\0'; src++) {\n\tif (!(*src & 0x80)\n\t\t&& Tcl_UniCharIsUpper(UCHAR(*src))) {\n\t    *src = (char) Tcl_UniCharToLower(UCHAR(*src));\n\t}\n\tif (*src == '-') {\n\t    i++;\n\t    if (i == XLFD_NUMFIELDS) {\n\t\tcontinue;\n\t    }\n\t    *src = '\\0';\n\t    field[i] = src + 1;\n\t    if (i > XLFD_NUMFIELDS) {\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common,\n     * but it is (strictly) malformed, because the first * is eliding both the\n     * Setwidth and the Addstyle fields. If the Addstyle field is a number,\n     * then assume the above incorrect form was used and shift all the rest of\n     * the fields right by one, so the number gets interpreted as a pixelsize.\n     * This fix is so that we don't get a million reports that \"it works under\n     * X (as a native font name), but gives a syntax error under Windows (as a\n     * parsed set of attributes)\".\n     */\n\n    if ((i > XLFD_ADD_STYLE) && FieldSpecified(field[XLFD_ADD_STYLE])) {\n\tif (atoi(field[XLFD_ADD_STYLE]) != 0) {\n\t    for (j = XLFD_NUMFIELDS - 1; j >= XLFD_ADD_STYLE; j--) {\n\t\tfield[j + 1] = field[j];\n\t    }\n\t    field[XLFD_ADD_STYLE] = NULL;\n\t    i++;\n\t}\n    }\n\n    /*\n     * Bail if we don't have enough of the fields (up to pointsize).\n     */\n\n    if (i < XLFD_FAMILY) {\n\tTcl_DStringFree(&ds);\n\treturn TCL_ERROR;\n    }\n\n    if (FieldSpecified(field[XLFD_FOUNDRY])) {\n\txaPtr->foundry = Tk_GetUid(field[XLFD_FOUNDRY]);\n    }\n\n    if (FieldSpecified(field[XLFD_FAMILY])) {\n\tfaPtr->family = Tk_GetUid(field[XLFD_FAMILY]);\n    }\n    if (FieldSpecified(field[XLFD_WEIGHT])) {\n\tfaPtr->weight = TkFindStateNum(NULL, NULL, xlfdWeightMap,\n\t\tfield[XLFD_WEIGHT]);\n    }\n    if (FieldSpecified(field[XLFD_SLANT])) {\n\txaPtr->slant = TkFindStateNum(NULL, NULL, xlfdSlantMap,\n\t\tfield[XLFD_SLANT]);\n\tif (xaPtr->slant == TK_FS_ROMAN) {\n\t    faPtr->slant = TK_FS_ROMAN;\n\t} else {\n\t    faPtr->slant = TK_FS_ITALIC;\n\t}\n    }\n    if (FieldSpecified(field[XLFD_SETWIDTH])) {\n\txaPtr->setwidth = TkFindStateNum(NULL, NULL, xlfdSetwidthMap,\n\t\tfield[XLFD_SETWIDTH]);\n    }\n\n    /* XLFD_ADD_STYLE ignored. */\n\n    /*\n     * Pointsize in tenths of a point, but treat it as tenths of a pixel for\n     * historical compatibility.\n     */\n\n    faPtr->size = 12.0;\n\n    if (FieldSpecified(field[XLFD_POINT_SIZE])) {\n\tif (field[XLFD_POINT_SIZE][0] == '[') {\n\t    /*\n\t     * Some X fonts have the point size specified as follows:\n\t     *\n\t     *\t    [ N1 N2 N3 N4 ]\n\t     *\n\t     * where N1 is the point size (in points, not decipoints!), and\n\t     * N2, N3, and N4 are some additional numbers that I don't know\n\t     * the purpose of, so I ignore them.\n\t     */\n\n\t    faPtr->size = atof(field[XLFD_POINT_SIZE] + 1);\n\t} else if (Tcl_GetInt(NULL, field[XLFD_POINT_SIZE],\n\t\t&i) == TCL_OK) {\n\t    faPtr->size = i/10.0;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Pixel height of font. If specified, overrides pointsize.\n     */\n\n    if (FieldSpecified(field[XLFD_PIXEL_SIZE])) {\n\tif (field[XLFD_PIXEL_SIZE][0] == '[') {\n\t    /*\n\t     * Some X fonts have the pixel size specified as follows:\n\t     *\n\t     *\t    [ N1 N2 N3 N4 ]\n\t     *\n\t     * where N1 is the pixel size, and where N2, N3, and N4 are some\n\t     * additional numbers that I don't know the purpose of, so I\n\t     * ignore them.\n\t     */\n\n\t    faPtr->size = atof(field[XLFD_PIXEL_SIZE] + 1);\n\t} else if (Tcl_GetInt(NULL, field[XLFD_PIXEL_SIZE],\n\t\t&i) == TCL_OK) {\n\t    faPtr->size = (double)i;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    faPtr->size = -faPtr->size;\n\n    /* XLFD_RESOLUTION_X ignored. */\n\n    /* XLFD_RESOLUTION_Y ignored. */\n\n    /* XLFD_SPACING ignored. */\n\n    /* XLFD_AVERAGE_WIDTH ignored. */\n\n    if (FieldSpecified(field[XLFD_CHARSET])) {\n\txaPtr->charset = Tk_GetUid(field[XLFD_CHARSET]);\n    } else {\n\txaPtr->charset = Tk_GetUid(\"iso8859-1\");\n    }\n    Tcl_DStringFree(&ds);\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FieldSpecified --\n *\n *\tHelper function for TkParseXLFD(). Determines if a field in the XLFD\n *\twas set to a non-null, non-don't-care value.\n *\n * Results:\n *\tThe return value is 0 if the field in the XLFD was not set and should\n *\tbe ignored, non-zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nFieldSpecified(\n    const char *field)\t\t/* The field of the XLFD to check. Strictly\n\t\t\t\t * speaking, only when the string is \"*\" does\n\t\t\t\t * it mean don't-care. However, an unspecified\n\t\t\t\t * or question mark is also interpreted as\n\t\t\t\t * don't-care. */\n{\n    char ch;\n\n    if (field == NULL) {\n\treturn 0;\n    }\n    ch = field[0];\n    return (ch != '*' && ch != '?');\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFontGetPixels --\n *\n *\tGiven a font size specification (as described in the TkFontAttributes\n *\tstructure) return the number of pixels it represents.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\ndouble\nTkFontGetPixels(\n    Tk_Window tkwin,\t\t/* For point->pixel conversion factor. */\n    double size)\t\t/* Font size. */\n{\n    double d;\n\n    if (size <= 0.0) {\n\treturn -size;\n    }\n\n    d = size * 25.4 / 72.0;\n    d *= WidthOfScreen(Tk_Screen(tkwin));\n    d /= WidthMMOfScreen(Tk_Screen(tkwin));\n    return d;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFontGetPoints --\n *\n *\tGiven a font size specification (as described in the TkFontAttributes\n *\tstructure) return the number of points it represents.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\ndouble\nTkFontGetPoints(\n    Tk_Window tkwin,\t\t/* For pixel->point conversion factor. */\n    double size)\t\t/* Font size. */\n{\n    double d;\n\n    if (size >= 0.0) {\n\treturn size;\n    }\n\n    d = -size * 72.0 / 25.4;\n    d *= WidthMMOfScreen(Tk_Screen(tkwin));\n    d /= WidthOfScreen(Tk_Screen(tkwin));\n    return d;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkFontGetAliasList --\n *\n *\tGiven a font name, find the list of all aliases for that font name.\n *\tOne of the names in this list will probably be the name that this\n *\tplatform expects when asking for the font.\n *\n * Results:\n *\tAs above. The return value is NULL if the font name has no aliases.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nconst char *const *\nTkFontGetAliasList(\n    const char *faceName)\t/* Font name to test for aliases. */\n{\n    int i, j;\n\n    for (i = 0; fontAliases[i] != NULL; i++) {\n\tfor (j = 0; fontAliases[i][j] != NULL; j++) {\n\t    if (strcasecmp(faceName, fontAliases[i][j]) == 0) {\n\t\treturn fontAliases[i];\n\t    }\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkFontGetFallbacks --\n *\n *\tGet the list of font fallbacks that the platform-specific code can use\n *\tto try to find the closest matching font the name requested.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nconst char *const *const *\nTkFontGetFallbacks(void)\n{\n    return fontFallbacks;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkFontGetGlobalClass --\n *\n *\tGet the list of fonts to try if the requested font name does not\n *\texist and no fallbacks for that font name could be used either.\n *\tThe names in this list are considered preferred over all the other\n *\tfont names in the system when looking for a last-ditch fallback.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nconst char *const *\nTkFontGetGlobalClass(void)\n{\n    return globalFontClass;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkFontGetSymbolClass --\n *\n *\tGet the list of fonts that are symbolic; used if the operating system\n *\tcannot apriori identify symbolic fonts on its own.\n *\n * Results:\n *\tAs above.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nconst char *const *\nTkFontGetSymbolClass(void)\n{\n    return symbolClass;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugFont --\n *\n *\tThis function returns debugging information about a font.\n *\n * Results:\n *\tThe return value is a list with one sublist for each TkFont\n *\tcorresponding to \"name\". Each sublist has two elements that contain\n *\tthe resourceRefCount and objRefCount fields from the TkFont structure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkDebugFont(\n    Tk_Window tkwin,\t\t/* The window in which the font will be used\n\t\t\t\t * (not currently used). */\n    const char *name)\t\t/* Name of the desired font. */\n{\n    TkFont *fontPtr;\n    Tcl_HashEntry *hashPtr;\n    Tcl_Obj *resultPtr, *objPtr;\n\n    resultPtr = Tcl_NewObj();\n    hashPtr = Tcl_FindHashEntry(\n\t    &((TkWindow *) tkwin)->mainPtr->fontInfoPtr->fontCache, name);\n    if (hashPtr != NULL) {\n\tfontPtr = (TkFont *)Tcl_GetHashValue(hashPtr);\n\tif (fontPtr == NULL) {\n\t    Tcl_Panic(\"TkDebugFont found empty hash table entry\");\n\t}\n\tfor ( ; (fontPtr != NULL); fontPtr = fontPtr->nextPtr) {\n\t    objPtr = Tcl_NewObj();\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(fontPtr->resourceRefCount));\n\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t    Tcl_NewWideIntObj(fontPtr->objRefCount));\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);\n\t}\n    }\n    return resultPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkFont.h",
    "content": "/*\n * tkFont.h --\n *\n *\tDeclarations for interfaces between the generic and platform-specific\n *\tparts of the font package. This information is not visible outside of\n *\tthe font package.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKFONT\n#define _TKFONT\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * The following structure keeps track of the attributes of a font. It can be\n * used to keep track of either the desired attributes or the actual\n * attributes gotten when the font was instantiated.\n */\n\nstruct TkFontAttributes {\n    Tk_Uid family;\t\t/* Font family, or NULL to represent plaform-\n\t\t\t\t * specific default system font. */\n    double size;\t\t/* Pointsize of font, 0.0 for default size, or\n\t\t\t\t * negative number meaning pixel size. */\n    int weight;\t\t\t/* Weight flag; see below for def'n. */\n    int slant;\t\t\t/* Slant flag; see below for def'n. */\n    int underline;\t\t/* Non-zero for underline font. */\n    int overstrike;\t\t/* Non-zero for overstrike font. */\n};\n\n/*\n * Possible values for the \"weight\" field in a TkFontAttributes structure.\n * Weight is a subjective term and depends on what the company that created\n * the font considers bold.\n */\n\n#define TK_FW_NORMAL\t0\n#define TK_FW_BOLD\t1\n\n#define TK_FW_UNKNOWN\t-1\t/* Unknown weight. This value is used for\n\t\t\t\t * error checking and is never actually stored\n\t\t\t\t * in the weight field. */\n\n/*\n * Possible values for the \"slant\" field in a TkFontAttributes structure.\n */\n\n#define TK_FS_ROMAN\t0\n#define TK_FS_ITALIC\t1\n#define TK_FS_OBLIQUE\t2\t/* This value is only used when parsing X font\n\t\t\t\t * names to determine the closest match. It is\n\t\t\t\t * only stored in the XLFDAttributes\n\t\t\t\t * structure, never in the slant field of the\n\t\t\t\t * TkFontAttributes. */\n\n#define TK_FS_UNKNOWN\t-1\t/* Unknown slant. This value is used for error\n\t\t\t\t * checking and is never actually stored in\n\t\t\t\t * the slant field. */\n\n/*\n * The following structure keeps track of the metrics for an instantiated\n * font. The metrics are the physical properties of the font itself.\n */\n\ntypedef struct TkFontMetrics {\n    int\tascent;\t\t\t/* From baseline to top of font. */\n    int\tdescent;\t\t/* From baseline to bottom of font. */\n    int maxWidth;\t\t/* Width of widest character in font. */\n    int fixed;\t\t\t/* Non-zero if this is a fixed-width font,\n\t\t\t\t * 0 otherwise. */\n} TkFontMetrics;\n\n/*\n * The following structure is used to keep track of the generic information\n * about a font. Each platform-specific font is represented by a structure\n * with the following structure at its beginning, plus any platform-specific\n * stuff after that.\n */\n\ntypedef struct TkFont {\n    /*\n     * Fields used and maintained exclusively by generic code.\n     */\n\n    Tcl_Size resourceRefCount;\t/* Number of active uses of this font (each\n\t\t\t\t * active use corresponds to a call to\n\t\t\t\t * Tk_AllocFontFromTable or Tk_GetFont). If\n\t\t\t\t * this count is 0, then this TkFont structure\n\t\t\t\t * is no longer valid and it isn't present in\n\t\t\t\t * a hash table: it is being kept around only\n\t\t\t\t * because there are objects referring to it.\n\t\t\t\t * The structure is freed when\n\t\t\t\t * resourceRefCount and objRefCount are both\n\t\t\t\t * 0. */\n    Tcl_Size objRefCount;\t\t/* The number of Tcl objects that reference\n\t\t\t\t * this structure. */\n    Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure,\n\t\t\t\t * used when deleting it. */\n    Tcl_HashEntry *namedHashPtr;/* Pointer to hash table entry that\n\t\t\t\t * corresponds to the named font that the\n\t\t\t\t * tkfont was based on, or NULL if the tkfont\n\t\t\t\t * was not based on a named font. */\n    Screen *screen;\t\t/* The screen where this font is valid. */\n    int tabWidth;\t\t/* Width of tabs in this font (pixels). */\n    int\tunderlinePos;\t\t/* Offset from baseline to origin of underline\n\t\t\t\t * bar (used for drawing underlines on a\n\t\t\t\t * non-underlined font). */\n    int underlineHeight;\t/* Height of underline bar (used for drawing\n\t\t\t\t * underlines on a non-underlined font). */\n\n    /*\n     * Fields used in the generic code that are filled in by\n     * platform-specific code.\n     */\n\n    Font fid;\t\t\t/* For backwards compatibility with XGCValues\n\t\t\t\t * structures. Remove when TkGCValues is\n\t\t\t\t * implemented. */\n    TkFontAttributes fa;\t/* Actual font attributes obtained when the\n\t\t\t\t * the font was created, as opposed to the\n\t\t\t\t * desired attributes passed in to\n\t\t\t\t * TkpGetFontFromAttributes(). The desired\n\t\t\t\t * metrics can be determined from the string\n\t\t\t\t * that was used to create this font. */\n    TkFontMetrics fm;\t\t/* Font metrics determined when font was\n\t\t\t\t * created. */\n    Colormap colormap; /* Only used with HAVE_XFT */\n    Visual* visual; /* Only used with HAVE_XFT */\n    struct TkFont *nextPtr;\t/* Points to the next TkFont structure with\n\t\t\t\t * the same name. All fonts with the same name\n\t\t\t\t * (but different displays) are chained\n\t\t\t\t * together off a single entry in a hash\n\t\t\t\t * table. */\n} TkFont;\n\n/*\n * The following structure is used to return attributes when parsing an XLFD.\n * The extra information is of interest to the Unix-specific code when\n * attempting to find the closest matching font.\n */\n\ntypedef struct TkXLFDAttributes {\n    Tk_Uid foundry;\t\t/* The foundry of the font. */\n    int slant;\t\t\t/* The tristate value for the slant, which is\n\t\t\t\t * significant under X. */\n    int setwidth;\t\t/* The proportionate width, see below for\n\t\t\t\t * definition. */\n    Tk_Uid charset;\t\t/* The actual charset string. */\n} TkXLFDAttributes;\n\n/*\n * Possible values for the \"setwidth\" field in a TkXLFDAttributes structure.\n * The setwidth is whether characters are considered wider or narrower than\n * normal.\n */\n\n#define TK_SW_NORMAL\t0\n#define TK_SW_CONDENSE\t1\n#define TK_SW_EXPAND\t2\n#define TK_SW_UNKNOWN\t3\t/* Unknown setwidth. This value may be stored\n\t\t\t\t * in the setwidth field. */\n\n/*\n * The following defines specify the meaning of the fields in a fully\n * qualified XLFD.\n */\n\n#define XLFD_FOUNDRY\t    0\n#define XLFD_FAMILY\t    1\n#define XLFD_WEIGHT\t    2\n#define XLFD_SLANT\t    3\n#define XLFD_SETWIDTH\t    4\n#define XLFD_ADD_STYLE\t    5\n#define XLFD_PIXEL_SIZE\t    6\n#define XLFD_POINT_SIZE\t    7\n#define XLFD_RESOLUTION_X   8\n#define XLFD_RESOLUTION_Y   9\n#define XLFD_SPACING\t    10\n#define XLFD_AVERAGE_WIDTH  11\n#define XLFD_CHARSET\t    12\n#define XLFD_NUMFIELDS\t    13\t/* Number of fields in XLFD. */\n\n/*\n * Helper macro. How to correctly round a double to a short.\n */\n\n#define ROUND16(x)\t((short) floor((x) + 0.5))\n\n/*\n * Low-level API exported by generic code to platform-specific code.\n */\n\n#define TkInitFontAttributes(fa)   memset((fa), 0, sizeof(TkFontAttributes));\n#define TkInitXLFDAttributes(xa)   memset((xa), 0, sizeof(TkXLFDAttributes));\n\nMODULE_SCOPE int\tTkFontParseXLFD(const char *string,\n\t\t\t    TkFontAttributes *faPtr, TkXLFDAttributes *xaPtr);\nMODULE_SCOPE const char *const * TkFontGetAliasList(const char *faceName);\nMODULE_SCOPE const char *const *const * TkFontGetFallbacks(void);\nMODULE_SCOPE double\tTkFontGetPixels(Tk_Window tkwin, double size);\nMODULE_SCOPE double\tTkFontGetPoints(Tk_Window tkwin, double size);\nMODULE_SCOPE const char *const * TkFontGetGlobalClass(void);\nMODULE_SCOPE const char *const * TkFontGetSymbolClass(void);\nMODULE_SCOPE int\tTkCreateNamedFont(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *name, TkFontAttributes *faPtr);\nMODULE_SCOPE int\tTkDeleteNamedFont(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, const char *name);\n\n/*\n * Low-level API exported by platform-specific code to generic code.\n */\n\nMODULE_SCOPE void\tTkpDeleteFont(TkFont *tkFontPtr);\nMODULE_SCOPE void\tTkpFontPkgInit(TkMainInfo *mainPtr);\nMODULE_SCOPE TkFont *\tTkpGetFontFromAttributes(TkFont *tkFontPtr,\n\t\t\t    Tk_Window tkwin, const TkFontAttributes *faPtr);\nMODULE_SCOPE void\tTkpGetFontFamilies(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin);\nMODULE_SCOPE TkFont *\tTkpGetNativeFont(Tk_Window tkwin, const char *name);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t/* _TKFONT */\n"
  },
  {
    "path": "generic/tkFrame.c",
    "content": "/*\n * tkFrame.c --\n *\n *\tThis module implements \"frame\", \"labelframe\" and \"toplevel\" widgets\n *\tfor the Tk toolkit. Frames are windows with a background color and\n *\tpossibly a 3-D effect, but not much else in the way of attributes.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"default.h\"\n\n/*\n * The following enum is used to define the type of the frame.\n */\n\nenum FrameType {\n    TYPE_FRAME, TYPE_TOPLEVEL, TYPE_LABELFRAME\n};\n\n/*\n * A data structure of the following type is kept for each\n * frame that currently exists for this process:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the frame. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up. */\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with widget. Used to\n\t\t\t\t * delete widget command. */\n    Tcl_Command widgetCmd;\t/* Token for frame's widget command. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n    Tcl_Obj *classNameObj;\t/* Class name for widget (from configuration\n\t\t\t\t * option). May be NULL. */\n    int type;\t\t\t/* Type of widget, such as TYPE_FRAME. */\n    Tcl_Obj *screenNameObj;\t/* Screen on which widget is created. Non-null\n\t\t\t\t * only for top-levels. May be NULL. */\n    Tcl_Obj *visualNameObj;\t/* Textual description of visual for window,\n\t\t\t\t * from -visual option. May be NULL. */\n    Tcl_Obj *colormapNameObj;\t/* Textual description of colormap for window,\n\t\t\t\t * from -colormap option. May be NULL. */\n    Tcl_Obj *menuNameObj;\t/* Textual description of menu to use for\n\t\t\t\t * menubar. Malloc-ed, may be NULL. */\n    Colormap colormap;\t\t/* If not None, identifies a colormap\n\t\t\t\t * allocated for this window, which must be\n\t\t\t\t * freed when the window is deleted. */\n    Tk_3DBorder border;\t\t/* Structure used to draw 3-D border and\n\t\t\t\t * background. NULL means no background or\n\t\t\t\t * border. */\n    Tcl_Obj *borderWidthObj;\t\t/* Width of 3-D border (if any). */\n    int relief;\t\t\t/* 3-d effect: TK_RELIEF_RAISED etc. */\n    Tcl_Obj *highlightWidthObj;\t\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. 0 means don't\n\t\t\t\t * draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    Tcl_Obj *widthObj;\t\t/* Width to request for window. <= 0 means\n\t\t\t\t * don't request any size. */\n    Tcl_Obj *heightObj;\t\t/* Height to request for window. <= 0 means\n\t\t\t\t * don't request any size. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or None. */\n    Tcl_Obj *takeFocusObj;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    bool isContainer;\t\t/* True means this window is a container, false means\n\t\t\t\t * that it isn't. */\n    Tcl_Obj *useThisObj;\t/* If the window is embedded, this points to\n\t\t\t\t * the name of the window in which it is\n\t\t\t\t * embedded. For non-embedded windows this is NULL. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n    Tcl_Obj *padXObj;\t\t/* Value of -padx option: specifies how many\n\t\t\t\t * pixels of extra space to leave on left and\n\t\t\t\t * right of child area. */\n    Tcl_Obj *padYObj;\t\t/* Value of -padx option: specifies how many\n\t\t\t\t * pixels of extra space to leave above and\n\t\t\t\t * below child area. */\n    Tcl_Obj *bgimgPtr;\t\t/* Value of -backgroundimage option: specifies\n\t\t\t\t * image to display on window's background, or\n\t\t\t\t * NULL if none. */\n    Tk_Image bgimg;\t\t/* Derived from bgimgPtr by calling\n\t\t\t\t * Tk_GetImage, or NULL if bgimgPtr is\n\t\t\t\t * NULL. */\n    bool tile;\t\t\t/* Whether to tile the bgimg. */\n#ifndef TK_NO_DOUBLE_BUFFERING\n    GC copyGC;\t\t\t/* GC for copying when double-buffering. */\n#endif /* TK_NO_DOUBLE_BUFFERING */\n} Frame;\n\n/*\n * A data structure of the following type is kept for each labelframe widget\n * managed by this file:\n */\n\ntypedef struct {\n    Frame frame;\t\t/* A pointer to the generic frame structure.\n\t\t\t\t * This must be the first element of the\n\t\t\t\t * Labelframe. */\n    /*\n     * Labelframe specific configuration settings.\n     */\n    Tcl_Obj *textPtr;\t\t/* Value of -text option: specifies text to\n\t\t\t\t * display in button. */\n    Tk_Font tkfont;\t\t/* Value of -font option: specifies font to\n\t\t\t\t * use for display text. */\n    XColor *textColorPtr;\t/* Value of -fg option: specifies foreground\n\t\t\t\t * color in normal mode. */\n    int labelAnchor;\t\t/* Value of -labelanchor option: specifies\n\t\t\t\t * where to place the label. */\n    Tk_Window labelWin;\t\t/* Value of -labelwidget option: Window to use\n\t\t\t\t * as label for the frame. */\n    /*\n     * Labelframe specific fields for use with configuration settings above.\n     */\n    GC textGC;\t\t\t/* GC for drawing text in normal mode. */\n    Tk_TextLayout textLayout;\t/* Stored text layout information. */\n    XRectangle labelBox;\t/* The label's actual size and position. */\n    int labelReqWidth;\t\t/* The label's requested width. */\n    int labelReqHeight;\t\t/* The label's requested height. */\n    int labelTextX, labelTextY;\t/* Position of the text to be drawn. */\n} Labelframe;\n\n/*\n * The following macros define how many extra pixels to leave around a label's\n * text.\n */\n\n#define LABELSPACING 1\n#define LABELMARGIN 4\n\n/*\n * Flag bits for frames:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * GOT_FOCUS:\t\t\tNon-zero means this widget currently has the\n *\t\t\t\tinput focus.\n */\n\n#define REDRAW_PENDING\t\t1\n#define GOT_FOCUS\t\t4\n\n/*\n * The following enum is used to define a type for the -labelanchor option of\n * the Labelframe widget. These values are used as indices into the string\n * table below.\n */\n\nenum labelanchor {\n    LABELANCHOR_E, LABELANCHOR_EN, LABELANCHOR_ES,\n    LABELANCHOR_N, LABELANCHOR_NE, LABELANCHOR_NW,\n    LABELANCHOR_S, LABELANCHOR_SE, LABELANCHOR_SW,\n    LABELANCHOR_W, LABELANCHOR_WN, LABELANCHOR_WS\n};\n\nstatic const char *const labelAnchorStrings[] = {\n    \"e\", \"en\", \"es\", \"n\", \"ne\", \"nw\", \"s\", \"se\", \"sw\", \"w\", \"wn\", \"ws\",\n    NULL\n};\n\n/*\n * Information used for parsing configuration options. There are one common\n * table used by all and one table for each widget class.\n */\n\nstatic const Tk_OptionSpec commonOptSpec[] = {\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_FRAME_BG_COLOR, TCL_INDEX_NONE, offsetof(Frame, border),\n\tTK_OPTION_NULL_OK, DEF_FRAME_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_STRING, \"-colormap\", \"colormap\", \"Colormap\",\n\tDEF_FRAME_COLORMAP, offsetof(Frame, colormapNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    /*\n     * Having -container is useless in a labelframe since a container has\n     * no border. It should be deprecated.\n     */\n    {TK_OPTION_BOOLEAN, \"-container\", \"container\", \"Container\",\n\tDEF_FRAME_CONTAINER, TCL_INDEX_NONE, offsetof(Frame, isContainer), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_FRAME_CURSOR, TCL_INDEX_NONE, offsetof(Frame, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\",\n\tDEF_FRAME_HEIGHT, offsetof(Frame, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_FRAME_HIGHLIGHT_BG, TCL_INDEX_NONE,\n\toffsetof(Frame, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_FRAME_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Frame, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_FRAME_HIGHLIGHT_WIDTH, offsetof(Frame, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\tDEF_FRAME_PADX, offsetof(Frame, padXObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\tDEF_FRAME_PADY, offsetof(Frame, padYObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_FRAME_TAKE_FOCUS, offsetof(Frame, takeFocusObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-visual\", \"visual\", \"Visual\",\n\tDEF_FRAME_VISUAL, offsetof(Frame, visualNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\",\n\tDEF_FRAME_WIDTH, offsetof(Frame, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\nstatic const Tk_OptionSpec frameOptSpec[] = {\n    {TK_OPTION_STRING, \"-backgroundimage\", \"backgroundImage\", \"BackgroundImage\",\n\tDEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bgimg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-backgroundimage\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_FRAME_BORDER_WIDTH, offsetof(Frame, borderWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-class\", \"class\", \"Class\",\n\tDEF_FRAME_CLASS, offsetof(Frame, classNameObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-tile\", \"tile\", \"Tile\",\n\tDEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, 0, 0, commonOptSpec, 0}\n};\n\nstatic const Tk_OptionSpec toplevelOptSpec[] = {\n    {TK_OPTION_STRING, \"-backgroundimage\", \"backgroundImage\", \"BackgroundImage\",\n\tDEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bgimg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-backgroundimage\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_FRAME_BORDER_WIDTH, offsetof(Frame, borderWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-class\", \"class\", \"Class\",\n\tDEF_TOPLEVEL_CLASS, offsetof(Frame, classNameObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-menu\", \"menu\", \"Menu\",\n\tDEF_TOPLEVEL_MENU, offsetof(Frame, menuNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},\n    {TK_OPTION_STRING, \"-screen\", \"screen\", \"Screen\",\n\tDEF_TOPLEVEL_SCREEN, offsetof(Frame, screenNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-tile\", \"tile\", \"Tile\",\n\tDEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_STRING, \"-use\", \"use\", \"Use\",\n\tDEF_TOPLEVEL_USE, offsetof(Frame, useThisObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, 0, 0, commonOptSpec, 0}\n};\n\nstatic const Tk_OptionSpec labelframeOptSpec[] = {\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_LABELFRAME_BORDER_WIDTH, offsetof(Frame, borderWidthObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING, \"-class\", \"class\", \"Class\",\n\tDEF_LABELFRAME_CLASS, offsetof(Frame, classNameObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_LABELFRAME_FONT, TCL_INDEX_NONE, offsetof(Labelframe, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_LABELFRAME_FG, TCL_INDEX_NONE, offsetof(Labelframe, textColorPtr), 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-labelanchor\", \"labelAnchor\", \"LabelAnchor\",\n\tDEF_LABELFRAME_LABELANCHOR, TCL_INDEX_NONE, offsetof(Labelframe, labelAnchor),\n\t0, labelAnchorStrings, 0},\n    {TK_OPTION_WINDOW, \"-labelwidget\", \"labelWidget\", \"LabelWidget\",\n\tNULL, TCL_INDEX_NONE, offsetof(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_LABELFRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_LABELFRAME_TEXT, offsetof(Labelframe, textPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, 0, 0, commonOptSpec, 0}\n};\n\n/*\n * Class names for widgets, indexed by FrameType.\n */\n\nstatic const char *const classNames[] = {\"Frame\", \"Toplevel\", \"Labelframe\"};\n\n/*\n * The following table maps from FrameType to the option template for that\n * class of widgets.\n */\n\nstatic const Tk_OptionSpec *const optionSpecs[] = {\n    frameOptSpec,\n    toplevelOptSpec,\n    labelframeOptSpec,\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tComputeFrameGeometry(Frame *framePtr);\nstatic int\t\tConfigureFrame(Tcl_Interp *interp, Frame *framePtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic Tcl_FreeProc\tDestroyFrame;\nstatic void\t\tDestroyFramePartly(Frame *framePtr);\nstatic void\t\tDisplayFrame(void *clientData);\nstatic void\t\tDrawFrameBackground(Tk_Window tkwin, Pixmap pixmap,\n\t\t\t    int highlightWidth, int borderWidth,\n\t\t\t    Tk_Image bgimg, bool bgtile);\nstatic void\t\tFrameBgImageProc(void *clientData,\n\t\t\t    int x, int y, int width, int height,\n\t\t\t    int imgWidth, int imgHeight);\nstatic void\t\tFrameCmdDeletedProc(void *clientData);\nstatic void\t\tFrameEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tFrameLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tFrameRequestProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tFrameStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_ObjCmdProc2 FrameWidgetObjCmd;\nstatic void\t\tFrameWorldChanged(void *instanceData);\nstatic void\t\tMapFrame(void *clientData);\n\n/*\n * The structure below defines frame class behavior by means of functions that\n * can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs frameClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    FrameWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n/*\n * The structure below defines the official type record for the labelframe's\n * geometry manager:\n */\n\nstatic const Tk_GeomMgr frameGeomType = {\n    \"labelframe\",\t\t/* name */\n    FrameRequestProc,\t\t/* requestProc */\n    FrameLostContentProc\t\t/* lostContentProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_FrameObjCmd, Tk_ToplevelObjCmd, Tk_LabelframeObjCmd --\n *\n *\tThese functions are invoked to process the \"frame\", \"toplevel\" and\n *\t\"labelframe\" Tcl commands. See the user documentation for details on\n *\twhat they do.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation. These functions are just wrappers; they\n *\tcall CreateFrame to do all of the real work.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_FrameObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    return TkCreateFrame(clientData, interp, objc, objv, TYPE_FRAME, NULL);\n}\n\nint\nTk_ToplevelObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    return TkCreateFrame(clientData, interp, objc, objv, TYPE_TOPLEVEL, NULL);\n}\n\nint\nTk_LabelframeObjCmd(\n    void *clientData,\t/* Either NULL or pointer to option table. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    return TkCreateFrame(clientData, interp, objc, objv, TYPE_LABELFRAME, NULL);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkCreateFrame --\n *\n *\tThis function is the old command function for the \"frame\" and\n *\t\"toplevel\" commands. Now it is used directly by Tk_Init to create a\n *\tnew main window. See the user documentation for the \"frame\" and\n *\t\"toplevel\" commands for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkCreateFrame(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    int type,\t/* What widget type to create. */\n    const char *appName)\t/* Should only be non-NULL if there are no\n\t\t\t\t * Main window associated with the\n\t\t\t\t * interpreter. Gives the base name to use for\n\t\t\t\t * the new application. */\n{\n    Tk_Window tkwin;\n    Frame *framePtr;\n    Tk_OptionTable optionTable;\n    Tk_Window newWin;\n    const char *className, *screenName, *visualName, *colormapName;\n    const char *arg, *useOption;\n    int depth;\n    Tcl_Size i, length;\n    unsigned int mask;\n    Colormap colormap;\n    Visual *visual;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);\n\n    /*\n     * Pre-process the argument list. Scan through it to find any \"-class\",\n     * \"-screen\", \"-visual\", and \"-colormap\" options. These arguments need to\n     * be processed specially, before the window is configured using the usual\n     * Tk mechanisms.\n     */\n\n    className = colormapName = screenName = visualName = useOption = NULL;\n    colormap = None;\n    for (i = 2; i < objc; i += 2) {\n\targ = Tcl_GetStringFromObj(objv[i], &length);\n\tif (length < 2) {\n\t    continue;\n\t}\n\tif ((arg[1] == 'c') && (length >= 3)\n\t\t&& (strncmp(arg, \"-class\", length) == 0)) {\n\t    className = Tcl_GetString(objv[i+1]);\n\t} else if ((arg[1] == 'c') && (length >= 3)\n\t\t&& (strncmp(arg, \"-colormap\", length) == 0)) {\n\t    colormapName = Tcl_GetString(objv[i+1]);\n\t} else if ((arg[1] == 's') && (type == TYPE_TOPLEVEL)\n\t\t&& (strncmp(arg, \"-screen\", length) == 0)) {\n\t    screenName = Tcl_GetString(objv[i+1]);\n\t} else if ((arg[1] == 'u') && (type == TYPE_TOPLEVEL)\n\t\t&& (strncmp(arg, \"-use\", length) == 0)) {\n\t    useOption = Tcl_GetString(objv[i+1]);\n\t} else if ((arg[1] == 'v')\n\t\t&& (strncmp(arg, \"-visual\", length) == 0)) {\n\t    visualName = Tcl_GetString(objv[i+1]);\n\t}\n    }\n\n    /*\n     * Create the window, and deal with the special options -use, -classname,\n     * -colormap, -screenname, and -visual. These options must be handle\n     * before calling ConfigureFrame below, and they must also be processed in\n     * a particular order, for the following reasons:\n     * 1. Must set the window's class before calling ConfigureFrame, so that\n     *\t  unspecified options are looked up in the option database using the\n     *\t  correct class.\n     * 2. Must set visual information before calling ConfigureFrame so that\n     *\t  colors are allocated in a proper colormap.\n     * 3. Must call Tk_UseWindow before setting non-default visual\n     *\t  information, since Tk_UseWindow changes the defaults.\n     */\n\n    if (screenName == NULL) {\n\tscreenName = (type == TYPE_TOPLEVEL) ? \"\" : NULL;\n    }\n\n    /*\n     * Main window associated with interpreter. If we're called by Tk_Init to\n     * create a new application, then this is NULL.\n     */\n\n    tkwin = Tk_MainWindow(interp);\n    if (tkwin != NULL) {\n\tnewWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),\n\t\tscreenName);\n    } else if (appName == NULL) {\n\t/*\n\t * This occurs when someone tried to create a frame/toplevel while we\n\t * are being destroyed. Let an error be thrown.\n\t */\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unable to create widget \\\"%s\\\"\", Tcl_GetString(objv[1])));\n\tTcl_SetErrorCode(interp, \"TK\", \"APPLICATION_GONE\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else {\n\t/*\n\t * We were called from Tk_Init; create a new application.\n\t */\n\n\tnewWin = TkCreateMainWindow(interp, screenName, appName);\n    }\n    if (newWin == NULL) {\n\tgoto error;\n    }\n\n    /*\n     * Mark Tk frames as suitable candidates for [wm manage].\n     */\n\n    ((TkWindow *)newWin)->flags |= TK_WM_MANAGEABLE;\n\n    if (className == NULL) {\n\tclassName = Tk_GetOption(newWin, \"class\", \"Class\");\n\tif (className == NULL) {\n\t    className = classNames[type];\n\t}\n    }\n    Tk_SetClass(newWin, className);\n    if (useOption == NULL) {\n\tuseOption = Tk_GetOption(newWin, \"use\", \"Use\");\n    }\n    if ((useOption != NULL) && (*useOption != 0)\n\t    && (Tk_UseWindow(interp, newWin, useOption) != TCL_OK)) {\n\tgoto error;\n    }\n    if (visualName == NULL) {\n\tvisualName = Tk_GetOption(newWin, \"visual\", \"Visual\");\n    }\n    if (colormapName == NULL) {\n\tcolormapName = Tk_GetOption(newWin, \"colormap\", \"Colormap\");\n    }\n    if ((colormapName != NULL) && (*colormapName == 0)) {\n\tcolormapName = NULL;\n    }\n    if (visualName != NULL) {\n\tvisual = Tk_GetVisual(interp, newWin, visualName, &depth,\n\t\t(colormapName == NULL) ? &colormap : NULL);\n\tif (visual == NULL) {\n\t    goto error;\n\t}\n\tTk_SetWindowVisual(newWin, visual, depth, colormap);\n    }\n    if (colormapName != NULL) {\n\tcolormap = Tk_GetColormap(interp, newWin, colormapName);\n\tif (colormap == None) {\n\t    goto error;\n\t}\n\tTk_SetWindowColormap(newWin, colormap);\n    }\n\n    /*\n     * For top-level windows, provide an initial geometry request of 200x200,\n     * just so the window looks nicer on the screen if it doesn't request a\n     * size for itself.\n     */\n\n    if (type == TYPE_TOPLEVEL) {\n\tTk_GeometryRequest(newWin, 200, 200);\n    }\n\n    /*\n     * Create the widget record, process configuration options, and create\n     * event handlers. Then fill in a few additional fields in the widget\n     * record from the special options.\n     */\n\n    if (type == TYPE_LABELFRAME) {\n\tframePtr = (Frame *)Tcl_Alloc(sizeof(Labelframe));\n\tmemset(framePtr, 0, sizeof(Labelframe));\n    } else {\n\tframePtr = (Frame *)Tcl_Alloc(sizeof(Frame));\n\tmemset(framePtr, 0, sizeof(Frame));\n    }\n    framePtr->tkwin = newWin;\n    framePtr->display = Tk_Display(newWin);\n    framePtr->interp = interp;\n    framePtr->widgetCmd\t= Tcl_CreateObjCommand2(interp, Tk_PathName(newWin),\n\t    FrameWidgetObjCmd, framePtr, FrameCmdDeletedProc);\n    framePtr->optionTable = optionTable;\n    framePtr->type = type;\n    framePtr->colormap = colormap;\n    framePtr->relief = TK_RELIEF_FLAT;\n    framePtr->cursor = NULL;\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\tLabelframe *labelframePtr = (Labelframe *) framePtr;\n\n\tlabelframePtr->labelAnchor = LABELANCHOR_NW;\n\tlabelframePtr->textGC = NULL;\n    }\n\n    /*\n     * Store backreference to frame widget in window structure.\n     */\n\n    Tk_SetClassProcs(newWin, &frameClass, framePtr);\n\n    mask = ExposureMask | StructureNotifyMask | FocusChangeMask;\n    if (type == TYPE_TOPLEVEL) {\n\tmask |= ActivateMask;\n    }\n    Tk_CreateEventHandler(newWin, mask, FrameEventProc, framePtr);\n    if ((Tk_InitOptions(interp, framePtr, optionTable, newWin)\n\t    != TCL_OK) ||\n\t    (ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) {\n\tgoto error;\n    }\n    if (framePtr->isContainer) {\n\tif (framePtr->useThisObj != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"windows cannot have both the -use and the -container\"\n\t\t    \" option set\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FRAME\", \"CONTAINMENT\", (char *)NULL);\n\t    goto error;\n\t}\n\tTk_MakeContainer(framePtr->tkwin);\n    }\n    if (type == TYPE_TOPLEVEL) {\n\tTcl_DoWhenIdle(MapFrame, framePtr);\n    }\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(newWin));\n    return TCL_OK;\n\n  error:\n    if (newWin != NULL) {\n\tTk_DestroyWindow(newWin);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FrameWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a frame widget. See the user documentation for details on what it\n *\tdoes.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nFrameWidgetObjCmd(\n    void *clientData,\t/* Information about frame widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const frameOptions[] = {\n\t\"cget\", \"configure\", NULL\n    };\n    enum options {\n\tFRAME_CGET, FRAME_CONFIGURE\n    };\n    Frame *framePtr = (Frame *)clientData;\n    int result = TCL_OK, index;\n    int c;\n    Tcl_Size i, length;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], frameOptions,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Preserve(framePtr);\n    switch ((enum options) index) {\n    case FRAME_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tobjPtr = Tk_GetOptionValue(interp, framePtr,\n\t\tframePtr->optionTable, objv[2], framePtr->tkwin);\n\tif (objPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n    case FRAME_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, framePtr,\n\t\t    framePtr->optionTable, (objc == 3) ? objv[2] : NULL,\n\t\t    framePtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    /*\n\t     * Don't allow the options -class, -colormap, -container, -screen,\n\t     * -use, or -visual to be changed.\n\t     */\n\n\t    for (i = 2; i < objc; i++) {\n\t\tconst char *arg = Tcl_GetStringFromObj(objv[i], &length);\n\n\t\tif (length < 2) {\n\t\t    continue;\n\t\t}\n\t\tc = arg[1];\n\t\tif (((c == 'c') && (length >= 2)\n\t\t\t&& (strncmp(arg, \"-class\", length) == 0))\n\t\t    || ((c == 'c') && (length >= 3)\n\t\t\t&& (strncmp(arg, \"-colormap\", length) == 0))\n\t\t    || ((c == 'c') && (length >= 3)\n\t\t\t&& (strncmp(arg, \"-container\", length) == 0))\n\t\t    || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL)\n\t\t\t&& (strncmp(arg, \"-screen\", length) == 0))\n\t\t    || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL)\n\t\t\t&& (strncmp(arg, \"-use\", length) == 0))\n\t\t    || ((c == 'v')\n\t\t\t&& (strncmp(arg, \"-visual\", length) == 0))) {\n\n#ifdef _WIN32\n\t\t    if (c == 'u') {\n\t\t\tconst char *string = Tcl_GetString(objv[i+1]);\n\n\t\t\tif (Tk_UseWindow(interp, framePtr->tkwin,\n\t\t\t\tstring) != TCL_OK) {\n\t\t\t    result = TCL_ERROR;\n\t\t\t    goto done;\n\t\t\t}\n\t\t\tcontinue;\n\t\t    }\n#endif\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"can't modify %s option after widget is created\",\n\t\t\t    arg));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"FRAME\", \"CREATE_ONLY\",\n\t\t\t    (char *)NULL);\n\t\t    result = TCL_ERROR;\n\t\t    goto done;\n\t\t}\n\t    }\n\t    result = ConfigureFrame(interp, framePtr, objc-2, objv+2);\n\t}\n\tbreak;\n    }\n\n  done:\n    Tcl_Release(framePtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyFrame --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of a frame at a safe time (when no-one is\n *\tusing it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the frame is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyFrame(\n    void *memPtr)\t\t/* Info about frame widget. */\n{\n    Frame *framePtr = (Frame *)memPtr;\n    Labelframe *labelframePtr = (Labelframe *)memPtr;\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\tTk_FreeTextLayout(labelframePtr->textLayout);\n\tif (labelframePtr->textGC != NULL) {\n\t    Tk_FreeGC(framePtr->display, labelframePtr->textGC);\n\t}\n    }\n#ifndef TK_NO_DOUBLE_BUFFERING\n    if (framePtr->copyGC != NULL) {\n\tTk_FreeGC(framePtr->display, framePtr->copyGC);\n    }\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    if (framePtr->colormap != None) {\n\tTk_FreeColormap(framePtr->display, framePtr->colormap);\n    }\n    if (framePtr->bgimg) {\n\tTk_FreeImage(framePtr->bgimg);\n    }\n    Tcl_Free(framePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyFramePartly --\n *\n *\tThis function is invoked to clean up everything that needs tkwin to be\n *\tdefined when deleted. During the destruction process tkwin is always\n *\tset to NULL and this function must be called before that happens.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSome things associated with the frame are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyFramePartly(\n    Frame *framePtr)\t\t/* Info about frame widget. */\n{\n    Labelframe *labelframePtr = (Labelframe *) framePtr;\n\n    if (framePtr->type == TYPE_LABELFRAME && labelframePtr->labelWin != NULL) {\n\tTk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,\n\t\tFrameStructureProc, framePtr);\n\tTk_ManageGeometry(labelframePtr->labelWin, NULL, NULL);\n\tif (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {\n\t    Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);\n\t}\n\tTk_UnmapWindow(labelframePtr->labelWin);\n\tlabelframePtr->labelWin = NULL;\n    }\n\n    Tk_FreeConfigOptions(framePtr, framePtr->optionTable,\n\t    framePtr->tkwin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureFrame --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a frame\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as text string, colors, font, etc. get\n *\tset for framePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureFrame(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Frame *framePtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    Tk_SavedOptions savedOptions;\n    Tcl_Obj *oldMenuNameObj;\n    Tk_Window oldWindow = NULL;\n    Labelframe *labelframePtr = (Labelframe *) framePtr;\n    Tk_Image image = NULL;\n\n    /*\n     * Need the old menubar name for the menu code to delete it.\n     */\n\n    oldMenuNameObj = framePtr->menuNameObj;\n    if (oldMenuNameObj) {\n\tTcl_IncrRefCount(oldMenuNameObj);\n    }\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\toldWindow = labelframePtr->labelWin;\n    }\n    if (Tk_SetOptions(interp, framePtr,\n\t    framePtr->optionTable, objc, objv,\n\t    framePtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\tif (oldMenuNameObj != NULL) {\n\t    Tcl_DecrRefCount(oldMenuNameObj);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    if (framePtr->bgimgPtr) {\n\timage = Tk_GetImage(interp, framePtr->tkwin,\n\t\tTcl_GetString(framePtr->bgimgPtr), FrameBgImageProc, framePtr);\n\tif (image == NULL) {\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t    return TCL_ERROR;\n\t}\n    }\n    if (framePtr->bgimg) {\n\tTk_FreeImage(framePtr->bgimg);\n    }\n    framePtr->bgimg = image;\n\n    Tk_FreeSavedOptions(&savedOptions);\n\n    /*\n     * A few of the options require additional processing.\n     */\n\n    if ((((oldMenuNameObj == NULL) && (framePtr->menuNameObj != NULL))\n\t    || ((oldMenuNameObj != NULL) && (framePtr->menuNameObj == NULL))\n\t    || ((oldMenuNameObj != NULL) && (framePtr->menuNameObj != NULL)\n\t    && strcmp(Tcl_GetString(oldMenuNameObj), Tcl_GetString(framePtr->menuNameObj)) != 0))\n\t    && framePtr->type == TYPE_TOPLEVEL) {\n\tTk_SetWindowMenubar(interp, framePtr->tkwin, (oldMenuNameObj ? Tcl_GetString(oldMenuNameObj) : NULL),\n\t\t(framePtr->menuNameObj ? Tcl_GetString(framePtr->menuNameObj) : NULL));\n    }\n\n    if (oldMenuNameObj != NULL) {\n\tTcl_DecrRefCount(oldMenuNameObj);\n    }\n\n    if (framePtr->border != NULL) {\n\tTk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);\n    } else {\n\tTk_SetWindowBackgroundPixmap(framePtr->tkwin, None);\n    }\n\n    /*\n     * If a -labelwidget is specified, check that it is valid and set up\n     * geometry management for it.\n     */\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\tif (oldWindow != labelframePtr->labelWin) {\n\t    if (oldWindow != NULL) {\n\t\tTk_DeleteEventHandler(oldWindow, StructureNotifyMask,\n\t\t\tFrameStructureProc, framePtr);\n\t\tTk_ManageGeometry(oldWindow, NULL, NULL);\n\t\tTk_UnmaintainGeometry(oldWindow, framePtr->tkwin);\n\t\tTk_UnmapWindow(oldWindow);\n\t    }\n\t    if (labelframePtr->labelWin != NULL) {\n\t\tTk_Window ancestor, parent, sibling = NULL;\n\n\t\t/*\n\t\t * Make sure that the frame is either the parent of the window\n\t\t * used as label or a descendant of that parent. Also, don't\n\t\t * allow a top-level window to be managed inside the frame.\n\t\t */\n\n\t\tparent = Tk_Parent(labelframePtr->labelWin);\n\t\tfor (ancestor = framePtr->tkwin; ;\n\t\t     ancestor = Tk_Parent(ancestor)) {\n\t\t    if (ancestor == parent) {\n\t\t\tbreak;\n\t\t    }\n\t\t    sibling = ancestor;\n\t\t    if (Tk_IsTopLevel(ancestor)) {\n\t\t\tgoto badLabelWindow;\n\t\t    }\n\t\t}\n\t\tif (Tk_IsTopLevel(labelframePtr->labelWin)) {\n\t\t    goto badLabelWindow;\n\t\t}\n\t\tif (labelframePtr->labelWin == framePtr->tkwin) {\n\t\t    goto badLabelWindow;\n\t\t}\n\t\tTk_CreateEventHandler(labelframePtr->labelWin,\n\t\t\tStructureNotifyMask, FrameStructureProc, framePtr);\n\t\tTk_ManageGeometry(labelframePtr->labelWin, &frameGeomType,\n\t\t\tframePtr);\n\n\t\t/*\n\t\t * If the frame is not parent to the label, make sure the\n\t\t * label is above its sibling in the stacking order.\n\t\t */\n\n\t\tif (sibling != NULL) {\n\t\t    Tk_RestackWindow(labelframePtr->labelWin, Above, sibling);\n\t\t}\n\t    }\n\t}\n    }\n\n    FrameWorldChanged(framePtr);\n    return TCL_OK;\n\n  badLabelWindow:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"can't use %s as label in this frame\",\n\t    Tk_PathName(labelframePtr->labelWin)));\n    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\", (char *)NULL);\n    labelframePtr->labelWin = NULL;\n    return TCL_ERROR;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FrameWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrame will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFrameWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    Frame *framePtr = (Frame *)instanceData;\n    Labelframe *labelframePtr = (Labelframe *)instanceData;\n    Tk_Window tkwin = framePtr->tkwin;\n    XGCValues gcValues;\n    GC gc;\n    int anyTextLabel, anyWindowLabel;\n    int bWidthLeft, bWidthRight, bWidthTop, bWidthBottom;\n    const char *labelText;\n    int padX, padY, width, height;\n    int borderWidth, highlightWidth;\n\n    anyTextLabel = (framePtr->type == TYPE_LABELFRAME) &&\n\t    (labelframePtr->textPtr != NULL) &&\n\t    (labelframePtr->labelWin == NULL);\n    anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) &&\n\t    (labelframePtr->labelWin != NULL);\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    gcValues.graphics_exposures = False;\n    gc = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);\n    if (framePtr->copyGC != NULL) {\n\tTk_FreeGC(framePtr->display, framePtr->copyGC);\n    }\n    framePtr->copyGC = gc;\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->borderWidthObj, &borderWidth);\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\t/*\n\t * The textGC is needed even in the labelWin case, so it's always\n\t * created for a labelframe.\n\t */\n\n\tgcValues.font = Tk_FontId(labelframePtr->tkfont);\n\tgcValues.foreground = labelframePtr->textColorPtr->pixel;\n\tgcValues.graphics_exposures = False;\n\tgc = Tk_GetGC(tkwin, GCForeground | GCFont | GCGraphicsExposures,\n\t\t&gcValues);\n\tif (labelframePtr->textGC != NULL) {\n\t    Tk_FreeGC(framePtr->display, labelframePtr->textGC);\n\t}\n\tlabelframePtr->textGC = gc;\n\n\t/*\n\t * Calculate label size.\n\t */\n\n\tlabelframePtr->labelReqWidth = labelframePtr->labelReqHeight = 0;\n\n\tif (anyTextLabel) {\n\t    labelText = Tcl_GetString(labelframePtr->textPtr);\n\t    Tk_FreeTextLayout(labelframePtr->textLayout);\n\t    labelframePtr->textLayout =\n\t\t    Tk_ComputeTextLayout(labelframePtr->tkfont,\n\t\t    labelText, TCL_INDEX_NONE, 0, TK_JUSTIFY_CENTER, 0,\n\t\t    &labelframePtr->labelReqWidth,\n\t\t    &labelframePtr->labelReqHeight);\n\t    labelframePtr->labelReqWidth += 2 * LABELSPACING;\n\t    labelframePtr->labelReqHeight += 2 * LABELSPACING;\n\t} else if (anyWindowLabel) {\n\t    labelframePtr->labelReqWidth = Tk_ReqWidth(labelframePtr->labelWin);\n\t    labelframePtr->labelReqHeight =\n\t\t    Tk_ReqHeight(labelframePtr->labelWin);\n\t}\n\n\t/*\n\t * Make sure label size is at least as big as the border. This\n\t * simplifies later calculations and gives a better appearance with\n\t * thick borders.\n\t */\n\n\tif ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&\n\t\t(labelframePtr->labelAnchor <= LABELANCHOR_SW)) {\n\t    if (labelframePtr->labelReqHeight < borderWidth) {\n\t\tlabelframePtr->labelReqHeight = borderWidth;\n\t    }\n\t} else {\n\t    if (labelframePtr->labelReqWidth < borderWidth) {\n\t\tlabelframePtr->labelReqWidth = borderWidth;\n\t    }\n\t}\n    }\n\n    /*\n     * Calculate individual border widths.\n     */\n\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->highlightWidthObj, &highlightWidth);\n    bWidthBottom = bWidthTop = bWidthRight = bWidthLeft =\n\t    borderWidth + highlightWidth;\n\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->padYObj, &padY);\n    bWidthLeft   += padX;\n    bWidthRight  += padX;\n    bWidthTop    += padY;\n    bWidthBottom += padY;\n\n    if (anyTextLabel || anyWindowLabel) {\n\tswitch (labelframePtr->labelAnchor) {\n\tcase LABELANCHOR_E:\n\tcase LABELANCHOR_EN:\n\tcase LABELANCHOR_ES:\n\t    bWidthRight += labelframePtr->labelReqWidth - borderWidth;\n\t    break;\n\tcase LABELANCHOR_N:\n\tcase LABELANCHOR_NE:\n\tcase LABELANCHOR_NW:\n\t    bWidthTop += labelframePtr->labelReqHeight - borderWidth;\n\t    break;\n\tcase LABELANCHOR_S:\n\tcase LABELANCHOR_SE:\n\tcase LABELANCHOR_SW:\n\t    bWidthBottom += labelframePtr->labelReqHeight - borderWidth;\n\t    break;\n\tdefault:\n\t    bWidthLeft += labelframePtr->labelReqWidth - borderWidth;\n\t    break;\n\t}\n    }\n\n    Tk_SetInternalBorderEx(tkwin, bWidthLeft, bWidthRight, bWidthTop,\n\t    bWidthBottom);\n\n    ComputeFrameGeometry(framePtr);\n\n    /*\n     * A labelframe should request size for its label.\n     */\n\n    if (framePtr->type == TYPE_LABELFRAME) {\n\tint minwidth = labelframePtr->labelReqWidth;\n\tint minheight = labelframePtr->labelReqHeight;\n\tint padding = highlightWidth;\n\n\tif (borderWidth > 0) {\n\t    padding += borderWidth + LABELMARGIN;\n\t}\n\tpadding *= 2;\n\tif ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&\n\t\t(labelframePtr->labelAnchor <= LABELANCHOR_SW)) {\n\t    minwidth += padding;\n\t    minheight += borderWidth + highlightWidth;\n\t} else {\n\t    minheight += padding;\n\t    minwidth += borderWidth + highlightWidth;\n\t}\n\tTk_SetMinimumRequestSize(tkwin, minwidth, minheight);\n    }\n\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->widthObj, &width);\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->heightObj, &height);\n    if ((width > 0) || (height > 0)) {\n\tTk_GeometryRequest(tkwin, width, height);\n    }\n\n    if (Tk_IsMapped(tkwin)) {\n\tif (!(framePtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(DisplayFrame, framePtr);\n\t}\n\tframePtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeFrameGeometry --\n *\n *\tThis function is called to compute various geometrical information for\n *\ta frame, such as where various things get displayed. It's called when\n *\tthe window is reconfigured.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDisplay-related numbers get changed in *framePtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nComputeFrameGeometry(\n    Frame *framePtr)\t/* Information about widget. */\n{\n    int otherWidth, otherHeight, otherWidthT, otherHeightT, padding;\n    int maxWidth, maxHeight;\n    Tk_Window tkwin;\n    int borderWidth, highlightWidth;\n    Labelframe *labelframePtr = (Labelframe *) framePtr;\n\n    /*\n     * We have nothing to do here unless there is a label.\n     */\n\n    if (framePtr->type != TYPE_LABELFRAME) {\n\treturn;\n    }\n    if (labelframePtr->textPtr == NULL && labelframePtr->labelWin == NULL) {\n\treturn;\n    }\n\n    tkwin = framePtr->tkwin;\n\n    /*\n     * Calculate the available size for the label\n     */\n\n    labelframePtr->labelBox.width = (unsigned short)labelframePtr->labelReqWidth;\n    labelframePtr->labelBox.height = (unsigned short)labelframePtr->labelReqHeight;\n\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->highlightWidthObj, &highlightWidth);\n    padding = highlightWidth;\n    if (borderWidth > 0) {\n\tpadding += borderWidth + LABELMARGIN;\n    }\n    padding *= 2;\n\n    maxHeight = Tk_Height(tkwin);\n    maxWidth  = Tk_Width(tkwin);\n\n    if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&\n\t    (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {\n\tmaxWidth -= padding;\n\tif (maxWidth < 1) {\n\t    maxWidth = 1;\n\t}\n    } else {\n\tmaxHeight -= padding;\n\tif (maxHeight < 1) {\n\t    maxHeight = 1;\n\t}\n    }\n    if (labelframePtr->labelBox.width > maxWidth) {\n\tlabelframePtr->labelBox.width = (unsigned short)maxWidth;\n    }\n    if (labelframePtr->labelBox.height > maxHeight) {\n\tlabelframePtr->labelBox.height = (unsigned short)maxHeight;\n    }\n\n    /*\n     * Calculate label and text position. The text's position is based on the\n     * requested size (= the text's real size) to get proper alignment if the\n     * text does not fit.\n     */\n\n    otherWidth   = Tk_Width(tkwin)  - labelframePtr->labelBox.width;\n    otherHeight  = Tk_Height(tkwin) - labelframePtr->labelBox.height;\n    otherWidthT  = Tk_Width(tkwin)  - labelframePtr->labelReqWidth;\n    otherHeightT = Tk_Height(tkwin) - labelframePtr->labelReqHeight;\n    padding = highlightWidth;\n\n    switch (labelframePtr->labelAnchor) {\n    case LABELANCHOR_E:\n    case LABELANCHOR_EN:\n    case LABELANCHOR_ES:\n\tlabelframePtr->labelTextX = otherWidthT - padding;\n\tlabelframePtr->labelBox.x = (short)(otherWidth - padding);\n\tbreak;\n    case LABELANCHOR_N:\n    case LABELANCHOR_NE:\n    case LABELANCHOR_NW:\n\tlabelframePtr->labelTextY = padding;\n\tlabelframePtr->labelBox.y = (short)padding;\n\tbreak;\n    case LABELANCHOR_S:\n    case LABELANCHOR_SE:\n    case LABELANCHOR_SW:\n\tlabelframePtr->labelTextY = otherHeightT - padding;\n\tlabelframePtr->labelBox.y = (short)(otherHeight - padding);\n\tbreak;\n    default:\n\tlabelframePtr->labelTextX = padding;\n\tlabelframePtr->labelBox.x = (short)padding;\n\tbreak;\n    }\n\n    if (borderWidth > 0) {\n\tpadding += borderWidth + LABELMARGIN;\n    }\n\n    switch (labelframePtr->labelAnchor) {\n    case LABELANCHOR_NW:\n    case LABELANCHOR_SW:\n\tlabelframePtr->labelTextX = padding;\n\tlabelframePtr->labelBox.x = (short)padding;\n\tbreak;\n    case LABELANCHOR_N:\n    case LABELANCHOR_S:\n\tlabelframePtr->labelTextX = otherWidthT / 2;\n\tlabelframePtr->labelBox.x = (short)(otherWidth / 2);\n\tbreak;\n    case LABELANCHOR_NE:\n    case LABELANCHOR_SE:\n\tlabelframePtr->labelTextX = otherWidthT - padding;\n\tlabelframePtr->labelBox.x = (short)(otherWidth - padding);\n\tbreak;\n    case LABELANCHOR_EN:\n    case LABELANCHOR_WN:\n\tlabelframePtr->labelTextY = padding;\n\tlabelframePtr->labelBox.y = (short)padding;\n\tbreak;\n    case LABELANCHOR_E:\n    case LABELANCHOR_W:\n\tlabelframePtr->labelTextY = otherHeightT / 2;\n\tlabelframePtr->labelBox.y = (short)(otherHeight / 2);\n\tbreak;\n    default:\n\tlabelframePtr->labelTextY = otherHeightT - padding;\n\tlabelframePtr->labelBox.y = (short)(otherHeight - padding);\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayFrame --\n *\n *\tThis function is invoked to display a frame widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the frame in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayFrame(\n    void *clientData)\t/* Information about widget. */\n{\n    Frame *framePtr = (Frame *)clientData;\n    Tk_Window tkwin = framePtr->tkwin;\n    int bdX1, bdY1, bdX2, bdY2;\n    Pixmap pixmap;\n    Bool useClipping = False;\n    int borderWidth, highlightWidth;\n\n    framePtr->flags &= ~REDRAW_PENDING;\n    if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    /*\n     * Highlight shall always be drawn if it exists, so do that first.\n     */\n\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->highlightWidthObj, &highlightWidth);\n\n    if (highlightWidth > 0) {\n\tGC fgGC, bgGC;\n\n\tbgGC = Tk_GCForColor(framePtr->highlightBgColorPtr,\n\t\tTk_WindowId(tkwin));\n\tif (framePtr->flags & GOT_FOCUS) {\n\t    fgGC = Tk_GCForColor(framePtr->highlightColorPtr,\n\t\t    Tk_WindowId(tkwin));\n\t    Tk_DrawHighlightBorder(tkwin, fgGC, bgGC, highlightWidth,\n\t\t    Tk_WindowId(tkwin));\n\t} else {\n\t    Tk_DrawHighlightBorder(tkwin, bgGC, bgGC, highlightWidth,\n\t\t    Tk_WindowId(tkwin));\n\t}\n    }\n\n    /*\n     * If -background is set to \"\", no interior is drawn.\n     */\n\n    if (framePtr->border == NULL) {\n\treturn;\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * In order to avoid screen flashes, this function redraws the frame into\n     * off-screen memory, then copies it back on-screen in a single operation.\n     * This means there's no point in time where the on-screen image has been\n     * cleared.\n     * Also, ensure that the pixmap size is at least 1x1 pixels to prevent\n     * crashes, see [610aa08858].\n     */\n\n    pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),\n\t(Tk_Width(tkwin) > 0 ? Tk_Width(tkwin) : 1),\n\t(Tk_Height(tkwin) > 0 ? Tk_Height(tkwin) : 1),\n\tTk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n    Tk_ClipDrawableToRect(Tk_Display(tkwin), pixmap, 0, 0,\n\t\t\t  Tk_Width(tkwin), Tk_Height(tkwin));\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->borderWidthObj, &borderWidth);\n\n    if (framePtr->type != TYPE_LABELFRAME) {\n\t/*\n\t * Pass to platform specific draw function. In general, it just draws\n\t * a simple rectangle, but it may \"theme\" the background.\n\t */\n\n    noLabel:\n\tTkpDrawFrameEx(tkwin, pixmap, framePtr->border, highlightWidth,\n\t\tborderWidth, framePtr->relief);\n\tif (framePtr->bgimg) {\n\t    DrawFrameBackground(tkwin, pixmap, highlightWidth, borderWidth,\n\t\t    framePtr->bgimg, framePtr->tile);\n\t}\n    } else {\n\tLabelframe *labelframePtr = (Labelframe *) framePtr;\n\n\tif ((labelframePtr->textPtr == NULL) &&\n\t\t(labelframePtr->labelWin == NULL)) {\n\t    goto noLabel;\n\t}\n\n\t/*\n\t * Clear the pixmap.\n\t */\n\n\tTk_Fill3DRectangle(tkwin, pixmap, framePtr->border, 0, 0,\n\t\tTk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\n\t/*\n\t * Calculate how the label affects the border's position.\n\t */\n\n\tbdX1 = bdY1 = highlightWidth;\n\tbdX2 = Tk_Width(tkwin) - highlightWidth;\n\tbdY2 = Tk_Height(tkwin) - highlightWidth;\n\n\tswitch (labelframePtr->labelAnchor) {\n\tcase LABELANCHOR_E:\n\tcase LABELANCHOR_EN:\n\tcase LABELANCHOR_ES:\n\t    bdX2 -= (labelframePtr->labelBox.width-borderWidth) / 2;\n\t    break;\n\tcase LABELANCHOR_N:\n\tcase LABELANCHOR_NE:\n\tcase LABELANCHOR_NW:\n\t    /*\n\t     * Since the glyphs of the text tend to be in the lower part we\n\t     * favor a lower border position by rounding up.\n\t     */\n\n\t    bdY1 += (labelframePtr->labelBox.height - borderWidth+1)/2;\n\t    break;\n\tcase LABELANCHOR_S:\n\tcase LABELANCHOR_SE:\n\tcase LABELANCHOR_SW:\n\t    bdY2 -= (labelframePtr->labelBox.height - borderWidth) / 2;\n\t    break;\n\tdefault:\n\t    bdX1 += (labelframePtr->labelBox.width - borderWidth) / 2;\n\t    break;\n\t}\n\n\t/*\n\t * Draw border\n\t */\n\n\tTk_Draw3DRectangle(tkwin, pixmap, framePtr->border, bdX1, bdY1,\n\t\tbdX2 - bdX1, bdY2 - bdY1, borderWidth,\n\t\tframePtr->relief);\n\n\tif (labelframePtr->labelWin == NULL) {\n\t    /*\n\t     * Clear behind the label\n\t     */\n\n\t    Tk_Fill3DRectangle(tkwin, pixmap,\n\t\t    framePtr->border, labelframePtr->labelBox.x,\n\t\t    labelframePtr->labelBox.y, labelframePtr->labelBox.width,\n\t\t    labelframePtr->labelBox.height, 0, TK_RELIEF_FLAT);\n\n\t    /*\n\t     * Draw label. If there is not room for the entire label, use\n\t     * clipping to get a nice appearance.\n\t     */\n\n\t    if ((labelframePtr->labelBox.width < labelframePtr->labelReqWidth)\n\t\t    || (labelframePtr->labelBox.height <\n\t\t\t    labelframePtr->labelReqHeight)) {\n\t\tuseClipping = True;\n\t\tXSetClipRectangles(framePtr->display, labelframePtr->textGC, 0, 0,\n\t\t\t&labelframePtr->labelBox, 1, Unsorted);\n\t    }\n\n\t    Tk_DrawTextLayout(framePtr->display, pixmap,\n\t\t    labelframePtr->textGC, labelframePtr->textLayout,\n\t\t    labelframePtr->labelTextX + LABELSPACING,\n\t\t    labelframePtr->labelTextY + LABELSPACING, 0, -1);\n\n\t    if (useClipping) {\n\t\tXSetClipMask(framePtr->display, labelframePtr->textGC, None);\n\t    }\n\t} else {\n\t    /*\n\t     * Reposition and map the window (but in different ways depending\n\t     * on whether the frame is the window's parent).\n\t     */\n\n\t    if (framePtr->tkwin == Tk_Parent(labelframePtr->labelWin)) {\n\t\tif ((labelframePtr->labelBox.x != Tk_X(labelframePtr->labelWin))\n\t\t\t|| (labelframePtr->labelBox.y !=\n\t\t\t\tTk_Y(labelframePtr->labelWin))\n\t\t\t|| (labelframePtr->labelBox.width !=\n\t\t\t\tTk_Width(labelframePtr->labelWin))\n\t\t\t|| (labelframePtr->labelBox.height !=\n\t\t\t\tTk_Height(labelframePtr->labelWin))) {\n\t\t    Tk_MoveResizeWindow(labelframePtr->labelWin,\n\t\t\t    labelframePtr->labelBox.x,\n\t\t\t    labelframePtr->labelBox.y,\n\t\t\t    labelframePtr->labelBox.width,\n\t\t\t    labelframePtr->labelBox.height);\n\t\t}\n\t\tTk_MapWindow(labelframePtr->labelWin);\n\t    } else {\n\t\tTk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin,\n\t\t\tlabelframePtr->labelBox.x, labelframePtr->labelBox.y,\n\t\t\tlabelframePtr->labelBox.width,\n\t\t\tlabelframePtr->labelBox.height);\n\t    }\n\t}\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Everything's been redisplayed; now copy the pixmap onto the screen and\n     * free up the pixmap.\n     */\n\n    XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),\n\t    framePtr->copyGC, highlightWidth, highlightWidth,\n\t    (unsigned) (Tk_Width(tkwin) - 2 * highlightWidth),\n\t    (unsigned) (Tk_Height(tkwin) - 2 * highlightWidth),\n\t    highlightWidth, highlightWidth);\n    Tk_FreePixmap(framePtr->display, pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawFrame --\n *\n *\tThis procedure draws the rectangular frame area.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws inside the tkwin area.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawFrame(\n    Tk_Window tkwin,\n    Tk_3DBorder border,\n    int highlightWidth,\n    int borderWidth,\n    int relief)\n{\n    /*\n     * Legacy shim to allow for external callers. Internal ones use\n     * non-exposed TkpDrawFrameEx directly so they can use double-buffering.\n     */\n\n    TkpDrawFrameEx(tkwin, Tk_WindowId(tkwin), border,\n\t    highlightWidth, borderWidth, relief);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FrameEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher on structure changes to\n *\ta frame. For frames with 3D borders, this function is also invoked for\n *\texposures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nFrameEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t/* Information about event. */\n{\n    Frame *framePtr = (Frame *)clientData;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tgoto redraw;\n    } else if (eventPtr->type == ConfigureNotify) {\n\tComputeFrameGeometry(framePtr);\n\tgoto redraw;\n    } else if (eventPtr->type == DestroyNotify) {\n\tif (framePtr->menuNameObj != NULL) {\n\t    Tk_SetWindowMenubar(framePtr->interp, framePtr->tkwin,\n\t\t    Tcl_GetString(framePtr->menuNameObj), NULL);\n\t    Tcl_DecrRefCount(framePtr->menuNameObj);\n\t    framePtr->menuNameObj = NULL;\n\t}\n\tif (framePtr->tkwin != NULL) {\n\t    /*\n\t     * If this window is a container, then this event could be coming\n\t     * from the embedded application, in which case Tk_DestroyWindow\n\t     * hasn't been called yet. When Tk_DestroyWindow is called later,\n\t     * then another destroy event will be generated. We need to be\n\t     * sure we ignore the second event, since the frame could be gone\n\t     * by then. To do so, delete the event handler explicitly\n\t     * (normally it's done implicitly by Tk_DestroyWindow).\n\t     */\n\n\t    /*\n\t     * Since the tkwin pointer will be gone when we reach\n\t     * DestroyFrame, we must free all options now.\n\t     */\n\n\t    DestroyFramePartly(framePtr);\n\n\t    Tk_DeleteEventHandler(framePtr->tkwin,\n\t\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t\t    FrameEventProc, framePtr);\n\t    framePtr->tkwin = NULL;\n\t    Tcl_DeleteCommandFromToken(framePtr->interp, framePtr->widgetCmd);\n\t}\n\tif (framePtr->flags & REDRAW_PENDING) {\n\t    Tcl_CancelIdleCall(DisplayFrame, framePtr);\n\t}\n\tTcl_CancelIdleCall(MapFrame, framePtr);\n\tTcl_EventuallyFree(framePtr, DestroyFrame);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    int highlightWidth;\n\t    framePtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    int highlightWidth;\n\t    framePtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, framePtr->tkwin, framePtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    } else if (eventPtr->type == ActivateNotify) {\n\tTk_SetMainMenubar(framePtr->interp, framePtr->tkwin,\n\t\t(framePtr->menuNameObj ? Tcl_GetString(framePtr->menuNameObj) : NULL));\n    }\n    return;\n\n  redraw:\n    if ((framePtr->tkwin != NULL) && !(framePtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayFrame, framePtr);\n\tframePtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FrameCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFrameCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    Frame *framePtr = (Frame *)clientData;\n    Tk_Window tkwin = framePtr->tkwin;\n\n    if (framePtr->menuNameObj != NULL) {\n\tTk_SetWindowMenubar(framePtr->interp, framePtr->tkwin,\n\t\tTcl_GetString(framePtr->menuNameObj), NULL);\n\tTcl_DecrRefCount(framePtr->menuNameObj);\n\tframePtr->menuNameObj = NULL;\n    }\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\t/*\n\t * Some options need tkwin to be freed, so we free them here, before\n\t * setting tkwin to NULL.\n\t */\n\n\tDestroyFramePartly(framePtr);\n\n\tframePtr->tkwin = NULL;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MapFrame --\n *\n *\tThis function is invoked as a when-idle handler to map a newly-created\n *\ttop-level frame.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe frame given by the clientData argument is mapped.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMapFrame(\n    void *clientData)\t\t/* Pointer to frame structure. */\n{\n    Frame *framePtr = (Frame *)clientData;\n\n    /*\n     * Wait for all other background events to be processed before mapping\n     * window. This ensures that the window's correct geometry will have been\n     * determined before it is first mapped, so that the window manager\n     * doesn't get a false idea of its desired geometry.\n     */\n\n    Tcl_Preserve(framePtr);\n    while (1) {\n\tif (Tcl_DoOneEvent(TCL_IDLE_EVENTS) == 0) {\n\t    break;\n\t}\n\n\t/*\n\t * After each event, make sure that the window still exists and quit\n\t * if the window has been destroyed.\n\t */\n\n\tif (framePtr->tkwin == NULL) {\n\t    Tcl_Release(framePtr);\n\t    return;\n\t}\n    }\n    Tk_MapWindow(framePtr->tkwin);\n    Tcl_Release(framePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkInstallFrameMenu --\n *\n *\tThis function is needed when a Windows HWND is created and a menubar\n *\thas been set to the window with a system menu. It notifies the menu\n *\tpackage so that the system menu can be rebuilt.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe system menu (if any) is created for the menubar associated with\n *\tthis frame.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkInstallFrameMenu(\n    Tk_Window tkwin)\t\t/* The window that was just created. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    if (winPtr->mainPtr != NULL) {\n\tFrame *framePtr = (Frame *)winPtr->instanceData;\n\n\tif (framePtr == NULL) {\n\t    Tcl_Panic(\"TkInstallFrameMenu couldn't get frame pointer\");\n\t}\n\tTkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp,\n\t\t(framePtr->menuNameObj ? Tcl_GetString(framePtr->menuNameObj) : NULL));\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FrameStructureProc --\n *\n *\tThis function is invoked whenever StructureNotify events occur for a\n *\twindow that's managed as label for the frame. This procudure's only\n *\tpurpose is to clean up when windows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is disassociated from the frame when it is deleted.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nFrameStructureProc(\n    void *clientData,\t/* Pointer to record describing frame. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Labelframe *labelframePtr = (Labelframe *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * This should only happen in a labelframe but it doesn't hurt to be\n\t * careful.\n\t */\n\n\tif (labelframePtr->frame.type == TYPE_LABELFRAME) {\n\t    labelframePtr->labelWin = NULL;\n\t    FrameWorldChanged(labelframePtr);\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FrameRequestProc --\n *\n *\tThis function is invoked whenever a window that's associated with a\n *\tframe changes its requested dimensions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size and location on the screen of the window may change depending\n *\ton the options specified for the frame.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nFrameRequestProc(\n    void *clientData,\t/* Pointer to record for frame. */\n    TCL_UNUSED(Tk_Window))\t\t/* Window that changed its desired size. */\n{\n    Frame *framePtr = (Frame *)clientData;\n\n    FrameWorldChanged(framePtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FrameLostContentProc --\n *\n *\tThis function is invoked by Tk whenever some other geometry claims\n *\tcontrol over a content window that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all frame-related information about the content window.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nFrameLostContentProc(\n    void *clientData,\t/* Frame structure for content window that was\n\t\t\t\t * stolen away. */\n    TCL_UNUSED(Tk_Window))\t\t/* Tk's handle for the content window window. */\n{\n    Frame *framePtr = (Frame *)clientData;\n    Labelframe *labelframePtr = (Labelframe *)clientData;\n\n    /*\n     * This should only happen in a labelframe but it doesn't hurt to be\n     * careful.\n     */\n\n    if (labelframePtr->frame.type == TYPE_LABELFRAME) {\n\tTk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,\n\t\tFrameStructureProc, labelframePtr);\n\tif (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {\n\t    Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);\n\t}\n\tTk_UnmapWindow(labelframePtr->labelWin);\n\tlabelframePtr->labelWin = NULL;\n    }\n    FrameWorldChanged(framePtr);\n}\n\f\nvoid\nTkMapTopFrame(\n     Tk_Window tkwin)\n{\n    Frame *framePtr = (Frame *)((TkWindow *)tkwin)->instanceData;\n    Tk_OptionTable optionTable;\n\n    if (Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_FRAME) {\n\tframePtr->type = TYPE_TOPLEVEL;\n\tTcl_DoWhenIdle(MapFrame, framePtr);\n\tif (framePtr->menuNameObj != NULL) {\n\t    Tk_SetWindowMenubar(framePtr->interp, framePtr->tkwin, NULL,\n\t\t    Tcl_GetString(framePtr->menuNameObj));\n\t}\n    } else if (!Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_TOPLEVEL) {\n\tframePtr->type = TYPE_FRAME;\n    } else {\n\t/*\n\t * Not a frame or toplevel, skip it.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * The option table has already been created so the cached pointer will be\n     * returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(framePtr->interp,\n\t    optionSpecs[framePtr->type]);\n    framePtr->optionTable = optionTable;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkToplevelWindowFromCommandToken --\n *\n *\tIf the given command name to the command for a toplevel window in the\n *\tgiven interpreter, return the tkwin for that toplevel window. Note\n *\tthat this lookup can't be done using the standard tkwin internal table\n *\tbecause the command might have been renamed.\n *\n * Results:\n *\tA Tk_Window token, or NULL if the name does not refer to a toplevel\n *\twindow.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nTk_Window\nTkToplevelWindowForCommand(\n    Tcl_Interp *interp,\n    const char *cmdName)\n{\n    Tcl_CmdInfo cmdInfo;\n    Frame *framePtr;\n\n    if (Tcl_GetCommandInfo(interp, cmdName, &cmdInfo) == 0) {\n\treturn NULL;\n    }\n    if (cmdInfo.objProc2 != FrameWidgetObjCmd) {\n\treturn NULL;\n    }\n    framePtr = (Frame *)cmdInfo.objClientData2;\n    if (framePtr->type != TYPE_TOPLEVEL) {\n\treturn NULL;\n    }\n    return framePtr->tkwin;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FrameBgImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size or contents of an image\n *\tdisplayed on a frame's background.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the button to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFrameBgImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int), /* Upper left pixel (within image) that must */\n    TCL_UNUSED(int), /* be redisplayed. */\n    TCL_UNUSED(int),\t/* Dimensions of area to redisplay (might be */\n    TCL_UNUSED(int), /* <= 0). */\n    TCL_UNUSED(int), /* New dimensions of image. */\n    TCL_UNUSED(int))\n{\n    Frame *framePtr = (Frame *)clientData;\n\n    /*\n     * Changing the background image never alters the dimensions of the frame.\n     */\n\n    if (framePtr->tkwin && Tk_IsMapped(framePtr->tkwin) &&\n\t    !(framePtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayFrame, framePtr);\n\tframePtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawFrameBackground --\n *\n *\tThis function draws the background image of a rectangular frame area.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws inside the tkwin area.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawFrameBackground(\n    Tk_Window tkwin,\n    Pixmap pixmap,\n    int highlightWidth,\n    int borderWidth,\n    Tk_Image bgimg,\n    bool bgtile)\n{\n    int width, height;\t\t\t/* Area to paint on. */\n    int imageWidth, imageHeight;\t/* Dimensions of image. */\n    const int bw = highlightWidth + borderWidth;\n\n    Tk_SizeOfImage(bgimg, &imageWidth, &imageHeight);\n    width = Tk_Width(tkwin) - 2*bw;\n    height = Tk_Height(tkwin) - 2*bw;\n\n    if (bgtile) {\n\t/*\n\t * Draw the image tiled in the widget (inside the border).\n\t */\n\n\tint x, y;\n\n\tfor (x = bw; x - bw < width; x += imageWidth) {\n\t    int w = imageWidth;\n\t    if (x - bw + imageWidth > width) {\n\t\tw = (width + bw) - x;\n\t    }\n\t    for (y = bw; y < height + bw; y += imageHeight) {\n\t\tint h = imageHeight;\n\t\tif (y - bw + imageHeight > height) {\n\t\t    h = (height + bw) - y;\n\t\t}\n\t\tTk_RedrawImage(bgimg, 0, 0, w, h, pixmap, x, y);\n\t    }\n\t}\n    } else {\n\t/*\n\t * Draw the image centred in the widget (inside the border).\n\t */\n\n\tint x, y, xOff, yOff, w, h;\n\n\tif (width > imageWidth) {\n\t    x = 0;\n\t    xOff = (Tk_Width(tkwin) - imageWidth) / 2;\n\t    w = imageWidth;\n\t} else {\n\t    x = (imageWidth - width) / 2;\n\t    xOff = bw;\n\t    w = width;\n\t}\n\tif (height > imageHeight) {\n\t    y = 0;\n\t    yOff = (Tk_Height(tkwin) - imageHeight) / 2;\n\t    h = imageHeight;\n\t} else {\n\t    y = (imageHeight - height) / 2;\n\t    yOff = bw;\n\t    h = height;\n\t}\n\tTk_RedrawImage(bgimg, x, y, w, h, pixmap, xOff, yOff);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkGC.c",
    "content": "/*\n * tkGC.c --\n *\n *\tThis file maintains a database of read-only graphics contexts for the\n *\tTk toolkit, in order to allow GC's to be shared.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * One of the following data structures exists for each GC that is currently\n * active. The structure is indexed with two hash tables, one based on the\n * values in the graphics context and the other based on the display and GC\n * identifier.\n */\n\ntypedef struct {\n    GC gc;\t\t\t/* Graphics context. */\n    Display *display;\t\t/* Display to which gc belongs. */\n    size_t refCount;\t\t/* Number of active uses of gc. */\n    Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting\n\t\t\t\t * this structure). */\n} TkGC;\n\ntypedef struct {\n    XGCValues values;\t\t/* Desired values for GC. */\n    Display *display;\t\t/* Display for which GC is valid. */\n    int screenNum;\t\t/* screen number of display */\n    int depth;\t\t\t/* and depth for which GC is valid. */\n} ValueKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tGCInit(TkDisplay *dispPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetGC --\n *\n *\tGiven a desired set of values for a graphics context, find a read-only\n *\tgraphics context with the desired values.\n *\n * Results:\n *\tThe return value is the X identifer for the desired graphics context.\n *\tThe caller should never modify this GC, and should call Tk_FreeGC when\n *\tthe GC is no longer needed.\n *\n * Side effects:\n *\tThe GC is added to an internal database with a reference count. For\n *\teach call to this function, there should eventually be a call to\n *\tTk_FreeGC, so that the database can be cleaned up when GC's aren't\n *\tneeded anymore.\n *\n *----------------------------------------------------------------------\n */\n\nGC\nTk_GetGC(\n    Tk_Window tkwin,\t\t/* Window in which GC will be used. */\n    unsigned long valueMask,\n\t\t\t\t/* 1 bits correspond to values specified in\n\t\t\t\t * *valuesPtr; other values are set from\n\t\t\t\t * defaults. */\n    XGCValues *valuePtr)\n\t\t\t\t/* Values are specified here for bits set in\n\t\t\t\t * valueMask. */\n{\n    ValueKey valueKey;\n    Tcl_HashEntry *valueHashPtr, *idHashPtr;\n    TkGC *gcPtr;\n    int isNew;\n    Drawable d, freeDrawable;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (dispPtr->gcInit <= 0) {\n\tGCInit(dispPtr);\n    }\n\n    /*\n     * Must zero valueKey at start to clear out pad bytes that may be part of\n     * structure on some systems.\n     */\n\n    memset(&valueKey, 0, sizeof(valueKey));\n\n    /*\n     * First, check to see if there's already a GC that will work for this\n     * request (exact matches only, sorry).\n     */\n\n    if (valueMask & GCFunction) {\n\tvalueKey.values.function = valuePtr->function;\n    } else {\n\tvalueKey.values.function = GXcopy;\n    }\n    if (valueMask & GCPlaneMask) {\n\tvalueKey.values.plane_mask = valuePtr->plane_mask;\n    } else {\n\tvalueKey.values.plane_mask = (unsigned) ~0;\n    }\n    if (valueMask & GCForeground) {\n\tvalueKey.values.foreground = valuePtr->foreground;\n    } else {\n\tvalueKey.values.foreground = 0;\n    }\n    if (valueMask & GCBackground) {\n\tvalueKey.values.background = valuePtr->background;\n    } else {\n\tvalueKey.values.background = 1;\n    }\n    if (valueMask & GCLineWidth) {\n\tvalueKey.values.line_width = valuePtr->line_width;\n    } else {\n\tvalueKey.values.line_width = 0;\n    }\n    if (valueMask & GCLineStyle) {\n\tvalueKey.values.line_style = valuePtr->line_style;\n    } else {\n\tvalueKey.values.line_style = LineSolid;\n    }\n    if (valueMask & GCCapStyle) {\n\tvalueKey.values.cap_style = valuePtr->cap_style;\n    } else {\n\tvalueKey.values.cap_style = CapButt;\n    }\n    if (valueMask & GCJoinStyle) {\n\tvalueKey.values.join_style = valuePtr->join_style;\n    } else {\n\tvalueKey.values.join_style = JoinMiter;\n    }\n    if (valueMask & GCFillStyle) {\n\tvalueKey.values.fill_style = valuePtr->fill_style;\n    } else {\n\tvalueKey.values.fill_style = FillSolid;\n    }\n    if (valueMask & GCFillRule) {\n\tvalueKey.values.fill_rule = valuePtr->fill_rule;\n    } else {\n\tvalueKey.values.fill_rule = EvenOddRule;\n    }\n    if (valueMask & GCArcMode) {\n\tvalueKey.values.arc_mode = valuePtr->arc_mode;\n    } else {\n\tvalueKey.values.arc_mode = ArcPieSlice;\n    }\n    if (valueMask & GCTile) {\n\tvalueKey.values.tile = valuePtr->tile;\n    } else {\n\tvalueKey.values.tile = None;\n    }\n    if (valueMask & GCStipple) {\n\tvalueKey.values.stipple = valuePtr->stipple;\n    } else {\n\tvalueKey.values.stipple = None;\n    }\n    if (valueMask & GCTileStipXOrigin) {\n\tvalueKey.values.ts_x_origin = valuePtr->ts_x_origin;\n    } else {\n\tvalueKey.values.ts_x_origin = 0;\n    }\n    if (valueMask & GCTileStipYOrigin) {\n\tvalueKey.values.ts_y_origin = valuePtr->ts_y_origin;\n    } else {\n\tvalueKey.values.ts_y_origin = 0;\n    }\n    if (valueMask & GCFont) {\n\tvalueKey.values.font = valuePtr->font;\n    } else {\n\tvalueKey.values.font = None;\n    }\n    if (valueMask & GCSubwindowMode) {\n\tvalueKey.values.subwindow_mode = valuePtr->subwindow_mode;\n    } else {\n\tvalueKey.values.subwindow_mode = ClipByChildren;\n    }\n    if (valueMask & GCGraphicsExposures) {\n\tvalueKey.values.graphics_exposures = valuePtr->graphics_exposures;\n    } else {\n\tvalueKey.values.graphics_exposures = True;\n    }\n    if (valueMask & GCClipXOrigin) {\n\tvalueKey.values.clip_x_origin = valuePtr->clip_x_origin;\n    } else {\n\tvalueKey.values.clip_x_origin = 0;\n    }\n    if (valueMask & GCClipYOrigin) {\n\tvalueKey.values.clip_y_origin = valuePtr->clip_y_origin;\n    } else {\n\tvalueKey.values.clip_y_origin = 0;\n    }\n    if (valueMask & GCClipMask) {\n\tvalueKey.values.clip_mask = valuePtr->clip_mask;\n    } else {\n\tvalueKey.values.clip_mask = None;\n    }\n    if (valueMask & GCDashOffset) {\n\tvalueKey.values.dash_offset = valuePtr->dash_offset;\n    } else {\n\tvalueKey.values.dash_offset = 0;\n    }\n    if (valueMask & GCDashList) {\n\tvalueKey.values.dashes = valuePtr->dashes;\n    } else {\n\tvalueKey.values.dashes = 4;\n    }\n    valueKey.display = Tk_Display(tkwin);\n    valueKey.screenNum = Tk_ScreenNumber(tkwin);\n    valueKey.depth = Tk_Depth(tkwin);\n    valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,\n\t    (char *) &valueKey, &isNew);\n    if (!isNew) {\n\tgcPtr = (TkGC *)Tcl_GetHashValue(valueHashPtr);\n\tgcPtr->refCount++;\n\treturn gcPtr->gc;\n    }\n\n    /*\n     * No GC is currently available for this set of values. Allocate a new GC\n     * and add a new structure to the database.\n     */\n\n    gcPtr = (TkGC *)Tcl_Alloc(sizeof(TkGC));\n\n    /*\n     * Find or make a drawable to use to specify the screen and depth of the\n     * GC. We may have to make a small pixmap, to avoid doing\n     * Tk_MakeWindowExist on the window.\n     */\n\n    freeDrawable = None;\n    if (Tk_WindowId(tkwin) != None) {\n\td = Tk_WindowId(tkwin);\n    } else if (valueKey.depth ==\n\t    DefaultDepth(valueKey.display, valueKey.screenNum)) {\n\td = RootWindow(valueKey.display, valueKey.screenNum);\n    } else {\n\td = Tk_GetPixmap(valueKey.display,\n\t\tRootWindow(valueKey.display, valueKey.screenNum),\n\t\t1, 1, valueKey.depth);\n\tfreeDrawable = d;\n    }\n\n    gcPtr->gc = XCreateGC(valueKey.display, d, valueMask, &valueKey.values);\n    gcPtr->display = valueKey.display;\n    gcPtr->refCount = 1;\n    gcPtr->valueHashPtr = valueHashPtr;\n    idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable,\n\t    (char *) gcPtr->gc, &isNew);\n    if (!isNew) {\n\tTcl_Panic(\"GC already registered in Tk_GetGC\");\n    }\n    Tcl_SetHashValue(valueHashPtr, gcPtr);\n    Tcl_SetHashValue(idHashPtr, gcPtr);\n    if (freeDrawable != None) {\n\tTk_FreePixmap(valueKey.display, freeDrawable);\n    }\n\n    return gcPtr->gc;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeGC --\n *\n *\tThis function is called to release a graphics context allocated by\n *\tTk_GetGC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count associated with gc is decremented, and gc is\n *\tofficially deallocated if no-one is using it anymore.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeGC(\n    Display *display,\t\t/* Display for which gc was allocated. */\n    GC gc)\t\t\t/* Graphics context to be released. */\n{\n    Tcl_HashEntry *idHashPtr;\n    TkGC *gcPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    if (!dispPtr->gcInit) {\n\tTcl_Panic(\"Tk_FreeGC called before Tk_GetGC\");\n    }\n    if (dispPtr->gcInit < 0) {\n\t/*\n\t * The GCCleanup has been called, and remaining GCs have been freed.\n\t * This may still get called by other things shutting down, but the\n\t * GCs should no longer be in use.\n\t */\n\n\treturn;\n    }\n\n    idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, gc);\n    if (idHashPtr == NULL) {\n\tTcl_Panic(\"Tk_FreeGC received unknown gc argument\");\n    }\n    gcPtr = (TkGC *)Tcl_GetHashValue(idHashPtr);\n    if (gcPtr->refCount-- <= 1) {\n\tXFreeGC(gcPtr->display, gcPtr->gc);\n\tTcl_DeleteHashEntry(gcPtr->valueHashPtr);\n\tTcl_DeleteHashEntry(idHashPtr);\n\tTcl_Free(gcPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGCCleanup --\n *\n *\tFrees the structures used for GC management. We need to have it called\n *\tnear the end, when other cleanup that calls Tk_FreeGC is all done.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGC resources are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGCCleanup(\n    TkDisplay *dispPtr)\t\t/* display to clean up resources in */\n{\n    Tcl_HashEntry *entryPtr;\n    Tcl_HashSearch search;\n    TkGC *gcPtr;\n\n    for (entryPtr = Tcl_FirstHashEntry(&dispPtr->gcIdTable, &search);\n\t    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {\n\tgcPtr = (TkGC *)Tcl_GetHashValue(entryPtr);\n\n\tXFreeGC(gcPtr->display, gcPtr->gc);\n\tTcl_DeleteHashEntry(gcPtr->valueHashPtr);\n\tTcl_DeleteHashEntry(entryPtr);\n\tTcl_Free(gcPtr);\n    }\n    Tcl_DeleteHashTable(&dispPtr->gcValueTable);\n    Tcl_DeleteHashTable(&dispPtr->gcIdTable);\n    dispPtr->gcInit = -1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GCInit --\n *\n *\tInitialize the structures used for GC management.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRead the code.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGCInit(\n    TkDisplay *dispPtr)\n{\n    if (dispPtr->gcInit < 0) {\n\tTcl_Panic(\"called GCInit after GCCleanup\");\n    }\n    dispPtr->gcInit = 1;\n    Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int));\n    Tcl_InitHashTable(&dispPtr->gcIdTable, TCL_ONE_WORD_KEYS);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkGeometry.c",
    "content": "/*\n * tkGeometry.c --\n *\n *\tThis file contains generic Tk code for geometry management (stuff\n *\tthat's used by all geometry managers).\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Data structures of the following type are used by Tk_MaintainGeometry. For\n * each content managed by Tk_MaintainGeometry, there is one of these structures\n * associated with its container.\n */\n\ntypedef struct MaintainContent {\n    Tk_Window content;\t\t/* The content window being positioned. */\n    Tk_Window container;\t\t/* The container that determines content's\n\t\t\t\t * position; it must be a descendant of\n\t\t\t\t * content's parent. */\n    int x, y;\t\t\t/* Desired position of content relative to\n\t\t\t\t * container. */\n    int width, height;\t\t/* Desired dimensions of content. */\n    struct MaintainContent *nextPtr;\n\t\t\t\t/* Next in list of Maintains associated with\n\t\t\t\t * container. */\n} MaintainContent;\n\n/*\n * For each window that has been specified as a content to Tk_MaintainGeometry,\n * there is a structure of the following type:\n */\n\ntypedef struct MaintainContainer {\n    Tk_Window ancestor;\t\t/* The lowest ancestor of this window for\n\t\t\t\t * which we have *not* created a\n\t\t\t\t * StructureNotify handler. May be the same as\n\t\t\t\t * the window itself. */\n    int checkScheduled;\t\t/* Non-zero means that there is already a call\n\t\t\t\t * to MaintainCheckProc scheduled as an idle\n\t\t\t\t * handler. */\n    MaintainContent *contentPtr;\t/* First in list of all content associated with\n\t\t\t\t * this container. */\n} MaintainContainer;\n\n/*\n * Prototypes for static procedures in this file:\n */\n\nstatic void\t\tMaintainCheckProc(void *clientData);\nstatic void\t\tMaintainContainerProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tMaintainContentProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ManageGeometry --\n *\n *\tArrange for a particular procedure to manage the geometry of a given\n *\tcontent window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProc becomes the new geometry manager for tkwin, replacing any\n *\tprevious geometry manager. The geometry manager will be notified (by\n *\tcalling procedures in *mgrPtr) when interesting things happen in the\n *\tfuture. If there was an existing geometry manager for tkwin different\n *\tfrom the new one, it is notified by calling its lostContentProc.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_ManageGeometry(\n    Tk_Window tkwin,\t\t/* Window whose geometry is to be managed by\n\t\t\t\t * proc. */\n    const Tk_GeomMgr *mgrPtr,\t/* Static structure describing the geometry\n\t\t\t\t * manager. This structure must never go\n\t\t\t\t * away. */\n    void *clientData)\t/* Arbitrary one-word argument to pass to\n\t\t\t\t * geometry manager procedures. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)\n\t    && ((winPtr->geomMgrPtr != mgrPtr)\n\t\t|| (winPtr->geomData != clientData))\n\t    && (winPtr->geomMgrPtr->lostContentProc != NULL)) {\n\twinPtr->geomMgrPtr->lostContentProc(winPtr->geomData, tkwin);\n    }\n\n    winPtr->geomMgrPtr = mgrPtr;\n    winPtr->geomData = clientData;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GeometryRequest --\n *\n *\tThis procedure is invoked by widget code to indicate its preferences\n *\tabout the size of a window it manages. In general, widget code should\n *\tcall this procedure rather than Tk_ResizeWindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe geometry manager for tkwin (if any) is invoked to handle the\n *\trequest. If possible, it will reconfigure tkwin and/or other windows\n *\tto satisfy the request. The caller gets no indication of success or\n *\tfailure, but it will get X events if the window size was actually\n *\tchanged.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_GeometryRequest(\n    Tk_Window tkwin,\t\t/* Window that geometry information pertains\n\t\t\t\t * to. */\n    int reqWidth, int reqHeight)/* Minimum desired dimensions for window, in\n\t\t\t\t * pixels. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    /*\n     * X gets very upset if a window requests a width or height of zero, so\n     * rounds requested sizes up to at least 1.\n     */\n\n    if (reqWidth <= 0) {\n\treqWidth = 1;\n    }\n    if (reqHeight <= 0) {\n\treqHeight = 1;\n    }\n    if ((reqWidth == winPtr->reqWidth) && (reqHeight == winPtr->reqHeight)) {\n\treturn;\n    }\n    winPtr->reqWidth = reqWidth;\n    winPtr->reqHeight = reqHeight;\n    if ((winPtr->geomMgrPtr != NULL)\n\t    && (winPtr->geomMgrPtr->requestProc != NULL)) {\n\twinPtr->geomMgrPtr->requestProc(winPtr->geomData, tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetInternalBorderEx --\n *\n *\tNotify relevant geometry managers that a window has an internal border\n *\tof a given width and that child windows should not be placed on that\n *\tborder.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe border widths are recorded for the window, and all geometry\n *\tmanagers of all children are notified so that can re-layout, if\n *\tnecessary.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetInternalBorderEx(\n    Tk_Window tkwin,\t\t/* Window that will have internal border. */\n    int left, int right,\t/* Width of internal border, in pixels. */\n    int top, int bottom)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    int changed = 0;\n\n    if (left < 0) {\n\tleft = 0;\n    }\n    if (left != winPtr->internalBorderLeft) {\n\twinPtr->internalBorderLeft = left;\n\tchanged = 1;\n    }\n\n    if (right < 0) {\n\tright = 0;\n    }\n    if (right != winPtr->internalBorderRight) {\n\twinPtr->internalBorderRight = right;\n\tchanged = 1;\n    }\n\n    if (top < 0) {\n\ttop = 0;\n    }\n    if (top != winPtr->internalBorderTop) {\n\twinPtr->internalBorderTop = top;\n\tchanged = 1;\n    }\n\n    if (bottom < 0) {\n\tbottom = 0;\n    }\n    if (bottom != winPtr->internalBorderBottom) {\n\twinPtr->internalBorderBottom = bottom;\n\tchanged = 1;\n    }\n\n    /*\n     * All the content for which this is the container window must now be\n     * repositioned to take account of the new internal border width. To\n     * signal all the geometry managers to do this, trigger a ConfigureNotify\n     * event. This will cause geometry managers to recompute everything.\n     */\n\n    if (changed) {\n\tTkDoConfigureNotify(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetInternalBorder --\n *\n *\tNotify relevant geometry managers that a window has an internal border\n *\tof a given width and that child windows should not be placed on that\n *\tborder.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe border width is recorded for the window, and all geometry managers\n *\tof all children are notified so that can re-layout, if necessary.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetInternalBorder(\n    Tk_Window tkwin,\t\t/* Window that will have internal border. */\n    int width)\t\t\t/* Width of internal border, in pixels. */\n{\n    Tk_SetInternalBorderEx(tkwin, width, width, width, width);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetMinimumRequestSize --\n *\n *\tNotify relevant geometry managers that a window has a minimum request\n *\tsize.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe minimum request size is recorded for the window, and a new size is\n *\trequested for the window, if necessary.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetMinimumRequestSize(\n    Tk_Window tkwin,\t\t/* Window that will have internal border. */\n    int minWidth, int minHeight)/* Minimum requested size, in pixels. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if ((winPtr->minReqWidth == minWidth) &&\n\t    (winPtr->minReqHeight == minHeight)) {\n\treturn;\n    }\n\n    winPtr->minReqWidth = minWidth;\n    winPtr->minReqHeight = minHeight;\n\n    /*\n     * The changed min size may cause geometry managers to get a different\n     * result, so make them recompute. To signal all the geometry managers to\n     * do this, just resize the window to its current size. The\n     * ConfigureNotify event will cause geometry managers to recompute\n     * everything.\n     */\n\n    Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetGeometryContainer --\n *\n *\tSet a geometry container for this window. Only one container may own\n *\ta window at any time.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe geometry container is recorded for the window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkSetGeometryContainer(\n    Tcl_Interp *interp,\t\t/* Current interpreter, for error. */\n    Tk_Window tkwin,\t\t/* Window that will have geometry container\n\t\t\t\t * set. */\n    const char *name)\t\t/* The name of the geometry manager. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (winPtr->geomMgrName != NULL &&\n\t    strcmp(winPtr->geomMgrName, name) == 0) {\n\treturn TCL_OK;\n    }\n    if (winPtr->geomMgrName != NULL) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"cannot use geometry manager \\\"%s\\\" inside \\\"%s\\\":\"\n\t\t    \" %s is already managing its content windows\",\n\t\t    name, Tk_PathName(tkwin), winPtr->geomMgrName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"FIGHT\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    winPtr->geomMgrName = (char *)Tcl_Alloc(strlen(name) + 1);\n    strcpy(winPtr->geomMgrName, name);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFreeGeometryContainer --\n *\n *\tRemove a geometry container for this window. Only one container may own\n *\ta window at any time.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe geometry container is cleared for the window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkFreeGeometryContainer(\n    Tk_Window tkwin,\t\t/* Window that will have geometry container\n\t\t\t\t * cleared. */\n    const char *name)\t\t/* The name of the geometry manager. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (winPtr->geomMgrName != NULL &&\n\t    strcmp(winPtr->geomMgrName, name) != 0) {\n\tTcl_Panic(\"Trying to free %s from geometry manager %s\",\n\t\twinPtr->geomMgrName, name);\n    }\n    if (winPtr->geomMgrName != NULL) {\n\tTcl_Free(winPtr->geomMgrName);\n\twinPtr->geomMgrName = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MaintainGeometry --\n *\n *\tThis procedure is invoked by geometry managers to handle content whose\n *\tcontainer's are not their parents. It translates the desired geometry for\n *\tthe content into the coordinate system of the parent and respositions\n *\tthe content if it isn't already at the right place. Furthermore, it sets\n *\tup event handlers so that if the container (or any of its ancestors up to\n *\tthe content's parent) is mapped, unmapped, or moved, then the content will\n *\tbe adjusted to match.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEvent handlers are created and state is allocated to keep track of\n *\tcontent. Note: if content was already managed for container by\n *\tTk_MaintainGeometry, then the previous information is replaced with\n *\tthe new information. The caller must eventually call\n *\tTk_UnmaintainGeometry to eliminate the correspondence (or, the state\n *\tis automatically freed when either window is destroyed).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MaintainGeometry(\n    Tk_Window window,\t\t/* Window for geometry management. */\n    Tk_Window container,\t\t/* Container for window; must be a descendant of\n\t\t\t\t * window's parent. */\n    int x, int y,\t\t/* Desired position of window within container. */\n    int width, int height)\t/* Desired dimensions for window. */\n{\n    Tcl_HashEntry *hPtr;\n    MaintainContainer *containerPtr;\n    MaintainContent *contentPtr;\n    int isNew, map;\n    Tk_Window ancestor, parent;\n    TkDisplay *dispPtr = ((TkWindow *) container)->dispPtr;\n\n    ((TkWindow *)window)->maintainerPtr = (TkWindow *)container;\n\n    if (container == Tk_Parent(window)) {\n\t/*\n\t * If the window is a direct descendant of the container, don't bother\n\t * setting up the extra infrastructure for management, just make a\n\t * call to Tk_MoveResizeWindow; the parent/child relationship will\n\t * take care of the rest.\n\t */\n\n\tTk_MoveResizeWindow(window, x, y, width, height);\n\n\t/*\n\t * Map the window if the container is already mapped; otherwise, wait\n\t * until the container is mapped later (in which case mapping the window\n\t * is taken care of elsewhere).\n\t */\n\n\tif (Tk_IsMapped(container)) {\n\t    Tk_MapWindow(window);\n\t}\n\treturn;\n    }\n\n    if (!dispPtr->geomInit) {\n\tdispPtr->geomInit = 1;\n\tTcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);\n    }\n\n    /*\n     * See if there is already a MaintainContainer structure for the container; if\n     * not, then create one.\n     */\n\n    parent = Tk_Parent(window);\n    hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable,\n\t    (char *) container, &isNew);\n    if (!isNew) {\n\tcontainerPtr = (MaintainContainer *)Tcl_GetHashValue(hPtr);\n    } else {\n\tcontainerPtr = (MaintainContainer *)Tcl_Alloc(sizeof(MaintainContainer));\n\tcontainerPtr->ancestor = container;\n\tcontainerPtr->checkScheduled = 0;\n\tcontainerPtr->contentPtr = NULL;\n\tTcl_SetHashValue(hPtr, containerPtr);\n    }\n\n    /*\n     * Create a MaintainContent structure for the window if there isn't already\n     * one.\n     */\n\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tif (contentPtr->content == window) {\n\t    goto gotContent;\n\t}\n    }\n    contentPtr = (MaintainContent *)Tcl_Alloc(sizeof(MaintainContent));\n    contentPtr->content = window;\n    contentPtr->container = container;\n    contentPtr->nextPtr = containerPtr->contentPtr;\n    containerPtr->contentPtr = contentPtr;\n    Tk_CreateEventHandler(window, StructureNotifyMask, MaintainContentProc,\n\t    contentPtr);\n\n    /*\n     * Make sure that there are event handlers registered for all the windows\n     * between container and windows's parent (including container but not window's\n     * parent). There may already be handlers for container and some of its\n     * ancestors (containerPtr->ancestor tells how many).\n     */\n\n    for (ancestor = container; ancestor != parent;\n\t    ancestor = Tk_Parent(ancestor)) {\n\tif (ancestor == containerPtr->ancestor) {\n\t    Tk_CreateEventHandler(ancestor, StructureNotifyMask,\n\t\t    MaintainContainerProc, containerPtr);\n\t    containerPtr->ancestor = Tk_Parent(ancestor);\n\t}\n    }\n\n    /*\n     * Fill in up-to-date information in the structure, then update the window\n     * if it's not currently in the right place or state.\n     */\n\n  gotContent:\n    contentPtr->x = x;\n    contentPtr->y = y;\n    contentPtr->width = width;\n    contentPtr->height = height;\n    map = 1;\n    for (ancestor = contentPtr->container; ; ancestor = Tk_Parent(ancestor)) {\n\tif (!Tk_IsMapped(ancestor) && (ancestor != parent)) {\n\t    map = 0;\n\t}\n\tif (ancestor == parent) {\n\t    if ((x != Tk_X(contentPtr->content))\n\t\t    || (y != Tk_Y(contentPtr->content))\n\t\t    || (width != Tk_Width(contentPtr->content))\n\t\t    || (height != Tk_Height(contentPtr->content))) {\n\t\tTk_MoveResizeWindow(contentPtr->content, x, y, width, height);\n\t    }\n\t    if (map) {\n\t\tTk_MapWindow(contentPtr->content);\n\t    } else {\n\t\tTk_UnmapWindow(contentPtr->content);\n\t    }\n\t    break;\n\t}\n\tx += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;\n\ty += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UnmaintainGeometry --\n *\n *\tThis procedure cancels a previous Tk_MaintainGeometry call, so that\n *\tthe relationship between window and container is no longer maintained.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is unmapped and state is released, so that window won't track\n *\tcontainer any more. If we weren't previously managing window relative to\n *\tcontainer, then this procedure has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UnmaintainGeometry(\n    Tk_Window window,\t\t/* Window for geometry management. */\n    Tk_Window container)\t\t/* Container for window; must be a descendant of\n\t\t\t\t * window's parent. */\n{\n    Tcl_HashEntry *hPtr;\n    MaintainContainer *containerPtr;\n    MaintainContent *contentPtr, *prevPtr;\n    Tk_Window ancestor;\n    TkDisplay *dispPtr = ((TkWindow *) window)->dispPtr;\n\n    ((TkWindow *)window)->maintainerPtr = NULL;\n\n    if (container == Tk_Parent(window)) {\n\t/*\n\t * If the window is a direct descendant of the container,\n\t * Tk_MaintainGeometry will not have set up any of the extra\n\t * infrastructure. Don't even bother to look for it, just return.\n\t */\n\treturn;\n    }\n\n    if (!dispPtr->geomInit) {\n\tdispPtr->geomInit = 1;\n\tTcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);\n    }\n\n    if (!(((TkWindow *) window)->flags & TK_ALREADY_DEAD)) {\n\tTk_UnmapWindow(window);\n    }\n    hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, container);\n    if (hPtr == NULL) {\n\treturn;\n    }\n    containerPtr = (MaintainContainer *)Tcl_GetHashValue(hPtr);\n    contentPtr = containerPtr->contentPtr;\n    if (contentPtr->content == window) {\n\tcontainerPtr->contentPtr = contentPtr->nextPtr;\n    } else {\n\tfor (prevPtr = contentPtr, contentPtr = contentPtr->nextPtr; ;\n\t\tprevPtr = contentPtr, contentPtr = contentPtr->nextPtr) {\n\t    if (contentPtr == NULL) {\n\t\treturn;\n\t    }\n\t    if (contentPtr->content == window) {\n\t\tprevPtr->nextPtr = contentPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    Tk_DeleteEventHandler(contentPtr->content, StructureNotifyMask,\n\t    MaintainContentProc, contentPtr);\n    Tcl_Free(contentPtr);\n    if (containerPtr->contentPtr == NULL) {\n\tif (containerPtr->ancestor != NULL) {\n\t    for (ancestor = container; ; ancestor = Tk_Parent(ancestor)) {\n\t\tTk_DeleteEventHandler(ancestor, StructureNotifyMask,\n\t\t\tMaintainContainerProc, containerPtr);\n\t\tif (ancestor == containerPtr->ancestor) {\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (containerPtr->checkScheduled) {\n\t    Tcl_CancelIdleCall(MaintainCheckProc, containerPtr);\n\t}\n\tTcl_DeleteHashEntry(hPtr);\n\tTcl_Free(containerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MaintainContainerProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher in response to\n *\tStructureNotify events on the container or one of its ancestors, on\n *\tbehalf of Tk_MaintainGeometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIt schedules a call to MaintainCheckProc, which will eventually caused\n *\tthe postions and mapped states to be recalculated for all the\n *\tmaintained windows of the container. Or, if the container window is being\n *\tdeleted then state is cleaned up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMaintainContainerProc(\n    void *clientData,\t/* Pointer to MaintainContainer structure for the\n\t\t\t\t * container window. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    MaintainContainer *containerPtr = (MaintainContainer *)clientData;\n    MaintainContent *contentPtr;\n    int done;\n\n    if ((eventPtr->type == ConfigureNotify)\n\t    || (eventPtr->type == MapNotify)\n\t    || (eventPtr->type == UnmapNotify)) {\n\tif (!containerPtr->checkScheduled) {\n\t    containerPtr->checkScheduled = 1;\n\t    Tcl_DoWhenIdle(MaintainCheckProc, containerPtr);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * Delete all of the state associated with this container, but be careful\n\t * not to use containerPtr after the last window is deleted, since its\n\t * memory will have been freed.\n\t */\n\n\tdone = 0;\n\tdo {\n\t    contentPtr = containerPtr->contentPtr;\n\t    if (contentPtr->nextPtr == NULL) {\n\t\tdone = 1;\n\t    }\n\t    Tk_UnmaintainGeometry(contentPtr->content, contentPtr->container);\n\t} while (!done);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MaintainContentProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher in response to\n *\tStructureNotify events on a window being managed by\n *\tTk_MaintainGeometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf the event is a DestroyNotify event then the Maintain state and\n *\tevent handlers for this window are deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMaintainContentProc(\n    void *clientData,\t/* Pointer to MaintainContent structure for\n\t\t\t\t * container-window pair. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    MaintainContent *contentPtr = (MaintainContent *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tTk_UnmaintainGeometry(contentPtr->content, contentPtr->container);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MaintainCheckProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher as an idle\n *\thandler, when a container or one of its ancestors has been reconfigured,\n *\tmapped, or unmapped. Its job is to scan all of the windows for the\n *\tcontainer and reposition them, map them, or unmap them as needed to\n *\tmaintain their geometry relative to the container.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWindows can get repositioned, mapped, or unmapped.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMaintainCheckProc(\n    void *clientData)\t/* Pointer to MaintainContainer structure for the\n\t\t\t\t * container window. */\n{\n    MaintainContainer *containerPtr = (MaintainContainer *)clientData;\n    MaintainContent *contentPtr;\n    Tk_Window ancestor, parent;\n    int x, y, map;\n\n    containerPtr->checkScheduled = 0;\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tparent = Tk_Parent(contentPtr->content);\n\tx = contentPtr->x;\n\ty = contentPtr->y;\n\tmap = 1;\n\tfor (ancestor = contentPtr->container; ; ancestor = Tk_Parent(ancestor)) {\n\t    if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {\n\t\tmap = 0;\n\t    }\n\t    if (ancestor == parent) {\n\t\tif ((x != Tk_X(contentPtr->content))\n\t\t\t|| (y != Tk_Y(contentPtr->content))) {\n\t\t    Tk_MoveWindow(contentPtr->content, x, y);\n\t\t}\n\t\tif (map) {\n\t\t    Tk_MapWindow(contentPtr->content);\n\t\t} else {\n\t\t    Tk_UnmapWindow(contentPtr->content);\n\t\t}\n\t\tbreak;\n\t    }\n\t    x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;\n\t    y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkGet.c",
    "content": "/*\n * tkGet.c --\n *\n *\tThis file contains a number of \"Tk_GetXXX\" procedures, which parse\n *\ttext strings into useful forms for Tk. This file has the simpler\n *\tfunctions, like Tk_GetDirection and Tk_GetUid. The more complex\n *\tfunctions like Tk_GetColor are in separate files.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * One of these structures is created per thread to store thread-specific\n * data. In this case, it is used to house the Tk_Uid structs used by each\n * thread. The \"dataKey\" below is used to locate the ThreadSpecificData for\n * the current thread.\n */\n\ntypedef struct {\n    bool initialized;\n    Tcl_HashTable uidTable;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\nstatic void\t\tFreeUidThreadExitProc(void *clientData);\n\n/*\n * The following tables defines the string values for reliefs, which are\n * used by Tk_GetAnchorFromObj and Tk_GetJustifyFromObj.\n */\n\nconst char *const tkAnchorStrings[] = {\n    \"n\", \"ne\", \"e\", \"se\", \"s\", \"sw\", \"w\", \"nw\", \"center\", NULL\n};\nconst char *const tkJustifyStrings[] = {\n    \"left\", \"right\", \"center\", NULL\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetAnchorFromObj --\n *\n *\tReturn a Tk_Anchor value based on the value of the objPtr.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tThe object gets converted by Tcl_GetIndexFromObj.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetAnchorFromObj(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tcl_Obj *objPtr,\t\t/* The object we are trying to get the value\n\t\t\t\t * from. */\n    Tk_Anchor *anchorPtr)\t/* Where to place the Tk_Anchor that\n\t\t\t\t * corresponds to the string value of\n\t\t\t\t * objPtr. */\n{\n    int index, code;\n\n    code = Tcl_GetIndexFromObj(interp, objPtr, tkAnchorStrings, \"anchor\", 0,\n\t    &index);\n    if (code == TCL_OK) {\n\t*anchorPtr = (Tk_Anchor) index;\n    }\n    return code;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetAnchor --\n *\n *\tGiven a string, return the corresponding Tk_Anchor.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the position is stored at\n *\t*anchorPtr; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetAnchor(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    const char *string,\t\t/* String describing a direction. */\n    Tk_Anchor *anchorPtr)\t/* Where to store Tk_Anchor corresponding to\n\t\t\t\t * string. */\n{\n    switch (string[0]) {\n    case 'n':\n\tif (string[1] == 0) {\n\t    *anchorPtr = TK_ANCHOR_N;\n\t    return TCL_OK;\n\t} else if ((string[1] == 'e') && (string[2] == 0)) {\n\t    *anchorPtr = TK_ANCHOR_NE;\n\t    return TCL_OK;\n\t} else if ((string[1] == 'w') && (string[2] == 0)) {\n\t    *anchorPtr = TK_ANCHOR_NW;\n\t    return TCL_OK;\n\t}\n\tgoto error;\n    case 's':\n\tif (string[1] == 0) {\n\t    *anchorPtr = TK_ANCHOR_S;\n\t    return TCL_OK;\n\t} else if ((string[1] == 'e') && (string[2] == 0)) {\n\t    *anchorPtr = TK_ANCHOR_SE;\n\t    return TCL_OK;\n\t} else if ((string[1] == 'w') && (string[2] == 0)) {\n\t    *anchorPtr = TK_ANCHOR_SW;\n\t    return TCL_OK;\n\t} else {\n\t    goto error;\n\t}\n    case 'e':\n\tif (string[1] == 0) {\n\t    *anchorPtr = TK_ANCHOR_E;\n\t    return TCL_OK;\n\t}\n\tgoto error;\n    case 'w':\n\tif (string[1] == 0) {\n\t    *anchorPtr = TK_ANCHOR_W;\n\t    return TCL_OK;\n\t}\n\tgoto error;\n    case 'c':\n\tif (strncmp(string, \"center\", strlen(string)) == 0) {\n\t    *anchorPtr = TK_ANCHOR_CENTER;\n\t    return TCL_OK;\n\t}\n\tgoto error;\n    }\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad anchor \\\"%s\\\": must be\"\n\t    \" n, ne, e, se, s, sw, w, nw, or center\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"ANCHOR\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfAnchor --\n *\n *\tGiven a Tk_Anchor, return the string that corresponds to it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfAnchor(\n    Tk_Anchor anchor)\t\t/* Anchor for which identifying string is\n\t\t\t\t * desired. */\n{\n    switch (anchor) {\n    case TK_ANCHOR_N: return \"n\";\n    case TK_ANCHOR_NE: return \"ne\";\n    case TK_ANCHOR_E: return \"e\";\n    case TK_ANCHOR_SE: return \"se\";\n    case TK_ANCHOR_S: return \"s\";\n    case TK_ANCHOR_SW: return \"sw\";\n    case TK_ANCHOR_W: return \"w\";\n    case TK_ANCHOR_NW: return \"nw\";\n    case TK_ANCHOR_CENTER: return \"center\";\n    case TK_ANCHOR_NULL: return \"\";\n    }\n    return \"unknown anchor position\";\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetJoinStyle --\n *\n *\tGiven a string, return the corresponding Tk JoinStyle.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the justification is stored at\n *\t*joinPtr; otherwise TCL_ERROR is returned and an error message is left\n *\tin the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetJoinStyle(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    const char *string,\t\t/* String describing a justification style. */\n    int *joinPtr)\t\t/* Where to store join style corresponding to\n\t\t\t\t * string. */\n{\n    int c;\n    size_t length;\n\n    c = string[0];\n    length = strlen(string);\n\n    if ((c == 'b') && (strncmp(string, \"bevel\", length) == 0)) {\n\t*joinPtr = JoinBevel;\n\treturn TCL_OK;\n    }\n    if ((c == 'm') && (strncmp(string, \"miter\", length) == 0)) {\n\t*joinPtr = JoinMiter;\n\treturn TCL_OK;\n    }\n    if ((c == 'r') && (strncmp(string, \"round\", length) == 0)) {\n\t*joinPtr = JoinRound;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad join style \\\"%s\\\": must be bevel, miter, or round\",\n\t    string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"JOIN\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfJoinStyle --\n *\n *\tGiven a Tk JoinStyle, return the string that corresponds to it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfJoinStyle(\n    int join)\t\t\t/* Join style for which identifying string is\n\t\t\t\t * desired. */\n{\n    switch (join) {\n    case JoinBevel: return \"bevel\";\n    case JoinMiter: return \"miter\";\n    case JoinRound: return \"round\";\n    }\n    return \"unknown join style\";\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetCapStyle --\n *\n *\tGiven a string, return the corresponding Tk CapStyle.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the justification is stored at\n *\t*capPtr; otherwise TCL_ERROR is returned and an error message is left\n *\tin the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetCapStyle(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    const char *string,\t\t/* String describing a justification style. */\n    int *capPtr)\t\t/* Where to store cap style corresponding to\n\t\t\t\t * string. */\n{\n    int c;\n    size_t length;\n\n    c = string[0];\n    length = strlen(string);\n\n    if ((c == 'b') && (strncmp(string, \"butt\", length) == 0)) {\n\t*capPtr = CapButt;\n\treturn TCL_OK;\n    }\n    if ((c == 'p') && (strncmp(string, \"projecting\", length) == 0)) {\n\t*capPtr = CapProjecting;\n\treturn TCL_OK;\n    }\n    if ((c == 'r') && (strncmp(string, \"round\", length) == 0)) {\n\t*capPtr = CapRound;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad cap style \\\"%s\\\": must be butt, projecting, or round\",\n\t    string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CAP\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfCapStyle --\n *\n *\tGiven a Tk CapStyle, return the string that corresponds to it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfCapStyle(\n    int cap)\t\t\t/* Cap style for which identifying string is\n\t\t\t\t * desired. */\n{\n    switch (cap) {\n    case CapButt: return \"butt\";\n    case CapProjecting: return \"projecting\";\n    case CapRound: return \"round\";\n    }\n    return \"unknown cap style\";\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetJustifyFromObj --\n *\n *\tReturn a Tk_Justify value based on the value of the objPtr.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tThe object gets converted by Tcl_GetIndexFromObj.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetJustifyFromObj(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tcl_Obj *objPtr,\t\t/* The object we are trying to get the value\n\t\t\t\t * from. */\n    Tk_Justify *justifyPtr)\t/* Where to place the Tk_Justify that\n\t\t\t\t * corresponds to the string value of\n\t\t\t\t * objPtr. */\n{\n    int index, code;\n\n    code = Tcl_GetIndexFromObj(interp, objPtr, tkJustifyStrings,\n\t    \"justification\", 0, &index);\n    if (code == TCL_OK) {\n\t*justifyPtr = (Tk_Justify) index;\n    }\n    return code;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetJustify --\n *\n *\tGiven a string, return the corresponding Tk_Justify.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the justification is stored at\n *\t*justifyPtr; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetJustify(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    const char *string,\t\t/* String describing a justification style. */\n    Tk_Justify *justifyPtr)\t/* Where to store Tk_Justify corresponding to\n\t\t\t\t * string. */\n{\n    int c;\n    size_t length;\n\n    c = string[0];\n    length = strlen(string);\n\n    if ((c == 'l') && (strncmp(string, \"left\", length) == 0)) {\n\t*justifyPtr = TK_JUSTIFY_LEFT;\n\treturn TCL_OK;\n    }\n    if ((c == 'r') && (strncmp(string, \"right\", length) == 0)) {\n\t*justifyPtr = TK_JUSTIFY_RIGHT;\n\treturn TCL_OK;\n    }\n    if ((c == 'c') && (strncmp(string, \"center\", length) == 0)) {\n\t*justifyPtr = TK_JUSTIFY_CENTER;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad justification \\\"%s\\\": must be left, right, or center\",\n\t    string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"JUSTIFY\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_NameOfJustify --\n *\n *\tGiven a Tk_Justify, return the string that corresponds\n *\tto it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfJustify(\n    Tk_Justify justify)\t\t/* Justification style for which identifying\n\t\t\t\t * string is desired. */\n{\n    switch (justify) {\n    case TK_JUSTIFY_LEFT: return \"left\";\n    case TK_JUSTIFY_RIGHT: return \"right\";\n    case TK_JUSTIFY_CENTER: return \"center\";\n    case TK_JUSTIFY_NULL: return \"\";\n    }\n    return \"unknown justification style\";\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeUidThreadExitProc --\n *\n *\tCleans up memory used for Tk_Uids in the thread.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll information in the identifier table is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeUidThreadExitProc(\n    TCL_UNUSED(void *))\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    Tcl_DeleteHashTable(&tsdPtr->uidTable);\n    tsdPtr->initialized = false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetUid --\n *\n *\tGiven a string, this function returns a unique identifier for the\n *\tstring.\n *\n * Results:\n *\tThis function returns a Tk_Uid corresponding to the \"string\" argument.\n *\tThe Tk_Uid has a string value identical to string (strcmp will return\n *\t0), but it's guaranteed that any other calls to this function with a\n *\tstring equal to \"string\" will return exactly the same result (i.e. can\n *\tcompare Tk_Uid *values* directly, without having to call strcmp on\n *\twhat they point to).\n *\n * Side effects:\n *\tNew information may be entered into the identifier table.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Uid\nTk_GetUid(\n    const char *string)\t\t/* String to convert. */\n{\n    int dummy;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashTable *tablePtr = &tsdPtr->uidTable;\n\n    if (!tsdPtr->initialized) {\n\tTcl_InitHashTable(tablePtr, TCL_STRING_KEYS);\n\tTcl_CreateThreadExitHandler(FreeUidThreadExitProc, NULL);\n\ttsdPtr->initialized = true;\n    }\n    return (Tk_Uid) Tcl_GetHashKey(tablePtr,\n\t    Tcl_CreateHashEntry(tablePtr, string, &dummy));\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetScreenMM --\n *\n *\tGiven a string, returns the number of screen millimeters corresponding\n *\tto that string.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the screen distance is stored\n *\tat *doublePtr; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetScreenMM(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    Tk_Window tkwin,\t\t/* Window whose screen determines conversion\n\t\t\t\t * from centimeters and other absolute\n\t\t\t\t * units. */\n    const char *string,\t\t/* String describing a screen distance. */\n    double *doublePtr)\t\t/* Place to store converted result. */\n{\n    const char *rest;\n    double d;\n    Tcl_DString ds;\n\n    if (Tcl_GetDouble(NULL, string, &d) == TCL_OK) {\n\tif (!tkwin) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"bad screen\", -1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SCREEN_DISTANCE\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\td /= WidthOfScreen(Tk_Screen(tkwin));\n\td *= WidthMMOfScreen(Tk_Screen(tkwin));\n\t*doublePtr = d;\n\treturn TCL_OK;\n    }\n    rest = string + strlen(string);\n    while ((rest > string) && isspace(UCHAR(rest[-1]))) {\n\t--rest; /* skip all spaces at the end */\n    }\n    if (rest > string) {\n\t--rest; /* point to the character just before the last space */\n    }\n\tif (rest == string) {\n\terror:\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"expected screen distance or \\\"\\\" but got \\\"%.50s\\\"\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, string, rest-string);\n    if (Tcl_GetDouble(NULL, Tcl_DStringValue(&ds), &d) != TCL_OK) {\n\tTcl_DStringFree(&ds);\n\tgoto error;\n    }\n    Tcl_DStringFree(&ds);\n    switch (*rest) {\n    case 'c':\n\td *= 10;\n\tbreak;\n    case 'i':\n\td *= 25.4;\n\tbreak;\n    case 'm':\n\tbreak;\n    case 'p':\n\td *= 25.4/72.0;\n\tbreak;\n    default:\n\tgoto error;\n    }\n    *doublePtr = d;\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetPixels --\n *\n *\tGiven a string, returns the number of pixels corresponding to that\n *\tstring.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the rounded pixel distance is\n *\tstored at *intPtr; otherwise TCL_ERROR is returned and an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetPixels(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    Tk_Window tkwin,\t\t/* Window whose screen determines conversion\n\t\t\t\t * from centimeters and other absolute\n\t\t\t\t * units. */\n    const char *string,\t\t/* String describing a number of pixels. */\n    int *intPtr)\t\t/* Place to store converted result. */\n{\n    double d;\n\n    if (TkGetDoublePixels(interp, tkwin, string, &d) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (d < 0) {\n\t*intPtr = (int) (d - 0.5);\n    } else {\n\t*intPtr = (int) (d + 0.5);\n    }\n    return TCL_OK;\n}\n/*\n *--------------------------------------------------------------\n *\n * TkGetDoublePixels --\n *\n *\tGiven a string, returns the number of pixels corresponding to that\n *\tstring.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the pixel distance is stored\n *\tat *doublePtr; otherwise TCL_ERROR is returned and an error message is\n *\tleft in interp->result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkGetDoublePixels(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    Tk_Window tkwin,\t\t/* Window whose screen determines conversion\n\t\t\t\t * from centimeters and other absolute\n\t\t\t\t * units. */\n    const char *string,\t\t/* String describing a number of pixels. */\n    double *doublePtr)\t\t/* Place to store converted result. */\n{\n    const char *rest;\n    double d;\n    Tcl_DString ds;\n\n    if (Tcl_GetDouble(NULL, string, &d) == TCL_OK) {\n\t*doublePtr = d;\n\treturn TCL_OK;\n    }\n    if (!tkwin) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"bad screen\", -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"FRACTIONAL_PIXELS\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    rest = string + strlen(string);\n    while ((rest > string) && isspace(UCHAR(rest[-1]))) {\n\t--rest; /* skip all spaces at the end */\n    }\n    if (rest > string) {\n\t--rest; /* point to the character just before the last space */\n    }\n\tif (rest == string) {\n\terror:\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"expected screen distance but got \\\"%.50s\\\"\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, string, rest-string);\n    if (Tcl_GetDouble(NULL, Tcl_DStringValue(&ds), &d) != TCL_OK) {\n\tTcl_DStringFree(&ds);\n\tgoto error;\n    }\n    Tcl_DStringFree(&ds);\n    switch (*rest) {\n    case 'c':\n\td *= 10*WidthOfScreen(Tk_Screen(tkwin));\n\td /= WidthMMOfScreen(Tk_Screen(tkwin));\n\tbreak;\n    case 'i':\n\td *= 25.4*WidthOfScreen(Tk_Screen(tkwin));\n\td /= WidthMMOfScreen(Tk_Screen(tkwin));\n\tbreak;\n    case 'm':\n\td *= WidthOfScreen(Tk_Screen(tkwin));\n\td /= WidthMMOfScreen(Tk_Screen(tkwin));\n\tbreak;\n    case 'p':\n\td *= (25.4/72.0)*WidthOfScreen(Tk_Screen(tkwin));\n\td /= WidthMMOfScreen(Tk_Screen(tkwin));\n\tbreak;\n    default:\n\tgoto error;\n    }\n    *doublePtr = d;\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkGrab.c",
    "content": "/*\n * tkGrab.c --\n *\n *\tThis file provides functions that implement grabs for Tk.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif !defined(MAC_OSX_TK)\n#include \"tkUnixInt.h\"\n#else\n#include \"tkMacOSXInt.h\"\n#endif\n\n/*\n * The grab state machine has four states: ungrabbed, button pressed, grabbed,\n * and button pressed while grabbed. In addition, there are three pieces of\n * grab state information: the current grab window, the current restrict\n * window, and whether the mouse is captured.\n *\n * The current grab window specifies the point in the Tk window hierarchy\n * above which pointer events will not be reported. Any window within the\n * subtree below the grab window will continue to receive events as normal.\n * Events outside of the grab tree will be reported to the grab window.\n *\n * If the current restrict window is set, then all pointer events will be\n * reported only to the restrict window. The restrict window is normally set\n * during an automatic button grab.\n *\n * The mouse capture state specifies whether the window system will report\n * mouse events outside of any Tk toplevels. This is set during a global grab\n * or an automatic button grab.\n *\n * The transitions between different states is given in the following table:\n *\n * Event\\State\tU\tB\tG\tGB\n * -----------\t--\t--\t--\t--\n * FirstPress\tB\tB\tGB\tGB\n * Press\tB\tB\tG\tGB\n * Release\tU\tB\tG\tGB\n * LastRelease\tU\tU\tG\tG\n * Grab\t\tG\tG\tG\tG\n * Ungrab\tU\tB\tU\tU\n *\n * Note: U=Ungrabbed, B=Button, G=Grabbed, GB=Grab and Button\n *\n * In addition, the following conditions are always true:\n *\n * State\\Variable\tGrab\t     Restrict\t     Capture\n * --------------\t----\t     --------\t     -------\n * Ungrabbed\t\t 0\t\t0\t\t0\n * Button\t\t 0\t\t1\t\t1\n * Grabbed\t\t 1\t\t0\t\tb/g\n * Grab and Button\t 1\t\t1\t\t1\n *\n * Note: 0 means variable is set to NULL, 1 means variable is set to some\n * window, b/g means the variable is set to a window if a button is currently\n * down or a global grab is in effect.\n *\n * The final complication to all of this is enter and leave events. In order\n * to correctly handle all of the various cases, Tk cannot rely on X\n * enter/leave events in all situations. The following describes the correct\n * sequence of enter and leave events that should be observed by Tk scripts:\n *\n * Event(state)\t\tEnter/Leave From -> To\n * ------------\t\t----------------------\n * LastRelease(B | GB): restrict window -> anc(grab window, event window)\n * Grab(U | B):\tevent window -> anc(grab window, event window)\n * Grab(G):\t\tanc(old grab window, event window) ->\n *\t\t\t\tanc(new grab window, event window)\n * Grab(GB):\t\trestrict window -> anc(new grab window, event window)\n * Ungrab(G):\t\tanc(grab window, event window) -> event window\n * Ungrab(GB):\t\trestrict window -> event window\n *\n * Note: anc(x,y) returns the least ancestor of y that is in the tree of x,\n * terminating at toplevels.\n */\n\n/*\n * The following structure is used to pass information to GrabRestrictProc\n * from EatGrabEvents.\n */\n\ntypedef struct {\n    Display *display;\t\t/* Display from which to discard events. */\n    unsigned int serial;\t/* Serial number with which to compare. */\n} GrabInfo;\n\n/*\n * Bit definitions for grabFlags field of TkDisplay structures:\n *\n * GRAB_GLOBAL\t\t\t1 means this is a global grab (we grabbed via\n *\t\t\t\tthe server so all applications are locked out).\n *\t\t\t\t0 means this is a local grab that affects only\n *\t\t\t\tthis application.\n * GRAB_TEMP_GLOBAL\t\t1 means we've temporarily grabbed via the\n *\t\t\t\tserver because a button is down and we want to\n *\t\t\t\tmake sure that we get the button-up event. The\n *\t\t\t\tgrab will be released when the last mouse\n *\t\t\t\tbutton goes up.\n */\n\n#define GRAB_GLOBAL\t\t1\n#define GRAB_TEMP_GLOBAL\t4\n\n/*\n * The following structure is a Tcl_Event that triggers a change in the\n * grabWinPtr field of a display. This event guarantees that the change occurs\n * in the proper order relative to enter and leave events.\n */\n\ntypedef struct NewGrabWinEvent {\n    Tcl_Event header;\t\t/* Standard information for all Tcl events. */\n    TkDisplay *dispPtr;\t\t/* Display whose grab window is to change. */\n    Window grabWindow;\t\t/* New grab window for display. This is\n\t\t\t\t * recorded instead of a (TkWindow *) because\n\t\t\t\t * it will allow us to detect cases where the\n\t\t\t\t * window is destroyed before this event is\n\t\t\t\t * processed. */\n} NewGrabWinEvent;\n\n/*\n * The following magic value is stored in the \"send_event\" field of\n * EnterNotify and LeaveNotify events that are generated in this file. This\n * allows us to separate \"real\" events coming from the server from those that\n * we generated.\n */\n\n#define GENERATED_GRAB_EVENT_MAGIC ((Bool) 0x147321ac)\n\n/*\n * Forward declarations for functions declared later in this file:\n */\n\nstatic void\t\tEatGrabEvents(TkDisplay *dispPtr, unsigned int serial);\nstatic TkWindow *\tFindCommonAncestor(TkWindow *winPtr1,\n\t\t\t    TkWindow *winPtr2, int *countPtr1, int *countPtr2);\nstatic Tk_RestrictProc GrabRestrictProc;\nstatic int\t\tGrabWinEventProc(Tcl_Event *evPtr, int flags);\nstatic void\t\tMovePointer2(TkWindow *sourcePtr, TkWindow *destPtr,\n\t\t\t    int mode, int leaveEvents, int EnterEvents);\nstatic void\t\tQueueGrabWindowChange(TkDisplay *dispPtr,\n\t\t\t    TkWindow *grabWinPtr);\nstatic void\t\tReleaseButtonGrab(TkDisplay *dispPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GrabObjCmd --\n *\n *\tThis function is invoked to process the \"grab\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GrabObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int globalGrab;\n    Tk_Window tkwin;\n    TkDisplay *dispPtr;\n    const char *arg;\n    int index;\n    Tcl_Size len;\n    static const char *const optionStrings[] = {\n\t\"current\", \"release\", \"set\", \"status\", NULL\n    };\n    static const char *const flagStrings[] = {\n\t\"-global\", NULL\n    };\n    enum options {\n\tGRABCMD_CURRENT, GRABCMD_RELEASE, GRABCMD_SET, GRABCMD_STATUS\n    };\n\n    if (objc < 2) {\n\t/*\n\t * Can't use Tcl_WrongNumArgs here because we want the message to\n\t * read:\n\t * wrong # args: should be \"cmd ?-global? window\" or \"cmd option\n\t *    ?arg ...?\"\n\t * We can fake it with Tcl_WrongNumArgs if we assume the command name\n\t * is \"grab\", but if it has been aliased, the message will be\n\t * incorrect.\n\t */\n\n\tTcl_WrongNumArgs(interp, 1, objv, \"?-global? window\");\n\tTcl_AppendResult(interp, \" or \\\"\", Tcl_GetString(objv[0]),\n\t\t\" option ?arg ...?\\\"\", (char *)NULL);\n\t/* This API not exposed:\n\t *\n\t((Interp *) interp)->flags |= INTERP_ALTERNATE_WRONG_ARGS;\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\t */\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * First check for a window name or \"-global\" as the first argument.\n     */\n\n    arg = Tcl_GetStringFromObj(objv[1], &len);\n    if (arg[0] == '.') {\n\t/* [grab window] */\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"?-global? window\");\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_NameToWindow(interp, arg, (Tk_Window)clientData);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\treturn Tk_Grab(interp, tkwin, 0);\n    } else if (arg[0] == '-' && len > 1) {\n\tif (Tcl_GetIndexFromObj(interp, objv[1], flagStrings, \"option\", 0,\n\t\t&index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/* [grab -global window] */\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"?-global? window\");\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), (Tk_Window)clientData);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\treturn Tk_Grab(interp, tkwin, 1);\n    }\n\n    /*\n     * First argument is not a window name and not \"-global\", find out which\n     * option it is.\n     */\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case GRABCMD_CURRENT:\n\t/* [grab current ?window?] */\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"current ?window?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 3) {\n\t    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),\n\t\t    (Tk_Window)clientData);\n\t    if (tkwin == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\t    if (dispPtr->eventualGrabWinPtr != NULL) {\n\t\tTcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window)\n\t\t\tdispPtr->eventualGrabWinPtr));\n\t    }\n\t} else {\n\t    Tcl_Obj *resultObj = Tcl_NewObj();\n\n\t    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t\t    dispPtr = dispPtr->nextPtr) {\n\t\tif (dispPtr->eventualGrabWinPtr != NULL) {\n\t\t    Tcl_ListObjAppendElement(NULL, resultObj, Tk_NewWindowObj(\n\t\t\t    (Tk_Window) dispPtr->eventualGrabWinPtr));\n\t\t}\n\t    }\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\treturn TCL_OK;\n\n    case GRABCMD_RELEASE:\n\t/* [grab release window] */\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"release window\");\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), (Tk_Window)clientData);\n\tif (tkwin == NULL) {\n\t    Tcl_ResetResult(interp);\n\t} else {\n\t    Tk_Ungrab(tkwin);\n\t}\n\tbreak;\n\n    case GRABCMD_SET:\n\t/* [grab set ?-global? window] */\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"set ?-global? window\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 3) {\n\t    globalGrab = 0;\n\t    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),\n\t\t    (Tk_Window)clientData);\n\t} else {\n\t    globalGrab = 1;\n\n\t    /*\n\t     * We could just test the argument by hand instead of using\n\t     * Tcl_GetIndexFromObj; the benefit of using the function is that\n\t     * it sets up the error message for us, so we are certain to be\n\t     * consistant with the rest of Tcl.\n\t     */\n\n\t    if (Tcl_GetIndexFromObj(interp, objv[2], flagStrings, \"option\",\n\t\t    0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[3]),\n\t\t    (Tk_Window)clientData);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\treturn Tk_Grab(interp, tkwin, globalGrab);\n\n    case GRABCMD_STATUS: {\n\t/* [grab status window] */\n\tTkWindow *winPtr;\n\tconst char *statusString;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"status window\");\n\t    return TCL_ERROR;\n\t}\n\twinPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]),\n\t\t(Tk_Window)clientData);\n\tif (winPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tdispPtr = winPtr->dispPtr;\n\tif (dispPtr->eventualGrabWinPtr != winPtr) {\n\t    statusString = \"none\";\n\t} else if (dispPtr->grabFlags & GRAB_GLOBAL) {\n\t    statusString = \"global\";\n\t} else {\n\t    statusString = \"local\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(statusString, TCL_INDEX_NONE));\n\tbreak;\n    }\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Grab --\n *\n *\tGrabs the pointer and keyboard, so that mouse-related events are only\n *\treported relative to a given window and its descendants.\n *\n * Results:\n *\tA standard Tcl result is returned. TCL_OK is the normal return value;\n *\tif the grab could not be set then TCL_ERROR is returned and the\n *\tinterp's result will hold an error message.\n *\n * Side effects:\n *\tOnce this call completes successfully, no window outside the tree\n *\trooted at tkwin will receive pointer- or keyboard-related events until\n *\tthe next call to Tk_Ungrab. If a previous grab was in effect within\n *\tthis application, then it is replaced with a new one.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_Grab(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Window tkwin,\t\t/* Window on whose behalf the pointer is to be\n\t\t\t\t * grabbed. */\n    int grabGlobal)\t\t/* Non-zero means issue a grab to the server\n\t\t\t\t * so that no other application gets mouse or\n\t\t\t\t * keyboard events. Zero means the grab only\n\t\t\t\t * applies within this application. */\n{\n    int grabResult, numTries;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkWindow *winPtr2;\n    unsigned int serial;\n\n    ReleaseButtonGrab(dispPtr);\n    if (dispPtr->eventualGrabWinPtr != NULL) {\n\tif ((dispPtr->eventualGrabWinPtr == winPtr)\n\t\t&& (grabGlobal == ((dispPtr->grabFlags & GRAB_GLOBAL) != 0))) {\n\t    return TCL_OK;\n\t}\n\tif (dispPtr->eventualGrabWinPtr->mainPtr != winPtr->mainPtr) {\n\t    goto alreadyGrabbed;\n\t}\n\tTk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);\n    }\n\n    Tk_MakeWindowExist(tkwin);\n    if (!grabGlobal) {\n\tWindow dummy1, dummy2;\n\tint dummy3, dummy4, dummy5, dummy6;\n\tunsigned int state;\n\n\t/*\n\t * Local grab. However, if any mouse buttons are down, turn it into a\n\t * global grab temporarily, until the last button goes up. This does\n\t * two things: (a) it makes sure that we see the button-up event; and\n\t * (b) it allows us to track mouse motion among all of the windows of\n\t * this application.\n\t */\n\n\tdispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);\n\tXQueryPointer(dispPtr->display, winPtr->window, &dummy1,\n\t\t&dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &state);\n\tif (state & ALL_BUTTONS) {\n\t    dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;\n\t    goto setGlobalGrab;\n\t}\n    } else {\n\tdispPtr->grabFlags |= GRAB_GLOBAL;\n    setGlobalGrab:\n\n\t/*\n\t * Tricky point: must ungrab before grabbing. This is needed in case\n\t * there is a button auto-grab already in effect. If there is, and the\n\t * mouse has moved to a different window, X won't generate enter and\n\t * leave events to move the mouse if we grab without ungrabbing.\n\t */\n\n\tXUngrabPointer(dispPtr->display, CurrentTime);\n\tserial = NextRequest(dispPtr->display);\n\n\t/*\n\t * Another tricky point: there are races with some window managers\n\t * that can cause grabs to fail because the window manager hasn't\n\t * released its grab quickly enough. To work around this problem,\n\t * retry a few times after AlreadyGrabbed errors to give the grab\n\t * release enough time to register with the server.\n\t */\n\n\tgrabResult = 0;\t\t\t/* Needed only to prevent gcc compiler\n\t\t\t\t\t * warnings. */\n\tfor (numTries = 0; numTries < 10; numTries++) {\n\t    grabResult = XGrabPointer(dispPtr->display, winPtr->window,\n\t\t    True, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask\n\t\t    |PointerMotionMask, GrabModeAsync, GrabModeAsync, None,\n\t\t    None, CurrentTime);\n\t    if (grabResult != AlreadyGrabbed) {\n\t\tbreak;\n\t    }\n\t    Tcl_Sleep(100);\n\t}\n\tif (grabResult != 0) {\n\t    goto grabError;\n\t}\n\tgrabResult = XGrabKeyboard(dispPtr->display, Tk_WindowId(tkwin),\n\t\tFalse, GrabModeAsync, GrabModeAsync, CurrentTime);\n\tif (grabResult != 0) {\n\t    XUngrabPointer(dispPtr->display, CurrentTime);\n\t    goto grabError;\n\t}\n\n\t/*\n\t * Eat up any grab-related events generated by the server for the\n\t * grab. There are several reasons for doing this:\n\t *\n\t * 1. We have to synthesize the events for local grabs anyway, since\n\t *    the server doesn't participate in them.\n\t * 2. The server doesn't always generate the right events for global\n\t *    grabs (e.g. it generates events even if the current window is in\n\t *    the grab tree, which we don't want).\n\t * 3. We want all the grab-related events to be processed immediately\n\t *    (before other events that are already queued); events coming\n\t *    from the server will be in the wrong place, but events we\n\t *    synthesize here will go to the front of the queue.\n\t */\n\n\tEatGrabEvents(dispPtr, serial);\n    }\n\n    /*\n     * Synthesize leave events to move the pointer from its current window up\n     * to the lowest ancestor that it has in common with the grab window.\n     * However, only do this if the pointer is outside the grab window's\n     * subtree but inside the grab window's application.\n     */\n\n    if ((dispPtr->serverWinPtr != NULL)\n\t    && (dispPtr->serverWinPtr->mainPtr == winPtr->mainPtr)) {\n\tfor (winPtr2 = dispPtr->serverWinPtr; ; winPtr2 = winPtr2->parentPtr) {\n\t    if (winPtr2 == winPtr) {\n\t\tbreak;\n\t    }\n\t    if (winPtr2 == NULL) {\n\t\tMovePointer2(dispPtr->serverWinPtr, winPtr, NotifyGrab, 1, 0);\n\t\tbreak;\n\t    }\n\t}\n    }\n    QueueGrabWindowChange(dispPtr, winPtr);\n    return TCL_OK;\n\n  grabError:\n    if (grabResult == GrabNotViewable) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"grab failed: window not viewable\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRAB\", \"UNVIEWABLE\", (char *)NULL);\n    } else if (grabResult == AlreadyGrabbed) {\n    alreadyGrabbed:\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"grab failed: another application has grab\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRAB\", \"GRABBED\", (char *)NULL);\n    } else if (grabResult == GrabFrozen) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"grab failed: keyboard or pointer frozen\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRAB\", \"FROZEN\", (char *)NULL);\n    } else if (grabResult == GrabInvalidTime) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"grab failed: invalid time\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRAB\", \"BAD_TIME\", (char *)NULL);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"grab failed for unknown reason (code %d)\", grabResult));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRAB\", \"UNKNOWN\", (char *)NULL);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Ungrab --\n *\n *\tReleases a grab on the mouse pointer and keyboard, if there is one set\n *\ton the specified window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPointer and keyboard events will start being delivered to other\n *\twindows again.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_Ungrab(\n    Tk_Window tkwin)\t\t/* Window whose grab should be released. */\n{\n    TkDisplay *dispPtr;\n    TkWindow *grabWinPtr, *winPtr;\n    unsigned int serial;\n\n    grabWinPtr = (TkWindow *) tkwin;\n    dispPtr = grabWinPtr->dispPtr;\n    if (grabWinPtr != dispPtr->eventualGrabWinPtr) {\n\treturn;\n    }\n    ReleaseButtonGrab(dispPtr);\n    QueueGrabWindowChange(dispPtr, NULL);\n    if (dispPtr->grabFlags & (GRAB_GLOBAL|GRAB_TEMP_GLOBAL)) {\n\tdispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);\n\tserial = NextRequest(dispPtr->display);\n\tXUngrabPointer(dispPtr->display, CurrentTime);\n\tXUngrabKeyboard(dispPtr->display, CurrentTime);\n\tEatGrabEvents(dispPtr, serial);\n    }\n\n    /*\n     * Generate events to move the pointer back to the window where it really\n     * is. Some notes:\n     * 1. As with grabs, only do this if the \"real\" window is not a descendant\n     *    of the grab window, since in this case the pointer is already where\n     *    it's supposed to be.\n     * 2. If the \"real\" window is in some other application then don't\n     *    generate any events at all, since everything's already been reported\n     *    correctly.\n     * 3. Only generate enter events. Don't generate leave events, because we\n     *    never told the lower-level windows that they had the pointer in the\n     *    first place.\n     */\n\n    for (winPtr = dispPtr->serverWinPtr; ; winPtr = winPtr->parentPtr) {\n\tif (winPtr == grabWinPtr) {\n\t    break;\n\t}\n\tif (winPtr == NULL) {\n\t    if ((dispPtr->serverWinPtr == NULL) ||\n\t\t    (dispPtr->serverWinPtr->mainPtr == grabWinPtr->mainPtr)) {\n\t\tMovePointer2(grabWinPtr, dispPtr->serverWinPtr,\n\t\t\tNotifyUngrab, 0, 1);\n\t    }\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReleaseButtonGrab --\n *\n *\tThis function is called to release a simulated button grab, if there\n *\tis one in effect. A button grab is present whenever\n *\tdispPtr->buttonWinPtr is non-NULL or when the GRAB_TEMP_GLOBAL flag is\n *\tset.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDispPtr->buttonWinPtr is reset to NULL, and enter and leave events are\n *\tgenerated if necessary to move the pointer from the button grab window\n *\tto its current window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nReleaseButtonGrab(\n    TkDisplay *dispPtr)/* Display whose button grab is to be\n\t\t\t\t * released. */\n{\n    unsigned int serial;\n\n    if (dispPtr->buttonWinPtr != NULL) {\n\tif (dispPtr->buttonWinPtr != dispPtr->serverWinPtr) {\n\t    MovePointer2(dispPtr->buttonWinPtr, dispPtr->serverWinPtr,\n\t\t    NotifyUngrab, 1, 1);\n\t}\n\tdispPtr->buttonWinPtr = NULL;\n    }\n    if (dispPtr->grabFlags & GRAB_TEMP_GLOBAL) {\n\tdispPtr->grabFlags &= ~GRAB_TEMP_GLOBAL;\n\tserial = NextRequest(dispPtr->display);\n\tXUngrabPointer(dispPtr->display, CurrentTime);\n\tXUngrabKeyboard(dispPtr->display, CurrentTime);\n\tEatGrabEvents(dispPtr, serial);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPointerEvent --\n *\n *\tThis function is called for each pointer-related event, before the\n *\tevent has been processed. It does various things to make grabs work\n *\tcorrectly.\n *\tAlso, this function takes care of warping the mouse pointer with\n *\trespect to a given window, both when there is a grab in effect and\n *\twhen there is none.\n *\n * Results:\n *\tIf the return value is true it means the event should be processed (event\n *\thandlers should be invoked). If the return value is false it means the\n *\tevent should be ignored in order to make grabs work correctly. In some\n *\tcases this function modifies the event.\n *\n * Side effects:\n *\tGrab state information may be updated. New events may also be pushed\n *\tback onto the event queue to replace or augment the one passed in\n *\there.\n *\tThe mouse pointer may be moved.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkPointerEvent(\n    XEvent *eventPtr,\t/* Pointer to the event. */\n    TkWindow *winPtr)\t\t/* Tk's information for window where event was\n\t\t\t\t * reported. */\n{\n    TkWindow *winPtr2;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    unsigned int serial;\n    int outsideGrabTree = 0;\n    int ancestorOfGrab = 0;\n    int appGrabbed = 0;\t\t/* Non-zero means event is being reported to\n\t\t\t\t * an application that is affected by the\n\t\t\t\t * grab. */\n\n    /*\n     * Collect information about the grab (if any).\n     */\n\n    switch (TkGrabState(winPtr)) {\n    case TK_GRAB_IN_TREE:\n\tappGrabbed = 1;\n\tbreak;\n    case TK_GRAB_ANCESTOR:\n\tappGrabbed = 1;\n\toutsideGrabTree = 1;\n\tancestorOfGrab = 1;\n\tbreak;\n    case TK_GRAB_EXCLUDED:\n\tappGrabbed = 1;\n\toutsideGrabTree = 1;\n\tbreak;\n    }\n\n    if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) {\n\t/*\n\t * Keep track of what window the mouse is *really* over. Any events\n\t * that we generate have a special send_event value, which is detected\n\t * below and used to ignore the event for purposes of setting\n\t * serverWinPtr.\n\t */\n\n\tif (eventPtr->xcrossing.send_event != GENERATED_GRAB_EVENT_MAGIC) {\n\t    if ((eventPtr->type == LeaveNotify) &&\n\t\t    (winPtr->flags & TK_TOP_HIERARCHY)) {\n\t\tdispPtr->serverWinPtr = NULL;\n\t    } else {\n\t\tdispPtr->serverWinPtr = winPtr;\n\t    }\n\t}\n\n\t/*\n\t * When a grab is active, X continues to report enter and leave events\n\t * for windows outside the tree of the grab window:\n\t * 1. Detect these events and ignore them except for windows above the\n\t *    grab window.\n\t * 2. Allow Enter and Leave events to pass through the windows above\n\t *    the grab window, but never let them end up with the pointer *in*\n\t *    one of those windows.\n\t */\n\n\tif (dispPtr->grabWinPtr != NULL) {\n\t    if (outsideGrabTree && appGrabbed) {\n\t\tif (!ancestorOfGrab) {\n\t\t    return false;\n\t\t}\n\t\tswitch (eventPtr->xcrossing.detail) {\n\t\tcase NotifyInferior:\n\t\t    return false;\n\t\tcase NotifyAncestor:\n\t\t    eventPtr->xcrossing.detail = NotifyVirtual;\n\t\t    break;\n\t\tcase NotifyNonlinear:\n\t\t    eventPtr->xcrossing.detail = NotifyNonlinearVirtual;\n\t\t    break;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Make buttons have the same grab-like behavior inside a grab as\n\t     * they do outside a grab: do this by ignoring enter and leave\n\t     * events except for the window in which the button was pressed.\n\t     */\n\n\t    if ((dispPtr->buttonWinPtr != NULL)\n\t\t    && (winPtr != dispPtr->buttonWinPtr)) {\n\t\treturn false;\n\t    }\n\t}\n\treturn true;\n    }\n\n    if ((eventPtr->type == MotionNotify) && !appGrabbed) {\n\n\t/*\n\t * Warp the mouse pointer with respect to window dispPtr->warpWindow\n\t * if such a window was set in HandleEventGenerate.\n\t */\n\n\tTkDoWarpWrtWin(dispPtr);\n    }\n\n    if (!appGrabbed) {\n\treturn true;\n    }\n\n    /*\n     * From this point on, there is a grab in effect.\n     */\n\n    if (eventPtr->type == MotionNotify) {\n\t/*\n\t * When grabs are active, X reports motion events relative to the\n\t * window under the pointer. Instead, it should report the events\n\t * relative to the window the button went down in, if there is a\n\t * button down. Otherwise, if the pointer window is outside the\n\t * subtree of the grab window, the events should be reported relative\n\t * to the grab window. Otherwise, the event should be reported to the\n\t * pointer window.\n\t */\n\n\twinPtr2 = winPtr;\n\tif (dispPtr->buttonWinPtr != NULL) {\n\t    winPtr2 = dispPtr->buttonWinPtr;\n\t} else if (outsideGrabTree || (dispPtr->serverWinPtr == NULL)) {\n\t    winPtr2 = dispPtr->grabWinPtr;\n\t}\n\tif (winPtr2 != winPtr) {\n\t    TkChangeEventWindow(eventPtr, winPtr2);\n\t    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);\n\t    return false;\n\t}\n\n\t/*\n\t * Warp the mouse pointer with respect to window dispPtr->warpWindow\n\t * if such a window was set in HandleEventGenerate.\n\t */\n\n\tTkDoWarpWrtWin(dispPtr);\n\treturn true;\n    }\n\n    /*\n     * Process ButtonPress and ButtonRelease events:\n     * 1. Keep track of whether a button is down and what window it went down\n     *    in.\n     * 2. If the first button goes down outside the grab tree, pretend it went\n     *    down in the grab window. Note: it's important to redirect events to\n     *    the grab window like this in order to make things like menus work,\n     *    where button presses outside the grabbed menu need to be seen. An\n     *    application can always ignore the events if they occur outside its\n     *    window.\n     * 3. If a button press or release occurs outside the window where the\n     *    first button was pressed, retarget the event so it's reported to the\n     *    window where the first button was pressed.\n     * 4. If the last button is released in a window different than where the\n     *    first button was pressed, generate Enter/Leave events to move the\n     *    mouse from the button window to its current window.\n     * 5. If the grab is set at a time when a button is already down, or if\n     *    the window where the button was pressed was deleted, then\n     *    dispPtr->buttonWinPtr will stay NULL. Just forget about the\n     *    auto-grab for the button press; events will go to whatever window\n     *    contains the pointer. If this window isn't in the grab tree then\n     *    redirect events to the grab window.\n     * 6. When a button is pressed during a local grab, the X server sets a\n     *    grab of its own, since it doesn't even know about our local grab.\n     *    This causes enter and leave events no longer to be generated in the\n     *    same way as for global grabs. To eliminate this problem, set a\n     *    temporary global grab when the first button goes down and release it\n     *    when the last button comes up.\n     */\n\n    if ((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease)) {\n\twinPtr2 = dispPtr->buttonWinPtr;\n\tif (winPtr2 == NULL) {\n\t    if (outsideGrabTree) {\n\t\twinPtr2 = dispPtr->grabWinPtr;\t\t\t/* Note 5. */\n\t    } else {\n\t\twinPtr2 = winPtr;\t\t\t\t/* Note 5. */\n\t    }\n\t}\n\tif (eventPtr->type == ButtonPress) {\n\t    if (!(eventPtr->xbutton.state & ALL_BUTTONS)) {\n\t\tif (outsideGrabTree) {\n\t\t    TkChangeEventWindow(eventPtr, dispPtr->grabWinPtr);\n\t\t    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);\n\t\t    return false;\t\t\t\t\t/* Note 2. */\n\t\t}\n\t\tif (!(dispPtr->grabFlags & GRAB_GLOBAL)) {\t/* Note 6. */\n\t\t    serial = NextRequest(dispPtr->display);\n\t\t    if (XGrabPointer(dispPtr->display,\n\t\t\t    dispPtr->grabWinPtr->window, True,\n\t\t\t    ButtonPressMask|ButtonReleaseMask|ButtonMotionMask,\n\t\t\t    GrabModeAsync, GrabModeAsync, None, None,\n\t\t\t    CurrentTime) == 0) {\n\t\t\tEatGrabEvents(dispPtr, serial);\n\t\t\tif (XGrabKeyboard(dispPtr->display, winPtr->window,\n\t\t\t\tFalse, GrabModeAsync, GrabModeAsync,\n\t\t\t\tCurrentTime) == 0) {\n\t\t\t    dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;\n\t\t\t} else {\n\t\t\t    XUngrabPointer(dispPtr->display, CurrentTime);\n\t\t\t}\n\t\t    }\n\t\t}\n\t\tdispPtr->buttonWinPtr = winPtr;\n\t\treturn true;\n\t    }\n\t} else {\n\t    if (eventPtr->xbutton.button != AnyButton &&\n\t\t    ((eventPtr->xbutton.state & ALL_BUTTONS)\n\t\t    == Tk_GetButtonMask(eventPtr->xbutton.button))) {\n\t\tReleaseButtonGrab(dispPtr);\t\t\t/* Note 4. */\n\t    }\n\t}\n\tif (winPtr2 != winPtr) {\n\t    TkChangeEventWindow(eventPtr, winPtr2);\n\t    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);\n\t    return false;\t\t\t\t\t\t/* Note 3. */\n\t}\n    }\n\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkChangeEventWindow --\n *\n *\tGiven an event and a new window to which the event should be\n *\tretargeted, modify fields of the event so that the event is properly\n *\tretargeted to the new window.\n *\n * Results:\n *\tThe following fields of eventPtr are modified: window, subwindow, x,\n *\ty, same_screen.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkChangeEventWindow(\n    XEvent *eventPtr,\t/* Event to retarget. Must have type\n\t\t\t\t * ButtonPress, ButtonRelease, KeyPress,\n\t\t\t\t * KeyRelease, MotionNotify, EnterNotify, or\n\t\t\t\t * LeaveNotify. */\n    TkWindow *winPtr)\t\t/* New target window for event. */\n{\n    int x, y, sameScreen, bd;\n    TkWindow *childPtr;\n\n    eventPtr->xmotion.window = Tk_WindowId(winPtr);\n    if (eventPtr->xmotion.root ==\n\t    RootWindow(winPtr->display, winPtr->screenNum)) {\n\tTk_GetRootCoords((Tk_Window) winPtr, &x, &y);\n\teventPtr->xmotion.x = eventPtr->xmotion.x_root - x;\n\teventPtr->xmotion.y = eventPtr->xmotion.y_root - y;\n\teventPtr->xmotion.subwindow = None;\n\tfor (childPtr = winPtr->childList; childPtr != NULL;\n\t\tchildPtr = childPtr->nextPtr) {\n\t    if (childPtr->flags & TK_TOP_HIERARCHY) {\n\t\tcontinue;\n\t    }\n\t    x = eventPtr->xmotion.x - childPtr->changes.x;\n\t    y = eventPtr->xmotion.y - childPtr->changes.y;\n\t    bd = childPtr->changes.border_width;\n\t    if ((x >= -bd) && (y >= -bd)\n\t\t    && (x < (childPtr->changes.width + bd))\n\t\t    && (y < (childPtr->changes.height + bd))) {\n\t\teventPtr->xmotion.subwindow = childPtr->window;\n\t    }\n\t}\n\tsameScreen = 1;\n    } else {\n\teventPtr->xmotion.x = 0;\n\teventPtr->xmotion.y = 0;\n\teventPtr->xmotion.subwindow = None;\n\tsameScreen = 0;\n    }\n    if (eventPtr->type == MotionNotify) {\n\teventPtr->xmotion.same_screen = sameScreen;\n    } else {\n\teventPtr->xbutton.same_screen = sameScreen;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkInOutEvents --\n *\n *\tThis function synthesizes EnterNotify and LeaveNotify events to\n *\tcorrectly transfer the pointer from one window to another. It can also\n *\tbe used to generate FocusIn and FocusOut events to move the input\n *\tfocus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSynthesized events may be pushed back onto the event queue. The event\n *\tpointed to by eventPtr is modified.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkInOutEvents(\n    XEvent *eventPtr,\t\t/* A template X event. Must have all fields\n\t\t\t\t * properly set except for type, window,\n\t\t\t\t * subwindow, x, y, detail, and same_screen.\n\t\t\t\t * (Not all of these fields are valid for\n\t\t\t\t * FocusIn/FocusOut events; x_root and y_root\n\t\t\t\t * must be valid for Enter/Leave events, even\n\t\t\t\t * though x and y needn't be valid). */\n    TkWindow *sourcePtr,\t/* Window that used to have the pointer or\n\t\t\t\t * focus (NULL means it was not in a window\n\t\t\t\t * managed by this process). */\n    TkWindow *destPtr,\t\t/* Window that is to end up with the pointer\n\t\t\t\t * or focus (NULL means it's not one managed\n\t\t\t\t * by this process). */\n    int leaveType,\t\t/* Type of events to generate for windows\n\t\t\t\t * being left (LeaveNotify or FocusOut). 0\n\t\t\t\t * means don't generate leave events. */\n    int enterType,\t\t/* Type of events to generate for windows\n\t\t\t\t * being entered (EnterNotify or FocusIn). 0\n\t\t\t\t * means don't generate enter events. */\n    Tcl_QueuePosition position)\t/* Position at which events are added to the\n\t\t\t\t * system event queue. */\n{\n    TkWindow *winPtr;\n    int upLevels, downLevels, i, j, focus;\n\n    /*\n     * There are four possible cases to deal with:\n     *\n     * 1. SourcePtr and destPtr are the same. There's nothing to do in this\n     *    case.\n     * 2. SourcePtr is an ancestor of destPtr in the same top-level window.\n     *    Must generate events down the window tree from source to dest.\n     * 3. DestPtr is an ancestor of sourcePtr in the same top-level window.\n     *    Must generate events up the window tree from sourcePtr to destPtr.\n     * 4. All other cases. Must first generate events up the window tree from\n     *    sourcePtr to its top-level, then down from destPtr's top-level to\n     *    destPtr. This form is called \"non-linear.\"\n     *\n     * The call to FindCommonAncestor separates these four cases and decides\n     * how many levels up and down events have to be generated for.\n     */\n\n    if (sourcePtr == destPtr) {\n\treturn;\n    }\n    if ((leaveType == FocusOut) || (enterType == FocusIn)) {\n\tfocus = 1;\n    } else {\n\tfocus = 0;\n    }\n    FindCommonAncestor(sourcePtr, destPtr, &upLevels, &downLevels);\n\n    /*\n     * Generate enter/leave events and add them to the grab event queue.\n     */\n\n#define QUEUE(w, t, d)\t\t\t\t\t\\\n    if (w->window != None) {\t\t\t\t\\\n\teventPtr->type = t;\t\t\t\t\\\n\tif (focus) {\t\t\t\t\t\\\n\t    eventPtr->xfocus.window = w->window;\t\\\n\t    eventPtr->xfocus.detail = d;\t\t\\\n\t} else {\t\t\t\t\t\\\n\t    eventPtr->xcrossing.detail = d;\t\t\\\n\t    TkChangeEventWindow(eventPtr, w);\t\t\\\n\t}\t\t\t\t\t\t\\\n\tTk_QueueWindowEvent(eventPtr, position);\t\\\n    }\n\n    if (downLevels == 0) {\n\t/*\n\t * SourcePtr is an inferior of destPtr.\n\t */\n\n\tif (leaveType != 0) {\n\t    QUEUE(sourcePtr, leaveType, NotifyAncestor);\n\t    for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;\n\t\t    winPtr = winPtr->parentPtr, i--) {\n\t\tQUEUE(winPtr, leaveType, NotifyVirtual);\n\t    }\n\t}\n\tif ((enterType != 0) && (destPtr != NULL)) {\n\t    QUEUE(destPtr, enterType, NotifyInferior);\n\t}\n    } else if (upLevels == 0) {\n\t/*\n\t * DestPtr is an inferior of sourcePtr.\n\t */\n\n\tif ((leaveType != 0) && (sourcePtr != NULL)) {\n\t    QUEUE(sourcePtr, leaveType, NotifyInferior);\n\t}\n\tif (enterType != 0) {\n\t    for (i = downLevels-1; i > 0; i--) {\n\t\tfor (winPtr = destPtr->parentPtr, j = 1; j < i;\n\t\t\twinPtr = winPtr->parentPtr, j++) {\n\t\t    /* empty */\n\t\t}\n\t\tQUEUE(winPtr, enterType, NotifyVirtual);\n\t    }\n\t    if (destPtr != NULL) {\n\t\tQUEUE(destPtr, enterType, NotifyAncestor);\n\t    }\n\t}\n    } else {\n\t/*\n\t * Non-linear: neither window is an inferior of the other.\n\t */\n\n\tif (leaveType != 0) {\n\t    QUEUE(sourcePtr, leaveType, NotifyNonlinear);\n\t    for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;\n\t\t    winPtr = winPtr->parentPtr, i--) {\n\t\tQUEUE(winPtr, leaveType, NotifyNonlinearVirtual);\n\t    }\n\t}\n\tif (enterType != 0) {\n\t    for (i = downLevels-1; i > 0; i--) {\n\t\tfor (winPtr = destPtr->parentPtr, j = 1; j < i;\n\t\t\twinPtr = winPtr->parentPtr, j++) {\n\t\t}\n\t\tQUEUE(winPtr, enterType, NotifyNonlinearVirtual);\n\t    }\n\t    if (destPtr != NULL) {\n\t\tQUEUE(destPtr, enterType, NotifyNonlinear);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MovePointer2 --\n *\n *\tThis function synthesizes EnterNotify and LeaveNotify events to\n *\tcorrectly transfer the pointer from one window to another. It is\n *\tdifferent from TkInOutEvents in that no template X event needs to be\n *\tsupplied; this function generates the template event and calls\n *\tTkInOutEvents.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSynthesized events may be pushed back onto the event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMovePointer2(\n    TkWindow *sourcePtr,\t/* Window currently containing pointer (NULL\n\t\t\t\t * means it's not one managed by this\n\t\t\t\t * process). */\n    TkWindow *destPtr,\t\t/* Window that is to end up containing the\n\t\t\t\t * pointer (NULL means it's not one managed by\n\t\t\t\t * this process). */\n    int mode,\t\t\t/* Mode for enter/leave events, such as\n\t\t\t\t * NotifyNormal or NotifyUngrab. */\n    int leaveEvents,\t\t/* Non-zero means generate leave events for\n\t\t\t\t * the windows being left. Zero means don't\n\t\t\t\t * generate leave events. */\n    int enterEvents)\t\t/* Non-zero means generate enter events for\n\t\t\t\t * the windows being entered. Zero means don't\n\t\t\t\t * generate enter events. */\n{\n    XEvent event;\n    Window dummy1, dummy2;\n    int dummy3, dummy4;\n    TkWindow *winPtr;\n\n    winPtr = sourcePtr;\n    if ((winPtr == NULL) || (winPtr->window == None)) {\n\twinPtr = destPtr;\n\tif ((winPtr == NULL) || (winPtr->window == None)) {\n\t    return;\n\t}\n    }\n\n    event.xcrossing.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xcrossing.send_event = GENERATED_GRAB_EVENT_MAGIC;\n    event.xcrossing.display = winPtr->display;\n    event.xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);\n    event.xcrossing.time = TkCurrentTime(winPtr->dispPtr);\n    XQueryPointer(winPtr->display, winPtr->window, &dummy1, &dummy2,\n\t    &event.xcrossing.x_root, &event.xcrossing.y_root,\n\t    &dummy3, &dummy4, &event.xcrossing.state);\n    event.xcrossing.mode = mode;\n    event.xcrossing.focus = False;\n    TkInOutEvents(&event, sourcePtr, destPtr, (leaveEvents) ? LeaveNotify : 0,\n\t    (enterEvents) ? EnterNotify : 0, TCL_QUEUE_MARK);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGrabDeadWindow --\n *\n *\tThis function is invoked whenever a window is deleted, so that\n *\tgrab-related cleanup can be performed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tVarious cleanups happen, such as generating events to move the pointer\n *\tback to its \"natural\" window as if an ungrab had been done. See the\n *\tcode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGrabDeadWindow(\n    TkWindow *winPtr)\t/* Window that is in the process of being\n\t\t\t\t * deleted. */\n{\n    TkDisplay *dispPtr = winPtr->dispPtr;\n\n    if (dispPtr->eventualGrabWinPtr == winPtr) {\n\t/*\n\t * Grab window was deleted. Release the grab.\n\t */\n\n\tTk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);\n    } else if (dispPtr->buttonWinPtr == winPtr) {\n\tReleaseButtonGrab(dispPtr);\n    }\n    if (dispPtr->serverWinPtr == winPtr) {\n\tif (winPtr->flags & TK_TOP_HIERARCHY) {\n\t    dispPtr->serverWinPtr = NULL;\n\t} else {\n\t    dispPtr->serverWinPtr = winPtr->parentPtr;\n\t}\n    }\n    if (dispPtr->grabWinPtr == winPtr) {\n\tdispPtr->grabWinPtr = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EatGrabEvents --\n *\n *\tThis function is called to eliminate any Enter, Leave, FocusIn, or\n *\tFocusOut events in the event queue for a display that have mode\n *\tNotifyGrab or NotifyUngrab and have a serial number no less than a\n *\tgiven value and are not generated by the grab module.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDispPtr's display gets sync-ed, and some of the events get removed\n *\tfrom the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEatGrabEvents(\n    TkDisplay *dispPtr,\t\t/* Display from which to consume events. */\n    unsigned int serial)\t/* Only discard events that have a serial\n\t\t\t\t * number at least this great. */\n{\n    Tk_RestrictProc *prevProc;\n    GrabInfo info;\n    void *prevArg;\n\n    info.display = dispPtr->display;\n    info.serial = serial;\n    TkpSync(info.display);\n    prevProc = Tk_RestrictEvents(GrabRestrictProc, &info, &prevArg);\n    while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {\n\t/* EMPTY */\n    }\n    Tk_RestrictEvents(prevProc, prevArg, &prevArg);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GrabRestrictProc --\n *\n *\tA Tk_RestrictProc used by EatGrabEvents to eliminate any Enter, Leave,\n *\tFocusIn, or FocusOut events in the event queue for a display that has\n *\tmode NotifyGrab or NotifyUngrab and have a serial number no less than\n *\ta given value.\n *\n * Results:\n *\tReturns either TK_DISCARD_EVENT or TK_DEFER_EVENT.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_RestrictAction\nGrabRestrictProc(\n    void *arg,\n    XEvent *eventPtr)\n{\n    GrabInfo *info = (GrabInfo *)arg;\n    int mode, diff;\n\n    /*\n     * The diff caculation is trickier than it may seem. Don't forget that\n     * serial numbers can wrap around, so can't compare the two serial numbers\n     * directly.\n     */\n\n    diff = eventPtr->xany.serial - info->serial;\n    if ((eventPtr->type == EnterNotify)\n\t    || (eventPtr->type == LeaveNotify)) {\n\tmode = eventPtr->xcrossing.mode;\n    } else if ((eventPtr->type == FocusIn)\n\t    || (eventPtr->type == FocusOut)) {\n\tmode = eventPtr->xfocus.mode;\n    } else {\n\tmode = NotifyNormal;\n    }\n    if ((info->display != eventPtr->xany.display) || (mode == NotifyNormal)\n\t    || (diff < 0)) {\n\treturn TK_DEFER_EVENT;\n    } else {\n\treturn TK_DISCARD_EVENT;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * QueueGrabWindowChange --\n *\n *\tThis function queues a special event in the Tcl event queue, which\n *\twill cause the \"grabWinPtr\" field for the display to get modified when\n *\tthe event is processed. This is needed to make sure that the grab\n *\twindow changes at the proper time relative to grab-related enter and\n *\tleave events that are also in the queue. In particular, this approach\n *\tworks even when multiple grabs and ungrabs happen back-to-back.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDispPtr->grabWinPtr will be modified later (by GrabWinEventProc) when\n *\tthe event is removed from the grab event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nQueueGrabWindowChange(\n    TkDisplay *dispPtr,\t\t/* Display on which to change the grab\n\t\t\t\t * window. */\n    TkWindow *grabWinPtr)\t/* Window that is to become the new grab\n\t\t\t\t * window (may be NULL). */\n{\n    NewGrabWinEvent *grabEvPtr;\n\n    grabEvPtr = (NewGrabWinEvent *)Tcl_Alloc(sizeof(NewGrabWinEvent));\n    grabEvPtr->header.proc = GrabWinEventProc;\n    grabEvPtr->dispPtr = dispPtr;\n    if (grabWinPtr == NULL) {\n\tgrabEvPtr->grabWindow = None;\n    } else {\n\tgrabEvPtr->grabWindow = grabWinPtr->window;\n    }\n    Tcl_QueueEvent(&grabEvPtr->header, TCL_QUEUE_MARK);\n    dispPtr->eventualGrabWinPtr = grabWinPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GrabWinEventProc --\n *\n *\tThis function is invoked as a handler for Tcl_Events of type\n *\tNewGrabWinEvent. It updates the current grab window field in a\n *\tdisplay.\n *\n * Results:\n *\tReturns 1 if the event was processed, 0 if it should be deferred for\n *\tprocessing later.\n *\n * Side effects:\n *\tThe grabWinPtr field is modified in the display associated with the\n *\tevent.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGrabWinEventProc(\n    Tcl_Event *evPtr,\t\t/* Event of type NewGrabWinEvent. */\n    TCL_UNUSED(int))\t\t\t/* Flags argument to Tcl_DoOneEvent: indicates\n\t\t\t\t * what kinds of events are being processed\n\t\t\t\t * right now. */\n{\n    NewGrabWinEvent *grabEvPtr = (NewGrabWinEvent *) evPtr;\n\n    grabEvPtr->dispPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(\n\t    grabEvPtr->dispPtr->display, grabEvPtr->grabWindow);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindCommonAncestor --\n *\n *\tGiven two windows, this function finds their least common ancestor and\n *\talso computes how many levels up this ancestor is from each of the\n *\toriginal windows.\n *\n * Results:\n *\tIf the windows are in different applications or top-level windows,\n *\tthen NULL is returned and *countPtr1 and *countPtr2 are set to the\n *\tdepths of the two windows in their respective top-level windows (1\n *\tmeans the window is a top-level, 2 means its parent is a top-level,\n *\tand so on). Otherwise, the return value is a pointer to the common\n *\tancestor and the counts are set to the distance of winPtr1 and winPtr2\n *\tfrom this ancestor (1 means they're children, 2 means grand-children,\n *\tetc.).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkWindow *\nFindCommonAncestor(\n    TkWindow *winPtr1,\t\t/* First window. May be NULL. */\n    TkWindow *winPtr2,\t\t/* Second window. May be NULL. */\n    int *countPtr1,\t\t/* Store nesting level of winPtr1 within\n\t\t\t\t * common ancestor here. */\n    int *countPtr2)\t\t/* Store nesting level of winPtr2 within\n\t\t\t\t * common ancestor here. */\n{\n    TkWindow *winPtr;\n    TkWindow *ancestorPtr;\n    int count1, count2, i;\n\n    /*\n     * Mark winPtr1 and all of its ancestors with a special flag bit.\n     */\n\n    if (winPtr1 != NULL) {\n\tfor (winPtr = winPtr1; winPtr != NULL; winPtr = winPtr->parentPtr) {\n\t    winPtr->flags |= TK_GRAB_FLAG;\n\t    if (winPtr->flags & TK_TOP_HIERARCHY) {\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * Search upwards from winPtr2 until an ancestor of winPtr1 is found or a\n     * top-level window is reached.\n     */\n\n    winPtr = winPtr2;\n    count2 = 0;\n    ancestorPtr = NULL;\n    if (winPtr2 != NULL) {\n\tfor (; winPtr != NULL; count2++, winPtr = winPtr->parentPtr) {\n\t    if (winPtr->flags & TK_GRAB_FLAG) {\n\t\tancestorPtr = winPtr;\n\t\tbreak;\n\t    }\n\t    if (winPtr->flags & TK_TOP_HIERARCHY)  {\n\t\tcount2++;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * Search upwards from winPtr1 again, clearing the flag bits and\n     * remembering how many levels up we had to go.\n     */\n\n    if (winPtr1 == NULL) {\n\tcount1 = 0;\n    } else {\n\tcount1 = -1;\n\tfor (i = 0, winPtr = winPtr1; winPtr != NULL;\n\t\ti++, winPtr = winPtr->parentPtr) {\n\t    winPtr->flags &= ~TK_GRAB_FLAG;\n\t    if (winPtr == ancestorPtr) {\n\t\tcount1 = i;\n\t    }\n\t    if (winPtr->flags & TK_TOP_HIERARCHY) {\n\t\tif (count1 == -1) {\n\t\t    count1 = i+1;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    *countPtr1 = count1;\n    *countPtr2 = count2;\n    return ancestorPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPositionInTree --\n *\n *\tCompute where the given window is relative to a particular subtree of\n *\tthe window hierarchy.\n *\n * Results:\n *\tReturns TK_GRAB_IN_TREE if the window is contained in the subtree.\n *\tReturns TK_GRAB_ANCESTOR if the window is an ancestor of the subtree,\n *\tin the same toplevel. Otherwise it returns TK_GRAB_EXCLUDED.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPositionInTree(\n    TkWindow *winPtr,\t\t/* Window to be checked. */\n    TkWindow *treePtr)\t\t/* Root of tree to compare against. */\n{\n    TkWindow *winPtr2;\n\n    for (winPtr2 = winPtr; winPtr2 != treePtr;\n\t   winPtr2 = winPtr2->parentPtr) {\n\tif (winPtr2 == NULL) {\n\t    for (winPtr2 = treePtr; winPtr2 != NULL;\n\t\t    winPtr2 = winPtr2->parentPtr) {\n\t\tif (winPtr2 == winPtr) {\n\t\t    return TK_GRAB_ANCESTOR;\n\t\t}\n\t\tif (winPtr2->flags & TK_TOP_HIERARCHY) {\n\t\t    break;\n\t\t}\n\t    }\n\t    return TK_GRAB_EXCLUDED;\n\t}\n    }\n    return TK_GRAB_IN_TREE;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGrabState --\n *\n *\tGiven a window, this function returns a value that indicates the grab\n *\tstate of the application relative to the window.\n *\n * Results:\n *\tThe return value is one of three things:\n *\t    TK_GRAB_NONE -\tno grab is in effect.\n *\t    TK_GRAB_IN_TREE -   there is a grab in effect, and winPtr is in\n *\t\t\t\tthe grabbed subtree.\n *\t    TK_GRAB_ANCESTOR -  there is a grab in effect; winPtr is an\n *\t\t\t\tancestor of the grabbed window, in the same\n *\t\t\t\ttoplevel.\n *\t    TK_GRAB_EXCLUDED -\tthere is a grab in effect; winPtr is outside\n *\t\t\t\tthe tree of the grab and is not an ancestor of\n *\t\t\t\tthe grabbed window in the same toplevel.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGrabState(\n    TkWindow *winPtr)\t\t/* Window for which grab information is\n\t\t\t\t * needed. */\n{\n    TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;\n\n    if (grabWinPtr == NULL) {\n\treturn TK_GRAB_NONE;\n    }\n    if ((winPtr->mainPtr != grabWinPtr->mainPtr)\n\t    && !(winPtr->dispPtr->grabFlags & GRAB_GLOBAL)) {\n\treturn TK_GRAB_NONE;\n    }\n\n    return TkPositionInTree(winPtr, grabWinPtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkGrid.c",
    "content": "/*\n * tkGrid.c --\n *\n *\tGrid based geometry manager.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Convenience Macros\n */\n\n#ifdef MAX\n#   undef MAX\n#endif\n#define MAX(x,y)\t((x) > (y) ? (x) : (y))\n\n#define COLUMN\t\t(1)\t/* Working on column offsets. */\n#define ROW\t\t(2)\t/* Working on row offsets. */\n\n#define CHECK_ONLY\t(1)\t/* Check max slot constraint. */\n#define CHECK_SPACE\t(2)\t/* Alloc more space, don't change max. */\n\n/*\n * Pre-allocate enough row and column slots for \"typical\" sized tables this\n * value should be chosen so by the time the extra malloc's are required, the\n * layout calculations overwehlm them. [A \"slot\" contains information for\n * either a row or column, depending upon the context.]\n */\n\n#define TYPICAL_SIZE\t25\t/* (Arbitrary guess) */\n#define PREALLOC\t10\t/* Extra slots to allocate. */\n\n/*\n * Pre-allocate room for uniform groups during layout.\n */\n\n#define UNIFORM_PREALLOC 10\n\n/*\n * Data structures are allocated dynamically to support arbitrary sized\n * tables. However, the space is proportional to the highest numbered slot\n * with some non-default property. This limit is used to head off mistakes and\n * denial of service attacks by limiting the amount of storage required.\n */\n\n#define MAX_ELEMENT\t10000\n\n/*\n * Special characters to support relative layouts.\n */\n\n#define REL_SKIP\t'x'\t/* Skip this column. */\n#define REL_HORIZ\t'-'\t/* Extend previous widget horizontally. */\n#define REL_VERT\t'^'\t/* Extend widget from row above. */\n\n/*\n * Default value for 'grid anchor'.\n */\n\n#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW\n\n/*\n * Structure to hold information for grid containers. A slot is either a row or\n * column.\n */\n\ntypedef struct SlotInfo {\n    int minSize;\t\t/* The minimum size of this slot (in pixels).\n\t\t\t\t * It is set via the rowconfigure or\n\t\t\t\t * columnconfigure commands. */\n    int weight;\t\t\t/* The resize weight of this slot. (0) means\n\t\t\t\t * this slot doesn't resize. Extra space in\n\t\t\t\t * the layout is given distributed among slots\n\t\t\t\t * inproportion to their weights. */\n    int pad;\t\t\t/* Extra padding, in pixels, required for this\n\t\t\t\t * slot. This amount is \"added\" to the largest\n\t\t\t\t * content in the slot. */\n    Tk_Uid uniform;\t\t/* Value of -uniform option. It is used to\n\t\t\t\t * group slots that should have the same\n\t\t\t\t * size. */\n    int offset;\t\t\t/* This is a cached value used for\n\t\t\t\t * introspection. It is the pixel offset of\n\t\t\t\t * the right or bottom edge of this slot from\n\t\t\t\t * the beginning of the layout. */\n    int temp;\t\t\t/* This is a temporary value used for\n\t\t\t\t * calculating adjusted weights when shrinking\n\t\t\t\t * the layout below its nominal size. */\n} SlotInfo;\n\n/*\n * Structure to hold information during layout calculations. There is one of\n * these for each slot, an array for each of the rows or columns.\n */\n\ntypedef struct GridLayout {\n    struct Gridder *binNextPtr;\t/* The next content window in this bin. Each bin\n\t\t\t\t * contains a list of all content whose spans\n\t\t\t\t * are >1 and whose right edges fall in this\n\t\t\t\t * slot. */\n    int minSize;\t\t/* Minimum size needed for this slot, in\n\t\t\t\t * pixels. This is the space required to hold\n\t\t\t\t * any content contained entirely in this slot,\n\t\t\t\t * adjusted for any slot constrants, such as\n\t\t\t\t * size or padding. */\n    int pad;\t\t\t/* Padding needed for this slot */\n    int weight;\t\t\t/* Slot weight, controls resizing. */\n    Tk_Uid uniform;\t\t/* Value of -uniform option. It is used to\n\t\t\t\t * group slots that should have the same\n\t\t\t\t * size. */\n    int minOffset;\t\t/* The minimum offset, in pixels, from the\n\t\t\t\t * beginning of the layout to the bottom/right\n\t\t\t\t * edge of the slot calculated from top/left\n\t\t\t\t * to bottom/right. */\n    int maxOffset;\t\t/* The maximum offset, in pixels, from the\n\t\t\t\t * beginning of the layout to the bottom/right\n\t\t\t\t * edge of the slot calculated from\n\t\t\t\t * bottom/right to top/left. */\n} GridLayout;\n\n/*\n * Keep one of these for each geometry container.\n */\n\ntypedef struct {\n    SlotInfo *columnPtr;\t/* Pointer to array of column constraints. */\n    SlotInfo *rowPtr;\t\t/* Pointer to array of row constraints. */\n    int columnEnd;\t\t/* The last column occupied by any content. */\n    int columnMax;\t\t/* The number of columns with constraints. */\n    int columnSpace;\t\t/* The number of slots currently allocated for\n\t\t\t\t * column constraints. */\n    int rowEnd;\t\t\t/* The last row occupied by any content. */\n    int rowMax;\t\t\t/* The number of rows with constraints. */\n    int rowSpace;\t\t/* The number of slots currently allocated for\n\t\t\t\t * row constraints. */\n    int startX;\t\t\t/* Pixel offset of this layout within its\n\t\t\t\t * container. */\n    int startY;\t\t\t/* Pixel offset of this layout within its\n\t\t\t\t * container. */\n    Tk_Anchor anchor;\t\t/* Value of anchor option: specifies where a\n\t\t\t\t * grid without weight should be placed. */\n} GridContainer;\n\n/*\n * For each window that the grid cares about (either because the window is\n * managed by the grid or because the window has content that are managed by\n * the grid), there is a structure of the following type:\n */\n\ntypedef struct Gridder {\n    Tk_Window tkwin;\t\t/* Tk token for window. NULL means that the\n\t\t\t\t * window has been deleted, but the gridder\n\t\t\t\t * hasn't had a chance to clean up yet because\n\t\t\t\t * the structure is still in use. */\n    struct Gridder *containerPtr;\t/* Container window within which this window is\n\t\t\t\t * managed (NULL means this window isn't\n\t\t\t\t * managed by the gridder). */\n    struct Gridder *nextPtr;\t/* Next window managed within same container.\n\t\t\t\t * List order doesn't matter. */\n    struct Gridder *contentPtr;\t/* First in list of content managed inside this\n\t\t\t\t * window (NULL means no grid content). */\n    GridContainer *containerDataPtr;\t/* Additional data for geometry container. */\n    Tcl_Obj *in;                /* Store container name when removed. */\n    int column, row;\t\t/* Location in the grid (starting from\n\t\t\t\t * zero). */\n    int numCols, numRows;\t/* Number of columns or rows this content spans.\n\t\t\t\t * Should be at least 1. */\n    int padX, padY;\t\t/* Total additional pixels to leave around the\n\t\t\t\t * window. Some is of this space is on each\n\t\t\t\t * side. This is space *outside* the window:\n\t\t\t\t * we'll allocate extra space in frame but\n\t\t\t\t * won't enlarge window). */\n    int padLeft, padTop;\t/* The part of padX or padY to use on the left\n\t\t\t\t * or top of the widget, respectively. By\n\t\t\t\t * default, this is half of padX or padY. */\n    int iPadX, iPadY;\t\t/* Total extra pixels to allocate inside the\n\t\t\t\t * window (half this amount will appear on\n\t\t\t\t * each side). */\n    int sticky;\t\t\t/* which sides of its cavity this window\n\t\t\t\t * sticks to. See below for definitions */\n    int doubleBw;\t\t/* Twice the window's last known border width.\n\t\t\t\t * If this changes, the window must be\n\t\t\t\t * re-arranged within its container. */\n    int *abortPtr;\t\t/* If non-NULL, it means that there is a\n\t\t\t\t * nested call to ArrangeGrid already working\n\t\t\t\t * on this window. *abortPtr may be set to 1\n\t\t\t\t * to abort that nested call. This happens,\n\t\t\t\t * for example, if tkwin or any of its content\n\t\t\t\t * is deleted. */\n    int flags;\t\t\t/* Miscellaneous flags; see below for\n\t\t\t\t * definitions. */\n\n    /*\n     * These fields are used temporarily for layout calculations only.\n     */\n\n    struct Gridder *binNextPtr;\t/* Link to next span>1 content in this bin. */\n    int size;\t\t\t/* Nominal size (width or height) in pixels of\n\t\t\t\t * the content. This includes the padding. */\n} Gridder;\n\n/*\n * Flag values for \"sticky\"ness. The 16 combinations subsume the packer's\n * notion of anchor and fill.\n *\n * STICK_NORTH\t\t\tThis window sticks to the top of its cavity.\n * STICK_EAST\t\t\tThis window sticks to the right edge of its\n *\t\t\t\tcavity.\n * STICK_SOUTH\t\t\tThis window sticks to the bottom of its cavity.\n * STICK_WEST\t\t\tThis window sticks to the left edge of its\n *\t\t\t\tcavity.\n */\n\n#define STICK_NORTH\t\t1\n#define STICK_EAST\t\t2\n#define STICK_SOUTH\t\t4\n#define STICK_WEST\t\t8\n\n\n/*\n * Structure to gather information about uniform groups during layout.\n */\n\ntypedef struct UniformGroup {\n    Tk_Uid group;\n    int minSize;\n} UniformGroup;\n\n/*\n * Flag values for Grid structures:\n *\n * REQUESTED_RELAYOUT\t\t1 means a Tcl_DoWhenIdle request has already\n *\t\t\t\tbeen made to re-arrange all the content of this\n *\t\t\t\twindow.\n * DONT_PROPAGATE\t\t1 means don't set this window's requested\n *\t\t\t\tsize. 0 means if this window is a container then\n *\t\t\t\tTk will set its requested size to fit the\n *\t\t\t\tneeds of its content.\n * ALLOCED_CONTAINER\t\t1 means that Grid has allocated itself as\n *\t\t\t\tgeometry container for this window.\n */\n\n#define REQUESTED_RELAYOUT\t1\n#define DONT_PROPAGATE\t\t2\n#define ALLOCED_CONTAINER\t4\n\n/*\n * Prototypes for procedures used only in this file:\n */\n\nstatic void\t\tAdjustForSticky(Gridder *contentPtr, int *xPtr,\n\t\t\t    int *yPtr, int *widthPtr, int *heightPtr);\nstatic int\t\tAdjustOffsets(int width, Tcl_Size elements,\n\t\t\t    SlotInfo *slotPtr);\nstatic void\t\tArrangeGrid(void *clientData);\nstatic int\t\tCheckSlotData(Gridder *containerPtr, Tcl_Size slot,\n\t\t\t    int slotType, int checkOnly);\nstatic int\t\tConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic Tcl_FreeProc\tDestroyGrid;\nstatic Gridder *\tGetGrid(Tk_Window tkwin);\nstatic int\t\tGridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tGridBboxCommand(Tk_Window tkwin, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tGridForgetRemoveCommand(Tk_Window tkwin,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tGridInfoCommand(Tk_Window tkwin, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tGridLocationCommand(Tk_Window tkwin,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tGridPropagateCommand(Tk_Window tkwin,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tGridRowColumnConfigureCommand(Tk_Window tkwin,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tGridSizeCommand(Tk_Window tkwin, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tGridContentCommand(Tk_Window tkwin, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tGridStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tGridLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tGridReqProc(void *clientData, Tk_Window tkwin);\nstatic void\t\tInitContainerData(Gridder *containerPtr);\nstatic Tcl_Obj *\tNewPairObj(Tcl_WideInt, Tcl_WideInt);\nstatic Tcl_Obj *\tNewQuadObj(Tcl_WideInt, Tcl_WideInt, Tcl_WideInt, Tcl_WideInt);\nstatic int\t\tResolveConstraints(Gridder *gridPtr, int rowOrColumn,\n\t\t\t    int maxOffset);\nstatic void\t\tSetGridSize(Gridder *gridPtr);\nstatic int\t\tSetContentColumn(Tcl_Interp *interp, Gridder *contentPtr,\n\t\t\t    int column, int numCols);\nstatic int\t\tSetContentRow(Tcl_Interp *interp, Gridder *contentPtr,\n\t\t\t    int row, int numRows);\nstatic Tcl_Obj *\tStickyToObj(int flags);\nstatic int\t\tStringToSticky(const char *string);\nstatic void\t\tUnlink(Gridder *gridPtr);\n\nstatic const Tk_GeomMgr gridMgrType = {\n    \"grid\",\t\t\t/* name */\n    GridReqProc,\t\t/* requestProc */\n    GridLostContentProc,\t\t/* lostContentProc */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GridCmd --\n *\n *\tThis procedure is invoked to process the \"grid\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GridObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    static const char *const optionStrings[] = {\n\t\"anchor\", \"bbox\", \"columnconfigure\", \"configure\",\n\t\"content\", \"forget\", \"info\", \"location\", \"propagate\",\n\t\"remove\", \"rowconfigure\", \"size\", \"slaves\", NULL\n    };\n    static const char *const optionStringsNoDep[] = {\n\t\"anchor\", \"bbox\", \"columnconfigure\", \"configure\",\n\t\"content\", \"forget\", \"info\", \"location\", \"propagate\",\n\t\"remove\", \"rowconfigure\", \"size\", NULL\n    };\n    enum options {\n\tGRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE,\n\tGRID_CONTENT, GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE,\n\tGRID_REMOVE, GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES\n    };\n    int index;\n\n    if (objc >= 2) {\n\tconst char *argv1 = Tcl_GetString(objv[1]);\n\n\tif ((argv1[0] == '.') || (argv1[0] == REL_SKIP) ||\n\t\t(argv1[0] == REL_VERT)) {\n\t    return ConfigureContent(interp, tkwin, objc-1, objv+1);\n\t}\n    }\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option arg ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(NULL, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t/*\n\t * Call it again without the deprecated ones to get a proper error\n\t * message. This works well since there can't be any ambiguity between\n\t * deprecated and new options.\n\t */\n\n\tTcl_GetIndexFromObjStruct(interp, objv[1], optionStringsNoDep,\n\t\tsizeof(char *), \"option\", 0, &index);\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case GRID_ANCHOR:\n\treturn GridAnchorCommand(tkwin, interp, objc, objv);\n    case GRID_BBOX:\n\treturn GridBboxCommand(tkwin, interp, objc, objv);\n    case GRID_CONFIGURE:\n\treturn ConfigureContent(interp, tkwin, objc-2, objv+2);\n    case GRID_FORGET:\n    case GRID_REMOVE:\n\treturn GridForgetRemoveCommand(tkwin, interp, objc, objv);\n    case GRID_INFO:\n\treturn GridInfoCommand(tkwin, interp, objc, objv);\n    case GRID_LOCATION:\n\treturn GridLocationCommand(tkwin, interp, objc, objv);\n    case GRID_PROPAGATE:\n\treturn GridPropagateCommand(tkwin, interp, objc, objv);\n    case GRID_SIZE:\n\treturn GridSizeCommand(tkwin, interp, objc, objv);\n    case GRID_SLAVES:\n    case GRID_CONTENT:\n\treturn GridContentCommand(tkwin, interp, objc, objv);\n\n    /*\n     * Sample argument combinations:\n     *  grid columnconfigure <container> <index> -option\n     *  grid columnconfigure <container> <index> -option value -option value\n     *  grid rowconfigure <container> <index>\n     *  grid rowconfigure <container> <index> -option\n     *  grid rowconfigure <container> <index> -option value -option value.\n     */\n\n    case GRID_COLUMNCONFIGURE:\n    case GRID_ROWCONFIGURE:\n\treturn GridRowColumnConfigureCommand(tkwin, interp, objc, objv);\n    }\n\n    /* This should not happen */\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"internal error in grid\", TCL_INDEX_NONE));\n    Tcl_SetErrorCode(interp, \"TK\", \"API_ABUSE\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridAnchorCommand --\n *\n *\tImplementation of the [grid anchor] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay recompute grid geometry.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridAnchorCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\n    GridContainer *gridPtr;\n    Tk_Anchor old;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?anchor?\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n\n    if (objc == 3) {\n\tgridPtr = containerPtr->containerDataPtr;\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\tTk_NameOfAnchor(gridPtr?gridPtr->anchor:GRID_DEFAULT_ANCHOR),\n\t\t-1));\n\treturn TCL_OK;\n    }\n\n    InitContainerData(containerPtr);\n    gridPtr = containerPtr->containerDataPtr;\n    old = gridPtr->anchor;\n    if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Only request a relayout if the anchor changes.\n     */\n\n    if (old != gridPtr->anchor) {\n\tif (containerPtr->abortPtr != NULL) {\n\t    *containerPtr->abortPtr = 1;\n\t}\n\tif (!(containerPtr->flags & REQUESTED_RELAYOUT)) {\n\t    containerPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridBboxCommand --\n *\n *\tImplementation of the [grid bbox] subcommand.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tPlaces bounding box information in the interp's result field.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridBboxCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\t\t/* container grid record */\n    GridContainer *gridPtr;\t/* pointer to grid data */\n    int row, column;\t\t/* origin for bounding box */\n    int row2, column2;\t\t/* end of bounding box */\n    int endX, endY;\t\t/* last column/row in the layout */\n    int x=0, y=0;\t\t/* starting pixels for this bounding box */\n    int width, height;\t\t/* size of the bounding box */\n\n    if (objc!=3 && objc != 5 && objc != 7) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?column row ?column row??\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n\n    if (objc >= 5) {\n\tif (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[4], &row) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tcolumn2 = column;\n\trow2 = row;\n    }\n\n    if (objc == 7) {\n\tif (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[6], &row2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    gridPtr = containerPtr->containerDataPtr;\n    if (gridPtr == NULL) {\n\tTcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));\n\treturn TCL_OK;\n    }\n\n    SetGridSize(containerPtr);\n    endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);\n    endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);\n\n    if ((endX == 0) || (endY == 0)) {\n\tTcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));\n\treturn TCL_OK;\n    }\n    if (objc == 3) {\n\trow = 0;\n\tcolumn = 0;\n\trow2 = endY;\n\tcolumn2 = endX;\n    }\n\n    if (column > column2) {\n\tint temp = column;\n\n\tcolumn = column2;\n\tcolumn2 = temp;\n    }\n    if (row > row2) {\n\tint temp = row;\n\n\trow = row2;\n\trow2 = temp;\n    }\n\n    if (column > 0 && column < endX) {\n\tx = gridPtr->columnPtr[column-1].offset;\n    } else if (column > 0) {\n\tx = gridPtr->columnPtr[endX-1].offset;\n    }\n\n    if (row > 0 && row < endY) {\n\ty = gridPtr->rowPtr[row-1].offset;\n    } else if (row > 0) {\n\ty = gridPtr->rowPtr[endY-1].offset;\n    }\n\n    if (column2 < 0) {\n\twidth = 0;\n    } else if (column2 >= endX) {\n\twidth = gridPtr->columnPtr[endX-1].offset - x;\n    } else {\n\twidth = gridPtr->columnPtr[column2].offset - x;\n    }\n\n    if (row2 < 0) {\n\theight = 0;\n    } else if (row2 >= endY) {\n\theight = gridPtr->rowPtr[endY-1].offset - y;\n    } else {\n\theight = gridPtr->rowPtr[row2].offset - y;\n    }\n\n    Tcl_SetObjResult(interp, NewQuadObj(\n\t    x + gridPtr->startX, y + gridPtr->startY, width, height));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridForgetRemoveCommand --\n *\n *\tImplementation of the [grid forget]/[grid remove] subcommands. See the\n *\tuser documentation for details on what these do.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tRemoves a window from a grid layout.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridForgetRemoveCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window content;\n    Gridder *contentPtr;\n    Tcl_Size i;\n    const char *string = Tcl_GetString(objv[1]);\n    char c = string[0];\n\n    for (i = 2; i < objc; i++) {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!(contentPtr = GetGrid(content))) {\n\t    continue;\n\t}\n\tif (contentPtr->containerPtr != NULL) {\n\t    /*\n\t     * For \"forget\", reset all the settings to their defaults\n\t     */\n\n\t    if (c == 'f') {\n\t\tcontentPtr->column = -1;\n\t\tcontentPtr->row = -1;\n\t\tcontentPtr->numCols = 1;\n\t\tcontentPtr->numRows = 1;\n\t\tcontentPtr->padX = 0;\n\t\tcontentPtr->padY = 0;\n\t\tcontentPtr->padLeft = 0;\n\t\tcontentPtr->padTop = 0;\n\t\tcontentPtr->iPadX = 0;\n\t\tcontentPtr->iPadY = 0;\n\t\tif (contentPtr->in != NULL) {\n\t\t    Tcl_DecrRefCount(contentPtr->in);\n\t\t    contentPtr->in = NULL;\n\t\t}\n\t\tcontentPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;\n\t\tif (contentPtr->flags & REQUESTED_RELAYOUT) {\n\t\t    Tcl_CancelIdleCall(ArrangeGrid, contentPtr);\n\t\t}\n\t\tcontentPtr->flags = 0;\n\t\tcontentPtr->sticky = 0;\n\t    } else {\n\t\t/*\n\t\t * When removing, store name of container to be able to\n\t\t * restore it later, even if the container is recreated.\n\t\t */\n\n\t\tif (contentPtr->in != NULL) {\n\t\t    Tcl_DecrRefCount(contentPtr->in);\n\t\t    contentPtr->in = NULL;\n\t\t}\n\t\tif (contentPtr->containerPtr != NULL) {\n\t\t    contentPtr->in = Tcl_NewStringObj(\n\t\t\t    Tk_PathName(contentPtr->containerPtr->tkwin), TCL_INDEX_NONE);\n\t\t    Tcl_IncrRefCount(contentPtr->in);\n\t\t}\n\t    }\n\t    Tk_ManageGeometry(content, NULL, NULL);\n\t    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\t\tTk_UnmaintainGeometry(contentPtr->tkwin,\n\t\t\tcontentPtr->containerPtr->tkwin);\n\t    }\n\t    Unlink(contentPtr);\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridInfoCommand --\n *\n *\tImplementation of the [grid info] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tPuts gridding information in the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridInfoCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Gridder *contentPtr;\n    Tk_Window content;\n    Tcl_Obj *infoObj;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &content) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(contentPtr = GetGrid(content))) {\n\treturn TCL_OK;\n    }\n    if (contentPtr->containerPtr == NULL) {\n\tTcl_ResetResult(interp);\n\treturn TCL_OK;\n    }\n\n    infoObj = Tcl_NewObj();\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-in\", TCL_INDEX_NONE),\n\t    Tk_NewWindowObj(contentPtr->containerPtr->tkwin));\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-column\", TCL_INDEX_NONE),\n\t    Tcl_NewWideIntObj(contentPtr->column));\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-row\", TCL_INDEX_NONE),\n\t    Tcl_NewWideIntObj(contentPtr->row));\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-columnspan\", TCL_INDEX_NONE),\n\t    Tcl_NewWideIntObj(contentPtr->numCols));\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-rowspan\", TCL_INDEX_NONE),\n\t    Tcl_NewWideIntObj(contentPtr->numRows));\n    TkAppendPadAmount(infoObj, \"-ipadx\", contentPtr->iPadX/2, contentPtr->iPadX);\n    TkAppendPadAmount(infoObj, \"-ipady\", contentPtr->iPadY/2, contentPtr->iPadY);\n    TkAppendPadAmount(infoObj, \"-padx\", contentPtr->padLeft, contentPtr->padX);\n    TkAppendPadAmount(infoObj, \"-pady\", contentPtr->padTop, contentPtr->padY);\n    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-sticky\", TCL_INDEX_NONE),\n\t    StickyToObj(contentPtr->sticky));\n    Tcl_SetObjResult(interp, infoObj);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridLocationCommand --\n *\n *\tImplementation of the [grid location] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tPuts location information in the interpreter's result field.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridLocationCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\t\t/* Container grid record. */\n    GridContainer *gridPtr;\t/* Pointer to grid data. */\n    SlotInfo *slotPtr;\n    int x, y;\t\t\t/* Offset in pixels, from edge of container. */\n    int i, j;\t\t\t/* Corresponding column and row indeces. */\n    int endX, endY;\t\t/* End of grid. */\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window x y\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (Tk_GetPixelsFromObj(interp, container, objv[3], &x) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (Tk_GetPixelsFromObj(interp, container, objv[4], &y) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n    if (containerPtr->containerDataPtr == NULL) {\n\tTcl_SetObjResult(interp, NewPairObj(-1, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n    gridPtr = containerPtr->containerDataPtr;\n\n    /*\n     * Update any pending requests. This is not always the steady state value,\n     * as more configure events could be in the pipeline, but its as close as\n     * its easy to get.\n     */\n\n    while (containerPtr->flags & REQUESTED_RELAYOUT) {\n\tTcl_CancelIdleCall(ArrangeGrid, containerPtr);\n\tArrangeGrid(containerPtr);\n    }\n    SetGridSize(containerPtr);\n    endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);\n    endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);\n\n    slotPtr = containerPtr->containerDataPtr->columnPtr;\n    if (x < containerPtr->containerDataPtr->startX) {\n\ti = -1;\n    } else {\n\tx -= containerPtr->containerDataPtr->startX;\n\tfor (i = 0; slotPtr[i].offset < x && i < endX; i++) {\n\t    /* null body */\n\t}\n    }\n\n    slotPtr = containerPtr->containerDataPtr->rowPtr;\n    if (y < containerPtr->containerDataPtr->startY) {\n\tj = -1;\n    } else {\n\ty -= containerPtr->containerDataPtr->startY;\n\tfor (j = 0; slotPtr[j].offset < y && j < endY; j++) {\n\t    /* null body */\n\t}\n    }\n\n    Tcl_SetObjResult(interp, NewPairObj(i, j));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridPropagateCommand --\n *\n *\tImplementation of the [grid propagate] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay alter geometry propagation for a widget.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridPropagateCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\n    int propagate, old;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?boolean?\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewBooleanObj(!(containerPtr->flags & DONT_PROPAGATE)));\n\treturn TCL_OK;\n    }\n    if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Only request a relayout if the propagation bit changes.\n     */\n\n    old = !(containerPtr->flags & DONT_PROPAGATE);\n    if (propagate != old) {\n\tif (propagate) {\n\t    /*\n\t     * If we have content, we need to register as geometry container.\n\t     */\n\n\t    if (containerPtr->contentPtr != NULL) {\n\t\tif (TkSetGeometryContainer(interp, container, \"grid\")\t!= TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontainerPtr->flags |= ALLOCED_CONTAINER;\n\t    }\n\t    containerPtr->flags &= ~DONT_PROPAGATE;\n\t} else {\n\t    if (containerPtr->flags & ALLOCED_CONTAINER) {\n\t\tTkFreeGeometryContainer(container, \"grid\");\n\t\tcontainerPtr->flags &= ~ALLOCED_CONTAINER;\n\t    }\n\t    containerPtr->flags |= DONT_PROPAGATE;\n\t}\n\n\t/*\n\t * Re-arrange the container to allow new geometry information to\n\t * propagate upwards to the container's container.\n\t */\n\n\tif (containerPtr->abortPtr != NULL) {\n\t    *containerPtr->abortPtr = 1;\n\t}\n\tif (!(containerPtr->flags & REQUESTED_RELAYOUT)) {\n\t    containerPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridRowColumnConfigureCommand --\n *\n *\tImplementation of the [grid rowconfigure] and [grid columnconfigure]\n *\tsubcommands. See the user documentation for details on what these do.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tDepends on arguments; see user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridRowColumnConfigureCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container, content;\n    Gridder *containerPtr, *contentPtr;\n    SlotInfo *slotPtr = NULL;\n    Tcl_Size slot;\t\t/* the column or row number */\n    int slotType;\t\t/* COLUMN or ROW */\n    int size;\t\t\t/* the configuration value */\n    Tcl_Size lObjc;\t\t/* Number of items in index list */\n    Tcl_Obj **lObjv;\t\t/* array of indices */\n    int ok;\t\t\t/* temporary TCL result code */\n    Tcl_Size i, j, first, last;\n    const char *string;\n    static const char *const optionStrings[] = {\n\t\"-minsize\", \"-pad\", \"-uniform\", \"-weight\", NULL\n    };\n    enum options {\n\tROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT\n    };\n    int index;\n    Tcl_Obj *listCopy;\n\n    if (((objc % 2 != 0) && (objc > 6)) || (objc < 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window index ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    listCopy = Tcl_DuplicateObj(objv[3]);\n    Tcl_IncrRefCount(listCopy);\n    if (Tcl_ListObjGetElements(interp, listCopy, &lObjc, &lObjv) != TCL_OK) {\n\tTcl_DecrRefCount(listCopy);\n\treturn TCL_ERROR;\n    }\n\n    string = Tcl_GetString(objv[1]);\n    slotType = (*string == 'c') ? COLUMN : ROW;\n    if (lObjc == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"no %s indices specified\",\n\t\t(slotType == COLUMN) ? \"column\" : \"row\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"NO_INDEX\", (char *)NULL);\n\tTcl_DecrRefCount(listCopy);\n\treturn TCL_ERROR;\n    }\n\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n    first = 0;\n    last = 0;\n\n    if ((objc == 4) || (objc == 5)) {\n\tif (lObjc != 1) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"must specify a single element on retrieval\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"USAGE\", (char *)NULL);\n\t    Tcl_DecrRefCount(listCopy);\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetSizeIntFromObj(interp, lObjv[0], &slot) != TCL_OK) {\n\t    Tcl_AppendResult(interp,\n\t\t    \" (when retrieving options only integer indices are \"\n\t\t    \"allowed)\", (char *)NULL);\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"INDEX_FORMAT\", (char *)NULL);\n\t    Tcl_DecrRefCount(listCopy);\n\t    return TCL_ERROR;\n\t}\n\tok = CheckSlotData(containerPtr, slot, slotType, /* checkOnly */ 1);\n\tif (ok == TCL_OK) {\n\t    slotPtr = (slotType == COLUMN) ?\n\t\t    containerPtr->containerDataPtr->columnPtr :\n\t\t    containerPtr->containerDataPtr->rowPtr;\n\t}\n\n\t/*\n\t * Return all of the options for this row or column. If the request is\n\t * out of range, return all 0's.\n\t */\n\n\tif (objc == 4) {\n\t    int minsize = 0, pad = 0, weight = 0;\n\t    Tk_Uid uniform = NULL;\n\t    Tcl_Obj *res = Tcl_NewListObj(0, NULL);\n\n\t    if (ok == TCL_OK) {\n\t\tminsize = slotPtr[slot].minSize;\n\t\tpad     = slotPtr[slot].pad;\n\t\tweight  = slotPtr[slot].weight;\n\t\tuniform = slotPtr[slot].uniform;\n\t    }\n\n\t    Tcl_ListObjAppendElement(interp, res,\n\t\t    Tcl_NewStringObj(\"-minsize\", TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(minsize));\n\t    Tcl_ListObjAppendElement(interp, res,\n\t\t    Tcl_NewStringObj(\"-pad\", TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(pad));\n\t    Tcl_ListObjAppendElement(interp, res,\n\t\t    Tcl_NewStringObj(\"-uniform\", TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, res,\n\t\t    Tcl_NewStringObj(uniform == NULL ? \"\" : uniform, TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, res,\n\t\t    Tcl_NewStringObj(\"-weight\", TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(weight));\n\t    Tcl_SetObjResult(interp, res);\n\t    Tcl_DecrRefCount(listCopy);\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * If only one option is given, with no value, the current value is\n\t * returned.\n\t */\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[4], optionStrings,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t    Tcl_DecrRefCount(listCopy);\n\t    return TCL_ERROR;\n\t}\n\tif (index == ROWCOL_MINSIZE) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\t    (ok == TCL_OK) ? slotPtr[slot].minSize : 0));\n\t} else if (index == ROWCOL_WEIGHT) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\t    (ok == TCL_OK) ? slotPtr[slot].weight : 0));\n\t} else if (index == ROWCOL_UNIFORM) {\n\t    Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : \"\";\n\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    (value == NULL) ? \"\" : value, TCL_INDEX_NONE));\n\t} else if (index == ROWCOL_PAD) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\t    (ok == TCL_OK) ? slotPtr[slot].pad : 0));\n\t}\n\tTcl_DecrRefCount(listCopy);\n\treturn TCL_OK;\n    }\n\n    for (j = 0; j < lObjc; j++) {\n\tint allContent = 0;\n\n\tif (Tcl_GetSizeIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) {\n\t    first = slot;\n\t    last = slot;\n\t    contentPtr = NULL;\n\t} else if (strcmp(Tcl_GetString(lObjv[j]), \"all\") == 0) {\n\t    /*\n\t     * Make sure container is initialised.\n\t     */\n\n\t    InitContainerData(containerPtr);\n\n\t    contentPtr = containerPtr->contentPtr;\n\t    if (contentPtr == NULL) {\n\t\tcontinue;\n\t    }\n\t    allContent = 1;\n\t} else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &content)\n\t\t== TCL_OK) {\n\t    /*\n\t     * Is it gridded in this container?\n\t     */\n\n\t    if (!(contentPtr = GetGrid(content))) {\n\t\tcontinue;\n\t    }\n\t    if (contentPtr->containerPtr != containerPtr) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"the window \\\"%s\\\" is not managed by \\\"%s\\\"\",\n\t\t\tTcl_GetString(lObjv[j]), Tcl_GetString(objv[2])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"NOT_MANAGED\", (char *)NULL);\n\t\tTcl_DecrRefCount(listCopy);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"illegal index \\\"%s\\\"\", Tcl_GetString(lObjv[j])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID_INDEX\", (char *)NULL);\n\t    Tcl_DecrRefCount(listCopy);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * The outer loop is only to handle \"all\".\n\t */\n\n\tdo {\n\t    if (contentPtr != NULL) {\n\t\tfirst = (slotType == COLUMN) ?\n\t\t\tcontentPtr->column : contentPtr->row;\n\t\tlast = first - 1 + ((slotType == COLUMN) ?\n\t\t\tcontentPtr->numCols : contentPtr->numRows);\n\t    }\n\n\t    for (slot = first; slot <= last; slot++) {\n\t\tok = CheckSlotData(containerPtr, slot, slotType, /*checkOnly*/ 0);\n\t\tif (ok != TCL_OK) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"\\\"%s\\\" is out of range\",\n\t\t\t    Tcl_GetString(lObjv[j])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"INDEX_RANGE\",\n\t\t\t    (char *)NULL);\n\t\t    Tcl_DecrRefCount(listCopy);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tslotPtr = (slotType == COLUMN) ?\n\t\t\tcontainerPtr->containerDataPtr->columnPtr :\n\t\t\tcontainerPtr->containerDataPtr->rowPtr;\n\n\t\t/*\n\t\t * Loop through each option value pair, setting the values as\n\t\t * required.\n\t\t */\n\n\t\tfor (i = 4; i < objc; i += 2) {\n\t\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\t\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t\t\tTcl_DecrRefCount(listCopy);\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    if (index == ROWCOL_MINSIZE) {\n\t\t\tif (Tk_GetPixelsFromObj(interp, container, objv[i+1],\n\t\t\t\t&size) != TCL_OK) {\n\t\t\t    Tcl_DecrRefCount(listCopy);\n\t\t\t    return TCL_ERROR;\n\t\t\t} else {\n\t\t\t    slotPtr[slot].minSize = size;\n\t\t\t}\n\t\t    } else if (index == ROWCOL_WEIGHT) {\n\t\t\tint wt;\n\n\t\t\tif (Tcl_GetIntFromObj(interp,objv[i+1],&wt)!=TCL_OK) {\n\t\t\t    Tcl_DecrRefCount(listCopy);\n\t\t\t    return TCL_ERROR;\n\t\t\t} else if (wt < 0) {\n\t\t\t    Tcl_DecrRefCount(listCopy);\n\t\t\t    goto negativeIndex;\n\t\t\t} else {\n\t\t\t    slotPtr[slot].weight = wt;\n\t\t\t}\n\t\t    } else if (index == ROWCOL_UNIFORM) {\n\t\t\tslotPtr[slot].uniform =\n\t\t\t\tTk_GetUid(Tcl_GetString(objv[i+1]));\n\t\t\tif (slotPtr[slot].uniform != NULL &&\n\t\t\t\tslotPtr[slot].uniform[0] == 0) {\n\t\t\t    slotPtr[slot].uniform = NULL;\n\t\t\t}\n\t\t    } else if (index == ROWCOL_PAD) {\n\t\t\tif (Tk_GetPixelsFromObj(interp, container, objv[i+1],\n\t\t\t\t&size) != TCL_OK) {\n\t\t\t    Tcl_DecrRefCount(listCopy);\n\t\t\t    return TCL_ERROR;\n\t\t\t} else if (size < 0) {\n\t\t\t    Tcl_DecrRefCount(listCopy);\n\t\t\t    goto negativeIndex;\n\t\t\t} else {\n\t\t\t    slotPtr[slot].pad = size;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t    if (contentPtr != NULL) {\n\t\tcontentPtr = contentPtr->nextPtr;\n\t    }\n\t} while ((allContent == 1) && (contentPtr != NULL));\n    }\n    Tcl_DecrRefCount(listCopy);\n\n    /*\n     * We changed a property, re-arrange the table, and check for constraint\n     * shrinkage. A null slotPtr will occur for 'all' checks.\n     */\n\n    if (slotPtr != NULL) {\n\tif (slotType == ROW) {\n\t    last = containerPtr->containerDataPtr->rowMax - 1;\n\n\t    while ((last >= 0) && (slotPtr[last].weight == 0)\n\t\t    && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)\n\t\t    && (slotPtr[last].uniform == NULL)) {\n\t\tlast--;\n\t    }\n\t    containerPtr->containerDataPtr->rowMax = last+1;\n\t} else {\n\t    last = containerPtr->containerDataPtr->columnMax - 1;\n\n\t    while ((last >= 0) && (slotPtr[last].weight == 0)\n\t\t    && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)\n\t\t    && (slotPtr[last].uniform == NULL)) {\n\t\tlast--;\n\t    }\n\t    containerPtr->containerDataPtr->columnMax = last + 1;\n\t}\n    }\n\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n    if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {\n\tcontainerPtr->flags |= REQUESTED_RELAYOUT;\n\tTcl_DoWhenIdle(ArrangeGrid, containerPtr);\n    }\n    return TCL_OK;\n\n  negativeIndex:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"invalid arg \\\"%s\\\": should be non-negative\",\n\t    Tcl_GetString(objv[i])));\n    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"NEG_INDEX\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridSizeCommand --\n *\n *\tImplementation of the [grid size] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tPuts grid size information in the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridSizeCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\n    GridContainer *gridPtr;\t/* pointer to grid data */\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n\n    if (containerPtr->containerDataPtr != NULL) {\n\tSetGridSize(containerPtr);\n\tgridPtr = containerPtr->containerDataPtr;\n\tTcl_SetObjResult(interp, NewPairObj(\n\t\tMAX(gridPtr->columnEnd, gridPtr->columnMax),\n\t\tMAX(gridPtr->rowEnd, gridPtr->rowMax)));\n    } else {\n\tTcl_SetObjResult(interp, NewPairObj(0, 0));\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridContentCommand --\n *\n *\tImplementation of the [grid content] subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tPlaces a list of content windows of the specified window in the\n *\tinterpreter's result field.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGridContentCommand(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window container;\n    Gridder *containerPtr;\t\t/* container grid record */\n    Gridder *contentPtr;\n    Tcl_Size i;\n    int row = -1, column = -1, value, index;\n    static const char *const optionStrings[] = {\n\t\"-column\", \"-row\", NULL\n    };\n    enum options { CONTENT_COLUMN, CONTENT_ROW };\n    Tcl_Obj *res;\n\n    if ((objc < 3) || ((objc % 2) == 0)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    for (i = 3; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[i+1], &value) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (value < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%d is an invalid value: should NOT be < 0\", value));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"NEG_INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (index == CONTENT_COLUMN) {\n\t    column = value;\n\t} else {\n\t    row = value;\n\t}\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!(containerPtr = GetGrid(container))) {\n\treturn TCL_OK;\n    }\n\n    res = Tcl_NewListObj(0, NULL);\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tif ((column >= 0) && (contentPtr->column > column\n\t\t|| contentPtr->column+contentPtr->numCols-1 < column)) {\n\t    continue;\n\t}\n\tif ((row >= 0) && (contentPtr->row > row ||\n\t\tcontentPtr->row+contentPtr->numRows-1 < row)) {\n\t    continue;\n\t}\n\tTcl_ListObjAppendElement(interp,res, Tk_NewWindowObj(contentPtr->tkwin));\n    }\n    Tcl_SetObjResult(interp, res);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridReqProc --\n *\n *\tThis procedure is invoked by Tk_GeometryRequest for windows managed by\n *\tthe grid.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for tkwin, and all its managed siblings, to be re-arranged at\n *\tthe next idle point.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGridReqProc(\n    void *clientData,\t/* Grid's information about window that got\n\t\t\t\t * new preferred geometry. */\n    TCL_UNUSED(Tk_Window))\t\t/* Other Tk-related information about the\n\t\t\t\t * window. */\n{\n    Gridder *gridPtr = (Gridder *)clientData;\n\n    gridPtr = gridPtr->containerPtr;\n    if (gridPtr && !(gridPtr->flags & REQUESTED_RELAYOUT)) {\n\tgridPtr->flags |= REQUESTED_RELAYOUT;\n\tTcl_DoWhenIdle(ArrangeGrid, gridPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridLostContentProc --\n *\n *\tThis procedure is invoked by Tk whenever some other geometry claims\n *\tcontrol over a content that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all grid-related information about the content.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGridLostContentProc(\n    void *clientData,\t/* Grid structure for content window that was\n\t\t\t\t * stolen away. */\n    TCL_UNUSED(Tk_Window))\t\t/* Tk's handle for the content window. */\n{\n    Gridder *contentPtr = (Gridder *)clientData;\n\n    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\tTk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n    }\n    Unlink(contentPtr);\n    Tk_UnmapWindow(contentPtr->tkwin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustOffsets --\n *\n *\tThis procedure adjusts the size of the layout to fit in the space\n *\tprovided. If it needs more space, the extra is added according to the\n *\tweights. If it needs less, the space is removed according to the\n *\tweights, but at no time does the size drop below the minsize specified\n *\tfor that slot.\n *\n * Results:\n *\tThe size used by the layout.\n *\n * Side effects:\n *\tThe slot offsets are modified to shrink the layout.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nAdjustOffsets(\n    int size,\t\t\t/* The total layout size (in pixels). */\n    Tcl_Size slots,\t\t\t/* Number of slots. */\n    SlotInfo *slotPtr)\t/* Pointer to slot array. */\n{\n    Tcl_Size slot;\t\t/* Current slot. */\n    int diff;\t\t\t/* Extra pixels needed to add to the layout. */\n    int totalWeight;\t\t/* Sum of the weights for all the slots. */\n    int weight;\t\t\t/* Sum of the weights so far. */\n    int minSize;\t\t/* Minimum possible layout size. */\n    int newDiff;\t\t/* The most pixels that can be added on the\n\t\t\t\t * current pass. */\n\n    diff = size - slotPtr[slots-1].offset;\n\n    /*\n     * The layout is already the correct size; all done.\n     */\n\n    if (diff == 0) {\n\treturn size;\n    }\n\n    /*\n     * If all the weights are zero, there is nothing more to do.\n     */\n\n    totalWeight = 0;\n    for (slot = 0; slot < slots; slot++) {\n\ttotalWeight += slotPtr[slot].weight;\n    }\n\n    if (totalWeight == 0) {\n\treturn slotPtr[slots-1].offset;\n    }\n\n    /*\n     * Add extra space according to the slot weights. This is done\n     * cumulatively to prevent round-off error accumulation.\n     */\n\n    if (diff > 0) {\n\tweight = 0;\n\tfor (slot = 0; slot < slots; slot++) {\n\t    weight += slotPtr[slot].weight;\n\t    slotPtr[slot].offset += diff * weight / totalWeight;\n\t}\n\treturn size;\n    }\n\n    /*\n     * The layout must shrink below its requested size. Compute the minimum\n     * possible size by looking at the slot minSizes. Store each slot's\n     * minimum size in temp.\n     */\n\n    minSize = 0;\n    for (slot = 0; slot < slots; slot++) {\n\tif (slotPtr[slot].weight > 0) {\n\t    slotPtr[slot].temp = slotPtr[slot].minSize;\n\t} else if (slot > 0) {\n\t    slotPtr[slot].temp = slotPtr[slot].offset - slotPtr[slot-1].offset;\n\t} else {\n\t    slotPtr[slot].temp = slotPtr[slot].offset;\n\t}\n\tminSize += slotPtr[slot].temp;\n    }\n\n    /*\n     * If the requested size is less than the minimum required size, set the\n     * slot sizes to their minimum values.\n     */\n\n    if (size <= minSize) {\n\tint offset = 0;\n\n\tfor (slot = 0; slot < slots; slot++) {\n\t    offset += slotPtr[slot].temp;\n\t    slotPtr[slot].offset = offset;\n\t}\n\treturn minSize;\n    }\n\n    /*\n     * Remove space from slots according to their weights. The weights get\n     * renormalized anytime a slot shrinks to its minimum size.\n     */\n\n    while (diff < 0) {\n\t/*\n\t * Find the total weight for the shrinkable slots.\n\t */\n\n\ttotalWeight = 0;\n\tfor (slot = 0; slot < slots; slot++) {\n\t    int current = (slot == 0) ? slotPtr[slot].offset :\n\t\t    slotPtr[slot].offset - slotPtr[slot-1].offset;\n\n\t    if (current > slotPtr[slot].minSize) {\n\t\ttotalWeight += slotPtr[slot].weight;\n\t\tslotPtr[slot].temp = slotPtr[slot].weight;\n\t    } else {\n\t\tslotPtr[slot].temp = 0;\n\t    }\n\t}\n\tif (totalWeight == 0) {\n\t    break;\n\t}\n\n\t/*\n\t * Find the maximum amount of space we can distribute this pass.\n\t */\n\n\tnewDiff = diff;\n\tfor (slot = 0; slot < slots; slot++) {\n\t    int current;\t/* Current size of this slot. */\n\t    int maxDiff;\t/* Maximum diff that would cause this slot to\n\t\t\t\t * equal its minsize. */\n\n\t    if (slotPtr[slot].temp == 0) {\n\t\tcontinue;\n\t    }\n\t    current = (slot == 0) ? slotPtr[slot].offset :\n\t\t    slotPtr[slot].offset - slotPtr[slot-1].offset;\n\t    maxDiff = totalWeight * (slotPtr[slot].minSize - current)\n\t\t    / slotPtr[slot].temp;\n\t    if (maxDiff > newDiff) {\n\t\tnewDiff = maxDiff;\n\t    }\n\t}\n\n\t/*\n\t * Now distribute the space.\n\t */\n\n\tweight = 0;\n\tfor (slot = 0; slot < slots; slot++) {\n\t    weight += slotPtr[slot].temp;\n\t    slotPtr[slot].offset += newDiff * weight / totalWeight;\n\t}\n\tdiff -= newDiff;\n    }\n    return size;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustForSticky --\n *\n *\tThis procedure adjusts the size of a content in its cavity based on its\n *\t\"sticky\" flags.\n *\n * Results:\n *\tThe input x, y, width, and height are changed to represent the desired\n *\tcoordinates of the content.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAdjustForSticky(\n    Gridder *contentPtr,\t/* Content window to arrange in its cavity. */\n    int *xPtr,\t\t/* Pixel location of the left edge of the cavity. */\n    int *yPtr,\t\t/* Pixel location of the top edge of the cavity. */\n    int *widthPtr,\t/* Width of the cavity (in pixels). */\n    int *heightPtr)\t/* Height of the cavity (in pixels). */\n{\n    int diffx = 0;\t/* Cavity width - content width. */\n    int diffy = 0;\t/* Cavity hight - content height. */\n    int sticky = contentPtr->sticky;\n\n    *xPtr += contentPtr->padLeft;\n    *widthPtr -= contentPtr->padX;\n    *yPtr += contentPtr->padTop;\n    *heightPtr -= contentPtr->padY;\n\n    if (*widthPtr > (Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX)) {\n\tdiffx = *widthPtr - (Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX);\n\t*widthPtr = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX;\n    }\n\n    if (*heightPtr > (Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY)) {\n\tdiffy = *heightPtr - (Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY);\n\t*heightPtr = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY;\n    }\n\n    if (sticky&STICK_EAST && sticky&STICK_WEST) {\n\t*widthPtr += diffx;\n    }\n    if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {\n\t*heightPtr += diffy;\n    }\n    if (!(sticky&STICK_WEST)) {\n\t*xPtr += (sticky&STICK_EAST) ? diffx : diffx/2;\n    }\n    if (!(sticky&STICK_NORTH)) {\n\t*yPtr += (sticky&STICK_SOUTH) ? diffy : diffy/2;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ArrangeGrid --\n *\n *\tThis procedure is invoked (using the Tcl_DoWhenIdle mechanism) to\n *\tre-layout a set of windows managed by the grid. It is invoked at idle\n *\ttime so that a series of grid requests can be merged into a single\n *\tlayout operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe content of containerPtr may get resized or moved.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nArrangeGrid(\n    void *clientData)\t/* Structure describing container whose content\n\t\t\t\t * are to be re-layed out. */\n{\n    Gridder *containerPtr = (Gridder *)clientData;\n    Gridder *contentPtr;\n    GridContainer *slotPtr = containerPtr->containerDataPtr;\n    int abort;\n    int width, height;\t\t/* Requested size of layout, in pixels. */\n    int realWidth, realHeight;\t/* Actual size layout should take-up. */\n    int usedX, usedY;\n\n    containerPtr->flags &= ~REQUESTED_RELAYOUT;\n\n    /*\n     * If the container has no content anymore, then don't change the container size.\n     * Otherwise there is no way to \"relinquish\" control over the container\n     * so another geometry manager can take over.\n     */\n\n    if (containerPtr->contentPtr == NULL) {\n\treturn;\n    }\n\n    if (containerPtr->containerDataPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Abort any nested call to ArrangeGrid for this window, since we'll do\n     * everything necessary here, and set up so this call can be aborted if\n     * necessary.\n     */\n\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n    containerPtr->abortPtr = &abort;\n    abort = 0;\n    Tcl_Preserve(containerPtr);\n\n    /*\n     * Call the constraint engine to fill in the row and column offsets.\n     */\n\n    SetGridSize(containerPtr);\n    width = ResolveConstraints(containerPtr, COLUMN, 0);\n    height = ResolveConstraints(containerPtr, ROW, 0);\n    width += Tk_InternalBorderLeft(containerPtr->tkwin) +\n\t    Tk_InternalBorderRight(containerPtr->tkwin);\n    height += Tk_InternalBorderTop(containerPtr->tkwin) +\n\t    Tk_InternalBorderBottom(containerPtr->tkwin);\n\n    if (width < Tk_MinReqWidth(containerPtr->tkwin)) {\n\twidth = Tk_MinReqWidth(containerPtr->tkwin);\n    }\n    if (height < Tk_MinReqHeight(containerPtr->tkwin)) {\n\theight = Tk_MinReqHeight(containerPtr->tkwin);\n    }\n\n    if (((width != Tk_ReqWidth(containerPtr->tkwin))\n\t    || (height != Tk_ReqHeight(containerPtr->tkwin)))\n\t    && !(containerPtr->flags & DONT_PROPAGATE)) {\n\tTk_GeometryRequest(containerPtr->tkwin, width, height);\n\tif (width>1 && height>1) {\n\t    containerPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);\n\t}\n\tcontainerPtr->abortPtr = NULL;\n\tTcl_Release(containerPtr);\n\treturn;\n    }\n\n    /*\n     * If the currently requested layout size doesn't match the container's\n     * window size, then adjust the slot offsets according to the weights. If\n     * all of the weights are zero, place the layout according to the anchor\n     * value.\n     */\n\n    realWidth = Tk_Width(containerPtr->tkwin) -\n\t    Tk_InternalBorderLeft(containerPtr->tkwin) -\n\t    Tk_InternalBorderRight(containerPtr->tkwin);\n    realHeight = Tk_Height(containerPtr->tkwin) -\n\t    Tk_InternalBorderTop(containerPtr->tkwin) -\n\t    Tk_InternalBorderBottom(containerPtr->tkwin);\n    usedX = AdjustOffsets(realWidth,\n\t    MAX(slotPtr->columnEnd, slotPtr->columnMax), slotPtr->columnPtr);\n    usedY = AdjustOffsets(realHeight, MAX(slotPtr->rowEnd, slotPtr->rowMax),\n\t    slotPtr->rowPtr);\n    TkComputeAnchor(containerPtr->containerDataPtr->anchor, containerPtr->tkwin,\n\t    0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY);\n\n    /*\n     * Now adjust the actual size of the content to its cavity by computing the\n     * cavity size, and adjusting the widget according to its stickyness.\n     */\n\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL && !abort;\n\t    contentPtr = contentPtr->nextPtr) {\n\tint x, y;\t\t\t/* Top left coordinate */\n\tint col = contentPtr->column;\n\tint row = contentPtr->row;\n\n\tx = (col>0) ? slotPtr->columnPtr[col-1].offset : 0;\n\ty = (row>0) ? slotPtr->rowPtr[row-1].offset : 0;\n\n\twidth = slotPtr->columnPtr[contentPtr->numCols+col-1].offset - x;\n\theight = slotPtr->rowPtr[contentPtr->numRows+row-1].offset - y;\n\n\tx += slotPtr->startX;\n\ty += slotPtr->startY;\n\n\tAdjustForSticky(contentPtr, &x, &y, &width, &height);\n\n\t/*\n\t * Now put the window in the proper spot. (This was taken directly\n\t * from tkPack.c.) If the content is a child of the container, then do this\n\t * here. Otherwise let Tk_MaintainGeometry do the work.\n\t */\n\n\tif (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {\n\t    if ((width <= 0) || (height <= 0)) {\n\t\tTk_UnmapWindow(contentPtr->tkwin);\n\t    } else {\n\t\tif ((x != Tk_X(contentPtr->tkwin))\n\t\t\t|| (y != Tk_Y(contentPtr->tkwin))\n\t\t\t|| (width != Tk_Width(contentPtr->tkwin))\n\t\t\t|| (height != Tk_Height(contentPtr->tkwin))) {\n\t\t    Tk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);\n\t\t}\n\t\tif (abort) {\n\t\t    break;\n\t\t}\n\n\t\t/*\n\t\t * Don't map the content if the container isn't mapped: wait until\n\t\t * the container gets mapped later.\n\t\t */\n\n\t\tif (Tk_IsMapped(containerPtr->tkwin)) {\n\t\t    Tk_MapWindow(contentPtr->tkwin);\n\t\t}\n\t    }\n\t} else if ((width <= 0) || (height <= 0)) {\n\t    Tk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t} else {\n\t    Tk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin, x, y,\n\t\t    width, height);\n\t}\n    }\n\n    containerPtr->abortPtr = NULL;\n    Tcl_Release(containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ResolveConstraints --\n *\n *\tResolve all of the column and row boundaries. Most of the calculations\n *\tare identical for rows and columns, so this procedure is called twice,\n *\tonce for rows, and again for columns.\n *\n * Results:\n *\tThe offset (in pixels) from the left/top edge of this layout is\n *\treturned.\n *\n * Side effects:\n *\tThe slot offsets are copied into the SlotInfo structure for the\n *\tgeometry container.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nResolveConstraints(\n    Gridder *containerPtr,\t\t/* The geometry container for this grid. */\n    int slotType,\t\t/* Either ROW or COLUMN. */\n    int maxOffset)\t\t/* The actual maximum size of this layout in\n\t\t\t\t * pixels, or 0 (not currently used). */\n{\n    SlotInfo *slotPtr;\t/* Pointer to row/col constraints. */\n    Gridder *contentPtr;\t/* List of content windows in this grid. */\n    int constraintCount;\t/* Count of rows or columns that have\n\t\t\t\t * constraints. */\n    int slotCount;\t\t/* Last occupied row or column. */\n    int gridCount;\t\t/* The larger of slotCount and\n\t\t\t\t * constraintCount. */\n    GridLayout *layoutPtr;\t/* Temporary layout structure. */\n    int requiredSize;\t\t/* The natural size of the grid (pixels).\n\t\t\t\t * This is the minimum size needed to\n\t\t\t\t * accommodate all of the content at their\n\t\t\t\t * requested sizes. */\n    int offset;\t\t\t/* The pixel offset of the right edge of the\n\t\t\t\t * current slot from the beginning of the\n\t\t\t\t * layout. */\n    int slot;\t\t\t/* The current slot. */\n    int start;\t\t\t/* The first slot of a contiguous set whose\n\t\t\t\t * constraints are not yet fully resolved. */\n    int end;\t\t\t/* The Last slot of a contiguous set whose\n\t\t\t\t * constraints are not yet fully resolved. */\n    UniformGroup uniformPre[UNIFORM_PREALLOC];\n\t\t\t\t/* Pre-allocated space for uniform groups. */\n    UniformGroup *uniformGroupPtr;\n\t\t\t\t/* Uniform groups data. */\n    int uniformGroups;\t\t/* Number of currently used uniform groups. */\n    int uniformGroupsAlloced;\t/* Size of allocated space for uniform\n\t\t\t\t * groups. */\n    int minSize;\n    int prevGrow, accWeight, grow;\n\n    /*\n     * For typical sized tables, we'll use stack space for the layout data to\n     * avoid the overhead of a malloc and free for every layout.\n     */\n\n    GridLayout layoutData[TYPICAL_SIZE + 1];\n\n    if (slotType == COLUMN) {\n\tconstraintCount = containerPtr->containerDataPtr->columnMax;\n\tslotCount = containerPtr->containerDataPtr->columnEnd;\n\tslotPtr = containerPtr->containerDataPtr->columnPtr;\n    } else {\n\tconstraintCount = containerPtr->containerDataPtr->rowMax;\n\tslotCount = containerPtr->containerDataPtr->rowEnd;\n\tslotPtr = containerPtr->containerDataPtr->rowPtr;\n    }\n\n    /*\n     * Make sure there is enough memory for the layout.\n     */\n\n    gridCount = MAX(constraintCount, slotCount);\n    if (gridCount >= TYPICAL_SIZE) {\n\tlayoutPtr = (GridLayout *)Tcl_Alloc(sizeof(GridLayout) * (1+gridCount));\n    } else {\n\tlayoutPtr = layoutData;\n    }\n\n    /*\n     * Allocate an extra layout slot to represent the left/top edge of the 0th\n     * slot to make it easier to calculate slot widths from offsets without\n     * special case code.\n     *\n     * Initialize the \"dummy\" slot to the left/top of the table. This slot\n     * avoids special casing the first slot.\n     */\n\n    layoutPtr->minOffset = 0;\n    layoutPtr->maxOffset = 0;\n    layoutPtr++;\n\n    /*\n     * Step 1.\n     * Copy the slot constraints into the layout structure, and initialize the\n     * rest of the fields.\n     */\n\n    for (slot=0; slot < constraintCount; slot++) {\n\tlayoutPtr[slot].minSize = slotPtr[slot].minSize;\n\tlayoutPtr[slot].weight = slotPtr[slot].weight;\n\tlayoutPtr[slot].uniform = slotPtr[slot].uniform;\n\tlayoutPtr[slot].pad = slotPtr[slot].pad;\n\tlayoutPtr[slot].binNextPtr = NULL;\n    }\n    for (; slot<gridCount; slot++) {\n\tlayoutPtr[slot].minSize = 0;\n\tlayoutPtr[slot].weight = 0;\n\tlayoutPtr[slot].uniform = NULL;\n\tlayoutPtr[slot].pad = 0;\n\tlayoutPtr[slot].binNextPtr = NULL;\n    }\n\n    /*\n     * Step 2.\n     * Content with a span of 1 are used to determine the minimum size of each\n     * slot. Content whose span is two or more slots don't contribute to the\n     * minimum size of each slot directly, but can cause slots to grow if\n     * their size exceeds the the sizes of the slots they span.\n     *\n     * Bin all content whose spans are > 1 by their right edges. This allows\n     * the computation on minimum and maximum possible layout sizes at each\n     * slot boundary, without the need to re-sort the content.\n     */\n\n    switch (slotType) {\n    case COLUMN:\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\t    int rightEdge = contentPtr->column + contentPtr->numCols - 1;\n\n\t    contentPtr->size = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->padX\n\t\t    + contentPtr->iPadX + contentPtr->doubleBw;\n\t    if (contentPtr->numCols > 1) {\n\t\tcontentPtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;\n\t\tlayoutPtr[rightEdge].binNextPtr = contentPtr;\n\t    } else if (rightEdge >= 0) {\n\t\tint size = contentPtr->size + layoutPtr[rightEdge].pad;\n\n\t\tif (size > layoutPtr[rightEdge].minSize) {\n\t\t    layoutPtr[rightEdge].minSize = size;\n\t\t}\n\t    }\n\t}\n\tbreak;\n    case ROW:\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\t    int rightEdge = contentPtr->row + contentPtr->numRows - 1;\n\n\t    contentPtr->size = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->padY\n\t\t    + contentPtr->iPadY + contentPtr->doubleBw;\n\t    if (contentPtr->numRows > 1) {\n\t\tcontentPtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;\n\t\tlayoutPtr[rightEdge].binNextPtr = contentPtr;\n\t    } else if (rightEdge >= 0) {\n\t\tint size = contentPtr->size + layoutPtr[rightEdge].pad;\n\n\t\tif (size > layoutPtr[rightEdge].minSize) {\n\t\t    layoutPtr[rightEdge].minSize = size;\n\t\t}\n\t    }\n\t}\n\tbreak;\n    }\n\n    /*\n     * Step 2b.\n     * Consider demands on uniform sizes.\n     */\n\n    uniformGroupPtr = uniformPre;\n    uniformGroupsAlloced = UNIFORM_PREALLOC;\n    uniformGroups = 0;\n\n    for (slot = 0; slot < gridCount; slot++) {\n\tif (layoutPtr[slot].uniform != NULL) {\n\t\tint weight;\n\t    for (start = 0; start < uniformGroups; start++) {\n\t\tif (uniformGroupPtr[start].group == layoutPtr[slot].uniform) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (start >= uniformGroups) {\n\t\t/*\n\t\t * Have not seen that group before, set up data for it.\n\t\t */\n\n\t\tif (uniformGroups >= uniformGroupsAlloced) {\n\t\t    /*\n\t\t     * We need to allocate more space.\n\t\t     */\n\n\t\t    size_t oldSize = uniformGroupsAlloced\n\t\t\t    * sizeof(UniformGroup);\n\t\t    size_t newSize = (uniformGroupsAlloced + UNIFORM_PREALLOC)\n\t\t\t    * sizeof(UniformGroup);\n\t\t    UniformGroup *newUG = (UniformGroup *)Tcl_Alloc(newSize);\n\t\t    UniformGroup *oldUG = uniformGroupPtr;\n\n\t\t    memcpy(newUG, oldUG, oldSize);\n\t\t    if (oldUG != uniformPre) {\n\t\t\tTcl_Free(oldUG);\n\t\t    }\n\t\t    uniformGroupPtr = newUG;\n\t\t    uniformGroupsAlloced += UNIFORM_PREALLOC;\n\t\t}\n\t\tuniformGroups++;\n\t\tuniformGroupPtr[start].group = layoutPtr[slot].uniform;\n\t\tuniformGroupPtr[start].minSize = 0;\n\t    }\n\t    weight = layoutPtr[slot].weight;\n\t    weight = weight > 0 ? weight : 1;\n\t    minSize = (layoutPtr[slot].minSize + weight - 1) / weight;\n\t    if (minSize > uniformGroupPtr[start].minSize) {\n\t\tuniformGroupPtr[start].minSize = minSize;\n\t    }\n\t}\n    }\n\n    /*\n     * Data has been gathered about uniform groups. Now relayout accordingly.\n     */\n\n    if (uniformGroups > 0) {\n\tfor (slot = 0; slot < gridCount; slot++) {\n\t    if (layoutPtr[slot].uniform != NULL) {\n\t\tfor (start = 0; start < uniformGroups; start++) {\n\t\t    if (uniformGroupPtr[start].group ==\n\t\t\t    layoutPtr[slot].uniform) {\n\t\t\tint weight = layoutPtr[slot].weight;\n\t\t\tweight = weight > 0 ? weight : 1;\n\t\t\tlayoutPtr[slot].minSize =\n\t\t\t\tuniformGroupPtr[start].minSize * weight;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    if (uniformGroupPtr != uniformPre) {\n\tTcl_Free(uniformGroupPtr);\n    }\n\n    /*\n     * Step 3.\n     * Determine the minimum slot offsets going from left to right that would\n     * fit all of the content. This determines the minimum\n     */\n\n    for (offset=0,slot=0; slot < gridCount; slot++) {\n\tlayoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset;\n\tfor (contentPtr = layoutPtr[slot].binNextPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->binNextPtr) {\n\t    int span = (slotType == COLUMN) ?\n\t\t    contentPtr->numCols : contentPtr->numRows;\n\t    int required = contentPtr->size + layoutPtr[slot - span].minOffset;\n\n\t    if (required > layoutPtr[slot].minOffset) {\n\t\tlayoutPtr[slot].minOffset = required;\n\t    }\n\t}\n\toffset = layoutPtr[slot].minOffset;\n    }\n\n    /*\n     * At this point, we know the minimum required size of the entire layout.\n     * It might be prudent to stop here if our \"container\" will resize itself to\n     * this size.\n     */\n\n    requiredSize = offset;\n    if (maxOffset > offset) {\n\toffset=maxOffset;\n    }\n\n    /*\n     * Step 4.\n     * Determine the minimum slot offsets going from right to left, bounding\n     * the pixel range of each slot boundary. Pre-fill all of the right\n     * offsets with the actual size of the table; they will be reduced as\n     * required.\n     */\n\n    for (slot=0; slot < gridCount; slot++) {\n\tlayoutPtr[slot].maxOffset = offset;\n    }\n    for (slot=gridCount-1; slot > 0;) {\n\tfor (contentPtr = layoutPtr[slot].binNextPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->binNextPtr) {\n\t    int span = (slotType == COLUMN) ?\n\t\t    contentPtr->numCols : contentPtr->numRows;\n\t    int require = offset - contentPtr->size;\n\t    int startSlot = slot - span;\n\n\t    if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) {\n\t\tlayoutPtr[startSlot].maxOffset = require;\n\t    }\n\t}\n\toffset -= layoutPtr[slot].minSize;\n\tslot--;\n\tif (layoutPtr[slot].maxOffset < offset) {\n\t    offset = layoutPtr[slot].maxOffset;\n\t} else {\n\t    layoutPtr[slot].maxOffset = offset;\n\t}\n    }\n\n    /*\n     * Step 5.\n     * At this point, each slot boundary has a range of values that will\n     * satisfy the overall layout size. Make repeated passes over the layout\n     * structure looking for spans of slot boundaries where the minOffsets are\n     * less than the maxOffsets, and adjust the offsets according to the slot\n     * weights. At each pass, at least one slot boundary will have its range\n     * of possible values fixed at a single value.\n     */\n\n    for (start = 0; start < gridCount;) {\n\tint totalWeight = 0;\t/* Sum of the weights for all of the slots in\n\t\t\t\t * this span. */\n\tint need = 0;\t\t/* The minimum space needed to layout this\n\t\t\t\t * span. */\n\tint have;\t\t/* The actual amount of space that will be\n\t\t\t\t * taken up by this span. */\n\tint weight;\t\t/* Cumulative weights of the columns in this\n\t\t\t\t * span. */\n\tint noWeights = 0;\t/* True if the span has no weights. */\n\n\t/*\n\t * Find a span by identifying ranges of slots whose edges are already\n\t * constrained at fixed offsets, but whose internal slot boundaries\n\t * have a range of possible positions.\n\t */\n\n\tif (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) {\n\t    start++;\n\t    continue;\n\t}\n\n\tfor (end = start + 1; end < gridCount; end++) {\n\t    if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) {\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * We found a span. Compute the total weight, minumum space required,\n\t * for this span, and the actual amount of space the span should use.\n\t */\n\n\tfor (slot = start; slot <= end; slot++) {\n\t    totalWeight += layoutPtr[slot].weight;\n\t    need += layoutPtr[slot].minSize;\n\t}\n\thave = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset;\n\n\t/*\n\t * If all the weights in the span are zero, then distribute the extra\n\t * space evenly.\n\t */\n\n\tif (totalWeight == 0) {\n\t    noWeights++;\n\t    totalWeight = end - start + 1;\n\t}\n\n\t/*\n\t * It might not be possible to give the span all of the space\n\t * available on this pass without violating the size constraints of\n\t * one or more of the internal slot boundaries. Try to determine the\n\t * maximum amount of space that when added to the entire span, would\n\t * cause a slot boundary to have its possible range reduced to one\n\t * value, and reduce the amount of extra space allocated on this pass\n\t * accordingly.\n\t *\n\t * The calculation is done cumulatively to avoid accumulating roundoff\n\t * errors.\n\t */\n\n\tdo {\n\t    int prevMinOffset = layoutPtr[start - 1].minOffset;\n\n\t    prevGrow = 0;\n\t    accWeight = 0;\n\t    for (slot = start; slot <= end; slot++) {\n\t\tweight = noWeights ? 1 : layoutPtr[slot].weight;\n\t\taccWeight += weight;\n\t\tgrow = (have - need) * accWeight / totalWeight - prevGrow;\n\t\tprevGrow += grow;\n\n\t\tif ((weight > 0) &&\n\t\t\t((prevMinOffset + layoutPtr[slot].minSize + grow)\n\t\t\t> layoutPtr[slot].maxOffset)) {\n\t\t    int newHave;\n\n\t\t    /*\n\t\t     * There is not enough room to grow that much. Calculate\n\t\t     * how much this slot can grow and how much \"have\" that\n\t\t     * corresponds to.\n\t\t     */\n\n\t\t    grow = layoutPtr[slot].maxOffset -\n\t\t\t    layoutPtr[slot].minSize - prevMinOffset;\n\t\t    newHave = grow * totalWeight / weight;\n\t\t    if (newHave > totalWeight) {\n\t\t\t/*\n\t\t\t * By distributing multiples of totalWeight we\n\t\t\t * minimize rounding errors since they will only\n\t\t\t * happen in the last loop(s).\n\t\t\t */\n\n\t\t\tnewHave = newHave / totalWeight * totalWeight;\n\t\t    }\n\t\t    if (newHave <= 0) {\n\t\t\t/*\n\t\t\t * We can end up with a \"have\" of 0 here if the\n\t\t\t * previous slots have taken all the space. In that\n\t\t\t * case we cannot guess an appropriate \"have\" so we\n\t\t\t * just try some lower \"have\" that is >= 1, to make\n\t\t\t * sure this terminates.\n\t\t\t */\n\n\t\t\tnewHave = (have - need) - 1;\n\t\t\tif (newHave > (3 * totalWeight)) {\n\t\t\t    /*\n\t\t\t     * Go down 25% for large values.\n\t\t\t     */\n\t\t\t    newHave = newHave * 3 / 4;\n\t\t\t}\n\n\t\t\tif (newHave > totalWeight) {\n\t\t\t    /*\n\t\t\t     * Round down to a multiple of totalWeight.\n\t\t\t     */\n\t\t\t    newHave = newHave / totalWeight * totalWeight;\n\t\t\t}\n\n\t\t\tif (newHave <= 0) {\n\t\t\t    newHave = 1;\n\t\t\t}\n\t\t    }\n\t\t    have = newHave + need;\n\n\t\t    /*\n\t\t     * Restart loop to check if the new \"have\" will fit.\n\t\t     */\n\n\t\t    break;\n\t\t}\n\t\tprevMinOffset += layoutPtr[slot].minSize + grow;\n\t\tif (prevMinOffset < layoutPtr[slot].minOffset) {\n\t\t    prevMinOffset = layoutPtr[slot].minOffset;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Quit the outer loop if the inner loop ran all the way.\n\t     */\n\t} while (slot <= end);\n\n\t/*\n\t * Now distribute the extra space among the slots by adjusting the\n\t * minSizes and minOffsets.\n\t */\n\n\tprevGrow = 0;\n\taccWeight = 0;\n\tfor (slot = start; slot <= end; slot++) {\n\t    accWeight += noWeights ? 1 : layoutPtr[slot].weight;\n\t    grow = (have - need) * accWeight / totalWeight - prevGrow;\n\t    prevGrow += grow;\n\t    layoutPtr[slot].minSize += grow;\n\t    if ((layoutPtr[slot-1].minOffset + layoutPtr[slot].minSize)\n\t\t    > layoutPtr[slot].minOffset) {\n\t\tlayoutPtr[slot].minOffset = layoutPtr[slot-1].minOffset +\n\t\t\tlayoutPtr[slot].minSize;\n\t    }\n\t}\n\n\t/*\n\t * Having pushed the top/left boundaries of the slots to take up extra\n\t * space, the bottom/right space is recalculated to propagate the new\n\t * space allocation.\n\t */\n\n\tfor (slot = end; slot > start; slot--) {\n\t    /*\n\t     * maxOffset may not go up.\n\t     */\n\n\t    if ((layoutPtr[slot].maxOffset-layoutPtr[slot].minSize)\n\t\t    < layoutPtr[slot-1].maxOffset) {\n\t\tlayoutPtr[slot-1].maxOffset =\n\t\t\tlayoutPtr[slot].maxOffset-layoutPtr[slot].minSize;\n\t    }\n\t}\n    }\n\n    /*\n     * Step 6.\n     * All of the space has been apportioned; copy the layout information back\n     * into the container.\n     */\n\n    for (slot=0; slot < gridCount; slot++) {\n\tslotPtr[slot].offset = layoutPtr[slot].minOffset;\n    }\n\n    --layoutPtr;\n    if (layoutPtr != layoutData) {\n\tTcl_Free(layoutPtr);\n    }\n    return requiredSize;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetGrid --\n *\n *\tThis internal procedure is used to locate a Grid structure for a given\n *\twindow, creating one if one doesn't exist already, except if the window\n *\tis already dead.\n *\n * Results:\n *\tThe return value is a pointer to the Grid structure corresponding to\n *\ttkwin, or NULL when tkwin is already dead.\n *\n * Side effects:\n *\tA new grid structure may be created. If so, then a callback is set up\n *\tto clean things up when the window is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Gridder *\nGetGrid(\n    Tk_Window tkwin)\t\t/* Token for window for which grid structure\n\t\t\t\t * is desired. */\n{\n    Gridder *gridPtr;\n    Tcl_HashEntry *hPtr;\n    int isNew;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (((TkWindow *) tkwin)->flags & TK_ALREADY_DEAD) {\n\treturn NULL;\n    }\n\n    if (!dispPtr->gridInit) {\n\tTcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS);\n\tdispPtr->gridInit = 1;\n    }\n\n    /*\n     * See if there's already grid for this window. If not, then create a new\n     * one.\n     */\n\n    hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char*) tkwin, &isNew);\n    if (!isNew) {\n\treturn (Gridder *)Tcl_GetHashValue(hPtr);\n    }\n    gridPtr = (Gridder *)Tcl_Alloc(sizeof(Gridder));\n    gridPtr->tkwin = tkwin;\n    gridPtr->containerPtr = NULL;\n    gridPtr->containerDataPtr = NULL;\n    gridPtr->nextPtr = NULL;\n    gridPtr->contentPtr = NULL;\n    gridPtr->binNextPtr = NULL;\n\n    gridPtr->column = -1;\n    gridPtr->row = -1;\n    gridPtr->numCols = 1;\n    gridPtr->numRows = 1;\n\n    gridPtr->padX = 0;\n    gridPtr->padY = 0;\n    gridPtr->padLeft = 0;\n    gridPtr->padTop = 0;\n    gridPtr->iPadX = 0;\n    gridPtr->iPadY = 0;\n    gridPtr->doubleBw = 2 * Tk_Changes(tkwin)->border_width;\n    gridPtr->abortPtr = NULL;\n    gridPtr->flags = 0;\n    gridPtr->sticky = 0;\n    gridPtr->size = 0;\n    gridPtr->in = NULL;\n    Tcl_SetHashValue(hPtr, gridPtr);\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t    GridStructureProc, gridPtr);\n    return gridPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetGridSize --\n *\n *\tThis internal procedure sets the size of the grid occupied by content.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe width and height arguments are filled in the container data\n *\tstructure. Additional space is allocated for the constraints to\n *\taccommodate the offsets.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSetGridSize(\n    Gridder *containerPtr)\t\t/* The geometry container for this grid. */\n{\n    Gridder *contentPtr;\t/* Current content window. */\n    int maxX = 0, maxY = 0;\n\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tmaxX = MAX(maxX, contentPtr->numCols + contentPtr->column);\n\tmaxY = MAX(maxY, contentPtr->numRows + contentPtr->row);\n    }\n    containerPtr->containerDataPtr->columnEnd = maxX;\n    containerPtr->containerDataPtr->rowEnd = maxY;\n    CheckSlotData(containerPtr, maxX, COLUMN, CHECK_SPACE);\n    CheckSlotData(containerPtr, maxY, ROW, CHECK_SPACE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetContentColumn --\n *\n *\tUpdate column data for a content, checking that MAX_ELEMENT bound\n *      is not passed.\n *\n * Results:\n *\tTCL_ERROR if out of bounds, TCL_OK otherwise\n *\n * Side effects:\n *\tContent fields are updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetContentColumn(\n    Tcl_Interp *interp,\t\t/* Interp for error message. */\n    Gridder *contentPtr,\t\t/* Content to be updated. */\n    int column,\t\t\t/* New column or -1 to be unchanged. */\n    int numCols)\t\t/* New columnspan or -1 to be unchanged. */\n{\n    int newColumn, newNumCols, lastCol;\n\n    newColumn = (column >= 0) ? column : contentPtr->column;\n    newNumCols = (numCols >= 1) ? numCols : contentPtr->numCols;\n\n    lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols;\n    if (lastCol >= MAX_ELEMENT) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"column out of bounds\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"BAD_COLUMN\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    contentPtr->column = newColumn;\n    contentPtr->numCols = newNumCols;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetContentRow --\n *\n *\tUpdate row data for a content, checking that MAX_ELEMENT bound\n *      is not passed.\n *\n * Results:\n *\tTCL_ERROR if out of bounds, TCL_OK otherwise\n *\n * Side effects:\n *\tContent fields are updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetContentRow(\n    Tcl_Interp *interp,\t\t/* Interp for error message. */\n    Gridder *contentPtr,\t\t/* Content to be updated. */\n    int row,\t\t\t/* New row or -1 to be unchanged. */\n    int numRows)\t\t/* New rowspan or -1 to be unchanged. */\n{\n    int newRow, newNumRows, lastRow;\n\n    newRow = (row >= 0) ? row : contentPtr->row;\n    newNumRows = (numRows >= 1) ? numRows : contentPtr->numRows;\n\n    lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows;\n    if (lastRow >= MAX_ELEMENT) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"row out of bounds\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"BAD_ROW\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    contentPtr->row = newRow;\n    contentPtr->numRows = newNumRows;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckSlotData --\n *\n *\tThis internal procedure is used to manage the storage for row and\n *\tcolumn (slot) constraints.\n *\n * Results:\n *\tTRUE if the index is OK, False otherwise.\n *\n * Side effects:\n *\tA new container grid structure may be created. If so, then it is\n *\tinitialized. In addition, additional storage for a row or column\n *\tconstraints may be allocated, and the constraint maximums are\n *\tadjusted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCheckSlotData(\n    Gridder *containerPtr,\t\t/* The geometry container for this grid. */\n    Tcl_Size slot,\t\t\t/* Which slot to look at. */\n    int slotType,\t\t/* ROW or COLUMN. */\n    int checkOnly)\t\t/* Don't allocate new space if true. */\n{\n    Tcl_Size numSlot;\t\t/* Number of slots already allocated (Space) */\n    int end;\t\t\t/* Last used constraint. */\n\n    /*\n     * If slot is out of bounds, return immediately.\n     */\n\n    if (slot < 0 || slot >= MAX_ELEMENT) {\n\treturn TCL_ERROR;\n    }\n\n    if ((checkOnly == CHECK_ONLY) && (containerPtr->containerDataPtr == NULL)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If we need to allocate more space, allocate a little extra to avoid\n     * repeated re-alloc's for large tables. We need enough space to hold all\n     * of the offsets as well.\n     */\n\n    InitContainerData(containerPtr);\n    end = (slotType == ROW) ? containerPtr->containerDataPtr->rowMax :\n\t    containerPtr->containerDataPtr->columnMax;\n    if (checkOnly == CHECK_ONLY) {\n\treturn ((end < slot) ? TCL_ERROR : TCL_OK);\n    } else {\n\tnumSlot = (slotType == ROW) ? containerPtr->containerDataPtr->rowSpace\n\t\t: containerPtr->containerDataPtr->columnSpace;\n\tif (slot >= numSlot) {\n\t    int newNumSlot = slot + PREALLOC;\n\t    size_t oldSize = numSlot * sizeof(SlotInfo);\n\t    size_t newSize = newNumSlot * sizeof(SlotInfo);\n\t    SlotInfo *newSI = (SlotInfo *)Tcl_Alloc(newSize);\n\t    SlotInfo *oldSI = (slotType == ROW)\n\t\t    ? containerPtr->containerDataPtr->rowPtr\n\t\t    : containerPtr->containerDataPtr->columnPtr;\n\n\t    memcpy(newSI, oldSI, oldSize);\n\t    memset(newSI+numSlot, 0, newSize - oldSize);\n\t    Tcl_Free(oldSI);\n\t    if (slotType == ROW) {\n\t\tcontainerPtr->containerDataPtr->rowPtr = newSI;\n\t\tcontainerPtr->containerDataPtr->rowSpace = newNumSlot;\n\t    } else {\n\t\tcontainerPtr->containerDataPtr->columnPtr = newSI;\n\t\tcontainerPtr->containerDataPtr->columnSpace = newNumSlot;\n\t    }\n\t}\n\tif (slot >= end && checkOnly != CHECK_SPACE) {\n\t    if (slotType == ROW) {\n\t\tcontainerPtr->containerDataPtr->rowMax = slot+1;\n\t    } else {\n\t\tcontainerPtr->containerDataPtr->columnMax = slot+1;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitContainerData --\n *\n *\tThis internal procedure is used to allocate and initialize the data\n *\tfor a geometry container, if the data doesn't exist already.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tA new container grid structure may be created. If so, then it is\n *\tinitialized.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitContainerData(\n    Gridder *containerPtr)\n{\n    if (containerPtr->containerDataPtr == NULL) {\n\tGridContainer *gridPtr = containerPtr->containerDataPtr = (GridContainer *)\n\t\tTcl_Alloc(sizeof(GridContainer));\n\tsize_t size = sizeof(SlotInfo) * TYPICAL_SIZE;\n\n\tgridPtr->columnEnd = 0;\n\tgridPtr->columnMax = 0;\n\tgridPtr->columnPtr = (SlotInfo *)Tcl_Alloc(size);\n\tgridPtr->columnSpace = TYPICAL_SIZE;\n\tgridPtr->rowEnd = 0;\n\tgridPtr->rowMax = 0;\n\tgridPtr->rowPtr = (SlotInfo *)Tcl_Alloc(size);\n\tgridPtr->rowSpace = TYPICAL_SIZE;\n\tgridPtr->startX = 0;\n\tgridPtr->startY = 0;\n\tgridPtr->anchor = GRID_DEFAULT_ANCHOR;\n\n\tmemset(gridPtr->columnPtr, 0, size);\n\tmemset(gridPtr->rowPtr, 0, size);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Unlink --\n *\n *\tRemove a grid from its container's list of content.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe container will be scheduled for re-arranging, and the size of the\n *\tgrid will be adjusted accordingly\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnlink(\n    Gridder *contentPtr)\t/* Window to unlink. */\n{\n    Gridder *containerPtr, *contentPtr2;\n\n    containerPtr = contentPtr->containerPtr;\n    if (containerPtr == NULL) {\n\treturn;\n    }\n\n    if (containerPtr->contentPtr == contentPtr) {\n\tcontainerPtr->contentPtr = contentPtr->nextPtr;\n    } else {\n\tfor (contentPtr2=containerPtr->contentPtr ; ; contentPtr2=contentPtr2->nextPtr) {\n\t    if (contentPtr2 == NULL) {\n\t\tTcl_Panic(\"Unlink couldn't find previous window\");\n\t    }\n\t    if (contentPtr2->nextPtr == contentPtr) {\n\t\tcontentPtr2->nextPtr = contentPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {\n\tcontainerPtr->flags |= REQUESTED_RELAYOUT;\n\tTcl_DoWhenIdle(ArrangeGrid, containerPtr);\n    }\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n\n    SetGridSize(contentPtr->containerPtr);\n    contentPtr->containerPtr = NULL;\n\n    /*\n     * If we have emptied this container from content it means we are no longer\n     * handling it and should mark it as free.\n     *\n     * Send the event \"NoManagedChild\" to the container to inform it about there\n     * being no managed children inside it.\n     */\n\n    if ((containerPtr->contentPtr == NULL) && (containerPtr->flags & ALLOCED_CONTAINER)) {\n\tTkFreeGeometryContainer(containerPtr->tkwin, \"grid\");\n\tcontainerPtr->flags &= ~ALLOCED_CONTAINER;\n\tTk_SendVirtualEvent(containerPtr->tkwin, \"NoManagedChild\", NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyGrid --\n *\n *\tThis procedure is invoked by Tcl_EventuallyFree or Tcl_Release to\n *\tclean up the internal structure of a grid at a safe time (when no-one\n *\tis using it anymore). Cleaning up the grid involves freeing the main\n *\tstructure for all windows and the container structure for geometry\n *\tmanagers.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the grid is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyGrid(\n    void *memPtr)\t\t/* Info about window that is now dead. */\n{\n    Gridder *gridPtr = (Gridder *)memPtr;\n\n    if (gridPtr->flags & REQUESTED_RELAYOUT) {\n\tTcl_CancelIdleCall(ArrangeGrid, gridPtr);\n    }\n    if (gridPtr->containerDataPtr != NULL) {\n\tif (gridPtr->containerDataPtr->rowPtr != NULL) {\n\t    Tcl_Free(gridPtr->containerDataPtr -> rowPtr);\n\t}\n\tif (gridPtr->containerDataPtr->columnPtr != NULL) {\n\t    Tcl_Free(gridPtr->containerDataPtr -> columnPtr);\n\t}\n\tTcl_Free(gridPtr->containerDataPtr);\n    }\n    if (gridPtr->in != NULL) {\n\tTcl_DecrRefCount(gridPtr->in);\n    }\n    Tcl_Free(gridPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GridStructureProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher in response to\n *\tStructureNotify events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf a window was just deleted, clean up all its grid-related\n *\tinformation. If it was just resized, re-configure its content, if any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGridStructureProc(\n    void *clientData,\t/* Our information about window referred to by\n\t\t\t\t * eventPtr. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Gridder *gridPtr = (Gridder *)clientData;\n    TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr;\n\n    if (eventPtr->type == ConfigureNotify) {\n\tif ((gridPtr->contentPtr != NULL)\n\t\t&& !(gridPtr->flags & REQUESTED_RELAYOUT)) {\n\t    gridPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, gridPtr);\n\t}\n\tif ((gridPtr->containerPtr != NULL) &&\n\t\t(gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) {\n\t    if (!(gridPtr->containerPtr->flags & REQUESTED_RELAYOUT)) {\n\t\tgridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width;\n\t\tgridPtr->containerPtr->flags |= REQUESTED_RELAYOUT;\n\t\tTcl_DoWhenIdle(ArrangeGrid, gridPtr->containerPtr);\n\t    }\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tGridder *contentPtr, *nextPtr;\n\n\tif (gridPtr->containerPtr != NULL) {\n\t    Unlink(gridPtr);\n\t}\n\tfor (contentPtr = gridPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = nextPtr) {\n\t    Tk_ManageGeometry(contentPtr->tkwin, NULL, NULL);\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t    contentPtr->containerPtr = NULL;\n\t    nextPtr = contentPtr->nextPtr;\n\t    contentPtr->nextPtr = NULL;\n\t}\n\tTcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable,\n\t\tgridPtr->tkwin));\n\tif (gridPtr->flags & REQUESTED_RELAYOUT) {\n\t    Tcl_CancelIdleCall(ArrangeGrid, gridPtr);\n\t}\n\tgridPtr->tkwin = NULL;\n\tTcl_EventuallyFree(gridPtr, DestroyGrid);\n    } else if (eventPtr->type == MapNotify) {\n\tif ((gridPtr->contentPtr != NULL)\n\t\t&& !(gridPtr->flags & REQUESTED_RELAYOUT)) {\n\t    gridPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, gridPtr);\n\t}\n    } else if (eventPtr->type == UnmapNotify) {\n\tGridder *contentPtr;\n\n\tfor (contentPtr = gridPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureContent --\n *\n *\tThis implements the guts of the \"grid configure\" command. Given a list\n *\tof content and configuration options, it arranges for the grid to\n *\tmanage the content and sets the specified options. Arguments consist\n *\tof windows or window shortcuts followed by \"-option value\" pairs.\n *\n * Results:\n *\tTCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned\n *\tand the interp's result is set to contain an error message.\n *\n * Side effects:\n *\tContent windows get taken over by the grid.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureContent(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Any window in application containing\n\t\t\t\t * content. Used to look up content names. */\n    Tcl_Size objc,\t\t\t/* Number of elements in argv. */\n    Tcl_Obj *const objv[])\t/* Argument objects: contains one or more\n\t\t\t\t * window names followed by any number of\n\t\t\t\t * \"option value\" pairs. Caller must make sure\n\t\t\t\t * that there is at least one window name. */\n{\n    Gridder *containerPtr = NULL;\n    Gridder *contentPtr;\n    Tk_Window other, content, parent, ancestor;\n    TkWindow *container;\n    Tcl_Size i, j, numWindows;\n    int width, tmp;\n    int defaultRow = -1;\n    int defaultColumn = 0;\t/* Default column number */\n    int defaultColumnSpan = 1;\t/* Default number of columns */\n    const char *lastWindow;\t/* Use this window to base current row/col\n\t\t\t\t * on */\n    int numSkip;\t\t/* Number of 'x' found */\n    static const char *const optionStrings[] = {\n\t\"-column\", \"-columnspan\", \"-in\", \"-ipadx\", \"-ipady\",\n\t\"-padx\", \"-pady\", \"-row\", \"-rowspan\", \"-sticky\", NULL\n    };\n    enum options {\n\tCONF_COLUMN, CONF_COLUMNSPAN, CONF_IN, CONF_IPADX, CONF_IPADY,\n\tCONF_PADX, CONF_PADY, CONF_ROW, CONF_ROWSPAN, CONF_STICKY };\n    int index;\n    const char *string;\n    char firstChar;\n    int positionGiven;\n\n    /*\n     * Count the number of windows, or window short-cuts.\n     */\n\n    firstChar = 0;\n    for (numWindows=0, i=0; i < objc; i++) {\n\tTcl_Size length;\n\tchar prevChar = firstChar;\n\n\tstring = Tcl_GetStringFromObj(objv[i], &length);\n\tfirstChar = string[0];\n\n\tif (firstChar == '.') {\n\t    /*\n\t     * Check that windows are valid, and locate the first content's\n\t     * parent window (default for -in).\n\t     */\n\n\t    if (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (containerPtr == NULL) {\n\t\t/*\n\t\t * Is there any saved -in from a removed content?\n\t\t * If there is, it becomes default for -in.\n\t\t * If the stored container does not exist, just ignore it.\n\t\t */\n\n\t\tif (!(contentPtr = GetGrid(content))) {\n\t\t    continue;\n\t\t}\n\t\tif (contentPtr->in != NULL) {\n\t\t    if (TkGetWindowFromObj(interp, content, contentPtr->in, &parent)\n\t\t\t    == TCL_OK) {\n\t\t\tif (!(containerPtr = GetGrid(parent))) {\n\t\t\t    continue;\n\t\t\t}\n\t\t\tInitContainerData(containerPtr);\n\t\t    }\n\t\t}\n\t    }\n\t    if (containerPtr == NULL) {\n\t\tparent = Tk_Parent(content);\n\t\tif (parent != NULL) {\n\t\t    if (!(containerPtr = GetGrid(parent))) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    InitContainerData(containerPtr);\n\t\t}\n\t    }\n\t    numWindows++;\n\t    continue;\n\t}\n\tif (length > 1 && i == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad argument \\\"%s\\\": must be name of window\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"BAD_PARAMETER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (length > 1 && firstChar == '-') {\n\t    break;\n\t}\n\tif (length > 1) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"unexpected parameter \\\"%s\\\" in configure list:\"\n\t\t    \" should be window name or option\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"BAD_PARAMETER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif ((firstChar == REL_HORIZ) && ((numWindows == 0) ||\n\t\t(prevChar == REL_SKIP) || (prevChar == REL_VERT))) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"must specify window before shortcut '-'\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"SHORTCUT_USAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif ((firstChar == REL_VERT) || (firstChar == REL_SKIP)\n\t\t|| (firstChar == REL_HORIZ)) {\n\t    continue;\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"invalid window shortcut, \\\"%s\\\" should be '-', 'x', or '^'\",\n\t\tstring));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"SHORTCUT_USAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    numWindows = i;\n\n    if ((objc - numWindows) & 1) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"extra option or option with no value\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"BAD_PARAMETER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Go through all options looking for -in and -row, which are needed to be\n     * found first to handle the special case where ^ is used on a row without\n     * windows names, but with an -in option. Since all options are checked\n     * here, we do not need to handle the error case again later.\n     */\n\n    for (i = numWindows; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == CONF_IN) {\n\t    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) !=\n\t\t    TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (!(containerPtr = GetGrid(other))) {\n\t\tcontinue;\n\t    }\n\t    InitContainerData(containerPtr);\n\t} else if (index == CONF_ROW) {\n\t    if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK\n\t\t    || tmp < 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"bad row value \\\"%s\\\": must be a non-negative integer\",\n\t\t\tTcl_GetString(objv[i+1])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"POSITIVE_INT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    defaultRow = tmp;\n\t}\n    }\n\n    /*\n     * If no -row is given, use the next row after the highest occupied row\n     * of the container.\n     */\n\n    if (defaultRow < 0) {\n\tif (containerPtr != NULL && containerPtr->containerDataPtr != NULL) {\n\t    SetGridSize(containerPtr);\n\t    defaultRow = containerPtr->containerDataPtr->rowEnd;\n\t} else {\n\t    defaultRow = 0;\n\t}\n    }\n\n    /*\n     * Iterate over all of the content windows and short-cuts, parsing options\n     * for each content. It's a bit wasteful to re-parse the options for each\n     * content, but things get too messy if we try to parse the arguments just\n     * once at the beginning. For example, if a content already is managed we\n     * want to just change a few existing values without resetting everything.\n     * If there are multiple windows, the -in option only gets processed for\n     * the first window.\n     */\n\n    positionGiven = 0;\n    for (j = 0; j < numWindows; j++) {\n\tstring = Tcl_GetString(objv[j]);\n\tfirstChar = string[0];\n\n\t/*\n\t * '^' and 'x' cause us to skip a column. '-' is processed as part of\n\t * its preceeding content.\n\t */\n\n\tif ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) {\n\t    defaultColumn++;\n\t    continue;\n\t}\n\tif (firstChar == REL_HORIZ) {\n\t    continue;\n\t}\n\n\tfor (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows;\n\t\tdefaultColumnSpan++) {\n\t    string = Tcl_GetString(objv[j + defaultColumnSpan]);\n\n\t    if (*string != REL_HORIZ) {\n\t\tbreak;\n\t    }\n\t}\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[j], &content) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tk_TopWinHierarchy(content)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't manage \\\"%s\\\": it's a top-level window\",\n\t\t    Tcl_GetString(objv[j])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"TOPLEVEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (!(contentPtr = GetGrid(content))) {\n\t    continue;\n\t}\n\n\t/*\n\t * The following statement is taken from tkPack.c:\n\t *\n\t * \"If the content isn't currently managed, reset all of its\n\t * configuration information to default values (there could be old\n\t * values left from a previous packer).\"\n\t *\n\t * I [D.S.] disagree with this statement. If a content is disabled\n\t * (using \"forget\") and then re-enabled, I submit that 90% of the time\n\t * the programmer will want it to retain its old configuration\n\t * information. If the programmer doesn't want this behavior, then the\n\t * defaults can be reestablished by hand, without having to worry\n\t * about keeping track of the old state.\n\t */\n\n\tfor (i = numWindows; i < objc; i += 2) {\n\t    Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\t    sizeof(char *), \"option\", 0, &index);\n\t    switch ((enum options) index) {\n\t    case CONF_COLUMN:\n\t\tif (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK\n\t\t\t|| tmp < 0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad column value \\\"%s\\\": must be a non-negative integer\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"COLUMN\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (SetContentColumn(interp, contentPtr, tmp, -1) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_COLUMNSPAN:\n\t\tif (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK\n\t\t\t|| tmp <= 0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad columnspan value \\\"%s\\\": must be a positive integer\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SPAN\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (SetContentColumn(interp, contentPtr, -1, tmp) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_IN:\n\t\tif (TkGetWindowFromObj(interp, tkwin, objv[i+1],\n\t\t\t&other) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (other == content) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"window can't be managed in itself\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"SELF\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tpositionGiven = 1;\n\t\tif (!(containerPtr = GetGrid(other))) {\n\t\t    continue;\n\t\t}\n\t\tInitContainerData(containerPtr);\n\t\tbreak;\n\t    case CONF_STICKY: {\n\t\tint sticky = StringToSticky(Tcl_GetString(objv[i+1]));\n\n\t\tif (sticky == -1) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad stickyness value \\\"%s\\\": must be\"\n\t\t\t    \" a string containing n, e, s, and/or w\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"STICKY\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->sticky = sticky;\n\t\tbreak;\n\t    }\n\t    case CONF_IPADX:\n\t\tif ((Tk_GetPixelsFromObj(NULL, content, objv[i+1],\n\t\t\t&tmp) != TCL_OK) || (tmp < 0)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad ipadx value \\\"%s\\\": must be positive screen distance\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INT_PAD\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->iPadX = tmp * 2;\n\t\tbreak;\n\t    case CONF_IPADY:\n\t\tif ((Tk_GetPixelsFromObj(NULL, content, objv[i+1],\n\t\t\t&tmp) != TCL_OK) || (tmp < 0)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad ipady value \\\"%s\\\": must be positive screen distance\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INT_PAD\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->iPadY = tmp * 2;\n\t\tbreak;\n\t    case CONF_PADX:\n\t\tif (TkParsePadAmount(interp, tkwin, objv[i+1],\n\t\t\t&contentPtr->padLeft, &contentPtr->padX) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_PADY:\n\t\tif (TkParsePadAmount(interp, tkwin, objv[i+1],\n\t\t\t&contentPtr->padTop, &contentPtr->padY) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_ROW:\n\t\tif (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK\n\t\t\t|| tmp < 0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad row value \\\"%s\\\": must be a non-negative integer\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"COLUMN\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (SetContentRow(interp, contentPtr, tmp, -1) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_ROWSPAN:\n\t\tif ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK)\n\t\t\t|| tmp <= 0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad rowspan value \\\"%s\\\": must be a positive integer\",\n\t\t\t    Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SPAN\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (SetContentRow(interp, contentPtr, -1, tmp) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * If no position was specified via -in and the content is already\n\t * packed, then leave it in its current location.\n\t */\n\n\tif (!positionGiven && (contentPtr->containerPtr != NULL)) {\n\t    containerPtr = contentPtr->containerPtr;\n\t    goto scheduleLayout;\n\t}\n\n\t/*\n\t * If the same -in window is passed in again, then just leave it in\n\t * its current location.\n\t */\n\n\tif (positionGiven && (containerPtr == contentPtr->containerPtr)) {\n\t    goto scheduleLayout;\n\t}\n\n\t/*\n\t * Make sure we have a geometry container. We look at:\n\t *  1)   the -in flag\n\t *  2)   the parent of the first content.\n\t */\n\n\tparent = Tk_Parent(content);\n\tif (containerPtr == NULL) {\n\t    if (!(containerPtr = GetGrid(parent))) {\n\t\tcontinue;\n\t    }\n\t    InitContainerData(containerPtr);\n\t}\n\n\tif (contentPtr->containerPtr != NULL && contentPtr->containerPtr != containerPtr) {\n\t    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\t\tTk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n\t    }\n\t    Unlink(contentPtr);\n\t    contentPtr->containerPtr = NULL;\n\t}\n\n\tif (contentPtr->containerPtr == NULL) {\n\t    Gridder *tempPtr = containerPtr->contentPtr;\n\n\t    contentPtr->containerPtr = containerPtr;\n\t    containerPtr->contentPtr = contentPtr;\n\t    contentPtr->nextPtr = tempPtr;\n\t}\n\n\t/*\n\t * Make sure that the content's parent is either the container or an\n\t * ancestor of the container, and that the container and content aren't the\n\t * same.\n\t */\n\n\tfor (ancestor = containerPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {\n\t    if (ancestor == parent) {\n\t\tbreak;\n\t    }\n\t    if (Tk_TopWinHierarchy(ancestor)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't put \\\"%s\\\" inside \\\"%s\\\"\", Tcl_GetString(objv[j]),\n\t\t\tTk_PathName(containerPtr->tkwin)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\", (char *)NULL);\n\t\tUnlink(contentPtr);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * Check for management loops.\n\t */\n\n\tfor (container = (TkWindow *)containerPtr->tkwin; container != NULL;\n\t     container = (TkWindow *)TkGetContainer(container)) {\n\t    if (container == (TkWindow *)content) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't put \\\"%s\\\" inside \\\"%s\\\": would cause management loop\",\n\t\t    Tcl_GetString(objv[j]), Tk_PathName(containerPtr->tkwin)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"LOOP\", (char *)NULL);\n\t\tUnlink(contentPtr);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (containerPtr->tkwin != Tk_Parent(content)) {\n\t    ((TkWindow *)content)->maintainerPtr = (TkWindow *)containerPtr->tkwin;\n\t}\n\n\tTk_ManageGeometry(content, &gridMgrType, contentPtr);\n\n\tif (!(containerPtr->flags & DONT_PROPAGATE)) {\n\t    if (TkSetGeometryContainer(interp, containerPtr->tkwin, \"grid\")\n\t\t    != TCL_OK) {\n\t\tTk_ManageGeometry(content, NULL, NULL);\n\t\tUnlink(contentPtr);\n\t\treturn TCL_ERROR;\n\t    }\n\t    containerPtr->flags |= ALLOCED_CONTAINER;\n\t}\n\n\t/*\n\t * Assign default position information.\n\t */\n\n\tif (contentPtr->column == -1) {\n\t    if (SetContentColumn(interp, contentPtr, defaultColumn,-1) != TCL_OK){\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (SetContentColumn(interp, contentPtr, -1,\n\t\tcontentPtr->numCols + defaultColumnSpan - 1) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (contentPtr->row == -1) {\n\t    if (SetContentRow(interp, contentPtr, defaultRow, -1) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tdefaultColumn += contentPtr->numCols;\n\tdefaultColumnSpan = 1;\n\n\t/*\n\t * Arrange for the container to be re-arranged at the first idle moment.\n\t */\n\n    scheduleLayout:\n\tif (containerPtr->abortPtr != NULL) {\n\t    *containerPtr->abortPtr = 1;\n\t}\n\tif (!(containerPtr->flags & REQUESTED_RELAYOUT)) {\n\t    containerPtr->flags |= REQUESTED_RELAYOUT;\n\t    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);\n\t}\n    }\n\n    /*\n     * Now look for all the \"^\"'s.\n     */\n\n    lastWindow = NULL;\n    numSkip = 0;\n    for (j = 0; j < numWindows; j++) {\n\tstruct Gridder *otherPtr;\n\tint match;\t\t\t/* Found a match for the ^ */\n\tint lastRow, lastColumn;\t/* Implied end of table. */\n\n\tstring = Tcl_GetString(objv[j]);\n\tfirstChar = string[0];\n\n\tif (firstChar == '.') {\n\t    lastWindow = string;\n\t    numSkip = 0;\n\t}\n\tif (firstChar == REL_SKIP) {\n\t    numSkip++;\n\t}\n\tif (firstChar != REL_VERT) {\n\t    continue;\n\t}\n\n\tif (containerPtr == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't use '^', can't find container window\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"SHORTCUT_USAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Count the number of consecutive ^'s starting from this position.\n\t */\n\n\tfor (width = 1; width + j < numWindows; width++) {\n\t    string = Tcl_GetString(objv[j+width]);\n\n\t    if (*string != REL_VERT) {\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * Find the implied grid location of the ^\n\t */\n\n\tif (lastWindow == NULL) {\n\t    lastRow = defaultRow - 1;\n\t    lastColumn = 0;\n\t} else {\n\t    other = Tk_NameToWindow(interp, lastWindow, tkwin);\n\t    if (!(otherPtr = GetGrid(other))) {\n\t\tcontinue;\n\t    }\n\t    lastRow = otherPtr->row + otherPtr->numRows - 2;\n\t    lastColumn = otherPtr->column + otherPtr->numCols;\n\t}\n\n\tlastColumn += numSkip;\n\n\tmatch = 0;\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\n\t    if (contentPtr->column == lastColumn\n\t\t    && contentPtr->row + contentPtr->numRows - 1 == lastRow) {\n\t\tif (contentPtr->numCols <= width) {\n\t\t    if (SetContentRow(interp, contentPtr, -1,\n\t\t\t    contentPtr->numRows + 1) != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    match++;\n\t\t    j += contentPtr->numCols - 1;\n\t\t    lastWindow = Tk_PathName(contentPtr->tkwin);\n\t\t    numSkip = 0;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (!match) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't find content to extend with \\\"^\\\"\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GRID\", \"SHORTCUT_USAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (containerPtr == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't determine container window\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"GRID\", \"SHORTCUT_USAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    SetGridSize(containerPtr);\n\n    /*\n     * If we have emptied this container from content it means we are no longer\n     * handling it and should mark it as free.\n     *\n     * Send the event \"NoManagedChild\" to the container to inform it about there\n     * being no managed children inside it.\n     */\n\n    if (containerPtr->contentPtr == NULL && containerPtr->flags & ALLOCED_CONTAINER) {\n\tTkFreeGeometryContainer(containerPtr->tkwin, \"grid\");\n\tcontainerPtr->flags &= ~ALLOCED_CONTAINER;\n\tTk_SendVirtualEvent(containerPtr->tkwin, \"NoManagedChild\", NULL);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StickyToObj\n *\n *\tConverts the internal boolean combination of \"sticky\" bits onto a Tcl\n *\tlist element containing zero or more of n, s, e, or w.\n *\n * Results:\n *\tA new object is returned that holds the sticky representation.\n *\n * Side effects:\n *\tnone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nStickyToObj(\n    int flags)\t\t\t/* The sticky flags. */\n{\n    int count = 0;\n    char buffer[4];\n\n    if (flags & STICK_NORTH) {\n\tbuffer[count++] = 'n';\n    }\n    if (flags & STICK_EAST) {\n\tbuffer[count++] = 'e';\n    }\n    if (flags & STICK_SOUTH) {\n\tbuffer[count++] = 's';\n    }\n    if (flags & STICK_WEST) {\n\tbuffer[count++] = 'w';\n    }\n    return Tcl_NewStringObj(buffer, count);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringToSticky --\n *\n *\tConverts an ascii string representing a widgets stickyness into the\n *\tboolean result.\n *\n * Results:\n *\tThe boolean combination of the \"sticky\" bits is retuned. If an error\n *\toccurs, such as an invalid character, -1 is returned instead.\n *\n * Side effects:\n *\tnone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringToSticky(\n    const char *string)\n{\n    int sticky = 0;\n    char c;\n\n    while ((c = *string++) != '\\0') {\n\tswitch (c) {\n\tcase 'n': case 'N':\n\t    sticky |= STICK_NORTH;\n\t    break;\n\tcase 'e': case 'E':\n\t    sticky |= STICK_EAST;\n\t    break;\n\tcase 's': case 'S':\n\t    sticky |= STICK_SOUTH;\n\t    break;\n\tcase 'w': case 'W':\n\t    sticky |= STICK_WEST;\n\t    break;\n\tcase ' ': case ',': case '\\t': case '\\r': case '\\n':\n\t    break;\n\tdefault:\n\t    return -1;\n\t}\n    }\n    return sticky;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NewPairObj --\n *\n *\tCreates a new list object and fills it with two integer objects.\n *\n * Results:\n *\tThe newly created list object is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nNewPairObj(\n    Tcl_WideInt val1, Tcl_WideInt val2)\n{\n    Tcl_Obj *ary[2];\n\n    ary[0] = Tcl_NewWideIntObj(val1);\n    ary[1] = Tcl_NewWideIntObj(val2);\n    return Tcl_NewListObj(2, ary);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NewQuadObj --\n *\n *\tCreates a new list object and fills it with four integer objects.\n *\n * Results:\n *\tThe newly created list object is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nNewQuadObj(\n    Tcl_WideInt val1, Tcl_WideInt val2, Tcl_WideInt val3, Tcl_WideInt val4)\n{\n    Tcl_Obj *ary[4];\n\n    ary[0] = Tcl_NewWideIntObj(val1);\n    ary[1] = Tcl_NewWideIntObj(val2);\n    ary[2] = Tcl_NewWideIntObj(val3);\n    ary[3] = Tcl_NewWideIntObj(val4);\n    return Tcl_NewListObj(4, ary);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkIcu.c",
    "content": "/*\n * tkIcu.c --\n *\n *\ttkIcu.c implements various Tk commands which can find\n *\tgrapheme cluster and workchar bounderies in Unicode strings.\n *\n * Copyright © 2021 Jan Nijtmans\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Runtime linking of libicu.\n */\ntypedef enum UBreakIteratorTypex {\n\t  UBRK_CHARACTERX = 0,\n\t  UBRK_WORDX = 1\n} UBreakIteratorTypex;\n\ntypedef enum UErrorCodex {\n    U_ZERO_ERRORZ              =  0     /**< No error, no warning. */\n} UErrorCodex;\n\ntypedef void *(*fn_icu_open)(UBreakIteratorTypex, const char *,\n\tconst uint16_t *, int32_t, UErrorCodex *);\ntypedef void\t(*fn_icu_close)(void *);\ntypedef int32_t\t(*fn_icu_preceding)(void *, int32_t);\ntypedef int32_t\t(*fn_icu_following)(void *, int32_t);\ntypedef int32_t\t(*fn_icu_previous)(void *);\ntypedef int32_t\t(*fn_icu_next)(void *);\ntypedef void\t(*fn_icu_setText)(void *, const void *, int32_t, UErrorCodex *);\ntypedef int32_t (*fn_icu_canonicalize)(const char *, char *, int32_t, UErrorCodex *);\n\nstatic struct {\n    size_t\t\t\t\tnopen;\n    Tcl_LoadHandle\t\tlib;\n    fn_icu_open\t\t\topen;\n    fn_icu_close\t\tclose;\n    fn_icu_preceding\tpreceding;\n    fn_icu_following\tfollowing;\n    fn_icu_previous\tprevious;\n    fn_icu_next\tnext;\n    fn_icu_setText\tsetText;\n    fn_icu_canonicalize\tcanonicalize;\n} icu_fns = {\n    0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#define FLAG_WORD 1\n#define FLAG_FOLLOWING 4\n#define FLAG_SPACE 8\n\n#define icu_open\t\t\ticu_fns.open\n#define icu_close\t\t\ticu_fns.close\n#define icu_preceding\t\ticu_fns.preceding\n#define icu_following\t\ticu_fns.following\n#define icu_previous\t\ticu_fns.previous\n#define icu_next\t\ticu_fns.next\n#define icu_setText\t\ticu_fns.setText\n#define icu_canonicalize\ticu_fns.canonicalize\n\nTCL_DECLARE_MUTEX(icu_mutex);\n\nstatic int\nstartEndOfCmd(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tcl_DString ds;\n    Tcl_Size len;\n    const char *str;\n    UErrorCodex errorCode = U_ZERO_ERRORZ;\n    void *it;\n    Tcl_Size idx;\n    int flags = (int)PTR2INT(clientData);\n    const uint16_t *ustr;\n    char locale[128];\n\n    if ((size_t)(objc - 3) > 1) {\n\tTcl_WrongNumArgs(interp, 1 , objv, \"str start ?locale?\");\n\treturn TCL_ERROR;\n    }\n    locale[0] = '\\0';\n    if (objc > 3) {\n\tif (!TkObjIsEmpty(objv[3]) && icu_canonicalize) {\n\t    icu_canonicalize(Tcl_GetString(objv[3]), locale, sizeof(locale), &errorCode);\n\t} else {\n\t    strncpy(locale, Tcl_GetString(objv[3]), sizeof(locale));\n\t}\n\tlocale[sizeof(locale) - 1] = '\\0';\n    }\n    Tcl_DStringInit(&ds);\n    str = Tcl_GetStringFromObj(objv[1], &len);\n    Tcl_UtfToChar16DString(str, len, &ds);\n    len = Tcl_DStringLength(&ds)/2;\n    Tcl_Size ulen = Tcl_GetCharLength(objv[1]);\n    if (TkGetIntForIndex(objv[2], ulen-1, 0, &idx) != TCL_OK) {\n\tTcl_DStringFree(&ds);\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad index \\\"%s\\\": must be integer?[+-]integer?, end?[+-]integer?, or \\\"\\\"\", Tcl_GetString(objv[2])));\n\tTcl_SetErrorCode(interp, \"TK\", \"ICU\", \"INDEX\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    it = icu_open((UBreakIteratorTypex)(flags&3), locale[0] ? locale : NULL,\n\t\tNULL, -1, &errorCode);\n    if (it != NULL) {\n\terrorCode = U_ZERO_ERRORZ;\n\tustr = (const uint16_t *)Tcl_DStringValue(&ds);\n\ticu_setText(it, ustr, (int32_t)len, &errorCode);\n    }\n    if (it == NULL || errorCode != U_ZERO_ERRORZ) {\n\tTcl_DStringFree(&ds);\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"cannot open ICU iterator, errorcode: %d\", (int)errorCode));\n\tTcl_SetErrorCode(interp, \"TK\", \"ICU\", \"CANNOTOPEN\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (idx >= ulen) {\n\tidx = len;\n    } else if (idx > 0 && len != ulen) {\n\t/* The string contains codepoints > \\uFFFF. Determine UTF-16 index */\n\tTcl_Size newIdx = 0;\n\tfor (Tcl_Size i = 0; i < idx; i++) {\n\t    newIdx += 1 + (((newIdx < len-1) && (ustr[newIdx]&0xFC00) == 0xD800) && ((ustr[newIdx+1]&0xFC00) == 0xDC00));\n\t}\n\tidx = newIdx;\n    }\n    if (flags & FLAG_FOLLOWING) {\n\tif ((idx < 0) && (flags & FLAG_WORD)) {\n\t    idx = 0;\n\t}\n\tidx = icu_following(it, (int32_t)idx);\n\tif ((flags & FLAG_WORD) && idx >= len) {\n\t    idx = -1;\n\t}\n    } else if (idx > 0) {\n\tif (!(flags & FLAG_WORD)) {\n\t    idx += 1 + (((ustr[idx]&0xFC00) == 0xD800) && ((ustr[idx+1]&0xFC00) == 0xDC00));\n\t}\n\tidx = icu_preceding(it, (int32_t)idx);\n\tif (idx == 0 && (flags & FLAG_WORD)) {\n\t    flags &= ~FLAG_WORD; /* If 0 is reached here, don't do a further search */\n\t}\n    }\n    if ((flags & FLAG_WORD) && (idx != TCL_INDEX_NONE)) {\n\tif (!(flags & FLAG_SPACE) == ((idx >= len) || Tcl_UniCharIsSpace(ustr[idx]))) {\n\t    if (flags & FLAG_FOLLOWING) {\n\t\tidx = icu_next(it);\n\t\tif (idx >= len) {\n\t\t    idx = TCL_INDEX_NONE;\n\t\t}\n\t    } else {\n\t\tidx = icu_previous(it);\n\t    }\n\t} else if (idx == 0 && !(flags & FLAG_FOLLOWING)) {\n\t    idx = TCL_INDEX_NONE;\n\t}\n    }\n    icu_close(it);\n    Tcl_DStringFree(&ds);\n    if (idx != TCL_INDEX_NONE) {\n\tif (idx > 0 && len != ulen) {\n\t    /* The string contains codepoints > \\uFFFF. Determine UTF-32 index */\n\t    Tcl_Size newIdx = 1;\n\t    for (Tcl_Size i = 1; i < idx; i++) {\n\tif (((ustr[i-1]&0xFC00) != 0xD800) || ((ustr[i]&0xFC00) != 0xDC00)) newIdx++;\n\t    }\n\t    idx = newIdx;\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(idx));\n    }\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * SysNotifyDeleteCmd --\n *\n *      Delete notification and clean up.\n *\n * Results:\n *\tWindow destroyed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nicuCleanup(\n    TCL_UNUSED(void *))\n{\n    Tcl_MutexLock(&icu_mutex);\n    if (icu_fns.nopen-- <= 1) {\n\tif (icu_fns.lib != NULL) {\n\t    Tcl_FSUnloadFile(NULL, icu_fns.lib);\n\t}\n\tmemset(&icu_fns, 0, sizeof(icu_fns));\n    }\n    Tcl_MutexUnlock(&icu_mutex);\n}\n\nvoid\nIcu_Init(\n    Tcl_Interp *interp)\n{\n    Tcl_MutexLock(&icu_mutex);\n    char symbol[24];\n    char icuversion[4] = \"_80\"; /* Highest ICU version + 1 */\n\n    if (icu_fns.nopen == 0) {\n\tint i = 0;\n\tTcl_Obj *nameobj;\n\tstatic const char *iculibs[] = {\n#if defined(_WIN32)\n\t    \"icuuc??.dll\", /* When running under Windows, user-provided */\n\t    NULL,\n\t    \"cygicuuc??.dll\", /* When running under Cygwin */\n#elif defined(__CYGWIN__)\n\t    \"cygicuuc??.dll\",\n#elif defined(MAC_OSX_TCL)\n\t    \"libicuuc.??.dylib\",\n#else\n\t    \"libicuuc.so.??\",\n#endif\n\t    NULL\n\t};\n\n\t/* Going back down to ICU version 60 */\n\twhile ((icu_fns.lib == NULL) && (icuversion[1] >= '6')) {\n\t    if (--icuversion[2] < '0') {\n\t\ticuversion[1]--; icuversion[2] = '9';\n\t    }\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n\t    if (tclStubsPtr->tcl_CreateFileHandler) {\n\t\t/* Running on Cygwin, so try to load the cygwin icu dll */\n\t\ti = 2;\n\t    } else\n#endif\n\t    i = 0;\n\t    while (iculibs[i] != NULL) {\n\t\tTcl_ResetResult(interp);\n\t\tnameobj = Tcl_NewStringObj(iculibs[i], TCL_INDEX_NONE);\n\t\tchar *nameStr = Tcl_GetString(nameobj);\n\t\tchar *p = strchr(nameStr, '?');\n\t\tif (p != NULL) {\n\t\t    memcpy(p, icuversion+1, 2);\n\t\t}\n\t\tTcl_IncrRefCount(nameobj);\n\t\tif (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.lib)\n\t\t\t== TCL_OK) {\n\t\t    if (p == NULL) {\n\t\t\ticuversion[0] = '\\0';\n\t\t    }\n\t\t    Tcl_DecrRefCount(nameobj);\n\t\t    break;\n\t\t}\n\t\tTcl_DecrRefCount(nameobj);\n\t\t++i;\n\t    }\n\t}\n#if defined(_WIN32)\n\tif (icu_fns.lib == NULL) {\n\t    Tcl_ResetResult(interp);\n\t\tnameobj = Tcl_NewStringObj(\"icu.dll\", TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(nameobj);\n\t\tif (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.lib)\n\t\t\t== TCL_OK) {\n\t\t    icuversion[0] = '\\0';\n\t\t}\n\t\tTcl_DecrRefCount(nameobj);\n\t}\n\tif (icu_fns.lib == NULL) {\n\t    Tcl_ResetResult(interp);\n\t\tnameobj = Tcl_NewStringObj(\"icuuc.dll\", TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(nameobj);\n\t\tif (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.lib)\n\t\t\t== TCL_OK) {\n\t\t    icuversion[0] = '\\0';\n\t\t}\n\t\tTcl_DecrRefCount(nameobj);\n\t}\n#endif\n\tif (icu_fns.lib != NULL) {\n#define ICU_SYM(name)\t\t\t\t\t\t\t\\\n\t    strcpy(symbol, \"ubrk_\" #name ); \\\n\t    strcat(symbol, icuversion); \\\n\t    icu_fns.name = (fn_icu_ ## name)\t\t\t\t\\\n\t\tTcl_FindSymbol(NULL, icu_fns.lib, symbol)\n\t    ICU_SYM(open);\n\t    if (!icu_fns.open && *icuversion) {\n\t\t/* FreeBSD doesn't append the ICU version to the symbol name, see [1da19a69f8] */\n\t\t*icuversion = 0;\n\t\tICU_SYM(open); /* try again without version suffix */\n\t    }\n\t    ICU_SYM(close);\n\t    ICU_SYM(preceding);\n\t    ICU_SYM(following);\n\t    ICU_SYM(previous);\n\t    ICU_SYM(next);\n\t    ICU_SYM(setText);\n\t    strcpy(symbol, \"uloc_canonicalize\");\n\t    strcat(symbol, icuversion);\n\t    icu_fns.canonicalize = (fn_icu_canonicalize)\n\t\t    Tcl_FindSymbol(NULL, icu_fns.lib, symbol);\n#undef ICU_SYM\n\t}\n    }\n    Tcl_MutexUnlock(&icu_mutex);\n\n    if (icu_fns.lib != NULL) {\n\tTcl_CreateObjCommand2(interp, \"::tk::startOfCluster\", startEndOfCmd,\n\t\tINT2PTR(0), icuCleanup);\n\tTcl_CreateObjCommand2(interp, \"::tk::startOfNextWord\", startEndOfCmd,\n\t\tINT2PTR(FLAG_WORD|FLAG_FOLLOWING), icuCleanup);\n\tTcl_CreateObjCommand2(interp, \"::tk::startOfPreviousWord\", startEndOfCmd,\n\t\tINT2PTR(FLAG_WORD), icuCleanup);\n\tTcl_CreateObjCommand2(interp, \"::tk::endOfCluster\", startEndOfCmd,\n\t\tINT2PTR(FLAG_FOLLOWING), icuCleanup);\n\tTcl_CreateObjCommand2(interp, \"::tk::endOfWord\", startEndOfCmd,\n\t\tINT2PTR(FLAG_WORD|FLAG_FOLLOWING|FLAG_SPACE), icuCleanup);\n    icu_fns.nopen += 5;\n    }\n}\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * coding: utf-8\n * End:\n */\n\n"
  },
  {
    "path": "generic/tkImage.c",
    "content": "/*\n * tkImage.c --\n *\n *\tThis module implements the image protocol, which allows lots of\n *\tdifferent kinds of images to be used in lots of different widgets.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Each call to Tk_GetImage returns a pointer to one of the following\n * structures, which is used as a token by clients (widgets) that display\n * images.\n */\n\ntypedef struct Image {\n    Tk_Window tkwin;\t\t/* Window passed to Tk_GetImage (needed to\n\t\t\t\t * \"re-get\" the image later if the manager\n\t\t\t\t * changes). */\n    Display *display;\t\t/* Display for tkwin. Needed because when the\n\t\t\t\t * image is eventually freed tkwin may not\n\t\t\t\t * exist anymore. */\n    struct ImageModel *modelPtr;\n\t\t\t\t/* Model for this image (identifiers image\n\t\t\t\t * manager, for example). */\n    void *instanceData;\t/* One word argument to pass to image manager\n\t\t\t\t * when dealing with this image instance. */\n    Tk_ImageChangedProc *changeProc;\n\t\t\t\t/* Code in widget to call when image changes\n\t\t\t\t * in a way that affects redisplay. */\n    void *widgetClientData;/* Argument to pass to changeProc. */\n    struct Image *nextPtr;\t/* Next in list of all image instances\n\t\t\t\t * associated with the same name. */\n    struct Image *prevPtr;\t/* Previous in list of all image instances\n\t\t\t\t * associated with the same name. */\n} Image;\n\n/*\n * For each image model there is one of the following structures, which\n * represents a name in the image table and all of the images instantiated\n * from it. Entries in mainPtr->imageTable point to these structures.\n */\n\ntypedef struct ImageModel {\n    Tk_ImageType *typePtr;\t/* Information about image type. NULL means\n\t\t\t\t * that no image manager owns this image: the\n\t\t\t\t * image was deleted. */\n    void *modelData;\t/* One-word argument to pass to image mgr when\n\t\t\t\t * dealing with the model, as opposed to\n\t\t\t\t * instances. */\n    int width, height;\t\t/* Last known dimensions for image. */\n    Tcl_HashTable *tablePtr;\t/* Pointer to hash table containing image (the\n\t\t\t\t * imageTable field in some TkMainInfo\n\t\t\t\t * structure). */\n    Tcl_HashEntry *hPtr;\t/* Hash entry in mainPtr->imageTable for this\n\t\t\t\t * structure (used to delete the hash\n\t\t\t\t * entry). */\n    Image *instancePtr;\t\t/* Pointer to first in list of instances\n\t\t\t\t * derived from this name. */\n    bool deleted;\t\t/* Flag set when image is being deleted. */\n    TkWindow *winPtr;\t\t/* Main window of interpreter (used to detect\n\t\t\t\t * when the world is falling apart.) */\n} ImageModel;\n\ntypedef struct {\n    Tk_ImageType *imageTypeList;/* First in a list of all known image\n\t\t\t\t * types. */\n    bool initialized;\t\t/* Set to true if we've initialized the\n\t\t\t\t * structure. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Prototypes for local functions:\n */\n\nstatic void\t\tImageTypeThreadExitProc(void *clientData);\nstatic Tcl_FreeProc\tDeleteImage;\nstatic void\t\tEventuallyDeleteImage(ImageModel *modelPtr,\n\t\t\t    int forgetImageHashNow);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageTypeThreadExitProc --\n *\n *\tClean up the registered list of image types.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe thread's linked lists of photo image formats is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageTypeThreadExitProc(\n    TCL_UNUSED(void *))\n{\n    Tk_ImageType *freePtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    while (tsdPtr->imageTypeList != NULL) {\n\tfreePtr = tsdPtr->imageTypeList;\n\ttsdPtr->imageTypeList = tsdPtr->imageTypeList->nextPtr;\n\tTcl_Free(freePtr);\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreateImageType --\n *\n *\tThis function is invoked by an image manager to tell Tk about a new\n *\tkind of image and the functions that manage the new type. The function\n *\tis typically invoked during Tcl_AppInit.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe new image type is entered into a table used in the \"image create\"\n *\tcommand.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreateImageType(\n    const Tk_ImageType *typePtr)\n\t\t\t\t/* Structure describing the type. All of the\n\t\t\t\t * fields except \"nextPtr\" must be filled in\n\t\t\t\t * by caller. */\n{\n    Tk_ImageType *copyPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\tTcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL);\n    }\n    copyPtr = (Tk_ImageType *)Tcl_Alloc(sizeof(Tk_ImageType));\n    *copyPtr = *typePtr;\n    copyPtr->nextPtr = tsdPtr->imageTypeList;\n    tsdPtr->imageTypeList = copyPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ImageObjCmd --\n *\n *\tThis function is invoked to process the \"image\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ImageObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    static const char *const imageOptions[] = {\n\t\"create\", \"delete\", \"height\", \"inuse\", \"names\", \"type\", \"types\",\n\t\"width\", NULL\n    };\n    enum options {\n\tIMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES,\n\tIMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH\n    };\n    TkWindow *winPtr = (TkWindow *)clientData;\n    Tcl_Size i, firstOption;\n    int isNew, index;\n    Tk_ImageType *typePtr;\n    ImageModel *modelPtr;\n    Image *imagePtr;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n    char idString[16 + TCL_INTEGER_SPACE];\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    const char *arg, *name;\n    Tcl_Obj *resultObj;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?args?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], imageOptions,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch ((enum options) index) {\n    case IMAGE_CREATE: {\n\tTcl_Obj **args;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"type ?name? ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Look up the image type.\n\t */\n\n\targ = Tcl_GetString(objv[2]);\n\tfor (typePtr = tsdPtr->imageTypeList; typePtr != NULL;\n\t\ttypePtr = typePtr->nextPtr) {\n\t    if ((*arg == typePtr->name[0])\n\t\t    && (strcmp(arg, typePtr->name) == 0)) {\n\t\tbreak;\n\t    }\n\t}\n\tif (typePtr == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"image type \\\"%s\\\" does not exist\", arg));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"IMAGE_TYPE\", arg, (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Figure out a name to use for the new image.\n\t */\n\n\tif ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {\n\t    do {\n\t\tdispPtr->imageId++;\n\t\tsnprintf(idString, sizeof(idString), \"image%d\", dispPtr->imageId);\n\t\tname = idString;\n\t    } while (Tcl_FindCommand(interp, name, NULL, 0) != NULL);\n\t    firstOption = 3;\n\t} else {\n\t    TkWindow *topWin;\n\n\t    name = arg;\n\t    firstOption = 4;\n\n\t    /*\n\t     * Need to check if the _command_ that we are about to create is\n\t     * the name of the current model widget command (normally \".\" but\n\t     * could have been renamed) and fail in that case before a really\n\t     * nasty and hard to stop crash happens.\n\t     */\n\n\t    topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name);\n\t    if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"images may not be named the same as the main window\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SMASH_MAIN\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * Create the data structure for the new image.\n\t */\n\n\thPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &isNew);\n\tif (isNew) {\n\t    modelPtr = (ImageModel *)Tcl_Alloc(sizeof(ImageModel));\n\t    modelPtr->typePtr = NULL;\n\t    modelPtr->modelData = NULL;\n\t    modelPtr->width = modelPtr->height = 1;\n\t    modelPtr->tablePtr = &winPtr->mainPtr->imageTable;\n\t    modelPtr->hPtr = hPtr;\n\t    modelPtr->instancePtr = NULL;\n\t    modelPtr->deleted = false;\n\t    modelPtr->winPtr = winPtr->mainPtr->winPtr;\n\t    Tcl_Preserve(modelPtr->winPtr);\n\t    Tcl_SetHashValue(hPtr, modelPtr);\n\t} else {\n\t    /*\n\t     * An image already exists by this name. Disconnect the instances\n\t     * from the model.\n\t     */\n\n\t    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n\t    if (modelPtr->typePtr != NULL) {\n\t\tfor (imagePtr = modelPtr->instancePtr; imagePtr != NULL;\n\t\t\timagePtr = imagePtr->nextPtr) {\n\t\t    modelPtr->typePtr->freeProc(imagePtr->instanceData,\n\t\t\t    imagePtr->display);\n\t\t    imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,\n\t\t\t    modelPtr->width, modelPtr->height,\n\t\t\t    modelPtr->width, modelPtr->height);\n\t\t}\n\t\tmodelPtr->typePtr->deleteProc(modelPtr->modelData);\n\t\tmodelPtr->typePtr = NULL;\n\t    }\n\t    modelPtr->deleted = false;\n\t}\n\n\t/*\n\t * Call the image type manager so that it can perform its own\n\t * initialization, then re-\"get\" for any existing instances of the\n\t * image.\n\t */\n\n\tobjv += firstOption;\n\tobjc -= firstOption;\n\targs = (Tcl_Obj **) objv;\n\tTcl_Preserve(modelPtr);\n\ti = typePtr->createProc(interp, name, objc, args, typePtr,\n\t\t(Tk_ImageModel)modelPtr, &modelPtr->modelData);\n\tif (i != TCL_OK){\n\t    EventuallyDeleteImage(modelPtr, 0);\n\t    Tcl_Release(modelPtr);\n\t    return TCL_ERROR;\n\t}\n\tTcl_Release(modelPtr);\n\tmodelPtr->typePtr = typePtr;\n\tfor (imagePtr = modelPtr->instancePtr; imagePtr != NULL;\n\t\timagePtr = imagePtr->nextPtr) {\n\t    imagePtr->instanceData = typePtr->getProc(imagePtr->tkwin,\n\t\t    modelPtr->modelData);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t(const char *)Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), TCL_INDEX_NONE));\n\tbreak;\n    }\n    case IMAGE_DELETE:\n\tfor (i = 2; i < objc; i++) {\n\t    arg = Tcl_GetString(objv[i]);\n\t    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);\n\t    if (hPtr == NULL) {\n\t\tgoto alreadyDeleted;\n\t    }\n\t    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n\t    if (modelPtr->deleted) {\n\t\tgoto alreadyDeleted;\n\t    }\n\t    DeleteImage((char *)modelPtr);\n\t}\n\tbreak;\n    case IMAGE_NAMES:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\thPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);\n\tresultObj = Tcl_NewObj();\n\tfor ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n\t    if (modelPtr->deleted) {\n\t\tcontinue;\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    (const char *)Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), TCL_INDEX_NONE));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    case IMAGE_TYPES:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tfor (typePtr = tsdPtr->imageTypeList; typePtr != NULL;\n\t\ttypePtr = typePtr->nextPtr) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    typePtr->name, TCL_INDEX_NONE));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n\n    case IMAGE_HEIGHT:\n    case IMAGE_INUSE:\n    case IMAGE_TYPE:\n    case IMAGE_WIDTH:\n\t/*\n\t * These operations all parse virtually identically. First check to\n\t * see if three args are given. Then get a non-deleted model from the\n\t * third arg.\n\t */\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"name\");\n\t    return TCL_ERROR;\n\t}\n\n\targ = Tcl_GetString(objv[2]);\n\thPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);\n\tif (hPtr == NULL) {\n\t    goto alreadyDeleted;\n\t}\n\tmodelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n\tif (modelPtr->deleted) {\n\t    goto alreadyDeleted;\n\t}\n\n\t/*\n\t * Now we read off the specific piece of data we were asked for.\n\t */\n\n\tswitch ((enum options) index) {\n\tcase IMAGE_HEIGHT:\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(modelPtr->height));\n\t    break;\n\tcase IMAGE_INUSE:\n\t    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\t    modelPtr->typePtr && modelPtr->instancePtr));\n\t    break;\n\tcase IMAGE_TYPE:\n\t    if (modelPtr->typePtr != NULL) {\n\t\tTcl_SetObjResult(interp,\n\t\t\tTcl_NewStringObj(modelPtr->typePtr->name, TCL_INDEX_NONE));\n\t    }\n\t    break;\n\tcase IMAGE_WIDTH:\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(modelPtr->width));\n\t    break;\n\tdefault:\n\t    Tcl_Panic(\"can't happen\");\n\t}\n\tbreak;\n    }\n    return TCL_OK;\n\n  alreadyDeleted:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"image \\\"%s\\\" does not exist\",arg));\n    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"IMAGE\", arg, (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ImageChanged --\n *\n *\tThis function is called by an image manager whenever something has\n *\thappened that requires the image to be redrawn (some of its pixels\n *\thave changed, or its size has changed).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAny widgets that display the image are notified so that they can\n *\tredisplay themselves as appropriate.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ImageChanged(\n    Tk_ImageModel imageModel,\t/* Image that needs redisplay. */\n    int x, int y,\t\t/* Coordinates of upper-left pixel of region\n\t\t\t\t * of image that needs to be redrawn. */\n    int width, int height,\t/* Dimensions (in pixels) of region of image\n\t\t\t\t * to redraw. If either dimension is zero then\n\t\t\t\t * the image doesn't need to be redrawn\n\t\t\t\t * (perhaps all that happened is that its size\n\t\t\t\t * changed). */\n    int imageWidth, int imageHeight)\n\t\t\t\t/* New dimensions of image. */\n{\n    ImageModel *modelPtr = (ImageModel *) imageModel;\n    Image *imagePtr;\n\n    modelPtr->width = imageWidth;\n    modelPtr->height = imageHeight;\n    for (imagePtr = modelPtr->instancePtr; imagePtr != NULL;\n\t    imagePtr = imagePtr->nextPtr) {\n\timagePtr->changeProc(imagePtr->widgetClientData, x, y, width, height,\n\t\timageWidth, imageHeight);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_NameOfImage --\n *\n *\tGiven a token for an image model, this function returns the name of\n *\tthe image.\n *\n * Results:\n *\tThe return value is the string name for imageModel.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfImage(\n    Tk_ImageModel imageModel)\t/* Token for image. */\n{\n    ImageModel *modelPtr = (ImageModel *) imageModel;\n\n    if (modelPtr->hPtr == NULL) {\n\treturn NULL;\n    }\n    return (const char *)Tcl_GetHashKey(modelPtr->tablePtr, modelPtr->hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetImage --\n *\n *\tThis function is invoked by a widget when it wants to use a particular\n *\timage in a particular window.\n *\n * Results:\n *\tThe return value is a token for the image. If there is no image by the\n *\tgiven name, then NULL is returned and an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tTk records the fact that the widget is using the image, and it will\n *\tinvoke changeProc later if the widget needs redisplay (i.e. its size\n *\tchanges or some of its pixels change). The caller must eventually\n *\tinvoke Tk_FreeImage when it no longer needs the image.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Image\nTk_GetImage(\n    Tcl_Interp *interp,\t\t/* Place to leave error message if image can't\n\t\t\t\t * be found. */\n    Tk_Window tkwin,\t\t/* Token for window in which image will be\n\t\t\t\t * used. */\n    const char *name,\t\t/* Name of desired image. */\n    Tk_ImageChangedProc *changeProc,\n\t\t\t\t/* Function to invoke when redisplay is needed\n\t\t\t\t * because image's pixels or size changed. */\n    void *clientData)\t/* One-word argument to pass to damageProc. */\n{\n    Tcl_HashEntry *hPtr;\n    ImageModel *modelPtr;\n    Image *imagePtr;\n\n    hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);\n    if (hPtr == NULL) {\n\tgoto noSuchImage;\n    }\n    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n    if (modelPtr->typePtr == NULL) {\n\tgoto noSuchImage;\n    }\n    if (modelPtr->deleted) {\n\tgoto noSuchImage;\n    }\n    imagePtr = (Image *)Tcl_Alloc(sizeof(Image));\n    imagePtr->tkwin = tkwin;\n    imagePtr->display = Tk_Display(tkwin);\n    imagePtr->modelPtr = modelPtr;\n    imagePtr->instanceData =\n\t    modelPtr->typePtr->getProc(tkwin, modelPtr->modelData);\n    imagePtr->changeProc = changeProc;\n    imagePtr->widgetClientData = clientData;\n    imagePtr->nextPtr = modelPtr->instancePtr;\n    if (imagePtr->nextPtr) {\n\timagePtr->nextPtr->prevPtr = imagePtr;\n    }\n    imagePtr->prevPtr = NULL;\n    modelPtr->instancePtr = imagePtr;\n    return (Tk_Image) imagePtr;\n\n  noSuchImage:\n    if (interp) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"image \\\"%s\\\" does not exist\", name));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"IMAGE\", name, (char *)NULL);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeImage --\n *\n *\tThis function is invoked by a widget when it no longer needs an image\n *\tacquired by a previous call to Tk_GetImage. For each call to\n *\tTk_GetImage there must be exactly one call to Tk_FreeImage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe association between the image and the widget is removed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeImage(\n    Tk_Image image)\t\t/* Token for image that is no longer needed by\n\t\t\t\t * a widget. */\n{\n    Image *imagePtr = (Image *) image;\n    ImageModel *modelPtr = imagePtr->modelPtr;\n\n    /*\n     * Clean up the particular instance.\n     */\n\n    if (modelPtr->typePtr != NULL) {\n\tmodelPtr->typePtr->freeProc(imagePtr->instanceData,\n\t\timagePtr->display);\n    }\n    if (imagePtr->prevPtr) {\n\timagePtr->prevPtr->nextPtr = imagePtr->nextPtr;\n\tif (imagePtr->nextPtr) {\n\t    imagePtr->nextPtr->prevPtr = imagePtr->prevPtr;\n\t}\n    } else {\n\tmodelPtr->instancePtr = imagePtr->nextPtr;\n\tif (modelPtr->instancePtr) {\n\t    modelPtr->instancePtr->prevPtr = NULL;\n\t}\n    }\n    Tcl_Free(imagePtr);\n\n    /*\n     * If there are no more instances left for the model, and if the model\n     * image has been deleted, then delete the model too.\n     */\n\n    if ((modelPtr->typePtr == NULL) && (modelPtr->instancePtr == NULL)) {\n\tif (modelPtr->hPtr != NULL) {\n\t    Tcl_DeleteHashEntry(modelPtr->hPtr);\n\t}\n\tTcl_Release(modelPtr->winPtr);\n\tTcl_Free(modelPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PostscriptImage --\n *\n *\tThis function is called by widgets that contain images in order to\n *\tredisplay an image on the screen or an off-screen pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image's manager is notified, and it redraws the desired portion of\n *\tthe image before returning.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PostscriptImage(\n    Tk_Image image,\t\t/* Token for image to redisplay. */\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tk_PostscriptInfo psinfo,\t/* postscript info */\n    int x, int y,\t\t/* Upper-left pixel of region in image that\n\t\t\t\t * needs to be redisplayed. */\n    int width, int height,\t/* Dimensions of region to redraw. */\n    int prepass)\n{\n    Image *imagePtr = (Image *) image;\n    int result;\n    XImage *ximage;\n    Pixmap pmap;\n    GC newGC;\n    XGCValues gcValues;\n\n    if (imagePtr->modelPtr->typePtr == NULL) {\n\t/*\n\t * No model for image, so nothing to display on postscript.\n\t */\n\n\treturn TCL_OK;\n    }\n\n    /*\n     * Check if an image specific postscript-generation function exists;\n     * otherwise go on with generic code.\n     */\n\n    if (imagePtr->modelPtr->typePtr->postscriptProc != NULL) {\n\treturn imagePtr->modelPtr->typePtr->postscriptProc(\n\t\timagePtr->modelPtr->modelData, interp, tkwin, psinfo,\n\t\tx, y, width, height, prepass);\n    }\n\n    if (prepass) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Create a Pixmap, tell the image to redraw itself there, and then\n     * generate an XImage from the Pixmap. We can then read pixel values out\n     * of the XImage.\n     */\n\n    pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), width, height,\n\t    Tk_Depth(tkwin));\n\n    gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));\n    newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    if (newGC != NULL) {\n\tXFillRectangle(Tk_Display(tkwin), pmap, newGC, 0, 0,\n\t\t(unsigned) width, (unsigned) height);\n\tTk_FreeGC(Tk_Display(tkwin), newGC);\n    }\n\n    Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);\n\n    ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,\n\t    (unsigned) width, (unsigned) height, AllPlanes, ZPixmap);\n\n    Tk_FreePixmap(Tk_Display(tkwin), pmap);\n\n    if (ximage == NULL) {\n\t/*\n\t * The XGetImage() function is apparently not implemented on this\n\t * system. Just ignore it.\n\t */\n\n\treturn TCL_OK;\n    }\n    result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,\n\t    width, height);\n\n    XDestroyImage(ximage);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_RedrawImage --\n *\n *\tThis function is called by widgets that contain images in order to\n *\tredisplay an image on the screen or an off-screen pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image's manager is notified, and it redraws the desired portion of\n *\tthe image before returning.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_RedrawImage(\n    Tk_Image image,\t\t/* Token for image to redisplay. */\n    int imageX, int imageY,\t/* Upper-left pixel of region in image that\n\t\t\t\t * needs to be redisplayed. */\n    int width, int height,\t/* Dimensions of region to redraw. */\n    Drawable drawable,\t\t/* Drawable in which to display image (window\n\t\t\t\t * or pixmap). If this is a pixmap, it must\n\t\t\t\t * have the same depth as the window used in\n\t\t\t\t * the Tk_GetImage call for the image. */\n    int drawableX, int drawableY)\n\t\t\t\t/* Coordinates in drawable that correspond to\n\t\t\t\t * imageX and imageY. */\n{\n    Image *imagePtr = (Image *) image;\n\n    if (imagePtr->modelPtr->typePtr == NULL) {\n\t/*\n\t * No model for image, so nothing to display.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * Clip the redraw area to the area of the image.\n     */\n\n    if (imageX < 0) {\n\twidth += imageX;\n\tdrawableX -= imageX;\n\timageX = 0;\n    }\n    if (imageY < 0) {\n\theight += imageY;\n\tdrawableY -= imageY;\n\timageY = 0;\n    }\n    if ((imageX + width) > imagePtr->modelPtr->width) {\n\twidth = imagePtr->modelPtr->width - imageX;\n    }\n    if ((imageY + height) > imagePtr->modelPtr->height) {\n\theight = imagePtr->modelPtr->height - imageY;\n    }\n    imagePtr->modelPtr->typePtr->displayProc(imagePtr->instanceData,\n\t    imagePtr->display, drawable, imageX, imageY, width, height,\n\t    drawableX, drawableY);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SizeOfImage --\n *\n *\tThis function returns the current dimensions of an image.\n *\n * Results:\n *\tThe width and height of the image are returned in *widthPtr and\n *\t*heightPtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SizeOfImage(\n    Tk_Image image,\t\t/* Token for image whose size is wanted. */\n    int *widthPtr,\t\t/* Return width of image here. */\n    int *heightPtr)\t\t/* Return height of image here. */\n{\n    Image *imagePtr = (Image *) image;\n\n    *widthPtr = imagePtr->modelPtr->width;\n    *heightPtr = imagePtr->modelPtr->height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteImage --\n *\n *\tGiven the name of an image, this function destroys the image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image is destroyed; existing instances will display as blank\n *\tareas. If no such image exists then the function does nothing.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteImage(\n    Tcl_Interp *interp,\t\t/* Interpreter in which the image was\n\t\t\t\t * created. */\n    const char *name)\t\t/* Name of image. */\n{\n    Tcl_HashEntry *hPtr;\n    TkWindow *winPtr;\n\n    winPtr = (TkWindow *) Tk_MainWindow(interp);\n    if (winPtr == NULL) {\n\treturn;\n    }\n    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);\n    if (hPtr == NULL) {\n\treturn;\n    }\n    DeleteImage((char *)Tcl_GetHashValue(hPtr));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteImage --\n *\n *\tThis function is responsible for deleting an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe connection is dropped between instances of this image and an image\n *\tmodel. Image instances will redisplay themselves as empty areas, but\n *\texisting instances will not be deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteImage(\n    void *blockPtr)\t/* Pointer to main data structure for image. */\n{\n    Image *imagePtr;\n    Tk_ImageType *typePtr;\n    ImageModel *modelPtr = (ImageModel *)blockPtr;\n\n    typePtr = modelPtr->typePtr;\n    modelPtr->typePtr = NULL;\n    if (typePtr != NULL) {\n\tfor (imagePtr = modelPtr->instancePtr; imagePtr != NULL;\n\t\timagePtr = imagePtr->nextPtr) {\n\t    typePtr->freeProc(imagePtr->instanceData, imagePtr->display);\n\t    imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,\n\t\t    modelPtr->width, modelPtr->height, modelPtr->width,\n\t\t    modelPtr->height);\n\t}\n\ttypePtr->deleteProc(modelPtr->modelData);\n    }\n    if (modelPtr->instancePtr == NULL) {\n\tif (modelPtr->hPtr != NULL) {\n\t    Tcl_DeleteHashEntry(modelPtr->hPtr);\n\t}\n\tTcl_Release(modelPtr->winPtr);\n\tTcl_Free(modelPtr);\n    } else {\n\tmodelPtr->deleted = true;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EventuallyDeleteImage --\n *\n *\tArrange for an image to be deleted when it is safe to do so.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tImage will get freed, though not until it is no longer Tcl_Preserve()d\n *\tby anything. May be called multiple times on the same image without\n *\till effects.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEventuallyDeleteImage(\n    ImageModel *modelPtr,\t/* Pointer to main data structure for image. */\n    int forgetImageHashNow)\t/* Flag to say whether the hash table is about\n\t\t\t\t * to vanish. */\n{\n    if (forgetImageHashNow) {\n\tmodelPtr->hPtr = NULL;\n    }\n    if (!modelPtr->deleted) {\n\tmodelPtr->deleted = true;\n\tTcl_EventuallyFree(modelPtr, DeleteImage);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDeleteAllImages --\n *\n *\tThis function is called when an application is deleted. It calls back\n *\tall of the managers for all images so that they can cleanup, then it\n *\tdeletes all of Tk's internal information about images.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll information for all images gets deleted.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDeleteAllImages(\n    TkMainInfo *mainPtr)\t/* Structure describing application that is\n\t\t\t\t * going away. */\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n\n    for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);\n\t    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\tEventuallyDeleteImage((ImageModel *)Tcl_GetHashValue(hPtr), 1);\n    }\n    Tcl_DeleteHashTable(&mainPtr->imageTable);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetImageModelData --\n *\n *\tGiven the name of an image, this function returns the type of the\n *\timage and the clientData associated with its model.\n *\n * Results:\n *\tIf there is no image by the given name, then NULL is returned and a\n *\tNULL value is stored at *typePtrPtr. Otherwise the return value is the\n *\tclientData returned by the createProc when the image was created and a\n *\tpointer to the type structure for the image is stored at *typePtrPtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid *\nTk_GetImageModelData(\n    Tcl_Interp *interp,\t\t/* Interpreter in which the image was\n\t\t\t\t * created. */\n    const char *name,\t\t/* Name of image. */\n    const Tk_ImageType **typePtrPtr)\n\t\t\t\t/* Points to location to fill in with pointer\n\t\t\t\t * to type information for image. */\n{\n    TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);\n    Tcl_HashEntry *hPtr;\n    ImageModel *modelPtr;\n\n    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);\n    if (hPtr == NULL) {\n\t*typePtrPtr = NULL;\n\treturn NULL;\n    }\n    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);\n    if (modelPtr->deleted) {\n\t*typePtrPtr = NULL;\n\treturn NULL;\n    }\n    *typePtrPtr = modelPtr->typePtr;\n    return modelPtr->modelData;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetTSOrigin --\n *\n *\tSet the pattern origin of the tile to a common point (i.e. the origin\n *\t(0,0) of the top level window) so that tiles from two different\n *\twidgets will match up. This done by setting the GCTileStipOrigin field\n *\tis set to the translated origin of the toplevel window in the\n *\thierarchy.\n *\n * Results:\n *\tNone.\n *\n * Side Effects:\n *\tThe GCTileStipOrigin is reset in the GC. This will cause the tile\n *\torigin to change when the GC is used for drawing.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetTSOrigin(\n    Tk_Window tkwin,\n    GC gc,\n    int x, int y)\n{\n    while (!Tk_TopWinHierarchy(tkwin)) {\n\tx -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;\n\ty -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;\n\ttkwin = Tk_Parent(tkwin);\n    }\n    XSetTSOrigin(Tk_Display(tkwin), gc, x, y);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgBmap.c",
    "content": "/*\n * tkImgBmap.c --\n *\n *\tThis procedure implements images of type \"bitmap\" for Tk.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The following data structure represents the model for a bitmap\n * image:\n */\n\ntypedef struct {\n    Tk_ImageModel tkModel;\t/* Tk's token for image model. NULL means the\n\t\t\t\t * image is being deleted. */\n    Tcl_Interp *interp;\t\t/* Interpreter for application that is using\n\t\t\t\t * image. */\n    Tcl_Command imageCmd;\t/* Token for image command (used to delete it\n\t\t\t\t * when the image goes away). NULL means the\n\t\t\t\t * image command has already been deleted. */\n    int width, height;\t\t/* Dimensions of image. */\n    char *data;\t\t\t/* Data comprising bitmap (suitable for input\n\t\t\t\t * to XCreateBitmapFromData). May be NULL if\n\t\t\t\t * no data. Malloc'ed. */\n    char *maskData;\t\t/* Data for bitmap's mask (suitable for input\n\t\t\t\t * to XCreateBitmapFromData). Malloc'ed. */\n    Tk_Uid fgUid;\t\t/* Value of -foreground option. */\n    Tk_Uid bgUid;\t\t/* Value of -background option. */\n    char *fileString;\t\t/* Value of -file option (malloc'ed). */\n    char *dataString;\t\t/* Value of -data option (malloc'ed). */\n    char *maskFileString;\t/* Value of -maskfile option (malloc'ed). */\n    char *maskDataString;\t/* Value of -maskdata option (malloc'ed). */\n    struct BitmapInstance *instancePtr;\n\t\t\t\t/* First in list of all instances associated\n\t\t\t\t * with this model. */\n} BitmapModel;\n\n/*\n * The following data structure represents all of the instances of an image\n * that lie within a particular window:\n */\n\ntypedef struct BitmapInstance {\n    size_t refCount;\t\t/* Number of instances that share this data\n\t\t\t\t * structure. */\n    BitmapModel *modelPtr;\t/* Pointer to model for image. */\n    Tk_Window tkwin;\t\t/* Window in which the instances will be\n\t\t\t\t * displayed. */\n    XColor *fg;\t\t\t/* Foreground color for displaying image. */\n    XColor *bg;\t\t\t/* Background color for displaying image. */\n    Pixmap bitmap;\t\t/* The bitmap to display. */\n    Pixmap mask;\t\t/* Mask: only display bitmap pixels where\n\t\t\t\t * there are 1's here. */\n    GC gc;\t\t\t/* Graphics context for displaying bitmap.\n\t\t\t\t * None means there was an error while setting\n\t\t\t\t * up the instance, so it cannot be\n\t\t\t\t * displayed. */\n    struct BitmapInstance *nextPtr;\n\t\t\t\t/* Next in list of all instance structures\n\t\t\t\t * associated with modelPtr (NULL means end\n\t\t\t\t * of list). */\n} BitmapInstance;\n\n/*\n * The type record for bitmap images:\n */\n\nstatic int\t\tGetByte(Tcl_Channel chan);\nstatic int\t\tImgBmapCreate(Tcl_Interp *interp,\n\t\t\t    const char *name, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    const Tk_ImageType *typePtr, Tk_ImageModel model,\n\t\t\t    void **clientDataPtr);\nstatic void\t*ImgBmapGet(Tk_Window tkwin, void *clientData);\nstatic void\t\tImgBmapDisplay(void *clientData,\n\t\t\t    Display *display, Drawable drawable,\n\t\t\t    int imageX, int imageY, int width, int height,\n\t\t\t    int drawableX, int drawableY);\nstatic void\t\tImgBmapFree(void *clientData, Display *display);\nstatic void\t\tImgBmapDelete(void *clientData);\nstatic int\t\tImgBmapPostscript(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tk_PostscriptInfo psinfo, int x, int y,\n\t\t\t    int width, int height, int prepass);\n\nTk_ImageType tkBitmapImageType = {\n    \"bitmap\",\t\t\t/* name */\n    ImgBmapCreate,\t\t/* createProc */\n    ImgBmapGet,\t\t\t/* getProc */\n    ImgBmapDisplay,\t\t/* displayProc */\n    ImgBmapFree,\t\t/* freeProc */\n    ImgBmapDelete,\t\t/* deleteProc */\n    ImgBmapPostscript,\t\t/* postscriptProc */\n    NULL,\t\t\t/* nextPtr */\n    NULL\n};\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_UID, \"-background\", NULL, NULL,\n\t\"\", offsetof(BitmapModel, bgUid), 0, NULL},\n    {TK_CONFIG_STRING, \"-data\", NULL, NULL,\n\tNULL, offsetof(BitmapModel, dataString), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_STRING, \"-file\", NULL, NULL,\n\tNULL, offsetof(BitmapModel, fileString), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_UID, \"-foreground\", NULL, NULL,\n\t\"#000000\", offsetof(BitmapModel, fgUid), 0, NULL},\n    {TK_CONFIG_STRING, \"-maskdata\", NULL, NULL,\n\tNULL, offsetof(BitmapModel, maskDataString), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_STRING, \"-maskfile\", NULL, NULL,\n\tNULL, offsetof(BitmapModel, maskFileString), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * The following data structure is used to describe the state of parsing a\n * bitmap file or string. It is used for communication between TkGetBitmapData\n * and NextBitmapWord.\n */\n\n#define MAX_WORD_LENGTH 100\ntypedef struct ParseInfo {\n    const char *string; /* Next character of string data for bitmap,\n\t\t\t\t * or NULL if bitmap is being read from\n\t\t\t\t * file. */\n    Tcl_Channel chan;\t\t/* File containing bitmap data, or NULL if no\n\t\t\t\t * file. */\n    char word[MAX_WORD_LENGTH+1];\n\t\t\t\t/* Current word of bitmap data, NULL\n\t\t\t\t * terminated. */\n    int wordLength;\t\t/* Number of non-NULL bytes in word. */\n} ParseInfo;\n\n/*\n * Prototypes for procedures used only locally in this file:\n */\n\nstatic Tcl_ObjCmdProc2 ImgBmapCmd;\nstatic void\t\tImgBmapCmdDeletedProc(void *clientData);\nstatic void\t\tImgBmapConfigureInstance(BitmapInstance *instancePtr);\nstatic int\t\tImgBmapConfigureModel(BitmapModel *modelPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[], int flags);\nstatic int\t\tNextBitmapWord(ParseInfo *parseInfoPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapCreate --\n *\n *\tThis procedure is called by the Tk image code to create \"test\" images.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe data structure for a new image is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgBmapCreate(\n    Tcl_Interp *interp,\t\t/* Interpreter for application containing\n\t\t\t\t * image. */\n    const char *name,\t\t\t/* Name to use for image. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects for options (doesn't\n\t\t\t\t * include image name or type). */\n    TCL_UNUSED(const Tk_ImageType *),/* Pointer to our type record (not used). */\n    Tk_ImageModel model,\t/* Token for image, to be used by us in later\n\t\t\t\t * callbacks. */\n    void **clientDataPtr)\t/* Store manager's token for image here; it\n\t\t\t\t * will be returned in later callbacks. */\n{\n    BitmapModel *modelPtr = (BitmapModel *)Tcl_Alloc(sizeof(BitmapModel));\n\n    modelPtr->tkModel = model;\n    modelPtr->interp = interp;\n    modelPtr->imageCmd = Tcl_CreateObjCommand2(interp, name, ImgBmapCmd,\n\t    modelPtr, ImgBmapCmdDeletedProc);\n    modelPtr->width = modelPtr->height = 0;\n    modelPtr->data = NULL;\n    modelPtr->maskData = NULL;\n    modelPtr->fgUid = NULL;\n    modelPtr->bgUid = NULL;\n    modelPtr->fileString = NULL;\n    modelPtr->dataString = NULL;\n    modelPtr->maskFileString = NULL;\n    modelPtr->maskDataString = NULL;\n    modelPtr->instancePtr = NULL;\n    if (ImgBmapConfigureModel(modelPtr, objc, objv, 0) != TCL_OK) {\n\tImgBmapDelete(modelPtr);\n\treturn TCL_ERROR;\n    }\n    *clientDataPtr = modelPtr;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapConfigureModel --\n *\n *\tThis procedure is called when a bitmap image is created or\n *\treconfigured. It process configuration options and resets any\n *\tinstances of the image.\n *\n * Results:\n *\tA standard Tcl return value. If TCL_ERROR is returned then an error\n *\tmessage is left in the modelPtr->interp's result.\n *\n * Side effects:\n *\tExisting instances of the image will be redisplayed to match the new\n *\tconfiguration options.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgBmapConfigureModel(\n    BitmapModel *modelPtr,\t/* Pointer to data structure describing\n\t\t\t\t * overall bitmap image to (reconfigure). */\n    Tcl_Size objc,\t\t\t/* Number of entries in objv. */\n    Tcl_Obj *const objv[],\t/* Pairs of configuration options for image. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget, such\n\t\t\t\t * as TK_CONFIG_ARGV_ONLY. */\n{\n    BitmapInstance *instancePtr;\n    int maskWidth, maskHeight, dummy1, dummy2;\n\n    if (Tk_ConfigureWidget(modelPtr->interp, Tk_MainWindow(modelPtr->interp),\n\t    configSpecs, objc, objv, modelPtr, flags) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the bitmap and/or mask to create binary data. Make sure that the\n     * bitmap and mask have the same dimensions.\n     */\n\n    if (modelPtr->data != NULL) {\n\tTcl_Free(modelPtr->data);\n\tmodelPtr->data = NULL;\n    }\n    if ((modelPtr->fileString != NULL) || (modelPtr->dataString != NULL)) {\n\tmodelPtr->data = TkGetBitmapData(modelPtr->interp,\n\t\tmodelPtr->dataString, modelPtr->fileString,\n\t\t&modelPtr->width, &modelPtr->height, &dummy1, &dummy2);\n\tif (modelPtr->data == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (modelPtr->maskData != NULL) {\n\tTcl_Free(modelPtr->maskData);\n\tmodelPtr->maskData = NULL;\n    }\n    if ((modelPtr->maskFileString != NULL)\n\t    || (modelPtr->maskDataString != NULL)) {\n\tif (modelPtr->data == NULL) {\n\t    Tcl_SetObjResult(modelPtr->interp, Tcl_NewStringObj(\n\t\t    \"cannot have a mask without a bitmap\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(modelPtr->interp, \"TK\", \"IMAGE\", \"BITMAP\",\n\t\t    \"NO_BITMAP\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tmodelPtr->maskData = TkGetBitmapData(modelPtr->interp,\n\t\tmodelPtr->maskDataString, modelPtr->maskFileString,\n\t\t&maskWidth, &maskHeight, &dummy1, &dummy2);\n\tif (modelPtr->maskData == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif ((maskWidth != modelPtr->width)\n\t\t|| (maskHeight != modelPtr->height)) {\n\t    Tcl_Free(modelPtr->maskData);\n\t    modelPtr->maskData = NULL;\n\t    Tcl_SetObjResult(modelPtr->interp, Tcl_NewStringObj(\n\t\t    \"bitmap and mask have different sizes\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(modelPtr->interp, \"TK\", \"IMAGE\", \"BITMAP\",\n\t\t    \"MASK_SIZE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Cycle through all of the instances of this image, regenerating the\n     * information for each instance. Then force the image to be redisplayed\n     * everywhere that it is used.\n     */\n\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tImgBmapConfigureInstance(instancePtr);\n    }\n    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,\n\t    modelPtr->height, modelPtr->width, modelPtr->height);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapConfigureInstance --\n *\n *\tThis procedure is called to create displaying information for a bitmap\n *\timage instance based on the configuration information in the model.\n *\tIt is invoked both when new instances are created and when the model\n *\tis reconfigured.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates errors via Tcl_BackgroundException if there are problems in\n *\tsetting up the instance.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapConfigureInstance(\n    BitmapInstance *instancePtr)/* Instance to reconfigure. */\n{\n    BitmapModel *modelPtr = instancePtr->modelPtr;\n    XColor *colorPtr;\n    XGCValues gcValues;\n    GC gc;\n    unsigned int mask;\n    Pixmap oldBitmap, oldMask;\n\n    /*\n     * For each of the options in modelPtr, translate the string form into an\n     * internal form appropriate for instancePtr.\n     */\n\n    if (*modelPtr->bgUid != 0) {\n\tcolorPtr = Tk_GetColor(modelPtr->interp, instancePtr->tkwin,\n\t\tmodelPtr->bgUid);\n\tif (colorPtr == NULL) {\n\t    goto error;\n\t}\n    } else {\n\tcolorPtr = NULL;\n    }\n    if (instancePtr->bg != NULL) {\n\tTk_FreeColor(instancePtr->bg);\n    }\n    instancePtr->bg = colorPtr;\n\n    colorPtr = Tk_GetColor(modelPtr->interp, instancePtr->tkwin,\n\t    modelPtr->fgUid);\n    if (colorPtr == NULL) {\n\tgoto error;\n    }\n    if (instancePtr->fg != NULL) {\n\tTk_FreeColor(instancePtr->fg);\n    }\n    instancePtr->fg = colorPtr;\n\n    /*\n     * Careful: We have to allocate new Pixmaps before deleting the old ones.\n     * Otherwise, The XID allocator will always return the same XID for the\n     * new Pixmaps as was used for the old Pixmaps. And that will prevent the\n     * data and/or mask from changing in the GC below.\n     */\n\n    oldBitmap = instancePtr->bitmap;\n    instancePtr->bitmap = None;\n    oldMask = instancePtr->mask;\n    instancePtr->mask = None;\n\n    if (modelPtr->data != NULL) {\n\tinstancePtr->bitmap = XCreateBitmapFromData(\n\t\tTk_Display(instancePtr->tkwin),\n\t\tRootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),\n\t\tmodelPtr->data, (unsigned) modelPtr->width,\n\t\t(unsigned) modelPtr->height);\n    }\n    if (modelPtr->maskData != NULL) {\n\tinstancePtr->mask = XCreateBitmapFromData(\n\t\tTk_Display(instancePtr->tkwin),\n\t\tRootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),\n\t\tmodelPtr->maskData, (unsigned) modelPtr->width,\n\t\t(unsigned) modelPtr->height);\n    }\n\n    if (oldMask != None) {\n\tTk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);\n    }\n    if (oldBitmap != None) {\n\tTk_FreePixmap(Tk_Display(instancePtr->tkwin), oldBitmap);\n    }\n\n    if (modelPtr->data != NULL) {\n\tgcValues.foreground = instancePtr->fg->pixel;\n\tgcValues.graphics_exposures = False;\n\tmask = GCForeground|GCGraphicsExposures;\n\tif (instancePtr->bg != NULL) {\n\t    gcValues.background = instancePtr->bg->pixel;\n\t    mask |= GCBackground;\n\t    if (instancePtr->mask != None) {\n\t\tgcValues.clip_mask = instancePtr->mask;\n\t\tmask |= GCClipMask;\n\t    }\n\t} else {\n\t    gcValues.clip_mask = instancePtr->bitmap;\n\t    mask |= GCClipMask;\n\t}\n\tgc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);\n    } else {\n\tgc = NULL;\n    }\n    if (instancePtr->gc != NULL) {\n\tTk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);\n    }\n    instancePtr->gc = gc;\n    return;\n\n  error:\n    /*\n     * An error occurred: clear the graphics context in the instance to make\n     * it clear that this instance cannot be displayed. Then report the error.\n     */\n\n    if (instancePtr->gc != NULL) {\n\tTk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);\n    }\n    instancePtr->gc = NULL;\n    Tcl_AppendObjToErrorInfo(modelPtr->interp, Tcl_ObjPrintf(\n\t    \"\\n    (while configuring image \\\"%s\\\")\", Tk_NameOfImage(\n\t    modelPtr->tkModel)));\n    Tcl_BackgroundException(modelPtr->interp, TCL_ERROR);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetBitmapData --\n *\n *\tGiven a file name or ASCII string, this procedure parses the file or\n *\tstring contents to produce binary data for a bitmap.\n *\n * Results:\n *\tIf the bitmap description was parsed successfully then the return\n *\tvalue is a malloc-ed array containing the bitmap data. The dimensions\n *\tof the data are stored in *widthPtr and *heightPtr. *hotXPtr and\n *\t*hotYPtr are set to the bitmap hotspot if one is defined, otherwise\n *\tthey are set to -1, -1. If an error occurred, NULL is returned and an\n *\terror message is left in the interp's result.\n *\n * Side effects:\n *\tA bitmap is created.\n *\n *----------------------------------------------------------------------\n */\n\nchar *\nTkGetBitmapData(\n    Tcl_Interp *interp,\t\t/* For reporting errors, or NULL. */\n    const char *string,\t\t/* String describing bitmap. May be NULL. */\n    const char *fileName,\t/* Name of file containing bitmap description.\n\t\t\t\t * Used only if string is NULL. Must not be\n\t\t\t\t * NULL if string is NULL. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* Dimensions of bitmap get returned here. */\n    int *hotXPtr, int *hotYPtr)\t/* Position of hot spot or -1,-1. */\n{\n    int width, height, numBytes, hotX, hotY;\n    const char *expandedFileName;\n    char *p, *end;\n    ParseInfo pi;\n    char *data = NULL;\n    Tcl_DString buffer;\n\n    pi.string = string;\n    if (string == NULL) {\n\tif ((interp != NULL) && Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't get bitmap data from a file in a safe interpreter\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"BITMAP_FILE\", (char *)NULL);\n\t    return NULL;\n\t}\n\texpandedFileName = Tcl_TranslateFileName(NULL, fileName, &buffer);\n\tif (expandedFileName == NULL) {\n\t    Tcl_SetErrno(ENOENT);\n\t    goto cannotRead;\n\t}\n\tpi.chan = Tcl_OpenFileChannel(interp, expandedFileName, \"r\", 0);\n\tTcl_DStringFree(&buffer);\n\tif (pi.chan == NULL) {\n\tcannotRead:\n\t    if (interp != NULL) {\n\t\tTcl_ResetResult(interp);\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"couldn't read bitmap file \\\"%s\\\": %s\",\n\t\t\tfileName, Tcl_PosixError(interp)));\n\t    }\n\t    return NULL;\n\t}\n\n\tif (Tcl_SetChannelOption(interp, pi.chan, \"-translation\", \"binary\")\n\t\t!= TCL_OK) {\n\t    return NULL;\n\t}\n    } else {\n\tpi.chan = NULL;\n    }\n\n    /*\n     * Parse the lines that define the dimensions of the bitmap, plus the\n     * first line that defines the bitmap data (it declares the name of a data\n     * variable but doesn't include any actual data). These lines look\n     * something like the following:\n     *\n     *\t\t#define foo_width 16\n     *\t\t#define foo_height 16\n     *\t\t#define foo_x_hot 3\n     *\t\t#define foo_y_hot 3\n     *\t\tstatic char foo_bits[] = {\n     *\n     * The x_hot and y_hot lines may or may not be present. It's important to\n     * check for \"char\" in the last line, in order to reject old X10-style\n     * bitmaps that used shorts.\n     */\n\n    width = 0;\n    height = 0;\n    hotX = -1;\n    hotY = -1;\n    while (1) {\n\tif (NextBitmapWord(&pi) != TCL_OK) {\n\t    goto error;\n\t}\n\tif ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')\n\t\t&& (strcmp(pi.word+pi.wordLength-6, \"_width\") == 0)) {\n\t    if (NextBitmapWord(&pi) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    width = strtol(pi.word, &end, 0);\n\t    if ((end == pi.word) || (*end != 0)) {\n\t\tgoto error;\n\t    }\n\t} else if ((pi.wordLength >= 7) && (pi.word[pi.wordLength-7] == '_')\n\t\t&& (strcmp(pi.word+pi.wordLength-7, \"_height\") == 0)) {\n\t    if (NextBitmapWord(&pi) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    height = strtol(pi.word, &end, 0);\n\t    if ((end == pi.word) || (*end != 0)) {\n\t\tgoto error;\n\t    }\n\t} else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')\n\t\t&& (strcmp(pi.word+pi.wordLength-6, \"_x_hot\") == 0)) {\n\t    if (NextBitmapWord(&pi) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    hotX = strtol(pi.word, &end, 0);\n\t    if ((end == pi.word) || (*end != 0)) {\n\t\tgoto error;\n\t    }\n\t} else if ((pi.wordLength >= 6) && (pi.word[pi.wordLength-6] == '_')\n\t\t&& (strcmp(pi.word+pi.wordLength-6, \"_y_hot\") == 0)) {\n\t    if (NextBitmapWord(&pi) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    hotY = strtol(pi.word, &end, 0);\n\t    if ((end == pi.word) || (*end != 0)) {\n\t\tgoto error;\n\t    }\n\t} else if ((pi.word[0] == 'c') && (strcmp(pi.word, \"char\") == 0)) {\n\t    while (1) {\n\t\tif (NextBitmapWord(&pi) != TCL_OK) {\n\t\t    goto error;\n\t\t}\n\t\tif ((pi.word[0] == '{') && (pi.word[1] == 0)) {\n\t\t    goto getData;\n\t\t}\n\t    }\n\t} else if ((pi.word[0] == '{') && (pi.word[1] == 0)) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"format error in bitmap data; looks like it's an\"\n\t\t\t\" obsolete X10 bitmap file\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"BITMAP\", \"OBSOLETE\",\n\t\t\t(char *)NULL);\n\t    }\n\t    goto errorCleanup;\n\t}\n    }\n\n    /*\n     * Now we've read everything but the data. Allocate an array and read in\n     * the data.\n     */\n\n  getData:\n    if ((width <= 0) || (height <= 0)) {\n\tgoto error;\n    }\n    numBytes = ((width+7)/8) * height;\n    data = (char *)Tcl_Alloc(numBytes);\n    for (p = data; numBytes > 0; p++, numBytes--) {\n\tif (NextBitmapWord(&pi) != TCL_OK) {\n\t    goto error;\n\t}\n\t*p = (char) strtol(pi.word, &end, 0);\n\tif (end == pi.word) {\n\t    goto error;\n\t}\n    }\n\n    /*\n     * All done. Clean up and return.\n     */\n\n    if (pi.chan != NULL) {\n\tTcl_Close(NULL, pi.chan);\n    }\n    *widthPtr = width;\n    *heightPtr = height;\n    *hotXPtr = hotX;\n    *hotYPtr = hotY;\n    return data;\n\n  error:\n    if (interp != NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"format error in bitmap data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"BITMAP\", \"FORMAT\", (char *)NULL);\n    }\n\n  errorCleanup:\n    if (data != NULL) {\n\tTcl_Free(data);\n    }\n    if (pi.chan != NULL) {\n\tTcl_Close(NULL, pi.chan);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NextBitmapWord --\n *\n *\tThis procedure retrieves the next word of information (stuff between\n *\tcommas or white space) from a bitmap description.\n *\n * Results:\n *\tReturns TCL_OK if all went well. In this case the next word, and its\n *\tlength, will be availble in *parseInfoPtr. If the end of the bitmap\n *\tdescription was reached then TCL_ERROR is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nNextBitmapWord(\n    ParseInfo *parseInfoPtr)\t/* Describes what we're reading and where we\n\t\t\t\t * are in it. */\n{\n    const char *src;\n    char *dst;\n    int c;\n\n    parseInfoPtr->wordLength = 0;\n    dst = parseInfoPtr->word;\n    if (parseInfoPtr->string != NULL) {\n\tfor (src = parseInfoPtr->string; isspace(UCHAR(*src)) || (*src == ',');\n\t\tsrc++) {\n\t    if (*src == 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tfor ( ; !isspace(UCHAR(*src)) && (*src != ',') && (*src != 0); src++) {\n\t    *dst = *src;\n\t    dst++;\n\t    parseInfoPtr->wordLength++;\n\t    if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tparseInfoPtr->string = src;\n    } else {\n\tfor (c = GetByte(parseInfoPtr->chan); isspace(UCHAR(c)) || (c == ',');\n\t\tc = GetByte(parseInfoPtr->chan)) {\n\t    if (c == EOF) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tfor ( ; !isspace(UCHAR(c)) && (c != ',') && (c != EOF);\n\t\tc = GetByte(parseInfoPtr->chan)) {\n\t    *dst = (char)c;\n\t    dst++;\n\t    parseInfoPtr->wordLength++;\n\t    if (parseInfoPtr->wordLength > MAX_WORD_LENGTH) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n    if (parseInfoPtr->wordLength == 0) {\n\treturn TCL_ERROR;\n    }\n    parseInfoPtr->word[parseInfoPtr->wordLength] = 0;\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImgBmapCmd --\n *\n *\tThis procedure is invoked to process the Tcl command that corresponds\n *\tto an image managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nImgBmapCmd(\n    void *clientData,\t/* Information about the image model. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const bmapOptions[] = {\"cget\", \"configure\", NULL};\n    BitmapModel *modelPtr = (BitmapModel *)clientData;\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], bmapOptions,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch (index) {\n    case 0: /* cget */\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    return TCL_ERROR;\n\t}\n\treturn Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,\n\t\tmodelPtr, Tcl_GetString(objv[2]), 0);\n    case 1: /* configure */\n\tif (objc == 2) {\n\t    return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),\n\t\t    configSpecs, modelPtr, NULL, 0);\n\t} else if (objc == 3) {\n\t    return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),\n\t\t    configSpecs, modelPtr,\n\t\t    Tcl_GetString(objv[2]), 0);\n\t} else {\n\t    return ImgBmapConfigureModel(modelPtr, objc-2, objv+2,\n\t\t    TK_CONFIG_ARGV_ONLY);\n\t}\n    default:\n\tTcl_Panic(\"bad const entries to bmapOptions in ImgBmapCmd\");\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapGet --\n *\n *\tThis procedure is called for each use of a bitmap image in a widget.\n *\n * Results:\n *\tThe return value is a token for the instance, which is passed back to\n *\tus in calls to ImgBmapDisplay and ImgBmapFree.\n *\n * Side effects:\n *\tA data structure is set up for the instance (or, an existing instance\n *\tis re-used for the new one).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void *\nImgBmapGet(\n    Tk_Window tkwin,\t\t/* Window in which the instance will be\n\t\t\t\t * used. */\n    void *modelData)\t/* Pointer to our model structure for the\n\t\t\t\t * image. */\n{\n    BitmapModel *modelPtr = (BitmapModel *)modelData;\n    BitmapInstance *instancePtr;\n\n    /*\n     * See if there is already an instance for this window. If so then just\n     * re-use it.\n     */\n\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tif (instancePtr->tkwin == tkwin) {\n\t    instancePtr->refCount++;\n\t    return instancePtr;\n\t}\n    }\n\n    /*\n     * The image isn't already in use in this window. Make a new instance of\n     * the image.\n     */\n\n    instancePtr = (BitmapInstance *)Tcl_Alloc(sizeof(BitmapInstance));\n    instancePtr->refCount = 1;\n    instancePtr->modelPtr = modelPtr;\n    instancePtr->tkwin = tkwin;\n    instancePtr->fg = NULL;\n    instancePtr->bg = NULL;\n    instancePtr->bitmap = None;\n    instancePtr->mask = None;\n    instancePtr->gc = NULL;\n    instancePtr->nextPtr = modelPtr->instancePtr;\n    modelPtr->instancePtr = instancePtr;\n    ImgBmapConfigureInstance(instancePtr);\n\n    /*\n     * If this is the first instance, must set the size of the image.\n     */\n\n    if (instancePtr->nextPtr == NULL) {\n\tTk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0, modelPtr->width,\n\t\tmodelPtr->height);\n    }\n\n    return instancePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapDisplay --\n *\n *\tThis procedure is invoked to draw a bitmap image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA portion of the image gets rendered in a pixmap or window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapDisplay(\n    void *clientData,\t/* Pointer to BitmapInstance structure for\n\t\t\t\t * instance to be displayed. */\n    Display *display,\t\t/* Display on which to draw image. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw image. */\n    int imageX, int imageY,\t/* Upper-left corner of region within image to\n\t\t\t\t * draw. */\n    int width, int height,\t/* Dimensions of region within image to draw. */\n    int drawableX, int drawableY)\n\t\t\t\t/* Coordinates within drawable that correspond\n\t\t\t\t * to imageX and imageY. */\n{\n    BitmapInstance *instancePtr = (BitmapInstance *)clientData;\n    bool masking;\n\n    /*\n     * If there's no graphics context, it means that an error occurred while\n     * creating the image instance so it can't be displayed.\n     */\n\n    if (instancePtr->gc == NULL) {\n\treturn;\n    }\n\n    /*\n     * If masking is in effect, must modify the mask origin within the\n     * graphics context to line up with the image's origin. Then draw the\n     * image and reset the clip origin, if there's a mask.\n     */\n\n    masking = (instancePtr->mask != None) || (instancePtr->bg == NULL);\n    if (masking) {\n\tXSetClipOrigin(display, instancePtr->gc, drawableX - imageX,\n\t\tdrawableY - imageY);\n    }\n    XCopyPlane(display, instancePtr->bitmap, drawable, instancePtr->gc,\n\t    imageX, imageY, (unsigned) width, (unsigned) height,\n\t    drawableX, drawableY, 1);\n    if (masking) {\n\tXSetClipOrigin(display, instancePtr->gc, 0, 0);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapFree --\n *\n *\tThis procedure is called when a widget ceases to use a particular\n *\tinstance of an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInternal data structures get cleaned up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapFree(\n    void *clientData,\t/* Pointer to BitmapInstance structure for\n\t\t\t\t * instance to be displayed. */\n    Display *display)\t\t/* Display containing window that used image. */\n{\n    BitmapInstance *instancePtr = (BitmapInstance *)clientData;\n    BitmapInstance *prevPtr;\n\n    if (instancePtr->refCount-- > 1) {\n\treturn;\n    }\n\n    /*\n     * There are no more uses of the image within this widget. Free the\n     * instance structure.\n     */\n\n    if (instancePtr->fg != NULL) {\n\tTk_FreeColor(instancePtr->fg);\n    }\n    if (instancePtr->bg != NULL) {\n\tTk_FreeColor(instancePtr->bg);\n    }\n    if (instancePtr->bitmap != None) {\n\tTk_FreePixmap(display, instancePtr->bitmap);\n    }\n    if (instancePtr->mask != None) {\n\tTk_FreePixmap(display, instancePtr->mask);\n    }\n    if (instancePtr->gc != NULL) {\n\tTk_FreeGC(display, instancePtr->gc);\n    }\n    if (instancePtr->modelPtr->instancePtr == instancePtr) {\n\tinstancePtr->modelPtr->instancePtr = instancePtr->nextPtr;\n    } else {\n\tfor (prevPtr = instancePtr->modelPtr->instancePtr;\n\t\tprevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {\n\t    /* Empty loop body */\n\t}\n\tprevPtr->nextPtr = instancePtr->nextPtr;\n    }\n    Tcl_Free(instancePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapDelete --\n *\n *\tThis procedure is called by the image code to delete the model\n *\tstructure for an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with the image get freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapDelete(\n    void *modelData)\t/* Pointer to BitmapModel structure for\n\t\t\t\t * image. Must not have any more instances. */\n{\n    BitmapModel *modelPtr = (BitmapModel *)modelData;\n\n    if (modelPtr->instancePtr != NULL) {\n\tTcl_Panic(\"tried to delete bitmap image when instances still exist\");\n    }\n    modelPtr->tkModel = NULL;\n    if (modelPtr->imageCmd != NULL) {\n\tTcl_DeleteCommandFromToken(modelPtr->interp, modelPtr->imageCmd);\n    }\n    if (modelPtr->data != NULL) {\n\tTcl_Free(modelPtr->data);\n    }\n    if (modelPtr->maskData != NULL) {\n\tTcl_Free(modelPtr->maskData);\n    }\n    Tk_FreeOptions(configSpecs, modelPtr, NULL, 0);\n    Tcl_Free(modelPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapCmdDeletedProc --\n *\n *\tThis procedure is invoked when the image command for an image is\n *\tdeleted. It deletes the image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapCmdDeletedProc(\n    void *clientData)\t/* Pointer to BitmapModel structure for\n\t\t\t\t * image. */\n{\n    BitmapModel *modelPtr = (BitmapModel *)clientData;\n\n    modelPtr->imageCmd = NULL;\n    if (modelPtr->tkModel != NULL) {\n\tTk_DeleteImage(modelPtr->interp, Tk_NameOfImage(modelPtr->tkModel));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetByte --\n *\n *\tGet the next byte from the open channel.\n *\n * Results:\n *\tThe next byte or EOF.\n *\n * Side effects:\n *\tWe read from the channel.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetByte(\n    Tcl_Channel chan)\t/* The channel we read from. */\n{\n    char buffer;\n\n    if (Tcl_Read(chan, &buffer, 1) != 1) {\n\treturn EOF;\n    } else {\n\treturn buffer;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapPsImagemask --\n *\n *\tThis procedure generates postscript suitable for rendering a single\n *\tbitmap of an image. A single bitmap image might contain both a\n *\tforeground and a background bitmap. This routine is called once for\n *\teach such bitmap in a bitmap image.\n *\n *\tPrior to invoking this routine, the following setup has occurred:\n *\n *\t   1.  The postscript foreground color has been set to the color used\n *\t       to render the bitmap.\n *\n *\t   2.  The origin of the postscript coordinate system is set to the\n *\t       lower left corner of the bitmap.\n *\n *\t   3.  The postscript coordinate system has been scaled so that the\n *\t       entire bitmap is one unit squared.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPostscript code is appended to psObj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgBmapPsImagemask(\n    Tcl_Obj *psObj,\t\t/* Append postscript to this buffer. */\n    int width, int height,\t/* Width and height of the bitmap in pixels */\n    char *data)\t\t\t/* Data for the bitmap. */\n{\n    int i, j, nBytePerRow;\n\n    /*\n     * The bit order of bitmaps in Tk is the opposite of the bit order that\n     * postscript uses. (In Tk, the least significant bit is on the right side\n     * of the bitmap and in postscript the least significant bit is shown on\n     * the left.) The following array is used to reverse the order of bits\n     * within a byte so that the bits will be in the order postscript expects.\n     */\n\n    static const unsigned char bit_reverse[] = {\n       0, 128, 64, 192, 32, 160,  96, 224, 16, 144, 80, 208, 48, 176, 112, 240,\n       8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,\n       4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,\n      12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,\n       2, 130, 66, 194, 34, 162,  98, 226, 18, 146, 82, 210, 50, 178, 114, 242,\n      10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,\n       6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,\n      14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,\n       1, 129, 65, 193, 33, 161,  97, 225, 17, 145, 81, 209, 49, 177, 113, 241,\n       9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,\n       5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,\n      13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,\n       3, 131, 67, 195, 35, 163,  99, 227, 19, 147, 83, 211, 51, 179, 115, 243,\n      11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,\n       7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,\n      15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255,\n    };\n\n    Tcl_AppendPrintfToObj(psObj,\n\t    \"0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\\n\",\n\t    width, height, width, -height, height);\n\n    nBytePerRow = (width + 7) / 8;\n    for (i=0; i<height; i++) {\n\tfor (j=0; j<nBytePerRow; j++) {\n\t    Tcl_AppendPrintfToObj(psObj, \" %02x\",\n\t\t    bit_reverse[0xff & data[i*nBytePerRow + j]]);\n\t}\n\tTcl_AppendToObj(psObj, \"\\n\", TCL_INDEX_NONE);\n    }\n\n    Tcl_AppendToObj(psObj, \">} imagemask \\n\", TCL_INDEX_NONE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgBmapPostscript --\n *\n *\tThis procedure generates postscript for rendering a bitmap image.\n *\n * Results:\n *\tOn success, this routine writes postscript code into interp->result\n *\tand returns TCL_OK TCL_ERROR is returned and an error message is left\n *\tin interp->result if anything goes wrong.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgBmapPostscript(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tk_PostscriptInfo psinfo,\n    int x, int y, int width, int height,\n    int prepass)\n{\n    BitmapModel *modelPtr = (BitmapModel *)clientData;\n    Tcl_InterpState interpState;\n    Tcl_Obj *psObj;\n\n    if (prepass) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * There is nothing to do for bitmaps with zero width or height.\n     */\n\n    if (width<=0 || height<=0 || modelPtr->width<=0 || modelPtr->height<=0){\n\treturn TCL_OK;\n    }\n\n    /*\n     * Some postscript implementations cannot handle bitmap strings longer\n     * than about 60k characters. If the bitmap data is that big or bigger,\n     * we bail out.\n     */\n\n    if (modelPtr->width*modelPtr->height > 60000) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"unable to generate postscript for bitmaps larger than 60000\"\n\t\t\" pixels\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"PS\", \"MEMLIMIT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Translate the origin of the coordinate system to be the lower-left\n     * corner of the bitmap and adjust the scale of the coordinate system so\n     * that entire bitmap covers one square unit of the page. The calling\n     * function put a \"gsave\" into the postscript and will add a \"grestore\" at\n     * after this routine returns, so it is safe to make whatever changes are\n     * necessary here.\n     */\n\n    if (x != 0 || y != 0) {\n\tTcl_AppendPrintfToObj(psObj, \"%d %d moveto\\n\", x, y);\n    }\n    if (width != 1 || height != 1) {\n\tTcl_AppendPrintfToObj(psObj, \"%d %d scale\\n\", width, height);\n    }\n\n    /*\n     * Color the background, if there is one. This step is skipped if the\n     * background is transparent. If the background is not transparent and\n     * there is no background mask, then color the complete rectangle that\n     * encloses the bitmap. If there is a background mask, then only apply\n     * color to the bits specified by the mask.\n     */\n\n    if ((modelPtr->bgUid != NULL) && (modelPtr->bgUid[0] != '\\000')) {\n\tXColor color;\n\n\tTkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), modelPtr->bgUid,\n\t\t&color);\n\tTcl_ResetResult(interp);\n\tif (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {\n\t    goto error;\n\t}\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (modelPtr->maskData == NULL) {\n\t    Tcl_AppendToObj(psObj,\n\t\t    \"0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto \"\n\t\t    \"closepath fill\\n\", TCL_INDEX_NONE);\n\t} else {\n\t    ImgBmapPsImagemask(psObj, modelPtr->width, modelPtr->height,\n\t\t    modelPtr->maskData);\n\t}\n    }\n\n    /*\n     * Draw the bitmap foreground, assuming there is one.\n     */\n\n    if ((modelPtr->fgUid != NULL) && (modelPtr->data != NULL)) {\n\tXColor color;\n\n\tTkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), modelPtr->fgUid,\n\t\t&color);\n\tTcl_ResetResult(interp);\n\tif (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {\n\t    goto error;\n\t}\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tImgBmapPsImagemask(psObj, modelPtr->width, modelPtr->height,\n\t\tmodelPtr->data);\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    return TCL_OK;\n\n  error:\n    Tcl_DiscardInterpState(interpState);\n    Tcl_DecrRefCount(psObj);\n    return TCL_ERROR;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgGIF.c",
    "content": "/*\n * tkImgGIF.c --\n *\n *\tA photo image file handler for GIF files. Reads 87a and 89a GIF files.\n *\tAt present, there only is a file write function. GIF images may be\n *\tread using the -data option of the photo image. The data may be given\n *\tas a binary string in a Tcl_Obj or by representing the data as BASE64\n *\tencoded ascii. Derived from the giftoppm code found in the pbmplus\n *\tpackage and tkImgFmtPPM.c in the tk4.0b2 distribution.\n *\n * Copyright © Reed Wade (wade@cs.utk.edu), University of Tennessee\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1997 Australian National University\n * Copyright © 2005-2010 Donal K. Fellows\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * This file also contains code from the giftoppm program, which is\n * copyrighted as follows:\n *\n * +--------------------------------------------------------------------+\n * | Copyright 1990, David Koblas.\t\t\t\t\t|\n * |   Permission to use, copy, modify, and distribute this software\t|\n * |   and its documentation for any purpose and without fee is hereby\t|\n * |   granted, provided that the above copyright notice appear in all\t|\n * |   copies and that both that copyright notice and this permission\t|\n * |   notice appear in supporting documentation. This software is\t|\n * |   provided \"as is\" without express or implied warranty.\t\t|\n * +--------------------------------------------------------------------+\n */\n\n#include \"tkInt.h\"\n\n/*\n * GIF's are represented as data in either binary or base64 format. base64\n * strings consist of 4 6-bit characters -> 3 8 bit bytes. A-Z, a-z, 0-9, +\n * and / represent the 64 values (in order). '=' is a trailing padding char\n * when the un-encoded data is not a multiple of 3 bytes. We'll ignore white\n * space when encountered. Any other invalid character is treated as an EOF\n */\n\n#define GIF_SPECIAL\t(256)\n#define GIF_PAD\t\t(GIF_SPECIAL+1)\n#define GIF_SPACE\t(GIF_SPECIAL+2)\n#define GIF_BAD\t\t(GIF_SPECIAL+3)\n#define GIF_DONE\t(GIF_SPECIAL+4)\n\n/*\n * structure to hold the data of a Graphic Control Extension block.\n */\n\ntypedef struct {\n    bool blockPresent;\t\t/* if 1, the block was read and is in scope */\n    int transparent;\t\t/* Transparency index */\n    int delayTime;\t\t/* update delay time in 10ms */\n    int disposalMethod;\t\t/* disposal method 0-3 */\n    int userInteraction;\t/* user interaction 0/1 */\n} GIFGraphicControlExtensionBlock;\n\n/*\n * structure to \"mimic\" FILE for Mread, so we can look like fread. The decoder\n * state keeps track of which byte we are about to read, or EOF.\n */\n\ntypedef struct mFile {\n    unsigned char *data;\t/* mmencoded source string */\n    int c;\t\t\t/* bits left over from previous character */\n    int state;\t\t\t/* decoder state (0-4 or GIF_DONE) */\n    Tcl_Size length;\t\t\t/* Total amount of bytes in data */\n} MFile;\n\n/*\n * Non-ASCII encoding support:\n * Most data in a GIF image is binary and is treated as such. However, a few\n * key bits are stashed in ASCII. If we try to compare those pieces to the\n * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To\n * accommodate these systems, we test against the numeric value of the ASCII\n * characters instead of the characters themselves. This is encoding\n * independent.\n */\n\nstatic const char GIF87a[] = {\t\t\t/* ASCII GIF87a */\n    0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00\n};\nstatic const char GIF89a[] = {\t\t\t/* ASCII GIF89a */\n    0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00\n};\n#define GIF_TERMINATOR\t0x3b\t\t\t/* ASCII ; */\n#define GIF_EXTENSION\t0x21\t\t\t/* ASCII ! */\n#define GIF_START\t0x2c\t\t\t/* ASCII , */\n\n/*\n * Flags used to notify that we've got inline data instead of a file to read\n * from. Note that we need to figure out which type of inline data we've got\n * before handing off to the GIF reading code; this is done in StringReadGIF.\n */\n\n#define INLINE_DATA_BINARY\t((const char *) 0x01)\n#define INLINE_DATA_BASE64\t((const char *) 0x02)\n\n/*\n *\t\tHACK ALERT!!  HACK ALERT!!  HACK ALERT!!\n * This code is hard-wired for reading from files. In order to read from a\n * data stream, we'll trick fread so we can reuse the same code. 0==from file;\n * 1==from base64 encoded data; 2==from binary data\n */\n\ntypedef struct {\n    const char *fromData;\n    unsigned char workingBuffer[280];\n    struct {\n\tint bytes;\n\tint done;\n\tunsigned int window;\n\tint bitsInWindow;\n\tunsigned char *c;\n    } reader;\n} GIFImageConfig;\n\n/*\n * Type of a function used to do the writing to a file or buffer when\n * serializing in the GIF format.\n */\n\ntypedef Tcl_Size (WriteBytesFunc) (void *clientData, const char *bytes,\n\t\t\t    Tcl_Size byteCount);\n\n/*\n * The format record for the GIF file format:\n */\n\nstatic int\t\tFileMatchGIF(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *format,\n\t\t\t    Tcl_Obj *metadataInObj, int *widthPtr,\n\t\t\t    int *heightPtr, Tcl_Obj *metadataOutObj);\nstatic int\t\tFileReadGIF(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *format,\n\t\t\t    Tcl_Obj *metadataInObj, Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY, Tcl_Obj *metadataOutObj);\nstatic int\t\tStringMatchGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,\n\t\t\t    Tcl_Obj *format, Tcl_Obj *metadataInObj,\n\t\t\t    int *widthPtr, int *heightPtr,\n\t\t\t    Tcl_Obj *metadataOutObj);\nstatic int\t\tStringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,\n\t\t\t    Tcl_Obj *format, Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY, Tcl_Obj *metadataOutObj);\nstatic int\t\tFileWriteGIF(Tcl_Interp *interp, const char *filename,\n\t\t\t    Tcl_Obj *format, Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tStringWriteGIF(Tcl_Interp *interp, Tcl_Obj *format,\n\t\t\t    Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tCommonWriteGIF(Tcl_Interp *interp,\n\t\t\t    void *clientData,\n\t\t\t    WriteBytesFunc *writeProc, Tcl_Obj *format,\n\t\t\t    Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\n\nTk_PhotoImageFormatVersion3 tkImgFmtGIF = {\n    \"gif\",\t\t/* name */\n    FileMatchGIF,\t/* fileMatchProc */\n    StringMatchGIF,\t/* stringMatchProc */\n    FileReadGIF,\t/* fileReadProc */\n    StringReadGIF,\t/* stringReadProc */\n    FileWriteGIF,\t/* fileWriteProc */\n    StringWriteGIF,\t/* stringWriteProc */\n    NULL\n};\n\n#define INTERLACE\t\t0x40\n#define LOCALCOLORMAP\t\t0x80\n#define BitSet(byte, bit)\t(((byte) & (bit)) == (bit))\n#define MAXCOLORMAPSIZE\t\t256\n#define CM_RED\t\t\t0\n#define CM_GREEN\t\t1\n#define CM_BLUE\t\t\t2\n#define CM_ALPHA\t\t3\n#define MAX_LWZ_BITS\t\t12\n#define LM_to_uint(a,b)\t\t(((b)<<8)|(a))\n\n/*\n * Prototypes for local functions defined in this file:\n */\n\nstatic int\t\tReadOneByte(Tcl_Interp *interp,\n\t\t\t    GIFImageConfig *gifConfPtr, Tcl_Channel chan);\nstatic int\t\tDoExtension(GIFImageConfig *gifConfPtr,\n\t\t\t    Tcl_Channel chan, int label, unsigned char *buffer,\n\t\t\t    GIFGraphicControlExtensionBlock\n\t\t\t    *gifGraphicControlExtensionBlock,\n\t\t\t    Tcl_Obj *metadataOutObj);\nstatic int\t\tGetCode(Tcl_Channel chan, int code_size, int flag,\n\t\t\t    GIFImageConfig *gifConfPtr);\nstatic int\t\tGetDataBlock(GIFImageConfig *gifConfPtr,\n\t\t\t    Tcl_Channel chan, unsigned char *buf);\nstatic int\t\tReadColorMap(GIFImageConfig *gifConfPtr,\n\t\t\t    Tcl_Channel chan, int number,\n\t\t\t    unsigned char buffer[MAXCOLORMAPSIZE][4]);\nstatic int\t\tReadGIFHeader(GIFImageConfig *gifConfPtr,\n\t\t\t    Tcl_Channel chan, int *widthPtr, int *heightPtr);\nstatic int\t\tReadImage(GIFImageConfig *gifConfPtr,\n\t\t\t    Tcl_Interp *interp, unsigned char *imagePtr,\n\t\t\t    Tcl_Channel chan, int len, int rows,\n\t\t\t    unsigned char cmap[MAXCOLORMAPSIZE][4], int srcX,\n\t\t\t    int srcY, int interlace, int transparent);\n\n/*\n * these are for the BASE64 image reader code only\n */\n\nstatic Tcl_Size\t\tFread(GIFImageConfig *gifConfPtr, unsigned char *dst,\n\t\t\t    Tcl_Size size, Tcl_Size count, Tcl_Channel chan);\nstatic Tcl_Size\t\tMread(unsigned char *dst, Tcl_Size size, Tcl_Size count,\n\t\t\t    MFile *handle);\nstatic int\t\tMgetc(MFile *handle);\nstatic int\t\tchar64(int c);\nstatic void\t\tmInit(unsigned char *string, MFile *handle,\n\t\t\t    Tcl_Size length);\n\n/*\n * Types, defines and variables needed to write and compress a GIF.\n */\n\n#define LSB(a)\t\t((unsigned char) (((short)(a)) & 0x00FF))\n#define MSB(a)\t\t((unsigned char) (((short)(a)) >> 8))\n\n#define GIFBITS\t\t12\n#define HSIZE\t\t5003\t/* 80% occupancy */\n\n#define DEFAULT_BACKGROUND_VALUE\t0xD9\n\ntypedef struct {\n    int ssize;\n    int csize;\n    int rsize;\n    unsigned char *pixelOffset;\n    int pixelSize;\n    int pixelPitch;\n    int greenOffset;\n    int blueOffset;\n    int alphaOffset;\n    int num;\n    unsigned char mapa[MAXCOLORMAPSIZE][3];\n} GifWriterState;\n\ntypedef int (* ifunptr) (GifWriterState *statePtr);\n\n/*\n * Support for compression of GIFs.\n */\n\n#define MAXCODE(numBits)\t(((long) 1 << (numBits)) - 1)\n\n#ifdef SIGNED_COMPARE_SLOW\n#define U(x)\t((unsigned) (x))\n#else\n#define U(x)\t(x)\n#endif\n\ntypedef struct {\n    int numBits;\t\t/* Number of bits/code. */\n    long maxCode;\t\t/* Maximum code, given numBits. */\n    int hashTable[HSIZE];\n    unsigned int codeTable[HSIZE];\n    long hSize;\t\t\t/* For dynamic table sizing. */\n\n    /*\n     * To save much memory, we overlay the table used by compress() with those\n     * used by decompress(). The tab_prefix table is the same size and type as\n     * the codeTable. The tab_suffix table needs 2**GIFBITS characters. We get\n     * this from the beginning of hashTable. The output stack uses the rest of\n     * hashTable, and contains characters. There is plenty of room for any\n     * possible stack (stack used to be 8000 characters).\n     */\n\n    int freeEntry;\t\t/* First unused entry. */\n\n    /*\n     * Block compression parameters.  After all codes are used up, and\n     * compression rate changes, start over.\n     */\n\n    bool clearFlag;\n\n    int offset;\n    unsigned int inCount;\t/* Length of input */\n    unsigned int outCount;\t/* # of codes output (for debugging) */\n\n    /*\n     * Algorithm: use open addressing double hashing (no chaining) on the\n     * prefix code / next character combination. We do a variant of Knuth's\n     * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime\n     * secondary probe. Here, the modular division first probe is gives way to\n     * a faster exclusive-or manipulation. Also do block compression with an\n     * adaptive reset, whereby the code table is cleared when the compression\n     * ratio decreases, but after the table fills. The variable-length output\n     * codes are re-sized at this point, and a special CLEAR code is generated\n     * for the decompressor. Late addition: construct the table according to\n     * file size for noticeable speed improvement on small files. Please\n     * direct questions about this implementation to ames!jaw.\n     */\n\n    int initialBits;\n    void *destination;\n    WriteBytesFunc *writeProc;\n\n    int clearCode;\n    int eofCode;\n\n    unsigned long currentAccumulated;\n    int currentBits;\n\n    /*\n     * Number of characters so far in this 'packet'\n     */\n\n    int accumulatedByteCount;\n\n    /*\n     * Define the storage for the packet accumulator\n     */\n\n    unsigned char packetAccumulator[256];\n} GIFState_t;\n\n/*\n * Definition of new functions to write GIFs\n */\n\nstatic int\t\tColorNumber(GifWriterState *statePtr,\n\t\t\t    int red, int green, int blue);\nstatic void\t\tCompress(int initBits, void *handle,\n\t\t\t    WriteBytesFunc *writeProc, ifunptr readValue,\n\t\t\t    GifWriterState *statePtr);\nstatic int\t\tIsNewColor(GifWriterState *statePtr,\n\t\t\t    int red, int green, int blue);\nstatic void\t\tSaveMap(GifWriterState *statePtr,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tReadValue(GifWriterState *statePtr);\nstatic WriteBytesFunc\tWriteToChannel;\nstatic WriteBytesFunc\tWriteToByteArray;\nstatic void\t\tOutput(GIFState_t *statePtr, long code);\nstatic void\t\tClearForBlock(GIFState_t *statePtr);\nstatic void\t\tClearHashTable(GIFState_t *statePtr, int hSize);\nstatic void\t\tCharInit(GIFState_t *statePtr);\nstatic void\t\tCharOut(GIFState_t *statePtr, int c);\nstatic void\t\tFlushChar(GIFState_t *statePtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileMatchGIF --\n *\n *\tThis function is invoked by the photo image type to see if a file\n *\tcontains image data in GIF format.\n *\n * Results:\n *\tThe return value is 1 if the first characters in file f look like GIF\n *\tdata, and 0 otherwise.\n *\n * Side effects:\n *\tThe access position in f may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileMatchGIF(\n    TCL_UNUSED(Tcl_Interp *),\t/* not used */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    TCL_UNUSED(const char *),\t/* The name of the image file. */\n    TCL_UNUSED(Tcl_Obj *),\t/* User-specified format object, or NULL. */\n    TCL_UNUSED(Tcl_Obj *),\t/* metadata input, may be NULL */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here if the file is a valid raw GIF file. */\n    TCL_UNUSED(Tcl_Obj *))\t/* metadata return dict, may be NULL */\n{\n    GIFImageConfig gifConf;\n\n    memset(&gifConf, 0, sizeof(GIFImageConfig));\n    return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileReadGIF --\n *\n *\tThis function is called by the photo image type to read GIF format\n *\tdata from a file and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tThe access position in file f is changed, and new data is added to the\n *\timage given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileReadGIF(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    const char *fileName,\t/* The name of the image file. */\n    Tcl_Obj *format,\t\t/* User-specified format object, or NULL. */\n    TCL_UNUSED(Tcl_Obj *),\t/* metadata input, may be NULL */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY,\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n    Tcl_Obj *metadataOutObj)\t/* metadata return dict, may be NULL */\n{\n    int fileWidth, fileHeight, imageWidth, imageHeight;\n    unsigned int nBytes;\n    int index = 0, result = TCL_ERROR;\n    Tcl_Size objc = 0, i;\n    Tcl_Obj **objv;\n    unsigned char buf[100];\n    unsigned char *trashBuffer = NULL;\n    int bitPixel;\n    int gifLabel;\n    unsigned char colorMap[MAXCOLORMAPSIZE][4];\n    GIFGraphicControlExtensionBlock gifGraphicControlExtensionBlock;\n    static const char *const optionStrings[] = {\n\t\"-index\", NULL\n    };\n    GIFImageConfig gifConf, *gifConfPtr = &gifConf;\n\n    gifGraphicControlExtensionBlock.blockPresent = false;\n    /*\n     * Decode the magic used to convey when we're sourcing data from a string\n     * source and not a file.\n     */\n\n    memset(colorMap, 0, MAXCOLORMAPSIZE*4);\n    memset(gifConfPtr, 0, sizeof(GIFImageConfig));\n    if (fileName == INLINE_DATA_BINARY || fileName == INLINE_DATA_BASE64) {\n\tgifConfPtr->fromData = fileName;\n\tfileName = \"inline data\";\n    }\n\n    /*\n     * Parse the format string to get options.\n     */\n\n    if (format && Tcl_ListObjGetElements(interp, format,\n\t    &objc, &objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    for (i = 1; i < objc; i++) {\n\tint optionIdx;\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\tsizeof(char *), \"option name\", 0, &optionIdx) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (i == (objc-1)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no value given for \\\"%s\\\" option\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"OPT_VALUE\",\n\t\t    (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Read the GIF file header and check for some sanity.\n     */\n\n    if (!ReadGIFHeader(gifConfPtr, chan, &fileWidth, &fileHeight)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"couldn't read GIF header from file \\\"%s\\\"\", fileName));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"HEADER\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if ((fileWidth <= 0) || (fileHeight <= 0)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"GIF image file \\\"%s\\\" has dimension(s) <= 0\", fileName));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"BOGUS_SIZE\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Get the general colormap information.\n     */\n\n    if (Fread(gifConfPtr, buf, 1, 3, chan) != 3) {\n\t/*\n\t * Bug [865af0148c]: 3 bytes should be there, but data ended before\n\t */\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"GIF file truncated\", -1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"TRUNCATED\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n    bitPixel = 2 << (buf[0] & 0x07);\n\n    if (BitSet(buf[0], LOCALCOLORMAP)) {\t/* Global Colormap */\n\tif (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"error reading color map\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"COLOR_MAP\",\n\t\t    (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if ((srcX + width) > fileWidth) {\n\twidth = fileWidth - srcX;\n    }\n    if ((srcY + height) > fileHeight) {\n\theight = fileHeight - srcY;\n    }\n    if ((width <= 0) || (height <= 0)\n\t    || (srcX >= fileWidth) || (srcY >= fileHeight)) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Make sure we have enough space in the photo image to hold the data from\n     * the GIF.\n     */\n\n    if (Tk_PhotoExpand(interp, imageHandle,\n\t    destX + width, destY + height) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * -------------------------------------------------------------------------\n     * From here on, go to error to not leave memory leaks\n     * -------------------------------------------------------------------------\n     */\n\n    /*\n     * Search for the frame from the GIF to display.\n     */\n\n    while (1) {\n\tif (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {\n\t    goto error;\n\t}\n\n\tswitch (gifLabel) {\n\tcase GIF_TERMINATOR:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"no image data for this index\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"NO_DATA\",\n\t\t    (char *)NULL);\n\t    goto error;\n\n\tcase GIF_EXTENSION:\n\t    /*\n\t     * This is a GIF extension.\n\t     */\n\n\t    if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {\n\t\tgoto error;\n\t    }\n\t    if (DoExtension(gifConfPtr, chan, gifLabel,\n\t\t    gifConfPtr->workingBuffer, &gifGraphicControlExtensionBlock,\n\t\t    metadataOutObj)\n\t\t    < 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"error reading extension in GIF image\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"BAD_EXT\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    continue;\n\tcase GIF_START:\n\t    if (Fread(gifConfPtr, buf, 1, 9, chan) != 9) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't read left/top/width/height in GIF image\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"DIMENSIONS\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    break;\n\tdefault:\n\t    /*\n\t     * Not a valid start character; ignore it.\n\t     */\n\n\t    continue;\n\t}\n\n\t/*\n\t * We've read the header for a GIF frame. Work out what we are going\n\t * to do about it.\n\t */\n\n\timageWidth = LM_to_uint(buf[4], buf[5]);\n\timageHeight = LM_to_uint(buf[6], buf[7]);\n\tbitPixel = 1 << ((buf[8] & 0x07) + 1);\n\n\tif (index--) {\n\t    /*\n\t     * This is not the GIF frame we want to read: skip it.\n\t     */\n\n\t    if (BitSet(buf[8], LOCALCOLORMAP)) {\n\t\tif (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"error reading color map\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\",\n\t\t\t    \"COLOR_MAP\", (char *)NULL);\n\t\t    goto error;\n\t\t}\n\t    }\n\n\t    /*\n\t     * If we've not yet allocated a trash buffer, do so now.\n\t     */\n\n\t    if (trashBuffer == NULL) {\n\t\tif (fileWidth > (int)((UINT_MAX/3)/fileHeight)) {\n\t\t    goto error;\n\t\t}\n\t\tnBytes = fileWidth * fileHeight * 3;\n\t\ttrashBuffer = (unsigned char *)Tcl_Alloc(nBytes);\n\t\tif (trashBuffer) {\n\t\t    memset(trashBuffer, 0, nBytes);\n\t\t}\n\t    }\n\n\t    /*\n\t     * Slurp! Process the data for this image and stuff it in a trash\n\t     * buffer.\n\t     *\n\t     * Yes, it might be more efficient here to *not* store the data\n\t     * (we're just going to throw it away later). However, I elected\n\t     * to implement it this way for good reasons. First, I wanted to\n\t     * avoid duplicating the (fairly complex) LWZ decoder in\n\t     * ReadImage. Fine, you say, why didn't you just modify it to\n\t     * allow the use of a NULL specifier for the output buffer? I\n\t     * tried that, but it negatively impacted the performance of what\n\t     * I think will be the common case: reading the first image in the\n\t     * file. Rather than marginally improve the speed of the less\n\t     * frequent case, I chose to maintain high performance for the\n\t     * common case.\n\t     */\n\n\t    if (ReadImage(gifConfPtr, interp, trashBuffer, chan, imageWidth,\n\t\t    imageHeight, colorMap, 0, 0, 0, -1) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\n\t    /*\n\t     * This extension starts a new scope, so Graphic control Extension\n\t     * data should be cleared\n\t     */\n\t    gifGraphicControlExtensionBlock.blockPresent = false;\n\n\t    continue;\n\t}\n\tbreak;\n    }\n\n    /*\n     * Found the frame we want to read. Next, check for a local color map for\n     * this frame.\n     */\n\n    if (BitSet(buf[8], LOCALCOLORMAP)) {\n\tif (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"error reading color map\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"COLOR_MAP\",\n\t\t    (char *)NULL);\n\t    goto error;\n\t}\n    }\n\n    /*\n     * Extract the location within the overall visible image to put the data\n     * in this frame, together with the size of this frame.\n     */\n\n    index = LM_to_uint(buf[0], buf[1]);\n    srcX -= index;\n    if (srcX<0) {\n\tdestX -= srcX; width += srcX;\n\tsrcX = 0;\n    }\n\n    if (width > imageWidth) {\n\twidth = imageWidth;\n    }\n\n    index = LM_to_uint(buf[2], buf[3]);\n    srcY -= index;\n    if (index > srcY) {\n\tdestY -= srcY; height += srcY;\n\tsrcY = 0;\n    }\n    if (height > imageHeight) {\n\theight = imageHeight;\n    }\n\n    if ((width > 0) && (height > 0)) {\n\tunsigned char* pixelPtr;\n\tTk_PhotoImageBlock block;\n\tint transparent = -1;\n\tif (gifGraphicControlExtensionBlock.blockPresent) {\n\t    transparent = gifGraphicControlExtensionBlock.transparent;\n\t}\n\t/*\n\t * Read the data and put it into the photo buffer for display by the\n\t * general image machinery.\n\t */\n\n\tblock.width = width;\n\tblock.height = height;\n\tblock.pixelSize = (transparent>=0) ? 4 : 3;\n\tblock.offset[0] = 0;\n\tblock.offset[1] = 1;\n\tblock.offset[2] = 2;\n\tblock.offset[3] = (transparent>=0) ? 3 : 0;\n\tif (imageWidth > INT_MAX/block.pixelSize) {\n\t    goto error;\n\t}\n\tblock.pitch = block.pixelSize * imageWidth;\n\tif (imageHeight > (int)(UINT_MAX/block.pitch)) {\n\t    goto error;\n\t}\n\tnBytes = block.pitch * imageHeight;\n\tpixelPtr = (unsigned char*)Tcl_Alloc(nBytes);\n\tif (pixelPtr) {\n\t    memset(pixelPtr, 0, nBytes);\n\t}\n\n\tblock.pixelPtr = pixelPtr;\n\tif (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth,\n\t\timageHeight, colorMap, srcX, srcY, BitSet(buf[8], INTERLACE),\n\t\ttransparent) != TCL_OK) {\n\t    Tcl_Free(pixelPtr);\n\t    goto error;\n\t}\n\tblock.pixelPtr += srcX * block.pixelSize + srcY * block.pitch;\n\tif (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,\n\t\twidth, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {\n\t    Tcl_Free(pixelPtr);\n\t    goto error;\n\t}\n\tTcl_Free(pixelPtr);\n    }\n\n    /*\n     * Update the metadata dictionary with current image data\n     */\n\n    if (NULL != metadataOutObj) {\n\n\t/*\n\t * Save the update box, if not the whole image\n\t */\n\n\tif ( width != fileWidth || height != fileHeight) {\n\t    Tcl_Obj *itemList[4];\n\t    itemList[0] = Tcl_NewIntObj(destX);\n\t    itemList[1] = Tcl_NewIntObj(destY);\n\t    itemList[2] = Tcl_NewIntObj(width);\n\t    itemList[3] = Tcl_NewIntObj(height);\n\t    if ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t    Tcl_NewStringObj(\"update region\",-1),\n\t\t    Tcl_NewListObj(4, itemList) )) {\n\t\tresult = TCL_ERROR;\n\t\tgoto error;\n\t    }\n\t}\n\n\t/*\n\t * Copy the Graphic Control Extension Block data to the metadata\n\t * dictionary\n\t */\n\n\tif (gifGraphicControlExtensionBlock.blockPresent) {\n\t    if ( gifGraphicControlExtensionBlock.delayTime != 0) {\n\t\tif ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t\tTcl_NewStringObj(\"delay time\",-1),\n\t\t\tTcl_NewIntObj(gifGraphicControlExtensionBlock.delayTime)\n\t\t\t)) {\n\t\t    result = TCL_ERROR;\n\t\t    goto error;\n\t\t}\n\t    }\n\t    switch ( gifGraphicControlExtensionBlock.disposalMethod ) {\n\t    case 1: /* Do not dispose */\n\t\tif ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t\tTcl_NewStringObj(\"disposal method\",-1),\n\t\t\tTcl_NewStringObj(\"do not dispose\",-1))) {\n\t\t    result = TCL_ERROR;\n\t\t    goto error;\n\t\t}\n\t\tbreak;\n\t    case 2: /* Restore to background color */\n\t\tif ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t\tTcl_NewStringObj(\"disposal method\",-1),\n\t\t\tTcl_NewStringObj(\"restore to background color\",-1))) {\n\t\t    result = TCL_ERROR;\n\t\t    goto error;\n\t\t}\n\t\tbreak;\n\t    case 3: /* Restore to previous */\n\t\tif ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t\tTcl_NewStringObj(\"disposal method\",-1),\n\t\t\tTcl_NewStringObj(\"restore to previous\",-1))) {\n\t\t    result = TCL_ERROR;\n\t\t    goto error;\n\t\t}\n\t\tbreak;\n\t    }\n\t    if ( gifGraphicControlExtensionBlock.userInteraction != 0) {\n\t\tif ( TCL_OK != Tcl_DictObjPut(interp, metadataOutObj,\n\t\t\tTcl_NewStringObj(\"user interaction\",-1),\n\t\t\tTcl_NewBooleanObj(1))) {\n\t\t    result = TCL_ERROR;\n\t\t    goto error;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * We've successfully read the GIF frame (or there was nothing to read,\n     * which suits as well). We're done.\n     */\n\n    while (1) {\n\tif (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {\n\t    goto error;\n\t}\n\tswitch (gifLabel) {\n\tcase GIF_TERMINATOR:\n\t    break;\n\n\tcase GIF_EXTENSION:\n\t    /*\n\t     * This is a GIF extension.\n\t     */\n\n\t    if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) {\n\t\tgoto error;\n\t    }\n\t    if (DoExtension(gifConfPtr, chan, gifLabel,\n\t\t    gifConfPtr->workingBuffer, &gifGraphicControlExtensionBlock,\n\t\t    metadataOutObj)\n\t\t    < 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"error reading extension in GIF image\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"BAD_EXT\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    continue;\n\tcase GIF_START:\n\t    /*\n\t     * There should not be a second image block - bail out without error\n\t     */\n\t    break;\n\tdefault:\n\t    /*\n\t     * Not a valid start character; ignore it.\n\t     */\n\n\t    continue;\n\t}\n\tbreak;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, TCL_INDEX_NONE));\n    result = TCL_OK;\n\nerror:\n\n    /*\n     * If a trash buffer has been allocated, free it now.\n     */\n\n    if (trashBuffer != NULL) {\n\tTcl_Free(trashBuffer);\n    }\n    return result;\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * Read one Byte --\n *\n *\tRead one byte (label byte) from the image stream.\n *\n * Results:\n *\tThe return value is 1 if the first characters in the data are like GIF\n *\tdata, and 0 otherwise.\n *\n * Side effects:\n *\tThe access position in the source is incremented.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadOneByte(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    GIFImageConfig *gifConfPtr,\n    Tcl_Channel chan\t\t/* The image file, open for reading. */\n    )\n{\n    unsigned char buf[2];\n    if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {\n\t/*\n\t * Premature end of image.\n\t */\n\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"premature end of image data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"PREMATURE_END\", (char *)NULL);\n\treturn -1;\n    }\n    return buf[0];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringMatchGIF --\n *\n *\tThis function is invoked by the photo image type to see if an object\n *\tcontains image data in GIF format.\n *\n * Results:\n *\tThe return value is 1 if the first characters in the data are like GIF\n *\tdata, and 0 otherwise.\n *\n * Side effects:\n *\tThe size of the image is placed in widthPtr and heightPtr.\n *\n *----------------------------------------------------------------------\n */\n\n\nstatic int\nStringMatchGIF(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* not used */\n    Tcl_Obj *dataObj,\t\t/* the object containing the image data */\n    TCL_UNUSED(Tcl_Obj *),\t\t/* the image format object, or NULL */\n    TCL_UNUSED(Tcl_Obj *),\t/* metadata input, may be NULL */\n    int *widthPtr,\t\t/* where to put the string width */\n    int *heightPtr,\t\t/* where to put the string height */\n    TCL_UNUSED(Tcl_Obj *))\t/* metadata return dict, may be NULL */\n{\n    unsigned char *data, header[10];\n    Tcl_Size got, length;\n    MFile handle;\n\n    data = Tcl_GetByteArrayFromObj(dataObj, &length);\n\n    /*\n     * Header is a minimum of 10 bytes.\n     */\n\n    if (!data || length < 10) {\n\treturn 0;\n    }\n\n    /*\n     * Check whether the data is Base64 encoded.\n     */\n\n    if ((strncmp(GIF87a, (char *) data, 6) != 0) &&\n\t    (strncmp(GIF89a, (char *) data, 6) != 0)) {\n\t/*\n\t * Try interpreting the data as Base64 encoded\n\t */\n\n\tmInit((unsigned char *) data, &handle, length);\n\tgot = Mread(header, 10, 1, &handle);\n\tif (got != 10 ||\n\t\t((strncmp(GIF87a, (char *) header, 6) != 0)\n\t\t&& (strncmp(GIF89a, (char *) header, 6) != 0))) {\n\t    return 0;\n\t}\n    } else {\n\tmemcpy(header, data, 10);\n    }\n    *widthPtr = LM_to_uint(header[6], header[7]);\n    *heightPtr = LM_to_uint(header[8], header[9]);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringReadGIF --\n *\n *\tThis function is called by the photo image type to read GIF format\n *\tdata from an object, optionally base64 encoded, and give it to the\n *\tphoto image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNew data is added to the image given by imageHandle. This function\n *\tcalls FileReadGIF by redefining the operation of fprintf temporarily.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringReadGIF(\n    Tcl_Interp *interp,\t\t/* interpreter for reporting errors in */\n    Tcl_Obj *dataObj,\t\t/* object containing the image */\n    Tcl_Obj *format,\t\t/* format object, or NULL */\n    Tcl_Obj *metadataInObj,\t/* metadata input, may be NULL */\n    Tk_PhotoHandle imageHandle,\t/* the image to write this data into */\n    int destX, int destY,\t/* The rectangular region of the */\n    int width, int height,\t/* image to copy */\n    int srcX, int srcY,\n    Tcl_Obj *metadataOutObj)\t/* metadata return dict, may be NULL */\n{\n    MFile handle, *hdlPtr = &handle;\n    Tcl_Size length;\n    const char *xferFormat;\n    unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length);\n\n    mInit(data, hdlPtr, length);\n\n    /*\n     * Check whether the data is Base64 encoded by doing a character-by-\n     * charcter comparison with the binary-format headers; BASE64-encoded\n     * never matches (matching the other way is harder because of potential\n     * padding of the BASE64 data).\n     */\n\n    if (strncmp(GIF87a, (char *) data, 6)\n\t    && strncmp(GIF89a, (char *) data, 6)) {\n\txferFormat = INLINE_DATA_BASE64;\n    } else {\n\txferFormat = INLINE_DATA_BINARY;\n    }\n\n    /*\n     * Fall through to the file reader now that we have a correctly-configured\n     * pseudo-channel to pull the data from.\n     */\n\n    return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, format,\n\t    metadataInObj, imageHandle, destX, destY, width, height, srcX, srcY,\n\t    metadataOutObj);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadGIFHeader --\n *\n *\tThis function reads the GIF header from the beginning of a GIF file\n *\tand returns the dimensions of the image.\n *\n * Results:\n *\tThe return value is 1 if file \"f\" appears to start with a valid GIF\n *\theader, 0 otherwise. If the header is valid, then *widthPtr and\n *\t*heightPtr are modified to hold the dimensions of the image.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadGIFHeader(\n    GIFImageConfig *gifConfPtr,\n    Tcl_Channel chan,\t\t/* Image file to read the header from */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n{\n    unsigned char buf[7];\n\n    if ((Fread(gifConfPtr, buf, 1, 6, chan) != 6)\n\t    || ((strncmp(GIF87a, (char *) buf, 6) != 0)\n\t    && (strncmp(GIF89a, (char *) buf, 6) != 0))) {\n\treturn 0;\n    }\n\n    if (Fread(gifConfPtr, buf, 1, 4, chan) != 4) {\n\treturn 0;\n    }\n\n    *widthPtr = LM_to_uint(buf[0], buf[1]);\n    *heightPtr = LM_to_uint(buf[2], buf[3]);\n    return 1;\n}\n\f\n/*\n *-----------------------------------------------------------------\n * The code below is copied from the giftoppm program and modified just\n * slightly.\n *-----------------------------------------------------------------\n */\n\nstatic int\nReadColorMap(\n    GIFImageConfig *gifConfPtr,\n    Tcl_Channel chan,\n    int number,\n    unsigned char buffer[MAXCOLORMAPSIZE][4])\n{\n    int i;\n    unsigned char rgb[3];\n\n    for (i = 0; i < number; ++i) {\n\tif (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) {\n\t    return 0;\n\t}\n\n\tif (buffer) {\n\t    buffer[i][CM_RED] = rgb[0];\n\t    buffer[i][CM_GREEN] = rgb[1];\n\t    buffer[i][CM_BLUE] = rgb[2];\n\t    buffer[i][CM_ALPHA] = 255;\n\t}\n    }\n    return 1;\n}\n\f\n/*\n*----------------------------------------------------------------------\n*\n* DoExtension --\n*\n*\tProcess a GIF extension block\n*\n* Results:\n*\t-1 to trigger an extension read error\n*       >= 0 ok\n*\n* Side effects:\n*       The gifGraphicControlExtensionBlock is set if present in current\n*       extensions\n*       The data of the following extensions are saved to the metadata dict:\n*       - Application extension\n*         - Comment extension in key \"comment\"\n*       Plain text extensions are currently ignored.\n*\n*----------------------------------------------------------------------\n*/\n\nstatic int\nDoExtension(\n    GIFImageConfig *gifConfPtr,\n    Tcl_Channel chan,\n    int label,\n    unsigned char *buf, /* defined as 280 byte working buffer */\n    GIFGraphicControlExtensionBlock *gifGraphicControlExtensionBlock,\n    Tcl_Obj *metadataOutObj)\n{\n    int count;\n    /* Prepare extension name\n     * Maximum string size: \"comment\" + Code(3) + trailing zero\n     */\n    char extensionStreamName[8];\n    extensionStreamName[0] = '\\0';\n\n    switch (label) {\n    case 0x01:\t\t\t/* Plain Text Extension */\n\t/*\n\t * This extension starts a new scope, so Graphic control Extension\n\t * data should be cleared\n\t */\n\tgifGraphicControlExtensionBlock->blockPresent = false;\n\t/* this extension is ignored, skip below */\n\tbreak;\n    case 0xf9:\t\t\t/* Graphic Control Extension */\n\tcount = GetDataBlock(gifConfPtr, chan, buf);\n\tif (count < 0) {\n\t    return -1;\n\t}\n\tgifGraphicControlExtensionBlock->blockPresent = true;\n\t/* save disposal method */\n\tgifGraphicControlExtensionBlock->disposalMethod\n\t\t= ((buf[0] & 0x1C) >> 2);\n\t/* save disposal method */\n\tgifGraphicControlExtensionBlock->userInteraction = ((buf[0] & 2) >> 1);\n\t/* save delay time */\n\tgifGraphicControlExtensionBlock->delayTime\n\t\t= LM_to_uint(buf[1], buf[2]);\n\t/* save transparent index if given */\n\tif ((buf[0] & 0x1) == 0) {\n\t    gifGraphicControlExtensionBlock->transparent = -1;\n\t} else {\n\t    gifGraphicControlExtensionBlock->transparent = buf[3];\n\t}\n\tbreak;\n    case 0xfe:\t\t\t/* Comment Extension */\n\tstrcpy(extensionStreamName,\"comment\");\n\t/* copy the extension data below */\n\tbreak;\n    }\n    /* Add extension to dict */\n    if (NULL != metadataOutObj\n\t    && extensionStreamName[0] != '\\0' ) {\n\tTcl_Obj *ValueObj = NULL;\n\tint length = 0;\n\tfor (;;) {\n\t    count = GetDataBlock(gifConfPtr, chan, buf);\n\t    switch (count) {\n\t    case -1: /* error */\n\t\treturn -1;\n\t    case 0: /* end of data */\n\t\tif (length > 0) {\n\t\t    if ( TCL_OK != Tcl_DictObjPut(NULL, metadataOutObj,\n\t\t\t    Tcl_NewByteArrayObj(\n\t\t\t\t(unsigned char *)extensionStreamName,\n\t\t\t    strlen(extensionStreamName)), ValueObj)) {\n\t\t\treturn -1;\n\t\t    }\n\t\t}\n\t\t/* return success */\n\t\treturn 0;\n\t    default: /* block received */\n\t\tif (length == 0) {\n\t\t    /* first block */\n\t\t    ValueObj = Tcl_NewByteArrayObj(buf, count);\n\t\t    length = count;\n\t\t} else {\n\t\t    /* consecutive block */\n\t\t    unsigned char *bytePtr;\n\t\t    bytePtr = Tcl_SetByteArrayLength(ValueObj, length+count);\n\t\t    memcpy(bytePtr+length,buf,count);\n\t\t    length += count;\n\t\t}\n\t\tbreak;\n\t    }\n\t} /* for */\n    }\n    /* skip eventual remaining data block bytes */\n    do {\n\tcount = GetDataBlock(gifConfPtr, chan, buf);\n    } while (count > 0);\n    return count; /* this may be -1 for error or 0 */\n}\n\f\nstatic int\nGetDataBlock(\n    GIFImageConfig *gifConfPtr,\n    Tcl_Channel chan,\n    unsigned char *buf)\n{\n    unsigned char count;\n\n    if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) {\n\treturn -1;\n    }\n\n    if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) {\n\treturn -1;\n    }\n\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadImage --\n *\n *\tProcess a GIF image from a given source, with a given height, width,\n *\ttransparency, etc.\n *\n *\tThis code is based on the code found in the ImageMagick GIF decoder,\n *\twhich is © 2000 ImageMagick Studio.\n *\n *\tSome thoughts on our implementation:\n *\tIt sure would be nice if ReadImage didn't take 11 parameters! I think\n *\tthat if we were smarter, we could avoid doing that.\n *\n *\tPossible further optimizations: we could pull the GetCode function\n *\tdirectly into ReadImage, which would improve our speed.\n *\n * Results:\n *\tProcesses a GIF image and loads the pixel data into a memory array.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadImage(\n    GIFImageConfig *gifConfPtr,\n    Tcl_Interp *interp,\n    unsigned char *imagePtr,\n    Tcl_Channel chan,\n    int len, int rows,\n    unsigned char cmap[MAXCOLORMAPSIZE][4],\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    int interlace,\n    int transparent)\n{\n    unsigned char initialCodeSize;\n    int xpos = 0, ypos = 0, pass = 0, i, count;\n    unsigned char *pixelPtr;\n    static const int interlaceStep[] = { 8, 8, 4, 2 };\n    static const int interlaceStart[] = { 0, 4, 2, 1 };\n    unsigned short prefix[(1 << MAX_LWZ_BITS)];\n    unsigned char append[(1 << MAX_LWZ_BITS)];\n    unsigned char stack[(1 << MAX_LWZ_BITS)*2];\n    unsigned char *top;\n    int codeSize, clearCode, inCode, endCode, oldCode, maxCode;\n    int code, firstCode, v;\n\n    /*\n     * Initialize the decoder\n     */\n\n    if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"error reading GIF image: %s\", Tcl_PosixError(interp)));\n\treturn TCL_ERROR;\n    }\n\n    if (initialCodeSize > MAX_LWZ_BITS) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"malformed image\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"MALFORMED\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (transparent != -1) {\n\tcmap[transparent][CM_RED] = 0;\n\tcmap[transparent][CM_GREEN] = 0;\n\tcmap[transparent][CM_BLUE] = 0;\n\tcmap[transparent][CM_ALPHA] = 0;\n    }\n\n    pixelPtr = imagePtr;\n\n    /*\n     * Initialize the decoder.\n     *\n     * Set values for \"special\" numbers:\n     * clear code\treset the decoder\n     * end code\t\tstop decoding\n     * code size\tsize of the next code to retrieve\n     * max code\t\tnext available table position\n     */\n\n    clearCode = 1 << (int) initialCodeSize;\n    endCode = clearCode + 1;\n    codeSize = (int) initialCodeSize + 1;\n    maxCode = clearCode + 2;\n    oldCode = -1;\n    firstCode = -1;\n\n    memset(prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short));\n    memset(append, 0, (1 << MAX_LWZ_BITS) * sizeof(char));\n    for (i = 0; i < clearCode; i++) {\n\tappend[i] = i;\n    }\n    top = stack;\n\n    GetCode(chan, 0, 1, gifConfPtr);\n\n    /*\n     * Read until we finish the image\n     */\n\n    for (i = 0, ypos = 0; i < rows; i++) {\n\tfor (xpos = 0; xpos < len; ) {\n\t    if (top == stack) {\n\t\t/*\n\t\t * Bummer - our stack is empty. Now we have to work!\n\t\t */\n\n\t\tcode = GetCode(chan, codeSize, 0, gifConfPtr);\n\t\tif (code < 0) {\n\t\t    return TCL_OK;\n\t\t}\n\n\t\tif (code > maxCode || code == endCode) {\n\t\t    /*\n\t\t     * If we're doing things right, we should never receive a\n\t\t     * code that is greater than our current maximum code. If\n\t\t     * we do, bail, because our decoder does not yet have that\n\t\t     * code set up.\n\t\t     *\n\t\t     * If the code is the magic endCode value, quit.\n\t\t     */\n\n\t\t    return TCL_OK;\n\t\t}\n\n\t\tif (code == clearCode) {\n\t\t    /*\n\t\t     * Reset the decoder.\n\t\t     */\n\n\t\t    codeSize = initialCodeSize + 1;\n\t\t    maxCode = clearCode + 2;\n\t\t    oldCode = -1;\n\t\t    continue;\n\t\t}\n\n\t\tif (oldCode == -1) {\n\t\t    /*\n\t\t     * Last pass reset the decoder, so the first code we see\n\t\t     * must be a singleton. Seed the stack with it, and set up\n\t\t     * the old/first code pointers for insertion into the\n\t\t     * codes table. We can't just roll this into the clearCode\n\t\t     * test above, because at that point we have not yet read\n\t\t     * the next code.\n\t\t     */\n\n\t\t    *top++ = append[code];\n\t\t    oldCode = code;\n\t\t    firstCode = code;\n\t\t    continue;\n\t\t}\n\n\t\tinCode = code;\n\n\t\tif ((code == maxCode) && (maxCode < (1 << MAX_LWZ_BITS))) {\n\t\t    /*\n\t\t     * maxCode is always one bigger than our highest assigned\n\t\t     * code. If the code we see is equal to maxCode, then we\n\t\t     * are about to add a new entry to the codes table.\n\t\t     */\n\n\t\t    *top++ = firstCode;\n\t\t    code = oldCode;\n\t\t}\n\n\t\twhile (code > clearCode) {\n\t\t    /*\n\t\t     * Populate the stack by tracing the code in the codes\n\t\t     * table from its tail to its head\n\t\t     */\n\n\t\t    *top++ = append[code];\n\t\t    code = prefix[code];\n\t\t}\n\t\tfirstCode = append[code];\n\n\t\t/*\n\t\t * Push the head of the code onto the stack.\n\t\t */\n\n\t\t*top++ = firstCode;\n\n\t\tif (maxCode < (1 << MAX_LWZ_BITS)) {\n\t\t    /*\n\t\t     * If there's still room in our codes table, add a new entry.\n\t\t     * Otherwise don't, and keep using the current table.\n\t\t     * See DEFERRED CLEAR CODE IN LZW COMPRESSION in the GIF89a\n\t\t     * specification.\n\t\t     */\n\n\t\t    prefix[maxCode] = oldCode;\n\t\t    append[maxCode] = firstCode;\n\t\t    maxCode++;\n\t\t}\n\n\t\t/*\n\t\t * maxCode tells us the maximum code value we can accept. If\n\t\t * we see that we need more bits to represent it than we are\n\t\t * requesting from the unpacker, we need to increase the\n\t\t * number we ask for.\n\t\t */\n\n\t\tif ((maxCode >= (1 << codeSize))\n\t\t\t&& (maxCode < (1<<MAX_LWZ_BITS))) {\n\t\t    codeSize++;\n\t\t}\n\t\toldCode = inCode;\n\t    }\n\n\t    /*\n\t     * Pop the next color index off the stack.\n\t     */\n\n\t    v = *(--top);\n\t    if (v < 0) {\n\t\treturn TCL_OK;\n\t    }\n\n\t    /*\n\t     * If pixelPtr is null, we're skipping this image (presumably\n\t     * there are more in the file and we will be called to read one of\n\t     * them later)\n\t     */\n\n\t    *pixelPtr++ = cmap[v][CM_RED];\n\t    *pixelPtr++ = cmap[v][CM_GREEN];\n\t    *pixelPtr++ = cmap[v][CM_BLUE];\n\t    if (transparent >= 0) {\n\t\t*pixelPtr++ = cmap[v][CM_ALPHA];\n\t    }\n\t    xpos++;\n\n\t}\n\n\t/*\n\t * If interlacing, the next ypos is not just +1.\n\t */\n\n\tif (interlace) {\n\t    ypos += interlaceStep[pass];\n\t    while (ypos >= rows) {\n\t\tpass++;\n\t\tif (pass > 3) {\n\t\t    return TCL_OK;\n\t\t}\n\t\typos = interlaceStart[pass];\n\t    }\n\t} else {\n\t    ypos++;\n\t}\n\tpixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);\n    }\n\n    /*\n     * Now read until the final zero byte.\n     * It was observed that there might be 1 length blocks\n     * (test imgPhoto-14.1) which are not read.\n     *\n     * The field \"stack\" is abused for temporary buffer. it has 4096 bytes\n     * and we need 256.\n     *\n     * Loop until we hit a 0 length block which is the end sign.\n     */\n    while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack)))\n    {\n\tif (-1 == count ) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error reading GIF image: %s\", Tcl_PosixError(interp)));\n\t    return TCL_ERROR;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetCode --\n *\n *\tExtract the next compression code from the file. In GIF's, the\n *\tcompression codes are between 3 and 12 bits long and are then packed\n *\tinto 8 bit bytes, left to right, for example:\n *\t\tbbbaaaaa\n *\t\tdcccccbb\n *\t\teeeedddd\n *\t\t...\n *\tWe use a byte buffer read from the file and a sliding window to unpack\n *\tthe bytes. Thanks to ImageMagick for the sliding window idea.\n *\targs:  chan\t    the channel to read from\n *\t       code_size    size of the code to extract\n *\t       flag\t    boolean indicating whether the extractor should be\n *\t\t\t    reset or not\n *\n * Results:\n *\tcode\t\t    the next compression code\n *\n * Side effects:\n *\tMay consume more input from chan.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetCode(\n    Tcl_Channel chan,\n    int code_size,\n    int flag,\n    GIFImageConfig *gifConfPtr)\n{\n    int ret;\n\n    if (flag) {\n\t/*\n\t * Initialize the decoder.\n\t */\n\n\tgifConfPtr->reader.bitsInWindow = 0;\n\tgifConfPtr->reader.bytes = 0;\n\tgifConfPtr->reader.window = 0;\n\tgifConfPtr->reader.done = 0;\n\tgifConfPtr->reader.c = NULL;\n\treturn 0;\n    }\n\n    while (gifConfPtr->reader.bitsInWindow < code_size) {\n\t/*\n\t * Not enough bits in our window to cover the request.\n\t */\n\n\tif (gifConfPtr->reader.done) {\n\t    return -1;\n\t}\n\tif (gifConfPtr->reader.bytes == 0) {\n\t    /*\n\t     * Not enough bytes in our buffer to add to the window.\n\t     */\n\n\t    gifConfPtr->reader.bytes =\n\t\t    GetDataBlock(gifConfPtr, chan, gifConfPtr->workingBuffer);\n\t    gifConfPtr->reader.c = gifConfPtr->workingBuffer;\n\t    if (gifConfPtr->reader.bytes <= 0) {\n\t\tgifConfPtr->reader.done = 1;\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * Tack another byte onto the window, see if that's enough.\n\t */\n\n\tgifConfPtr->reader.window +=\n\t\t(*gifConfPtr->reader.c) << gifConfPtr->reader.bitsInWindow;\n\tgifConfPtr->reader.c++;\n\tgifConfPtr->reader.bitsInWindow += 8;\n\tgifConfPtr->reader.bytes--;\n    }\n\n    /*\n     * The next code will always be the last code_size bits of the window.\n     */\n\n    ret = gifConfPtr->reader.window & ((1 << code_size) - 1);\n\n    /*\n     * Shift data in the window to put the next code at the end.\n     */\n\n    gifConfPtr->reader.window >>= code_size;\n    gifConfPtr->reader.bitsInWindow -= code_size;\n    return ret;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Minit -- --\n *\n *\tThis function initializes a base64 decoder handle\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe base64 handle is initialized\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nmInit(\n    unsigned char *string,\t/* string containing initial mmencoded data */\n    MFile *handle,\t\t/* mmdecode \"file\" handle */\n    Tcl_Size length)\t\t\t/* Number of bytes in string */\n{\n    handle->data = string;\n    handle->state = 0;\n    handle->c = 0;\n    handle->length = length;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Mread --\n *\n *\tThis function is invoked by the GIF file reader as a temporary\n *\treplacement for \"fread\", to get GIF data out of a string (using\n *\tMgetc).\n *\n * Results:\n *\tThe return value is the number of characters \"read\"\n *\n * Side effects:\n *\tThe base64 handle will change state.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nMread(\n    unsigned char *dst,\t\t/* where to put the result */\n    Tcl_Size chunkSize,\t\t/* size of each transfer */\n    Tcl_Size numChunks,\t\t/* number of chunks */\n    MFile *handle)\t\t/* mmdecode \"file\" handle */\n{\n    int c;\n    Tcl_Size i, count = chunkSize * numChunks;\n\n    for (i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) {\n\t*dst++ = c;\n    }\n    return i;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Mgetc --\n *\n *\tThis function gets the next decoded character from an mmencode handle.\n *\tThis causes at least 1 character to be \"read\" from the encoded string.\n *\n * Results:\n *\tThe next byte (or GIF_DONE) is returned.\n *\n * Side effects:\n *\tThe base64 handle will change state.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMgetc(\n    MFile *handle)\t\t/* Handle containing decoder data and state */\n{\n    int c;\n    int result = 0;\t\t/* Initialization needed only to prevent gcc\n\t\t\t\t * compiler warning. */\n\n    if (handle->state == GIF_DONE) {\n\treturn GIF_DONE;\n    }\n\n    do {\n\tif (handle->length-- <= 0) {\n\t    return GIF_DONE;\n\t}\n\tc = char64(*handle->data);\n\thandle->data++;\n    } while (c == GIF_SPACE);\n\n    if (c > GIF_SPECIAL) {\n\thandle->state = GIF_DONE;\n\treturn handle->c;\n    }\n\n    switch (handle->state++) {\n    case 0:\n\thandle->c = c<<2;\n\tresult = Mgetc(handle);\n\tbreak;\n    case 1:\n\tresult = handle->c | (c>>4);\n\thandle->c = (c&0xF)<<4;\n\tbreak;\n    case 2:\n\tresult = handle->c | (c>>2);\n\thandle->c = (c&0x3) << 6;\n\tbreak;\n    case 3:\n\tresult = handle->c | c;\n\thandle->state = 0;\n\tbreak;\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * char64 --\n *\n *\tThis function converts a base64 ascii character into its binary\n *\tequivalent. This code is a slightly modified version of the char64\n *\tfunction in N. Borenstein's metamail decoder.\n *\n * Results:\n *\tThe binary value, or an error code.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nchar64(\n    int c)\n{\n    switch(c) {\n    case 'A': return 0;  case 'B': return 1;  case 'C': return 2;\n    case 'D': return 3;  case 'E': return 4;  case 'F': return 5;\n    case 'G': return 6;  case 'H': return 7;  case 'I': return 8;\n    case 'J': return 9;  case 'K': return 10; case 'L': return 11;\n    case 'M': return 12; case 'N': return 13; case 'O': return 14;\n    case 'P': return 15; case 'Q': return 16; case 'R': return 17;\n    case 'S': return 18; case 'T': return 19; case 'U': return 20;\n    case 'V': return 21; case 'W': return 22; case 'X': return 23;\n    case 'Y': return 24; case 'Z': return 25; case 'a': return 26;\n    case 'b': return 27; case 'c': return 28; case 'd': return 29;\n    case 'e': return 30; case 'f': return 31; case 'g': return 32;\n    case 'h': return 33; case 'i': return 34; case 'j': return 35;\n    case 'k': return 36; case 'l': return 37; case 'm': return 38;\n    case 'n': return 39; case 'o': return 40; case 'p': return 41;\n    case 'q': return 42; case 'r': return 43; case 's': return 44;\n    case 't': return 45; case 'u': return 46; case 'v': return 47;\n    case 'w': return 48; case 'x': return 49; case 'y': return 50;\n    case 'z': return 51; case '0': return 52; case '1': return 53;\n    case '2': return 54; case '3': return 55; case '4': return 56;\n    case '5': return 57; case '6': return 58; case '7': return 59;\n    case '8': return 60; case '9': return 61; case '+': return 62;\n    case '/': return 63;\n\n    case ' ': case '\\t': case '\\n': case '\\r': case '\\f':\n\treturn GIF_SPACE;\n    case '=':\n\treturn GIF_PAD;\n    case '\\0':\n\treturn GIF_DONE;\n    default:\n\treturn GIF_BAD;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Fread --\n *\n *\tThis function calls either fread or Mread to read data from a file or\n *\ta base64 encoded string.\n *\n * Results: - same as POSIX fread() or Tcl Tcl_Read()\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nFread(\n    GIFImageConfig *gifConfPtr,\n    unsigned char *dst,\t\t/* where to put the result */\n    Tcl_Size hunk, Tcl_Size count,\t/* how many */\n    Tcl_Channel chan)\n{\n    if (hunk < 0 || count < 0) {\n\treturn -1;\n    }\n\n    if (gifConfPtr->fromData == INLINE_DATA_BASE64) {\n\treturn Mread(dst, hunk, count, (MFile *) chan);\n    }\n\n    if (gifConfPtr->fromData == INLINE_DATA_BINARY) {\n\tMFile *handle = (MFile *) chan;\n\n\tif ((handle->length <= 0) || (handle->length < hunk*count)) {\n\t    return -1;\n\t}\n\tmemcpy(dst, handle->data, hunk * count);\n\thandle->data += hunk * count;\n\thandle->length -= hunk * count;\n\treturn hunk * count;\n    }\n\n    /*\n     * Otherwise we've got a real file to read.\n     */\n\n    return Tcl_Read(chan, (char *) dst, hunk * count);\n}\n\f\n/*\n * ChanWriteGIF - writes a image in GIF format.\n *-------------------------------------------------------------------------\n * Author:\t\tLolo\n *\t\t\tEngeneering Projects Area\n *\t\t\tDepartment of Mining\n *\t\t\tUniversity of Oviedo\n * e-mail\t\tzz11425958@zeus.etsimo.uniovi.es\n *\t\t\tlolo@pcsig22.etsimo.uniovi.es\n * Date:\t\tFri September 20 1996\n *\n * Modified for transparency handling (gif89a)\n * by Jan Nijtmans <nijtmans@users.sourceforge.net>\n *\n *----------------------------------------------------------------------\n * FileWriteGIF-\n *\n *\tThis function is called by the photo image type to write GIF format\n *\tdata from a photo image into a given file\n *\n * Results:\n *\tA standard TCL completion code.  If TCL_ERROR is returned then an\n *\terror message is left in the interp's result.\n *\n *----------------------------------------------------------------------\n */\n\n\f\nstatic int\nFileWriteGIF(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    const char *filename,\n    Tcl_Obj *format,\n    Tcl_Obj *metadataInObj,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    Tcl_Channel chan = NULL;\n    int result;\n\n    chan = Tcl_OpenFileChannel(interp, (char *) filename, \"w\", 0644);\n    if (!chan) {\n\treturn TCL_ERROR;\n    }\n    if (Tcl_SetChannelOption(interp, chan, \"-translation\", \"binary\")\n\t    != TCL_OK) {\n\tTcl_Close(NULL, chan);\n\treturn TCL_ERROR;\n    }\n\n    result = CommonWriteGIF(interp, chan, WriteToChannel, format, metadataInObj,\n\t    blockPtr);\n\n    if (Tcl_Close(interp, chan) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    return result;\n}\n\nstatic int\nStringWriteGIF(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors and\n\t\t\t\t * returning the GIF data. */\n    Tcl_Obj *format,\n    Tcl_Obj *metadataInObj,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    int result;\n    Tcl_Obj *objPtr = Tcl_NewObj();\n\n    Tcl_IncrRefCount(objPtr);\n    result = CommonWriteGIF(interp, objPtr, WriteToByteArray, format,\n\t    metadataInObj, blockPtr);\n    if (result == TCL_OK) {\n\tTcl_SetObjResult(interp, objPtr);\n    }\n    Tcl_DecrRefCount(objPtr);\n    return result;\n}\n\nstatic Tcl_Size\nWriteToChannel(\n    void *clientData,\n    const char *bytes,\n    Tcl_Size byteCount)\n{\n    Tcl_Channel handle = (Tcl_Channel)clientData;\n\n    return Tcl_Write(handle, bytes, byteCount);\n}\n\nstatic Tcl_Size\nWriteToByteArray(\n    void *clientData,\n    const char *bytes,\n    Tcl_Size byteCount)\n{\n    Tcl_Obj *objPtr = (Tcl_Obj *)clientData;\n    Tcl_Obj *tmpObj = Tcl_NewByteArrayObj((unsigned char *) bytes, byteCount);\n\n    Tcl_IncrRefCount(tmpObj);\n    Tcl_AppendObjToObj(objPtr, tmpObj);\n    Tcl_DecrRefCount(tmpObj);\n    return byteCount;\n}\n\f\nstatic int\nCommonWriteGIF(\n    Tcl_Interp *interp,\n    void *handle,\n    WriteBytesFunc *writeProc,\n    TCL_UNUSED(Tcl_Obj *),\n    Tcl_Obj *metadataInObj,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    GifWriterState state;\n    int resolution;\n    long width, height, x;\n    unsigned char c;\n    unsigned int top, left;\n\n    top = 0;\n    left = 0;\n\n    memset(&state, 0, sizeof(state));\n\n    state.pixelSize = blockPtr->pixelSize;\n    state.greenOffset = blockPtr->offset[1]-blockPtr->offset[0];\n    state.blueOffset = blockPtr->offset[2]-blockPtr->offset[0];\n    state.alphaOffset = blockPtr->offset[0];\n    if (state.alphaOffset < blockPtr->offset[2]) {\n\tstate.alphaOffset = blockPtr->offset[2];\n    }\n    if (++state.alphaOffset < state.pixelSize) {\n\tstate.alphaOffset -= blockPtr->offset[0];\n    } else {\n\tstate.alphaOffset = 0;\n    }\n\n    writeProc(handle, (char *) (state.alphaOffset ? GIF89a : GIF87a), 6);\n\n    for (x = 0; x < MAXCOLORMAPSIZE ;x++) {\n\tstate.mapa[x][CM_RED] = 255;\n\tstate.mapa[x][CM_GREEN] = 255;\n\tstate.mapa[x][CM_BLUE] = 255;\n    }\n\n    width = blockPtr->width;\n    height = blockPtr->height;\n    state.pixelOffset = blockPtr->pixelPtr + blockPtr->offset[0];\n    state.pixelPitch = blockPtr->pitch;\n    SaveMap(&state, blockPtr);\n    if (state.num >= MAXCOLORMAPSIZE) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"too many colors\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"GIF\", \"COLORFUL\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (state.num<2) {\n\tstate.num = 2;\n    }\n    c = LSB(width);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(width);\n    writeProc(handle, (char *) &c, 1);\n    c = LSB(height);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(height);\n    writeProc(handle, (char *) &c, 1);\n\n    resolution = 0;\n    while (state.num >> resolution) {\n\tresolution++;\n    }\n    c = 111 + resolution * 17;\n    writeProc(handle, (char *) &c, 1);\n\n    state.num = 1 << resolution;\n\n    /*\n     * Background color\n     */\n\n    c = 0;\n    writeProc(handle, (char *) &c, 1);\n\n    /*\n     * Zero for future expansion.\n     */\n\n    writeProc(handle, (char *) &c, 1);\n\n    for (x = 0; x < state.num; x++) {\n\tc = state.mapa[x][CM_RED];\n\twriteProc(handle, (char *) &c, 1);\n\tc = state.mapa[x][CM_GREEN];\n\twriteProc(handle, (char *) &c, 1);\n\tc = state.mapa[x][CM_BLUE];\n\twriteProc(handle, (char *) &c, 1);\n    }\n\n    /*\n     * Write out extension for transparent colour index, if necessary.\n     */\n\n    if (state.alphaOffset) {\n\tc = GIF_EXTENSION;\n\twriteProc(handle, (char *) &c, 1);\n\twriteProc(handle, \"\\371\\4\\1\\0\\0\\0\", 7);\n    }\n\n    c = GIF_START;\n    writeProc(handle, (char *) &c, 1);\n    c = LSB(top);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(top);\n    writeProc(handle, (char *) &c, 1);\n    c = LSB(left);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(left);\n    writeProc(handle, (char *) &c, 1);\n\n    c = LSB(width);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(width);\n    writeProc(handle, (char *) &c, 1);\n\n    c = LSB(height);\n    writeProc(handle, (char *) &c, 1);\n    c = MSB(height);\n    writeProc(handle, (char *) &c, 1);\n\n    c = 0;\n    writeProc(handle, (char *) &c, 1);\n    c = resolution;\n    writeProc(handle, (char *) &c, 1);\n\n    state.ssize = state.rsize = blockPtr->width;\n    state.csize = blockPtr->height;\n    Compress(resolution+1, handle, writeProc, ReadValue, &state);\n\n    c = 0;\n    writeProc(handle, (char *) &c, 1);\n    /*\n     * Check for metadata keys to add to file\n     */\n    if (NULL != metadataInObj) {\n\tTcl_Obj *itemData;\n\n\t/*\n\t * Check and code comment block\n\t */\n\n\tif (TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj,\n\t\tTcl_NewStringObj(\"comment\",-1),\n\t\t&itemData)) {\n\t    return TCL_ERROR;\n\t}\n\tif (itemData != NULL) {\n\t    Tcl_Size length;\n\t    unsigned char *comment;\n\t    comment = Tcl_GetByteArrayFromObj(itemData, &length);\n\t    if (length > 0) {\n\t\t/* write comment header */\n\t\twriteProc(handle, (char *) \"\\x21\\xfe\", 2);\n\t\t/* write comment blocks */\n\t\tfor (;length > 0;) {\n\t\t    int blockLength;\n\t\t    unsigned char blockLengthChar;\n\t\t    if (length > 255) {\n\t\t\tlength -=255;\n\t\t\tblockLength = 255;\n\t\t    } else {\n\t\t\tblockLength = length;\n\t\t\tlength = 0;\n\t\t    }\n\t\t    blockLengthChar = (unsigned char) blockLength;\n\t\t    writeProc(handle, (char *) &blockLengthChar, 1);\n\t\t    writeProc(handle, (char *) comment, blockLength);\n\t\t    comment += blockLength;\n\t\t}\n\t\t/* Block terminator */\n\t\tc = 0;\n\t\twriteProc(handle, (char *) &c, 1);\n\t    }\n\t}\n    }\n    c = GIF_TERMINATOR;\n    writeProc(handle, (char *) &c, 1);\n\n    return TCL_OK;\n}\n\f\nstatic int\nColorNumber(\n    GifWriterState *statePtr,\n    int red, int green, int blue)\n{\n    int x = (statePtr->alphaOffset != 0);\n\n    for (; x <= MAXCOLORMAPSIZE; x++) {\n\tif ((statePtr->mapa[x][CM_RED] == red) &&\n\t\t(statePtr->mapa[x][CM_GREEN] == green) &&\n\t\t(statePtr->mapa[x][CM_BLUE] == blue)) {\n\t    return x;\n\t}\n    }\n    return -1;\n}\n\f\nstatic int\nIsNewColor(\n    GifWriterState *statePtr,\n    int red, int green, int blue)\n{\n    int x = (statePtr->alphaOffset != 0);\n\n    for (; x<=statePtr->num ; x++) {\n\tif ((statePtr->mapa[x][CM_RED] == red) &&\n\t\t(statePtr->mapa[x][CM_GREEN] == green) &&\n\t\t(statePtr->mapa[x][CM_BLUE] == blue)) {\n\t    return 0;\n\t}\n    }\n    return 1;\n}\n\f\nstatic void\nSaveMap(\n    GifWriterState *statePtr,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    unsigned char *colores;\n    int x, y;\n    unsigned char red, green, blue;\n\n    if (statePtr->alphaOffset) {\n\tstatePtr->num = 0;\n\tstatePtr->mapa[0][CM_RED] = DEFAULT_BACKGROUND_VALUE;\n\tstatePtr->mapa[0][CM_GREEN] = DEFAULT_BACKGROUND_VALUE;\n\tstatePtr->mapa[0][CM_BLUE] = DEFAULT_BACKGROUND_VALUE;\n    } else {\n\tstatePtr->num = -1;\n    }\n\n    for (y=0 ; y<blockPtr->height ; y++) {\n\tcolores = blockPtr->pixelPtr + blockPtr->offset[0] + y*blockPtr->pitch;\n\tfor (x=0 ; x<blockPtr->width ; x++) {\n\t    if (!statePtr->alphaOffset || colores[statePtr->alphaOffset]!=0) {\n\t\tred = colores[0];\n\t\tgreen = colores[statePtr->greenOffset];\n\t\tblue = colores[statePtr->blueOffset];\n\t\tif (IsNewColor(statePtr, red, green, blue)) {\n\t\t    statePtr->num++;\n\t\t    if (statePtr->num >= MAXCOLORMAPSIZE) {\n\t\t\treturn;\n\t\t    }\n\t\t    statePtr->mapa[statePtr->num][CM_RED] = red;\n\t\t    statePtr->mapa[statePtr->num][CM_GREEN] = green;\n\t\t    statePtr->mapa[statePtr->num][CM_BLUE] = blue;\n\t\t}\n\t    }\n\t    colores += statePtr->pixelSize;\n\t}\n    }\n}\n\f\nstatic int\nReadValue(\n    GifWriterState *statePtr)\n{\n    unsigned int col;\n\n    if (statePtr->csize == 0) {\n\treturn EOF;\n    }\n    if (statePtr->alphaOffset\n\t    && (statePtr->pixelOffset[statePtr->alphaOffset]==0)) {\n\tcol = 0;\n    } else {\n\tcol = ColorNumber(statePtr, statePtr->pixelOffset[0],\n\t\tstatePtr->pixelOffset[statePtr->greenOffset],\n\t\tstatePtr->pixelOffset[statePtr->blueOffset]);\n    }\n    statePtr->pixelOffset += statePtr->pixelSize;\n    if (--statePtr->ssize <= 0) {\n\tstatePtr->ssize = statePtr->rsize;\n\tstatePtr->csize--;\n\tstatePtr->pixelOffset += statePtr->pixelPitch\n\t\t- (statePtr->rsize * statePtr->pixelSize);\n    }\n\n    return col;\n}\n\f\n/*\n * GIF Image compression - modified 'Compress'\n *\n * Based on: compress.c - File compression ala IEEE Computer, June 1984.\n *\n * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)\n *              Jim McKie               (decvax!mcvax!jim)\n *              Steve Davies            (decvax!vax135!petsd!peora!srd)\n *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)\n *              James A. Woods          (decvax!ihnp4!ames!jaw)\n *              Joe Orost               (decvax!vax135!petsd!joe)\n */\n\f\nstatic void\nCompress(\n    int initialBits,\n    void *handle,\n    WriteBytesFunc *writeProc,\n    ifunptr readValue,\n    GifWriterState *statePtr)\n{\n    long fcode, ent, disp, hSize, i = 0;\n    int c, hshift;\n    GIFState_t state;\n\n    memset(&state, 0, sizeof(state));\n\n    /*\n     * Set up the globals:  initialBits - initial number of bits\n     *\t\t\t    outChannel\t- pointer to output file\n     */\n\n    state.initialBits = initialBits;\n    state.destination = handle;\n    state.writeProc = writeProc;\n\n    /*\n     * Set up the necessary values.\n     */\n\n    state.offset = 0;\n    state.hSize = HSIZE;\n    state.outCount = 0;\n    state.clearFlag = false;\n    state.inCount = 1;\n    state.maxCode = MAXCODE(state.numBits = state.initialBits);\n    state.clearCode = 1 << (initialBits - 1);\n    state.eofCode = state.clearCode + 1;\n    state.freeEntry = state.clearCode + 2;\n    CharInit(&state);\n\n    ent = readValue(statePtr);\n\n    hshift = 0;\n    for (fcode = (long) state.hSize;  fcode < 65536L;  fcode *= 2L) {\n\thshift++;\n    }\n    hshift = 8 - hshift;\t\t/* Set hash code range bound */\n\n    hSize = state.hSize;\n    ClearHashTable(&state, (int) hSize); /* Clear hash table */\n\n    Output(&state, (long) state.clearCode);\n\n    while (U(c = readValue(statePtr)) != U(EOF)) {\n\tstate.inCount++;\n\n\tfcode = (long) (((long) c << GIFBITS) + ent);\n\ti = ((long)c << hshift) ^ ent;\t/* XOR hashing */\n\n\tif (state.hashTable[i] == fcode) {\n\t    ent = state.codeTable[i];\n\t    continue;\n\t} else if ((long) state.hashTable[i] < 0) {\t/* Empty slot */\n\t    goto nomatch;\n\t}\n\n\tdisp = hSize - i;\t\t/* Secondary hash (after G. Knott) */\n\tif (i == 0) {\n\t    disp = 1;\n\t}\n\n    probe:\n\tif ((i -= disp) < 0) {\n\t    i += hSize;\n\t}\n\n\tif (state.hashTable[i] == fcode) {\n\t    ent = state.codeTable[i];\n\t    continue;\n\t}\n\tif ((long) state.hashTable[i] > 0) {\n\t    goto probe;\n\t}\n\n    nomatch:\n\tOutput(&state, (long) ent);\n\tstate.outCount++;\n\tent = c;\n\tif (U(state.freeEntry) < U((long)1 << GIFBITS)) {\n\t    state.codeTable[i] = state.freeEntry++; /* code -> hashtable */\n\t    state.hashTable[i] = fcode;\n\t} else {\n\t    ClearForBlock(&state);\n\t}\n    }\n\n    /*\n     * Put out the final code.\n     */\n\n    Output(&state, (long) ent);\n    state.outCount++;\n    Output(&state, (long) state.eofCode);\n}\n\f\n/*****************************************************************\n * Output --\n *\tOutput the given code.\n *\n * Inputs:\n *\tcode:\tA numBits-bit integer. If == -1, then EOF. This assumes that\n *\t\tnumBits =< (long) wordsize - 1.\n * Outputs:\n *\tOutputs code to the file.\n * Assumptions:\n *\tChars are 8 bits long.\n * Algorithm:\n *\tMaintain a GIFBITS character long buffer (so that 8 codes will fit in\n *\tit exactly). Use the VAX insv instruction to insert each code in turn.\n *\tWhen the buffer fills up empty it and start over.\n */\n\nstatic void\nOutput(\n    GIFState_t *statePtr,\n    long code)\n{\n    static const unsigned long masks[] = {\n\t0x0000,\n\t0x0001, 0x0003, 0x0007, 0x000F,\n\t0x001F, 0x003F, 0x007F, 0x00FF,\n\t0x01FF, 0x03FF, 0x07FF, 0x0FFF,\n\t0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF\n    };\n\n    statePtr->currentAccumulated &= masks[statePtr->currentBits];\n    if (statePtr->currentBits > 0) {\n\tstatePtr->currentAccumulated |= ((long) code << statePtr->currentBits);\n    } else {\n\tstatePtr->currentAccumulated = code;\n    }\n    statePtr->currentBits += statePtr->numBits;\n\n    while (statePtr->currentBits >= 8) {\n\tCharOut(statePtr, (unsigned) (statePtr->currentAccumulated & 0xff));\n\tstatePtr->currentAccumulated >>= 8;\n\tstatePtr->currentBits -= 8;\n    }\n\n    /*\n     * If the next entry is going to be too big for the code size, then\n     * increase it, if possible.\n     */\n\n    if ((statePtr->freeEntry > statePtr->maxCode) || statePtr->clearFlag) {\n\tif (statePtr->clearFlag) {\n\t    statePtr->maxCode = MAXCODE(\n\t\t    statePtr->numBits = statePtr->initialBits);\n\t    statePtr->clearFlag = false;\n\t} else {\n\t    statePtr->numBits++;\n\t    if (statePtr->numBits == GIFBITS) {\n\t\tstatePtr->maxCode = (long)1 << GIFBITS;\n\t    } else {\n\t\tstatePtr->maxCode = MAXCODE(statePtr->numBits);\n\t    }\n\t}\n    }\n\n    if (code == statePtr->eofCode) {\n\t/*\n\t * At EOF, write the rest of the buffer.\n\t */\n\n\twhile (statePtr->currentBits > 0) {\n\t    CharOut(statePtr,\n\t\t    (unsigned) (statePtr->currentAccumulated & 0xff));\n\t    statePtr->currentAccumulated >>= 8;\n\t    statePtr->currentBits -= 8;\n\t}\n\tFlushChar(statePtr);\n    }\n}\n\f\n/*\n * Clear out the hash table\n */\n\nstatic void\nClearForBlock(\t\t\t/* Table clear for block compress. */\n    GIFState_t *statePtr)\n{\n    ClearHashTable(statePtr, (int) statePtr->hSize);\n    statePtr->freeEntry = statePtr->clearCode + 2;\n    statePtr->clearFlag = true;\n\n    Output(statePtr, (long) statePtr->clearCode);\n}\n\f\nstatic void\nClearHashTable(\t\t\t/* Reset code table. */\n    GIFState_t *statePtr,\n    int hSize)\n{\n    int *hashTablePtr = statePtr->hashTable + hSize;\n    long i;\n    long m1 = -1;\n\n    i = hSize - 16;\n    do {\t\t\t/* might use Sys V memset(3) here */\n\t*(hashTablePtr-16) = m1;\n\t*(hashTablePtr-15) = m1;\n\t*(hashTablePtr-14) = m1;\n\t*(hashTablePtr-13) = m1;\n\t*(hashTablePtr-12) = m1;\n\t*(hashTablePtr-11) = m1;\n\t*(hashTablePtr-10) = m1;\n\t*(hashTablePtr-9) = m1;\n\t*(hashTablePtr-8) = m1;\n\t*(hashTablePtr-7) = m1;\n\t*(hashTablePtr-6) = m1;\n\t*(hashTablePtr-5) = m1;\n\t*(hashTablePtr-4) = m1;\n\t*(hashTablePtr-3) = m1;\n\t*(hashTablePtr-2) = m1;\n\t*(hashTablePtr-1) = m1;\n\thashTablePtr -= 16;\n    } while ((i -= 16) >= 0);\n\n    for (i += 16; i > 0; i--) {\n\t*--hashTablePtr = m1;\n    }\n}\n\f\n/*\n *****************************************************************************\n *\n * GIF Specific routines\n *\n *****************************************************************************\n */\n\n/*\n * Set up the 'byte output' routine\n */\n\nstatic void\nCharInit(\n    GIFState_t *statePtr)\n{\n    statePtr->accumulatedByteCount = 0;\n    statePtr->currentAccumulated = 0;\n    statePtr->currentBits = 0;\n}\n\f\n/*\n * Add a character to the end of the current packet, and if it is 254\n * characters, flush the packet to disk.\n */\n\nstatic void\nCharOut(\n    GIFState_t *statePtr,\n    int c)\n{\n    statePtr->packetAccumulator[statePtr->accumulatedByteCount++] = c;\n    if (statePtr->accumulatedByteCount >= 254) {\n\tFlushChar(statePtr);\n    }\n}\n\f\n/*\n * Flush the packet to disk, and reset the accumulator\n */\n\nstatic void\nFlushChar(\n    GIFState_t *statePtr)\n{\n    unsigned char c;\n\n    if (statePtr->accumulatedByteCount > 0) {\n\tc = statePtr->accumulatedByteCount;\n\tstatePtr->writeProc(statePtr->destination, (const char *) &c, 1);\n\tstatePtr->writeProc(statePtr->destination,\n\t\t(const char *) statePtr->packetAccumulator,\n\t\tstatePtr->accumulatedByteCount);\n\tstatePtr->accumulatedByteCount = 0;\n    }\n}\n\n/* The End */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgListFormat.c",
    "content": "/*\n * tkImgListFormat.c --\n *\n *      Implements the default image data format. I.e. the format used for\n *      [imageName data] and [imageName put] if no other format is specified.\n *\n *      The default format consits of a list of scan lines (rows) with each\n *      list element being itself a list of pixels (or columns). For details,\n *      see the manpage photo.n\n *\n *      This image format cannot read/write files, it is meant for string\n *      data only.\n *\n *\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2002-2003 Donal K. Fellows\n * Copyright © 2003 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Authors:\n *      Paul Mackerras (paulus@cs.anu.edu.au),\n *              Department of Computer Science,\n *              Australian National University.\n *\n *      Simon Bachmann (simonbachmann@bluewin.ch)\n */\n\n\n#include \"tkImgPhoto.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Message to generate when an attempt to allocate memory for an image fails.\n */\n\n#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \\\n\t\"not enough free memory for image buffer\"\n\n\n/*\n * Color name length limit: do not attempt to parse as color strings that are\n * longer than this limit\n */\n\n#define TK_PHOTO_MAX_COLOR_LENGTH 99\n\n/*\n * Symbols for the different formats of a color string.\n */\n\nenum ColorFormatType {\n    COLORFORMAT_TKCOLOR,\n    COLORFORMAT_EMPTYSTRING,\n    COLORFORMAT_LIST,\n    COLORFORMAT_RGB1,\n    COLORFORMAT_RGB2,\n    COLORFORMAT_RGBA1,\n    COLORFORMAT_RGBA2\n};\n\n/*\n * Names for the color format types above.\n * Order must match the one in enum ColorFormatType\n */\n\nstatic const char *const colorFormatNames[] = {\n    \"tkcolor\",\n    \"emptystring\",\n    \"list\",\n    \"rgb-short\",\n    \"rgb\",\n    \"rgba-short\",\n    \"rgba\",\n    NULL\n};\n\n/*\n * The following data structure is used to return information from\n * ParseFormatOptions:\n */\n\nstruct FormatOptions {\n    int options;         /* Individual bits indicate which options were\n\t\t\t  * specified - see below. */\n    Tcl_Obj *formatName; /* Name specified without an option. */\n    enum ColorFormatType colorFormat;\n\t\t\t /* The color format type given with the\n\t\t\t  * -colorformat option */\n};\n\n/*\n * Bit definitions for use with ParseFormatOptions: each bit is set in the\n * allowedOptions parameter on a call to ParseFormatOptions if that option\n * is allowed for the current photo image subcommand. On return, the bit is\n * set in the options field of the FormatOptions structure if that option\n * was specified.\n *\n * OPT_COLORFORMAT:         Set if -alpha option allowed/specified.\n */\n\n#define OPT_COLORFORMAT     1\n\n/*\n * List of format option names. The order here must match the order of\n * declarations of the FMT_OPT_* constants above.\n */\n\nstatic const char *const formatOptionNames[] = {\n    \"-colorformat\",\n    NULL\n};\n\n/*\n * Forward declarations\n */\n\nstatic int      ParseFormatOptions(Tcl_Interp *interp, int allowedOptions,\n\t\t    Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Size *indexPtr,\n\t\t    struct FormatOptions *optPtr);\nstatic Tcl_Obj  *GetBadOptMsg(const char *badValue, int allowedOpts);\nstatic int      StringMatchDef(Tcl_Obj *data, Tcl_Obj *formatString,\n\t\t    int *widthPtr, int *heightPtr, Tcl_Interp *interp);\nstatic int      StringReadDef(Tcl_Interp *interp, Tcl_Obj *data,\n\t\t    Tcl_Obj *formatString, Tk_PhotoHandle imageHandle,\n\t\t    int destX, int destY, int width, int height,\n\t\t    int srcX, int srcY);\nstatic int      StringWriteDef(Tcl_Interp *interp,\n\t\t    Tcl_Obj *formatString,\n\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int      ParseColor(Tcl_Interp *interp, Tcl_Obj *specObj,\n\t\t    Display *display, Colormap colormap, unsigned char *redPtr,\n\t\t    unsigned char *greenPtr, unsigned char *bluePtr,\n\t\t    unsigned char *alphaPtr);\nstatic int      ParseColorAsList(const char *colorString, unsigned char *redPtr,\n\t\t    unsigned char *greenPtr, unsigned char *bluePtr,\n\t\t    unsigned char *alphaPtr);\nstatic int      ParseColorAsHex(Tcl_Interp *interp, const char *colorString,\n\t\t    int colorStrLen, Display *display, Colormap colormap,\n\t\t    unsigned char *redPtr, unsigned char *greenPtr,\n\t\t    unsigned char *bluePtr, unsigned char *alphaPtr);\nstatic int      ParseColorAsStandard(Tcl_Interp *interp,\n\t\t    const char *colorString, int colorStrLen,\n\t\t    Display *display, Colormap colormap,\n\t\t    unsigned char *redPtr, unsigned char *greenPtr,\n\t\t    unsigned char *bluePtr, unsigned char *alphaPtr);\n\n/*\n * The format record for the default image handler\n */\n\nTk_PhotoImageFormat tkImgFmtDefault = {\n    \"default\",      /* name */\n    NULL,           /* fileMatchProc: format doesn't support file ops */\n    StringMatchDef, /* stringMatchProc */\n    NULL,           /* fileReadProc: format doesn't support file read */\n    StringReadDef,  /* stringReadProc */\n    NULL,           /* fileWriteProc: format doesn't support file write */\n    StringWriteDef, /* stringWriteProc */\n    NULL            /* nextPtr */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseFormatOptions --\n *\n *      Parse the options passed to the image format handler.\n *\n * Results:\n *      On success, the structure pointed to by optPtr is filled with the\n *      values passed or with the defaults and TCL_OK returned.\n *      If an error occurs, leaves an error message in interp and returns\n *      TCL_ERROR.\n *\n * Side effects:\n *      The value in *indexPtr is updated to the index of the fist\n *      element in argv[] that does not look like an option/value, or to\n *      objc if parsing reached the end of argv[].\n *\n *----------------------------------------------------------------------\n */\nstatic int\nParseFormatOptions(\n    Tcl_Interp *interp,               /* For error messages */\n    int allowedOptions,               /* Bitfield specifying which options are\n\t\t\t\t       * to be considered allowed */\n    Tcl_Size objc,                         /* Number of elements in argv[] */\n    Tcl_Obj *const objv[],            /* The arguments to parse */\n    Tcl_Size *indexPtr,                    /* Index giving the first element to\n\t\t\t\t       * parse. The value is updated to the\n\t\t\t\t       * index where parsing ended */\n    struct FormatOptions *optPtr)     /* Parsed option values are written to\n\t\t\t\t       * this struct */\n\n{\n    Tcl_Size optIndex, index;\n    bool first = true;\n    int typeIndex;\n    const char *option;\n\n    /*\n     * Fill in default values\n     */\n    optPtr->options = 0;\n    optPtr->formatName = NULL;\n    optPtr->colorFormat = COLORFORMAT_RGB2;\n    for (index = *indexPtr; index < objc; *indexPtr = ++index) {\n\tint optionExists;\n\n\t/*\n\t * The first value can be the format handler's name. It goes to\n\t * optPtr->name.\n\t */\n\toption = Tcl_GetString(objv[index]);\n\tif (option[0] != '-') {\n\t    if (first) {\n\t\toptPtr->formatName = objv[index];\n\t\tfirst = false;\n\t\tcontinue;\n\t    } else {\n\t\tbreak;\n\t    }\n\t}\n\tfirst = false;\n\n\t/*\n\t * Check if option is known and allowed\n\t */\n\n\toptionExists = 1;\n\tif (Tcl_GetIndexFromObj(NULL, objv[index], formatOptionNames,\n\t\t\"format option\", 0, &optIndex) != TCL_OK) {\n\t    optionExists = 0;\n\t}\n\tif (!optionExists || !((1 << optIndex) & allowedOptions)) {\n\t    Tcl_SetObjResult(interp, GetBadOptMsg(Tcl_GetString(objv[index]),\n\t\t    allowedOptions));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Option-specific checks\n\t */\n\n\tswitch (1 << optIndex) {\n\tcase OPT_COLORFORMAT:\n\t    *indexPtr = ++index;\n\t    if (index >= objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"the \\\"%s\\\" option \"\n\t\t\t\"requires a value\", Tcl_GetString(objv[index - 1])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"MISSING_VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (Tcl_GetIndexFromObj(NULL, objv[index], colorFormatNames, \"\",\n\t\t    TCL_EXACT, &typeIndex) != TCL_OK\n\t\t    || (typeIndex != COLORFORMAT_LIST\n\t\t    && typeIndex != COLORFORMAT_RGB2\n\t\t    && typeIndex != COLORFORMAT_RGBA2) ) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad color format \"\n\t\t\t\"\\\"%s\\\": must be rgb, rgba, or list\",\n\t\t\tTcl_GetString(objv[index])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"BAD_COLOR_FORMAT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    optPtr->colorFormat = (enum ColorFormatType)typeIndex;\n\t    break;\n\tdefault:\n\t    Tcl_Panic(\"ParseFormatOptions: unexpected switch fallthrough\");\n\t}\n\n\t/*\n\t * Add option to bitfield in optPtr\n\t */\n\toptPtr->options |= (1 << optIndex);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n *  GetBadOptMsg --\n *\n *      Build a Tcl_Obj containing an error message in the form \"bad option\n *      \"xx\": must be y, or z\", based on the bits set in allowedOpts.\n *\n * Results:\n *      A Tcl Object containig the error message.\n *\n * Side effects:\n *      None\n *----------------------------------------------------------------------\n */\nstatic Tcl_Obj *\nGetBadOptMsg(\n    const char *badValue,   /* the erroneous option */\n    int allowedOpts)        /* bitfield specifying the allowed options */\n{\n    int i, bit;\n    Tcl_Obj *resObj = Tcl_ObjPrintf(\"bad format option \\\"%s\\\": \", badValue);\n\n    if (allowedOpts == 0) {\n\tTcl_AppendToObj(resObj, \"no options allowed\", TCL_INDEX_NONE);\n    } else {\n\tTcl_AppendToObj(resObj, \"must be \", TCL_INDEX_NONE);\n\tbit = 1;\n\tfor (i = 0; formatOptionNames[i] != NULL; i++) {\n\t    if (allowedOpts & bit) {\n\t\tif (allowedOpts & (bit -1)) {\n\t\t    /*\n\t\t     * not the first option\n\t\t     */\n\t\t    if (allowedOpts & ~((bit << 1) - 1)) {\n\t\t\t/*\n\t\t\t * not the last option\n\t\t\t */\n\t\t\tTcl_AppendToObj(resObj, \", \", TCL_INDEX_NONE);\n\t\t    } else {\n\t\t\tTcl_AppendToObj(resObj, \", or \", TCL_INDEX_NONE);\n\t\t    }\n\t\t}\n\t\tTcl_AppendToObj(resObj, formatOptionNames[i], TCL_INDEX_NONE);\n\t    }\n\t    bit <<=1;\n\t}\n    }\n    return resObj;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringMatchDef --\n *\n *      Default string match function. Test if image data in string form\n *      appears to be in the default list-of-list-of-pixel-data format\n *      accepted by the \"<img> put\" command.\n *\n * Results:\n *      If thte data is in the default format, writes the size of the image\n *      to widthPtr and heightPtr and returns 1. Otherwise, leaves an error\n *      message in interp (if not NULL) and returns 0.\n *      Note that this function does not parse all data points. A return\n *      value of 1 does not guarantee that the data can be read without\n *      errors.\n *\n * Side effects:\n *      None\n *----------------------------------------------------------------------\n */\nstatic int\nStringMatchDef(\n    Tcl_Obj *data,          /* The data to check */\n    TCL_UNUSED(Tcl_Obj *),  /* Value of the -format option, not used here */\n    int *widthPtr,          /* Width of image is written to this location */\n    int *heightPtr,         /* Height of image is written to this location */\n    Tcl_Interp *interp)     /* Error messages are left in this interpreter */\n{\n    Tcl_Size y, rowCount, colCount, curColCount;\n    unsigned char dummy;\n    Tcl_Obj **rowListPtr, *pixelData;\n\n    /*\n     * See if data can be parsed as a list, if every element is itself a valid\n     * list and all sublists have the same length.\n     */\n\n    if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr)\n\t    != TCL_OK) {\n\treturn 0;\n    }\n    if (rowCount == 0) {\n\t/*\n\t * empty list is valid data\n\t */\n\n\t*widthPtr = 0;\n\t*heightPtr = 0;\n\treturn 1;\n    }\n    colCount = -1;\n    for (y = 0; y < rowCount; y++) {\n\tif (Tcl_ListObjLength(interp, rowListPtr[y], &curColCount) != TCL_OK) {\n\t    return 0;\n\t}\n\tif (colCount < 0) {\n\t    colCount = curColCount;\n\t} else if (curColCount != colCount) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"invalid row # %\" TCL_SIZE_MODIFIER \"d: \"\n\t\t\t\"all rows must have the same number of elements\", y));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"INVALID_DATA\", (char *)NULL);\n\t    }\n\t    return 0;\n\t}\n    }\n\n    /*\n     * Data in base64 encoding (or even binary data), might actually pass\n     * these tests. To avoid parsing it as list of lists format, check one\n     * pixel for validity.\n     */\n    if (Tcl_ListObjIndex(interp, rowListPtr[0], 0, &pixelData) != TCL_OK) {\n\treturn 0;\n    }\n    (void)Tcl_GetString(pixelData);\n    if (pixelData->length > TK_PHOTO_MAX_COLOR_LENGTH) {\n\treturn 0;\n    }\n    if (ParseColor(interp, pixelData, Tk_Display(Tk_MainWindow(interp)),\n\t    Tk_Colormap(Tk_MainWindow(interp)), &dummy, &dummy, &dummy, &dummy)\n\t    != TCL_OK) {\n\treturn 0;\n    }\n\n    /*\n     * Looks like we have valid data for this format.\n     * We do not check any pixel values - that's the job of ImgStringRead()\n     */\n\n    *widthPtr = colCount;\n    *heightPtr = rowCount;\n\n    return 1;\n\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * StringReadDef --\n *\n *      String read function for default format. (see manpage for details on\n *      the format).\n *\n * Results:\n *      A standard Tcl result.\n *\n * Side effects:\n *      If the data has valid format, write it to the image identified by\n *      imageHandle.\n *      If the image data cannot be parsed, an error message is left in\n *      interp.\n *\n *----------------------------------------------------------------------\n*/\n\nstatic int\nStringReadDef(\n    Tcl_Interp *interp,         /* leave error messages here */\n    Tcl_Obj *data,              /* the data to parse */\n    Tcl_Obj *formatString,      /* value of the -format option */\n    Tk_PhotoHandle imageHandle, /* write data to this image */\n    int destX, int destY,       /* start writing data at this point\n\t\t\t\t * in destination image*/\n    int width, int height,      /* dimensions of area to write to */\n    int srcX, int srcY)         /* start reading source data at these\n\t\t\t\t * coordinates */\n{\n    Tcl_Obj **rowListPtr, **colListPtr;\n    Tcl_Obj **objv;\n    Tcl_Size objc, rowCount, colCount, curColCount;\n    unsigned char *curPixelPtr;\n    int x, y;\n    Tk_PhotoImageBlock srcBlock;\n    Display *display;\n    Colormap colormap;\n    struct FormatOptions opts;\n    Tcl_Size optIndex;\n\n    /*\n     * Parse format suboptions\n     * We don't use any format suboptions, but we still need to provide useful\n     * error messages if suboptions were specified.\n     */\n\n    memset(&opts, 0, sizeof(opts));\n    if (formatString != NULL) {\n\tif (Tcl_ListObjGetElements(interp, formatString, &objc, &objv)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\toptIndex = 0;\n\tif (ParseFormatOptions(interp, 0, objc, objv, &optIndex, &opts)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (optIndex < objc) {\n\t    Tcl_SetObjResult(interp,\n\t\t    GetBadOptMsg(Tcl_GetString(objv[optIndex]), 0));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Check input data\n     */\n\n    if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr)\n\t    != TCL_OK ) {\n\treturn TCL_ERROR;\n    }\n    if ( rowCount > 0 && Tcl_ListObjLength(interp, rowListPtr[0], &colCount)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (width <= 0 || height <= 0 || rowCount == 0 || colCount == 0) {\n\t/*\n\t * No changes with zero sized input or zero sized output region\n\t */\n\n\treturn TCL_OK;\n    }\n    if (srcX < 0 || srcY < 0 || srcX >= rowCount || srcY >= colCount) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"source coordinates out of range\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"COORDINATES\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Memory allocation overflow protection.\n     * May not be able to trigger/ demo / test this.\n     */\n\n    if (colCount > (int)(UINT_MAX / 4 / rowCount)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"photo image dimensions exceed Tcl memory limits\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\"OVERFLOW\", (char *)NULL);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Read data and put it to imageHandle\n     */\n\n    srcBlock.width = colCount - srcX;\n    srcBlock.height = rowCount - srcY;\n    srcBlock.pixelSize = 4;\n    srcBlock.pitch = srcBlock.width * 4;\n    srcBlock.offset[0] = 0;\n    srcBlock.offset[1] = 1;\n    srcBlock.offset[2] = 2;\n    srcBlock.offset[3] = 3;\n    srcBlock.pixelPtr = (unsigned char *)Tcl_AttemptAlloc(srcBlock.pitch * srcBlock.height);\n    if (srcBlock.pixelPtr == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(TK_PHOTO_ALLOC_FAILURE_MESSAGE));\n\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    curPixelPtr = srcBlock.pixelPtr;\n    display = Tk_Display(Tk_MainWindow(interp));\n    colormap = Tk_Colormap(Tk_MainWindow(interp));\n    for (y = srcY; y < rowCount; y++) {\n\t/*\n\t * We don't test the length of row, as that's been done in\n\t * ImgStringMatch()\n\t */\n\n\tif (Tcl_ListObjGetElements(interp, rowListPtr[y], &curColCount,\n\t\t&colListPtr) != TCL_OK) {\n\t    goto errorExit;\n\t}\n\tfor (x = srcX; x < colCount; x++) {\n\t    if (ParseColor(interp, colListPtr[x], display, colormap,\n\t\t    curPixelPtr, curPixelPtr + 1, curPixelPtr + 2,\n\t\t    curPixelPtr + 3) != TCL_OK) {\n\t\tgoto errorExit;\n\t    }\n\t    curPixelPtr += 4;\n\t}\n    }\n\n    /*\n     * Write image data to destHandle\n     */\n    if (Tk_PhotoPutBlock(interp, imageHandle, &srcBlock, destX, destY,\n\t    width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {\n\tgoto errorExit;\n    }\n\n    Tcl_Free(srcBlock.pixelPtr);\n\n    return TCL_OK;\n\n  errorExit:\n    Tcl_Free(srcBlock.pixelPtr);\n\n    return TCL_ERROR;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * StringWriteDef --\n *\n *      String write function for default image data format. See the user\n *      documentation for details.\n *\n * Results:\n *      The converted data is set as the result of interp. Returns a standard\n *      Tcl result.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringWriteDef(\n    Tcl_Interp *interp,                 /* For the result and errors */\n    Tcl_Obj *formatString,              /* The value of the -format option */\n    Tk_PhotoImageBlock *blockPtr)       /* The image data to convert */\n{\n    int greenOffset, blueOffset, alphaOffset, hasAlpha;\n    Tcl_Obj *result, **objv = NULL;\n    Tcl_Size objc, allowedOpts, optIndex;\n    struct FormatOptions opts;\n\n    /*\n     * Parse format suboptions\n     */\n    if (Tcl_ListObjGetElements(interp, formatString, &objc, &objv)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    allowedOpts = OPT_COLORFORMAT;\n    optIndex = 0;\n    if (ParseFormatOptions(interp, allowedOpts, objc, objv, &optIndex, &opts)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (optIndex < objc) {\n\tTcl_SetObjResult(interp,\n\t\tGetBadOptMsg(Tcl_GetString(objv[optIndex]), allowedOpts));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];\n    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];\n\n    /*\n     * A negative alpha offset signals that the image is fully opaque.\n     * That's not really documented anywhere, but it's the way it is!\n     */\n\n    if (blockPtr->offset[3] < 0) {\n\thasAlpha = 0;\n\talphaOffset = 0;\n    } else {\n\thasAlpha = 1;\n\talphaOffset = blockPtr->offset[3] - blockPtr->offset[0];\n    }\n\n    if ((blockPtr->width > 0) && (blockPtr->height > 0)) {\n\tint row, col;\n\tTcl_DString data, line;\n\tchar colorBuf[11];\n\tunsigned char *pixelPtr;\n\tunsigned char alphaVal = 255;\n\n\tTcl_DStringInit(&data);\n\tfor (row=0; row<blockPtr->height; row++) {\n\t    pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0]\n\t\t    + row * blockPtr->pitch;\n\t    Tcl_DStringInit(&line);\n\t    for (col=0; col<blockPtr->width; col++) {\n\t\tif (hasAlpha) {\n\t\t    alphaVal = pixelPtr[alphaOffset];\n\t\t}\n\n\t\t/*\n\t\t * We don't build lines as a list for #RGBA and #RGB. Since\n\t\t * these color formats look like comments, the first element\n\t\t * of the list would get quoted with an additional {} .\n\t\t * While this is not a problem if the data is used as\n\t\t * a list, it would cause problems if someone decides to parse\n\t\t * it as a string (and it looks kinda strange)\n\t\t */\n\n\t\tswitch (opts.colorFormat) {\n\t\tcase COLORFORMAT_RGB2:\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"#%02x%02x%02x \",  pixelPtr[0],\n\t\t\t    pixelPtr[greenOffset], pixelPtr[blueOffset]);\n\t\t    Tcl_DStringAppend(&line, colorBuf, TCL_INDEX_NONE);\n\t\t    break;\n\t\tcase COLORFORMAT_RGBA2:\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"#%02x%02x%02x%02x \",\n\t\t\t    pixelPtr[0], pixelPtr[greenOffset],\n\t\t\t    pixelPtr[blueOffset], alphaVal);\n\t\t    Tcl_DStringAppend(&line, colorBuf, TCL_INDEX_NONE);\n\t\t    break;\n\t\tcase COLORFORMAT_LIST:\n\t\t    Tcl_DStringStartSublist(&line);\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"%d\", pixelPtr[0]);\n\t\t    Tcl_DStringAppendElement(&line, colorBuf);\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"%d\", pixelPtr[greenOffset]);\n\t\t    Tcl_DStringAppendElement(&line, colorBuf);\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"%d\", pixelPtr[blueOffset]);\n\t\t    Tcl_DStringAppendElement(&line, colorBuf);\n\t\t    snprintf(colorBuf, sizeof(colorBuf), \"%d\", alphaVal);\n\t\t    Tcl_DStringAppendElement(&line, colorBuf);\n\t\t    Tcl_DStringEndSublist(&line);\n\t\t    break;\n\t\tdefault:\n\t\t    Tcl_Panic(\"unexpected switch fallthrough\");\n\t\t}\n\t\tpixelPtr += blockPtr->pixelSize;\n\t    }\n\t    if (opts.colorFormat != COLORFORMAT_LIST) {\n\t\t/*\n\t\t * For the #XXX formats, we need to remove the last\n\t\t * whitespace.\n\t\t */\n\n\t\t*(Tcl_DStringValue(&line) + Tcl_DStringLength(&line) - 1)\n\t\t\t= '\\0';\n\t    }\n\t    Tcl_DStringAppendElement(&data, Tcl_DStringValue(&line));\n\t    Tcl_DStringFree(&line);\n\t}\n\tresult = Tcl_NewStringObj(Tcl_DStringValue(&data), TCL_INDEX_NONE);\n\tTcl_DStringFree(&data);\n    } else {\n\tresult = Tcl_NewObj();\n    }\n\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseColor --\n *\n *      This function extracts color and alpha values from a string. It\n *      understands standard Tk color formats, alpha suffixes and the color\n *      formats specific to photo images, which include alpha data.\n *\n * Results:\n *      On success, writes red, green, blue and alpha values to the\n *      corresponding pointers. If the color spec contains no alpha\n *      information, 255 is taken as transparency value.\n *      If the input cannot be parsed, leaves an error message in\n *      interp. Returns a standard Tcl result.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\nstatic int\nParseColor(\n    Tcl_Interp *interp,         /* error messages go there */\n    Tcl_Obj *specObj,           /* the color data to parse */\n    Display *display,           /* display of main window, needed to parse\n\t\t\t\t * standard Tk colors */\n    Colormap colormap,          /* colormap of current display */\n    unsigned char *redPtr,      /* the result is written to these pointers */\n    unsigned char *greenPtr,\n    unsigned char *bluePtr,\n    unsigned char *alphaPtr)\n{\n    const char *specString;\n    Tcl_Size length;\n\n    /*\n     * Find out which color format we have\n     */\n\n    specString = Tcl_GetStringFromObj(specObj, &length);\n\n    if (length == 0) {\n\t/* Empty string */\n\t*redPtr = *greenPtr = *bluePtr = *alphaPtr = 0;\n\treturn TCL_OK;\n    }\n    if (length > TK_PHOTO_MAX_COLOR_LENGTH) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"invalid color\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\"INVALID_COLOR\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (specString[0] == '#') {\n\treturn ParseColorAsHex(interp, specString, length, display,\n\t\tcolormap, redPtr, greenPtr, bluePtr, alphaPtr);\n    }\n    if (ParseColorAsList(specString,\n\t    redPtr, greenPtr, bluePtr, alphaPtr) == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Parsing the color as standard Tk color always is the last option tried\n     * because TkParseColor() is very slow with values it cannot parse.\n     */\n\n    Tcl_ResetResult(interp);\n    return ParseColorAsStandard(interp, specString, length, display,\n\t    colormap, redPtr, greenPtr, bluePtr, alphaPtr);\n\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseColorAsList --\n *\n *      This function extracts color and alpha values from a list of 3 or 4\n *      integers (the list color format).\n *\n * Results:\n *      On success, writes red, green, blue and alpha values to the\n *      corresponding pointers. If the color spec contains no alpha\n *      information, 255 is taken as transparency value.\n *      Returns a standard Tcl result.\n *\n * Side effects:\n *      None\n *\n *----------------------------------------------------------------------\n */\nstatic int\nParseColorAsList(\n    const char *colorString,    /* the color data to parse */\n    unsigned char *redPtr,      /* the result is written to these pointers */\n    unsigned char *greenPtr,\n    unsigned char *bluePtr,\n    unsigned char *alphaPtr)\n{\n    /*\n     * This is kinda ugly. The code would be certainly nicer if it\n     * used Tcl_ListObjGetElements() and Tcl_GetIntFromObj(). But with\n     * strtol() it's *much* faster.\n     */\n\n    const char *curPos;\n    int values[4];\n    int i;\n\n    curPos = colorString;\n    i = 0;\n\n    /*\n     * strtol can give false positives with a sequence of space chars.\n     * To avoid that, advance the pointer to the next non-blank char.\n     */\n\n    while(isspace(UCHAR(*curPos))) {\n\t++curPos;\n    }\n    while (i < 4 && *curPos != '\\0') {\n\tvalues[i] = strtol(curPos, (char **)&curPos, 0);\n\tif (values[i] < 0 || values[i] > 255) {\n\t    return TCL_ERROR;\n\t}\n\twhile(isspace(UCHAR(*curPos))) {\n\t    ++curPos;\n\t}\n\t++i;\n    }\n\n    if (i < 3 || *curPos != '\\0') {\n\treturn TCL_ERROR;\n    }\n    if (i < 4) {\n\tvalues[3] = 255;\n    }\n\n    *redPtr = (unsigned char) values[0];\n    *greenPtr = (unsigned char) values[1];\n    *bluePtr = (unsigned char) values[2];\n    *alphaPtr = (unsigned char) values[3];\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseColorAsHex --\n *\n *      This function extracts color and alpha values from a string\n *      starting with '#', followed by hex digits. It understands both\n *      the #RGBA form and the #RBG (with optional suffix)\n *\n * Results:\n *      On success, writes red, green, blue and alpha values to the\n *      corresponding pointers. If the color spec contains no alpha\n *      information, 255 is taken as transparency value.\n *      Returns a standard Tcl result.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\nstatic int\nParseColorAsHex(\n    Tcl_Interp *interp,         /* error messages are left here */\n    const char *colorString,    /* the color data to parse */\n    int colorStrLen,            /* length of the color string */\n    Display *display,           /* display of main window */\n    Colormap colormap,          /* colormap of current display */\n    unsigned char *redPtr,      /* the result is written to these pointers */\n    unsigned char *greenPtr,\n    unsigned char *bluePtr,\n    unsigned char *alphaPtr)\n{\n    int i;\n    unsigned long int colorValue = 0;\n\n    if (colorStrLen - 1 != 4 && colorStrLen - 1 != 8) {\n\treturn ParseColorAsStandard(interp, colorString, colorStrLen,\n\t\tdisplay, colormap, redPtr, greenPtr, bluePtr, alphaPtr);\n    }\n    for (i = 1; i < colorStrLen; i++) {\n\tif (!isxdigit(UCHAR(colorString[i]))) {\n\t    /*\n\t     * There still is a chance that this is a Tk color with\n\t     * an alpha suffix\n\t     */\n\n\t    return ParseColorAsStandard(interp, colorString, colorStrLen,\n\t\t    display, colormap, redPtr, greenPtr, bluePtr, alphaPtr);\n\t}\n    }\n\n    colorValue = strtoul(colorString + 1, NULL, 16);\n    switch (colorStrLen - 1) {\n    case 4:\n\t/* #RGBA format */\n\t*redPtr = (unsigned char) ((colorValue >> 12) * 0x11);\n\t*greenPtr = (unsigned char) (((colorValue >> 8) & 0xf) * 0x11);\n\t*bluePtr = (unsigned char) (((colorValue >> 4) & 0xf) * 0x11);\n\t*alphaPtr = (unsigned char) ((colorValue & 0xf) * 0x11);\n\treturn TCL_OK;\n    case 8:\n\t/* #RRGGBBAA format */\n\t*redPtr = (unsigned char) (colorValue >> 24);\n\t*greenPtr = (unsigned char) ((colorValue >> 16) & 0xff);\n\t*bluePtr = (unsigned char) ((colorValue >> 8) & 0xff);\n\t*alphaPtr = (unsigned char) (colorValue & 0xff);\n\treturn TCL_OK;\n    default:\n\tTcl_Panic(\"unexpected switch fallthrough\");\n    }\n\n    /* Shouldn't get here */\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseColorAsStandard --\n *\n *      This function tries to split a color string in a color and a\n *      suffix part and to extract color and alpha values from them. The\n *      color part is treated as regular Tk color.\n *\n * Results:\n *      On success, writes red, green, blue and alpha values to the\n *      corresponding pointers. If the color spec contains no alpha\n *      information, 255 is taken as transparency value.\n *      Returns a standard Tcl result.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\nstatic int\nParseColorAsStandard(\n    Tcl_Interp *interp,         /* error messages are left here */\n    const char *specString,    /* the color data to parse */\n    int specStrLen,            /* length of the color string */\n    Display *display,           /* display of main window */\n    Colormap colormap,          /* colormap of current display */\n    unsigned char *redPtr,      /* the result is written to these pointers */\n    unsigned char *greenPtr,\n    unsigned char *bluePtr,\n    unsigned char *alphaPtr)\n{\n    XColor parsedColor;\n    const char *suffixString, *colorString;\n    char colorBuffer[TK_PHOTO_MAX_COLOR_LENGTH + 1];\n    double fracAlpha;\n    unsigned int suffixAlpha = 0;\n    int i;\n\n    /*\n     * Split color data string in color and suffix parts\n     */\n\n    if ((suffixString = strrchr(specString, '@')) == NULL\n\t    && ((suffixString = strrchr(specString, '#')) == NULL\n\t\t    || suffixString == specString)) {\n\tsuffixString = specString + specStrLen;\n\tcolorString = specString;\n    } else {\n\tstrncpy(colorBuffer, specString, suffixString - specString);\n\tcolorBuffer[suffixString - specString] = '\\0';\n\tcolorString = (const char*)colorBuffer;\n    }\n\n    /*\n     * Try to parse as standard Tk color.\n     *\n     * We don't use Tk_GetColor() et al. here, as those functions\n     * might return a color that does not exactly match the given name\n     * if the colormap is full. Also, we don't really want the color to be\n     * added to the colormap.\n     */\n\n    if (TkParseColor(display, colormap, colorString, &parsedColor) == 0) {\n\t Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"invalid color name \\\"%s\\\"\", specString));\n\t Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t \"INVALID_COLOR\", (char *)NULL);\n\t return TCL_ERROR;\n    }\n\n    /*\n     * parse the Suffix\n     */\n\n    switch (suffixString[0]) {\n    case '\\0':\n\tsuffixAlpha = 255;\n\tbreak;\n    case '@':\n\tif (Tcl_GetDouble(NULL, suffixString + 1, &fracAlpha) != TCL_OK) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"invalid alpha \"\n\t\t    \"suffix \\\"%s\\\": expected floating-point value\",\n\t\t    suffixString));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t    \"INVALID COLOR\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (fracAlpha < 0 || fracAlpha > 1) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"invalid alpha suffix\"\n\t\t    \" \\\"%s\\\": value must be in the range from 0 to 1\",\n\t\t    suffixString));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t    \"INVALID_COLOR\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tsuffixAlpha = (unsigned int) floor(fracAlpha * 255 + 0.5);\n\tbreak;\n    case '#':\n\tif (strlen(suffixString + 1) < 1 || strlen(suffixString + 1)> 2) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"invalid alpha suffix \\\"%s\\\"\", suffixString));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t    \"INVALID_COLOR\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tfor (i = 1; i <= (int)strlen(suffixString + 1); i++) {\n\t    if ( ! isxdigit(UCHAR(suffixString[i]))) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"invalid alpha suffix \\\"%s\\\": expected hex digit\",\n\t\t\tsuffixString));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"INVALID_COLOR\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (strlen(suffixString + 1) == 1) {\n\t    sscanf(suffixString, \"#%1x\", &suffixAlpha);\n\t    suffixAlpha *= 0x11;\n\t} else {\n\t    sscanf(suffixString, \"#%2x\", &suffixAlpha);\n\t}\n\tbreak;\n    default:\n\tTcl_Panic(\"unexpected switch fallthrough\");\n    }\n\n    *redPtr = (unsigned char) (parsedColor.red >> 8);\n    *greenPtr = (unsigned char) (parsedColor.green >> 8);\n    *bluePtr = (unsigned char) (parsedColor.blue >> 8);\n    *alphaPtr = (unsigned char) suffixAlpha;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDebugStringMatchDef --\n *\n *      Debugging function for StringMatchDef. Basically just an alias for\n *      that function, intended to expose it directly to tests, as\n *      StirngMatchDef cannot be sufficiently tested otherwise.\n *\n * Results:\n *      See StringMatchDef.\n *\n * Side effects:\n *      None\n *----------------------------------------------------------------------\n */\nbool\nTkDebugPhotoStringMatchDef(\n    Tcl_Interp *interp,     /* Error messages are left in this interpreter */\n    Tcl_Obj *data,          /* The data to check */\n    Tcl_Obj *formatString,  /* Value of the -format option, not used here */\n    int *widthPtr,          /* Width of image is written to this location */\n    int *heightPtr)         /* Height of image is written to this location */\n{\n    return StringMatchDef(data, formatString, widthPtr, heightPtr, interp) != 0;\n}\n\f\n\n/* Local Variables: */\n/* mode: c */\n/* fill-column: 78 */\n/* c-basic-offset: 4 */\n/* tab-width: 8 */\n/* indent-tabs-mode: nil */\n/* End: */\n"
  },
  {
    "path": "generic/tkImgPNG.c",
    "content": "/*\n * tkImgPNG.c --\n *\n *\tA Tk photo image file handler for PNG files.\n *\n * Copyright © 2006-2008 Muonics, Inc.\n * Copyright © 2008 Donal K. Fellows\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#define\tPNG_UINT32(a,b,c,d)\t\\\n\t(((unsigned long)(a) << 24) | ((unsigned long)(b) << 16) | ((unsigned long)(c) << 8) | (unsigned long)(d))\n#define\tPNG_BLOCK_SZ\t1024\t\t/* Process up to 1k at a time. */\n#define PNG_MIN(a, b) (((a) < (b)) ? (a) : (b))\n\n/*\n * Every PNG image starts with the following 8-byte signature.\n */\n\n#define PNG_SIG_SZ\t8\nstatic const unsigned char pngSignature[] = {\n    137, 80, 78, 71, 13, 10, 26, 10\n};\n\nstatic const int startLine[8] = {\n    0, 0, 0, 4, 0, 2, 0, 1\n};\n\n/*\n * Chunk type flags.\n */\n\n#define PNG_CF_ANCILLARY 0x20000000L\t/* Non-critical chunk (can ignore). */\n#define PNG_CF_PRIVATE   0x00100000L\t/* Application-specific chunk. */\n#define PNG_CF_RESERVED  0x00001000L\t/* Not used. */\n#define PNG_CF_COPYSAFE  0x00000010L\t/* Opaque data safe for copying. */\n\n/*\n * Chunk types, not all of which have support implemented. Note that there are\n * others in the official extension set which we will never support (as they\n * are officially deprecated).\n */\n\n#define CHUNK_IDAT\tPNG_UINT32('I','D','A','T')\t/* Pixel data. */\n#define CHUNK_IEND\tPNG_UINT32('I','E','N','D')\t/* End of Image. */\n#define CHUNK_IHDR\tPNG_UINT32('I','H','D','R')\t/* Header. */\n#define CHUNK_PLTE\tPNG_UINT32('P','L','T','E')\t/* Palette. */\n\n#define CHUNK_bKGD\tPNG_UINT32('b','K','G','D')\t/* Background Color */\n#define CHUNK_cHRM\tPNG_UINT32('c','H','R','M')\t/* Chroma values. */\n#define CHUNK_gAMA\tPNG_UINT32('g','A','M','A')\t/* Gamma. */\n#define CHUNK_hIST\tPNG_UINT32('h','I','S','T')\t/* Histogram. */\n#define CHUNK_iCCP\tPNG_UINT32('i','C','C','P')\t/* Color profile. */\n#define CHUNK_iTXt\tPNG_UINT32('i','T','X','t')\t/* Internationalized\n\t\t\t\t\t\t\t * text (comments,\n\t\t\t\t\t\t\t * etc.) */\n#define CHUNK_oFFs\tPNG_UINT32('o','F','F','s')\t/* Image offset. */\n#define CHUNK_pCAL\tPNG_UINT32('p','C','A','L')\t/* Pixel calibration\n\t\t\t\t\t\t\t * data. */\n#define CHUNK_pHYs\tPNG_UINT32('p','H','Y','s')\t/* Physical pixel\n\t\t\t\t\t\t\t * dimensions. */\n#define CHUNK_sBIT\tPNG_UINT32('s','B','I','T')\t/* Significant bits */\n#define CHUNK_sCAL\tPNG_UINT32('s','C','A','L')\t/* Physical scale. */\n#define CHUNK_sPLT\tPNG_UINT32('s','P','L','T')\t/* Suggested\n\t\t\t\t\t\t\t * palette. */\n#define CHUNK_sRGB\tPNG_UINT32('s','R','G','B')\t/* Standard RGB space\n\t\t\t\t\t\t\t * declaration. */\n#define CHUNK_tEXt\tPNG_UINT32('t','E','X','t')\t/* Plain Latin-1\n\t\t\t\t\t\t\t * text. */\n#define CHUNK_tIME\tPNG_UINT32('t','I','M','E')\t/* Time stamp. */\n#define CHUNK_tRNS\tPNG_UINT32('t','R','N','S')\t/* Transparency. */\n#define CHUNK_zTXt\tPNG_UINT32('z','T','X','t')\t/* Compressed Latin-1\n\t\t\t\t\t\t\t * text. */\n\n/*\n * Color flags.\n */\n\n#define PNG_COLOR_INDEXED\t1\n#define PNG_COLOR_USED\t\t2\n#define PNG_COLOR_ALPHA\t\t4\n\n/*\n * Actual color types.\n */\n\n#define PNG_COLOR_GRAY\t\t0\n#define PNG_COLOR_RGB\t\t(PNG_COLOR_USED)\n#define PNG_COLOR_PLTE\t\t(PNG_COLOR_USED | PNG_COLOR_INDEXED)\n#define PNG_COLOR_GRAYALPHA\t(PNG_COLOR_GRAY | PNG_COLOR_ALPHA)\n#define PNG_COLOR_RGBA\t\t(PNG_COLOR_USED | PNG_COLOR_ALPHA)\n\n/*\n * Compression Methods.\n */\n\n#define PNG_COMPRESS_DEFLATE\t0\n\n/*\n * Filter Methods.\n */\n\n#define PNG_FILTMETH_STANDARD\t0\n\n/*\n * Interlacing Methods.\n */\n\n#define\tPNG_INTERLACE_NONE\t0\n#define PNG_INTERLACE_ADAM7\t1\n\n/*\n * State information, used to store everything about the PNG image being\n * currently parsed or created.\n */\n\ntypedef struct {\n    /*\n     * PNG data source/destination channel/object/byte array.\n     */\n\n    Tcl_Channel channel;\t/* Channel for from-file reads. */\n    Tcl_Obj *objDataPtr;\n    unsigned char *strDataBuf;\t/* Raw source data for from-string reads. */\n    Tcl_Size strDataLen;\t\t/* Length of source data. */\n    unsigned char *base64Data;\t/* base64 encoded string data. */\n    unsigned char base64Bits;\t/* Remaining bits from last base64 read. */\n    unsigned char base64State;\t/* Current state of base64 decoder. */\n    double alpha;\t\t/* Alpha from -format option. */\n\n    /*\n     * Image header information.\n     */\n\n    unsigned char bitDepth;\t/* Number of bits per pixel. */\n    unsigned char colorType;\t/* Grayscale, TrueColor, etc. */\n    unsigned char compression;\t/* Compression Mode (always zlib). */\n    unsigned char filter;\t/* Filter mode (0 - 3). */\n    unsigned char interlace;\t/* Type of interlacing (if any). */\n    unsigned char numChannels;\t/* Number of channels per pixel. */\n    unsigned char bytesPerPixel;/* Bytes per pixel in scan line. */\n    int bitScale;\t\t/* Scale factor for RGB/Gray depths < 8. */\n    int currentLine;\t\t/* Current line being unfiltered. */\n    unsigned char phase;\t/* Interlacing phase (0..6). */\n    Tk_PhotoImageBlock block;\n    int blockLen;\t\t/* Number of bytes in Tk image pixels. */\n\n    /*\n     * For containing data read from PLTE (palette) and tRNS (transparency)\n     * chunks.\n     */\n\n    int paletteLen;\t\t/* Number of PLTE entries (1..256). */\n    bool useTRNS;\t\t/* Flag to indicate whether there was a\n\t\t\t\t * palette given. */\n    struct {\n\tunsigned char red;\n\tunsigned char green;\n\tunsigned char blue;\n\tunsigned char alpha;\n    } palette[256];\t\t/* Palette RGB/Transparency table. */\n    unsigned char transVal[6];\t/* Fully-transparent RGB/Gray Value. */\n\n    /*\n     * For compressing and decompressing IDAT chunks.\n     */\n\n    Tcl_ZlibStream stream;\t/* Inflating or deflating stream; this one is\n\t\t\t\t * not bound to a Tcl command. */\n    Tcl_Obj *lastLineObj;\t/* Last line of pixels, for unfiltering. */\n    Tcl_Obj *thisLineObj;\t/* Current line of pixels to process. */\n    int lineSize;\t\t/* Number of bytes in a PNG line. */\n    int phaseSize;\t\t/* Number of bytes/line in current phase. */\n\n\n    /*\n     * Physical size: pHYS chunks.\n     */\n\n    double DPI;\n    double aspect;\n\n} PNGImage;\n\n/*\n * Maximum size of various chunks.\n */\n\n#define\tPNG_PLTE_MAXSZ 768\t/* 3 bytes/RGB entry, 256 entries max */\n#define\tPNG_TRNS_MAXSZ 256\t/* 1-byte alpha, 256 entries max */\n\n/*\n * Forward declarations of non-global functions defined in this file:\n */\n\nstatic void\t\tApplyAlpha(PNGImage *pngPtr);\nstatic int\t\tCheckColor(Tcl_Interp *interp, PNGImage *pngPtr);\nstatic inline int\tCheckCRC(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned long calculated);\nstatic void\t\tCleanupPNGImage(PNGImage *pngPtr);\nstatic int\t\tDecodeLine(Tcl_Interp *interp, PNGImage *pngPtr);\nstatic int\t\tDecodePNG(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    Tcl_Obj *fmtObj, Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY);\nstatic int\t\tEncodePNG(Tcl_Interp *interp,\n\t\t\t    Tk_PhotoImageBlock *blockPtr, PNGImage *pngPtr,\n\t\t\t    Tcl_Obj *metadataInObj);\nstatic int\t\tFileMatchPNG(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *fmtObj,\n\t\t\t    Tcl_Obj *metadataInObj, int *widthPtr,\n\t\t\t    int *heightPtr, Tcl_Obj *metadataOut);\nstatic int\t\tFileReadPNG(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *fmtObj,\n\t\t\t    Tcl_Obj *metadataInObj, Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY, Tcl_Obj *metadataOutPtr);\nstatic int\t\tFileWritePNG(Tcl_Interp *interp, const char *filename,\n\t\t\t    Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tInitPNGImage(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    Tcl_Channel chan, Tcl_Obj *objPtr, int dir);\nstatic inline unsigned char Paeth(int a, int b, int c);\nstatic int\t\tParseFormat(Tcl_Interp *interp, Tcl_Obj *fmtObj,\n\t\t\t    PNGImage *pngPtr);\nstatic int\t\tReadBase64(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned char *destPtr, Tcl_Size destSz,\n\t\t\t    unsigned long *crcPtr);\nstatic int\t\tReadByteArray(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned char *destPtr, Tcl_Size destSz,\n\t\t\t    unsigned long *crcPtr);\nstatic int\t\tReadData(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned char *destPtr, Tcl_Size destSz,\n\t\t\t    unsigned long *crcPtr);\nstatic int\t\tReadChunkHeader(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    Tcl_Size *sizePtr, unsigned long *typePtr,\n\t\t\t    unsigned long *crcPtr);\nstatic int\t\tReadIDAT(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    int chunkSz, unsigned long crc);\nstatic int\t\tReadIHDR(Tcl_Interp *interp, PNGImage *pngPtr);\nstatic inline int\tReadInt32(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned long *resultPtr, unsigned long *crcPtr);\nstatic int\t\tReadPLTE(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    int chunkSz, unsigned long crc);\nstatic int\t\tReadTRNS(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    int chunkSz, unsigned long crc);\nstatic int\t\tSkipChunk(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    int chunkSz, unsigned long crc);\nstatic int\t\tStringMatchPNG(Tcl_Interp *interp, Tcl_Obj *pObjData,\n\t\t\t    Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj,\n\t\t\t    int *widthPtr, int *heightPtr,\n\t\t\t    Tcl_Obj *metadataOutObj);\nstatic int\t\tStringReadPNG(Tcl_Interp *interp, Tcl_Obj *pObjData,\n\t\t\t    Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY, Tcl_Obj *metadataOutObj);\n\nstatic int\t\tStringWritePNG(Tcl_Interp *interp, Tcl_Obj *fmtObj,\n\t\t\t    Tcl_Obj *metadataInObj,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tUnfilterLine(Tcl_Interp *interp, PNGImage *pngPtr);\nstatic inline int\tWriteByte(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned char c, unsigned long *crcPtr);\nstatic inline int\tWriteChunk(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned long chunkType,\n\t\t\t    const unsigned char *dataPtr, Tcl_Size dataSize);\nstatic int\t\tWriteData(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    const unsigned char *srcPtr, Tcl_Size srcSz,\n\t\t\t    unsigned long *crcPtr);\nstatic int\t\tWriteExtraChunks(Tcl_Interp *interp,\n\t\t\t    PNGImage *pngPtr, Tcl_Obj *metadataInObj);\nstatic int\t\tWriteIHDR(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tWriteIDAT(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic inline int\tWriteInt32(Tcl_Interp *interp, PNGImage *pngPtr,\n\t\t\t    unsigned long l, unsigned long *crcPtr);\n\n/*\n * The format record for the PNG file format:\n */\n\nTk_PhotoImageFormatVersion3 tkImgFmtPNG = {\n    \"png\",\t\t\t/* name */\n    FileMatchPNG,\t\t/* fileMatchProc */\n    StringMatchPNG,\t\t/* stringMatchProc */\n    FileReadPNG,\t\t/* fileReadProc */\n    StringReadPNG,\t\t/* stringReadProc */\n    FileWritePNG,\t\t/* fileWriteProc */\n    StringWritePNG,\t\t/* stringWriteProc */\n    NULL\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitPNGImage --\n *\n *\tThis function is invoked by each of the Tk image handler procs\n *\t(MatchStringProc, etc.) to initialize state information used during\n *\tthe course of encoding or decoding a PNG image.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if initialization failed.\n *\n * Side effects:\n *\tThe reference count of the -data Tcl_Obj*, if any, is incremented.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInitPNGImage(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    Tcl_Channel chan,\n    Tcl_Obj *objPtr,\n    int dir)\n{\n    memset(pngPtr, 0, sizeof(PNGImage));\n\n    pngPtr->channel = chan;\n    pngPtr->alpha = 1.0;\n\n    /*\n     * If decoding from a -data string object, increment its reference count\n     * for the duration of the decode and get its length and byte array for\n     * reading with ReadData().\n     */\n\n    if (objPtr) {\n\tTcl_IncrRefCount(objPtr);\n\tpngPtr->objDataPtr = objPtr;\n\tpngPtr->strDataBuf =\n\t\tTcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen);\n    }\n\n    /*\n     * Initialize the palette transparency table to fully opaque.\n     */\n\n    memset(pngPtr->palette, 255, sizeof(pngPtr->palette));\n\n    /*\n     * Initialize Zlib inflate/deflate stream.\n     */\n\n    if (Tcl_ZlibStreamInit(NULL, dir, TCL_ZLIB_FORMAT_ZLIB,\n\t    TCL_ZLIB_COMPRESS_DEFAULT, NULL, &pngPtr->stream) != TCL_OK) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"zlib initialization failed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"ZLIB_INIT\", (char *)NULL);\n\t}\n\tif (objPtr) {\n\t    Tcl_DecrRefCount(objPtr);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Initialize physical size pHYS values\n     */\n\n    pngPtr->DPI = -1;\n    pngPtr->aspect = -1;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CleanupPNGImage --\n *\n *\tThis function is invoked by each of the Tk image handler procs\n *\t(MatchStringProc, etc.) prior to returning to Tcl in order to clean up\n *\tany allocated memory and call other cleanup handlers such as zlib's\n *\tinflateEnd/deflateEnd.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe reference count of the -data Tcl_Obj*, if any, is decremented.\n *\tBuffers are freed, streams are closed. The PNGImage should not be used\n *\tfor any purpose without being reinitialized post-cleanup.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCleanupPNGImage(\n    PNGImage *pngPtr)\n{\n    /*\n     * Don't need the object containing the -data value anymore.\n     */\n\n    if (pngPtr->objDataPtr) {\n\tTcl_DecrRefCount(pngPtr->objDataPtr);\n    }\n\n    /*\n     * Discard pixel buffer.\n     */\n\n    if (pngPtr->stream) {\n\tTcl_ZlibStreamClose(pngPtr->stream);\n    }\n\n    if (pngPtr->block.pixelPtr) {\n\tTcl_Free(pngPtr->block.pixelPtr);\n    }\n    if (pngPtr->thisLineObj) {\n\tTcl_DecrRefCount(pngPtr->thisLineObj);\n    }\n    if (pngPtr->lastLineObj) {\n\tTcl_DecrRefCount(pngPtr->lastLineObj);\n    }\n\n    memset(pngPtr, 0, sizeof(PNGImage));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadBase64 --\n *\n *\tThis function is invoked to read the specified number of bytes from\n *\tbase-64 encoded image data.\n *\n *\tNote: It would be better if the Tk_PhotoImage stuff handled this by\n *\tcreating a channel from the -data value, which would take care of\n *\tbase64 decoding and made the data readable as if it were coming from a\n *\tfile.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs.\n *\n * Side effects:\n *\tThe file position will change. The running CRC is updated if a pointer\n *\tto it is provided.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadBase64(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned char *destPtr,\n    Tcl_Size destSz,\n    unsigned long *crcPtr)\n{\n    static const unsigned char from64[] = {\n\t0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80, 0x80,\n\t0x83, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x3e,\n\t0x83, 0x83, 0x83, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,\n\t0x3b, 0x3c, 0x3d, 0x83, 0x83, 0x83, 0x81, 0x83, 0x83, 0x83, 0x00,\n\t0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,\n\t0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,\n\t0x17, 0x18, 0x19, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x1a, 0x1b,\n\t0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,\n\t0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,\n\t0x32, 0x33, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,\n\t0x83, 0x83, 0x83\n    };\n\n    /*\n     * Definitions for the base-64 decoder.\n     */\n\n#define PNG64_SPECIAL\t0x80\t/* Flag bit */\n#define PNG64_SPACE\t0x80\t/* Whitespace */\n#define PNG64_PAD\t0x81\t/* Padding */\n#define PNG64_DONE\t0x82\t/* End of data */\n#define PNG64_BAD\t0x83\t/* Ooooh, naughty! */\n\n    while (destSz && pngPtr->strDataLen) {\n\tunsigned char c = 0;\n\tunsigned char c64 = from64[*pngPtr->strDataBuf++];\n\n\tpngPtr->strDataLen--;\n\n\tif (PNG64_SPACE == c64) {\n\t    continue;\n\t}\n\n\tif (c64 & PNG64_SPECIAL) {\n\t    c = (unsigned char) pngPtr->base64Bits;\n\t} else {\n\t    switch (pngPtr->base64State++) {\n\t    case 0:\n\t\tpngPtr->base64Bits = c64 << 2;\n\t\tcontinue;\n\t    case 1:\n\t\tc = (unsigned char) (pngPtr->base64Bits | (c64 >> 4));\n\t\tpngPtr->base64Bits = (c64 & 0xF) << 4;\n\t\tbreak;\n\t    case 2:\n\t\tc = (unsigned char) (pngPtr->base64Bits | (c64 >> 2));\n\t\tpngPtr->base64Bits = (c64 & 0x3) << 6;\n\t\tbreak;\n\t    case 3:\n\t\tc = (unsigned char) (pngPtr->base64Bits | c64);\n\t\tpngPtr->base64State = 0;\n\t\tpngPtr->base64Bits = 0;\n\t\tbreak;\n\t    }\n\t}\n\n\tif (crcPtr) {\n\t    *crcPtr = Tcl_ZlibCRC32(*crcPtr, &c, 1);\n\t}\n\n\tif (destPtr) {\n\t    *destPtr++ = c;\n\t}\n\n\tdestSz--;\n\n\tif (c64 & PNG64_SPECIAL) {\n\t    break;\n\t}\n    }\n\n    if (destSz) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"unexpected end of image data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EARLY_END\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadByteArray --\n *\n *\tThis function is invoked to read the specified number of bytes from a\n *\tnon-base64-encoded byte array provided via the -data option.\n *\n *\tNote: It would be better if the Tk_PhotoImage stuff handled this by\n *\tcreating a channel from the -data value and made the data readable as\n *\tif it were coming from a file.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs.\n *\n * Side effects:\n *\tThe file position will change. The running CRC is updated if a pointer\n *\tto it is provided.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadByteArray(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned char *destPtr,\n    Tcl_Size destSz,\n    unsigned long *crcPtr)\n{\n    /*\n     * Check to make sure the number of requested bytes are available.\n     */\n\n    if (pngPtr->strDataLen < destSz) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"unexpected end of image data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EARLY_END\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    while (destSz) {\n\tTcl_Size blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);\n\n\tmemcpy(destPtr, pngPtr->strDataBuf, blockSz);\n\n\tpngPtr->strDataBuf += blockSz;\n\tpngPtr->strDataLen -= blockSz;\n\n\tif (crcPtr) {\n\t    *crcPtr = Tcl_ZlibCRC32(*crcPtr, destPtr, blockSz);\n\t}\n\n\tdestPtr += blockSz;\n\tdestSz -= blockSz;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadData --\n *\n *\tThis function is invoked to read the specified number of bytes from\n *\tthe image file or data. It is a wrapper around the choice of byte\n *\tarray Tcl_Obj or Tcl_Channel which depends on whether the image data\n *\tis coming from a file or -data.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs.\n *\n * Side effects:\n *\tThe file position will change. The running CRC is updated if a pointer\n *\tto it is provided.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadData(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned char *destPtr,\n    Tcl_Size destSz,\n    unsigned long *crcPtr)\n{\n    if (pngPtr->base64Data) {\n\treturn ReadBase64(interp, pngPtr, destPtr, destSz, crcPtr);\n    } else if (pngPtr->strDataBuf) {\n\treturn ReadByteArray(interp, pngPtr, destPtr, destSz, crcPtr);\n    }\n\n    while (destSz) {\n\tTcl_Size blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);\n\n\tblockSz = Tcl_Read(pngPtr->channel, (char *)destPtr, blockSz);\n\tif (blockSz == TCL_IO_FAILURE) {\n\t    /* TODO: failure info... */\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"channel read failed: %s\", Tcl_PosixError(interp)));\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Update CRC, pointer, and remaining count if anything was read.\n\t */\n\n\tif (blockSz) {\n\t    if (crcPtr) {\n\t\t*crcPtr = Tcl_ZlibCRC32(*crcPtr, destPtr, blockSz);\n\t    }\n\n\t    destPtr += blockSz;\n\t    destSz -= blockSz;\n\t}\n\n\t/*\n\t * Check for EOF before all desired data was read.\n\t */\n\n\tif (destSz && Tcl_Eof(pngPtr->channel)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"unexpected end of file\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EOF\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadInt32 --\n *\n *\tThis function is invoked to read a 32-bit integer in network byte\n *\torder from the image data and return the value in host byte order.\n *\tThis is used, for example, to read the 32-bit CRC value for a chunk\n *\tstored in the image file for comparison with the calculated CRC value.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs.\n *\n * Side effects:\n *\tThe file position will change. The running CRC is updated if a pointer\n *\tto it is provided.\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline int\nReadInt32(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned long *resultPtr,\n    unsigned long *crcPtr)\n{\n    unsigned char p[4];\n\n    if (ReadData(interp, pngPtr, p, 4, crcPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    *resultPtr = PNG_UINT32(p[0], p[1], p[2], p[3]);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckCRC --\n *\n *\tThis function is reads the final 4-byte integer CRC from a chunk and\n *\tcompares it to the running CRC calculated over the chunk type and data\n *\tfields.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error or CRC mismatch occurs.\n *\n * Side effects:\n *\tThe file position will change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline int\nCheckCRC(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned long calculated)\n{\n    unsigned long chunked;\n\n    /*\n     * Read the CRC field at the end of the chunk.\n     */\n\n    if (ReadInt32(interp, pngPtr, &chunked, NULL) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Compare the read CRC to what we calculate to make sure they match.\n     */\n\n    if (calculated != chunked) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"CRC check failed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"CRC\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SkipChunk --\n *\n *\tThis function is used to skip a PNG chunk that is not used by this\n *\timplementation. Given the input stream has had the chunk length and\n *\tchunk type fields already read, this function will read the number of\n *\tbytes indicated by the chunk length, plus four for the CRC, and will\n *\tverify that CRC is correct for the skipped data.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error or CRC mismatch occurs.\n *\n * Side effects:\n *\tThe file position will change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSkipChunk(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    int chunkSz,\n    unsigned long crc)\n{\n    unsigned char buffer[PNG_BLOCK_SZ];\n\n    /*\n     * Skip data in blocks until none is left. Read up to PNG_BLOCK_SZ bytes\n     * at a time, rather than trusting the claimed chunk size, which may not\n     * be trustworthy.\n     */\n\n    while (chunkSz) {\n\tint blockSz = PNG_MIN(chunkSz, PNG_BLOCK_SZ);\n\n\tif (ReadData(interp, pngPtr, buffer, blockSz, &crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\tchunkSz -= blockSz;\n    }\n\n    if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n * 4.3. Summary of standard chunks\n *\n * This table summarizes some properties of the standard chunk types.\n *\n *\tCritical chunks (must appear in this order, except PLTE is optional):\n *\n *\t\tName   Multiple\t Ordering constraints OK?\n *\n *\t\tIHDR\tNo\t Must be first\n *\t\tPLTE\tNo\t Before IDAT\n *\t\tIDAT\tYes\t Multiple IDATs must be consecutive\n *\t\tIEND\tNo\t Must be last\n *\n *\tAncillary chunks (need not appear in this order):\n *\n *\t\tName   Multiple\t Ordering constraints OK?\n *\n *\t\tcHRM\tNo\t Before PLTE and IDAT\n *\t\tgAMA\tNo\t Before PLTE and IDAT\n *\t\tiCCP\tNo\t Before PLTE and IDAT\n *\t\tsBIT\tNo\t Before PLTE and IDAT\n *\t\tsRGB\tNo\t Before PLTE and IDAT\n *\t\tbKGD\tNo\t After PLTE; before IDAT\n *\t\thIST\tNo\t After PLTE; before IDAT\n *\t\ttRNS\tNo\t After PLTE; before IDAT\n *\t\tpHYs\tNo\t Before IDAT\n *\t\tsPLT\tYes\t Before IDAT\n *\t\ttIME\tNo\t None\n *\t\tiTXt\tYes\t None\n *\t\ttEXt\tYes\t None\n *\t\tzTXt\tYes\t None\n *\n *\t[From the PNG specification.]\n */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadChunkHeader --\n *\n *\tThis function is used at the start of each chunk to extract the\n *\tfour-byte chunk length and four-byte chunk type fields. It will\n *\tcontinue reading until it finds a chunk type that is handled by this\n *\timplementation, checking the CRC of any chunks it skips.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or an unknown critical\n *\tchunk type is encountered.\n *\n * Side effects:\n *\tThe file position will change. The running CRC is updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadChunkHeader(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    Tcl_Size *sizePtr,\n    unsigned long *typePtr,\n    unsigned long *crcPtr)\n{\n    unsigned long chunkType = 0;\n    int chunkSz = 0;\n    unsigned long crc = 0;\n\n    /*\n     * Continue until finding a chunk type that is handled.\n     */\n\n    while (!chunkType) {\n\tunsigned long temp;\n\tunsigned char pc[4];\n\tint i;\n\n\t/*\n\t * Read the 4-byte length field for the chunk. The length field is not\n\t * included in the CRC calculation, so the running CRC must be reset\n\t * afterward. Limit chunk lengths to INT_MAX, to align with the\n\t * maximum size for Tcl_Read, Tcl_GetByteArrayFromObj, etc.\n\t */\n\n\tif (ReadData(interp, pngPtr, pc, 4, NULL) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\ttemp = PNG_UINT32(pc[0], pc[1], pc[2], pc[3]);\n\n\tif (temp > INT_MAX) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"chunk size is out of supported range on this architecture\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"OUTSIZE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tchunkSz = (int) temp;\n\tcrc = Tcl_ZlibCRC32(0, NULL, 0);\n\n\t/*\n\t * Read the 4-byte chunk type.\n\t */\n\n\tif (ReadData(interp, pngPtr, pc, 4, &crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Convert it to a host-order integer for simple comparison.\n\t */\n\n\tchunkType = PNG_UINT32(pc[0], pc[1], pc[2], pc[3]);\n\n\t/*\n\t * Check to see if this is a known/supported chunk type. Note that the\n\t * PNG specs require non-critical (i.e., ancillary) chunk types that\n\t * are not recognized to be ignored, rather than be treated as an\n\t * error. It does, however, recommend that an unknown critical chunk\n\t * type be treated as a failure.\n\t *\n\t * This switch/loop acts as a filter of sorts for undesired chunk\n\t * types. The chunk type should still be checked elsewhere for\n\t * determining it is in the correct order.\n\t */\n\n\tswitch (chunkType) {\n\t    /*\n\t     * These chunk types are required and/or supported.\n\t     */\n\n\tcase CHUNK_IDAT:\n\tcase CHUNK_IEND:\n\tcase CHUNK_IHDR:\n\tcase CHUNK_pHYs:\n\tcase CHUNK_PLTE:\n\tcase CHUNK_tRNS:\n\t    break;\n\n\t    /*\n\t     * These chunk types are part of the standard, but are not used by\n\t     * this implementation (at least not yet). Note that these are all\n\t     * ancillary chunks (lowercase first letter).\n\t     */\n\n\tcase CHUNK_bKGD:\n\tcase CHUNK_cHRM:\n\tcase CHUNK_gAMA:\n\tcase CHUNK_hIST:\n\tcase CHUNK_iCCP:\n\tcase CHUNK_iTXt:\n\tcase CHUNK_oFFs:\n\tcase CHUNK_pCAL:\n\tcase CHUNK_sBIT:\n\tcase CHUNK_sCAL:\n\tcase CHUNK_sPLT:\n\tcase CHUNK_sRGB:\n\tcase CHUNK_tEXt:\n\tcase CHUNK_tIME:\n\tcase CHUNK_zTXt:\n\t    /*\n\t     * TODO: might want to check order here.\n\t     */\n\n\t    if (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    chunkType = 0;\n\t    break;\n\n\tdefault:\n\t    /*\n\t     * Unknown chunk type. If it's critical, we can't continue.\n\t     */\n\n\t    if (!(chunkType & PNG_CF_ANCILLARY)) {\n\t\tif (chunkType & PNG_UINT32(128,128,128,128)) {\n\t\t    /*\n\t\t     * No nice ASCII conversion; shouldn't happen either, but\n\t\t     * we'll be doubly careful.\n\t\t     */\n\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"encountered an unsupported critical chunk type\",\n\t\t\t    -1));\n\t\t} else {\n\t\t    char typeString[5];\n\n\t\t    typeString[0] = (char) ((chunkType >> 24) & 255);\n\t\t    typeString[1] = (char) ((chunkType >> 16) & 255);\n\t\t    typeString[2] = (char) ((chunkType >> 8) & 255);\n\t\t    typeString[3] = (char) (chunkType & 255);\n\t\t    typeString[4] = '\\0';\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"encountered an unsupported critical chunk type\"\n\t\t\t    \" \\\"%s\\\"\", typeString));\n\t\t}\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\",\n\t\t\t\"UNSUPPORTED_CRITICAL\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Check to see if the chunk type has legal bytes.\n\t     */\n\n\t    for (i=0 ; i<4 ; i++) {\n\t\tif ((pc[i] < 65) || (pc[i] > 122) ||\n\t\t\t((pc[i] > 90) && (pc[i] < 97))) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"invalid chunk type\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\",\n\t\t\t    \"INVALID_CHUNK\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\n\t    /*\n\t     * It seems to be an otherwise legally labelled ancillary chunk\n\t     * that we don't want, so skip it after at least checking its CRC.\n\t     */\n\n\t    if (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    chunkType = 0;\n\t}\n    }\n\n    /*\n     * Found a known chunk type that's handled, albiet possibly not in the\n     * right order. Send back the chunk type (for further checking or\n     * handling), the chunk size and the current CRC for the rest of the\n     * calculation.\n     */\n\n    *typePtr = chunkType;\n    *sizePtr = chunkSz;\n    *crcPtr = crc;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckColor --\n *\n *\tDo validation on color type, depth, and related information, and\n *\tcalculates storage requirements and offsets based on image dimensions\n *\tand color.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if color information is invalid or some other\n *\tfailure occurs.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCheckColor(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr)\n{\n    int offset;\n\n    /*\n     * Verify the color type is valid and the bit depth is allowed.\n     */\n\n    switch (pngPtr->colorType) {\n    case PNG_COLOR_GRAY:\n\tpngPtr->numChannels = 1;\n\tif ((1 != pngPtr->bitDepth) && (2 != pngPtr->bitDepth) &&\n\t\t(4 != pngPtr->bitDepth) && (8 != pngPtr->bitDepth) &&\n\t\t(16 != pngPtr->bitDepth)) {\n\t    goto unsupportedDepth;\n\t}\n\tbreak;\n\n    case PNG_COLOR_RGB:\n\tpngPtr->numChannels = 3;\n\tif ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {\n\t    goto unsupportedDepth;\n\t}\n\tbreak;\n\n    case PNG_COLOR_PLTE:\n\tpngPtr->numChannels = 1;\n\tif ((1 != pngPtr->bitDepth) && (2 != pngPtr->bitDepth) &&\n\t\t(4 != pngPtr->bitDepth) && (8 != pngPtr->bitDepth)) {\n\t    goto unsupportedDepth;\n\t}\n\tbreak;\n\n    case PNG_COLOR_GRAYALPHA:\n\tpngPtr->numChannels = 2;\n\tif ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {\n\t    goto unsupportedDepth;\n\t}\n\tbreak;\n\n    case PNG_COLOR_RGBA:\n\tpngPtr->numChannels = 4;\n\tif ((8 != pngPtr->bitDepth) && (16 != pngPtr->bitDepth)) {\n\tunsupportedDepth:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"bit depth is not allowed for given color type\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_DEPTH\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tbreak;\n\n    default:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown color type field %d\", pngPtr->colorType));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"UNKNOWN_COLOR\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Set up the Tk photo block's pixel size and channel offsets. offset\n     * array elements should already be 0 from the memset during InitPNGImage.\n     */\n\n    offset = (pngPtr->bitDepth > 8) ? 2 : 1;\n\n    if (pngPtr->colorType & PNG_COLOR_USED) {\n\tpngPtr->block.pixelSize = offset * 4;\n\tpngPtr->block.offset[1] = offset;\n\tpngPtr->block.offset[2] = offset * 2;\n\tpngPtr->block.offset[3] = offset * 3;\n    } else {\n\tpngPtr->block.pixelSize = offset * 2;\n\tpngPtr->block.offset[3] = offset;\n    }\n\n    /*\n     * Calculate the block pitch, which is the number of bytes per line in the\n     * image, given image width and depth of color. Make sure that it it isn't\n     * larger than Tk can handle.\n     */\n\n    if (pngPtr->block.width > INT_MAX / pngPtr->block.pixelSize) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"image pitch is out of supported range on this architecture\",\n\t\t-1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"PITCH\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    pngPtr->block.pitch = pngPtr->block.pixelSize * pngPtr->block.width;\n\n    /*\n     * Calculate the total size of the image as represented to Tk given pitch\n     * and image height. Make sure that it isn't larger than Tk can handle.\n     */\n\n    if (pngPtr->block.height > INT_MAX / pngPtr->block.pitch) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"image total size is out of supported range on this architecture\",\n\t\t-1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"SIZE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    pngPtr->blockLen = pngPtr->block.height * pngPtr->block.pitch;\n\n    /*\n     * Determine number of bytes per pixel in the source for later use.\n     */\n\n    switch (pngPtr->colorType) {\n    case PNG_COLOR_GRAY:\n\tpngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 2 : 1;\n\tbreak;\n    case PNG_COLOR_RGB:\n\tpngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 6 : 3;\n\tbreak;\n    case PNG_COLOR_PLTE:\n\tpngPtr->bytesPerPixel = 1;\n\tbreak;\n    case PNG_COLOR_GRAYALPHA:\n\tpngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 4 : 2;\n\tbreak;\n    case PNG_COLOR_RGBA:\n\tpngPtr->bytesPerPixel = (pngPtr->bitDepth > 8) ? 8 : 4;\n\tbreak;\n    default:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown color type %d\", pngPtr->colorType));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"UNKNOWN_COLOR\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Calculate scale factor for bit depths less than 8, in order to adjust\n     * them to a minimum of 8 bits per pixel in the Tk image.\n     */\n\n    if (pngPtr->bitDepth < 8) {\n\tpngPtr->bitScale = 255 / (int)(pow(2, pngPtr->bitDepth) - 1);\n    } else {\n\tpngPtr->bitScale = 1;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadIHDR --\n *\n *\tThis function reads the PNG header from the beginning of a PNG file\n *\tand returns the dimensions of the image.\n *\n * Results:\n *\tThe return value is 1 if file \"f\" appears to start with a valid PNG\n *\theader, 0 otherwise. If the header is valid, then *widthPtr and\n *\t*heightPtr are modified to hold the dimensions of the image.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadIHDR(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr)\n{\n    unsigned char sigBuf[PNG_SIG_SZ];\n    unsigned long chunkType;\n    Tcl_Size chunkSz;\n    unsigned long crc;\n    unsigned long width, height;\n    bool mismatch;\n\n    /*\n     * Read the appropriate number of bytes for the PNG signature.\n     */\n\n    if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Compare the read bytes to the expected signature.\n     */\n\n    mismatch = memcmp(sigBuf, pngSignature, PNG_SIG_SZ) != 0;\n\n    /*\n     * If reading from string, reset position and try base64 decode.\n     */\n\n    if (mismatch && pngPtr->strDataBuf) {\n\tpngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr,\n\t\t&pngPtr->strDataLen);\n\tpngPtr->base64Data = pngPtr->strDataBuf;\n\n\tif (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\tmismatch = memcmp(sigBuf, pngSignature, PNG_SIG_SZ) != 0;\n    }\n\n    if (mismatch) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"data stream does not have a PNG signature\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"NO_SIG\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t    &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Read in the IHDR (header) chunk for width, height, etc.\n     *\n     * The first chunk in the file must be the IHDR (headr) chunk.\n     */\n\n    if (chunkType != CHUNK_IHDR) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"expected IHDR chunk type\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"NO_IHDR\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (chunkSz != 13) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"invalid IHDR chunk size\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_IHDR\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Read and verify the image width and height to be sure Tk can handle its\n     * dimensions. The PNG specification does not permit zero-width or\n     * zero-height images.\n     */\n\n    if (ReadInt32(interp, pngPtr, &width, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (ReadInt32(interp, pngPtr, &height, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (!width || !height || (width > INT_MAX) || (height > INT_MAX)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"image dimensions are invalid or beyond architecture limits\",\n\t\t-1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"DIMENSIONS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Set height and width for the Tk photo block.\n     */\n\n    pngPtr->block.width = (int) width;\n    pngPtr->block.height = (int) height;\n\n    /*\n     * Read and the Bit Depth and Color Type.\n     */\n\n    if (ReadData(interp, pngPtr, &pngPtr->bitDepth, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (ReadData(interp, pngPtr, &pngPtr->colorType, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Verify that the color type is valid, the bit depth is allowed for the\n     * color type, and calculate the number of channels and pixel depth (bits\n     * per pixel * channels). Also set up offsets and sizes in the Tk photo\n     * block for the pixel data.\n     */\n\n    if (CheckColor(interp, pngPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Only one compression method is currently defined by the standard.\n     */\n\n    if (ReadData(interp, pngPtr, &pngPtr->compression, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (pngPtr->compression != PNG_COMPRESS_DEFLATE) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown compression method %d\", pngPtr->compression));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_COMPRESS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Only one filter method is currently defined by the standard; the method\n     * has five actual filter types associated with it.\n     */\n\n    if (ReadData(interp, pngPtr, &pngPtr->filter, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (pngPtr->filter != PNG_FILTMETH_STANDARD) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown filter method %d\", pngPtr->filter));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_FILTER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (ReadData(interp, pngPtr, &pngPtr->interlace, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    switch (pngPtr->interlace) {\n    case PNG_INTERLACE_NONE:\n    case PNG_INTERLACE_ADAM7:\n\tbreak;\n\n    default:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown interlace method %d\", pngPtr->interlace));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_INTERLACE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return CheckCRC(interp, pngPtr, crc);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadPLTE --\n *\n *\tThis function reads the PLTE (indexed color palette) chunk data from\n *\tthe PNG file and populates the palette table in the PNGImage\n *\tstructure.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or the PLTE chunk is\n *\tinvalid.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadPLTE(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    int chunkSz,\n    unsigned long crc)\n{\n    unsigned char buffer[PNG_PLTE_MAXSZ];\n    int i, c;\n\n    /*\n     * This chunk is mandatory for color type 3 and forbidden for 2 and 6.\n     */\n\n    switch (pngPtr->colorType) {\n    case PNG_COLOR_GRAY:\n    case PNG_COLOR_GRAYALPHA:\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"PLTE chunk type forbidden for grayscale\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"PLTE_UNEXPECTED\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n\n    default:\n\tbreak;\n    }\n\n    /*\n     * The palette chunk contains from 1 to 256 palette entries. Each entry\n     * consists of a 3-byte RGB value. It must therefore contain a non-zero\n     * multiple of 3 bytes, up to 768.\n     */\n\n    if (!chunkSz || (chunkSz > PNG_PLTE_MAXSZ) || (chunkSz % 3)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"invalid palette chunk size\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_PLTE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Read the palette contents and stash them for later, possibly.\n     */\n\n    if (ReadData(interp, pngPtr, buffer, chunkSz, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Stash away the palette entries and entry count for later mapping each\n     * pixel's palette index to its color.\n     */\n\n    for (i=0, c=0 ; c<chunkSz ; i++) {\n\tpngPtr->palette[i].red = buffer[c++];\n\tpngPtr->palette[i].green = buffer[c++];\n\tpngPtr->palette[i].blue = buffer[c++];\n    }\n\n    pngPtr->paletteLen = i;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadTRNS --\n *\n *\tThis function reads the tRNS (transparency) chunk data from the PNG\n *\tfile and populates the alpha field of the palette table in the\n *\tPNGImage structure or the single color transparency, as appropriate\n *\tfor the color type.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or the tRNS chunk is\n *\tinvalid.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadTRNS(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    int chunkSz,\n    unsigned long crc)\n{\n    unsigned char buffer[PNG_TRNS_MAXSZ];\n    int i;\n\n    if (pngPtr->colorType & PNG_COLOR_ALPHA) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"tRNS chunk not allowed color types with a full alpha channel\",\n\t\t-1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"INVALID_TRNS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * For indexed color, there is up to one single-byte transparency value\n     * per palette entry (thus a max of 256).\n     */\n\n    if (chunkSz > PNG_TRNS_MAXSZ) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"invalid tRNS chunk size\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_TRNS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Read in the raw transparency information.\n     */\n\n    if (ReadData(interp, pngPtr, buffer, chunkSz, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    switch (pngPtr->colorType) {\n    case PNG_COLOR_GRAYALPHA:\n    case PNG_COLOR_RGBA:\n\tbreak;\n\n    case PNG_COLOR_PLTE:\n\t/*\n\t * The number of tRNS entries must be less than or equal to the number\n\t * of PLTE entries, and consists of a single-byte alpha level for the\n\t * corresponding PLTE entry.\n\t */\n\n\tif (chunkSz > pngPtr->paletteLen) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"size of tRNS chunk is too large for the palette\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"TRNS_SIZE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (i=0 ; i<chunkSz ; i++) {\n\t    pngPtr->palette[i].alpha = buffer[i];\n\t}\n\tbreak;\n\n    case PNG_COLOR_GRAY:\n\t/*\n\t * Grayscale uses a single 2-byte gray level, which we'll store in\n\t * palette index 0, since we're not using the palette.\n\t */\n\n\tif (chunkSz != 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid tRNS chunk size - must 2 bytes for grayscale\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_TRNS\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * According to the PNG specs, if the bit depth is less than 16, then\n\t * only the lower byte is used.\n\t */\n\n\tif (16 == pngPtr->bitDepth) {\n\t    pngPtr->transVal[0] = buffer[0];\n\t    pngPtr->transVal[1] = buffer[1];\n\t} else {\n\t    pngPtr->transVal[0] = buffer[1];\n\t}\n\tpngPtr->useTRNS = true;\n\tbreak;\n\n    case PNG_COLOR_RGB:\n\t/*\n\t * TrueColor uses a single RRGGBB triplet.\n\t */\n\n\tif (chunkSz != 6) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid tRNS chunk size - must 6 bytes for RGB\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_TRNS\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * According to the PNG specs, if the bit depth is less than 16, then\n\t * only the lower byte is used. But the tRNS chunk still contains two\n\t * bytes per channel.\n\t */\n\n\tif (16 == pngPtr->bitDepth) {\n\t    memcpy(pngPtr->transVal, buffer, 6);\n\t} else {\n\t    pngPtr->transVal[0] = buffer[1];\n\t    pngPtr->transVal[1] = buffer[3];\n\t    pngPtr->transVal[2] = buffer[5];\n\t}\n\tpngPtr->useTRNS = true;\n\tbreak;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadPHYS --\n *\n *\tThis function reads the PHYS (physical size) chunk data from\n *\tthe PNG file and populates the fields in the PNGImage\n *\tstructure.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or the PHYS chunk is\n *\tinvalid.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadPHYS(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    int chunkSz,\n    unsigned long crc)\n{\n    unsigned long PPUx, PPUy;\n    char unitSpecifier;\n\n    /*\n     * Check chunk size equal 9 bytes\n     */\n\n    if (chunkSz != 9) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"invalid physical chunk size\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_PHYS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Read the chunk data\n     * 4 bytes: Pixels per unit, x axis\n     * 4 bytes: Pixels per unit, y axis\n     * 1 byte: unit specifier\n     */\n\n    if (ReadInt32(interp, pngPtr, &PPUx, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    if (ReadInt32(interp, pngPtr, &PPUy, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    if (ReadData(interp, pngPtr, (unsigned char *)&unitSpecifier, 1, &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if ( PPUx > 2147483647 || PPUy > 2147483647\n\t    || unitSpecifier > 1 ) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"invalid physical size value\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_PHYS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (PPUx > 0) {\n\tpngPtr->aspect = ((double) PPUy) / ((double) PPUx);\n    }\n    if (1 == unitSpecifier) {\n\tpngPtr->DPI = ((double) PPUx) * 0.0254;\n    }\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Paeth --\n *\n *\tUtility function for applying the Paeth filter to a pixel. The Paeth\n *\tfilter is a linear function of the pixel to be filtered and the pixels\n *\tto the left, above, and above-left of the pixel to be unfiltered.\n *\n * Results:\n *\tResult of the Paeth function for the left, above, and above-left\n *\tpixels.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline unsigned char\nPaeth(\n    int a,\n    int b,\n    int c)\n{\n    int pa = abs(b - c);\n    int pb = abs(a - c);\n    int pc = abs(a + b - c - c);\n\n    if ((pa <= pb) && (pa <= pc)) {\n\treturn (unsigned char) a;\n    }\n\n    if (pb <= pc) {\n\treturn (unsigned char) b;\n    }\n\n    return (unsigned char) c;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UnfilterLine --\n *\n *\tApplies the filter algorithm specified in first byte of a line to the\n *\tline of pixels being read from a PNG image.\n *\n *\tPNG specifies four filter algorithms (Sub, Up, Average, and Paeth)\n *\tthat combine a pixel's value with those of other pixels in the same\n *\tand/or previous lines. Filtering is intended to make an image more\n *\tcompressible.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the filter type is not recognized.\n *\n * Side effects:\n *\tPixel data in thisLineObj are modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nUnfilterLine(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr)\n{\n    unsigned char *thisLine =\n\t    Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, (Tcl_Size *)NULL);\n    unsigned char *lastLine =\n\t    Tcl_GetByteArrayFromObj(pngPtr->lastLineObj, (Tcl_Size *)NULL);\n\n#define\tPNG_FILTER_NONE\t\t0\n#define\tPNG_FILTER_SUB\t\t1\n#define\tPNG_FILTER_UP\t\t2\n#define\tPNG_FILTER_AVG\t\t3\n#define\tPNG_FILTER_PAETH\t4\n\n    switch (*thisLine) {\n    case PNG_FILTER_NONE:\t/* Nothing to do */\n\tbreak;\n    case PNG_FILTER_SUB: {\t/* Sub(x) = Raw(x) - Raw(x-bpp) */\n\tunsigned char *rawBpp = thisLine + 1;\n\tunsigned char *raw = rawBpp + pngPtr->bytesPerPixel;\n\tunsigned char *end = thisLine + pngPtr->phaseSize;\n\n\twhile (raw < end) {\n\t    *raw++ += *rawBpp++;\n\t}\n\tbreak;\n    }\n    case PNG_FILTER_UP:\t\t/* Up(x) = Raw(x) - Prior(x) */\n\tif (pngPtr->currentLine > startLine[pngPtr->phase]) {\n\t    unsigned char *prior = lastLine + 1;\n\t    unsigned char *raw = thisLine + 1;\n\t    unsigned char *end = thisLine + pngPtr->phaseSize;\n\n\t    while (raw < end) {\n\t\t*raw++ += *prior++;\n\t    }\n\t}\n\tbreak;\n    case PNG_FILTER_AVG:\n\t/* Avg(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2) */\n\tif (pngPtr->currentLine > startLine[pngPtr->phase]) {\n\t    unsigned char *prior = lastLine + 1;\n\t    unsigned char *rawBpp = thisLine + 1;\n\t    unsigned char *raw = rawBpp;\n\t    unsigned char *end = thisLine + pngPtr->phaseSize;\n\t    unsigned char *end2 = raw + pngPtr->bytesPerPixel;\n\n\t    while ((raw < end2) && (raw < end)) {\n\t\t*raw++ += *prior++ / 2;\n\t    }\n\n\t    while (raw < end) {\n\t\t*raw++ += (unsigned char)\n\t\t\t(((int) *rawBpp++ + (int) *prior++) / 2);\n\t    }\n\t} else {\n\t    unsigned char *rawBpp = thisLine + 1;\n\t    unsigned char *raw = rawBpp + pngPtr->bytesPerPixel;\n\t    unsigned char *end = thisLine + pngPtr->phaseSize;\n\n\t    while (raw < end) {\n\t\t*raw++ += *rawBpp++ / 2;\n\t    }\n\t}\n\tbreak;\n    case PNG_FILTER_PAETH:\n\t/* Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) */\n\tif (pngPtr->currentLine > startLine[pngPtr->phase]) {\n\t    unsigned char *priorBpp = lastLine + 1;\n\t    unsigned char *prior = priorBpp;\n\t    unsigned char *rawBpp = thisLine + 1;\n\t    unsigned char *raw = rawBpp;\n\t    unsigned char *end = thisLine + pngPtr->phaseSize;\n\t    unsigned char *end2 = rawBpp + pngPtr->bytesPerPixel;\n\n\t    while ((raw < end) && (raw < end2)) {\n\t\t*raw++ += *prior++;\n\t    }\n\n\t    while (raw < end) {\n\t\t*raw++ += Paeth(*rawBpp++, *prior++, *priorBpp++);\n\t    }\n\t} else {\n\t    unsigned char *rawBpp = thisLine + 1;\n\t    unsigned char *raw = rawBpp + pngPtr->bytesPerPixel;\n\t    unsigned char *end = thisLine + pngPtr->phaseSize;\n\n\t    while (raw < end) {\n\t\t*raw++ += *rawBpp++;\n\t    }\n\t}\n\tbreak;\n    default:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"invalid filter type %d\", *thisLine));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_FILTER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DecodeLine --\n *\n *\tUnfilters a line of pixels from the PNG source data and decodes the\n *\tdata into the Tk_PhotoImageBlock for later copying into the Tk image.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the filter type is not recognized.\n *\n * Side effects:\n *\tPixel data in thisLine and block are modified and state information\n *\tupdated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDecodeLine(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr)\n{\n    unsigned char *pixelPtr = pngPtr->block.pixelPtr;\n    int colNum = 0;\t\t/* Current pixel column */\n    unsigned char chan = 0;\t/* Current channel (0..3) = (R, G, B, A) */\n    unsigned char readByte = 0;\t/* Current scan line byte */\n    int haveBits = 0;\t\t/* Number of bits remaining in current byte */\n    unsigned char pixBits = 0;\t/* Extracted bits for current channel */\n    int shifts = 0;\t\t/* Number of channels extracted from byte */\n    int offset = 0;\t\t/* Current offset into pixelPtr */\n    int colStep = 1;\t\t/* Column increment each pass */\n    int pixStep = 0;\t\t/* extra pixelPtr increment each pass */\n    unsigned char lastPixel[6];\n    unsigned char *p = Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, (Tcl_Size *)NULL);\n\n    p++;\n    if (UnfilterLine(interp, pngPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    if (pngPtr->currentLine >= pngPtr->block.height) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"PNG image data overflow\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"DATA_OVERFLOW\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n\n    if (pngPtr->interlace) {\n\tswitch (pngPtr->phase) {\n\tcase 1:\t\t\t/* Phase 1: */\n\t    colStep = 8;\t/* 1 pixel per block of 8 per line */\n\t    break;\t\t/* Start at column 0 */\n\tcase 2:\t\t\t/* Phase 2: */\n\t    colStep = 8;\t/* 1 pixels per block of 8 per line */\n\t    colNum = 4;\t\t/* Start at column 4 */\n\t    break;\n\tcase 3:\t\t\t/* Phase 3: */\n\t    colStep = 4;\t/* 2 pixels per block of 8 per line */\n\t    break;\t\t/* Start at column 0 */\n\tcase 4:\t\t\t/* Phase 4: */\n\t    colStep = 4;\t/* 2 pixels per block of 8 per line */\n\t    colNum = 2;\t\t/* Start at column 2 */\n\t    break;\n\tcase 5:\t\t\t/* Phase 5: */\n\t    colStep = 2;\t/* 4 pixels per block of 8 per line */\n\t    break;\t\t/* Start at column 0 */\n\tcase 6:\t\t\t/* Phase 6: */\n\t    colStep = 2;\t/* 4 pixels per block of 8 per line */\n\t    colNum = 1;\t\t/* Start at column 1 */\n\t    break;\n\t\t\t\t/* Phase 7: */\n\t\t\t\t/* 8 pixels per block of 8 per line */\n\t\t\t\t/* Start at column 0 */\n\t}\n    }\n\n    /*\n     * Calculate offset into pixelPtr for the first pixel of the line.\n     */\n\n    offset = pngPtr->currentLine * pngPtr->block.pitch;\n\n    /*\n     * Adjust up for the starting pixel of the line.\n     */\n\n    offset += colNum * pngPtr->block.pixelSize;\n\n    /*\n     * Calculate the extra number of bytes to skip between columns.\n     */\n\n    pixStep = (colStep - 1) * pngPtr->block.pixelSize;\n\n    for ( ; colNum < pngPtr->block.width ; colNum += colStep) {\n\tif (haveBits < (pngPtr->bitDepth * pngPtr->numChannels)) {\n\t    haveBits = 0;\n\t}\n\n\tfor (chan = 0 ; chan < pngPtr->numChannels ; chan++) {\n\t    if (!haveBits) {\n\t\tshifts = 0;\n\t\treadByte = *p++;\n\t\thaveBits += 8;\n\t    }\n\n\t    if (16 == pngPtr->bitDepth) {\n\t\tpngPtr->block.pixelPtr[offset++] = readByte;\n\n\t\tif (pngPtr->useTRNS) {\n\t\t    lastPixel[chan * 2] = readByte;\n\t\t}\n\n\t\treadByte = *p++;\n\n\t\tif (pngPtr->useTRNS) {\n\t\t    lastPixel[(chan * 2) + 1] = readByte;\n\t\t}\n\n\t\tpngPtr->block.pixelPtr[offset++] = readByte;\n\n\t\thaveBits = 0;\n\t\tcontinue;\n\t    }\n\n\t    switch (pngPtr->bitDepth) {\n\t    case 1:\n\t\tpixBits = (unsigned char)((readByte >> (7-shifts)) & 0x01);\n\t\tbreak;\n\t    case 2:\n\t\tpixBits = (unsigned char)((readByte >> (6-shifts*2)) & 0x03);\n\t\tbreak;\n\t    case 4:\n\t\tpixBits = (unsigned char)((readByte >> (4-shifts*4)) & 0x0f);\n\t\tbreak;\n\t    case 8:\n\t\tpixBits = readByte;\n\t\tbreak;\n\t    }\n\n\t    if (PNG_COLOR_PLTE == pngPtr->colorType) {\n\t\tpixelPtr[offset++] = pngPtr->palette[pixBits].red;\n\t\tpixelPtr[offset++] = pngPtr->palette[pixBits].green;\n\t\tpixelPtr[offset++] = pngPtr->palette[pixBits].blue;\n\t\tpixelPtr[offset++] = pngPtr->palette[pixBits].alpha;\n\t\tchan += 2;\n\t    } else {\n\t\tpixelPtr[offset++] = (unsigned char)\n\t\t\t(pixBits * pngPtr->bitScale);\n\n\t\tif (pngPtr->useTRNS) {\n\t\t    lastPixel[chan] = pixBits;\n\t\t}\n\t    }\n\n\t    haveBits -= pngPtr->bitDepth;\n\t    shifts++;\n\t}\n\n\t/*\n\t * Apply boolean transparency via tRNS data if necessary (where\n\t * necessary means a tRNS chunk was provided and we're not using an\n\t * alpha channel or indexed alpha).\n\t */\n\n\tif ((PNG_COLOR_PLTE != pngPtr->colorType) &&\n\t\t!(pngPtr->colorType & PNG_COLOR_ALPHA)) {\n\t    unsigned char alpha;\n\n\t    if (pngPtr->useTRNS) {\n\t\tif (memcmp(lastPixel, pngPtr->transVal,\n\t\t\tpngPtr->bytesPerPixel) == 0) {\n\t\t    alpha = 0x00;\n\t\t} else {\n\t\t    alpha = 0xff;\n\t\t}\n\t    } else {\n\t\talpha = 0xff;\n\t    }\n\n\t    pixelPtr[offset++] = alpha;\n\n\t    if (16 == pngPtr->bitDepth) {\n\t\tpixelPtr[offset++] = alpha;\n\t    }\n\t}\n\n\toffset += pixStep;\n    }\n\n    if (pngPtr->interlace) {\n\t/* Skip lines */\n\n\tswitch (pngPtr->phase) {\n\tcase 1: case 2: case 3:\n\t    pngPtr->currentLine += 8;\n\t    break;\n\tcase 4: case 5:\n\t    pngPtr->currentLine += 4;\n\t    break;\n\tcase 6: case 7:\n\t    pngPtr->currentLine += 2;\n\t    break;\n\t}\n\n\t/*\n\t * Start the next phase if there are no more lines to do.\n\t */\n\n\tif (pngPtr->currentLine >= pngPtr->block.height) {\n\t    unsigned long pixels = 0;\n\n\t    while ((!pixels || (pngPtr->currentLine >= pngPtr->block.height))\n\t\t    && (pngPtr->phase < 7)) {\n\t\tpngPtr->phase++;\n\n\t\tswitch (pngPtr->phase) {\n\t\tcase 2:\n\t\t    pixels = (pngPtr->block.width + 3) >> 3;\n\t\t    pngPtr->currentLine = 0;\n\t\t    break;\n\t\tcase 3:\n\t\t    pixels = (pngPtr->block.width + 3) >> 2;\n\t\t    pngPtr->currentLine = 4;\n\t\t    break;\n\t\tcase 4:\n\t\t    pixels = (pngPtr->block.width + 1) >> 2;\n\t\t    pngPtr->currentLine = 0;\n\t\t    break;\n\t\tcase 5:\n\t\t    pixels = (pngPtr->block.width + 1) >> 1;\n\t\t    pngPtr->currentLine = 2;\n\t\t    break;\n\t\tcase 6:\n\t\t    pixels = pngPtr->block.width >> 1;\n\t\t    pngPtr->currentLine = 0;\n\t\t    break;\n\t\tcase 7:\n\t\t    pngPtr->currentLine = 1;\n\t\t    pixels = pngPtr->block.width;\n\t\t    break;\n\t\t}\n\t    }\n\n\t    if (16 == pngPtr->bitDepth) {\n\t\tpngPtr->phaseSize = 1 + (pngPtr->numChannels * pixels * 2);\n\t    } else {\n\t\tpngPtr->phaseSize = 1 + ((pngPtr->numChannels * pixels *\n\t\t\tpngPtr->bitDepth + 7) >> 3);\n\t    }\n\t}\n    } else {\n\tpngPtr->currentLine++;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadIDAT --\n *\n *\tThis function reads the IDAT (pixel data) chunk from the PNG file to\n *\tbuild the image. It will continue reading until all IDAT chunks have\n *\tbeen processed or an error occurs.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or an IDAT chunk is\n *\tinvalid.\n *\n * Side effects:\n *\tThe access position in f advances. Memory may be allocated by zlib\n *\tthrough PNGZAlloc.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadIDAT(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    int chunkSz,\n    unsigned long crc)\n{\n    /*\n     * Process IDAT contents until there is no more in this chunk.\n     */\n\n    while (chunkSz && !Tcl_ZlibStreamEof(pngPtr->stream)) {\n\tTcl_Size len1, len2;\n\n\t/*\n\t * Read another block of input into the zlib stream if data remains.\n\t */\n\n\tif (chunkSz) {\n\t    Tcl_Obj *inputObj = NULL;\n\t    int blockSz = PNG_MIN(chunkSz, PNG_BLOCK_SZ);\n\t    unsigned char *inputPtr = NULL;\n\n\t    /*\n\t     * Check for end of zlib stream.\n\t     */\n\n\t    if (Tcl_ZlibStreamEof(pngPtr->stream)) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"extra data after end of zlib stream\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EXTRA_DATA\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    inputObj = Tcl_NewObj();\n\t    Tcl_IncrRefCount(inputObj);\n\t    inputPtr = Tcl_SetByteArrayLength(inputObj, blockSz);\n\n\t    /*\n\t     * Read the next bit of IDAT chunk data, up to read buffer size.\n\t     */\n\n\t    if (ReadData(interp, pngPtr, inputPtr, blockSz,\n\t\t    &crc) == TCL_ERROR) {\n\t\tTcl_DecrRefCount(inputObj);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    chunkSz -= blockSz;\n\n\t    Tcl_ZlibStreamPut(pngPtr->stream, inputObj, TCL_ZLIB_NO_FLUSH);\n\t    Tcl_DecrRefCount(inputObj);\n\t}\n\n\t/*\n\t * Inflate, processing each output buffer's worth as a line of pixels,\n\t * until we cannot fill the buffer any more.\n\t */\n\n    getNextLine:\n\tTcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len1);\n\tif (Tcl_ZlibStreamGet(pngPtr->stream, pngPtr->thisLineObj,\n\t\tpngPtr->phaseSize - len1) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len2);\n\n\tif (len2 == (Tcl_Size)pngPtr->phaseSize) {\n\t    if (pngPtr->phase > 7) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"extra data after final scan line of final phase\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EXTRA_DATA\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (DecodeLine(interp, pngPtr) == TCL_ERROR) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Swap the current/last lines so that we always have the last\n\t     * line processed available, which is necessary for filtering.\n\t     */\n\n\t    {\n\t\tTcl_Obj *temp = pngPtr->lastLineObj;\n\n\t\tpngPtr->lastLineObj = pngPtr->thisLineObj;\n\t\tpngPtr->thisLineObj = temp;\n\t    }\n\t    Tcl_SetByteArrayLength(pngPtr->thisLineObj, 0);\n\n\t    /*\n\t     * Try to read another line of pixels out of the buffer\n\t     * immediately, but don't allow write past end of block.\n\t     */\n\n\t    if (pngPtr->currentLine < pngPtr->block.height) {\n\t\tgoto getNextLine;\n\t    }\n\n\t}\n\n\t/*\n\t * Got less than a whole buffer-load of pixels. Either we're going to\n\t * be getting more data from the next IDAT, or we've done what we can\n\t * here.\n\t */\n    }\n\n    /*\n     * Ensure that if we've got to the end of the compressed data, we've\n     * also got to the end of the compressed stream. This sanity check is\n     * enforced by most PNG readers.\n     */\n\n    if (chunkSz != 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"compressed data after stream finalize in PNG data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EXTRA_DATA\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return CheckCRC(interp, pngPtr, crc);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ApplyAlpha --\n *\n *\tApplies an overall alpha value to a complete image that has been read.\n *\tThis alpha value is specified using the -format option to [image\n *\tcreate photo].\n *\n * Results:\n *\tN/A\n *\n * Side effects:\n *\tThe access position in f may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nApplyAlpha(\n    PNGImage *pngPtr)\n{\n    if (pngPtr->alpha != 1.0) {\n\tunsigned char *p = pngPtr->block.pixelPtr;\n\tunsigned char *endPtr = p + pngPtr->blockLen;\n\tint offset = pngPtr->block.offset[3];\n\n\tp += offset;\n\n\tif (16 == pngPtr->bitDepth) {\n\t    unsigned int channel;\n\n\t    while (p < endPtr) {\n\t\tchannel = (unsigned int)\n\t\t\t(((p[0] << 8) | p[1]) * pngPtr->alpha);\n\n\t\t*p++ = (unsigned char) (channel >> 8);\n\t\t*p++ = (unsigned char) (channel & 0xff);\n\n\t\tp += offset;\n\t    }\n\t} else {\n\t    while (p < endPtr) {\n\t\tp[0] = (unsigned char) (pngPtr->alpha * p[0]);\n\t\tp += 1 + offset;\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseFormat --\n *\n *\tThis function parses the -format string that can be specified to the\n *\t[image create photo] command to extract options for postprocessing of\n *\tloaded images. Currently, this just allows specifying and applying an\n *\toverall alpha value to the loaded image (for example, to make it\n *\tentirely 50% as transparent as the actual image file).\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the format specification is invalid.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nParseFormat(\n    Tcl_Interp *interp,\n    Tcl_Obj *fmtObj,\n    PNGImage *pngPtr)\n{\n    Tcl_Obj **objv = NULL;\n    Tcl_Size objc = 0;\n    static const char *const fmtOptions[] = {\n\t\"-alpha\", NULL\n    };\n    enum fmtOptionsEnum {\n\tOPT_ALPHA\n    };\n\n    /*\n     * Extract elements of format specification as a list.\n     */\n\n    if (fmtObj &&\n\t    Tcl_ListObjGetElements(interp, fmtObj, &objc, &objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    for (; objc>0 ; objc--, objv++) {\n\tint optIndex;\n\n\t/*\n\t * Ignore the \"png\" part of the format specification.\n\t */\n\n\tif (!strcasecmp(Tcl_GetString(objv[0]), \"png\")) {\n\t    continue;\n\t}\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions,\n\t\tsizeof(char *), \"option\", 0, &optIndex) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (objc < 2) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"value\");\n\t    return TCL_ERROR;\n\t}\n\n\tobjc--;\n\tobjv++;\n\n\tswitch ((enum fmtOptionsEnum) optIndex) {\n\tcase OPT_ALPHA:\n\t    if (Tcl_GetDoubleFromObj(interp, objv[0],\n\t\t    &pngPtr->alpha) == TCL_ERROR) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if ((pngPtr->alpha < 0.0) || (pngPtr->alpha > 1.0)) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"-alpha value must be between 0.0 and 1.0\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_ALPHA\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DecodePNG --\n *\n *\tThis function handles the entirety of reading a PNG file (or data)\n *\tfrom the first byte to the last.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O error occurs or any problems are\n *\tdetected in the PNG file.\n *\n * Side effects:\n *\tThe access position in f advances. Memory may be allocated and image\n *\tdimensions and contents may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDecodePNG(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    PNGImage *pngPtr,\t\t/* PNG image information record. */\n    Tcl_Obj *fmtObj,\t\t/* User-specified format object, or NULL. */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY)\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n{\n    unsigned long chunkType;\n    int result;\n    Tcl_Size chunkSz;\n    unsigned long crc;\n\n    /*\n     * Parse the PNG signature and IHDR (header) chunk.\n     */\n\n    if (ReadIHDR(interp, pngPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Extract alpha value from -format object, if specified.\n     */\n\n    if (ParseFormat(interp, fmtObj, pngPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * The next chunk may either be a PLTE (Palette) chunk or the first of at\n     * least one IDAT (data) chunks. It could also be one of a number of\n     * ancillary chunks, but those are skipped for us by the switch in\n     * ReadChunkHeader().\n     *\n     * PLTE is mandatory for color type 3 and forbidden for 2 and 6\n     */\n\n    if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t    &crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Physical header may be present here so try to parse it\n     */\n\n    if (CHUNK_pHYs == chunkType) {\n\t/*\n\t * Finish parsing the PHYS chunk.\n\t */\n\n\tif (ReadPHYS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Begin the next chunk.\n\t */\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (CHUNK_PLTE == chunkType) {\n\t/*\n\t * Finish parsing the PLTE chunk.\n\t */\n\n\tif (ReadPLTE(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Begin the next chunk.\n\t */\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    } else if (PNG_COLOR_PLTE == pngPtr->colorType) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"PLTE chunk required for indexed color\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"NEED_PLTE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * The next chunk may be a tRNS (palette transparency) chunk, depending on\n     * the color type. It must come after the PLTE chunk and before the IDAT\n     * chunk, but can be present if there is no PLTE chunk because it can be\n     * used for Grayscale and TrueColor in lieu of an alpha channel.\n     */\n\n    if (CHUNK_tRNS == chunkType) {\n\t/*\n\t * Finish parsing the tRNS chunk.\n\t */\n\n\tif (ReadTRNS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Begin the next chunk.\n\t */\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Physical header may be present here so try to parse it\n     */\n\n    if (CHUNK_pHYs == chunkType) {\n\t/*\n\t * Finish parsing the PHYS chunk.\n\t */\n\n\tif (ReadPHYS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Begin the next chunk.\n\t */\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Other ancillary chunk types could appear here, but for now we're only\n     * interested in IDAT. The others should have been skipped.\n     */\n\n    if (chunkType != CHUNK_IDAT) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"at least one IDAT chunk is required\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"NEED_IDAT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Expand the photo size (if not set by the user) to provide enough space\n     * for the image being parsed. It does not matter if width or height wrap\n     * to negative here: Tk will not shrink the image.\n     */\n\n    if (Tk_PhotoExpand(interp, imageHandle, destX + width,\n\t    destY + height) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * A scan line consists of one byte for a filter type, plus the number of\n     * bits per color sample times the number of color samples per pixel.\n     */\n\n    if (pngPtr->block.width > ((INT_MAX - 1) / (pngPtr->numChannels * 2))) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"line size is out of supported range on this architecture\",\n\t\t-1));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"LINE_SIZE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (16 == pngPtr->bitDepth) {\n\tpngPtr->lineSize = 1 + (pngPtr->numChannels * pngPtr->block.width*2);\n    } else {\n\tpngPtr->lineSize = 1 + ((pngPtr->numChannels * pngPtr->block.width) /\n\t\t(8 / pngPtr->bitDepth));\n\tif (pngPtr->block.width % (8 / pngPtr->bitDepth)) {\n\t    pngPtr->lineSize++;\n\t}\n    }\n\n    /*\n     * Allocate space for decoding the scan lines.\n     */\n\n    pngPtr->lastLineObj = Tcl_NewObj();\n    Tcl_IncrRefCount(pngPtr->lastLineObj);\n    pngPtr->thisLineObj = Tcl_NewObj();\n    Tcl_IncrRefCount(pngPtr->thisLineObj);\n\n    pngPtr->block.pixelPtr = (unsigned char *)Tcl_AttemptAlloc(pngPtr->blockLen);\n    if (!pngPtr->block.pixelPtr) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"memory allocation failed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Determine size of the first phase if interlaced. Phase size should\n     * always be <= line size, so probably not necessary to check for\n     * arithmetic overflow here: should be covered by line size check.\n     */\n\n    if (pngPtr->interlace) {\n\t/*\n\t * Only one pixel per block of 8 per line in the first phase.\n\t */\n\n\tunsigned int pixels = (pngPtr->block.width + 7) >> 3;\n\n\tpngPtr->phase = 1;\n\tif (16 == pngPtr->bitDepth) {\n\t    pngPtr->phaseSize = 1 + pngPtr->numChannels*pixels*2;\n\t} else {\n\t    pngPtr->phaseSize = 1 +\n\t\t    ((pngPtr->numChannels*pixels*pngPtr->bitDepth + 7) >> 3);\n\t}\n    } else {\n\tpngPtr->phaseSize = pngPtr->lineSize;\n    }\n\n    /*\n     * All of the IDAT (data) chunks must be consecutive.\n     */\n\n    while (CHUNK_IDAT == chunkType) {\n\tif (ReadIDAT(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Ensure that we've got to the end of the compressed stream now that\n     * there are no more IDAT segments. This sanity check is enforced by most\n     * PNG readers.\n     */\n\n    if (!Tcl_ZlibStreamEof(pngPtr->stream)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"unfinalized data stream in PNG data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"EXTRA_DATA\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Now skip the remaining chunks which we're also not interested in.\n     */\n\n    while (CHUNK_IEND != chunkType) {\n\tif (SkipChunk(interp, pngPtr, chunkSz, crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType,\n\t\t&crc) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Got the IEND (end of image) chunk. Do some final checks...\n     */\n\n    if (chunkSz) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"IEND chunk contents must be empty\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_IEND\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Check the CRC on the IEND chunk.\n     */\n\n    if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * TODO: verify that nothing else comes after the IEND chunk, or do we\n     * really care?\n     */\n\n#if 0\n    if (ReadData(interp, pngPtr, &c, 1, NULL) != TCL_ERROR) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"extra data following IEND chunk\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"BAD_IEND\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n#endif\n\n    /*\n     * Apply overall image alpha if specified.\n     */\n\n    ApplyAlpha(pngPtr);\n\n    /*\n     * Copy the decoded image block into the Tk photo image.\n     */\n\n    pngPtr->block.pixelPtr += srcX * pngPtr->block.pixelSize + srcY * pngPtr->block.pitch;\n    result = Tk_PhotoPutBlock(interp, imageHandle, &pngPtr->block, destX, destY,\n\t    width, height, TK_PHOTO_COMPOSITE_SET);\n    pngPtr->block.pixelPtr -= srcX * pngPtr->block.pixelSize + srcY * pngPtr->block.pitch;\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileMatchPNG --\n *\n *\tThis function is invoked by the photo image type to see if a file\n *\tcontains image data in PNG format.\n *\n * Results:\n *\tThe return value is 1 if the first characters in file f look like PNG\n *\tdata, and 0 otherwise.\n *\n * Side effects:\n *\tThe access position in f may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileMatchPNG(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    TCL_UNUSED(const char *),\t/* The name of the image file. */\n    TCL_UNUSED(Tcl_Obj *),\t/* User-specified format object, or NULL. */\n    TCL_UNUSED(Tcl_Obj *),\t/* metadata input, may be NULL */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here if the file is a valid raw GIF file. */\n    TCL_UNUSED(Tcl_Obj *))\t/* metadata return dict, may be NULL */\n{\n    PNGImage png;\n    int match = 0;\n\n    InitPNGImage(NULL, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE);\n\n    if (ReadIHDR(interp, &png) == TCL_OK) {\n\t*widthPtr = png.block.width;\n\t*heightPtr = png.block.height;\n\tmatch = 1;\n    }\n\n    CleanupPNGImage(&png);\n\n    return match;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileReadPNG --\n *\n *\tThis function is called by the photo image type to read PNG format\n *\tdata from a file and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tThe access position in file f is changed, and new data is added to the\n *\timage given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileReadPNG(\n    Tcl_Interp* interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    TCL_UNUSED(const char*),\t/* The name of the image file. */\n    Tcl_Obj *fmtObj,\t\t/* User-specified format object, or NULL. */\n    TCL_UNUSED(Tcl_Obj*),\t/* metadata input, may be NULL */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY,\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n    Tcl_Obj* metadataOutObj)\t/* metadata return dict, may be NULL */\n{\n    PNGImage png;\n    int result = TCL_ERROR;\n\n    result = InitPNGImage(interp, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE);\n\n    if (TCL_OK == result) {\n\tresult = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY, width, height, srcX, srcY);\n    }\n\n    if (TCL_OK == result && metadataOutObj != NULL && png.DPI != -1) {\n\tresult = Tcl_DictObjPut(NULL, metadataOutObj,\n\t\tTcl_NewStringObj(\"DPI\",-1),\n\t\tTcl_NewDoubleObj(png.DPI));\n    }\n\n    if (TCL_OK == result && metadataOutObj != NULL && png.aspect != -1) {\n\tresult = Tcl_DictObjPut(NULL, metadataOutObj,\n\t\tTcl_NewStringObj(\"aspect\",-1),\n\t\tTcl_NewDoubleObj(png.aspect));\n    }\n\n    CleanupPNGImage(&png);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringMatchPNG --\n *\n *\tThis function is invoked by the photo image type to see if an object\n *\tcontains image data in PNG format.\n *\n * Results:\n *\tThe return value is 1 if the first characters in the data are like PNG\n *\tdata, and 0 otherwise.\n *\n * Side effects:\n *\tThe size of the image is placed in widthPre and heightPtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringMatchPNG(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Obj *pObjData,\t\t/* the object containing the image data */\n    TCL_UNUSED(Tcl_Obj *),\t/* the image format object, or NULL */\n    TCL_UNUSED(Tcl_Obj *),\t/* metadata input, may be NULL */\n    int *widthPtr,\t\t/* where to put the string width */\n    int *heightPtr,\t\t/* where to put the string height */\n    TCL_UNUSED(Tcl_Obj *))\t/* metadata return dict, may be NULL */\n{\n    PNGImage png;\n    int match = 0;\n\n    InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE);\n\n    png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen);\n\n    if (png.strDataBuf != NULL && ReadIHDR(interp, &png) == TCL_OK) {\n\t*widthPtr = png.block.width;\n\t*heightPtr = png.block.height;\n\tmatch = 1;\n    }\n\n    CleanupPNGImage(&png);\n    return match;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringReadPNG --\n *\n *\tThis function is called by the photo image type to read PNG format\n *\tdata from an object and give it to the photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNew data is added to the image given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringReadPNG(\n    Tcl_Interp* interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Obj *pObjData,\n    Tcl_Obj *fmtObj,\t\t/* User-specified format object, or NULL. */\n    TCL_UNUSED(Tcl_Obj*),\t/* metadata input, may be NULL */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY,\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n    Tcl_Obj *metadataOutObj)\t/* metadata return dict, may be NULL */\n{\n    PNGImage png;\n    int result = TCL_ERROR;\n\n    result = InitPNGImage(interp, &png, NULL, pObjData,\n\t    TCL_ZLIB_STREAM_INFLATE);\n\n    if (TCL_OK == result) {\n\tresult = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY, width, height, srcX, srcY);\n    }\n\n    if (TCL_OK == result && metadataOutObj != NULL && png.DPI != -1) {\n\tresult = Tcl_DictObjPut(NULL, metadataOutObj,\n\t\tTcl_NewStringObj(\"DPI\",-1),\n\t\tTcl_NewDoubleObj(png.DPI));\n    }\n\n    if (TCL_OK == result && metadataOutObj != NULL && png.aspect != -1) {\n\tresult = Tcl_DictObjPut(NULL, metadataOutObj,\n\t\tTcl_NewStringObj(\"aspect\",-1),\n\t\tTcl_NewDoubleObj(png.aspect));\n    }\n\n    CleanupPNGImage(&png);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteData --\n *\n *\tThis function writes a bytes from a buffer out to the PNG image.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tFile or buffer will be modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWriteData(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    const unsigned char *srcPtr,\n    Tcl_Size srcSz,\n    unsigned long *crcPtr)\n{\n    if (!srcPtr || srcSz <= 0) {\n\treturn TCL_OK;\n    }\n\n    if (crcPtr) {\n\t*crcPtr = Tcl_ZlibCRC32(*crcPtr, srcPtr, srcSz);\n    }\n\n    /*\n     * TODO: is Tcl_AppendObjToObj faster here? i.e., does Tcl join the\n     * objects immediately or store them in a multi-object rep?\n     */\n\n    if (pngPtr->objDataPtr) {\n\tTcl_Size objSz;\n\tunsigned char *destPtr;\n\n\tTcl_GetByteArrayFromObj(pngPtr->objDataPtr, &objSz);\n\n\tif (objSz + srcSz > INT_MAX) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"image too large to store completely in byte array\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"TOO_LARGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tdestPtr = Tcl_SetByteArrayLength(pngPtr->objDataPtr, objSz + srcSz);\n\n\tif (!destPtr) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"memory allocation failed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tmemcpy(destPtr+objSz, srcPtr, srcSz);\n    } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) == TCL_IO_FAILURE) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"write to channel failed: %s\", Tcl_PosixError(interp)));\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\nstatic inline int\nWriteByte(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned char c,\n    unsigned long *crcPtr)\n{\n    return WriteData(interp, pngPtr, &c, 1, crcPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * LongToInt32 --\n *\n *\tThis function transforms to a 32-bit integer value as\n *\tfour bytes in network byte order.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tBuffer will be modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline void\nLongToInt32(\n    unsigned long l,\n    unsigned char *pc)\n{\n    pc[0] = (unsigned char) ((l & 0xff000000) >> 24);\n    pc[1] = (unsigned char) ((l & 0x00ff0000) >> 16);\n    pc[2] = (unsigned char) ((l & 0x0000ff00) >> 8);\n    pc[3] = (unsigned char) ((l & 0x000000ff) >> 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteInt32 --\n *\n *\tThis function writes a 32-bit integer value out to the PNG image as\n *\tfour bytes in network byte order.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tFile or buffer will be modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline int\nWriteInt32(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned long l,\n    unsigned long *crcPtr)\n{\n    unsigned char pc[4];\n    LongToInt32(l,pc);\n    return WriteData(interp, pngPtr, pc, 4, crcPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteChunk --\n *\n *\tWrites a complete chunk to the PNG image, including chunk type,\n *\tlength, contents, and CRC.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic inline int\nWriteChunk(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    unsigned long chunkType,\n    const unsigned char *dataPtr,\n    Tcl_Size dataSize)\n{\n    unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0);\n    int result = TCL_OK;\n\n    /*\n     * Write the length field for the chunk.\n     */\n\n    result = WriteInt32(interp, pngPtr, dataSize, NULL);\n\n    /*\n     * Write the Chunk Type.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, chunkType, &crc);\n    }\n\n    /*\n     * Write the contents (if any).\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteData(interp, pngPtr, dataPtr, dataSize, &crc);\n    }\n\n    /*\n     * Write out the CRC at the end of the chunk.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, crc, NULL);\n    }\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteIHDR --\n *\n *\tThis function writes the PNG header at the beginning of a PNG file,\n *\twhich includes information such as dimensions and color type.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tFile or buffer will be modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWriteIHDR(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0);\n    int result = TCL_OK;\n\n    /*\n     * The IHDR (header) chunk has a fixed size of 13 bytes.\n     */\n\n    result = WriteInt32(interp, pngPtr, 13, NULL);\n\n    /*\n     * Write the IHDR Chunk Type.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, CHUNK_IHDR, &crc);\n    }\n\n    /*\n     * Write the image width, height.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, (unsigned long) blockPtr->width,\n\t\t&crc);\n    }\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, (unsigned long) blockPtr->height,\n\t\t&crc);\n    }\n\n    /*\n     * Write bit depth. Although the PNG format supports 16 bits per channel,\n     * Tk supports only 8 in the internal representation, which blockPtr\n     * points to.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteByte(interp, pngPtr, 8, &crc);\n    }\n\n    /*\n     * Write out the color type, previously determined.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteByte(interp, pngPtr, pngPtr->colorType, &crc);\n    }\n\n    /*\n     * Write compression method (only one method is defined).\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteByte(interp, pngPtr, PNG_COMPRESS_DEFLATE, &crc);\n    }\n\n    /*\n     * Write filter method (only one method is defined).\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteByte(interp, pngPtr, PNG_FILTMETH_STANDARD, &crc);\n    }\n\n    /*\n     * Write interlace method as not interlaced.\n     *\n     * TODO: support interlace through -format?\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteByte(interp, pngPtr, PNG_INTERLACE_NONE, &crc);\n    }\n\n    /*\n     * Write out the CRC at the end of the chunk.\n     */\n\n    if (TCL_OK == result) {\n\tresult = WriteInt32(interp, pngPtr, crc, NULL);\n    }\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteIDAT --\n *\n *\tWrites the IDAT (data) chunk to the PNG image, containing the pixel\n *\tchannel data. Currently, image lines are not filtered and writing\n *\tinterlaced pixels is not supported.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWriteIDAT(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    int rowNum, flush = TCL_ZLIB_NO_FLUSH, result;\n    Tcl_Obj *outputObj;\n    unsigned char *outputBytes;\n    Tcl_Size outputSize;\n\n    /*\n     * Filter and compress each row one at a time.\n     */\n\n    for (rowNum=0 ; rowNum < blockPtr->height ; rowNum++) {\n\tint colNum;\n\tunsigned char *srcPtr, *destPtr;\n\n\tsrcPtr = blockPtr->pixelPtr + (rowNum * blockPtr->pitch);\n\tdestPtr = Tcl_SetByteArrayLength(pngPtr->thisLineObj,\n\t\tpngPtr->lineSize);\n\n\t/*\n\t * TODO: use Paeth filtering.\n\t */\n\n\t*destPtr++ = PNG_FILTER_NONE;\n\n\t/*\n\t * Copy each pixel into the destination buffer after the filter type\n\t * before filtering.\n\t */\n\n\tfor (colNum = 0 ; colNum < blockPtr->width ; colNum++) {\n\t    /*\n\t     * Copy red or gray channel.\n\t     */\n\n\t    *destPtr++ = srcPtr[blockPtr->offset[0]];\n\n\t    /*\n\t     * If not grayscale, copy the green and blue channels.\n\t     */\n\n\t    if (pngPtr->colorType & PNG_COLOR_USED) {\n\t\t*destPtr++ = srcPtr[blockPtr->offset[1]];\n\t\t*destPtr++ = srcPtr[blockPtr->offset[2]];\n\t    }\n\n\t    /*\n\t     * Copy the alpha channel, if used.\n\t     */\n\n\t    if (pngPtr->colorType & PNG_COLOR_ALPHA) {\n\t\t*destPtr++ = srcPtr[blockPtr->offset[3]];\n\t    }\n\n\t    /*\n\t     * Point to the start of the next pixel.\n\t     */\n\n\t    srcPtr += blockPtr->pixelSize;\n\t}\n\n\t/*\n\t * Compress the line of pixels into the destination. If this is the\n\t * last line, finalize the compressor at the same time. Note that this\n\t * can't be just a flush; that leads to a file that some PNG readers\n\t * choke on. [Bug 2984787]\n\t */\n\n\tif (rowNum + 1 == blockPtr->height) {\n\t    flush = TCL_ZLIB_FINALIZE;\n\t}\n\tif (Tcl_ZlibStreamPut(pngPtr->stream, pngPtr->thisLineObj,\n\t\tflush) != TCL_OK) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"deflate() returned error\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"DEFLATE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Swap line buffers to keep the last around for filtering next.\n\t */\n\n\t{\n\t    Tcl_Obj *temp = pngPtr->lastLineObj;\n\n\t    pngPtr->lastLineObj = pngPtr->thisLineObj;\n\t    pngPtr->thisLineObj = temp;\n\t}\n    }\n\n    /*\n     * Now get the compressed data and write it as one big IDAT chunk.\n     */\n\n    outputObj = Tcl_NewObj();\n    (void) Tcl_ZlibStreamGet(pngPtr->stream, outputObj, TCL_INDEX_NONE);\n    outputBytes = Tcl_GetByteArrayFromObj(outputObj, &outputSize);\n    result = WriteChunk(interp, pngPtr, CHUNK_IDAT, outputBytes, outputSize);\n    Tcl_DecrRefCount(outputObj);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WriteExtraChunks --\n *\n *\tWrites an sBIT and a tEXt chunks to the PNG image, describing a bunch\n *\tof not very important metadata that many readers seem to need anyway.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if the write fails.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWriteExtraChunks(\n    Tcl_Interp *interp,\n    PNGImage *pngPtr,\n    Tcl_Obj *metadataInObj)\n{\n    static const unsigned char sBIT_contents[] = {\n\t8, 8, 8, 8\n    };\n    int sBIT_length = 4;\n    Tcl_DString buf;\n\n    /*\n     * Each byte of each channel is always significant; we always write RGBA\n     * images with 8 bits per channel as that is what the photo image's basic\n     * data model is.\n     */\n\n    switch (pngPtr->colorType) {\n    case PNG_COLOR_GRAY:\n\tsBIT_length = 1;\n\tbreak;\n    case PNG_COLOR_GRAYALPHA:\n\tsBIT_length = 2;\n\tbreak;\n    case PNG_COLOR_RGB:\n    case PNG_COLOR_PLTE:\n\tsBIT_length = 3;\n\tbreak;\n    case PNG_COLOR_RGBA:\n\tsBIT_length = 4;\n\tbreak;\n    }\n    if (WriteChunk(interp, pngPtr, CHUNK_sBIT, sBIT_contents, sBIT_length)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Say that it is Tk that made the PNG. Note that we *need* the NUL at the\n     * end of \"Software\" to be transferred; do *not* change the length\n     * parameter to -1 there!\n     */\n\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, \"Software\", 9);\n    Tcl_DStringAppend(&buf, \"Tk Toolkit v\", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, TK_PATCH_LEVEL, TCL_INDEX_NONE);\n    if (WriteChunk(interp, pngPtr, CHUNK_tEXt,\n\t    (unsigned char *) Tcl_DStringValue(&buf),\n\t    Tcl_DStringLength(&buf)) != TCL_OK) {\n\tTcl_DStringFree(&buf);\n\treturn TCL_ERROR;\n    }\n    Tcl_DStringFree(&buf);\n\n    /*\n     * Add a pHYs chunk if there is metadata for DPI and/or aspect\n     * aspect = PPUy / PPUx\n     * DPI = PPUx * 0.0254\n     * The physical chunk consists of:\n     * - Points per meter in x direction (32 bit)\n     * - Points per meter in x direction (32 bit)\n     * - Unit specifier: 0: no unit (only aspect), 1: Points per meter\n     */\n\n    if (metadataInObj != NULL) {\n\n\tTcl_Obj *aspectObj, *DPIObj;\n\tdouble aspectValue=-1, DPIValue=-1;\n\tunsigned long PPUx = 65536, PPUy = 65536;\n\tchar unitSpecifier;\n\n\tif (TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj,\n\t\tTcl_NewStringObj(\"aspect\",-1),\n\t\t&aspectObj) ||\n\t    TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj,\n\t\tTcl_NewStringObj(\"DPI\",-1),\n\t\t&DPIObj) ) {\n\t    return TCL_ERROR;\n\t}\n\tif (DPIObj != NULL) {\n\t    if (TCL_ERROR == Tcl_GetDoubleFromObj(interp, DPIObj, &DPIValue))\n\t    {\n\t\treturn TCL_ERROR;\n\t    }\n\t    PPUx = (unsigned long)floor(DPIValue / 0.0254+0.5);\n\t    if (aspectObj == NULL) {\n\t\tPPUy = PPUx;\n\t    }\n\t    unitSpecifier = 1;\n\t}\n\tif (aspectObj != NULL) {\n\t    if (TCL_ERROR == Tcl_GetDoubleFromObj(interp, aspectObj,\n\t\t    &aspectValue)) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * aspect = PPUy / PPUx\n\t     */\n\n\t    if (DPIObj == NULL) {\n\t\tunitSpecifier = 0;\n\t\tPPUx = 65536;\n\t\tPPUy = (unsigned long)floor(65536.0 * aspectValue+0.5);\n\t    } else {\n\t\tPPUy = (unsigned long)floor(DPIValue * aspectValue / 0.0254+0.5);\n\t    }\n\t}\n\tif (DPIObj != NULL || aspectObj != NULL) {\n\t    unsigned char buffer[9];\n\n\t    if ( PPUx > 2147483647 || PPUy > 2147483647 ) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"DPI or aspect out of range\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"PHYS\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    LongToInt32(PPUx, buffer);\n\t    LongToInt32(PPUy, buffer+4);\n\t    buffer[8] = unitSpecifier;\n\t    if (WriteChunk(interp, pngPtr, CHUNK_pHYs, buffer, 9)\n\t\t    != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EncodePNG --\n *\n *\tThis function handles the entirety of writing a PNG file (or data)\n *\tfrom the first byte to the last. No effort is made to optimize the\n *\timage data for best compression.\n *\n * Results:\n *\tTCL_OK, or TCL_ERROR if an I/O or memory error occurs.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nEncodePNG(\n    Tcl_Interp *interp,\n    Tk_PhotoImageBlock *blockPtr,\n    PNGImage *pngPtr,\n    Tcl_Obj *metadataInObj)\n{\n    int greenOffset, blueOffset, alphaOffset;\n\n    /*\n     * Determine appropriate color type based on color usage (e.g., only red\n     * and maybe alpha channel = grayscale).\n     *\n     * TODO: Check whether this is doing any good; Tk might just be pushing\n     * full RGBA data all the time through here, even though the actual image\n     * doesn't need it...\n     */\n\n    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];\n    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];\n    alphaOffset = blockPtr->offset[3];\n    if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {\n\talphaOffset = 0;\n    } else {\n\talphaOffset -= blockPtr->offset[0];\n    }\n\n    if ((greenOffset != 0) || (blueOffset != 0)) {\n\tif (alphaOffset) {\n\t    pngPtr->colorType = PNG_COLOR_RGBA;\n\t    pngPtr->bytesPerPixel = 4;\n\t} else {\n\t    pngPtr->colorType = PNG_COLOR_RGB;\n\t    pngPtr->bytesPerPixel = 3;\n\t}\n    } else {\n\tif (alphaOffset) {\n\t    pngPtr->colorType = PNG_COLOR_GRAYALPHA;\n\t    pngPtr->bytesPerPixel = 2;\n\t} else {\n\t    pngPtr->colorType = PNG_COLOR_GRAY;\n\t    pngPtr->bytesPerPixel = 1;\n\t}\n    }\n\n    /*\n     * Allocate buffers for lines for filtering and compressed data.\n     */\n\n    pngPtr->lineSize = 1 + (pngPtr->bytesPerPixel * blockPtr->width);\n    pngPtr->blockLen = pngPtr->lineSize * blockPtr->height;\n\n    if ((blockPtr->width > (INT_MAX - 1) / (pngPtr->bytesPerPixel)) ||\n\t    (blockPtr->height > INT_MAX / pngPtr->lineSize)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"image is too large to encode pixel data\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PNG\", \"TOO_LARGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    pngPtr->lastLineObj = Tcl_NewObj();\n    Tcl_IncrRefCount(pngPtr->lastLineObj);\n    pngPtr->thisLineObj = Tcl_NewObj();\n    Tcl_IncrRefCount(pngPtr->thisLineObj);\n\n    /*\n     * Write out the PNG Signature that all PNGs begin with.\n     */\n\n    if (WriteData(interp, pngPtr, pngSignature, PNG_SIG_SZ,\n\t    NULL) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Write out the IHDR (header) chunk containing image dimensions, color\n     * type, etc.\n     */\n\n    if (WriteIHDR(interp, pngPtr, blockPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Write out the extra chunks containing metadata that is of interest to\n     * other programs more than us.\n     */\n\n    if (WriteExtraChunks(interp, pngPtr, metadataInObj) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Write out the image pixels in the IDAT (data) chunk.\n     */\n\n    if (WriteIDAT(interp, pngPtr, blockPtr) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Write out the IEND chunk that all PNGs end with.\n     */\n\n    return WriteChunk(interp, pngPtr, CHUNK_IEND, NULL, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileWritePNG --\n *\n *\tThis function is called by the photo image type to write PNG format\n *\tdata to a file.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tThe specified file is overwritten.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileWritePNG(\n    Tcl_Interp *interp,\n    const char *filename,\n    TCL_UNUSED(Tcl_Obj *),\n    Tcl_Obj *metadataInObj,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    Tcl_Channel chan;\n    PNGImage png;\n    int result = TCL_ERROR;\n\n    /*\n     * Open a Tcl file channel where the image data will be stored. Tk ought\n     * to take care of this, and just provide a channel, but it doesn't.\n     */\n\n    chan = Tcl_OpenFileChannel(interp, filename, \"w\", 0644);\n\n    if (!chan) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Initalize PNGImage instance for encoding.\n     */\n\n    if (InitPNGImage(interp, &png, chan, NULL,\n\t    TCL_ZLIB_STREAM_DEFLATE) == TCL_ERROR) {\n\tgoto cleanup;\n    }\n\n    if (Tcl_SetChannelOption(interp, chan, \"-translation\", \"binary\")\n\t    != TCL_OK) {\n\tgoto cleanup;\n    }\n\n    /*\n     * Write the raw PNG data out to the file.\n     */\n\n    result = EncodePNG(interp, blockPtr, &png, metadataInObj);\n\n  cleanup:\n    Tcl_Close(interp, chan);\n    CleanupPNGImage(&png);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringWritePNG --\n *\n *\tThis function is called by the photo image type to write PNG format\n *\tdata to a Tcl object and return it in the result.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringWritePNG(\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Obj *),\n    Tcl_Obj *metadataInObj,\n    Tk_PhotoImageBlock *blockPtr)\n{\n    Tcl_Obj *resultObj = Tcl_NewObj();\n    PNGImage png;\n    int result = TCL_ERROR;\n\n    /*\n     * Initalize PNGImage instance for encoding.\n     */\n\n    if (InitPNGImage(interp, &png, NULL, resultObj,\n\t    TCL_ZLIB_STREAM_DEFLATE) == TCL_ERROR) {\n\tgoto cleanup;\n    }\n\n    /*\n     * Write the raw PNG data into the prepared Tcl_Obj buffer. Set the result\n     * back to the interpreter if successful.\n     */\n\n    result = EncodePNG(interp, blockPtr, &png, metadataInObj);\n\n    if (TCL_OK == result) {\n\tTcl_SetObjResult(interp, png.objDataPtr);\n    }\n\n  cleanup:\n    CleanupPNGImage(&png);\n    return result;\n}\n\f\n/*\n * Local Variables:\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgPPM.c",
    "content": "/*\n * tkImgPPM.c --\n *\n *\tA photo image file handler for PPM (Portable PixMap) files.\n *\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Author: Paul Mackerras (paulus@cs.anu.edu.au),\n *\tDepartment of Computer Science,\n *\tAustralian National University.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The maximum amount of memory to allocate for data read from the file. If we\n * need more than this, we do it in pieces.\n */\n\n#define MAX_MEMORY\t10000\t\t/* don't allocate > 10KB */\n\n/*\n * Define PGM and PPM, i.e. gray images and color images.\n */\n\n#define PGM 1\n#define PPM 2\n\n/*\n * The format record for the PPM file format:\n */\n\nstatic int\t\tFileMatchPPM(Tcl_Channel chan, const char *fileName,\n\t\t\t    Tcl_Obj *format, int *widthPtr, int *heightPtr,\n\t\t\t    Tcl_Interp *interp);\nstatic int\t\tFileReadPPM(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *format,\n\t\t\t    Tk_PhotoHandle imageHandle, int destX, int destY,\n\t\t\t    int width, int height, int srcX, int srcY);\nstatic int\t\tFileWritePPM(Tcl_Interp *interp, const char *fileName,\n\t\t\t    Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tStringWritePPM(Tcl_Interp *interp, Tcl_Obj *format,\n\t\t\t    Tk_PhotoImageBlock *blockPtr);\nstatic int\t\tStringMatchPPM(Tcl_Obj *dataObj, Tcl_Obj *format,\n\t\t\t    int *widthPtr, int *heightPtr, Tcl_Interp *interp);\nstatic int\t\tStringReadPPM(Tcl_Interp *interp, Tcl_Obj *dataObj,\n\t\t\t    Tcl_Obj *format, Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY);\n\nTk_PhotoImageFormat tkImgFmtPPM = {\n    \"ppm\",\t\t\t/* name */\n    FileMatchPPM,\t\t/* fileMatchProc */\n    StringMatchPPM,\t\t/* stringMatchProc */\n    FileReadPPM,\t\t/* fileReadProc */\n    StringReadPPM,\t\t/* stringReadProc */\n    FileWritePPM,\t\t/* fileWriteProc */\n    StringWritePPM,\t\t/* stringWriteProc */\n    NULL\n};\n\n/*\n * Prototypes for local functions defined in this file:\n */\n\nstatic int\t\tReadPPMFileHeader(Tcl_Channel chan, int *widthPtr,\n\t\t\t    int *heightPtr, int *maxIntensityPtr);\nstatic int\t\tReadPPMStringHeader(Tcl_Obj *dataObj, int *widthPtr,\n\t\t\t    int *heightPtr, int *maxIntensityPtr,\n\t\t\t    unsigned char **dataBufferPtr, int *dataSizePtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileMatchPPM --\n *\n *\tThis function is invoked by the photo image type to see if a file\n *\tcontains image data in PPM format.\n *\n * Results:\n *\tThe return value is >0 if the first characters in file \"f\" look like\n *\tPPM data, and 0 otherwise.\n *\n * Side effects:\n *\tThe access position in f may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileMatchPPM(\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    TCL_UNUSED(const char *),\t/* The name of the image file. */\n    TCL_UNUSED(Tcl_Obj *),\t\t/* User-specified format string, or NULL. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here if the file is a valid raw PPM\n\t\t\t\t * file. */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* unused */\n{\n    int dummy;\n\n    return ReadPPMFileHeader(chan, widthPtr, heightPtr, &dummy);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileReadPPM --\n *\n *\tThis function is called by the photo image type to read PPM format\n *\tdata from a file and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tThe access position in file f is changed, and new data is added to the\n *\timage given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileReadPPM(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    const char *fileName,\t/* The name of the image file. */\n    TCL_UNUSED(Tcl_Obj *),\t\t/* User-specified format string, or NULL. */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY)\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n{\n    int fileWidth, fileHeight, maxIntensity;\n    int nLines, h, type, bytesPerChannel = 1;\n    size_t nBytes, count;\n    unsigned char *pixelPtr;\n    Tk_PhotoImageBlock block;\n\n    type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity);\n    if (type == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"couldn't read raw PPM header from file \\\"%s\\\"\", fileName));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"NO_HEADER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if ((fileWidth <= 0) || (fileHeight <= 0)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"PPM image file \\\"%s\\\" has dimension(s) <= 0\", fileName));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"DIMENSIONS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"PPM image file \\\"%s\\\" has bad maximum intensity value %d\",\n\t\tfileName, maxIntensity));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"INTENSITY\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (maxIntensity > 0x00ff) {\n\tbytesPerChannel = 2;\n    }\n\n    if ((srcX + width) > fileWidth) {\n\twidth = fileWidth - srcX;\n    }\n    if ((srcY + height) > fileHeight) {\n\theight = fileHeight - srcY;\n    }\n    if ((width <= 0) || (height <= 0)\n\t    || (srcX >= fileWidth) || (srcY >= fileHeight)) {\n\treturn TCL_OK;\n    }\n\n    if (type == PGM) {\n\tblock.pixelSize = 1 * bytesPerChannel;\n\tblock.offset[0] = 0;\n\tblock.offset[1] = 0;\n\tblock.offset[2] = 0;\n    } else {\n\tblock.pixelSize = 3 * bytesPerChannel;\n\tblock.offset[0] = 0;\n\tblock.offset[1] = 1 * bytesPerChannel;\n\tblock.offset[2] = 2 * bytesPerChannel;\n    }\n    block.offset[3] = 0;\n    block.width = width;\n    block.pitch = block.pixelSize * fileWidth;\n\n    if (Tk_PhotoExpand(interp, imageHandle,\n\t    destX + width, destY + height) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (srcY > 0) {\n\tTcl_Seek(chan, (long long)srcY * block.pitch, SEEK_CUR);\n    }\n\n    nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;\n    if (nLines > height) {\n\tnLines = height;\n    }\n    if (nLines <= 0) {\n\tnLines = 1;\n    }\n    nBytes = nLines * block.pitch;\n    pixelPtr = (unsigned char *)Tcl_Alloc(nBytes);\n    block.pixelPtr = pixelPtr + srcX * block.pixelSize;\n\n    for (h = height; h > 0; h -= nLines) {\n\tif (nLines > h) {\n\t    nLines = h;\n\t    nBytes = nLines * block.pitch;\n\t}\n\tcount = Tcl_Read(chan, (char *) pixelPtr, nBytes);\n\tif (count != nBytes) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error reading PPM image file \\\"%s\\\": %s\", fileName,\n\t\t    Tcl_Eof(chan)?\"not enough data\":Tcl_PosixError(interp)));\n\t    if (Tcl_Eof(chan)) {\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"EOF\", (char *)NULL);\n\t    }\n\t    Tcl_Free(pixelPtr);\n\t    return TCL_ERROR;\n\t}\n\tif (maxIntensity < 0x00ff) {\n\t    unsigned char *p;\n\n\t    for (p = pixelPtr; count > 0; count--, p++) {\n\t\t*p = (((int) *p) * 255)/maxIntensity;\n\t    }\n\t} else if (maxIntensity > 0x00ff) {\n\t    unsigned char *p;\n\t    unsigned int value;\n\n\t    for (p = pixelPtr; count > 0; count -= 2, p += 2) {\n\t\tvalue = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]);\n\t\tvalue = value * 255 / maxIntensity;\n\t\tp[0] = p[1] = (unsigned char) value;\n\t    }\n\t}\n\tblock.height = nLines;\n\tif (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,\n\t\twidth, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {\n\t    Tcl_Free(pixelPtr);\n\t    return TCL_ERROR;\n\t}\n\tdestY += nLines;\n    }\n\n    Tcl_Free(pixelPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FileWritePPM --\n *\n *\tThis function is invoked to write image data to a file in PPM format\n *\t(although we can read PGM files, we never write them).\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tData is written to the file given by \"fileName\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileWritePPM(\n    Tcl_Interp *interp,\n    const char *fileName,\n    TCL_UNUSED(Tcl_Obj *),\n    Tk_PhotoImageBlock *blockPtr)\n{\n    Tcl_Channel chan;\n    int w, h, greenOffset, blueOffset;\n    size_t nBytes;\n    unsigned char *pixelPtr, *pixLinePtr;\n    char header[16 + TCL_INTEGER_SPACE * 2];\n\n    chan = Tcl_OpenFileChannel(interp, fileName, \"w\", 0666);\n    if (chan == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_SetChannelOption(interp, chan, \"-translation\", \"binary\")\n\t    != TCL_OK) {\n\tTcl_Close(NULL, chan);\n\treturn TCL_ERROR;\n    }\n\n    snprintf(header, sizeof(header), \"P6\\n%d %d\\n255\\n\", blockPtr->width, blockPtr->height);\n    Tcl_Write(chan, header, TCL_INDEX_NONE);\n\n    pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];\n    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];\n    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];\n\n    if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)\n\t    && (blockPtr->pitch == (blockPtr->width * 3))) {\n\tnBytes = blockPtr->height * blockPtr->pitch;\n\tif ((size_t)Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) {\n\t    goto writeerror;\n\t}\n    } else {\n\tfor (h = blockPtr->height; h > 0; h--) {\n\t    pixelPtr = pixLinePtr;\n\t    for (w = blockPtr->width; w > 0; w--) {\n\t\tif (Tcl_Write(chan,(char *)&pixelPtr[0], 1) == TCL_IO_FAILURE ||\n\t\t\tTcl_Write(chan,(char *)&pixelPtr[greenOffset],1) == TCL_IO_FAILURE ||\n\t\t\tTcl_Write(chan,(char *)&pixelPtr[blueOffset],1) == TCL_IO_FAILURE) {\n\t\t    goto writeerror;\n\t\t}\n\t\tpixelPtr += blockPtr->pixelSize;\n\t    }\n\t    pixLinePtr += blockPtr->pitch;\n\t}\n    }\n\n    if (Tcl_Close(NULL, chan) == 0) {\n\treturn TCL_OK;\n    }\n    chan = NULL;\n\n  writeerror:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"error writing \\\"%s\\\": %s\",\n\t    fileName, Tcl_PosixError(interp)));\n    if (chan != NULL) {\n\tTcl_Close(NULL, chan);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringWritePPM --\n *\n *\tThis function is invoked to write image data to a string in PPM\n *\tformat.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringWritePPM(\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Obj *),\n    Tk_PhotoImageBlock *blockPtr)\n{\n    int w, h, size, greenOffset, blueOffset;\n    unsigned char *pixLinePtr, *byteArray;\n    char header[16 + TCL_INTEGER_SPACE * 2];\n    Tcl_Obj *byteArrayObj;\n\n    snprintf(header, sizeof(header), \"P6\\n%d %d\\n255\\n\", blockPtr->width, blockPtr->height);\n\n    /*\n     * Construct a byte array of the right size with the header and\n     * get a pointer to the data part of it.\n     */\n\n    size = strlen(header);\n    byteArrayObj = Tcl_NewByteArrayObj((unsigned char *)header, size);\n    byteArray = Tcl_SetByteArrayLength(byteArrayObj,\n\t    size + 3*blockPtr->width*blockPtr->height);\n    byteArray += size;\n\n    pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];\n    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];\n    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];\n\n    /*\n     * Check if we can do the data move in single action.\n     */\n\n    if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)\n\t    && (blockPtr->pitch == (blockPtr->width * 3))) {\n\tmemcpy(byteArray, pixLinePtr,\n\t\t(unsigned)blockPtr->height * blockPtr->pitch);\n    } else {\n\tfor (h = blockPtr->height; h > 0; h--) {\n\t    unsigned char *pixelPtr = pixLinePtr;\n\n\t    for (w = blockPtr->width; w > 0; w--) {\n\t\t*byteArray++ = pixelPtr[0];\n\t\t*byteArray++ = pixelPtr[greenOffset];\n\t\t*byteArray++ = pixelPtr[blueOffset];\n\t\tpixelPtr += blockPtr->pixelSize;\n\t    }\n\t    pixLinePtr += blockPtr->pitch;\n\t}\n    }\n\n    /*\n     * Return the object in the interpreter result.\n     */\n\n    Tcl_SetObjResult(interp, byteArrayObj);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringMatchPPM --\n *\n *\tThis function is invoked by the photo image type to see if a string\n *\tcontains image data in PPM format.\n *\n * Results:\n *\tThe return value is >0 if the first characters in file \"f\" look like\n *\tPPM data, and 0 otherwise.\n *\n * Side effects:\n *\tThe access position in f may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringMatchPPM(\n    Tcl_Obj *dataObj,\t\t/* The image data. */\n    TCL_UNUSED(Tcl_Obj *),\t\t/* User-specified format string, or NULL. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here if the file is a valid raw PPM\n\t\t\t\t * file. */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* unused */\n{\n    int dummy;\n\n    return ReadPPMStringHeader(dataObj, widthPtr, heightPtr,\n\t    &dummy, NULL, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StringReadPPM --\n *\n *\tThis function is called by the photo image type to read PPM format\n *\tdata from a string and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNew data is added to the image given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringReadPPM(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Obj *dataObj,\t\t/* The image data. */\n    TCL_UNUSED(Tcl_Obj *),\t\t/* User-specified format string, or NULL. */\n    Tk_PhotoHandle imageHandle,\t/* The photo image to write into. */\n    int destX, int destY,\t/* Coordinates of top-left pixel in photo\n\t\t\t\t * image to be written to. */\n    int width, int height,\t/* Dimensions of block of photo image to be\n\t\t\t\t * written to. */\n    int srcX, int srcY)\t\t/* Coordinates of top-left pixel to be used in\n\t\t\t\t * image being read. */\n{\n    int fileWidth, fileHeight, maxIntensity;\n    int nLines, nBytes, h, type, count, dataSize, bytesPerChannel = 1;\n    unsigned char *pixelPtr, *dataBuffer;\n    Tk_PhotoImageBlock block;\n\n    type = ReadPPMStringHeader(dataObj, &fileWidth, &fileHeight,\n\t    &maxIntensity, &dataBuffer, &dataSize);\n    if (type == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"couldn't read raw PPM header from string\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"NO_HEADER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if ((fileWidth <= 0) || (fileHeight <= 0)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"PPM image data has dimension(s) <= 0\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"DIMENSIONS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if ((maxIntensity <= 0) || (maxIntensity > 0xffff)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"PPM image data has bad maximum intensity value %d\",\n\t\tmaxIntensity));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"INTENSITY\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (maxIntensity > 0x00ff) {\n\tbytesPerChannel = 2;\n    }\n\n    if ((srcX + width) > fileWidth) {\n\twidth = fileWidth - srcX;\n    }\n    if ((srcY + height) > fileHeight) {\n\theight = fileHeight - srcY;\n    }\n    if ((width <= 0) || (height <= 0)\n\t|| (srcX >= fileWidth) || (srcY >= fileHeight)) {\n\treturn TCL_OK;\n    }\n\n    if (type == PGM) {\n\tblock.pixelSize = 1 * bytesPerChannel;\n\tblock.offset[0] = 0;\n\tblock.offset[1] = 0;\n\tblock.offset[2] = 0;\n    } else {\n\tblock.pixelSize = 3 * bytesPerChannel;\n\tblock.offset[0] = 0;\n\tblock.offset[1] = 1 * bytesPerChannel;\n\tblock.offset[2] = 2 * bytesPerChannel;\n    }\n    block.offset[3] = 0;\n    block.width = width;\n    block.pitch = block.pixelSize * fileWidth;\n\n    if (srcY > 0) {\n\tdataBuffer += srcY * block.pitch;\n\tdataSize -= srcY * block.pitch;\n    }\n\n    if (maxIntensity == 0x00ff) {\n\t/*\n\t * We have all the data in memory, so write everything in one go.\n\t */\n\n\tif (block.pitch*height > dataSize) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"truncated PPM data\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"TRUNCATED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tblock.pixelPtr = dataBuffer + srcX * block.pixelSize;\n\tblock.height = height;\n\treturn Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,\n\t\twidth, height, TK_PHOTO_COMPOSITE_SET);\n    }\n\n    if (Tk_PhotoExpand(interp, imageHandle,\n\t    destX + width, destY + height) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;\n    if (nLines > height) {\n\tnLines = height;\n    }\n    if (nLines <= 0) {\n\tnLines = 1;\n    }\n    nBytes = nLines * block.pitch;\n    pixelPtr = (unsigned char *)Tcl_Alloc(nBytes);\n    block.pixelPtr = pixelPtr + srcX * block.pixelSize;\n\n    for (h = height; h > 0; h -= nLines) {\n\tunsigned char *p;\n\n\tif (nLines > h) {\n\t    nLines = h;\n\t    nBytes = nLines * block.pitch;\n\t}\n\tif (dataSize < nBytes) {\n\t    Tcl_Free(pixelPtr);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"truncated PPM data\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PPM\", \"TRUNCATED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (maxIntensity < 0x00ff) {\n\t    for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) {\n\t\t*p = (((int) *dataBuffer) * 255)/maxIntensity;\n\t    }\n\t} else {\n\t    unsigned int value;\n\n\t    for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2, dataBuffer += 2) {\n\t\tvalue = ((unsigned int)dataBuffer[0]) * 256 + ((unsigned int)dataBuffer[1]);\n\t\tvalue = value * 255 / maxIntensity;\n\t\tp[0] = p[1] = (unsigned char) value;\n\t    }\n\t}\n\tdataSize -= nBytes;\n\tblock.height = nLines;\n\tif (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,\n\t\twidth, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {\n\t    Tcl_Free(pixelPtr);\n\t    return TCL_ERROR;\n\t}\n\tdestY += nLines;\n    }\n\n    Tcl_Free(pixelPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadPPMFileHeader --\n *\n *\tThis function reads the PPM header from the beginning of a PPM file\n *\tand returns information from the header.\n *\n * Results:\n *\tThe return value is PGM if file \"f\" appears to start with a valid PGM\n *\theader, PPM if \"f\" appears to start with a valid PPM header, and 0\n *\totherwise. If the header is valid, then *widthPtr and *heightPtr are\n *\tmodified to hold the dimensions of the image and *maxIntensityPtr is\n *\tmodified to hold the value of a \"fully on\" intensity value.\n *\n * Side effects:\n *\tThe access position in f advances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadPPMFileHeader(\n    Tcl_Channel chan,\t\t/* Image file to read the header from. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n    int *maxIntensityPtr)\t/* The maximum intensity value for the image\n\t\t\t\t * is stored here. */\n{\n#define BUFFER_SIZE 1000\n    char buffer[BUFFER_SIZE], c;\n    int i, numFields, type = 0;\n\n    /*\n     * Read 4 space-separated fields from the file, ignoring comments (any\n     * line that starts with \"#\").\n     */\n\n    if (Tcl_Read(chan, &c, 1) != 1) {\n\treturn 0;\n    }\n    i = 0;\n    for (numFields = 0; numFields < 4; numFields++) {\n\t/*\n\t * Skip comments and white space.\n\t */\n\n\twhile (1) {\n\t    while (isspace(UCHAR(c))) {\n\t\tif (Tcl_Read(chan, &c, 1) != 1) {\n\t\t    return 0;\n\t\t}\n\t    }\n\t    if (c != '#') {\n\t\tbreak;\n\t    }\n\t    do {\n\t\tif (Tcl_Read(chan, &c, 1) != 1) {\n\t\t    return 0;\n\t\t}\n\t    } while (c != '\\n');\n\t}\n\n\t/*\n\t * Read a field (everything up to the next white space).\n\t */\n\n\twhile (!isspace(UCHAR(c))) {\n\t    if (i < (BUFFER_SIZE-2)) {\n\t\tbuffer[i] = c;\n\t\ti++;\n\t    }\n\t    if (Tcl_Read(chan, &c, 1) != 1) {\n\t\tgoto done;\n\t    }\n\t}\n\tif (i < (BUFFER_SIZE-1)) {\n\t    buffer[i] = ' ';\n\t    i++;\n\t}\n    }\n\n  done:\n    buffer[i] = 0;\n\n    /*\n     * Parse the fields, which are: id, width, height, maxIntensity.\n     */\n\n    if (strncmp(buffer, \"P6 \", 3) == 0) {\n\ttype = PPM;\n    } else if (strncmp(buffer, \"P5 \", 3) == 0) {\n\ttype = PGM;\n    } else {\n\treturn 0;\n    }\n    if (sscanf(buffer+3, \"%d %d %d\", widthPtr, heightPtr, maxIntensityPtr)\n\t    != 3) {\n\treturn 0;\n    }\n    return type;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadPPMStringHeader --\n *\n *\tThis function reads the PPM header from the beginning of a PPM-format\n *\tstring and returns information from the header.\n *\n * Results:\n *\tThe return value is PGM if the string appears to start with a valid\n *\tPGM header, PPM if the string appears to start with a valid PPM\n *\theader, and 0 otherwise. If the header is valid, then *widthPtr and\n *\t*heightPtr are modified to hold the dimensions of the image and\n *\t*maxIntensityPtr is modified to hold the value of a \"fully on\"\n *\tintensity value.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadPPMStringHeader(\n    Tcl_Obj *dataPtr,\t\t/* Object to read the header from. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n    int *maxIntensityPtr,\t/* The maximum intensity value for the image\n\t\t\t\t * is stored here. */\n    unsigned char **dataBufferPtr,\n    int *dataSizePtr)\n{\n#define BUFFER_SIZE 1000\n    char buffer[BUFFER_SIZE], c;\n    int i, numFields, type = 0;\n    Tcl_Size dataSize;\n    unsigned char *dataBuffer;\n\n    dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize);\n    if (!dataBuffer) {\n\treturn 0;\n    }\n\n    /*\n     * Read 4 space-separated fields from the string, ignoring comments (any\n     * line that starts with \"#\").\n     */\n\n    if (dataSize-- < 1) {\n\treturn 0;\n    }\n    c = (char) (*dataBuffer++);\n    i = 0;\n    for (numFields = 0; numFields < 4; numFields++) {\n\t/*\n\t * Skip comments and white space.\n\t */\n\n\twhile (1) {\n\t    while (isspace(UCHAR(c))) {\n\t\tif (dataSize-- < 1) {\n\t\t    return 0;\n\t\t}\n\t\tc = (char) (*dataBuffer++);\n\t    }\n\t    if (c != '#') {\n\t\tbreak;\n\t    }\n\t    do {\n\t\tif (dataSize-- < 1) {\n\t\t    return 0;\n\t\t}\n\t\tc = (char) (*dataBuffer++);\n\t    } while (c != '\\n');\n\t}\n\n\t/*\n\t * Read a field (everything up to the next white space).\n\t */\n\n\twhile (!isspace(UCHAR(c))) {\n\t    if (i < (BUFFER_SIZE-2)) {\n\t\tbuffer[i] = c;\n\t\ti++;\n\t    }\n\t    if (dataSize-- < 1) {\n\t\tgoto done;\n\t    }\n\t    c = (char) (*dataBuffer++);\n\t}\n\tif (i < (BUFFER_SIZE-1)) {\n\t    buffer[i] = ' ';\n\t    i++;\n\t}\n    }\n\n  done:\n    buffer[i] = 0;\n\n    /*\n     * Parse the fields, which are: id, width, height, maxIntensity.\n     */\n\n    if (strncmp(buffer, \"P6 \", 3) == 0) {\n\ttype = PPM;\n    } else if (strncmp(buffer, \"P5 \", 3) == 0) {\n\ttype = PGM;\n    } else {\n\treturn 0;\n    }\n    if (sscanf(buffer+3, \"%d %d %d\", widthPtr, heightPtr, maxIntensityPtr)\n\t    != 3) {\n\treturn 0;\n    }\n    if (dataBufferPtr != NULL) {\n\t*dataBufferPtr = dataBuffer;\n\t*dataSizePtr = dataSize;\n    }\n    return type;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgPhInstance.c",
    "content": "/*\n * tkImgPhInstance.c --\n *\n *\tImplements the rendering of images of type \"photo\" for Tk. Photo\n *\timages are stored in full color (32 bits per pixel including alpha\n *\tchannel) and displayed using dithering if necessary.\n *\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2002-2008 Donal K. Fellows\n * Copyright © 2003 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Author: Paul Mackerras (paulus@cs.anu.edu.au),\n *\t   Department of Computer Science,\n *\t   Australian National University.\n */\n\n#include \"tkImgPhoto.h\"\n#include \"tkPort.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Declaration for internal Xlib function used here:\n */\n#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TK)\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern int\t\t_XInitImageFuncPtrs(XImage *image);\n#ifdef __cplusplus\n}\n#endif\n#endif\n\n/*\n * Forward declarations\n */\n\n#ifndef TK_CAN_RENDER_RGBA\nstatic void\t\tBlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr,\n\t\t\t    int xOffset, int yOffset, int width, int height);\n#endif\nstatic int\t\tIsValidPalette(PhotoInstance *instancePtr,\n\t\t\t    const char *palette);\nstatic int\t\tCountBits(unsigned mask);\nstatic void\t\tGetColorTable(PhotoInstance *instancePtr);\nstatic void\t\tFreeColorTable(ColorTable *colorPtr, int force);\nstatic void\t\tAllocateColors(ColorTable *colorPtr);\nstatic void\t\tDisposeColorTable(void *clientData);\nstatic int\t\tReclaimColors(ColorTableId *id, int numColors);\n\n/*\n * Hash table used to hash from (display, colormap, palette, gamma) to\n * ColorTable address.\n */\n\nstatic Tcl_HashTable imgPhotoColorHash;\nstatic bool imgPhotoColorHashInitialized;\n#define N_COLOR_HASH\t(sizeof(ColorTableId) / sizeof(int))\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgPhotoConfigureInstance --\n *\n *\tThis function is called to create displaying information for a photo\n *\timage instance based on the configuration information in the model.\n *\tIt is invoked both when new instances are created and when the model\n *\tis reconfigured.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates errors via Tcl_BackgroundException if there are problems in\n *\tsetting up the instance.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgPhotoConfigureInstance(\n    PhotoInstance *instancePtr)\t/* Instance to reconfigure. */\n{\n    PhotoModel *modelPtr = instancePtr->modelPtr;\n    XImage *imagePtr;\n    int bitsPerPixel;\n    ColorTable *colorTablePtr;\n    XRectangle validBox;\n\n    /*\n     * If the -palette configuration option has been set for the model, use\n     * the value specified for our palette, but only if it is a valid palette\n     * for our windows. Use the gamma value specified the model.\n     */\n\n    if ((modelPtr->palette && modelPtr->palette[0])\n\t    && IsValidPalette(instancePtr, modelPtr->palette)) {\n\tinstancePtr->palette = modelPtr->palette;\n    } else {\n\tinstancePtr->palette = instancePtr->defaultPalette;\n    }\n    instancePtr->gamma = modelPtr->gamma;\n\n    /*\n     * If we don't currently have a color table, or if the one we have no\n     * longer applies (e.g. because our palette or gamma has changed), get a\n     * new one.\n     */\n\n    colorTablePtr = instancePtr->colorTablePtr;\n    if ((colorTablePtr == NULL)\n\t    || (instancePtr->colormap != colorTablePtr->id.colormap)\n\t    || (instancePtr->palette != colorTablePtr->id.palette)\n\t    || (instancePtr->gamma != colorTablePtr->id.gamma)) {\n\t/*\n\t * Free up our old color table, and get a new one.\n\t */\n\n\tif (colorTablePtr != NULL) {\n\t    colorTablePtr->liveRefCount--;\n\t    FreeColorTable(colorTablePtr, 0);\n\t}\n\tGetColorTable(instancePtr);\n\n\t/*\n\t * Create a new XImage structure for sending data to the X server, if\n\t * necessary.\n\t */\n\n\tif (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) {\n\t    bitsPerPixel = 1;\n\t} else {\n\t    bitsPerPixel = instancePtr->visualInfo.depth;\n\t}\n\n\tif ((instancePtr->imagePtr == NULL)\n\t\t|| (instancePtr->imagePtr->bits_per_pixel != bitsPerPixel)) {\n\t    if (instancePtr->imagePtr != NULL) {\n\t\tXDestroyImage(instancePtr->imagePtr);\n\t    }\n\t    imagePtr = XCreateImage(instancePtr->display,\n\t\t    instancePtr->visualInfo.visual, (unsigned) bitsPerPixel,\n\t\t    (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, NULL,\n\t\t    1, 1, 32, 0);\n\t    instancePtr->imagePtr = imagePtr;\n\n\t    /*\n\t     * We create images using the local host's endianness, rather than\n\t     * the endianness of the server; otherwise we would have to\n\t     * byte-swap any 16 or 32 bit values that we store in the image\n\t     * if the server's endianness is different from ours.\n\t     */\n\n\t    if (imagePtr != NULL) {\n#ifdef WORDS_BIGENDIAN\n\t\timagePtr->byte_order = MSBFirst;\n#else\n\t\timagePtr->byte_order = LSBFirst;\n#endif\n\t\t_XInitImageFuncPtrs(imagePtr);\n\t    }\n\t}\n    }\n\n    /*\n     * If the user has specified a width and/or height for the model which is\n     * different from our current width/height, set the size to the values\n     * specified by the user. If we have no pixmap, we do this also, since it\n     * has the side effect of allocating a pixmap for us.\n     */\n\n    if ((instancePtr->pixels == None) || (instancePtr->error == NULL)\n\t    || (instancePtr->width != modelPtr->width)\n\t    || (instancePtr->height != modelPtr->height)) {\n\tTkImgPhotoInstanceSetSize(instancePtr);\n    }\n\n    /*\n     * Redither this instance if necessary.\n     */\n\n    if ((modelPtr->flags & IMAGE_CHANGED)\n\t    || (instancePtr->colorTablePtr != colorTablePtr)) {\n\tXClipBox(modelPtr->validRegion, &validBox);\n\tif ((validBox.width > 0) && (validBox.height > 0)) {\n\t    TkImgDitherInstance(instancePtr, validBox.x, validBox.y,\n\t\t    validBox.width, validBox.height);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgPhotoGet --\n *\n *\tThis function is called for each use of a photo image in a widget.\n *\n * Results:\n *\tThe return value is a token for the instance, which is passed back to\n *\tus in calls to TkImgPhotoDisplay and ImgPhotoFree.\n *\n * Side effects:\n *\tA data structure is set up for the instance (or, an existing instance\n *\tis re-used for the new one).\n *\n *----------------------------------------------------------------------\n */\n\nvoid *\nTkImgPhotoGet(\n    Tk_Window tkwin,\t\t/* Window in which the instance will be\n\t\t\t\t * used. */\n    void *modelData)\t/* Pointer to our model structure for the\n\t\t\t\t * image. */\n{\n    PhotoModel *modelPtr = (PhotoModel *)modelData;\n    PhotoInstance *instancePtr;\n    Colormap colormap;\n    bool mono;\n    int nRed, nGreen, nBlue, numVisuals;\n    XVisualInfo visualInfo, *visInfoPtr;\n    char buf[TCL_INTEGER_SPACE * 3];\n    XColor *white, *black;\n    XGCValues gcValues;\n#if (!defined(_WIN32) && !defined(MAC_OSX_TK))\n    int gcmask;\n#endif\n\n    /*\n     * Table of \"best\" choices for palette for PseudoColor displays with\n     * between 3 and 15 bits/pixel.\n     */\n\n    static const int paletteChoice[13][3] = {\n\t/*  #red, #green, #blue */\n\t {2,  2,  2,\t\t/* 3 bits, 8 colors */},\n\t {2,  3,  2,\t\t/* 4 bits, 12 colors */},\n\t {3,  4,  2,\t\t/* 5 bits, 24 colors */},\n\t {4,  5,  3,\t\t/* 6 bits, 60 colors */},\n\t {5,  6,  4,\t\t/* 7 bits, 120 colors */},\n\t {7,  7,  4,\t\t/* 8 bits, 198 colors */},\n\t {8, 10,  6,\t\t/* 9 bits, 480 colors */},\n\t{10, 12,  8,\t\t/* 10 bits, 960 colors */},\n\t{14, 15,  9,\t\t/* 11 bits, 1890 colors */},\n\t{16, 20, 12,\t\t/* 12 bits, 3840 colors */},\n\t{20, 24, 16,\t\t/* 13 bits, 7680 colors */},\n\t{26, 30, 20,\t\t/* 14 bits, 15600 colors */},\n\t{32, 32, 30,\t\t/* 15 bits, 30720 colors */}\n    };\n\n    /*\n     * See if there is already an instance for windows using the same\n     * colormap. If so then just re-use it.\n     */\n\n    colormap = Tk_Colormap(tkwin);\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tif ((colormap == instancePtr->colormap)\n\t    && (Tk_Display(tkwin) == instancePtr->display)\n#if (!defined(_WIN32) && !defined(MAC_OSX_TK))\n\t    && (Tk_Visual(tkwin) == instancePtr->visualInfo.visual)\n#endif\n\t    ) {\n\t    /*\n\t     * Re-use this instance.\n\t     */\n\n\t    if (instancePtr->refCount == 0) {\n\t\t/*\n\t\t * We are resurrecting this instance.\n\t\t */\n\n\t\tTcl_CancelIdleCall(TkImgDisposeInstance, instancePtr);\n\t\tif (instancePtr->colorTablePtr != NULL) {\n\t\t    FreeColorTable(instancePtr->colorTablePtr, 0);\n\t\t}\n\t\tGetColorTable(instancePtr);\n\t    }\n\t    instancePtr->refCount++;\n\t    return instancePtr;\n\t}\n    }\n\n    /*\n     * The image isn't already in use in a window with the same colormap. Make\n     * a new instance of the image.\n     */\n\n    instancePtr = (PhotoInstance *)Tcl_Alloc(sizeof(PhotoInstance));\n    instancePtr->modelPtr = modelPtr;\n    instancePtr->display = Tk_Display(tkwin);\n    instancePtr->colormap = Tk_Colormap(tkwin);\n    Tk_PreserveColormap(instancePtr->display, instancePtr->colormap);\n    instancePtr->refCount = 1;\n    instancePtr->colorTablePtr = NULL;\n    instancePtr->pixels = None;\n    instancePtr->error = NULL;\n    instancePtr->width = 0;\n    instancePtr->height = 0;\n    instancePtr->imagePtr = 0;\n    instancePtr->nextPtr = modelPtr->instancePtr;\n    modelPtr->instancePtr = instancePtr;\n\n    /*\n     * Obtain information about the visual and decide on the default palette.\n     */\n\n    visualInfo.screen = Tk_ScreenNumber(tkwin);\n    visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));\n    visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),\n\t    VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals);\n    if (visInfoPtr == NULL) {\n\tTcl_Panic(\"TkImgPhotoGet couldn't find visual for window\");\n    }\n\n    nRed = 2;\n    nGreen = nBlue = 0;\n    mono = true;\n    instancePtr->visualInfo = *visInfoPtr;\n#if (!defined(_WIN32) && !defined(MAC_OSX_TK))\n    gcmask = 0;\n    instancePtr->visualInfo.visual = Tk_Visual(tkwin);\n#endif\n    switch (visInfoPtr->c_class) {\n    case DirectColor:\n    case TrueColor:\n\tnRed = 1 << CountBits(visInfoPtr->red_mask);\n\tnGreen = 1 << CountBits(visInfoPtr->green_mask);\n\tnBlue = 1 << CountBits(visInfoPtr->blue_mask);\n\tmono = false;\n#if (!defined(_WIN32) && !defined(MAC_OSX_TK))\n\tif (visInfoPtr->depth > 24) {\n\t    gcValues.plane_mask = visInfoPtr->red_mask\n\t\t    | visInfoPtr->green_mask\n\t\t    | visInfoPtr->blue_mask;\n\t    gcmask = GCPlaneMask;\n\t}\n#endif\n\tbreak;\n    case PseudoColor:\n    case StaticColor:\n\tif (visInfoPtr->depth > 15) {\n\t    nRed = 32;\n\t    nGreen = 32;\n\t    nBlue = 32;\n\t    mono = false;\n\t} else if (visInfoPtr->depth >= 3) {\n\t    const int *ip = paletteChoice[visInfoPtr->depth - 3];\n\n\t    nRed = ip[0];\n\t    nGreen = ip[1];\n\t    nBlue = ip[2];\n\t    mono = false;\n\t}\n\tbreak;\n    case GrayScale:\n    case StaticGray:\n\tnRed = 1 << visInfoPtr->depth;\n\tbreak;\n    }\n    XFree(visInfoPtr);\n\n    if (mono) {\n\tsnprintf(buf, sizeof(buf), \"%d\", nRed);\n    } else {\n\tsnprintf(buf, sizeof(buf), \"%d/%d/%d\", nRed, nGreen, nBlue);\n    }\n    instancePtr->defaultPalette = Tk_GetUid(buf);\n\n    /*\n     * Make a GC with background = black and foreground = white.\n     */\n\n    white = Tk_GetColor(modelPtr->interp, tkwin, \"white\");\n    black = Tk_GetColor(modelPtr->interp, tkwin, \"black\");\n    gcValues.foreground = (white != NULL)? white->pixel:\n\t    WhitePixelOfScreen(Tk_Screen(tkwin));\n    gcValues.background = (black != NULL)? black->pixel:\n\t    BlackPixelOfScreen(Tk_Screen(tkwin));\n    Tk_FreeColor(white);\n    Tk_FreeColor(black);\n    gcValues.graphics_exposures = False;\n#if (!defined(_WIN32) && !defined(MAC_OSX_TK))\n    instancePtr->gc = Tk_GetGC(tkwin,\n\tgcmask|GCForeground|GCBackground|GCGraphicsExposures, &gcValues);\n#else\n    instancePtr->gc = Tk_GetGC(tkwin,\n\tGCForeground|GCBackground|GCGraphicsExposures, &gcValues);\n#endif\n\n    /*\n     * Set configuration options and finish the initialization of the\n     * instance. This will also dither the image if necessary.\n     */\n\n    TkImgPhotoConfigureInstance(instancePtr);\n\n    /*\n     * If this is the first instance, must set the size of the image.\n     */\n\n    if (instancePtr->nextPtr == NULL) {\n\tTk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,\n\t\tmodelPtr->width, modelPtr->height);\n    }\n\n    return instancePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BlendComplexAlpha --\n *\n *\tThis function is called when an image with partially transparent\n *\tpixels must be drawn over another image. It blends the photo data onto\n *\ta local copy of the surface that we are drawing on, *including* the\n *\tpixels drawn by everything that should be drawn underneath the image.\n *\n *\tMuch of this code has hard-coded values in for speed because this\n *\troutine is performance critical for complex image drawing.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tBackground image passed in gets drawn over with image data.\n *\n * Notes:\n *\tThis should work on all platforms that set mask and shift data\n *\tproperly from the visualInfo. RGB is really only a 24+ bpp version\n *\twhereas RGB15 is the correct version and works for 15bpp+, but it\n *\tslower, so it's only used for 15bpp+.\n *\n *\tNote that Win32 pre-defines those operations that we really need.\n *\n *----------------------------------------------------------------------\n */\n#ifndef TK_CAN_RENDER_RGBA\n#ifndef _WIN32\n#define GetRValue(rgb)\t(UCHAR(((rgb) & red_mask) >> red_shift))\n#define GetGValue(rgb)\t(UCHAR(((rgb) & green_mask) >> green_shift))\n#define GetBValue(rgb)\t(UCHAR(((rgb) & blue_mask) >> blue_shift))\n#define RGB(r, g, b)\t((unsigned)( \\\n\t(UCHAR(r) << red_shift)   | \\\n\t(UCHAR(g) << green_shift) | \\\n\t(UCHAR(b) << blue_shift)  ))\n#define RGB15(r, g, b)\t((unsigned)( \\\n\t(((r) * red_mask / 255)   & red_mask)   | \\\n\t(((g) * green_mask / 255) & green_mask) | \\\n\t(((b) * blue_mask / 255)  & blue_mask)  ))\n#endif /* !_WIN32 */\n\nstatic void\nBlendComplexAlpha(\n    XImage *bgImg,\t\t/* Background image to draw on. */\n    PhotoInstance *iPtr,\t/* Image instance to draw. */\n    int xOffset, int yOffset,\t/* X & Y offset into image instance to\n\t\t\t\t * draw. */\n    int width, int height)\t/* Width & height of image to draw. */\n{\n    int x, y, line;\n    unsigned long pixel;\n    unsigned char r, g, b, alpha, unalpha, *modelPtr;\n    unsigned char *alphaAr = iPtr->modelPtr->pix32;\n\n    /*\n     * This blending is an integer version of the Source-Over compositing rule\n     * (see Porter&Duff, \"Compositing Digital Images\", proceedings of SIGGRAPH\n     * 1984) that has been hard-coded (for speed) to work with targetting a\n     * solid surface.\n     *\n     * The 'unalpha' field must be 255-alpha; it is separated out to encourage\n     * more efficient compilation.\n     */\n\n#define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \\\n\t((bgPix * unalpha + imgPix * alpha) / 255)\n\n    /*\n     * We have to get the mask and shift info from the visual on non-Win32 so\n     * that the macros Get*Value(), RGB() and RGB15() work correctly. This\n     * might be cached for better performance.\n     */\n\n#ifndef _WIN32\n    unsigned long red_mask, green_mask, blue_mask;\n    unsigned long red_shift, green_shift, blue_shift;\n    Visual *visual = iPtr->visualInfo.visual;\n\n    red_mask = visual->red_mask;\n    green_mask = visual->green_mask;\n    blue_mask = visual->blue_mask;\n    red_shift = 0;\n    green_shift = 0;\n    blue_shift = 0;\n    while ((0x0001 & (red_mask >> red_shift)) == 0) {\n\tred_shift++;\n    }\n    while ((0x0001 & (green_mask >> green_shift)) == 0) {\n\tgreen_shift++;\n    }\n    while ((0x0001 & (blue_mask >> blue_shift)) == 0) {\n\tblue_shift++;\n    }\n#endif /* !_WIN32 */\n\n    /*\n     * Only UNIX requires the special case for <24bpp. It varies with 3 extra\n     * shifts and uses RGB15. The 24+bpp version could also then be further\n     * optimized.\n     */\n\n#if !defined(_WIN32)\n    if (bgImg->depth < 24) {\n\tunsigned char red_mlen, green_mlen, blue_mlen;\n\n\tred_mlen = 8 - CountBits(red_mask >> red_shift);\n\tgreen_mlen = 8 - CountBits(green_mask >> green_shift);\n\tblue_mlen = 8 - CountBits(blue_mask >> blue_shift);\n\tfor (y = 0; y < height; y++) {\n\t    line = (y + yOffset) * iPtr->modelPtr->width;\n\t    for (x = 0; x < width; x++) {\n\t\tmodelPtr = alphaAr + ((line + x + xOffset) * 4);\n\t\talpha = modelPtr[3];\n\n\t\t/*\n\t\t * Ignore pixels that are fully transparent\n\t\t */\n\n\t\tif (alpha) {\n\t\t    /*\n\t\t     * We could perhaps be more efficient than XGetPixel for\n\t\t     * 24 and 32 bit displays, but this seems \"fast enough\".\n\t\t     */\n\n\t\t    r = modelPtr[0];\n\t\t    g = modelPtr[1];\n\t\t    b = modelPtr[2];\n\t\t    if (alpha != 255) {\n\t\t\t/*\n\t\t\t * Only blend pixels that have some transparency\n\t\t\t */\n\n\t\t\tunsigned char ra, ga, ba;\n\n\t\t\tpixel = XGetPixel(bgImg, x, y);\n\t\t\tra = GetRValue(pixel) << red_mlen;\n\t\t\tga = GetGValue(pixel) << green_mlen;\n\t\t\tba = GetBValue(pixel) << blue_mlen;\n\t\t\tunalpha = 255 - alpha;\t/* Calculate once. */\n\t\t\tr = ALPHA_BLEND(ra, r, alpha, unalpha);\n\t\t\tg = ALPHA_BLEND(ga, g, alpha, unalpha);\n\t\t\tb = ALPHA_BLEND(ba, b, alpha, unalpha);\n\t\t    }\n\t\t    XPutPixel(bgImg, x, y, RGB15(r, g, b));\n\t\t}\n\t    }\n\t}\n\treturn;\n    }\n#endif /* !_WIN32 */\n\n    for (y = 0; y < height; y++) {\n\tline = (y + yOffset) * iPtr->modelPtr->width;\n\tfor (x = 0; x < width; x++) {\n\t    modelPtr = alphaAr + ((line + x + xOffset) * 4);\n\t    alpha = modelPtr[3];\n\n\t    /*\n\t     * Ignore pixels that are fully transparent\n\t     */\n\n\t    if (alpha) {\n\t\t/*\n\t\t * We could perhaps be more efficient than XGetPixel for 24\n\t\t * and 32 bit displays, but this seems \"fast enough\".\n\t\t */\n\n\t\tr = modelPtr[0];\n\t\tg = modelPtr[1];\n\t\tb = modelPtr[2];\n\t\tif (alpha != 255) {\n\t\t    /*\n\t\t     * Only blend pixels that have some transparency\n\t\t     */\n\n\t\t    unsigned char ra, ga, ba;\n\n\t\t    pixel = XGetPixel(bgImg, x, y);\n\t\t    ra = GetRValue(pixel);\n\t\t    ga = GetGValue(pixel);\n\t\t    ba = GetBValue(pixel);\n\t\t    unalpha = 255 - alpha;\t/* Calculate once. */\n\t\t    r = ALPHA_BLEND(ra, r, alpha, unalpha);\n\t\t    g = ALPHA_BLEND(ga, g, alpha, unalpha);\n\t\t    b = ALPHA_BLEND(ba, b, alpha, unalpha);\n\t\t}\n\t\tXPutPixel(bgImg, x, y, RGB(r, g, b));\n\t    }\n\t}\n    }\n#undef ALPHA_BLEND\n}\n#endif /* TK_CAN_RENDER_RGBA */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgPhotoDisplay --\n *\n *\tThis function is invoked to draw a photo image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA portion of the image gets rendered in a pixmap or window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgPhotoDisplay(\n    void *clientData,\t/* Pointer to PhotoInstance structure for\n\t\t\t\t * instance to be displayed. */\n    Display *display,\t\t/* Display on which to draw image. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw image. */\n    int imageX, int imageY,\t/* Upper-left corner of region within image to\n\t\t\t\t * draw. */\n    int width, int height,\t/* Dimensions of region within image to\n\t\t\t\t * draw. */\n    int drawableX,int drawableY)/* Coordinates within drawable that correspond\n\t\t\t\t * to imageX and imageY. */\n{\n    PhotoInstance *instancePtr = (PhotoInstance *)clientData;\n#ifndef TK_CAN_RENDER_RGBA\n    XVisualInfo visInfo = instancePtr->visualInfo;\n#endif\n\n    /*\n     * If there's no pixmap, it means that an error occurred while creating\n     * the image instance so it can't be displayed.\n     */\n\n    if (instancePtr->pixels == None) {\n\treturn;\n    }\n\n#ifdef TK_CAN_RENDER_RGBA\n\n    /*\n     * We can use TkpPutRGBAImage to render RGBA Ximages directly so there is\n     * no need to call XGetImage or to do the Porter-Duff compositing by hand.\n     */\n\n    unsigned char *rgbaPixels = instancePtr->modelPtr->pix32;\n    XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels,\n\t\t\t\t (unsigned int)instancePtr->width,\n\t\t\t\t (unsigned int)instancePtr->height,\n\t\t\t\t 0, (unsigned int)(4 * instancePtr->width));\n    TkpPutRGBAImage(display, drawable, instancePtr->gc,\n\t       photo, imageX, imageY, drawableX, drawableY,\n\t       (unsigned int) width, (unsigned int) height);\n    photo->data = NULL;\n    XDestroyImage(photo);\n\n#else\n\n    if ((instancePtr->modelPtr->flags & COMPLEX_ALPHA)\n\t    && visInfo.depth >= 15\n\t    && (visInfo.c_class == DirectColor || visInfo.c_class == TrueColor)) {\n\tTk_ErrorHandler handler;\n\tXImage *bgImg = NULL;\n\n\t/*\n\t * Create an error handler to suppress the case where the input was\n\t * not properly constrained, which can cause an X error. [Bug 979239]\n\t */\n\n\thandler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n\t/*\n\t * Pull the current background from the display to blend with\n\t */\n\n\tbgImg = XGetImage(display, drawable, drawableX, drawableY,\n\t\t(unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);\n\tif (bgImg == NULL) {\n\t    Tk_DeleteErrorHandler(handler);\n\t    /* We failed to get the image, so draw without blending alpha.\n\t     * It's the best we can do.\n\t     */\n\t    goto fallBack;\n\t}\n\n\tBlendComplexAlpha(bgImg, instancePtr, imageX, imageY, width, height);\n\n\t/*\n\t * Color info is unimportant as we only do this operation for depth >=\n\t * 15.\n\t */\n\n\tTkPutImage(NULL, 0, display, drawable, instancePtr->gc,\n\t\tbgImg, 0, 0, drawableX, drawableY,\n\t\t(unsigned int) width, (unsigned int) height);\n\tXDestroyImage(bgImg);\n\tTk_DeleteErrorHandler(handler);\n    } else {\n\t/*\n\t * modelPtr->validRegion describes which parts of the image contain valid\n\t * data. We set this region as the clip mask for the gc, setting its\n\t * origin appropriately, and use it when drawing the image.\n\t */\n\n    fallBack:\n\tXSetRegion(display, instancePtr->gc,\n\t\tinstancePtr->modelPtr->validRegion);\n\tXSetClipOrigin(display, instancePtr->gc, drawableX - imageX,\n\t\tdrawableY - imageY);\n\tXCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,\n\t\timageX, imageY, (unsigned) width, (unsigned) height,\n\t\tdrawableX, drawableY);\n\tXSetClipMask(display, instancePtr->gc, None);\n\tXSetClipOrigin(display, instancePtr->gc, 0, 0);\n    }\n    (void)XFlush(display);\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgPhotoFree --\n *\n *\tThis function is called when a widget ceases to use a particular\n *\tinstance of an image. We don't actually get rid of the instance until\n *\tlater because we may be about to get this instance again.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInternal data structures get cleaned up, later.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgPhotoFree(\n    void *clientData,\t/* Pointer to PhotoInstance structure for\n\t\t\t\t * instance to be displayed. */\n    TCL_UNUSED(Display *))\t/* Display containing window that used\n\t\t\t\t * image. */\n{\n    PhotoInstance *instancePtr = (PhotoInstance *)clientData;\n    ColorTable *colorPtr;\n\n    if (instancePtr->refCount-- > 1) {\n\treturn;\n    }\n\n    /*\n     * There are no more uses of the image within this widget. Decrement the\n     * count of live uses of its color table, so that its colors can be\n     * reclaimed if necessary, and set up an idle call to free the instance\n     * structure.\n     */\n\n    colorPtr = instancePtr->colorTablePtr;\n    if (colorPtr != NULL) {\n\tcolorPtr->liveRefCount--;\n    }\n\n    Tcl_DoWhenIdle(TkImgDisposeInstance, instancePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgPhotoInstanceSetSize --\n *\n *\tThis function reallocates the instance pixmap and dithering error\n *\tarray for a photo instance, as necessary, to change the image's size\n *\tto `width' x `height' pixels.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStorage gets reallocated, here and in the X server.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgPhotoInstanceSetSize(\n    PhotoInstance *instancePtr)\t/* Instance whose size is to be changed. */\n{\n    PhotoModel *modelPtr;\n    schar *newError, *errSrcPtr, *errDestPtr;\n    int h, offset;\n    XRectangle validBox;\n    Pixmap newPixmap;\n\n    modelPtr = instancePtr->modelPtr;\n    XClipBox(modelPtr->validRegion, &validBox);\n\n    if ((instancePtr->width != modelPtr->width)\n\t    || (instancePtr->height != modelPtr->height)\n\t    || (instancePtr->pixels == None)) {\n\tnewPixmap = Tk_GetPixmap(instancePtr->display,\n\t\tRootWindow(instancePtr->display,\n\t\t\tinstancePtr->visualInfo.screen),\n\t\t(modelPtr->width > 0) ? modelPtr->width: 1,\n\t\t(modelPtr->height > 0) ? modelPtr->height: 1,\n\t\tinstancePtr->visualInfo.depth);\n\tif (!newPixmap) {\n\t    Tcl_Panic(\"Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize\");\n\t}\n\n\t/*\n\t * The following is a gross hack needed to properly support colormaps\n\t * under Windows. Before the pixels can be copied to the pixmap, the\n\t * relevent colormap must be associated with the drawable. Normally we\n\t * can infer this association from the window that was used to create\n\t * the pixmap. However, in this case we're using the root window, so\n\t * we have to be more explicit.\n\t */\n\n\tTkSetPixmapColormap(newPixmap, instancePtr->colormap);\n\n\tif (instancePtr->pixels != None) {\n\t    /*\n\t     * Copy any common pixels from the old pixmap and free it.\n\t     */\n\n\t    XCopyArea(instancePtr->display, instancePtr->pixels, newPixmap,\n\t\t    instancePtr->gc, validBox.x, validBox.y,\n\t\t    validBox.width, validBox.height, validBox.x, validBox.y);\n\t    Tk_FreePixmap(instancePtr->display, instancePtr->pixels);\n\t}\n\tinstancePtr->pixels = newPixmap;\n    }\n\n    if ((instancePtr->width != modelPtr->width)\n\t    || (instancePtr->height != modelPtr->height)\n\t    || (instancePtr->error == NULL)) {\n\tif (modelPtr->height > 0 && modelPtr->width > 0) {\n\t    /*\n\t     * TODO: use Tcl_AttemptAlloc() here once there is a strategy that\n\t     * will allow us to recover from failure. Right now, there's no\n\t     * such possibility.\n\t     */\n\n\t    newError = (schar *)Tcl_Alloc(modelPtr->height * modelPtr->width\n\t\t    * 3 * sizeof(schar));\n\n\t    /*\n\t     * Zero the new array so that we don't get bogus error values\n\t     * propagating into areas we dither later.\n\t     */\n\n\t    if ((instancePtr->error != NULL)\n\t\t    && ((instancePtr->width == modelPtr->width)\n\t\t    || (validBox.width == modelPtr->width))) {\n\t\tif (validBox.y > 0) {\n\t\t    memset(newError, 0, (size_t)\n\t\t\t    validBox.y * modelPtr->width * 3 * sizeof(schar));\n\t\t}\n\t\th = validBox.y + validBox.height;\n\t\tif (h < modelPtr->height) {\n\t\t    memset(newError + h*modelPtr->width*3, 0,\n\t\t\t    (size_t) (modelPtr->height - h)\n\t\t\t    * modelPtr->width * 3 * sizeof(schar));\n\t\t}\n\t    } else {\n\t\tmemset(newError, 0, (size_t)\n\t\t\tmodelPtr->height * modelPtr->width *3*sizeof(schar));\n\t    }\n\t} else {\n\t    newError = NULL;\n\t}\n\n\tif (instancePtr->error != NULL) {\n\t    /*\n\t     * Copy the common area over to the new array and free the old\n\t     * array.\n\t     */\n\n\t    if (modelPtr->width == instancePtr->width) {\n\t\toffset = validBox.y * modelPtr->width * 3;\n\t\tmemcpy(newError + offset, instancePtr->error + offset,\n\t\t\t(size_t) validBox.height\n\t\t\t* modelPtr->width * 3 * sizeof(schar));\n\n\t    } else if (validBox.width > 0 && validBox.height > 0) {\n\t\terrDestPtr = newError +\n\t\t\t(validBox.y * modelPtr->width + validBox.x) * 3;\n\t\terrSrcPtr = instancePtr->error +\n\t\t\t(validBox.y * instancePtr->width + validBox.x) * 3;\n\n\t\tfor (h = validBox.height; h > 0; --h) {\n\t\t    memcpy(errDestPtr, errSrcPtr,\n\t\t\t    validBox.width * 3 * sizeof(schar));\n\t\t    errDestPtr += modelPtr->width * 3;\n\t\t    errSrcPtr += instancePtr->width * 3;\n\t\t}\n\t    }\n\t    Tcl_Free(instancePtr->error);\n\t}\n\n\tinstancePtr->error = newError;\n    }\n\n    instancePtr->width = modelPtr->width;\n    instancePtr->height = modelPtr->height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IsValidPalette --\n *\n *\tThis function is called to check whether a value given for the\n *\t-palette option is valid for a particular instance of a photo image.\n *\n * Results:\n *\tA boolean value: 1 if the palette is acceptable, 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nIsValidPalette(\n    PhotoInstance *instancePtr,\t/* Instance to which the palette specification\n\t\t\t\t * is to be applied. */\n    const char *palette)\t/* Palette specification string. */\n{\n    int nRed, nGreen, nBlue, numColors;\n    bool mono;\n    char *endp;\n\n    /*\n     * First parse the specification: it must be of the form %d or %d/%d/%d.\n     */\n\n    nRed = strtol(palette, &endp, 10);\n    if ((endp == palette) || ((*endp != 0) && (*endp != '/'))\n\t    || (nRed < 2) || (nRed > 256)) {\n\treturn 0;\n    }\n\n    if (*endp == 0) {\n\tmono = true;\n\tnGreen = nBlue = nRed;\n    } else {\n\tpalette = endp + 1;\n\tnGreen = strtol(palette, &endp, 10);\n\tif ((endp == palette) || (*endp != '/') || (nGreen < 2)\n\t\t|| (nGreen > 256)) {\n\t    return 0;\n\t}\n\tpalette = endp + 1;\n\tnBlue = strtol(palette, &endp, 10);\n\tif ((endp == palette) || (*endp != 0) || (nBlue < 2)\n\t\t|| (nBlue > 256)) {\n\t    return 0;\n\t}\n\tmono = false;\n    }\n\n    switch (instancePtr->visualInfo.c_class) {\n    case DirectColor:\n    case TrueColor:\n\tif ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask)))\n\t\t|| (nGreen>(1<<CountBits(instancePtr->visualInfo.green_mask)))\n\t\t|| (nBlue>(1<<CountBits(instancePtr->visualInfo.blue_mask)))) {\n\t    return 0;\n\t}\n\tbreak;\n    case PseudoColor:\n    case StaticColor:\n\tnumColors = nRed;\n\tif (!mono) {\n\t    numColors *= nGreen * nBlue;\n\t}\n\tif (numColors > (1 << instancePtr->visualInfo.depth)) {\n\t    return 0;\n\t}\n\tbreak;\n    case GrayScale:\n    case StaticGray:\n\tif (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) {\n\t    return 0;\n\t}\n\tbreak;\n    }\n\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CountBits --\n *\n *\tThis function counts how many bits are set to 1 in `mask'.\n *\n * Results:\n *\tThe integer number of bits.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCountBits(\n    unsigned mask)\t\t\t/* Value to count the 1 bits in. */\n{\n    int n;\n\n    for (n=0 ; mask!=0 ; mask&=mask-1) {\n\tn++;\n    }\n    return n;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetColorTable --\n *\n *\tThis function is called to allocate a table of colormap information\n *\tfor an instance of a photo image. Only one such table is allocated for\n *\tall photo instances using the same display, colormap, palette and\n *\tgamma values, so that the application need only request a set of\n *\tcolors from the X server once for all such photo widgets. This\n *\tfunction maintains a hash table to find previously-allocated\n *\tColorTables.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new ColorTable may be allocated and placed in the hash table, and\n *\thave colors allocated for it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetColorTable(\n    PhotoInstance *instancePtr)\t/* Instance needing a color table. */\n{\n    ColorTable *colorPtr;\n    Tcl_HashEntry *entry;\n    ColorTableId id;\n    int isNew;\n\n    /*\n     * Look for an existing ColorTable in the hash table.\n     */\n\n    memset(&id, 0, sizeof(id));\n    id.display = instancePtr->display;\n    id.colormap = instancePtr->colormap;\n    id.palette = instancePtr->palette;\n    id.gamma = instancePtr->gamma;\n    if (!imgPhotoColorHashInitialized) {\n\tTcl_InitHashTable(&imgPhotoColorHash, N_COLOR_HASH);\n\timgPhotoColorHashInitialized = true;\n    }\n    entry = Tcl_CreateHashEntry(&imgPhotoColorHash, (char *) &id, &isNew);\n\n    if (!isNew) {\n\t/*\n\t * Re-use the existing entry.\n\t */\n\n\tcolorPtr = (ColorTable *)Tcl_GetHashValue(entry);\n    } else {\n\t/*\n\t * No color table currently available; need to make one.\n\t */\n\n\tcolorPtr = (ColorTable *)Tcl_Alloc(sizeof(ColorTable));\n\n\t/*\n\t * The following line of code should not normally be needed due to the\n\t * assignment in the following line. However, it compensates for bugs\n\t * in some compilers (HP, for example) where sizeof(ColorTable) is 24\n\t * but the assignment only copies 20 bytes, leaving 4 bytes\n\t * uninitialized; these cause problems when using the id for lookups\n\t * in imgPhotoColorHash, and can result in core dumps.\n\t */\n\n\tmemset(&colorPtr->id, 0, sizeof(ColorTableId));\n\tcolorPtr->id = id;\n\tTk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap);\n\tcolorPtr->flags = 0;\n\tcolorPtr->refCount = 0;\n\tcolorPtr->liveRefCount = 0;\n\tcolorPtr->numColors = 0;\n\tcolorPtr->visualInfo = instancePtr->visualInfo;\n\tcolorPtr->pixelMap = NULL;\n\tTcl_SetHashValue(entry, colorPtr);\n    }\n\n    colorPtr->refCount++;\n    colorPtr->liveRefCount++;\n    instancePtr->colorTablePtr = colorPtr;\n    if (colorPtr->flags & DISPOSE_PENDING) {\n\tTcl_CancelIdleCall(DisposeColorTable, colorPtr);\n\tcolorPtr->flags &= ~DISPOSE_PENDING;\n    }\n\n    /*\n     * Allocate colors for this color table if necessary.\n     */\n\n    if ((colorPtr->numColors == 0) && !(colorPtr->flags & BLACK_AND_WHITE)) {\n\tAllocateColors(colorPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeColorTable --\n *\n *\tThis function is called when an instance ceases using a color table.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf no other instances are using this color table, a when-idle handler\n *\tis registered to free up the color table and the colors allocated for\n *\tit.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeColorTable(\n    ColorTable *colorPtr,\t/* Pointer to the color table which is no\n\t\t\t\t * longer required by an instance. */\n    int force)\t\t\t/* Force free to happen immediately. */\n{\n    if (colorPtr->refCount-- > 1) {\n\treturn;\n    }\n\n    if (force) {\n\tif (colorPtr->flags & DISPOSE_PENDING) {\n\t    Tcl_CancelIdleCall(DisposeColorTable, colorPtr);\n\t    colorPtr->flags &= ~DISPOSE_PENDING;\n\t}\n\tDisposeColorTable(colorPtr);\n    } else if (!(colorPtr->flags & DISPOSE_PENDING)) {\n\tTcl_DoWhenIdle(DisposeColorTable, colorPtr);\n\tcolorPtr->flags |= DISPOSE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AllocateColors --\n *\n *\tThis function allocates the colors required by a color table, and sets\n *\tup the fields in the color table data structure which are used in\n *\tdithering.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tColors are allocated from the X server. Fields in the color table data\n *\tstructure are updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAllocateColors(\n    ColorTable *colorPtr)\t/* Pointer to the color table requiring colors\n\t\t\t\t * to be allocated. */\n{\n    int i, r, g, b, rMult;\n    bool mono;\n    int numColors, nRed, nGreen, nBlue;\n    double fr, fg, fb, igam;\n    XColor *colors;\n    unsigned long *pixels;\n\n    /*\n     * 16-bit intensity value for i/n of full intensity.\n     */\n#define CFRAC(i, n)\t((i) * 65535 / (n))\n\n    /* As for CFRAC, but apply exponent of g. */\n#define CGFRAC(i, n, g)\t((int)(65535 * pow((double)(i) / (n), (g))))\n\n    /*\n     * First parse the palette specification to get the required number of\n     * shades of each primary.\n     */\n\n    mono = sscanf(colorPtr->id.palette, \"%d/%d/%d\", &nRed, &nGreen, &nBlue)\n\t    <= 1;\n    igam = 1.0 / colorPtr->id.gamma;\n\n    /*\n     * Each time around this loop, we reduce the number of colors we're trying\n     * to allocate until we succeed in allocating all of the colors we need.\n     */\n\n    for (;;) {\n\t/*\n\t * If we are using 1 bit/pixel, we don't need to allocate any colors\n\t * (we just use the foreground and background colors in the GC).\n\t */\n\n\tif (mono && (nRed <= 2)) {\n\t    colorPtr->flags |= BLACK_AND_WHITE;\n\t    return;\n\t}\n\n\t/*\n\t * Calculate the RGB coordinates of the colors we want to allocate and\n\t * store them in *colors.\n\t */\n\n\tif ((colorPtr->visualInfo.c_class == DirectColor)\n\t\t|| (colorPtr->visualInfo.c_class == TrueColor)) {\n\n\t    /*\n\t     * Direct/True Color: allocate shades of red, green, blue\n\t     * independently.\n\t     */\n\n\t    if (mono) {\n\t\tnumColors = nGreen = nBlue = nRed;\n\t    } else {\n\t\tnumColors = MAX(MAX(nRed, nGreen), nBlue);\n\t    }\n\t    colors = (XColor *)Tcl_Alloc(numColors * sizeof(XColor));\n\n\t    for (i = 0; i < numColors; ++i) {\n\t\tif (igam == 1.0) {\n\t\t    colors[i].red = CFRAC(i, nRed - 1);\n\t\t    colors[i].green = CFRAC(i, nGreen - 1);\n\t\t    colors[i].blue = CFRAC(i, nBlue - 1);\n\t\t} else {\n\t\t    colors[i].red = CGFRAC(i, nRed - 1, igam);\n\t\t    colors[i].green = CGFRAC(i, nGreen - 1, igam);\n\t\t    colors[i].blue = CGFRAC(i, nBlue - 1, igam);\n\t\t}\n\t    }\n\t} else {\n\t    /*\n\t     * PseudoColor, StaticColor, GrayScale or StaticGray visual: we\n\t     * have to allocate each color in the color cube separately.\n\t     */\n\n\t    numColors = (mono) ? nRed: (nRed * nGreen * nBlue);\n\t    colors = (XColor *)Tcl_Alloc(numColors * sizeof(XColor));\n\n\t    if (!mono) {\n\t\t/*\n\t\t * Color display using a PseudoColor or StaticColor visual.\n\t\t */\n\n\t\ti = 0;\n\t\tfor (r = 0; r < nRed; ++r) {\n\t\t    for (g = 0; g < nGreen; ++g) {\n\t\t\tfor (b = 0; b < nBlue; ++b) {\n\t\t\t    if (igam == 1.0) {\n\t\t\t\tcolors[i].red = CFRAC(r, nRed - 1);\n\t\t\t\tcolors[i].green = CFRAC(g, nGreen - 1);\n\t\t\t\tcolors[i].blue = CFRAC(b, nBlue - 1);\n\t\t\t    } else {\n\t\t\t\tcolors[i].red = CGFRAC(r, nRed - 1, igam);\n\t\t\t\tcolors[i].green = CGFRAC(g, nGreen - 1, igam);\n\t\t\t\tcolors[i].blue = CGFRAC(b, nBlue - 1, igam);\n\t\t\t    }\n\t\t\t    i++;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * Monochrome display - allocate the shades of gray we want.\n\t\t */\n\n\t\tfor (i = 0; i < numColors; ++i) {\n\t\t    if (igam == 1.0) {\n\t\t\tr = CFRAC(i, numColors - 1);\n\t\t    } else {\n\t\t\tr = CGFRAC(i, numColors - 1, igam);\n\t\t    }\n\t\t    colors[i].red = colors[i].green = colors[i].blue = r;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Now try to allocate the colors we've calculated.\n\t */\n\n\tpixels = (unsigned long *)Tcl_Alloc(numColors * sizeof(unsigned long));\n\tfor (i = 0; i < numColors; ++i) {\n\t    if (XAllocColor(colorPtr->id.display, colorPtr->id.colormap,\n\t\t    &colors[i]) == 0) {\n\t\t/*\n\t\t * Can't get all the colors we want in the default colormap;\n\t\t * first try freeing colors from other unused color tables.\n\t\t */\n\n\t\tif (!ReclaimColors(&colorPtr->id, numColors - i)\n\t\t\t|| XAllocColor(colorPtr->id.display,\n\t\t\tcolorPtr->id.colormap, &colors[i]) == 0) {\n\t\t    /*\n\t\t     * Still can't allocate the color.\n\t\t     */\n\n\t\t    break;\n\t\t}\n\t    }\n\t    pixels[i] = colors[i].pixel;\n\t}\n\n\t/*\n\t * If we didn't get all of the colors, reduce the resolution of the\n\t * color cube, free the ones we got, and try again.\n\t */\n\n\tif (i >= numColors) {\n\t    break;\n\t}\n\tXFreeColors(colorPtr->id.display, colorPtr->id.colormap, pixels, i, 0);\n\tTcl_Free(colors);\n\tTcl_Free(pixels);\n\n\tif (!mono) {\n\t    if ((nRed == 2) && (nGreen == 2) && (nBlue == 2)) {\n\t\t/*\n\t\t * Fall back to 1-bit monochrome display.\n\t\t */\n\n\t\tmono = true;\n\t    } else {\n\t\t/*\n\t\t * Reduce the number of shades of each primary to about 3/4 of\n\t\t * the previous value. This should reduce the total number of\n\t\t * colors required to about half the previous value for\n\t\t * PseudoColor displays.\n\t\t */\n\n\t\tnRed = (nRed * 3 + 2) / 4;\n\t\tnGreen = (nGreen * 3 + 2) / 4;\n\t\tnBlue = (nBlue * 3 + 2) / 4;\n\t    }\n\t} else {\n\t    /*\n\t     * Reduce the number of shades of gray to about 1/2.\n\t     */\n\n\t    nRed = nRed / 2;\n\t}\n    }\n\n    /*\n     * We have allocated all of the necessary colors: fill in various fields\n     * of the ColorTable record.\n     */\n\n    if (!mono) {\n\tcolorPtr->flags |= COLOR_WINDOW;\n\n\t/*\n\t * The following is a hairy hack. We only want to index into the\n\t * pixelMap on colormap displays. However, if the display is on\n\t * Windows, then we actually want to store the index not the value\n\t * since we will be passing the color table into the TkPutImage call.\n\t */\n\n#ifndef _WIN32\n\tif ((colorPtr->visualInfo.c_class != DirectColor)\n\t\t&& (colorPtr->visualInfo.c_class != TrueColor)) {\n\t    colorPtr->flags |= MAP_COLORS;\n\t}\n#endif /* _WIN32 */\n    }\n\n    colorPtr->numColors = numColors;\n    colorPtr->pixelMap = pixels;\n\n    /*\n     * Set up quantization tables for dithering.\n     */\n\n    rMult = nGreen * nBlue;\n    for (i = 0; i < 256; ++i) {\n\tr = (i * (nRed - 1) + 127) / 255;\n\tif (mono) {\n\t    fr = (double) colors[r].red / 65535.0;\n\t    if (colorPtr->id.gamma != 1.0 ) {\n\t\tfr = pow(fr, colorPtr->id.gamma);\n\t    }\n\t    colorPtr->colorQuant[0][i] = (int)(fr * 255.99);\n\t    colorPtr->redValues[i] = colors[r].pixel;\n\t} else {\n\t    g = (i * (nGreen - 1) + 127) / 255;\n\t    b = (i * (nBlue - 1) + 127) / 255;\n\t    if ((colorPtr->visualInfo.c_class == DirectColor)\n\t\t    || (colorPtr->visualInfo.c_class == TrueColor)) {\n\t\tcolorPtr->redValues[i] =\n\t\t\tcolors[r].pixel & colorPtr->visualInfo.red_mask;\n\t\tcolorPtr->greenValues[i] =\n\t\t\tcolors[g].pixel & colorPtr->visualInfo.green_mask;\n\t\tcolorPtr->blueValues[i] =\n\t\t\tcolors[b].pixel & colorPtr->visualInfo.blue_mask;\n\t    } else {\n\t\tr *= rMult;\n\t\tg *= nBlue;\n\t\tcolorPtr->redValues[i] = r;\n\t\tcolorPtr->greenValues[i] = g;\n\t\tcolorPtr->blueValues[i] = b;\n\t    }\n\t    fr = (double) colors[r].red / 65535.0;\n\t    fg = (double) colors[g].green / 65535.0;\n\t    fb = (double) colors[b].blue / 65535.0;\n\t    if (colorPtr->id.gamma != 1.0) {\n\t\tfr = pow(fr, colorPtr->id.gamma);\n\t\tfg = pow(fg, colorPtr->id.gamma);\n\t\tfb = pow(fb, colorPtr->id.gamma);\n\t    }\n\t    colorPtr->colorQuant[0][i] = (int)(fr * 255.99);\n\t    colorPtr->colorQuant[1][i] = (int)(fg * 255.99);\n\t    colorPtr->colorQuant[2][i] = (int)(fb * 255.99);\n\t}\n    }\n\n    Tcl_Free(colors);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisposeColorTable --\n *\n *\tRelease a color table and its associated resources.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe colors in the argument color table are freed, as is the color\n *\ttable structure itself. The color table is removed from the hash table\n *\twhich is used to locate color tables.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisposeColorTable(\n    void *clientData)\t/* Pointer to the ColorTable whose\n\t\t\t\t * colors are to be released. */\n{\n    ColorTable *colorPtr = (ColorTable *)clientData;\n    Tcl_HashEntry *entry;\n\n    if (colorPtr->pixelMap != NULL) {\n\tif (colorPtr->numColors > 0) {\n\t    XFreeColors(colorPtr->id.display, colorPtr->id.colormap,\n\t\t    colorPtr->pixelMap, colorPtr->numColors, 0);\n\t    Tk_FreeColormap(colorPtr->id.display, colorPtr->id.colormap);\n\t}\n\tTcl_Free(colorPtr->pixelMap);\n    }\n\n    entry = Tcl_FindHashEntry(&imgPhotoColorHash, &colorPtr->id);\n    if (entry == NULL) {\n\tTcl_Panic(\"DisposeColorTable couldn't find hash entry\");\n    }\n    Tcl_DeleteHashEntry(entry);\n\n    Tcl_Free(colorPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReclaimColors --\n *\n *\tThis function is called to try to free up colors in the colormap used\n *\tby a color table. It looks for other color tables with the same\n *\tcolormap and with a zero live reference count, and frees their colors.\n *\tIt only does so if there is the possibility of freeing up at least\n *\t`numColors' colors.\n *\n * Results:\n *\tThe return value is TRUE if any colors were freed, FALSE otherwise.\n *\n * Side effects:\n *\tColorTables which are not currently in use may lose their color\n *\tallocations.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReclaimColors(\n    ColorTableId *id,\t\t/* Pointer to information identifying\n\t\t\t\t * the color table which needs more colors. */\n    int numColors)\t\t/* Number of colors required. */\n{\n    Tcl_HashSearch srch;\n    Tcl_HashEntry *entry;\n    ColorTable *colorPtr;\n    int nAvail = 0;\n\n    /*\n     * First scan through the color hash table to get an upper bound on how\n     * many colors we might be able to free.\n     */\n\n    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);\n    while (entry != NULL) {\n\tcolorPtr = (ColorTable *)Tcl_GetHashValue(entry);\n\tif ((colorPtr->id.display == id->display)\n\t\t&& (colorPtr->id.colormap == id->colormap)\n\t\t&& (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0)\n\t\t&& ((colorPtr->id.palette != id->palette)\n\t\t\t|| (colorPtr->id.gamma != id->gamma))) {\n\t    /*\n\t     * We could take this guy's colors off him.\n\t     */\n\n\t    nAvail += colorPtr->numColors;\n\t}\n\tentry = Tcl_NextHashEntry(&srch);\n    }\n\n    /*\n     * nAvail is an (over)estimate of the number of colors we could free.\n     */\n\n    if (nAvail < numColors) {\n\treturn 0;\n    }\n\n    /*\n     * Scan through a second time freeing colors.\n     */\n\n    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);\n    while ((entry != NULL) && (numColors > 0)) {\n\tcolorPtr = (ColorTable *)Tcl_GetHashValue(entry);\n\tif ((colorPtr->id.display == id->display)\n\t\t&& (colorPtr->id.colormap == id->colormap)\n\t\t&& (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0)\n\t\t&& ((colorPtr->id.palette != id->palette)\n\t\t\t|| (colorPtr->id.gamma != id->gamma))) {\n\t    /*\n\t     * Free the colors that this ColorTable has.\n\t     */\n\n\t    XFreeColors(colorPtr->id.display, colorPtr->id.colormap,\n\t\t    colorPtr->pixelMap, colorPtr->numColors, 0);\n\t    numColors -= colorPtr->numColors;\n\t    colorPtr->numColors = 0;\n\t    Tcl_Free(colorPtr->pixelMap);\n\t    colorPtr->pixelMap = NULL;\n\t}\n\n\tentry = Tcl_NextHashEntry(&srch);\n    }\n    return 1;\t\t\t/* We freed some colors. */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgDisposeInstance --\n *\n *\tThis function is called to finally free up an instance of a photo\n *\timage which is no longer required.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe instance data structure and the resources it references are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgDisposeInstance(\n    void *clientData)\t/* Pointer to the instance whose resources are\n\t\t\t\t * to be released. */\n{\n    PhotoInstance *instancePtr = (PhotoInstance *)clientData;\n    PhotoInstance *prevPtr;\n\n    if (instancePtr->pixels != None) {\n\tTk_FreePixmap(instancePtr->display, instancePtr->pixels);\n    }\n    if (instancePtr->gc != NULL) {\n\tTk_FreeGC(instancePtr->display, instancePtr->gc);\n    }\n    if (instancePtr->imagePtr != NULL) {\n\tXDestroyImage(instancePtr->imagePtr);\n    }\n    if (instancePtr->error != NULL) {\n\tTcl_Free(instancePtr->error);\n    }\n    if (instancePtr->colorTablePtr != NULL) {\n\tFreeColorTable(instancePtr->colorTablePtr, 1);\n    }\n\n    if (instancePtr->modelPtr->instancePtr == instancePtr) {\n\tinstancePtr->modelPtr->instancePtr = instancePtr->nextPtr;\n    } else {\n\tfor (prevPtr = instancePtr->modelPtr->instancePtr;\n\t\tprevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {\n\t    /* Empty loop body. */\n\t}\n\tprevPtr->nextPtr = instancePtr->nextPtr;\n    }\n    Tk_FreeColormap(instancePtr->display, instancePtr->colormap);\n    Tcl_Free(instancePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgDitherInstance --\n *\n *\tThis function is called to update an area of an instance's pixmap by\n *\tdithering the corresponding area of the model.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe instance's pixmap gets updated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgDitherInstance(\n    PhotoInstance *instancePtr,\t/* The instance to be updated. */\n    int xStart, int yStart,\t/* Coordinates of the top-left pixel in the\n\t\t\t\t * block to be dithered. */\n    int width, int height)\t/* Dimensions of the block to be dithered. */\n{\n    PhotoModel *modelPtr = instancePtr->modelPtr;\n    ColorTable *colorPtr = instancePtr->colorTablePtr;\n    XImage *imagePtr;\n    int nLines, bigEndian, i, c, x, y, xEnd;\n    bool doDithering = true;\n    int bitsPerPixel, bytesPerLine, lineLength;\n    unsigned char *srcLinePtr;\n    schar *errLinePtr;\n    unsigned firstBit, word, mask;\n\n    /*\n     * Turn dithering off in certain cases where it is not needed (TrueColor,\n     * DirectColor with many colors).\n     */\n\n    if ((colorPtr->visualInfo.c_class == DirectColor)\n\t    || (colorPtr->visualInfo.c_class == TrueColor)) {\n\tint nRed, nGreen, nBlue, result;\n\n\tresult = sscanf(colorPtr->id.palette, \"%d/%d/%d\", &nRed,\n\t\t&nGreen, &nBlue);\n\tif ((nRed >= 256)\n\t\t&& ((result == 1) || ((nGreen >= 256) && (nBlue >= 256)))) {\n\t    doDithering = false;\n\t}\n    }\n\n    /*\n     * First work out how many lines to do at a time, then how many bytes\n     * we'll need for pixel storage, and allocate it.\n     */\n\n    nLines = (MAX_PIXELS + width - 1) / width;\n    if (nLines < 1) {\n\tnLines = 1;\n    }\n    if (nLines > height ) {\n\tnLines = height;\n    }\n\n    imagePtr = instancePtr->imagePtr;\n    if (imagePtr == NULL) {\n\treturn;\t\t\t/* We must be really tight on memory. */\n    }\n    bitsPerPixel = imagePtr->bits_per_pixel;\n    bytesPerLine = ((bitsPerPixel * width + 31) >> 3) & ~3;\n    imagePtr->width = width;\n    imagePtr->height = nLines;\n    imagePtr->bytes_per_line = bytesPerLine;\n\n    /*\n     * TODO: use Tcl_AttemptAlloc() here once we have some strategy for\n     * recovering from the failure.\n     */\n\n    imagePtr->data = (char *)Tcl_Alloc(imagePtr->bytes_per_line * nLines);\n    bigEndian = imagePtr->bitmap_bit_order == MSBFirst;\n    firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1;\n\n    lineLength = modelPtr->width * 3;\n    srcLinePtr = modelPtr->pix32 + (yStart * modelPtr->width + xStart) * 4;\n    errLinePtr = instancePtr->error + yStart * lineLength + xStart * 3;\n    xEnd = xStart + width;\n\n    /*\n     * Loop over the image, doing at most nLines lines before updating the\n     * screen image.\n     */\n\n    for (; height > 0; height -= nLines) {\n\tunsigned char *dstLinePtr = (unsigned char *) imagePtr->data;\n\tint yEnd;\n\n\tif (nLines > height) {\n\t    nLines = height;\n\t}\n\tyEnd = yStart + nLines;\n\tfor (y = yStart; y < yEnd; ++y) {\n\t    unsigned char *srcPtr = srcLinePtr;\n\t    schar *errPtr = errLinePtr;\n\t    unsigned char *destBytePtr = dstLinePtr;\n\t    unsigned *destLongPtr = (unsigned *) dstLinePtr;\n\n\t    if (colorPtr->flags & COLOR_WINDOW) {\n\t\t/*\n\t\t * Color window. We dither the three components independently,\n\t\t * using Floyd-Steinberg dithering, which propagates errors\n\t\t * from the quantization of pixels to the pixels below and to\n\t\t * the right.\n\t\t */\n\n\t\tfor (x = xStart; x < xEnd; ++x) {\n\t\t    int col[3];\n\n\t\t    if (doDithering) {\n\t\t\tfor (i = 0; i < 3; ++i) {\n\t\t\t    /*\n\t\t\t     * Compute the error propagated into this pixel\n\t\t\t     * for this component. If e[x,y] is the array of\n\t\t\t     * quantization error values, we compute\n\t\t\t     *     7/16 * e[x-1,y] + 1/16 * e[x-1,y-1]\n\t\t\t     *   + 5/16 * e[x,y-1] + 3/16 * e[x+1,y-1]\n\t\t\t     * and round it to an integer.\n\t\t\t     *\n\t\t\t     * The expression ((c + 2056) >> 4) - 128 computes\n\t\t\t     * round(c / 16), and works correctly on machines\n\t\t\t     * without a sign-extending right shift.\n\t\t\t     */\n\n\t\t\t    c = (x > 0) ? errPtr[-3] * 7: 0;\n\t\t\t    if (y > 0) {\n\t\t\t\tif (x > 0) {\n\t\t\t\t    c += errPtr[-lineLength-3];\n\t\t\t\t}\n\t\t\t\tc += errPtr[-lineLength] * 5;\n\t\t\t\tif ((x + 1) < modelPtr->width) {\n\t\t\t\t    c += errPtr[-lineLength+3] * 3;\n\t\t\t\t}\n\t\t\t    }\n\n\t\t\t    /*\n\t\t\t     * Add the propagated error to the value of this\n\t\t\t     * component, quantize it, and store the\n\t\t\t     * quantization error.\n\t\t\t     */\n\n\t\t\t    c = ((c + 2056) >> 4) - 128 + *srcPtr++;\n\t\t\t    if (c < 0) {\n\t\t\t\tc = 0;\n\t\t\t    } else if (c > 255) {\n\t\t\t\tc = 255;\n\t\t\t    }\n\t\t\t    col[i] = colorPtr->colorQuant[i][c];\n\t\t\t    *errPtr++ = c - col[i];\n\t\t\t}\n\t\t    } else {\n\t\t\t/*\n\t\t\t * Output is virtually continuous in this case, so\n\t\t\t * don't bother dithering.\n\t\t\t */\n\n\t\t\tcol[0] = *srcPtr++;\n\t\t\tcol[1] = *srcPtr++;\n\t\t\tcol[2] = *srcPtr++;\n\t\t    }\n\t\t    srcPtr++;\n\n\t\t    /*\n\t\t     * Translate the quantized component values into an X\n\t\t     * pixel value, and store it in the image.\n\t\t     */\n\n\t\t    i = colorPtr->redValues[col[0]]\n\t\t\t    + colorPtr->greenValues[col[1]]\n\t\t\t    + colorPtr->blueValues[col[2]];\n\t\t    if (colorPtr->flags & MAP_COLORS) {\n\t\t\ti = colorPtr->pixelMap[i];\n\t\t    }\n\t\t    switch (bitsPerPixel) {\n\t\t    case NBBY:\n\t\t\t*destBytePtr++ = i;\n\t\t\tbreak;\n#ifndef _WIN32\n\t\t\t/*\n\t\t\t * This case is not valid for Windows because the\n\t\t\t * image format is different from the pixel format in\n\t\t\t * Win32. Eventually we need to fix the image code in\n\t\t\t * Tk to use the Windows native image ordering. This\n\t\t\t * would speed up the image code for all of the common\n\t\t\t * sizes.\n\t\t\t */\n\n\t\t    case NBBY * sizeof(unsigned):\n\t\t\t*destLongPtr++ = i;\n\t\t\tbreak;\n#endif\n\t\t    default:\n\t\t\tXPutPixel(imagePtr, x - xStart, y - yStart,\n\t\t\t\t(unsigned) i);\n\t\t    }\n\t\t}\n\n\t    } else if (bitsPerPixel > 1) {\n\t\t/*\n\t\t * Multibit monochrome window. The operation here is similar\n\t\t * to the color window case above, except that there is only\n\t\t * one component. If the model image is in color, use the\n\t\t * luminance computed as\n\t\t *\t0.344 * red + 0.5 * green + 0.156 * blue.\n\t\t */\n\n\t\tfor (x = xStart; x < xEnd; ++x) {\n\t\t    c = (x > 0) ? errPtr[-1] * 7: 0;\n\t\t    if (y > 0) {\n\t\t\tif (x > 0) {\n\t\t\t    c += errPtr[-lineLength-1];\n\t\t\t}\n\t\t\tc += errPtr[-lineLength] * 5;\n\t\t\tif (x + 1 < modelPtr->width) {\n\t\t\t    c += errPtr[-lineLength+1] * 3;\n\t\t\t}\n\t\t    }\n\t\t    c = ((c + 2056) >> 4) - 128;\n\n\t\t    if (modelPtr->flags & COLOR_IMAGE) {\n\t\t\tc += (unsigned) (srcPtr[0] * 11 + srcPtr[1] * 16\n\t\t\t\t+ srcPtr[2] * 5 + 16) >> 5;\n\t\t    } else {\n\t\t\tc += srcPtr[0];\n\t\t    }\n\t\t    srcPtr += 4;\n\n\t\t    if (c < 0) {\n\t\t\tc = 0;\n\t\t    } else if (c > 255) {\n\t\t\tc = 255;\n\t\t    }\n\t\t    i = colorPtr->colorQuant[0][c];\n\t\t    *errPtr++ = c - i;\n\t\t    i = colorPtr->redValues[i];\n\t\t    switch (bitsPerPixel) {\n\t\t    case NBBY:\n\t\t\t*destBytePtr++ = i;\n\t\t\tbreak;\n#ifndef _WIN32\n\t\t\t/*\n\t\t\t * This case is not valid for Windows because the\n\t\t\t * image format is different from the pixel format in\n\t\t\t * Win32. Eventually we need to fix the image code in\n\t\t\t * Tk to use the Windows native image ordering. This\n\t\t\t * would speed up the image code for all of the common\n\t\t\t * sizes.\n\t\t\t */\n\n\t\t    case NBBY * sizeof(unsigned):\n\t\t\t*destLongPtr++ = i;\n\t\t\tbreak;\n#endif\n\t\t    default:\n\t\t\tXPutPixel(imagePtr, x - xStart, y - yStart,\n\t\t\t\t(unsigned) i);\n\t\t    }\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * 1-bit monochrome window. This is similar to the multibit\n\t\t * monochrome case above, except that the quantization is\n\t\t * simpler (we only have black = 0 and white = 255), and we\n\t\t * produce an XY-Bitmap.\n\t\t */\n\n\t\tword = 0;\n\t\tmask = firstBit;\n\t\tfor (x = xStart; x < xEnd; ++x) {\n\t\t    /*\n\t\t     * If we have accumulated a whole word, store it in the\n\t\t     * image and start a new word.\n\t\t     */\n\n\t\t    if (mask == 0) {\n\t\t\t*destLongPtr++ = word;\n\t\t\tmask = firstBit;\n\t\t\tword = 0;\n\t\t    }\n\n\t\t    c = (x > 0) ? errPtr[-1] * 7: 0;\n\t\t    if (y > 0) {\n\t\t\tif (x > 0) {\n\t\t\t    c += errPtr[-lineLength-1];\n\t\t\t}\n\t\t\tc += errPtr[-lineLength] * 5;\n\t\t\tif (x + 1 < modelPtr->width) {\n\t\t\t    c += errPtr[-lineLength+1] * 3;\n\t\t\t}\n\t\t    }\n\t\t    c = ((c + 2056) >> 4) - 128;\n\n\t\t    if (modelPtr->flags & COLOR_IMAGE) {\n\t\t\tc += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16\n\t\t\t\t+ srcPtr[2] * 5 + 16) >> 5;\n\t\t    } else {\n\t\t\tc += srcPtr[0];\n\t\t    }\n\t\t    srcPtr += 4;\n\n\t\t    if (c < 0) {\n\t\t\tc = 0;\n\t\t    } else if (c > 255) {\n\t\t\tc = 255;\n\t\t    }\n\t\t    if (c >= 128) {\n\t\t\tword |= mask;\n\t\t\t*errPtr++ = c - 255;\n\t\t    } else {\n\t\t\t*errPtr++ = c;\n\t\t    }\n\t\t    mask = bigEndian? (mask >> 1): (mask << 1);\n\t\t}\n\t\t*destLongPtr = word;\n\t    }\n\t    srcLinePtr += modelPtr->width * 4;\n\t    errLinePtr += lineLength;\n\t    dstLinePtr += bytesPerLine;\n\t}\n\n\t/*\n\t * Update the pixmap for this instance with the block of pixels that\n\t * we have just computed.\n\t */\n\n\tTkPutImage(colorPtr->pixelMap, colorPtr->numColors,\n\t\tinstancePtr->display, instancePtr->pixels,\n\t\tinstancePtr->gc, imagePtr, 0, 0, xStart, yStart,\n\t\t(unsigned) width, (unsigned) nLines);\n\tyStart = yEnd;\n    }\n\n    Tcl_Free(imagePtr->data);\n    imagePtr->data = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkImgResetDither --\n *\n *\tThis function is called to eliminate the content of a photo instance's\n *\tdither error buffer. It's called when the overall image is blanked.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe instance's dither buffer gets cleared.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkImgResetDither(\n    PhotoInstance *instancePtr)\n{\n    if (instancePtr->error) {\n\tmemset(instancePtr->error, 0,\n\t\t(size_t) instancePtr->modelPtr->width\n\t\t* instancePtr->modelPtr->height * 3 * sizeof(schar));\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgPhoto.c",
    "content": "/*\n * tkImgPhoto.c --\n *\n *\tImplements images of type \"photo\" for Tk. Photo images are stored in\n *\tfull color (32 bits per pixel including alpha channel) and displayed\n *\tusing dithering if necessary.\n *\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2002-2003 Donal K. Fellows\n * Copyright © 2003 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Author: Paul Mackerras (paulus@cs.anu.edu.au),\n *\t   Department of Computer Science,\n *\t   Australian National University.\n */\n\n#include \"tkImgPhoto.h\"\n\n/*\n * The following data structure is used to return information from\n * ParseSubcommandOptions:\n */\n\nstruct SubcommandOptions {\n    int options;\t\t/* Individual bits indicate which options were\n\t\t\t\t * specified - see below. */\n    Tcl_Obj *name;\t\t/* Name specified without an option. */\n    int fromX, fromY;\t\t/* Values specified for -from option. */\n    int fromX2, fromY2;\t\t/* Second coordinate pair for -from option. */\n    int toX, toY;\t\t/* Values specified for -to option. */\n    int toX2, toY2;\t\t/* Second coordinate pair for -to option. */\n    int zoomX, zoomY;\t\t/* Values specified for -zoom option. */\n    int subsampleX, subsampleY;\t/* Values specified for -subsample option. */\n    Tcl_Obj *format;\t\t/* Value specified for -format option. */\n    XColor *background;\t\t/* Value specified for -background option. */\n    int compositingRule;\t/* Value specified for -compositingrule\n\t\t\t\t * option. */\n    Tcl_Obj *metadata;\t\t/* Value specified for -metadata option. */\n};\n\n/*\n * Bit definitions for use with ParseSubcommandOptions: each bit is set in the\n * allowedOptions parameter on a call to ParseSubcommandOptions if that option\n * is allowed for the current photo image subcommand. On return, the bit is\n * set in the options field of the SubcommandOptions structure if that option\n * was specified.\n *\n * OPT_ALPHA:\t\t\tSet if -alpha option allowed/specified.\n * OPT_BACKGROUND:\t\tSet if -format option allowed/specified.\n * OPT_COMPOSITE:\t\tSet if -compositingrule option allowed/spec'd.\n * OPT_FORMAT:\t\t\tSet if -format option allowed/specified.\n * OPT_FROM:\t\t\tSet if -from option allowed/specified.\n * OPT_GRAYSCALE:\t\tSet if -grayscale option allowed/specified.\n * OPT_METADATA:\t\tSet if -metadata option allowed/specified.\n * OPT_SHRINK:\t\t\tSet if -shrink option allowed/specified.\n * OPT_SUBSAMPLE:\t\tSet if -subsample option allowed/spec'd.\n * OPT_TO:\t\t\tSet if -to option allowed/specified.\n * OPT_WITHALPHA:\t\tSet if -withalpha option allowed/specified.\n * OPT_ZOOM:\t\t\tSet if -zoom option allowed/specified.\n */\n\n#define OPT_ALPHA\t1\n#define OPT_BACKGROUND\t2\n#define OPT_COMPOSITE\t4\n#define OPT_FORMAT\t8\n#define OPT_FROM\t0x10\n#define OPT_GRAYSCALE\t0x20\n#define OPT_METADATA\t0x40\n#define OPT_SHRINK\t0x80\n#define OPT_SUBSAMPLE\t0x100\n#define OPT_TO\t\t0x200\n#define OPT_WITHALPHA\t0x400\n#define OPT_ZOOM\t0x800\n\n/*\n * List of option names. The order here must match the order of declarations\n * of the OPT_* constants above.\n */\n\nstatic const char *const optionNames[] = {\n    \"-alpha\",\n    \"-background\",\n    \"-compositingrule\",\n    \"-format\",\n    \"-from\",\n    \"-grayscale\",\n    \"-metadata\",\n    \"-shrink\",\n    \"-subsample\",\n    \"-to\",\n    \"-withalpha\",\n    \"-zoom\",\n    NULL\n};\n\n/*\n * Message to generate when an attempt to resize an image fails due to memory\n * problems.\n */\n\n#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \\\n\t\"not enough free memory for image buffer\"\n\n/*\n * Functions used in the type record for photo images.\n */\n\nstatic int\t\tImgPhotoCreate(Tcl_Interp *interp, const char *name,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    const Tk_ImageType *typePtr, Tk_ImageModel model,\n\t\t\t    void **clientDataPtr);\nstatic void\t\tImgPhotoDelete(void *clientData);\nstatic int\t\tImgPhotoPostscript(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tk_PostscriptInfo psInfo, int x, int y, int width,\n\t\t\t    int height, int prepass);\n\n/*\n * The type record itself for photo images:\n */\n\nTk_ImageType tkPhotoImageType = {\n    \"photo\",\t\t\t/* name */\n    ImgPhotoCreate,\t\t/* createProc */\n    TkImgPhotoGet,\t\t/* getProc */\n    TkImgPhotoDisplay,\t\t/* displayProc */\n    TkImgPhotoFree,\t\t/* freeProc */\n    ImgPhotoDelete,\t\t/* deleteProc */\n    ImgPhotoPostscript,\t\t/* postscriptProc */\n    NULL,\t\t\t/* nextPtr */\n    NULL\n};\n\ntypedef struct {\n    Tk_PhotoImageFormat *formatList;\n\t\t\t\t/* Pointer to the first in the list of known\n\t\t\t\t * photo image formats.*/\n    Tk_PhotoImageFormatVersion3 *formatListVersion3;\n\t\t\t\t/* Pointer to the first in the list of known\n\t\t\t\t * photo image formats in Version3 format.*/\n    bool initialized;\t\t/* Set to true if we've initialized the\n\t\t\t\t * structure. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Default configuration\n */\n\n#define DEF_PHOTO_GAMMA\t\t\"1\"\n#define DEF_PHOTO_HEIGHT\t\"0\"\n#define DEF_PHOTO_PALETTE\t\"\"\n#define DEF_PHOTO_WIDTH\t\t\"0\"\n\n/*\n * Information used for parsing configuration specifications:\n */\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_STRING, \"-data\", NULL, NULL,\n\t NULL, TCL_INDEX_NONE, TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_STRING, \"-file\", NULL, NULL,\n\t NULL, offsetof(PhotoModel, fileObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_STRING, \"-format\", NULL, NULL,\n\t NULL, TCL_INDEX_NONE, TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_DOUBLE, \"-gamma\", NULL, NULL,\n\t DEF_PHOTO_GAMMA, offsetof(PhotoModel, gamma), 0, NULL},\n    {TK_CONFIG_INT, \"-height\", NULL, NULL,\n\t DEF_PHOTO_HEIGHT, offsetof(PhotoModel, userHeight), 0, NULL},\n    {TK_CONFIG_STRING, \"-metadata\", NULL, NULL,\n\t NULL, TCL_INDEX_NONE, TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_UID, \"-palette\", NULL, NULL,\n\t DEF_PHOTO_PALETTE, offsetof(PhotoModel, palette), 0, NULL},\n    {TK_CONFIG_INT, \"-width\", NULL, NULL,\n\t DEF_PHOTO_WIDTH, offsetof(PhotoModel, userWidth), 0, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Forward declarations\n */\n\nstatic void\t\tPhotoFormatThreadExitProc(void *clientData);\nstatic Tcl_ObjCmdProc2 ImgPhotoCmd;\nstatic int\t\tParseSubcommandOptions(\n\t\t\t    struct SubcommandOptions *optPtr,\n\t\t\t    Tcl_Interp *interp, int allowedOptions,\n\t\t\t    Tcl_Size *indexPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tImgPhotoCmdDeletedProc(void *clientData);\nstatic int\t\tImgPhotoConfigureModel(Tcl_Interp *interp,\n\t\t\t    PhotoModel *modelPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic int\t\tToggleComplexAlphaIfNeeded(PhotoModel *mPtr);\nstatic int\t\tImgPhotoSetSize(PhotoModel *modelPtr, int width,\n\t\t\t    int height);\nstatic char *\t\tImgGetPhoto(PhotoModel *modelPtr,\n\t\t\t    Tk_PhotoImageBlock *blockPtr,\n\t\t\t    struct SubcommandOptions *optPtr);\nstatic int\t\tMatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *formatString,\n\t\t\t    Tcl_Obj *metadataInObj,\n\t\t\t    Tcl_Obj *metadataOutObj,\n\t\t\t    Tk_PhotoImageFormat **imageFormatPtr,\n\t\t\t    Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic int\t\tMatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data,\n\t\t\t    Tcl_Obj *formatString,\n\t\t\t    Tcl_Obj *metadataInObj,\n\t\t\t    Tcl_Obj *metadataOutObj,\n\t\t\t    Tk_PhotoImageFormat **imageFormatPtr,\n\t\t\t    Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic const char *\tGetExtension(const char *path);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PhotoFormatThreadExitProc --\n *\n *\tClean up the registered list of photo formats.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe thread's linked lists of photo image formats is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPhotoFormatThreadExitProc(\n    TCL_UNUSED(void *))\t/* not used */\n{\n    Tk_PhotoImageFormat *freePtr;\n    Tk_PhotoImageFormatVersion3 *freePtrVersion3;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    while (tsdPtr->formatList != NULL) {\n\tfreePtr = tsdPtr->formatList;\n\ttsdPtr->formatList = tsdPtr->formatList->nextPtr;\n\tTcl_Free((void *)freePtr->name);\n\tTcl_Free(freePtr);\n    }\n    while (tsdPtr->formatListVersion3 != NULL) {\n\tfreePtrVersion3 = tsdPtr->formatListVersion3;\n\ttsdPtr->formatListVersion3 = tsdPtr->formatListVersion3->nextPtr;\n\tTcl_Free((void *)freePtrVersion3->name);\n\tTcl_Free(freePtrVersion3);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreatePhotoImageFormat,\n * Tk_CreatePhotoImageFormatVersion3 --\n *\n *\tThis function is invoked by an image file handler to register a new\n *\tphoto image format and the functions that handle the new format. The\n *\tfunction is typically invoked during Tcl_AppInit.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe new image file format is entered into a table used in the photo\n *\timage \"read\" and \"write\" subcommands.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_CreatePhotoImageFormat(\n    const Tk_PhotoImageFormat *formatPtr)\n\t\t\t\t/* Structure describing the format. All of the\n\t\t\t\t * fields except \"nextPtr\" must be filled in\n\t\t\t\t * by caller. */\n{\n    Tk_PhotoImageFormat *copyPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\tTcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);\n    }\n    copyPtr = (Tk_PhotoImageFormat *)Tcl_Alloc(sizeof(Tk_PhotoImageFormat));\n    *copyPtr = *formatPtr;\n    {\n\t/* for compatibility with aMSN: make a copy of formatPtr->name */\n\tchar *name = (char *)Tcl_Alloc(strlen(formatPtr->name) + 1);\n\tstrcpy(name, formatPtr->name);\n\tcopyPtr->name = name;\n\tcopyPtr->nextPtr = tsdPtr->formatList;\n\ttsdPtr->formatList = copyPtr;\n    }\n}\nvoid\nTk_CreatePhotoImageFormatVersion3(\n    const Tk_PhotoImageFormatVersion3 *formatPtr)\n\t\t\t\t/* Structure describing the format. All of the\n\t\t\t\t * fields except \"nextPtr\" must be filled in\n\t\t\t\t * by caller. */\n{\n    Tk_PhotoImageFormatVersion3 *copyPtr;\n    char *name;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\tTcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);\n    }\n    copyPtr = (Tk_PhotoImageFormatVersion3 *)\n\t    Tcl_Alloc(sizeof(Tk_PhotoImageFormatVersion3));\n    *copyPtr = *formatPtr;\n    /* for compatibility with aMSN: make a copy of formatPtr->name */\n    name = (char *)Tcl_Alloc(strlen(formatPtr->name) + 1);\n    strcpy(name, formatPtr->name);\n    copyPtr->name = name;\n    copyPtr->nextPtr = tsdPtr->formatListVersion3;\n    tsdPtr->formatListVersion3 = copyPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoCreate --\n *\n *\tThis function is called by the Tk image code to create a new photo\n *\timage.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe data structure for a new photo image is allocated and initialized.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgPhotoCreate(\n    Tcl_Interp *interp,\t\t/* Interpreter for application containing\n\t\t\t\t * image. */\n    const char *name,\t\t/* Name to use for image. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects for options (doesn't\n\t\t\t\t * include image name or type). */\n    TCL_UNUSED(const Tk_ImageType *),/* Pointer to our type record (not used). */\n    Tk_ImageModel model,\t/* Token for image, to be used by us in later\n\t\t\t\t * callbacks. */\n    void **clientDataPtr)\t/* Store manager's token for image here; it\n\t\t\t\t * will be returned in later callbacks. */\n{\n    PhotoModel *modelPtr;\n\n    /*\n     * Allocate and initialize the photo image model record.\n     */\n\n    modelPtr = (PhotoModel *)Tcl_Alloc(sizeof(PhotoModel));\n    memset(modelPtr, 0, sizeof(PhotoModel));\n    modelPtr->tkModel = model;\n    modelPtr->interp = interp;\n    modelPtr->imageCmd = Tcl_CreateObjCommand2(interp, name, ImgPhotoCmd,\n\t    modelPtr, ImgPhotoCmdDeletedProc);\n    modelPtr->palette = NULL;\n    modelPtr->pix32 = NULL;\n    modelPtr->instancePtr = NULL;\n    modelPtr->validRegion = XCreateRegion();\n\n    /*\n     * Process configuration options given in the image create command.\n     */\n\n    if (ImgPhotoConfigureModel(interp, modelPtr, objc, objv, 0) != TCL_OK) {\n\tImgPhotoDelete(modelPtr);\n\treturn TCL_ERROR;\n    }\n\n    *clientDataPtr = modelPtr;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a photo image. See the user documentation for details on what it\n *\tdoes.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgPhotoCmd(\n    void *clientData,\t/* Information about photo model. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const photoOptions[] = {\n\t\"blank\", \"cget\", \"configure\", \"copy\", \"data\", \"get\", \"put\",\n\t\"read\", \"redither\", \"transparency\", \"write\", NULL\n    };\n    enum PhotoOptions {\n\tPHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,\n\tPHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS,\n\tPHOTO_WRITE\n    };\n\n    PhotoModel *modelPtr = (PhotoModel *)clientData;\n    int result, x, y, width, height;\n    Tcl_Size index;\n    struct SubcommandOptions options;\n    unsigned char *pixelPtr;\n    Tk_PhotoImageBlock block;\n    Tk_PhotoImageFormat *imageFormat;\n    Tk_PhotoImageFormatVersion3 *imageFormatVersion3;\n    Tcl_Size length;\n    int imageWidth, imageHeight;\n    bool matched;\n    Tcl_Channel chan;\n    Tk_PhotoHandle srcHandle;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum PhotoOptions) index) {\n    case PHOTO_BLANK:\n\t/*\n\t * photo blank command - just call Tk_PhotoBlank.\n\t */\n\n\tif (objc == 2) {\n\t    Tk_PhotoBlank(modelPtr);\n\t    return TCL_OK;\n\t} else {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\n    case PHOTO_CGET: {\n\tconst char *arg;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    return TCL_ERROR;\n\t}\n\targ = Tcl_GetStringFromObj(objv[2], &length);\n\tif (strncmp(arg,\"-data\", length) == 0) {\n\t    if (modelPtr->dataObj) {\n\t\tTcl_SetObjResult(interp, modelPtr->dataObj);\n\t    }\n\t} else if (strncmp(arg,\"-format\", length) == 0) {\n\t    if (modelPtr->format) {\n\t\tTcl_SetObjResult(interp, modelPtr->format);\n\t    }\n\t} else if (strncmp(arg, \"-metadata\", length) == 0) {\n\t    if (modelPtr->metadata) {\n\t\tTcl_SetObjResult(interp, modelPtr->metadata);\n\t    }\n\t} else {\n\t    Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,\n\t\t    modelPtr, Tcl_GetString(objv[2]), 0);\n\t}\n\treturn TCL_OK;\n    }\n\n    case PHOTO_CONFIGURE:\n\t/*\n\t * photo configure command - handle this in the standard way.\n\t */\n\n\tif (objc == 2) {\n\t    Tcl_Obj *obj, *subobj;\n\n\t    result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),\n\t\t    configSpecs, modelPtr, NULL, 0);\n\t    if (result != TCL_OK) {\n\t\treturn result;\n\t    }\n\t    obj = Tcl_NewObj();\n\t    subobj = Tcl_NewStringObj(\"-data {} {} {}\", 14);\n\t    if (modelPtr->dataObj) {\n\t\tTcl_ListObjAppendElement(NULL, subobj, modelPtr->dataObj);\n\t    } else {\n\t\tTcl_AppendStringsToObj(subobj, \" {}\", (char *)NULL);\n\t    }\n\t    Tcl_ListObjAppendElement(interp, obj, subobj);\n\t    subobj = Tcl_NewStringObj(\"-format {} {} {}\", 16);\n\t    if (modelPtr->format) {\n\t\tTcl_ListObjAppendElement(NULL, subobj, modelPtr->format);\n\t    } else {\n\t\tTcl_AppendStringsToObj(subobj, \" {}\", (char *)NULL);\n\t    }\n\t    Tcl_ListObjAppendElement(interp, obj, subobj);\n\t    subobj = Tcl_NewStringObj(\"-metadata {} {} {}\", 18);\n\t    if (modelPtr->metadata) {\n\t\tTcl_ListObjAppendElement(NULL, subobj, modelPtr->metadata);\n\t    } else {\n\t\tTcl_AppendStringsToObj(subobj, \" {}\", (char *)NULL);\n\t    }\n\t    Tcl_ListObjAppendElement(interp, obj, subobj);\n\t    Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp));\n\t    Tcl_SetObjResult(interp, obj);\n\t    return TCL_OK;\n\n\t} else if (objc == 3) {\n\t    const char *arg = Tcl_GetStringFromObj(objv[2], &length);\n\n\t    if (length > 1 && !strncmp(arg, \"-data\", length)) {\n\t\tTcl_AppendResult(interp, \"-data {} {} {}\", (char *)NULL);\n\t\tif (modelPtr->dataObj) {\n\t\t    /*\n\t\t     * TODO: Modifying result is bad!\n\t\t     */\n\n\t\t    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),\n\t\t\t    modelPtr->dataObj);\n\t\t} else {\n\t\t    Tcl_AppendResult(interp, \" {}\", (char *)NULL);\n\t\t}\n\t\treturn TCL_OK;\n\t    } else if (length > 1 &&\n\t\t    !strncmp(arg, \"-format\", length)) {\n\t\tTcl_AppendResult(interp, \"-format {} {} {}\", (char *)NULL);\n\t\tif (modelPtr->format) {\n\t\t    /*\n\t\t     * TODO: Modifying result is bad!\n\t\t     */\n\n\t\t    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),\n\t\t\t    modelPtr->format);\n\t\t} else {\n\t\t    Tcl_AppendResult(interp, \" {}\", (char *)NULL);\n\t\t}\n\t\treturn TCL_OK;\n\t    } else if (length > 1 &&\n\t\t!strncmp(arg, \"-metadata\", length)) {\n\t\tTcl_AppendResult(interp, \"-metadata {} {} {}\", (char *)NULL);\n\t\tif (modelPtr->metadata) {\n\t\t    /*\n\t\t     * TODO: Modifying result is bad!\n\t\t     */\n\n\t\t    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),\n\t\t\tmodelPtr->metadata);\n\t\t} else {\n\t\t    Tcl_AppendResult(interp, \" {}\", (char *)NULL);\n\t\t}\n\t\treturn TCL_OK;\n\t    } else {\n\t\treturn Tk_ConfigureInfo(interp, Tk_MainWindow(interp),\n\t\t\tconfigSpecs, modelPtr, arg, 0);\n\t    }\n\t} else {\n\t    return ImgPhotoConfigureModel(interp, modelPtr, objc-2, objv+2,\n\t\t    TK_CONFIG_ARGV_ONLY);\n\t}\n\n    case PHOTO_COPY:\n\t/*\n\t * photo copy command - first parse options.\n\t */\n\n\tindex = 2;\n\tmemset(&options, 0, sizeof(options));\n\toptions.zoomX = options.zoomY = 1;\n\toptions.subsampleX = options.subsampleY = 1;\n\toptions.name = NULL;\n\toptions.compositingRule = TK_PHOTO_COMPOSITE_OVERLAY;\n\tif (ParseSubcommandOptions(&options, interp,\n\t\tOPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK |\n\t\tOPT_COMPOSITE, &index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (options.name == NULL || index < objc) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Look for the source image and get a pointer to its image data.\n\t * Check the values given for the -from option.\n\t */\n\n\tsrcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name));\n\tif (srcHandle == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"image \\\"%s\\\" does not exist or is not a photo image\",\n\t\t    Tcl_GetString(options.name)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"PHOTO\",\n\t\t    Tcl_GetString(options.name), (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_PhotoGetImage(srcHandle, &block);\n\tif ((options.fromX > block.width) || (options.fromY > block.height)\n\t\t|| (options.fromX2 > block.width)\n\t\t|| (options.fromY2 > block.height)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"coordinates for -from option extend outside source image\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_FROM\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Hack to pass through the message that the place we're coming from\n\t * has a simple alpha channel.\n\t */\n\n\tif (!(((PhotoModel *) srcHandle)->flags & COMPLEX_ALPHA)) {\n\t    options.compositingRule |= SOURCE_IS_SIMPLE_ALPHA_PHOTO;\n\t}\n\n\t/*\n\t * Fill in default values for unspecified parameters.\n\t */\n\n\tif (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {\n\t    options.fromX2 = block.width;\n\t    options.fromY2 = block.height;\n\t}\n\tif (!(options.options & OPT_TO) || (options.toX2 < 0)) {\n\t    width = options.fromX2 - options.fromX;\n\t    if (options.subsampleX > 0) {\n\t\twidth = (width + options.subsampleX - 1) / options.subsampleX;\n\t    } else if (options.subsampleX == 0) {\n\t\twidth = 0;\n\t    } else {\n\t\twidth = (width - options.subsampleX - 1) / -options.subsampleX;\n\t    }\n\t    options.toX2 = options.toX + width * options.zoomX;\n\n\t    height = options.fromY2 - options.fromY;\n\t    if (options.subsampleY > 0) {\n\t\theight = (height + options.subsampleY - 1)\n\t\t\t/ options.subsampleY;\n\t    } else if (options.subsampleY == 0) {\n\t\theight = 0;\n\t    } else {\n\t\theight = (height - options.subsampleY - 1)\n\t\t\t/ -options.subsampleY;\n\t    }\n\t    options.toY2 = options.toY + height * options.zoomY;\n\t}\n\n\t/*\n\t * Copy the image data over using Tk_PhotoPutZoomedBlock.\n\t */\n\n\tif (block.pixelPtr) {\n\t    block.pixelPtr += options.fromX * block.pixelSize\n\t\t    + options.fromY * block.pitch;\n\t    block.width = options.fromX2 - options.fromX;\n\t    block.height = options.fromY2 - options.fromY;\n\t    result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) modelPtr,\n\t\t    &block, options.toX, options.toY, options.toX2 - options.toX,\n\t\t    options.toY2 - options.toY, options.zoomX, options.zoomY,\n\t\t    options.subsampleX, options.subsampleY,\n\t\t    options.compositingRule);\n\t} else {\n\t    result = TCL_OK;\n\t}\n\n\t/*\n\t * Set the destination image size if the -shrink option was specified.\n\t * This has to be done _after_ copying the data. Otherwise, if source\n\t * and destination are the same image, block.pixelPtr would point to\n\t * an invalid memory block (bug [5239fd749b]).\n\t */\n\n\tif (options.options & OPT_SHRINK) {\n\t    if (ImgPhotoSetSize(modelPtr, options.toX2,\n\t\t    options.toY2) != TCL_OK) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (block.pixelPtr || (options.options & OPT_SHRINK)) {\n\t    Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,\n\t\t    modelPtr->width, modelPtr->height);\n\t}\n\treturn result;\n\n    case PHOTO_DATA: {\n\tchar *data = NULL;\n\tTcl_Obj *freeObj = NULL;\n\tTcl_Obj *metadataIn;\n\n\t/*\n\t * photo data command - first parse and check any options given.\n\t */\n\n\tTk_ImageStringWriteProc *stringWriteProc = NULL;\n\tTk_ImageStringWriteProcVersion3 *stringWriteProcVersion3 = NULL;\n\n\tindex = 1;\n\tmemset(&options, 0, sizeof(options));\n\toptions.name = NULL;\n\toptions.format = NULL;\n\toptions.metadata = NULL;\n\toptions.fromX = 0;\n\toptions.fromY = 0;\n\tif (ParseSubcommandOptions(&options, interp,\n\t\tOPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND\n\t\t| OPT_METADATA,\n\t\t&index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif ((options.name == NULL) || (index < objc)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...?\");\n\t    if (options.background) {\n\t\tTk_FreeColor(options.background);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tif ((options.fromX > modelPtr->width)\n\t\t|| (options.fromY > modelPtr->height)\n\t\t|| (options.fromX2 > modelPtr->width)\n\t\t|| (options.fromY2 > modelPtr->height)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"coordinates for -from option extend outside image\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_FROM\", (char *)NULL);\n\t    if (options.background) {\n\t\tTk_FreeColor(options.background);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Fill in default values for unspecified parameters.\n\t */\n\n\tif (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {\n\t    options.fromX2 = modelPtr->width;\n\t    options.fromY2 = modelPtr->height;\n\t}\n\tif (!(options.options & OPT_FORMAT)) {\n\t    options.format = Tcl_NewStringObj(\"default\", TCL_INDEX_NONE);\n\t    freeObj = options.format;\n\t}\n\n\t/*\n\t * Use argument metadata if specified, otherwise the master metadata\n\t */\n\n\tif (NULL != options.metadata) {\n\t    metadataIn = options.metadata;\n\t} else {\n\t    metadataIn = modelPtr->metadata;\n\t}\n\n\t/*\n\t * Search for an appropriate image string format handler.\n\t */\n\n\tmatched = false;\n\tfor (imageFormat = tsdPtr->formatList; imageFormat != NULL;\n\t\timageFormat = imageFormat->nextPtr) {\n\t    if ((strncasecmp(Tcl_GetString(options.format),\n\t\t    imageFormat->name, strlen(imageFormat->name)) == 0)) {\n\t\tmatched = true;\n\t\tif (imageFormat->stringWriteProc != NULL) {\n\t\t    stringWriteProc = imageFormat->stringWriteProc;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (stringWriteProc == NULL) {\n\t    for (imageFormatVersion3 = tsdPtr->formatListVersion3;\n\t\t    imageFormatVersion3 != NULL;\n\t\t    imageFormatVersion3 = imageFormatVersion3->nextPtr) {\n\t\tif ((strncasecmp(Tcl_GetString(options.format),\n\t\t\timageFormatVersion3->name,\n\t\t\tstrlen(imageFormatVersion3->name)) == 0)) {\n\t\t    matched = true;\n\t\t    if (imageFormatVersion3->stringWriteProc != NULL) {\n\t\t\tstringWriteProcVersion3 =\n\t\t\t\timageFormatVersion3->stringWriteProc;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tif (stringWriteProc == NULL && stringWriteProcVersion3 == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"image string format \\\"%s\\\" is %s\",\n\t\t    Tcl_GetString(options.format),\n\t\t    (matched ? \"not supported\" : \"unknown\")));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"PHOTO_FORMAT\",\n\t\t    Tcl_GetString(options.format), (char *)NULL);\n\t    goto dataErrorExit;\n\t}\n\n\t/*\n\t * Call the handler's string write function to write out the image.\n\t */\n\n\tdata = ImgGetPhoto(modelPtr, &block, &options);\n\n\tif (stringWriteProc == NULL) {\n\t    result = (stringWriteProcVersion3)(interp,\n\t\t    options.format, metadataIn, &block);\n\t} else {\n\t    typedef int (*NewStringWriteProc)(Tcl_Interp *interp,\n\t\t    Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr);\n\n\t    result = ((NewStringWriteProc)(void *)stringWriteProc)(interp,\n\t\t    options.format, &block);\n\t}\n\tif (options.background) {\n\t    Tk_FreeColor(options.background);\n\t}\n\tif (data) {\n\t    Tcl_Free(data);\n\t}\n\tif (freeObj != NULL) {\n\t    Tcl_DecrRefCount(freeObj);\n\t}\n\treturn result;\n\n      dataErrorExit:\n\tif (options.background) {\n\t    Tk_FreeColor(options.background);\n\t}\n\tif (data) {\n\t    Tcl_Free(data);\n\t}\n\tif (freeObj != NULL) {\n\t    Tcl_DecrRefCount(freeObj);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    case PHOTO_GET: {\n\t/*\n\t * photo get command - first parse and check parameters.\n\t */\n\n\tTcl_Obj *channels[4];\n\tint i, channelCount = 3;\n\n\tindex = 3;\n\tmemset(&options, 0, sizeof(options));\n\toptions.name = NULL;\n\tif (ParseSubcommandOptions(&options, interp, OPT_WITHALPHA,\n\t\t&index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (options.name == NULL || index < objc) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"x y ?-withalpha?\");\n\t    return TCL_ERROR;\n\t}\n\tif (options.options & OPT_WITHALPHA) {\n\t    channelCount = 4;\n\t}\n\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif ((x < 0) || (x >= modelPtr->width)\n\t\t|| (y < 0) || (y >= modelPtr->height)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s get: coordinates out of range\",\n\t\t    Tcl_GetString(objv[0])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"COORDINATES\",\n\t\t    (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Extract the value of the desired pixel and format it as a list.\n\t */\n\n\tpixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n\tfor (i = 0; i < channelCount; i++) {\n\t    channels[i] = Tcl_NewWideIntObj(pixelPtr[i]);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewListObj(channelCount, channels));\n\treturn TCL_OK;\n    }\n\n    case PHOTO_PUT: {\n\tTcl_Obj *format, *data;\n\n\t/*\n\t * photo put command - first parse the options.\n\t */\n\n\tindex = 2;\n\tmemset(&options, 0, sizeof(options));\n\toptions.name = NULL;\n\toptions.format = NULL;\n\toptions.metadata = NULL;\n\tif (ParseSubcommandOptions(&options, interp,\n\t\tOPT_TO|OPT_FORMAT|OPT_METADATA,\n\t\t&index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif ((options.name == NULL) || (index < objc)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"data ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * See if there's a format that can read the data\n\t */\n\n\tif (MatchStringFormat(interp, objv[2], options.format,\n\t\toptions.metadata, NULL, &imageFormat,\n\t\t&imageFormatVersion3, &imageWidth, &imageHeight)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!(options.options & OPT_TO) || (options.toX2 < 0)) {\n\t    options.toX2 = options.toX + imageWidth;\n\t    options.toY2 = options.toY + imageHeight;\n\t}\n\tif (imageWidth > options.toX2 - options.toX) {\n\t    imageWidth = options.toX2 - options.toX;\n\t}\n\tif (imageHeight > options.toY2 - options.toY) {\n\t    imageHeight = options.toY2 - options.toY;\n\t}\n\tformat = options.format;\n\tdata = objv[2];\n\tif (imageFormat != NULL) {\n\t    if (imageFormat->stringReadProc(interp, data, format,\n\t\t    (Tk_PhotoHandle) modelPtr, options.toX, options.toY,\n\t\t    options.toX2 - options.toX,\n\t\t    options.toY2 - options.toY, 0, 0) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    if (imageFormatVersion3->stringReadProc(interp, data, format,\n\t\t    options.metadata,\n\t\t    (Tk_PhotoHandle) modelPtr, options.toX, options.toY,\n\t\t    options.toX2 - options.toX,\n\t\t    options.toY2 - options.toY, 0, 0,\n\t\t    NULL)\n\t\t    != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * SB: is the next line really needed? The stringReadProc\n\t * writes image data with Tk_PhotoPutBlock(), which in turn\n\t * takes care to notify the changed image and to set/unset the\n\t * IMAGE_CHANGED bit.\n\t */\n\tmodelPtr->flags |= IMAGE_CHANGED;\n\n\treturn TCL_OK;\n    }\n    case PHOTO_READ: {\n\tTcl_Obj *format;\n\n\t/*\n\t * photo read command - first parse the options specified.\n\t */\n\n\tindex = 2;\n\tmemset(&options, 0, sizeof(options));\n\toptions.name = NULL;\n\toptions.format = NULL;\n\toptions.metadata = NULL;\n\tif (ParseSubcommandOptions(&options, interp,\n\t\tOPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK | OPT_METADATA,\n\t\t&index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif ((options.name == NULL) || (index < objc)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"fileName ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Prevent file system access in safe interpreters.\n\t */\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't get image from a file in a safe interpreter\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"PHOTO_FILE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Open the image file and look for a handler for it.\n\t */\n\n\tchan = Tcl_OpenFileChannel(interp,\n\t\tTcl_GetString(options.name), \"r\", 0);\n\tif (chan == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_SetChannelOption(interp, chan, \"-translation\", \"binary\")\n\t\t!= TCL_OK) {\n\t    Tcl_Close(NULL, chan);\n\t    return TCL_ERROR;\n\t}\n\n\tif (MatchFileFormat(interp, chan,\n\t\tTcl_GetString(options.name), options.format,\n\t\toptions.metadata, NULL, &imageFormat,\n\t\t&imageFormatVersion3, &imageWidth, &imageHeight)\n\t\t!= TCL_OK) {\n\t    result = TCL_ERROR;\n\t    goto readCleanup;\n\t}\n\n\t/*\n\t * Check the values given for the -from option.\n\t */\n\n\tif ((options.fromX > imageWidth) || (options.fromY > imageHeight)\n\t\t|| (options.fromX2 > imageWidth)\n\t\t|| (options.fromY2 > imageHeight)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"coordinates for -from option extend outside source image\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_FROM\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto readCleanup;\n\t}\n\tif (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {\n\t    width = imageWidth - options.fromX;\n\t    height = imageHeight - options.fromY;\n\t} else {\n\t    width = options.fromX2 - options.fromX;\n\t    height = options.fromY2 - options.fromY;\n\t}\n\n\t/*\n\t * If the -shrink option was specified, set the size of the image.\n\t */\n\n\tif (options.options & OPT_SHRINK) {\n\t    if (ImgPhotoSetSize(modelPtr, options.toX + width,\n\t\t    options.toY + height) != TCL_OK) {\n\t\tTcl_ResetResult(interp);\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto readCleanup;\n\t    }\n\t}\n\n\t/*\n\t * Call the handler's file read function to read the data into the\n\t * image.\n\t */\n\n\tformat = options.format;\n\tif (imageFormat != NULL) {\n\t    result = imageFormat->fileReadProc(interp, chan,\n\t\t    Tcl_GetString(options.name),\n\t\t    format, (Tk_PhotoHandle) modelPtr, options.toX,\n\t\t    options.toY, width, height, options.fromX, options.fromY);\n\t} else {\n\t    result = imageFormatVersion3->fileReadProc(interp, chan,\n\t\t    Tcl_GetString(options.name),\n\t\t    format, options.metadata, (Tk_PhotoHandle) modelPtr,\n\t\t    options.toX, options.toY, width, height, options.fromX,\n\t\t    options.fromY, NULL);\n\t}\nreadCleanup:\n\tif (chan != NULL) {\n\t    Tcl_Close(NULL, chan);\n\t}\n\treturn result;\n    }\n\n    case PHOTO_REDITHER:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Call Dither if any part of the image is not correctly dithered at\n\t * present.\n\t */\n\n\tx = modelPtr->ditherX;\n\ty = modelPtr->ditherY;\n\tif (modelPtr->ditherX != 0) {\n\t    Tk_DitherPhoto((Tk_PhotoHandle) modelPtr, x, y,\n\t\t    modelPtr->width - x, 1);\n\t}\n\tif (modelPtr->ditherY < modelPtr->height) {\n\t    x = 0;\n\t    Tk_DitherPhoto((Tk_PhotoHandle)modelPtr, 0,\n\t\t    modelPtr->ditherY, modelPtr->width,\n\t\t    modelPtr->height - modelPtr->ditherY);\n\t}\n\n\tif (y < modelPtr->height) {\n\t    /*\n\t     * Tell the core image code that part of the image has changed.\n\t     */\n\n\t    Tk_ImageChanged(modelPtr->tkModel, x, y,\n\t\t    (modelPtr->width - x), (modelPtr->height - y),\n\t\t    modelPtr->width, modelPtr->height);\n\t}\n\treturn TCL_OK;\n\n    case PHOTO_TRANS: {\n\tstatic const char *const photoTransOptions[] = {\n\t    \"get\", \"set\", NULL\n\t};\n\tenum transOptions {\n\t    PHOTO_TRANS_GET, PHOTO_TRANS_SET\n\t};\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIndexFromObj(interp, objv[2], photoTransOptions, \"option\",\n\t\t0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tswitch ((enum transOptions) index) {\n\tcase PHOTO_TRANS_GET: {\n\t    bool boolMode;\n\n\t    /*\n\t     * parse fixed args and option\n\t     */\n\n\t    if (objc > 6 || objc < 5) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"x y ?-option?\");\n\t\treturn TCL_ERROR;\n\t    }\n\t    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    index = 4;\n\t    memset(&options, 0, sizeof(options));\n\t    if (ParseSubcommandOptions(&options, interp,\n\t\t    OPT_ALPHA, &index, objc, objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (index < objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"unknown option \\\"%s\\\": must be -alpha\",\n\t\t\tTcl_GetString(objv[index])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    boolMode = true;\n\t    if (options.options & OPT_ALPHA) {\n\t\tboolMode = false;\n\t    }\n\n\t    if ((x < 0) || (x >= modelPtr->width)\n\t\t    || (y < 0) || (y >= modelPtr->height)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"%s transparency get: coordinates out of range\",\n\t\t\tTcl_GetString(objv[0])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"COORDINATES\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Extract and return the desired value\n\t     */\n\t    pixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n\t    if (boolMode) {\n\t\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(pixelPtr[3] == 0));\n\t    } else {\n\t\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(pixelPtr[3]));\n\t    }\n\t    return TCL_OK;\n\t}\n\n\tcase PHOTO_TRANS_SET: {\n\t    int newVal;\n\t    bool boolMode;\n\t    XRectangle setBox;\n\t    Region modRegion;\n\n\t    /*\n\t     * Parse args and option, check for valid values\n\t     */\n\n\t    if (objc < 6 || objc > 7) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"x y newVal ?-option?\");\n\t\treturn TCL_ERROR;\n\t    }\n\t    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    index = 5;\n\t    memset(&options, 0, sizeof(options));\n\t    if (ParseSubcommandOptions(&options, interp,\n\t\t    OPT_ALPHA, &index, objc, objv) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (index < objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"unknown option \\\"%s\\\": must be -alpha\",\n\t\t\tTcl_GetString(objv[index])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    boolMode = true;\n\t    if (options.options & OPT_ALPHA) {\n\t\tboolMode = false;\n\t    }\n\n\t    if ((x < 0) || (x >= modelPtr->width)\n\t\t|| (y < 0) || (y >= modelPtr->height)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"%s transparency set: coordinates out of range\",\n\t\t\tTcl_GetString(objv[0])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"COORDINATES\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (boolMode) {\n\t\tif (Tcl_GetBooleanFromObj(interp, objv[5], &newVal) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else {\n\t\tif (Tcl_GetIntFromObj(interp, objv[5], &newVal) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (newVal < 0 || newVal > 255) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"invalid alpha value \\\"%d\\\": \"\n\t\t\t    \"must be integer between 0 and 255\", newVal));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t    \"BAD_VALUE\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Set new alpha value for the pixel\n\t     */\n\n\t    pixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n\t    if (boolMode) {\n\t\tpixelPtr[3] = newVal ? 0 : 255;\n\t    } else {\n\t\tpixelPtr[3] = newVal;\n\t    }\n\n\t    /*\n\t     * Update the validRegion of the image\n\t     */\n\n\t    setBox.x = x;\n\t    setBox.y = y;\n\t    setBox.width = 1;\n\t    setBox.height = 1;\n\t    modRegion = XCreateRegion();\n\t    XUnionRectWithRegion(&setBox, modRegion, modRegion);\n\t    if (pixelPtr[3]) {\n\t\tXUnionRectWithRegion(&setBox, modelPtr->validRegion,\n\t\t\tmodelPtr->validRegion);\n\t    } else {\n\t\tXSubtractRegion(modelPtr->validRegion, modRegion,\n\t\t\tmodelPtr->validRegion);\n\t    }\n\t    XDestroyRegion(modRegion);\n\n\t    /*\n\t     * Inform the generic image code that the image\n\t     * has (potentially) changed.\n\t     */\n\n\t    Tk_ImageChanged(modelPtr->tkModel, x, y, 1, 1,\n\t\t    modelPtr->width, modelPtr->height);\n\t    modelPtr->flags &= ~IMAGE_CHANGED;\n\t    return TCL_OK;\n\t}\n\n\t}\n\tTcl_Panic(\"unexpected fallthrough\");\n\tbreak;\n    }\n\n    case PHOTO_WRITE: {\n\tchar *data;\n\tconst char *fmtString;\n\tTcl_Obj *format, *metadataIn;\n\tbool usedExt;\n\n\t/*\n\t * Prevent file system access in safe interpreters.\n\t */\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't write image to a file in a safe interpreter\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"PHOTO_FILE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * photo write command - first parse and check any options given.\n\t */\n\n\tindex = 2;\n\tmemset(&options, 0, sizeof(options));\n\toptions.name = NULL;\n\toptions.format = NULL;\n\toptions.metadata = NULL;\n\tif (ParseSubcommandOptions(&options, interp,\n\t\tOPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND\n\t\t| OPT_METADATA,\n\t\t&index, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif ((options.name == NULL) || (index < objc)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"fileName ?-option value ...?\");\n\t    if (options.background) {\n\t\tTk_FreeColor(options.background);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tif ((options.fromX > modelPtr->width)\n\t\t|| (options.fromY > modelPtr->height)\n\t\t|| (options.fromX2 > modelPtr->width)\n\t\t|| (options.fromY2 > modelPtr->height)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"coordinates for -from option extend outside image\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_FROM\", (char *)NULL);\n\t    if (options.background) {\n\t\tTk_FreeColor(options.background);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Fill in default values for unspecified parameters. Note that a\n\t * missing -format flag results in us having a guess from the file\n\t * extension. [Bug 2983824]\n\t */\n\n\tif (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {\n\t    options.fromX2 = modelPtr->width;\n\t    options.fromY2 = modelPtr->height;\n\t}\n\tif (options.format == NULL) {\n\t    fmtString = GetExtension(Tcl_GetString(options.name));\n\t    usedExt = (fmtString != NULL);\n\t} else {\n\t    fmtString = Tcl_GetString(options.format);\n\t    usedExt = false;\n\t}\n\n\n\t/*\n\t * Use argument metadata if specified, otherwise the master metadata\n\t */\n\n\tif (NULL != options.metadata) {\n\t    metadataIn = options.metadata;\n\t} else {\n\t    metadataIn = modelPtr->metadata;\n\t}\n\n\t/*\n\t * Search for an appropriate image file format handler, and give an\n\t * error if none is found.\n\t */\n\n\tmatched = false;\n    redoFormatLookup:\n\timageFormatVersion3 = NULL;\n\tfor (imageFormat = tsdPtr->formatList; imageFormat != NULL;\n\t\timageFormat = imageFormat->nextPtr) {\n\t    if ((fmtString == NULL)\n\t\t    || (strncasecmp(fmtString, imageFormat->name,\n\t\t\t    strlen(imageFormat->name)) == 0)) {\n\t\tmatched = true;\n\t\tif (imageFormat->fileWriteProc != NULL) {\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (imageFormat == NULL) {\n\t    for (imageFormatVersion3 = tsdPtr->formatListVersion3;\n\t\t    imageFormatVersion3 != NULL;\n\t\t    imageFormatVersion3 = imageFormatVersion3->nextPtr) {\n\t\tif ((fmtString == NULL)\n\t\t\t|| (strncasecmp(fmtString, imageFormatVersion3->name,\n\t\t\t\tstrlen(imageFormatVersion3->name)) == 0)) {\n\t\t    matched = true;\n\t\t    if (imageFormatVersion3->fileWriteProc != NULL) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tif (usedExt && !matched) {\n\t    /*\n\t     * If we didn't find one and we're using file extensions as the\n\t     * basis for the guessing, go back and look again without\n\t     * prejudice. Supports old broken code.\n\t     */\n\n\t    usedExt = false;\n\t    fmtString = NULL;\n\t    goto redoFormatLookup;\n\t}\n\tif (imageFormat == NULL && imageFormatVersion3 == NULL) {\n\t    if (fmtString == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"no available image file format has file writing\"\n\t\t\t\" capability\", TCL_INDEX_NONE));\n\t    } else if (!matched) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"image file format \\\"%s\\\" is unknown\", fmtString));\n\t    } else {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"image file format \\\"%s\\\" has no file writing capability\",\n\t\t\tfmtString));\n\t    }\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"PHOTO_FORMAT\",\n\t\t    fmtString, (char *)NULL);\n\t    if (options.background) {\n\t\tTk_FreeColor(options.background);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Call the handler's file write function to write out the image.\n\t */\n\n\tdata = ImgGetPhoto(modelPtr, &block, &options);\n\tformat = options.format;\n\tif (imageFormat != NULL) {\n\t    result = imageFormat->fileWriteProc(interp,\n\t\t    Tcl_GetString(options.name), format, &block);\n\t} else {\n\t    result = imageFormatVersion3->fileWriteProc(interp,\n\t\t    Tcl_GetString(options.name), format, metadataIn,\n\t\t    &block);\n\t}\n\tif (options.background) {\n\t    Tk_FreeColor(options.background);\n\t}\n\tif (data) {\n\t    Tcl_Free(data);\n\t}\n\treturn result;\n    }\n\n    }\n    Tcl_Panic(\"unexpected fallthrough\");\n    return TCL_ERROR; /* NOT REACHED */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetExtension --\n *\n *\tReturn the extension part of a path, or NULL if there is no extension.\n *\tThe returned string will be a substring of the argument string, so\n *\tshould not be Tcl_Free()d directly. No side effects.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const char *\nGetExtension(\n    const char *path)\n{\n    char c;\n    const char *extension = NULL;\n\n    for (; (c=*path++) != '\\0' ;) {\n\tif (c == '.') {\n\t    extension = path;\n\t}\n    }\n    if (extension != NULL && extension[0] == '\\0') {\n\textension = NULL;\n    }\n    return extension;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseSubcommandOptions --\n *\n *\tThis function is invoked to process one of the options which may be\n *\tspecified for the photo image subcommands, namely, -from, -to, -zoom,\n *\t-subsample, -format, -shrink, -compositingrule, -alpha, -boolean,\n *\t-withalpha and -metadata.\n *\tParsing starts at the index in *optIndexPtr and stops at the end of\n *\tobjv[] or at the first value that does not belong to an option.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tFields in *optPtr get filled in. The value of optIndexPtr is updated\n *\tto contain the index of the first element in argv[] that was not\n *\tparsed, or objc if the end of objv[] was reached.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nParseSubcommandOptions(\n    struct SubcommandOptions *optPtr,\n\t\t\t\t/* Information about the options specified and\n\t\t\t\t * the values given is returned here. */\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    int allowedOptions,\t\t/* Indicates which options are valid for the\n\t\t\t\t * current command. */\n    Tcl_Size *optIndexPtr,\t\t/* Points to a variable containing the current\n\t\t\t\t * index in objv; this variable is updated by\n\t\t\t\t * this function. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv[]. */\n    Tcl_Obj *const objv[])\t/* Arguments to be parsed. */\n{\n    static const char *const compositingRules[] = {\n\t\"overlay\", \"set\",\t/* Note that these must match the\n\t\t\t\t * TK_PHOTO_COMPOSITE_* constants. */\n\tNULL\n    };\n    Tcl_Size index, length, argIndex;\n    int c, bit, currentBit;\n    int values[4], numValues, maxValues;\n    const char *option, *expandedOption, *needed;\n    const char *const *listPtr;\n    Tcl_Obj *msgObj;\n\n    for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {\n\t/*\n\t * We can have one value specified without an option; it goes into\n\t * optPtr->name.\n\t */\n\n\texpandedOption = option = Tcl_GetStringFromObj(objv[index], &length);\n\tif (option[0] != '-') {\n\t    if (optPtr->name == NULL) {\n\t\toptPtr->name = objv[index];\n\t\tcontinue;\n\t    }\n\t    break;\n\t}\n\n\t/*\n\t * Work out which option this is.\n\t */\n\n\tc = option[0];\n\tbit = 0;\n\tcurrentBit = 1;\n\tfor (listPtr = optionNames; *listPtr != NULL; ++listPtr) {\n\t    if ((c == *listPtr[0])\n\t\t    && (strncmp(option, *listPtr, length) == 0)) {\n\t\texpandedOption = *listPtr;\n\t\tif (bit != 0) {\n\t\t    goto unknownOrAmbiguousOption;\n\t\t}\n\t\tbit = currentBit;\n\t    }\n\t    currentBit <<= 1;\n\t}\n\n\t/*\n\t * If this option is not recognized and allowed, put an error message\n\t * in the interpreter and return.\n\t */\n\n\tif (!(allowedOptions & bit)) {\n\t    if (optPtr->name != NULL) {\n\t\tgoto unknownOrAmbiguousOption;\n\t    }\n\t    optPtr->name = objv[index];\n\t    continue;\n\t}\n\n\t/*\n\t * For the -from, -to, -zoom and -subsample options, parse the values\n\t * given. Report an error if too few or too many values are given.\n\t */\n\n\tif (bit == OPT_BACKGROUND) {\n\t    /*\n\t     * The -background option takes a single XColor value.\n\t     */\n\n\t    if (index + 1 >= objc) {\n\t\tgoto oneValueRequired;\n\t    }\n\t    *optIndexPtr = ++index;\n\t    optPtr->background = Tk_AllocColorFromObj(interp, Tk_MainWindow(interp),\n\t\t    objv[index]);\n\t    if (!optPtr->background) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else if (bit == OPT_FORMAT) {\n\t    /*\n\t     * The -format option takes a single string value. Note that\n\t     * parsing this is outside the scope of this function.\n\t     */\n\n\t    if (index + 1 >= objc) {\n\t\tgoto oneValueRequired;\n\t    }\n\t    *optIndexPtr = ++index;\n\t    optPtr->format = objv[index];\n\t} else if (bit == OPT_METADATA) {\n\t    /*\n\t    * The -metadata option takes a single dict value. Note that\n\t    * parsing this is outside the scope of this function.\n\t    */\n\n\t    if (index + 1 >= objc) {\n\t\tgoto oneValueRequired;\n\t    }\n\t    *optIndexPtr = ++index;\n\t    optPtr->metadata = objv[index];\n\t} else if (bit == OPT_COMPOSITE) {\n\t    /*\n\t     * The -compositingrule option takes a single value from a\n\t     * well-known set.\n\t     */\n\n\t    if (index + 1 >= objc) {\n\t\tgoto oneValueRequired;\n\t    }\n\t    index++;\n\t    if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,\n\t\t    \"compositing rule\", 0, &optPtr->compositingRule)\n\t\t    != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    *optIndexPtr = index;\n\t} else if (bit == OPT_TO || bit == OPT_FROM\n\t\t|| bit == OPT_SUBSAMPLE || bit == OPT_ZOOM) {\n\t    const char *val;\n\n\t    maxValues = ((bit == OPT_FROM) || (bit == OPT_TO)) ? 4 : 2;\n\t    argIndex = index + 1;\n\t    for (numValues = 0; numValues < maxValues; ++numValues) {\n\t\tif (argIndex >= objc) {\n\t\t    break;\n\t\t}\n\t\tval = Tcl_GetString(objv[argIndex]);\n\t\tif ((argIndex < objc) && (isdigit(UCHAR(val[0]))\n\t\t\t|| ((val[0] == '-') && isdigit(UCHAR(val[1]))))) {\n\t\t    if (Tcl_GetInt(interp, val, &values[numValues])\n\t\t\t    != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t} else {\n\t\t    break;\n\t\t}\n\t\targIndex++;\n\t    }\n\n\t    if (numValues == 0) {\n\t\tgoto manyValuesRequired;\n\t    }\n\t    *optIndexPtr = (index += numValues);\n\n\t    /*\n\t     * Y values default to the corresponding X value if not specified.\n\t     */\n\n\t    if (numValues == 1) {\n\t\tvalues[1] = values[0];\n\t    }\n\t    if (numValues == 3) {\n\t\tvalues[3] = values[2];\n\t    }\n\n\t    /*\n\t     * Check the values given and put them in the appropriate field of\n\t     * the SubcommandOptions structure.\n\t     */\n\n\t    switch (bit) {\n\t    case OPT_FROM:\n\t\tif ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)\n\t\t\t&& ((values[2] < 0) || (values[3] < 0)))) {\n\t\t    needed = \"non-negative\";\n\t\t    goto numberOutOfRange;\n\t\t}\n\t\tif (numValues <= 2) {\n\t\t    optPtr->fromX = values[0];\n\t\t    optPtr->fromY = values[1];\n\t\t    optPtr->fromX2 = -1;\n\t\t    optPtr->fromY2 = -1;\n\t\t} else {\n\t\t    optPtr->fromX = MIN(values[0], values[2]);\n\t\t    optPtr->fromY = MIN(values[1], values[3]);\n\t\t    optPtr->fromX2 = MAX(values[0], values[2]);\n\t\t    optPtr->fromY2 = MAX(values[1], values[3]);\n\t\t}\n\t\tbreak;\n\t    case OPT_SUBSAMPLE:\n\t\toptPtr->subsampleX = values[0];\n\t\toptPtr->subsampleY = values[1];\n\t\tbreak;\n\t    case OPT_TO:\n\t\tif ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)\n\t\t\t&& ((values[2] < 0) || (values[3] < 0)))) {\n\t\t    needed = \"non-negative\";\n\t\t    goto numberOutOfRange;\n\t\t}\n\t\tif (numValues <= 2) {\n\t\t    optPtr->toX = values[0];\n\t\t    optPtr->toY = values[1];\n\t\t    optPtr->toX2 = -1;\n\t\t    optPtr->toY2 = -1;\n\t\t} else {\n\t\t    optPtr->toX = MIN(values[0], values[2]);\n\t\t    optPtr->toY = MIN(values[1], values[3]);\n\t\t    optPtr->toX2 = MAX(values[0], values[2]);\n\t\t    optPtr->toY2 = MAX(values[1], values[3]);\n\t\t}\n\t\tbreak;\n\t    case OPT_ZOOM:\n\t\tif ((values[0] <= 0) || (values[1] <= 0)) {\n\t\t    needed = \"positive\";\n\t\t    goto numberOutOfRange;\n\t\t}\n\t\toptPtr->zoomX = values[0];\n\t\toptPtr->zoomY = values[1];\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * Remember that we saw this option.\n\t */\n\n\toptPtr->options |= bit;\n    }\n    return TCL_OK;\n\n    /*\n     * Exception generation.\n     */\n\n  oneValueRequired:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"the \\\"%s\\\" option requires a value\", expandedOption));\n    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"MISSING_VALUE\", (char *)NULL);\n    return TCL_ERROR;\n\n  manyValuesRequired:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"the \\\"%s\\\" option requires one %s integer values\",\n\t    expandedOption, (maxValues == 2) ? \"or two\": \"to four\"));\n    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"MISSING_VALUE\", (char *)NULL);\n    return TCL_ERROR;\n\n  numberOutOfRange:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"value(s) for the %s option must be %s\", expandedOption, needed));\n    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_VALUE\", (char *)NULL);\n    return TCL_ERROR;\n\n  unknownOrAmbiguousOption:\n    msgObj = Tcl_ObjPrintf(\"unrecognized option \\\"%s\\\": must be \", option);\n    bit = 1;\n    for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {\n\tif (allowedOptions & bit) {\n\t    if (allowedOptions & (bit - 1)) {\n\t\tif (allowedOptions & ~((bit << 1) - 1)) {\n\t\t    Tcl_AppendToObj(msgObj, \", \", TCL_INDEX_NONE);\n\t\t} else {\n\t\t    Tcl_AppendToObj(msgObj, \", or \", TCL_INDEX_NONE);\n\t\t}\n\t    }\n\t    Tcl_AppendToObj(msgObj, *listPtr, TCL_INDEX_NONE);\n\t}\n\tbit <<= 1;\n    }\n    Tcl_SetObjResult(interp, msgObj);\n    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\", \"BAD_OPTION\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoConfigureModel --\n *\n *\tThis function is called when a photo image is created or reconfigured.\n *\tIt processes configuration options and resets any instances of the\n *\timage.\n *\n * Results:\n *\tA standard Tcl return value. If TCL_ERROR is returned then an error\n *\tmessage is left in the modelPtr->interp's result.\n *\n * Side effects:\n *\tExisting instances of the image will be redisplayed to match the new\n *\tconfiguration options.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgPhotoConfigureModel(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    PhotoModel *modelPtr,\t/* Pointer to data structure describing\n\t\t\t\t * overall photo image to (re)configure. */\n    Tcl_Size objc,\t\t\t/* Number of entries in objv. */\n    Tcl_Obj *const objv[],\t/* Pairs of configuration options for image. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget, such\n\t\t\t\t * as TK_CONFIG_ARGV_ONLY. */\n{\n    PhotoInstance *instancePtr;\n    Tcl_Obj *oldFileObj;\n    const char *oldPaletteString;\n    Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL,\n\t    *metadataInObj = NULL, *metadataOutObj = NULL;\n    Tcl_Obj *tempdata, *tempformat;\n    Tcl_Size i, length;\n    int result, imageWidth, imageHeight;\n    double oldGamma;\n    Tcl_Channel chan;\n    Tk_PhotoImageFormat *imageFormat;\n    Tk_PhotoImageFormatVersion3 *imageFormatVersion3;\n\n    for (i = 0; i < objc; i++) {\n\tconst char *arg = Tcl_GetStringFromObj(objv[i], &length);\n\tif ((length > 1) && (arg[0] == '-')) {\n\t    if ((arg[1] == 'd') &&\n\t\t    !strncmp(arg, \"-data\", length)) {\n\t\tif (++i < objc) {\n\t\t    data = objv[i];\n\t\t} else {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"value for \\\"-data\\\" missing\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t    \"MISSING_VALUE\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else if ((arg[1] == 'f') &&\n\t\t    !strncmp(arg, \"-format\", length)) {\n\t\tif (++i < objc) {\n\t\t    format = objv[i];\n\t\t} else {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t    \"value for \\\"-format\\\" missing\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t    \"MISSING_VALUE\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else if ((arg[1] == 'm') &&\n\t\t!strncmp(arg, \"-metadata\", length)) {\n\t\tif (++i < objc) {\n\t\t    metadataInObj = objv[i];\n\t\t} else {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"value for \\\"-metadata\\\" missing\", TCL_INDEX_NONE));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"MISSING_VALUE\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Save the current values for fileString and dataString, so we can tell\n     * if the user specifies them anew. IMPORTANT: if the format changes we\n     * have to interpret \"-file\" and \"-data\" again as well! It might be that\n     * the format string influences how \"-data\" or \"-file\" is interpreted.\n     */\n\n    oldFileObj = modelPtr->fileObj;\n    if (oldFileObj == NULL) {\n\toldData = modelPtr->dataObj;\n\tif (oldData != NULL) {\n\t    Tcl_IncrRefCount(oldData);\n\t}\n    } else {\n\toldData = NULL;\n    }\n    oldFormat = modelPtr->format;\n    if (oldFormat != NULL) {\n\tTcl_IncrRefCount(oldFormat);\n    }\n    oldPaletteString = modelPtr->palette;\n    oldGamma = modelPtr->gamma;\n\n    /*\n     * Process the configuration options specified.\n     */\n\n    if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,\n\t    objc, objv, modelPtr, flags) != TCL_OK) {\n\tgoto errorExit;\n    }\n\n    /*\n     * Regard the empty string for -file, -data, -format or -metadata as the null value.\n     */\n\n    if ((modelPtr->fileObj != NULL) && (Tcl_GetString(modelPtr->fileObj)[0] == 0)) {\n\tTcl_DecrRefCount(modelPtr->fileObj);\n\tmodelPtr->fileObj = NULL;\n    }\n    if (data) {\n\t/*\n\t * Force into ByteArray format, which most (all) image handlers will\n\t * use anyway. Empty length means ignore the -data option.\n\t */\n\tTcl_Size bytesize;\n\n\t(void) Tcl_GetByteArrayFromObj(data, &bytesize);\n\tif (bytesize) {\n\t    Tcl_IncrRefCount(data);\n\t} else {\n\t    data = NULL;\n\t}\n\tif (modelPtr->dataObj) {\n\t    Tcl_DecrRefCount(modelPtr->dataObj);\n\t}\n\tmodelPtr->dataObj = data;\n    }\n    if (format) {\n\t/*\n\t * Stringify to ignore -format \"\". It may come in as a list or other\n\t * object.\n\t */\n\n\t(void) Tcl_GetString(format);\n\tif (format->length) {\n\t    Tcl_IncrRefCount(format);\n\t} else {\n\t    format = NULL;\n\t}\n\tif (modelPtr->format) {\n\t    Tcl_DecrRefCount(modelPtr->format);\n\t}\n\tmodelPtr->format = format;\n    }\n    if (metadataInObj) {\n\t/*\n\t * Make -metadata a dict.\n\t * Take also empty metadatas as this may be a sign to replace\n\t * existing metadata.\n\t */\n\tTcl_Size dictSize;\n\n\tif (TCL_OK != Tcl_DictObjSize(interp,metadataInObj, &dictSize)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"value for \\\"-metadata\\\" not a dict\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t    \"UNRECOGNIZED_DATA\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (dictSize > 0) {\n\t    Tcl_IncrRefCount(metadataInObj);\n\t} else {\n\t    metadataInObj = NULL;\n\t}\n\tif (modelPtr->metadata) {\n\t    Tcl_DecrRefCount(modelPtr->metadata);\n\t}\n\tmodelPtr->metadata = metadataInObj;\n    }\n    /*\n     * Set the image to the user-requested size, if any, and make sure storage\n     * is correctly allocated for this image.\n     */\n\n    if (ImgPhotoSetSize(modelPtr, modelPtr->width,\n\t    modelPtr->height) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\tgoto errorExit;\n    }\n\n    /*\n     * Read in the image from the file or string if the user has specified the\n     * -file or -data option.\n     */\n\n    if ((modelPtr->fileObj != NULL)\n\t    && ((modelPtr->fileObj != oldFileObj)\n\t    || (modelPtr->format != oldFormat))) {\n\t/*\n\t * Prevent file system access in a safe interpreter.\n\t */\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_ResetResult(interp);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't get image from a file in a safe interpreter\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"PHOTO_FILE\", (char *)NULL);\n\t    goto errorExit;\n\t}\n\n\tchan = Tcl_OpenFileChannel(interp, Tcl_GetString(modelPtr->fileObj), \"rb\", 0);\n\tif (chan == NULL) {\n\t    goto errorExit;\n\t}\n\n\t/*\n\t * Flag that we want the metadata result dict\n\t */\n\n\tmetadataOutObj = Tcl_NewDictObj();\n\tTcl_IncrRefCount(metadataOutObj);\n\n\tif ((MatchFileFormat(interp, chan, (modelPtr->fileObj ? Tcl_GetString(modelPtr->fileObj) : NULL),\n\t\t\tmodelPtr->format, modelPtr->metadata, metadataOutObj,\n\t\t\t&imageFormat, &imageFormatVersion3,\n\t\t\t&imageWidth, &imageHeight) != TCL_OK)) {\n\t    Tcl_Close(NULL, chan);\n\t    goto errorExit;\n\t}\n\tresult = ImgPhotoSetSize(modelPtr, imageWidth, imageHeight);\n\tif (result != TCL_OK) {\n\t    Tcl_Close(NULL, chan);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    TK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    goto errorExit;\n\t}\n\ttempformat = modelPtr->format;\n\tif (imageFormat != NULL) {\n\t    result = imageFormat->fileReadProc(interp, chan,\n\t\t    (modelPtr->fileObj ? Tcl_GetString(modelPtr->fileObj) : NULL), tempformat,\n\t\t    (Tk_PhotoHandle) modelPtr,\n\t\t    0, 0, imageWidth, imageHeight, 0, 0);\n\t} else {\n\t    result = imageFormatVersion3->fileReadProc(interp, chan,\n\t\t    (modelPtr->fileObj ? Tcl_GetString(modelPtr->fileObj) : NULL), tempformat, modelPtr->metadata,\n\t\t    (Tk_PhotoHandle) modelPtr,\n\t\t    0, 0, imageWidth, imageHeight, 0, 0,\n\t\t    metadataOutObj);\n\t}\n\n\tTcl_Close(NULL, chan);\n\tif (result != TCL_OK) {\n\t    goto errorExit;\n\t}\n\n\tTcl_ResetResult(interp);\n\tmodelPtr->flags |= IMAGE_CHANGED;\n    }\n\n    if ((modelPtr->fileObj == NULL) && (modelPtr->dataObj != NULL)\n\t    && ((modelPtr->dataObj != oldData)\n\t\t    || (modelPtr->format != oldFormat))) {\n\n\t/*\n\t * Flag that we want the metadata result dict\n\t */\n\n\tmetadataOutObj = Tcl_NewDictObj();\n\tTcl_IncrRefCount(metadataOutObj);\n\n\tif (MatchStringFormat(interp, modelPtr->dataObj,\n\t\tmodelPtr->format, modelPtr->metadata, metadataOutObj,\n\t\t&imageFormat, &imageFormatVersion3, &imageWidth,\n\t\t&imageHeight) != TCL_OK) {\n\t    goto errorExit;\n\t}\n\tif (ImgPhotoSetSize(modelPtr, imageWidth, imageHeight) != TCL_OK) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    TK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    goto errorExit;\n\t}\n\ttempformat = modelPtr->format;\n\ttempdata = modelPtr->dataObj;\n\tif (imageFormat != NULL) {\n\t    if (imageFormat->stringReadProc(interp, tempdata, tempformat,\n\t\t    (Tk_PhotoHandle) modelPtr, 0, 0, imageWidth, imageHeight,\n\t\t    0, 0) != TCL_OK) {\n\t\tgoto errorExit;\n\t    }\n\t} else {\n\t    if (imageFormatVersion3->stringReadProc(interp, tempdata, tempformat,\n\t\t    modelPtr->metadata, (Tk_PhotoHandle) modelPtr, 0, 0,\n\t\t    imageWidth, imageHeight, 0, 0, metadataOutObj) != TCL_OK) {\n\t\tgoto errorExit;\n\t    }\n\t}\n\n\tTcl_ResetResult(interp);\n\tmodelPtr->flags |= IMAGE_CHANGED;\n    }\n\n    /*\n     * Merge driver returned metadata and master metadata\n     */\n    if (metadataOutObj != NULL) {\n\tTcl_Size dictSize;\n\tif (TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"driver metadata not a dict\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t    \"UNRECOGNIZED_DATA\", (char *)NULL);\n\t    goto errorExit;\n\t}\n\tif (dictSize > 0) {\n\n\t    /*\n\t     * We have driver return metadata\n\t     */\n\n\t    if (modelPtr->metadata == NULL) {\n\t\tmodelPtr->metadata = metadataOutObj;\n\t\tmetadataOutObj = NULL;\n\t    } else {\n\t\tTcl_DictSearch search;\n\t\tTcl_Obj *key, *value;\n\t\tint done;\n\n\t\tif (Tcl_IsShared(modelPtr->metadata)) {\n\t\t    Tcl_DecrRefCount(modelPtr->metadata);\n\t\t    modelPtr->metadata = Tcl_DuplicateObj(modelPtr->metadata);\n\t\t    Tcl_IncrRefCount(modelPtr->metadata);\n\t\t}\n\n\t\tif (Tcl_DictObjFirst(interp, metadataOutObj, &search, &key,\n\t\t\t&value, &done) != TCL_OK) {\n\t\t    goto errorExit;\n\t\t}\n\t\tfor (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {\n\t\t    Tcl_DictObjPut(interp, modelPtr->metadata, key, value);\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Enforce a reasonable value for gamma.\n     */\n\n    if (modelPtr->gamma <= 0) {\n\tmodelPtr->gamma = 1.0;\n    }\n\n    if ((modelPtr->gamma != oldGamma)\n\t    || (modelPtr->palette != oldPaletteString)) {\n\tmodelPtr->flags |= IMAGE_CHANGED;\n    }\n\n    /*\n     * Cycle through all of the instances of this image, regenerating the\n     * information for each instance. Then force the image to be redisplayed\n     * everywhere that it is used.\n     */\n\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tTkImgPhotoConfigureInstance(instancePtr);\n    }\n\n    /*\n     * Inform the generic image code that the image has (potentially) changed.\n     */\n\n    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,\n\t    modelPtr->height, modelPtr->width, modelPtr->height);\n    modelPtr->flags &= ~IMAGE_CHANGED;\n\n    if (oldData != NULL) {\n\tTcl_DecrRefCount(oldData);\n    }\n    if (oldFormat != NULL) {\n\tTcl_DecrRefCount(oldFormat);\n    }\n    if (metadataOutObj != NULL) {\n\tTcl_DecrRefCount(metadataOutObj);\n    }\n\n    ToggleComplexAlphaIfNeeded(modelPtr);\n\n    return TCL_OK;\n\n  errorExit:\n    if (oldData != NULL) {\n\tTcl_DecrRefCount(oldData);\n    }\n    if (oldFormat != NULL) {\n\tTcl_DecrRefCount(oldFormat);\n    }\n    if (metadataOutObj != NULL) {\n\tTcl_DecrRefCount(metadataOutObj);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ToggleComplexAlphaIfNeeded --\n *\n *\tThis function is called when an image is modified to check if any\n *\tpartially transparent pixels exist, which requires blending instead of\n *\tstraight copy.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\t(Re)sets COMPLEX_ALPHA flag of model.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nToggleComplexAlphaIfNeeded(\n    PhotoModel *mPtr)\n{\n    size_t len = (size_t)MAX(mPtr->userWidth, mPtr->width) *\n\t    (size_t)MAX(mPtr->userHeight, mPtr->height) * 4;\n    unsigned char *c = mPtr->pix32;\n    unsigned char *end;\n\n    /*\n     * Set the COMPLEX_ALPHA flag if we have an image with partially\n     * transparent bits.\n     */\n\n    mPtr->flags &= ~COMPLEX_ALPHA;\n    if (c == NULL) {\n\treturn 0;\n    }\n    end = c + len;\n    c += 3;\t\t\t/* Start at first alpha byte. */\n    for (; c < end; c += 4) {\n\tif (*c && *c != 255) {\n\t    mPtr->flags |= COMPLEX_ALPHA;\n\t    break;\n\t}\n    }\n    return (mPtr->flags & COMPLEX_ALPHA);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoDelete --\n *\n *\tThis function is called by the image code to delete the model\n *\tstructure for an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with the image get freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgPhotoDelete(\n    void *modelData)\t/* Pointer to PhotoModel structure for image.\n\t\t\t\t * Must not have any more instances. */\n{\n    PhotoModel *modelPtr = (PhotoModel *)modelData;\n    PhotoInstance *instancePtr;\n\n    while ((instancePtr = modelPtr->instancePtr) != NULL) {\n\tif (instancePtr->refCount > 0) {\n\t    Tcl_Panic(\"tried to delete photo image when instances still exist\");\n\t}\n\tTcl_CancelIdleCall(TkImgDisposeInstance, instancePtr);\n\tTkImgDisposeInstance(instancePtr);\n    }\n    modelPtr->tkModel = NULL;\n    if (modelPtr->imageCmd != NULL) {\n\tTcl_DeleteCommandFromToken(modelPtr->interp, modelPtr->imageCmd);\n    }\n    if (modelPtr->pix32 != NULL) {\n\tTcl_Free(modelPtr->pix32);\n    }\n    if (modelPtr->validRegion != NULL) {\n\tXDestroyRegion(modelPtr->validRegion);\n    }\n    if (modelPtr->dataObj != NULL) {\n\tTcl_DecrRefCount(modelPtr->dataObj);\n    }\n    if (modelPtr->format != NULL) {\n\tTcl_DecrRefCount(modelPtr->format);\n    }\n    if (modelPtr->metadata != NULL) {\n\tTcl_DecrRefCount(modelPtr->metadata);\n    }\n    Tk_FreeOptions(configSpecs, modelPtr, NULL, 0);\n    Tcl_Free(modelPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoCmdDeletedProc --\n *\n *\tThis function is invoked when the image command for an image is\n *\tdeleted. It deletes the image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImgPhotoCmdDeletedProc(\n    void *clientData)\t/* Pointer to PhotoModel structure for\n\t\t\t\t * image. */\n{\n    PhotoModel *modelPtr = (PhotoModel *)clientData;\n\n    modelPtr->imageCmd = NULL;\n    if (modelPtr->tkModel != NULL) {\n\tTk_DeleteImage(modelPtr->interp, Tk_NameOfImage(modelPtr->tkModel));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgPhotoSetSize --\n *\n *\tThis function reallocates the image storage and instance pixmaps for a\n *\tphoto image, as necessary, to change the image's size to `width' x\n *\t`height' pixels.\n *\n * Results:\n *\tTCL_OK if successful, TCL_ERROR if failure occurred (currently just\n *\twith memory allocation.)\n *\n * Side effects:\n *\tStorage gets reallocated, for the model and all its instances.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImgPhotoSetSize(\n    PhotoModel *modelPtr,\n    int width, int height)\n{\n    unsigned char *newPix32 = NULL;\n    int h, offset, pitch;\n    unsigned char *srcPtr, *destPtr;\n    XRectangle validBox, clipBox;\n    Region clipRegion;\n    PhotoInstance *instancePtr;\n\n    if (modelPtr->userWidth > 0) {\n\twidth = modelPtr->userWidth;\n    }\n    if (modelPtr->userHeight > 0) {\n\theight = modelPtr->userHeight;\n    }\n\n    if (width > INT_MAX / 4) {\n\t/* Pitch overflows int */\n\treturn TCL_ERROR;\n    }\n    pitch = width * 4;\n\n    /*\n     * Test if we're going to (re)allocate the main buffer now, so that any\n     * failures will leave the photo unchanged.\n     */\n\n    if ((width != modelPtr->width) || (height != modelPtr->height)\n\t    || (modelPtr->pix32 == NULL)) {\n\tunsigned newPixSize;\n\n\tif (pitch && height > (int)(UINT_MAX / pitch)) {\n\t    return TCL_ERROR;\n\t}\n\tnewPixSize = height * pitch;\n\n\t/*\n\t * Some mallocs() really hate allocating zero bytes. [Bug 619544]\n\t */\n\n\tif (newPixSize == 0) {\n\t    newPix32 = NULL;\n\t} else {\n\t    newPix32 = (unsigned char *)Tcl_AttemptAlloc(newPixSize);\n\t    if (newPix32 == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n\n    /*\n     * We have to trim the valid region if it is currently larger than the new\n     * image size.\n     */\n\n    XClipBox(modelPtr->validRegion, &validBox);\n    if ((validBox.x + validBox.width > width)\n\t    || (validBox.y + validBox.height > height)) {\n\tclipBox.x = 0;\n\tclipBox.y = 0;\n\tclipBox.width = width;\n\tclipBox.height = height;\n\tclipRegion = XCreateRegion();\n\tXUnionRectWithRegion(&clipBox, clipRegion, clipRegion);\n\tXIntersectRegion(modelPtr->validRegion, clipRegion,\n\t\tmodelPtr->validRegion);\n\tXDestroyRegion(clipRegion);\n\tXClipBox(modelPtr->validRegion, &validBox);\n    }\n\n    /*\n     * Use the reallocated storage (allocation above) for the 32-bit image and\n     * copy over valid regions. Note that this test is true precisely when the\n     * allocation has already been done.\n     */\n\n    if (newPix32 != NULL) {\n\t/*\n\t * Zero the new array. The dithering code shouldn't read the areas\n\t * outside validBox, but they might be copied to another photo image\n\t * or written to a file.\n\t */\n\n\tif ((modelPtr->pix32 != NULL)\n\t    && ((width == modelPtr->width) || (width == validBox.width))) {\n\t    if (validBox.y > 0) {\n\t\tmemset(newPix32, 0, ((size_t) validBox.y * pitch));\n\t    }\n\t    h = validBox.y + validBox.height;\n\t    if (h < height) {\n\t\tmemset(newPix32 + h*pitch, 0, ((size_t) (height - h) * pitch));\n\t    }\n\t} else {\n\t    memset(newPix32, 0, ((size_t)height * pitch));\n\t}\n\n\tif (modelPtr->pix32 != NULL) {\n\t    /*\n\t     * Copy the common area over to the new array array and free the\n\t     * old array.\n\t     */\n\n\t    if (width == modelPtr->width) {\n\n\t\t/*\n\t\t * The region to be copied is contiguous.\n\t\t */\n\n\t\toffset = validBox.y * pitch;\n\t\tmemcpy(newPix32 + offset, modelPtr->pix32 + offset,\n\t\t\t((size_t)validBox.height * pitch));\n\n\t    } else if ((validBox.width > 0) && (validBox.height > 0)) {\n\t\t/*\n\t\t * Area to be copied is not contiguous - copy line by line.\n\t\t */\n\n\t\tdestPtr = newPix32 + (validBox.y * width + validBox.x) * 4;\n\t\tsrcPtr = modelPtr->pix32 + (validBox.y * modelPtr->width\n\t\t\t+ validBox.x) * 4;\n\t\tfor (h = validBox.height; h > 0; h--) {\n\t\t    memcpy(destPtr, srcPtr, ((size_t)validBox.width * 4));\n\t\t    destPtr += width * 4;\n\t\t    srcPtr += modelPtr->width * 4;\n\t\t}\n\t    }\n\n\t    Tcl_Free(modelPtr->pix32);\n\t}\n\n\tmodelPtr->pix32 = newPix32;\n\tmodelPtr->width = width;\n\tmodelPtr->height = height;\n\n\t/*\n\t * Dithering will be correct up to the end of the last pre-existing\n\t * complete scanline.\n\t */\n\n\tif ((validBox.x > 0) || (validBox.y > 0)) {\n\t    modelPtr->ditherX = 0;\n\t    modelPtr->ditherY = 0;\n\t} else if (validBox.width == width) {\n\t    if ((int) validBox.height < modelPtr->ditherY) {\n\t\tmodelPtr->ditherX = 0;\n\t\tmodelPtr->ditherY = validBox.height;\n\t    }\n\t} else if ((modelPtr->ditherY > 0)\n\t\t|| ((int) validBox.width < modelPtr->ditherX)) {\n\t    modelPtr->ditherX = validBox.width;\n\t    modelPtr->ditherY = 0;\n\t}\n    }\n\n    ToggleComplexAlphaIfNeeded(modelPtr);\n\n    /*\n     * Now adjust the sizes of the pixmaps for all of the instances.\n     */\n\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tTkImgPhotoInstanceSetSize(instancePtr);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MatchFileFormat --\n *\n *\tThis function is called to find a photo image file format handler\n *\twhich can parse the image data in the given file. If a user-specified\n *\tformat string is provided, only handlers whose names match a prefix of\n *\tthe format string are tried.\n *\n * Results:\n *\tA standard TCL return value. If the return value is TCL_OK, a pointer\n *\tto the image format record is returned in *imageFormatPtr or\n *\t*imageFormatVersion3Ptr, and the width and height of the image are\n *\treturned in *widthPtr and *heightPtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMatchFileFormat(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Channel chan,\t\t/* The image file, open for reading. */\n    const char *fileName,\t/* The name of the image file. */\n    Tcl_Obj *formatObj,\t\t/* User-specified format string, or NULL. */\n    Tcl_Obj *metadataInObj,\t/* User-specified metadata, may be NULL */\n    Tcl_Obj *metadataOutObj,\t/* metadata to return, may be NULL */\n    Tk_PhotoImageFormat **imageFormatPtr,\n\t\t\t\t/* A pointer to the photo image format record\n\t\t\t\t * is returned here. For formatVersion3, this is\n\t\t\t\t * set to NULL */\n    Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr,\n\t\t\t\t/* A pointer to the photo image formatVersion3\n\t\t\t\t * record is returned here. For non\n\t\t\t\t * formatVersion3, this is set to NULL*/\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n{\n    bool matched = false;\n    Tk_PhotoImageFormat *formatPtr;\n    Tk_PhotoImageFormatVersion3 *formatVersion3Ptr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    const char *formatString = NULL;\n\n    if (formatObj) {\n\tformatString = Tcl_GetString(formatObj);\n    }\n\n    /*\n     * Scan through the table of file format handlers to find one which can\n     * handle the image.\n     */\n\n    for (formatPtr = tsdPtr->formatList; formatPtr != NULL;\n\t    formatPtr = formatPtr->nextPtr) {\n\tif (formatObj != NULL) {\n\t    if (strncasecmp(formatString,\n\t\t    formatPtr->name, strlen(formatPtr->name)) != 0) {\n\t\tcontinue;\n\t    }\n\t    matched = true;\n\t    if (formatPtr->fileMatchProc == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"-file option isn't supported for %s images\",\n\t\t\tformatString));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"NOT_FILE_FORMAT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (formatPtr->fileMatchProc != NULL) {\n\t    (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);\n\n\t    if (formatPtr->fileMatchProc(chan, fileName, formatObj,\n\t\t    widthPtr, heightPtr, interp)) {\n\t\tif (*widthPtr < 1) {\n\t\t    *widthPtr = 1;\n\t\t}\n\t\tif (*heightPtr < 1) {\n\t\t    *heightPtr = 1;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * For old and not version 3 format, exit now with success\n     */\n\n    if (formatPtr != NULL) {\n\t*imageFormatPtr = formatPtr;\n\t*imageFormatVersion3Ptr = NULL;\n\t(void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Scan through the table of file format version 3 handlers to find one\n     * which can handle the image.\n     */\n\n    for (formatVersion3Ptr = tsdPtr->formatListVersion3;\n\t    formatVersion3Ptr != NULL;\n\t    formatVersion3Ptr = formatVersion3Ptr->nextPtr) {\n\tif (formatObj != NULL) {\n\t    if (strncasecmp(formatString,\n\t\t    formatVersion3Ptr->name, strlen(formatVersion3Ptr->name))\n\t\t    != 0) {\n\t\tcontinue;\n\t    }\n\t    matched = true;\n\t    if (formatVersion3Ptr->fileMatchProc == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"-file option isn't supported for %s images\",\n\t\t\tformatString));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"NOT_FILE_FORMAT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (formatVersion3Ptr->fileMatchProc != NULL) {\n\t    (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);\n\n\t    if (formatVersion3Ptr->fileMatchProc(interp, chan, fileName,\n\t\t    formatObj, metadataInObj, widthPtr, heightPtr,\n\t\t    metadataOutObj)) {\n\t\tif (*widthPtr < 1) {\n\t\t    *widthPtr = 1;\n\t\t}\n\t\tif (*heightPtr < 1) {\n\t\t    *heightPtr = 1;\n\t\t}\n\t\t*imageFormatVersion3Ptr = formatVersion3Ptr;\n\t\t*imageFormatPtr = NULL;\n\t\t(void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);\n\t\treturn TCL_OK;\n\t    }\n\n\t    /*\n\t     * Check if driver has shared or changed the metadata Tcl object.\n\t     * In this case, release and recreate it.\n\t     */\n\n\t    if (metadataOutObj != NULL) {\n\t\tTcl_Size dictSize;\n\t\tif (Tcl_IsShared(metadataOutObj)\n\t\t\t|| TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize)\n\t\t\t|| dictSize > 0) {\n\t\t    Tcl_DecrRefCount(metadataOutObj);\n\t\t    metadataOutObj = Tcl_NewDictObj();\n\t\t    Tcl_IncrRefCount(metadataOutObj);\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * No matching format found\n     */\n\n    if ((formatObj != NULL) && !matched) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"image file format \\\"%s\\\" is not supported\",\n\t\tformatString));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"PHOTO_FORMAT\",\n\t\tformatString, (char *)NULL);\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"couldn't recognize data in image file \\\"%s\\\"\",\n\t\tfileName));\n\tTcl_SetErrorCode(interp, \"TK\", \"PHOTO\", \"IMAGE\",\n\t\t\"UNRECOGNIZED_DATA\", (char *)NULL);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MatchStringFormat --\n *\n *\tThis function is called to find a photo image file format handler\n *\twhich can parse the image data in the given string. If a\n *\tuser-specified format string is provided, only handlers whose names\n *\tmatch a prefix of the format string are tried.\n *\n * Results:\n *\tA standard TCL return value. If the return value is TCL_OK, a pointer\n *\tto the image format record is returned in *imageFormatPtr or\n *\t*imageFormatVersion3Ptr, and the width and height of the image are\n *\treturned in *widthPtr and *heightPtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMatchStringFormat(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tcl_Obj *data,\t\t/* Object containing the image data. */\n    Tcl_Obj *formatObj,\t\t/* User-specified format string, or NULL. */\n    Tcl_Obj *metadataInObj,\t/* User-specified metadata, may be NULL */\n    Tcl_Obj *metadataOutObj,\t/* metadata output dict, may be NULL */\n    Tk_PhotoImageFormat **imageFormatPtr,\n\t\t\t\t/* A pointer to the photo image format record\n\t\t\t\t * is returned here. For formatVersion3, this is\n\t\t\t\t * set to NULL*/\n    Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr,\n\t\t\t\t/* A pointer to the photo image formatVersion3\n\t\t\t\t * record is returned here. For non\n\t\t\t\t * formatVersion3, this is set to NULL*/\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n{\n    bool matched = false;\n    Tk_PhotoImageFormat *formatPtr, *defaultFormatPtr = NULL;\n    Tk_PhotoImageFormatVersion3 *formatVersion3Ptr = NULL;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    const char *formatString = NULL;\n\n    if (formatObj) {\n\tformatString = Tcl_GetString(formatObj);\n    }\n\n    /*\n     * Scan through the table of file format handlers to find one which can\n     * handle the image.\n     */\n\n    for (formatPtr = tsdPtr->formatList; formatPtr != NULL;\n\t    formatPtr = formatPtr->nextPtr) {\n\t/*\n\t * To keep the behaviour of older versions (Tk <= 8.6), the default\n\t * list-of-lists string format is checked last. Remember its position.\n\t */\n\n\tif (strncasecmp(\"default\", formatPtr->name, strlen(formatPtr->name))\n\t\t== 0) {\n\t    defaultFormatPtr = formatPtr;\n\t}\n\n\tif (formatObj != NULL) {\n\t    if (strncasecmp(formatString,\n\t\t    formatPtr->name, strlen(formatPtr->name)) != 0) {\n\t\tcontinue;\n\t    }\n\t    matched = true;\n\t    if (formatPtr->stringMatchProc == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"-data option isn't supported for %s images\",\n\t\t\tformatString));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"NOT_DATA_FORMAT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * If this is the default format, and it was not passed as -format\n\t * option, skip the stringMatchProc test. It'll be done later\n\t */\n\n\tif (formatObj == NULL && formatPtr == defaultFormatPtr) {\n\t    continue;\n\t}\n\n\tif ((formatPtr->stringMatchProc != NULL)\n\t\t&& (formatPtr->stringReadProc != NULL)\n\t\t&& formatPtr->stringMatchProc(data, formatObj,\n\t\t\twidthPtr, heightPtr, interp)) {\n\t    break;\n\t}\n    }\n\n    if (formatPtr == NULL) {\n\tfor (formatVersion3Ptr = tsdPtr->formatListVersion3;\n\t\tformatVersion3Ptr != NULL;\n\t\tformatVersion3Ptr = formatVersion3Ptr->nextPtr) {\n\t    if (formatObj != NULL) {\n\t\tif (strncasecmp(formatString,\n\t\t\tformatVersion3Ptr->name, strlen(formatVersion3Ptr->name)\n\t\t\t) != 0) {\n\t\t    continue;\n\t\t}\n\t\tmatched = true;\n\t\tif (formatVersion3Ptr->stringMatchProc == NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"-data option isn't supported for %s images\",\n\t\t\t    formatString));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t    \"NOT_DATA_FORMAT\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    if ((formatVersion3Ptr->stringMatchProc != NULL)\n\t\t    && (formatVersion3Ptr->stringReadProc != NULL)\n\t\t    && formatVersion3Ptr->stringMatchProc(interp, data,\n\t\t\t    formatObj, metadataInObj, widthPtr, heightPtr,\n\t\t\t    metadataOutObj)) {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * Check if driver has shared or changed the metadata tcl object.\n\t     * In this case, release and recreate it.\n\t     */\n\n\t    if (metadataOutObj != NULL) {\n\t\tTcl_Size dictSize;\n\t\tif (Tcl_IsShared(metadataOutObj)\n\t\t\t|| TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize)\n\t\t\t|| dictSize > 0) {\n\t\t    Tcl_DecrRefCount(metadataOutObj);\n\t\t    metadataOutObj = Tcl_NewDictObj();\n\t\t    Tcl_IncrRefCount(metadataOutObj);\n\t\t}\n\t    }\n\t}\n    }\n\n    if (formatPtr == NULL && formatVersion3Ptr == NULL) {\n\t/*\n\t * Try the default format as last resort (only if no -format option\n\t * was passed).\n\t */\n\n\tif ( formatObj == NULL && defaultFormatPtr == NULL) {\n\t    Tcl_Panic(\"default image format handler not registered\");\n\t}\n\tif ( formatObj == NULL\n\t\t&& defaultFormatPtr->stringMatchProc != NULL\n\t\t&& defaultFormatPtr->stringReadProc != NULL\n\t\t&& defaultFormatPtr->stringMatchProc(data, formatObj,\n\t\twidthPtr, heightPtr, interp) != 0) {\n\t    formatPtr = defaultFormatPtr;\n\t} else if ((formatObj != NULL) && !matched) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"image format \\\"%s\\\" is not supported\", formatString));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"PHOTO_FORMAT\",\n\t\t    formatString, (char *)NULL);\n\t    return TCL_ERROR;\n\t} else {\n\n\t    /*\n\t     * Some lower level routine (stringMatchProc) may have already set\n\t     * a specific error message, so just return this. Otherwise return\n\t     * a generic image data error.\n\t     */\n\n\t    if (Tcl_GetString(Tcl_GetObjResult(interp))[0] == '\\0') {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't recognize image data\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"PHOTO\",\n\t\t\t\"UNRECOGNIZED_DATA\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n    }\n\n    *imageFormatPtr = formatPtr;\n    *imageFormatVersion3Ptr = formatVersion3Ptr;\n\n    /*\n     * Some stringMatchProc might have left error messages and error codes in\n     * interp.\tClear them before return.\n     */\n    Tcl_ResetResult(interp);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FindPhoto --\n *\n *\tThis function is called to get an opaque handle (actually a\n *\tPhotoModel *) for a given image, which can be used in subsequent\n *\tcalls to Tk_PhotoPutBlock, etc. The `name' parameter is the name of\n *\tthe image.\n *\n * Results:\n *\tThe handle for the photo image, or NULL if there is no photo image\n *\twith the name given.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_PhotoHandle\nTk_FindPhoto(\n    Tcl_Interp *interp,\t\t/* Interpreter (application) in which image\n\t\t\t\t * exists. */\n    const char *imageName)\t/* Name of the desired photo image. */\n{\n    const Tk_ImageType *typePtr;\n    void *clientData =\n\t    Tk_GetImageModelData(interp, imageName, &typePtr);\n\n    if ((typePtr == NULL) || (typePtr->name != tkPhotoImageType.name)) {\n\treturn NULL;\n    }\n    return clientData;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoPutBlock --\n *\n *\tThis function is called to put image data into a photo image.\n *\n * Results:\n *\tA standard Tcl result code.\n *\n * Side effects:\n *\tThe image data is stored. The image may be expanded. The Tk image code\n *\tis informed that the image has changed. If the result code is\n *\tTCL_ERROR, an error message will be placed in the interpreter (if\n *\tnon-NULL).\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PhotoPutBlock(\n    Tcl_Interp *interp,\t\t/* Interpreter for passing back error\n\t\t\t\t * messages, or NULL. */\n    Tk_PhotoHandle handle,\t/* Opaque handle for the photo image to be\n\t\t\t\t * updated. */\n    Tk_PhotoImageBlock *blockPtr,\n\t\t\t\t/* Pointer to a structure describing the pixel\n\t\t\t\t * data to be copied into the image. */\n    int x, int y,\t\t/* Coordinates of the top-left pixel to be\n\t\t\t\t * updated in the image. */\n    int width, int height,\t/* Dimensions of the area of the image to be\n\t\t\t\t * updated. */\n    int compRule)\t\t/* Compositing rule to use when processing\n\t\t\t\t * transparent pixels. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n    Tk_PhotoImageBlock sourceBlock;\n    unsigned char *memToFree;\n    int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;\n    int wLeft, hLeft, wCopy, hCopy, pitch;\n    unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr;\n    int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;\n    XRectangle rect;\n\n    /*\n     * Zero-sized blocks never cause any changes. [Bug 3078902]\n     */\n\n    if (blockPtr->height == 0 || blockPtr->width == 0) {\n\treturn TCL_OK;\n    }\n\n    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;\n\n    if ((modelPtr->userWidth != 0) && ((x + width) > modelPtr->userWidth)) {\n\twidth = modelPtr->userWidth - x;\n    }\n    if ((modelPtr->userHeight != 0)\n\t    && ((y + height) > modelPtr->userHeight)) {\n\theight = modelPtr->userHeight - y;\n    }\n    if ((width <= 0) || (height <= 0)) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Fix for bug e4336bef5d:\n     *\n     * Make a local copy of *blockPtr, as we might have to change some\n     * of its fields and don't want to interfere with the caller's data.\n     *\n     * If source and destination are the same image, create a copy  of the\n     * source data in our local sourceBlock.\n     *\n     * To find out, just comparing the pointers is not enough - they might have\n     * different values and still point to the same block of memory. (e.g.\n     * if the -from option was passed to [imageName copy])\n     */\n    sourceBlock = *blockPtr;\n    memToFree = NULL;\n    if (modelPtr->pix32 && (sourceBlock.pixelPtr >= modelPtr->pix32)\n\t    && (sourceBlock.pixelPtr < modelPtr->pix32 + modelPtr->width\n\t    * modelPtr->height * 4)) {\n\t/*\n\t * Fix 5c51be6411: avoid reading\n\t *\n\t *\t(sourceBlock.pitch - sourceBlock.width * sourceBlock.pixelSize)\n\t *\n\t * bytes past the end of modelPtr->pix32[] when\n\t *\n\t *\tblockPtr->pixelPtr > (modelPtr->pix32 +\n\t *\t\t4 * modelPtr->width * modelPtr->height -\n\t *\t\tsourceBlock.height * sourceBlock.pitch)\n\t */\n\tunsigned int cpyLen = (sourceBlock.height - 1) * sourceBlock.pitch +\n\t\tsourceBlock.width * sourceBlock.pixelSize;\n\n\tsourceBlock.pixelPtr = (unsigned char *)Tcl_AttemptAlloc(cpyLen);\n\tif (sourceBlock.pixelPtr == NULL) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tmemToFree = sourceBlock.pixelPtr;\n\tmemcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, cpyLen);\n    }\n\n\n    xEnd = x + width;\n    yEnd = y + height;\n    if ((xEnd > modelPtr->width) || (yEnd > modelPtr->height)) {\n\tif (ImgPhotoSetSize(modelPtr, MAX(xEnd, modelPtr->width),\n\t\tMAX(yEnd, modelPtr->height)) == TCL_ERROR) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    }\n\t    goto errorExit;\n\t}\n    }\n\n    if ((y < modelPtr->ditherY) || ((y == modelPtr->ditherY)\n\t    && (x < modelPtr->ditherX))) {\n\t/*\n\t * The dithering isn't correct past the start of this block.\n\t */\n\n\tmodelPtr->ditherX = x;\n\tmodelPtr->ditherY = y;\n    }\n\n    /*\n     * If this image block could have different red, green and blue\n     * components, mark it as a color image.\n     */\n\n    greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];\n    blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];\n    alphaOffset = sourceBlock.offset[3];\n    if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {\n\talphaOffset = 0;\n\tsourceIsSimplePhoto = 1;\n    } else {\n\talphaOffset -= sourceBlock.offset[0];\n    }\n    if ((greenOffset != 0) || (blueOffset != 0)) {\n\tmodelPtr->flags |= COLOR_IMAGE;\n    }\n\n    /*\n     * Copy the data into our local 32-bit/pixel array. If we can do it with a\n     * single memmove, we do.\n     */\n\n    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n    pitch = modelPtr->width * 4;\n\n    /*\n     * Test to see if we can do the whole write in a single copy. This test is\n     * probably too restrictive. We should also be able to do a memmove if\n     * pixelSize == 3 and alphaOffset == 0. Maybe other cases too.\n     */\n\n    if ((sourceBlock.pixelSize == 4)\n\t    && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)\n\t    && (width <= sourceBlock.width) && (height <= sourceBlock.height)\n\t    && ((height == 1) || ((x == 0) && (width == modelPtr->width)\n\t\t&& (sourceBlock.pitch == pitch)))\n\t    && (compRule == TK_PHOTO_COMPOSITE_SET)) {\n\tmemmove(destLinePtr, sourceBlock.pixelPtr + sourceBlock.offset[0],\n\t\t((size_t)height * width * 4));\n\n\t/*\n\t * We know there's an alpha offset and we're setting the data, so skip\n\t * directly to the point when we recompute the photo validity region.\n\t */\n\n\tgoto recalculateValidRegion;\n    }\n\n    /*\n     * Copy and merge pixels according to the compositing rule.\n     */\n\n    for (hLeft = height; hLeft > 0;) {\n\tint pixelSize = sourceBlock.pixelSize;\n\tint compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET);\n\n\tsrcLinePtr = sourceBlock.pixelPtr + sourceBlock.offset[0];\n\thCopy = MIN(hLeft, sourceBlock.height);\n\thLeft -= hCopy;\n\tfor (; hCopy > 0; --hCopy) {\n\t    /*\n\t     * If the layout of the source line matches our memory layout and\n\t     * we're setting, we can just copy the bytes directly, which is\n\t     * much faster.\n\t     */\n\n\t    if ((pixelSize == 4) && (greenOffset == 1)\n\t\t    && (blueOffset == 2) && (alphaOffset == 3)\n\t\t    && (width <= sourceBlock.width)\n\t\t    && compRuleSet) {\n\t\tmemcpy(destLinePtr, srcLinePtr, ((size_t)width * 4));\n\t\tsrcLinePtr += sourceBlock.pitch;\n\t\tdestLinePtr += pitch;\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * Have to copy the slow way.\n\t     */\n\n\t    destPtr = destLinePtr;\n\t    for (wLeft = width; wLeft > 0;) {\n\t\twCopy = MIN(wLeft, sourceBlock.width);\n\t\twLeft -= wCopy;\n\t\tsrcPtr = srcLinePtr;\n\n\t\t/*\n\t\t * But we might be lucky and be able to use fairly fast loops.\n\t\t * It's worth checking...\n\t\t */\n\n\t\tif (alphaOffset == 0) {\n\t\t    /*\n\t\t     * This is the non-alpha case, so can still be fairly\n\t\t     * fast. Note that in the non-alpha-source case, the\n\t\t     * compositing rule doesn't apply.\n\t\t     */\n\n\t\t    for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {\n\t\t\t*destPtr++ = srcPtr[0];\n\t\t\t*destPtr++ = srcPtr[greenOffset];\n\t\t\t*destPtr++ = srcPtr[blueOffset];\n\t\t\t*destPtr++ = 255;\n\t\t    }\n\t\t    continue;\n\t\t} else if (compRuleSet) {\n\t\t    /*\n\t\t     * This is the SET compositing rule, which just replaces\n\t\t     * what was there before with the new data. This is\n\t\t     * another fairly fast case. No point in doing a memcpy();\n\t\t     * the order of channels is probably wrong.\n\t\t     */\n\n\t\t    for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {\n\t\t\t*destPtr++ = srcPtr[0];\n\t\t\t*destPtr++ = srcPtr[greenOffset];\n\t\t\t*destPtr++ = srcPtr[blueOffset];\n\t\t\t*destPtr++ = srcPtr[alphaOffset];\n\t\t    }\n\t\t    continue;\n\t\t}\n\n\t\t/*\n\t\t * Bother; need to consider the alpha value of each pixel to\n\t\t * know what to do.\n\t\t */\n\n\t\tfor (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) {\n\t\t    int alpha = srcPtr[alphaOffset];\n\n\t\t    if (alpha == 255 || !destPtr[3]) {\n\t\t\t/*\n\t\t\t * Either the source is 100% opaque, or the\n\t\t\t * destination is entirely blank. In all cases, we\n\t\t\t * just set the destination to the source.\n\t\t\t */\n\n\t\t\t*destPtr++ = srcPtr[0];\n\t\t\t*destPtr++ = srcPtr[greenOffset];\n\t\t\t*destPtr++ = srcPtr[blueOffset];\n\t\t\t*destPtr++ = alpha;\n\t\t\tcontinue;\n\t\t    }\n\n\t\t    /*\n\t\t     * Can still skip doing work if the source is 100%\n\t\t     * transparent at this point.\n\t\t     */\n\n\t\t    if (alpha) {\n\t\t\tint Alpha = destPtr[3];\n\n\t\t\t/*\n\t\t\t * OK, there's real work to be done. Luckily, there's\n\t\t\t * a substantial literature on what to do in this\n\t\t\t * case. In particular, Porter and Duff have done a\n\t\t\t * taxonomy of compositing rules, and the right one is\n\t\t\t * the \"Source Over\" rule. This code implements that.\n\t\t\t */\n\n\t\t\tdestPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, destPtr[0],\n\t\t\t\tAlpha);\n\t\t\tdestPtr[1] = PD_SRC_OVER(srcPtr[greenOffset], alpha,\n\t\t\t\tdestPtr[1], Alpha);\n\t\t\tdestPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha,\n\t\t\t\tdestPtr[2], Alpha);\n\t\t\tdestPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha);\n\t\t    }\n\n\t\t    destPtr += 4;\n\t\t}\n\t    }\n\t    srcLinePtr += sourceBlock.pitch;\n\t    destLinePtr += pitch;\n\t}\n    }\n\n    /*\n     * Add this new block to the region which specifies which data is valid.\n     */\n\n    if (alphaOffset) {\n\t/*\n\t * This block is grossly inefficient. For each row in the image, it\n\t * finds each contiguous string of nontransparent pixels, then marks\n\t * those areas as valid in the validRegion mask. This makes drawing\n\t * very efficient, because of the way we use X: we just say, here's\n\t * your mask, and here's your data. We need not worry about the\n\t * current background color, etc. But this costs us a lot on the image\n\t * setup. Still, image setup only happens once, whereas the drawing\n\t * happens many times, so this might be the best way to go.\n\t *\n\t * An alternative might be to not set up this mask, and instead, at\n\t * drawing time, for each transparent pixel, set its color to the\n\t * color of the background behind that pixel. This is what I suspect\n\t * most of programs do. However, they don't have to deal with the\n\t * canvas, which could have many different background colors.\n\t * Determining the correct bg color for a given pixel might be\n\t * expensive.\n\t */\n\n\tif (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {\n\t    Region workRgn;\n\n\t    /*\n\t     * Don't need this when using the OVERLAY compositing rule, which\n\t     * always strictly increases the valid region.\n\t     */\n\n\trecalculateValidRegion:\n\t    workRgn = XCreateRegion();\n\t    rect.x = x;\n\t    rect.y = y;\n\t    rect.width = width;\n\t    rect.height = height;\n\t    XUnionRectWithRegion(&rect, workRgn, workRgn);\n\t    XSubtractRegion(modelPtr->validRegion, workRgn,\n\t\t    modelPtr->validRegion);\n\t    XDestroyRegion(workRgn);\n\t}\n\n\t/*\n\t * Factorize out the main part of the building of the region data to\n\t * allow for more efficient per-platform implementations. [Bug 919066]\n\t */\n\n\tTkpBuildRegionFromAlphaData(modelPtr->validRegion, (unsigned) x,\n\t\t(unsigned) y, (unsigned) width, (unsigned) height,\n\t\tmodelPtr->pix32 + (y * modelPtr->width + x) * 4 + 3,\n\t\t4, (unsigned) modelPtr->width * 4);\n    } else {\n\trect.x = x;\n\trect.y = y;\n\trect.width = width;\n\trect.height = height;\n\tXUnionRectWithRegion(&rect, modelPtr->validRegion,\n\t\tmodelPtr->validRegion);\n    }\n\n    /*\n     * Check if display code needs alpha blending...\n     */\n\n    if (!sourceIsSimplePhoto && (height == 1)) {\n\t/*\n\t * Optimize the single span case if we can. This speeds up code that\n\t * builds up large simple-alpha images by scan-lines or individual\n\t * pixels. We don't negate COMPLEX_ALPHA in this case. [Bug 1409140]\n\t * [Patch 1539990]\n\t */\n\n\tif (!(modelPtr->flags & COMPLEX_ALPHA)) {\n\t    int x1;\n\n\t    for (x1=x ; x1<x+width ; x1++) {\n\t\tunsigned char newAlpha;\n\n\t\tdestLinePtr = modelPtr->pix32 + (y*modelPtr->width + x1)*4;\n\t\tnewAlpha = destLinePtr[3];\n\t\tif (newAlpha && newAlpha != 255) {\n\t\t    modelPtr->flags |= COMPLEX_ALPHA;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    } else if ((alphaOffset != 0) || (modelPtr->flags & COMPLEX_ALPHA)) {\n\t/*\n\t * Check for partial transparency if alpha pixels are specified, or\n\t * rescan if we already knew such pixels existed. To restrict this\n\t * Toggle to only checking the changed pixels requires knowing where\n\t * the alpha pixels are.\n\t */\n\n\tToggleComplexAlphaIfNeeded(modelPtr);\n    }\n\n    /*\n     * Update each instance.\n     */\n\n    Tk_DitherPhoto((Tk_PhotoHandle)modelPtr, x, y, width, height);\n\n    /*\n     * Tell the core image code that this image has changed.\n     */\n\n    Tk_ImageChanged(modelPtr->tkModel, x, y, width, height,\n\t    modelPtr->width, modelPtr->height);\n\n    if (memToFree) Tcl_Free(memToFree);\n\n    return TCL_OK;\n\n  errorExit:\n    if (memToFree) Tcl_Free(memToFree);\n\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoPutZoomedBlock --\n *\n *\tThis function is called to put image data into a photo image, with\n *\tpossible subsampling and/or zooming of the pixels.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image data is stored. The image may be expanded. The Tk image code\n *\tis informed that the image has changed.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PhotoPutZoomedBlock(\n    Tcl_Interp *interp,\t\t/* Interpreter for passing back error\n\t\t\t\t * messages, or NULL. */\n    Tk_PhotoHandle handle,\t/* Opaque handle for the photo image to be\n\t\t\t\t * updated. */\n    Tk_PhotoImageBlock *blockPtr,\n\t\t\t\t/* Pointer to a structure describing the pixel\n\t\t\t\t * data to be copied into the image. */\n    int x, int y,\t\t/* Coordinates of the top-left pixel to be\n\t\t\t\t * updated in the image. */\n    int width, int height,\t/* Dimensions of the area of the image to be\n\t\t\t\t * updated. */\n    int zoomX, int zoomY,\t/* Zoom factors for the X and Y axes. */\n    int subsampleX, int subsampleY,\n\t\t\t\t/* Subsampling factors for the X and Y\n\t\t\t\t * axes. */\n    int compRule)\t\t/* Compositing rule to use when processing\n\t\t\t\t * transparent pixels. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n    Tk_PhotoImageBlock sourceBlock;\n    unsigned char *memToFree;\n    int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;\n    int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt;\n    unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr;\n    int pitch, xRepeat, yRepeat, blockXSkip, blockYSkip, sourceIsSimplePhoto;\n    XRectangle rect;\n\n    /*\n     * Zero-sized blocks never cause any changes. [Bug 3078902]\n     */\n\n    if (blockPtr->height == 0 || blockPtr->width == 0) {\n\treturn TCL_OK;\n    }\n\n    if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) {\n\treturn Tk_PhotoPutBlock(interp, handle, blockPtr, x, y, width, height,\n\t\tcompRule);\n    }\n\n    sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;\n    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;\n\n    if (zoomX <= 0 || zoomY <= 0) {\n\treturn TCL_OK;\n    }\n    if ((modelPtr->userWidth != 0) && ((x + width) > modelPtr->userWidth)) {\n\twidth = modelPtr->userWidth - x;\n    }\n    if ((modelPtr->userHeight != 0)\n\t    && ((y + height) > modelPtr->userHeight)) {\n\theight = modelPtr->userHeight - y;\n    }\n    if (width <= 0 || height <= 0) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Fix for Bug e4336bef5d:\n     * Make a local copy of *blockPtr, as we might have to change some\n     * of its fields and don't want to interfere with the caller's data.\n     *\n     * If source and destination are the same image, create a copy  of the\n     * source data in our local sourceBlock.\n     *\n     * To find out, just comparing the pointers is not enough - they might have\n     * different values and still point to the same block of memory. (e.g.\n     * if the -from option was passed to [imageName copy])\n     */\n    sourceBlock = *blockPtr;\n    memToFree = NULL;\n    if (modelPtr->pix32 && (sourceBlock.pixelPtr >= modelPtr->pix32)\n\t    && (sourceBlock.pixelPtr < modelPtr->pix32 + modelPtr->width\n\t    * modelPtr->height * 4)) {\n\t/*\n\t * Fix 5c51be6411: avoid reading\n\t *\n\t *\t(sourceBlock.pitch - sourceBlock.width * sourceBlock.pixelSize)\n\t *\n\t * bytes past the end of modelPtr->pix32[] when\n\t *\n\t *\tblockPtr->pixelPtr > (modelPtr->pix32 +\n\t *\t\t4 * modelPtr->width * modelPtr->height -\n\t *\t\tsourceBlock.height * sourceBlock.pitch)\n\t */\n\tunsigned int cpyLen = (sourceBlock.height - 1) * sourceBlock.pitch +\n\t\tsourceBlock.width * sourceBlock.pixelSize;\n\n\tsourceBlock.pixelPtr = (unsigned char *)Tcl_AttemptAlloc(cpyLen);\n\tif (sourceBlock.pixelPtr == NULL) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tmemToFree = sourceBlock.pixelPtr;\n\tmemcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, cpyLen);\n    }\n\n    xEnd = x + width;\n    yEnd = y + height;\n    if ((xEnd > modelPtr->width) || (yEnd > modelPtr->height)) {\n\tif (ImgPhotoSetSize(modelPtr, MAX(xEnd, modelPtr->width),\n\t\tMAX(yEnd, modelPtr->height)) == TCL_ERROR) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    }\n\t    goto errorExit;\n\t}\n    }\n\n    if ((y < modelPtr->ditherY) || ((y == modelPtr->ditherY)\n\t    && (x < modelPtr->ditherX))) {\n\t/*\n\t * The dithering isn't correct past the start of this block.\n\t */\n\n\tmodelPtr->ditherX = x;\n\tmodelPtr->ditherY = y;\n    }\n\n    /*\n     * If this image block could have different red, green and blue\n     * components, mark it as a color image.\n     */\n\n    greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];\n    blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];\n    alphaOffset = sourceBlock.offset[3];\n    if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {\n\talphaOffset = 0;\n\tsourceIsSimplePhoto = 1;\n    } else {\n\talphaOffset -= sourceBlock.offset[0];\n    }\n    if ((greenOffset != 0) || (blueOffset != 0)) {\n\tmodelPtr->flags |= COLOR_IMAGE;\n    }\n\n    /*\n     * Work out what area the pixel data in the block expands to after\n     * subsampling and zooming.\n     */\n\n    blockXSkip = subsampleX * sourceBlock.pixelSize;\n    blockYSkip = subsampleY * sourceBlock.pitch;\n    if (subsampleX > 0) {\n\tblockWid = ((sourceBlock.width + subsampleX - 1) / subsampleX) * zoomX;\n    } else if (subsampleX == 0) {\n\tblockWid = width;\n    } else {\n\tblockWid = ((sourceBlock.width - subsampleX - 1) / -subsampleX) * zoomX;\n    }\n    if (subsampleY > 0) {\n\tblockHt = ((sourceBlock.height + subsampleY - 1) / subsampleY) * zoomY;\n    } else if (subsampleY == 0) {\n\tblockHt = height;\n    } else {\n\tblockHt = ((sourceBlock.height - subsampleY - 1) / -subsampleY) * zoomY;\n    }\n\n    /*\n     * Copy the data into our local 32-bit/pixel array.\n     */\n\n    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n    srcOrigPtr = sourceBlock.pixelPtr + sourceBlock.offset[0];\n    if (subsampleX < 0) {\n\tsrcOrigPtr += (sourceBlock.width - 1) * sourceBlock.pixelSize;\n    }\n    if (subsampleY < 0) {\n\tsrcOrigPtr += (sourceBlock.height - 1) * sourceBlock.pitch;\n    }\n\n    pitch = modelPtr->width * 4;\n    for (hLeft = height; hLeft > 0; ) {\n\thCopy = MIN(hLeft, blockHt);\n\thLeft -= hCopy;\n\tyRepeat = zoomY;\n\tsrcLinePtr = srcOrigPtr;\n\tfor (; hCopy > 0; --hCopy) {\n\t    destPtr = destLinePtr;\n\t    for (wLeft = width; wLeft > 0;) {\n\t\twCopy = MIN(wLeft, blockWid);\n\t\twLeft -= wCopy;\n\t\tsrcPtr = srcLinePtr;\n\t\tfor (; wCopy > 0; wCopy -= zoomX) {\n\t\t    for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) {\n\t\t\tint alpha = srcPtr[alphaOffset];/* Source alpha. */\n\n\t\t\t/*\n\t\t\t * Common case (solid pixels) first\n\t\t\t */\n\n\t\t\tif (!alphaOffset || (alpha == 255)) {\n\t\t\t    *destPtr++ = srcPtr[0];\n\t\t\t    *destPtr++ = srcPtr[greenOffset];\n\t\t\t    *destPtr++ = srcPtr[blueOffset];\n\t\t\t    *destPtr++ = 255;\n\t\t\t    continue;\n\t\t\t}\n\n\t\t\tif (compRule==TK_PHOTO_COMPOSITE_SET || !destPtr[3]) {\n\t\t\t    /*\n\t\t\t     * Either this is the SET rule (we overwrite\n\t\t\t     * whatever is there) or the destination is\n\t\t\t     * entirely blank. In both cases, we just set the\n\t\t\t     * destination to the source.\n\t\t\t     */\n\n\t\t\t    *destPtr++ = srcPtr[0];\n\t\t\t    *destPtr++ = srcPtr[greenOffset];\n\t\t\t    *destPtr++ = srcPtr[blueOffset];\n\t\t\t    *destPtr++ = alpha;\n\t\t\t} else if (alpha) {\n\t\t\t    int Alpha = destPtr[3];\t/* Destination\n\t\t\t\t\t\t\t * alpha. */\n\n\t\t\t    destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha,\n\t\t\t\t    destPtr[0], Alpha);\n\t\t\t    destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,\n\t\t\t\t    destPtr[1], Alpha);\n\t\t\t    destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha,\n\t\t\t\t    destPtr[2], Alpha);\n\t\t\t    destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha);\n\n\t\t\t    destPtr += 4;\n\t\t\t} else {\n\t\t\t    destPtr += 4;\n\t\t\t}\n\t\t    }\n\t\t    srcPtr += blockXSkip;\n\t\t}\n\t    }\n\t    destLinePtr += pitch;\n\t    yRepeat--;\n\t    if (yRepeat <= 0) {\n\t\tsrcLinePtr += blockYSkip;\n\t\tyRepeat = zoomY;\n\t    }\n\t}\n    }\n\n    /*\n     * Recompute the region of data for which we have valid pixels to plot.\n     */\n\n    if (alphaOffset) {\n\tif (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {\n\t    /*\n\t     * Don't need this when using the OVERLAY compositing rule, which\n\t     * always strictly increases the valid region.\n\t     */\n\n\t    Region workRgn = XCreateRegion();\n\n\t    rect.x = x;\n\t    rect.y = y;\n\t    rect.width = width;\n\t    rect.height = 1;\n\t    XUnionRectWithRegion(&rect, workRgn, workRgn);\n\t    XSubtractRegion(modelPtr->validRegion, workRgn,\n\t\t    modelPtr->validRegion);\n\t    XDestroyRegion(workRgn);\n\t}\n\n\tTkpBuildRegionFromAlphaData(modelPtr->validRegion,\n\t\t(unsigned)x, (unsigned)y, (unsigned)width, (unsigned)height,\n\t\t&modelPtr->pix32[(y * modelPtr->width + x) * 4 + 3], 4,\n\t\t(unsigned) modelPtr->width * 4);\n    } else {\n\trect.x = x;\n\trect.y = y;\n\trect.width = width;\n\trect.height = height;\n\tXUnionRectWithRegion(&rect, modelPtr->validRegion,\n\t\tmodelPtr->validRegion);\n    }\n\n    /*\n     * Check if display code needs alpha blending...\n     */\n\n    if (!sourceIsSimplePhoto && (width == 1) && (height == 1)) {\n\t/*\n\t * Optimize the single pixel case if we can. This speeds up code that\n\t * builds up large simple-alpha images by single pixels. We don't\n\t * negate COMPLEX_ALPHA in this case. [Bug 1409140]\n\t */\n\tif (!(modelPtr->flags & COMPLEX_ALPHA)) {\n\t    unsigned char newAlpha;\n\n\t    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;\n\t    newAlpha = destLinePtr[3];\n\n\t    if (newAlpha && newAlpha != 255) {\n\t\tmodelPtr->flags |= COMPLEX_ALPHA;\n\t    }\n\t}\n    } else if ((alphaOffset != 0) || (modelPtr->flags & COMPLEX_ALPHA)) {\n\t/*\n\t * Check for partial transparency if alpha pixels are specified, or\n\t * rescan if we already knew such pixels existed. To restrict this\n\t * Toggle to only checking the changed pixels requires knowing where\n\t * the alpha pixels are.\n\t */\n\tToggleComplexAlphaIfNeeded(modelPtr);\n    }\n\n    /*\n     * Update each instance.\n     */\n\n    Tk_DitherPhoto((Tk_PhotoHandle) modelPtr, x, y, width, height);\n\n    /*\n     * Tell the core image code that this image has changed.\n     */\n\n    Tk_ImageChanged(modelPtr->tkModel, x, y, width, height, modelPtr->width,\n\t    modelPtr->height);\n\n    if (memToFree) Tcl_Free(memToFree);\n\n    return TCL_OK;\n\n  errorExit:\n    if (memToFree) Tcl_Free(memToFree);\n\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DitherPhoto --\n *\n *\tThis function is called to update an area of each instance's pixmap by\n *\tdithering the corresponding area of the image model.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe pixmap of each instance of this image gets updated. The fields in\n *\t*modelPtr indicating which area of the image is correctly dithered\n *\tget updated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DitherPhoto(\n    Tk_PhotoHandle photo,\t/* Image model whose instances are to be\n\t\t\t\t * updated. */\n    int x, int y,\t\t/* Coordinates of the top-left pixel in the\n\t\t\t\t * area to be dithered. */\n    int width, int height)\t/* Dimensions of the area to be dithered. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) photo;\n    PhotoInstance *instancePtr;\n\n    if ((width <= 0) || (height <= 0)) {\n\treturn;\n    }\n\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tTkImgDitherInstance(instancePtr, x, y, width, height);\n    }\n\n    /*\n     * Work out whether this block will be correctly dithered and whether it\n     * will extend the correctly dithered region.\n     */\n\n    if (((y < modelPtr->ditherY)\n\t    || ((y == modelPtr->ditherY) && (x <= modelPtr->ditherX)))\n\t    && ((y + height) > (modelPtr->ditherY))) {\n\t/*\n\t * This block starts inside (or immediately after) the correctly\n\t * dithered region, so the first scan line at least will be right.\n\t * Furthermore this block extends into scanline modelPtr->ditherY.\n\t */\n\n\tif ((x == 0) && (width == modelPtr->width)) {\n\t    /*\n\t     * We are doing the full width, therefore the dithering will be\n\t     * correct to the end.\n\t     */\n\n\t    modelPtr->ditherX = 0;\n\t    modelPtr->ditherY = y + height;\n\t} else {\n\t    /*\n\t     * We are doing partial scanlines, therefore the\n\t     * correctly-dithered region will be extended by at most one scan\n\t     * line.\n\t     */\n\n\t    if (x <= modelPtr->ditherX) {\n\t\tmodelPtr->ditherX = x + width;\n\t\tif (modelPtr->ditherX >= modelPtr->width) {\n\t\t    modelPtr->ditherX = 0;\n\t\t    modelPtr->ditherY++;\n\t\t}\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoBlank --\n *\n *\tThis function is called to clear an entire photo image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe valid region for the image is set to the null region. The generic\n *\timage code is notified that the image has changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_PhotoBlank(\n    Tk_PhotoHandle handle)\t/* Handle for the image to be blanked. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n    PhotoInstance *instancePtr;\n\n    modelPtr->ditherX = modelPtr->ditherY = 0;\n    modelPtr->flags = 0;\n\n    /*\n     * The image has valid data nowhere.\n     */\n\n    if (modelPtr->validRegion != NULL) {\n\tXDestroyRegion(modelPtr->validRegion);\n    }\n    modelPtr->validRegion = XCreateRegion();\n\n    /*\n     * Clear out the 32-bit pixel storage array. Clear out the dithering error\n     * arrays for each instance.\n     */\n\n    if (modelPtr->pix32) {\n\tmemset(modelPtr->pix32, 0,\n\t\t((size_t)modelPtr->width * modelPtr->height * 4));\n    }\n    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;\n\t    instancePtr = instancePtr->nextPtr) {\n\tTkImgResetDither(instancePtr);\n    }\n\n    /*\n     * Tell the core image code that this image has changed.\n     */\n\n    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,\n\t    modelPtr->height, modelPtr->width, modelPtr->height);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoExpand --\n *\n *\tThis function is called to request that a photo image be expanded if\n *\tnecessary to be at least `width' pixels wide and `height' pixels high.\n *\tIf the user has declared a definite image size (using the -width and\n *\t-height configuration options) then this call has no effect.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size of the photo image may change; if so the generic image code\n *\tis informed.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PhotoExpand(\n    Tcl_Interp *interp,\t\t/* Interpreter for passing back error\n\t\t\t\t * messages, or NULL. */\n    Tk_PhotoHandle handle,\t/* Handle for the image to be expanded. */\n    int width, int height)\t/* Desired minimum dimensions of the image. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n\n    if (width <= modelPtr->width) {\n\twidth = modelPtr->width;\n    }\n    if (height <= modelPtr->height) {\n\theight = modelPtr->height;\n    }\n    if ((width != modelPtr->width) || (height != modelPtr->height)) {\n\tif (ImgPhotoSetSize(modelPtr, MAX(width, modelPtr->width),\n\t\tMAX(height, modelPtr->height)) == TCL_ERROR) {\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\tTK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\tTk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0, modelPtr->width,\n\t\tmodelPtr->height);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoGetSize --\n *\n *\tThis function is called to obtain the current size of a photo image.\n *\n * Results:\n *\tThe image's width and height are returned in *widthp and *heightp.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_PhotoGetSize(\n    Tk_PhotoHandle handle,\t/* Handle for the image whose dimensions are\n\t\t\t\t * requested. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* The dimensions of the image are returned\n\t\t\t\t * here. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n\n    *widthPtr = modelPtr->width;\n    *heightPtr = modelPtr->height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoSetSize --\n *\n *\tThis function is called to set size of a photo image. This call is\n *\tequivalent to using the -width and -height configuration options.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size of the image may change; if so the generic image code is\n *\tinformed.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PhotoSetSize(\n    Tcl_Interp *interp,\t\t/* Interpreter for passing back error\n\t\t\t\t * messages, or NULL. */\n    Tk_PhotoHandle handle,\t/* Handle for the image whose size is to be\n\t\t\t\t * set. */\n    int width, int height)\t/* New dimensions for the image. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n\n    modelPtr->userWidth = width;\n    modelPtr->userHeight = height;\n    if (ImgPhotoSetSize(modelPtr, ((width > 0) ? width: modelPtr->width),\n\t    ((height > 0) ? height: modelPtr->height)) == TCL_ERROR) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    TK_PHOTO_ALLOC_FAILURE_MESSAGE, TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MALLOC\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,\n\t    modelPtr->width, modelPtr->height);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetPhotoValidRegion --\n *\n *\tThis function is called to get the part of the photo where there is\n *\tvalid data. Or, conversely, the part of the photo which is\n *\ttransparent.\n *\n * Results:\n *\tA Region value that indicates the current area of the photo that is\n *\tvalid. This value should not be used after any modification to the\n *\tphoto image.\n *\n * Side Effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nRegion\nTkPhotoGetValidRegion(\n    Tk_PhotoHandle handle)\t/* Handle for the image whose valid region is\n\t\t\t\t * to obtained. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n\n    return modelPtr->validRegion;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImgGetPhoto --\n *\n *\tThis function is called to obtain image data from a photo image. This\n *\tfunction fills in the Tk_PhotoImageBlock structure pointed to by\n *\t`blockPtr' with details of the address and layout of the image data in\n *\tmemory.\n *\n * Results:\n *\tA pointer to the allocated data which should be freed later. NULL if\n *\tthere is no need to free data because blockPtr->pixelPtr points\n *\tdirectly to the image data.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic char *\nImgGetPhoto(\n    PhotoModel *modelPtr,\t/* Handle for the photo image from which image\n\t\t\t\t * data is desired. */\n    Tk_PhotoImageBlock *blockPtr,\n\t\t\t\t/* Information about the address and layout of\n\t\t\t\t * the image data is returned here. */\n    struct SubcommandOptions *optPtr)\n{\n    unsigned char *pixelPtr;\n    int x, y, greenOffset, blueOffset, alphaOffset;\n\n    Tk_PhotoGetImage((Tk_PhotoHandle) modelPtr, blockPtr);\n    if (!blockPtr->pixelPtr) {\n\treturn NULL;\n    }\n    blockPtr->pixelPtr += optPtr->fromY * blockPtr->pitch\n\t    + optPtr->fromX * blockPtr->pixelSize;\n    blockPtr->width = optPtr->fromX2 - optPtr->fromX;\n    blockPtr->height = optPtr->fromY2 - optPtr->fromY;\n\n    if (!(modelPtr->flags & COLOR_IMAGE) &&\n\t    (!(optPtr->options & OPT_BACKGROUND)\n\t    || ((optPtr->background->red == optPtr->background->green)\n\t    && (optPtr->background->red == optPtr->background->blue)))) {\n\tblockPtr->offset[0] = blockPtr->offset[1] = blockPtr->offset[2];\n    }\n    alphaOffset = 0;\n    for (y = 0; y < blockPtr->height; y++) {\n\tpixelPtr = blockPtr->pixelPtr + (y * blockPtr->pitch)\n\t\t+ blockPtr->pixelSize - 1;\n\tfor (x = 0; x < blockPtr->width; x++) {\n\t    if (*pixelPtr != 255) {\n\t\talphaOffset = 3;\n\t\tbreak;\n\t    }\n\t    pixelPtr += blockPtr->pixelSize;\n\t}\n\tif (alphaOffset) {\n\t    break;\n\t}\n    }\n    if (!alphaOffset) {\n\tblockPtr->offset[3]= -1; /* Tell caller alpha need not be read */\n    }\n    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];\n    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];\n    if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) ||\n\t    ((optPtr->options & OPT_GRAYSCALE) && (greenOffset||blueOffset))) {\n\tint newPixelSize;\n\tunsigned char *srcPtr, *destPtr;\n\tchar *data;\n\n\tnewPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset)\n\t\t? 2 : 1;\n\tif ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {\n\t    newPixelSize += 2;\n\t}\n\n\tif (blockPtr->height > (int)((UINT_MAX/newPixelSize)/blockPtr->width)) {\n\t    return NULL;\n\t}\n\tdata = (char *)Tcl_AttemptAlloc(newPixelSize*blockPtr->width*blockPtr->height);\n\tif (data == NULL) {\n\t    return NULL;\n\t}\n\tsrcPtr = blockPtr->pixelPtr + blockPtr->offset[0];\n\tdestPtr = (unsigned char *) data;\n\tif (!greenOffset && !blueOffset) {\n\t    for (y = blockPtr->height; y > 0; y--) {\n\t\tfor (x = blockPtr->width; x > 0; x--) {\n\t\t    *destPtr = *srcPtr;\n\t\t    srcPtr += blockPtr->pixelSize;\n\t\t    destPtr += newPixelSize;\n\t\t}\n\t\tsrcPtr += blockPtr->pitch -\n\t\t\tblockPtr->width * blockPtr->pixelSize;\n\t    }\n\t} else if (optPtr->options & OPT_GRAYSCALE) {\n\t    for (y = blockPtr->height; y > 0; y--) {\n\t\tfor (x = blockPtr->width; x > 0; x--) {\n\t\t    *destPtr = (unsigned char) ((srcPtr[0]*11 + srcPtr[1]*16\n\t\t\t    + srcPtr[2]*5 + 16) >> 5);\n\t\t    srcPtr += blockPtr->pixelSize;\n\t\t    destPtr += newPixelSize;\n\t\t}\n\t\tsrcPtr += blockPtr->pitch -\n\t\t\tblockPtr->width * blockPtr->pixelSize;\n\t    }\n\t} else {\n\t    for (y = blockPtr->height; y > 0; y--) {\n\t\tfor (x = blockPtr->width; x > 0; x--) {\n\t\t    destPtr[0] = srcPtr[0];\n\t\t    destPtr[1] = srcPtr[1];\n\t\t    destPtr[2] = srcPtr[2];\n\t\t    srcPtr += blockPtr->pixelSize;\n\t\t    destPtr += newPixelSize;\n\t\t}\n\t\tsrcPtr += blockPtr->pitch -\n\t\t\tblockPtr->width * blockPtr->pixelSize;\n\t    }\n\t}\n\tsrcPtr = blockPtr->pixelPtr + alphaOffset;\n\tdestPtr = (unsigned char *) data;\n\tif (!alphaOffset) {\n\t    /*\n\t     * Nothing to be done.\n\t     */\n\t} else if (optPtr->options & OPT_BACKGROUND) {\n\t    if (newPixelSize > 2) {\n\t\tint red = optPtr->background->red>>8;\n\t\tint green = optPtr->background->green>>8;\n\t\tint blue = optPtr->background->blue>>8;\n\n\t\tfor (y = blockPtr->height; y > 0; y--) {\n\t\t    for (x = blockPtr->width; x > 0; x--) {\n\t\t\tdestPtr[0] += (unsigned char) (((255 - *srcPtr) *\n\t\t\t\t(red-destPtr[0])) / 255);\n\t\t\tdestPtr[1] += (unsigned char) (((255 - *srcPtr) *\n\t\t\t\t(green-destPtr[1])) / 255);\n\t\t\tdestPtr[2] += (unsigned char) (((255 - *srcPtr) *\n\t\t\t\t(blue-destPtr[2])) / 255);\n\t\t\tsrcPtr += blockPtr->pixelSize;\n\t\t\tdestPtr += newPixelSize;\n\t\t    }\n\t\t    srcPtr += blockPtr->pitch -\n\t\t\t    blockPtr->width * blockPtr->pixelSize;\n\t\t}\n\t    } else {\n\t\tint gray = (unsigned char) (((optPtr->background->red>>8) * 11\n\t\t\t+ (optPtr->background->green>>8) * 16\n\t\t\t+ (optPtr->background->blue>>8) * 5 + 16) >> 5);\n\n\t\tfor (y = blockPtr->height; y > 0; y--) {\n\t\t    for (x = blockPtr->width; x > 0; x--) {\n\t\t\tdestPtr[0] += ((255 - *srcPtr) *\n\t\t\t\t(gray-destPtr[0])) / 255;\n\t\t\tsrcPtr += blockPtr->pixelSize;\n\t\t\tdestPtr += newPixelSize;\n\t\t    }\n\t\t    srcPtr += blockPtr->pitch -\n\t\t\t    blockPtr->width * blockPtr->pixelSize;\n\t\t}\n\t    }\n\t} else {\n\t    destPtr += newPixelSize-1;\n\t    for (y = blockPtr->height; y > 0; y--) {\n\t\tfor (x = blockPtr->width; x > 0; x--) {\n\t\t    *destPtr = *srcPtr;\n\t\t    srcPtr += blockPtr->pixelSize;\n\t\t    destPtr += newPixelSize;\n\t\t}\n\t\tsrcPtr += blockPtr->pitch -\n\t\t\tblockPtr->width * blockPtr->pixelSize;\n\t    }\n\t}\n\tblockPtr->pixelPtr = (unsigned char *) data;\n\tblockPtr->pixelSize = newPixelSize;\n\tblockPtr->pitch = newPixelSize * blockPtr->width;\n\tblockPtr->offset[0] = 0;\n\tif (newPixelSize > 2) {\n\t    blockPtr->offset[1] = 1;\n\t    blockPtr->offset[2] = 2;\n\t    blockPtr->offset[3]= 3;\n\t} else {\n\t    blockPtr->offset[1] = 0;\n\t    blockPtr->offset[2] = 0;\n\t    blockPtr->offset[3]= 1;\n\t}\n\treturn data;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PhotoGetImage --\n *\n *\tThis function is called to obtain image data from a photo image. This\n *\tfunction fills in the Tk_PhotoImageBlock structure pointed to by\n *\t`blockPtr' with details of the address and layout of the image data in\n *\tmemory.\n *\n * Results:\n *\tTRUE (1) indicating that image data is available, for backwards\n *\tcompatibility with the old photo widget.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_PhotoGetImage(\n    Tk_PhotoHandle handle,\t/* Handle for the photo image from which image\n\t\t\t\t * data is desired. */\n    Tk_PhotoImageBlock *blockPtr)\n\t\t\t\t/* Information about the address and layout of\n\t\t\t\t * the image data is returned here. */\n{\n    PhotoModel *modelPtr = (PhotoModel *) handle;\n\n    blockPtr->pixelPtr = modelPtr->pix32;\n    blockPtr->width = modelPtr->width;\n    blockPtr->height = modelPtr->height;\n    blockPtr->pitch = modelPtr->width * 4;\n    blockPtr->pixelSize = 4;\n    blockPtr->offset[0] = 0;\n    blockPtr->offset[1] = 1;\n    blockPtr->offset[2] = 2;\n    blockPtr->offset[3] = 3;\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ImgPostscriptPhoto --\n *\n *\tThis function is called to output the contents of a photo image in\n *\tPostscript by calling the Tk_PostscriptPhoto function.\n *\n * Results:\n *\tReturns a standard Tcl return value.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nImgPhotoPostscript(\n    void *clientData,\t/* Handle for the photo image. */\n    Tcl_Interp *interp,\t\t/* Interpreter. */\n    TCL_UNUSED(Tk_Window),\t\t/* (unused) */\n    Tk_PostscriptInfo psInfo,\t/* Postscript info. */\n    int x, int y,\t\t/* First pixel to output. */\n    int width, int height,\t/* Width and height of area. */\n    TCL_UNUSED(int))\t\t/* (unused) */\n{\n    Tk_PhotoImageBlock block;\n\n    Tk_PhotoGetImage(clientData, &block);\n    block.pixelPtr += y * block.pitch + x * block.pixelSize;\n\n    return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * tab-width: 8\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgPhoto.h",
    "content": "/*\n * tkImgPhoto.h --\n *\n *\tDeclarations for images of type \"photo\" for Tk.\n *\n * Copyright © 1994 The Australian National University.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2002-2008 Donal K. Fellows\n * Copyright © 2003 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * Author: Paul Mackerras (paulus@cs.anu.edu.au),\n *\t   Department of Computer Science,\n *\t   Australian National University.\n */\n\n#include \"tkInt.h\"\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif defined(__CYGWIN__)\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * Forward declarations of the structures we define.\n */\n\n#define PhotoMaster PhotoModel\ntypedef struct ColorTableId\tColorTableId;\ntypedef struct ColorTable\tColorTable;\ntypedef struct PhotoInstance\tPhotoInstance;\ntypedef struct PhotoModel\tPhotoModel;\n\n/*\n * A signed 8-bit integral type. If chars are unsigned and the compiler isn't\n * an ANSI one, then we have to use short instead (which wastes space) to get\n * signed behavior.\n */\n\n#if defined(__STDC__) || defined(_AIX)\n    typedef signed char schar;\n#else\n#   ifndef __CHAR_UNSIGNED__\n\ttypedef char schar;\n#   else\n\ttypedef short schar;\n#   endif\n#endif\n\n/*\n * The maximum number of pixels to transmit to the server in a single\n * XPutImage call.\n */\n\n#define MAX_PIXELS 65536\n\n/*\n * The set of colors required to display a photo image in a window depends on:\n *\t- the visual used by the window\n *\t- the palette, which specifies how many levels of each primary color to\n *\t  use, and\n *\t- the gamma value for the image.\n *\n * Pixel values allocated for specific colors are valid only for the colormap\n * in which they were allocated. Sets of pixel values allocated for displaying\n * photos are re-used in other windows if possible, that is, if the display,\n * colormap, palette and gamma values match. A hash table is used to locate\n * these sets of pixel values, using the following data structure as key:\n */\n\nstruct ColorTableId {\n    Display *display;\t\t/* Qualifies the colormap resource ID. */\n    Colormap colormap;\t\t/* Colormap that the windows are using. */\n    double gamma;\t\t/* Gamma exponent value for images. */\n    Tk_Uid palette;\t\t/* Specifies how many shades of each primary\n\t\t\t\t * we want to allocate. */\n};\n\n/*\n * For a particular (display, colormap, palette, gamma) combination, a data\n * structure of the following type is used to store the allocated pixel values\n * and other information:\n */\n\nstruct ColorTable {\n    ColorTableId id;\t\t/* Information used in selecting this color\n\t\t\t\t * table. */\n    size_t\trefCount;\t\t/* Number of instances using this map. */\n    size_t liveRefCount;\t\t/* Number of instances which are actually in\n\t\t\t\t * use, using this map. */\n    int\tflags;\t\t\t/* See below. */\n    int\tnumColors;\t\t/* Number of colors allocated for this map. */\n\n    XVisualInfo\tvisualInfo;\t/* Information about the visual for windows\n\t\t\t\t * using this color table. */\n\n    unsigned redValues[256];\t/* Maps 8-bit values of red intensity to a\n\t\t\t\t * pixel value or index in pixelMap. */\n    unsigned greenValues[256];\t/* Ditto for green intensity. */\n    unsigned blueValues[256];\t/* Ditto for blue intensity. */\n    unsigned long *pixelMap;\t/* Actual pixel values allocated. */\n\n    unsigned char colorQuant[3][256];\n\t\t\t\t/* Maps 8-bit intensities to quantized\n\t\t\t\t * intensities. The first index is 0 for red,\n\t\t\t\t * 1 for green, 2 for blue. */\n};\n\n/*\n * Bit definitions for the flags field of a ColorTable.\n * BLACK_AND_WHITE:\t\t1 means only black and white colors are\n *\t\t\t\tavailable.\n * COLOR_WINDOW:\t\t1 means a full 3-D color cube has been\n *\t\t\t\tallocated.\n * DISPOSE_PENDING:\t\t1 means a call to DisposeColorTable has been\n *\t\t\t\tscheduled as an idle handler, but it hasn't\n *\t\t\t\tbeen invoked yet.\n * MAP_COLORS:\t\t\t1 means pixel values should be mapped through\n *\t\t\t\tpixelMap.\n */\n\n#ifdef COLOR_WINDOW\n#undef COLOR_WINDOW\n#endif\n\n#define BLACK_AND_WHITE\t\t1\n#define COLOR_WINDOW\t\t2\n#define DISPOSE_PENDING\t\t4\n#define MAP_COLORS\t\t8\n\n/*\n * Definition of the data associated with each photo image model.\n */\n\nstruct PhotoModel {\n    Tk_ImageModel tkModel;\t/* Tk's token for image model. NULL means the\n\t\t\t\t * image is being deleted. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with the application\n\t\t\t\t * using this image. */\n    Tcl_Command imageCmd;\t/* Token for image command (used to delete it\n\t\t\t\t * when the image goes away). NULL means the\n\t\t\t\t * image command has already been deleted. */\n    int\tflags;\t\t\t/* Sundry flags, defined below. */\n    int\twidth, height;\t\t/* Dimensions of image. */\n    int userWidth, userHeight;\t/* User-declared image dimensions. */\n    Tk_Uid palette;\t\t/* User-specified default palette for\n\t\t\t\t * instances of this image. */\n    double gamma;\t\t/* Display gamma value to correct for. */\n    Tcl_Obj *fileObj;\t\t/* Name of file to read into image. */\n    Tcl_Obj *dataObj;\t\t/* Object to use as contents of image. */\n    Tcl_Obj *format;\t\t/* User-specified format of data in image file\n\t\t\t\t * or string value. */\n    Tcl_Obj *metadata;\t\t/* User-specified metadata dict or read from\n\t\t\t\t * image file */\n    unsigned char *pix32;\t/* Local storage for 32-bit image. */\n    int ditherX, ditherY;\t/* Location of first incorrectly dithered\n\t\t\t\t * pixel in image. */\n    Region validRegion;\t/* Tk region indicating which parts of the\n\t\t\t\t * image have valid image data. */\n    PhotoInstance *instancePtr;\t/* First in the list of instances associated\n\t\t\t\t * with this model. */\n};\n\n/*\n * Bit definitions for the flags field of a PhotoModel.\n * COLOR_IMAGE:\t\t\t1 means that the image has different color\n *\t\t\t\tcomponents.\n * IMAGE_CHANGED:\t\t1 means that the instances of this image need\n *\t\t\t\tto be redithered.\n * COMPLEX_ALPHA:\t\t1 means that the instances of this image have\n *\t\t\t\talpha values that aren't 0 or 255, and so need\n *\t\t\t\tthe copy-merge-replace renderer .\n */\n\n#define COLOR_IMAGE\t\t1\n#define IMAGE_CHANGED\t\t2\n#define COMPLEX_ALPHA\t\t4\n\n/*\n * Flag to OR with the compositing rule to indicate that the source, despite\n * having an alpha channel, has simple alpha.\n */\n\n#define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000\n\n/*\n * The following data structure represents all of the instances of a photo\n * image in windows on a given screen that are using the same colormap.\n */\n\nstruct PhotoInstance {\n    PhotoModel *modelPtr;\t/* Pointer to model for image. */\n    Display *display;\t\t/* Display for windows using this instance. */\n    Colormap colormap;\t\t/* The image may only be used in windows with\n\t\t\t\t * this particular colormap. */\n    PhotoInstance *nextPtr;\t/* Pointer to the next instance in the list of\n\t\t\t\t * instances associated with this model. */\n    size_t refCount;\t\t/* Number of instances using this structure. */\n    Tk_Uid palette;\t\t/* Palette for these particular instances. */\n    double gamma;\t\t/* Gamma value for these instances. */\n    Tk_Uid defaultPalette;\t/* Default palette to use if a palette is not\n\t\t\t\t * specified for the model. */\n    ColorTable *colorTablePtr;\t/* Pointer to information about colors\n\t\t\t\t * allocated for image display in windows like\n\t\t\t\t * this one. */\n    Pixmap pixels;\t\t/* X pixmap containing dithered image. */\n    int width, height;\t\t/* Dimensions of the pixmap. */\n    schar *error;\t\t/* Error image, used in dithering. */\n    XImage *imagePtr;\t\t/* Image structure for converted pixels. */\n    XVisualInfo visualInfo;\t/* Information about the visual that these\n\t\t\t\t * windows are using. */\n    GC gc;\t\t\t/* Graphics context for writing images to the\n\t\t\t\t * pixmap. */\n};\n\n/*\n * Implementation of the Porter-Duff Source-Over compositing rule.\n */\n\n#define PD_SRC_OVER(srcColor, srcAlpha, dstColor, dstAlpha) \\\n\t(srcColor*srcAlpha/255) + dstAlpha*(255-srcAlpha)/255*dstColor/255\n#define PD_SRC_OVER_ALPHA(srcAlpha, dstAlpha) \\\n\t(srcAlpha + (255-srcAlpha)*dstAlpha/255)\n\n#undef MIN\n#define MIN(a, b)\t((a) < (b)? (a): (b))\n#undef MAX\n#define MAX(a, b)\t((a) > (b)? (a): (b))\n\f\n/*\n * Declarations of functions shared between the different parts of the\n * photo image implementation.\n */\n\nMODULE_SCOPE void\tTkImgPhotoConfigureInstance(\n\t\t\t    PhotoInstance *instancePtr);\nMODULE_SCOPE void\tTkImgDisposeInstance(void *clientData);\nMODULE_SCOPE void\tTkImgPhotoInstanceSetSize(PhotoInstance *instancePtr);\nMODULE_SCOPE void *TkImgPhotoGet(Tk_Window tkwin, void *clientData);\nMODULE_SCOPE void\tTkImgDitherInstance(PhotoInstance *instancePtr, int x,\n\t\t\t    int y, int width, int height);\nMODULE_SCOPE void\tTkImgPhotoDisplay(void *clientData,\n\t\t\t    Display *display, Drawable drawable,\n\t\t\t    int imageX, int imageY, int width, int height,\n\t\t\t    int drawableX, int drawableY);\nMODULE_SCOPE void\tTkImgPhotoFree(void *clientData,\n\t\t\t    Display *display);\nMODULE_SCOPE void\tTkImgResetDither(PhotoInstance *instancePtr);\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkImgSVGnano.c",
    "content": "/*\n * tkImgSVGnano.c\n *\n *\tA photo file handler for SVG files.\n *\n * Copyright © 2013-14 Mikko Mononen memon@inside.org\n * Copyright © 2018 Christian Gollwitzer auriocus@gmx.de\n * Copyright © 2018 Christian Werner https://www.androwish.org/\n * Copyright © 2018 Rene Zaumseil r.zaumseil@freenet.de\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * This handler is build using the original nanosvg library files from\n * https://github.com/memononen/nanosvg\n *\n */\n\n#include \"tkInt.h\"\n#define NANOSVG_malloc\tTcl_Alloc\n#define NANOSVG_realloc\tTcl_Realloc\n#define NANOSVG_free\tTcl_Free\n#define NANOSVG_SCOPE MODULE_SCOPE\n#define NANOSVG_ALL_COLOR_KEYWORDS\n#define NANOSVG_IMPLEMENTATION\n#include \"nanosvg.h\"\n#define NANOSVGRAST_IMPLEMENTATION\n#include \"nanosvgrast.h\"\n\n/* Additional parameters to nsvgRasterize() */\n\ntypedef struct {\n    double scale;\n    int scaleToHeight;\n    int scaleToWidth;\n} RastOpts;\n\n/*\n * Per interp cache of last NSVGimage which was matched to\n * be immediately rasterized after the match. This helps to\n * eliminate double parsing of the SVG file/string.\n */\n\ntypedef struct {\n    /* A poiner to remember if it is the same svn image (data)\n     * It is a Tcl_Channel if image created by -file option\n     * or a Tcl_Obj, if image is created with the -data option\n     */\n    void *dataOrChan;\n    Tcl_DString formatString;\n    NSVGimage *nsvgImage;\n    RastOpts ropts;\n} NSVGcache;\n\nstatic const void *\tMemMem(const void *haystack, size_t haysize,\n\t\t\t       const void *needle, size_t needlen);\nstatic int\t\tFileMatchSVG(Tcl_Channel chan, const char *fileName,\n\t\t\t    Tcl_Obj *format, int *widthPtr, int *heightPtr,\n\t\t\t    Tcl_Interp *interp);\nstatic int\t\tFileReadSVG(Tcl_Interp *interp, Tcl_Channel chan,\n\t\t\t    const char *fileName, Tcl_Obj *format,\n\t\t\t    Tk_PhotoHandle imageHandle, int destX, int destY,\n\t\t\t    int width, int height, int srcX, int srcY);\nstatic int\t\tStringMatchSVG(Tcl_Obj *dataObj, Tcl_Obj *format,\n\t\t\t    int *widthPtr, int *heightPtr, Tcl_Interp *interp);\nstatic int\t\tStringReadSVG(Tcl_Interp *interp, Tcl_Obj *dataObj,\n\t\t\t    Tcl_Obj *format, Tk_PhotoHandle imageHandle,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY);\nstatic NSVGimage *\tParseSVGWithOptions(Tcl_Interp *interp,\n\t\t\t    const char *input, Tcl_Size length, Tcl_Obj *format,\n\t\t\t    RastOpts *ropts);\nstatic int\t\tRasterizeSVG(Tcl_Interp *interp,\n\t\t\t    Tk_PhotoHandle imageHandle, NSVGimage *nsvgImage,\n\t\t\t    int destX, int destY, int width, int height,\n\t\t\t    int srcX, int srcY, RastOpts *ropts);\nstatic double\t\tGetScaleFromParameters(NSVGimage *nsvgImage,\n\t\t\t    RastOpts *ropts, int *widthPtr, int *heightPtr);\nstatic NSVGcache *\tGetCachePtr(Tcl_Interp *interp);\nstatic int\t\tCacheSVG(Tcl_Interp *interp, void *dataOrChan,\n\t\t\t    Tcl_Obj *formatObj, NSVGimage *nsvgImage,\n\t\t\t    RastOpts *ropts);\nstatic NSVGimage *\tGetCachedSVG(Tcl_Interp *interp, void *dataOrChan,\n\t\t\t    Tcl_Obj *formatObj, RastOpts *ropts);\nstatic void\t\tCleanCache(Tcl_Interp *interp);\nstatic void\t\tFreeCache(void *clientData, Tcl_Interp *interp);\n\n/*\n * The format record for the SVG nano file format:\n */\n\nTk_PhotoImageFormat tkImgFmtSVGnano = {\n    \"svg\",\t\t\t/* name */\n    FileMatchSVG,\t\t/* fileMatchProc */\n    StringMatchSVG,\t\t/* stringMatchProc */\n    FileReadSVG,\t\t/* fileReadProc */\n    StringReadSVG,\t\t/* stringReadProc */\n    NULL,\t\t\t/* fileWriteProc */\n    NULL,\t\t\t/* stringWriteProc */\n    NULL\n};\n\n/*\n *----------------------------------------------------------------------\n *\n * MemMem --\n *\n *\tLike strstr() but operating on memory buffers with sizes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const void *\nMemMem(const void *haystack, size_t haylen,\n       const void *needle, size_t needlen)\n{\n    const void *hayend, *second, *p;\n    unsigned char first;\n\n    if ((needlen <= 0) || (haylen < needlen)) {\n\treturn NULL;\n    }\n    hayend = (const void *) ((char *) haystack + haylen - needlen);\n    first = ((char *) needle)[0];\n    second = (const void *) ((char *) needle + 1);\n    needlen -= 1;\n    while (haystack < hayend) {\n\tp = memchr(haystack, first, (char *) hayend - (char *) haystack);\n\tif (p == NULL) {\n\t    break;\n\t}\n\tif (needlen == 0) {\n\t    return p;\n\t}\n\thaystack = (const void *) ((char *) p + 1);\n\tif (memcmp(second, haystack, needlen) == 0) {\n\t    return p;\n\t}\n    }\n    return NULL;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * FileMatchSVG --\n *\n *\tThis function is invoked by the photo image type to see if a file\n *\tcontains image data in SVG format.\n *\n * Results:\n *\tThe return value is >0 if the file can be successfully parsed,\n *\tand 0 otherwise.\n *\n * Side effects:\n *\tThe file is saved in the internal cache for further use.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileMatchSVG(\n    Tcl_Channel chan,\n    TCL_UNUSED(const char *),\n    Tcl_Obj *formatObj,\n    int *widthPtr, int *heightPtr,\n    Tcl_Interp *interp)\n{\n    Tcl_Size length;\n    Tcl_Obj *dataObj = Tcl_NewObj();\n    const char *data;\n    RastOpts ropts;\n    NSVGimage *nsvgImage;\n\n    CleanCache(interp);\n    if (Tcl_ReadChars(chan, dataObj, 4096, 0) == TCL_IO_FAILURE) {\n\t/* in case of an error reading the file */\n\tTcl_DecrRefCount(dataObj);\n\treturn 0;\n    }\n    data = Tcl_GetStringFromObj(dataObj, &length);\n    /* should have a '<svg' and a '>' in the first 4k */\n    if ((memchr(data, '>', length) == NULL) ||\n\t(MemMem(data, length, \"<svg\", 4) == NULL)) {\n\tTcl_DecrRefCount(dataObj);\n\treturn 0;\n    }\n    if (!Tcl_Eof(chan) && (Tcl_ReadChars(chan, dataObj, TCL_INDEX_NONE, 1) == TCL_IO_FAILURE)) {\n\t/* in case of an error reading the file */\n\tTcl_DecrRefCount(dataObj);\n\treturn 0;\n    }\n    data = Tcl_GetStringFromObj(dataObj, &length);\n    nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts);\n    Tcl_DecrRefCount(dataObj);\n    if (nsvgImage != NULL) {\n\tGetScaleFromParameters(nsvgImage, &ropts, widthPtr, heightPtr);\n\tif ((*widthPtr <= 0.0) || (*heightPtr <= 0.0)) {\n\t    nsvgDelete(nsvgImage);\n\t    return 0;\n\t}\n\tif (!CacheSVG(interp, chan, formatObj, nsvgImage, &ropts)) {\n\t    nsvgDelete(nsvgImage);\n\t}\n\treturn 1;\n    }\n    return 0;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * FileReadSVG --\n *\n *\tThis function is called by the photo image type to read SVG format\n *\tdata from a file and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tThe access position in file f is changed, and new data is added to the\n *\timage given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFileReadSVG(\n    Tcl_Interp *interp,\n    Tcl_Channel chan,\n    TCL_UNUSED(const char *),\n    Tcl_Obj *formatObj,\n    Tk_PhotoHandle imageHandle,\n    int destX, int destY,\n    int width, int height,\n    int srcX, int srcY)\n{\n    Tcl_Size length;\n    const char *data;\n    RastOpts ropts;\n    NSVGimage *nsvgImage = GetCachedSVG(interp, chan, formatObj, &ropts);\n\n    if (nsvgImage == NULL) {\n\tTcl_Obj *dataObj = Tcl_NewObj();\n\n\tif (Tcl_ReadChars(chan, dataObj, TCL_INDEX_NONE, 0) == TCL_IO_FAILURE) {\n\t    /* in case of an error reading the file */\n\t    Tcl_DecrRefCount(dataObj);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"read error\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"READ_ERROR\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tdata = Tcl_GetStringFromObj(dataObj, &length);\n\tnsvgImage = ParseSVGWithOptions(interp, data, length, formatObj,\n\t\t\t    &ropts);\n\tTcl_DecrRefCount(dataObj);\n\tif (nsvgImage == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n    return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY,\n\t\twidth, height, srcX, srcY, &ropts);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * StringMatchSVG --\n *\n *\tThis function is invoked by the photo image type to see if a string\n *\tcontains image data in SVG format.\n *\n * Results:\n *\tThe return value is >0 if the file can be successfully parsed,\n *\tand 0 otherwise.\n *\n * Side effects:\n *\tThe file is saved in the internal cache for further use.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringMatchSVG(\n    Tcl_Obj *dataObj,\n    Tcl_Obj *formatObj,\n    int *widthPtr, int *heightPtr,\n    Tcl_Interp *interp)\n{\n    Tcl_Size length, testLength;\n    const char *data;\n    RastOpts ropts;\n    NSVGimage *nsvgImage;\n\n    CleanCache(interp);\n    data = Tcl_GetStringFromObj(dataObj, &length);\n    /* should have a '<svg' and a '>' in the first 4k */\n    testLength = (length > 4096) ? 4096 : length;\n    if ((memchr(data, '>', testLength) == NULL) ||\n\t(MemMem(data, testLength, \"<svg\", 4) == NULL)) {\n\treturn 0;\n    }\n    nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts);\n    if (nsvgImage != NULL) {\n\tGetScaleFromParameters(nsvgImage, &ropts, widthPtr, heightPtr);\n\tif ((*widthPtr <= 0.0) || (*heightPtr <= 0.0)) {\n\t    nsvgDelete(nsvgImage);\n\t    return 0;\n\t}\n\tif (!CacheSVG(interp, dataObj, formatObj, nsvgImage, &ropts)) {\n\t    nsvgDelete(nsvgImage);\n\t}\n\treturn 1;\n    }\n    return 0;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * StringReadSVG --\n *\n *\tThis function is called by the photo image type to read SVG format\n *\tdata from a string and write it into a given photo image.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNew data is added to the image given by imageHandle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nStringReadSVG(\n    Tcl_Interp *interp,\n    Tcl_Obj *dataObj,\n    Tcl_Obj *formatObj,\n    Tk_PhotoHandle imageHandle,\n    int destX, int destY,\n    int width, int height,\n    int srcX, int srcY)\n{\n    Tcl_Size length;\n    const char *data;\n    RastOpts ropts;\n    NSVGimage *nsvgImage = GetCachedSVG(interp, dataObj, formatObj, &ropts);\n\n    if (nsvgImage == NULL) {\n\tdata = Tcl_GetStringFromObj(dataObj, &length);\n\tnsvgImage = ParseSVGWithOptions(interp, data, length, formatObj,\n\t\t\t    &ropts);\n    }\n    if (nsvgImage == NULL) {\n\treturn TCL_ERROR;\n    }\n    return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY,\n\t\twidth, height, srcX, srcY, &ropts);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * ParseSVGWithOptions --\n *\n *\tThis function is called to parse the given input string as SVG.\n *\n * Results:\n *\tReturn a newly create NSVGimage on success, and NULL otherwise.\n *\n * Side effects:\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSVGimage *\nParseSVGWithOptions(\n    Tcl_Interp *interp,\n    const char *input,\n    Tcl_Size length,\n    Tcl_Obj *formatObj,\n    RastOpts *ropts)\n{\n    Tcl_Obj **objv = NULL;\n    Tcl_Size objc = 0;\n    double dpi = 96.0;\n    char *inputCopy = NULL;\n    NSVGimage *nsvgImage;\n    bool parameterScaleSeen = false;\n    static const char *const fmtOptions[] = {\n\t\"-dpi\", \"-scale\", \"-scaletoheight\", \"-scaletowidth\", NULL\n    };\n    enum fmtOptionsEnum {\n\tOPT_DPI, OPT_SCALE, OPT_SCALE_TO_HEIGHT, OPT_SCALE_TO_WIDTH\n    };\n\n    /*\n     * The parser destroys the original input string,\n     * therefore first duplicate.\n     */\n\n    inputCopy = (char *)Tcl_AttemptAlloc(length+1);\n    if (inputCopy == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"cannot alloc data buffer\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"OUT_OF_MEMORY\", (char *)NULL);\n\tgoto error;\n    }\n    memcpy(inputCopy, input, length);\n    inputCopy[length] = '\\0';\n\n    /*\n     * Process elements of format specification as a list.\n     */\n\n    ropts->scale = 1.0;\n    ropts->scaleToHeight = 0;\n    ropts->scaleToWidth = 0;\n    if ((formatObj != NULL) &&\n\t    Tcl_ListObjGetElements(interp, formatObj, &objc, &objv) != TCL_OK) {\n\tgoto error;\n    }\n    for (; objc > 0 ; objc--, objv++) {\n\tint optIndex;\n\n\t/*\n\t * Ignore the \"svg\" part of the format specification.\n\t */\n\n\tif (!strcasecmp(Tcl_GetString(objv[0]), \"svg\")) {\n\t    continue;\n\t}\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions,\n\t\tsizeof(char *), \"option\", 0, &optIndex) == TCL_ERROR) {\n\t    goto error;\n\t}\n\n\tif (objc < 2) {\n\t    Tcl_Free(inputCopy);\n\t    inputCopy = NULL;\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"value\");\n\t    goto error;\n\t}\n\n\tobjc--;\n\tobjv++;\n\n\t/*\n\t * check that only one scale option is given\n\t */\n\tswitch ((enum fmtOptionsEnum)optIndex) {\n\tcase OPT_SCALE:\n\tcase OPT_SCALE_TO_HEIGHT:\n\tcase OPT_SCALE_TO_WIDTH:\n\t    if ( parameterScaleSeen ) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"only one of -scale, -scaletoheight, -scaletowidth may be given\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"BAD_SCALE\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    parameterScaleSeen = true;\n\t    break;\n\tdefault:\n\t    break;\n\t}\n\n\t/*\n\t * Decode parameters\n\t */\n\tswitch ((enum fmtOptionsEnum) optIndex) {\n\tcase OPT_DPI:\n\t    if (Tcl_GetDoubleFromObj(interp, objv[0], &dpi) == TCL_ERROR) {\n\t\tgoto error;\n\t    }\n\t    if (dpi < 0.0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"-dpi value must be positive\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"BAD_DPI\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    break;\n\tcase OPT_SCALE:\n\t    if (Tcl_GetDoubleFromObj(interp, objv[0], &ropts->scale) ==\n\t\tTCL_ERROR) {\n\t\tgoto error;\n\t    }\n\t    if (ropts->scale <= 0.0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"-scale value must be positive\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"BAD_SCALE\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    break;\n\tcase OPT_SCALE_TO_HEIGHT:\n\t    if (Tcl_GetIntFromObj(interp, objv[0], &ropts->scaleToHeight) ==\n\t\tTCL_ERROR) {\n\t\tgoto error;\n\t    }\n\t    if (ropts->scaleToHeight <= 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"-scaletoheight value must be positive\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"BAD_SCALE\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    break;\n\tcase OPT_SCALE_TO_WIDTH:\n\t    if (Tcl_GetIntFromObj(interp, objv[0], &ropts->scaleToWidth) ==\n\t\tTCL_ERROR) {\n\t\tgoto error;\n\t    }\n\t    if (ropts->scaleToWidth <= 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"-scaletowidth value must be positive\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"BAD_SCALE\",\n\t\t\t(char *)NULL);\n\t\tgoto error;\n\t    }\n\t    break;\n\t}\n    }\n\n    nsvgImage = nsvgParse(inputCopy, \"px\", (float) dpi);\n    if (nsvgImage == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"cannot parse SVG image\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"PARSE_ERROR\", (char *)NULL);\n\tgoto error;\n    }\n    Tcl_Free(inputCopy);\n    return nsvgImage;\n\nerror:\n    if (inputCopy != NULL) {\n\tTcl_Free(inputCopy);\n    }\n    return NULL;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * RasterizeSVG --\n *\n *\tThis function is called to rasterize the given nsvgImage and\n *\tfill the imageHandle with data.\n *\n * Results:\n *\tA standard TCL completion code. If TCL_ERROR is returned then an error\n *\tmessage is left in the interp's result.\n *\n *\n * Side effects:\n *\tOn error the given nsvgImage will be deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nRasterizeSVG(\n    Tcl_Interp *interp,\n    Tk_PhotoHandle imageHandle,\n    NSVGimage *nsvgImage,\n    int destX, int destY,\n    int width, int height,\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    RastOpts *ropts)\n{\n    int w, h, c;\n    NSVGrasterizer *rast;\n    unsigned char *imgData;\n    Tk_PhotoImageBlock svgblock;\n    double scale;\n    Tcl_WideUInt wh;\n\n    scale = GetScaleFromParameters(nsvgImage, ropts, &w, &h);\n\n    rast = nsvgCreateRasterizer();\n    if (rast == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"cannot initialize rasterizer\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"RASTERIZER_ERROR\",\n\t\t(char *)NULL);\n\tgoto cleanAST;\n    }\n\n    /* Tk Ticket [822330269b] Check potential int overflow in following Tcl_Alloc */\n    wh = (Tcl_WideUInt)w * (Tcl_WideUInt)h;\n    if ( w < 0 || h < 0 || wh > INT_MAX / 4) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"image size overflow\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"IMAGE_SIZE_OVERFLOW\", (char *)NULL);\n\tgoto cleanRAST;\n    }\n\n    imgData = (unsigned char *)Tcl_AttemptAlloc(wh * 4);\n    if (imgData == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"cannot alloc image buffer\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SVG\", \"OUT_OF_MEMORY\", (char *)NULL);\n\tgoto cleanRAST;\n    }\n    nsvgRasterize(rast, nsvgImage, 0, 0,\n\t    (float) scale, imgData, w, h, w * 4);\n    /* transfer the data to a photo block */\n    svgblock.pixelPtr = imgData;\n    svgblock.width = w;\n    svgblock.height = h;\n    svgblock.pitch = w * 4;\n    svgblock.pixelSize = 4;\n    for (c = 0; c <= 3; c++) {\n\tsvgblock.offset[c] = c;\n    }\n    if (Tk_PhotoExpand(interp, imageHandle,\n\t\tdestX + width, destY + height) != TCL_OK) {\n\tgoto cleanRAST;\n    }\n    if (Tk_PhotoPutBlock(interp, imageHandle, &svgblock, destX, destY,\n\t\twidth, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {\n\tgoto cleanimg;\n    }\n    Tcl_Free(imgData);\n    nsvgDeleteRasterizer(rast);\n    nsvgDelete(nsvgImage);\n    return TCL_OK;\n\ncleanimg:\n    Tcl_Free(imgData);\n\ncleanRAST:\n    nsvgDeleteRasterizer(rast);\n\ncleanAST:\n    nsvgDelete(nsvgImage);\n    return TCL_ERROR;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetScaleFromParameters --\n *\n *\tGet the scale value from the already parsed parameters -scale,\n *\t-scaletoheight and -scaletowidth.\n *\n *\tThe image width and height is also returned.\n *\n * Results:\n *\tThe evaluated or configured scale value, or 0.0 on failure\n *\n * Side effects:\n *\theightPtr and widthPtr are set to height and width of the image.\n *\n *----------------------------------------------------------------------\n */\n\nstatic double\nGetScaleFromParameters(\n    NSVGimage *nsvgImage,\n    RastOpts *ropts,\n    int *widthPtr,\n    int *heightPtr)\n{\n    double scale;\n    int width, height;\n\n    if ((nsvgImage->width == 0.0) || (nsvgImage->height == 0.0)) {\n\twidth = height = 0;\n\tscale = 1.0;\n    } else if (ropts->scaleToHeight > 0) {\n\t/*\n\t * Fixed height\n\t */\n\theight = ropts->scaleToHeight;\n\tscale = height / nsvgImage->height;\n\twidth = (int) ceil(nsvgImage->width * scale);\n    } else if (ropts->scaleToWidth > 0) {\n\t/*\n\t * Fixed width\n\t */\n\twidth = ropts->scaleToWidth;\n\tscale = width / nsvgImage->width;\n\theight = (int) ceil(nsvgImage->height * scale);\n    } else {\n\t/*\n\t * Scale factor\n\t */\n\tscale = ropts->scale;\n\twidth = (int) ceil(nsvgImage->width * scale);\n\theight = (int) ceil(nsvgImage->height * scale);\n    }\n\n    *heightPtr = height;\n    *widthPtr = width;\n    return scale;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetCachePtr --\n *\n *\tThis function is called to get the per interpreter used\n *\tsvg image cache.\n *\n * Results:\n *\tReturn a pointer to the used cache.\n *\n * Side effects:\n *\tInitialize the cache on the first call.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSVGcache *\nGetCachePtr(\n    Tcl_Interp *interp\n) {\n    NSVGcache *cachePtr = (NSVGcache *)Tcl_GetAssocData(interp, \"tksvgnano\", NULL);\n    if (cachePtr == NULL) {\n\tcachePtr = (NSVGcache *)Tcl_Alloc(sizeof(NSVGcache));\n\tcachePtr->dataOrChan = NULL;\n\tTcl_DStringInit(&cachePtr->formatString);\n\tcachePtr->nsvgImage = NULL;\n\tTcl_SetAssocData(interp, \"tksvgnano\", FreeCache, cachePtr);\n    }\n    return cachePtr;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * CacheSVG --\n *\n *\tAdd the given svg image informations to the cache for further usage.\n *\n * Results:\n *\tReturn 1 on success, and 0 otherwise.\n *\n * Side effects:\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCacheSVG(\n    Tcl_Interp *interp,\n    void *dataOrChan,\n    Tcl_Obj *formatObj,\n    NSVGimage *nsvgImage,\n    RastOpts *ropts)\n{\n    Tcl_Size length;\n    const char *data;\n    NSVGcache *cachePtr = GetCachePtr(interp);\n\n    if (cachePtr != NULL) {\n\tcachePtr->dataOrChan = dataOrChan;\n\tif (formatObj != NULL) {\n\t    data = Tcl_GetStringFromObj(formatObj, &length);\n\t    Tcl_DStringAppend(&cachePtr->formatString, data, length);\n\t}\n\tcachePtr->nsvgImage = nsvgImage;\n\tcachePtr->ropts = *ropts;\n\treturn 1;\n    }\n    return 0;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetCachedSVG --\n *\n *\tTry to get the NSVGimage from the internal cache.\n *\n * Results:\n *\tReturn the found NSVGimage on success, and NULL otherwise.\n *\n * Side effects:\n *\tCalls the CleanCache() function.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSVGimage *\nGetCachedSVG(\n    Tcl_Interp *interp,\n    void *dataOrChan,\n    Tcl_Obj *formatObj,\n    RastOpts *ropts)\n{\n    Tcl_Size length;\n    const char *data;\n    NSVGcache *cachePtr = GetCachePtr(interp);\n    NSVGimage *nsvgImage = NULL;\n\n    if ((cachePtr != NULL) && (cachePtr->nsvgImage != NULL) &&\n\t(cachePtr->dataOrChan == dataOrChan)) {\n\tif (formatObj != NULL) {\n\t    data = Tcl_GetStringFromObj(formatObj, &length);\n\t    if (strcmp(data, Tcl_DStringValue(&cachePtr->formatString)) == 0) {\n\t\tnsvgImage = cachePtr->nsvgImage;\n\t\t*ropts = cachePtr->ropts;\n\t\tcachePtr->nsvgImage = NULL;\n\t    }\n\t} else if (Tcl_DStringLength(&cachePtr->formatString) == 0) {\n\t    nsvgImage = cachePtr->nsvgImage;\n\t    *ropts = cachePtr->ropts;\n\t    cachePtr->nsvgImage = NULL;\n\t}\n    }\n    CleanCache(interp);\n    return nsvgImage;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * CleanCache --\n *\n *\tReset the cache and delete the saved image in it.\n *\n * Results:\n *\n * Side effects:\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCleanCache(Tcl_Interp *interp)\n{\n    NSVGcache *cachePtr = GetCachePtr(interp);\n\n    if (cachePtr != NULL) {\n\tcachePtr->dataOrChan = NULL;\n\tTcl_DStringSetLength(&cachePtr->formatString, 0);\n\tif (cachePtr->nsvgImage != NULL) {\n\t    nsvgDelete(cachePtr->nsvgImage);\n\t    cachePtr->nsvgImage = NULL;\n\t}\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * FreeCache --\n *\n *\tThis function is called to clean up the internal cache data.\n *\n * Results:\n *\n * Side effects:\n *\tExisting image data in the cache and the cache will be deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeCache(void *clientData, TCL_UNUSED(Tcl_Interp *))\n{\n    NSVGcache *cachePtr = (NSVGcache *)clientData;\n\n    Tcl_DStringFree(&cachePtr->formatString);\n    if (cachePtr->nsvgImage != NULL) {\n\tnsvgDelete(cachePtr->nsvgImage);\n    }\n    Tcl_Free(cachePtr);\n}\n\n"
  },
  {
    "path": "generic/tkImgUtil.c",
    "content": "/*\n * tkImgUtil.c --\n *\n *\tThis file contains image related utility functions.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"xbytes.h\"\n#ifdef _WIN32\n#   include \"tkWinInt.h\"\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkAlignImageData --\n *\n *\tThis function takes an image and copies the data into an aligned\n *\tbuffer, performing any necessary bit swapping.\n *\n * Results:\n *\tReturns a newly allocated buffer that should be freed by the caller.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nchar *\nTkAlignImageData(\n    XImage *image,\t\t/* Image to be aligned. */\n    int alignment,\t\t/* Number of bytes to which the data should be\n\t\t\t\t * aligned (e.g. 2 or 4) */\n    int bitOrder)\t\t/* Desired bit order: LSBFirst or MSBFirst. */\n{\n    long dataWidth;\n    char *data, *srcPtr, *destPtr;\n    int i, j;\n\n    if (image->bits_per_pixel != 1) {\n\tTcl_Panic(\n\t\t\"TkAlignImageData: Can't handle image depths greater than 1.\");\n    }\n\n    /*\n     * Compute line width for output data buffer.\n     */\n\n    dataWidth = image->bytes_per_line;\n    if (dataWidth % alignment) {\n\tdataWidth += (alignment - (dataWidth % alignment));\n    }\n\n    data = (char *)Tcl_Alloc(dataWidth * image->height);\n\n    destPtr = data;\n    for (i = 0; i < image->height; i++) {\n\tsrcPtr = &image->data[i * image->bytes_per_line];\n\tfor (j = 0; j < dataWidth; j++) {\n\t    if (j >= image->bytes_per_line) {\n\t\t*destPtr = 0;\n\t    } else if (image->bitmap_bit_order != bitOrder) {\n\t\t*destPtr = xBitReverseTable[(unsigned char)(*(srcPtr++))];\n\t    } else {\n\t\t*destPtr = *(srcPtr++);\n\t    }\n\t    destPtr++;\n\t}\n    }\n    return data;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkInt.decls",
    "content": "# tkInt.decls --\n#\n#\tThis file contains the declarations for all unsupported functions that\n#\tare exported by the Tk library. This file is used to generate the\n#\ttkIntDecls.h, tkIntPlatDecls.h, tkIntStub.c, and tkPlatStub.c files.\n#\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nlibrary tk\n\f\n##############################################################################\n\n# Define the unsupported generic interfaces.\n\ninterface tkInt\nscspec EXTERN\n\n# Declare each of the functions in the unsupported internal Tcl interface.\n# These interfaces are allowed to changed between versions. Use at your own\n# risk. Note that the position of functions should not be changed between\n# versions to avoid gratuitous incompatibilities.\n\ndeclare 0 {\n    TkWindow *TkAllocWindow(TkDisplay *dispPtr, int screenNum,\n\t    TkWindow *parentPtr)\n}\ndeclare 1 {\n    void TkBezierPoints(double *control, int numSteps, double *coordPtr)\n}\ndeclare 2 {\n    void TkBezierScreenPoints(Tk_Canvas canvas, double *control,\n\t    int numSteps, XPoint *xPointPtr)\n}\n#\n# Slot 3 unused (WAS: TkBindDeadWindow)\n#\ndeclare 4 {\n    void TkBindEventProc(TkWindow *winPtr, XEvent *eventPtr)\n}\ndeclare 5 {\n    void TkBindFree(TkMainInfo *mainPtr)\n}\ndeclare 6 {\n    void TkBindInit(TkMainInfo *mainPtr)\n}\ndeclare 7 {\n    void TkChangeEventWindow(XEvent *eventPtr, TkWindow *winPtr)\n}\ndeclare 8 {\n    int TkClipInit(Tcl_Interp *interp, TkDisplay *dispPtr)\n}\ndeclare 9 {\n    void TkComputeAnchor(Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY,\n\t    int innerWidth, int innerHeight, int *xPtr, int *yPtr)\n}\n#\n# Slot 10 unused (WAS: TkCopyAndGlobalEval)\n# Slot 11 unused (WAS: TkCreateBindingProcedure)\n#\ndeclare 12 {\n    TkCursor *TkCreateCursorFromData(Tk_Window tkwin,\n\t    const char *source, const char *mask, int width, int height,\n\t    int xHot, int yHot, XColor fg, XColor bg)\n}\ndeclare 13 {\n    int TkCreateFrame(void *clientData, Tcl_Interp *interp,\n\t    Tcl_Size objc, Tcl_Obj *const *objv, int type, const char *appName)\n}\ndeclare 14 {\n    Tk_Window TkCreateMainWindow(Tcl_Interp *interp,\n\t    const char *screenName, const char *baseName)\n}\ndeclare 15 {\n    Time TkCurrentTime(TkDisplay *dispPtr)\n}\ndeclare 16 {\n    void TkDeleteAllImages(TkMainInfo *mainPtr)\n}\ndeclare 17 {\n    void TkDoConfigureNotify(TkWindow *winPtr)\n}\ndeclare 18 {\n    void TkDrawInsetFocusHighlight(Tk_Window tkwin, GC gc, int width,\n\t    Drawable drawable, int padding)\n}\ndeclare 19 {\n    void TkEventDeadWindow(TkWindow *winPtr)\n}\ndeclare 20 {\n    void TkFillPolygon(Tk_Canvas canvas, double *coordPtr, Tcl_Size numPoints,\n\t    Display *display, Drawable drawable, GC gc, GC outlineGC)\n}\ndeclare 21 {\n    int TkFindStateNum(Tcl_Interp *interp, const char *option,\n\t    const TkStateMap *mapPtr, const char *strKey)\n}\ndeclare 22 {\n    const char *TkFindStateString(const TkStateMap *mapPtr, int numKey)\n}\ndeclare 23 {\n    void TkFocusDeadWindow(TkWindow *winPtr)\n}\ndeclare 24 {\n    bool TkFocusFilterEvent(TkWindow *winPtr, XEvent *eventPtr)\n}\ndeclare 25 {\n    TkWindow *TkFocusKeyEvent(TkWindow *winPtr, XEvent *eventPtr)\n}\ndeclare 26 {\n    void TkFontPkgInit(TkMainInfo *mainPtr)\n}\ndeclare 27 {\n    void TkFontPkgFree(TkMainInfo *mainPtr)\n}\ndeclare 28 {\n    void TkFreeBindingTags(TkWindow *winPtr)\n}\n\n# Name change only, TkFreeCursor in Tcl 8.0.x now TkpFreeCursor\ndeclare 29 {\n    void TkpFreeCursor(TkCursor *cursorPtr)\n}\ndeclare 30 {\n    char *TkGetBitmapData(Tcl_Interp *interp, const char *string,\n\t    const char *fileName, int *widthPtr, int *heightPtr,\n\t    int *hotXPtr, int *hotYPtr)\n}\ndeclare 31 {\n    void TkGetButtPoints(double *p1, double *p2,\n\t    double width, int project, double *m1, double *m2)\n}\ndeclare 32 {\n    TkCursor *TkGetCursorByName(Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *string)\n}\ndeclare 33 {\n    const char *TkGetDefaultScreenName(Tcl_Interp *interp,\n\t    const char *screenName)\n}\ndeclare 34 {\n    TkDisplay *TkGetDisplay(Display *display)\n}\ndeclare 35 {\n    Tcl_Size TkGetDisplayOf(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv,\n\t    Tk_Window *tkwinPtr)\n}\ndeclare 36 {\n    TkWindow *TkGetFocusWin(TkWindow *winPtr)\n}\ndeclare 37 {\n    int TkGetInterpNames(Tcl_Interp *interp, Tk_Window tkwin)\n}\ndeclare 38 {\n    bool TkGetMiterPoints(double *p1, double *p2, double *p3,\n\t    double width, double *m1, double *m2)\n}\ndeclare 39 {\n    void TkGetPointerCoords(Tk_Window tkwin, int *xPtr, int *yPtr)\n}\ndeclare 40 {\n    void TkGetServerInfo(Tcl_Interp *interp, Tk_Window tkwin)\n}\ndeclare 41 {\n    void TkGrabDeadWindow(TkWindow *winPtr)\n}\ndeclare 42 {\n    int TkGrabState(TkWindow *winPtr)\n}\ndeclare 43 {\n    void TkIncludePoint(Tk_Item *itemPtr, double *pointPtr)\n}\ndeclare 44 {\n    void TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr,\n\t    TkWindow *destPtr, int leaveType, int enterType,\n\t    Tcl_QueuePosition position)\n}\ndeclare 45 {\n    void TkInstallFrameMenu(Tk_Window tkwin)\n}\ndeclare 46 {\n    const char *TkKeysymToString(KeySym keysym)\n}\ndeclare 47 {\n    int TkLineToArea(double *end1Ptr, double *end2Ptr, double *rectPtr)\n}\ndeclare 48 {\n    double TkLineToPoint(double *end1Ptr, double *end2Ptr, double *pointPtr)\n}\ndeclare 49 {\n    int TkMakeBezierCurve(Tk_Canvas canvas, double *pointPtr, int numPoints,\n\t    int numSteps, XPoint *xPoints, double *dblPoints)\n}\ndeclare 50 {\n    void TkMakeBezierPostscript(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, double *pointPtr, int numPoints)\n}\ndeclare 51 {\n    void TkOptionClassChanged(TkWindow *winPtr)\n}\ndeclare 52 {\n    void TkOptionDeadWindow(TkWindow *winPtr)\n}\ndeclare 53 {\n    int TkOvalToArea(double *ovalPtr, double *rectPtr)\n}\ndeclare 54 {\n    double TkOvalToPoint(double *ovalPtr,\n\t    double width, int filled, double *pointPtr)\n}\ndeclare 55 {\n    size_t TkpChangeFocus(TkWindow *winPtr, int force)\n}\ndeclare 56 {\n    void TkpCloseDisplay(TkDisplay *dispPtr)\n}\ndeclare 57 {\n    void TkpClaimFocus(TkWindow *topLevelPtr, int force)\n}\ndeclare 58 {\n    void TkpDisplayWarning(const char *msg, const char *title)\n}\ndeclare 59 {\n    void TkpGetAppName(Tcl_Interp *interp, Tcl_DString *name)\n}\ndeclare 61 {\n    TkWindow *TkpGetWrapperWindow(TkWindow *winPtr)\n}\ndeclare 62 {\n    int TkpInit(Tcl_Interp *interp)\n}\ndeclare 63 {\n    void TkpInitializeMenuBindings(Tcl_Interp *interp,\n\t    Tk_BindingTable bindingTable)\n}\ndeclare 65 {\n    void TkpMakeMenuWindow(Tk_Window tkwin, int transient)\n}\ndeclare 67 {\n    void TkpMenuNotifyToplevelCreate(Tcl_Interp *interp, const char *menuName)\n}\ndeclare 68 {\n    TkDisplay *TkpOpenDisplay(const char *display_name)\n}\ndeclare 69 {\n    bool TkPointerEvent(XEvent *eventPtr, TkWindow *winPtr)\n}\ndeclare 70 {\n    int TkPolygonToArea(double *polyPtr, Tcl_Size numPoints, double *rectPtr)\n}\ndeclare 71 {\n    double TkPolygonToPoint(double *polyPtr, Tcl_Size numPoints, double *pointPtr)\n}\ndeclare 72 {\n    int TkPositionInTree(TkWindow *winPtr, TkWindow *treePtr)\n}\ndeclare 73 {\n    void TkpRedirectKeyEvent(TkWindow *winPtr, XEvent *eventPtr)\n}\ndeclare 77 {\n    void TkQueueEventForAllChildren(TkWindow *winPtr, XEvent *eventPtr)\n}\ndeclare 78 {\n    int TkReadBitmapFile(Display *display, Drawable d, const char *filename,\n\t    unsigned int *width_return, unsigned int *height_return,\n\t    Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return)\n}\ndeclare 79 {\n    bool TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,\n\t    int width, int height, int dx, int dy, Region damageRgn)\n}\ndeclare 80 {\n    void TkSelDeadWindow(TkWindow *winPtr)\n}\ndeclare 81 {\n    void TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr)\n}\ndeclare 82 {\n    void TkSelInit(Tk_Window tkwin)\n}\ndeclare 83 {\n    void TkSelPropProc(XEvent *eventPtr)\n}\ndeclare 86 {\n    KeySym TkStringToKeysym(const char *name)\n}\ndeclare 87 {\n    int TkThickPolyLineToArea(double *coordPtr, Tcl_Size numPoints,\n\t    double width, int capStyle, int joinStyle, double *rectPtr)\n}\ndeclare 88 {\n    void TkWmAddToColormapWindows(TkWindow *winPtr)\n}\ndeclare 89 {\n    void TkWmDeadWindow(TkWindow *winPtr)\n}\ndeclare 90 {\n    TkWindow *TkWmFocusToplevel(TkWindow *winPtr)\n}\ndeclare 91 {\n    void TkWmMapWindow(TkWindow *winPtr)\n}\ndeclare 92 {\n    void TkWmNewWindow(TkWindow *winPtr)\n}\ndeclare 93 {\n    void TkWmProtocolEventProc(TkWindow *winPtr, XEvent *evenvPtr)\n}\ndeclare 94 {\n    void TkWmRemoveFromColormapWindows(TkWindow *winPtr)\n}\ndeclare 95 {\n    void TkWmRestackToplevel(TkWindow *winPtr, int aboveBelow,\n\t    TkWindow *otherPtr)\n}\ndeclare 96 {\n    void TkWmSetClass(TkWindow *winPtr)\n}\ndeclare 97 {\n    void TkWmUnmapWindow(TkWindow *winPtr)\n}\n\n# new for 8.1\n\ndeclare 98 {\n    Tcl_Obj *TkDebugBitmap(Tk_Window tkwin, const char *name)\n}\ndeclare 99 {\n    Tcl_Obj *TkDebugBorder(Tk_Window tkwin, const char *name)\n}\ndeclare 100 {\n    Tcl_Obj *TkDebugCursor(Tk_Window tkwin, const char *name)\n}\ndeclare 101 {\n    Tcl_Obj *TkDebugColor(Tk_Window tkwin, const char *name)\n}\ndeclare 102 {\n    Tcl_Obj *TkDebugConfig(Tcl_Interp *interp, Tk_OptionTable table)\n}\ndeclare 103 {\n    Tcl_Obj *TkDebugFont(Tk_Window tkwin, const char *name)\n}\ndeclare 104 {\n    int TkFindStateNumObj(Tcl_Interp *interp, Tcl_Obj *optionPtr,\n\t    const TkStateMap *mapPtr, Tcl_Obj *keyPtr)\n}\ndeclare 105 {\n    Tcl_HashTable *TkGetBitmapPredefTable(void)\n}\ndeclare 106 {\n    TkDisplay *TkGetDisplayList(void)\n}\ndeclare 107 {\n    TkMainInfo *TkGetMainInfoList(void)\n}\ndeclare 108 {\n    int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Tcl_Obj *objPtr, Tk_Window *windowPtr)\n}\ndeclare 109 {\n    const char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr)\n}\ndeclare 110 {\n    void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont)\n}\ndeclare 112 {\n    void TkpMenuThreadInit(void)\n}\ndeclare 113 {\n    int XClipBox(Region rgn, XRectangle *rect_return)\n}\ndeclare 114 {\n    Region XCreateRegion(void)\n}\ndeclare 115 {\n    int XDestroyRegion(Region rgn)\n}\ndeclare 116 {\n    int XIntersectRegion(Region sra, Region srcb, Region dr_return)\n}\ndeclare 117 {\n    int XRectInRegion(Region rgn, int x, int y, unsigned int width,\n\t    unsigned int height)\n}\ndeclare 118 {\n    int XSetRegion(Display *display, GC gc, Region rgn)\n}\ndeclare 119 {\n    int XUnionRectWithRegion(XRectangle *rect,\n\t    Region src, Region dr_return)\n}\ndeclare 121 {\n    Pixmap TkpCreateNativeBitmap(Display *display, const void *source)\n}\ndeclare 122 {\n    void TkpDefineNativeBitmaps(void)\n}\ndeclare 124 {\n    Pixmap TkpGetNativeAppBitmap(Display *display,\n\t    const char *name, int *width, int *height)\n}\ndeclare 136 {\n    void TkSetFocusWin(TkWindow *winPtr, int force)\n}\ndeclare 137 {\n    void TkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym,\n\t    XEvent *eventPtr)\n}\ndeclare 138 {\n    KeySym TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr)\n}\ndeclare 139 {\n    void TkpInitKeymapInfo(TkDisplay *dispPtr)\n}\ndeclare 140 {\n    Region TkPhotoGetValidRegion(Tk_PhotoHandle handle)\n}\ndeclare 141 {\n    TkWindow **TkWmStackorderToplevel(TkWindow *parentPtr)\n}\ndeclare 142 {\n    void TkFocusFree(TkMainInfo *mainPtr)\n}\ndeclare 143 {\n    void TkClipCleanup(TkDisplay *dispPtr)\n}\ndeclare 144 {\n    void TkGCCleanup(TkDisplay *dispPtr)\n}\ndeclare 145 {\n    int XSubtractRegion(Region sra, Region srcb, Region dr_return)\n}\ndeclare 146 {\n    void TkStylePkgInit(TkMainInfo *mainPtr)\n}\ndeclare 147 {\n    void TkStylePkgFree(TkMainInfo *mainPtr)\n}\ndeclare 148 {\n    Tk_Window TkToplevelWindowForCommand(Tcl_Interp *interp,\n\t    const char *cmdName)\n}\ndeclare 149 {\n    const Tk_OptionSpec *TkGetOptionSpec(const char *name,\n\t    Tk_OptionTable optionTable)\n}\n\n# TIP#168\ndeclare 150 {\n    int TkMakeRawCurve(Tk_Canvas canvas, double *pointPtr, int numPoints,\n\t    int numSteps, XPoint *xPoints, double *dblPoints)\n}\ndeclare 151 {\n    void TkMakeRawCurvePostscript(Tcl_Interp *interp,\n\t    Tk_Canvas canvas, double *pointPtr, int numPoints)\n}\ndeclare 152 {\n    void TkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border,\n\t    int highlightWidth, int borderWidth, int relief)\n}\ndeclare 153 {\n    void TkCreateThreadExitHandler(Tcl_ExitProc *proc, void *clientData)\n}\ndeclare 154 {\n    void TkDeleteThreadExitHandler(Tcl_ExitProc *proc, void *clientData)\n}\n\n# entries needed only by tktest:\ndeclare 156 {\n    int TkpTestembedCmd(void *clientData, Tcl_Interp *interp, Tcl_Size objc,\n\t    Tcl_Obj *const *objv)\n}\ndeclare 157 {\n    int TkpTesttextCmd(void *dummy, Tcl_Interp *interp, Tcl_Size objc,\n\t    Tcl_Obj *const *objv)\n}\ndeclare 158 {\n    int TkSelGetSelection(Tcl_Interp *interp, Tk_Window tkwin,\n\t    Atom selection, Atom target, Tk_GetSelProc *proc,\n\t    void *clientData)\n}\ndeclare 159 {\n    int TkTextGetIndex(Tcl_Interp *interp, struct TkText *textPtr,\n\t    const char *string, struct TkTextIndex *indexPtr)\n}\ndeclare 160 {\n    bool TkTextIndexBackBytes(const struct TkText *textPtr,\n\t    const struct TkTextIndex *srcPtr, Tcl_Size count,\n\t    struct TkTextIndex *dstPtr)\n}\ndeclare 161 {\n    bool TkTextIndexForwBytes(const struct TkText *textPtr,\n\t    const struct TkTextIndex *srcPtr, Tcl_Size count,\n\t    struct TkTextIndex *dstPtr)\n}\ndeclare 162 {\n    struct TkTextIndex *TkTextMakeByteIndex(TkTextBTree tree,\n\t    const struct TkText *textPtr, Tcl_Size lineIndex,\n\t    Tcl_Size byteIndex, struct TkTextIndex *indexPtr)\n}\ndeclare 163 {\n    Tcl_Size TkTextPrintIndex(const struct TkText *textPtr,\n\t    const struct TkTextIndex *indexPtr, char *string)\n}\ndeclare 164 {\n    struct TkTextSegment *TkTextSetMark(struct TkText *textPtr,\n\t    const char *name, struct TkTextIndex *indexPtr)\n}\ndeclare 165 {\n    int TkTextXviewCmd(struct TkText *textPtr, Tcl_Interp *interp,\n\t    Tcl_Size objc, Tcl_Obj *const *objv)\n}\ndeclare 166 {\n    void TkTextChanged(struct TkSharedText *sharedTextPtr,\n\t    struct TkText *textPtr, const struct TkTextIndex *index1Ptr,\n\t    const struct TkTextIndex *index2Ptr)\n}\ndeclare 167 {\n    Tcl_Size TkBTreeNumLines(TkTextBTree tree,\n\t    const struct TkText *textPtr)\n}\ndeclare 168 {\n    void TkTextInsertDisplayProc(struct TkText *textPtr,\n\t    struct TkTextDispChunk *chunkPtr, int x, int y,\n\t    int height, int baseline, Display *display,\n\t    Drawable dst, int screenY)\n}\n# Next group of functions exposed due to [Bug 2768945].\ndeclare 169 {\n    int TkStateParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 170 {\n    const char *TkStatePrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 171 {\n    int TkCanvasDashParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 172 {\n    const char *TkCanvasDashPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 173 {\n    int TkOffsetParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 174 {\n    const char *TkOffsetPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 175 {\n    int TkPixelParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 176 {\n    const char *TkPixelPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 177 {\n    int TkOrientParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 178 {\n    const char *TkOrientPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\ndeclare 179 {\n    int TkSmoothParseProc(void *clientData, Tcl_Interp *interp,\n\t    Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset)\n}\ndeclare 180 {\n    const char *TkSmoothPrintProc(void *clientData, Tk_Window tkwin,\n\t    char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr)\n}\n\n# Angled text API, exposed for Emiliano Gavilán's RBC work.\ndeclare 181 {\n    void TkDrawAngledTextLayout(Display *display, Drawable drawable, GC gc,\n\t    Tk_TextLayout layout, int x, int y, double angle, Tcl_Size firstChar,\n\t    Tcl_Size lastChar)\n}\ndeclare 182 {\n    void TkUnderlineAngledTextLayout(Display *display, Drawable drawable,\n\t    GC gc, Tk_TextLayout layout, int x, int y, double angle,\n\t    int underline)\n}\ndeclare 183 {\n    int TkIntersectAngledTextLayout(Tk_TextLayout layout, int x, int y,\n\t    int width, int height, double angle)\n}\ndeclare 184 {\n    void TkDrawAngledChars(Display *display,Drawable drawable, GC gc,\n\t    Tk_Font tkfont, const char *source, Tcl_Size numBytes, double x,\n\t    double y, double angle)\n}\n\n# Debugging / testing functions for photo images\ndeclare 187 {\n    bool TkDebugPhotoStringMatchDef(Tcl_Interp *inter, Tcl_Obj *data,\n\t    Tcl_Obj *formatString, int *widthPtr, int *heightPtr)\n}\n\n\f\n##############################################################################\n\n# Define the platform specific internal Tcl interface. These functions are\n# only available on the designated platform.\n\ninterface tkIntPlat\n\n################################\n# Unix specific functions\n\ndeclare 0 x11 {\n    void TkCreateXEventSource(void)\n}\ndeclare 1 x11 {\n    void TkAboutDlg(void)\n}\ndeclare 2 x11 {\n    void TkGenerateActivateEvents(TkWindow *winPtr, int active)\n}\ndeclare 6 x11 {\n    int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)\n}\ndeclare 9 x11 {\n    bool TkpWmSetState(TkWindow *winPtr, int state)\n}\ndeclare 38 x11 {\n    bool TkpCmapStressed(Tk_Window tkwin, Colormap colormap)\n}\ndeclare 39 x11 {\n    void TkpSync(Display *display)\n}\ndeclare 40 x11 {\n    Window TkUnixContainerId(TkWindow *winPtr)\n}\ndeclare 41 x11 {\n    bool TkUnixDoOneXEvent(Tcl_Time *timePtr)\n}\ndeclare 42 x11 {\n    void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar)\n}\ndeclare 43 x11 {\n    void TkWmCleanup(TkDisplay *dispPtr)\n}\ndeclare 44 x11 {\n    void TkSendCleanup(TkDisplay *dispPtr)\n}\n# only needed by tktest:\ndeclare 45 x11 {\n    int TkpTestsendCmd(void *clientData, Tcl_Interp *interp, Tcl_Size objc,\n\t    Tcl_Obj *const *objv)\n}\n\n################################\n# Windows specific functions\n\ndeclare 0 win {\n    void TkCreateXEventSource(void)\n}\ndeclare 1 win {\n    void TkAboutDlg(void)\n}\ndeclare 2 win {\n    void TkGenerateActivateEvents(TkWindow *winPtr, int active)\n}\ndeclare 3 win {\n    unsigned long TkpGetMS(void)\n}\ndeclare 4 win {\n    void TkPointerDeadWindow(TkWindow *winPtr)\n}\ndeclare 5 win {\n    void TkpPrintWindowId(char *buf, Window window)\n}\ndeclare 6 win {\n    int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)\n}\ndeclare 7 win {\n    void TkpSetCapture(TkWindow *winPtr)\n}\ndeclare 8 win {\n    void TkpSetCursor(Cursor cursor)\n}\ndeclare 9 win {\n    bool TkpWmSetState(TkWindow *winPtr, int state)\n}\ndeclare 10 win {\n    void TkSetPixmapColormap(Pixmap pixmap, Colormap colormap)\n}\n# removed in Tk 9.1\n#declare 11 win {\n#   void TkWinCancelMouseTimer(void)\n#}\ndeclare 12 win {\n    void TkWinClipboardRender(TkDisplay *dispPtr, UINT format)\n}\n# removed in Tk 9.1\n#declare 13 win {\n#   LRESULT TkWinEmbeddedEventProc(HWND hwnd, UINT message,\n#\t    WPARAM wParam, LPARAM lParam)\n#}\ndeclare 14 win {\n    void TkWinFillRect(HDC dc, int x, int y, int width, int height, int pixel)\n}\ndeclare 15 win {\n    COLORREF TkWinGetBorderPixels(Tk_Window tkwin, Tk_3DBorder border,\n\t    int which)\n}\ndeclare 16 win {\n    HDC TkWinGetDrawableDC(Display *display, Drawable d, TkWinDCState *state)\n}\n# removed in Tk 9.1\n#declare 17 win {\n#   unsigned int TkWinGetModifierState(void)\n#}\n# removed in Tk 9.1\n#declare 18 win {\n#   HPALETTE TkWinGetSystemPalette(void)\n#}\n# removed in Tk 9.1\n#declare 19 win {\n#   HWND TkWinGetWrapperWindow(Tk_Window tkwin)\n#}\n# removed in Tk 9.1\n#declare 20 win {\n#   int TkWinHandleMenuEvent(HWND *phwnd, UINT *pMessage, WPARAM *pwParam,\n#\t    LPARAM *plParam, LRESULT *plResult)\n#}\n# removed in Tk 9.1\n#declare 21 win {\n#   int TkWinIndexOfColor(XColor *colorPtr)\n#}\ndeclare 22 win {\n    void TkWinReleaseDrawableDC(Drawable d, HDC hdc, TkWinDCState *state)\n}\ndeclare 23 win {\n    LRESULT TkWinResendEvent(WNDPROC wndproc, HWND hwnd, XEvent *eventPtr)\n}\n# removed in Tk 9.1\n#declare 24 win {\n#   HPALETTE TkWinSelectPalette(HDC dc, Colormap colormap)\n#}\n# removed in Tk 9.1\n#declare 25 win {\n#   void TkWinSetMenu(Tk_Window tkwin, HMENU hMenu)\n#}\ndeclare 26 win {\n    void TkWinSetWindowPos(HWND hwnd, HWND siblingHwnd, int pos)\n}\ndeclare 27 win {\n    void TkWinWmCleanup(HINSTANCE hInstance)\n}\ndeclare 28 win {\n    void TkWinXCleanup(void *clientData)\n}\ndeclare 29 win {\n    void TkWinXInit(HINSTANCE hInstance)\n}\n\n# new for 8.1\n\ndeclare 30 win {\n    void TkWinSetForegroundWindow(TkWindow *winPtr)\n}\ndeclare 31 win {\n    void TkWinDialogDebug(int debug)\n}\n# removed in Tk 9.1\n#declare 32 win {\n#   Tcl_Obj *TkWinGetMenuSystemDefault(Tk_Window tkwin,\n#\t    const char *dbName, const char *className)\n#}\ndeclare 33 win {\n    char *TkAlignImageData(XImage *image, int alignment, int bitOrder)\n}\n\n# new for 8.4.1\n\ndeclare 34 win {\n    void TkWinSetHINSTANCE(HINSTANCE hInstance)\n}\n\n# removed in Tk 9.1\n#declare 35 win {\n#   int TkWinGetPlatformTheme(void)\n#}\n\n# Exported through stub table since Tk 8.4.20/8.5.9\n\ndeclare 36 win {\n    LRESULT __stdcall TkWinChildProc(HWND hwnd,\n\t    UINT message, WPARAM wParam, LPARAM lParam)\n}\n\ndeclare 38 win {\n    bool TkpCmapStressed(Tk_Window tkwin, Colormap colormap)\n}\ndeclare 39 win {\n    void TkpSync(Display *display)\n}\ndeclare 40 win {\n    Window TkUnixContainerId(TkWindow *winPtr)\n}\ndeclare 41 win {\n    bool TkUnixDoOneXEvent(Tcl_Time *timePtr)\n}\ndeclare 42 win {\n    void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar)\n}\ndeclare 43 win {\n    void TkWmCleanup(TkDisplay *dispPtr)\n}\ndeclare 44 win {\n    void TkSendCleanup(TkDisplay *dispPtr)\n}\n# only needed by tktest:\ndeclare 45 win {\n    int TkpTestsendCmd(void *clientData, Tcl_Interp *interp, Tcl_Size objc,\n\t    Tcl_Obj *const *objv)\n}\ndeclare 47 win {\n    Tk_Window TkpGetCapture(void)\n}\n\n################################\n# Aqua specific functions\n\ndeclare 1 aqua {\n    void TkAboutDlg(void)\n}\ndeclare 2 aqua {\n    void TkGenerateActivateEvents(TkWindow *winPtr, int active)\n}\ndeclare 3 aqua {\n    unsigned long TkpGetMS(void)\n}\ndeclare 4 aqua {\n    void TkPointerDeadWindow(TkWindow *winPtr)\n}\ndeclare 6 aqua {\n    int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)\n}\ndeclare 8 aqua {\n    void TkpSetCursor(Cursor cursor)\n}\n# removed in Tk 9.1\n#declare 8 aqua {\n#   unsigned int TkMacOSXButtonKeyState(void)\n#}\ndeclare 9 aqua {\n    bool TkpWmSetState(TkWindow *winPtr, int state)\n}\n# removed in Tk 9.1\n#declare 10 aqua {\n#   void TkMacOSXClearMenubarActive(void)\n#}\ndeclare 11 aqua {\n    void TkpSetCapture(TkWindow *winPtr)\n}\ndeclare 14 aqua {\n    int TkMacOSXDoHLEvent(void *theEvent)\n}\ndeclare 16 aqua {\n    Window TkMacOSXGetXWindow(void *macWinPtr)\n}\n# removed in Tk 9.1\n#declare 17 aqua {\n#   int TkMacOSXGrowToplevel(void *whichWindow, XPoint start)\n#}\n# removed in Tk 9.1\n#declare 21 aqua {\n#   void TkMacOSXInvalidateWindow(MacDrawable *macWin, int flag)\n#}\n# removed in Tk 9.1\n#declare 23 aqua {\n#   void TkMacOSXMakeRealWindowExist(TkWindow *winPtr)\n#}\n# removed in Tk 9.1\n#declare 24 aqua {\n#   void *TkMacOSXMakeStippleMap(Drawable d1, Drawable d2)\n#}\n# removed in Tk 9.1\n#declare 27 aqua {\n#    int TkMacOSXResizable(TkWindow *winPtr)\n#}\n# removed in Tk 9.1\n#declare 29 aqua {\n#    void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag)\n#}\ndeclare 32 aqua {\n    void TkMacOSXUpdateClipRgn(TkWindow *winPtr)\n}\ndeclare 35 aqua {\n    Region TkMacOSXVisableClipRgn(TkWindow *winPtr)\n}\ndeclare 36 aqua {\n    void TkMacOSXWinBounds(TkWindow *winPtr, void *geometry)\n}\ndeclare 37 aqua {\n    void TkMacOSXWindowOffset(void *wRef, int *xOffset, int *yOffset)\n}\ndeclare 38 aqua {\n    bool TkSetMacColor(unsigned long pixel, void *macColor)\n}\ndeclare 39 aqua {\n    void TkSetWMName(TkWindow *winPtr, const char *title)\n}\ndeclare 41 aqua {\n    bool TkMacOSXZoomToplevel(void *whichWindow, short zoomPart)\n}\ndeclare 42 aqua {\n    Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, int rootX, int rootY,\n\t    int *newX, int *newY)\n}\ndeclare 43 aqua {\n    MacDrawable *TkMacOSXContainerId(TkWindow *winPtr)\n}\ndeclare 44 aqua {\n    MacDrawable *TkMacOSXGetHostToplevel(TkWindow *winPtr)\n}\n# removed in Tk 9.1\n#declare 46 aqua {\n#   int TkpIsWindowFloating(void *window)\n#}\ndeclare 47 aqua {\n    Tk_Window TkpGetCapture(void)\n}\ndeclare 49 aqua {\n    Tk_Window TkMacOSXGetContainer(TkWindow *winPtr)\n}\n# removed in Tk 9.1\n#declare 50 aqua {\n#   int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)\n#}\n# removed in Tk 9.1\n#declare 51 aqua {\n#   void TkGenWMDestroyEvent(Tk_Window tkwin)\n#}\n#\n# Slot 52 unused (WAS: TkMacOSXSetDrawingEnabled)\n#\n# Made public as Tk_MacOSXGetNSWindowForDrawable\n#declare 54 aqua {\n#   void *TkMacOSXDrawable(Drawable drawable)\n#}\n\f\n##############################################################################\n\n# Define the platform specific internal Xlib interfaces.\n\ninterface tkIntXlib\n\n################################\n# X functions for Windows/MacOS/Wayland\n\ndeclare 0 {\n    int XSetDashes(Display *display, GC gc, int dash_offset,\n\t    const char *dash_list, int n)\n}\ndeclare 1 {\n    XModifierKeymap *XGetModifierMapping(Display *d)\n}\ndeclare 2 {\n    XImage *XCreateImage(Display *d, Visual *v, unsigned int ui1, int i1,\n\t    int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3,\n\t    int i4)\n}\ndeclare 3 {\n    XImage *XGetImage(Display *d, Drawable dr, int i1, int i2,\n\t    unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)\n}\ndeclare 4 {\n    char *XGetAtomName(Display *d, Atom a)\n}\ndeclare 5 {\n    char *XKeysymToString(KeySym k)\n}\ndeclare 6 {\n    Colormap XCreateColormap(Display *d, Window w, Visual *v, int i)\n}\ndeclare 7 {\n    Cursor XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,\n\t    XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2)\n}\ndeclare 8 {\n    Cursor XCreateGlyphCursor(Display *d, Font f1, Font f2,\n\t    unsigned int ui1, unsigned int ui2, XColor const *x1,\n\t    XColor const *x2)\n}\ndeclare 9 {\n    GContext XGContextFromGC(GC g)\n}\ndeclare 10 {\n    XHostAddress *XListHosts(Display *d, int *i, Bool *b)\n}\n# Removed in 9.1, because it is deprecated in X11\n#declare 11 {\n#    KeySym XKeycodeToKeysym(Display *d, unsigned int k, int i)\n#}\ndeclare 12 {\n    KeySym XStringToKeysym(const char *c)\n}\ndeclare 13 {\n    Window XRootWindow(Display *d, int i)\n}\ndeclare 14 {\n    XErrorHandler XSetErrorHandler(XErrorHandler x)\n}\ndeclare 15 {\n    Status XIconifyWindow(Display *d, Window w, int i)\n}\ndeclare 16 {\n    Status XWithdrawWindow(Display *d, Window w, int i)\n}\ndeclare 17 {\n    Status XGetWMColormapWindows(Display *d, Window w, Window **wpp, int *ip)\n}\ndeclare 18 {\n    Status XAllocColor(Display *d, Colormap c, XColor *xp)\n}\ndeclare 19 {\n    int XBell(Display *d, int i)\n}\ndeclare 20 {\n    int XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,\n\t    int i2, const unsigned char *c, int i3)\n}\ndeclare 21 {\n    int XChangeWindowAttributes(Display *d, Window w, unsigned long ul,\n\t    XSetWindowAttributes *x)\n}\ndeclare 22 {\n    int XClearWindow(Display *d, Window w)\n}\ndeclare 23 {\n    int XConfigureWindow(Display *d, Window w, unsigned int i,\n\t    XWindowChanges *x)\n}\ndeclare 24 {\n    int XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,\n\t    int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)\n}\ndeclare 25 {\n    int XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,\n\t    int i2, unsigned int ui1, unsigned int ui2,\n\t    int i3, int i4, unsigned long ul)\n}\ndeclare 26 {\n    Pixmap XCreateBitmapFromData(Display *display, Drawable d,\n\t    const char *data, unsigned int width, unsigned int height)\n}\ndeclare 27 {\n    int XDefineCursor(Display *d, Window w, Cursor c)\n}\ndeclare 28 {\n    int XDeleteProperty(Display *d, Window w, Atom a)\n}\ndeclare 29 {\n    int XDestroyWindow(Display *d, Window w)\n}\ndeclare 30 {\n    int XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,\n\t    unsigned int ui1, unsigned int ui2, int i3, int i4)\n}\ndeclare 31 {\n    int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)\n}\ndeclare 32 {\n    int XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,\n\t    unsigned int ui1, unsigned int ui2)\n}\ndeclare 33 {\n    int XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,\n\t    unsigned int ui1, unsigned int ui2, int i3, int i4)\n}\ndeclare 34 {\n    int XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,\n\t    int i1, int i2, int i3)\n}\ndeclare 35 {\n    int XFillRectangles(Display *d, Drawable dr, GC g, XRectangle *x, int i)\n}\ndeclare 36 {\n    int XForceScreenSaver(Display *d, int i)\n}\ndeclare 37 {\n    int XFreeColormap(Display *d, Colormap c)\n}\ndeclare 38 {\n    int XFreeColors(Display *d, Colormap c,\n\t    unsigned long *ulp, int i, unsigned long ul)\n}\ndeclare 39 {\n    int XFreeCursor(Display *d, Cursor c)\n}\ndeclare 40 {\n    int XFreeModifiermap(XModifierKeymap *x)\n}\ndeclare 41 {\n    Status XGetGeometry(Display *d, Drawable dr, Window *w, int *i1,\n\t    int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3,\n\t    unsigned int *ui4)\n}\ndeclare 42 {\n    int XGetInputFocus(Display *d, Window *w, int *i)\n}\ndeclare 43 {\n    int XGetWindowProperty(Display *d, Window w, Atom a1, long l1, long l2,\n\t    Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1,\n\t    unsigned long *ulp2, unsigned char **cpp)\n}\ndeclare 44 {\n    Status XGetWindowAttributes(Display *d, Window w, XWindowAttributes *x)\n}\ndeclare 45 {\n    int XGrabKeyboard(Display *d, Window w, Bool b, int i1, int i2, Time t)\n}\ndeclare 46 {\n    int XGrabPointer(Display *d, Window w1, Bool b, unsigned int ui,\n\t    int i1, int i2, Window w2, Cursor c, Time t)\n}\ndeclare 47 {\n    KeyCode XKeysymToKeycode(Display *d, KeySym k)\n}\ndeclare 48 {\n    Status XLookupColor(Display *d, Colormap c1, const char *c2,\n\t    XColor *x1, XColor *x2)\n}\ndeclare 49 {\n    int XMapWindow(Display *d, Window w)\n}\ndeclare 50 {\n    int XMoveResizeWindow(Display *d, Window w, int i1, int i2,\n\t    unsigned int ui1, unsigned int ui2)\n}\ndeclare 51 {\n    int XMoveWindow(Display *d, Window w, int i1, int i2)\n}\ndeclare 52 {\n    int XNextEvent(Display *d, XEvent *x)\n}\ndeclare 53 {\n    int XPutBackEvent(Display *d, XEvent *x)\n}\ndeclare 54 {\n    int XQueryColors(Display *d, Colormap c, XColor *x, int i)\n}\ndeclare 55 {\n    Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3,\n\t    int *i1, int *i2, int *i3, int *i4, unsigned int *ui)\n}\ndeclare 56 {\n    Status XQueryTree(Display *d, Window w1, Window *w2, Window *w3,\n\t    Window **w4, unsigned int *ui)\n}\ndeclare 57 {\n    int XRaiseWindow(Display *d, Window w)\n}\ndeclare 58 {\n    int XRefreshKeyboardMapping(XMappingEvent *x)\n}\ndeclare 59 {\n    int XResizeWindow(Display *d, Window w, unsigned int ui1,\n\t    unsigned int ui2)\n}\ndeclare 60 {\n    int XSelectInput(Display *d, Window w, long l)\n}\ndeclare 61 {\n    Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x)\n}\ndeclare 62 {\n    int XSetCommand(Display *d, Window w, char **c, int i)\n}\ndeclare 63 {\n    int XSetIconName(Display *d, Window w, const char *c)\n}\ndeclare 64 {\n    int XSetInputFocus(Display *d, Window w, int i, Time t)\n}\ndeclare 65 {\n    int XSetSelectionOwner(Display *d, Atom a, Window w, Time t)\n}\ndeclare 66 {\n    int XSetWindowBackground(Display *d, Window w, unsigned long ul)\n}\ndeclare 67 {\n    int XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)\n}\ndeclare 68 {\n    int XSetWindowBorder(Display *d, Window w, unsigned long ul)\n}\ndeclare 69 {\n    int XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)\n}\ndeclare 70 {\n    int XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)\n}\ndeclare 71 {\n    int XSetWindowColormap(Display *d, Window w, Colormap c)\n}\ndeclare 72 {\n    Bool XTranslateCoordinates(Display *d, Window w1, Window w2, int i1,\n\t    int i2, int *i3, int *i4, Window *w3)\n}\ndeclare 73 {\n    int XUngrabKeyboard(Display *d, Time t)\n}\ndeclare 74 {\n    int XUngrabPointer(Display *d, Time t)\n}\ndeclare 75 {\n    int XUnmapWindow(Display *d, Window w)\n}\ndeclare 76 {\n    int XWindowEvent(Display *d, Window w, long l, XEvent *x)\n}\ndeclare 77 {\n    void XDestroyIC(XIC x)\n}\ndeclare 78 {\n    Bool XFilterEvent(XEvent *x, Window w)\n}\ndeclare 79 {\n    int XmbLookupString(XIC xi, XKeyPressedEvent *xk, char *c, int i,\n\t    KeySym *k, Status *s)\n}\ndeclare 80 {\n    int TkPutImage(unsigned long *colors, int ncolors, Display *display,\n\t    Drawable d, GC gc, XImage *image, int src_x, int src_y,\n\t    int dest_x, int dest_y, unsigned int width, unsigned int height)\n}\ndeclare 81 {\n    int XSetClipRectangles(Display *display, GC gc, int clip_x_origin,\n\t    int clip_y_origin, XRectangle *rectangles, int n, int ordering)\n}\ndeclare 82 {\n    Status XParseColor(Display *display, Colormap map,\n\t    const char *spec, XColor *colorPtr)\n}\ndeclare 83 {\n    GC XCreateGC(Display *display, Drawable d,\n\t    unsigned long valuemask, XGCValues *values)\n}\ndeclare 84 {\n    int XFreeGC(Display *display, GC gc)\n}\ndeclare 85 {\n    Atom XInternAtom(Display *display, const char *atom_name,\n\t    Bool only_if_exists)\n}\ndeclare 86 {\n    int XSetBackground(Display *display, GC gc, unsigned long foreground)\n}\ndeclare 87 {\n    int XSetForeground(Display *display, GC gc, unsigned long foreground)\n}\ndeclare 88 {\n    int XSetClipMask(Display *display, GC gc, Pixmap pixmap)\n}\ndeclare 89 {\n    int XSetClipOrigin(Display *display, GC gc,\n\t    int clip_x_origin, int clip_y_origin)\n}\ndeclare 90 {\n    int XSetTSOrigin(Display *display, GC gc,\n\t    int ts_x_origin, int ts_y_origin)\n}\ndeclare 91 {\n    int XChangeGC(Display *d, GC gc, unsigned long mask, XGCValues *values)\n}\ndeclare 92 {\n    int XSetFont(Display *display, GC gc, Font font)\n}\ndeclare 93 {\n    int XSetArcMode(Display *display, GC gc, int arc_mode)\n}\ndeclare 94 {\n    int XSetStipple(Display *display, GC gc, Pixmap stipple)\n}\ndeclare 95 {\n    int XSetFillRule(Display *display, GC gc, int fill_rule)\n}\ndeclare 96 {\n    int XSetFillStyle(Display *display, GC gc, int fill_style)\n}\ndeclare 97 {\n    int XSetFunction(Display *display, GC gc, int function)\n}\ndeclare 98 {\n    int XSetLineAttributes(Display *display, GC gc, unsigned int line_width,\n\t    int line_style, int cap_style, int join_style)\n}\ndeclare 99 {\n    int _XInitImageFuncPtrs(XImage *image)\n}\ndeclare 100 {\n    XIC XCreateIC(XIM xim, ...)\n}\ndeclare 101 {\n    XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask,\n\t    XVisualInfo *vinfo_template, int *nitems_return)\n}\ndeclare 102 {\n    void XSetWMClientMachine(Display *display, Window w,\n\t    XTextProperty *text_prop)\n}\ndeclare 103 {\n    Status XStringListToTextProperty(char **list, int count,\n\t    XTextProperty *text_prop_return)\n}\ndeclare 104 {\n    int XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1,\n\t    int x2, int y2)\n}\ndeclare 105 {\n    int XWarpPointer(Display *d, Window s, Window dw, int sx, int sy,\n\t    unsigned int sw, unsigned int sh, int dx, int dy)\n}\ndeclare 106 {\n    int XFillRectangle(Display *display, Drawable d, GC gc,\n\t    int x, int y, unsigned int width, unsigned int height)\n}\n\n# New in Tk 8.6\ndeclare 107 {\n    int XFlush(Display *display)\n}\ndeclare 108 {\n    int XGrabServer(Display *display)\n}\ndeclare 109 {\n    int XUngrabServer(Display *display)\n}\ndeclare 110 {\n    int XFree(void *data)\n}\ndeclare 111 {\n    int XNoOp(Display *display)\n}\ndeclare 112 {\n    XAfterFunction XSynchronize(Display *display, Bool onoff)\n}\ndeclare 113 {\n    int XSync(Display *display, Bool discard)\n}\ndeclare 114 {\n    VisualID XVisualIDFromVisual(Visual *visual)\n}\n\n# For tktreectrl\ndeclare 120 {\n    int XOffsetRegion(Region rgn, int dx, int dy)\n}\ndeclare 121 {\n    int XUnionRegion(Region srca, Region srcb, Region dr_return)\n}\n\n# For 3dcanvas\ndeclare 122 {\n    Window XCreateWindow(Display *display, Window parent, int x, int y,\n\t    unsigned int width, unsigned int height,\n\t    unsigned int border_width, int depth, unsigned int clazz,\n\t    Visual *visual, unsigned long value_mask,\n\t    XSetWindowAttributes *attributes)\n}\n\n# Various, e.g. for stub-enabled BLT\ndeclare 129 {\n    int XLowerWindow(Display *d, Window w)\n}\ndeclare 130 {\n    int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)\n}\ndeclare 131 {\n    int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)\n}\ndeclare 132 {\n    int XDrawRectangles(Display *d, Drawable dr, GC gc, XRectangle *r, int n)\n}\ndeclare 133 {\n    int XDrawSegments(Display *d, Drawable dr, GC gc, XSegment *s, int n)\n}\ndeclare 134 {\n    int XDrawPoint(Display *d, Drawable dr, GC gc, int x, int y)\n}\ndeclare 135 {\n    int XDrawPoints(Display *d, Drawable dr, GC gc, XPoint *p, int n, int m)\n}\ndeclare 136 {\n    int XReparentWindow(Display *d, Window w, Window p, int x, int y)\n}\ndeclare 137 {\n    int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,\n\t    int sx, int sy, int dx, int dy,\n\t    unsigned int w, unsigned int h)\n}\ndeclare 138 {\n    Region XPolygonRegion(XPoint *pts, int n, int rule)\n}\ndeclare 139 {\n    int XPointInRegion(Region rgn, int x, int y)\n}\n# For XIM\ndeclare 140 {\n    XVaNestedList XVaCreateNestedList(int dummy, ...)\n}\ndeclare 141 {\n    char *XSetICValues(XIC xic, ...)\n}\ndeclare 142 {\n    char *XGetICValues(XIC xic, ...)\n}\ndeclare 143 {\n    void XSetICFocus(XIC xic)\n}\ndeclare 144 {\n    int XXorRegion(Region sra, Region srb, Region dr_return)\n}\ndeclare 145 {\n    Bool XEqualRegion(Region r1, Region r2)\n}\ndeclare 147 {\n    void XFreeFontSet(Display *display, XFontSet fontset)\n}\ndeclare 148 {\n    int XCloseIM(XIM im)\n}\ndeclare 149 {\n    Bool XRegisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,\n\t    char *res_name, char *res_class, XIDProc callback, XPointer client_data)\n}\ndeclare 150 {\n    Bool XUnregisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,\n\t    char *res_name, char *res_class, XIDProc callback, XPointer client_data)\n}\ndeclare 151 {\n    char *XSetLocaleModifiers(const char *modifier_list)\n}\ndeclare 152 {\n    XIM XOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name,\n\t    char *res_class)\n}\ndeclare 153 {\n    char *XGetIMValues(XIM im, ...)\n}\ndeclare 154 {\n    char *XSetIMValues(XIM im, ...)\n}\ndeclare 155 {\n    XFontSet XCreateFontSet(Display *display, const char *base_font_name_list,\n\t    char ***missing_charset_list, int *missing_charset_count, char **def_string)\n}\ndeclare 156 {\n    void XFreeStringList(char **list)\n}\ndeclare 157 {\n    KeySym XkbKeycodeToKeysym(Display *d, unsigned int k, int g, int i)\n}\ndeclare 158 {\n    Display *XkbOpenDisplay(const char *name, int *ev_rtrn, int *err_rtrn,\n\t    int *major_rtrn, int *minor_rtrn, int *reason)\n}\n\f\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "generic/tkInt.h",
    "content": "/*\n * tkInt.h --\n *\n *\tDeclarations for things used internally by the Tk functions but not\n *\texported outside the module.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKINT\n#define _TKINT\n\n#ifndef _TKPORT\n#include \"tkPort.h\"\n#endif\n#include <X11/Xatom.h>\n\n/*\n * Ensure WORDS_BIGENDIAN is defined correctly:\n * Needs to happen here in addition to configure to work with fat compiles on\n * Darwin (where configure runs only once for multiple architectures).\n */\n\n#ifdef HAVE_SYS_TYPES_H\n#    include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_PARAM_H\n#    include <sys/param.h>\n#endif\n#include <stdint.h>\n#include <stdlib.h>\n#if defined(_MSC_VER) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 202311L))\n#include <stdbool.h>\n#endif\n#ifdef BYTE_ORDER\n#    ifdef BIG_ENDIAN\n#\t if BYTE_ORDER == BIG_ENDIAN\n#\t     undef WORDS_BIGENDIAN\n#\t     define WORDS_BIGENDIAN 1\n#\t endif\n#    endif\n#    ifdef LITTLE_ENDIAN\n#\t if BYTE_ORDER == LITTLE_ENDIAN\n#\t     undef WORDS_BIGENDIAN\n#\t endif\n#    endif\n#endif\n\n/*\n * Used to tag functions that are only to be visible within the module being\n * built and not outside it (where this is supported by the linker).\n */\n\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#\tdefine MODULE_SCOPE extern \"C\"\n#   else\n#\tdefine MODULE_SCOPE extern\n#   endif\n#endif\n\n#ifndef JOIN\n#  define JOIN(a,b) JOIN1(a,b)\n#  define JOIN1(a,b) a##b\n#endif\n\n#ifndef TCL_UNUSED\n#   if defined(__cplusplus)\n#\tdefine TCL_UNUSED(T) T\n#   elif defined(__GNUC__) && (__GNUC__ > 2)\n#\tdefine TCL_UNUSED(T) T JOIN(dummy, __LINE__) __attribute__((unused))\n#   else\n#\tdefine TCL_UNUSED(T) T JOIN(dummy, __LINE__)\n#   endif\n#endif\n\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)\n#   define TKFLEXARRAY\n#elif defined(__GNUC__) && (__GNUC__ > 2)\n#   define TKFLEXARRAY 0\n#else\n#   define TKFLEXARRAY 1\n#endif\n\n/*\n * Macros used to cast between pointers and integers (e.g. when storing an int\n * in ClientData), on 64-bit architectures they avoid gcc warning about \"cast\n * to/from pointer from/to integer of different size\".\n */\n\n#if !defined(INT2PTR)\n#   define INT2PTR(p) ((void *)(ptrdiff_t)(p))\n#endif\n#if !defined(PTR2INT)\n#   define PTR2INT(p) ((ptrdiff_t)(p))\n#endif\n#if !defined(UINT2PTR)\n#   define UINT2PTR(p) ((void *)(size_t)(p))\n#endif\n#if !defined(PTR2UINT)\n#   define PTR2UINT(p) ((size_t)(p))\n#endif\n\n/*\n * Fallback in case Tk is linked against a Tcl version not having TIP #585\n * (TCL_INDEX_TEMP_TABLE) or TIP #613/#618 (TCL_NULL_OK)\n */\n\n#ifndef TCL_NULL_OK\n#   define TCL_NULL_OK 32\n#endif\n#if !defined(TCL_INDEX_TEMP_TABLE)\n#   define TCL_INDEX_TEMP_TABLE 64\n#endif\n\n#ifndef TCL_Z_MODIFIER\n#   if defined(_WIN64)\n#\tdefine TCL_Z_MODIFIER\t\"I\"\n#   elif defined(__GNUC__) && !defined(_WIN32)\n#\tdefine TCL_Z_MODIFIER\t\"z\"\n#   else\n#\tdefine TCL_Z_MODIFIER\t\"\"\n#   endif\n#endif /* !TCL_Z_MODIFIER */\n#undef TCL_LL_MODIFIER\n#if defined(_WIN32) && (!defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO)\n#   define TCL_LL_MODIFIER\t\"I64\"\n#else\n#   define TCL_LL_MODIFIER\t\"ll\"\n#endif\n\n#if !defined(TCL_SIZE_MODIFIER)\n#   define TCL_SIZE_MODIFIER \"\"\n#endif\n\n/*\n * Opaque type declarations:\n */\n\ntypedef struct TkColormap TkColormap;\ntypedef struct TkFontAttributes TkFontAttributes;\ntypedef struct TkGrabEvent TkGrabEvent;\n#ifndef TK_NO_DEPRECATED\n    typedef Cursor TkpCursor;\n    typedef Region TkRegion;\n#endif\ntypedef struct TkStressedCmap TkStressedCmap;\ntypedef struct TkBindInfo_ *TkBindInfo;\ntypedef struct Busy *TkBusy;\n\n/*\n * One of the following structures is maintained for each cursor in use in the\n * system. This structure is used by tkCursor.c and the various system-\n * specific cursor files.\n */\n\ntypedef struct TkCursor {\n    Tk_Cursor cursor;\t\t/* System specific identifier for cursor. */\n    Display *display;\t\t/* Display containing cursor. Needed for\n\t\t\t\t * disposal and retrieval of cursors. */\n    Tcl_Size resourceRefCount;\t/* Number of active uses of this cursor (each\n\t\t\t\t * active use corresponds to a call to\n\t\t\t\t * Tk_AllocPreserveFromObj or Tk_Preserve). If\n\t\t\t\t * this count is 0, then this structure is no\n\t\t\t\t * longer valid and it isn't present in a hash\n\t\t\t\t * table: it is being kept around only because\n\t\t\t\t * there are objects referring to it. The\n\t\t\t\t * structure is freed when resourceRefCount\n\t\t\t\t * and objRefCount are both 0. */\n    Tcl_Size objRefCount;\t\t/* Number of Tcl objects that reference this\n\t\t\t\t * structure.. */\n    Tcl_HashTable *otherTable;\t/* Second table (other than idTable) used to\n\t\t\t\t * index this entry. */\n    Tcl_HashEntry *hashPtr;\t/* Entry in otherTable for this structure\n\t\t\t\t * (needed when deleting). */\n    Tcl_HashEntry *idHashPtr;\t/* Entry in idTable for this structure (needed\n\t\t\t\t * when deleting). */\n    struct TkCursor *nextPtr;\t/* Points to the next TkCursor structure with\n\t\t\t\t * the same name. Cursors with the same name\n\t\t\t\t * but different displays are chained together\n\t\t\t\t * off a single hash table entry. */\n} TkCursor;\n\n/*\n * The following structure is kept one-per-TkDisplay to maintain information\n * about the caret (cursor location) on this display. This is used to dictate\n * global focus location (Windows Accessibility guidelines) and to position\n * the IME or XIM over-the-spot window.\n */\n\ntypedef struct TkCaret {\n    struct TkWindow *winPtr;\t/* The window on which we requested caret\n\t\t\t\t * placement. */\n    int x;\t\t\t/* Relative x coord of the caret. */\n    int y;\t\t\t/* Relative y coord of the caret. */\n    int height;\t\t\t/* Specified height of the window. */\n} TkCaret;\n\n/*\n * One of the following structures is maintained for each display containing a\n * window managed by Tk. In part, the structure is used to store thread-\n * specific data, since each thread will have its own TkDisplay structure.\n */\n\ntypedef enum TkLockUsage {LU_IGNORE, LU_CAPS, LU_SHIFT} TkLockUsage;\n\ntypedef struct TkDisplay {\n    Display *display;\t\t/* Xlib's info about display. */\n    struct TkDisplay *nextPtr;\t/* Next in list of all displays. */\n    char *name;\t\t\t/* Name of display (with any screen identifier\n\t\t\t\t * removed). Malloc-ed. */\n    Time lastEventTime;\t\t/* Time of last event received for this\n\t\t\t\t * display. */\n\n    /*\n     * Information used primarily by tk3d.c:\n     */\n\n    int borderInit;\t\t/* 0 means borderTable needs initializing. */\n    Tcl_HashTable borderTable;\t/* Maps from color name to TkBorder\n\t\t\t\t * structure. */\n\n    /*\n     * Information used by tkAtom.c only:\n     */\n\n    int atomInit;\t\t/* 0 means stuff below hasn't been initialized\n\t\t\t\t * yet. */\n    Tcl_HashTable nameTable;\t/* Maps from names to Atom's. */\n    Tcl_HashTable atomTable;\t/* Maps from Atom's back to names. */\n\n    /*\n     * Information used primarily by tkBind.c:\n     */\n\n    int bindInfoStale;\t\t/* Non-zero means the variables in this part\n\t\t\t\t * of the structure are potentially incorrect\n\t\t\t\t * and should be recomputed. */\n    unsigned int modeModMask;\t/* Has one bit set to indicate the modifier\n\t\t\t\t * corresponding to \"mode shift\". If no such\n\t\t\t\t * modifier, than this is zero. */\n    unsigned int metaModMask;\t/* Has one bit set to indicate the modifier\n\t\t\t\t * corresponding to the \"Meta\" key. If no such\n\t\t\t\t * modifier, then this is zero. */\n    unsigned int altModMask;\t/* Has one bit set to indicate the modifier\n\t\t\t\t * corresponding to the \"Meta\" key. If no such\n\t\t\t\t * modifier, then this is zero. */\n    TkLockUsage lockUsage;\n\t\t\t\t/* Indicates how to interpret lock\n\t\t\t\t * modifier. */\n    Tcl_Size numModKeyCodes;\t\t/* Number of entries in modKeyCodes array\n\t\t\t\t * below. */\n    KeyCode *modKeyCodes;\t/* Pointer to an array giving keycodes for all\n\t\t\t\t * of the keys that have modifiers associated\n\t\t\t\t * with them. Malloc'ed, but may be NULL. */\n\n    /*\n     * Information used by tkBitmap.c only:\n     */\n\n    int bitmapInit;\t\t/* 0 means tables above need initializing. */\n    int bitmapAutoNumber;\t/* Used to number bitmaps. */\n    Tcl_HashTable bitmapNameTable;\n\t\t\t\t/* Maps from name of bitmap to the first\n\t\t\t\t * TkBitmap record for that name. */\n    Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap\n\t\t\t\t * structure for the bitmap. */\n    Tcl_HashTable bitmapDataTable;\n\t\t\t\t/* Used by Tk_GetBitmapFromData to map from a\n\t\t\t\t * collection of in-core data about a bitmap\n\t\t\t\t * to a reference giving an automatically-\n\t\t\t\t * generated name for the bitmap. */\n\n    /*\n     * Information used by tkCanvas.c only:\n     */\n\n    int numIdSearches;\n    int numSlowSearches;\n\n    /*\n     * Used by tkColor.c only:\n     */\n\n    int colorInit;\t\t/* 0 means color module needs initializing. */\n    TkStressedCmap *stressPtr;\t/* First in list of colormaps that have filled\n\t\t\t\t * up, so we have to pick an approximate\n\t\t\t\t * color. */\n    Tcl_HashTable colorNameTable;\n\t\t\t\t/* Maps from color name to TkColor structure\n\t\t\t\t * for that color. */\n    Tcl_HashTable colorValueTable;\n\t\t\t\t/* Maps from integer RGB values to TkColor\n\t\t\t\t * structures. */\n\n    /*\n     * Used by tkCursor.c only:\n     */\n\n    int cursorInit;\t\t/* 0 means cursor module need initializing. */\n    Tcl_HashTable cursorNameTable;\n\t\t\t\t/* Maps from a string name to a cursor to the\n\t\t\t\t * TkCursor record for the cursor. */\n    Tcl_HashTable cursorDataTable;\n\t\t\t\t/* Maps from a collection of in-core data\n\t\t\t\t * about a cursor to a TkCursor structure. */\n    Tcl_HashTable cursorIdTable;\n\t\t\t\t/* Maps from a cursor id to the TkCursor\n\t\t\t\t * structure for the cursor. */\n    char cursorString[20];\t/* Used to store a cursor id string. */\n    Font cursorFont;\t\t/* Font to use for standard cursors. None\n\t\t\t\t * means font not loaded yet. */\n\n    /*\n     * Information used by tkError.c only:\n     */\n\n    struct TkErrorHandler *errorPtr;\n\t\t\t\t/* First in list of error handlers for this\n\t\t\t\t * display. NULL means no handlers exist at\n\t\t\t\t * present. */\n    Tcl_Size deleteCount;\t\t/* Counts # of handlers deleted since last\n\t\t\t\t * time inactive handlers were garbage-\n\t\t\t\t * collected. When this number gets big,\n\t\t\t\t * handlers get cleaned up. */\n\n    /*\n     * Used by tkEvent.c only:\n     */\n\n    struct TkWindowEvent *delayedMotionPtr;\n\t\t\t\t/* Points to a malloc-ed motion event whose\n\t\t\t\t * processing has been delayed in the hopes\n\t\t\t\t * that another motion event will come along\n\t\t\t\t * right away and we can merge the two of them\n\t\t\t\t * together. NULL means that there is no\n\t\t\t\t * delayed motion event. */\n\n    /*\n     * Information used by tkFocus.c only:\n     */\n\n    int focusDebug;\t\t/* 1 means collect focus debugging\n\t\t\t\t * statistics. */\n    struct TkWindow *implicitWinPtr;\n\t\t\t\t/* If the focus arrived at a toplevel window\n\t\t\t\t * implicitly via an Enter event (rather than\n\t\t\t\t * via a FocusIn event), this points to the\n\t\t\t\t * toplevel window. Otherwise it is NULL. */\n    struct TkWindow *focusPtr;\t/* Points to the window on this display that\n\t\t\t\t * should be receiving keyboard events. When\n\t\t\t\t * multiple applications on the display have\n\t\t\t\t * the focus, this will refer to the innermost\n\t\t\t\t * window in the innermost application. This\n\t\t\t\t * information isn't used on Windows, but it's\n\t\t\t\t * needed on the Mac, and also on X11 when XIM\n\t\t\t\t * processing is being done. */\n\n    /*\n     * Information used by tkGC.c only:\n     */\n\n    Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure\n\t\t\t\t * describing a GC with those values. */\n    Tcl_HashTable gcIdTable;    /* Maps from a GC to a TkGC. */\n    int gcInit;\t\t\t/* 0 means the tables below need\n\t\t\t\t * initializing. */\n\n    /*\n     * Information used by tkGeometry.c only:\n     */\n\n    Tcl_HashTable maintainHashTable;\n\t\t\t\t/* Hash table that maps from a container's\n\t\t\t\t * Tk_Window token to a list of windows managed\n\t\t\t\t * by that container. */\n    int geomInit;\n\n    /*\n     * Information used by tkGrid.c, tkPack.c, tkPlace.c, tkPointer.c,\n     * and ttkMacOSXTheme.c:\n     */\n\n#define TkGetContainer(tkwin) (Tk_TopWinHierarchy((TkWindow *)tkwin) ? NULL : \\\n\t(((TkWindow *)tkwin)->maintainerPtr != NULL ? \\\n\t ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr))\n\n    /*\n     * Information used by tkGet.c only:\n     */\n\n    Tcl_HashTable uidTable;\t/* Stores all Tk_Uid used in a thread. */\n    int uidInit;\t\t/* 0 means uidTable needs initializing. */\n\n    /*\n     * Information used by tkGrab.c only:\n     */\n\n    struct TkWindow *grabWinPtr;/* Window in which the pointer is currently\n\t\t\t\t * grabbed, or NULL if none. */\n    struct TkWindow *eventualGrabWinPtr;\n\t\t\t\t/* Value that grabWinPtr will have once the\n\t\t\t\t * grab event queue (below) has been\n\t\t\t\t * completely emptied. */\n    struct TkWindow *buttonWinPtr;\n\t\t\t\t/* Window in which first mouse button was\n\t\t\t\t * pressed while grab was in effect, or NULL\n\t\t\t\t * if no such press in effect. */\n    struct TkWindow *serverWinPtr;\n\t\t\t\t/* If no application contains the pointer then\n\t\t\t\t * this is NULL. Otherwise it contains the\n\t\t\t\t * last window for which we've gotten an Enter\n\t\t\t\t * or Leave event from the server (i.e. the\n\t\t\t\t * last window known to have contained the\n\t\t\t\t * pointer). Doesn't reflect events that were\n\t\t\t\t * synthesized in tkGrab.c. */\n    TkGrabEvent *firstGrabEventPtr;\n\t\t\t\t/* First in list of enter/leave events\n\t\t\t\t * synthesized by grab code. These events must\n\t\t\t\t * be processed in order before any other\n\t\t\t\t * events are processed. NULL means no such\n\t\t\t\t * events. */\n    TkGrabEvent *lastGrabEventPtr;\n\t\t\t\t/* Last in list of synthesized events, or NULL\n\t\t\t\t * if list is empty. */\n    int grabFlags;\t\t/* Miscellaneous flag values. See definitions\n\t\t\t\t * in tkGrab.c. */\n\n    /*\n     * Information used by tkGrid.c only:\n     */\n\n    int gridInit;\t\t/* 0 means table below needs initializing. */\n    Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to corresponding\n\t\t\t\t * Grid structures. */\n\n    /*\n     * Information used by tkImage.c only:\n     */\n\n    int imageId;\t\t/* Value used to number image ids. */\n\n    /*\n     * Information used by tkMacWinMenu.c only:\n     */\n\n    int postCommandGeneration;\n\n    /*\n     * Information used by tkPack.c only.\n     */\n\n    int packInit;\t\t/* 0 means table below needs initializing. */\n    Tcl_HashTable packerHashTable;\n\t\t\t\t/* Maps from Tk_Window tokens to corresponding\n\t\t\t\t * Packer structures. */\n\n    /*\n     * Information used by tkPlace.c only.\n     */\n\n    int placeInit;\t\t/* 0 means tables below need initializing. */\n    Tcl_HashTable containerTable;\t/* Maps from Tk_Window token to the Container\n\t\t\t\t * structure for the window, if it exists. */\n    Tcl_HashTable contentTable;\t/* Maps from Tk_Window token to the Content\n\t\t\t\t * structure for the window, if it exists. */\n\n    /*\n     * Information used by tkSelect.c and tkClipboard.c only:\n     */\n\n    struct TkSelectionInfo *selectionInfoPtr;\n\t\t\t\t/* First in list of selection information\n\t\t\t\t * records. Each entry contains information\n\t\t\t\t * about the current owner of a particular\n\t\t\t\t * selection on this display. */\n    Atom multipleAtom;\t\t/* Atom for MULTIPLE. None means selection\n\t\t\t\t * stuff isn't initialized. */\n    Atom incrAtom;\t\t/* Atom for INCR. */\n    Atom targetsAtom;\t\t/* Atom for TARGETS. */\n    Atom timestampAtom;\t\t/* Atom for TIMESTAMP. */\n    Atom textAtom;\t\t/* Atom for TEXT. */\n    Atom compoundTextAtom;\t/* Atom for COMPOUND_TEXT. */\n    Atom applicationAtom;\t/* Atom for TK_APPLICATION. */\n    Atom windowAtom;\t\t/* Atom for TK_WINDOW. */\n    Atom clipboardAtom;\t\t/* Atom for CLIPBOARD. */\n    Atom utf8Atom;\t\t/* Atom for UTF8_STRING. */\n    Atom atomPairAtom;          /* Atom for ATOM_PAIR. */\n\n    Tk_Window clipWindow;\t/* Window used for clipboard ownership and to\n\t\t\t\t * retrieve selections between processes. NULL\n\t\t\t\t * means clipboard info hasn't been\n\t\t\t\t * initialized. */\n    int clipboardActive;\t/* 1 means we currently own the clipboard\n\t\t\t\t * selection, 0 means we don't. */\n    struct TkMainInfo *clipboardAppPtr;\n\t\t\t\t/* Last application that owned clipboard. */\n    struct TkClipboardTarget *clipTargetPtr;\n\t\t\t\t/* First in list of clipboard type information\n\t\t\t\t * records. Each entry contains information\n\t\t\t\t * about the buffers for a given selection\n\t\t\t\t * target. */\n\n    /*\n     * Information used by tkSend.c only:\n     */\n\n    Tk_Window commTkwin;\t/* Window used for communication between\n\t\t\t\t * interpreters during \"send\" commands. NULL\n\t\t\t\t * means send info hasn't been initialized\n\t\t\t\t * yet. */\n    Atom commProperty;\t\t/* X's name for comm property. */\n    Atom registryProperty;\t/* X's name for property containing registry\n\t\t\t\t * of interpreter names. */\n    Atom appNameProperty;\t/* X's name for property used to hold the\n\t\t\t\t * application name on each comm window. */\n\n    /*\n     * Information used by tkUnixWm.c and tkWinWm.c only:\n     */\n\n    struct TkWmInfo *firstWmPtr;/* Points to first top-level window. */\n    struct TkWmInfo *foregroundWmPtr;\n\t\t\t\t/* Points to the foreground window. */\n\n    /*\n     * Information used by tkVisual.c only:\n     */\n\n    TkColormap *cmapPtr;\t/* First in list of all non-default colormaps\n\t\t\t\t * allocated for this display. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    XIM inputMethod;\t\t/* Input method for this display. */\n    XIMStyle inputStyle;\t/* Input style selected for this display. */\n    XFontSet inputXfs;\t\t/* XFontSet cached for over-the-spot XIM. */\n    Tcl_HashTable winTable;\t/* Maps from X window ids to TkWindow ptrs. */\n\n    Tcl_Size refCount;\t\t/* Reference count of how many Tk applications\n\t\t\t\t * are using this display. Used to clean up\n\t\t\t\t * the display when we no longer have any Tk\n\t\t\t\t * applications using it. */\n\n    Tk_Window warpWindow;\n    Tk_Window warpMainwin;\t/* For finding the root window for warping\n\t\t\t\t * purposes. */\n    int warpX;\n    int warpY;\n\n    /*\n     * The following field(s) were all added for Tk8.4\n     */\n\n    unsigned int flags;\t\t/* Various flag values: these are all defined\n\t\t\t\t * in below. */\n    TkCaret caret;\t\t/* Information about the caret for this\n\t\t\t\t * display. This is not a pointer. */\n\n    int iconDataSize;\t\t/* Size of default iconphoto image data. */\n    unsigned char *iconDataPtr;\t/* Default iconphoto image data, if set. */\n    int ximGeneration;          /* Used to invalidate XIC */\n} TkDisplay;\n\n/*\n * Flag values for TkDisplay flags.\n *  TK_DISPLAY_COLLAPSE_MOTION_EVENTS:\t(default on)\n *\tIndicates that we should collapse motion events on this display\n *  TK_DISPLAY_USE_IM:\t\t\t(default on, set via tk.tcl)\n *\tWhether to use input methods for this display\n *  TK_DISPLAY_WM_TRACING:\t\t(default off)\n *\tWhether we should do wm tracing on this display.\n */\n\n#define TK_DISPLAY_COLLAPSE_MOTION_EVENTS\t(1 << 0)\n#define TK_DISPLAY_USE_IM\t\t\t(1 << 1)\n#define TK_DISPLAY_WM_TRACING\t\t\t(1 << 3)\n\n/*\n * One of the following structures exists for each error handler created by a\n * call to Tk_CreateErrorHandler. The structure is managed by tkError.c.\n */\n\ntypedef struct TkErrorHandler {\n    TkDisplay *dispPtr;\t\t/* Display to which handler applies. */\n    unsigned long firstRequest;\t/* Only errors with serial numbers >= to this\n\t\t\t\t * are considered. */\n    unsigned long lastRequest;\t/* Only errors with serial numbers <= to this\n\t\t\t\t * are considered. This field is filled in\n\t\t\t\t * when XUnhandle is called. -1 means\n\t\t\t\t * XUnhandle hasn't been called yet. */\n    int error;\t\t\t/* Consider only errors with this error_code\n\t\t\t\t * (-1 means consider all errors). */\n    int request;\t\t/* Consider only errors with this major\n\t\t\t\t * request code (-1 means consider all major\n\t\t\t\t * codes). */\n    int minorCode;\t\t/* Consider only errors with this minor\n\t\t\t\t * request code (-1 means consider all minor\n\t\t\t\t * codes). */\n    Tk_ErrorProc *errorProc;\t/* Function to invoke when a matching error\n\t\t\t\t * occurs. NULL means just ignore errors. */\n    void *clientData;\t/* Arbitrary value to pass to errorProc. */\n    struct TkErrorHandler *nextPtr;\n\t\t\t\t/* Pointer to next older handler for this\n\t\t\t\t * display, or NULL for end of list. */\n} TkErrorHandler;\n\n/*\n * One of the following structures exists for each event handler created by\n * calling Tk_CreateEventHandler. This information is used by tkEvent.c only.\n */\n\ntypedef struct TkEventHandler {\n    unsigned long mask;\t\t/* Events for which to invoke proc. */\n    Tk_EventProc *proc;\t\t/* Function to invoke when an event in mask\n\t\t\t\t * occurs. */\n    void *clientData;\t/* Argument to pass to proc. */\n    struct TkEventHandler *nextPtr;\n\t\t\t\t/* Next in list of handlers associated with\n\t\t\t\t * window (NULL means end of list). */\n} TkEventHandler;\n\n/*\n * Tk keeps one of the following data structures for each main window (created\n * by a call to TkCreateMainWindow). It stores information that is shared by\n * all of the windows associated with a particular main window.\n */\n\ntypedef struct TkMainInfo {\n    Tcl_Size refCount;\t\t/* Number of windows whose \"mainPtr\" fields\n\t\t\t\t * point here. When this becomes zero, can\n\t\t\t\t * free up the structure (the reference count\n\t\t\t\t * is zero because windows can get deleted in\n\t\t\t\t * almost any order; the main window isn't\n\t\t\t\t * necessarily the last one deleted). */\n    struct TkWindow *winPtr;\t/* Pointer to main window. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with application. */\n    Tcl_HashTable nameTable;\t/* Hash table mapping path names to TkWindow\n\t\t\t\t * structs for all windows related to this\n\t\t\t\t * main window. Managed by tkWindow.c. */\n    size_t deletionEpoch;\t\t/* Incremented by window deletions. */\n    Tk_BindingTable bindingTable;\n\t\t\t\t/* Used in conjunction with \"bind\" command to\n\t\t\t\t * bind events to Tcl commands. */\n    TkBindInfo bindInfo;\t/* Information used by tkBind.c on a per\n\t\t\t\t * application basis. */\n    struct TkFontInfo *fontInfoPtr;\n\t\t\t\t/* Information used by tkFont.c on a per\n\t\t\t\t * application basis. */\n\n    /*\n     * Information used only by tkFocus.c and tk*Embed.c:\n     */\n\n    struct TkToplevelFocusInfo *tlFocusPtr;\n\t\t\t\t/* First in list of records containing focus\n\t\t\t\t * information for each top-level in the\n\t\t\t\t * application. Used only by tkFocus.c. */\n    struct TkDisplayFocusInfo *displayFocusPtr;\n\t\t\t\t/* First in list of records containing focus\n\t\t\t\t * information for each display that this\n\t\t\t\t * application has ever used. Used only by\n\t\t\t\t * tkFocus.c. */\n\n    struct ElArray *optionRootPtr;\n\t\t\t\t/* Top level of option hierarchy for this main\n\t\t\t\t * window. NULL means uninitialized. Managed\n\t\t\t\t * by tkOption.c. */\n    Tcl_HashTable imageTable;\t/* Maps from image names to Tk_ImageModel\n\t\t\t\t * structures. Managed by tkImage.c. */\n    int strictMotif;\t\t/* This is linked to the tk_strictMotif global\n\t\t\t\t * variable. */\n    int alwaysShowSelection;\t/* This is linked to the\n\t\t\t\t * ::tk::AlwaysShowSelection variable. */\n    struct TkMainInfo *nextPtr;\t/* Next in list of all main windows managed by\n\t\t\t\t * this process. */\n    Tcl_HashTable busyTable;\t/* Information used by [tk busy] command. */\n    void *tclUpdateObjProc;\n\t\t\t\t/* Saved Tcl [update] command, used to restore\n\t\t\t\t * Tcl's version of [update] after Tk is shut\n\t\t\t\t * down. Only for Tcl 9.0 */\n    Tcl_ObjCmdProc2 *tclUpdateObjProc2;\n\t\t\t\t/* Saved Tcl [update] command, used to restore\n\t\t\t\t * Tcl's version of [update] after Tk is shut\n\t\t\t\t * down. For Tcl 9.1+ */\n    unsigned int nbTabPosition, nbTabPlacement;\n\t\t\t\t/* Information used by ttk::notebook. */\n    int troughInnerX, troughInnerY, troughInnerWidth, troughInnerHeight;\n\t\t\t\t/* Information used by ttk::scale. */\n} TkMainInfo;\n\n/*\n * Tk keeps the following data structure for each of it's builtin bitmaps.\n * This structure is only used by tkBitmap.c and other platform specific\n * bitmap files.\n */\n\ntypedef struct {\n    const void *source;\t\t/* Bits for bitmap. */\n    int width, height;\t\t/* Dimensions of bitmap. */\n    int native;\t\t\t/* 0 means generic (X style) bitmap, 1 means\n\t\t\t\t * native style bitmap. */\n} TkPredefBitmap;\n\n/*\n * Tk keeps one of the following structures for each window. Some of the\n * information (like size and location) is a shadow of information managed by\n * the X server, and some is special information used here, such as event and\n * geometry management information. This information is (mostly) managed by\n * tkWindow.c. WARNING: the declaration below must be kept consistent with the\n * Tk_FakeWin structure in tk.h. If you change one, be sure to change the\n * other!\n */\n\ntypedef struct TkWindow {\n    /*\n     * Structural information:\n     */\n\n    Display *display;\t\t/* Display containing window. */\n    TkDisplay *dispPtr;\t\t/* Tk's information about display for\n\t\t\t\t * window. */\n    int screenNum;\t\t/* Index of screen for window, among all those\n\t\t\t\t * for dispPtr. */\n    Visual *visual;\t\t/* Visual to use for window. If not default,\n\t\t\t\t * MUST be set before X window is created. */\n    int depth;\t\t\t/* Number of bits/pixel. */\n    Window window;\t\t/* X's id for window. None means window hasn't\n\t\t\t\t * actually been created yet, or it's been\n\t\t\t\t * deleted. */\n    struct TkWindow *childList;\t/* First in list of child windows, or NULL if\n\t\t\t\t * no children. List is in stacking order,\n\t\t\t\t * lowest window first.*/\n    struct TkWindow *lastChildPtr;\n\t\t\t\t/* Last in list of child windows (highest in\n\t\t\t\t * stacking order), or NULL if no children. */\n    struct TkWindow *parentPtr;\t/* Pointer to parent window (logical parent,\n\t\t\t\t * not necessarily X parent). NULL means\n\t\t\t\t * either this is the main window, or the\n\t\t\t\t * window's parent has already been deleted. */\n    struct TkWindow *nextPtr;\t/* Next higher sibling (in stacking order) in\n\t\t\t\t * list of children with same parent. NULL\n\t\t\t\t * means end of list. */\n    TkMainInfo *mainPtr;\t/* Information shared by all windows\n\t\t\t\t * associated with a particular main window.\n\t\t\t\t * NULL means this window is a rogue that is\n\t\t\t\t * not associated with any application (at\n\t\t\t\t * present, this only happens for the dummy\n\t\t\t\t * windows used for \"send\" communication). */\n\n    /*\n     * Name and type information for the window:\n     */\n\n    char *pathName;\t\t/* Path name of window (concatenation of all\n\t\t\t\t * names between this window and its top-level\n\t\t\t\t * ancestor). This is a pointer into an entry\n\t\t\t\t * in mainPtr->nameTable. NULL means that the\n\t\t\t\t * window hasn't been completely created\n\t\t\t\t * yet. */\n    Tk_Uid nameUid;\t\t/* Name of the window within its parent\n\t\t\t\t * (unique within the parent). */\n    Tk_Uid classUid;\t\t/* Class of the window. NULL means window\n\t\t\t\t * hasn't been given a class yet. */\n\n    /*\n     * Geometry and other attributes of window. This information may not be\n     * updated on the server immediately; stuff that hasn't been reflected in\n     * the server yet is called \"dirty\". At present, information can be dirty\n     * only if the window hasn't yet been created.\n     */\n\n    XWindowChanges changes;\t/* Geometry and other info about window. */\n    unsigned int dirtyChanges;\t/* Bits indicate fields of \"changes\" that are\n\t\t\t\t * dirty. */\n    XSetWindowAttributes atts;\t/* Current attributes of window. */\n    unsigned long dirtyAtts;\t/* Bits indicate fields of \"atts\" that are\n\t\t\t\t * dirty. */\n\n    unsigned int flags;\t\t/* Various flag values: these are all defined\n\t\t\t\t * in tk.h (confusing, but they're needed\n\t\t\t\t * there for some query macros). */\n\n    /*\n     * Information kept by the event manager (tkEvent.c):\n     */\n\n    TkEventHandler *handlerList;/* First in list of event handlers declared\n\t\t\t\t * for this window, or NULL if none. */\n    XIC inputContext;\t\t/* XIM input context. */\n\n    /*\n     * Information used for event bindings (see \"bind\" and \"bindtags\" commands\n     * in tkCmds.c):\n     */\n\n    void **tagPtr;\t\t/* Points to array of tags used for bindings\n\t\t\t\t * on this window. Each tag is a Tk_Uid.\n\t\t\t\t * Malloc'ed. NULL means no tags. */\n    Tcl_Size numTags;\t\t/* Number of tags at *tagPtr. */\n\n    /*\n     * Information used by tkOption.c to manage options for the window.\n     */\n\n    Tcl_Size optionLevel;\t\t/* TCL_INDEX_NONE means no option information is currently\n\t\t\t\t * cached for this window. Otherwise this\n\t\t\t\t * gives the level in the option stack at\n\t\t\t\t * which info is cached. */\n    /*\n     * Information used by tkSelect.c to manage the selection.\n     */\n\n    struct TkSelHandler *selHandlerList;\n\t\t\t\t/* First in list of handlers for returning the\n\t\t\t\t * selection in various forms. */\n\n    /*\n     * Information used by tkGeometry.c for geometry management.\n     */\n\n    const Tk_GeomMgr *geomMgrPtr;\n\t\t\t\t/* Information about geometry manager for this\n\t\t\t\t * window. */\n    void *geomData;\t/* Argument for geometry manager functions. */\n    int reqWidth, reqHeight;\t/* Arguments from last call to\n\t\t\t\t * Tk_GeometryRequest, or 0's if\n\t\t\t\t * Tk_GeometryRequest hasn't been called. */\n    int internalBorderLeft;\t/* Width of internal border of window (0 means\n\t\t\t\t * no internal border). Geometry managers\n\t\t\t\t * should not normally place children on top\n\t\t\t\t * of the border. Fields for the other three\n\t\t\t\t * sides are found below. */\n\n    /*\n     * Information maintained by tkWm.c for window manager communication.\n     */\n\n    struct TkWmInfo *wmInfoPtr;\t/* For top-level windows (and also for special\n\t\t\t\t * Unix menubar and wrapper windows), points\n\t\t\t\t * to structure with wm-related info (see\n\t\t\t\t * tkWm.c). For other windows, this is\n\t\t\t\t * NULL. */\n\n    /*\n     * Information used by widget classes.\n     */\n\n    const Tk_ClassProcs *classProcsPtr;\n    void *instanceData;\n\n    /*\n     * Platform specific information private to each port.\n     */\n\n    struct TkWindowPrivate *privatePtr;\n\n    /*\n     * More information used by tkGeometry.c for geometry management.\n     */\n\n    /* The remaining fields of internal border. */\n    int internalBorderRight;\n    int internalBorderTop;\n    int internalBorderBottom;\n\n    int minReqWidth;\t\t/* Minimum requested width. */\n    int minReqHeight;\t\t/* Minimum requested height. */\n    int ximGeneration;          /* Used to invalidate XIC */\n    char *geomMgrName;          /* Records the name of the geometry manager. */\n    struct TkWindow *maintainerPtr;\n\t\t\t\t/* The geometry container for this window. The\n\t\t\t\t * value is NULL if the window has no container or\n\t\t\t\t * if its container is its parent. */\n} TkWindow;\n\n/*\n * String tables:\n */\n\nMODULE_SCOPE const char *const tkStateStrings[];\nMODULE_SCOPE const char *const tkCompoundStrings[];\nMODULE_SCOPE const char *const tkAnchorStrings[];\nMODULE_SCOPE const char *const tkReliefStrings[];\nMODULE_SCOPE const char *const tkJustifyStrings[];\n\n/*\n * Real definition of some events. Note that these events come from outside\n * but have internally generated pieces added to them.\n */\n\ntypedef struct {\n    XKeyEvent keyEvent;\t\t/* The real event from X11. */\n#ifdef _WIN32\n#   ifndef XMaxTransChars\n#\tdefine XMaxTransChars 7\n#   endif\n    char trans_chars[XMaxTransChars]; /* translated characters */\n    unsigned char nbytes;\n#elif !defined(MAC_OSX_TK)\n    char *charValuePtr;\t\t/* A pointer to a string that holds the key's\n\t\t\t\t * %A substitution text (before backslash\n\t\t\t\t * adding), or NULL if that has not been\n\t\t\t\t * computed yet. If non-NULL, this string was\n\t\t\t\t * allocated with Tcl_Alloc(). */\n    Tcl_Size charValueLen;\t/* Length of string in charValuePtr when that\n\t\t\t\t * is non-NULL. */\n    KeySym keysym;\t\t/* Key symbol computed after input methods\n\t\t\t\t * have been invoked */\n#endif\n} TkKeyEvent;\n\n/*\n * Flags passed to TkpMakeMenuWindow's 'transient' argument.\n */\n\n#define TK_MAKE_MENU_TEAROFF\t0\t/* Only non-transient case. */\n#define TK_MAKE_MENU_POPUP\t1\n#define TK_MAKE_MENU_DROPDOWN\t2\n\n/*\n * The following structure is used with TkMakeEnsemble to create ensemble\n * commands and optionally to create sub-ensembles.\n */\n\ntypedef struct TkEnsemble {\n    const char *name;\n    Tcl_ObjCmdProc2 *proc;\n    const struct TkEnsemble *subensemble;\n} TkEnsemble;\n\n/*\n * The following structure is used as a two way map between integers and\n * strings, usually to map between an internal C representation and the\n * strings used in Tcl.\n */\n\ntypedef struct TkStateMap {\n    int numKey;\t\t\t/* Integer representation of a value. */\n    const char *strKey;\t\t/* String representation of a value. */\n} TkStateMap;\n\n/*\n * This structure is used by the Mac and Window porting layers as the internal\n * representation of a clip_mask in a GC.\n */\n\ntypedef struct TkpClipMask {\n    int type;\t\t\t/* TKP_CLIP_PIXMAP or TKP_CLIP_REGION. */\n    union {\n\tPixmap pixmap;\n\tRegion region;\n    } value;\n} TkpClipMask;\n\n#define TKP_CLIP_PIXMAP 0\n#define TKP_CLIP_REGION 1\n\n/*\n * Return values from TkGrabState:\n */\n\n#define TK_GRAB_NONE\t\t0\n#define TK_GRAB_IN_TREE\t\t1\n#define TK_GRAB_ANCESTOR\t2\n#define TK_GRAB_EXCLUDED\t3\n\n/*\n * The macro below is used to modify a \"char\" value (e.g. by casting it to an\n * unsigned character) so that it can be used safely with macros such as\n * isspace().\n */\n\n#define UCHAR(c) ((unsigned char) (c))\n\n/*\n * The following symbol is used in the mode field of FocusIn events generated\n * by an embedded application to request the input focus from its container.\n */\n\n#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20)\n\n/*\n * The following special modifier mask bits are defined, to indicate logical\n * modifiers such as Meta and Alt that may float among the actual modifier\n * bits.\n */\n\n#define META_MASK\t(AnyModifier<<1)\n#define ALT_MASK\t(AnyModifier<<2)\n#define EXTENDED_MASK\t(AnyModifier<<3)\n\n/*\n * Buttons 8 and 9 are the Xbuttons (left and right side-buttons). On Windows/Mac, those\n * are known as Buttons 4 and 5. At script level, they also get the numbers 4 and 5.\n */\n\n#ifndef Button8\n# define Button8 8\n#endif\n#ifndef Button9\n# define Button9 9\n#endif\n\n/*\n * The Button<B>Mask modifiers for <B> in {6 7 8 9}\n * are internally used by Tk. They must be above the\n * AnyModifier bit since anything below is reserved\n * for the X protocol. If a future X11 version\n * defines these, we adhere.\n */\n\n#ifndef Button6Mask\n# define Button6Mask (AnyModifier<<6)\n#endif\n#ifndef Button7Mask\n# define Button7Mask (AnyModifier<<7)\n#endif\n#ifndef Button8Mask\n# define Button8Mask (AnyModifier<<8)\n#endif\n#ifndef Button9Mask\n# define Button9Mask (AnyModifier<<9)\n#endif\n\n/*\n * Mask that selects any of the state bits corresponding to buttons, plus\n * masks that select individual buttons' bits:\n */\n\n#define ALL_BUTTONS \\\n\t(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask \\\n\t\t|Button6Mask|Button7Mask|Button8Mask|Button9Mask)\n\n\n/*\n * Object types not declared in tkObj.c need to be mentioned here so they can\n * be properly registered with Tcl:\n */\n\nMODULE_SCOPE const Tcl_ObjType tkBorderObjType;\nMODULE_SCOPE const Tcl_ObjType tkBitmapObjType;\nMODULE_SCOPE const Tcl_ObjType tkColorObjType;\nMODULE_SCOPE const Tcl_ObjType tkCursorObjType;\nMODULE_SCOPE const Tcl_ObjType tkFontObjType;\nMODULE_SCOPE const Tcl_ObjType tkStateKeyObjType;\nMODULE_SCOPE const Tcl_ObjType tkTextIndexType;\n\n/*\n * Miscellaneous variables shared among Tk modules but not exported to the\n * outside world:\n */\n\nMODULE_SCOPE const Tk_SmoothMethod tkBezierSmoothMethod;\nMODULE_SCOPE Tk_ImageType\ttkBitmapImageType;\nMODULE_SCOPE Tk_PhotoImageFormatVersion3 tkImgFmtGIF;\nMODULE_SCOPE void\t\t(*tkHandleEventProc) (XEvent* eventPtr);\nMODULE_SCOPE Tk_PhotoImageFormat tkImgFmtDefault;\nMODULE_SCOPE Tk_PhotoImageFormatVersion3 tkImgFmtPNG;\nMODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPPM;\nMODULE_SCOPE Tk_PhotoImageFormat tkImgFmtSVGnano;\nMODULE_SCOPE TkMainInfo\t\t*tkMainWindowList;\nMODULE_SCOPE Tk_ImageType\ttkPhotoImageType;\nMODULE_SCOPE Tcl_HashTable\ttkPredefBitmapTable;\n\nMODULE_SCOPE const char *const tkWebColors[20];\n\n/*\n * The definition of pi, at least from the perspective of double-precision\n * floats.\n */\n\n#ifndef PI\n#ifdef M_PI\n#define PI\tM_PI\n#else\n#define PI\t3.14159265358979323846\n#endif\n#endif\n\n/*\n * Support for Clang Static Analyzer <https://clang-analyzer.llvm.org/>\n */\n\n#if defined(PURIFY) && defined(__clang__)\n#if __has_feature(attribute_analyzer_noreturn) && \\\n\t!defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED)\nvoid Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn));\n#endif\n#if !defined(CLANG_ASSERT)\n#define CLANG_ASSERT(x) assert(x)\n#endif\n#elif !defined(CLANG_ASSERT)\n#define CLANG_ASSERT(x)\n#endif /* PURIFY && __clang__ */\n\n/*\n * The following magic value is stored in the \"send_event\" field of FocusIn\n * and FocusOut events. This allows us to separate \"real\" events coming from\n * the server from those that we generated.\n */\n\n#define GENERATED_FOCUS_EVENT_MAGIC\t((Bool) 0x547321ac)\n\n/*\n * Exported internals.\n */\n\n#include \"tkIntDecls.h\"  /* IWYU pragma: export */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Themed widget set init function, and handler called when Tk is destroyed.\n */\n\nMODULE_SCOPE int\tTtk_Init(Tcl_Interp *interp);\nMODULE_SCOPE void\tTtk_TkDestroyedHandler(Tcl_Interp *interp);\n\n/*\n * Internal functions shared among Tk modules but not exported to the outside\n * world:\n */\n\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_BellObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_BindObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_BindtagsObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_BusyObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ButtonObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_CanvasObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_CheckbuttonObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ClipboardObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ChooseColorObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ChooseDirectoryObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_DestroyObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_EntryObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_EventObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_FrameObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_FocusObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_FontObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_GetOpenFileObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_GetSaveFileObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_GrabObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_GridObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ImageObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_LabelObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_LabelframeObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ListboxObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_LowerObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_MenuObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_MenubuttonObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_MessageBoxObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_MessageObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_PanedWindowObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_OptionObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_PackObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_PlaceObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_RadiobuttonObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_RaiseObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ScaleObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ScrollbarObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_SelectionObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_SendObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_SpinboxObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_TextObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_TkwaitObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_ToplevelObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_UpdateObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_WinfoObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 Tk_WmObjCmd;\n\nMODULE_SCOPE int\tTkSetGeometryContainer(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, const char *name);\nMODULE_SCOPE void\tTkFreeGeometryContainer(Tk_Window tkwin,\n\t\t\t    const char *name);\n\nMODULE_SCOPE void\tTkRegisterObjTypes(void);\nMODULE_SCOPE Tcl_ObjCmdProc2 TkDeadAppObjCmd;\nMODULE_SCOPE int\tTkCanvasGetCoordObj(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tcl_Obj *obj,\n\t\t\t    double *doublePtr);\nMODULE_SCOPE int\tTkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *string, double *doublePtr);\nMODULE_SCOPE int\tTkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tk_PostscriptInfo psInfo, XImage *ximage,\n\t\t\t    int x, int y, int width, int height);\nMODULE_SCOPE void       TkMapTopFrame(Tk_Window tkwin);\nMODULE_SCOPE XEvent *\tTkpGetBindingXEvent(Tcl_Interp *interp);\nMODULE_SCOPE void\tTkCreateExitHandler(Tcl_ExitProc *proc,\n\t\t\t    void *clientData);\nMODULE_SCOPE void\tTkDeleteExitHandler(Tcl_ExitProc *proc,\n\t\t\t    void *clientData);\nMODULE_SCOPE Tcl_ExitProc\tTkFinalize;\nMODULE_SCOPE Tcl_ExitProc\tTkFinalizeThread;\nMODULE_SCOPE void\tTkpBuildRegionFromAlphaData(Region region,\n\t\t\t    unsigned x, unsigned y, unsigned width,\n\t\t\t    unsigned height, unsigned char *dataPtr,\n\t\t\t    unsigned pixelStride, unsigned lineStride);\nMODULE_SCOPE void\tTkAppendPadAmount(Tcl_Obj *bufferObj,\n\t\t\t    const char *buffer, int pad1, int pad2);\nMODULE_SCOPE int\tTkParsePadAmount(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tcl_Obj *objPtr,\n\t\t\t    int *pad1Ptr, int *pad2Ptr);\nMODULE_SCOPE void       TkFocusSplit(TkWindow *winPtr);\nMODULE_SCOPE void       TkFocusJoin(TkWindow *winPtr);\nMODULE_SCOPE void\tTkpDrawAngledCharsInContext(Display * display,\n\t\t\t    Drawable drawable, GC gc, Tk_Font tkfont,\n\t\t\t    const char *source, Tcl_Size numBytes, Tcl_Size rangeStart,\n\t\t\t    Tcl_Size rangeLength, double x, double y, double angle);\nMODULE_SCOPE void\tTkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont,\n\t\t\t    int c, struct TkFontAttributes *faPtr);\nMODULE_SCOPE void\tTkpDrawFrameEx(Tk_Window tkwin, Drawable drawable,\n\t\t\t    Tk_3DBorder border, int highlightWidth,\n\t\t\t    int borderWidth, int relief);\nMODULE_SCOPE void\tTkpShowBusyWindow(TkBusy busy);\nMODULE_SCOPE void\tTkpHideBusyWindow(TkBusy busy);\nMODULE_SCOPE Tcl_Size\tTkLengthOne(Tcl_Obj *);\nMODULE_SCOPE void\tTkpMakeTransparentWindowExist(Tk_Window tkwin,\n\t\t\t    Window parent);\nMODULE_SCOPE void\tTkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,\n\t\t\t    Window *parentPtr, Tk_Window tkParent,\n\t\t\t    TkBusy busy);\nMODULE_SCOPE int\tTkBackgroundEvalObjv(Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const *objv, int flags);\nMODULE_SCOPE void\tTkDrawDottedRect(Display *disp, Drawable d, GC gc,\n\t\t\t    int x, int y, int width, int height);\nMODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,\n\t\t\t    const char *nsname, const char *name,\n\t\t\t    void *clientData, const TkEnsemble *map);\nMODULE_SCOPE double\tTkScalingLevel(Tk_Window tkwin);\nMODULE_SCOPE bool\tTkObjIsEmpty(Tcl_Obj *objPtr);\nMODULE_SCOPE int\tTkInitTkCmd(Tcl_Interp *interp,\n\t\t\t    void *clientData);\nMODULE_SCOPE int\tTkInitFontchooser(Tcl_Interp *interp,\n\t\t\t    void *clientData);\nMODULE_SCOPE void\tTkInitEmbeddedConfigurationInformation(\n\t\t\t    Tcl_Interp *interp);\nMODULE_SCOPE void\tTkDoWarpWrtWin(TkDisplay *dispPtr);\nMODULE_SCOPE void\tTkpWarpPointer(TkDisplay *dispPtr);\nMODULE_SCOPE void\tTkRotatePoint(double originX, double originY,\n\t\t\t    double sine, double cosine, double *xPtr,\n\t\t\t    double *yPtr);\nMODULE_SCOPE int TkGetIntForIndex(Tcl_Obj *, Tcl_Size, int lastOK, Tcl_Size*);\n\n#define TkNewIndexObj(value) (((Tcl_Size)(value) == TCL_INDEX_NONE) ? Tcl_NewObj() : Tcl_NewWideIntObj((Tcl_WideInt)(value)))\n#define TK_OPTION_UNDERLINE_DEF(type, field) NULL, TCL_INDEX_NONE, offsetof(type, field), TK_OPTION_NULL_OK, NULL\n\n\n#ifdef _WIN32\n#define TkParseColor XParseColor\n#else\nMODULE_SCOPE Status TkParseColor (Display * display,\n\t\t\t\tColormap map, const char* spec,\n\t\t\t\tXColor * colorPtr);\n#endif\n#if !defined(_WIN32) && !defined(__CYGWIN__) /* UNIX and MacOSX */\n#undef TkPutImage\n#define TkPutImage(colors, ncolors, display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \\\n\tXPutImage(display, pixels, gc, image, srcx, srcy, destx, desty, width, height);\n#else\n#undef XPutImage\n#define XPutImage(display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \\\n\tTkPutImage(NULL, 0, display, pixels, gc, image, srcx, srcy, destx, desty, width, height);\n#endif\n\n/*\n * These macros are just wrappers for the equivalent X Region calls.\n */\n#ifndef TK_NO_DEPRECATED\n#   define TkClipBox XClipBox\n#   define TkCreateRegion XCreateRegion\n#   define TkDestroyRegion XDestroyRegion\n#   define TkIntersectRegion XIntersectRegion\n#   define TkRectInRegion XRectInRegion\n#   define TkSetRegion XSetRegion\n#   define TkSubtractRegion XSubtractRegion\n#   define TkUnionRectWithRegion XUnionRectWithRegion\n#endif\n\n#ifdef HAVE_XFT\nMODULE_SCOPE void\tTkUnixSetXftClipRegion(Region clipRegion);\n#endif\n\nMODULE_SCOPE void\tTkpCopyRegion(Region dst, Region src);\n\n#if !defined(__cplusplus) && !defined(c_plusplus)\n# define c_class class\n#endif\n\nMODULE_SCOPE  void       Icu_Init(Tcl_Interp* interp);\n\n/*\n * Unsupported commands.\n */\n\nMODULE_SCOPE Tcl_ObjCmdProc2 TkUnsupported1ObjCmd;\n\n/*\n * For Tktest.\n */\nMODULE_SCOPE Tcl_ObjCmdProc2 SquareObjCmd;\n#if !(defined(_WIN32) || defined(MAC_OSX_TK))\n#define TkplatformtestInit(x) TCL_OK\n#else\nMODULE_SCOPE int\tTkplatformtestInit(Tcl_Interp *interp);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _TKINT */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkIntDecls.h",
    "content": "/*\n * tkIntDecls.h --\n *\n *\tThis file contains the declarations for all unsupported\n *\tfunctions that are exported by the Tk library.  These\n *\tinterfaces are not guaranteed to remain the same between\n *\tversions.  Use at your own risk.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKINTDECLS\n#define _TKINTDECLS\n\n#include \"X11/Xutil.h\"\n\n#ifdef BUILD_tk\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n#endif\n\nstruct TkText;\ntypedef struct TkTextBTree_ *TkTextBTree;\nstruct TkTextDispChunk;\nstruct TkTextIndex;\nstruct TkTextSegment;\nstruct TkSharedText;\n\n/*\n * WARNING: This file is automatically generated by the tools/genStubs.tcl\n * script.  Any modifications to the function declarations below should be made\n * in the generic/tkInt.decls script.\n */\n\n/* !BEGIN!: Do not edit below this line. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n/* 0 */\nEXTERN TkWindow *\tTkAllocWindow(TkDisplay *dispPtr, int screenNum,\n\t\t\t\tTkWindow *parentPtr);\n/* 1 */\nEXTERN void\t\tTkBezierPoints(double *control, int numSteps,\n\t\t\t\tdouble *coordPtr);\n/* 2 */\nEXTERN void\t\tTkBezierScreenPoints(Tk_Canvas canvas,\n\t\t\t\tdouble *control, int numSteps,\n\t\t\t\tXPoint *xPointPtr);\n/* Slot 3 is reserved */\n/* 4 */\nEXTERN void\t\tTkBindEventProc(TkWindow *winPtr, XEvent *eventPtr);\n/* 5 */\nEXTERN void\t\tTkBindFree(TkMainInfo *mainPtr);\n/* 6 */\nEXTERN void\t\tTkBindInit(TkMainInfo *mainPtr);\n/* 7 */\nEXTERN void\t\tTkChangeEventWindow(XEvent *eventPtr,\n\t\t\t\tTkWindow *winPtr);\n/* 8 */\nEXTERN int\t\tTkClipInit(Tcl_Interp *interp, TkDisplay *dispPtr);\n/* 9 */\nEXTERN void\t\tTkComputeAnchor(Tk_Anchor anchor, Tk_Window tkwin,\n\t\t\t\tint padX, int padY, int innerWidth,\n\t\t\t\tint innerHeight, int *xPtr, int *yPtr);\n/* Slot 10 is reserved */\n/* Slot 11 is reserved */\n/* 12 */\nEXTERN TkCursor *\tTkCreateCursorFromData(Tk_Window tkwin,\n\t\t\t\tconst char *source, const char *mask,\n\t\t\t\tint width, int height, int xHot, int yHot,\n\t\t\t\tXColor fg, XColor bg);\n/* 13 */\nEXTERN int\t\tTkCreateFrame(void *clientData, Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv,\n\t\t\t\tint type, const char *appName);\n/* 14 */\nEXTERN Tk_Window\tTkCreateMainWindow(Tcl_Interp *interp,\n\t\t\t\tconst char *screenName, const char *baseName);\n/* 15 */\nEXTERN Time\t\tTkCurrentTime(TkDisplay *dispPtr);\n/* 16 */\nEXTERN void\t\tTkDeleteAllImages(TkMainInfo *mainPtr);\n/* 17 */\nEXTERN void\t\tTkDoConfigureNotify(TkWindow *winPtr);\n/* 18 */\nEXTERN void\t\tTkDrawInsetFocusHighlight(Tk_Window tkwin, GC gc,\n\t\t\t\tint width, Drawable drawable, int padding);\n/* 19 */\nEXTERN void\t\tTkEventDeadWindow(TkWindow *winPtr);\n/* 20 */\nEXTERN void\t\tTkFillPolygon(Tk_Canvas canvas, double *coordPtr,\n\t\t\t\tTcl_Size numPoints, Display *display,\n\t\t\t\tDrawable drawable, GC gc, GC outlineGC);\n/* 21 */\nEXTERN int\t\tTkFindStateNum(Tcl_Interp *interp,\n\t\t\t\tconst char *option, const TkStateMap *mapPtr,\n\t\t\t\tconst char *strKey);\n/* 22 */\nEXTERN const char *\tTkFindStateString(const TkStateMap *mapPtr,\n\t\t\t\tint numKey);\n/* 23 */\nEXTERN void\t\tTkFocusDeadWindow(TkWindow *winPtr);\n/* 24 */\nEXTERN bool\t\tTkFocusFilterEvent(TkWindow *winPtr,\n\t\t\t\tXEvent *eventPtr);\n/* 25 */\nEXTERN TkWindow *\tTkFocusKeyEvent(TkWindow *winPtr, XEvent *eventPtr);\n/* 26 */\nEXTERN void\t\tTkFontPkgInit(TkMainInfo *mainPtr);\n/* 27 */\nEXTERN void\t\tTkFontPkgFree(TkMainInfo *mainPtr);\n/* 28 */\nEXTERN void\t\tTkFreeBindingTags(TkWindow *winPtr);\n/* 29 */\nEXTERN void\t\tTkpFreeCursor(TkCursor *cursorPtr);\n/* 30 */\nEXTERN char *\t\tTkGetBitmapData(Tcl_Interp *interp,\n\t\t\t\tconst char *string, const char *fileName,\n\t\t\t\tint *widthPtr, int *heightPtr, int *hotXPtr,\n\t\t\t\tint *hotYPtr);\n/* 31 */\nEXTERN void\t\tTkGetButtPoints(double *p1, double *p2, double width,\n\t\t\t\tint project, double *m1, double *m2);\n/* 32 */\nEXTERN TkCursor *\tTkGetCursorByName(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, const char *string);\n/* 33 */\nEXTERN const char *\tTkGetDefaultScreenName(Tcl_Interp *interp,\n\t\t\t\tconst char *screenName);\n/* 34 */\nEXTERN TkDisplay *\tTkGetDisplay(Display *display);\n/* 35 */\nEXTERN Tcl_Size\t\tTkGetDisplayOf(Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t\tTcl_Obj *const *objv, Tk_Window *tkwinPtr);\n/* 36 */\nEXTERN TkWindow *\tTkGetFocusWin(TkWindow *winPtr);\n/* 37 */\nEXTERN int\t\tTkGetInterpNames(Tcl_Interp *interp, Tk_Window tkwin);\n/* 38 */\nEXTERN bool\t\tTkGetMiterPoints(double *p1, double *p2, double *p3,\n\t\t\t\tdouble width, double *m1, double *m2);\n/* 39 */\nEXTERN void\t\tTkGetPointerCoords(Tk_Window tkwin, int *xPtr,\n\t\t\t\tint *yPtr);\n/* 40 */\nEXTERN void\t\tTkGetServerInfo(Tcl_Interp *interp, Tk_Window tkwin);\n/* 41 */\nEXTERN void\t\tTkGrabDeadWindow(TkWindow *winPtr);\n/* 42 */\nEXTERN int\t\tTkGrabState(TkWindow *winPtr);\n/* 43 */\nEXTERN void\t\tTkIncludePoint(Tk_Item *itemPtr, double *pointPtr);\n/* 44 */\nEXTERN void\t\tTkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr,\n\t\t\t\tTkWindow *destPtr, int leaveType,\n\t\t\t\tint enterType, Tcl_QueuePosition position);\n/* 45 */\nEXTERN void\t\tTkInstallFrameMenu(Tk_Window tkwin);\n/* 46 */\nEXTERN const char *\tTkKeysymToString(KeySym keysym);\n/* 47 */\nEXTERN int\t\tTkLineToArea(double *end1Ptr, double *end2Ptr,\n\t\t\t\tdouble *rectPtr);\n/* 48 */\nEXTERN double\t\tTkLineToPoint(double *end1Ptr, double *end2Ptr,\n\t\t\t\tdouble *pointPtr);\n/* 49 */\nEXTERN int\t\tTkMakeBezierCurve(Tk_Canvas canvas, double *pointPtr,\n\t\t\t\tint numPoints, int numSteps, XPoint *xPoints,\n\t\t\t\tdouble *dblPoints);\n/* 50 */\nEXTERN void\t\tTkMakeBezierPostscript(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, double *pointPtr,\n\t\t\t\tint numPoints);\n/* 51 */\nEXTERN void\t\tTkOptionClassChanged(TkWindow *winPtr);\n/* 52 */\nEXTERN void\t\tTkOptionDeadWindow(TkWindow *winPtr);\n/* 53 */\nEXTERN int\t\tTkOvalToArea(double *ovalPtr, double *rectPtr);\n/* 54 */\nEXTERN double\t\tTkOvalToPoint(double *ovalPtr, double width,\n\t\t\t\tint filled, double *pointPtr);\n/* 55 */\nEXTERN size_t\t\tTkpChangeFocus(TkWindow *winPtr, int force);\n/* 56 */\nEXTERN void\t\tTkpCloseDisplay(TkDisplay *dispPtr);\n/* 57 */\nEXTERN void\t\tTkpClaimFocus(TkWindow *topLevelPtr, int force);\n/* 58 */\nEXTERN void\t\tTkpDisplayWarning(const char *msg, const char *title);\n/* 59 */\nEXTERN void\t\tTkpGetAppName(Tcl_Interp *interp, Tcl_DString *name);\n/* Slot 60 is reserved */\n/* 61 */\nEXTERN TkWindow *\tTkpGetWrapperWindow(TkWindow *winPtr);\n/* 62 */\nEXTERN int\t\tTkpInit(Tcl_Interp *interp);\n/* 63 */\nEXTERN void\t\tTkpInitializeMenuBindings(Tcl_Interp *interp,\n\t\t\t\tTk_BindingTable bindingTable);\n/* Slot 64 is reserved */\n/* 65 */\nEXTERN void\t\tTkpMakeMenuWindow(Tk_Window tkwin, int transient);\n/* Slot 66 is reserved */\n/* 67 */\nEXTERN void\t\tTkpMenuNotifyToplevelCreate(Tcl_Interp *interp,\n\t\t\t\tconst char *menuName);\n/* 68 */\nEXTERN TkDisplay *\tTkpOpenDisplay(const char *display_name);\n/* 69 */\nEXTERN bool\t\tTkPointerEvent(XEvent *eventPtr, TkWindow *winPtr);\n/* 70 */\nEXTERN int\t\tTkPolygonToArea(double *polyPtr, Tcl_Size numPoints,\n\t\t\t\tdouble *rectPtr);\n/* 71 */\nEXTERN double\t\tTkPolygonToPoint(double *polyPtr, Tcl_Size numPoints,\n\t\t\t\tdouble *pointPtr);\n/* 72 */\nEXTERN int\t\tTkPositionInTree(TkWindow *winPtr, TkWindow *treePtr);\n/* 73 */\nEXTERN void\t\tTkpRedirectKeyEvent(TkWindow *winPtr,\n\t\t\t\tXEvent *eventPtr);\n/* Slot 74 is reserved */\n/* Slot 75 is reserved */\n/* Slot 76 is reserved */\n/* 77 */\nEXTERN void\t\tTkQueueEventForAllChildren(TkWindow *winPtr,\n\t\t\t\tXEvent *eventPtr);\n/* 78 */\nEXTERN int\t\tTkReadBitmapFile(Display *display, Drawable d,\n\t\t\t\tconst char *filename,\n\t\t\t\tunsigned int *width_return,\n\t\t\t\tunsigned int *height_return,\n\t\t\t\tPixmap *bitmap_return, int *x_hot_return,\n\t\t\t\tint *y_hot_return);\n/* 79 */\nEXTERN bool\t\tTkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,\n\t\t\t\tint width, int height, int dx, int dy,\n\t\t\t\tRegion damageRgn);\n/* 80 */\nEXTERN void\t\tTkSelDeadWindow(TkWindow *winPtr);\n/* 81 */\nEXTERN void\t\tTkSelEventProc(Tk_Window tkwin, XEvent *eventPtr);\n/* 82 */\nEXTERN void\t\tTkSelInit(Tk_Window tkwin);\n/* 83 */\nEXTERN void\t\tTkSelPropProc(XEvent *eventPtr);\n/* Slot 84 is reserved */\n/* Slot 85 is reserved */\n/* 86 */\nEXTERN KeySym\t\tTkStringToKeysym(const char *name);\n/* 87 */\nEXTERN int\t\tTkThickPolyLineToArea(double *coordPtr,\n\t\t\t\tTcl_Size numPoints, double width,\n\t\t\t\tint capStyle, int joinStyle, double *rectPtr);\n/* 88 */\nEXTERN void\t\tTkWmAddToColormapWindows(TkWindow *winPtr);\n/* 89 */\nEXTERN void\t\tTkWmDeadWindow(TkWindow *winPtr);\n/* 90 */\nEXTERN TkWindow *\tTkWmFocusToplevel(TkWindow *winPtr);\n/* 91 */\nEXTERN void\t\tTkWmMapWindow(TkWindow *winPtr);\n/* 92 */\nEXTERN void\t\tTkWmNewWindow(TkWindow *winPtr);\n/* 93 */\nEXTERN void\t\tTkWmProtocolEventProc(TkWindow *winPtr,\n\t\t\t\tXEvent *evenvPtr);\n/* 94 */\nEXTERN void\t\tTkWmRemoveFromColormapWindows(TkWindow *winPtr);\n/* 95 */\nEXTERN void\t\tTkWmRestackToplevel(TkWindow *winPtr, int aboveBelow,\n\t\t\t\tTkWindow *otherPtr);\n/* 96 */\nEXTERN void\t\tTkWmSetClass(TkWindow *winPtr);\n/* 97 */\nEXTERN void\t\tTkWmUnmapWindow(TkWindow *winPtr);\n/* 98 */\nEXTERN Tcl_Obj *\tTkDebugBitmap(Tk_Window tkwin, const char *name);\n/* 99 */\nEXTERN Tcl_Obj *\tTkDebugBorder(Tk_Window tkwin, const char *name);\n/* 100 */\nEXTERN Tcl_Obj *\tTkDebugCursor(Tk_Window tkwin, const char *name);\n/* 101 */\nEXTERN Tcl_Obj *\tTkDebugColor(Tk_Window tkwin, const char *name);\n/* 102 */\nEXTERN Tcl_Obj *\tTkDebugConfig(Tcl_Interp *interp,\n\t\t\t\tTk_OptionTable table);\n/* 103 */\nEXTERN Tcl_Obj *\tTkDebugFont(Tk_Window tkwin, const char *name);\n/* 104 */\nEXTERN int\t\tTkFindStateNumObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *optionPtr, const TkStateMap *mapPtr,\n\t\t\t\tTcl_Obj *keyPtr);\n/* 105 */\nEXTERN Tcl_HashTable *\tTkGetBitmapPredefTable(void);\n/* 106 */\nEXTERN TkDisplay *\tTkGetDisplayList(void);\n/* 107 */\nEXTERN TkMainInfo *\tTkGetMainInfoList(void);\n/* 108 */\nEXTERN int\t\tTkGetWindowFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr,\n\t\t\t\tTk_Window *windowPtr);\n/* 109 */\nEXTERN const char *\tTkpGetString(TkWindow *winPtr, XEvent *eventPtr,\n\t\t\t\tTcl_DString *dsPtr);\n/* 110 */\nEXTERN void\t\tTkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont);\n/* Slot 111 is reserved */\n/* 112 */\nEXTERN void\t\tTkpMenuThreadInit(void);\n/* 113 */\nEXTERN int\t\tXClipBox(Region rgn, XRectangle *rect_return);\n/* 114 */\nEXTERN Region\t\tXCreateRegion(void);\n/* 115 */\nEXTERN int\t\tXDestroyRegion(Region rgn);\n/* 116 */\nEXTERN int\t\tXIntersectRegion(Region sra, Region srcb,\n\t\t\t\tRegion dr_return);\n/* 117 */\nEXTERN int\t\tXRectInRegion(Region rgn, int x, int y,\n\t\t\t\tunsigned int width, unsigned int height);\n/* 118 */\nEXTERN int\t\tXSetRegion(Display *display, GC gc, Region rgn);\n/* 119 */\nEXTERN int\t\tXUnionRectWithRegion(XRectangle *rect, Region src,\n\t\t\t\tRegion dr_return);\n/* Slot 120 is reserved */\n/* 121 */\nEXTERN Pixmap\t\tTkpCreateNativeBitmap(Display *display,\n\t\t\t\tconst void *source);\n/* 122 */\nEXTERN void\t\tTkpDefineNativeBitmaps(void);\n/* Slot 123 is reserved */\n/* 124 */\nEXTERN Pixmap\t\tTkpGetNativeAppBitmap(Display *display,\n\t\t\t\tconst char *name, int *width, int *height);\n/* Slot 125 is reserved */\n/* Slot 126 is reserved */\n/* Slot 127 is reserved */\n/* Slot 128 is reserved */\n/* Slot 129 is reserved */\n/* Slot 130 is reserved */\n/* Slot 131 is reserved */\n/* Slot 132 is reserved */\n/* Slot 133 is reserved */\n/* Slot 134 is reserved */\n/* Slot 135 is reserved */\n/* 136 */\nEXTERN void\t\tTkSetFocusWin(TkWindow *winPtr, int force);\n/* 137 */\nEXTERN void\t\tTkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym,\n\t\t\t\tXEvent *eventPtr);\n/* 138 */\nEXTERN KeySym\t\tTkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr);\n/* 139 */\nEXTERN void\t\tTkpInitKeymapInfo(TkDisplay *dispPtr);\n/* 140 */\nEXTERN Region\t\tTkPhotoGetValidRegion(Tk_PhotoHandle handle);\n/* 141 */\nEXTERN TkWindow **\tTkWmStackorderToplevel(TkWindow *parentPtr);\n/* 142 */\nEXTERN void\t\tTkFocusFree(TkMainInfo *mainPtr);\n/* 143 */\nEXTERN void\t\tTkClipCleanup(TkDisplay *dispPtr);\n/* 144 */\nEXTERN void\t\tTkGCCleanup(TkDisplay *dispPtr);\n/* 145 */\nEXTERN int\t\tXSubtractRegion(Region sra, Region srcb,\n\t\t\t\tRegion dr_return);\n/* 146 */\nEXTERN void\t\tTkStylePkgInit(TkMainInfo *mainPtr);\n/* 147 */\nEXTERN void\t\tTkStylePkgFree(TkMainInfo *mainPtr);\n/* 148 */\nEXTERN Tk_Window\tTkToplevelWindowForCommand(Tcl_Interp *interp,\n\t\t\t\tconst char *cmdName);\n/* 149 */\nEXTERN const Tk_OptionSpec * TkGetOptionSpec(const char *name,\n\t\t\t\tTk_OptionTable optionTable);\n/* 150 */\nEXTERN int\t\tTkMakeRawCurve(Tk_Canvas canvas, double *pointPtr,\n\t\t\t\tint numPoints, int numSteps, XPoint *xPoints,\n\t\t\t\tdouble *dblPoints);\n/* 151 */\nEXTERN void\t\tTkMakeRawCurvePostscript(Tcl_Interp *interp,\n\t\t\t\tTk_Canvas canvas, double *pointPtr,\n\t\t\t\tint numPoints);\n/* 152 */\nEXTERN void\t\tTkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border,\n\t\t\t\tint highlightWidth, int borderWidth,\n\t\t\t\tint relief);\n/* 153 */\nEXTERN void\t\tTkCreateThreadExitHandler(Tcl_ExitProc *proc,\n\t\t\t\tvoid *clientData);\n/* 154 */\nEXTERN void\t\tTkDeleteThreadExitHandler(Tcl_ExitProc *proc,\n\t\t\t\tvoid *clientData);\n/* Slot 155 is reserved */\n/* 156 */\nEXTERN int\t\tTkpTestembedCmd(void *clientData, Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv);\n/* 157 */\nEXTERN int\t\tTkpTesttextCmd(void *dummy, Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv);\n/* 158 */\nEXTERN int\t\tTkSelGetSelection(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Atom selection, Atom target,\n\t\t\t\tTk_GetSelProc *proc, void *clientData);\n/* 159 */\nEXTERN int\t\tTkTextGetIndex(Tcl_Interp *interp,\n\t\t\t\tstruct TkText *textPtr, const char *string,\n\t\t\t\tstruct TkTextIndex *indexPtr);\n/* 160 */\nEXTERN bool\t\tTkTextIndexBackBytes(const struct TkText *textPtr,\n\t\t\t\tconst struct TkTextIndex *srcPtr,\n\t\t\t\tTcl_Size count, struct TkTextIndex *dstPtr);\n/* 161 */\nEXTERN bool\t\tTkTextIndexForwBytes(const struct TkText *textPtr,\n\t\t\t\tconst struct TkTextIndex *srcPtr,\n\t\t\t\tTcl_Size count, struct TkTextIndex *dstPtr);\n/* 162 */\nEXTERN struct TkTextIndex * TkTextMakeByteIndex(TkTextBTree tree,\n\t\t\t\tconst struct TkText *textPtr,\n\t\t\t\tTcl_Size lineIndex, Tcl_Size byteIndex,\n\t\t\t\tstruct TkTextIndex *indexPtr);\n/* 163 */\nEXTERN Tcl_Size\t\tTkTextPrintIndex(const struct TkText *textPtr,\n\t\t\t\tconst struct TkTextIndex *indexPtr,\n\t\t\t\tchar *string);\n/* 164 */\nEXTERN struct TkTextSegment * TkTextSetMark(struct TkText *textPtr,\n\t\t\t\tconst char *name,\n\t\t\t\tstruct TkTextIndex *indexPtr);\n/* 165 */\nEXTERN int\t\tTkTextXviewCmd(struct TkText *textPtr,\n\t\t\t\tTcl_Interp *interp, Tcl_Size objc,\n\t\t\t\tTcl_Obj *const *objv);\n/* 166 */\nEXTERN void\t\tTkTextChanged(struct TkSharedText *sharedTextPtr,\n\t\t\t\tstruct TkText *textPtr,\n\t\t\t\tconst struct TkTextIndex *index1Ptr,\n\t\t\t\tconst struct TkTextIndex *index2Ptr);\n/* 167 */\nEXTERN Tcl_Size\t\tTkBTreeNumLines(TkTextBTree tree,\n\t\t\t\tconst struct TkText *textPtr);\n/* 168 */\nEXTERN void\t\tTkTextInsertDisplayProc(struct TkText *textPtr,\n\t\t\t\tstruct TkTextDispChunk *chunkPtr, int x,\n\t\t\t\tint y, int height, int baseline,\n\t\t\t\tDisplay *display, Drawable dst, int screenY);\n/* 169 */\nEXTERN int\t\tTkStateParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 170 */\nEXTERN const char *\tTkStatePrintProc(void *clientData, Tk_Window tkwin,\n\t\t\t\tchar *widgRec, Tcl_Size offset,\n\t\t\t\tTcl_FreeProc **freeProcPtr);\n/* 171 */\nEXTERN int\t\tTkCanvasDashParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 172 */\nEXTERN const char *\tTkCanvasDashPrintProc(void *clientData,\n\t\t\t\tTk_Window tkwin, char *widgRec,\n\t\t\t\tTcl_Size offset, Tcl_FreeProc **freeProcPtr);\n/* 173 */\nEXTERN int\t\tTkOffsetParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 174 */\nEXTERN const char *\tTkOffsetPrintProc(void *clientData, Tk_Window tkwin,\n\t\t\t\tchar *widgRec, Tcl_Size offset,\n\t\t\t\tTcl_FreeProc **freeProcPtr);\n/* 175 */\nEXTERN int\t\tTkPixelParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 176 */\nEXTERN const char *\tTkPixelPrintProc(void *clientData, Tk_Window tkwin,\n\t\t\t\tchar *widgRec, Tcl_Size offset,\n\t\t\t\tTcl_FreeProc **freeProcPtr);\n/* 177 */\nEXTERN int\t\tTkOrientParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 178 */\nEXTERN const char *\tTkOrientPrintProc(void *clientData, Tk_Window tkwin,\n\t\t\t\tchar *widgRec, Tcl_Size offset,\n\t\t\t\tTcl_FreeProc **freeProcPtr);\n/* 179 */\nEXTERN int\t\tTkSmoothParseProc(void *clientData,\n\t\t\t\tTcl_Interp *interp, Tk_Window tkwin,\n\t\t\t\tconst char *value, char *widgRec,\n\t\t\t\tTcl_Size offset);\n/* 180 */\nEXTERN const char *\tTkSmoothPrintProc(void *clientData, Tk_Window tkwin,\n\t\t\t\tchar *widgRec, Tcl_Size offset,\n\t\t\t\tTcl_FreeProc **freeProcPtr);\n/* 181 */\nEXTERN void\t\tTkDrawAngledTextLayout(Display *display,\n\t\t\t\tDrawable drawable, GC gc,\n\t\t\t\tTk_TextLayout layout, int x, int y,\n\t\t\t\tdouble angle, Tcl_Size firstChar,\n\t\t\t\tTcl_Size lastChar);\n/* 182 */\nEXTERN void\t\tTkUnderlineAngledTextLayout(Display *display,\n\t\t\t\tDrawable drawable, GC gc,\n\t\t\t\tTk_TextLayout layout, int x, int y,\n\t\t\t\tdouble angle, int underline);\n/* 183 */\nEXTERN int\t\tTkIntersectAngledTextLayout(Tk_TextLayout layout,\n\t\t\t\tint x, int y, int width, int height,\n\t\t\t\tdouble angle);\n/* 184 */\nEXTERN void\t\tTkDrawAngledChars(Display *display,\n\t\t\t\tDrawable drawable, GC gc, Tk_Font tkfont,\n\t\t\t\tconst char *source, Tcl_Size numBytes,\n\t\t\t\tdouble x, double y, double angle);\n/* Slot 185 is reserved */\n/* Slot 186 is reserved */\n/* 187 */\nEXTERN bool\t\tTkDebugPhotoStringMatchDef(Tcl_Interp *inter,\n\t\t\t\tTcl_Obj *data, Tcl_Obj *formatString,\n\t\t\t\tint *widthPtr, int *heightPtr);\n\ntypedef struct TkIntStubs {\n    int magic;\n    void *hooks;\n\n    TkWindow * (*tkAllocWindow) (TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr); /* 0 */\n    void (*tkBezierPoints) (double *control, int numSteps, double *coordPtr); /* 1 */\n    void (*tkBezierScreenPoints) (Tk_Canvas canvas, double *control, int numSteps, XPoint *xPointPtr); /* 2 */\n    void (*reserved3)(void);\n    void (*tkBindEventProc) (TkWindow *winPtr, XEvent *eventPtr); /* 4 */\n    void (*tkBindFree) (TkMainInfo *mainPtr); /* 5 */\n    void (*tkBindInit) (TkMainInfo *mainPtr); /* 6 */\n    void (*tkChangeEventWindow) (XEvent *eventPtr, TkWindow *winPtr); /* 7 */\n    int (*tkClipInit) (Tcl_Interp *interp, TkDisplay *dispPtr); /* 8 */\n    void (*tkComputeAnchor) (Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int *xPtr, int *yPtr); /* 9 */\n    void (*reserved10)(void);\n    void (*reserved11)(void);\n    TkCursor * (*tkCreateCursorFromData) (Tk_Window tkwin, const char *source, const char *mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg); /* 12 */\n    int (*tkCreateFrame) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, int type, const char *appName); /* 13 */\n    Tk_Window (*tkCreateMainWindow) (Tcl_Interp *interp, const char *screenName, const char *baseName); /* 14 */\n    Time (*tkCurrentTime) (TkDisplay *dispPtr); /* 15 */\n    void (*tkDeleteAllImages) (TkMainInfo *mainPtr); /* 16 */\n    void (*tkDoConfigureNotify) (TkWindow *winPtr); /* 17 */\n    void (*tkDrawInsetFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding); /* 18 */\n    void (*tkEventDeadWindow) (TkWindow *winPtr); /* 19 */\n    void (*tkFillPolygon) (Tk_Canvas canvas, double *coordPtr, Tcl_Size numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC); /* 20 */\n    int (*tkFindStateNum) (Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey); /* 21 */\n    const char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */\n    void (*tkFocusDeadWindow) (TkWindow *winPtr); /* 23 */\n    bool (*tkFocusFilterEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 24 */\n    TkWindow * (*tkFocusKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 25 */\n    void (*tkFontPkgInit) (TkMainInfo *mainPtr); /* 26 */\n    void (*tkFontPkgFree) (TkMainInfo *mainPtr); /* 27 */\n    void (*tkFreeBindingTags) (TkWindow *winPtr); /* 28 */\n    void (*tkpFreeCursor) (TkCursor *cursorPtr); /* 29 */\n    char * (*tkGetBitmapData) (Tcl_Interp *interp, const char *string, const char *fileName, int *widthPtr, int *heightPtr, int *hotXPtr, int *hotYPtr); /* 30 */\n    void (*tkGetButtPoints) (double *p1, double *p2, double width, int project, double *m1, double *m2); /* 31 */\n    TkCursor * (*tkGetCursorByName) (Tcl_Interp *interp, Tk_Window tkwin, const char *string); /* 32 */\n    const char * (*tkGetDefaultScreenName) (Tcl_Interp *interp, const char *screenName); /* 33 */\n    TkDisplay * (*tkGetDisplay) (Display *display); /* 34 */\n    Tcl_Size (*tkGetDisplayOf) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, Tk_Window *tkwinPtr); /* 35 */\n    TkWindow * (*tkGetFocusWin) (TkWindow *winPtr); /* 36 */\n    int (*tkGetInterpNames) (Tcl_Interp *interp, Tk_Window tkwin); /* 37 */\n    bool (*tkGetMiterPoints) (double *p1, double *p2, double *p3, double width, double *m1, double *m2); /* 38 */\n    void (*tkGetPointerCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 39 */\n    void (*tkGetServerInfo) (Tcl_Interp *interp, Tk_Window tkwin); /* 40 */\n    void (*tkGrabDeadWindow) (TkWindow *winPtr); /* 41 */\n    int (*tkGrabState) (TkWindow *winPtr); /* 42 */\n    void (*tkIncludePoint) (Tk_Item *itemPtr, double *pointPtr); /* 43 */\n    void (*tkInOutEvents) (XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 44 */\n    void (*tkInstallFrameMenu) (Tk_Window tkwin); /* 45 */\n    const char * (*tkKeysymToString) (KeySym keysym); /* 46 */\n    int (*tkLineToArea) (double *end1Ptr, double *end2Ptr, double *rectPtr); /* 47 */\n    double (*tkLineToPoint) (double *end1Ptr, double *end2Ptr, double *pointPtr); /* 48 */\n    int (*tkMakeBezierCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint *xPoints, double *dblPoints); /* 49 */\n    void (*tkMakeBezierPostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 50 */\n    void (*tkOptionClassChanged) (TkWindow *winPtr); /* 51 */\n    void (*tkOptionDeadWindow) (TkWindow *winPtr); /* 52 */\n    int (*tkOvalToArea) (double *ovalPtr, double *rectPtr); /* 53 */\n    double (*tkOvalToPoint) (double *ovalPtr, double width, int filled, double *pointPtr); /* 54 */\n    size_t (*tkpChangeFocus) (TkWindow *winPtr, int force); /* 55 */\n    void (*tkpCloseDisplay) (TkDisplay *dispPtr); /* 56 */\n    void (*tkpClaimFocus) (TkWindow *topLevelPtr, int force); /* 57 */\n    void (*tkpDisplayWarning) (const char *msg, const char *title); /* 58 */\n    void (*tkpGetAppName) (Tcl_Interp *interp, Tcl_DString *name); /* 59 */\n    void (*reserved60)(void);\n    TkWindow * (*tkpGetWrapperWindow) (TkWindow *winPtr); /* 61 */\n    int (*tkpInit) (Tcl_Interp *interp); /* 62 */\n    void (*tkpInitializeMenuBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable); /* 63 */\n    void (*reserved64)(void);\n    void (*tkpMakeMenuWindow) (Tk_Window tkwin, int transient); /* 65 */\n    void (*reserved66)(void);\n    void (*tkpMenuNotifyToplevelCreate) (Tcl_Interp *interp, const char *menuName); /* 67 */\n    TkDisplay * (*tkpOpenDisplay) (const char *display_name); /* 68 */\n    bool (*tkPointerEvent) (XEvent *eventPtr, TkWindow *winPtr); /* 69 */\n    int (*tkPolygonToArea) (double *polyPtr, Tcl_Size numPoints, double *rectPtr); /* 70 */\n    double (*tkPolygonToPoint) (double *polyPtr, Tcl_Size numPoints, double *pointPtr); /* 71 */\n    int (*tkPositionInTree) (TkWindow *winPtr, TkWindow *treePtr); /* 72 */\n    void (*tkpRedirectKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 73 */\n    void (*reserved74)(void);\n    void (*reserved75)(void);\n    void (*reserved76)(void);\n    void (*tkQueueEventForAllChildren) (TkWindow *winPtr, XEvent *eventPtr); /* 77 */\n    int (*tkReadBitmapFile) (Display *display, Drawable d, const char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return); /* 78 */\n    bool (*tkScrollWindow) (Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, Region damageRgn); /* 79 */\n    void (*tkSelDeadWindow) (TkWindow *winPtr); /* 80 */\n    void (*tkSelEventProc) (Tk_Window tkwin, XEvent *eventPtr); /* 81 */\n    void (*tkSelInit) (Tk_Window tkwin); /* 82 */\n    void (*tkSelPropProc) (XEvent *eventPtr); /* 83 */\n    void (*reserved84)(void);\n    void (*reserved85)(void);\n    KeySym (*tkStringToKeysym) (const char *name); /* 86 */\n    int (*tkThickPolyLineToArea) (double *coordPtr, Tcl_Size numPoints, double width, int capStyle, int joinStyle, double *rectPtr); /* 87 */\n    void (*tkWmAddToColormapWindows) (TkWindow *winPtr); /* 88 */\n    void (*tkWmDeadWindow) (TkWindow *winPtr); /* 89 */\n    TkWindow * (*tkWmFocusToplevel) (TkWindow *winPtr); /* 90 */\n    void (*tkWmMapWindow) (TkWindow *winPtr); /* 91 */\n    void (*tkWmNewWindow) (TkWindow *winPtr); /* 92 */\n    void (*tkWmProtocolEventProc) (TkWindow *winPtr, XEvent *evenvPtr); /* 93 */\n    void (*tkWmRemoveFromColormapWindows) (TkWindow *winPtr); /* 94 */\n    void (*tkWmRestackToplevel) (TkWindow *winPtr, int aboveBelow, TkWindow *otherPtr); /* 95 */\n    void (*tkWmSetClass) (TkWindow *winPtr); /* 96 */\n    void (*tkWmUnmapWindow) (TkWindow *winPtr); /* 97 */\n    Tcl_Obj * (*tkDebugBitmap) (Tk_Window tkwin, const char *name); /* 98 */\n    Tcl_Obj * (*tkDebugBorder) (Tk_Window tkwin, const char *name); /* 99 */\n    Tcl_Obj * (*tkDebugCursor) (Tk_Window tkwin, const char *name); /* 100 */\n    Tcl_Obj * (*tkDebugColor) (Tk_Window tkwin, const char *name); /* 101 */\n    Tcl_Obj * (*tkDebugConfig) (Tcl_Interp *interp, Tk_OptionTable table); /* 102 */\n    Tcl_Obj * (*tkDebugFont) (Tk_Window tkwin, const char *name); /* 103 */\n    int (*tkFindStateNumObj) (Tcl_Interp *interp, Tcl_Obj *optionPtr, const TkStateMap *mapPtr, Tcl_Obj *keyPtr); /* 104 */\n    Tcl_HashTable * (*tkGetBitmapPredefTable) (void); /* 105 */\n    TkDisplay * (*tkGetDisplayList) (void); /* 106 */\n    TkMainInfo * (*tkGetMainInfoList) (void); /* 107 */\n    int (*tkGetWindowFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 108 */\n    const char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */\n    void (*tkpGetSubFonts) (Tcl_Interp *interp, Tk_Font tkfont); /* 110 */\n    void (*reserved111)(void);\n    void (*tkpMenuThreadInit) (void); /* 112 */\n    int (*xClipBox) (Region rgn, XRectangle *rect_return); /* 113 */\n    Region (*xCreateRegion) (void); /* 114 */\n    int (*xDestroyRegion) (Region rgn); /* 115 */\n    int (*xIntersectRegion) (Region sra, Region srcb, Region dr_return); /* 116 */\n    int (*xRectInRegion) (Region rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */\n    int (*xSetRegion) (Display *display, GC gc, Region rgn); /* 118 */\n    int (*xUnionRectWithRegion) (XRectangle *rect, Region src, Region dr_return); /* 119 */\n    void (*reserved120)(void);\n    Pixmap (*tkpCreateNativeBitmap) (Display *display, const void *source); /* 121 */\n    void (*tkpDefineNativeBitmaps) (void); /* 122 */\n    void (*reserved123)(void);\n    Pixmap (*tkpGetNativeAppBitmap) (Display *display, const char *name, int *width, int *height); /* 124 */\n    void (*reserved125)(void);\n    void (*reserved126)(void);\n    void (*reserved127)(void);\n    void (*reserved128)(void);\n    void (*reserved129)(void);\n    void (*reserved130)(void);\n    void (*reserved131)(void);\n    void (*reserved132)(void);\n    void (*reserved133)(void);\n    void (*reserved134)(void);\n    void (*reserved135)(void);\n    void (*tkSetFocusWin) (TkWindow *winPtr, int force); /* 136 */\n    void (*tkpSetKeycodeAndState) (Tk_Window tkwin, KeySym keySym, XEvent *eventPtr); /* 137 */\n    KeySym (*tkpGetKeySym) (TkDisplay *dispPtr, XEvent *eventPtr); /* 138 */\n    void (*tkpInitKeymapInfo) (TkDisplay *dispPtr); /* 139 */\n    Region (*tkPhotoGetValidRegion) (Tk_PhotoHandle handle); /* 140 */\n    TkWindow ** (*tkWmStackorderToplevel) (TkWindow *parentPtr); /* 141 */\n    void (*tkFocusFree) (TkMainInfo *mainPtr); /* 142 */\n    void (*tkClipCleanup) (TkDisplay *dispPtr); /* 143 */\n    void (*tkGCCleanup) (TkDisplay *dispPtr); /* 144 */\n    int (*xSubtractRegion) (Region sra, Region srcb, Region dr_return); /* 145 */\n    void (*tkStylePkgInit) (TkMainInfo *mainPtr); /* 146 */\n    void (*tkStylePkgFree) (TkMainInfo *mainPtr); /* 147 */\n    Tk_Window (*tkToplevelWindowForCommand) (Tcl_Interp *interp, const char *cmdName); /* 148 */\n    const Tk_OptionSpec * (*tkGetOptionSpec) (const char *name, Tk_OptionTable optionTable); /* 149 */\n    int (*tkMakeRawCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint *xPoints, double *dblPoints); /* 150 */\n    void (*tkMakeRawCurvePostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 151 */\n    void (*tkpDrawFrame) (Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief); /* 152 */\n    void (*tkCreateThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 153 */\n    void (*tkDeleteThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 154 */\n    void (*reserved155)(void);\n    int (*tkpTestembedCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv); /* 156 */\n    int (*tkpTesttextCmd) (void *dummy, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv); /* 157 */\n    int (*tkSelGetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, void *clientData); /* 158 */\n    int (*tkTextGetIndex) (Tcl_Interp *interp, struct TkText *textPtr, const char *string, struct TkTextIndex *indexPtr); /* 159 */\n    bool (*tkTextIndexBackBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, Tcl_Size count, struct TkTextIndex *dstPtr); /* 160 */\n    bool (*tkTextIndexForwBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, Tcl_Size count, struct TkTextIndex *dstPtr); /* 161 */\n    struct TkTextIndex * (*tkTextMakeByteIndex) (TkTextBTree tree, const struct TkText *textPtr, Tcl_Size lineIndex, Tcl_Size byteIndex, struct TkTextIndex *indexPtr); /* 162 */\n    Tcl_Size (*tkTextPrintIndex) (const struct TkText *textPtr, const struct TkTextIndex *indexPtr, char *string); /* 163 */\n    struct TkTextSegment * (*tkTextSetMark) (struct TkText *textPtr, const char *name, struct TkTextIndex *indexPtr); /* 164 */\n    int (*tkTextXviewCmd) (struct TkText *textPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv); /* 165 */\n    void (*tkTextChanged) (struct TkSharedText *sharedTextPtr, struct TkText *textPtr, const struct TkTextIndex *index1Ptr, const struct TkTextIndex *index2Ptr); /* 166 */\n    Tcl_Size (*tkBTreeNumLines) (TkTextBTree tree, const struct TkText *textPtr); /* 167 */\n    void (*tkTextInsertDisplayProc) (struct TkText *textPtr, struct TkTextDispChunk *chunkPtr, int x, int y, int height, int baseline, Display *display, Drawable dst, int screenY); /* 168 */\n    int (*tkStateParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 169 */\n    const char * (*tkStatePrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 170 */\n    int (*tkCanvasDashParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 171 */\n    const char * (*tkCanvasDashPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 172 */\n    int (*tkOffsetParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 173 */\n    const char * (*tkOffsetPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 174 */\n    int (*tkPixelParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 175 */\n    const char * (*tkPixelPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 176 */\n    int (*tkOrientParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 177 */\n    const char * (*tkOrientPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 178 */\n    int (*tkSmoothParseProc) (void *clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, Tcl_Size offset); /* 179 */\n    const char * (*tkSmoothPrintProc) (void *clientData, Tk_Window tkwin, char *widgRec, Tcl_Size offset, Tcl_FreeProc **freeProcPtr); /* 180 */\n    void (*tkDrawAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, Tcl_Size firstChar, Tcl_Size lastChar); /* 181 */\n    void (*tkUnderlineAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int underline); /* 182 */\n    int (*tkIntersectAngledTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height, double angle); /* 183 */\n    void (*tkDrawAngledChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, Tcl_Size numBytes, double x, double y, double angle); /* 184 */\n    void (*reserved185)(void);\n    void (*reserved186)(void);\n    bool (*tkDebugPhotoStringMatchDef) (Tcl_Interp *inter, Tcl_Obj *data, Tcl_Obj *formatString, int *widthPtr, int *heightPtr); /* 187 */\n} TkIntStubs;\n\nextern const TkIntStubs *tkIntStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#define TkAllocWindow \\\n\t(tkIntStubsPtr->tkAllocWindow) /* 0 */\n#define TkBezierPoints \\\n\t(tkIntStubsPtr->tkBezierPoints) /* 1 */\n#define TkBezierScreenPoints \\\n\t(tkIntStubsPtr->tkBezierScreenPoints) /* 2 */\n/* Slot 3 is reserved */\n#define TkBindEventProc \\\n\t(tkIntStubsPtr->tkBindEventProc) /* 4 */\n#define TkBindFree \\\n\t(tkIntStubsPtr->tkBindFree) /* 5 */\n#define TkBindInit \\\n\t(tkIntStubsPtr->tkBindInit) /* 6 */\n#define TkChangeEventWindow \\\n\t(tkIntStubsPtr->tkChangeEventWindow) /* 7 */\n#define TkClipInit \\\n\t(tkIntStubsPtr->tkClipInit) /* 8 */\n#define TkComputeAnchor \\\n\t(tkIntStubsPtr->tkComputeAnchor) /* 9 */\n/* Slot 10 is reserved */\n/* Slot 11 is reserved */\n#define TkCreateCursorFromData \\\n\t(tkIntStubsPtr->tkCreateCursorFromData) /* 12 */\n#define TkCreateFrame \\\n\t(tkIntStubsPtr->tkCreateFrame) /* 13 */\n#define TkCreateMainWindow \\\n\t(tkIntStubsPtr->tkCreateMainWindow) /* 14 */\n#define TkCurrentTime \\\n\t(tkIntStubsPtr->tkCurrentTime) /* 15 */\n#define TkDeleteAllImages \\\n\t(tkIntStubsPtr->tkDeleteAllImages) /* 16 */\n#define TkDoConfigureNotify \\\n\t(tkIntStubsPtr->tkDoConfigureNotify) /* 17 */\n#define TkDrawInsetFocusHighlight \\\n\t(tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */\n#define TkEventDeadWindow \\\n\t(tkIntStubsPtr->tkEventDeadWindow) /* 19 */\n#define TkFillPolygon \\\n\t(tkIntStubsPtr->tkFillPolygon) /* 20 */\n#define TkFindStateNum \\\n\t(tkIntStubsPtr->tkFindStateNum) /* 21 */\n#define TkFindStateString \\\n\t(tkIntStubsPtr->tkFindStateString) /* 22 */\n#define TkFocusDeadWindow \\\n\t(tkIntStubsPtr->tkFocusDeadWindow) /* 23 */\n#define TkFocusFilterEvent \\\n\t(tkIntStubsPtr->tkFocusFilterEvent) /* 24 */\n#define TkFocusKeyEvent \\\n\t(tkIntStubsPtr->tkFocusKeyEvent) /* 25 */\n#define TkFontPkgInit \\\n\t(tkIntStubsPtr->tkFontPkgInit) /* 26 */\n#define TkFontPkgFree \\\n\t(tkIntStubsPtr->tkFontPkgFree) /* 27 */\n#define TkFreeBindingTags \\\n\t(tkIntStubsPtr->tkFreeBindingTags) /* 28 */\n#define TkpFreeCursor \\\n\t(tkIntStubsPtr->tkpFreeCursor) /* 29 */\n#define TkGetBitmapData \\\n\t(tkIntStubsPtr->tkGetBitmapData) /* 30 */\n#define TkGetButtPoints \\\n\t(tkIntStubsPtr->tkGetButtPoints) /* 31 */\n#define TkGetCursorByName \\\n\t(tkIntStubsPtr->tkGetCursorByName) /* 32 */\n#define TkGetDefaultScreenName \\\n\t(tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */\n#define TkGetDisplay \\\n\t(tkIntStubsPtr->tkGetDisplay) /* 34 */\n#define TkGetDisplayOf \\\n\t(tkIntStubsPtr->tkGetDisplayOf) /* 35 */\n#define TkGetFocusWin \\\n\t(tkIntStubsPtr->tkGetFocusWin) /* 36 */\n#define TkGetInterpNames \\\n\t(tkIntStubsPtr->tkGetInterpNames) /* 37 */\n#define TkGetMiterPoints \\\n\t(tkIntStubsPtr->tkGetMiterPoints) /* 38 */\n#define TkGetPointerCoords \\\n\t(tkIntStubsPtr->tkGetPointerCoords) /* 39 */\n#define TkGetServerInfo \\\n\t(tkIntStubsPtr->tkGetServerInfo) /* 40 */\n#define TkGrabDeadWindow \\\n\t(tkIntStubsPtr->tkGrabDeadWindow) /* 41 */\n#define TkGrabState \\\n\t(tkIntStubsPtr->tkGrabState) /* 42 */\n#define TkIncludePoint \\\n\t(tkIntStubsPtr->tkIncludePoint) /* 43 */\n#define TkInOutEvents \\\n\t(tkIntStubsPtr->tkInOutEvents) /* 44 */\n#define TkInstallFrameMenu \\\n\t(tkIntStubsPtr->tkInstallFrameMenu) /* 45 */\n#define TkKeysymToString \\\n\t(tkIntStubsPtr->tkKeysymToString) /* 46 */\n#define TkLineToArea \\\n\t(tkIntStubsPtr->tkLineToArea) /* 47 */\n#define TkLineToPoint \\\n\t(tkIntStubsPtr->tkLineToPoint) /* 48 */\n#define TkMakeBezierCurve \\\n\t(tkIntStubsPtr->tkMakeBezierCurve) /* 49 */\n#define TkMakeBezierPostscript \\\n\t(tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */\n#define TkOptionClassChanged \\\n\t(tkIntStubsPtr->tkOptionClassChanged) /* 51 */\n#define TkOptionDeadWindow \\\n\t(tkIntStubsPtr->tkOptionDeadWindow) /* 52 */\n#define TkOvalToArea \\\n\t(tkIntStubsPtr->tkOvalToArea) /* 53 */\n#define TkOvalToPoint \\\n\t(tkIntStubsPtr->tkOvalToPoint) /* 54 */\n#define TkpChangeFocus \\\n\t(tkIntStubsPtr->tkpChangeFocus) /* 55 */\n#define TkpCloseDisplay \\\n\t(tkIntStubsPtr->tkpCloseDisplay) /* 56 */\n#define TkpClaimFocus \\\n\t(tkIntStubsPtr->tkpClaimFocus) /* 57 */\n#define TkpDisplayWarning \\\n\t(tkIntStubsPtr->tkpDisplayWarning) /* 58 */\n#define TkpGetAppName \\\n\t(tkIntStubsPtr->tkpGetAppName) /* 59 */\n/* Slot 60 is reserved */\n#define TkpGetWrapperWindow \\\n\t(tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */\n#define TkpInit \\\n\t(tkIntStubsPtr->tkpInit) /* 62 */\n#define TkpInitializeMenuBindings \\\n\t(tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */\n/* Slot 64 is reserved */\n#define TkpMakeMenuWindow \\\n\t(tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */\n/* Slot 66 is reserved */\n#define TkpMenuNotifyToplevelCreate \\\n\t(tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */\n#define TkpOpenDisplay \\\n\t(tkIntStubsPtr->tkpOpenDisplay) /* 68 */\n#define TkPointerEvent \\\n\t(tkIntStubsPtr->tkPointerEvent) /* 69 */\n#define TkPolygonToArea \\\n\t(tkIntStubsPtr->tkPolygonToArea) /* 70 */\n#define TkPolygonToPoint \\\n\t(tkIntStubsPtr->tkPolygonToPoint) /* 71 */\n#define TkPositionInTree \\\n\t(tkIntStubsPtr->tkPositionInTree) /* 72 */\n#define TkpRedirectKeyEvent \\\n\t(tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */\n/* Slot 74 is reserved */\n/* Slot 75 is reserved */\n/* Slot 76 is reserved */\n#define TkQueueEventForAllChildren \\\n\t(tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */\n#define TkReadBitmapFile \\\n\t(tkIntStubsPtr->tkReadBitmapFile) /* 78 */\n#define TkScrollWindow \\\n\t(tkIntStubsPtr->tkScrollWindow) /* 79 */\n#define TkSelDeadWindow \\\n\t(tkIntStubsPtr->tkSelDeadWindow) /* 80 */\n#define TkSelEventProc \\\n\t(tkIntStubsPtr->tkSelEventProc) /* 81 */\n#define TkSelInit \\\n\t(tkIntStubsPtr->tkSelInit) /* 82 */\n#define TkSelPropProc \\\n\t(tkIntStubsPtr->tkSelPropProc) /* 83 */\n/* Slot 84 is reserved */\n/* Slot 85 is reserved */\n#define TkStringToKeysym \\\n\t(tkIntStubsPtr->tkStringToKeysym) /* 86 */\n#define TkThickPolyLineToArea \\\n\t(tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */\n#define TkWmAddToColormapWindows \\\n\t(tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */\n#define TkWmDeadWindow \\\n\t(tkIntStubsPtr->tkWmDeadWindow) /* 89 */\n#define TkWmFocusToplevel \\\n\t(tkIntStubsPtr->tkWmFocusToplevel) /* 90 */\n#define TkWmMapWindow \\\n\t(tkIntStubsPtr->tkWmMapWindow) /* 91 */\n#define TkWmNewWindow \\\n\t(tkIntStubsPtr->tkWmNewWindow) /* 92 */\n#define TkWmProtocolEventProc \\\n\t(tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */\n#define TkWmRemoveFromColormapWindows \\\n\t(tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */\n#define TkWmRestackToplevel \\\n\t(tkIntStubsPtr->tkWmRestackToplevel) /* 95 */\n#define TkWmSetClass \\\n\t(tkIntStubsPtr->tkWmSetClass) /* 96 */\n#define TkWmUnmapWindow \\\n\t(tkIntStubsPtr->tkWmUnmapWindow) /* 97 */\n#define TkDebugBitmap \\\n\t(tkIntStubsPtr->tkDebugBitmap) /* 98 */\n#define TkDebugBorder \\\n\t(tkIntStubsPtr->tkDebugBorder) /* 99 */\n#define TkDebugCursor \\\n\t(tkIntStubsPtr->tkDebugCursor) /* 100 */\n#define TkDebugColor \\\n\t(tkIntStubsPtr->tkDebugColor) /* 101 */\n#define TkDebugConfig \\\n\t(tkIntStubsPtr->tkDebugConfig) /* 102 */\n#define TkDebugFont \\\n\t(tkIntStubsPtr->tkDebugFont) /* 103 */\n#define TkFindStateNumObj \\\n\t(tkIntStubsPtr->tkFindStateNumObj) /* 104 */\n#define TkGetBitmapPredefTable \\\n\t(tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */\n#define TkGetDisplayList \\\n\t(tkIntStubsPtr->tkGetDisplayList) /* 106 */\n#define TkGetMainInfoList \\\n\t(tkIntStubsPtr->tkGetMainInfoList) /* 107 */\n#define TkGetWindowFromObj \\\n\t(tkIntStubsPtr->tkGetWindowFromObj) /* 108 */\n#define TkpGetString \\\n\t(tkIntStubsPtr->tkpGetString) /* 109 */\n#define TkpGetSubFonts \\\n\t(tkIntStubsPtr->tkpGetSubFonts) /* 110 */\n/* Slot 111 is reserved */\n#define TkpMenuThreadInit \\\n\t(tkIntStubsPtr->tkpMenuThreadInit) /* 112 */\n#define XClipBox \\\n\t(tkIntStubsPtr->xClipBox) /* 113 */\n#define XCreateRegion \\\n\t(tkIntStubsPtr->xCreateRegion) /* 114 */\n#define XDestroyRegion \\\n\t(tkIntStubsPtr->xDestroyRegion) /* 115 */\n#define XIntersectRegion \\\n\t(tkIntStubsPtr->xIntersectRegion) /* 116 */\n#define XRectInRegion \\\n\t(tkIntStubsPtr->xRectInRegion) /* 117 */\n#define XSetRegion \\\n\t(tkIntStubsPtr->xSetRegion) /* 118 */\n#define XUnionRectWithRegion \\\n\t(tkIntStubsPtr->xUnionRectWithRegion) /* 119 */\n/* Slot 120 is reserved */\n#define TkpCreateNativeBitmap \\\n\t(tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */\n#define TkpDefineNativeBitmaps \\\n\t(tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */\n/* Slot 123 is reserved */\n#define TkpGetNativeAppBitmap \\\n\t(tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */\n/* Slot 125 is reserved */\n/* Slot 126 is reserved */\n/* Slot 127 is reserved */\n/* Slot 128 is reserved */\n/* Slot 129 is reserved */\n/* Slot 130 is reserved */\n/* Slot 131 is reserved */\n/* Slot 132 is reserved */\n/* Slot 133 is reserved */\n/* Slot 134 is reserved */\n/* Slot 135 is reserved */\n#define TkSetFocusWin \\\n\t(tkIntStubsPtr->tkSetFocusWin) /* 136 */\n#define TkpSetKeycodeAndState \\\n\t(tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */\n#define TkpGetKeySym \\\n\t(tkIntStubsPtr->tkpGetKeySym) /* 138 */\n#define TkpInitKeymapInfo \\\n\t(tkIntStubsPtr->tkpInitKeymapInfo) /* 139 */\n#define TkPhotoGetValidRegion \\\n\t(tkIntStubsPtr->tkPhotoGetValidRegion) /* 140 */\n#define TkWmStackorderToplevel \\\n\t(tkIntStubsPtr->tkWmStackorderToplevel) /* 141 */\n#define TkFocusFree \\\n\t(tkIntStubsPtr->tkFocusFree) /* 142 */\n#define TkClipCleanup \\\n\t(tkIntStubsPtr->tkClipCleanup) /* 143 */\n#define TkGCCleanup \\\n\t(tkIntStubsPtr->tkGCCleanup) /* 144 */\n#define XSubtractRegion \\\n\t(tkIntStubsPtr->xSubtractRegion) /* 145 */\n#define TkStylePkgInit \\\n\t(tkIntStubsPtr->tkStylePkgInit) /* 146 */\n#define TkStylePkgFree \\\n\t(tkIntStubsPtr->tkStylePkgFree) /* 147 */\n#define TkToplevelWindowForCommand \\\n\t(tkIntStubsPtr->tkToplevelWindowForCommand) /* 148 */\n#define TkGetOptionSpec \\\n\t(tkIntStubsPtr->tkGetOptionSpec) /* 149 */\n#define TkMakeRawCurve \\\n\t(tkIntStubsPtr->tkMakeRawCurve) /* 150 */\n#define TkMakeRawCurvePostscript \\\n\t(tkIntStubsPtr->tkMakeRawCurvePostscript) /* 151 */\n#define TkpDrawFrame \\\n\t(tkIntStubsPtr->tkpDrawFrame) /* 152 */\n#define TkCreateThreadExitHandler \\\n\t(tkIntStubsPtr->tkCreateThreadExitHandler) /* 153 */\n#define TkDeleteThreadExitHandler \\\n\t(tkIntStubsPtr->tkDeleteThreadExitHandler) /* 154 */\n/* Slot 155 is reserved */\n#define TkpTestembedCmd \\\n\t(tkIntStubsPtr->tkpTestembedCmd) /* 156 */\n#define TkpTesttextCmd \\\n\t(tkIntStubsPtr->tkpTesttextCmd) /* 157 */\n#define TkSelGetSelection \\\n\t(tkIntStubsPtr->tkSelGetSelection) /* 158 */\n#define TkTextGetIndex \\\n\t(tkIntStubsPtr->tkTextGetIndex) /* 159 */\n#define TkTextIndexBackBytes \\\n\t(tkIntStubsPtr->tkTextIndexBackBytes) /* 160 */\n#define TkTextIndexForwBytes \\\n\t(tkIntStubsPtr->tkTextIndexForwBytes) /* 161 */\n#define TkTextMakeByteIndex \\\n\t(tkIntStubsPtr->tkTextMakeByteIndex) /* 162 */\n#define TkTextPrintIndex \\\n\t(tkIntStubsPtr->tkTextPrintIndex) /* 163 */\n#define TkTextSetMark \\\n\t(tkIntStubsPtr->tkTextSetMark) /* 164 */\n#define TkTextXviewCmd \\\n\t(tkIntStubsPtr->tkTextXviewCmd) /* 165 */\n#define TkTextChanged \\\n\t(tkIntStubsPtr->tkTextChanged) /* 166 */\n#define TkBTreeNumLines \\\n\t(tkIntStubsPtr->tkBTreeNumLines) /* 167 */\n#define TkTextInsertDisplayProc \\\n\t(tkIntStubsPtr->tkTextInsertDisplayProc) /* 168 */\n#define TkStateParseProc \\\n\t(tkIntStubsPtr->tkStateParseProc) /* 169 */\n#define TkStatePrintProc \\\n\t(tkIntStubsPtr->tkStatePrintProc) /* 170 */\n#define TkCanvasDashParseProc \\\n\t(tkIntStubsPtr->tkCanvasDashParseProc) /* 171 */\n#define TkCanvasDashPrintProc \\\n\t(tkIntStubsPtr->tkCanvasDashPrintProc) /* 172 */\n#define TkOffsetParseProc \\\n\t(tkIntStubsPtr->tkOffsetParseProc) /* 173 */\n#define TkOffsetPrintProc \\\n\t(tkIntStubsPtr->tkOffsetPrintProc) /* 174 */\n#define TkPixelParseProc \\\n\t(tkIntStubsPtr->tkPixelParseProc) /* 175 */\n#define TkPixelPrintProc \\\n\t(tkIntStubsPtr->tkPixelPrintProc) /* 176 */\n#define TkOrientParseProc \\\n\t(tkIntStubsPtr->tkOrientParseProc) /* 177 */\n#define TkOrientPrintProc \\\n\t(tkIntStubsPtr->tkOrientPrintProc) /* 178 */\n#define TkSmoothParseProc \\\n\t(tkIntStubsPtr->tkSmoothParseProc) /* 179 */\n#define TkSmoothPrintProc \\\n\t(tkIntStubsPtr->tkSmoothPrintProc) /* 180 */\n#define TkDrawAngledTextLayout \\\n\t(tkIntStubsPtr->tkDrawAngledTextLayout) /* 181 */\n#define TkUnderlineAngledTextLayout \\\n\t(tkIntStubsPtr->tkUnderlineAngledTextLayout) /* 182 */\n#define TkIntersectAngledTextLayout \\\n\t(tkIntStubsPtr->tkIntersectAngledTextLayout) /* 183 */\n#define TkDrawAngledChars \\\n\t(tkIntStubsPtr->tkDrawAngledChars) /* 184 */\n/* Slot 185 is reserved */\n/* Slot 186 is reserved */\n#define TkDebugPhotoStringMatchDef \\\n\t(tkIntStubsPtr->tkDebugPhotoStringMatchDef) /* 187 */\n\n#endif /* defined(USE_TK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#if !defined(MAC_OSX_TK) && !defined(USE_TK_STUBS)\n#   undef TkpDefineNativeBitmaps\n#   undef TkpCreateNativeBitmap\n#   undef TkpGetNativeAppBitmap\n#   define TkpDefineNativeBitmaps()\n#   define TkpCreateNativeBitmap(display, source) None\n#   define TkpGetNativeAppBitmap(display, name, w, h) None\n#endif\n\n#endif /* _TKINTDECLS */\n"
  },
  {
    "path": "generic/tkIntPlatDecls.h",
    "content": "/*\n * tkIntPlatDecls.h --\n *\n *\tThis file contains the declarations for all platform dependent\n *\tunsupported functions that are exported by the Tk library.  These\n *\tinterfaces are not guaranteed to remain the same between\n *\tversions.  Use at your own risk.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n * All rights reserved.\n */\n\n#ifndef _TKINTPLATDECLS\n#define _TKINTPLATDECLS\n\n#ifdef BUILD_tk\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n#endif\n\n/*\n * WARNING: This file is automatically generated by the tools/genStubs.tcl\n * script.  Any modifications to the function declarations below should be made\n * in the generic/tkInt.decls script.\n */\n\n/* !BEGIN!: Do not edit below this line. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n/* 0 */\nEXTERN void\t\tTkCreateXEventSource(void);\n/* 1 */\nEXTERN void\t\tTkAboutDlg(void);\n/* 2 */\nEXTERN void\t\tTkGenerateActivateEvents(TkWindow *winPtr,\n\t\t\t\tint active);\n/* 3 */\nEXTERN unsigned long\tTkpGetMS(void);\n/* 4 */\nEXTERN void\t\tTkPointerDeadWindow(TkWindow *winPtr);\n/* 5 */\nEXTERN void\t\tTkpPrintWindowId(char *buf, Window window);\n/* 6 */\nEXTERN int\t\tTkpScanWindowId(Tcl_Interp *interp,\n\t\t\t\tconst char *string, Window *idPtr);\n/* 7 */\nEXTERN void\t\tTkpSetCapture(TkWindow *winPtr);\n/* 8 */\nEXTERN void\t\tTkpSetCursor(Cursor cursor);\n/* 9 */\nEXTERN bool\t\tTkpWmSetState(TkWindow *winPtr, int state);\n/* 10 */\nEXTERN void\t\tTkSetPixmapColormap(Pixmap pixmap, Colormap colormap);\n/* Slot 11 is reserved */\n/* 12 */\nEXTERN void\t\tTkWinClipboardRender(TkDisplay *dispPtr, UINT format);\n/* Slot 13 is reserved */\n/* 14 */\nEXTERN void\t\tTkWinFillRect(HDC dc, int x, int y, int width,\n\t\t\t\tint height, int pixel);\n/* 15 */\nEXTERN COLORREF\t\tTkWinGetBorderPixels(Tk_Window tkwin,\n\t\t\t\tTk_3DBorder border, int which);\n/* 16 */\nEXTERN HDC\t\tTkWinGetDrawableDC(Display *display, Drawable d,\n\t\t\t\tTkWinDCState *state);\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n/* 22 */\nEXTERN void\t\tTkWinReleaseDrawableDC(Drawable d, HDC hdc,\n\t\t\t\tTkWinDCState *state);\n/* 23 */\nEXTERN LRESULT\t\tTkWinResendEvent(WNDPROC wndproc, HWND hwnd,\n\t\t\t\tXEvent *eventPtr);\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n/* 26 */\nEXTERN void\t\tTkWinSetWindowPos(HWND hwnd, HWND siblingHwnd,\n\t\t\t\tint pos);\n/* 27 */\nEXTERN void\t\tTkWinWmCleanup(HINSTANCE hInstance);\n/* 28 */\nEXTERN void\t\tTkWinXCleanup(void *clientData);\n/* 29 */\nEXTERN void\t\tTkWinXInit(HINSTANCE hInstance);\n/* 30 */\nEXTERN void\t\tTkWinSetForegroundWindow(TkWindow *winPtr);\n/* 31 */\nEXTERN void\t\tTkWinDialogDebug(int debug);\n/* Slot 32 is reserved */\n/* 33 */\nEXTERN char *\t\tTkAlignImageData(XImage *image, int alignment,\n\t\t\t\tint bitOrder);\n/* 34 */\nEXTERN void\t\tTkWinSetHINSTANCE(HINSTANCE hInstance);\n/* Slot 35 is reserved */\n/* 36 */\nEXTERN LRESULT __stdcall TkWinChildProc(HWND hwnd, UINT message,\n\t\t\t\tWPARAM wParam, LPARAM lParam);\n/* Slot 37 is reserved */\n/* 38 */\nEXTERN bool\t\tTkpCmapStressed(Tk_Window tkwin, Colormap colormap);\n/* 39 */\nEXTERN void\t\tTkpSync(Display *display);\n/* 40 */\nEXTERN Window\t\tTkUnixContainerId(TkWindow *winPtr);\n/* 41 */\nEXTERN bool\t\tTkUnixDoOneXEvent(Tcl_Time *timePtr);\n/* 42 */\nEXTERN void\t\tTkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar);\n/* 43 */\nEXTERN void\t\tTkWmCleanup(TkDisplay *dispPtr);\n/* 44 */\nEXTERN void\t\tTkSendCleanup(TkDisplay *dispPtr);\n/* 45 */\nEXTERN int\t\tTkpTestsendCmd(void *clientData, Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv);\n/* Slot 46 is reserved */\n/* 47 */\nEXTERN Tk_Window\tTkpGetCapture(void);\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n/* Slot 0 is reserved */\n/* 1 */\nEXTERN void\t\tTkAboutDlg(void);\n/* 2 */\nEXTERN void\t\tTkGenerateActivateEvents(TkWindow *winPtr,\n\t\t\t\tint active);\n/* 3 */\nEXTERN unsigned long\tTkpGetMS(void);\n/* 4 */\nEXTERN void\t\tTkPointerDeadWindow(TkWindow *winPtr);\n/* Slot 5 is reserved */\n/* 6 */\nEXTERN int\t\tTkpScanWindowId(Tcl_Interp *interp,\n\t\t\t\tconst char *string, Window *idPtr);\n/* Slot 7 is reserved */\n/* 8 */\nEXTERN void\t\tTkpSetCursor(Cursor cursor);\n/* 9 */\nEXTERN bool\t\tTkpWmSetState(TkWindow *winPtr, int state);\n/* Slot 10 is reserved */\n/* 11 */\nEXTERN void\t\tTkpSetCapture(TkWindow *winPtr);\n/* Slot 12 is reserved */\n/* Slot 13 is reserved */\n/* 14 */\nEXTERN int\t\tTkMacOSXDoHLEvent(void *theEvent);\n/* Slot 15 is reserved */\n/* 16 */\nEXTERN Window\t\tTkMacOSXGetXWindow(void *macWinPtr);\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n/* Slot 22 is reserved */\n/* Slot 23 is reserved */\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n/* Slot 26 is reserved */\n/* Slot 27 is reserved */\n/* Slot 28 is reserved */\n/* Slot 29 is reserved */\n/* Slot 30 is reserved */\n/* Slot 31 is reserved */\n/* 32 */\nEXTERN void\t\tTkMacOSXUpdateClipRgn(TkWindow *winPtr);\n/* Slot 33 is reserved */\n/* Slot 34 is reserved */\n/* 35 */\nEXTERN Region\t\tTkMacOSXVisableClipRgn(TkWindow *winPtr);\n/* 36 */\nEXTERN void\t\tTkMacOSXWinBounds(TkWindow *winPtr, void *geometry);\n/* 37 */\nEXTERN void\t\tTkMacOSXWindowOffset(void *wRef, int *xOffset,\n\t\t\t\tint *yOffset);\n/* 38 */\nEXTERN bool\t\tTkSetMacColor(unsigned long pixel, void *macColor);\n/* 39 */\nEXTERN void\t\tTkSetWMName(TkWindow *winPtr, const char *title);\n/* Slot 40 is reserved */\n/* 41 */\nEXTERN bool\t\tTkMacOSXZoomToplevel(void *whichWindow,\n\t\t\t\tshort zoomPart);\n/* 42 */\nEXTERN Tk_Window\tTk_TopCoordsToWindow(Tk_Window tkwin, int rootX,\n\t\t\t\tint rootY, int *newX, int *newY);\n/* 43 */\nEXTERN MacDrawable *\tTkMacOSXContainerId(TkWindow *winPtr);\n/* 44 */\nEXTERN MacDrawable *\tTkMacOSXGetHostToplevel(TkWindow *winPtr);\n/* Slot 45 is reserved */\n/* Slot 46 is reserved */\n/* 47 */\nEXTERN Tk_Window\tTkpGetCapture(void);\n/* Slot 48 is reserved */\n/* 49 */\nEXTERN Tk_Window\tTkMacOSXGetContainer(TkWindow *winPtr);\n#endif /* AQUA */\n#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */\n/* 0 */\nEXTERN void\t\tTkCreateXEventSource(void);\n/* 1 */\nEXTERN void\t\tTkAboutDlg(void);\n/* 2 */\nEXTERN void\t\tTkGenerateActivateEvents(TkWindow *winPtr,\n\t\t\t\tint active);\n/* Slot 3 is reserved */\n/* Slot 4 is reserved */\n/* Slot 5 is reserved */\n/* 6 */\nEXTERN int\t\tTkpScanWindowId(Tcl_Interp *interp,\n\t\t\t\tconst char *string, Window *idPtr);\n/* Slot 7 is reserved */\n/* Slot 8 is reserved */\n/* 9 */\nEXTERN bool\t\tTkpWmSetState(TkWindow *winPtr, int state);\n/* Slot 10 is reserved */\n/* Slot 11 is reserved */\n/* Slot 12 is reserved */\n/* Slot 13 is reserved */\n/* Slot 14 is reserved */\n/* Slot 15 is reserved */\n/* Slot 16 is reserved */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n/* Slot 22 is reserved */\n/* Slot 23 is reserved */\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n/* Slot 26 is reserved */\n/* Slot 27 is reserved */\n/* Slot 28 is reserved */\n/* Slot 29 is reserved */\n/* Slot 30 is reserved */\n/* Slot 31 is reserved */\n/* Slot 32 is reserved */\n/* Slot 33 is reserved */\n/* Slot 34 is reserved */\n/* Slot 35 is reserved */\n/* Slot 36 is reserved */\n/* Slot 37 is reserved */\n/* 38 */\nEXTERN bool\t\tTkpCmapStressed(Tk_Window tkwin, Colormap colormap);\n/* 39 */\nEXTERN void\t\tTkpSync(Display *display);\n/* 40 */\nEXTERN Window\t\tTkUnixContainerId(TkWindow *winPtr);\n/* 41 */\nEXTERN bool\t\tTkUnixDoOneXEvent(Tcl_Time *timePtr);\n/* 42 */\nEXTERN void\t\tTkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar);\n/* 43 */\nEXTERN void\t\tTkWmCleanup(TkDisplay *dispPtr);\n/* 44 */\nEXTERN void\t\tTkSendCleanup(TkDisplay *dispPtr);\n/* 45 */\nEXTERN int\t\tTkpTestsendCmd(void *clientData, Tcl_Interp *interp,\n\t\t\t\tTcl_Size objc, Tcl_Obj *const *objv);\n#endif /* X11 */\n\ntypedef struct TkIntPlatStubs {\n    int magic;\n    void *hooks;\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n    void (*tkCreateXEventSource) (void); /* 0 */\n    void (*tkAboutDlg) (void); /* 1 */\n    void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */\n    unsigned long (*tkpGetMS) (void); /* 3 */\n    void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 4 */\n    void (*tkpPrintWindowId) (char *buf, Window window); /* 5 */\n    int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 6 */\n    void (*tkpSetCapture) (TkWindow *winPtr); /* 7 */\n    void (*tkpSetCursor) (Cursor cursor); /* 8 */\n    bool (*tkpWmSetState) (TkWindow *winPtr, int state); /* 9 */\n    void (*tkSetPixmapColormap) (Pixmap pixmap, Colormap colormap); /* 10 */\n    void (*reserved11)(void);\n    void (*tkWinClipboardRender) (TkDisplay *dispPtr, UINT format); /* 12 */\n    void (*reserved13)(void);\n    void (*tkWinFillRect) (HDC dc, int x, int y, int width, int height, int pixel); /* 14 */\n    COLORREF (*tkWinGetBorderPixels) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 15 */\n    HDC (*tkWinGetDrawableDC) (Display *display, Drawable d, TkWinDCState *state); /* 16 */\n    void (*reserved17)(void);\n    void (*reserved18)(void);\n    void (*reserved19)(void);\n    void (*reserved20)(void);\n    void (*reserved21)(void);\n    void (*tkWinReleaseDrawableDC) (Drawable d, HDC hdc, TkWinDCState *state); /* 22 */\n    LRESULT (*tkWinResendEvent) (WNDPROC wndproc, HWND hwnd, XEvent *eventPtr); /* 23 */\n    void (*reserved24)(void);\n    void (*reserved25)(void);\n    void (*tkWinSetWindowPos) (HWND hwnd, HWND siblingHwnd, int pos); /* 26 */\n    void (*tkWinWmCleanup) (HINSTANCE hInstance); /* 27 */\n    void (*tkWinXCleanup) (void *clientData); /* 28 */\n    void (*tkWinXInit) (HINSTANCE hInstance); /* 29 */\n    void (*tkWinSetForegroundWindow) (TkWindow *winPtr); /* 30 */\n    void (*tkWinDialogDebug) (int debug); /* 31 */\n    void (*reserved32)(void);\n    char * (*tkAlignImageData) (XImage *image, int alignment, int bitOrder); /* 33 */\n    void (*tkWinSetHINSTANCE) (HINSTANCE hInstance); /* 34 */\n    void (*reserved35)(void);\n    LRESULT (__stdcall *tkWinChildProc) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* 36 */\n    void (*reserved37)(void);\n    bool (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 38 */\n    void (*tkpSync) (Display *display); /* 39 */\n    Window (*tkUnixContainerId) (TkWindow *winPtr); /* 40 */\n    bool (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 41 */\n    void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 42 */\n    void (*tkWmCleanup) (TkDisplay *dispPtr); /* 43 */\n    void (*tkSendCleanup) (TkDisplay *dispPtr); /* 44 */\n    int (*tkpTestsendCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv); /* 45 */\n    void (*reserved46)(void);\n    Tk_Window (*tkpGetCapture) (void); /* 47 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n    void (*reserved0)(void);\n    void (*tkAboutDlg) (void); /* 1 */\n    void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */\n    unsigned long (*tkpGetMS) (void); /* 3 */\n    void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 4 */\n    void (*reserved5)(void);\n    int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 6 */\n    void (*reserved7)(void);\n    void (*tkpSetCursor) (Cursor cursor); /* 8 */\n    bool (*tkpWmSetState) (TkWindow *winPtr, int state); /* 9 */\n    void (*reserved10)(void);\n    void (*tkpSetCapture) (TkWindow *winPtr); /* 11 */\n    void (*reserved12)(void);\n    void (*reserved13)(void);\n    int (*tkMacOSXDoHLEvent) (void *theEvent); /* 14 */\n    void (*reserved15)(void);\n    Window (*tkMacOSXGetXWindow) (void *macWinPtr); /* 16 */\n    void (*reserved17)(void);\n    void (*reserved18)(void);\n    void (*reserved19)(void);\n    void (*reserved20)(void);\n    void (*reserved21)(void);\n    void (*reserved22)(void);\n    void (*reserved23)(void);\n    void (*reserved24)(void);\n    void (*reserved25)(void);\n    void (*reserved26)(void);\n    void (*reserved27)(void);\n    void (*reserved28)(void);\n    void (*reserved29)(void);\n    void (*reserved30)(void);\n    void (*reserved31)(void);\n    void (*tkMacOSXUpdateClipRgn) (TkWindow *winPtr); /* 32 */\n    void (*reserved33)(void);\n    void (*reserved34)(void);\n    Region (*tkMacOSXVisableClipRgn) (TkWindow *winPtr); /* 35 */\n    void (*tkMacOSXWinBounds) (TkWindow *winPtr, void *geometry); /* 36 */\n    void (*tkMacOSXWindowOffset) (void *wRef, int *xOffset, int *yOffset); /* 37 */\n    bool (*tkSetMacColor) (unsigned long pixel, void *macColor); /* 38 */\n    void (*tkSetWMName) (TkWindow *winPtr, const char *title); /* 39 */\n    void (*reserved40)(void);\n    bool (*tkMacOSXZoomToplevel) (void *whichWindow, short zoomPart); /* 41 */\n    Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */\n    MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */\n    MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */\n    void (*reserved45)(void);\n    void (*reserved46)(void);\n    Tk_Window (*tkpGetCapture) (void); /* 47 */\n    void (*reserved48)(void);\n    Tk_Window (*tkMacOSXGetContainer) (TkWindow *winPtr); /* 49 */\n#endif /* AQUA */\n#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */\n    void (*tkCreateXEventSource) (void); /* 0 */\n    void (*tkAboutDlg) (void); /* 1 */\n    void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */\n    void (*reserved3)(void);\n    void (*reserved4)(void);\n    void (*reserved5)(void);\n    int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 6 */\n    void (*reserved7)(void);\n    void (*reserved8)(void);\n    bool (*tkpWmSetState) (TkWindow *winPtr, int state); /* 9 */\n    void (*reserved10)(void);\n    void (*reserved11)(void);\n    void (*reserved12)(void);\n    void (*reserved13)(void);\n    void (*reserved14)(void);\n    void (*reserved15)(void);\n    void (*reserved16)(void);\n    void (*reserved17)(void);\n    void (*reserved18)(void);\n    void (*reserved19)(void);\n    void (*reserved20)(void);\n    void (*reserved21)(void);\n    void (*reserved22)(void);\n    void (*reserved23)(void);\n    void (*reserved24)(void);\n    void (*reserved25)(void);\n    void (*reserved26)(void);\n    void (*reserved27)(void);\n    void (*reserved28)(void);\n    void (*reserved29)(void);\n    void (*reserved30)(void);\n    void (*reserved31)(void);\n    void (*reserved32)(void);\n    void (*reserved33)(void);\n    void (*reserved34)(void);\n    void (*reserved35)(void);\n    void (*reserved36)(void);\n    void (*reserved37)(void);\n    bool (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 38 */\n    void (*tkpSync) (Display *display); /* 39 */\n    Window (*tkUnixContainerId) (TkWindow *winPtr); /* 40 */\n    bool (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 41 */\n    void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 42 */\n    void (*tkWmCleanup) (TkDisplay *dispPtr); /* 43 */\n    void (*tkSendCleanup) (TkDisplay *dispPtr); /* 44 */\n    int (*tkpTestsendCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv); /* 45 */\n#endif /* X11 */\n} TkIntPlatStubs;\n\nextern const TkIntPlatStubs *tkIntPlatStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n#define TkCreateXEventSource \\\n\t(tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */\n#define TkAboutDlg \\\n\t(tkIntPlatStubsPtr->tkAboutDlg) /* 1 */\n#define TkGenerateActivateEvents \\\n\t(tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */\n#define TkpGetMS \\\n\t(tkIntPlatStubsPtr->tkpGetMS) /* 3 */\n#define TkPointerDeadWindow \\\n\t(tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */\n#define TkpPrintWindowId \\\n\t(tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */\n#define TkpScanWindowId \\\n\t(tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */\n#define TkpSetCapture \\\n\t(tkIntPlatStubsPtr->tkpSetCapture) /* 7 */\n#define TkpSetCursor \\\n\t(tkIntPlatStubsPtr->tkpSetCursor) /* 8 */\n#define TkpWmSetState \\\n\t(tkIntPlatStubsPtr->tkpWmSetState) /* 9 */\n#define TkSetPixmapColormap \\\n\t(tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */\n/* Slot 11 is reserved */\n#define TkWinClipboardRender \\\n\t(tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */\n/* Slot 13 is reserved */\n#define TkWinFillRect \\\n\t(tkIntPlatStubsPtr->tkWinFillRect) /* 14 */\n#define TkWinGetBorderPixels \\\n\t(tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */\n#define TkWinGetDrawableDC \\\n\t(tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n#define TkWinReleaseDrawableDC \\\n\t(tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */\n#define TkWinResendEvent \\\n\t(tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n#define TkWinSetWindowPos \\\n\t(tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */\n#define TkWinWmCleanup \\\n\t(tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */\n#define TkWinXCleanup \\\n\t(tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */\n#define TkWinXInit \\\n\t(tkIntPlatStubsPtr->tkWinXInit) /* 29 */\n#define TkWinSetForegroundWindow \\\n\t(tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */\n#define TkWinDialogDebug \\\n\t(tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */\n/* Slot 32 is reserved */\n#define TkAlignImageData \\\n\t(tkIntPlatStubsPtr->tkAlignImageData) /* 33 */\n#define TkWinSetHINSTANCE \\\n\t(tkIntPlatStubsPtr->tkWinSetHINSTANCE) /* 34 */\n/* Slot 35 is reserved */\n#define TkWinChildProc \\\n\t(tkIntPlatStubsPtr->tkWinChildProc) /* 36 */\n/* Slot 37 is reserved */\n#define TkpCmapStressed \\\n\t(tkIntPlatStubsPtr->tkpCmapStressed) /* 38 */\n#define TkpSync \\\n\t(tkIntPlatStubsPtr->tkpSync) /* 39 */\n#define TkUnixContainerId \\\n\t(tkIntPlatStubsPtr->tkUnixContainerId) /* 40 */\n#define TkUnixDoOneXEvent \\\n\t(tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 41 */\n#define TkUnixSetMenubar \\\n\t(tkIntPlatStubsPtr->tkUnixSetMenubar) /* 42 */\n#define TkWmCleanup \\\n\t(tkIntPlatStubsPtr->tkWmCleanup) /* 43 */\n#define TkSendCleanup \\\n\t(tkIntPlatStubsPtr->tkSendCleanup) /* 44 */\n#define TkpTestsendCmd \\\n\t(tkIntPlatStubsPtr->tkpTestsendCmd) /* 45 */\n/* Slot 46 is reserved */\n#define TkpGetCapture \\\n\t(tkIntPlatStubsPtr->tkpGetCapture) /* 47 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n/* Slot 0 is reserved */\n#define TkAboutDlg \\\n\t(tkIntPlatStubsPtr->tkAboutDlg) /* 1 */\n#define TkGenerateActivateEvents \\\n\t(tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */\n#define TkpGetMS \\\n\t(tkIntPlatStubsPtr->tkpGetMS) /* 3 */\n#define TkPointerDeadWindow \\\n\t(tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */\n/* Slot 5 is reserved */\n#define TkpScanWindowId \\\n\t(tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */\n/* Slot 7 is reserved */\n#define TkpSetCursor \\\n\t(tkIntPlatStubsPtr->tkpSetCursor) /* 8 */\n#define TkpWmSetState \\\n\t(tkIntPlatStubsPtr->tkpWmSetState) /* 9 */\n/* Slot 10 is reserved */\n#define TkpSetCapture \\\n\t(tkIntPlatStubsPtr->tkpSetCapture) /* 11 */\n/* Slot 12 is reserved */\n/* Slot 13 is reserved */\n#define TkMacOSXDoHLEvent \\\n\t(tkIntPlatStubsPtr->tkMacOSXDoHLEvent) /* 14 */\n/* Slot 15 is reserved */\n#define TkMacOSXGetXWindow \\\n\t(tkIntPlatStubsPtr->tkMacOSXGetXWindow) /* 16 */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n/* Slot 22 is reserved */\n/* Slot 23 is reserved */\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n/* Slot 26 is reserved */\n/* Slot 27 is reserved */\n/* Slot 28 is reserved */\n/* Slot 29 is reserved */\n/* Slot 30 is reserved */\n/* Slot 31 is reserved */\n#define TkMacOSXUpdateClipRgn \\\n\t(tkIntPlatStubsPtr->tkMacOSXUpdateClipRgn) /* 32 */\n/* Slot 33 is reserved */\n/* Slot 34 is reserved */\n#define TkMacOSXVisableClipRgn \\\n\t(tkIntPlatStubsPtr->tkMacOSXVisableClipRgn) /* 35 */\n#define TkMacOSXWinBounds \\\n\t(tkIntPlatStubsPtr->tkMacOSXWinBounds) /* 36 */\n#define TkMacOSXWindowOffset \\\n\t(tkIntPlatStubsPtr->tkMacOSXWindowOffset) /* 37 */\n#define TkSetMacColor \\\n\t(tkIntPlatStubsPtr->tkSetMacColor) /* 38 */\n#define TkSetWMName \\\n\t(tkIntPlatStubsPtr->tkSetWMName) /* 39 */\n/* Slot 40 is reserved */\n#define TkMacOSXZoomToplevel \\\n\t(tkIntPlatStubsPtr->tkMacOSXZoomToplevel) /* 41 */\n#define Tk_TopCoordsToWindow \\\n\t(tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 42 */\n#define TkMacOSXContainerId \\\n\t(tkIntPlatStubsPtr->tkMacOSXContainerId) /* 43 */\n#define TkMacOSXGetHostToplevel \\\n\t(tkIntPlatStubsPtr->tkMacOSXGetHostToplevel) /* 44 */\n/* Slot 45 is reserved */\n/* Slot 46 is reserved */\n#define TkpGetCapture \\\n\t(tkIntPlatStubsPtr->tkpGetCapture) /* 47 */\n/* Slot 48 is reserved */\n#define TkMacOSXGetContainer \\\n\t(tkIntPlatStubsPtr->tkMacOSXGetContainer) /* 49 */\n#endif /* AQUA */\n#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */\n#define TkCreateXEventSource \\\n\t(tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */\n#define TkAboutDlg \\\n\t(tkIntPlatStubsPtr->tkAboutDlg) /* 1 */\n#define TkGenerateActivateEvents \\\n\t(tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */\n/* Slot 3 is reserved */\n/* Slot 4 is reserved */\n/* Slot 5 is reserved */\n#define TkpScanWindowId \\\n\t(tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */\n/* Slot 7 is reserved */\n/* Slot 8 is reserved */\n#define TkpWmSetState \\\n\t(tkIntPlatStubsPtr->tkpWmSetState) /* 9 */\n/* Slot 10 is reserved */\n/* Slot 11 is reserved */\n/* Slot 12 is reserved */\n/* Slot 13 is reserved */\n/* Slot 14 is reserved */\n/* Slot 15 is reserved */\n/* Slot 16 is reserved */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* Slot 20 is reserved */\n/* Slot 21 is reserved */\n/* Slot 22 is reserved */\n/* Slot 23 is reserved */\n/* Slot 24 is reserved */\n/* Slot 25 is reserved */\n/* Slot 26 is reserved */\n/* Slot 27 is reserved */\n/* Slot 28 is reserved */\n/* Slot 29 is reserved */\n/* Slot 30 is reserved */\n/* Slot 31 is reserved */\n/* Slot 32 is reserved */\n/* Slot 33 is reserved */\n/* Slot 34 is reserved */\n/* Slot 35 is reserved */\n/* Slot 36 is reserved */\n/* Slot 37 is reserved */\n#define TkpCmapStressed \\\n\t(tkIntPlatStubsPtr->tkpCmapStressed) /* 38 */\n#define TkpSync \\\n\t(tkIntPlatStubsPtr->tkpSync) /* 39 */\n#define TkUnixContainerId \\\n\t(tkIntPlatStubsPtr->tkUnixContainerId) /* 40 */\n#define TkUnixDoOneXEvent \\\n\t(tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 41 */\n#define TkUnixSetMenubar \\\n\t(tkIntPlatStubsPtr->tkUnixSetMenubar) /* 42 */\n#define TkWmCleanup \\\n\t(tkIntPlatStubsPtr->tkWmCleanup) /* 43 */\n#define TkSendCleanup \\\n\t(tkIntPlatStubsPtr->tkSendCleanup) /* 44 */\n#define TkpTestsendCmd \\\n\t(tkIntPlatStubsPtr->tkpTestsendCmd) /* 45 */\n#endif /* X11 */\n\n#endif /* defined(USE_TK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#ifdef _WIN32\n#   undef TkpCmapStressed\n#   undef TkpSync\n#   define TkpCmapStressed(win, colormap) ((void)(win), (void)(colormap), false)\n#   define TkpSync(display) (void)(display)\n#endif\n\n#ifndef TK_NO_DEPRECATED\n#   define TkMacOSXDrawable Tk_MacOSXGetNSWindowForDrawable\n#   define TkWinGetPlatformTheme() (3)\n#endif\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#endif /* _TKINTPLATDECLS */\n"
  },
  {
    "path": "generic/tkIntXlibDecls.h",
    "content": "/*\n * tkIntXlibDecls.h --\n *\n *\tThis file contains the declarations for all platform dependent\n *\tunsupported functions that are exported by the Tk library.  These\n *\tinterfaces are not guaranteed to remain the same between\n *\tversions.  Use at your own risk.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n * All rights reserved.\n */\n\n#ifndef _TKINTXLIBDECLS\n#define _TKINTXLIBDECLS\n\n/*\n * WARNING: This file is automatically generated by the tools/genStubs.tcl\n * script.  Any modifications to the function declarations below should be made\n * in the generic/tkInt.decls script.\n */\n\n#ifndef _TCL\n#   include <tcl.h>\n#endif\n\n#ifndef EXTERN\n#   define EXTERN extern TCL_STORAGE_CLASS\n#endif\n\n#include \"X11/Xutil.h\"\n\n#ifdef BUILD_tk\n#  undef TCL_STORAGE_CLASS\n#  define TCL_STORAGE_CLASS DLLEXPORT\n#else\n#  ifndef TCL_STORAGE_CLASS\n#    define TCL_STORAGE_CLASS DLLIMPORT\n#  endif\n#endif\n\n#if defined(MAC_OSX_TK) && !defined(MAC_OSX_TCL)\n#  define MAC_OSX_TCL 1\n#endif\n\ntypedef int (*XAfterFunction) (\t    /* WARNING, this type not in Xlib spec */\n    Display*\t\t/* display */\n);\n\n/* !BEGIN!: Do not edit below this line. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n/* 0 */\nEXTERN int\t\tXSetDashes(Display *display, GC gc, int dash_offset,\n\t\t\t\tconst char *dash_list, int n);\n/* 1 */\nEXTERN XModifierKeymap * XGetModifierMapping(Display *d);\n/* 2 */\nEXTERN XImage *\t\tXCreateImage(Display *d, Visual *v, unsigned int ui1,\n\t\t\t\tint i1, int i2, char *cp, unsigned int ui2,\n\t\t\t\tunsigned int ui3, int i3, int i4);\n/* 3 */\nEXTERN XImage *\t\tXGetImage(Display *d, Drawable dr, int i1, int i2,\n\t\t\t\tunsigned int ui1, unsigned int ui2,\n\t\t\t\tunsigned long ul, int i3);\n/* 4 */\nEXTERN char *\t\tXGetAtomName(Display *d, Atom a);\n/* 5 */\nEXTERN char *\t\tXKeysymToString(KeySym k);\n/* 6 */\nEXTERN Colormap\t\tXCreateColormap(Display *d, Window w, Visual *v,\n\t\t\t\tint i);\n/* 7 */\nEXTERN Cursor\t\tXCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,\n\t\t\t\tXColor *x1, XColor *x2, unsigned int ui1,\n\t\t\t\tunsigned int ui2);\n/* 8 */\nEXTERN Cursor\t\tXCreateGlyphCursor(Display *d, Font f1, Font f2,\n\t\t\t\tunsigned int ui1, unsigned int ui2,\n\t\t\t\tXColor const *x1, XColor const *x2);\n/* 9 */\nEXTERN GContext\t\tXGContextFromGC(GC g);\n/* 10 */\nEXTERN XHostAddress *\tXListHosts(Display *d, int *i, Bool *b);\n/* Slot 11 is reserved */\n/* 12 */\nEXTERN KeySym\t\tXStringToKeysym(const char *c);\n/* 13 */\nEXTERN Window\t\tXRootWindow(Display *d, int i);\n/* 14 */\nEXTERN XErrorHandler\tXSetErrorHandler(XErrorHandler x);\n/* 15 */\nEXTERN Status\t\tXIconifyWindow(Display *d, Window w, int i);\n/* 16 */\nEXTERN Status\t\tXWithdrawWindow(Display *d, Window w, int i);\n/* 17 */\nEXTERN Status\t\tXGetWMColormapWindows(Display *d, Window w,\n\t\t\t\tWindow **wpp, int *ip);\n/* 18 */\nEXTERN Status\t\tXAllocColor(Display *d, Colormap c, XColor *xp);\n/* 19 */\nEXTERN int\t\tXBell(Display *d, int i);\n/* 20 */\nEXTERN int\t\tXChangeProperty(Display *d, Window w, Atom a1,\n\t\t\t\tAtom a2, int i1, int i2,\n\t\t\t\tconst unsigned char *c, int i3);\n/* 21 */\nEXTERN int\t\tXChangeWindowAttributes(Display *d, Window w,\n\t\t\t\tunsigned long ul, XSetWindowAttributes *x);\n/* 22 */\nEXTERN int\t\tXClearWindow(Display *d, Window w);\n/* 23 */\nEXTERN int\t\tXConfigureWindow(Display *d, Window w,\n\t\t\t\tunsigned int i, XWindowChanges *x);\n/* 24 */\nEXTERN int\t\tXCopyArea(Display *d, Drawable dr1, Drawable dr2,\n\t\t\t\tGC g, int i1, int i2, unsigned int ui1,\n\t\t\t\tunsigned int ui2, int i3, int i4);\n/* 25 */\nEXTERN int\t\tXCopyPlane(Display *d, Drawable dr1, Drawable dr2,\n\t\t\t\tGC g, int i1, int i2, unsigned int ui1,\n\t\t\t\tunsigned int ui2, int i3, int i4,\n\t\t\t\tunsigned long ul);\n/* 26 */\nEXTERN Pixmap\t\tXCreateBitmapFromData(Display *display, Drawable d,\n\t\t\t\tconst char *data, unsigned int width,\n\t\t\t\tunsigned int height);\n/* 27 */\nEXTERN int\t\tXDefineCursor(Display *d, Window w, Cursor c);\n/* 28 */\nEXTERN int\t\tXDeleteProperty(Display *d, Window w, Atom a);\n/* 29 */\nEXTERN int\t\tXDestroyWindow(Display *d, Window w);\n/* 30 */\nEXTERN int\t\tXDrawArc(Display *d, Drawable dr, GC g, int i1,\n\t\t\t\tint i2, unsigned int ui1, unsigned int ui2,\n\t\t\t\tint i3, int i4);\n/* 31 */\nEXTERN int\t\tXDrawLines(Display *d, Drawable dr, GC g, XPoint *x,\n\t\t\t\tint i1, int i2);\n/* 32 */\nEXTERN int\t\tXDrawRectangle(Display *d, Drawable dr, GC g, int i1,\n\t\t\t\tint i2, unsigned int ui1, unsigned int ui2);\n/* 33 */\nEXTERN int\t\tXFillArc(Display *d, Drawable dr, GC g, int i1,\n\t\t\t\tint i2, unsigned int ui1, unsigned int ui2,\n\t\t\t\tint i3, int i4);\n/* 34 */\nEXTERN int\t\tXFillPolygon(Display *d, Drawable dr, GC g,\n\t\t\t\tXPoint *x, int i1, int i2, int i3);\n/* 35 */\nEXTERN int\t\tXFillRectangles(Display *d, Drawable dr, GC g,\n\t\t\t\tXRectangle *x, int i);\n/* 36 */\nEXTERN int\t\tXForceScreenSaver(Display *d, int i);\n/* 37 */\nEXTERN int\t\tXFreeColormap(Display *d, Colormap c);\n/* 38 */\nEXTERN int\t\tXFreeColors(Display *d, Colormap c,\n\t\t\t\tunsigned long *ulp, int i, unsigned long ul);\n/* 39 */\nEXTERN int\t\tXFreeCursor(Display *d, Cursor c);\n/* 40 */\nEXTERN int\t\tXFreeModifiermap(XModifierKeymap *x);\n/* 41 */\nEXTERN Status\t\tXGetGeometry(Display *d, Drawable dr, Window *w,\n\t\t\t\tint *i1, int *i2, unsigned int *ui1,\n\t\t\t\tunsigned int *ui2, unsigned int *ui3,\n\t\t\t\tunsigned int *ui4);\n/* 42 */\nEXTERN int\t\tXGetInputFocus(Display *d, Window *w, int *i);\n/* 43 */\nEXTERN int\t\tXGetWindowProperty(Display *d, Window w, Atom a1,\n\t\t\t\tlong l1, long l2, Bool b, Atom a2, Atom *ap,\n\t\t\t\tint *ip, unsigned long *ulp1,\n\t\t\t\tunsigned long *ulp2, unsigned char **cpp);\n/* 44 */\nEXTERN Status\t\tXGetWindowAttributes(Display *d, Window w,\n\t\t\t\tXWindowAttributes *x);\n/* 45 */\nEXTERN int\t\tXGrabKeyboard(Display *d, Window w, Bool b, int i1,\n\t\t\t\tint i2, Time t);\n/* 46 */\nEXTERN int\t\tXGrabPointer(Display *d, Window w1, Bool b,\n\t\t\t\tunsigned int ui, int i1, int i2, Window w2,\n\t\t\t\tCursor c, Time t);\n/* 47 */\nEXTERN KeyCode\t\tXKeysymToKeycode(Display *d, KeySym k);\n/* 48 */\nEXTERN Status\t\tXLookupColor(Display *d, Colormap c1, const char *c2,\n\t\t\t\tXColor *x1, XColor *x2);\n/* 49 */\nEXTERN int\t\tXMapWindow(Display *d, Window w);\n/* 50 */\nEXTERN int\t\tXMoveResizeWindow(Display *d, Window w, int i1,\n\t\t\t\tint i2, unsigned int ui1, unsigned int ui2);\n/* 51 */\nEXTERN int\t\tXMoveWindow(Display *d, Window w, int i1, int i2);\n/* 52 */\nEXTERN int\t\tXNextEvent(Display *d, XEvent *x);\n/* 53 */\nEXTERN int\t\tXPutBackEvent(Display *d, XEvent *x);\n/* 54 */\nEXTERN int\t\tXQueryColors(Display *d, Colormap c, XColor *x,\n\t\t\t\tint i);\n/* 55 */\nEXTERN Bool\t\tXQueryPointer(Display *d, Window w1, Window *w2,\n\t\t\t\tWindow *w3, int *i1, int *i2, int *i3,\n\t\t\t\tint *i4, unsigned int *ui);\n/* 56 */\nEXTERN Status\t\tXQueryTree(Display *d, Window w1, Window *w2,\n\t\t\t\tWindow *w3, Window **w4, unsigned int *ui);\n/* 57 */\nEXTERN int\t\tXRaiseWindow(Display *d, Window w);\n/* 58 */\nEXTERN int\t\tXRefreshKeyboardMapping(XMappingEvent *x);\n/* 59 */\nEXTERN int\t\tXResizeWindow(Display *d, Window w, unsigned int ui1,\n\t\t\t\tunsigned int ui2);\n/* 60 */\nEXTERN int\t\tXSelectInput(Display *d, Window w, long l);\n/* 61 */\nEXTERN Status\t\tXSendEvent(Display *d, Window w, Bool b, long l,\n\t\t\t\tXEvent *x);\n/* 62 */\nEXTERN int\t\tXSetCommand(Display *d, Window w, char **c, int i);\n/* 63 */\nEXTERN int\t\tXSetIconName(Display *d, Window w, const char *c);\n/* 64 */\nEXTERN int\t\tXSetInputFocus(Display *d, Window w, int i, Time t);\n/* 65 */\nEXTERN int\t\tXSetSelectionOwner(Display *d, Atom a, Window w,\n\t\t\t\tTime t);\n/* 66 */\nEXTERN int\t\tXSetWindowBackground(Display *d, Window w,\n\t\t\t\tunsigned long ul);\n/* 67 */\nEXTERN int\t\tXSetWindowBackgroundPixmap(Display *d, Window w,\n\t\t\t\tPixmap p);\n/* 68 */\nEXTERN int\t\tXSetWindowBorder(Display *d, Window w,\n\t\t\t\tunsigned long ul);\n/* 69 */\nEXTERN int\t\tXSetWindowBorderPixmap(Display *d, Window w,\n\t\t\t\tPixmap p);\n/* 70 */\nEXTERN int\t\tXSetWindowBorderWidth(Display *d, Window w,\n\t\t\t\tunsigned int ui);\n/* 71 */\nEXTERN int\t\tXSetWindowColormap(Display *d, Window w, Colormap c);\n/* 72 */\nEXTERN Bool\t\tXTranslateCoordinates(Display *d, Window w1,\n\t\t\t\tWindow w2, int i1, int i2, int *i3, int *i4,\n\t\t\t\tWindow *w3);\n/* 73 */\nEXTERN int\t\tXUngrabKeyboard(Display *d, Time t);\n/* 74 */\nEXTERN int\t\tXUngrabPointer(Display *d, Time t);\n/* 75 */\nEXTERN int\t\tXUnmapWindow(Display *d, Window w);\n/* 76 */\nEXTERN int\t\tXWindowEvent(Display *d, Window w, long l, XEvent *x);\n/* 77 */\nEXTERN void\t\tXDestroyIC(XIC x);\n/* 78 */\nEXTERN Bool\t\tXFilterEvent(XEvent *x, Window w);\n/* 79 */\nEXTERN int\t\tXmbLookupString(XIC xi, XKeyPressedEvent *xk,\n\t\t\t\tchar *c, int i, KeySym *k, Status *s);\n/* 80 */\nEXTERN int\t\tTkPutImage(unsigned long *colors, int ncolors,\n\t\t\t\tDisplay *display, Drawable d, GC gc,\n\t\t\t\tXImage *image, int src_x, int src_y,\n\t\t\t\tint dest_x, int dest_y, unsigned int width,\n\t\t\t\tunsigned int height);\n/* 81 */\nEXTERN int\t\tXSetClipRectangles(Display *display, GC gc,\n\t\t\t\tint clip_x_origin, int clip_y_origin,\n\t\t\t\tXRectangle *rectangles, int n, int ordering);\n/* 82 */\nEXTERN Status\t\tXParseColor(Display *display, Colormap map,\n\t\t\t\tconst char *spec, XColor *colorPtr);\n/* 83 */\nEXTERN GC\t\tXCreateGC(Display *display, Drawable d,\n\t\t\t\tunsigned long valuemask, XGCValues *values);\n/* 84 */\nEXTERN int\t\tXFreeGC(Display *display, GC gc);\n/* 85 */\nEXTERN Atom\t\tXInternAtom(Display *display, const char *atom_name,\n\t\t\t\tBool only_if_exists);\n/* 86 */\nEXTERN int\t\tXSetBackground(Display *display, GC gc,\n\t\t\t\tunsigned long foreground);\n/* 87 */\nEXTERN int\t\tXSetForeground(Display *display, GC gc,\n\t\t\t\tunsigned long foreground);\n/* 88 */\nEXTERN int\t\tXSetClipMask(Display *display, GC gc, Pixmap pixmap);\n/* 89 */\nEXTERN int\t\tXSetClipOrigin(Display *display, GC gc,\n\t\t\t\tint clip_x_origin, int clip_y_origin);\n/* 90 */\nEXTERN int\t\tXSetTSOrigin(Display *display, GC gc,\n\t\t\t\tint ts_x_origin, int ts_y_origin);\n/* 91 */\nEXTERN int\t\tXChangeGC(Display *d, GC gc, unsigned long mask,\n\t\t\t\tXGCValues *values);\n/* 92 */\nEXTERN int\t\tXSetFont(Display *display, GC gc, Font font);\n/* 93 */\nEXTERN int\t\tXSetArcMode(Display *display, GC gc, int arc_mode);\n/* 94 */\nEXTERN int\t\tXSetStipple(Display *display, GC gc, Pixmap stipple);\n/* 95 */\nEXTERN int\t\tXSetFillRule(Display *display, GC gc, int fill_rule);\n/* 96 */\nEXTERN int\t\tXSetFillStyle(Display *display, GC gc,\n\t\t\t\tint fill_style);\n/* 97 */\nEXTERN int\t\tXSetFunction(Display *display, GC gc, int function);\n/* 98 */\nEXTERN int\t\tXSetLineAttributes(Display *display, GC gc,\n\t\t\t\tunsigned int line_width, int line_style,\n\t\t\t\tint cap_style, int join_style);\n/* 99 */\nEXTERN int\t\t_XInitImageFuncPtrs(XImage *image);\n/* 100 */\nEXTERN XIC\t\tXCreateIC(XIM xim, ...);\n/* 101 */\nEXTERN XVisualInfo *\tXGetVisualInfo(Display *display, long vinfo_mask,\n\t\t\t\tXVisualInfo *vinfo_template,\n\t\t\t\tint *nitems_return);\n/* 102 */\nEXTERN void\t\tXSetWMClientMachine(Display *display, Window w,\n\t\t\t\tXTextProperty *text_prop);\n/* 103 */\nEXTERN Status\t\tXStringListToTextProperty(char **list, int count,\n\t\t\t\tXTextProperty *text_prop_return);\n/* 104 */\nEXTERN int\t\tXDrawLine(Display *d, Drawable dr, GC g, int x1,\n\t\t\t\tint y1, int x2, int y2);\n/* 105 */\nEXTERN int\t\tXWarpPointer(Display *d, Window s, Window dw, int sx,\n\t\t\t\tint sy, unsigned int sw, unsigned int sh,\n\t\t\t\tint dx, int dy);\n/* 106 */\nEXTERN int\t\tXFillRectangle(Display *display, Drawable d, GC gc,\n\t\t\t\tint x, int y, unsigned int width,\n\t\t\t\tunsigned int height);\n/* 107 */\nEXTERN int\t\tXFlush(Display *display);\n/* 108 */\nEXTERN int\t\tXGrabServer(Display *display);\n/* 109 */\nEXTERN int\t\tXUngrabServer(Display *display);\n/* 110 */\nEXTERN int\t\tXFree(void *data);\n/* 111 */\nEXTERN int\t\tXNoOp(Display *display);\n/* 112 */\nEXTERN XAfterFunction\tXSynchronize(Display *display, Bool onoff);\n/* 113 */\nEXTERN int\t\tXSync(Display *display, Bool discard);\n/* 114 */\nEXTERN VisualID\t\tXVisualIDFromVisual(Visual *visual);\n/* Slot 115 is reserved */\n/* Slot 116 is reserved */\n/* Slot 117 is reserved */\n/* Slot 118 is reserved */\n/* Slot 119 is reserved */\n/* 120 */\nEXTERN int\t\tXOffsetRegion(Region rgn, int dx, int dy);\n/* 121 */\nEXTERN int\t\tXUnionRegion(Region srca, Region srcb,\n\t\t\t\tRegion dr_return);\n/* 122 */\nEXTERN Window\t\tXCreateWindow(Display *display, Window parent, int x,\n\t\t\t\tint y, unsigned int width,\n\t\t\t\tunsigned int height,\n\t\t\t\tunsigned int border_width, int depth,\n\t\t\t\tunsigned int clazz, Visual *visual,\n\t\t\t\tunsigned long value_mask,\n\t\t\t\tXSetWindowAttributes *attributes);\n/* Slot 123 is reserved */\n/* Slot 124 is reserved */\n/* Slot 125 is reserved */\n/* Slot 126 is reserved */\n/* Slot 127 is reserved */\n/* Slot 128 is reserved */\n/* 129 */\nEXTERN int\t\tXLowerWindow(Display *d, Window w);\n/* 130 */\nEXTERN int\t\tXFillArcs(Display *d, Drawable dr, GC gc, XArc *a,\n\t\t\t\tint n);\n/* 131 */\nEXTERN int\t\tXDrawArcs(Display *d, Drawable dr, GC gc, XArc *a,\n\t\t\t\tint n);\n/* 132 */\nEXTERN int\t\tXDrawRectangles(Display *d, Drawable dr, GC gc,\n\t\t\t\tXRectangle *r, int n);\n/* 133 */\nEXTERN int\t\tXDrawSegments(Display *d, Drawable dr, GC gc,\n\t\t\t\tXSegment *s, int n);\n/* 134 */\nEXTERN int\t\tXDrawPoint(Display *d, Drawable dr, GC gc, int x,\n\t\t\t\tint y);\n/* 135 */\nEXTERN int\t\tXDrawPoints(Display *d, Drawable dr, GC gc,\n\t\t\t\tXPoint *p, int n, int m);\n/* 136 */\nEXTERN int\t\tXReparentWindow(Display *d, Window w, Window p,\n\t\t\t\tint x, int y);\n/* 137 */\nEXTERN int\t\tXPutImage(Display *d, Drawable dr, GC gc, XImage *im,\n\t\t\t\tint sx, int sy, int dx, int dy,\n\t\t\t\tunsigned int w, unsigned int h);\n/* 138 */\nEXTERN Region\t\tXPolygonRegion(XPoint *pts, int n, int rule);\n/* 139 */\nEXTERN int\t\tXPointInRegion(Region rgn, int x, int y);\n/* 140 */\nEXTERN XVaNestedList\tXVaCreateNestedList(int dummy, ...);\n/* 141 */\nEXTERN char *\t\tXSetICValues(XIC xic, ...);\n/* 142 */\nEXTERN char *\t\tXGetICValues(XIC xic, ...);\n/* 143 */\nEXTERN void\t\tXSetICFocus(XIC xic);\n/* 144 */\nEXTERN int\t\tXXorRegion(Region sra, Region srb, Region dr_return);\n/* 145 */\nEXTERN Bool\t\tXEqualRegion(Region r1, Region r2);\n/* Slot 146 is reserved */\n/* 147 */\nEXTERN void\t\tXFreeFontSet(Display *display, XFontSet fontset);\n/* 148 */\nEXTERN int\t\tXCloseIM(XIM im);\n/* 149 */\nEXTERN Bool\t\tXRegisterIMInstantiateCallback(Display *dpy,\n\t\t\t\tstruct _XrmHashBucketRec *rbd,\n\t\t\t\tchar *res_name, char *res_class,\n\t\t\t\tXIDProc callback, XPointer client_data);\n/* 150 */\nEXTERN Bool\t\tXUnregisterIMInstantiateCallback(Display *dpy,\n\t\t\t\tstruct _XrmHashBucketRec *rbd,\n\t\t\t\tchar *res_name, char *res_class,\n\t\t\t\tXIDProc callback, XPointer client_data);\n/* 151 */\nEXTERN char *\t\tXSetLocaleModifiers(const char *modifier_list);\n/* 152 */\nEXTERN XIM\t\tXOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb,\n\t\t\t\tchar *res_name, char *res_class);\n/* 153 */\nEXTERN char *\t\tXGetIMValues(XIM im, ...);\n/* 154 */\nEXTERN char *\t\tXSetIMValues(XIM im, ...);\n/* 155 */\nEXTERN XFontSet\t\tXCreateFontSet(Display *display,\n\t\t\t\tconst char *base_font_name_list,\n\t\t\t\tchar ***missing_charset_list,\n\t\t\t\tint *missing_charset_count,\n\t\t\t\tchar **def_string);\n/* 156 */\nEXTERN void\t\tXFreeStringList(char **list);\n/* 157 */\nEXTERN KeySym\t\tXkbKeycodeToKeysym(Display *d, unsigned int k, int g,\n\t\t\t\tint i);\n/* 158 */\nEXTERN Display *\tXkbOpenDisplay(const char *name, int *ev_rtrn,\n\t\t\t\tint *err_rtrn, int *major_rtrn,\n\t\t\t\tint *minor_rtrn, int *reason);\n\ntypedef struct TkIntXlibStubs {\n    int magic;\n    void *hooks;\n\n    int (*xSetDashes) (Display *display, GC gc, int dash_offset, const char *dash_list, int n); /* 0 */\n    XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */\n    XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */\n    XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */\n    char * (*xGetAtomName) (Display *d, Atom a); /* 4 */\n    char * (*xKeysymToString) (KeySym k); /* 5 */\n    Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */\n    Cursor (*xCreatePixmapCursor) (Display *d, Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2); /* 7 */\n    Cursor (*xCreateGlyphCursor) (Display *d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor const *x1, XColor const *x2); /* 8 */\n    GContext (*xGContextFromGC) (GC g); /* 9 */\n    XHostAddress * (*xListHosts) (Display *d, int *i, Bool *b); /* 10 */\n    void (*reserved11)(void);\n    KeySym (*xStringToKeysym) (const char *c); /* 12 */\n    Window (*xRootWindow) (Display *d, int i); /* 13 */\n    XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 14 */\n    Status (*xIconifyWindow) (Display *d, Window w, int i); /* 15 */\n    Status (*xWithdrawWindow) (Display *d, Window w, int i); /* 16 */\n    Status (*xGetWMColormapWindows) (Display *d, Window w, Window **wpp, int *ip); /* 17 */\n    Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 18 */\n    int (*xBell) (Display *d, int i); /* 19 */\n    int (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, const unsigned char *c, int i3); /* 20 */\n    int (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 21 */\n    int (*xClearWindow) (Display *d, Window w); /* 22 */\n    int (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 23 */\n    int (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 24 */\n    int (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 25 */\n    Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, const char *data, unsigned int width, unsigned int height); /* 26 */\n    int (*xDefineCursor) (Display *d, Window w, Cursor c); /* 27 */\n    int (*xDeleteProperty) (Display *d, Window w, Atom a); /* 28 */\n    int (*xDestroyWindow) (Display *d, Window w); /* 29 */\n    int (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 30 */\n    int (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 31 */\n    int (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 32 */\n    int (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 33 */\n    int (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 34 */\n    int (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 35 */\n    int (*xForceScreenSaver) (Display *d, int i); /* 36 */\n    int (*xFreeColormap) (Display *d, Colormap c); /* 37 */\n    int (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 38 */\n    int (*xFreeCursor) (Display *d, Cursor c); /* 39 */\n    int (*xFreeModifiermap) (XModifierKeymap *x); /* 40 */\n    Status (*xGetGeometry) (Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4); /* 41 */\n    int (*xGetInputFocus) (Display *d, Window *w, int *i); /* 42 */\n    int (*xGetWindowProperty) (Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp); /* 43 */\n    Status (*xGetWindowAttributes) (Display *d, Window w, XWindowAttributes *x); /* 44 */\n    int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 45 */\n    int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 46 */\n    KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 47 */\n    Status (*xLookupColor) (Display *d, Colormap c1, const char *c2, XColor *x1, XColor *x2); /* 48 */\n    int (*xMapWindow) (Display *d, Window w); /* 49 */\n    int (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 50 */\n    int (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 51 */\n    int (*xNextEvent) (Display *d, XEvent *x); /* 52 */\n    int (*xPutBackEvent) (Display *d, XEvent *x); /* 53 */\n    int (*xQueryColors) (Display *d, Colormap c, XColor *x, int i); /* 54 */\n    Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 55 */\n    Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 56 */\n    int (*xRaiseWindow) (Display *d, Window w); /* 57 */\n    int (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 58 */\n    int (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 59 */\n    int (*xSelectInput) (Display *d, Window w, long l); /* 60 */\n    Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 61 */\n    int (*xSetCommand) (Display *d, Window w, char **c, int i); /* 62 */\n    int (*xSetIconName) (Display *d, Window w, const char *c); /* 63 */\n    int (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 64 */\n    int (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 65 */\n    int (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 66 */\n    int (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 67 */\n    int (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 68 */\n    int (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 69 */\n    int (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 70 */\n    int (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 71 */\n    Bool (*xTranslateCoordinates) (Display *d, Window w1, Window w2, int i1, int i2, int *i3, int *i4, Window *w3); /* 72 */\n    int (*xUngrabKeyboard) (Display *d, Time t); /* 73 */\n    int (*xUngrabPointer) (Display *d, Time t); /* 74 */\n    int (*xUnmapWindow) (Display *d, Window w); /* 75 */\n    int (*xWindowEvent) (Display *d, Window w, long l, XEvent *x); /* 76 */\n    void (*xDestroyIC) (XIC x); /* 77 */\n    Bool (*xFilterEvent) (XEvent *x, Window w); /* 78 */\n    int (*xmbLookupString) (XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s); /* 79 */\n    int (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 80 */\n    int (*xSetClipRectangles) (Display *display, GC gc, int clip_x_origin, int clip_y_origin, XRectangle *rectangles, int n, int ordering); /* 81 */\n    Status (*xParseColor) (Display *display, Colormap map, const char *spec, XColor *colorPtr); /* 82 */\n    GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 83 */\n    int (*xFreeGC) (Display *display, GC gc); /* 84 */\n    Atom (*xInternAtom) (Display *display, const char *atom_name, Bool only_if_exists); /* 85 */\n    int (*xSetBackground) (Display *display, GC gc, unsigned long foreground); /* 86 */\n    int (*xSetForeground) (Display *display, GC gc, unsigned long foreground); /* 87 */\n    int (*xSetClipMask) (Display *display, GC gc, Pixmap pixmap); /* 88 */\n    int (*xSetClipOrigin) (Display *display, GC gc, int clip_x_origin, int clip_y_origin); /* 89 */\n    int (*xSetTSOrigin) (Display *display, GC gc, int ts_x_origin, int ts_y_origin); /* 90 */\n    int (*xChangeGC) (Display *d, GC gc, unsigned long mask, XGCValues *values); /* 91 */\n    int (*xSetFont) (Display *display, GC gc, Font font); /* 92 */\n    int (*xSetArcMode) (Display *display, GC gc, int arc_mode); /* 93 */\n    int (*xSetStipple) (Display *display, GC gc, Pixmap stipple); /* 94 */\n    int (*xSetFillRule) (Display *display, GC gc, int fill_rule); /* 95 */\n    int (*xSetFillStyle) (Display *display, GC gc, int fill_style); /* 96 */\n    int (*xSetFunction) (Display *display, GC gc, int function); /* 97 */\n    int (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 98 */\n    int (*_XInitImageFuncPtrs) (XImage *image); /* 99 */\n    XIC (*xCreateIC) (XIM xim, ...); /* 100 */\n    XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 101 */\n    void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 102 */\n    Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 103 */\n    int (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 104 */\n    int (*xWarpPointer) (Display *d, Window s, Window dw, int sx, int sy, unsigned int sw, unsigned int sh, int dx, int dy); /* 105 */\n    int (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 106 */\n    int (*xFlush) (Display *display); /* 107 */\n    int (*xGrabServer) (Display *display); /* 108 */\n    int (*xUngrabServer) (Display *display); /* 109 */\n    int (*xFree) (void *data); /* 110 */\n    int (*xNoOp) (Display *display); /* 111 */\n    XAfterFunction (*xSynchronize) (Display *display, Bool onoff); /* 112 */\n    int (*xSync) (Display *display, Bool discard); /* 113 */\n    VisualID (*xVisualIDFromVisual) (Visual *visual); /* 114 */\n    void (*reserved115)(void);\n    void (*reserved116)(void);\n    void (*reserved117)(void);\n    void (*reserved118)(void);\n    void (*reserved119)(void);\n    int (*xOffsetRegion) (Region rgn, int dx, int dy); /* 120 */\n    int (*xUnionRegion) (Region srca, Region srcb, Region dr_return); /* 121 */\n    Window (*xCreateWindow) (Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long value_mask, XSetWindowAttributes *attributes); /* 122 */\n    void (*reserved123)(void);\n    void (*reserved124)(void);\n    void (*reserved125)(void);\n    void (*reserved126)(void);\n    void (*reserved127)(void);\n    void (*reserved128)(void);\n    int (*xLowerWindow) (Display *d, Window w); /* 129 */\n    int (*xFillArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 130 */\n    int (*xDrawArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 131 */\n    int (*xDrawRectangles) (Display *d, Drawable dr, GC gc, XRectangle *r, int n); /* 132 */\n    int (*xDrawSegments) (Display *d, Drawable dr, GC gc, XSegment *s, int n); /* 133 */\n    int (*xDrawPoint) (Display *d, Drawable dr, GC gc, int x, int y); /* 134 */\n    int (*xDrawPoints) (Display *d, Drawable dr, GC gc, XPoint *p, int n, int m); /* 135 */\n    int (*xReparentWindow) (Display *d, Window w, Window p, int x, int y); /* 136 */\n    int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */\n    Region (*xPolygonRegion) (XPoint *pts, int n, int rule); /* 138 */\n    int (*xPointInRegion) (Region rgn, int x, int y); /* 139 */\n    XVaNestedList (*xVaCreateNestedList) (int dummy, ...); /* 140 */\n    char * (*xSetICValues) (XIC xic, ...); /* 141 */\n    char * (*xGetICValues) (XIC xic, ...); /* 142 */\n    void (*xSetICFocus) (XIC xic); /* 143 */\n    int (*xXorRegion) (Region sra, Region srb, Region dr_return); /* 144 */\n    Bool (*xEqualRegion) (Region r1, Region r2); /* 145 */\n    void (*reserved146)(void);\n    void (*xFreeFontSet) (Display *display, XFontSet fontset); /* 147 */\n    int (*xCloseIM) (XIM im); /* 148 */\n    Bool (*xRegisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 149 */\n    Bool (*xUnregisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 150 */\n    char * (*xSetLocaleModifiers) (const char *modifier_list); /* 151 */\n    XIM (*xOpenIM) (Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name, char *res_class); /* 152 */\n    char * (*xGetIMValues) (XIM im, ...); /* 153 */\n    char * (*xSetIMValues) (XIM im, ...); /* 154 */\n    XFontSet (*xCreateFontSet) (Display *display, const char *base_font_name_list, char ***missing_charset_list, int *missing_charset_count, char **def_string); /* 155 */\n    void (*xFreeStringList) (char **list); /* 156 */\n    KeySym (*xkbKeycodeToKeysym) (Display *d, unsigned int k, int g, int i); /* 157 */\n    Display * (*xkbOpenDisplay) (const char *name, int *ev_rtrn, int *err_rtrn, int *major_rtrn, int *minor_rtrn, int *reason); /* 158 */\n} TkIntXlibStubs;\n\nextern const TkIntXlibStubs *tkIntXlibStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#define XSetDashes \\\n\t(tkIntXlibStubsPtr->xSetDashes) /* 0 */\n#define XGetModifierMapping \\\n\t(tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */\n#define XCreateImage \\\n\t(tkIntXlibStubsPtr->xCreateImage) /* 2 */\n#define XGetImage \\\n\t(tkIntXlibStubsPtr->xGetImage) /* 3 */\n#define XGetAtomName \\\n\t(tkIntXlibStubsPtr->xGetAtomName) /* 4 */\n#define XKeysymToString \\\n\t(tkIntXlibStubsPtr->xKeysymToString) /* 5 */\n#define XCreateColormap \\\n\t(tkIntXlibStubsPtr->xCreateColormap) /* 6 */\n#define XCreatePixmapCursor \\\n\t(tkIntXlibStubsPtr->xCreatePixmapCursor) /* 7 */\n#define XCreateGlyphCursor \\\n\t(tkIntXlibStubsPtr->xCreateGlyphCursor) /* 8 */\n#define XGContextFromGC \\\n\t(tkIntXlibStubsPtr->xGContextFromGC) /* 9 */\n#define XListHosts \\\n\t(tkIntXlibStubsPtr->xListHosts) /* 10 */\n/* Slot 11 is reserved */\n#define XStringToKeysym \\\n\t(tkIntXlibStubsPtr->xStringToKeysym) /* 12 */\n#define XRootWindow \\\n\t(tkIntXlibStubsPtr->xRootWindow) /* 13 */\n#define XSetErrorHandler \\\n\t(tkIntXlibStubsPtr->xSetErrorHandler) /* 14 */\n#define XIconifyWindow \\\n\t(tkIntXlibStubsPtr->xIconifyWindow) /* 15 */\n#define XWithdrawWindow \\\n\t(tkIntXlibStubsPtr->xWithdrawWindow) /* 16 */\n#define XGetWMColormapWindows \\\n\t(tkIntXlibStubsPtr->xGetWMColormapWindows) /* 17 */\n#define XAllocColor \\\n\t(tkIntXlibStubsPtr->xAllocColor) /* 18 */\n#define XBell \\\n\t(tkIntXlibStubsPtr->xBell) /* 19 */\n#define XChangeProperty \\\n\t(tkIntXlibStubsPtr->xChangeProperty) /* 20 */\n#define XChangeWindowAttributes \\\n\t(tkIntXlibStubsPtr->xChangeWindowAttributes) /* 21 */\n#define XClearWindow \\\n\t(tkIntXlibStubsPtr->xClearWindow) /* 22 */\n#define XConfigureWindow \\\n\t(tkIntXlibStubsPtr->xConfigureWindow) /* 23 */\n#define XCopyArea \\\n\t(tkIntXlibStubsPtr->xCopyArea) /* 24 */\n#define XCopyPlane \\\n\t(tkIntXlibStubsPtr->xCopyPlane) /* 25 */\n#define XCreateBitmapFromData \\\n\t(tkIntXlibStubsPtr->xCreateBitmapFromData) /* 26 */\n#define XDefineCursor \\\n\t(tkIntXlibStubsPtr->xDefineCursor) /* 27 */\n#define XDeleteProperty \\\n\t(tkIntXlibStubsPtr->xDeleteProperty) /* 28 */\n#define XDestroyWindow \\\n\t(tkIntXlibStubsPtr->xDestroyWindow) /* 29 */\n#define XDrawArc \\\n\t(tkIntXlibStubsPtr->xDrawArc) /* 30 */\n#define XDrawLines \\\n\t(tkIntXlibStubsPtr->xDrawLines) /* 31 */\n#define XDrawRectangle \\\n\t(tkIntXlibStubsPtr->xDrawRectangle) /* 32 */\n#define XFillArc \\\n\t(tkIntXlibStubsPtr->xFillArc) /* 33 */\n#define XFillPolygon \\\n\t(tkIntXlibStubsPtr->xFillPolygon) /* 34 */\n#define XFillRectangles \\\n\t(tkIntXlibStubsPtr->xFillRectangles) /* 35 */\n#define XForceScreenSaver \\\n\t(tkIntXlibStubsPtr->xForceScreenSaver) /* 36 */\n#define XFreeColormap \\\n\t(tkIntXlibStubsPtr->xFreeColormap) /* 37 */\n#define XFreeColors \\\n\t(tkIntXlibStubsPtr->xFreeColors) /* 38 */\n#define XFreeCursor \\\n\t(tkIntXlibStubsPtr->xFreeCursor) /* 39 */\n#define XFreeModifiermap \\\n\t(tkIntXlibStubsPtr->xFreeModifiermap) /* 40 */\n#define XGetGeometry \\\n\t(tkIntXlibStubsPtr->xGetGeometry) /* 41 */\n#define XGetInputFocus \\\n\t(tkIntXlibStubsPtr->xGetInputFocus) /* 42 */\n#define XGetWindowProperty \\\n\t(tkIntXlibStubsPtr->xGetWindowProperty) /* 43 */\n#define XGetWindowAttributes \\\n\t(tkIntXlibStubsPtr->xGetWindowAttributes) /* 44 */\n#define XGrabKeyboard \\\n\t(tkIntXlibStubsPtr->xGrabKeyboard) /* 45 */\n#define XGrabPointer \\\n\t(tkIntXlibStubsPtr->xGrabPointer) /* 46 */\n#define XKeysymToKeycode \\\n\t(tkIntXlibStubsPtr->xKeysymToKeycode) /* 47 */\n#define XLookupColor \\\n\t(tkIntXlibStubsPtr->xLookupColor) /* 48 */\n#define XMapWindow \\\n\t(tkIntXlibStubsPtr->xMapWindow) /* 49 */\n#define XMoveResizeWindow \\\n\t(tkIntXlibStubsPtr->xMoveResizeWindow) /* 50 */\n#define XMoveWindow \\\n\t(tkIntXlibStubsPtr->xMoveWindow) /* 51 */\n#define XNextEvent \\\n\t(tkIntXlibStubsPtr->xNextEvent) /* 52 */\n#define XPutBackEvent \\\n\t(tkIntXlibStubsPtr->xPutBackEvent) /* 53 */\n#define XQueryColors \\\n\t(tkIntXlibStubsPtr->xQueryColors) /* 54 */\n#define XQueryPointer \\\n\t(tkIntXlibStubsPtr->xQueryPointer) /* 55 */\n#define XQueryTree \\\n\t(tkIntXlibStubsPtr->xQueryTree) /* 56 */\n#define XRaiseWindow \\\n\t(tkIntXlibStubsPtr->xRaiseWindow) /* 57 */\n#define XRefreshKeyboardMapping \\\n\t(tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 58 */\n#define XResizeWindow \\\n\t(tkIntXlibStubsPtr->xResizeWindow) /* 59 */\n#define XSelectInput \\\n\t(tkIntXlibStubsPtr->xSelectInput) /* 60 */\n#define XSendEvent \\\n\t(tkIntXlibStubsPtr->xSendEvent) /* 61 */\n#define XSetCommand \\\n\t(tkIntXlibStubsPtr->xSetCommand) /* 62 */\n#define XSetIconName \\\n\t(tkIntXlibStubsPtr->xSetIconName) /* 63 */\n#define XSetInputFocus \\\n\t(tkIntXlibStubsPtr->xSetInputFocus) /* 64 */\n#define XSetSelectionOwner \\\n\t(tkIntXlibStubsPtr->xSetSelectionOwner) /* 65 */\n#define XSetWindowBackground \\\n\t(tkIntXlibStubsPtr->xSetWindowBackground) /* 66 */\n#define XSetWindowBackgroundPixmap \\\n\t(tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 67 */\n#define XSetWindowBorder \\\n\t(tkIntXlibStubsPtr->xSetWindowBorder) /* 68 */\n#define XSetWindowBorderPixmap \\\n\t(tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 69 */\n#define XSetWindowBorderWidth \\\n\t(tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 70 */\n#define XSetWindowColormap \\\n\t(tkIntXlibStubsPtr->xSetWindowColormap) /* 71 */\n#define XTranslateCoordinates \\\n\t(tkIntXlibStubsPtr->xTranslateCoordinates) /* 72 */\n#define XUngrabKeyboard \\\n\t(tkIntXlibStubsPtr->xUngrabKeyboard) /* 73 */\n#define XUngrabPointer \\\n\t(tkIntXlibStubsPtr->xUngrabPointer) /* 74 */\n#define XUnmapWindow \\\n\t(tkIntXlibStubsPtr->xUnmapWindow) /* 75 */\n#define XWindowEvent \\\n\t(tkIntXlibStubsPtr->xWindowEvent) /* 76 */\n#define XDestroyIC \\\n\t(tkIntXlibStubsPtr->xDestroyIC) /* 77 */\n#define XFilterEvent \\\n\t(tkIntXlibStubsPtr->xFilterEvent) /* 78 */\n#define XmbLookupString \\\n\t(tkIntXlibStubsPtr->xmbLookupString) /* 79 */\n#define TkPutImage \\\n\t(tkIntXlibStubsPtr->tkPutImage) /* 80 */\n#define XSetClipRectangles \\\n\t(tkIntXlibStubsPtr->xSetClipRectangles) /* 81 */\n#define XParseColor \\\n\t(tkIntXlibStubsPtr->xParseColor) /* 82 */\n#define XCreateGC \\\n\t(tkIntXlibStubsPtr->xCreateGC) /* 83 */\n#define XFreeGC \\\n\t(tkIntXlibStubsPtr->xFreeGC) /* 84 */\n#define XInternAtom \\\n\t(tkIntXlibStubsPtr->xInternAtom) /* 85 */\n#define XSetBackground \\\n\t(tkIntXlibStubsPtr->xSetBackground) /* 86 */\n#define XSetForeground \\\n\t(tkIntXlibStubsPtr->xSetForeground) /* 87 */\n#define XSetClipMask \\\n\t(tkIntXlibStubsPtr->xSetClipMask) /* 88 */\n#define XSetClipOrigin \\\n\t(tkIntXlibStubsPtr->xSetClipOrigin) /* 89 */\n#define XSetTSOrigin \\\n\t(tkIntXlibStubsPtr->xSetTSOrigin) /* 90 */\n#define XChangeGC \\\n\t(tkIntXlibStubsPtr->xChangeGC) /* 91 */\n#define XSetFont \\\n\t(tkIntXlibStubsPtr->xSetFont) /* 92 */\n#define XSetArcMode \\\n\t(tkIntXlibStubsPtr->xSetArcMode) /* 93 */\n#define XSetStipple \\\n\t(tkIntXlibStubsPtr->xSetStipple) /* 94 */\n#define XSetFillRule \\\n\t(tkIntXlibStubsPtr->xSetFillRule) /* 95 */\n#define XSetFillStyle \\\n\t(tkIntXlibStubsPtr->xSetFillStyle) /* 96 */\n#define XSetFunction \\\n\t(tkIntXlibStubsPtr->xSetFunction) /* 97 */\n#define XSetLineAttributes \\\n\t(tkIntXlibStubsPtr->xSetLineAttributes) /* 98 */\n#define _XInitImageFuncPtrs \\\n\t(tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 99 */\n#define XCreateIC \\\n\t(tkIntXlibStubsPtr->xCreateIC) /* 100 */\n#define XGetVisualInfo \\\n\t(tkIntXlibStubsPtr->xGetVisualInfo) /* 101 */\n#define XSetWMClientMachine \\\n\t(tkIntXlibStubsPtr->xSetWMClientMachine) /* 102 */\n#define XStringListToTextProperty \\\n\t(tkIntXlibStubsPtr->xStringListToTextProperty) /* 103 */\n#define XDrawLine \\\n\t(tkIntXlibStubsPtr->xDrawLine) /* 104 */\n#define XWarpPointer \\\n\t(tkIntXlibStubsPtr->xWarpPointer) /* 105 */\n#define XFillRectangle \\\n\t(tkIntXlibStubsPtr->xFillRectangle) /* 106 */\n#define XFlush \\\n\t(tkIntXlibStubsPtr->xFlush) /* 107 */\n#define XGrabServer \\\n\t(tkIntXlibStubsPtr->xGrabServer) /* 108 */\n#define XUngrabServer \\\n\t(tkIntXlibStubsPtr->xUngrabServer) /* 109 */\n#define XFree \\\n\t(tkIntXlibStubsPtr->xFree) /* 110 */\n#define XNoOp \\\n\t(tkIntXlibStubsPtr->xNoOp) /* 111 */\n#define XSynchronize \\\n\t(tkIntXlibStubsPtr->xSynchronize) /* 112 */\n#define XSync \\\n\t(tkIntXlibStubsPtr->xSync) /* 113 */\n#define XVisualIDFromVisual \\\n\t(tkIntXlibStubsPtr->xVisualIDFromVisual) /* 114 */\n/* Slot 115 is reserved */\n/* Slot 116 is reserved */\n/* Slot 117 is reserved */\n/* Slot 118 is reserved */\n/* Slot 119 is reserved */\n#define XOffsetRegion \\\n\t(tkIntXlibStubsPtr->xOffsetRegion) /* 120 */\n#define XUnionRegion \\\n\t(tkIntXlibStubsPtr->xUnionRegion) /* 121 */\n#define XCreateWindow \\\n\t(tkIntXlibStubsPtr->xCreateWindow) /* 122 */\n/* Slot 123 is reserved */\n/* Slot 124 is reserved */\n/* Slot 125 is reserved */\n/* Slot 126 is reserved */\n/* Slot 127 is reserved */\n/* Slot 128 is reserved */\n#define XLowerWindow \\\n\t(tkIntXlibStubsPtr->xLowerWindow) /* 129 */\n#define XFillArcs \\\n\t(tkIntXlibStubsPtr->xFillArcs) /* 130 */\n#define XDrawArcs \\\n\t(tkIntXlibStubsPtr->xDrawArcs) /* 131 */\n#define XDrawRectangles \\\n\t(tkIntXlibStubsPtr->xDrawRectangles) /* 132 */\n#define XDrawSegments \\\n\t(tkIntXlibStubsPtr->xDrawSegments) /* 133 */\n#define XDrawPoint \\\n\t(tkIntXlibStubsPtr->xDrawPoint) /* 134 */\n#define XDrawPoints \\\n\t(tkIntXlibStubsPtr->xDrawPoints) /* 135 */\n#define XReparentWindow \\\n\t(tkIntXlibStubsPtr->xReparentWindow) /* 136 */\n#define XPutImage \\\n\t(tkIntXlibStubsPtr->xPutImage) /* 137 */\n#define XPolygonRegion \\\n\t(tkIntXlibStubsPtr->xPolygonRegion) /* 138 */\n#define XPointInRegion \\\n\t(tkIntXlibStubsPtr->xPointInRegion) /* 139 */\n#define XVaCreateNestedList \\\n\t(tkIntXlibStubsPtr->xVaCreateNestedList) /* 140 */\n#define XSetICValues \\\n\t(tkIntXlibStubsPtr->xSetICValues) /* 141 */\n#define XGetICValues \\\n\t(tkIntXlibStubsPtr->xGetICValues) /* 142 */\n#define XSetICFocus \\\n\t(tkIntXlibStubsPtr->xSetICFocus) /* 143 */\n#define XXorRegion \\\n\t(tkIntXlibStubsPtr->xXorRegion) /* 144 */\n#define XEqualRegion \\\n\t(tkIntXlibStubsPtr->xEqualRegion) /* 145 */\n/* Slot 146 is reserved */\n#define XFreeFontSet \\\n\t(tkIntXlibStubsPtr->xFreeFontSet) /* 147 */\n#define XCloseIM \\\n\t(tkIntXlibStubsPtr->xCloseIM) /* 148 */\n#define XRegisterIMInstantiateCallback \\\n\t(tkIntXlibStubsPtr->xRegisterIMInstantiateCallback) /* 149 */\n#define XUnregisterIMInstantiateCallback \\\n\t(tkIntXlibStubsPtr->xUnregisterIMInstantiateCallback) /* 150 */\n#define XSetLocaleModifiers \\\n\t(tkIntXlibStubsPtr->xSetLocaleModifiers) /* 151 */\n#define XOpenIM \\\n\t(tkIntXlibStubsPtr->xOpenIM) /* 152 */\n#define XGetIMValues \\\n\t(tkIntXlibStubsPtr->xGetIMValues) /* 153 */\n#define XSetIMValues \\\n\t(tkIntXlibStubsPtr->xSetIMValues) /* 154 */\n#define XCreateFontSet \\\n\t(tkIntXlibStubsPtr->xCreateFontSet) /* 155 */\n#define XFreeStringList \\\n\t(tkIntXlibStubsPtr->xFreeStringList) /* 156 */\n#define XkbKeycodeToKeysym \\\n\t(tkIntXlibStubsPtr->xkbKeycodeToKeysym) /* 157 */\n#define XkbOpenDisplay \\\n\t(tkIntXlibStubsPtr->xkbOpenDisplay) /* 158 */\n\n#endif /* defined(USE_TK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#endif /* _TKINTXLIBDECLS */\n"
  },
  {
    "path": "generic/tkListbox.c",
    "content": "/*\n * tkListbox.c --\n *\n *\tThis module implements listbox widgets for the Tk toolkit. A listbox\n *\tdisplays a collection of strings, one per line, and provides scrolling\n *\tand selection.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"default.h\"\n\ntypedef struct {\n    Tk_OptionTable listboxOptionTable;\n\t\t\t\t/* Table defining configuration options\n\t\t\t\t * available for the listbox. */\n    Tk_OptionTable itemAttrOptionTable;\n\t\t\t\t/* Table defining configuration options\n\t\t\t\t * available for listbox items. */\n} ListboxOptionTables;\n\n/*\n * A data structure of the following type is kept for each listbox widget\n * managed by this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the listbox. NULL\n\t\t\t\t * means that the window has been destroyed\n\t\t\t\t * but the data structures haven't yet been\n\t\t\t\t * cleaned up. */\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with listbox. */\n    Tcl_Command widgetCmd;\t/* Token for listbox's widget command. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n    Tk_OptionTable itemAttrOptionTable;\n\t\t\t\t/* Table that defines configuration options\n\t\t\t\t * available for listbox items. */\n    Tcl_Obj *listVarNameObj;\t/* List variable name */\n    Tcl_Obj *listObj;\t\t/* Pointer to the list object being used */\n    Tcl_Size nElements;\t\t/* Holds the current count of elements */\n    Tcl_HashTable *selection;\t/* Tracks selection */\n    Tcl_HashTable *itemAttrTable;\n\t\t\t\t/* Tracks item attributes */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tk_3DBorder normalBorder;\t/* Used for drawing border around whole\n\t\t\t\t * window, plus used for background. */\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border around window. */\n    int relief;\t\t\t/* 3-D effect: TK_RELIEF_RAISED, etc. */\n    Tcl_Obj *highlightWidthObj;\t\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. <= 0 means\n\t\t\t\t * don't draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    Tk_Font tkfont;\t\t/* Information about text font, or NULL. */\n    XColor *fgColorPtr;\t\t/* Text color in normal mode. */\n    XColor *dfgColorPtr;\t/* Text color in disabled mode. */\n    GC textGC;\t\t\t/* For drawing normal text. */\n    Tk_3DBorder selBorder;\t/* Borders and backgrounds for selected\n\t\t\t\t * elements. */\n    Tk_3DBorder inactiveSelBorder;\n\t\t\t\t/* Borders and backgrounds for selected\n\t\t\t\t * elements when they don't have the focus. */\n    Tcl_Obj *selBorderWidthObj;\t/* Width of border around selection. */\n    XColor *selFgColorPtr;\t/* Foreground color for selected elements. */\n    XColor *inactiveSelFgColorPtr;\n\t\t\t\t/* Foreground color for selected elements when\n\t\t\t\t * they don't have the focus. */\n    GC selTextGC;\t\t/* For drawing selected text. */\n    int width;\t\t\t/* Desired width of window, in characters. */\n    int height;\t\t\t/* Desired height of window, in lines. */\n    int lineHeight;\t\t/* Number of pixels allocated for each line in\n\t\t\t\t * display. */\n    int topIndex;\t\t/* Index of top-most element visible in\n\t\t\t\t * window. */\n    int fullLines;\t\t/* Number of lines that are completely\n\t\t\t\t * visible in window. There may be one\n\t\t\t\t * additional line at the bottom that is\n\t\t\t\t * partially visible. */\n    int partialLine;\t\t/* 0 means that the window holds exactly\n\t\t\t\t * fullLines lines. 1 means that there is one\n\t\t\t\t * additional line that is partially\n\t\t\t\t * visible. */\n    bool setGrid;\t\t/* True means pass gridding information to\n\t\t\t\t * window manager. */\n\n    /*\n     * Information to support horizontal scrolling:\n     */\n\n    int maxWidth;\t\t/* Width (in pixels) of widest string in\n\t\t\t\t * listbox. */\n    int xScrollUnit;\t\t/* Number of pixels in one \"unit\" for\n\t\t\t\t * horizontal scrolling (window scrolls\n\t\t\t\t * horizontally in increments of this size).\n\t\t\t\t * This is an average character size. */\n    int xOffset;\t\t/* The left edge of each string in the listbox\n\t\t\t\t * is offset to the left by this many pixels\n\t\t\t\t * (0 means no offset, positive means there is\n\t\t\t\t * an offset). This is x scrolling information\n\t\t\t\t * is not linked to justification. */\n\n    /*\n     * Information about what's selected or active, if any.\n     */\n\n    Tcl_Obj *selectModeObj;\t\t/* Selection style: single, browse, multiple,\n\t\t\t\t * or extended. This value isn't used in C\n\t\t\t\t * code, but the Tcl bindings use it. */\n    int numSelected;\t\t/* Number of elements currently selected. */\n    int selectAnchor;\t\t/* Fixed end of selection (i.e. element at\n\t\t\t\t * which selection was started.) */\n    bool exportSelection;\t/* True means tie internal listbox to X\n\t\t\t\t * selection. */\n    int active;\t\t\t/* Index of \"active\" element (the one that has\n\t\t\t\t * been selected by keyboard traversal). -1\n\t\t\t\t * means none. */\n    int activeStyle;\t\t/* Style in which to draw the active element.\n\t\t\t\t * One of: underline, none, dotbox */\n\n    /*\n     * Information for scanning:\n     */\n\n    int scanMarkX;\t\t/* X-position at which scan started (e.g.\n\t\t\t\t * button was pressed here). */\n    int scanMarkY;\t\t/* Y-position at which scan started (e.g.\n\t\t\t\t * button was pressed here). */\n    int scanMarkXOffset;\t/* Value of \"xOffset\" field when scan\n\t\t\t\t * started. */\n    int scanMarkYIndex;\t\t/* Index of line that was at top of window\n\t\t\t\t * when scan started. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or None. */\n    Tcl_Obj *takeFocusObj;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    Tcl_Obj *yScrollCmdObj;\t/* Command prefix for communicating with\n\t\t\t\t * vertical scrollbar. NULL means no command\n\t\t\t\t * to issue. May be NULL. */\n    Tcl_Obj *xScrollCmdObj;\t/* Command prefix for communicating with\n\t\t\t\t * horizontal scrollbar. NULL means no command\n\t\t\t\t * to issue. May be NULL. */\n    int state;\t\t\t/* Listbox state. */\n    Pixmap gray;\t\t/* Pixmap for displaying disabled text. */\n    int flags;\t\t\t/* Various flag bits: see below for\n\t\t\t\t * definitions. */\n    Tk_Justify justify;         /* Justification. */\n} Listbox;\n\n/*\n * How to encode the keys for the hash tables used to store what items are\n * selected and what the attributes are.\n */\n\n#define KEY(i)\t\t((char *) INT2PTR(i))\n\n/*\n * ItemAttr structures are used to store item configuration information for\n * the items in a listbox\n */\n\ntypedef struct {\n    Tk_3DBorder border;\t\t/* Used for drawing background around text */\n    Tk_3DBorder selBorder;\t/* Used for selected text */\n    XColor *fgColor;\t\t/* Text color in normal mode. */\n    XColor *selFgColor;\t\t/* Text color in selected mode. */\n} ItemAttr;\n\n/*\n * Flag bits for listboxes:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * UPDATE_V_SCROLLBAR:\t\tNon-zero means vertical scrollbar needs to be\n *\t\t\t\tupdated.\n * UPDATE_H_SCROLLBAR:\t\tNon-zero means horizontal scrollbar needs to\n *\t\t\t\tbe updated.\n * GOT_FOCUS:\t\t\tNon-zero means this widget currently has the\n *\t\t\t\tinput focus.\n * MAXWIDTH_IS_STALE:\t\tStored maxWidth may be out-of-date.\n * LISTBOX_DELETED:\t\tThis listbox has been effectively destroyed.\n */\n\n#define REDRAW_PENDING\t\t1\n#define UPDATE_V_SCROLLBAR\t2\n#define UPDATE_H_SCROLLBAR\t4\n#define GOT_FOCUS\t\t8\n#define MAXWIDTH_IS_STALE\t16\n#define LISTBOX_DELETED\t\t32\n\n/*\n * The following enum is used to define a type for the -state option of the\n * Listbox widget. These values are used as indices into the string table\n * below.\n */\n\nenum state {\n    STATE_DISABLED, STATE_NORMAL\n};\n\nenum activeStyle {\n    ACTIVE_STYLE_DOTBOX, ACTIVE_STYLE_NONE, ACTIVE_STYLE_UNDERLINE\n};\n\nstatic const char *const activeStyleStrings[] = {\n    \"dotbox\", \"none\", \"underline\", NULL\n};\n\n/*\n * The optionSpecs table defines the valid configuration options for the\n * listbox widget.\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_STRING_TABLE, \"-activestyle\", \"activeStyle\", \"ActiveStyle\",\n\tDEF_LISTBOX_ACTIVE_STYLE, TCL_INDEX_NONE, offsetof(Listbox, activeStyle),\n\t0, activeStyleStrings, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\t DEF_LISTBOX_BG_COLOR, TCL_INDEX_NONE, offsetof(Listbox, normalBorder),\n\t 0, DEF_LISTBOX_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\t NULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\t NULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\t DEF_LISTBOX_BORDER_WIDTH, offsetof(Listbox, borderWidthObj), TCL_INDEX_NONE,\n\t 0, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\t DEF_LISTBOX_CURSOR, TCL_INDEX_NONE, offsetof(Listbox, cursor),\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t \"DisabledForeground\", DEF_LISTBOX_DISABLED_FG, TCL_INDEX_NONE,\n\t offsetof(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-exportselection\", \"exportSelection\",\n\t \"ExportSelection\", DEF_LISTBOX_EXPORT_SELECTION, TCL_INDEX_NONE,\n\t offsetof(Listbox, exportSelection), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\t NULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\t DEF_LISTBOX_FONT, TCL_INDEX_NONE, offsetof(Listbox, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\t DEF_LISTBOX_FG, TCL_INDEX_NONE, offsetof(Listbox, fgColorPtr), 0, 0, 0},\n    {TK_OPTION_INT, \"-height\", \"height\", \"Height\",\n\t DEF_LISTBOX_HEIGHT, TCL_INDEX_NONE, offsetof(Listbox, height), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t \"HighlightBackground\", DEF_LISTBOX_HIGHLIGHT_BG, TCL_INDEX_NONE,\n\t offsetof(Listbox, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\t DEF_LISTBOX_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Listbox, highlightColorPtr),\n\t 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t \"HighlightThickness\", DEF_LISTBOX_HIGHLIGHT_WIDTH,\n\t offsetof(Listbox, highlightWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_BORDER, \"-inactiveselectbackground\", \"inactiveSelectBackground\",\n\t\"Foreground\", DEF_LISTBOX_INACTIVE_SELECT_COLOR,\n\tTCL_INDEX_NONE, offsetof(Listbox, inactiveSelBorder),\n\tTK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_MONO, 0},\n    {TK_OPTION_COLOR, \"-inactiveselectforeground\", \"inactiveSelectForeground\",\n\t\"Background\", DEF_LISTBOX_INACTIVE_SELECT_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(Listbox, inactiveSelFgColorPtr),\n\tTK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_LISTBOX_JUSTIFY, TCL_INDEX_NONE, offsetof(Listbox, justify),\n\tTK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\t DEF_LISTBOX_RELIEF, TCL_INDEX_NONE, offsetof(Listbox, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\t DEF_LISTBOX_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Listbox, selBorder),\n\t 0, DEF_LISTBOX_SELECT_MONO, 0},\n    {TK_OPTION_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\",\n\t \"BorderWidth\", DEF_LISTBOX_SELECT_BD, offsetof(Listbox, selBorderWidthObj),\n\t TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\t DEF_LISTBOX_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Listbox, selFgColorPtr),\n\t TK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0},\n    {TK_OPTION_STRING, \"-selectmode\", \"selectMode\", \"SelectMode\",\n\t DEF_LISTBOX_SELECT_MODE, offsetof(Listbox, selectModeObj), TCL_INDEX_NONE,\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-setgrid\", \"setGrid\", \"SetGrid\",\n\t DEF_LISTBOX_SET_GRID, TCL_INDEX_NONE, offsetof(Listbox, setGrid), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_LISTBOX_STATE, TCL_INDEX_NONE, offsetof(Listbox, state),\n\t0, &tkStateStrings[1], 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\t DEF_LISTBOX_TAKE_FOCUS, offsetof(Listbox, takeFocusObj), TCL_INDEX_NONE,\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\t DEF_LISTBOX_WIDTH, TCL_INDEX_NONE, offsetof(Listbox, width), 0, 0, 0},\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\t DEF_LISTBOX_SCROLL_COMMAND, offsetof(Listbox, xScrollCmdObj), TCL_INDEX_NONE,\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-yscrollcommand\", \"yScrollCommand\", \"ScrollCommand\",\n\t DEF_LISTBOX_SCROLL_COMMAND, offsetof(Listbox, yScrollCmdObj), TCL_INDEX_NONE,\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-listvariable\", \"listVariable\", \"Variable\",\n\t DEF_LISTBOX_LIST_VARIABLE, offsetof(Listbox, listVarNameObj), TCL_INDEX_NONE,\n\t TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * The itemAttrOptionSpecs table defines the valid configuration options for\n * listbox items.\n */\n\nstatic const Tk_OptionSpec itemAttrOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", NULL, NULL,\n     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, border),\n     TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n     NULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n     NULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_COLOR, \"-foreground\", NULL, NULL,\n     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, fgColor),\n     TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", NULL, NULL,\n     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, selBorder),\n     TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", NULL, NULL,\n     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, selFgColor),\n     TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, NULL, 0}\n};\n\n/*\n * The following tables define the listbox widget commands (and sub-commands)\n * and map the indexes into the string tables into enumerated types used to\n * dispatch the listbox widget command.\n */\n\nstatic const char *const commandNames[] = {\n    \"activate\", \"bbox\", \"cget\", \"configure\", \"curselection\", \"delete\", \"get\",\n    \"index\", \"insert\", \"itemcget\", \"itemconfigure\", \"nearest\", \"scan\",\n    \"see\", \"selection\", \"size\", \"xview\", \"yview\", NULL\n};\nenum command {\n    COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE,\n    COMMAND_CURSELECTION, COMMAND_DELETE, COMMAND_GET, COMMAND_INDEX,\n    COMMAND_INSERT, COMMAND_ITEMCGET, COMMAND_ITEMCONFIGURE,\n    COMMAND_NEAREST, COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION,\n    COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW\n};\n\nstatic const char *const selCommandNames[] = {\n    \"anchor\", \"clear\", \"includes\", \"set\", NULL\n};\nenum selcommand {\n    SELECTION_ANCHOR, SELECTION_CLEAR, SELECTION_INCLUDES, SELECTION_SET\n};\n\nstatic const char *const scanCommandNames[] = {\n    \"dragto\", \"mark\", NULL\n};\nenum scancommand {\n    SCAN_DRAGTO, SCAN_MARK\n};\n\nstatic const char *const indexNames[] = {\n    \"active\", \"anchor\", NULL\n};\nenum indices {\n    INDEX_ACTIVE, INDEX_ANCHOR\n};\n\n/*\n * Declarations for procedures defined later in this file.\n */\n\nstatic void\t\tChangeListboxOffset(Listbox *listPtr, int offset);\nstatic void\t\tChangeListboxView(Listbox *listPtr, int index);\nstatic int\t\tConfigureListbox(Tcl_Interp *interp, Listbox *listPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tConfigureListboxItem(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, ItemAttr *attrs, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], Tcl_Size index);\nstatic int\t\tListboxDeleteSubCmd(Listbox *listPtr,\n\t\t\t    int first, int last);\nstatic Tcl_FreeProc\tDestroyListbox;\nstatic void\t\tDestroyListboxOptionTables(void *clientData,\n\t\t\t    Tcl_Interp *interp);\nstatic void\t\tDisplayListbox(void *clientData);\nstatic int\t\tGetListboxIndex(Tcl_Interp *interp, Listbox *listPtr,\n\t\t\t    Tcl_Obj *index, int endIsSize, Tcl_Size *indexPtr);\nstatic int\t\tListboxInsertSubCmd(Listbox *listPtr,\n\t\t\t    Tcl_Size index, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tListboxCmdDeletedProc(void *clientData);\nstatic void\t\tListboxComputeGeometry(Listbox *listPtr,\n\t\t\t    int fontChanged, int maxIsStale, int updateGrid);\nstatic void\t\tListboxEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_Size\tListboxFetchSelection(void *clientData,\n\t\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\nstatic void\t\tListboxLostSelection(void *clientData);\nstatic void\t\tGenerateListboxSelectEvent(Listbox *listPtr);\nstatic void\t\tEventuallyRedrawRange(Listbox *listPtr,\n\t\t\t    Tcl_Size first, Tcl_Size last);\nstatic void\t\tListboxScanTo(Listbox *listPtr, int x, int y);\nstatic int\t\tListboxSelect(Listbox *listPtr,\n\t\t\t    int first, int last, int select);\nstatic void\t\tListboxUpdateHScrollbar(Listbox *listPtr);\nstatic void\t\tListboxUpdateVScrollbar(Listbox *listPtr);\nstatic Tcl_ObjCmdProc2 ListboxWidgetObjCmd;\nstatic int\t\tListboxBboxSubCmd(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, int index);\nstatic int\t\tListboxSelectionSubCmd(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tListboxXviewSubCmd(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tListboxYviewSubCmd(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic ItemAttr *\tListboxGetItemAttributes(Tcl_Interp *interp,\n\t\t\t    Listbox *listPtr, int index);\nstatic void\t\tListboxWorldChanged(void *instanceData);\nstatic int\t\tNearestListboxElement(Listbox *listPtr, int y);\nstatic char *\t\tListboxListVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic void\t\tMigrateHashEntries(Tcl_HashTable *table,\n\t\t\t    Tcl_Size first, Tcl_Size last, Tcl_Size offset);\nstatic int\t\tGetMaxOffset(Listbox *listPtr);\n\n/*\n * The structure below defines button class behavior by means of procedures\n * that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs listboxClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    ListboxWorldChanged,\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ListboxObjCmd --\n *\n *\tThis procedure is invoked to process the \"listbox\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ListboxObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Listbox *listPtr;\n    Tk_Window tkwin;\n    ListboxOptionTables *optionTables;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    optionTables = (ListboxOptionTables *)Tcl_GetAssocData(interp, \"ListboxOptionTables\", NULL);\n    if (optionTables == NULL) {\n\t/*\n\t * We haven't created the option tables for this widget class yet. Do\n\t * it now and save the a pointer to them as the void *for the\n\t * command, so future invocations will have access to it.\n\t */\n\n\toptionTables = (ListboxOptionTables *)Tcl_Alloc(sizeof(ListboxOptionTables));\n\n\t/*\n\t * Set up an exit handler to free the optionTables struct.\n\t */\n\n\tTcl_SetAssocData(interp, \"ListboxOptionTables\",\n\t\tDestroyListboxOptionTables, optionTables);\n\n\t/*\n\t * Create the listbox option table and the listbox item option table.\n\t */\n\n\toptionTables->listboxOptionTable =\n\t\tTk_CreateOptionTable(interp, optionSpecs);\n\toptionTables->itemAttrOptionTable =\n\t\tTk_CreateOptionTable(interp, itemAttrOptionSpecs);\n    }\n\n    /*\n     * Initialize the fields of the structure that won't be initialized by\n     * ConfigureListbox, or that ConfigureListbox requires to be initialized\n     * already (e.g. resource pointers).\n     */\n\n    listPtr\t\t\t = (Listbox *)Tcl_Alloc(sizeof(Listbox));\n    memset(listPtr, 0, sizeof(Listbox));\n\n    listPtr->tkwin\t\t   = tkwin;\n    listPtr->display\t\t   = Tk_Display(tkwin);\n    listPtr->interp\t\t   = interp;\n    listPtr->widgetCmd\t\t   = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(listPtr->tkwin), ListboxWidgetObjCmd, listPtr,\n\t    ListboxCmdDeletedProc);\n    listPtr->optionTable\t   = optionTables->listboxOptionTable;\n    listPtr->itemAttrOptionTable   = optionTables->itemAttrOptionTable;\n    listPtr->selection\t\t   = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n    Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS);\n    listPtr->itemAttrTable\t   = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n    Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS);\n    listPtr->relief\t\t   = TK_RELIEF_RAISED;\n    listPtr->textGC\t\t   = NULL;\n    listPtr->inactiveSelBorder\t   = NULL;\n    listPtr->selFgColorPtr\t   = NULL;\n    listPtr->inactiveSelFgColorPtr = NULL;\n    listPtr->selTextGC\t\t   = NULL;\n    listPtr->fullLines\t\t   = 1;\n    listPtr->xScrollUnit\t   = 1;\n    listPtr->exportSelection\t   = true;\n    listPtr->cursor\t\t   = NULL;\n    listPtr->state\t\t   = STATE_NORMAL;\n    listPtr->gray\t\t   = None;\n    listPtr->justify               = TK_JUSTIFY_LEFT;\n\n    /*\n     * Keep a hold of the associated tkwin until we destroy the listbox,\n     * otherwise Tk might free it while we still need it.\n     */\n\n    Tcl_Preserve(listPtr->tkwin);\n\n    Tk_SetClass(listPtr->tkwin, \"Listbox\");\n    Tk_SetClassProcs(listPtr->tkwin, &listboxClass, listPtr);\n    Tk_CreateEventHandler(listPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    ListboxEventProc, listPtr);\n    Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING,\n\t    ListboxFetchSelection, listPtr, XA_STRING);\n    if (Tk_InitOptions(interp, listPtr,\n\t    optionTables->listboxOptionTable, tkwin) != TCL_OK) {\n\tTk_DestroyWindow(listPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    if (ConfigureListbox(interp, listPtr, objc-2, objv+2) != TCL_OK) {\n\tTk_DestroyWindow(listPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(listPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxWidgetObjCmd --\n *\n *\tThis Tcl_Obj based procedure is invoked to process the Tcl command\n *\tthat corresponds to a widget managed by this module. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxWidgetObjCmd(\n    void *clientData,\t/* Information about listbox widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Arguments as Tcl_Obj's. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n    int cmdIndex;\n    Tcl_Size index;\n    int result = TCL_OK;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the command by looking up the second argument in the list of\n     * valid subcommand names.\n     */\n\n    result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,\n\t    \"option\", 0, &cmdIndex);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    Tcl_Preserve(listPtr);\n\n    /*\n     * The subcommand was valid, so continue processing.\n     */\n\n    switch (cmdIndex) {\n    case COMMAND_ACTIVATE:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tif (!(listPtr->state & STATE_NORMAL)) {\n\t    break;\n\t}\n\n\tif (index >= listPtr->nElements) {\n\t    index = listPtr->nElements-1;\n\t}\n\tif (index < 0) {\n\t    index = 0;\n\t}\n\tlistPtr->active = index;\n\tEventuallyRedrawRange(listPtr, listPtr->active, listPtr->active);\n\tresult = TCL_OK;\n\tbreak;\n\n    case COMMAND_BBOX:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tresult = ListboxBboxSubCmd(interp, listPtr, index);\n\tbreak;\n\n    case COMMAND_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tobjPtr = Tk_GetOptionValue(interp, listPtr,\n\t\tlistPtr->optionTable, objv[2], listPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tresult = TCL_OK;\n\tbreak;\n\n    case COMMAND_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, listPtr,\n\t\t    listPtr->optionTable,\n\t\t    (objc == 3) ? objv[2] : NULL, listPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    result = TCL_OK;\n\t} else {\n\t    result = ConfigureListbox(interp, listPtr, objc-2, objv+2);\n\t}\n\tbreak;\n\n    case COMMAND_CURSELECTION: {\n\tint i;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\t/*\n\t * Of course, it would be more efficient to use the Tcl_HashTable\n\t * search functions (Tcl_FirstHashEntry, Tcl_NextHashEntry), but then\n\t * the result wouldn't be in sorted order. So instead we loop through\n\t * the indices in order, adding them to the result if they are\n\t * selected.\n\t */\n\n\tobjPtr = Tcl_NewObj();\n\tfor (i = 0; i < (int)listPtr->nElements; i++) {\n\t    if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) {\n\t\tTcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(i));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_DELETE: {\n\tTcl_Size first, last;\n\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"firstIndex ?lastIndex?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &first);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tif (!(listPtr->state & STATE_NORMAL)) {\n\t    break;\n\t}\n\n\tif (first < (int)listPtr->nElements) {\n\t    /*\n\t     * if a \"last index\" was given, get it now; otherwise, use the\n\t     * first index as the last index.\n\t     */\n\n\t    if (objc == 4) {\n\t\tresult = GetListboxIndex(interp, listPtr, objv[3], 0, &last);\n\t\tif (result != TCL_OK) {\n\t\t    break;\n\t\t}\n\t    } else {\n\t\tlast = first;\n\t    }\n\t    if (last >= (int)listPtr->nElements) {\n\t\tlast = listPtr->nElements - 1;\n\t    }\n\t    result = ListboxDeleteSubCmd(listPtr, first, last);\n\t} else {\n\t    result = TCL_OK;\n\t}\n\tbreak;\n    }\n\n    case COMMAND_GET: {\n\tTcl_Size listLen, first, last;\n\tTcl_Obj **elemPtrs;\n\n\tif (objc != 3 && objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"firstIndex ?lastIndex?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &first);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tlast = first;\n\tif (objc == 4) {\n\t    result = GetListboxIndex(interp, listPtr, objv[3], 0, &last);\n\t    if (result != TCL_OK) {\n\t\tbreak;\n\t    }\n\t}\n\tif (first >= (int)listPtr->nElements) {\n\t    result = TCL_OK;\n\t    break;\n\t}\n\tif (last >= (int)listPtr->nElements) {\n\t    last = listPtr->nElements - 1;\n\t}\n\tif (first < 0) {\n\t    first = 0;\n\t}\n\tif (first > last) {\n\t    result = TCL_OK;\n\t    break;\n\t}\n\tresult = Tcl_ListObjGetElements(interp, listPtr->listObj, &listLen,\n\t\t&elemPtrs);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tif (objc == 3) {\n\t    /*\n\t     * One element request - we return a string\n\t     */\n\n\t    Tcl_SetObjResult(interp, elemPtrs[first]);\n\t} else {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewListObj(last-first+1, elemPtrs+first));\n\t}\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_INDEX:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 1, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(index));\n\tresult = TCL_OK;\n\tbreak;\n\n    case COMMAND_INSERT:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index ?element ...?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 1, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tif (!(listPtr->state & STATE_NORMAL)) {\n\t    break;\n\t}\n\n\tresult = ListboxInsertSubCmd(listPtr, index, objc-3, objv+3);\n\tbreak;\n\n    case COMMAND_ITEMCGET: {\n\tItemAttr *attrPtr;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index option\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tif (index < 0 || index >= (int)listPtr->nElements) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"item number \\\"%s\\\" out of range\",\n\t\t    Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LISTBOX\", \"ITEM_INDEX\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tattrPtr = ListboxGetItemAttributes(interp, listPtr, index);\n\n\tobjPtr = Tk_GetOptionValue(interp, (char *) attrPtr,\n\t\tlistPtr->itemAttrOptionTable, objv[3], listPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_ITEMCONFIGURE: {\n\tItemAttr *attrPtr;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"index ?-option value ...?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\n\tif (index < 0 || index >= (int)listPtr->nElements) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"item number \\\"%s\\\" out of range\",\n\t\t    Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LISTBOX\", \"ITEM_INDEX\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tattrPtr = ListboxGetItemAttributes(interp, listPtr, index);\n\tif (objc <= 4) {\n\t    objPtr = Tk_GetOptionInfo(interp, attrPtr,\n\t\t    listPtr->itemAttrOptionTable,\n\t\t    (objc == 4) ? objv[3] : NULL, listPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    result = TCL_OK;\n\t} else {\n\t    result = ConfigureListboxItem(interp, listPtr, attrPtr,\n\t\t    objc-3, objv+3, index);\n\t}\n\tbreak;\n    }\n\n    case COMMAND_NEAREST: {\n\tint y;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"y\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = Tcl_GetIntFromObj(interp, objv[2], &y);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tindex = NearestListboxElement(listPtr, y);\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(index));\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_SCAN: {\n\tint x, y, scanCmdIndex;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"mark|dragto x y\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK\n\t\t|| Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tresult = Tcl_GetIndexFromObj(interp, objv[2], scanCommandNames,\n\t\t\"option\", 0, &scanCmdIndex);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tswitch (scanCmdIndex) {\n\tcase SCAN_MARK:\n\t    listPtr->scanMarkX = x;\n\t    listPtr->scanMarkY = y;\n\t    listPtr->scanMarkXOffset = listPtr->xOffset;\n\t    listPtr->scanMarkYIndex = listPtr->topIndex;\n\t    break;\n\tcase SCAN_DRAGTO:\n\t    ListboxScanTo(listPtr, x, y);\n\t    break;\n\t}\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_SEE: {\n\tint diff;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = GetListboxIndex(interp, listPtr, objv[2], 0, &index);\n\tif (result != TCL_OK) {\n\t    break;\n\t}\n\tif (index >= (int)listPtr->nElements) {\n\t    index = listPtr->nElements - 1;\n\t}\n\tif (index < 0) {\n\t    index = 0;\n\t}\n\tdiff = listPtr->topIndex - index;\n\tif (diff > 0) {\n\t    if (diff <= listPtr->fullLines / 3) {\n\t\tChangeListboxView(listPtr, index);\n\t    } else {\n\t\tChangeListboxView(listPtr, index - (listPtr->fullLines - 1)/2);\n\t    }\n\t} else {\n\t    diff = index - (listPtr->topIndex + listPtr->fullLines - 1);\n\t    if (diff > 0) {\n\t\tif (diff <= listPtr->fullLines / 3) {\n\t\t    ChangeListboxView(listPtr, listPtr->topIndex + diff);\n\t\t} else {\n\t\t    ChangeListboxView(listPtr, index-(listPtr->fullLines - 1)/2);\n\t\t}\n\t    }\n\t}\n\tresult = TCL_OK;\n\tbreak;\n    }\n\n    case COMMAND_SELECTION:\n\tresult = ListboxSelectionSubCmd(interp, listPtr, objc, objv);\n\tbreak;\n    case COMMAND_SIZE:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(listPtr->nElements));\n\tresult = TCL_OK;\n\tbreak;\n    case COMMAND_XVIEW:\n\tresult = ListboxXviewSubCmd(interp, listPtr, objc, objv);\n\tbreak;\n    case COMMAND_YVIEW:\n\tresult = ListboxYviewSubCmd(interp, listPtr, objc, objv);\n\tbreak;\n    }\n    Tcl_Release(listPtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxBboxSubCmd --\n *\n *\tThis procedure is invoked to process a listbox bbox request. See the\n *\tuser documentation for more information.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tFor valid indices, places the bbox of the requested element in the\n *\tinterpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxBboxSubCmd(\n    Tcl_Interp *interp,\t\t/* Pointer to the calling Tcl interpreter */\n    Listbox *listPtr,\t\t/* Information about the listbox */\n    int index)\t\t\t/* Index of the element to get bbox info on */\n{\n    Tk_Window tkwin = listPtr->tkwin;\n    int lastVisibleIndex;\n\n    /*\n     * Determine the index of the last visible item in the listbox.\n     */\n\n    lastVisibleIndex = listPtr->topIndex + listPtr->fullLines\n\t    + listPtr->partialLine;\n    if ((int)listPtr->nElements < lastVisibleIndex) {\n\tlastVisibleIndex = listPtr->nElements;\n    }\n\n    /*\n     * Only allow bbox requests for indices that are visible.\n     */\n\n    if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) {\n\tTcl_Obj *el, *results[4];\n\tconst char *stringRep;\n\tint pixelWidth, x, y, result;\n\tTcl_Size stringLen;\n\tTk_FontMetrics fm;\n\tint selBorderWidth;\n\n\t/*\n\t * Compute the pixel width of the requested element.\n\t */\n\n\tresult = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n\n\tstringRep = Tcl_GetStringFromObj(el, &stringLen);\n\tTk_GetFontMetrics(listPtr->tkfont, &fm);\n\tpixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);\n\n\tTk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n\tif (listPtr->justify == TK_JUSTIFY_LEFT) {\n\t    x = (listPtr->inset + selBorderWidth) - listPtr->xOffset;\n\t} else if (listPtr->justify == TK_JUSTIFY_RIGHT) {\n\t    x = Tk_Width(tkwin) - (listPtr->inset + selBorderWidth)\n\t\t    - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr);\n\t} else {\n\t    x = (Tk_Width(tkwin) - pixelWidth) / 2\n\t\t    - listPtr->xOffset + GetMaxOffset(listPtr) / 2;\n\t}\n\ty = ((index - listPtr->topIndex)*listPtr->lineHeight)\n\t\t+ listPtr->inset + selBorderWidth;\n\tresults[0] = Tcl_NewWideIntObj(x);\n\tresults[1] = Tcl_NewWideIntObj(y);\n\tresults[2] = Tcl_NewWideIntObj(pixelWidth);\n\tresults[3] = Tcl_NewWideIntObj(fm.linespace);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxSelectionSubCmd --\n *\n *\tThis procedure is invoked to process the selection sub command for\n *\tlistbox widgets.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay set the interpreter's result field.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxSelectionSubCmd(\n    Tcl_Interp *interp,\t\t/* Pointer to the calling Tcl interpreter */\n    Listbox *listPtr,\t\t/* Information about the listbox */\n    Tcl_Size objc,\t\t\t/* Number of arguments in the objv array */\n    Tcl_Obj *const objv[])\t/* Array of arguments to the procedure */\n{\n    int selCmdIndex;\n    Tcl_Size first, last;\n    int result = TCL_OK;\n\n    if (objc != 4 && objc != 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option index ?index?\");\n\treturn TCL_ERROR;\n    }\n    result = GetListboxIndex(interp, listPtr, objv[3], 0, &first);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    last = first;\n    if (objc == 5) {\n\tresult = GetListboxIndex(interp, listPtr, objv[4], 0, &last);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n    result = Tcl_GetIndexFromObj(interp, objv[2], selCommandNames,\n\t    \"option\", 0, &selCmdIndex);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * Only allow 'selection includes' to respond if disabled. [Bug #632514]\n     */\n\n    if ((listPtr->state == STATE_DISABLED)\n\t    && (selCmdIndex != SELECTION_INCLUDES)) {\n\treturn TCL_OK;\n    }\n\n    switch (selCmdIndex) {\n    case SELECTION_ANCHOR:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t    return TCL_ERROR;\n\t}\n\tif (first >= (int)listPtr->nElements) {\n\t    first = listPtr->nElements - 1;\n\t}\n\tif (first < 0) {\n\t    first = 0;\n\t}\n\tlistPtr->selectAnchor = first;\n\tresult = TCL_OK;\n\tbreak;\n    case SELECTION_CLEAR:\n\tresult = ListboxSelect(listPtr, first, last, 0);\n\tbreak;\n    case SELECTION_INCLUDES:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\tTcl_FindHashEntry(listPtr->selection, KEY(first)) != NULL));\n\tresult = TCL_OK;\n\tbreak;\n    case SELECTION_SET:\n\tresult = ListboxSelect(listPtr, first, last, 1);\n\tbreak;\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxXviewSubCmd --\n *\n *\tProcess the listbox \"xview\" subcommand.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay change the listbox viewing area; may set the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxXviewSubCmd(\n    Tcl_Interp *interp,\t\t/* Pointer to the calling Tcl interpreter */\n    Listbox *listPtr,\t\t/* Information about the listbox */\n    Tcl_Size objc,\t\t\t/* Number of arguments in the objv array */\n    Tcl_Obj *const objv[])\t/* Array of arguments to the procedure */\n{\n    int index, count, windowWidth, windowUnits;\n    int offset = 0;\t\t/* Initialized to stop gcc warnings. */\n    double fraction;\n    int selBorderWidth;\n\n\tTk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n    windowWidth = Tk_Width(listPtr->tkwin)\n\t    - 2 * (listPtr->inset + selBorderWidth);\n    if (objc == 2) {\n\tTcl_Obj *results[2];\n\n\tif (listPtr->maxWidth == 0) {\n\t    results[0] = Tcl_NewDoubleObj(0.0);\n\t    results[1] = Tcl_NewDoubleObj(1.0);\n\t} else {\n\t    double fraction2;\n\n\t    fraction = listPtr->xOffset / (double) listPtr->maxWidth;\n\t    fraction2 = (listPtr->xOffset + windowWidth)\n\t\t    / (double) listPtr->maxWidth;\n\t    if (fraction2 > 1.0) {\n\t\tfraction2 = 1.0;\n\t    }\n\t    results[0] = Tcl_NewDoubleObj(fraction);\n\t    results[1] = Tcl_NewDoubleObj(fraction2);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n    } else if (objc == 3) {\n\tif (Tcl_GetIntFromObj(interp, objv[2], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tChangeListboxOffset(listPtr, index*listPtr->xScrollUnit);\n    } else {\n\tswitch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {\n\tcase TK_SCROLL_MOVETO:\n\t    offset = (int) (fraction*listPtr->maxWidth + 0.5);\n\t    break;\n\tcase TK_SCROLL_PAGES:\n\t    windowUnits = windowWidth / listPtr->xScrollUnit;\n\t    if (windowUnits > 2) {\n\t\toffset = listPtr->xOffset\n\t\t\t+ count*listPtr->xScrollUnit*(windowUnits-2);\n\t    } else {\n\t\toffset = listPtr->xOffset + count*listPtr->xScrollUnit;\n\t    }\n\t    break;\n\tcase TK_SCROLL_UNITS:\n\t    offset = listPtr->xOffset + count*listPtr->xScrollUnit;\n\t    break;\n\tdefault:\n\t    return TCL_ERROR;\n\t}\n\tChangeListboxOffset(listPtr, offset);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxYviewSubCmd --\n *\n *\tProcess the listbox \"yview\" subcommand.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay change the listbox viewing area; may set the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxYviewSubCmd(\n    Tcl_Interp *interp,\t\t/* Pointer to the calling Tcl interpreter */\n    Listbox *listPtr,\t\t/* Information about the listbox */\n    Tcl_Size objc,\t\t\t/* Number of arguments in the objv array */\n    Tcl_Obj *const objv[])\t/* Array of arguments to the procedure */\n{\n    Tcl_Size index;\n    int count;\n    double fraction;\n\n    if (objc == 2) {\n\tTcl_Obj *results[2];\n\n\tif (listPtr->nElements == 0) {\n\t    results[0] = Tcl_NewDoubleObj(0.0);\n\t    results[1] = Tcl_NewDoubleObj(1.0);\n\t} else {\n\t    double fraction2, numEls = (double) listPtr->nElements;\n\n\t    fraction = listPtr->topIndex / numEls;\n\t    fraction2 = (listPtr->topIndex+listPtr->fullLines) / numEls;\n\t    if (fraction2 > 1.0) {\n\t\tfraction2 = 1.0;\n\t    }\n\t    results[0] = Tcl_NewDoubleObj(fraction);\n\t    results[1] = Tcl_NewDoubleObj(fraction2);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n    } else if (objc == 3) {\n\tif (GetListboxIndex(interp, listPtr, objv[2], 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tChangeListboxView(listPtr, index);\n    } else {\n\tswitch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {\n\tcase TK_SCROLL_MOVETO:\n\t    index = (Tcl_Size)(listPtr->nElements*fraction + 0.5);\n\t    break;\n\tcase TK_SCROLL_PAGES:\n\t    if (listPtr->fullLines > 2) {\n\t\tindex = listPtr->topIndex + count*(listPtr->fullLines-2);\n\t    } else {\n\t\tindex = listPtr->topIndex + count;\n\t    }\n\t    break;\n\tcase TK_SCROLL_UNITS:\n\t    index = listPtr->topIndex + count;\n\t    break;\n\tdefault:\n\t    return TCL_ERROR;\n\t}\n\tChangeListboxView(listPtr, index);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxGetItemAttributes --\n *\n *\tReturns a pointer to the ItemAttr record for a given index, creating\n *\tone if it does not already exist.\n *\n * Results:\n *\tPointer to an ItemAttr record.\n *\n * Side effects:\n *\tMemory may be allocated for the ItemAttr record.\n *\n *----------------------------------------------------------------------\n */\n\nstatic ItemAttr *\nListboxGetItemAttributes(\n    Tcl_Interp *interp,\t\t/* Pointer to the calling Tcl interpreter */\n    Listbox *listPtr,\t\t/* Information about the listbox */\n    int index)\t\t\t/* Index of the item to retrieve attributes\n\t\t\t\t * for. */\n{\n    int isNew;\n    Tcl_HashEntry *entry;\n    ItemAttr *attrs;\n\n    entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, KEY(index), &isNew);\n    if (isNew) {\n\tattrs = (ItemAttr *)Tcl_Alloc(sizeof(ItemAttr));\n\tattrs->border = NULL;\n\tattrs->selBorder = NULL;\n\tattrs->fgColor = NULL;\n\tattrs->selFgColor = NULL;\n\tTk_InitOptions(interp, attrs, listPtr->itemAttrOptionTable,\n\t\tlistPtr->tkwin);\n\tTcl_SetHashValue(entry, attrs);\n    } else {\n\tattrs = (ItemAttr *)Tcl_GetHashValue(entry);\n    }\n    return attrs;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyListbox --\n *\n *\tThis procedure is invoked by Tcl_EventuallyFree or Tcl_Release to\n *\tclean up the internal structure of a listbox at a safe time (when\n *\tno-one is using it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the listbox is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyListbox(\n    void *memPtr)\t\t/* Info about listbox widget. */\n{\n    Listbox *listPtr = (Listbox *)memPtr;\n    Tcl_HashEntry *entry;\n    Tcl_HashSearch search;\n\n    /*\n     * If we have an internal list object, free it.\n     */\n\n    if (listPtr->listObj != NULL) {\n\tTcl_DecrRefCount(listPtr->listObj);\n\tlistPtr->listObj = NULL;\n    }\n\n    if (listPtr->listVarNameObj != NULL) {\n\tTcl_UntraceVar2(listPtr->interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tListboxListVarProc, listPtr);\n    }\n\n    /*\n     * Free the selection hash table.\n     */\n\n    Tcl_DeleteHashTable(listPtr->selection);\n    Tcl_Free(listPtr->selection);\n\n    /*\n     * Free the item attribute hash table.\n     */\n\n    for (entry = Tcl_FirstHashEntry(listPtr->itemAttrTable, &search);\n\t    entry != NULL; entry = Tcl_NextHashEntry(&search)) {\n\tTcl_Free(Tcl_GetHashValue(entry));\n    }\n    Tcl_DeleteHashTable(listPtr->itemAttrTable);\n    Tcl_Free(listPtr->itemAttrTable);\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    if (listPtr->textGC != NULL) {\n\tTk_FreeGC(listPtr->display, listPtr->textGC);\n    }\n    if (listPtr->selTextGC != NULL) {\n\tTk_FreeGC(listPtr->display, listPtr->selTextGC);\n    }\n    if (listPtr->gray != None) {\n\tTk_FreeBitmap(Tk_Display(listPtr->tkwin), listPtr->gray);\n    }\n\n    Tk_FreeConfigOptions(listPtr, listPtr->optionTable,\n\t    listPtr->tkwin);\n    Tcl_Release(listPtr->tkwin);\n    listPtr->tkwin = NULL;\n    Tcl_Free(listPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyListboxOptionTables --\n *\n *\tThis procedure is registered as an exit callback when the listbox\n *\tcommand is first called. It cleans up the OptionTables structure\n *\tallocated by that command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees memory.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyListboxOptionTables(\n    void *clientData,\t/* Pointer to the OptionTables struct */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* Pointer to the calling interp */\n{\n    Tcl_Free(clientData);\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureListbox --\n *\n *\tThis procedure is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a listbox\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor listPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureListbox(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Listbox *listPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    Tk_SavedOptions savedOptions;\n    Tcl_Obj *oldListObj = NULL;\n    Tcl_Obj *errorResult = NULL;\n    int oldExport, error;\n    int borderWidth, highlightWidth;\n\n    oldExport = (listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp));\n    if (listPtr->listVarNameObj != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tListboxListVarProc, listPtr);\n    }\n\n    for (error = 0; error <= 1; error++) {\n\tif (!error) {\n\t    /*\n\t     * First pass: set options to new values.\n\t     */\n\n\t    if (Tk_SetOptions(interp, listPtr,\n\t\t    listPtr->optionTable, objc, objv,\n\t\t    listPtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * Second pass: restore options to old values.\n\t     */\n\n\t    errorResult = Tcl_GetObjResult(interp);\n\t    Tcl_IncrRefCount(errorResult);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t}\n\n\t/*\n\t * A few options need special processing, such as setting the\n\t * background from a 3-D border.\n\t */\n\n\tTk_SetBackgroundFromBorder(listPtr->tkwin, listPtr->normalBorder);\n\n\tTk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->borderWidthObj, &borderWidth);\n\tTk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->highlightWidthObj, &highlightWidth);\n\tlistPtr->inset = highlightWidth + borderWidth;\n\n\t/*\n\t * Claim the selection if we've suddenly started exporting it and\n\t * there is a selection to export and this interp is unsafe.\n\t */\n\n\tif (listPtr->exportSelection && (!oldExport)\n\t\t&& (!Tcl_IsSafe(listPtr->interp))\n\t\t&& (listPtr->numSelected != 0)) {\n\t    Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY,\n\t\t    ListboxLostSelection, listPtr);\n\t}\n\n\t/*\n\t * Verify the current status of the list var.\n\t * PREVIOUS STATE | NEW STATE  | ACTION\n\t * ---------------+------------+----------------------------------\n\t * no listvar     | listvar    | If listvar does not exist, create it\n\t *\t\t\t\t and copy the internal list obj's\n\t *\t\t\t\t content to the new var. If it does\n\t *\t\t\t\t exist, toss the internal list obj.\n\t *\n\t * listvar\t  | no listvar | Copy old listvar content to the\n\t *\t\t\t\t internal list obj\n\t *\n\t * listvar\t  | listvar    | no special action\n\t *\n\t * no listvar     | no listvar | no special action\n\t */\n\n\toldListObj = listPtr->listObj;\n\tif (listPtr->listVarNameObj != NULL) {\n\t    Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, Tcl_GetString(listPtr->listVarNameObj),\n\t\t    NULL, TCL_GLOBAL_ONLY);\n\t    Tcl_Size dummy;\n\n\t    if (listVarObj == NULL) {\n\t\tlistVarObj = (oldListObj ? oldListObj : Tcl_NewObj());\n\t\tif (Tcl_SetVar2Ex(interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\t\tlistVarObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t\t\t== NULL) {\n\t\t    continue;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Make sure the object is a good list object.\n\t     */\n\n\t    if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy)\n\t\t    != TCL_OK) {\n\t\tTcl_AppendResult(listPtr->interp,\n\t\t\t\": invalid -listvariable value\", (char *)NULL);\n\t\tcontinue;\n\t    }\n\n\t    listPtr->listObj = listVarObj;\n\t    Tcl_TraceVar2(listPtr->interp, Tcl_GetString(listPtr->listVarNameObj),\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    ListboxListVarProc, listPtr);\n\t} else if (listPtr->listObj == NULL) {\n\t    listPtr->listObj = Tcl_NewObj();\n\t}\n\tTcl_IncrRefCount(listPtr->listObj);\n\tif (oldListObj != NULL) {\n\t    Tcl_DecrRefCount(oldListObj);\n\t}\n\tbreak;\n    }\n    if (!error) {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n\n    /*\n     * Make sure that the list length is correct.\n     */\n\n    Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);\n\n    if (error) {\n\tTcl_SetObjResult(interp, errorResult);\n\tTcl_DecrRefCount(errorResult);\n\treturn TCL_ERROR;\n    }\n    ListboxWorldChanged(listPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureListboxItem --\n *\n *\tThis procedure is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a listbox\n *\titem.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor a listbox item; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureListboxItem(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Listbox *listPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    ItemAttr *attrs,\t\t/* Information about the item to configure */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[],\t/* Arguments. */\n    Tcl_Size index)\t\t\t/* Index of the listbox item being configure */\n{\n    Tk_SavedOptions savedOptions;\n\n    if (Tk_SetOptions(interp, attrs,\n\t    listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin,\n\t    &savedOptions, NULL) != TCL_OK) {\n\tTk_RestoreSavedOptions(&savedOptions);\n\treturn TCL_ERROR;\n    }\n    Tk_FreeSavedOptions(&savedOptions);\n\n    /*\n     * Redraw this index - ListboxWorldChanged would need to be called if item\n     * attributes were checked in the \"world\".\n     */\n\n    EventuallyRedrawRange(listPtr, index, index);\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ListboxWorldChanged --\n *\n *\tThis procedure is called when the world has changed in some way and\n *\tthe widget needs to recompute all its graphics contexts and determine\n *\tits new geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tListbox will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nListboxWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC gc;\n    unsigned long mask;\n    Listbox *listPtr = (Listbox *)instanceData;\n\n    if (listPtr->state & STATE_NORMAL) {\n\tgcValues.foreground = listPtr->fgColorPtr->pixel;\n\tgcValues.graphics_exposures = False;\n\tmask = GCForeground | GCFont | GCGraphicsExposures;\n    } else if (listPtr->dfgColorPtr != NULL) {\n\tgcValues.foreground = listPtr->dfgColorPtr->pixel;\n\tgcValues.graphics_exposures = False;\n\tmask = GCForeground | GCFont | GCGraphicsExposures;\n    } else {\n\tgcValues.foreground = listPtr->fgColorPtr->pixel;\n\tmask = GCForeground | GCFont;\n\tif (listPtr->gray == None) {\n\t    listPtr->gray = Tk_GetBitmap(NULL, listPtr->tkwin, \"gray50\");\n\t}\n\tif (listPtr->gray != None) {\n\t    gcValues.fill_style = FillStippled;\n\t    gcValues.stipple = listPtr->gray;\n\t    mask |= GCFillStyle | GCStipple;\n\t}\n    }\n\n    gcValues.font = Tk_FontId(listPtr->tkfont);\n    gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);\n    if (listPtr->textGC != NULL) {\n\tTk_FreeGC(listPtr->display, listPtr->textGC);\n    }\n    listPtr->textGC = gc;\n\n    if (listPtr->selFgColorPtr != NULL) {\n\tgcValues.foreground = listPtr->selFgColorPtr->pixel;\n    }\n    gcValues.font = Tk_FontId(listPtr->tkfont);\n    mask = GCForeground | GCFont;\n    gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);\n    if (listPtr->selTextGC != NULL) {\n\tTk_FreeGC(listPtr->display, listPtr->selTextGC);\n    }\n    listPtr->selTextGC = gc;\n\n    /*\n     * Register the desired geometry for the window and arrange for the window\n     * to be redisplayed.\n     */\n\n    ListboxComputeGeometry(listPtr, 1, 1, 1);\n    listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;\n    EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayListbox --\n *\n *\tThis procedure redraws the contents of a listbox window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayListbox(\n    void *clientData)\t/* Information about window. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n    Tk_Window tkwin = listPtr->tkwin;\n    Display *disp = listPtr->display;\n    GC gc;\n    int i, limit, x, y, prevSelected, freeGC;\n    Tcl_Size stringLen;\n    Tk_FontMetrics fm;\n    Tcl_Obj *curElement;\n    Tcl_HashEntry *entry;\n    const char *stringRep;\n    ItemAttr *attrs;\n    Tk_3DBorder selectedBg;\n    XGCValues gcValues;\n    unsigned long mask;\n    int left, right;\t\t/* Non-zero values here indicate that the left\n\t\t\t\t * or right edge of the listbox is\n\t\t\t\t * off-screen. */\n    Pixmap pixmap;\n    int textWidth;\n    int borderWidth, selBorderWidth, highlightWidth;\n\n    listPtr->flags &= ~REDRAW_PENDING;\n    if (listPtr->flags & LISTBOX_DELETED) {\n\treturn;\n    }\n\n    if (listPtr->flags & MAXWIDTH_IS_STALE) {\n\tListboxComputeGeometry(listPtr, 0, 1, 0);\n\tlistPtr->flags &= ~MAXWIDTH_IS_STALE;\n\tlistPtr->flags |= UPDATE_H_SCROLLBAR;\n    }\n\n    Tcl_Preserve(listPtr);\n    if (listPtr->flags & UPDATE_V_SCROLLBAR) {\n\tListboxUpdateVScrollbar(listPtr);\n\tif ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) {\n\t    Tcl_Release(listPtr);\n\t    return;\n\t}\n    }\n    if (listPtr->flags & UPDATE_H_SCROLLBAR) {\n\tListboxUpdateHScrollbar(listPtr);\n\tif ((listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(tkwin)) {\n\t    Tcl_Release(listPtr);\n\t    return;\n\t}\n    }\n    listPtr->flags &= ~(REDRAW_PENDING|UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR);\n    Tcl_Release(listPtr);\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Redrawing is done in a temporary pixmap that is allocated here and\n     * freed at the end of the procedure. All drawing is done to the pixmap,\n     * and the pixmap is copied to the screen at the end of the procedure.\n     * This provides the smoothest possible visual effects (no flashing on the\n     * screen).\n     */\n\n    pixmap = Tk_GetPixmap(disp, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    Tk_Fill3DRectangle(tkwin, pixmap, listPtr->normalBorder, 0, 0,\n\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\n    /*\n     * Display each item in the listbox.\n     */\n\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n    limit = listPtr->topIndex + listPtr->fullLines + listPtr->partialLine - 1;\n    if (limit >= (int)listPtr->nElements) {\n\tlimit = listPtr->nElements-1;\n    }\n    left = right = 0;\n    if (listPtr->xOffset > 0) {\n\tleft = selBorderWidth + 1;\n    }\n    if ((listPtr->maxWidth - listPtr->xOffset) > (Tk_Width(listPtr->tkwin)\n\t    - 2 * (listPtr->inset + selBorderWidth))) {\n\tright = selBorderWidth + 1;\n    }\n    prevSelected = 0;\n\n    for (i = listPtr->topIndex; i <= limit; i++) {\n\tint width = Tk_Width(tkwin);\t/* zeroth approx to silence warning */\n\n\tx = listPtr->inset;\n\ty = (i - listPtr->topIndex) * listPtr->lineHeight + listPtr->inset;\n\tgc = listPtr->textGC;\n\tfreeGC = 0;\n\n\t/*\n\t * Lookup this item in the item attributes table, to see if it has\n\t * special foreground/background colors.\n\t */\n\n\tentry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));\n\n\t/*\n\t * If the listbox is enabled, items may be drawn differently; they may\n\t * be drawn selected, or they may have special foreground or background\n\t * colors.\n\t */\n\n\tif (listPtr->state & STATE_NORMAL) {\n\t    if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) {\n\t\t/*\n\t\t * Selected items are drawn differently.\n\t\t */\n\n\t\twidth = Tk_Width(tkwin) - 2 * listPtr->inset;\n\t\tselectedBg = listPtr->selBorder;\n\t\tgc = listPtr->selTextGC;\n\n\t\t/*\n\t\t * If the widget doesn't have the focus and the value of the\n\t\t * -inactiveselectbackground option is not empty then use this\n\t\t * value.  Otherwise, if there is attribute information for\n\t\t * this item, then adjust the drawing accordingly.\n\t\t */\n\n\t\tif (!(listPtr->flags & GOT_FOCUS) &&\n\t\t\tlistPtr->inactiveSelBorder) {\n\t\t    selectedBg = listPtr->inactiveSelBorder;\n\n\t\t    if (listPtr->inactiveSelFgColorPtr) {\n\t\t\tgcValues.foreground =\n\t\t\t\tlistPtr->inactiveSelFgColorPtr->pixel;\n\t\t\tgcValues.font = Tk_FontId(listPtr->tkfont);\n\t\t\tgcValues.graphics_exposures = False;\n\t\t\tmask = GCForeground | GCFont | GCGraphicsExposures;\n\t\t\tgc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);\n\t\t\tfreeGC = 1;\n\t\t    }\n\t\t} else if (entry != NULL) {\n\t\t    attrs = (ItemAttr *)Tcl_GetHashValue(entry);\n\n\t\t    if (attrs->selBorder != NULL) {\n\t\t\tselectedBg = attrs->selBorder;\n\t\t    }\n\n\t\t    if (attrs->selFgColor != NULL) {\n\t\t\tgcValues.foreground = attrs->selFgColor->pixel;\n\t\t\tgcValues.font = Tk_FontId(listPtr->tkfont);\n\t\t\tgcValues.graphics_exposures = False;\n\t\t\tmask = GCForeground | GCFont | GCGraphicsExposures;\n\t\t\tgc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);\n\t\t\tfreeGC = 1;\n\t\t    }\n\t\t}\n\n\t\tTk_Fill3DRectangle(tkwin, pixmap, selectedBg, x, y,\n\t\t\twidth, listPtr->lineHeight, 0, TK_RELIEF_FLAT);\n\n\t\t/*\n\t\t * Draw beveled edges around the selection, if there are\n\t\t * visible edges next to this element. Special considerations:\n\t\t *\n\t\t * 1. The left and right bevels may not be visible if\n\t\t *\thorizontal scrolling is enabled (the \"left\" & \"right\"\n\t\t *\tvariables are zero to indicate that the corresponding\n\t\t *\tbevel is visible).\n\t\t * 2. Top and bottom bevels are only drawn if this is the\n\t\t *\tfirst or last seleted item.\n\t\t * 3. If the left or right bevel isn't visible, then the\n\t\t *\t\"left\" & \"right\" vars, computed above, have non-zero\n\t\t *\tvalues that extend the top and bottom bevels so that\n\t\t *\tthe mitered corners are off-screen.\n\t\t */\n\n\t\t/* Draw left bevel */\n\t\tif (left == 0) {\n\t\t    Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,\n\t\t\t    x, y, selBorderWidth, listPtr->lineHeight,\n\t\t\t    1, TK_RELIEF_RAISED);\n\t\t}\n\t\t/* Draw right bevel */\n\t\tif (right == 0) {\n\t\t    Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,\n\t\t\t    x + width - selBorderWidth, y,\n\t\t\t    selBorderWidth, listPtr->lineHeight,\n\t\t\t    0, TK_RELIEF_RAISED);\n\t\t}\n\t\t/* Draw top bevel */\n\t\tif (!prevSelected) {\n\t\t    Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg,\n\t\t\t    x-left, y, width+left+right,\n\t\t\t    selBorderWidth,\n\t\t\t    1, 1, 1, TK_RELIEF_RAISED);\n\t\t}\n\t\t/* Draw bottom bevel */\n\t\tif (i + 1 == (int)listPtr->nElements ||\n\t\t\t!Tcl_FindHashEntry(listPtr->selection, KEY(i + 1))) {\n\t\t    Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg, x-left,\n\t\t\t    y + listPtr->lineHeight - selBorderWidth,\n\t\t\t    width+left+right, selBorderWidth, 0, 0, 0,\n\t\t\t    TK_RELIEF_RAISED);\n\t\t}\n\t\tprevSelected = 1;\n\t    } else {\n\t\t/*\n\t\t * If there is an item attributes record for this item, draw\n\t\t * the background box and set the foreground color accordingly.\n\t\t */\n\n\t\tif (entry != NULL) {\n\t\t    attrs = (ItemAttr *)Tcl_GetHashValue(entry);\n\n\t\t    /*\n\t\t     * If the item has its own background color, draw it now.\n\t\t     */\n\n\t\t    if (attrs->border != NULL) {\n\t\t\twidth = Tk_Width(tkwin) - 2 * listPtr->inset;\n\t\t\tTk_Fill3DRectangle(tkwin, pixmap, attrs->border, x, y,\n\t\t\t\twidth, listPtr->lineHeight, 0, TK_RELIEF_FLAT);\n\t\t    }\n\n\t\t    /*\n\t\t     * If the item has its own foreground, use it to override\n\t\t     * the value in the gcValues structure.\n\t\t     */\n\n\t\t    if ((listPtr->state & STATE_NORMAL)\n\t\t\t    && attrs->fgColor != NULL) {\n\t\t\tgcValues.foreground = attrs->fgColor->pixel;\n\t\t\tgcValues.font = Tk_FontId(listPtr->tkfont);\n\t\t\tgcValues.graphics_exposures = False;\n\t\t\tmask = GCForeground | GCFont | GCGraphicsExposures;\n\t\t\tgc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);\n\t\t\tfreeGC = 1;\n\t\t    }\n\t\t}\n\t\tprevSelected = 0;\n\t    }\n\t}\n\n\t/*\n\t * Draw the actual text of this item.\n\t */\n\n\tTcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);\n\tstringRep = Tcl_GetStringFromObj(curElement, &stringLen);\n\ttextWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);\n\n\tTk_GetFontMetrics(listPtr->tkfont, &fm);\n\ty += fm.ascent + selBorderWidth;\n\n\tif (listPtr->justify == TK_JUSTIFY_LEFT) {\n\t    x = (listPtr->inset + selBorderWidth) - listPtr->xOffset;\n\t} else if (listPtr->justify == TK_JUSTIFY_RIGHT) {\n\t    x = Tk_Width(tkwin) - (listPtr->inset + selBorderWidth)\n\t\t    - textWidth - listPtr->xOffset + GetMaxOffset(listPtr);\n\t} else {\n\t    x = (Tk_Width(tkwin) - textWidth)/2\n\t\t    - listPtr->xOffset + GetMaxOffset(listPtr)/2;\n\t}\n\n\tTk_DrawChars(disp, pixmap, gc, listPtr->tkfont,\n\t\tstringRep, stringLen, x, y);\n\n\t/*\n\t * If this is the active element, apply the activestyle to it.\n\t */\n\n\tif ((i == listPtr->active) && (listPtr->flags & GOT_FOCUS)) {\n\t    if (listPtr->activeStyle == ACTIVE_STYLE_UNDERLINE) {\n\t\t/*\n\t\t * Underline the text.\n\t\t */\n\n\t\tTk_UnderlineChars(disp, pixmap, gc, listPtr->tkfont,\n\t\t\tstringRep, x, y, 0, stringLen);\n\t    } else if (listPtr->activeStyle == ACTIVE_STYLE_DOTBOX) {\n\t\t/*\n\t\t * Draw a dotted box around the text.\n\t\t */\n\n\t\tx = listPtr->inset;\n\t\ty = (i - listPtr->topIndex) * listPtr->lineHeight\n\t\t\t+ listPtr->inset;\n\t\twidth = Tk_Width(tkwin) - 2 * listPtr->inset;\n\n\t\tTkDrawDottedRect(disp, pixmap, gc, x, y,\n\t\t\twidth, listPtr->lineHeight);\n\n\t\tif (!freeGC) {\n\t\t    /*\n\t\t     * Don't bother changing if it is about to be freed.\n\t\t     */\n\n\t\t    gcValues.line_style = LineSolid;\n\t\t    XChangeGC(disp, gc, GCLineStyle, &gcValues);\n\t\t}\n\t    }\n\t}\n\n\tif (freeGC) {\n\t    Tk_FreeGC(disp, gc);\n\t}\n    }\n\n    /*\n     * Redraw the border for the listbox to make sure that it's on top of any\n     * of the text of the listbox entries.\n     */\n\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->highlightWidthObj, &highlightWidth);\n    Tk_Draw3DRectangle(tkwin, pixmap, listPtr->normalBorder,\n\t    highlightWidth, highlightWidth,\n\t    Tk_Width(tkwin) - 2 * highlightWidth,\n\t    Tk_Height(tkwin) - 2 * highlightWidth,\n\t    borderWidth, listPtr->relief);\n    if (highlightWidth > 0) {\n\tGC fgGC, bgGC;\n\n\tbgGC = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap);\n\tif (listPtr->flags & GOT_FOCUS) {\n\t    fgGC = Tk_GCForColor(listPtr->highlightColorPtr, pixmap);\n\t    Tk_DrawHighlightBorder(tkwin, fgGC, bgGC,\n\t\t    highlightWidth, pixmap);\n\t} else {\n\t    Tk_DrawHighlightBorder(tkwin, bgGC, bgGC,\n\t\t    highlightWidth, pixmap);\n\t}\n    }\n#ifndef TK_NO_DOUBLE_BUFFERING\n    XCopyArea(disp, pixmap, Tk_WindowId(tkwin), listPtr->textGC, 0, 0,\n\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(disp, pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxComputeGeometry --\n *\n *\tThis procedure is invoked to recompute geometry information such as\n *\tthe sizes of the elements and the overall dimensions desired for the\n *\tlistbox.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGeometry information is updated and a new requested size is registered\n *\tfor the widget. Internal border and gridding information is also set.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxComputeGeometry(\n    Listbox *listPtr,\t\t/* Listbox whose geometry is to be\n\t\t\t\t * recomputed. */\n    int fontChanged,\t\t/* Non-zero means the font may have changed so\n\t\t\t\t * per-element width information also has to\n\t\t\t\t * be computed. */\n    int maxIsStale,\t\t/* Non-zero means the \"maxWidth\" field may no\n\t\t\t\t * longer be up-to-date and must be\n\t\t\t\t * recomputed. If fontChanged is 1 then this\n\t\t\t\t * must be 1. */\n    int updateGrid)\t\t/* Non-zero means call Tk_SetGrid or\n\t\t\t\t * Tk_UnsetGrid to update gridding for the\n\t\t\t\t * window. */\n{\n    int width, height, pixelWidth, pixelHeight, i, result;\n    Tcl_Size textLength;\n    Tk_FontMetrics fm;\n    Tcl_Obj *element;\n    const char *text;\n    int selBorderWidth;\n\n    if (fontChanged || maxIsStale) {\n\tlistPtr->xScrollUnit = Tk_TextWidth(listPtr->tkfont, \"0\", 1);\n\tif (listPtr->xScrollUnit == 0) {\n\t    listPtr->xScrollUnit = 1;\n\t}\n\tlistPtr->maxWidth = 0;\n\tfor (i = 0; i < (int)listPtr->nElements; i++) {\n\t    /*\n\t     * Compute the pixel width of the current element.\n\t     */\n\n\t    result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,\n\t\t    &element);\n\t    if (result != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t    text = Tcl_GetStringFromObj(element, &textLength);\n\t    Tk_GetFontMetrics(listPtr->tkfont, &fm);\n\t    pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength);\n\t    if (pixelWidth > listPtr->maxWidth) {\n\t\tlistPtr->maxWidth = pixelWidth;\n\t    }\n\t}\n    }\n\n    Tk_GetFontMetrics(listPtr->tkfont, &fm);\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n    listPtr->lineHeight = fm.linespace + 1 + 2 * selBorderWidth;\n    width = listPtr->width;\n    if (width <= 0) {\n\twidth = (listPtr->maxWidth + listPtr->xScrollUnit - 1)\n\t\t/ listPtr->xScrollUnit;\n\tif (width < 1) {\n\t    width = 1;\n\t}\n    }\n    pixelWidth = width*listPtr->xScrollUnit + 2 * listPtr->inset\n\t    + 2 * selBorderWidth;\n    height = listPtr->height;\n    if (listPtr->height <= 0) {\n\theight = (int)listPtr->nElements;\n\tif (height < 1) {\n\t    height = 1;\n\t}\n    }\n    pixelHeight = height*listPtr->lineHeight + 2 * listPtr->inset;\n    Tk_GeometryRequest(listPtr->tkwin, pixelWidth, pixelHeight);\n    Tk_SetInternalBorder(listPtr->tkwin, listPtr->inset);\n    if (updateGrid) {\n\tif (listPtr->setGrid) {\n\t    Tk_SetGrid(listPtr->tkwin, width, height, listPtr->xScrollUnit,\n\t\t    listPtr->lineHeight);\n\t} else {\n\t    Tk_UnsetGrid(listPtr->tkwin);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxInsertSubCmd --\n *\n *\tThis procedure is invoked to handle the listbox \"insert\" subcommand.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tNew elements are added to the listbox pointed to by listPtr; a refresh\n *\tcallback is registered for the listbox.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxInsertSubCmd(\n    Listbox *listPtr,\t/* Listbox that is to get the new elements. */\n    Tcl_Size index,\t\t/* Add the new elements before this\n\t\t\t\t * element. */\n    Tcl_Size objc,\t\t\t/* Number of new elements to add. */\n    Tcl_Obj *const objv[])\t/* New elements (one per entry). */\n{\n    int oldMaxWidth, pixelWidth, result;\n    Tcl_Size i, length;\n    Tcl_Obj *newListObj;\n    const char *stringRep;\n\n    oldMaxWidth = listPtr->maxWidth;\n    for (i = 0; i < objc; i++) {\n\t/*\n\t * Check if any of the new elements are wider than the current widest;\n\t * if so, update our notion of \"widest.\"\n\t */\n\n\tstringRep = Tcl_GetStringFromObj(objv[i], &length);\n\tpixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);\n\tif (pixelWidth > listPtr->maxWidth) {\n\t    listPtr->maxWidth = pixelWidth;\n\t}\n    }\n\n    /*\n     * Adjust selection and attribute information for every index after the\n     * first index.\n     */\n\n    MigrateHashEntries(listPtr->selection, index, listPtr->nElements-1, objc);\n    MigrateHashEntries(listPtr->itemAttrTable, index, listPtr->nElements-1,\n\t    objc);\n\n    /*\n     * If the object is shared, duplicate it before writing to it.\n     */\n\n    if (Tcl_IsShared(listPtr->listObj)) {\n\tnewListObj = Tcl_DuplicateObj(listPtr->listObj);\n    } else {\n\tnewListObj = listPtr->listObj;\n    }\n    result = Tcl_ListObjReplace(listPtr->interp, newListObj, index, 0,\n\t    objc, objv);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * Replace the current object and set attached listvar, if any. This may\n     * error if listvar points to a var in a deleted namespace, but we ignore\n     * those errors. If the namespace is recreated, it will auto-sync with the\n     * current value. [Bug 1424513]\n     */\n\n    Tcl_IncrRefCount(newListObj);\n    Tcl_DecrRefCount(listPtr->listObj);\n    listPtr->listObj = newListObj;\n    if (listPtr->listVarNameObj != NULL) {\n\tTcl_SetVar2Ex(listPtr->interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\tlistPtr->listObj, TCL_GLOBAL_ONLY);\n    }\n\n    /*\n     * Get the new list length.\n     */\n\n    Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);\n\n    /*\n     * Update the \"special\" indices (anchor, topIndex, active) to account for\n     * the renumbering that just occurred. Then arrange for the new\n     * information to be displayed.\n     */\n\n    if (index <= listPtr->selectAnchor) {\n\tlistPtr->selectAnchor += objc;\n    }\n    if (index < listPtr->topIndex) {\n\tlistPtr->topIndex += objc;\n    }\n    if (index <= listPtr->active) {\n\tlistPtr->active += objc;\n\tif ((listPtr->active >= (int)listPtr->nElements) &&\n\t\t((int)listPtr->nElements > 0)) {\n\t    listPtr->active = listPtr->nElements-1;\n\t}\n    }\n    listPtr->flags |= UPDATE_V_SCROLLBAR;\n    if (listPtr->maxWidth != oldMaxWidth) {\n\tlistPtr->flags |= UPDATE_H_SCROLLBAR;\n    }\n    ListboxComputeGeometry(listPtr, 0, 0, 0);\n    EventuallyRedrawRange(listPtr, index, listPtr->nElements-1);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxDeleteSubCmd --\n *\n *\tProcess a listbox \"delete\" subcommand by removing one or more elements\n *\tfrom a listbox widget.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tThe listbox will be modified and (eventually) redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxDeleteSubCmd(\n    Listbox *listPtr,\t/* Listbox widget to modify. */\n    int first,\t\t\t/* Index of first element to delete. */\n    int last)\t\t\t/* Index of last element to delete. */\n{\n    int count, i, widthChanged, result, pixelWidth;\n    Tcl_Size length;\n    Tcl_Obj *newListObj, *element;\n    const char *stringRep;\n    Tcl_HashEntry *entry;\n\n    /*\n     * Adjust the range to fit within the existing elements of the listbox,\n     * and make sure there's something to delete.\n     */\n\n    if (first < 0) {\n\tfirst = 0;\n    }\n    if (last >= (int)listPtr->nElements) {\n\tlast = listPtr->nElements-1;\n    }\n    count = last + 1 - first;\n    if (count <= 0) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Foreach deleted index we must:\n     * a) remove selection information,\n     * b) check the width of the element; if it is equal to the max, set\n     *    widthChanged to 1, because it may be the only element with that\n     *    width.\n     */\n\n    widthChanged = 0;\n    for (i = first; i <= last; i++) {\n\t/*\n\t * Remove selection information.\n\t */\n\n\tentry = Tcl_FindHashEntry(listPtr->selection, KEY(i));\n\tif (entry != NULL) {\n\t    listPtr->numSelected--;\n\t    Tcl_DeleteHashEntry(entry);\n\t}\n\n\tentry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));\n\tif (entry != NULL) {\n\t    Tcl_Free(Tcl_GetHashValue(entry));\n\t    Tcl_DeleteHashEntry(entry);\n\t}\n\n\t/*\n\t * Check width of the element. We only have to check if widthChanged\n\t * has not already been set to 1, because we only need one maxWidth\n\t * element to disappear for us to have to recompute the width.\n\t */\n\n\tif (widthChanged == 0) {\n\t    Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element);\n\t    stringRep = Tcl_GetStringFromObj(element, &length);\n\t    pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);\n\t    if (pixelWidth == listPtr->maxWidth) {\n\t\twidthChanged = 1;\n\t    }\n\t}\n    }\n\n    /*\n     * Adjust selection and attribute info for indices after lastIndex.\n     */\n\n    MigrateHashEntries(listPtr->selection, last+1,\n\t    listPtr->nElements-1, count*-1);\n    MigrateHashEntries(listPtr->itemAttrTable, last+1,\n\t    listPtr->nElements-1, count*-1);\n\n    /*\n     * Delete the requested elements.\n     */\n\n    if (Tcl_IsShared(listPtr->listObj)) {\n\tnewListObj = Tcl_DuplicateObj(listPtr->listObj);\n    } else {\n\tnewListObj = listPtr->listObj;\n    }\n    result = Tcl_ListObjReplace(listPtr->interp,\n\t    newListObj, first, count, 0, NULL);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * Replace the current object and set attached listvar, if any. This may\n     * error if listvar points to a var in a deleted namespace, but we ignore\n     * those errors. If the namespace is recreated, it will auto-sync with the\n     * current value. [Bug 1424513]\n     */\n\n    Tcl_IncrRefCount(newListObj);\n    Tcl_DecrRefCount(listPtr->listObj);\n    listPtr->listObj = newListObj;\n    if (listPtr->listVarNameObj != NULL) {\n\tTcl_SetVar2Ex(listPtr->interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\tlistPtr->listObj, TCL_GLOBAL_ONLY);\n    }\n\n    /*\n     * Get the new list length.\n     */\n\n    Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);\n\n    /*\n     * Update the selection and viewing information to reflect the change in\n     * the element numbering, and redisplay to slide information up over the\n     * elements that were deleted.\n     */\n\n    if (first <= listPtr->selectAnchor) {\n\tlistPtr->selectAnchor -= count;\n\tif (listPtr->selectAnchor < first) {\n\t    listPtr->selectAnchor = first;\n\t}\n    }\n    if (first <= listPtr->topIndex) {\n\tlistPtr->topIndex -= count;\n\tif (listPtr->topIndex < first) {\n\t    listPtr->topIndex = first;\n\t}\n    }\n    if (listPtr->topIndex > ((int)listPtr->nElements - listPtr->fullLines)) {\n\tlistPtr->topIndex = listPtr->nElements - listPtr->fullLines;\n\tif (listPtr->topIndex < 0) {\n\t    listPtr->topIndex = 0;\n\t}\n    }\n    if (listPtr->active > last) {\n\tlistPtr->active -= count;\n    } else if (listPtr->active >= first) {\n\tlistPtr->active = first;\n\tif ((listPtr->active >= (int)listPtr->nElements) &&\n\t\t((int)listPtr->nElements > 0)) {\n\t    listPtr->active = listPtr->nElements-1;\n\t}\n    }\n    listPtr->flags |= UPDATE_V_SCROLLBAR;\n    ListboxComputeGeometry(listPtr, 0, widthChanged, 0);\n    if (widthChanged) {\n\tlistPtr->flags |= UPDATE_H_SCROLLBAR;\n    }\n    EventuallyRedrawRange(listPtr, first, listPtr->nElements-1);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ListboxEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tlistboxes.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nListboxEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n\n    if (eventPtr->type == Expose) {\n\tEventuallyRedrawRange(listPtr,\n\t\tNearestListboxElement(listPtr, eventPtr->xexpose.y),\n\t\tNearestListboxElement(listPtr, eventPtr->xexpose.y\n\t\t+ eventPtr->xexpose.height));\n    } else if (eventPtr->type == DestroyNotify) {\n\tif (!(listPtr->flags & LISTBOX_DELETED)) {\n\t    listPtr->flags |= LISTBOX_DELETED;\n\t    Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd);\n\t    if (listPtr->setGrid) {\n\t\tTk_UnsetGrid(listPtr->tkwin);\n\t    }\n\t    if (listPtr->flags & REDRAW_PENDING) {\n\t\tTcl_CancelIdleCall(DisplayListbox, clientData);\n\t    }\n\t    Tcl_EventuallyFree(clientData, DestroyListbox);\n\t}\n    } else if (eventPtr->type == ConfigureNotify) {\n\tint vertSpace;\n\n\tvertSpace = Tk_Height(listPtr->tkwin) - 2 * listPtr->inset;\n\tlistPtr->fullLines = vertSpace / listPtr->lineHeight;\n\tif ((listPtr->fullLines*listPtr->lineHeight) < vertSpace) {\n\t    listPtr->partialLine = 1;\n\t} else {\n\t    listPtr->partialLine = 0;\n\t}\n\tlistPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;\n\tChangeListboxView(listPtr, listPtr->topIndex);\n\tChangeListboxOffset(listPtr, listPtr->xOffset);\n\n\t/*\n\t * Redraw the whole listbox. It's hard to tell what needs to be\n\t * redrawn (e.g. if the listbox has shrunk then we may only need to\n\t * redraw the borders), so just redraw everything for safety.\n\t */\n\n\tEventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    listPtr->flags |= GOT_FOCUS;\n\t    EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    listPtr->flags &= ~GOT_FOCUS;\n\t    EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxCmdDeletedProc --\n *\n *\tThis procedure is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n\n    /*\n     * This procedure could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this procedure destroys the\n     * widget.\n     */\n\n    if (!(listPtr->flags & LISTBOX_DELETED)) {\n\tTk_DestroyWindow(listPtr->tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetListboxIndex --\n *\n *\tParse an index into a listbox and return either its value or an error.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the index (into listPtr) corresponding to string. Otherwise an\n *\terror message is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetListboxIndex(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    Listbox *listPtr,\t\t/* Listbox for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *indexObj,\t\t/* Specifies an element in the listbox. */\n    int lastOK,\t\t/* If 1, \"end\" refers to the number of entries\n\t\t\t\t * in the listbox. If 0, \"end\" refers to 1\n\t\t\t\t * less than the number of entries. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted index. */\n{\n    int result;\n    Tcl_Size idx, index;\n    char *stringRep;\n\n    result = TkGetIntForIndex(indexObj, listPtr->nElements - 1, lastOK, &idx);\n    if (result == TCL_OK) {\n\tif ((idx != TCL_INDEX_NONE) && (idx > listPtr->nElements)) {\n\t    idx = listPtr->nElements;\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    /*\n     * First see if the index is one of the named indices.\n     */\n\n    result = Tcl_GetIndexFromObj(NULL, indexObj, indexNames, \"\", 0, &index);\n    if (result == TCL_OK) {\n\tswitch (index) {\n\tcase INDEX_ACTIVE:\n\t    /* \"active\" index */\n\t    *indexPtr = listPtr->active;\n\t    break;\n\tcase INDEX_ANCHOR:\n\t    /* \"anchor\" index */\n\t    *indexPtr = listPtr->selectAnchor;\n\t    break;\n\t}\n\treturn TCL_OK;\n    }\n\n    /*\n     * The index didn't match any of the named indices; maybe it's an @x,y\n     */\n\n    stringRep = Tcl_GetString(indexObj);\n    if (stringRep[0] == '@') {\n\n\t/*\n\t * @x,y index\n\t */\n\n\tint y;\n\tchar *start;\n\tchar *rest;\n\n\tstart = stringRep + 1;\n\trest = strchr(start, ',');\n\tif (!rest) {\n\t    goto badIndex;\n\t}\n\t*rest = '\\0';\n\tif (Tcl_GetInt(NULL, start, &y) != TCL_OK) {\n\t    *rest = ',';\n\t    goto badIndex;\n\t}\n\t*rest = ',';\n\tstart = rest+1;\n\tif (Tcl_GetInt(NULL, start, &y) != TCL_OK) {\n\t    goto badIndex;\n\t}\n\t*indexPtr = NearestListboxElement(listPtr, y);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Everything failed, nothing matched. Throw up an error message.\n     */\n\n  badIndex:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad listbox index \\\"%s\\\": must be active, anchor, end, @x,y,\"\n\t    \" or an index\", Tcl_GetString(indexObj)));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"LISTBOX_INDEX\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ChangeListboxView --\n *\n *\tChange the view on a listbox widget so that a given element is\n *\tdisplayed at the top.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhat's displayed on the screen is changed. If there is a scrollbar\n *\tassociated with this widget, then the scrollbar is instructed to\n *\tchange its display too.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nChangeListboxView(\n    Listbox *listPtr,\t/* Information about widget. */\n    int index)\t\t\t/* Index of element in listPtr that should now\n\t\t\t\t * appear at the top of the listbox. */\n{\n    if (index >= ((int)listPtr->nElements - listPtr->fullLines)) {\n\tindex = listPtr->nElements - listPtr->fullLines;\n    }\n    if (index < 0) {\n\tindex = 0;\n    }\n    if (listPtr->topIndex != index) {\n\tlistPtr->topIndex = index;\n\tEventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n\tlistPtr->flags |= UPDATE_V_SCROLLBAR;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ChangListboxOffset --\n *\n *\tChange the horizontal offset for a listbox.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe listbox may be redrawn to reflect its new horizontal offset.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nChangeListboxOffset(\n    Listbox *listPtr,\t/* Information about widget. */\n    int offset)\t\t\t/* Desired new \"xOffset\" for listbox. */\n{\n    int maxOffset;\n\n    /*\n     * Make sure that the new offset is within the allowable range, and round\n     * it off to an even multiple of xScrollUnit.\n     *\n     * Add half a scroll unit to do entry/text-like synchronization. [Bug\n     * #225025]\n     */\n\n    offset += listPtr->xScrollUnit / 2;\n    maxOffset = GetMaxOffset(listPtr);\n    if (offset > maxOffset) {\n\toffset = maxOffset;\n    }\n    if (offset < 0) {\n\toffset = 0;\n    }\n    offset -= offset % listPtr->xScrollUnit;\n    if (offset != listPtr->xOffset) {\n\tlistPtr->xOffset = offset;\n\tlistPtr->flags |= UPDATE_H_SCROLLBAR;\n\tEventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxScanTo --\n *\n *\tGiven a point (presumably of the curent mouse location) drag the view\n *\tin the window to implement the scan operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe view in the window may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxScanTo(\n    Listbox *listPtr,\t/* Information about widget. */\n    int x,\t\t\t/* X-coordinate to use for scan operation. */\n    int y)\t\t\t/* Y-coordinate to use for scan operation. */\n{\n    int newTopIndex, newOffset, maxIndex, maxOffset;\n\n    maxIndex = listPtr->nElements - listPtr->fullLines;\n    maxOffset = GetMaxOffset(listPtr);\n\n    /*\n     * Compute new top line for screen by amplifying the difference between\n     * the current position and the place where the scan started (the \"mark\"\n     * position). If we run off the top or bottom of the list, then reset the\n     * mark point so that the current position continues to correspond to the\n     * edge of the window. This means that the picture will start dragging as\n     * soon as the mouse reverses direction (without this reset, might have to\n     * slide mouse a long ways back before the picture starts moving again).\n     */\n\n    newTopIndex = listPtr->scanMarkYIndex\n\t    - (10*(y - listPtr->scanMarkY)) / listPtr->lineHeight;\n    if (newTopIndex > maxIndex) {\n\tnewTopIndex = listPtr->scanMarkYIndex = maxIndex;\n\tlistPtr->scanMarkY = y;\n    } else if (newTopIndex < 0) {\n\tnewTopIndex = listPtr->scanMarkYIndex = 0;\n\tlistPtr->scanMarkY = y;\n    }\n    ChangeListboxView(listPtr, newTopIndex);\n\n    /*\n     * Compute new left edge for display in a similar fashion by amplifying\n     * the difference between the current position and the place where the\n     * scan started.\n     */\n\n    newOffset = listPtr->scanMarkXOffset - 10*(x - listPtr->scanMarkX);\n    if (newOffset > maxOffset) {\n\tnewOffset = listPtr->scanMarkXOffset = maxOffset;\n\tlistPtr->scanMarkX = x;\n    } else if (newOffset < 0) {\n\tnewOffset = listPtr->scanMarkXOffset = 0;\n\tlistPtr->scanMarkX = x;\n    }\n    ChangeListboxOffset(listPtr, newOffset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NearestListboxElement --\n *\n *\tGiven a y-coordinate inside a listbox, compute the index of the\n *\telement under that y-coordinate (or closest to that y-coordinate).\n *\n * Results:\n *\tThe return value is an index of an element of listPtr. If listPtr has\n *\tno elements, then 0 is always returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nNearestListboxElement(\n    Listbox *listPtr,\t/* Information about widget. */\n    int y)\t\t\t/* Y-coordinate in listPtr's window. */\n{\n    int index;\n\n    index = (y - listPtr->inset) / listPtr->lineHeight;\n    if (index >= (listPtr->fullLines + listPtr->partialLine)) {\n\tindex = listPtr->fullLines + listPtr->partialLine - 1;\n    }\n    if (index < 0) {\n\tindex = 0;\n    }\n    index += listPtr->topIndex;\n    if (index >= (int)listPtr->nElements) {\n\tindex = listPtr->nElements-1;\n    }\n    return index;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxSelect --\n *\n *\tSelect or deselect one or more elements in a listbox..\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tAll of the elements in the range between first and last are marked as\n *\teither selected or deselected, depending on the \"select\" argument. Any\n *\titems whose state changes are redisplayed. The selection is claimed\n *\tfrom X when the number of selected elements changes from zero to\n *\tnon-zero.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nListboxSelect(\n    Listbox *listPtr,\t/* Information about widget. */\n    int first,\t\t\t/* Index of first element to select or\n\t\t\t\t * deselect. */\n    int last,\t\t\t/* Index of last element to select or\n\t\t\t\t * deselect. */\n    int select)\t\t\t/* 1 means select items, 0 means deselect\n\t\t\t\t * them. */\n{\n    int i, firstRedisplay, oldCount, isNew;\n    Tcl_HashEntry *entry;\n\n    if (last < first) {\n\ti = first;\n\tfirst = last;\n\tlast = i;\n    }\n    if ((last < 0) || (first >= (int)listPtr->nElements)) {\n\treturn TCL_OK;\n    }\n    if (first < 0) {\n\tfirst = 0;\n    }\n    if (last >= (int)listPtr->nElements) {\n\tlast = listPtr->nElements - 1;\n    }\n    oldCount = listPtr->numSelected;\n    firstRedisplay = -1;\n\n    /*\n     * For each index in the range, find it in our selection hash table. If\n     * it's not there but should be, add it. If it's there but shouldn't be,\n     * remove it.\n     */\n\n    for (i = first; i <= last; i++) {\n\tentry = Tcl_FindHashEntry(listPtr->selection, KEY(i));\n\tif (entry != NULL) {\n\t    if (!select) {\n\t\tTcl_DeleteHashEntry(entry);\n\t\tlistPtr->numSelected--;\n\t\tif (firstRedisplay < 0) {\n\t\t    firstRedisplay = i;\n\t\t}\n\t    }\n\t} else {\n\t    if (select) {\n\t\tentry = Tcl_CreateHashEntry(listPtr->selection, KEY(i),\n\t\t\t&isNew);\n\t\tTcl_SetHashValue(entry, NULL);\n\t\tlistPtr->numSelected++;\n\t\tif (firstRedisplay < 0) {\n\t\t    firstRedisplay = i;\n\t\t}\n\t    }\n\t}\n    }\n\n    if (firstRedisplay >= 0) {\n\tEventuallyRedrawRange(listPtr, first, last);\n    }\n    if ((oldCount == 0) && (listPtr->numSelected > 0)\n\t    && (listPtr->exportSelection)\n\t    && (!Tcl_IsSafe(listPtr->interp))) {\n\tTk_OwnSelection(listPtr->tkwin, XA_PRIMARY,\n\t\tListboxLostSelection, listPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxFetchSelection --\n *\n *\tThis procedure is called back by Tk when the selection is requested by\n *\tsomeone. It returns part or all of the selection in a buffer provided\n *\tby the caller.\n *\n * Results:\n *\tThe return value is the number of non-NULL bytes stored at buffer.\n *\tBuffer is filled (or partially filled) with a NULL-terminated string\n *\tcontaining part or all of the selection, as given by offset and\n *\tmaxBytes. The selection is returned as a Tcl list with one list\n *\telement for each element in the listbox.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nListboxFetchSelection(\n    void *clientData,\t/* Information about listbox widget. */\n    Tcl_Size offset,\t\t\t/* Offset within selection of first byte to be\n\t\t\t\t * returned. */\n    char *buffer,\t\t/* Location in which to place selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum number of bytes to place at buffer,\n\t\t\t\t * not including terminating NULL\n\t\t\t\t * character. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n    Tcl_DString selection;\n    int count, needNewline, i;\n    Tcl_Size length, stringLen;\n    Tcl_Obj *curElement;\n    const char *stringRep;\n    Tcl_HashEntry *entry;\n\n    if ((!listPtr->exportSelection) || Tcl_IsSafe(listPtr->interp)) {\n\treturn -1;\n    }\n\n    /*\n     * Use a dynamic string to accumulate the contents of the selection.\n     */\n\n    needNewline = 0;\n    Tcl_DStringInit(&selection);\n    for (i = 0; i < (int)listPtr->nElements; i++) {\n\tentry = Tcl_FindHashEntry(listPtr->selection, KEY(i));\n\tif (entry != NULL) {\n\t    if (needNewline) {\n\t\tTcl_DStringAppend(&selection, \"\\n\", 1);\n\t    }\n\t    Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,\n\t\t    &curElement);\n\t    stringRep = Tcl_GetStringFromObj(curElement, &stringLen);\n\t    Tcl_DStringAppend(&selection, stringRep, stringLen);\n\t    needNewline = 1;\n\t}\n    }\n\n    length = Tcl_DStringLength(&selection);\n    if (length == 0) {\n\treturn -1;\n    }\n\n    /*\n     * Copy the requested portion of the selection to the buffer.\n     */\n\n    if (length <= offset) {\n\tcount = 0;\n    } else {\n\tcount = length - offset;\n\tif (count > (int)maxBytes) {\n\t    count = (int)maxBytes;\n\t}\n\tmemcpy(buffer, Tcl_DStringValue(&selection) + offset, count);\n    }\n    buffer[count] = '\\0';\n    Tcl_DStringFree(&selection);\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxLostSelection --\n *\n *\tThis procedure is called back by Tk when the selection is grabbed away\n *\tfrom a listbox widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe existing selection is unhighlighted, and the window is marked as\n *\tnot containing a selection.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxLostSelection(\n    void *clientData)\t/* Information about listbox widget. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n\n    if ((listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp))\n\t    && (listPtr->nElements > 0)) {\n\tListboxSelect(listPtr, 0, listPtr->nElements-1, 0);\n\tGenerateListboxSelectEvent(listPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateListboxSelectEvent --\n *\n *\tSend an event that the listbox selection was updated. This is\n *\tequivalent to event generate $listboxWidget <<ListboxSelect>>\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tAny side effect possible, depending on bindings to this event.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateListboxSelectEvent(\n    Listbox *listPtr)\t\t/* Information about widget. */\n{\n    Tk_SendVirtualEvent(listPtr->tkwin, \"ListboxSelect\", NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EventuallyRedrawRange --\n *\n *\tEnsure that a given range of elements is eventually redrawn on the\n *\tdisplay (if those elements in fact appear on the display).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEventuallyRedrawRange(\n    Listbox *listPtr,\t/* Information about widget. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Index of first element in list that needs\n\t\t\t\t * to be redrawn. */\n    TCL_UNUSED(Tcl_Size))\t\t\t/* Index of last element in list that needs to\n\t\t\t\t * be redrawn. May be less than first; these\n\t\t\t\t * just bracket a range. */\n{\n    /*\n     * We don't have to register a redraw callback if one is already pending,\n     * or if the window doesn't exist, or if the window isn't mapped.\n     */\n\n    if ((listPtr->flags & REDRAW_PENDING)\n\t    || (listPtr->flags & LISTBOX_DELETED)\n\t    || !Tk_IsMapped(listPtr->tkwin)) {\n\treturn;\n    }\n    listPtr->flags |= REDRAW_PENDING;\n    Tcl_DoWhenIdle(DisplayListbox, listPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxUpdateVScrollbar --\n *\n *\tThis procedure is invoked whenever information has changed in a\n *\tlistbox in a way that would invalidate a vertical scrollbar display.\n *\tIf there is an associated scrollbar, then this command updates it by\n *\tinvoking a Tcl command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Tcl command is invoked, and an additional command may be invoked to\n *\tprocess errors in the command.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxUpdateVScrollbar(\n    Listbox *listPtr)\t/* Information about widget. */\n{\n    char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];\n    double first, last;\n    int result;\n    Tcl_Interp *interp;\n    Tcl_DString buf;\n\n    if (listPtr->yScrollCmdObj == NULL) {\n\treturn;\n    }\n    if (listPtr->nElements == 0) {\n\tfirst = 0.0;\n\tlast = 1.0;\n    } else {\n\tfirst = listPtr->topIndex / (double) listPtr->nElements;\n\tlast = (listPtr->topIndex + listPtr->fullLines)\n\t\t/ (double) listPtr->nElements;\n\tif (last > 1.0) {\n\t    last = 1.0;\n\t}\n    }\n    Tcl_PrintDouble(NULL, first, firstStr);\n    Tcl_PrintDouble(NULL, last, lastStr);\n\n    /*\n     * We must hold onto the interpreter from the listPtr because the data at\n     * listPtr might be freed as a result of the Tcl_EvalEx.\n     */\n\n    interp = listPtr->interp;\n    Tcl_Preserve(interp);\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, Tcl_GetString(listPtr->yScrollCmdObj), TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, firstStr, TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, lastStr, TCL_INDEX_NONE);\n    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    Tcl_DStringFree(&buf);\n    if (result != TCL_OK) {\n\tTcl_AddErrorInfo(interp,\n\t\t\"\\n    (vertical scrolling command executed by listbox)\");\n\tTcl_BackgroundException(interp, result);\n    }\n    Tcl_Release(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxUpdateHScrollbar --\n *\n *\tThis procedure is invoked whenever information has changed in a\n *\tlistbox in a way that would invalidate a horizontal scrollbar display.\n *\tIf there is an associated horizontal scrollbar, then this command\n *\tupdates it by invoking a Tcl command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Tcl command is invoked, and an additional command may be invoked to\n *\tprocess errors in the command.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nListboxUpdateHScrollbar(\n    Listbox *listPtr)\t/* Information about widget. */\n{\n    char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];\n    int result, windowWidth;\n    double first, last;\n    Tcl_Interp *interp;\n    Tcl_DString buf;\n    int selBorderWidth;\n\n    if (listPtr->xScrollCmdObj == NULL) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n    windowWidth = Tk_Width(listPtr->tkwin)\n\t    - 2 * (listPtr->inset + selBorderWidth);\n    if (listPtr->maxWidth == 0) {\n\tfirst = 0;\n\tlast = 1.0;\n    } else {\n\tfirst = listPtr->xOffset / (double) listPtr->maxWidth;\n\tlast = (listPtr->xOffset + windowWidth) / (double) listPtr->maxWidth;\n\tif (last > 1.0) {\n\t    last = 1.0;\n\t}\n    }\n    Tcl_PrintDouble(NULL, first, firstStr);\n    Tcl_PrintDouble(NULL, last, lastStr);\n\n    /*\n     * We must hold onto the interpreter because the data referred to at\n     * listPtr might be freed as a result of the call to Tcl_EvalEx.\n     */\n\n    interp = listPtr->interp;\n    Tcl_Preserve(interp);\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, Tcl_GetString(listPtr->xScrollCmdObj), TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, firstStr, TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, lastStr, TCL_INDEX_NONE);\n    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    Tcl_DStringFree(&buf);\n    if (result != TCL_OK) {\n\tTcl_AddErrorInfo(interp,\n\t\t\"\\n    (horizontal scrolling command executed by listbox)\");\n\tTcl_BackgroundException(interp, result);\n    }\n    Tcl_Release(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ListboxListVarProc --\n *\n *\tCalled whenever the trace on the listbox list var fires.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic char *\nListboxListVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(const char *),\n    int flags)\t\t\t/* Information about what happened. */\n{\n    Listbox *listPtr = (Listbox *)clientData;\n    Tcl_Obj *oldListObj, *varListObj;\n    Tcl_Size oldLength, i;\n    Tcl_HashEntry *entry;\n\n    /*\n     * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\n\tif (!Tcl_InterpDeleted(interp) && listPtr->listVarNameObj) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(listPtr->listVarNameObj),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tListboxListVarProc, probe);\n\t\tif (probe == (void *)listPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * listVarName, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t    Tcl_SetVar2Ex(interp, Tcl_GetString(listPtr->listVarNameObj), NULL,\n\t\t    listPtr->listObj, TCL_GLOBAL_ONLY);\n\t    Tcl_TraceVar2(interp, Tcl_GetString(listPtr->listVarNameObj),\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    ListboxListVarProc, clientData);\n\t    return NULL;\n\t}\n    } else {\n\toldListObj = listPtr->listObj;\n\tvarListObj = Tcl_GetVar2Ex(listPtr->interp, Tcl_GetString(listPtr->listVarNameObj),\n\t\tNULL, TCL_GLOBAL_ONLY);\n\n\t/*\n\t * Make sure the new value is a good list; if it's not, disallow the\n\t * change - the fact that it is a listvar means that it must always be\n\t * a valid list - and return an error message.\n\t */\n\n\tif (Tcl_ListObjLength(listPtr->interp, varListObj, &i) != TCL_OK) {\n\t    Tcl_SetVar2Ex(interp, Tcl_GetString(listPtr->listVarNameObj), NULL, oldListObj,\n\t\t    TCL_GLOBAL_ONLY);\n\t    return (char *) \"invalid listvar value\";\n\t}\n\n\tlistPtr->listObj = varListObj;\n\n\t/*\n\t * Incr the obj ref count so it doesn't vanish if the var is unset.\n\t */\n\n\tTcl_IncrRefCount(listPtr->listObj);\n\n\t/*\n\t * Clean up the ref to our old list obj.\n\t */\n\n\tTcl_DecrRefCount(oldListObj);\n    }\n\n    /*\n     * If the list length has decreased, then we should clean up selection and\n     * attributes information for elements past the end of the new list.\n     */\n\n    oldLength = listPtr->nElements;\n    Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);\n    if (listPtr->nElements < oldLength) {\n\tfor (i = listPtr->nElements; i < oldLength; i++) {\n\t    /*\n\t     * Clean up selection.\n\t     */\n\n\t    entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));\n\t    if (entry != NULL) {\n\t\tlistPtr->numSelected--;\n\t\tTcl_DeleteHashEntry(entry);\n\t    }\n\n\t    /*\n\t     * Clean up attributes.\n\t     */\n\n\t    entry = Tcl_FindHashEntry(listPtr->itemAttrTable, KEY(i));\n\t    if (entry != NULL) {\n\t\tTcl_Free(Tcl_GetHashValue(entry));\n\t\tTcl_DeleteHashEntry(entry);\n\t    }\n\t}\n    }\n\n    if (oldLength != listPtr->nElements) {\n\tlistPtr->flags |= UPDATE_V_SCROLLBAR;\n\tif (listPtr->topIndex > ((int)listPtr->nElements - listPtr->fullLines)) {\n\t    listPtr->topIndex = listPtr->nElements - listPtr->fullLines;\n\t    if (listPtr->topIndex < 0) {\n\t\tlistPtr->topIndex = 0;\n\t    }\n\t}\n    }\n\n    /*\n     * The computed maxWidth may have changed as a result of this operation.\n     * However, we don't want to recompute it every time this trace fires\n     * (imagine the user doing 1000 lappends to the listvar). Therefore, set\n     * the MAXWIDTH_IS_STALE flag, which will cause the width to be recomputed\n     * next time the list is redrawn.\n     */\n\n    listPtr->flags |= MAXWIDTH_IS_STALE;\n\n    EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MigrateHashEntries --\n *\n *\tGiven a hash table with entries keyed by a single integer value, move\n *\tall entries in a given range by a fixed amount, so that if in the\n *\toriginal table there was an entry with key n and the offset was i, in\n *\tthe new table that entry would have key n + i.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRekeys some hash table entries.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMigrateHashEntries(\n    Tcl_HashTable *table,\n    Tcl_Size first,\n    Tcl_Size last,\n    Tcl_Size offset)\n{\n    Tcl_Size i;\n    int isNew;\n    Tcl_HashEntry *entry;\n    void *clientData;\n\n    if (offset == 0) {\n\treturn;\n    }\n\n    /*\n     * It's more efficient to do one if/else and nest the for loops inside,\n     * although we could avoid some code duplication if we nested the if/else\n     * inside the for loops.\n     */\n\n    if (offset > 0) {\n\tfor (i = last; i >= first; i--) {\n\t    entry = Tcl_FindHashEntry(table, KEY(i));\n\t    if (entry != NULL) {\n\t\tclientData = Tcl_GetHashValue(entry);\n\t\tTcl_DeleteHashEntry(entry);\n\t\tentry = Tcl_CreateHashEntry(table, KEY(i + offset), &isNew);\n\t\tTcl_SetHashValue(entry, clientData);\n\t    }\n\t}\n    } else {\n\tfor (i = first; i <= last; i++) {\n\t    entry = Tcl_FindHashEntry(table, KEY(i));\n\t    if (entry != NULL) {\n\t\tclientData = Tcl_GetHashValue(entry);\n\t\tTcl_DeleteHashEntry(entry);\n\t\tentry = Tcl_CreateHashEntry(table, KEY(i + offset), &isNew);\n\t\tTcl_SetHashValue(entry, clientData);\n\t    }\n\t}\n    }\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMaxOffset --\n *\n *\tPassing in a listbox pointer, returns the maximum offset for the box,\n *\ti.e. the maximum possible horizontal scrolling value (in pixels).\n *\n * Results:\n *\tListbox's maxOffset.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n*/\nstatic int GetMaxOffset(\n    Listbox *listPtr)\n{\n    int maxOffset, selBorderWidth;\n\n    Tk_GetPixelsFromObj(NULL, listPtr->tkwin, listPtr->selBorderWidthObj, &selBorderWidth);\n    maxOffset = listPtr->maxWidth -\n\t    (Tk_Width(listPtr->tkwin) - 2 * listPtr->inset -\n\t    2 * selBorderWidth) + listPtr->xScrollUnit - 1;\n    if (maxOffset < 0) {\n\n\t/*\n\t * Listbox is larger in width than its largest width item.\n\t */\n\n\tmaxOffset = 0;\n    }\n    maxOffset -= maxOffset % listPtr->xScrollUnit;\n\n    return maxOffset;\n}\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMacWinMenu.c",
    "content": "/*\n * tkMacWinMenu.c --\n *\n *\tThis module implements the common elements of the Mac and Windows\n *\tspecific features of menus. This file is not used for UNIX.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkMenu.h\"\n\ntypedef struct {\n    int postCommandGeneration;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\nstatic int\t\tPreprocessMenu(TkMenu *menuPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PreprocessMenu --\n *\n *\tThe guts of the preprocessing. Recursive.\n *\n * Results:\n *\tThe return value is a standard Tcl result (errors can occur while the\n *\tpostcommands are being processed).\n *\n * Side effects:\n *\tSince commands can get executed while this routine is being executed,\n *\tthe entire world can change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPreprocessMenu(\n    TkMenu *menuPtr)\n{\n    int index, result, finished;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    Tcl_Preserve(menuPtr);\n\n    /*\n     * First, let's process the post command on ourselves. If this command\n     * destroys this menu, or if there was an error, we are done.\n     */\n\n    result = TkPostCommand(menuPtr);\n    if ((result != TCL_OK) || (menuPtr->tkwin == NULL)) {\n\tgoto done;\n    }\n\n    /*\n     * Now, we go through structure and process all of the commands. Since the\n     * structure is changing, we stop after we do one command, and start over.\n     * When we get through without doing any, we are done.\n     */\n\n    do {\n\tfinished = 1;\n\tfor (index = 0; index < menuPtr->numEntries; index++) {\n\t    TkMenuEntry *entryPtr = menuPtr->entries[index];\n\n\t    if ((entryPtr->type == CASCADE_ENTRY)\n\t\t    && (entryPtr->namePtr != NULL)\n\t\t    && (entryPtr->childMenuRefPtr != NULL)\n\t\t    && (entryPtr->childMenuRefPtr->menuPtr != NULL)) {\n\t\tTkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr;\n\n\t\tif (cascadeMenuPtr->postCommandGeneration !=\n\t\t\ttsdPtr->postCommandGeneration) {\n\t\t    cascadeMenuPtr->postCommandGeneration =\n\t\t\t    tsdPtr->postCommandGeneration;\n\t\t    result = PreprocessMenu(cascadeMenuPtr);\n\t\t    if (result != TCL_OK) {\n\t\t\tgoto done;\n\t\t    }\n\t\t    finished = 0;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    } while (!finished);\n\n  done:\n    Tcl_Release(menuPtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPreprocessMenu --\n *\n *\tOn the Mac and on Windows, all of the postcommand processing has to be\n *\tdone on the entire tree underneath the main window to be posted. This\n *\tmeans that we have to traverse the menu tree and issue the\n *\tpostcommands for all of the menus that have cascades attached. Since\n *\tthe postcommands can change the menu structure while we are\n *\ttraversing, we have to be extremely careful. Basically, the idea is to\n *\ttraverse the structure until we succesfully process one postcommand.\n *\tThen we start over, and do it again until we traverse the whole\n *\tstructure without processing any postcommands.\n *\n *\tWe are also going to set up the cascade back pointers in here since we\n *\thave to traverse the entire structure underneath the menu anyway. We\n *\tcan clear the postcommand marks while we do that.\n *\n * Results:\n *\tThe return value is a standard Tcl result (errors can occur while the\n *\tpostcommands are being processed).\n *\n * Side effects:\n *\tSince commands can get executed while this routine is being executed,\n *\tthe entire world can change.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPreprocessMenu(\n    TkMenu *menuPtr)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->postCommandGeneration++;\n    menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration;\n    return PreprocessMenu(menuPtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMain.c",
    "content": "/*\n * tkMain.c --\n *\n *\tThis file contains a generic main program for Tk-based applications.\n *\tIt can be used as-is for many applications, just by supplying a\n *\tdifferent appInitProc function for each specific application. Or, it\n *\tcan be used as a template for creating new main programs for Tk\n *\tapplications.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#if defined(_WIN32) && !defined(UNICODE) && !defined(STATIC_BUILD)\nMODULE_SCOPE void TkCygwinMainEx(Tcl_Size, char **, Tcl_AppInitProc *, Tcl_Interp *);\n#endif\n\n/*\n * The default prompt used when the user has not overridden it.\n */\n\nstatic const char DEFAULT_PRIMARY_PROMPT[] = \"% \";\nstatic const char ENCODING_ERROR[] = \"\\n\\t(encoding error in stderr)\";\n\n/*\n * This file can be compiled on Windows in UNICODE mode, as well as on all\n * other platforms using the native encoding. This is done by using the normal\n * Windows functions like _tcscmp, but on platforms which don't have <tchar.h>\n * we have to translate that to strcmp here.\n */\n#ifdef _WIN32\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n/*  Little hack to eliminate the need for \"tclInt.h\" here:\n    Just copy a small portion of TclIntPlatStubs, just\n    enough to make it work. See [600b72bfbc] */\ntypedef struct TclIntPlatStubs {\n    int magic;\n    void *hooks;\n    void (*dummy[16]) (void); /* dummy entries 0-15, not used */\n    bool (*tclpIsAtty) (int fd); /* 16 */\n} TclIntPlatStubs;\nextern const TclIntPlatStubs *tclIntPlatStubsPtr;\n#ifdef __cplusplus\n}\n#endif\n#   include \"tkWinInt.h\"\n#else\n#   define TCHAR char\n#   define TEXT(arg) arg\n#   define _tcscmp strcmp\n#   define _tcslen strlen\n#   define _tcsncmp strncmp\n#endif\n\n#ifdef MAC_OSX_TK\n#include \"tkMacOSXInt.h\"\n#endif\n\nstatic inline Tcl_Obj *\nNewNativeObj(\n    TCHAR *string)\n{\n    Tcl_Obj *obj;\n    Tcl_DString ds;\n    const char *str;\n\n#if defined(_WIN32) && defined(UNICODE)\n    Tcl_DStringInit(&ds);\n    Tcl_WCharToUtfDString(string, -1, &ds);\n    str = Tcl_DStringValue(&ds);\n#else\n    str = Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds);\n#endif\n    obj = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));\n    Tcl_DStringFree(&ds);\n    return obj;\n}\n\n/*\n * Declarations for various library functions and variables (don't want to\n * include tclInt.h or tclPort.h here, because people might copy this file out\n * of the Tk source directory to make their own modified versions). Note: do\n * not declare \"exit\" here even though a declaration is really needed, because\n * it will conflict with a declaration elsewhere on some systems.\n */\n\n#if defined(_WIN32)\n#define isatty WinIsTty\nstatic bool WinIsTty(int fd) {\n    HANDLE handle;\n\n    /*\n     * For now, under Windows, we assume we are not running as a console mode\n     * app, so we need to use the GUI console. In order to enable this, we\n     * always claim to be running on a tty. This probably isn't the right way\n     * to do it.\n     */\n\n#if !defined(STATIC_BUILD)\n\tif (tclStubsPtr->tcl_CreateFileHandler && tclIntPlatStubsPtr->tclpIsAtty) {\n\t    /* We are running on Cygwin */\n\t    return tclIntPlatStubsPtr->tclpIsAtty(fd);\n\t}\n#endif\n    handle = GetStdHandle(STD_INPUT_HANDLE + (DWORD)fd);\n\t/*\n\t * If it's a bad or closed handle, then it's been connected to a wish\n\t * console window. A character file handle is a tty by definition.\n\t */\n    return (handle == INVALID_HANDLE_VALUE) || (handle == 0)\n\t     || (GetFileType(handle) == FILE_TYPE_UNKNOWN)\n\t     || (GetFileType(handle) == FILE_TYPE_CHAR);\n}\n#else\nextern int\t\tisatty(int fd);\n#endif\n\ntypedef struct {\n    Tcl_Interp *interp;\t\t/* Interpreter that evaluates interactive\n\t\t\t\t * commands. */\n    Tcl_Channel input;\t\t/* The standard input channel from which lines\n\t\t\t\t * are read. */\n    Tcl_DString command;\t/* Used to assemble lines of terminal input\n\t\t\t\t * into Tcl commands. */\n    Tcl_DString line;\t\t/* Used to read the next line from the\n\t\t\t\t * terminal input. */\n    bool tty;\t\t/* true means standard input is a\n\t\t\t\t * terminal-like device. false means it's a\n\t\t\t\t * file. */\n    bool gotPartial;\n} InteractiveState;\n\n/*\n * Forward declarations for functions defined later in this file.\n */\n\nstatic void\t\tPrompt(Tcl_Interp *interp, InteractiveState *isPtr);\nstatic void\t\tStdinProc(void *clientData, int mask);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MainEx --\n *\n *\tMain program for Wish and most other Tk-based applications.\n *\n * Results:\n *\tNone. This function never returns (it exits the process when it's\n *\tdone).\n *\n * Side effects:\n *\tThis function initializes the Tk world and then starts interpreting\n *\tcommands; almost anything could happen, depending on the script being\n *\tinterpreted.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MainEx(\n    Tcl_Size argc,\t\t\t/* Number of arguments. */\n    TCHAR **argv,\t\t/* Array of argument strings. */\n    Tcl_AppInitProc *appInitProc,\n\t\t\t\t/* Application-specific initialization\n\t\t\t\t * function to call after most initialization\n\t\t\t\t * but before starting to execute commands. */\n    Tcl_Interp *interp)\n{\n    int i=0;\t\t\t/* argv[i] index */\n    Tcl_Obj *path, *argvPtr, *appName;\n    const char *encodingName;\n    int code;\n    bool nullStdin = false;\n    Tcl_Channel chan;\n    InteractiveState is;\n\n    if (0 < argc) {\n\t--argc;\t\t\t/* \"consume\" argv[0] */\n\t++i;\n    }\n\n    /*\n     * Ensure that we are getting a compatible version of Tcl.\n     */\n\n    if (Tcl_InitStubs(interp, \"9.0\", 0) == NULL) {\n\tTcl_Panic(\"%s\", Tcl_GetString(Tcl_GetObjResult(interp)));\n    }\n\n#if defined(_WIN32) && !defined(UNICODE) && !defined(STATIC_BUILD)\n\n    if (tclStubsPtr->tcl_CreateFileHandler) {\n\t/* We are running win32 Tk under Cygwin, so let's check\n\t * whether the env(\"DISPLAY\") variable or the -display\n\t * argument is set. If so, we really want to run the\n\t * Tk_MainEx function of cygtcl9tk9.?.dll, not this one. */\n\tif (Tcl_GetVar2(interp, \"env\", \"DISPLAY\", TCL_GLOBAL_ONLY)) {\n\tloadCygwinTk:\n\t    TkCygwinMainEx(argc, argv, appInitProc, interp);\n\t    /* Only returns when Tk_MainEx() was not found */\n\t} else {\n\t    Tcl_Size j;\n\n\t    for (j = 1; j < argc; ++j) {\n\t\tif (!strcmp(argv[j], \"-display\")) {\n\t\t    goto loadCygwinTk;\n\t\t}\n\t    }\n\t}\n    }\n#endif\n\n    Tcl_InitMemory(interp);\n\n    is.interp = interp;\n    is.gotPartial = false;\n    Tcl_Preserve(interp);\n\n#if defined(_WIN32)\n#if !defined(STATIC_BUILD)\n    /* If compiled for Win32 but running on Cygwin, don't use console */\n    if (!tclStubsPtr->tcl_CreateFileHandler)\n#endif\n    Tk_InitConsoleChannels(interp);\n#endif\n\n#ifdef MAC_OSX_TK\n    if (Tcl_GetStartupScript(NULL) == NULL) {\n\tTkMacOSXDefaultStartupScript();\n    }\n#endif\n\n    /*\n     * If the application has not already set a startup script, parse the\n     * first few command line arguments to determine the script path and\n     * encoding.\n     */\n\n    if (NULL == Tcl_GetStartupScript(NULL)) {\n\n\t/*\n\t * Check whether first 3 args (argv[1] - argv[3]) look like\n\t *  -encoding ENCODING FILENAME\n\t * or like\n\t *  FILENAME\n\t */\n\n\t/* mind argc is being adjusted as we proceed */\n\tif ((argc >= 3) && (0 == _tcscmp(TEXT(\"-encoding\"), argv[1]))\n\t\t&& ('-' != argv[3][0])) {\n\t    Tcl_Obj *value = NewNativeObj(argv[2]);\n\t    Tcl_SetStartupScript(NewNativeObj(argv[3]), Tcl_GetString(value));\n\t    Tcl_DecrRefCount(value);\n\t    argc -= 3;\n\t    i += 3;\n\t} else if ((argc >= 1) && ('-' != argv[1][0])) {\n\t    Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);\n\t    argc--;\n\t    i++;\n\t}\n    }\n\n    path = Tcl_GetStartupScript(&encodingName);\n    if (path == NULL) {\n\tappName = NewNativeObj(argv[0]);\n    } else {\n\tappName = path;\n    }\n    Tcl_SetVar2Ex(interp, \"argv0\", NULL, appName, TCL_GLOBAL_ONLY);\n\n    Tcl_SetVar2Ex(interp, \"argc\", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY);\n\n    argvPtr = Tcl_NewListObj(0, NULL);\n    while (argc--) {\n\tTcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(argv[i++]));\n    }\n    Tcl_SetVar2Ex(interp, \"argv\", NULL, argvPtr, TCL_GLOBAL_ONLY);\n\n    /*\n     * Set the \"tcl_interactive\" variable.\n     */\n\n    is.tty = isatty(0);\n#if defined(MAC_OSX_TK)\n    /*\n     * On TkAqua, if we don't have a TTY and stdin is a special character file\n     * of length 0, (e.g. /dev/null, which is what Finder sets when double\n     * clicking Wish) then use the GUI console.\n     */\n\n    if (!is.tty) {\n\tstruct stat st;\n\n\tnullStdin = fstat(0, &st) || (S_ISCHR(st.st_mode) && !st.st_blocks);\n    }\n#endif\n    Tcl_SetVar2Ex(interp, \"tcl_interactive\", NULL,\n\t    Tcl_NewBooleanObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY);\n\n    /*\n     * Invoke application-specific initialization.\n     */\n\n    if (appInitProc(interp) != TCL_OK) {\n\tTkpDisplayWarning(Tcl_GetString(Tcl_GetObjResult(interp)),\n\t\t\"application-specific initialization failed\");\n    }\n\n    /*\n     * Invoke the script specified on the command line, if any. Must fetch it\n     * again, as the appInitProc might have reset it.\n     */\n\n    path = Tcl_GetStartupScript(&encodingName);\n    if (path != NULL) {\n\tTcl_ResetResult(interp);\n\tcode = Tcl_FSEvalFileEx(interp, path, encodingName);\n\tif (code != TCL_OK) {\n\t    /*\n\t     * The following statement guarantees that the errorInfo variable\n\t     * is set properly.\n\t     */\n\n\t    Tcl_AddErrorInfo(interp, \"\");\n\t    TkpDisplayWarning(Tcl_GetVar2(interp, \"errorInfo\", NULL,\n\t\t    TCL_GLOBAL_ONLY), \"Error in startup script\");\n\t    Tcl_DeleteInterp(interp);\n\t    Tcl_Exit(1);\n\t}\n\tis.tty = false;\n    } else {\n\n\t/*\n\t * Evaluate the .rc file, if one has been specified.\n\t */\n\n\tTcl_SourceRCFile(interp);\n\n\t/*\n\t * Establish a channel handler for stdin.\n\t */\n\n\tis.input = Tcl_GetStdChannel(TCL_STDIN);\n\tif (is.input) {\n\t    Tcl_CreateChannelHandler(is.input, TCL_READABLE, StdinProc, &is);\n\t}\n\tif (is.tty) {\n\t    Prompt(interp, &is);\n\t}\n    }\n\n    chan = Tcl_GetStdChannel(TCL_STDOUT);\n    if (chan) {\n\tTcl_Flush(chan);\n    }\n    Tcl_DStringInit(&is.command);\n    Tcl_DStringInit(&is.line);\n    Tcl_ResetResult(interp);\n\n    /*\n     * Loop infinitely, waiting for commands to execute. When there are no\n     * windows left, Tk_MainLoop returns and we exit.\n     */\n\n    Tk_MainLoop();\n    Tcl_DeleteInterp(interp);\n    Tcl_Release(interp);\n    Tcl_SetStartupScript(NULL, NULL);\n    Tcl_Exit(0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StdinProc --\n *\n *\tThis function is invoked by the event dispatcher whenever standard\n *\tinput becomes readable. It grabs the next line of input characters,\n *\tadds them to a command being assembled, and executes the command if\n *\tit's complete.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCould be almost arbitrary, depending on the command that's typed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nStdinProc(\n    void *clientData,\t/* The state of interactive cmd line */\n    TCL_UNUSED(int) /*mask*/)\n{\n    char *cmd;\n    int code;\n    Tcl_Size length;\n    InteractiveState *isPtr = (InteractiveState *)clientData;\n    Tcl_Channel chan = isPtr->input;\n    Tcl_Interp *interp = isPtr->interp;\n\n    length = Tcl_Gets(chan, &isPtr->line);\n\n    if ((length < 0) && !isPtr->gotPartial) {\n\tif (isPtr->tty) {\n\t    /*\n\t     * Would be better to find a way to exit the mainLoop? Or perhaps\n\t     * evaluate [exit]? Leaving as is for now due to compatibility\n\t     * concerns.\n\t     */\n\n\t    Tcl_Exit(0);\n\t}\n\tTcl_DeleteChannelHandler(chan, StdinProc, isPtr);\n\treturn;\n    }\n\n    Tcl_DStringAppend(&isPtr->command, Tcl_DStringValue(&isPtr->line), TCL_INDEX_NONE);\n    cmd = Tcl_DStringAppend(&isPtr->command, \"\\n\", TCL_INDEX_NONE);\n    Tcl_DStringFree(&isPtr->line);\n    if (!Tcl_CommandComplete(cmd)) {\n\tisPtr->gotPartial = true;\n\tgoto prompt;\n    }\n    isPtr->gotPartial = false;\n\n    /*\n     * Disable the stdin channel handler while evaluating the command;\n     * otherwise if the command re-enters the event loop we might process\n     * commands from stdin before the current command is finished. Among other\n     * things, this will trash the text of the command being evaluated.\n     */\n\n    Tcl_CreateChannelHandler(chan, 0, StdinProc, isPtr);\n    code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL);\n    isPtr->input = chan = Tcl_GetStdChannel(TCL_STDIN);\n    if (chan != NULL) {\n\tTcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, isPtr);\n    }\n    Tcl_DStringFree(&isPtr->command);\n    if (code != TCL_OK) {\n\tchan = Tcl_GetStdChannel(TCL_STDERR);\n\n\tif (chan != NULL) {\n\t    if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {\n\t\tTcl_WriteChars(chan, ENCODING_ERROR, -1);\n\t    }\n\t    Tcl_WriteChars(chan, \"\\n\", 1);\n\t}\n    } else if (isPtr->tty) {\n\tTcl_Obj *resultPtr = Tcl_GetObjResult(interp);\n\tchan = Tcl_GetStdChannel(TCL_STDOUT);\n\n\tTcl_IncrRefCount(resultPtr);\n\t(void)Tcl_GetStringFromObj(resultPtr, &length);\n\tif ((length > 0) && (chan != NULL)) {\n\t    if (Tcl_WriteObj(chan, resultPtr) < 0) {\n\t\tTcl_WriteChars(chan, \"\\n\\t(encoding error in stdout)\", -1);\n\t    }\n\t    Tcl_WriteChars(chan, \"\\n\", 1);\n\t}\n\tTcl_DecrRefCount(resultPtr);\n    }\n\n    /*\n     * If a tty stdin is still around, output a prompt.\n     */\n\n  prompt:\n    if (isPtr->tty && (isPtr->input != NULL)) {\n\tPrompt(interp, isPtr);\n    }\n    Tcl_ResetResult(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Prompt --\n *\n *\tIssue a prompt on standard output, or invoke a script to issue the\n *\tprompt.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA prompt gets output, and a Tcl script may be evaluated in interp.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPrompt(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for prompting. */\n    InteractiveState *isPtr) /* InteractiveState. */\n{\n    Tcl_Obj *promptCmdPtr;\n    int code;\n    Tcl_Channel chan;\n\n    promptCmdPtr = Tcl_GetVar2Ex(interp,\n\tisPtr->gotPartial ? \"tcl_prompt2\" : \"tcl_prompt1\", NULL, TCL_GLOBAL_ONLY);\n    if (promptCmdPtr == NULL) {\n    defaultPrompt:\n\tif (!isPtr->gotPartial) {\n\t    chan = Tcl_GetStdChannel(TCL_STDOUT);\n\t    if (chan != NULL) {\n\t\tTcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT,\n\t\t\tsizeof(DEFAULT_PRIMARY_PROMPT) - 1);\n\t    }\n\t}\n    } else {\n\tcode = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL);\n\tif (code != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (script that generates prompt)\");\n\t    chan = Tcl_GetStdChannel(TCL_STDERR);\n\t    if (chan != NULL) {\n\t    if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {\n\t\tTcl_WriteChars(chan, ENCODING_ERROR, -1);\n\t    }\n\t\tTcl_WriteChars(chan, \"\\n\", 1);\n\t    }\n\t    goto defaultPrompt;\n\t}\n    }\n\n    chan = Tcl_GetStdChannel(TCL_STDOUT);\n    if (chan != NULL) {\n\tTcl_Flush(chan);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMenu.c",
    "content": "/*\n * tkMenu.c --\n *\n * This file contains most of the code for implementing menus in Tk. It takes\n * care of all of the generic (platform-independent) parts of menus, and is\n * supplemented by platform-specific files. The geometry calculation and\n * drawing code for menus is in the file tkMenuDraw.c\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Notes on implementation of menus:\n *\n * Menus can be used in three ways:\n * - as a popup menu, either as part of a menubutton or standalone.\n * - as a menubar. The menu's cascade items are arranged according to the\n *   specific platform to provide the user access to the menus at all times\n * - as a tearoff palette. This is a window with the menu's items in it.\n *\n * The goal is to provide the Tk developer with a way to use a common set of\n * menus for all of these tasks.\n *\n * In order to make the bindings for cascade menus work properly under Unix,\n * the cascade menus' pathnames must be proper children of the menu that they\n * are cascade from. So if there is a menu .m, and it has two cascades\n * labelled \"File\" and \"Edit\", the cascade menus might have the pathnames\n * .m.file and .m.edit. Another constraint is that the menus used for menubars\n * must be children of the toplevel widget that they are attached to. And on\n * the Macintosh, the platform specific menu handle for cascades attached to a\n * menu bar must have a title that matches the label for the cascade menu.\n *\n * To handle all of the constraints, Tk menubars and tearoff menus are\n * implemented using menu clones. Menu clones are full menus in their own\n * right; they have a Tk window and pathname associated with them; they have a\n * TkMenu structure and array of entries. However, they are linked with the\n * original menu that they were cloned from. They reflect the attributes of the\n * original, or \"main\", menu. So if an item is added to a menu, and that\n * menu has clones, then the item must be added to all of its clones also.\n * Menus are cloned when a menu is torn-off or when a menu is assigned as a\n * menubar using the \"-menu\" option of the toplevel's pathname configure\n * subcommand. When a clone is destroyed, only the clone is destroyed, but\n * when the main menu is destroyed, all clones are also destroyed. This\n * allows the developer to just deal with one set of menus when creating and\n * destroying.\n *\n * Clones are rather tricky when a menu with cascade entries is cloned (such\n * as a menubar). Not only does the menu have to be cloned, but each cascade\n * entry's corresponding menu must also be cloned. This maintains the pathname\n * parent-child hierarchy necessary for menubars and toplevels to work. This\n * leads to several special cases:\n *\n * 1. When a new menu is created, and it is pointed to by cascade entries in\n * cloned menus, the new menu has to be cloned to parallel the cascade\n * structure.\n * 2. When a cascade item is added to a menu that has been cloned, and the\n * menu that the cascade item points to exists, that menu has to be cloned.\n * 3. When the menu that a cascade entry points to is changed, the old cloned\n * cascade menu has to be discarded, and the new one has to be cloned.\n */\n\n#if 0\n\n/*\n * used only to test for old config code\n */\n\n#define __NO_OLD_CONFIG\n#endif\n\n#include \"tkInt.h\"\n#include \"tkMenu.h\"\n\n#define MENU_HASH_KEY \"tkMenus\"\n\ntypedef struct {\n    bool menusInitialized;\t/* Flag indicates whether thread-specific\n\t\t\t\t * elements of the Windows Menu module have\n\t\t\t\t * been initialized. */\n    Tk_OptionTable menuOptionTable;\n\t\t\t\t/* The option table for menus. */\n    Tk_OptionTable entryOptionTables[6];\n\t\t\t\t/* The tables for menu entries. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The following flag indicates whether the process-wide state for the Menu\n * module has been initialized. The Mutex protects access to that flag.\n */\n\nstatic bool menusInitialized;\nTCL_DECLARE_MUTEX(menuMutex)\n\n/*\n * Configuration specs for individual menu entries. If this changes, be sure\n * to update code in TkpMenuInit that changes the font string entry.\n */\n\nstatic const char *const menuEntryTypeStrings[] = {\n    \"cascade\", \"checkbutton\", \"command\", \"radiobutton\", \"separator\", NULL\n};\n\nstatic const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", NULL, NULL,\n\tDEF_MENU_ENTRY_ACTIVE_BG, offsetof(TkMenuEntry, activeBorderPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", NULL, NULL,\n\tDEF_MENU_ENTRY_ACTIVE_FG,\n\toffsetof(TkMenuEntry, activeFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-accelerator\", NULL, NULL,\n\tDEF_MENU_ENTRY_ACCELERATOR,\n\toffsetof(TkMenuEntry, accelPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BORDER, \"-background\", NULL, NULL,\n\tDEF_MENU_ENTRY_BG,\n\toffsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", NULL, NULL,\n\tDEF_MENU_ENTRY_BITMAP,\n\toffsetof(TkMenuEntry, bitmapPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-columnbreak\", NULL, NULL,\n\tDEF_MENU_ENTRY_COLUMN_BREAK,\n\tTCL_INDEX_NONE, offsetof(TkMenuEntry, columnBreak), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_STRING, \"-command\", NULL, NULL,\n\tDEF_MENU_ENTRY_COMMAND,\n\toffsetof(TkMenuEntry, commandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_MENU_ENTRY_COMPOUND, TCL_INDEX_NONE, offsetof(TkMenuEntry, compound), 0,\n\ttkCompoundStrings, 0},\n    {TK_OPTION_FONT, \"-font\", NULL, NULL,\n\tDEF_MENU_ENTRY_FONT,\n\toffsetof(TkMenuEntry, fontPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_COLOR, \"-foreground\", NULL, NULL,\n\tDEF_MENU_ENTRY_FG,\n\toffsetof(TkMenuEntry, fgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-hidemargin\", NULL, NULL,\n\tDEF_MENU_ENTRY_HIDE_MARGIN,\n\tTCL_INDEX_NONE, offsetof(TkMenuEntry, hideMargin), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_STRING, \"-image\", NULL, NULL,\n\tDEF_MENU_ENTRY_IMAGE,\n\toffsetof(TkMenuEntry, imagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-label\", NULL, NULL,\n\tDEF_MENU_ENTRY_LABEL,\n\toffsetof(TkMenuEntry, labelPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", NULL, NULL,\n\tDEF_MENU_ENTRY_STATE,\n\tTCL_INDEX_NONE, offsetof(TkMenuEntry, state),\n\t0, tkStateStrings, 0},\n    {TK_OPTION_INDEX, \"-underline\", NULL, NULL,\n\tTK_OPTION_UNDERLINE_DEF(TkMenuEntry, underline), 0},\n    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}\n};\n\nstatic const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", NULL, NULL,\n\tDEF_MENU_ENTRY_BG,\n\toffsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}\n};\n\nstatic const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {\n    {TK_OPTION_BOOLEAN, \"-indicatoron\", NULL, NULL,\n\tDEF_MENU_ENTRY_INDICATOR,\n\tTCL_INDEX_NONE, offsetof(TkMenuEntry, indicatorOn), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_STRING, \"-offvalue\", NULL, NULL,\n\tDEF_MENU_ENTRY_OFF_VALUE,\n\toffsetof(TkMenuEntry, offValuePtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_STRING, \"-onvalue\", NULL, NULL,\n\tDEF_MENU_ENTRY_ON_VALUE,\n\toffsetof(TkMenuEntry, onValuePtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_COLOR, \"-selectcolor\", NULL, NULL,\n\tDEF_MENU_ENTRY_SELECT,\n\toffsetof(TkMenuEntry, indicatorFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-selectimage\", NULL, NULL,\n\tDEF_MENU_ENTRY_SELECT_IMAGE,\n\toffsetof(TkMenuEntry, selectImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-variable\", NULL, NULL,\n\tDEF_MENU_ENTRY_CHECK_VARIABLE,\n\toffsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}\n};\n\nstatic const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {\n    {TK_OPTION_BOOLEAN, \"-indicatoron\", NULL, NULL,\n\tDEF_MENU_ENTRY_INDICATOR,\n\tTCL_INDEX_NONE, offsetof(TkMenuEntry, indicatorOn), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_COLOR, \"-selectcolor\", NULL, NULL,\n\tDEF_MENU_ENTRY_SELECT,\n\toffsetof(TkMenuEntry, indicatorFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-selectimage\", NULL, NULL,\n\tDEF_MENU_ENTRY_SELECT_IMAGE,\n\toffsetof(TkMenuEntry, selectImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-value\", NULL, NULL,\n\tDEF_MENU_ENTRY_VALUE,\n\toffsetof(TkMenuEntry, onValuePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-variable\", NULL, NULL,\n\tDEF_MENU_ENTRY_RADIO_VARIABLE,\n\toffsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}\n};\n\nstatic const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {\n    {TK_OPTION_STRING, \"-menu\", NULL, NULL,\n\tDEF_MENU_ENTRY_MENU,\n\toffsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}\n};\n\nstatic const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", NULL, NULL,\n\tDEF_MENU_ENTRY_BG,\n\toffsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", NULL, NULL,\n\tDEF_MENU_ENTRY_STATE, TCL_INDEX_NONE, offsetof(TkMenuEntry, state),\n\t0, tkStateStrings, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}\n};\n\nstatic const Tk_OptionSpec *specsArray[] = {\n    tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,\n    tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,\n    tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs\n};\n\n/*\n * Menu type strings for use with Tcl_GetIndexFromObj.\n */\n\nstatic const char *const menuTypeStrings[] = {\n    \"menubar\", \"normal\", \"tearoff\", NULL\n};\n\nstatic const Tk_OptionSpec tkMenuConfigSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\",\n\t\"Foreground\", DEF_MENU_ACTIVE_BG_COLOR,\n\toffsetof(TkMenu, activeBorderPtr), TCL_INDEX_NONE, 0,\n\tDEF_MENU_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_PIXELS, \"-activeborderwidth\", \"activeBorderWidth\",\n\t\"BorderWidth\", DEF_MENU_ACTIVE_BORDER_WIDTH,\n\toffsetof(TkMenu, activeBorderWidthPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\",\n\t\"Background\", DEF_MENU_ACTIVE_FG_COLOR,\n\toffsetof(TkMenu, activeFgPtr), TCL_INDEX_NONE, 0,\n\tDEF_MENU_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_RELIEF, \"-activerelief\", \"activeRelief\", \"Relief\",\n\tDEF_MENU_ACTIVE_RELIEF, TCL_INDEX_NONE,\n\toffsetof(TkMenu, activeRelief), 0, NULL, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_MENU_BG_COLOR, offsetof(TkMenu, borderPtr), TCL_INDEX_NONE, 0,\n\tDEF_MENU_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_MENU_BORDER_WIDTH,\n\toffsetof(TkMenu, borderWidthObj), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_MENU_CURSOR,\n\toffsetof(TkMenu, cursorPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_MENU_DISABLED_FG_COLOR,\n\toffsetof(TkMenu, disabledFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK,\n\tDEF_MENU_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_MENU_FONT, offsetof(TkMenu, fontPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_MENU_FG, offsetof(TkMenu, fgPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_STRING, \"-postcommand\", \"postCommand\", \"Command\",\n\tDEF_MENU_POST_COMMAND,\n\toffsetof(TkMenu, postCommandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_MENU_RELIEF, TCL_INDEX_NONE, offsetof(TkMenu, relief), 0, NULL, 0},\n    {TK_OPTION_COLOR, \"-selectcolor\", \"selectColor\", \"Background\",\n\tDEF_MENU_SELECT_COLOR, offsetof(TkMenu, indicatorFgPtr), TCL_INDEX_NONE, 0,\n\tDEF_MENU_SELECT_MONO, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_MENU_TAKE_FOCUS,\n\toffsetof(TkMenu, takeFocusPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-tearoff\", \"tearOff\", \"TearOff\",\n\tDEF_MENU_TEAROFF, TCL_INDEX_NONE, offsetof(TkMenu, tearoff), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_STRING, \"-tearoffcommand\", \"tearOffCommand\",\n\t\"TearOffCommand\", DEF_MENU_TEAROFF_CMD,\n\toffsetof(TkMenu, tearoffCommandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING, \"-title\", \"title\", \"Title\",\n\tDEF_MENU_TITLE,\t offsetof(TkMenu, titlePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, NULL, 0},\n    {TK_OPTION_STRING_TABLE, \"-type\", \"type\", \"Type\",\n\tDEF_MENU_TYPE, offsetof(TkMenu, menuTypePtr), TCL_INDEX_NONE,\n\t0, menuTypeStrings, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}\n};\n\n/*\n * Command line options. Put here because MenuCmd has to look at them along\n * with MenuWidgetObjCmd.\n */\n\nstatic const char *const menuOptions[] = {\n    \"activate\", \"add\", \"cget\", \"clone\", \"configure\", \"delete\", \"entrycget\",\n    \"entryconfigure\", \"id\", \"index\", \"insert\", \"invoke\", \"post\", \"postcascade\",\n    \"type\", \"unpost\", \"xposition\", \"yposition\", NULL\n};\nenum options {\n    MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE,\n    MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_ID, MENU_INDEX,\n    MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE,\n    MENU_UNPOST, MENU_XPOSITION, MENU_YPOSITION\n};\n\n/*\n * Prototypes for static functions in this file:\n */\n\nstatic int\t\tCheckForLoops(Tcl_Interp *interp, const char *name,\n\t\t\t    TkMenu *menuPtr);\nstatic int\t\tCheckForLoops0(Tcl_Interp *interp, const char *pathName,\n\t\t\t    const char *name);\nstatic int\t\tCloneMenu(TkMenu *menuPtr, Tcl_Obj *newMenuName,\n\t\t\t    Tcl_Obj *newMenuTypeString);\nstatic int\t\tConfigureMenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tConfigureMenuCloneEntries(TkMenu *menuPtr, int index,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tConfigureMenuEntry(TkMenuEntry *mePtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteMenuCloneEntries(TkMenu *menuPtr,\n\t\t\t    int first, int last);\nstatic void\t\tDestroyMenuHashTable(void *clientData,\n\t\t\t    Tcl_Interp *interp);\nstatic void\t\tDestroyMenuInstance(TkMenu *menuPtr);\nstatic Tcl_FreeProc\tDestroyMenuEntry;\nstatic Tcl_Size\tGetIndexFromCoords(Tcl_Interp *interp,\n\t\t\t    TkMenu *menuPtr, const char *string,\n\t\t\t    Tcl_Size *indexPtr);\nstatic int\t\tMenuDoYPosition(Tcl_Interp *interp,\n\t\t\t    TkMenu *menuPtr, Tcl_Obj *objPtr);\nstatic int\t\tMenuDoXPosition(Tcl_Interp *interp,\n\t\t\t    TkMenu *menuPtr, Tcl_Obj *objPtr);\nstatic int\t\tMenuAddOrInsert(Tcl_Interp *interp,\n\t\t\t    TkMenu *menuPtr, Tcl_Obj *indexPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tMenuCmdDeletedProc(void *clientData);\nstatic TkMenuEntry *\tMenuNewEntry(TkMenu *menuPtr, Tcl_Size index, int type);\nstatic char *\t\tMenuVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic Tcl_ObjCmdProc2 MenuWidgetObjCmd;\nstatic void\t\tMenuWorldChanged(void *instanceData);\nstatic int\t\tPostProcessEntry(TkMenuEntry *mePtr);\nstatic void\t\tRecursivelyDeleteMenu(TkMenu *menuPtr);\nstatic void\t\tUnhookCascadeEntry(TkMenuEntry *mePtr);\nstatic void\t\tMenuCleanup(void *unused);\nstatic int\t\tGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    Tcl_Obj *objPtr, int lastOK, Tcl_Size *indexPtr);\n\n/*\n * The structure below is a list of procs that respond to certain window\n * manager events. One of these includes a font change, which forces the\n * geometry proc to be called.\n */\n\nstatic const Tk_ClassProcs menuClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    MenuWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_MenuObjCmd --\n *\n *\tThis function is invoked to process the \"menu\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_MenuObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    Tk_Window newWin;\n    TkMenu *menuPtr;\n    TkMenuReferences *menuRefPtr;\n    Tcl_Size i;\n    int index, toplevel;\n    const char *windowName;\n    static const char *const typeStringList[] = {\"-type\", NULL};\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    TkMenuInit();\n\n    toplevel = 1;\n    for (i = 2; i < (objc - 1); i++) {\n\tif (Tcl_GetIndexFromObjStruct(NULL, objv[i], typeStringList,\n\t\tsizeof(char *), NULL, 0, &index) != TCL_ERROR) {\n\t    if ((Tcl_GetIndexFromObjStruct(NULL, objv[i + 1], menuTypeStrings,\n\t\t    sizeof(char *), NULL, 0, &index) == TCL_OK) && (index == MENUBAR)) {\n\t\ttoplevel = 0;\n\t    }\n\t    break;\n\t}\n    }\n\n    windowName = Tcl_GetString(objv[1]);\n    newWin = Tk_CreateWindowFromPath(interp, tkwin, windowName,\n\t    toplevel ? \"\" : NULL);\n    if (newWin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Initialize the data structure for the menu. Note that the menuPtr is\n     * eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, when\n     * Tcl_EventuallyFree is called.\n     */\n\n    menuPtr = (TkMenu *)Tcl_Alloc(sizeof(TkMenu));\n    memset(menuPtr, 0, sizeof(TkMenu));\n    menuPtr->tkwin = newWin;\n    menuPtr->display = Tk_Display(newWin);\n    menuPtr->interp = interp;\n    menuPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr,\n\t    MenuCmdDeletedProc);\n    menuPtr->active = TCL_INDEX_NONE;\n    menuPtr->cursorPtr = NULL;\n    menuPtr->mainMenuPtr = menuPtr;\n    menuPtr->menuType = UNKNOWN_TYPE;\n    Tcl_InitHashTable(&menuPtr->items, TCL_STRING_KEYS);\n    menuPtr->serial = 0;\n    TkMenuInitializeDrawingFields(menuPtr);\n\n    Tk_SetClass(menuPtr->tkwin, \"Menu\");\n    Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr);\n    Tk_CreateEventHandler(newWin,\n\t    ExposureMask|StructureNotifyMask|ActivateMask,\n\t    TkMenuEventProc, menuPtr);\n    if (Tk_InitOptions(interp, menuPtr,\n\t    tsdPtr->menuOptionTable, menuPtr->tkwin)\n\t    != TCL_OK) {\n\tTk_DestroyWindow(menuPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n\n    menuRefPtr = TkCreateMenuReferences(menuPtr->interp,\n\t    Tk_PathName(menuPtr->tkwin));\n    menuRefPtr->menuPtr = menuPtr;\n    menuPtr->menuRefPtr = menuRefPtr;\n    if (TCL_OK != TkpNewMenu(menuPtr)) {\n\tTk_DestroyWindow(menuPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    if (ConfigureMenu(interp, menuPtr, objc - 2, objv + 2) != TCL_OK) {\n\tTk_DestroyWindow(menuPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If a menu has a parent menu pointing to it as a cascade entry, the\n     * parent menu needs to be told that this menu now exists so that the\n     * platform-part of the menu is correctly updated.\n     *\n     * If a menu has an instance and has cascade entries, then each cascade\n     * menu must also have a parallel instance. This is especially true on the\n     * Mac, where each menu has to have a separate title everytime it is in a\n     * menubar. For instance, say you have a menu .m1 with a cascade entry for\n     * .m2, where .m2 does not exist yet. You then put .m1 into a menubar.\n     * This creates a menubar instance for .m1, but since .m2 is not there,\n     * nothing else happens. When we go to create .m2, we hook it up properly\n     * with .m1. However, we now need to clone .m2 and assign the clone of .m2\n     * to be the cascade entry for the clone of .m1. This is special case #1\n     * listed in the introductory comment.\n     */\n\n    if (menuRefPtr->parentEntryPtr != NULL) {\n\tTkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;\n\tTkMenuEntry *nextCascadePtr;\n\tTcl_Obj *newMenuName, *newObjv[2];\n\n\twhile (cascadeListPtr != NULL) {\n\t    nextCascadePtr = cascadeListPtr->nextCascadePtr;\n\n\t    /*\n\t     * If we have a new main menu, and an existing cloned menu\n\t     * points to this menu in a cascade entry, we have to clone the\n\t     * new menu and point the entry to the clone instead of the menu\n\t     * we are creating. Otherwise, ConfigureMenuEntry will hook up the\n\t     * platform-specific cascade linkages now that the menu we are\n\t     * creating exists.\n\t     */\n\n\t    if ((menuPtr->mainMenuPtr != menuPtr)\n\t\t    || ((menuPtr->mainMenuPtr == menuPtr)\n\t\t    && ((cascadeListPtr->menuPtr->mainMenuPtr\n\t\t    == cascadeListPtr->menuPtr)))) {\n\t\tnewObjv[0] = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\t\tnewObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin),-1);\n\t\tTcl_IncrRefCount(newObjv[0]);\n\t\tTcl_IncrRefCount(newObjv[1]);\n\t\tConfigureMenuEntry(cascadeListPtr, 2, newObjv);\n\t\tTcl_DecrRefCount(newObjv[0]);\n\t\tTcl_DecrRefCount(newObjv[1]);\n\t    } else {\n\t\tTcl_Obj *normalPtr = Tcl_NewStringObj(\"normal\", TCL_INDEX_NONE);\n\t\tTcl_Obj *windowNamePtr = Tcl_NewStringObj(\n\t\t\tTk_PathName(cascadeListPtr->menuPtr->tkwin), TCL_INDEX_NONE);\n\n\t\tTcl_IncrRefCount(normalPtr);\n\t\tTcl_IncrRefCount(windowNamePtr);\n\t\tnewMenuName = TkNewMenuName(menuPtr->interp,\n\t\t\twindowNamePtr, menuPtr);\n\t\tTcl_IncrRefCount(newMenuName);\n\t\tCloneMenu(menuPtr, newMenuName, normalPtr);\n\n\t\t/*\n\t\t * Now we can set the new menu instance to be the cascade\n\t\t * entry of the parent's instance.\n\t\t */\n\n\t\tnewObjv[0] = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\t\tnewObjv[1] = newMenuName;\n\t\tTcl_IncrRefCount(newObjv[0]);\n\t\tConfigureMenuEntry(cascadeListPtr, 2, newObjv);\n\t\tTcl_DecrRefCount(normalPtr);\n\t\tTcl_DecrRefCount(newObjv[0]);\n\t\tTcl_DecrRefCount(newObjv[1]);\n\t\tTcl_DecrRefCount(windowNamePtr);\n\t    }\n\t    cascadeListPtr = nextCascadePtr;\n\t}\n    }\n\n    /*\n     * If there already exist toplevel widgets that refer to this menu, find\n     * them and notify them so that they can reconfigure their geometry to\n     * reflect the menu.\n     */\n\n    if (menuRefPtr->topLevelListPtr != NULL) {\n\tTkMenuTopLevelList *topLevelListPtr = menuRefPtr->topLevelListPtr;\n\tTkMenuTopLevelList *nextPtr;\n\tTk_Window listtkwin;\n\n\twhile (topLevelListPtr != NULL) {\n\t    /*\n\t     * Need to get the next pointer first. Tk_SetWindowMenubar changes\n\t     * the list, so that the next pointer is different after calling\n\t     * it.\n\t     */\n\n\t    nextPtr = topLevelListPtr->nextPtr;\n\t    listtkwin = topLevelListPtr->tkwin;\n\t    Tk_SetWindowMenubar(menuPtr->interp, listtkwin,\n\t\t    Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin));\n\t    topLevelListPtr = nextPtr;\n\t}\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(menuPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMenuWidgetObjCmd(\n    void *clientData,\t/* Information about menu widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n    TkMenuEntry *mePtr;\n    int result = TCL_OK;\n    int option;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], menuOptions,\n\t    sizeof(char *), \"option\", 0, &option) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Preserve(menuPtr);\n\n    switch ((enum options) option) {\n    case MENU_ACTIVATE: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (menuPtr->active == index) {\n\t    goto done;\n\t}\n\tif ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY)\n\t\t|| (menuPtr->entries[index]->state == ENTRY_DISABLED))) {\n\t    index = TCL_INDEX_NONE;\n\t}\n\tresult = TkActivateMenuEntry(menuPtr, index);\n\tbreak;\n    }\n    case MENU_ADD:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"type ?-option value ...?\");\n\t    goto error;\n\t}\n\n\tif (MenuAddOrInsert(interp, menuPtr, NULL, objc-2, objv+2) != TCL_OK){\n\t    goto error;\n\t}\n\tbreak;\n    case MENU_CGET: {\n\tTcl_Obj *resultPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    goto error;\n\t}\n\tresultPtr = Tk_GetOptionValue(interp, menuPtr,\n\t\ttsdPtr->menuOptionTable, objv[2],\n\t\tmenuPtr->tkwin);\n\tif (resultPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n    case MENU_CLONE:\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"newMenuName ?menuType?\");\n\t    goto error;\n\t}\n\tresult = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);\n\tbreak;\n    case MENU_CONFIGURE: {\n\tTcl_Obj *resultPtr;\n\n\tif (objc == 2) {\n\t    resultPtr = Tk_GetOptionInfo(interp, menuPtr,\n\t\t    tsdPtr->menuOptionTable, NULL,\n\t\t    menuPtr->tkwin);\n\t    if (resultPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tresult = TCL_OK;\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t    }\n\t} else if (objc == 3) {\n\t    resultPtr = Tk_GetOptionInfo(interp, menuPtr,\n\t\t    tsdPtr->menuOptionTable, objv[2],\n\t\t    menuPtr->tkwin);\n\t    if (resultPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tresult = TCL_OK;\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t    }\n\t} else {\n\t    result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);\n\t}\n\tif (result != TCL_OK) {\n\t    goto error;\n\t}\n\tbreak;\n    }\n    case MENU_DELETE: {\n\tTcl_Size first, last;\n\tTcl_WideInt w;\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"first ?last?\");\n\t    goto error;\n\t}\n\n\t/*\n\t * If 'first' explicitly refers to past the end of the menu, we don't\n\t * do anything. [Bug 220950]\n\t */\n\n\tif (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))\n\t\t&& Tcl_GetWideIntFromObj(NULL, objv[2], &w) == TCL_OK) {\n\t    first = w;\n\t    if (first >= menuPtr->numEntries) {\n\t\tgoto done;\n\t    }\n\t} else if (GetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){\n\t    goto error;\n\t}\n\tif (objc == 3) {\n\t    last = first;\n\t} else if (GetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tif (menuPtr->tearoff && (first == 0)) {\n\t    /*\n\t     * Sorry, can't delete the tearoff entry; must reconfigure the\n\t     * menu.\n\t     */\n\n\t    first = 1;\n\t}\n\tif ((first < 0) || (last < first)) {\n\t    goto done;\n\t}\n\tDeleteMenuCloneEntries(menuPtr, first, last);\n\tbreak;\n    }\n    case MENU_ENTRYCGET: {\n\tTcl_Size index;\n\tTcl_Obj *resultPtr;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index option\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    goto done;\n\t}\n\tmePtr = menuPtr->entries[index];\n\tTcl_Preserve(mePtr);\n\tresultPtr = Tk_GetOptionValue(interp, mePtr,\n\t\tmePtr->optionTable, objv[3], menuPtr->tkwin);\n\tTcl_Release(mePtr);\n\tif (resultPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, resultPtr);\n\tbreak;\n    }\n    case MENU_ENTRYCONFIGURE: {\n\tTcl_Size index;\n\tTcl_Obj *resultPtr;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index ?-option value ...?\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    goto done;\n\t}\n\tmePtr = menuPtr->entries[index];\n\tTcl_Preserve(mePtr);\n\tif (objc == 3) {\n\t    resultPtr = Tk_GetOptionInfo(interp, mePtr,\n\t\t    mePtr->optionTable, NULL, menuPtr->tkwin);\n\t    if (resultPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tresult = TCL_OK;\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t    }\n\t} else if (objc == 4) {\n\t    resultPtr = Tk_GetOptionInfo(interp, mePtr,\n\t\t    mePtr->optionTable, objv[3], menuPtr->tkwin);\n\t    if (resultPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tresult = TCL_OK;\n\t\tTcl_SetObjResult(interp, resultPtr);\n\t    }\n\t} else {\n\t    result = ConfigureMenuCloneEntries(menuPtr, index,\n\t\t    objc-3, objv+3);\n\t}\n\tTcl_Release(mePtr);\n\tbreak;\n    }\n    case MENU_ID: {\n\tTcl_Size index;\n\tconst char *idStr;\n\tTcl_HashEntry *entryPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    goto done;\n\t}\n\tentryPtr = menuPtr->entries[index]->entryPtr;\n\tif (entryPtr) {\n\t    idStr = (const char *)Tcl_GetHashKey(&menuPtr->items, entryPtr);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(idStr, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    }\n    case MENU_INDEX: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"string\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewObj());\n\t} else {\n\t    Tcl_SetObjResult(interp, TkNewIndexObj(index));\n\t}\n\tbreak;\n    }\n    case MENU_INSERT:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"index type ?-option value ...?\");\n\t    goto error;\n\t}\n\tif (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) {\n\t    goto error;\n\t}\n\tbreak;\n    case MENU_INVOKE: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    goto done;\n\t}\n\tresult = TkInvokeMenu(interp, menuPtr, index);\n\tbreak;\n    }\n    case MENU_POST: {\n\tint x, y;\n\tTcl_Size index = TCL_INDEX_NONE;\n\n\tif (objc != 4 && objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"x y ?index?\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    goto error;\n\t}\n\tif (objc == 5) {\n\t    if (GetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t}\n\n\t/*\n\t * Tearoff menus are the same as ordinary menus on the Mac and are\n\t * posted differently on Windows than non-tearoffs. TkpPostMenu\n\t * does not actually map the menu's window on those platforms, and\n\t * popup menus have to be handled specially.  Also, menubar menus are\n\t * not intended to be posted (bug 1567681, 2160206).\n\t */\n\n\tif (menuPtr->menuType == MENUBAR) {\n\t    Tcl_AppendResult(interp, \"a menubar menu cannot be posted\", (char *)NULL);\n\t    return TCL_ERROR;\n\t} else if (menuPtr->menuType != TEAROFF_MENU) {\n\t    result = TkpPostMenu(interp, menuPtr, x, y, index);\n\t} else {\n\t    result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);\n\t}\n\tbreak;\n    }\n    case MENU_POSTCASCADE: {\n\tTcl_Size index;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {\n\t    result = TkPostSubmenu(interp, menuPtr, NULL);\n\t} else {\n\t    result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);\n\t}\n\tbreak;\n    }\n    case MENU_TYPE: {\n\tTcl_Size index;\n\tconst char *typeStr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tif (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (index < 0) {\n\t    goto done;\n\t}\n\tif (menuPtr->entries[index]->type == TEAROFF_ENTRY) {\n\t    typeStr = \"tearoff\";\n\t} else {\n\t    typeStr = menuEntryTypeStrings[menuPtr->entries[index]->type];\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case MENU_UNPOST:\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    goto error;\n\t}\n\tTk_UnmapWindow(menuPtr->tkwin);\n\tresult = TkPostSubmenu(interp, menuPtr, NULL);\n\tbreak;\n    case MENU_XPOSITION:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tresult = MenuDoXPosition(interp, menuPtr, objv[2]);\n\tbreak;\n    case MENU_YPOSITION:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    goto error;\n\t}\n\tresult = MenuDoYPosition(interp, menuPtr, objv[2]);\n\tbreak;\n    }\n  done:\n    Tcl_Release(menuPtr);\n    return result;\n\n  error:\n    Tcl_Release(menuPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkInvokeMenu --\n *\n *\tGiven a menu and an index, takes the appropriate action for the entry\n *\tassociated with that index.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tCommands may get excecuted; variables may get set; sub-menus may get\n *\tposted, the passed menu may be destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkInvokeMenu(\n    Tcl_Interp *interp,\t\t/* The interp that the menu lives in. */\n    TkMenu *menuPtr,\t\t/* The menu we are invoking. */\n\t\t\t\t/* Must be protected by Tcl_Preserve\n\t\t\t\t * against freeing by the caller.\n\t\t\t\t * Tk Bug [2d3a81c0].\n\t\t\t\t */\n    Tcl_Size index)\t\t/* The zero based index of the item we are\n\t\t\t\t * invoking. */\n{\n    int result = TCL_OK;\n    TkMenuEntry *mePtr;\n    Tcl_Obj *commandPtr = NULL, *namePtr = NULL;\n\n    if (index < 0) {\n\tgoto done;\n    }\n    mePtr = menuPtr->entries[index];\n    if (mePtr->state == ENTRY_DISABLED) {\n\tgoto done;\n    }\n\n    if (mePtr->commandPtr != NULL) {\n\tcommandPtr = mePtr->commandPtr;\n\tTcl_IncrRefCount(commandPtr);\n    }\n    if ((mePtr->type == CHECK_BUTTON_ENTRY) ||\n\t    (mePtr->type == RADIO_BUTTON_ENTRY)) {\n\tif (mePtr->namePtr != NULL) {\n\t    namePtr = mePtr->namePtr;\n\t    Tcl_IncrRefCount(namePtr);\n\t}\n    }\n\n    if (mePtr->type == TEAROFF_ENTRY) {\n\tTcl_DString ds;\n\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, \"tk::TearOffMenu \", TCL_INDEX_NONE);\n\tTcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), TCL_INDEX_NONE);\n\tresult = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&ds);\n    } else if ((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    && (namePtr != NULL)) {\n\tTcl_Obj *valuePtr;\n\n\tif (mePtr->entryFlags & ENTRY_SELECTED) {\n\t    valuePtr = mePtr->offValuePtr;\n\t} else {\n\t    valuePtr = mePtr->onValuePtr;\n\t}\n\tif (valuePtr == NULL) {\n\t    valuePtr = Tcl_NewObj();\n\t}\n\tTcl_IncrRefCount(valuePtr);\n\tif (Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr,\n\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {\n\t    result = TCL_ERROR;\n\t}\n\tTcl_DecrRefCount(valuePtr);\n    } else if ((mePtr->type == RADIO_BUTTON_ENTRY)\n\t    && (namePtr != NULL)) {\n\tTcl_Obj *valuePtr = mePtr->onValuePtr;\n\n\tif (valuePtr == NULL) {\n\t    valuePtr = Tcl_NewObj();\n\t}\n\tTcl_IncrRefCount(valuePtr);\n\tif (Tcl_ObjSetVar2(interp, namePtr, NULL, valuePtr,\n\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {\n\t    result = TCL_ERROR;\n\t}\n\tTcl_DecrRefCount(valuePtr);\n    }\n\n    /*\n     * We check numEntries in addition to whether the menu entry has a command\n     * because that goes to zero if the menu gets deleted (e.g., during\n     * command evaluation).\n     */\n\n    if ((menuPtr->numEntries != 0) && (result == TCL_OK)\n\t    && (commandPtr != NULL)) {\n\tresult = Tcl_EvalObjEx(interp, commandPtr, TCL_EVAL_GLOBAL);\n    }\n    if (commandPtr != NULL) {\n\tTcl_DecrRefCount(commandPtr);\n    }\n    if (namePtr != NULL) {\n\tTcl_DecrRefCount(namePtr);\n    }\n\n  done:\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyMenuInstance --\n *\n *\tThis function is invoked by TkDestroyMenu to clean up the internal\n *\tstructure of a menu at a safe time (when no-one is using it anymore).\n *\tOnly takes care of one instance of the menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the menu is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyMenuInstance(\n    TkMenu *menuPtr)\t\t/* Info about menu widget. */\n{\n    int i;\n    TkMenu *menuInstancePtr;\n    TkMenuEntry *cascadePtr, *nextCascadePtr;\n    Tcl_Obj *newObjv[2];\n    TkMenu *parentMainMenuPtr;\n    TkMenuEntry *parentMainEntryPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * If the menu has any cascade menu entries pointing to it, the cascade\n     * entries need to be told that the menu is going away. We need to clear\n     * the menu ptr field in the menu reference at this point in the code so\n     * that everything else can forget about this menu properly. We also need\n     * to reset -menu field of all entries that are not main menus back to\n     * this entry name if this is a main menu pointed to by another main\n     * menu. If there is a clone menu that points to this menu, then this menu\n     * is itself a clone, so when this menu goes away, the -menu field of the\n     * pointing entry must be set back to this menu's main menu name so that\n     * later if another menu is created the cascade hierarchy can be\n     * maintained.\n     */\n\n    TkpDestroyMenu(menuPtr);\n    if (menuPtr->menuRefPtr == NULL) {\n\treturn;\n    }\n    cascadePtr = menuPtr->menuRefPtr->parentEntryPtr;\n    menuPtr->menuRefPtr->menuPtr = NULL;\n    if (TkFreeMenuReferences(menuPtr->menuRefPtr)) {\n\tmenuPtr->menuRefPtr = NULL;\n    }\n\n    for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) {\n\tnextCascadePtr = cascadePtr->nextCascadePtr;\n\n\tif (menuPtr->mainMenuPtr != menuPtr) {\n\t    Tcl_Obj *menuNamePtr = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\n\t    parentMainMenuPtr = cascadePtr->menuPtr->mainMenuPtr;\n\t    parentMainEntryPtr =\n\t\t    parentMainMenuPtr->entries[cascadePtr->index];\n\t    newObjv[0] = menuNamePtr;\n\t    newObjv[1] = parentMainEntryPtr->namePtr;\n\n\t    /*\n\t     * It is possible that the menu info is out of sync, and these\n\t     * things point to NULL, so verify existence [Bug: 3402]\n\t     */\n\n\t    if (newObjv[0] && newObjv[1]) {\n\t\tTcl_IncrRefCount(newObjv[0]);\n\t\tTcl_IncrRefCount(newObjv[1]);\n\t\tConfigureMenuEntry(cascadePtr, 2, newObjv);\n\t\tTcl_DecrRefCount(newObjv[0]);\n\t\tTcl_DecrRefCount(newObjv[1]);\n\t    }\n\t} else {\n\t    ConfigureMenuEntry(cascadePtr, 0, NULL);\n\t}\n    }\n\n    if (menuPtr->mainMenuPtr != menuPtr) {\n\tfor (menuInstancePtr = menuPtr->mainMenuPtr;\n\t\tmenuInstancePtr != NULL;\n\t\tmenuInstancePtr = menuInstancePtr->nextInstancePtr) {\n\t    if (menuInstancePtr->nextInstancePtr == menuPtr) {\n\t\tmenuInstancePtr->nextInstancePtr =\n\t\t\tmenuInstancePtr->nextInstancePtr->nextInstancePtr;\n\t\tbreak;\n\t    }\n\t}\n    } else if (menuPtr->nextInstancePtr != NULL) {\n\tTcl_Panic(\"Attempting to delete main menu when there are still clones\");\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeConfigOptions handle all the standard option-related stuff.\n     */\n\n    for (i = menuPtr->numEntries; --i >= 0; ) {\n\t/*\n\t * Clean up the hash entry for the menu item ID.\n\t * This cannot be postponed until the entry is eventually freed,\n\t * because the hash table may already have been deleted by then.\n\t */\n\n\tif (menuPtr->entries[i]->entryPtr) {\n\t    Tcl_DeleteHashEntry(menuPtr->entries[i]->entryPtr);\n\t    menuPtr->entries[i]->entryPtr = NULL;\n\t}\n\n\t/*\n\t * As each menu entry is deleted from the end of the array of entries,\n\t * decrement menuPtr->numEntries. Otherwise, the act of deleting menu\n\t * entry i will dereference freed memory attempting to queue a redraw\n\t * for menu entries (i+1)...numEntries.\n\t */\n\n\tTcl_EventuallyFree(menuPtr->entries[i],\n\t\tDestroyMenuEntry);\n\tmenuPtr->numEntries = i;\n    }\n    menuPtr->active = -1;\n    if (menuPtr->entries != NULL) {\n\tTcl_Free(menuPtr->entries);\n\tmenuPtr->entries = NULL;\n    }\n    Tcl_DeleteHashTable(&menuPtr->items);\n    TkMenuFreeDrawOptions(menuPtr);\n    Tk_FreeConfigOptions(menuPtr,\n\t    tsdPtr->menuOptionTable, menuPtr->tkwin);\n    if (menuPtr->tkwin != NULL) {\n\tTk_Window tkwin = menuPtr->tkwin;\n\n\tmenuPtr->tkwin = NULL;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDestroyMenu --\n *\n *\tThis function is invoked to clean up the internal structure of a menu\n *\tat a safe time (when no-one is using it anymore). If called on a main\n *\tinstance, destroys all of the instances. If called on a non-main\n *\tinstance, just destroys that instance.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the menu is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDestroyMenu(\n    TkMenu *menuPtr)\t\t/* Info about menu widget. */\n{\n    TkMenu *menuInstancePtr;\n    TkMenuTopLevelList *topLevelListPtr, *nextTopLevelPtr;\n\n    if (menuPtr->menuFlags & MENU_DELETION_PENDING) {\n\treturn;\n    }\n\n    Tcl_Preserve(menuPtr);\n\n    /*\n     * Now destroy all non-tearoff instances of this menu if this is a parent\n     * menu. Is this loop safe enough? Are there going to be destroy bindings\n     * on child menus which kill the parent? If not, we have to do a slightly\n     * more complex scheme.\n     */\n\n    menuPtr->menuFlags |= MENU_DELETION_PENDING;\n    if (menuPtr->menuRefPtr != NULL) {\n\t/*\n\t * If any toplevel widgets have this menu as their menubar, the\n\t * geometry of the window may have to be recalculated.\n\t */\n\n\ttopLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;\n\twhile (topLevelListPtr != NULL) {\n\t    nextTopLevelPtr = topLevelListPtr->nextPtr;\n\t    TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);\n\t    topLevelListPtr = nextTopLevelPtr;\n\t}\n    }\n    if (menuPtr->mainMenuPtr == menuPtr) {\n\twhile (menuPtr->nextInstancePtr != NULL) {\n\t    menuInstancePtr = menuPtr->nextInstancePtr;\n\t    menuPtr->nextInstancePtr = menuInstancePtr->nextInstancePtr;\n\t    if (menuInstancePtr->tkwin != NULL) {\n\t\tTk_Window tkwin = menuInstancePtr->tkwin;\n\n\t\t/*\n\t\t * Note: it may be desirable to NULL out the tkwin field of\n\t\t * menuInstancePtr here:\n\t\t * menuInstancePtr->tkwin = NULL;\n\t\t */\n\n\t\tTk_DestroyWindow(tkwin);\n\t    }\n\t}\n    }\n\n    DestroyMenuInstance(menuPtr);\n\n    Tcl_Release(menuPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UnhookCascadeEntry --\n *\n *\tThis entry is removed from the list of entries that point to the\n *\tcascade menu. This is done in preparation for changing the menu that\n *\tthis entry points to.\n *\n *\tAt the end of this function, the menu entry no longer contains a\n *\treference to a 'TkMenuReferences' structure, and therefore no such\n *\tstructure contains a reference to this menu entry either.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe appropriate lists are modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnhookCascadeEntry(\n    TkMenuEntry *mePtr)\t\t/* The cascade entry we are removing from the\n\t\t\t\t * cascade list. */\n{\n    TkMenuEntry *cascadeEntryPtr;\n    TkMenuEntry *prevCascadePtr;\n    TkMenuReferences *menuRefPtr;\n\n    menuRefPtr = mePtr->childMenuRefPtr;\n    if (menuRefPtr == NULL) {\n\treturn;\n    }\n\n    cascadeEntryPtr = menuRefPtr->parentEntryPtr;\n    if (cascadeEntryPtr == NULL) {\n\tTkFreeMenuReferences(menuRefPtr);\n\tmePtr->childMenuRefPtr = NULL;\n\treturn;\n    }\n\n    /*\n     * Singularly linked list deletion. The two special cases are 1. one\n     * element; 2. The first element is the one we want.\n     */\n\n    if (cascadeEntryPtr == mePtr) {\n\tif (cascadeEntryPtr->nextCascadePtr == NULL) {\n\t    /*\n\t     * This is the last menu entry which points to this menu, so we\n\t     * need to clear out the list pointer in the cascade itself.\n\t     */\n\n\t    menuRefPtr->parentEntryPtr = NULL;\n\n\t    /*\n\t     * The original field is set to zero below, after it is freed.\n\t     */\n\n\t    TkFreeMenuReferences(menuRefPtr);\n\t} else {\n\t    menuRefPtr->parentEntryPtr = cascadeEntryPtr->nextCascadePtr;\n\t}\n\tmePtr->nextCascadePtr = NULL;\n    } else {\n\tfor (prevCascadePtr = cascadeEntryPtr,\n\t\tcascadeEntryPtr = cascadeEntryPtr->nextCascadePtr;\n\t\tcascadeEntryPtr != NULL;\n\t\tprevCascadePtr = cascadeEntryPtr,\n\t\tcascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {\n\t    if (cascadeEntryPtr == mePtr){\n\t\tprevCascadePtr->nextCascadePtr =\n\t\t\tcascadeEntryPtr->nextCascadePtr;\n\t\tcascadeEntryPtr->nextCascadePtr = NULL;\n\t\tbreak;\n\t    }\n\t}\n\tmePtr->nextCascadePtr = NULL;\n    }\n    mePtr->childMenuRefPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyMenuEntry --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of a menu entry at a safe time (when no-one\n *\tis using it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the menu entry is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyMenuEntry(\n    void *memPtr)\t\t/* Pointer to entry to be freed. */\n{\n    TkMenuEntry *mePtr = (TkMenuEntry *)memPtr;\n    TkMenu *menuPtr = mePtr->menuPtr;\n\n    if (menuPtr->postedCascade == mePtr) {\n\t/*\n\t * Ignore errors while unposting the menu, since it's possible that\n\t * the menu has already been deleted and the unpost will generate an\n\t * error.\n\t */\n\n\tTkPostSubmenu(menuPtr->interp, menuPtr, NULL);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeConfigOptions handle all the standard option-related stuff.\n     */\n\n    if (mePtr->type == CASCADE_ENTRY) {\n\tif (menuPtr->mainMenuPtr != menuPtr) {\n\t    TkMenu *destroyThis = NULL;\n\t    TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;\n\n\t    /*\n\t     * The menu as a whole is a clone. We must delete the clone of the\n\t     * cascaded menu for the particular entry we are destroying.\n\t     */\n\n\t    if (menuRefPtr != NULL) {\n\t\tdestroyThis = menuRefPtr->menuPtr;\n\n\t\t/*\n\t\t * But only if it is a clone. What can happen is that we are\n\t\t * in the middle of deleting a menu and this menu pointer has\n\t\t * already been reset to point to the original menu. In that\n\t\t * case we have nothing special to do.\n\t\t */\n\n\t\tif ((destroyThis != NULL)\n\t\t\t&& (destroyThis->mainMenuPtr == destroyThis)) {\n\t\t    destroyThis = NULL;\n\t\t}\n\t    }\n\t    UnhookCascadeEntry(mePtr);\n\t    menuRefPtr = mePtr->childMenuRefPtr;\n\t    if (menuRefPtr != NULL) {\n\t\tif (menuRefPtr->menuPtr == destroyThis) {\n\t\t    menuRefPtr->menuPtr = NULL;\n\t\t}\n\t    }\n\t    if (destroyThis != NULL) {\n\t\tTkDestroyMenu(destroyThis);\n\t    }\n\t} else {\n\t    UnhookCascadeEntry(mePtr);\n\t}\n    }\n    if (mePtr->image != NULL) {\n\tTk_FreeImage(mePtr->image);\n    }\n    if (mePtr->selectImage != NULL) {\n\tTk_FreeImage(mePtr->selectImage);\n    }\n    if (((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    || (mePtr->type == RADIO_BUTTON_ENTRY))\n\t    && (mePtr->namePtr != NULL)) {\n\tconst char *varName = Tcl_GetString(mePtr->namePtr);\n\n\tTcl_UntraceVar2(menuPtr->interp, varName, NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuVarProc, mePtr);\n    }\n    if (mePtr->entryPtr) {\n\tTcl_DeleteHashEntry(mePtr->entryPtr);\n\tmePtr->entryPtr = NULL;\n    }\n    TkpDestroyMenuEntry(mePtr);\n    TkMenuEntryFreeDrawOptions(mePtr);\n    Tk_FreeConfigOptions(mePtr, mePtr->optionTable, menuPtr->tkwin);\n    Tcl_Free(mePtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * MenuWorldChanged --\n *\n *\tThis function is called when the world has changed in some way (such\n *\tas the fonts in the system changing) and the widget needs to recompute\n *\tall its graphics contexts and determine its new geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMenu will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nMenuWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    TkMenu *menuPtr = (TkMenu *)instanceData;\n    Tcl_Size i;\n\n    TkMenuConfigureDrawOptions(menuPtr);\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tTkMenuConfigureEntryDrawOptions(menuPtr->entries[i],\n\t\tmenuPtr->entries[i]->index);\n\tTkpConfigureMenuEntry(menuPtr->entries[i]);\n    }\n    TkEventuallyRecomputeMenu(menuPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureMenu --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a menu widget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, font, etc. get set for\n *\tmenuPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureMenu(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkMenu *menuPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    int i;\n    TkMenu *menuListPtr, *cleanupPtr;\n    int result;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;\n\t    menuListPtr = menuListPtr->nextInstancePtr) {\n\tmenuListPtr->errorStructPtr = (Tk_SavedOptions *)Tcl_Alloc(sizeof(Tk_SavedOptions));\n\tresult = Tk_SetOptions(interp, menuListPtr,\n\t\ttsdPtr->menuOptionTable, objc, objv,\n\t\tmenuListPtr->tkwin, menuListPtr->errorStructPtr, NULL);\n\tif (result != TCL_OK) {\n\t    for (cleanupPtr = menuPtr->mainMenuPtr;\n\t\t    cleanupPtr != menuListPtr;\n\t\t    cleanupPtr = cleanupPtr->nextInstancePtr) {\n\t\tTk_RestoreSavedOptions(cleanupPtr->errorStructPtr);\n\t\tTcl_Free(cleanupPtr->errorStructPtr);\n\t\tcleanupPtr->errorStructPtr = NULL;\n\t    }\n\t    if (menuListPtr->errorStructPtr != NULL) {\n\t\tTk_RestoreSavedOptions(menuListPtr->errorStructPtr);\n\t\tTcl_Free(menuListPtr->errorStructPtr);\n\t\tmenuListPtr->errorStructPtr = NULL;\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * When a menu is created, the type is in all of the arguments to the\n\t * menu command. Let Tk_ConfigureWidget take care of parsing them, and\n\t * then set the type after we can look at the type string. Once set, a\n\t * menu's type cannot be changed\n\t */\n\n\tif (menuListPtr->menuType == UNKNOWN_TYPE) {\n\t    Tcl_GetIndexFromObjStruct(NULL, menuListPtr->menuTypePtr,\n\t\t    menuTypeStrings, sizeof(char *), NULL, 0, &menuListPtr->menuType);\n\n\t    /*\n\t     * Configure the new window to be either a pop-up menu or a\n\t     * tear-off menu. We don't do this for menubars since they are not\n\t     * toplevel windows. Also, since this gets called before CloneMenu\n\t     * has a chance to set the menuType field, we have to look at the\n\t     * menuTypeName field to tell that this is a menu bar.\n\t     */\n\n\t    if (menuListPtr->menuType == MAIN_MENU) {\n\t\tint typeFlag = TK_MAKE_MENU_POPUP;\n\t\tTk_Window tkwin = menuPtr->tkwin;\n\n\t\t/*\n\t\t * Work out if we are the child of a menubar or a popup.\n\t\t */\n\n\t\twhile (1) {\n\t\t    Tk_Window parent = Tk_Parent(tkwin);\n\n\t\t    if (parent == NULL ||\n\t\t\tTk_Class(parent) != Tk_Class(menuPtr->tkwin)) {\n\t\t\tbreak;\n\t\t    }\n\t\t    tkwin = parent;\n\t\t}\n\t\tif (((TkMenu *) tkwin)->menuType == MENUBAR) {\n\t\t    typeFlag = TK_MAKE_MENU_DROPDOWN;\n\t\t}\n\n\t\tTkpMakeMenuWindow(menuListPtr->tkwin, typeFlag);\n\t    } else if (menuListPtr->menuType == TEAROFF_MENU) {\n\t\tTkpMakeMenuWindow(menuListPtr->tkwin, TK_MAKE_MENU_TEAROFF);\n\t    }\n\t}\n\n\t/*\n\t * Depending on the -tearOff option, make sure that there is or isn't\n\t * an initial tear-off entry at the beginning of the menu.\n\t */\n\n\tif (menuListPtr->tearoff) {\n\t    if ((menuListPtr->numEntries == 0)\n\t\t    || (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) {\n\t\tif (MenuNewEntry(menuListPtr, 0, TEAROFF_ENTRY) == NULL) {\n\t\t    for (cleanupPtr = menuPtr->mainMenuPtr;\n\t\t\t    cleanupPtr != menuListPtr;\n\t\t\t    cleanupPtr = cleanupPtr->nextInstancePtr) {\n\t\t\tTk_RestoreSavedOptions(cleanupPtr->errorStructPtr);\n\t\t\tTcl_Free(cleanupPtr->errorStructPtr);\n\t\t\tcleanupPtr->errorStructPtr = NULL;\n\t\t    }\n\t\t    if (menuListPtr->errorStructPtr != NULL) {\n\t\t\tTk_RestoreSavedOptions(menuListPtr->errorStructPtr);\n\t\t\tTcl_Free(menuListPtr->errorStructPtr);\n\t\t\tmenuListPtr->errorStructPtr = NULL;\n\t\t    }\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t} else if ((menuListPtr->numEntries > 0)\n\t\t&& (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) {\n\n\t    Tcl_EventuallyFree(menuListPtr->entries[0], DestroyMenuEntry);\n\n\t    for (i = 0; i < menuListPtr->numEntries - 1; i++) {\n\t\tmenuListPtr->entries[i] = menuListPtr->entries[i + 1];\n\t\tmenuListPtr->entries[i]->index = i;\n\t    }\n\t    if (--menuListPtr->numEntries == 0) {\n\t\tTcl_Free(menuListPtr->entries);\n\t\tmenuListPtr->entries = NULL;\n\t    }\n\t}\n\n\tTkMenuConfigureDrawOptions(menuListPtr);\n\n\t/*\n\t * After reconfiguring a menu, we need to reconfigure all of the\n\t * entries in the menu, since some of the things in the children (such\n\t * as graphics contexts) may have to change to reflect changes in the\n\t * parent.\n\t */\n\n\tfor (i = 0; i < menuListPtr->numEntries; i++) {\n\t    TkMenuEntry *mePtr;\n\n\t    mePtr = menuListPtr->entries[i];\n\t    ConfigureMenuEntry(mePtr, 0, NULL);\n\t}\n\n\tTkEventuallyRecomputeMenu(menuListPtr);\n    }\n\n    for (cleanupPtr = menuPtr->mainMenuPtr; cleanupPtr != NULL;\n\t    cleanupPtr = cleanupPtr->nextInstancePtr) {\n\tTk_FreeSavedOptions(cleanupPtr->errorStructPtr);\n\tTcl_Free(cleanupPtr->errorStructPtr);\n\tcleanupPtr->errorStructPtr = NULL;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PostProcessEntry --\n *\n *\tThis is called by ConfigureMenuEntry to do all of the configuration\n *\tafter Tk_SetOptions is called. This is separate so that error handling\n *\tis easier.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information such as label and accelerator get set for\n *\tmePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPostProcessEntry(\n    TkMenuEntry *mePtr)\t\t\t/* The entry we are configuring. */\n{\n    TkMenu *menuPtr = mePtr->menuPtr;\n    int index = mePtr->index;\n    const char *name;\n    Tk_Image image;\n\n    /*\n     * The code below handles special configuration stuff not taken care of by\n     * Tk_ConfigureWidget, such as special processing for defaults, sizing\n     * strings, graphics contexts, etc.\n     */\n\n    if (mePtr->labelPtr == NULL) {\n\tmePtr->labelLength = 0;\n    } else {\n\t(void)Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);\n    }\n    if (mePtr->accelPtr == NULL) {\n\tmePtr->accelLength = 0;\n    } else {\n\t(void)Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);\n    }\n\n    /*\n     * If this is a cascade entry, the platform-specific data of the child\n     * menu has to be updated. Also, the links that point to parents and\n     * cascades have to be updated.\n     */\n\n    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {\n\tTkMenuEntry *cascadeEntryPtr;\n\tint alreadyThere;\n\tTkMenuReferences *menuRefPtr;\n\tchar *oldHashKey = NULL;\t/* Initialization only needed to\n\t\t\t\t\t * prevent compiler warning. */\n\n\t/*\n\t * This is a cascade entry. If the menu that the cascade entry is\n\t * pointing to has changed, we need to remove this entry from the list\n\t * of entries pointing to the old menu, and add a cascade reference to\n\t * the list of entries pointing to the new menu.\n\t *\n\t * BUG: We are not recloning for special case #3 yet.\n\t */\n\n\tname = Tcl_GetString(mePtr->namePtr);\n\tif (mePtr->childMenuRefPtr != NULL) {\n\t    oldHashKey = (char *)Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),\n\t\t    mePtr->childMenuRefPtr->hashEntryPtr);\n\t    if (strcmp(oldHashKey, name) != 0) {\n\t\tUnhookCascadeEntry(mePtr);\n\t    }\n\t}\n\n\tif ((mePtr->childMenuRefPtr == NULL)\n\t\t|| (strcmp(oldHashKey, name) != 0)) {\n\t    menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name);\n\t    mePtr->childMenuRefPtr = menuRefPtr;\n\n\t    if (menuRefPtr->parentEntryPtr == NULL) {\n\t\tmenuRefPtr->parentEntryPtr = mePtr;\n\t    } else {\n\t\talreadyThere = 0;\n\t\tfor (cascadeEntryPtr = menuRefPtr->parentEntryPtr;\n\t\t\tcascadeEntryPtr != NULL;\n\t\t\tcascadeEntryPtr =\n\t\t\tcascadeEntryPtr->nextCascadePtr) {\n\t\t    if (cascadeEntryPtr == mePtr) {\n\t\t\talreadyThere = 1;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\n\t\t/*\n\t\t * Put the item at the front of the list.\n\t\t */\n\n\t\tif (!alreadyThere) {\n\t\t    mePtr->nextCascadePtr = menuRefPtr->parentEntryPtr;\n\t\t    menuRefPtr->parentEntryPtr = mePtr;\n\t\t}\n\t    }\n\t}\n    }\n\n    if (TkMenuConfigureEntryDrawOptions(mePtr, index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Get the images for the entry, if there are any. Allocate the new images\n     * before freeing the old ones, so that the reference counts don't go to\n     * zero and cause image data to be discarded.\n     */\n\n    if (mePtr->imagePtr != NULL) {\n\tconst char *imageString = Tcl_GetString(mePtr->imagePtr);\n\n\timage = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString,\n\t\tTkMenuImageProc, mePtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (mePtr->image != NULL) {\n\tTk_FreeImage(mePtr->image);\n    }\n    mePtr->image = image;\n    if (mePtr->selectImagePtr != NULL) {\n\tconst char *selectImageString = Tcl_GetString(mePtr->selectImagePtr);\n\n\timage = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString,\n\t\tTkMenuSelectImageProc, mePtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (mePtr->selectImage != NULL) {\n\tTk_FreeImage(mePtr->selectImage);\n    }\n    mePtr->selectImage = image;\n\n    if ((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    || (mePtr->type == RADIO_BUTTON_ENTRY)) {\n\tTcl_Obj *valuePtr;\n\n\tif (mePtr->namePtr == NULL) {\n\t    if (mePtr->labelPtr == NULL) {\n\t\tmePtr->namePtr = NULL;\n\t    } else {\n\t\tmePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);\n\t\tTcl_IncrRefCount(mePtr->namePtr);\n\t    }\n\t}\n\tif (mePtr->onValuePtr == NULL) {\n\t    if (mePtr->labelPtr == NULL) {\n\t\tmePtr->onValuePtr = NULL;\n\t    } else {\n\t\tmePtr->onValuePtr = Tcl_DuplicateObj(mePtr->labelPtr);\n\t\tTcl_IncrRefCount(mePtr->onValuePtr);\n\t    }\n\t}\n\n\t/*\n\t * Select the entry if the associated variable has the appropriate\n\t * value, initialize the variable if it doesn't exist, then set a\n\t * trace on the variable to monitor future changes to its value.\n\t */\n\n\tif (mePtr->namePtr != NULL) {\n\t    valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, NULL,\n\t\t    TCL_GLOBAL_ONLY);\n\t} else {\n\t    valuePtr = NULL;\n\t}\n\tmePtr->entryFlags &= ~ENTRY_SELECTED;\n\tif (valuePtr != NULL) {\n\t    if (mePtr->onValuePtr != NULL) {\n\t\tconst char *value = Tcl_GetString(valuePtr);\n\t\tconst char *onValue = Tcl_GetString(mePtr->onValuePtr);\n\n\t\tif (strcmp(value, onValue) == 0) {\n\t\t    mePtr->entryFlags |= ENTRY_SELECTED;\n\t\t}\n\t    }\n\t} else {\n\t    if (mePtr->namePtr != NULL) {\n\t\tTcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL,\n\t\t\t(mePtr->type == CHECK_BUTTON_ENTRY)\n\t\t\t? mePtr->offValuePtr : Tcl_NewObj(), TCL_GLOBAL_ONLY);\n\t    }\n\t}\n\tif (mePtr->namePtr != NULL) {\n\t    name = Tcl_GetString(mePtr->namePtr);\n\t    Tcl_TraceVar2(menuPtr->interp, name,\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    MenuVarProc, mePtr);\n\t}\n    }\n\n    if (TkpConfigureMenuEntry(mePtr) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureMenuEntry --\n *\n *\tThis function is called to process an objv/objc list in order to\n *\tconfigure (or reconfigure) one entry in a menu.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information such as label and accelerator get set for\n *\tmePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureMenuEntry(\n    TkMenuEntry *mePtr,/* Information about menu entry; may or may\n\t\t\t\t * not already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    TkMenu *menuPtr = mePtr->menuPtr;\n    Tk_SavedOptions errorStruct;\n    int result;\n\n    /*\n     * If this entry is a check button or radio button, then remove its old\n     * trace function.\n     */\n\n    if ((mePtr->namePtr != NULL)\n\t    && ((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    || (mePtr->type == RADIO_BUTTON_ENTRY))) {\n\tconst char *name = Tcl_GetString(mePtr->namePtr);\n\n\tTcl_UntraceVar2(menuPtr->interp, name, NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuVarProc, mePtr);\n    }\n\n    result = TCL_OK;\n    if (menuPtr->tkwin != NULL) {\n\tif (Tk_SetOptions(menuPtr->interp, mePtr,\n\t\tmePtr->optionTable, objc, objv, menuPtr->tkwin,\n\t\t&errorStruct, NULL) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * If we are adding a cascade, ensure that the change will not destroy\n\t * the tree structure of the menu hierarchy.  Creating a loop will\n\t * cause a crash.  See ticket [7f67bb4054].\n\t */\n\n\tif ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {\n\t    const char *cascadeName = Tcl_GetString(mePtr->namePtr);\n\n\t    if (CheckForLoops(menuPtr->interp, cascadeName, menuPtr)) {\n\t\tTcl_SetObjResult(menuPtr->interp, Tcl_ObjPrintf(\n\t\t\t\"cannot add recursive cascade menu \\\"%s\\\"\",\n\t\t\tcascadeName));\n\t\tTcl_SetErrorCode(menuPtr->interp, \"TK\", \"MENU\", \"RECURSION\",\n\t\t\t(char *) NULL);\n\t\tresult = TCL_ERROR;\n\t    }\n\t}\n\n\tif (result == TCL_OK) {\n\t    result = PostProcessEntry(mePtr);\n\t}\n\tif (result != TCL_OK) {\n\t    Tk_RestoreSavedOptions(&errorStruct);\n\t    PostProcessEntry(mePtr);\n\t}\n\tTk_FreeSavedOptions(&errorStruct);\n    }\n\n    TkEventuallyRecomputeMenu(menuPtr);\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckForLoops0, CheckForLoops --\n *\n *\tChecks for loops in use of -menu option in cascades.\n *\n * Results:\n *\tTrue when loop detected.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCheckForLoops0(\n    Tcl_Interp *interp,\t\t/* Used for lookups. */\n    const char *pathName,\t/* Current menu to look for cascade. */\n    const char *name)\t\t/* Value of -menu option to check. */\n{\n    TkMenuReferences *menuRefPtr;\n\n    menuRefPtr = TkFindMenuReferences(interp, pathName);\n    if (menuRefPtr == NULL) {\n\treturn 0;\n    }\n    if (menuRefPtr->menuPtr != NULL) {\n\tTkMenu *menuPtr = menuRefPtr->menuPtr;\n\tconst char *parentName;\n\n\tif (menuPtr->tkwin != NULL) {\n\t    parentName = Tk_PathName(menuPtr->tkwin);\n\t    if (strcmp(name, parentName) == 0) {\n\t\treturn 1;\n\t    }\n\t    if ((menuPtr->mainMenuPtr != menuPtr) &&\n\t\t    (menuPtr->mainMenuPtr->tkwin != NULL)) {\n\t\tparentName = Tk_PathName(menuPtr->mainMenuPtr->tkwin);\n\t\tif (strcmp(name, parentName) == 0) {\n\t\t    return 1;\n\t\t}\n\t    }\n\t}\n    }\n    if (menuRefPtr->parentEntryPtr != NULL) {\n\tTkMenuEntry *cascadePtr = menuRefPtr->parentEntryPtr;\n\tconst char *cascadeName;\n\n\twhile (cascadePtr != NULL) {\n\t    cascadeName = Tcl_GetString(cascadePtr->namePtr);\n\t    if ((strcmp(pathName, cascadeName) != 0) &&\n\t\t    CheckForLoops0(interp, cascadeName, name)) {\n\t\treturn 1;\n\t    }\n\t    if ((cascadePtr->menuPtr != NULL) &&\n\t\t    (cascadePtr->menuPtr->tkwin != NULL)) {\n\t\tcascadeName = Tk_PathName(cascadePtr->menuPtr->tkwin);\n\t\tif ((strcmp(pathName, cascadeName) != 0) &&\n\t\t\tCheckForLoops0(interp, cascadeName, name)) {\n\t\t    return 1;\n\t\t}\n\t    }\n\t    if (cascadePtr->menuPtr != NULL) {\n\t\tTkMenu *mainMenuPtr = cascadePtr->menuPtr->mainMenuPtr;\n\n\t\tif ((mainMenuPtr != cascadePtr->menuPtr) &&\n\t\t\t(mainMenuPtr->tkwin != NULL)) {\n\t\t    cascadeName = Tk_PathName(mainMenuPtr->tkwin);\n\t\t    if ((strcmp(pathName, cascadeName) != 0) &&\n\t\t\t    CheckForLoops0(interp, cascadeName, name)) {\n\t\t\treturn 1;\n\t\t    }\n\t\t}\n\t    }\n\n\t    cascadePtr = cascadePtr->nextCascadePtr;\n\t}\n    }\n    return 0;\n}\n\f\nstatic int\nCheckForLoops(\n    Tcl_Interp *interp,\t\t/* Used for lookups. */\n    const char *name,\t\t/* Value of -menu option to check. */\n    TkMenu *menuPtr)\t\t/* Information about menu. */\n{\n    const char *pathName = NULL;\n\n    if (menuPtr->tkwin != NULL) {\n\tpathName = Tk_PathName(menuPtr->tkwin);\n\tif (strcmp(name, pathName) == 0) {\n\t    return 1;\n\t}\n    }\n    if (pathName != NULL) {\nif (CheckForLoops0(interp, pathName, name)) {\n\t    return 1;\n\t}\n    }\n    pathName = NULL;\n    if ((menuPtr->mainMenuPtr != menuPtr) &&\n\t    (menuPtr->mainMenuPtr->tkwin != NULL)) {\n\tpathName = Tk_PathName(menuPtr->mainMenuPtr->tkwin);\n\tif (strcmp(name, pathName) == 0) {\n\t    return 1;\n\t}\n    }\n    if (pathName != NULL) {\n\tif (CheckForLoops0(interp, pathName, name)) {\n\t    return 1;\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureMenuCloneEntries --\n *\n *\tCalls ConfigureMenuEntry for each menu in the clone chain.\n *\n * Results:\n *\tThe return value is a standard Tcl result.\n *\n * Side effects:\n *\tConfiguration information such as label and accelerator get set for\n *\tmePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureMenuCloneEntries(\n    TkMenu *menuPtr,\t\t/* Information about whole menu. */\n    int index,\t\t\t/* Index of mePtr within menuPtr's entries. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    TkMenuEntry *mePtr;\n    TkMenu *menuListPtr;\n    int cascadeEntryChanged = 0;\n    TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL;\n    Tcl_Obj *oldCascadePtr = NULL;\n    const char *newCascadeName;\n\n    /*\n     * Cascades are kind of tricky here. This is special case #3 in the\n     * comment at the top of this file. Basically, if a menu is the main\n     * menu of a clone chain, and has an entry with a cascade menu, the clones\n     * of the menu will point to clones of the cascade menu. We have to\n     * destroy the clones of the cascades, clone the new cascade menu, and\n     * configure the entry to point to the new clone.\n     */\n\n    mePtr = menuPtr->mainMenuPtr->entries[index];\n    if (mePtr->type == CASCADE_ENTRY) {\n\toldCascadePtr = mePtr->namePtr;\n\tif (oldCascadePtr != NULL) {\n\t    Tcl_IncrRefCount(oldCascadePtr);\n\t}\n    }\n\n    if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (mePtr->type == CASCADE_ENTRY) {\n\tconst char *oldCascadeName;\n\n\tif (mePtr->namePtr != NULL) {\n\t    newCascadeName = Tcl_GetString(mePtr->namePtr);\n\t} else {\n\t    newCascadeName = NULL;\n\t}\n\n\tif ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) {\n\t    cascadeEntryChanged = 0;\n\t} else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL))\n\t\t|| ((oldCascadePtr != NULL)\n\t\t&& (mePtr->namePtr == NULL))) {\n\t    cascadeEntryChanged = 1;\n\t} else {\n\t    oldCascadeName = Tcl_GetString(oldCascadePtr);\n\t    cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName)\n\t\t    != 0);\n\t}\n\tif (oldCascadePtr != NULL) {\n\t    Tcl_DecrRefCount(oldCascadePtr);\n\t}\n    }\n\n    if (cascadeEntryChanged) {\n\tif (mePtr->namePtr != NULL) {\n\t    newCascadeName = Tcl_GetString(mePtr->namePtr);\n\t    cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,\n\t\t    newCascadeName);\n\t}\n    }\n\n    for (menuListPtr = menuPtr->mainMenuPtr->nextInstancePtr;\n\t    menuListPtr != NULL;\n\t    menuListPtr = menuListPtr->nextInstancePtr) {\n\n\tmePtr = menuListPtr->entries[index];\n\n\tif (cascadeEntryChanged && (mePtr->namePtr != NULL)) {\n\t    oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,\n\t\t    mePtr->namePtr);\n\n\t    if ((oldCascadeMenuRefPtr != NULL)\n\t\t    && (oldCascadeMenuRefPtr->menuPtr != NULL)) {\n\t\tRecursivelyDeleteMenu(oldCascadeMenuRefPtr->menuPtr);\n\t    }\n\t}\n\n\tif (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (cascadeEntryChanged && (mePtr->namePtr != NULL)) {\n\t    if (cascadeMenuRefPtr && cascadeMenuRefPtr->menuPtr != NULL) {\n\t\tTcl_Obj *newObjv[2];\n\t\tTcl_Obj *newCloneNamePtr;\n\t\tTcl_Obj *pathNamePtr = Tcl_NewStringObj(\n\t\t\tTk_PathName(menuListPtr->tkwin), TCL_INDEX_NONE);\n\t\tTcl_Obj *normalPtr = Tcl_NewStringObj(\"normal\", TCL_INDEX_NONE);\n\t\tTcl_Obj *menuObjPtr = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\n\t\tTcl_IncrRefCount(pathNamePtr);\n\t\tnewCloneNamePtr = TkNewMenuName(menuPtr->interp,\n\t\t\tpathNamePtr,\n\t\t\tcascadeMenuRefPtr->menuPtr);\n\t\tTcl_IncrRefCount(newCloneNamePtr);\n\t\tTcl_IncrRefCount(normalPtr);\n\t\tCloneMenu(cascadeMenuRefPtr->menuPtr, newCloneNamePtr,\n\t\t\tnormalPtr);\n\n\t\tnewObjv[0] = menuObjPtr;\n\t\tnewObjv[1] = newCloneNamePtr;\n\t\tTcl_IncrRefCount(menuObjPtr);\n\t\tConfigureMenuEntry(mePtr, 2, newObjv);\n\t\tTcl_DecrRefCount(newCloneNamePtr);\n\t\tTcl_DecrRefCount(pathNamePtr);\n\t\tTcl_DecrRefCount(normalPtr);\n\t\tTcl_DecrRefCount(menuObjPtr);\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetMenuIndex --\n *\n *\tParse a textual index into a menu and return the numerical index of\n *\tthe indicated entry.\n *\n * Results:\n *\tA standard Tcl result. If all went well, then *indexPtr is filled in\n *\twith the entry index corresponding to string (ranges from -1 to the\n *\tnumber of entries in the menu minus one). Otherwise an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nGetMenuIndex(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    TkMenu *menuPtr,\t\t/* Menu for which the index is being\n\t\t\t\t * specified. */\n    Tcl_Obj *objPtr,\t\t/* Specification of an entry in menu. See\n\t\t\t\t * manual entry for valid .*/\n    int lastOK,\t\t\t/* Non-zero means its OK to return index just\n\t\t\t\t * *after* last entry. */\n    Tcl_Size *indexPtr)\t\t/* Where to store converted index. */\n{\n    Tcl_Size i;\n    const char *string;\n    Tcl_HashEntry *entryPtr;\n\n    if (TkGetIntForIndex(objPtr, menuPtr->numEntries - 1, lastOK, indexPtr) == TCL_OK) {\n\t/* TCL_INDEX_NONE is only accepted if it does not result from a negative number */\n\tif (*indexPtr >= 0 || Tcl_GetString(objPtr)[0] != '-') {\n\t    if (*indexPtr >= menuPtr->numEntries) {\n\t\t*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);\n\t    }\n\t    return TCL_OK;\n\t}\n    }\n\n    string = Tcl_GetString(objPtr);\n\n    if ((string[0] == 'a') && (strcmp(string, \"active\") == 0)) {\n\t*indexPtr = menuPtr->active;\n\treturn TCL_OK;\n    }\n\n    if ((string[0] == 'l') && (strcmp(string, \"last\") == 0)) {\n\t*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);\n\treturn TCL_OK;\n    }\n\n    if (string[0] == 0) {\n\t*indexPtr = TCL_INDEX_NONE;\n\treturn TCL_OK;\n    }\n#if !defined(TK_NO_DEPRECATED)\n    if ((string[0] == 'n') && (strcmp(string, \"none\") == 0)) {\n\t*indexPtr = TCL_INDEX_NONE;\n\treturn TCL_OK;\n    }\n#endif\n\n    if (string[0] == '@') {\n\tif (GetIndexFromCoords(interp, menuPtr, string, indexPtr)\n\t\t== TCL_OK) {\n\t    return TCL_OK;\n\t}\n    }\n\n    entryPtr = Tcl_FindHashEntry(&menuPtr->items, string);\n    if (entryPtr) {\n\tTkMenuEntry *mePtr = (TkMenuEntry *)Tcl_GetHashValue(entryPtr);\n\t*indexPtr = mePtr->index;\n\treturn TCL_OK;\n    }\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tTcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;\n\tconst char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);\n\n\tif ((label != NULL) && (Tcl_StringCaseMatch(label, string, 0))) {\n\t    *indexPtr = i;\n\t    return TCL_OK;\n\t}\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad menu entry index \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"MENU\", \"INDEX\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n    Tk_Window tkwin = menuPtr->tkwin;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\t/*\n\t * Note: it may be desirable to NULL out the tkwin field of menuPtr\n\t * here:\n\t * menuPtr->tkwin = NULL;\n\t */\n\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuNewEntry --\n *\n *\tThis function allocates and initializes a new menu entry.\n *\n * Results:\n *\tThe return value is a pointer to a new menu entry structure, which has\n *\tbeen malloc-ed, initialized, and entered into the entry array for the\n *\tmenu.\n *\n * Side effects:\n *\tStorage gets allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkMenuEntry *\nMenuNewEntry(\n    TkMenu *menuPtr,\t\t/* Menu that will hold the new entry. */\n    Tcl_Size index,\t\t\t/* Where in the menu the new entry is to\n\t\t\t\t * go. */\n    int type)\t\t\t/* The type of the new entry. */\n{\n    TkMenuEntry *mePtr;\n    TkMenuEntry **newEntries;\n    Tcl_Size i;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Create a new array of entries with an empty slot for the new entry.\n     */\n\n    newEntries = (TkMenuEntry **)Tcl_Alloc((menuPtr->numEntries+1) * sizeof(TkMenuEntry *));\n    for (i = 0; i < index; i++) {\n\tnewEntries[i] = menuPtr->entries[i];\n    }\n    for (; i < menuPtr->numEntries; i++) {\n\tnewEntries[i+1] = menuPtr->entries[i];\n\tnewEntries[i+1]->index = i + 1;\n    }\n    if (menuPtr->numEntries != 0) {\n\tTcl_Free(menuPtr->entries);\n    }\n    menuPtr->entries = newEntries;\n    menuPtr->numEntries++;\n    mePtr = (TkMenuEntry *)Tcl_Alloc(sizeof(TkMenuEntry));\n    menuPtr->entries[index] = mePtr;\n    mePtr->type = type;\n    mePtr->optionTable = tsdPtr->entryOptionTables[type];\n    mePtr->menuPtr = menuPtr;\n    mePtr->labelPtr = NULL;\n    mePtr->labelLength = 0;\n    mePtr->underline = INT_MIN;\n    mePtr->bitmapPtr = NULL;\n    mePtr->imagePtr = NULL;\n    mePtr->image = NULL;\n    mePtr->selectImagePtr = NULL;\n    mePtr->selectImage = NULL;\n    mePtr->accelPtr = NULL;\n    mePtr->accelLength = 0;\n    mePtr->state = ENTRY_DISABLED;\n    mePtr->borderPtr = NULL;\n    mePtr->fgPtr = NULL;\n    mePtr->activeBorderPtr = NULL;\n    mePtr->activeFgPtr = NULL;\n    mePtr->fontPtr = NULL;\n    mePtr->indicatorOn = false;\n    mePtr->indicatorFgPtr = NULL;\n    mePtr->columnBreak = false;\n    mePtr->hideMargin = false;\n    mePtr->commandPtr = NULL;\n    mePtr->namePtr = NULL;\n    mePtr->childMenuRefPtr = NULL;\n    mePtr->onValuePtr = NULL;\n    mePtr->offValuePtr = NULL;\n    mePtr->entryFlags = 0;\n    mePtr->index = index;\n    mePtr->nextCascadePtr = NULL;\n    if (Tk_InitOptions(menuPtr->interp, mePtr,\n\t    mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {\n\tTcl_Free(mePtr);\n\treturn NULL;\n    }\n    mePtr->entryPtr = NULL;\n    TkMenuInitializeEntryDrawingFields(mePtr);\n    if (TkpMenuNewEntry(mePtr) != TCL_OK) {\n\tTk_FreeConfigOptions(mePtr, mePtr->optionTable,\n\t\tmenuPtr->tkwin);\n\tTcl_Free(mePtr);\n\treturn NULL;\n    }\n\n    return mePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuAddOrInsert --\n *\n *\tThis function does all of the work of the \"add\" and \"insert\" widget\n *\tcommands, allowing the code for these to be shared.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tA new menu entry is created in menuPtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMenuAddOrInsert(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkMenu *menuPtr,\t\t/* Widget in which to create new entry. */\n    Tcl_Obj *indexPtr,\t\t/* Object describing index at which to insert.\n\t\t\t\t * NULL means insert at end. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments to command: first arg is type of\n\t\t\t\t * entry, others are config options. */\n{\n    int type;\n    Tcl_Size index;\n    TkMenuEntry *mePtr;\n    TkMenu *menuListPtr;\n    Tcl_HashEntry *entryPtr;\n    Tcl_Obj *idPtr = NULL;\n    int isNew;\n    int offs;\n\n    if (indexPtr != NULL) {\n\tif (GetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tindex = menuPtr->numEntries;\n    }\n    if (index < 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad menu entry index \\\"%s\\\"\", Tcl_GetString(indexPtr)));\n\tTcl_SetErrorCode(interp, \"TK\", \"MENU\", \"INDEX\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (menuPtr->tearoff && (index == 0)) {\n\tindex = 1;\n    }\n\n    /*\n     * Figure out the type of the new entry.\n     */\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[0], menuEntryTypeStrings,\n\t    sizeof(char *), \"menu entry type\", 0, &type) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    offs = 1;\n\n    /*\n     * Check for a user supplied id\n     */\n\n    if (objc % 2 == 0) {\n\tidPtr = objv[offs];\n\tif (Tcl_FindHashEntry(&menuPtr->items, Tcl_GetString(idPtr))) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"entry \\\"%s\\\" already exists\", Tcl_GetString(idPtr)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MENU\", \"ENTRY_EXISTS\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\toffs++;\n    }\n\n    /*\n     * Now we have to add an entry for every instance related to this menu.\n     */\n    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;\n\t    menuListPtr = menuListPtr->nextInstancePtr) {\n\tTkMenu *errorMenuPtr;\n\tint i;\n\tmePtr = MenuNewEntry(menuListPtr, index, type);\n\tif (mePtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (ConfigureMenuEntry(mePtr, objc - offs, objv + offs) != TCL_OK) {\n\t    for (errorMenuPtr = menuPtr->mainMenuPtr;\n\t\t    errorMenuPtr != NULL;\n\t\t    errorMenuPtr = errorMenuPtr->nextInstancePtr) {\n\t\tTcl_EventuallyFree(errorMenuPtr->entries[index],\n\t\t\tDestroyMenuEntry);\n\t\tfor (i = index; i < errorMenuPtr->numEntries - 1; i++) {\n\t\t    errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1];\n\t\t    errorMenuPtr->entries[i]->index = i;\n\t\t}\n\t\tif (--errorMenuPtr->numEntries == 0) {\n\t\t    Tcl_Free(errorMenuPtr->entries);\n\t\t    errorMenuPtr->entries = NULL;\n\t\t}\n\t\tif (errorMenuPtr == menuListPtr) {\n\t\t    break;\n\t\t}\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\tif (idPtr == NULL) {\n\t    char idbuf[16];\n\t    /* Generate an id for the new entry on the main menu */\n\t    do {\n\t\tsnprintf(idbuf, sizeof(idbuf), \"e%03X\", ++menuPtr->serial);\n\t\tentryPtr = Tcl_CreateHashEntry(\n\t\t\t&menuListPtr->items, idbuf, &isNew);\n\t    } while (!isNew);\n\t    idPtr = Tcl_NewStringObj(idbuf, TCL_INDEX_NONE);\n\t} else {\n\t    /* Reuse the specified or previously generated id on all clones */\n\t    entryPtr = Tcl_CreateHashEntry(\n\t\t    &menuListPtr->items, Tcl_GetString(idPtr), &isNew);\n\t}\n\tTcl_SetHashValue(entryPtr, mePtr);\n\tmePtr->entryPtr = entryPtr;\n\n\t/*\n\t * If a menu has cascades, then every instance of the menu has to have\n\t * its own parallel cascade structure. So adding an entry to a menu\n\t * with clones means that the menu that the entry points to has to be\n\t * cloned for every clone the main menu has. This is special case #2\n\t * in the comment at the top of this file.\n\t */\n\n\tif ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {\n\t    if ((mePtr->namePtr != NULL)\n\t\t    && (mePtr->childMenuRefPtr != NULL)\n\t\t    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {\n\t\tTkMenu *cascadeMenuPtr =\n\t\t\tmePtr->childMenuRefPtr->menuPtr->mainMenuPtr;\n\t\tTcl_Obj *newCascadePtr, *newObjv[2];\n\t\tTcl_Obj *menuNamePtr = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\t\tTcl_Obj *windowNamePtr =\n\t\t\tTcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), TCL_INDEX_NONE);\n\t\tTcl_Obj *normalPtr = Tcl_NewStringObj(\"normal\", TCL_INDEX_NONE);\n\t\tTkMenuReferences *menuRefPtr;\n\n\t\tTcl_IncrRefCount(windowNamePtr);\n\t\tnewCascadePtr = TkNewMenuName(menuListPtr->interp,\n\t\t\twindowNamePtr, cascadeMenuPtr);\n\t\tTcl_IncrRefCount(newCascadePtr);\n\t\tTcl_IncrRefCount(normalPtr);\n\t\tCloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr);\n\n\t\tmenuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp,\n\t\t\tnewCascadePtr);\n\t\tif (menuRefPtr == NULL) {\n\t\t    Tcl_Panic(\"CloneMenu failed inside of MenuAddOrInsert\");\n\t\t}\n\t\tnewObjv[0] = menuNamePtr;\n\t\tnewObjv[1] = newCascadePtr;\n\t\tTcl_IncrRefCount(menuNamePtr);\n\t\tTcl_IncrRefCount(newCascadePtr);\n\t\tConfigureMenuEntry(mePtr, 2, newObjv);\n\t\tTcl_DecrRefCount(newCascadePtr);\n\t\tTcl_DecrRefCount(menuNamePtr);\n\t\tTcl_DecrRefCount(windowNamePtr);\n\t\tTcl_DecrRefCount(normalPtr);\n\t    }\n\t}\n    }\n\n    Tcl_SetObjResult(interp, idPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuVarProc --\n *\n *\tThis function is invoked when someone changes the state variable\n *\tassociated with a radiobutton or checkbutton menu entry. The entry's\n *\tselected state is set to match the value of the variable.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe menu entry may become selected or deselected.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nMenuVarProc(\n    void *clientData,\t/* Information about menu entry. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t/* First part of variable's name. */\n    TCL_UNUSED(const char *),\t/* Second part of variable's name. */\n    int flags)\t\t\t/* Describes what just happened. */\n{\n    TkMenuEntry *mePtr = (TkMenuEntry *)clientData;\n    TkMenu *menuPtr;\n    const char *value;\n    const char *name, *onValue;\n\n    if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) {\n\t/*\n\t * Do nothing if the interpreter is going away or we have\n\t * no variable name.\n\t */\n\n\treturn NULL;\n    }\n\n    menuPtr = mePtr->menuPtr;\n\n    if (menuPtr->menuFlags & MENU_DELETION_PENDING) {\n\treturn NULL;\n    }\n\n    name = Tcl_GetString(mePtr->namePtr);\n\n    /*\n     * If the variable is being unset, then re-establish the trace.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tvoid *probe = NULL;\n\tmePtr->entryFlags &= ~ENTRY_SELECTED;\n\n\tdo {\n\t\tprobe = Tcl_VarTraceInfo(interp, name,\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tMenuVarProc, probe);\n\t\tif (probe == (void *)mePtr) {\n\t\t    break;\n\t\t}\n\t} while (probe);\n\tif (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * namePtr, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t}\n\tTcl_TraceVar2(interp, name, NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuVarProc, clientData);\n\tTkpConfigureMenuEntry(mePtr);\n\tTkEventuallyRedrawMenu(menuPtr, NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Use the value of the variable to update the selected status of the menu\n     * entry.\n     */\n\n    value = Tcl_GetVar2(interp, name, NULL, TCL_GLOBAL_ONLY);\n    if (value == NULL) {\n\tvalue = \"\";\n    }\n    if (mePtr->onValuePtr != NULL) {\n\tonValue = Tcl_GetString(mePtr->onValuePtr);\n\tif (strcmp(value, onValue) == 0) {\n\t    if (mePtr->entryFlags & ENTRY_SELECTED) {\n\t\treturn NULL;\n\t    }\n\t    mePtr->entryFlags |= ENTRY_SELECTED;\n\t} else if (mePtr->entryFlags & ENTRY_SELECTED) {\n\t    mePtr->entryFlags &= ~ENTRY_SELECTED;\n\t} else {\n\t    return NULL;\n\t}\n    } else {\n\treturn NULL;\n    }\n    TkpConfigureMenuEntry(mePtr);\n    TkEventuallyRedrawMenu(menuPtr, mePtr);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkActivateMenuEntry --\n *\n *\tThis function is invoked to make a particular menu entry the active\n *\tone, deactivating any other entry that might currently be active.\n *\n * Results:\n *\tThe return value is a standard Tcl result (errors can occur while\n *\tposting and unposting submenus).\n *\n * Side effects:\n *\tMenu entries get redisplayed, and the active entry changes. Submenus\n *\tmay get posted and unposted.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkActivateMenuEntry(\n    TkMenu *menuPtr,\t/* Menu in which to activate. */\n    Tcl_Size index)\t\t\t/* Index of entry to activate, or\n\t\t\t\t * TCL_INDEX_NONE to deactivate all entries. */\n{\n    TkMenuEntry *mePtr;\n    int result = TCL_OK;\n\n    if (menuPtr->active >= 0) {\n\tmePtr = menuPtr->entries[menuPtr->active];\n\n\t/*\n\t * Don't change the state unless it's currently active (state might\n\t * already have been changed to disabled).\n\t */\n\n\tif (mePtr->state == ENTRY_ACTIVE) {\n\t    mePtr->state = ENTRY_NORMAL;\n\t}\n\tTkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);\n    }\n    menuPtr->active = index;\n    if (index >= 0) {\n\tmePtr = menuPtr->entries[index];\n\tmePtr->state = ENTRY_ACTIVE;\n\tTkEventuallyRedrawMenu(menuPtr, mePtr);\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPostCommand --\n *\n *\tExecute the postcommand for the given menu.\n *\n * Results:\n *\tThe return value is a standard Tcl result (errors can occur while the\n *\tpostcommands are being processed).\n *\n * Side effects:\n *\tSince commands can get executed while this routine is being executed,\n *\tthe entire world can change.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPostCommand(\n    TkMenu *menuPtr)\n{\n    int result;\n\n    /*\n     * If there is a command for the menu, execute it. This may change the\n     * size of the menu, so be sure to recompute the menu's geometry if\n     * needed.\n     */\n\n    if (menuPtr->postCommandPtr != NULL) {\n\tTcl_Obj *postCommandPtr = menuPtr->postCommandPtr;\n\n\tTcl_IncrRefCount(postCommandPtr);\n\tresult = Tcl_EvalObjEx(menuPtr->interp, postCommandPtr,\n\t\tTCL_EVAL_GLOBAL);\n\tTcl_DecrRefCount(postCommandPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n\tTkRecomputeMenu(menuPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CloneMenu --\n *\n *\tCreates a child copy of the menu. It will be inserted into the menu's\n *\tinstance chain. All attributes and entry attributes will be\n *\tduplicated.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tAllocates storage. After the menu is created, any configuration done\n *\twith this menu or any related one will be reflected in all of them.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCloneMenu(\n    TkMenu *menuPtr,\t\t/* The menu we are going to clone. */\n    Tcl_Obj *newMenuNamePtr,\t/* The name to give the new menu. */\n    Tcl_Obj *newMenuTypePtr)\t/* What kind of menu is this, a normal menu a\n\t\t\t\t * menubar, or a tearoff? */\n{\n    int returnResult;\n    int menuType;\n    Tcl_Size i;\n    TkMenuReferences *menuRefPtr;\n    Tcl_Obj *menuDupCommandArray[4];\n\n    if (newMenuTypePtr == NULL) {\n\tmenuType = MAIN_MENU;\n    } else {\n\tif (Tcl_GetIndexFromObjStruct(menuPtr->interp, newMenuTypePtr,\n\t\tmenuTypeStrings, sizeof(char *), \"menu type\", 0, &menuType) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    menuDupCommandArray[0] = Tcl_NewStringObj(\"tk::MenuDup\", TCL_INDEX_NONE);\n    menuDupCommandArray[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), TCL_INDEX_NONE);\n    menuDupCommandArray[2] = newMenuNamePtr;\n    if (newMenuTypePtr == NULL) {\n\tmenuDupCommandArray[3] = Tcl_NewStringObj(\"normal\", TCL_INDEX_NONE);\n    } else {\n\tmenuDupCommandArray[3] = newMenuTypePtr;\n    }\n    for (i = 0; i < 4; i++) {\n\tTcl_IncrRefCount(menuDupCommandArray[i]);\n    }\n    Tcl_Preserve(menuPtr);\n    returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, 0);\n    for (i = 0; i < 4; i++) {\n\tTcl_DecrRefCount(menuDupCommandArray[i]);\n    }\n\n    /*\n     * Make sure the tcl command actually created the clone.\n     */\n\n    if ((returnResult == TCL_OK) &&\n\t    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,\n\t    newMenuNamePtr)) != NULL)\n\t    && (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) {\n\tTkMenu *newMenuPtr = menuRefPtr->menuPtr;\n\tTcl_Obj *newObjv[3];\n\tTcl_Size numElements;\n\n\t/*\n\t * Now put this newly created menu into the parent menu's instance\n\t * chain.\n\t */\n\n\tif (menuPtr->nextInstancePtr == NULL) {\n\t    menuPtr->nextInstancePtr = newMenuPtr;\n\t    newMenuPtr->mainMenuPtr = menuPtr->mainMenuPtr;\n\t} else {\n\t    TkMenu *mainMenuPtr;\n\n\t    mainMenuPtr = menuPtr->mainMenuPtr;\n\t    newMenuPtr->nextInstancePtr = mainMenuPtr->nextInstancePtr;\n\t    mainMenuPtr->nextInstancePtr = newMenuPtr;\n\t    newMenuPtr->mainMenuPtr = mainMenuPtr;\n\t}\n\n\t/*\n\t * Add the main menu's window to the bind tags for this window after\n\t * this window's tag. This is so the user can bind to either this\n\t * clone (which may not be easy to do) or the entire menu clone\n\t * structure.\n\t */\n\n\tnewObjv[0] = Tcl_NewStringObj(\"bindtags\", TCL_INDEX_NONE);\n\tnewObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), TCL_INDEX_NONE);\n\tTcl_IncrRefCount(newObjv[0]);\n\tTcl_IncrRefCount(newObjv[1]);\n\tif (Tk_BindtagsObjCmd(newMenuPtr->tkwin, newMenuPtr->interp, 2,\n\t\tnewObjv) == TCL_OK) {\n\t    const char *windowName;\n\t    Tcl_Obj *bindingsPtr =\n\t\t    Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp));\n\t    Tcl_Obj *elementPtr;\n\n\t    Tcl_IncrRefCount(bindingsPtr);\n\t    Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements);\n\t    for (i = 0; i < numElements; i++) {\n\t\tTcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i,\n\t\t\t&elementPtr);\n\t\twindowName = Tcl_GetString(elementPtr);\n\t\tif (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin))\n\t\t\t== 0) {\n\t\t    Tcl_Obj *newElementPtr = Tcl_NewStringObj(\n\t\t\t    Tk_PathName(newMenuPtr->mainMenuPtr->tkwin), TCL_INDEX_NONE);\n\n\t\t    /*\n\t\t     * The newElementPtr will have its refCount incremented\n\t\t     * here, so we don't need to worry about it any more.\n\t\t     */\n\n\t\t    Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,\n\t\t\t    i + 1, 0, 1, &newElementPtr);\n\t\t    newObjv[2] = bindingsPtr;\n\t\t    Tk_BindtagsObjCmd(newMenuPtr->tkwin, menuPtr->interp, 3,\n\t\t\t    newObjv);\n\t\t    break;\n\t\t}\n\t    }\n\t    Tcl_DecrRefCount(bindingsPtr);\n\t}\n\tTcl_DecrRefCount(newObjv[0]);\n\tTcl_DecrRefCount(newObjv[1]);\n\tTcl_ResetResult(menuPtr->interp);\n\n\t/*\n\t * Clone all of the cascade menus that this menu points to.\n\t */\n\n\tfor (i = 0; i < menuPtr->numEntries; i++) {\n\t    TkMenuReferences *cascadeRefPtr;\n\t    TkMenu *oldCascadePtr;\n\n\t    if ((menuPtr->entries[i]->type == CASCADE_ENTRY)\n\t\t&& (menuPtr->entries[i]->namePtr != NULL)) {\n\t\tcascadeRefPtr =\n\t\t\tTkFindMenuReferencesObj(menuPtr->interp,\n\t\t\tmenuPtr->entries[i]->namePtr);\n\t\tif ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) {\n\t\t    Tcl_Obj *windowNamePtr =\n\t\t\t    Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin),\n\t\t\t    -1);\n\t\t    Tcl_Obj *newCascadePtr;\n\n\t\t    oldCascadePtr = cascadeRefPtr->menuPtr;\n\n\t\t    Tcl_IncrRefCount(windowNamePtr);\n\t\t    newCascadePtr = TkNewMenuName(menuPtr->interp,\n\t\t\t    windowNamePtr, oldCascadePtr);\n\t\t    Tcl_IncrRefCount(newCascadePtr);\n\t\t    CloneMenu(oldCascadePtr, newCascadePtr, NULL);\n\n\t\t    newObjv[0] = Tcl_NewStringObj(\"-menu\", TCL_INDEX_NONE);\n\t\t    newObjv[1] = newCascadePtr;\n\t\t    Tcl_IncrRefCount(newObjv[0]);\n\t\t    ConfigureMenuEntry(newMenuPtr->entries[i], 2, newObjv);\n\t\t    Tcl_DecrRefCount(newObjv[0]);\n\t\t    Tcl_DecrRefCount(newCascadePtr);\n\t\t    Tcl_DecrRefCount(windowNamePtr);\n\t\t}\n\t    }\n\t}\n\n\treturnResult = TCL_OK;\n    } else {\n\treturnResult = TCL_ERROR;\n    }\n    Tcl_Release(menuPtr);\n    return returnResult;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuDoXPosition --\n *\n *\tGiven arguments from an option command line, returns the X position.\n *\n * Results:\n *\tReturns TCL_OK or TCL_Error\n *\n * Side effects:\n *\txPosition is set to the X-position of the menu entry.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMenuDoXPosition(\n    Tcl_Interp *interp,\n    TkMenu *menuPtr,\n    Tcl_Obj *objPtr)\n{\n    Tcl_Size index;\n\n    TkRecomputeMenu(menuPtr);\n    if (GetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_ResetResult(interp);\n    if (index < 0) {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(0));\n    } else {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->x));\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuDoYPosition --\n *\n *\tGiven arguments from an option command line, returns the Y position.\n *\n * Results:\n *\tReturns TCL_OK or TCL_Error\n *\n * Side effects:\n *\tyPosition is set to the Y-position of the menu entry.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMenuDoYPosition(\n    Tcl_Interp *interp,\n    TkMenu *menuPtr,\n    Tcl_Obj *objPtr)\n{\n    Tcl_Size index;\n\n    TkRecomputeMenu(menuPtr);\n    if (GetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {\n\tgoto error;\n    }\n    Tcl_ResetResult(interp);\n    if (index < 0) {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(0));\n    } else {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->y));\n    }\n\n    return TCL_OK;\n\n  error:\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetIndexFromCoords --\n *\n *\tGiven a string of the form \"@integer\", return the menu item\n *\tcorresponding to the provided y-coordinate in the menu window.\n *\n * Results:\n *\tIf int is a valid number, *indexPtr will be the number of the\n *\tmenuentry that is the correct height. If int is invalid, *indexPtr\n *\twill be unchanged. Returns appropriate Tcl error number.\n *\n * Side effects:\n *\tIf int is invalid, interp's result will be set to NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nGetIndexFromCoords(\n    Tcl_Interp *interp,\t\t/* Interpreter of menu. */\n    TkMenu *menuPtr,\t\t/* The menu we are searching. */\n    const char *string,\t\t/* The @string we are parsing. */\n    Tcl_Size *indexPtr)\t\t/* The index of the item that matches. */\n{\n    int x, y;\n    Tcl_Size i;\n    const char *p;\n    const char *rest;\n    int x2, borderwidth, max;\n\n    TkRecomputeMenu(menuPtr);\n    p = string + 1;\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t    menuPtr->borderWidthObj, &borderwidth);\n    rest = strchr(p, ',');\n    if (rest) {\n\tTcl_DString ds;\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, p, rest - p);\n\n\tif (Tcl_GetInt(NULL, Tcl_DStringValue(&ds), &x) != TCL_OK) {\n\t    goto error;\n\t}\n    } else {\n\tx = borderwidth;\n\trest = string;\n    }\n    p = rest + 1;\n    if (Tcl_GetInt(NULL, p, &y) != TCL_OK) {\n\t    goto error;\n\t}\n\n    *indexPtr = -1;\n\n    /* set the width of the final column to the remainder of the window\n     * being aware of windows that may not be mapped yet.\n     */\n    max = Tk_IsMapped(menuPtr->tkwin)\n      ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin);\n    max -= borderwidth;\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tif (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) {\n\t    x2 = max;\n\t} else {\n\t    x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width;\n\t}\n\tif ((x >= menuPtr->entries[i]->x) && (y >= menuPtr->entries[i]->y)\n\t\t&& (x < x2)\n\t\t&& (y < (menuPtr->entries[i]->y\n\t\t+ menuPtr->entries[i]->height))) {\n\t    *indexPtr = i;\n\t    break;\n\t}\n    }\n    return TCL_OK;\n\n  error:\n    Tcl_ResetResult(interp);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RecursivelyDeleteMenu --\n *\n *\tDeletes a menu and any cascades underneath it. Used for deleting\n *\tinstances when a menu is no longer being used as a menubar, for\n *\tinstance.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDestroys the menu and all cascade menus underneath it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRecursivelyDeleteMenu(\n    TkMenu *menuPtr)\t\t/* The menubar instance we are deleting. */\n{\n    Tcl_Size i;\n    TkMenuEntry *mePtr;\n\n    /*\n     * It is not 100% clear that this preserve/release pair is required, but\n     * we have added them for safety in this very complex code.\n     */\n\n    Tcl_Preserve(menuPtr);\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tmePtr = menuPtr->entries[i];\n\tif ((mePtr->type == CASCADE_ENTRY)\n\t\t&& (mePtr->childMenuRefPtr != NULL)\n\t\t&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {\n\t    RecursivelyDeleteMenu(mePtr->childMenuRefPtr->menuPtr);\n\t}\n    }\n    if (menuPtr->tkwin != NULL) {\n\tTk_DestroyWindow(menuPtr->tkwin);\n    }\n\n    Tcl_Release(menuPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkNewMenuName --\n *\n *\tMakes a new unique name for a cloned menu. Will be a child of oldName.\n *\n * Results:\n *\tReturns a char * which has been allocated; caller must free.\n *\n * Side effects:\n *\tMemory is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkNewMenuName(\n    Tcl_Interp *interp,\t\t/* The interp the new name has to live in.*/\n    Tcl_Obj *parentPtr,\t\t/* The prefix path of the new name. */\n    TkMenu *menuPtr)\t\t/* The menu we are cloning. */\n{\n    Tcl_Obj *resultPtr = NULL;\t/* Initialization needed only to prevent\n\t\t\t\t * compiler warning. */\n    Tcl_Obj *childPtr;\n    char *destString;\n    int i;\n    int doDot;\n    Tcl_HashTable *nameTablePtr = NULL;\n    TkWindow *winPtr = (TkWindow *) menuPtr->tkwin;\n    const char *parentName = Tcl_GetString(parentPtr);\n\n    if (winPtr->mainPtr != NULL) {\n\tnameTablePtr = &(winPtr->mainPtr->nameTable);\n    }\n\n    doDot = parentName[strlen(parentName) - 1] != '.';\n\n    childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), TCL_INDEX_NONE);\n    for (destString = Tcl_GetString(childPtr);\n\t    *destString != '\\0'; destString++) {\n\tif (*destString == '.') {\n\t    *destString = '#';\n\t}\n    }\n\n    for (i = 0; ; i++) {\n\tif (i == 0) {\n\t    resultPtr = Tcl_DuplicateObj(parentPtr);\n\t    if (doDot) {\n\t\tTcl_AppendToObj(resultPtr, \".\", TCL_INDEX_NONE);\n\t    }\n\t    Tcl_AppendObjToObj(resultPtr, childPtr);\n\t} else {\n\t    Tcl_Obj *intPtr;\n\n\t    Tcl_DecrRefCount(resultPtr);\n\t    resultPtr = Tcl_DuplicateObj(parentPtr);\n\t    if (doDot) {\n\t\tTcl_AppendToObj(resultPtr, \".\", TCL_INDEX_NONE);\n\t    }\n\t    Tcl_AppendObjToObj(resultPtr, childPtr);\n\t    intPtr = Tcl_NewWideIntObj(i);\n\t    Tcl_AppendObjToObj(resultPtr, intPtr);\n\t    Tcl_DecrRefCount(intPtr);\n\t}\n\tdestString = Tcl_GetString(resultPtr);\n\tif ((Tcl_FindCommand(interp, destString, NULL, 0) == NULL)\n\t\t&& ((nameTablePtr == NULL)\n\t\t|| (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) {\n\t    break;\n\t}\n    }\n    Tcl_DecrRefCount(childPtr);\n    return resultPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetWindowMenubar --\n *\n *\tAssociates a menu with a window. Called by ConfigureFrame in in\n *\tresponse to a \"-menu .foo\" configuration option for a top level.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe old menu clones for the menubar are thrown away, and a handler is\n *\tset up to allocate the new ones.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetWindowMenubar(\n    Tcl_Interp *interp,\t\t/* The interpreter the toplevel lives in. */\n    Tk_Window tkwin,\t\t/* The toplevel window. */\n    const char *oldMenuName, /* The name of the menubar previously set in\n\t\t\t\t * this toplevel. NULL means no menu was set\n\t\t\t\t * previously. */\n    const char *menuName)\t/* The name of the new menubar that the\n\t\t\t\t * toplevel needs to be set to. NULL means\n\t\t\t\t * that their is no menu now. */\n{\n    TkMenuTopLevelList *topLevelListPtr, *prevTopLevelPtr;\n    TkMenu *menuPtr;\n    TkMenuReferences *menuRefPtr;\n\n    /*\n     * Destroy the menubar instances of the old menu. Take this window out of\n     * the old menu's top level reference list.\n     */\n\n    if (oldMenuName != NULL) {\n\tmenuRefPtr = TkFindMenuReferences(interp, oldMenuName);\n\tif (menuRefPtr != NULL) {\n\t    /*\n\t     * Find the menubar instance that is to be removed. Destroy it and\n\t     * all of the cascades underneath it.\n\t     */\n\n\t    if (menuRefPtr->menuPtr != NULL) {\n\t\tTkMenu *instancePtr;\n\n\t\tmenuPtr = menuRefPtr->menuPtr;\n\n\t\tfor (instancePtr = menuPtr->mainMenuPtr;\n\t\t\tinstancePtr != NULL;\n\t\t\tinstancePtr = instancePtr->nextInstancePtr) {\n\t\t    if (instancePtr->menuType == MENUBAR\n\t\t\t    && instancePtr->parentTopLevelPtr == tkwin) {\n\t\t\tRecursivelyDeleteMenu(instancePtr);\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\n\t    /*\n\t     * Now we need to remove this toplevel from the list of toplevels\n\t     * that reference this menu.\n\t     */\n\n\t    topLevelListPtr = menuRefPtr->topLevelListPtr;\n\t    prevTopLevelPtr = NULL;\n\n\t    while ((topLevelListPtr != NULL)\n\t\t    && (topLevelListPtr->tkwin != tkwin)) {\n\t\tprevTopLevelPtr = topLevelListPtr;\n\t\ttopLevelListPtr = topLevelListPtr->nextPtr;\n\t    }\n\n\t    /*\n\t     * Now we have found the toplevel reference that matches the\n\t     * tkwin; remove this reference from the list.\n\t     */\n\n\t    if (topLevelListPtr != NULL) {\n\t\tif (prevTopLevelPtr == NULL) {\n\t\t    menuRefPtr->topLevelListPtr =\n\t\t\t    menuRefPtr->topLevelListPtr->nextPtr;\n\t\t} else {\n\t\t    prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr;\n\t\t}\n\t\tTcl_Free(topLevelListPtr);\n\t\tTkFreeMenuReferences(menuRefPtr);\n\t    }\n\t}\n    }\n\n    /*\n     * Now, add the clone references for the new menu.\n     */\n\n    if (menuName != NULL && menuName[0] != 0) {\n\tTkMenu *menuBarPtr = NULL;\n\n\tmenuRefPtr = TkCreateMenuReferences(interp, menuName);\n\n\tmenuPtr = menuRefPtr->menuPtr;\n\tif (menuPtr != NULL) {\n\t    Tcl_Obj *cloneMenuPtr;\n\t    TkMenuReferences *cloneMenuRefPtr;\n\t    Tcl_Obj *newObjv[4];\n\t    Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin),\n\t\t    -1);\n\t    Tcl_Obj *menubarPtr = Tcl_NewStringObj(\"menubar\", TCL_INDEX_NONE);\n\n\t    /*\n\t     * Clone the menu and all of the cascades underneath it.\n\t     */\n\n\t    Tcl_IncrRefCount(windowNamePtr);\n\t    cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,\n\t\t    menuPtr);\n\t    Tcl_IncrRefCount(cloneMenuPtr);\n\t    Tcl_IncrRefCount(menubarPtr);\n\t    CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);\n\n\t    cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);\n\t    if ((cloneMenuRefPtr != NULL)\n\t\t    && (cloneMenuRefPtr->menuPtr != NULL)) {\n\t\tTcl_Obj *cursorPtr = Tcl_NewStringObj(\"-cursor\", TCL_INDEX_NONE);\n\t\tTcl_Obj *nullPtr = Tcl_NewObj();\n\n\t\tcloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin;\n\t\tmenuBarPtr = cloneMenuRefPtr->menuPtr;\n\t\tnewObjv[0] = cursorPtr;\n\t\tnewObjv[1] = nullPtr;\n\t\tTcl_IncrRefCount(cursorPtr);\n\t\tTcl_IncrRefCount(nullPtr);\n\t\tConfigureMenu(menuPtr->interp, cloneMenuRefPtr->menuPtr,\n\t\t\t2, newObjv);\n\t\tTcl_DecrRefCount(cursorPtr);\n\t\tTcl_DecrRefCount(nullPtr);\n\t    }\n\n\t    TkpSetWindowMenuBar(tkwin, menuBarPtr);\n\t    Tcl_DecrRefCount(cloneMenuPtr);\n\t    Tcl_DecrRefCount(menubarPtr);\n\t    Tcl_DecrRefCount(windowNamePtr);\n\t} else {\n\t    TkpSetWindowMenuBar(tkwin, NULL);\n\t}\n\n\t/*\n\t * Add this window to the menu's list of windows that refer to this\n\t * menu.\n\t */\n\n\ttopLevelListPtr = (TkMenuTopLevelList *)Tcl_Alloc(sizeof(TkMenuTopLevelList));\n\ttopLevelListPtr->tkwin = tkwin;\n\ttopLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr;\n\tmenuRefPtr->topLevelListPtr = topLevelListPtr;\n    } else {\n\tTkpSetWindowMenuBar(tkwin, NULL);\n    }\n    Tk_SetMainMenubar(interp, tkwin, menuName);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyMenuHashTable --\n *\n *\tCalled when an interp is deleted and a menu hash table has been set in\n *\tit.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe hash table is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyMenuHashTable(\n    void *clientData,\t/* The menu hash table we are destroying. */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* The interpreter we are destroying. */\n{\n    Tcl_DeleteHashTable((Tcl_HashTable *)clientData);\n    Tcl_Free(clientData);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetMenuHashTable --\n *\n *\tFor a given interp, give back the menu hash table that goes with it.\n *\tIf the hash table does not exist, it is created.\n *\n * Results:\n *\tReturns a hash table pointer.\n *\n * Side effects:\n *\tA new hash table is created if there were no table in the interp\n *\toriginally.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_HashTable *\nTkGetMenuHashTable(\n    Tcl_Interp *interp)\t\t/* The interp we need the hash table in.*/\n{\n    Tcl_HashTable *menuTablePtr = (Tcl_HashTable *)\n\t    Tcl_GetAssocData(interp, MENU_HASH_KEY, NULL);\n\n    if (menuTablePtr == NULL) {\n\tmenuTablePtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tTcl_InitHashTable(menuTablePtr, TCL_STRING_KEYS);\n\tTcl_SetAssocData(interp, MENU_HASH_KEY, DestroyMenuHashTable,\n\t\tmenuTablePtr);\n    }\n    return menuTablePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateMenuReferences --\n *\n *\tGiven a pathname, gives back a pointer to a TkMenuReferences\n *\tstructure. If a reference is not already in the hash table, one is\n *\tcreated.\n *\n * Results:\n *\tReturns a pointer to a menu reference structure. Should not be freed\n *\tby caller; when a field of the reference is cleared,\n *\tTkFreeMenuReferences should be called.\n *\n * Side effects:\n *\tA new hash table entry is created if there were no references to the\n *\tmenu originally.\n *\n *----------------------------------------------------------------------\n */\n\nTkMenuReferences *\nTkCreateMenuReferences(\n    Tcl_Interp *interp,\n    const char *pathName)\t\t/* The path of the menu widget. */\n{\n    Tcl_HashEntry *hashEntryPtr;\n    TkMenuReferences *menuRefPtr;\n    int newEntry;\n    Tcl_HashTable *menuTablePtr = TkGetMenuHashTable(interp);\n\n    hashEntryPtr = Tcl_CreateHashEntry(menuTablePtr, pathName, &newEntry);\n    if (newEntry) {\n\tmenuRefPtr = (TkMenuReferences *)Tcl_Alloc(sizeof(TkMenuReferences));\n\tmenuRefPtr->menuPtr = NULL;\n\tmenuRefPtr->topLevelListPtr = NULL;\n\tmenuRefPtr->parentEntryPtr = NULL;\n\tmenuRefPtr->hashEntryPtr = hashEntryPtr;\n\tTcl_SetHashValue(hashEntryPtr, menuRefPtr);\n    } else {\n\tmenuRefPtr = (TkMenuReferences *)Tcl_GetHashValue(hashEntryPtr);\n    }\n    return menuRefPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFindMenuReferences --\n *\n *\tGiven a pathname, gives back a pointer to the TkMenuReferences\n *\tstructure.\n *\n * Results:\n *\tReturns a pointer to a menu reference structure. Should not be freed\n *\tby calller; when a field of the reference is cleared,\n *\tTkFreeMenuReferences should be called. Returns NULL if no reference\n *\twith this pathname exists.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkMenuReferences *\nTkFindMenuReferences(\n    Tcl_Interp *interp,\t\t/* The interp the menu is living in. */\n    const char *pathName)\t/* The path of the menu widget. */\n{\n    Tcl_HashEntry *hashEntryPtr;\n    TkMenuReferences *menuRefPtr = NULL;\n    Tcl_HashTable *menuTablePtr;\n\n    menuTablePtr = TkGetMenuHashTable(interp);\n    hashEntryPtr = Tcl_FindHashEntry(menuTablePtr, pathName);\n    if (hashEntryPtr != NULL) {\n\tmenuRefPtr = (TkMenuReferences *)Tcl_GetHashValue(hashEntryPtr);\n    }\n    return menuRefPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFindMenuReferencesObj --\n *\n *\tGiven a pathname, gives back a pointer to the TkMenuReferences\n *\tstructure.\n *\n * Results:\n *\tReturns a pointer to a menu reference structure. Should not be freed\n *\tby calller; when a field of the reference is cleared,\n *\tTkFreeMenuReferences should be called. Returns NULL if no reference\n *\twith this pathname exists.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkMenuReferences *\nTkFindMenuReferencesObj(\n    Tcl_Interp *interp,\t\t/* The interp the menu is living in. */\n    Tcl_Obj *objPtr)\t\t/* The path of the menu widget. */\n{\n    const char *pathName = Tcl_GetString(objPtr);\n\n    return TkFindMenuReferences(interp, pathName);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkFreeMenuReferences --\n *\n *\tThis is called after one of the fields in a menu reference is cleared.\n *\tIt cleans up the ref if it is now empty.\n *\n * Results:\n *\tReturns true if the references structure was freed, and false otherwise.\n *\n * Side effects:\n *\tIf this is the last field to be cleared, the menu ref is taken out of\n *\tthe hash table.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkFreeMenuReferences(\n    TkMenuReferences *menuRefPtr)\n\t\t\t\t/* The menu reference to free. */\n{\n    if ((menuRefPtr->menuPtr == NULL)\n\t    && (menuRefPtr->parentEntryPtr == NULL)\n\t    && (menuRefPtr->topLevelListPtr == NULL)) {\n\tTcl_DeleteHashEntry(menuRefPtr->hashEntryPtr);\n\tTcl_Free(menuRefPtr);\n\treturn true;\n    }\n    return false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteMenuCloneEntries --\n *\n *\tFor every clone in this clone chain, delete the menu entries given by\n *\tthe parameters.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe appropriate entries are deleted from all clones of this menu.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteMenuCloneEntries(\n    TkMenu *menuPtr,\t\t/* The menu the command was issued with. */\n    int\tfirst,\t\t\t/* The zero-based first entry in the set of\n\t\t\t\t * entries to delete. */\n    int last)\t\t\t/* The zero-based last entry. */\n{\n    TkMenu *menuListPtr;\n    Tcl_Size numDeleted, i, j;\n\n    numDeleted = last + 1 - first;\n    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;\n\t    menuListPtr = menuListPtr->nextInstancePtr) {\n\tfor (i = last; i >= first; i--) {\n\t    Tcl_EventuallyFree(menuListPtr->entries[i], DestroyMenuEntry);\n\t}\n\tfor (i = last + 1; i < menuListPtr->numEntries; i++) {\n\t    j = i - numDeleted;\n\t    menuListPtr->entries[j] = menuListPtr->entries[i];\n\t    menuListPtr->entries[j]->index = j;\n\t}\n\tmenuListPtr->numEntries -= numDeleted;\n\tif (menuListPtr->numEntries == 0) {\n\t    Tcl_Free(menuListPtr->entries);\n\t    menuListPtr->entries = NULL;\n\t}\n\tif (((int)menuListPtr->active >= first)\n\t\t&& ((int)menuListPtr->active <= last)) {\n\t    menuListPtr->active = -1;\n\t} else if ((int)menuListPtr->active > last) {\n\t    menuListPtr->active -= numDeleted;\n\t}\n\tTkEventuallyRecomputeMenu(menuListPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuCleanup --\n *\n *\tResets menusInitialized to allow Tk to be finalized and reused without\n *\tthe DLL being unloaded.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuCleanup(\n    TCL_UNUSED(void *))\n{\n    menusInitialized = false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuInit --\n *\n *\tSets up the hash tables and the variables used by the menu package.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tlastMenuID gets initialized, and the parent hash and the command hash\n *\tare allocated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuInit(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!menusInitialized) {\n\tTcl_MutexLock(&menuMutex);\n\tif (!menusInitialized) {\n\t    TkpMenuInit();\n\t    menusInitialized = true;\n\t}\n\n\t/*\n\t * Make sure we cleanup on finalize.\n\t */\n\n\tTkCreateExitHandler((Tcl_ExitProc *) MenuCleanup, NULL);\n\tTcl_MutexUnlock(&menuMutex);\n    }\n    if (!tsdPtr->menusInitialized) {\n\tTkpMenuThreadInit();\n\ttsdPtr->menuOptionTable =\n\t\tTk_CreateOptionTable(NULL, tkMenuConfigSpecs);\n\ttsdPtr->entryOptionTables[TEAROFF_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[TEAROFF_ENTRY]);\n\ttsdPtr->entryOptionTables[COMMAND_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[COMMAND_ENTRY]);\n\ttsdPtr->entryOptionTables[CASCADE_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[CASCADE_ENTRY]);\n\ttsdPtr->entryOptionTables[SEPARATOR_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[SEPARATOR_ENTRY]);\n\ttsdPtr->entryOptionTables[RADIO_BUTTON_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[RADIO_BUTTON_ENTRY]);\n\ttsdPtr->entryOptionTables[CHECK_BUTTON_ENTRY] =\n\t\tTk_CreateOptionTable(NULL, specsArray[CHECK_BUTTON_ENTRY]);\n\ttsdPtr->menusInitialized = true;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMenu.h",
    "content": "/*\n * tkMenu.h --\n *\n *\tDeclarations shared among all of the files that implement menu\n *\twidgets.\n *\n * Copyright © 1996-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMENU\n#define _TKMENU\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n#ifndef _DEFAULT\n#include \"default.h\"\n#endif\n\n/*\n * Dummy types used by the platform menu code.\n */\n\ntypedef struct TkMenuPlatformData_ *TkMenuPlatformData;\ntypedef struct TkMenuPlatformEntryData_ *TkMenuPlatformEntryData;\n\n/*\n * Legal values for the \"compound\" field of TkMenuEntry and TkMenuButton\n * records.\n */\n\nenum compound {\n    COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE,\n    COMPOUND_RIGHT, COMPOUND_TOP\n};\n\n/*\n * Additional menu entry drawing parameters for Windows platform.\n * DRAW_MENU_ENTRY_ARROW makes TkpDrawMenuEntry draw the arrow\n * itself when cascade entry is disabled.\n * DRAW_MENU_ENTRY_NOUNDERLINE forbids underline when ODS_NOACCEL\n * is set, thus obeying the system-wide Windows UI setting.\n * Additional menu entry drawing parameter for UNIX platform.\n * DRAW_MENU_ENTRY_STRICTMOTIF.\n */\n\ntypedef enum {\n    DRAW_MENU_ENTRY_DEFAULT = (0),\n    DRAW_MENU_ENTRY_ARROW = (1<<0),\n    DRAW_MENU_ENTRY_NOUNDERLINE = (1<<1),\n    DRAW_MENU_ENTRY_STRICTMOTIF = (1<<2)\n} DrawMenuFlags;\n\n/*\n * One of the following data structures is kept for each entry of each menu\n * managed by this file:\n */\n\ntypedef struct TkMenuEntry {\n    int type;\t\t\t/* Type of menu entry; see below for valid\n\t\t\t\t * types. */\n    struct TkMenu *menuPtr;\t/* Menu with which this entry is\n\t\t\t\t * associated. */\n    Tk_OptionTable optionTable;\t/* Option table for this menu entry. */\n    Tcl_Obj *labelPtr;\t\t/* Main text label displayed in entry (NULL if\n\t\t\t\t * no label). */\n    Tcl_Size labelLength;\t/* Number of non-NULL characters in label. */\n    int state;\t\t\t/* State of button for display purposes:\n\t\t\t\t * normal, active, or disabled. */\n    int underline;\t\t/* Value of -underline option: specifies index\n\t\t\t\t * of character to underline (INT_MIN means don't\n\t\t\t\t * underline anything). */\n    Tcl_Obj *underlinePtr;\t/* Index of character to underline. */\n    Tcl_Obj *bitmapPtr;\t\t/* Bitmap to display in menu entry, or NULL.\n\t\t\t\t * If not NULL then label is ignored. */\n    Tcl_Obj *imagePtr;\t\t/* Name of image to display, or NULL. If not\n\t\t\t\t * NULL, bitmap, text, and textVarName are\n\t\t\t\t * ignored. */\n    Tk_Image image;\t\t/* Image to display in menu entry, or NULL if\n\t\t\t\t * none. */\n    Tcl_Obj *selectImagePtr;\t/* Name of image to display when selected, or\n\t\t\t\t * NULL. */\n    Tk_Image selectImage;\t/* Image to display in entry when selected, or\n\t\t\t\t * NULL if none. Ignored if image is NULL. */\n    Tcl_Obj *accelPtr;\t\t/* Accelerator string displayed at right of\n\t\t\t\t * menu entry. NULL means no such accelerator.\n\t\t\t\t * Malloc'ed. */\n    Tcl_Size accelLength;\t/* Number of non-NULL characters in\n\t\t\t\t * accelerator. */\n    bool indicatorOn;\t\t/* True means draw indicator, false means\n\t\t\t\t * don't draw it. This field is ignored unless\n\t\t\t\t * the entry is a radio or check button. */\n    /*\n     * Display attributes\n     */\n\n    Tcl_Obj *borderPtr;\t\t/* Structure used to draw background for\n\t\t\t\t * entry. NULL means use overall border for\n\t\t\t\t * menu. */\n    Tcl_Obj *fgPtr;\t\t/* Foreground color to use for entry. NULL\n\t\t\t\t * means use foreground color from menu. */\n    Tcl_Obj *activeBorderPtr;\t/* Used to draw background and border when\n\t\t\t\t * element is active. NULL means use\n\t\t\t\t * activeBorder from menu. */\n    Tcl_Obj *activeFgPtr;\t/* Foreground color to use when entry is\n\t\t\t\t * active. NULL means use active foreground\n\t\t\t\t * from menu. */\n    Tcl_Obj *indicatorFgPtr;\t/* Color for indicators in radio and check\n\t\t\t\t * button entries. NULL means use indicatorFg\n\t\t\t\t * GC from menu. */\n    Tcl_Obj *fontPtr;\t\t/* Text font for menu entries. NULL means use\n\t\t\t\t * overall font for menu. */\n    bool columnBreak;\t\t/* If this is false, this item appears below the\n\t\t\t\t * item in front of it. If this is true, this\n\t\t\t\t * item starts a new column. This field is\n\t\t\t\t * always false for tearoff and separator\n\t\t\t\t * entries. */\n    bool hideMargin;\t\t/* If this is false, then the item has enough\n\t\t\t\t * margin to accommodate a standard check mark\n\t\t\t\t * and a default right margin. If this is true,\n\t\t\t\t * then the item has no such margins, and\n\t\t\t\t * checkbuttons and radiobuttons with this set\n\t\t\t\t * will have a rectangle drawn in the\n\t\t\t\t * indicator around the item if the item is\n\t\t\t\t * checked. This is useful for palette menus.\n\t\t\t\t * This field is ignored for separators and\n\t\t\t\t * tearoffs. */\n    int indicatorSpace;\t\t/* The width of the indicator space for this\n\t\t\t\t * entry. */\n    int labelWidth;\t\t/* Number of pixels to allow for displaying\n\t\t\t\t * labels in menu entries. */\n    int compound;\t\t/* Value of -compound option; specifies\n\t\t\t\t * whether the entry should show both an image\n\t\t\t\t * and text, and, if so, how. */\n\n    /*\n     * Information used to implement this entry's action:\n     */\n\n    Tcl_Obj *commandPtr;\t/* Command to invoke when entry is invoked.\n\t\t\t\t * Malloc'ed. */\n    Tcl_Obj *namePtr;\t\t/* Name of variable (for check buttons and\n\t\t\t\t * radio buttons) or menu (for cascade\n\t\t\t\t * entries). Malloc'ed. */\n    Tcl_Obj *onValuePtr;\t/* Value to store in variable when selected\n\t\t\t\t * (only for radio and check buttons).\n\t\t\t\t * Malloc'ed. */\n    Tcl_Obj *offValuePtr;\t/* Value to store in variable when not\n\t\t\t\t * selected (only for check buttons).\n\t\t\t\t * Malloc'ed. */\n\n    /*\n     * Information used for drawing this menu entry.\n     */\n\n    int width;\t\t\t/* Number of pixels occupied by entry in\n\t\t\t\t * horizontal dimension. Not used except in\n\t\t\t\t * menubars. The width of norma menus is\n\t\t\t\t * dependent on the rest of the menu. */\n    int x;\t\t\t/* X-coordinate of leftmost pixel in entry. */\n    int height;\t\t\t/* Number of pixels occupied by entry in\n\t\t\t\t * vertical dimension, including raised border\n\t\t\t\t * drawn around entry when active. */\n    int y;\t\t\t/* Y-coordinate of topmost pixel in entry. */\n    GC textGC;\t\t\t/* GC for drawing text in entry. NULL means\n\t\t\t\t * use overall textGC for menu. */\n    GC activeGC;\t\t/* GC for drawing text in entry when active.\n\t\t\t\t * NULL means use overall activeGC for\n\t\t\t\t * menu. */\n    GC disabledGC;\t\t/* Used to produce disabled effect for entry.\n\t\t\t\t * NULL means use overall disabledGC from menu\n\t\t\t\t * structure. See comments for disabledFg in\n\t\t\t\t * menu structure for more information. */\n    GC indicatorGC;\t\t/* For drawing indicators. NULL means use GC\n\t\t\t\t * from menu. */\n\n    /*\n     * Miscellaneous fields.\n     */\n\n    int entryFlags;\t\t/* Various flags. See below for\n\t\t\t\t * definitions. */\n    int index;\t\t\t/* Need to know which index we are. This is\n\t\t\t\t * zero-based. This is the top-left entry of\n\t\t\t\t * the menu. */\n    Tcl_HashEntry *entryPtr;\t/* Back-pointer to hash table entry */\n    /*\n     * Bookeeping for main menus and cascade menus.\n     */\n\n    struct TkMenuReferences *childMenuRefPtr;\n\t\t\t\t/* A pointer to the hash table entry for the\n\t\t\t\t * child menu. Stored here when the menu entry\n\t\t\t\t * is configured so that a hash lookup is not\n\t\t\t\t * necessary later.*/\n    struct TkMenuEntry *nextCascadePtr;\n\t\t\t\t/* The next cascade entry that is a parent of\n\t\t\t\t * this entry's child cascade menu. NULL end\n\t\t\t\t * of list, this is not a cascade entry, or\n\t\t\t\t * the menu that this entry point to does not\n\t\t\t\t * yet exist. */\n    TkMenuPlatformEntryData platformEntryData;\n\t\t\t\t/* The data for the specific type of menu.\n\t\t\t\t * Depends on platform and menu type what kind\n\t\t\t\t * of options are in this structure. */\n} TkMenuEntry;\n\n/*\n * Flag values defined for menu entries:\n *\n * ENTRY_SELECTED:\t\tNon-zero means this is a radio or check button\n *\t\t\t\tand that it should be drawn in the \"selected\"\n *\t\t\t\tstate.\n * ENTRY_NEEDS_REDISPLAY:\tNon-zero means the entry should be redisplayed.\n * ENTRY_LAST_COLUMN:\t\tUsed by the drawing code. If the entry is in\n *\t\t\t\tthe last column, the space to its right needs\n *\t\t\t\tto be filled.\n * ENTRY_PLATFORM_FLAG1 - 4\tThese flags are reserved for use by the\n *\t\t\t\tplatform-dependent implementation of menus\n *\t\t\t\tand should not be used by anything else.\n */\n\n#define ENTRY_SELECTED\t\t1\n#define ENTRY_NEEDS_REDISPLAY\t2\n#define ENTRY_LAST_COLUMN\t4\n#define ENTRY_PLATFORM_FLAG1\t(1 << 30)\n#define ENTRY_PLATFORM_FLAG2\t(1 << 29)\n#define ENTRY_PLATFORM_FLAG3\t(1 << 28)\n#define ENTRY_PLATFORM_FLAG4\t(1 << 27)\n\n/*\n * Types defined for MenuEntries:\n */\n\n#define CASCADE_ENTRY 0\n#define CHECK_BUTTON_ENTRY 1\n#define COMMAND_ENTRY 2\n#define RADIO_BUTTON_ENTRY 3\n#define SEPARATOR_ENTRY 4\n#define TEAROFF_ENTRY 5\n\n/*\n * Menu states\n */\n\n#define ENTRY_ACTIVE 0\n#define ENTRY_DISABLED 1\n#define ENTRY_NORMAL 2\n\n/*\n * A data structure of the following type is kept for each menu widget:\n */\n\ntypedef struct TkMenu {\n    Tk_Window tkwin;\t\t/* Window that embodies the pane. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up. */\n    Display *display;\t\t/* Display containing widget. Needed, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed up even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with menu. */\n    Tcl_Command widgetCmd;\t/* Token for menu's widget command. */\n    TkMenuEntry **entries;\t/* Array of pointers to all the entries in the\n\t\t\t\t * menu. NULL means no entries. */\n    Tcl_Size numEntries;\t\t/* Number of elements in entries. */\n    Tcl_Size active;\t\t\t/* Index of active entry. TCL_INDEX_NONE means\n\t\t\t\t * nothing active. */\n    int menuType;\t\t/* MAIN_MENU, TEAROFF_MENU, or MENUBAR. See\n\t\t\t\t * below for definitions. */\n    Tcl_Obj *menuTypePtr;\t/* Used to control whether created tkwin is a\n\t\t\t\t * toplevel or not. \"normal\", \"menubar\", or\n\t\t\t\t * \"toplevel\" */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *borderPtr;\t\t/* Structure used to draw 3-D border and\n\t\t\t\t * background for menu. */\n    Tcl_Obj *borderWidthObj;\t/* Width of border around whole menu. */\n    Tcl_Obj *activeBorderPtr;\t/* Used to draw background and border for\n\t\t\t\t * active element (if any). */\n    Tcl_Obj *activeBorderWidthPtr;\n\t\t\t\t/* Width of border around active element. */\n    int relief;\t\t/* 3-d effect: TK_RELIEF_RAISED, etc. */\n    Tcl_Obj *fontPtr;\t\t/* Text font for menu entries. */\n    Tcl_Obj *fgPtr;\t\t/* Foreground color for entries. */\n    Tcl_Obj *disabledFgPtr;\t/* Foreground color when disabled. NULL means\n\t\t\t\t * use normalFg with a 50% stipple instead. */\n    Tcl_Obj *activeFgPtr;\t/* Foreground color for active entry. */\n    Tcl_Obj *indicatorFgPtr;\t/* Color for indicators in radio and check\n\t\t\t\t * button entries. */\n    Pixmap gray;\t\t/* Bitmap for drawing disabled entries in a\n\t\t\t\t * stippled fashion. None means not allocated\n\t\t\t\t * yet. */\n    GC textGC;\t\t\t/* GC for drawing text and other features of\n\t\t\t\t * menu entries. */\n    GC disabledGC;\t\t/* Used to produce disabled effect. If\n\t\t\t\t * disabledFg isn't NULL, this GC is used to\n\t\t\t\t * draw text and icons for disabled entries.\n\t\t\t\t * Otherwise text and icons are drawn with\n\t\t\t\t * normalGC and this GC is used to stipple\n\t\t\t\t * background across them. */\n    GC activeGC;\t\t/* GC for drawing active entry. */\n    GC indicatorGC;\t\t/* For drawing indicators. */\n    GC disabledImageGC;\t\t/* Used for drawing disabled images. They have\n\t\t\t\t * to be stippled. This is created when the\n\t\t\t\t * image is about to be drawn the first\n\t\t\t\t * time. */\n\n    /*\n     * Information about geometry of menu.\n     */\n\n    int totalWidth;\t\t/* Width of entire menu. */\n    int totalHeight;\t\t/* Height of entire menu. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    bool tearoff;\t\t/* True means this menu can be torn off. On some\n\t\t\t\t * platforms, the user can drag an outline of\n\t\t\t\t * the menu by just dragging outside of the\n\t\t\t\t * menu, and the tearoff is created where the\n\t\t\t\t * mouse is released. On others, an indicator\n\t\t\t\t * (such as a dashed stripe) is drawn, and\n\t\t\t\t * when the menu is selected, the tearoff is\n\t\t\t\t * created. */\n    Tcl_Obj *titlePtr;\t\t/* The title to use when this menu is torn\n\t\t\t\t * off. If this is NULL, a default scheme will\n\t\t\t\t * be used to generate a title for tearoff. */\n    Tcl_Obj *tearoffCommandPtr;\t/* If non-NULL, points to a command to run\n\t\t\t\t * whenever the menu is torn-off. */\n    Tcl_Obj *takeFocusPtr;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. Malloc'ed, but may be NULL. */\n    Tcl_Obj *cursorPtr;\t\t/* Current cursor for window, or NULL. */\n    Tcl_Obj *postCommandPtr;\t/* Used to detect cycles in cascade hierarchy\n\t\t\t\t * trees when preprocessing postcommands on\n\t\t\t\t * some platforms. See PostMenu for more\n\t\t\t\t * details. */\n    int postCommandGeneration;\t/* Need to do pre-invocation post command\n\t\t\t\t * traversal. */\n    int menuFlags;\t\t/* Flags for use by X; see below for\n\t\t\t\t * definition. */\n    TkMenuEntry *postedCascade;\t/* Points to menu entry for cascaded submenu\n\t\t\t\t * that is currently posted or NULL if no\n\t\t\t\t * submenu posted. */\n    struct TkMenu *nextInstancePtr;\n\t\t\t\t/* The next instance of this menu in the\n\t\t\t\t * chain. */\n    struct TkMenu *mainMenuPtr;\n\t\t\t\t/* A pointer to the original menu for this\n\t\t\t\t * clone chain. Points back to this structure\n\t\t\t\t * if this menu is a main menu. */\n    void *reserved1; /* not used any more. */\n    Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the\n\t\t\t\t * toplevel that owns the menu. Only\n\t\t\t\t * applicable for menubar clones. */\n    struct TkMenuReferences *menuRefPtr;\n\t\t\t\t/* Each menu is hashed into a table with the\n\t\t\t\t * name of the menu's window as the key. The\n\t\t\t\t * information in this hash table includes a\n\t\t\t\t * pointer to the menu (so that cascades can\n\t\t\t\t * find this menu), a pointer to the list of\n\t\t\t\t * toplevel widgets that have this menu as its\n\t\t\t\t * menubar, and a list of menu entries that\n\t\t\t\t * have this menu specified as a cascade. */\n    TkMenuPlatformData platformData;\n\t\t\t\t/* The data for the specific type of menu.\n\t\t\t\t * Depends on platform and menu type what kind\n\t\t\t\t * of options are in this structure. */\n    Tk_OptionSpec *extensionPtr;/* Needed by the configuration package for\n\t\t\t\t * this widget to be extended. */\n    Tk_SavedOptions *errorStructPtr;\n\t\t\t\t/* We actually have to allocate these because\n\t\t\t\t * multiple menus get changed during one\n\t\t\t\t * ConfigureMenu call. */\n    int activeRelief;\t/* 3-d effect for active element. */\n    Tcl_HashTable items;\t/* Map: id -> entry */\n    int serial;\t\t\t/* Next item # for autogenerated ids */\n} TkMenu;\n\n/*\n * When the toplevel configure -menu command is executed, the menu may not\n * exist yet. We need to keep a linked list of windows that reference a\n * particular menu.\n */\n\ntypedef struct TkMenuTopLevelList {\n    struct TkMenuTopLevelList *nextPtr;\n\t\t\t\t/* The next window in the list. */\n    Tk_Window tkwin;\t\t/* The window that has this menu as its\n\t\t\t\t * menubar. */\n} TkMenuTopLevelList;\n\n/*\n * The following structure is used to keep track of things which reference a\n * menu. It is created when:\n * - a menu is created.\n * - a cascade entry is added to a menu with a non-null name\n * - the \"-menu\" configuration option is used on a toplevel widget with a\n *   non-null parameter.\n *\n * One of these three fields must be non-NULL, but any of the fields may be\n * NULL. This structure makes it easy to determine whether or not anything\n * like recalculating platform data or geometry is necessary when one of the\n * three actions above is performed.\n */\n\ntypedef struct TkMenuReferences {\n    struct TkMenu *menuPtr;\t/* The menu data structure. This is NULL if\n\t\t\t\t * the menu does not exist. */\n    TkMenuTopLevelList *topLevelListPtr;\n\t\t\t\t/* First in the list of all toplevels that\n\t\t\t\t * have this menu as its menubar. NULL if no\n\t\t\t\t * toplevel widgets have this menu as its\n\t\t\t\t * menubar. */\n    TkMenuEntry *parentEntryPtr;/* First in the list of all cascade menu\n\t\t\t\t * entries that have this menu as their child.\n\t\t\t\t * NULL means no cascade entries. */\n    Tcl_HashEntry *hashEntryPtr;/* This is needed because the pathname of the\n\t\t\t\t * window (which is what we hash on) may not\n\t\t\t\t * be around when we are deleting. */\n} TkMenuReferences;\n\n/*\n * Flag bits for menus:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * RESIZE_PENDING:\t\tNon-zero means a call to ComputeMenuGeometry\n *\t\t\t\thas already been scheduled.\n * MENU_DELETION_PENDING\tNon-zero means that we are currently\n *\t\t\t\tdestroying this menu's internal structures.\n *\t\t\t\tThis is useful when we are in the middle of\n *\t\t\t\tcleaning this main menu's chain of menus up\n *\t\t\t\twhen TkDestroyMenu was called again on this\n *\t\t\t\tmenu (via a destroy binding or somesuch).\n * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of\n *\t\t\t\tdestroying this menu's Tk_Window.\n * MENU_PLATFORM_FLAG1...\tReserved for use by the platform-specific menu\n *\t\t\t\tcode.\n */\n\n#define REDRAW_PENDING\t\t\t1\n#define RESIZE_PENDING\t\t\t2\n#define MENU_DELETION_PENDING\t\t4\n#define MENU_WIN_DESTRUCTION_PENDING\t8\n#define MENU_PLATFORM_FLAG1\t(1 << 30)\n#define MENU_PLATFORM_FLAG2\t(1 << 29)\n#define MENU_PLATFORM_FLAG3\t(1 << 28)\n\n/*\n * Each menu created by the user is a MAIN_MENU. When a menu is torn off, a\n * TEAROFF_MENU instance is created. When a menu is assigned to a toplevel as\n * a menu bar, a MENUBAR instance is created. All instances have the same\n * configuration information. If the main instance is deleted, all instances\n * are deleted. If one of the other instances is deleted, only that instance\n * is deleted.\n */\n\n#define UNKNOWN_TYPE\t\t-1\n#define MENUBAR\t\t0\n#define MAIN_MENU\t\t1\n#define TEAROFF_MENU\t\t2\n\n/*\n * Various geometry definitions:\n */\n\n#define CASCADE_ARROW_HEIGHT\t10\n#define CASCADE_ARROW_WIDTH\t8\n#define DECORATION_BORDER_WIDTH\t2\n\n/*\n * Menu-related functions that are shared among Tk modules but not exported to\n * the outside world:\n */\n\nMODULE_SCOPE int\tTkActivateMenuEntry(TkMenu *menuPtr, Tcl_Size index);\nMODULE_SCOPE void\tTkBindMenu(Tk_Window tkwin, TkMenu *menuPtr);\nMODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp,\n\t\t\t    const char *name);\nMODULE_SCOPE void\tTkDestroyMenu(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkEventuallyRecomputeMenu(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkEventuallyRedrawMenu(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr);\nMODULE_SCOPE TkMenuReferences*TkFindMenuReferences(Tcl_Interp *interp, const char *name);\nMODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *namePtr);\nMODULE_SCOPE bool\tTkFreeMenuReferences(TkMenuReferences *menuRefPtr);\nMODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp);\nMODULE_SCOPE void\tTkMenuInitializeDrawingFields(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr);\nMODULE_SCOPE int\tTkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    Tcl_Size index);\nMODULE_SCOPE void\tTkMenuConfigureDrawOptions(TkMenu *menuPtr);\nMODULE_SCOPE int\tTkMenuConfigureEntryDrawOptions(\n\t\t\t    TkMenuEntry *mePtr, Tcl_Size index);\nMODULE_SCOPE void\tTkMenuFreeDrawOptions(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr);\nMODULE_SCOPE void\tTkMenuEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nMODULE_SCOPE void\tTkMenuImageProc(void *clientData, int x, int y,\n\t\t\t    int width, int height, int imgWidth,\n\t\t\t    int imgHeight);\nMODULE_SCOPE void\tTkMenuInit(void);\nMODULE_SCOPE void\tTkMenuSelectImageProc(void *clientData, int x,\n\t\t\t    int y, int width, int height, int imgWidth,\n\t\t\t    int imgHeight);\nMODULE_SCOPE Tcl_Obj *\tTkNewMenuName(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *parentNamePtr, TkMenu *menuPtr);\nMODULE_SCOPE int\tTkPostCommand(TkMenu *menuPtr);\nMODULE_SCOPE int\tTkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr);\nMODULE_SCOPE int\tTkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    int x, int y);\nMODULE_SCOPE int\tTkPreprocessMenu(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkRecomputeMenu(TkMenu *menuPtr);\n\n/*\n * These routines are the platform-dependent routines called by the common\n * code.\n */\n\nMODULE_SCOPE void\tTkpComputeMenubarGeometry(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkpComputeStandardMenuGeometry(TkMenu *menuPtr);\nMODULE_SCOPE int\tTkpConfigureMenuEntry(TkMenuEntry *mePtr);\nMODULE_SCOPE void\tTkpDestroyMenu(TkMenu *menuPtr);\nMODULE_SCOPE void\tTkpDestroyMenuEntry(TkMenuEntry *mEntryPtr);\nMODULE_SCOPE void\tTkpDrawMenuEntry(TkMenuEntry *mePtr,\n\t\t\t    Drawable d, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *menuMetricsPtr, int x,\n\t\t\t    int y, int width, int height,\n\t\t\t    DrawMenuFlags drawingParameters);\nMODULE_SCOPE void\tTkpMenuInit(void);\nMODULE_SCOPE int\tTkpMenuNewEntry(TkMenuEntry *mePtr);\nMODULE_SCOPE int\tTkpNewMenu(TkMenu *menuPtr);\nMODULE_SCOPE int\tTkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    int x, int y, Tcl_Size index);\nMODULE_SCOPE int\tTkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,\n\t\t\t    int x, int y, Tcl_Size index);\nMODULE_SCOPE void\tTkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr);\n\n#endif /* _TKMENU */\n"
  },
  {
    "path": "generic/tkMenuDraw.c",
    "content": "/*\n * tkMenuDraw.c --\n *\n *\tThis module implements the platform-independent drawing and geometry\n *\tcalculations of menu widgets.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkMenu.h\"\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tAdjustMenuCoords(TkMenu *menuPtr, TkMenuEntry *mePtr,\n\t\t\t    int *xPtr, int *yPtr);\nstatic void\t\tComputeMenuGeometry(void *clientData);\nstatic void\t\tDisplayMenu(void *clientData);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuInitializeDrawingFields --\n *\n *\tFills in drawing fields of a new menu. Called when new menu is created\n *\tby MenuCmd.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tmenuPtr fields are initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuInitializeDrawingFields(\n    TkMenu *menuPtr)\t\t/* The menu we are initializing. */\n{\n    menuPtr->textGC = NULL;\n    menuPtr->gray = None;\n    menuPtr->disabledGC = NULL;\n    menuPtr->activeGC = NULL;\n    menuPtr->indicatorGC = NULL;\n    menuPtr->disabledImageGC = NULL;\n    menuPtr->totalWidth = menuPtr->totalHeight = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuInitializeEntryDrawingFields --\n *\n *\tFills in drawing fields of a new menu entry. Called when an entry is\n *\tcreated.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuInitializeEntryDrawingFields(\n    TkMenuEntry *mePtr)\t\t/* The menu we are initializing. */\n{\n    mePtr->width = 0;\n    mePtr->height = 0;\n    mePtr->x = 0;\n    mePtr->y = 0;\n    mePtr->indicatorSpace = 0;\n    mePtr->labelWidth = 0;\n    mePtr->textGC = NULL;\n    mePtr->activeGC = NULL;\n    mePtr->disabledGC = NULL;\n    mePtr->indicatorGC = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuFreeDrawOptions --\n *\n *\tFrees up any structures allocated for the drawing of a menu. Called\n *\twhen menu is deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStorage is released.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuFreeDrawOptions(\n    TkMenu *menuPtr)\n{\n    if (menuPtr->textGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->textGC);\n    }\n    if (menuPtr->disabledImageGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);\n    }\n    if (menuPtr->gray != None) {\n\tTk_FreeBitmap(menuPtr->display, menuPtr->gray);\n    }\n    if (menuPtr->disabledGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->disabledGC);\n    }\n    if (menuPtr->activeGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->activeGC);\n    }\n    if (menuPtr->indicatorGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->indicatorGC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuEntryFreeDrawOptions --\n *\n *\tFrees up drawing structures for a menu entry. Called when menu entry\n *\tis freed.\n *\n * RESULTS:\n *\tNone.\n *\n * Side effects:\n *\tStorage is freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuEntryFreeDrawOptions(\n    TkMenuEntry *mePtr)\n{\n    if (mePtr->textGC != NULL) {\n\tTk_FreeGC(mePtr->menuPtr->display, mePtr->textGC);\n    }\n    if (mePtr->disabledGC != NULL) {\n\tTk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC);\n    }\n    if (mePtr->activeGC != NULL) {\n\tTk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC);\n    }\n    if (mePtr->indicatorGC != NULL) {\n\tTk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuConfigureDrawOptions --\n *\n *\tSets the menu's drawing attributes in preparation for drawing the\n *\tmenu.\n *\n * RESULTS:\n *\tNone.\n *\n * Side effects:\n *\tStorage is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuConfigureDrawOptions(\n    TkMenu *menuPtr)\t\t/* The menu we are configuring. */\n{\n    XGCValues gcValues;\n    GC newGC;\n    unsigned long mask;\n    Tk_3DBorder border, activeBorder;\n    Tk_Font tkfont;\n    XColor *fg, *activeFg, *indicatorFg;\n\n    /*\n     * A few options need special processing, such as setting the background\n     * from a 3-D border, or filling in complicated defaults that couldn't be\n     * specified to Tk_ConfigureWidget.\n     */\n\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n    Tk_SetBackgroundFromBorder(menuPtr->tkwin, border);\n\n    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n    gcValues.font = Tk_FontId(tkfont);\n    fg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->fgPtr);\n    gcValues.foreground = fg->pixel;\n    gcValues.background = Tk_3DBorderColor(border)->pixel;\n    newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,\n\t    &gcValues);\n    if (menuPtr->textGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->textGC);\n    }\n    menuPtr->textGC = newGC;\n\n    gcValues.font = Tk_FontId(tkfont);\n    gcValues.background = Tk_3DBorderColor(border)->pixel;\n    if (menuPtr->disabledFgPtr != NULL) {\n\tXColor *disabledFg;\n\n\tdisabledFg = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\tmenuPtr->disabledFgPtr);\n\tgcValues.foreground = disabledFg->pixel;\n\tmask = GCForeground|GCBackground|GCFont;\n    } else {\n\tgcValues.foreground = gcValues.background;\n\tmask = GCForeground;\n\tif (menuPtr->gray == None) {\n\t    menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,\n\t\t    \"gray50\");\n\t}\n\tif (menuPtr->gray != None) {\n\t    gcValues.fill_style = FillStippled;\n\t    gcValues.stipple = menuPtr->gray;\n\t    mask = GCForeground|GCFillStyle|GCStipple;\n\t}\n    }\n    newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);\n    if (menuPtr->disabledGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->disabledGC);\n    }\n    menuPtr->disabledGC = newGC;\n\n    gcValues.foreground = Tk_3DBorderColor(border)->pixel;\n    if (menuPtr->gray == None) {\n\tmenuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,\n\t\t\"gray50\");\n    }\n    if (menuPtr->gray != None) {\n\tgcValues.fill_style = FillStippled;\n\tgcValues.stipple = menuPtr->gray;\n\tnewGC = Tk_GetGC(menuPtr->tkwin,\n\t    GCForeground|GCFillStyle|GCStipple, &gcValues);\n    }\n    if (menuPtr->disabledImageGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);\n    }\n    menuPtr->disabledImageGC = newGC;\n\n    gcValues.font = Tk_FontId(tkfont);\n    activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr);\n    gcValues.foreground = activeFg->pixel;\n    activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t    menuPtr->activeBorderPtr);\n    gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;\n    newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,\n\t    &gcValues);\n    if (menuPtr->activeGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->activeGC);\n    }\n    menuPtr->activeGC = newGC;\n\n    indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,\n\t    menuPtr->indicatorFgPtr);\n    gcValues.foreground = indicatorFg->pixel;\n    gcValues.background = Tk_3DBorderColor(border)->pixel;\n    newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,\n\t    &gcValues);\n    if (menuPtr->indicatorGC != NULL) {\n\tTk_FreeGC(menuPtr->display, menuPtr->indicatorGC);\n    }\n    menuPtr->indicatorGC = newGC;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuConfigureEntryDrawOptions --\n *\n *\tCalculates any entry-specific draw options for the given menu entry.\n *\n * Results:\n *\tReturns a standard Tcl error.\n *\n * Side effects:\n *\tStorage may be allocated.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMenuConfigureEntryDrawOptions(\n    TkMenuEntry *mePtr,\n    Tcl_Size index)\n{\n    XGCValues gcValues;\n    GC newGC, newActiveGC, newDisabledGC, newIndicatorGC;\n    unsigned long mask;\n    Tk_Font tkfont;\n    TkMenu *menuPtr = mePtr->menuPtr;\n\n    tkfont = Tk_GetFontFromObj(menuPtr->tkwin,\n\t    (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);\n\n    if (mePtr->state == ENTRY_ACTIVE) {\n\tif (index != menuPtr->active) {\n\t    TkActivateMenuEntry(menuPtr, index);\n\t}\n    } else {\n\tif (index == menuPtr->active) {\n\t    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n\t}\n    }\n\n    if ((mePtr->fontPtr != NULL)\n\t    || (mePtr->borderPtr != NULL)\n\t    || (mePtr->fgPtr != NULL)\n\t    || (mePtr->activeBorderPtr != NULL)\n\t    || (mePtr->activeFgPtr != NULL)\n\t    || (mePtr->indicatorFgPtr != NULL)) {\n\tXColor *fg, *indicatorFg, *activeFg;\n\tTk_3DBorder border, activeBorder;\n\n\tfg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL)\n\t\t? mePtr->fgPtr : menuPtr->fgPtr);\n\tgcValues.foreground = fg->pixel;\n\tborder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t\t(mePtr->borderPtr != NULL) ? mePtr->borderPtr\n\t\t: menuPtr->borderPtr);\n\tgcValues.background = Tk_3DBorderColor(border)->pixel;\n\n\tgcValues.font = Tk_FontId(tkfont);\n\n\t/*\n\t * Note: disable GraphicsExpose events; we know there won't be\n\t * obscured areas when copying from an off-screen pixmap to the screen\n\t * and this gets rid of unnecessary events.\n\t */\n\n\tgcValues.graphics_exposures = False;\n\tnewGC = Tk_GetGC(menuPtr->tkwin,\n\t\tGCForeground|GCBackground|GCFont|GCGraphicsExposures,\n\t\t&gcValues);\n\n\tindicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\t(mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr\n\t\t: menuPtr->indicatorFgPtr);\n\tgcValues.foreground = indicatorFg->pixel;\n\tnewIndicatorGC = Tk_GetGC(menuPtr->tkwin,\n\t\tGCForeground|GCBackground|GCGraphicsExposures,\n\t\t&gcValues);\n\n\tif ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {\n\t    XColor *disabledFg;\n\n\t    disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\t    menuPtr->disabledFgPtr);\n\t    gcValues.foreground = disabledFg->pixel;\n\t    mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;\n\t} else {\n\t    gcValues.foreground = gcValues.background;\n\t    gcValues.fill_style = FillStippled;\n\t    gcValues.stipple = menuPtr->gray;\n\t    mask = GCForeground|GCFillStyle|GCStipple;\n\t}\n\tnewDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);\n\n\tactiveFg = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\t(mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr\n\t\t: menuPtr->activeFgPtr);\n\tactiveBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t\t(mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr\n\t\t: menuPtr->activeBorderPtr);\n\n\tgcValues.foreground = activeFg->pixel;\n\tgcValues.background = Tk_3DBorderColor(activeBorder)->pixel;\n\tnewActiveGC = Tk_GetGC(menuPtr->tkwin,\n\t\tGCForeground|GCBackground|GCFont|GCGraphicsExposures,\n\t\t&gcValues);\n    } else {\n\tnewGC = NULL;\n\tnewActiveGC = NULL;\n\tnewDisabledGC = NULL;\n\tnewIndicatorGC = NULL;\n    }\n    if (mePtr->textGC != NULL) {\n\tTk_FreeGC(menuPtr->display, mePtr->textGC);\n    }\n    mePtr->textGC = newGC;\n    if (mePtr->activeGC != NULL) {\n\tTk_FreeGC(menuPtr->display, mePtr->activeGC);\n    }\n    mePtr->activeGC = newActiveGC;\n    if (mePtr->disabledGC != NULL) {\n\tTk_FreeGC(menuPtr->display, mePtr->disabledGC);\n    }\n    mePtr->disabledGC = newDisabledGC;\n    if (mePtr->indicatorGC != NULL) {\n\tTk_FreeGC(menuPtr->display, mePtr->indicatorGC);\n    }\n    mePtr->indicatorGC = newIndicatorGC;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkEventuallyRecomputeMenu --\n *\n *\tTells Tcl to redo the geometry because this menu has changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMenu geometry is recomputed at idle time, and the menu will be\n *\tredisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkEventuallyRecomputeMenu(\n    TkMenu *menuPtr)\n{\n    if (!(menuPtr->menuFlags & RESIZE_PENDING)) {\n\tmenuPtr->menuFlags |= RESIZE_PENDING;\n\tTcl_DoWhenIdle(ComputeMenuGeometry, menuPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkRecomputeMenu --\n *\n *\tTells Tcl to redo the geometry because this menu has changed. Does it\n *\tnow; removes any ComputeMenuGeometries from the idler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMenu geometry is immediately reconfigured.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkRecomputeMenu(\n    TkMenu *menuPtr)\n{\n    if (menuPtr->menuFlags & RESIZE_PENDING) {\n\tTcl_CancelIdleCall(ComputeMenuGeometry, menuPtr);\n\tComputeMenuGeometry(menuPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkEventuallyRedrawMenu --\n *\n *\tArrange for an entry of a menu, or the whole menu, to be redisplayed\n *\tat some point in the future.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA when-idle handler is scheduled to do the redisplay, if there isn't\n *\tone already scheduled.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkEventuallyRedrawMenu(\n    TkMenu *menuPtr,\t/* Information about menu to redraw. */\n    TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the\n\t\t\t\t * entries in the menu. */\n{\n    Tcl_Size i;\n\n    if (menuPtr->tkwin == NULL) {\n\treturn;\n    }\n    if (mePtr != NULL) {\n\tmePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY;\n    } else {\n\tfor (i = 0; i < menuPtr->numEntries; i++) {\n\t    menuPtr->entries[i]->entryFlags |= ENTRY_NEEDS_REDISPLAY;\n\t}\n    }\n    if (!Tk_IsMapped(menuPtr->tkwin)\n\t    || (menuPtr->menuFlags & REDRAW_PENDING)) {\n\treturn;\n    }\n    Tcl_DoWhenIdle(DisplayMenu, menuPtr);\n    menuPtr->menuFlags |= REDRAW_PENDING;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeMenuGeometry --\n *\n *\tThis function is invoked to recompute the size and layout of a menu.\n *\tIt is called as a when-idle handler so that it only gets done once,\n *\teven if a group of changes is made to the menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeMenuGeometry(\n    void *clientData)\t/* Structure describing menu. */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n\n    if (menuPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    if (menuPtr->menuType == MENUBAR) {\n\tTkpComputeMenubarGeometry(menuPtr);\n    } else {\n\tTkpComputeStandardMenuGeometry(menuPtr);\n    }\n\n    if ((menuPtr->totalWidth != Tk_ReqWidth(menuPtr->tkwin)) ||\n\t    (menuPtr->totalHeight != Tk_ReqHeight(menuPtr->tkwin))) {\n\tTk_GeometryRequest(menuPtr->tkwin, menuPtr->totalWidth,\n\t\tmenuPtr->totalHeight);\n    }\n\n    /*\n     * Must always force a redisplay here if the window is mapped (even if the\n     * size didn't change, something else might have changed in the menu, such\n     * as a label or accelerator). The resize will force a redisplay above.\n     */\n\n    TkEventuallyRedrawMenu(menuPtr, NULL);\n\n    menuPtr->menuFlags &= ~RESIZE_PENDING;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuSelectImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size of contents of an image\n *\tdisplayed in a menu entry when it is selected.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the menu to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuSelectImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int), /* Upper left pixel (within image) that must */\n    TCL_UNUSED(int), /* be redisplayed. */\n    TCL_UNUSED(int), /* Dimensions of area to redisplay (may be */\n    TCL_UNUSED(int), /* <= 0). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))/* New dimensions of image. */\n{\n    TkMenuEntry *mePtr = (TkMenuEntry *)clientData;\n\n    if ((mePtr->entryFlags & ENTRY_SELECTED)\n\t    && !(mePtr->menuPtr->menuFlags & REDRAW_PENDING)) {\n\tmePtr->menuPtr->menuFlags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayMenu, mePtr->menuPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayMenu --\n *\n *\tThis function is invoked to display a menu widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayMenu(\n    void *clientData)\t/* Information about widget. */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n    TkMenuEntry *mePtr;\n    Tk_Window tkwin = menuPtr->tkwin;\n    Tcl_Size index;\n    Tk_Font tkfont;\n    Tk_FontMetrics menuMetrics;\n    int width;\n    int borderWidth;\n    Tk_3DBorder border;\n\n\n    menuPtr->menuFlags &= ~REDRAW_PENDING;\n    if ((menuPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t    &borderWidth);\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n\n    if (menuPtr->menuType == MENUBAR) {\n\tTk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth,\n\t\tborderWidth, Tk_Width(tkwin) - 2 * borderWidth,\n\t\tTk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT);\n    }\n\n    DrawMenuFlags drawingParameters = DRAW_MENU_ENTRY_ARROW;\n    if (Tk_StrictMotif(menuPtr->tkwin)) {\n\tdrawingParameters = (DrawMenuFlags)(drawingParameters | DRAW_MENU_ENTRY_STRICTMOTIF);\n    }\n\n    /*\n     * See note in ComputeMenuGeometry. We don't want to be doing font metrics\n     * all of the time.\n     */\n\n    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n    Tk_GetFontMetrics(tkfont, &menuMetrics);\n\n    /*\n     * Loop through all of the entries, drawing them one at a time.\n     */\n\n    for (index = 0; index < menuPtr->numEntries; index++) {\n\tmePtr = menuPtr->entries[index];\n\tif (menuPtr->menuType != MENUBAR) {\n\t    if (!(mePtr->entryFlags & ENTRY_NEEDS_REDISPLAY)) {\n\t\tcontinue;\n\t    }\n\t}\n\tmePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY;\n\n\tTkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,\n\t\t&menuMetrics, mePtr->x, mePtr->y, mePtr->width,\n\t\tmePtr->height, drawingParameters);\n\n\tif (mePtr->entryFlags & ENTRY_LAST_COLUMN) {\n\n\t    /*\n\t     * Paint the area at the right of an entry in the last column.\n\t     * This has zero width except after menu resizing.\n\t     */\n\n\t    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,\n\t\t    mePtr->x + mePtr->width, mePtr->y,\n\t\t    Tk_Width(tkwin) - mePtr->x - mePtr->width - borderWidth,\n\t\t    mePtr->height, 0, TK_RELIEF_FLAT);\n\t}\n\n\tif ((index > 0) && (menuPtr->menuType != MENUBAR)\n\t\t&& mePtr->columnBreak) {\n\n\t    /*\n\t     * Paint the area under the last entry in a column.\n\t     */\n\n\t    mePtr = menuPtr->entries[index - 1];\n\t    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,\n\t\tmePtr->x, mePtr->y + mePtr->height, mePtr->width,\n\t\tTk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,\n\t\t0, TK_RELIEF_FLAT);\n\t}\n    }\n\n    if (menuPtr->menuType != MENUBAR) {\n\tint x, y, height;\n\n\tif (menuPtr->numEntries == 0) {\n\t    x = y = borderWidth;\n\t    width = Tk_Width(tkwin) - 2 * borderWidth;\n\t    height = Tk_Height(tkwin) - 2 * borderWidth;\n\t} else {\n\t    mePtr = menuPtr->entries[menuPtr->numEntries - 1];\n\n\t    /*\n\t     * Paint the area under the last entry of the menu.\n\t     */\n\n\t    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),\n\t\tborder, mePtr->x, mePtr->y + mePtr->height, mePtr->width,\n\t\tTk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,\n\t\t0, TK_RELIEF_FLAT);\n\t    x = mePtr->x + mePtr->width;\n\t    y = mePtr->y + mePtr->height;\n\t    width = Tk_Width(tkwin) - x - borderWidth;\n\t    height = Tk_Height(tkwin) - y - borderWidth;\n\t}\n\n\t/*\n\t * Paint the area at the bottom right of the last entry.\n\t * This has zero width except after menu resizing.\n\t */\n\n\tTk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y,\n\t\twidth, height, 0, TK_RELIEF_FLAT);\n    }\n\n    Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin),\n\t    border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,\n\t    menuPtr->relief);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMenuEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tmenus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkMenuEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tTkEventuallyRedrawMenu(menuPtr, NULL);\n    } else if (eventPtr->type == ConfigureNotify) {\n\tTkEventuallyRecomputeMenu(menuPtr);\n\tTkEventuallyRedrawMenu(menuPtr, NULL);\n    } else if (eventPtr->type == ActivateNotify) {\n\tif (menuPtr->menuType == TEAROFF_MENU) {\n\t    Tk_SetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tif (menuPtr->tkwin != NULL) {\n\t    if (!(menuPtr->menuFlags & MENU_DELETION_PENDING)) {\n\t\tTkDestroyMenu(menuPtr);\n\t    }\n\t    menuPtr->tkwin = NULL;\n\t}\n\tif (menuPtr->menuFlags & MENU_WIN_DESTRUCTION_PENDING) {\n\t    return;\n\t}\n\tmenuPtr->menuFlags |= MENU_WIN_DESTRUCTION_PENDING;\n\tif (menuPtr->widgetCmd != NULL) {\n\t    Tcl_DeleteCommandFromToken(menuPtr->interp, menuPtr->widgetCmd);\n\t    menuPtr->widgetCmd = NULL;\n\t}\n\tif (menuPtr->menuFlags & REDRAW_PENDING) {\n\t    Tcl_CancelIdleCall(DisplayMenu, menuPtr);\n\t    menuPtr->menuFlags &= ~REDRAW_PENDING;\n\t}\n\tif (menuPtr->menuFlags & RESIZE_PENDING) {\n\t    Tcl_CancelIdleCall(ComputeMenuGeometry, menuPtr);\n\t    menuPtr->menuFlags &= ~RESIZE_PENDING;\n\t}\n\tTcl_EventuallyFree(menuPtr, TCL_DYNAMIC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMenuImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size of contents of an image\n *\tdisplayed in a menu entry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the menu to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMenuImageProc(\n    void *clientData,/* Pointer to widget record. */\n    TCL_UNUSED(int), /* Upper left pixel (within image) that must */\n    TCL_UNUSED(int), /*\t\t * be redisplayed. */\n    TCL_UNUSED(int), /* Dimensions of area to redisplay (may be */\n    TCL_UNUSED(int), /* <=0). */\n    TCL_UNUSED(int), /* New dimensions of image. */\n    TCL_UNUSED(int))\n{\n    TkMenu *menuPtr = (TkMenu *)((TkMenuEntry *) clientData)->menuPtr;\n\n    if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags & RESIZE_PENDING)) {\n\tmenuPtr->menuFlags |= RESIZE_PENDING;\n\tTcl_DoWhenIdle(ComputeMenuGeometry, menuPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPostTearoffMenu --\n *\n *\tPosts a tearoff menu on the screen. Adjusts the menu's position so\n *\tthat it fits on the screen, and maps and raises the menu.\n *\n * Results:\n *\tReturns a standard Tcl Error.\n *\n * Side effects:\n *\tThe menu is posted.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPostTearoffMenu(\n    Tcl_Interp *interp,\t\t/* The interpreter of the menu */\n    TkMenu *menuPtr,\t\t/* The menu we are posting */\n    int x, int y)\t\t/* The root X,Y coordinates where we are\n\t\t\t\t * posting */\n{\n    return TkpPostTearoffMenu(interp, menuPtr, x, y, -1);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkPostSubmenu --\n *\n *\tThis function arranges for a particular submenu (i.e. the menu\n *\tcorresponding to a given cascade entry) to be posted.\n *\n * Results:\n *\tA standard Tcl return result. Errors may occur in the Tcl commands\n *\tgenerated to post and unpost submenus.\n *\n * Side effects:\n *\tIf there is already a submenu posted, it is unposted. The new submenu\n *\tis then posted.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkPostSubmenu(\n    Tcl_Interp *interp,\t\t/* Used for invoking sub-commands and\n\t\t\t\t * reporting errors. */\n    TkMenu *menuPtr,\t/* Information about menu as a whole. */\n    TkMenuEntry *mePtr)/* Info about submenu that is to be posted.\n\t\t\t\t * NULL means make sure that no submenu is\n\t\t\t\t * posted. */\n{\n    int result, x, y;\n    Tcl_Obj *subary[4];\n\n    if (mePtr == menuPtr->postedCascade) {\n\treturn TCL_OK;\n    }\n\n    if (menuPtr->postedCascade != NULL) {\n\t/*\n\t * Note: when unposting a submenu, we have to redraw the entire parent\n\t * menu. This is because of a combination of the following things:\n\t * (a) the submenu partially overlaps the parent.\n\t * (b) the submenu specifies \"save under\", which causes the X server\n\t *     to make a copy of the information under it when it is posted.\n\t *     When the submenu is unposted, the X server copies this data\n\t *     back and doesn't generate any Expose events for the parent.\n\t * (c) the parent may have redisplayed itself after the submenu was\n\t *     posted, in which case the saved information is no longer\n\t *     correct.\n\t * The simplest solution is just force a complete redisplay of the\n\t * parent.\n\t */\n\n\tsubary[0] = menuPtr->postedCascade->namePtr;\n\tsubary[1] = Tcl_NewStringObj(\"unpost\", TCL_INDEX_NONE);\n\tTcl_IncrRefCount(subary[1]);\n\tTkEventuallyRedrawMenu(menuPtr, NULL);\n\tresult = Tcl_EvalObjv(interp, 2, subary, 0);\n\tTcl_DecrRefCount(subary[1]);\n\tmenuPtr->postedCascade = NULL;\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n\n    if ((mePtr != NULL) && (mePtr->namePtr != NULL)\n\t    && Tk_IsMapped(menuPtr->tkwin)) {\n\t/*\n\t * Position the cascade with its upper left corner slightly below and\n\t * to the left of the upper right corner of the menu entry (this is an\n\t * attempt to match Motif behavior).\n\t *\n\t * The menu has to redrawn so that the entry can change relief.\n\t *\n\t * Set postedCascade early to ensure tear-off submenus work on\n\t * Windows. [Bug 873613]\n\t */\n\n\tTk_GetRootCoords(menuPtr->tkwin, &x, &y);\n\tAdjustMenuCoords(menuPtr, mePtr, &x, &y);\n\n\tmenuPtr->postedCascade = mePtr;\n\tsubary[0] = mePtr->namePtr;\n\tsubary[1] = Tcl_NewStringObj(\"post\", TCL_INDEX_NONE);\n\tsubary[2] = Tcl_NewWideIntObj(x);\n\tsubary[3] = Tcl_NewWideIntObj(y);\n\tTcl_IncrRefCount(subary[1]);\n\tTcl_IncrRefCount(subary[2]);\n\tTcl_IncrRefCount(subary[3]);\n\tresult = Tcl_EvalObjv(interp, 4, subary, 0);\n\tTcl_DecrRefCount(subary[1]);\n\tTcl_DecrRefCount(subary[2]);\n\tTcl_DecrRefCount(subary[3]);\n\tif (result != TCL_OK) {\n\t    menuPtr->postedCascade = NULL;\n\t    return result;\n\t}\n\tTkEventuallyRedrawMenu(menuPtr, mePtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustMenuCoords --\n *\n *\tAdjusts the given coordinates down and the left to give a Motif look.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu is eventually redrawn if necessary.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAdjustMenuCoords(\n    TkMenu *menuPtr,\n    TkMenuEntry *mePtr,\n    int *xPtr,\n    int *yPtr)\n{\n    if (menuPtr->menuType == MENUBAR) {\n\t*xPtr += mePtr->x;\n\t*yPtr += mePtr->y + mePtr->height;\n    } else {\n\tint borderWidth, activeBorderWidth;\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint scaled2 = (int)round(2*scalingLevel);\n\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t\t&borderWidth);\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\t*xPtr += Tk_Width(menuPtr->tkwin) - borderWidth\t- activeBorderWidth\n\t\t- scaled2;\n\t*yPtr += mePtr->y + activeBorderWidth + scaled2;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMenubutton.c",
    "content": "/*\n * tkMenubutton.c --\n *\n *\tThis module implements button-like widgets that are used to invoke\n *\tpull-down menus.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkMenubutton.h\"\n\n/*\n * The structure below defines menubutton class behavior by means of\n * procedures that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs menubuttonClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TkMenuButtonWorldChanged,\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n/*\n * The following table defines the legal values for the -direction option. It\n * is used together with the \"enum direction\" declaration in tkMenubutton.h.\n */\n\nstatic const char *const directionStrings[] = {\n    \"above\", \"below\", \"flush\", \"left\", \"right\", NULL\n};\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_MENUBUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE,\n\toffsetof(TkMenuButton, activeBorder), 0,\n\tDEF_MENUBUTTON_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-activeforeground\", \"activeForeground\", \"Background\",\n\tDEF_MENUBUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE,\n\toffsetof(TkMenuButton, activeFg),\n\t0, DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\tDEF_MENUBUTTON_ANCHOR, TCL_INDEX_NONE,\n\toffsetof(TkMenuButton, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_MENUBUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkMenuButton, normalBorder),\n\t0, DEF_MENUBUTTON_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL, NULL, 0, TCL_INDEX_NONE,\n\t0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL, NULL, 0, TCL_INDEX_NONE,\n\t0, \"-background\", 0},\n    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\",\n\tDEF_MENUBUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkMenuButton, bitmap),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_MENUBUTTON_BORDER_WIDTH, offsetof(TkMenuButton, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_MENUBUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkMenuButton, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-direction\", \"direction\", \"Direction\",\n\tDEF_MENUBUTTON_DIRECTION, TCL_INDEX_NONE, offsetof(TkMenuButton, direction),\n\tTK_OPTION_ENUM_VAR, directionStrings, 0},\n    {TK_OPTION_COLOR, \"-disabledforeground\", \"disabledForeground\",\n\t\"DisabledForeground\", DEF_MENUBUTTON_DISABLED_FG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,\n\tDEF_MENUBUTTON_DISABLED_FG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL, NULL, 0, TCL_INDEX_NONE,\n\t0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_MENUBUTTON_FONT, TCL_INDEX_NONE, offsetof(TkMenuButton, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_MENUBUTTON_FG, TCL_INDEX_NONE, offsetof(TkMenuButton, normalFg), 0, 0, 0},\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_MENUBUTTON_HEIGHT, offsetof(TkMenuButton, heightObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkMenuButton, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_MENUBUTTON_HIGHLIGHT, TCL_INDEX_NONE,\n\toffsetof(TkMenuButton, highlightColorPtr),\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,\n\toffsetof(TkMenuButton, highlightWidthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tDEF_MENUBUTTON_IMAGE, offsetof(TkMenuButton, imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-indicatoron\", \"indicatorOn\", \"IndicatorOn\",\n\tDEF_MENUBUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkMenuButton, indicatorOn),\n\tTK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_MENUBUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkMenuButton, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_STRING, \"-menu\", \"menu\", \"Menu\",\n\tDEF_MENUBUTTON_MENU, offsetof(TkMenuButton, menuNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\tDEF_MENUBUTTON_PADX, offsetof(TkMenuButton, padXObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\tDEF_MENUBUTTON_PADY, offsetof(TkMenuButton, padYObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_MENUBUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkMenuButton, relief),\n\t0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tDEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkMenuButton, compound),\n\t0, tkCompoundStrings, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_MENUBUTTON_STATE, TCL_INDEX_NONE, offsetof(TkMenuButton, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_MENUBUTTON_TAKE_FOCUS, offsetof(TkMenuButton, takeFocusObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_MENUBUTTON_TEXT, offsetof(TkMenuButton, textObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_MENUBUTTON_TEXT_VARIABLE, offsetof(TkMenuButton, textVarNameObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTK_OPTION_UNDERLINE_DEF(TkMenuButton, underline), 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tDEF_MENUBUTTON_WIDTH, offsetof(TkMenuButton, widthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tDEF_MENUBUTTON_WRAP_LENGTH, offsetof(TkMenuButton, wrapLengthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n};\n\n/*\n * The following tables define the menubutton widget commands and map the\n * indexes into the string tables into a single enumerated type used to\n * dispatch the scale widget command.\n */\n\nstatic const char *const commandNames[] = {\n    \"cget\", \"configure\", NULL\n};\n\nenum command {\n    COMMAND_CGET, COMMAND_CONFIGURE\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tMenuButtonCmdDeletedProc(void *clientData);\nstatic void\t\tMenuButtonEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tMenuButtonImageProc(void *clientData,\n\t\t\t    int x, int y, int width, int height, int imgWidth,\n\t\t\t    int imgHeight);\nstatic char *\t\tMenuButtonTextVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic Tcl_ObjCmdProc2 MenuButtonWidgetObjCmd;\nstatic int\t\tConfigureMenuButton(Tcl_Interp *interp,\n\t\t\t    TkMenuButton *mbPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tDestroyMenuButton(void *memPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_MenubuttonObjCmd --\n *\n *\tThis function is invoked to process the \"button\", \"label\",\n *\t\"radiobutton\", and \"checkbutton\" Tcl commands. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_MenubuttonObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkMenuButton *mbPtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the new window.\n     */\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    Tk_SetClass(tkwin, \"Menubutton\");\n    mbPtr = TkpCreateMenuButton(tkwin);\n\n    Tk_SetClassProcs(tkwin, &menubuttonClass, mbPtr);\n\n    /*\n     * Initialize the data structure for the button.\n     */\n\n    mbPtr->tkwin = tkwin;\n    mbPtr->display = Tk_Display(tkwin);\n    mbPtr->interp = interp;\n    mbPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd, mbPtr,\n\t    MenuButtonCmdDeletedProc);\n    mbPtr->optionTable = optionTable;\n    mbPtr->menuNameObj = NULL;\n    mbPtr->textObj = NULL;\n    mbPtr->underline = INT_MIN;\n    mbPtr->textVarNameObj = NULL;\n    mbPtr->bitmap = None;\n    mbPtr->imageObj = NULL;\n    mbPtr->image = NULL;\n    mbPtr->state = STATE_NORMAL;\n    mbPtr->normalBorder = NULL;\n    mbPtr->activeBorder = NULL;\n    mbPtr->borderWidthObj = NULL;\n    mbPtr->relief = TK_RELIEF_FLAT;\n    mbPtr->highlightWidthObj = 0;\n    mbPtr->highlightBgColorPtr = NULL;\n    mbPtr->highlightColorPtr = NULL;\n    mbPtr->inset = 0;\n    mbPtr->tkfont = NULL;\n    mbPtr->normalFg = NULL;\n    mbPtr->activeFg = NULL;\n    mbPtr->disabledFg = NULL;\n    mbPtr->normalTextGC = NULL;\n    mbPtr->activeTextGC = NULL;\n    mbPtr->gray = None;\n    mbPtr->disabledGC = NULL;\n    mbPtr->stippleGC = NULL;\n    mbPtr->leftBearing = 0;\n    mbPtr->rightBearing = 0;\n    mbPtr->widthObj = NULL;\n    mbPtr->heightObj = NULL;\n    mbPtr->width = 0;\n    mbPtr->height = 0;\n    mbPtr->wrapLengthObj = 0;\n    mbPtr->padXObj = NULL;\n    mbPtr->padYObj = NULL;\n    mbPtr->anchor = TK_ANCHOR_CENTER;\n    mbPtr->justify = TK_JUSTIFY_CENTER;\n    mbPtr->textLayout = NULL;\n    mbPtr->indicatorOn = false;\n    mbPtr->indicatorWidth = 0;\n    mbPtr->indicatorHeight = 0;\n    mbPtr->direction = DIRECTION_FLUSH;\n    mbPtr->cursor = NULL;\n    mbPtr->takeFocusObj = NULL;\n    mbPtr->flags = 0;\n\n    Tk_CreateEventHandler(mbPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    MenuButtonEventProc, mbPtr);\n\n    if (Tk_InitOptions(interp, mbPtr, optionTable, tkwin) != TCL_OK) {\n\tTk_DestroyWindow(mbPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {\n\tTk_DestroyWindow(mbPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(mbPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMenuButtonWidgetObjCmd(\n    void *clientData,\t/* Information about button widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n    int result, index;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames,\n\t    sizeof(char *), \"option\", 0, &index);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    Tcl_Preserve(mbPtr);\n\n    switch (index) {\n    case COMMAND_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"cget option\");\n\t    goto error;\n\t}\n\n\tobjPtr = Tk_GetOptionValue(interp, mbPtr,\n\t\tmbPtr->optionTable, objv[2], mbPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n\n    case COMMAND_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, mbPtr,\n\t\t    mbPtr->optionTable, (objc == 3) ? objv[2] : NULL,\n\t\t    mbPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureMenuButton(interp, mbPtr, objc-2, objv+2);\n\t}\n\tbreak;\n    }\n    Tcl_Release(mbPtr);\n    return result;\n\n  error:\n    Tcl_Release(mbPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyMenuButton --\n *\n *\tThis function is invoked to recycle all of the resources associated\n *\twith a menubutton widget. It is invoked as a when-idle handler in\n *\torder to make sure that there is no other use of the menubutton\n *\tpending at the time of the deletion.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the widget is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyMenuButton(\n    void *memPtr)\t\t/* Info about button widget. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)memPtr;\n    TkpDestroyMenuButton(mbPtr);\n\n    if (mbPtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(TkpDisplayMenuButton, mbPtr);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);\n    if (mbPtr->textVarNameObj != NULL) {\n\tTcl_UntraceVar2(mbPtr->interp, Tcl_GetString(mbPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuButtonTextVarProc, mbPtr);\n    }\n    if (mbPtr->image != NULL) {\n\tTk_FreeImage(mbPtr->image);\n    }\n    if (mbPtr->normalTextGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->normalTextGC);\n    }\n    if (mbPtr->activeTextGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->activeTextGC);\n    }\n    if (mbPtr->disabledGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->disabledGC);\n    }\n    if (mbPtr->stippleGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->stippleGC);\n    }\n    if (mbPtr->gray != None) {\n\tTk_FreeBitmap(mbPtr->display, mbPtr->gray);\n    }\n    if (mbPtr->textLayout != NULL) {\n\tTk_FreeTextLayout(mbPtr->textLayout);\n    }\n    Tk_FreeConfigOptions(mbPtr, mbPtr->optionTable, mbPtr->tkwin);\n    mbPtr->tkwin = NULL;\n    Tcl_EventuallyFree(mbPtr, TCL_DYNAMIC);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureMenuButton --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a menubutton\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as text string, colors, font, etc. get\n *\tset for mbPtr; old resources get freed, if there were any. The\n *\tmenubutton is redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureMenuButton(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkMenuButton *mbPtr,\n\t\t\t\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments. */\n{\n    Tk_SavedOptions savedOptions;\n    Tcl_Obj *errorResult = NULL;\n    int error;\n    Tk_Image image;\n\n    /*\n     * Eliminate any existing trace on variables monitored by the menubutton.\n     */\n\n    if (mbPtr->textVarNameObj != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuButtonTextVarProc, mbPtr);\n    }\n\n    /*\n     * The following loop is potentially executed twice. During the first pass\n     * configuration options get set to their new values. If there is an error\n     * in this pass, we execute a second pass to restore all the options to\n     * their previous values.\n     */\n\n    for (error = 0; error <= 1; error++) {\n\tif (!error) {\n\t    /*\n\t     * First pass: set options to new values.\n\t     */\n\n\t    if (Tk_SetOptions(interp, mbPtr,\n\t\t    mbPtr->optionTable, objc, objv,\n\t\t    mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * Second pass: restore options to old values.\n\t     */\n\n\t    errorResult = Tcl_GetObjResult(interp);\n\t    Tcl_IncrRefCount(errorResult);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t}\n\n\t/*\n\t * A few options need special processing, such as setting the\n\t * background from a 3-D border, or filling in complicated defaults\n\t * that couldn't be specified to Tk_SetOptions.\n\t */\n\n\tif ((mbPtr->state == STATE_ACTIVE)\n\t\t&& !Tk_StrictMotif(mbPtr->tkwin)) {\n\t    Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);\n\t} else {\n\t    Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);\n\t}\n\n\t/*\n\t * Get the image for the widget, if there is one. Allocate the new\n\t * image before freeing the old one, so that the reference count\n\t * doesn't go to zero and cause image data to be discarded.\n\t */\n\n\tif (mbPtr->imageObj != NULL) {\n\t    image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,\n\t\t    Tcl_GetString(mbPtr->imageObj), MenuButtonImageProc, mbPtr);\n\t    if (image == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    image = NULL;\n\t}\n\tif (mbPtr->image != NULL) {\n\t    Tk_FreeImage(mbPtr->image);\n\t}\n\tmbPtr->image = image;\n\n\t/*\n\t * Recompute the geometry for the button.\n\t */\n\n\tif ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {\n\t    if (Tk_GetPixelsFromObj(interp, mbPtr->tkwin, mbPtr->widthObj,\n\t\t    &mbPtr->width) != TCL_OK) {\n\t    widthError:\n\t\tTcl_AddErrorInfo(interp, \"\\n    (processing \\\"-width\\\" option)\");\n\t\tcontinue;\n\t    }\n\t    if (Tk_GetPixelsFromObj(interp, mbPtr->tkwin, mbPtr->heightObj,\n\t\t    &mbPtr->height) != TCL_OK) {\n\t    heightError:\n\t\tTcl_AddErrorInfo(interp, \"\\n    (processing \\\"-height\\\" option)\");\n\t\tcontinue;\n\t    }\n\t} else {\n\t    if (Tcl_GetIntFromObj(interp, mbPtr->widthObj, &mbPtr->width)\n\t\t    != TCL_OK) {\n\t\tgoto widthError;\n\t    }\n\t    if (Tcl_GetIntFromObj(interp, mbPtr->heightObj, &mbPtr->height)\n\t\t    != TCL_OK) {\n\t\tgoto heightError;\n\t    }\n\t}\n\tbreak;\n    }\n\n    if (!error) {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n\n    if (mbPtr->textVarNameObj != NULL) {\n\t/*\n\t * If no image or -compound is used, display the value of a variable.\n\t * Set up a trace to watch for any changes in it, create the variable\n\t * if it doesn't exist, and fetch its current value.\n\t */\n\tconst char *value;\n\n\tvalue = Tcl_GetVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n\tif (value == NULL) {\n\t    Tcl_SetVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL, mbPtr->textObj ? Tcl_GetString(mbPtr->textObj) : \"\",\n\t\t    TCL_GLOBAL_ONLY);\n\t} else {\n\t    if (mbPtr->textObj != NULL) {\n\t\tTcl_DecrRefCount(mbPtr->textObj);\n\t    }\n\t    mbPtr->textObj = Tcl_NewStringObj(value, TCL_INDEX_NONE);\n\t    Tcl_IncrRefCount(mbPtr->textObj);\n\t}\n\tTcl_TraceVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMenuButtonTextVarProc, mbPtr);\n    }\n\n    TkMenuButtonWorldChanged(mbPtr);\n    if (error) {\n\tTcl_SetObjResult(interp, errorResult);\n\tTcl_DecrRefCount(errorResult);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkMenuButtonWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTkMenuButton will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkMenuButtonWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC gc;\n    unsigned long mask;\n    TkMenuButton *mbPtr = (TkMenuButton *)instanceData;\n\n    gcValues.font = Tk_FontId(mbPtr->tkfont);\n    gcValues.foreground = mbPtr->normalFg->pixel;\n    gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;\n\n    /*\n     * Note: GraphicsExpose events are disabled in GC's because they're used\n     * to copy stuff from an off-screen pixmap onto the screen (we know that\n     * there's no problem with obscured areas).\n     */\n\n    gcValues.graphics_exposures = False;\n    mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;\n    gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);\n    if (mbPtr->normalTextGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->normalTextGC);\n    }\n    mbPtr->normalTextGC = gc;\n\n    gcValues.foreground = mbPtr->activeFg->pixel;\n    gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;\n    mask = GCForeground | GCBackground | GCFont;\n    gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);\n    if (mbPtr->activeTextGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->activeTextGC);\n    }\n    mbPtr->activeTextGC = gc;\n\n    gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;\n\n    /*\n     * Create the GC that can be used for stippling\n     */\n\n    if (mbPtr->stippleGC == NULL) {\n\tgcValues.foreground = gcValues.background;\n\tmask = GCForeground;\n\tif (mbPtr->gray == None) {\n\t    mbPtr->gray = Tk_GetBitmap(NULL, mbPtr->tkwin, \"gray50\");\n\t}\n\tif (mbPtr->gray != None) {\n\t    gcValues.fill_style = FillStippled;\n\t    gcValues.stipple = mbPtr->gray;\n\t    mask |= GCFillStyle | GCStipple;\n\t}\n\tmbPtr->stippleGC = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);\n    }\n\n    /*\n     * Allocate the disabled graphics context, for drawing text in its\n     * disabled state.\n     */\n\n    mask = GCForeground | GCBackground | GCFont;\n    if (mbPtr->disabledFg != NULL) {\n\tgcValues.foreground = mbPtr->disabledFg->pixel;\n    } else {\n\tgcValues.foreground = gcValues.background;\n    }\n    gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);\n    if (mbPtr->disabledGC != NULL) {\n\tTk_FreeGC(mbPtr->display, mbPtr->disabledGC);\n    }\n    mbPtr->disabledGC = gc;\n\n    TkpComputeMenuButtonGeometry(mbPtr);\n\n    /*\n     * Lastly, arrange for the button to be redisplayed.\n     */\n\n    if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);\n\tmbPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tbuttons.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMenuButtonEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n    int highlightWidth;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tgoto redraw;\n    } else if (eventPtr->type == ConfigureNotify) {\n\t/*\n\t * Must redraw after size changes, since layout could have changed and\n\t * borders will need to be redrawn.\n\t */\n\n\tgoto redraw;\n    } else if (eventPtr->type == DestroyNotify) {\n\tDestroyMenuButton(mbPtr);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    mbPtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    mbPtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    }\n    return;\n\n  redraw:\n    if ((mbPtr->tkwin != NULL) && !(mbPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);\n\tmbPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuButtonCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuButtonCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n    Tk_Window tkwin = mbPtr->tkwin;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonTextVarProc --\n *\n *\tThis function is invoked when someone changes the variable whose\n *\tcontents are to be displayed in a menu button.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe text displayed in the menu button will change to match the\n *\tvariable.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nMenuButtonTextVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t\t/* Name of variable. */\n    TCL_UNUSED(const char *),\t\t/* Second part of variable name. */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n    const char *value;\n\n    /*\n     * If the variable is unset, then immediately recreate it unless the whole\n     * interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tif (!Tcl_InterpDeleted(interp) && mbPtr->textVarNameObj) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(mbPtr->textVarNameObj),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tMenuButtonTextVarProc, probe);\n\t\tif (probe == (void *)mbPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * textVarName, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t    Tcl_SetVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL, mbPtr->textObj ? Tcl_GetString(mbPtr->textObj) : \"\",\n\t\t    TCL_GLOBAL_ONLY);\n\t    Tcl_TraceVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL,\n\t\t    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    MenuButtonTextVarProc, clientData);\n\t}\n\treturn NULL;\n    }\n\n    value = Tcl_GetVar2(interp, Tcl_GetString(mbPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n    if (value == NULL) {\n\tvalue = \"\";\n    }\n    if (mbPtr->textObj != NULL) {\n\tTcl_DecrRefCount(mbPtr->textObj);\n    }\n    mbPtr->textObj= Tcl_NewStringObj(value, TCL_INDEX_NONE);\n\tTcl_IncrRefCount(mbPtr->textObj);\n    TkpComputeMenuButtonGeometry(mbPtr);\n\n    if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin)\n\t    && !(mbPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);\n\tmbPtr->flags |= REDRAW_PENDING;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuButtonImageProc --\n *\n *\tThis function is invoked by the image code whenever the manager for an\n *\timage does something that affects the size of contents of an image\n *\tdisplayed in a button.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the button to get redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuButtonImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int),\t/* x, Upper left pixel (within image) that must */\n    TCL_UNUSED(int),\t/* y, be redisplayed. */\n    TCL_UNUSED(int),\t/* width, Dimensions of area to redisplay (may be <= */\n    TCL_UNUSED(int),\t/* height, 0). */\n    TCL_UNUSED(int),\t/* imgWidth, New dimensions of image. */\n    TCL_UNUSED(int))\t/* imgHeight */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n\n    if (mbPtr->tkwin != NULL) {\n\tTkpComputeMenuButtonGeometry(mbPtr);\n\tif (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);\n\t    mbPtr->flags |= REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkMenubutton.h",
    "content": "/*\n * tkMenubutton.h --\n *\n *\tDeclarations of types and functions used to implement the menubutton\n *\twidget.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMENUBUTTON\n#define _TKMENUBUTTON\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n#ifndef _TKMENU\n#include \"tkMenu.h\"\n#endif\n\n/*\n * Legal values for the \"orient\" field of TkMenubutton records.\n */\n\nenum direction {\n    DIRECTION_ABOVE, DIRECTION_BELOW, DIRECTION_FLUSH,\n    DIRECTION_LEFT, DIRECTION_RIGHT\n};\n\n/*\n * Legal values for the \"state\" field of TkMenubutton records.\n */\n\nenum state {\n    STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL\n};\n\n/*\n * A data structure of the following type is kept for each widget managed by\n * this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the widget. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up. */\n    Display *display;\t\t/* Display containing widget. Needed, among\n\t\t\t\t * other things, so that resources can bee\n\t\t\t\t * freed up even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with menubutton. */\n    Tcl_Command widgetCmd;\t/* Token for menubutton's widget command. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n    Tcl_Obj *menuNameObj;\t\t/* Name of menu associated with widget. */\n\n    /*\n     * Information about what's displayed in the menu button:\n     */\n\n    Tcl_Obj *textObj;\t\t\t/* Text to display in button. May be NULL. */\n    int underline;\t\t/* Index of character to underline. INT_MIN means no underline */\n    Tcl_Obj *textVarNameObj;\t/* Name of variable or NULL. If\n\t\t\t\t * non-NULL, button displays the contents of\n\t\t\t\t * this variable. */\n    Pixmap bitmap;\t\t/* Bitmap to display or None. If not None then\n\t\t\t\t * text and textVar and underline are\n\t\t\t\t * ignored. */\n    Tcl_Obj *imageObj;\t\t/* Name of image to display, or\n\t\t\t\t * NULL. If non-NULL, bitmap, text, and\n\t\t\t\t * textVarName are ignored. */\n    Tk_Image image;\t\t/* Image to display in window, or NULL if\n\t\t\t\t * none. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    enum state state;\t\t/* State of button for display purposes:\n\t\t\t\t * normal, active, or disabled. */\n    Tk_3DBorder normalBorder;\t/* Structure used to draw 3-D border and\n\t\t\t\t * background when window isn't active. NULL\n\t\t\t\t * means no such border exists. */\n    Tk_3DBorder activeBorder;\t/* Structure used to draw 3-D border and\n\t\t\t\t * background when window is active. NULL\n\t\t\t\t * means no such border exists. */\n    Tcl_Obj *borderWidthObj;\t/* Width of border. */\n    int relief;\t\t\t/* 3-d effect: TK_RELIEF_RAISED, etc. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. 0 means\n\t\t\t\t * don't draw a highlight. */\n    XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    Tk_Font tkfont;\t\t/* Information about text font, or NULL. */\n    XColor *normalFg;\t\t/* Foreground color in normal mode. */\n    XColor *activeFg;\t\t/* Foreground color in active mode. NULL means\n\t\t\t\t * use normalFg instead. */\n    XColor *disabledFg;\t\t/* Foreground color when disabled. NULL means\n\t\t\t\t * use normalFg with a 50% stipple instead. */\n    GC normalTextGC;\t\t/* GC for drawing text in normal mode. */\n    GC activeTextGC;\t\t/* GC for drawing text in active mode (NULL\n\t\t\t\t * means use normalTextGC). */\n    Pixmap gray;\t\t/* Pixmap for displaying disabled text/icon if\n\t\t\t\t * disabledFg is NULL. */\n    GC disabledGC;\t\t/* Used to produce disabled effect for\n\t\t\t\t * text. */\n    GC stippleGC;\t\t/* Used to produce disabled stipple effect for\n\t\t\t\t * images when disabled. */\n    int leftBearing;\t\t/* Distance from text origin to leftmost drawn\n\t\t\t\t * pixel (positive means to right). */\n    int rightBearing;\t\t/* Amount text sticks right from its\n\t\t\t\t * origin. */\n    Tcl_Obj *widthObj;\t\t/* Value of -width option. */\n    Tcl_Obj *heightObj;\t\t/* Value of -height option. */\n    int width, height;\t\t/* If > 0, these specify dimensions to request\n\t\t\t\t * for window, in characters for text and in\n\t\t\t\t * pixels for bitmaps. In this case the actual\n\t\t\t\t * size of the text string or bitmap is\n\t\t\t\t * ignored in computing desired window\n\t\t\t\t * size. */\n    Tcl_Obj *wrapLengthObj;\t/* Line length (in pixels) at which to wrap\n\t\t\t\t * onto next line. 0 means don't wrap\n\t\t\t\t * except at newlines. */\n    Tcl_Obj *padXObj, *padYObj;\t/* Extra space around text or bitmap (pixels\n\t\t\t\t * on each side). */\n    Tk_Anchor anchor;\t\t/* Where text/bitmap should be displayed\n\t\t\t\t * inside window region. */\n    Tk_Justify justify;\t\t/* Justification to use for multi-line\n\t\t\t\t * text. */\n    int textWidth;\t\t/* Width needed to display text as requested,\n\t\t\t\t * in pixels. */\n    int textHeight;\t\t/* Height needed to display text as requested,\n\t\t\t\t * in pixels. */\n    Tk_TextLayout textLayout;\t/* Saved text layout information. */\n    bool indicatorOn;\t\t/* True means display indicator; false means\n\t\t\t\t * don't display. */\n    int indicatorHeight;\t/* Height of indicator in pixels. This same\n\t\t\t\t * amount of extra space is also left on each\n\t\t\t\t * side of the indicator. 0 if no\n\t\t\t\t * indicator. */\n    int indicatorWidth;\t\t/* Width of indicator in pixels, including\n\t\t\t\t * indicatorHeight in padding on each side. 0\n\t\t\t\t * if no indicator. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    int compound;\t\t/* Value of -compound option; specifies\n\t\t\t\t * whether the menubutton should show both an\n\t\t\t\t * image and text, and, if so, how. */\n    enum direction direction;\t/* Direction for where to pop the menu. Valid\n\t\t\t\t * directions are \"above\", \"below\", \"flush\",\n\t\t\t\t * \"left\", and \"right\". \"above\" and \"below\"\n\t\t\t\t * will attempt to pop the menu completely\n\t\t\t\t * above or below the menu respectively.\n\t\t\t\t * \"flush\" means that the upper left corner\n\t\t\t\t * of the menubutton is where the menu pops up.\n\t\t\t\t * \"left\" and \"right\" will pop the menu left\n\t\t\t\t * or right, and the active item will be next\n\t\t\t\t * to the button. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    Tcl_Obj *takeFocusObj;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n} TkMenuButton;\n\n/*\n * Flag bits for buttons:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * POSTED:\t\t\tNon-zero means that the menu associated with\n *\t\t\t\tthis button has been posted (typically because\n *\t\t\t\tof an active button press).\n * GOT_FOCUS:\t\t\tNon-zero means this button currently has the\n *\t\t\t\tinput focus.\n */\n\n#define REDRAW_PENDING\t\t1\n#define POSTED\t\t\t2\n#define GOT_FOCUS\t\t4\n\n/*\n * The following constants define the dimensions of the cascade indicator,\n * which is displayed if the \"-indicatoron\" option is true. The units for\n * these options are 1/10 millimeters.\n */\n\n#define INDICATOR_WIDTH\t\t40\n#define INDICATOR_HEIGHT\t17\n\n/*\n * Declaration of procedures used in the implementation of the button widget.\n */\n\nMODULE_SCOPE void\tTkpComputeMenuButtonGeometry(TkMenuButton *mbPtr);\nMODULE_SCOPE TkMenuButton *TkpCreateMenuButton(Tk_Window tkwin);\nMODULE_SCOPE void\tTkpDisplayMenuButton(void *clientData);\nMODULE_SCOPE void\tTkpDestroyMenuButton(TkMenuButton *mbPtr);\nMODULE_SCOPE void\tTkMenuButtonWorldChanged(void *instanceData);\n\n#endif /* _TKMENUBUTTON */\n"
  },
  {
    "path": "generic/tkMessage.c",
    "content": "/*\n * tkMessage.c --\n *\n *\tThis module implements a message widgets for the Tk toolkit. A message\n *\twidget displays a multi-line string in a window according to a\n *\tparticular aspect ratio.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Ajuba Solutions.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"default.h\"\n\n/*\n * A data structure of the following type is kept for each message widget\n * managed by this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the message. NULL\n\t\t\t\t * means that the window has been destroyed\n\t\t\t\t * but the data structures haven't yet been\n\t\t\t\t * cleaned up.*/\n    Tk_OptionTable optionTable;\t/* Table that defines options available for\n\t\t\t\t * this widget. */\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with message. */\n    Tcl_Command widgetCmd;\t/* Token for message's widget command. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *stringObj;\t\t/* String displayed in message. */\n    Tcl_Obj *textVarNameObj;\t/* Name of variable or NULL.\n\t\t\t\t * If non-NULL, message displays the contents\n\t\t\t\t * of this variable. */\n    Tk_3DBorder border;\t\t/* Structure used to draw 3-D border and\n\t\t\t\t * background. NULL means a border hasn't been\n\t\t\t\t * created yet. */\n    Tcl_Obj *borderWidthObj;\t/* Width of border. */\n    int relief;\t\t\t/* 3-D effect: TK_RELIEF_RAISED, etc. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw\n\t\t\t\t * around widget when it has the focus.\n\t\t\t\t * 0 means don't draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight\n\t\t\t\t * area when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    Tk_Font tkfont;\t\t/* Information about text font, or NULL. */\n    XColor *fgColorPtr;\t\t/* Foreground color in normal mode. */\n    Tcl_Obj *padXObj, *padYObj;\t/* Tcl_Obj rep's of padX, padY values. */\n    Tcl_Obj *widthObj;\t\t\t/* User-requested width, in pixels. 0 means\n\t\t\t\t * compute width using aspect ratio. */\n    int aspect;\t\t\t/* Desired aspect ratio for window\n\t\t\t\t * (100*width/height). */\n    int msgWidth;\t\t/* Width in pixels needed to display\n\t\t\t\t * message. */\n    int msgHeight;\t\t/* Height in pixels needed to display\n\t\t\t\t * message. */\n    Tk_Anchor anchor;\t\t/* Where to position text within window region\n\t\t\t\t * if window is larger or smaller than\n\t\t\t\t * needed. */\n    Tk_Justify justify;\t\t/* Justification for text. */\n\n    GC textGC;\t\t\t/* GC for drawing text in normal mode. */\n    Tk_TextLayout textLayout;\t/* Saved layout information. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or None. */\n    Tcl_Obj *takeFocusObj;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n} Message;\n\n/*\n * Flag bits for messages:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler\n *\t\t\t\thas already been queued to redraw\n *\t\t\t\tthis window.\n * GOT_FOCUS:\t\t\tNon-zero means this button currently\n *\t\t\t\thas the input focus.\n * MESSAGE_DELETED:\t\tThe message has been effectively deleted.\n */\n\n#define REDRAW_PENDING\t\t1\n#define GOT_FOCUS\t\t4\n#define MESSAGE_DELETED\t\t8\n\n/*\n * Information used for argv parsing.\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\", DEF_MESSAGE_ANCHOR,\n\tTCL_INDEX_NONE, offsetof(Message, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_INT, \"-aspect\", \"aspect\", \"Aspect\", DEF_MESSAGE_ASPECT,\n\tTCL_INDEX_NONE, offsetof(Message, aspect), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_MESSAGE_BG_COLOR, TCL_INDEX_NONE, offsetof(Message, border), 0,\n\tDEF_MESSAGE_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL, NULL,\n\t0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL, NULL,\n\t0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_MESSAGE_BORDER_WIDTH, offsetof(Message, borderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_MESSAGE_CURSOR, TCL_INDEX_NONE, offsetof(Message, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", NULL, NULL, NULL,\n\t0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_MESSAGE_FONT, TCL_INDEX_NONE, offsetof(Message, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_MESSAGE_FG, TCL_INDEX_NONE, offsetof(Message, fgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_MESSAGE_HIGHLIGHT_BG, TCL_INDEX_NONE,\n\toffsetof(Message, highlightBgColorPtr), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_MESSAGE_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Message, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_MESSAGE_HIGHLIGHT_WIDTH, offsetof(Message, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\tDEF_MESSAGE_JUSTIFY, TCL_INDEX_NONE, offsetof(Message, justify), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\tDEF_MESSAGE_PADX, offsetof(Message, padXObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\tDEF_MESSAGE_PADY, offsetof(Message, padYObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_MESSAGE_RELIEF, TCL_INDEX_NONE, offsetof(Message, relief), 0, 0, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_MESSAGE_TAKE_FOCUS, offsetof(Message, takeFocusObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tDEF_MESSAGE_TEXT, offsetof(Message, stringObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tDEF_MESSAGE_TEXT_VARIABLE, offsetof(Message, textVarNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\",\n\tDEF_MESSAGE_WIDTH, offsetof(Message, widthObj), TCL_INDEX_NONE, 0, 0 ,0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tMessageCmdDeletedProc(void *clientData);\nstatic void\t\tMessageEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic char *\t\tMessageTextVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic Tcl_ObjCmdProc2 MessageWidgetObjCmd;\nstatic void\t\tMessageWorldChanged(void *instanceData);\nstatic void\t\tComputeMessageGeometry(Message *msgPtr);\nstatic int\t\tConfigureMessage(Tcl_Interp *interp, Message *msgPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[], int flags);\nstatic void\t\tDestroyMessage(void *memPtr);\nstatic void\t\tDisplayMessage(void *clientData);\n\n/*\n * The structure below defines message class behavior by means of functions\n * that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs messageClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    MessageWorldChanged,\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_MessageObjCmd --\n *\n *\tThis function is invoked to process the \"message\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_MessageObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    Message *msgPtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    msgPtr = (Message *)Tcl_Alloc(sizeof(Message));\n    memset(msgPtr, 0, sizeof(Message));\n\n    /*\n     * Set values for those fields that don't take a 0 or NULL value.\n     */\n\n    msgPtr->tkwin = tkwin;\n    msgPtr->display = Tk_Display(tkwin);\n    msgPtr->interp = interp;\n    msgPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(msgPtr->tkwin), MessageWidgetObjCmd, msgPtr,\n\t    MessageCmdDeletedProc);\n    msgPtr->optionTable = optionTable;\n    msgPtr->relief = TK_RELIEF_FLAT;\n    msgPtr->textGC = NULL;\n    msgPtr->anchor = TK_ANCHOR_CENTER;\n    msgPtr->aspect = 150;\n    msgPtr->justify = TK_JUSTIFY_LEFT;\n    msgPtr->cursor = NULL;\n\n    Tk_SetClass(msgPtr->tkwin, \"Message\");\n    Tk_SetClassProcs(msgPtr->tkwin, &messageClass, msgPtr);\n    Tk_CreateEventHandler(msgPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    MessageEventProc, msgPtr);\n    if (Tk_InitOptions(interp, msgPtr, optionTable, tkwin) != TCL_OK) {\n\tTk_DestroyWindow(msgPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    if (ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0) != TCL_OK) {\n\tTk_DestroyWindow(msgPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(msgPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MessageWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMessageWidgetObjCmd(\n    void *clientData,\t/* Information about message widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    Message *msgPtr = (Message *)clientData;\n    static const char *const optionStrings[] = { \"cget\", \"configure\", NULL };\n    enum options { MESSAGE_CGET, MESSAGE_CONFIGURE };\n    int index;\n    int result = TCL_OK;\n    Tcl_Obj *objPtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    Tcl_Preserve(msgPtr);\n\n    switch ((enum options) index) {\n    case MESSAGE_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t} else {\n\t    objPtr = Tk_GetOptionValue(interp, msgPtr,\n\t\t    msgPtr->optionTable, objv[2], msgPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, objPtr);\n\t\tresult = TCL_OK;\n\t    }\n\t}\n\tbreak;\n    case MESSAGE_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, msgPtr,\n\t\t    msgPtr->optionTable, (objc == 3) ? objv[2] : NULL,\n\t\t    msgPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, objPtr);\n\t\tresult = TCL_OK;\n\t    }\n\t} else {\n\t    result = ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0);\n\t}\n\tbreak;\n    }\n\n    Tcl_Release(msgPtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyMessage --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of a message at a safe time (when no-one is\n *\tusing it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the message is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyMessage(\n    void *memPtr)\t\t/* Info about message widget. */\n{\n    Message *msgPtr = (Message *) memPtr;\n\n    msgPtr->flags |= MESSAGE_DELETED;\n\n    Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd);\n    if (msgPtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(DisplayMessage, msgPtr);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeConfigOptions handle all the standard option-related stuff.\n     */\n\n    if (msgPtr->textGC != NULL) {\n\tTk_FreeGC(msgPtr->display, msgPtr->textGC);\n    }\n    if (msgPtr->textLayout != NULL) {\n\tTk_FreeTextLayout(msgPtr->textLayout);\n    }\n    if (msgPtr->textVarNameObj != NULL) {\n\tTcl_UntraceVar2(msgPtr->interp, Tcl_GetString(msgPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMessageTextVarProc, msgPtr);\n    }\n    Tk_FreeConfigOptions(msgPtr, msgPtr->optionTable, msgPtr->tkwin);\n    msgPtr->tkwin = NULL;\n    Tcl_Free(msgPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureMessage --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a message\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as text string, colors, font, etc. get\n *\tset for msgPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureMessage(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Message *msgPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[],\t/* Arguments. */\n    TCL_UNUSED(int))\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    Tk_SavedOptions savedOptions;\n\n    /*\n     * Eliminate any existing trace on a variable monitored by the message.\n     */\n\n    if (msgPtr->textVarNameObj != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMessageTextVarProc, msgPtr);\n    }\n\n    if (Tk_SetOptions(interp, msgPtr, msgPtr->optionTable, objc, objv,\n\t    msgPtr->tkwin, &savedOptions, NULL) != TCL_OK) {\n\tTk_RestoreSavedOptions(&savedOptions);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If the message is to display the value of a variable, then set up a\n     * trace on the variable's value, create the variable if it doesn't exist,\n     * and fetch its current value.\n     */\n\n    if (msgPtr->textVarNameObj != NULL) {\n\tconst char *value;\n\n\tvalue = Tcl_GetVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n\tif (value == NULL) {\n\t    Tcl_SetVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL, Tcl_GetString(msgPtr->stringObj),\n\t\t    TCL_GLOBAL_ONLY);\n\t} else {\n\t    if (msgPtr->stringObj != NULL) {\n\t\tTcl_DecrRefCount(msgPtr->stringObj);\n\t    }\n\t    msgPtr->stringObj = Tcl_NewStringObj(value, TCL_INDEX_NONE);\n\t    Tcl_IncrRefCount(msgPtr->stringObj);\n\t}\n\tTcl_TraceVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tMessageTextVarProc, msgPtr);\n    }\n\n    Tk_FreeSavedOptions(&savedOptions);\n    MessageWorldChanged(msgPtr);\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * MessageWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMessage will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nMessageWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC gc = NULL;\n    Message *msgPtr = (Message *)instanceData;\n\n    if (msgPtr->border != NULL) {\n\tTk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);\n    }\n\n    gcValues.font = Tk_FontId(msgPtr->tkfont);\n    gcValues.foreground = msgPtr->fgColorPtr->pixel;\n    gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);\n    if (msgPtr->textGC != NULL) {\n\tTk_FreeGC(msgPtr->display, msgPtr->textGC);\n    }\n    msgPtr->textGC = gc;\n\n    /*\n     * Recompute the desired geometry for the window, and arrange for the\n     * window to be redisplayed.\n     */\n\n    ComputeMessageGeometry(msgPtr);\n    if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)\n\t    && !(msgPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayMessage, msgPtr);\n\tmsgPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeMessageGeometry --\n *\n *\tCompute the desired geometry for a message window, taking into account\n *\tthe desired aspect ratio for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTk_GeometryRequest is called to inform the geometry manager of the\n *\tdesired geometry for this window.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeMessageGeometry(\n    Message *msgPtr)\t/* Information about window. */\n{\n    int width, inc, height;\n    int thisWidth, thisHeight, maxWidth;\n    int aspect, lowerBound, upperBound, inset;\n    int borderWidth, highlightWidth, padX, padY;\n    Tk_FontMetrics fm;\n    Tcl_Size numChars;\n\n    Tk_FreeTextLayout(msgPtr->textLayout);\n\n    Tk_GetFontMetrics(msgPtr->tkfont, &fm);\n    if (msgPtr->padXObj) {\n\tTk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->padXObj, &padX);\n    } else {\n\tpadX = fm.ascent / 2;\n    }\n    if (msgPtr->padYObj) {\n\tTk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->padYObj, &padY);\n    } else {\n\tpadY = fm.ascent / 4;\n    }\n\n    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->highlightWidthObj, &highlightWidth);\n    inset = borderWidth + highlightWidth;\n\n    /*\n     * Compute acceptable bounds for the final aspect ratio.\n     */\n\n    aspect = msgPtr->aspect/10;\n    if (aspect < 5) {\n\taspect = 5;\n    }\n    lowerBound = msgPtr->aspect - aspect;\n    upperBound = msgPtr->aspect + aspect;\n\n    /*\n     * Do the computation in multiple passes: start off with a very wide\n     * window, and compute its height. Then change the width and try again.\n     * Reduce the size of the change and iterate until dimensions are found\n     * that approximate the desired aspect ratio. Or, if the user gave an\n     * explicit width then just use that.\n     */\n\n    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->widthObj, &width);\n    if (width > 0) {\n\tinc = 0;\n    } else {\n\twidth = WidthOfScreen(Tk_Screen(msgPtr->tkwin))/2;\n\tinc = width/2;\n    }\n\n    numChars = Tcl_GetCharLength(msgPtr->stringObj);\n    for ( ; ; inc /= 2) {\n\tmsgPtr->textLayout = Tk_ComputeTextLayout(msgPtr->tkfont,\n\t\tTcl_GetString(msgPtr->stringObj), numChars, width, msgPtr->justify,\n\t\t0, &thisWidth, &thisHeight);\n\tmaxWidth = thisWidth + 2 * (inset + padX);\n\theight = thisHeight + 2 * (inset + padY);\n\n\tif (inc <= 2) {\n\t    break;\n\t}\n\taspect = (100 * maxWidth) / height;\n\n\tif (aspect < lowerBound) {\n\t    width += inc;\n\t} else if (aspect > upperBound) {\n\t    width -= inc;\n\t} else {\n\t    break;\n\t}\n\tTk_FreeTextLayout(msgPtr->textLayout);\n    }\n    msgPtr->msgWidth = thisWidth;\n    msgPtr->msgHeight = thisHeight;\n    Tk_GeometryRequest(msgPtr->tkwin, maxWidth, height);\n    Tk_SetInternalBorder(msgPtr->tkwin, inset);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayMessage --\n *\n *\tThis function redraws the contents of a message window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayMessage(\n    void *clientData)\t/* Information about window. */\n{\n    Message *msgPtr = (Message *)clientData;\n    Tk_Window tkwin = msgPtr->tkwin;\n    int x, y;\n    int width, borderWidth, highlightWidth, padX, padY;\n    Tk_FontMetrics fm;\n\n    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetFontMetrics(msgPtr->tkfont, &fm);\n    if (msgPtr->padXObj) {\n\tTk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->padXObj, &padX);\n    } else {\n\tpadX = fm.ascent / 2;\n    }\n    if (msgPtr->padYObj) {\n\tTk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->padYObj, &padY);\n    } else {\n\tpadY = fm.ascent / 4;\n    }\n\n    width = highlightWidth;\n    msgPtr->flags &= ~REDRAW_PENDING;\n    if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n    if (msgPtr->border != NULL) {\n\twidth += borderWidth;\n    }\n    if (msgPtr->relief == TK_RELIEF_FLAT) {\n\twidth = highlightWidth;\n    }\n    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,\n\t    width, width,\n\t    Tk_Width(tkwin) - 2 * width,\n\t    Tk_Height(tkwin) - 2 * width,\n\t    0, TK_RELIEF_FLAT);\n\n    /*\n     * Compute starting y-location for message based on message size and\n     * anchor option.\n     */\n\n    TkComputeAnchor(msgPtr->anchor, tkwin, padX, padY,\n\t    msgPtr->msgWidth, msgPtr->msgHeight, &x, &y);\n    Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC,\n\t    msgPtr->textLayout, x, y, 0, -1);\n\n    if (width > highlightWidth) {\n\tTk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,\n\t\thighlightWidth, highlightWidth,\n\t\tTk_Width(tkwin) - 2 * highlightWidth,\n\t\tTk_Height(tkwin) - 2 * highlightWidth,\n\t\tborderWidth, msgPtr->relief);\n    }\n    if (highlightWidth > 0) {\n\tGC fgGC, bgGC;\n\n\tbgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));\n\tif (msgPtr->flags & GOT_FOCUS) {\n\t    fgGC = Tk_GCForColor(msgPtr->highlightColorPtr,Tk_WindowId(tkwin));\n\t    Tk_DrawHighlightBorder(tkwin, fgGC, bgGC, highlightWidth,\n\t\t    Tk_WindowId(tkwin));\n\t} else {\n\t    Tk_DrawHighlightBorder(tkwin, bgGC, bgGC, highlightWidth,\n\t\t    Tk_WindowId(tkwin));\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MessageEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tmessages.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMessageEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    Message *msgPtr = (Message *)clientData;\n    int highlightWidth;\n\n    if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))\n\t    || (eventPtr->type == ConfigureNotify)) {\n\tgoto redraw;\n    } else if (eventPtr->type == DestroyNotify) {\n\tDestroyMessage(clientData);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    msgPtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    msgPtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, msgPtr->tkwin, msgPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tgoto redraw;\n\t    }\n\t}\n    }\n    return;\n\n  redraw:\n    if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayMessage, msgPtr);\n\tmsgPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MessageCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMessageCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    Message *msgPtr = (Message *)clientData;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (!(msgPtr->flags & MESSAGE_DELETED)) {\n\tTk_DestroyWindow(msgPtr->tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MessageTextVarProc --\n *\n *\tThis function is invoked when someone changes the variable whose\n *\tcontents are to be displayed in a message.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe text displayed in the message will change to match the variable.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nMessageTextVarProc(\n    void *clientData,\t/* Information about message. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t/* Name of variable. */\n    TCL_UNUSED(const char *),\t/* Second part of variable name. */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    Message *msgPtr = (Message *)clientData;\n    const char *value;\n\n    /*\n     * If the variable is unset, then immediately recreate it unless the whole\n     * interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tif (!Tcl_InterpDeleted(interp) && msgPtr->textVarNameObj) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(msgPtr->textVarNameObj),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tMessageTextVarProc, probe);\n\t\tif (probe == (void *)msgPtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * textVarName, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t    Tcl_SetVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL, Tcl_GetString(msgPtr->stringObj),\n\t\t    TCL_GLOBAL_ONLY);\n\t    Tcl_TraceVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL,\n\t\t    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    MessageTextVarProc, clientData);\n\t}\n\treturn NULL;\n    }\n\n    value = Tcl_GetVar2(interp, Tcl_GetString(msgPtr->textVarNameObj), NULL, TCL_GLOBAL_ONLY);\n    if (value == NULL) {\n\tvalue = \"\";\n    }\n    if (msgPtr->stringObj != NULL) {\n\tTcl_DecrRefCount(msgPtr->stringObj);\n    }\n    msgPtr->stringObj = Tcl_NewStringObj(value, TCL_INDEX_NONE);\n    Tcl_IncrRefCount(msgPtr->stringObj);\n    ComputeMessageGeometry(msgPtr);\n\n    if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)\n\t    && !(msgPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayMessage, msgPtr);\n\tmsgPtr->flags |= REDRAW_PENDING;\n    }\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkObj.c",
    "content": "/*\n * tkObj.c --\n *\n *\tThis file contains functions that implement the common Tk object types\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The following structure is the internal representation for pixel objects.\n */\n\ntypedef struct PixelRep {\n    double value;\n    int units;\n    Tk_Window tkwin;\n    int returnValue;\n} PixelRep;\n\n#define SIMPLE_PIXELREP(objPtr)\t\t\t\t\\\n    ((objPtr)->internalRep.twoPtrValue.ptr2 == 0)\n\n#define SET_SIMPLEPIXEL(objPtr, intval)\t\t\t\\\n    (objPtr)->internalRep.twoPtrValue.ptr1 = INT2PTR(intval);\t\\\n    (objPtr)->internalRep.twoPtrValue.ptr2 = 0\n\n#define GET_SIMPLEPIXEL(objPtr)\t\t\t\t\\\n    (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr1))\n\n#define SET_COMPLEXPIXEL(objPtr, repPtr)\t\t\\\n    (objPtr)->internalRep.twoPtrValue.ptr1 = NULL;\t\t\\\n    (objPtr)->internalRep.twoPtrValue.ptr2 = repPtr\n\n#define GET_COMPLEXPIXEL(objPtr)\t\t\t\\\n    ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)\n\n/*\n * One of these structures is created per thread to store thread-specific\n * data. In this case, it is used to contain references to selected\n * Tcl_ObjTypes that we can use as screen distances without conversion. The\n * \"dataKey\" below is used to locate the ThreadSpecificData for the current\n * thread.\n */\n\ntypedef struct {\n    const Tcl_ObjType *doubleTypePtr;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The following structure is the internal representation for mm objects.\n */\n\ntypedef struct MMRep {\n    double value;\n    int units;\n    Tk_Window tkwin;\n    double returnValue;\n} MMRep;\n\n/*\n * The following structure is the internal representation for window objects.\n * A WindowRep caches name-to-window lookups. The cache is invalid if tkwin is\n * NULL or if mainPtr->deletionEpoch does not match epoch.\n */\n\ntypedef struct WindowRep {\n    Tk_Window tkwin;\t\t/* Cached window; NULL if not found. */\n    TkMainInfo *mainPtr;\t/* MainWindow associated with tkwin. */\n    size_t epoch;\t\t\t/* Value of mainPtr->deletionEpoch at last\n\t\t\t\t * successful lookup. */\n} WindowRep;\n\n/*\n * Prototypes for functions defined later in this file:\n */\n\nstatic void\t\tDupMMInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);\nstatic void\t\tDupPixelInternalRep(Tcl_Obj *srcPtr, Tcl_Obj*copyPtr);\nstatic void\t\tDupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj*copyPtr);\nstatic void\t\tFreeMMInternalRep(Tcl_Obj *objPtr);\nstatic void\t\tFreePixelInternalRep(Tcl_Obj *objPtr);\nstatic void\t\tFreeWindowInternalRep(Tcl_Obj *objPtr);\nstatic ThreadSpecificData *GetTypeCache(void);\nstatic void\t\tUpdateStringOfMM(Tcl_Obj *objPtr);\nstatic int\t\tSetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);\nstatic int\t\tSetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);\nstatic int\t\tSetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);\nstatic Tcl_Size\tLengthOneOrTwo(Tcl_Obj *objPtr);\n\n\n/*\n * The following structure defines the implementation of the \"pixel\" Tcl\n * object, used for measuring distances. The pixel object remembers its\n * initial display-independent settings.\n */\n\nstatic const Tcl_ObjType pixelObjType = {\n    \"pixel\",\t\t\t/* name */\n    FreePixelInternalRep,\t/* freeIntRepProc */\n    DupPixelInternalRep,\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V1(LengthOneOrTwo)\n};\n\nTcl_Size\nTkLengthOne(\n    TCL_UNUSED(Tcl_Obj *))\n{\n    return 1;\n}\n\n/*\n * The following structure defines the implementation of the \"pixel\" Tcl\n * object, used for measuring distances. The pixel object remembers its\n * initial display-independent settings.\n */\n\nstatic const Tcl_ObjType mmObjType = {\n    \"mm\",\t\t\t/* name */\n    FreeMMInternalRep,\t\t/* freeIntRepProc */\n    DupMMInternalRep,\t\t/* dupIntRepProc */\n    UpdateStringOfMM,\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V1(LengthOneOrTwo)\n};\n\n/*\n * The following structure defines the implementation of the \"window\"\n * Tcl object.\n */\n\nstatic const Tcl_ObjType windowObjType = {\n    \"window\",\t\t\t/* name */\n    FreeWindowInternalRep,\t/* freeIntRepProc */\n    DupWindowInternalRep,\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * LengthOneOrTwo --\n *\n *\tDetermine the length of a \"pixel\" or \"mm\". It returns 2 if there is any\n *\tspace between the float and the 'c', 'i', 'm' or 'p', 1 otherwise.\n *\n *----------------------------------------------------------------------\n */\nTcl_Size\nLengthOneOrTwo(\n    Tcl_Obj *objPtr)\n{\n    if (objPtr->bytes) {\n\tconst char *p = objPtr->bytes + strlen(objPtr->bytes);\n\twhile (strchr(\" \\f\\n\\r\\t\\v\", *--p)) {\n\t    // skip spacing at end;\n\t}\n\tif (strchr(\"cimp\", *p)) {\n\t    // Check whether character is preceded by space\n\t    if (strchr(\" \\f\\n\\r\\t\\v\", *--p)) {\n\t\treturn 2;\n\t    }\n\t}\n    }\n    return 1;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetTypeCache --\n *\n *\tGet (and build if necessary) the cache of useful Tcl object types for\n *\tcomparisons in the conversion functions.  This allows optimized checks\n *\tfor standard cases.\n *\n *----------------------------------------------------------------------\n */\n\nstatic ThreadSpecificData *\nGetTypeCache(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->doubleTypePtr == NULL) {\n\t/* Smart initialization of doubleTypePtr without\n\t * hash-table lookup or creating complete Tcl_Obj's */\n\tTcl_Obj obj;\n\tobj.length = 3;\n\tobj.bytes = (char *)\"0.0\";\n\tobj.typePtr = NULL;\n\tTcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue);\n\ttsdPtr->doubleTypePtr = obj.typePtr;\n    }\n    return tsdPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetIntForIndex --\n *\n *\tAlmost the same as Tcl_GetIntForIndex, but it retrieves an int. Accepts\n *\t\"\" (empty string) as well.\n *\n * Results:\n *\tThe return value is a standard Tcl object result.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetIntForIndex(\n    Tcl_Obj *indexObj,\n    Tcl_Size end,\n    int lastOK,\n    Tcl_Size *indexPtr)\n{\n    if (TkObjIsEmpty(indexObj)) {\n\t*indexPtr = (end == -1) ? -1 - TCL_SIZE_MAX : TCL_INDEX_NONE;\n\treturn TCL_OK;\n    }\n    return Tcl_GetIntForIndex(NULL, indexObj, end + lastOK, indexPtr);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetPixelsFromObjEx --\n *\n *\tAttempt to return a pixel value from the Tcl object \"objPtr\". If the\n *\tobject is not already a pixel value, an attempt will be made to\n *\tconvert it to one.\n *\n * Results:\n *\tThe return value is a standard Tcl object result. If an error occurs\n *\tduring conversion, an error message is left in the interpreter's\n *\tresult unless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf the object is not already a pixel, the conversion will free any old\n *\tinternal representation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic\nint\nGetPixelsFromObjEx(\n    Tcl_Interp *interp,\t/* Used for error reporting if not NULL. */\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr,\t\t/* The object from which to get pixels. */\n    int *intPtr,\n    double *dblPtr)\t\t/* Places to store resulting pixels. */\n{\n    int result, fresh;\n    double d;\n    PixelRep *pixelPtr;\n    static const double bias[] = {\n\t1.0,\t10.0,\t25.4,\t0.35277777777777775 /*25.4 / 72.0*/\n    };\n\n    if (objPtr->typePtr != &pixelObjType) {\n\n\tif (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) {\n\t    if (dblPtr != NULL) {\n\t\t*dblPtr = d;\n\t    }\n\t    *intPtr = (int) (d<0 ? d-0.5 : d+0.5);\n\t    return TCL_OK;\n\t}\n    }\n\n retry:\n    fresh = (objPtr->typePtr != &pixelObjType);\n    if (fresh) {\n\tresult = SetPixelFromAny(interp, objPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n\n    if (SIMPLE_PIXELREP(objPtr)) {\n\t*intPtr = GET_SIMPLEPIXEL(objPtr);\n\tif (dblPtr) {\n\t    *dblPtr = (double) (*intPtr);\n\t}\n    } else {\n\tpixelPtr = GET_COMPLEXPIXEL(objPtr);\n\tif ((!fresh) && (pixelPtr->tkwin != tkwin)) {\n\t    /*\n\t     * In the case of exo-screen conversions of non-pixels, we force a\n\t     * recomputation from the string.\n\t     */\n\n\t    FreePixelInternalRep(objPtr);\n\t    goto retry;\n\t}\n\tif ((pixelPtr->tkwin != tkwin) || dblPtr) {\n\t    d = pixelPtr->value;\n\t    if (pixelPtr->units >= 0) {\n\t\td *= bias[pixelPtr->units] * WidthOfScreen(Tk_Screen(tkwin));\n\t\td /= WidthMMOfScreen(Tk_Screen(tkwin));\n\t    }\n\t    pixelPtr->returnValue = (int) (d<0 ? d-0.5 : d+0.5);\n\t    pixelPtr->tkwin = tkwin;\n\t    if (dblPtr) {\n\t\t*dblPtr = d;\n\t    }\n\t}\n\t*intPtr = pixelPtr->returnValue;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetPixelsFromObj --\n *\n *\tAttempt to return a pixel value from the Tcl object \"objPtr\". If the\n *\tobject is not already a pixel value, an attempt will be made to\n *\tconvert it to one.\n *\n * Results:\n *\tThe return value is a standard Tcl object result. If an error occurs\n *\tduring conversion, an error message is left in the interpreter's\n *\tresult unless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf the object is not already a pixel, the conversion will free any old\n *\tinternal representation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetPixelsFromObj(\n    Tcl_Interp *interp,\t/* Used for error reporting if not NULL. */\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr,\t\t/* The object from which to get pixels. */\n    int *intPtr)\t\t/* Place to store resulting pixels. */\n{\n    return GetPixelsFromObjEx(interp, tkwin, objPtr, intPtr, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetDoublePixelsFromObj --\n *\n *\tAttempt  to  return   a  double  pixel  value  from   the  Tcl  object\n *\t\"objPtr\". If the object is not  already a pixel value, an attempt will\n *\tbe made to convert it to one, the internal unit being pixels.\n *\n * Results:\n *\tThe return value is a standard Tcl object result. If an error occurs\n *\tduring conversion, an error message is left in the interpreter's\n *\tresult unless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf the object is not already a pixel, the conversion will free any old\n *\tinternal representation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetDoublePixelsFromObj(\n    Tcl_Interp *interp,\t/* Used for error reporting if not NULL. */\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr,\t\t/* The object from which to get pixels. */\n    double *doublePtr)\t\t/* Place to store resulting pixels. */\n{\n    double d;\n    int result, val;\n\n    result = GetPixelsFromObjEx(interp, tkwin, objPtr, &val, &d);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    if (objPtr->typePtr == &pixelObjType && !SIMPLE_PIXELREP(objPtr)) {\n\tPixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr);\n\n\tif (pixelPtr->units >= 0) {\n\t    /*\n\t     * Internally \"shimmer\" to pixel units.\n\t     */\n\n\t    pixelPtr->units = -1;\n\t    pixelPtr->value = d;\n\t}\n    }\n    *doublePtr = d;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreePixelInternalRep --\n *\n *\tDeallocate the storage associated with a pixel object's internal\n *\trepresentation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees objPtr's internal representation and sets objPtr's internalRep\n *\tto NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreePixelInternalRep(\n    Tcl_Obj *objPtr)\t\t/* Pixel object with internal rep to free. */\n{\n    if (!SIMPLE_PIXELREP(objPtr)) {\n\tPixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr);\n\n\tTcl_Free(pixelPtr);\n    }\n    SET_SIMPLEPIXEL(objPtr, 0);\n    objPtr->typePtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DupPixelInternalRep --\n *\n *\tInitialize the internal representation of a pixel Tcl_Obj to a copy of\n *\tthe internal representation of an existing pixel object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tcopyPtr's internal rep is set to the pixel corresponding to srcPtr's\n *\tinternal rep.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDupPixelInternalRep(\n    Tcl_Obj *srcPtr,\t/* Object with internal rep to copy. */\n    Tcl_Obj *copyPtr)\t/* Object with internal rep to set. */\n{\n    copyPtr->typePtr = srcPtr->typePtr;\n\n    if (SIMPLE_PIXELREP(srcPtr)) {\n\tSET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));\n    } else {\n\tPixelRep *oldPtr, *newPtr;\n\n\toldPtr = GET_COMPLEXPIXEL(srcPtr);\n\tnewPtr = (PixelRep *)Tcl_Alloc(sizeof(PixelRep));\n\tnewPtr->value = oldPtr->value;\n\tnewPtr->units = oldPtr->units;\n\tnewPtr->tkwin = oldPtr->tkwin;\n\tnewPtr->returnValue = oldPtr->returnValue;\n\tSET_COMPLEXPIXEL(copyPtr, newPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetPixelFromAny --\n *\n *\tAttempt to generate a pixel internal form for the Tcl object \"objPtr\".\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf no error occurs, a pixel representation of the object is stored\n *\tinternally and the type of \"objPtr\" is set to pixel.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetPixelFromAny(\n    Tcl_Interp *interp,\t\t/* Used for error reporting if not NULL. */\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    ThreadSpecificData *typeCache = GetTypeCache();\n    const Tcl_ObjType *typePtr;\n    char *string;\n    char *rest;\n    double d;\n    int i, units;\n\n    if (objPtr->typePtr != typeCache->doubleTypePtr\n\t    && Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {\n\td = (double) units;\n\tunits = -1;\n\n\t/*\n\t * In the case of ints, we need to ensure that a valid string exists\n\t * in order for int-but-not-string objects to be converted back to\n\t * ints again from pixel obj types.\n\t */\n\n\t(void) Tcl_GetString(objPtr);\n    } else if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) {\n\tunits = -1;\n    } else {\n\tchar savechar;\n\tstring = Tcl_GetString(objPtr);\n\n\trest = string + strlen(string);\n\twhile ((rest > string) && isspace(UCHAR(rest[-1]))) {\n\t    --rest; /* skip all spaces at the end */\n\t}\n\tif (rest > string) {\n\t    --rest; /* point to the character just before the last space */\n\t}\n\tif (rest == string) {\n\terror:\n\t    if (interp != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"expected screen distance but got \\\"%.50s\\\"\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\tswitch (*rest) {\n\tcase 'm':\n\t    units = 0;\n\t    break;\n\tcase 'c':\n\t    units = 1;\n\t    break;\n\tcase 'i':\n\t    units = 2;\n\t    break;\n\tcase 'p':\n\t    units = 3;\n\t    break;\n\tdefault:\n\t    goto error;\n\t}\n\tsavechar = *rest;\n\t*rest = '\\0';\n\tif (Tcl_GetDouble(NULL, string, &d) != TCL_OK) {\n\t    *rest = savechar;\n\t    goto error;\n\t}\n\t*rest = savechar;\n    }\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n\n    objPtr->typePtr = &pixelObjType;\n\n    i = (int) d;\n    if ((units < 0) && (i == d)) {\n\tSET_SIMPLEPIXEL(objPtr, i);\n    } else {\n\tPixelRep *pixelPtr = (PixelRep *)Tcl_Alloc(sizeof(PixelRep));\n\n\tpixelPtr->value = d;\n\tpixelPtr->units = units;\n\tpixelPtr->tkwin = NULL;\n\tpixelPtr->returnValue = i;\n\tSET_COMPLEXPIXEL(objPtr, pixelPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetMMFromObj --\n *\n *\tAttempt to return an mm value from the Tcl object \"objPtr\". If the\n *\tobject is not already an mm value, an attempt will be made to convert\n *\tit to one.\n *\n * Results:\n *\tThe return value is a standard Tcl object result. If an error occurs\n *\tduring conversion, an error message is left in the interpreter's\n *\tresult unless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf the object is not already a pixel, the conversion will free any old\n *\tinternal representation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetMMFromObj(\n    Tcl_Interp *interp,\t/* Used for error reporting if not NULL. */\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr,\t\t/* The object from which to get mms. */\n    double *doublePtr)\t\t/* Place to store resulting millimeters. */\n{\n    int result;\n    double d;\n    MMRep *mmPtr;\n    static const double bias[] = {\n\t10.0,\t25.4,\t1.0,\t0.35277777777777775 /*25.4 / 72.0*/\n    };\n\n    if (objPtr->typePtr != &mmObjType) {\n\tresult = SetMMFromAny(interp, objPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n\n    mmPtr = (MMRep *)objPtr->internalRep.twoPtrValue.ptr1;\n    if (mmPtr->tkwin != tkwin) {\n\td = mmPtr->value;\n\tif (mmPtr->units == -1) {\n\t    d /= WidthOfScreen(Tk_Screen(tkwin));\n\t    d *= WidthMMOfScreen(Tk_Screen(tkwin));\n\t} else {\n\t    d *= bias[mmPtr->units];\n\t}\n\tmmPtr->tkwin = tkwin;\n\tmmPtr->returnValue = d;\n    }\n    *doublePtr = mmPtr->returnValue;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeMMInternalRep --\n *\n *\tDeallocate the storage associated with a mm object's internal\n *\trepresentation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees objPtr's internal representation and sets objPtr's internalRep\n *\tto NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeMMInternalRep(\n    Tcl_Obj *objPtr)\t\t/* MM object with internal rep to free. */\n{\n    Tcl_Free(objPtr->internalRep.twoPtrValue.ptr1);\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    objPtr->typePtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DupMMInternalRep --\n *\n *\tInitialize the internal representation of a pixel Tcl_Obj to a copy of\n *\tthe internal representation of an existing pixel object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tcopyPtr's internal rep is set to the pixel corresponding to srcPtr's\n *\tinternal rep.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDupMMInternalRep(\n    Tcl_Obj *srcPtr,\t/* Object with internal rep to copy. */\n    Tcl_Obj *copyPtr)\t/* Object with internal rep to set. */\n{\n    MMRep *oldPtr, *newPtr;\n\n    copyPtr->typePtr = srcPtr->typePtr;\n    oldPtr = (MMRep *)srcPtr->internalRep.twoPtrValue.ptr1;\n    newPtr = (MMRep *)Tcl_Alloc(sizeof(MMRep));\n    newPtr->value = oldPtr->value;\n    newPtr->units = oldPtr->units;\n    newPtr->tkwin = oldPtr->tkwin;\n    newPtr->returnValue = oldPtr->returnValue;\n    copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateStringOfMM --\n *\n *\tUpdate the string representation for a pixel Tcl_Obj this function is\n *\tonly called, if the pixel Tcl_Obj has no unit, because with units the\n *\tstring representation is created by SetMMFromAny\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe object's string is set to a valid string that results from the\n *\tdouble-to-string conversion.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateStringOfMM(\n    Tcl_Obj *objPtr)   /* pixel obj with string rep to update. */\n{\n    MMRep *mmPtr;\n    char buffer[TCL_DOUBLE_SPACE];\n    size_t len;\n\n    mmPtr = (MMRep *)objPtr->internalRep.twoPtrValue.ptr1;\n    /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */\n    if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) {\n\tTcl_Panic(\"UpdateStringOfMM: false precondition\");\n    }\n\n    Tcl_PrintDouble(NULL, mmPtr->value, buffer);\n    len = strlen(buffer);\n\n    objPtr->bytes = (char *)Tcl_Alloc(len + 1);\n    strcpy(objPtr->bytes, buffer);\n    objPtr->length = len;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetMMFromAny --\n *\n *\tAttempt to generate a mm internal form for the Tcl object \"objPtr\".\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs during\n *\tconversion, an error message is left in the interpreter's result\n *\tunless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf no error occurs, a mm representation of the object is stored\n *\tinternally and the type of \"objPtr\" is set to mm.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetMMFromAny(\n    Tcl_Interp *interp,\t\t/* Used for error reporting if not NULL. */\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    ThreadSpecificData *typeCache = GetTypeCache();\n    const Tcl_ObjType *typePtr;\n    char *string;\n    char *rest;\n    double d;\n    int units;\n    MMRep *mmPtr;\n\n    if (objPtr->typePtr != typeCache->doubleTypePtr\n\t    && Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) {\n\td = (double) units;\n\tunits = -1;\n\n\t/*\n\t * In the case of ints, we need to ensure that a valid string exists\n\t * in order for int-but-not-string objects to be converted back to\n\t * ints again from mm obj types.\n\t */\n\n\t(void) Tcl_GetString(objPtr);\n    } else if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) {\n\tunits = -1;\n    } else {\n\tchar savechar;\n\n\t/*\n\t * It wasn't a known int or double, so parse it.\n\t */\n\n\tstring = Tcl_GetString(objPtr);\n\n\trest = string + strlen(string);\n\twhile ((rest > string) && isspace(UCHAR(rest[-1]))) {\n\t    --rest; /* skip all spaces at the end */\n\t}\n\tif (rest > string) {\n\t    --rest; /* point to the character just before the last space */\n\t}\n\tif (rest == string) {\n\terror:\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"expected screen distance but got \\\"%.50s\\\"\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tswitch (*rest) {\n\tcase 'c':\n\t    units = 0;\n\t    break;\n\tcase 'i':\n\t    units = 1;\n\t    break;\n\tcase 'm':\n\t    units = 2;\n\t    break;\n\tcase 'p':\n\t    units = 3;\n\t    break;\n\tdefault:\n\t    goto error;\n\t}\n\tsavechar = *rest;\n\t*rest = '\\0';\n\tif (Tcl_GetDouble(NULL, string, &d) != TCL_OK) {\n\t    *rest = savechar;\n\t    goto error;\n\t}\n\t*rest = savechar;\n    }\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n\n    objPtr->typePtr = &mmObjType;\n\n    mmPtr = (MMRep *)Tcl_Alloc(sizeof(MMRep));\n    mmPtr->value = d;\n    mmPtr->units = units;\n    mmPtr->tkwin = NULL;\n    mmPtr->returnValue\t= d;\n\n    objPtr->internalRep.twoPtrValue.ptr1 = mmPtr;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetWindowFromObj --\n *\n *\tAttempt to return a Tk_Window from the Tcl object \"objPtr\". If the\n *\tobject is not already a Tk_Window, an attempt will be made to convert\n *\tit to one.\n *\n * Results:\n *\tThe return value is a standard Tcl object result. If an error occurs\n *\tduring conversion, an error message is left in the interpreter's\n *\tresult unless \"interp\" is NULL.\n *\n * Side effects:\n *\tIf the object is not already a Tk_Window, the conversion will free any\n *\told internal representation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetWindowFromObj(\n    Tcl_Interp *interp,\t/* Used for error reporting if not NULL. */\n    Tk_Window tkwin,\t\t/* A token to get the main window from. */\n    Tcl_Obj *objPtr,\t\t/* The object from which to get window. */\n    Tk_Window *windowPtr)\t/* Place to store resulting window. */\n{\n    TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;\n    WindowRep *winPtr;\n\n    if (objPtr->typePtr != &windowObjType) {\n\tint result = SetWindowFromAny(interp, objPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n\n    winPtr = (WindowRep *)objPtr->internalRep.twoPtrValue.ptr1;\n    if (winPtr->tkwin == NULL\n\t    || winPtr->mainPtr == NULL\n\t    || winPtr->mainPtr != mainPtr\n\t    || winPtr->epoch != mainPtr->deletionEpoch) {\n\t/*\n\t * Cache is invalid.\n\t */\n\n\twinPtr->tkwin = Tk_NameToWindow(interp,\n\t\tTcl_GetString(objPtr), tkwin);\n\tif (winPtr->tkwin == NULL) {\n\t    /* ASSERT: Tk_NameToWindow has left error message in interp */\n\t    return TCL_ERROR;\n\t}\n\n\twinPtr->mainPtr = mainPtr;\n\twinPtr->epoch = mainPtr ? mainPtr->deletionEpoch : 0;\n    }\n\n    *windowPtr = winPtr->tkwin;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetWindowFromAny --\n *\n *\tGenerate a windowObj internal form for the Tcl object \"objPtr\".\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tSets objPtr's internal representation to an uninitialized windowObj.\n *\tFrees the old internal representation, if any.\n *\n * See also:\n *\tTkGetWindowFromObj, which initializes the WindowRep cache.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetWindowFromAny(\n    TCL_UNUSED(Tcl_Interp *),\n    Tcl_Obj *objPtr)\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n    WindowRep *winPtr;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n\n    winPtr = (WindowRep *)Tcl_Alloc(sizeof(WindowRep));\n    winPtr->tkwin = NULL;\n    winPtr->mainPtr = NULL;\n    winPtr->epoch = 0;\n\n    objPtr->internalRep.twoPtrValue.ptr1 = winPtr;\n    objPtr->typePtr = &windowObjType;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DupWindowInternalRep --\n *\n *\tInitialize the internal representation of a window Tcl_Obj to a copy\n *\tof the internal representation of an existing window object.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tcopyPtr's internal rep is set to refer to the same window as srcPtr's\n *\tinternal rep.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDupWindowInternalRep(\n    Tcl_Obj *srcPtr,\n    Tcl_Obj *copyPtr)\n{\n    WindowRep *oldPtr, *newPtr;\n\n    oldPtr = (WindowRep *)srcPtr->internalRep.twoPtrValue.ptr1;\n    newPtr = (WindowRep *)Tcl_Alloc(sizeof(WindowRep));\n    newPtr->tkwin = oldPtr->tkwin;\n    newPtr->mainPtr = oldPtr->mainPtr;\n    newPtr->epoch = oldPtr->epoch;\n    copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;\n    copyPtr->typePtr = srcPtr->typePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeWindowInternalRep --\n *\n *\tDeallocate the storage associated with a window object's internal\n *\trepresentation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees objPtr's internal representation and sets objPtr's internalRep\n *\tto NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeWindowInternalRep(\n    Tcl_Obj *objPtr)\t\t/* Window object with internal rep to free. */\n{\n    Tcl_Free(objPtr->internalRep.twoPtrValue.ptr1);\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    objPtr->typePtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_NewWindowObj --\n *\n *\tThis function allocates a new Tcl_Obj that refers to a particular\n *\tTk window.\n *\n * Results:\n *\tA standard Tcl object reference, with refcount 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_NewWindowObj(\n    Tk_Window tkwin)\n{\n    Tcl_Obj *objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), TCL_INDEX_NONE);\n    TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;\n    WindowRep *winPtr;\n\n    SetWindowFromAny(NULL, objPtr);\n\n    winPtr = (WindowRep *)objPtr->internalRep.twoPtrValue.ptr1;\n    winPtr->tkwin = tkwin;\n    winPtr->mainPtr = mainPtr;\n    winPtr->epoch = mainPtr->deletionEpoch;\n    return objPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkParsePadAmount --\n *\n *\tThis function parses a padding specification and returns the\n *\tappropriate padding values. A padding specification can be either a\n *\tsingle pixel width, or a list of two pixel widths. If a single pixel\n *\twidth, the amount specified is used for padding on both sides. If two\n *\tamounts are specified, then they specify the left/right or top/bottom\n *\tpadding.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tAn error message is written to the interpreter if something is not\n *\tright.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkParsePadAmount(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* A window.  Needed by Tk_GetPixels() */\n    Tcl_Obj *specObj,\t\t/* The argument to \"-padx\", \"-pady\", \"-ipadx\",\n\t\t\t\t * or \"-ipady\". The thing to be parsed. */\n    int *halfPtr,\t\t/* Write the left/top part of padding here */\n    int *allPtr)\t\t/* Write the total padding here */\n{\n    int firstInt, secondInt;    /* The two components of the padding */\n    Tcl_Size objc;\t\t\t/* The length of the list (should be 1 or 2) */\n    Tcl_Obj **objv;\t\t/* The objects in the list */\n\n    /*\n     * Check for a common case where a single object would otherwise be\n     * shimmered between a list and a pixel spec.\n     */\n\n    if (specObj->typePtr == &pixelObjType) {\n\tif (Tk_GetPixelsFromObj(interp, tkwin, specObj, &firstInt) != TCL_OK){\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad pad value \\\"%s\\\": must be positive screen distance\",\n\t\t    Tcl_GetString(specObj)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PADDING\", \"DIST\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tsecondInt = firstInt;\n\tgoto done;\n    }\n\n    /*\n     * Pad specifications are a list of one or two elements, each of which is\n     * a pixel specification.\n     */\n\n    if (Tcl_ListObjGetElements(interp, specObj, &objc, &objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (objc != 1 && objc != 2) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"wrong number of parts to pad specification\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PADDING\", \"PARTS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the first part.\n     */\n\n    if (Tk_GetPixelsFromObj(interp, tkwin, objv[0], &firstInt) != TCL_OK ||\n\t    (firstInt < 0)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad pad value \\\"%s\\\": must be positive screen distance\",\n\t\tTcl_GetString(objv[0])));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PADDING\", \"DIST\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the second part if it exists, otherwise it is as if it was the\n     * same as the first part.\n     */\n\n    if (objc == 1) {\n\tsecondInt = firstInt;\n    } else if (Tk_GetPixelsFromObj(interp, tkwin, objv[1],\n\t    &secondInt) != TCL_OK || (secondInt < 0)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad 2nd pad value \\\"%s\\\": must be positive screen distance\",\n\t\tTcl_GetString(objv[1])));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PADDING\", \"DIST\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Write the parsed bits back into the receiving variables.\n     */\n\n  done:\n    if (halfPtr != 0) {\n\t*halfPtr = firstInt;\n    }\n    *allPtr = firstInt + secondInt;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkRegisterObjTypes --\n *\n *\tRegisters Tk's Tcl_ObjType structures with the Tcl run-time.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tAll instances of Tcl_ObjType structures used in Tk are registered with\n *\tTcl.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkRegisterObjTypes(void)\n{\n    Tcl_RegisterObjType(&tkBorderObjType);\n    Tcl_RegisterObjType(&tkBitmapObjType);\n    Tcl_RegisterObjType(&tkColorObjType);\n    Tcl_RegisterObjType(&tkCursorObjType);\n    Tcl_RegisterObjType(&tkFontObjType);\n    Tcl_RegisterObjType(&mmObjType);\n    Tcl_RegisterObjType(&pixelObjType);\n    Tcl_RegisterObjType(&tkStateKeyObjType);\n    Tcl_RegisterObjType(&windowObjType);\n    Tcl_RegisterObjType(&tkTextIndexType);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkOldConfig.c",
    "content": "/*\n * tkOldConfig.c --\n *\n *\tThis file contains the Tk_ConfigureWidget function. THIS FILE IS HERE\n *\tFOR BACKWARD COMPATIBILITY; THE NEW CONFIGURATION PACKAGE SHOULD BE\n *\tUSED FOR NEW PROJECTS.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Values for \"flags\" field of Tk_ConfigSpec structures. Be sure to coordinate\n * these values with those defined in tk.h (TK_CONFIG_COLOR_ONLY, etc.) There\n * must not be overlap!\n */\n\n#ifndef TK_CONFIG_OPTION_SPECIFIED\n#  define TK_CONFIG_OPTION_SPECIFIED      (1 << 4)\n#endif\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tDoConfig(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tk_ConfigSpec *specPtr, Tcl_Obj *value,\n\t\t\t    void *widgRec);\nstatic Tk_ConfigSpec *\tFindConfigSpec(Tcl_Interp *interp,\n\t\t\t    Tk_ConfigSpec *specs, const char *argvName,\n\t\t\t    int needFlags, int hateFlags);\nstatic char *\t\tFormatConfigInfo(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const Tk_ConfigSpec *specPtr, void *widgRec);\nstatic const char *\tFormatConfigValue(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const Tk_ConfigSpec *specPtr, void *widgRec,\n\t\t\t    char *buffer, Tcl_FreeProc **freeProcPtr);\nstatic Tk_ConfigSpec *\tGetCachedSpecs(Tcl_Interp *interp,\n\t\t\t    const Tk_ConfigSpec *staticSpecs);\nstatic void\t\tDeleteSpecCacheTable(void *clientData,\n\t\t\t    Tcl_Interp *interp);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ConfigureWidget --\n *\n *\tProcess command-line options and database options to fill in fields of\n *\ta widget record with resources and other parameters.\n *\n * Results:\n *\tA standard Tcl return value. In case of an error, the interp's result\n *\twill hold an error message.\n *\n * Side effects:\n *\tThe fields of widgRec get filled in with information from objc/objv\n *\tand the option database. Old information in widgRec's fields gets\n *\trecycled. A copy of the spec-table is taken with (some of) the char*\n *\tfields converted into Tk_Uid fields; this copy will be released when\n *\tthe interpreter terminates.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ConfigureWidget(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Window containing widget (needed to set up\n\t\t\t\t * X resources). */\n    const Tk_ConfigSpec *specs,\t/* Describes legal options. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const *objv,\t\t/* Command-line options. */\n    void *widgRec,\t\t/* Record whose fields are to be modified.\n\t\t\t\t * Values must be properly initialized. */\n    int flags)\t\t\t/* Used to specify additional flags that must\n\t\t\t\t * be present in config specs for them to be\n\t\t\t\t * considered. Also, may have\n\t\t\t\t * TK_CONFIG_ARGV_ONLY set. */\n{\n    Tk_ConfigSpec *specPtr, *staticSpecs;\n    Tk_Uid value;\t\t/* Value of option from database. */\n    int needFlags;\t\t/* Specs must contain this set of flags or\n\t\t\t\t * else they are not considered. */\n    int hateFlags;\t\t/* If a spec contains any bits here, it's not\n\t\t\t\t * considered. */\n\n    if (tkwin == NULL) {\n\t/*\n\t * Either we're not really in Tk, or the main window was destroyed and\n\t * we're on our way out of the application\n\t */\n\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"NULL main window\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"NO_MAIN_WINDOW\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);\n    if (Tk_Depth(tkwin) <= 1) {\n\thateFlags = TK_CONFIG_COLOR_ONLY;\n    } else {\n\thateFlags = TK_CONFIG_MONO_ONLY;\n    }\n\n    /*\n     * Get the build of the config for this interpreter.\n     */\n\n    staticSpecs = GetCachedSpecs(interp, specs);\n\n    for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {\n\tspecPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;\n    }\n\n    /*\n     * Pass one: scan through all of the arguments, processing those that\n     * match entries in the specs.\n     */\n\n    for ( ; objc > 0; objc -= 2, objv += 2) {\n\tconst char *arg;\n\n\targ = Tcl_GetString(*objv);\n\tspecPtr = FindConfigSpec(interp, staticSpecs, arg, needFlags, hateFlags);\n\tif (specPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Process the entry.\n\t */\n\n\tif (objc < 2) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", arg));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE_MISSING\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (DoConfig(interp, tkwin, specPtr, objv[1], widgRec) != TCL_OK) {\n\t    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t    \"\\n    (processing \\\"%.40s\\\" option)\",specPtr->argvName));\n\t    return TCL_ERROR;\n\t}\n\tif (!(flags & TK_CONFIG_ARGV_ONLY)) {\n\t    specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;\n\t}\n    }\n\n    /*\n     * Pass two: scan through all of the specs again; if no command-line\n     * argument matched a spec, then check for info in the option database.\n     * If there was nothing in the database, then use the default.\n     */\n\n    if (!(flags & TK_CONFIG_ARGV_ONLY)) {\n\tfor (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {\n\t    if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)\n\t\t    || (specPtr->argvName == NULL)\n\t\t    || (specPtr->type == TK_CONFIG_SYNONYM)) {\n\t\tcontinue;\n\t    }\n\t    if (((specPtr->specFlags & needFlags) != needFlags)\n\t\t    || (specPtr->specFlags & hateFlags)) {\n\t\tcontinue;\n\t    }\n\t    value = NULL;\n\t    if (specPtr->dbName != NULL) {\n\t\tvalue = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);\n\t    }\n\t    if (value != NULL) {\n\t\tTcl_Obj *arg = Tcl_NewStringObj(value, TCL_INDEX_NONE);\n\t\tTcl_IncrRefCount(arg);\n\t\tif (DoConfig(interp, tkwin, specPtr, arg, widgRec) !=\n\t\t\tTCL_OK) {\n\t\t    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\t    \"\\n    (%s \\\"%.50s\\\" in widget \\\"%.50s\\\")\",\n\t\t\t    \"database entry for\", specPtr->dbName,\n\t\t\t    Tk_PathName(tkwin)));\n\t\t    Tcl_DecrRefCount(arg);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tTcl_DecrRefCount(arg);\n\t    } else {\n\t\tif ((specPtr->defValue != NULL) && !(specPtr->specFlags\n\t\t\t& TK_CONFIG_DONT_SET_DEFAULT)) {\n\t\t    Tcl_Obj *arg = Tcl_NewStringObj(specPtr->defValue, TCL_INDEX_NONE);\n\t\t    Tcl_IncrRefCount(arg);\n\t\t    if (DoConfig(interp, tkwin, specPtr, arg, widgRec) !=\n\t\t\t    TCL_OK) {\n\t\t\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\t\t\"\\n    (%s \\\"%.50s\\\" in widget \\\"%.50s\\\")\",\n\t\t\t\t\"default value for\", specPtr->dbName,\n\t\t\t\tTk_PathName(tkwin)));\n\t\t\tTcl_DecrRefCount(arg);\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    Tcl_DecrRefCount(arg);\n\t\t}\n\t    }\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FindConfigSpec --\n *\n *\tSearch through a table of configuration specs, looking for one that\n *\tmatches a given argvName.\n *\n * Results:\n *\tThe return value is a pointer to the matching entry, or NULL if\n *\tnothing matched. In that case an error message is left in the interp's\n *\tresult.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tk_ConfigSpec *\nFindConfigSpec(\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    Tk_ConfigSpec *specs,\t/* Pointer to table of configuration\n\t\t\t\t * specifications for a widget. */\n    const char *argvName,\t/* Name (suitable for use in a \"config\"\n\t\t\t\t * command) identifying particular option. */\n    int needFlags,\t\t/* Flags that must be present in matching\n\t\t\t\t * entry. */\n    int hateFlags)\t\t/* Flags that must NOT be present in matching\n\t\t\t\t * entry. */\n{\n    Tk_ConfigSpec *specPtr;\n    char c;\t\t/* First character of current argument. */\n    Tk_ConfigSpec *matchPtr;\t/* Matching spec, or NULL. */\n    size_t length;\n\n    c = argvName[1];\n    length = strlen(argvName);\n    matchPtr = NULL;\n    for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {\n\tif (specPtr->argvName == NULL) {\n\t    continue;\n\t}\n\tif ((specPtr->argvName[1] != c)\n\t\t|| (strncmp(specPtr->argvName, argvName, length) != 0)) {\n\t    continue;\n\t}\n\tif (((specPtr->specFlags & needFlags) != needFlags)\n\t\t|| (specPtr->specFlags & hateFlags)) {\n\t    continue;\n\t}\n\tif (specPtr->argvName[length] == 0) {\n\t    matchPtr = specPtr;\n\t    goto gotMatch;\n\t}\n\tif (matchPtr != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"ambiguous option \\\"%s\\\"\", argvName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"OPTION\", argvName, (char *)NULL);\n\t    return NULL;\n\t}\n\tmatchPtr = specPtr;\n    }\n\n    if (matchPtr == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"unknown option \\\"%s\\\"\", argvName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"OPTION\", argvName, (char *)NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Found a matching entry. If it's a synonym, then find the entry that\n     * it's a synonym for.\n     */\n\n  gotMatch:\n    specPtr = matchPtr;\n    if (specPtr->type == TK_CONFIG_SYNONYM) {\n\tfor (specPtr = specs; ; specPtr++) {\n\t    if (specPtr->type == TK_CONFIG_END) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"couldn't find synonym for option \\\"%s\\\"\",\n\t\t\targvName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"OPTION\", argvName,\n\t\t\t(char *)NULL);\n\t\treturn NULL;\n\t    }\n\t    if ((specPtr->dbName == matchPtr->dbName)\n\t\t    && (specPtr->type != TK_CONFIG_SYNONYM)\n\t\t    && ((specPtr->specFlags & needFlags) == needFlags)\n\t\t    && !(specPtr->specFlags & hateFlags)) {\n\t\tbreak;\n\t    }\n\t}\n    }\n    return specPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DoConfig --\n *\n *\tThis function applies a single configuration option to a widget\n *\trecord.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tWidgRec is modified as indicated by specPtr and value. The old value\n *\tis recycled, if that is appropriate for the value type.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nDoConfig(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Window containing widget (needed to set up\n\t\t\t\t * X resources). */\n    Tk_ConfigSpec *specPtr,\t/* Specifier to apply. */\n    Tcl_Obj *arg,\t\t/* Value to use to fill in widgRec. */\n    void *widgRec)\t\t/* Record whose fields are to be modified.\n\t\t\t\t * Values must be properly initialized. */\n{\n    void *ptr;\n    int nullValue = 0;\n    const char *value = Tcl_GetString(arg);\n\n    if ((*value == 0) && (specPtr->specFlags & TCL_NULL_OK)) {\n\tnullValue = 1;\n    }\n\n    if ((specPtr->specFlags & TK_CONFIG_OBJS) && (specPtr->type != TK_CONFIG_STRING)\n\t    && (specPtr->type != TK_CONFIG_PIXELS)) {\n\t/* Prevent surprises for other options than TK_CONFIG_(STRING|PIXELS) */\n\tTcl_AppendResult(interp, \"TK_CONFIG_OBJS not supported\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    do {\n\tif (specPtr->offset < 0) {\n\t    break;\n\t}\n\tptr = (char *)widgRec + specPtr->offset;\n\tswitch (specPtr->type) {\n\tcase TK_CONFIG_BOOLEAN:\n\t    if (Tcl_GetBooleanFromObj(interp, arg, (int *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_INT:\n\t    if (Tcl_GetIntFromObj(interp, arg, (int *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_DOUBLE:\n\t    if (Tcl_GetDoubleFromObj(interp, arg, (double *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_STRING: {\n\t    char *oldStr, *newStr;\n\n\t    if (nullValue) {\n\t\tnewStr = NULL;\n\t    } else if (specPtr->specFlags & TK_CONFIG_OBJS) {\n\t\tTcl_IncrRefCount(arg);\n\t\tnewStr = (char *)arg;\n\t    } else {\n\t\tnewStr = (char *)Tcl_Alloc(strlen(value) + 1);\n\t\tstrcpy(newStr, value);\n\t    }\n\t    oldStr = *((char **)ptr);\n\t    if (oldStr != NULL) {\n\t\tif (specPtr->specFlags & TK_CONFIG_OBJS) {\n\t\t    Tcl_DecrRefCount((Tcl_Obj *)oldStr);\n\t\t} else {\n\t\t    Tcl_Free(oldStr);\n\t\t}\n\t    }\n\t    *((char **)ptr) = newStr;\n\t    break;\n\t}\n\tcase TK_CONFIG_UID:\n\t    if (nullValue) {\n\t\t*((Tk_Uid *)ptr) = NULL;\n\t    } else {\n\t\t*((Tk_Uid *)ptr) = Tk_GetUid(value);\n\t    }\n\t    break;\n\tcase TK_CONFIG_COLOR: {\n\t    XColor *newPtr, *oldPtr;\n\n\t    if (nullValue) {\n\t\tnewPtr = NULL;\n\t    } else {\n\t\tnewPtr = Tk_AllocColorFromObj(interp, tkwin, arg);\n\t\tif (newPtr == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    oldPtr = *((XColor **)ptr);\n\t    if (oldPtr != NULL) {\n\t\tTk_FreeColor(oldPtr);\n\t    }\n\t    *((XColor **)ptr) = newPtr;\n\t    break;\n\t}\n\tcase TK_CONFIG_FONT: {\n\t    Tk_Font newFont;\n\n\t    if (nullValue) {\n\t\tnewFont = NULL;\n\t    } else {\n\t\tnewFont = Tk_AllocFontFromObj(interp, tkwin, arg);\n\t\tif (newFont == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    Tk_FreeFont(*((Tk_Font *)ptr));\n\t    *((Tk_Font *)ptr) = newFont;\n\t    break;\n\t}\n\tcase TK_CONFIG_BITMAP: {\n\t    Pixmap newBmp, oldBmp;\n\n\t    if (nullValue) {\n\t\tnewBmp = None;\n\t    } else {\n\t\tnewBmp = Tk_AllocBitmapFromObj(interp, tkwin, arg);\n\t\tif (newBmp == None) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    oldBmp = *((Pixmap *)ptr);\n\t    if (oldBmp != None) {\n\t\tTk_FreeBitmap(Tk_Display(tkwin), oldBmp);\n\t    }\n\t    *((Pixmap *)ptr) = newBmp;\n\t    break;\n\t}\n\tcase TK_CONFIG_BORDER: {\n\t    Tk_3DBorder newBorder, oldBorder;\n\n\t    if (nullValue) {\n\t\tnewBorder = NULL;\n\t    } else {\n\t\tnewBorder = Tk_Alloc3DBorderFromObj(interp, tkwin, arg);\n\t\tif (newBorder == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    oldBorder = *((Tk_3DBorder *)ptr);\n\t    if (oldBorder != NULL) {\n\t\tTk_Free3DBorder(oldBorder);\n\t    }\n\t    *((Tk_3DBorder *)ptr) = newBorder;\n\t    break;\n\t}\n\tcase TK_CONFIG_RELIEF:\n\t    if (Tk_GetReliefFromObj(interp, arg, (int *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_CURSOR:\n\tcase TK_CONFIG_ACTIVE_CURSOR: {\n\t    Tk_Cursor newCursor, oldCursor;\n\n\t    if (nullValue) {\n\t\tnewCursor = NULL;\n\t    } else {\n\t\tnewCursor = Tk_AllocCursorFromObj(interp, tkwin, arg);\n\t\tif (newCursor == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    oldCursor = *((Tk_Cursor *)ptr);\n\t    if (oldCursor != NULL) {\n\t\tTk_FreeCursor(Tk_Display(tkwin), oldCursor);\n\t    }\n\t    *((Tk_Cursor *)ptr) = newCursor;\n\t    if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) {\n\t\tTk_DefineCursor(tkwin, newCursor);\n\t    }\n\t    break;\n\t}\n\tcase TK_CONFIG_JUSTIFY:\n\t    if (Tk_GetJustifyFromObj(interp, arg, (Tk_Justify *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_ANCHOR:\n\t    if (Tk_GetAnchorFromObj(interp, arg, (Tk_Anchor *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_CAP_STYLE:\n\t    if (Tk_GetCapStyle(interp, value, (int *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_JOIN_STYLE:\n\t    if (Tk_GetJoinStyle(interp, value, (int *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_PIXELS: {\n\t    bool nullOK = (specPtr->specFlags & TCL_NULL_OK) != 0;\n\t    if (specPtr->specFlags & TK_CONFIG_OBJS) {\n\t\tint dummy;\n\t\tif (nullValue) {\n\t\t    if (*(Tcl_Obj **)ptr != NULL) {\n\t\t\tTcl_DecrRefCount(*(Tcl_Obj **)ptr);\n\t\t\t*(Tcl_Obj **)ptr = NULL;\n\t\t    }\n\t\t} else if (Tk_GetPixelsFromObj((nullOK ? NULL : interp), tkwin, arg, &dummy)\n\t\t\t!= TCL_OK) {\n\t\twrongPixel:\n\t\t    if (interp && nullOK) {\n\t\t\tTcl_AppendResult(interp, \"expected screen distance or \\\"\\\" but got \\\"\",\n\t\t\t\tTcl_GetString(arg), \"\\\"\", (char *)NULL);\n\t\t    }\n\t\t    return TCL_ERROR;\n\t\t} else if (!(specPtr->specFlags & TK_OPTION_NEG_OK) && (dummy < 0)) {\n\t\t\tif (interp) {\n\t\t\t    Tcl_AppendResult(interp, \"expected screen distance \",\n\t\t\t\t    nullOK ? \" or \\\"\\\"\" : \"\",\n\t\t\t\t    \"but got \\\"\", Tcl_GetString(arg), \"\\\"\", (char *)NULL);\n\t\t\t}\n\t\t\treturn TCL_ERROR;\n\t\t} else {\n\t\t    Tcl_IncrRefCount(arg);\n\t\t    if (*(Tcl_Obj **)ptr != NULL) {\n\t\t\tTcl_DecrRefCount(*(Tcl_Obj **)ptr);\n\t\t    }\n\t\t    *(Tcl_Obj **)ptr = arg;\n\t\t}\n\t    } else if (nullValue) {\n\t\t*(int *)ptr = INT_MIN;\n\t    } else if (Tk_GetPixelsFromObj((nullOK ? NULL : interp), tkwin, arg, (int *)ptr)\n\t\t!= TCL_OK) {\n\t\tgoto wrongPixel;\n\t    }\n\t    break;\n\t}\n\tcase TK_CONFIG_MM:\n\t    if (Tk_GetScreenMM(interp, tkwin, value, (double *)ptr) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase TK_CONFIG_WINDOW: {\n\t    Tk_Window tkwin2;\n\n\t    if (nullValue) {\n\t\ttkwin2 = NULL;\n\t    } else {\n\t\ttkwin2 = Tk_NameToWindow(interp, value, tkwin);\n\t\tif (tkwin2 == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    *((Tk_Window *)ptr) = tkwin2;\n\t    break;\n\t}\n\tcase TK_CONFIG_CUSTOM:\n\t    if (specPtr->customPtr->parseProc(specPtr->customPtr->clientData,\n\t\t    interp, tkwin, value, (char *)widgRec, specPtr->offset)!=TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tdefault:\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad config table: unknown type %d\", specPtr->type));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"BAD_CONFIG\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tspecPtr++;\n    } while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ConfigureInfo --\n *\n *\tReturn information about the configuration options for a window, and\n *\ttheir current values.\n *\n * Results:\n *\tAlways returns TCL_OK. The interp's result will be modified hold a\n *\tdescription of either a single configuration option available for\n *\t\"widgRec\" via \"specs\", or all the configuration options available. In\n *\tthe \"all\" case, the result will available for \"widgRec\" via \"specs\".\n *\tThe result will be a list, each of whose entries describes one option.\n *\tEach entry will itself be a list containing the option's name for use\n *\ton command lines, database name, database class, default value, and\n *\tcurrent value (empty string if none). For options that are synonyms,\n *\tthe list will contain only two values: name and synonym name. If the\n *\t\"name\" argument is non-NULL, then the only information returned is\n *\tthat for the named argument (i.e. the corresponding entry in the\n *\toverall list is returned).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ConfigureInfo(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Window corresponding to widgRec. */\n    const Tk_ConfigSpec *specs, /* Describes legal options. */\n    void *widgRec,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    const char *argvName,\t/* If non-NULL, indicates a single option\n\t\t\t\t * whose info is to be returned. Otherwise\n\t\t\t\t * info is returned for all options. */\n    int flags)\t\t\t/* Used to specify additional flags that must\n\t\t\t\t * be present in config specs for them to be\n\t\t\t\t * considered. */\n{\n    Tk_ConfigSpec *specPtr, *staticSpecs;\n    int needFlags, hateFlags;\n    char *list;\n    const char *leader = \"{\";\n\n    needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);\n    if (Tk_Depth(tkwin) <= 1) {\n\thateFlags = TK_CONFIG_COLOR_ONLY;\n    } else {\n\thateFlags = TK_CONFIG_MONO_ONLY;\n    }\n\n    /*\n     * Get the build of the config for this interpreter.\n     */\n\n    staticSpecs = GetCachedSpecs(interp, specs);\n\n    /*\n     * If information is only wanted for a single configuration spec, then\n     * handle that one spec specially.\n     */\n\n    Tcl_ResetResult(interp);\n    if (argvName != NULL) {\n\tspecPtr = FindConfigSpec(interp, staticSpecs, argvName, needFlags,\n\t\thateFlags);\n\tif (specPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tlist = FormatConfigInfo(interp, tkwin, specPtr, widgRec);\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(list, TCL_INDEX_NONE));\n\tTcl_Free(list);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Loop through all the specs, creating a big list with all their\n     * information.\n     */\n\n    for (specPtr = staticSpecs; specPtr->type != TK_CONFIG_END; specPtr++) {\n\tif ((argvName != NULL) && (specPtr->argvName != argvName)) {\n\t    continue;\n\t}\n\tif (((specPtr->specFlags & needFlags) != needFlags)\n\t\t|| (specPtr->specFlags & hateFlags)) {\n\t    continue;\n\t}\n\tif ((specPtr->argvName == NULL) || (specPtr->offset < 0)) {\n\t    continue;\n\t}\n\tlist = FormatConfigInfo(interp, tkwin, specPtr, widgRec);\n\tTcl_AppendResult(interp, leader, list, \"}\", (char *)NULL);\n\tTcl_Free(list);\n\tleader = \" {\";\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FormatConfigInfo --\n *\n *\tCreate a valid Tcl list holding the configuration information for a\n *\tsingle configuration option.\n *\n * Results:\n *\tA Tcl list, dynamically allocated. The caller is expected to arrange\n *\tfor this list to be freed eventually.\n *\n * Side effects:\n *\tMemory is allocated.\n *\n *--------------------------------------------------------------\n */\n\nstatic char *\nFormatConfigInfo(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for things like\n\t\t\t\t * floating-point precision. */\n    Tk_Window tkwin,\t\t/* Window corresponding to widget. */\n    const Tk_ConfigSpec *specPtr,\n\t\t\t\t/* Pointer to information describing\n\t\t\t\t * option. */\n    void *widgRec)\t\t/* Pointer to record holding current values of\n\t\t\t\t * info for widget. */\n{\n    const char *argv[6];\n    char *result;\n    char buffer[200];\n    Tcl_FreeProc *freeProc = NULL;\n\n    argv[0] = specPtr->argvName;\n    argv[1] = specPtr->dbName;\n    argv[2] = specPtr->dbClass;\n    argv[3] = specPtr->defValue;\n    if (specPtr->type == TK_CONFIG_SYNONYM) {\n\treturn Tcl_Merge(2, argv);\n    }\n    argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,\n\t    &freeProc);\n    if (argv[1] == NULL) {\n\targv[1] = \"\";\n    }\n    if (argv[2] == NULL) {\n\targv[2] = \"\";\n    }\n    if (argv[3] == NULL) {\n\targv[3] = \"\";\n    }\n    if (argv[4] == NULL) {\n\targv[4] = \"\";\n    }\n    result = Tcl_Merge(5, argv);\n    if (freeProc != NULL) {\n\tif (freeProc == TCL_DYNAMIC) {\n\t    Tcl_Free((void *)argv[4]);\n\t} else {\n\t    freeProc((void *)argv[4]);\n\t}\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FormatConfigValue --\n *\n *\tThis function formats the current value of a configuration option.\n *\n * Results:\n *\tThe return value is the formatted value of the option given by specPtr\n *\tand widgRec. If the value is static, so that it need not be freed,\n *\t*freeProcPtr will be set to NULL; otherwise *freeProcPtr will be set\n *\tto the address of a function to free the result, and the caller must\n *\tinvoke this function when it is finished with the result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const char *\nFormatConfigValue(\n    Tcl_Interp *interp,\t\t/* Interpreter for use in real conversions. */\n    Tk_Window tkwin,\t\t/* Window corresponding to widget. */\n    const Tk_ConfigSpec *specPtr, /* Pointer to information describing option.\n\t\t\t\t * Must not point to a synonym option. */\n    void *widgRec,\t\t/* Pointer to record holding current values of\n\t\t\t\t * info for widget. */\n    char *buffer,\t\t/* Static buffer to use for small values.\n\t\t\t\t * Must have at least 200 bytes of storage. */\n    Tcl_FreeProc **freeProcPtr)\t/* Pointer to word to fill in with address of\n\t\t\t\t * function to free the result, or NULL if\n\t\t\t\t * result is static. */\n{\n    void *ptr;\n    const char *result;\n\n    *freeProcPtr = NULL;\n    if (specPtr->offset < 0) {\n\treturn NULL;\n    }\n    ptr = (char *)widgRec + specPtr->offset;\n    result = \"\";\n    if (specPtr->specFlags & TK_CONFIG_OBJS) {\n\tif (*(Tcl_Obj **)ptr != NULL) {\n\t    result = Tcl_GetString(*(Tcl_Obj **)ptr);\n\t}\n\treturn result;\n    }\n    switch (specPtr->type) {\n    case TK_CONFIG_BOOLEAN:\n\tif (*((int *)ptr) == 0) {\n\t    result = \"0\";\n\t} else {\n\t    result = \"1\";\n\t}\n\tbreak;\n    case TK_CONFIG_INT:\n\tsnprintf(buffer, 200, \"%d\", *((int *)ptr));\n\tresult = buffer;\n\tbreak;\n    case TK_CONFIG_DOUBLE:\n\tTcl_PrintDouble(interp, *((double *)ptr), buffer);\n\tresult = buffer;\n\tbreak;\n    case TK_CONFIG_STRING:\n\tresult = *(char **)ptr;\n\tif (result == NULL) {\n\t    result = \"\";\n\t}\n\tbreak;\n    case TK_CONFIG_UID: {\n\tTk_Uid uid = *((Tk_Uid *)ptr);\n\n\tif (uid != NULL) {\n\t    result = uid;\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_COLOR: {\n\tXColor *colorPtr = *((XColor **)ptr);\n\n\tif (colorPtr != NULL) {\n\t    result = Tk_NameOfColor(colorPtr);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_FONT: {\n\tTk_Font tkfont = *((Tk_Font *)ptr);\n\n\tif (tkfont != NULL) {\n\t    result = Tk_NameOfFont(tkfont);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_BITMAP: {\n\tPixmap pixmap = *((Pixmap *)ptr);\n\n\tif (pixmap != None) {\n\t    result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_BORDER: {\n\tTk_3DBorder border = *((Tk_3DBorder *)ptr);\n\n\tif (border != NULL) {\n\t    result = Tk_NameOf3DBorder(border);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_RELIEF:\n\tresult = Tk_NameOfRelief(*((int *)ptr));\n\tbreak;\n    case TK_CONFIG_CURSOR:\n    case TK_CONFIG_ACTIVE_CURSOR: {\n\tTk_Cursor cursor = *((Tk_Cursor *)ptr);\n\n\tif (cursor != NULL) {\n\t    result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_JUSTIFY:\n\tresult = Tk_NameOfJustify(*((Tk_Justify *)ptr));\n\tbreak;\n    case TK_CONFIG_ANCHOR:\n\tresult = Tk_NameOfAnchor(*((Tk_Anchor *)ptr));\n\tbreak;\n    case TK_CONFIG_CAP_STYLE:\n\tresult = Tk_NameOfCapStyle(*((int *)ptr));\n\tbreak;\n    case TK_CONFIG_JOIN_STYLE:\n\tresult = Tk_NameOfJoinStyle(*((int *)ptr));\n\tbreak;\n    case TK_CONFIG_PIXELS:\n\tif ((*(int *)ptr != INT_MIN) || !(specPtr->specFlags & TCL_NULL_OK)) {\n\t    snprintf(buffer, 200, \"%d\", *((int *)ptr));\n\t    result = buffer;\n\t}\n\tbreak;\n    case TK_CONFIG_MM:\n\tTcl_PrintDouble(interp, *((double *)ptr), buffer);\n\tresult = buffer;\n\tbreak;\n    case TK_CONFIG_WINDOW: {\n\ttkwin = *((Tk_Window *)ptr);\n\tif (tkwin != NULL) {\n\t    result = Tk_PathName(tkwin);\n\t}\n\tbreak;\n    }\n    case TK_CONFIG_CUSTOM:\n\tresult = specPtr->customPtr->printProc(specPtr->customPtr->clientData,\n\t\ttkwin, (char *)widgRec, specPtr->offset, freeProcPtr);\n\tbreak;\n    default:\n\tresult = \"?? unknown type ??\";\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ConfigureValue --\n *\n *\tThis function returns the current value of a configuration option for\n *\ta widget.\n *\n * Results:\n *\tThe return value is a standard Tcl completion code (TCL_OK or\n *\tTCL_ERROR). The interp's result will be set to hold either the value\n *\tof the option given by argvName (if TCL_OK is returned) or an error\n *\tmessage (if TCL_ERROR is returned).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ConfigureValue(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Window corresponding to widgRec. */\n    const Tk_ConfigSpec *specs, /* Describes legal options. */\n    void *widgRec,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    const char *argvName,\t/* Gives the command-line name for the option\n\t\t\t\t * whose value is to be returned. */\n    int flags)\t\t\t/* Used to specify additional flags that must\n\t\t\t\t * be present in config specs for them to be\n\t\t\t\t * considered. */\n{\n    Tk_ConfigSpec *specPtr;\n    int needFlags, hateFlags;\n    Tcl_FreeProc *freeProc;\n    const char *result;\n    char buffer[200];\n\n    needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);\n    if (Tk_Depth(tkwin) <= 1) {\n\thateFlags = TK_CONFIG_COLOR_ONLY;\n    } else {\n\thateFlags = TK_CONFIG_MONO_ONLY;\n    }\n\n    /*\n     * Get the build of the config for this interpreter.\n     */\n\n    specPtr = GetCachedSpecs(interp, specs);\n\n    specPtr = FindConfigSpec(interp, specPtr, argvName, needFlags, hateFlags);\n    if (specPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n    result = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,\n\t    &freeProc);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(result, TCL_INDEX_NONE));\n    if (freeProc != NULL) {\n\tif (freeProc == TCL_DYNAMIC) {\n\t    Tcl_Free((void *)result);\n\t} else {\n\t    freeProc((void *)result);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeOptions --\n *\n *\tFree up all resources associated with configuration options.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAny resource in widgRec that is controlled by a configuration option\n *\t(e.g. a Tk_3DBorder or XColor) is freed in the appropriate fashion.\n *\n * Notes:\n *\tSince this is not looking anything up, this uses the static version of\n *\tthe config specs.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeOptions(\n    const Tk_ConfigSpec *specs,\t/* Describes legal options. */\n    void *widgRec,\t\t/* Record whose fields contain current values\n\t\t\t\t * for options. */\n    Display *display,\t\t/* X display; needed for freeing some\n\t\t\t\t * resources. */\n    int needFlags)\t\t/* Used to specify additional flags that must\n\t\t\t\t * be present in config specs for them to be\n\t\t\t\t * considered. */\n{\n    const Tk_ConfigSpec *specPtr;\n    char *ptr;\n\n    for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {\n\tif ((specPtr->specFlags & needFlags) != needFlags) {\n\t    continue;\n\t}\n\tif (specPtr->offset < 0) {\n\t    continue;\n\t}\n\tptr = (char *)widgRec + specPtr->offset;\n\tif ((specPtr->specFlags & TK_CONFIG_OBJS) && (*(Tcl_Obj **)ptr != NULL)) {\n\t    Tcl_DecrRefCount(*(Tcl_Obj **)ptr);\n\t    *(Tcl_Obj **)ptr = NULL;\n\t    continue;\n\t}\n\tswitch (specPtr->type) {\n\tcase TK_CONFIG_STRING:\n\t    if (*((char **)ptr) != NULL) {\n\t\tTcl_Free(*((char **)ptr));\n\t\t*((char **)ptr) = NULL;\n\t    }\n\t    break;\n\tcase TK_CONFIG_COLOR:\n\t    if (*((XColor **)ptr) != NULL) {\n\t\tTk_FreeColor(*((XColor **)ptr));\n\t\t*((XColor **)ptr) = NULL;\n\t    }\n\t    break;\n\tcase TK_CONFIG_FONT:\n\t    Tk_FreeFont(*((Tk_Font *)ptr));\n\t    *((Tk_Font *)ptr) = NULL;\n\t    break;\n\tcase TK_CONFIG_BITMAP:\n\t    if (*((Pixmap *)ptr) != None) {\n\t\tTk_FreeBitmap(display, *((Pixmap *)ptr));\n\t\t*((Pixmap *)ptr) = None;\n\t    }\n\t    break;\n\tcase TK_CONFIG_BORDER:\n\t    if (*((Tk_3DBorder *)ptr) != NULL) {\n\t\tTk_Free3DBorder(*((Tk_3DBorder *)ptr));\n\t\t*((Tk_3DBorder *)ptr) = NULL;\n\t    }\n\t    break;\n\tcase TK_CONFIG_CURSOR:\n\tcase TK_CONFIG_ACTIVE_CURSOR:\n\t    if (*((Tk_Cursor *)ptr) != NULL) {\n\t\tTk_FreeCursor(display, *((Tk_Cursor *)ptr));\n\t\t*((Tk_Cursor *)ptr) = NULL;\n\t    }\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetCachedSpecs --\n *\n *\tReturns a writable per-interpreter (and hence thread-local) copy of\n *\tthe given spec-table with (some of) the char* fields converted into\n *\tTk_Uid fields; this copy will be released when the interpreter\n *\tterminates (during AssocData cleanup).\n *\n * Results:\n *\tA pointer to the copied table.\n *\n * Notes:\n *\tThe conversion to Tk_Uid is only done the first time, when the table\n *\tcopy is taken. After that, the table is assumed to have Tk_Uids where\n *\tthey are needed. The time of deletion of the caches isn't very\n *\timportant unless you've got a lot of code that uses Tk_ConfigureWidget\n *\t(or *Info or *Value} when the interpreter is being deleted.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tk_ConfigSpec *\nGetCachedSpecs(\n    Tcl_Interp *interp,\t\t/* Interpreter in which to store the cache. */\n    const Tk_ConfigSpec *staticSpecs)\n\t\t\t\t/* Value to cache a copy of; it is also used\n\t\t\t\t * as a key into the cache. */\n{\n    Tk_ConfigSpec *cachedSpecs;\n    Tcl_HashTable *specCacheTablePtr;\n    Tcl_HashEntry *entryPtr;\n    int isNew;\n\n    /*\n     * Get (or allocate if it doesn't exist) the hash table that the writable\n     * copies of the widget specs are stored in. In effect, this is\n     * self-initializing code.\n     */\n\n    specCacheTablePtr = (Tcl_HashTable *)\n\t    Tcl_GetAssocData(interp, \"tkConfigSpec.threadTable\", NULL);\n    if (specCacheTablePtr == NULL) {\n\tspecCacheTablePtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tTcl_InitHashTable(specCacheTablePtr, TCL_ONE_WORD_KEYS);\n\tTcl_SetAssocData(interp, \"tkConfigSpec.threadTable\",\n\t\tDeleteSpecCacheTable, specCacheTablePtr);\n    }\n\n    /*\n     * Look up or create the hash entry that the constant specs are mapped to,\n     * which will have the writable specs as its associated value.\n     */\n\n    entryPtr = Tcl_CreateHashEntry(specCacheTablePtr, (char *) staticSpecs,\n\t    &isNew);\n    if (isNew) {\n\tsize_t entrySpace = sizeof(Tk_ConfigSpec);\n\tconst Tk_ConfigSpec *staticSpecPtr;\n\tTk_ConfigSpec *specPtr;\n\n\t/*\n\t * OK, no working copy in this interpreter so copy. Need to work out\n\t * how much space to allocate first.\n\t */\n\n\tfor (staticSpecPtr=staticSpecs; staticSpecPtr->type!=TK_CONFIG_END;\n\t\tstaticSpecPtr++) {\n\t    entrySpace += sizeof(Tk_ConfigSpec);\n\t}\n\n\t/*\n\t * Now allocate our working copy's space and copy over the contents\n\t * from the origin.\n\t */\n\n\tcachedSpecs = (Tk_ConfigSpec *)Tcl_Alloc(entrySpace);\n\tmemcpy(cachedSpecs, staticSpecs, entrySpace);\n\tTcl_SetHashValue(entryPtr, cachedSpecs);\n\n\t/*\n\t * Finally, go through and replace database names, database classes\n\t * and default values with Tk_Uids. This is the bit that has to be\n\t * per-thread.\n\t */\n\n\tfor (specPtr=cachedSpecs; specPtr->type!=TK_CONFIG_END; specPtr++) {\n\t    if (specPtr->argvName != NULL) {\n\t\tif (specPtr->dbName != NULL) {\n\t\t    specPtr->dbName = Tk_GetUid(specPtr->dbName);\n\t\t}\n\t\tif (specPtr->dbClass != NULL) {\n\t\t    specPtr->dbClass = Tk_GetUid(specPtr->dbClass);\n\t\t}\n\t\tif (specPtr->defValue != NULL) {\n\t\t    specPtr->defValue = Tk_GetUid(specPtr->defValue);\n\t\t}\n\t    }\n\t}\n    } else {\n\tcachedSpecs = (Tk_ConfigSpec *)Tcl_GetHashValue(entryPtr);\n    }\n\n    return cachedSpecs;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteSpecCacheTable --\n *\n *\tDelete the per-interpreter copy of all the Tk_ConfigSpec tables which\n *\twere stored in the interpreter's assoc-data store.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tNone (does *not* use any Tk API).\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteSpecCacheTable(\n    void *clientData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    Tcl_HashTable *tablePtr = (Tcl_HashTable *)clientData;\n    Tcl_HashEntry *entryPtr;\n    Tcl_HashSearch search;\n\n    for (entryPtr = Tcl_FirstHashEntry(tablePtr,&search); entryPtr != NULL;\n\t    entryPtr = Tcl_NextHashEntry(&search)) {\n\t/*\n\t * Someone else deallocates the Tk_Uids themselves.\n\t */\n\n\tTcl_Free(Tcl_GetHashValue(entryPtr));\n    }\n    Tcl_DeleteHashTable(tablePtr);\n    Tcl_Free(tablePtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkOption.c",
    "content": "/*\n * tkOption.c --\n *\n *\tThis module contains functions to manage the option database, which\n *\tallows various strings to be associated with windows either by name or\n *\tby class or both.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The option database is stored as one tree for each main window. Each name\n * or class field in an option is associated with a node or leaf of the tree.\n * For example, the options \"x.y.z\" and \"x.y*a\" each correspond to three nodes\n * in the tree; they share the nodes \"x\" and \"x.y\", but have different leaf\n * nodes. One of the following structures exists for each node or leaf in the\n * option tree. It is actually stored as part of the parent node, and\n * describes a particular child of the parent.\n *\n * The structure of the option db tree is a little confusing. There are four\n * different kinds of nodes in the tree:\n *\tinterior class nodes\n *\tinterior name nodes\n *\tleaf class nodes\n *\tleaf name nodes\n *\n * All interior nodes refer to _window_ classes and names; all leaf nodes\n * refer to _option_ classes and names. When looking for a particular option,\n * therefore, you must compare interior node values to corresponding window\n * values, and compare leaf node values to corresponding option values.\n *\n * The tree is actually stored in a collection of arrays; there is one each\n * combination of WILDCARD/EXACT and CLASS/NAME and NODE/LEAF. The NODE arrays\n * contain the interior nodes of the tree; each element has a pointer to an\n * array of elements which are the leaves of the tree. The LEAF arrays, rather\n * than holding the leaves of the tree, hold a cached subset of the option\n * database, consisting of the values of all defined options for a single\n * window, and some additional information about each ancestor of the window\n * (since some options may be inherited from a parent), all the way back to\n * the root window.\n *\n * Each time a call is made to Tk_GetOption, Tk will attempt to use the cached\n * information to satisfy the lookup. If the call is for a window other than\n * that for which options are currently cached, the portion of the cache that\n * contains information for common ancestors of the two windows is retained\n * and the remainder is discarded and rebuilt with new information for the new\n * window.\n */\n\ntypedef struct Element {\n    Tk_Uid nameUid;\t\t/* Name or class from one element of an option\n\t\t\t\t * spec. */\n    union {\n\tstruct ElArray *arrayPtr;\n\t\t\t\t/* If this is an intermediate node, a pointer\n\t\t\t\t * to a structure describing the remaining\n\t\t\t\t * elements of all options whose prefixes are\n\t\t\t\t * the same up through this element. */\n\tTk_Uid valueUid;\t/* For leaf nodes, this is the string value of\n\t\t\t\t * the option. */\n    } child;\n    int priority;\t\t/* Used to select among matching options.\n\t\t\t\t * Includes both the priority level and a\n\t\t\t\t * serial #. Greater value means higher\n\t\t\t\t * priority. Irrelevant except in leaf\n\t\t\t\t * nodes. */\n    int flags;\t\t\t/* OR-ed combination of bits. See below for\n\t\t\t\t * values. */\n} Element;\n\n/*\n * Flags in Element structures:\n *\n * CLASS -\t\tNon-zero means this element refers to a class, zero\n *\t\t\tmeans this element refers to a name.\n * NODE -\t\tZero means this is a leaf element (the child field is\n *\t\t\ta value, not a pointer to another node). One means\n *\t\t\tthis is a node element.\n * WILDCARD -\t\tNon-zero means this there was a star in the original\n *\t\t\tspecification just before this element. Zero means\n *\t\t\tthere was a dot.\n */\n\n#define TYPE_MASK\t\t0x7\n\n#define CLASS\t\t\t0x1\n#define NODE\t\t\t0x2\n#define WILDCARD\t\t0x4\n\n#define EXACT_LEAF_NAME\t\t0x0\n#define EXACT_LEAF_CLASS\t0x1\n#define EXACT_NODE_NAME\t\t0x2\n#define EXACT_NODE_CLASS\t0x3\n#define WILDCARD_LEAF_NAME\t0x4\n#define WILDCARD_LEAF_CLASS\t0x5\n#define WILDCARD_NODE_NAME\t0x6\n#define WILDCARD_NODE_CLASS\t0x7\n\n/*\n * The following structure is used to manage a dynamic array of Elements.\n * These structures are used for two purposes: to store the contents of a node\n * in the option tree, and for the option stacks described below.\n */\n\ntypedef struct ElArray {\n    int arraySize;\t\t/* Number of elements actually allocated in\n\t\t\t\t * the \"els\" array. */\n    int numUsed;\t\t/* Number of elements currently in use out of\n\t\t\t\t * els. */\n    Element *nextToUse;\t\t/* Pointer to &els[numUsed]. */\n    Element els[1];\t\t/* Array of structures describing children of\n\t\t\t\t * this node. The array will actually contain\n\t\t\t\t * enough elements for all of the children\n\t\t\t\t * (and even a few extras, perhaps). This must\n\t\t\t\t * be the last field in the structure. */\n} ElArray;\n\n#define EL_ARRAY_SIZE(numEls) ((unsigned) (sizeof(ElArray) \\\n\t+ ((numEls)-1)*sizeof(Element)))\n#define INITIAL_SIZE 5\n\n/*\n * In addition to the option tree, which is a relatively static structure,\n * there are eight additional structures called \"stacks\", which are used to\n * speed up queries into the option database. The stack structures are\n * designed for the situation where an individual widget makes repeated\n * requests for its particular options. The requests differ only in their last\n * name/class, so during the first request we extract all the options\n * pertaining to the particular widget and save them in a stack-like cache;\n * subsequent requests for the same widget can search the cache relatively\n * quickly. In fact, the cache is a hierarchical one, storing a list of\n * relevant options for this widget and all of its ancestors up to the\n * application root; hence the name \"stack\".\n *\n * Each of the eight stacks consists of an array of Elements, ordered in terms\n * of levels in the window hierarchy. All the elements relevant for the\n * top-level widget appear first in the array, followed by all those from the\n * next-level widget on the path to the current widget, etc. down to those for\n * the current widget.\n *\n * Cached information is divided into eight stacks according to the CLASS,\n * NODE, and WILDCARD flags. Leaf and non-leaf information is kept separate to\n * speed up individual probes (non-leaf information is only relevant when\n * building the stacks, but isn't relevant when making probes; similarly, only\n * non-leaf information is relevant when the stacks are being extended to the\n * next widget down in the widget hierarchy). Wildcard elements are handled\n * separately from \"exact\" elements because once they appear at a particular\n * level in the stack they remain active for all deeper levels; exact elements\n * are only relevant at a particular level. For example, when searching for\n * options relevant in a particular window, the entire wildcard stacks get\n * checked, but only the portions of the exact stacks that pertain to the\n * window's parent. Lastly, name and class stacks are kept separate because\n * different search keys are used when searching them; keeping them separate\n * speeds up the searches.\n */\n\n#define NUM_STACKS 8\n\n/*\n * One of the following structures is used to keep track of each level in the\n * stacks.\n */\n\ntypedef struct StackLevel {\n    TkWindow *winPtr;\t\t/* Window corresponding to this stack\n\t\t\t\t * level. */\n    int bases[NUM_STACKS];\t/* For each stack, index of first element on\n\t\t\t\t * stack corresponding to this level (used to\n\t\t\t\t * restore \"numUsed\" fields when popping out\n\t\t\t\t * of a level. */\n} StackLevel;\n\ntypedef struct {\n    bool initialized;\t\t/* 0 means the ThreadSpecific Data structure\n\t\t\t\t * for the current thread needs to be\n\t\t\t\t * initialized. */\n    ElArray *stacks[NUM_STACKS];\n    TkWindow *cachedWindow;\t/* Lowest-level window currently loaded in\n\t\t\t\t * stacks at present. NULL means stacks have\n\t\t\t\t * never been used, or have been invalidated\n\t\t\t\t * because of a change to the database. */\n    /*\n     * Information about all of the stack levels that are currently active.\n     * This array grows dynamically to become as large as needed.\n     */\n\n    StackLevel *levels;\t\t/* Array describing current stack. */\n    int numLevels;\t\t/* Total space allocated. */\n    int curLevel;\t\t/* Highest level currently in use. Note:\n\t\t\t\t * curLevel is never 0! (I don't remember why\n\t\t\t\t * anymore...) */\n    int serial;\t\t\t/* A serial number for all options entered\n\t\t\t\t * into the database so far. It increments on\n\t\t\t\t * each addition to the option database. It is\n\t\t\t\t * used in computing option priorities, so\n\t\t\t\t * that the most recent entry wins when\n\t\t\t\t * choosing between options at the same\n\t\t\t\t * priority level. */\n    Element defaultMatch;\t/* Special \"no match\" Element to use as\n\t\t\t\t * default for searches.*/\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic int\t\tAddFromString(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    char *string, int priority);\nstatic void\t\tClearOptionTree(ElArray *arrayPtr);\nstatic ElArray *\tExtendArray(ElArray *arrayPtr, Element *elPtr);\nstatic void\t\tExtendStacks(ElArray *arrayPtr, int leaf);\nstatic int\t\tGetDefaultOptions(Tcl_Interp *interp,\n\t\t\t    TkWindow *winPtr);\nstatic ElArray *\tNewArray(int numEls);\nstatic void\t\tOptionThreadExitProc(void *clientData);\nstatic void\t\tOptionInit(TkMainInfo *mainPtr);\nstatic int\t\tParsePriority(Tcl_Interp *interp, const char *string);\nstatic int\t\tReadOptionFile(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    const char *fileName, int priority);\nstatic void\t\tSetupStacks(TkWindow *winPtr, int leaf);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_AddOption --\n *\n *\tAdd a new option to the option database.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation is added to the option database.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_AddOption(\n    Tk_Window tkwin,\t\t/* Window token; option will be associated\n\t\t\t\t * with main window for this window. */\n    const char *name,\t\t/* Multi-element name of option. */\n    const char *value,\t\t/* String value for option. */\n    int priority)\t\t/* Overall priority level to use for this\n\t\t\t\t * option, such as TK_USER_DEFAULT_PRIO or\n\t\t\t\t * TK_INTERACTIVE_PRIO. Must be between 0 and\n\t\t\t\t * TK_MAX_PRIO. */\n{\n    TkWindow *winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr;\n    ElArray **arrayPtrPtr;\n    Element *elPtr;\n    Element newEl;\n    const char *p;\n    const char *field;\n    int count, firstField;\n    size_t length;\n#define TMP_SIZE 100\n    char tmp[TMP_SIZE+1];\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->mainPtr->optionRootPtr == NULL) {\n\tOptionInit(winPtr->mainPtr);\n    }\n    tsdPtr->cachedWindow = NULL;/* Invalidate the cache. */\n\n    /*\n     * Compute the priority for the new element, including both the overall\n     * level and the serial number (to disambiguate with the level).\n     */\n\n    if (priority < 0) {\n\tpriority = 0;\n    } else if (priority > TK_MAX_PRIO) {\n\tpriority = TK_MAX_PRIO;\n    }\n    newEl.priority = (priority << 24) + tsdPtr->serial;\n    tsdPtr->serial++;\n\n    /*\n     * Parse the option one field at a time.\n     */\n\n    arrayPtrPtr = &(((TkWindow *) tkwin)->mainPtr->optionRootPtr);\n    p = name;\n    for (firstField = 1; ; firstField = 0) {\n\t/*\n\t * Scan the next field from the name and convert it to a Tk_Uid. Must\n\t * copy the field before calling Tk_Uid, so that a terminating NULL\n\t * may be added without modifying the source string.\n\t */\n\n\tif (*p == '*') {\n\t    newEl.flags = WILDCARD;\n\t    p++;\n\t} else {\n\t    newEl.flags = 0;\n\t}\n\tfield = p;\n\twhile ((*p != 0) && (*p != '.') && (*p != '*')) {\n\t    p++;\n\t}\n\tlength = p - field;\n\tif (length > TMP_SIZE) {\n\t    length = TMP_SIZE;\n\t}\n\tstrncpy(tmp, field, length);\n\ttmp[length] = 0;\n\tnewEl.nameUid = Tk_GetUid(tmp);\n\tif (isupper(UCHAR(*field))) {\n\t    newEl.flags |= CLASS;\n\t}\n\n\tif (*p != 0) {\n\t    /*\n\t     * New element will be a node. If this option can't possibly apply\n\t     * to this main window, then just skip it. Otherwise, add it to\n\t     * the parent, if it isn't already there, and descend into it.\n\t     */\n\n\t    newEl.flags |= NODE;\n\t    if (firstField && !(newEl.flags & WILDCARD)\n\t\t    && (newEl.nameUid != winPtr->nameUid)\n\t\t    && (newEl.nameUid != winPtr->classUid)) {\n\t\treturn;\n\t    }\n\t    for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;\n\t\t    ; elPtr++, count--) {\n\t\tif (count == 0) {\n\t\t    newEl.child.arrayPtr = NewArray(5);\n\t\t    *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);\n\t\t    arrayPtrPtr = &((*arrayPtrPtr)\n\t\t\t    ->nextToUse[-1].child.arrayPtr);\n\t\t    break;\n\t\t}\n\t\tif ((elPtr->nameUid == newEl.nameUid)\n\t\t\t&& (elPtr->flags == newEl.flags)) {\n\t\t    arrayPtrPtr = &(elPtr->child.arrayPtr);\n\t\t    break;\n\t\t}\n\t    }\n\t    if (*p == '.') {\n\t\tp++;\n\t    }\n\t} else {\n\t    /*\n\t     * New element is a leaf. Add it to the parent, if it isn't\n\t     * already there. If it exists already, keep whichever value has\n\t     * highest priority.\n\t     */\n\n\t    newEl.child.valueUid = Tk_GetUid(value);\n\t    for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;\n\t\t    ; elPtr++, count--) {\n\t\tif (count == 0) {\n\t\t    *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);\n\t\t    return;\n\t\t}\n\t\tif ((elPtr->nameUid == newEl.nameUid)\n\t\t\t&& (elPtr->flags == newEl.flags)) {\n\t\t    if (elPtr->priority < newEl.priority) {\n\t\t\telPtr->priority = newEl.priority;\n\t\t\telPtr->child.valueUid = newEl.child.valueUid;\n\t\t    }\n\t\t    return;\n\t\t}\n\t    }\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetOption --\n *\n *\tRetrieve an option from the option database.\n *\n * Results:\n *\tThe return value is the value specified in the option database for the\n *\tgiven name and class on the given window. If there is nothing\n *\tspecified in the database for that option, then NULL is returned.\n *\n * Side effects:\n *\tThe internal caches used to speed up option mapping may be modified,\n *\tif this tkwin is different from the last tkwin used for option\n *\tretrieval.\n *\n *--------------------------------------------------------------\n */\n\nTk_Uid\nTk_GetOption(\n    Tk_Window tkwin,\t\t/* Token for window that option is associated\n\t\t\t\t * with. */\n    const char *name,\t\t/* Name of option. */\n    const char *className)\t/* Class of option. NULL means there is no\n\t\t\t\t * class for this option: just check for\n\t\t\t\t * name. */\n{\n    Tk_Uid nameId, classId = NULL;\n    const char *masqName;\n    Element *elPtr, *bestPtr;\n    int count;\n    StackLevel *levelPtr;\n    int stackDepth[NUM_STACKS];\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Note: no need to call OptionInit here: it will be done by the\n     * SetupStacks call below (squeeze out those nanoseconds).\n     */\n\n    if (tkwin != (Tk_Window) tsdPtr->cachedWindow) {\n\tSetupStacks((TkWindow *) tkwin, 1);\n    }\n\n    /*\n     * Get a default \"best\" match.\n     */\n\n    bestPtr = &tsdPtr->defaultMatch;\n\n    /*\n     * For megawidget support, we want to have some widget options masquerade\n     * as options for other widgets. For example, a combobox has a button in\n     * it; this button ought to pick up the *Button.background, etc., options.\n     * But because the class of the widget is Combobox, our normal search\n     * won't get that option.\n     *\n     * To work around this, the option name field syntax was extended to allow\n     * for a \".\" in the name; if this character occurs in the name, then it\n     * indicates that this name contains a new window class and an option\n     * name, ie, \"Button.foreground\". If we see this form in the name field,\n     * we query the option database directly (since the option stacks will not\n     * have the information we need).\n     */\n\n    masqName = strchr(name, (int)'.');\n    if (masqName != NULL) {\n\t/*\n\t * This option is masquerading with a different window class. Search\n\t * the stack to the depth it was before the current window's\n\t * information was pushed (the value for which is stored in the bases\n\t * field).\n\t */\n\n\tlevelPtr = &tsdPtr->levels[tsdPtr->curLevel];\n\tnameId = Tk_GetUid(masqName+1);\n\tfor (count = 0; count < NUM_STACKS; count++) {\n\t    stackDepth[count] = levelPtr->bases[count];\n\t}\n    } else {\n\t/*\n\t * No option masquerading here. Just use the current level to get the\n\t * stack depths.\n\t */\n\n\tnameId = Tk_GetUid(name);\n\tfor (count = 0; count < NUM_STACKS; count++) {\n\t    stackDepth[count] = tsdPtr->stacks[count]->numUsed;\n\t}\n    }\n\n    /*\n     * Probe the stacks for matches.\n     */\n\n    for (elPtr = tsdPtr->stacks[EXACT_LEAF_NAME]->els,\n\t    count = stackDepth[EXACT_LEAF_NAME]; count > 0;\n\t    elPtr++, count--) {\n\tif ((elPtr->nameUid == nameId)\n\t\t&& (elPtr->priority > bestPtr->priority)) {\n\t    bestPtr = elPtr;\n\t}\n    }\n    for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_NAME]->els,\n\t    count = stackDepth[WILDCARD_LEAF_NAME]; count > 0;\n\t    elPtr++, count--) {\n\tif ((elPtr->nameUid == nameId)\n\t\t&& (elPtr->priority > bestPtr->priority)) {\n\t    bestPtr = elPtr;\n\t}\n    }\n\n    if (className != NULL) {\n\tclassId = Tk_GetUid(className);\n\tfor (elPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]->els,\n\t\tcount = stackDepth[EXACT_LEAF_CLASS]; count > 0;\n\t\telPtr++, count--) {\n\t    if ((elPtr->nameUid == classId)\n\t\t    && (elPtr->priority > bestPtr->priority)) {\n\t\tbestPtr = elPtr;\n\t    }\n\t}\n\tfor (elPtr = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->els,\n\t\tcount = stackDepth[WILDCARD_LEAF_CLASS]; count > 0;\n\t\telPtr++, count--) {\n\t    if ((elPtr->nameUid == classId)\n\t\t    && (elPtr->priority > bestPtr->priority)) {\n\t\tbestPtr = elPtr;\n\t    }\n\t}\n    }\n\n    /*\n     * If this option was masquerading with a different window class, probe\n     * the option database now. Note that this will be inefficient if the\n     * option database is densely populated, or if the widget has many\n     * masquerading options.\n     */\n\n    if (masqName != NULL) {\n\tchar *masqClass;\n\tTk_Uid nodeId, winClassId, winNameId;\n\tTcl_Size classNameLength;\n\tElement *nodePtr, *leafPtr;\n\tstatic const int searchOrder[] = {\n\t    EXACT_NODE_NAME, WILDCARD_NODE_NAME, EXACT_NODE_CLASS,\n\t    WILDCARD_NODE_CLASS, -1\n\t};\n\tconst int *currentPtr;\n\tint currentStack, leafCount;\n\n\t/*\n\t * Extract the masquerade class name from the name field.\n\t */\n\n\tclassNameLength\t= masqName - name;\n\tmasqClass = (char *)Tcl_Alloc(classNameLength + 1);\n\tstrncpy(masqClass, name, classNameLength);\n\tmasqClass[classNameLength] = '\\0';\n\n\twinClassId = Tk_GetUid(masqClass);\n\tTcl_Free(masqClass);\n\twinNameId = ((TkWindow *) tkwin)->nameUid;\n\n\tlevelPtr = &tsdPtr->levels[tsdPtr->curLevel];\n\n\tfor (currentPtr = searchOrder; *currentPtr != -1; currentPtr++) {\n\t    currentStack = *currentPtr;\n\t    nodePtr = tsdPtr->stacks[currentStack]->els;\n\t    count = levelPtr->bases[currentStack];\n\n\t    /*\n\t     * For wildcard stacks, check all entries; for non-wildcard\n\t     * stacks, only check things that matched in the parent.\n\t     */\n\n\t    if (!(currentStack & WILDCARD)) {\n\t\tnodePtr += levelPtr[-1].bases[currentStack];\n\t\tcount\t-= levelPtr[-1].bases[currentStack];\n\t    }\n\n\t    if (currentStack & CLASS) {\n\t\tnodeId = winClassId;\n\t    } else {\n\t\tnodeId = winNameId;\n\t    }\n\n\t    for ( ; count > 0; nodePtr++, count--) {\n\t\tif (nodePtr->nameUid == nodeId) {\n\t\t    leafPtr = nodePtr->child.arrayPtr->els;\n\t\t    leafCount = nodePtr->child.arrayPtr->numUsed;\n\t\t    for ( ; leafCount > 0; leafPtr++, leafCount--) {\n\t\t\tif (leafPtr->flags & CLASS && className != NULL) {\n\t\t\t    if (leafPtr->nameUid == classId &&\n\t\t\t\t    leafPtr->priority > bestPtr->priority) {\n\t\t\t\tbestPtr = leafPtr;\n\t\t\t    }\n\t\t\t} else {\n\t\t\t    if (leafPtr->nameUid == nameId &&\n\t\t\t\t    leafPtr->priority > bestPtr->priority) {\n\t\t\t\tbestPtr = leafPtr;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    return bestPtr->child.valueUid;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_OptionObjCmd --\n *\n *\tThis function is invoked to process the \"option\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_OptionObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of Tcl_Obj arguments. */\n    Tcl_Obj *const objv[])\t/* Tcl_Obj arguments. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    int index, result;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    static const char *const optionCmds[] = {\n\t\"add\", \"clear\", \"get\", \"readfile\", NULL\n    };\n    enum optionVals {\n\tOPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"cmd arg ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObjStruct(interp, objv[1], optionCmds,\n\t    sizeof(char *), \"option\", 0, &index);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    result = TCL_OK;\n    switch ((enum optionVals) index) {\n    case OPTION_ADD: {\n\tint priority;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pattern value ?priority?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (objc == 4) {\n\t    priority = TK_INTERACTIVE_PRIO;\n\t} else {\n\t    priority = ParsePriority(interp, Tcl_GetString(objv[4]));\n\t    if (priority < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tTk_AddOption(tkwin, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]),\n\t\tpriority);\n\tbreak;\n    }\n\n    case OPTION_CLEAR: {\n\tTkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;\n\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"\");\n\t    return TCL_ERROR;\n\t}\n\tif (mainPtr->optionRootPtr != NULL) {\n\t    ClearOptionTree(mainPtr->optionRootPtr);\n\t    mainPtr->optionRootPtr = NULL;\n\t}\n\ttsdPtr->cachedWindow = NULL;\n\tbreak;\n    }\n\n    case OPTION_GET: {\n\tTk_Window window;\n\tTk_Uid value;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window name class\");\n\t    return TCL_ERROR;\n\t}\n\twindow = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);\n\tif (window == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tvalue = Tk_GetOption(window, Tcl_GetString(objv[3]),\n\t\tTcl_GetString(objv[4]));\n\tif (value != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(value, TCL_INDEX_NONE));\n\t}\n\tbreak;\n    }\n\n    case OPTION_READFILE: {\n\tint priority;\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"fileName ?priority?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (objc == 4) {\n\t    priority = ParsePriority(interp, Tcl_GetString(objv[3]));\n\t    if (priority < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    priority = TK_INTERACTIVE_PRIO;\n\t}\n\tresult = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]),\n\t\tpriority);\n\tbreak;\n    }\n    }\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkOptionDeadWindow --\n *\n *\tThis function is called whenever a window is deleted. It cleans up any\n *\toption-related stuff associated with the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOption-related resources are freed. See code below for details.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkOptionDeadWindow(\n    TkWindow *winPtr)\t/* Window to be cleaned up. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * If this window is in the option stacks, then clear the stacks.\n     *\n     * XXX: OptionThreadExitProc will be invoked before DeleteWindowsExitProc\n     * XXX: if it is thread-specific (which it should be), invalidating the\n     * XXX: tsd. Tk shutdown needs to be verified to handle this correctly.\n     */\n\n    if (tsdPtr->initialized && (winPtr->optionLevel != TCL_INDEX_NONE)) {\n\tint i;\n\n\tfor (i = 1; i <= tsdPtr->curLevel; i++) {\n\t    tsdPtr->levels[i].winPtr->optionLevel = TCL_INDEX_NONE;\n\t}\n\ttsdPtr->curLevel = -1;\n\ttsdPtr->cachedWindow = NULL;\n    }\n\n    /*\n     * If this window was a main window, then delete its option database.\n     */\n\n    if ((winPtr->mainPtr != NULL) && (winPtr->mainPtr->winPtr == winPtr)\n\t    && (winPtr->mainPtr->optionRootPtr != NULL)) {\n\tClearOptionTree(winPtr->mainPtr->optionRootPtr);\n\twinPtr->mainPtr->optionRootPtr = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkOptionClassChanged --\n *\n *\tThis function is invoked when a window's class changes. If the window\n *\tis on the option cache, this function flushes any information for the\n *\twindow, since the new class could change what is relevant.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe option cache may be flushed in part or in whole.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkOptionClassChanged(\n    TkWindow *winPtr)\t\t/* Window whose class changed. */\n{\n    int i, j, *basePtr;\n    ElArray *arrayPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->optionLevel < 0) {\n\treturn;\n    }\n\n    /*\n     * Find the lowest stack level that refers to this window, then flush all\n     * of the levels above the matching one.\n     */\n\n    for (i = 1; i <= tsdPtr->curLevel; i++) {\n\tif (tsdPtr->levels[i].winPtr == winPtr) {\n\t    for (j = i; j <= tsdPtr->curLevel; j++) {\n\t\ttsdPtr->levels[j].winPtr->optionLevel = TCL_INDEX_NONE;\n\t    }\n\t    tsdPtr->curLevel = i-1;\n\t    basePtr = tsdPtr->levels[i].bases;\n\t    for (j = 0; j < NUM_STACKS; j++) {\n\t\tarrayPtr = tsdPtr->stacks[j];\n\t\tarrayPtr->numUsed = basePtr[j];\n\t\tarrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];\n\t    }\n\t    if (tsdPtr->curLevel <= 0) {\n\t\ttsdPtr->cachedWindow = NULL;\n\t    } else {\n\t\ttsdPtr->cachedWindow = tsdPtr->levels[tsdPtr->curLevel].winPtr;\n\t    }\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParsePriority --\n *\n *\tParse a string priority value.\n *\n * Results:\n *\tThe return value is the integer priority level corresponding to\n *\tstring, or -1 if string doesn't point to a valid priority level. In\n *\tthis case, an error message is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nParsePriority(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    const char *string)\t\t/* Describes a priority level, either\n\t\t\t\t * symbolically or numerically. */\n{\n    int priority, c;\n    size_t length;\n\n    c = string[0];\n    length = strlen(string);\n    if ((c == 'w')\n\t    && (strncmp(string, \"widgetDefault\", length) == 0)) {\n\treturn TK_WIDGET_DEFAULT_PRIO;\n    } else if ((c == 's')\n\t    && (strncmp(string, \"startupFile\", length) == 0)) {\n\treturn TK_STARTUP_FILE_PRIO;\n    } else if ((c == 'u')\n\t    && (strncmp(string, \"userDefault\", length) == 0)) {\n\treturn TK_USER_DEFAULT_PRIO;\n    } else if ((c == 'i')\n\t    && (strncmp(string, \"interactive\", length) == 0)) {\n\treturn TK_INTERACTIVE_PRIO;\n    } else {\n\tchar *end;\n\n\tpriority = strtoul(string, &end, 0);\n\tif ((end == string) || (*end != 0) || (priority < 0)\n\t\t|| (priority > 100)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad priority level \\\"%s\\\": must be \"\n\t\t    \"widgetDefault, startupFile, userDefault, \"\n\t\t    \"interactive, or a number between 0 and 100\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PRIORITY\", (char *)NULL);\n\t    return -1;\n\t}\n    }\n    return priority;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AddFromString --\n *\n *\tGiven a string containing lines in the standard format for X resources\n *\t(see other documentation for details on what this is), parse the\n *\tresource specifications and enter them as options for tkwin's main\n *\twindow.\n *\n * Results:\n *\tThe return value is a standard Tcl return code. In the case of an\n *\terror in parsing string, TCL_ERROR will be returned and an error\n *\tmessage will be left in the interp's result. The memory at string is\n *\ttotally trashed by this function. If you care about its contents, make\n *\ta copy before calling here.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nAddFromString(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting results. */\n    Tk_Window tkwin,\t\t/* Token for window: options are entered for\n\t\t\t\t * this window's main window. */\n    char *string,\t\t/* String containing option specifiers. */\n    int priority)\t\t/* Priority level to use for options in this\n\t\t\t\t * string, such as TK_USER_DEFAULT_PRIO or\n\t\t\t\t * TK_INTERACTIVE_PRIO. Must be between 0 and\n\t\t\t\t * TK_MAX_PRIO. */\n{\n    char *src, *dst;\n    char *name, *value;\n    int lineNum;\n\n    src = string;\n    lineNum = 1;\n    while (1) {\n\t/*\n\t * Skip leading white space and empty lines and comment lines, and\n\t * check for the end of the spec.\n\t */\n\n\twhile ((*src == ' ') || (*src == '\\t')) {\n\t    src++;\n\t}\n\tif ((*src == '#') || (*src == '!')) {\n\t    do {\n\t\tsrc++;\n\t\tif ((src[0] == '\\\\') && (src[1] == '\\n')) {\n\t\t    src += 2;\n\t\t    lineNum++;\n\t\t}\n\t    } while ((*src != '\\n') && (*src != 0));\n\t}\n\tif (*src == '\\n') {\n\t    src++;\n\t    lineNum++;\n\t    continue;\n\t}\n\tif (*src == '\\0') {\n\t    break;\n\t}\n\n\t/*\n\t * Parse off the option name, collapsing out backslash-newline\n\t * sequences of course.\n\t */\n\n\tdst = name = src;\n\twhile (*src != ':') {\n\t    if ((*src == '\\0') || (*src == '\\n')) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"missing colon on line %d\", lineNum));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"OPTIONDB\", \"COLON\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if ((src[0] == '\\\\') && (src[1] == '\\n')) {\n\t\tsrc += 2;\n\t\tlineNum++;\n\t    } else {\n\t\t*dst = *src;\n\t\tdst++;\n\t\tsrc++;\n\t    }\n\t}\n\n\t/*\n\t * Eliminate trailing white space on the name, and null-terminate\n\t * it.\n\t */\n\n\twhile ((dst != name) && ((dst[-1] == ' ') || (dst[-1] == '\\t'))) {\n\t    dst--;\n\t}\n\t*dst = '\\0';\n\n\t/*\n\t * Skip white space between the name and the value.\n\t */\n\n\tsrc++;\n\twhile ((*src == ' ') || (*src == '\\t')) {\n\t    src++;\n\t}\n\tif (*src == '\\\\' && (src[1] == '\\t' || src[1] == ' ')) {\n\t    src++;\n\t}\n\tif (*src == '\\0') {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"missing value on line %d\", lineNum));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"OPTIONDB\", \"VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Parse off the value, squeezing out backslash-newline sequences\n\t * along the way.\n\t */\n\n\tdst = value = src;\n\twhile (*src != '\\n') {\n\t    if (*src == '\\0') {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"missing newline on line %d\", lineNum));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"OPTIONDB\", \"NEWLINE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (*src == '\\\\'){\n\t\tif (src[1] == '\\n') {\n\t\t    src += 2;\n\t\t    lineNum++;\n\t\t    continue;\n\t\t} else if (src[1] == 'n') {\n\t\t    src += 2;\n\t\t    *dst++ = '\\n';\n\t\t    continue;\n\t\t} else if (src[1] == '\\\\') {\n\t\t    ++src;\n\t\t} else if (src[1] >= '0' && src[1] <= '3' && src[2] >= '0' &&\n\t\t\tsrc[2] <= '9' && src[3] >= '0' && src[3] <= '9') {\n\t\t    *dst++ = ((src[1]&7)<<6) | ((src[2]&7)<<3) | (src[3]&7);\n\t\t    src += 4;\n\t\t    continue;\n\t\t}\n\t    }\n\t    *dst++ = *src++;\n\t}\n\t*dst = 0;\n\n\t/*\n\t * Enter the option into the database.\n\t */\n\n\tTk_AddOption(tkwin, name, value, priority);\n\tsrc++;\n\tlineNum++;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadOptionFile --\n *\n *\tRead a file of options (\"resources\" in the old X terminology) and load\n *\tthem into the option database.\n *\n * Results:\n *\tThe return value is a standard Tcl return code. In the case of an\n *\terror in parsing string, TCL_ERROR will be returned and an error\n *\tmessage will be left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadOptionFile(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting results. */\n    Tk_Window tkwin,\t\t/* Token for window: options are entered for\n\t\t\t\t * this window's main window. */\n    const char *fileName,\t/* Name of file containing options. */\n    int priority)\t\t/* Priority level to use for options in this\n\t\t\t\t * file, such as TK_USER_DEFAULT_PRIO or\n\t\t\t\t * TK_INTERACTIVE_PRIO. Must be between 0 and\n\t\t\t\t * TK_MAX_PRIO. */\n{\n    const char *realName;\n    Tcl_Obj *buffer;\n    int result;\n    Tcl_Size bufferSize;\n    Tcl_Channel chan;\n    Tcl_DString newName;\n\n    /*\n     * Prevent file system access in a safe interpreter.\n     */\n\n    if (Tcl_IsSafe(interp)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't read options from a file in a safe interpreter\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"OPTION_FILE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    realName = Tcl_TranslateFileName(interp, fileName, &newName);\n    if (realName == NULL) {\n\treturn TCL_ERROR;\n    }\n    chan = Tcl_OpenFileChannel(interp, realName, \"r\", 0);\n    Tcl_DStringFree(&newName);\n    if (chan == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"couldn't open \\\"%s\\\": %s\",\n\t\tfileName, Tcl_PosixError(interp)));\n\treturn TCL_ERROR;\n    }\n\n    buffer = Tcl_NewObj();\n    Tcl_IncrRefCount(buffer);\n    Tcl_SetChannelOption(NULL, chan, \"-encoding\", \"utf-8\");\n    bufferSize = Tcl_ReadChars(chan, buffer, TCL_INDEX_NONE, 0);\n    if (bufferSize == TCL_IO_FAILURE) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"error reading file \\\"%s\\\": %s\",\n\t\tfileName, Tcl_PosixError(interp)));\n\tTcl_Close(NULL, chan);\n\treturn TCL_ERROR;\n    }\n    Tcl_Close(NULL, chan);\n    result = AddFromString(interp, tkwin, Tcl_GetString(buffer), priority);\n    Tcl_DecrRefCount(buffer);\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * NewArray --\n *\n *\tCreate a new ElArray structure of a given size.\n *\n * Results:\n *\tThe return value is a pointer to a properly initialized element array\n *\twith \"numEls\" space. The array is marked as having no active elements.\n *\n * Side effects:\n *\tMemory is allocated.\n *\n *--------------------------------------------------------------\n */\n\nstatic ElArray *\nNewArray(\n    int numEls)\t\t\t/* How many elements of space to allocate. */\n{\n    ElArray *arrayPtr = (ElArray *)Tcl_Alloc(EL_ARRAY_SIZE(numEls));\n\n    arrayPtr->arraySize = numEls;\n    arrayPtr->numUsed = 0;\n    arrayPtr->nextToUse = arrayPtr->els;\n    return arrayPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ExtendArray --\n *\n *\tAdd a new element to an array, extending the array if necessary.\n *\n * Results:\n *\tThe return value is a pointer to the new array, which will be\n *\tdifferent from arrayPtr if the array got expanded.\n *\n * Side effects:\n *\tMemory may be allocated or freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic ElArray *\nExtendArray(\n    ElArray *arrayPtr,\t/* Array to be extended. */\n    Element *elPtr)\t/* Element to be copied into array. */\n{\n    /*\n     * If the current array has filled up, make it bigger.\n     */\n\n    if (arrayPtr->numUsed >= arrayPtr->arraySize) {\n\tint newSize = 2*arrayPtr->arraySize;\n\n\tarrayPtr = (ElArray *)Tcl_Realloc(arrayPtr, EL_ARRAY_SIZE(newSize));\n\tarrayPtr->arraySize = newSize;\n\tarrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];\n    }\n\n    *arrayPtr->nextToUse = *elPtr;\n    arrayPtr->nextToUse++;\n    arrayPtr->numUsed++;\n    return arrayPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SetupStacks --\n *\n *\tArrange the stacks so that they cache all the option information for a\n *\tparticular window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe stacks are modified to hold information for tkwin and all its\n *\tancestors in the window hierarchy.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nSetupStacks(\n    TkWindow *winPtr,\t\t/* Window for which information is to be\n\t\t\t\t * cached. */\n    int leaf)\t\t\t/* Non-zero means this is the leaf window\n\t\t\t\t * being probed. Zero means this is an\n\t\t\t\t * ancestor of the desired leaf. */\n{\n    int level, i;\n    const int *iPtr;\n    StackLevel *levelPtr;\n    ElArray *arrayPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * The following array defines the order in which the current stacks are\n     * searched to find matching entries to add to the stacks. Given the\n     * current priority-based scheme, the order below is no longer relevant;\n     * all that matters is that an element is on the list *somewhere*. The\n     * ordering is a relic of the old days when priorities were determined\n     * differently.\n     */\n\n    static const int searchOrder[] = {WILDCARD_NODE_CLASS, WILDCARD_NODE_NAME,\n\t    EXACT_NODE_CLASS, EXACT_NODE_NAME, -1};\n\n    if (winPtr->mainPtr->optionRootPtr == NULL) {\n\tOptionInit(winPtr->mainPtr);\n    }\n\n    /*\n     * Step 1: make sure that options are cached for this window's parent.\n     */\n\n    if (winPtr->parentPtr != NULL) {\n\tlevel = winPtr->parentPtr->optionLevel;\n\tif ((level == -1) || (tsdPtr->cachedWindow == NULL)) {\n\t    SetupStacks(winPtr->parentPtr, 0);\n\t    level = winPtr->parentPtr->optionLevel;\n\t}\n\tlevel++;\n    } else {\n\tlevel = 1;\n    }\n\n    /*\n     * Step 2: pop extra unneeded information off the stacks and mark those\n     * windows as no longer having cached information.\n     */\n\n    if (tsdPtr->curLevel >= level) {\n\twhile (tsdPtr->curLevel >= level) {\n\t    tsdPtr->levels[tsdPtr->curLevel].winPtr->optionLevel = TCL_INDEX_NONE;\n\t    tsdPtr->curLevel--;\n\t}\n\tlevelPtr = &tsdPtr->levels[level];\n\tfor (i = 0; i < NUM_STACKS; i++) {\n\t    arrayPtr = tsdPtr->stacks[i];\n\t    arrayPtr->numUsed = levelPtr->bases[i];\n\t    arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];\n\t}\n    }\n    tsdPtr->curLevel = winPtr->optionLevel = level;\n\n    /*\n     * Step 3: if the root database information isn't loaded or isn't valid,\n     * initialize level 0 of the stack from the database root (this only\n     * happens if winPtr is a main window).\n     */\n\n    if ((tsdPtr->curLevel == 1)\n\t    && ((tsdPtr->cachedWindow == NULL)\n\t    || (tsdPtr->cachedWindow->mainPtr != winPtr->mainPtr))) {\n\tfor (i = 0; i < NUM_STACKS; i++) {\n\t    arrayPtr = tsdPtr->stacks[i];\n\t    arrayPtr->numUsed = 0;\n\t    arrayPtr->nextToUse = arrayPtr->els;\n\t}\n\tExtendStacks(winPtr->mainPtr->optionRootPtr, 0);\n    }\n\n    /*\n     * Step 4: create a new stack level; grow the level array if we've run out\n     * of levels. Clear the stacks for EXACT_LEAF_NAME and EXACT_LEAF_CLASS\n     * (anything that was there is of no use any more).\n     */\n\n    if (tsdPtr->curLevel >= tsdPtr->numLevels) {\n\tStackLevel *newLevels = (StackLevel *)\n\t\tTcl_Alloc(tsdPtr->numLevels * 2 * sizeof(StackLevel));\n\n\tmemcpy(newLevels, tsdPtr->levels,\n\t\ttsdPtr->numLevels * sizeof(StackLevel));\n\tTcl_Free(tsdPtr->levels);\n\ttsdPtr->numLevels *= 2;\n\ttsdPtr->levels = newLevels;\n    }\n    levelPtr = &tsdPtr->levels[tsdPtr->curLevel];\n    levelPtr->winPtr = winPtr;\n    arrayPtr = tsdPtr->stacks[EXACT_LEAF_NAME];\n    arrayPtr->numUsed = 0;\n    arrayPtr->nextToUse = arrayPtr->els;\n    arrayPtr = tsdPtr->stacks[EXACT_LEAF_CLASS];\n    arrayPtr->numUsed = 0;\n    arrayPtr->nextToUse = arrayPtr->els;\n    for (i = 0; i < NUM_STACKS; i++) {\n\tlevelPtr->bases[i] = tsdPtr->stacks[i]->numUsed;\n    }\n\n    /*\n     * Step 5: scan the current stack level looking for matches to this\n     * window's name or class; where found, add new information to the stacks.\n     */\n\n    for (iPtr = searchOrder; *iPtr != -1; iPtr++) {\n\tElement *elPtr;\n\tint count;\n\tTk_Uid id;\n\n\ti = *iPtr;\n\tif (i & CLASS) {\n\t    id = winPtr->classUid;\n\t} else {\n\t    id = winPtr->nameUid;\n\t}\n\telPtr = tsdPtr->stacks[i]->els;\n\tcount = levelPtr->bases[i];\n\n\t/*\n\t * For wildcard stacks, check all entries; for non-wildcard stacks,\n\t * only check things that matched in the parent.\n\t */\n\n\tif (!(i & WILDCARD)) {\n\t    elPtr += levelPtr[-1].bases[i];\n\t    count -= levelPtr[-1].bases[i];\n\t}\n\tfor ( ; count > 0; elPtr++, count--) {\n\t    if (elPtr->nameUid != id) {\n\t\tcontinue;\n\t    }\n\t    ExtendStacks(elPtr->child.arrayPtr, leaf);\n\t}\n    }\n    tsdPtr->cachedWindow = winPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ExtendStacks --\n *\n *\tGiven an element array, copy all the elements from the array onto the\n *\tsystem stacks (except for irrelevant leaf elements).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe option stacks are extended.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nExtendStacks(\n    ElArray *arrayPtr,\t\t/* Array of elements to copy onto stacks. */\n    int leaf)\t\t\t/* If zero, then don't copy exact leaf\n\t\t\t\t * elements. */\n{\n    int count;\n    Element *elPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (elPtr = arrayPtr->els, count = arrayPtr->numUsed;\n\t    count > 0; elPtr++, count--) {\n\tif (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) {\n\t    continue;\n\t}\n\ttsdPtr->stacks[elPtr->flags] =\n\t\tExtendArray(tsdPtr->stacks[elPtr->flags], elPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * OptionThreadExitProc --\n *\n *\tFree data structures for option handling.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOption-related data structures get freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nOptionThreadExitProc(\n    TCL_UNUSED(void *))\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->initialized) {\n\tint i;\n\n\tfor (i = 0; i < NUM_STACKS; i++) {\n\t    Tcl_Free(tsdPtr->stacks[i]);\n\t}\n\tTcl_Free(tsdPtr->levels);\n\ttsdPtr->initialized = false;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * OptionInit --\n *\n *\tInitialize data structures for option handling.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOption-related data structures get initialized.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nOptionInit(\n    TkMainInfo *mainPtr)\n\t\t\t\t/* Top-level information about window that\n\t\t\t\t * isn't initialized yet. */\n{\n    int i;\n    Tcl_Interp *interp;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Element *defaultMatchPtr = &tsdPtr->defaultMatch;\n\n    /*\n     * First, once-only initialization.\n     */\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\ttsdPtr->cachedWindow = NULL;\n\ttsdPtr->numLevels = 5;\n\ttsdPtr->curLevel = -1;\n\ttsdPtr->serial = 0;\n\n\ttsdPtr->levels = (StackLevel *)Tcl_Alloc(5 * sizeof(StackLevel));\n\tfor (i = 0; i < NUM_STACKS; i++) {\n\t    tsdPtr->stacks[i] = NewArray(10);\n\t    tsdPtr->levels[0].bases[i] = 0;\n\t}\n\n\tdefaultMatchPtr->nameUid = NULL;\n\tdefaultMatchPtr->child.valueUid = NULL;\n\tdefaultMatchPtr->priority = -1;\n\tdefaultMatchPtr->flags = 0;\n\tTcl_CreateThreadExitHandler(OptionThreadExitProc, NULL);\n    }\n\n    /*\n     * Then, per-main-window initialization. Create and delete dummy\n     * interpreter for message logging.\n     */\n\n    mainPtr->optionRootPtr = NewArray(20);\n    interp = Tcl_CreateInterp();\n    GetDefaultOptions(interp, mainPtr->winPtr);\n    Tcl_DeleteInterp(interp);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ClearOptionTree --\n *\n *\tThis function is called to erase everything in a hierarchical option\n *\tdatabase.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll the options associated with arrayPtr are deleted, along with all\n *\toption subtrees. The space pointed to by arrayPtr is freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nClearOptionTree(\n    ElArray *arrayPtr)\t\t/* Array of options; delete everything\n\t\t\t\t * referred to recursively by this. */\n{\n    Element *elPtr;\n    int count;\n\n    for (count = arrayPtr->numUsed, elPtr = arrayPtr->els;  count > 0;\n\t    count--, elPtr++) {\n\tif (elPtr->flags & NODE) {\n\t    ClearOptionTree(elPtr->child.arrayPtr);\n\t}\n    }\n    Tcl_Free(arrayPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * GetDefaultOptions --\n *\n *\tThis function is invoked to load the default set of options for a\n *\twindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOptions are added to those for winPtr's main window. If there exists a\n *\tRESOURCE_MANAGER proprety for winPtr's display, that is used.\n *\tOtherwise, the .Xdefaults file in the user's home directory is used.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nGetDefaultOptions(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    TkWindow *winPtr)\t\t/* Fetch option defaults for main window\n\t\t\t\t * associated with this. */\n{\n    char *regProp, **regPropPtr = &regProp;\n    int result = TCL_OK, actualFormat;\n    unsigned long numItems, bytesAfter;\n    Atom actualType;\n\n    /*\n     * Try the RESOURCE_MANAGER property on the root window first.\n     */\n\n    regProp = NULL;\n    result = XGetWindowProperty(winPtr->display,\n\t    RootWindow(winPtr->display, 0), XA_RESOURCE_MANAGER, 0, 100000,\n\t    False, XA_STRING, &actualType, &actualFormat, &numItems,\n\t    &bytesAfter, (unsigned char **) regPropPtr);\n\n    if ((result == Success) && (actualType == XA_STRING)\n\t    && (actualFormat == 8)) {\n\tresult = AddFromString(interp, (Tk_Window) winPtr, regProp,\n\t\tTK_USER_DEFAULT_PRIO);\n\tXFree(regProp);\n\treturn result;\n    }\n\n    /*\n     * No luck there. Try a .Xdefaults file in the user's home directory.\n     */\n\n    if (regProp != NULL) {\n\tXFree(regProp);\n    }\n    if (Tcl_EvalEx(interp, \"file tildeexpand ~/.Xdefaults\",\n\t    TCL_INDEX_NONE, TCL_EVAL_GLOBAL) == TCL_OK) {\n\tTcl_Obj *xdefaults = Tcl_GetObjResult(interp);\n\tTcl_IncrRefCount(xdefaults);\n\tTcl_ResetResult(interp);\n\tresult = ReadOptionFile(interp, (Tk_Window)winPtr, Tcl_GetString(xdefaults),\n\t\tTK_USER_DEFAULT_PRIO);\n\tTcl_DecrRefCount(xdefaults);\n    }\n    return result;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPack.c",
    "content": "/*\n * tkPack.c --\n *\n *\tThis file contains code to implement the \"packer\" geometry manager for\n *\tTk.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\ntypedef enum {BOTTOM, LEFT, RIGHT, TOP} Side;\nstatic const char *const sideNames[] = {\n    \"bottom\", \"left\", \"right\", \"top\", NULL\n};\n\n/*\n * For each window that the packer cares about (either because the window is\n * managed by the packer or because the window has content that are managed by\n * the packer), there is a structure of the following type:\n */\n\ntypedef struct Packer {\n    Tk_Window tkwin;\t\t/* Tk token for window. NULL means that the\n\t\t\t\t * window has been deleted, but the packet\n\t\t\t\t * hasn't had a chance to clean up yet because\n\t\t\t\t * the structure is still in use. */\n    struct Packer *containerPtr;\t/* Container window within which this window is\n\t\t\t\t * packed (NULL means this window isn't\n\t\t\t\t * managed by the packer). */\n    struct Packer *nextPtr;\t/* Next window packed within same container. List\n\t\t\t\t * is priority-ordered: first on list gets\n\t\t\t\t * packed first. */\n    struct Packer *contentPtr;\t/* First in list of content packed inside this\n\t\t\t\t * window (NULL means no packed content). */\n    Side side;\t\t\t/* Side of container against which this window is\n\t\t\t\t * packed. */\n    Tk_Anchor anchor;\t\t/* If frame allocated for window is larger\n\t\t\t\t * than window needs, this indicates how where\n\t\t\t\t * to position window in frame. */\n    int padX, padY;\t\t/* Total additional pixels to leave around the\n\t\t\t\t * window. Some is of this space is on each\n\t\t\t\t * side. This is space *outside* the window:\n\t\t\t\t * we'll allocate extra space in frame but\n\t\t\t\t * won't enlarge window). */\n    int padLeft, padTop;\t/* The part of padX or padY to use on the left\n\t\t\t\t * or top of the widget, respectively. By\n\t\t\t\t * default, this is half of padX or padY. */\n    int iPadX, iPadY;\t\t/* Total extra pixels to allocate inside the\n\t\t\t\t * window (half of this amount will appear on\n\t\t\t\t * each side). */\n    int doubleBw;\t\t/* Twice the window's last known border width.\n\t\t\t\t * If this changes, the window must be\n\t\t\t\t * repacked within its container. */\n    int *abortPtr;\t\t/* If non-NULL, it means that there is a\n\t\t\t\t * nested call to ArrangePacking already\n\t\t\t\t * working on this window. *abortPtr may be\n\t\t\t\t * set to 1 to abort that nested call. This\n\t\t\t\t * happens, for example, if tkwin or any of\n\t\t\t\t * its content is deleted. */\n    int flags;\t\t\t/* Miscellaneous flags; see below for\n\t\t\t\t * definitions. */\n} Packer;\n\n/*\n * Flag values for Packer structures:\n *\n * REQUESTED_REPACK:\t\t1 means a Tcl_DoWhenIdle request has already\n *\t\t\t\tbeen made to repack all the content of this\n *\t\t\t\twindow.\n * FILLX:\t\t\t1 means if frame allocated for window is wider\n *\t\t\t\tthan window needs, expand window to fill\n *\t\t\t\tframe. 0 means don't make window any larger\n *\t\t\t\tthan needed.\n * FILLY:\t\t\tSame as FILLX, except for height.\n * EXPAND:\t\t\t1 means this window's frame will absorb any\n *\t\t\t\textra space in the container window.\n * OLD_STYLE:\t\t\t1 means this window is being managed with the\n *\t\t\t\told-style packer algorithms (before Tk version\n *\t\t\t\t3.3). The main difference is that padding and\n *\t\t\t\tfilling are done differently.\n * DONT_PROPAGATE:\t\t1 means don't set this window's requested\n *\t\t\t\tsize. 0 means if this window is a container then\n *\t\t\t\tTk will set its requested size to fit the\n *\t\t\t\tneeds of its content.\n * ALLOCED_CONTAINER\t1 means that Pack has allocated itself as\n *\t\t\t\tgeometry container for this window.\n */\n\n#define REQUESTED_REPACK\t1\n#define FILLX\t\t\t2\n#define FILLY\t\t\t4\n#define EXPAND\t\t\t8\n#define OLD_STYLE\t\t16\n#define DONT_PROPAGATE\t\t32\n#define ALLOCED_CONTAINER\t64\n\n/*\n * The following structure is the official type record for the packer:\n */\n\nstatic void\t\tPackReqProc(void *clientData, Tk_Window tkwin);\nstatic void\t\tPackLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\n\nstatic const Tk_GeomMgr packerType = {\n    \"pack\",\t\t\t/* name */\n    PackReqProc,\t\t/* requestProc */\n    PackLostContentProc,\t\t/* lostContentProc */\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tArrangePacking(void *clientData);\nstatic int\t\tConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic Tcl_FreeProc\tDestroyPacker;\nstatic Packer *\t\tGetPacker(Tk_Window tkwin);\nstatic void\t\tPackStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tUnlink(Packer *packPtr);\nstatic int\t\tXExpansion(Packer *contentPtr, int cavityWidth);\nstatic int\t\tYExpansion(Packer *contentPtr, int cavityHeight);\n\f\n/*\n *------------------------------------------------------------------------\n *\n * TkAppendPadAmount --\n *\n *\tThis function generates a text value that describes one of the -padx,\n *\t-pady, -ipadx, or -ipady configuration options. The text value\n *\tgenerated is appended to the given Tcl_Obj.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *------------------------------------------------------------------------\n */\n\nvoid\nTkAppendPadAmount(\n    Tcl_Obj *bufferObj,\t\t/* The interpreter into which the result is\n\t\t\t\t * written. */\n    const char *switchName,\t/* One of \"padx\", \"pady\", \"ipadx\" or\n\t\t\t\t * \"ipady\" */\n    int halfSpace,\t\t/* The left or top padding amount */\n    int allSpace)\t\t/* The total amount of padding */\n{\n    Tcl_Obj *padding[2];\n\n    if (halfSpace*2 == allSpace) {\n\tTcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, TCL_INDEX_NONE),\n\t\tTcl_NewWideIntObj(halfSpace));\n    } else {\n\tpadding[0] = Tcl_NewWideIntObj(halfSpace);\n\tpadding[1] = Tcl_NewWideIntObj(allSpace - halfSpace);\n\tTcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, TCL_INDEX_NONE),\n\t\tTcl_NewListObj(2, padding));\n    }\n}\n\f\n/*\n *------------------------------------------------------------------------\n *\n * Tk_PackCmd --\n *\n *\tThis function is invoked to process the \"pack\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *------------------------------------------------------------------------\n */\n\nint\nTk_PackObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    const char *argv2;\n    static const char *const optionStrings[] = {\n\t\"configure\", \"content\", \"forget\", \"info\", \"propagate\", \"slaves\", NULL };\n    static const char *const optionStringsNoDep[] = {\n\t\"configure\", \"content\", \"forget\", \"info\", \"propagate\", NULL };\n    enum options {\n\tPACK_CONFIGURE, PACK_CONTENT, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES };\n    int index;\n\n    if (objc >= 2) {\n\tconst char *string = Tcl_GetString(objv[1]);\n\n\tif (string[0] == '.') {\n\t    return ConfigureContent(interp, tkwin, objc-1, objv+1);\n\t}\n    }\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option arg ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(NULL, objv[1], optionStrings,\n\t    \"option\", 0, &index) != TCL_OK) {\n\t/*\n\t * Call it again without the deprecated ones to get a proper error\n\t * message. This works well since there can't be any ambiguity between\n\t * deprecated and new options.\n\t */\n\n\tTcl_GetIndexFromObj(interp, objv[1], optionStringsNoDep,\n\t\t\"option\", 0, &index);\n\treturn TCL_ERROR;\n    }\n\n    argv2 = Tcl_GetString(objv[2]);\n    switch ((enum options) index) {\n    case PACK_CONFIGURE:\n\tif (argv2[0] != '.') {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad argument \\\"%s\\\": must be name of window\", argv2));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"WINDOW_PATH\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\treturn ConfigureContent(interp, tkwin, objc-2, objv+2);\n    case PACK_FORGET: {\n\tTk_Window content;\n\tPacker *contentPtr;\n\tTcl_Size i;\n\n\tfor (i = 2; i < objc; i++) {\n\t    if (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t    if (!(contentPtr = GetPacker(content))) {\n\t\tcontinue;\n\t    }\n\t    if ((contentPtr != NULL) && (contentPtr->containerPtr != NULL)) {\n\t\tTk_ManageGeometry(content, NULL, NULL);\n\t\tif (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\t\t    Tk_UnmaintainGeometry(contentPtr->tkwin,\n\t\t\t    contentPtr->containerPtr->tkwin);\n\t\t}\n\t\tUnlink(contentPtr);\n\t\tTk_UnmapWindow(contentPtr->tkwin);\n\t    }\n\t}\n\tbreak;\n    }\n    case PACK_INFO: {\n\tPacker *contentPtr;\n\tTk_Window content;\n\tTcl_Obj *infoObj;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &content) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (!(contentPtr = GetPacker(content))) {\n\t    return TCL_OK;\n\t}\n\tif (contentPtr->containerPtr == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't packed\", argv2));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"PACK\", \"NOT_PACKED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tinfoObj = Tcl_NewObj();\n\tTcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-in\", TCL_INDEX_NONE),\n\t\tTk_NewWindowObj(contentPtr->containerPtr->tkwin));\n\tTcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-anchor\", TCL_INDEX_NONE),\n\t\tTcl_NewStringObj(Tk_NameOfAnchor(contentPtr->anchor), TCL_INDEX_NONE));\n\tTcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-expand\", TCL_INDEX_NONE),\n\t\tTcl_NewBooleanObj(contentPtr->flags & EXPAND));\n\tswitch (contentPtr->flags & (FILLX|FILLY)) {\n\tcase 0:\n\t    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-fill\", TCL_INDEX_NONE),\n\t\t    Tcl_NewStringObj(\"none\", TCL_INDEX_NONE));\n\t    break;\n\tcase FILLX:\n\t    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-fill\", TCL_INDEX_NONE),\n\t\t    Tcl_NewStringObj(\"x\", TCL_INDEX_NONE));\n\t    break;\n\tcase FILLY:\n\t    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-fill\", TCL_INDEX_NONE),\n\t\t    Tcl_NewStringObj(\"y\", TCL_INDEX_NONE));\n\t    break;\n\tcase FILLX|FILLY:\n\t    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-fill\", TCL_INDEX_NONE),\n\t\t    Tcl_NewStringObj(\"both\", TCL_INDEX_NONE));\n\t    break;\n\t}\n\tTkAppendPadAmount(infoObj, \"-ipadx\", contentPtr->iPadX/2, contentPtr->iPadX);\n\tTkAppendPadAmount(infoObj, \"-ipady\", contentPtr->iPadY/2, contentPtr->iPadY);\n\tTkAppendPadAmount(infoObj, \"-padx\", contentPtr->padLeft,contentPtr->padX);\n\tTkAppendPadAmount(infoObj, \"-pady\", contentPtr->padTop, contentPtr->padY);\n\tTcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj(\"-side\", TCL_INDEX_NONE),\n\t\tTcl_NewStringObj(sideNames[contentPtr->side], TCL_INDEX_NONE));\n\tTcl_SetObjResult(interp, infoObj);\n\tbreak;\n    }\n    case PACK_PROPAGATE: {\n\tTk_Window container;\n\tPacker *containerPtr;\n\tint propagate;\n\n\tif (objc > 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?boolean?\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (!(containerPtr = GetPacker(container))) {\n\t    return TCL_OK;\n\t}\n\tif (objc == 3) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewBooleanObj(!(containerPtr->flags & DONT_PROPAGATE)));\n\t    return TCL_OK;\n\t}\n\tif (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (propagate) {\n\t    /*\n\t     * If we have content windows, we need to register as geometry container.\n\t     */\n\n\t    if (containerPtr->contentPtr != NULL) {\n\t\tif (TkSetGeometryContainer(interp, container, \"pack\") != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontainerPtr->flags |= ALLOCED_CONTAINER;\n\t    }\n\t    containerPtr->flags &= ~DONT_PROPAGATE;\n\n\t    /*\n\t     * Repack the container to allow new geometry information to\n\t     * propagate upwards to the container's container.\n\t     */\n\n\t    if (containerPtr->abortPtr != NULL) {\n\t\t*containerPtr->abortPtr = 1;\n\t    }\n\t    if (!(containerPtr->flags & REQUESTED_REPACK)) {\n\t\tcontainerPtr->flags |= REQUESTED_REPACK;\n\t\tTcl_DoWhenIdle(ArrangePacking, containerPtr);\n\t    }\n\t} else {\n\t    if (containerPtr->flags & ALLOCED_CONTAINER) {\n\t\tTkFreeGeometryContainer(container, \"pack\");\n\t\tcontainerPtr->flags &= ~ALLOCED_CONTAINER;\n\t    }\n\t    containerPtr->flags |= DONT_PROPAGATE;\n\t}\n\tbreak;\n    }\n    case PACK_SLAVES:\n    case PACK_CONTENT: {\n\tTk_Window container;\n\tPacker *containerPtr, *contentPtr;\n\tTcl_Obj *resultObj;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tif (!(containerPtr = GetPacker(container))) {\n\t    return TCL_OK;\n\t}\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj,\n\t\t    Tk_NewWindowObj(contentPtr->tkwin));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    }\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *------------------------------------------------------------------------\n *\n * PackReqProc --\n *\n *\tThis function is invoked by Tk_GeometryRequest for windows managed by\n *\tthe packer.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for tkwin, and all its managed siblings, to be re-packed at\n *\tthe next idle point.\n *\n *------------------------------------------------------------------------\n */\n\nstatic void\nPackReqProc(\n    void *clientData,\t/* Packer's information about window that got\n\t\t\t\t * new preferred geometry.  */\n    TCL_UNUSED(Tk_Window))\t\t/* Other Tk-related information about the\n\t\t\t\t * window. */\n{\n    Packer *packPtr = (Packer *)clientData;\n\n    packPtr = packPtr->containerPtr;\n    if (!(packPtr->flags & REQUESTED_REPACK)) {\n\tpackPtr->flags |= REQUESTED_REPACK;\n\tTcl_DoWhenIdle(ArrangePacking, packPtr);\n    }\n}\n\f\n/*\n *------------------------------------------------------------------------\n *\n * PackLostContentProc --\n *\n *\tThis function is invoked by Tk whenever some other geometry claims\n *\tcontrol over a content window that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all packer-related information about the content.\n *\n *------------------------------------------------------------------------\n */\n\nstatic void\nPackLostContentProc(\n    void *clientData,\t/* Packer structure for content window that was\n\t\t\t\t * stolen away. */\n    TCL_UNUSED(Tk_Window))\t\t/* Tk's handle for the content window. */\n{\n    Packer *contentPtr = (Packer *)clientData;\n\n    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\tTk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n    }\n    Unlink(contentPtr);\n    Tk_UnmapWindow(contentPtr->tkwin);\n}\n\f\n/*\n *------------------------------------------------------------------------\n *\n * ArrangePacking --\n *\n *\tThis function is invoked (using the Tcl_DoWhenIdle mechanism) to\n *\tre-layout a set of windows managed by the packer. It is invoked at\n *\tidle time so that a series of packer requests can be merged into a\n *\tsingle layout operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe packed content of containerPtr may get resized or moved.\n *\n *------------------------------------------------------------------------\n */\n\nstatic void\nArrangePacking(\n    void *clientData)\t/* Structure describing container whose content\n\t\t\t\t * are to be re-layed out. */\n{\n    Packer *containerPtr = (Packer *)clientData;\n    Packer *contentPtr;\n    int cavityX, cavityY, cavityWidth, cavityHeight;\n\t\t\t\t/* These variables keep track of the\n\t\t\t\t * as-yet-unallocated space remaining in the\n\t\t\t\t * middle of the container window. */\n    int frameX, frameY, frameWidth, frameHeight;\n\t\t\t\t/* These variables keep track of the frame\n\t\t\t\t * allocated to the current window. */\n    int x, y, width, height;\t/* These variables are used to hold the actual\n\t\t\t\t * geometry of the current window. */\n    int abort;\t\t\t/* May get set to non-zero to abort this\n\t\t\t\t * repacking operation. */\n    int borderX, borderY;\n    int borderTop, borderBtm;\n    int borderLeft, borderRight;\n    int maxWidth, maxHeight, tmp;\n\n    containerPtr->flags &= ~REQUESTED_REPACK;\n\n    /*\n     * If the container has no content anymore, then leave the container's size as-is.\n     * Otherwise there is no way to \"relinquish\" control over the container\n     * so another geometry manager can take over.\n     */\n\n    if (containerPtr->contentPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Abort any nested call to ArrangePacking for this window, since we'll do\n     * everything necessary here, and set up so this call can be aborted if\n     * necessary.\n     */\n\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n    containerPtr->abortPtr = &abort;\n    abort = 0;\n    Tcl_Preserve(containerPtr);\n\n    /*\n     * Pass #1: scan all the content to figure out the total amount of space\n     * needed. Two separate width and height values are computed:\n     *\n     * width -\t\tHolds the sum of the widths (plus padding) of all the\n     *\t\t\tcontent seen so far that were packed LEFT or RIGHT.\n     * height -\t\tHolds the sum of the heights (plus padding) of all the\n     *\t\t\tcontent seen so far that were packed TOP or BOTTOM.\n     *\n     * maxWidth -\tGradually builds up the width needed by the container to\n     *\t\t\tjust barely satisfy all the content's needs. For each\n     *\t\t\tcontent, the code computes the width needed for all the\n     *\t\t\tcontent so far and updates maxWidth if the new value is\n     *\t\t\tgreater.\n     * maxHeight -\tSame as maxWidth, except keeps height info.\n     */\n\n    width = maxWidth = Tk_InternalBorderLeft(containerPtr->tkwin) +\n\t    Tk_InternalBorderRight(containerPtr->tkwin);\n    height = maxHeight = Tk_InternalBorderTop(containerPtr->tkwin) +\n\t    Tk_InternalBorderBottom(containerPtr->tkwin);\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tif ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {\n\t    tmp = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padX + contentPtr->iPadX + width;\n\t    if (tmp > maxWidth) {\n\t\tmaxWidth = tmp;\n\t    }\n\t    height += Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padY + contentPtr->iPadY;\n\t} else {\n\t    tmp = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padY + contentPtr->iPadY + height;\n\t    if (tmp > maxHeight) {\n\t\tmaxHeight = tmp;\n\t    }\n\t    width += Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padX + contentPtr->iPadX;\n\t}\n    }\n    if (width > maxWidth) {\n\tmaxWidth = width;\n    }\n    if (height > maxHeight) {\n\tmaxHeight = height;\n    }\n\n    if (maxWidth < Tk_MinReqWidth(containerPtr->tkwin)) {\n\tmaxWidth = Tk_MinReqWidth(containerPtr->tkwin);\n    }\n    if (maxHeight < Tk_MinReqHeight(containerPtr->tkwin)) {\n\tmaxHeight = Tk_MinReqHeight(containerPtr->tkwin);\n    }\n\n    /*\n     * If the total amount of space needed in the container window has changed,\n     * and if we're propagating geometry information, then notify the next\n     * geometry manager up and requeue ourselves to start again after the\n     * container has had a chance to resize us.\n     */\n\n    if (((maxWidth != Tk_ReqWidth(containerPtr->tkwin))\n\t    || (maxHeight != Tk_ReqHeight(containerPtr->tkwin)))\n\t    && !(containerPtr->flags & DONT_PROPAGATE)) {\n\tTk_GeometryRequest(containerPtr->tkwin, maxWidth, maxHeight);\n\tcontainerPtr->flags |= REQUESTED_REPACK;\n\tTcl_DoWhenIdle(ArrangePacking, containerPtr);\n\tgoto done;\n    }\n\n    /*\n     * Pass #2: scan the content a second time assigning new sizes. The\n     * \"cavity\" variables keep track of the unclaimed space in the cavity of\n     * the window; this shrinks inward as we allocate windows around the\n     * edges. The \"frame\" variables keep track of the space allocated to the\n     * current window and its frame. The current window is then placed\n     * somewhere inside the frame, depending on anchor.\n     */\n\n    cavityX = x = Tk_InternalBorderLeft(containerPtr->tkwin);\n    cavityY = y = Tk_InternalBorderTop(containerPtr->tkwin);\n    cavityWidth = Tk_Width(containerPtr->tkwin) -\n\t    Tk_InternalBorderLeft(containerPtr->tkwin) -\n\t    Tk_InternalBorderRight(containerPtr->tkwin);\n    cavityHeight = Tk_Height(containerPtr->tkwin) -\n\t    Tk_InternalBorderTop(containerPtr->tkwin) -\n\t    Tk_InternalBorderBottom(containerPtr->tkwin);\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t    contentPtr = contentPtr->nextPtr) {\n\tif ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {\n\t    frameWidth = cavityWidth;\n\t    frameHeight = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padY + contentPtr->iPadY;\n\t    if (contentPtr->flags & EXPAND) {\n\t\tframeHeight += YExpansion(contentPtr, cavityHeight);\n\t    }\n\t    cavityHeight -= frameHeight;\n\t    if (cavityHeight < 0) {\n\t\tframeHeight += cavityHeight;\n\t\tcavityHeight = 0;\n\t    }\n\t    frameX = cavityX;\n\t    if (contentPtr->side == TOP) {\n\t\tframeY = cavityY;\n\t\tcavityY += frameHeight;\n\t    } else {\n\t\tframeY = cavityY + cavityHeight;\n\t    }\n\t} else {\n\t    frameHeight = cavityHeight;\n\t    frameWidth = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t    + contentPtr->padX + contentPtr->iPadX;\n\t    if (contentPtr->flags & EXPAND) {\n\t\tframeWidth += XExpansion(contentPtr, cavityWidth);\n\t    }\n\t    cavityWidth -= frameWidth;\n\t    if (cavityWidth < 0) {\n\t\tframeWidth += cavityWidth;\n\t\tcavityWidth = 0;\n\t    }\n\t    frameY = cavityY;\n\t    if (contentPtr->side == LEFT) {\n\t\tframeX = cavityX;\n\t\tcavityX += frameWidth;\n\t    } else {\n\t\tframeX = cavityX + cavityWidth;\n\t    }\n\t}\n\n\t/*\n\t * Now that we've got the size of the frame for the window, compute\n\t * the window's actual size and location using the fill, padding, and\n\t * frame factors. The variables \"borderX\" and \"borderY\" are used to\n\t * handle the differences between old-style packing and the new style\n\t * (in old-style, iPadX and iPadY are always zero and padding is\n\t * completely ignored except when computing frame size).\n\t */\n\n\tif (contentPtr->flags & OLD_STYLE) {\n\t    borderX = borderY = 0;\n\t    borderTop = borderBtm = 0;\n\t    borderLeft = borderRight = 0;\n\t} else {\n\t    borderX = contentPtr->padX;\n\t    borderY = contentPtr->padY;\n\t    borderLeft = contentPtr->padLeft;\n\t    borderRight = borderX - borderLeft;\n\t    borderTop = contentPtr->padTop;\n\t    borderBtm = borderY - borderTop;\n\t}\n\twidth = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t+ contentPtr->iPadX;\n\tif ((contentPtr->flags & FILLX)\n\t\t|| (width > (frameWidth - borderX))) {\n\t    width = frameWidth - borderX;\n\t}\n\theight = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t+ contentPtr->iPadY;\n\tif ((contentPtr->flags & FILLY)\n\t\t|| (height > (frameHeight - borderY))) {\n\t    height = frameHeight - borderY;\n\t}\n\tswitch (contentPtr->anchor) {\n\tcase TK_ANCHOR_N:\n\t    x = frameX + (borderLeft + frameWidth - width - borderRight)/2;\n\t    y = frameY + borderTop;\n\t    break;\n\tcase TK_ANCHOR_NE:\n\t    x = frameX + frameWidth - width - borderRight;\n\t    y = frameY + borderTop;\n\t    break;\n\tcase TK_ANCHOR_E:\n\t    x = frameX + frameWidth - width - borderRight;\n\t    y = frameY + (borderTop + frameHeight - height - borderBtm)/2;\n\t    break;\n\tcase TK_ANCHOR_SE:\n\t    x = frameX + frameWidth - width - borderRight;\n\t    y = frameY + frameHeight - height - borderBtm;\n\t    break;\n\tcase TK_ANCHOR_S:\n\t    x = frameX + (borderLeft + frameWidth - width - borderRight)/2;\n\t    y = frameY + frameHeight - height - borderBtm;\n\t    break;\n\tcase TK_ANCHOR_SW:\n\t    x = frameX + borderLeft;\n\t    y = frameY + frameHeight - height - borderBtm;\n\t    break;\n\tcase TK_ANCHOR_W:\n\t    x = frameX + borderLeft;\n\t    y = frameY + (borderTop + frameHeight - height - borderBtm)/2;\n\t    break;\n\tcase TK_ANCHOR_NW:\n\t    x = frameX + borderLeft;\n\t    y = frameY + borderTop;\n\t    break;\n\tdefault:\n\t    x = frameX + (borderLeft + frameWidth - width - borderRight)/2;\n\t    y = frameY + (borderTop + frameHeight - height - borderBtm)/2;\n\t    break;\n\t}\n\twidth -= contentPtr->doubleBw;\n\theight -= contentPtr->doubleBw;\n\n\t/*\n\t * The final step is to set the position, size, and mapped/unmapped\n\t * state of the content. If the content is a child of the container, then do\n\t * this here. Otherwise let Tk_MaintainGeometry do the work.\n\t */\n\n\tif (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {\n\t    if ((width <= 0) || (height <= 0)) {\n\t\tTk_UnmapWindow(contentPtr->tkwin);\n\t    } else {\n\t\tif ((x != Tk_X(contentPtr->tkwin))\n\t\t\t|| (y != Tk_Y(contentPtr->tkwin))\n\t\t\t|| (width != Tk_Width(contentPtr->tkwin))\n\t\t\t|| (height != Tk_Height(contentPtr->tkwin))) {\n\t\t    Tk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);\n\t\t}\n\t\tif (abort) {\n\t\t    goto done;\n\t\t}\n\n\t\t/*\n\t\t * Don't map the content if the container isn't mapped: wait until\n\t\t * the container gets mapped later.\n\t\t */\n\n\t\tif (Tk_IsMapped(containerPtr->tkwin)) {\n\t\t    Tk_MapWindow(contentPtr->tkwin);\n\t\t}\n\t    }\n\t} else {\n\t    if ((width <= 0) || (height <= 0)) {\n\t\tTk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);\n\t\tTk_UnmapWindow(contentPtr->tkwin);\n\t    } else {\n\t\tTk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin,\n\t\t\tx, y, width, height);\n\t    }\n\t}\n\n\t/*\n\t * Changes to the window's structure could cause almost anything to\n\t * happen, including deleting the parent or child. If this happens,\n\t * we'll be told to abort.\n\t */\n\n\tif (abort) {\n\t    goto done;\n\t}\n    }\n\n  done:\n    containerPtr->abortPtr = NULL;\n    Tcl_Release(containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XExpansion --\n *\n *\tGiven a list of packed content, the first of which is packed on the\n *\tleft or right and is expandable, compute how much to expand the child.\n *\n * Results:\n *\tThe return value is the number of additional pixels to give to the\n *\tchild.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nXExpansion(\n    Packer *contentPtr,\t/* First in list of remaining content. */\n    int cavityWidth)\t\t/* Horizontal space left for all remaining\n\t\t\t\t * content. */\n{\n    int numExpand, minExpand, curExpand;\n    int childWidth;\n\n    /*\n     * This function is tricky because windows packed top or bottom can be\n     * interspersed among expandable windows packed left or right. Scan\n     * through the list, keeping a running sum of the widths of all left and\n     * right windows (actually, count the cavity space not allocated) and a\n     * running count of all expandable left and right windows. At each top or\n     * bottom window, and at the end of the list, compute the expansion factor\n     * that seems reasonable at that point. Return the smallest factor seen at\n     * any of these points.\n     */\n\n    minExpand = cavityWidth;\n    numExpand = 0;\n    for ( ; contentPtr != NULL; contentPtr = contentPtr->nextPtr) {\n\tchildWidth = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t+ contentPtr->padX + contentPtr->iPadX;\n\tif ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {\n\t    if (numExpand) {\n\t\tcurExpand = (cavityWidth - childWidth)/numExpand;\n\t\tif (curExpand < minExpand) {\n\t\t    minExpand = curExpand;\n\t\t}\n\t    }\n\t} else {\n\t    cavityWidth -= childWidth;\n\t    if (contentPtr->flags & EXPAND) {\n\t\tnumExpand++;\n\t    }\n\t}\n    }\n    if (numExpand) {\n\tcurExpand = cavityWidth/numExpand;\n\tif (curExpand < minExpand) {\n\t    minExpand = curExpand;\n\t}\n    }\n    return (minExpand < 0) ? 0 : minExpand;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * YExpansion --\n *\n *\tGiven a list of packed content, the first of which is packed on the top\n *\tor bottom and is expandable, compute how much to expand the child.\n *\n * Results:\n *\tThe return value is the number of additional pixels to give to the\n *\tchild.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nYExpansion(\n    Packer *contentPtr,\t/* First in list of remaining content. */\n    int cavityHeight)\t\t/* Vertical space left for all remaining\n\t\t\t\t * content. */\n{\n    int numExpand, minExpand, curExpand;\n    int childHeight;\n\n    /*\n     * See comments for XExpansion.\n     */\n\n    minExpand = cavityHeight;\n    numExpand = 0;\n    for ( ; contentPtr != NULL; contentPtr = contentPtr->nextPtr) {\n\tchildHeight = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw\n\t\t+ contentPtr->padY + contentPtr->iPadY;\n\tif ((contentPtr->side == LEFT) || (contentPtr->side == RIGHT)) {\n\t    if (numExpand) {\n\t\tcurExpand = (cavityHeight - childHeight)/numExpand;\n\t\tif (curExpand < minExpand) {\n\t\t    minExpand = curExpand;\n\t\t}\n\t    }\n\t} else {\n\t    cavityHeight -= childHeight;\n\t    if (contentPtr->flags & EXPAND) {\n\t\tnumExpand++;\n\t    }\n\t}\n    }\n    if (numExpand) {\n\tcurExpand = cavityHeight/numExpand;\n\tif (curExpand < minExpand) {\n\t    minExpand = curExpand;\n\t}\n    }\n    return (minExpand < 0) ? 0 : minExpand;\n}\n\f\n/*\n *------------------------------------------------------------------------\n *\n * GetPacker --\n *\n *\tThis internal function is used to locate a Packer structure for a\n *\twindow, creating one if one doesn't exist already, except if the window\n *\tis already dead.\n *\n * Results:\n *\tThe return value is a pointer to the Packer structure corresponding to\n *\ttkwin, or NULL when tkwin is already dead.\n *\n * Side effects:\n *\tA new packer structure may be created. If so, then a callback is set\n *\tup to clean things up when the window is deleted.\n *\n *------------------------------------------------------------------------\n */\n\nstatic Packer *\nGetPacker(\n    Tk_Window tkwin)\t\t/* Token for window for which packer structure\n\t\t\t\t * is desired. */\n{\n    Packer *packPtr;\n    Tcl_HashEntry *hPtr;\n    int isNew;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (((TkWindow *) tkwin)->flags & TK_ALREADY_DEAD) {\n\treturn NULL;\n    }\n\n    if (!dispPtr->packInit) {\n\tdispPtr->packInit = 1;\n\tTcl_InitHashTable(&dispPtr->packerHashTable, TCL_ONE_WORD_KEYS);\n    }\n\n    /*\n     * See if there's already packer for this window. If not, then create a\n     * new one.\n     */\n\n    hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin,\n\t    &isNew);\n    if (!isNew) {\n\treturn (Packer *)Tcl_GetHashValue(hPtr);\n    }\n    packPtr = (Packer *)Tcl_Alloc(sizeof(Packer));\n    packPtr->tkwin = tkwin;\n    packPtr->containerPtr = NULL;\n    packPtr->nextPtr = NULL;\n    packPtr->contentPtr = NULL;\n    packPtr->side = TOP;\n    packPtr->anchor = TK_ANCHOR_CENTER;\n    packPtr->padX = packPtr->padY = 0;\n    packPtr->padLeft = packPtr->padTop = 0;\n    packPtr->iPadX = packPtr->iPadY = 0;\n    packPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;\n    packPtr->abortPtr = NULL;\n    packPtr->flags = 0;\n    Tcl_SetHashValue(hPtr, packPtr);\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t    PackStructureProc, packPtr);\n    return packPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Unlink --\n *\n *\tRemove a packer from its container's list of content.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe container will be scheduled for repacking.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnlink(\n    Packer *packPtr)\t/* Window to unlink. */\n{\n    Packer *containerPtr, *packPtr2;\n\n    containerPtr = packPtr->containerPtr;\n    if (containerPtr == NULL) {\n\treturn;\n    }\n    if (containerPtr->contentPtr == packPtr) {\n\tcontainerPtr->contentPtr = packPtr->nextPtr;\n    } else {\n\tfor (packPtr2 = containerPtr->contentPtr; ; packPtr2 = packPtr2->nextPtr) {\n\t    if (packPtr2 == NULL) {\n\t\tTcl_Panic(\"Unlink couldn't find previous window\");\n\t    }\n\t    if (packPtr2->nextPtr == packPtr) {\n\t\tpackPtr2->nextPtr = packPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    if (!(containerPtr->flags & REQUESTED_REPACK)) {\n\tcontainerPtr->flags |= REQUESTED_REPACK;\n\tTcl_DoWhenIdle(ArrangePacking, containerPtr);\n    }\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n\n    packPtr->containerPtr = NULL;\n\n    /*\n     * If we have emptied this container from content it means we are no longer\n     * handling it and should mark it as free.\n     *\n     * Send the event \"NoManagedChild\" to the container to inform it about there\n     * being no managed children inside it.\n     */\n\n    if ((containerPtr->contentPtr == NULL) && (containerPtr->flags & ALLOCED_CONTAINER)) {\n\tTkFreeGeometryContainer(containerPtr->tkwin, \"pack\");\n\tcontainerPtr->flags &= ~ALLOCED_CONTAINER;\n\tTk_SendVirtualEvent(containerPtr->tkwin, \"NoManagedChild\", NULL);\n    }\n\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyPacker --\n *\n *\tThis function is invoked by Tcl_EventuallyFree or Tcl_Release to clean\n *\tup the internal structure of a packer at a safe time (when no-one is\n *\tusing it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the packer is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyPacker(\n    void *memPtr)\t\t/* Info about packed window that is now dead. */\n{\n    Packer *packPtr = (Packer *)memPtr;\n\n    if (packPtr->flags & REQUESTED_REPACK) {\n\tTcl_CancelIdleCall(ArrangePacking, packPtr);\n    }\n    Tcl_Free(packPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PackStructureProc --\n *\n *\tThis function is invoked by the Tk event dispatcher in response to\n *\tStructureNotify events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf a window was just deleted, clean up all its packer-related\n *\tinformation. If it was just resized, repack its content, if any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPackStructureProc(\n    void *clientData,\t/* Our information about window referred to by\n\t\t\t\t * eventPtr. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Packer *packPtr = (Packer *)clientData;\n\n    if (eventPtr->type == ConfigureNotify) {\n\tif ((packPtr->contentPtr != NULL)\n\t\t&& !(packPtr->flags & REQUESTED_REPACK)) {\n\t    packPtr->flags |= REQUESTED_REPACK;\n\t    Tcl_DoWhenIdle(ArrangePacking, packPtr);\n\t}\n\tif ((packPtr->containerPtr != NULL)\n\t\t&& (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) {\n\t    if (!(packPtr->containerPtr->flags & REQUESTED_REPACK)) {\n\t\tpackPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width;\n\t\tpackPtr->containerPtr->flags |= REQUESTED_REPACK;\n\t\tTcl_DoWhenIdle(ArrangePacking, packPtr->containerPtr);\n\t    }\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tPacker *contentPtr, *nextPtr;\n\n\tif (packPtr->containerPtr != NULL) {\n\t    Unlink(packPtr);\n\t}\n\n\tfor (contentPtr = packPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = nextPtr) {\n\t    Tk_ManageGeometry(contentPtr->tkwin, NULL, NULL);\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t    contentPtr->containerPtr = NULL;\n\t    nextPtr = contentPtr->nextPtr;\n\t    contentPtr->nextPtr = NULL;\n\t}\n\n\tif (packPtr->tkwin != NULL) {\n\t    TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr;\n\t    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable,\n\t\t    packPtr->tkwin));\n\t}\n\n\tif (packPtr->flags & REQUESTED_REPACK) {\n\t    Tcl_CancelIdleCall(ArrangePacking, packPtr);\n\t}\n\tpackPtr->tkwin = NULL;\n\tTcl_EventuallyFree(packPtr, DestroyPacker);\n    } else if (eventPtr->type == MapNotify) {\n\t/*\n\t * When a container gets mapped, must redo the geometry computation so\n\t * that all of its content get remapped.\n\t */\n\n\tif ((packPtr->contentPtr != NULL)\n\t\t&& !(packPtr->flags & REQUESTED_REPACK)) {\n\t    packPtr->flags |= REQUESTED_REPACK;\n\t    Tcl_DoWhenIdle(ArrangePacking, packPtr);\n\t}\n    } else if (eventPtr->type == UnmapNotify) {\n\tPacker *packPtr2;\n\n\t/*\n\t * Unmap all of the content when the container gets unmapped, so that they\n\t * don't bother to keep redisplaying themselves.\n\t */\n\n\tfor (packPtr2 = packPtr->contentPtr; packPtr2 != NULL;\n\t     packPtr2 = packPtr2->nextPtr) {\n\t    Tk_UnmapWindow(packPtr2->tkwin);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureContent --\n *\n *\tThis implements the guts of the \"pack configure\" command. Given a list\n *\tof content and configuration options, it arranges for the packer to\n *\tmanage the content and sets the specified options.\n *\n * Results:\n *\tTCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned\n *\tand the interp's result is set to contain an error message.\n *\n * Side effects:\n *\tContent windows get taken over by the packer.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureContent(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Window tkwin,\t\t/* Any window in application containing\n\t\t\t\t * content. Used to look up content names. */\n    Tcl_Size objc,\t\t\t/* Number of elements in argv. */\n    Tcl_Obj *const objv[])\t/* Argument objects: contains one or more\n\t\t\t\t * window names followed by any number of\n\t\t\t\t * \"option value\" pairs. Caller must make sure\n\t\t\t\t * that there is at least one window name. */\n{\n    Packer *containerPtr, *contentPtr, *prevPtr, *otherPtr;\n    Tk_Window other, content, parent, ancestor;\n    TkWindow *container;\n    int tmp, positionGiven;\n    Tcl_Size i, j, numWindows;\n    const char *string;\n    static const char *const optionStrings[] = {\n\t\"-after\", \"-anchor\", \"-before\", \"-expand\", \"-fill\",\n\t\"-in\", \"-ipadx\", \"-ipady\", \"-padx\", \"-pady\", \"-side\", NULL };\n    enum options {\n\tCONF_AFTER, CONF_ANCHOR, CONF_BEFORE, CONF_EXPAND, CONF_FILL,\n\tCONF_IN, CONF_IPADX, CONF_IPADY, CONF_PADX, CONF_PADY, CONF_SIDE };\n    int index, side;\n\n    /*\n     * Find out how many windows are specified.\n     */\n\n    for (numWindows = 0; numWindows < objc; numWindows++) {\n\tstring = Tcl_GetString(objv[numWindows]);\n\tif (string[0] != '.') {\n\t    break;\n\t}\n    }\n\n    /*\n     * Iterate over all of the content windows, parsing the configuration\n     * options for each content. It's a bit wasteful to re-parse the options for\n     * each content, but things get too messy if we try to parse the arguments\n     * just once at the beginning. For example, if a content already is packed\n     * we want to just change a few existing values without resetting\n     * everything. If there are multiple windows, the -after, -before, and -in\n     * options only get processed for the first window.\n     */\n\n    containerPtr = NULL;\n    prevPtr = NULL;\n    positionGiven = 0;\n    for (j = 0; j < numWindows; j++) {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[j], &content) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tk_TopWinHierarchy(content)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't pack \\\"%s\\\": it's a top-level window\",\n\t\t    Tcl_GetString(objv[j])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"TOPLEVEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (!(contentPtr = GetPacker(content))) {\n\t    continue;\n\t}\n\n\tcontentPtr->flags &= ~OLD_STYLE;\n\n\t/*\n\t * If the content isn't currently packed, reset all of its configuration\n\t * information to default values (there could be old values left from\n\t * a previous packing).\n\t */\n\n\tif (contentPtr->containerPtr == NULL) {\n\t    contentPtr->side = TOP;\n\t    contentPtr->anchor = TK_ANCHOR_CENTER;\n\t    contentPtr->padX = contentPtr->padY = 0;\n\t    contentPtr->padLeft = contentPtr->padTop = 0;\n\t    contentPtr->iPadX = contentPtr->iPadY = 0;\n\t    contentPtr->flags &= ~(FILLX|FILLY|EXPAND);\n\t}\n\n\tfor (i = numWindows; i < objc; i+=2) {\n\t    if ((i+2) > objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"extra option \\\"%s\\\" (option with no value?)\",\n\t\t\tTcl_GetString(objv[i])));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"PACK\", \"BAD_PARAMETER\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings,\n\t\t    \"option\", 0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    switch ((enum options) index) {\n\t    case CONF_AFTER:\n\t\tif (j == 0) {\n\t\t    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)\n\t\t\t    != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    if (!(prevPtr = GetPacker(other))) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (prevPtr->containerPtr == NULL) {\n\t\t    notPacked:\n\t\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\t\"window \\\"%s\\\" isn't packed\",\n\t\t\t\tTcl_GetString(objv[i+1])));\n\t\t\tTcl_SetErrorCode(interp, \"TK\", \"PACK\", \"NOT_PACKED\",\n\t\t\t\t(char *)NULL);\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    containerPtr = prevPtr->containerPtr;\n\t\t    positionGiven = 1;\n\t\t}\n\t\tbreak;\n\t    case CONF_ANCHOR:\n\t\tif (Tk_GetAnchorFromObj(interp, objv[i+1], &contentPtr->anchor)\n\t\t\t!= TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_BEFORE:\n\t\tif (j == 0) {\n\t\t    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)\n\t\t\t    != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    if (!(otherPtr = GetPacker(other))) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (otherPtr->containerPtr == NULL) {\n\t\t\tgoto notPacked;\n\t\t    }\n\t\t    containerPtr = otherPtr->containerPtr;\n\t\t    prevPtr = containerPtr->contentPtr;\n\t\t    if (prevPtr == otherPtr) {\n\t\t\tprevPtr = NULL;\n\t\t    } else {\n\t\t\twhile (prevPtr->nextPtr != otherPtr) {\n\t\t\t    prevPtr = prevPtr->nextPtr;\n\t\t\t}\n\t\t    }\n\t\t    positionGiven = 1;\n\t\t}\n\t\tbreak;\n\t    case CONF_EXPAND:\n\t\tif (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->flags &= ~EXPAND;\n\t\tif (tmp) {\n\t\t    contentPtr->flags |= EXPAND;\n\t\t}\n\t\tbreak;\n\t    case CONF_FILL:\n\t\tstring = Tcl_GetString(objv[i+1]);\n\t\tif (strcmp(string, \"none\") == 0) {\n\t\t    contentPtr->flags &= ~(FILLX|FILLY);\n\t\t} else if (strcmp(string, \"x\") == 0) {\n\t\t    contentPtr->flags = (contentPtr->flags & ~FILLY) | FILLX;\n\t\t} else if (strcmp(string, \"y\") == 0) {\n\t\t    contentPtr->flags = (contentPtr->flags & ~FILLX) | FILLY;\n\t\t} else if (strcmp(string, \"both\") == 0) {\n\t\t    contentPtr->flags |= FILLX|FILLY;\n\t\t} else {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad fill style \\\"%s\\\": must be \"\n\t\t\t    \"none, x, y, or both\", string));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"FILL\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_IN:\n\t\tif (j == 0) {\n\t\t    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)\n\t\t\t    != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t    if (!(containerPtr = GetPacker(other))) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    prevPtr = containerPtr->contentPtr;\n\t\t    if (prevPtr != NULL) {\n\t\t\twhile (prevPtr->nextPtr != NULL) {\n\t\t\t    prevPtr = prevPtr->nextPtr;\n\t\t\t}\n\t\t    }\n\t\t    positionGiven = 1;\n\t\t}\n\t\tbreak;\n\t    case CONF_IPADX:\n\t\tif ((Tk_GetPixelsFromObj(interp, content, objv[i+1], &tmp)\n\t\t\t!= TCL_OK) || (tmp < 0)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad ipadx value \\\"%s\\\": must be positive screen\"\n\t\t\t    \" distance\", Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INT_PAD\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->iPadX = tmp * 2;\n\t\tbreak;\n\t    case CONF_IPADY:\n\t\tif ((Tk_GetPixelsFromObj(interp, content, objv[i+1], &tmp)\n\t\t\t!= TCL_OK) || (tmp < 0)) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"bad ipady value \\\"%s\\\": must be positive screen\"\n\t\t\t    \" distance\", Tcl_GetString(objv[i+1])));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INT_PAD\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->iPadY = tmp * 2;\n\t\tbreak;\n\t    case CONF_PADX:\n\t\tif (TkParsePadAmount(interp, content, objv[i+1],\n\t\t\t&contentPtr->padLeft, &contentPtr->padX) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_PADY:\n\t\tif (TkParsePadAmount(interp, content, objv[i+1],\n\t\t\t&contentPtr->padTop, &contentPtr->padY) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case CONF_SIDE:\n\t\tif (Tcl_GetIndexFromObj(interp, objv[i+1], sideNames,\n\t\t\t\"side\", TCL_EXACT, &side) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tcontentPtr->side = (Side) side;\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * If no position in a packing list was specified and the content is\n\t * already packed, then leave it in its current location in its\n\t * current packing list.\n\t */\n\n\tif (!positionGiven && (contentPtr->containerPtr != NULL)) {\n\t    containerPtr = contentPtr->containerPtr;\n\t    goto scheduleLayout;\n\t}\n\n\t/*\n\t * If the content is going to be put back after itself or the same -in\n\t * window is passed in again, then just skip the whole operation,\n\t * since it won't work anyway.\n\t */\n\n\tif (prevPtr == contentPtr) {\n\t    containerPtr = contentPtr->containerPtr;\n\t    goto scheduleLayout;\n\t}\n\n\t/*\n\t * If none of the \"-in\", \"-before\", or \"-after\" options has been\n\t * specified, arrange for the content to go at the end of the order for\n\t * its parent.\n\t */\n\n\tif (!positionGiven) {\n\t    if (!(containerPtr = GetPacker(Tk_Parent(content)))) {\n\t\tcontinue;\n\t    }\n\t    prevPtr = containerPtr->contentPtr;\n\t    if (prevPtr != NULL) {\n\t\twhile (prevPtr->nextPtr != NULL) {\n\t\t    prevPtr = prevPtr->nextPtr;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Make sure that the content's parent is either the container or an\n\t * ancestor of the container, and that the container and content aren't the\n\t * same.\n\t */\n\n\tparent = Tk_Parent(content);\n\tfor (ancestor = containerPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {\n\t    if (ancestor == parent) {\n\t\tbreak;\n\t    }\n\t    if (Tk_TopWinHierarchy(ancestor)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't pack \\\"%s\\\" inside \\\"%s\\\"\", Tcl_GetString(objv[j]),\n\t\t\tTk_PathName(containerPtr->tkwin)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (content == containerPtr->tkwin) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't pack \\\"%s\\\" inside itself\", Tcl_GetString(objv[j])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"SELF\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Check for management loops.\n\t */\n\n\tfor (container = (TkWindow *)containerPtr->tkwin; container != NULL;\n\t     container = (TkWindow *)TkGetContainer(container)) {\n\t    if (container == (TkWindow *)content) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't put \\\"%s\\\" inside \\\"%s\\\": would cause management loop\",\n\t\t\tTcl_GetString(objv[j]), Tk_PathName(containerPtr->tkwin)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"LOOP\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (containerPtr->tkwin != Tk_Parent(content)) {\n\t    ((TkWindow *)content)->maintainerPtr = (TkWindow *)containerPtr->tkwin;\n\t}\n\n\t/*\n\t * Unpack the content if it's currently packed, then position it after\n\t * prevPtr.\n\t */\n\n\tif (contentPtr->containerPtr != NULL) {\n\t    if ((contentPtr->containerPtr != containerPtr) &&\n\t\t    (contentPtr->containerPtr->tkwin\n\t\t    != Tk_Parent(contentPtr->tkwin))) {\n\t\tTk_UnmaintainGeometry(contentPtr->tkwin,\n\t\t\tcontentPtr->containerPtr->tkwin);\n\t    }\n\t    Unlink(contentPtr);\n\t}\n\n\tcontentPtr->containerPtr = containerPtr;\n\tif (prevPtr == NULL) {\n\t    contentPtr->nextPtr = containerPtr->contentPtr;\n\t    containerPtr->contentPtr = contentPtr;\n\t} else {\n\t    contentPtr->nextPtr = prevPtr->nextPtr;\n\t    prevPtr->nextPtr = contentPtr;\n\t}\n\tTk_ManageGeometry(content, &packerType, contentPtr);\n\tprevPtr = contentPtr;\n\n\tif (!(containerPtr->flags & DONT_PROPAGATE)) {\n\t    if (TkSetGeometryContainer(interp, containerPtr->tkwin, \"pack\")\n\t\t    != TCL_OK) {\n\t\tTk_ManageGeometry(content, NULL, NULL);\n\t\tUnlink(contentPtr);\n\t\treturn TCL_ERROR;\n\t    }\n\t    containerPtr->flags |= ALLOCED_CONTAINER;\n\t}\n\n\t/*\n\t * Arrange for the container to be re-packed at the first idle moment.\n\t */\n\n    scheduleLayout:\n\tif (containerPtr->abortPtr != NULL) {\n\t    *containerPtr->abortPtr = 1;\n\t}\n\tif (!(containerPtr->flags & REQUESTED_REPACK)) {\n\t    containerPtr->flags |= REQUESTED_REPACK;\n\t    Tcl_DoWhenIdle(ArrangePacking, containerPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPanedWindow.c",
    "content": "/*\n * tkPanedWindow.c --\n *\n *\tThis module implements \"paned window\" widgets that are object based. A\n *\t\"paned window\" is a widget that manages the geometry for some number\n *\tof other widgets, placing a movable \"sash\" between them, which can be\n *\tused to alter the relative sizes of adjacent widgets.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n * Copyright © 2000 Ajuba Solutions.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"default.h\"\n\n/*\n * Flag values for \"sticky\"ness. The 16 combinations subsume the packer's\n * notion of anchor and fill.\n *\n * STICK_NORTH\t\tThis window sticks to the top of its cavity.\n * STICK_EAST\t\tThis window sticks to the right edge of its cavity.\n * STICK_SOUTH\t\tThis window sticks to the bottom of its cavity.\n * STICK_WEST\t\tThis window sticks to the left edge of its cavity.\n */\n\n#define STICK_NORTH\t\t1\n#define STICK_EAST\t\t2\n#define STICK_SOUTH\t\t4\n#define STICK_WEST\t\t8\n\n/*\n * The following table defines the legal values for the -orient option.\n */\n\nstatic const char *const orientStrings[] = {\n    \"horizontal\", \"vertical\", NULL\n};\n\nenum orient { ORIENT_HORIZONTAL, ORIENT_VERTICAL };\n\n/*\n * The following table defines the legal values for the -stretch option.\n */\n\nstatic const char *const stretchStrings[] = {\n    \"always\", \"first\", \"last\", \"middle\", \"never\", NULL\n};\n\nenum stretch {\n    STRETCH_ALWAYS,\t\t/* Always give extra space to this pane. */\n    STRETCH_FIRST,\t\t/* Give extra space to pane if it is first. */\n    STRETCH_LAST,\t\t/* Give extra space to pane if it is last. */\n    STRETCH_MIDDLE,\t\t/* Give extra space to pane only if it is\n\t\t\t\t * neither first nor last. */\n    STRETCH_NEVER\t\t/* Never give extra space to this pane. */\n};\n\n/*\n * Codify the stretchiness rule in one place.\n */\n\n#define IsStretchable(stretch,index,first,last)\t\t\t\\\n    (((stretch) == STRETCH_ALWAYS) ||\t\t\t\t\\\n     ((stretch) == STRETCH_FIRST && (index) == (first)) ||\t\\\n     ((stretch) == STRETCH_LAST && (index) == (last)) ||\t\\\n     ((stretch) == STRETCH_MIDDLE && (index) != (first) && (index) != (last)))\n\ntypedef struct {\n    Tk_OptionTable pwOptions;\t/* Token for paned window option table. */\n    Tk_OptionTable paneOpts;\t/* Token for pane cget option table. */\n} OptionTables;\n\n/*\n * One structure of the following type is kept for each window\n * managed by a paned window widget.\n */\n\ntypedef struct Pane {\n    Tk_Window tkwin;\t\t/* Window being managed. */\n    Tcl_Obj *minSizeObj;\t\t/* Minimum size of this pane, on the relevant\n\t\t\t\t * axis, in pixels. */\n    Tcl_Obj *padXObj;\t\t/* Additional padding requested for pane, in\n\t\t\t\t * the x dimension. */\n    Tcl_Obj *padYObj;\t\t/* Additional padding requested for pane, in\n\t\t\t\t * the y dimension. */\n    Tcl_Obj *widthObj, *heightObj;\n\t\t\t\t/* Tcl_Obj rep's of pane width/height, to\n\t\t\t\t * allow for null values. */\n    int sticky;\t\t\t/* Sticky string. */\n    int x, y;\t\t\t/* Coordinates of the widget. */\n    int paneWidth, paneHeight;\t/* Pane dimensions (may be different from\n\t\t\t\t * pane width/height). */\n    int sashx, sashy;\t\t/* Coordinates of the sash of the right or\n\t\t\t\t * bottom of this pane. */\n    int markx, marky;\t\t/* Coordinates of the last mark set for the\n\t\t\t\t * sash. */\n    int handlex, handley;\t/* Coordinates of the sash handle. */\n    enum stretch stretch;\t/* Controls how pane grows/shrinks */\n    bool hide;\t\t\t/* Controls visibility of pane */\n    struct PanedWindow *containerPtr;\n\t\t\t\t/* Paned window managing the window. */\n    Tk_Window after;\t\t/* Placeholder for parsing options. */\n    Tk_Window before;\t\t/* Placeholder for parsing options. */\n    int width;\t\t\t/* Pane width. Same as widthObj, but updatable */\n    int height;\t\t\t/* Pane height. Same as heightObj, but updatable */\n} Pane;\n\n/*\n * A data structure of the following type is kept for each paned window widget\n * managed by this file:\n */\n\ntypedef struct PanedWindow {\n    Tk_Window tkwin;\t\t/* Window that embodies the paned window. */\n    Tk_Window proxywin;\t\t/* Window for the resizing proxy. */\n    Display *display;\t\t/* X's token for the window's display. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with widget. */\n    Tcl_Command widgetCmd;\t/* Token for square's widget command. */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n    Tk_OptionTable paneOpts;\t/* Token for pane cget table. */\n    Tk_3DBorder background;\t/* Background color. */\n    Tcl_Obj *borderWidthObj;\n    int relief;\t\t\t/* 3D border effect (TK_RELIEF_RAISED, etc) */\n    Tcl_Obj *widthObj;\t\t/* Tcl_Obj rep for width. */\n    Tcl_Obj *heightObj;\t\t/* Tcl_Obj rep for height. */\n    enum orient orient;\t\t/* Orientation of the widget. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or None. */\n    bool resizeOpaque;\t\t/* Boolean indicating whether resize should be\n\t\t\t\t * opaque or rubberband style. */\n    int sashRelief;\t\t/* Relief used to draw sash. */\n    Tcl_Obj *sashWidthObj;\t/* Tcl_Obj rep for sash width. */\n    Tcl_Obj *sashPadObj;\t/* Tcl_Obj rep for sash padding. */\n    bool showHandle;\t\t/* Boolean indicating whether sash handles\n\t\t\t\t * should be drawn. */\n    Tcl_Obj *handleSizeObj;\t/* Size of one side of a sash handle (handles\n\t\t\t\t * are square), in pixels. */\n    Tcl_Obj *handlePadObj;\t/* Distance from border to draw handle. */\n    Tk_Cursor sashCursor;\t/* Cursor used when mouse is above a sash. */\n    GC gc;\t\t\t/* Graphics context for copying from\n\t\t\t\t * off-screen pixmap onto screen. */\n    int proxyx, proxyy;\t\t/* Proxy x,y coordinates. */\n    Tk_3DBorder proxyBackground;/* Background color used to draw proxy. If NULL, use background. */\n    Tcl_Obj *proxyBorderWidthObj; /* Tcl_Obj rep for proxyBorderWidth */\n    int proxyRelief;\t\t/* Relief used to draw proxy, if TK_RELIEF_NULL then use relief. */\n    Pane **panes;\t\t/* Pointer to array of Panes. */\n    Tcl_Size numPanes;\t\t/* Number of panes. */\n    int sizeofPanes;\t\t/* Number of elements in the panes array. */\n    int flags;\t\t\t/* Flags for widget; see below. */\n} PanedWindow;\n\n/*\n * Flags used for paned windows:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has been\n *\t\t\t\tqueued to redraw this window.\n *\n * WIDGET_DELETED:\t\tNon-zero means that the paned window has been,\n *\t\t\t\tor is in the process of being, deleted.\n *\n * RESIZE_PENDING:\t\tNon-zero means that the window might need to\n *\t\t\t\tchange its size (or the size of its panes)\n *\t\t\t\tbecause of a change in the size of one of its\n *\t\t\t\tchildren.\n */\n\n#define REDRAW_PENDING\t\t0x0001\n#define WIDGET_DELETED\t\t0x0002\n#define REQUESTED_RELAYOUT\t0x0004\n#define RECOMPUTE_GEOMETRY\t0x0008\n#define PROXY_REDRAW_PENDING\t0x0010\n#define RESIZE_PENDING\t\t0x0020\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tPanedWindowCmdDeletedProc(void *clientData);\nstatic int\t\tConfigurePanedWindow(Tcl_Interp *interp,\n\t\t\t    PanedWindow *pwPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tDestroyPanedWindow(PanedWindow *pwPtr);\nstatic void\t\tDisplayPanedWindow(void *clientData);\nstatic void\t\tPanedWindowEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tProxyWindowEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tDisplayProxyWindow(void *clientData);\nstatic void\t\tPanedWindowWorldChanged(void *instanceData);\nstatic Tcl_ObjCmdProc2 PanedWindowWidgetObjCmd;\nstatic void\t\tPanedWindowLostPaneProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tPanedWindowReqProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tArrangePanes(void *clientData);\nstatic void\t\tUnlink(Pane *panePtr);\nstatic Pane *\t\tGetPane(PanedWindow *pwPtr, Tk_Window tkwin);\nstatic void\t\tGetFirstLastVisiblePane(PanedWindow *pwPtr,\n\t\t\t    int *firstPtr, int *lastPtr);\nstatic void\t\tPaneStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tPanedWindowSashCommand(PanedWindow *pwPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj * const objv[]);\nstatic int\t\tPanedWindowProxyCommand(PanedWindow *pwPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj * const objv[]);\nstatic void\t\tComputeGeometry(PanedWindow *pwPtr);\nstatic int\t\tConfigurePanes(PanedWindow *pwPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj * const objv[]);\nstatic void\t\tDestroyOptionTables(void *clientData,\n\t\t\t    Tcl_Interp *interp);\nstatic int\t\tSetSticky(void *clientData, Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tcl_Obj **value, char *recordPtr,\n\t\t\t    Tcl_Size internalOffset, char *oldInternalPtr,\n\t\t\t    int flags);\nstatic Tcl_Obj *\tGetSticky(void *clientData, Tk_Window tkwin,\n\t\t\t    char *recordPtr, Tcl_Size internalOffset);\nstatic void\t\tRestoreSticky(void *clientData, Tk_Window tkwin,\n\t\t\t    char *internalPtr, char *oldInternalPtr);\nstatic void\t\tAdjustForSticky(int sticky, int cavityWidth,\n\t\t\t    int cavityHeight, int *xPtr, int *yPtr,\n\t\t\t    int *paneWidthPtr, int *paneHeightPtr);\nstatic void\t\tMoveSash(PanedWindow *pwPtr, int sash, int diff);\nstatic void *\tComputeSlotAddress(void *recordPtr, Tcl_Size offset);\nstatic int\t\tPanedWindowIdentifyCoords(PanedWindow *pwPtr,\n\t\t\t    Tcl_Interp *interp, int x, int y);\n\n/*\n * Sashes are between panes only, so there is one less sash than panes\n */\n\n#define ValidSashIndex(pwPtr, sash) \\\n\t(((sash) >= 0) && ((sash) < ((pwPtr)->numPanes-1)))\n\nstatic const Tk_GeomMgr panedWindowMgrType = {\n    \"panedwindow\",\t\t/* name */\n    PanedWindowReqProc,\t\t/* requestProc */\n    PanedWindowLostPaneProc,\t/* lostPaneProc */\n};\n\n/*\n * Information used for objv parsing.\n */\n\n#define GEOMETRY\t\t0x0001\n\n/*\n * The following structure contains pointers to functions used for processing\n * the custom \"-sticky\" option for panes.\n */\n\nstatic const Tk_ObjCustomOption stickyOption = {\n    \"sticky\",\t\t\t/* name */\n    SetSticky,\t\t\t/* setProc */\n    GetSticky,\t\t\t/* getProc */\n    RestoreSticky,\t\t/* restoreProc */\n    NULL,\t\t\t/* freeProc */\n    0\n};\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_PANEDWINDOW_BG_COLOR, TCL_INDEX_NONE, offsetof(PanedWindow, background), 0,\n\tDEF_PANEDWINDOW_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_PANEDWINDOW_BORDERWIDTH, offsetof(PanedWindow, borderWidthObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_PANEDWINDOW_CURSOR, TCL_INDEX_NONE, offsetof(PanedWindow, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-handlepad\", \"handlePad\", \"HandlePad\",\n\tDEF_PANEDWINDOW_HANDLEPAD, offsetof(PanedWindow, handlePadObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY},\n    {TK_OPTION_PIXELS, \"-handlesize\", \"handleSize\", \"HandleSize\",\n\tDEF_PANEDWINDOW_HANDLESIZE, offsetof(PanedWindow, handleSizeObj),\n\tTCL_INDEX_NONE, 0, 0, GEOMETRY},\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\",\n\tDEF_PANEDWINDOW_HEIGHT, offsetof(PanedWindow, heightObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, GEOMETRY},\n    {TK_OPTION_BOOLEAN, \"-opaqueresize\", \"opaqueResize\", \"OpaqueResize\",\n\tDEF_PANEDWINDOW_OPAQUERESIZE, TCL_INDEX_NONE,\n\toffsetof(PanedWindow, resizeOpaque), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\",\n\tDEF_PANEDWINDOW_ORIENT, TCL_INDEX_NONE, offsetof(PanedWindow, orient),\n\tTK_OPTION_ENUM_VAR, orientStrings, GEOMETRY},\n    {TK_OPTION_BORDER, \"-proxybackground\", \"proxyBackground\", \"ProxyBackground\",\n\t0, TCL_INDEX_NONE, offsetof(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,\n\t(void *)DEF_PANEDWINDOW_BG_MONO, 0},\n    {TK_OPTION_PIXELS, \"-proxyborderwidth\", \"proxyBorderWidth\", \"ProxyBorderWidth\",\n\tDEF_PANEDWINDOW_PROXYBORDER, offsetof(PanedWindow, proxyBorderWidthObj),\n\tTCL_INDEX_NONE, 0, 0, GEOMETRY},\n    {TK_OPTION_RELIEF, \"-proxyrelief\", \"proxyRelief\", \"Relief\",\n\t0, TCL_INDEX_NONE, offsetof(PanedWindow, proxyRelief),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_PANEDWINDOW_RELIEF, TCL_INDEX_NONE, offsetof(PanedWindow, relief), 0, 0, 0},\n    {TK_OPTION_CURSOR, \"-sashcursor\", \"sashCursor\", \"Cursor\",\n\tDEF_PANEDWINDOW_SASHCURSOR, TCL_INDEX_NONE, offsetof(PanedWindow, sashCursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-sashpad\", \"sashPad\", \"SashPad\",\n\tDEF_PANEDWINDOW_SASHPAD, offsetof(PanedWindow, sashPadObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY},\n    {TK_OPTION_RELIEF, \"-sashrelief\", \"sashRelief\", \"Relief\",\n\tDEF_PANEDWINDOW_SASHRELIEF, TCL_INDEX_NONE, offsetof(PanedWindow, sashRelief),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-sashwidth\", \"sashWidth\", \"Width\",\n\tDEF_PANEDWINDOW_SASHWIDTH, offsetof(PanedWindow, sashWidthObj),\n\tTCL_INDEX_NONE, 0, 0, GEOMETRY},\n    {TK_OPTION_BOOLEAN, \"-showhandle\", \"showHandle\", \"ShowHandle\",\n\tDEF_PANEDWINDOW_SHOWHANDLE, TCL_INDEX_NONE, offsetof(PanedWindow, showHandle),\n\tTK_OPTION_VAR(bool), 0, GEOMETRY},\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\",\n\tDEF_PANEDWINDOW_WIDTH, offsetof(PanedWindow, widthObj),\n\tTCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, GEOMETRY},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\nstatic const Tk_OptionSpec paneOptionSpecs[] = {\n    {TK_OPTION_WINDOW, \"-after\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_AFTER, TCL_INDEX_NONE, offsetof(Pane, after),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_WINDOW, \"-before\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_BEFORE, TCL_INDEX_NONE, offsetof(Pane, before),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-height\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_HEIGHT, offsetof(Pane, heightObj),\n\toffsetof(Pane, height), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-hide\", \"hide\", \"Hide\",\n\tDEF_PANEDWINDOW_PANE_HIDE, TCL_INDEX_NONE, offsetof(Pane, hide), TK_OPTION_VAR(bool), 0, GEOMETRY},\n    {TK_OPTION_PIXELS, \"-minsize\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_MINSIZE, offsetof(Pane, minSizeObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_PADX, offsetof(Pane, padXObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_PADY, offsetof(Pane, padYObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_CUSTOM, \"-sticky\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_STICKY, TCL_INDEX_NONE, offsetof(Pane, sticky),\n\t0, &stickyOption, 0},\n    {TK_OPTION_STRING_TABLE, \"-stretch\", \"stretch\", \"Stretch\",\n\tDEF_PANEDWINDOW_PANE_STRETCH, TCL_INDEX_NONE, offsetof(Pane, stretch),\n\tTK_OPTION_ENUM_VAR, stretchStrings, 0},\n    {TK_OPTION_PIXELS, \"-width\", NULL, NULL,\n\tDEF_PANEDWINDOW_PANE_WIDTH, offsetof(Pane, widthObj),\n\toffsetof(Pane, width), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PanedWindowObjCmd --\n *\n *\tThis function is invoked to process the \"panedwindow\" Tcl command. It\n *\tcreates a new \"panedwindow\" widget.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tA new widget is created and configured.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PanedWindowObjCmd(\n    TCL_UNUSED(void *),\t/* NULL. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj * const objv[])\t/* Argument objects. */\n{\n    PanedWindow *pwPtr;\n    Tk_Window tkwin, parent;\n    OptionTables *pwOpts;\n    XSetWindowAttributes atts;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    pwOpts = (OptionTables *)\n\t    Tcl_GetAssocData(interp, \"PanedWindowOptionTables\", NULL);\n    if (pwOpts == NULL) {\n\t/*\n\t * The first time this function is invoked, the option tables will be\n\t * NULL. We then create the option tables from the templates and store\n\t * a pointer to the tables as the command's clientData so we'll have\n\t * easy access to it in the future.\n\t */\n\n\tpwOpts = (OptionTables *)Tcl_Alloc(sizeof(OptionTables));\n\n\t/*\n\t * Set up an exit handler to free the optionTables struct.\n\t */\n\n\tTcl_SetAssocData(interp, \"PanedWindowOptionTables\",\n\t\tDestroyOptionTables, pwOpts);\n\n\t/*\n\t * Create the paned window option tables.\n\t */\n\n\tpwOpts->pwOptions = Tk_CreateOptionTable(interp, optionSpecs);\n\tpwOpts->paneOpts = Tk_CreateOptionTable(interp, paneOptionSpecs);\n    }\n\n    Tk_SetClass(tkwin, \"Panedwindow\");\n\n    /*\n     * Allocate and initialize the widget record.\n     */\n\n    pwPtr = (PanedWindow *)Tcl_Alloc(sizeof(PanedWindow));\n    memset((void *)pwPtr, 0, (sizeof(PanedWindow)));\n    pwPtr->tkwin = tkwin;\n    pwPtr->display = Tk_Display(tkwin);\n    pwPtr->interp = interp;\n    pwPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(pwPtr->tkwin), PanedWindowWidgetObjCmd, pwPtr,\n\t    PanedWindowCmdDeletedProc);\n    pwPtr->optionTable = pwOpts->pwOptions;\n    pwPtr->paneOpts = pwOpts->paneOpts;\n    pwPtr->relief = TK_RELIEF_RAISED;\n    pwPtr->gc = NULL;\n    pwPtr->cursor = NULL;\n    pwPtr->sashCursor = NULL;\n\n    /*\n     * Keep a hold of the associated tkwin until we destroy the widget,\n     * otherwise Tk might free it while we still need it.\n     */\n\n    Tcl_Preserve(pwPtr->tkwin);\n\n    if (Tk_InitOptions(interp, pwPtr, pwOpts->pwOptions,\n\t    tkwin) != TCL_OK) {\n\tTk_DestroyWindow(pwPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tk_CreateEventHandler(pwPtr->tkwin, ExposureMask|StructureNotifyMask,\n\t    PanedWindowEventProc, pwPtr);\n\n    /*\n     * Find the toplevel ancestor of the panedwindow, and make a proxy win as\n     * a child of that window; this way the proxy can always float above\n     * panes in the panedwindow.\n     */\n\n    parent = Tk_Parent(pwPtr->tkwin);\n    while (!(Tk_IsTopLevel(parent))) {\n\tparent = Tk_Parent(parent);\n\tif (parent == NULL) {\n\t    parent = pwPtr->tkwin;\n\t    break;\n\t}\n    }\n\n    pwPtr->proxywin = Tk_CreateAnonymousWindow(interp, parent, NULL);\n\n    /*\n     * The proxy window has to be able to share GCs with the main panedwindow\n     * despite being children of windows with potentially different\n     * characteristics, and it looks better that way too. [Bug 702230] Also\n     * set the X window save under attribute to avoid expose events as the\n     * proxy sash is dragged across the panes. [Bug 1036963]\n     */\n\n    Tk_SetWindowVisual(pwPtr->proxywin,\n\t    Tk_Visual(tkwin), Tk_Depth(tkwin), Tk_Colormap(tkwin));\n    Tk_CreateEventHandler(pwPtr->proxywin, ExposureMask, ProxyWindowEventProc,\n\t    pwPtr);\n    atts.save_under = True;\n    Tk_ChangeWindowAttributes(pwPtr->proxywin, CWSaveUnder, &atts);\n\n    if (ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2) != TCL_OK) {\n\tTk_DestroyWindow(pwPtr->proxywin);\n\tTk_DestroyWindow(pwPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(pwPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PanedWindowWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nPanedWindowWidgetObjCmd(\n    void *clientData,\t/* Information about square widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj * const objv[])\t/* Argument objects. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n    int result = TCL_OK;\n    static const char *const optionStrings[] = {\n\t\"add\", \"cget\", \"configure\", \"forget\", \"identify\", \"panecget\",\n\t\"paneconfigure\", \"panes\", \"proxy\", \"sash\", NULL\n    };\n    enum options {\n\tPW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY, PW_PANECGET,\n\tPW_PANECONFIGURE, PW_PANES, PW_PROXY, PW_SASH\n    };\n    Tcl_Obj *resultObj;\n    int index, x, y;\n    Tcl_Size count, i;\n    Tk_Window tkwin;\n    Pane *panePtr;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"command\",\n\t    0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    Tcl_Preserve(pwPtr);\n\n    switch ((enum options) index) {\n    case PW_ADD:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"widget ?widget ...?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = ConfigurePanes(pwPtr, interp, objc, objv);\n\tbreak;\n\n    case PW_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresultObj = Tk_GetOptionValue(interp, pwPtr,\n\t\tpwPtr->optionTable, objv[2], pwPtr->tkwin);\n\tif (resultObj == NULL) {\n\t    result = TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\tbreak;\n\n    case PW_CONFIGURE:\n\tresultObj = NULL;\n\tif (objc <= 3) {\n\t    resultObj = Tk_GetOptionInfo(interp, pwPtr,\n\t\t    pwPtr->optionTable,\n\t\t    (objc == 3) ? objv[2] : NULL, pwPtr->tkwin);\n\t    if (resultObj == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, resultObj);\n\t    }\n\t} else {\n\t    result = ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2);\n\t}\n\tbreak;\n\n    case PW_FORGET: {\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"widget ?widget ...?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\t/*\n\t * Clean up each window named in the arg list.\n\t */\n\tfor (count = 0, i = 2; i < objc; i++) {\n\t    Tk_Window pane = Tk_NameToWindow(interp, Tcl_GetString(objv[i]),\n\t\t    pwPtr->tkwin);\n\n\t    if (pane == NULL) {\n\t\tcontinue;\n\t    }\n\t    panePtr = GetPane(pwPtr, pane);\n\t    if ((panePtr != NULL) && (panePtr->containerPtr != NULL)) {\n\t\tcount++;\n\t\tTk_ManageGeometry(pane, NULL, NULL);\n\t\tTk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);\n\t\tTk_DeleteEventHandler(panePtr->tkwin, StructureNotifyMask,\n\t\t\tPaneStructureProc, panePtr);\n\t\tTk_UnmapWindow(panePtr->tkwin);\n\t\tUnlink(panePtr);\n\t    }\n\t    if (count != 0) {\n\t\tComputeGeometry(pwPtr);\n\t    }\n\t}\n\tbreak;\n    }\n\n    case PW_IDENTIFY:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"x y\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresult = PanedWindowIdentifyCoords(pwPtr, interp, x, y);\n\tbreak;\n\n    case PW_PANECGET:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pane option\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin);\n\tif (tkwin == NULL) {\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresultObj = NULL;\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    if (pwPtr->panes[i]->tkwin == tkwin) {\n\t\tresultObj = Tk_GetOptionValue(interp,\n\t\t\tpwPtr->panes[i], pwPtr->paneOpts,\n\t\t\tobjv[3], tkwin);\n\t    }\n\t}\n\tif (resultObj == NULL) {\n\t    if (i == pwPtr->numPanes) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"not managed by this window\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"PANEDWINDOW\", \"UNMANAGED\",\n\t\t\t(char *)NULL);\n\t    }\n\t    result = TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, resultObj);\n\t}\n\tbreak;\n\n    case PW_PANECONFIGURE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"pane ?-option value ...?\");\n\t    result = TCL_ERROR;\n\t    break;\n\t}\n\tresultObj = NULL;\n\tif (objc <= 4) {\n\t    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),\n\t\t    pwPtr->tkwin);\n\t    if (tkwin == NULL) {\n\t\t/*\n\t\t * Just a plain old bad window; Tk_NameToWindow filled in an\n\t\t * error message for us.\n\t\t */\n\n\t\tresult = TCL_ERROR;\n\t\tbreak;\n\t    }\n\t    for (i = 0; i < pwPtr->numPanes; i++) {\n\t\tif (pwPtr->panes[i]->tkwin == tkwin) {\n\t\t    resultObj = Tk_GetOptionInfo(interp,\n\t\t\t    pwPtr->panes[i], pwPtr->paneOpts,\n\t\t\t    (objc == 4) ? objv[3] : NULL,\n\t\t\t    pwPtr->tkwin);\n\t\t    if (resultObj == NULL) {\n\t\t\tresult = TCL_ERROR;\n\t\t    } else {\n\t\t\tTcl_SetObjResult(interp, resultObj);\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t} else {\n\t    result = ConfigurePanes(pwPtr, interp, objc, objv);\n\t}\n\tbreak;\n\n    case PW_PANES:\n\tresultObj = Tcl_NewObj();\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj,\n\t\t    Tk_NewWindowObj(pwPtr->panes[i]->tkwin));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n\n    case PW_PROXY:\n\tresult = PanedWindowProxyCommand(pwPtr, interp, objc, objv);\n\tbreak;\n\n    case PW_SASH:\n\tresult = PanedWindowSashCommand(pwPtr, interp, objc, objv);\n\tbreak;\n    }\n    Tcl_Release(pwPtr);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigurePanes --\n *\n *\tAdd or alter the configuration options of a pane in a paned window.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tDepends on options; may add a pane to the paned window, may alter the\n *\tgeometry management options of a pane.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigurePanes(\n    PanedWindow *pwPtr,\t\t/* Information about paned window. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int found, doubleBw, numNewPanes, haveLoc;\n    Tcl_Size index, insertIndex, i, j, firstOptionArg;\n    Tk_Window tkwin = NULL, ancestor, parent;\n    Pane *panePtr, **inserts, **newPanes;\n    Pane options;\n    const char *arg;\n\n    /*\n     * Find the non-window name arguments; these are the configure options for\n     * the panes. Also validate that the window names given are legitimate\n     * (ie, they are real windows, they are not the panedwindow itself, etc.).\n     */\n\n    for (i = 2; i < objc; i++) {\n\targ = Tcl_GetString(objv[i]);\n\tif (arg[0] == '-') {\n\t    break;\n\t} else {\n\t    tkwin = Tk_NameToWindow(interp, arg, pwPtr->tkwin);\n\t    if (tkwin == NULL) {\n\t\t/*\n\t\t * Just a plain old bad window; Tk_NameToWindow filled in an\n\t\t * error message for us.\n\t\t */\n\n\t\treturn TCL_ERROR;\n\t    } else if (tkwin == pwPtr->tkwin) {\n\t\t/*\n\t\t * A panedwindow cannot manage itself.\n\t\t */\n\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"cannot add %s to itself\", arg));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"SELF\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    } else if (Tk_IsTopLevel(tkwin)) {\n\t\t/*\n\t\t * A panedwindow cannot manage a toplevel.\n\t\t */\n\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"cannot add toplevel %s to %s\", arg,\n\t\t\tTk_PathName(pwPtr->tkwin)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"TOPLEVEL\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    } else {\n\t\t/*\n\t\t * Make sure the panedwindow is the parent of the pane,\n\t\t * or a descendant of the pane's parent.\n\t\t */\n\n\t\tparent = Tk_Parent(tkwin);\n\t\tfor (ancestor = pwPtr->tkwin;;ancestor = Tk_Parent(ancestor)) {\n\t\t    if (ancestor == parent) {\n\t\t\tbreak;\n\t\t    }\n\t\t    if (Tk_IsTopLevel(ancestor)) {\n\t\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\t\"cannot add %s to %s\", arg,\n\t\t\t\tTk_PathName(pwPtr->tkwin)));\n\t\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\",\n\t\t\t\t\"HIERARCHY\", (char *)NULL);\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n    firstOptionArg = i;\n\n    /*\n     * Pre-parse the configuration options, to get the before/after specifiers\n     * into an easy-to-find location (a local variable). Also, check the\n     * return from Tk_SetOptions once, here, so we can save a little bit of\n     * extra testing in the for loop below.\n     */\n\n    memset((void *)&options, 0, sizeof(Pane));\n    if (Tk_SetOptions(interp, &options, pwPtr->paneOpts,\n\t    objc - firstOptionArg, objv + firstOptionArg,\n\t    pwPtr->tkwin, NULL, NULL) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If either -after or -before was given, find the numerical index that\n     * corresponds to the given window. If both -after and -before are given,\n     * the option precedence is: -after, then -before.\n     */\n\n    index = -1;\n    haveLoc = 0;\n    if (options.after != NULL) {\n\ttkwin = options.after;\n\thaveLoc = 1;\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    if (options.after == pwPtr->panes[i]->tkwin) {\n\t\tindex = i + 1;\n\t\tbreak;\n\t    }\n\t}\n    } else if (options.before != NULL) {\n\ttkwin = options.before;\n\thaveLoc = 1;\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    if (options.before == pwPtr->panes[i]->tkwin) {\n\t\tindex = i;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * If a window was given for -after/-before, but it's not a window managed\n     * by the panedwindow, throw an error\n     */\n\n    if (haveLoc && index == -1) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" is not managed by %s\",\n\t\tTk_PathName(tkwin), Tk_PathName(pwPtr->tkwin)));\n\tTcl_SetErrorCode(interp, \"TK\", \"PANEDWINDOW\", \"UNMANAGED\", (char *)NULL);\n\tTk_FreeConfigOptions(&options, pwPtr->paneOpts,\n\t\tpwPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Allocate an array to hold, in order, the pointers to the pane\n     * structures corresponding to the windows specified. Some of those\n     * structures may already have existed, some may be new.\n     */\n\n    inserts = (Pane **)Tcl_Alloc(sizeof(Pane *) * (firstOptionArg - 2));\n    insertIndex = 0;\n\n    /*\n     * Populate the inserts array, creating new pane structures as necessary,\n     * applying the options to each structure as we go, and, if necessary,\n     * marking the spot in the original panes array as empty (for\n     * pre-existing pane structures).\n     */\n\n    for (i = 0, numNewPanes = 0; i < firstOptionArg - 2; i++) {\n\t/*\n\t * We don't check that tkwin is NULL here, because the pre-pass above\n\t * guarantees that the input at this stage is good.\n\t */\n\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i + 2]),\n\t\tpwPtr->tkwin);\n\n\tfound = 0;\n\tfor (j = 0; j < pwPtr->numPanes; j++) {\n\t    if (pwPtr->panes[j] != NULL && pwPtr->panes[j]->tkwin == tkwin) {\n\t\tint minSize;\n\t\tTk_SetOptions(interp, pwPtr->panes[j],\n\t\t\tpwPtr->paneOpts, objc - firstOptionArg,\n\t\t\tobjv + firstOptionArg, pwPtr->tkwin, NULL, NULL);\n\t\tTk_GetPixelsFromObj(NULL, tkwin, pwPtr->panes[j]->minSizeObj, &minSize);\n\t\tfound = 1;\n\n\t\t/*\n\t\t * If the pane is supposed to move, add it to the inserts\n\t\t * array now; otherwise, leave it where it is.\n\t\t */\n\n\t\tif (index != -1) {\n\t\t    inserts[insertIndex++] = pwPtr->panes[j];\n\t\t    pwPtr->panes[j] = NULL;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\n\tif (found) {\n\t    continue;\n\t}\n\n\t/*\n\t * Make sure this pane wasn't already put into the inserts array,\n\t * i.e., when the user specifies the same window multiple times in a\n\t * single add command.\n\t */\n\tfor (j = 0; j < insertIndex; j++) {\n\t    if (inserts[j]->tkwin == tkwin) {\n\t\tfound = 1;\n\t\tbreak;\n\t    }\n\t}\n\tif (found) {\n\t    continue;\n\t}\n\n\t/*\n\t * Create a new pane structure and initialize it. All panes start\n\t * out with their \"natural\" dimensions.\n\t */\n\tint minSize;\n\n\tpanePtr = (Pane *)Tcl_Alloc(sizeof(Pane));\n\tmemset(panePtr, 0, sizeof(Pane));\n\tTk_InitOptions(interp, panePtr, pwPtr->paneOpts,\n\t\tpwPtr->tkwin);\n\tTk_SetOptions(interp, panePtr, pwPtr->paneOpts,\n\t\tobjc - firstOptionArg, objv + firstOptionArg,\n\t\tpwPtr->tkwin, NULL, NULL);\n\tpanePtr->tkwin = tkwin;\n\tpanePtr->containerPtr = pwPtr;\n\tdoubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;\n\tif (panePtr->width > 0) {\n\t    panePtr->paneWidth = panePtr->width;\n\t} else {\n\t    panePtr->paneWidth = Tk_ReqWidth(tkwin) + doubleBw;\n\t}\n\tif (panePtr->height > 0) {\n\t    panePtr->paneHeight = panePtr->height;\n\t} else {\n\t    panePtr->paneHeight = Tk_ReqHeight(tkwin) + doubleBw;\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &minSize);\n\n\t/*\n\t * Set up the geometry management callbacks for this pane.\n\t */\n\n\tTk_CreateEventHandler(panePtr->tkwin, StructureNotifyMask,\n\t\tPaneStructureProc, panePtr);\n\tTk_ManageGeometry(panePtr->tkwin, &panedWindowMgrType, panePtr);\n\tinserts[insertIndex++] = panePtr;\n\tnumNewPanes++;\n    }\n\n    /*\n     * Allocate the new panes array, then copy the panes into it, in order.\n     */\n\n    i = sizeof(Pane *) * (pwPtr->numPanes + numNewPanes);\n    newPanes = (Pane **)Tcl_Alloc(i);\n    memset(newPanes, 0, i);\n    if (index == -1) {\n\t/*\n\t * If none of the existing panes have to be moved, just copy the old\n\t * and append the new.\n\t * Be careful about the case pwPtr->numPanes == 0 since in this case\n\t * pwPtr->panes is NULL, and the memcpy would have undefined behavior.\n\t */\n\tif (pwPtr->numPanes) {\n\t    memcpy(newPanes, pwPtr->panes,\n\t\t    sizeof(Pane *) * pwPtr->numPanes);\n\t}\n\tmemcpy(&newPanes[pwPtr->numPanes], inserts,\n\t\tsizeof(Pane *) * numNewPanes);\n    } else {\n\t/*\n\t * If some of the existing panes were moved, the old panes array\n\t * will be partially populated, with some valid and some invalid\n\t * entries. Walk through it, copying valid entries to the new panes\n\t * array as we go; when we get to the insert location for the new\n\t * panes, copy the inserts array over, then finish off the old panes\n\t * array.\n\t */\n\n\tfor (i = 0, j = 0; i < index; i++) {\n\t    if (pwPtr->panes[i] != NULL) {\n\t\tnewPanes[j] = pwPtr->panes[i];\n\t\tj++;\n\t    }\n\t}\n\n\tmemcpy(&newPanes[j], inserts, sizeof(Pane *)*insertIndex);\n\tj += firstOptionArg - 2;\n\n\tfor (i = index; i < pwPtr->numPanes; i++) {\n\t    if (pwPtr->panes[i] != NULL) {\n\t\tnewPanes[j] = pwPtr->panes[i];\n\t\tj++;\n\t    }\n\t}\n    }\n\n    /*\n     * Make the new panes array the paned window's pane array, and clean up.\n     */\n\n    Tcl_Free(pwPtr->panes);\n    Tcl_Free(inserts);\n    pwPtr->panes = newPanes;\n\n    /*\n     * Set the paned window's pane count to the new value.\n     */\n\n    pwPtr->numPanes += numNewPanes;\n\n    Tk_FreeConfigOptions(&options, pwPtr->paneOpts, pwPtr->tkwin);\n\n    ComputeGeometry(pwPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PanedWindowSashCommand --\n *\n *\tImplementation of the panedwindow sash subcommand. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tDepends on the arguments.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPanedWindowSashCommand(\n    PanedWindow *pwPtr,\t\t/* Pointer to paned window information. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const sashOptionStrings[] = {\n\t\"coord\", \"dragto\", \"mark\", \"place\", NULL\n    };\n    enum sashOptions {\n\tSASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE\n    };\n    int index, sash, x, y, diff;\n    Tcl_Obj *coords[2];\n    Pane *panePtr;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum sashOptions) index) {\n    case SASH_COORD:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!ValidSashIndex(pwPtr, sash)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid sash index\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SASH_INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tpanePtr = pwPtr->panes[sash];\n\n\tcoords[0] = Tcl_NewWideIntObj(panePtr->sashx);\n\tcoords[1] = Tcl_NewWideIntObj(panePtr->sashy);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, coords));\n\tbreak;\n\n    case SASH_MARK:\n\tif (objc != 6 && objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index ?x y?\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!ValidSashIndex(pwPtr, sash)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid sash index\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SASH_INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (objc == 6) {\n\t    if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    pwPtr->panes[sash]->markx = x;\n\t    pwPtr->panes[sash]->marky = y;\n\t} else {\n\t    coords[0] = Tcl_NewWideIntObj(pwPtr->panes[sash]->markx);\n\t    coords[1] = Tcl_NewWideIntObj(pwPtr->panes[sash]->marky);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));\n\t}\n\tbreak;\n\n    case SASH_DRAGTO:\n    case SASH_PLACE:\n\tif (objc != 6) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index x y\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!ValidSashIndex(pwPtr, sash)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid sash index\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SASH_INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tpanePtr = pwPtr->panes[sash];\n\tif (pwPtr->orient == ORIENT_HORIZONTAL) {\n\t    if (index == SASH_PLACE) {\n\t\tdiff = x - pwPtr->panes[sash]->sashx;\n\t    } else {\n\t\tdiff = x - pwPtr->panes[sash]->markx;\n\t    }\n\t} else {\n\t    if (index == SASH_PLACE) {\n\t\tdiff = y - pwPtr->panes[sash]->sashy;\n\t    } else {\n\t\tdiff = y - pwPtr->panes[sash]->marky;\n\t    }\n\t}\n\n\tMoveSash(pwPtr, sash, diff);\n\tComputeGeometry(pwPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigurePanedWindow --\n *\n *\tThis function is called to process an objv/objc list in conjunction\n *\twith the Tk option database to configure (or reconfigure) a paned\n *\twindow widget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor pwPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigurePanedWindow(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    PanedWindow *pwPtr,\t\t/* Information about widget. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    Tk_SavedOptions savedOptions;\n    int typemask = 0;\n\n    if (Tk_SetOptions(interp, pwPtr, pwPtr->optionTable, objc, objv,\n\t    pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) {\n\tTk_RestoreSavedOptions(&savedOptions);\n\treturn TCL_ERROR;\n    }\n\n    Tk_FreeSavedOptions(&savedOptions);\n\n    PanedWindowWorldChanged(pwPtr);\n\n    /*\n     * If an option that affects geometry has changed, make a re-layout\n     * request.\n     */\n\n    if (typemask & GEOMETRY) {\n\tComputeGeometry(pwPtr);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PanedWindowWorldChanged --\n *\n *\tThis function is invoked anytime a paned window's world has changed in\n *\tsome way that causes the widget to have to recompute graphics contexts\n *\tand geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPaned window will be relayed out and redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPanedWindowWorldChanged(\n    void *instanceData)\t/* Information about the paned window. */\n{\n    XGCValues gcValues;\n    GC newGC;\n    PanedWindow *pwPtr = (PanedWindow *)instanceData;\n    int borderWidth, width = -1, height = -1;\n\n    /*\n     * Allocated a graphics context for drawing the paned window widget\n     * elements (background, sashes, etc.) and set the window background.\n     */\n\n    gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel;\n    newGC = Tk_GetGC(pwPtr->tkwin, GCBackground, &gcValues);\n    if (pwPtr->gc != NULL) {\n\tTk_FreeGC(pwPtr->display, pwPtr->gc);\n    }\n    pwPtr->gc = newGC;\n    Tk_SetWindowBackground(pwPtr->tkwin, gcValues.background);\n\n    /*\n     * Issue geometry size requests to Tk.\n     */\n\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->borderWidthObj, &borderWidth);\n    Tk_SetInternalBorder(pwPtr->tkwin, borderWidth);\n    if (pwPtr->widthObj) {\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->widthObj, &width);\n    }\n    if (pwPtr->heightObj) {\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->heightObj, &height);\n    }\n    if (width > 0 && height > 0) {\n\tTk_GeometryRequest(pwPtr->tkwin, width, height);\n    }\n\n    /*\n     * Arrange for the window to be redrawn, if neccessary.\n     */\n\n    if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayPanedWindow, pwPtr);\n\tpwPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PanedWindowEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tpaned windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPanedWindowEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n    Tcl_Size i;\n\n    if (eventPtr->type == Expose) {\n\tif (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);\n\t    pwPtr->flags |= REDRAW_PENDING;\n\t}\n    } else if (eventPtr->type == ConfigureNotify) {\n\tpwPtr->flags |= REQUESTED_RELAYOUT;\n\tif (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);\n\t    pwPtr->flags |= REDRAW_PENDING;\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tDestroyPanedWindow(pwPtr);\n    } else if (eventPtr->type == UnmapNotify) {\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    if (!pwPtr->panes[i]->hide) {\n\t\tTk_UnmapWindow(pwPtr->panes[i]->tkwin);\n\t    }\n\t}\n    } else if (eventPtr->type == MapNotify) {\n\tfor (i = 0; i < pwPtr->numPanes; i++) {\n\t    if (!pwPtr->panes[i]->hide) {\n\t\tTk_MapWindow(pwPtr->panes[i]->tkwin);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PanedWindowCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPanedWindowCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted or because the command was deleted,\n     * and then this function destroys the widget. The WIDGET_DELETED flag\n     * distinguishes these cases.\n     */\n\n    if (!(pwPtr->flags & WIDGET_DELETED)) {\n\tTk_DestroyWindow(pwPtr->proxywin);\n\tTk_DestroyWindow(pwPtr->tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayPanedWindow --\n *\n *\tThis function redraws the contents of a paned window widget. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's\n *\tnothing else for the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayPanedWindow(\n    void *clientData)\t/* Information about window. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n    Pane *panePtr;\n    Pixmap pixmap;\n    Tk_Window tkwin = pwPtr->tkwin;\n    int sashWidth, sashHeight;\n    const bool horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);\n    int first, last;\n    int borderWidth;\n    Tcl_Size i;\n\n    pwPtr->flags &= ~REDRAW_PENDING;\n    if ((pwPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    if (pwPtr->flags & REQUESTED_RELAYOUT) {\n\tArrangePanes(clientData);\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Create a pixmap for double-buffering, if necessary.\n     */\n\n    pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n    /*\n     * Redraw the widget's background and border.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, pwPtr->borderWidthObj, &borderWidth);\n    Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0,\n\t    Tk_Width(tkwin), Tk_Height(tkwin), borderWidth, pwPtr->relief);\n\n    /*\n     * Set up boilerplate geometry values for sashes (width, height, common\n     * coordinates).\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, pwPtr->sashWidthObj, &sashWidth);\n    if (horizontal) {\n\tsashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderLeft(tkwin));\n    } else {\n\tsashHeight = sashWidth;\n\tsashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderLeft(tkwin));\n    }\n\n    /*\n     * Draw the sashes.\n     */\n\n    GetFirstLastVisiblePane(pwPtr, &first, &last);\n    for (i = 0; i < pwPtr->numPanes - 1; i++) {\n\n\tpanePtr = pwPtr->panes[i];\n\tif (panePtr->hide || i == last) {\n\t    continue;\n\t}\n\tif (sashWidth > 0 && sashHeight > 0) {\n\t    Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,\n\t\t    panePtr->sashx, panePtr->sashy, sashWidth, sashHeight,\n\t\t    1, pwPtr->sashRelief);\n\t}\n\tif (pwPtr->showHandle) {\n\t    int handleSize;\n\t    Tk_GetPixelsFromObj(NULL, tkwin, pwPtr->handleSizeObj, &handleSize);\n\t    Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,\n\t\t    panePtr->handlex, panePtr->handley,\n\t\t    handleSize, handleSize, 1,\n\t\t    TK_RELIEF_RAISED);\n\t}\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0,\n\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(Tk_Display(tkwin), pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyPanedWindow --\n *\n *\tThis function is invoked by PanedWindowEventProc to free the internal\n *\tstructure of a paned window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the paned window is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyPanedWindow(\n    PanedWindow *pwPtr)\t\t/* Info about paned window widget. */\n{\n    Tcl_Size i;\n\n    /*\n     * First mark the widget as in the process of being deleted, so that any\n     * code that causes calls to other paned window functions will abort.\n     */\n\n    pwPtr->flags |= WIDGET_DELETED;\n\n    /*\n     * Cancel idle callbacks for redrawing the widget and for rearranging the\n     * panes.\n     */\n\n    if (pwPtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(DisplayPanedWindow, pwPtr);\n    }\n    if (pwPtr->flags & RESIZE_PENDING) {\n\tTcl_CancelIdleCall(ArrangePanes, pwPtr);\n    }\n\n    /*\n     * Clean up the pane list; foreach pane:\n     *  o  Cancel the pane's structure notification callback\n     *  o  Cancel geometry management for the pane.\n     *  o  Free memory for the pane\n     */\n\n    for (i = 0; i < pwPtr->numPanes; i++) {\n\tTk_DeleteEventHandler(pwPtr->panes[i]->tkwin, StructureNotifyMask,\n\t\tPaneStructureProc, pwPtr->panes[i]);\n\tTk_ManageGeometry(pwPtr->panes[i]->tkwin, NULL, NULL);\n\tTk_FreeConfigOptions(pwPtr->panes[i], pwPtr->paneOpts,\n\t\tpwPtr->tkwin);\n\tTcl_Free(pwPtr->panes[i]);\n\tpwPtr->panes[i] = NULL;\n    }\n    if (pwPtr->panes) {\n\tTcl_Free(pwPtr->panes);\n    }\n\n    /*\n     * Remove the widget command from the interpreter.\n     */\n\n    Tcl_DeleteCommandFromToken(pwPtr->interp, pwPtr->widgetCmd);\n\n    /*\n     * Let Tk_FreeConfigOptions clean up the rest.\n     */\n\n    Tk_FreeConfigOptions(pwPtr, pwPtr->optionTable, pwPtr->tkwin);\n    Tcl_Release(pwPtr->tkwin);\n    pwPtr->tkwin = NULL;\n\n    Tcl_EventuallyFree(pwPtr, TCL_DYNAMIC);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PanedWindowReqProc --\n *\n *\tThis function is invoked by Tk_GeometryRequest for windows managed by\n *\ta paned window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for tkwin, and all its managed siblings, to be re-arranged at\n *\tthe next idle point.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPanedWindowReqProc(\n    void *clientData,\t/* Paned window's information about window\n\t\t\t\t * that got new preferred geometry. */\n    TCL_UNUSED(Tk_Window))\t\t/* Other Tk-related information about the\n\t\t\t\t * window. */\n{\n    Pane *panePtr = (Pane *)clientData;\n    PanedWindow *pwPtr = (PanedWindow *) panePtr->containerPtr;\n\n    if (Tk_IsMapped(pwPtr->tkwin)) {\n\tif (!(pwPtr->flags & RESIZE_PENDING)) {\n\t    pwPtr->flags |= RESIZE_PENDING;\n\t    Tcl_DoWhenIdle(ArrangePanes, pwPtr);\n\t}\n    } else {\n\tint doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;\n\n\tif (panePtr->width <= 0) {\n\t    panePtr->paneWidth = Tk_ReqWidth(panePtr->tkwin) + doubleBw;\n\t}\n\tif (panePtr->height <= 0) {\n\t    panePtr->paneHeight = Tk_ReqHeight(panePtr->tkwin) + doubleBw;\n\t}\n\tComputeGeometry(pwPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PanedWindowLostPaneProc --\n *\n *\tThis function is invoked by Tk whenever some other geometry claims\n *\tcontrol over a pane that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all information about the pane. Causes geometry to be\n *\trecomputed for the panedwindow.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPanedWindowLostPaneProc(\n    void *clientData,\t/* Grid structure for the pane that was\n\t\t\t\t * stolen away. */\n    TCL_UNUSED(Tk_Window))\t\t/* Tk's handle for the pane. */\n{\n    Pane *panePtr = (Pane *)clientData;\n    PanedWindow *pwPtr = (PanedWindow *) panePtr->containerPtr;\n\n    if (pwPtr->tkwin != Tk_Parent(panePtr->tkwin)) {\n\tTk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);\n    }\n    Unlink(panePtr);\n    Tk_DeleteEventHandler(panePtr->tkwin, StructureNotifyMask,\n\t    PaneStructureProc, panePtr);\n    Tk_UnmapWindow(panePtr->tkwin);\n    panePtr->tkwin = NULL;\n    Tcl_Free(panePtr);\n    ComputeGeometry(pwPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ArrangePanes --\n *\n *\tThis function is invoked (using the Tcl_DoWhenIdle mechanism) to\n *\tre-layout a set of windows managed by a paned window. It is invoked at\n *\tidle time so that a series of pane requests can be merged into a\n *\tsingle layout operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe panes of containerPtr may get resized or moved.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nArrangePanes(\n    void *clientData)\t/* Structure describing parent whose panes\n\t\t\t\t * are to be re-layed out. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n    Pane *panePtr;\n    int newPaneWidth, newPaneHeight, paneX, paneY;\n    int paneWidth, paneHeight, paneSize, paneMinSize;\n    int doubleBw;\n    int x, y;\n    int sashWidth, sashOffset, sashCount, handleOffset;\n    int sashReserve, sxReserve, syReserve;\n    int internalBW;\n    int paneDynSize, paneDynMinSize, pwHeight, pwWidth, pwSize;\n    int first, last;\n    int stretchReserve, stretchAmount;\n    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);\n    int handleSize, sashPad, handlePad;\n    Tcl_Size i;\n\n    pwPtr->flags &= ~(REQUESTED_RELAYOUT|RESIZE_PENDING);\n\n    /*\n     * If the parent has no panes anymore, then don't do anything at all:\n     * just leave the parent's size as-is. Otherwise there is no way to\n     * \"relinquish\" control over the parent so another geometry manager can\n     * take over.\n     */\n\n    if (pwPtr->numPanes == 0) {\n\treturn;\n    }\n\n    Tcl_Preserve(pwPtr);\n\n    /*\n     * Find index of first and last visible panes.\n     */\n\n    GetFirstLastVisiblePane(pwPtr, &first, &last);\n\n    /*\n     * First pass; compute sizes\n     */\n\n    paneDynSize = paneDynMinSize = 0;\n    internalBW = Tk_InternalBorderLeft(pwPtr->tkwin);\n    pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);\n    pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);\n    x = y = internalBW;\n    stretchReserve = (horizontal ? pwWidth : pwHeight);\n\n    /*\n     * Calculate the sash width, including handle and padding, and the sash\n     * and handle offsets.\n     */\n\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashPadObj, &sashPad);\n    sashOffset = handleOffset = sashPad;\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashWidthObj, &sashWidth);\n    if (pwPtr->showHandle && handleSize > sashWidth) {\n\tsashOffset = ((handleSize - sashWidth) / 2) + sashPad;\n\tsashWidth = (2 * sashPad) + handleSize;\n    } else {\n\thandleOffset = ((sashWidth - handleSize) / 2) + sashPad;\n\tsashWidth = (2 * sashPad) + sashWidth;\n    }\n\n    for (i = sashCount = 0; i < pwPtr->numPanes; i++) {\n\tint padX, padY, minSize;\n\n\tpanePtr = pwPtr->panes[i];\n\n\tif (panePtr->hide) {\n\t    continue;\n\t}\n\n\t/*\n\t * Compute the total size needed by all the panes and the left-over,\n\t * or shortage of space available.\n\t */\n\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padXObj, &padX);\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padYObj, &padY);\n\tif (horizontal) {\n\t    if (panePtr->width > 0) {\n\t\tpaneSize = panePtr->width;\n\t    } else {\n\t\tpaneSize = panePtr->paneWidth;\n\t    }\n\t    stretchReserve -= paneSize + (2 * padX);\n\t} else {\n\t    if (panePtr->height > 0) {\n\t\tpaneSize = panePtr->height;\n\t    } else {\n\t\tpaneSize = panePtr->paneHeight;\n\t    }\n\t    stretchReserve -= paneSize + (2 * padY);\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &minSize);\n\tif (IsStretchable(panePtr->stretch,i,first,last)\n\t\t&& Tk_IsMapped(pwPtr->tkwin)) {\n\t    paneDynSize += paneSize;\n\t    paneDynMinSize += minSize;\n\t}\n\tif (i != last) {\n\t    stretchReserve -= sashWidth;\n\t    sashCount++;\n\t}\n    }\n\n    /*\n     * Second pass; adjust/arrange panes.\n     */\n\n    for (i = 0; i < pwPtr->numPanes; i++) {\n\tint padX, padY;\n\n\tpanePtr = pwPtr->panes[i];\n\n\tif (panePtr->hide) {\n\t    Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);\n\t    Tk_UnmapWindow(panePtr->tkwin);\n\t    continue;\n\t}\n\n\t/*\n\t * Compute the size of this pane. The algorithm (assuming a\n\t * horizontal paned window) is:\n\t *\n\t * 1.  Get \"base\" dimensions. If a width or height is specified for\n\t *     this pane, use those values; else use the ReqWidth/ReqHeight.\n\t * 2.  Using base dimensions, pane dimensions, and sticky values,\n\t *     determine the x and y, and actual width and height of the\n\t *     widget.\n\t */\n\n\tdoubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;\n\tnewPaneWidth = (panePtr->width > 0 ? panePtr->width :\n\t\tTk_ReqWidth(panePtr->tkwin) + doubleBw);\n\tnewPaneHeight = (panePtr->height > 0 ? panePtr->height :\n\t\tTk_ReqHeight(panePtr->tkwin) + doubleBw);\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &paneMinSize);\n\n\t/*\n\t * Calculate pane width and height.\n\t */\n\n\tif (horizontal) {\n\t    if (panePtr->width > 0) {\n\t\tpaneSize = panePtr->width;\n\t    } else {\n\t\tpaneSize = panePtr->paneWidth;\n\t    }\n\t    pwSize = pwWidth;\n\t} else {\n\t    if (panePtr->height > 0) {\n\t\tpaneSize = panePtr->height;\n\t    } else {\n\t\tpaneSize = panePtr->paneHeight;\n\t    }\n\t    pwSize = pwHeight;\n\t}\n\tif (IsStretchable(panePtr->stretch, i, first, last)) {\n\t    double frac;\n\n\t    if (paneDynSize > 0) {\n\t\tfrac = (double)paneSize / (double)paneDynSize;\n\t    } else {\n\t\tfrac = (double)paneSize / (double)pwSize;\n\t    }\n\n\t    paneDynSize -= paneSize;\n\t    paneDynMinSize -= paneMinSize;\n\t    stretchAmount = (int) (frac * stretchReserve);\n\t    if (paneSize + stretchAmount >= paneMinSize) {\n\t\tstretchReserve -= stretchAmount;\n\t\tpaneSize += stretchAmount;\n\t    } else {\n\t\tstretchReserve += paneSize - paneMinSize;\n\t\tpaneSize = paneMinSize;\n\t    }\n\t    if (i == last && stretchReserve > 0) {\n\t\tpaneSize += stretchReserve;\n\t\tstretchReserve = 0;\n\t    }\n\t} else if (paneDynSize - paneDynMinSize + stretchReserve < 0) {\n\t    if (paneSize + paneDynSize - paneDynMinSize + stretchReserve\n\t\t    <= paneMinSize) {\n\t\tstretchReserve += paneSize - paneMinSize;\n\t\tpaneSize = paneMinSize;\n\t    } else {\n\t\tpaneSize += paneDynSize - paneDynMinSize + stretchReserve;\n\t\tstretchReserve = paneDynMinSize - paneDynSize;\n\t    }\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padXObj, &padX);\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padYObj, &padY);\n\tif (horizontal) {\n\t    paneWidth = paneSize;\n\t    paneHeight = pwHeight - (2 * padY);\n\t} else {\n\t    paneWidth = pwWidth - (2 * padX);\n\t    paneHeight = paneSize;\n\t}\n\n\t/*\n\t * Adjust for area reserved for sashes.\n\t */\n\n\tif (sashCount) {\n\t    sashReserve = sashWidth * sashCount;\n\t    if (horizontal) {\n\t\tsxReserve = sashReserve;\n\t\tsyReserve = 0;\n\t    } else {\n\t\tsxReserve = 0;\n\t\tsyReserve = sashReserve;\n\t    }\n\t} else {\n\t    sxReserve = syReserve = 0;\n\t}\n\n\tif (pwWidth - sxReserve < x + paneWidth - internalBW) {\n\t    paneWidth = pwWidth - sxReserve - x + internalBW;\n\t}\n\tif (pwHeight - syReserve < y + paneHeight - internalBW) {\n\t    paneHeight = pwHeight - syReserve - y + internalBW;\n\t}\n\n\tif (newPaneWidth > paneWidth) {\n\t    newPaneWidth = paneWidth;\n\t}\n\tif (newPaneHeight > paneHeight) {\n\t    newPaneHeight = paneHeight;\n\t}\n\n\tpanePtr->x = x;\n\tpanePtr->y = y;\n\n\t/*\n\t * Compute the location of the sash at the right or bottom of the\n\t * parcel and the location of the next parcel.\n\t */\n\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handlePadObj, &handlePad);\n\tif (horizontal) {\n\t    x += paneWidth + (2 * padX);\n\t    if (x < internalBW) {\n\t\tx = internalBW;\n\t    }\n\t    panePtr->sashx = x + sashOffset;\n\t    panePtr->sashy = y;\n\t    panePtr->handlex = x + handleOffset;\n\t    panePtr->handley = y + handlePad;\n\t    x += sashWidth;\n\t} else {\n\t    y += paneHeight + (2 * padY);\n\t    if (y < internalBW) {\n\t\ty = internalBW;\n\t    }\n\t    panePtr->sashx = x;\n\t    panePtr->sashy = y + sashOffset;\n\t    panePtr->handlex = x + handlePad;\n\t    panePtr->handley = y + handleOffset;\n\t    y += sashWidth;\n\t}\n\n\t/*\n\t * Compute the actual dimensions of the pane in the pane.\n\t */\n\n\tpaneX = panePtr->x;\n\tpaneY = panePtr->y;\n\tAdjustForSticky(panePtr->sticky, paneWidth, paneHeight,\n\t\t&paneX, &paneY, &newPaneWidth, &newPaneHeight);\n\n\tpaneX += padX;\n\tpaneY += padY;\n\n\t/*\n\t * Now put the window in the proper spot.\n\t */\n\n\tif (newPaneWidth <= 0 || newPaneHeight <= 0 ||\n\t\t(horizontal ? paneX - internalBW > pwWidth :\n\t\tpaneY - internalBW > pwHeight)) {\n\t    Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);\n\t    Tk_UnmapWindow(panePtr->tkwin);\n\t} else {\n\t    Tk_MaintainGeometry(panePtr->tkwin, pwPtr->tkwin,\n\t\t    paneX, paneY, newPaneWidth, newPaneHeight);\n\t}\n\tsashCount--;\n    }\n    Tcl_Release(pwPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Unlink --\n *\n *\tRemove a pane from a paned window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe paned window will be scheduled for re-arranging and redrawing.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnlink(\n    Pane *panePtr)\t\t/* Window to unlink. */\n{\n    PanedWindow *containerPtr;\n    Tcl_Size i, j;\n\n    containerPtr = panePtr->containerPtr;\n    if (containerPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Find the specified pane in the panedwindow's list of panes, then\n     * remove it from that list.\n     */\n\n    for (i = 0; i < containerPtr->numPanes; i++) {\n\tif (containerPtr->panes[i] == panePtr) {\n\t    for (j = i; j < containerPtr->numPanes - 1; j++) {\n\t\tcontainerPtr->panes[j] = containerPtr->panes[j + 1];\n\t    }\n\t    break;\n\t}\n    }\n\n    /*\n     * Clean out any -after or -before references to this pane\n     */\n\n    for (i = 0; i < containerPtr->numPanes; i++) {\n\tif (containerPtr->panes[i]->before == panePtr->tkwin) {\n\t    containerPtr->panes[i]->before = NULL;\n\t}\n\tif (containerPtr->panes[i]->after == panePtr->tkwin) {\n\t    containerPtr->panes[i]->after = NULL;\n\t}\n    }\n\n    containerPtr->flags |= REQUESTED_RELAYOUT;\n    if (!(containerPtr->flags & REDRAW_PENDING)) {\n\tcontainerPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayPanedWindow, containerPtr);\n    }\n\n    /*\n     * Set the pane's containerPtr to NULL, so that we can tell that the pane\n     * is no longer attached to any panedwindow.\n     */\n\n    panePtr->containerPtr = NULL;\n\n    containerPtr->numPanes--;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetPane --\n *\n *\tGiven a token to a Tk window, find the pane that corresponds to that\n *\ttoken in a given paned window.\n *\n * Results:\n *\tPointer to the pane structure, or NULL if the window is not managed\n *\tby this paned window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Pane *\nGetPane(\n    PanedWindow *pwPtr,\t\t/* Pointer to the paned window info. */\n    Tk_Window tkwin)\t\t/* Window to search for. */\n{\n    Tcl_Size i;\n\n    for (i = 0; i < pwPtr->numPanes; i++) {\n\tif (pwPtr->panes[i]->tkwin == tkwin) {\n\t    return pwPtr->panes[i];\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetFirstLastVisiblePane --\n *\n *\tGiven panedwindow, find the index of the first and last visible panes\n *\tof that paned window.\n *\n * Results:\n *\tIndex of the first and last visible panes.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetFirstLastVisiblePane(\n    PanedWindow *pwPtr,\t\t/* Pointer to the paned window info. */\n    int *firstPtr,\t\t/* Returned index for first. */\n    int *lastPtr)\t\t/* Returned index for last. */\n{\n    Tcl_Size i;\n\n    for (i = 0, *lastPtr = 0, *firstPtr = -1; i < pwPtr->numPanes; i++) {\n\tif (pwPtr->panes[i]->hide == 0) {\n\t    if (*firstPtr < 0) {\n\t\t*firstPtr = i;\n\t    }\n\t    *lastPtr = i;\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PaneStructureProc --\n *\n *\tThis function is invoked whenever StructureNotify events occur for a\n *\twindow that's managed by a paned window. This function's only purpose\n *\tis to clean up when windows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe paned window pane structure associated with the window\n *\tis freed, and the pane is disassociated from the paned\n *\twindow which managed it.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPaneStructureProc(\n    void *clientData,\t/* Pointer to record describing window item. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Pane *panePtr = (Pane *)clientData;\n    PanedWindow *pwPtr = panePtr->containerPtr;\n\n    if (eventPtr->type == DestroyNotify) {\n\tUnlink(panePtr);\n\tpanePtr->tkwin = NULL;\n\tTcl_Free(panePtr);\n\tComputeGeometry(pwPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeGeometry --\n *\n *\tCompute geometry for the paned window, including coordinates of all\n *\tpanes and each sash.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRecomputes geometry information for a paned window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nComputeGeometry(\n    PanedWindow *pwPtr)\t\t/* Pointer to the Paned Window structure. */\n{\n    int x, y, doubleBw, internalBw;\n    int sashWidth, sashOffset, handleOffset;\n    int reqWidth, reqHeight, dim, handleSize;\n    Pane *panePtr;\n    const bool horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);\n    int sashPad;\n    int width = -1, height = -1;\n    Tcl_Size i;\n\n    pwPtr->flags |= REQUESTED_RELAYOUT;\n\n    x = y = internalBw = Tk_InternalBorderLeft(pwPtr->tkwin);\n    reqWidth = reqHeight = 0;\n\n    /*\n     * Sashes and handles share space on the display. To simplify processing\n     * below, precompute the x and y offsets of the handles and sashes within\n     * the space occupied by their combination; later, just add those offsets\n     * blindly (avoiding the extra showHandle, etc, checks).\n     */\n\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashPadObj, &sashPad);\n    sashOffset = handleOffset = sashPad;\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashWidthObj, &sashWidth);\n    if (pwPtr->showHandle && handleSize > sashWidth) {\n\tsashOffset = ((handleSize - sashWidth) / 2) + sashPad;\n\tsashWidth = (2 * sashPad) + handleSize;\n    } else {\n\thandleOffset = ((sashWidth - handleSize) / 2) + sashPad;\n\tsashWidth = (2 * sashPad) + sashWidth;\n    }\n\n    for (i = 0; i < pwPtr->numPanes; i++) {\n\tint padX, padY, minSize, handlePad;\n\tpanePtr = pwPtr->panes[i];\n\n\tif (panePtr->hide) {\n\t    continue;\n\t}\n\n\t/*\n\t * First set the coordinates for the top left corner of the pane's\n\t * parcel.\n\t */\n\n\tpanePtr->x = x;\n\tpanePtr->y = y;\n\n\t/*\n\t * Make sure the pane's paned dimension is at least minsize. This\n\t * check may be redundant, since the only way to change a pane's size\n\t * is by moving a sash, and that code checks the minsize.\n\t */\n\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &minSize);\n\tif (horizontal) {\n\t    if (panePtr->paneWidth < minSize) {\n\t\tpanePtr->paneWidth = minSize;\n\t    }\n\t} else {\n\t    if (panePtr->paneHeight < minSize) {\n\t\tpanePtr->paneHeight = minSize;\n\t    }\n\t}\n\n\t/*\n\t * Compute the location of the sash at the right or bottom of the\n\t * parcel.\n\t */\n\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padXObj, &padX);\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padYObj, &padY);\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handlePadObj, &handlePad);\n\tif (horizontal) {\n\t    x += panePtr->paneWidth + (2 * padX);\n\t    panePtr->sashx = x + sashOffset;\n\t    panePtr->sashy = y;\n\t    panePtr->handlex = x + handleOffset;\n\t    panePtr->handley = y + handlePad;\n\t    x += sashWidth;\n\t} else {\n\t    y += panePtr->paneHeight + (2 * padY);\n\t    panePtr->sashx = x;\n\t    panePtr->sashy = y + sashOffset;\n\t    panePtr->handlex = x + handlePad;\n\t    panePtr->handley = y + handleOffset;\n\t    y += sashWidth;\n\t}\n\n\t/*\n\t * Find the maximum height/width of the panes, for computing the\n\t * requested height/width of the paned window.\n\t */\n\n\tif (horizontal) {\n\t    /*\n\t     * If the pane has an explicit height set, use that; otherwise,\n\t     * use the pane's requested height.\n\t     */\n\n\t    if (panePtr->height > 0) {\n\t\tdim = panePtr->height;\n\t    } else {\n\t\tdoubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;\n\t\tdim = Tk_ReqHeight(panePtr->tkwin) + doubleBw;\n\t    }\n\t    dim += 2 * padY;\n\t    if (dim > reqHeight) {\n\t\treqHeight = dim;\n\t    }\n\t} else {\n\t    /*\n\t     * If the pane has an explicit width set use that; otherwise, use\n\t     * the pane's requested width.\n\t     */\n\n\t    if (panePtr->width > 0) {\n\t\tdim = panePtr->width;\n\t    } else {\n\t\tdoubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;\n\t\tdim = Tk_ReqWidth(panePtr->tkwin) + doubleBw;\n\t    }\n\t    dim += 2 * padX;\n\t    if (dim > reqWidth) {\n\t\treqWidth = dim;\n\t    }\n\t}\n    }\n\n    /*\n     * The loop above should have left x (or y) equal to the sum of the widths\n     * (or heights) of the widgets, plus the size of one sash and the sash\n     * padding for each widget, plus the width of the left (or top) border of\n     * the paned window.\n     *\n     * The requested width (or height) is therefore x (or y) minus the size of\n     * one sash and padding, plus the width of the right (or bottom) border of\n     * the paned window.\n     *\n     * The height (or width) is equal to the maximum height (or width) of the\n     * panes, plus the width of the border of the top and bottom (or left and\n     * right) of the paned window.\n     *\n     * If the panedwindow has an explicit width/height set use that;\n     * otherwise, use the requested width/height.\n     */\n\n    if (pwPtr->widthObj) {\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->widthObj, &width);\n    }\n    if (pwPtr->heightObj) {\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->heightObj, &height);\n    }\n    if (horizontal) {\n\treqWidth = (width > 0 ?\n\t\twidth : x - sashWidth + internalBw);\n\treqHeight = (height > 0 ?\n\t\theight : reqHeight + (2 * internalBw));\n    } else {\n\treqWidth = (width > 0 ?\n\t\twidth : reqWidth + (2 * internalBw));\n\treqHeight = (height > 0 ?\n\t\theight : y - sashWidth + internalBw);\n    }\n    Tk_GeometryRequest(pwPtr->tkwin, reqWidth, reqHeight);\n    if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {\n\tpwPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayPanedWindow, pwPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyOptionTables --\n *\n *\tThis function is registered as an exit callback when the paned window\n *\tcommand is first called. It cleans up the OptionTables structure\n *\tallocated by that command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees memory.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyOptionTables(\n    void *clientData,\t/* Pointer to the OptionTables struct */\n    TCL_UNUSED(Tcl_Interp *))\t\t/* Pointer to the calling interp */\n{\n    Tcl_Free(clientData);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetSticky -\n *\n *\tConverts an internal boolean combination of \"sticky\" bits into a Tcl\n *\tstring obj containing zero or more of n, s, e, or w.\n *\n * Results:\n *\tTcl_Obj containing the string representation of the sticky value.\n *\n * Side effects:\n *\tCreates a new Tcl_Obj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetSticky(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *recordPtr,\t\t/* Pointer to widget record. */\n    Tcl_Size internalOffset)\t\t/* Offset within *recordPtr containing the\n\t\t\t\t * sticky value. */\n{\n    int sticky = *(int *)(recordPtr + internalOffset);\n    char buffer[5];\n    char *p = &buffer[0];\n\n    if (sticky & STICK_NORTH) {\n\t*p++ = 'n';\n    }\n    if (sticky & STICK_EAST) {\n\t*p++ = 'e';\n    }\n    if (sticky & STICK_SOUTH) {\n\t*p++ = 's';\n    }\n    if (sticky & STICK_WEST) {\n\t*p++ = 'w';\n    }\n    *p = '\\0';\n\n    return Tcl_NewStringObj(buffer, TCL_INDEX_NONE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetSticky --\n *\n *\tConverts a Tcl_Obj representing a widgets stickyness into an integer\n *\tvalue.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay store the integer value into the internal representation pointer.\n *\tMay change the pointer to the Tcl_Obj to NULL to indicate that the\n *\tspecified string was empty and that is acceptable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetSticky(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interp; may be used for errors. */\n    TCL_UNUSED(Tk_Window),\t/* Window for which option is being set. */\n    Tcl_Obj **value,\t\t/* Pointer to the pointer to the value object.\n\t\t\t\t * We use a pointer to the pointer because we\n\t\t\t\t * may need to return a value (NULL). */\n    char *recordPtr,\t\t/* Pointer to storage for the widget record. */\n    Tcl_Size internalOffset,\t\t/* Offset within *recordPtr at which the\n\t\t\t\t * internal value is to be stored. */\n    char *oldInternalPtr,\t/* Pointer to storage for the old value. */\n    int flags)\t\t\t/* Flags for the option, set Tk_SetOptions. */\n{\n    int sticky = 0;\n    char c;\n    void *internalPtr;\n    const char *string;\n\n    internalPtr = ComputeSlotAddress(recordPtr, internalOffset);\n\n    if ((flags & TK_OPTION_NULL_OK) && TkObjIsEmpty(*value)) {\n\t*value = NULL;\n    } else {\n\t/*\n\t * Convert the sticky specifier into an integer value.\n\t */\n\n\tstring = Tcl_GetString(*value);\n\n\twhile ((c = *string++) != '\\0') {\n\t    switch (c) {\n\t    case 'n': case 'N':\n\t\tsticky |= STICK_NORTH;\n\t\tbreak;\n\t    case 'e': case 'E':\n\t\tsticky |= STICK_EAST;\n\t\tbreak;\n\t    case 's': case 'S':\n\t\tsticky |= STICK_SOUTH;\n\t\tbreak;\n\t    case 'w': case 'W':\n\t\tsticky |= STICK_WEST;\n\t\tbreak;\n\t    case ' ': case ',': case '\\t': case '\\r': case '\\n':\n\t\tbreak;\n\t    default:\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"bad stickyness value \\\"%s\\\": must be a string\"\n\t\t\t\" containing zero or more of n, e, s, and w\",\n\t\t\tTcl_GetString(*value)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"STICKY\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n\n    if (internalPtr != NULL) {\n\t*((int *) oldInternalPtr) = *((int *) internalPtr);\n\t*((int *) internalPtr) = sticky;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RestoreSticky --\n *\n *\tRestore a sticky option value from a saved value.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the old value.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRestoreSticky(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *internalPtr,\t\t/* Pointer to storage for value. */\n    char *oldInternalPtr)\t/* Pointer to old value. */\n{\n    *(int *)internalPtr = *(int *)oldInternalPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustForSticky --\n *\n *\tGiven the x,y coords of the top-left corner of a pane, the dimensions\n *\tof that pane, and the dimensions of a pane, compute the x,y coords\n *\tand actual dimensions of the pane based on the pane's sticky value.\n *\n * Results:\n *\tNo direct return; sets the x, y, paneWidth and paneHeight to correct\n *\tvalues.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAdjustForSticky(\n    int sticky,\t\t\t/* Sticky value; see top of file for\n\t\t\t\t * definition. */\n    int cavityWidth,\t\t/* Width of the cavity. */\n    int cavityHeight,\t\t/* Height of the cavity. */\n    int *xPtr, int *yPtr,\t/* Initially, coordinates of the top-left\n\t\t\t\t * corner of cavity; also return values for\n\t\t\t\t * actual x, y coords of pane. */\n    int *paneWidthPtr,\t\t/* Pane width. */\n    int *paneHeightPtr)\t/* Pane height. */\n{\n    int diffx = 0;\t\t/* Cavity width - pane width. */\n    int diffy = 0;\t\t/* Cavity hight - pane height. */\n\n    if (cavityWidth > *paneWidthPtr) {\n\tdiffx = cavityWidth - *paneWidthPtr;\n    }\n\n    if (cavityHeight > *paneHeightPtr) {\n\tdiffy = cavityHeight - *paneHeightPtr;\n    }\n\n    if ((sticky & STICK_EAST) && (sticky & STICK_WEST)) {\n\t*paneWidthPtr += diffx;\n    }\n    if ((sticky & STICK_NORTH) && (sticky & STICK_SOUTH)) {\n\t*paneHeightPtr += diffy;\n    }\n    if (!(sticky & STICK_WEST)) {\n\t*xPtr += (sticky & STICK_EAST) ? diffx : diffx/2;\n    }\n    if (!(sticky & STICK_NORTH)) {\n\t*yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MoveSash --\n *\n *\tMove the sash given by index the amount given.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRecomputes the sizes of the panes in a panedwindow.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMoveSash(\n    PanedWindow *pwPtr,\n    int sash,\n    int diff)\n{\n    Tcl_Size i;\n    int expandPane, reduceFirst, reduceLast, reduceIncr, paneSize, sashOffset;\n    Pane *panePtr;\n    int stretchReserve = 0;\n    int nextSash = sash + 1;\n    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);\n    int handleSize, sashPad, sashWidth;\n\n    if (diff == 0)\n\treturn;\n\n    /*\n     * Update the pane sizes with their real sizes.\n     */\n\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashPadObj, &sashPad);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashWidthObj, &sashWidth);\n    if (pwPtr->showHandle && handleSize > sashWidth) {\n\tsashOffset = ((handleSize - sashWidth) / 2) + sashPad;\n    } else {\n\tsashOffset = sashPad;\n    }\n    for (i = 0; i < pwPtr->numPanes; i++) {\n\tint padX, padY;\n\n\tpanePtr = pwPtr->panes[i];\n\tif (panePtr->hide) {\n\t    continue;\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padXObj, &padX);\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->padYObj, &padY);\n\tif (horizontal) {\n\t    panePtr->paneWidth = panePtr->width = panePtr->sashx\n\t\t    - sashOffset - panePtr->x - (2 * padX);\n\t} else {\n\t    panePtr->paneHeight = panePtr->height = panePtr->sashy\n\t\t    - sashOffset - panePtr->y - (2 * padY);\n\t}\n    }\n\n    /*\n     * There must be a next sash since it is only possible to enter this\n     * routine when moving an actual sash which implies there exists a visible\n     * pane to either side of the sash.\n     */\n\n    while (nextSash < pwPtr->numPanes-1 && pwPtr->panes[nextSash]->hide) {\n\tnextSash++;\n    }\n\n    /*\n     * Consolidate +/-diff variables to reduce duplicate code.\n     */\n\n    if (diff > 0) {\n\texpandPane = sash;\n\treduceFirst = nextSash;\n\treduceLast = pwPtr->numPanes;\n\treduceIncr = 1;\n    } else {\n\tdiff = abs(diff);\n\texpandPane = nextSash;\n\treduceFirst = sash;\n\treduceLast = -1;\n\treduceIncr = -1;\n    }\n\n    /*\n     * Calculate how much room we have to stretch in and adjust diff value\n     * accordingly.\n     */\n    for (i = reduceFirst; i != reduceLast; i += reduceIncr) {\n\tint minSize;\n\n\tpanePtr = pwPtr->panes[i];\n\tif (panePtr->hide) {\n\t    continue;\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &minSize);\n\tif (horizontal) {\n\t    stretchReserve += panePtr->width - minSize;\n\t} else {\n\t    stretchReserve += panePtr->height - minSize;\n\t}\n    }\n    if (stretchReserve <= 0) {\n\treturn;\n    }\n    if (diff > stretchReserve) {\n\tdiff = stretchReserve;\n    }\n\n    /*\n     * Expand pane by diff amount.\n     */\n\n    panePtr = pwPtr->panes[expandPane];\n    if (horizontal) {\n\tpanePtr->paneWidth = panePtr->width += diff;\n    } else {\n\tpanePtr->paneHeight = panePtr->height += diff;\n    }\n\n    /*\n     * Reduce panes, respecting minsize, until diff amount has been used.\n     */\n\n    for (i = reduceFirst; i != reduceLast; i += reduceIncr) {\n\tint minSize;\n\n\tpanePtr = pwPtr->panes[i];\n\tif (panePtr->hide) {\n\t    continue;\n\t}\n\tif (horizontal) {\n\t    paneSize = panePtr->width;\n\t} else {\n\t    paneSize = panePtr->height;\n\t}\n\tTk_GetPixelsFromObj(NULL, panePtr->tkwin, panePtr->minSizeObj, &minSize);\n\tif (diff > (paneSize - minSize)) {\n\t    diff -= paneSize - minSize;\n\t    paneSize = minSize;\n\t} else {\n\t    paneSize -= diff;\n\t    i = reduceLast - reduceIncr;\n\t}\n\tif (horizontal) {\n\t    panePtr->paneWidth = panePtr->width = paneSize;\n\t} else {\n\t    panePtr->paneHeight = panePtr->height = paneSize;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ProxyWindowEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tpaned window proxy windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nProxyWindowEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n\n    if (eventPtr->type == Expose) {\n\tif (pwPtr->proxywin != NULL &&!(pwPtr->flags & PROXY_REDRAW_PENDING)) {\n\t    Tcl_DoWhenIdle(DisplayProxyWindow, pwPtr);\n\t    pwPtr->flags |= PROXY_REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayProxyWindow --\n *\n *\tThis function redraws a paned window proxy window. It is invoked as a\n *\tdo-when-idle handler, so it only runs when there's nothing else for\n *\tthe application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayProxyWindow(\n    void *clientData)\t/* Information about window. */\n{\n    PanedWindow *pwPtr = (PanedWindow *)clientData;\n    Pixmap pixmap;\n    Tk_Window tkwin = pwPtr->proxywin;\n    int proxyBorderWidth;\n\n    pwPtr->flags &= ~PROXY_REDRAW_PENDING;\n    if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Create a pixmap for double-buffering, if necessary.\n     */\n\n    pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n    /*\n     * Redraw the widget's background and border.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, pwPtr->proxyBorderWidthObj, &proxyBorderWidth);\n    Tk_Fill3DRectangle(tkwin, pixmap,\n\t    pwPtr->proxyBackground ? pwPtr->proxyBackground : pwPtr->background,\n\t    0, 0, Tk_Width(tkwin), Tk_Height(tkwin), proxyBorderWidth,\n\t    (pwPtr->proxyRelief != TK_RELIEF_NULL) ? pwPtr->proxyRelief : pwPtr->sashRelief);\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Copy the pixmap to the display.\n     */\n\n    XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0,\n\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(Tk_Display(tkwin), pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PanedWindowProxyCommand --\n *\n *\tHandles the panedwindow proxy subcommand. See the user documentation\n *\tfor details.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay map or unmap the proxy sash.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPanedWindowProxyCommand(\n    PanedWindow *pwPtr,\t\t/* Pointer to paned window information. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const optionStrings[] = {\n\t\"coord\", \"forget\", \"place\", NULL\n    };\n    enum options {\n\tPROXY_COORD, PROXY_FORGET, PROXY_PLACE\n    };\n    int index, x, y, sashWidth, sashHeight;\n    int internalBW, pwWidth, pwHeight;\n    Tcl_Obj *coords[2];\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case PROXY_COORD:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tcoords[0] = Tcl_NewWideIntObj(pwPtr->proxyx);\n\tcoords[1] = Tcl_NewWideIntObj(pwPtr->proxyy);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, coords));\n\tbreak;\n\n    case PROXY_FORGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (Tk_IsMapped(pwPtr->proxywin)) {\n\t    Tk_UnmapWindow(pwPtr->proxywin);\n\t    Tk_UnmaintainGeometry(pwPtr->proxywin, pwPtr->tkwin);\n\t}\n\tbreak;\n\n    case PROXY_PLACE:\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"x y\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tinternalBW = Tk_InternalBorderLeft(pwPtr->tkwin);\n\tTk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashWidthObj, &sashWidth);\n\tif (pwPtr->orient == ORIENT_HORIZONTAL) {\n\t    if (x < 0) {\n\t\tx = 0;\n\t    }\n\t    pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);\n\t    if (x > pwWidth) {\n\t\tx = pwWidth;\n\t    }\n\t    y = Tk_InternalBorderLeft(pwPtr->tkwin);\n\t    sashHeight = Tk_Height(pwPtr->tkwin) -\n\t\t    (2 * Tk_InternalBorderLeft(pwPtr->tkwin));\n\t} else {\n\t    if (y < 0) {\n\t\ty = 0;\n\t    }\n\t    pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);\n\t    if (y > pwHeight) {\n\t\ty = pwHeight;\n\t    }\n\t    x = Tk_InternalBorderLeft(pwPtr->tkwin);\n\t    sashHeight = sashWidth;\n\t    sashWidth = Tk_Width(pwPtr->tkwin) -\n\t\t    (2 * Tk_InternalBorderLeft(pwPtr->tkwin));\n\t}\n\n\tif (sashWidth < 1) {\n\t    sashWidth = 1;\n\t}\n\tif (sashHeight < 1) {\n\t    sashHeight = 1;\n\t}\n\n\t/*\n\t * Stash the proxy coordinates for future \"proxy coord\" calls.\n\t */\n\n\tpwPtr->proxyx = x;\n\tpwPtr->proxyy = y;\n\n\t/*\n\t * Make sure the proxy window is higher in the stacking order than the\n\t * panes, so that it will be visible when drawn. It would be more\n\t * correct to push the proxy window just high enough to appear above\n\t * the highest pane, but it's much easier to just force it all the\n\t * way to the top of the stacking order.\n\t */\n\n\tTk_RestackWindow(pwPtr->proxywin, Above, NULL);\n\n\t/*\n\t * Let Tk_MaintainGeometry take care of placing the window at the\n\t * right coordinates.\n\t */\n\n\tTk_MaintainGeometry(pwPtr->proxywin, pwPtr->tkwin, x, y,\n\t\tsashWidth, sashHeight);\n\tbreak;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeInternalPointer --\n *\n *\tGiven a pointer to the start of a record and the offset of a slot\n *\twithin that record, compute the address of that slot.\n *\n * Results:\n *\tIf offset is non-negative, returns the computed address; else, returns\n *\tNULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void *\nComputeSlotAddress(\n    void *recordPtr,\t/* Pointer to the start of a record. */\n    Tcl_Size offset)\t\t/* Offset of a slot within that record; may be TCL_INDEX_NONE. */\n{\n    if (offset != TCL_INDEX_NONE) {\n\treturn (char *)recordPtr + offset;\n    } else {\n\treturn NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PanedWindowIdentifyCoords --\n *\n *\tGiven a pair of x,y coordinates, identify the panedwindow component at\n *\tthat point, if any.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tModifies the interpreter's result to contain either an empty list, or\n *\ta two element list of the form {sash n} or {handle n} to indicate that\n *\tthe point lies within the n'th sash or handle.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPanedWindowIdentifyCoords(\n    PanedWindow *pwPtr,\t\t/* Information about the widget. */\n    Tcl_Interp *interp,\t\t/* Interpreter in which to store result. */\n    int x, int y)\t\t/* Coordinates of the point to identify. */\n{\n    int sashHeight, sashWidth, thisx, thisy;\n    int found, lpad, rpad, tpad, bpad;\n    int first, last, handleSize, sashPad;\n    bool isHandle;\n    Tcl_Size i;\n\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashPadObj, &sashPad);\n    Tk_GetPixelsFromObj(NULL, pwPtr->tkwin, pwPtr->sashWidthObj, &sashWidth);\n    if (pwPtr->orient == ORIENT_HORIZONTAL) {\n\tif (Tk_IsMapped(pwPtr->tkwin)) {\n\t    sashHeight = Tk_Height(pwPtr->tkwin);\n\t} else {\n\t    sashHeight = Tk_ReqHeight(pwPtr->tkwin);\n\t}\n\tsashHeight -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin);\n\tif (pwPtr->showHandle && handleSize > sashWidth) {\n\t    lpad = (handleSize - sashWidth) / 2;\n\t    rpad = handleSize - lpad;\n\t    lpad += sashPad;\n\t    rpad += sashPad;\n\t    sashWidth = handleSize;\n\t} else {\n\t    lpad = rpad = sashPad;\n\t}\n\ttpad = bpad = 0;\n    } else {\n\tif (pwPtr->showHandle && handleSize > sashWidth) {\n\t    sashHeight = handleSize;\n\t    tpad = (handleSize - sashWidth) / 2;\n\t    bpad = handleSize - tpad;\n\t    tpad += sashPad;\n\t    bpad += sashPad;\n\t} else {\n\t    sashHeight = sashWidth;\n\t    tpad = bpad = sashPad;\n\t}\n\tif (Tk_IsMapped(pwPtr->tkwin)) {\n\t    sashWidth = Tk_Width(pwPtr->tkwin);\n\t} else {\n\t    sashWidth = Tk_ReqWidth(pwPtr->tkwin);\n\t}\n\tsashWidth -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin);\n\tlpad = rpad = 0;\n    }\n\n    GetFirstLastVisiblePane(pwPtr, &first, &last);\n    isHandle = false;\n    found = -1;\n    for (i = 0; i < pwPtr->numPanes - 1; i++) {\n\tif (pwPtr->panes[i]->hide || i == last) {\n\t    continue;\n\t}\n\tthisx = pwPtr->panes[i]->sashx;\n\tthisy = pwPtr->panes[i]->sashy;\n\n\tif (((thisx - lpad) <= x && x <= (thisx + rpad + sashWidth)) &&\n\t\t((thisy - tpad) <= y && y <= (thisy + bpad + sashHeight))) {\n\t    found = i;\n\n\t    /*\n\t     * Determine if the point is over the handle or the sash.\n\t     */\n\n\t    if (pwPtr->showHandle) {\n\t\tthisx = pwPtr->panes[i]->handlex;\n\t\tthisy = pwPtr->panes[i]->handley;\n\t\tif (pwPtr->orient == ORIENT_HORIZONTAL) {\n\t\t    if (thisy <= y && y <= (thisy + handleSize)) {\n\t\t\tisHandle = true;\n\t\t    }\n\t\t} else {\n\t\t    if (thisx <= x && x <= (thisx + handleSize)) {\n\t\t\tisHandle = true;\n\t\t    }\n\t\t}\n\t    }\n\t    break;\n\t}\n    }\n\n    /*\n     * Set results. Note that the empty string is the default (this function\n     * is called inside the implementation of a command).\n     */\n\n    if (found != -1) {\n\tTcl_Obj *list[2];\n\n\tlist[0] = Tcl_NewWideIntObj(found);\n\tlist[1] = Tcl_NewStringObj((isHandle ? \"handle\" : \"sash\"), TCL_INDEX_NONE);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, list));\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPkgConfig.c",
    "content": "/*\n * tkPkgConfig.c --\n *\n *\tThis file contains the configuration information to embed into the tcl\n *\tbinary library.\n *\n * Copyright © 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>\n * Copyright © 2017 Stuart Cassoff <stwo@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/* Note, the definitions in this module are influenced by the following C\n * preprocessor macros:\n *\n * - _WIN32 || __CYGWIN__\tThe value for the fontsytem key will be\n *   MAC_OSX_TK\t\t\tchosen based on these macros/defines.\n *   HAVE_XFT\t\t\tdeclares that xft font support was requested.\n *\n * - CFG_RUNTIME_*\t\tPaths to various stuff at runtime.\n * - CFG_INSTALL_*\t\tPaths to various stuff at installation time.\n *\n * - TCL_CFGVAL_ENCODING\tstring containing the encoding used for the\n *\t\t\t\tconfiguration values.\n */\n\n#include \"tkInt.h\"\n\f\n\n#ifndef TCL_CFGVAL_ENCODING\n#define TCL_CFGVAL_ENCODING \"utf-8\"\n#endif\n\n/*\n * Use C preprocessor statements to define the various values for the embedded\n * configuration information.\n */\n\n#if defined(_WIN32)\n#  define CFG_FONTSYSTEM\t\"gdi\"\n#elif defined(MAC_OSX_TK)\n#  define CFG_FONTSYSTEM\t\"cocoa\"\n#elif defined(HAVE_XFT)\n#  define CFG_FONTSYSTEM\t\"xft\"\n#elif defined(HAVE_BIDI)\t\n#  define CFG_FONTSYSTEM\t\"xft\"\n#else\n#  define CFG_FONTSYSTEM\t\"x11\"\n#endif\n\n/*\n  The macOS framework build first installs the framework in the build\n  directory and then copies it to /Library/Frameworks/Tk.framework.\n  Without these macros the pkgconfig paths point into the build\n  directory instead of into the installed framework.\n*/\n\n#if defined(MAC_OSX_TK) && defined(TK_FRAMEWORK)\n  #undef CFG_INSTALL_LIBDIR\n  #undef CFG_RUNTIME_LIBDIR\n  #undef CFG_INSTALL_BINDIR\n  #undef CFG_RUNTIME_BINDIR\n  #undef CFG_INSTALL_DOCDIR\n  #undef CFG_RUNTIME_DOCDIR\n  #undef CFG_INSTALL_SCRDIR\n  #undef CFG_RUNTIME_SCRDIR\n  #undef CFG_INSTALL_INCDIR\n  #undef CFG_RUNTIME_INCDIR\n  #undef CFG_INSTALL_DEMODIR\n  #undef CFG_RUNTIME_DEMODIR\n  #define VERSION_DIR \"/Library/Frameworks/Tk.framework/Versions/\"TK_VERSION\n  #define CFG_INSTALL_LIBDIR VERSION_DIR\n  #define CFG_RUNTIME_LIBDIR CFG_INSTALL_LIBDIR\n  #define CFG_INSTALL_BINDIR VERSION_DIR\n  #define CFG_RUNTIME_BINDIR CFG_INSTALL_BINDIR\n  #define CFG_INSTALL_DOCDIR VERSION_DIR \"/Resources/Documentation\"\n  #define CFG_RUNTIME_DOCDIR CFG_INSTALL_DOCDIR\n  #define CFG_INSTALL_SCRDIR VERSION_DIR \"/Resources/Scripts\"\n  #define CFG_RUNTIME_SCRDIR CFG_INSTALL_SCRDIR\n  #define CFG_INSTALL_INCDIR VERSION_DIR \"/Headers\"\n  #define CFG_RUNTIME_INCDIR CFG_INSTALL_INCDIR\n  #define CFG_INSTALL_DEMODIR VERSION_DIR \"/Resources/Scripts/demos\"\n  #define CFG_RUNTIME_DEMODIR CFG_INSTALL_DEMODIR\n#endif\n\nstatic const Tcl_Config cfg[] = {\n    {\"fontsystem\",\t\tCFG_FONTSYSTEM},\n\n    /* Runtime paths to various stuff */\n\n#ifdef CFG_RUNTIME_LIBDIR\n    {\"libdir,runtime\",\t\tCFG_RUNTIME_LIBDIR},\n#endif\n#ifdef CFG_RUNTIME_BINDIR\n    {\"bindir,runtime\",\t\tCFG_RUNTIME_BINDIR},\n#endif\n#ifdef CFG_RUNTIME_SCRDIR\n    {\"scriptdir,runtime\",\tCFG_RUNTIME_SCRDIR},\n#endif\n#ifdef CFG_RUNTIME_INCDIR\n    {\"includedir,runtime\",\tCFG_RUNTIME_INCDIR},\n#endif\n#ifdef CFG_RUNTIME_DOCDIR\n    {\"docdir,runtime\",\t\tCFG_RUNTIME_DOCDIR},\n#endif\n#ifdef CFG_RUNTIME_DEMODIR\n    {\"demodir,runtime\",\t\tCFG_RUNTIME_DEMODIR},\n#endif\n#if !defined(STATIC_BUILD) && defined(CFG_RUNTIME_DLLFILE)\n    {\"dllfile,runtime\",\t\tCFG_RUNTIME_DLLFILE},\n#endif\n\n    /* Installation paths to various stuff */\n\n#ifdef CFG_INSTALL_LIBDIR\n    {\"libdir,install\",\t\tCFG_INSTALL_LIBDIR},\n#endif\n#ifdef CFG_INSTALL_BINDIR\n    {\"bindir,install\",\t\tCFG_INSTALL_BINDIR},\n#endif\n#ifdef CFG_INSTALL_SCRDIR\n    {\"scriptdir,install\",\tCFG_INSTALL_SCRDIR},\n#endif\n#ifdef CFG_INSTALL_INCDIR\n    {\"includedir,install\",\tCFG_INSTALL_INCDIR},\n#endif\n#ifdef CFG_INSTALL_DOCDIR\n    {\"docdir,install\",\t\tCFG_INSTALL_DOCDIR},\n#endif\n#ifdef CFG_INSTALL_DEMODIR\n    {\"demodir,install\",\t\tCFG_INSTALL_DEMODIR},\n#endif\n\n    /* Last entry, closes the array */\n    {NULL, NULL}\n};\n\f\nvoid\nTkInitEmbeddedConfigurationInformation(\n    Tcl_Interp *interp)\t\t/* Interpreter the configuration command is\n\t\t\t\t * registered in. */\n{\n    Tcl_RegisterConfig(interp, \"tk\", cfg, TCL_CFGVAL_ENCODING);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPlace.c",
    "content": "/*\n * tkPlace.c --\n *\n *\tThis file contains code to implement a simple geometry manager for Tk\n *\tbased on absolute placement or \"rubber-sheet\" placement.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Border modes for relative placement:\n *\n * BM_INSIDE:\t\trelative distances computed using area inside all\n *\t\t\tborders of container window.\n * BM_OUTSIDE:\t\trelative distances computed using outside area that\n *\t\t\tincludes all borders of container.\n * BM_IGNORE:\t\tborder issues are ignored: place relative to container's\n *\t\t\tactual window size.\n */\n\nstatic const char *const borderModeStrings[] = {\n    \"inside\", \"ignore\", \"outside\", NULL\n};\n\ntypedef enum {BM_INSIDE, BM_IGNORE, BM_OUTSIDE} BorderMode;\n\n/*\n * For each window whose geometry is managed by the placer there is a\n * structure of the following type:\n */\n\ntypedef struct Content {\n    Tk_Window tkwin;\t\t/* Tk's token for window. */\n    Tk_Window inTkwin;\t\t/* Token for the -in window. */\n    struct Container *containerPtr;\t/* Pointer to information for window relative\n\t\t\t\t * to which tkwin is placed. This isn't\n\t\t\t\t * necessarily the logical parent of tkwin.\n\t\t\t\t * NULL means the container was deleted or never\n\t\t\t\t * assigned. */\n    struct Content *nextPtr;\t/* Next in list of windows placed relative to\n\t\t\t\t * same container (NULL for end of list). */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this command. */\n    /*\n     * Geometry information for window; where there are both relative and\n     * absolute values for the same attribute (e.g. x and relX) only one of\n     * them is actually used, depending on flags.\n     */\n\n    int x, y;\t\t\t/* X and Y pixel coordinates for tkwin. */\n    Tcl_Obj *xObj, *yObj;\t/* Tcl_Obj rep's of x, y coords, to keep pixel\n\t\t\t\t * spec. information. */\n    double relX, relY;\t\t/* X and Y coordinates relative to size of\n\t\t\t\t * container. */\n    int width, height;\t\t/* Absolute dimensions for tkwin. */\n    Tcl_Obj *widthObj;\t\t/* Tcl_Obj rep of width, to keep pixel\n\t\t\t\t * spec. */\n    Tcl_Obj *heightObj;\t\t/* Tcl_Obj rep of height, to keep pixel\n\t\t\t\t * spec. */\n    double relWidth, relHeight;\t/* Dimensions for tkwin relative to size of\n\t\t\t\t * container. */\n    Tcl_Obj *relWidthObj;\n    Tcl_Obj *relHeightObj;\n    Tk_Anchor anchor;\t\t/* Which point on tkwin is placed at the given\n\t\t\t\t * position. */\n    BorderMode borderMode;\t/* How to treat borders of container window. */\n} Content;\n\n/*\n * Type masks for options:\n */\n\n#define IN_MASK\t\t1\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_ANCHOR, \"-anchor\", NULL, NULL, \"nw\", TCL_INDEX_NONE,\n\toffsetof(Content, anchor), TK_OPTION_ENUM_VAR, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-bordermode\", NULL, NULL, \"inside\", TCL_INDEX_NONE,\n\toffsetof(Content, borderMode), TK_OPTION_ENUM_VAR, borderModeStrings, 0},\n    {TK_OPTION_PIXELS, \"-height\", NULL, NULL, NULL, offsetof(Content, heightObj),\n\toffsetof(Content, height), TK_OPTION_NULL_OK|TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_WINDOW, \"-in\", NULL, NULL, \"\", TCL_INDEX_NONE, offsetof(Content, inTkwin),\n\t0, 0, IN_MASK},\n    {TK_OPTION_DOUBLE, \"-relheight\", NULL, NULL, NULL,\n\toffsetof(Content, relHeightObj), offsetof(Content, relHeight),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_DOUBLE, \"-relwidth\", NULL, NULL, NULL,\n\toffsetof(Content, relWidthObj), offsetof(Content, relWidth),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_DOUBLE, \"-relx\", NULL, NULL, \"0.0\", TCL_INDEX_NONE,\n\toffsetof(Content, relX), 0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-rely\", NULL, NULL, \"0.0\", TCL_INDEX_NONE,\n\toffsetof(Content, relY), 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-width\", NULL, NULL, NULL, offsetof(Content, widthObj),\n\toffsetof(Content, width), TK_OPTION_NULL_OK|TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-x\", NULL, NULL, \"0\", offsetof(Content, xObj),\n\toffsetof(Content, x), TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-y\", NULL, NULL, \"0\", offsetof(Content, yObj),\n\toffsetof(Content, y), TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * For each container window that has a content managed by the placer there is a\n * structure of the following form:\n */\n\ntypedef struct Container {\n    Tk_Window tkwin;\t\t/* Tk's token for container window. */\n    struct Content *contentPtr;\t/* First in linked list of content windowslaced\n\t\t\t\t * relative to this container. */\n    int *abortPtr;\t\t/* If non-NULL, it means that there is a nested\n\t\t\t\t * call to RecomputePlacement already working on\n\t\t\t\t * this window.  *abortPtr may be set to 1 to\n\t\t\t\t * abort that nested call.  This happens, for\n\t\t\t\t * example, if tkwin or any of its content\n\t\t\t\t * is deleted. */\n    int flags;\t\t\t/* See below for bit definitions. */\n} Container;\n\n/*\n * Flag definitions for containers:\n *\n * PARENT_RECONFIG_PENDING -\t1 means that a call to RecomputePlacement is\n *\t\t\t\talready pending via a Do_When_Idle handler.\n */\n\n#define PARENT_RECONFIG_PENDING\t1\n\n/*\n * The following structure is the official type record for the placer:\n */\n\nstatic void\t\tPlaceRequestProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tPlaceLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\n\nstatic const Tk_GeomMgr placerType = {\n    \"place\",\t\t\t/* name */\n    PlaceRequestProc,\t\t/* requestProc */\n    PlaceLostContentProc,\t\t/* lostContentProc */\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tContentStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tk_OptionTable table, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tPlaceInfoCommand(Tcl_Interp *interp, Tk_Window tkwin);\nstatic Content *\t\tCreateContent(Tk_Window tkwin, Tk_OptionTable table);\nstatic void\t\tFreeContent(Content *contentPtr);\nstatic Content *\t\tFindContent(Tk_Window tkwin);\nstatic Container *\t\tCreateContainer(Tk_Window tkwin);\nstatic Container *\t\tFindContainer(Tk_Window tkwin);\nstatic void\t\tPlaceStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tRecomputePlacement(void *clientData);\nstatic void\t\tUnlinkContent(Content *contentPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_PlaceObjCmd --\n *\n *\tThis function is invoked to process the \"place\" Tcl commands. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_PlaceObjCmd(\n    void *clientData,\t/* Interpreter main window. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window main_win = (Tk_Window)clientData;\n    Tk_Window tkwin;\n    Content *contentPtr;\n    TkDisplay *dispPtr;\n    Tk_OptionTable optionTable;\n    static const char *const optionStrings[] = {\n\t\"configure\", \"content\", \"forget\", \"info\", \"slaves\", NULL\n    };\n    static const char *const optionStringsNoDep[] = {\n\t\"configure\", \"content\", \"forget\", \"info\", NULL\n    };\n    enum options { PLACE_CONFIGURE, PLACE_CONTENT, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES };\n    int index;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option|pathName args\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n     optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    /*\n     * Handle special shortcut where window name is first argument.\n     */\n\n    if (Tcl_GetString(objv[1])[0] == '.') {\n\tif (TkGetWindowFromObj(interp, main_win, objv[1],\n\t\t&tkwin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Initialize, if that hasn't been done yet.\n\t */\n\n\tdispPtr = ((TkWindow *) tkwin)->dispPtr;\n\tif (!dispPtr->placeInit) {\n\t    Tcl_InitHashTable(&dispPtr->containerTable, TCL_ONE_WORD_KEYS);\n\t    Tcl_InitHashTable(&dispPtr->contentTable, TCL_ONE_WORD_KEYS);\n\t    dispPtr->placeInit = 1;\n\t}\n\n\treturn ConfigureContent(interp, tkwin, optionTable, objc-2, objv+2);\n    }\n\n    /*\n     * Handle more general case of option followed by window name followed by\n     * possible additional arguments.\n     */\n\n    if (TkGetWindowFromObj(interp, main_win, objv[2],\n\t    &tkwin) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Initialize, if that hasn't been done yet.\n     */\n\n    dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    if (!dispPtr->placeInit) {\n\tTcl_InitHashTable(&dispPtr->containerTable, TCL_ONE_WORD_KEYS);\n\tTcl_InitHashTable(&dispPtr->contentTable, TCL_ONE_WORD_KEYS);\n\tdispPtr->placeInit = 1;\n    }\n\n    if (Tcl_GetIndexFromObj(NULL, objv[1], optionStrings,\n\t    \"option\", 0, &index) != TCL_OK) {\n\t/*\n\t * Call it again without the deprecated ones to get a proper error\n\t * message. This works well since there can't be any ambiguity between\n\t * deprecated and new options.\n\t */\n\n\tTcl_GetIndexFromObjStruct(interp, objv[1], optionStringsNoDep,\n\t\tsizeof(char *), \"option\", 0, &index);\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case PLACE_CONFIGURE:\n\tif (objc == 3 || objc == 4) {\n\t    Tcl_Obj *objPtr;\n\n\t    contentPtr = FindContent(tkwin);\n\t    if (contentPtr == NULL) {\n\t\treturn TCL_OK;\n\t    }\n\t    objPtr = Tk_GetOptionInfo(interp, contentPtr, optionTable,\n\t\t    (objc == 4) ? objv[3] : NULL, tkwin);\n\t    if (objPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    return TCL_OK;\n\t}\n\treturn ConfigureContent(interp, tkwin, optionTable, objc-3, objv+3);\n\n    case PLACE_FORGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName\");\n\t    return TCL_ERROR;\n\t}\n\tcontentPtr = FindContent(tkwin);\n\tif (contentPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tif ((contentPtr->containerPtr != NULL) &&\n\t\t(contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin))) {\n\t    Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n\t}\n\tUnlinkContent(contentPtr);\n\tTcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,\n\t\ttkwin));\n\tTk_DeleteEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,\n\t\tcontentPtr);\n\tTk_ManageGeometry(tkwin, NULL, NULL);\n\tTk_UnmapWindow(tkwin);\n\tFreeContent(contentPtr);\n\tbreak;\n\n    case PLACE_INFO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName\");\n\t    return TCL_ERROR;\n\t}\n\treturn PlaceInfoCommand(interp, tkwin);\n\n    case PLACE_SLAVES:\n    case PLACE_CONTENT: {\n\tContainer *containerPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"pathName\");\n\t    return TCL_ERROR;\n\t}\n\tcontainerPtr = FindContainer(tkwin);\n\tif (containerPtr != NULL) {\n\t    Tcl_Obj *listPtr = Tcl_NewObj();\n\n\t    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\t    contentPtr = contentPtr->nextPtr) {\n\t\tTcl_ListObjAppendElement(NULL, listPtr,\n\t\t\tTk_NewWindowObj(contentPtr->tkwin));\n\t    }\n\t    Tcl_SetObjResult(interp, listPtr);\n\t}\n\tbreak;\n    }\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateContent --\n *\n *\tGiven a Tk_Window token, find the Content structure corresponding to\n *\tthat token, creating a new one if necessary.\n *\n * Results:\n *\tPointer to the Content structure.\n *\n * Side effects:\n *\tA new Content structure may be created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Content *\nCreateContent(\n    Tk_Window tkwin,\t\t/* Token for desired content. */\n    Tk_OptionTable table)\n{\n    Tcl_HashEntry *hPtr;\n    Content *contentPtr;\n    int isNew;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    hPtr = Tcl_CreateHashEntry(&dispPtr->contentTable, (char *) tkwin, &isNew);\n    if (!isNew) {\n\treturn (Content *)Tcl_GetHashValue(hPtr);\n    }\n\n    /*\n     * No preexisting content structure for that window, so make a new one and\n     * populate it with some default values.\n     */\n\n    contentPtr = (Content *)Tcl_Alloc(sizeof(Content));\n    memset(contentPtr, 0, sizeof(Content));\n    contentPtr->tkwin = tkwin;\n    contentPtr->inTkwin = NULL;\n    contentPtr->anchor = TK_ANCHOR_NW;\n    contentPtr->borderMode = BM_INSIDE;\n    contentPtr->width = INT_MIN;\n    contentPtr->height = INT_MIN;\n    contentPtr->relWidth = NAN;\n    contentPtr->relHeight = NAN;\n    contentPtr->optionTable = table;\n    Tcl_SetHashValue(hPtr, contentPtr);\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,\n\t    contentPtr);\n    return contentPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeContent --\n *\n *\tFrees the resources held by a Content structure.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMemory are freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeContent(\n    Content *contentPtr)\n{\n    if (contentPtr->containerPtr && (contentPtr->containerPtr->flags & PARENT_RECONFIG_PENDING)) {\n\tTcl_CancelIdleCall(RecomputePlacement, contentPtr->containerPtr);\n    }\n    Tk_FreeConfigOptions(contentPtr, contentPtr->optionTable,\n\t    contentPtr->tkwin);\n    Tcl_Free(contentPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindContent --\n *\n *\tGiven a Tk_Window token, find the Content structure corresponding to\n *\tthat token. This is purely a lookup function; it will not create a\n *\trecord if one does not yet exist.\n *\n * Results:\n *\tPointer to Content structure; NULL if none exists.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Content *\nFindContent(\n    Tk_Window tkwin)\t\t/* Token for desired content. */\n{\n    Tcl_HashEntry *hPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    hPtr = Tcl_FindHashEntry(&dispPtr->contentTable, tkwin);\n    if (hPtr == NULL) {\n\treturn NULL;\n    }\n    return (Content *)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UnlinkContent --\n *\n *\tThis function removes a content window from the chain of content windows in its\n *\tcontainer.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe content list of contentPtr's container changes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnlinkContent(\n    Content *contentPtr)\t\t/* Content structure to be unlinked. */\n{\n    Container *containerPtr;\n    Content *prevPtr;\n\n    containerPtr = contentPtr->containerPtr;\n    if (containerPtr == NULL) {\n\treturn;\n    }\n    if (containerPtr->contentPtr == contentPtr) {\n\tcontainerPtr->contentPtr = contentPtr->nextPtr;\n    } else {\n\tfor (prevPtr = containerPtr->contentPtr; ; prevPtr = prevPtr->nextPtr) {\n\t    if (prevPtr == NULL) {\n\t\tTcl_Panic(\"UnlinkContent couldn't find content to unlink\");\n\t    }\n\t    if (prevPtr->nextPtr == contentPtr) {\n\t\tprevPtr->nextPtr = contentPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n    contentPtr->containerPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateContainer --\n *\n *\tGiven a Tk_Window token, find the Container structure corresponding to\n *\tthat token, creating a new one if necessary.\n *\n * Results:\n *\tPointer to the Container structure.\n *\n * Side effects:\n *\tA new Container structure may be created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Container *\nCreateContainer(\n    Tk_Window tkwin)\t\t/* Token for desired container. */\n{\n    Tcl_HashEntry *hPtr;\n    Container *containerPtr;\n    int isNew;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    hPtr = Tcl_CreateHashEntry(&dispPtr->containerTable, (char *)tkwin, &isNew);\n    if (isNew) {\n\tcontainerPtr = (Container *)Tcl_Alloc(sizeof(Container));\n\tcontainerPtr->tkwin = tkwin;\n\tcontainerPtr->contentPtr = NULL;\n\tcontainerPtr->abortPtr = NULL;\n\tcontainerPtr->flags = 0;\n\tTcl_SetHashValue(hPtr, containerPtr);\n\tTk_CreateEventHandler(containerPtr->tkwin, StructureNotifyMask,\n\t\tPlaceStructureProc, containerPtr);\n    } else {\n\tcontainerPtr = (Container *)Tcl_GetHashValue(hPtr);\n    }\n    return containerPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindContainer --\n *\n *\tGiven a Tk_Window token, find the Container structure corresponding to\n *\tthat token. This is simply a lookup function; a new record will not be\n *\tcreated if one does not already exist.\n *\n * Results:\n *\tPointer to the Container structure; NULL if one does not exist for the\n *\tgiven Tk_Window token.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Container *\nFindContainer(\n    Tk_Window tkwin)\t\t/* Token for desired container. */\n{\n    Tcl_HashEntry *hPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    hPtr = Tcl_FindHashEntry(&dispPtr->containerTable, tkwin);\n    if (hPtr == NULL) {\n\treturn NULL;\n    }\n    return (Container *)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureContent --\n *\n *\tThis function is called to process an objv/objc list to reconfigure\n *\tthe placement of a window.\n *\n * Results:\n *\tA standard Tcl result. If an error occurs then a message is left in\n *\tthe interp's result.\n *\n * Side effects:\n *\tInformation in contentPtr may change, and contentPtr's container is scheduled\n *\tfor reconfiguration.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureContent(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Window tkwin,\t\t/* Token for the window to manipulate. */\n    Tk_OptionTable table,\t/* Token for option table. */\n    Tcl_Size objc,\t\t\t/* Number of config arguments. */\n    Tcl_Obj *const objv[])\t/* Object values for arguments. */\n{\n    Container *containerPtr;\n    Tk_SavedOptions savedOptions;\n    int mask;\n    Content *contentPtr;\n    Tk_Window containerWin = NULL;\n    TkWindow *container;\n\n    if (Tk_TopWinHierarchy(tkwin)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use placer on top-level window \\\"%s\\\"; use \"\n\t\t\"wm command instead\", Tk_PathName(tkwin)));\n\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"TOPLEVEL\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    contentPtr = CreateContent(tkwin, table);\n\n    if (Tk_SetOptions(interp, contentPtr, table, objc, objv,\n\t    contentPtr->tkwin, &savedOptions, &mask) != TCL_OK) {\n\tgoto error;\n    }\n\n    if (!(mask & IN_MASK) && (contentPtr->containerPtr != NULL)) {\n\t/*\n\t * If no -in option was passed and the content is already placed then\n\t * just recompute the placement.\n\t */\n\n\tcontainerPtr = contentPtr->containerPtr;\n\tgoto scheduleLayout;\n    } else if (mask & IN_MASK) {\n\t/* -in changed */\n\tTk_Window win;\n\tTk_Window ancestor;\n\n\twin = contentPtr->inTkwin;\n\n\t/*\n\t * Make sure that the new container is either the logical parent of the\n\t * content window or a descendant of that window, and that the container and content\n\t * aren't the same.\n\t */\n\n\tfor (ancestor = win; ; ancestor = Tk_Parent(ancestor)) {\n\t    if (ancestor == Tk_Parent(contentPtr->tkwin)) {\n\t\tbreak;\n\t    }\n\t    if (Tk_TopWinHierarchy(ancestor)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't place \\\"%s\\\" relative to \\\"%s\\\"\",\n\t\t\tTk_PathName(contentPtr->tkwin), Tk_PathName(win)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\", (char *)NULL);\n\t\tgoto error;\n\t    }\n\t}\n\tif (contentPtr->tkwin == win) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't place \\\"%s\\\" relative to itself\",\n\t\t    Tk_PathName(contentPtr->tkwin)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"LOOP\", (char *)NULL);\n\t    goto error;\n\t}\n\n\t/*\n\t * Check for management loops.\n\t */\n\n\tfor (container = (TkWindow *)win; container != NULL;\n\t     container = (TkWindow *)TkGetContainer(container)) {\n\t    if (container == (TkWindow *)contentPtr->tkwin) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't put \\\"%s\\\" inside \\\"%s\\\": would cause management loop\",\n\t\t\tTk_PathName(contentPtr->tkwin), Tk_PathName(win)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"GEOMETRY\", \"LOOP\", (char *)NULL);\n\t\tgoto error;\n\t    }\n\t}\n\tif (win != Tk_Parent(contentPtr->tkwin)) {\n\t    ((TkWindow *)contentPtr->tkwin)->maintainerPtr = (TkWindow *)win;\n\t}\n\n\tif ((contentPtr->containerPtr != NULL)\n\t\t&& (contentPtr->containerPtr->tkwin == win)) {\n\t    /*\n\t     * Re-using same old container. Nothing to do.\n\t     */\n\n\t    containerPtr = contentPtr->containerPtr;\n\t    goto scheduleLayout;\n\t}\n\tif ((contentPtr->containerPtr != NULL) &&\n\t\t(contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin))) {\n\t    Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n\t}\n\tUnlinkContent(contentPtr);\n\tcontainerWin = win;\n    }\n\n    /*\n     * If there's no container specified for this content, use its Tk_Parent.\n     */\n\n    if (containerWin == NULL) {\n\tcontainerWin = Tk_Parent(contentPtr->tkwin);\n\tcontentPtr->inTkwin = containerWin;\n    }\n\n    /*\n     * Manage the content window in this container.\n     */\n\n    containerPtr = CreateContainer(containerWin);\n    contentPtr->containerPtr = containerPtr;\n    contentPtr->nextPtr = containerPtr->contentPtr;\n    containerPtr->contentPtr = contentPtr;\n    Tk_ManageGeometry(contentPtr->tkwin, &placerType, contentPtr);\n\n    /*\n     * Arrange for the container to be re-arranged at the first idle moment.\n     */\n\n  scheduleLayout:\n    Tk_FreeSavedOptions(&savedOptions);\n\n    if (!(containerPtr->flags & PARENT_RECONFIG_PENDING)) {\n\tcontainerPtr->flags |= PARENT_RECONFIG_PENDING;\n\tTcl_DoWhenIdle(RecomputePlacement, containerPtr);\n    }\n    return TCL_OK;\n\n    /*\n     * Error while processing some option, cleanup and return.\n     */\n\n  error:\n    Tk_RestoreSavedOptions(&savedOptions);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PlaceInfoCommand --\n *\n *\tImplementation of the [place info] subcommand. See the user\n *\tdocumentation for information on what it does.\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tIf the given tkwin is managed by the placer, this function will put\n *\tinformation about that placement in the interp's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPlaceInfoCommand(\n    Tcl_Interp *interp,\t\t/* Interp into which to place result. */\n    Tk_Window tkwin)\t\t/* Token for the window to get info on. */\n{\n    Content *contentPtr;\n    Tcl_Obj *infoObj;\n\n    contentPtr = FindContent(tkwin);\n    if (contentPtr == NULL) {\n\treturn TCL_OK;\n    }\n    infoObj = Tcl_NewObj();\n    if (contentPtr->containerPtr != NULL) {\n\tTcl_AppendToObj(infoObj, \"-in\", TCL_INDEX_NONE);\n\tTcl_ListObjAppendElement(NULL, infoObj,\n\t\tTk_NewWindowObj(contentPtr->containerPtr->tkwin));\n\tTcl_AppendToObj(infoObj, \" \", TCL_INDEX_NONE);\n    }\n    Tcl_AppendPrintfToObj(infoObj,\n\t    \"-x %d -relx %.4g -y %d -rely %.4g\",\n\t    contentPtr->x, contentPtr->relX, contentPtr->y, contentPtr->relY);\n    if (contentPtr->widthObj) {\n\tTcl_AppendPrintfToObj(infoObj, \" -width %d\", contentPtr->width);\n    } else {\n\tTcl_AppendToObj(infoObj, \" -width {}\", TCL_INDEX_NONE);\n    }\n    if (contentPtr->relWidthObj) {\n\tTcl_AppendPrintfToObj(infoObj,\n\t\t\" -relwidth %.4g\", contentPtr->relWidth);\n    } else {\n\tTcl_AppendToObj(infoObj, \" -relwidth {}\", TCL_INDEX_NONE);\n    }\n    if (contentPtr->heightObj) {\n\tTcl_AppendPrintfToObj(infoObj, \" -height %d\", contentPtr->height);\n    } else {\n\tTcl_AppendToObj(infoObj, \" -height {}\", TCL_INDEX_NONE);\n    }\n    if (contentPtr->relHeightObj) {\n\tTcl_AppendPrintfToObj(infoObj,\n\t\t\" -relheight %.4g\", contentPtr->relHeight);\n    } else {\n\tTcl_AppendToObj(infoObj, \" -relheight {}\", TCL_INDEX_NONE);\n    }\n\n    Tcl_AppendPrintfToObj(infoObj, \" -anchor %s -bordermode %s\",\n\t    Tk_NameOfAnchor(contentPtr->anchor),\n\t    borderModeStrings[contentPtr->borderMode]);\n    Tcl_SetObjResult(interp, infoObj);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RecomputePlacement --\n *\n *\tThis function is called as a when-idle handler. It recomputes the\n *\tgeometries of all the content of a given container.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWindows may change size or shape.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRecomputePlacement(\n    void *clientData)\t/* Pointer to Container record. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Content *contentPtr;\n    int x, y, width, height, tmp;\n    int containerWidth, containerHeight, containerX, containerY;\n    double x1, y1, x2, y2;\n    int abort;\t\t\t/* May get set to non-zero to abort this\n\t\t\t\t * placement operation. */\n\n    containerPtr->flags &= ~PARENT_RECONFIG_PENDING;\n\n    /*\n     * Abort any nested call to RecomputePlacement for this window, since\n     * we'll do everything necessary here, and set up so this call can be\n     * aborted if necessary.\n     */\n\n    if (containerPtr->abortPtr != NULL) {\n\t*containerPtr->abortPtr = 1;\n    }\n    containerPtr->abortPtr = &abort;\n    abort = 0;\n    Tcl_Preserve(containerPtr);\n\n    /*\n     * Iterate over all the content windows for the container. Each content's geometry can\n     * be computed independently of the other content. Changes to the window's\n     * structure could cause almost anything to happen, including deleting the\n     * parent or child. If this happens, we'll be told to abort.\n     */\n\n    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL && !abort;\n\t    contentPtr = contentPtr->nextPtr) {\n\t/*\n\t * Step 1: compute size and borderwidth of container, taking into account\n\t * desired border mode.\n\t */\n\n\tcontainerX = containerY = 0;\n\tcontainerWidth = Tk_Width(containerPtr->tkwin);\n\tcontainerHeight = Tk_Height(containerPtr->tkwin);\n\tif (contentPtr->borderMode == BM_INSIDE) {\n\t    containerX = Tk_InternalBorderLeft(containerPtr->tkwin);\n\t    containerY = Tk_InternalBorderTop(containerPtr->tkwin);\n\t    containerWidth -= containerX + Tk_InternalBorderRight(containerPtr->tkwin);\n\t    containerHeight -= containerY +\n\t\t    Tk_InternalBorderBottom(containerPtr->tkwin);\n\t} else if (contentPtr->borderMode == BM_OUTSIDE) {\n\t    containerX = containerY = -Tk_Changes(containerPtr->tkwin)->border_width;\n\t    containerWidth -= 2 * containerX;\n\t    containerHeight -= 2 * containerY;\n\t}\n\n\t/*\n\t * Step 2: compute size of content (outside dimensions including border)\n\t * and location of anchor point within container.\n\t */\n\n\tx1 = contentPtr->x + containerX + (contentPtr->relX*containerWidth);\n\tx = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5));\n\ty1 = contentPtr->y + containerY + (contentPtr->relY*containerHeight);\n\ty = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5));\n\tif ((contentPtr->widthObj) || contentPtr->relWidthObj) {\n\t    width = 0;\n\t    if (contentPtr->widthObj) {\n\t\twidth += contentPtr->width;\n\t    }\n\t    if (contentPtr->relWidthObj) {\n\t\t/*\n\t\t * The code below is a bit tricky. In order to round correctly\n\t\t * when both relX and relWidth are specified, compute the\n\t\t * location of the right edge and round that, then compute\n\t\t * width. If we compute the width and round it, rounding\n\t\t * errors in relX and relWidth accumulate.\n\t\t */\n\n\t\tx2 = x1 + (contentPtr->relWidth*containerWidth);\n\t\ttmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5));\n\t\twidth += tmp - x;\n\t    }\n\t} else {\n\t    width = Tk_ReqWidth(contentPtr->tkwin)\n\t\t    + 2*Tk_Changes(contentPtr->tkwin)->border_width;\n\t}\n\tif (contentPtr->heightObj || contentPtr->relHeightObj) {\n\t    height = 0;\n\t    if (contentPtr->heightObj) {\n\t\theight += contentPtr->height;\n\t    }\n\t    if (contentPtr->relHeightObj) {\n\t\t/*\n\t\t * See note above for rounding errors in width computation.\n\t\t */\n\n\t\ty2 = y1 + (contentPtr->relHeight*containerHeight);\n\t\ttmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5));\n\t\theight += tmp - y;\n\t    }\n\t} else {\n\t    height = Tk_ReqHeight(contentPtr->tkwin)\n\t\t    + 2*Tk_Changes(contentPtr->tkwin)->border_width;\n\t}\n\n\t/*\n\t * Step 3: adjust the x and y positions so that the desired anchor\n\t * point on the content appears at that position. Also adjust for the\n\t * border mode and container's border.\n\t */\n\n\tswitch (contentPtr->anchor) {\n\tcase TK_ANCHOR_N:\n\t    x -= width/2;\n\t    break;\n\tcase TK_ANCHOR_NE:\n\t    x -= width;\n\t    break;\n\tcase TK_ANCHOR_E:\n\t    x -= width;\n\t    y -= height/2;\n\t    break;\n\tcase TK_ANCHOR_SE:\n\t    x -= width;\n\t    y -= height;\n\t    break;\n\tcase TK_ANCHOR_S:\n\t    x -= width/2;\n\t    y -= height;\n\t    break;\n\tcase TK_ANCHOR_SW:\n\t    y -= height;\n\t    break;\n\tcase TK_ANCHOR_W:\n\t    y -= height/2;\n\t    break;\n\tcase TK_ANCHOR_NW:\n\t    break;\n\tdefault:\n\t    x -= width/2;\n\t    y -= height/2;\n\t    break;\n\t}\n\n\t/*\n\t * Step 4: adjust width and height again to reflect inside dimensions\n\t * of window rather than outside. Also make sure that the width and\n\t * height aren't zero.\n\t */\n\n\twidth -= 2*Tk_Changes(contentPtr->tkwin)->border_width;\n\theight -= 2*Tk_Changes(contentPtr->tkwin)->border_width;\n\tif (width <= 0) {\n\t    width = 1;\n\t}\n\tif (height <= 0) {\n\t    height = 1;\n\t}\n\n\t/*\n\t * Step 5: reconfigure the window and map it if needed. If the content\n\t * is a child of the container, we do this ourselves. If the content isn't\n\t * a child of the container, let Tk_MaintainGeometry do the work (it will\n\t * re-adjust things as relevant windows map, unmap, and move).\n\t */\n\n\tif (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {\n\t    if ((x != Tk_X(contentPtr->tkwin))\n\t\t    || (y != Tk_Y(contentPtr->tkwin))\n\t\t    || (width != Tk_Width(contentPtr->tkwin))\n\t\t    || (height != Tk_Height(contentPtr->tkwin))) {\n\t\tTk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);\n\t    }\n\t    if (abort) {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * Don't map the content unless the container is mapped: the content will\n\t     * get mapped later, when the container is mapped.\n\t     */\n\n\t    if (Tk_IsMapped(containerPtr->tkwin)) {\n\t\tTk_MapWindow(contentPtr->tkwin);\n\t    }\n\t} else {\n\t    if ((width <= 0) || (height <= 0)) {\n\t\tTk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);\n\t\tTk_UnmapWindow(contentPtr->tkwin);\n\t    } else {\n\t\tTk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin,\n\t\t\tx, y, width, height);\n\t    }\n\t}\n    }\n\n    containerPtr->abortPtr = NULL;\n    Tcl_Release(containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PlaceStructureProc --\n *\n *\tThis function is invoked by the Tk event handler when StructureNotify\n *\tevents occur for a container window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStructures get cleaned up if the window was deleted. If the window was\n *\tresized then content geometries get recomputed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPlaceStructureProc(\n    void *clientData,\t/* Pointer to Container structure for window\n\t\t\t\t * referred to by eventPtr. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Content *contentPtr, *nextPtr;\n    TkDisplay *dispPtr = ((TkWindow *) containerPtr->tkwin)->dispPtr;\n\n    switch (eventPtr->type) {\n    case ConfigureNotify:\n\tif ((containerPtr->contentPtr != NULL)\n\t\t&& !(containerPtr->flags & PARENT_RECONFIG_PENDING)) {\n\t    containerPtr->flags |= PARENT_RECONFIG_PENDING;\n\t    Tcl_DoWhenIdle(RecomputePlacement, containerPtr);\n\t}\n\treturn;\n    case DestroyNotify:\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = nextPtr) {\n\t    contentPtr->containerPtr = NULL;\n\t    nextPtr = contentPtr->nextPtr;\n\t    contentPtr->nextPtr = NULL;\n\t}\n\tTcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->containerTable,\n\t\tcontainerPtr->tkwin));\n\tif (containerPtr->flags & PARENT_RECONFIG_PENDING) {\n\t    Tcl_CancelIdleCall(RecomputePlacement, containerPtr);\n\t}\n\tcontainerPtr->tkwin = NULL;\n\tif (containerPtr->abortPtr != NULL) {\n\t    *containerPtr->abortPtr = 1;\n\t}\n\tTcl_EventuallyFree(containerPtr, TCL_DYNAMIC);\n\treturn;\n    case MapNotify:\n\t/*\n\t * When a container gets mapped, must redo the geometry computation so\n\t * that all of its content get remapped.\n\t */\n\n\tif ((containerPtr->contentPtr != NULL)\n\t\t&& !(containerPtr->flags & PARENT_RECONFIG_PENDING)) {\n\t    containerPtr->flags |= PARENT_RECONFIG_PENDING;\n\t    Tcl_DoWhenIdle(RecomputePlacement, containerPtr);\n\t}\n\treturn;\n    case UnmapNotify:\n\t/*\n\t * Unmap all of the content when the container gets unmapped, so that they\n\t * don't keep redisplaying themselves.\n\t */\n\n\tfor (contentPtr = containerPtr->contentPtr; contentPtr != NULL;\n\t\tcontentPtr = contentPtr->nextPtr) {\n\t    Tk_UnmapWindow(contentPtr->tkwin);\n\t}\n\treturn;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ContentStructureProc --\n *\n *\tThis function is invoked by the Tk event handler when StructureNotify\n *\tevents occur for a content window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStructures get cleaned up if the window was deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nContentStructureProc(\n    void *clientData,\t/* Pointer to Content structure for window\n\t\t\t\t * referred to by eventPtr. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    Content *contentPtr = (Content *)clientData;\n    TkDisplay *dispPtr = ((TkWindow *) contentPtr->tkwin)->dispPtr;\n\n    if (eventPtr->type == DestroyNotify) {\n\tif (contentPtr->containerPtr != NULL) {\n\t    UnlinkContent(contentPtr);\n\t}\n\tTcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,\n\t\tcontentPtr->tkwin));\n\tFreeContent(contentPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PlaceRequestProc --\n *\n *\tThis function is invoked by Tk whenever a content managed by us changes\n *\tits requested geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window will get relayed out, if its requested size has anything to\n *\tdo with its actual size.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPlaceRequestProc(\n    void *clientData,\t/* Pointer to our record for content. */\n    TCL_UNUSED(Tk_Window))\t\t/* Window that changed its desired size. */\n{\n    Content *contentPtr = (Content *)clientData;\n    Container *containerPtr;\n\n    if ((contentPtr->widthObj || contentPtr->relWidthObj)\n\t    && (contentPtr->heightObj || contentPtr->relHeightObj)) {\n\t/*\n\t * Send a ConfigureNotify to indicate that the size change\n\t * request was rejected.\n\t */\n\n\tTkDoConfigureNotify((TkWindow *)(contentPtr->tkwin));\n\treturn;\n    }\n    containerPtr = contentPtr->containerPtr;\n    if (containerPtr == NULL) {\n\treturn;\n    }\n    if (!(containerPtr->flags & PARENT_RECONFIG_PENDING)) {\n\tcontainerPtr->flags |= PARENT_RECONFIG_PENDING;\n\tTcl_DoWhenIdle(RecomputePlacement, containerPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PlaceLostContentProc --\n *\n *\tThis function is invoked by Tk whenever some other geometry claims\n *\tcontrol over a content window that used to be managed by us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tForgets all placer-related information about the content window.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPlaceLostContentProc(\n    void *clientData,\t/* Content structure for content window that was\n\t\t\t\t * stolen away. */\n    Tk_Window tkwin)\t\t/* Tk's handle for the content window. */\n{\n    Content *contentPtr = (Content *)clientData;\n    TkDisplay *dispPtr = ((TkWindow *) contentPtr->tkwin)->dispPtr;\n\n    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {\n\tTk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);\n    }\n    Tk_UnmapWindow(tkwin);\n    UnlinkContent(contentPtr);\n    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,\n\t    tkwin));\n    Tk_DeleteEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,\n\t    contentPtr);\n    FreeContent(contentPtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPlatDecls.h",
    "content": "/*\n * tkPlatDecls.h --\n *\n *\tDeclarations of functions in the platform-specific public Tcl API.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKPLATDECLS\n#define _TKPLATDECLS\n\n#ifdef BUILD_tk\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n#endif\n\n/*\n * WARNING: This file is automatically generated by the tools/genStubs.tcl\n * script.  Any modifications to the function declarations below should be made\n * in the generic/tk.decls script.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* !BEGIN!: Do not edit below this line. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n/* 0 */\nEXTERN Window\t\tTk_AttachHWND(Tk_Window tkwin, HWND hwnd);\n/* 1 */\nEXTERN HINSTANCE\tTk_GetHINSTANCE(void);\n/* 2 */\nEXTERN HWND\t\tTk_GetHWND(Window window);\n/* 3 */\nEXTERN Tk_Window\tTk_HWNDToWindow(HWND hwnd);\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n/* Slot 0 is reserved */\n/* Slot 1 is reserved */\n/* Slot 2 is reserved */\n/* Slot 3 is reserved */\n/* 4 */\nEXTERN void\t\tTkMacOSXInitAppleEvents(Tcl_Interp *interp);\n/* Slot 5 is reserved */\n/* 6 */\nEXTERN void\t\tTkMacOSXInvalClipRgns(Tk_Window tkwin);\n/* Slot 7 is reserved */\n/* 8 */\nEXTERN void *\t\tTkMacOSXGetRootControl(Drawable drawable);\n/* 9 */\nEXTERN void\t\tTk_MacOSXSetupTkNotifier(void);\n/* 10 */\nEXTERN int\t\tTk_MacOSXIsAppInFront(void);\n/* 11 */\nEXTERN Tk_Window\tTk_MacOSXGetTkWindow(void *w);\n/* 12 */\nEXTERN void *\t\tTk_MacOSXGetCGContextForDrawable(Drawable drawable);\n/* 13 */\nEXTERN void *\t\tTk_MacOSXGetNSWindowForDrawable(Drawable drawable);\n/* Slot 14 is reserved */\n/* Slot 15 is reserved */\n/* 16 */\nEXTERN void\t\tTkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,\n\t\t\t\tint width, int height, int flags);\n#endif /* AQUA */\n\ntypedef struct TkPlatStubs {\n    int magic;\n    void *hooks;\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n    Window (*tk_AttachHWND) (Tk_Window tkwin, HWND hwnd); /* 0 */\n    HINSTANCE (*tk_GetHINSTANCE) (void); /* 1 */\n    HWND (*tk_GetHWND) (Window window); /* 2 */\n    Tk_Window (*tk_HWNDToWindow) (HWND hwnd); /* 3 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n    void (*reserved0)(void);\n    void (*reserved1)(void);\n    void (*reserved2)(void);\n    void (*reserved3)(void);\n    void (*tkMacOSXInitAppleEvents) (Tcl_Interp *interp); /* 4 */\n    void (*reserved5)(void);\n    void (*tkMacOSXInvalClipRgns) (Tk_Window tkwin); /* 6 */\n    void (*reserved7)(void);\n    void * (*tkMacOSXGetRootControl) (Drawable drawable); /* 8 */\n    void (*tk_MacOSXSetupTkNotifier) (void); /* 9 */\n    int (*tk_MacOSXIsAppInFront) (void); /* 10 */\n    Tk_Window (*tk_MacOSXGetTkWindow) (void *w); /* 11 */\n    void * (*tk_MacOSXGetCGContextForDrawable) (Drawable drawable); /* 12 */\n    void * (*tk_MacOSXGetNSWindowForDrawable) (Drawable drawable); /* 13 */\n    void (*reserved14)(void);\n    void (*reserved15)(void);\n    void (*tkGenWMConfigureEvent) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 16 */\n#endif /* AQUA */\n} TkPlatStubs;\n\nextern const TkPlatStubs *tkPlatStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n#define Tk_AttachHWND \\\n\t(tkPlatStubsPtr->tk_AttachHWND) /* 0 */\n#define Tk_GetHINSTANCE \\\n\t(tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */\n#define Tk_GetHWND \\\n\t(tkPlatStubsPtr->tk_GetHWND) /* 2 */\n#define Tk_HWNDToWindow \\\n\t(tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n/* Slot 0 is reserved */\n/* Slot 1 is reserved */\n/* Slot 2 is reserved */\n/* Slot 3 is reserved */\n#define TkMacOSXInitAppleEvents \\\n\t(tkPlatStubsPtr->tkMacOSXInitAppleEvents) /* 4 */\n/* Slot 5 is reserved */\n#define TkMacOSXInvalClipRgns \\\n\t(tkPlatStubsPtr->tkMacOSXInvalClipRgns) /* 6 */\n/* Slot 7 is reserved */\n#define TkMacOSXGetRootControl \\\n\t(tkPlatStubsPtr->tkMacOSXGetRootControl) /* 8 */\n#define Tk_MacOSXSetupTkNotifier \\\n\t(tkPlatStubsPtr->tk_MacOSXSetupTkNotifier) /* 9 */\n#define Tk_MacOSXIsAppInFront \\\n\t(tkPlatStubsPtr->tk_MacOSXIsAppInFront) /* 10 */\n#define Tk_MacOSXGetTkWindow \\\n\t(tkPlatStubsPtr->tk_MacOSXGetTkWindow) /* 11 */\n#define Tk_MacOSXGetCGContextForDrawable \\\n\t(tkPlatStubsPtr->tk_MacOSXGetCGContextForDrawable) /* 12 */\n#define Tk_MacOSXGetNSWindowForDrawable \\\n\t(tkPlatStubsPtr->tk_MacOSXGetNSWindowForDrawable) /* 13 */\n/* Slot 14 is reserved */\n/* Slot 15 is reserved */\n#define TkGenWMConfigureEvent \\\n\t(tkPlatStubsPtr->tkGenWMConfigureEvent) /* 16 */\n#endif /* AQUA */\n\n#endif /* defined(USE_TK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#ifdef __cplusplus\n}\n#endif\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLIMPORT\n\n#define Tk_MacOSXGetNSViewForDrawable TkMacOSXGetRootControl\n\n#endif /* _TKPLATDECLS */\n"
  },
  {
    "path": "generic/tkPointer.c",
    "content": "/*\n * tkPointer.c --\n *\n *\tThis file contains functions for emulating the X server pointer and\n *\tgrab state machine. This file is used by the Mac and Windows platforms\n *\tto generate appropriate enter/leave events, and to update the global\n *\tgrab window information.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n#if defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#endif\n\ntypedef struct {\n    TkWindow *grabWinPtr;\t/* Window that defines the top of the grab\n\t\t\t\t * tree in a global grab. */\n    unsigned lastState;\t\t/* Last known state flags. */\n    XPoint lastPos;\t\t/* Last reported mouse position. */\n    TkWindow *lastWinPtr;\t/* Last reported mouse window. */\n    TkWindow *restrictWinPtr;\t/* Window to which all mouse events will be\n\t\t\t\t * reported. */\n    TkWindow *cursorWinPtr;\t/* Window that is currently controlling the\n\t\t\t\t * global cursor. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations of procedures used in this file.\n */\n\nstatic int\t\tGenerateEnterLeave(TkWindow *winPtr, int x, int y,\n\t\t\t    int state);\nstatic void\t\tInitializeEvent(XEvent *eventPtr, TkWindow *winPtr,\n\t\t\t    int type, int x, int y, int state, int detail);\nstatic void\t\tUpdateCursor(TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitializeEvent --\n *\n *\tInitializes the common fields for several X events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFills in the specified event structure.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitializeEvent(\n    XEvent *eventPtr,\t\t/* Event structure to initialize. */\n    TkWindow *winPtr,\t\t/* Window to make event relative to. */\n    int type,\t\t\t/* Message type. */\n    int x, int y,\t\t/* Root coords of event. */\n    int state,\t\t\t/* State flags. */\n    int detail)\t\t\t/* Detail value. */\n{\n    eventPtr->type = type;\n    eventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display);\n    eventPtr->xany.send_event = False;\n    eventPtr->xany.display = winPtr->display;\n\n    eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);\n    eventPtr->xcrossing.time = TkpGetMS();\n    eventPtr->xcrossing.x_root = x;\n    eventPtr->xcrossing.y_root = y;\n\n    switch (type) {\n    case EnterNotify:\n    case LeaveNotify:\n\teventPtr->xcrossing.mode = NotifyNormal;\n\teventPtr->xcrossing.state = state;\n\teventPtr->xcrossing.detail = detail;\n\teventPtr->xcrossing.focus = False;\n\tbreak;\n    case MotionNotify:\n\teventPtr->xmotion.state = state;\n\teventPtr->xmotion.is_hint = detail;\n\tbreak;\n    case ButtonPress:\n    case ButtonRelease:\n\teventPtr->xbutton.state = state;\n\teventPtr->xbutton.button = detail;\n\tbreak;\n    }\n    TkChangeEventWindow(eventPtr, winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateEnterLeave --\n *\n *\tUpdate the current mouse window and position, and generate any\n *\tenter/leave events that are needed.\n *\n * Results:\n *\tReturns 1 if enter/leave events were generated.\n *\n * Side effects:\n *\tMay insert events into the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGenerateEnterLeave(\n    TkWindow *winPtr,\t\t/* Current Tk window (or NULL). */\n    int x, int y,\t\t/* Current mouse position in root coords. */\n    int state)\t\t\t/* State flags. */\n{\n    int crossed = 0;\t\t/* 1 if mouse crossed a window boundary */\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr;\n    TkWindow *lastWinPtr = tsdPtr->lastWinPtr;\n\n    if (winPtr != tsdPtr->lastWinPtr) {\n\tif (restrictWinPtr) {\n\t    int newPos, oldPos;\n\n\t    newPos = TkPositionInTree(winPtr, restrictWinPtr);\n\t    oldPos = TkPositionInTree(lastWinPtr, restrictWinPtr);\n\n\t    /*\n\t     * Check if the mouse crossed into or out of the restrict window.\n\t     * If so, we need to generate an Enter or Leave event.\n\t     */\n\n\t    if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)\n\t\t    || (oldPos == TK_GRAB_IN_TREE))) {\n\t\tXEvent event;\n\t\tint type, detail;\n\n\t\tif (newPos == TK_GRAB_IN_TREE) {\n\t\t    type = EnterNotify;\n\t\t} else {\n\t\t    type = LeaveNotify;\n\t\t}\n\t\tif ((oldPos == TK_GRAB_ANCESTOR)\n\t\t\t|| (newPos == TK_GRAB_ANCESTOR)) {\n\t\t    detail = NotifyAncestor;\n\t\t} else {\n\t\t    detail = NotifyVirtual;\n\t\t}\n\t\tInitializeEvent(&event, restrictWinPtr, type, x, y,\n\t\t\tstate, detail);\n\t\tTk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t    }\n\n\t} else {\n\t    TkWindow *targetPtr;\n\n\t    if ((lastWinPtr == NULL)\n\t\t|| (lastWinPtr->window == None)) {\n\t\ttargetPtr = winPtr;\n\t    } else {\n\t\ttargetPtr = lastWinPtr;\n\t    }\n\n\t    if (targetPtr && (targetPtr->window != None)) {\n\t\tXEvent event;\n\n\t\t/*\n\t\t * Generate appropriate Enter/Leave events.\n\t\t */\n\n\t\tInitializeEvent(&event, targetPtr, LeaveNotify, x, y, state,\n\t\t\tNotifyAncestor);\n\n\t\tTkInOutEvents(&event, lastWinPtr, winPtr, LeaveNotify,\n\t\t\tEnterNotify, TCL_QUEUE_TAIL);\n\t\tcrossed = 1;\n\t    }\n\t}\n\ttsdPtr->lastWinPtr = winPtr;\n    }\n\n    return crossed;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UpdatePointer --\n *\n *\tThis function updates the pointer state machine given an the current\n *\twindow, position and modifier state.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay queue new events and update the grab state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UpdatePointer(\n    Tk_Window tkwin,\t\t/* Window to which pointer event is reported.\n\t\t\t\t * May be NULL. */\n    int x, int y,\t\t/* Pointer location in root coords. */\n    int state)\t\t\t/* Modifier state mask. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    TkWindow *targetWinPtr;\n    XPoint pos;\n    XEvent event;\n    unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS;\n    int type, b;\n    unsigned mask;\n\n    pos.x = x;\n    pos.y = y;\n\n    /*\n     * Use the current keyboard state, but the old mouse button state since we\n     * haven't generated the button events yet.\n     */\n\n    tsdPtr->lastState = (state & ~ALL_BUTTONS) | (tsdPtr->lastState\n\t    & ALL_BUTTONS);\n\n    /*\n     * Generate Enter/Leave events. If the pointer has crossed window\n     * boundaries, update the current mouse position so we don't generate\n     * redundant motion events.\n     */\n\n    if (GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState)) {\n\ttsdPtr->lastPos = pos;\n    }\n\n    /*\n     * Generate ButtonPress/ButtonRelease events based on the differences\n     * between the current button state and the last known button state.\n     */\n\n    for (b = Button1; b <= Button9; b++) {\n\tmask = Tk_GetButtonMask(b);\n\tif (changes & mask) {\n\t    if (state & mask) {\n\t\ttype = ButtonPress;\n\n\t\t/*\n\t\t * ButtonPress - Set restrict window if we aren't grabbed, or\n\t\t * if this is the first button down.\n\t\t */\n\n\t\tif (!tsdPtr->restrictWinPtr) {\n\t\t    if (!tsdPtr->grabWinPtr) {\n\t\t\t/*\n\t\t\t * Mouse is not grabbed, so set a button grab.\n\t\t\t */\n\n\t\t\ttsdPtr->restrictWinPtr = winPtr;\n\t\t\tTkpSetCapture(tsdPtr->restrictWinPtr);\n\n\t\t    } else if (!(tsdPtr->lastState & ALL_BUTTONS)) {\n\t\t\t/*\n\t\t\t * Mouse is in a non-button grab, so ensure the button\n\t\t\t * grab is inside the grab tree.\n\t\t\t */\n\n\t\t\tif (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)\n\t\t\t\t== TK_GRAB_IN_TREE) {\n\t\t\t    tsdPtr->restrictWinPtr = winPtr;\n\t\t\t} else {\n\t\t\t    tsdPtr->restrictWinPtr = tsdPtr->grabWinPtr;\n\t\t\t}\n\t\t\tTkpSetCapture(tsdPtr->restrictWinPtr);\n\t\t    }\n\t\t}\n\n\t    } else {\n\t\ttype = ButtonRelease;\n\n\t\t/*\n\t\t * ButtonRelease - Release the mouse capture and clear the\n\t\t * restrict window when the last button is released. If we\n\t\t * are in a global grab, restore the grab window capture.\n\t\t */\n\n\t\tif ((tsdPtr->lastState & ALL_BUTTONS) == mask) {\n\t\t    TkpSetCapture(tsdPtr->grabWinPtr);\n\t\t}\n\n\t\t/*\n\t\t * If we are releasing a restrict window, then we need to send\n\t\t * the button event followed by mouse motion from the restrict\n\t\t * window to the current mouse position.\n\t\t */\n\n\t\tif (tsdPtr->restrictWinPtr) {\n\t\t    InitializeEvent(&event, tsdPtr->restrictWinPtr, type, x, y,\n\t\t\t    tsdPtr->lastState, b);\n\t\t    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t\t    tsdPtr->lastState &= ~mask;\n\t\t    tsdPtr->lastWinPtr = tsdPtr->restrictWinPtr;\n\t\t    tsdPtr->restrictWinPtr = NULL;\n\n\t\t    GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState);\n\t\t    tsdPtr->lastPos = pos;\n\t\t    continue;\n\t\t}\n\t    }\n\n\t    /*\n\t     * If a restrict window is set, make sure the pointer event is\n\t     * reported relative to that window. Otherwise, if a global grab\n\t     * is in effect then events outside of windows managed by Tk\n\t     * should be reported to the grab window.\n\t     */\n\n\t    if (tsdPtr->restrictWinPtr) {\n\t\ttargetWinPtr = tsdPtr->restrictWinPtr;\n\t    } else if (tsdPtr->grabWinPtr && !winPtr) {\n\t\ttargetWinPtr = tsdPtr->grabWinPtr;\n\t    } else {\n\t\ttargetWinPtr = winPtr;\n\t    }\n\n\t    /*\n\t     * If we still have a target window, send the event.\n\t     */\n\n\t    if (targetWinPtr != NULL) {\n\t\tInitializeEvent(&event, targetWinPtr, type, x, y,\n\t\t\ttsdPtr->lastState, b);\n\t\tTk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t    }\n\n\t    /*\n\t     * Update the state for the next iteration.\n\t     */\n\n\t    tsdPtr->lastState = (type == ButtonPress)\n\t\t    ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask);\n\t    tsdPtr->lastPos = pos;\n\t}\n    }\n\n    /*\n     * Make sure the cursor window is up to date.\n     */\n\n    if (tsdPtr->restrictWinPtr) {\n\ttargetWinPtr = tsdPtr->restrictWinPtr;\n    } else if (tsdPtr->grabWinPtr) {\n\ttargetWinPtr = (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)\n\t\t== TK_GRAB_IN_TREE) ? winPtr : tsdPtr->grabWinPtr;\n    } else {\n\ttargetWinPtr = winPtr;\n    }\n    UpdateCursor(targetWinPtr);\n\n    /*\n     * If no other events caused the position to be updated, generate a motion\n     * event.\n     */\n\n    if (tsdPtr->lastPos.x != pos.x || tsdPtr->lastPos.y != pos.y) {\n\tif (tsdPtr->restrictWinPtr) {\n\t    targetWinPtr = tsdPtr->restrictWinPtr;\n\t} else if (tsdPtr->grabWinPtr && !winPtr) {\n\t    targetWinPtr = tsdPtr->grabWinPtr;\n\t}\n\n\tif (targetWinPtr != NULL) {\n\t    InitializeEvent(&event, targetWinPtr, MotionNotify, x, y,\n\t\t    tsdPtr->lastState, NotifyAncestor);\n\t    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t}\n\ttsdPtr->lastPos = pos;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGrabPointer --\n *\n *\tCapture the mouse so event are reported outside of toplevels. Note\n *\tthat this is a very limited implementation that only supports\n *\tGrabModeAsync and owner_events True.\n *\n * Results:\n *\tAlways returns GrabSuccess.\n *\n * Side effects:\n *\tTurns on mouse capture, sets the global grab pointer, and clears any\n *\twindow restrictions.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXGrabPointer(\n    Display *display,\n    Window grab_window,\n    TCL_UNUSED(Bool),\t/* owner_events */\n    TCL_UNUSED(unsigned int),\t/* event_mask */\n    TCL_UNUSED(int),\t/* pointer_mode */\n    TCL_UNUSED(int),\t/* keyboard_mode */\n    TCL_UNUSED(Window),\t/* confine_to */\n    TCL_UNUSED(Cursor),\t/* cursor */\n    TCL_UNUSED(Time))\t/* time */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    LastKnownRequestProcessed(display)++;\n    tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);\n    tsdPtr->restrictWinPtr = NULL;\n    TkpSetCapture(tsdPtr->grabWinPtr);\n    if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr)\n\t    != TK_GRAB_IN_TREE) {\n\tUpdateCursor(tsdPtr->grabWinPtr);\n    }\n    return GrabSuccess;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUngrabPointer --\n *\n *\tRelease the current grab.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tReleases the mouse capture.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUngrabPointer(\n    Display *display,\n    TCL_UNUSED(Time)) /* time */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    LastKnownRequestProcessed(display)++;\n    tsdPtr->grabWinPtr = NULL;\n    tsdPtr->restrictWinPtr = NULL;\n    TkpSetCapture(NULL);\n    UpdateCursor(tsdPtr->lastWinPtr);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPointerDeadWindow --\n *\n *\tClean up pointer module state when a window is destroyed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay release the current capture window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkPointerDeadWindow(\n    TkWindow *winPtr)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr == tsdPtr->lastWinPtr) {\n\ttsdPtr->lastWinPtr = TkGetContainer(winPtr);\n    }\n    if (winPtr == tsdPtr->grabWinPtr) {\n\ttsdPtr->grabWinPtr = NULL;\n    }\n    if (winPtr == tsdPtr->restrictWinPtr) {\n\ttsdPtr->restrictWinPtr = NULL;\n    }\n    if (!(tsdPtr->restrictWinPtr || tsdPtr->grabWinPtr)) {\n\n\t/*\n\t * Release mouse capture only if the dead window is the capturing\n\t * window.\n\t */\n\n\tif (winPtr == (TkWindow *)TkpGetCapture()) {\n\t    TkpSetCapture(NULL);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateCursor --\n *\n *\tSet the windows global cursor to the cursor associated with the given\n *\tTk window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the mouse cursor.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateCursor(\n    TkWindow *winPtr)\n{\n    Cursor cursor = None;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * A window inherits its cursor from its parent if it doesn't have one of\n     * its own. Top level windows inherit the default cursor.\n     */\n\n    tsdPtr->cursorWinPtr = winPtr;\n    while (winPtr != NULL) {\n\tif (winPtr->atts.cursor != None) {\n\t    cursor = winPtr->atts.cursor;\n\t    break;\n\t} else if (winPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n\twinPtr = winPtr->parentPtr;\n    }\n    TkpSetCursor(cursor);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDefineCursor --\n *\n *\tThis function is called to update the cursor on a window. Since the\n *\tmouse might be in the specified window, we need to check the specified\n *\twindow against the current mouse position and grab state.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay update the cursor.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDefineCursor(\n    Display *display,\n    Window w,\n    TCL_UNUSED(Cursor)) /* cursor */\n{\n    TkWindow *winPtr = (TkWindow *) Tk_IdToWindow(display, w);\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->cursorWinPtr == winPtr) {\n\tUpdateCursor(winPtr);\n    }\n    LastKnownRequestProcessed(display)++;\n    return Success;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkPort.h",
    "content": "/*\n * tkPort.h --\n *\n *\tThis header file handles porting issues that occur because of\n *\tdifferences between systems.  It reads in platform specific\n *\tportability files.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKPORT\n#define _TKPORT\n\n#if defined(_WIN32)\n#   include \"tkWinPort.h\"\n#endif\n#ifndef _TK\n#   include \"tk.h\"\n#endif\n#if !defined(_WIN32)\n#   if defined(MAC_OSX_TK)\n#\tinclude \"tkMacOSXPort.h\"\n#   else\n#\tinclude \"tkUnixPort.h\"\n#   endif\n#endif\n\n#endif /* _TKPORT */\n"
  },
  {
    "path": "generic/tkRectOval.c",
    "content": "/*\n * tkRectOval.c --\n *\n *\tThis file implements rectangle and oval items for canvas widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n#include \"default.h\"\n\n/*\n * The structure below defines the record for each rectangle/oval item.\n */\n\ntypedef struct RectOvalItem  {\n    Tk_Item header;\t\t/* Generic stuff that's the same for all\n\t\t\t\t * types. MUST BE FIRST IN STRUCTURE. */\n    Tk_Outline outline;\t\t/* Outline structure */\n    double bbox[4];\t\t/* Coordinates of bounding box for rectangle\n\t\t\t\t * or oval (x1, y1, x2, y2). Item includes x1\n\t\t\t\t * and x2 but not y1 and y2. */\n    Tk_TSOffset tsoffset;\n    XColor *fillColor;\t\t/* Color for filling rectangle/oval. */\n    XColor *activeFillColor;\t/* Color for filling rectangle/oval if state\n\t\t\t\t * is active. */\n    XColor *disabledFillColor;\t/* Color for filling rectangle/oval if state\n\t\t\t\t * is disabled. */\n    Pixmap fillStipple;\t\t/* Stipple bitmap for filling item. */\n    Pixmap activeFillStipple;\t/* Stipple bitmap for filling item if state is\n\t\t\t\t * active. */\n    Pixmap disabledFillStipple;\t/* Stipple bitmap for filling item if state is\n\t\t\t\t * disabled. */\n    GC fillGC;\t\t\t/* Graphics context for filling item. */\n} RectOvalItem;\n\n/*\n * Information used for parsing configuration specs:\n */\n\nstatic const Tk_CustomOption stateOption = {\n    TkStateParseProc, TkStatePrintProc, INT2PTR(2)\n};\nstatic const Tk_CustomOption tagsOption = {\n    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL\n};\nstatic const Tk_CustomOption dashOption = {\n    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL\n};\nstatic const Tk_CustomOption offsetOption = {\n    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)\n};\nstatic const Tk_CustomOption pixelOption = {\n    TkPixelParseProc, TkPixelPrintProc, NULL\n};\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_CUSTOM, \"-activedash\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.activeDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-activefill\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-activeoutline\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activeoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.activeStipple),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-activestipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-activewidth\", NULL, NULL,\n\t\"0.0\", offsetof(RectOvalItem, outline.activeWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_CUSTOM, \"-dash\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.dash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_PIXELS, \"-dashoffset\", NULL, NULL,\n\t\"0\", offsetof(RectOvalItem, outline.offsetObj),\n\tTK_CONFIG_OBJS|TK_OPTION_NEG_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disableddash\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.disabledDash),\n\tTK_CONFIG_NULL_OK, &dashOption},\n    {TK_CONFIG_COLOR, \"-disabledfill\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-disabledoutline\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.disabledColor),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledoutlinestipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.disabledStipple),\n\tTK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_BITMAP, \"-disabledstipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-disabledwidth\", NULL, NULL,\n\t\"0.0\", offsetof(RectOvalItem, outline.disabledWidth),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_COLOR, \"-fill\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-offset\", NULL, NULL,\n\t\"0,0\", offsetof(RectOvalItem, tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_COLOR, \"-outline\", NULL, NULL,\n\tDEF_CANVITEM_OUTLINE, offsetof(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-outlineoffset\", NULL, NULL,\n\t\"0,0\", offsetof(RectOvalItem, outline.tsoffset),\n\tTK_CONFIG_DONT_SET_DEFAULT, &offsetOption},\n    {TK_CONFIG_BITMAP, \"-outlinestipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-state\", NULL, NULL,\n\tNULL, offsetof(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption},\n    {TK_CONFIG_BITMAP, \"-stipple\", NULL, NULL,\n\tNULL, offsetof(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_CUSTOM, \"-tags\", NULL, NULL,\n\tNULL, 0, TK_CONFIG_NULL_OK, &tagsOption},\n    {TK_CONFIG_CUSTOM, \"-width\", NULL, NULL,\n\t\"1.0\", offsetof(RectOvalItem, outline.width),\n\tTK_CONFIG_DONT_SET_DEFAULT, &pixelOption},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic void\t\tComputeRectOvalBbox(Tk_Canvas canvas,\n\t\t\t    RectOvalItem *rectOvalPtr);\nstatic int\t\tConfigureRectOval(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    int flags);\nstatic int\t\tCreateRectOval(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDeleteRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Display *display);\nstatic void\t\tDisplayRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    Display *display, Drawable dst, int x, int y,\n\t\t\t    int width, int height);\nstatic int\t\tOvalToArea(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double *areaPtr);\nstatic double\t\tOvalToPoint(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double *pointPtr);\nstatic int\t\tRectOvalCoords(Tcl_Interp *interp, Tk_Canvas canvas,\n\t\t\t    Tk_Item *itemPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tRectOvalToPostscript(Tcl_Interp *interp,\n\t\t\t    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);\nstatic int\t\tRectToArea(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double *areaPtr);\nstatic double\t\tRectToPoint(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double *pointPtr);\nstatic void\t\tRotateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY, double angleRad);\nstatic void\t\tScaleRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double originX, double originY,\n\t\t\t    double scaleX, double scaleY);\nstatic void\t\tTranslateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,\n\t\t\t    double deltaX, double deltaY);\n\n/*\n * The structures below defines the rectangle and oval item types by means of\n * functions that can be invoked by generic item code.\n */\n\nTk_ItemType tkRectangleType = {\n    \"rectangle\",\t\t/* name */\n    sizeof(RectOvalItem),\t/* itemSize */\n    CreateRectOval,\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureRectOval,\t\t/* configureProc */\n    RectOvalCoords,\t\t/* coordProc */\n    DeleteRectOval,\t\t/* deleteProc */\n    DisplayRectOval,\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    RectToPoint,\t\t/* pointProc */\n    RectToArea,\t\t\t/* areaProc */\n    RectOvalToPostscript,\t/* postscriptProc */\n    ScaleRectOval,\t\t/* scaleProc */\n    TranslateRectOval,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* icursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateRectOval,\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\nTk_ItemType tkOvalType = {\n    \"oval\",\t\t\t/* name */\n    sizeof(RectOvalItem),\t/* itemSize */\n    CreateRectOval,\t\t/* createProc */\n    configSpecs,\t\t/* configSpecs */\n    ConfigureRectOval,\t\t/* configureProc */\n    RectOvalCoords,\t\t/* coordProc */\n    DeleteRectOval,\t\t/* deleteProc */\n    DisplayRectOval,\t\t/* displayProc */\n    0,\t\t\t\t/* flags */\n    OvalToPoint,\t\t/* pointProc */\n    OvalToArea,\t\t\t/* areaProc */\n    RectOvalToPostscript,\t/* postscriptProc */\n    ScaleRectOval,\t\t/* scaleProc */\n    TranslateRectOval,\t\t/* translateProc */\n    NULL,\t\t\t/* indexProc */\n    NULL,\t\t\t/* cursorProc */\n    NULL,\t\t\t/* selectionProc */\n    NULL,\t\t\t/* insertProc */\n    NULL,\t\t\t/* dTextProc */\n    NULL,\t\t\t/* nextPtr */\n    RotateRectOval,\t\t/* rotateProc */\n    0, NULL, NULL\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateRectOval --\n *\n *\tThis function is invoked to create a new rectangle or oval item in a\n *\tcanvas.\n *\n * Results:\n *\tA standard Tcl return value. If an error occurred in creating the\n *\titem, then an error message is left in the interp's result; in this\n *\tcase itemPtr is left uninitialized, so it can be safely freed by the\n *\tcaller.\n *\n * Side effects:\n *\tA new rectangle or oval item is created.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateRectOval(\n    Tcl_Interp *interp,\t\t/* For error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas to hold new item. */\n    Tk_Item *itemPtr,\t\t/* Record to hold new item; header has been\n\t\t\t\t * initialized by caller. */\n    Tcl_Size objc,\t\t\t/* Number of arguments in objv. */\n    Tcl_Obj *const objv[])\t/* Arguments describing rectangle. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n    Tcl_Size i;\n\n    if (objc == 0) {\n\tTcl_Panic(\"canvas did not pass any coords\");\n    }\n\n    /*\n     * Carry out initialization that is needed in order to clean up after\n     * errors during the the remainder of this function.\n     */\n\n    Tk_CreateOutline(&(rectOvalPtr->outline));\n    rectOvalPtr->tsoffset.flags = 0;\n    rectOvalPtr->tsoffset.xoffset = 0;\n    rectOvalPtr->tsoffset.yoffset = 0;\n    rectOvalPtr->fillColor = NULL;\n    rectOvalPtr->activeFillColor = NULL;\n    rectOvalPtr->disabledFillColor = NULL;\n    rectOvalPtr->fillStipple = None;\n    rectOvalPtr->activeFillStipple = None;\n    rectOvalPtr->disabledFillStipple = None;\n    rectOvalPtr->fillGC = NULL;\n\n    /*\n     * Process the arguments to fill in the item record.\n     */\n\n    for (i = 1; i < objc; i++) {\n\tconst char *arg = Tcl_GetString(objv[i]);\n\n\tif ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {\n\t    break;\n\t}\n    }\n    if ((RectOvalCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {\n\tgoto error;\n    }\n    if (ConfigureRectOval(interp, canvas, itemPtr, objc-i, objv+i, 0)\n\t    == TCL_OK) {\n\treturn TCL_OK;\n    }\n\n  error:\n    DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RectOvalCoords --\n *\n *\tThis function is invoked to process the \"coords\" widget command on\n *\trectangles and ovals. See the user documentation for details on what\n *\tit does.\n *\n * Results:\n *\tReturns TCL_OK or TCL_ERROR, and sets the interp's result.\n *\n * Side effects:\n *\tThe coordinates for the given item may be changed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nRectOvalCoords(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item whose coordinates are to be read or\n\t\t\t\t * modified. */\n    Tcl_Size objc,\t\t\t/* Number of coordinates supplied in objv. */\n    Tcl_Obj *const objv[])\t/* Array of coordinates: x1,y1,x2,y2,... */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n\n    /*\n     * If no coordinates, return the current coordinates (i.e. bounding box).\n     */\n\n    if (objc == 0) {\n\tTcl_Obj *bbox[4];\n\n\tbbox[0] = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);\n\tbbox[1] = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);\n\tbbox[2] = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);\n\tbbox[3] = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));\n\treturn TCL_OK;\n    }\n\n    /*\n     * If one \"coordinate\", treat as list of coordinates.\n     */\n\n    if (objc == 1) {\n\tif (Tcl_ListObjGetElements(interp, objv[0], &objc,\n\t\t(Tcl_Obj ***) &objv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Better have four coordinates now. Spit out an error message otherwise.\n     */\n\n    if (objc != 4) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"wrong # coordinates: expected 0 or 4, got %\" TCL_SIZE_MODIFIER \"d\", objc));\n\tTcl_SetErrorCode(interp, \"TK\", \"CANVAS\", \"COORDS\",\n\t\t(rectOvalPtr->header.typePtr == &tkRectangleType\n\t\t\t? \"RECTANGLE\" : \"OVAL\"), (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the coordinates and update our bounding box.\n     */\n\n    if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],\n\t\t&rectOvalPtr->bbox[0]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],\n\t\t&rectOvalPtr->bbox[1]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2],\n\t\t&rectOvalPtr->bbox[2]) != TCL_OK)\n\t    || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3],\n\t\t&rectOvalPtr->bbox[3]) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    ComputeRectOvalBbox(canvas, rectOvalPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ConfigureRectOval --\n *\n *\tThis function is invoked to configure various aspects of a rectangle\n *\tor oval item, such as its border and background colors.\n *\n * Results:\n *\tA standard Tcl result code. If an error occurs, then an error message\n *\tis left in the interp's result.\n *\n * Side effects:\n *\tConfiguration information, such as colors and stipple patterns, may be\n *\tset for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nConfigureRectOval(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Canvas canvas,\t\t/* Canvas containing itemPtr. */\n    Tk_Item *itemPtr,\t\t/* Rectangle item to reconfigure. */\n    Tcl_Size objc,\t\t\t/* Number of elements in objv. */\n    Tcl_Obj *const objv[],\t/* Arguments describing things to configure. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n    XGCValues gcValues;\n    GC newGC;\n    unsigned long mask;\n    Tk_Window tkwin;\n    Tk_TSOffset *tsoffset;\n    XColor *color;\n    Pixmap stipple;\n    Tk_State state;\n\n    tkwin = Tk_CanvasTkwin(canvas);\n\n    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,\n\t    objv, rectOvalPtr, flags)) {\n\treturn TCL_ERROR;\n    }\n    state = itemPtr->state;\n\n    /*\n     * A few of the options require additional processing, such as graphics\n     * contexts.\n     */\n\n    if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||\n\t    rectOvalPtr->outline.activeDash.number != 0 ||\n\t    rectOvalPtr->outline.activeColor != NULL ||\n\t    rectOvalPtr->outline.activeStipple != None ||\n\t    rectOvalPtr->activeFillColor != NULL ||\n\t    rectOvalPtr->activeFillStipple != None) {\n\titemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;\n    } else {\n\titemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;\n    }\n\n    tsoffset = &rectOvalPtr->outline.tsoffset;\n    flags = tsoffset->flags;\n    if (flags & TK_OFFSET_LEFT) {\n\ttsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);\n    } else if (flags & TK_OFFSET_CENTER) {\n\ttsoffset->xoffset = (int)\n\t\t((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);\n    } else if (flags & TK_OFFSET_RIGHT) {\n\ttsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);\n    }\n    if (flags & TK_OFFSET_TOP) {\n\ttsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);\n    } else if (flags & TK_OFFSET_MIDDLE) {\n\ttsoffset->yoffset = (int)\n\t\t((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);\n    } else if (flags & TK_OFFSET_BOTTOM) {\n\ttsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);\n    }\n\n    /*\n     * Configure the outline graphics context. If mask is non-zero, the gc has\n     * changed and must be reallocated, provided that the new settings specify\n     * a valid outline (non-zero width and non-NULL color)\n     */\n\n    mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,\n\t    &(rectOvalPtr->outline));\n    if (mask && \\\n\t    rectOvalPtr->outline.width != 0 && \\\n\t    rectOvalPtr->outline.color != NULL) {\n\tgcValues.cap_style = CapProjecting;\n\tmask |= GCCapStyle;\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    } else {\n\tnewGC = NULL;\n    }\n    if (rectOvalPtr->outline.gc != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);\n    }\n    rectOvalPtr->outline.gc = newGC;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    if (state == TK_STATE_HIDDEN) {\n\tComputeRectOvalBbox(canvas, rectOvalPtr);\n\treturn TCL_OK;\n    }\n\n    color = rectOvalPtr->fillColor;\n    stipple = rectOvalPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (rectOvalPtr->activeFillColor!=NULL) {\n\t    color = rectOvalPtr->activeFillColor;\n\t}\n\tif (rectOvalPtr->activeFillStipple!=None) {\n\t    stipple = rectOvalPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectOvalPtr->disabledFillColor!=NULL) {\n\t    color = rectOvalPtr->disabledFillColor;\n\t}\n\tif (rectOvalPtr->disabledFillStipple!=None) {\n\t    stipple = rectOvalPtr->disabledFillStipple;\n\t}\n    }\n\n    if (color == NULL) {\n\tnewGC = NULL;\n    } else {\n\tgcValues.foreground = color->pixel;\n\tif (stipple != None) {\n\t    gcValues.stipple = stipple;\n\t    gcValues.fill_style = FillStippled;\n\t    mask = GCForeground|GCStipple|GCFillStyle;\n\t} else {\n\t    mask = GCForeground;\n\t}\n#ifdef MAC_OSX_TK\n\t/*\n\t * Mac OS X CG drawing needs access to the outline linewidth even for\n\t * fills (as linewidth controls antialiasing).\n\t */\n\tgcValues.line_width = rectOvalPtr->outline.gc != NULL ?\n\t\trectOvalPtr->outline.gc->line_width : 0;\n\tmask |= GCLineWidth;\n#endif\n\tnewGC = Tk_GetGC(tkwin, mask, &gcValues);\n    }\n    if (rectOvalPtr->fillGC != NULL) {\n\tTk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);\n    }\n    rectOvalPtr->fillGC = newGC;\n\n    tsoffset = &rectOvalPtr->tsoffset;\n    flags = tsoffset->flags;\n    if (flags & TK_OFFSET_LEFT) {\n\ttsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);\n    } else if (flags & TK_OFFSET_CENTER) {\n\ttsoffset->xoffset = (int)\n\t\t((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);\n    } else if (flags & TK_OFFSET_RIGHT) {\n\ttsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);\n    }\n    if (flags & TK_OFFSET_TOP) {\n\ttsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);\n    } else if (flags & TK_OFFSET_MIDDLE) {\n\ttsoffset->yoffset = (int)\n\t\t((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);\n    } else if (flags & TK_OFFSET_BOTTOM) {\n\ttsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);\n    }\n\n    ComputeRectOvalBbox(canvas, rectOvalPtr);\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteRectOval --\n *\n *\tThis function is called to clean up the data structure associated with\n *\ta rectangle or oval item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with itemPtr are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteRectOval(\n    TCL_UNUSED(Tk_Canvas),\t\t/* Info about overall widget. */\n    Tk_Item *itemPtr,\t\t/* Item that is being deleted. */\n    Display *display)\t\t/* Display containing window for canvas. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n\n    Tk_DeleteOutline(display, &(rectOvalPtr->outline));\n    if (rectOvalPtr->fillColor != NULL) {\n\tTk_FreeColor(rectOvalPtr->fillColor);\n    }\n    if (rectOvalPtr->activeFillColor != NULL) {\n\tTk_FreeColor(rectOvalPtr->activeFillColor);\n    }\n    if (rectOvalPtr->disabledFillColor != NULL) {\n\tTk_FreeColor(rectOvalPtr->disabledFillColor);\n    }\n    if (rectOvalPtr->fillStipple != None) {\n\tTk_FreeBitmap(display, rectOvalPtr->fillStipple);\n    }\n    if (rectOvalPtr->activeFillStipple != None) {\n\tTk_FreeBitmap(display, rectOvalPtr->activeFillStipple);\n    }\n    if (rectOvalPtr->disabledFillStipple != None) {\n\tTk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);\n    }\n    if (rectOvalPtr->fillGC != NULL) {\n\tTk_FreeGC(display, rectOvalPtr->fillGC);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeRectOvalBbox --\n *\n *\tThis function is invoked to compute the bounding box of all the pixels\n *\tthat may be drawn as part of a rectangle or oval.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe fields x1, y1, x2, and y2 are updated in the header for itemPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nComputeRectOvalBbox(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    RectOvalItem *rectOvalPtr)\t/* Item whose bbox is to be recomputed. */\n{\n    int bloat, tmp;\n    double dtmp, width;\n    Tk_State state = rectOvalPtr->header.state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = rectOvalPtr->outline.width;\n    if (state == TK_STATE_HIDDEN) {\n\trectOvalPtr->header.x1 = rectOvalPtr->header.y1 =\n\trectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;\n\treturn;\n    }\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) rectOvalPtr) {\n\tif (rectOvalPtr->outline.activeWidth>width) {\n\t    width = rectOvalPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectOvalPtr->outline.disabledWidth>0) {\n\t    width = rectOvalPtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * Make sure that the first coordinates are the lowest ones.\n     */\n\n    if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {\n\tdouble tmpY = rectOvalPtr->bbox[3];\n\n\trectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];\n\trectOvalPtr->bbox[1] = tmpY;\n    }\n    if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {\n\tdouble tmpX = rectOvalPtr->bbox[2];\n\n\trectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];\n\trectOvalPtr->bbox[0] = tmpX;\n    }\n\n    if (rectOvalPtr->outline.gc == NULL) {\n\t/*\n\t * The Win32 switch was added for 8.3 to solve a problem with ovals\n\t * leaving traces on bottom and right of 1 pixel. This may not be the\n\t * correct place to solve it, but it works.\n\t */\n\n#ifdef _WIN32\n\tbloat = 1;\n#else\n\tbloat = 0;\n#endif /* _WIN32 */\n    } else {\n#ifdef MAC_OSX_TK\n\t/*\n\t * Mac OS X CoreGraphics needs correct rounding here otherwise it will\n\t * draw outside the bounding box. Probably correct on other platforms\n\t * as well?\n\t */\n\n\tbloat = (int) (width+1.5)/2;\n#else\n\tbloat = (int) (width+1)/2;\n#endif /* MAC_OSX_TK */\n    }\n\n    /*\n     * Special note: the rectangle is always drawn at least 1x1 in size, so\n     * round up the upper coordinates to be at least 1 unit greater than the\n     * lower ones.\n     */\n\n    tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5\n\t    : rectOvalPtr->bbox[0] - .5);\n    rectOvalPtr->header.x1 = tmp - bloat;\n    tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5\n\t    : rectOvalPtr->bbox[1] - .5);\n    rectOvalPtr->header.y1 = tmp - bloat;\n    dtmp = rectOvalPtr->bbox[2];\n    if (dtmp < (rectOvalPtr->bbox[0] + 1)) {\n\tdtmp = rectOvalPtr->bbox[0] + 1;\n    }\n    tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);\n    rectOvalPtr->header.x2 = tmp + bloat;\n    dtmp = rectOvalPtr->bbox[3];\n    if (dtmp < (rectOvalPtr->bbox[1] + 1)) {\n\tdtmp = rectOvalPtr->bbox[1] + 1;\n    }\n    tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);\n    rectOvalPtr->header.y2 = tmp + bloat;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayRectOval --\n *\n *\tThis function is invoked to draw a rectangle or oval item in a given\n *\tdrawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItemPtr is drawn in drawable using the transformation information in\n *\tcanvas.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayRectOval(\n    Tk_Canvas canvas,\t\t/* Canvas that contains item. */\n    Tk_Item *itemPtr,\t\t/* Item to be displayed. */\n    Display *display,\t\t/* Display on which to draw item. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw item. */\n    TCL_UNUSED(int),/* Describes region of canvas that must be */\n    TCL_UNUSED(int),/* redisplayed (not used). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n    short x1, y1, x2, y2;\n    Pixmap fillStipple;\n    Tk_State state = itemPtr->state;\n\n    /*\n     * Compute the screen coordinates of the bounding box for the item. Make\n     * sure that the bbox is at least one pixel large, since some X servers\n     * will die if it isn't.\n     */\n\n    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0],rectOvalPtr->bbox[1],\n\t    &x1, &y1);\n    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],\n\t    &x2, &y2);\n    if (x2 == x1) {\n\n\t/*\n\t * The width of the bounding box corresponds to less than one pixel\n\t * on screen. Adjustment is needed to avoid drawing attempts with zero\n\t * width items (which would draw nothing). The bounding box spans\n\t * either 1 or 2 pixels. Select which pixel will be drawn.\n\t */\n\n\tshort ix1 = (short) (rectOvalPtr->bbox[0]);\n\tshort ix2 = (short) (rectOvalPtr->bbox[2]);\n\n\tif (ix1 == ix2) {\n\n\t    /*\n\t     * x1 and x2 are \"within the same pixel\". Use this pixel.\n\t     * Note: the degenerated case (bbox[0]==bbox[2]) of a completely\n\t     * flat box results in arbitrary selection of the pixel at the\n\t     * right (with positive coordinate) or left (with negative\n\t     * coordinate) of the box. There is no \"best choice\" here.\n\t     */\n\n\t    if (ix1 > 0) {\n\t\tx2 += 1;\n\t    } else {\n\t\tx1 -= 1;\n\t    }\n\t} else {\n\n\t    /*\n\t     * (x1,x2) span two pixels. Select the one with the larger\n\t     * covered \"area\".\n\t     */\n\n\t    if (ix1 > 0) {\n\t\tif ((rectOvalPtr->bbox[2] - ix2) > (ix2 - rectOvalPtr->bbox[0])) {\n\t\t    x2 += 1;\n\t\t} else {\n\t\t    x1 -= 1;\n\t\t}\n\t    } else {\n\t\tif ((rectOvalPtr->bbox[2] - ix1) > (ix1 - rectOvalPtr->bbox[0])) {\n\t\t    x2 += 1;\n\t\t} else {\n\t\t    x1 -= 1;\n\t\t}\n\t    }\n\t}\n    }\n    if (y2 == y1) {\n\n\t/*\n\t * The height of the bounding box corresponds to less than one pixel\n\t * on screen. Adjustment is needed to avoid drawing attempts with zero\n\t * height items (which would draw nothing). The bounding box spans\n\t * either 1 or 2 pixels. Select which pixel will be drawn.\n\t */\n\n\tshort iy1 = (short) (rectOvalPtr->bbox[1]);\n\tshort iy2 = (short) (rectOvalPtr->bbox[3]);\n\n\tif (iy1 == iy2) {\n\n\t    /*\n\t     * y1 and y2 are \"within the same pixel\". Use this pixel.\n\t     * Note: the degenerated case (bbox[1]==bbox[3]) of a completely\n\t     * flat box results in arbitrary selection of the pixel below\n\t     * (with positive coordinate) or above (with negative coordinate)\n\t     * the box. There is no \"best choice\" here.\n\t     */\n\n\t    if (iy1 > 0) {\n\t\ty2 += 1;\n\t    } else {\n\t\ty1 -= 1;\n\t    }\n\t} else {\n\n\t    /*\n\t     * (y1,y2) span two pixels. Select the one with the larger\n\t     * covered \"area\".\n\t     */\n\n\t    if (iy1 > 0) {\n\t\tif ((rectOvalPtr->bbox[3] - iy2) > (iy2 - rectOvalPtr->bbox[1])) {\n\t\t    y2 += 1;\n\t\t} else {\n\t\t    y1 -= 1;\n\t\t}\n\t    } else {\n\t\tif ((rectOvalPtr->bbox[3] - iy1) > (iy1 - rectOvalPtr->bbox[1])) {\n\t\t    y2 += 1;\n\t\t} else {\n\t\t    y1 -= 1;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Display filled part first (if wanted), then outline. If we're\n     * stippling, then modify the stipple offset in the GC. Be sure to reset\n     * the offset when done, since the GC is supposed to be read-only.\n     */\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    fillStipple = rectOvalPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) rectOvalPtr) {\n\tif (rectOvalPtr->activeFillStipple != None) {\n\t    fillStipple = rectOvalPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectOvalPtr->disabledFillStipple != None) {\n\t    fillStipple = rectOvalPtr->disabledFillStipple;\n\t}\n    }\n\n    if (rectOvalPtr->fillGC != NULL) {\n\tif (fillStipple != None) {\n\t    Tk_TSOffset *tsoffset;\n\t    int w = 0, h = 0;\n\n\t    tsoffset = &rectOvalPtr->tsoffset;\n\t    if (tsoffset) {\n\t\tint flags = tsoffset->flags;\n\n\t\tif (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {\n\t\t    Tk_SizeOfBitmap(display, fillStipple, &w, &h);\n\t\t    if (flags & TK_OFFSET_CENTER) {\n\t\t\tw /= 2;\n\t\t    } else {\n\t\t\tw = 0;\n\t\t    }\n\t\t    if (flags & TK_OFFSET_MIDDLE) {\n\t\t\th /= 2;\n\t\t    } else {\n\t\t\th = 0;\n\t\t    }\n\t\t}\n\t\ttsoffset->xoffset -= w;\n\t\ttsoffset->yoffset -= h;\n\t    }\n\t    Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);\n\t    if (tsoffset) {\n\t\ttsoffset->xoffset += w;\n\t\ttsoffset->yoffset += h;\n\t    }\n\t}\n\tif (rectOvalPtr->header.typePtr == &tkRectangleType) {\n\t    XFillRectangle(display, drawable, rectOvalPtr->fillGC,\n\t\t    x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));\n\t} else {\n\t    XFillArc(display, drawable, rectOvalPtr->fillGC,\n\t\t    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),\n\t\t    0, 360*64);\n\t}\n\tif (fillStipple != None) {\n\t    XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);\n\t}\n    }\n\n    if (rectOvalPtr->outline.gc != NULL) {\n\tTk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));\n\tif (rectOvalPtr->header.typePtr == &tkRectangleType) {\n\t    XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,\n\t\t    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));\n\t} else {\n\t    XDrawArc(display, drawable, rectOvalPtr->outline.gc,\n\t\t    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);\n\t}\n\tTk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RectToPoint --\n *\n *\tComputes the distance from a given point to a given rectangle, in\n *\tcanvas units.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the rectangle. If the point\n *\tisn't inside the rectangle then the return value is the distance from\n *\tthe point to the rectangle. If itemPtr is filled, then anywhere in the\n *\tinterior is considered \"inside\"; if itemPtr isn't filled, then\n *\t\"inside\" means only the area occupied by the outline.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nRectToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;\n    double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;\n    double width;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = rectPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (rectPtr->outline.activeWidth>width) {\n\t    width = rectPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectPtr->outline.disabledWidth>0) {\n\t    width = rectPtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * Generate a new larger rectangle that includes the border width, if\n     * there is one.\n     */\n\n    x1 = rectPtr->bbox[0];\n    y1 = rectPtr->bbox[1];\n    x2 = rectPtr->bbox[2];\n    y2 = rectPtr->bbox[3];\n    if (rectPtr->outline.gc != NULL) {\n\tinc = width/2.0;\n\tx1 -= inc;\n\ty1 -= inc;\n\tx2 += inc;\n\ty2 += inc;\n    }\n\n    /*\n     * If the point is inside the rectangle, handle specially: distance is 0\n     * if rectangle is filled, otherwise compute distance to nearest edge of\n     * rectangle and subtract width of edge.\n     */\n\n    if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)\n\t    && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {\n\tif ((rectPtr->fillGC != NULL) || (rectPtr->outline.gc == NULL)) {\n\t    return 0.0;\n\t}\n\txDiff = pointPtr[0] - x1;\n\ttmp = x2 - pointPtr[0];\n\tif (tmp < xDiff) {\n\t    xDiff = tmp;\n\t}\n\tyDiff = pointPtr[1] - y1;\n\ttmp = y2 - pointPtr[1];\n\tif (tmp < yDiff) {\n\t    yDiff = tmp;\n\t}\n\tif (yDiff < xDiff) {\n\t    xDiff = yDiff;\n\t}\n\txDiff -= width;\n\tif (xDiff < 0.0) {\n\t    return 0.0;\n\t}\n\treturn xDiff;\n    }\n\n    /*\n     * Point is outside rectangle.\n     */\n\n    if (pointPtr[0] < x1) {\n\txDiff = x1 - pointPtr[0];\n    } else if (pointPtr[0] > x2)  {\n\txDiff = pointPtr[0] - x2;\n    } else {\n\txDiff = 0;\n    }\n\n    if (pointPtr[1] < y1) {\n\tyDiff = y1 - pointPtr[1];\n    } else if (pointPtr[1] > y2)  {\n\tyDiff = pointPtr[1] - y2;\n    } else {\n\tyDiff = 0;\n    }\n\n    return hypot(xDiff, yDiff);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * OvalToPoint --\n *\n *\tComputes the distance from a given point to a given oval, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point whose x and y coordinates are\n *\tcoordPtr[0] and coordPtr[1] is inside the oval. If the point isn't\n *\tinside the oval then the return value is the distance from the point\n *\tto the oval. If itemPtr is filled, then anywhere in the interior is\n *\tconsidered \"inside\"; if itemPtr isn't filled, then \"inside\" means only\n *\tthe area occupied by the outline.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic double\nOvalToPoint(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against point. */\n    double *pointPtr)\t\t/* Pointer to x and y coordinates. */\n{\n    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;\n    double width;\n    int filled;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = (double) ovalPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (ovalPtr->outline.activeWidth>width) {\n\t    width = (double) ovalPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (ovalPtr->outline.disabledWidth>0) {\n\t    width = (double) ovalPtr->outline.disabledWidth;\n\t}\n    }\n\n\n    filled = ovalPtr->fillGC != NULL;\n    if (ovalPtr->outline.gc == NULL) {\n\twidth = 0.0;\n\tfilled = 1;\n    }\n    return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RectToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangle.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nRectToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against rectangle. */\n    double *areaPtr)\t\t/* Pointer to array of four coordinates (x1,\n\t\t\t\t * y1, x2, y2) describing rectangular area. */\n{\n    RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;\n    double halfWidth;\n    double width;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = rectPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (rectPtr->outline.activeWidth > width) {\n\t    width = rectPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectPtr->outline.disabledWidth > 0) {\n\t    width = rectPtr->outline.disabledWidth;\n\t}\n    }\n\n    halfWidth = width/2.0;\n    if (rectPtr->outline.gc == NULL) {\n\thalfWidth = 0.0;\n    }\n\n    if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))\n\t    || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))\n\t    || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))\n\t    || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {\n\treturn -1;\n    }\n    if ((rectPtr->fillGC == NULL) && (rectPtr->outline.gc != NULL)\n\t    && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))\n\t    && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))\n\t    && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))\n\t    && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {\n\treturn -1;\n    }\n    if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))\n\t    && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))\n\t    && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))\n\t    && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * OvalToArea --\n *\n *\tThis function is called to determine whether an item lies entirely\n *\tinside, entirely outside, or overlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the item is entirely outside the area given by\n *\trectPtr, 0 if it overlaps, and 1 if it is entirely inside the given\n *\tarea.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nOvalToArea(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item to check against oval. */\n    double *areaPtr)\t\t/* Pointer to array of four coordinates (x1,\n\t\t\t\t * y1, x2, y2) describing rectangular area. */\n{\n    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;\n    double oval[4], halfWidth, width;\n    int result;\n    Tk_State state = itemPtr->state;\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n\n    width = ovalPtr->outline.width;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (ovalPtr->outline.activeWidth > width) {\n\t    width = ovalPtr->outline.activeWidth;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (ovalPtr->outline.disabledWidth > 0) {\n\t    width = ovalPtr->outline.disabledWidth;\n\t}\n    }\n\n    /*\n     * Expand the oval to include the width of the outline, if any.\n     */\n\n    halfWidth = width/2.0;\n    if (ovalPtr->outline.gc == NULL) {\n\thalfWidth = 0.0;\n    }\n    oval[0] = ovalPtr->bbox[0] - halfWidth;\n    oval[1] = ovalPtr->bbox[1] - halfWidth;\n    oval[2] = ovalPtr->bbox[2] + halfWidth;\n    oval[3] = ovalPtr->bbox[3] + halfWidth;\n\n    result = TkOvalToArea(oval, areaPtr);\n\n    /*\n     * If the rectangle appears to overlap the oval and the oval isn't filled,\n     * do one more check to see if perhaps all four of the rectangle's corners\n     * are totally inside the oval's unfilled center, in which case we should\n     * return \"outside\".\n     */\n\n    if ((result == 0) && (ovalPtr->outline.gc != NULL)\n\t    && (ovalPtr->fillGC == NULL)) {\n\tdouble centerX, centerY, height;\n\tdouble xDelta1, yDelta1, xDelta2, yDelta2;\n\n\tcenterX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;\n\tcenterY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;\n\twidth = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;\n\theight = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;\n\txDelta1 = (areaPtr[0] - centerX)/width;\n\txDelta1 *= xDelta1;\n\tyDelta1 = (areaPtr[1] - centerY)/height;\n\tyDelta1 *= yDelta1;\n\txDelta2 = (areaPtr[2] - centerX)/width;\n\txDelta2 *= xDelta2;\n\tyDelta2 = (areaPtr[3] - centerY)/height;\n\tyDelta2 *= yDelta2;\n\tif (((xDelta1 + yDelta1) < 1.0)\n\t\t&& ((xDelta1 + yDelta2) < 1.0)\n\t\t&& ((xDelta2 + yDelta1) < 1.0)\n\t\t&& ((xDelta2 + yDelta2) < 1.0)) {\n\t    return -1;\n\t}\n    }\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RotateRectOval --\n *\n *\tThis function is invoked to rotate a rectangle or oval item's\n *\tcoordinates. It works by rotating a computed point in the centre of\n *\tthe bounding box, NOT by rotating the corners of the bounding box.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the rectangle or oval is rotated by angleRad about\n *\t(originX, originY), and the bounding box is updated in the generic\n *\tpart of the item structure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRotateRectOval(\n    Tk_Canvas canvas,\t\t/* Canvas containing rectangle. */\n    Tk_Item *itemPtr,\t\t/* Rectangle to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to rotate rect. */\n    double angleRad)\t\t/* Amount to scale in X direction. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n    double newX, newY, oldX, oldY;\n\n    /*\n     * Compute the centre of the box, then rotate that about the origin.\n     */\n\n    newX = oldX = (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2]) / 2.0;\n    newY = oldY = (rectOvalPtr->bbox[1] + rectOvalPtr->bbox[3]) / 2.0;\n    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),\n\t    &newX, &newY);\n\n    /*\n     * Apply the translation to the box.\n     */\n\n    rectOvalPtr->bbox[0] += newX - oldX;\n    rectOvalPtr->bbox[1] += newY - oldY;\n    rectOvalPtr->bbox[2] += newX - oldX;\n    rectOvalPtr->bbox[3] += newY - oldY;\n    ComputeRectOvalBbox(canvas, rectOvalPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleRectOval --\n *\n *\tThis function is invoked to rescale a rectangle or oval item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe rectangle or oval referred to by itemPtr is rescaled so that the\n *\tfollowing transformation is applied to all point coordinates:\n *\t\tx' = originX + scaleX*(x-originX)\n *\t\ty' = originY + scaleY*(y-originY)\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleRectOval(\n    Tk_Canvas canvas,\t\t/* Canvas containing rectangle. */\n    Tk_Item *itemPtr,\t\t/* Rectangle to be scaled. */\n    double originX, double originY,\n\t\t\t\t/* Origin about which to scale rect. */\n    double scaleX,\t\t/* Amount to scale in X direction. */\n    double scaleY)\t\t/* Amount to scale in Y direction. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n\n    rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);\n    rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);\n    rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);\n    rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);\n    ComputeRectOvalBbox(canvas, rectOvalPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TranslateRectOval --\n *\n *\tThis function is called to move a rectangle or oval by a given amount.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe position of the rectangle or oval is offset by (xDelta, yDelta),\n *\tand the bounding box is updated in the generic part of the item\n *\tstructure.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTranslateRectOval(\n    Tk_Canvas canvas,\t\t/* Canvas containing item. */\n    Tk_Item *itemPtr,\t\t/* Item that is being moved. */\n    double deltaX, double deltaY)\n\t\t\t\t/* Amount by which item is to be moved. */\n{\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n\n    rectOvalPtr->bbox[0] += deltaX;\n    rectOvalPtr->bbox[1] += deltaY;\n    rectOvalPtr->bbox[2] += deltaX;\n    rectOvalPtr->bbox[3] += deltaY;\n    ComputeRectOvalBbox(canvas, rectOvalPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RectOvalToPostscript --\n *\n *\tThis function is called to generate Postscript for rectangle and oval\n *\titems.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If an error occurs in\n *\tgenerating Postscript then an error message is left in the interp's\n *\tresult, replacing whatever used to be there. If no error occurs, then\n *\tPostscript for the rectangle is appended to the result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nRectOvalToPostscript(\n    Tcl_Interp *interp,\t\t/* Interpreter for error reporting. */\n    Tk_Canvas canvas,\t\t/* Information about overall canvas. */\n    Tk_Item *itemPtr,\t\t/* Item for which Postscript is wanted. */\n    TCL_UNUSED(int))\t\t/* 1 means this is a prepass to collect font\n\t\t\t\t * information; 0 means final Postscript is\n\t\t\t\t * being created. */\n{\n    Tcl_Obj *pathObj, *psObj;\n    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;\n    double y1, y2;\n    XColor *color;\n    XColor *fillColor;\n    Pixmap fillStipple;\n    Tk_State state = itemPtr->state;\n    Tcl_InterpState interpState;\n\n    y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);\n    y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);\n\n    /*\n     * Generate a string that creates a path for the rectangle or oval. This\n     * is the only part of the function's code that is type-specific.\n     */\n\n    if (rectOvalPtr->header.typePtr == &tkRectangleType) {\n\tpathObj = Tcl_ObjPrintf(\n\t\t\"%.15g %.15g moveto \"\n\t\t\"%.15g 0 rlineto \"\n\t\t\"0 %.15g rlineto \"\n\t\t\"%.15g 0 rlineto \"\n\t\t\"closepath\\n\",\n\t\trectOvalPtr->bbox[0], y1,\n\t\trectOvalPtr->bbox[2]-rectOvalPtr->bbox[0],\n\t\ty2-y1,\n\t\trectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);\n    } else {\n\tpathObj = Tcl_ObjPrintf(\n\t\t\"matrix currentmatrix\\n\"\n\t\t\"%.15g %.15g translate \"\n\t\t\"%.15g %.15g scale \"\n\t\t\"1 0 moveto 0 0 1 0 360 arc\\n\"\n\t\t\"setmatrix\\n\",\n\t\t(rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,\n\t\t(rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);\n    }\n\n    if (state == TK_STATE_NULL) {\n\tstate = Canvas(canvas)->canvas_state;\n    }\n    color = rectOvalPtr->outline.color;\n    fillColor = rectOvalPtr->fillColor;\n    fillStipple = rectOvalPtr->fillStipple;\n    if (Canvas(canvas)->currentItemPtr == itemPtr) {\n\tif (rectOvalPtr->outline.activeColor!=NULL) {\n\t    color = rectOvalPtr->outline.activeColor;\n\t}\n\tif (rectOvalPtr->activeFillColor!=NULL) {\n\t    fillColor = rectOvalPtr->activeFillColor;\n\t}\n\tif (rectOvalPtr->activeFillStipple!=None) {\n\t    fillStipple = rectOvalPtr->activeFillStipple;\n\t}\n    } else if (state == TK_STATE_DISABLED) {\n\tif (rectOvalPtr->outline.disabledColor!=NULL) {\n\t    color = rectOvalPtr->outline.disabledColor;\n\t}\n\tif (rectOvalPtr->disabledFillColor!=NULL) {\n\t    fillColor = rectOvalPtr->disabledFillColor;\n\t}\n\tif (rectOvalPtr->disabledFillStipple!=None) {\n\t    fillStipple = rectOvalPtr->disabledFillStipple;\n\t}\n    }\n\n    /*\n     * Make our working space.\n     */\n\n    psObj = Tcl_NewObj();\n    interpState = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * First draw the filled area of the rectangle.\n     */\n\n    if (fillColor != NULL) {\n\tTcl_AppendObjToObj(psObj, pathObj);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsColor(interp, canvas, fillColor);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\n\tif (fillStipple != None) {\n\t    Tcl_AppendToObj(psObj, \"clip \", TCL_INDEX_NONE);\n\n\t    Tcl_ResetResult(interp);\n\t    Tk_CanvasPsStipple(interp, canvas, fillStipple);\n\t    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n\t    if (color != NULL) {\n\t\tTcl_AppendToObj(psObj, \"grestore gsave\\n\", TCL_INDEX_NONE);\n\t    }\n\t} else {\n\t    Tcl_AppendToObj(psObj, \"fill\\n\", TCL_INDEX_NONE);\n\t}\n    }\n\n    /*\n     * Now draw the outline, if there is one.\n     */\n\n    if (color != NULL) {\n\tTcl_AppendObjToObj(psObj, pathObj);\n\tTcl_AppendToObj(psObj, \"0 setlinejoin 2 setlinecap\\n\", TCL_INDEX_NONE);\n\n\tTcl_ResetResult(interp);\n\tTk_CanvasPsOutline(canvas, itemPtr, &rectOvalPtr->outline);\n\tTcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));\n    }\n\n    /*\n     * Plug the accumulated postscript back into the result.\n     */\n\n    (void) Tcl_RestoreInterpState(interp, interpState);\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n    Tcl_DecrRefCount(pathObj);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkScale.c",
    "content": "/*\n * tkScale.c --\n *\n *\tThis module implements a scale widgets for the Tk toolkit. A scale\n *\tdisplays a slider that can be adjusted to change a value; it also\n *\tdisplays numeric labels and a textual label, if desired.\n *\n *\tThe modifications to use floating-point values are based on an\n *\timplementation by Paul Mackerras. The -variable option is due to\n *\tHenning Schulzrinne. All of these are used with permission.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkScale.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The following table defines the legal values for the -orient option. It is\n * used together with the \"enum orient\" declaration in tkScale.h.\n */\n\nstatic const char *const orientStrings[] = {\n    \"horizontal\", \"vertical\", NULL\n};\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_SCALE_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, activeBorder),\n\t0, DEF_SCALE_ACTIVE_BG_MONO, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_SCALE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, bgBorder),\n\t0, DEF_SCALE_BG_MONO, 0},\n    {TK_OPTION_DOUBLE, \"-bigincrement\", \"bigIncrement\", \"BigIncrement\",\n\tDEF_SCALE_BIG_INCREMENT, TCL_INDEX_NONE, offsetof(TkScale, bigIncrement),\n\t0, 0, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_SCALE_BORDER_WIDTH, offsetof(TkScale, borderWidthObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_SCALE_COMMAND, offsetof(TkScale, commandObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_SCALE_CURSOR, TCL_INDEX_NONE, offsetof(TkScale, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INT, \"-digits\", \"digits\", \"Digits\",\n\tDEF_SCALE_DIGITS, TCL_INDEX_NONE, offsetof(TkScale, digits),\n\t0, 0, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_SCALE_FONT, TCL_INDEX_NONE, offsetof(TkScale, tkfont), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_SCALE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, textColorPtr), 0,\n\tDEF_SCALE_FG_MONO, 0},\n    {TK_OPTION_DOUBLE, \"-from\", \"from\", \"From\", DEF_SCALE_FROM, TCL_INDEX_NONE,\n\toffsetof(TkScale, fromValue), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_SCALE_HIGHLIGHT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkScale, highlightBorder),\n\t0, DEF_SCALE_HIGHLIGHT_BG_MONO, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_SCALE_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkScale, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_SCALE_HIGHLIGHT_WIDTH, offsetof(TkScale, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-label\", \"label\", \"Label\",\n\tDEF_SCALE_LABEL, offsetof(TkScale, labelObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-length\", \"length\", \"Length\",\n\tDEF_SCALE_LENGTH, offsetof(TkScale, lengthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\",\n\tDEF_SCALE_ORIENT, TCL_INDEX_NONE, offsetof(TkScale, orient),\n\tTK_OPTION_ENUM_VAR, orientStrings, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_SCALE_RELIEF, TCL_INDEX_NONE, offsetof(TkScale, relief), 0, 0, 0},\n    {TK_OPTION_INT, \"-repeatdelay\", \"repeatDelay\", \"RepeatDelay\",\n\tDEF_SCALE_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(TkScale, repeatDelay),\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-repeatinterval\", \"repeatInterval\", \"RepeatInterval\",\n\tDEF_SCALE_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(TkScale, repeatInterval),\n\t0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-resolution\", \"resolution\", \"Resolution\",\n\tDEF_SCALE_RESOLUTION, TCL_INDEX_NONE, offsetof(TkScale, resolution),\n\t0, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-showvalue\", \"showValue\", \"ShowValue\",\n\tDEF_SCALE_SHOW_VALUE, TCL_INDEX_NONE, offsetof(TkScale, showValue),\n\tTK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_PIXELS, \"-sliderlength\", \"sliderLength\", \"SliderLength\",\n\tDEF_SCALE_SLIDER_LENGTH, offsetof(TkScale, sliderLengthObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_RELIEF, \"-sliderrelief\", \"sliderRelief\", \"SliderRelief\",\n\tDEF_SCALE_SLIDER_RELIEF, TCL_INDEX_NONE, offsetof(TkScale, sliderRelief),\n\t0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_SCALE_STATE, TCL_INDEX_NONE, offsetof(TkScale, state),\n\tTK_OPTION_ENUM_VAR, tkStateStrings, 0},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_SCALE_TAKE_FOCUS, offsetof(TkScale, takeFocusPtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_DOUBLE, \"-tickinterval\", \"tickInterval\", \"TickInterval\",\n\tDEF_SCALE_TICK_INTERVAL, TCL_INDEX_NONE, offsetof(TkScale, tickInterval),\n\t0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-to\", \"to\", \"To\",\n\tDEF_SCALE_TO, TCL_INDEX_NONE, offsetof(TkScale, toValue), 0, 0, 0},\n    {TK_OPTION_COLOR, \"-troughcolor\", \"troughColor\", \"Background\",\n\tDEF_SCALE_TROUGH_COLOR, TCL_INDEX_NONE, offsetof(TkScale, troughColorPtr),\n\t0, DEF_SCALE_TROUGH_MONO, 0},\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\tDEF_SCALE_VARIABLE, offsetof(TkScale, varNamePtr), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\",\n\tDEF_SCALE_WIDTH, offsetof(TkScale, widthObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}\n};\n\n/*\n * The following tables define the scale widget commands and map the indexes\n * into the string tables into a single enumerated type used to dispatch the\n * scale widget command.\n */\n\nstatic const char *const commandNames[] = {\n    \"cget\", \"configure\", \"coords\", \"get\", \"identify\", \"set\", NULL\n};\n\nenum command {\n    COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,\n    COMMAND_IDENTIFY, COMMAND_SET\n};\n\n/*\n * Forward declarations for procedures defined later in this file:\n */\n\nstatic void\t\tComputeFormat(TkScale *scalePtr, int forTicks);\nstatic void\t\tComputeScaleGeometry(TkScale *scalePtr);\nstatic int\t\tConfigureScale(Tcl_Interp *interp, TkScale *scalePtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tDestroyScale(void *memPtr);\nstatic double\t\tMaxTickRoundingError(TkScale *scalePtr,\n\t\t\t    double tickResolution);\nstatic void\t\tScaleCmdDeletedProc(void *clientData);\nstatic void\t\tScaleEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic char *\t\tScaleVarProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *name1,\n\t\t\t    const char *name2, int flags);\nstatic Tcl_ObjCmdProc2 ScaleWidgetObjCmd;\nstatic void\t\tScaleWorldChanged(void *instanceData);\nstatic void\t\tScaleSetVariable(TkScale *scalePtr);\n\n/*\n * The structure below defines scale class behavior by means of procedures\n * that can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs scaleClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    ScaleWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleDigit, ScaleMax, ScaleMin, ScaleRound --\n *\n *\tSimple math helper functions, designed to be automatically inlined by\n *\tthe compiler most of the time.\n *\n *--------------------------------------------------------------\n */\n\nstatic inline int\nScaleDigit(\n    double value)\n{\n    return (int) floor(log10(fabs(value)));\n}\n\nstatic inline double\nScaleMax(\n    double a,\n    double b)\n{\n    return (a > b) ? a : b;\n}\n\nstatic inline double\nScaleMin(\n    double a,\n    double b)\n{\n    return (a < b) ? a : b;\n}\n\nstatic inline int\nScaleRound(\n    double value)\n{\n    return (int) floor(value + 0.5);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ScaleObjCmd --\n *\n *\tThis procedure is invoked to process the \"scale\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ScaleObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    TkScale *scalePtr;\n    Tk_OptionTable optionTable;\n    Tk_Window tkwin;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    Tk_SetClass(tkwin, \"Scale\");\n    scalePtr = TkpCreateScale(tkwin);\n\n    /*\n     * Initialize fields that won't be initialized by ConfigureScale, or which\n     * ConfigureScale expects to have reasonable values (e.g. resource\n     * pointers).\n     */\n\n    scalePtr->tkwin\t\t= tkwin;\n    scalePtr->display\t\t= Tk_Display(tkwin);\n    scalePtr->interp\t\t= interp;\n    scalePtr->widgetCmd\t\t= Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(scalePtr->tkwin), ScaleWidgetObjCmd,\n\t    scalePtr, ScaleCmdDeletedProc);\n    scalePtr->optionTable\t= optionTable;\n    scalePtr->orient\t\t= ORIENT_VERTICAL;\n    scalePtr->widthObj\t\t= NULL;\n    scalePtr->lengthObj\t\t= NULL;\n    scalePtr->value\t\t= 0.0;\n    scalePtr->varNamePtr\t= NULL;\n    scalePtr->fromValue\t\t= 0.0;\n    scalePtr->toValue\t\t= 0.0;\n    scalePtr->tickInterval\t= 0.0;\n    scalePtr->resolution\t= 1.0;\n    scalePtr->digits\t\t= 0;\n    scalePtr->bigIncrement\t= 0.0;\n    scalePtr->commandObj\t= NULL;\n    scalePtr->repeatDelay\t= 0;\n    scalePtr->repeatInterval\t= 0;\n    scalePtr->labelObj\t\t= NULL;\n    scalePtr->state\t\t= STATE_NORMAL;\n    scalePtr->borderWidthObj\t= NULL;\n    scalePtr->bgBorder\t\t= NULL;\n    scalePtr->activeBorder\t= NULL;\n    scalePtr->sliderRelief\t= TK_RELIEF_RAISED;\n    scalePtr->troughColorPtr\t= NULL;\n    scalePtr->troughGC\t\t= NULL;\n    scalePtr->copyGC\t\t= NULL;\n    scalePtr->tkfont\t\t= NULL;\n    scalePtr->textColorPtr\t= NULL;\n    scalePtr->textGC\t\t= NULL;\n    scalePtr->relief\t\t= TK_RELIEF_FLAT;\n    scalePtr->highlightWidthObj\t= NULL;\n    scalePtr->highlightBorder\t= NULL;\n    scalePtr->highlightColorPtr\t= NULL;\n    scalePtr->inset\t\t= 0;\n    scalePtr->sliderLengthObj\t= NULL;\n    scalePtr->showValue\t\t= false;\n    scalePtr->horizLabelY\t= 0;\n    scalePtr->horizValueY\t= 0;\n    scalePtr->horizTroughY\t= 0;\n    scalePtr->horizTickY\t= 0;\n    scalePtr->vertTickRightX\t= 0;\n    scalePtr->vertValueRightX\t= 0;\n    scalePtr->vertTroughX\t= 0;\n    scalePtr->vertLabelX\t= 0;\n    scalePtr->fontHeight\t= 0;\n    scalePtr->cursor\t\t= NULL;\n    scalePtr->takeFocusPtr\t= NULL;\n    scalePtr->flags\t\t= NEVER_SET;\n\n\n\n    Tk_SetClassProcs(scalePtr->tkwin, &scaleClass, scalePtr);\n    Tk_CreateEventHandler(scalePtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    ScaleEventProc, scalePtr);\n\n    if ((Tk_InitOptions(interp, scalePtr, optionTable, tkwin)\n\t    != TCL_OK) ||\n\t    (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {\n\tTk_DestroyWindow(scalePtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * The widget was just created, no command callback must be invoked.\n     */\n\n    scalePtr->flags &= ~INVOKE_COMMAND;\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(scalePtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleWidgetObjCmd --\n *\n *\tThis procedure is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nScaleWidgetObjCmd(\n    void *clientData,\t/* Information about scale widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    TkScale *scalePtr = (TkScale *)clientData;\n    Tcl_Obj *objPtr;\n    int index, result;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames,\n\t    sizeof(char *), \"option\", 0, &index);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    Tcl_Preserve(scalePtr);\n\n    switch (index) {\n    case COMMAND_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"cget option\");\n\t    goto error;\n\t}\n\tobjPtr = Tk_GetOptionValue(interp, scalePtr,\n\t\tscalePtr->optionTable, objv[2], scalePtr->tkwin);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n    case COMMAND_CONFIGURE:\n\tif (objc <= 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, scalePtr,\n\t\t    scalePtr->optionTable,\n\t\t    (objc == 3) ? objv[2] : NULL, scalePtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureScale(interp, scalePtr, objc-2, objv+2);\n\t}\n\tbreak;\n    case COMMAND_COORDS: {\n\tint x, y, width, borderWidth;\n\tdouble value;\n\tTcl_Obj *coords[2];\n\n\tif ((objc != 2) && (objc != 3)) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"coords ?value?\");\n\t    goto error;\n\t}\n\tif (objc == 3) {\n\t    if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t} else {\n\t    value = scalePtr->value;\n\t}\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->widthObj, &width);\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n\tif (scalePtr->orient == ORIENT_VERTICAL) {\n\t    x = scalePtr->vertTroughX + width/2\n\t\t    + borderWidth;\n\t    y = TkScaleValueToPixel(scalePtr, value);\n\t} else {\n\t    x = TkScaleValueToPixel(scalePtr, value);\n\t    y = scalePtr->horizTroughY + width/2\n\t\t    + borderWidth;\n\t}\n\tcoords[0] = Tcl_NewWideIntObj(x);\n\tcoords[1] = Tcl_NewWideIntObj(y);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, coords));\n\tbreak;\n    }\n    case COMMAND_GET: {\n\tdouble value;\n\tint x, y;\n\n\tif ((objc != 2) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"get ?x y?\");\n\t    goto error;\n\t}\n\tif (objc == 2) {\n\t    value = scalePtr->value;\n\t} else {\n\t    if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) ||\n\t\t    (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t\tgoto error;\n\t    }\n\t    value = TkScalePixelToValue(scalePtr, x, y);\n\t}\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value));\n\tbreak;\n    }\n    case COMMAND_IDENTIFY: {\n\tint x, y;\n\tconst char *zone = \"\";\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"identify x y\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    goto error;\n\t}\n\tswitch (TkpScaleElement(scalePtr, x, y)) {\n\tcase TROUGH1:\tzone = \"trough1\"; break;\n\tcase SLIDER:\tzone = \"slider\";  break;\n\tcase TROUGH2:\tzone = \"trough2\"; break;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(zone, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case COMMAND_SET: {\n\tdouble value;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"set value\");\n\t    goto error;\n\t}\n\tif (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (scalePtr->state != STATE_DISABLED) {\n\t    TkScaleSetValue(scalePtr, value, 1, 1);\n\t}\n\tbreak;\n    }\n    }\n    Tcl_Release(scalePtr);\n    return result;\n\n  error:\n    Tcl_Release(scalePtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyScale --\n *\n *\tThis procedure is invoked by Tcl_EventuallyFree or Tcl_Release to\n *\tclean up the internal structure of a button at a safe time (when\n *\tno-one is using it anymore).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEverything associated with the scale is freed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyScale(\n    void *memPtr)\t/* Info about scale widget. */\n{\n    TkScale *scalePtr = (TkScale *) memPtr;\n\n    scalePtr->flags |= SCALE_DELETED;\n\n    Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);\n    if (scalePtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(TkpDisplayScale, scalePtr);\n    }\n\n    /*\n     * Free up all the stuff that requires special handling, then let\n     * Tk_FreeOptions handle all the standard option-related stuff.\n     */\n\n    if (scalePtr->varNamePtr != NULL) {\n\tTcl_UntraceVar2(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tScaleVarProc, scalePtr);\n    }\n    if (scalePtr->troughGC != NULL) {\n\tTk_FreeGC(scalePtr->display, scalePtr->troughGC);\n    }\n    if (scalePtr->copyGC != NULL) {\n\tTk_FreeGC(scalePtr->display, scalePtr->copyGC);\n    }\n    if (scalePtr->textGC != NULL) {\n\tTk_FreeGC(scalePtr->display, scalePtr->textGC);\n    }\n    Tk_FreeConfigOptions(scalePtr, scalePtr->optionTable,\n\t    scalePtr->tkwin);\n    scalePtr->tkwin = NULL;\n    TkpDestroyScale(scalePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureScale --\n *\n *\tThis procedure is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a scale\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor scalePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureScale(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkScale *scalePtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in objv. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    Tk_SavedOptions savedOptions;\n    Tcl_Obj *errorResult = NULL;\n    int error, highlightWidth, borderWidth;\n    double varValue;\n\n    /*\n     * Eliminate any existing trace on a variable monitored by the scale.\n     */\n\n    if (scalePtr->varNamePtr != NULL) {\n\tTcl_UntraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tScaleVarProc, scalePtr);\n    }\n\n    for (error = 0; error <= 1; error++) {\n\tif (!error) {\n\t    /*\n\t     * First pass: set options to new values.\n\t     */\n\n\t    if (Tk_SetOptions(interp, scalePtr,\n\t\t    scalePtr->optionTable, objc, objv, scalePtr->tkwin,\n\t\t    &savedOptions, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t} else {\n\t    /*\n\t     * Second pass: restore options to old values.\n\t     */\n\n\t    errorResult = Tcl_GetObjResult(interp);\n\t    Tcl_IncrRefCount(errorResult);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t}\n\n\t/*\n\t * If the scale is tied to the value of a variable, then set the\n\t * scale's value from the value of the variable, if it exists and it\n\t * holds a valid double value.\n\t */\n\n\tif (scalePtr->varNamePtr != NULL) {\n\t    double value;\n\t    Tcl_Obj *valuePtr;\n\n\t    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,\n\t\t    TCL_GLOBAL_ONLY);\n\t    if ((valuePtr != NULL) &&\n\t\t    (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {\n\t\tscalePtr->value = TkRoundValueToResolution(scalePtr, value);\n\t    }\n\t}\n\n\t/*\n\t * The fromValue shall not be rounded to the resolution, but the\n\t * toValue and tickInterval do.\n\t */\n\n\tscalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);\n\tscalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,\n\t\tscalePtr->tickInterval);\n\n\t/*\n\t * Make sure that the tick interval has the right sign so that\n\t * addition moves from fromValue to toValue.\n\t */\n\n\tif ((scalePtr->tickInterval < 0)\n\t\t^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) {\n\t    scalePtr->tickInterval = -scalePtr->tickInterval;\n\t}\n\n\tComputeFormat(scalePtr, 0);\n\tComputeFormat(scalePtr, 1);\n\n\tTk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);\n\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->highlightWidthObj, &highlightWidth);\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n\tscalePtr->inset = highlightWidth + borderWidth;\n\tbreak;\n    }\n    if (!error) {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n\n    /*\n     * Set the scale value to itself; all this does is to make sure that the\n     * scale's value is within the new acceptable range for the scale. We\n     * don't set the var here because we need to make special checks for\n     * possibly changed varNamePtr.\n     */\n\n    TkScaleSetValue(scalePtr, scalePtr->value, 0, 1);\n\n    /*\n     * Reestablish the variable trace, if it is needed.\n     */\n\n    if (scalePtr->varNamePtr != NULL) {\n\tTcl_Obj *valuePtr;\n\n\t/*\n\t * Set the associated variable only when the new value differs from\n\t * the current value, or the variable doesn't yet exist.\n\t */\n\n\tvaluePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,\n\t\tTCL_GLOBAL_ONLY);\n\tif ((valuePtr == NULL) || (Tcl_GetDoubleFromObj(NULL,\n\t\tvaluePtr, &varValue) != TCL_OK)) {\n\t    ScaleSetVariable(scalePtr);\n\t} else {\n\t    char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE];\n\n\t    Tcl_PrintDouble(NULL, varValue, varString);\n\t    Tcl_PrintDouble(NULL, scalePtr->value, scaleString);\n\t    if (strcmp(varString, scaleString)) {\n\t\tScaleSetVariable(scalePtr);\n\t    }\n\t}\n\tTcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tScaleVarProc, scalePtr);\n    }\n\n    ScaleWorldChanged(scalePtr);\n    if (error) {\n\tTcl_SetObjResult(interp, errorResult);\n\tTcl_DecrRefCount(errorResult);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ScaleWorldChanged --\n *\n *\tThis procedure is called when the world has changed in some way and\n *\tthe widget needs to recompute all its graphics contexts and determine\n *\tits new geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tScale will be relayed out and redisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nScaleWorldChanged(\n    void *instanceData)\t/* Information about widget. */\n{\n    XGCValues gcValues;\n    GC gc;\n    TkScale *scalePtr = (TkScale *)instanceData;\n    int highlightWidth, borderWidth;\n\n    gcValues.foreground = scalePtr->troughColorPtr->pixel;\n    gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);\n    if (scalePtr->troughGC != NULL) {\n\tTk_FreeGC(scalePtr->display, scalePtr->troughGC);\n    }\n    scalePtr->troughGC = gc;\n\n    gcValues.font = Tk_FontId(scalePtr->tkfont);\n    gcValues.foreground = scalePtr->textColorPtr->pixel;\n    gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);\n    if (scalePtr->textGC != NULL) {\n\tTk_FreeGC(scalePtr->display, scalePtr->textGC);\n    }\n    scalePtr->textGC = gc;\n\n    if (scalePtr->copyGC == NULL) {\n\tgcValues.graphics_exposures = False;\n\tscalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,\n\t\t&gcValues);\n    }\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n    scalePtr->inset = highlightWidth + borderWidth;\n\n    /*\n     * Recompute display-related information, and let the geometry manager\n     * know how much space is needed now.\n     */\n\n    ComputeScaleGeometry(scalePtr);\n\n    TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);\n}\n\f\n /*\n  *----------------------------------------------------------------------\n  *\n  * MaxTickRoundingError --\n  *\n  *      Given the separation between values that can be displayed on ticks,\n  *      this calculates the maximum magnitude of error for the displayed\n  *      value. Tries to be clever by working out the increment in error\n  *      between ticks rather than testing all of them, so may overestimate\n  *      error if it is greater than 0.25 x the value separation.\n  *\n  * Results:\n  *      Maximum error magnitude of tick numbers.\n  *\n  * Side effects:\n  *      None.\n  *\n  *----------------------------------------------------------------------\n  */\n\nstatic double\nMaxTickRoundingError(\n    TkScale *scalePtr,\t\t/* Information about scale widget. */\n    double tickResolution)      /* Separation between displayable values. */\n{\n    double tickPosn, firstTickError, lastTickError, intervalError;\n    int tickCount;\n\n    /*\n     * Compute the error for each tick-related measure.\n     */\n\n    tickPosn = scalePtr->fromValue / tickResolution;\n    firstTickError = tickPosn - ScaleRound(tickPosn);\n\n    tickPosn = scalePtr->tickInterval / tickResolution;\n    intervalError = tickPosn - ScaleRound(tickPosn);\n\n    tickCount = (int) ((scalePtr->toValue - scalePtr->fromValue) /\n\t    scalePtr->tickInterval);\t/* not including first */\n    lastTickError = ScaleMin(0.5,\n\t    fabs(firstTickError + tickCount * intervalError));\n\n    /*\n     * Compute the maximum cumulative rounding error.\n     */\n\n    return ScaleMax(fabs(firstTickError), lastTickError) * tickResolution;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeFormat --\n *\n *\tThis procedure is invoked to recompute the \"valueFormat\" or\n *\t\"tickFormat\" field of a scale's widget record, which determines how\n *\tthe value of the scale or one of its ticks is converted to a string.\n *\n * Results:\n *\tNone.\n *\n * Side effects: The valueFormat or tickFormat field of scalePtr is modified.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nComputeFormat(\n    TkScale *scalePtr,\t\t/* Information about scale widget. */\n    int forTicks)               /* Do for ticks rather than value */\n{\n    double maxValue, x;\n    int mostSigDigit, numDigits, leastSigDigit, afterDecimal;\n    int eDigits, fDigits;\n\n    /*\n     * Compute the displacement from the decimal of the most significant digit\n     * required for any number in the scale's range.\n     */\n\n    maxValue = fabs(scalePtr->fromValue);\n    x = fabs(scalePtr->toValue);\n    if (x > maxValue) {\n\tmaxValue = x;\n    }\n    if (maxValue == 0) {\n\tmaxValue = 1;\n    }\n    mostSigDigit = ScaleDigit(maxValue);\n\n    if (forTicks) {\n\t/*\n\t * Display only enough digits to ensure adjacent ticks have different\n\t * values.\n\t */\n\n\tif (scalePtr->tickInterval != 0) {\n\t    leastSigDigit = ScaleDigit(scalePtr->tickInterval);\n\n\t    /*\n\t     * Now add more digits until max error is less than\n\t     * TICK_VALUES_DISPLAY_ACCURACY intervals\n\t     */\n\n\t    while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit))\n\t\t    > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) {\n\t\t--leastSigDigit;\n\t    }\n\t    numDigits = 1 + mostSigDigit - leastSigDigit;\n\t} else {\n\t    numDigits = 1;\n\t}\n    } else {\n\t/*\n\t * If the number of significant digits wasn't specified explicitly,\n\t * compute it. It's the difference between the most significant digit\n\t * needed to represent any number on the scale and the most\n\t * significant digit of the smallest difference between numbers on the\n\t * scale. In other words, display enough digits so that at least one\n\t * digit will be different between any two adjacent positions of the\n\t * scale.\n\t */\n\n\tnumDigits = scalePtr->digits;\n\tif (numDigits > TCL_MAX_PREC) {\n\t    numDigits = 0;\n\t}\n\tif (numDigits <= 0) {\n\t    if (scalePtr->resolution > 0) {\n\t\t/*\n\t\t * A resolution was specified for the scale, so just use it.\n\t\t */\n\n\t\tleastSigDigit = ScaleDigit(scalePtr->resolution);\n\t    } else {\n\t\t/*\n\t\t * No resolution was specified, so compute the difference in\n\t\t * value between adjacent pixels and use it for the least\n\t\t * significant digit.\n\t\t */\n\t\tint length;\n\n\t\tx = fabs(scalePtr->fromValue - scalePtr->toValue);\n\t    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->lengthObj, &length);\n\t\tif (length > 0) {\n\t\t    x /= length;\n\t\t}\n\t\tif (x > 0) {\n\t\t    leastSigDigit = ScaleDigit(x);\n\t\t} else {\n\t\t    leastSigDigit = 0;\n\t\t}\n\t    }\n\t    numDigits = mostSigDigit - leastSigDigit + 1;\n\t    if (numDigits < 1) {\n\t\tnumDigits = 1;\n\t    }\n\t}\n    }\n\n    /*\n     * Compute the number of characters required using \"e\" format and \"f\"\n     * format, and then choose whichever one takes fewer characters.\n     */\n\n    eDigits = numDigits + 4;\n    if (numDigits > 1) {\n\teDigits++;\t\t\t/* Decimal point. */\n    }\n    afterDecimal = numDigits - mostSigDigit - 1;\n    if (afterDecimal < 0) {\n\tafterDecimal = 0;\n    }\n    fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;\n    if (afterDecimal > 0) {\n\tfDigits++;\t\t\t/* Decimal point. */\n    }\n    if (mostSigDigit < 0) {\n\tfDigits++;\t\t\t/* Zero to left of decimal point. */\n    }\n\n    if (forTicks) {\n\tif (fDigits <= eDigits) {\n\t    snprintf(scalePtr->tickFormat, sizeof(scalePtr->tickFormat), \"%%.%df\", afterDecimal);\n\t} else {\n\t    snprintf(scalePtr->tickFormat, sizeof(scalePtr->tickFormat), \"%%.%de\", numDigits - 1);\n\t}\n    } else {\n\tif (fDigits <= eDigits) {\n\t    snprintf(scalePtr->valueFormat, sizeof(scalePtr->valueFormat), \"%%.%df\", afterDecimal);\n\t} else {\n\t    snprintf(scalePtr->valueFormat, sizeof(scalePtr->valueFormat), \"%%.%de\", numDigits - 1);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeScaleGeometry --\n *\n *\tThis procedure is called to compute various geometrical information\n *\tfor a scale, such as where various things get displayed. It's called\n *\twhen the window is reconfigured.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDisplay-related numbers get changed in *scalePtr. The geometry manager\n *\tgets told about the window's preferred size.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nComputeScaleGeometry(\n    TkScale *scalePtr)\t/* Information about widget. */\n{\n    char valueString[TCL_DOUBLE_SPACE];\n    int tmp, valuePixels, tickPixels, x, y, extraSpace;\n    Tk_FontMetrics fm;\n    int length, width, borderWidth;\n\n    Tk_GetFontMetrics(scalePtr->tkfont, &fm);\n    scalePtr->fontHeight = fm.linespace + SPACING;\n\n    /*\n     * Horizontal scales are simpler than vertical ones because all sizes are\n     * the same (the height of a line of text); handle them first and then\n     * quit.\n     */\n\n    if (scalePtr->orient == ORIENT_HORIZONTAL) {\n\ty = scalePtr->inset;\n\textraSpace = 0;\n\tif (scalePtr->labelObj != NULL) {\n\t    scalePtr->horizLabelY = y + SPACING;\n\t    y += scalePtr->fontHeight;\n\t    extraSpace = SPACING;\n\t}\n\tif (scalePtr->showValue) {\n\t    scalePtr->horizValueY = y + SPACING;\n\t    y += scalePtr->fontHeight;\n\t    extraSpace = SPACING;\n\t} else {\n\t    scalePtr->horizValueY = y;\n\t}\n\ty += extraSpace;\n\tscalePtr->horizTroughY = y;\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->lengthObj, &length);\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->widthObj, &width);\n\tTk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n\ty += width + 2 * borderWidth;\n\tif (scalePtr->tickInterval != 0) {\n\t    scalePtr->horizTickY = y + SPACING;\n\t    y += scalePtr->fontHeight + SPACING;\n\t}\n\tTk_GeometryRequest(scalePtr->tkwin,\n\t\tlength + 2*scalePtr->inset, y + scalePtr->inset);\n\tTk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);\n\treturn;\n    }\n\n    /*\n     * Vertical scale: compute the amount of space needed to display the\n     * scales value by formatting strings for the two end points; use\n     * whichever length is longer.\n     */\n\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,\n\t    scalePtr->fromValue) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);\n\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,\n\t    scalePtr->toValue) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);\n    if (valuePixels < tmp) {\n\tvaluePixels = tmp;\n    }\n\n    /*\n     * Now do the same thing for the tick values\n     */\n\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,\n\t    scalePtr->fromValue) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);\n\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,\n\t    scalePtr->toValue) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);\n    if (tickPixels < tmp) {\n\ttickPixels = tmp;\n    }\n\n    /*\n     * Assign x-locations to the elements of the scale, working from left to\n     * right.\n     */\n\n    x = scalePtr->inset;\n    if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {\n\tscalePtr->vertTickRightX = x + SPACING + tickPixels;\n\tscalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels\n\t\t+ fm.ascent/2;\n\tx = scalePtr->vertValueRightX + SPACING;\n    } else if (scalePtr->tickInterval != 0) {\n\tscalePtr->vertTickRightX = x + SPACING + tickPixels;\n\tscalePtr->vertValueRightX = scalePtr->vertTickRightX;\n\tx = scalePtr->vertTickRightX + SPACING;\n    } else if (scalePtr->showValue) {\n\tscalePtr->vertTickRightX = x;\n\tscalePtr->vertValueRightX = x + SPACING + valuePixels;\n\tx = scalePtr->vertValueRightX + SPACING;\n    } else {\n\tscalePtr->vertTickRightX = x;\n\tscalePtr->vertValueRightX = x;\n    }\n    scalePtr->vertTroughX = x;\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->widthObj, &width);\n    x += 2 * borderWidth + width;\n    if (scalePtr->labelObj == NULL) {\n\tscalePtr->vertLabelX = 0;\n    } else {\n\tTcl_Size labelLength;\n\tconst char *label= Tcl_GetStringFromObj(scalePtr->labelObj, &labelLength);\n\tscalePtr->vertLabelX = x + fm.ascent/2;\n\tx = scalePtr->vertLabelX + fm.ascent/2\n\t    + Tk_TextWidth(scalePtr->tkfont, label, labelLength);\n    }\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->lengthObj, &length);\n    Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,\n\t    length + 2*scalePtr->inset);\n    Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tscales.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkScale *scalePtr = (TkScale *)clientData;\n    int highlightWidth;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tTkEventuallyRedrawScale(scalePtr, REDRAW_ALL);\n    } else if (eventPtr->type == DestroyNotify) {\n\tDestroyScale(clientData);\n    } else if (eventPtr->type == ConfigureNotify) {\n\tComputeScaleGeometry(scalePtr);\n\tTkEventuallyRedrawScale(scalePtr, REDRAW_ALL);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    scalePtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tTkEventuallyRedrawScale(scalePtr, REDRAW_ALL);\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    scalePtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tTkEventuallyRedrawScale(scalePtr, REDRAW_ALL);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScaleCmdDeletedProc --\n *\n *\tThis procedure is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nScaleCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkScale *scalePtr = (TkScale *)clientData;\n    Tk_Window tkwin = scalePtr->tkwin;\n\n    /*\n     * This procedure could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this procedure destroys the\n     * widget.\n     */\n\n    if (!(scalePtr->flags & SCALE_DELETED)) {\n\tscalePtr->flags |= SCALE_DELETED;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkEventuallyRedrawScale --\n *\n *\tArrange for part or all of a scale widget to redrawn at the next\n *\tconvenient time in the future.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf \"what\" is REDRAW_SLIDER then just the slider and the value readout\n *\twill be redrawn; if \"what\" is REDRAW_ALL then the entire widget will\n *\tbe redrawn.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkEventuallyRedrawScale(\n    TkScale *scalePtr,\t/* Information about widget. */\n    int what)\t\t\t/* What to redraw: REDRAW_SLIDER or\n\t\t\t\t * REDRAW_ALL. */\n{\n    if ((what == 0) || (scalePtr->tkwin == NULL)\n\t    || !Tk_IsMapped(scalePtr->tkwin)) {\n\treturn;\n    }\n    if (!(scalePtr->flags & REDRAW_PENDING)) {\n\tscalePtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(TkpDisplayScale, scalePtr);\n    }\n    scalePtr->flags |= what;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkRoundValueToResolution, TkRoundIntervalToResolution --\n *\n *\tRound a given floating-point value to the nearest multiple of the\n *\tscale's resolution.\n *\tTkRoundValueToResolution rounds an absolute value based on the from\n *\tvalue as a reference.\n *\tTkRoundIntervalToResolution rounds a relative value without\n *\treference, i.e.\tit rounds an interval.\n *\n * Results:\n *\tThe return value is the rounded result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTkRoundValueToResolution(\n    TkScale *scalePtr,\t\t/* Information about scale widget. */\n    double value)\t\t/* Value to round. */\n{\n    return TkRoundIntervalToResolution(scalePtr, value - scalePtr->fromValue)\n\t    + scalePtr->fromValue;\n}\n\ndouble\nTkRoundIntervalToResolution(\n    TkScale *scalePtr,\t\t/* Information about scale widget. */\n    double value)\t\t/* Value to round. */\n{\n    double rem, rounded, tick;\n\n    if (scalePtr->resolution <= 0) {\n\treturn value;\n    }\n    tick = floor(value/scalePtr->resolution);\n    rounded = scalePtr->resolution * tick;\n    rem = value - rounded;\n    if (rem < 0) {\n\tif (rem <= -scalePtr->resolution/2) {\n\t    rounded = (tick - 1.0) * scalePtr->resolution;\n\t}\n    } else {\n\tif (rem >= scalePtr->resolution/2) {\n\t    rounded = (tick + 1.0) * scalePtr->resolution;\n\t}\n    }\n    return rounded;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScaleVarProc --\n *\n *\tThis procedure is invoked by Tcl whenever someone modifies a variable\n *\tassociated with a scale widget.\n *\n * Results:\n *\tNULL is always returned.\n *\n * Side effects:\n *\tThe value displayed in the scale will change to match the variable's\n *\tnew value. If the variable has a bogus value then it is reset to the\n *\tvalue of the scale.\n *\n *----------------------------------------------------------------------\n */\n\nstatic char *\nScaleVarProc(\n    void *clientData,\t/* Information about button. */\n    Tcl_Interp *interp,\t\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t/* Name of variable. */\n    TCL_UNUSED(const char *),\t/* Second part of variable name. */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    TkScale *scalePtr = (TkScale *)clientData;\n    const char *resultStr;\n    double value;\n    Tcl_Obj *valuePtr;\n    int result;\n\n    /*\n     * If the variable is unset, then immediately recreate it unless the whole\n     * interpreter is going away.\n     */\n\n    if (flags & TCL_TRACE_UNSETS) {\n\tif (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) {\n\t    void *probe = NULL;\n\n\t    do {\n\t\tprobe = Tcl_VarTraceInfo(interp,\n\t\t\tTcl_GetString(scalePtr->varNamePtr),\n\t\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t\tScaleVarProc, probe);\n\t\tif (probe == (void *)scalePtr) {\n\t\t    break;\n\t\t}\n\t    } while (probe);\n\t    if (probe) {\n\t\t/*\n\t\t * We were able to fetch the unset trace for our\n\t\t * varNamePtr, which means it is not unset and not\n\t\t * the cause of this unset trace. Instead some outdated\n\t\t * former variable must be, and we should ignore it.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t    Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),\n\t\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\t    ScaleVarProc, clientData);\n\t    scalePtr->flags |= NEVER_SET;\n\t    TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);\n\t}\n\treturn NULL;\n    }\n\n    /*\n     * If we came here because we updated the variable (in TkScaleSetValue),\n     * then ignore the trace. Otherwise update the scale with the value of the\n     * variable.\n     */\n\n    if (scalePtr->flags & SETTING_VAR) {\n\treturn NULL;\n    }\n    resultStr = NULL;\n    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,\n\t    TCL_GLOBAL_ONLY);\n    result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);\n    if (result != TCL_OK) {\n\tresultStr = \"cannot assign a non-numeric value to a scale variable\";\n\tScaleSetVariable(scalePtr);\n    } else {\n\tscalePtr->value = TkRoundValueToResolution(scalePtr, value);\n\n\t/*\n\t * This code is a bit tricky because it sets the scale's value before\n\t * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to\n\t * set the variable again or to invoke the -command. However, it also\n\t * won't redisplay the scale, so we have to ask for that explicitly.\n\t */\n\n\tTkScaleSetValue(scalePtr, scalePtr->value, 1, 0);\n    }\n    TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);\n\n    return (char *) resultStr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkScaleSetValue --\n *\n *\tThis procedure changes the value of a scale and invokes a Tcl command\n *\tto reflect the current position of a scale\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Tcl command is invoked, and an additional error-processing command\n *\tmay also be invoked. The scale's slider is redrawn.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkScaleSetValue(\n    TkScale *scalePtr,\t/* Info about widget. */\n    double value,\t\t/* New value for scale. Gets adjusted if it's\n\t\t\t\t * off the scale. */\n    int setVar,\t\t\t/* Non-zero means reflect new value through to\n\t\t\t\t * associated variable, if any. */\n    int invokeCommand)\t\t/* Non-zero means invoked -command option to\n\t\t\t\t * notify of new value, 0 means don't. */\n{\n    value = TkRoundValueToResolution(scalePtr, value);\n    if ((value < scalePtr->fromValue)\n\t    ^ (scalePtr->toValue < scalePtr->fromValue)) {\n\tvalue = scalePtr->fromValue;\n    }\n    if ((value > scalePtr->toValue)\n\t    ^ (scalePtr->toValue < scalePtr->fromValue)) {\n\tvalue = scalePtr->toValue;\n    }\n    if (scalePtr->flags & NEVER_SET) {\n\tscalePtr->flags &= ~NEVER_SET;\n    } else if (scalePtr->value == value) {\n\treturn;\n    }\n    scalePtr->value = value;\n\n    /*\n     * Schedule command callback invocation only if there is such a command\n     * already registered, otherwise the callback would trigger later when\n     * configuring the widget -command option even if the value did not change.\n     */\n\n    if ((invokeCommand) && (scalePtr->commandObj != NULL)) {\n\tscalePtr->flags |= INVOKE_COMMAND;\n    }\n    TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);\n\n    if (setVar && scalePtr->varNamePtr) {\n\tScaleSetVariable(scalePtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScaleSetVariable --\n *\n *\tThis procedure sets the variable associated with a scale, if any.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOther write traces on the variable will trigger.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScaleSetVariable(\n    TkScale *scalePtr)\t/* Info about widget. */\n{\n    if (scalePtr->varNamePtr != NULL) {\n\tchar string[TCL_DOUBLE_SPACE];\n\n\tif (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,\n\t\tscalePtr->value) < 0) {\n\t    string[TCL_DOUBLE_SPACE - 1] = '\\0';\n\t}\n\tscalePtr->flags |= SETTING_VAR;\n\tTcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,\n\t\tTcl_NewStringObj(string, TCL_INDEX_NONE), TCL_GLOBAL_ONLY);\n\tscalePtr->flags &= ~SETTING_VAR;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScalePixelToValue --\n *\n *\tGiven a pixel within a scale window, return the scale reading\n *\tcorresponding to that pixel.\n *\n * Results:\n *\tA double-precision scale reading. If the value is outside the legal\n *\trange for the scale then it's rounded to the nearest end of the scale.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\ndouble\nTkScalePixelToValue(\n    TkScale *scalePtr,\t/* Information about widget. */\n    int x, int y)\t\t/* Coordinates of point within window. */\n{\n    double value, pixelRange;\n    int borderWidth, sliderLength;\n\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->sliderLengthObj, &sliderLength);\n    if (scalePtr->orient == ORIENT_VERTICAL) {\n\tpixelRange = Tk_Height(scalePtr->tkwin) - sliderLength\n\t\t- 2 * scalePtr->inset - 2 * borderWidth;\n\tvalue = y;\n    } else {\n\tpixelRange = Tk_Width(scalePtr->tkwin) - sliderLength\n\t\t- 2 * scalePtr->inset - 2 * borderWidth;\n\tvalue = x;\n    }\n\n    if (pixelRange <= 0) {\n\t/*\n\t * Not enough room for the slider to actually slide: just return the\n\t * scale's current value.\n\t */\n\n\treturn scalePtr->value;\n    }\n    value -= sliderLength/2 + scalePtr->inset\n\t    + borderWidth;\n    value /= pixelRange;\n    if (value < 0) {\n\tvalue = 0;\n    }\n    if (value > 1) {\n\tvalue = 1;\n    }\n    value = scalePtr->fromValue +\n\t\tvalue * (scalePtr->toValue - scalePtr->fromValue);\n    return TkRoundValueToResolution(scalePtr, value);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScaleValueToPixel --\n *\n *\tGiven a reading of the scale, return the x-coordinate or y-coordinate\n *\tcorresponding to that reading, depending on whether the scale is\n *\tvertical or horizontal, respectively.\n *\n * Results:\n *\tAn integer value giving the pixel location corresponding to reading.\n *\tThe value is restricted to lie within the defined range for the scale.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkScaleValueToPixel(\n    TkScale *scalePtr,\t/* Information about widget. */\n    double value)\t\t/* Reading of the widget. */\n{\n    int y, pixelRange;\n    double valueRange;\n    int borderWidth, sliderLength;\n\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->sliderLengthObj, &sliderLength);\n    valueRange = scalePtr->toValue - scalePtr->fromValue;\n    pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)\n\t    ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin))\n\t- sliderLength - 2 * scalePtr->inset - 2 * borderWidth;\n    if (valueRange == 0) {\n\ty = 0;\n    } else {\n\ty = ScaleRound((value - scalePtr->fromValue) * pixelRange\n\t\t/ valueRange);\n\tif (y < 0) {\n\t    y = 0;\n\t} else if (y > pixelRange) {\n\t    y = pixelRange;\n\t}\n    }\n    y += sliderLength / 2 + scalePtr->inset + borderWidth;\n    return y;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkScale.h",
    "content": "/*\n * tkScale.h --\n *\n *\tDeclarations of types and functions used to implement the scale\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 1999-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKSCALE\n#define _TKSCALE\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Legal values for the \"orient\" field of TkScale records.\n */\n\nenum orient {\n    ORIENT_HORIZONTAL, ORIENT_VERTICAL\n};\n\n/*\n * Legal values for the \"state\" field of TkScale records.\n */\n\nenum state {\n    STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL\n};\n\n/*\n * A data structure of the following type is kept for each scale widget\n * managed by this file:\n */\n\ntypedef struct TkScale {\n    Tk_Window tkwin;\t\t/* Window that embodies the scale. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up.*/\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with scale. */\n    Tcl_Command widgetCmd;\t/* Token for scale's widget command. */\n    Tk_OptionTable optionTable;\t/* Table that defines configuration options\n\t\t\t\t * available for this widget. */\n    enum orient orient;\t\t/* Orientation for window (vertical or\n\t\t\t\t * horizontal). */\n    Tcl_Obj *widthObj;\t\t/* Desired narrow dimension of scale, in\n\t\t\t\t * pixels. */\n    Tcl_Obj *lengthObj;\t/* Desired long dimension of scale, in\n\t\t\t\t * pixels. */\n    double value;\t\t/* Current value of scale. */\n    Tcl_Obj *varNamePtr;\t/* Name of variable or NULL. If non-NULL,\n\t\t\t\t * scale's value tracks the contents of this\n\t\t\t\t * variable and vice versa. */\n    double fromValue;\t\t/* Value corresponding to left or top of\n\t\t\t\t * scale. */\n    double toValue;\t\t/* Value corresponding to right or bottom of\n\t\t\t\t * scale. */\n    double tickInterval;\t/* Distance between tick marks; 0 means don't\n\t\t\t\t * display any tick marks. */\n    double resolution;\t\t/* If > 0, all values are rounded to an even\n\t\t\t\t * multiple of this value. */\n    int digits;\t\t\t/* Number of significant digits to print in\n\t\t\t\t * values. 0 means we get to choose the number\n\t\t\t\t * based on resolution and/or the range of the\n\t\t\t\t * scale. */\n    char valueFormat[16];\t/* Snprintf conversion specifier computed from\n\t\t\t\t * digits and other information. */\n    char tickFormat[16];\t/* Snprintf conversion specifier computed from\n\t\t\t\t * tick interval. */\n    double bigIncrement;\t/* Amount to use for large increments to scale\n\t\t\t\t * value. (0 means we pick a value). */\n    Tcl_Obj *commandObj;\t/* Command prefix to use when invoking Tcl\n\t\t\t\t * commands because the scale value changed.\n\t\t\t\t * NULL means don't invoke commands. */\n    int repeatDelay;\t\t/* How long to wait before auto-repeating on\n\t\t\t\t * scrolling actions (in ms). */\n    int repeatInterval;\t\t/* Interval between autorepeats (in ms). */\n    Tcl_Obj *labelObj;\t\t/* Label to display above or to right of\n\t\t\t\t * scale; NULL means don't display a label. */\n    enum state state;\t\t/* Values are active, normal, or disabled.\n\t\t\t\t * Value of scale cannot be changed when\n\t\t\t\t * disabled. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border around window. */\n    Tk_3DBorder bgBorder;\t/* Used for drawing slider and other\n\t\t\t\t * background areas. */\n    Tk_3DBorder activeBorder;\t/* For drawing the slider when active. */\n    int sliderRelief;\t\t/* Is slider to be drawn raised, sunken,\n\t\t\t\t * etc. */\n    XColor *troughColorPtr;\t/* Color for drawing trough. */\n    GC troughGC;\t\t/* For drawing trough. */\n    GC copyGC;\t\t\t/* Used for copying from pixmap onto screen */\n    Tk_Font tkfont;\t\t/* Information about text font, or NULL. */\n    XColor *textColorPtr;\t/* Color for drawing text. */\n    GC textGC;\t\t\t/* GC for drawing text in normal mode. */\n    int relief;\t\t\t/* Indicates whether window as a whole is\n\t\t\t\t * raised, sunken, or flat. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. <= 0 means\n\t\t\t\t * don't draw a highlight. */\n    Tk_3DBorder highlightBorder;/* Value of -highlightbackground option:\n\t\t\t\t * specifies background with which to draw 3-D\n\t\t\t\t * default ring and focus highlight area when\n\t\t\t\t * highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    Tcl_Obj *sliderLengthObj;\t/* Length of slider, measured in pixels along\n\t\t\t\t * long dimension of scale. */\n    bool showValue;\t\t/* True means to display the scale value\n\t\t\t\t * below or to the left of the slider; false\n\t\t\t\t * means don't display the value. */\n\n    /*\n     * Layout information for horizontal scales, assuming that window gets the\n     * size it requested:\n     */\n\n    int horizLabelY;\t\t/* Y-coord at which to draw label. */\n    int horizValueY;\t\t/* Y-coord at which to draw value text. */\n    int horizTroughY;\t\t/* Y-coord of top of slider trough. */\n    int horizTickY;\t\t/* Y-coord at which to draw tick text. */\n    /*\n     * Layout information for vertical scales, assuming that window gets the\n     * size it requested:\n     */\n\n    int vertTickRightX;\t\t/* X-location of right side of tick-marks. */\n    int vertValueRightX;\t/* X-location of right side of value string. */\n    int vertTroughX;\t\t/* X-location of scale's slider trough. */\n    int vertLabelX;\t\t/* X-location of origin of label. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    int fontHeight;\t\t/* Height of scale font. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    Tcl_Obj *takeFocusPtr;\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n} TkScale;\n\n/*\n * Flag bits for scales:\n *\n * REDRAW_SLIDER -\t\t1 means slider (and numerical readout) need to\n *\t\t\t\tbe redrawn.\n * REDRAW_OTHER -\t\t1 means other stuff besides slider and value\n *\t\t\t\tneed to be redrawn.\n * REDRAW_ALL -\t\t\t1 means the entire widget needs to be redrawn.\n * REDRAW_PENDING -\t\t1 means any sort of redraw is pending\n * ACTIVE -\t\t\t1 means the widget is active (the mouse is in\n *\t\t\t\tits window).\n * INVOKE_COMMAND -\t\t1 means the scale's command needs to be\n *\t\t\t\tinvoked during the next redisplay (the value\n *\t\t\t\tof the scale has changed since the last time\n *\t\t\t\tthe command was invoked).\n * SETTING_VAR -\t\t1 means that the associated variable is being\n *\t\t\t\tset by us, so there's no need for ScaleVarProc\n *\t\t\t\tto do anything.\n * NEVER_SET -\t\t\t1 means that the scale's value has never been\n *\t\t\t\tset before (so must invoke -command and set\n *\t\t\t\tassociated variable even if the value doesn't\n *\t\t\t\tappear to have changed).\n * GOT_FOCUS -\t\t\t1 means that the focus is currently in this\n *\t\t\t\twidget.\n * SCALE_DELETED -\t\t1 means the scale widget is being deleted\n */\n\n#define REDRAW_SLIDER\t\t(1<<0)\n#define REDRAW_OTHER\t\t(1<<1)\n#define REDRAW_ALL\t\t(REDRAW_OTHER|REDRAW_SLIDER)\n#define REDRAW_PENDING\t\t(1<<2)\n#define ACTIVE\t\t\t(1<<3)\n#define INVOKE_COMMAND\t\t(1<<4)\n#define SETTING_VAR\t\t(1<<5)\n#define NEVER_SET\t\t(1<<6)\n#define GOT_FOCUS\t\t(1<<7)\n#define SCALE_DELETED\t\t(1<<8)\n\n/*\n * Symbolic values for the active parts of a slider. These are the values that\n * may be returned by the ScaleElement procedure.\n */\n\n#define OTHER\t\t0\n#define TROUGH1\t\t1\n#define SLIDER\t\t2\n#define TROUGH2\t\t3\n\n/*\n * Space to leave between scale area and text, and between text and edge of\n * window.\n */\n\n#define SPACING 2\n\n/*\n * The tick values are all displayed with the same number of decimal places.\n * This number of decimal places is such that the displayed values are all\n * accurate to within the following proportion of a tick interval.\n */\n\n#define TICK_VALUES_DISPLAY_ACCURACY 0.2\n\n/*\n * Declaration of procedures used in the implementation of the scale widget.\n */\n\nMODULE_SCOPE void\tTkEventuallyRedrawScale(TkScale *scalePtr, int what);\nMODULE_SCOPE double\tTkRoundValueToResolution(TkScale *scalePtr, double value);\nMODULE_SCOPE double\tTkRoundIntervalToResolution(TkScale *scalePtr, double value);\nMODULE_SCOPE TkScale *\tTkpCreateScale(Tk_Window tkwin);\nMODULE_SCOPE void\tTkpDestroyScale(TkScale *scalePtr);\nMODULE_SCOPE void\tTkpDisplayScale(void *clientData);\nMODULE_SCOPE int\tTkpScaleElement(TkScale *scalePtr, int x, int y);\nMODULE_SCOPE void\tTkScaleSetValue(TkScale *scalePtr, double value,\n\t\t\t    int setVar, int invokeCommand);\nMODULE_SCOPE double\tTkScalePixelToValue(TkScale *scalePtr, int x, int y);\nMODULE_SCOPE int\tTkScaleValueToPixel(TkScale *scalePtr, double value);\n\n#endif /* _TKSCALE */\n"
  },
  {
    "path": "generic/tkScrollbar.c",
    "content": "/*\n * tkScrollbar.c --\n *\n *\tThis module implements a scrollbar widgets for the Tk toolkit. A\n *\tscrollbar displays a slider and two arrows; mouse clicks on features\n *\twithin the scrollbar cause scrolling commands to be invoked.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkScrollbar.h\"\n#include \"default.h\"\n\n/*\n * Custom option for handling \"-orient\"\n */\n\nstatic const Tk_CustomOption orientOption = {\n    TkOrientParseProc, TkOrientPrintProc, NULL\n};\n\n/* non-const space for \"-width\" default value for scrollbars */\nchar tkDefScrollbarWidth[TCL_INTEGER_SPACE] = DEF_SCROLLBAR_WIDTH;\n\n/*\n * Information used for argv parsing.\n */\n\nstatic const Tk_ConfigSpec configSpecs[] = {\n    {TK_CONFIG_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_SCROLLBAR_ACTIVE_BG_COLOR, offsetof(TkScrollbar, activeBorder),\n\tTK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_BORDER, \"-activebackground\", \"activeBackground\", \"Foreground\",\n\tDEF_SCROLLBAR_ACTIVE_BG_MONO, offsetof(TkScrollbar, activeBorder),\n\tTK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_RELIEF, \"-activerelief\", \"activeRelief\", \"Relief\",\n\tDEF_SCROLLBAR_ACTIVE_RELIEF, offsetof(TkScrollbar, activeRelief), 0, NULL},\n    {TK_CONFIG_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_SCROLLBAR_BG_COLOR, offsetof(TkScrollbar, bgBorder),\n\tTK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_SCROLLBAR_BG_MONO, offsetof(TkScrollbar, bgBorder),\n\tTK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_SYNONYM, \"-bd\", \"borderWidth\", NULL, NULL, 0, 0, NULL},\n    {TK_CONFIG_SYNONYM, \"-bg\", \"background\", NULL, NULL, 0, 0, NULL},\n    {TK_CONFIG_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_SCROLLBAR_BORDER_WIDTH, offsetof(TkScrollbar, borderWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_STRING, \"-command\", \"command\", \"Command\",\n\tDEF_SCROLLBAR_COMMAND, offsetof(TkScrollbar, commandObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_ACTIVE_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_SCROLLBAR_CURSOR, offsetof(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_PIXELS, \"-elementborderwidth\", \"elementBorderWidth\",\n\t\"BorderWidth\", DEF_SCROLLBAR_EL_BORDER_WIDTH,\n\toffsetof(TkScrollbar, elementBorderWidthObj), TK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_SCROLLBAR_HIGHLIGHT_BG,\n\toffsetof(TkScrollbar, highlightBgColorPtr), 0, NULL},\n    {TK_CONFIG_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_SCROLLBAR_HIGHLIGHT,\n\toffsetof(TkScrollbar, highlightColorPtr), 0, NULL},\n    {TK_CONFIG_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\",\n\tDEF_SCROLLBAR_HIGHLIGHT_WIDTH, offsetof(TkScrollbar, highlightWidthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_BOOLEAN, \"-jump\", \"jump\", \"Jump\",\n\tDEF_SCROLLBAR_JUMP, offsetof(TkScrollbar, jump), 0, NULL},\n    {TK_CONFIG_CUSTOM, \"-orient\", \"orient\", \"Orient\",\n\tDEF_SCROLLBAR_ORIENT, offsetof(TkScrollbar, vertical), 0,\n\t&orientOption},\n    {TK_CONFIG_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_SCROLLBAR_RELIEF, offsetof(TkScrollbar, relief), 0, NULL},\n    {TK_CONFIG_INT, \"-repeatdelay\", \"repeatDelay\", \"RepeatDelay\",\n\tDEF_SCROLLBAR_REPEAT_DELAY, offsetof(TkScrollbar, repeatDelay), 0, NULL},\n    {TK_CONFIG_INT, \"-repeatinterval\", \"repeatInterval\", \"RepeatInterval\",\n\tDEF_SCROLLBAR_REPEAT_INTERVAL, offsetof(TkScrollbar, repeatInterval), 0, NULL},\n    {TK_CONFIG_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_SCROLLBAR_TAKE_FOCUS, offsetof(TkScrollbar, takeFocusObj),\n\tTK_CONFIG_OBJS|TK_CONFIG_NULL_OK, NULL},\n    {TK_CONFIG_COLOR, \"-troughcolor\", \"troughColor\", \"Background\",\n\tDEF_SCROLLBAR_TROUGH_COLOR, offsetof(TkScrollbar, troughColorPtr),\n\tTK_CONFIG_COLOR_ONLY, NULL},\n    {TK_CONFIG_COLOR, \"-troughcolor\", \"troughColor\", \"Background\",\n\tDEF_SCROLLBAR_TROUGH_MONO, offsetof(TkScrollbar, troughColorPtr),\n\tTK_CONFIG_MONO_ONLY, NULL},\n    {TK_CONFIG_PIXELS, \"-width\", \"width\", \"Width\",\n\ttkDefScrollbarWidth, offsetof(TkScrollbar, widthObj), TK_CONFIG_OBJS, NULL},\n    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tConfigureScrollbar(Tcl_Interp *interp,\n\t\t\t    TkScrollbar *scrollPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], int flags);\nstatic void\t\tScrollbarCmdDeletedProc(void *clientData);\nstatic Tcl_ObjCmdProc2 ScrollbarWidgetObjCmd;\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_ScrollbarObjCmd --\n *\n *\tThis function is invoked to process the \"scrollbar\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_ScrollbarObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkScrollbar *scrollPtr;\n    Tk_Window newWin;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), NULL);\n    if (newWin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    Tk_SetClass(newWin, \"Scrollbar\");\n    scrollPtr = TkpCreateScrollbar(newWin);\n\n    Tk_SetClassProcs(newWin, &tkpScrollbarProcs, scrollPtr);\n\n    /*\n     * Initialize fields that won't be initialized by ConfigureScrollbar, or\n     * which ConfigureScrollbar expects to have reasonable values (e.g.\n     * resource pointers).\n     */\n\n    scrollPtr->tkwin = newWin;\n    scrollPtr->display = Tk_Display(newWin);\n    scrollPtr->interp = interp;\n    scrollPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetObjCmd,\n\t    scrollPtr, ScrollbarCmdDeletedProc);\n    scrollPtr->vertical = 0;\n    scrollPtr->widthObj = 0;\n    scrollPtr->commandObj = NULL;\n    scrollPtr->repeatDelay = 0;\n    scrollPtr->repeatInterval = 0;\n    scrollPtr->borderWidthObj = NULL;\n    scrollPtr->bgBorder = NULL;\n    scrollPtr->activeBorder = NULL;\n    scrollPtr->troughColorPtr = NULL;\n    scrollPtr->relief = TK_RELIEF_FLAT;\n    scrollPtr->highlightWidthObj = NULL;\n    scrollPtr->highlightBgColorPtr = NULL;\n    scrollPtr->highlightColorPtr = NULL;\n    scrollPtr->inset = 0;\n    scrollPtr->elementBorderWidthObj = NULL;\n    scrollPtr->arrowLength = 0;\n    scrollPtr->sliderFirst = 0;\n    scrollPtr->sliderLast = 0;\n    scrollPtr->activeField = 0;\n    scrollPtr->activeRelief = TK_RELIEF_RAISED;\n    scrollPtr->firstFraction = 0.0;\n    scrollPtr->lastFraction = 0.0;\n    scrollPtr->cursor = NULL;\n    scrollPtr->takeFocusObj = NULL;\n    scrollPtr->flags = 0;\n\n    if (ConfigureScrollbar(interp, scrollPtr, objc-2, objv+2, 0) != TCL_OK) {\n\tTk_DestroyWindow(scrollPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(scrollPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScrollbarWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nScrollbarWidgetObjCmd(\n    void *clientData,\t/* Information about scrollbar widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n    int result = TCL_OK, cmdIndex, length;\n    Tcl_Size len;\n    static const char *const commandNames[] = {\n\t\"activate\", \"cget\", \"configure\", \"delta\", \"fraction\",\n\t\"get\", \"identify\", \"set\", NULL\n    };\n    enum command {\n\tCOMMAND_ACTIVATE, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELTA,\n\tCOMMAND_FRACTION, COMMAND_GET, COMMAND_IDENTIFY, COMMAND_SET\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    /*\n     * Parse the command by looking up the second argument in the list of\n     * valid subcommand names\n     */\n\n    result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,\n\t    \"option\", 0, &cmdIndex);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n    Tcl_Preserve(scrollPtr);\n    switch (cmdIndex) {\n    case COMMAND_ACTIVATE: {\n\tint oldActiveField, c;\n\n\tif (objc == 2) {\n\t    const char *zone = \"\";\n\n\t    switch (scrollPtr->activeField) {\n\t    case TOP_ARROW:\tzone = \"arrow1\"; break;\n\t    case SLIDER:\tzone = \"slider\"; break;\n\t    case BOTTOM_ARROW:\tzone = \"arrow2\"; break;\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, TCL_INDEX_NONE));\n\t    goto done;\n\t}\n\tif (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"activate element\");\n\t    goto error;\n\t}\n\tc = Tcl_GetStringFromObj(objv[2], &len)[0];\n\toldActiveField = scrollPtr->activeField;\n\tif ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), \"arrow1\") == 0)) {\n\t    scrollPtr->activeField = TOP_ARROW;\n\t} else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), \"arrow2\") == 0)) {\n\t    scrollPtr->activeField = BOTTOM_ARROW;\n\t} else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), \"slider\", len) == 0)) {\n\t    scrollPtr->activeField = SLIDER;\n\t} else {\n\t    scrollPtr->activeField = OUTSIDE;\n\t}\n\tif (oldActiveField != scrollPtr->activeField) {\n\t    TkScrollbarEventuallyRedraw(scrollPtr);\n\t}\n\tbreak;\n    }\n    case COMMAND_CGET: {\n\tif (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"cget option\");\n\t    goto error;\n\t}\n\tresult = Tk_ConfigureValue(interp, scrollPtr->tkwin,\n\t\tconfigSpecs, scrollPtr, Tcl_GetString(objv[2]), 0);\n\tbreak;\n    }\n    case COMMAND_CONFIGURE: {\n\tif (objc == 2) {\n\t    result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,\n\t\t    configSpecs, scrollPtr, NULL, 0);\n\t} else if (objc == 3) {\n\t    result = Tk_ConfigureInfo(interp, scrollPtr->tkwin,\n\t\t    configSpecs, scrollPtr, Tcl_GetString(objv[2]), 0);\n\t} else {\n\t    result = ConfigureScrollbar(interp, scrollPtr, objc-2,\n\t\t    objv+2, TK_CONFIG_ARGV_ONLY);\n\t}\n\tbreak;\n    }\n    case COMMAND_DELTA: {\n\tint xDelta, yDelta, pixels;\n\tdouble fraction;\n\n\tif (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"delta xDelta yDelta\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &xDelta) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &yDelta) != TCL_OK)) {\n\t    goto error;\n\t}\n\tif (scrollPtr->vertical) {\n\t    pixels = yDelta;\n\t    length = Tk_Height(scrollPtr->tkwin) - 1\n\t\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n\t} else {\n\t    pixels = xDelta;\n\t    length = Tk_Width(scrollPtr->tkwin) - 1\n\t\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n\t}\n\tif (length == 0) {\n\t    fraction = 0.0;\n\t} else {\n\t    fraction = ((double) pixels / (double) length);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));\n\tbreak;\n    }\n    case COMMAND_FRACTION: {\n\tint x, y, pos;\n\tdouble fraction;\n\n\tif (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"fraction x y\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    goto error;\n\t}\n\tif (scrollPtr->vertical) {\n\t    pos = y - (scrollPtr->arrowLength + scrollPtr->inset);\n\t    length = Tk_Height(scrollPtr->tkwin) - 1\n\t\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n\t} else {\n\t    pos = x - (scrollPtr->arrowLength + scrollPtr->inset);\n\t    length = Tk_Width(scrollPtr->tkwin) - 1\n\t\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n\t}\n\tif (length == 0) {\n\t    fraction = 0.0;\n\t} else {\n\t    fraction = ((double) pos / (double) length);\n\t}\n\tif (fraction < 0) {\n\t    fraction = 0;\n\t} else if (fraction > 1.0) {\n\t    fraction = 1.0;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));\n\tbreak;\n    }\n    case COMMAND_GET: {\n\tTcl_Obj *resObjs[4];\n\n\tif (objc != 2) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"get\");\n\t    goto error;\n\t}\n\tresObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);\n\tresObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));\n\tbreak;\n    }\n    case COMMAND_IDENTIFY: {\n\tint x, y;\n\tconst char *zone = \"\";\n\n\tif (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"identify x y\");\n\t    goto error;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {\n\t    goto error;\n\t}\n\tswitch (TkpScrollbarPosition(scrollPtr, x, y)) {\n\tcase TOP_ARROW:\t\tzone = \"arrow1\";  break;\n\tcase TOP_GAP:\t\tzone = \"trough1\"; break;\n\tcase SLIDER:\t\tzone = \"slider\";  break;\n\tcase BOTTOM_GAP:\tzone = \"trough2\"; break;\n\tcase BOTTOM_ARROW:\tzone = \"arrow2\";  break;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(zone, TCL_INDEX_NONE));\n\tbreak;\n    }\n    case COMMAND_SET: {\n\tif (objc == 4) {\n\t    double first, last;\n\n\t    if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (Tcl_GetDoubleFromObj(interp, objv[3], &last) != TCL_OK) {\n\t\tgoto error;\n\t    }\n\t    if (first < 0) {\n\t\tscrollPtr->firstFraction = 0;\n\t    } else if (first > 1.0) {\n\t\tscrollPtr->firstFraction = 1.0;\n\t    } else {\n\t\tscrollPtr->firstFraction = first;\n\t    }\n\t    if (last < scrollPtr->firstFraction) {\n\t\tscrollPtr->lastFraction = scrollPtr->firstFraction;\n\t    } else if (last > 1.0) {\n\t\tscrollPtr->lastFraction = 1.0;\n\t    } else {\n\t\tscrollPtr->lastFraction = last;\n\t    }\n\t} else {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"set firstFraction lastFraction\");\n\t    goto error;\n\t}\n\tTkpComputeScrollbarGeometry(scrollPtr);\n\tTkScrollbarEventuallyRedraw(scrollPtr);\n\tbreak;\n    }\n    }\n\n  done:\n    Tcl_Release(scrollPtr);\n    return result;\n\n  error:\n    Tcl_Release(scrollPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureScrollbar --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a scrollbar\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor scrollPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureScrollbar(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkScrollbar *scrollPtr,\n\t\t\t\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of valid entries in argv. */\n    Tcl_Obj *const objv[],\t\t/* Arguments. */\n    int flags)\t\t\t/* Flags to pass to Tk_ConfigureWidget. */\n{\n    if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, objc,\n\t    objv, scrollPtr, flags) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Configure platform specific options.\n     */\n\n    TkpConfigureScrollbar(scrollPtr);\n\n    /*\n     * Register the desired geometry for the window (leave enough space for\n     * the two arrows plus a minimum-size slider, plus border around the whole\n     * window, if any). Then arrange for the window to be redisplayed.\n     */\n\n    TkpComputeScrollbarGeometry(scrollPtr);\n    TkScrollbarEventuallyRedraw(scrollPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkScrollbarEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher for various events on\n *\tscrollbars.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkScrollbarEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n    int highlightWidth;\n\n    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {\n\tTkScrollbarEventuallyRedraw(scrollPtr);\n    } else if (eventPtr->type == DestroyNotify) {\n\tTkpDestroyScrollbar(scrollPtr);\n\tif (scrollPtr->tkwin != NULL) {\n\t    scrollPtr->tkwin = NULL;\n\t    Tcl_DeleteCommandFromToken(scrollPtr->interp,\n\t\t    scrollPtr->widgetCmd);\n\t}\n\tif (scrollPtr->flags & REDRAW_PENDING) {\n\t    Tcl_CancelIdleCall(TkpDisplayScrollbar, scrollPtr);\n\t}\n\t/*\n\t * Free up all the stuff that requires special handling, then let\n\t * Tk_FreeOptions handle all the standard option-related stuff.\n\t */\n\n\tTk_FreeOptions(configSpecs, scrollPtr, scrollPtr->display, 0);\n\tTcl_EventuallyFree(scrollPtr, TCL_DYNAMIC);\n    } else if (eventPtr->type == ConfigureNotify) {\n\tTkpComputeScrollbarGeometry(scrollPtr);\n\tTkScrollbarEventuallyRedraw(scrollPtr);\n    } else if (eventPtr->type == FocusIn) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    scrollPtr->flags |= GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tTkScrollbarEventuallyRedraw(scrollPtr);\n\t    }\n\t}\n    } else if (eventPtr->type == FocusOut) {\n\tif (eventPtr->xfocus.detail != NotifyInferior) {\n\t    scrollPtr->flags &= ~GOT_FOCUS;\n\t    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tTkScrollbarEventuallyRedraw(scrollPtr);\n\t    }\n\t}\n    } else if (eventPtr->type == MapNotify) {\n\tTkScrollbarEventuallyRedraw(scrollPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScrollbarCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nScrollbarCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n    Tk_Window tkwin = scrollPtr->tkwin;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\tscrollPtr->tkwin = NULL;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkScrollbarEventuallyRedraw --\n *\n *\tArrange for one or more of the fields of a scrollbar to be redrawn.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkScrollbarEventuallyRedraw(\n    TkScrollbar *scrollPtr)\t/* Information about widget. */\n{\n    if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(scrollPtr->tkwin)) {\n\treturn;\n    }\n    if (!(scrollPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(TkpDisplayScrollbar, scrollPtr);\n\tscrollPtr->flags |= REDRAW_PENDING;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkScrollbar.h",
    "content": "/*\n * tkScrollbar.h --\n *\n *\tDeclarations of types and functions used to implement the scrollbar\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKSCROLLBAR\n#define _TKSCROLLBAR\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * A data structure of the following type is kept for each scrollbar widget.\n */\n\ntypedef struct TkScrollbar {\n    Tk_Window tkwin;\t\t/* Window that embodies the scrollbar. NULL\n\t\t\t\t * means that the window has been destroyed\n\t\t\t\t * but the data structures haven't yet been\n\t\t\t\t * cleaned up.*/\n    Display *display;\t\t/* Display containing widget. Used, among\n\t\t\t\t * other things, so that resources can be\n\t\t\t\t * freed even after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with scrollbar. */\n    Tcl_Command widgetCmd;\t/* Token for scrollbar's widget command. */\n    int vertical;\t\t/* Non-zero means vertical orientation\n\t\t\t\t * requested, zero means horizontal. */\n    Tcl_Obj *widthObj;\t\t/* Desired narrow dimension of scrollbar, in\n\t\t\t\t * pixels. */\n    Tcl_Obj *commandObj;\t\t/* Command prefix to use when invoking\n\t\t\t\t * scrolling commands. NULL means don't invoke\n\t\t\t\t * commands. */\n    int repeatDelay;\t\t/* How long to wait before auto-repeating on\n\t\t\t\t * scrolling actions (in ms). */\n    int repeatInterval;\t\t/* Interval between autorepeats (in ms). */\n    int jump;\t\t\t/* Value of -jump option. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D borders. */\n    Tk_3DBorder bgBorder;\t/* Used for drawing background (all flat\n\t\t\t\t * surfaces except for trough). */\n    Tk_3DBorder activeBorder;\t/* For drawing backgrounds when active (i.e.\n\t\t\t\t * when mouse is positioned over element). */\n    XColor *troughColorPtr;\t/* Color for drawing trough. */\n    int relief;\t\t\t/* Indicates whether window as a whole is\n\t\t\t\t * raised, sunken, or flat. */\n    Tcl_Obj *highlightWidthObj;\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. <= 0 means\n\t\t\t\t * don't draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    int inset;\t\t\t/* Total width of all borders, including\n\t\t\t\t * traversal highlight and 3-D border.\n\t\t\t\t * Indicates how much interior stuff must be\n\t\t\t\t * offset from outside edges to leave room for\n\t\t\t\t * borders. */\n    Tcl_Obj *elementBorderWidthObj;\t/* Width of border to draw around elements\n\t\t\t\t * inside scrollbar (arrows and slider). -1\n\t\t\t\t * means use borderWidth. */\n    int arrowLength;\t\t/* Length of arrows along long dimension of\n\t\t\t\t * scrollbar, including space for a small gap\n\t\t\t\t * between the arrow and the slider.\n\t\t\t\t * Recomputed on window size changes. */\n    int sliderFirst;\t\t/* Pixel coordinate of top or left edge of\n\t\t\t\t * slider area, including border. */\n    int sliderLast;\t\t/* Coordinate of pixel just after bottom or\n\t\t\t\t * right edge of slider area, including\n\t\t\t\t * border. */\n    int activeField;\t\t/* Names field to be displayed in active\n\t\t\t\t * colors, such as TOP_ARROW, or 0 for no\n\t\t\t\t * field. */\n    int activeRelief;\t\t/* Value of -activeRelief option: relief to\n\t\t\t\t * use for active element. */\n\n    /*\n     * Information describing the application related to the scrollbar, which\n     * is provided by the application by invoking the \"set\" widget command.\n     */\n\n    double firstFraction;\t/* Position of first visible thing in window,\n\t\t\t\t * specified as a fraction between 0 and 1.0. */\n    double lastFraction;\t/* Position of last visible thing in window,\n\t\t\t\t * specified as a fraction between 0 and 1.0. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    Tcl_Obj *takeFocusObj;\t\t/* Value of -takefocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    int flags;\t\t\t/* Various flags; see below for\n\t\t\t\t * definitions. */\n} TkScrollbar;\n\n/*\n * Legal values for \"activeField\" field of Scrollbar structures. These are\n * also the return values from the ScrollbarPosition function.\n */\n\n#define OUTSIDE\t\t0\n#define TOP_ARROW\t1\n#define TOP_GAP\t\t2\n#define SLIDER\t\t3\n#define BOTTOM_GAP\t4\n#define BOTTOM_ARROW\t5\n\n/*\n * Flag bits for scrollbars:\n *\n * REDRAW_PENDING:\t\tNon-zero means a DoWhenIdle handler has\n *\t\t\t\talready been queued to redraw this window.\n * GOT_FOCUS:\t\t\tNon-zero means this window has the input\n *\t\t\t\tfocus.\n */\n\n#define REDRAW_PENDING\t\t1\n#define GOT_FOCUS\t\t4\n\n/*\n * Declaration of scrollbar class functions structure\n * and default scrollbar width, for use in configSpec.\n */\n\nMODULE_SCOPE const Tk_ClassProcs tkpScrollbarProcs;\nMODULE_SCOPE char tkDefScrollbarWidth[TCL_INTEGER_SPACE];\n\n/*\n * Declaration of functions used in the implementation of the scrollbar\n * widget.\n */\n\nMODULE_SCOPE void\tTkScrollbarEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nMODULE_SCOPE void\tTkScrollbarEventuallyRedraw(TkScrollbar *scrollPtr);\nMODULE_SCOPE void\tTkpComputeScrollbarGeometry(TkScrollbar *scrollPtr);\nMODULE_SCOPE TkScrollbar *TkpCreateScrollbar(Tk_Window tkwin);\nMODULE_SCOPE void\tTkpDestroyScrollbar(TkScrollbar *scrollPtr);\nMODULE_SCOPE void\tTkpDisplayScrollbar(void *clientData);\nMODULE_SCOPE void\tTkpConfigureScrollbar(TkScrollbar *scrollPtr);\nMODULE_SCOPE int\tTkpScrollbarPosition(TkScrollbar *scrollPtr,\n\t\t\t    int x, int y);\n\n#endif /* _TKSCROLLBAR */\n"
  },
  {
    "path": "generic/tkSelect.c",
    "content": "/*\n * tkSelect.c --\n *\n *\tThis file manages the selection for the Tk toolkit, translating\n *\tbetween the standard X ICCCM conventions and Tcl commands.\n *\n * Copyright © 1990-1993 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkSelect.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * When a selection handler is set up by invoking \"selection handle\", one of\n * the following data structures is set up to hold information about the\n * command to invoke and its interpreter.\n */\n\ntypedef struct {\n    Tcl_Interp *interp;\t\t/* Interpreter in which to invoke command. */\n    Tcl_Size cmdLength;\t\t/* # of non-NULL bytes in command. */\n    Tcl_Size charOffset;\t\t/* The offset of the next char to retrieve. */\n    Tcl_Size byteOffset;\t/* The expected byte offset of the next\n\t\t\t\t * chunk. */\n    char buffer[4];\t\t/* A buffer to hold part of a UTF character\n\t\t\t\t * that is split across chunks. */\n    char command[TKFLEXARRAY];\t\t/* Command to invoke. Actual space is\n\t\t\t\t * allocated as large as necessary. This must\n\t\t\t\t * be the last entry in the structure. */\n} CommandInfo;\n\n/*\n * When selection ownership is claimed with the \"selection own\" Tcl command,\n * one of the following structures is created to record the Tcl command to be\n * executed when the selection is lost again.\n */\n\ntypedef struct LostCommand {\n    Tcl_Interp *interp;\t\t/* Interpreter in which to invoke command. */\n    Tcl_Obj *cmdObj;\t\t/* Reference to command to invoke. */\n} LostCommand;\n\n/*\n * The structure below is used to keep each thread's pending list separate.\n */\n\ntypedef struct {\n    TkSelInProgress *pendingPtr;\n\t\t\t\t/* Topmost search in progress, or NULL if\n\t\t\t\t * none. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic Tcl_Size\tHandleTclCommand(void *clientData,\n\t\t\t    Tcl_Size offset, char *buffer, Tcl_Size maxBytes);\nstatic void\t\tLostSelection(void *clientData);\nstatic int\t\tSelGetProc(void *clientData,\n\t\t\t    Tcl_Interp *interp, const char *portion);\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateSelHandler --\n *\n *\tThis function is called to register a function as the handler for\n *\tselection requests of a particular target type on a particular window\n *\tfor a particular selection.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n\n *\tIn the future, whenever the selection is in tkwin's window and someone\n *\trequests the selection in the form given by target, proc will be\n *\tinvoked to provide part or all of the selection in the given form. If\n *\tthere was already a handler declared for the given window, target and\n *\tselection type, then it is replaced. Proc should have the following\n *\tform:\n *\n *\tint\n *\tproc(\n *\t    void *clientData,\n *\t    int offset,\n *\t    char *buffer,\n *\t    int maxBytes)\n *\t{\n *\t}\n *\n *\tThe clientData argument to proc will be the same as the clientData\n *\targument to this function. The offset argument indicates which portion\n *\tof the selection to return: skip the first offset bytes. Buffer is a\n *\tpointer to an area in which to place the converted selection, and\n *\tmaxBytes gives the number of bytes available at buffer. Proc should\n *\tplace the selection in buffer as a string, and return a count of the\n *\tnumber of bytes of selection actually placed in buffer (not including\n *\tthe terminating NULL character). If the return value equals maxBytes,\n *\tthis is a sign that there is probably still more selection information\n *\tavailable.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_CreateSelHandler(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Atom selection,\t\t/* Selection to be handled. */\n    Atom target,\t\t/* The kind of selection conversions that can\n\t\t\t\t * be handled by proc, e.g. TARGETS or\n\t\t\t\t * STRING. */\n    Tk_SelectionProc *proc,\t/* Function to invoke to convert selection to\n\t\t\t\t * type \"target\". */\n    void *clientData,\t/* Value to pass to proc. */\n    Atom format)\t\t/* Format in which the selection information\n\t\t\t\t * should be returned to the requestor.\n\t\t\t\t * XA_STRING is best by far, but anything\n\t\t\t\t * listed in the ICCCM will be tolerated\n\t\t\t\t * (blech). */\n{\n    TkSelHandler *selPtr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (winPtr->dispPtr->multipleAtom == None) {\n\tTkSelInit(tkwin);\n    }\n\n    /*\n     * See if there's already a handler for this target and selection on this\n     * window. If so, re-use it. If not, create a new one.\n     */\n\n    for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {\n\tif (selPtr == NULL) {\n\t    selPtr = (TkSelHandler *)Tcl_Alloc(sizeof(TkSelHandler));\n\t    selPtr->nextPtr = winPtr->selHandlerList;\n\t    winPtr->selHandlerList = selPtr;\n\t    break;\n\t}\n\tif ((selPtr->selection == selection) && (selPtr->target == target)) {\n\t    /*\n\t     * Special case: when replacing handler created by \"selection\n\t     * handle\", free up memory. Should there be a callback to allow\n\t     * other clients to do this too?\n\t     */\n\n\t    if (selPtr->proc == HandleTclCommand) {\n\t\tTcl_Free(selPtr->clientData);\n\t    }\n\t    break;\n\t}\n    }\n    selPtr->selection = selection;\n    selPtr->target = target;\n    selPtr->format = format;\n    selPtr->proc = proc;\n    selPtr->clientData = clientData;\n    if (format == XA_STRING) {\n\tselPtr->size = 8;\n    } else {\n\tselPtr->size = 32;\n    }\n\n    if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) {\n\t/*\n\t * If the user asked for a STRING handler and we understand\n\t * UTF8_STRING, we implicitly create a UTF8_STRING handler for them.\n\t */\n\n\ttarget = winPtr->dispPtr->utf8Atom;\n\tfor (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {\n\t    if (selPtr == NULL) {\n\t\tselPtr = (TkSelHandler *)Tcl_Alloc(sizeof(TkSelHandler));\n\t\tselPtr->nextPtr = winPtr->selHandlerList;\n\t\twinPtr->selHandlerList = selPtr;\n\t\tselPtr->selection = selection;\n\t\tselPtr->target = target;\n\t\tselPtr->format = target; /* We want UTF8_STRING format */\n\t\tselPtr->proc = proc;\n\t\tif (selPtr->proc == HandleTclCommand) {\n\t\t    /*\n\t\t     * The clientData is selection controlled memory, so we\n\t\t     * should make a copy for this selPtr.\n\t\t     */\n\n\t\t    size_t cmdInfoLen = offsetof(CommandInfo, command) + 1 +\n\t\t\t    ((CommandInfo *)clientData)->cmdLength;\n\n\t\t    selPtr->clientData = Tcl_Alloc(cmdInfoLen);\n\t\t    memcpy(selPtr->clientData, clientData, cmdInfoLen);\n\t\t} else {\n\t\t    selPtr->clientData = clientData;\n\t\t}\n\t\tselPtr->size = 8;\n\t\tbreak;\n\t    }\n\t    if (selPtr->selection==selection && selPtr->target==target) {\n\t\t/*\n\t\t * Looks like we had a utf-8 target already. Leave it alone.\n\t\t */\n\n\t\tbreak;\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DeleteSelHandler --\n *\n *\tRemove the selection handler for a given window, target, and\n *\tselection, if it exists.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe selection handler for tkwin and target is removed. If there is no\n *\tsuch handler then nothing happens.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DeleteSelHandler(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Atom selection,\t\t/* The selection whose handler is to be\n\t\t\t\t * removed. */\n    Atom target)\t\t/* The target whose selection handler is to be\n\t\t\t\t * removed. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkSelHandler *selPtr, *prevPtr;\n    TkSelInProgress *ipPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Find the selection handler to be deleted, or return if it doesn't\n     * exist.\n     */\n\n    for (selPtr = winPtr->selHandlerList, prevPtr = NULL; ;\n\t    prevPtr = selPtr, selPtr = selPtr->nextPtr) {\n\tif (selPtr == NULL) {\n\t    return;\n\t}\n\tif ((selPtr->selection == selection) && (selPtr->target == target)) {\n\t    break;\n\t}\n    }\n\n    /*\n     * If ConvertSelection is processing this handler, tell it that the\n     * handler is dead.\n     */\n\n    for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;\n\t    ipPtr = ipPtr->nextPtr) {\n\tif (ipPtr->selPtr == selPtr) {\n\t    ipPtr->selPtr = NULL;\n\t}\n    }\n\n    /*\n     * Free resources associated with the handler.\n     */\n\n    if (prevPtr == NULL) {\n\twinPtr->selHandlerList = selPtr->nextPtr;\n    } else {\n\tprevPtr->nextPtr = selPtr->nextPtr;\n    }\n\n    if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) {\n\t/*\n\t * If the user asked for a STRING handler and we understand\n\t * UTF8_STRING, we may have implicitly created a UTF8_STRING handler\n\t * for them. Look for it and delete it as necessary.\n\t */\n\n\tTkSelHandler *utf8selPtr;\n\n\ttarget = winPtr->dispPtr->utf8Atom;\n\tfor (utf8selPtr = winPtr->selHandlerList; utf8selPtr != NULL;\n\t\tutf8selPtr = utf8selPtr->nextPtr) {\n\t    if ((utf8selPtr->selection == selection)\n\t\t    && (utf8selPtr->target == target)) {\n\t\tbreak;\n\t    }\n\t}\n\tif (utf8selPtr != NULL) {\n\t    if ((utf8selPtr->format == target)\n\t\t    && (utf8selPtr->proc == selPtr->proc)\n\t\t    && (utf8selPtr->size == selPtr->size)) {\n\t\t/*\n\t\t * This recursive call is OK, because we've changed the value\n\t\t * of 'target'.\n\t\t */\n\n\t\tTk_DeleteSelHandler(tkwin, selection, target);\n\t    }\n\t}\n    }\n\n    if (selPtr->proc == HandleTclCommand) {\n\t/*\n\t * Mark the CommandInfo as deleted and free it if we can.\n\t */\n\n\t((CommandInfo *) selPtr->clientData)->interp = NULL;\n\tTcl_EventuallyFree(selPtr->clientData, TCL_DYNAMIC);\n    }\n    Tcl_Free(selPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_OwnSelection --\n *\n *\tArrange for tkwin to become the owner of a selection.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrom now on, requests for the selection will be directed to functions\n *\tassociated with tkwin (they must have been declared with calls to\n *\tTk_CreateSelHandler). When the selection is lost by this window, proc\n *\twill be invoked (see the manual entry for details). This function may\n *\tinvoke callbacks, including Tcl scripts, so any calling function\n *\tshould be reentrant at the point where Tk_OwnSelection is invoked.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_OwnSelection(\n    Tk_Window tkwin,\t\t/* Window to become new selection owner. */\n    Atom selection,\t\t/* Selection that window should own. */\n    Tk_LostSelProc *proc,\t/* Function to call when selection is taken\n\t\t\t\t * away from tkwin. */\n    void *clientData)\t/* Arbitrary one-word argument to pass to\n\t\t\t\t * proc. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkSelectionInfo *infoPtr;\n    Tk_LostSelProc *clearProc = NULL;\n    void *clearData = NULL;/* Initialization needed only to prevent\n\t\t\t\t * compiler warning. */\n\n    if (dispPtr->multipleAtom == None) {\n\tTkSelInit(tkwin);\n    }\n    Tk_MakeWindowExist(tkwin);\n\n    /*\n     * This code is somewhat tricky. First, we find the specified selection on\n     * the selection list. If the previous owner is in this process, and is a\n     * different window, then we need to invoke the clearProc. However, it's\n     * dangerous to call the clearProc right now, because it could invoke a\n     * Tcl script that wrecks the current state (e.g. it could delete the\n     * window). To be safe, defer the call until the end of the function when\n     * we no longer care about the state.\n     */\n\n    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;\n\t    infoPtr = infoPtr->nextPtr) {\n\tif (infoPtr->selection == selection) {\n\t    break;\n\t}\n    }\n    if (infoPtr == NULL) {\n\tinfoPtr = (TkSelectionInfo *)Tcl_Alloc(sizeof(TkSelectionInfo));\n\tinfoPtr->selection = selection;\n\tinfoPtr->nextPtr = dispPtr->selectionInfoPtr;\n\tdispPtr->selectionInfoPtr = infoPtr;\n    } else if (infoPtr->clearProc != NULL) {\n\tif (infoPtr->owner != tkwin) {\n\t    clearProc = infoPtr->clearProc;\n\t    clearData = infoPtr->clearData;\n\t} else if (infoPtr->clearProc == LostSelection) {\n\t    /*\n\t     * If the selection handler is one created by \"selection own\", be\n\t     * sure to free the record for it; otherwise there will be a\n\t     * memory leak.\n\t     */\n\n\t    Tcl_Free(infoPtr->clearData);\n\t}\n    }\n\n    infoPtr->owner = tkwin;\n    infoPtr->serial = NextRequest(winPtr->display);\n    infoPtr->clearProc = proc;\n    infoPtr->clearData = clientData;\n\n    /*\n     * Note that we are using CurrentTime, even though ICCCM recommends\n     * against this practice (the problem is that we don't necessarily have a\n     * valid time to use). We will not be able to retrieve a useful timestamp\n     * for the TIMESTAMP target later.\n     */\n\n    infoPtr->time = CurrentTime;\n\n    /*\n     * Note that we are not checking to see if the selection claim succeeded.\n     * If the ownership does not change, then the clearProc may never be\n     * invoked, and we will return incorrect information when queried for the\n     * current selection owner.\n     */\n\n    XSetSelectionOwner(winPtr->display, infoPtr->selection, winPtr->window,\n\t    infoPtr->time);\n\n    /*\n     * Now that we are done, we can invoke clearProc without running into\n     * reentrancy problems.\n     */\n\n    if (clearProc != NULL) {\n\tclearProc(clearData);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ClearSelection --\n *\n *\tEliminate the specified selection on tkwin's display, if there is one.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe specified selection is cleared, so that future requests to\n *\tretrieve it will fail until some application owns it again. This\n *\tfunction invokes callbacks, possibly including Tcl scripts, so any\n *\tcalling function should be reentrant at the point Tk_ClearSelection is\n *\tinvoked.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ClearSelection(\n    Tk_Window tkwin,\t\t/* Window that selects a display. */\n    Atom selection)\t\t/* Selection to be cancelled. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkSelectionInfo *infoPtr;\n    TkSelectionInfo *prevPtr;\n    TkSelectionInfo *nextPtr;\n    Tk_LostSelProc *clearProc = NULL;\n    void *clearData = NULL;/* Initialization needed only to prevent\n\t\t\t\t * compiler warning. */\n\n    if (dispPtr->multipleAtom == None) {\n\tTkSelInit(tkwin);\n    }\n\n    for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;\n\t    infoPtr != NULL; infoPtr = nextPtr) {\n\tnextPtr = infoPtr->nextPtr;\n\tif (infoPtr->selection == selection) {\n\t    if (prevPtr == NULL) {\n\t\tdispPtr->selectionInfoPtr = nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = nextPtr;\n\t    }\n\t    break;\n\t}\n\tprevPtr = infoPtr;\n    }\n\n    if (infoPtr != NULL) {\n\tclearProc = infoPtr->clearProc;\n\tclearData = infoPtr->clearData;\n\tTcl_Free(infoPtr);\n    }\n    XSetSelectionOwner(winPtr->display, selection, None, CurrentTime);\n\n    if (clearProc != NULL) {\n\tclearProc(clearData);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_GetSelection --\n *\n *\tRetrieve the value of a selection and pass it off (in pieces,\n *\tpossibly) to a given function.\n *\n * Results:\n *\tThe return value is a standard Tcl return value. If an error occurs\n *\t(such as no selection exists) then an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tThe standard X11 protocols are used to retrieve the selection. When it\n *\tarrives, it is passed to proc. If the selection is very large, it will\n *\tbe passed to proc in several pieces. Proc should have the following\n *\tstructure:\n *\n *\tint\n *\tproc(\n *\t    void *clientData,\n *\t    Tcl_Interp *interp,\n *\t    char *portion)\n *\t{\n *\t}\n *\n *\tThe interp and clientData arguments to proc will be the same as the\n *\tcorresponding arguments to Tk_GetSelection. The portion argument\n *\tpoints to a character string containing part of the selection, and\n *\tnumBytes indicates the length of the portion, not including the\n *\tterminating NULL character. If the selection arrives in several\n *\tpieces, the \"portion\" arguments in separate calls will contain\n *\tsuccessive parts of the selection. Proc should normally return TCL_OK.\n *\tIf it detects an error then it should return TCL_ERROR and leave an\n *\terror message in the interp's result; the remainder of the selection\n *\tretrieval will be aborted.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_GetSelection(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tk_Window tkwin,\t\t/* Window on whose behalf to retrieve the\n\t\t\t\t * selection (determines display from which to\n\t\t\t\t * retrieve). */\n    Atom selection,\t\t/* Selection to retrieve. */\n    Atom target,\t\t/* Desired form in which selection is to be\n\t\t\t\t * returned. */\n    Tk_GetSelProc *proc,\t/* Function to call to process the selection,\n\t\t\t\t * once it has been retrieved. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkSelectionInfo *infoPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (dispPtr->multipleAtom == None) {\n\tTkSelInit(tkwin);\n    }\n\n    /*\n     * If the selection is owned by a window managed by this process, then\n     * call the retrieval function directly, rather than going through the X\n     * server (it's dangerous to go through the X server in this case because\n     * it could result in deadlock if an INCR-style selection results).\n     */\n\n    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;\n\t    infoPtr = infoPtr->nextPtr) {\n\tif (infoPtr->selection == selection) {\n\t    break;\n\t}\n    }\n    if (infoPtr != NULL) {\n\tTkSelHandler *selPtr;\n\tTcl_Size offset, count;\n\tint result;\n\tchar buffer[TK_SEL_BYTES_AT_ONCE+1];\n\tTkSelInProgress ip;\n\n\tfor (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList;\n\t\tselPtr != NULL; selPtr = selPtr->nextPtr) {\n\t    if (selPtr->target==target && selPtr->selection==selection) {\n\t\tbreak;\n\t    }\n\t}\n\tif (selPtr == NULL) {\n\t    Atom type;\n\n\t    count = TkSelDefaultSelection(infoPtr, target, buffer,\n\t\t    TK_SEL_BYTES_AT_ONCE, &type);\n\t    if (count < 0) {\n\t\tgoto cantget;\n\t    } else if (count > TK_SEL_BYTES_AT_ONCE) {\n\t\tTcl_Panic(\"selection handler returned too many bytes\");\n\t    }\n\t    buffer[count] = 0;\n\t    result = proc(clientData, interp, buffer);\n\t} else {\n\t    offset = 0;\n\t    result = TCL_OK;\n\t    ip.selPtr = selPtr;\n\t    ip.nextPtr = tsdPtr->pendingPtr;\n\t    tsdPtr->pendingPtr = &ip;\n\t    while (1) {\n\t\tcount = selPtr->proc(selPtr->clientData, offset, buffer,\n\t\t\tTK_SEL_BYTES_AT_ONCE);\n\t\tif ((count < 0) || (ip.selPtr == NULL)) {\n\t\t    tsdPtr->pendingPtr = ip.nextPtr;\n\t\t    goto cantget;\n\t\t}\n\t\tif (count > TK_SEL_BYTES_AT_ONCE) {\n\t\t    Tcl_Panic(\"selection handler returned too many bytes\");\n\t\t}\n\t\tbuffer[count] = '\\0';\n\t\tresult = proc(clientData, interp, buffer);\n\t\tif ((result != TCL_OK) || (count < TK_SEL_BYTES_AT_ONCE)\n\t\t\t|| (ip.selPtr == NULL)) {\n\t\t    break;\n\t\t}\n\t\toffset += count;\n\t    }\n\t    tsdPtr->pendingPtr = ip.nextPtr;\n\t}\n\treturn result;\n    }\n\n    /*\n     * The selection is owned by some other process.\n     */\n\n    return TkSelGetSelection(interp, tkwin, selection, target, proc,\n\t    clientData);\n\n  cantget:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"%s selection doesn't exist or form \\\"%s\\\" not defined\",\n\t    Tk_GetAtomName(tkwin, selection),\n\t    Tk_GetAtomName(tkwin, target)));\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SelectionObjCmd --\n *\n *\tThis function is invoked to process the \"selection\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SelectionObjCmd(\n    void *clientData,\t/* Main window associated with\n\t\t\t\t * interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    const char *path = NULL;\n    Atom selection;\n    const char *selName = NULL;\n    const char *string;\n    Tcl_Size count;\n    int index;\n    Tcl_Obj *const *objs;\n    static const char *const optionStrings[] = {\n\t\"clear\", \"get\", \"handle\", \"own\", NULL\n    };\n    enum options {\n\tSELECTION_CLEAR, SELECTION_GET, SELECTION_HANDLE, SELECTION_OWN\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, \"option\", 0,\n\t    &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case SELECTION_CLEAR: {\n\tstatic const char *const clearOptionStrings[] = {\n\t    \"-displayof\", \"-selection\", NULL\n\t};\n\tenum clearOptions { CLEAR_DISPLAYOF, CLEAR_SELECTION };\n\tint clearIndex;\n\n\tfor (count = objc-2, objs = objv+2; count > 0;\n\t\tcount-=2, objs+=2) {\n\t    string = Tcl_GetString(objs[0]);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\t    if (count < 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (Tcl_GetIndexFromObj(interp, objs[0], clearOptionStrings,\n\t\t    \"option\", 0, &clearIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    switch ((enum clearOptions) clearIndex) {\n\t    case CLEAR_DISPLAYOF:\n\t\tpath = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case CLEAR_SELECTION:\n\t\tselName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    }\n\t}\n\n\tif (count == 1) {\n\t    path = Tcl_GetString(objs[0]);\n\t} else if (count > 1) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (path != NULL) {\n\t    tkwin = Tk_NameToWindow(interp, path, tkwin);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (selName != NULL) {\n\t    selection = Tk_InternAtom(tkwin, selName);\n\t} else {\n\t    selection = XA_PRIMARY;\n\t}\n\n\tTk_ClearSelection(tkwin, selection);\n\tbreak;\n    }\n\n    case SELECTION_GET: {\n\tAtom target;\n\tconst char *targetName = NULL;\n\tTcl_DString selBytes;\n\tint result;\n\tstatic const char *const getOptionStrings[] = {\n\t    \"-displayof\", \"-selection\", \"-type\", NULL\n\t};\n\tenum getOptions { GET_DISPLAYOF, GET_SELECTION, GET_TYPE };\n\tint getIndex;\n\n\tfor (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count>0;\n\t\tcount-=2, objs+=2) {\n\t    string = Tcl_GetString(objs[0]);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\t    if (count < 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (Tcl_GetIndexFromObj(interp, objs[0], getOptionStrings,\n\t\t    \"option\", 0, &getIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    switch ((enum getOptions) getIndex) {\n\t    case GET_DISPLAYOF:\n\t\tpath = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case GET_SELECTION:\n\t\tselName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case GET_TYPE:\n\t\ttargetName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    }\n\t}\n\n\tif (path != NULL) {\n\t    tkwin = Tk_NameToWindow(interp, path, tkwin);\n\t}\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (selName != NULL) {\n\t    selection = Tk_InternAtom(tkwin, selName);\n\t} else {\n\t    selection = XA_PRIMARY;\n\t}\n\tif (count > 1) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...?\");\n\t    return TCL_ERROR;\n\t} else if (count == 1) {\n\t    target = Tk_InternAtom(tkwin, Tcl_GetString(objs[0]));\n\t} else if (targetName != NULL) {\n\t    target = Tk_InternAtom(tkwin, targetName);\n\t} else {\n\t    target = XA_STRING;\n\t}\n\n\tTcl_DStringInit(&selBytes);\n\tresult = Tk_GetSelection(interp, tkwin, selection, target,\n\t\tSelGetProc, &selBytes);\n\tif (result == TCL_OK) {\n\t    Tcl_DStringResult(interp, &selBytes);\n\t} else {\n\t    Tcl_DStringFree(&selBytes);\n\t}\n\treturn result;\n    }\n\n    case SELECTION_HANDLE: {\n\tAtom target, format;\n\tconst char *targetName = NULL;\n\tconst char *formatName = NULL;\n\tCommandInfo *cmdInfoPtr;\n\tTcl_Size cmdLength;\n\tstatic const char *const handleOptionStrings[] = {\n\t    \"-format\", \"-selection\", \"-type\", NULL\n\t};\n\tenum handleOptions {\n\t    HANDLE_FORMAT, HANDLE_SELECTION, HANDLE_TYPE\n\t};\n\tint handleIndex;\n\n\tfor (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0;\n\t\tcount-=2, objs+=2) {\n\t    string = Tcl_GetString(objs[0]);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\t    if (count < 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (Tcl_GetIndexFromObj(interp, objs[0],handleOptionStrings,\n\t\t    \"option\", 0, &handleIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    switch ((enum handleOptions) handleIndex) {\n\t    case HANDLE_FORMAT:\n\t\tformatName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case HANDLE_SELECTION:\n\t\tselName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case HANDLE_TYPE:\n\t\ttargetName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    }\n\t}\n\n\tif ((count < 2) || (count > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"?-option value ...? window command\");\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (selName != NULL) {\n\t    selection = Tk_InternAtom(tkwin, selName);\n\t} else {\n\t    selection = XA_PRIMARY;\n\t}\n\n\tif (count > 2) {\n\t    target = Tk_InternAtom(tkwin, Tcl_GetString(objs[2]));\n\t} else if (targetName != NULL) {\n\t    target = Tk_InternAtom(tkwin, targetName);\n\t} else {\n\t    target = XA_STRING;\n\t}\n\tif (count > 3) {\n\t    format = Tk_InternAtom(tkwin, Tcl_GetString(objs[3]));\n\t} else if (formatName != NULL) {\n\t    format = Tk_InternAtom(tkwin, formatName);\n\t} else {\n\t    format = XA_STRING;\n\t}\n\tstring = Tcl_GetStringFromObj(objs[1], &cmdLength);\n\tif (cmdLength == 0) {\n\t    Tk_DeleteSelHandler(tkwin, selection, target);\n\t} else {\n\t    cmdInfoPtr = (CommandInfo *)Tcl_Alloc(offsetof(CommandInfo, command)\n\t\t    + 1 + cmdLength);\n\t    cmdInfoPtr->interp = interp;\n\t    cmdInfoPtr->charOffset = 0;\n\t    cmdInfoPtr->byteOffset = 0;\n\t    cmdInfoPtr->buffer[0] = '\\0';\n\t    cmdInfoPtr->cmdLength = cmdLength;\n\t    memcpy(cmdInfoPtr->command, string, cmdLength + 1);\n\t    Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand,\n\t\t    cmdInfoPtr, format);\n\t}\n\treturn TCL_OK;\n    }\n\n    case SELECTION_OWN: {\n\tLostCommand *lostPtr;\n\tTcl_Obj *commandObj = NULL;\n\tstatic const char *const ownOptionStrings[] = {\n\t    \"-command\", \"-displayof\", \"-selection\", NULL\n\t};\n\tenum ownOptions { OWN_COMMAND, OWN_DISPLAYOF, OWN_SELECTION };\n\tint ownIndex;\n\n\tfor (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0;\n\t\tcount-=2, objs+=2) {\n\t    string = Tcl_GetString(objs[0]);\n\t    if (string[0] != '-') {\n\t\tbreak;\n\t    }\n\t    if (count < 2) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"value for \\\"%s\\\" missing\", string));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    if (Tcl_GetIndexFromObj(interp, objs[0], ownOptionStrings,\n\t\t    \"option\", 0, &ownIndex) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    switch ((enum ownOptions) ownIndex) {\n\t    case OWN_COMMAND:\n\t\tcommandObj = objs[1];\n\t\tbreak;\n\t    case OWN_DISPLAYOF:\n\t\tpath = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    case OWN_SELECTION:\n\t\tselName = Tcl_GetString(objs[1]);\n\t\tbreak;\n\t    }\n\t}\n\n\tif (count > 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-option value ...? ?window?\");\n\t    return TCL_ERROR;\n\t}\n\tif (selName != NULL) {\n\t    selection = Tk_InternAtom(tkwin, selName);\n\t} else {\n\t    selection = XA_PRIMARY;\n\t}\n\n\tif (count == 0) {\n\t    TkSelectionInfo *infoPtr;\n\t    TkWindow *winPtr;\n\n\t    if (path != NULL) {\n\t\ttkwin = Tk_NameToWindow(interp, path, tkwin);\n\t    }\n\t    if (tkwin == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    winPtr = (TkWindow *) tkwin;\n\t    for (infoPtr = winPtr->dispPtr->selectionInfoPtr;\n\t\t    infoPtr != NULL; infoPtr = infoPtr->nextPtr) {\n\t\tif (infoPtr->selection == selection) {\n\t\t    break;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Ignore the internal clipboard window.\n\t     */\n\n\t    if ((infoPtr != NULL)\n\t\t    && (infoPtr->owner != winPtr->dispPtr->clipWindow)) {\n\t\tTcl_SetObjResult(interp, Tk_NewWindowObj(infoPtr->owner));\n\t    }\n\t    return TCL_OK;\n\t}\n\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (count == 2) {\n\t    commandObj = objs[1];\n\t}\n\tif (commandObj == NULL) {\n\t    Tk_OwnSelection(tkwin, selection, NULL, NULL);\n\t    return TCL_OK;\n\t}\n\tlostPtr = (LostCommand *)Tcl_Alloc(sizeof(LostCommand));\n\tlostPtr->interp = interp;\n\tlostPtr->cmdObj = commandObj;\n\tTcl_IncrRefCount(commandObj);\n\tTk_OwnSelection(tkwin, selection, LostSelection, lostPtr);\n\treturn TCL_OK;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelGetInProgress --\n *\n *\tThis function returns a pointer to the thread-local list of pending\n *\tsearches.\n *\n * Results:\n *\tThe return value is a pointer to the first search in progress, or NULL\n *\tif there are none.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkSelInProgress *\nTkSelGetInProgress(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return tsdPtr->pendingPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelSetInProgress --\n *\n *\tThis function is used to set the thread-local list of pending\n *\tsearches. It is required because the pending list is kept in thread\n *\tlocal storage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\nvoid\nTkSelSetInProgress(\n    TkSelInProgress *pendingPtr)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->pendingPtr = pendingPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelDeadWindow --\n *\n *\tThis function is invoked just before a TkWindow is deleted. It\n *\tperforms selection-related cleanup.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees up memory associated with the selection.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelDeadWindow(\n    TkWindow *winPtr)\t/* Window that's being deleted. */\n{\n    TkSelHandler *selPtr;\n    TkSelInProgress *ipPtr;\n    TkSelectionInfo *infoPtr, *prevPtr, *nextPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * While deleting all the handlers, be careful to check whether\n     * ConvertSelection or TkSelPropProc are about to process one of the\n     * deleted handlers.\n     */\n\n    while (winPtr->selHandlerList != NULL) {\n\tselPtr = winPtr->selHandlerList;\n\twinPtr->selHandlerList = selPtr->nextPtr;\n\tfor (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;\n\t\tipPtr = ipPtr->nextPtr) {\n\t    if (ipPtr->selPtr == selPtr) {\n\t\tipPtr->selPtr = NULL;\n\t    }\n\t}\n\tif (selPtr->proc == HandleTclCommand) {\n\t    /*\n\t     * Mark the CommandInfo as deleted and free it when we can.\n\t     */\n\n\t    ((CommandInfo *) selPtr->clientData)->interp = NULL;\n\t    Tcl_EventuallyFree(selPtr->clientData, TCL_DYNAMIC);\n\t}\n\tTcl_Free(selPtr);\n    }\n\n    /*\n     * Remove selections owned by window being deleted.\n     */\n\n    for (infoPtr = winPtr->dispPtr->selectionInfoPtr, prevPtr = NULL;\n\t    infoPtr != NULL; infoPtr = nextPtr) {\n\tnextPtr = infoPtr->nextPtr;\n\tif (infoPtr->owner == (Tk_Window) winPtr) {\n\t    if (infoPtr->clearProc == LostSelection) {\n\t\tTcl_Free(infoPtr->clearData);\n\t    }\n\t    Tcl_Free(infoPtr);\n\t    infoPtr = prevPtr;\n\t    if (prevPtr == NULL) {\n\t\twinPtr->dispPtr->selectionInfoPtr = nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = nextPtr;\n\t    }\n\t}\n\tprevPtr = infoPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelInit --\n *\n *\tInitialize selection-related information for a display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSelection-related information is initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelInit(\n    Tk_Window tkwin)\t\t/* Window token (used to find display to\n\t\t\t\t * initialize). */\n{\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    /*\n     * Fetch commonly-used atoms.\n     */\n\n    dispPtr->multipleAtom\t= Tk_InternAtom(tkwin, \"MULTIPLE\");\n    dispPtr->incrAtom\t\t= Tk_InternAtom(tkwin, \"INCR\");\n    dispPtr->targetsAtom\t= Tk_InternAtom(tkwin, \"TARGETS\");\n    dispPtr->timestampAtom\t= Tk_InternAtom(tkwin, \"TIMESTAMP\");\n    dispPtr->textAtom\t\t= Tk_InternAtom(tkwin, \"TEXT\");\n    dispPtr->compoundTextAtom\t= Tk_InternAtom(tkwin, \"COMPOUND_TEXT\");\n    dispPtr->applicationAtom\t= Tk_InternAtom(tkwin, \"TK_APPLICATION\");\n    dispPtr->windowAtom\t\t= Tk_InternAtom(tkwin, \"TK_WINDOW\");\n    dispPtr->clipboardAtom\t= Tk_InternAtom(tkwin, \"CLIPBOARD\");\n    dispPtr->atomPairAtom\t= Tk_InternAtom(tkwin, \"ATOM_PAIR\");\n\n    /*\n     * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us to\n     * support older X servers that didn't have UTF8_STRING yet. This is\n     * necessary on Unix systems. For more information, see:\n     *\t  https://www.cl.cam.ac.uk/~mgk25/unicode.html#x11\n     */\n\n#if !defined(_WIN32)\n    dispPtr->utf8Atom\t\t= Tk_InternAtom(tkwin, \"UTF8_STRING\");\n#else\n    dispPtr->utf8Atom\t\t= (Atom) 0;\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelClearSelection --\n *\n *\tThis function is invoked to process a SelectionClear event.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInvokes the clear function for the window which lost the\n *\tselection.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelClearSelection(\n    Tk_Window tkwin,\t\t/* Window for which event was targeted. */\n    XEvent *eventPtr)\t/* X SelectionClear event. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    TkSelectionInfo *infoPtr;\n    TkSelectionInfo *prevPtr;\n\n    /*\n     * Invoke clear function for window that just lost the selection. This\n     * code is a bit tricky, because any callbacks due to selection changes\n     * between windows managed by the process have already been made. Thus,\n     * ignore the event unless it refers to the window that's currently the\n     * selection owner and the event was generated after the server saw the\n     * SetSelectionOwner request.\n     */\n\n    for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;\n\t    infoPtr != NULL; infoPtr = infoPtr->nextPtr) {\n\tif (infoPtr->selection == eventPtr->xselectionclear.selection) {\n\t    break;\n\t}\n\tprevPtr = infoPtr;\n    }\n\n    if (infoPtr != NULL && (infoPtr->owner == tkwin) &&\n\t    (eventPtr->xselectionclear.serial >= (unsigned long) infoPtr->serial)) {\n\tif (prevPtr == NULL) {\n\t    dispPtr->selectionInfoPtr = infoPtr->nextPtr;\n\t} else {\n\t    prevPtr->nextPtr = infoPtr->nextPtr;\n\t}\n\n\t/*\n\t * Because of reentrancy problems, calling clearProc must be done\n\t * after the infoPtr has been removed from the selectionInfoPtr list\n\t * (clearProc could modify the list, e.g. by creating a new\n\t * selection).\n\t */\n\n\tif (infoPtr->clearProc != NULL) {\n\t    infoPtr->clearProc(infoPtr->clearData);\n\t}\n\tTcl_Free(infoPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SelGetProc --\n *\n *\tThis function is invoked to process pieces of the selection as they\n *\tarrive during \"selection get\" commands.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tBytes get appended to the dynamic string pointed to by the clientData\n *\targument.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSelGetProc(\n    void *clientData,\t/* Dynamic string holding partially assembled\n\t\t\t\t * selection. */\n    TCL_UNUSED(Tcl_Interp *),\t/* Interpreter used for error reporting (not\n\t\t\t\t * used). */\n    const char *portion)\t/* New information to be appended. */\n{\n    Tcl_DStringAppend((Tcl_DString *)clientData, portion, TCL_INDEX_NONE);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * HandleTclCommand --\n *\n *\tThis function acts as selection handler for handlers created by the\n *\t\"selection handle\" command. It invokes a Tcl command to retrieve the\n *\tselection.\n *\n * Results:\n *\tThe return value is a count of the number of bytes actually stored at\n *\tbuffer, or -1 if an error occurs while executing the Tcl command to\n *\tretrieve the selection.\n *\n * Side effects:\n *\tNone except for things done by the Tcl command.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nHandleTclCommand(\n    void *clientData,\t/* Information about command to execute. */\n    Tcl_Size offset,\t\t\t/* Return selection bytes starting at this\n\t\t\t\t * offset. */\n    char *buffer,\t\t/* Place to store converted selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum # of bytes to store at buffer. */\n{\n    CommandInfo *cmdInfoPtr = (CommandInfo *)clientData;\n    Tcl_Size length;\n    Tcl_Obj *command;\n    const char *string;\n    Tcl_Interp *interp = cmdInfoPtr->interp;\n    Tcl_InterpState savedState;\n    int code;\n    Tcl_Size extraBytes, charOffset, numChars, count;\n    const char *p;\n\n    /*\n     * We must also protect the interpreter and the command from being deleted\n     * too soon.\n     */\n\n    Tcl_Preserve(clientData);\n    Tcl_Preserve(interp);\n\n    /*\n     * Compute the proper byte offset in the case where the last chunk split a\n     * character.\n     */\n\n    if (offset == cmdInfoPtr->byteOffset) {\n\tcharOffset = cmdInfoPtr->charOffset;\n\textraBytes = strlen(cmdInfoPtr->buffer);\n\tif (extraBytes > 0) {\n\t    strcpy(buffer, cmdInfoPtr->buffer);\n\t    maxBytes -= extraBytes;\n\t    buffer += extraBytes;\n\t}\n    } else {\n\tcmdInfoPtr->byteOffset = 0;\n\tcmdInfoPtr->charOffset = 0;\n\textraBytes = 0;\n\tcharOffset = 0;\n    }\n\n    /*\n     * First, generate a command by taking the command string and appending\n     * the offset and maximum # of bytes.\n     */\n\n    command = Tcl_ObjPrintf(\"%s %\" TCL_SIZE_MODIFIER \"d %\" TCL_SIZE_MODIFIER \"d\",\n\t    cmdInfoPtr->command, charOffset, maxBytes);\n    Tcl_IncrRefCount(command);\n\n    /*\n     * Execute the command. Be sure to restore the state of the interpreter\n     * after executing the command.\n     */\n\n    savedState = Tcl_SaveInterpState(interp, TCL_OK);\n    code = Tcl_EvalObjEx(interp, command, TCL_EVAL_GLOBAL);\n    Tcl_DecrRefCount(command);\n    if (code == TCL_OK) {\n\t/*\n\t * TODO: This assumes that bytes are characters; that's not true!\n\t */\n\n\tstring = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);\n\tcount = (length > maxBytes) ? maxBytes : length;\n\tmemcpy(buffer, string, count);\n\tbuffer[count] = '\\0';\n\n\t/*\n\t * Update the partial character information for the next retrieval if\n\t * the command has not been deleted.\n\t */\n\n\tif (cmdInfoPtr->interp != NULL) {\n\t    if (length <= maxBytes) {\n\t\tcmdInfoPtr->charOffset += Tcl_NumUtfChars(string, TCL_INDEX_NONE);\n\t\tcmdInfoPtr->buffer[0] = '\\0';\n\t    } else {\n\t\tTcl_UniChar ch = 0;\n\t\tp = string;\n\t\tstring += count;\n\t\tnumChars = 0;\n\t\twhile (p < string) {\n\t\t    p += Tcl_UtfToUniChar(p, &ch);\n\t\t    numChars++;\n\t\t}\n\t\tcmdInfoPtr->charOffset += numChars;\n\t\tlength = p - string;\n\t\tif (length > 0) {\n\t\t    strncpy(cmdInfoPtr->buffer, string, length);\n\t\t}\n\t\tcmdInfoPtr->buffer[length] = '\\0';\n\t    }\n\t    cmdInfoPtr->byteOffset += count + extraBytes;\n\t}\n\tcount += extraBytes;\n    } else {\n\t/*\n\t * Something went wrong. Log errors as background errors, and silently\n\t * drop everything else.\n\t */\n\n\tif (code == TCL_ERROR) {\n\t    Tcl_AddErrorInfo(interp, \"\\n    (command handling selection)\");\n\t    Tcl_BackgroundException(interp, code);\n\t}\n\tcount = TCL_INDEX_NONE;\n    }\n    (void) Tcl_RestoreInterpState(interp, savedState);\n\n    Tcl_Release(clientData);\n    Tcl_Release(interp);\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelDefaultSelection --\n *\n *\tThis function is called to generate selection information for a few\n *\tstandard targets such as TIMESTAMP and TARGETS. It is invoked only if\n *\tno handler has been declared by the application.\n *\n * Results:\n *\tIf \"target\" is a standard target understood by this function, the\n *\tselection is converted to that form and stored as a character string\n *\tin buffer. The type of the selection (e.g. STRING or ATOM) is stored\n *\tin *typePtr, and the return value is a count of the # of non-NULL\n *\tbytes at buffer. If the target wasn't understood, or if there isn't\n *\tenough space at buffer to hold the entire selection (no INCR-mode\n *\ttransfers for this stuff!), then TCL_INDEX_NONE is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkSelDefaultSelection(\n    TkSelectionInfo *infoPtr,\t/* Info about selection being retrieved. */\n    Atom target,\t\t/* Desired form of selection. */\n    char *buffer,\t\t/* Place to put selection characters. */\n    Tcl_Size maxBytes,\t\t/* Maximum # of bytes to store at buffer. */\n    Atom *typePtr)\t\t/* Store here the type of the selection, for\n\t\t\t\t * use in converting to proper X format. */\n{\n    TkWindow *winPtr = (TkWindow *) infoPtr->owner;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n\n    if (target == dispPtr->timestampAtom) {\n\tif (maxBytes < 20) {\n\t    return TCL_INDEX_NONE;\n\t}\n\tsnprintf(buffer, maxBytes, \"0x%x\", (unsigned int) infoPtr->time);\n\t*typePtr = XA_INTEGER;\n\treturn strlen(buffer);\n    }\n\n    if (target == dispPtr->targetsAtom) {\n\tTkSelHandler *selPtr;\n\tTcl_Size length;\n\tTcl_DString ds;\n\n\tif (maxBytes < 50) {\n\t    return TCL_INDEX_NONE;\n\t}\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds,\n\t\t\"MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW\", TCL_INDEX_NONE);\n\tfor (selPtr = winPtr->selHandlerList; selPtr != NULL;\n\t\tselPtr = selPtr->nextPtr) {\n\t    if ((selPtr->selection == infoPtr->selection)\n\t\t    && (selPtr->target != dispPtr->applicationAtom)\n\t\t    && (selPtr->target != dispPtr->windowAtom)) {\n\t\tconst char *atomString = Tk_GetAtomName((Tk_Window) winPtr,\n\t\t\tselPtr->target);\n\n\t\tTcl_DStringAppendElement(&ds, atomString);\n\t    }\n\t}\n\tlength = Tcl_DStringLength(&ds);\n\tif (length >= maxBytes) {\n\t    Tcl_DStringFree(&ds);\n\t    return TCL_INDEX_NONE;\n\t}\n\tmemcpy(buffer, Tcl_DStringValue(&ds), length + 1);\n\tTcl_DStringFree(&ds);\n\t*typePtr = XA_ATOM;\n\treturn length;\n    }\n\n    if (target == dispPtr->applicationAtom) {\n\tTcl_Size length;\n\tTk_Uid name = winPtr->mainPtr->winPtr->nameUid;\n\n\tlength = strlen(name);\n\tif (maxBytes <= length) {\n\t    return TCL_INDEX_NONE;\n\t}\n\tstrcpy(buffer, name);\n\t*typePtr = XA_STRING;\n\treturn length;\n    }\n\n    if (target == dispPtr->windowAtom) {\n\tTcl_Size length;\n\tchar *name = winPtr->pathName;\n\n\tlength = strlen(name);\n\tif (maxBytes <= length) {\n\t    return TCL_INDEX_NONE;\n\t}\n\tstrcpy(buffer, name);\n\t*typePtr = XA_STRING;\n\treturn length;\n    }\n\n    return TCL_INDEX_NONE;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * LostSelection --\n *\n *\tThis function is invoked when a window has lost ownership of the\n *\tselection and the ownership was claimed with the command \"selection\n *\town\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Tcl script is executed; it can do almost anything.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nLostSelection(\n    void *clientData)\t/* Pointer to LostCommand structure. */\n{\n    LostCommand *lostPtr = (LostCommand *)clientData;\n    Tcl_Interp *interp = lostPtr->interp;\n    Tcl_InterpState savedState;\n    int code;\n\n    Tcl_Preserve(interp);\n\n    /*\n     * Execute the command. Save the interpreter's result, if any, and restore\n     * it after executing the command.\n     */\n\n    savedState = Tcl_SaveInterpState(interp, TCL_OK);\n    Tcl_ResetResult(interp);\n    code = Tcl_EvalObjEx(interp, lostPtr->cmdObj, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_BackgroundException(interp, code);\n    }\n    (void) Tcl_RestoreInterpState(interp, savedState);\n\n    /*\n     * Free the storage for the command, since we're done with it now.\n     */\n\n    Tcl_DecrRefCount(lostPtr->cmdObj);\n    Tcl_Free(lostPtr);\n    Tcl_Release(interp);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkSelect.h",
    "content": "/*\n * tkSelect.h --\n *\n *\tDeclarations of types shared among the files that implement selection\n *\tsupport.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKSELECT\n#define _TKSELECT\n\n/*\n * When a selection is owned by a window on a given display, one of the\n * following structures is present on a list of current selections in the\n * display structure. The structure is used to record the current owner of a\n * selection for use in later retrieval requests. There is a list of such\n * structures because a display can have multiple different selections active\n * at the same time.\n */\n\ntypedef struct TkSelectionInfo {\n    Atom selection;\t\t/* Selection name, e.g. XA_PRIMARY. */\n    Tk_Window owner;\t\t/* Current owner of this selection. */\n    unsigned long serial;\t/* Serial number of last XSelectionSetOwner\n\t\t\t\t * request made to server for this selection\n\t\t\t\t * (used to filter out redundant\n\t\t\t\t * SelectionClear events). */\n    Time time;\t\t\t/* Timestamp used to acquire selection. */\n    Tk_LostSelProc *clearProc;\t/* Procedure to call when owner loses\n\t\t\t\t * selection. */\n    void *clearData;\t/* Info to pass to clearProc. */\n    struct TkSelectionInfo *nextPtr;\n\t\t\t\t/* Next in list of current selections on this\n\t\t\t\t * display. NULL means end of list. */\n} TkSelectionInfo;\n\n/*\n * One of the following structures exists for each selection handler created\n * for a window by calling Tk_CreateSelHandler. The handlers are linked in a\n * list rooted in the TkWindow structure.\n */\n\ntypedef struct TkSelHandler {\n    Atom selection;\t\t/* Selection name, e.g. XA_PRIMARY. */\n    Atom target;\t\t/* Target type for selection conversion, such\n\t\t\t\t * as TARGETS or STRING. */\n    Atom format;\t\t/* Format in which selection info will be\n\t\t\t\t * returned, such as STRING or ATOM. */\n    Tk_SelectionProc *proc;\t/* Procedure to generate selection in this\n\t\t\t\t * format. */\n    void *clientData;\t/* Argument to pass to proc. */\n    Tcl_Size size;\t\t\t/* Size of units returned by proc (8 for\n\t\t\t\t * STRING, 32 for almost anything else). */\n    struct TkSelHandler *nextPtr;\n\t\t\t\t/* Next selection handler associated with same\n\t\t\t\t * window (NULL for end of list). */\n} TkSelHandler;\n\n/*\n * When the selection is being retrieved, one of the following structures is\n * present on a list of pending selection retrievals. The structure is used to\n * communicate between the background procedure that requests the selection\n * and the foreground event handler that processes the events in which the\n * selection is returned. There is a list of such structures so that there can\n * be multiple simultaneous selection retrievals (e.g. on different displays).\n */\n\ntypedef struct TkSelRetrievalInfo {\n    Tcl_Interp *interp;\t\t/* Interpreter for error reporting. */\n    TkWindow *winPtr;\t\t/* Window used as requestor for selection. */\n    Atom selection;\t\t/* Selection being requested. */\n    Atom property;\t\t/* Property where selection will appear. */\n    Atom target;\t\t/* Desired form for selection. */\n    Tk_GetSelProc *proc;\t/* Procedure to call to handle pieces of\n\t\t\t\t * selection. */\n    void *clientData;\t/* Argument for proc. */\n    int result;\t\t\t/* Initially -1. Set to a Tcl return value\n\t\t\t\t * once the selection has been retrieved. */\n    Tcl_TimerToken timeout;\t/* Token for current timeout procedure. */\n    int idleTime;\t\t/* Number of seconds that have gone by without\n\t\t\t\t * hearing anything from the selection\n\t\t\t\t * owner. */\n    Tcl_EncodingState encState;\t/* Holds intermediate state during translations\n\t\t\t\t * of data that cross buffer boundaries. */\n    int encFlags;\t\t/* Encoding translation state flags. */\n    Tcl_DString buf;\t\t/* Buffer to hold translation data. */\n    struct TkSelRetrievalInfo *nextPtr;\n\t\t\t\t/* Next in list of all pending selection\n\t\t\t\t * retrievals. NULL means end of list. */\n} TkSelRetrievalInfo;\n\n/*\n * The clipboard contains a list of buffers of various types and formats. All\n * of the buffers of a given type will be returned in sequence when the\n * CLIPBOARD selection is retrieved. All buffers of a given type on the same\n * clipboard must have the same format. The TkClipboardTarget structure is\n * used to record the information about a chain of buffers of the same type.\n */\n\ntypedef struct TkClipboardBuffer {\n    char *buffer;\t\t/* Null terminated data buffer. */\n    Tcl_Size length;\t\t/* Length of string in buffer. */\n    struct TkClipboardBuffer *nextPtr;\n\t\t\t\t/* Next in list of buffers. NULL means end of\n\t\t\t\t * list . */\n} TkClipboardBuffer;\n\ntypedef struct TkClipboardTarget {\n    Atom type;\t\t\t/* Type conversion supported. */\n    Atom format;\t\t/* Representation used for data. */\n    TkClipboardBuffer *firstBufferPtr;\n\t\t\t\t/* First in list of data buffers. */\n    TkClipboardBuffer *lastBufferPtr;\n\t\t\t\t/* Last in list of clipboard buffers. Used to\n\t\t\t\t * speed up appends. */\n    struct TkClipboardTarget *nextPtr;\n\t\t\t\t/* Next in list of targets on clipboard. NULL\n\t\t\t\t * means end of list. */\n} TkClipboardTarget;\n\n/*\n * Options enum for the TkClipboardObjCmd.  These are defined here\n * so they can be used as an argument to TkSelUpdateClipboard.\n */\n\ntypedef enum {\n    CLIPBOARD_APPEND, CLIPBOARD_CLEAR, CLIPBOARD_GET\n} clipboardOption;\n\n\n/*\n * It is possible for a Tk_SelectionProc to delete the handler that it\n * represents. If this happens, the code that is retrieving the selection\n * needs to know about it so it doesn't use the now-defunct handler structure.\n * One structure of the following form is created for each retrieval in\n * progress, so that the retriever can find out if its handler is deleted. All\n * of the pending retrievals (if there are more than one) are linked into a\n * list.\n */\n\ntypedef struct TkSelInProgress {\n    TkSelHandler *selPtr;\t/* Handler being executed. If this handler is\n\t\t\t\t * deleted, the field is set to NULL. */\n    struct TkSelInProgress *nextPtr;\n\t\t\t\t/* Next higher nested search. */\n} TkSelInProgress;\n\n/*\n * Chunk size for retrieving selection. It's defined both in words and in\n * bytes; the word size is used to allocate buffer space that's guaranteed to\n * be word-aligned and that has an extra character for the terminating NULL.\n */\n\n#define TK_SEL_BYTES_AT_ONCE 4000\n#define TK_SEL_WORDS_AT_ONCE 1001\n\n/*\n * Declarations for procedures that are used by the selection-related files\n * but shouldn't be used anywhere else in Tk (or by Tk clients):\n */\n\nMODULE_SCOPE TkSelInProgress *TkSelGetInProgress(void);\nMODULE_SCOPE void\tTkSelSetInProgress(TkSelInProgress *pendingPtr);\nMODULE_SCOPE void\tTkSelClearSelection(Tk_Window tkwin, XEvent *eventPtr);\nMODULE_SCOPE Tcl_Size TkSelDefaultSelection(TkSelectionInfo *infoPtr,\n\t\t\t    Atom target, char *buffer, Tcl_Size maxBytes,\n\t\t\t    Atom *typePtr);\n#ifndef TkSelUpdateClipboard\nMODULE_SCOPE void\tTkSelUpdateClipboard(TkWindow *winPtr, clipboardOption option);\n#endif\n\n#endif /* _TKSELECT */\n"
  },
  {
    "path": "generic/tkSquare.c",
    "content": "/*\n * tkSquare.c --\n *\n *\tThis module implements \"square\" widgets that are object based. A\n *\t\"square\" is a widget that displays a single square that can be moved\n *\taround and resized. This file is intended as an example of how to\n *\tbuild a widget; it isn't included in the normal wish, but it is\n *\tincluded in \"tktest\".\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#if 0\n#define __NO_OLD_CONFIG\n#endif\n#ifndef USE_TCL_STUBS\n#   define USE_TCL_STUBS\n#endif\n#ifndef USE_TK_STUBS\n#   define USE_TK_STUBS\n#endif\n#include \"tkInt.h\"\n\n/*\n * A data structure of the following type is kept for each square widget\n * managed by this file:\n */\n\ntypedef struct {\n    Tk_Window tkwin;\t\t/* Window that embodies the square. NULL means\n\t\t\t\t * window has been deleted but widget record\n\t\t\t\t * hasn't been cleaned up yet. */\n    Display *display;\t\t/* X's token for the window's display. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with widget. */\n    Tcl_Command widgetCmd;\t/* Token for square's widget command. */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n    Tcl_Obj *xPtr, *yPtr;\t/* Position of square's upper-left corner\n\t\t\t\t * within widget. */\n    int x, y;\n    Tcl_Obj *sizeObjPtr;\t/* Width and height of square. */\n\n    /*\n     * Information used when displaying widget:\n     */\n\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border around whole widget. */\n    Tcl_Obj *bgBorderPtr;\n    Tcl_Obj *fgBorderPtr;\n    Tcl_Obj *reliefPtr;\n    GC gc;\t\t\t/* Graphics context for copying from\n\t\t\t\t * off-screen pixmap onto screen. */\n    bool doubleBuffer;\t/* true means double-buffer redisplay with\n\t\t\t\t * pixmap; false means draw straight onto the\n\t\t\t\t * display. */\n    bool updatePending;\t\t/* true means a call to SquareDisplay has\n\t\t\t\t * already been scheduled. */\n} Square;\n\n/*\n * Information used for argv parsing.\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\t    \"#d9d9d9\", offsetof(Square, bgBorderPtr), TCL_INDEX_NONE, 0,\n\t    \"white\", 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,\n\t    \"-borderwidth\", 0},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,\n\t    \"-background\", 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\t    \"2\", offsetof(Square, borderWidthObj), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-dbl\", \"doubleBuffer\", \"DoubleBuffer\",\n\t    \"1\", TCL_INDEX_NONE, offsetof(Square, doubleBuffer), TK_OPTION_VAR(bool) , NULL, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,\n\t    \"-foreground\", 0},\n    {TK_OPTION_BORDER, \"-foreground\", \"foreground\", \"Foreground\",\n\t    \"#b03060\", offsetof(Square, fgBorderPtr), TCL_INDEX_NONE, 0,\n\t    \"black\", 0},\n    {TK_OPTION_PIXELS, \"-posx\", \"posx\", \"PosX\", \"0\",\n\t    offsetof(Square, xPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_PIXELS, \"-posy\", \"posy\", \"PosY\", \"0\",\n\t    offsetof(Square, yPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\t    \"raised\", offsetof(Square, reliefPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_PIXELS, \"-size\", \"size\", \"Size\", \"20\",\n\t    offsetof(Square, sizeObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n};\n\n/*\n * Forward declarations for procedures defined later in this file:\n */\n\nstatic void\t\tSquareDeletedProc(void *clientData);\nstatic int\t\tSquareConfigure(Tcl_Interp *interp, Square *squarePtr);\nstatic void\t\tSquareDisplay(void *clientData);\nstatic void\t\tKeepInWindow(Square *squarePtr);\nstatic void\t\tSquareObjEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_ObjCmdProc2 SquareWidgetObjCmd;\n\f\n/*\n *--------------------------------------------------------------\n *\n * SquareCmd --\n *\n *\tThis procedure is invoked to process the \"square\" Tcl command. It\n *\tcreates a new \"square\" widget.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tA new widget is created and configured.\n *\n *--------------------------------------------------------------\n */\n\nint\nSquareObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Square *squarePtr;\n    Tk_Window tkwin;\n    Tk_OptionTable optionTable;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n    Tk_SetClass(tkwin, \"Square\");\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the refcount will get bumped and just the pointer will be\n     * returned. The refcount getting bumped does not concern us, because Tk\n     * will ensure the table is deleted when the interpreter is destroyed.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    /*\n     * Allocate and initialize the widget record. The memset allows us to set\n     * just the non-NULL/0 items.\n     */\n\n    squarePtr = (Square *)Tcl_Alloc(sizeof(Square));\n    memset(squarePtr, 0, sizeof(Square));\n\n    squarePtr->tkwin = tkwin;\n    squarePtr->display = Tk_Display(tkwin);\n    squarePtr->interp = interp;\n    squarePtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, squarePtr,\n\t    SquareDeletedProc);\n    squarePtr->gc = NULL;\n    squarePtr->optionTable = optionTable;\n\n    if (Tk_InitOptions(interp, squarePtr, optionTable, tkwin)\n\t    != TCL_OK) {\n\tTk_DestroyWindow(squarePtr->tkwin);\n\tTcl_Free(squarePtr);\n\treturn TCL_ERROR;\n    }\n\n    Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,\n\t    SquareObjEventProc, squarePtr);\n    if (Tk_SetOptions(interp, squarePtr, optionTable, objc - 2,\n\t    objv + 2, tkwin, NULL, NULL) != TCL_OK) {\n\tgoto error;\n    }\n    if (SquareConfigure(interp, squarePtr) != TCL_OK) {\n\tgoto error;\n    }\n\n    Tcl_SetObjResult(interp,\n\t    Tcl_NewStringObj(Tk_PathName(squarePtr->tkwin), TCL_INDEX_NONE));\n    return TCL_OK;\n\n  error:\n    Tk_DestroyWindow(squarePtr->tkwin);\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SquareWidgetObjCmd --\n *\n *\tThis procedure is invoked to process the Tcl command that corresponds\n *\tto a widget managed by this module. See the user documentation for\n *\tdetails on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSquareWidgetObjCmd(\n    void *clientData,\t/* Information about square widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj * const objv[])\t/* Argument objects. */\n{\n    Square *squarePtr = (Square *)clientData;\n    int result = TCL_OK;\n    static const char *const squareOptions[] = {\"cget\", \"configure\", NULL};\n    enum {\n\tSQUARE_CGET, SQUARE_CONFIGURE\n    };\n    Tcl_Obj *resultObjPtr;\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], squareOptions,\n\t    sizeof(char *), \"command\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    Tcl_Preserve(squarePtr);\n\n    switch (index) {\n    case SQUARE_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    goto error;\n\t}\n\tresultObjPtr = Tk_GetOptionValue(interp, squarePtr,\n\t\tsquarePtr->optionTable, objv[2], squarePtr->tkwin);\n\tif (resultObjPtr == NULL) {\n\t    result = TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, resultObjPtr);\n\t}\n\tbreak;\n    case SQUARE_CONFIGURE:\n\tresultObjPtr = NULL;\n\tif (objc == 2) {\n\t    resultObjPtr = Tk_GetOptionInfo(interp, squarePtr,\n\t\t    squarePtr->optionTable, NULL, squarePtr->tkwin);\n\t    if (resultObjPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    }\n\t} else if (objc == 3) {\n\t    resultObjPtr = Tk_GetOptionInfo(interp, squarePtr,\n\t\t    squarePtr->optionTable, objv[2], squarePtr->tkwin);\n\t    if (resultObjPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    }\n\t} else {\n\t    result = Tk_SetOptions(interp, squarePtr,\n\t\t    squarePtr->optionTable, objc - 2, objv + 2,\n\t\t    squarePtr->tkwin, NULL, NULL);\n\t    if (result == TCL_OK) {\n\t\tresult = SquareConfigure(interp, squarePtr);\n\t    }\n\t    if (!squarePtr->updatePending) {\n\t\tTcl_DoWhenIdle(SquareDisplay, squarePtr);\n\t\tsquarePtr->updatePending = true;\n\t    }\n\t}\n\tif (resultObjPtr != NULL) {\n\t    Tcl_SetObjResult(interp, resultObjPtr);\n\t}\n    }\n    Tcl_Release(squarePtr);\n    return result;\n\n  error:\n    Tcl_Release(squarePtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SquareConfigure --\n *\n *\tThis procedure is called to process an objv/objc list in conjunction\n *\twith the Tk option database to configure (or reconfigure) a square\n *\twidget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as colors, border width, etc. get set\n *\tfor squarePtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSquareConfigure(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Used for error reporting. */\n    Square *squarePtr)\t\t/* Information about widget. */\n{\n    int borderWidth;\n    Tk_3DBorder bgBorder;\n\n    /*\n     * Set the background for the window and create a graphics context for use\n     * during redisplay.\n     */\n\n    bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,\n\t    squarePtr->bgBorderPtr);\n    Tk_SetWindowBackground(squarePtr->tkwin,\n\t    Tk_3DBorderColor(bgBorder)->pixel);\n    if ((squarePtr->gc == NULL) && squarePtr->doubleBuffer) {\n\tXGCValues gcValues;\n\tgcValues.function = GXcopy;\n\tgcValues.graphics_exposures = False;\n\tsquarePtr->gc = Tk_GetGC(squarePtr->tkwin,\n\t\tGCFunction|GCGraphicsExposures, &gcValues);\n    }\n\n    /*\n     * Register the desired geometry for the window. Then arrange for the\n     * window to be redisplayed.\n     */\n\n    Tk_GeometryRequest(squarePtr->tkwin, 200, 150);\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthObj,\n\t    &borderWidth);\n    Tk_SetInternalBorder(squarePtr->tkwin, borderWidth);\n    if (!squarePtr->updatePending) {\n\tTcl_DoWhenIdle(SquareDisplay, squarePtr);\n\tsquarePtr->updatePending = true;\n    }\n    KeepInWindow(squarePtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SquareObjEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tsquares.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nSquareObjEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    Square *squarePtr = (Square *)clientData;\n\n    if (eventPtr->type == Expose) {\n\tif (!squarePtr->updatePending) {\n\t    Tcl_DoWhenIdle(SquareDisplay, squarePtr);\n\t    squarePtr->updatePending = true;\n\t}\n    } else if (eventPtr->type == ConfigureNotify) {\n\tKeepInWindow(squarePtr);\n\tif (!squarePtr->updatePending) {\n\t    Tcl_DoWhenIdle(SquareDisplay, squarePtr);\n\t    squarePtr->updatePending = true;\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tif (squarePtr->tkwin != NULL) {\n\t    Tk_FreeConfigOptions(squarePtr, squarePtr->optionTable,\n\t\t    squarePtr->tkwin);\n\t    if (squarePtr->gc != NULL) {\n\t\tTk_FreeGC(squarePtr->display, squarePtr->gc);\n\t    }\n\t    squarePtr->tkwin = NULL;\n\t    Tcl_DeleteCommandFromToken(squarePtr->interp,\n\t\t    squarePtr->widgetCmd);\n\t}\n\tif (squarePtr->updatePending) {\n\t    Tcl_CancelIdleCall(SquareDisplay, squarePtr);\n\t}\n\tTcl_EventuallyFree(squarePtr, TCL_DYNAMIC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SquareDeletedProc --\n *\n *\tThis procedure is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSquareDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    Square *squarePtr = (Square *)clientData;\n    Tk_Window tkwin = squarePtr->tkwin;\n\n    /*\n     * This procedure could be invoked either because the window was destroyed\n     * and the command was then deleted (in which case tkwin is NULL) or\n     * because the command was deleted, and then this procedure destroys the\n     * widget.\n     */\n\n    if (tkwin != NULL) {\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SquareDisplay --\n *\n *\tThis procedure redraws the contents of a square window. It is invoked\n *\tas a do-when-idle handler, so it only runs when there's nothing else\n *\tfor the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nSquareDisplay(\n    void *clientData)\t/* Information about window. */\n{\n    Square *squarePtr = (Square *)clientData;\n    Tk_Window tkwin = squarePtr->tkwin;\n    Pixmap pm = None;\n    Drawable d;\n    int borderWidth, size, relief;\n    Tk_3DBorder bgBorder, fgBorder;\n\n    squarePtr->updatePending = false;\n    if (!Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    /*\n     * Create a pixmap for double-buffering, if necessary.\n     */\n\n    if (squarePtr->doubleBuffer) {\n\tpm = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t\tTk_Width(tkwin), Tk_Height(tkwin),\n\t\tDefaultDepthOfScreen(Tk_Screen(tkwin)));\n\td = pm;\n    } else {\n\td = Tk_WindowId(tkwin);\n    }\n\n    /*\n     * Redraw the widget's background and border.\n     */\n\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthObj,\n\t    &borderWidth);\n    bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,\n\t    squarePtr->bgBorderPtr);\n    Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);\n    Tk_Fill3DRectangle(tkwin, d, bgBorder, 0, 0, Tk_Width(tkwin),\n\t    Tk_Height(tkwin), borderWidth, relief);\n\n    /*\n     * Display the square.\n     */\n\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);\n    fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,\n\t    squarePtr->fgBorderPtr);\n    Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size,\n\t    size, borderWidth, TK_RELIEF_RAISED);\n\n    /*\n     * If double-buffered, copy to the screen and release the pixmap.\n     */\n\n    if (squarePtr->doubleBuffer) {\n\tXCopyArea(Tk_Display(tkwin), pm, Tk_WindowId(tkwin), squarePtr->gc,\n\t\t0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),\n\t\t0, 0);\n\tTk_FreePixmap(Tk_Display(tkwin), pm);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * KeepInWindow --\n *\n *\tAdjust the position of the square if necessary to keep it in the\n *\twidget's window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe x and y position of the square are adjusted if necessary to keep\n *\tthe square in the window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nKeepInWindow(\n    Square *squarePtr)\t/* Pointer to widget record. */\n{\n    int i, bd, relief;\n    int borderWidth, size;\n\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthObj,\n\t    &borderWidth);\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr,\n\t    &squarePtr->x);\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr,\n\t    &squarePtr->y);\n    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);\n    Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);\n    bd = 0;\n    if (relief != TK_RELIEF_FLAT) {\n\tbd = borderWidth;\n    }\n    i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + size);\n    if (i < 0) {\n\tsquarePtr->x += i;\n    }\n    i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + size);\n    if (i < 0) {\n\tsquarePtr->y += i;\n    }\n    if (squarePtr->x < bd) {\n\tsquarePtr->x = bd;\n    }\n    if (squarePtr->y < bd) {\n\tsquarePtr->y = bd;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkStubInit.c",
    "content": "/*\n * tkStubInit.c --\n *\n *\tThis file contains the initializers for the Tk stub vectors.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#if !(defined(_WIN32) || defined(MAC_OSX_TK))\n/* UNIX */\n#define UNIX_TK\n#include \"tkUnixInt.h\"\n#endif\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n#if defined(MAC_OSX_TK)\n/* we could have used _TKMACINT */\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXPrivate.h\"\n#else\n#   define Tk_ClipDrawableToRect 0\n#endif\n\n/* TODO: These ought to come in some other way */\n#include \"tkPlatDecls.h\"\n#include \"tkIntXlibDecls.h\"\n\nMODULE_SCOPE const TkStubs tkStubs;\n\n/*\n * Remove macro that might interfere with the definition below.\n */\n\n#undef TkPutImage\n#undef XPutImage\n#define TkUnusedStubEntry 0\n\n#define TkPointToChar_ PointToChar /* Move out of the way */\nstatic int PointToChar(Tk_TextLayout layout, int x, int y)\n{\n    return (int)Tk_PointToChar(layout, x, y);\n}\n\n#if !defined(MAC_OSX_TK)\nstatic int\ndoNothing(void)\n{\n    /* dummy implementation, no need to do anything */\n    return 0;\n}\n#   undef TkpDefineNativeBitmaps\n#   undef TkpCreateNativeBitmap\n#   undef TkpGetNativeAppBitmap\n#   define TkpDefineNativeBitmaps ((void (*)(void))(void *)doNothing)\n#   define TkpCreateNativeBitmap ((Pixmap (*)(Display *, const void *))(void *)doNothing)\n#   define TkpGetNativeAppBitmap ((Pixmap (*)(Display *, const char *, int *, int *))(void *)doNothing)\n#   define TkAboutDlg ((void (*)(void))(void *)doNothing)\n#endif\n\n#ifdef _WIN32\n\n#undef TkpCmapStressed\n#define TkpCmapStressed ((bool (*)(Tk_Window, Colormap))(void *)doNothing)\n#undef TkpSync\n#define TkpSync ((void (*)(Display *))(void *)doNothing)\n\nvoid\nTkCreateXEventSource(void)\n{\n    TkWinXInit(Tk_GetHINSTANCE());\n}\n\n#   define TkUnixContainerId 0\n#   define TkUnixDoOneXEvent 0\n#   define TkUnixSetMenubar 0\n#   define TkWmCleanup (void (*)(TkDisplay *))(void *)doNothing\n#   define TkSendCleanup (void (*)(TkDisplay *))(void *)doNothing\n#   define TkpTestsendCmd 0\n\n#else /* !_WIN32 */\n\n/*\n * Make sure that extensions which call XParseColor through the stub\n * table, call TkParseColor instead. [Bug 3486474]\n */\n#   define XParseColor\tTkParseColor\n\n#   ifdef __CYGWIN__\n\n/*\n * Trick, so we don't have to include <windows.h> here, which in any\n * case lacks this function anyway.\n */\n\n#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS\t0x00000004\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nint __stdcall GetModuleHandleExW(unsigned int, const char *, void *);\n#ifdef __cplusplus\n}\n#endif\n\nvoid\nTkSetPixmapColormap(\n    Pixmap pixmap,\n    Colormap colormap)\n{\n    (void)pixmap;\n    (void)colormap;\n}\n\nvoid\nTkpPrintWindowId(\n    char *buf,\t\t\t/* Pointer to string large enough to hold\n\t\t\t\t * the hex representation of a pointer. */\n    Window window)\t\t/* Window to be printed into buffer. */\n{\n    snprintf(buf, TCL_INTEGER_SPACE, \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)window);\n}\n\n/* TODO: To be implemented for Cygwin */\n#\tdefine Tk_AttachHWND 0\n#\tdefine Tk_GetHWND 0\n#\tdefine Tk_HWNDToWindow 0\n#\tdefine TkAlignImageData 0\n#\tdefine TkpGetMS 0\n#\tdefine TkpGetCapture 0\n#\tdefine TkPointerDeadWindow 0\n#\tdefine TkpSetCapture 0\n#\tdefine TkpSetCursor 0\n#\tdefine TkWinClipboardRender 0\n#\tdefine TkWinFillRect 0\n#\tdefine TkWinGetBorderPixels 0\n#\tdefine TkWinGetDrawableDC 0\n#\tdefine TkWinReleaseDrawableDC 0\n#\tdefine TkWinResendEvent 0\n#\tdefine TkWinSetMenu 0\n#\tdefine TkWinSetWindowPos 0\n#\tdefine TkWinWmCleanup 0\n#\tdefine TkWinXCleanup 0\n#\tdefine TkWinXInit 0\n#\tdefine TkWinSetForegroundWindow 0\n#\tdefine TkWinDialogDebug 0\n#\tdefine TkWinSetHINSTANCE 0\n#\tdefine TkWinChildProc 0\n\n#   endif\n#endif /* !_WIN32 */\n\n#if !defined(_WIN32)\n\nint\nTkPutImage(\n    unsigned long *colors,\t/* Array of pixel values used by this image.\n\t\t\t\t * May be NULL. */\n    int ncolors,\t\t/* Number of colors used, or 0. */\n    Display *display,\n    Drawable d,\t\t\t/* Destination drawable. */\n    GC gc,\n    XImage *image,\t\t/* Source image. */\n    int src_x, int src_y,\t/* Offset of subimage. */\n    int dest_x, int dest_y,\t/* Position of subimage origin in drawable. */\n    unsigned int width, unsigned int height)\n\t\t\t\t/* Dimensions of subimage. */\n{\n\t(void)colors;\n\t(void)ncolors;\n\n    return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);\n}\n#endif /* MAC_OSX_TCL */\n\n\n/*\n * WARNING: The contents of this file is automatically generated by the\n * tools/genStubs.tcl script. Any modifications to the function declarations\n * below should be made in the generic/tk.decls script.\n */\n\n#ifdef __GNUC__\n/*\n * The rest of this file shouldn't warn about deprecated functions; they're\n * there because we intend them to be so and know that this file is OK to\n * touch those fields.\n */\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\n/* !BEGIN!: Do not edit below this line. */\n\nstatic const TkIntStubs tkIntStubs = {\n    TCL_STUB_MAGIC,\n    0,\n    TkAllocWindow, /* 0 */\n    TkBezierPoints, /* 1 */\n    TkBezierScreenPoints, /* 2 */\n    0, /* 3 */\n    TkBindEventProc, /* 4 */\n    TkBindFree, /* 5 */\n    TkBindInit, /* 6 */\n    TkChangeEventWindow, /* 7 */\n    TkClipInit, /* 8 */\n    TkComputeAnchor, /* 9 */\n    0, /* 10 */\n    0, /* 11 */\n    TkCreateCursorFromData, /* 12 */\n    TkCreateFrame, /* 13 */\n    TkCreateMainWindow, /* 14 */\n    TkCurrentTime, /* 15 */\n    TkDeleteAllImages, /* 16 */\n    TkDoConfigureNotify, /* 17 */\n    TkDrawInsetFocusHighlight, /* 18 */\n    TkEventDeadWindow, /* 19 */\n    TkFillPolygon, /* 20 */\n    TkFindStateNum, /* 21 */\n    TkFindStateString, /* 22 */\n    TkFocusDeadWindow, /* 23 */\n    TkFocusFilterEvent, /* 24 */\n    TkFocusKeyEvent, /* 25 */\n    TkFontPkgInit, /* 26 */\n    TkFontPkgFree, /* 27 */\n    TkFreeBindingTags, /* 28 */\n    TkpFreeCursor, /* 29 */\n    TkGetBitmapData, /* 30 */\n    TkGetButtPoints, /* 31 */\n    TkGetCursorByName, /* 32 */\n    TkGetDefaultScreenName, /* 33 */\n    TkGetDisplay, /* 34 */\n    TkGetDisplayOf, /* 35 */\n    TkGetFocusWin, /* 36 */\n    TkGetInterpNames, /* 37 */\n    TkGetMiterPoints, /* 38 */\n    TkGetPointerCoords, /* 39 */\n    TkGetServerInfo, /* 40 */\n    TkGrabDeadWindow, /* 41 */\n    TkGrabState, /* 42 */\n    TkIncludePoint, /* 43 */\n    TkInOutEvents, /* 44 */\n    TkInstallFrameMenu, /* 45 */\n    TkKeysymToString, /* 46 */\n    TkLineToArea, /* 47 */\n    TkLineToPoint, /* 48 */\n    TkMakeBezierCurve, /* 49 */\n    TkMakeBezierPostscript, /* 50 */\n    TkOptionClassChanged, /* 51 */\n    TkOptionDeadWindow, /* 52 */\n    TkOvalToArea, /* 53 */\n    TkOvalToPoint, /* 54 */\n    TkpChangeFocus, /* 55 */\n    TkpCloseDisplay, /* 56 */\n    TkpClaimFocus, /* 57 */\n    TkpDisplayWarning, /* 58 */\n    TkpGetAppName, /* 59 */\n    0, /* 60 */\n    TkpGetWrapperWindow, /* 61 */\n    TkpInit, /* 62 */\n    TkpInitializeMenuBindings, /* 63 */\n    0, /* 64 */\n    TkpMakeMenuWindow, /* 65 */\n    0, /* 66 */\n    TkpMenuNotifyToplevelCreate, /* 67 */\n    TkpOpenDisplay, /* 68 */\n    TkPointerEvent, /* 69 */\n    TkPolygonToArea, /* 70 */\n    TkPolygonToPoint, /* 71 */\n    TkPositionInTree, /* 72 */\n    TkpRedirectKeyEvent, /* 73 */\n    0, /* 74 */\n    0, /* 75 */\n    0, /* 76 */\n    TkQueueEventForAllChildren, /* 77 */\n    TkReadBitmapFile, /* 78 */\n    TkScrollWindow, /* 79 */\n    TkSelDeadWindow, /* 80 */\n    TkSelEventProc, /* 81 */\n    TkSelInit, /* 82 */\n    TkSelPropProc, /* 83 */\n    0, /* 84 */\n    0, /* 85 */\n    TkStringToKeysym, /* 86 */\n    TkThickPolyLineToArea, /* 87 */\n    TkWmAddToColormapWindows, /* 88 */\n    TkWmDeadWindow, /* 89 */\n    TkWmFocusToplevel, /* 90 */\n    TkWmMapWindow, /* 91 */\n    TkWmNewWindow, /* 92 */\n    TkWmProtocolEventProc, /* 93 */\n    TkWmRemoveFromColormapWindows, /* 94 */\n    TkWmRestackToplevel, /* 95 */\n    TkWmSetClass, /* 96 */\n    TkWmUnmapWindow, /* 97 */\n    TkDebugBitmap, /* 98 */\n    TkDebugBorder, /* 99 */\n    TkDebugCursor, /* 100 */\n    TkDebugColor, /* 101 */\n    TkDebugConfig, /* 102 */\n    TkDebugFont, /* 103 */\n    TkFindStateNumObj, /* 104 */\n    TkGetBitmapPredefTable, /* 105 */\n    TkGetDisplayList, /* 106 */\n    TkGetMainInfoList, /* 107 */\n    TkGetWindowFromObj, /* 108 */\n    TkpGetString, /* 109 */\n    TkpGetSubFonts, /* 110 */\n    0, /* 111 */\n    TkpMenuThreadInit, /* 112 */\n    XClipBox, /* 113 */\n    XCreateRegion, /* 114 */\n    XDestroyRegion, /* 115 */\n    XIntersectRegion, /* 116 */\n    XRectInRegion, /* 117 */\n    XSetRegion, /* 118 */\n    XUnionRectWithRegion, /* 119 */\n    0, /* 120 */\n    TkpCreateNativeBitmap, /* 121 */\n    TkpDefineNativeBitmaps, /* 122 */\n    0, /* 123 */\n    TkpGetNativeAppBitmap, /* 124 */\n    0, /* 125 */\n    0, /* 126 */\n    0, /* 127 */\n    0, /* 128 */\n    0, /* 129 */\n    0, /* 130 */\n    0, /* 131 */\n    0, /* 132 */\n    0, /* 133 */\n    0, /* 134 */\n    0, /* 135 */\n    TkSetFocusWin, /* 136 */\n    TkpSetKeycodeAndState, /* 137 */\n    TkpGetKeySym, /* 138 */\n    TkpInitKeymapInfo, /* 139 */\n    TkPhotoGetValidRegion, /* 140 */\n    TkWmStackorderToplevel, /* 141 */\n    TkFocusFree, /* 142 */\n    TkClipCleanup, /* 143 */\n    TkGCCleanup, /* 144 */\n    XSubtractRegion, /* 145 */\n    TkStylePkgInit, /* 146 */\n    TkStylePkgFree, /* 147 */\n    TkToplevelWindowForCommand, /* 148 */\n    TkGetOptionSpec, /* 149 */\n    TkMakeRawCurve, /* 150 */\n    TkMakeRawCurvePostscript, /* 151 */\n    TkpDrawFrame, /* 152 */\n    TkCreateThreadExitHandler, /* 153 */\n    TkDeleteThreadExitHandler, /* 154 */\n    0, /* 155 */\n    TkpTestembedCmd, /* 156 */\n    TkpTesttextCmd, /* 157 */\n    TkSelGetSelection, /* 158 */\n    TkTextGetIndex, /* 159 */\n    TkTextIndexBackBytes, /* 160 */\n    TkTextIndexForwBytes, /* 161 */\n    TkTextMakeByteIndex, /* 162 */\n    TkTextPrintIndex, /* 163 */\n    TkTextSetMark, /* 164 */\n    TkTextXviewCmd, /* 165 */\n    TkTextChanged, /* 166 */\n    TkBTreeNumLines, /* 167 */\n    TkTextInsertDisplayProc, /* 168 */\n    TkStateParseProc, /* 169 */\n    TkStatePrintProc, /* 170 */\n    TkCanvasDashParseProc, /* 171 */\n    TkCanvasDashPrintProc, /* 172 */\n    TkOffsetParseProc, /* 173 */\n    TkOffsetPrintProc, /* 174 */\n    TkPixelParseProc, /* 175 */\n    TkPixelPrintProc, /* 176 */\n    TkOrientParseProc, /* 177 */\n    TkOrientPrintProc, /* 178 */\n    TkSmoothParseProc, /* 179 */\n    TkSmoothPrintProc, /* 180 */\n    TkDrawAngledTextLayout, /* 181 */\n    TkUnderlineAngledTextLayout, /* 182 */\n    TkIntersectAngledTextLayout, /* 183 */\n    TkDrawAngledChars, /* 184 */\n    0, /* 185 */\n    0, /* 186 */\n    TkDebugPhotoStringMatchDef, /* 187 */\n};\n\nstatic const TkIntPlatStubs tkIntPlatStubs = {\n    TCL_STUB_MAGIC,\n    0,\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n    TkCreateXEventSource, /* 0 */\n    TkAboutDlg, /* 1 */\n    TkGenerateActivateEvents, /* 2 */\n    TkpGetMS, /* 3 */\n    TkPointerDeadWindow, /* 4 */\n    TkpPrintWindowId, /* 5 */\n    TkpScanWindowId, /* 6 */\n    TkpSetCapture, /* 7 */\n    TkpSetCursor, /* 8 */\n    TkpWmSetState, /* 9 */\n    TkSetPixmapColormap, /* 10 */\n    0, /* 11 */\n    TkWinClipboardRender, /* 12 */\n    0, /* 13 */\n    TkWinFillRect, /* 14 */\n    TkWinGetBorderPixels, /* 15 */\n    TkWinGetDrawableDC, /* 16 */\n    0, /* 17 */\n    0, /* 18 */\n    0, /* 19 */\n    0, /* 20 */\n    0, /* 21 */\n    TkWinReleaseDrawableDC, /* 22 */\n    TkWinResendEvent, /* 23 */\n    0, /* 24 */\n    0, /* 25 */\n    TkWinSetWindowPos, /* 26 */\n    TkWinWmCleanup, /* 27 */\n    TkWinXCleanup, /* 28 */\n    TkWinXInit, /* 29 */\n    TkWinSetForegroundWindow, /* 30 */\n    TkWinDialogDebug, /* 31 */\n    0, /* 32 */\n    TkAlignImageData, /* 33 */\n    TkWinSetHINSTANCE, /* 34 */\n    0, /* 35 */\n    TkWinChildProc, /* 36 */\n    0, /* 37 */\n    TkpCmapStressed, /* 38 */\n    TkpSync, /* 39 */\n    TkUnixContainerId, /* 40 */\n    TkUnixDoOneXEvent, /* 41 */\n    TkUnixSetMenubar, /* 42 */\n    TkWmCleanup, /* 43 */\n    TkSendCleanup, /* 44 */\n    TkpTestsendCmd, /* 45 */\n    0, /* 46 */\n    TkpGetCapture, /* 47 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n    0, /* 0 */\n    TkAboutDlg, /* 1 */\n    TkGenerateActivateEvents, /* 2 */\n    TkpGetMS, /* 3 */\n    TkPointerDeadWindow, /* 4 */\n    0, /* 5 */\n    TkpScanWindowId, /* 6 */\n    0, /* 7 */\n    TkpSetCursor, /* 8 */\n    TkpWmSetState, /* 9 */\n    0, /* 10 */\n    TkpSetCapture, /* 11 */\n    0, /* 12 */\n    0, /* 13 */\n    TkMacOSXDoHLEvent, /* 14 */\n    0, /* 15 */\n    TkMacOSXGetXWindow, /* 16 */\n    0, /* 17 */\n    0, /* 18 */\n    0, /* 19 */\n    0, /* 20 */\n    0, /* 21 */\n    0, /* 22 */\n    0, /* 23 */\n    0, /* 24 */\n    0, /* 25 */\n    0, /* 26 */\n    0, /* 27 */\n    0, /* 28 */\n    0, /* 29 */\n    0, /* 30 */\n    0, /* 31 */\n    TkMacOSXUpdateClipRgn, /* 32 */\n    0, /* 33 */\n    0, /* 34 */\n    TkMacOSXVisableClipRgn, /* 35 */\n    TkMacOSXWinBounds, /* 36 */\n    TkMacOSXWindowOffset, /* 37 */\n    TkSetMacColor, /* 38 */\n    TkSetWMName, /* 39 */\n    0, /* 40 */\n    TkMacOSXZoomToplevel, /* 41 */\n    Tk_TopCoordsToWindow, /* 42 */\n    TkMacOSXContainerId, /* 43 */\n    TkMacOSXGetHostToplevel, /* 44 */\n    0, /* 45 */\n    0, /* 46 */\n    TkpGetCapture, /* 47 */\n    0, /* 48 */\n    TkMacOSXGetContainer, /* 49 */\n#endif /* AQUA */\n#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */\n    TkCreateXEventSource, /* 0 */\n    TkAboutDlg, /* 1 */\n    TkGenerateActivateEvents, /* 2 */\n    0, /* 3 */\n    0, /* 4 */\n    0, /* 5 */\n    TkpScanWindowId, /* 6 */\n    0, /* 7 */\n    0, /* 8 */\n    TkpWmSetState, /* 9 */\n    0, /* 10 */\n    0, /* 11 */\n    0, /* 12 */\n    0, /* 13 */\n    0, /* 14 */\n    0, /* 15 */\n    0, /* 16 */\n    0, /* 17 */\n    0, /* 18 */\n    0, /* 19 */\n    0, /* 20 */\n    0, /* 21 */\n    0, /* 22 */\n    0, /* 23 */\n    0, /* 24 */\n    0, /* 25 */\n    0, /* 26 */\n    0, /* 27 */\n    0, /* 28 */\n    0, /* 29 */\n    0, /* 30 */\n    0, /* 31 */\n    0, /* 32 */\n    0, /* 33 */\n    0, /* 34 */\n    0, /* 35 */\n    0, /* 36 */\n    0, /* 37 */\n    TkpCmapStressed, /* 38 */\n    TkpSync, /* 39 */\n    TkUnixContainerId, /* 40 */\n    TkUnixDoOneXEvent, /* 41 */\n    TkUnixSetMenubar, /* 42 */\n    TkWmCleanup, /* 43 */\n    TkSendCleanup, /* 44 */\n    TkpTestsendCmd, /* 45 */\n#endif /* X11 */\n};\n\nstatic const TkIntXlibStubs tkIntXlibStubs = {\n    TCL_STUB_MAGIC,\n    0,\n    XSetDashes, /* 0 */\n    XGetModifierMapping, /* 1 */\n    XCreateImage, /* 2 */\n    XGetImage, /* 3 */\n    XGetAtomName, /* 4 */\n    XKeysymToString, /* 5 */\n    XCreateColormap, /* 6 */\n    XCreatePixmapCursor, /* 7 */\n    XCreateGlyphCursor, /* 8 */\n    XGContextFromGC, /* 9 */\n    XListHosts, /* 10 */\n    0, /* 11 */\n    XStringToKeysym, /* 12 */\n    XRootWindow, /* 13 */\n    XSetErrorHandler, /* 14 */\n    XIconifyWindow, /* 15 */\n    XWithdrawWindow, /* 16 */\n    XGetWMColormapWindows, /* 17 */\n    XAllocColor, /* 18 */\n    XBell, /* 19 */\n    XChangeProperty, /* 20 */\n    XChangeWindowAttributes, /* 21 */\n    XClearWindow, /* 22 */\n    XConfigureWindow, /* 23 */\n    XCopyArea, /* 24 */\n    XCopyPlane, /* 25 */\n    XCreateBitmapFromData, /* 26 */\n    XDefineCursor, /* 27 */\n    XDeleteProperty, /* 28 */\n    XDestroyWindow, /* 29 */\n    XDrawArc, /* 30 */\n    XDrawLines, /* 31 */\n    XDrawRectangle, /* 32 */\n    XFillArc, /* 33 */\n    XFillPolygon, /* 34 */\n    XFillRectangles, /* 35 */\n    XForceScreenSaver, /* 36 */\n    XFreeColormap, /* 37 */\n    XFreeColors, /* 38 */\n    XFreeCursor, /* 39 */\n    XFreeModifiermap, /* 40 */\n    XGetGeometry, /* 41 */\n    XGetInputFocus, /* 42 */\n    XGetWindowProperty, /* 43 */\n    XGetWindowAttributes, /* 44 */\n    XGrabKeyboard, /* 45 */\n    XGrabPointer, /* 46 */\n    XKeysymToKeycode, /* 47 */\n    XLookupColor, /* 48 */\n    XMapWindow, /* 49 */\n    XMoveResizeWindow, /* 50 */\n    XMoveWindow, /* 51 */\n    XNextEvent, /* 52 */\n    XPutBackEvent, /* 53 */\n    XQueryColors, /* 54 */\n    XQueryPointer, /* 55 */\n    XQueryTree, /* 56 */\n    XRaiseWindow, /* 57 */\n    XRefreshKeyboardMapping, /* 58 */\n    XResizeWindow, /* 59 */\n    XSelectInput, /* 60 */\n    XSendEvent, /* 61 */\n    XSetCommand, /* 62 */\n    XSetIconName, /* 63 */\n    XSetInputFocus, /* 64 */\n    XSetSelectionOwner, /* 65 */\n    XSetWindowBackground, /* 66 */\n    XSetWindowBackgroundPixmap, /* 67 */\n    XSetWindowBorder, /* 68 */\n    XSetWindowBorderPixmap, /* 69 */\n    XSetWindowBorderWidth, /* 70 */\n    XSetWindowColormap, /* 71 */\n    XTranslateCoordinates, /* 72 */\n    XUngrabKeyboard, /* 73 */\n    XUngrabPointer, /* 74 */\n    XUnmapWindow, /* 75 */\n    XWindowEvent, /* 76 */\n    XDestroyIC, /* 77 */\n    XFilterEvent, /* 78 */\n    XmbLookupString, /* 79 */\n    TkPutImage, /* 80 */\n    XSetClipRectangles, /* 81 */\n    XParseColor, /* 82 */\n    XCreateGC, /* 83 */\n    XFreeGC, /* 84 */\n    XInternAtom, /* 85 */\n    XSetBackground, /* 86 */\n    XSetForeground, /* 87 */\n    XSetClipMask, /* 88 */\n    XSetClipOrigin, /* 89 */\n    XSetTSOrigin, /* 90 */\n    XChangeGC, /* 91 */\n    XSetFont, /* 92 */\n    XSetArcMode, /* 93 */\n    XSetStipple, /* 94 */\n    XSetFillRule, /* 95 */\n    XSetFillStyle, /* 96 */\n    XSetFunction, /* 97 */\n    XSetLineAttributes, /* 98 */\n    _XInitImageFuncPtrs, /* 99 */\n    XCreateIC, /* 100 */\n    XGetVisualInfo, /* 101 */\n    XSetWMClientMachine, /* 102 */\n    XStringListToTextProperty, /* 103 */\n    XDrawLine, /* 104 */\n    XWarpPointer, /* 105 */\n    XFillRectangle, /* 106 */\n    XFlush, /* 107 */\n    XGrabServer, /* 108 */\n    XUngrabServer, /* 109 */\n    XFree, /* 110 */\n    XNoOp, /* 111 */\n    XSynchronize, /* 112 */\n    XSync, /* 113 */\n    XVisualIDFromVisual, /* 114 */\n    0, /* 115 */\n    0, /* 116 */\n    0, /* 117 */\n    0, /* 118 */\n    0, /* 119 */\n    XOffsetRegion, /* 120 */\n    XUnionRegion, /* 121 */\n    XCreateWindow, /* 122 */\n    0, /* 123 */\n    0, /* 124 */\n    0, /* 125 */\n    0, /* 126 */\n    0, /* 127 */\n    0, /* 128 */\n    XLowerWindow, /* 129 */\n    XFillArcs, /* 130 */\n    XDrawArcs, /* 131 */\n    XDrawRectangles, /* 132 */\n    XDrawSegments, /* 133 */\n    XDrawPoint, /* 134 */\n    XDrawPoints, /* 135 */\n    XReparentWindow, /* 136 */\n    XPutImage, /* 137 */\n    XPolygonRegion, /* 138 */\n    XPointInRegion, /* 139 */\n    XVaCreateNestedList, /* 140 */\n    XSetICValues, /* 141 */\n    XGetICValues, /* 142 */\n    XSetICFocus, /* 143 */\n    XXorRegion, /* 144 */\n    XEqualRegion, /* 145 */\n    0, /* 146 */\n    XFreeFontSet, /* 147 */\n    XCloseIM, /* 148 */\n    XRegisterIMInstantiateCallback, /* 149 */\n    XUnregisterIMInstantiateCallback, /* 150 */\n    XSetLocaleModifiers, /* 151 */\n    XOpenIM, /* 152 */\n    XGetIMValues, /* 153 */\n    XSetIMValues, /* 154 */\n    XCreateFontSet, /* 155 */\n    XFreeStringList, /* 156 */\n    XkbKeycodeToKeysym, /* 157 */\n    XkbOpenDisplay, /* 158 */\n};\n\nstatic const TkPlatStubs tkPlatStubs = {\n    TCL_STUB_MAGIC,\n    0,\n#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */\n    Tk_AttachHWND, /* 0 */\n    Tk_GetHINSTANCE, /* 1 */\n    Tk_GetHWND, /* 2 */\n    Tk_HWNDToWindow, /* 3 */\n#endif /* WIN */\n#ifdef MAC_OSX_TK /* AQUA */\n    0, /* 0 */\n    0, /* 1 */\n    0, /* 2 */\n    0, /* 3 */\n    TkMacOSXInitAppleEvents, /* 4 */\n    0, /* 5 */\n    TkMacOSXInvalClipRgns, /* 6 */\n    0, /* 7 */\n    TkMacOSXGetRootControl, /* 8 */\n    Tk_MacOSXSetupTkNotifier, /* 9 */\n    Tk_MacOSXIsAppInFront, /* 10 */\n    Tk_MacOSXGetTkWindow, /* 11 */\n    Tk_MacOSXGetCGContextForDrawable, /* 12 */\n    Tk_MacOSXGetNSWindowForDrawable, /* 13 */\n    0, /* 14 */\n    0, /* 15 */\n    TkGenWMConfigureEvent, /* 16 */\n#endif /* AQUA */\n};\n\nstatic const TkStubHooks tkStubHooks = {\n    &tkPlatStubs,\n    &tkIntStubs,\n    &tkIntPlatStubs,\n    &tkIntXlibStubs\n};\n\nconst TkStubs tkStubs = {\n    TCL_STUB_MAGIC,\n    &tkStubHooks,\n    Tk_MainLoop, /* 0 */\n    Tk_3DBorderColor, /* 1 */\n    Tk_3DBorderGC, /* 2 */\n    Tk_3DHorizontalBevel, /* 3 */\n    Tk_3DVerticalBevel, /* 4 */\n    Tk_AddOption, /* 5 */\n    Tk_BindEvent, /* 6 */\n    Tk_CanvasDrawableCoords, /* 7 */\n    Tk_CanvasEventuallyRedraw, /* 8 */\n    Tk_CanvasGetCoord, /* 9 */\n    Tk_CanvasGetTextInfo, /* 10 */\n    Tk_CanvasPsBitmap, /* 11 */\n    Tk_CanvasPsColor, /* 12 */\n    Tk_CanvasPsFont, /* 13 */\n    Tk_CanvasPsPath, /* 14 */\n    Tk_CanvasPsStipple, /* 15 */\n    Tk_CanvasPsY, /* 16 */\n    Tk_CanvasSetStippleOrigin, /* 17 */\n    Tk_CanvasTagsParseProc, /* 18 */\n    Tk_CanvasTagsPrintProc, /* 19 */\n    Tk_CanvasTkwin, /* 20 */\n    Tk_CanvasWindowCoords, /* 21 */\n    Tk_ChangeWindowAttributes, /* 22 */\n    Tk_CharBbox, /* 23 */\n    Tk_ClearSelection, /* 24 */\n    Tk_ClipboardAppend, /* 25 */\n    Tk_ClipboardClear, /* 26 */\n    Tk_ConfigureInfo, /* 27 */\n    Tk_ConfigureValue, /* 28 */\n    Tk_ConfigureWidget, /* 29 */\n    Tk_ConfigureWindow, /* 30 */\n    Tk_ComputeTextLayout, /* 31 */\n    Tk_CoordsToWindow, /* 32 */\n    Tk_CreateBinding, /* 33 */\n    Tk_CreateBindingTable, /* 34 */\n    Tk_CreateErrorHandler, /* 35 */\n    Tk_CreateEventHandler, /* 36 */\n    Tk_CreateGenericHandler, /* 37 */\n    Tk_CreateImageType, /* 38 */\n    Tk_CreateItemType, /* 39 */\n    Tk_CreatePhotoImageFormat, /* 40 */\n    Tk_CreateSelHandler, /* 41 */\n    Tk_CreateWindow, /* 42 */\n    Tk_CreateWindowFromPath, /* 43 */\n    Tk_DefineBitmap, /* 44 */\n    Tk_DefineCursor, /* 45 */\n    Tk_DeleteAllBindings, /* 46 */\n    Tk_DeleteBinding, /* 47 */\n    Tk_DeleteBindingTable, /* 48 */\n    Tk_DeleteErrorHandler, /* 49 */\n    Tk_DeleteEventHandler, /* 50 */\n    Tk_DeleteGenericHandler, /* 51 */\n    Tk_DeleteImage, /* 52 */\n    Tk_DeleteSelHandler, /* 53 */\n    Tk_DestroyWindow, /* 54 */\n    Tk_DisplayName, /* 55 */\n    Tk_DistanceToTextLayout, /* 56 */\n    Tk_Draw3DPolygon, /* 57 */\n    Tk_Draw3DRectangle, /* 58 */\n    Tk_DrawChars, /* 59 */\n    Tk_DrawFocusHighlight, /* 60 */\n    Tk_DrawTextLayout, /* 61 */\n    Tk_Fill3DPolygon, /* 62 */\n    Tk_Fill3DRectangle, /* 63 */\n    Tk_FindPhoto, /* 64 */\n    Tk_FontId, /* 65 */\n    Tk_Free3DBorder, /* 66 */\n    Tk_FreeBitmap, /* 67 */\n    Tk_FreeColor, /* 68 */\n    Tk_FreeColormap, /* 69 */\n    Tk_FreeCursor, /* 70 */\n    Tk_FreeFont, /* 71 */\n    Tk_FreeGC, /* 72 */\n    Tk_FreeImage, /* 73 */\n    Tk_FreeOptions, /* 74 */\n    Tk_FreePixmap, /* 75 */\n    Tk_FreeTextLayout, /* 76 */\n    0, /* 77 */\n    Tk_GCForColor, /* 78 */\n    Tk_GeometryRequest, /* 79 */\n    Tk_Get3DBorder, /* 80 */\n    Tk_GetAllBindings, /* 81 */\n    Tk_GetAnchor, /* 82 */\n    Tk_GetAtomName, /* 83 */\n    Tk_GetBinding, /* 84 */\n    Tk_GetBitmap, /* 85 */\n    Tk_GetBitmapFromData, /* 86 */\n    Tk_GetCapStyle, /* 87 */\n    Tk_GetColor, /* 88 */\n    Tk_GetColorByValue, /* 89 */\n    Tk_GetColormap, /* 90 */\n    Tk_GetCursor, /* 91 */\n    Tk_GetCursorFromData, /* 92 */\n    Tk_GetFont, /* 93 */\n    Tk_GetFontFromObj, /* 94 */\n    Tk_GetFontMetrics, /* 95 */\n    Tk_GetGC, /* 96 */\n    Tk_GetImage, /* 97 */\n    Tk_GetImageModelData, /* 98 */\n    Tk_GetItemTypes, /* 99 */\n    Tk_GetJoinStyle, /* 100 */\n    Tk_GetJustify, /* 101 */\n    Tk_GetNumMainWindows, /* 102 */\n    Tk_GetOption, /* 103 */\n    Tk_GetPixels, /* 104 */\n    Tk_GetPixmap, /* 105 */\n    Tk_GetRelief, /* 106 */\n    Tk_GetRootCoords, /* 107 */\n    Tk_GetScrollInfo, /* 108 */\n    Tk_GetScreenMM, /* 109 */\n    Tk_GetSelection, /* 110 */\n    Tk_GetUid, /* 111 */\n    Tk_GetVisual, /* 112 */\n    Tk_GetVRootGeometry, /* 113 */\n    Tk_Grab, /* 114 */\n    Tk_HandleEvent, /* 115 */\n    Tk_IdToWindow, /* 116 */\n    Tk_ImageChanged, /* 117 */\n    0, /* 118 */\n    Tk_InternAtom, /* 119 */\n    Tk_IntersectTextLayout, /* 120 */\n    Tk_MaintainGeometry, /* 121 */\n    Tk_MainWindow, /* 122 */\n    Tk_MakeWindowExist, /* 123 */\n    Tk_ManageGeometry, /* 124 */\n    Tk_MapWindow, /* 125 */\n    Tk_MeasureChars, /* 126 */\n    Tk_MoveResizeWindow, /* 127 */\n    Tk_MoveWindow, /* 128 */\n    Tk_MoveToplevelWindow, /* 129 */\n    Tk_NameOf3DBorder, /* 130 */\n    Tk_NameOfAnchor, /* 131 */\n    Tk_NameOfBitmap, /* 132 */\n    Tk_NameOfCapStyle, /* 133 */\n    Tk_NameOfColor, /* 134 */\n    Tk_NameOfCursor, /* 135 */\n    Tk_NameOfFont, /* 136 */\n    Tk_NameOfImage, /* 137 */\n    Tk_NameOfJoinStyle, /* 138 */\n    Tk_NameOfJustify, /* 139 */\n    Tk_NameOfRelief, /* 140 */\n    Tk_NameToWindow, /* 141 */\n    Tk_OwnSelection, /* 142 */\n    Tk_ParseArgv, /* 143 */\n    0, /* 144 */\n    0, /* 145 */\n    Tk_PhotoGetImage, /* 146 */\n    Tk_PhotoBlank, /* 147 */\n    0, /* 148 */\n    Tk_PhotoGetSize, /* 149 */\n    Tk_PointToChar, /* 150 */\n    TkPointToChar_, /* 151 */\n    Tk_PostscriptFontName, /* 152 */\n    Tk_PreserveColormap, /* 153 */\n    Tk_QueueWindowEvent, /* 154 */\n    Tk_RedrawImage, /* 155 */\n    Tk_ResizeWindow, /* 156 */\n    Tk_RestackWindow, /* 157 */\n    Tk_RestrictEvents, /* 158 */\n    0, /* 159 */\n    Tk_SetAppName, /* 160 */\n    Tk_SetBackgroundFromBorder, /* 161 */\n    Tk_SetClass, /* 162 */\n    Tk_SetGrid, /* 163 */\n    Tk_SetInternalBorder, /* 164 */\n    Tk_SetWindowBackground, /* 165 */\n    Tk_SetWindowBackgroundPixmap, /* 166 */\n    Tk_SetWindowBorder, /* 167 */\n    Tk_SetWindowBorderWidth, /* 168 */\n    Tk_SetWindowBorderPixmap, /* 169 */\n    Tk_SetWindowColormap, /* 170 */\n    Tk_SetWindowVisual, /* 171 */\n    Tk_SizeOfBitmap, /* 172 */\n    Tk_SizeOfImage, /* 173 */\n    Tk_StrictMotif, /* 174 */\n    Tk_TextLayoutToPostscript, /* 175 */\n    Tk_TextWidth, /* 176 */\n    Tk_UndefineCursor, /* 177 */\n    Tk_UnderlineChars, /* 178 */\n    Tk_UnderlineTextLayout, /* 179 */\n    Tk_Ungrab, /* 180 */\n    Tk_UnmaintainGeometry, /* 181 */\n    Tk_UnmapWindow, /* 182 */\n    Tk_UnsetGrid, /* 183 */\n    Tk_UpdatePointer, /* 184 */\n    Tk_AllocBitmapFromObj, /* 185 */\n    Tk_Alloc3DBorderFromObj, /* 186 */\n    Tk_AllocColorFromObj, /* 187 */\n    Tk_AllocCursorFromObj, /* 188 */\n    Tk_AllocFontFromObj, /* 189 */\n    Tk_CreateOptionTable, /* 190 */\n    Tk_DeleteOptionTable, /* 191 */\n    Tk_Free3DBorderFromObj, /* 192 */\n    Tk_FreeBitmapFromObj, /* 193 */\n    Tk_FreeColorFromObj, /* 194 */\n    Tk_FreeConfigOptions, /* 195 */\n    Tk_FreeSavedOptions, /* 196 */\n    Tk_FreeCursorFromObj, /* 197 */\n    Tk_FreeFontFromObj, /* 198 */\n    Tk_Get3DBorderFromObj, /* 199 */\n    Tk_GetAnchorFromObj, /* 200 */\n    Tk_GetBitmapFromObj, /* 201 */\n    Tk_GetColorFromObj, /* 202 */\n    Tk_GetCursorFromObj, /* 203 */\n    Tk_GetOptionInfo, /* 204 */\n    Tk_GetOptionValue, /* 205 */\n    Tk_GetJustifyFromObj, /* 206 */\n    Tk_GetMMFromObj, /* 207 */\n    Tk_GetPixelsFromObj, /* 208 */\n    Tk_GetReliefFromObj, /* 209 */\n    Tk_GetScrollInfoObj, /* 210 */\n    Tk_InitOptions, /* 211 */\n    0, /* 212 */\n    Tk_RestoreSavedOptions, /* 213 */\n    Tk_SetOptions, /* 214 */\n    Tk_InitConsoleChannels, /* 215 */\n    0, /* 216 */\n    Tk_CreateSmoothMethod, /* 217 */\n    0, /* 218 */\n    0, /* 219 */\n    Tk_GetDash, /* 220 */\n    Tk_CreateOutline, /* 221 */\n    Tk_DeleteOutline, /* 222 */\n    Tk_ConfigOutlineGC, /* 223 */\n    Tk_ChangeOutlineGC, /* 224 */\n    Tk_ResetOutlineGC, /* 225 */\n    Tk_CanvasPsOutline, /* 226 */\n    Tk_SetTSOrigin, /* 227 */\n    Tk_CanvasGetCoordFromObj, /* 228 */\n    Tk_CanvasSetOffset, /* 229 */\n    Tk_DitherPhoto, /* 230 */\n    Tk_PostscriptBitmap, /* 231 */\n    Tk_PostscriptColor, /* 232 */\n    Tk_PostscriptFont, /* 233 */\n    Tk_PostscriptImage, /* 234 */\n    Tk_PostscriptPath, /* 235 */\n    Tk_PostscriptStipple, /* 236 */\n    Tk_PostscriptY, /* 237 */\n    Tk_PostscriptPhoto, /* 238 */\n    Tk_CreateClientMessageHandler, /* 239 */\n    Tk_DeleteClientMessageHandler, /* 240 */\n    Tk_CreateAnonymousWindow, /* 241 */\n    Tk_SetClassProcs, /* 242 */\n    Tk_SetInternalBorderEx, /* 243 */\n    Tk_SetMinimumRequestSize, /* 244 */\n    Tk_SetCaretPos, /* 245 */\n    0, /* 246 */\n    0, /* 247 */\n    Tk_CollapseMotionEvents, /* 248 */\n    Tk_RegisterStyleEngine, /* 249 */\n    Tk_GetStyleEngine, /* 250 */\n    Tk_RegisterStyledElement, /* 251 */\n    Tk_GetElementId, /* 252 */\n    Tk_CreateStyle, /* 253 */\n    Tk_GetStyle, /* 254 */\n    Tk_FreeStyle, /* 255 */\n    Tk_NameOfStyle, /* 256 */\n    Tk_AllocStyleFromObj, /* 257 */\n    0, /* 258 */\n    0, /* 259 */\n    Tk_GetStyledElement, /* 260 */\n    Tk_GetElementSize, /* 261 */\n    Tk_GetElementBox, /* 262 */\n    Tk_GetElementBorderWidth, /* 263 */\n    Tk_DrawElement, /* 264 */\n    Tk_PhotoExpand, /* 265 */\n    Tk_PhotoPutBlock, /* 266 */\n    Tk_PhotoPutZoomedBlock, /* 267 */\n    Tk_PhotoSetSize, /* 268 */\n    Tk_GetUserInactiveTime, /* 269 */\n    Tk_ResetUserInactiveTime, /* 270 */\n    Tk_Interp, /* 271 */\n    0, /* 272 */\n    0, /* 273 */\n    Tk_AlwaysShowSelection, /* 274 */\n    Tk_GetButtonMask, /* 275 */\n    Tk_GetDoublePixelsFromObj, /* 276 */\n    Tk_NewWindowObj, /* 277 */\n    Tk_SendVirtualEvent, /* 278 */\n    Tk_FontGetDescription, /* 279 */\n    Tk_CreatePhotoImageFormatVersion3, /* 280 */\n    Tk_DrawHighlightBorder, /* 281 */\n    Tk_SetMainMenubar, /* 282 */\n    Tk_SetWindowMenubar, /* 283 */\n    Tk_ClipDrawableToRect, /* 284 */\n    Tk_GetSystemDefault, /* 285 */\n    Tk_UseWindow, /* 286 */\n    Tk_MakeContainer, /* 287 */\n    Tk_GetOtherWindow, /* 288 */\n    Tk_Get3DBorderColors, /* 289 */\n    Tk_MakeWindow, /* 290 */\n    Tk_UnderlineCharsInContext, /* 291 */\n    Tk_DrawCharsInContext, /* 292 */\n    Tk_MeasureCharsInContext, /* 293 */\n    TkUnusedStubEntry, /* 294 */\n};\n\n/* !END!: Do not edit above this line. */\n\n\n#ifdef __CYGWIN__\nvoid *Tk_GetHINSTANCE(void)\n{\n    void *hInstance = NULL;\n\n    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,\n\t    (const char *) &tkIntStubs, &hInstance);\n    return hInstance;\n}\n#endif\n\n"
  },
  {
    "path": "generic/tkStubLib.c",
    "content": "/*\n * tkStubLib.c --\n *\n *\tStub object that will be statically linked into extensions that want\n *\tto access Tk.\n *\n * Copyright © 1998-1999 Scriptics Corporation.\n * Copyright © 1998 Paul Duffin.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n#ifdef MAC_OSX_TK\n#include \"tkMacOSXInt.h\"\n#endif\n\n#if !(defined(_WIN32) || defined(MAC_OSX_TK))\n#include \"tkUnixInt.h\"\n#endif\n\n/* TODO: These ought to come in some other way */\n#include \"tkPlatDecls.h\"\n#include \"tkIntXlibDecls.h\"\n\nMODULE_SCOPE const TkStubs *tkStubsPtr;\nMODULE_SCOPE const TkPlatStubs *tkPlatStubsPtr;\nMODULE_SCOPE const TkIntStubs *tkIntStubsPtr;\nMODULE_SCOPE const TkIntPlatStubs *tkIntPlatStubsPtr;\nMODULE_SCOPE const TkIntXlibStubs *tkIntXlibStubsPtr;\n\f\nconst TkStubs *tkStubsPtr = NULL;\nconst TkPlatStubs *tkPlatStubsPtr = NULL;\nconst TkIntStubs *tkIntStubsPtr = NULL;\nconst TkIntPlatStubs *tkIntPlatStubsPtr = NULL;\nconst TkIntXlibStubs *tkIntXlibStubsPtr = NULL;\n\f\n/*\n * Use our own isdigit to avoid linking to libc on windows\n */\n\nstatic int\nisDigit(const int c)\n{\n    return (c >= '0' && c <= '9');\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_InitStubs --\n *\n *\tChecks that the correct version of Tk is loaded and that it supports\n *\tstubs. It then initialises the stub table pointers.\n *\n * Results:\n *\tThe actual version of Tk that satisfies the request, or NULL to\n *\tindicate that an error occurred.\n *\n * Side effects:\n *\tSets the stub table pointers.\n *\n *----------------------------------------------------------------------\n */\n#undef Tk_InitStubs\nMODULE_SCOPE const char *\nTk_InitStubs(\n    Tcl_Interp *interp,\n    const char *version,\n    int exact)\n{\n    const char *packageName = \"tk\";\n    const char *errMsg = NULL;\n    void *clientData = NULL;\n    const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,\n\t    packageName, version, 0, &clientData);\n\n    if (actualVersion == NULL) {\n\tpackageName = \"Tk\";\n\tactualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,\n\t    packageName, version, 0, &clientData);\n\tif (actualVersion == NULL) {\n\t    return NULL;\n\t}\n    }\n\n    if (exact) {\n\tconst char *p = version;\n\tint count = 0;\n\n\twhile (*p) {\n\t    count += !isDigit(*p++);\n\t}\n\tif (count == 1) {\n\t    const char *q = actualVersion;\n\n\t    p = version;\n\t    while (*p && (*p == *q)) {\n\t\tp++; q++;\n\t    }\n\t    if (*p || isDigit(*q)) {\n\t\t/* Construct error message */\n\t\ttclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, 1, NULL);\n\t\treturn NULL;\n\t    }\n\t} else {\n\t    actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName,\n\t\t    version, 1, NULL);\n\t    if (actualVersion == NULL) {\n\t\treturn NULL;\n\t    }\n\t}\n    }\n    if (clientData == NULL) {\n\terrMsg = \"missing stub table pointer\";\n    } else {\n\ttkStubsPtr = (const TkStubs *)clientData;\n\tif (tkStubsPtr->hooks) {\n\t    tkPlatStubsPtr = tkStubsPtr->hooks->tkPlatStubs;\n\t    tkIntStubsPtr = tkStubsPtr->hooks->tkIntStubs;\n\t    tkIntPlatStubsPtr = tkStubsPtr->hooks->tkIntPlatStubs;\n\t    tkIntXlibStubsPtr = tkStubsPtr->hooks->tkIntXlibStubs;\n\t} else {\n\t    tkPlatStubsPtr = NULL;\n\t    tkIntStubsPtr = NULL;\n\t    tkIntPlatStubsPtr = NULL;\n\t    tkIntXlibStubsPtr = NULL;\n\t}\n\treturn actualVersion;\n    }\n    tclStubsPtr->tcl_ResetResult(interp);\n    tclStubsPtr->tcl_AppendResult(interp, \"Error loading \", packageName,\n\t    \" (requested version \", version, \", actual version \",\n\t    actualVersion, \"): \", errMsg, NULL);\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkStyle.c",
    "content": "/*\n * tkStyle.c --\n *\n *\tThis file implements the widget styles and themes support.\n *\n * Copyright © 1990-1993 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The following structure is used to cache widget option specs matching an\n * element's required options defined by Tk_ElementOptionSpecs. It also holds\n * information behind Tk_StyledElement opaque tokens.\n */\n\ntypedef struct StyledWidgetSpec {\n    struct StyledElement *elementPtr;\n\t\t\t\t/* Pointer to the element holding this\n\t\t\t\t * structure. */\n    Tk_OptionTable optionTable;\t/* Option table for the widget class using the\n\t\t\t\t * element. */\n    const Tk_OptionSpec **optionsPtr;\n\t\t\t\t/* Table of option spec pointers, matching the\n\t\t\t\t * option list provided during element\n\t\t\t\t * registration. Malloc'd. */\n} StyledWidgetSpec;\n\n/*\n * Elements are declared using static templates. But static information must\n * be completed by dynamic information only accessible at runtime. For each\n * registered element, an instance of the following structure is stored in\n * each style engine and used to cache information about the widget types\n * (identified by their optionTable) that use the given element.\n */\n\ntypedef struct StyledElement {\n    struct Tk_ElementSpec *specPtr;\n\t\t\t\t/* Filled with template provided during\n\t\t\t\t * registration. NULL means no implementation\n\t\t\t\t * is available for the current engine. */\n    int nbWidgetSpecs;\t\t/* Size of the array below. Number of distinct\n\t\t\t\t * widget classes (actually, distinct option\n\t\t\t\t * tables) that used the element so far. */\n    StyledWidgetSpec *widgetSpecs;\n\t\t\t\t/* See above for the structure definition.\n\t\t\t\t * Table grows dynamically as new widgets use\n\t\t\t\t * the element. Malloc'd. */\n} StyledElement;\n\n/*\n * The following structure holds information behind Tk_StyleEngine opaque\n * tokens.\n */\n\ntypedef struct StyleEngine {\n    const char *name;\t\t/* Name of engine. Points to a hash key. */\n    StyledElement *elements;\t/* Table of widget element descriptors. Each\n\t\t\t\t * element is indexed by a unique system-wide\n\t\t\t\t * ID. Table grows dynamically as new elements\n\t\t\t\t * are registered. Malloc'd. */\n    struct StyleEngine *parentPtr;\n\t\t\t\t/* Parent engine. Engines may be layered to\n\t\t\t\t * form a fallback chain, terminated by the\n\t\t\t\t * default system engine. */\n} StyleEngine;\n\n/*\n * Styles are instances of style engines. The following structure holds\n * information behind Tk_Style opaque tokens.\n */\n\ntypedef struct Style {\n    const char *name;\t\t/* Name of style. Points to a hash key. */\n    StyleEngine *enginePtr;\t/* Style engine of which the style is an\n\t\t\t\t * instance. */\n    void *clientData;\t/* Data provided during registration. */\n} Style;\n\n/*\n * Each registered element uses an instance of the following structure.\n */\n\ntypedef struct Element {\n    const char *name;\t\t/* Name of element. Points to a hash key. */\n    int id;\t\t\t/* Id of element. */\n    int genericId;\t\t/* Id of generic element. */\n    int created;\t\t/* Boolean, whether the element was created\n\t\t\t\t * explicitly (was registered) or implicitly\n\t\t\t\t * (by a derived element). */\n} Element;\n\n/*\n * Thread-local data.\n */\n\ntypedef struct {\n    size_t nbInit;\t\t\t/* Number of calls to the init proc. */\n    Tcl_HashTable engineTable;\t/* Map a name to a style engine. Keys are\n\t\t\t\t * strings, values are Tk_StyleEngine\n\t\t\t\t * pointers. */\n    StyleEngine *defaultEnginePtr;\n\t\t\t\t/* Default, core-defined style engine. Global\n\t\t\t\t * fallback for all engines. */\n    Tcl_HashTable styleTable;\t/* Map a name to a style. Keys are strings,\n\t\t\t\t * values are Tk_Style pointers.*/\n    Tcl_Size nbElements;\t\t/* Size of the below tables. */\n    Tcl_HashTable elementTable;\t/* Map a name to an element Id. Keys are\n\t\t\t\t * strings, values are integer element IDs. */\n    Element *elements;\t\t/* Array of Elements. */\n} ThreadSpecificData;\n\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tCreateElement(const char *name, int create);\nstatic void\t\tDupStyleObjProc(Tcl_Obj *srcObjPtr,\n\t\t\t    Tcl_Obj *dupObjPtr);\nstatic void\t\tFreeElement(Element *elementPtr);\nstatic void\t\tFreeStyledElement(StyledElement *elementPtr);\nstatic void\t\tFreeStyleEngine(StyleEngine *enginePtr);\nstatic void\t\tFreeStyleObjProc(Tcl_Obj *objPtr);\nstatic void\t\tFreeWidgetSpec(StyledWidgetSpec *widgetSpecPtr);\nstatic StyledElement *\tGetStyledElement(StyleEngine *enginePtr,\n\t\t\t    Tcl_Size elementId);\nstatic StyledWidgetSpec*GetWidgetSpec(StyledElement *elementPtr,\n\t\t\t    Tk_OptionTable optionTable);\nstatic void\t\tInitElement(Element *elementPtr, const char *name,\n\t\t\t    int id, int genericId, int created);\nstatic void\t\tInitStyle(Style *stylePtr, const char *name,\n\t\t\t    StyleEngine *enginePtr, void *clientData);\nstatic void\t\tInitStyledElement(StyledElement *elementPtr);\nstatic void\t\tInitStyleEngine(StyleEngine *enginePtr,\n\t\t\t    const char *name, StyleEngine *parentPtr);\nstatic void\t\tInitWidgetSpec(StyledWidgetSpec *widgetSpecPtr,\n\t\t\t    StyledElement *elementPtr,\n\t\t\t    Tk_OptionTable optionTable);\nstatic int\t\tSetStyleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);\n\n/*\n * The following structure defines the implementation of the \"style\" Tcl\n * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each\n * style object points to the Style structure for the stylefont, or NULL.\n */\n\nstatic const Tcl_ObjType styleObjType = {\n    \"style\",\t\t\t/* name */\n    FreeStyleObjProc,\t\t/* freeIntRepProc */\n    DupStyleObjProc,\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkStylePkgInit --\n *\n *\tThis function is called when an application is created. It initializes\n *\tall the structures that are used by the style package on a per\n *\tapplication basis.\n *\n * Results:\n *\tStores data in thread-local storage.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkStylePkgInit(\n    TCL_UNUSED(TkMainInfo *))\t/* The application being created. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->nbInit != 0) {\n\treturn;\n    }\n\n    /*\n     * Initialize tables.\n     */\n\n    Tcl_InitHashTable(&tsdPtr->engineTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&tsdPtr->styleTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&tsdPtr->elementTable, TCL_STRING_KEYS);\n    tsdPtr->nbElements = 0;\n    tsdPtr->elements = NULL;\n\n    /*\n     * Create the default system engine.\n     */\n\n    tsdPtr->defaultEnginePtr = (StyleEngine *)\n\t    Tk_RegisterStyleEngine(NULL, NULL);\n\n    /*\n     * Create the default system style.\n     */\n\n    Tk_CreateStyle(NULL, (Tk_StyleEngine) tsdPtr->defaultEnginePtr, NULL);\n\n    tsdPtr->nbInit++;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkStylePkgFree --\n *\n *\tThis function is called when an application is deleted. It deletes all\n *\tthe structures that were used by the style package for this\n *\tapplication.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkStylePkgFree(\n    TCL_UNUSED(TkMainInfo *))\t/* The application being deleted. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n    StyleEngine *enginePtr;\n    Tcl_Size i;\n\n    tsdPtr->nbInit--;\n    if (tsdPtr->nbInit != 0) {\n\treturn;\n    }\n\n    /*\n     * Free styles.\n     */\n\n    entryPtr = Tcl_FirstHashEntry(&tsdPtr->styleTable, &search);\n    while (entryPtr != NULL) {\n\tTcl_Free(Tcl_GetHashValue(entryPtr));\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&tsdPtr->styleTable);\n\n    /*\n     * Free engines.\n     */\n\n    entryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);\n    while (entryPtr != NULL) {\n\tenginePtr = (StyleEngine *)Tcl_GetHashValue(entryPtr);\n\tFreeStyleEngine(enginePtr);\n\tTcl_Free(enginePtr);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&tsdPtr->engineTable);\n\n    /*\n     * Free elements.\n     */\n\n    for (i = 0; i < tsdPtr->nbElements; i++) {\n\tFreeElement(tsdPtr->elements+i);\n    }\n    Tcl_DeleteHashTable(&tsdPtr->elementTable);\n    Tcl_Free(tsdPtr->elements);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_RegisterStyleEngine --\n *\n *\tThis function is called to register a new style engine. Style engines\n *\tare stored in thread-local space.\n *\n * Results:\n *\tThe newly allocated engine, or NULL if an engine with the same name\n *\texists.\n *\n * Side effects:\n *\tMemory allocated. Data added to thread-local table.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_StyleEngine\nTk_RegisterStyleEngine(\n    const char *name,\t\t/* Name of the engine to create. NULL or empty\n\t\t\t\t * means the default system engine. */\n    Tk_StyleEngine parent)\t/* The engine's parent. NULL means the default\n\t\t\t\t * system engine. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr;\n    int newEntry;\n    StyleEngine *enginePtr;\n\n    /*\n     * Attempt to create a new entry in the engine table.\n     */\n\n    entryPtr = Tcl_CreateHashEntry(&tsdPtr->engineTable,\n\t    (name != NULL ? name : \"\"), &newEntry);\n    if (!newEntry) {\n\t/*\n\t * An engine was already registered by that name.\n\t */\n\n\treturn NULL;\n    }\n\n    /*\n     * Allocate and intitialize a new engine.\n     */\n\n    enginePtr = (StyleEngine *)Tcl_Alloc(sizeof(StyleEngine));\n    InitStyleEngine(enginePtr, (const char *)Tcl_GetHashKey(&tsdPtr->engineTable, entryPtr),\n\t    (StyleEngine *) parent);\n    Tcl_SetHashValue(entryPtr, enginePtr);\n\n    return (Tk_StyleEngine) enginePtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitStyleEngine --\n *\n *\tInitialize a newly allocated style engine.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitStyleEngine(\n    StyleEngine *enginePtr,\t/* Points to an uninitialized engine. */\n    const char *name,\t\t/* Name of the registered engine. NULL or empty\n\t\t\t\t * means the default system engine. Usually\n\t\t\t\t * points to the hash key. */\n    StyleEngine *parentPtr)\t/* The engine's parent. NULL means the default\n\t\t\t\t * system engine. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_Size elementId;\n\n    if (name == NULL || *name == '\\0') {\n\t/*\n\t * This is the default style engine.\n\t */\n\n\tenginePtr->parentPtr = NULL;\n    } else if (parentPtr == NULL) {\n\t/*\n\t * The default style engine is the parent.\n\t */\n\n\tenginePtr->parentPtr = tsdPtr->defaultEnginePtr;\n    } else {\n\tenginePtr->parentPtr = parentPtr;\n    }\n\n    /*\n     * Allocate and initialize elements array.\n     */\n\n    if (tsdPtr->nbElements > 0) {\n\tenginePtr->elements = (StyledElement *)Tcl_Alloc(\n\t\tsizeof(StyledElement) * tsdPtr->nbElements);\n\tfor (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {\n\t    InitStyledElement(enginePtr->elements+elementId);\n\t}\n    } else {\n\tenginePtr->elements = NULL;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeStyleEngine --\n *\n *\tFree an engine and its associated data.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeStyleEngine(\n    StyleEngine *enginePtr)\t/* The style engine to free. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_Size elementId;\n\n    /*\n     * Free allocated elements.\n     */\n\n    for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {\n\tFreeStyledElement(enginePtr->elements+elementId);\n    }\n    Tcl_Free(enginePtr->elements);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetStyleEngine --\n *\n *\tRetrieve a registered style engine by its name.\n *\n * Results:\n *\tA pointer to the style engine, or NULL if none found.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_StyleEngine\nTk_GetStyleEngine(\n    const char *name)\t\t/* Name of the engine to retrieve. NULL or\n\t\t\t\t * empty means the default system engine. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr;\n\n    if (name == NULL) {\n\treturn (Tk_StyleEngine) tsdPtr->defaultEnginePtr;\n    }\n\n    entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name!=NULL?name:\"\"));\n    if (!entryPtr) {\n\treturn NULL;\n    }\n\n    return (Tk_StyleEngine)Tcl_GetHashValue(entryPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitElement --\n *\n *\tInitialize a newly allocated element.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitElement(\n    Element *elementPtr,\t/* Points to an uninitialized element.*/\n    const char *name,\t\t/* Name of the registered element. Usually\n\t\t\t\t * points to the hash key. */\n    int id,\t\t\t/* Unique element ID. */\n    int genericId,\t\t/* ID of generic element. -1 means none. */\n    int created)\t\t/* Boolean, whether the element was created\n\t\t\t\t * explicitly (was registered) or implicitly\n\t\t\t\t * (by a derived element). */\n{\n    elementPtr->name = name;\n    elementPtr->id = id;\n    elementPtr->genericId = genericId;\n    elementPtr->created = (created?1:0);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeElement --\n *\n *\tFree an element and its associated data.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeElement(\n    TCL_UNUSED(Element *))\t/* The element to free. */\n{\n    /* Nothing to do. */\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitStyledElement --\n *\n *\tInitialize a newly allocated styled element.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitStyledElement(\n    StyledElement *elementPtr)\t/* Points to an uninitialized element.*/\n{\n    memset(elementPtr, 0, sizeof(StyledElement));\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeStyledElement --\n *\n *\tFree a styled element and its associated data.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeStyledElement(\n    StyledElement *elementPtr)\t/* The styled element to free. */\n{\n    int i;\n\n    /*\n     * Free allocated widget specs.\n     */\n\n    for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {\n\tFreeWidgetSpec(elementPtr->widgetSpecs+i);\n    }\n    Tcl_Free(elementPtr->widgetSpecs);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * CreateElement --\n *\n *\tFind an existing or create a new element.\n *\n * Results:\n *\tThe unique ID for the created or found element.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nCreateElement(\n    const char *name,\t\t/* Name of the element. */\n    int create)\t\t\t/* Boolean, whether the element is being\n\t\t\t\t * created explicitly (being registered) or\n\t\t\t\t * implicitly (by a derived element). */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr, *engineEntryPtr;\n    Tcl_HashSearch search;\n    int newEntry, elementId, genericId = -1;\n    const char *dot;\n    StyleEngine *enginePtr;\n\n    /*\n     * Find or create the element.\n     */\n\n    entryPtr = Tcl_CreateHashEntry(&tsdPtr->elementTable, name, &newEntry);\n    if (!newEntry) {\n\telementId = PTR2INT(Tcl_GetHashValue(entryPtr));\n\tif (create) {\n\t    tsdPtr->elements[elementId].created = 1;\n\t}\n\treturn elementId;\n    }\n\n    /*\n     * The element didn't exist. If it's a derived element, find or create its\n     * generic element ID.\n     */\n\n    dot = strchr(name, '.');\n    if (dot) {\n\tgenericId = CreateElement(dot+1, 0);\n    }\n\n    elementId = tsdPtr->nbElements++;\n    Tcl_SetHashValue(entryPtr, INT2PTR(elementId));\n\n    /*\n     * Reallocate element table.\n     */\n\n    tsdPtr->elements = (Element *)Tcl_Realloc(tsdPtr->elements,\n\t    sizeof(Element) * tsdPtr->nbElements);\n    InitElement(tsdPtr->elements+elementId,\n\t    (const char *)Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId,\n\t    genericId, create);\n\n    /*\n     * Reallocate style engines' element table.\n     */\n\n    engineEntryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);\n    while (engineEntryPtr != NULL) {\n\tenginePtr = (StyleEngine *)Tcl_GetHashValue(engineEntryPtr);\n\n\tenginePtr->elements = (StyledElement *)Tcl_Realloc(enginePtr->elements,\n\t\tsizeof(StyledElement) * tsdPtr->nbElements);\n\tInitStyledElement(enginePtr->elements+elementId);\n\n\tengineEntryPtr = Tcl_NextHashEntry(&search);\n    }\n\n    return elementId;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetElementId --\n *\n *\tFind an existing element.\n *\n * Results:\n *\tThe unique ID for the found element, or -1 if not found.\n *\n * Side effects:\n *\tGeneric elements may be created.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_GetElementId(\n    const char *name)\t\t/* Name of the element. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr;\n    int genericId = -1;\n    const char *dot;\n\n    /*\n     * Find the element Id.\n     */\n\n    entryPtr = Tcl_FindHashEntry(&tsdPtr->elementTable, name);\n    if (entryPtr) {\n\treturn PTR2INT(Tcl_GetHashValue(entryPtr));\n    }\n\n    /*\n     * Element not found. If the given name was derived, then first search for\n     * the generic element. If found, create the new derived element.\n     */\n\n    dot = strchr(name, '.');\n    if (!dot) {\n\treturn -1;\n    }\n    genericId = Tk_GetElementId(dot+1);\n    if (genericId == -1) {\n\treturn -1;\n    }\n    if (!tsdPtr->elements[genericId].created) {\n\t/*\n\t * The generic element was created implicitly and thus has no real\n\t * existence.\n\t */\n\n\treturn -1;\n    } else {\n\t/*\n\t * The generic element was created explicitly. Create the derived\n\t * element.\n\t */\n\n\treturn CreateElement(name, 1);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_RegisterStyledElement --\n *\n *\tRegister an implementation of a new or existing element for the given\n *\tstyle engine.\n *\n * Results:\n *\tThe unique ID for the created or found element.\n *\n * Side effects:\n *\tElements may be created. Memory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_RegisterStyledElement(\n    Tk_StyleEngine engine,\t/* Style engine providing the\n\t\t\t\t * implementation. */\n    Tk_ElementSpec *templatePtr)/* Static template information about the\n\t\t\t\t * element. */\n{\n    int elementId;\n    StyledElement *elementPtr;\n    Tk_ElementSpec *specPtr;\n    int nbOptions;\n    Tk_ElementOptionSpec *srcOptions, *dstOptions;\n\n    if (templatePtr->version != TK_STYLE_VERSION_1) {\n\t/*\n\t * Version mismatch. Do nothing.\n\t */\n\n\treturn -1;\n    }\n\n    if (engine == NULL) {\n\tengine = Tk_GetStyleEngine(NULL);\n    }\n\n    /*\n     * Register the element, allocating storage in the various engines if\n     * necessary.\n     */\n\n    elementId = CreateElement(templatePtr->name, 1);\n\n    /*\n     * Initialize the styled element.\n     */\n\n    elementPtr = ((StyleEngine *) engine)->elements+elementId;\n\n    specPtr = (Tk_ElementSpec *)Tcl_Alloc(sizeof(Tk_ElementSpec));\n    specPtr->version = templatePtr->version;\n    specPtr->name = (char *)Tcl_Alloc(strlen(templatePtr->name)+1);\n    strcpy(specPtr->name, templatePtr->name);\n    nbOptions = 0;\n    for (nbOptions = 0, srcOptions = templatePtr->options;\n\t    srcOptions->name != NULL; nbOptions++, srcOptions++) {\n\t/* empty body */\n    }\n    specPtr->options = (Tk_ElementOptionSpec *)\n\t    Tcl_Alloc(sizeof(Tk_ElementOptionSpec) * (nbOptions+1));\n    for (srcOptions = templatePtr->options, dstOptions = specPtr->options;\n\t    /* End condition within loop */; srcOptions++, dstOptions++) {\n\tif (srcOptions->name == NULL) {\n\t    dstOptions->name = NULL;\n\t    break;\n\t}\n\n\tdstOptions->name = (char *)Tcl_Alloc(strlen(srcOptions->name)+1);\n\tstrcpy(dstOptions->name, srcOptions->name);\n\tdstOptions->type = srcOptions->type;\n    }\n    specPtr->getSize = templatePtr->getSize;\n    specPtr->getBox = templatePtr->getBox;\n    specPtr->getBorderWidth = templatePtr->getBorderWidth;\n    specPtr->draw = templatePtr->draw;\n\n    elementPtr->specPtr = specPtr;\n    elementPtr->nbWidgetSpecs = 0;\n    elementPtr->widgetSpecs = NULL;\n\n    return elementId;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetStyledElement --\n *\n *\tGet a registered implementation of an existing element for the given\n *\tstyle engine.\n *\n * Results:\n *\tThe styled element descriptor, or NULL if not found.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic StyledElement *\nGetStyledElement(\n    StyleEngine *enginePtr,\t/* Style engine providing the implementation.\n\t\t\t\t * NULL means the default system engine. */\n    Tcl_Size elementId)\t\t/* Unique element ID */\n{\n    StyledElement *elementPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    StyleEngine *enginePtr2;\n\n    if (enginePtr == NULL) {\n\tenginePtr = tsdPtr->defaultEnginePtr;\n    }\n\n    while (elementId != TCL_INDEX_NONE && elementId < tsdPtr->nbElements) {\n\t/*\n\t * Look for an implemented element through the engine chain.\n\t */\n\n\tenginePtr2 = enginePtr;\n\tdo {\n\t    elementPtr = enginePtr2->elements+elementId;\n\t    if (elementPtr->specPtr != NULL) {\n\t\treturn elementPtr;\n\t    }\n\t    enginePtr2 = enginePtr2->parentPtr;\n\t} while (enginePtr2 != NULL);\n\n\t/*\n\t * None found, try with the generic element.\n\t */\n\n\telementId = tsdPtr->elements[elementId].genericId;\n    }\n\n    /*\n     * No matching element found.\n     */\n\n    return NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitWidgetSpec --\n *\n *\tInitialize a newly allocated widget spec.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitWidgetSpec(\n    StyledWidgetSpec *widgetSpecPtr,\n\t\t\t\t/* Points to an uninitialized widget spec. */\n    StyledElement *elementPtr,\t/* Styled element descriptor. */\n    Tk_OptionTable optionTable)\t/* The widget's option table. */\n{\n    int i, nbOptions;\n    Tk_ElementOptionSpec *elementOptionPtr;\n    const Tk_OptionSpec *widgetOptionPtr;\n\n    widgetSpecPtr->elementPtr = elementPtr;\n    widgetSpecPtr->optionTable = optionTable;\n\n    /*\n     * Count the number of options.\n     */\n\n    for (nbOptions = 0, elementOptionPtr = elementPtr->specPtr->options;\n\t    elementOptionPtr->name != NULL; nbOptions++, elementOptionPtr++) {\n\t/* empty body */\n    }\n\n    /*\n     * Build the widget option list.\n     */\n\n    widgetSpecPtr->optionsPtr =\n\t    (const Tk_OptionSpec **)Tcl_Alloc(sizeof(Tk_OptionSpec *) * nbOptions);\n    for (i = 0, elementOptionPtr = elementPtr->specPtr->options;\n\t    i < nbOptions; i++, elementOptionPtr++) {\n\twidgetOptionPtr = TkGetOptionSpec(elementOptionPtr->name, optionTable);\n\n\t/*\n\t * Check that the widget option type is compatible with one of the\n\t * element's required types.\n\t */\n\n\tif (elementOptionPtr->type == TK_OPTION_END\n\t    || elementOptionPtr->type == widgetOptionPtr->type) {\n\t    widgetSpecPtr->optionsPtr[i] = widgetOptionPtr;\n\t} else {\n\t    widgetSpecPtr->optionsPtr[i] = NULL;\n\t}\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeWidgetSpec --\n *\n *\tFree a widget spec and its associated data.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMemory freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeWidgetSpec(\n    StyledWidgetSpec *widgetSpecPtr)\n\t\t\t\t/* The widget spec to free. */\n{\n    Tcl_Free(widgetSpecPtr->optionsPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetWidgetSpec --\n *\n *\tReturn a new or existing widget spec for the given element and widget\n *\ttype (identified by its option table).\n *\n * Results:\n *\tA pointer to the matching widget spec.\n *\n * Side effects:\n *\tMemory may be allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic StyledWidgetSpec *\nGetWidgetSpec(\n    StyledElement *elementPtr,\t/* Styled element descriptor. */\n    Tk_OptionTable optionTable)\t/* The widget's option table. */\n{\n    StyledWidgetSpec *widgetSpecPtr;\n    int i;\n\n    /*\n     * Try to find an existing widget spec.\n     */\n\n    for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {\n\twidgetSpecPtr = elementPtr->widgetSpecs+i;\n\tif (widgetSpecPtr->optionTable == optionTable) {\n\t    return widgetSpecPtr;\n\t}\n    }\n\n    /*\n     * Create and initialize a new widget spec.\n     */\n\n    i = elementPtr->nbWidgetSpecs++;\n    elementPtr->widgetSpecs = (StyledWidgetSpec *)Tcl_Realloc(elementPtr->widgetSpecs,\n\t    sizeof(StyledWidgetSpec) * elementPtr->nbWidgetSpecs);\n    widgetSpecPtr = elementPtr->widgetSpecs+i;\n    InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable);\n\n    return widgetSpecPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetStyledElement --\n *\n *\tThis function returns a styled instance of the given element.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCached data may be allocated or updated.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_StyledElement\nTk_GetStyledElement(\n    Tk_Style style,\t\t/* The widget style. */\n    Tcl_Size elementId,\t\t/* Unique element ID. */\n    Tk_OptionTable optionTable)\t/* Option table for the widget. */\n{\n    Style *stylePtr = (Style *) style;\n    StyledElement *elementPtr;\n\n    /*\n     * Get an element implementation and call corresponding hook.\n     */\n\n    elementPtr = GetStyledElement((stylePtr?stylePtr->enginePtr:NULL),\n\t    elementId);\n    if (!elementPtr) {\n\treturn NULL;\n    }\n\n    return (Tk_StyledElement) GetWidgetSpec(elementPtr, optionTable);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetElementSize --\n *\n *\tThis function computes the size of the given widget element according\n *\tto its style.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCached data may be allocated or updated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_GetElementSize(\n    Tk_Style style,\t\t/* The widget style. */\n    Tk_StyledElement element,\t/* The styled element, previously returned by\n\t\t\t\t * Tk_GetStyledElement. */\n    void *recordPtr,\t\t/* The widget record. */\n    Tk_Window tkwin,\t\t/* The widget window. */\n    int width, int height,\t/* Requested size. */\n    int inner,\t\t\t/* If TRUE, compute the outer size according\n\t\t\t\t * to the requested minimum inner size. If\n\t\t\t\t * FALSE, compute the inner size according to\n\t\t\t\t * the requested maximum outer size. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* Returned size. */\n{\n    Style *stylePtr = (Style *) style;\n    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;\n\n    widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData,\n\t    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner,\n\t    widthPtr, heightPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetElementBox --\n *\n *\tThis function computes the bounding or inscribed box coordinates of\n *\tthe given widget element according to its style and within the given\n *\tlimits.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCached data may be allocated or updated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_GetElementBox(\n    Tk_Style style,\t\t/* The widget style. */\n    Tk_StyledElement element,\t/* The styled element, previously returned by\n\t\t\t\t * Tk_GetStyledElement. */\n    void *recordPtr,\t\t/* The widget record. */\n    Tk_Window tkwin,\t\t/* The widget window. */\n    int x, int y,\t\t/* Top left corner of available area. */\n    int width, int height,\t/* Size of available area. */\n    int inner,\t\t\t/* Boolean. If TRUE, compute the bounding box\n\t\t\t\t * according to the requested inscribed box\n\t\t\t\t * size. If FALSE, compute the inscribed box\n\t\t\t\t * according to the requested bounding box. */\n    int *xPtr, int *yPtr,\t/* Returned top left corner. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* Returned size. */\n{\n    Style *stylePtr = (Style *) style;\n    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;\n\n    widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData,\n\t    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height,\n\t    inner, xPtr, yPtr, widthPtr, heightPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetElementBorderWidth --\n *\n *\tThis function computes the border widthof the given widget element\n *\taccording to its style and within the given limits.\n *\n * Results:\n *\tBorder width in pixels. This value is uniform for all four sides.\n *\n * Side effects:\n *\tCached data may be allocated or updated.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_GetElementBorderWidth(\n    Tk_Style style,\t\t/* The widget style. */\n    Tk_StyledElement element,\t/* The styled element, previously returned by\n\t\t\t\t * Tk_GetStyledElement. */\n    void *recordPtr,\t\t/* The widget record. */\n    Tk_Window tkwin)\t\t/* The widget window. */\n{\n    Style *stylePtr = (Style *) style;\n    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;\n\n    return widgetSpecPtr->elementPtr->specPtr->getBorderWidth(\n\t    stylePtr->clientData, (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawElement --\n *\n *\tThis function draw the given widget element in a given drawable area.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tCached data may be allocated or updated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawElement(\n    Tk_Style style,\t\t/* The widget style. */\n    Tk_StyledElement element,\t/* The styled element, previously returned by\n\t\t\t\t * Tk_GetStyledElement. */\n    void *recordPtr,\t\t/* The widget record. */\n    Tk_Window tkwin,\t\t/* The widget window. */\n    Drawable d,\t\t\t/* Where to draw element. */\n    int x, int y,\t\t/* Top left corner of element. */\n    int width, int height,\t/* Size of element. */\n    int state)\t\t\t/* Drawing state flags. */\n{\n    Style *stylePtr = (Style *) style;\n    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;\n\n    widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData,\n\t    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width,\n\t    height, state);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_CreateStyle --\n *\n *\tThis function is called to create a new style as an instance of the\n *\tgiven engine. Styles are stored in thread-local space.\n *\n * Results:\n *\tThe newly allocated style, or NULL if the style already exists.\n *\n * Side effects:\n *\tMemory allocated. Data added to thread-local table.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_Style\nTk_CreateStyle(\n    const char *name,\t\t/* Name of the style to create. NULL or empty\n\t\t\t\t * means the default system style. */\n    Tk_StyleEngine engine,\t/* The style engine. */\n    void *clientData)\t/* Private data passed as is to engine code. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr;\n    int newEntry;\n    Style *stylePtr;\n\n    /*\n     * Attempt to create a new entry in the style table.\n     */\n\n    entryPtr = Tcl_CreateHashEntry(&tsdPtr->styleTable, (name?name:\"\"),\n\t    &newEntry);\n    if (!newEntry) {\n\t/*\n\t * A style was already registered by that name.\n\t */\n\n\treturn NULL;\n    }\n\n    /*\n     * Allocate and intitialize a new style.\n     */\n\n    stylePtr = (Style *)Tcl_Alloc(sizeof(Style));\n    InitStyle(stylePtr, (const char *)Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr),\n\t    (engine!=NULL ? (StyleEngine*) engine : tsdPtr->defaultEnginePtr),\n\t    clientData);\n    Tcl_SetHashValue(entryPtr, stylePtr);\n\n    return (Tk_Style) stylePtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_NameOfStyle --\n *\n *\tGiven a style, return its registered name.\n *\n * Results:\n *\tThe return value is the name that was passed to Tk_CreateStyle() to\n *\tcreate the style. The storage for the returned string is private (it\n *\tpoints to the corresponding hash key) The caller should not modify\n *\tthis string.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nconst char *\nTk_NameOfStyle(\n    Tk_Style style)\t\t/* Style whose name is desired. */\n{\n    Style *stylePtr = (Style *) style;\n\n    return stylePtr->name;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitStyle --\n *\n *\tInitialize a newly allocated style.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitStyle(\n    Style *stylePtr,\t\t/* Points to an uninitialized style. */\n    const char *name,\t\t/* Name of the registered style. NULL or empty\n\t\t\t\t * means the default system style. Usually\n\t\t\t\t * points to the hash key. */\n    StyleEngine *enginePtr,\t/* The style engine. */\n    void *clientData)\t/* Private data passed as is to engine code. */\n{\n    stylePtr->name = name;\n    stylePtr->enginePtr = enginePtr;\n    stylePtr->clientData = clientData;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_GetStyle --\n *\n *\tRetrieve a registered style by its name.\n *\n * Results:\n *\tA pointer to the style engine, or NULL if none found. In the latter\n *\tcase and if the interp is not NULL, an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_Style\nTk_GetStyle(\n    Tcl_Interp *interp,\t\t/* Interp for error return. */\n    const char *name)\t\t/* Name of the style to retrieve. NULL or empty\n\t\t\t\t * means the default system style. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_HashEntry *entryPtr;\n\n    /*\n     * Search for a corresponding entry in the style table.\n     */\n\n    entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name!=NULL?name:\"\"));\n    if (entryPtr == NULL) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"style \\\"%s\\\" does not exist\", name));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"STYLE\", name, (char *)NULL);\n\t}\n\treturn NULL;\n    }\n    return (Tk_Style)Tcl_GetHashValue(entryPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_FreeStyle --\n *\n *\tNo-op. Present only for stubs compatibility.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_FreeStyle(\n    TCL_UNUSED(Tk_Style))\n{\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_AllocStyleFromObj --\n *\n *\tMap the string name of a style to a corresponding Tk_Style. The style\n *\tmust have already been created by Tk_CreateStyle.\n *\n * Results:\n *\tThe return value is a token for the style that matches objPtr, or NULL\n *\tif none found. If NULL is returned, an error message will be left in\n *\tinterp's result object.\n *\n *---------------------------------------------------------------------------\n */\n\nTk_Style\nTk_AllocStyleFromObj(\n    Tcl_Interp *interp,\t\t/* Interp for error return. */\n    Tcl_Obj *objPtr)\t\t/* Object containing name of the style to\n\t\t\t\t * retrieve. */\n{\n    if (objPtr->typePtr != &styleObjType) {\n\tif (SetStyleFromAny(interp, objPtr) != TCL_OK) {\n\t    return NULL;\n\t}\n    }\n    return (Tk_Style)objPtr->internalRep.twoPtrValue.ptr1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetStyleFromAny --\n *\n *\tConvert the internal representation of a Tcl object to the style\n *\tinternal form.\n *\n * Results:\n *\tIf an error occurs is returned (e.g. the style doesn't exist), an\n *\terror message will be left in interp's result and TCL_ERROR is returned.\n *\n * Side effects:\n *\tThe object is left with its typePtr pointing to styleObjType.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetStyleFromAny(\n    Tcl_Interp *interp,\t\t/* Used for error reporting if not NULL. */\n    Tcl_Obj *objPtr)\t\t/* The object to convert. */\n{\n    const Tcl_ObjType *typePtr;\n    const char *name;\n    Tk_Style style;\n\n    /*\n     * Free the old internalRep before setting the new one.\n     */\n\n    name = Tcl_GetString(objPtr);\n    typePtr = objPtr->typePtr;\n    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\ttypePtr->freeIntRepProc(objPtr);\n    }\n\n    style = Tk_GetStyle(interp, name);\n    if (style == NULL) {\n\treturn TCL_ERROR;\n    }\n    objPtr->typePtr = &styleObjType;\n    objPtr->internalRep.twoPtrValue.ptr1 = style;\n\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FreeStyleObjProc --\n *\n *\tThis proc is called to release an object reference to a style. Called\n *\twhen the object's internal rep is released.\n *\n * Results:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFreeStyleObjProc(\n    Tcl_Obj *objPtr)\t\t/* The object we are releasing. */\n{\n    objPtr->internalRep.twoPtrValue.ptr1 = NULL;\n    objPtr->typePtr = NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * DupStyleObjProc --\n *\n *\tWhen a cached style object is duplicated, this is called to update the\n *\tinternal reps.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nDupStyleObjProc(\n    Tcl_Obj *srcObjPtr,\t\t/* The object we are copying from. */\n    Tcl_Obj *dupObjPtr)\t\t/* The object we are copying to. */\n{\n    dupObjPtr->typePtr = srcObjPtr->typePtr;\n    dupObjPtr->internalRep.twoPtrValue.ptr1 =\n\t    srcObjPtr->internalRep.twoPtrValue.ptr1;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTest.c",
    "content": "/*\n * tkTest.c --\n *\n *\tThis file contains C command functions for a bunch of additional Tcl\n *\tcommands that are used for testing out Tcl's C interfaces. These\n *\tcommands are not normally included in Tcl applications; they're only\n *\tused for testing.\n *\n * Copyright © 1993-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#undef STATIC_BUILD\n#ifndef USE_TCL_STUBS\n#   define USE_TCL_STUBS\n#endif\n#ifndef USE_TK_STUBS\n#   define USE_TK_STUBS\n#endif\n#include \"tkInt.h\"\n#include \"tkText.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n#if defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#include \"tkScrollbar.h\"\n#define LOG_DISPLAY(drawable) TkTestLogDisplay(drawable)\n#else\n#define LOG_DISPLAY(drawable) 1\n#endif\n\n#ifdef __UNIX__\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the\n * Tcltest_Init declaration is in the source file itself, which is only\n * accessed when we are building a library.\n */\n\n#undef TCL_STORAGE_CLASS\n#define TCL_STORAGE_CLASS DLLEXPORT\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nEXTERN Tcl_LibraryInitProc Tktest_Init;\n#ifdef __cplusplus\n}\n#endif\n\n/*\n * The following data structure represents the model for a test image:\n */\n\ntypedef struct TImageModel {\n    Tk_ImageModel model;\t/* Tk's token for image model. */\n    Tcl_Interp *interp;\t\t/* Interpreter for application. */\n    int width, height;\t\t/* Dimensions of image. */\n    char *imageName;\t\t/* Name of image (malloc-ed). */\n    char *varName;\t\t/* Name of variable in which to log events for\n\t\t\t\t * image (malloc-ed). */\n} TImageModel;\n\n/*\n * The following data structure represents a particular use of a particular\n * test image.\n */\n\ntypedef struct TImageInstance {\n    TImageModel *modelPtr;\t/* Pointer to model for image. */\n    XColor *fg;\t\t\t/* Foreground color for drawing in image. */\n    GC gc;\t\t\t/* Graphics context for drawing in image. */\n    Bool displayFailed;         /* macOS display attempted out of drawRect. */\n    char buffer[200 + TCL_INTEGER_SPACE * 6]; /* message to log on display. */\n} TImageInstance;\n\n/*\n * The type record for test images:\n */\n\nstatic int\t\tImageCreate(Tcl_Interp *interp,\n\t\t\t    const char *name, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    const Tk_ImageType *typePtr, Tk_ImageModel model,\n\t\t\t    void **clientDataPtr);\nstatic void\t*ImageGet(Tk_Window tkwin, void *clientData);\nstatic void\t\tImageDisplay(void *clientData,\n\t\t\t    Display *display, Drawable drawable,\n\t\t\t    int imageX, int imageY, int width,\n\t\t\t    int height, int drawableX,\n\t\t\t    int drawableY);\nstatic void\t\tImageFree(void *clientData, Display *display);\nstatic void\t\tImageDelete(void *clientData);\n\nstatic Tk_ImageType imageType = {\n    \"test\",\t\t\t/* name */\n    ImageCreate,\t\t/* createProc */\n    ImageGet,\t\t\t/* getProc */\n    ImageDisplay,\t\t/* displayProc */\n    ImageFree,\t\t\t/* freeProc */\n    ImageDelete,\t\t/* deleteProc */\n    NULL,\t\t\t/* postscriptPtr */\n    NULL,\t\t\t/* nextPtr */\n    NULL\n};\n\n/*\n * One of the following structures describes each of the interpreters created\n * by the \"testnewapp\" command. This information is used by the\n * \"testdeleteinterps\" command to destroy all of those interpreters.\n */\n\ntypedef struct NewApp {\n    Tcl_Interp *interp;\t\t/* Token for interpreter. */\n    struct NewApp *nextPtr;\t/* Next in list of new interpreters. */\n} NewApp;\n\nstatic NewApp *newAppPtr = NULL;/* First in list of all new interpreters. */\n\n/*\n * Header for trivial configuration command items.\n */\n\n#define ODD\tTK_CONFIG_USER_BIT\n#define EVEN\t(TK_CONFIG_USER_BIT << 1)\n\nenum {\n    NONE,\n    ODD_TYPE,\n    EVEN_TYPE\n};\n\ntypedef struct TrivialCommandHeader {\n    Tcl_Interp *interp;\t\t/* The interp that this command lives in. */\n    Tk_OptionTable optionTable;\t/* The option table that go with this\n\t\t\t\t * command. */\n    Tk_Window tkwin;\t\t/* For widgets, the window associated with\n\t\t\t\t * this widget. */\n    Tcl_Command widgetCmd;\t/* For widgets, the command associated with\n\t\t\t\t * this widget. */\n} TrivialCommandHeader;\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic Tcl_ObjCmdProc2 ImageObjCmd;\nstatic Tcl_ObjCmdProc2 TestbitmapObjCmd;\nstatic Tcl_ObjCmdProc2 TestborderObjCmd;\nstatic Tcl_ObjCmdProc2 TestcolorObjCmd;\nstatic Tcl_ObjCmdProc2 TestcursorObjCmd;\nstatic Tcl_ObjCmdProc2 TestdeleteappsObjCmd;\nstatic Tcl_ObjCmdProc2 TestfontObjCmd;\nstatic Tcl_ObjCmdProc2 TestmakeexistObjCmd;\n#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))\nstatic Tcl_ObjCmdProc2 TestmenubarObjCmd;\n#endif\n#if defined(_WIN32)\nstatic Tcl_ObjCmdProc2 TestmetricsObjCmd;\n#endif\nstatic Tcl_ObjCmdProc2 TestobjconfigObjCmd;\nstatic Tk_CustomOptionSetProc CustomOptionSet;\nstatic Tk_CustomOptionGetProc CustomOptionGet;\nstatic Tk_CustomOptionRestoreProc CustomOptionRestore;\nstatic Tk_CustomOptionFreeProc CustomOptionFree;\nstatic Tcl_ObjCmdProc2 TestpropObjCmd;\nstatic Tcl_ObjCmdProc2 TestprintfObjCmd;\n#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))\nstatic Tcl_ObjCmdProc2 TestwrapperObjCmd;\n#endif\nstatic void\t\tTrivialCmdDeletedProc(void *clientData);\nstatic Tcl_ObjCmdProc2 TrivialConfigObjCmd;\nstatic void\t\tTrivialEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_ObjCmdProc2 TestPhotoStringMatchCmd;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tktest_Init --\n *\n *\tThis function performs initialization for the Tk test suite extensions.\n *\n * Results:\n *\tReturns a standard Tcl completion code, and leaves an error message in\n *\tthe interp's result if an error occurs.\n *\n * Side effects:\n *\tCreates several test commands.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTktest_Init(\n    Tcl_Interp *interp)\t\t/* Interpreter for application. */\n{\n    static bool initialized = false;\n\n    if (Tcl_InitStubs(interp, \"9.0\", 0) == NULL) {\n\treturn TCL_ERROR;\n    }\n    if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create additional commands for testing Tk.\n     */\n\n    if (Tcl_PkgProvideEx(interp, \"tk::test\", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    Tcl_CreateObjCommand2(interp, \"square\", SquareObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"testbitmap\", TestbitmapObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testborder\", TestborderObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testcolor\", TestcolorObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testcursor\", TestcursorObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testdeleteapps\", TestdeleteappsObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testembed\", TkpTestembedCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testobjconfig\", TestobjconfigObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testfont\", TestfontObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testmakeexist\", TestmakeexistObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testprop\", TestpropObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testprintf\", TestprintfObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"testtext\", TkpTesttextCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testphotostringmatch\",\n\t    TestPhotoStringMatchCmd, Tk_MainWindow(interp),\n\t    NULL);\n\n#if defined(_WIN32)\n    Tcl_CreateObjCommand2(interp, \"testmetrics\", TestmetricsObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n#elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK)\n    Tcl_CreateObjCommand2(interp, \"testmenubar\", TestmenubarObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testsend\", TkpTestsendCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testwrapper\", TestwrapperObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n#endif /* _WIN32 */\n\n    /*\n     * Create test image type.\n     */\n\n    if (!initialized) {\n\tinitialized = true;\n\tTk_CreateImageType(&imageType);\n    }\n\n    /*\n     * And finally add any platform specific test commands.\n     */\n\n    return TkplatformtestInit(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestbitmapObjCmd --\n *\n *\tThis function implements the \"testbitmap\" command, which is used to\n *\ttest color resource handling in tkBitmap tmp.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestbitmapObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"bitmap\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1])));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestborderObjCmd --\n *\n *\tThis function implements the \"testborder\" command, which is used to\n *\ttest color resource handling in tkBorder.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestborderObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"border\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1])));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestcolorObjCmd --\n *\n *\tThis function implements the \"testcolor\" command, which is used to\n *\ttest color resource handling in tkColor.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestcolorObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"color\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, TkDebugColor(Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1])));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestcursorObjCmd --\n *\n *\tThis function implements the \"testcursor\" command, which is used to\n *\ttest color resource handling in tkCursor.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestcursorObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"cursor\");\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, TkDebugCursor(Tk_MainWindow(interp),\n\t    Tcl_GetString(objv[1])));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestdeleteappsObjCmd --\n *\n *\tThis function implements the \"testdeleteapps\" command. It cleans up\n *\tall the interpreters left behind by the \"testnewapp\" command.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tAll the interpreters created by previous calls to \"testnewapp\" get\n *\tdeleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestdeleteappsObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t\t/* Argument strings. */\n{\n    NewApp *nextPtr;\n\n    while (newAppPtr != NULL) {\n\tnextPtr = newAppPtr->nextPtr;\n\tTcl_DeleteInterp(newAppPtr->interp);\n\tTcl_Free(newAppPtr);\n\tnewAppPtr = nextPtr;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestobjconfigObjCmd --\n *\n *\tThis function implements the \"testobjconfig\" command, which is used to\n *\ttest the functions in tkConfig.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestobjconfigObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const options[] = {\n\t\"alltypes\", \"chain1\", \"chain2\", \"chain3\", \"configerror\", \"delete\", \"info\",\n\t\"internal\", \"new\", \"notenoughparams\", \"twowindows\", NULL\n    };\n    enum {\n\tALL_TYPES, CHAIN1, CHAIN2, CHAIN3, CONFIG_ERROR,\n\tDEL,\t\t\t/* Can't use DELETE: VC++ compiler barfs. */\n\tINFO, INTERNAL, NEW, NOT_ENOUGH_PARAMS, TWO_WINDOWS\n    };\n    static Tk_OptionTable tables[11];\n\t\t\t\t/* Holds pointers to option tables created by\n\t\t\t\t * commands below; indexed with same values as\n\t\t\t\t * \"options\" array. */\n    static const Tk_ObjCustomOption CustomOption = {\n\t\"custom option\",\n\tCustomOptionSet,\n\tCustomOptionGet,\n\tCustomOptionRestore,\n\tCustomOptionFree,\n\tINT2PTR(1)\n    };\n    Tk_Window mainWin = (Tk_Window)clientData;\n    Tk_Window tkwin;\n    int index, result = TCL_OK;\n\n    /*\n     * Structures used by the \"chain1\" subcommand and also shared by the\n     * \"chain2\" subcommand:\n     */\n\n    typedef struct {\n\tTrivialCommandHeader header;\n\tTcl_Obj *base1ObjPtr;\n\tTcl_Obj *base2ObjPtr;\n\tTcl_Obj *extension3ObjPtr;\n\tTcl_Obj *extension4ObjPtr;\n\tTcl_Obj *extension5ObjPtr;\n    } ExtensionWidgetRecord;\n    static const Tk_OptionSpec baseSpecs[] = {\n\t{TK_OPTION_STRING, \"-one\", \"one\", \"One\", \"one\",\n\t\toffsetof(ExtensionWidgetRecord, base1ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t{TK_OPTION_STRING, \"-two\", \"two\", \"Two\", \"two\",\n\t\toffsetof(ExtensionWidgetRecord, base2ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"command\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"command\", 0, &index)!= TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch (index) {\n    case ALL_TYPES: {\n\ttypedef struct {\n\t    TrivialCommandHeader header;\n\t    Tcl_Obj *booleanPtr;\n\t    Tcl_Obj *integerPtr;\n\t    Tcl_Obj *doublePtr;\n\t    Tcl_Obj *stringPtr;\n\t    Tcl_Obj *stringTablePtr;\n\t    Tcl_Obj *stringTablePtr2;\n\t    Tcl_Obj *colorPtr;\n\t    Tcl_Obj *fontPtr;\n\t    Tcl_Obj *bitmapPtr;\n\t    Tcl_Obj *borderPtr;\n\t    Tcl_Obj *reliefPtr;\n\t    Tcl_Obj *cursorPtr;\n\t    Tcl_Obj *activeCursorPtr;\n\t    Tcl_Obj *justifyPtr;\n\t    Tcl_Obj *anchorPtr;\n\t    Tcl_Obj *pixelPtr;\n\t    Tcl_Obj *mmPtr;\n\t    Tcl_Obj *customPtr;\n\t} TypesRecord;\n\tTypesRecord *recordPtr;\n\tstatic const char *const stringTable[] = {\n\t    \"one\", \"two\", \"three\", \"four\", NULL\n\t};\n\tstatic const char *const stringTable2[] = {\n\t    \"one\", \"two\", NULL\n\t};\n\tstatic const Tk_OptionSpec typesSpecs[] = {\n\t    {TK_OPTION_BOOLEAN, \"-boolean\", \"boolean\", \"Boolean\", NULL,\n\t\toffsetof(TypesRecord, booleanPtr), TCL_INDEX_NONE, TK_CONFIG_NULL_OK, 0, 0x1},\n\t    {TK_OPTION_INT, \"-integer\", \"integer\", \"Integer\", \"7\",\n\t\toffsetof(TypesRecord, integerPtr), TCL_INDEX_NONE, 0, 0, 0x2},\n\t    {TK_OPTION_DOUBLE, \"-double\", \"double\", \"Double\", \"3.14159\",\n\t\toffsetof(TypesRecord, doublePtr), TCL_INDEX_NONE, 0, 0, 0x4},\n\t    {TK_OPTION_STRING, \"-string\", \"string\", \"String\",\n\t\t\"foo\", offsetof(TypesRecord, stringPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x8},\n\t    {TK_OPTION_STRING_TABLE,\n\t\t\"-stringtable\", \"StringTable\", \"stringTable\",\n\t\t\"one\", offsetof(TypesRecord, stringTablePtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, stringTable, 0x10},\n\t    {TK_OPTION_STRING_TABLE,\n\t\t\"-stringtable2\", \"StringTable2\", \"stringTable2\",\n\t\t\"two\", offsetof(TypesRecord, stringTablePtr2), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, stringTable2, 0x10},\n\t    {TK_OPTION_COLOR, \"-color\", \"color\", \"Color\",\n\t\t\"red\", offsetof(TypesRecord, colorPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, \"black\", 0x20},\n\t    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\", \"Helvetica 12\",\n\t\toffsetof(TypesRecord, fontPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x40},\n\t    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\", \"gray50\",\n\t\toffsetof(TypesRecord, bitmapPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x80},\n\t    {TK_OPTION_BORDER, \"-border\", \"border\", \"Border\",\n\t\t\"blue\", offsetof(TypesRecord, borderPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, \"white\", 0x100},\n\t    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\", NULL,\n\t\toffsetof(TypesRecord, reliefPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x200},\n\t    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\", \"xterm\",\n\t\toffsetof(TypesRecord, cursorPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x400},\n\t    {TK_OPTION_JUSTIFY, \"-justify\", NULL, NULL, \"left\",\n\t\toffsetof(TypesRecord, justifyPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x800},\n\t    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\", \"center\",\n\t\toffsetof(TypesRecord, anchorPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x1000},\n\t    {TK_OPTION_PIXELS, \"-pixel\", \"pixel\", \"Pixel\",\n\t\t\"1\", offsetof(TypesRecord, pixelPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, 0, 0x2000},\n\t    {TK_OPTION_CUSTOM, \"-custom\", NULL, NULL,\n\t\t\"\", offsetof(TypesRecord, customPtr), TCL_INDEX_NONE,\n\t\tTK_CONFIG_NULL_OK, &CustomOption, 0x4000},\n\t    {TK_OPTION_SYNONYM, \"-synonym\", NULL, NULL,\n\t\tNULL, 0, TCL_INDEX_NONE, 0, \"-color\", 0x8000},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\tTk_OptionTable optionTable;\n\n\toptionTable = Tk_CreateOptionTable(interp, typesSpecs);\n\ttables[index] = optionTable;\n\ttkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,\n\t\tTcl_GetString(objv[2]), NULL);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_SetClass(tkwin, \"Test\");\n\n\trecordPtr = (TypesRecord *)Tcl_Alloc(sizeof(TypesRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = optionTable;\n\trecordPtr->header.tkwin = tkwin;\n\trecordPtr->booleanPtr = NULL;\n\trecordPtr->integerPtr = NULL;\n\trecordPtr->doublePtr = NULL;\n\trecordPtr->stringPtr = NULL;\n\trecordPtr->colorPtr = NULL;\n\trecordPtr->fontPtr = NULL;\n\trecordPtr->bitmapPtr = NULL;\n\trecordPtr->borderPtr = NULL;\n\trecordPtr->reliefPtr = NULL;\n\trecordPtr->cursorPtr = NULL;\n\trecordPtr->justifyPtr = NULL;\n\trecordPtr->anchorPtr = NULL;\n\trecordPtr->pixelPtr = NULL;\n\trecordPtr->mmPtr = NULL;\n\trecordPtr->stringTablePtr = NULL;\n\trecordPtr->stringTablePtr2 = NULL;\n\trecordPtr->customPtr = NULL;\n\tresult = Tk_InitOptions(interp, recordPtr, optionTable,\n\t\ttkwin);\n\tif (result == TCL_OK) {\n\t    recordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t    Tcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t    recordPtr, TrivialCmdDeletedProc);\n\t    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t    TrivialEventProc, recordPtr);\n\t    result = Tk_SetOptions(interp, recordPtr, optionTable,\n\t\t    objc-3, objv+3, tkwin, NULL, NULL);\n\t    if (result != TCL_OK) {\n\t\tTk_DestroyWindow(tkwin);\n\t    }\n\t} else {\n\t    Tk_DestroyWindow(tkwin);\n\t    Tcl_Free(recordPtr);\n\t}\n\tif (result == TCL_OK) {\n\t    Tcl_SetObjResult(interp, objv[2]);\n\t}\n\tbreak;\n    }\n\n    case CHAIN1: {\n\tExtensionWidgetRecord *recordPtr;\n\tTk_OptionTable optionTable;\n\n\ttkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,\n\t\tTcl_GetString(objv[2]), NULL);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_SetClass(tkwin, \"Test\");\n\toptionTable = Tk_CreateOptionTable(interp, baseSpecs);\n\ttables[index] = optionTable;\n\n\trecordPtr = (ExtensionWidgetRecord *)Tcl_Alloc(sizeof(ExtensionWidgetRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = optionTable;\n\trecordPtr->header.tkwin = tkwin;\n\trecordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;\n\trecordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;\n\tresult = Tk_InitOptions(interp, recordPtr, optionTable, tkwin);\n\tif (result == TCL_OK) {\n\t    result = Tk_SetOptions(interp, recordPtr, optionTable,\n\t\t    objc-3, objv+3, tkwin, NULL, NULL);\n\t    if (result != TCL_OK) {\n\t\tTk_FreeConfigOptions(recordPtr, optionTable, tkwin);\n\t    }\n\t}\n\tif (result == TCL_OK) {\n\t    recordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t    Tcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t    recordPtr, TrivialCmdDeletedProc);\n\t    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t    TrivialEventProc, recordPtr);\n\t    Tcl_SetObjResult(interp, objv[2]);\n\t}\n\tbreak;\n    }\n\n    case CHAIN2:\n    case CHAIN3: {\n\tExtensionWidgetRecord *recordPtr;\n\tstatic const Tk_OptionSpec extensionSpecs[] = {\n\t    {TK_OPTION_STRING, \"-three\", \"three\", \"Three\", \"three\",\n\t\toffsetof(ExtensionWidgetRecord, extension3ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_STRING, \"-four\", \"four\", \"Four\", \"four\",\n\t\toffsetof(ExtensionWidgetRecord, extension4ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_STRING, \"-two\", \"two\", \"Two\", \"two and a half\",\n\t\toffsetof(ExtensionWidgetRecord, base2ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_STRING,\n\t\t\"-oneAgain\", \"oneAgain\", \"OneAgain\", \"one again\",\n\t\toffsetof(ExtensionWidgetRecord, extension5ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,\n\t\tbaseSpecs, 0}\n\t};\n\tTk_OptionTable optionTable;\n\n\ttkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,\n\t\tTcl_GetString(objv[2]), NULL);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_SetClass(tkwin, \"Test\");\n\toptionTable = Tk_CreateOptionTable(interp, extensionSpecs);\n\ttables[index] = optionTable;\n\n\trecordPtr = (ExtensionWidgetRecord *)Tcl_Alloc(sizeof(ExtensionWidgetRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = optionTable;\n\trecordPtr->header.tkwin = tkwin;\n\trecordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;\n\trecordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;\n\trecordPtr->extension5ObjPtr = NULL;\n\tresult = Tk_InitOptions(interp, recordPtr, optionTable, tkwin);\n\tif (result == TCL_OK) {\n\t    result = Tk_SetOptions(interp, recordPtr, optionTable,\n\t\t    objc-3, objv+3, tkwin, NULL, NULL);\n\t    if (result != TCL_OK) {\n\t\tTk_FreeConfigOptions(recordPtr, optionTable, tkwin);\n\t    }\n\t}\n\tif (result == TCL_OK) {\n\t    recordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t    Tcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t    recordPtr, TrivialCmdDeletedProc);\n\t    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t    TrivialEventProc, recordPtr);\n\t    Tcl_SetObjResult(interp, objv[2]);\n\t}\n\tbreak;\n    }\n\n    case CONFIG_ERROR: {\n\ttypedef struct {\n\t    Tcl_Obj *intPtr;\n\t} ErrorWidgetRecord;\n\tErrorWidgetRecord widgetRecord;\n\tstatic const Tk_OptionSpec errorSpecs[] = {\n\t    {TK_OPTION_INT, \"-int\", \"integer\", \"Integer\", \"bogus\",\n\t\toffsetof(ErrorWidgetRecord, intPtr), 0, TK_OPTION_NULL_OK, NULL, 0},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\tTk_OptionTable optionTable;\n\n\twidgetRecord.intPtr = NULL;\n\toptionTable = Tk_CreateOptionTable(interp, errorSpecs);\n\ttables[index] = optionTable;\n\treturn Tk_InitOptions(interp, &widgetRecord, optionTable,\n\t\t(Tk_Window) NULL);\n    }\n\n    case DEL:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tableName\");\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[2], options,\n\t\tsizeof(char *), \"table\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (tables[index] != NULL) {\n\t    Tk_DeleteOptionTable(tables[index]);\n\t    /* Make sure that Tk_DeleteOptionTable() is never done\n\t     * twice for the same table. */\n\t    tables[index] = NULL;\n\t}\n\tbreak;\n\n    case INFO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"tableName\");\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[2], options,\n\t\tsizeof(char *), \"table\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, TkDebugConfig(interp, tables[index]));\n\tbreak;\n\n    case INTERNAL: {\n\t/*\n\t * This command is similar to the \"alltypes\" command except that it\n\t * stores all the configuration options as internal forms instead of\n\t * objects.\n\t */\n\n\ttypedef struct {\n\t    TrivialCommandHeader header;\n\t    int boolValue;\n\t    int integer;\n\t    double doubleValue;\n\t    char *string;\n\t    int index;\n\t    XColor *colorPtr;\n\t    Tk_Font tkfont;\n\t    Pixmap bitmap;\n\t    Tk_3DBorder border;\n\t    int relief;\n\t    Tk_Cursor cursor;\n\t    Tk_Justify justify;\n\t    Tk_Anchor anchor;\n\t    int pixels;\n\t    double mm;\n\t    Tk_Window tkwin;\n\t    char *custom;\n\t} InternalRecord;\n\tInternalRecord *recordPtr;\n\tstatic const char *const internalStringTable[] = {\n\t    \"one\", \"two\", \"three\", \"four\", NULL\n\t};\n\tstatic const Tk_OptionSpec internalSpecs[] = {\n\t    {TK_OPTION_BOOLEAN, \"-boolean\", \"boolean\", \"Boolean\", \"1\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, boolValue), TK_CONFIG_NULL_OK, 0, 0x1},\n\t    {TK_OPTION_INT, \"-integer\", \"integer\", \"Integer\", \"148962237\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, integer), 0, 0, 0x2},\n\t    {TK_OPTION_DOUBLE, \"-double\", \"double\", \"Double\", \"3.14159\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, doubleValue), 0, 0, 0x4},\n\t    {TK_OPTION_STRING, \"-string\", \"string\", \"String\", \"foo\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, string),\n\t\tTK_CONFIG_NULL_OK, 0, 0x8},\n\t    {TK_OPTION_STRING_TABLE,\n\t\t\"-stringtable\", \"StringTable\", \"stringTable\", \"one\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, index),\n\t\tTK_CONFIG_NULL_OK, internalStringTable, 0x10},\n\t    {TK_OPTION_COLOR, \"-color\", \"color\", \"Color\", \"red\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, colorPtr),\n\t\tTK_CONFIG_NULL_OK, \"black\", 0x20},\n\t    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\", \"Helvetica 12\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, tkfont),\n\t\tTK_CONFIG_NULL_OK, 0, 0x40},\n\t    {TK_OPTION_BITMAP, \"-bitmap\", \"bitmap\", \"Bitmap\", \"gray50\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, bitmap),\n\t\tTK_CONFIG_NULL_OK, 0, 0x80},\n\t    {TK_OPTION_BORDER, \"-border\", \"border\", \"Border\", \"blue\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, border),\n\t\tTK_CONFIG_NULL_OK, \"white\", 0x100},\n\t    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\", NULL,\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, relief),\n\t\tTK_CONFIG_NULL_OK, 0, 0x200},\n\t    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\", \"xterm\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, cursor),\n\t\tTK_CONFIG_NULL_OK, 0, 0x400},\n\t    {TK_OPTION_JUSTIFY, \"-justify\", NULL, NULL, \"left\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, justify),\n\t\tTK_CONFIG_NULL_OK|TK_OPTION_ENUM_VAR, 0, 0x800},\n\t    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\", \"center\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, anchor),\n\t\tTK_CONFIG_NULL_OK|TK_OPTION_ENUM_VAR, 0, 0x1000},\n\t    {TK_OPTION_PIXELS, \"-pixel\", \"pixel\", \"Pixel\", \"1\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, pixels),\n\t\tTK_CONFIG_NULL_OK, 0, 0x2000},\n\t    {TK_OPTION_WINDOW, \"-window\", \"window\", \"Window\", NULL,\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, tkwin),\n\t\tTK_CONFIG_NULL_OK, 0, 0},\n\t    {TK_OPTION_CUSTOM, \"-custom\", NULL, NULL, \"\",\n\t\tTCL_INDEX_NONE, offsetof(InternalRecord, custom),\n\t\tTK_CONFIG_NULL_OK, &CustomOption, 0x4000},\n\t    {TK_OPTION_SYNONYM, \"-synonym\", NULL, NULL,\n\t\tNULL, TCL_INDEX_NONE, TCL_INDEX_NONE, 0, \"-color\", 0x8000},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\tTk_OptionTable optionTable;\n\n\toptionTable = Tk_CreateOptionTable(interp, internalSpecs);\n\ttables[index] = optionTable;\n\ttkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,\n\t\tTcl_GetString(objv[2]), NULL);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_SetClass(tkwin, \"Test\");\n\n\trecordPtr = (InternalRecord *)Tcl_Alloc(sizeof(InternalRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = optionTable;\n\trecordPtr->header.tkwin = tkwin;\n\trecordPtr->boolValue = 0;\n\trecordPtr->integer = 0;\n\trecordPtr->doubleValue = 0.0;\n\trecordPtr->string = NULL;\n\trecordPtr->index = 0;\n\trecordPtr->colorPtr = NULL;\n\trecordPtr->tkfont = NULL;\n\trecordPtr->bitmap = None;\n\trecordPtr->border = NULL;\n\trecordPtr->relief = TK_RELIEF_FLAT;\n\trecordPtr->cursor = NULL;\n\trecordPtr->justify = TK_JUSTIFY_LEFT;\n\trecordPtr->anchor = TK_ANCHOR_CENTER;\n\trecordPtr->pixels = 0;\n\trecordPtr->mm = 0.0;\n\trecordPtr->tkwin = NULL;\n\trecordPtr->custom = NULL;\n\tresult = Tk_InitOptions(interp, recordPtr, optionTable,\n\t\ttkwin);\n\tif (result == TCL_OK) {\n\t    recordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t    Tcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t    recordPtr, TrivialCmdDeletedProc);\n\t    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t    TrivialEventProc, recordPtr);\n\t    result = Tk_SetOptions(interp, recordPtr, optionTable,\n\t\t    objc - 3, objv + 3, tkwin, NULL, NULL);\n\t    if (result != TCL_OK) {\n\t\tTk_DestroyWindow(tkwin);\n\t    }\n\t} else {\n\t    Tk_DestroyWindow(tkwin);\n\t    Tcl_Free(recordPtr);\n\t}\n\tif (result == TCL_OK) {\n\t    Tcl_SetObjResult(interp, objv[2]);\n\t}\n\tbreak;\n    }\n\n    case NEW: {\n\ttypedef struct {\n\t    TrivialCommandHeader header;\n\t    Tcl_Obj *one;\n\t    Tcl_Obj *two;\n\t    Tcl_Obj *three;\n\t    Tcl_Obj *four;\n\t    Tcl_Obj *five;\n\t} FiveRecord;\n\tFiveRecord *recordPtr;\n\tstatic const Tk_OptionSpec smallSpecs[] = {\n\t    {TK_OPTION_INT, \"-one\", \"one\", \"One\", \"1\",\n\t\toffsetof(FiveRecord, one), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_INT, \"-two\", \"two\", \"Two\", \"2\",\n\t\toffsetof(FiveRecord, two), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_INT, \"-three\", \"three\", \"Three\", \"3\",\n\t\toffsetof(FiveRecord, three), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_INT, \"-four\", \"four\", \"Four\", \"4\",\n\t\toffsetof(FiveRecord, four), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_STRING, \"-five\", NULL, NULL, NULL,\n\t\toffsetof(FiveRecord, five), TCL_INDEX_NONE, 0, NULL, 0},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"new name ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\n\trecordPtr = (FiveRecord *)Tcl_Alloc(sizeof(FiveRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = Tk_CreateOptionTable(interp,\n\t\tsmallSpecs);\n\ttables[index] = recordPtr->header.optionTable;\n\trecordPtr->header.tkwin = NULL;\n\trecordPtr->one = recordPtr->two = recordPtr->three = NULL;\n\trecordPtr->four = recordPtr->five = NULL;\n\tTcl_SetObjResult(interp, objv[2]);\n\tresult = Tk_InitOptions(interp, recordPtr,\n\t\trecordPtr->header.optionTable, (Tk_Window) NULL);\n\tif (result == TCL_OK) {\n\t    result = Tk_SetOptions(interp, recordPtr,\n\t\t    recordPtr->header.optionTable, objc - 3, objv + 3,\n\t\t    (Tk_Window) NULL, NULL, NULL);\n\t    if (result == TCL_OK) {\n\t\trecordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t\tTcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t\trecordPtr, TrivialCmdDeletedProc);\n\t    } else {\n\t\tTk_FreeConfigOptions(recordPtr,\n\t\t\trecordPtr->header.optionTable, (Tk_Window) NULL);\n\t    }\n\t}\n\tif (result != TCL_OK) {\n\t    Tcl_Free(recordPtr);\n\t}\n\n\tbreak;\n    }\n    case NOT_ENOUGH_PARAMS: {\n\ttypedef struct {\n\t    Tcl_Obj *fooObjPtr;\n\t} NotEnoughRecord;\n\tNotEnoughRecord record;\n\tstatic const Tk_OptionSpec errorSpecs[] = {\n\t    {TK_OPTION_INT, \"-foo\", \"foo\", \"Foo\", \"0\",\n\t\toffsetof(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\tTcl_Obj *newObjPtr = Tcl_NewStringObj(\"-foo\", TCL_INDEX_NONE);\n\tTk_OptionTable optionTable;\n\n\trecord.fooObjPtr = NULL;\n\n\ttkwin = Tk_CreateWindowFromPath(interp, mainWin, \".config\", NULL);\n\tTk_SetClass(tkwin, \"Config\");\n\toptionTable = Tk_CreateOptionTable(interp, errorSpecs);\n\ttables[index] = optionTable;\n\tTk_InitOptions(interp, &record, optionTable, tkwin);\n\tif (Tk_SetOptions(interp, &record, optionTable, 1,\n\t\t&newObjPtr, tkwin, NULL, NULL) != TCL_OK) {\n\t    result = TCL_ERROR;\n\t}\n\tTcl_DecrRefCount(newObjPtr);\n\tTk_FreeConfigOptions( (char *) &record, optionTable, tkwin);\n\tTk_DestroyWindow(tkwin);\n\treturn result;\n    }\n\n    case TWO_WINDOWS: {\n\ttypedef struct {\n\t    TrivialCommandHeader header;\n\t    Tcl_Obj *windowPtr;\n\t} ContentRecord;\n\tContentRecord *recordPtr;\n\tstatic const Tk_OptionSpec contentSpecs[] = {\n\t    {TK_OPTION_WINDOW, \"-window\", \"window\", \"Window\", \".bar\",\n\t\toffsetof(ContentRecord, windowPtr), TCL_INDEX_NONE, TK_CONFIG_NULL_OK, NULL, 0},\n\t    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}\n\t};\n\ttkwin = Tk_CreateWindowFromPath(interp,\n\t\t(Tk_Window)clientData, Tcl_GetString(objv[2]), NULL);\n\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_SetClass(tkwin, \"Test\");\n\n\trecordPtr = (ContentRecord *)Tcl_Alloc(sizeof(ContentRecord));\n\trecordPtr->header.interp = interp;\n\trecordPtr->header.optionTable = Tk_CreateOptionTable(interp,\n\t\tcontentSpecs);\n\ttables[index] = recordPtr->header.optionTable;\n\trecordPtr->header.tkwin = tkwin;\n\trecordPtr->windowPtr = NULL;\n\n\tresult = Tk_InitOptions(interp, recordPtr,\n\t\trecordPtr->header.optionTable, tkwin);\n\tif (result == TCL_OK) {\n\t    result = Tk_SetOptions(interp, recordPtr,\n\t\t    recordPtr->header.optionTable, objc - 3, objv + 3,\n\t\t    tkwin, NULL, NULL);\n\t    if (result == TCL_OK) {\n\t\trecordPtr->header.widgetCmd = Tcl_CreateObjCommand2(interp,\n\t\t\tTcl_GetString(objv[2]), TrivialConfigObjCmd,\n\t\t\trecordPtr, TrivialCmdDeletedProc);\n\t\tTk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t\tTrivialEventProc, recordPtr);\n\t\tTcl_SetObjResult(interp, objv[2]);\n\t    } else {\n\t\tTk_FreeConfigOptions(recordPtr,\n\t\t\trecordPtr->header.optionTable, tkwin);\n\t    }\n\t}\n\tif (result != TCL_OK) {\n\t    Tk_DestroyWindow(tkwin);\n\t    Tcl_Free(recordPtr);\n\t}\n    }\n    }\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrivialConfigObjCmd --\n *\n *\tThis command is used to test the configuration package. It only\n *\thandles the \"configure\" and \"cget\" subcommands.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTrivialConfigObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int result = TCL_OK;\n    static const char *const options[] = {\n\t\"cget\", \"configure\", \"csave\", NULL\n    };\n    enum {\n\tCGET, CONFIGURE, CSAVE\n    };\n    Tcl_Obj *resultObjPtr;\n    int index, mask;\n    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;\n    Tk_Window tkwin = headerPtr->tkwin;\n    Tk_SavedOptions saved;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"command\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    Tcl_Preserve(clientData);\n\n    switch (index) {\n    case CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tresultObjPtr = Tk_GetOptionValue(interp, clientData,\n\t\theaderPtr->optionTable, objv[2], tkwin);\n\tif (resultObjPtr != NULL) {\n\t    Tcl_SetObjResult(interp, resultObjPtr);\n\t    result = TCL_OK;\n\t} else {\n\t    result = TCL_ERROR;\n\t}\n\tbreak;\n    case CONFIGURE:\n\tif (objc == 2) {\n\t    resultObjPtr = Tk_GetOptionInfo(interp, clientData,\n\t\t    headerPtr->optionTable, NULL, tkwin);\n\t    if (resultObjPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, resultObjPtr);\n\t    }\n\t} else if (objc == 3) {\n\t    resultObjPtr = Tk_GetOptionInfo(interp, clientData,\n\t\t    headerPtr->optionTable, objv[2], tkwin);\n\t    if (resultObjPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, resultObjPtr);\n\t    }\n\t} else {\n\t    result = Tk_SetOptions(interp, clientData,\n\t\t    headerPtr->optionTable, objc - 2, objv + 2,\n\t\t    tkwin, NULL, &mask);\n\t    if (result == TCL_OK) {\n\t\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(mask));\n\t    }\n\t}\n\tbreak;\n    case CSAVE:\n\tresult = Tk_SetOptions(interp, clientData,\n\t\theaderPtr->optionTable, objc - 2, objv + 2,\n\t\ttkwin, &saved, &mask);\n\tTk_FreeSavedOptions(&saved);\n\tif (result == TCL_OK) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(mask));\n\t}\n\tbreak;\n    }\n  done:\n    Tcl_Release(clientData);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrivialCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrivialCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;\n    Tk_Window tkwin = headerPtr->tkwin;\n\n    if (tkwin != NULL) {\n\tTk_DestroyWindow(tkwin);\n    } else if (headerPtr->optionTable != NULL) {\n\t/*\n\t * This is a \"new\" object, which doesn't have a window, so we can't\n\t * depend on cleaning up in the event function. Free its resources\n\t * here.\n\t */\n\n\tTk_FreeConfigOptions(clientData,\n\t\theaderPtr->optionTable, NULL);\n\tTcl_EventuallyFree(clientData, TCL_DYNAMIC);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TrivialEventProc --\n *\n *\tA dummy event proc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTrivialEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tif (headerPtr->tkwin != NULL) {\n\t    Tk_FreeConfigOptions(clientData,\n\t\t    headerPtr->optionTable, headerPtr->tkwin);\n\t    headerPtr->optionTable = NULL;\n\t    headerPtr->tkwin = NULL;\n\t    Tcl_DeleteCommandFromToken(headerPtr->interp,\n\t\t    headerPtr->widgetCmd);\n\t}\n\tTcl_EventuallyFree(clientData, TCL_DYNAMIC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestfontObjCmd --\n *\n *\tThis function implements the \"testfont\" command, which is used to test\n *\tTkFont objects.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestfontObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const options[] = {\"counts\", \"subfonts\", NULL};\n    enum option {COUNTS, SUBFONTS};\n    int index;\n    Tk_Window tkwin;\n    Tk_Font tkfont;\n\n    tkwin = (Tk_Window)clientData;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option fontName\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"command\", 0, &index)!= TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum option) index) {\n    case COUNTS:\n\tTcl_SetObjResult(interp,\n\t\tTkDebugFont(Tk_MainWindow(interp), Tcl_GetString(objv[2])));\n\tbreak;\n    case SUBFONTS:\n\ttkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);\n\tif (tkfont == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTkpGetSubFonts(interp, tkfont);\n\tTk_FreeFont(tkfont);\n\tbreak;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageCreate --\n *\n *\tThis function is called by the Tk image code to create \"test\" images.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe data structure for a new image is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImageCreate(\n    Tcl_Interp *interp,\t\t/* Interpreter for application containing\n\t\t\t\t * image. */\n    const char *name,\t\t\t/* Name to use for image. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument strings for options (doesn't\n\t\t\t\t * include image name or type). */\n    TCL_UNUSED(const Tk_ImageType *),\t/* Pointer to our type record (not used). */\n\tTk_ImageModel model,\t/* Token for image, to be used by us in later\n\t\t\t\t * callbacks. */\n    void **clientDataPtr)\t/* Store manager's token for image here; it\n\t\t\t\t * will be returned in later callbacks. */\n{\n    TImageModel *timPtr;\n    const char *varName;\n    Tcl_Size i;\n\n    varName = \"log\";\n    for (i = 0; i < objc; i += 2) {\n\tif (strcmp(Tcl_GetString(objv[i]), \"-variable\") != 0) {\n\t    Tcl_AppendResult(interp, \"bad option name \\\"\",\n\t\t    Tcl_GetString(objv[i]), \"\\\"\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif ((i+1) == objc) {\n\t    Tcl_AppendResult(interp, \"no value given for \\\"\",\n\t\t    Tcl_GetString(objv[i]), \"\\\" option\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tvarName = Tcl_GetString(objv[i+1]);\n    }\n\n    timPtr = (TImageModel *)Tcl_Alloc(sizeof(TImageModel));\n    timPtr->model = model;\n    timPtr->interp = interp;\n    timPtr->width = 30;\n    timPtr->height = 15;\n    timPtr->imageName = (char *)Tcl_Alloc(strlen(name) + 1);\n    strcpy(timPtr->imageName, name);\n    timPtr->varName = (char *)Tcl_Alloc(strlen(varName) + 1);\n    strcpy(timPtr->varName, varName);\n    Tcl_CreateObjCommand2(interp, name, ImageObjCmd, timPtr, NULL);\n    *clientDataPtr = timPtr;\n    Tk_ImageChanged(model, 0, 0, 30, 15, 30, 15);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageObjCmd --\n *\n *\tThis function implements the commands corresponding to individual\n *\timages.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tForces windows to be created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImageObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    TImageModel *timPtr = (TImageModel *)clientData;\n    int x, y, width, height;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (strcmp(Tcl_GetString(objv[1]), \"changed\") == 0) {\n\tif (objc != 8) {\n\t\tTcl_WrongNumArgs(interp, 1, objv, \"changed x y width height\"\n\t\t\t\" imageWidth imageHeight\");\n\t    return TCL_ERROR;\n\t}\n\tif ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tTk_ImageChanged(timPtr->model, x, y, width, height, timPtr->width,\n\t\ttimPtr->height);\n    } else {\n\tTcl_AppendResult(interp, \"bad option \\\"\", Tcl_GetString(objv[1]),\n\t\t\"\\\": must be changed\", NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageGet --\n *\n *\tThis function is called by Tk to set things up for using a test image\n *\tin a particular widget.\n *\n * Results:\n *\tThe return value is a token for the image instance, which is used in\n *\tfuture callbacks to ImageDisplay and ImageFree.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void *\nImageGet(\n    Tk_Window tkwin,\t\t/* Token for window in which image will be\n\t\t\t\t * used. */\n    void *clientData)\t/* Pointer to TImageModel for image. */\n{\n    TImageModel *timPtr = (TImageModel *)clientData;\n    TImageInstance *instPtr;\n    char buffer[100];\n    XGCValues gcValues;\n\n    snprintf(buffer, sizeof(buffer), \"%s get\", timPtr->imageName);\n    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,\n\t    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);\n\n    instPtr = (TImageInstance *)Tcl_Alloc(sizeof(TImageInstance));\n    instPtr->modelPtr = timPtr;\n    instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, \"#ff0000\");\n    gcValues.foreground = instPtr->fg->pixel;\n    instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    instPtr->displayFailed = False;\n    return instPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageDisplay --\n *\n *\tThis function is invoked to redisplay part or all of an image in a\n *\tgiven drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image gets partially redrawn, as an \"X\" that shows the exact\n *\tredraw area.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageDisplay(\n    void *clientData,\t/* Pointer to TImageInstance for image. */\n    Display *display,\t\t/* Display to use for drawing. */\n    Drawable drawable,\t\t/* Where to redraw image. */\n    int imageX, int imageY,\t/* Origin of area to redraw, relative to\n\t\t\t\t * origin of image. */\n    int width, int height,\t/* Dimensions of area to redraw. */\n    int drawableX, int drawableY)\n\t\t\t\t/* Coordinates in drawable corresponding to\n\t\t\t\t * imageX and imageY. */\n{\n    TImageInstance *instPtr = (TImageInstance *)clientData;\n\n    /*\n     * The purpose of the test image type is to track the calls to an image\n     * display proc and record the parameters passed in each call.  On macOS a\n     * display proc must be run inside of the drawRect method of an NSView in\n     * order for the graphics operations to have any effect.  To deal with\n     * this, whenever a display proc is called outside of any drawRect method\n     * it schedules a redraw of the NSView.\n     *\n     * In an attempt to work around this, each image instance maintains it own\n     * copy of the log message which gets written on the first call to the\n     * display proc.  This usually means that the message created on macOS is\n     * the same as that created on other platforms.  However it is possible\n     * for the messages to differ for other reasons, namely differences in\n     * how damage regions are computed.\n     */\n\n    if (LOG_DISPLAY(drawable)) {\n\tif (instPtr->displayFailed == False) {\n\n\t    /*\n\t     * Drawing is possible on the first call to DisplayImage.\n\t     * Log the message.\n\t     */\n\n\t    snprintf(instPtr->buffer, sizeof(instPtr->buffer), \"%s display %d %d %d %d\",\n\t    instPtr->modelPtr->imageName, imageX, imageY, width, height);\n\t}\n\tTcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName,\n\t\t    NULL, instPtr->buffer,\n\t\t    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);\n\tinstPtr->displayFailed = False;\n    } else {\n\n\t/*\n\t * Drawing is not possible on the first call to DisplayImage.\n\t * Save the message, but do not log it until the actual display.\n\t */\n\n\tif (instPtr->displayFailed == False) {\n\t    snprintf(instPtr->buffer, sizeof(instPtr->buffer), \"%s display %d %d %d %d\",\n\t\t    instPtr->modelPtr->imageName, imageX, imageY, width, height);\n\t}\n\tinstPtr->displayFailed = True;\n    }\n    if (width > (instPtr->modelPtr->width - imageX)) {\n\twidth = instPtr->modelPtr->width - imageX;\n    }\n    if (height > (instPtr->modelPtr->height - imageY)) {\n\theight = instPtr->modelPtr->height - imageY;\n    }\n\n    XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,\n\t    (unsigned) (width-1), (unsigned) (height-1));\n    XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,\n\t    (int) (drawableX + width - 1), (int) (drawableY + height - 1));\n    XDrawLine(display, drawable, instPtr->gc, drawableX,\n\t    (int) (drawableY + height - 1),\n\t    (int) (drawableX + width - 1), drawableY);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageFree --\n *\n *\tThis function is called when an instance of an image is no longer\n *\tused.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation related to the instance is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageFree(\n    void *clientData,\t/* Pointer to TImageInstance for instance. */\n    Display *display)\t\t/* Display where image was to be drawn. */\n{\n    TImageInstance *instPtr = (TImageInstance *)clientData;\n    char buffer[200];\n\n    snprintf(buffer, sizeof(buffer), \"%s free\", instPtr->modelPtr->imageName);\n    Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName, NULL,\n\t    buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);\n    Tk_FreeColor(instPtr->fg);\n    Tk_FreeGC(display, instPtr->gc);\n    Tcl_Free(instPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageDelete --\n *\n *\tThis function is called to clean up a test image when an application\n *\tgoes away.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation about the image is deleted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageDelete(\n    void *clientData)\t/* Pointer to TImageModel for image. When\n\t\t\t\t * this function is called, no more instances\n\t\t\t\t * exist. */\n{\n    TImageModel *timPtr = (TImageModel *)clientData;\n    char buffer[100];\n\n    snprintf(buffer, sizeof(buffer), \"%s delete\", timPtr->imageName);\n    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,\n\t    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);\n\n    Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);\n    Tcl_Free(timPtr->imageName);\n    Tcl_Free(timPtr->varName);\n    Tcl_Free(timPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestmakeexistObjCmd --\n *\n *\tThis function implements the \"testmakeexist\" command. It calls\n *\tTk_MakeWindowExist on each of its arguments to force the windows to be\n *\tcreated.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tForces windows to be created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestmakeexistObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    Tk_Window mainWin = (Tk_Window)clientData;\n    Tcl_Size i;\n    Tk_Window tkwin;\n\n    for (i = 1; i < objc; i++) {\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTk_MakeWindowExist(tkwin);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestmenubarObjCmd --\n *\n *\tThis function implements the \"testmenubar\" command. It is used to test\n *\tthe Unix facilities for creating space above a toplevel window for a\n *\tmenubar.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tChanges menubar related stuff.\n *\n *----------------------------------------------------------------------\n */\n\n#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))\nstatic int\nTestmenubarObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n#ifdef __UNIX__\n    Tk_Window mainWin = (Tk_Window)clientData;\n    Tk_Window tkwin, menubar;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (strcmp(Tcl_GetString(objv[1]), \"window\") == 0) {\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"windows toplevel menubar\");\n\t    return TCL_ERROR;\n\t}\n\ttkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainWin);\n\tif (tkwin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetString(objv[3])[0] == 0) {\n\t    TkUnixSetMenubar(tkwin, NULL);\n\t} else {\n\t    menubar = Tk_NameToWindow(interp, Tcl_GetString(objv[3]), mainWin);\n\t    if (menubar == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkUnixSetMenubar(tkwin, menubar);\n\t}\n    } else {\n\tTcl_AppendResult(interp, \"bad option \\\"\", Tcl_GetString(objv[1]),\n\t\t\"\\\": must be  window\", NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n#else\n    Tcl_AppendResult(interp, \"testmenubar is supported only under Unix\", NULL);\n    return TCL_ERROR;\n#endif\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestmetricsObjCmd --\n *\n *\tThis function implements the testmetrics command. It provides a way to\n *\tdetermine the size of various widget components.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n#if defined(_WIN32)\nstatic int\nTestmetricsObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    char buf[TCL_INTEGER_SPACE];\n    int val;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (strcmp(Tcl_GetString(objv[1]), \"cyvscroll\") == 0) {\n\tval = GetSystemMetrics(SM_CYVSCROLL);\n    } else  if (strcmp(Tcl_GetString(objv[1]), \"cxhscroll\") == 0) {\n\tval = GetSystemMetrics(SM_CXHSCROLL);\n    } else {\n\tTcl_AppendResult(interp, \"bad option \\\"\", Tcl_GetString(objv[1]),\n\t\t\"\\\": must be cxhscroll or cyvscroll\", NULL);\n\treturn TCL_ERROR;\n    }\n    snprintf(buf, sizeof(buf), \"%d\", val);\n    Tcl_AppendResult(interp, buf, NULL);\n    return TCL_OK;\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestpropObjCmd --\n *\n *\tThis function implements the \"testprop\" command. It fetches and prints\n *\tthe value of a property on a window.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestpropObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    Tk_Window mainWin = (Tk_Window)clientData;\n    int result, actualFormat;\n    unsigned long bytesAfter, length, value;\n    Atom actualType, propName;\n    unsigned char *property, *p;\n    char *end;\n    Window w;\n    char buffer[30];\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window property\");\n\treturn TCL_ERROR;\n    }\n\n    w = strtoul(Tcl_GetString(objv[1]), &end, 0);\n    propName = Tk_InternAtom(mainWin, Tcl_GetString(objv[2]));\n    property = NULL;\n    result = XGetWindowProperty(Tk_Display(mainWin),\n\t    w, propName, 0, 100000, False, AnyPropertyType,\n\t    &actualType, &actualFormat, &length,\n\t    &bytesAfter, &property);\n    if ((result == Success) && (actualType != None)) {\n\tif ((actualFormat == 8) && (actualType == XA_STRING)) {\n\t    for (p = property; ((unsigned long)(p-property)) < length; p++) {\n\t\tif (*p == 0) {\n\t\t    *p = '\\n';\n\t\t}\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj((/*!unsigned*/char*)property, TCL_INDEX_NONE));\n\t} else {\n\t    for (p = property; length > 0; length--) {\n\t\tif (actualFormat == 32) {\n\t\t    value = *((long *) p);\n\t\t    p += sizeof(long);\n\t\t} else if (actualFormat == 16) {\n\t\t    value = 0xffff & (*((short *) p));\n\t\t    p += sizeof(short);\n\t\t} else {\n\t\t    value = 0xff & *p;\n\t\t    p += 1;\n\t\t}\n\t\tsnprintf(buffer, sizeof(buffer), \"0x%lx\", value);\n\t\tTcl_AppendElement(interp, buffer);\n\t    }\n\t}\n    }\n    if (property != NULL) {\n\tXFree(property);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestpropObjCmd --\n *\n *\tThis function implements the \"testprop\" command. It fetches and prints\n *\tthe value of a property on a window.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestprintfObjCmd(\n    TCL_UNUSED(void *),\t/* Not used */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    char buffer[256];\n    Tcl_WideInt wideInt;\n    long long longLongInt;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"wideint\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetWideIntFromObj(interp, objv[1], &wideInt) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    longLongInt = wideInt;\n\n    /* Just add a lot of arguments to snprintf. Reason: on AMD64, the first\n     * 4 or 6 arguments (we assume 8, just in case) might be put in registers,\n     * which still woudn't tell if the assumed size is correct: We want this\n     * test-case to fail if the 64-bit value is printed as truncated to 32-bit.\n     */\n    snprintf(buffer, sizeof(buffer), \"%s%s%s%s%s%s%s%s%\" TCL_LL_MODIFIER \"d %\"\n\t    TCL_LL_MODIFIER \"u\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\",\n\t    longLongInt, (unsigned long long)longLongInt);\n    Tcl_AppendResult(interp, buffer, NULL);\n    return TCL_OK;\n}\n\f\n#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))\n/*\n *----------------------------------------------------------------------\n *\n * TestwrapperObjCmd --\n *\n *\tThis function implements the \"testwrapper\" command. It provides a way\n *\tfrom Tcl to determine the extra window Tk adds in between the toplevel\n *\twindow and the window decorations.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestwrapperObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    TkWindow *winPtr, *wrapperPtr;\n    Tk_Window tkwin;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = (Tk_Window)clientData;\n    winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);\n    if (winPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    wrapperPtr = TkpGetWrapperWindow(winPtr);\n    if (wrapperPtr != NULL) {\n\tchar buf[TCL_INTEGER_SPACE];\n\n\tTkpPrintWindowId(buf, Tk_WindowId(wrapperPtr));\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n    }\n    return TCL_OK;\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CustomOptionSet, CustomOptionGet, CustomOptionRestore, CustomOptionFree --\n *\n *\tHandlers for object-based custom configuration options. See\n *\tTestobjconfigcommand.\n *\n * Results:\n *\tSee user documentation for expected results from these functions.\n *\t\tCustomOptionSet\t\tStandard Tcl Result.\n *\t\tCustomOptionGet\t\tTcl_Obj * containing value.\n *\t\tCustomOptionRestore\tNone.\n *\t\tCustomOptionFree\tNone.\n *\n * Side effects:\n *\tDepends on the function.\n *\t\tCustomOptionSet\t\tSets option value to new setting.\n *\t\tCustomOptionGet\t\tCreates a new Tcl_Obj.\n *\t\tCustomOptionRestore\tResets option value to original value.\n *\t\tCustomOptionFree\tFree storage for internal rep of option.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCustomOptionSet(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tk_Window),\n    Tcl_Obj **value,\n    char *recordPtr,\n    Tcl_Size internalOffset,\n    char *saveInternalPtr,\n    int flags)\n{\n    int objEmpty;\n    char *newStr, *string, *internalPtr;\n\n    objEmpty = 0;\n\n    if (internalOffset != TCL_INDEX_NONE) {\n\tinternalPtr = recordPtr + internalOffset;\n    } else {\n\tinternalPtr = NULL;\n    }\n\n    /*\n     * See if the object is empty.\n     */\n\n    if (value == NULL) {\n\tobjEmpty = 1;\n\tCLANG_ASSERT(value);\n    } else if ((*value)->bytes != NULL) {\n\tobjEmpty = ((*value)->length == 0);\n    } else {\n\t(void)Tcl_GetString(*value);\n\tobjEmpty = ((*value)->length == 0);\n    }\n\n    if ((flags & TK_OPTION_NULL_OK) && objEmpty) {\n\t*value = NULL;\n    } else {\n\tstring = Tcl_GetString(*value);\n\tTcl_UtfToUpper(string);\n\tif (strcmp(string, \"BAD\") == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"expected good value, got \\\"BAD\\\"\", TCL_INDEX_NONE));\n\t    return TCL_ERROR;\n\t}\n    }\n    if (internalPtr != NULL) {\n\tif (*value != NULL) {\n\t    string = Tcl_GetString(*value);\n\t    newStr = (char *)Tcl_Alloc((*value)->length + 1);\n\t    strcpy(newStr, string);\n\t} else {\n\t    newStr = NULL;\n\t}\n\t*((char **) saveInternalPtr) = *((char **) internalPtr);\n\t*((char **) internalPtr) = newStr;\n    }\n\n    return TCL_OK;\n}\n\nstatic Tcl_Obj *\nCustomOptionGet(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *recordPtr,\n    Tcl_Size internalOffset)\n{\n    return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), TCL_INDEX_NONE));\n}\n\nstatic void\nCustomOptionRestore(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *internalPtr,\n    char *saveInternalPtr)\n{\n    *(char **)internalPtr = *(char **)saveInternalPtr;\n    return;\n}\n\nstatic void\nCustomOptionFree(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *internalPtr)\n{\n    if (*(char **)internalPtr != NULL) {\n\tTcl_Free(*(char **)internalPtr);\n    }\n}\n/*\n *----------------------------------------------------------------------\n *\n * TestPhotoStringMatchCmd --\n *\n *\tThis function implements the \"testphotostringmatch\" command. It\n *\tprovides a way from Tcl to call the string match function for the\n *\tdefault image handler directly.\n *\n * Results:\n *\tA standard Tcl result. If data is in the proper format, the result in\n *\tinterp will contain width and height as a list. If the data cannot be\n *\tparsed as default image format, returns TCL_ERROR and leaves an\n *\tappropriate error message in interp.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestPhotoStringMatchCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    Tcl_Obj *dummy = NULL;\n    Tcl_Obj *resultObj[2];\n    int width, height;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"imageData\");\n\treturn TCL_ERROR;\n    }\n    if (TkDebugPhotoStringMatchDef(interp, objv[1], dummy, &width, &height)) {\n\tresultObj[0] = Tcl_NewWideIntObj(width);\n\tresultObj[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, resultObj));\n\treturn TCL_OK;\n    } else {\n\treturn TCL_ERROR;\n    }\n}\n\n\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkText.c",
    "content": "/*\n * tkText.c --\n *\n *\tThis module provides a big chunk of the implementation of multi-line\n *\teditable text widgets for Tk. Among other things, it provides the Tcl\n *\tcommand interfaces to text widgets. The B-tree representation of text\n *\tand its actual display are implemented elsewhere.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n * Copyright © 1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkUndo.h\"\n#include \"default.h\"\n\n#if defined(MAC_OSX_TK)\n#define Style TkStyle\n#define DInfo TkDInfo\n#endif\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n#include \"tkText.h\"\n\n/*\n * Used to avoid having to allocate and deallocate arrays on the fly for\n * commonly used functions. Must be > 0.\n */\n\n#define PIXEL_CLIENTS 5\n\n/*\n * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap\n * option of the Text widget. These values are used as indices into the string\n * table below.\n */\n\nconst char *const tkTextWrapStrings[] = {\n    \"char\", \"none\", \"word\", NULL\n};\n\n/*\n * The 'TkTextTabStyle' enum in tkText.h is used to define a type for the\n * -tabstyle option of the Text widget. These values are used as indices into\n * the string table below.\n */\n\nconst char *const tkTextTabStyleStrings[] = {\n    \"tabular\", \"wordprocessor\", NULL\n};\n\n/*\n * The 'TkTextInsertUnfocussed' enum in tkText.h is used to define a type for\n * the -insertunfocussed option of the Text widget. These values are used as\n * indice into the string table below.\n */\n\nstatic const char *const insertUnfocussedStrings[] = {\n    \"hollow\", \"none\", \"solid\", NULL\n};\n\n/*\n * The following functions and custom option type are used to define the\n * \"line\" option type, and thereby handle the text widget '-startline',\n * '-endline' configuration options which are of that type.\n *\n * We do not need a 'freeProc' because all changes to these two options are\n * handled through the TK_TEXT_LINE_RANGE flag in the optionSpecs list, and\n * the internal storage is just a pointer, which therefore doesn't need\n * freeing.\n */\n\nstatic int\t\tSetLineStartEnd(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tk_Window tkwin,\n\t\t\t    Tcl_Obj **value, char *recordPtr,\n\t\t\t    Tcl_Size internalOffset, char *oldInternalPtr,\n\t\t\t    int flags);\nstatic Tcl_Obj *\tGetLineStartEnd(void *clientData,\n\t\t\t    Tk_Window tkwin, char *recordPtr,\n\t\t\t    Tcl_Size internalOffset);\nstatic void\t\tRestoreLineStartEnd(void *clientData,\n\t\t\t    Tk_Window tkwin, char *internalPtr,\n\t\t\t    char *oldInternalPtr);\n\nstatic const Tk_ObjCustomOption lineOption = {\n    \"line\",\t\t\t/* name */\n    SetLineStartEnd,\t\t/* setProc */\n    GetLineStartEnd,\t\t/* getProc */\n    RestoreLineStartEnd,\t/* restoreProc */\n    NULL,\t\t\t/* freeProc */\n    0\n};\n\n/*\n * Information used to parse text configuration options:\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_BOOLEAN, \"-autoseparators\", \"autoSeparators\",\n\t\"AutoSeparators\", DEF_TEXT_AUTO_SEPARATORS, TCL_INDEX_NONE,\n\toffsetof(TkText, autoSeparators),\n\tTK_OPTION_DONT_SET_DEFAULT|TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_BORDER, \"-background\", \"background\", \"Background\",\n\tDEF_TEXT_BG_COLOR, TCL_INDEX_NONE, offsetof(TkText, border),\n\t0, DEF_TEXT_BG_MONO, 0},\n    {TK_OPTION_SYNONYM, \"-bd\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-borderwidth\",\n\tTK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_SYNONYM, \"-bg\", NULL, NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-background\", 0},\n    {TK_OPTION_BOOLEAN, \"-blockcursor\", \"blockCursor\",\n\t\"BlockCursor\", DEF_TEXT_BLOCK_CURSOR, TCL_INDEX_NONE,\n\toffsetof(TkText, insertCursorType), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tDEF_TEXT_BORDER_WIDTH, offsetof(TkText, borderWidthObj), TCL_INDEX_NONE,\n\t0, 0, TK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\",\n\tDEF_TEXT_CURSOR, TCL_INDEX_NONE, offsetof(TkText, cursor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_CUSTOM, \"-endline\", NULL, NULL,\n\t NULL, TCL_INDEX_NONE, offsetof(TkText, end), TK_OPTION_NULL_OK,\n\t &lineOption, TK_TEXT_LINE_RANGE},\n    {TK_OPTION_BOOLEAN, \"-exportselection\", \"exportSelection\",\n\t\"ExportSelection\", DEF_TEXT_EXPORT_SELECTION, TCL_INDEX_NONE,\n\toffsetof(TkText, exportSelection), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_SYNONYM, \"-fg\", \"foreground\", NULL,\n\tNULL, 0, TCL_INDEX_NONE, 0, \"-foreground\", 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_TEXT_FONT, TCL_INDEX_NONE, offsetof(TkText, tkfont), 0, 0,\n\tTK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_COLOR, \"-foreground\", \"foreground\", \"Foreground\",\n\tDEF_TEXT_FG, TCL_INDEX_NONE, offsetof(TkText, fgColor), 0,\n\t0, 0},\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\",\n\tDEF_TEXT_HEIGHT, offsetof(TkText, heightObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightbackground\", \"highlightBackground\",\n\t\"HighlightBackground\", DEF_TEXT_HIGHLIGHT_BG,\n\tTCL_INDEX_NONE, offsetof(TkText, highlightBgColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_COLOR, \"-highlightcolor\", \"highlightColor\", \"HighlightColor\",\n\tDEF_TEXT_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkText, highlightColorPtr),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-highlightthickness\", \"highlightThickness\",\n\t\"HighlightThickness\", DEF_TEXT_HIGHLIGHT_WIDTH, offsetof(TkText, highlightWidthObj),\n\tTCL_INDEX_NONE, 0, 0, TK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_BORDER, \"-inactiveselectbackground\",\"inactiveSelectBackground\",\n\t\"Foreground\",\n\tDEF_TEXT_INACTIVE_SELECT_BG_COLOR,\n\tTCL_INDEX_NONE, offsetof(TkText, inactiveSelBorder),\n\tTK_OPTION_NULL_OK, DEF_TEXT_SELECT_MONO, 0},\n    {TK_OPTION_BORDER, \"-insertbackground\", \"insertBackground\", \"Foreground\",\n\tDEF_TEXT_INSERT_BG,\n\tTCL_INDEX_NONE, offsetof(TkText, insertBorder),\n\t0, 0, 0},\n    {TK_OPTION_PIXELS, \"-insertborderwidth\", \"insertBorderWidth\",\n\t\"BorderWidth\", DEF_TEXT_INSERT_BD_COLOR, offsetof(TkText, insertBorderWidthObj),\n\tTCL_INDEX_NONE, 0,\n\tDEF_TEXT_INSERT_BD_MONO, 0},\n    {TK_OPTION_INT, \"-insertofftime\", \"insertOffTime\", \"OffTime\",\n\tDEF_TEXT_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(TkText, insertOffTime),\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-insertontime\", \"insertOnTime\", \"OnTime\",\n\tDEF_TEXT_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(TkText, insertOnTime),\n\t0, 0, 0},\n    {TK_OPTION_STRING_TABLE,\n\t\"-insertunfocussed\", \"insertUnfocussed\", \"InsertUnfocussed\",\n\tDEF_TEXT_INSERT_UNFOCUSSED, TCL_INDEX_NONE, offsetof(TkText, insertUnfocussed),\n\tTK_OPTION_ENUM_VAR, insertUnfocussedStrings, 0},\n    {TK_OPTION_PIXELS, \"-insertwidth\", \"insertWidth\", \"InsertWidth\",\n\tDEF_TEXT_INSERT_WIDTH, offsetof(TkText, insertWidthObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_INT, \"-maxundo\", \"maxUndo\", \"MaxUndo\",\n\tDEF_TEXT_MAX_UNDO, TCL_INDEX_NONE, offsetof(TkText, maxUndo),\n\tTK_OPTION_DONT_SET_DEFAULT, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", \"padX\", \"Pad\",\n\tDEF_TEXT_PADX, offsetof(TkText, padXObj), TCL_INDEX_NONE, 0, 0,\n\tTK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_PIXELS, \"-pady\", \"padY\", \"Pad\",\n\tDEF_TEXT_PADY, offsetof(TkText, padYObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tDEF_TEXT_RELIEF, TCL_INDEX_NONE, offsetof(TkText, relief), 0, 0, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", \"selectBackground\", \"Foreground\",\n\tDEF_TEXT_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkText, selBorder),\n\t0, DEF_TEXT_SELECT_MONO, 0},\n    {TK_OPTION_PIXELS, \"-selectborderwidth\", \"selectBorderWidth\",\n\t\"BorderWidth\", DEF_TEXT_SELECT_BD_COLOR,\n\toffsetof(TkText, selBorderWidthObj), TCL_INDEX_NONE,\n\t0, DEF_TEXT_SELECT_BD_MONO, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", \"selectForeground\", \"Background\",\n\tDEF_TEXT_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(TkText, selFgColorPtr),\n\tTK_OPTION_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0},\n    {TK_OPTION_BOOLEAN, \"-setgrid\", \"setGrid\", \"SetGrid\",\n\tDEF_TEXT_SET_GRID, TCL_INDEX_NONE, offsetof(TkText, setGrid), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_PIXELS, \"-spacing1\", \"spacing1\", \"Spacing\",\n\tDEF_TEXT_SPACING1, offsetof(TkText, spacing1Obj), TCL_INDEX_NONE,\n\t0, 0, TK_TEXT_LINE_GEOMETRY },\n    {TK_OPTION_PIXELS, \"-spacing2\", \"spacing2\", \"Spacing\",\n\tDEF_TEXT_SPACING2, offsetof(TkText, spacing2Obj), TCL_INDEX_NONE,\n\t0, 0, TK_TEXT_LINE_GEOMETRY },\n    {TK_OPTION_PIXELS, \"-spacing3\", \"spacing3\", \"Spacing\",\n\tDEF_TEXT_SPACING3, offsetof(TkText, spacing3Obj), TCL_INDEX_NONE,\n\t0, 0, TK_TEXT_LINE_GEOMETRY },\n    {TK_OPTION_CUSTOM, \"-startline\", NULL, NULL,\n\t NULL, TCL_INDEX_NONE, offsetof(TkText, start), TK_OPTION_NULL_OK,\n\t &lineOption, TK_TEXT_LINE_RANGE},\n    {TK_OPTION_STRING_TABLE, \"-state\", \"state\", \"State\",\n\tDEF_TEXT_STATE, TCL_INDEX_NONE, offsetof(TkText, state),\n\tTK_OPTION_ENUM_VAR, &tkStateStrings[1], 0},\n    {TK_OPTION_STRING, \"-tabs\", \"tabs\", \"Tabs\",\n\tDEF_TEXT_TABS, offsetof(TkText, tabOptionObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, TK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_STRING_TABLE, \"-tabstyle\", \"tabStyle\", \"TabStyle\",\n\tDEF_TEXT_TABSTYLE, TCL_INDEX_NONE, offsetof(TkText, tabStyle),\n\tTK_OPTION_ENUM_VAR, tkTextTabStyleStrings, TK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\",\n\tDEF_TEXT_TAKE_FOCUS, offsetof(TkText, takeFocusObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-undo\", \"undo\", \"Undo\",\n\tDEF_TEXT_UNDO, TCL_INDEX_NONE, offsetof(TkText, undo),\n\tTK_OPTION_DONT_SET_DEFAULT|TK_OPTION_VAR(bool), 0 , 0},\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\tDEF_TEXT_WIDTH, TCL_INDEX_NONE, offsetof(TkText, width), 0, 0,\n\tTK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_STRING_TABLE, \"-wrap\", \"wrap\", \"Wrap\",\n\tDEF_TEXT_WRAP, TCL_INDEX_NONE, offsetof(TkText, wrapMode),\n\tTK_OPTION_ENUM_VAR, tkTextWrapStrings, TK_TEXT_LINE_GEOMETRY},\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tDEF_TEXT_XSCROLL_COMMAND, offsetof(TkText, xScrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-yscrollcommand\", \"yScrollCommand\", \"ScrollCommand\",\n\tDEF_TEXT_YSCROLL_COMMAND, offsetof(TkText, yScrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0}\n};\n\n/*\n * These three typedefs, the structure and the SearchPerform, SearchCore\n * functions below are used for line-based searches of the text widget, and,\n * in particular, to handle multi-line matching even though the text widget is\n * a single-line based data structure. They are completely abstracted away\n * from the Text widget internals, however, so could easily be re-used with\n * any line-based entity to provide multi-line matching.\n *\n * We have abstracted this code away from the text widget to try to keep Tk as\n * modular as possible.\n */\n\nstruct SearchSpec;\t/* Forward declaration. */\n\ntypedef void *SearchAddLineProc(Tcl_Size lineNum,\n\t\t\t    struct SearchSpec *searchSpecPtr,\n\t\t\t    Tcl_Obj *theLine, Tcl_Size *lenPtr,\n\t\t\t    int *extraLinesPtr);\ntypedef bool\t\tSearchMatchProc(Tcl_Size lineNum,\n\t\t\t    struct SearchSpec *searchSpecPtr,\n\t\t\t    void *clientData, Tcl_Obj *theLine,\n\t\t\t    Tcl_Size matchOffset, Tcl_Size matchLength);\ntypedef int\t\tSearchLineIndexProc(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *objPtr, struct SearchSpec *searchSpecPtr,\n\t\t\t    Tcl_Size *linePosPtr, Tcl_Size *offsetPosPtr);\n\ntypedef struct SearchSpec {\n    bool exact;\t\t\t/* Whether search is exact or regexp. */\n    bool noCase;\t\t\t/* Case-insenstivive? */\n    bool noLineStop;\t\t/* If not set, a regexp search will use the\n\t\t\t\t * TCL_REG_NLSTOP flag. */\n    bool overlap;\t\t/* If set, results from multiple searches\n\t\t\t\t * (-all) are allowed to overlap each\n\t\t\t\t * other. */\n    bool strictLimits;\t\t/* If set, matches must be completely inside\n\t\t\t\t * the from,to range. Otherwise the limits\n\t\t\t\t * only apply to the start of each match. */\n    bool all;\t\t\t/* Whether all or the first match should be\n\t\t\t\t * reported. */\n    bool backwards;\t\t/* Searching forwards or backwards. */\n    int searchElide;\t\t/* Search in hidden text as well. */\n    Tcl_Size startLine;\t\t/* First line to examine. */\n    Tcl_Size startOffset;\t\t/* Index in first line to start at. */\n    Tcl_Size stopLine;\t\t/* Last line to examine, or -1 when we search\n\t\t\t\t * all available text. */\n    Tcl_Size stopOffset;\t\t/* Index to stop at, provided stopLine is not\n\t\t\t\t * -1. */\n    Tcl_Size numLines;\t\t/* Total lines which are available. */\n    Tcl_Obj *varPtr;\t\t/* If non-NULL, store length(s) of match(es)\n\t\t\t\t * in this variable. */\n    Tcl_Obj *countPtr;\t\t/* Keeps track of currently found lengths. */\n    Tcl_Obj *resPtr;\t\t/* Keeps track of currently found locations */\n    SearchAddLineProc *addLineProc;\n\t\t\t\t/* Function to call when we need to add\n\t\t\t\t * another line to the search string so far */\n    SearchMatchProc *foundMatchProc;\n\t\t\t\t/* Function to call when we have found a\n\t\t\t\t * match. */\n    SearchLineIndexProc *lineIndexProc;\n\t\t\t\t/* Function to call when we have found a\n\t\t\t\t * match. */\n    void *clientData;\t/* Information about structure being searched,\n\t\t\t\t * in this case a text widget. */\n} SearchSpec;\n\n/*\n * The text-widget-independent functions which actually perform the search,\n * handling both regexp and exact searches.\n */\n\nstatic int\t\tSearchCore(Tcl_Interp *interp,\n\t\t\t    SearchSpec *searchSpecPtr, Tcl_Obj *patObj);\nstatic int\t\tSearchPerform(Tcl_Interp *interp,\n\t\t\t    SearchSpec *searchSpecPtr, Tcl_Obj *patObj,\n\t\t\t    Tcl_Obj *fromPtr, Tcl_Obj *toPtr);\n\n/*\n * Boolean variable indicating whether or not special debugging code should be\n * executed.\n */\n\nint tkTextDebug = 0;\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tConfigureText(Tcl_Interp *interp,\n\t\t\t    TkText *textPtr, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tDeleteIndexRange(TkSharedText *sharedPtr,\n\t\t\t    TkText *textPtr, const TkTextIndex *indexPtr1,\n\t\t\t    const TkTextIndex *indexPtr2, int viewUpdate);\nstatic Tcl_Size\t\tCountIndices(const TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr1,\n\t\t\t    const TkTextIndex *indexPtr2,\n\t\t\t    TkTextCountType type);\nstatic void\t\tDestroyText(TkText *textPtr);\nstatic Tcl_Size\t\tInsertChars(TkSharedText *sharedTextPtr,\n\t\t\t    TkText *textPtr, TkTextIndex *indexPtr,\n\t\t\t    Tcl_Obj *stringPtr, bool viewUpdate);\nstatic void\t\tTextBlinkProc(void *clientData);\nstatic Tcl_CmdDeleteProc TextCmdDeletedProc;\nstatic int\t\tCreateWidget(TkSharedText *sharedPtr, Tk_Window tkwin,\n\t\t\t    Tcl_Interp *interp, const TkText *parent,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tTextEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic Tcl_Size\tTextFetchSelection(void *clientData, Tcl_Size offset,\n\t\t\t    char *buffer, Tcl_Size maxBytes);\nstatic int\t\tTextIndexSortProc(const void *first,\n\t\t\t    const void *second);\nstatic int\t\tTextInsertCmd(TkSharedText *sharedTextPtr,\n\t\t\t    TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    const TkTextIndex *indexPtr, int viewUpdate);\nstatic int\t\tTextReplaceCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    const TkTextIndex *indexFromPtr,\n\t\t\t    const TkTextIndex *indexToPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[], int viewUpdate);\nstatic int\t\tTextSearchCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tTextEditCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic Tcl_ObjCmdProc2 TextWidgetObjCmd;\nstatic Tcl_ObjCmdProc2 SharedTextObjCmd;\nstatic void\t\tTextWorldChangedCallback(void *instanceData);\nstatic void\t\tTextWorldChanged(TkText *textPtr, int mask);\nstatic int\t\tTextDumpCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic bool\t\tDumpLine(Tcl_Interp *interp, TkText *textPtr,\n\t\t\t    int what, TkTextLine *linePtr, Tcl_Size start, Tcl_Size end,\n\t\t\t    Tcl_Size lineno, Tcl_Obj *command);\nstatic bool\t\tDumpSegment(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    const char *key, const char *value,\n\t\t\t    Tcl_Obj *command, const TkTextIndex *index,\n\t\t\t    int what);\nstatic int\t\tTextEditUndo(TkText *textPtr);\nstatic int\t\tTextEditRedo(TkText *textPtr);\nstatic Tcl_Obj *\tTextGetText(const TkText *textPtr,\n\t\t\t    const TkTextIndex *index1,\n\t\t\t    const TkTextIndex *index2, int visibleOnly);\nstatic void\t\tGenerateModifiedEvent(TkText *textPtr);\nstatic void\t\tGenerateUndoStackEvent(TkText *textPtr);\nstatic void\t\tUpdateDirtyFlag(TkSharedText *sharedPtr);\nstatic void\t\tTextPushUndoAction(TkText *textPtr,\n\t\t\t    Tcl_Obj *undoString, int insert,\n\t\t\t    const TkTextIndex *index1Ptr,\n\t\t\t    const TkTextIndex *index2Ptr);\nstatic Tcl_Size\t\tTextSearchIndexInLine(const SearchSpec *searchSpecPtr,\n\t\t\t    TkTextLine *linePtr, Tcl_Size byteIndex);\nstatic int\t\tTextPeerCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic TkUndoProc\tTextUndoRedoCallback;\n\n/*\n * Declarations of the three search procs required by the multi-line search\n * routines.\n */\n\nstatic SearchMatchProc\t\tTextSearchFoundMatch;\nstatic SearchAddLineProc\tTextSearchAddNextLine;\nstatic SearchLineIndexProc\tTextSearchGetLineIndex;\n\n/*\n * The structure below defines text class behavior by means of functions that\n * can be invoked from generic window code.\n */\n\nstatic const Tk_ClassProcs textClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TextWorldChangedCallback,\t/* worldChangedProc */\n    NULL,\t\t\t\t\t/* createProc */\n    NULL\t\t\t\t\t/* modalProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_TextObjCmd --\n *\n *\tThis function is invoked to process the \"text\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_TextObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    return CreateWidget(NULL, tkwin, interp, NULL, objc, objv);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CreateWidget --\n *\n *\tThis function is invoked to process the \"text\" Tcl command, (when\n *\tcalled by Tk_TextObjCmd) and the \"$text peer create\" text widget\n *\tsub-command (called from TextPeerCmd).\n *\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result, places the name of the widget created into the\n *\tinterp's result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCreateWidget(\n    TkSharedText *sharedPtr,\t/* Shared widget info, or NULL. */\n    Tk_Window tkwin,\t\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    const TkText *parent,\t/* If non-NULL then take default start, end\n\t\t\t\t * from this parent. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkText *textPtr;\n    Tk_OptionTable optionTable;\n    TkTextIndex startIndex;\n    Tk_Window newWin;\n\n    /*\n     * Create the window.\n     */\n\n    newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),\n\t    NULL);\n    if (newWin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the text widget and initialize everything to zero, then set the\n     * necessary initial (non-NULL) values. It is important that the 'set' tag\n     * and 'insert', 'current' mark pointers are all NULL to start.\n     */\n\n    textPtr = (TkText *)Tcl_Alloc(sizeof(TkText));\n    memset(textPtr, 0, sizeof(TkText));\n\n    textPtr->tkwin = newWin;\n    textPtr->display = Tk_Display(newWin);\n    textPtr->interp = interp;\n    textPtr->widgetCmd = Tcl_CreateObjCommand2(interp,\n\t    Tk_PathName(textPtr->tkwin), TextWidgetObjCmd,\n\t    textPtr, TextCmdDeletedProc);\n\n    if (sharedPtr == NULL) {\n\tsharedPtr = (TkSharedText *)Tcl_Alloc(sizeof(TkSharedText));\n\tmemset(sharedPtr, 0, sizeof(TkSharedText));\n\n\tsharedPtr->refCount = 0;\n\tsharedPtr->peers = NULL;\n\tsharedPtr->tree = TkBTreeCreate(sharedPtr);\n\n\tTcl_InitHashTable(&sharedPtr->tagTable, TCL_STRING_KEYS);\n\tTcl_InitHashTable(&sharedPtr->markTable, TCL_STRING_KEYS);\n\tTcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS);\n\tTcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS);\n\tsharedPtr->undoStack = TkUndoInitStack(interp,0);\n\tsharedPtr->undo = false;\n\tsharedPtr->isDirty = 0;\n\tsharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;\n\tsharedPtr->autoSeparators = true;\n\tsharedPtr->lastEditMode = TK_TEXT_EDIT_OTHER;\n\tsharedPtr->stateEpoch = 0;\n\tsharedPtr->imageCount = 0;\n    }\n\n    /*\n     * Add the new widget to the shared list.\n     */\n\n    textPtr->sharedTextPtr = sharedPtr;\n    sharedPtr->refCount++;\n    textPtr->next = sharedPtr->peers;\n    sharedPtr->peers = textPtr;\n\n    /*\n     * This refCount will be held until DestroyText is called. Note also that\n     * the later call to 'TkTextCreateDInfo' will add more refCounts.\n     */\n\n    textPtr->refCount = 1;\n\n    /*\n     * Specify start and end lines in the B-tree. The default is the same as\n     * the parent, but this can be adjusted to display more or less if the\n     * start, end where given as configuration options.\n     */\n\n    if (parent != NULL) {\n\ttextPtr->start = parent->start;\n\ttextPtr->end = parent->end;\n    } else {\n\ttextPtr->start = NULL;\n\ttextPtr->end = NULL;\n    }\n\n    textPtr->state = TK_TEXT_STATE_NORMAL;\n    textPtr->relief = TK_RELIEF_FLAT;\n    textPtr->cursor = NULL;\n    textPtr->charWidth = 1;\n    textPtr->charHeight = 10;\n    textPtr->wrapMode = TEXT_WRAPMODE_CHAR;\n    textPtr->prevWidth = Tk_Width(newWin);\n    textPtr->prevHeight = Tk_Height(newWin);\n\n    /*\n     * Register with the B-tree. In some sense it would be best if we could do\n     * this later (after configuration options), so that any changes to\n     * start,end do not require a total recalculation.\n     */\n\n    TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight);\n\n    /*\n     * This will add refCounts to textPtr.\n     */\n\n    TkTextCreateDInfo(textPtr);\n    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t    &startIndex);\n    TkTextSetYView(textPtr, &startIndex, 0);\n    textPtr->exportSelection = true;\n    textPtr->pickEvent.type = LeaveNotify;\n    textPtr->undo = textPtr->sharedTextPtr->undo;\n    textPtr->maxUndo = textPtr->sharedTextPtr->maxUndo;\n    textPtr->autoSeparators = textPtr->sharedTextPtr->autoSeparators;\n    textPtr->tabOptionObj = NULL;\n\n    /*\n     * Create the \"sel\" tag and the \"current\" and \"insert\" marks.\n     */\n\n    textPtr->selBorder = NULL;\n    textPtr->inactiveSelBorder = NULL;\n    textPtr->selBorderWidthObj = NULL;\n    textPtr->selFgColorPtr = NULL;\n\n    /*\n     * Note: it is important that textPtr->selTagPtr is NULL before this\n     * initial call.\n     */\n\n    textPtr->selTagPtr = TkTextCreateTag(textPtr, \"sel\", NULL);\n    Tk_GetRelief(interp, DEF_TEXT_SELECT_RELIEF, &textPtr->selTagPtr->relief);\n    textPtr->currentMarkPtr = TkTextSetMark(textPtr, \"current\", &startIndex);\n    textPtr->insertMarkPtr = TkTextSetMark(textPtr, \"insert\", &startIndex);\n\n    /*\n     * Create the option table for this widget class. If it has already been\n     * created, the cached pointer will be returned.\n     */\n\n    optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n    Tk_SetClass(textPtr->tkwin, \"Text\");\n    Tk_SetClassProcs(textPtr->tkwin, &textClass, textPtr);\n    textPtr->optionTable = optionTable;\n\n    Tk_CreateEventHandler(textPtr->tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    TextEventProc, textPtr);\n    Tk_CreateEventHandler(textPtr->tkwin, KeyPressMask|KeyReleaseMask\n\t    |ButtonPressMask|ButtonReleaseMask|EnterWindowMask\n\t    |LeaveWindowMask|PointerMotionMask|VirtualEventMask,\n\t    TkTextBindProc, textPtr);\n    Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING,\n\t    TextFetchSelection, textPtr, XA_STRING);\n\n    if (Tk_InitOptions(interp, textPtr, optionTable, textPtr->tkwin)\n\t    != TCL_OK) {\n\tTk_DestroyWindow(textPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n    if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) {\n\tTk_DestroyWindow(textPtr->tkwin);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tk_NewWindowObj(textPtr->tkwin));\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextWidgetObjCmd --\n *\n *\tThis function is invoked to process the Tcl command that corresponds\n *\tto a text widget. See the user documentation for details on what it\n *\tdoes.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTextWidgetObjCmd(\n    void *clientData,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    int result = TCL_OK;\n    int idx;\n\n    static const char *const optionStrings[] = {\n\t\"bbox\", \"cget\", \"compare\", \"configure\", \"count\", \"debug\", \"delete\",\n\t\"dlineinfo\", \"dump\", \"edit\", \"get\", \"image\", \"index\", \"insert\",\n\t\"mark\", \"peer\", \"pendingsync\", \"replace\", \"scan\", \"search\",\n\t\"see\", \"sync\", \"tag\", \"window\", \"xview\", \"yview\", NULL\n    };\n    enum options {\n\tTEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,\n\tTEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,\n\tTEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,\n\tTEXT_PEER, TEXT_PENDINGSYNC, TEXT_REPLACE, TEXT_SCAN,\n\tTEXT_SEARCH, TEXT_SEE, TEXT_SYNC, TEXT_TAG, TEXT_WINDOW,\n\tTEXT_XVIEW, TEXT_YVIEW\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &idx) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    textPtr->refCount++;\n\n    switch ((enum options) idx) {\n    case TEXT_BBOX: {\n\tint x, y, width, height;\n\tconst TkTextIndex *indexPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tif (indexPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height,\n\t\tNULL, NULL) == 0) {\n\t    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);\n\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));\n\n\t    Tcl_SetObjResult(interp, listObj);\n\t}\n\tbreak;\n    }\n    case TEXT_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t} else {\n\t    Tcl_Obj *objPtr = Tk_GetOptionValue(interp, textPtr,\n\t\t    textPtr->optionTable, objv[2], textPtr->tkwin);\n\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    result = TCL_OK;\n\t}\n\tbreak;\n    case TEXT_COMPARE: {\n\tint relation, value;\n\tconst char *p;\n\tconst TkTextIndex *index1Ptr, *index2Ptr;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index1 op index2\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindex1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tindex2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[4]);\n\tif (index1Ptr == NULL || index2Ptr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\trelation = TkTextIndexCmp(index1Ptr, index2Ptr);\n\tp = Tcl_GetString(objv[3]);\n\tif (p[0] == '<') {\n\t    value = (relation < 0);\n\t    if ((p[1] == '=') && (p[2] == 0)) {\n\t\tvalue = (relation <= 0);\n\t    } else if (p[1] != 0) {\n\t\tgoto compareError;\n\t    }\n\t} else if (p[0] == '>') {\n\t    value = (relation > 0);\n\t    if ((p[1] == '=') && (p[2] == 0)) {\n\t\tvalue = (relation >= 0);\n\t    } else if (p[1] != 0) {\n\t\tgoto compareError;\n\t    }\n\t} else if ((p[0] == '=') && (p[1] == '=') && (p[2] == 0)) {\n\t    value = (relation == 0);\n\t} else if ((p[0] == '!') && (p[1] == '=') && (p[2] == 0)) {\n\t    value = (relation != 0);\n\t} else {\n\t    goto compareError;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(value));\n\tbreak;\n\n    compareError:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad comparison operator \\\"%s\\\": must be\"\n\t\t\" <, <=, ==, >=, >, or !=\", Tcl_GetString(objv[3])));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"COMPARISON\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n    case TEXT_CONFIGURE:\n\tif (objc <= 3) {\n\t    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, textPtr,\n\t\t    textPtr->optionTable, ((objc == 3) ? objv[2] : NULL),\n\t\t    textPtr->tkwin);\n\n\t    if (objPtr == NULL) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t} else {\n\t    result = ConfigureText(interp, textPtr, objc-2, objv+2);\n\t}\n\tbreak;\n    case TEXT_COUNT: {\n\tconst TkTextIndex *indexFromPtr, *indexToPtr;\n\tTcl_Size i;\n\tint found = 0, update = 0;\n\tTcl_Obj *objPtr = NULL;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"?-option value ...? index1 index2\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tindexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-2]);\n\tif (indexFromPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-1]);\n\tif (indexToPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tfor (i = 2; i < objc-2; i++) {\n\t    Tcl_Size value;\n\t    Tcl_Size length;\n\t    const char *option = Tcl_GetStringFromObj(objv[i], &length);\n\t    char c;\n\n\t    if (length < 2 || option[0] != '-') {\n\t\tgoto badOption;\n\t    }\n\t    c = option[1];\n\t    if (c == 'c' && !strncmp(\"-chars\", option, (size_t)length)) {\n\t\tvalue = CountIndices(textPtr, indexFromPtr, indexToPtr,\n\t\t\tCOUNT_CHARS);\n\t    } else if (c == 'd' && (length > 8)\n\t\t    && !strncmp(\"-displaychars\", option, (size_t)length)) {\n\t\tvalue = CountIndices(textPtr, indexFromPtr, indexToPtr,\n\t\t\tCOUNT_DISPLAY_CHARS);\n\t    } else if (c == 'd' && (length > 8)\n\t\t    && !strncmp(\"-displayindices\", option, (size_t)length)) {\n\t\tvalue = CountIndices(textPtr, indexFromPtr, indexToPtr,\n\t\t\tCOUNT_DISPLAY_INDICES);\n\t    } else if (c == 'd' && (length > 8)\n\t\t    && !strncmp(\"-displaylines\", option, (size_t)length)) {\n\t\tTkTextLine *fromPtr, *lastPtr;\n\t\tTkTextIndex index, index2;\n\n\t\tint compare = TkTextIndexCmp(indexFromPtr, indexToPtr);\n\t\tvalue = 0;\n\n\t\tif (compare == 0) {\n\t\t    goto countDone;\n\t\t}\n\n\t\tif (compare > 0) {\n\t\t    const TkTextIndex *tmpPtr = indexFromPtr;\n\n\t\t    indexFromPtr = indexToPtr;\n\t\t    indexToPtr = tmpPtr;\n\t\t}\n\n\t\tlastPtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t\ttextPtr,\n\t\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree,textPtr));\n\t\tfromPtr = indexFromPtr->linePtr;\n\t\tif (fromPtr == lastPtr) {\n\t\t    goto countDone;\n\t\t}\n\n\t\t/*\n\t\t * Caution: we must NEVER call TkTextUpdateOneLine with the\n\t\t * last artificial line in the widget.\n\t\t */\n\n\t\tindex = *indexFromPtr;\n\t\tindex.byteIndex = 0;\n\n\t\t/*\n\t\t * We're going to count up all display lines in the logical\n\t\t * line of 'indexFromPtr' up to, but not including the logical\n\t\t * line of 'indexToPtr' (except if this line is elided), and\n\t\t * then subtract off what came in too much from elided lines,\n\t\t * also subtract off what we didn't want from 'from' and add\n\t\t * on what we didn't count from 'to'.\n\t\t */\n\n\t\twhile (TkTextIndexCmp(&index,indexToPtr) < 0) {\n\t\t    value += TkTextUpdateOneLine(textPtr, index.linePtr,\n\t\t\t    0, &index, 0);\n\t\t}\n\n\t\tindex2 = index;\n\n\t\t/*\n\t\t * Now we need to adjust the count to:\n\t\t *   - subtract off the number of display lines between\n\t\t *     indexToPtr and index2, since we might have skipped past\n\t\t *     indexToPtr, if we have several logical lines in a\n\t\t *     single display line\n\t\t *   - subtract off the number of display lines overcounted\n\t\t *     in the first logical line\n\t\t *   - add on the number of display lines in the last logical\n\t\t *     line\n\t\t * This logic is still ok if both indexFromPtr and indexToPtr\n\t\t * are in the same logical line.\n\t\t */\n\n\t\tindex = *indexToPtr;\n\t\tindex.byteIndex = 0;\n\t\twhile (TkTextIndexCmp(&index,&index2) < 0) {\n\t\t    value -= TkTextUpdateOneLine(textPtr, index.linePtr,\n\t\t\t    0, &index, 0);\n\t\t}\n\t\tindex.linePtr = indexFromPtr->linePtr;\n\t\tindex.byteIndex = 0;\n\t\twhile (1) {\n\t\t    TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);\n\t\t    if (TkTextIndexCmp(&index,indexFromPtr) >= 0) {\n\t\t\tbreak;\n\t\t    }\n\t\t    TkTextIndexForwBytes(textPtr, &index, 1, &index);\n\t\t    value--;\n\n\t\t}\n\t\tif (indexToPtr->linePtr != lastPtr) {\n\t\t    index.linePtr = indexToPtr->linePtr;\n\t\t    index.byteIndex = 0;\n\t\t    while (1) {\n\t\t\tTkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);\n\t\t\tif (TkTextIndexCmp(&index,indexToPtr) >= 0) {\n\t\t\t    break;\n\t\t\t}\n\t\t\tTkTextIndexForwBytes(textPtr, &index, 1, &index);\n\t\t\tvalue++;\n\t\t    }\n\t\t}\n\n\t\tif (compare > 0) {\n\t\t    value = -value;\n\t\t}\n\t    } else if (c == 'i'\n\t\t    && !strncmp(\"-indices\", option, (size_t)length)) {\n\t\tvalue = CountIndices(textPtr, indexFromPtr, indexToPtr,\n\t\t\tCOUNT_INDICES);\n\t    } else if (c == 'l'\n\t\t    && !strncmp(\"-lines\", option, (size_t)length)) {\n\t\tvalue = TkBTreeLinesTo(textPtr, indexToPtr->linePtr)\n\t\t\t- TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);\n\t    } else if (c == 'u'\n\t\t    && !strncmp(\"-update\", option, (size_t)length)) {\n\t\tupdate = 1;\n\t\tcontinue;\n\t    } else if (c == 'x'\n\t\t    && !strncmp(\"-xpixels\", option, (size_t)length)) {\n\t\tint x1, x2;\n\t\tTkTextIndex index;\n\n\t\tindex = *indexFromPtr;\n\t\tTkTextFindDisplayLineEnd(textPtr, &index, 0, &x1);\n\t\tindex = *indexToPtr;\n\t\tTkTextFindDisplayLineEnd(textPtr, &index, 0, &x2);\n\t\tvalue = x2 - x1;\n\t    } else if (c == 'y'\n\t\t    && !strncmp(\"-ypixels\", option, (size_t)length)) {\n\t\tif (update) {\n\t\t    TkTextUpdateLineMetrics(textPtr,\n\t\t\t    TkBTreeLinesTo(textPtr, indexFromPtr->linePtr),\n\t\t\t    TkBTreeLinesTo(textPtr, indexToPtr->linePtr), -1);\n\t\t}\n\t\tvalue = TkTextIndexYPixels(textPtr, indexToPtr)\n\t\t\t- TkTextIndexYPixels(textPtr, indexFromPtr);\n\t    } else {\n\t\tgoto badOption;\n\t    }\n\n\tcountDone:\n\t    found++;\n\t    if (found == 1) {\n\t\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(value));\n\t    } else {\n\t\tif (found == 2) {\n\t\t    /*\n\t\t     * Move the first item we put into the result into the\n\t\t     * first element of the list object.\n\t\t     */\n\n\t\t    objPtr = Tcl_NewObj();\n\t\t    Tcl_ListObjAppendElement(NULL, objPtr,\n\t\t\t    Tcl_GetObjResult(interp));\n\t\t}\n\t\tTcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(value));\n\t    }\n\t}\n\n\tif (found == 0) {\n\t    /*\n\t     * Use the default '-indices'.\n\t     */\n\n\t    Tcl_Size value = CountIndices(textPtr, indexFromPtr, indexToPtr,\n\t\t    COUNT_INDICES);\n\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value));\n\t} else if (found > 1) {\n\t    Tcl_SetObjResult(interp, objPtr);\n\t}\n\tbreak;\n\n    badOption:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad option \\\"%s\\\": must be -chars, -displaychars, \"\n\t\t\"-displayindices, -displaylines, -indices, -lines, -update, \"\n\t\t\"-xpixels, or -ypixels\", Tcl_GetString(objv[i])));\n\tTcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"INDEX_OPTION\", (char *)NULL);\n\tresult = TCL_ERROR;\n\tgoto done;\n    }\n    case TEXT_DEBUG:\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"boolean\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(tkBTreeDebug));\n\t} else {\n\t    if (Tcl_GetBooleanFromObj(interp, objv[2],\n\t\t    &tkBTreeDebug) != TCL_OK) {\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    tkTextDebug = tkBTreeDebug;\n\t}\n\tbreak;\n    case TEXT_DELETE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index1 ?index2 ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (textPtr->state != TK_TEXT_STATE_DISABLED) {\n\t    if (objc < 5) {\n\t\t/*\n\t\t * Simple case requires no predetermination of indices.\n\t\t */\n\n\t\tconst TkTextIndex *indexPtr1, *indexPtr2;\n\n\t\t/*\n\t\t * Parse the starting and stopping indices.\n\t\t */\n\n\t\tindexPtr1 = TkTextGetIndexFromObj(textPtr->interp, textPtr,\n\t\t\tobjv[2]);\n\t\tif (indexPtr1 == NULL) {\n\t\t    result = TCL_ERROR;\n\t\t    goto done;\n\t\t}\n\t\tif (objc == 4) {\n\t\t    indexPtr2 = TkTextGetIndexFromObj(textPtr->interp,\n\t\t\t    textPtr, objv[3]);\n\t\t    if (indexPtr2 == NULL) {\n\t\t\tresult = TCL_ERROR;\n\t\t\tgoto done;\n\t\t    }\n\t\t} else {\n\t\t    indexPtr2 = NULL;\n\t\t}\n\t\tDeleteIndexRange(NULL, textPtr, indexPtr1, indexPtr2, 1);\n\t    } else {\n\t\t/*\n\t\t * Multi-index pair case requires that we prevalidate the\n\t\t * indices and sort from last to first so that deletes occur\n\t\t * in the exact (unshifted) text. It also needs to handle\n\t\t * partial and fully overlapping ranges. We have to do this\n\t\t * with multiple passes.\n\t\t */\n\n\t\tTkTextIndex *indices, *ixStart, *ixEnd, *lastStart;\n\t\tchar *useIdx;\n\t\tTcl_Size i;\n\n\t\tobjc -= 2;\n\t\tobjv += 2;\n\t\tindices = (TkTextIndex *)Tcl_Alloc(((size_t)objc + 1) * sizeof(TkTextIndex));\n\n\t\t/*\n\t\t * First pass verifies that all indices are valid.\n\t\t */\n\n\t\tfor (i = 0; i < objc; i++) {\n\t\t    const TkTextIndex *indexPtr =\n\t\t\t    TkTextGetIndexFromObj(interp, textPtr, objv[i]);\n\n\t\t    if (indexPtr == NULL) {\n\t\t\tresult = TCL_ERROR;\n\t\t\tTcl_Free(indices);\n\t\t\tgoto done;\n\t\t    }\n\t\t    indices[i] = *indexPtr;\n\t\t}\n\n\t\t/*\n\t\t * Pad out the pairs evenly to make later code easier.\n\t\t */\n\n\t\tif (objc & 1) {\n\t\t    indices[i] = indices[i-1];\n\t\t    TkTextIndexForwChars(NULL, &indices[i], 1, &indices[i],\n\t\t\t    COUNT_INDICES);\n\t\t    objc++;\n\t\t}\n\t\tuseIdx = (char *)Tcl_Alloc(((size_t)objc));\n\t\tmemset(useIdx, 0, (size_t)objc);\n\n\t\t/*\n\t\t * Do a decreasing order sort so that we delete the end ranges\n\t\t * first to maintain index consistency.\n\t\t */\n\n\t\tqsort(indices, (size_t) objc / 2,\n\t\t\t2 * sizeof(TkTextIndex), TextIndexSortProc);\n\t\tlastStart = NULL;\n\n\t\t/*\n\t\t * Second pass will handle bogus ranges (end < start) and\n\t\t * overlapping ranges.\n\t\t */\n\n\t\tfor (i = 0; i < objc; i += 2) {\n\t\t    ixStart = &indices[i];\n\t\t    ixEnd = &indices[i+1];\n\t\t    if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (lastStart) {\n\t\t\tif (TkTextIndexCmp(ixStart, lastStart) == 0) {\n\t\t\t    /*\n\t\t\t     * Start indices were equal, and the sort placed\n\t\t\t     * the longest range first, so skip this one.\n\t\t\t     */\n\n\t\t\t    continue;\n\t\t\t} else if (TkTextIndexCmp(lastStart, ixEnd) < 0) {\n\t\t\t    /*\n\t\t\t     * The next pair has a start range before the end\n\t\t\t     * point of the last range. Constrain the delete\n\t\t\t     * range, but use the pointer values.\n\t\t\t     */\n\n\t\t\t    *ixEnd = *lastStart;\n\t\t\t    if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {\n\t\t\t\tcontinue;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t    lastStart = ixStart;\n\t\t    useIdx[i] = 1;\n\t\t}\n\n\t\t/*\n\t\t * Final pass take the input from the previous and deletes the\n\t\t * ranges which are flagged to be deleted.\n\t\t */\n\n\t\tfor (i = 0; i < objc; i += 2) {\n\t\t    if (useIdx[i]) {\n\t\t\t/*\n\t\t\t * We don't need to check the return value because all\n\t\t\t * indices are preparsed above.\n\t\t\t */\n\n\t\t\tDeleteIndexRange(NULL, textPtr, &indices[i],\n\t\t\t\t&indices[i+1], 1);\n\t\t    }\n\t\t}\n\t\tTcl_Free(indices);\n\t    }\n\t}\n\tbreak;\n    case TEXT_DLINEINFO: {\n\tint x, y, width, height, base;\n\tconst TkTextIndex *indexPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tif (indexPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, &height,\n\t\t&base) == 0) {\n\t    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);\n\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));\n\t    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(base));\n\n\t    Tcl_SetObjResult(interp, listObj);\n\t}\n\tbreak;\n    }\n    case TEXT_DUMP:\n\tresult = TextDumpCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_EDIT:\n\tresult = TextEditCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_GET: {\n\tTcl_Obj *objPtr = NULL;\n\tTcl_Size i;\n\tint found = 0, visible = 0;\n\tconst char *name;\n\tTcl_Size length;\n\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"?-displaychars? ?--? index1 ?index2 ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\t/*\n\t * Simple, restrictive argument parsing. The only options are -- and\n\t * -displaychars (or any unique prefix).\n\t */\n\n\ti = 2;\n\tif (objc > 3) {\n\t    name = Tcl_GetStringFromObj(objv[i], &length);\n\t    if (length > 1 && name[0] == '-') {\n\t\tif (strncmp(\"-displaychars\", name, (size_t)length) == 0) {\n\t\t    i++;\n\t\t    visible = 1;\n\t\t    name = Tcl_GetStringFromObj(objv[i], &length);\n\t\t}\n\t\tif ((i < objc-1) && (length == 2) && !strcmp(\"--\", name)) {\n\t\t    i++;\n\t\t}\n\t    }\n\t}\n\n\tfor (; i < objc; i += 2) {\n\t    const TkTextIndex *index1Ptr, *index2Ptr;\n\t    TkTextIndex index2;\n\n\t    index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i]);\n\t    if (index1Ptr == NULL) {\n\t\tif (objPtr) {\n\t\t    Tcl_DecrRefCount(objPtr);\n\t\t}\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\n\t    if (i+1 == objc) {\n\t\tTkTextIndexForwChars(NULL, index1Ptr, 1, &index2,\n\t\t\tCOUNT_INDICES);\n\t\tindex2Ptr = &index2;\n\t    } else {\n\t\tindex2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i+1]);\n\t\tif (index2Ptr == NULL) {\n\t\t    if (objPtr) {\n\t\t\tTcl_DecrRefCount(objPtr);\n\t\t    }\n\t\t    result = TCL_ERROR;\n\t\t    goto done;\n\t\t}\n\t    }\n\n\t    if (TkTextIndexCmp(index1Ptr, index2Ptr) < 0) {\n\t\t/*\n\t\t * We want to move the text we get from the window into the\n\t\t * result, but since this could in principle be a megabyte or\n\t\t * more, we want to do it efficiently!\n\t\t */\n\n\t\tTcl_Obj *get = TextGetText(textPtr, index1Ptr, index2Ptr,\n\t\t\tvisible);\n\n\t\tfound++;\n\t\tif (found == 1) {\n\t\t    Tcl_SetObjResult(interp, get);\n\t\t} else {\n\t\t    if (found == 2) {\n\t\t\t/*\n\t\t\t * Move the first item we put into the result into the\n\t\t\t * first element of the list object.\n\t\t\t */\n\n\t\t\tobjPtr = Tcl_NewObj();\n\t\t\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\t\t\tTcl_GetObjResult(interp));\n\t\t    }\n\t\t    Tcl_ListObjAppendElement(NULL, objPtr, get);\n\t\t}\n\t    }\n\t}\n\tif (found > 1) {\n\t    Tcl_SetObjResult(interp, objPtr);\n\t}\n\tbreak;\n    }\n    case TEXT_IMAGE:\n\tresult = TkTextImageCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_INDEX: {\n\tconst TkTextIndex *indexPtr;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\n\tindexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tif (indexPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tTcl_SetObjResult(interp, TkTextNewIndexObj(textPtr, indexPtr));\n\tbreak;\n    }\n    case TEXT_INSERT: {\n\tconst TkTextIndex *indexPtr;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"index chars ?tagList chars tagList ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tif (indexPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (textPtr->state != TK_TEXT_STATE_DISABLED) {\n\t    result = TextInsertCmd(NULL, textPtr, interp, objc-3, objv+3,\n\t\t    indexPtr, 1);\n\t}\n\tbreak;\n    }\n    case TEXT_MARK:\n\tresult = TkTextMarkCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_PEER:\n\tresult = TextPeerCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_PENDINGSYNC: {\n\tif (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tTcl_SetObjResult(interp,\n\t\tTcl_NewBooleanObj(TkTextPendingsync(textPtr)));\n\tbreak;\n    }\n    case TEXT_REPLACE: {\n\tconst TkTextIndex *indexFromPtr, *indexToPtr;\n\n\tif (objc < 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"index1 index2 chars ?tagList chars tagList ...?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);\n\tif (indexFromPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tindexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[3]);\n\tif (indexToPtr == NULL) {\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (TkTextIndexCmp(indexFromPtr, indexToPtr) > 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"index \\\"%s\\\" before \\\"%s\\\" in the text\",\n\t\t    Tcl_GetString(objv[3]), Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"INDEX_ORDER\", (char *)NULL);\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (textPtr->state != TK_TEXT_STATE_DISABLED) {\n\t    Tcl_Size lineNum;\n\t    Tcl_Size byteIndex;\n\t    TkTextIndex index;\n\n\t    /*\n\t     * The 'replace' operation is quite complex to do correctly,\n\t     * because we want a number of criteria to hold:\n\t     *\n\t     * 1.  The insertion point shouldn't move, unless it is within the\n\t     *\t   deleted range. In this case it should end up after the new\n\t     *\t   text.\n\t     *\n\t     * 2.  The window should not change the text it shows - should not\n\t     *\t   scroll vertically - unless the result of the replace is\n\t     *\t   that the insertion position which used to be on-screen is\n\t     *\t   now off-screen.\n\t     */\n\n\t    byteIndex = textPtr->topIndex.byteIndex;\n\t    lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr);\n\n\t    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n\t    if ((TkTextIndexCmp(indexFromPtr, &index) < 0)\n\t\t    && (TkTextIndexCmp(indexToPtr, &index) > 0)) {\n\t\t/*\n\t\t * The insertion point is inside the range to be replaced, so\n\t\t * we have to do some calculations to ensure it doesn't move\n\t\t * unnecessarily.\n\t\t */\n\n\t\tTcl_Size deleteInsertOffset, insertLength, indexFromLine, indexFromByteOffset;\n\t\tTcl_Size j;\n\n\t\tinsertLength = 0;\n\t\tfor (j = 4; j < objc; j += 2) {\n\t\t    insertLength += Tcl_GetCharLength(objv[j]);\n\t\t}\n\n\t\t/*\n\t\t * Calculate 'deleteInsertOffset' as an offset we will apply\n\t\t * to the insertion point after this operation.\n\t\t */\n\n\t\tdeleteInsertOffset = CountIndices(textPtr, indexFromPtr,\n\t\t\t&index, COUNT_CHARS);\n\t\tif (deleteInsertOffset > insertLength) {\n\t\t    deleteInsertOffset = insertLength;\n\t\t}\n\n\t\tindexFromLine = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);\n\t\tindexFromByteOffset = indexFromPtr->byteIndex;\n\n\t\tresult = TextReplaceCmd(textPtr, interp, indexFromPtr,\n\t\t\tindexToPtr, objc, objv, 0);\n\n\t\tif (result == TCL_OK) {\n\t\t    /*\n\t\t     * Move the insertion position to the correct place.\n\t\t     */\n\n\t\t    TkTextIndex indexTmp;\n\n\t\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, indexFromLine,\n\t\t\t    indexFromByteOffset, &indexTmp);\n\t\t    TkTextIndexForwChars(NULL, &indexTmp,\n\t\t\t    deleteInsertOffset, &index, COUNT_INDICES);\n\t\t    TkBTreeUnlinkSegment(textPtr->insertMarkPtr,\n\t\t\t    textPtr->insertMarkPtr->body.mark.linePtr);\n\t\t    TkBTreeLinkSegment(textPtr->insertMarkPtr, &index);\n\t\t}\n\t    } else {\n\t\tresult = TextReplaceCmd(textPtr, interp, indexFromPtr,\n\t\t\tindexToPtr, objc, objv, 1);\n\t    }\n\t    if (result == TCL_OK) {\n\t\t/*\n\t\t * Now ensure the top-line is in the right place.\n\t\t */\n\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineNum, byteIndex, &index);\n\t\tTkTextSetYView(textPtr, &index, TK_TEXT_NOPIXELADJUST);\n\t    }\n\t}\n\tbreak;\n    }\n    case TEXT_SCAN:\n\tresult = TkTextScanCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_SEARCH:\n\tresult = TextSearchCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_SEE:\n\tresult = TkTextSeeCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_SYNC: {\n\tif (objc == 4) {\n\t    Tcl_Obj *cmd = objv[3];\n\t    Tcl_Size len;\n\t    const char *option = Tcl_GetStringFromObj(objv[2], &len);\n\t    if (strncmp(option, \"-command\", (size_t)len)) {\n\t\tTcl_AppendResult(interp, \"wrong option \\\"\", option, \"\\\": should be \\\"-command\\\"\", (char *)NULL);\n\t\tresult = TCL_ERROR;\n\t\tgoto done;\n\t    }\n\t    Tcl_IncrRefCount(cmd);\n\t    if (TkTextPendingsync(textPtr)) {\n\t\tif (textPtr->afterSyncCmd) {\n\t\t    Tcl_DecrRefCount(textPtr->afterSyncCmd);\n\t\t}\n\t\ttextPtr->afterSyncCmd = cmd;\n\t    } else {\n\t\ttextPtr->afterSyncCmd = cmd;\n\t\tTcl_DoWhenIdle(TkTextRunAfterSyncCmd, textPtr);\n\t    }\n\t    break;\n\t} else if (objc != 2) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?-command command?\");\n\t    result = TCL_ERROR;\n\t    goto done;\n\t}\n\tif (textPtr->afterSyncCmd) {\n\t    Tcl_CancelIdleCall(TkTextRunAfterSyncCmd, textPtr);\n\t    Tcl_DecrRefCount(textPtr->afterSyncCmd);\n\t}\n\ttextPtr->afterSyncCmd = NULL;\n\tTkTextUpdateLineMetrics(textPtr, 0,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);\n\tbreak;\n    }\n    case TEXT_TAG:\n\tresult = TkTextTagCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_WINDOW:\n\tresult = TkTextWindowCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_XVIEW:\n\tresult = TkTextXviewCmd(textPtr, interp, objc, objv);\n\tbreak;\n    case TEXT_YVIEW:\n\tresult = TkTextYviewCmd(textPtr, interp, objc, objv);\n\tbreak;\n    }\n\n  done:\n    if (textPtr->refCount-- <= 1) {\n\tTcl_Free(textPtr);\n    }\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SharedTextObjCmd --\n *\n *\tThis function is invoked to process commands on the shared portion of\n *\ta text widget. Currently it is not actually exported as a Tcl command,\n *\tand is only used internally to process parts of undo/redo scripts.\n *\tSee the user documentation for 'text' for details on what it does -\n *\tthe only subcommands it currently supports are 'insert' and 'delete'.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation for \"text\".\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSharedTextObjCmd(\n    void *clientData,\t/* Information about shared test B-tree. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkSharedText *sharedPtr = (TkSharedText *)clientData;\n    int result = TCL_OK;\n    int index;\n\n    static const char *const optionStrings[] = {\n\t\"delete\", \"insert\", NULL\n    };\n    enum options {\n\tTEXT_DELETE, TEXT_INSERT\n    };\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case TEXT_DELETE:\n\tif (objc < 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"index1 ?index2 ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc < 5) {\n\t    /*\n\t     * Simple case requires no predetermination of indices.\n\t     */\n\n\t    TkTextIndex index1;\n\n\t    /*\n\t     * Parse the starting and stopping indices.\n\t     */\n\n\t    result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2],\n\t\t    &index1);\n\t    if (result != TCL_OK) {\n\t\treturn result;\n\t    }\n\t    if (objc == 4) {\n\t\tTkTextIndex index2;\n\n\t\tresult = TkTextSharedGetObjIndex(interp, sharedPtr, objv[3],\n\t\t\t&index2);\n\t\tif (result != TCL_OK) {\n\t\t    return result;\n\t\t}\n\t\tDeleteIndexRange(sharedPtr, NULL, &index1, &index2, 1);\n\t    } else {\n\t\tDeleteIndexRange(sharedPtr, NULL, &index1, NULL, 1);\n\t    }\n\t    return TCL_OK;\n\t} else {\n\t    /* Too many arguments */\n\t    return TCL_ERROR;\n\t}\n\tbreak;\n    case TEXT_INSERT: {\n\tTkTextIndex index1;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"index chars ?tagList chars tagList ...?\");\n\t    return TCL_ERROR;\n\t}\n\tresult = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2],\n\t\t&index1);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n\treturn TextInsertCmd(sharedPtr, NULL, interp, objc-3, objv+3, &index1,\n\t\t1);\n    }\n    default:\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextPeerCmd --\n *\n *\tThis function is invoked to process the \"text peer\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTextPeerCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = textPtr->tkwin;\n    int index;\n\n    static const char *const peerOptionStrings[] = {\n\t\"create\", \"names\", NULL\n    };\n    enum peerOptions {\n\tPEER_CREATE, PEER_NAMES\n    };\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], peerOptionStrings,\n\t    sizeof(char *), \"peer option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum peerOptions) index) {\n    case PEER_CREATE:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"pathName ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\treturn CreateWidget(textPtr->sharedTextPtr, tkwin, interp, textPtr,\n\t\tobjc-2, objv+2);\n    case PEER_NAMES: {\n\tTkText *tPtr = textPtr->sharedTextPtr->peers;\n\tTcl_Obj *peersObj;\n\n\tif (objc > 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tpeersObj = Tcl_NewObj();\n\twhile (tPtr != NULL) {\n\t    if (tPtr != textPtr) {\n\t\tTcl_ListObjAppendElement(NULL, peersObj,\n\t\t\tTk_NewWindowObj(tPtr->tkwin));\n\t    }\n\t    tPtr = tPtr->next;\n\t}\n\tTcl_SetObjResult(interp, peersObj);\n    }\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextReplaceCmd --\n *\n *\tThis function is invoked to process part of the \"replace\" widget\n *\tcommand for text widgets.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *\tIf 'viewUpdate' is false, then textPtr->topIndex may no longer be a\n *\tvalid index after this function returns. The caller is responsible for\n *\tensuring a correct index is in place.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextReplaceCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    const TkTextIndex *indexFromPtr,\n\t\t\t\t/* Index from which to replace. */\n    const TkTextIndex *indexToPtr,\n\t\t\t\t/* Index to which to replace. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    int viewUpdate)\t\t/* Update vertical view if set. */\n{\n    /*\n     * Perform the deletion and insertion, but ensure no undo-separator is\n     * placed between the two operations. Since we are using the helper\n     * functions 'DeleteIndexRange' and 'TextInsertCmd' we have to pretend\n     * that the autoSeparators setting is off, so that we don't get an\n     * undo-separator between the delete and insert.\n     */\n\n    bool origAutoSep = textPtr->sharedTextPtr->autoSeparators;\n    int result;\n\tTcl_Size lineNumber;\n    TkTextIndex indexTmp;\n\n    if (textPtr->sharedTextPtr->undo) {\n\ttextPtr->sharedTextPtr->autoSeparators = false;\n\tif (origAutoSep &&\n\t\ttextPtr->sharedTextPtr->lastEditMode!=TK_TEXT_EDIT_REPLACE) {\n\t    TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);\n\t}\n    }\n\n    /*\n     * Must save and restore line in indexFromPtr based on line number; can't\n     * keep the line itself as that might be eliminated/invalidated when\n     * deleting the range. [Bug 1602537]\n     */\n\n    indexTmp = *indexFromPtr;\n    lineNumber = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr);\n    DeleteIndexRange(NULL, textPtr, indexFromPtr, indexToPtr, viewUpdate);\n    indexTmp.linePtr = TkBTreeFindLine(indexTmp.tree, textPtr, lineNumber);\n    result = TextInsertCmd(NULL, textPtr, interp, objc-4, objv+4,\n\t    &indexTmp, viewUpdate);\n\n    if (textPtr->sharedTextPtr->undo) {\n\ttextPtr->sharedTextPtr->lastEditMode = TK_TEXT_EDIT_REPLACE;\n\ttextPtr->sharedTextPtr->autoSeparators = origAutoSep;\n    }\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextIndexSortProc --\n *\n *\tThis function is called by qsort when sorting an array of indices in\n *\t*decreasing* order (last to first).\n *\n * Results:\n *\tThe return value is -1 if the first argument should be before the\n *\tsecond element, 0 if it's equivalent, and 1 if it should be after the\n *\tsecond element.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextIndexSortProc(\n    const void *first,\t\t/* Elements to be compared. */\n    const void *second)\n{\n    TkTextIndex *pair1 = (TkTextIndex *) first;\n    TkTextIndex *pair2 = (TkTextIndex *) second;\n    int cmp = TkTextIndexCmp(&pair1[1], &pair2[1]);\n\n    if (cmp == 0) {\n\t/*\n\t * If the first indices were equal, we want the second index of the\n\t * pair also to be the greater. Use pointer magic to access the second\n\t * index pair.\n\t */\n\n\tcmp = TkTextIndexCmp(&pair1[0], &pair2[0]);\n    }\n    if (cmp > 0) {\n\treturn -1;\n    } else if (cmp < 0) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyText --\n *\n *\tThis function is invoked when we receive a destroy event to clean up\n *\tthe internal structure of a text widget. We will free up most of the\n *\tinternal structure and delete the associated Tcl command. If there are\n *\tno outstanding references to the widget, we also free up the textPtr\n *\titself.\n *\n *\tThe widget has already been flagged as deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEither everything or almost everything associated with the text is\n *\tfreed up.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyText(\n    TkText *textPtr)\t\t/* Info about text widget. */\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n    TkTextTag *tagPtr;\n    TkSharedText *sharedTextPtr = textPtr->sharedTextPtr;\n\n    /*\n     * Free up all the stuff that requires special handling. We have already\n     * called let Tk_FreeConfigOptions to handle all the standard\n     * option-related stuff (and so none of that exists when we are called).\n     * Special note: free up display-related information before deleting the\n     * B-tree, since display-related stuff may refer to stuff in the B-tree.\n     */\n\n    TkTextFreeDInfo(textPtr);\n    textPtr->dInfoPtr = NULL;\n\n    /*\n     * Remove ourselves from the peer list.\n     */\n\n    if (sharedTextPtr->peers == textPtr) {\n\tsharedTextPtr->peers = textPtr->next;\n    } else {\n\tTkText *nextPtr = sharedTextPtr->peers;\n\twhile (nextPtr != NULL) {\n\t    if (nextPtr->next == textPtr) {\n\t\tnextPtr->next = textPtr->next;\n\t\tbreak;\n\t    }\n\t    nextPtr = nextPtr->next;\n\t}\n    }\n\n    /*\n     * Always clean up the widget-specific tags first. Common tags (i.e. most)\n     * will only be cleaned up when the shared structure is cleaned up.\n     *\n     * We also need to clean up widget-specific marks ('insert', 'current'),\n     * since otherwise marks will never disappear from the B-tree.\n     */\n\n    TkTextDeleteTag(textPtr, textPtr->selTagPtr);\n    TkBTreeUnlinkSegment(textPtr->insertMarkPtr,\n\t    textPtr->insertMarkPtr->body.mark.linePtr);\n    Tcl_Free(textPtr->insertMarkPtr);\n    TkBTreeUnlinkSegment(textPtr->currentMarkPtr,\n\t    textPtr->currentMarkPtr->body.mark.linePtr);\n    Tcl_Free(textPtr->currentMarkPtr);\n\n    /*\n     * Now we've cleaned up everything of relevance to us in the B-tree, so we\n     * disassociate outselves from it.\n     *\n     * When the refCount reaches zero, it's time to clean up the shared\n     * portion of the text widget.\n     */\n\n    if (sharedTextPtr->refCount-- > 1) {\n\tTkBTreeRemoveClient(sharedTextPtr->tree, textPtr);\n\n\t/*\n\t * Free up any embedded windows which belong to this widget.\n\t */\n\n\tfor (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->windowTable, &search);\n\t\thPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    TkTextEmbWindowClient *loop;\n\t    TkTextSegment *ewPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n\n\t    loop = ewPtr->body.ew.clients;\n\t    if (loop->textPtr == textPtr) {\n\t\tewPtr->body.ew.clients = loop->next;\n\t\tTkTextWinFreeClient(hPtr, loop);\n\t    } else {\n\t\tTkTextEmbWindowClient *client = ewPtr->body.ew.clients;\n\n\t\tclient = loop->next;\n\t\twhile (client != NULL) {\n\t\t    if (client->textPtr == textPtr) {\n\t\t\tloop->next = client->next;\n\t\t\tTkTextWinFreeClient(hPtr, client);\n\t\t\tbreak;\n\t\t    } else {\n\t\t\tloop = loop->next;\n\t\t    }\n\t\t    client = loop->next;\n\t\t}\n\t    }\n\t}\n    } else {\n\t/*\n\t * No need to call 'TkBTreeRemoveClient' first, since this will do\n\t * everything in one go, more quickly.\n\t */\n\n\tTkBTreeDestroy(sharedTextPtr->tree);\n\n\tfor (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);\n\t\thPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    tagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);\n\n\t    /*\n\t     * No need to use 'TkTextDeleteTag' since we've already removed\n\t     * the B-tree completely.\n\t     */\n\n\t    TkTextFreeTag(textPtr, tagPtr);\n\t}\n\tTcl_DeleteHashTable(&sharedTextPtr->tagTable);\n\tfor (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->markTable, &search);\n\t     hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_Free(Tcl_GetHashValue(hPtr));\n\t}\n\tTcl_DeleteHashTable(&sharedTextPtr->markTable);\n\tTkUndoFreeStack(sharedTextPtr->undoStack);\n\n\tTcl_DeleteHashTable(&sharedTextPtr->windowTable);\n\tTcl_DeleteHashTable(&sharedTextPtr->imageTable);\n\n\tif (sharedTextPtr->bindingTable != NULL) {\n\t    Tk_DeleteBindingTable(sharedTextPtr->bindingTable);\n\t}\n\tTcl_Free(sharedTextPtr);\n    }\n\n    if (textPtr->tabArrayPtr != NULL) {\n\tTcl_Free(textPtr->tabArrayPtr);\n    }\n    if (textPtr->insertBlinkHandler != NULL) {\n\tTcl_DeleteTimerHandler(textPtr->insertBlinkHandler);\n    }\n\n    textPtr->tkwin = NULL;\n    Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd);\n    if (textPtr->afterSyncCmd){\n\tTcl_DecrRefCount(textPtr->afterSyncCmd);\n\ttextPtr->afterSyncCmd = NULL;\n    }\n    if (textPtr->refCount-- <= 1) {\n\tTcl_Free(textPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureText --\n *\n *\tThis function is called to process an objv/objc list, plus the Tk\n *\toption database, in order to configure (or reconfigure) a text widget.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information, such as text string, colors, font, etc. get\n *\tset for textPtr; old resources get freed, if there were any.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nConfigureText(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkText *textPtr,\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_SavedOptions savedOptions;\n    bool oldExport = (textPtr->exportSelection) && (!Tcl_IsSafe(textPtr->interp));\n    int mask = 0;\n\n    if (Tk_SetOptions(interp, (char *) textPtr, textPtr->optionTable,\n\t    objc, objv, textPtr->tkwin, &savedOptions, &mask) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Copy down shared flags.\n     */\n\n    textPtr->sharedTextPtr->undo = textPtr->undo;\n    textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo;\n    textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators;\n\n    TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack,\n\t    textPtr->sharedTextPtr->maxUndo);\n\n    /*\n     * A few other options also need special processing, such as parsing the\n     * geometry and setting the background from a 3-D border.\n     */\n\n    Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border);\n\n    if (mask & TK_TEXT_LINE_RANGE) {\n\tTcl_Size start, end, current;\n\tTkTextIndex index1, index2, index3;\n\n\t/*\n\t * Line start and/or end have been adjusted. We need to validate the\n\t * first displayed line and arrange for re-layout.\n\t */\n\n\tTkBTreeClientRangeChanged(textPtr, textPtr->charHeight);\n\n\tif (textPtr->start != NULL) {\n\t    start = TkBTreeLinesTo(NULL, textPtr->start);\n\t} else {\n\t    start = 0;\n\t}\n\tif (textPtr->end != NULL) {\n\t    end = TkBTreeLinesTo(NULL, textPtr->end);\n\t} else {\n\t    end = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL);\n\t}\n\tif (start > end) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"-startline must be less than or equal to -endline\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"INDEX_ORDER\", (char *)NULL);\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t    return TCL_ERROR;\n\t}\n\tcurrent = TkBTreeLinesTo(NULL, textPtr->topIndex.linePtr);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0,\n\t\t    &index1);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0,\n\t\t    &index2);\n\tif (current < start || current > end) {\n\t    TkTextSearch search;\n\t    TkTextIndex first, last;\n\t    bool selChanged = false;\n\n\t    TkTextSetYView(textPtr, &index1, 0);\n\n\t    /*\n\t     * We may need to adjust the selection. So we have to check\n\t     * whether the \"sel\" tag was applied to anything outside the\n\t     * current start,end.\n\t     */\n\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, 0, 0,\n\t\t    &first);\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL,\n\t\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL),\n\t\t    0, &last);\n\t    TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);\n\t    if (!TkBTreeCharTagged(&first, textPtr->selTagPtr)\n\t\t    && !TkBTreeNextTag(&search)) {\n\t\t/* Nothing tagged with \"sel\" */\n\t    } else {\n\t\tTcl_Size line = TkBTreeLinesTo(NULL, search.curIndex.linePtr);\n\n\t\tif (line < start) {\n\t\t    selChanged = true;\n\t\t} else {\n\t\t    TkTextLine *linePtr = search.curIndex.linePtr;\n\n\t\t    while (TkBTreeNextTag(&search)) {\n\t\t\tlinePtr = search.curIndex.linePtr;\n\t\t    }\n\t\t    line = TkBTreeLinesTo(NULL, linePtr);\n\t\t    if (line >= end) {\n\t\t\tselChanged = true;\n\t\t    }\n\t\t}\n\t    }\n\t    if (selChanged) {\n\t\t/*\n\t\t * Send an event that the selection has changed, and abort any\n\t\t * partial-selections in progress.\n\t\t */\n\n\t\tTkTextSelectionEvent(textPtr);\n\t\ttextPtr->abortSelections = true;\n\t    }\n\t}\n\n\t/* Indices are potentially obsolete after changing -startline and/or\n\t * -endline, therefore increase the epoch.\n\t * Also, clamp the insert and current (unshared) marks to the new\n\t * -startline/-endline range limits of the widget. All other (shared)\n\t * marks are unchanged.\n\t * The return value of TkTextMarkNameToIndex does not need to be\n\t * checked: \"insert\" and \"current\" marks always exist, and the\n\t * purpose of the code below precisely is to move them inside the\n\t * -startline/-endline range.\n\t */\n\n\ttextPtr->sharedTextPtr->stateEpoch++;\n\tTkTextMarkNameToIndex(textPtr, \"insert\", &index3);\n\tif (TkTextIndexCmp(&index3, &index1) < 0) {\n\t    textPtr->insertMarkPtr = TkTextSetMark(textPtr, \"insert\", &index1);\n\t}\n\tif (TkTextIndexCmp(&index3, &index2) > 0) {\n\t    textPtr->insertMarkPtr = TkTextSetMark(textPtr, \"insert\", &index2);\n\t}\n\tTkTextMarkNameToIndex(textPtr, \"current\", &index3);\n\tif (TkTextIndexCmp(&index3, &index1) < 0) {\n\t    textPtr->currentMarkPtr = TkTextSetMark(textPtr, \"current\", &index1);\n\t}\n\tif (TkTextIndexCmp(&index3, &index2) > 0) {\n\t    textPtr->currentMarkPtr = TkTextSetMark(textPtr, \"current\", &index2);\n\t}\n    }\n\n    /*\n     * Parse tab stops.\n     */\n\n    if (textPtr->tabArrayPtr != NULL) {\n\tTcl_Free(textPtr->tabArrayPtr);\n\ttextPtr->tabArrayPtr = NULL;\n    }\n    if (textPtr->tabOptionObj != NULL) {\n\ttextPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin,\n\t\ttextPtr->tabOptionObj);\n\tif (textPtr->tabArrayPtr == NULL) {\n\t    Tcl_AddErrorInfo(interp,\"\\n    (while processing -tabs option)\");\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Make sure that configuration options are properly mirrored between the\n     * widget record and the \"sel\" tags. NOTE: we don't have to free up\n     * information during the mirroring; old information was freed when it was\n     * replaced in the widget record.\n     */\n\n    if (textPtr->selTagPtr->selBorder == NULL) {\n\ttextPtr->selTagPtr->border = textPtr->selBorder;\n    } else {\n\ttextPtr->selTagPtr->selBorder = textPtr->selBorder;\n    }\n    if (textPtr->selTagPtr->borderWidthObj != textPtr->selBorderWidthObj) {\n\ttextPtr->selTagPtr->borderWidthObj = textPtr->selBorderWidthObj;\n    }\n    if (textPtr->selTagPtr->selFgColor == NULL) {\n\ttextPtr->selTagPtr->fgColor = textPtr->selFgColorPtr;\n    } else {\n\ttextPtr->selTagPtr->selFgColor = textPtr->selFgColorPtr;\n    }\n    textPtr->selTagPtr->affectsDisplay = false;\n    textPtr->selTagPtr->affectsDisplayGeometry = false;\n    if ((textPtr->selTagPtr->elide >= 0)\n\t    || (textPtr->selTagPtr->tkfont != NULL)\n\t    || (textPtr->selTagPtr->justify != TK_JUSTIFY_NULL)\n\t    || (textPtr->selTagPtr->lMargin1Obj != NULL)\n\t    || (textPtr->selTagPtr->lMargin2Obj != NULL)\n\t    || (textPtr->selTagPtr->offsetObj != NULL)\n\t    || (textPtr->selTagPtr->rMarginObj != NULL)\n\t    || (textPtr->selTagPtr->spacing1Obj != NULL)\n\t    || (textPtr->selTagPtr->spacing2Obj != NULL)\n\t    || (textPtr->selTagPtr->spacing3Obj != NULL)\n\t    || (textPtr->selTagPtr->tabStringPtr != NULL)\n\t    || (textPtr->selTagPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR)\n\t    || (textPtr->selTagPtr->tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR)\n\t    || (textPtr->selTagPtr->wrapMode == TEXT_WRAPMODE_CHAR)\n\t    || (textPtr->selTagPtr->wrapMode == TEXT_WRAPMODE_NONE)\n\t    || (textPtr->selTagPtr->wrapMode == TEXT_WRAPMODE_WORD)) {\n\ttextPtr->selTagPtr->affectsDisplay = true;\n\ttextPtr->selTagPtr->affectsDisplayGeometry = true;\n    }\n    if ((textPtr->selTagPtr->border != NULL)\n\t    || (textPtr->selTagPtr->selBorder != NULL)\n\t    || (textPtr->selTagPtr->relief != TK_RELIEF_NULL)\n\t    || (textPtr->selTagPtr->bgStipple != None)\n\t    || (textPtr->selTagPtr->fgColor != NULL)\n\t    || (textPtr->selTagPtr->selFgColor != NULL)\n\t    || (textPtr->selTagPtr->fgStipple != None)\n\t    || (textPtr->selTagPtr->overstrike >= 0)\n\t    || (textPtr->selTagPtr->overstrikeColor != NULL)\n\t    || (textPtr->selTagPtr->underline >= 0)\n\t    || (textPtr->selTagPtr->underlineColor != NULL)\n\t    || (textPtr->selTagPtr->lMarginColor != NULL)\n\t    || (textPtr->selTagPtr->rMarginColor != NULL)) {\n\ttextPtr->selTagPtr->affectsDisplay = true;\n    }\n    TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, true);\n\n    /*\n     * Claim the selection if we've suddenly started exporting it and there\n     * are tagged characters.\n     */\n\n    if (textPtr->exportSelection && (!oldExport) && (!Tcl_IsSafe(textPtr->interp))) {\n\tTkTextSearch search;\n\tTkTextIndex first, last;\n\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t\t&first);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),\n\t\t0, &last);\n\tTkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);\n\tif (TkBTreeCharTagged(&first, textPtr->selTagPtr)\n\t\t|| TkBTreeNextTag(&search)) {\n\t    Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY, TkTextLostSelection,\n\t\t    textPtr);\n\t    textPtr->flags |= GOT_SELECTION;\n\t}\n    }\n\n    /*\n     * Account for state changes that would reenable blinking cursor state.\n     */\n\n    if (textPtr->flags & GOT_FOCUS) {\n\tTcl_DeleteTimerHandler(textPtr->insertBlinkHandler);\n\ttextPtr->insertBlinkHandler = NULL;\n\tTextBlinkProc(textPtr);\n    }\n\n    /*\n     * Register the desired geometry for the window, and arrange for the\n     * window to be redisplayed.\n     */\n\n    if (textPtr->width <= 0) {\n\ttextPtr->width = 1;\n    }\n    Tk_FreeSavedOptions(&savedOptions);\n    TextWorldChanged(textPtr, mask);\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TextWorldChangedCallback --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfigures all tags in the Text with a empty objc/objv, for the side\n *\teffect of causing all the items to recompute their geometry and to be\n *\tredisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nTextWorldChangedCallback(\n    void *instanceData)\t/* Information about widget. */\n{\n    TkText *textPtr = (TkText *)instanceData;\n\n    TextWorldChanged(textPtr, TK_TEXT_LINE_GEOMETRY);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TextWorldChanged --\n *\n *\tThis function is called when the world has changed in some way and the\n *\twidget needs to recompute all its graphics contexts and determine its\n *\tnew geometry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfigures all tags in the Text with a empty objc/objv, for the side\n *\teffect of causing all the items to recompute their geometry and to be\n *\tredisplayed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nTextWorldChanged(\n    TkText *textPtr,\t\t/* Information about widget. */\n    int mask)\t\t\t/* OR'd collection of bits showing what has\n\t\t\t\t * changed. */\n{\n    Tk_FontMetrics fm;\n    int border, height;\n    int oldCharHeight = textPtr->charHeight;\n    int padX, padY;\n    int spacing1, spacing3;\n    int borderWidth, highlightWidth;\n\n    textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, \"0\", 1);\n    if (textPtr->charWidth <= 0) {\n\ttextPtr->charWidth = 1;\n    }\n    Tk_GetFontMetrics(textPtr->tkfont, &fm);\n\n    textPtr->charHeight = fm.linespace;\n    if (textPtr->charHeight <= 0) {\n\ttextPtr->charHeight = 1;\n    }\n    if (textPtr->charHeight != oldCharHeight) {\n\tTkBTreeClientRangeChanged(textPtr, textPtr->charHeight);\n    }\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->spacing1Obj, &spacing1);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->spacing3Obj, &spacing3);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->heightObj, &height);\n    if (height < 1) {\n\theight = 1;\n    }\n    border = borderWidth + highlightWidth;\n    Tk_GeometryRequest(textPtr->tkwin,\n\t    textPtr->width * textPtr->charWidth + 2 * padX + 2 * border,\n\t    height * (fm.linespace + spacing1 + spacing3)\n\t\t    + 2 * padY + 2*border);\n\n    Tk_SetInternalBorderEx(textPtr->tkwin,\n\t    border + padX, border + padX, border + padY, border + padY);\n    if (textPtr->setGrid) {\n\tTk_SetGrid(textPtr->tkwin, textPtr->width, height,\n\t\ttextPtr->charWidth, textPtr->charHeight);\n    } else {\n\tTk_UnsetGrid(textPtr->tkwin);\n    }\n\n    TkTextRelayoutWindow(textPtr, mask);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TextEventProc --\n *\n *\tThis function is invoked by the Tk dispatcher on structure changes to\n *\ta text. For texts with 3D borders, this function is also invoked for\n *\texposures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up.\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTextEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t/* Information about event. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    TkTextIndex index, index2;\n    int highlightWidth;\n\n    if (eventPtr->type == Expose) {\n\tTkTextRedrawRegion(textPtr, eventPtr->xexpose.x,\n\t\teventPtr->xexpose.y, eventPtr->xexpose.width,\n\t\teventPtr->xexpose.height);\n    } else if (eventPtr->type == ConfigureNotify) {\n\tif ((textPtr->prevWidth != Tk_Width(textPtr->tkwin))\n\t\t|| (textPtr->prevHeight != Tk_Height(textPtr->tkwin))) {\n\t    int mask = 0;\n\n\t    if (textPtr->prevWidth != Tk_Width(textPtr->tkwin)) {\n\t\tmask = TK_TEXT_LINE_GEOMETRY;\n\t    }\n\t    TkTextRelayoutWindow(textPtr, mask);\n\t    textPtr->prevWidth = Tk_Width(textPtr->tkwin);\n\t    textPtr->prevHeight = Tk_Height(textPtr->tkwin);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * NOTE: we must zero out selBorder, selBorderWidthObj and\n\t * selFgColorPtr: they are duplicates of information in the \"sel\" tag,\n\t * which will be freed up when we delete all tags. Hence we don't want\n\t * the automatic config options freeing process to delete them as\n\t * well.\n\t */\n\n\ttextPtr->selBorder = NULL;\n\ttextPtr->selBorderWidthObj = NULL;\n\ttextPtr->selFgColorPtr = NULL;\n\tif (textPtr->setGrid) {\n\t    Tk_UnsetGrid(textPtr->tkwin);\n\t    textPtr->setGrid = false;\n\t}\n\tif (!(textPtr->flags & OPTIONS_FREED)) {\n\t    Tk_FreeConfigOptions(textPtr, textPtr->optionTable,\n\t\t    textPtr->tkwin);\n\t    textPtr->flags |= OPTIONS_FREED;\n\t}\n\ttextPtr->flags |= DESTROYED;\n\n\t/*\n\t * Call 'DestroyTest' to handle the deletion for us. The actual\n\t * textPtr may still exist after this, if there are some outstanding\n\t * references. But we have flagged it as DESTROYED just above, so\n\t * nothing will try to make use of it very extensively.\n\t */\n\n\tDestroyText(textPtr);\n    } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {\n\tif (eventPtr->xfocus.detail == NotifyInferior\n\t\t|| eventPtr->xfocus.detail == NotifyAncestor\n\t\t|| eventPtr->xfocus.detail == NotifyNonlinear) {\n\t    Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler);\n\t    if (eventPtr->type == FocusIn) {\n\t\ttextPtr->flags |= GOT_FOCUS | INSERT_ON;\n\t\tif (textPtr->insertOffTime != 0) {\n\t\t    textPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\t\t    textPtr->insertOnTime, TextBlinkProc, textPtr);\n\t\t}\n\t    } else {\n\t\ttextPtr->flags &= ~(GOT_FOCUS | INSERT_ON);\n\t\ttextPtr->insertBlinkHandler = NULL;\n\t    }\n\t    if (textPtr->inactiveSelBorder != textPtr->selBorder) {\n\t\tTkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr,\n\t\t\ttrue);\n\t    }\n\t    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n\t    TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);\n\n\t    /*\n\t     * While we wish to redisplay, no heights have changed, so no need\n\t     * to call TkTextInvalidateLineMetrics.\n\t     */\n\n\t    TkTextChanged(NULL, textPtr, &index, &index2);\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->highlightWidthObj, &highlightWidth);\n\t    if (highlightWidth > 0) {\n\t\tTkTextRedrawRegion(textPtr, 0, 0, highlightWidth, highlightWidth);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextCmdDeletedProc --\n *\n *\tThis function is invoked when a widget command is deleted. If the\n *\twidget isn't already in the process of being destroyed, this command\n *\tdestroys it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe widget is destroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTextCmdDeletedProc(\n    void *clientData)\t/* Pointer to widget record for widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    Tk_Window tkwin = textPtr->tkwin;\n\n    /*\n     * This function could be invoked either because the window was destroyed\n     * and the command was then deleted (in which this flag is already set) or\n     * because the command was deleted, and then this function destroys the\n     * widget.\n     */\n\n    if (!(textPtr->flags & DESTROYED)) {\n\tif (textPtr->setGrid) {\n\t    Tk_UnsetGrid(textPtr->tkwin);\n\t    textPtr->setGrid = false;\n\t}\n\ttextPtr->flags |= DESTROYED;\n\tTk_DestroyWindow(tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InsertChars --\n *\n *\tThis function implements most of the functionality of the \"insert\"\n *\twidget command.\n *\n * Results:\n *\tThe length of the inserted string.\n *\n * Side effects:\n *\tThe characters in \"stringPtr\" get added to the text just before the\n *\tcharacter indicated by \"indexPtr\".\n *\n *\tIf 'viewUpdate' is true, we may adjust the window contents'\n *\ty-position, and scrollbar setting.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nInsertChars(\n    TkSharedText *sharedTextPtr,\n    TkText *textPtr,\t\t/* Overall information about text widget. */\n    TkTextIndex *indexPtr,\t/* Where to insert new characters. May be\n\t\t\t\t * modified if the index is not valid for\n\t\t\t\t * insertion (e.g. if at \"end\"). */\n    Tcl_Obj *stringPtr,\t\t/* Null-terminated string containing new\n\t\t\t\t * information to add to text. */\n    bool viewUpdate)\t\t/* Update the view if set. */\n{\n    Tcl_Size lineIndex;\n    Tcl_Size length;\n    TkText *tPtr;\n    int *lineAndByteIndex;\n    int resetViewCount;\n    int pixels[2*PIXEL_CLIENTS];\n    const char *string = Tcl_GetStringFromObj(stringPtr, &length);\n\n    if (sharedTextPtr == NULL) {\n\tsharedTextPtr = textPtr->sharedTextPtr;\n    }\n\n    /*\n     * Don't allow insertions on the last (dummy) line of the text. This is\n     * the only place in this function where the indexPtr is modified.\n     */\n\n    lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);\n    if (lineIndex == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) {\n\tlineIndex--;\n\tTkTextMakeByteIndex(sharedTextPtr->tree, textPtr, lineIndex, 1000000,\n\t\tindexPtr);\n    }\n\n    /*\n     * Notify the display module that lines are about to change, then do the\n     * insertion. If the insertion occurs on the top line of the widget\n     * (textPtr->topIndex), then we have to recompute topIndex after the\n     * insertion, since the insertion could invalidate it.\n     */\n\n    resetViewCount = 0;\n    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {\n\tlineAndByteIndex = (int *)Tcl_Alloc(sizeof(int) * 2 * sharedTextPtr->refCount);\n    } else {\n\tlineAndByteIndex = pixels;\n    }\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\tlineAndByteIndex[resetViewCount] = -1;\n\tif (indexPtr->linePtr == tPtr->topIndex.linePtr) {\n\t    lineAndByteIndex[resetViewCount] =\n\t\t    TkBTreeLinesTo(tPtr, indexPtr->linePtr);\n\t    lineAndByteIndex[resetViewCount+1] = tPtr->topIndex.byteIndex;\n\t    if (lineAndByteIndex[resetViewCount+1] > indexPtr->byteIndex) {\n\t\tlineAndByteIndex[resetViewCount+1] += length;\n\t    }\n\t}\n\tresetViewCount += 2;\n    }\n\n    TkTextChanged(sharedTextPtr, NULL, indexPtr, indexPtr);\n\n    sharedTextPtr->stateEpoch++;\n\n    TkBTreeInsertChars(sharedTextPtr->tree, indexPtr, string);\n\n    /*\n     * Push the insertion on the undo stack, and update the modified status of\n     * the widget.\n     */\n\n    if (length > 0) {\n\tif (sharedTextPtr->undo) {\n\t    TkTextIndex toIndex;\n\n\t    if (sharedTextPtr->autoSeparators &&\n\t\tsharedTextPtr->lastEditMode != TK_TEXT_EDIT_INSERT) {\n\t\tTkUndoInsertUndoSeparator(sharedTextPtr->undoStack);\n\t    }\n\n\t    sharedTextPtr->lastEditMode = TK_TEXT_EDIT_INSERT;\n\n\t    TkTextIndexForwBytes(textPtr, indexPtr, length, &toIndex);\n\t    TextPushUndoAction(textPtr, stringPtr, 1, indexPtr, &toIndex);\n\t}\n\n\tUpdateDirtyFlag(sharedTextPtr);\n    }\n\n    resetViewCount = 0;\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\tif (lineAndByteIndex[resetViewCount] != -1) {\n\t    if ((tPtr != textPtr) || viewUpdate) {\n\t\tTkTextIndex newTop;\n\n\t\tTkTextMakeByteIndex(sharedTextPtr->tree, tPtr,\n\t\t\tlineAndByteIndex[resetViewCount], 0, &newTop);\n\t\tTkTextIndexForwBytes(tPtr, &newTop,\n\t\t\tlineAndByteIndex[resetViewCount+1], &newTop);\n\t\tTkTextSetYView(tPtr, &newTop, 0);\n\t    }\n\t}\n\tresetViewCount += 2;\n    }\n    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {\n\tTcl_Free(lineAndByteIndex);\n    }\n\n    /*\n     * Invalidate any selection retrievals in progress, and send an event\n     * that the selection changed if that is the case.\n     */\n\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\tif (TkBTreeCharTagged(indexPtr, tPtr->selTagPtr)) {\n\t    TkTextSelectionEvent(tPtr);\n\t}\n\ttPtr->abortSelections = true;\n    }\n\n    /*\n     * For convenience, return the length of the string.\n     */\n\n    return length;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextPushUndoAction --\n *\n *\tShared by insert and delete actions. Stores the appropriate scripts\n *\tinto our undo stack. We will add a single refCount to the 'undoString'\n *\tobject, so, if it previously had a refCount of zero, the caller should\n *\tnot free it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tItems pushed onto stack.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTextPushUndoAction(\n    TkText *textPtr,\t\t/* Overall information about text widget. */\n    Tcl_Obj *undoString,\t/* New text. */\n    int insert,\t\t\t/* 1 if insert, else delete. */\n    const TkTextIndex *index1Ptr,\n\t\t\t\t/* Index describing first location. */\n    const TkTextIndex *index2Ptr)\n\t\t\t\t/* Index describing second location. */\n{\n    TkUndoSubAtom *iAtom, *dAtom;\n    bool canUndo, canRedo;\n    char lMarkName[16 + TCL_INTEGER_SPACE] = \"tk::undoMarkL\";\n    char rMarkName[16 + TCL_INTEGER_SPACE] = \"tk::undoMarkR\";\n    char stringUndoMarkId[TCL_INTEGER_SPACE] = \"\";\n\n    /*\n     * Create the helpers.\n     */\n\n    Tcl_Obj *seeInsertObj = Tcl_NewObj();\n    Tcl_Obj *markSet1InsertObj = Tcl_NewObj();\n    Tcl_Obj *markSet2InsertObj = NULL;\n    Tcl_Obj *insertCmdObj = Tcl_NewObj();\n    Tcl_Obj *deleteCmdObj = Tcl_NewObj();\n    Tcl_Obj *markSetLUndoMarkCmdObj = Tcl_NewObj();\n    Tcl_Obj *markSetRUndoMarkCmdObj = NULL;\n    Tcl_Obj *markGravityLUndoMarkCmdObj = Tcl_NewObj();\n    Tcl_Obj *markGravityRUndoMarkCmdObj = NULL;\n\n    /*\n     * Get the index positions.\n     */\n\n    Tcl_Obj *index1Obj = TkTextNewIndexObj(NULL, index1Ptr);\n    Tcl_Obj *index2Obj = TkTextNewIndexObj(NULL, index2Ptr);\n\n    /*\n     * These need refCounts, because they are used more than once below.\n     */\n\n    Tcl_IncrRefCount(seeInsertObj);\n    Tcl_IncrRefCount(index1Obj);\n    Tcl_IncrRefCount(index2Obj);\n\n    Tcl_ListObjAppendElement(NULL, seeInsertObj,\n\t    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, seeInsertObj, Tcl_NewStringObj(\"see\", 3));\n    Tcl_ListObjAppendElement(NULL, seeInsertObj,\n\t    Tcl_NewStringObj(\"insert\", 6));\n\n    Tcl_ListObjAppendElement(NULL, markSet1InsertObj,\n\t    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markSet1InsertObj,\n\t    Tcl_NewStringObj(\"mark\", 4));\n    Tcl_ListObjAppendElement(NULL, markSet1InsertObj,\n\t    Tcl_NewStringObj(\"set\", 3));\n    Tcl_ListObjAppendElement(NULL, markSet1InsertObj,\n\t    Tcl_NewStringObj(\"insert\", 6));\n    markSet2InsertObj = Tcl_DuplicateObj(markSet1InsertObj);\n    Tcl_ListObjAppendElement(NULL, markSet1InsertObj, index1Obj);\n    Tcl_ListObjAppendElement(NULL, markSet2InsertObj, index2Obj);\n\n    Tcl_ListObjAppendElement(NULL, insertCmdObj,\n\t    Tcl_NewStringObj(\"insert\", 6));\n    Tcl_ListObjAppendElement(NULL, insertCmdObj, index1Obj);\n\n    /*\n     * Only use of 'undoString' is here.\n     */\n\n    Tcl_ListObjAppendElement(NULL, insertCmdObj, undoString);\n\n    Tcl_ListObjAppendElement(NULL, deleteCmdObj,\n\t    Tcl_NewStringObj(\"delete\", 6));\n    Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj);\n    Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj);\n\n    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"mark\", 4));\n    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"set\", 3));\n    markSetRUndoMarkCmdObj = Tcl_DuplicateObj(markSetLUndoMarkCmdObj);\n    textPtr->sharedTextPtr->undoMarkId++;\n    snprintf(stringUndoMarkId, TCL_INTEGER_SPACE, \"%\" TCL_Z_MODIFIER \"d\", textPtr->sharedTextPtr->undoMarkId);\n    strcat(lMarkName, stringUndoMarkId);\n    strcat(rMarkName, stringUndoMarkId);\n    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(lMarkName, TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj,\n\t    Tcl_NewStringObj(rMarkName, TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, index1Obj);\n    Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, index2Obj);\n\n    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"mark\", 4));\n    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"gravity\", 7));\n    markGravityRUndoMarkCmdObj = Tcl_DuplicateObj(markGravityLUndoMarkCmdObj);\n    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(lMarkName, TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj,\n\t    Tcl_NewStringObj(rMarkName, TCL_INDEX_NONE));\n    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"left\", 4));\n    Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj,\n\t    Tcl_NewStringObj(\"right\", 5));\n\n    /*\n     * Note: we don't wish to use textPtr->widgetCmd in these callbacks\n     * because if we delete the textPtr, but peers still exist, we will then\n     * have references to a non-existent Tcl_Command in the undo stack, which\n     * will lead to crashes later. Also, the behaviour of the widget w.r.t.\n     * bindings (%W substitutions) always uses the widget path name, so there\n     * is no good reason the undo stack should do otherwise.\n     *\n     * For the 'insert' and 'delete' actions, we have to register a functional\n     * callback, because these actions are defined to operate on the\n     * underlying data shared by all peers.\n     */\n\n    iAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,\n\t    insertCmdObj, NULL);\n    TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom);\n    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom);\n    TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, iAtom);\n    TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, iAtom);\n    TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, iAtom);\n    TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, iAtom);\n\n    dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,\n\t    deleteCmdObj, NULL);\n    TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom);\n    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom);\n    TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, dAtom);\n    TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, dAtom);\n    TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, dAtom);\n    TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, dAtom);\n\n    Tcl_DecrRefCount(seeInsertObj);\n    Tcl_DecrRefCount(index1Obj);\n    Tcl_DecrRefCount(index2Obj);\n\n    canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);\n    canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);\n\n    /*\n     * Depending whether the action is to insert or delete, we provide the\n     * appropriate second and third arguments to TkUndoPushAction. (The first\n     * is the 'actionCommand', and the second the 'revertCommand').\n     */\n\n    if (insert) {\n\tTkUndoPushAction(textPtr->sharedTextPtr->undoStack, iAtom, dAtom);\n    } else {\n\tTkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);\n    }\n\n    if (!canUndo || canRedo) {\n\tGenerateUndoStackEvent(textPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextUndoRedoCallback --\n *\n *\tThis function is registered with the generic undo/redo code to handle\n *\t'insert' and 'delete' actions on all text widgets. We cannot perform\n *\tthose actions on any particular text widget, because that text widget\n *\tmight have been deleted by the time we get here.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tWill insert or delete text, depending on the first word contained in\n *\tobjPtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTextUndoRedoCallback(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    void *clientData,\t/* Passed from undo code, but contains our\n\t\t\t\t * shared text data structure. */\n    Tcl_Obj *objPtr)\t\t/* Arguments of a command to be handled by the\n\t\t\t\t * shared text data structure. */\n{\n    TkSharedText *sharedPtr = (TkSharedText *)clientData;\n    int res;\n    Tcl_Size objc;\n    Tcl_Obj **objv;\n    TkText *textPtr;\n\n    res = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);\n    if (res != TCL_OK) {\n\treturn res;\n    }\n\n    /*\n     * If possible, use a real text widget to perform the undo/redo action\n     * (i.e. insertion or deletion of text). This provides maximum\n     * compatibility with older versions of Tk, in which the user may rename\n     * the text widget to allow capture of undo or redo actions.\n     *\n     * In particular, this sorting of capture is useful in text editors based\n     * on the Tk text widget, which need to know which new text needs\n     * re-coloring.\n     *\n     * It would be better if the text widget provided some other mechanism to\n     * allow capture of this information (\"What has just changed in the text\n     * widget?\"). What we have here is not entirely satisfactory under all\n     * circumstances.\n     */\n\n    textPtr = sharedPtr->peers;\n    while (textPtr != NULL) {\n\tif (textPtr->start == NULL && textPtr->end == NULL) {\n\t    Tcl_Obj *cmdNameObj, *evalObj;\n\n\t    evalObj = Tcl_NewObj();\n\t    Tcl_IncrRefCount(evalObj);\n\n\t    /*\n\t     * We might wish to use the real, current command-name for the\n\t     * widget, but this will break any code that has over-ridden the\n\t     * widget, and is expecting to observe the insert/delete actions\n\t     * which are caused by undo/redo operations.\n\t     *\n\t     * cmdNameObj = Tcl_NewObj();\n\t     * Tcl_GetCommandFullName(interp, textPtr->widgetCmd, cmdNameObj);\n\t     *\n\t     * While such interception is not explicitly documented as\n\t     * supported, it does occur, and so until we can provide some\n\t     * alternative mechanism for such code to do what it needs, we\n\t     * allow it to take place here.\n\t     */\n\n\t    cmdNameObj = Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), TCL_INDEX_NONE);\n\t    Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj);\n\t    Tcl_ListObjAppendList(NULL, evalObj, objPtr);\n\t    res = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL);\n\t    Tcl_DecrRefCount(evalObj);\n\t    return res;\n\t}\n\ttextPtr = textPtr->next;\n    }\n\n    /*\n     * If there's no current text widget which shows everything, then we fall\n     * back on acting directly. This means there is no way to intercept from\n     * the Tcl level.\n     */\n\n    return SharedTextObjCmd(sharedPtr, interp, objc+1, objv-1);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CountIndices --\n *\n *\tThis function implements most of the functionality of the \"count\"\n *\twidget command.\n *\n *\tNote that 'textPtr' is only used if we need to check for elided\n *\tattributes, i.e. if type is COUNT_DISPLAY_INDICES or\n *\tCOUNT_DISPLAY_CHARS\n *\n * Results:\n *\tReturns the number of characters in the range.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nCountIndices(\n    const TkText *textPtr,\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr1,\n\t\t\t\t/* Index describing location of first\n\t\t\t\t * character to delete. */\n    const TkTextIndex *indexPtr2,\n\t\t\t\t/* Index describing location of last character\n\t\t\t\t * to delete. NULL means just delete the one\n\t\t\t\t * character given by indexPtr1. */\n    TkTextCountType type)\t/* The kind of indices to count. */\n{\n    /*\n     * Order the starting and stopping indices.\n     */\n\n    int compare = TkTextIndexCmp(indexPtr1, indexPtr2);\n\n    if (compare == 0) {\n\treturn 0;\n    } else if (compare > 0) {\n\treturn -TkTextIndexCount(textPtr, indexPtr2, indexPtr1, type);\n    } else {\n\treturn TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteIndexRange --\n *\n *\tThis function implements most of the functionality of the \"delete\"\n *\twidget command.\n *\n * Results:\n *\tReturns a standard Tcl result, currently always TCL_OK.\n *\n * Side effects:\n *\tCharacters and other entities (windows, images) get deleted from the\n *\ttext.\n *\n *\tIf 'viewUpdate' is true, we may adjust the window contents'\n *\ty-position, and scrollbar setting.\n *\n *\tIf 'viewUpdate' is true we can guarantee that textPtr->topIndex\n *\tpoints to a valid TkTextLine after this function returns. However, if\n *\t'viewUpdate' is false, then there is no such guarantee (since\n *\ttopIndex.linePtr can be garbage). The caller is expected to take\n *\tactions to ensure the topIndex is validated before laying out the\n *\twindow again.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDeleteIndexRange(\n    TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */\n    TkText *textPtr,\t\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr1,\n\t\t\t\t/* Index describing location of first\n\t\t\t\t * character (or other entity) to delete. */\n    const TkTextIndex *indexPtr2,\n\t\t\t\t/* Index describing location of last\n\t\t\t\t * character (or other entity) to delete.\n\t\t\t\t * NULL means just delete the one character\n\t\t\t\t * given by indexPtr1. */\n    int viewUpdate)\t\t/* Update vertical view if set. */\n{\n    Tcl_Size line1, line2;\n    TkTextIndex index1, index2;\n    TkText *tPtr;\n    int *lineAndByteIndex;\n    int resetViewCount;\n    int pixels[2*PIXEL_CLIENTS];\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n    Tcl_Size i;\n\n    if (sharedTextPtr == NULL) {\n\tsharedTextPtr = textPtr->sharedTextPtr;\n    }\n\n    /*\n     * Prepare the starting and stopping indices.\n     */\n\n    index1 = *indexPtr1;\n    if (indexPtr2 != NULL) {\n\tindex2 = *indexPtr2;\n    } else {\n\tindex2 = index1;\n\tTkTextIndexForwChars(NULL, &index2, 1, &index2, COUNT_INDICES);\n    }\n\n    /*\n     * Make sure there's really something to delete.\n     */\n\n    if (TkTextIndexCmp(&index1, &index2) >= 0) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * The code below is ugly, but it's needed to make sure there is always a\n     * dummy empty line at the end of the text. If the final newline of the\n     * file (just before the dummy line) is being deleted, then back up index\n     * to just before the newline. If there is a newline just before the first\n     * character being deleted, then back up the first index too. The idea is\n     * that a deletion involving a range starting at a line start and\n     * including the final \\n (i.e. index2 is \"end\") is an attempt to delete\n     * complete lines, so the \\n before the deleted block shall become the new\n     * final \\n. Furthermore, remove any tags that are present on the newline\n     * that isn't going to be deleted after all (this simulates deleting the\n     * newline and then adding a \"clean\" one back again). Note that index1 and\n     * index2 might now be equal again which means that no text will be\n     * deleted but tags might be removed.\n     */\n\n    line1 = TkBTreeLinesTo(textPtr, index1.linePtr);\n    line2 = TkBTreeLinesTo(textPtr, index2.linePtr);\n    if (line2 == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) {\n\tTkTextTag **arrayPtr;\n\tTcl_Size arraySize;\n\tTkTextIndex oldIndex2;\n\n\toldIndex2 = index2;\n\tTkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES);\n\tline2--;\n\tif ((index1.byteIndex == 0) && (line1 != 0)) {\n\t    TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES);\n\t    line1--;\n\t}\n\tarrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize);\n\tif (arrayPtr != NULL) {\n\t    for (i = 0; i < arraySize; i++) {\n\t\tTkBTreeTag(&index2, &oldIndex2, arrayPtr[i], false);\n\t    }\n\t    Tcl_Free(arrayPtr);\n\t}\n    }\n\n    /*\n     * For speed, we remove all tags from the range first. If we don't\n     * do this, the code below can (when there are many tags) grow\n     * non-linearly in execution time.\n     */\n\n    for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);\n\t    hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {\n\tTkBTreeTag(&index1, &index2, (TkTextTag *)Tcl_GetHashValue(hPtr), false);\n    }\n\n    /*\n     * Special case for the sel tag which is not in the hash table. We\n     * need to do this once for each peer text widget.\n     */\n\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ;\n\t    tPtr = tPtr->next) {\n\tif (TkBTreeTag(&index1, &index2, tPtr->selTagPtr, false)) {\n\t    /*\n\t     * Send an event that the selection changed. This is\n\t     * equivalent to:\n\t     *\tevent generate $textWidget <<Selection>>\n\t     */\n\n\t    TkTextSelectionEvent(textPtr);\n\t    tPtr->abortSelections = true;\n\t}\n    }\n\n    /*\n     * Tell the display what's about to happen so it can discard obsolete\n     * display information, then do the deletion. Also, if the deletion\n     * involves the top line on the screen, then we have to reset the view\n     * (the deletion will invalidate textPtr->topIndex). Compute what the new\n     * first character will be, then do the deletion, then reset the view.\n     */\n\n    TkTextChanged(sharedTextPtr, NULL, &index1, &index2);\n\n    resetViewCount = 0;\n    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {\n\tlineAndByteIndex = (int *)Tcl_Alloc(sizeof(int) * 2 * sharedTextPtr->refCount);\n    } else {\n\tlineAndByteIndex = pixels;\n    }\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\tTcl_Size line = 0;\n\tTcl_Size byteIndex = 0;\n\tbool resetView = false;\n\n\tif (TkTextIndexCmp(&index2, &tPtr->topIndex) >= 0) {\n\t    if (TkTextIndexCmp(&index1, &tPtr->topIndex) <= 0) {\n\t\t/*\n\t\t * Deletion range straddles topIndex: use the beginning of the\n\t\t * range as the new topIndex.\n\t\t */\n\n\t\tresetView = true;\n\t\tline = line1;\n\t\tbyteIndex = index1.byteIndex;\n\t    } else if (index1.linePtr == tPtr->topIndex.linePtr) {\n\t\t/*\n\t\t * Deletion range starts on top line but after topIndex. Use\n\t\t * the current topIndex as the new one.\n\t\t */\n\n\t\tresetView = true;\n\t\tline = line1;\n\t\tbyteIndex = tPtr->topIndex.byteIndex;\n\t    } else {\n\t\t/*\n\t\t * Deletion range starts after the top line. This peers's view\n\t\t * will not need to be reset. Nothing to do.\n\t\t */\n\t    }\n\t} else if (index2.linePtr == tPtr->topIndex.linePtr) {\n\t    /*\n\t     * Deletion range ends on top line but before topIndex. Figure out\n\t     * what will be the new character index for the character\n\t     * currently pointed to by topIndex.\n\t     */\n\n\t    resetView = true;\n\t    line = line2;\n\t    byteIndex = tPtr->topIndex.byteIndex;\n\t    if (index1.linePtr != index2.linePtr) {\n\t\tbyteIndex -= index2.byteIndex;\n\t    } else {\n\t\tbyteIndex -= (index2.byteIndex - index1.byteIndex);\n\t    }\n\t} else {\n\t    /*\n\t     * Deletion range ends before the top line. This peers's view\n\t     * will not need to be reset. Nothing to do.\n\t     */\n\t}\n\tif (resetView) {\n\t    lineAndByteIndex[resetViewCount] = line;\n\t    lineAndByteIndex[resetViewCount+1] = byteIndex;\n\t} else {\n\t    lineAndByteIndex[resetViewCount] = -1;\n\t}\n\tresetViewCount += 2;\n    }\n\n    /*\n     * Push the deletion on the undo stack if something was actually deleted.\n     */\n\n    if (TkTextIndexCmp(&index1, &index2) < 0) {\n\tif (sharedTextPtr->undo) {\n\t    Tcl_Obj *get;\n\n\t    if (sharedTextPtr->autoSeparators\n\t\t    && (sharedTextPtr->lastEditMode != TK_TEXT_EDIT_DELETE)) {\n\t\tTkUndoInsertUndoSeparator(sharedTextPtr->undoStack);\n\t    }\n\n\t    sharedTextPtr->lastEditMode = TK_TEXT_EDIT_DELETE;\n\n\t    get = TextGetText(textPtr, &index1, &index2, 0);\n\t    TextPushUndoAction(textPtr, get, 0, &index1, &index2);\n\t}\n\tsharedTextPtr->stateEpoch++;\n\n\tTkBTreeDeleteIndexRange(sharedTextPtr->tree, &index1, &index2);\n\n\tUpdateDirtyFlag(sharedTextPtr);\n    }\n\n    resetViewCount = 0;\n    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\tTcl_Size line = lineAndByteIndex[resetViewCount];\n\n\tif (line != -1) {\n\t    Tcl_Size byteIndex = lineAndByteIndex[resetViewCount+1];\n\t    TkTextIndex indexTmp;\n\n\t    if (tPtr == textPtr) {\n\t\tif (viewUpdate) {\n\t\t    /*\n\t\t     * line cannot be before -startline of textPtr because\n\t\t     * this line corresponds to an index which is necessarily\n\t\t     * between \"1.0\" and \"end\" relative to textPtr.\n\t\t     * Therefore no need to clamp line to the -start/-end\n\t\t     * range.\n\t\t     */\n\n\t\t    TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line,\n\t\t\t    byteIndex, &indexTmp);\n\t\t    TkTextSetYView(tPtr, &indexTmp, 0);\n\t\t}\n\t    } else {\n\t\tTkTextMakeByteIndex(sharedTextPtr->tree, NULL, line,\n\t\t\tbyteIndex, &indexTmp);\n\t\t/*\n\t\t * line may be before -startline of tPtr and must be\n\t\t * clamped to -startline before providing it to\n\t\t * TkTextSetYView otherwise lines before -startline\n\t\t * would be displayed.\n\t\t * There is no need to worry about -endline however,\n\t\t * because the view will only be reset if the deletion\n\t\t * involves the TOP line of the screen. That said,\n\t\t * the following call adjusts to both.\n\t\t */\n\n\t\tTkTextIndexAdjustToStartEnd(tPtr, &indexTmp, false);\n\n\t\tTkTextSetYView(tPtr, &indexTmp, 0);\n\t    }\n\t}\n\tresetViewCount += 2;\n    }\n    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {\n\tTcl_Free(lineAndByteIndex);\n    }\n\n    if (line1 >= line2) {\n\t/*\n\t * Invalidate any selection retrievals in progress, assuming we didn't\n\t * check for this case above.\n\t */\n\n\tfor (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {\n\t    tPtr->abortSelections = true;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextFetchSelection --\n *\n *\tThis function is called back by Tk when the selection is requested by\n *\tsomeone. It returns part or all of the selection in a buffer provided\n *\tby the caller.\n *\n * Results:\n *\tThe return value is the number of non-NULL bytes stored at buffer.\n *\tBuffer is filled (or partially filled) with a NULL-terminated string\n *\tcontaining part or all of the selection, as given by offset and\n *\tmaxBytes.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nTextFetchSelection(\n    void *clientData,\t/* Information about text widget. */\n    Tcl_Size offset,\t\t\t/* Offset within selection of first character\n\t\t\t\t * to be returned. */\n    char *buffer,\t\t/* Location in which to place selection. */\n    Tcl_Size maxBytes)\t\t/* Maximum number of bytes to place at buffer,\n\t\t\t\t * not including terminating NULL\n\t\t\t\t * character. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    TkTextIndex eof;\n    Tcl_Size count, offsetInSeg, chunkSize;\n    TkTextSearch search;\n    TkTextSegment *segPtr;\n\n    if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {\n\treturn -1;\n    }\n\n    /*\n     * Find the beginning of the next range of selected text. Note: if the\n     * selection is being retrieved in multiple pieces (offset != 0) and some\n     * modification has been made to the text that affects the selection then\n     * reject the selection request (make 'em start over again).\n     */\n\n    if (offset == 0) {\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t\t&textPtr->selIndex);\n\ttextPtr->abortSelections = false;\n    } else if (textPtr->abortSelections) {\n\treturn 0;\n    }\n    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &eof);\n    TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search);\n    if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) {\n\tif (!TkBTreeNextTag(&search)) {\n\t    if (offset == 0) {\n\t\treturn -1;\n\t    } else {\n\t\treturn 0;\n\t    }\n\t}\n\ttextPtr->selIndex = search.curIndex;\n    }\n\n    /*\n     * Each iteration through the outer loop below scans one selected range.\n     * Each iteration through the inner loop scans one segment in the selected\n     * range.\n     */\n\n    count = 0;\n    while (1) {\n\t/*\n\t * Find the end of the current range of selected text.\n\t */\n\n\tif (!TkBTreeNextTag(&search)) {\n\t    Tcl_Panic(\"TextFetchSelection couldn't find end of range\");\n\t}\n\n\t/*\n\t * Copy information from character segments into the buffer until\n\t * either we run out of space in the buffer or we get to the end of\n\t * this range of text.\n\t */\n\n\twhile (1) {\n\t    if (maxBytes == 0) {\n\t\tgoto fetchDone;\n\t    }\n\t    segPtr = TkTextIndexToSeg(&textPtr->selIndex, &offsetInSeg);\n\t    chunkSize = segPtr->size - offsetInSeg;\n\t    if (chunkSize > maxBytes) {\n\t\tchunkSize = maxBytes;\n\t    }\n\t    if (textPtr->selIndex.linePtr == search.curIndex.linePtr) {\n\t\tTcl_Size leftInRange;\n\n\t\tleftInRange = search.curIndex.byteIndex\n\t\t\t- textPtr->selIndex.byteIndex;\n\t\tif (leftInRange < chunkSize) {\n\t\t    chunkSize = leftInRange;\n\t\t    if (chunkSize <= 0) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t    if ((segPtr->typePtr == &tkTextCharType)\n\t\t    && !TkTextIsElided(textPtr, &textPtr->selIndex, NULL)) {\n\t\tmemcpy(buffer, segPtr->body.chars + offsetInSeg,\n\t\t\t(size_t)chunkSize);\n\t\tbuffer += chunkSize;\n\t\tmaxBytes -= chunkSize;\n\t\tcount += chunkSize;\n\t    }\n\t    TkTextIndexForwBytes(textPtr, &textPtr->selIndex, chunkSize,\n\t\t    &textPtr->selIndex);\n\t}\n\n\t/*\n\t * Find the beginning of the next range of selected text.\n\t */\n\n\tif (!TkBTreeNextTag(&search)) {\n\t    break;\n\t}\n\ttextPtr->selIndex = search.curIndex;\n    }\n\n  fetchDone:\n    *buffer = 0;\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextLostSelection --\n *\n *\tThis function is called back by Tk when the selection is grabbed away\n *\tfrom a text widget. On Windows and Mac systems, we want to remember\n *\tthe selection for the next time the focus enters the window. On Unix,\n *\tjust remove the \"sel\" tag from everything in the widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe \"sel\" tag is cleared from the window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextLostSelection(\n    void *clientData)\t/* Information about text widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n\n    if (Tk_AlwaysShowSelection(textPtr->tkwin)) {\n\tTkTextIndex start, end;\n\n\tif ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {\n\t    return;\n\t}\n\n\t/*\n\t * On Windows and Mac systems, we want to remember the selection for\n\t * the next time the focus enters the window. On Unix, just remove the\n\t * \"sel\" tag from everything in the widget.\n\t */\n\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t0, 0, &start);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),\n\t\t0, &end);\n\tTkTextRedrawTag(NULL, textPtr, &start, &end, textPtr->selTagPtr, true);\n\tTkBTreeTag(&start, &end, textPtr->selTagPtr, false);\n    }\n\n    /*\n     * Send an event that the selection changed. This is equivalent to:\n     *\t   event generate $textWidget <<Selection>>\n     */\n\n    TkTextSelectionEvent(textPtr);\n\n    textPtr->flags &= ~GOT_SELECTION;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextSelectionEvent --\n *\n *\tWhen anything relevant to the \"sel\" tag has been changed, call this\n *\tfunction to generate a <<Selection>> event.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf <<Selection>> bindings are present, they will trigger.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextSelectionEvent(\n    TkText *textPtr)\n{\n    /*\n     * Send an event that the selection changed. This is equivalent to:\n     *     event generate $textWidget <<Selection>>\n     */\n\n    Tk_SendVirtualEvent(textPtr->tkwin, \"Selection\", NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextBlinkProc --\n *\n *\tThis function is called as a timer handler to blink the insertion\n *\tcursor off and on.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor gets turned on or off, redisplay gets invoked, and this\n *\tfunction reschedules itself.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTextBlinkProc(\n    void *clientData)\t/* Pointer to record describing text. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    TkTextIndex index;\n    int x, y, w, h, charWidth;\n\n    if ((textPtr->state == TK_TEXT_STATE_DISABLED) ||\n\t    !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {\n\tif (!(textPtr->flags & GOT_FOCUS) &&\n\t\t(textPtr->insertUnfocussed != TK_TEXT_INSERT_NOFOCUS_NONE)) {\n\t    /*\n\t     * The widget doesn't have the focus yet it is configured to\n\t     * display the cursor when it doesn't have the focus. Act now!\n\t     */\n\n\t    textPtr->flags |= INSERT_ON;\n\t    goto redrawInsert;\n\t}\n\tif ((textPtr->insertOffTime == 0) && !(textPtr->flags & INSERT_ON)) {\n\t    /*\n\t     * The widget was configured to have zero offtime while the\n\t     * insertion point was not displayed. We have to display it once.\n\t     */\n\n\t    textPtr->flags |= INSERT_ON;\n\t    goto redrawInsert;\n\t}\n\treturn;\n    }\n    if (textPtr->flags & INSERT_ON) {\n\ttextPtr->flags &= ~INSERT_ON;\n\ttextPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\ttextPtr->insertOffTime, TextBlinkProc, textPtr);\n    } else {\n\ttextPtr->flags |= INSERT_ON;\n\ttextPtr->insertBlinkHandler = Tcl_CreateTimerHandler(\n\t\ttextPtr->insertOnTime, TextBlinkProc, textPtr);\n    }\n  redrawInsert:\n    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n    if (TkTextIndexBbox(textPtr, &index, &x, &y, &w, &h,\n\t    &charWidth, NULL) == 0) {\n\tint insertWidth;\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);\n\tif (textPtr->insertCursorType) {\n\t    /* Block cursor */\n\t    TkTextRedrawRegion(textPtr, x - insertWidth / 2, y,\n\t\t    charWidth + insertWidth / 2, h);\n\t} else {\n\t    /* I-beam cursor */\n\t    TkTextRedrawRegion(textPtr, x - insertWidth / 2, y,\n\t\t    insertWidth, h);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextInsertCmd --\n *\n *\tThis function is invoked to process the \"insert\" and \"replace\" widget\n *\tcommands for text widgets.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *\tIf 'viewUpdate' is true, we may adjust the window contents'\n *\ty-position, and scrollbar setting.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextInsertCmd(\n    TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    const TkTextIndex *indexPtr,/* Index at which to insert. */\n    int viewUpdate)\t\t/* Update the view if set. */\n{\n    TkTextIndex index1, index2;\n    Tcl_Size j;\n\n    if (sharedTextPtr == NULL) {\n\tsharedTextPtr = textPtr->sharedTextPtr;\n    }\n\n    index1 = *indexPtr;\n    for (j = 0; j < objc; j += 2) {\n\t/*\n\t * Here we rely on this call to modify index1 if it is outside the\n\t * acceptable range. In particular, if index1 is \"end\", it must be set\n\t * to the last allowable index for insertion, otherwise subsequent tag\n\t * insertions will fail.\n\t */\n\n\tTcl_Size length = InsertChars(sharedTextPtr, textPtr, &index1, objv[j],\n\t\tviewUpdate);\n\n\tif (objc > (j+1)) {\n\t    Tcl_Obj **tagNamePtrs;\n\t    TkTextTag **oldTagArrayPtr;\n\t    Tcl_Size numTags;\n\n\t    TkTextIndexForwBytes(textPtr, &index1, length, &index2);\n\t    oldTagArrayPtr = TkBTreeGetTags(&index1, NULL, &numTags);\n\t    if (oldTagArrayPtr != NULL) {\n\t\tTcl_Size i;\n\n\t\tfor (i = 0; i < numTags; i++) {\n\t\t    TkBTreeTag(&index1, &index2, oldTagArrayPtr[i], false);\n\t\t}\n\t\tTcl_Free(oldTagArrayPtr);\n\t    }\n\t    if (Tcl_ListObjGetElements(interp, objv[j+1], &numTags,\n\t\t    &tagNamePtrs) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    } else {\n\t\tTcl_Size i;\n\n\t\tfor (i = 0; i < numTags; i++) {\n\t\t    const char *strTag = Tcl_GetString(tagNamePtrs[i]);\n\n\t\t    TkBTreeTag(&index1, &index2,\n\t\t\t    TkTextCreateTag(textPtr, strTag, NULL), true);\n\t\t}\n\t\tindex1 = index2;\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextSearchCmd --\n *\n *\tThis function is invoked to process the \"search\" widget command for\n *\ttext widgets. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextSearchCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tcl_Size i, argsLeft;\n    int code;\n    SearchSpec searchSpec;\n\n    static const char *const switchStrings[] = {\n\t\"-hidden\",\n\t\"--\", \"-all\", \"-backwards\", \"-count\", \"-elide\", \"-exact\", \"-forwards\",\n\t\"-nocase\", \"-nolinestop\", \"-overlap\", \"-regexp\", \"-strictlimits\", NULL\n    };\n    enum SearchSwitches {\n\tTK_TEXT_SEARCH_HIDDEN,\n\tTK_TEXT_SEARCH_END, TK_TEXT_SEARCH_ALL, TK_TEXT_SEARCH_BACK, TK_TEXT_SEARCH_COUNT, TK_TEXT_SEARCH_ELIDE,\n\tTK_TEXT_SEARCH_EXACT, TK_TEXT_SEARCH_FWD, TK_TEXT_SEARCH_NOCASE,\n\tTK_TEXT_SEARCH_NOLINESTOP, TK_TEXT_SEARCH_OVERLAP, TK_TEXT_SEARCH_REGEXP, TK_TEXT_SEARCH_STRICTLIMITS\n    };\n\n    /*\n     * Set up the search specification, including the last 4 fields which are\n     * text widget specific.\n     */\n\n    searchSpec.exact = true;\n    searchSpec.noCase = false;\n    searchSpec.all = false;\n    searchSpec.backwards = false;\n    searchSpec.searchElide = false;\n    searchSpec.noLineStop = false;\n    searchSpec.overlap = false;\n    searchSpec.strictLimits = false;\n    searchSpec.varPtr = NULL;\n    searchSpec.countPtr = NULL;\n    searchSpec.resPtr = NULL;\n    searchSpec.numLines =\n\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n    searchSpec.clientData = textPtr;\n    searchSpec.addLineProc = &TextSearchAddNextLine;\n    searchSpec.foundMatchProc = &TextSearchFoundMatch;\n    searchSpec.lineIndexProc = &TextSearchGetLineIndex;\n\n    /*\n     * Parse switches and other arguments.\n     */\n\n    for (i=2 ; i<objc ; i++) {\n\tint index;\n\n\tif (Tcl_GetString(objv[i])[0] != '-') {\n\t    break;\n\t}\n\n\tif (Tcl_GetIndexFromObjStruct(NULL, objv[i], switchStrings,\n\t\tsizeof(char *), \"switch\", 0, &index) != TCL_OK) {\n\t    /*\n\t     * Hide the -hidden option, generating the error description with\n\t     * the side effects of T_GIFO.\n\t     */\n\n\t    (void) Tcl_GetIndexFromObjStruct(interp, objv[i], switchStrings+1,\n\t\t    sizeof(char *), \"switch\", 0, &index);\n\t    return TCL_ERROR;\n\t}\n\n\tswitch ((enum SearchSwitches) index) {\n\tcase TK_TEXT_SEARCH_END:\n\t    i++;\n\t    goto endOfSwitchProcessing;\n\tcase TK_TEXT_SEARCH_ALL:\n\t    searchSpec.all = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_BACK:\n\t    searchSpec.backwards = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_COUNT:\n\t    if (i + 1 >= objc) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"no value given for \\\"-count\\\" option\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"VALUE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    i++;\n\n\t    /*\n\t     * Assumption objv[i] isn't going to disappear on us during this\n\t     * function, which is fair.\n\t     */\n\n\t    searchSpec.varPtr = objv[i];\n\t    break;\n\tcase TK_TEXT_SEARCH_ELIDE:\n\tcase TK_TEXT_SEARCH_HIDDEN:\n\t    searchSpec.searchElide = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_EXACT:\n\t    searchSpec.exact = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_FWD:\n\t    searchSpec.backwards = false;\n\t    break;\n\tcase TK_TEXT_SEARCH_NOCASE:\n\t    searchSpec.noCase = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_NOLINESTOP:\n\t    searchSpec.noLineStop = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_OVERLAP:\n\t    searchSpec.overlap = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_STRICTLIMITS:\n\t    searchSpec.strictLimits = true;\n\t    break;\n\tcase TK_TEXT_SEARCH_REGEXP:\n\t    searchSpec.exact = false;\n\t    break;\n\tdefault:\n\t    Tcl_Panic(\"unexpected switch fallthrough\");\n\t}\n    }\n  endOfSwitchProcessing:\n\n    argsLeft = objc - (i+2);\n    if ((argsLeft != 0) && (argsLeft != 1)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"?switches? pattern index ?stopIndex?\");\n\treturn TCL_ERROR;\n    }\n\n    if (searchSpec.noLineStop && searchSpec.exact) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"the \\\"-nolinestop\\\" option requires the \\\"-regexp\\\" option\"\n\t\t\" to be present\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"SEARCH_USAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (searchSpec.overlap && !searchSpec.all) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"the \\\"-overlap\\\" option requires the \\\"-all\\\" option\"\n\t\t\" to be present\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"SEARCH_USAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Scan through all of the lines of the text circularly, starting at the\n     * given index. 'objv[i]' is the pattern which may be an exact string or a\n     * regexp pattern depending on the flags set above.\n     */\n\n    code = SearchPerform(interp, &searchSpec, objv[i], objv[i+1],\n\t    (argsLeft == 1 ? objv[i+2] : NULL));\n    if (code != TCL_OK) {\n\tgoto cleanup;\n    }\n\n    /*\n     * Set the '-count' variable, if given.\n     */\n\n    if (searchSpec.varPtr != NULL && searchSpec.countPtr != NULL) {\n\tTcl_IncrRefCount(searchSpec.countPtr);\n\tif (Tcl_ObjSetVar2(interp, searchSpec.varPtr, NULL,\n\t\tsearchSpec.countPtr, TCL_LEAVE_ERR_MSG) == NULL) {\n\t    code = TCL_ERROR;\n\t    goto cleanup;\n\t}\n    }\n\n    /*\n     * Set the result.\n     */\n\n    if (searchSpec.resPtr != NULL) {\n\tTcl_SetObjResult(interp, searchSpec.resPtr);\n\tsearchSpec.resPtr = NULL;\n    }\n\n  cleanup:\n    if (searchSpec.countPtr != NULL) {\n\tTcl_DecrRefCount(searchSpec.countPtr);\n    }\n    if (searchSpec.resPtr != NULL) {\n\tTcl_DecrRefCount(searchSpec.resPtr);\n    }\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextSearchGetLineIndex --\n *\n *\tExtract a row, text offset index position from an objPtr\n *\n *\tThis means we ignore any embedded windows/images and elided text\n *\t(unless we are searching that).\n *\n * Results:\n *\tStandard Tcl error code (with a message in the interpreter on error\n *\tconditions).\n *\n *\tThe offset placed in offsetPosPtr is a utf-8 char* byte index for\n *\texact searches, and a Unicode character index for regexp searches.\n *\n *\tThe line number should start at zero (searches which wrap around\n *\tassume the first line is numbered 0).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextSearchGetLineIndex(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    Tcl_Obj *objPtr,\t\t/* Contains a textual index like \"1.2\" */\n    SearchSpec *searchSpecPtr,\t/* Contains other search parameters. */\n    Tcl_Size *linePosPtr,\t\t/* For returning the line number. */\n    Tcl_Size *offsetPosPtr)\t\t/* For returning the text offset in the\n\t\t\t\t * line. */\n{\n    const TkTextIndex *indexPtr;\n    Tcl_Size line;\n    TkText *textPtr = (TkText *)searchSpecPtr->clientData;\n\n    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objPtr);\n    if (indexPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    line = TkBTreeLinesTo(textPtr, indexPtr->linePtr);\n    if (line >= searchSpecPtr->numLines) {\n\tTkTextLine *linePtr;\n\tTcl_Size count = 0;\n\tTkTextSegment *segPtr;\n\n\tline = searchSpecPtr->numLines-1;\n\tlinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, line);\n\n\t/*\n\t * Count the number of bytes in this line.\n\t */\n\n\tfor (segPtr=linePtr->segPtr ; segPtr!=NULL ; segPtr=segPtr->nextPtr) {\n\t    count += segPtr->size;\n\t}\n\t*offsetPosPtr = TextSearchIndexInLine(searchSpecPtr, linePtr, count);\n    } else {\n\t*offsetPosPtr = TextSearchIndexInLine(searchSpecPtr,\n\t\tindexPtr->linePtr, indexPtr->byteIndex);\n    }\n\n    *linePosPtr = line;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextSearchIndexInLine --\n *\n *\tFind textual index of 'byteIndex' in the searchable characters of\n *\t'linePtr'.\n *\n *\tThis means we ignore any embedded windows/images and elided text\n *\t(unless we are searching that).\n *\n * Results:\n *\tThe returned index is a utf-8 char* byte index for exact searches, and\n *\ta Unicode character index for regexp searches.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Size\nTextSearchIndexInLine(\n    const SearchSpec *searchSpecPtr,\n\t\t\t\t/* Search parameters. */\n    TkTextLine *linePtr,\t/* The line we're looking at. */\n    Tcl_Size byteIndex)\t\t/* Index into the line. */\n{\n    TkTextSegment *segPtr;\n    TkTextIndex curIndex;\n    Tcl_Size index;\n    Tcl_Size leftToScan;\n    TkText *textPtr = (TkText *)searchSpecPtr->clientData;\n\n    index = 0;\n    curIndex.tree = textPtr->sharedTextPtr->tree;\n    curIndex.linePtr = linePtr; curIndex.byteIndex = 0;\n    for (segPtr = linePtr->segPtr, leftToScan = byteIndex;\n\t    leftToScan > 0;\n\t    curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {\n\tif ((segPtr->typePtr == &tkTextCharType) &&\n\t\t(searchSpecPtr->searchElide\n\t\t|| !TkTextIsElided(textPtr, &curIndex, NULL))) {\n\t    if (leftToScan < segPtr->size) {\n\t\tif (searchSpecPtr->exact) {\n\t\t    index += leftToScan;\n\t\t} else {\n\t\t    index += Tcl_NumUtfChars(segPtr->body.chars, leftToScan);\n\t\t}\n\t    } else if (searchSpecPtr->exact) {\n\t\tindex += segPtr->size;\n\t    } else {\n\t\tindex += Tcl_NumUtfChars(segPtr->body.chars, -1);\n\t    }\n\t}\n\tleftToScan -= segPtr->size;\n    }\n    return index;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextSearchAddNextLine --\n *\n *\tAdds a line from the text widget to the object 'theLine'.\n *\n * Results:\n *\tA pointer to the TkTextLine corresponding to the given line, or NULL\n *\tif there was no available line.\n *\n *\tAlso 'lenPtr' (if non-NULL) is filled in with the total length of\n *\t'theLine' (not just what we added to it, but the length including what\n *\twas already in there). This is in bytes for an exact search and in\n *\tchars for a regexp search.\n *\n *\tAlso 'extraLinesPtr' (if non-NULL) will have its value incremented by\n *\t1 for each additional logical line we have added because a newline is\n *\telided (this will only ever happen if we have chosen not to search\n *\telided text, of course).\n *\n * Side effects:\n *\tMemory may be allocated or re-allocated for theLine's string\n *\trepresentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void *\nTextSearchAddNextLine(\n    Tcl_Size lineNum,\t\t/* Line we must add. */\n    SearchSpec *searchSpecPtr,\t/* Search parameters. */\n    Tcl_Obj *theLine,\t\t/* Object to append to. */\n    Tcl_Size *lenPtr,\t\t/* For returning the total length. */\n    int *extraLinesPtr)\t\t/* If non-NULL, will have its value\n\t\t\t\t * incremented by the number of additional\n\t\t\t\t * logical lines which are merged into this\n\t\t\t\t * one by newlines being elided. */\n{\n    TkTextLine *linePtr, *thisLinePtr;\n    TkTextIndex curIndex;\n    TkTextSegment *segPtr;\n    TkText *textPtr = (TkText *)searchSpecPtr->clientData;\n    bool nothingYet = true;\n\n    /*\n     * Extract the text from the line.\n     */\n\n    linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, lineNum);\n    if (linePtr == NULL) {\n\treturn NULL;\n    }\n    curIndex.tree = textPtr->sharedTextPtr->tree;\n    thisLinePtr = linePtr;\n\n    while (thisLinePtr != NULL) {\n\tint elideWraps = 0;\n\n\tcurIndex.linePtr = thisLinePtr;\n\tcurIndex.byteIndex = 0;\n\tfor (segPtr = thisLinePtr->segPtr; segPtr != NULL;\n\t\tcurIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {\n\t    if (!searchSpecPtr->searchElide\n\t\t    && TkTextIsElided(textPtr, &curIndex, NULL)) {\n\t\t/*\n\t\t * If we reach the end of the logical line, and if we have at\n\t\t * least one character in the string, then we continue\n\t\t * wrapping to the next logical line. If there are no\n\t\t * characters yet, then the entire line of characters is\n\t\t * elided and there's no need to complicate matters by\n\t\t * wrapping - we'll look at the next line in due course.\n\t\t */\n\n\t\tif (segPtr->nextPtr == NULL && !nothingYet) {\n\t\t    elideWraps = 1;\n\t\t}\n\t\tcontinue;\n\t    }\n\t    if (segPtr->typePtr != &tkTextCharType) {\n\t\tcontinue;\n\t    }\n\t    Tcl_AppendToObj(theLine, segPtr->body.chars, segPtr->size);\n\t    nothingYet = false;\n\t}\n\tif (!elideWraps) {\n\t    break;\n\t}\n\tlineNum++;\n\tif (lineNum >= searchSpecPtr->numLines) {\n\t    break;\n\t}\n\tthisLinePtr = TkBTreeNextLine(textPtr, thisLinePtr);\n\tif (thisLinePtr != NULL && extraLinesPtr != NULL) {\n\t    /*\n\t     * Tell our caller we have an extra line merged in.\n\t     */\n\n\t    *extraLinesPtr = (*extraLinesPtr) + 1;\n\t}\n    }\n\n    /*\n     * If we're ignoring case, convert the line to lower case. There is no\n     * need to do this for regexp searches, since they handle a flag for this\n     * purpose.\n     */\n\n    if (searchSpecPtr->exact && searchSpecPtr->noCase) {\n\tTcl_SetObjLength(theLine, Tcl_UtfToLower(Tcl_GetString(theLine)));\n    }\n\n    if (lenPtr != NULL) {\n\tif (searchSpecPtr->exact) {\n\t    Tcl_GetString(theLine);\n\t    *lenPtr = theLine->length;\n\t} else {\n\t    *lenPtr = Tcl_GetCharLength(theLine);\n\t}\n    }\n    return linePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextSearchFoundMatch --\n *\n *\tStores information from a successful search.\n *\n * Results:\n *\t1 if the information was stored, 0 if the position at which the match\n *\twas found actually falls outside the allowable search region (and\n *\ttherefore the search is actually complete).\n *\n * Side effects:\n *\tMemory may be allocated in the 'countPtr' and 'resPtr' fields of\n *\t'searchSpecPtr'. Each of those objects will have refCount zero and\n *\tmust eventually be freed or stored elsewhere as appropriate.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nTextSearchFoundMatch(\n    Tcl_Size lineNum,\t\t/* Line on which match was found. */\n    SearchSpec *searchSpecPtr,\t/* Search parameters. */\n    void *clientData,\t/* Token returned by the 'addNextLineProc',\n\t\t\t\t * TextSearchAddNextLine. May be NULL, in\n\t\t\t\t * which we case we must generate it (from\n\t\t\t\t * lineNum). */\n    Tcl_Obj *theLine,\t\t/* Text from current line, only accessed for\n\t\t\t\t * exact searches, and is allowed to be NULL\n\t\t\t\t * for regexp searches. */\n    Tcl_Size matchOffset,\t\t/* Offset of found item in utf-8 bytes for\n\t\t\t\t * exact search, Unicode chars for regexp. */\n    Tcl_Size matchLength)\t\t/* Length also in bytes/chars as per search\n\t\t\t\t * type. */\n{\n    Tcl_Size numChars;\n    Tcl_Size leftToScan;\n    TkTextIndex curIndex, foundIndex;\n    TkTextSegment *segPtr;\n    TkTextLine *linePtr;\n    TkText *textPtr = (TkText *)searchSpecPtr->clientData;\n\n    if (lineNum == searchSpecPtr->stopLine) {\n\t/*\n\t * If the current index is on the wrong side of the stopIndex, then\n\t * the item we just found is actually outside the acceptable range,\n\t * and the search is over.\n\t */\n\n\tif (searchSpecPtr->backwards !=\n\t\t(matchOffset >= searchSpecPtr->stopOffset)) {\n\t    return false;\n\t}\n    }\n\n    /*\n     * Calculate the character count, which may need augmenting if there are\n     * embedded windows or elided text.\n     */\n\n    if (searchSpecPtr->exact) {\n\tconst char *startOfLine = Tcl_GetString(theLine);\n\n\tnumChars = Tcl_NumUtfChars(startOfLine + matchOffset, matchLength);\n    } else {\n\tnumChars = matchLength;\n    }\n\n    /*\n     * If we're using strict limits checking, ensure that the match with its\n     * full length fits inside the given range.\n     */\n\n    if (searchSpecPtr->strictLimits && lineNum == searchSpecPtr->stopLine) {\n\tif (searchSpecPtr->backwards ^\n\t\t((matchOffset + numChars) > searchSpecPtr->stopOffset)) {\n\t    return false;\n\t}\n    }\n\n    /*\n     * The index information returned by the regular expression parser only\n     * considers textual information: it doesn't account for embedded windows,\n     * elided text (when we are not searching elided text) or any other\n     * non-textual info. Scan through the line's segments again to adjust both\n     * matchChar and matchCount.\n     *\n     * We will walk through the segments of this line until we have either\n     * reached the end of the match or we have reached the end of the line.\n     */\n\n    linePtr = (TkTextLine *)clientData;\n    if (linePtr == NULL) {\n\tlinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t\tlineNum);\n    }\n\n    curIndex.tree = textPtr->sharedTextPtr->tree;\n\n    /*\n     * Find the starting point.\n     */\n\n    leftToScan = matchOffset;\n    while (1) {\n\tcurIndex.linePtr = linePtr;\n\tcurIndex.byteIndex = 0;\n\n\t/*\n\t * Note that we allow leftToScan to be zero because we want to skip\n\t * over any preceding non-textual items.\n\t */\n\n\tfor (segPtr = linePtr->segPtr; leftToScan >= 0 && segPtr;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if (segPtr->typePtr != &tkTextCharType) {\n\t\tmatchOffset += segPtr->size;\n\t    } else if (!searchSpecPtr->searchElide\n\t\t    && TkTextIsElided(textPtr, &curIndex, NULL)) {\n\t\tif (searchSpecPtr->exact) {\n\t\t    matchOffset += segPtr->size;\n\t\t} else {\n\t\t    matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1);\n\t\t}\n\t    } else {\n\t\tif (searchSpecPtr->exact) {\n\t\t    leftToScan -= segPtr->size;\n\t\t} else {\n\t\t    leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);\n\t\t}\n\t    }\n\t    curIndex.byteIndex += segPtr->size;\n\t}\n\tif (segPtr == NULL && leftToScan >= 0) {\n\t    /*\n\t     * This will only happen if we are eliding newlines.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(textPtr, linePtr);\n\t    if (linePtr == NULL) {\n\t\t/*\n\t\t * If we reach the end of the text, we have a serious problem,\n\t\t * unless there's actually nothing left to look for.\n\t\t */\n\n\t\tif (leftToScan == 0) {\n\t\t    break;\n\t\t} else {\n\t\t    Tcl_Panic(\"Reached end of text in a match\");\n\t\t}\n\t    }\n\n\t    /*\n\t     * We've wrapped to the beginning of the next logical line, which\n\t     * has been merged with the previous one whose newline was elided.\n\t     */\n\n\t    lineNum++;\n\t    matchOffset = 0;\n\t} else {\n\t    break;\n\t}\n    }\n\n    /*\n     * Calculate and store the found index in the result.\n     */\n\n    if (searchSpecPtr->exact) {\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum,\n\t\tmatchOffset, &foundIndex);\n    } else {\n\tTkTextMakeCharIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum,\n\t\tmatchOffset, &foundIndex);\n    }\n\n    if (searchSpecPtr->all) {\n\tif (searchSpecPtr->resPtr == NULL) {\n\t    searchSpecPtr->resPtr = Tcl_NewObj();\n\t}\n\tTcl_ListObjAppendElement(NULL, searchSpecPtr->resPtr,\n\t\tTkTextNewIndexObj(textPtr, &foundIndex));\n    } else {\n\tsearchSpecPtr->resPtr = TkTextNewIndexObj(textPtr, &foundIndex);\n    }\n\n    /*\n     * Find the end point. Here 'leftToScan' could be negative already as a\n     * result of the above loop if the segment we reached spanned the start of\n     * the string. When we add matchLength it will become non-negative.\n     */\n\n    for (leftToScan += matchLength; leftToScan > 0;\n\t    curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {\n\tif (segPtr == NULL) {\n\t    /*\n\t     * We are on the next line - this of course should only ever\n\t     * happen with searches which have matched across multiple lines.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(textPtr, linePtr);\n\t    segPtr = linePtr->segPtr;\n\t    curIndex.linePtr = linePtr; curIndex.byteIndex = 0;\n\t}\n\tif (segPtr->typePtr != &tkTextCharType) {\n\t    /*\n\t     * Anything we didn't count in the search needs adding.\n\t     */\n\n\t    numChars += segPtr->size;\n\t    continue;\n\t} else if (!searchSpecPtr->searchElide\n\t\t&& TkTextIsElided(textPtr, &curIndex, NULL)) {\n\t    numChars += Tcl_NumUtfChars(segPtr->body.chars, -1);\n\t    continue;\n\t}\n\tif (searchSpecPtr->exact) {\n\t    leftToScan -= segPtr->size;\n\t} else {\n\t    leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);\n\t}\n    }\n\n    /*\n     * Now store the count result, if it is wanted.\n     */\n\n    if (searchSpecPtr->varPtr != NULL) {\n\tTcl_Obj *tmpPtr = Tcl_NewWideIntObj(numChars);\n\tif (searchSpecPtr->all) {\n\t    if (searchSpecPtr->countPtr == NULL) {\n\t\tsearchSpecPtr->countPtr = Tcl_NewObj();\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr);\n\t} else {\n\t    searchSpecPtr->countPtr = tmpPtr;\n\t}\n    }\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextGetTabs --\n *\n *\tParses a string description of a set of tab stops.\n *\n * Results:\n *\tThe return value is a pointer to a malloc'ed structure holding parsed\n *\tinformation about the tab stops. If an error occurred then the return\n *\tvalue is NULL and an error message is left in the interp's result.\n *\n * Side effects:\n *\tMemory is allocated for the structure that is returned. It is up to\n *\tthe caller to free this structure when it is no longer needed.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextTabArray *\nTkTextGetTabs(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tk_Window tkwin,\t\t/* Information about the window. */\n    Tcl_Obj *stringPtr)\t\t/* Description of the tab stops. See the text\n\t\t\t\t * manual entry for details. */\n{\n    Tcl_Size objc, i;\n    size_t count;\n    Tcl_Obj **objv;\n    TkTextTabArray *tabArrayPtr;\n    TkTextTab *tabPtr;\n    int ch;\n    double prevStop, lastStop;\n    /*\n     * Map these strings to TkTextTabAlign values.\n     */\n    static const char *const tabOptionStrings[] = {\n\t\"left\", \"right\", \"center\", \"numeric\", NULL\n    };\n\n    if (Tcl_ListObjGetElements(interp, stringPtr, &objc, &objv) != TCL_OK) {\n\treturn NULL;\n    }\n\n    /*\n     * First find out how many entries we need to allocate in the tab array.\n     */\n\n    count = 0;\n    for (i = 0; i < objc; i++) {\n\tchar c = Tcl_GetString(objv[i])[0];\n\n\tif ((c != 'l') && (c != 'r') && (c != 'c') && (c != 'n')) {\n\t    count++;\n\t}\n    }\n\n    /*\n     * Parse the elements of the list one at a time to fill in the array.\n     */\n\n    tabArrayPtr = (TkTextTabArray *)Tcl_Alloc(offsetof(TkTextTabArray, tabs)\n\t    + count * sizeof(TkTextTab));\n    tabArrayPtr->numTabs = 0;\n    prevStop = 0.0;\n    lastStop = 0.0;\n    for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < objc; i++, tabPtr++) {\n\tint index;\n\n\t/*\n\t * This will round fractional pixels above 0.5 upwards, and otherwise\n\t * downwards, to find the right integer pixel position.\n\t */\n\n\tif (Tk_GetPixelsFromObj(interp, tkwin, objv[i],\n\t\t&tabPtr->location) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tif (tabPtr->location <= 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"tab stop \\\"%s\\\" is not at a positive distance\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"TAB_STOP\", (char *)NULL);\n\t    goto error;\n\t}\n\n\tprevStop = lastStop;\n\tif (Tk_GetDoublePixelsFromObj(interp, tkwin, objv[i],\n\t\t&lastStop) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tif (i > 0 && (tabPtr->location <= (tabPtr-1)->location)) {\n\t    /*\n\t     * This tab is actually to the left of the previous one, which is\n\t     * illegal.\n\t     */\n\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"tabs must be monotonically increasing, but \\\"%s\\\" is \"\n\t\t    \"smaller than or equal to the previous tab\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"TAB_STOP\", (char *)NULL);\n\t    goto error;\n\t}\n\n\ttabArrayPtr->numTabs++;\n\n\t/*\n\t * See if there is an explicit alignment in the next list element.\n\t * Otherwise just use \"left\".\n\t */\n\n\ttabPtr->alignment = LEFT;\n\tif ((i+1) == objc) {\n\t    continue;\n\t}\n\n\t/*\n\t * There may be a more efficient way of getting this.\n\t */\n\n\tTcl_UtfToUniChar(Tcl_GetString(objv[i+1]), &ch);\n\tif (!Tcl_UniCharIsAlpha(ch)) {\n\t    continue;\n\t}\n\ti += 1;\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], tabOptionStrings,\n\t\tsizeof(char *), \"tab alignment\", 0, &index) != TCL_OK) {\n\t    goto error;\n\t}\n\ttabPtr->alignment = (TkTextTabAlign) index;\n    }\n\n    /*\n     * For when we need to interpolate tab stops, store these two so we know\n     * the tab stop size to very high precision. With the above checks, we can\n     * guarantee that tabIncrement is strictly positive here.\n     */\n\n    tabArrayPtr->lastTab = lastStop;\n    tabArrayPtr->tabIncrement = lastStop - prevStop;\n\n    return tabArrayPtr;\n\n  error:\n    Tcl_Free(tabArrayPtr);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextDumpCmd --\n *\n *\tReturn information about the text, tags, marks, and embedded windows\n *\tand images in a text widget. See the man page for the description of\n *\tthe text dump operation for all the details.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tMemory is allocated for the result, if needed (standard Tcl result\n *\tside effects).\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextDumpCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"dump\". */\n{\n    TkTextIndex index1, index2;\n    Tcl_Size arg;\n    Tcl_Size lineno;\t\t\t/* Current line number. */\n    int what = 0;\t\t/* bitfield to select segment types. */\n    bool atEnd;\t\t\t/* True if dumping up to logical end. */\n    TkTextLine *linePtr;\n    Tcl_Obj *command = NULL;\t/* Script callback to apply to segments. */\n#define TK_DUMP_TEXT\t0x1\n#define TK_DUMP_MARK\t0x2\n#define TK_DUMP_TAG\t0x4\n#define TK_DUMP_WIN\t0x8\n#define TK_DUMP_IMG\t0x10\n#define TK_DUMP_ALL\t(TK_DUMP_TEXT|TK_DUMP_MARK|TK_DUMP_TAG| \\\n\tTK_DUMP_WIN|TK_DUMP_IMG)\n    static const char *const optStrings[] = {\n\t\"-all\", \"-command\", \"-image\", \"-mark\", \"-tag\", \"-text\", \"-window\",\n\tNULL\n    };\n    enum opts {\n\tDUMP_ALL, DUMP_CMD, DUMP_IMG, DUMP_MARK, DUMP_TAG, DUMP_TXT, DUMP_WIN\n    };\n\n    for (arg=2 ; arg < objc ; arg++) {\n\tint index;\n\tif (Tcl_GetString(objv[arg])[0] != '-') {\n\t    break;\n\t}\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[arg], optStrings,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((enum opts) index) {\n\tcase DUMP_ALL:\n\t    what = TK_DUMP_ALL;\n\t    break;\n\tcase DUMP_TXT:\n\t    what |= TK_DUMP_TEXT;\n\t    break;\n\tcase DUMP_TAG:\n\t    what |= TK_DUMP_TAG;\n\t    break;\n\tcase DUMP_MARK:\n\t    what |= TK_DUMP_MARK;\n\t    break;\n\tcase DUMP_IMG:\n\t    what |= TK_DUMP_IMG;\n\t    break;\n\tcase DUMP_WIN:\n\t    what |= TK_DUMP_WIN;\n\t    break;\n\tcase DUMP_CMD:\n\t    arg++;\n\t    if (arg >= objc) {\n\t\tgoto wrongArgs;\n\t    }\n\t    command = objv[arg];\n\t    break;\n\tdefault:\n\t    Tcl_Panic(\"unexpected switch fallthrough\");\n\t}\n    }\n    if (arg >= objc || arg+2 < objc) {\n    wrongArgs:\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Usage: %s dump ?-all -image -text -mark -tag -window? \"\n\t\t\"?-command script? index ?index2?\", Tcl_GetString(objv[0])));\n\tTcl_SetErrorCode(interp, \"TCL\", \"WRONGARGS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (what == 0) {\n\twhat = TK_DUMP_ALL;\n    }\n    if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index1) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    arg++;\n    atEnd = false;\n    if (objc == arg) {\n\tTkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES);\n    } else {\n\tTcl_Size length;\n\tconst char *str;\n\n\tif (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstr = Tcl_GetStringFromObj(objv[arg], &length);\n\tif (strncmp(str, \"end\", (size_t)length) == 0) {\n\t    atEnd = true;\n\t}\n    }\n    if (TkTextIndexCmp(&index1, &index2) >= 0) {\n\treturn TCL_OK;\n    }\n    lineno = TkBTreeLinesTo(textPtr, index1.linePtr);\n    if (index1.linePtr == index2.linePtr) {\n\tDumpLine(interp, textPtr, what, index1.linePtr,\n\t\tindex1.byteIndex, index2.byteIndex, lineno, command);\n    } else {\n\tbool textChanged;\n\tTcl_Size lineend = TkBTreeLinesTo(textPtr, index2.linePtr);\n\tTcl_Size endByteIndex = index2.byteIndex;\n\n\ttextChanged = DumpLine(interp, textPtr, what, index1.linePtr,\n\t\tindex1.byteIndex, 32000000, lineno, command);\n\tif (textChanged) {\n\t    if (textPtr->flags & DESTROYED) {\n\t\treturn TCL_OK;\n\t    }\n\t    linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t    textPtr, lineno);\n\t    textChanged = false;\n\t} else {\n\t    linePtr = index1.linePtr;\n\t}\n\twhile ((linePtr = TkBTreeNextLine(textPtr, linePtr)) != NULL) {\n\t    lineno++;\n\t    if (lineno == lineend) {\n\t\tbreak;\n\t    }\n\t    textChanged = DumpLine(interp, textPtr, what, linePtr, 0,\n\t\t    32000000, lineno, command);\n\t    if (textChanged) {\n\t\tif (textPtr->flags & DESTROYED) {\n\t\t    return TCL_OK;\n\t\t}\n\t\tlinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t\ttextPtr, lineno);\n\t\ttextChanged = false;\n\t    }\n\t}\n\tif (linePtr != NULL) {\n\t    DumpLine(interp, textPtr, what, linePtr, 0, endByteIndex, lineno,\n\t\t    command);\n\t    if (textPtr->flags & DESTROYED) {\n\t\treturn TCL_OK;\n\t    }\n\t}\n    }\n\n    /*\n     * Special case to get the leftovers hiding at the end mark.\n     */\n\n    if (atEnd) {\n\tif (textPtr->flags & DESTROYED) {\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * Re-get the end index, in case it has changed.\n\t */\n\n\tif (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tDumpLine(interp, textPtr, what & ~TK_DUMP_TEXT, index2.linePtr,\n\t\t0, 1, lineno, command);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DumpLine\n *\n *\tReturn information about a given text line from character position\n *\t\"start\" up to, but not including, \"end\".\n *\n * Results:\n *\tReturns true if the command callback made any changes to the text widget\n *\twhich will have invalidated internal structures such as TkTextSegment,\n *\tTkTextIndex, pointers. Our caller can then take action to recompute\n *\tsuch entities. Returns false otherwise.\n *\n * Side effects:\n *\tNone, but see DumpSegment which can have arbitrary side-effects\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nDumpLine(\n    Tcl_Interp *interp,\n    TkText *textPtr,\n    int what,\t\t\t/* Bit flags to select segment types. */\n    TkTextLine *linePtr,\t/* The current line. */\n    Tcl_Size startByte, Tcl_Size endByte,\t/* Byte range to dump. */\n    Tcl_Size lineno,\t\t\t/* Line number for indices dump. */\n    Tcl_Obj *command)\t\t/* Script to apply to the segment. */\n{\n    TkTextSegment *segPtr;\n    TkTextIndex index;\n    Tcl_Size offset = 0;\n    bool textChanged = false;\n\n    /*\n     * Must loop through line looking at its segments.\n     * character\n     * toggleOn, toggleOff\n     * mark\n     * image\n     * window\n     */\n\n    segPtr = linePtr->segPtr;\n    while ((offset < endByte) && (segPtr != NULL)) {\n\tTcl_Size currentSize = segPtr->size;\n\tbool lineChanged = false;\n\n\tif ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) &&\n\t\t(offset + currentSize > startByte)) {\n\t    Tcl_Size last = currentSize;\t/* Index of last char in seg. */\n\t    Tcl_Size first = 0;\t\t/* Index of first char in seg. */\n\n\t    if (offset + currentSize > endByte) {\n\t\tlast = endByte - offset;\n\t    }\n\t    if (startByte > offset) {\n\t\tfirst = startByte - offset;\n\t    }\n\t    if (last != currentSize) {\n\t\t/*\n\t\t * To avoid modifying the string in place we copy over just\n\t\t * the segment that we want. Since DumpSegment can modify the\n\t\t * text, we could not confidently revert the modification\n\t\t * here.\n\t\t */\n\n\t\tTcl_Size length = last - first;\n\t\tchar *range = (char *)Tcl_Alloc((size_t)length + 1);\n\n\t\tmemcpy(range, segPtr->body.chars + first, (size_t)length);\n\t\trange[length] = '\\0';\n\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset + first, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"text\", range,\n\t\t\tcommand, &index, what);\n\t\tTcl_Free(range);\n\t    } else {\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset + first, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"text\",\n\t\t\tsegPtr->body.chars + first, command, &index, what);\n\t    }\n\t} else if ((offset >= startByte)) {\n\t    if ((what & TK_DUMP_MARK)\n\t\t    && (segPtr->typePtr == &tkTextLeftMarkType\n\t\t    || segPtr->typePtr == &tkTextRightMarkType)) {\n\t\tconst char *name;\n\t\tTkTextMark *markPtr = &segPtr->body.mark;\n\n\t\tif (segPtr == textPtr->insertMarkPtr) {\n\t\t    name = \"insert\";\n\t\t} else if (segPtr == textPtr->currentMarkPtr) {\n\t\t    name = \"current\";\n\t\t} else if (markPtr->hPtr == NULL) {\n\t\t    name = NULL;\n\t\t    lineChanged = 0;\n\t\t} else {\n\t\t    name = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,\n\t\t\t    markPtr->hPtr);\n\t\t}\n\t\tif (name != NULL) {\n\t\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\t    lineno, offset, &index);\n\t\t    lineChanged = DumpSegment(textPtr, interp, \"mark\", name,\n\t\t\t    command, &index, what);\n\t\t}\n\t    } else if ((what & TK_DUMP_TAG) &&\n\t\t    (segPtr->typePtr == &tkTextToggleOnType)) {\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"tagon\",\n\t\t\tsegPtr->body.toggle.tagPtr->name, command, &index,\n\t\t\twhat);\n\t    } else if ((what & TK_DUMP_TAG) &&\n\t\t    (segPtr->typePtr == &tkTextToggleOffType)) {\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"tagoff\",\n\t\t\tsegPtr->body.toggle.tagPtr->name, command, &index,\n\t\t\twhat);\n\t    } else if ((what & TK_DUMP_IMG) &&\n\t\t    (segPtr->typePtr == &tkTextEmbImageType)) {\n\t\tTkTextEmbImage *eiPtr = &segPtr->body.ei;\n\t\tconst char *name = eiPtr->name;\n\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"image\", name,\n\t\t\tcommand, &index, what);\n\t    } else if ((what & TK_DUMP_WIN) &&\n\t\t    (segPtr->typePtr == &tkTextEmbWindowType)) {\n\t\tTkTextEmbWindow *ewPtr = &segPtr->body.ew;\n\t\tconst char *pathname;\n\n\t\tif (ewPtr->tkwin == NULL) {\n\t\t    pathname = \"\";\n\t\t} else {\n\t\t    pathname = Tk_PathName(ewPtr->tkwin);\n\t\t}\n\t\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t\tlineno, offset, &index);\n\t\tlineChanged = DumpSegment(textPtr, interp, \"window\", pathname,\n\t\t\tcommand, &index, what);\n\t    }\n\t}\n\n\toffset += currentSize;\n\tif (lineChanged) {\n\t    TkTextSegment *newSegPtr;\n\t    Tcl_Size newOffset = 0;\n\n\t    textChanged = true;\n\n\t    /*\n\t     * Our indices are no longer valid.\n\t     */\n\n\t    if (textPtr->flags & DESTROYED) {\n\t\treturn textChanged;\n\t    }\n\t    linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t    textPtr, lineno);\n\t    newSegPtr = linePtr->segPtr;\n\t    if (segPtr != newSegPtr) {\n\t\twhile ((newOffset < endByte) && (newOffset < offset)\n\t\t\t&& (newSegPtr != NULL)) {\n\t\t    newOffset += currentSize;\n\t\t    newSegPtr = newSegPtr->nextPtr;\n\t\t    if (segPtr == newSegPtr) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tif (segPtr != newSegPtr && newOffset == offset\n\t\t\t&& currentSize == 0) {\n\t\t    TkTextSegment *searchPtr = newSegPtr;\n\n\t\t    while (searchPtr != NULL && searchPtr->size == 0) {\n\t\t\tif (searchPtr == segPtr) {\n\t\t\t    newSegPtr = searchPtr;\n\t\t\t    break;\n\t\t\t}\n\t\t\tsearchPtr = searchPtr->nextPtr;\n\t\t    }\n\t\t}\n\t\tsegPtr = newSegPtr;\n\t    }\n\t}\n\tif (segPtr != NULL) {\n\t    segPtr = segPtr->nextPtr;\n\t}\n    }\n    return textChanged;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DumpSegment\n *\n *\tEither append information about the current segment to the result, or\n *\tmake a script callback with that information as arguments.\n *\n * Results:\n *\tReturns 1 if the command callback made any changes to the text widget\n *\twhich will have invalidated internal structures such as TkTextSegment,\n *\tTkTextIndex, pointers. Our caller can then take action to recompute\n *\tsuch entities. Returns 0 otherwise.\n *\n * Side effects:\n *\tEither evals the callback or appends elements to the result string.\n *\tThe callback can have arbitrary side-effects.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nDumpSegment(\n    TkText *textPtr,\n    Tcl_Interp *interp,\n    const char *key,\t\t/* Segment type key. */\n    const char *value,\t\t/* Segment value. */\n    Tcl_Obj *command,\t\t/* Script callback. */\n    const TkTextIndex *index,\t/* index with line/byte position info. */\n    TCL_UNUSED(int))\t\t/* Look for TK_DUMP_INDEX bit. */\n{\n    char buffer[TK_POS_CHARS];\n    Tcl_Obj *values[3], *tuple;\n\n    TkTextPrintIndex(textPtr, index, buffer);\n    values[0] = Tcl_NewStringObj(key, -1);\n    values[1] = Tcl_NewStringObj(value, -1);\n    values[2] = Tcl_NewStringObj(buffer, -1);\n    tuple = Tcl_NewListObj(3, values);\n    if (command == NULL) {\n\tTcl_ListObjAppendList(NULL, Tcl_GetObjResult(interp), tuple);\n\tTcl_DecrRefCount(tuple);\n\treturn false;\n    } else {\n\tTcl_Size oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree);\n\tTcl_DString buf;\n\tint code;\n\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(command), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, Tcl_GetString(tuple), TCL_INDEX_NONE);\n\tcode = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tif (code != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (segment dumping command executed by text)\");\n\t    Tcl_BackgroundException(interp, code);\n\t}\n\tTcl_DecrRefCount(tuple);\n\treturn ((textPtr->flags & DESTROYED) ||\n\t\tTkBTreeEpoch(textPtr->sharedTextPtr->tree) != oldStateEpoch);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextEditUndo --\n *\n *\tUndo the last change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tApart from manipulating the undo and redo stacks, the state of the\n *\trest of the widget may also change (due to whatever is being undone).\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextEditUndo(\n    TkText *textPtr)\t\t/* Overall information about text widget. */\n{\n    int status;\n    Tcl_Obj *cmdObj;\n    int code;\n\n    if (!textPtr->sharedTextPtr->undo) {\n\treturn TCL_OK;\n    }\n\n    if (textPtr->sharedTextPtr->autoSeparators) {\n\tTkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);\n    }\n\n    /*\n     * Turn off the undo feature while we revert a compound action, setting\n     * the dirty handling mode to undo for the duration (unless it is\n     * 'fixed').\n     */\n\n    textPtr->sharedTextPtr->undo = false;\n    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {\n\ttextPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO;\n    }\n\n    status = TkUndoRevert(textPtr->sharedTextPtr->undoStack);\n\n    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {\n\ttextPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;\n    }\n    textPtr->sharedTextPtr->undo = true;\n\n    if (textPtr->sharedTextPtr->autoSeparators) {\n\tTkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);\n    }\n\n    /*\n     * Convert undo/redo temporary marks set by TkUndoRevert() into\n     * indices left in the interp result.\n     */\n\n    cmdObj = Tcl_ObjPrintf(\"::tk::TextUndoRedoProcessMarks %s\",\n\t    Tk_PathName(textPtr->tkwin));\n    Tcl_IncrRefCount(cmdObj);\n    code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_AddErrorInfo(textPtr->interp,\n\t\t\"\\n    (on undoing)\");\n\tTcl_BackgroundException(textPtr->interp, code);\n    }\n    Tcl_DecrRefCount(cmdObj);\n\n    return status;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextEditRedo --\n *\n *\tRedo the last undone change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tApart from manipulating the undo and redo stacks, the state of the\n *\trest of the widget may also change (due to whatever is being redone).\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextEditRedo(\n    TkText *textPtr)\t\t/* Overall information about text widget. */\n{\n    int status;\n    Tcl_Obj *cmdObj;\n    int code;\n\n    if (!textPtr->sharedTextPtr->undo) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Turn off the undo feature temporarily while we revert a previously\n     * undone compound action, setting the dirty handling mode to redo for the\n     * duration (unless it is 'fixed').\n     */\n\n    textPtr->sharedTextPtr->undo = false;\n    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {\n\ttextPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO;\n    }\n\n    status = TkUndoApply(textPtr->sharedTextPtr->undoStack);\n\n    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {\n\ttextPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;\n    }\n    textPtr->sharedTextPtr->undo = true;\n\n    /*\n     * Convert undo/redo temporary marks set by TkUndoApply() into\n     * indices left in the interp result.\n     */\n\n    cmdObj = Tcl_ObjPrintf(\"::tk::TextUndoRedoProcessMarks %s\",\n\t    Tk_PathName(textPtr->tkwin));\n    Tcl_IncrRefCount(cmdObj);\n    code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_AddErrorInfo(textPtr->interp,\n\t\t\"\\n    (on undoing)\");\n\tTcl_BackgroundException(textPtr->interp, code);\n    }\n    Tcl_DecrRefCount(cmdObj);\n\n    return status;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextEditCmd --\n *\n *\tHandle the subcommands to \"$text edit ...\". See documentation for\n *\tdetails.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextEditCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int index, setModified, oldModified;\n    bool canRedo = false;\n    bool canUndo = false;\n\n    static const char *const editOptionStrings[] = {\n\t\"canundo\", \"canredo\", \"modified\", \"redo\", \"reset\", \"separator\",\n\t\"undo\", NULL\n    };\n    enum editOptions {\n\tEDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,\n\tEDIT_SEPARATOR, EDIT_UNDO\n    };\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], editOptionStrings,\n\t    sizeof(char *), \"edit option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum editOptions) index) {\n    case EDIT_CANREDO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t     return TCL_ERROR;\n\t}\n\tif (textPtr->sharedTextPtr->undo) {\n\t    canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(canRedo));\n\tbreak;\n    case EDIT_CANUNDO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t     return TCL_ERROR;\n\t}\n\tif (textPtr->sharedTextPtr->undo) {\n\t    canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(canUndo));\n\tbreak;\n    case EDIT_MODIFIED:\n\tif (objc == 3) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewBooleanObj(textPtr->sharedTextPtr->isDirty));\n\t    return TCL_OK;\n\t} else if (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"?boolean?\");\n\t    return TCL_ERROR;\n\t} else if (Tcl_GetBooleanFromObj(interp, objv[3],\n\t\t&setModified) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Set or reset the dirty info, and trigger a Modified event.\n\t */\n\n\tsetModified = setModified ? 1 : 0;\n\n\toldModified = textPtr->sharedTextPtr->isDirty;\n\ttextPtr->sharedTextPtr->isDirty = setModified;\n\tif (setModified) {\n\t    textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED;\n\t} else {\n\t    textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;\n\t}\n\n\t/*\n\t * Only issue the <<Modified>> event if the flag actually changed.\n\t * However, degree of modified-ness doesn't matter. [Bug 1799782]\n\t */\n\n\tif ((!oldModified) != (!setModified)) {\n\t    GenerateModifiedEvent(textPtr);\n\t}\n\tbreak;\n    case EDIT_REDO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tcanUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);\n\tif (TextEditRedo(textPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"nothing to redo\", -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_REDO\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tcanRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);\n\tif (!canUndo || !canRedo) {\n\t    GenerateUndoStackEvent(textPtr);\n\t}\n\tbreak;\n    case EDIT_RESET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tcanUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);\n\tcanRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);\n\tTkUndoClearStacks(textPtr->sharedTextPtr->undoStack);\n\tif (canUndo || canRedo) {\n\t    GenerateUndoStackEvent(textPtr);\n\t}\n\tbreak;\n    case EDIT_SEPARATOR:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tTkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack);\n\tbreak;\n    case EDIT_UNDO:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tcanRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);\n\tif (TextEditUndo(textPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"nothing to undo\", -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_UNDO\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tcanUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);\n\tif (!canRedo || !canUndo) {\n\t    GenerateUndoStackEvent(textPtr);\n\t}\n\tbreak;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextGetText --\n *\n *\tReturns the text from indexPtr1 to indexPtr2, placing that text in a\n *\tstring object which is returned with a refCount of zero.\n *\n *\tSince the amount of text may potentially be several megabytes (e.g.\n *\tin text editors built on the text widget), efficiency is very\n *\timportant. We may want to investigate the efficiency of the\n *\tTcl_AppendToObj more carefully (e.g. if we know we are going to be\n *\tappending several thousand lines, we could attempt to pre-allocate a\n *\tlarger space).\n *\n * Results:\n *\tTcl_Obj of string type containing the specified text. If the\n *\tvisibleOnly flag is set to 1, then only those characters which are not\n *\telided will be returned. Otherwise (flag is 0) all characters in the\n *\tgiven range are returned.\n *\n * Side effects:\n *\tMemory will be allocated for the new object. Remember to free it if it\n *\tisn't going to be stored appropriately.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nTextGetText(\n    const TkText *textPtr,\t/* Information about text widget. */\n    const TkTextIndex *indexPtr1,\n\t\t\t\t/* Get text from this index... */\n    const TkTextIndex *indexPtr2,\n\t\t\t\t/* ...to this index. */\n    int visibleOnly)\t\t/* If non-zero, then only return non-elided\n\t\t\t\t * characters. */\n{\n    TkTextIndex tmpIndex;\n    Tcl_Obj *resultPtr = Tcl_NewObj();\n\n    TkTextMakeByteIndex(indexPtr1->tree, textPtr,\n\t    TkBTreeLinesTo(textPtr, indexPtr1->linePtr),\n\t    indexPtr1->byteIndex, &tmpIndex);\n\n    if (TkTextIndexCmp(indexPtr1, indexPtr2) < 0) {\n\twhile (1) {\n\t    Tcl_Size offset;\n\t    TkTextSegment *segPtr = TkTextIndexToSeg(&tmpIndex, &offset);\n\t    Tcl_Size last = segPtr->size, last2;\n\n\t    if (tmpIndex.linePtr == indexPtr2->linePtr) {\n\t\t/*\n\t\t * The last line that was requested must be handled carefully,\n\t\t * because we may need to break out of this loop in the middle\n\t\t * of the line.\n\t\t */\n\n\t\tif (indexPtr2->byteIndex == tmpIndex.byteIndex) {\n\t\t    break;\n\t\t}\n\t\tlast2 = indexPtr2->byteIndex - tmpIndex.byteIndex + offset;\n\t\tif (last2 < last) {\n\t\t    last = last2;\n\t\t}\n\t    }\n\t    if (segPtr->typePtr == &tkTextCharType &&\n\t\t    !(visibleOnly && TkTextIsElided(textPtr,&tmpIndex,NULL))){\n\t\tTcl_AppendToObj(resultPtr, segPtr->body.chars + offset,\n\t\t\tlast - offset);\n\t    }\n\t    TkTextIndexForwBytes(textPtr, &tmpIndex, last-offset, &tmpIndex);\n\t}\n    }\n    return resultPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateModifiedEvent --\n *\n *\tSend an event that the text was modified. This is equivalent to:\n *\t   event generate $textWidget <<Modified>>\n *\tfor all peers of $textWidget.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMay force the text window into existence.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateModifiedEvent(\n    TkText *textPtr)\t/* Information about text widget. */\n{\n    for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;\n\t    textPtr = textPtr->next) {\n\tTk_MakeWindowExist(textPtr->tkwin);\n\tTk_SendVirtualEvent(textPtr->tkwin, \"Modified\", NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateUndoStackEvent --\n *\n *\tSend an event that the undo or redo stack became empty or unempty.\n *\tThis is equivalent to:\n *\t   event generate $textWidget <<UndoStack>>\n *\tfor all peers of $textWidget.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMay force the text window (and all peers) into existence.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateUndoStackEvent(\n    TkText *textPtr)\t/* Information about text widget. */\n{\n    for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;\n\t    textPtr = textPtr->next) {\n\tTk_MakeWindowExist(textPtr->tkwin);\n\tTk_SendVirtualEvent(textPtr->tkwin, \"UndoStack\", NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateDirtyFlag --\n *\n *\tUpdates the dirtyness of the text widget\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateDirtyFlag(\n    TkSharedText *sharedTextPtr)/* Information about text widget. */\n{\n    int oldDirtyFlag;\n\n    /*\n     * If we've been forced to be dirty, we stay dirty (until explicitly\n     * reset, of course).\n     */\n\n    if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) {\n\treturn;\n    }\n\n    if (sharedTextPtr->isDirty < 0\n\t    && sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) {\n\t/*\n\t * If dirty flag is negative, only redo operations can make it zero\n\t * again. If we do a normal operation, it can never become zero any\n\t * more (other than by explicit reset).\n\t */\n\n\tsharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED;\n\treturn;\n    }\n\n    oldDirtyFlag = sharedTextPtr->isDirty;\n    if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_UNDO) {\n\tsharedTextPtr->isDirty--;\n    } else {\n\tsharedTextPtr->isDirty++;\n    }\n\n    if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) {\n\tGenerateModifiedEvent(sharedTextPtr->peers);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextRunAfterSyncCmd --\n *\n *\tThis function is called by the event loop and executes the command\n *      scheduled by [.text sync -command $cmd].\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAnything may happen, depending on $cmd contents.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextRunAfterSyncCmd(\n    void *clientData)\t\t/* Information about text widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    int code;\n\n    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t/*\n\t* The widget has been deleted. Don't do anything.\n\t*/\n\n\tif (textPtr->refCount-- <= 1) {\n\t    Tcl_Free(textPtr);\n\t}\n\treturn;\n    }\n\n    Tcl_Preserve(textPtr->interp);\n    code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);\n    if (code == TCL_ERROR) {\n\tTcl_AddErrorInfo(textPtr->interp, \"\\n    (text sync)\");\n\tTcl_BackgroundException(textPtr->interp, TCL_ERROR);\n    }\n    Tcl_Release(textPtr->interp);\n    Tcl_DecrRefCount(textPtr->afterSyncCmd);\n    textPtr->afterSyncCmd = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SearchPerform --\n *\n *\tOverall control of search process. Is given a pattern, a starting\n *\tindex and an ending index, and attempts to perform a search. This\n *\tfunction is actually completely independent of Tk, and could in the\n *\tfuture be split off.\n *\n * Results:\n *\tStandard Tcl result code. In particular, if fromPtr or toPtr are not\n *\tconsidered valid by the 'lineIndexProc', an error will be thrown and\n *\tno search performed.\n *\n * Side effects:\n *\tSee 'SearchCore'.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSearchPerform(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    SearchSpec *searchSpecPtr,\t/* Search parameters. */\n    Tcl_Obj *patObj,\t\t/* Contains an exact string or a regexp\n\t\t\t\t * pattern. Must have a refCount > 0. */\n    Tcl_Obj *fromPtr,\t\t/* Contains information describing the first\n\t\t\t\t * index. */\n    Tcl_Obj *toPtr)\t\t/* NULL or information describing the last\n\t\t\t\t * index. */\n{\n    /*\n     * Find the starting line and starting offset (measured in Unicode chars\n     * for regexp search, utf-8 bytes for exact search).\n     */\n\n    if (searchSpecPtr->lineIndexProc(interp, fromPtr, searchSpecPtr,\n\t    &searchSpecPtr->startLine,\n\t    &searchSpecPtr->startOffset) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Find the optional end location, similarly.\n     */\n\n    if (toPtr != NULL) {\n\tconst TkTextIndex *indexToPtr, *indexFromPtr;\n\tTkText *textPtr = (TkText *)searchSpecPtr->clientData;\n\n\tindexToPtr = TkTextGetIndexFromObj(interp, textPtr, toPtr);\n\tif (indexToPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tindexFromPtr = TkTextGetIndexFromObj(interp, textPtr, fromPtr);\n\n\t/*\n\t * Check for any empty search range here. It might be better in the\n\t * future to embed that in SearchCore (whose default behaviour is to\n\t * wrap when given a negative search range).\n\t */\n\n\tif (TkTextIndexCmp(indexFromPtr, indexToPtr) ==\n\t\t(searchSpecPtr->backwards ? -1 : 1)) {\n\t    return TCL_OK;\n\t}\n\n\tif (searchSpecPtr->lineIndexProc(interp, toPtr, searchSpecPtr,\n\t\t&searchSpecPtr->stopLine,\n\t\t&searchSpecPtr->stopOffset) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tsearchSpecPtr->stopLine = -1;\n    }\n\n    /*\n     * Scan through all of the lines of the text circularly, starting at the\n     * given index. 'patObj' is the pattern which may be an exact string or a\n     * regexp pattern depending on the flags in searchSpecPtr.\n     */\n\n    return SearchCore(interp, searchSpecPtr, patObj);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SearchCore --\n *\n *\tThe core of the search function. This function is actually completely\n *\tindependent of Tk, and could in the future be split off.\n *\n *\tThe function assumes regexp-based searches operate on Unicode strings,\n *\tand exact searches on utf-8 strings. Therefore the 'foundMatchProc'\n *\tand 'addLineProc' need to be aware of this distinction.\n *\n * Results:\n *\tStandard Tcl result code.\n *\n * Side effects:\n *\tOnly those of the 'searchSpecPtr->foundMatchProc' which is called\n *\twhenever a match is found.\n *\n *\tNote that the way matching across multiple lines is implemented, we\n *\tstart afresh with each line we have available, even though we may\n *\talready have examined the contents of that line (and further ones) if\n *\twe were attempting a multi-line match using the previous line. This\n *\tmeans there may be ways to speed this up a lot by not throwing away\n *\tall the multi-line information one has accumulated. Profiling should\n *\tbe done to see where the bottlenecks lie before attempting this,\n *\thowever. We would also need to be very careful such optimisation keep\n *\twithin the specified search bounds.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSearchCore(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    SearchSpec *searchSpecPtr,\t/* Search parameters. */\n    Tcl_Obj *patObj)\t\t/* Contains an exact string or a regexp\n\t\t\t\t * pattern. Must have a refCount > 0. */\n{\n    /*\n     * For exact searches these are utf-8 char* offsets, for regexp searches\n     * they are Unicode char offsets.\n     */\n\n    Tcl_Size firstOffset, lastOffset;\n    Tcl_Size matchOffset,  matchLength;\n    int passes;\n    Tcl_Size lineNum = searchSpecPtr->startLine;\n    int code = TCL_OK;\n    Tcl_Obj *theLine;\n    Tcl_Size alreadySearchOffset = -1;\n\n    const char *pattern = NULL;\t/* For exact searches only. */\n    Tcl_Size firstNewLine = -1;\t/* For exact searches only. */\n    Tcl_RegExp regexp = NULL;\t/* For regexp searches only. */\n\n    /*\n     * These items are for backward regexp searches only. They are for two\n     * purposes: to allow us to report backwards matches in the correct order,\n     * even though the implementation uses repeated forward searches; and to\n     * provide for overlap checking between backwards matches on different\n     * text lines.\n     */\n\n#define LOTS_OF_MATCHES 20\n    int matchNum = LOTS_OF_MATCHES;\n    Tcl_Size smArray[2 * LOTS_OF_MATCHES];\n    Tcl_Size *storeMatch = smArray;\n    Tcl_Size *storeLength = smArray + LOTS_OF_MATCHES;\n    Tcl_Size lastBackwardsLineMatch = -1;\n    Tcl_Size lastBackwardsMatchOffset = -1;\n\n    if (searchSpecPtr->exact) {\n\t/*\n\t * Convert the pattern to lower-case if we're supposed to ignore case.\n\t */\n\n\tif (searchSpecPtr->noCase) {\n\t    patObj = Tcl_DuplicateObj(patObj);\n\n\t    /*\n\t     * This can change the length of the string behind the object's\n\t     * back, so ensure it is correctly synchronised.\n\t     */\n\n\t    Tcl_SetObjLength(patObj, Tcl_UtfToLower(Tcl_GetString(patObj)));\n\t}\n    } else {\n\t/*\n\t * Compile the regular expression. We want '^$' to match after and\n\t * before \\n respectively, so use the TCL_REG_NLANCH flag.\n\t */\n\n\tregexp = Tcl_GetRegExpFromObj(interp, patObj,\n\t\t(searchSpecPtr->noCase ? TCL_REG_NOCASE : 0)\n\t\t| (searchSpecPtr->noLineStop ? 0 : TCL_REG_NLSTOP)\n\t\t| TCL_REG_ADVANCED | TCL_REG_CANMATCH | TCL_REG_NLANCH);\n\tif (regexp == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * For exact strings, we want to know where the first newline is, and we\n     * will also use this as a flag to test whether it is even possible to\n     * match the pattern on a single line. If not we will have to search\n     * across multiple lines.\n     */\n\n    if (searchSpecPtr->exact) {\n\tconst char *nl;\n\n\t/*\n\t * We only need to set the matchLength once for exact searches, and we\n\t * do it here. It is also used below as the actual pattern length, so\n\t * it has dual purpose.\n\t */\n\n\tpattern = Tcl_GetStringFromObj(patObj, &matchLength);\n\tnl = strchr(pattern, '\\n');\n\n\t/*\n\t * If there is no newline, or it is the very end of the string, then\n\t * we don't need any special treatment, since single-line matching\n\t * will work fine.\n\t */\n\n\tif (nl != NULL && nl[1] != '\\0') {\n\t    firstNewLine = (nl - pattern);\n\t}\n    } else {\n\tmatchLength = 0;\t/* Only needed to prevent compiler warnings. */\n    }\n\n    /*\n     * Keep a reference here, so that we can be sure the object doesn't\n     * disappear behind our backs and invalidate its contents which we are\n     * using.\n     */\n\n    Tcl_IncrRefCount(patObj);\n\n    /*\n     * For building up the current line being checked.\n     */\n\n    theLine = Tcl_NewObj();\n    Tcl_IncrRefCount(theLine);\n\n    for (passes = 0; passes < 2; ) {\n\tvoid *lineInfo;\n\tint linesSearched = 1;\n\tint extraLinesSearched = 0;\n\n\tif (lineNum >= searchSpecPtr->numLines) {\n\t    /*\n\t     * Don't search the dummy last line of the text.\n\t     */\n\n\t    goto nextLine;\n\t}\n\n\t/*\n\t * Extract the text from the line, storing its length in 'lastOffset'\n\t * (in bytes if exact, chars if regexp), since obviously the length is\n\t * the maximum offset at which it is possible to find something on\n\t * this line, which is what 'lastOffset' represents.\n\t */\n\n\tlineInfo = searchSpecPtr->addLineProc(lineNum, searchSpecPtr, theLine,\n\t\t&lastOffset, &linesSearched);\n\n\tif (lineInfo == NULL) {\n\t    /*\n\t     * This should not happen, since 'lineNum' should be valid in the\n\t     * call above. However, let's try to be flexible and not cause a\n\t     * crash below.\n\t     */\n\n\t    goto nextLine;\n\t}\n\n\tif (lineNum == searchSpecPtr->stopLine && searchSpecPtr->backwards) {\n\t    firstOffset = searchSpecPtr->stopOffset;\n\t} else {\n\t    firstOffset = 0;\n\t}\n\n\tif (alreadySearchOffset >= 0) {\n\t    if (searchSpecPtr->backwards) {\n\t\tif (alreadySearchOffset < lastOffset) {\n\t\t    lastOffset = alreadySearchOffset;\n\t\t}\n\t    } else {\n\t\tif (alreadySearchOffset > firstOffset) {\n\t\t    firstOffset = alreadySearchOffset;\n\t\t}\n\t    }\n\t    alreadySearchOffset = -1;\n\t}\n\n\tif (lineNum == searchSpecPtr->startLine) {\n\t    /*\n\t     * The starting line is tricky: the first time we see it we check\n\t     * one part of the line, and the second pass through we check the\n\t     * other part of the line.\n\t     */\n\n\t    passes++;\n\t    if ((passes == 1) ^ searchSpecPtr->backwards) {\n\t\t/*\n\t\t * Forward search and first pass, or backward search and\n\t\t * second pass.\n\t\t *\n\t\t * Only use the last part of the line.\n\t\t */\n\n\t\tif (searchSpecPtr->startOffset > firstOffset) {\n\t\t    firstOffset = searchSpecPtr->startOffset;\n\t\t}\n\t\tif ((firstOffset >= lastOffset)\n\t\t    && ((lastOffset != 0) || searchSpecPtr->exact)) {\n\t\t    goto nextLine;\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * Use only the first part of the line.\n\t\t */\n\n\t\tif (searchSpecPtr->startOffset < lastOffset) {\n\t\t    lastOffset = searchSpecPtr->startOffset;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Check for matches within the current line 'lineNum'. If so, and if\n\t * we're searching backwards or for all matches, repeat the search\n\t * until we find the last match in the line. The 'lastOffset' is one\n\t * beyond the last position in the line at which a match is allowed to\n\t * begin.\n\t */\n\n\tmatchOffset = TCL_INDEX_NONE;\n\n\tif (searchSpecPtr->exact) {\n\t    int maxExtraLines = 0;\n\t    const char *startOfLine = Tcl_GetString(theLine);\n\n\t    CLANG_ASSERT(pattern);\n\t    do {\n\t\tint ch;\n\t\tconst char *p;\n\t\tTcl_Size lastFullLine = lastOffset;\n\n\t\tif (firstNewLine == -1) {\n\t\t    if (searchSpecPtr->strictLimits\n\t\t\t    && (firstOffset + matchLength > lastOffset)) {\n\t\t\t/*\n\t\t\t * Not enough characters to match.\n\t\t\t */\n\n\t\t\tbreak;\n\t\t    }\n\n\t\t    /*\n\t\t     * Single line matching. We want to scan forwards or\n\t\t     * backwards as appropriate.\n\t\t     */\n\n\t\t    if (searchSpecPtr->backwards) {\n\t\t\t/*\n\t\t\t * Search back either from the previous match or from\n\t\t\t * 'startOfLine + lastOffset - 1' until we find a\n\t\t\t * match.\n\t\t\t */\n\n\t\t\tconst char c = matchLength ? pattern[0] : '\\0';\n\n\t\t\tif (alreadySearchOffset >= 0) {\n\t\t\t    p = startOfLine + alreadySearchOffset;\n\t\t\t    alreadySearchOffset = -1;\n\t\t\t} else {\n\t\t\t    p = startOfLine + lastOffset -1;\n\t\t\t}\n\t\t\twhile (p >= startOfLine + firstOffset) {\n\t\t\t    if (matchLength == 0 || (p[0] == c && !strncmp(\n\t\t\t\t     p, pattern, (size_t)matchLength))) {\n\t\t\t\tgoto backwardsMatch;\n\t\t\t    }\n\t\t\t    p--;\n\t\t\t}\n\t\t\tbreak;\n\t\t    } else {\n\t\t\tp = strstr(startOfLine + firstOffset, pattern);\n\t\t    }\n\t\t    if (p == NULL) {\n\t\t\t/*\n\t\t\t * Single line match failed.\n\t\t\t */\n\n\t\t\tbreak;\n\t\t    }\n\t\t} else if (firstNewLine >= (lastOffset - firstOffset)) {\n\t\t    /*\n\t\t     * Multi-line match, but not enough characters to match.\n\t\t     */\n\n\t\t    break;\n\t\t} else {\n\t\t    /*\n\t\t     * Multi-line match has only one possible match position,\n\t\t     * because we know where the '\\n' is.\n\t\t     */\n\n\t\t    p = startOfLine + lastOffset - firstNewLine - 1;\n\t\t    if (strncmp(p, pattern, (size_t)firstNewLine + 1)) {\n\t\t\t/*\n\t\t\t * No match.\n\t\t\t */\n\n\t\t\tbreak;\n\t\t    } else {\n\t\t\tint extraLines = 1;\n\n\t\t\t/*\n\t\t\t * If we find a match that overlaps more than one\n\t\t\t * line, we will use this value to determine the first\n\t\t\t * allowed starting offset for the following search\n\t\t\t * (to avoid overlapping results).\n\t\t\t */\n\n\t\t\tTcl_Size lastTotal = lastOffset;\n\t\t\tTcl_Size skipFirst = lastOffset - firstNewLine -1;\n\n\t\t\t/*\n\t\t\t * We may be able to match if given more text. The\n\t\t\t * following 'while' block handles multi-line exact\n\t\t\t * searches.\n\t\t\t */\n\n\t\t\twhile (1) {\n\t\t\t    lastFullLine = lastTotal;\n\n\t\t\t    if (lineNum+extraLines>=searchSpecPtr->numLines) {\n\t\t\t\tp = NULL;\n\t\t\t\tbreak;\n\t\t\t    }\n\n\t\t\t    /*\n\t\t\t     * Only add the line if we haven't already done so\n\t\t\t     * already.\n\t\t\t     */\n\n\t\t\t    if (extraLines > maxExtraLines) {\n\t\t\t\tif (searchSpecPtr->addLineProc(lineNum\n\t\t\t\t\t+ extraLines, searchSpecPtr, theLine,\n\t\t\t\t\t&lastTotal, &extraLines) == NULL) {\n\t\t\t\t    p = NULL;\n\t\t\t\t    if (!searchSpecPtr->backwards) {\n\t\t\t\t\textraLinesSearched = extraLines;\n\t\t\t\t    }\n\t\t\t\t    break;\n\t\t\t\t}\n\t\t\t\tmaxExtraLines = extraLines;\n\t\t\t    }\n\n\t\t\t    startOfLine = Tcl_GetString(theLine);\n\t\t\t    p = startOfLine + skipFirst;\n\n\t\t\t    /*\n\t\t\t     * Use the fact that 'matchLength = patLength' for\n\t\t\t     * exact searches.\n\t\t\t     */\n\n\t\t\t    if (lastTotal - skipFirst >= matchLength) {\n\t\t\t\t/*\n\t\t\t\t * We now have enough text to match, so we\n\t\t\t\t * make a final test and break whatever the\n\t\t\t\t * result.\n\t\t\t\t */\n\n\t\t\t\tif (strncmp(p, pattern, (size_t)matchLength)) {\n\t\t\t\t    p = NULL;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t    } else {\n\t\t\t\t/*\n\t\t\t\t * Not enough text yet, but check the prefix.\n\t\t\t\t */\n\n\t\t\t\tif (strncmp(p, pattern,\n\t\t\t\t\t(unsigned)(lastTotal - skipFirst))) {\n\t\t\t\t    p = NULL;\n\t\t\t\t    break;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * The prefix matches, so keep looking.\n\t\t\t\t */\n\t\t\t    }\n\t\t\t    extraLines++;\n\t\t\t}\n\t\t\t/*\n\t\t\t * If we reach here, with p != NULL, we've found a\n\t\t\t * multi-line match, else we started a multi-match but\n\t\t\t * didn't finish it off, so we go to the next line.\n\t\t\t */\n\n\t\t\tif (p == NULL) {\n\t\t\t    break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * We've found a multi-line match.\n\t\t\t */\n\n\t\t\tif (extraLines > 0) {\n\t\t\t    extraLinesSearched = extraLines - 1;\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t    backwardsMatch:\n\t\tif ((p - startOfLine) >= lastOffset) {\n\t\t    break;\n\t\t}\n\n\t\t/*\n\t\t * Remember the match.\n\t\t */\n\n\t\tmatchOffset = p - startOfLine;\n\n\t\tif (searchSpecPtr->all &&\n\t\t\t!searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,\n\t\t\tlineInfo, theLine, matchOffset, matchLength)) {\n\t\t    /*\n\t\t     * We reached the end of the search.\n\t\t     */\n\n\t\t    goto searchDone;\n\t\t}\n\n\t\tif (!searchSpecPtr->overlap) {\n\t\t    if (searchSpecPtr->backwards) {\n\t\t\talreadySearchOffset = p - startOfLine;\n\t\t\tif (firstNewLine != -1) {\n\t\t\t    break;\n\t\t\t} else {\n\t\t\t    alreadySearchOffset -= (matchLength ? matchLength : 1);\n\t\t\t    if (alreadySearchOffset < 0) {\n\t\t\t\tbreak;\n\t\t\t    }\n\t\t\t}\n\t\t    } else {\n\t\t\tfirstOffset = matchLength ? p - startOfLine + matchLength\n\t\t\t\t\t\t  : p - startOfLine + 1;\n\t\t\tif (firstOffset >= lastOffset) {\n\t\t\t    /*\n\t\t\t     * Now, we have to be careful not to find\n\t\t\t     * overlapping matches either on the same or\n\t\t\t     * following lines. Assume that if we did find\n\t\t\t     * something, it goes until the last extra line we\n\t\t\t     * added.\n\t\t\t     *\n\t\t\t     * We can break out of the loop, since we know no\n\t\t\t     * more will be found.\n\t\t\t     */\n\n\t\t\t    if (!searchSpecPtr->backwards) {\n\t\t\t\talreadySearchOffset =\n\t\t\t\t\tfirstOffset - lastFullLine;\n\t\t\t\tbreak;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t} else {\n\t\t    if (searchSpecPtr->backwards) {\n\t\t\talreadySearchOffset = p - startOfLine - 1;\n\t\t\tif (alreadySearchOffset < 0) {\n\t\t\t    break;\n\t\t\t}\n\t\t    } else {\n\t\t\tfirstOffset = p - startOfLine +\n\t\t\t\tTcl_UtfToUniChar(startOfLine+matchOffset,&ch);\n\t\t    }\n\t\t}\n\t    } while (searchSpecPtr->all);\n\t} else {\n\t    int maxExtraLines = 0;\n\t    int matches = 0;\n\t    Tcl_Size lastNonOverlap = -1;\n\n\t    do {\n\t\tTcl_RegExpInfo info;\n\t\tint match;\n\t\tTcl_Size lastFullLine = lastOffset;\n\n\t\tmatch = Tcl_RegExpExecObj(interp, regexp, theLine,\n\t\t\tfirstOffset, 1, (firstOffset>0 ? TCL_REG_NOTBOL : 0));\n\t\tif (match < 0) {\n\t\t    code = TCL_ERROR;\n\t\t    goto searchDone;\n\t\t}\n\t\tTcl_RegExpGetInfo(regexp, &info);\n\n\t\t/*\n\t\t * If we don't have a match, or if we do, but it extends to\n\t\t * the end of the line, we must try to add more lines to get a\n\t\t * full greedy match.\n\t\t */\n\n\t\tif (!match ||\n\t\t\t((info.extendStart == info.matches[0].start)\n\t\t\t&& (info.matches[0].end == (lastOffset - firstOffset)))) {\n\t\t    int extraLines = 0;\n\t\t    Tcl_Size prevFullLine;\n\n\t\t    /*\n\t\t     * If we find a match that overlaps more than one line, we\n\t\t     * will use this value to determine the first allowed\n\t\t     * starting offset for the following search (to avoid\n\t\t     * overlapping results).\n\t\t     */\n\n\t\t    Tcl_Size lastTotal = lastOffset;\n\n\t\t    if ((lastBackwardsLineMatch != -1)\n\t\t\t    && (lastBackwardsLineMatch == (lineNum + 1))) {\n\t\t\tlastNonOverlap = lastTotal;\n\t\t    }\n\n\t\t    if (info.extendStart < 0) {\n\t\t\t/*\n\t\t\t * No multi-line match is possible.\n\t\t\t */\n\n\t\t\tbreak;\n\t\t    }\n\n\t\t    /*\n\t\t     * We may be able to match if given more text. The\n\t\t     * following 'while' block handles multi-line regexp\n\t\t     * searches.\n\t\t     */\n\n\t\t    while (1) {\n\t\t\tprevFullLine = lastTotal;\n\n\t\t\t/*\n\t\t\t * Move firstOffset to first possible start.\n\t\t\t */\n\n\t\t\tif (!match) {\n\t\t\t    firstOffset += info.extendStart;\n\t\t\t}\n\t\t\tif (firstOffset >= lastOffset) {\n\t\t\t    /*\n\t\t\t     * We're being told that the only possible new\n\t\t\t     * match is starting after the end of the line.\n\t\t\t     * But, that is the next line which we will handle\n\t\t\t     * when we look at that line.\n\t\t\t     */\n\n\t\t\t    if (!match && !searchSpecPtr->backwards\n\t\t\t\t    && (firstOffset == 0)) {\n\t\t\t\textraLinesSearched = extraLines;\n\t\t\t    }\n\t\t\t    break;\n\t\t\t}\n\n\t\t\tif (lineNum + extraLines >= searchSpecPtr->numLines) {\n\t\t\t    break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Add next line, provided we haven't already done so.\n\t\t\t */\n\n\t\t\tif (extraLines > maxExtraLines) {\n\t\t\t    if (searchSpecPtr->addLineProc(lineNum\n\t\t\t\t    + extraLines, searchSpecPtr, theLine,\n\t\t\t\t    &lastTotal, &extraLines) == NULL) {\n\t\t\t\t/*\n\t\t\t\t * There are no more acceptable lines, so we\n\t\t\t\t * can say we have searched all of these.\n\t\t\t\t */\n\n\t\t\t\tif (!match && !searchSpecPtr->backwards) {\n\t\t\t\t    extraLinesSearched = extraLines;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t    }\n\n\t\t\t    maxExtraLines = extraLines;\n\t\t\t    if ((lastBackwardsLineMatch != -1)\n\t\t\t\t    && (lastBackwardsLineMatch\n\t\t\t\t    == (lineNum + extraLines + 1))) {\n\t\t\t\tlastNonOverlap = lastTotal;\n\t\t\t    }\n\t\t\t}\n\n\t\t\tmatch = Tcl_RegExpExecObj(interp, regexp, theLine,\n\t\t\t\tfirstOffset, 1,\n\t\t\t\t((firstOffset > 0) ? TCL_REG_NOTBOL : 0));\n\t\t\tif (match < 0) {\n\t\t\t    code = TCL_ERROR;\n\t\t\t    goto searchDone;\n\t\t\t}\n\t\t\tTcl_RegExpGetInfo(regexp, &info);\n\n\t\t\t/*\n\t\t\t * Unfortunately there are bugs in Tcl's regexp\n\t\t\t * library, which tells us that info.extendStart is\n\t\t\t * zero when it should not be (should be -1), which\n\t\t\t * makes our task a bit more complicated here. We\n\t\t\t * check if there was a match, and the end of the\n\t\t\t * match leaves an entire extra line unmatched, then\n\t\t\t * we stop searching. Clearly it still might sometimes\n\t\t\t * be possible to add more text and match again, but\n\t\t\t * Tcl's regexp library doesn't tell us that.\n\t\t\t *\n\t\t\t * This means we often add and search one more line\n\t\t\t * than might be necessary if Tcl were able to give us\n\t\t\t * a correct value of info.extendStart under all\n\t\t\t * circumstances.\n\t\t\t */\n\n\t\t\tif ((match &&\n\t\t\t\tfirstOffset + info.matches[0].end != lastTotal &&\n\t\t\t\tfirstOffset + info.matches[0].end < prevFullLine)\n\t\t\t\t|| info.extendStart < 0) {\n\t\t\t    break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * If there is a match, but that match starts after\n\t\t\t * the end of the first line, then we'll handle that\n\t\t\t * next time around, when we're actually looking at\n\t\t\t * that line.\n\t\t\t */\n\n\t\t\tif (match && (info.matches[0].start >= lastOffset)) {\n\t\t\t    break;\n\t\t\t}\n\t\t\tif (match && ((firstOffset + info.matches[0].end)\n\t\t\t\t>= prevFullLine)) {\n\t\t\t    if (extraLines > 0) {\n\t\t\t\textraLinesSearched = extraLines - 1;\n\t\t\t    }\n\t\t\t    lastFullLine = prevFullLine;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * The prefix matches, so keep looking.\n\t\t\t */\n\n\t\t\textraLines++;\n\t\t    }\n\n\t\t    /*\n\t\t     * If we reach here with 'match == 1', we've found a\n\t\t     * multi-line match, which we will record in the code\n\t\t     * which follows directly else we started a multi-line\n\t\t     * match but didn't finish it off, so we go to the next\n\t\t     * line.\n\t\t     */\n\n\t\t    if (!match) {\n\t\t\t/*\n\t\t\t * Here is where we could perform an optimisation,\n\t\t\t * since we have already retrieved the contents of the\n\t\t\t * next line (perhaps many more), so we shouldn't\n\t\t\t * really throw it all away and start again. This\n\t\t\t * could be particularly important for complex regexp\n\t\t\t * searches.\n\t\t\t *\n\t\t\t * This 'break' will take us to just before the\n\t\t\t * 'nextLine:' below.\n\t\t\t */\n\n\t\t\tbreak;\n\t\t    }\n\n\t\t    if (lastBackwardsLineMatch != -1) {\n\t\t\tif ((lineNum + linesSearched + extraLinesSearched)\n\t\t\t\t== lastBackwardsLineMatch) {\n\t\t\t    /*\n\t\t\t     * Possible overlap or inclusion.\n\t\t\t     */\n\n\t\t\t    Tcl_Size thisOffset = firstOffset + info.matches[0].end\n\t\t\t\t    - info.matches[0].start;\n\n\t\t\t    if (lastNonOverlap != -1) {\n\t\t\t\t/*\n\t\t\t\t * Possible overlap or enclosure.\n\t\t\t\t */\n\n\t\t\t\tif (thisOffset - lastNonOverlap >=\n\t\t\t\t\tlastBackwardsMatchOffset + matchLength){\n\t\t\t\t    /*\n\t\t\t\t     * Totally encloses previous match, so\n\t\t\t\t     * forget the previous match.\n\t\t\t\t     */\n\n\t\t\t\t    lastBackwardsLineMatch = -1;\n\t\t\t\t} else if ((thisOffset - lastNonOverlap)\n\t\t\t\t\t> lastBackwardsMatchOffset) {\n\t\t\t\t    /*\n\t\t\t\t     * Overlap. Previous match is ok, and the\n\t\t\t\t     * current match is only ok if we are\n\t\t\t\t     * searching with -overlap.\n\t\t\t\t     */\n\n\t\t\t\t    if (searchSpecPtr->overlap) {\n\t\t\t\t\tgoto recordBackwardsMatch;\n\t\t\t\t    } else {\n\t\t\t\t\tmatch = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t    }\n\t\t\t\t} else {\n\t\t\t\t    /*\n\t\t\t\t     * No overlap, although the same line was\n\t\t\t\t     * reached.\n\t\t\t\t     */\n\n\t\t\t\t    goto recordBackwardsMatch;\n\t\t\t\t}\n\t\t\t    } else {\n\t\t\t\t/*\n\t\t\t\t * No overlap.\n\t\t\t\t */\n\n\t\t\t\tgoto recordBackwardsMatch;\n\t\t\t    }\n\t\t\t} else if (lineNum+linesSearched+extraLinesSearched\n\t\t\t\t< lastBackwardsLineMatch) {\n\t\t\t    /*\n\t\t\t     * No overlap.\n\t\t\t     */\n\n\t\t\t    goto recordBackwardsMatch;\n\t\t\t} else {\n\t\t\t    /*\n\t\t\t     * Totally enclosed.\n\t\t\t     */\n\n\t\t\t    lastBackwardsLineMatch = -1;\n\t\t\t}\n\t\t    }\n\n\t\t} else {\n\t\t    /*\n\t\t     * Matched in a single line.\n\t\t     */\n\n\t\t    if (lastBackwardsLineMatch != -1) {\n\t\t    recordBackwardsMatch:\n\t\t\tsearchSpecPtr->foundMatchProc(lastBackwardsLineMatch,\n\t\t\t\tsearchSpecPtr, NULL, NULL,\n\t\t\t\tlastBackwardsMatchOffset, matchLength);\n\t\t\tlastBackwardsLineMatch = -1;\n\t\t\tif (!searchSpecPtr->all) {\n\t\t\t    goto searchDone;\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t\tfirstOffset += info.matches[0].start;\n\t\tif (firstOffset >= lastOffset) {\n\t\t    break;\n\t\t}\n\n\t\t/*\n\t\t * Update our local variables with the match, if we haven't\n\t\t * yet found anything, or if we're doing '-all' or\n\t\t * '-backwards' _and_ this match isn't fully enclosed in the\n\t\t * previous match.\n\t\t */\n\n\t\tif (matchOffset == -1 ||\n\t\t\t((searchSpecPtr->all || searchSpecPtr->backwards)\n\t\t\t&& ((firstOffset < matchOffset)\n\t\t\t|| ((firstOffset + info.matches[0].end\n\t\t\t\t- info.matches[0].start)\n\t\t\t\t> matchOffset + matchLength)))) {\n\n\t\t    matchOffset = firstOffset;\n\t\t    matchLength = info.matches[0].end - info.matches[0].start;\n\n\t\t    if (searchSpecPtr->backwards) {\n\t\t\t/*\n\t\t\t * To get backwards searches in the correct order, we\n\t\t\t * must store them away here.\n\t\t\t */\n\n\t\t\tif (matches == matchNum) {\n\t\t\t    /*\n\t\t\t     * We've run out of space in our normal store, so\n\t\t\t     * we must allocate space for these backwards\n\t\t\t     * matches on the heap.\n\t\t\t     */\n\n\t\t\t    Tcl_Size *newArray = (Tcl_Size *)\n\t\t\t\t    Tcl_Alloc(4 * (size_t)matchNum * sizeof(Tcl_Size));\n\t\t\t    memcpy(newArray, storeMatch, (size_t)matchNum*sizeof(Tcl_Size));\n\t\t\t    memcpy(newArray + 2*matchNum, storeLength,\n\t\t\t\t    (size_t)matchNum * sizeof(Tcl_Size));\n\t\t\t    if (storeMatch != smArray) {\n\t\t\t\tTcl_Free(storeMatch);\n\t\t\t    }\n\t\t\t    matchNum *= 2;\n\t\t\t    storeMatch = newArray;\n\t\t\t    storeLength = newArray + matchNum;\n\t\t\t}\n\t\t\tstoreMatch[matches] = matchOffset;\n\t\t\tstoreLength[matches] = matchLength;\n\t\t\tmatches++;\n\t\t    } else {\n\t\t\t/*\n\t\t\t * Now actually record the match, but only if we are\n\t\t\t * doing an '-all' search.\n\t\t\t */\n\n\t\t\tif (searchSpecPtr->all &&\n\t\t\t\t!searchSpecPtr->foundMatchProc(lineNum,\n\t\t\t\tsearchSpecPtr, lineInfo, theLine, matchOffset,\n\t\t\t\tmatchLength)) {\n\t\t\t    /*\n\t\t\t     * We reached the end of the search.\n\t\t\t     */\n\n\t\t\t    goto searchDone;\n\t\t\t}\n\t\t    }\n\n\t\t    /*\n\t\t     * For forward matches, unless we allow overlaps, we move\n\t\t     * this on by the length of the current match so that we\n\t\t     * explicitly disallow overlapping matches.\n\t\t     */\n\n\t\t    if (matchLength > 0 && !searchSpecPtr->overlap\n\t\t\t    && !searchSpecPtr->backwards) {\n\t\t\tfirstOffset += matchLength;\n\t\t\tif (firstOffset >= lastOffset) {\n\t\t\t    /*\n\t\t\t     * Now, we have to be careful not to find\n\t\t\t     * overlapping matches either on the same or\n\t\t\t     * following lines. Assume that if we did find\n\t\t\t     * something, it goes until the last extra line we\n\t\t\t     * added.\n\t\t\t     *\n\t\t\t     * We can break out of the loop, since we know no\n\t\t\t     * more will be found.\n\t\t\t     */\n\n\t\t\t    alreadySearchOffset = firstOffset - lastFullLine;\n\t\t\t    break;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * We'll add this on again just below.\n\t\t\t */\n\n\t\t\tfirstOffset --;\n\t\t    }\n\t\t}\n\n\t\t/*\n\t\t * Move the starting point on, in case we are doing repeated\n\t\t * or backwards searches (for the latter, we actually do\n\t\t * repeated forward searches).\n\t\t */\n\n\t\tfirstOffset++;\n\t    } while (searchSpecPtr->backwards || searchSpecPtr->all);\n\n\t    if (matches > 0) {\n\t\t/*\n\t\t * Now we have all the matches in our array, but not stored\n\t\t * with 'foundMatchProc' yet.\n\t\t */\n\n\t\tmatches--;\n\t\tmatchOffset = storeMatch[matches];\n\t\tmatchLength = storeLength[matches];\n\t\twhile (--matches >= 0) {\n\t\t    if (lineNum == searchSpecPtr->stopLine) {\n\t\t\t/*\n\t\t\t * It appears as if a condition like:\n\t\t\t *\n\t\t\t * if (storeMatch[matches]<searchSpecPtr->stopOffset)\n\t\t\t *\tbreak;\n\t\t\t *\n\t\t\t * might be needed here, but no test case has been\n\t\t\t * found which would exercise such a problem.\n\t\t\t */\n\t\t    }\n\t\t    if (storeMatch[matches] + storeLength[matches]\n\t\t\t    >= matchOffset + matchLength) {\n\t\t\t/*\n\t\t\t * The new match totally encloses the previous one, so\n\t\t\t * we overwrite the previous one.\n\t\t\t */\n\n\t\t\tmatchOffset = storeMatch[matches];\n\t\t\tmatchLength = storeLength[matches];\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (!searchSpecPtr->overlap) {\n\t\t\tif (storeMatch[matches] + storeLength[matches]\n\t\t\t\t> matchOffset) {\n\t\t\t    continue;\n\t\t\t}\n\t\t    }\n\t\t    searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,\n\t\t\t    lineInfo, theLine, matchOffset, matchLength);\n\t\t    if (!searchSpecPtr->all) {\n\t\t\tgoto searchDone;\n\t\t    }\n\t\t    matchOffset = storeMatch[matches];\n\t\t    matchLength = storeLength[matches];\n\t\t}\n\t\tif (searchSpecPtr->all && matches > 0) {\n\t\t    /*\n\t\t     * We only need to do this for the '-all' case, because\n\t\t     * just below we will call the foundMatchProc for the\n\t\t     * non-all case.\n\t\t     */\n\n\t\t    searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr,\n\t\t\t    lineInfo, theLine, matchOffset, matchLength);\n\t\t} else {\n\t\t    lastBackwardsLineMatch = lineNum;\n\t\t    lastBackwardsMatchOffset = matchOffset;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * If the 'all' flag is set, we will already have stored all matches,\n\t * so we just proceed to the next line.\n\t *\n\t * If not, and there is a match we need to store that information and\n\t * we are done.\n\t */\n\n\tif ((lastBackwardsLineMatch == -1) && (matchOffset != TCL_INDEX_NONE)\n\t\t&& !searchSpecPtr->all) {\n\t    searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr, lineInfo,\n\t\t    theLine, matchOffset, matchLength);\n\t    goto searchDone;\n\t}\n\n\t/*\n\t * Go to the next (or previous) line;\n\t */\n\n    nextLine:\n\tlinesSearched += extraLinesSearched;\n\n\twhile (linesSearched-- > 0) {\n\t    /*\n\t     * If we have just completed the 'stopLine', we are done.\n\t     */\n\n\t    if (lineNum == searchSpecPtr->stopLine) {\n\t\tgoto searchDone;\n\t    }\n\n\t    if (searchSpecPtr->backwards) {\n\t\tlineNum--;\n\n\t\tif (lastBackwardsLineMatch != -1\n\t\t\t&& ((lineNum < 0)\n\t\t\t|| (lineNum + 2 < lastBackwardsLineMatch))) {\n\t\t    searchSpecPtr->foundMatchProc(lastBackwardsLineMatch,\n\t\t\t    searchSpecPtr, NULL, NULL,\n\t\t\t    lastBackwardsMatchOffset, matchLength);\n\t\t    lastBackwardsLineMatch = -1;\n\t\t    if (!searchSpecPtr->all) {\n\t\t\tgoto searchDone;\n\t\t    }\n\t\t}\n\n\t\tif (lineNum < 0) {\n\t\t    lineNum = searchSpecPtr->numLines-1;\n\t\t}\n\t\tif (!searchSpecPtr->exact) {\n\t\t    /*\n\t\t     * The 'exact' search loops above are designed to give us\n\t\t     * an accurate picture of the number of lines which we can\n\t\t     * skip here. For 'regexp' searches, on the other hand,\n\t\t     * which can match potentially variable lengths, we cannot\n\t\t     * skip multiple lines when searching backwards. Therefore\n\t\t     * we only allow one line to be skipped here.\n\t\t     */\n\n\t\t    break;\n\t\t}\n\t    } else {\n\t\tlineNum++;\n\t\tif (lineNum >= searchSpecPtr->numLines) {\n\t\t    lineNum = 0;\n\t\t}\n\t    }\n\t    if (lineNum == searchSpecPtr->startLine && linesSearched > 0) {\n\t\t/*\n\t\t * We've just searched all the way round and have gone right\n\t\t * through the start line without finding anything in the last\n\t\t * attempt.\n\t\t */\n\n\t\tbreak;\n\t    }\n\t}\n\n\tTcl_SetObjLength(theLine, 0);\n    }\n  searchDone:\n\n    if (lastBackwardsLineMatch != -1) {\n\tsearchSpecPtr->foundMatchProc(lastBackwardsLineMatch, searchSpecPtr,\n\t\tNULL, NULL, lastBackwardsMatchOffset, matchLength);\n    }\n\n    /*\n     * Free up the cached line and pattern.\n     */\n\n    Tcl_DecrRefCount(theLine);\n    Tcl_DecrRefCount(patObj);\n\n    /*\n     * Free up any extra space we allocated.\n     */\n\n    if (storeMatch != smArray) {\n\tTcl_Free(storeMatch);\n    }\n\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetLineStartEnd -\n *\n *\tConverts an internal TkTextLine ptr into a Tcl string obj containing\n *\tthe line number. (Handler for the 'line' configuration option type.)\n *\n * Results:\n *\tTcl_Obj containing the string representation of the line value.\n *\n * Side effects:\n *\tCreates a new Tcl_Obj.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetLineStartEnd(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *recordPtr,\t\t/* Pointer to widget record. */\n    Tcl_Size internalOffset)\t\t/* Offset within *recordPtr containing the\n\t\t\t\t * line value. */\n{\n    TkTextLine *linePtr = *(TkTextLine **)(recordPtr + internalOffset);\n\n    if (linePtr == NULL) {\n\treturn Tcl_NewObj();\n    }\n    return Tcl_NewWideIntObj(1 + TkBTreeLinesTo(NULL, linePtr));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetLineStartEnd --\n *\n *\tConverts a Tcl_Obj representing a widget's (start or end) line into a\n *\tTkTextLine* value. (Handler for the 'line' configuration option type.)\n *\n * Results:\n *\tStandard Tcl result.\n *\n * Side effects:\n *\tMay store the TkTextLine* value into the internal representation\n *\tpointer. May change the pointer to the Tcl_Obj to NULL to indicate\n *\tthat the specified string was empty and that is acceptable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetLineStartEnd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interp; may be used for errors. */\n    TCL_UNUSED(Tk_Window),\t/* Window for which option is being set. */\n    Tcl_Obj **value,\t\t/* Pointer to the pointer to the value object.\n\t\t\t\t * We use a pointer to the pointer because we\n\t\t\t\t * may need to return a value (NULL). */\n    char *recordPtr,\t\t/* Pointer to storage for the widget record. */\n    Tcl_Size internalOffset,\t\t/* Offset within *recordPtr at which the\n\t\t\t\t * internal value is to be stored. */\n    char *oldInternalPtr,\t/* Pointer to storage for the old value. */\n    int flags)\t\t\t/* Flags for the option, set Tk_SetOptions. */\n{\n    TkTextLine *linePtr = NULL;\n    char *internalPtr;\n    TkText *textPtr = (TkText *) recordPtr;\n\n    if (internalOffset != TCL_INDEX_NONE) {\n\tinternalPtr = (char *)recordPtr + internalOffset;\n    } else {\n\tinternalPtr = NULL;\n    }\n\n    if ((flags & TK_OPTION_NULL_OK) && TkObjIsEmpty(*value)) {\n\t*value = NULL;\n    } else {\n\tint line;\n\n\tif (Tcl_GetIntFromObj(interp, *value, &line) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tlinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, NULL, line-1);\n    }\n\n    if (internalPtr != NULL) {\n\t*((TkTextLine **) oldInternalPtr) = *((TkTextLine **) internalPtr);\n\t*((TkTextLine **) internalPtr) = linePtr;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RestoreLineStartEnd --\n *\n *\tRestore a line option value from a saved value. (Handler for the\n *\t'line' configuration option type.)\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the old value.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRestoreLineStartEnd(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(Tk_Window),\n    char *internalPtr,\t\t/* Pointer to storage for value. */\n    char *oldInternalPtr)\t/* Pointer to old value. */\n{\n    *(TkTextLine **)internalPtr = *(TkTextLine **)oldInternalPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTesttextCmd --\n *\n *\tThis function implements the \"testtext\" command. It provides a set of\n *\tfunctions for testing text widgets and the associated functions in\n *\ttkText*.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tDepends on option; see below.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpTesttextCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    TkText *textPtr;\n    Tcl_Size len;\n    Tcl_WideInt lineIndex, byteIndex;\n    Tcl_WideInt byteOffset;\n    TkTextIndex index;\n    char buf[TK_POS_CHARS];\n    Tcl_CmdInfo info;\n\n    if (objc < 3) {\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) == 0) {\n\treturn TCL_ERROR;\n    }\n    textPtr = (TkText *)info.objClientData2;\n    Tcl_GetStringFromObj(objv[2], &len);\n    if (strncmp(Tcl_GetString(objv[2]), \"byteindex\", (size_t)len) == 0) {\n\tif (objc != 5) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetWideIntFromObj(interp, objv[3], &lineIndex)) {\n\t    return TCL_ERROR;\n\t}\n\tlineIndex--;\n\tif (Tcl_GetWideIntFromObj(interp, objv[4], &byteIndex)) {\n\t    return TCL_ERROR;\n\t}\n\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineIndex,\n\t\tbyteIndex, &index);\n    } else if (strncmp(Tcl_GetString(objv[2]), \"forwbytes\", (size_t)len) == 0) {\n\tif (objc != 5) {\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetWideIntFromObj(interp, objv[4], &byteOffset)) {\n\t    return TCL_ERROR;\n\t}\n\tTkTextIndexForwBytes(textPtr, &index, byteOffset, &index);\n    } else if (strncmp(Tcl_GetString(objv[2]), \"backbytes\", (size_t)len) == 0) {\n\tif (objc != 5) {\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetIndex(interp, textPtr, Tcl_GetString(objv[3]), &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetWideIntFromObj(interp, objv[4], &byteOffset)) {\n\t    return TCL_ERROR;\n\t}\n\tTkTextIndexBackBytes(textPtr, &index, byteOffset, &index);\n    } else {\n\treturn TCL_ERROR;\n    }\n\n    TkTextSetMark(textPtr, \"insert\", &index);\n    TkTextPrintIndex(textPtr, &index, buf);\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"%s %\" TCL_Z_MODIFIER \"d\", buf, index.byteIndex));\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkText.h",
    "content": "/*\n * tkText.h --\n *\n *\tDeclarations shared among the files that implement text widgets.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKTEXT\n#define _TKTEXT\n\n#ifndef _TK\n#include \"tk.h\"\n#endif\n\n#ifndef _TKUNDO\n#include \"tkUndo.h\"\n#endif\n\n/*\n * The data structure below defines a single logical line of text (from\n * newline to newline, not necessarily what appears on one display line of the\n * screen).\n */\n\ntypedef struct TkTextLine {\n    struct Node *parentPtr;\t/* Pointer to parent node containing line. */\n    struct TkTextLine *nextPtr;\t/* Next in linked list of lines with same\n\t\t\t\t * parent node in B-tree. NULL means end of\n\t\t\t\t * list. */\n    struct TkTextSegment *segPtr;\n\t\t\t\t/* First in ordered list of segments that make\n\t\t\t\t * up the line. */\n    int *pixels;\t\t/* Array containing two integers for each\n\t\t\t\t * referring text widget. The first of these\n\t\t\t\t * is the number of vertical pixels taken up\n\t\t\t\t * by this line, whether currently displayed\n\t\t\t\t * or not. This number is only updated\n\t\t\t\t * asychronously. The second of these is the\n\t\t\t\t * last epoch at which the pixel height was\n\t\t\t\t * recalculated. */\n} TkTextLine;\n\n/*\n * -----------------------------------------------------------------------\n * Segments: each line is divided into one or more segments, where each\n * segment is one of several things, such as a group of characters, a tag\n * toggle, a mark, or an embedded widget. Each segment starts with a standard\n * header followed by a body that varies from type to type.\n * -----------------------------------------------------------------------\n */\n\n/*\n * The data structure below defines the body of a segment that represents a\n * tag toggle. There is one of these structures at both the beginning and end\n * of each tagged range.\n */\n\ntypedef struct TkTextToggle {\n    struct TkTextTag *tagPtr;\t/* Tag that starts or ends here. */\n    bool inNodeCounts;\t\t/* True means this toggle has been accounted for\n\t\t\t\t * in node toggle counts; false means it hasn't,\n\t\t\t\t * yet. */\n} TkTextToggle;\n\n/*\n * The data structure below defines line segments that represent marks. There\n * is one of these for each mark in the text.\n */\n\ntypedef struct TkTextMark {\n    struct TkText *textPtr;\t/* Overall information about text widget. */\n    TkTextLine *linePtr;\t/* Line structure that contains the\n\t\t\t\t * segment. */\n    Tcl_HashEntry *hPtr;\t/* Pointer to hash table entry for mark (in\n\t\t\t\t * sharedTextPtr->markTable). */\n} TkTextMark;\n\n/*\n * A structure of the following type holds information for each window\n * embedded in a text widget. This information is only used by the file\n * tkTextWind.c\n */\n\ntypedef struct TkTextEmbWindowClient {\n    struct TkText *textPtr;\t/* Information about the overall text\n\t\t\t\t * widget. */\n    Tk_Window tkwin;\t\t/* Window for this segment. NULL means that\n\t\t\t\t * the window hasn't been created yet. */\n    int chunkCount;\t\t/* Number of display chunks that refer to this\n\t\t\t\t * window. */\n    bool displayed;\t\t/* True means that the window has been\n\t\t\t\t * displayed on the screen recently. */\n    struct TkTextSegment *parent;\n    struct TkTextEmbWindowClient *next;\n} TkTextEmbWindowClient;\n\ntypedef enum {\n    TK_ALIGN_BASELINE, TK_ALIGN_BOTTOM, TK_ALIGN_CENTER, TK_ALIGN_TOP\n} TkAlignMode;\n\ntypedef struct TkTextEmbWindow {\n    struct TkSharedText *sharedTextPtr;\n\t\t\t\t/* Information about the shared portion of the\n\t\t\t\t * text widget. */\n    Tk_Window tkwin;\t\t/* Window for this segment. This is just a\n\t\t\t\t * temporary value, copied from 'clients', to\n\t\t\t\t * make option table updating easier. NULL\n\t\t\t\t * means that the window hasn't been created\n\t\t\t\t * yet. */\n    TkTextLine *linePtr;\t/* Line structure that contains this\n\t\t\t\t * window. */\n    Tcl_Obj *createObj;\t/* Script to create window on-demand. NULL\n\t\t\t\t * means no such script. */\n    Tcl_Obj *padXObj, *padYObj;\t\t/* Padding to leave around each side of window. */\n    TkAlignMode align;\t\t/* How to align window in vertical space. See\n\t\t\t\t * definitions in tkTextWind.c. */\n    bool stretch;\t\t/* Should window stretch to fill vertical\n\t\t\t\t * space of line (except for pady)? false or true. */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n    TkTextEmbWindowClient *clients;\n\t\t\t\t/* Linked list of peer-widget specific\n\t\t\t\t * information for this embedded window. */\n} TkTextEmbWindow;\n\n/*\n * A structure of the following type holds information for each image embedded\n * in a text widget. This information is only used by the file tkTextImage.c\n */\n\ntypedef struct TkTextEmbImage {\n    struct TkSharedText *sharedTextPtr;\n\t\t\t\t/* Information about the shared portion of the\n\t\t\t\t * text widget. This is used when the image\n\t\t\t\t * changes or is deleted. */\n    TkTextLine *linePtr;\t/* Line structure that contains this image. */\n    Tcl_Obj *imageObj;\t\t/* Name of the image for this segment. */\n    Tcl_Obj *imageNameObj;\t/* Name used by text widget to identify this\n\t\t\t\t * image. May be unique-ified. */\n    char *name;\t\t\t/* Name used in the hash table. Used by\n\t\t\t\t * \"image names\" to identify this instance of\n\t\t\t\t * the image. */\n    Tk_Image image;\t\t/* Image for this segment. NULL means that the\n\t\t\t\t * image hasn't been created yet. */\n    Tcl_Obj *padXObj, *padYObj;\t/* Padding to leave around each side of image,\n\t\t\t\t * in pixels. */\n    TkAlignMode align;\t\t/* How to align image in vertical space. See\n\t\t\t\t * definitions in tkTextImage.c. */\n    int chunkCount;\t\t/* Number of display chunks that refer to this\n\t\t\t\t * image. */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n} TkTextEmbImage;\n\n/*\n * The data structure below defines line segments.\n */\n\ntypedef struct TkTextSegment {\n    const struct Tk_SegType *typePtr;\n\t\t\t\t/* Pointer to record describing segment's\n\t\t\t\t * type. */\n    struct TkTextSegment *nextPtr;\n\t\t\t\t/* Next in list of segments for this line, or\n\t\t\t\t * NULL for end of list. */\n    Tcl_Size size;\t\t\t/* Size of this segment (# of bytes of index\n\t\t\t\t * space it occupies). */\n    union {\n\t/* The TKFLEXARRAY macro - unfortunately - doesn't work inside a union. */\n#if defined(__GNUC__) && (__GNUC__ > 2)\n\tchar chars[0];\t\t/* Characters that make up character info. */\n#else\t\t\t\t/* Actual length varies to hold as many */\n\tchar chars[1];\t\t/* characters as needed. See [dacd18294b] */\n#endif\n\tTkTextToggle toggle;\t/* Information about tag toggle. */\n\tTkTextMark mark;\t/* Information about mark. */\n\tTkTextEmbWindow ew;\t/* Information about embedded window. */\n\tTkTextEmbImage ei;\t/* Information about embedded image. */\n    } body;\n} TkTextSegment;\n\n/*\n * Data structures of the type defined below are used during the execution of\n * Tcl commands to keep track of various interesting places in a text. An\n * index is only valid up until the next modification to the character\n * structure of the b-tree so they can't be retained across Tcl commands.\n * However, mods to marks or tags don't invalidate indices.\n */\n\ntypedef struct TkTextIndex {\n    TkTextBTree tree;\t\t/* Tree containing desired position. */\n    TkTextLine *linePtr;\t/* Pointer to line containing position of\n\t\t\t\t * interest. */\n    Tcl_Size byteIndex;\t\t/* Index within line of desired character (0\n\t\t\t\t * means first one). */\n    struct TkText *textPtr;\t/* May be NULL, but otherwise the text widget\n\t\t\t\t * with which this index is associated. If not\n\t\t\t\t * NULL, then we have a refCount on the\n\t\t\t\t * widget. */\n} TkTextIndex;\n\n/*\n * Types for procedure pointers stored in TkTextDispChunk structures:\n */\n\ntypedef struct TkTextDispChunk TkTextDispChunk;\n\ntypedef void\t\tTk_ChunkDisplayProc(struct TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, int x, int y,\n\t\t\t    int height, int baseline, Display *display,\n\t\t\t    Drawable dst, int screenY);\ntypedef void\t\tTk_ChunkUndisplayProc(struct TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr);\ntypedef Tcl_Size\tTk_ChunkMeasureProc(TkTextDispChunk *chunkPtr, int x);\ntypedef void\t\tTk_ChunkBboxProc(struct TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, Tcl_Size index, int y,\n\t\t\t    int lineHeight, int baseline, int *xPtr,\n\t\t\t    int *yPtr, int *widthPtr, int *heightPtr);\n\n/*\n * The structure below represents a chunk of stuff that is displayed together\n * on the screen. This structure is allocated and freed by generic display\n * code but most of its fields are filled in by segment-type-specific code.\n */\n\nstruct TkTextDispChunk {\n    /*\n     * The fields below are set by the type-independent code before calling\n     * the segment-type-specific layoutProc. They should not be modified by\n     * segment-type-specific code.\n     */\n\n    int x;\t\t\t/* X position of chunk, in pixels. This\n\t\t\t\t * position is measured from the left edge of\n\t\t\t\t * the logical line, not from the left edge of\n\t\t\t\t * the window (i.e. it doesn't change under\n\t\t\t\t * horizontal scrolling). */\n    struct TkTextDispChunk *nextPtr;\n\t\t\t\t/* Next chunk in the display line or NULL for\n\t\t\t\t * the end of the list. */\n    struct TextStyle *stylePtr;\t/* Display information, known only to\n\t\t\t\t * tkTextDisp.c. */\n\n    /*\n     * The fields below are set by the layoutProc that creates the chunk.\n     */\n\n    Tk_ChunkDisplayProc *displayProc;\n\t\t\t\t/* Procedure to invoke to draw this chunk on\n\t\t\t\t * the display or an off-screen pixmap. */\n    Tk_ChunkUndisplayProc *undisplayProc;\n\t\t\t\t/* Procedure to invoke when segment ceases to\n\t\t\t\t * be displayed on screen anymore. */\n    Tk_ChunkMeasureProc *measureProc;\n\t\t\t\t/* Procedure to find character under a given\n\t\t\t\t * x-location. */\n    Tk_ChunkBboxProc *bboxProc;\t/* Procedure to find bounding box of character\n\t\t\t\t * in chunk. */\n    Tcl_Size numBytes;\t\t/* Number of bytes that will be displayed in\n\t\t\t\t * the chunk. */\n    int minAscent;\t\t/* Minimum space above the baseline needed by\n\t\t\t\t * this chunk. */\n    int minDescent;\t\t/* Minimum space below the baseline needed by\n\t\t\t\t * this chunk. */\n    int minHeight;\t\t/* Minimum total line height needed by this\n\t\t\t\t * chunk. */\n    int width;\t\t\t/* Width of this chunk, in pixels. Initially\n\t\t\t\t * set by chunk-specific code, but may be\n\t\t\t\t * increased to include tab or extra space at\n\t\t\t\t * end of line. */\n    Tcl_Size breakIndex;\t\t/* Index within chunk of last acceptable\n\t\t\t\t * position for a line (break just before this\n\t\t\t\t * byte index). <= 0 means don't break during\n\t\t\t\t * or immediately after this chunk. */\n    void *clientData;\t/* Additional information for use of\n\t\t\t\t * displayProc and undisplayProc. */\n};\n\n/*\n * One data structure of the following type is used for each tag in a text\n * widget. These structures are kept in sharedTextPtr->tagTable and referred\n * to in other structures.\n */\n\ntypedef enum {\n    TEXT_WRAPMODE_NULL = -1,\n    TEXT_WRAPMODE_CHAR,\n    TEXT_WRAPMODE_NONE,\n    TEXT_WRAPMODE_WORD\n} TkWrapMode;\n\n/*\n * The following are the supported styles of tabbing, used for the -tabstyle\n * option of the text widget. The first element is only used for tag options.\n */\n\ntypedef enum {\n    TK_TEXT_TABSTYLE_NULL = -1,\n    TK_TEXT_TABSTYLE_TABULAR,\n    TK_TEXT_TABSTYLE_WORDPROCESSOR\n} TkTextTabStyle;\n\nMODULE_SCOPE const char *const tkTextTabStyleStrings[];\n\n\nMODULE_SCOPE const char *const tkTextWrapStrings[];\n\ntypedef struct TkTextTag {\n    const char *name;\t\t/* Name of this tag. This field is actually a\n\t\t\t\t * pointer to the key from the entry in\n\t\t\t\t * sharedTextPtr->tagTable, so it needn't be\n\t\t\t\t * freed explicitly. For 'sel' tags this is\n\t\t\t\t * just a static string, so again need not be\n\t\t\t\t * freed. */\n    const struct TkText *textPtr;\n\t\t\t\t/* If non-NULL, then this tag only applies to\n\t\t\t\t * the given text widget (when there are peer\n\t\t\t\t * widgets). */\n    Tcl_Size priority;\t/* Priority of this tag within widget. 0 means\n\t\t\t\t * lowest priority. Exactly one tag has each\n\t\t\t\t * integer value between 0 and numTags-1. */\n    struct Node *tagRootPtr;\t/* Pointer into the B-Tree at the lowest node\n\t\t\t\t * that completely dominates the ranges of\n\t\t\t\t * text occupied by the tag. At this node\n\t\t\t\t * there is no information about the tag. One\n\t\t\t\t * or more children of the node do contain\n\t\t\t\t * information about the tag. */\n    Tcl_Size toggleCount;\t/* Total number of tag toggles. */\n\n    /*\n     * Information for displaying text with this tag. The information belows\n     * acts as an override on information specified by lower-priority tags.\n     * If no value is specified, then the next-lower-priority tag on the text\n     * determins the value. The text widget itself provides defaults if no tag\n     * specifies an override.\n     */\n\n    Tk_3DBorder border;\t\t/* Used for drawing background. NULL means no\n\t\t\t\t * value specified here. */\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border for background. */\n    int relief;\t\t\t/* 3-D relief for background. */\n    Pixmap bgStipple;\t\t/* Stipple bitmap for background. None means\n\t\t\t\t * no value specified here. */\n    XColor *fgColor;\t\t/* Foreground color for text. NULL means no\n\t\t\t\t * value specified here. */\n    Tk_Font tkfont;\t\t/* Font for displaying text. NULL means no\n\t\t\t\t * value specified here. */\n    Pixmap fgStipple;\t\t/* Stipple bitmap for text and other\n\t\t\t\t * foreground stuff. None means no value\n\t\t\t\t * specified here.*/\n    Tk_Justify justify;\t\t/* How to justify text: TK_JUSTIFY_CENTER,\n\t\t\t\t * TK_JUSTIFY_LEFT, or TK_JUSTIFY_RIGHT. */\n    Tcl_Obj *lMargin1Obj;\t/* Left margin for first display line of each\n\t\t\t\t * text line, in pixels. NULL means option not specified. */\n    int lMargin1;\t\t/* No longer used, but kept for binary compatibility. */\n    Tcl_Obj *lMargin2Obj;\t/* Left margin for second and later display lines\n\t\t\t\t * of each text line, in pixels NULL means option not specified. */\n    int lMargin2;\t\t/* No longer used, but kept for binary compatibility. */\n    Tk_3DBorder lMarginColor;\t/* Used for drawing background in left margins.\n\t\t\t\t * This is used for both lmargin1 and lmargin2.\n\t\t\t\t * NULL means no value specified here. */\n    Tcl_Obj *offsetObj;\t\t/* Vertical offset of text's baseline from\n\t\t\t\t * baseline of line. Used for superscripts and\n\t\t\t\t * subscripts. NULL means option not specified. */\n    int offset;\t\t\t/* No longer used, but kept for binary compatibility. */\n    int overstrike;\t\t/* > 0 means draw horizontal line through\n\t\t\t\t * middle of text. -1 means not specified. */\n    XColor *overstrikeColor;    /* Color for the overstrike. NULL means same\n\t\t\t\t * color as foreground. */\n    Tcl_Obj *rMarginObj;\t/* Right margin for text, in pixels. NULL\n\t\t\t\t * means option not specified. */\n    int rMargin;\t\t/* No longer used, but kept for binary compatibility. */\n    Tk_3DBorder rMarginColor;\t/* Used for drawing background in right margin.\n\t\t\t\t * NULL means no value specified here. */\n    Tk_3DBorder selBorder;\t/* Used for drawing background for selected text.\n\t\t\t\t * NULL means no value specified here. */\n    XColor *selFgColor;\t\t/* Foreground color for selected text. NULL means\n\t\t\t\t * no value specified here. */\n    Tcl_Obj *spacing1Obj;\t/* -spacing1 option object. NULL\n\t\t\t\t * means option not specified. */\n    Tcl_Obj *spacing2Obj;\t/* -spacing2 option object. NULL\n\t\t\t\t * means option not specified. */\n    Tcl_Obj *spacing3Obj;\t/* -spacing3 option object. NULL\n\t\t\t\t * means option not specified. */\n    Tcl_Obj *tabStringPtr;\t/* -tabs option. NULL means option not\n\t\t\t\t * specified. */\n    struct TkTextTabArray *tabArrayPtr;\n\t\t\t\t/* Info about tabs for tag (malloc-ed) or\n\t\t\t\t * NULL. Corresponds to tabStringPtr. */\n    TkTextTabStyle tabStyle;\t/* One of TK_TEXT_TABSTYLE_TABULAR or TK_TEXT_TABSTYLE_WORDPROCESSOR\n\t\t\t\t * or TK_TEXT_TABSTYLE_NULL (if not specified). */\n    int underline;\t\t/* > 0 means draw underline underneath\n\t\t\t\t * text. -1 means not specified. */\n    XColor *underlineColor;     /* Color for the underline. NULL means same\n\t\t\t\t * color as foreground. */\n    TkWrapMode wrapMode;\t/* How to handle wrap-around for this tag.\n\t\t\t\t * Must be TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_WORD,\n\t\t\t\t * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_NULL to\n\t\t\t\t * use wrapmode for whole widget. */\n    int elide;\t\t\t/* Non-zero means that data under this tag\n\t\t\t\t * should not be displayed. -1 means not specified. */\n    bool affectsDisplay;\t\t/* True means that this tag affects the\n\t\t\t\t * way information is displayed on the screen\n\t\t\t\t * (so need to redisplay if tag changes). */\n    bool affectsDisplayGeometry;\t/* True means that this tag affects the\n\t\t\t\t * size with which information is displayed on\n\t\t\t\t * the screen (so need to recalculate line\n\t\t\t\t * dimensions if tag changes). */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n} TkTextTag;\n\n#define TK_TAG_AFFECTS_DISPLAY\t0x1\n#define TK_TAG_UNDERLINE\t0x2\n#define TK_TAG_JUSTIFY\t\t0x4\n#define TK_TAG_OFFSET\t\t0x10\n\n/*\n * The data structure below is used for searching a B-tree for transitions on\n * a single tag (or for all tag transitions). No code outside of tkTextBTree.c\n * should ever modify any of the fields in these structures, but it's OK to\n * use them for read-only information.\n */\n\ntypedef struct TkTextSearch {\n    TkTextIndex curIndex;\t/* Position of last tag transition returned by\n\t\t\t\t * TkBTreeNextTag, or index of start of\n\t\t\t\t * segment containing starting position for\n\t\t\t\t * search if TkBTreeNextTag hasn't been called\n\t\t\t\t * yet, or same as stopIndex if search is\n\t\t\t\t * over. */\n    TkTextSegment *segPtr;\t/* Actual tag segment returned by last call to\n\t\t\t\t * TkBTreeNextTag, or NULL if TkBTreeNextTag\n\t\t\t\t * hasn't returned anything yet. */\n    TkTextSegment *nextPtr;\t/* Where to resume search in next call to\n\t\t\t\t * TkBTreeNextTag. */\n    TkTextSegment *lastPtr;\t/* Stop search before just before considering\n\t\t\t\t * this segment. */\n    TkTextTag *tagPtr;\t\t/* Tag to search for (or tag found, if allTags\n\t\t\t\t * is non-zero). */\n    Tcl_Size linesLeft;\t\t/* Lines left to search (including curIndex\n\t\t\t\t * and stopIndex). When this becomes <= 0 the\n\t\t\t\t * search is over. */\n    bool allTags;\t\t/* True means ignore tag check: search for\n\t\t\t\t * transitions on all tags. */\n} TkTextSearch;\n\n/*\n * The following data structure describes a single tab stop. It must be kept\n * in sync with the 'tabOptionStrings' array in the function 'TkTextGetTabs'\n */\n\ntypedef enum {LEFT, RIGHT, CENTER, NUMERIC} TkTextTabAlign;\n\ntypedef struct TkTextTab {\n    int location;\t\t/* Offset in pixels of this tab stop from the\n\t\t\t\t * left margin (lmargin2) of the text. */\n    TkTextTabAlign alignment;\t/* Where the tab stop appears relative to the\n\t\t\t\t * text. */\n} TkTextTab;\n\ntypedef struct TkTextTabArray {\n    int numTabs;\t\t/* Number of tab stops. */\n    double lastTab;\t\t/* The accurate fractional pixel position of\n\t\t\t\t * the last tab. */\n    double tabIncrement;\t/* The accurate fractional pixel increment\n\t\t\t\t * between interpolated tabs we have to create\n\t\t\t\t * when we exceed numTabs. */\n    TkTextTab tabs[TKFLEXARRAY];/* Array of tabs. The actual size will be\n\t\t\t\t * numTabs. THIS FIELD MUST BE THE LAST IN THE\n\t\t\t\t * STRUCTURE. */\n} TkTextTabArray;\n\n/*\n * Enumeration defining the edit modes of the widget.\n */\n\ntypedef enum {\n    TK_TEXT_EDIT_INSERT,\t/* insert mode */\n    TK_TEXT_EDIT_DELETE,\t/* delete mode */\n    TK_TEXT_EDIT_REPLACE,\t/* replace mode */\n    TK_TEXT_EDIT_OTHER\t\t/* none of the above */\n} TkTextEditMode;\n\n/*\n * Enumeration defining the ways in which a text widget may be modified (for\n * undo/redo handling).\n */\n\ntypedef enum {\n    TK_TEXT_DIRTY_NORMAL,\t/* Normal behavior. */\n    TK_TEXT_DIRTY_UNDO,\t\t/* Reverting a compound action. */\n    TK_TEXT_DIRTY_REDO,\t\t/* Reapplying a compound action. */\n    TK_TEXT_DIRTY_FIXED\t\t/* Forced to be dirty; can't be undone/redone\n\t\t\t\t * by normal activity. */\n} TkTextDirtyMode;\n\n/*\n * The following enum is used to define a type for the -state option of the\n * Text widget.\n */\n\ntypedef enum {\n    TK_TEXT_STATE_DISABLED, TK_TEXT_STATE_NORMAL\n} TkTextState;\n\n/*\n * A data structure of the following type is shared between each text widget\n * that are peers.\n */\n\ntypedef struct TkSharedText {\n    size_t refCount;\t\t/* Reference count this shared object. */\n    TkTextBTree tree;\t\t/* B-tree representation of text and tags for\n\t\t\t\t * widget. */\n    Tcl_HashTable tagTable;\t/* Hash table that maps from tag names to\n\t\t\t\t * pointers to TkTextTag structures. The \"sel\"\n\t\t\t\t * tag does not feature in this table, since\n\t\t\t\t * there's one of those for each text peer. */\n    Tcl_Size numTags;\t\t/* Number of tags currently defined for\n\t\t\t\t * widget; needed to keep track of\n\t\t\t\t * priorities. */\n    Tcl_HashTable markTable;\t/* Hash table that maps from mark names to\n\t\t\t\t * pointers to mark segments. The special\n\t\t\t\t * \"insert\" and \"current\" marks are not stored\n\t\t\t\t * in this table, but directly accessed as\n\t\t\t\t * fields of textPtr. */\n    Tcl_HashTable windowTable;\t/* Hash table that maps from window names to\n\t\t\t\t * pointers to window segments. If a window\n\t\t\t\t * segment doesn't yet have an associated\n\t\t\t\t * window, there is no entry for it here. */\n    Tcl_HashTable imageTable;\t/* Hash table that maps from image names to\n\t\t\t\t * pointers to image segments. If an image\n\t\t\t\t * segment doesn't yet have an associated\n\t\t\t\t * image, there is no entry for it here. */\n    Tk_BindingTable bindingTable;\n\t\t\t\t/* Table of all bindings currently defined for\n\t\t\t\t * this widget. NULL means that no bindings\n\t\t\t\t * exist, so the table hasn't been created.\n\t\t\t\t * Each \"object\" used for this table is the\n\t\t\t\t * name of a tag. */\n    Tcl_Size stateEpoch;\t/* This is incremented each time the B-tree's\n\t\t\t\t * contents change structurally, or when the\n\t\t\t\t * start/end limits change, and means that any\n\t\t\t\t * cached TkTextIndex objects are no longer\n\t\t\t\t * valid. */\n    int imageCount;\t\t/* Used for creating unique image names. */\n\n    /*\n     * Information related to the undo/redo functionality.\n     */\n\n    TkUndoRedoStack *undoStack;\t/* The undo/redo stack. */\n    int maxUndo;\t\t/* The maximum depth of the undo stack\n\t\t\t\t * expressed as the maximum number of compound\n\t\t\t\t * statements. */\n    bool undo;\t\t\t/* True means the undo/redo behaviour is\n\t\t\t\t * enabled. */\n    bool autoSeparators;\t\t/* True means the separators will be\n\t\t\t\t * inserted automatically. */\n    int isDirty;\t\t/* Flag indicating the 'dirtyness' of the\n\t\t\t\t * text widget. If the flag is not zero,\n\t\t\t\t * unsaved modifications have been applied to\n\t\t\t\t * the text widget. */\n    TkTextDirtyMode dirtyMode;\t/* The nature of the dirtyness characterized\n\t\t\t\t * by the isDirty flag. */\n    TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode\n\t\t\t\t * was. */\n\n    /*\n     * Keep track of all the peers\n     */\n\n    struct TkText *peers;\n\n    Tcl_Size undoMarkId;             /* Counts undo marks temporarily used during\n\t\t\t\t   undo and redo operations. */\n} TkSharedText;\n\n/*\n * The following enum is used to define a type for the -insertunfocussed\n * option of the Text widget.\n */\n\ntypedef enum {\n    TK_TEXT_INSERT_NOFOCUS_HOLLOW,\n    TK_TEXT_INSERT_NOFOCUS_NONE,\n    TK_TEXT_INSERT_NOFOCUS_SOLID\n} TkTextInsertUnfocussed;\n\n/*\n * A data structure of the following type is kept for each text widget that\n * currently exists for this process:\n */\n\ntypedef struct TkText {\n    /*\n     * Information related to and accessed by widget peers and the\n     * TkSharedText handling routines.\n     */\n\n    TkSharedText *sharedTextPtr;/* Shared section of all peers. */\n    struct TkText *next;\t/* Next in list of linked peers. */\n    TkTextLine *start;\t\t/* First B-tree line to show, or NULL to start\n\t\t\t\t * at the beginning. */\n    TkTextLine *end;\t\t/* Last B-tree line to show, or NULL for up to\n\t\t\t\t * the end. */\n    int pixelReference;\t\t/* Counter into the current tree reference\n\t\t\t\t * index corresponding to this widget. */\n    bool abortSelections;\t/* Set to true whenever the text is modified in a\n\t\t\t\t * way that interferes with selection\n\t\t\t\t * retrieval: used to abort incremental\n\t\t\t\t * selection retrievals. */\n\n    /*\n     * Standard Tk widget information and text-widget specific items\n     */\n\n    Tk_Window tkwin;\t\t/* Window that embodies the text. NULL means\n\t\t\t\t * that the window has been destroyed but the\n\t\t\t\t * data structures haven't yet been cleaned\n\t\t\t\t * up.*/\n    Display *display;\t\t/* Display for widget. Needed, among other\n\t\t\t\t * things, to allow resources to be freed even\n\t\t\t\t * after tkwin has gone away. */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with widget. Used to\n\t\t\t\t * delete widget command. */\n    Tcl_Command widgetCmd;\t/* Token for text's widget command. */\n    TkTextState state;\t\t/* Either TK_TEXT_STATE_DISABLED or TK_TEXT_STATE_NORMAL. A\n\t\t\t\t * text widget is read-only when disabled. */\n\n    /*\n     * Default information for displaying (may be overridden by tags applied\n     * to ranges of characters).\n     */\n\n    Tk_3DBorder border;\t\t/* Structure used to draw 3-D border and\n\t\t\t\t * default background. */\n    Tcl_Obj *borderWidthObj;\t/* Width of 3-D border to draw around entire\n\t\t\t\t * widget. */\n    Tcl_Obj *padXObj, *padYObj;\t\t/* Padding between text and window border. */\n    int relief;\t\t\t/* 3-d effect for border around entire widget:\n\t\t\t\t * TK_RELIEF_RAISED etc. */\n    Tcl_Obj *highlightWidthObj;\t\t/* Width in pixels of highlight to draw around\n\t\t\t\t * widget when it has the focus. <= 0 means\n\t\t\t\t * don't draw a highlight. */\n    XColor *highlightBgColorPtr;\n\t\t\t\t/* Color for drawing traversal highlight area\n\t\t\t\t * when highlight is off. */\n    XColor *highlightColorPtr;\t/* Color for drawing traversal highlight. */\n    Tk_Cursor cursor;\t\t/* Current cursor for window, or NULL. */\n    XColor *fgColor;\t\t/* Default foreground color for text. */\n    Tk_Font tkfont;\t\t/* Default font for displaying text. */\n    int charWidth;\t\t/* Width of average character in default\n\t\t\t\t * font. */\n    int charHeight;\t\t/* Height of average character in default\n\t\t\t\t * font, including line spacing. */\n    Tcl_Obj *spacing1Obj;\t/* Default extra spacing above first display\n\t\t\t\t * line for each text line. */\n    Tcl_Obj *spacing2Obj;\t/* Default extra spacing between display lines\n\t\t\t\t * for the same text line. */\n    Tcl_Obj *spacing3Obj;\t/* Default extra spacing below last display\n\t\t\t\t * line for each text line. */\n    Tcl_Obj *tabOptionObj;\t/* Value of -tabs option string. */\n    TkTextTabArray *tabArrayPtr;\n\t\t\t\t/* Information about tab stops (malloc'ed).\n\t\t\t\t * NULL means perform default tabbing\n\t\t\t\t * behavior. */\n    TkTextTabStyle tabStyle;\t/* One of TK_TEXT_TABSTYLE_TABULAR or TK_TEXT_TABSTYLE_WORDPROCESSOR. */\n\n    /*\n     * Additional information used for displaying:\n     */\n\n    TkWrapMode wrapMode;\t/* How to handle wrap-around. Must be\n\t\t\t\t * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or\n\t\t\t\t * TEXT_WRAPMODE_WORD, or TEXT_WRAPMODE_NULL to\n\t\t\t\t * use wrapmode for whole widget. */\n    int width;\t\t/* Desired dimensions for window, measured in characters */\n    Tcl_Obj *heightObj;\n    int prevWidth, prevHeight;\t/* Last known dimensions of window; used to\n\t\t\t\t * detect changes in size. */\n    TkTextIndex topIndex;\t/* Identifies first character in top display\n\t\t\t\t * line of window. */\n    struct TextDInfo *dInfoPtr;\t/* Information maintained by tkTextDisp.c. */\n\n    /*\n     * Information related to selection.\n     */\n\n    TkTextTag *selTagPtr;\t/* Pointer to \"sel\" tag. Used to tell when a\n\t\t\t\t * new selection has been made. */\n    Tk_3DBorder selBorder;\t/* Border and background for selected\n\t\t\t\t * characters. This is a copy of information\n\t\t\t\t * in *selTagPtr, so it shouldn't be\n\t\t\t\t * explicitly freed. */\n    Tk_3DBorder inactiveSelBorder;\n\t\t\t\t/* Border and background for selected\n\t\t\t\t * characters when they don't have the\n\t\t\t\t * focus. */\n    Tcl_Obj *selBorderWidthObj;\t/* Width of border around selection. */\n    XColor *selFgColorPtr;\t/* Foreground color for selected text. This is\n\t\t\t\t * a copy of information in *selTagPtr, so it\n\t\t\t\t * shouldn't be explicitly freed. */\n    TkTextIndex selIndex;\t/* Used during multi-pass selection\n\t\t\t\t * retrievals. This index identifies the next\n\t\t\t\t * character to be returned from the\n\t\t\t\t * selection. */\n\n    /*\n     * Information related to insertion cursor:\n     */\n\n    TkTextSegment *insertMarkPtr;\n\t\t\t\t/* Points to segment for \"insert\" mark. */\n    Tk_3DBorder insertBorder;\t/* Used to draw vertical bar for insertion\n\t\t\t\t * cursor. */\n    Tcl_Obj *insertWidthObj;\t\t/* Total width of insert cursor. */\n    Tcl_Obj *insertBorderWidthObj;\t/* Width of 3-D border around insert cursor */\n    TkTextInsertUnfocussed insertUnfocussed;\n\t\t\t\t/* How to display the insert cursor when the\n\t\t\t\t * text widget does not have the focus. */\n    int insertOnTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"on\" state for each blink. */\n    int insertOffTime;\t\t/* Number of milliseconds cursor should spend\n\t\t\t\t * in \"off\" state for each blink. */\n    Tcl_TimerToken insertBlinkHandler;\n\t\t\t\t/* Timer handler used to blink cursor on and\n\t\t\t\t * off. */\n\n    /*\n     * Information used for event bindings associated with tags:\n     */\n\n    TkTextSegment *currentMarkPtr;\n\t\t\t\t/* Pointer to segment for \"current\" mark, or\n\t\t\t\t * NULL if none. */\n    XEvent pickEvent;\t\t/* The event from which the current character\n\t\t\t\t * was chosen. Must be saved so that we can\n\t\t\t\t * repick after modifications to the text. */\n    Tcl_Size numCurTags;\t\t/* Number of tags associated with character at\n\t\t\t\t * current mark. */\n    TkTextTag **curTagArrayPtr;\t/* Pointer to array of tags for current mark,\n\t\t\t\t * or NULL if none. */\n\n    /*\n     * Miscellaneous additional information:\n     */\n\n    Tcl_Obj *takeFocusObj;\t\t/* Value of -takeFocus option; not used in the\n\t\t\t\t * C code, but used by keyboard traversal\n\t\t\t\t * scripts. May be NULL. */\n    Tcl_Obj *xScrollCmdObj;\t\t/* Prefix of command to issue to update\n\t\t\t\t * horizontal scrollbar when view changes. May be NULL. */\n    Tcl_Obj *yScrollCmdObj;\t\t/* Prefix of command to issue to update\n\t\t\t\t * vertical scrollbar when view changes. May be NULL. */\n    int flags;\t\t\t/* Miscellaneous flags; see below for\n\t\t\t\t * definitions. */\n    Tk_OptionTable optionTable;\t/* Token representing the configuration\n\t\t\t\t * specifications. */\n    Tcl_Size refCount;\t\t/* Number of cached TkTextIndex objects\n\t\t\t\t * refering to us. */\n    bool insertCursorType;\t/* false = standard insertion cursor, true = block\n\t\t\t\t * cursor. */\n    bool setGrid;\t\t/* True means pass gridding information to\n\t\t\t\t * window manager. */\n    bool exportSelection;\t/* True means tie \"sel\" tag to X\n\t\t\t\t * selection. */\n\n    /*\n     * Copies of information from the shared section relating to the undo/redo\n     * functonality\n     */\n\n    bool undo;\t\t\t/* True means the undo/redo behaviour is\n\t\t\t\t * enabled. */\n    bool autoSeparators;\t\t/* True means the separators will be\n\t\t\t\t * inserted automatically. */\n    int maxUndo;\t\t/* The maximum depth of the undo stack\n\t\t\t\t * expressed as the maximum number of compound\n\t\t\t\t * statements. */\n    Tcl_Obj *afterSyncCmd;\t/* Command to be executed when lines are up to\n\t\t\t\t * date */\n} TkText;\n\n/*\n * Flag values for TkText records:\n *\n * GOT_SELECTION:\t\tNon-zero means we've already claimed the\n *\t\t\t\tselection.\n * INSERT_ON:\t\t\tNon-zero means insertion cursor should be\n *\t\t\t\tdisplayed on screen.\n * GOT_FOCUS:\t\t\tNon-zero means this window has the input\n *\t\t\t\tfocus.\n * BUTTON_DOWN:\t\t\t1 means that a mouse button is currently down;\n *\t\t\t\tthis is used to implement grabs for the\n *\t\t\t\tduration of button presses.\n * UPDATE_SCROLLBARS:\t\tNon-zero means scrollbar(s) should be updated\n *\t\t\t\tduring next redisplay operation.\n * NEED_REPICK\t\t\tThis appears unused and should probably be\n *\t\t\t\tignored.\n * OPTIONS_FREED\t\tThe widget's options have been freed.\n * DESTROYED\t\t\tThe widget is going away.\n */\n\n#define GOT_SELECTION\t\t1\n#define INSERT_ON\t\t2\n#define GOT_FOCUS\t\t4\n#define BUTTON_DOWN\t\t8\n#define UPDATE_SCROLLBARS\t0x10\n#define NEED_REPICK\t\t0x20\n#define OPTIONS_FREED\t\t0x40\n#define DESTROYED\t\t0x80\n\n/*\n * Records of the following type define segment types in terms of a collection\n * of procedures that may be called to manipulate segments of that type.\n */\n\ntypedef TkTextSegment *\tTk_SegSplitProc(struct TkTextSegment *segPtr,\n\t\t\t    Tcl_Size index);\ntypedef int\t\tTk_SegDeleteProc(struct TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\ntypedef TkTextSegment *\tTk_SegCleanupProc(struct TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\ntypedef void\t\tTk_SegLineChangeProc(struct TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\ntypedef int\t\tTk_SegLayoutProc(struct TkText *textPtr,\n\t\t\t    struct TkTextIndex *indexPtr,\n\t\t\t    TkTextSegment *segPtr, Tcl_Size offset, int maxX,\n\t\t\t    Tcl_Size maxChars, int noCharsYet, TkWrapMode wrapMode,\n\t\t\t    struct TkTextDispChunk *chunkPtr);\ntypedef void\t\tTk_SegCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\n\ntypedef struct Tk_SegType {\n    const char *name;\t\t/* Name of this kind of segment. */\n    int leftGravity;\t\t/* If a segment has zero size (e.g. a mark or\n\t\t\t\t * tag toggle), does it attach to character to\n\t\t\t\t * its left or right? 1 means left, 0 means\n\t\t\t\t * right. */\n    Tk_SegSplitProc *splitProc;\t/* Procedure to split large segment into two\n\t\t\t\t * smaller ones. */\n    Tk_SegDeleteProc *deleteProc;\n\t\t\t\t/* Procedure to call to delete segment. */\n    Tk_SegCleanupProc *cleanupProc;\n\t\t\t\t/* After any change to a line, this procedure\n\t\t\t\t * is invoked for all segments left in the\n\t\t\t\t * line to perform any cleanup they wish\n\t\t\t\t * (e.g. joining neighboring segments). */\n    Tk_SegLineChangeProc *lineChangeProc;\n\t\t\t\t/* Invoked when a segment is about to be moved\n\t\t\t\t * from its current line to an earlier line\n\t\t\t\t * because of a deletion. The linePtr is that\n\t\t\t\t * for the segment's old line. CleanupProc\n\t\t\t\t * will be invoked after the deletion is\n\t\t\t\t * finished. */\n    Tk_SegLayoutProc *layoutProc;\n\t\t\t\t/* Returns size information when figuring out\n\t\t\t\t * what to display in window. */\n    Tk_SegCheckProc *checkProc;\t/* Called during consistency checks to check\n\t\t\t\t * internal consistency of segment. */\n} Tk_SegType;\n\n/*\n * The following type and items describe different flags for text widget items\n * to count. They are used in both tkText.c and tkTextIndex.c, in\n * 'CountIndices', 'TkTextIndexBackChars', 'TkTextIndexForwChars', and\n * 'TkTextIndexCount'.\n */\n\ntypedef int TkTextCountType;\n\n#define COUNT_CHARS 0\n#define COUNT_INDICES 1\n#define COUNT_DISPLAY 2\n#define COUNT_DISPLAY_CHARS (COUNT_CHARS | COUNT_DISPLAY)\n#define COUNT_DISPLAY_INDICES (COUNT_INDICES | COUNT_DISPLAY)\n\n/*\n * The following structure is used to keep track of elided text taking account\n * of different tag priorities, it is need for quick calculations of whether a\n * single index is elided, and to start at a given index and maintain a\n * correct elide state as we move or count forwards or backwards.\n */\n\n#define LOTSA_TAGS 1000\ntypedef struct TkTextElideInfo {\n    Tcl_Size numTags;\t\t/* Total tags in widget. */\n    bool elide;\t\t\t/* Is the state currently elided. */\n    Tcl_Size elidePriority;\t\t\t/* Tag priority controlling elide state. */\n    TkTextSegment *segPtr;\t/* Segment to look at next. */\n    Tcl_Size segOffset;\t\t/* Offset of segment within line. */\n    int deftagCnts[LOTSA_TAGS];\n    TkTextTag *deftagPtrs[LOTSA_TAGS];\n    int *tagCnts;\t\t/* 0 or 1 depending if the tag with that\n\t\t\t\t * priority is on or off. */\n    TkTextTag **tagPtrs;\t/* Only filled with a tagPtr if the\n\t\t\t\t * corresponding tagCnt is 1. */\n} TkTextElideInfo;\n\n/*\n * The constant below is used to specify a line when what is really wanted is\n * the entire text. For now, just use a very big number.\n */\n\n#define TK_END_OF_TEXT\t\t1000000\n\n/*\n * The following definition specifies the maximum number of characters needed\n * in a string to hold a position specifier.\n */\n\n#define TK_POS_CHARS\t\t30\n\n/*\n * Mask used for those options which may impact the pixel height calculations\n * of individual lines displayed in the widget.\n */\n\n#define TK_TEXT_LINE_GEOMETRY\t\t(1 << 0)\n\n/*\n * Mask used for those options which may impact the start and end lines\n * used in the widget.\n */\n\n#define TK_TEXT_LINE_RANGE\t\t(1 << 1)\n\n/*\n * Used as 'action' values in calls to TkTextInvalidateLineMetrics\n */\n\ntypedef enum {\n    TK_TEXT_INVALIDATE_ONLY,\n    TK_TEXT_INVALIDATE_INSERT,\n    TK_TEXT_INVALIDATE_DELETE\n} TkTextInvalidateAction;\n\n/*\n * Used as special 'pickPlace' values in calls to TkTextSetYView. Zero or\n * positive values indicate a number of pixels.\n */\n\n#define TK_TEXT_PICKPLACE\t-1\n#define TK_TEXT_NOPIXELADJUST\t-2\n\n/*\n * Declarations for variables shared among the text-related files:\n */\n\nMODULE_SCOPE int\ttkBTreeDebug;\nMODULE_SCOPE int\ttkTextDebug;\nMODULE_SCOPE const Tk_SegType tkTextCharType;\nMODULE_SCOPE const Tk_SegType tkTextLeftMarkType;\nMODULE_SCOPE const Tk_SegType tkTextRightMarkType;\nMODULE_SCOPE const Tk_SegType tkTextToggleOnType;\nMODULE_SCOPE const Tk_SegType tkTextToggleOffType;\nMODULE_SCOPE const Tk_SegType tkTextEmbWindowType;\nMODULE_SCOPE const Tk_SegType tkTextEmbImageType;\n\n/*\n * Convenience macros for use by B-tree clients which want to access pixel\n * information on each line. Currently only used by TkTextDisp.c\n */\n\n#define TkBTreeLinePixelCount(text, line) \\\n\t(line)->pixels[2*(text)->pixelReference]\n#define TkBTreeLinePixelEpoch(text, line) \\\n\t(line)->pixels[1+2*(text)->pixelReference]\n\n/*\n * Declarations for procedures that are used by the text-related files but\n * shouldn't be used anywhere else in Tk (or by Tk clients):\n */\n\nMODULE_SCOPE int\tTkBTreeAdjustPixelHeight(const TkText *textPtr,\n\t\t\t    TkTextLine *linePtr, int newPixelHeight,\n\t\t\t    int mergedLogicalLines);\nMODULE_SCOPE bool\tTkBTreeCharTagged(const TkTextIndex *indexPtr,\n\t\t\t    TkTextTag *tagPtr);\nMODULE_SCOPE void\tTkBTreeCheck(TkTextBTree tree);\nMODULE_SCOPE TkTextBTree TkBTreeCreate(TkSharedText *sharedTextPtr);\nMODULE_SCOPE void\tTkBTreeAddClient(TkTextBTree tree, TkText *textPtr,\n\t\t\t    int defaultHeight);\nMODULE_SCOPE void\tTkBTreeClientRangeChanged(TkText *textPtr,\n\t\t\t    int defaultHeight);\nMODULE_SCOPE void\tTkBTreeRemoveClient(TkTextBTree tree,\n\t\t\t    TkText *textPtr);\nMODULE_SCOPE void\tTkBTreeDestroy(TkTextBTree tree);\nMODULE_SCOPE void\tTkBTreeDeleteIndexRange(TkTextBTree tree,\n\t\t\t    TkTextIndex *index1Ptr, TkTextIndex *index2Ptr);\nMODULE_SCOPE Tcl_Size\tTkBTreeEpoch(TkTextBTree tree);\nMODULE_SCOPE TkTextLine *TkBTreeFindLine(TkTextBTree tree,\n\t\t\t    const TkText *textPtr, Tcl_Size line);\nMODULE_SCOPE TkTextLine *TkBTreeFindPixelLine(TkTextBTree tree,\n\t\t\t    const TkText *textPtr, int pixels,\n\t\t\t    int *pixelOffset);\nMODULE_SCOPE TkTextTag **TkBTreeGetTags(const TkTextIndex *indexPtr,\n\t\t\t    const TkText *textPtr, Tcl_Size *numTagsPtr);\nMODULE_SCOPE void\tTkBTreeInsertChars(TkTextBTree tree,\n\t\t\t    TkTextIndex *indexPtr, const char *string);\nMODULE_SCOPE Tcl_Size\tTkBTreeLinesTo(const TkText *textPtr,\n\t\t\t    TkTextLine *linePtr);\nMODULE_SCOPE int\tTkBTreePixelsTo(const TkText *textPtr,\n\t\t\t    TkTextLine *linePtr);\nMODULE_SCOPE void\tTkBTreeLinkSegment(TkTextSegment *segPtr,\n\t\t\t    TkTextIndex *indexPtr);\nMODULE_SCOPE TkTextLine *TkBTreeNextLine(const TkText *textPtr,\n\t\t\t    TkTextLine *linePtr);\nMODULE_SCOPE int\tTkBTreeNextTag(TkTextSearch *searchPtr);\nMODULE_SCOPE int\tTkBTreeNumPixels(TkTextBTree tree,\n\t\t\t    const TkText *textPtr);\nMODULE_SCOPE TkTextLine *TkBTreePreviousLine(TkText *textPtr,\n\t\t\t    TkTextLine *linePtr);\nMODULE_SCOPE int\tTkBTreePrevTag(TkTextSearch *searchPtr);\nMODULE_SCOPE void\tTkBTreeStartSearch(TkTextIndex *index1Ptr,\n\t\t\t    TkTextIndex *index2Ptr, TkTextTag *tagPtr,\n\t\t\t    TkTextSearch *searchPtr);\nMODULE_SCOPE void\tTkBTreeStartSearchBack(TkTextIndex *index1Ptr,\n\t\t\t    TkTextIndex *index2Ptr, TkTextTag *tagPtr,\n\t\t\t    TkTextSearch *searchPtr);\nMODULE_SCOPE int\tTkBTreeTag(TkTextIndex *index1Ptr,\n\t\t\t    TkTextIndex *index2Ptr, TkTextTag *tagPtr,\n\t\t\t    bool add);\nMODULE_SCOPE void\tTkBTreeUnlinkSegment(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nMODULE_SCOPE void\tTkTextBindProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nMODULE_SCOPE void\tTkTextSelectionEvent(TkText *textPtr);\nMODULE_SCOPE int\tTkTextIndexBbox(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,\n\t\t\t    int *widthPtr, int *heightPtr, int *charWidthPtr,\n\t\t\t    int *cursorWidthPtr);\nMODULE_SCOPE int\tTkTextCharLayoutProc(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, TkTextSegment *segPtr,\n\t\t\t    Tcl_Size offset, int maxX, Tcl_Size maxChars, int noCharsYet,\n\t\t\t    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);\nMODULE_SCOPE void\tTkTextCreateDInfo(TkText *textPtr);\nMODULE_SCOPE int\tTkTextDLineInfo(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,\n\t\t\t    int *widthPtr, int *heightPtr, int *basePtr);\nMODULE_SCOPE void\tTkTextEmbWinDisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, int x, int y,\n\t\t\t    int lineHeight, int baseline, Display *display,\n\t\t\t    Drawable dst, int screenY);\nMODULE_SCOPE TkTextTag *TkTextCreateTag(TkText *textPtr,\n\t\t\t    const char *tagName, int *newTag);\nMODULE_SCOPE void\tTkTextFreeDInfo(TkText *textPtr);\nMODULE_SCOPE void\tTkTextDeleteTag(TkText *textPtr, TkTextTag *tagPtr);\nMODULE_SCOPE void\tTkTextFreeTag(TkText *textPtr, TkTextTag *tagPtr);\nMODULE_SCOPE int\tTkTextGetObjIndex(Tcl_Interp *interp, TkText *textPtr,\n\t\t\t    Tcl_Obj *idxPtr, TkTextIndex *indexPtr);\nMODULE_SCOPE int\tTkTextSharedGetObjIndex(Tcl_Interp *interp,\n\t\t\t    TkSharedText *sharedTextPtr, Tcl_Obj *idxPtr,\n\t\t\t    TkTextIndex *indexPtr);\nMODULE_SCOPE const\tTkTextIndex *TkTextGetIndexFromObj(Tcl_Interp *interp,\n\t\t\t    TkText *textPtr, Tcl_Obj *objPtr);\nMODULE_SCOPE TkTextTabArray *TkTextGetTabs(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tcl_Obj *stringPtr);\nMODULE_SCOPE void\tTkTextFindDisplayLineEnd(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, int end, int *xOffset);\nMODULE_SCOPE void\tTkTextIndexBackChars(const TkText *textPtr,\n\t\t\t    const TkTextIndex *srcPtr, Tcl_Size count,\n\t\t\t    TkTextIndex *dstPtr, TkTextCountType type);\nMODULE_SCOPE int\tTkTextIndexCmp(const TkTextIndex *index1Ptr,\n\t\t\t    const TkTextIndex *index2Ptr);\nMODULE_SCOPE Tcl_Size\tTkTextIndexCountBytes(const TkText *textPtr,\n\t\t\t    const TkTextIndex *index1Ptr,\n\t\t\t    const TkTextIndex *index2Ptr);\nMODULE_SCOPE Tcl_Size\tTkTextIndexCount(const TkText *textPtr,\n\t\t\t    const TkTextIndex *index1Ptr,\n\t\t\t    const TkTextIndex *index2Ptr,\n\t\t\t    TkTextCountType type);\nMODULE_SCOPE void\tTkTextIndexForwChars(const TkText *textPtr,\n\t\t\t    const TkTextIndex *srcPtr, Tcl_Size count,\n\t\t\t    TkTextIndex *dstPtr, TkTextCountType type);\nMODULE_SCOPE void\tTkTextIndexOfX(TkText *textPtr, int x,\n\t\t\t    TkTextIndex *indexPtr);\nMODULE_SCOPE int\tTkTextIndexYPixels(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr);\nMODULE_SCOPE TkTextSegment *TkTextIndexToSeg(const TkTextIndex *indexPtr,\n\t\t\t    Tcl_Size *offsetPtr);\nMODULE_SCOPE void\tTkTextLostSelection(void *clientData);\nMODULE_SCOPE TkTextIndex *TkTextMakeCharIndex(TkTextBTree tree, TkText *textPtr,\n\t\t\t    Tcl_Size lineIndex, Tcl_Size charIndex,\n\t\t\t    TkTextIndex *indexPtr);\nMODULE_SCOPE int\tTkTextMeasureDown(TkText *textPtr,\n\t\t\t    TkTextIndex *srcPtr, int distance);\nMODULE_SCOPE void\tTkTextFreeElideInfo(TkTextElideInfo *infoPtr);\nMODULE_SCOPE bool\tTkTextIsElided(const TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr,\n\t\t\t    TkTextElideInfo *infoPtr);\nMODULE_SCOPE int\tTkTextMakePixelIndex(TkText *textPtr,\n\t\t\t    int pixelIndex, TkTextIndex *indexPtr);\nMODULE_SCOPE void\tTkTextInvalidateLineMetrics(\n\t\t\t    TkSharedText *sharedTextPtr, TkText *textPtr,\n\t\t\t    TkTextLine *linePtr, Tcl_Size lineCount, TkTextInvalidateAction action);\nMODULE_SCOPE Tcl_Size\tTkTextUpdateLineMetrics(TkText *textPtr, Tcl_Size lineNum,\n\t\t\t    Tcl_Size endLine, int doThisMuch);\nMODULE_SCOPE int\tTkTextUpdateOneLine(TkText *textPtr,\n\t\t\t    TkTextLine *linePtr, int pixelHeight,\n\t\t\t    TkTextIndex *indexPtr, int partialCalc);\nMODULE_SCOPE int\tTkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE int\tTkTextMarkNameToIndex(TkText *textPtr,\n\t\t\t    const char *name, TkTextIndex *indexPtr);\nMODULE_SCOPE void\tTkTextMarkSegToIndex(TkText *textPtr,\n\t\t\t    TkTextSegment *markPtr, TkTextIndex *indexPtr);\nMODULE_SCOPE void\tTkTextEventuallyRepick(TkText *textPtr);\nMODULE_SCOPE Bool\tTkTextPendingsync(TkText *textPtr);\nMODULE_SCOPE void\tTkTextPickCurrent(TkText *textPtr, XEvent *eventPtr);\nMODULE_SCOPE void\tTkTextPixelIndex(TkText *textPtr, int x, int y,\n\t\t\t    TkTextIndex *indexPtr, bool *nearest);\nMODULE_SCOPE Tcl_Obj *\tTkTextNewIndexObj(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr);\nMODULE_SCOPE void\tTkTextRedrawRegion(TkText *textPtr, int x, int y,\n\t\t\t    int width, int height);\nMODULE_SCOPE void\tTkTextRedrawTag(TkSharedText *sharedTextPtr,\n\t\t\t    TkText *textPtr, TkTextIndex *index1Ptr,\n\t\t\t    TkTextIndex *index2Ptr, TkTextTag *tagPtr,\n\t\t\t    bool withTag);\nMODULE_SCOPE void\tTkTextRelayoutWindow(TkText *textPtr, int mask);\nMODULE_SCOPE int\tTkTextScanCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE int\tTkTextSeeCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE Tcl_Size TkTextSegToOffset(const TkTextSegment *segPtr,\n\t\t\t    const TkTextLine *linePtr);\nMODULE_SCOPE void\tTkTextSetYView(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, int pickPlace);\nMODULE_SCOPE int\tTkTextTagCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE int\tTkTextImageCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE int\tTkTextImageIndex(TkText *textPtr,\n\t\t\t    const char *name, TkTextIndex *indexPtr);\nMODULE_SCOPE int\tTkTextWindowCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE int\tTkTextWindowIndex(TkText *textPtr, const char *name,\n\t\t\t    TkTextIndex *indexPtr);\nMODULE_SCOPE int\tTkTextYviewCmd(TkText *textPtr, Tcl_Interp *interp,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nMODULE_SCOPE void\tTkTextWinFreeClient(Tcl_HashEntry *hPtr,\n\t\t\t    TkTextEmbWindowClient *client);\nMODULE_SCOPE void       TkTextRunAfterSyncCmd(void *clientData);\nMODULE_SCOPE int        TkTextIndexAdjustToStartEnd(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, bool check);\n#endif /* _TKTEXT */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextBTree.c",
    "content": "/*\n * tkTextBTree.c --\n *\n *\tThis file contains code that manages the B-tree representation of text\n *\tfor Tk's text widget and implements character and toggle segment\n *\ttypes.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkText.h\"\n\n/*\n * Implementation notes:\n *\n * Most of this file is independent of the text widget implementation and\n * representation now. Without much effort this could be developed further\n * into a new Tcl object type of which the Tk text widget is one example of a\n * client.\n *\n * The B-tree is set up with a dummy last line of text which must not be\n * displayed, and must _never_ have a non-zero pixel count. This dummy line is\n * a historical convenience to avoid other code having to deal with NULL\n * TkTextLines. Since Tk 8.5, with pixel line height calculations and peer\n * widgets, this dummy line is becoming somewhat of a liability, and special\n * case code has been required to deal with it. It is probably a good idea to\n * investigate removing the dummy line completely. This could result in an\n * overall simplification (although it would require new special case code to\n * deal with the fact that '.text index end' would then not really point to a\n * valid line, rather it would point to the beginning of a non-existent line\n * one beyond all current lines - we could perhaps define that as a\n * TkTextIndex with a NULL TkTextLine ptr).\n */\n\n/*\n * The data structure below keeps summary information about one tag as part of\n * the tag information in a node.\n */\n\ntypedef struct Summary {\n    TkTextTag *tagPtr;\t\t/* Handle for tag. */\n    Tcl_Size toggleCount;\t\t/* Number of transitions into or out of this\n\t\t\t\t * tag that occur in the subtree rooted at\n\t\t\t\t * this node. */\n    struct Summary *nextPtr;\t/* Next in list of all tags for same node, or\n\t\t\t\t * NULL if at end of list. */\n} Summary;\n\n/*\n * The data structure below defines a node in the B-tree.\n */\n\ntypedef struct Node {\n    struct Node *parentPtr;\t/* Pointer to parent node, or NULL if this is\n\t\t\t\t * the root. */\n    struct Node *nextPtr;\t/* Next in list of siblings with the same\n\t\t\t\t * parent node, or NULL for end of list. */\n    Summary *summaryPtr;\t/* First in malloc-ed list of info about tags\n\t\t\t\t * in this subtree (NULL if no tag info in the\n\t\t\t\t * subtree). */\n    Tcl_Size level;\t\t/* Level of this node in the B-tree. 0 refers\n\t\t\t\t * to the bottom of the tree (children are\n\t\t\t\t * lines, not nodes). */\n    union {\t\t\t/* First in linked list of children. */\n\tstruct Node *nodePtr;\t/* Used if level > 0. */\n\tTkTextLine *linePtr;\t/* Used if level == 0. */\n    } children;\n    int numChildren;\t\t/* Number of children of this node. */\n    int numLines;\t\t/* Total number of lines (leaves) in the\n\t\t\t\t * subtree rooted here. */\n    int *numPixels;\t\t/* Array containing total number of vertical\n\t\t\t\t * display pixels in the subtree rooted here,\n\t\t\t\t * one entry for each peer widget. */\n} Node;\n\n/*\n * Used to avoid having to allocate and deallocate arrays on the fly for\n * commonly used functions. Must be > 0.\n */\n\n#define PIXEL_CLIENTS 5\n\n/*\n * Upper and lower bounds on how many children a node may have: rebalance when\n * either of these limits is exceeded. MAX_CHILDREN should be twice\n * MIN_CHILDREN and MIN_CHILDREN must be >= 2.\n */\n\n#define MAX_CHILDREN 12\n#define MIN_CHILDREN 6\n\n/*\n * The data structure below defines an entire B-tree. Since text widgets are\n * the only current B-tree clients, 'clients' and 'pixelReferences' are\n * identical.\n */\n\ntypedef struct BTree {\n    Node *rootPtr;\t\t/* Pointer to root of B-tree. */\n    int clients;\t\t/* Number of clients of this B-tree. */\n    int pixelReferences;\t/* Number of clients of this B-tree which care\n\t\t\t\t * about pixel heights. */\n    Tcl_Size stateEpoch;\t /* Updated each time any aspect of the B-tree\n\t\t\t\t * changes. */\n    TkSharedText *sharedTextPtr;/* Used to find tagTable in consistency\n\t\t\t\t * checking code, and to access list of all\n\t\t\t\t * B-tree clients. */\n    int startEndCount;\n    TkTextLine **startEnd;\n    TkText **startEndRef;\n} BTree;\n\n/*\n * The structure below is used to pass information between\n * TkBTreeGetTags and IncCount:\n */\n\ntypedef struct TagInfo {\n    int numTags;\t\t/* Number of tags for which there is currently\n\t\t\t\t * information in tags and counts. */\n    int arraySize;\t\t/* Number of entries allocated for tags and\n\t\t\t\t * counts. */\n    TkTextTag **tagPtrs;\t/* Array of tags seen so far. Malloc-ed. */\n    int *counts;\t\t/* Toggle count (so far) for each entry in\n\t\t\t\t * tags. Malloc-ed. */\n} TagInfo;\n\n/*\n * Variable that indicates whether to enable consistency checks for debugging.\n */\n\nint tkBTreeDebug = 0;\n\n/*\n * Macros that determine how much space to allocate for new segments:\n */\n\n#define CSEG_SIZE(chars) (offsetof(TkTextSegment, body) \\\n\t+ 1 + (chars))\n#define TSEG_SIZE (offsetof(TkTextSegment, body) \\\n\t+ sizeof(TkTextToggle))\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic int\t\tAdjustPixelClient(BTree *treePtr, int defaultHeight,\n\t\t\t    Node *nodePtr, TkTextLine *start, TkTextLine *end,\n\t\t\t    int useReference, int newPixelReferences,\n\t\t\t    int *counting);\nstatic void\t\tChangeNodeToggleCount(Node *nodePtr,\n\t\t\t    TkTextTag *tagPtr, Tcl_Size delta);\nstatic void\t\tCharCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic int\t\tCharDeleteProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\nstatic TkTextSegment *\tCharCleanupProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic TkTextSegment *\tCharSplitProc(TkTextSegment *segPtr, Tcl_Size index);\nstatic void\t\tCheckNodeConsistency(Node *nodePtr, int references);\nstatic void\t\tCleanupLine(TkTextLine *linePtr);\nstatic void\t\tDeleteSummaries(Summary *tagPtr);\nstatic void\t\tDestroyNode(Node *nodePtr);\nstatic TkTextSegment *\tFindTagEnd(TkTextBTree tree, TkTextTag *tagPtr,\n\t\t\t    TkTextIndex *indexPtr);\nstatic void\t\tIncCount(TkTextTag *tagPtr, Tcl_Size inc,\n\t\t\t    TagInfo *tagInfoPtr);\nstatic void\t\tRebalance(BTree *treePtr, Node *nodePtr);\nstatic void\t\tRecomputeNodeCounts(BTree *treePtr, Node *nodePtr);\nstatic void\t\tRemovePixelClient(BTree *treePtr, Node *nodePtr,\n\t\t\t    int overwriteWithLast);\nstatic TkTextSegment *\tSplitSeg(TkTextIndex *indexPtr);\nstatic void\t\tToggleCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic TkTextSegment *\tToggleCleanupProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic int\t\tToggleDeleteProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\nstatic void\t\tToggleLineChangeProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic TkTextSegment *\tFindTagStart(TkTextBTree tree, TkTextTag *tagPtr,\n\t\t\t    TkTextIndex *indexPtr);\nstatic void\t\tAdjustStartEndRefs(BTree *treePtr, TkText *textPtr,\n\t\t\t    int action);\n\n/*\n * Actions for use by AdjustStartEndRefs\n */\n\n#define TEXT_ADD_REFS\t\t1\n#define TEXT_REMOVE_REFS\t2\n\n/*\n * Type record for character segments:\n */\n\nconst Tk_SegType tkTextCharType = {\n    \"character\",\t\t/* name */\n    0,\t\t\t\t/* leftGravity */\n    CharSplitProc,\t\t/* splitProc */\n    CharDeleteProc,\t\t/* deleteProc */\n    CharCleanupProc,\t\t/* cleanupProc */\n    NULL,\t\t\t/* lineChangeProc */\n    TkTextCharLayoutProc,\t/* layoutProc */\n    CharCheckProc\t\t/* checkProc */\n};\n\n/*\n * Type record for segments marking the beginning of a tagged range:\n */\n\nconst Tk_SegType tkTextToggleOnType = {\n    \"toggleOn\",\t\t\t/* name */\n    0,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    ToggleDeleteProc,\t\t/* deleteProc */\n    ToggleCleanupProc,\t\t/* cleanupProc */\n    ToggleLineChangeProc,\t/* lineChangeProc */\n    NULL,\t\t\t/* layoutProc */\n    ToggleCheckProc\t\t/* checkProc */\n};\n\n/*\n * Type record for segments marking the end of a tagged range:\n */\n\nconst Tk_SegType tkTextToggleOffType = {\n    \"toggleOff\",\t\t/* name */\n    1,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    ToggleDeleteProc,\t\t/* deleteProc */\n    ToggleCleanupProc,\t\t/* cleanupProc */\n    ToggleLineChangeProc,\t/* lineChangeProc */\n    NULL,\t\t\t/* layoutProc */\n    ToggleCheckProc\t\t/* checkProc */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeCreate --\n *\n *\tThis function is called to create a new text B-tree.\n *\n * Results:\n *\tThe return value is a pointer to a new B-tree containing one line with\n *\tnothing but a newline character.\n *\n * Side effects:\n *\tMemory is allocated and initialized.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextBTree\nTkBTreeCreate(\n    TkSharedText *sharedTextPtr)\n{\n    BTree *treePtr;\n    Node *rootPtr;\n    TkTextLine *linePtr, *linePtr2;\n    TkTextSegment *segPtr;\n\n    /*\n     * The tree will initially have two empty lines. The second line isn't\n     * actually part of the tree's contents, but its presence makes several\n     * operations easier. The tree will have one node, which is also the root\n     * of the tree.\n     */\n\n    rootPtr = (Node *)Tcl_Alloc(sizeof(Node));\n    linePtr = (TkTextLine *)Tcl_Alloc(sizeof(TkTextLine));\n    linePtr2 = (TkTextLine *)Tcl_Alloc(sizeof(TkTextLine));\n\n    rootPtr->parentPtr = NULL;\n    rootPtr->nextPtr = NULL;\n    rootPtr->summaryPtr = NULL;\n    rootPtr->level = 0;\n    rootPtr->children.linePtr = linePtr;\n    rootPtr->numChildren = 2;\n    rootPtr->numLines = 2;\n\n    /*\n     * The tree currently has no registered clients, so all pixel count\n     * pointers are simply NULL.\n     */\n\n    rootPtr->numPixels = NULL;\n    linePtr->pixels = NULL;\n    linePtr2->pixels = NULL;\n\n    linePtr->parentPtr = rootPtr;\n    linePtr->nextPtr = linePtr2;\n    segPtr = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(1));\n    linePtr->segPtr = segPtr;\n    segPtr->typePtr = &tkTextCharType;\n    segPtr->nextPtr = NULL;\n    segPtr->size = 1;\n    segPtr->body.chars[0] = '\\n';\n    segPtr->body.chars[1] = 0;\n\n    linePtr2->parentPtr = rootPtr;\n    linePtr2->nextPtr = NULL;\n    segPtr = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(1));\n    linePtr2->segPtr = segPtr;\n    segPtr->typePtr = &tkTextCharType;\n    segPtr->nextPtr = NULL;\n    segPtr->size = 1;\n    segPtr->body.chars[0] = '\\n';\n    segPtr->body.chars[1] = 0;\n\n    treePtr = (BTree *)Tcl_Alloc(sizeof(BTree));\n    treePtr->sharedTextPtr = sharedTextPtr;\n    treePtr->rootPtr = rootPtr;\n    treePtr->clients = 0;\n    treePtr->stateEpoch = 0;\n    treePtr->pixelReferences = 0;\n    treePtr->startEndCount = 0;\n    treePtr->startEnd = NULL;\n    treePtr->startEndRef = NULL;\n\n    return (TkTextBTree) treePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeAddClient --\n *\n *\tThis function is called to provide a client with access to a given\n *\tB-tree. If the client wishes to make use of the B-tree's pixel height\n *\tstorage, caching and calculation mechanisms, then a non-negative\n *\t'defaultHeight' must be provided. In this case the return value is a\n *\tpixel tree reference which must be provided in all of the B-tree API\n *\twhich refers to or modifies pixel heights:\n *\n *\tTkBTreeAdjustPixelHeight,\n *\tTkBTreeFindPixelLine,\n *\tTkBTreeNumPixels,\n *\tTkBTreePixelsTo,\n *\t(and two private functions AdjustPixelClient, RemovePixelClient).\n *\n *\tIf this is not provided, then the above functions must never be called\n *\tfor this client.\n *\n * Results:\n *\tThe return value is the pixelReference used by the B-tree to refer to\n *\tpixel counts for the new client. It should be stored by the caller. If\n *\tdefaultHeight was negative, then the return value will be -1.\n *\n * Side effects:\n *\tMemory may be allocated and initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeAddClient(\n    TkTextBTree tree,\t\t/* B-tree to add a client to. */\n    TkText *textPtr,\t\t/* Client to add. */\n    int defaultHeight)\t\t/* Default line height for the new client, or\n\t\t\t\t * -1 if no pixel heights are to be kept. */\n{\n    BTree *treePtr = (BTree *) tree;\n\n    if (treePtr == NULL) {\n\tTcl_Panic(\"NULL treePtr in TkBTreeAddClient\");\n    }\n\n    if (textPtr->start != NULL || textPtr->end != NULL) {\n\tAdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS);\n    }\n\n    if (defaultHeight >= 0) {\n\tTkTextLine *end;\n\tint counting = (textPtr->start == NULL ? 1 : 0);\n\tint useReference = treePtr->pixelReferences;\n\n\t/*\n\t * We must set the 'end' value in AdjustPixelClient so that the last\n\t * dummy line in the B-tree doesn't contain a pixel height.\n\t */\n\n\tend = textPtr->end;\n\tif (end == NULL) {\n\t    end = TkBTreeFindLine(tree, NULL, TkBTreeNumLines(tree, NULL));\n\t}\n\tAdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr,\n\t\ttextPtr->start, end, useReference, useReference+1, &counting);\n\n\ttextPtr->pixelReference = useReference;\n\ttreePtr->pixelReferences++;\n    } else {\n\ttextPtr->pixelReference = -1;\n    }\n    treePtr->clients++;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeClientRangeChanged --\n *\n *\tCalled when the -startline or -endline options of a text widget client\n *\tof the B-tree have changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLots of processing of the B-tree is done, with potential for memory to\n *\tbe allocated and initialized for the pixel heights of the widget.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeClientRangeChanged(\n    TkText *textPtr,\t\t/* Client whose start, end have changed. */\n    int defaultHeight)\t\t/* Default line height for the new client, or\n\t\t\t\t * -1 if no pixel heights are to be kept. */\n{\n    TkTextLine *end;\n    BTree *treePtr = (BTree *) textPtr->sharedTextPtr->tree;\n\n    int counting = (textPtr->start == NULL ? 1 : 0);\n    int useReference = textPtr->pixelReference;\n\n    AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS | TEXT_REMOVE_REFS);\n\n    /*\n     * We must set the 'end' value in AdjustPixelClient so that the last dummy\n     * line in the B-tree doesn't contain a pixel height.\n     */\n\n    end = textPtr->end;\n    if (end == NULL) {\n\tend = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\tNULL, TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL));\n    }\n    AdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr,\n\t    textPtr->start, end, useReference, treePtr->pixelReferences,\n\t    &counting);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeDestroy --\n *\n *\tDelete a B-tree, recycling all of the storage it contains.\n *\n * Results:\n *\tThe tree is deleted, so 'tree' should never again be used.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeDestroy(\n    TkTextBTree tree)\t\t/* Tree to clean up. */\n{\n    BTree *treePtr = (BTree *) tree;\n\n    /*\n     * There's no need to loop over each client of the tree, calling\n     * 'TkBTreeRemoveClient', since the 'DestroyNode' will clean everything up\n     * itself.\n     */\n\n    DestroyNode(treePtr->rootPtr);\n    if (treePtr->startEnd != NULL) {\n\tTcl_Free(treePtr->startEnd);\n\tTcl_Free(treePtr->startEndRef);\n    }\n    Tcl_Free(treePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeEpoch --\n *\n *\tReturn the epoch for the B-tree. This number is incremented any time\n *\tanything changes in the tree.\n *\n * Results:\n *\tThe epoch number.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkBTreeEpoch(\n    TkTextBTree tree)\t\t/* Tree to get epoch for. */\n{\n    BTree *treePtr = (BTree *) tree;\n    return treePtr->stateEpoch;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeRemoveClient --\n *\n *\tRemove a client widget from its B-tree, cleaning up the pixel arrays\n *\twhich it uses if necessary. If this is the last such widget, we also\n *\tdestroy the whole tree.\n *\n * Results:\n *\tAll tree-specific aspects of the given client are deleted. If no more\n *\treferences exist, then the given tree is also deleted (in which case\n *\t'tree' must not be used again).\n *\n * Side effects:\n *\tMemory may be freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeRemoveClient(\n    TkTextBTree tree,\t\t/* Tree to remove client from. */\n    TkText *textPtr)\t\t/* Client to remove. */\n{\n    BTree *treePtr = (BTree *) tree;\n    int pixelReference = textPtr->pixelReference;\n\n    if (treePtr->clients == 1) {\n\t/*\n\t * The last reference to the tree.\n\t */\n\n\tDestroyNode(treePtr->rootPtr);\n\tTcl_Free(treePtr);\n\treturn;\n    } else if (pixelReference == -1) {\n\t/*\n\t * A client which doesn't care about pixels.\n\t */\n\n\ttreePtr->clients--;\n    } else {\n\t/*\n\t * Clean up pixel data for the given reference.\n\t */\n\n\tif (pixelReference == (treePtr->pixelReferences-1)) {\n\t    /*\n\t     * The widget we're removing has the last index, so deletion is\n\t     * easier.\n\t     */\n\n\t    RemovePixelClient(treePtr, treePtr->rootPtr, -1);\n\t} else {\n\t    TkText *adjustPtr;\n\n\t    RemovePixelClient(treePtr, treePtr->rootPtr, pixelReference);\n\n\t    /*\n\t     * Now we need to adjust the 'pixelReference' of the peer widget\n\t     * whose storage we've just moved.\n\t     */\n\n\t    adjustPtr = treePtr->sharedTextPtr->peers;\n\t    while (adjustPtr != NULL) {\n\t\tif (adjustPtr->pixelReference == treePtr->pixelReferences-1) {\n\t\t    adjustPtr->pixelReference = pixelReference;\n\t\t    break;\n\t\t}\n\t\tadjustPtr = adjustPtr->next;\n\t    }\n\t    if (adjustPtr == NULL) {\n\t\tTcl_Panic(\"Couldn't find text widget with correct reference\");\n\t    }\n\t}\n\ttreePtr->pixelReferences--;\n\ttreePtr->clients--;\n    }\n\n    if (textPtr->start != NULL || textPtr->end != NULL) {\n\tAdjustStartEndRefs(treePtr, textPtr, TEXT_REMOVE_REFS);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustStartEndRefs --\n *\n *\tModify B-tree's cache of start, end lines for the given text widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe number of cached items may change (treePtr->startEndCount).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAdjustStartEndRefs(\n    BTree *treePtr,\t\t/* The entire B-tree. */\n    TkText *textPtr,\t\t/* The text widget for which we want to adjust\n\t\t\t\t * its start and end cache. */\n    int action)\t\t\t/* Action to perform. */\n{\n    if (action & TEXT_REMOVE_REFS) {\n\tint i = 0;\n\tint count = 0;\n\n\twhile (i < treePtr->startEndCount) {\n\t    if (i != count) {\n\t\ttreePtr->startEnd[count] = treePtr->startEnd[i];\n\t\ttreePtr->startEndRef[count] = treePtr->startEndRef[i];\n\t    }\n\t    if (treePtr->startEndRef[i] != textPtr) {\n\t\tcount++;\n\t    }\n\t    i++;\n\t}\n\ttreePtr->startEndCount = count;\n\tif (count > 0) {\n\t    treePtr->startEnd = (TkTextLine**)Tcl_Realloc(treePtr->startEnd,\n\t\t    sizeof(TkTextLine*) * count);\n\t    treePtr->startEndRef = (TkText**)Tcl_Realloc(treePtr->startEndRef,\n\t\t    sizeof(TkText*) * count);\n\t}\n\telse {\n\t    Tcl_Free(treePtr->startEndRef);\n\t    treePtr->startEndRef = NULL;\n\t    Tcl_Free(treePtr->startEnd);\n\t    treePtr->startEnd = NULL;\n\t}\n    }\n    if ((action & TEXT_ADD_REFS)\n\t    && (textPtr->start != NULL || textPtr->end != NULL)) {\n\tint count;\n\n\tif (textPtr->start != NULL) {\n\t    treePtr->startEndCount++;\n\t}\n\tif (textPtr->end != NULL) {\n\t    treePtr->startEndCount++;\n\t}\n\n\tcount = treePtr->startEndCount;\n\n\ttreePtr->startEnd = (TkTextLine **)Tcl_Realloc(treePtr->startEnd,\n\t\tsizeof(TkTextLine *) * count);\n\ttreePtr->startEndRef = (TkText **)Tcl_Realloc(treePtr->startEndRef,\n\t\tsizeof(TkText *) * count);\n\n\tif (textPtr->start != NULL) {\n\t    count--;\n\t    treePtr->startEnd[count] = textPtr->start;\n\t    treePtr->startEndRef[count] = textPtr;\n\t}\n\tif (textPtr->end != NULL) {\n\t    count--;\n\t    treePtr->startEnd[count] = textPtr->end;\n\t    treePtr->startEndRef[count] = textPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustPixelClient --\n *\n *\tUtility function used to update all data structures for the existence\n *\tof a new peer widget based on this B-tree, or for the modification of\n *\tthe start, end lines of an existing peer widget.\n *\n *\tImmediately _after_ calling this, treePtr->pixelReferences and\n *\ttreePtr->clients should be adjusted if needed (i.e. if this is a new\n *\tpeer).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll the storage for Nodes and TkTextLines in the tree may be adjusted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nAdjustPixelClient(\n    BTree *treePtr,\t\t/* Pointer to tree. */\n    int defaultHeight,\t\t/* Default pixel line height, which can be\n\t\t\t\t * zero. */\n    Node *nodePtr,\t\t/* Adjust from this node downwards. */\n    TkTextLine *start,\t\t/* First line for this pixel client. */\n    TkTextLine *end,\t\t/* Last line for this pixel client. */\n    int useReference,\t\t/* pixel reference for the client we are\n\t\t\t\t * adding or changing. */\n    int newPixelReferences,\t/* New number of pixel references to this\n\t\t\t\t * B-tree. */\n    int *counting)\t\t/* References an integer which is zero if\n\t\t\t\t * we're outside the relevant range for this\n\t\t\t\t * client, and 1 if we're inside. */\n{\n    int pixelCount = 0;\n\n    /*\n     * Traverse entire tree down from nodePtr, reallocating pixel structures\n     * for each Node and TkTextLine, adding room for the new peer's pixel\n     * information (1 extra int per Node, 2 extra ints per TkTextLine). Also\n     * copy the information from the last peer into the new space (so it\n     * contains something sensible).\n     */\n\n    if (nodePtr->level != 0) {\n\tNode *loopPtr = nodePtr->children.nodePtr;\n\n\twhile (loopPtr != NULL) {\n\t    pixelCount += AdjustPixelClient(treePtr, defaultHeight, loopPtr,\n\t\t    start, end, useReference, newPixelReferences, counting);\n\t    loopPtr = loopPtr->nextPtr;\n\t}\n    } else {\n\tTkTextLine *linePtr = nodePtr->children.linePtr;\n\n\twhile (linePtr != NULL) {\n\t    if (!*counting && (linePtr == start)) {\n\t\t*counting = 1;\n\t    }\n\t    if (*counting && (linePtr == end)) {\n\t\t*counting = 0;\n\t    }\n\t    if (newPixelReferences != treePtr->pixelReferences) {\n\t\tlinePtr->pixels = (int *)Tcl_Realloc(linePtr->pixels,\n\t\t\tsizeof(int) * 2 * newPixelReferences);\n\t    }\n\n\t    /*\n\t     * Notice that for the very last line, we are never counting and\n\t     * therefore this always has a height of 0 and an epoch of 1.\n\t     */\n\n\t    linePtr->pixels[2*useReference] = (*counting ? defaultHeight : 0);\n\t    linePtr->pixels[2*useReference+1] = (*counting ? 0 : 1);\n\t    pixelCount += linePtr->pixels[2*useReference];\n\n\t    linePtr = linePtr->nextPtr;\n\t}\n    }\n    if (newPixelReferences != treePtr->pixelReferences) {\n\tnodePtr->numPixels = (int *)Tcl_Realloc(nodePtr->numPixels,\n\t\tsizeof(int) * newPixelReferences);\n    }\n    nodePtr->numPixels[useReference] = pixelCount;\n    return pixelCount;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemovePixelClient --\n *\n *\tUtility function used to update all data structures for the removal of\n *\ta peer widget which used to be based on this B-tree.\n *\n *\tImmediately _after_ calling this, treePtr->clients should be\n *\tdecremented.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll the storage for Nodes and TkTextLines in the tree may be adjusted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemovePixelClient(\n    BTree *treePtr,\t\t/* Pointer to tree. */\n    Node *nodePtr,\t\t/* Adjust from this node downwards. */\n    int overwriteWithLast)\t/* Over-write this peer widget's information\n\t\t\t\t * with the last one. */\n{\n    /*\n     * Traverse entire tree down from nodePtr, reallocating pixel structures\n     * for each Node and TkTextLine, removing space allocated for one peer. If\n     * 'overwriteWithLast' is not -1, then copy the information which was in\n     * the last slot on top of one of the others (i.e. it's not the last one\n     * we're deleting).\n     */\n\n    if (overwriteWithLast != -1) {\n\tnodePtr->numPixels[overwriteWithLast] =\n\t\tnodePtr->numPixels[treePtr->pixelReferences-1];\n    }\n    if (treePtr->pixelReferences == 1) {\n\tTcl_Free(nodePtr->numPixels);\n\tnodePtr->numPixels = NULL;\n    } else {\n\tnodePtr->numPixels = (int *)Tcl_Realloc(nodePtr->numPixels,\n\t\tsizeof(int) * (treePtr->pixelReferences - 1));\n    }\n    if (nodePtr->level != 0) {\n\tnodePtr = nodePtr->children.nodePtr;\n\twhile (nodePtr != NULL) {\n\t    RemovePixelClient(treePtr, nodePtr, overwriteWithLast);\n\t    nodePtr = nodePtr->nextPtr;\n\t}\n    } else {\n\tTkTextLine *linePtr = nodePtr->children.linePtr;\n\twhile (linePtr != NULL) {\n\t    if (overwriteWithLast != -1) {\n\t\tlinePtr->pixels[2*overwriteWithLast] =\n\t\t\tlinePtr->pixels[2*(treePtr->pixelReferences-1)];\n\t\tlinePtr->pixels[1+2*overwriteWithLast] =\n\t\t\tlinePtr->pixels[1+2*(treePtr->pixelReferences-1)];\n\t    }\n\t    if (treePtr->pixelReferences == 1) {\n\t\tlinePtr->pixels = NULL;\n\t    } else {\n\t\tlinePtr->pixels = (int *)Tcl_Realloc(linePtr->pixels,\n\t\t\tsizeof(int) * 2 * (treePtr->pixelReferences-1));\n\t    }\n\t    linePtr = linePtr->nextPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyNode --\n *\n *\tThis is a recursive utility function used during the deletion of a\n *\tB-tree.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll the storage for nodePtr and its descendants is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDestroyNode(\n    Node *nodePtr)\t/* Destroy from this node downwards. */\n{\n    if (nodePtr->level == 0) {\n\tTkTextLine *linePtr;\n\tTkTextSegment *segPtr;\n\n\twhile (nodePtr->children.linePtr != NULL) {\n\t    linePtr = nodePtr->children.linePtr;\n\t    nodePtr->children.linePtr = linePtr->nextPtr;\n\t    while (linePtr->segPtr != NULL) {\n\t\tsegPtr = linePtr->segPtr;\n\t\tlinePtr->segPtr = segPtr->nextPtr;\n\t\tsegPtr->typePtr->deleteProc(segPtr, linePtr, 1);\n\t    }\n\t    Tcl_Free(linePtr->pixels);\n\t    Tcl_Free(linePtr);\n\t}\n    } else {\n\tNode *childPtr;\n\n\twhile (nodePtr->children.nodePtr != NULL) {\n\t    childPtr = nodePtr->children.nodePtr;\n\t    nodePtr->children.nodePtr = childPtr->nextPtr;\n\t    DestroyNode(childPtr);\n\t}\n    }\n    DeleteSummaries(nodePtr->summaryPtr);\n    Tcl_Free(nodePtr->numPixels);\n    Tcl_Free(nodePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteSummaries --\n *\n *\tFree up all of the memory in a list of tag summaries associated with a\n *\tnode.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tStorage is released.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteSummaries(\n    Summary *summaryPtr)\n\t\t\t\t/* First in list of node's tag summaries. */\n{\n    Summary *nextPtr;\n\n    while (summaryPtr != NULL) {\n\tnextPtr = summaryPtr->nextPtr;\n\tTcl_Free(summaryPtr);\n\tsummaryPtr = nextPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeAdjustPixelHeight --\n *\n *\tAdjust the pixel height of a given logical line to the specified\n *\tvalue.\n *\n * Results:\n *\tTotal number of valid pixels currently known in the tree.\n *\n * Side effects:\n *\tUpdates overall data structures so pixel height count is consistent.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreeAdjustPixelHeight(\n    const TkText *textPtr,\t/* Client of the B-tree. */\n    TkTextLine *linePtr,\n\t\t\t\t/* The logical line to update. */\n    int newPixelHeight,\t\t/* The line's known height in pixels. */\n    int mergedLogicalLines)\t/* The number of extra logical lines which\n\t\t\t\t * have been merged with this one (due to\n\t\t\t\t * elided eols). They will have their pixel\n\t\t\t\t * height set to zero, and the total pixel\n\t\t\t\t * height associated with the given\n\t\t\t\t * linePtr. */\n{\n    Node *nodePtr;\n    int changeToPixelCount;\t/* Counts change to total number of pixels in\n\t\t\t\t * file. */\n    int pixelReference = textPtr->pixelReference;\n\n    changeToPixelCount = newPixelHeight - linePtr->pixels[2 * pixelReference];\n\n    /*\n     * Increment the pixel counts in all the parent nodes of the current line,\n     * then rebalance the tree if necessary.\n     */\n\n    nodePtr = linePtr->parentPtr;\n    nodePtr->numPixels[pixelReference] += changeToPixelCount;\n\n    while (nodePtr->parentPtr != NULL) {\n\tnodePtr = nodePtr->parentPtr;\n\tnodePtr->numPixels[pixelReference] += changeToPixelCount;\n    }\n\n    linePtr->pixels[2 * pixelReference] = newPixelHeight;\n\n    /*\n     * Any merged logical lines must have their height set to zero.\n     */\n\n    while (mergedLogicalLines-- > 0) {\n\tlinePtr = TkBTreeNextLine(textPtr, linePtr);\n\tTkBTreeAdjustPixelHeight(textPtr, linePtr, 0, 0);\n    }\n\n    /*\n     * Return total number of pixels in the tree.\n     */\n\n    return nodePtr->numPixels[pixelReference];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeInsertChars --\n *\n *\tInsert characters at a given position in a B-tree.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCharacters are added to the B-tree at the given position. If the\n *\tstring contains newlines, new lines will be added, which could cause\n *\tthe structure of the B-tree to change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeInsertChars(\n    TkTextBTree tree,\t\t/* Tree to insert into. */\n    TkTextIndex *indexPtr,\n\t\t\t\t/* Indicates where to insert text. When the\n\t\t\t\t * function returns, this index is no longer\n\t\t\t\t * valid because of changes to the segment\n\t\t\t\t * structure. */\n    const char *string)\t\t/* Pointer to bytes to insert (may contain\n\t\t\t\t * newlines, must be null-terminated). */\n{\n    Node *nodePtr;\n    TkTextSegment *prevPtr;\n\t\t\t\t/* The segment just before the first new\n\t\t\t\t * segment (NULL means new segment is at\n\t\t\t\t * beginning of line). */\n    TkTextSegment *curPtr;\t/* Current segment; new characters are\n\t\t\t\t * inserted just after this one. NULL means\n\t\t\t\t * insert at beginning of line. */\n    TkTextLine *linePtr;\t/* Current line (new segments are added to\n\t\t\t\t * this line). */\n    TkTextSegment *segPtr;\n    TkTextLine *newLinePtr;\n    size_t chunkSize;\t\t/* # characters in current chunk. */\n    const char *eol;\t/* Pointer to character just after last one in\n\t\t\t\t * current chunk. */\n    Tcl_Size changeToLineCount;\t/* Counts change to total number of lines in\n\t\t\t\t * file. */\n    int *changeToPixelCount;\t/* Counts change to total number of pixels in\n\t\t\t\t * file. */\n    int ref;\n    int pixels[PIXEL_CLIENTS];\n\n    BTree *treePtr = (BTree *) tree;\n    treePtr->stateEpoch++;\n    prevPtr = SplitSeg(indexPtr);\n    linePtr = indexPtr->linePtr;\n    curPtr = prevPtr;\n\n    /*\n     * Chop the string up into lines and create a new segment for each line,\n     * plus a new line for the leftovers from the previous line.\n     */\n\n    changeToLineCount = 0;\n    if (treePtr->pixelReferences > PIXEL_CLIENTS) {\n\tchangeToPixelCount = (int *)Tcl_Alloc(sizeof(int) * treePtr->pixelReferences);\n    } else {\n\tchangeToPixelCount = pixels;\n    }\n    for (ref = 0; ref < treePtr->pixelReferences; ref++) {\n\tchangeToPixelCount[ref] = 0;\n    }\n\n    while (*string != 0) {\n\tfor (eol = string; *eol != 0; eol++) {\n\t    if (*eol == '\\n') {\n\t\teol++;\n\t\tbreak;\n\t    }\n\t}\n\tchunkSize = eol-string;\n\tsegPtr = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(chunkSize));\n\tsegPtr->typePtr = &tkTextCharType;\n\tif (curPtr == NULL) {\n\t    segPtr->nextPtr = linePtr->segPtr;\n\t    linePtr->segPtr = segPtr;\n\t} else {\n\t    segPtr->nextPtr = curPtr->nextPtr;\n\t    curPtr->nextPtr = segPtr;\n\t}\n\tsegPtr->size = chunkSize;\n\tmemcpy(segPtr->body.chars, string, chunkSize);\n\tsegPtr->body.chars[chunkSize] = 0;\n\n\tif (eol[-1] != '\\n') {\n\t    break;\n\t}\n\n\t/*\n\t * The chunk ended with a newline, so create a new TkTextLine and move\n\t * the remainder of the old line to it.\n\t */\n\n\tnewLinePtr = (TkTextLine *)Tcl_Alloc(sizeof(TkTextLine));\n\tnewLinePtr->pixels = (int *)\n\t\tTcl_Alloc(sizeof(int) * 2 * treePtr->pixelReferences);\n\n\tnewLinePtr->parentPtr = linePtr->parentPtr;\n\tnewLinePtr->nextPtr = linePtr->nextPtr;\n\tlinePtr->nextPtr = newLinePtr;\n\tnewLinePtr->segPtr = segPtr->nextPtr;\n\n\t/*\n\t * Set up a starting default height, which will be re-adjusted later.\n\t * We need to do this for each referenced widget.\n\t */\n\n\tfor (ref = 0; ref < treePtr->pixelReferences; ref++) {\n\t    newLinePtr->pixels[2 * ref] = linePtr->pixels[2 * ref];\n\t    newLinePtr->pixels[2 * ref + 1] = 0;\n\t    changeToPixelCount[ref] += newLinePtr->pixels[2 * ref];\n\t}\n\n\tsegPtr->nextPtr = NULL;\n\tlinePtr = newLinePtr;\n\tcurPtr = NULL;\n\tchangeToLineCount++;\n\n\tstring = eol;\n    }\n\n    /*\n     * I don't believe it's possible for either of the two lines passed to\n     * this function to be the last line of text, but the function is robust\n     * to that case anyway. (We must never re-calculate the line height of\n     * the last line).\n     */\n\n    TkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL,\n\t    indexPtr->linePtr, changeToLineCount, TK_TEXT_INVALIDATE_INSERT);\n\n    /*\n     * Cleanup the starting line for the insertion, plus the ending line if\n     * it's different.\n     */\n\n    CleanupLine(indexPtr->linePtr);\n    if (linePtr != indexPtr->linePtr) {\n\tCleanupLine(linePtr);\n    }\n\n    /*\n     * Increment the line and pixel counts in all the parent nodes of the\n     * insertion point, then rebalance the tree if necessary.\n     */\n\n    for (nodePtr = linePtr->parentPtr ; nodePtr != NULL;\n\t    nodePtr = nodePtr->parentPtr) {\n\tnodePtr->numLines += changeToLineCount;\n\tfor (ref = 0; ref < treePtr->pixelReferences; ref++) {\n\t    nodePtr->numPixels[ref] += changeToPixelCount[ref];\n\t}\n    }\n    if (treePtr->pixelReferences > PIXEL_CLIENTS) {\n\tTcl_Free(changeToPixelCount);\n    }\n\n    nodePtr = linePtr->parentPtr;\n    nodePtr->numChildren += changeToLineCount;\n    if (nodePtr->numChildren > MAX_CHILDREN) {\n\tRebalance(treePtr, nodePtr);\n    }\n\n    if (tkBTreeDebug) {\n\tTkBTreeCheck(indexPtr->tree);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SplitSeg --\n *\n *\tThis function is called before adding or deleting segments. It does\n *\tthree things: (a) it finds the segment containing indexPtr; (b) if\n *\tthere are several such segments (because some segments have zero\n *\tlength) then it picks the first segment that does not have left\n *\tgravity; (c) if the index refers to the middle of a segment then it\n *\tsplits the segment so that the index now refers to the beginning of a\n *\tsegment.\n *\n * Results:\n *\tThe return value is a pointer to the segment just before the segment\n *\tcorresponding to indexPtr (as described above). If the segment\n *\tcorresponding to indexPtr is the first in its line then the return\n *\tvalue is NULL.\n *\n * Side effects:\n *\tThe segment referred to by indexPtr is split unless indexPtr refers to\n *\tits first character.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nSplitSeg(\n    TkTextIndex *indexPtr)\t/* Index identifying position at which to\n\t\t\t\t * split a segment. */\n{\n    TkTextSegment *prevPtr, *segPtr;\n    TkTextLine *linePtr;\n    Tcl_Size count = indexPtr->byteIndex;\n\n    linePtr = indexPtr->linePtr;\n    prevPtr = NULL;\n    segPtr = linePtr->segPtr;\n\n    while (segPtr != NULL) {\n\tif (segPtr->size > count) {\n\t    if (count == 0) {\n\t\treturn prevPtr;\n\t    }\n\t    segPtr = segPtr->typePtr->splitProc(segPtr, count);\n\t    if (prevPtr == NULL) {\n\t\tindexPtr->linePtr->segPtr = segPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = segPtr;\n\t    }\n\t    return segPtr;\n\t} else if ((segPtr->size == 0) && (count == 0)\n\t\t&& !segPtr->typePtr->leftGravity) {\n\t    return prevPtr;\n\t}\n\n\tcount -= segPtr->size;\n\tprevPtr = segPtr;\n\tsegPtr = segPtr->nextPtr;\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Two logical lines merged into one display line through eliding\n\t     * of a newline.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(NULL, linePtr);\n\t    if (linePtr == NULL) {\n\t\t/*\n\t\t * Reached end of the text.\n\t\t */\n\t    } else {\n\t\tsegPtr = linePtr->segPtr;\n\t    }\n\t}\n    }\n    Tcl_Panic(\"SplitSeg reached end of line!\");\n    return NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CleanupLine --\n *\n *\tThis function is called after modifications have been made to a line.\n *\tIt scans over all of the segments in the line, giving each a chance to\n *\tclean itself up, e.g. by merging with the following segments, updating\n *\tinternal information, etc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what the segment-specific cleanup functions do.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCleanupLine(\n    TkTextLine *linePtr)\t/* Line to be cleaned up. */\n{\n    TkTextSegment *segPtr, **prevPtrPtr;\n    int anyChanges;\n\n    /*\n     * Make a pass over all of the segments in the line, giving each a chance\n     * to clean itself up. This could potentially change the structure of the\n     * line, e.g. by merging two segments together or having two segments\n     * cancel themselves; if so, then repeat the whole process again, since\n     * the first structure change might make other structure changes possible.\n     * Repeat until eventually there are no changes.\n     */\n\n    while (1) {\n\tanyChanges = 0;\n\tfor (prevPtrPtr = &linePtr->segPtr, segPtr = *prevPtrPtr;\n\t\tsegPtr != NULL;\n\t\tprevPtrPtr = &(*prevPtrPtr)->nextPtr, segPtr = *prevPtrPtr) {\n\t    if (segPtr->typePtr->cleanupProc != NULL) {\n\t\t*prevPtrPtr = segPtr->typePtr->cleanupProc(segPtr, linePtr);\n\t\tif (segPtr != *prevPtrPtr) {\n\t\t    anyChanges = 1;\n\t\t}\n\t    }\n\t}\n\tif (!anyChanges) {\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeDeleteIndexRange --\n *\n *\tDelete a range of characters from a B-tree. The caller must make sure\n *\tthat the final newline of the B-tree is never deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation is deleted from the B-tree. This can cause the internal\n *\tstructure of the B-tree to change. Note: because of changes to the\n *\tB-tree structure, the indices pointed to by index1Ptr and index2Ptr\n *\tshould not be used after this function returns.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeDeleteIndexRange(\n    TkTextBTree tree,\t\t/* Tree to delete from. */\n    TkTextIndex *index1Ptr,\n\t\t\t\t/* Indicates first character that is to be\n\t\t\t\t * deleted. */\n    TkTextIndex *index2Ptr)\n\t\t\t\t/* Indicates character just after the last one\n\t\t\t\t * that is to be deleted. */\n{\n    TkTextSegment *prevPtr;\t/* The segment just before the start of the\n\t\t\t\t * deletion range. */\n    TkTextSegment *lastPtr;\t/* The segment just after the end of the\n\t\t\t\t * deletion range. */\n    TkTextSegment *segPtr, *nextPtr;\n    TkTextLine *curLinePtr;\n    Node *curNodePtr, *nodePtr;\n    int changeToLineCount = 0;\n    int ref;\n    BTree *treePtr = (BTree *) tree;\n\n    treePtr->stateEpoch++;\n\n    /*\n     * Tricky point: split at index2Ptr first; otherwise the split at\n     * index2Ptr may invalidate segPtr and/or prevPtr.\n     */\n\n    lastPtr = SplitSeg(index2Ptr);\n    if (lastPtr != NULL) {\n\tlastPtr = lastPtr->nextPtr;\n    } else {\n\tlastPtr = index2Ptr->linePtr->segPtr;\n    }\n    prevPtr = SplitSeg(index1Ptr);\n    if (prevPtr != NULL) {\n\tsegPtr = prevPtr->nextPtr;\n\tprevPtr->nextPtr = lastPtr;\n    } else {\n\tsegPtr = index1Ptr->linePtr->segPtr;\n\tindex1Ptr->linePtr->segPtr = lastPtr;\n    }\n\n    /*\n     * Delete all of the segments between prevPtr and lastPtr.\n     */\n\n    curLinePtr = index1Ptr->linePtr;\n\n    curNodePtr = curLinePtr->parentPtr;\n    while (segPtr != lastPtr) {\n\tif (segPtr == NULL) {\n\t    TkTextLine *nextLinePtr;\n\n\t    /*\n\t     * We just ran off the end of a line. First find the next line,\n\t     * then go back to the old line and delete it (unless it's the\n\t     * starting line for the range).\n\t     */\n\n\t    nextLinePtr = TkBTreeNextLine(NULL, curLinePtr);\n\t    if (curLinePtr != index1Ptr->linePtr) {\n\t\tif (curNodePtr == index1Ptr->linePtr->parentPtr) {\n\t\t    index1Ptr->linePtr->nextPtr = curLinePtr->nextPtr;\n\t\t} else {\n\t\t    curNodePtr->children.linePtr = curLinePtr->nextPtr;\n\t\t}\n\t\tfor (nodePtr = curNodePtr; nodePtr != NULL;\n\t\t\tnodePtr = nodePtr->parentPtr) {\n\t\t    nodePtr->numLines--;\n\t\t    for (ref = 0; ref < treePtr->pixelReferences; ref++) {\n\t\t\tnodePtr->numPixels[ref] -= curLinePtr->pixels[2*ref];\n\t\t    }\n\t\t}\n\t\tchangeToLineCount++;\n\t\tCLANG_ASSERT(curNodePtr);\n\t\tcurNodePtr->numChildren--;\n\n\t\t/*\n\t\t * Check if we need to adjust any partial clients.\n\t\t */\n\n\t\tif (treePtr->startEnd != NULL) {\n\t\t    int checkCount = 0;\n\n\t\t    while (checkCount < treePtr->startEndCount) {\n\t\t\tif (treePtr->startEnd[checkCount] == curLinePtr) {\n\t\t\t    TkText *peer = treePtr->startEndRef[checkCount];\n\n\t\t\t    /*\n\t\t\t     * We're deleting a line which is the start or end\n\t\t\t     * of a current client. This means we need to\n\t\t\t     * adjust that client.\n\t\t\t     */\n\n\t\t\t    treePtr->startEnd[checkCount] = nextLinePtr;\n\t\t\t    if (peer->start == curLinePtr) {\n\t\t\t\tpeer->start = nextLinePtr;\n\t\t\t    }\n\t\t\t    if (peer->end == curLinePtr) {\n\t\t\t\tpeer->end = nextLinePtr;\n\t\t\t    }\n\t\t\t}\n\t\t\tcheckCount++;\n\t\t    }\n\t\t}\n\t\tTcl_Free(curLinePtr->pixels);\n\t\tTcl_Free(curLinePtr);\n\t    }\n\t    curLinePtr = nextLinePtr;\n\t    segPtr = curLinePtr->segPtr;\n\n\t    /*\n\t     * If the node is empty then delete it and its parents recursively\n\t     * upwards until a non-empty node is found.\n\t     */\n\n\t    while (curNodePtr->numChildren == 0) {\n\t\tNode *parentPtr;\n\n\t\tparentPtr = curNodePtr->parentPtr;\n\t\tif (parentPtr->children.nodePtr == curNodePtr) {\n\t\t    parentPtr->children.nodePtr = curNodePtr->nextPtr;\n\t\t} else {\n\t\t    Node *prevNodePtr = parentPtr->children.nodePtr;\n\t\t    while (prevNodePtr->nextPtr != curNodePtr) {\n\t\t\tprevNodePtr = prevNodePtr->nextPtr;\n\t\t    }\n\t\t    prevNodePtr->nextPtr = curNodePtr->nextPtr;\n\t\t}\n\t\tparentPtr->numChildren--;\n\t\tDeleteSummaries(curNodePtr->summaryPtr);\n\t\tTcl_Free(curNodePtr->numPixels);\n\t\tTcl_Free(curNodePtr);\n\t\tcurNodePtr = parentPtr;\n\t    }\n\t    curNodePtr = curLinePtr->parentPtr;\n\t    continue;\n\t}\n\n\tnextPtr = segPtr->nextPtr;\n\tif (segPtr->typePtr->deleteProc(segPtr, curLinePtr, 0) != 0) {\n\t    /*\n\t     * This segment refuses to die. Move it to prevPtr and advance\n\t     * prevPtr if the segment has left gravity.\n\t     */\n\n\t    if (prevPtr == NULL) {\n\t\tsegPtr->nextPtr = index1Ptr->linePtr->segPtr;\n\t\tindex1Ptr->linePtr->segPtr = segPtr;\n\t    } else {\n\t\tsegPtr->nextPtr = prevPtr->nextPtr;\n\t\tprevPtr->nextPtr = segPtr;\n\t    }\n\t    if (segPtr->typePtr->leftGravity) {\n\t\tprevPtr = segPtr;\n\t    }\n\t}\n\tsegPtr = nextPtr;\n    }\n\n    /*\n     * If the beginning and end of the deletion range are in different lines,\n     * join the two lines together and discard the ending line.\n     */\n\n    if (index1Ptr->linePtr != index2Ptr->linePtr) {\n\tTkTextLine *prevLinePtr;\n\n\tfor (segPtr = lastPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if (segPtr->typePtr->lineChangeProc != NULL) {\n\t\tsegPtr->typePtr->lineChangeProc(segPtr, index2Ptr->linePtr);\n\t    }\n\t}\n\tcurNodePtr = index2Ptr->linePtr->parentPtr;\n\tfor (nodePtr = curNodePtr; nodePtr != NULL;\n\t\tnodePtr = nodePtr->parentPtr) {\n\t    nodePtr->numLines--;\n\t    for (ref = 0; ref < treePtr->pixelReferences; ref++) {\n\t\tnodePtr->numPixels[ref] -= index2Ptr->linePtr->pixels[2*ref];\n\t    }\n\t}\n\tchangeToLineCount++;\n\tcurNodePtr->numChildren--;\n\tprevLinePtr = curNodePtr->children.linePtr;\n\tif (prevLinePtr == index2Ptr->linePtr) {\n\t    curNodePtr->children.linePtr = index2Ptr->linePtr->nextPtr;\n\t} else {\n\t    while (prevLinePtr->nextPtr != index2Ptr->linePtr) {\n\t\tprevLinePtr = prevLinePtr->nextPtr;\n\t    }\n\t    prevLinePtr->nextPtr = index2Ptr->linePtr->nextPtr;\n\t}\n\n\t/*\n\t * Check if we need to adjust any partial clients. In this case if\n\t * we're deleting the line, we actually move back to the previous line\n\t * for our (start,end) storage. We do this because we still want the\n\t * portion of the second line that still exists to be in the start,end\n\t * range.\n\t */\n\n\tif (treePtr->startEnd != NULL) {\n\t    int checkCount = 0;\n\n\t    while (checkCount < treePtr->startEndCount &&\n\t\t    treePtr->startEnd[checkCount] != NULL) {\n\t\tif (treePtr->startEnd[checkCount] == index2Ptr->linePtr) {\n\t\t    TkText *peer = treePtr->startEndRef[checkCount];\n\n\t\t    /*\n\t\t     * We're deleting a line which is the start or end of a\n\t\t     * current client. This means we need to adjust that\n\t\t     * client.\n\t\t     */\n\n\t\t    treePtr->startEnd[checkCount] = index1Ptr->linePtr;\n\t\t    if (peer->start == index2Ptr->linePtr) {\n\t\t\tpeer->start = index1Ptr->linePtr;\n\t\t    }\n\t\t    if (peer->end == index2Ptr->linePtr) {\n\t\t\tpeer->end = index1Ptr->linePtr;\n\t\t    }\n\t\t}\n\t\tcheckCount++;\n\t    }\n\t}\n\tTcl_Free(index2Ptr->linePtr->pixels);\n\tTcl_Free(index2Ptr->linePtr);\n\n\tRebalance((BTree *) index2Ptr->tree, curNodePtr);\n    }\n\n    /*\n     * Cleanup the segments in the new line.\n     */\n\n    CleanupLine(index1Ptr->linePtr);\n\n    /*\n     * This line now needs to have its height recalculated. For safety, ensure\n     * we don't call this function with the last artificial line of text. I\n     * _believe_ that it isn't possible to get this far with the last line,\n     * but it is good to be safe.\n     */\n\n    if (TkBTreeNextLine(NULL, index1Ptr->linePtr) != NULL) {\n\tTkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL,\n\t\tindex1Ptr->linePtr, changeToLineCount,\n\t\tTK_TEXT_INVALIDATE_DELETE);\n    }\n\n    /*\n     * Lastly, rebalance the first node of the range.\n     */\n\n    Rebalance((BTree *) index1Ptr->tree, index1Ptr->linePtr->parentPtr);\n    if (tkBTreeDebug) {\n\tTkBTreeCheck(index1Ptr->tree);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeFindLine --\n *\n *\tFind a particular line in a B-tree based on its line number.\n *\n * Results:\n *\tThe return value is a pointer to the line structure for the line whose\n *\tindex is \"line\", or NULL if no such line exists.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextLine *\nTkBTreeFindLine(\n    TkTextBTree tree,\t\t/* B-tree in which to find line. */\n    const TkText *textPtr,\t/* Relative to this client of the B-tree. */\n    Tcl_Size line)\t\t\t/* Index of desired line. */\n{\n    BTree *treePtr = (BTree *) tree;\n    Node *nodePtr;\n    TkTextLine *linePtr;\n\n    if (treePtr == NULL) {\n\ttreePtr = (BTree *) textPtr->sharedTextPtr->tree;\n    }\n\n    nodePtr = treePtr->rootPtr;\n    if ((line < 0) || (line >= nodePtr->numLines)) {\n\treturn NULL;\n    }\n\n    /*\n     * Check for any start/end offset for this text widget.\n     */\n\n    if (textPtr != NULL) {\n\tif (textPtr->start != NULL) {\n\t    line += TkBTreeLinesTo(NULL, textPtr->start);\n\t    if (line >= nodePtr->numLines) {\n\t\treturn NULL;\n\t    }\n\t}\n\tif (textPtr->end != NULL) {\n\t    if (line > TkBTreeLinesTo(NULL, textPtr->end)) {\n\t\treturn NULL;\n\t    }\n\t}\n    }\n\n    /*\n     * Work down through levels of the tree until a node is found at level 0.\n     */\n\n    while (nodePtr->level != 0) {\n\tfor (nodePtr = nodePtr->children.nodePtr;\n\t\tnodePtr->numLines <= line;\n\t\tnodePtr = nodePtr->nextPtr) {\n\t    if (nodePtr == NULL) {\n\t\tTcl_Panic(\"TkBTreeFindLine ran out of nodes\");\n\t    }\n\t    line -= nodePtr->numLines;\n\t}\n    }\n\n    /*\n     * Work through the lines attached to the level-0 node.\n     */\n\n    for (linePtr = nodePtr->children.linePtr; line > 0;\n\t    linePtr = linePtr->nextPtr) {\n\tif (linePtr == NULL) {\n\t    Tcl_Panic(\"TkBTreeFindLine ran out of lines\");\n\t}\n\tline -= 1;\n    }\n    return linePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeFindPixelLine --\n *\n *\tFind a particular line in a B-tree based on its pixel count.\n *\n * Results:\n *\tThe return value is a pointer to the line structure for the line which\n *\tcontains the pixel \"pixels\", or NULL if no such line exists. If the\n *\tfirst line is of height 20, then pixels 0-19 will return it, and\n *\tpixels = 20 will return the next line.\n *\n *\tIf pixelOffset is non-NULL, it is set to the amount by which 'pixels'\n *\texceeds the first pixel located on the returned line. This should\n *\talways be non-negative.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextLine *\nTkBTreeFindPixelLine(\n    TkTextBTree tree,\t\t/* B-tree to use. */\n    const TkText *textPtr,\t/* Relative to this client of the B-tree. */\n    int pixels,\t\t\t/* Pixel index of desired line. */\n    int *pixelOffset)\t\t/* Used to return offset. */\n{\n    BTree *treePtr = (BTree *) tree;\n    Node *nodePtr;\n    TkTextLine *linePtr;\n    int pixelReference = textPtr->pixelReference;\n\n    nodePtr = treePtr->rootPtr;\n\n    if ((pixels < 0) || (pixels > nodePtr->numPixels[pixelReference])) {\n\treturn NULL;\n    }\n\n    if (nodePtr->numPixels[pixelReference] == 0) {\n\tTcl_Panic(\"TkBTreeFindPixelLine called with empty window\");\n    }\n\n    /*\n     * Work down through levels of the tree until a node is found at level 0.\n     */\n\n    while (nodePtr->level != 0) {\n\tfor (nodePtr = nodePtr->children.nodePtr;\n\t\tnodePtr->numPixels[pixelReference] <= pixels;\n\t\tnodePtr = nodePtr->nextPtr) {\n\t    if (nodePtr == NULL) {\n\t\tTcl_Panic(\"TkBTreeFindPixelLine ran out of nodes\");\n\t    }\n\t    pixels -= nodePtr->numPixels[pixelReference];\n\t}\n    }\n\n    /*\n     * Work through the lines attached to the level-0 node.\n     */\n\n    for (linePtr = nodePtr->children.linePtr;\n\t    linePtr->pixels[2 * pixelReference] < pixels;\n\t    linePtr = linePtr->nextPtr) {\n\tif (linePtr == NULL) {\n\t    Tcl_Panic(\"TkBTreeFindPixelLine ran out of lines\");\n\t}\n\tpixels -= linePtr->pixels[2 * pixelReference];\n    }\n\n    /*\n     * Check for any start/end offset for this text widget.\n     */\n\n    if (textPtr->start != NULL) {\n\tTcl_Size lineBoundary = TkBTreeLinesTo(NULL, textPtr->start);\n\n\tif (TkBTreeLinesTo(NULL, linePtr) < lineBoundary) {\n\t    linePtr = TkBTreeFindLine(tree, NULL, lineBoundary);\n\t}\n    }\n    if (textPtr->end != NULL) {\n\tTcl_Size lineBoundary = TkBTreeLinesTo(NULL, textPtr->end);\n\n\tif (TkBTreeLinesTo(NULL, linePtr) > lineBoundary) {\n\t    linePtr = TkBTreeFindLine(tree, NULL, lineBoundary);\n\t}\n    }\n\n    if (pixelOffset != NULL && linePtr != NULL) {\n\t*pixelOffset = pixels;\n    }\n    return linePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeNextLine --\n *\n *\tGiven an existing line in a B-tree, this function locates the next\n *\tline in the B-tree. This function is used for scanning through the\n *\tB-tree.\n *\n * Results:\n *\tThe return value is a pointer to the line that immediately follows\n *\tlinePtr, or NULL if there is no such line.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextLine *\nTkBTreeNextLine(\n    const TkText *textPtr,\t/* Next line in the context of this client. */\n    TkTextLine *linePtr)\n\t\t\t\t/* Pointer to existing line in B-tree. */\n{\n    Node *nodePtr;\n\n    if (linePtr->nextPtr != NULL) {\n\tif (textPtr != NULL && (linePtr == textPtr->end)) {\n\t    return NULL;\n\t} else {\n\t    return linePtr->nextPtr;\n\t}\n    }\n\n    /*\n     * This was the last line associated with the particular parent node.\n     * Search up the tree for the next node, then search down from that node\n     * to find the first line.\n     */\n\n    for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) {\n\tif (nodePtr->nextPtr != NULL) {\n\t    nodePtr = nodePtr->nextPtr;\n\t    break;\n\t}\n\tif (nodePtr->parentPtr == NULL) {\n\t    return NULL;\n\t}\n    }\n    while (nodePtr->level > 0) {\n\tnodePtr = nodePtr->children.nodePtr;\n    }\n    return nodePtr->children.linePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreePreviousLine --\n *\n *\tGiven an existing line in a B-tree, this function locates the previous\n *\tline in the B-tree. This function is used for scanning through the\n *\tB-tree in the reverse direction.\n *\n * Results:\n *\tThe return value is a pointer to the line that immediately preceeds\n *\tlinePtr, or NULL if there is no such line.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextLine *\nTkBTreePreviousLine(\n    TkText *textPtr,\t\t/* Relative to this client of the B-tree. */\n    TkTextLine *linePtr)\n\t\t\t\t/* Pointer to existing line in B-tree. */\n{\n    Node *nodePtr;\n    Node *node2Ptr;\n    TkTextLine *prevPtr;\n\n    if (textPtr != NULL && textPtr->start == linePtr) {\n\treturn NULL;\n    }\n\n    /*\n     * Find the line under this node just before the starting line.\n     */\n\n    prevPtr = linePtr->parentPtr->children.linePtr;   /* First line at leaf. */\n    while (prevPtr != linePtr) {\n\tif (prevPtr->nextPtr == linePtr) {\n\t    return prevPtr;\n\t}\n\tprevPtr = prevPtr->nextPtr;\n\tif (prevPtr == NULL) {\n\t    Tcl_Panic(\"TkBTreePreviousLine ran out of lines\");\n\t}\n    }\n\n    /*\n     * This was the first line associated with the particular parent node.\n     * Search up the tree for the previous node, then search down from that\n     * node to find its last line.\n     */\n\n    for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) {\n\tif (nodePtr == NULL || nodePtr->parentPtr == NULL) {\n\t    return NULL;\n\t}\n\tif (nodePtr != nodePtr->parentPtr->children.nodePtr) {\n\t    break;\n\t}\n    }\n    for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ;\n\t    node2Ptr = node2Ptr->children.nodePtr) {\n\twhile (node2Ptr->nextPtr != nodePtr) {\n\t    node2Ptr = node2Ptr->nextPtr;\n\t}\n\tif (node2Ptr->level == 0) {\n\t    break;\n\t}\n\tnodePtr = NULL;\n    }\n    for (prevPtr = node2Ptr->children.linePtr ; ; prevPtr = prevPtr->nextPtr) {\n\tif (prevPtr->nextPtr == NULL) {\n\t    return prevPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreePixelsTo --\n *\n *\tGiven a pointer to a line in a B-tree, return the numerical pixel\n *\tindex of the top of that line (i.e. the result does not include the\n *\theight of the given line).\n *\n *\tSince the last line of text (the artificial one) has zero height by\n *\tdefinition, calling this with the last line will return the total\n *\tnumber of pixels in the widget.\n *\n * Results:\n *\tThe result is the pixel height of the top of the given line.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreePixelsTo(\n    const TkText *textPtr,\t/* Relative to this client of the B-tree. */\n    TkTextLine *linePtr)\t/* Pointer to existing line in B-tree. */\n{\n    TkTextLine *linePtr2;\n    Node *nodePtr, *parentPtr;\n    int index;\n    int pixelReference = textPtr->pixelReference;\n\n    /*\n     * First count how many pixels precede this line in its level-0 node.\n     */\n\n    nodePtr = linePtr->parentPtr;\n    index = 0;\n    for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr;\n\t    linePtr2 = linePtr2->nextPtr) {\n\tif (linePtr2 == NULL) {\n\t    Tcl_Panic(\"TkBTreePixelsTo couldn't find line\");\n\t}\n\tindex += linePtr2->pixels[2 * pixelReference];\n    }\n\n    /*\n     * Now work up through the levels of the tree one at a time, counting how\n     * many pixels are in nodes preceding the current node.\n     */\n\n    for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL;\n\t    nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) {\n\tNode *nodePtr2;\n\n\tfor (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr;\n\t\tnodePtr2 = nodePtr2->nextPtr) {\n\t    if (nodePtr2 == NULL) {\n\t\tTcl_Panic(\"TkBTreePixelsTo couldn't find node\");\n\t    }\n\t    index += nodePtr2->numPixels[pixelReference];\n\t}\n    }\n    return index;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeLinesTo --\n *\n *\tGiven a pointer to a line in a B-tree, return the numerical index of\n *\tthat line.\n *\n * Results:\n *\tThe result is the index of linePtr within the tree, where 0\n *\tcorresponds to the first line in the tree.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkBTreeLinesTo(\n    const TkText *textPtr,\t/* Relative to this client of the B-tree. */\n    TkTextLine *linePtr)\t/* Pointer to existing line in B-tree. */\n{\n    TkTextLine *linePtr2;\n    Node *nodePtr, *parentPtr, *nodePtr2;\n    Tcl_Size index;\n\n    /*\n     * First count how many lines precede this one in its level-0 node.\n     */\n\n    nodePtr = linePtr->parentPtr;\n    index = 0;\n    for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr;\n\t    linePtr2 = linePtr2->nextPtr) {\n\tif (linePtr2 == NULL) {\n\t    Tcl_Panic(\"TkBTreeLinesTo couldn't find line\");\n\t}\n\tindex += 1;\n    }\n\n    /*\n     * Now work up through the levels of the tree one at a time, counting how\n     * many lines are in nodes preceding the current node.\n     */\n\n    for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL;\n\t    nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) {\n\tfor (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr;\n\t\tnodePtr2 = nodePtr2->nextPtr) {\n\t    if (nodePtr2 == NULL) {\n\t\tTcl_Panic(\"TkBTreeLinesTo couldn't find node\");\n\t    }\n\t    index += nodePtr2->numLines;\n\t}\n    }\n    if (textPtr != NULL) {\n\t/*\n\t * The index to return must be relative to textPtr, not to the entire\n\t * tree. Take care to never return a negative index when linePtr\n\t * denotes a line before -startline, or an index larger than the\n\t * number of lines in textPtr when linePtr is a line past -endline.\n\t */\n\n\tTcl_Size indexStart, indexEnd;\n\n\tif (textPtr->start != NULL) {\n\t    indexStart = TkBTreeLinesTo(NULL, textPtr->start);\n\t} else {\n\t    indexStart = 0;\n\t}\n\tif (textPtr->end != NULL) {\n\t    indexEnd = TkBTreeLinesTo(NULL, textPtr->end);\n\t} else {\n\t    indexEnd = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL);\n\t}\n\tif (index < indexStart) {\n\t    index = 0;\n\t} else if (index > indexEnd) {\n\t    index = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n\t} else {\n\t    index -= indexStart;\n\t}\n    }\n    return index;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeLinkSegment --\n *\n *\tThis function adds a new segment to a B-tree at a given location.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSegPtr will be linked into its tree.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeLinkSegment(\n    TkTextSegment *segPtr,\t/* Pointer to new segment to be added to\n\t\t\t\t * B-tree. Should be completely initialized by\n\t\t\t\t * caller except for nextPtr field. */\n    TkTextIndex *indexPtr)\t/* Where to add segment: it gets linked in\n\t\t\t\t * just before the segment indicated here. */\n{\n    TkTextSegment *prevPtr;\n\n    prevPtr = SplitSeg(indexPtr);\n    if (prevPtr == NULL) {\n\tsegPtr->nextPtr = indexPtr->linePtr->segPtr;\n\tindexPtr->linePtr->segPtr = segPtr;\n    } else {\n\tsegPtr->nextPtr = prevPtr->nextPtr;\n\tprevPtr->nextPtr = segPtr;\n    }\n    CleanupLine(indexPtr->linePtr);\n    if (tkBTreeDebug) {\n\tTkBTreeCheck(indexPtr->tree);\n    }\n    ((BTree *)indexPtr->tree)->stateEpoch++;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeUnlinkSegment --\n *\n *\tThis function unlinks a segment from its line in a B-tree.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSegPtr will be unlinked from linePtr. The segment itself isn't\n *\tmodified by this function.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeUnlinkSegment(\n    TkTextSegment *segPtr,\t/* Segment to be unlinked. */\n    TkTextLine *linePtr)\t/* Line that currently contains segment. */\n{\n    TkTextSegment *prevPtr;\n\n    if (linePtr->segPtr == segPtr) {\n\tlinePtr->segPtr = segPtr->nextPtr;\n    } else {\n\tprevPtr = linePtr->segPtr;\n\twhile (prevPtr->nextPtr != segPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\n\t    if (prevPtr == NULL) {\n\t\t/*\n\t\t * Two logical lines merged into one display line through\n\t\t * eliding of a newline.\n\t\t */\n\n\t\tlinePtr = TkBTreeNextLine(NULL, linePtr);\n\t\tprevPtr = linePtr->segPtr;\n\t    }\n\t}\n\tprevPtr->nextPtr = segPtr->nextPtr;\n    }\n    CleanupLine(linePtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeTag --\n *\n *\tTurn a given tag on or off for a given range of characters in a B-tree\n *\tof text.\n *\n * Results:\n *\t1 if the tags on any characters in the range were changed, and zero\n *\totherwise (i.e. if the tag was already absent (add = 0) or present\n *\t(add = 1) on the index range in question).\n *\n * Side effects:\n *\tThe given tag is added to the given range of characters in the tree or\n *\tremoved from all those characters, depending on the \"add\" argument.\n *\tThe structure of the btree is modified enough that index1Ptr and\n *\tindex2Ptr are no longer valid after this function returns, and the\n *\tindexes may be modified by this function.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreeTag(\n    TkTextIndex *index1Ptr,\n\t\t\t\t/* Indicates first character in range. */\n    TkTextIndex *index2Ptr,\n\t\t\t\t/* Indicates character just after the last one\n\t\t\t\t * in range. */\n    TkTextTag *tagPtr,\t\t/* Tag to add or remove. */\n    bool add)\t\t\t/* True means add tag to the given range of\n\t\t\t\t * characters; false means remove the tag from\n\t\t\t\t * the range. */\n{\n    TkTextSegment *segPtr, *prevPtr;\n    TkTextSearch search;\n    TkTextLine *cleanupLinePtr;\n    bool oldState, changed, anyChanges = false;\n\n    /*\n     * See whether the tag is present at the start of the range. If the state\n     * doesn't already match what we want then add a toggle there.\n     */\n\n    oldState = TkBTreeCharTagged(index1Ptr, tagPtr);\n    if (add != oldState) {\n\tsegPtr = (TkTextSegment *)Tcl_Alloc(TSEG_SIZE);\n\tsegPtr->typePtr = (add) ? &tkTextToggleOnType : &tkTextToggleOffType;\n\tprevPtr = SplitSeg(index1Ptr);\n\tif (prevPtr == NULL) {\n\t    segPtr->nextPtr = index1Ptr->linePtr->segPtr;\n\t    index1Ptr->linePtr->segPtr = segPtr;\n\t} else {\n\t    segPtr->nextPtr = prevPtr->nextPtr;\n\t    prevPtr->nextPtr = segPtr;\n\t}\n\tsegPtr->size = 0;\n\tsegPtr->body.toggle.tagPtr = tagPtr;\n\tsegPtr->body.toggle.inNodeCounts = false;\n\tanyChanges = 1;\n    }\n\n    /*\n     * Scan the range of characters and delete any internal tag transitions.\n     * Keep track of what the old state was at the end of the range, and add a\n     * toggle there if it's needed.\n     */\n\n    TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);\n    cleanupLinePtr = index1Ptr->linePtr;\n    while (TkBTreeNextTag(&search)) {\n\tanyChanges = 1;\n\toldState ^= 1;\n\tsegPtr = search.segPtr;\n\tprevPtr = search.curIndex.linePtr->segPtr;\n\tif (prevPtr == segPtr) {\n\t    search.curIndex.linePtr->segPtr = segPtr->nextPtr;\n\t} else {\n\t    while (prevPtr->nextPtr != segPtr) {\n\t\tprevPtr = prevPtr->nextPtr;\n\t    }\n\t    prevPtr->nextPtr = segPtr->nextPtr;\n\t}\n\tif (segPtr->body.toggle.inNodeCounts) {\n\t    ChangeNodeToggleCount(search.curIndex.linePtr->parentPtr,\n\t\t    segPtr->body.toggle.tagPtr, -1);\n\t    segPtr->body.toggle.inNodeCounts = false;\n\t    changed = 1;\n\t} else {\n\t    changed = 0;\n\t}\n\tTcl_Free(segPtr);\n\n\t/*\n\t * The code below is a bit tricky. After deleting a toggle we\n\t * eventually have to call CleanupLine, in order to allow character\n\t * segments to be merged together. To do this, we remember in\n\t * cleanupLinePtr a line that needs to be cleaned up, but we don't\n\t * clean it up until we've moved on to a different line. That way the\n\t * cleanup process won't goof up segPtr.\n\t */\n\n\tif (cleanupLinePtr != search.curIndex.linePtr) {\n\t    CleanupLine(cleanupLinePtr);\n\t    cleanupLinePtr = search.curIndex.linePtr;\n\t}\n\n\t/*\n\t * Quick hack. ChangeNodeToggleCount may move the tag's root location\n\t * around and leave the search in the void. This resets the search.\n\t */\n\n\tif (changed) {\n\t    TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);\n\t}\n    }\n    if ((add != 0) ^ oldState) {\n\tsegPtr = (TkTextSegment *)Tcl_Alloc(TSEG_SIZE);\n\tsegPtr->typePtr = (add) ? &tkTextToggleOffType : &tkTextToggleOnType;\n\tprevPtr = SplitSeg(index2Ptr);\n\tif (prevPtr == NULL) {\n\t    segPtr->nextPtr = index2Ptr->linePtr->segPtr;\n\t    index2Ptr->linePtr->segPtr = segPtr;\n\t} else {\n\t    segPtr->nextPtr = prevPtr->nextPtr;\n\t    prevPtr->nextPtr = segPtr;\n\t}\n\tsegPtr->size = 0;\n\tsegPtr->body.toggle.tagPtr = tagPtr;\n\tsegPtr->body.toggle.inNodeCounts = false;\n\tanyChanges = 1;\n    }\n\n    /*\n     * Cleanup cleanupLinePtr and the last line of the range, if these are\n     * different.\n     */\n\n    if (anyChanges) {\n\tCleanupLine(cleanupLinePtr);\n\tif (cleanupLinePtr != index2Ptr->linePtr) {\n\t    CleanupLine(index2Ptr->linePtr);\n\t}\n\t((BTree *)index1Ptr->tree)->stateEpoch++;\n    }\n\n    if (tkBTreeDebug) {\n\tTkBTreeCheck(index1Ptr->tree);\n    }\n    return anyChanges;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ChangeNodeToggleCount --\n *\n *\tThis function increments or decrements the toggle count for a\n *\tparticular tag in a particular node and all its ancestors up to the\n *\tper-tag root node.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe toggle count for tag is adjusted up or down by \"delta\" in nodePtr.\n *\tThis routine maintains the tagRootPtr that identifies the root node\n *\tfor the tag, moving it up or down the tree as needed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nChangeNodeToggleCount(\n    Node *nodePtr,\t/* Node whose toggle count for a tag must be\n\t\t\t\t * changed. */\n    TkTextTag *tagPtr,\t\t/* Information about tag. */\n    Tcl_Size delta)\t\t\t/* Amount to add to current toggle count for\n\t\t\t\t * tag (may be negative). */\n{\n    Summary *summaryPtr, *prevPtr;\n    Node *node2Ptr;\n    Tcl_Size rootLevel;\t/* Level of original tag root. */\n\n    tagPtr->toggleCount += delta;\n    if (tagPtr->tagRootPtr == NULL) {\n\ttagPtr->tagRootPtr = nodePtr;\n\treturn;\n    }\n\n    /*\n     * Note the level of the existing root for the tag so we can detect if it\n     * needs to be moved because of the toggle count change.\n     */\n\n    rootLevel = tagPtr->tagRootPtr->level;\n\n    /*\n     * Iterate over the node and its ancestors up to the tag root, adjusting\n     * summary counts at each node and moving the tag's root upwards if\n     * necessary.\n     */\n\n    for ( ; nodePtr != tagPtr->tagRootPtr; nodePtr = nodePtr->parentPtr) {\n\t/*\n\t * See if there's already an entry for this tag for this node. If so,\n\t * perhaps all we have to do is adjust its count.\n\t */\n\n\tfor (prevPtr = NULL, summaryPtr = nodePtr->summaryPtr;\n\t\tsummaryPtr != NULL;\n\t\tprevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) {\n\t    if (summaryPtr->tagPtr == tagPtr) {\n\t\tbreak;\n\t    }\n\t}\n\tif (summaryPtr != NULL) {\n\t    summaryPtr->toggleCount += delta;\n\t    if (summaryPtr->toggleCount > 0 &&\n\t\t    summaryPtr->toggleCount < tagPtr->toggleCount) {\n\t\tcontinue;\n\t    }\n\t    if (summaryPtr->toggleCount != 0) {\n\t\t/*\n\t\t * Should never find a node with max toggle count at this\n\t\t * point (there shouldn't have been a summary entry in the\n\t\t * first place).\n\t\t */\n\n\t\tTcl_Panic(\"ChangeNodeToggleCount: bad toggle count (%\" TCL_Z_MODIFIER \"d) max (%\" TCL_Z_MODIFIER \"d)\",\n\t\t    summaryPtr->toggleCount, tagPtr->toggleCount);\n\t    }\n\n\t    /*\n\t     * Zero toggle count; must remove this tag from the list.\n\t     */\n\n\t    if (prevPtr == NULL) {\n\t\tnodePtr->summaryPtr = summaryPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = summaryPtr->nextPtr;\n\t    }\n\t    Tcl_Free(summaryPtr);\n\t} else {\n\t    /*\n\t     * This tag isn't currently in the summary information list.\n\t     */\n\n\t    if (rootLevel == nodePtr->level) {\n\t\t/*\n\t\t * The old tag root is at the same level in the tree as this\n\t\t * node, but it isn't at this node. Move the tag root up a\n\t\t * level, in the hopes that it will now cover this node as\n\t\t * well as the old root (if not, we'll move it up again the\n\t\t * next time through the loop). To push it up one level we\n\t\t * copy the original toggle count into the summary information\n\t\t * at the old root and change the root to its parent node.\n\t\t */\n\n\t\tNode *rootNodePtr = tagPtr->tagRootPtr;\n\n\t\tsummaryPtr = (Summary *)Tcl_Alloc(sizeof(Summary));\n\t\tsummaryPtr->tagPtr = tagPtr;\n\t\tsummaryPtr->toggleCount = tagPtr->toggleCount - delta;\n\t\tsummaryPtr->nextPtr = rootNodePtr->summaryPtr;\n\t\trootNodePtr->summaryPtr = summaryPtr;\n\t\trootNodePtr = rootNodePtr->parentPtr;\n\t\trootLevel = rootNodePtr->level;\n\t\ttagPtr->tagRootPtr = rootNodePtr;\n\t    }\n\t    summaryPtr = (Summary *)Tcl_Alloc(sizeof(Summary));\n\t    summaryPtr->tagPtr = tagPtr;\n\t    summaryPtr->toggleCount = delta;\n\t    summaryPtr->nextPtr = nodePtr->summaryPtr;\n\t    nodePtr->summaryPtr = summaryPtr;\n\t}\n    }\n\n    /*\n     * If we've decremented the toggle count, then it may be necessary to push\n     * the tag root down one or more levels.\n     */\n\n    if (delta >= 0) {\n\treturn;\n    }\n    if (tagPtr->toggleCount == 0) {\n\ttagPtr->tagRootPtr = NULL;\n\treturn;\n    }\n    nodePtr = tagPtr->tagRootPtr;\n    while (nodePtr->level > 0) {\n\t/*\n\t * See if a single child node accounts for all of the tag's toggles.\n\t * If so, push the root down one level.\n\t */\n\n\tfor (node2Ptr = nodePtr->children.nodePtr;\n\t\tnode2Ptr != NULL ;\n\t\tnode2Ptr = node2Ptr->nextPtr) {\n\t    for (prevPtr = NULL, summaryPtr = node2Ptr->summaryPtr;\n\t\t    summaryPtr != NULL;\n\t\t    prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->tagPtr == tagPtr) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (summaryPtr == NULL) {\n\t\tcontinue;\n\t    }\n\t    if (summaryPtr->toggleCount != tagPtr->toggleCount) {\n\t\t/*\n\t\t * No node has all toggles, so the root is still valid.\n\t\t */\n\n\t\treturn;\n\t    }\n\n\t    /*\n\t     * This node has all the toggles, so push down the root.\n\t     */\n\n\t    if (prevPtr == NULL) {\n\t\tnode2Ptr->summaryPtr = summaryPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = summaryPtr->nextPtr;\n\t    }\n\t    Tcl_Free(summaryPtr);\n\t    tagPtr->tagRootPtr = node2Ptr;\n\t    break;\n\t}\n\tnodePtr = tagPtr->tagRootPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindTagStart --\n *\n *\tFind the start of the first range of a tag.\n *\n * Results:\n *\tThe return value is a pointer to the first tag toggle segment for the\n *\ttag. This can be either a tagon or tagoff segments because of the way\n *\tTkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag\n *\ttoggle.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nFindTagStart(\n    TkTextBTree tree,\t\t/* Tree to search within. */\n    TkTextTag *tagPtr,\t\t/* Tag to search for. */\n    TkTextIndex *indexPtr)\t/* Return - index information. */\n{\n    Node *nodePtr;\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    Summary *summaryPtr;\n    int offset;\n\n    nodePtr = tagPtr->tagRootPtr;\n    if (nodePtr == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Search from the root of the subtree that contains the tag down to the\n     * level 0 node.\n     */\n\n    while (nodePtr && nodePtr->level > 0) {\n\tfor (nodePtr = nodePtr->children.nodePtr ; nodePtr != NULL;\n\t\tnodePtr = nodePtr->nextPtr) {\n\t    for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->tagPtr == tagPtr) {\n\t\t    goto gotNodeWithTag;\n\t\t}\n\t    }\n\t}\n    gotNodeWithTag:\n\tcontinue;\n    }\n\n    if (nodePtr == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Work through the lines attached to the level-0 node.\n     */\n\n    for (linePtr = nodePtr->children.linePtr; linePtr != NULL;\n\t    linePtr = linePtr->nextPtr) {\n\tfor (offset = 0, segPtr = linePtr->segPtr ; segPtr != NULL;\n\t\toffset += segPtr->size, segPtr = segPtr->nextPtr) {\n\t    if (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType))\n\t\t    && (segPtr->body.toggle.tagPtr == tagPtr)) {\n\t\t/*\n\t\t * It is possible that this is a tagoff tag, but that gets\n\t\t * cleaned up later.\n\t\t */\n\n\t\tindexPtr->tree = tree;\n\t\tindexPtr->linePtr = linePtr;\n\t\tindexPtr->byteIndex = offset;\n\t\treturn segPtr;\n\t    }\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindTagEnd --\n *\n *\tFind the end of the last range of a tag.\n *\n * Results:\n *\tThe return value is a pointer to the last tag toggle segment for the\n *\ttag. This can be either a tagon or tagoff segments because of the way\n *\tTkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag\n *\ttoggle.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nFindTagEnd(\n    TkTextBTree tree,\t\t/* Tree to search within. */\n    TkTextTag *tagPtr,\t\t/* Tag to search for. */\n    TkTextIndex *indexPtr)\t/* Return - index information. */\n{\n    Node *nodePtr, *lastNodePtr;\n    TkTextLine *linePtr ,*lastLinePtr;\n    TkTextSegment *segPtr, *lastSegPtr, *last2SegPtr;\n    Summary *summaryPtr;\n    int lastoffset, lastoffset2, offset;\n\n    nodePtr = tagPtr->tagRootPtr;\n    if (nodePtr == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Search from the root of the subtree that contains the tag down to the\n     * level 0 node.\n     */\n\n    while (nodePtr && nodePtr->level > 0) {\n\tfor (lastNodePtr = NULL, nodePtr = nodePtr->children.nodePtr ;\n\t\tnodePtr != NULL; nodePtr = nodePtr->nextPtr) {\n\t    for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->tagPtr == tagPtr) {\n\t\t    lastNodePtr = nodePtr;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tnodePtr = lastNodePtr;\n    }\n\n    if (nodePtr == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Work through the lines attached to the level-0 node.\n     */\n\n    last2SegPtr = NULL;\n    lastoffset2 = 0;\n    lastoffset = 0;\n    for (lastLinePtr = NULL, linePtr = nodePtr->children.linePtr;\n\t    linePtr != NULL; linePtr = linePtr->nextPtr) {\n\tfor (offset = 0, lastSegPtr = NULL, segPtr = linePtr->segPtr ;\n\t\tsegPtr != NULL;\n\t\toffset += segPtr->size, segPtr = segPtr->nextPtr) {\n\t    if (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType))\n\t\t    && (segPtr->body.toggle.tagPtr == tagPtr)) {\n\t\tlastSegPtr = segPtr;\n\t\tlastoffset = offset;\n\t    }\n\t}\n\tif (lastSegPtr != NULL) {\n\t    lastLinePtr = linePtr;\n\t    last2SegPtr = lastSegPtr;\n\t    lastoffset2 = lastoffset;\n\t}\n    }\n    indexPtr->tree = tree;\n    indexPtr->linePtr = lastLinePtr;\n    indexPtr->byteIndex = lastoffset2;\n    return last2SegPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeStartSearch --\n *\n *\tThis function sets up a search for tag transitions involving a given\n *\ttag (or all tags) in a given range of the text.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe information at *searchPtr is set up so that subsequent calls to\n *\tTkBTreeNextTag or TkBTreePrevTag will return information about the\n *\tlocations of tag transitions. Note that TkBTreeNextTag or\n *\tTkBTreePrevTag must be called to get the first transition. Note:\n *\tunlike TkBTreeNextTag and TkBTreePrevTag, this routine does not\n *\tguarantee that searchPtr->curIndex is equal to *index1Ptr. It may be\n *\tgreater than that if *index1Ptr is less than the first tag transition.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeStartSearch(\n    TkTextIndex *index1Ptr,\t/* Search starts here. Tag toggles at this\n\t\t\t\t * position will not be returned. */\n    TkTextIndex *index2Ptr,\t/* Search stops here. Tag toggles at this\n\t\t\t\t * position *will* be returned. */\n    TkTextTag *tagPtr,\t\t/* Tag to search for. NULL means search for\n\t\t\t\t * any tag. */\n    TkTextSearch *searchPtr)\n\t\t\t\t/* Where to store information about search's\n\t\t\t\t * progress. */\n{\n    Tcl_Size offset;\n    TkTextIndex index0;\t\t/* First index of the tag. */\n    TkTextSegment *seg0Ptr;\t/* First segment of the tag. */\n\n    /*\n     * Find the segment that contains the first toggle for the tag. This may\n     * become the starting point in the search.\n     */\n\n    seg0Ptr = FindTagStart(index1Ptr->tree, tagPtr, &index0);\n    if (seg0Ptr == NULL) {\n\t/*\n\t * Even though there are no toggles, the display code still uses the\n\t * search curIndex, so initialize that anyway.\n\t */\n\n\tsearchPtr->linesLeft = 0;\n\tsearchPtr->curIndex = *index1Ptr;\n\tsearchPtr->segPtr = NULL;\n\tsearchPtr->nextPtr = NULL;\n\treturn;\n    }\n    if (TkTextIndexCmp(index1Ptr, &index0) < 0) {\n\t/*\n\t * Adjust start of search up to the first range of the tag.\n\t */\n\n\tsearchPtr->curIndex = index0;\n\tsearchPtr->segPtr = NULL;\n\tsearchPtr->nextPtr = seg0Ptr;\t/* Will be returned by NextTag. */\n\tindex1Ptr = &index0;\n    } else {\n\tsearchPtr->curIndex = *index1Ptr;\n\tsearchPtr->segPtr = NULL;\n\tsearchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset);\n\tsearchPtr->curIndex.byteIndex -= offset;\n    }\n    searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, NULL);\n    searchPtr->tagPtr = tagPtr;\n    searchPtr->linesLeft = TkBTreeLinesTo(NULL, index2Ptr->linePtr) + 1\n\t    - TkBTreeLinesTo(NULL, index1Ptr->linePtr);\n    searchPtr->allTags = (tagPtr == NULL);\n    if (searchPtr->linesLeft == 1) {\n\t/*\n\t * Starting and stopping segments are in the same line; mark the\n\t * search as over immediately if the second segment is before the\n\t * first. A search does not return a toggle at the very start of the\n\t * range, unless the range is artificially moved up to index0.\n\t */\n\n\tif (((index1Ptr == &index0) &&\n\t\t(index1Ptr->byteIndex > index2Ptr->byteIndex)) ||\n\t\t((index1Ptr != &index0) &&\n\t\t(index1Ptr->byteIndex >= index2Ptr->byteIndex))) {\n\t    searchPtr->linesLeft = 0;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeStartSearchBack --\n *\n *\tThis function sets up a search backwards for tag transitions involving\n *\ta given tag (or all tags) in a given range of the text. In the normal\n *\tcase the first index (*index1Ptr) is beyond the second index\n *\t(*index2Ptr).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe information at *searchPtr is set up so that subsequent calls to\n *\tTkBTreePrevTag will return information about the locations of tag\n *\ttransitions. Note that TkBTreePrevTag must be called to get the first\n *\ttransition. Note: unlike TkBTreeNextTag and TkBTreePrevTag, this\n *\troutine does not guarantee that searchPtr->curIndex is equal to\n *\t*index1Ptr. It may be less than that if *index1Ptr is greater than the\n *\tlast tag transition.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeStartSearchBack(\n    TkTextIndex *index1Ptr,\t/* Search starts here. Tag toggles at this\n\t\t\t\t * position will not be returned. */\n    TkTextIndex *index2Ptr,\t/* Search stops here. Tag toggles at this\n\t\t\t\t * position *will* be returned. */\n    TkTextTag *tagPtr,\t\t/* Tag to search for. NULL means search for\n\t\t\t\t * any tag. */\n    TkTextSearch *searchPtr)\n\t\t\t\t/* Where to store information about search's\n\t\t\t\t * progress. */\n{\n    Tcl_Size offset;\n    TkTextIndex index0;\t\t/* Last index of the tag. */\n    TkTextIndex backOne;\t/* One character before starting index. */\n    TkTextSegment *seg0Ptr;\t/* Last segment of the tag. */\n\n    /*\n     * Find the segment that contains the last toggle for the tag. This may\n     * become the starting point in the search.\n     */\n\n    seg0Ptr = FindTagEnd(index1Ptr->tree, tagPtr, &index0);\n    if (seg0Ptr == NULL) {\n\t/*\n\t * Even though there are no toggles, the display code still uses the\n\t * search curIndex, so initialize that anyway.\n\t */\n\n\tsearchPtr->linesLeft = 0;\n\tsearchPtr->curIndex = *index1Ptr;\n\tsearchPtr->segPtr = NULL;\n\tsearchPtr->nextPtr = NULL;\n\treturn;\n    }\n\n    /*\n     * Adjust the start of the search so it doesn't find any tag toggles\n     * that are right at the index specified by the user.\n     */\n\n    if (TkTextIndexCmp(index1Ptr, &index0) > 0) {\n\tsearchPtr->curIndex = index0;\n\tindex1Ptr = &index0;\n    } else {\n\tTkTextIndexBackChars(NULL, index1Ptr, 1, &searchPtr->curIndex,\n\t\tCOUNT_INDICES);\n    }\n    searchPtr->segPtr = NULL;\n    searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset);\n    searchPtr->curIndex.byteIndex -= offset;\n\n    /*\n     * Adjust the end of the search so it does find toggles that are right at\n     * the second index specified by the user.\n     */\n\n    if ((TkBTreeLinesTo(NULL, index2Ptr->linePtr) == 0) &&\n\t    (index2Ptr->byteIndex == 0)) {\n\tbackOne = *index2Ptr;\n\tsearchPtr->lastPtr = NULL;\t/* Signals special case for 1.0. */\n    } else {\n\tTkTextIndexBackChars(NULL, index2Ptr, 1, &backOne, COUNT_INDICES);\n\tsearchPtr->lastPtr = TkTextIndexToSeg(&backOne, NULL);\n    }\n    searchPtr->tagPtr = tagPtr;\n    searchPtr->linesLeft = TkBTreeLinesTo(NULL, index1Ptr->linePtr) + 1\n\t    - TkBTreeLinesTo(NULL, backOne.linePtr);\n    searchPtr->allTags = (tagPtr == NULL);\n    if (searchPtr->linesLeft == 1) {\n\t/*\n\t * Starting and stopping segments are in the same line; mark the\n\t * search as over immediately if the second segment is after the\n\t * first.\n\t */\n\n\tif (index1Ptr->byteIndex <= backOne.byteIndex) {\n\t    searchPtr->linesLeft = 0;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeNextTag --\n *\n *\tOnce a tag search has begun, successive calls to this function return\n *\tsuccessive tag toggles. Note: it is NOT SAFE to call this function if\n *\tcharacters have been inserted into or deleted from the B-tree since\n *\tthe call to TkBTreeStartSearch.\n *\n * Results:\n *\tThe return value is 1 if another toggle was found that met the\n *\tcriteria specified in the call to TkBTreeStartSearch; in this case\n *\tsearchPtr->curIndex gives the toggle's position and\n *\tsearchPtr->curTagPtr points to its segment. 0 is returned if no more\n *\tmatching tag transitions were found; in this case searchPtr->curIndex\n *\tis the same as searchPtr->stopIndex.\n *\n * Side effects:\n *\tInformation in *searchPtr is modified to update the state of the\n *\tsearch and indicate where the next tag toggle is located.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreeNextTag(\n    TkTextSearch *searchPtr)\n\t\t\t\t/* Information about search in progress; must\n\t\t\t\t * have been set up by call to\n\t\t\t\t * TkBTreeStartSearch. */\n{\n    TkTextSegment *segPtr;\n    Node *nodePtr;\n    Summary *summaryPtr;\n\n    if (searchPtr->linesLeft <= 0) {\n\tgoto searchOver;\n    }\n\n    /*\n     * The outermost loop iterates over lines that may potentially contain a\n     * relevant tag transition, starting from the current segment in the\n     * current line.\n     */\n\n    segPtr = searchPtr->nextPtr;\n    while (1) {\n\t/*\n\t * Check for more tags on the current line.\n\t */\n\n\tfor ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\t    if (segPtr == searchPtr->lastPtr) {\n\t\tgoto searchOver;\n\t    }\n\t    if (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType))\n\t\t    && (searchPtr->allTags\n\t\t    || (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {\n\t\tsearchPtr->segPtr = segPtr;\n\t\tsearchPtr->nextPtr = segPtr->nextPtr;\n\t\tsearchPtr->tagPtr = segPtr->body.toggle.tagPtr;\n\t\treturn 1;\n\t    }\n\t    searchPtr->curIndex.byteIndex += segPtr->size;\n\t}\n\n\t/*\n\t * See if there are more lines associated with the current parent\n\t * node. If so, go back to the top of the loop to search the next one.\n\t */\n\n\tnodePtr = searchPtr->curIndex.linePtr->parentPtr;\n\tsearchPtr->curIndex.linePtr = searchPtr->curIndex.linePtr->nextPtr;\n\tsearchPtr->linesLeft--;\n\tif (searchPtr->linesLeft <= 0) {\n\t    goto searchOver;\n\t}\n\tif (searchPtr->curIndex.linePtr != NULL) {\n\t    segPtr = searchPtr->curIndex.linePtr->segPtr;\n\t    searchPtr->curIndex.byteIndex = 0;\n\t    continue;\n\t}\n\tif (nodePtr == searchPtr->tagPtr->tagRootPtr) {\n\t    goto searchOver;\n\t}\n\n\t/*\n\t * Search across and up through the B-tree's node hierarchy looking\n\t * for the next node that has a relevant tag transition somewhere in\n\t * its subtree. Be sure to update linesLeft as we skip over large\n\t * chunks of lines.\n\t */\n\n\twhile (1) {\n\t    while (nodePtr->nextPtr == NULL) {\n\t\tif (nodePtr->parentPtr == NULL ||\n\t\t    nodePtr->parentPtr == searchPtr->tagPtr->tagRootPtr) {\n\t\t    goto searchOver;\n\t\t}\n\t\tnodePtr = nodePtr->parentPtr;\n\t    }\n\t    nodePtr = nodePtr->nextPtr;\n\t    for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif ((searchPtr->allTags) ||\n\t\t\t(summaryPtr->tagPtr == searchPtr->tagPtr)) {\n\t\t    goto gotNodeWithTag;\n\t\t}\n\t    }\n\t    searchPtr->linesLeft -= nodePtr->numLines;\n\t}\n\n\t/*\n\t * At this point we've found a subtree that has a relevant tag\n\t * transition. Now search down (and across) through that subtree to\n\t * find the first level-0 node that has a relevant tag transition.\n\t */\n\n    gotNodeWithTag:\n\twhile (nodePtr->level > 0) {\n\t    for (nodePtr = nodePtr->children.nodePtr; ;\n\t\t    nodePtr = nodePtr->nextPtr) {\n\t\tfor (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if ((searchPtr->allTags)\n\t\t\t    || (summaryPtr->tagPtr == searchPtr->tagPtr)) {\n\t\t\t/*\n\t\t\t * Would really like a multi-level continue here...\n\t\t\t */\n\n\t\t\tgoto nextChild;\n\t\t    }\n\t\t}\n\t\tsearchPtr->linesLeft -= nodePtr->numLines;\n\t\tif (nodePtr->nextPtr == NULL) {\n\t\t    Tcl_Panic(\"TkBTreeNextTag found incorrect tag summary info\");\n\t\t}\n\t    }\n\tnextChild:\n\t    continue;\n\t}\n\n\t/*\n\t * Now we're down to a level-0 node that contains a line that contains\n\t * a relevant tag transition. Set up line information and go back to\n\t * the beginning of the loop to search through lines.\n\t */\n\n\tsearchPtr->curIndex.linePtr = nodePtr->children.linePtr;\n\tsearchPtr->curIndex.byteIndex = 0;\n\tsegPtr = searchPtr->curIndex.linePtr->segPtr;\n\tif (searchPtr->linesLeft <= 0) {\n\t    goto searchOver;\n\t}\n\tcontinue;\n    }\n\n  searchOver:\n    searchPtr->linesLeft = 0;\n    searchPtr->segPtr = NULL;\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreePrevTag --\n *\n *\tOnce a tag search has begun, successive calls to this function return\n *\tsuccessive tag toggles in the reverse direction. Note: it is NOT SAFE\n *\tto call this function if characters have been inserted into or deleted\n *\tfrom the B-tree since the call to TkBTreeStartSearch.\n *\n * Results:\n *\tThe return value is 1 if another toggle was found that met the\n *\tcriteria specified in the call to TkBTreeStartSearch; in this case\n *\tsearchPtr->curIndex gives the toggle's position and\n *\tsearchPtr->curTagPtr points to its segment. 0 is returned if no more\n *\tmatching tag transitions were found; in this case searchPtr->curIndex\n *\tis the same as searchPtr->stopIndex.\n *\n * Side effects:\n *\tInformation in *searchPtr is modified to update the state of the\n *\tsearch and indicate where the next tag toggle is located.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreePrevTag(\n    TkTextSearch *searchPtr)\n\t\t\t\t/* Information about search in progress; must\n\t\t\t\t * have been set up by call to\n\t\t\t\t * TkBTreeStartSearch. */\n{\n    TkTextSegment *segPtr, *prevPtr;\n    TkTextLine *linePtr, *prevLinePtr;\n    Node *nodePtr, *node2Ptr, *prevNodePtr;\n    Summary *summaryPtr;\n    int byteIndex, linesSkipped;\n    bool pastLast;\t\t/* Saw last marker during scan. */\n\n    if (searchPtr->linesLeft <= 0) {\n\tgoto searchOver;\n    }\n\n    /*\n     * The outermost loop iterates over lines that may potentially contain a\n     * relevant tag transition, starting from the current segment in the\n     * current line. \"nextPtr\" is maintained as the last segment in a line\n     * that we can look at.\n     */\n\n    while (1) {\n\t/*\n\t * Check for the last toggle before the current segment on this line.\n\t */\n\n\tbyteIndex = 0;\n\tif (searchPtr->lastPtr == NULL) {\n\t    /*\n\t     * Search back to the very beginning, so pastLast is irrelevent.\n\t     */\n\n\t    pastLast = true;\n\t} else {\n\t    pastLast = false;\n\t}\n\n\tfor (prevPtr = NULL, segPtr = searchPtr->curIndex.linePtr->segPtr ;\n\t\tsegPtr != NULL && segPtr != searchPtr->nextPtr;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType))\n\t\t    && (searchPtr->allTags\n\t\t    || (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {\n\t\tprevPtr = segPtr;\n\t\tsearchPtr->curIndex.byteIndex = byteIndex;\n\t    }\n\t    if (segPtr == searchPtr->lastPtr) {\n\t\tprevPtr = NULL;\t\t/* Segments earlier than last don't\n\t\t\t\t\t * count. */\n\t\tpastLast = true;\n\t    }\n\t    byteIndex += segPtr->size;\n\t}\n\tif (prevPtr != NULL) {\n\t    if (searchPtr->linesLeft == 1 && !pastLast) {\n\t\t/*\n\t\t * We found a segment that is before the stopping index. Note\n\t\t * that it is OK if prevPtr == lastPtr.\n\t\t */\n\n\t\tgoto searchOver;\n\t    }\n\t    searchPtr->segPtr = prevPtr;\n\t    searchPtr->nextPtr = prevPtr;\n\t    searchPtr->tagPtr = prevPtr->body.toggle.tagPtr;\n\t    return 1;\n\t}\n\n\tsearchPtr->linesLeft--;\n\tif (searchPtr->linesLeft <= 0) {\n\t    goto searchOver;\n\t}\n\n\t/*\n\t * See if there are more lines associated with the current parent\n\t * node. If so, go back to the top of the loop to search the previous\n\t * one.\n\t */\n\n\tnodePtr = searchPtr->curIndex.linePtr->parentPtr;\n\tfor (prevLinePtr = NULL, linePtr = nodePtr->children.linePtr;\n\t\tlinePtr != NULL && linePtr != searchPtr->curIndex.linePtr;\n\t\tprevLinePtr = linePtr, linePtr = linePtr->nextPtr) {\n\t    /* empty loop body */ ;\n\t}\n\tif (prevLinePtr != NULL) {\n\t    searchPtr->curIndex.linePtr = prevLinePtr;\n\t    searchPtr->nextPtr = NULL;\n\t    continue;\n\t}\n\tif (nodePtr == searchPtr->tagPtr->tagRootPtr) {\n\t    goto searchOver;\n\t}\n\n\t/*\n\t * Search across and up through the B-tree's node hierarchy looking\n\t * for the previous node that has a relevant tag transition somewhere\n\t * in its subtree. The search and line counting is trickier with/out\n\t * back pointers. We'll scan all the nodes under a parent up to the\n\t * current node, searching all of them for tag state. The last one we\n\t * find, if any, is recorded in prevNodePtr, and any nodes past\n\t * prevNodePtr that don't have tag state increment linesSkipped.\n\t */\n\n\twhile (1) {\n\t    for (prevNodePtr = NULL, linesSkipped = 0,\n\t\t    node2Ptr = nodePtr->parentPtr->children.nodePtr ;\n\t\t    node2Ptr != nodePtr;  node2Ptr = node2Ptr->nextPtr) {\n\t\tfor (summaryPtr = node2Ptr->summaryPtr; summaryPtr != NULL;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if ((searchPtr->allTags) ||\n\t\t\t    (summaryPtr->tagPtr == searchPtr->tagPtr)) {\n\t\t\tprevNodePtr = node2Ptr;\n\t\t\tlinesSkipped = 0;\n\t\t\tgoto keepLooking;\n\t\t    }\n\t\t}\n\t\tlinesSkipped += node2Ptr->numLines;\n\n\t    keepLooking:\n\t\tcontinue;\n\t    }\n\t    if (prevNodePtr != NULL) {\n\t\tnodePtr = prevNodePtr;\n\t\tsearchPtr->linesLeft -= linesSkipped;\n\t\tgoto gotNodeWithTag;\n\t    }\n\t    nodePtr = nodePtr->parentPtr;\n\t    if (nodePtr->parentPtr == NULL ||\n\t\tnodePtr == searchPtr->tagPtr->tagRootPtr) {\n\t\tgoto searchOver;\n\t    }\n\t}\n\n\t/*\n\t * At this point we've found a subtree that has a relevant tag\n\t * transition. Now search down (and across) through that subtree to\n\t * find the last level-0 node that has a relevant tag transition.\n\t */\n\n    gotNodeWithTag:\n\twhile (nodePtr->level > 0) {\n\t    for (linesSkipped = 0, prevNodePtr = NULL,\n\t\t    nodePtr = nodePtr->children.nodePtr; nodePtr != NULL ;\n\t\t    nodePtr = nodePtr->nextPtr) {\n\t\tfor (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if ((searchPtr->allTags)\n\t\t\t    || (summaryPtr->tagPtr == searchPtr->tagPtr)) {\n\t\t\tprevNodePtr = nodePtr;\n\t\t\tlinesSkipped = 0;\n\t\t\tgoto keepLooking2;\n\t\t    }\n\t\t}\n\t\tlinesSkipped += nodePtr->numLines;\n\n\t    keepLooking2:\n\t\tcontinue;\n\t    }\n\t    if (prevNodePtr == NULL) {\n\t\tTcl_Panic(\"TkBTreePrevTag found incorrect tag summary info\");\n\t    }\n\t    searchPtr->linesLeft -= linesSkipped;\n\t    nodePtr = prevNodePtr;\n\t}\n\n\t/*\n\t * Now we're down to a level-0 node that contains a line that contains\n\t * a relevant tag transition. Set up line information and go back to\n\t * the beginning of the loop to search through lines. We start with\n\t * the last line below the node.\n\t */\n\n\tfor (prevLinePtr = NULL, linePtr = nodePtr->children.linePtr;\n\t\tlinePtr != NULL ;\n\t\tprevLinePtr = linePtr, linePtr = linePtr->nextPtr) {\n\t    /* empty loop body */ ;\n\t}\n\tsearchPtr->curIndex.linePtr = prevLinePtr;\n\tsearchPtr->curIndex.byteIndex = 0;\n\tif (searchPtr->linesLeft <= 0) {\n\t    goto searchOver;\n\t}\n\tcontinue;\n    }\n\n  searchOver:\n    searchPtr->linesLeft = 0;\n    searchPtr->segPtr = NULL;\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeCharTagged --\n *\n *\tDetermine whether a particular character has a particular tag.\n *\n * Results:\n *\tThe return value is 1 if the given tag is in effect at the character\n *\tgiven by linePtr and ch, and 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkBTreeCharTagged(\n    const TkTextIndex *indexPtr,/* Indicates a character position at which to\n\t\t\t\t * check for a tag. */\n    TkTextTag *tagPtr)\t\t/* Tag of interest. */\n{\n    Node *nodePtr;\n    TkTextLine *siblingLinePtr;\n    TkTextSegment *segPtr;\n    TkTextSegment *toggleSegPtr;\n    int toggles;\n\tTcl_Size index;\n\n    /*\n     * Check for toggles for the tag in indexPtr's line but before indexPtr.\n     * If there is one, its type indicates whether or not the character is\n     * tagged.\n     */\n\n    toggleSegPtr = NULL;\n    for (index = 0, segPtr = indexPtr->linePtr->segPtr;\n\t    (index + segPtr->size) <= indexPtr->byteIndex;\n\t    index += segPtr->size, segPtr = segPtr->nextPtr) {\n\tif (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t|| (segPtr->typePtr == &tkTextToggleOffType))\n\t\t&& (segPtr->body.toggle.tagPtr == tagPtr)) {\n\t    toggleSegPtr = segPtr;\n\t}\n    }\n    if (toggleSegPtr != NULL) {\n\treturn (toggleSegPtr->typePtr == &tkTextToggleOnType);\n    }\n\n    /*\n     * No toggle in this line. Look for toggles for the tag in lines that are\n     * predecessors of indexPtr->linePtr but under the same level-0 node.\n     */\n\n    for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;\n\t    siblingLinePtr != indexPtr->linePtr;\n\t    siblingLinePtr = siblingLinePtr->nextPtr) {\n\tfor (segPtr = siblingLinePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if (((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType))\n\t\t    && (segPtr->body.toggle.tagPtr == tagPtr)) {\n\t\ttoggleSegPtr = segPtr;\n\t    }\n\t}\n    }\n    if (toggleSegPtr != NULL) {\n\treturn (toggleSegPtr->typePtr == &tkTextToggleOnType);\n    }\n\n    /*\n     * No toggle in this node. Scan upwards through the ancestors of this\n     * node, counting the number of toggles of the given tag in siblings that\n     * precede that node.\n     */\n\n    toggles = 0;\n    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;\n\t    nodePtr = nodePtr->parentPtr) {\n\tNode *siblingPtr;\n\tSummary *summaryPtr;\n\n\tfor (siblingPtr = nodePtr->parentPtr->children.nodePtr;\n\t\tsiblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {\n\t    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->tagPtr == tagPtr) {\n\t\t    toggles += summaryPtr->toggleCount;\n\t\t}\n\t    }\n\t}\n\tif (nodePtr == tagPtr->tagRootPtr) {\n\t    break;\n\t}\n    }\n\n    /*\n     * An odd number of toggles means that the tag is present at the given\n     * point.\n     */\n\n    return (toggles & 1) != 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeGetTags --\n *\n *\tReturn information about all of the tags that are associated with a\n *\tparticular character in a B-tree of text.\n *\n * Results:\n *\tThe return value is a malloc-ed array containing pointers to\n *\tinformation for each of the tags that is associated with the character\n *\tat the position given by linePtr and ch. The word at *numTagsPtr is\n *\tfilled in with the number of pointers in the array. It is up to the\n *\tcaller to free the array by passing it to free. If there are no tags\n *\tat the given character then a NULL pointer is returned and *numTagsPtr\n *\twill be set to 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextTag **\nTkBTreeGetTags(\n    const TkTextIndex *indexPtr,/* Indicates a particular position in the\n\t\t\t\t * B-tree. */\n    const TkText *textPtr,\t/* If non-NULL, then only return tags for this\n\t\t\t\t * text widget (when there are peer\n\t\t\t\t * widgets). */\n    Tcl_Size *numTagsPtr)\t\t/* Store number of tags found at this\n\t\t\t\t * location. */\n{\n    Node *nodePtr;\n    TkTextLine *siblingLinePtr;\n    TkTextSegment *segPtr;\n    TkTextLine *linePtr;\n    Tcl_Size src, dst, index;\n    TagInfo tagInfo;\n#define NUM_TAG_INFOS 10\n\n    tagInfo.numTags = 0;\n    tagInfo.arraySize = NUM_TAG_INFOS;\n    tagInfo.tagPtrs = (TkTextTag **)Tcl_Alloc(NUM_TAG_INFOS * sizeof(TkTextTag *));\n    tagInfo.counts = (int *)Tcl_Alloc(NUM_TAG_INFOS * sizeof(int));\n\n    /*\n     * Record tag toggles within the line of indexPtr but preceding indexPtr.\n     */\n\n    linePtr = indexPtr->linePtr;\n    index = 0;\n    segPtr = linePtr->segPtr;\n    while ((index + segPtr->size) <= indexPtr->byteIndex) {\n\tif ((segPtr->typePtr == &tkTextToggleOnType)\n\t\t|| (segPtr->typePtr == &tkTextToggleOffType)) {\n\t    IncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo);\n\t}\n\tindex += segPtr->size;\n\tsegPtr = segPtr->nextPtr;\n\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Two logical lines merged into one display line through eliding\n\t     * of a newline.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(NULL, linePtr);\n\t    segPtr = linePtr->segPtr;\n\t}\n    }\n\n    /*\n     * Record toggles for tags in lines that are predecessors of\n     * indexPtr->linePtr but under the same level-0 node.\n     */\n\n    for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;\n\t    siblingLinePtr != indexPtr->linePtr;\n\t    siblingLinePtr = siblingLinePtr->nextPtr) {\n\tfor (segPtr = siblingLinePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if ((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType)) {\n\t\tIncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo);\n\t    }\n\t}\n    }\n\n    /*\n     * For each node in the ancestry of this line, record tag toggles for all\n     * siblings that precede that node.\n     */\n\n    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;\n\t    nodePtr = nodePtr->parentPtr) {\n\tNode *siblingPtr;\n\tSummary *summaryPtr;\n\n\tfor (siblingPtr = nodePtr->parentPtr->children.nodePtr;\n\t\tsiblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {\n\t    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->toggleCount & 1) {\n\t\t    IncCount(summaryPtr->tagPtr, summaryPtr->toggleCount,\n\t\t\t    &tagInfo);\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Go through the tag information and squash out all of the tags that have\n     * even toggle counts (these tags exist before the point of interest, but\n     * not at the desired character itself). Also squash out all tags that\n     * don't belong to the requested widget.\n     */\n\n    for (src = 0, dst = 0; src < tagInfo.numTags; src++) {\n\tif (tagInfo.counts[src] & 1) {\n\t    const TkText *tagTextPtr = tagInfo.tagPtrs[src]->textPtr;\n\n\t    if (tagTextPtr==NULL || textPtr==NULL || tagTextPtr==textPtr) {\n\t\ttagInfo.tagPtrs[dst] = tagInfo.tagPtrs[src];\n\t\tdst++;\n\t    }\n\t}\n    }\n    *numTagsPtr = dst;\n    Tcl_Free(tagInfo.counts);\n    if (dst == 0) {\n\tTcl_Free(tagInfo.tagPtrs);\n\treturn NULL;\n    }\n    return tagInfo.tagPtrs;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextIsElided --\n *\n *\tSpecial case to just return information about elided attribute.\n *\tSpecialized from TkBTreeGetTags(indexPtr, textPtr, numTagsPtr) and\n *\tGetStyle(textPtr, indexPtr). Just need to keep track of invisibility\n *\tsettings for each priority, pick highest one active at end.\n *\n *\tNote that this returns all elide information up to and including the\n *\tgiven index (quite obviously). However, this does mean that if\n *\tindexPtr is a line-start and one then iterates from the beginning of\n *\tthat line forwards, one will actually revisit the segPtrs of size zero\n *\t(for tag toggling, for example) which have already been seen here.\n *\n *\tFor this reason we fill in the fields 'segPtr' and 'segOffset' of\n *\telideInfo, enabling our caller easily to calculate incremental changes\n *\tfrom where we left off.\n *\n * Results:\n *\tReturns whether this text should be elided or not.\n *\n *\tOptionally returns more detailed information in elideInfo.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkTextIsElided(\n    const TkText *textPtr,\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr,/* The character in the text for which display\n\t\t\t\t * information is wanted. */\n    TkTextElideInfo *elideInfo)\t/* NULL or a pointer to a structure in which\n\t\t\t\t * indexPtr's elide state will be stored and\n\t\t\t\t * returned. */\n{\n    Node *nodePtr;\n    TkTextLine *siblingLinePtr;\n    TkTextSegment *segPtr;\n    TkTextTag *tagPtr = NULL;\n    Tcl_Size i;\n    TkTextElideInfo *infoPtr;\n    TkTextLine *linePtr;\n    bool elide;\n    Tcl_Size index;\n\n    if (elideInfo == NULL) {\n\tinfoPtr = (TkTextElideInfo *)Tcl_Alloc(sizeof(TkTextElideInfo));\n    } else {\n\tinfoPtr = elideInfo;\n    }\n\n    infoPtr->elide = false;\t\t/* If nobody says otherwise, it's visible. */\n    infoPtr->tagCnts = infoPtr->deftagCnts;\n    infoPtr->tagPtrs = infoPtr->deftagPtrs;\n    infoPtr->numTags = textPtr->sharedTextPtr->numTags;\n\n    /*\n     * Almost always avoid malloc, so stay out of system calls.\n     */\n\n    if (LOTSA_TAGS < infoPtr->numTags) {\n\tinfoPtr->tagCnts = (int *)Tcl_Alloc(sizeof(int) * infoPtr->numTags);\n\tinfoPtr->tagPtrs = (TkTextTag **)Tcl_Alloc(sizeof(TkTextTag *) * infoPtr->numTags);\n    }\n\n    for (i=0; i<infoPtr->numTags; i++) {\n\tinfoPtr->tagCnts[i] = 0;\n    }\n\n    /*\n     * Record tag toggles within the line of indexPtr but preceding indexPtr.\n     */\n\n    index = 0;\n    linePtr = indexPtr->linePtr;\n    segPtr = linePtr->segPtr;\n    while ((index + segPtr->size) <= indexPtr->byteIndex) {\n\tif ((segPtr->typePtr == &tkTextToggleOnType)\n\t\t|| (segPtr->typePtr == &tkTextToggleOffType)) {\n\t    tagPtr = segPtr->body.toggle.tagPtr;\n\t    if (tagPtr->elide >= 0) {\n\t\tinfoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\tinfoPtr->tagCnts[tagPtr->priority]++;\n\t    }\n\t}\n\n\tindex += segPtr->size;\n\tsegPtr = segPtr->nextPtr;\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Two logical lines merged into one display line through eliding\n\t     * of a newline.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(NULL, linePtr);\n\t    segPtr = linePtr->segPtr;\n\t}\n    }\n\n    /*\n     * Store the first segPtr we haven't examined completely so that our\n     * caller knows where to start.\n     */\n\n    infoPtr->segPtr = segPtr;\n    infoPtr->segOffset = index;\n\n    /*\n     * Record toggles for tags in lines that are predecessors of\n     * indexPtr->linePtr but under the same level-0 node.\n     */\n\n    for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;\n\t    siblingLinePtr != indexPtr->linePtr;\n\t    siblingLinePtr = siblingLinePtr->nextPtr) {\n\tfor (segPtr = siblingLinePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    if ((segPtr->typePtr == &tkTextToggleOnType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOffType)) {\n\t\ttagPtr = segPtr->body.toggle.tagPtr;\n\t\tif (tagPtr->elide >= 0) {\n\t\t    infoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\t    infoPtr->tagCnts[tagPtr->priority]++;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * For each node in the ancestry of this line, record tag toggles for all\n     * siblings that precede that node.\n     */\n\n    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;\n\t    nodePtr = nodePtr->parentPtr) {\n\tNode *siblingPtr;\n\tSummary *summaryPtr;\n\n\tfor (siblingPtr = nodePtr->parentPtr->children.nodePtr;\n\t\tsiblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {\n\t    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;\n\t\t    summaryPtr = summaryPtr->nextPtr) {\n\t\tif (summaryPtr->toggleCount & 1) {\n\t\t    tagPtr = summaryPtr->tagPtr;\n\t\t    if (tagPtr->elide >= 0) {\n\t\t\tinfoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\t\tinfoPtr->tagCnts[tagPtr->priority] +=\n\t\t\t\tsummaryPtr->toggleCount;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Now traverse from highest priority to lowest, take elided value from\n     * first odd count (= on).\n     */\n\n    infoPtr->elidePriority = -1;\n    for (i = infoPtr->numTags-1; i >=0; i--) {\n\tif (infoPtr->tagCnts[i] & 1) {\n\t    infoPtr->elide = infoPtr->tagPtrs[i]->elide > 0;\n\n\t    /*\n\t     * Note: i == infoPtr->tagPtrs[i]->priority\n\t     */\n\n\t    infoPtr->elidePriority = i;\n\t    break;\n\t}\n    }\n\n    elide = infoPtr->elide;\n\n    if (elideInfo == NULL) {\n\tif (LOTSA_TAGS < infoPtr->numTags) {\n\t    Tcl_Free(infoPtr->tagCnts);\n\t    Tcl_Free(infoPtr->tagPtrs);\n\t}\n\n\tTcl_Free(infoPtr);\n    }\n\n    return elide;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextFreeElideInfo --\n *\n *\tThis is a utility function used to free up any memory allocated by the\n *\tTkTextIsElided function above.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory may be freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextFreeElideInfo(\n    TkTextElideInfo *elideInfo)\t/* Free any allocated memory in this\n\t\t\t\t * structure. */\n{\n    if (LOTSA_TAGS < elideInfo->numTags) {\n\tTcl_Free(elideInfo->tagCnts);\n\tTcl_Free(elideInfo->tagPtrs);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IncCount --\n *\n *\tThis is a utility function used by TkBTreeGetTags. It increments the\n *\tcount for a particular tag, adding a new entry for that tag if there\n *\twasn't one previously.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe information at *tagInfoPtr may be modified, and the arrays may be\n *\treallocated to make them larger.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nIncCount(\n    TkTextTag *tagPtr,\t\t/* Handle for tag. */\n    Tcl_Size inc,\t\t\t/* Amount by which to increment tag count. */\n    TagInfo *tagInfoPtr)\t/* Holds cumulative information about tags;\n\t\t\t\t * increment count here. */\n{\n    TkTextTag **tagPtrPtr;\n    Tcl_Size count;\n\n    for (tagPtrPtr = tagInfoPtr->tagPtrs, count = tagInfoPtr->numTags;\n\t    count > 0; tagPtrPtr++, count--) {\n\tif (*tagPtrPtr == tagPtr) {\n\t    tagInfoPtr->counts[tagInfoPtr->numTags-count] += inc;\n\t    return;\n\t}\n    }\n\n    /*\n     * There isn't currently an entry for this tag, so we have to make a new\n     * one. If the arrays are full, then enlarge the arrays first.\n     */\n\n    if (tagInfoPtr->numTags == tagInfoPtr->arraySize) {\n\tTkTextTag **newTags;\n\tint *newCounts, newSize;\n\n\tnewSize = 2 * tagInfoPtr->arraySize;\n\tnewTags = (TkTextTag **)Tcl_Alloc(newSize * sizeof(TkTextTag *));\n\tmemcpy(newTags, tagInfoPtr->tagPtrs,\n\t\ttagInfoPtr->arraySize * sizeof(TkTextTag *));\n\tTcl_Free(tagInfoPtr->tagPtrs);\n\ttagInfoPtr->tagPtrs = newTags;\n\tnewCounts = (int *)Tcl_Alloc(newSize * sizeof(int));\n\tmemcpy(newCounts, tagInfoPtr->counts,\n\t\ttagInfoPtr->arraySize * sizeof(int));\n\tTcl_Free(tagInfoPtr->counts);\n\ttagInfoPtr->counts = newCounts;\n\ttagInfoPtr->arraySize = newSize;\n    }\n\n    tagInfoPtr->tagPtrs[tagInfoPtr->numTags] = tagPtr;\n    tagInfoPtr->counts[tagInfoPtr->numTags] = inc;\n    tagInfoPtr->numTags++;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeCheck --\n *\n *\tThis function runs a set of consistency checks over a B-tree and\n *\tpanics if any inconsistencies are found.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf a structural defect is found, the function panics with an error\n *\tmessage.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkBTreeCheck(\n    TkTextBTree tree)\t\t/* Tree to check. */\n{\n    BTree *treePtr = (BTree *) tree;\n    Summary *summaryPtr;\n    Node *nodePtr;\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    TkTextTag *tagPtr;\n    Tcl_HashEntry *entryPtr;\n    Tcl_HashSearch search;\n    Tcl_Size count;\n\n    /*\n     * Make sure that the tag toggle counts and the tag root pointers are OK.\n     */\n\n    for (entryPtr=Tcl_FirstHashEntry(&treePtr->sharedTextPtr->tagTable,&search);\n\t    entryPtr != NULL ; entryPtr = Tcl_NextHashEntry(&search)) {\n\ttagPtr = (TkTextTag *)Tcl_GetHashValue(entryPtr);\n\tnodePtr = tagPtr->tagRootPtr;\n\tif (nodePtr == NULL) {\n\t    if (tagPtr->toggleCount != 0) {\n\t\tTcl_Panic(\"TkBTreeCheck found \\\"%s\\\" with toggles (%\" TCL_Z_MODIFIER \"d) but no root\",\n\t\t\ttagPtr->name, tagPtr->toggleCount);\n\t    }\n\t    continue;\t\t/* No ranges for the tag. */\n\t} else if (tagPtr->toggleCount == 0) {\n\t    Tcl_Panic(\"TkBTreeCheck found root for \\\"%s\\\" with no toggles\",\n\t\t    tagPtr->name);\n\t} else if (tagPtr->toggleCount & 1) {\n\t    Tcl_Panic(\"TkBTreeCheck found odd toggle count for \\\"%s\\\" (%\" TCL_Z_MODIFIER \"d)\",\n\t\t    tagPtr->name, tagPtr->toggleCount);\n\t}\n\tfor (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t    if (summaryPtr->tagPtr == tagPtr) {\n\t\tTcl_Panic(\"TkBTreeCheck found root node with summary info\");\n\t    }\n\t}\n\tcount = 0;\n\tif (nodePtr->level > 0) {\n\t    for (nodePtr = nodePtr->children.nodePtr ; nodePtr != NULL ;\n\t\t    nodePtr = nodePtr->nextPtr) {\n\t\tfor (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if (summaryPtr->tagPtr == tagPtr) {\n\t\t\tcount += summaryPtr->toggleCount;\n\t\t    }\n\t\t}\n\t    }\n\t} else {\n\t    for (linePtr = nodePtr->children.linePtr ; linePtr != NULL ;\n\t\t    linePtr = linePtr->nextPtr) {\n\t\tfor (segPtr = linePtr->segPtr; segPtr != NULL;\n\t\t\tsegPtr = segPtr->nextPtr) {\n\t\t    if ((segPtr->typePtr == &tkTextToggleOnType ||\n\t\t\t segPtr->typePtr == &tkTextToggleOffType) &&\n\t\t\t segPtr->body.toggle.tagPtr == tagPtr) {\n\t\t\tcount++;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tif (count != tagPtr->toggleCount) {\n\t    Tcl_Panic(\"TkBTreeCheck toggleCount (%\" TCL_Z_MODIFIER \"d) wrong for \\\"%s\\\" should be (%\" TCL_Z_MODIFIER \"d)\",\n\t\t    tagPtr->toggleCount, tagPtr->name, count);\n\t}\n    }\n\n    /*\n     * Call a recursive function to do the main body of checks.\n     */\n\n    nodePtr = treePtr->rootPtr;\n    CheckNodeConsistency(treePtr->rootPtr, treePtr->pixelReferences);\n\n    /*\n     * Make sure that there are at least two lines in the text and that the\n     * last line has no characters except a newline.\n     */\n\n    if (nodePtr->numLines < 2) {\n\tTcl_Panic(\"TkBTreeCheck: less than 2 lines in tree\");\n    }\n    while (nodePtr->level > 0) {\n\tnodePtr = nodePtr->children.nodePtr;\n\twhile (nodePtr->nextPtr != NULL) {\n\t    nodePtr = nodePtr->nextPtr;\n\t}\n    }\n    linePtr = nodePtr->children.linePtr;\n    while (linePtr->nextPtr != NULL) {\n\tlinePtr = linePtr->nextPtr;\n    }\n    segPtr = linePtr->segPtr;\n    while ((segPtr->typePtr == &tkTextToggleOffType)\n\t    || (segPtr->typePtr == &tkTextRightMarkType)\n\t    || (segPtr->typePtr == &tkTextLeftMarkType)) {\n\t/*\n\t * It's OK to toggle a tag off in the last line, but not to start a\n\t * new range. It's also OK to have marks in the last line.\n\t */\n\n\tsegPtr = segPtr->nextPtr;\n    }\n    if (segPtr->typePtr != &tkTextCharType) {\n\tTcl_Panic(\"TkBTreeCheck: last line has bogus segment type\");\n    }\n    if (segPtr->nextPtr != NULL) {\n\tTcl_Panic(\"TkBTreeCheck: last line has too many segments\");\n    }\n    if (segPtr->size != 1) {\n\tTcl_Panic(\"TkBTreeCheck: last line has wrong # characters: % \" TCL_Z_MODIFIER \"d\",\n\t\tsegPtr->size);\n    }\n    if ((segPtr->body.chars[0] != '\\n') || (segPtr->body.chars[1] != 0)) {\n\tTcl_Panic(\"TkBTreeCheck: last line had bad value: %s\",\n\t\tsegPtr->body.chars);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckNodeConsistency --\n *\n *\tThis function is called as part of consistency checking for B-trees:\n *\tit checks several aspects of a node and also runs checks recursively\n *\ton the node's children.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf anything suspicious is found in the tree structure, the function\n *\tpanics.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCheckNodeConsistency(\n    Node *nodePtr,\t/* Node whose subtree should be checked. */\n    int references)\t\t/* Number of referring widgets which have\n\t\t\t\t * pixel counts. */\n{\n    Node *childNodePtr;\n    Summary *summaryPtr, *summaryPtr2;\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    int numChildren, numLines, minChildren, i;\n    int *numPixels;\n    Tcl_Size toggleCount;\n    int pixels[PIXEL_CLIENTS];\n\n    if (nodePtr->parentPtr != NULL) {\n\tminChildren = MIN_CHILDREN;\n    } else if (nodePtr->level > 0) {\n\tminChildren = 2;\n    } else {\n\tminChildren = 1;\n    }\n    if ((nodePtr->numChildren < minChildren)\n\t    || (nodePtr->numChildren > MAX_CHILDREN)) {\n\tTcl_Panic(\"CheckNodeConsistency: bad child count (%d)\",\n\t\tnodePtr->numChildren);\n    }\n\n    numChildren = 0;\n    numLines = 0;\n    if (references > PIXEL_CLIENTS) {\n\tnumPixels = (int *)Tcl_Alloc(sizeof(int) * references);\n    } else {\n\tnumPixels = pixels;\n    }\n    for (i = 0; i<references; i++) {\n\tnumPixels[i] = 0;\n    }\n\n    if (nodePtr->level == 0) {\n\tfor (linePtr = nodePtr->children.linePtr; linePtr != NULL;\n\t\tlinePtr = linePtr->nextPtr) {\n\t    if (linePtr->parentPtr != nodePtr) {\n\t\tTcl_Panic(\"CheckNodeConsistency: line doesn't point to parent\");\n\t    }\n\t    if (linePtr->segPtr == NULL) {\n\t\tTcl_Panic(\"CheckNodeConsistency: line has no segments\");\n\t    }\n\t    for (segPtr = linePtr->segPtr; segPtr != NULL;\n\t\t    segPtr = segPtr->nextPtr) {\n\t\tif (segPtr->typePtr->checkProc != NULL) {\n\t\t    segPtr->typePtr->checkProc(segPtr, linePtr);\n\t\t}\n\t\tif ((segPtr->size == 0) && (!segPtr->typePtr->leftGravity)\n\t\t\t&& (segPtr->nextPtr != NULL)\n\t\t\t&& (segPtr->nextPtr->size == 0)\n\t\t\t&& (segPtr->nextPtr->typePtr->leftGravity)) {\n\t\t    Tcl_Panic(\"CheckNodeConsistency: wrong segment order for gravity\");\n\t\t}\n\t\tif ((segPtr->nextPtr == NULL)\n\t\t\t&& (segPtr->typePtr != &tkTextCharType)) {\n\t\t    Tcl_Panic(\"CheckNodeConsistency: line ended with wrong type\");\n\t\t}\n\t    }\n\t    numChildren++;\n\t    numLines++;\n\t    for (i = 0; i<references; i++) {\n\t\tnumPixels[i] += linePtr->pixels[2 * i];\n\t    }\n\t}\n    } else {\n\tfor (childNodePtr = nodePtr->children.nodePtr; childNodePtr != NULL;\n\t\tchildNodePtr = childNodePtr->nextPtr) {\n\t    if (childNodePtr->parentPtr != nodePtr) {\n\t\tTcl_Panic(\"CheckNodeConsistency: node doesn't point to parent\");\n\t    }\n\t    if (childNodePtr->level != (nodePtr->level-1)) {\n\t\tTcl_Panic(\"CheckNodeConsistency: level mismatch (%\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d)\",\n\t\t\tnodePtr->level, childNodePtr->level);\n\t    }\n\t    CheckNodeConsistency(childNodePtr, references);\n\t    for (summaryPtr = childNodePtr->summaryPtr; summaryPtr != NULL;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\tfor (summaryPtr2 = nodePtr->summaryPtr; ;\n\t\t\tsummaryPtr2 = summaryPtr2->nextPtr) {\n\t\t    if (summaryPtr2 == NULL) {\n\t\t\tif (summaryPtr->tagPtr->tagRootPtr == nodePtr) {\n\t\t\t    break;\n\t\t\t}\n\t\t\tTcl_Panic(\"CheckNodeConsistency: node tag \\\"%s\\\" not %s\",\n\t\t\t\tsummaryPtr->tagPtr->name,\n\t\t\t\t\"present in parent summaries\");\n\t\t    }\n\t\t    if (summaryPtr->tagPtr == summaryPtr2->tagPtr) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t    numChildren++;\n\t    numLines += childNodePtr->numLines;\n\t    for (i = 0; i<references; i++) {\n\t\tnumPixels[i] += childNodePtr->numPixels[i];\n\t    }\n\t}\n    }\n    if (numChildren != nodePtr->numChildren) {\n\tTcl_Panic(\"CheckNodeConsistency: mismatch in numChildren (%d %d)\",\n\t\tnumChildren, nodePtr->numChildren);\n    }\n    if (numLines != nodePtr->numLines) {\n\tTcl_Panic(\"CheckNodeConsistency: mismatch in numLines (%d %d)\",\n\t\tnumLines, nodePtr->numLines);\n    }\n    for (i = 0; i<references; i++) {\n\tif (numPixels[i] != nodePtr->numPixels[i]) {\n\t    Tcl_Panic(\"CheckNodeConsistency: mismatch in numPixels (%d %d) for widget (%d)\",\n\t\t    numPixels[i], nodePtr->numPixels[i], i);\n\t}\n    }\n    if (references > PIXEL_CLIENTS) {\n\tTcl_Free(numPixels);\n    }\n\n    for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t    summaryPtr = summaryPtr->nextPtr) {\n\tif (summaryPtr->tagPtr->toggleCount == summaryPtr->toggleCount) {\n\t    Tcl_Panic(\"CheckNodeConsistency: found unpruned root for \\\"%s\\\"\",\n\t\t    summaryPtr->tagPtr->name);\n\t}\n\ttoggleCount = 0;\n\tif (nodePtr->level == 0) {\n\t    for (linePtr = nodePtr->children.linePtr; linePtr != NULL;\n\t\t    linePtr = linePtr->nextPtr) {\n\t\tfor (segPtr = linePtr->segPtr; segPtr != NULL;\n\t\t\tsegPtr = segPtr->nextPtr) {\n\t\t    if ((segPtr->typePtr != &tkTextToggleOnType)\n\t\t\t    && (segPtr->typePtr != &tkTextToggleOffType)) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    if (segPtr->body.toggle.tagPtr == summaryPtr->tagPtr) {\n\t\t\ttoggleCount++;\n\t\t    }\n\t\t}\n\t    }\n\t} else {\n\t    for (childNodePtr = nodePtr->children.nodePtr;\n\t\t    childNodePtr != NULL;\n\t\t    childNodePtr = childNodePtr->nextPtr) {\n\t\tfor (summaryPtr2 = childNodePtr->summaryPtr;\n\t\t\tsummaryPtr2 != NULL;\n\t\t\tsummaryPtr2 = summaryPtr2->nextPtr) {\n\t\t    if (summaryPtr2->tagPtr == summaryPtr->tagPtr) {\n\t\t\ttoggleCount += summaryPtr2->toggleCount;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tif (toggleCount != summaryPtr->toggleCount) {\n\t    Tcl_Panic(\"CheckNodeConsistency: mismatch in toggleCount (%\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d)\",\n\t\t    toggleCount, summaryPtr->toggleCount);\n\t}\n\tfor (summaryPtr2 = summaryPtr->nextPtr; summaryPtr2 != NULL;\n\t\tsummaryPtr2 = summaryPtr2->nextPtr) {\n\t    if (summaryPtr2->tagPtr == summaryPtr->tagPtr) {\n\t\tTcl_Panic(\"CheckNodeConsistency: duplicated node tag: %s\",\n\t\t\tsummaryPtr->tagPtr->name);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Rebalance --\n *\n *\tThis function is called when a node of a B-tree appears to be out of\n *\tbalance (too many children, or too few). It rebalances that node and\n *\tall of its ancestors in the tree.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe internal structure of treePtr may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRebalance(\n    BTree *treePtr,\t\t/* Tree that is being rebalanced. */\n    Node *nodePtr)\t/* Node that may be out of balance. */\n{\n    /*\n     * Loop over the entire ancestral chain of the node, working up through\n     * the tree one node at a time until the root node has been processed.\n     */\n\n    for ( ; nodePtr != NULL; nodePtr = nodePtr->parentPtr) {\n\tNode *newPtr, *childPtr;\n\tTkTextLine *linePtr;\n\tint i;\n\n\t/*\n\t * Check to see if the node has too many children. If it does, then\n\t * split off all but the first MIN_CHILDREN into a separate node\n\t * following the original one. Then repeat until the node has a decent\n\t * size.\n\t */\n\n\tif (nodePtr->numChildren > MAX_CHILDREN) {\n\t    while (1) {\n\t\t/*\n\t\t * If the node being split is the root node, then make a new\n\t\t * root node above it first.\n\t\t */\n\n\t\tif (nodePtr->parentPtr == NULL) {\n\t\t    newPtr = (Node *)Tcl_Alloc(sizeof(Node));\n\t\t    newPtr->parentPtr = NULL;\n\t\t    newPtr->nextPtr = NULL;\n\t\t    newPtr->summaryPtr = NULL;\n\t\t    newPtr->level = nodePtr->level + 1;\n\t\t    newPtr->children.nodePtr = nodePtr;\n\t\t    newPtr->numChildren = 1;\n\t\t    newPtr->numLines = nodePtr->numLines;\n\t\t    newPtr->numPixels = (int *)\n\t\t\t    Tcl_Alloc(sizeof(int) * treePtr->pixelReferences);\n\t\t    for (i=0; i<treePtr->pixelReferences; i++) {\n\t\t\tnewPtr->numPixels[i] = nodePtr->numPixels[i];\n\t\t    }\n\t\t    RecomputeNodeCounts(treePtr, newPtr);\n\t\t    treePtr->rootPtr = newPtr;\n\t\t}\n\t\tnewPtr = (Node *)Tcl_Alloc(sizeof(Node));\n\t\tnewPtr->numPixels = (int *)\n\t\t\tTcl_Alloc(sizeof(int) * treePtr->pixelReferences);\n\t\tfor (i=0; i<treePtr->pixelReferences; i++) {\n\t\t    newPtr->numPixels[i] = 0;\n\t\t}\n\t\tnewPtr->parentPtr = nodePtr->parentPtr;\n\t\tnewPtr->nextPtr = nodePtr->nextPtr;\n\t\tnodePtr->nextPtr = newPtr;\n\t\tnewPtr->summaryPtr = NULL;\n\t\tnewPtr->level = nodePtr->level;\n\t\tnewPtr->numChildren = nodePtr->numChildren - MIN_CHILDREN;\n\t\tif (nodePtr->level == 0) {\n\t\t    for (i = MIN_CHILDREN-1,\n\t\t\t    linePtr = nodePtr->children.linePtr;\n\t\t\t    i > 0; i--, linePtr = linePtr->nextPtr) {\n\t\t\t/* Empty loop body. */\n\t\t    }\n\t\t    newPtr->children.linePtr = linePtr->nextPtr;\n\t\t    linePtr->nextPtr = NULL;\n\t\t} else {\n\t\t    for (i = MIN_CHILDREN-1,\n\t\t\t    childPtr = nodePtr->children.nodePtr;\n\t\t\t    i > 0; i--, childPtr = childPtr->nextPtr) {\n\t\t\t/* Empty loop body. */\n\t\t    }\n\t\t    newPtr->children.nodePtr = childPtr->nextPtr;\n\t\t    childPtr->nextPtr = NULL;\n\t\t}\n\t\tRecomputeNodeCounts(treePtr, nodePtr);\n\t\tnodePtr->parentPtr->numChildren++;\n\t\tnodePtr = newPtr;\n\t\tif (nodePtr->numChildren <= MAX_CHILDREN) {\n\t\t    RecomputeNodeCounts(treePtr, nodePtr);\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\twhile (nodePtr->numChildren < MIN_CHILDREN) {\n\t    Node *otherPtr;\n\t    Node *halfwayNodePtr = NULL;       /* Initialization needed only */\n\t    TkTextLine *halfwayLinePtr = NULL; /* to prevent cc warnings. */\n\t    int totalChildren, firstChildren;\n\n\t    /*\n\t     * Too few children for this node. If this is the root then, it's\n\t     * OK for it to have less than MIN_CHILDREN children as long as\n\t     * it's got at least two. If it has only one (and isn't at level\n\t     * 0), then chop the root node out of the tree and use its child\n\t     * as the new root.\n\t     */\n\n\t    if (nodePtr->parentPtr == NULL) {\n\t\tif ((nodePtr->numChildren == 1) && (nodePtr->level > 0)) {\n\t\t    treePtr->rootPtr = nodePtr->children.nodePtr;\n\t\t    treePtr->rootPtr->parentPtr = NULL;\n\t\t    DeleteSummaries(nodePtr->summaryPtr);\n\t\t    Tcl_Free(nodePtr->numPixels);\n\t\t    Tcl_Free(nodePtr);\n\t\t}\n\t\treturn;\n\t    }\n\n\t    /*\n\t     * Not the root. Make sure that there are siblings to balance\n\t     * with.\n\t     */\n\n\t    if (nodePtr->parentPtr->numChildren < 2) {\n\t\tRebalance(treePtr, nodePtr->parentPtr);\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * Find a sibling neighbor to borrow from, and arrange for nodePtr\n\t     * to be the earlier of the pair.\n\t     */\n\n\t    if (nodePtr->nextPtr == NULL) {\n\t\tfor (otherPtr = nodePtr->parentPtr->children.nodePtr;\n\t\t\totherPtr->nextPtr != nodePtr;\n\t\t\totherPtr = otherPtr->nextPtr) {\n\t\t    /* Empty loop body. */\n\t\t}\n\t\tnodePtr = otherPtr;\n\t    }\n\t    otherPtr = nodePtr->nextPtr;\n\n\t    /*\n\t     * We're going to either merge the two siblings together into one\n\t     * node or redivide the children among them to balance their\n\t     * loads. As preparation, join their two child lists into a single\n\t     * list and remember the half-way point in the list.\n\t     */\n\n\t    totalChildren = nodePtr->numChildren + otherPtr->numChildren;\n\t    firstChildren = totalChildren/2;\n\t    if (nodePtr->children.nodePtr == NULL) {\n\t\tnodePtr->children = otherPtr->children;\n\t\totherPtr->children.nodePtr = NULL;\n\t\totherPtr->children.linePtr = NULL;\n\t    }\n\t    if (nodePtr->level == 0) {\n\t\tfor (linePtr = nodePtr->children.linePtr, i = 1;\n\t\t\tlinePtr->nextPtr != NULL;\n\t\t\tlinePtr = linePtr->nextPtr, i++) {\n\t\t    if (i == firstChildren) {\n\t\t\thalfwayLinePtr = linePtr;\n\t\t    }\n\t\t}\n\t\tlinePtr->nextPtr = otherPtr->children.linePtr;\n\t\twhile (i <= firstChildren) {\n\t\t    halfwayLinePtr = linePtr;\n\t\t    linePtr = linePtr->nextPtr;\n\t\t    i++;\n\t\t}\n\t    } else {\n\t\tfor (childPtr = nodePtr->children.nodePtr, i = 1;\n\t\t\tchildPtr->nextPtr != NULL;\n\t\t\tchildPtr = childPtr->nextPtr, i++) {\n\t\t    if (i <= firstChildren) {\n\t\t\tif (i == firstChildren) {\n\t\t\t    halfwayNodePtr = childPtr;\n\t\t\t}\n\t\t    }\n\t\t}\n\t\tchildPtr->nextPtr = otherPtr->children.nodePtr;\n\t\twhile (i <= firstChildren) {\n\t\t    halfwayNodePtr = childPtr;\n\t\t    childPtr = childPtr->nextPtr;\n\t\t    i++;\n\t\t}\n\t    }\n\n\t    /*\n\t     * If the two siblings can simply be merged together, do it.\n\t     */\n\n\t    if (totalChildren <= MAX_CHILDREN) {\n\t\tRecomputeNodeCounts(treePtr, nodePtr);\n\t\tnodePtr->nextPtr = otherPtr->nextPtr;\n\t\tnodePtr->parentPtr->numChildren--;\n\t\tDeleteSummaries(otherPtr->summaryPtr);\n\t\tTcl_Free(otherPtr->numPixels);\n\t\tTcl_Free(otherPtr);\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * The siblings can't be merged, so just divide their children\n\t     * evenly between them.\n\t     */\n\n\t    if (nodePtr->level == 0) {\n\t\tCLANG_ASSERT(halfwayLinePtr);\n\t\totherPtr->children.linePtr = halfwayLinePtr->nextPtr;\n\t\thalfwayLinePtr->nextPtr = NULL;\n\t    } else {\n\t\tCLANG_ASSERT(halfwayNodePtr);\n\t\totherPtr->children.nodePtr = halfwayNodePtr->nextPtr;\n\t\thalfwayNodePtr->nextPtr = NULL;\n\t    }\n\t    RecomputeNodeCounts(treePtr, nodePtr);\n\t    RecomputeNodeCounts(treePtr, otherPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RecomputeNodeCounts --\n *\n *\tThis function is called to recompute all the counts in a node (tags,\n *\tchild information, etc.) by scanning the information in its\n *\tdescendants. This function is called during rebalancing when a node's\n *\tchild structure has changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe tag counts for nodePtr are modified to reflect its current child\n *\tstructure, as are its numChildren and numLines fields. Also, all of\n *\tthe childrens' parentPtr fields are made to point to nodePtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRecomputeNodeCounts(\n    BTree *treePtr,\t/* The whole B-tree. */\n    Node *nodePtr)\t/* Node whose tag summary information must be\n\t\t\t\t * recomputed. */\n{\n    Summary *summaryPtr, *summaryPtr2;\n    Node *childPtr;\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    TkTextTag *tagPtr;\n    int ref;\n\n    /*\n     * Zero out all the existing counts for the node, but don't delete the\n     * existing Summary records (most of them will probably be reused).\n     */\n\n    for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL;\n\t    summaryPtr = summaryPtr->nextPtr) {\n\tsummaryPtr->toggleCount = 0;\n    }\n    nodePtr->numChildren = 0;\n    nodePtr->numLines = 0;\n    for (ref = 0; ref<treePtr->pixelReferences; ref++) {\n\tnodePtr->numPixels[ref] = 0;\n    }\n\n    /*\n     * Scan through the children, adding the childrens' tag counts into the\n     * node's tag counts and adding new Summary structures if necessary.\n     */\n\n    if (nodePtr->level == 0) {\n\tfor (linePtr = nodePtr->children.linePtr; linePtr != NULL;\n\t\tlinePtr = linePtr->nextPtr) {\n\t    nodePtr->numChildren++;\n\t    nodePtr->numLines++;\n\t    for (ref = 0; ref<treePtr->pixelReferences; ref++) {\n\t\tnodePtr->numPixels[ref] += linePtr->pixels[2 * ref];\n\t    }\n\t    linePtr->parentPtr = nodePtr;\n\t    for (segPtr = linePtr->segPtr; segPtr != NULL;\n\t\t    segPtr = segPtr->nextPtr) {\n\t\tif (((segPtr->typePtr != &tkTextToggleOnType)\n\t\t\t&& (segPtr->typePtr != &tkTextToggleOffType))\n\t\t\t|| !(segPtr->body.toggle.inNodeCounts)) {\n\t\t    continue;\n\t\t}\n\t\ttagPtr = segPtr->body.toggle.tagPtr;\n\t\tfor (summaryPtr = nodePtr->summaryPtr; ;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if (summaryPtr == NULL) {\n\t\t\tsummaryPtr = (Summary *)Tcl_Alloc(sizeof(Summary));\n\t\t\tsummaryPtr->tagPtr = tagPtr;\n\t\t\tsummaryPtr->toggleCount = 1;\n\t\t\tsummaryPtr->nextPtr = nodePtr->summaryPtr;\n\t\t\tnodePtr->summaryPtr = summaryPtr;\n\t\t\tbreak;\n\t\t    }\n\t\t    if (summaryPtr->tagPtr == tagPtr) {\n\t\t\tsummaryPtr->toggleCount++;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    } else {\n\tfor (childPtr = nodePtr->children.nodePtr; childPtr != NULL;\n\t\tchildPtr = childPtr->nextPtr) {\n\t    nodePtr->numChildren++;\n\t    nodePtr->numLines += childPtr->numLines;\n\t    for (ref = 0; ref<treePtr->pixelReferences; ref++) {\n\t\tnodePtr->numPixels[ref] += childPtr->numPixels[ref];\n\t    }\n\t    childPtr->parentPtr = nodePtr;\n\t    for (summaryPtr2 = childPtr->summaryPtr; summaryPtr2 != NULL;\n\t\t    summaryPtr2 = summaryPtr2->nextPtr) {\n\t\tfor (summaryPtr = nodePtr->summaryPtr; ;\n\t\t\tsummaryPtr = summaryPtr->nextPtr) {\n\t\t    if (summaryPtr == NULL) {\n\t\t\tsummaryPtr = (Summary *)Tcl_Alloc(sizeof(Summary));\n\t\t\tsummaryPtr->tagPtr = summaryPtr2->tagPtr;\n\t\t\tsummaryPtr->toggleCount = summaryPtr2->toggleCount;\n\t\t\tsummaryPtr->nextPtr = nodePtr->summaryPtr;\n\t\t\tnodePtr->summaryPtr = summaryPtr;\n\t\t\tbreak;\n\t\t    }\n\t\t    if (summaryPtr->tagPtr == summaryPtr2->tagPtr) {\n\t\t\tsummaryPtr->toggleCount += summaryPtr2->toggleCount;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Scan through the node's tag records again and delete any Summary\n     * records that still have a zero count, or that have all the toggles.\n     * The node with the children that account for all the tags toggles have\n     * no summary information, and they become the tagRootPtr for the tag.\n     */\n\n    summaryPtr2 = NULL;\n    for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; ) {\n\tif (summaryPtr->toggleCount > 0 &&\n\t\tsummaryPtr->toggleCount < summaryPtr->tagPtr->toggleCount) {\n\t    if (nodePtr->level == summaryPtr->tagPtr->tagRootPtr->level) {\n\t\t/*\n\t\t * The tag's root node split and some toggles left. The tag\n\t\t * root must move up a level.\n\t\t */\n\n\t\tsummaryPtr->tagPtr->tagRootPtr = nodePtr->parentPtr;\n\t    }\n\t    summaryPtr2 = summaryPtr;\n\t    summaryPtr = summaryPtr->nextPtr;\n\t    continue;\n\t}\n\tif (summaryPtr->toggleCount == summaryPtr->tagPtr->toggleCount) {\n\t    /*\n\t     * A node merge has collected all the toggles under one node. Push\n\t     * the root down to this level.\n\t     */\n\n\t    summaryPtr->tagPtr->tagRootPtr = nodePtr;\n\t}\n\tif (summaryPtr2 != NULL) {\n\t    summaryPtr2->nextPtr = summaryPtr->nextPtr;\n\t    Tcl_Free(summaryPtr);\n\t    summaryPtr = summaryPtr2->nextPtr;\n\t} else {\n\t    nodePtr->summaryPtr = summaryPtr->nextPtr;\n\t    Tcl_Free(summaryPtr);\n\t    summaryPtr = nodePtr->summaryPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeNumLines --\n *\n *\tThis function returns a count of the number of logical lines of text\n *\tpresent in a given B-tree.\n *\n * Results:\n *\tThe return value is a count of the number of usable lines in tree\n *\t(i.e. it doesn't include the dummy line that is just used to mark the\n *\tend of the tree).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkBTreeNumLines(\n    TkTextBTree tree,\t\t/* Information about tree. */\n    const TkText *textPtr)\t/* Relative to this client of the B-tree. */\n{\n    BTree *treePtr = (BTree *) tree;\n    Tcl_Size count;\n\n    if (textPtr != NULL && textPtr->end != NULL) {\n\tcount = TkBTreeLinesTo(NULL, textPtr->end);\n    } else {\n\tcount = treePtr->rootPtr->numLines - 1;\n    }\n    if (textPtr != NULL && textPtr->start != NULL) {\n\tcount -= TkBTreeLinesTo(NULL, textPtr->start);\n    }\n\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkBTreeNumPixels --\n *\n *\tThis function returns a count of the number of pixels of text present\n *\tin a given widget's B-tree representation.\n *\n * Results:\n *\tThe return value is a count of the number of usable pixels in tree\n *\t(since the dummy line used to mark the end of the B-tree is maintained\n *\twith zero height, as are any lines that are before or after the\n *\t'-start -end' range of the text widget in question, the number stored\n *\tat the root is the number we want).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkBTreeNumPixels(\n    TkTextBTree tree,\t\t/* The B-tree. */\n    const TkText *textPtr)\t/* Relative to this client of the B-tree. */\n{\n    BTree *treePtr = (BTree *) tree;\n    return treePtr->rootPtr->numPixels[textPtr->pixelReference];\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharSplitProc --\n *\n *\tThis function implements splitting for character segments.\n *\n * Results:\n *\tThe return value is a pointer to a chain of two segments that have the\n *\tsame characters as segPtr except split among the two segments.\n *\n * Side effects:\n *\tStorage for segPtr is freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nCharSplitProc(\n    TkTextSegment *segPtr,\t/* Pointer to segment to split. */\n    Tcl_Size index)\t\t\t/* Position within segment at which to\n\t\t\t\t * split. */\n{\n    TkTextSegment *newPtr1, *newPtr2;\n\n    newPtr1 = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(index));\n    newPtr2 = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(segPtr->size - index));\n    newPtr1->typePtr = &tkTextCharType;\n    newPtr1->nextPtr = newPtr2;\n    newPtr1->size = index;\n    memcpy(newPtr1->body.chars, segPtr->body.chars, index);\n    newPtr1->body.chars[index] = 0;\n    newPtr2->typePtr = &tkTextCharType;\n    newPtr2->nextPtr = segPtr->nextPtr;\n    newPtr2->size = segPtr->size - index;\n    memcpy(newPtr2->body.chars, segPtr->body.chars + index, newPtr2->size);\n    newPtr2->body.chars[newPtr2->size] = 0;\n    Tcl_Free(segPtr);\n    return newPtr1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharCleanupProc --\n *\n *\tThis function merges adjacent character segments into a single\n *\tcharacter segment, if possible.\n *\n * Results:\n *\tThe return value is a pointer to the first segment in the (new) list\n *\tof segments that used to start with segPtr.\n *\n * Side effects:\n *\tStorage for the segments may be allocated and freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nCharCleanupProc(\n    TkTextSegment *segPtr,\t/* Pointer to first of two adjacent segments\n\t\t\t\t * to join. */\n    TCL_UNUSED(TkTextLine *))\t/* Line containing segments (not used). */\n{\n    TkTextSegment *segPtr2, *newPtr;\n\n    segPtr2 = segPtr->nextPtr;\n    if ((segPtr2 == NULL) || (segPtr2->typePtr != &tkTextCharType)) {\n\treturn segPtr;\n    }\n    newPtr = (TkTextSegment *)Tcl_Alloc(CSEG_SIZE(segPtr->size + segPtr2->size));\n    newPtr->typePtr = &tkTextCharType;\n    newPtr->nextPtr = segPtr2->nextPtr;\n    newPtr->size = segPtr->size + segPtr2->size;\n    memcpy(newPtr->body.chars, segPtr->body.chars, segPtr->size);\n    memcpy(newPtr->body.chars + segPtr->size, segPtr2->body.chars, segPtr2->size);\n    newPtr->body.chars[newPtr->size] = 0;\n    Tcl_Free(segPtr);\n    Tcl_Free(segPtr2);\n    return newPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharDeleteProc --\n *\n *\tThis function is invoked to delete a character segment.\n *\n * Results:\n *\tAlways returns 0 to indicate that the segment was deleted.\n *\n * Side effects:\n *\tStorage for the segment is freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nCharDeleteProc(\n    TkTextSegment *segPtr,\t/* Segment to delete. */\n    TCL_UNUSED(TkTextLine *),\t/* Line containing segment. */\n    TCL_UNUSED(int))\t\t/* Non-zero means the entire tree is being\n\t\t\t\t * deleted, so everything must get cleaned\n\t\t\t\t * up. */\n{\n    Tcl_Free(segPtr);\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharCheckProc --\n *\n *\tThis function is invoked to perform consistency checks on character\n *\tsegments.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf the segment isn't inconsistent then the function panics.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCharCheckProc(\n    TkTextSegment *segPtr,\t/* Segment to check. */\n    TCL_UNUSED(TkTextLine *))\t/* Line containing segment. */\n{\n    /*\n     * Make sure that the segment contains the number of characters indicated\n     * by its header, and that the last segment in a line ends in a newline.\n     * Also make sure that there aren't ever two character segments adjacent\n     * to each other: they should be merged together.\n     */\n\n    if (segPtr->size + 1 <= 1) {\n\tTcl_Panic(\"CharCheckProc: segment has size <= 0\");\n    }\n    if (strlen(segPtr->body.chars) != (size_t)segPtr->size) {\n\tTcl_Panic(\"CharCheckProc: segment has wrong size\");\n    }\n    if (segPtr->nextPtr == NULL) {\n\tif (segPtr->body.chars[segPtr->size-1] != '\\n') {\n\t    Tcl_Panic(\"CharCheckProc: line doesn't end with newline\");\n\t}\n    } else if (segPtr->nextPtr->typePtr == &tkTextCharType) {\n\tTcl_Panic(\"CharCheckProc: adjacent character segments weren't merged\");\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ToggleDeleteProc --\n *\n *\tThis function is invoked to delete toggle segments.\n *\n * Results:\n *\tReturns 1 to indicate that the segment may not be deleted, unless the\n *\tentire B-tree is going away.\n *\n * Side effects:\n *\tIf the tree is going away then the toggle's memory is freed; otherwise\n *\tthe toggle counts in nodes above the segment get updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nToggleDeleteProc(\n    TkTextSegment *segPtr,\t/* Segment to check. */\n    TkTextLine *linePtr,\t/* Line containing segment. */\n    int treeGone)\t\t/* Non-zero means the entire tree is being\n\t\t\t\t * deleted, so everything must get cleaned\n\t\t\t\t * up. */\n{\n    if (treeGone) {\n\tTcl_Free(segPtr);\n\treturn 0;\n    }\n\n    /*\n     * This toggle is in the middle of a range of characters that's being\n     * deleted. Refuse to die. We'll be moved to the end of the deleted range\n     * and our cleanup function will be called later. Decrement node toggle\n     * counts here, and set a flag so we'll re-increment them in the cleanup\n     * function.\n     */\n\n    if (segPtr->body.toggle.inNodeCounts) {\n\tChangeNodeToggleCount(linePtr->parentPtr,\n\t\tsegPtr->body.toggle.tagPtr, -1);\n\tsegPtr->body.toggle.inNodeCounts = false;\n    }\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ToggleCleanupProc --\n *\n *\tThis function is called when a toggle is part of a line that's been\n *\tmodified in some way. It's invoked after the modifications are\n *\tcomplete.\n *\n * Results:\n *\tThe return value is the head segment in a new list that is to replace\n *\tthe tail of the line that used to start at segPtr. This allows the\n *\tfunction to delete or modify segPtr.\n *\n * Side effects:\n *\tToggle counts in the nodes above the new line will be updated if\n *\tthey're not already. Toggles may be collapsed if there are duplicate\n *\ttoggles at the same position.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nToggleCleanupProc(\n    TkTextSegment *segPtr,\t/* Segment to check. */\n    TkTextLine *linePtr)\t/* Line that now contains segment. */\n{\n    TkTextSegment *segPtr2, *prevPtr;\n    int counts;\n\n    /*\n     * If this is a toggle-off segment, look ahead through the next segments\n     * to see if there's a toggle-on segment for the same tag before any\n     * segments with non-zero size. If so then the two toggles cancel each\n     * other; remove them both.\n     */\n\n    if (segPtr->typePtr == &tkTextToggleOffType) {\n\tfor (prevPtr = segPtr, segPtr2 = prevPtr->nextPtr;\n\t\t(segPtr2 != NULL) && (segPtr2->size == 0);\n\t\tprevPtr = segPtr2, segPtr2 = prevPtr->nextPtr) {\n\t    if (segPtr2->typePtr != &tkTextToggleOnType) {\n\t\tcontinue;\n\t    }\n\t    if (segPtr2->body.toggle.tagPtr != segPtr->body.toggle.tagPtr) {\n\t\tcontinue;\n\t    }\n\t    counts = (segPtr->body.toggle.inNodeCounts ? 1 : 0)\n\t\t    + (segPtr2->body.toggle.inNodeCounts ? 1 : 0);\n\t    if (counts != 0) {\n\t\tChangeNodeToggleCount(linePtr->parentPtr,\n\t\t\tsegPtr->body.toggle.tagPtr, -counts);\n\t    }\n\t    prevPtr->nextPtr = segPtr2->nextPtr;\n\t    Tcl_Free(segPtr2);\n\t    segPtr2 = segPtr->nextPtr;\n\t    Tcl_Free(segPtr);\n\t    return segPtr2;\n\t}\n    }\n\n    if (!segPtr->body.toggle.inNodeCounts) {\n\tChangeNodeToggleCount(linePtr->parentPtr,\n\t\tsegPtr->body.toggle.tagPtr, 1);\n\tsegPtr->body.toggle.inNodeCounts = true;\n    }\n    return segPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ToggleLineChangeProc --\n *\n *\tThis function is invoked when a toggle segment is about to move from\n *\tone line to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tToggle counts are decremented in the nodes above the line.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nToggleLineChangeProc(\n    TkTextSegment *segPtr,\t/* Segment to check. */\n    TkTextLine *linePtr)\t/* Line that used to contain segment. */\n{\n    if (segPtr->body.toggle.inNodeCounts) {\n\tChangeNodeToggleCount(linePtr->parentPtr,\n\t\tsegPtr->body.toggle.tagPtr, -1);\n\tsegPtr->body.toggle.inNodeCounts = false;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ToggleCheckProc --\n *\n *\tThis function is invoked to perform consistency checks on toggle\n *\tsegments.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf a consistency problem is found the function panics.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nToggleCheckProc(\n    TkTextSegment *segPtr,\t/* Segment to check. */\n    TkTextLine *linePtr)\t/* Line containing segment. */\n{\n    Summary *summaryPtr;\n    bool needSummary;\n\n    if (segPtr->size != 0) {\n\tTcl_Panic(\"ToggleCheckProc: segment had non-zero size\");\n    }\n    if (!segPtr->body.toggle.inNodeCounts) {\n\tTcl_Panic(\"ToggleCheckProc: toggle counts not updated in nodes\");\n    }\n    needSummary = (segPtr->body.toggle.tagPtr->tagRootPtr!=linePtr->parentPtr);\n    for (summaryPtr = linePtr->parentPtr->summaryPtr; ;\n\t    summaryPtr = summaryPtr->nextPtr) {\n\tif (summaryPtr == NULL) {\n\t    if (needSummary) {\n\t\tTcl_Panic(\"ToggleCheckProc: tag not present in node\");\n\t    } else {\n\t\tbreak;\n\t    }\n\t}\n\tif (summaryPtr->tagPtr == segPtr->body.toggle.tagPtr) {\n\t    if (!needSummary) {\n\t\tTcl_Panic(\"ToggleCheckProc: tag present in root node summary\");\n\t    }\n\t    break;\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextDisp.c",
    "content": "/*\n * tkTextDisp.c --\n *\n *\tThis module provides facilities to display text widgets. It is the\n *\tonly place where information is kept about the screen layout of text\n *\twidgets. (Well, strictly, each TkTextLine and B-tree node caches its\n *\tlast observed pixel height, but that information originates here).\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkText.h\"\n#include \"tk3d.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif defined(__CYGWIN__)\n#include \"tkUnixInt.h\"\n#elif defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#endif\n\n/*\n * \"Calculations of line pixel heights and the size of the vertical\n * scrollbar.\"\n *\n * Given that tag, font and elide changes can happen to large numbers of\n * diverse chunks in a text widget containing megabytes of text, it is not\n * possible to recalculate all affected height information immediately any\n * such change takes place and maintain a responsive user-experience. Yet, for\n * an accurate vertical scrollbar to be drawn, we must know the total number\n * of vertical pixels shown on display versus the number available to be\n * displayed.\n *\n * The way the text widget solves this problem is by maintaining cached line\n * pixel heights (in the BTree for each logical line), and having asynchronous\n * timer callbacks (i) to iterate through the logical lines recalculating\n * their heights, and (ii) to recalculate the vertical scrollbar's position\n * and size.\n *\n * Typically this works well but there are some situations where the overall\n * functional design of this file causes some problems. These problems can\n * only arise because the calculations used to display lines on screen are not\n * connected to those in the iterating-line- recalculation-process.\n *\n * The reason for this disconnect is that the display calculations operate in\n * display lines, and the iteration and cache operates in logical lines.\n * Given that the display calculations both need not contain complete logical\n * lines (at top or bottom of display), and that they do not actually keep\n * track of logical lines (for simplicity of code and historical design), this\n * means a line may be known and drawn with a different pixel height to that\n * which is cached in the BTree, and this might cause some temporary\n * undesirable mismatch between display and the vertical scrollbar.\n *\n * All such mismatches should be temporary, however, since the asynchronous\n * height calculations will always catch up eventually.\n *\n * For further details see the comments before and within the following\n * functions below: LayoutDLine, AsyncUpdateLineMetrics, GetYView,\n * GetYPixelCount, TkTextUpdateOneLine, TkTextUpdateLineMetrics.\n *\n * For details of the way in which the BTree keeps track of pixel heights, see\n * tkTextBTree.c. Basically the BTree maintains two pieces of information: the\n * logical line indices and the pixel height cache.\n */\n\n/*\n * TK_LAYOUT_WITH_BASE_CHUNKS:\n *\n *\tWith this macro set, collect all char chunks that have no holes\n *\tbetween them, that are on the same line and use the same font and font\n *\tsize. Allocate the chars of all these chunks, the so-called \"stretch\",\n *\tin a DString in the first chunk, the so-called \"base chunk\". Use the\n *\tbase chunk string for measuring and drawing, so that these actions are\n *\talways performed with maximum context.\n *\n *\tThis is necessary for text rendering engines that provide ligatures\n *\tand sub-pixel layout, like ATSU on macOS. If we don't do this, the\n *\tmeasuring will change all the time, leading to an ugly \"tremble and\n *\tshiver\" effect. This is because of the continuous splitting and\n *\tre-merging of chunks that goes on in a text widget, when the cursor or\n *\tthe selection move.\n *\n * Side effects:\n *\n *\tMemory management changes. Instead of attaching the character data to\n *\tthe clientData structures of the char chunks, an additional DString is\n *\tused. The collection process will even lead to resizing this DString\n *\tfor large stretches (> TCL_DSTRING_STATIC_SIZE == 200). We could\n *\treduce the overall memory footprint by copying the result to a plain\n *\tchar array after the line breaking process, but that would complicate\n *\tthe code and make performance even worse speedwise. See also TODOs.\n *\n * TODOs:\n *\n *    -\tMove the character collection process from the LayoutProc into\n *\tLayoutDLine(), so that the collection can be done before actual\n *\tlayout. In this way measuring can look at the following text, too,\n *\tright from the beginning. Memory handling can also be improved with\n *\tthis. Problem: We don't easily know which chunks are adjacent until\n *\tall the other chunks have calculated their width. Apparently marks\n *\twould return width==0. A separate char collection loop would have to\n *\tknow these things.\n *\n *    -\tUse a new context parameter to pass the context from LayoutDLine() to\n *\tthe LayoutProc instead of using a global variable like now. Not\n *\tpressing until the previous point gets implemented.\n */\n\n/*\n * The following structure describes how to display a range of characters.\n * The information is generated by scanning all of the tags associated with\n * the characters and combining that with default information for the overall\n * widget. These structures form the hash keys for dInfoPtr->styleTable.\n */\n\ntypedef struct StyleValues {\n    Tk_3DBorder border;\t\t/* Used for drawing background under text.\n\t\t\t\t * NULL means use widget background. */\n    int borderWidth;\t\t/* Width of 3-D border for background. */\n    int relief;\t\t\t/* 3-D relief for background. */\n    Pixmap bgStipple;\t\t/* Stipple bitmap for background. None means\n\t\t\t\t * draw solid. */\n    XColor *fgColor;\t\t/* Foreground color for text. */\n    Tk_Font tkfont;\t\t/* Font for displaying text. */\n    Pixmap fgStipple;\t\t/* Stipple bitmap for text and other\n\t\t\t\t * foreground stuff. None means draw solid.*/\n    int justify;\t\t/* Justification style for text. */\n    int lMargin1;\t\t/* Left margin, in pixels, for first display\n\t\t\t\t * line of each text line. */\n    int lMargin2;\t\t/* Left margin, in pixels, for second and\n\t\t\t\t * later display lines of each text line. */\n    Tk_3DBorder lMarginColor;\t/* Color of left margins (1 and 2). */\n    int offset;\t\t\t/* Offset in pixels of baseline, relative to\n\t\t\t\t * baseline of line. */\n    int overstrike;\t\t/* Non-zero means draw overstrike through\n\t\t\t\t * text. */\n    XColor *overstrikeColor;\t/* Foreground color for overstrike through\n\t\t\t\t * text. */\n    int rMargin;\t\t/* Right margin, in pixels. */\n    Tk_3DBorder rMarginColor;\t/* Color of right margin. */\n    int spacing1;\t\t/* Spacing above first dline in text line. */\n    int spacing2;\t\t/* Spacing between lines of dline. */\n    int spacing3;\t\t/* Spacing below last dline in text line. */\n    TkTextTabArray *tabArrayPtr;/* Locations and types of tab stops (may be\n\t\t\t\t * NULL). */\n    TkTextTabStyle tabStyle;\t/* One of TK_TEXT_TABSTYLE_TABULAR\n\t\t\t\t * or TK_TEXT_TABSTYLE_WORDPROCESSOR. */\n    int underline;\t\t/* Non-zero means draw underline underneath\n\t\t\t\t * text. */\n    XColor *underlineColor;\t/* Foreground color for underline underneath\n\t\t\t\t * text. */\n    int elide;\t\t\t/* Zero means draw text, otherwise not. */\n    TkWrapMode wrapMode;\t/* How to handle wrap-around for this tag.\n\t\t\t\t * One of TEXT_WRAPMODE_CHAR,\n\t\t\t\t * TEXT_WRAPMODE_NONE or TEXT_WRAPMODE_WORD.*/\n} StyleValues;\n\n/*\n * The following structure extends the StyleValues structure above with\n * graphics contexts used to actually draw the characters. The entries in\n * dInfoPtr->styleTable point to structures of this type.\n */\n\ntypedef struct TextStyle {\n    Tcl_Size refCount;\t\t/* Number of times this structure is\n\t\t\t\t * referenced in Chunks. */\n    GC bgGC;\t\t\t/* Graphics context for background. None means\n\t\t\t\t * use widget background. */\n    GC fgGC;\t\t\t/* Graphics context for foreground. */\n    GC ulGC;\t\t\t/* Graphics context for underline. */\n    GC ovGC;\t\t\t/* Graphics context for overstrike. */\n    StyleValues *sValuePtr;\t/* Raw information from which GCs were\n\t\t\t\t * derived. */\n    Tcl_HashEntry *hPtr;\t/* Pointer to entry in styleTable. Used to\n\t\t\t\t * delete entry. */\n} TextStyle;\n\n/*\n * The following macro determines whether two styles have the same background\n * so that, for example, no beveled border should be drawn between them.\n */\n\n#define SAME_BACKGROUND(s1, s2) \\\n    (((s1)->sValuePtr->border == (s2)->sValuePtr->border) \\\n\t&& ((s1)->sValuePtr->borderWidth == (s2)->sValuePtr->borderWidth) \\\n\t&& ((s1)->sValuePtr->relief == (s2)->sValuePtr->relief) \\\n\t&& ((s1)->sValuePtr->bgStipple == (s2)->sValuePtr->bgStipple))\n\n/*\n * The following macro is used to compare two floating-point numbers to within\n * a certain degree of scale. Direct comparison fails on processors where the\n * processor and memory representations of FP numbers of a particular\n * precision is different (e.g. Intel)\n */\n\n#define FP_EQUAL_SCALE(double1, double2, scaleFactor) \\\n    (fabs((double1)-(double2))*((scaleFactor)+1.0) < 0.3)\n\n/*\n * Macros to make debugging/testing logging a little easier.\n */\n\n#define LOG(toVar,what)\t\t\t\t\t\t\t\\\n    Tcl_SetVar2(textPtr->interp, toVar, NULL, (what),\t\t\t\\\n\t\tTCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT)\n#define CLEAR(var)\t\t\t\t\t\t\t\\\n    Tcl_SetVar2(interp, var, NULL, \"\", TCL_GLOBAL_ONLY)\n\n/*\n * The following structure describes one line of the display, which may be\n * either part or all of one line of the text.\n */\n\ntypedef struct DLine {\n    TkTextIndex index;\t\t/* Identifies first character in text that is\n\t\t\t\t * displayed on this line. */\n    Tcl_Size byteCount;\t\t/* Number of bytes accounted for by this\n\t\t\t\t * display line, including a trailing space or\n\t\t\t\t * newline that isn't actually displayed. */\n    int logicalLinesMerged;\t/* Number of extra logical lines merged into\n\t\t\t\t * this one due to elided newlines. */\n    int y;\t\t\t/* Y-position at which line is supposed to be\n\t\t\t\t * drawn (topmost pixel of rectangular area\n\t\t\t\t * occupied by line). */\n    int oldY;\t\t\t/* Y-position at which line currently appears\n\t\t\t\t * on display. This is used to move lines by\n\t\t\t\t * scrolling rather than re-drawing. If\n\t\t\t\t * 'flags' have the OLD_Y_INVALID bit set,\n\t\t\t\t * then we will never examine this field\n\t\t\t\t * (which means line isn't currently visible\n\t\t\t\t * on display and must be redrawn). */\n    int height;\t\t\t/* Height of line, in pixels. */\n    int baseline;\t\t/* Offset of text baseline from y, in\n\t\t\t\t * pixels. */\n    int spaceAbove;\t\t/* How much extra space was added to the top\n\t\t\t\t * of the line because of spacing options.\n\t\t\t\t * This is included in height and baseline. */\n    int spaceBelow;\t\t/* How much extra space was added to the\n\t\t\t\t * bottom of the line because of spacing\n\t\t\t\t * options. This is included in height. */\n    Tk_3DBorder lMarginColor;\t/* Background color of the area corresponding\n\t\t\t\t * to the left margin of the display line. */\n    int lMarginWidth;\t\t/* Pixel width of the area corresponding to\n\t\t\t\t * the left margin. */\n    Tk_3DBorder rMarginColor;\t/* Background color of the area corresponding\n\t\t\t\t * to the right margin of the display line. */\n    int rMarginWidth;\t\t/* Pixel width of the area corresponding to\n\t\t\t\t * the right margin. */\n    int length;\t\t\t/* Total length of line, in pixels. */\n    TkTextDispChunk *chunkPtr;\t/* Pointer to first chunk in list of all of\n\t\t\t\t * those that are displayed on this line of\n\t\t\t\t * the screen. */\n    struct DLine *nextPtr;\t/* Next in list of all display lines for this\n\t\t\t\t * window. The list is sorted in order from\n\t\t\t\t * top to bottom. Note: the next DLine doesn't\n\t\t\t\t * always correspond to the next line of text:\n\t\t\t\t * (a) can have multiple DLines for one text\n\t\t\t\t * line (wrapping), (b) can have elided newlines,\n\t\t\t\t * and (c) can have gaps where DLine's\n\t\t\t\t * have been deleted because they're out of\n\t\t\t\t * date. */\n    int flags;\t\t\t/* Various flag bits: see below for values. */\n} DLine;\n\n/*\n * Flag bits for DLine structures:\n *\n * HAS_3D_BORDER -\t\tNon-zero means that at least one of the chunks\n *\t\t\t\tin this line has a 3D border, so it\n *\t\t\t\tpotentially interacts with 3D borders in\n *\t\t\t\tneighboring lines (see DisplayLineBackground).\n * NEW_LAYOUT -\t\t\tNon-zero means that the line has been\n *\t\t\t\tre-layed out since the last time the display\n *\t\t\t\twas updated.\n * TOP_LINE -\t\t\tNon-zero means that this was the top line in\n *\t\t\t\tin the window the last time that the window\n *\t\t\t\twas laid out. This is important because a line\n *\t\t\t\tmay be displayed differently if it's at the top\n *\t\t\t\tor bottom than if it's in the middle\n *\t\t\t\t(e.g. beveled edges aren't displayed for\n *\t\t\t\tmiddle lines if the adjacent line has a\n *\t\t\t\tsimilar background).\n * BOTTOM_LINE -\t\tNon-zero means that this was the bottom line\n *\t\t\t\tin the window the last time that the window\n *\t\t\t\twas laid out.\n * OLD_Y_INVALID -\t\tThe value of oldY in the structure is not\n *\t\t\t\tvalid or useful and should not be examined.\n *\t\t\t\t'oldY' is only useful when the DLine is\n *\t\t\t\tcurrently displayed at a different position\n *\t\t\t\tand we wish to re-display it via scrolling, so\n *\t\t\t\tthis means the DLine needs redrawing.\n */\n\n#define HAS_3D_BORDER\t1\n#define NEW_LAYOUT\t2\n#define TOP_LINE\t4\n#define BOTTOM_LINE\t8\n#define OLD_Y_INVALID  16\n\n/*\n * Overall display information for a text widget:\n */\n\ntypedef struct TextDInfo {\n    Tcl_HashTable styleTable;\t/* Hash table that maps from StyleValues to\n\t\t\t\t * TextStyles for this widget. */\n    DLine *dLinePtr;\t\t/* First in list of all display lines for this\n\t\t\t\t * widget, in order from top to bottom. */\n    int topPixelOffset;\t\t/* Identifies first pixel in top display line\n\t\t\t\t * to display in window. */\n    int newTopPixelOffset;\t/* Desired first pixel in top display line to\n\t\t\t\t * display in window. */\n    GC copyGC;\t\t\t/* Graphics context for copying from off-\n\t\t\t\t * screen pixmaps onto screen. */\n    GC scrollGC;\t\t/* Graphics context for copying from one place\n\t\t\t\t * in the window to another (scrolling):\n\t\t\t\t * differs from copyGC in that we need to get\n\t\t\t\t * GraphicsExpose events. */\n    int x;\t\t\t/* First x-coordinate that may be used for\n\t\t\t\t * actually displaying line information.\n\t\t\t\t * Leaves space for border, etc. */\n    int y;\t\t\t/* First y-coordinate that may be used for\n\t\t\t\t * actually displaying line information.\n\t\t\t\t * Leaves space for border, etc. */\n    int maxX;\t\t\t/* First x-coordinate to right of available\n\t\t\t\t * space for displaying lines. */\n    int maxY;\t\t\t/* First y-coordinate below available space\n\t\t\t\t * for displaying lines. */\n    int topOfEof;\t\t/* Top-most pixel (lowest y-value) that has\n\t\t\t\t * been drawn in the appropriate fashion for\n\t\t\t\t * the portion of the window after the last\n\t\t\t\t * line of the text. This field is used to\n\t\t\t\t * figure out when to redraw part or all of\n\t\t\t\t * the eof field. */\n\n    /*\n     * Information used for scrolling:\n     */\n\n    int newXPixelOffset;\t/* Desired x scroll position, measured as the\n\t\t\t\t * number of pixels off-screen to the left for\n\t\t\t\t * a line with no left margin. */\n    int curXPixelOffset;\t/* Actual x scroll position, measured as the\n\t\t\t\t * number of pixels off-screen to the left. */\n    int maxLength;\t\t/* Length in pixels of longest line that's\n\t\t\t\t * visible in window (length may exceed window\n\t\t\t\t * size). If there's no wrapping, this will be\n\t\t\t\t * zero. */\n    double xScrollFirst, xScrollLast;\n\t\t\t\t/* Most recent values reported to horizontal\n\t\t\t\t * scrollbar; used to eliminate unnecessary\n\t\t\t\t * reports. */\n    double yScrollFirst, yScrollLast;\n\t\t\t\t/* Most recent values reported to vertical\n\t\t\t\t * scrollbar; used to eliminate unnecessary\n\t\t\t\t * reports. */\n\n    /*\n     * The following information is used to implement scanning:\n     */\n\n    int scanMarkXPixel;\t\t/* Pixel index of left edge of the window when\n\t\t\t\t * the scan started. */\n    int scanMarkX;\t\t/* X-position of mouse at time scan started. */\n    int scanTotalYScroll;\t/* Total scrolling (in screen pixels) that has\n\t\t\t\t * occurred since scanMarkY was set. */\n    int scanMarkY;\t\t/* Y-position of mouse at time scan started. */\n\n    /*\n     * Miscellaneous information:\n     */\n\n    int dLinesInvalidated;\t/* This value is set to 1 whenever something\n\t\t\t\t * happens that invalidates information in\n\t\t\t\t * DLine structures; if a redisplay is in\n\t\t\t\t * progress, it will see this and abort the\n\t\t\t\t * redisplay. This is needed because, for\n\t\t\t\t * example, an embedded window could change\n\t\t\t\t * its size when it is first displayed,\n\t\t\t\t * invalidating the DLine that is currently\n\t\t\t\t * being displayed. If redisplay continues, it\n\t\t\t\t * will use freed memory and could dump\n\t\t\t\t * core. */\n    int flags;\t\t\t/* Various flag values: see below for\n\t\t\t\t * definitions. */\n    /*\n     * Information used to handle the asynchronous updating of the y-scrollbar\n     * and the vertical height calculations:\n     */\n\n    int lineMetricUpdateEpoch;\t/* Stores a number which is incremented each\n\t\t\t\t * time the text widget changes in a\n\t\t\t\t * significant way (e.g. resizing or\n\t\t\t\t * geometry-influencing tag changes). */\n    Tcl_Size currentMetricUpdateLine;/* Stores a counter which is used to iterate\n\t\t\t\t * over the logical lines contained in the\n\t\t\t\t * widget and update their geometry\n\t\t\t\t * calculations, if they are out of date. */\n    TkTextIndex metricIndex;\t/* If the current metric update line wraps\n\t\t\t\t * into very many display lines, then this is\n\t\t\t\t * used to keep track of what index we've got\n\t\t\t\t * to so far... */\n    int metricPixelHeight;\t/* ...and this is for the height calculation\n\t\t\t\t * so far...*/\n    Tcl_Size metricEpoch;\t\t/* ...and this for the epoch of the partial\n\t\t\t\t * calculation so it can be cancelled if\n\t\t\t\t * things change once more. This field will be\n\t\t\t\t * -1 if there is no long-line calculation in\n\t\t\t\t * progress, and take a non-negative value if\n\t\t\t\t * there is such a calculation in progress. */\n    Tcl_Size lastMetricUpdateLine;\t/* When the current update line reaches this\n\t\t\t\t * line, we are done and should stop the\n\t\t\t\t * asychronous callback mechanism. */\n    Tcl_TimerToken lineUpdateTimer;\n\t\t\t\t/* A token pointing to the current line metric\n\t\t\t\t * update callback. */\n    Tcl_TimerToken scrollbarTimer;\n\t\t\t\t/* A token pointing to the current scrollbar\n\t\t\t\t * update callback. */\n} TextDInfo;\n\n/*\n * In TkTextDispChunk structures for character segments, the clientData field\n * points to one of the following structures:\n */\n\n#ifndef TK_LAYOUT_WITH_BASE_CHUNKS\n\ntypedef struct CharInfo {\n    Tcl_Size numBytes;\t\t/* Number of bytes to display. */\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    char *chars;\t\t/* Pointer to UTF characters to display. */\n#else\n    char chars[TKFLEXARRAY];\t\t/* UTF characters to display.\n\t\t\t\t * Allocated as large as necessary. THIS MUST BE THE LAST\n\t\t\t\t * FIELD IN THE STRUCTURE. */\n#endif\n} CharInfo;\n\n#else /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\ntypedef struct CharInfo {\n    TkTextDispChunk *baseChunkPtr;\n    int baseOffset;\t\t/* Starting offset in base chunk baseChars. */\n    Tcl_Size numBytes;\t\t/* Number of bytes that belong to this chunk. */\n    const char *chars;\t\t/* UTF characters to display. Actually points\n\t\t\t\t * into the baseChars of the base chunk. Only\n\t\t\t\t * valid after FinalizeBaseChunk(). */\n} CharInfo;\n\n/*\n * The BaseCharInfo is a CharInfo with some additional data added.\n */\n\ntypedef struct BaseCharInfo {\n    CharInfo ci;\n    Tcl_DString baseChars;\t/* Actual characters for the stretch of text\n\t\t\t\t * represented by this base chunk. */\n    int width;\t\t\t/* Width in pixels of the whole string, if\n\t\t\t\t * known, else -1. Valid during\n\t\t\t\t * LayoutDLine(). */\n} BaseCharInfo;\n\n/* TODO: Thread safety */\nstatic TkTextDispChunk *baseCharChunkPtr = NULL;\n\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n/*\n * Flag values for TextDInfo structures:\n *\n * DINFO_OUT_OF_DATE:\t\tNon-zero means that the DLine structures for\n *\t\t\t\tthis window are partially or completely out of\n *\t\t\t\tdate and need to be recomputed.\n * REDRAW_PENDING:\t\tMeans that a when-idle handler has been\n *\t\t\t\tscheduled to update the display.\n * REDRAW_BORDERS:\t\tMeans window border or pad area has\n *\t\t\t\tpotentially been damaged and must be redrawn.\n * REPICK_NEEDED:\t\t1 means that the widget has been modified in a\n *\t\t\t\tway that could change the current character (a\n *\t\t\t\tdifferent character might be under the mouse\n *\t\t\t\tcursor now). Need to recompute the current\n *\t\t\t\tcharacter before the next redisplay.\n * OUT_OF_SYNC\t\t\t1 means that the last <<WidgetViewSync>> event had\n *\t\t\t\tvalue 0, indicating that the widget is out of sync.\n */\n\n#define DINFO_OUT_OF_DATE\t1\n#define REDRAW_PENDING\t\t2\n#define REDRAW_BORDERS\t\t4\n#define REPICK_NEEDED\t\t8\n#define OUT_OF_SYNC\t\t16\n/*\n * Action values for FreeDLines:\n *\n * DLINE_FREE:\t\tFree the lines, but no need to unlink them from the\n *\t\t\tcurrent list of actual display lines.\n * DLINE_UNLINK:\tFree and unlink from current display.\n * DLINE_FREE_TEMP:\tFree, but don't unlink, and also don't set\n *\t\t\t'dLinesInvalidated'.\n */\n\n#define DLINE_FREE\t  0\n#define DLINE_UNLINK\t  1\n#define DLINE_FREE_TEMP\t  2\n\n/*\n * The following counters keep statistics about redisplay that can be checked\n * to see how clever this code is at reducing redisplays.\n */\n\nstatic int numRedisplays;\t/* Number of calls to DisplayText. */\nstatic int linesRedrawn;\t/* Number of calls to DisplayDLine. */\nstatic int numCopies;\t\t/* Number of calls to XCopyArea to copy part\n\t\t\t\t * of the screen. */\nstatic int lineHeightsRecalculated;\n\t\t\t\t/* Number of line layouts purely for height\n\t\t\t\t * calculation purposes.*/\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tAdjustForTab(TkText *textPtr,\n\t\t\t    TkTextTabArray *tabArrayPtr, int index,\n\t\t\t    TkTextDispChunk *chunkPtr);\nstatic void\t\tCharBboxProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, Tcl_Size index, int y,\n\t\t\t    int lineHeight, int baseline, int *xPtr,\n\t\t\t    int *yPtr, int *widthPtr, int *heightPtr);\nstatic Tcl_Size\t\tCharChunkMeasureChars(TkTextDispChunk *chunkPtr,\n\t\t\t    const char *chars, Tcl_Size charsLen,\n\t\t\t    Tcl_Size start, Tcl_Size end, int startX, int maxX,\n\t\t\t    int flags, int *nextX);\nstatic void\t\tCharDisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, int x, int y,\n\t\t\t    int height, int baseline, Display *display,\n\t\t\t    Drawable dst, int screenY);\nstatic Tcl_Size\tCharMeasureProc(TkTextDispChunk *chunkPtr, int x);\nstatic void\t\tCharUndisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr);\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\nstatic void\t\tFinalizeBaseChunk(TkTextDispChunk *additionalChunkPtr);\nstatic void\t\tFreeBaseChunk(TkTextDispChunk *baseChunkPtr);\nstatic int\t\tIsSameFGStyle(TextStyle *style1, TextStyle *style2);\nstatic void\t\tRemoveFromBaseChunk(TkTextDispChunk *chunkPtr);\n#endif\n/*\n * Definitions of elided procs. Compiler can't inline these since we use\n * pointers to these functions. ElideDisplayProc and ElideUndisplayProc are\n * special-cased for speed, as potentially many elided DLine chunks if large,\n * tag toggle-filled elided region.\n */\nstatic void\t\tElideBboxProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, Tcl_Size index, int y,\n\t\t\t    int lineHeight, int baseline, int *xPtr,\n\t\t\t    int *yPtr, int *widthPtr, int *heightPtr);\nstatic Tcl_Size\tElideMeasureProc(TkTextDispChunk *chunkPtr, int x);\nstatic void\t\tDisplayDLine(TkText *textPtr, DLine *dlPtr,\n\t\t\t    DLine *prevPtr, Pixmap pixmap);\nstatic void\t\tDisplayLineBackground(TkText *textPtr, DLine *dlPtr,\n\t\t\t    DLine *prevPtr, Pixmap pixmap);\nstatic void\t\tDisplayText(void *clientData);\nstatic DLine *\t\tFindDLine(TkText *textPtr, DLine *dlPtr,\n\t\t\t    const TkTextIndex *indexPtr);\nstatic void\t\tFreeDLines(TkText *textPtr, DLine *firstPtr,\n\t\t\t    DLine *lastPtr, int action);\nstatic void\t\tFreeStyle(TkText *textPtr, TextStyle *stylePtr);\nstatic TextStyle *\tGetStyle(const TkText *textPtr, const TkTextIndex *indexPtr);\nstatic void\t\tGetXView(Tcl_Interp *interp, const TkText *textPtr,\n\t\t\t    int report);\nstatic void\t\tGetYView(Tcl_Interp *interp, TkText *textPtr,\n\t\t\t    int report);\nstatic int\t\tGetYPixelCount(TkText *textPtr, DLine *dlPtr);\nstatic DLine *\t\tLayoutDLine(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr);\nstatic Tcl_Size\tMeasureChars(Tk_Font tkfont, const char *source,\n\t\t\t    Tcl_Size maxBytes, Tcl_Size rangeStart, Tcl_Size rangeLength,\n\t\t\t    int startX, int maxX, int flags, int *nextXPtr);\nstatic void\t\tMeasureUp(TkText *textPtr,\n\t\t\t    const TkTextIndex *srcPtr, int distance,\n\t\t\t    TkTextIndex *dstPtr, int *overlap);\nstatic int\t\tNextTabStop(Tk_Font tkfont, int x, int tabOrigin);\nstatic void\t\tUpdateDisplayInfo(TkText *textPtr);\nstatic void\t\tYScrollByLines(TkText *textPtr, int offset);\nstatic void\t\tYScrollByPixels(TkText *textPtr, int offset);\nstatic int\t\tSizeOfTab(TkText *textPtr, TkTextTabStyle tabStyle,\n\t\t\t    TkTextTabArray *tabArrayPtr, int *indexPtr, int x,\n\t\t\t    int maxX);\nstatic void\t\tTextChanged(TkText *textPtr,\n\t\t\t    const TkTextIndex *index1Ptr,\n\t\t\t    const TkTextIndex *index2Ptr);\nstatic void\t\tTextInvalidateRegion(TkText *textPtr, Region region);\nstatic void\t\tTextRedrawTag(TkText *textPtr,\n\t\t\t    TkTextIndex *index1Ptr, TkTextIndex *index2Ptr,\n\t\t\t    TkTextTag *tagPtr, bool withTag);\nstatic void\t\tTextInvalidateLineMetrics(TkText *textPtr,\n\t\t\t    TkTextLine *linePtr, Tcl_Size lineCount, TkTextInvalidateAction action);\nstatic int\t\tCalculateDisplayLineHeight(TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr, int *byteCountPtr,\n\t\t\t    int *mergedLinePtr);\nstatic void\t\tDlineIndexOfX(TkText *textPtr,\n\t\t\t    DLine *dlPtr, int x, TkTextIndex *indexPtr);\nstatic int\t\tDlineXOfIndex(TkText *textPtr,\n\t\t\t    DLine *dlPtr, Tcl_Size byteIndex);\nstatic int\t\tTextGetScrollInfoObj(Tcl_Interp *interp,\n\t\t\t    TkText *textPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], double *dblPtr,\n\t\t\t    int *intPtr);\nstatic void\t\tAsyncUpdateLineMetrics(void *clientData);\nstatic void\t\tGenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync);\nstatic void\t\tAsyncUpdateYScrollbar(void *clientData);\nstatic int\t\tIsStartOfNotMergedLine(const TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr);\n\n/*\n * Result values returned by TextGetScrollInfoObj:\n */\n\n#define TKTEXT_SCROLL_MOVETO\t1\n#define TKTEXT_SCROLL_PAGES\t2\n#define TKTEXT_SCROLL_UNITS\t3\n#define TKTEXT_SCROLL_ERROR\t4\n#define TKTEXT_SCROLL_PIXELS\t5\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextCreateDInfo --\n *\n *\tThis function is called when a new text widget is created. Its job is\n *\tto set up display-related information for the widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA TextDInfo data structure is allocated and initialized and attached\n *\tto textPtr.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextCreateDInfo(\n    TkText *textPtr)\t\t/* Overall information for text widget. */\n{\n    TextDInfo *dInfoPtr;\n    XGCValues gcValues;\n\n    dInfoPtr = (TextDInfo *)Tcl_Alloc(sizeof(TextDInfo));\n    Tcl_InitHashTable(&dInfoPtr->styleTable, sizeof(StyleValues)/sizeof(int));\n    dInfoPtr->dLinePtr = NULL;\n    dInfoPtr->copyGC = NULL;\n    gcValues.graphics_exposures = True;\n    dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures,\n\t    &gcValues);\n    dInfoPtr->topOfEof = 0;\n    dInfoPtr->newXPixelOffset = 0;\n    dInfoPtr->curXPixelOffset = 0;\n    dInfoPtr->maxLength = 0;\n    dInfoPtr->xScrollFirst = -1;\n    dInfoPtr->xScrollLast = -1;\n    dInfoPtr->yScrollFirst = -1;\n    dInfoPtr->yScrollLast = -1;\n    dInfoPtr->scanMarkXPixel = 0;\n    dInfoPtr->scanMarkX = 0;\n    dInfoPtr->scanTotalYScroll = 0;\n    dInfoPtr->scanMarkY = 0;\n    dInfoPtr->dLinesInvalidated = 0;\n    dInfoPtr->flags = 0;\n    dInfoPtr->topPixelOffset = 0;\n    dInfoPtr->newTopPixelOffset = 0;\n    dInfoPtr->currentMetricUpdateLine = -1;\n    dInfoPtr->lastMetricUpdateLine = -1;\n    dInfoPtr->lineMetricUpdateEpoch = 1;\n    dInfoPtr->metricEpoch = -1;\n    dInfoPtr->metricIndex.textPtr = NULL;\n    dInfoPtr->metricIndex.linePtr = NULL;\n    dInfoPtr->lineUpdateTimer = NULL;\n    dInfoPtr->scrollbarTimer = NULL;\n\n    textPtr->dInfoPtr = dInfoPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextFreeDInfo --\n *\n *\tThis function is called to free up all of the private display\n *\tinformation kept by this file for a text widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLots of resources get freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextFreeDInfo(\n    TkText *textPtr)\t\t/* Overall information for text widget. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n\n    /*\n     * Be careful to free up styleTable *after* freeing up all the DLines, so\n     * that the hash table is still intact to free up the style-related\n     * information from the lines. Once the lines are all free then styleTable\n     * will be empty.\n     */\n\n    FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK);\n    Tcl_DeleteHashTable(&dInfoPtr->styleTable);\n    if (dInfoPtr->copyGC != NULL) {\n\tTk_FreeGC(textPtr->display, dInfoPtr->copyGC);\n    }\n    Tk_FreeGC(textPtr->display, dInfoPtr->scrollGC);\n    if (dInfoPtr->flags & REDRAW_PENDING) {\n\tTcl_CancelIdleCall(DisplayText, textPtr);\n    }\n    if (dInfoPtr->lineUpdateTimer != NULL) {\n\tTcl_DeleteTimerHandler(dInfoPtr->lineUpdateTimer);\n\ttextPtr->refCount--;\n\tdInfoPtr->lineUpdateTimer = NULL;\n    }\n    if (dInfoPtr->scrollbarTimer != NULL) {\n\tTcl_DeleteTimerHandler(dInfoPtr->scrollbarTimer);\n\ttextPtr->refCount--;\n\tdInfoPtr->scrollbarTimer = NULL;\n    }\n    Tcl_Free(dInfoPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetStyle --\n *\n *\tThis function creates all the information needed to display text at a\n *\tparticular location.\n *\n * Results:\n *\tThe return value is a pointer to a TextStyle structure that\n *\tcorresponds to *sValuePtr.\n *\n * Side effects:\n *\tA new entry may be created in the style table for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TextStyle *\nGetStyle(\n    const TkText *textPtr,\t\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr)/* The character in the text for which display\n\t\t\t\t * information is wanted. */\n{\n    TkTextTag **tagPtrs;\n    TkTextTag *tagPtr;\n    StyleValues styleValues;\n    TextStyle *stylePtr;\n    Tcl_HashEntry *hPtr;\n    Tcl_Size numTags, i;\n    int isNew;\n    int isSelected;\n    XGCValues gcValues;\n    unsigned long mask;\n    /*\n     * The variables below keep track of the highest-priority specification\n     * that has occurred for each of the various fields of the StyleValues.\n     */\n    Tcl_Size borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio;\n    Tcl_Size fgPrio, fontPrio, fgStipplePrio;\n    Tcl_Size underlinePrio, elidePrio, justifyPrio, offsetPrio;\n    Tcl_Size lMargin1Prio, lMargin2Prio, rMarginPrio;\n    Tcl_Size lMarginColorPrio, rMarginColorPrio;\n    Tcl_Size spacing1Prio, spacing2Prio, spacing3Prio;\n    Tcl_Size overstrikePrio, tabPrio, tabStylePrio, wrapPrio;\n\n    /*\n     * Find out what tags are present for the character, then compute a\n     * StyleValues structure corresponding to those tags (scan through all of\n     * the tags, saving information for the highest-priority tag).\n     */\n\n    tagPtrs = TkBTreeGetTags(indexPtr, textPtr, &numTags);\n    borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1;\n    fgPrio = fontPrio = fgStipplePrio = -1;\n    underlinePrio = elidePrio = justifyPrio = offsetPrio = -1;\n    lMargin1Prio = lMargin2Prio = rMarginPrio = -1;\n    lMarginColorPrio = rMarginColorPrio = -1;\n    spacing1Prio = spacing2Prio = spacing3Prio = -1;\n    overstrikePrio = tabPrio = tabStylePrio = wrapPrio = -1;\n    memset(&styleValues, 0, sizeof(StyleValues));\n    styleValues.relief = TK_RELIEF_FLAT;\n    styleValues.fgColor = textPtr->fgColor;\n    styleValues.underlineColor = textPtr->fgColor;\n    styleValues.overstrikeColor = textPtr->fgColor;\n    styleValues.tkfont = textPtr->tkfont;\n    styleValues.justify = TK_JUSTIFY_LEFT;\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->spacing1Obj, &styleValues.spacing1);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->spacing2Obj, &styleValues.spacing2);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->spacing3Obj, &styleValues.spacing3);\n    styleValues.tabArrayPtr = textPtr->tabArrayPtr;\n    styleValues.tabStyle = textPtr->tabStyle;\n    styleValues.wrapMode = textPtr->wrapMode;\n    styleValues.elide = 0;\n    isSelected = 0;\n\n    for (i = 0 ; i < numTags; i++) {\n\tif (textPtr->selTagPtr == tagPtrs[i]) {\n\t    isSelected = 1;\n\t    break;\n\t}\n    }\n\n    for (i = 0 ; i < numTags; i++) {\n\tTk_3DBorder border;\n\tXColor *fgColor;\n\n\ttagPtr = tagPtrs[i];\n\tborder = tagPtr->border;\n\tfgColor = tagPtr->fgColor;\n\n\t/*\n\t * If this is the selection tag, and inactiveSelBorder is NULL (the\n\t * default on Windows), then we need to skip it if we don't have the\n\t * focus.\n\t */\n\n\tif ((tagPtr == textPtr->selTagPtr) && !(textPtr->flags & GOT_FOCUS)) {\n\t    if (textPtr->inactiveSelBorder == NULL\n#ifdef MAC_OSX_TK\n\t\t    /* Don't show inactive selection in disabled widgets. */\n\t\t    || textPtr->state == TK_TEXT_STATE_DISABLED\n#endif\n\t    ) {\n\t\tcontinue;\n\t    }\n\t    border = textPtr->inactiveSelBorder;\n\t}\n\n\tif ((tagPtr->selBorder != NULL) && (isSelected)) {\n\t    border = tagPtr->selBorder;\n\t}\n\n\tif ((tagPtr->selFgColor != NULL) && isSelected) {\n\t    fgColor = tagPtr->selFgColor;\n\t}\n\n\tif ((border != NULL) && (tagPtr->priority > borderPrio)) {\n\t    styleValues.border = border;\n\t    borderPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->borderWidthObj != NULL)\n\t\t&& (Tcl_GetString(tagPtr->borderWidthObj)[0] != '\\0')\n\t\t&& (tagPtr->priority > borderWidthPrio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->borderWidthObj, &styleValues.borderWidth);\n\t    borderWidthPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->relief != TK_RELIEF_NULL)\n\t\t&& (tagPtr->priority > reliefPrio)) {\n\t    if (styleValues.border == NULL) {\n\t\tstyleValues.border = textPtr->border;\n\t    }\n\t    styleValues.relief = tagPtr->relief;\n\t    reliefPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->bgStipple != None)\n\t\t&& (tagPtr->priority > bgStipplePrio)) {\n\t    styleValues.bgStipple = tagPtr->bgStipple;\n\t    bgStipplePrio = tagPtr->priority;\n\t}\n\tif ((fgColor != NULL) && (tagPtr->priority > fgPrio)) {\n\t    styleValues.fgColor = fgColor;\n\t    fgPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->tkfont != NULL) && (tagPtr->priority > fontPrio)) {\n\t    styleValues.tkfont = tagPtr->tkfont;\n\t    fontPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->fgStipple != None)\n\t\t&& (tagPtr->priority > fgStipplePrio)) {\n\t    styleValues.fgStipple = tagPtr->fgStipple;\n\t    fgStipplePrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->justify != TK_JUSTIFY_NULL)\n\t\t&& (tagPtr->priority > justifyPrio)) {\n\t    styleValues.justify = tagPtr->justify;\n\t    justifyPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->lMargin1Obj != NULL)\n\t\t&& (tagPtr->priority > lMargin1Prio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->lMargin1Obj, &styleValues.lMargin1);\n\t    lMargin1Prio = tagPtr->priority;\n\t}\n\tif ((tagPtr->lMargin2Obj != NULL)\n\t\t&& (tagPtr->priority > lMargin2Prio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->lMargin2Obj, &styleValues.lMargin2);\n\t    lMargin2Prio = tagPtr->priority;\n\t}\n\tif ((tagPtr->lMarginColor != NULL)\n\t\t&& (tagPtr->priority > lMarginColorPrio)) {\n\t    styleValues.lMarginColor = tagPtr->lMarginColor;\n\t    lMarginColorPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->offsetObj != NULL)\n\t\t&& (tagPtr->priority > offsetPrio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->offsetObj, &styleValues.offset);\n\t    offsetPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->overstrike >= 0)\n\t\t&& (tagPtr->priority > overstrikePrio)) {\n\t    styleValues.overstrike = tagPtr->overstrike > 0;\n\t    overstrikePrio = tagPtr->priority;\n\t    if (tagPtr->overstrikeColor != NULL) {\n\t\tstyleValues.overstrikeColor = tagPtr->overstrikeColor;\n\t    } else if (fgColor != NULL) {\n\t\tstyleValues.overstrikeColor = fgColor;\n\t    }\n\t}\n\tif ((tagPtr->rMarginObj != NULL)\n\t\t&& (tagPtr->priority > rMarginPrio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->rMarginObj, &styleValues.rMargin);\n\t    rMarginPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->rMarginColor != NULL)\n\t\t&& (tagPtr->priority > rMarginColorPrio)) {\n\t    styleValues.rMarginColor = tagPtr->rMarginColor;\n\t    rMarginColorPrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->spacing1Obj != NULL)\n\t\t&& (tagPtr->priority > spacing1Prio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->spacing1Obj, &styleValues.spacing1);\n\t    spacing1Prio = tagPtr->priority;\n\t}\n\tif ((tagPtr->spacing2Obj != NULL)\n\t\t&& (tagPtr->priority > spacing2Prio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->spacing2Obj, &styleValues.spacing2);\n\t    spacing2Prio = tagPtr->priority;\n\t}\n\tif ((tagPtr->spacing3Obj != NULL)\n\t\t&& (tagPtr->priority > spacing3Prio)) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, tagPtr->spacing3Obj, &styleValues.spacing3);\n\t    spacing3Prio = tagPtr->priority;\n\t}\n\tif ((tagPtr->tabStringPtr != NULL)\n\t\t&& (tagPtr->priority > tabPrio)) {\n\t    styleValues.tabArrayPtr = tagPtr->tabArrayPtr;\n\t    tabPrio = tagPtr->priority;\n\t}\n\tif (((tagPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR)\n\t\t|| (tagPtr->tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR))\n\t\t&& (tagPtr->priority > tabStylePrio)) {\n\t    styleValues.tabStyle = tagPtr->tabStyle;\n\t    tabStylePrio = tagPtr->priority;\n\t}\n\tif ((tagPtr->underline >= 0)\n\t\t&& (tagPtr->priority > underlinePrio)) {\n\t    styleValues.underline = tagPtr->underline > 0;\n\t    underlinePrio = tagPtr->priority;\n\t    if (tagPtr->underlineColor != NULL) {\n\t\t styleValues.underlineColor = tagPtr->underlineColor;\n\t    } else if (fgColor != NULL) {\n\t\t styleValues.underlineColor = fgColor;\n\t    }\n\t}\n\tif ((tagPtr->elide >= 0)\n\t\t&& (tagPtr->priority > elidePrio)) {\n\t    styleValues.elide = tagPtr->elide > 0;\n\t    elidePrio = tagPtr->priority;\n\t}\n\tif (((tagPtr->wrapMode == TEXT_WRAPMODE_CHAR) || (tagPtr->wrapMode == TEXT_WRAPMODE_NONE)\n\t\t|| (tagPtr->wrapMode == TEXT_WRAPMODE_WORD)) && (tagPtr->priority > wrapPrio)) {\n\t    styleValues.wrapMode = tagPtr->wrapMode;\n\t    wrapPrio = tagPtr->priority;\n\t}\n    }\n    if (tagPtrs != NULL) {\n\tTcl_Free(tagPtrs);\n    }\n\n    /*\n     * Use an existing style if there's one around that matches.\n     */\n\n    hPtr = Tcl_CreateHashEntry(&textPtr->dInfoPtr->styleTable,\n\t    (char *) &styleValues, &isNew);\n    if (!isNew) {\n\tstylePtr = (TextStyle *)Tcl_GetHashValue(hPtr);\n\tstylePtr->refCount++;\n\treturn stylePtr;\n    }\n\n    /*\n     * No existing style matched. Make a new one.\n     */\n\n    stylePtr = (TextStyle *)Tcl_Alloc(sizeof(TextStyle));\n    stylePtr->refCount = 1;\n    if (styleValues.border != NULL) {\n\tgcValues.foreground = Tk_3DBorderColor(styleValues.border)->pixel;\n\tmask = GCForeground;\n\tif (styleValues.bgStipple != None) {\n\t    gcValues.stipple = styleValues.bgStipple;\n\t    gcValues.fill_style = FillStippled;\n\t    mask |= GCStipple|GCFillStyle;\n\t}\n\tstylePtr->bgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);\n    } else {\n\tstylePtr->bgGC = NULL;\n    }\n    mask = GCFont;\n    gcValues.font = Tk_FontId(styleValues.tkfont);\n    mask |= GCForeground;\n    gcValues.foreground = styleValues.fgColor->pixel;\n    if (styleValues.fgStipple != None) {\n\tgcValues.stipple = styleValues.fgStipple;\n\tgcValues.fill_style = FillStippled;\n\tmask |= GCStipple|GCFillStyle;\n    }\n    stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);\n    mask = GCForeground;\n    gcValues.foreground = styleValues.underlineColor->pixel;\n    stylePtr->ulGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);\n    gcValues.foreground = styleValues.overstrikeColor->pixel;\n    stylePtr->ovGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);\n    stylePtr->sValuePtr = (StyleValues *)\n\t    Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr);\n    stylePtr->hPtr = hPtr;\n    Tcl_SetHashValue(hPtr, stylePtr);\n    return stylePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeStyle --\n *\n *\tThis function is called when a TextStyle structure is no longer\n *\tneeded. It decrements the reference count and frees up the space for\n *\tthe style structure if the reference count is 0.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe storage and other resources associated with the style are freed up\n *\tif no-one's still using it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeStyle(\n    TkText *textPtr,\t\t/* Information about overall widget. */\n    TextStyle *stylePtr)\n\t\t\t\t/* Information about style to free. */\n{\n    if (stylePtr->refCount-- <= 1) {\n\tif (stylePtr->bgGC != NULL) {\n\t    Tk_FreeGC(textPtr->display, stylePtr->bgGC);\n\t}\n\tif (stylePtr->fgGC != NULL) {\n\t    Tk_FreeGC(textPtr->display, stylePtr->fgGC);\n\t}\n\tif (stylePtr->ulGC != NULL) {\n\t    Tk_FreeGC(textPtr->display, stylePtr->ulGC);\n\t}\n\tif (stylePtr->ovGC != NULL) {\n\t    Tk_FreeGC(textPtr->display, stylePtr->ovGC);\n\t}\n\tTcl_DeleteHashEntry(stylePtr->hPtr);\n\tTcl_Free(stylePtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * LayoutDLine --\n *\n *\tThis function generates a single DLine structure for a display line\n *\twhose leftmost character is given by indexPtr.\n *\n * Results:\n *\tThe return value is a pointer to a DLine structure describing the\n *\tdisplay line. All fields are filled in and correct except for y and\n *\tnextPtr.\n *\n * Side effects:\n *\tStorage is allocated for the new DLine.\n *\n *\tSee the comments in 'GetYView' for some thoughts on what the side-\n *\teffects of this call (or its callers) should be; the synchronisation\n *\tof TkTextLine->pixelHeight with the sum of the results of this\n *\tfunction operating on all display lines within each logical line.\n *\tIdeally the code should be refactored to ensure the cached pixel\n *\theight is never behind what is known when this function is called\n *\telsewhere.\n *\n *\tUnfortunately, this function is currently called from many different\n *\tplaces, not just to layout a display line for actual display, but also\n *\tsimply to calculate some metric or other of one or more display lines\n *\t(typically the height). It would be a good idea to do some profiling\n *\tof typical text widget usage and the way in which this is called and\n *\tsee if some optimization could or should be done.\n *\n *----------------------------------------------------------------------\n */\n\nstatic DLine *\nLayoutDLine(\n    TkText *textPtr,\t\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr)/* Beginning of display line. May not\n\t\t\t\t * necessarily point to a character\n\t\t\t\t * segment. */\n{\n    DLine *dlPtr;\t/* New display line. */\n    TkTextSegment *segPtr;\t/* Current segment in text. */\n    TkTextDispChunk *lastChunkPtr;\n\t\t\t\t/* Last chunk allocated so far for line. */\n    TkTextDispChunk *chunkPtr;\t/* Current chunk. */\n    TkTextIndex curIndex;\n    TkTextDispChunk *breakChunkPtr;\n\t\t\t\t/* Chunk containing best word break point, if\n\t\t\t\t * any. */\n    TkTextIndex breakIndex;\t/* Index of first character in\n\t\t\t\t * breakChunkPtr. */\n    Tcl_Size breakByteOffset;\t/* Byte offset of character within\n\t\t\t\t * breakChunkPtr just to right of best break\n\t\t\t\t * point. */\n    int justify;\t\t/* How to justify line: taken from style for\n\t\t\t\t * the first character in line. */\n    int jIndent;\t\t/* Additional indentation (beyond margins) due\n\t\t\t\t * to justification. */\n    int rMargin;\t\t/* Right margin width for line. */\n    TkWrapMode wrapMode;\t/* Wrap mode to use for this line. */\n    int x = 0, maxX = 0;\t/* Initializations needed only to stop\n\t\t\t\t * compiler warnings. */\n    int tabIndex;\t\t/* Index of the current tab stop. */\n    bool noCharsYet;\t\t/* True means that no characters have been\n\t\t\t\t * placed on the line yet. */\n    bool paragraphStart;\t\t/* True means that we are on the first\n\t\t\t\t * line of a paragraph (used to choose between\n\t\t\t\t * lmargin1, lmargin2). */\n    bool wholeLine;\t\t/* Non-zero means this display line runs to\n\t\t\t\t * the end of the text line. */\n    bool gotTab;\t\t\t/* True means the current chunk contains a\n\t\t\t\t * tab. */\n    TkTextDispChunk *tabChunkPtr;\n\t\t\t\t/* Pointer to the chunk containing the\n\t\t\t\t * previous tab stop. */\n    Tcl_Size maxBytes;\t\t/* Maximum number of bytes to include in this\n\t\t\t\t * chunk. */\n    TkTextTabArray *tabArrayPtr;/* Tab stops for line; taken from style for\n\t\t\t\t * the first character on line. */\n    TkTextTabStyle tabStyle;\t/* One of TK_TEXT_TABSTYLE_TABULAR\n\t\t\t\t * or TK_TEXT_TABSTYLE_WORDPROCESSOR. */\n    int tabSize;\t\t/* Number of pixels consumed by current tab\n\t\t\t\t * stop. */\n    TkTextDispChunk *lastCharChunkPtr;\n\t\t\t\t/* Pointer to last chunk in display lines with\n\t\t\t\t * numBytes > 0. Used to drop 0-sized chunks\n\t\t\t\t * from the end of the line. */\n    Tcl_Size byteOffset;\n    int ascent, descent, code;\n\tTcl_Size elidesize;\n    bool elide;\n    StyleValues *sValuePtr;\n    TkTextElideInfo info;\t/* Keep track of elide state. */\n\n    /*\n     * Create and initialize a new DLine structure.\n     */\n\n    dlPtr = (DLine *)Tcl_Alloc(sizeof(DLine));\n    dlPtr->index = *indexPtr;\n    dlPtr->byteCount = 0;\n    dlPtr->y = 0;\n    dlPtr->oldY = 0;\t\t/* Only set to avoid compiler warnings. */\n    dlPtr->height = 0;\n    dlPtr->baseline = 0;\n    dlPtr->chunkPtr = NULL;\n    dlPtr->nextPtr = NULL;\n    dlPtr->flags = NEW_LAYOUT | OLD_Y_INVALID;\n    dlPtr->logicalLinesMerged = 0;\n    dlPtr->lMarginColor = NULL;\n    dlPtr->lMarginWidth = 0;\n    dlPtr->rMarginColor = NULL;\n    dlPtr->rMarginWidth = 0;\n\n    /*\n     * This is not necessarily totally correct, where we have merged logical\n     * lines. Fixing this would require a quite significant overhaul, though,\n     * so currently we make do with this.\n     */\n\n    paragraphStart = (indexPtr->byteIndex == 0);\n\n    /*\n     * Special case entirely elide line as there may be 1000s or more.\n     */\n\n    elide = TkTextIsElided(textPtr, indexPtr, &info);\n    if (elide && indexPtr->byteIndex == 0) {\n\tmaxBytes = 0;\n\tfor (segPtr = info.segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\t    if (segPtr->size > 0) {\n\t\tif (elide == 0) {\n\t\t    /*\n\t\t     * We toggled a tag and the elide state changed to\n\t\t     * visible, and we have something of non-zero size.\n\t\t     * Therefore we must bail out.\n\t\t     */\n\n\t\t    break;\n\t\t}\n\t\tmaxBytes += segPtr->size;\n\n\t\t/*\n\t\t * Reset tag elide priority, since we're on a new character.\n\t\t */\n\n\t    } else if ((segPtr->typePtr == &tkTextToggleOffType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOnType)) {\n\t\tTkTextTag *tagPtr = segPtr->body.toggle.tagPtr;\n\n\t\t/*\n\t\t * The elide state only changes if this tag is either the\n\t\t * current highest priority tag (and is therefore being\n\t\t * toggled off), or it's a new tag with higher priority.\n\t\t */\n\n\t\tif (tagPtr->elide >= 0) {\n\t\t    info.tagCnts[tagPtr->priority]++;\n\t\t    if (info.tagCnts[tagPtr->priority] & 1) {\n\t\t\tinfo.tagPtrs[tagPtr->priority] = tagPtr;\n\t\t    }\n\t\t    if (tagPtr->priority >= info.elidePriority) {\n\t\t\tif (segPtr->typePtr == &tkTextToggleOffType) {\n\t\t\t    /*\n\t\t\t     * If it is being toggled off, and it has an elide\n\t\t\t     * string, it must actually be the current highest\n\t\t\t     * priority tag, so this check is redundant:\n\t\t\t     */\n\n\t\t\t    if (tagPtr->priority != info.elidePriority) {\n\t\t\t\tTcl_Panic(\"Bad tag priority being toggled off\");\n\t\t\t    }\n\n\t\t\t    /*\n\t\t\t     * Find previous elide tag, if any (if not then\n\t\t\t     * elide will be zero, of course).\n\t\t\t     */\n\n\t\t\t    elide = 0;\n\t\t\t    while (--info.elidePriority > 0) {\n\t\t\t\tif (info.tagCnts[info.elidePriority] & 1) {\n\t\t\t\t    elide = info.tagPtrs[info.elidePriority]\n\t\t\t\t\t    ->elide > 0;\n\t\t\t\t    break;\n\t\t\t\t}\n\t\t\t    }\n\t\t\t} else {\n\t\t\t    elide = tagPtr->elide > 0;\n\t\t\t    info.elidePriority = tagPtr->priority;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\tif (elide) {\n\t    dlPtr->byteCount = maxBytes;\n\t    dlPtr->spaceAbove = dlPtr->spaceBelow = dlPtr->length = 0;\n\t    if (dlPtr->index.byteIndex == 0) {\n\t\t/*\n\t\t * Elided state goes from beginning to end of an entire\n\t\t * logical line. This means we can update the line's pixel\n\t\t * height, and bring its pixel calculation up to date.\n\t\t */\n\n\t\tTkBTreeLinePixelEpoch(textPtr, dlPtr->index.linePtr)\n\t\t\t= textPtr->dInfoPtr->lineMetricUpdateEpoch;\n\n\t\tif (TkBTreeLinePixelCount(textPtr,dlPtr->index.linePtr) != 0) {\n\t\t    TkBTreeAdjustPixelHeight(textPtr,\n\t\t\t    dlPtr->index.linePtr, 0, 0);\n\t\t}\n\t    }\n\t    TkTextFreeElideInfo(&info);\n\t    return dlPtr;\n\t}\n    }\n    TkTextFreeElideInfo(&info);\n\n    /*\n     * Each iteration of the loop below creates one TkTextDispChunk for the\n     * new display line. The line will always have at least one chunk (for the\n     * newline character at the end, if there's nothing else available).\n     */\n\n    curIndex = *indexPtr;\n    lastChunkPtr = NULL;\n    chunkPtr = NULL;\n    noCharsYet = true;\n    elide = 0;\n    breakChunkPtr = NULL;\n    breakByteOffset = 0;\n    justify = TK_JUSTIFY_LEFT;\n    tabIndex = -1;\n    tabChunkPtr = NULL;\n    tabArrayPtr = NULL;\n    tabStyle = TK_TEXT_TABSTYLE_TABULAR;\n    rMargin = 0;\n    wrapMode = TEXT_WRAPMODE_CHAR;\n    tabSize = 0;\n    lastCharChunkPtr = NULL;\n\n    /*\n     * Find the first segment to consider for the line. Can't call\n     * TkTextIndexToSeg for this because it won't return a segment with zero\n     * size (such as the insertion cursor's mark).\n     */\n\n  connectNextLogicalLine:\n    byteOffset = curIndex.byteIndex;\n    segPtr = curIndex.linePtr->segPtr;\n    while ((byteOffset > 0) && (byteOffset >= segPtr->size)) {\n\tbyteOffset -= segPtr->size;\n\tsegPtr = segPtr->nextPtr;\n\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Two logical lines merged into one display line through eliding\n\t     * of a newline.\n\t     */\n\n\t    TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);\n\t    if (linePtr == NULL) {\n\t\tbreak;\n\t    }\n\n\t    dlPtr->logicalLinesMerged++;\n\t    curIndex.byteIndex = 0;\n\t    curIndex.linePtr = linePtr;\n\t    segPtr = curIndex.linePtr->segPtr;\n\t}\n    }\n\n    while (segPtr != NULL) {\n\t/*\n\t * Every logical line still gets at least one chunk due to\n\t * expectations in the rest of the code, but we are able to skip\n\t * elided portions of the line quickly.\n\t *\n\t * If current chunk is elided and last chunk was too, coalesce.\n\t *\n\t * This also means that each logical line which is entirely elided\n\t * still gets laid out into a DLine, but with zero height. This isn't\n\t * particularly a problem, but it does seem somewhat unnecessary. We\n\t * may wish to redesign the code to remove these zero height DLines in\n\t * the future.\n\t */\n\n\tif (elide && (lastChunkPtr != NULL)\n\t\t&& (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) {\n\t    elidesize = segPtr->size - byteOffset;\n\t    if (segPtr->size > byteOffset) {\n\t\tcurIndex.byteIndex += elidesize;\n\t\tlastChunkPtr->numBytes += elidesize;\n\t\tbreakByteOffset = lastChunkPtr->breakIndex\n\t\t\t= lastChunkPtr->numBytes;\n\n\t\t/*\n\t\t * If have we have a tag toggle, there is a chance that\n\t\t * invisibility state changed, so bail out.\n\t\t */\n\t    } else if ((segPtr->typePtr == &tkTextToggleOffType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOnType)) {\n\t\tif (segPtr->body.toggle.tagPtr->elide >= 0) {\n\t\t    elide = (segPtr->typePtr == &tkTextToggleOffType)\n\t\t\t    ^ (segPtr->body.toggle.tagPtr->elide > 0);\n\t\t}\n\t    }\n\n\t    byteOffset = 0;\n\t    segPtr = segPtr->nextPtr;\n\n\t    if (segPtr == NULL) {\n\t\t/*\n\t\t * Two logical lines merged into one display line through\n\t\t * eliding of a newline.\n\t\t */\n\n\t\tTkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);\n\n\t\tif (linePtr != NULL) {\n\t\t    dlPtr->logicalLinesMerged++;\n\t\t    curIndex.byteIndex = 0;\n\t\t    curIndex.linePtr = linePtr;\n\t\t    goto connectNextLogicalLine;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Code no longer needed, now that we allow logical lines to merge\n\t     * into a single display line.\n\t     *\n\t    if (segPtr == NULL && chunkPtr != NULL) {\n\t\tTcl_Free(chunkPtr);\n\t\tchunkPtr = NULL;\n\t    }\n\t     */\n\n\t    continue;\n\t}\n\n\tif (segPtr->typePtr->layoutProc == NULL) {\n\t    segPtr = segPtr->nextPtr;\n\t    byteOffset = 0;\n\t    continue;\n\t}\n\tif (chunkPtr == NULL) {\n\t    chunkPtr = (TkTextDispChunk *)Tcl_Alloc(sizeof(TkTextDispChunk));\n\t    chunkPtr->nextPtr = NULL;\n\t    chunkPtr->clientData = NULL;\n\t}\n\tchunkPtr->stylePtr = GetStyle(textPtr, &curIndex);\n\telide = chunkPtr->stylePtr->sValuePtr->elide;\n\n\t/*\n\t * Save style information such as justification and indentation, up\n\t * until the first character is encountered, then retain that\n\t * information for the rest of the line.\n\t */\n\n\tif (!elide && noCharsYet) {\n\t    tabArrayPtr = chunkPtr->stylePtr->sValuePtr->tabArrayPtr;\n\t    tabStyle = chunkPtr->stylePtr->sValuePtr->tabStyle;\n\t    justify = chunkPtr->stylePtr->sValuePtr->justify;\n\t    rMargin = chunkPtr->stylePtr->sValuePtr->rMargin;\n\t    wrapMode = chunkPtr->stylePtr->sValuePtr->wrapMode;\n\n\t    /*\n\t     * See above - this test may not be entirely correct where we have\n\t     * partially elided lines (and therefore merged logical lines).\n\t     * In such a case a byteIndex of zero doesn't necessarily mean the\n\t     * beginning of a logical line.\n\t     */\n\n\t    if (paragraphStart) {\n\t\t/*\n\t\t * Beginning of logical line.\n\t\t */\n\n\t\tx = chunkPtr->stylePtr->sValuePtr->lMargin1;\n\t    } else {\n\t\t/*\n\t\t * Beginning of display line.\n\t\t */\n\n\t\tx = chunkPtr->stylePtr->sValuePtr->lMargin2;\n\t    }\n\t    dlPtr->lMarginWidth = x;\n\t    if (wrapMode == TEXT_WRAPMODE_NONE) {\n\t\tmaxX = -1;\n\t    } else {\n\t\tmaxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x\n\t\t\t- rMargin;\n\t\tif (maxX < x) {\n\t\t    maxX = x;\n\t\t}\n\t    }\n\t}\n\n\tgotTab = false;\n\tmaxBytes = segPtr->size - byteOffset;\n\tif (segPtr->typePtr == &tkTextCharType) {\n\n\t    /*\n\t     * See if there is a tab in the current chunk; if so, only layout\n\t     * characters up to (and including) the tab.\n\t     */\n\n\t    if (!elide && justify == TK_JUSTIFY_LEFT) {\n\t\tchar *p;\n\n\t\tfor (p = segPtr->body.chars + byteOffset; *p != 0; p++) {\n\t\t    if (*p == '\\t') {\n\t\t\tmaxBytes = (p + 1 - segPtr->body.chars) - byteOffset;\n\t\t\tgotTab = true;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    if (baseCharChunkPtr != NULL) {\n\t\tint expectedX =\n\t\t\t((BaseCharInfo *) baseCharChunkPtr->clientData)->width\n\t\t\t+ baseCharChunkPtr->x;\n\n\t\tif ((expectedX != x) || !IsSameFGStyle(\n\t\t\tbaseCharChunkPtr->stylePtr, chunkPtr->stylePtr)) {\n\t\t    FinalizeBaseChunk(NULL);\n\t\t}\n\t    }\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\t}\n\tchunkPtr->x = x;\n\tif (elide /*&& maxBytes*/) {\n\t    /*\n\t     * Don't free style here, as other code expects to be able to do\n\t     * that.\n\t     */\n\n\t    /* breakByteOffset =*/\n\t    chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes;\n\t    chunkPtr->width = 0;\n\t    chunkPtr->minAscent = chunkPtr->minDescent\n\t\t    = chunkPtr->minHeight = 0;\n\n\t    /*\n\t     * Would just like to point to canonical empty chunk.\n\t     */\n\n\t    chunkPtr->displayProc = NULL;\n\t    chunkPtr->undisplayProc = NULL;\n\t    chunkPtr->measureProc = ElideMeasureProc;\n\t    chunkPtr->bboxProc = ElideBboxProc;\n\n\t    code = 1;\n\t} else {\n\t    code = segPtr->typePtr->layoutProc(textPtr, &curIndex, segPtr,\n\t\t    byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode,\n\t\t    chunkPtr);\n\t}\n\tif (code <= 0) {\n\t    FreeStyle(textPtr, chunkPtr->stylePtr);\n\t    if (code < 0) {\n\t\t/*\n\t\t * This segment doesn't wish to display itself (e.g. most\n\t\t * marks).\n\t\t */\n\n\t\tsegPtr = segPtr->nextPtr;\n\t\tbyteOffset = 0;\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * No characters from this segment fit in the window: this means\n\t     * we're at the end of the display line.\n\t     */\n\n\t    if (chunkPtr != NULL) {\n\t\tTcl_Free(chunkPtr);\n\t    }\n\t    break;\n\t}\n\n\t/*\n\t * We currently say we have some characters (and therefore something\n\t * from which to examine tag values for the first character of the\n\t * line) even if those characters are actually elided. This behaviour\n\t * is not well documented, and it might be more consistent to\n\t * completely ignore such elided characters and their tags. To do so\n\t * change this to:\n\t *\n\t * if (!elide && chunkPtr->numBytes > 0).\n\t */\n\n\tif (!elide && chunkPtr->numBytes > 0) {\n\t    noCharsYet = false;\n\t    lastCharChunkPtr = chunkPtr;\n\t}\n\tif (lastChunkPtr == NULL) {\n\t    dlPtr->chunkPtr = chunkPtr;\n\t} else {\n\t    lastChunkPtr->nextPtr = chunkPtr;\n\t}\n\tlastChunkPtr = chunkPtr;\n\tx += chunkPtr->width;\n\tif (chunkPtr->breakIndex > 0) {\n\t    breakByteOffset = chunkPtr->breakIndex;\n\t    breakIndex = curIndex;\n\t    breakChunkPtr = chunkPtr;\n\t}\n\tif (chunkPtr->numBytes != maxBytes) {\n\t    break;\n\t}\n\n\t/*\n\t * If we're at a new tab, adjust the layout for all the chunks\n\t * pertaining to the previous tab. Also adjust the amount of space\n\t * left in the line to account for space that will be eaten up by the\n\t * tab.\n\t */\n\n\tif (gotTab) {\n\t    if (tabIndex >= 0) {\n\t\tAdjustForTab(textPtr, tabArrayPtr, tabIndex, tabChunkPtr);\n\t\tx = chunkPtr->x + chunkPtr->width;\n\t    }\n\t    tabChunkPtr = chunkPtr;\n\t    tabSize = SizeOfTab(textPtr, tabStyle, tabArrayPtr, &tabIndex, x,\n\t\t    maxX);\n\t    if ((maxX >= 0) && (tabSize >= maxX - x)) {\n\t\tbreak;\n\t    }\n\t}\n\tcurIndex.byteIndex += chunkPtr->numBytes;\n\tbyteOffset += chunkPtr->numBytes;\n\tif (byteOffset >= segPtr->size) {\n\t    byteOffset = 0;\n\t    segPtr = segPtr->nextPtr;\n\t    if (elide && segPtr == NULL) {\n\t\t/*\n\t\t * An elided section started on this line, and carries on\n\t\t * until the newline. Hence the newline is actually elided,\n\t\t * and we want to merge the display of the next logical line\n\t\t * with this one.\n\t\t */\n\n\t\tTkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr);\n\n\t\tif (linePtr != NULL) {\n\t\t    dlPtr->logicalLinesMerged++;\n\t\t    curIndex.byteIndex = 0;\n\t\t    curIndex.linePtr = linePtr;\n\t\t    chunkPtr = NULL;\n\t\t    goto connectNextLogicalLine;\n\t\t}\n\t    }\n\t}\n\n\tchunkPtr = NULL;\n    }\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    FinalizeBaseChunk(NULL);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n    if (noCharsYet) {\n\tdlPtr->spaceAbove = 0;\n\tdlPtr->spaceBelow = 0;\n\tdlPtr->length = 0;\n\n\t/*\n\t * We used to Tcl_Panic here, saying that LayoutDLine couldn't place\n\t * any characters on a line, but I believe a more appropriate response\n\t * is to return a DLine with zero height. With elided lines, tag\n\t * transitions and asynchronous line height calculations, it is hard\n\t * to avoid this situation ever arising with the current code design.\n\t */\n\n\treturn dlPtr;\n    }\n    wholeLine = (segPtr == NULL);\n\n    /*\n     * We're at the end of the display line. Throw away everything after the\n     * most recent word break, if there is one; this may potentially require\n     * the last chunk to be layed out again.\n     */\n\n    if (breakChunkPtr == NULL) {\n\t/*\n\t * This code makes sure that we don't accidentally display chunks with\n\t * no characters at the end of the line (such as the insertion\n\t * cursor). These chunks belong on the next line. So, throw away\n\t * everything after the last chunk that has characters in it.\n\t */\n\n\tbreakChunkPtr = lastCharChunkPtr;\n\tbreakByteOffset = breakChunkPtr->numBytes;\n    }\n    if ((breakChunkPtr != NULL) && ((lastChunkPtr != breakChunkPtr)\n\t    || (breakByteOffset != lastChunkPtr->numBytes))) {\n\twhile (1) {\n\t    chunkPtr = breakChunkPtr->nextPtr;\n\t    if (chunkPtr == NULL) {\n\t\tbreak;\n\t    }\n\t    FreeStyle(textPtr, chunkPtr->stylePtr);\n\t    breakChunkPtr->nextPtr = chunkPtr->nextPtr;\n\t    if (chunkPtr->undisplayProc != NULL) {\n\t\tchunkPtr->undisplayProc(textPtr, chunkPtr);\n\t    }\n\t    Tcl_Free(chunkPtr);\n\t}\n\tif (breakByteOffset != breakChunkPtr->numBytes) {\n\t    if (breakChunkPtr->undisplayProc != NULL) {\n\t\tbreakChunkPtr->undisplayProc(textPtr, breakChunkPtr);\n\t    }\n\t    segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset);\n\t    segPtr->typePtr->layoutProc(textPtr, &breakIndex, segPtr,\n\t\t    byteOffset, maxX, breakByteOffset, 0, wrapMode,\n\t\t    breakChunkPtr);\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    FinalizeBaseChunk(NULL);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\t}\n\tlastChunkPtr = breakChunkPtr;\n\twholeLine = false;\n    }\n\n    /*\n     * Make tab adjustments for the last tab stop, if there is one.\n     */\n\n    if ((tabIndex >= 0) && (tabChunkPtr != NULL)) {\n\tAdjustForTab(textPtr, tabArrayPtr, tabIndex, tabChunkPtr);\n    }\n\n    /*\n     * Make one more pass over the line to recompute various things like its\n     * height, length, and total number of bytes. Also modify the x-locations\n     * of chunks to reflect justification. If we're not wrapping, I'm not sure\n     * what is the best way to handle right and center justification: should\n     * the total length, for purposes of justification, be (a) the window\n     * width, (b) the length of the longest line in the window, or (c) the\n     * length of the longest line in the text? (c) isn't available, (b) seems\n     * weird, since it can change with vertical scrolling, so (a) is what is\n     * implemented below.\n     */\n\n    if (wrapMode == TEXT_WRAPMODE_NONE) {\n\tmaxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin;\n    }\n    dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;\n    if (justify == TK_JUSTIFY_LEFT) {\n\tjIndent = 0;\n    } else if (justify == TK_JUSTIFY_RIGHT) {\n\tjIndent = maxX - dlPtr->length;\n    } else {\n\tjIndent = (maxX - dlPtr->length)/2;\n    }\n    ascent = descent = 0;\n    for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL;\n\t    chunkPtr = chunkPtr->nextPtr) {\n\tchunkPtr->x += jIndent;\n\tdlPtr->byteCount += chunkPtr->numBytes;\n\tif (chunkPtr->minAscent > ascent) {\n\t    ascent = chunkPtr->minAscent;\n\t}\n\tif (chunkPtr->minDescent > descent) {\n\t    descent = chunkPtr->minDescent;\n\t}\n\tif (chunkPtr->minHeight > dlPtr->height) {\n\t    dlPtr->height = chunkPtr->minHeight;\n\t}\n\tsValuePtr = chunkPtr->stylePtr->sValuePtr;\n\tif ((sValuePtr->borderWidth > 0)\n\t\t&& (sValuePtr->relief != TK_RELIEF_FLAT)) {\n\t    dlPtr->flags |= HAS_3D_BORDER;\n\t}\n    }\n    if (dlPtr->height < (ascent + descent)) {\n\tdlPtr->height = ascent + descent;\n\tdlPtr->baseline = ascent;\n    } else {\n\tdlPtr->baseline = ascent + (dlPtr->height - ascent - descent)/2;\n    }\n    sValuePtr = dlPtr->chunkPtr->stylePtr->sValuePtr;\n    if (dlPtr->index.byteIndex == 0) {\n\tdlPtr->spaceAbove = sValuePtr->spacing1;\n    } else {\n\tdlPtr->spaceAbove = sValuePtr->spacing2 - sValuePtr->spacing2/2;\n    }\n    if (wholeLine) {\n\tdlPtr->spaceBelow = sValuePtr->spacing3;\n    } else {\n\tdlPtr->spaceBelow = sValuePtr->spacing2/2;\n    }\n    dlPtr->height += dlPtr->spaceAbove + dlPtr->spaceBelow;\n    dlPtr->baseline += dlPtr->spaceAbove;\n    dlPtr->lMarginColor = sValuePtr->lMarginColor;\n    dlPtr->rMarginColor = sValuePtr->rMarginColor;\n    if (wrapMode != TEXT_WRAPMODE_NONE) {\n\tdlPtr->rMarginWidth = rMargin;\n    }\n\n    /*\n     * Recompute line length: may have changed because of justification.\n     */\n\n    dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;\n\n    return dlPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateDisplayInfo --\n *\n *\tThis function is invoked to recompute some or all of the DLine\n *\tstructures for a text widget. At the time it is called the DLine\n *\tstructures still left in the widget are guaranteed to be correct\n *\texcept that (a) the y-coordinates aren't necessarily correct, (b)\n *\tthere may be missing structures (the DLine structures get removed as\n *\tsoon as they are potentially out-of-date), and (c) DLine structures\n *\tthat don't start at the beginning of a line may be incorrect if\n *\tprevious information in the same line changed size in a way that moved\n *\ta line boundary (DLines for any info that changed will have been\n *\tdeleted, but not DLines for unchanged info in the same text line).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUpon return, the DLine information for textPtr correctly reflects the\n *\tpositions where characters will be displayed. However, this function\n *\tdoesn't actually bring the display up-to-date.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateDisplayInfo(\n    TkText *textPtr)\t\t/* Text widget to update. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr, *prevPtr;\n    TkTextIndex index;\n    TkTextLine *lastLinePtr;\n    int y, maxY, xPixelOffset, maxOffset, lineHeight;\n\n    if (!(dInfoPtr->flags & DINFO_OUT_OF_DATE)) {\n\treturn;\n    }\n    dInfoPtr->flags &= ~DINFO_OUT_OF_DATE;\n\n    /*\n     * Delete any DLines that are now above the top of the window.\n     */\n\n    index = textPtr->topIndex;\n    dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index);\n    if ((dlPtr != NULL) && (dlPtr != dInfoPtr->dLinePtr)) {\n\tFreeDLines(textPtr, dInfoPtr->dLinePtr, dlPtr, DLINE_UNLINK);\n    }\n    if (index.byteIndex == 0) {\n\tlineHeight = 0;\n    } else {\n\tlineHeight = -1;\n    }\n\n    /*\n     * Scan through the contents of the window from top to bottom, recomputing\n     * information for lines that are missing.\n     */\n\n    lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));\n    dlPtr = dInfoPtr->dLinePtr;\n    prevPtr = NULL;\n    y = dInfoPtr->y - dInfoPtr->newTopPixelOffset;\n    maxY = dInfoPtr->maxY;\n    while (1) {\n\tDLine *newPtr;\n\n\tif (index.linePtr == lastLinePtr) {\n\t    break;\n\t}\n\n\t/*\n\t * There are three possibilities right now:\n\t * (a) the next DLine (dlPtr) corresponds exactly to the next\n\t *     information we want to display: just use it as-is.\n\t * (b) the next DLine corresponds to a different line, or to a segment\n\t *     that will be coming later in the same line: leave this DLine\n\t *     alone in the hopes that we'll be able to use it later, then\n\t *     create a new DLine in front of it.\n\t * (c) the next DLine corresponds to a segment in the line we want,\n\t *     but it's a segment that has already been processed or will\n\t *     never be processed. Delete the DLine and try again.\n\t *\n\t * One other twist on all this. It's possible for 3D borders to\n\t * interact between lines (see DisplayLineBackground) so if a line is\n\t * relayed out and has styles with 3D borders, its neighbors have to\n\t * be redrawn if they have 3D borders too, since the interactions\n\t * could have changed (the neighbors don't have to be relayed out,\n\t * just redrawn).\n\t */\n\n\tif ((dlPtr == NULL) || (dlPtr->index.linePtr != index.linePtr)) {\n\t    /*\n\t     * Case (b) -- must make new DLine.\n\t     */\n\n\tmakeNewDLine:\n\t    if (tkTextDebug) {\n\t\tchar string[TK_POS_CHARS];\n\n\t\t/*\n\t\t * Debugging is enabled, so keep a log of all the lines that\n\t\t * were re-layed out. The test suite uses this information.\n\t\t */\n\n\t\tTkTextPrintIndex(textPtr, &index, string);\n\t\tLOG(\"tk_textRelayout\", string);\n\t    }\n\t    newPtr = LayoutDLine(textPtr, &index);\n\t    if (prevPtr == NULL) {\n\t\tdInfoPtr->dLinePtr = newPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = newPtr;\n\t\tif (prevPtr->flags & HAS_3D_BORDER) {\n\t\t    prevPtr->flags |= OLD_Y_INVALID;\n\t\t}\n\t    }\n\t    newPtr->nextPtr = dlPtr;\n\t    dlPtr = newPtr;\n\t} else {\n\t    /*\n\t     * DlPtr refers to the line we want. Next check the index within\n\t     * the line.\n\t     */\n\n\t    if (index.byteIndex == dlPtr->index.byteIndex) {\n\t\t/*\n\t\t * Case (a) - can use existing display line as-is.\n\t\t */\n\n\t\tif ((dlPtr->flags & HAS_3D_BORDER) && (prevPtr != NULL)\n\t\t\t&& (prevPtr->flags & (NEW_LAYOUT))) {\n\t\t    dlPtr->flags |= OLD_Y_INVALID;\n\t\t}\n\t\tgoto lineOK;\n\t    }\n\t    if (index.byteIndex < dlPtr->index.byteIndex) {\n\t\tgoto makeNewDLine;\n\t    }\n\n\t    /*\n\t     * Case (c) - dlPtr is useless. Discard it and start again with\n\t     * the next display line.\n\t     */\n\n\t    newPtr = dlPtr->nextPtr;\n\t    FreeDLines(textPtr, dlPtr, newPtr, DLINE_FREE);\n\t    dlPtr = newPtr;\n\t    if (prevPtr != NULL) {\n\t\tprevPtr->nextPtr = newPtr;\n\t    } else {\n\t\tdInfoPtr->dLinePtr = newPtr;\n\t    }\n\t    continue;\n\t}\n\n\t/*\n\t * Advance to the start of the next line.\n\t */\n\n    lineOK:\n\tdlPtr->y = y;\n\ty += dlPtr->height;\n\tif (lineHeight != -1) {\n\t    lineHeight += dlPtr->height;\n\t}\n\tTkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index);\n\tprevPtr = dlPtr;\n\tdlPtr = dlPtr->nextPtr;\n\n\t/*\n\t * If we switched text lines, delete any DLines left for the old text\n\t * line.\n\t */\n\n\tif (index.linePtr != prevPtr->index.linePtr) {\n\t    DLine *nextPtr;\n\n\t    nextPtr = dlPtr;\n\t    while ((nextPtr != NULL)\n\t\t    && (nextPtr->index.linePtr == prevPtr->index.linePtr)) {\n\t\tnextPtr = nextPtr->nextPtr;\n\t    }\n\t    if (nextPtr != dlPtr) {\n\t\tFreeDLines(textPtr, dlPtr, nextPtr, DLINE_FREE);\n\t\tprevPtr->nextPtr = nextPtr;\n\t\tdlPtr = nextPtr;\n\t    }\n\n\t    if ((lineHeight != -1) && (TkBTreeLinePixelCount(textPtr,\n\t\t    prevPtr->index.linePtr) != lineHeight)) {\n\t\t/*\n\t\t * The logical line height we just calculated is actually\n\t\t * different to the currently cached height of the text line.\n\t\t * That is fine (the text line heights are only calculated\n\t\t * asynchronously), but we must update the cached height so\n\t\t * that any counts made with DLine pointers are the same as\n\t\t * counts made through the BTree. This helps to ensure that\n\t\t * the scrollbar size corresponds accurately to that displayed\n\t\t * contents, even as the window is re-sized.\n\t\t */\n\n\t\tTkBTreeAdjustPixelHeight(textPtr, prevPtr->index.linePtr,\n\t\t\tlineHeight, 0);\n\n\t\t/*\n\t\t * I believe we can be 100% sure that we started at the\n\t\t * beginning of the logical line, so we can also adjust the\n\t\t * 'pixelCalculationEpoch' to mark it as being up to date.\n\t\t * There is a slight concern that we might not have got this\n\t\t * right for the first line in the re-display.\n\t\t */\n\n\t\tTkBTreeLinePixelEpoch(textPtr, prevPtr->index.linePtr) =\n\t\t\tdInfoPtr->lineMetricUpdateEpoch;\n\t    }\n\t    lineHeight = 0;\n\t}\n\n\t/*\n\t * It's important to have the following check here rather than in the\n\t * while statement for the loop, so that there's always at least one\n\t * DLine generated, regardless of how small the window is. This keeps\n\t * a lot of other code from breaking.\n\t */\n\n\tif (y >= maxY) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Delete any DLine structures that don't fit on the screen.\n     */\n\n    FreeDLines(textPtr, dlPtr, NULL, DLINE_UNLINK);\n\n    /*\n     * If there is extra space at the bottom of the window (because we've hit\n     * the end of the text), then bring in more lines at the top of the\n     * window, if there are any, to fill in the view.\n     *\n     * Since the top line may only be partially visible, we try first to\n     * simply show more pixels from that line (newTopPixelOffset). If that\n     * isn't enough, we have to layout more lines.\n     */\n\n    if (y < maxY) {\n\t/*\n\t * This counts how many vertical pixels we have left to fill by\n\t * pulling in more display pixels either from the first currently\n\t * displayed, or the lines above it.\n\t */\n\n\tint spaceLeft = maxY - y;\n\n\tif (spaceLeft <= dInfoPtr->newTopPixelOffset) {\n\t    /*\n\t     * We can fill up all the needed space just by showing more of the\n\t     * current top line.\n\t     */\n\n\t    dInfoPtr->newTopPixelOffset -= spaceLeft;\n\t    y += spaceLeft;\n\t    spaceLeft = 0;\n\t} else {\n\t    Tcl_Size lineNum, bytesToCount;\n\t    DLine *lowestPtr;\n\n\t    /*\n\t     * Add in all of the current top line, which won't be enough to\n\t     * bring y up to maxY (if it was we would be in the 'if' block\n\t     * above).\n\t     */\n\n\t    y += dInfoPtr->newTopPixelOffset;\n\t    dInfoPtr->newTopPixelOffset = 0;\n\n\t    /*\n\t     * Layout an entire text line (potentially > 1 display line), then\n\t     * link in as many display lines as fit without moving the bottom\n\t     * line out of the window. Repeat this until all the extra space\n\t     * has been used up or we've reached the beginning of the text.\n\t     */\n\n\t    spaceLeft = maxY - y;\n\t    if (dInfoPtr->dLinePtr == NULL) {\n\t\t/*\n\t\t * No lines have been laid out. This must be an empty peer\n\t\t * widget.\n\t\t */\n\n\t\tlineNum = TkBTreeNumLines(textPtr->sharedTextPtr->tree,\n\t\t\ttextPtr) - 1;\n\t\tbytesToCount = INT_MAX;\n\t    } else {\n\t\tlineNum = TkBTreeLinesTo(textPtr,\n\t\t\tdInfoPtr->dLinePtr->index.linePtr);\n\t\tbytesToCount = dInfoPtr->dLinePtr->index.byteIndex;\n\t\tif (bytesToCount == 0) {\n\t\t    bytesToCount = INT_MAX;\n\t\t    lineNum--;\n\t\t}\n\t    }\n\t    for ( ; (lineNum >= 0) && (spaceLeft > 0); lineNum--) {\n\t\tint pixelHeight = 0;\n\n\t\tindex.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t\ttextPtr, lineNum);\n\t\tindex.byteIndex = 0;\n\t\tlowestPtr = NULL;\n\n\t\tdo {\n\t\t    dlPtr = LayoutDLine(textPtr, &index);\n\t\t    pixelHeight += dlPtr->height;\n\t\t    dlPtr->nextPtr = lowestPtr;\n\t\t    lowestPtr = dlPtr;\n\t\t    if (dlPtr->length == 0 && dlPtr->height == 0) {\n\t\t\tbytesToCount--;\n\t\t\tbreak;\n\t\t    }\t/* elide */\n\t\t    TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount,\n\t\t\t    &index);\n\t\t    bytesToCount -= dlPtr->byteCount;\n\t\t} while ((bytesToCount > 0)\n\t\t\t&& (index.linePtr == lowestPtr->index.linePtr));\n\n\t\t/*\n\t\t * We may not have examined the entire line (depending on the\n\t\t * value of 'bytesToCount', so we only want to set this if it\n\t\t * is genuinely bigger).\n\t\t */\n\n\t\tif (pixelHeight > TkBTreeLinePixelCount(textPtr,\n\t\t\tlowestPtr->index.linePtr)) {\n\t\t    TkBTreeAdjustPixelHeight(textPtr,\n\t\t\t    lowestPtr->index.linePtr, pixelHeight, 0);\n\t\t    if (index.linePtr != lowestPtr->index.linePtr) {\n\t\t\t/*\n\t\t\t * We examined the entire line, so can update the\n\t\t\t * epoch.\n\t\t\t */\n\n\t\t\tTkBTreeLinePixelEpoch(textPtr,\n\t\t\t\tlowestPtr->index.linePtr) =\n\t\t\t\tdInfoPtr->lineMetricUpdateEpoch;\n\t\t    }\n\t\t}\n\n\t\t/*\n\t\t * Scan through the display lines from the bottom one up to\n\t\t * the top one.\n\t\t */\n\n\t\twhile (lowestPtr != NULL) {\n\t\t    dlPtr = lowestPtr;\n\t\t    spaceLeft -= dlPtr->height;\n\t\t    lowestPtr = dlPtr->nextPtr;\n\t\t    dlPtr->nextPtr = dInfoPtr->dLinePtr;\n\t\t    dInfoPtr->dLinePtr = dlPtr;\n\t\t    if (tkTextDebug) {\n\t\t\tchar string[TK_POS_CHARS];\n\n\t\t\tTkTextPrintIndex(textPtr, &dlPtr->index, string);\n\t\t\tLOG(\"tk_textRelayout\", string);\n\t\t    }\n\t\t    if (spaceLeft <= 0) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tFreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);\n\t\tbytesToCount = INT_MAX;\n\t    }\n\n\t    /*\n\t     * We've either filled in the space we wanted to or we've run out\n\t     * of display lines at the top of the text. Note that we already\n\t     * set dInfoPtr->newTopPixelOffset to zero above.\n\t     */\n\n\t    if (spaceLeft < 0) {\n\t\t/*\n\t\t * We've laid out a few too many vertical pixels at or above\n\t\t * the first line. Therefore we only want to show part of the\n\t\t * first displayed line, so that the last displayed line just\n\t\t * fits in the window.\n\t\t */\n\n\t\tdInfoPtr->newTopPixelOffset = -spaceLeft;\n\t\tif (dInfoPtr->newTopPixelOffset>=dInfoPtr->dLinePtr->height) {\n\t\t    /*\n\t\t     * Somehow the entire first line we laid out is shorter\n\t\t     * than the new offset. This should not occur and would\n\t\t     * indicate a bad problem in the logic above.\n\t\t     */\n\n\t\t    Tcl_Panic(\"Error in pixel height consistency while filling in spacesLeft\");\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Now we're all done except that the y-coordinates in all the DLines\n\t * are wrong and the top index for the text is wrong. Update them.\n\t */\n\n\tif (dInfoPtr->dLinePtr != NULL) {\n\t    textPtr->topIndex = dInfoPtr->dLinePtr->index;\n\t    y = dInfoPtr->y - dInfoPtr->newTopPixelOffset;\n\t    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;\n\t\t    dlPtr = dlPtr->nextPtr) {\n\t\tif (y > dInfoPtr->maxY) {\n\t\t    Tcl_Panic(\"Added too many new lines in UpdateDisplayInfo\");\n\t\t}\n\t\tdlPtr->y = y;\n\t\ty += dlPtr->height;\n\t    }\n\t}\n    }\n\n    /*\n     * If the old top or bottom line has scrolled elsewhere on the screen, we\n     * may not be able to re-use its old contents by copying bits (e.g., a\n     * beveled edge that was drawn when it was at the top or bottom won't be\n     * drawn when the line is in the middle and its neighbor has a matching\n     * background). Similarly, if the new top or bottom line came from\n     * somewhere else on the screen, we may not be able to copy the old bits.\n     */\n\n    dlPtr = dInfoPtr->dLinePtr;\n    if (dlPtr != NULL) {\n\tif ((dlPtr->flags & HAS_3D_BORDER) && !(dlPtr->flags & TOP_LINE)) {\n\t    dlPtr->flags |= OLD_Y_INVALID;\n\t}\n\twhile (1) {\n\t    if ((dlPtr->flags & TOP_LINE) && (dlPtr != dInfoPtr->dLinePtr)\n\t\t    && (dlPtr->flags & HAS_3D_BORDER)) {\n\t\tdlPtr->flags |= OLD_Y_INVALID;\n\t    }\n\n\t    /*\n\t     * If the old top-line was not completely showing (i.e. the\n\t     * pixelOffset is non-zero) and is no longer the top-line, then we\n\t     * must re-draw it.\n\t     */\n\n\t    if ((dlPtr->flags & TOP_LINE) &&\n\t\t    dInfoPtr->topPixelOffset!=0 && dlPtr!=dInfoPtr->dLinePtr) {\n\t\tdlPtr->flags |= OLD_Y_INVALID;\n\t    }\n\t    if ((dlPtr->flags & BOTTOM_LINE) && (dlPtr->nextPtr != NULL)\n\t\t    && (dlPtr->flags & HAS_3D_BORDER)) {\n\t\tdlPtr->flags |= OLD_Y_INVALID;\n\t    }\n\t    if (dlPtr->nextPtr == NULL) {\n\t\tif ((dlPtr->flags & HAS_3D_BORDER)\n\t\t\t&& !(dlPtr->flags & BOTTOM_LINE)) {\n\t\t    dlPtr->flags |= OLD_Y_INVALID;\n\t\t}\n\t\tdlPtr->flags &= ~TOP_LINE;\n\t\tdlPtr->flags |= BOTTOM_LINE;\n\t\tbreak;\n\t    }\n\t    dlPtr->flags &= ~(TOP_LINE|BOTTOM_LINE);\n\t    dlPtr = dlPtr->nextPtr;\n\t}\n\tdInfoPtr->dLinePtr->flags |= TOP_LINE;\n\tdInfoPtr->topPixelOffset = dInfoPtr->newTopPixelOffset;\n    }\n\n    /*\n     * Arrange for scrollbars to be updated.\n     */\n\n    textPtr->flags |= UPDATE_SCROLLBARS;\n\n    /*\n     * Deal with horizontal scrolling:\n     * 1. If there's empty space to the right of the longest line, shift the\n     *\t  screen to the right to fill in the empty space.\n     * 2. If the desired horizontal scroll position has changed, force a full\n     *\t  redisplay of all the lines in the widget.\n     * 3. If the wrap mode isn't \"none\" then re-scroll to the base position.\n     */\n\n    dInfoPtr->maxLength = 0;\n    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;\n\t    dlPtr = dlPtr->nextPtr) {\n\tif (dlPtr->length > dInfoPtr->maxLength) {\n\t    dInfoPtr->maxLength = dlPtr->length;\n\t}\n    }\n    maxOffset = dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x);\n\n    xPixelOffset = dInfoPtr->newXPixelOffset;\n    if (xPixelOffset > maxOffset) {\n\txPixelOffset = maxOffset;\n    }\n    if (xPixelOffset < 0) {\n\txPixelOffset = 0;\n    }\n\n    /*\n     * Here's a problem: see the tests textDisp-29.2.1-4\n     *\n     * If the widget is being created, but has not yet been configured it will\n     * have a maxY of 1 above, and we won't have examined all the lines\n     * (just the first line, in fact), and so maxOffset will not be a true\n     * reflection of the widget's lines. Therefore we must not overwrite the\n     * original newXPixelOffset in this case.\n     */\n\n    if (!(((Tk_FakeWin *) (textPtr->tkwin))->flags & TK_NEED_CONFIG_NOTIFY)) {\n\tdInfoPtr->newXPixelOffset = xPixelOffset;\n    }\n\n    if (xPixelOffset != dInfoPtr->curXPixelOffset) {\n\tdInfoPtr->curXPixelOffset = xPixelOffset;\n\tfor (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;\n\t\tdlPtr = dlPtr->nextPtr) {\n\t    dlPtr->flags |= OLD_Y_INVALID;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeDLines --\n *\n *\tThis function is called to free up all of the resources associated\n *\twith one or more DLine structures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory gets freed and various other resources are released.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeDLines(\n    TkText *textPtr,\t\t/* Information about overall text widget. */\n    DLine *firstPtr,\t/* Pointer to first DLine to free up. */\n    DLine *lastPtr,\t\t/* Pointer to DLine just after last one to\n\t\t\t\t * free (NULL means everything starting with\n\t\t\t\t * firstPtr). */\n    int action)\t\t\t/* DLINE_UNLINK means DLines are currently\n\t\t\t\t * linked into the list rooted at\n\t\t\t\t * textPtr->dInfoPtr->dLinePtr and they have\n\t\t\t\t * to be unlinked. DLINE_FREE means just free\n\t\t\t\t * without unlinking. DLINE_FREE_TEMP means\n\t\t\t\t * the DLine given is just a temporary one and\n\t\t\t\t * we shouldn't invalidate anything for the\n\t\t\t\t * overall widget. */\n{\n    TkTextDispChunk *chunkPtr, *nextChunkPtr;\n    DLine *nextDLinePtr;\n\n    if (action == DLINE_FREE_TEMP) {\n\tlineHeightsRecalculated++;\n\tif (tkTextDebug) {\n\t    char string[TK_POS_CHARS];\n\n\t    /*\n\t     * Debugging is enabled, so keep a log of all the lines whose\n\t     * height was recalculated. The test suite uses this information.\n\t     */\n\n\t    TkTextPrintIndex(textPtr, &firstPtr->index, string);\n\t    LOG(\"tk_textHeightCalc\", string);\n\t}\n    } else if (action == DLINE_UNLINK) {\n\tif (textPtr->dInfoPtr->dLinePtr == firstPtr) {\n\t    textPtr->dInfoPtr->dLinePtr = lastPtr;\n\t} else {\n\t    DLine *prevPtr;\n\n\t    for (prevPtr = textPtr->dInfoPtr->dLinePtr;\n\t\t    prevPtr->nextPtr != firstPtr; prevPtr = prevPtr->nextPtr) {\n\t\t/* Empty loop body. */\n\t    }\n\t    prevPtr->nextPtr = lastPtr;\n\t}\n    }\n    while (firstPtr != lastPtr) {\n\tnextDLinePtr = firstPtr->nextPtr;\n\tfor (chunkPtr = firstPtr->chunkPtr; chunkPtr != NULL;\n\t\tchunkPtr = nextChunkPtr) {\n\t    if (chunkPtr->undisplayProc != NULL) {\n\t\tchunkPtr->undisplayProc(textPtr, chunkPtr);\n\t    }\n\t    FreeStyle(textPtr, chunkPtr->stylePtr);\n\t    nextChunkPtr = chunkPtr->nextPtr;\n\t    Tcl_Free(chunkPtr);\n\t}\n\tTcl_Free(firstPtr);\n\tfirstPtr = nextDLinePtr;\n    }\n    if (action != DLINE_FREE_TEMP) {\n\ttextPtr->dInfoPtr->dLinesInvalidated = 1;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayDLine --\n *\n *\tThis function is invoked to draw a single line on the screen.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe line given by dlPtr is drawn at its correct position in textPtr's\n *\twindow. Note that this is one *display* line, not one *text* line.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayDLine(\n    TkText *textPtr,\t\t/* Text widget in which to draw line. */\n    DLine *dlPtr,\t\t/* Information about line to draw. */\n    DLine *prevPtr,\t\t/* Line just before one to draw, or NULL if\n\t\t\t\t * dlPtr is the top line. */\n    Pixmap pixmap)\t\t/* Pixmap to use for double-buffering. Caller\n\t\t\t\t * must make sure it's large enough to hold\n\t\t\t\t * line. */\n{\n    TkTextDispChunk *chunkPtr, tmpChunk, *otherChunkPtr = NULL;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    Display *display;\n    int height, y_off;\n    struct TextStyle tmpStyle;\n    TkBorder *borderPtr;\n    bool blockCursor = textPtr->insertCursorType;\n    bool haveFocus = (textPtr->flags & GOT_FOCUS) != 0;\n    bool showInsertCursor = (textPtr->flags & INSERT_ON) != 0;\n    bool solidUnfocussed =\n\t    textPtr->insertUnfocussed == TK_TEXT_INSERT_NOFOCUS_SOLID;\n#ifndef TK_NO_DOUBLE_BUFFERING\n    const int y = 0;\n#else\n    const int y = dlPtr->y;\n#endif /* TK_NO_DOUBLE_BUFFERING */\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    BaseCharInfo bci;\n#else\n    CharInfo ci;\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n    if (dlPtr->chunkPtr == NULL) return;\n\n    display = Tk_Display(textPtr->tkwin);\n\n    height = dlPtr->height;\n    if ((height + dlPtr->y) > dInfoPtr->maxY) {\n\theight = dInfoPtr->maxY - dlPtr->y;\n    }\n    if (dlPtr->y < dInfoPtr->y) {\n\ty_off = dInfoPtr->y - dlPtr->y;\n\theight -= y_off;\n    } else {\n\ty_off = 0;\n    }\n\n#ifdef TK_NO_DOUBLE_BUFFERING\n    Tk_ClipDrawableToRect(display, pixmap, dInfoPtr->x, y + y_off,\n\t    dInfoPtr->maxX - dInfoPtr->x, height);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n    /*\n     * First, clear the area of the line to the background color for the text\n     * widget.\n     */\n\n    Tk_Fill3DRectangle(textPtr->tkwin, pixmap, textPtr->border, 0, y,\n\t    Tk_Width(textPtr->tkwin), dlPtr->height, 0, TK_RELIEF_FLAT);\n\n    /*\n     * Second, draw background information for the whole line.\n     */\n\n    DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap);\n\n    /*\n     * Third, draw the background color of the left and right margins.\n     */\n    if (dlPtr->lMarginColor != NULL) {\n\tTk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->lMarginColor, 0, y,\n\t\tdlPtr->lMarginWidth + dInfoPtr->x - dInfoPtr->curXPixelOffset,\n\t\tdlPtr->height, 0, TK_RELIEF_FLAT);\n    }\n    if (dlPtr->rMarginColor != NULL) {\n\tTk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->rMarginColor,\n\t\tdInfoPtr->maxX - dlPtr->rMarginWidth + dInfoPtr->curXPixelOffset,\n\t\ty, dlPtr->rMarginWidth, dlPtr->height, 0, TK_RELIEF_FLAT);\n    }\n\n    /*\n     * Make another pass through all of the chunks to redraw the insertion\n     * cursor, if it is visible on this line. Must do it here rather than in\n     * the foreground pass below because otherwise a wide insertion cursor\n     * will obscure the character to its left.\n     */\n\n    if (textPtr->state != TK_TEXT_STATE_DISABLED) {\n\tfor (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);\n\t\tchunkPtr = chunkPtr->nextPtr) {\n\t    if (chunkPtr->displayProc == TkTextInsertDisplayProc) {\n\t\tint x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;\n\t\tchunkPtr->displayProc(textPtr, chunkPtr, x,\n\t\t\ty + dlPtr->spaceAbove,\n\t\t\tdlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,\n\t\t\tdlPtr->baseline - dlPtr->spaceAbove, display, pixmap,\n\t\t\tdlPtr->y + dlPtr->spaceAbove);\n\t    }\n\t}\n    }\n\n    /*\n     * Make yet another pass through all of the chunks to redraw all of\n     * foreground information. Note: we have to call the displayProc even for\n     * chunks that are off-screen. This is needed, for example, so that\n     * embedded windows can be unmapped in this case.\n     */\n\n    for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);\n\t    chunkPtr = chunkPtr->nextPtr) {\n\tif (chunkPtr->displayProc == TkTextInsertDisplayProc) {\n\t    /*\n\t     * Already displayed the insertion cursor above. Don't do it again\n\t     * here.\n\t     */\n\n\t    if (blockCursor &&\n\t\t    ((haveFocus && showInsertCursor) ||\n\t\t\t(!haveFocus && solidUnfocussed)) &&\n\t\t    (chunkPtr->nextPtr != NULL) &&\n\t\t    (chunkPtr->nextPtr->displayProc == CharDisplayProc) &&\n\t\t    (chunkPtr->nextPtr->numBytes > 0)) {\n\t\t/*\n\t\t * Make a temporary chunk for displaying the text\n\t\t * within the block cursor later on.\n\t\t */\n\n\t\tTkTextIndex index;\n\t\tint ix, iy, iw, ih, charWidth, cursorWidth;\n\t\tint endX;\n\t\tTcl_Size numBytes;\n\n\t\totherChunkPtr = &tmpChunk;\n\t\t*otherChunkPtr = *(chunkPtr->nextPtr);\n\t\tTkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n\t\tTkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih,\n\t\t\t&charWidth, &cursorWidth);\n\t\tnumBytes = CharChunkMeasureChars(otherChunkPtr, NULL, 0,\n\t\t\t0, -1, otherChunkPtr->x,\n\t\t\totherChunkPtr->x + cursorWidth, 0, &endX);\n\t\tif (numBytes > 0) {\n\t\t    XGCValues gcValues;\n\t\t    unsigned long mask;\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t\t    CharInfo *ciPtr;\n\t\t    BaseCharInfo *bciPtr;\n#endif\n\n\t\t    otherChunkPtr->undisplayProc = NULL;\n\t\t    tmpStyle = *otherChunkPtr->stylePtr;\n\t\t    otherChunkPtr->stylePtr = &tmpStyle;\n\t\t    tmpStyle.bgGC = NULL;\n\t\t    mask = GCFont;\n\t\t    gcValues.font = Tk_FontId(tmpStyle.sValuePtr->tkfont);\n\t\t    mask |= GCForeground;\n\t\t    borderPtr = (TkBorder *) textPtr->border;\n\t\t    gcValues.foreground = borderPtr->bgColorPtr->pixel;\n\t\t    tmpStyle.fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t\t    ciPtr = (CharInfo *) otherChunkPtr->clientData;\n\t\t    bciPtr = (BaseCharInfo *) ciPtr->baseChunkPtr->clientData;\n\t\t    bci.ci = *ciPtr;\n\t\t    Tcl_DStringInit(&bci.baseChars);\n\t\t    bci.width = -1;\n\t\t    Tcl_DStringAppend(&bci.baseChars,\n\t\t\t    Tcl_DStringValue(&bciPtr->baseChars) +\n\t\t\t    bci.ci.baseOffset, numBytes);\n\t\t    bci.ci.baseOffset = 0;\n\t\t    bci.ci.numBytes = Tcl_DStringLength(&bci.baseChars);\n\t\t    bci.ci.chars = Tcl_DStringValue(&bci.baseChars);\n\t\t    bci.ci.baseChunkPtr = otherChunkPtr;\n\t\t    otherChunkPtr->clientData = &bci;\n\t\t    otherChunkPtr->numBytes = bci.ci.numBytes;\n#else\n\t\t    ci = *((CharInfo *) (otherChunkPtr->clientData));\n\t\t    ci.numBytes = numBytes;\n\t\t    otherChunkPtr->clientData = &ci;\n\t\t    otherChunkPtr->numBytes = ci.numBytes;\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\t\t} else {\n\t\t    otherChunkPtr = NULL;\n\t\t}\n\t    }\n\t    continue;\n\t}\n\n\t/*\n\t * Don't call if elide. This tax OK since not very many visible DLines\n\t * in an area, but potentially many elide ones.\n\t */\n\n\tif (chunkPtr->displayProc != NULL) {\n\t    int x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;\n\n\t    if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {\n\t\t/*\n\t\t * Note: we have to call the displayProc even for chunks that\n\t\t * are off-screen. This is needed, for example, so that\n\t\t * embedded windows can be unmapped in this case. Display the\n\t\t * chunk at a coordinate that can be clearly identified by the\n\t\t * displayProc as being off-screen to the left (the\n\t\t * displayProc may not be able to tell if something is off to\n\t\t * the right).\n\t\t */\n\n\t\tx = -chunkPtr->width;\n\t    }\n\t    chunkPtr->displayProc(textPtr, chunkPtr, x,\n\t\t    y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove -\n\t\t    dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove,\n\t\t    display, pixmap, dlPtr->y + dlPtr->spaceAbove);\n\t}\n\n\tif (otherChunkPtr != NULL) {\n\t    if ((textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) {\n\t\t/*\n\t\t * Draw text within (i.e. \"under\") the block cursor.\n\t\t */\n\n\t\tint x = otherChunkPtr->x + dInfoPtr->x -\n\t\t\tdInfoPtr->curXPixelOffset;\n\n\t\tif ((x + otherChunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {\n\t\t    /*\n\t\t     * See note above.\n\t\t     */\n\n\t\t    x = -otherChunkPtr->width;\n\t\t}\n\t\totherChunkPtr->displayProc(textPtr, otherChunkPtr, x,\n\t\t\ty + dlPtr->spaceAbove, dlPtr->height -\n\t\t\tdlPtr->spaceAbove - dlPtr->spaceBelow,\n\t\t\tdlPtr->baseline - dlPtr->spaceAbove,\n\t\t\tdisplay, pixmap, dlPtr->y + dlPtr->spaceAbove);\n\t    }\n\t    if (otherChunkPtr->stylePtr->fgGC != NULL) {\n\t\tTk_FreeGC(textPtr->display, otherChunkPtr->stylePtr->fgGC);\n\t    }\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    Tcl_DStringFree(&bci.baseChars);\n#endif\n\t    otherChunkPtr = NULL;\n\t}\n\n\tif ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t    /*\n\t     * A displayProc called in the loop above invoked a binding\n\t     * that caused the widget to be deleted. Don't do anything.\n\t     */\n\t    return;\n\t}\n\tif (dInfoPtr->dLinesInvalidated) {\n\t    return;\n\t}\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Copy the pixmap onto the screen. If this is the first or last line on\n     * the screen then copy a piece of the line, so that it doesn't overflow\n     * into the border area. Another special trick: copy the padding area to\n     * the left of the line; this is because the insertion cursor sometimes\n     * overflows onto that area and we want to get as much of the cursor as\n     * possible.\n     */\n\n    XCopyArea(display, pixmap, Tk_WindowId(textPtr->tkwin), dInfoPtr->copyGC,\n\t    dInfoPtr->x, y + y_off, (unsigned) (dInfoPtr->maxX - dInfoPtr->x),\n\t    (unsigned) height, dInfoPtr->x, dlPtr->y + y_off);\n#else\n    Tk_ClipDrawableToRect(display, pixmap, 0, 0, -1, -1);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    linesRedrawn++;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayLineBackground --\n *\n *\tThis function is called to fill in the background for a display line.\n *\tIt draws 3D borders cleverly so that adjacent chunks with the same\n *\tstyle (whether on the same line or different lines) have a single 3D\n *\tborder around the whole region.\n *\n * Results:\n *\tThere is no return value. Pixmap is filled in with background\n *\tinformation for dlPtr.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayLineBackground(\n    TkText *textPtr,\t\t/* Text widget containing line. */\n    DLine *dlPtr,\t/* Information about line to draw. */\n    DLine *prevPtr,\t\t/* Line just above dlPtr, or NULL if dlPtr is\n\t\t\t\t * the top-most line in the window. */\n    Pixmap pixmap)\t\t/* Pixmap to use for double-buffering. Caller\n\t\t\t\t * must make sure it's large enough to hold\n\t\t\t\t * line. Caller must also have filled it with\n\t\t\t\t * the background color for the widget. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    TkTextDispChunk *chunkPtr;\t/* Pointer to chunk in the current line. */\n    TkTextDispChunk *chunkPtr2;\t/* Pointer to chunk in the line above or below\n\t\t\t\t * the current one. NULL if we're to the left\n\t\t\t\t * of or to the right of the chunks in the\n\t\t\t\t * line. */\n    TkTextDispChunk *nextPtr2;\t/* Next chunk after chunkPtr2 (it's not the\n\t\t\t\t * same as chunkPtr2->nextPtr in the case\n\t\t\t\t * where chunkPtr2 is NULL because the line is\n\t\t\t\t * indented). */\n    int leftX;\t\t\t/* The left edge of the region we're currently\n\t\t\t\t * working on. */\n    int leftXIn;\t\t/* 1 means beveled edge at leftX slopes right\n\t\t\t\t * as it goes down, 0 means it slopes left as\n\t\t\t\t * it goes down. */\n    int rightX;\t\t\t/* Right edge of chunkPtr. */\n    int rightX2;\t\t/* Right edge of chunkPtr2. */\n    int matchLeft;\t\t/* Does the style of this line match that of\n\t\t\t\t * its neighbor just to the left of the\n\t\t\t\t * current x coordinate? */\n    int matchRight;\t\t/* Does line's style match its neighbor just\n\t\t\t\t * to the right of the current x-coord? */\n    int minX, maxX, xOffset, bw;\n    StyleValues *sValuePtr;\n    Display *display;\n#ifndef TK_NO_DOUBLE_BUFFERING\n    const int y = 0;\n#else\n    const int y = dlPtr->y;\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n    /*\n     * Pass 1: scan through dlPtr from left to right. For each range of chunks\n     * with the same style, draw the main background for the style plus the\n     * vertical parts of the 3D borders (the left and right edges).\n     */\n\n    display = Tk_Display(textPtr->tkwin);\n    minX = dInfoPtr->curXPixelOffset;\n    xOffset = dInfoPtr->x - minX;\n    maxX = minX + dInfoPtr->maxX - dInfoPtr->x;\n    chunkPtr = dlPtr->chunkPtr;\n\n    /*\n     * Note A: in the following statement, and a few others later in this file\n     * marked with \"See Note A above\", the right side of the assignment was\n     * replaced with 0 on 6/18/97. This has the effect of highlighting the\n     * empty space to the left of a line whenever the leftmost character of\n     * the line is highlighted. This way, multi-line highlights always line up\n     * along their left edges. However, this may look funny in the case where\n     * a single word is highlighted. To undo the change, replace \"leftX = 0\"\n     * with \"leftX = chunkPtr->x\" and \"rightX2 = 0\" with \"rightX2 =\n     * nextPtr2->x\" here and at all the marked points below. This restores the\n     * old behavior where empty space to the left of a line is not\n     * highlighted, leaving a ragged left edge for multi-line highlights.\n     */\n\n    leftX = 0;\n    for (; leftX < maxX; chunkPtr = chunkPtr->nextPtr) {\n\tif ((chunkPtr->nextPtr != NULL)\n\t\t&& SAME_BACKGROUND(chunkPtr->nextPtr->stylePtr,\n\t\tchunkPtr->stylePtr)) {\n\t    continue;\n\t}\n\tsValuePtr = chunkPtr->stylePtr->sValuePtr;\n\trightX = chunkPtr->x + chunkPtr->width;\n\tif ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {\n\t    rightX = maxX;\n\t}\n\tif (chunkPtr->stylePtr->bgGC != NULL) {\n\t    /*\n\t     * Not visible - bail out now.\n\t     */\n\n\t    if (rightX + xOffset <= 0) {\n\t\tleftX = rightX;\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * Trim the start position for drawing to be no further away than\n\t     * -borderWidth. The reason is that on many X servers drawing from\n\t     * -32768 (or less) to +something simply does not display\n\t     * correctly. [Patch #541999]\n\t     */\n\n\t    if ((leftX + xOffset) < -(sValuePtr->borderWidth)) {\n\t\tleftX = -sValuePtr->borderWidth - xOffset;\n\t    }\n\t    if ((rightX - leftX) > 32767) {\n\t\trightX = leftX + 32767;\n\t    }\n\n\t    /*\n\t     * Prevent the borders from leaking on adjacent characters,\n\t     * which would happen for too large border width.\n\t     */\n\n\t    bw = sValuePtr->borderWidth;\n\t    if (leftX + sValuePtr->borderWidth > rightX) {\n\t\tbw = rightX - leftX;\n\t    }\n\n\t    XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC,\n\t\t    leftX + xOffset, y, (unsigned int) (rightX - leftX),\n\t\t    (unsigned int) dlPtr->height);\n\t    if (sValuePtr->relief != TK_RELIEF_FLAT) {\n\t\tTk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t\tleftX + xOffset, y, bw, dlPtr->height, 1,\n\t\t\tsValuePtr->relief);\n\t\tTk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t\trightX - bw + xOffset, y, bw, dlPtr->height, 0,\n\t\t\tsValuePtr->relief);\n\t    }\n\t}\n\tleftX = rightX;\n    }\n\n    /*\n     * Pass 2: draw the horizontal bevels along the top of the line. To do\n     * this, scan through dlPtr from left to right while simultaneously\n     * scanning through the line just above dlPtr. ChunkPtr2 and nextPtr2\n     * refer to two adjacent chunks in the line above.\n     */\n\n    chunkPtr = dlPtr->chunkPtr;\n    leftX = 0;\t\t\t\t/* See Note A above. */\n    leftXIn = 1;\n    rightX = chunkPtr->x + chunkPtr->width;\n    if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {\n\trightX = maxX;\n    }\n    chunkPtr2 = NULL;\n    if (prevPtr != NULL && prevPtr->chunkPtr != NULL) {\n\t/*\n\t * Find the chunk in the previous line that covers leftX.\n\t */\n\n\tnextPtr2 = prevPtr->chunkPtr;\n\trightX2 = 0;\t\t\t/* See Note A above. */\n\twhile (rightX2 <= leftX) {\n\t    chunkPtr2 = nextPtr2;\n\t    if (chunkPtr2 == NULL) {\n\t\tbreak;\n\t    }\n\t    nextPtr2 = chunkPtr2->nextPtr;\n\t    rightX2 = chunkPtr2->x + chunkPtr2->width;\n\t    if (nextPtr2 == NULL) {\n\t\trightX2 = INT_MAX;\n\t    }\n\t}\n    } else {\n\tnextPtr2 = NULL;\n\trightX2 = INT_MAX;\n    }\n\n    while (leftX < maxX) {\n\tmatchLeft = (chunkPtr2 != NULL)\n\t\t&& SAME_BACKGROUND(chunkPtr2->stylePtr, chunkPtr->stylePtr);\n\tsValuePtr = chunkPtr->stylePtr->sValuePtr;\n\tif (rightX <= rightX2) {\n\t    /*\n\t     * The chunk in our line is about to end. If its style changes\n\t     * then draw the bevel for the current style.\n\t     */\n\n\t    if ((chunkPtr->nextPtr == NULL)\n\t\t    || !SAME_BACKGROUND(chunkPtr->stylePtr,\n\t\t    chunkPtr->nextPtr->stylePtr)) {\n\t\tif (!matchLeft && (sValuePtr->relief != TK_RELIEF_FLAT)) {\n\t\t    Tk_3DHorizontalBevel(textPtr->tkwin, pixmap,\n\t\t\t    sValuePtr->border, leftX + xOffset, y,\n\t\t\t    rightX - leftX, sValuePtr->borderWidth, leftXIn,\n\t\t\t    1, 1, sValuePtr->relief);\n\t\t}\n\t\tleftX = rightX;\n\t\tleftXIn = 1;\n\n\t\t/*\n\t\t * If the chunk in the line above is also ending at the same\n\t\t * point then advance to the next chunk in that line.\n\t\t */\n\n\t\tif ((rightX == rightX2) && (chunkPtr2 != NULL)) {\n\t\t    goto nextChunk2;\n\t\t}\n\t    }\n\t    chunkPtr = chunkPtr->nextPtr;\n\t    if (chunkPtr == NULL) {\n\t\tbreak;\n\t    }\n\t    rightX = chunkPtr->x + chunkPtr->width;\n\t    if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {\n\t\trightX = maxX;\n\t    }\n\t    continue;\n\t}\n\n\t/*\n\t * The chunk in the line above is ending at an x-position where there\n\t * is no change in the style of the current line. If the style above\n\t * matches the current line on one side of the change but not on the\n\t * other, we have to draw an L-shaped piece of bevel.\n\t */\n\n\tmatchRight = (nextPtr2 != NULL)\n\t\t&& SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);\n\tif (matchLeft && !matchRight) {\n\t    bw = sValuePtr->borderWidth;\n\t    if (rightX2 - sValuePtr->borderWidth < leftX) {\n\t\tbw = rightX2 - leftX;\n\t    }\n\t    if (sValuePtr->relief != TK_RELIEF_FLAT) {\n\t\tTk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t\trightX2 - bw + xOffset, y, bw,\n\t\t\tsValuePtr->borderWidth, 0, sValuePtr->relief);\n\t    }\n\t    leftX = rightX2 - bw;\n\t    leftXIn = 0;\n\t} else if (!matchLeft && matchRight\n\t\t&& (sValuePtr->relief != TK_RELIEF_FLAT)) {\n\t    bw = sValuePtr->borderWidth;\n\t    if (rightX2 + sValuePtr->borderWidth > rightX) {\n\t\tbw = rightX - rightX2;\n\t    }\n\t    Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t    rightX2 + xOffset, y, bw, sValuePtr->borderWidth,\n\t\t    1, sValuePtr->relief);\n\t    Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t    leftX + xOffset, y, rightX2 + bw - leftX,\n\t\t    sValuePtr->borderWidth, leftXIn, 0, 1,\n\t\t    sValuePtr->relief);\n\t}\n\n    nextChunk2:\n\tchunkPtr2 = nextPtr2;\n\tif (chunkPtr2 == NULL) {\n\t    rightX2 = INT_MAX;\n\t} else {\n\t    nextPtr2 = chunkPtr2->nextPtr;\n\t    rightX2 = chunkPtr2->x + chunkPtr2->width;\n\t    if (nextPtr2 == NULL) {\n\t\trightX2 = INT_MAX;\n\t    }\n\t}\n    }\n\n    /*\n     * Pass 3: draw the horizontal bevels along the bottom of the line. This\n     * uses the same approach as pass 2.\n     */\n\n    chunkPtr = dlPtr->chunkPtr;\n    leftX = 0;\t\t\t\t/* See Note A above. */\n    leftXIn = 0;\n    rightX = chunkPtr->x + chunkPtr->width;\n    if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {\n\trightX = maxX;\n    }\n    chunkPtr2 = NULL;\n    if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) {\n\t/*\n\t * Find the chunk in the next line that covers leftX.\n\t */\n\n\tnextPtr2 = dlPtr->nextPtr->chunkPtr;\n\trightX2 = 0;\t\t\t/* See Note A above. */\n\twhile (rightX2 <= leftX) {\n\t    chunkPtr2 = nextPtr2;\n\t    if (chunkPtr2 == NULL) {\n\t\tbreak;\n\t    }\n\t    nextPtr2 = chunkPtr2->nextPtr;\n\t    rightX2 = chunkPtr2->x + chunkPtr2->width;\n\t    if (nextPtr2 == NULL) {\n\t\trightX2 = INT_MAX;\n\t    }\n\t}\n    } else {\n\tnextPtr2 = NULL;\n\trightX2 = INT_MAX;\n    }\n\n    while (leftX < maxX) {\n\tmatchLeft = (chunkPtr2 != NULL)\n\t\t&& SAME_BACKGROUND(chunkPtr2->stylePtr, chunkPtr->stylePtr);\n\tsValuePtr = chunkPtr->stylePtr->sValuePtr;\n\tif (rightX <= rightX2) {\n\t    if ((chunkPtr->nextPtr == NULL)\n\t\t    || !SAME_BACKGROUND(chunkPtr->stylePtr,\n\t\t    chunkPtr->nextPtr->stylePtr)) {\n\t\tif (!matchLeft && (sValuePtr->relief != TK_RELIEF_FLAT)) {\n\t\t    Tk_3DHorizontalBevel(textPtr->tkwin, pixmap,\n\t\t\t    sValuePtr->border, leftX + xOffset,\n\t\t\t    y + dlPtr->height - sValuePtr->borderWidth,\n\t\t\t    rightX - leftX, sValuePtr->borderWidth, leftXIn,\n\t\t\t    0, 0, sValuePtr->relief);\n\t\t}\n\t\tleftX = rightX;\n\t\tleftXIn = 0;\n\t\tif ((rightX == rightX2) && (chunkPtr2 != NULL)) {\n\t\t    goto nextChunk2b;\n\t\t}\n\t    }\n\t    chunkPtr = chunkPtr->nextPtr;\n\t    if (chunkPtr == NULL) {\n\t\tbreak;\n\t    }\n\t    rightX = chunkPtr->x + chunkPtr->width;\n\t    if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {\n\t\trightX = maxX;\n\t    }\n\t    continue;\n\t}\n\n\tmatchRight = (nextPtr2 != NULL)\n\t\t&& SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);\n\tif (matchLeft && !matchRight) {\n\t    bw = sValuePtr->borderWidth;\n\t    if (rightX2 - sValuePtr->borderWidth < leftX) {\n\t\tbw = rightX2 - leftX;\n\t    }\n\t    if (sValuePtr->relief != TK_RELIEF_FLAT) {\n\t\tTk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t\trightX2 - bw + xOffset,\n\t\t\ty + dlPtr->height - sValuePtr->borderWidth,\n\t\t\tbw, sValuePtr->borderWidth, 0, sValuePtr->relief);\n\t    }\n\t    leftX = rightX2 - bw;\n\t    leftXIn = 1;\n\t} else if (!matchLeft && matchRight\n\t\t&& (sValuePtr->relief != TK_RELIEF_FLAT)) {\n\t    bw = sValuePtr->borderWidth;\n\t    if (rightX2 + sValuePtr->borderWidth > rightX) {\n\t\tbw = rightX - rightX2;\n\t    }\n\t    Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t    rightX2 + xOffset,\n\t\t    y + dlPtr->height - sValuePtr->borderWidth, bw,\n\t\t    sValuePtr->borderWidth, 1, sValuePtr->relief);\n\t    Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,\n\t\t    leftX + xOffset,\n\t\t    y + dlPtr->height - sValuePtr->borderWidth,\n\t\t    rightX2 + bw - leftX, sValuePtr->borderWidth, leftXIn,\n\t\t    1, 0, sValuePtr->relief);\n\t}\n\n    nextChunk2b:\n\tchunkPtr2 = nextPtr2;\n\tif (chunkPtr2 == NULL) {\n\t    rightX2 = INT_MAX;\n\t} else {\n\t    nextPtr2 = chunkPtr2->nextPtr;\n\t    rightX2 = chunkPtr2->x + chunkPtr2->width;\n\t    if (nextPtr2 == NULL) {\n\t\trightX2 = INT_MAX;\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AsyncUpdateLineMetrics --\n *\n *\tThis function is invoked as a background handler to update the pixel-\n *\theight calculations of individual lines in an asychronous manner.\n *\n *\tCurrently a timer-handler is used for this purpose, which continuously\n *\treschedules itself. It may well be better to use some other approach\n *\t(e.g., a background thread). We can't use an idle-callback because of\n *\ta known bug in Tcl/Tk in which idle callbacks are not allowed to\n *\tre-schedule themselves. This just causes an effective infinite loop.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLine heights may be recalculated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAsyncUpdateLineMetrics(\n    void *clientData)\t/* Information about widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    Tcl_Size lineNum;\n\n    dInfoPtr->lineUpdateTimer = NULL;\n\n    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)\n\t    || !Tk_IsMapped(textPtr->tkwin)) {\n\t/*\n\t * The widget has been deleted, or is not mapped. Don't do anything.\n\t */\n\n\tif (textPtr->refCount-- <= 1) {\n\t    Tcl_Free(textPtr);\n\t}\n\treturn;\n    }\n\n    if (dInfoPtr->flags & REDRAW_PENDING) {\n\tdInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,\n\t\tAsyncUpdateLineMetrics, clientData);\n\treturn;\n    }\n\n    /*\n     * Reify where we end or all hell breaks loose with the calculations when\n     * we try to update. [Bug 2677890]\n     */\n\n    lineNum = dInfoPtr->currentMetricUpdateLine;\n    if (dInfoPtr->lastMetricUpdateLine == -1) {\n\tdInfoPtr->lastMetricUpdateLine =\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n    }\n\n    /*\n     * Update the lines in blocks of about 24 recalculations, or 250+ lines\n     * examined, so we pass in 256 for 'doThisMuch'.\n     */\n\n    lineNum = TkTextUpdateLineMetrics(textPtr, lineNum,\n\t    dInfoPtr->lastMetricUpdateLine, 256);\n\n    dInfoPtr->currentMetricUpdateLine = lineNum;\n\n    if (tkTextDebug) {\n\tchar buffer[2 * TCL_INTEGER_SPACE + 1];\n\n\tsnprintf(buffer, sizeof(buffer), \"%\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d\", lineNum, dInfoPtr->lastMetricUpdateLine);\n\tLOG(\"tk_textInvalidateLine\", buffer);\n    }\n\n    /*\n     * If we're not in the middle of a long-line calculation (metricEpoch==-1)\n     * and we've reached the last line, then we're done.\n     */\n\n    if (dInfoPtr->metricEpoch == -1\n\t    && lineNum == dInfoPtr->lastMetricUpdateLine) {\n\t/*\n\t * We have looped over all lines, so we're done. We must release our\n\t * refCount on the widget (the timer token was already set to NULL\n\t * above). If there is a registered aftersync command, run that first.\n\t * Cancel any pending idle task which would try to run the command\n\t * after the afterSyncCmd pointer had been set to NULL.\n\t */\n\n\tif (textPtr->afterSyncCmd) {\n\t    int code;\n\t    Tcl_CancelIdleCall(TkTextRunAfterSyncCmd, textPtr);\n\t    Tcl_Preserve(textPtr->interp);\n\t    code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd,\n\t\t    TCL_EVAL_GLOBAL);\n\t    if (code == TCL_ERROR) {\n\t\tTcl_AddErrorInfo(textPtr->interp, \"\\n    (text sync)\");\n\t\tTcl_BackgroundException(textPtr->interp, TCL_ERROR);\n\t    }\n\t    Tcl_Release(textPtr->interp);\n\t    Tcl_DecrRefCount(textPtr->afterSyncCmd);\n\t    textPtr->afterSyncCmd = NULL;\n\t}\n\n\t/*\n\t * Fire the <<WidgetViewSync>> event since the widget view is in sync\n\t * with its internal data (actually it will be after the next trip\n\t * through the event loop, because the widget redraws at idle-time).\n\t */\n\tGenerateWidgetViewSyncEvent(textPtr, 1);\n\n\tif (textPtr->refCount-- <= 1) {\n\t    Tcl_Free(textPtr);\n\t}\n\treturn;\n    }\n\n    /*\n     * Re-arm the timer. We already have a refCount on the text widget so no\n     * need to adjust that.\n     */\n\n    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,\n\t    AsyncUpdateLineMetrics, textPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateWidgetViewSyncEvent --\n *\n *      Send the <<WidgetViewSync>> event related to the text widget\n *      line metrics asynchronous update.  These events should only\n *      be sent when the sync status has changed.  So this function\n *      compares the requested state with the state saved in the\n *      TkText structure, and only generates the event if they are\n *      different.  This means that it is safe to call this function\n *      at any time when the state is known.\n *\n *      If an event is sent, the effect is equivalent to:\n *\t   event generate $textWidget <<WidgetViewSync>> -data $s\n *      where $s is the sync status: true (when the widget view is in\n *      sync with its internal data) or false (when it is not).\n *\n * Results:\n *      None\n *\n * Side effects:\n *      If corresponding bindings are present, they will trigger.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateWidgetViewSyncEvent(\n    TkText *textPtr,\t/* Information about text widget. */\n    Bool InSync)\t/* true if becoming in sync, false otherwise */\n{\n    Bool NewSyncState = (InSync != 0); /* ensure 0 or 1 value */\n    Bool OldSyncState = !(textPtr->dInfoPtr->flags & OUT_OF_SYNC);\n\n    if (NewSyncState != OldSyncState) {\n\tif (NewSyncState) {\n\t    textPtr->dInfoPtr->flags &= ~OUT_OF_SYNC;\n\t} else {\n\t    textPtr->dInfoPtr->flags |= OUT_OF_SYNC;\n\t}\n\tTk_SendVirtualEvent(textPtr->tkwin, \"WidgetViewSync\",\n\t\tTcl_NewBooleanObj(NewSyncState));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextUpdateLineMetrics --\n *\n *\tThis function updates the pixel height calculations of a range of\n *\tlines in the widget. The range is from lineNum to endLine, but, if\n *\tdoThisMuch is positive, then the function may return earlier, once a\n *\tcertain number of lines has been examined. The line counts are from 0.\n *\n *\tIf doThisMuch is -1, then all lines in the range will be updated. This\n *\twill potentially take quite some time for a large text widget.\n *\n *\tNote: with bad input for lineNum and endLine, this function can loop\n *\tindefinitely.\n *\n * Results:\n *\tThe index of the last line examined (or -1 if we are about to wrap\n *\taround from end to beginning of the widget, and the next line will be\n *\tthe first line).\n *\n * Side effects:\n *\tLine heights may be recalculated.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Size\nTkTextUpdateLineMetrics(\n    TkText *textPtr,\t\t/* Information about widget. */\n    Tcl_Size lineNum,\t\t/* Start at this line. */\n    Tcl_Size endLine,\t\t/* Go no further than this line. */\n    int doThisMuch)\t\t/* How many lines to check, or how many 10s of\n\t\t\t\t * lines to recalculate. If '-1' then do\n\t\t\t\t * everything in the range (which may take a\n\t\t\t\t * while). */\n{\n    TkTextLine *linePtr = NULL;\n    Tcl_Size count = 0;\n    Tcl_Size totalLines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n    bool fullUpdateRequested = (lineNum == 0 &&\n\t\t\t       endLine == totalLines &&\n\t\t\t       doThisMuch == -1);\n\n    if (totalLines == 0) {\n\t/*\n\t * Empty peer widget.\n\t */\n\n\treturn endLine;\n    }\n\n    while (1) {\n\n\t/*\n\t * Get a suitable line.\n\t */\n\n\tif (lineNum == -1 && linePtr == NULL) {\n\t    lineNum = 0;\n\t    linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t\t    lineNum);\n\t} else {\n\t    if (lineNum == -1 || linePtr == NULL) {\n\t\tif (lineNum == -1) {\n\t\t    lineNum = 0;\n\t\t}\n\t\tlinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t\ttextPtr, lineNum);\n\t    } else {\n\t\tlineNum++;\n\t\tlinePtr = TkBTreeNextLine(textPtr, linePtr);\n\t    }\n\n\t    /*\n\t     * If we're in the middle of a partial-line height calculation,\n\t     * then we can't be done.\n\t     */\n\n\t    if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) {\n\n\n\t\t/*\n\t\t * We have looped over all lines, so we're done.\n\t\t */\n\n\t\tbreak;\n\t    }\n\t}\n\n\tif (lineNum < totalLines) {\n\t    if (tkTextDebug) {\n\t\tchar buffer[4 * TCL_INTEGER_SPACE + 3];\n\n\t\tsnprintf(buffer, sizeof(buffer), \"%\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d %\" TCL_Z_MODIFIER \"d\",\n\t\t\tlineNum, endLine, totalLines, count);\n\t\tLOG(\"tk_textInvalidateLine\", buffer);\n\t    }\n\n\t    /*\n\t     * Now update the line's metrics if necessary.\n\t     */\n\n\t    if (TkBTreeLinePixelEpoch(textPtr, linePtr)\n\t\t    == textPtr->dInfoPtr->lineMetricUpdateEpoch) {\n\n\t\t/*\n\t\t * This line is already up to date. That means there's nothing\n\t\t * to do here.\n\t\t */\n\n\t    } else if (doThisMuch == -1) {\n\t\tcount += 8 * TkTextUpdateOneLine(textPtr, linePtr, 0,NULL,0);\n\t    } else {\n\t\tTkTextIndex index;\n\t\tTkTextIndex *indexPtr;\n\t\tint pixelHeight;\n\n\t\t/*\n\t\t * If the metric epoch is the same as the widget's epoch, then\n\t\t * we know that indexPtrs are still valid, and if the cached\n\t\t * metricIndex (if any) is for the same line as we wish to\n\t\t * examine, then we are looking at a long line wrapped many\n\t\t * times, which we will examine in pieces.\n\t\t */\n\n\t\tif (textPtr->dInfoPtr->metricEpoch ==\n\t\t\ttextPtr->sharedTextPtr->stateEpoch &&\n\t\t\ttextPtr->dInfoPtr->metricIndex.linePtr==linePtr) {\n\t\t    indexPtr = &textPtr->dInfoPtr->metricIndex;\n\t\t    pixelHeight = textPtr->dInfoPtr->metricPixelHeight;\n\t\t} else {\n\n\t\t    /*\n\t\t     * We must reset the partial line height calculation data\n\t\t     * here, so we don't use it when it is out of date.\n\t\t     */\n\n\t\t    textPtr->dInfoPtr->metricEpoch = -1;\n\t\t    index.tree = textPtr->sharedTextPtr->tree;\n\t\t    index.linePtr = linePtr;\n\t\t    index.byteIndex = 0;\n\t\t    index.textPtr = NULL;\n\t\t    indexPtr = &index;\n\t\t    pixelHeight = 0;\n\t\t}\n\n\t\t/*\n\t\t * Update the line and update the counter, counting 8 for each\n\t\t * display line we actually re-layout.\n\t\t */\n\n\t\tcount += 8 * TkTextUpdateOneLine(textPtr, linePtr,\n\t\t\tpixelHeight, indexPtr, 1);\n\n\t\tif (indexPtr->linePtr == linePtr) {\n\n\t\t    /*\n\t\t     * We didn't complete the logical line, because it\n\t\t     * produced very many display lines, which must be because\n\t\t     * it must be a long line wrapped many times. So we must\n\t\t     * cache as far as we got for next time around.\n\t\t     */\n\n\t\t    if (pixelHeight == 0) {\n\n\t\t\t/*\n\t\t\t * These have already been stored, unless we just\n\t\t\t * started the new line.\n\t\t\t */\n\n\t\t\ttextPtr->dInfoPtr->metricIndex = index;\n\t\t\ttextPtr->dInfoPtr->metricEpoch =\n\t\t\t\ttextPtr->sharedTextPtr->stateEpoch;\n\t\t    }\n\t\t    textPtr->dInfoPtr->metricPixelHeight =\n\t\t\t    TkBTreeLinePixelCount(textPtr, linePtr);\n\t\t    break;\n\t\t}\n\n\t\t/*\n\t\t * We're done with this long line.\n\t\t */\n\n\t\ttextPtr->dInfoPtr->metricEpoch = -1;\n\t    }\n\t} else {\n\n\t    /*\n\t     * We must never recalculate the height of the last artificial\n\t     * line. It must stay at zero, and if we recalculate it, it will\n\t     * change.\n\t     */\n\n\t    if (endLine >= totalLines) {\n\t\tlineNum = endLine;\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * Set things up for the next loop through.\n\t     */\n\n\t    lineNum = -1;\n\t}\n\tcount++;\n\n\tif (doThisMuch != -1 && count >= doThisMuch) {\n\t    break;\n\t}\n    }\n    if (doThisMuch == -1) {\n\n\t/*\n\t * If we were requested to update the entire range, then also update\n\t * the scrollbar.\n\t */\n\n\tGetYView(textPtr->interp, textPtr, 1);\n    }\n    if (fullUpdateRequested) {\n\tGenerateWidgetViewSyncEvent(textPtr, 1);\n    }\n    return lineNum;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextInvalidateLineMetrics, TextInvalidateLineMetrics --\n *\n *\tMark a number of text lines as having invalid line metric\n *\tcalculations. Never call this with linePtr as the last (artificial)\n *\tline in the text. Depending on 'action' which indicates whether the\n *\tgiven lines are simply invalid or have been inserted or deleted, the\n *\tpre-existing asynchronous line update range may need to be adjusted.\n *\n *\tIf linePtr is NULL then 'lineCount' and 'action' are ignored and all\n *\tlines are invalidated.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay schedule an asychronous callback.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextInvalidateLineMetrics(\n    TkSharedText *sharedTextPtr,    /* Shared widget section for all peers, or\n\t\t\t\t     * NULL. */\n    TkText *textPtr,\t\t    /* Widget record for text widget. */\n    TkTextLine *linePtr,\t    /* Invalidation starts from this line. */\n    Tcl_Size lineCount,\t\t    /* And includes this many following lines. */\n    TkTextInvalidateAction action)  /* Indicates what type of invalidation\n\t\t\t\t     * occurred, TK_TEXT_INVALIDATE_(ONLY|INSERT|DELETE). */\n{\n    if (sharedTextPtr == NULL) {\n\tTextInvalidateLineMetrics(textPtr, linePtr, lineCount, action);\n    } else {\n\ttextPtr = sharedTextPtr->peers;\n\twhile (textPtr != NULL) {\n\t    TextInvalidateLineMetrics(textPtr, linePtr, lineCount, action);\n\t    textPtr = textPtr->next;\n\t}\n    }\n}\n\f\nstatic void\nTextInvalidateLineMetrics(\n    TkText *textPtr,\t\t    /* Widget record for text widget. */\n    TkTextLine *linePtr,\t    /* Invalidation starts from this line. */\n    Tcl_Size lineCount,\t\t    /* And includes this many following lines. */\n    TkTextInvalidateAction action)  /* Indicates what type of invalidation\n\t\t\t\t     * occurred, TK_TEXT_INVALIDATE_(ONLY|INSERT|DELETE). */\n{\n    Tcl_Size fromLine;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n\n    if (linePtr != NULL) {\n\tTcl_Size counter = lineCount;\n\n\tfromLine = TkBTreeLinesTo(textPtr, linePtr);\n\n\t/*\n\t * Invalidate the height calculations of each line in the given range.\n\t */\n\n\tTkBTreeLinePixelEpoch(textPtr, linePtr) = 0;\n\twhile (counter > 0 && linePtr != NULL) {\n\t    linePtr = TkBTreeNextLine(textPtr, linePtr);\n\t    if (linePtr != NULL) {\n\t\tTkBTreeLinePixelEpoch(textPtr, linePtr) = 0;\n\t    }\n\t    counter--;\n\t}\n\n\t/*\n\t * Now schedule an examination of each line in the union of the old\n\t * and new update ranges, including the (possibly empty) range in\n\t * between. If that between range is not-empty, then we are examining\n\t * more lines than is strictly necessary (but the examination of the\n\t * extra lines should be quick, since their pixelCalculationEpoch will\n\t * be up to date). However, to keep track of that would require more\n\t * complex record-keeping than what we have.\n\t */\n\n\tif (dInfoPtr->lineUpdateTimer == NULL) {\n\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t    if (action == TK_TEXT_INVALIDATE_DELETE) {\n\t\tlineCount = 0;\n\t    }\n\t    dInfoPtr->lastMetricUpdateLine = fromLine + lineCount + 1;\n\t} else {\n\t    Tcl_Size toLine = fromLine + lineCount + 1;\n\n\t    if (action == TK_TEXT_INVALIDATE_DELETE) {\n\t\tif (toLine <= dInfoPtr->currentMetricUpdateLine) {\n\t\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t\t    if (dInfoPtr->lastMetricUpdateLine != -1) {\n\t\t\tdInfoPtr->lastMetricUpdateLine -= lineCount;\n\t\t    }\n\t\t} else if (fromLine <= dInfoPtr->currentMetricUpdateLine) {\n\t\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t\t    if (toLine <= dInfoPtr->lastMetricUpdateLine) {\n\t\t\tdInfoPtr->lastMetricUpdateLine -= lineCount;\n\t\t    }\n\t\t} else {\n\t\t    if (dInfoPtr->lastMetricUpdateLine != -1) {\n\t\t\tdInfoPtr->lastMetricUpdateLine = toLine;\n\t\t    }\n\t\t}\n\t    } else if (action == TK_TEXT_INVALIDATE_INSERT) {\n\t\tif (toLine <= dInfoPtr->currentMetricUpdateLine) {\n\t\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t\t    if (dInfoPtr->lastMetricUpdateLine != -1) {\n\t\t\tdInfoPtr->lastMetricUpdateLine += lineCount;\n\t\t    }\n\t\t} else if (fromLine <= dInfoPtr->currentMetricUpdateLine) {\n\t\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t\t    if (toLine <= dInfoPtr->lastMetricUpdateLine) {\n\t\t\tdInfoPtr->lastMetricUpdateLine += lineCount;\n\t\t    }\n\t\t    if (toLine > dInfoPtr->lastMetricUpdateLine) {\n\t\t\tdInfoPtr->lastMetricUpdateLine = toLine;\n\t\t    }\n\t\t} else {\n\t\t    if (dInfoPtr->lastMetricUpdateLine != -1) {\n\t\t\tdInfoPtr->lastMetricUpdateLine = toLine;\n\t\t    }\n\t\t}\n\t    } else {\n\t\tif (fromLine < dInfoPtr->currentMetricUpdateLine) {\n\t\t    dInfoPtr->currentMetricUpdateLine = fromLine;\n\t\t}\n\t\tif (dInfoPtr->lastMetricUpdateLine != -1\n\t\t\t&& toLine > dInfoPtr->lastMetricUpdateLine) {\n\t\t    dInfoPtr->lastMetricUpdateLine = toLine;\n\t\t}\n\t    }\n\t}\n    } else {\n\t/*\n\t * This invalidates the height of all lines in the widget.\n\t */\n\n\tif ((++dInfoPtr->lineMetricUpdateEpoch) == 0) {\n\t    dInfoPtr->lineMetricUpdateEpoch++;\n\t}\n\n\t/*\n\t * This has the effect of forcing an entire new loop of update checks\n\t * on all lines in the widget.\n\t */\n\n\tif (dInfoPtr->lineUpdateTimer == NULL) {\n\t    dInfoPtr->currentMetricUpdateLine = -1;\n\t}\n\tdInfoPtr->lastMetricUpdateLine = dInfoPtr->currentMetricUpdateLine;\n    }\n\n    /*\n     * Now re-set the current update calculations.\n     */\n\n    if (dInfoPtr->lineUpdateTimer == NULL) {\n\ttextPtr->refCount++;\n\tdInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,\n\t\tAsyncUpdateLineMetrics, textPtr);\n    }\n\n    /*\n     * The widget is out of sync: send a <<WidgetViewSync>> event.\n     */\n    GenerateWidgetViewSyncEvent(textPtr, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextFindDisplayLineEnd --\n *\n *\tThis function is invoked to find the index of the beginning or end of\n *\tthe particular display line on which the given index sits, whether\n *\tthat line is displayed or not.\n *\n *\tIf 'end' is zero, we look for the start, and if 'end' is one we look\n *\tfor the end.\n *\n *\tIf the beginning of the current display line is elided, and we are\n *\tlooking for the start of the line, then the returned index will be the\n *\tfirst elided index on the display line.\n *\n *\tSimilarly if the end of the current display line is elided and we are\n *\tlooking for the end, then the returned index will be the last elided\n *\tindex on the display line.\n *\n * Results:\n *\tModifies indexPtr to point to the given end.\n *\n *\tIf xOffset is non-NULL, it is set to the x-pixel offset of the given\n *\toriginal index within the given display line.\n *\n * Side effects:\n *\tThe combination of 'LayoutDLine' and 'FreeDLines' seems like a rather\n *\ttime-consuming way of gathering the information we need, so this would\n *\tbe a good place to look to speed up the calculations. In particular\n *\tthese calls will map and unmap embedded windows respectively, which I\n *\twould hope isn't exactly necessary!\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextFindDisplayLineEnd(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    TkTextIndex *indexPtr,\t/* Index we will adjust to the display line\n\t\t\t\t * start or end. */\n    int end,\t\t\t/* 0 = start, 1 = end. */\n    int *xOffset)\t\t/* NULL, or used to store the x-pixel offset\n\t\t\t\t * of the original index within its display\n\t\t\t\t * line. */\n{\n    TkTextIndex index;\n\n    if (!end && IsStartOfNotMergedLine(textPtr, indexPtr)) {\n\t/*\n\t * Nothing to do.\n\t */\n\n\tif (xOffset != NULL) {\n\t    *xOffset = 0;\n\t}\n\treturn;\n    }\n\n    index = *indexPtr;\n    index.byteIndex = 0;\n    index.textPtr = NULL;\n\n    while (1) {\n\tTkTextIndex endOfLastLine;\n\n\tif (TkTextIndexBackBytes(textPtr, &index, 1, &endOfLastLine)) {\n\t    /*\n\t     * Reached beginning of text.\n\t     */\n\n\t    break;\n\t}\n\n\tif (!TkTextIsElided(textPtr, &endOfLastLine, NULL)) {\n\t    /*\n\t     * The eol is not elided, so 'index' points to the start of a\n\t     * display line (as well as logical line).\n\t     */\n\n\t    break;\n\t}\n\n\t/*\n\t * indexPtr's logical line is actually merged with the previous\n\t * logical line whose eol is elided. Continue searching back to get a\n\t * real line start.\n\t */\n\n\tindex = endOfLastLine;\n\tindex.byteIndex = 0;\n    }\n\n    while (1) {\n\tDLine *dlPtr;\n\tTcl_Size byteCount;\n\tTkTextIndex nextLineStart;\n\n\tdlPtr = LayoutDLine(textPtr, &index);\n\tbyteCount = dlPtr->byteCount;\n\n\tTkTextIndexForwBytes(textPtr, &index, byteCount, &nextLineStart);\n\n\t/*\n\t * 'byteCount' goes up to the beginning of the next display line, so\n\t * equality here says we need one more line. We try to perform a quick\n\t * comparison which is valid for the case where the logical line is\n\t * the same, but otherwise fall back on a full TkTextIndexCmp.\n\t */\n\n\tif (((index.linePtr == indexPtr->linePtr)\n\t\t&& (index.byteIndex + byteCount > indexPtr->byteIndex))\n\t\t|| (dlPtr->logicalLinesMerged > 0\n\t\t&& TkTextIndexCmp(&nextLineStart, indexPtr) > 0)) {\n\t    /*\n\t     * It's on this display line.\n\t     */\n\n\t    if (xOffset != NULL) {\n\t\t/*\n\t\t * This call takes a byte index relative to the start of the\n\t\t * current _display_ line, not logical line. We are about to\n\t\t * overwrite indexPtr->byteIndex, so we must do this now.\n\t\t */\n\n\t\t*xOffset = DlineXOfIndex(textPtr, dlPtr,\n\t\t\tTkTextIndexCountBytes(textPtr, &dlPtr->index,\n\t\t\tindexPtr));\n\t    }\n\t    if (end) {\n\t\t/*\n\t\t * The index we want is one less than the number of bytes in\n\t\t * the display line.\n\t\t */\n\n\t\tTkTextIndexBackBytes(textPtr, &nextLineStart, 1, indexPtr);\n\t    } else {\n\t\t*indexPtr = index;\n\t    }\n\t    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\t    return;\n\t}\n\n\tFreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\tindex = nextLineStart;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CalculateDisplayLineHeight --\n *\n *\tThis function is invoked to recalculate the height of the particular\n *\tdisplay line which starts with the given index, whether that line is\n *\tdisplayed or not.\n *\n *\tThis function does not, in itself, update any cached information about\n *\tline heights. That should be done, where necessary, by its callers.\n *\n *\tThe behaviour of this function is _undefined_ if indexPtr is not\n *\tcurrently at the beginning of a display line.\n *\n * Results:\n *\tThe number of vertical pixels used by the display line.\n *\n *\tIf 'byteCountPtr' is non-NULL, then returns in that pointer the number\n *\tof byte indices on the given display line (which can be used to update\n *\tindexPtr in a loop).\n *\n *\tIf 'mergedLinePtr' is non-NULL, then returns in that pointer the\n *\tnumber of extra logical lines merged into the given display line.\n *\n * Side effects:\n *\tThe combination of 'LayoutDLine' and 'FreeDLines' seems like a rather\n *\ttime-consuming way of gathering the information we need, so this would\n *\tbe a good place to look to speed up the calculations. In particular\n *\tthese calls will map and unmap embedded windows respectively, which I\n *\twould hope isn't exactly necessary!\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCalculateDisplayLineHeight(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    const TkTextIndex *indexPtr,/* The index at the beginning of the display\n\t\t\t\t * line of interest. */\n    int *byteCountPtr,\t\t/* NULL or used to return the number of byte\n\t\t\t\t * indices on the given display line. */\n    int *mergedLinePtr)\t\t/* NULL or used to return if the given display\n\t\t\t\t * line merges with a following logical line\n\t\t\t\t * (because the eol is elided). */\n{\n    DLine *dlPtr;\n    int pixelHeight;\n\n    if (tkTextDebug) {\n\tint oldtkTextDebug = tkTextDebug;\n\t/*\n\t * Check that the indexPtr we are given really is at the start of a\n\t * display line. The gymnastics with tkTextDebug is to prevent\n\t * failure of a test suite test, that checks that lines are rendered\n\t * exactly once. TkTextFindDisplayLineEnd is used here for checking\n\t * indexPtr but it calls LayoutDLine/FreeDLine which makes the\n\t * counting wrong. The debug mode shall therefore be switched off\n\t * when calling TkTextFindDisplayLineEnd.\n\t */\n\n\tTkTextIndex indexPtr2 = *indexPtr;\n\ttkTextDebug = 0;\n\tTkTextFindDisplayLineEnd(textPtr, &indexPtr2, 0, NULL);\n\ttkTextDebug = oldtkTextDebug;\n\tif (TkTextIndexCmp(&indexPtr2,indexPtr) != 0) {\n\t    Tcl_Panic(\"CalculateDisplayLineHeight called with bad indexPtr\");\n\t}\n    }\n\n    /*\n     * Special case for artificial last line. May be better to move this\n     * inside LayoutDLine.\n     */\n\n    if (indexPtr->byteIndex == 0\n\t    && TkBTreeNextLine(textPtr, indexPtr->linePtr) == NULL) {\n\tif (byteCountPtr != NULL) {\n\t    *byteCountPtr = 0;\n\t}\n\tif (mergedLinePtr != NULL) {\n\t    *mergedLinePtr = 0;\n\t}\n\treturn 0;\n    }\n\n    /*\n     * Layout, find the information we need and then free the display-line we\n     * laid-out. We must use 'FreeDLines' because it will actually call the\n     * relevant code to unmap any embedded windows which were mapped in the\n     * LayoutDLine call!\n     */\n\n    dlPtr = LayoutDLine(textPtr, indexPtr);\n    pixelHeight = dlPtr->height;\n    if (byteCountPtr != NULL) {\n\t*byteCountPtr = dlPtr->byteCount;\n    }\n    if (mergedLinePtr != NULL) {\n\t*mergedLinePtr = dlPtr->logicalLinesMerged;\n    }\n    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\n    return pixelHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextIndexYPixels --\n *\n *\tThis function is invoked to calculate the number of vertical pixels\n *\tbetween the first index of the text widget and the given index. The\n *\trange from first logical line to given logical line is determined\n *\tusing the cached values, and the range inside the given logical line\n *\tis calculated on the fly.\n *\n * Results:\n *\tThe pixel distance between first pixel in the widget and the\n *\ttop of the index's current display line (could be zero).\n *\n * Side effects:\n *\tJust those of 'CalculateDisplayLineHeight'.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkTextIndexYPixels(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    const TkTextIndex *indexPtr)/* The index of which we want the pixel\n\t\t\t\t * distance from top of logical line to top of\n\t\t\t\t * index. */\n{\n    int pixelHeight;\n    TkTextIndex index;\n    int alreadyStartOfLine = 1;\n\n    /*\n     * Find the index denoting the closest position being at the same time\n     * the start of a logical line above indexPtr and the start of a display\n     * line.\n     */\n\n    index = *indexPtr;\n    while (1) {\n\tTkTextFindDisplayLineEnd(textPtr, &index, 0, NULL);\n\tif (index.byteIndex == 0) {\n\t    break;\n\t}\n\tTkTextIndexBackBytes(textPtr, &index, 1, &index);\n\talreadyStartOfLine = 0;\n    }\n\n    pixelHeight = TkBTreePixelsTo(textPtr, index.linePtr);\n\n    /*\n     * Shortcut to avoid layout of a superfluous display line. We know there\n     * is nothing more to add up to the height if the index we were given was\n     * already on the first display line of a logical line.\n     */\n\n    if (alreadyStartOfLine) {\n\treturn pixelHeight;\n    }\n\n    /*\n     * Iterate through display lines, starting at the logical line belonging\n     * to index, adding up the pixel height of each such display line as we\n     * go along, until we go past 'indexPtr'.\n     */\n\n    while (1) {\n\tint bytes, height, compare;\n\n\t/*\n\t * Currently this call doesn't have many side-effects. However, if in\n\t * the future we change the code so there are side-effects (such as\n\t * adjusting linePtr->pixelHeight), then the code might not quite work\n\t * as intended, specifically the 'linePtr->pixelHeight == pixelHeight'\n\t * test below this while loop.\n\t */\n\n\theight = CalculateDisplayLineHeight(textPtr, &index, &bytes, NULL);\n\n\tTkTextIndexForwBytes(textPtr, &index, bytes, &index);\n\n\tcompare = TkTextIndexCmp(&index,indexPtr);\n\tif (compare > 0) {\n\t    return pixelHeight;\n\t}\n\n\tif (height > 0) {\n\t    pixelHeight += height;\n\t}\n\n\tif (compare == 0) {\n\t    return pixelHeight;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextUpdateOneLine --\n *\n *\tThis function is invoked to recalculate the height of a particular\n *\tlogical line, whether that line is displayed or not.\n *\n *\tIt must NEVER be called for the artificial last TkTextLine which is\n *\tused internally for administrative purposes only. That line must\n *\tretain its initial height of 0 otherwise the pixel height calculation\n *\tmaintained by the B-tree will be wrong.\n *\n * Results:\n *\tThe number of display lines in the logical line. This could be zero if\n *\tthe line is totally elided.\n *\n * Side effects:\n *\tLine heights may be recalculated, and a timer to update the scrollbar\n *\tmay be installed. Also see the called function\n *\tCalculateDisplayLineHeight for its side effects.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkTextUpdateOneLine(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    TkTextLine *linePtr,\t/* The line of which to calculate the\n\t\t\t\t * height. */\n    int pixelHeight,\t\t/* If indexPtr is non-NULL, then this is the\n\t\t\t\t * number of pixels in the logical line\n\t\t\t\t * linePtr, up to the index which has been\n\t\t\t\t * given. */\n    TkTextIndex *indexPtr,\t/* Either NULL or an index at the start of a\n\t\t\t\t * display line belonging to linePtr, at which\n\t\t\t\t * we wish to start (e.g. up to which we have\n\t\t\t\t * already calculated). On return this will be\n\t\t\t\t * set to the first index on the next line. */\n    int partialCalc)\t\t/* Set to 1 if we are allowed to do partial\n\t\t\t\t * height calculations of long-lines. In this\n\t\t\t\t * case we'll only return what we know so\n\t\t\t\t * far. */\n{\n    TkTextIndex index;\n    int displayLines;\n    int mergedLines;\n\n    if (indexPtr == NULL) {\n\tindex.tree = textPtr->sharedTextPtr->tree;\n\tindex.linePtr = linePtr;\n\tindex.byteIndex = 0;\n\tindex.textPtr = NULL;\n\tindexPtr = &index;\n\tpixelHeight = 0;\n    }\n\n    /*\n     * CalculateDisplayLineHeight _must_ be called (below) with an index at\n     * the beginning of a display line. Force this to happen. This is needed\n     * when TkTextUpdateOneLine is called with a line that is merged with its\n     * previous line: the number of merged logical lines in a display line is\n     * calculated correctly only when CalculateDisplayLineHeight receives\n     * an index at the beginning of a display line. In turn this causes the\n     * merged lines to receive their correct zero pixel height in\n     * TkBTreeAdjustPixelHeight.\n     */\n\n    TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);\n    linePtr = indexPtr->linePtr;\n\n    /*\n     * Iterate through all display-lines corresponding to the single logical\n     * line 'linePtr' (and lines merged into this line due to eol elision),\n     * adding up the pixel height of each such display line as we go along.\n     * The final total is, therefore, the total height of all display lines\n     * made up by the logical line 'linePtr' and subsequent logical lines\n     * merged into this line.\n     */\n\n    displayLines = 0;\n    mergedLines = 0;\n\n    while (1) {\n\tint bytes, height, logicalLines;\n\n\t/*\n\t * Currently this call doesn't have many side-effects. However, if in\n\t * the future we change the code so there are side-effects (such as\n\t * adjusting linePtr->pixelHeight), then the code might not quite work\n\t * as intended, specifically the 'linePtr->pixelHeight == pixelHeight'\n\t * test below this while loop.\n\t */\n\n\theight = CalculateDisplayLineHeight(textPtr, indexPtr, &bytes,\n\t\t&logicalLines);\n\n\tif (height > 0) {\n\t    pixelHeight += height;\n\t    displayLines++;\n\t}\n\n\tmergedLines += logicalLines;\n\n\tif (TkTextIndexForwBytes(textPtr, indexPtr, bytes, indexPtr)) {\n\t    break;\n\t}\n\n\tif (mergedLines == 0) {\n\t    if (indexPtr->linePtr != linePtr) {\n\t\t/*\n\t\t * If we reached the end of the logical line, then either way\n\t\t * we don't have a partial calculation.\n\t\t */\n\n\t\tpartialCalc = 0;\n\t\tbreak;\n\t    }\n\t} else {\n\t    if (IsStartOfNotMergedLine(textPtr, indexPtr)) {\n\t\t/*\n\t\t * We've ended a logical line.\n\t\t */\n\n\t\tpartialCalc = 0;\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * We must still be on the same wrapped line, on a new logical\n\t     * line merged with the logical line 'linePtr'.\n\t     */\n\t}\n\tif (partialCalc && displayLines > 50 && mergedLines == 0) {\n\t    /*\n\t     * Only calculate 50 display lines at a time, to avoid huge\n\t     * delays. In any case it is very rare that a single line wraps 50\n\t     * times!\n\t     *\n\t     * If we have any merged lines, we must complete the full logical\n\t     * line layout here and now, because the partial-calculation code\n\t     * isn't designed to handle merged logical lines. Hence the\n\t     * 'mergedLines == 0' check.\n\t     */\n\n\t    break;\n\t}\n    }\n\n    if (!partialCalc) {\n\tint changed = 0;\n\n\t/*\n\t * Cancel any partial line height calculation state.\n\t */\n\n\ttextPtr->dInfoPtr->metricEpoch = -1;\n\n\t/*\n\t * Mark the logical line as being up to date (caution: it isn't yet up\n\t * to date, that will happen in TkBTreeAdjustPixelHeight just below).\n\t */\n\n\tTkBTreeLinePixelEpoch(textPtr, linePtr)\n\t\t= textPtr->dInfoPtr->lineMetricUpdateEpoch;\n\tif (TkBTreeLinePixelCount(textPtr, linePtr) != pixelHeight) {\n\t    changed = 1;\n\t}\n\n\tif (mergedLines > 0) {\n\t    int i = mergedLines;\n\t    TkTextLine *mergedLinePtr;\n\n\t    /*\n\t     * Loop over all merged logical lines, marking them up to date\n\t     * (again, the pixel count setting will actually happen in\n\t     * TkBTreeAdjustPixelHeight).\n\t     */\n\n\t    mergedLinePtr = linePtr;\n\t    while (i-- > 0) {\n\t\tmergedLinePtr = TkBTreeNextLine(textPtr, mergedLinePtr);\n\t\tTkBTreeLinePixelEpoch(textPtr, mergedLinePtr)\n\t\t\t= textPtr->dInfoPtr->lineMetricUpdateEpoch;\n\t\tif (TkBTreeLinePixelCount(textPtr, mergedLinePtr) != 0) {\n\t\t    changed = 1;\n\t\t}\n\t    }\n\t}\n\n\tif (!changed) {\n\t    /*\n\t     * If there's nothing to change, then we can already return.\n\t     */\n\n\t    return displayLines;\n\t}\n    }\n\n    /*\n     * We set the line's height, but the return value is now the height of the\n     * entire widget, which may be used just below for reporting/debugging\n     * purposes.\n     */\n\n    pixelHeight = TkBTreeAdjustPixelHeight(textPtr, linePtr, pixelHeight,\n\t    mergedLines);\n\n    if (tkTextDebug) {\n\tchar buffer[2 * TCL_INTEGER_SPACE + 1];\n\n\tif (TkBTreeNextLine(textPtr, linePtr) == NULL) {\n\t    Tcl_Panic(\"Mustn't ever update line height of last artificial line\");\n\t}\n\n\tsnprintf(buffer, sizeof(buffer), \"%\" TCL_Z_MODIFIER \"d %d\", TkBTreeLinesTo(textPtr,linePtr), pixelHeight);\n\tLOG(\"tk_textNumPixels\", buffer);\n    }\n    if (textPtr->dInfoPtr->scrollbarTimer == NULL) {\n\ttextPtr->refCount++;\n\ttextPtr->dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200,\n\t\tAsyncUpdateYScrollbar, textPtr);\n    }\n    return displayLines;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayText --\n *\n *\tThis function is invoked as a when-idle handler to update the display.\n *\tIt only redisplays the parts of the text widget that are out of date.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation is redrawn on the screen.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayText(\n    void *clientData)\t/* Information about widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr;\n    DLine *prevPtr;\n    Pixmap pixmap;\n    int maxHeight, borders;\n    int bottomY = 0;\t\t/* Initialization needed only to stop compiler\n\t\t\t\t * warnings. */\n    Tcl_Interp *interp;\n    int padX, padY;\n    int borderWidth, highlightWidth;\n\n\n    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t/*\n\t * The widget has been deleted.\t Don't do anything.\n\t */\n\n\treturn;\n    }\n\n    interp = textPtr->interp;\n    Tcl_Preserve(interp);\n\n    if (tkTextDebug) {\n\tCLEAR(\"tk_textRelayout\");\n    }\n\n    if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x)\n\t    || (dInfoPtr->maxY <= dInfoPtr->y)) {\n\tUpdateDisplayInfo(textPtr);\n\tdInfoPtr->flags &= ~REDRAW_PENDING;\n\tgoto doScrollbars;\n    }\n    numRedisplays++;\n    if (tkTextDebug) {\n\tCLEAR(\"tk_textRedraw\");\n    }\n\n    /*\n     * Choose a new current item if that is needed (this could cause event\n     * handlers to be invoked, hence the refcount management and the loop,\n     * since the handlers could conceivably necessitate yet another current\n     * item calculation). The tkwin check is because the whole window could go\n     * away in the Tcl_Release call.\n     */\n\n    while (dInfoPtr->flags & REPICK_NEEDED) {\n\ttextPtr->refCount++;\n\tdInfoPtr->flags &= ~REPICK_NEEDED;\n\tTkTextPickCurrent(textPtr, &textPtr->pickEvent);\n\tif (textPtr->refCount-- <= 1) {\n\t    Tcl_Free(textPtr);\n\t    goto end;\n\t}\n\tif ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t    goto end;\n\t}\n    }\n\n    /*\n     * First recompute what's supposed to be displayed.\n     */\n\n    UpdateDisplayInfo(textPtr);\n    dInfoPtr->dLinesInvalidated = 0;\n\n    /*\n     * See if it's possible to bring some parts of the screen up-to-date by\n     * scrolling (copying from other parts of the screen). We have to be\n     * particularly careful with the top and bottom lines of the display,\n     * since these may only be partially visible and therefore not helpful for\n     * some scrolling purposes.\n     */\n\n    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {\n\tDLine *dlPtr2;\n\tint offset, height, y, oldY;\n\tRegion damageRgn;\n\n\t/*\n\t * These tests are, in order:\n\t *\n\t * 1. If the line is already marked as invalid\n\t * 2. If the line hasn't moved\n\t * 3. If the line overlaps the bottom of the window and we are\n\t *    scrolling up.\n\t * 4. If the line overlaps the top of the window and we are scrolling\n\t *    down.\n\t *\n\t * If any of these tests are true, then we can't scroll this line's\n\t * part of the display.\n\t *\n\t * Note that even if tests 3 or 4 aren't true, we may be able to\n\t * scroll the line, but we still need to be sure to call embedded\n\t * window display procs on top and bottom lines if they have any\n\t * portion non-visible (see below).\n\t */\n\n\tif ((dlPtr->flags & OLD_Y_INVALID)\n\t\t|| (dlPtr->y == dlPtr->oldY)\n\t\t|| (((dlPtr->oldY + dlPtr->height) > dInfoPtr->maxY)\n\t\t    && (dlPtr->y < dlPtr->oldY))\n\t\t|| ((dlPtr->oldY < dInfoPtr->y) && (dlPtr->y > dlPtr->oldY))) {\n\t    continue;\n\t}\n\n\t/*\n\t * This line is already drawn somewhere in the window so it only needs\n\t * to be copied to its new location. See if there's a group of lines\n\t * that can all be copied together.\n\t */\n\n\toffset = dlPtr->y - dlPtr->oldY;\n\theight = dlPtr->height;\n\ty = dlPtr->y;\n\tfor (dlPtr2 = dlPtr->nextPtr; dlPtr2 != NULL;\n\t\tdlPtr2 = dlPtr2->nextPtr) {\n\t    if ((dlPtr2->flags & OLD_Y_INVALID)\n\t\t    || ((dlPtr2->oldY + offset) != dlPtr2->y)\n\t\t    || ((dlPtr2->oldY + dlPtr2->height) > dInfoPtr->maxY)) {\n\t\tbreak;\n\t    }\n\t    height += dlPtr2->height;\n\t}\n\n\t/*\n\t * Reduce the height of the area being copied if necessary to avoid\n\t * overwriting the border area.\n\t */\n\n\tif ((y + height) > dInfoPtr->maxY) {\n\t    height = dInfoPtr->maxY - y;\n\t}\n\toldY = dlPtr->oldY;\n\tif (y < dInfoPtr->y) {\n\t    /*\n\t     * Adjust if the area being copied is going to overwrite the top\n\t     * border of the window (so the top line is only half onscreen).\n\t     */\n\n\t    int y_off = dInfoPtr->y - dlPtr->y;\n\t    height -= y_off;\n\t    oldY += y_off;\n\t    y = dInfoPtr->y;\n\t}\n\n\t/*\n\t * Update the lines we are going to scroll to show that they have been\n\t * copied.\n\t */\n\n\twhile (1) {\n\t    /*\n\t     * The DLine already has OLD_Y_INVALID cleared.\n\t     */\n\n\t    dlPtr->oldY = dlPtr->y;\n\t    if (dlPtr->nextPtr == dlPtr2) {\n\t\tbreak;\n\t    }\n\t    dlPtr = dlPtr->nextPtr;\n\t}\n\t/*\n\t * Scan through the lines following the copied ones to see if we are\n\t * going to overwrite them with the copy operation. If so, mark them\n\t * for redisplay.\n\t */\n\n\tfor ( ; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {\n\t    if ((!(dlPtr2->flags & OLD_Y_INVALID))\n\t\t    && ((dlPtr2->oldY + dlPtr2->height) > y)\n\t\t    && (dlPtr2->oldY < (y + height))) {\n\t\tdlPtr2->flags |= OLD_Y_INVALID;\n\t    }\n\t}\n\n\t/*\n\t * Now scroll the lines. This may generate damage which we handle by\n\t * calling TextInvalidateRegion to mark the display blocks as stale.\n\t */\n\n\tdamageRgn = XCreateRegion();\n\tif (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, dInfoPtr->x,\n\t\toldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY,\n\t\tdamageRgn)) {\n#ifndef MACOSX_TK\n\t    /* No point in doing this on macOS. The DLines get redrawn anyway.*/\n\t    TextInvalidateRegion(textPtr, damageRgn);\n#endif\n\t}\n\tnumCopies++;\n\tXDestroyRegion(damageRgn);\n    }\n\n    /*\n     * Clear the REDRAW_PENDING flag here. This is actually pretty tricky. We\n     * want to wait until *after* doing the scrolling, since that could\n     * generate more areas to redraw and don't want to reschedule a redisplay\n     * for them. On the other hand, we can't wait until after all the\n     * redisplaying, because the act of redisplaying could actually generate\n     * more redisplays (e.g. in the case of a nested window with event\n     * bindings triggered by redisplay).\n     */\n\n    dInfoPtr->flags &= ~REDRAW_PENDING;\n\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padYObj, &padY);\n\n    /*\n     * Redraw the borders if that's needed.\n     */\n\n    if (dInfoPtr->flags & REDRAW_BORDERS) {\n\tif (tkTextDebug) {\n\t    LOG(\"tk_textRedraw\", \"borders\");\n\t}\n\n\tif (textPtr->tkwin == NULL) {\n\t    /*\n\t     * The widget has been deleted. Don't do anything.\n\t     */\n\n\t    goto end;\n\t}\n\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->borderWidthObj, &borderWidth);\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->highlightWidthObj, &highlightWidth);\n\tTk_Draw3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\ttextPtr->border, highlightWidth,\n\t\thighlightWidth,\n\t\tTk_Width(textPtr->tkwin) - 2 * highlightWidth,\n\t\tTk_Height(textPtr->tkwin) - 2 * highlightWidth,\n\t\tborderWidth, textPtr->relief);\n\tif (highlightWidth > 0) {\n\t    GC fgGC, bgGC;\n\n\t    bgGC = Tk_GCForColor(textPtr->highlightBgColorPtr,\n\t\t    Tk_WindowId(textPtr->tkwin));\n\t    if (textPtr->flags & GOT_FOCUS) {\n\t\tfgGC = Tk_GCForColor(textPtr->highlightColorPtr,\n\t\t\tTk_WindowId(textPtr->tkwin));\n\t\tTk_DrawHighlightBorder(textPtr->tkwin, fgGC, bgGC,\n\t\t\thighlightWidth, Tk_WindowId(textPtr->tkwin));\n\t    } else {\n\t\tTk_DrawHighlightBorder(textPtr->tkwin, bgGC, bgGC,\n\t\t\thighlightWidth, Tk_WindowId(textPtr->tkwin));\n\t    }\n\t}\n\tborders = borderWidth + highlightWidth;\n\tif (padY > 0) {\n\t    Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\t    textPtr->border, borders, borders,\n\t\t    Tk_Width(textPtr->tkwin) - 2 * borders, padY,\n\t\t    0, TK_RELIEF_FLAT);\n\t    Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\t    textPtr->border, borders,\n\t\t    Tk_Height(textPtr->tkwin) - borders - padY,\n\t\t    Tk_Width(textPtr->tkwin) - 2 * borders,\n\t\t    padY, 0, TK_RELIEF_FLAT);\n\t}\n\tif (padX > 0) {\n\t    Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\t    textPtr->border, borders, borders + padY,\n\t\t    padX,\n\t\t    Tk_Height(textPtr->tkwin) - 2 * borders -2 * padY,\n\t\t    0, TK_RELIEF_FLAT);\n\t    Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\t    textPtr->border,\n\t\t    Tk_Width(textPtr->tkwin) - borders - padX,\n\t\t    borders + padY, padX,\n\t\t    Tk_Height(textPtr->tkwin) - 2 * borders -2 * padY,\n\t\t    0, TK_RELIEF_FLAT);\n\t}\n\tdInfoPtr->flags &= ~REDRAW_BORDERS;\n    }\n\n    /*\n     * Now we have to redraw the lines that couldn't be updated by scrolling.\n     * First, compute the height of the largest line and allocate an off-\n     * screen pixmap to use for double-buffered displays.\n     */\n\n    maxHeight = -1;\n    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;\n\t    dlPtr = dlPtr->nextPtr) {\n\tif ((dlPtr->height > maxHeight) &&\n\t\t((dlPtr->flags&OLD_Y_INVALID) || (dlPtr->oldY != dlPtr->y))) {\n\t    maxHeight = dlPtr->height;\n\t}\n\tbottomY = dlPtr->y + dlPtr->height;\n    }\n\n    /*\n     * There used to be a line here which restricted 'maxHeight' to be no\n     * larger than 'dInfoPtr->maxY', but this is incorrect for the case where\n     * individual lines may be taller than the widget _and_ we have smooth\n     * scrolling. What we can do is restrict maxHeight to be no larger than\n     * 'dInfoPtr->maxY + dInfoPtr->topPixelOffset'.\n     */\n\n    if (maxHeight > (dInfoPtr->maxY + dInfoPtr->topPixelOffset)) {\n\tmaxHeight = (dInfoPtr->maxY + dInfoPtr->topPixelOffset);\n    }\n\n    if (maxHeight > 0) {\n#ifndef TK_NO_DOUBLE_BUFFERING\n\tpixmap = Tk_GetPixmap(Tk_Display(textPtr->tkwin),\n\t\tTk_WindowId(textPtr->tkwin), Tk_Width(textPtr->tkwin),\n\t\tmaxHeight, Tk_Depth(textPtr->tkwin));\n#else\n\tpixmap = Tk_WindowId(textPtr->tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\tfor (prevPtr = NULL, dlPtr = textPtr->dInfoPtr->dLinePtr;\n\t\t(dlPtr != NULL) && (dlPtr->y < dInfoPtr->maxY);\n\t\tprevPtr = dlPtr, dlPtr = dlPtr->nextPtr) {\n\t    if (dlPtr->chunkPtr == NULL) {\n\t\tcontinue;\n\t    }\n\t    if ((dlPtr->flags & OLD_Y_INVALID) || dlPtr->oldY != dlPtr->y) {\n\t\tif (tkTextDebug) {\n\t\t    char string[TK_POS_CHARS];\n\n\t\t    TkTextPrintIndex(textPtr, &dlPtr->index, string);\n\t\t    LOG(\"tk_textRedraw\", string);\n\t\t}\n\t\tDisplayDLine(textPtr, dlPtr, prevPtr, pixmap);\n\t\tif ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t\t    /*\n\t\t     * DisplayDLine called a displayProc which invoked a binding\n\t\t     * that caused the widget to be deleted. Don't do anything.\n\t\t     */\n\t\t    goto end;\n\t\t}\n\t\tif (dInfoPtr->dLinesInvalidated) {\n#ifndef TK_NO_DOUBLE_BUFFERING\n\t\t    Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\t\t    goto end;\n\t\t}\n\t\tdlPtr->oldY = dlPtr->y;\n\t\tdlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID);\n#ifdef MAC_OSX_TK\n\t    } else if (dlPtr->chunkPtr != NULL) {\n\t\t/*\n\t\t * On macOS we need to redisplay all embedded windows which\n\t\t * were moved by the call to TkScrollWindows above.  This is\n\t\t * not necessary on Unix or Windows because XScrollWindow will\n\t\t * have included the bounding rectangles of all of these\n\t\t * windows in the damage region.  The macosx implementation of\n\t\t * TkScrollWindow is not able to do this because no\n\t\t * information about embedded windows is avaliable to it. So\n\t\t * it simply generates a damage region which is the scroll\n\t\t * source rectangle minus the scroll destination rectangle.\n\t\t * (On Unix this is handled by GraphicsExpose events generated\n\t\t * by XCopyArea and on Windows by ScrollWindowEx.  On macOS\n\t\t * the embedded windows are not managed by the window manager,\n\t\t * so there is no analogous technique available.)\n\t\t *\n\t\t * On the other hand, this loop is already iterating through\n\t\t * all embedded windows which could possibly have been moved\n\t\t * by the scrolling.  So it is as efficient to redisplay them\n\t\t * here as it would have been if they had been redisplayed by\n\t\t * the call to TextInvalidateRegion above.\n\t\t */\n#else\n\t    } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0)\n\t\t    || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) {\n\t\t/*\n\t\t * On platforms other than macOS ...\n\t\t *\n\t\t * It's the first or last DLine which are also overlapping the\n\t\t * top or bottom of the window, but we decided above it wasn't\n\t\t * necessary to display them (we were able to update them by\n\t\t * scrolling). This is fine, except that if the lines contain\n\t\t * any embedded windows, we must still call the display proc\n\t\t * on them because they might need to be unmapped or they\n\t\t * might need to be moved to reflect their new position.\n\t\t * Otherwise, everything else moves, but the embedded window\n\t\t * doesn't!\n\t\t *\n\t\t * So, we loop through all the chunks, calling the display\n\t\t * proc of embedded windows only.\n\t\t */\n#endif\n\t\tTkTextDispChunk *chunkPtr;\n\n\t\tfor (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);\n\t\t\tchunkPtr = chunkPtr->nextPtr) {\n\t\t    int x;\n\t\t    if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset;\n\t\t    if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) {\n\t\t\t/*\n\t\t\t * Note: we have to call the displayProc even for\n\t\t\t * chunks that are off-screen. This is needed, for\n\t\t\t * example, so that embedded windows can be unmapped\n\t\t\t * in this case. Display the chunk at a coordinate\n\t\t\t * that can be clearly identified by the displayProc\n\t\t\t * as being off-screen to the left (the displayProc\n\t\t\t * may not be able to tell if something is off to the\n\t\t\t * right).\n\t\t\t */\n\n\t\t\tx = -chunkPtr->width;\n\t\t    }\n\t\t    if (tkTextDebug) {\n\t\t\tchar string[TK_POS_CHARS];\n\n\t\t\tTkTextPrintIndex(textPtr, &dlPtr->index, string);\n\t\t\tLOG(\"tk_textEmbWinDisplay\", string);\n\t\t    }\n#ifdef MAC_OSX_TK\n\t\t    /* We need to redisplay the entire DLine so that the\n\t\t     * background of the line will not contain artifacts left\n\t\t     * by the scrolling.\n\t\t     */\n\n\t\t    DisplayDLine(textPtr, dlPtr, NULL, pixmap);\n#else\n\t\t    TkTextEmbWinDisplayProc(textPtr, chunkPtr, x,\n\t\t\t    0,\n\t\t\t    dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow,\n\t\t\t    dlPtr->baseline - dlPtr->spaceAbove,\n\t\t\t    NULL,\n\t\t\t    None,\n\t\t\t    dlPtr->y + dlPtr->spaceAbove);\n#endif\n\t\t}\n\t    }\n\t}\n#ifndef TK_NO_DOUBLE_BUFFERING\n\tTk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    }\n\n    /*\n     * See if we need to refresh the part of the window below the last line of\n     * text (if there is any such area). Refresh the padding area on the left\n     * too, since the insertion cursor might have been displayed there\n     * previously).\n     */\n\n    if (dInfoPtr->topOfEof > dInfoPtr->maxY) {\n\tdInfoPtr->topOfEof = dInfoPtr->maxY;\n    }\n    if (bottomY < dInfoPtr->topOfEof) {\n\tif (tkTextDebug) {\n\t    LOG(\"tk_textRedraw\", \"eof\");\n\t}\n\n\tif ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t    /*\n\t     * The widget has been deleted. Don't do anything.\n\t     */\n\n\t    goto end;\n\t}\n\n\tTk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),\n\t\ttextPtr->border, dInfoPtr->x - padX, bottomY,\n\t\tdInfoPtr->maxX - (dInfoPtr->x - padX),\n\t\tdInfoPtr->topOfEof-bottomY, 0, TK_RELIEF_FLAT);\n    }\n    dInfoPtr->topOfEof = bottomY;\n\n    /*\n     * Update the vertical scrollbar, if there is one. Note: it's important to\n     * clear REDRAW_PENDING here, just in case the scroll function does\n     * something that requires redisplay.\n     */\n\n  doScrollbars:\n    if (textPtr->flags & UPDATE_SCROLLBARS) {\n\ttextPtr->flags &= ~UPDATE_SCROLLBARS;\n\tif (textPtr->yScrollCmdObj != NULL) {\n\t    GetYView(textPtr->interp, textPtr, 1);\n\t}\n\n\tif ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {\n\t    /*\n\t     * The widget has been deleted. Don't do anything.\n\t     */\n\n\t    goto end;\n\t}\n\n\t/*\n\t * Update the horizontal scrollbar, if any.\n\t */\n\n\tif (textPtr->xScrollCmdObj != NULL) {\n\t    GetXView(textPtr->interp, textPtr, 1);\n\t}\n    }\n\n  end:\n    Tcl_Release(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextEventuallyRepick --\n *\n *\tThis function is invoked whenever something happens that could change\n *\tthe current character or the tags associated with it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA repick is scheduled as an idle handler.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextEventuallyRepick(\n    TkText *textPtr)\t\t/* Widget record for text widget. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n\n    dInfoPtr->flags |= REPICK_NEEDED;\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tdInfoPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextRedrawRegion --\n *\n *\tThis function is invoked to schedule a redisplay for a given region of\n *\ta text widget. The redisplay itself may not occur immediately: it's\n *\tscheduled as a when-idle handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation will eventually be redrawn on the screen.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextRedrawRegion(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    int x, int y,\t\t/* Coordinates of upper-left corner of area to\n\t\t\t\t * be redrawn, in pixels relative to textPtr's\n\t\t\t\t * window. */\n    int width, int height)\t/* Width and height of area to be redrawn. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    Region damageRgn = XCreateRegion();\n    XRectangle rect;\n\n    rect.x = (short)x;\n    rect.y = (short)y;\n    rect.width = (unsigned short)width;\n    rect.height = (unsigned short)height;\n    XUnionRectWithRegion(&rect, damageRgn, damageRgn);\n\n    TextInvalidateRegion(textPtr, damageRgn);\n\n    XDestroyRegion(damageRgn);\n\n    /*\n     * Schedule the redisplay operation if there isn't one already scheduled.\n     */\n\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tdInfoPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextInvalidateRegion --\n *\n *\tMark a region of text as invalid.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUpdates the display information for the text widget.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTextInvalidateRegion(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    Region region)\t\t/* Region of area to redraw. */\n{\n    DLine *dlPtr;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    int maxY, inset;\n    XRectangle rect;\n    int padX, padY;\n    int borderWidth, highlightWidth;\n\n    /*\n     * Find all lines that overlap the given region and mark them for\n     * redisplay.\n     */\n\n    XClipBox(region, &rect);\n    maxY = rect.y + rect.height;\n    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;\n\t    dlPtr = dlPtr->nextPtr) {\n\tif ((!(dlPtr->flags & OLD_Y_INVALID))\n\t\t&& (XRectInRegion(region, rect.x, dlPtr->y,\n\t\trect.width, (unsigned int) dlPtr->height) != RectangleOut)) {\n\t    dlPtr->flags |= OLD_Y_INVALID;\n\t}\n    }\n    if (dInfoPtr->topOfEof < maxY) {\n\tdInfoPtr->topOfEof = maxY;\n    }\n\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->highlightWidthObj, &highlightWidth);\n    inset = borderWidth + highlightWidth;\n    if ((rect.x < (inset + padX))\n\t    || (rect.y < (inset + padY))\n\t    || ((int) (rect.x + rect.width) > (Tk_Width(textPtr->tkwin)\n\t\t    - inset - padX))\n\t    || (maxY > (Tk_Height(textPtr->tkwin) - inset - padY))) {\n\tdInfoPtr->flags |= REDRAW_BORDERS;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextChanged, TextChanged --\n *\n *\tThis function is invoked when info in a text widget is about to be\n *\tmodified in a way that changes how it is displayed (e.g. characters\n *\twere inserted or deleted, or tag information was changed). This\n *\tfunction must be called *before* a change is made, so that indexes in\n *\tthe display information are still valid.\n *\n *\tNote: if the range of indices may change geometry as well as simply\n *\trequiring redisplay, then the caller should also call\n *\tTkTextInvalidateLineMetrics.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe range of character between index1Ptr (inclusive) and index2Ptr\n *\t(exclusive) will be redisplayed at some point in the future (the\n *\tactual redisplay is scheduled as a when-idle handler).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextChanged(\n    TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */\n    TkText *textPtr,\t\t/* Widget record for text widget, or NULL. */\n    const TkTextIndex*index1Ptr,/* Index of first character to redisplay. */\n    const TkTextIndex*index2Ptr)/* Index of character just after last one to\n\t\t\t\t * redisplay. */\n{\n    if (sharedTextPtr == NULL) {\n\tTextChanged(textPtr, index1Ptr, index2Ptr);\n    } else {\n\ttextPtr = sharedTextPtr->peers;\n\twhile (textPtr != NULL) {\n\t    TextChanged(textPtr, index1Ptr, index2Ptr);\n\t    textPtr = textPtr->next;\n\t}\n    }\n}\n\f\nstatic void\nTextChanged(\n    TkText *textPtr,\t\t/* Widget record for text widget, or NULL. */\n    const TkTextIndex*index1Ptr,/* Index of first character to redisplay. */\n    const TkTextIndex*index2Ptr)/* Index of character just after last one to\n\t\t\t\t * redisplay. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *firstPtr, *lastPtr;\n    TkTextIndex rounded;\n    TkTextLine *linePtr;\n    int notBegin;\n\n    /*\n     * Schedule both a redisplay and a recomputation of display information.\n     * It's done here rather than the end of the function for two reasons:\n     *\n     * 1. If there are no display lines to update we'll want to return\n     *\t  immediately, well before the end of the function.\n     * 2. It's important to arrange for the redisplay BEFORE calling\n     *\t  FreeDLines. The reason for this is subtle and has to do with\n     *\t  embedded windows. The chunk delete function for an embedded window\n     *\t  will schedule an idle handler to unmap the window. However, we want\n     *\t  the idle handler for redisplay to be called first, so that it can\n     *\t  put the embedded window back on the screen again (if appropriate).\n     *\t  This will prevent the window from ever being unmapped, and thereby\n     *\t  avoid flashing.\n     */\n\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;\n\n    /*\n     * Find the DLines corresponding to index1Ptr and index2Ptr. There is one\n     * tricky thing here, which is that we have to relayout in units of whole\n     * text lines: This is necessary because the indices stored in the display\n     * lines will no longer be valid. It's also needed because any edit could\n     * change the way lines wrap.\n     * To relayout in units of whole text (logical) lines, round index1Ptr\n     * back to the beginning of its text line (or, if this line start is\n     * elided, to the beginning of the text line that starts the display line\n     * it is included in), and include all the display lines after index2Ptr,\n     * up to the end of its text line (or, if this line end is elided, up to\n     * the end of the first non elided text line after this line end).\n     */\n\n    rounded = *index1Ptr;\n    rounded.byteIndex = 0;\n    notBegin = 0;\n    while (!IsStartOfNotMergedLine(textPtr, &rounded) && notBegin) {\n\tnotBegin = !TkTextIndexBackBytes(textPtr, &rounded, 1, &rounded);\n\trounded.byteIndex = 0;\n    }\n\n    /*\n     * 'rounded' now points to the start of a display line as well as the\n     * real (non elided) start of a logical line, and this index is the\n     * closest before index1Ptr.\n     */\n\n    firstPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);\n\n    if (firstPtr == NULL) {\n\t/*\n\t * index1Ptr pertains to no display line, i.e this index is after\n\t * the last display line. Since index2Ptr is after index1Ptr, there\n\t * is no display line to free/redisplay and we can return early.\n\t */\n\n\treturn;\n    }\n\n    rounded = *index2Ptr;\n    linePtr = index2Ptr->linePtr;\n    do {\n\tlinePtr = TkBTreeNextLine(textPtr, linePtr);\n\tif (linePtr == NULL) {\n\t    break;\n\t}\n\trounded.linePtr = linePtr;\n\trounded.byteIndex = 0;\n    } while (!IsStartOfNotMergedLine(textPtr, &rounded));\n\n    if (linePtr == NULL) {\n\tlastPtr = NULL;\n    } else {\n\t/*\n\t * 'rounded' now points to the start of a display line as well as the\n\t * start of a logical line not merged with its previous line, and\n\t * this index is the closest after index2Ptr.\n\t */\n\n\tlastPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &rounded);\n\n\t/*\n\t * At least one display line is supposed to change. This makes the\n\t * redisplay OK in case the display line we expect to get here was\n\t * unlinked by a previous call to TkTextChanged and the text widget\n\t * did not update before reaching this point. This happens for\n\t * instance when moving the cursor up one line.\n\t * Note that lastPtr != NULL here, otherwise we would have returned\n\t * earlier when we tested for firstPtr being NULL.\n\t */\n\n\tif (lastPtr == firstPtr) {\n\t    lastPtr = lastPtr->nextPtr;\n\t}\n    }\n\n    /*\n     * Delete all the DLines from firstPtr up to but not including lastPtr.\n     */\n\n    FreeDLines(textPtr, firstPtr, lastPtr, DLINE_UNLINK);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextRedrawTag, TextRedrawTag --\n *\n *\tThis function is invoked to request a redraw of all characters in a\n *\tgiven range that have a particular tag on or off. It's called, for\n *\texample, when tag options change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation on the screen may be redrawn, and the layout of the screen\n *\tmay change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextRedrawTag(\n    TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    TkTextIndex *index1Ptr,\t/* First character in range to consider for\n\t\t\t\t * redisplay. NULL means start at beginning of\n\t\t\t\t * text. */\n    TkTextIndex *index2Ptr,\t/* Character just after last one to consider\n\t\t\t\t * for redisplay. NULL means process all the\n\t\t\t\t * characters in the text. */\n    TkTextTag *tagPtr,\t\t/* Information about tag. */\n    bool withTag)\t\t/* true means redraw characters that have the\n\t\t\t\t * tag, false means redraw those without. */\n{\n    if (sharedTextPtr == NULL) {\n\tTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag);\n    } else {\n\ttextPtr = sharedTextPtr->peers;\n\twhile (textPtr != NULL) {\n\t    TextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag);\n\t    textPtr = textPtr->next;\n\t}\n    }\n}\n\f\nstatic void\nTextRedrawTag(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    TkTextIndex *index1Ptr,\t/* First character in range to consider for\n\t\t\t\t * redisplay. NULL means start at beginning of\n\t\t\t\t * text. */\n    TkTextIndex *index2Ptr,\t/* Character just after last one to consider\n\t\t\t\t * for redisplay. NULL means process all the\n\t\t\t\t * characters in the text. */\n    TkTextTag *tagPtr,\t\t/* Information about tag. */\n    bool withTag)\t\t/* true means redraw characters that have the\n\t\t\t\t * tag, false means redraw those without. */\n{\n    DLine *dlPtr;\n    DLine *endPtr;\n    bool tagOn;\n    TkTextSearch search;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    TkTextIndex *curIndexPtr;\n    TkTextIndex endOfText, *endIndexPtr;\n\n    /*\n     * Invalidate the pixel calculation of all lines in the given range. This\n     * may be a bit over-aggressive, so we could consider more subtle\n     * techniques here in the future. In particular, when we create a tag for\n     * the first time with '.t tag configure foo -font \"Arial 20\"', say, even\n     * though that obviously can't apply to anything at all (the tag didn't\n     * exist a moment ago), we invalidate every single line in the widget.\n     */\n\n    if (tagPtr->affectsDisplayGeometry) {\n\tTkTextLine *startLine, *endLine;\n\tTcl_Size lineCount;\n\n\tif (index2Ptr == NULL) {\n\t    endLine = NULL;\n\t    lineCount = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n\t} else {\n\t    endLine = index2Ptr->linePtr;\n\t    lineCount = TkBTreeLinesTo(textPtr, endLine);\n\t}\n\tif (index1Ptr == NULL) {\n\t    startLine = NULL;\n\t} else {\n\t    startLine = index1Ptr->linePtr;\n\t    lineCount -= TkBTreeLinesTo(textPtr, startLine);\n\t}\n\tTkTextInvalidateLineMetrics(NULL, textPtr, startLine, lineCount,\n\t\tTK_TEXT_INVALIDATE_ONLY);\n    }\n\n    /*\n     * Round up the starting position if it's before the first line visible on\n     * the screen (we only care about what's on the screen).\n     */\n\n    dlPtr = dInfoPtr->dLinePtr;\n    if (dlPtr == NULL) {\n\treturn;\n    }\n    if ((index1Ptr == NULL) || (TkTextIndexCmp(&dlPtr->index, index1Ptr)>0)) {\n\tindex1Ptr = &dlPtr->index;\n    }\n\n    /*\n     * Set the stopping position if it wasn't specified.\n     */\n\n    if (index2Ptr == NULL) {\n\tTcl_Size lastLine = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n\n\tindex2Ptr = TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\tlastLine, 0, &endOfText);\n    }\n\n    /*\n     * Initialize a search through all transitions on the tag, starting with\n     * the first transition where the tag's current state is different from\n     * what it will eventually be.\n     */\n\n    TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);\n\n    /*\n     * Make our own curIndex because at this point search.curIndex may not\n     * equal index1Ptr->curIndex in the case the first tag toggle comes after\n     * index1Ptr (See the use of FindTagStart in TkBTreeStartSearch).\n     */\n\n    curIndexPtr = index1Ptr;\n    tagOn = TkBTreeCharTagged(index1Ptr, tagPtr);\n    if (tagOn != withTag) {\n\tif (!TkBTreeNextTag(&search)) {\n\t    return;\n\t}\n\tcurIndexPtr = &search.curIndex;\n    }\n\n    /*\n     * Schedule a redisplay and layout recalculation if they aren't already\n     * pending. This has to be done before calling FreeDLines, for the reason\n     * given in TkTextChanged.\n     */\n\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;\n\n    /*\n     * Each loop through the loop below is for one range of characters where\n     * the tag's current state is different than its eventual state. At the\n     * top of the loop, search contains information about the first character\n     * in the range.\n     */\n\n    while (1) {\n\t/*\n\t * Find the first DLine structure in the range. Note: if the desired\n\t * character isn't the first in its text line, then look for the\n\t * character just before it instead. This is needed to handle the case\n\t * where the first character of a wrapped display line just got\n\t * smaller, so that it now fits on the line before: need to relayout\n\t * the line containing the previous character.\n\t */\n\n\tif (IsStartOfNotMergedLine(textPtr, curIndexPtr)) {\n\t    dlPtr = FindDLine(textPtr, dlPtr, curIndexPtr);\n\t} else {\n\t    TkTextIndex tmp = *curIndexPtr;\n\n\t    TkTextIndexBackBytes(textPtr, &tmp, 1, &tmp);\n\t    dlPtr = FindDLine(textPtr, dlPtr, &tmp);\n\t}\n\tif (dlPtr == NULL) {\n\t    break;\n\t}\n\n\t/*\n\t * Find the first DLine structure that's past the end of the range.\n\t */\n\n\tif (!TkBTreeNextTag(&search)) {\n\t    endIndexPtr = index2Ptr;\n\t} else {\n\t    curIndexPtr = &search.curIndex;\n\t    endIndexPtr = curIndexPtr;\n\t}\n\tendPtr = FindDLine(textPtr, dlPtr, endIndexPtr);\n\tif ((endPtr != NULL)\n\t\t&& (TkTextIndexCmp(&endPtr->index,endIndexPtr) < 0)) {\n\t    endPtr = endPtr->nextPtr;\n\t}\n\n\t/*\n\t * Delete all of the display lines in the range, so that they'll be\n\t * re-layed out and redrawn.\n\t */\n\n\tFreeDLines(textPtr, dlPtr, endPtr, DLINE_UNLINK);\n\tdlPtr = endPtr;\n\n\t/*\n\t * Find the first text line in the next range.\n\t */\n\n\tif (!TkBTreeNextTag(&search)) {\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextRelayoutWindow --\n *\n *\tThis function is called when something has happened that invalidates\n *\tthe whole layout of characters on the screen, such as a change in a\n *\tconfiguration option for the overall text widget or a change in the\n *\twindow size. It causes all display information to be recomputed and\n *\tthe window to be redrawn.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll the display information will be recomputed for the window and the\n *\twindow will be redrawn.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextRelayoutWindow(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    int mask)\t\t\t/* OR'd collection of bits showing what has\n\t\t\t\t * changed. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    GC newGC;\n    XGCValues gcValues;\n    Bool inSync = 1;\n    int padX, padY;\n    int borderWidth, highlightWidth;\n\n    /*\n     * Schedule the window redisplay. See TkTextChanged for the reason why\n     * this has to be done before any calls to FreeDLines.\n     */\n\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n\tinSync = 0;\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|REDRAW_BORDERS|DINFO_OUT_OF_DATE\n\t    |REPICK_NEEDED;\n\n    /*\n     * (Re-)create the graphics context for drawing the traversal highlight.\n     */\n\n    gcValues.graphics_exposures = False;\n    newGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues);\n    if (dInfoPtr->copyGC != NULL) {\n\tTk_FreeGC(textPtr->display, dInfoPtr->copyGC);\n    }\n    dInfoPtr->copyGC = newGC;\n\n    /*\n     * Throw away all the current layout information.\n     */\n\n    FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK);\n    dInfoPtr->dLinePtr = NULL;\n\n    /*\n     * Recompute some overall things for the layout. Even if the window gets\n     * very small, pretend that there's at least one pixel of drawing space in\n     * it.\n     */\n\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->padYObj, &padY);\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->borderWidthObj, &borderWidth);\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->highlightWidthObj, &highlightWidth);\n    dInfoPtr->x = highlightWidth + borderWidth + padX;\n    dInfoPtr->y = highlightWidth + borderWidth + padY;\n    dInfoPtr->maxX = Tk_Width(textPtr->tkwin) - highlightWidth\n\t    - borderWidth - padX;\n    if (dInfoPtr->maxX <= dInfoPtr->x) {\n\tdInfoPtr->maxX = dInfoPtr->x + 1;\n    }\n\n    /*\n     * This is the only place where dInfoPtr->maxY is set.\n     */\n\n    dInfoPtr->maxY = Tk_Height(textPtr->tkwin) - highlightWidth\n\t    - borderWidth - padY;\n    if (dInfoPtr->maxY <= dInfoPtr->y) {\n\tdInfoPtr->maxY = dInfoPtr->y + 1;\n    }\n    dInfoPtr->topOfEof = dInfoPtr->maxY;\n\n    /*\n     * If the upper-left character isn't the first in a line, recompute it.\n     * This is necessary because a change in the window's size or options\n     * could change the way lines wrap.\n     */\n\n    if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) {\n\tTkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);\n    }\n\n    /*\n     * Invalidate cached scrollbar positions, so that scrollbars sliders will\n     * be updated.\n     */\n\n    dInfoPtr->xScrollFirst = dInfoPtr->xScrollLast = -1;\n    dInfoPtr->yScrollFirst = dInfoPtr->yScrollLast = -1;\n\n    if (mask & TK_TEXT_LINE_GEOMETRY) {\n\n\t/*\n\t * Set up line metric recalculation.\n\t *\n\t * Avoid the special zero value, since that is used to mark individual\n\t * lines as being out of date.\n\t */\n\n\tif ((++dInfoPtr->lineMetricUpdateEpoch) == 0) {\n\t    dInfoPtr->lineMetricUpdateEpoch++;\n\t}\n\n\tdInfoPtr->currentMetricUpdateLine = -1;\n\n\t/*\n\t * Also cancel any partial line-height calculations (for long-wrapped\n\t * lines) in progress.\n\t */\n\n\tdInfoPtr->metricEpoch = -1;\n\n\tif (dInfoPtr->lineUpdateTimer == NULL) {\n\t    textPtr->refCount++;\n\t    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,\n\t\t    AsyncUpdateLineMetrics, textPtr);\n\t    inSync = 0;\n\t}\n\n\tGenerateWidgetViewSyncEvent(textPtr, inSync);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextSetYView --\n *\n *\tThis function is called to specify what lines are to be displayed in a\n *\ttext widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe display will (eventually) be updated so that the position given by\n *\t\"indexPtr\" is visible on the screen at the position determined by\n *\t\"pickPlace\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextSetYView(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    TkTextIndex *indexPtr,\t/* Position that is to appear somewhere in the\n\t\t\t\t * view. */\n    int pickPlace)\t\t/* 0 means the given index must appear exactly\n\t\t\t\t * at the top of the screen. TK_TEXT_PICKPLACE\n\t\t\t\t * (-1) means we get to pick where it appears:\n\t\t\t\t * minimize screen motion or else display line\n\t\t\t\t * at center of screen. TK_TEXT_NOPIXELADJUST\n\t\t\t\t * (-2) indicates to make the given index the\n\t\t\t\t * top line, but if it is already the top\n\t\t\t\t * line, don't nudge it up or down by a few\n\t\t\t\t * pixels just to make sure it is entirely\n\t\t\t\t * displayed. Positive numbers indicate the\n\t\t\t\t * number of pixels of the index's line which\n\t\t\t\t * are to be off the top of the screen. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr;\n    int bottomY, close;\n    Tcl_Size lineIndex;\n    TkTextIndex tmpIndex, rounded;\n    int lineHeight;\n\n    /*\n     * If the specified position is the extra line at the end of the text,\n     * round it back to the last real line.\n     */\n\n    lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);\n    if (lineIndex == TkBTreeNumLines(indexPtr->tree, textPtr)) {\n\tTkTextIndexBackChars(textPtr, indexPtr, 1, &rounded, COUNT_INDICES);\n\tindexPtr = &rounded;\n    }\n\n    if (pickPlace == TK_TEXT_NOPIXELADJUST) {\n\tif (textPtr->topIndex.linePtr == indexPtr->linePtr\n\t\t&& textPtr->topIndex.byteIndex == indexPtr->byteIndex) {\n\t    pickPlace = dInfoPtr->topPixelOffset;\n\t} else {\n\t    pickPlace = 0;\n\t}\n    }\n\n    if (pickPlace != TK_TEXT_PICKPLACE) {\n\t/*\n\t * The specified position must go at the top of the screen. Just leave\n\t * all the DLine's alone: we may be able to reuse some of the\n\t * information that's currently on the screen without redisplaying it\n\t * all.\n\t */\n\n\ttextPtr->topIndex = *indexPtr;\n\tif (!IsStartOfNotMergedLine(textPtr, indexPtr)) {\n\t    TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);\n\t}\n\tdInfoPtr->newTopPixelOffset = pickPlace;\n\tgoto scheduleUpdate;\n    }\n\n    /*\n     * We have to pick where to display the index. First, bring the display\n     * information up to date and see if the index will be completely visible\n     * in the current screen configuration. If so then there's nothing to do.\n     */\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n    dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);\n    if (dlPtr != NULL) {\n\tif ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) {\n\t    /*\n\t     * Part of the line hangs off the bottom of the screen; pretend\n\t     * the whole line is off-screen.\n\t     */\n\n\t    dlPtr = NULL;\n\t} else {\n\t    if (TkTextIndexCmp(&dlPtr->index, indexPtr) <= 0) {\n\t\tif (dInfoPtr->dLinePtr == dlPtr && dInfoPtr->topPixelOffset != 0) {\n\t\t    /*\n\t\t     * It is on the top line, but that line is hanging off the top\n\t\t     * of the screen. Change the top overlap to zero and update.\n\t\t     */\n\n\t\t    dInfoPtr->newTopPixelOffset = 0;\n\t\t    goto scheduleUpdate;\n\t\t}\n\t\t/*\n\t\t * The line is already on screen, with no need to scroll.\n\t\t */\n\t\treturn;\n\t    }\n\t}\n    }\n\n    /*\n     * The desired line isn't already on-screen. Figure out what it means to\n     * be \"close\" to the top or bottom of the screen. Close means within 1/3\n     * of the screen height or within three lines, whichever is greater.\n     *\n     * If the line is not close, place it in the center of the window.\n     */\n\n    tmpIndex = *indexPtr;\n    TkTextFindDisplayLineEnd(textPtr, &tmpIndex, 0, NULL);\n    lineHeight = CalculateDisplayLineHeight(textPtr, &tmpIndex, NULL, NULL);\n\n    /*\n     * It would be better if 'bottomY' were calculated using the actual height\n     * of the given line, not 'textPtr->charHeight'.\n     */\n\n    bottomY = (dInfoPtr->y + dInfoPtr->maxY + lineHeight)/2;\n    close = (dInfoPtr->maxY - dInfoPtr->y)/3;\n    if (close < 3*textPtr->charHeight) {\n\tclose = 3*textPtr->charHeight;\n    }\n    if (dlPtr != NULL) {\n\tint overlap;\n\n\t/*\n\t * The desired line is above the top of screen. If it is \"close\" to\n\t * the top of the window then make it the top line on the screen.\n\t * MeasureUp counts from the bottom of the given index upwards, so we\n\t * add an extra half line to be sure we count far enough.\n\t */\n\n\tMeasureUp(textPtr, &textPtr->topIndex, close + textPtr->charHeight/2,\n\t\t&tmpIndex, &overlap);\n\tif (TkTextIndexCmp(&tmpIndex, indexPtr) <= 0) {\n\t    textPtr->topIndex = *indexPtr;\n\t    TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);\n\t    dInfoPtr->newTopPixelOffset = 0;\n\t    goto scheduleUpdate;\n\t}\n    } else {\n\tint overlap;\n\n\t/*\n\t * The desired line is below the bottom of the screen. If it is\n\t * \"close\" to the bottom of the screen then position it at the bottom\n\t * of the screen.\n\t */\n\n\tMeasureUp(textPtr, indexPtr, close + lineHeight\n\t\t- textPtr->charHeight/2, &tmpIndex, &overlap);\n\tif (FindDLine(textPtr, dInfoPtr->dLinePtr, &tmpIndex) != NULL) {\n\t    bottomY = dInfoPtr->maxY - dInfoPtr->y;\n\t}\n    }\n\n    /*\n     * If the window height is smaller than the line height, prefer to make\n     * the top of the line visible.\n     */\n\n    if (dInfoPtr->maxY - dInfoPtr->y < lineHeight) {\n\tbottomY = lineHeight;\n    }\n\n    /*\n     * Our job now is to arrange the display so that indexPtr appears as low\n     * on the screen as possible but with its bottom no lower than bottomY.\n     * BottomY is the bottom of the window if the desired line is just below\n     * the current screen, otherwise it is a half-line lower than the center\n     * of the window.\n     */\n\n    MeasureUp(textPtr, indexPtr, bottomY, &textPtr->topIndex,\n\t    &dInfoPtr->newTopPixelOffset);\n\n  scheduleUpdate:\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextMeasureDown --\n *\n *\tGiven one index, find the index of the first character on the highest\n *\tdisplay line that would be displayed no more than \"distance\" pixels\n *\tbelow the top of the given index.\n *\n * Results:\n *\tThe srcPtr is manipulated in place to reflect the new position. We\n *\treturn the number of pixels by which 'distance' overlaps the srcPtr.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextMeasureDown(\n    TkText *textPtr,\t\t/* Text widget in which to measure. */\n    TkTextIndex *srcPtr,\t/* Index of character from which to start\n\t\t\t\t * measuring. */\n    int distance)\t\t/* Vertical distance in pixels measured from\n\t\t\t\t * the top pixel in srcPtr's logical line. */\n{\n    TkTextLine *lastLinePtr;\n    DLine *dlPtr;\n    TkTextIndex loop;\n\n    lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));\n\n    do {\n\tdlPtr = LayoutDLine(textPtr, srcPtr);\n\tdlPtr->nextPtr = NULL;\n\n\tif (distance < dlPtr->height) {\n\t    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\t    break;\n\t}\n\tdistance -= dlPtr->height;\n\tTkTextIndexForwBytes(textPtr, srcPtr, dlPtr->byteCount, &loop);\n\tFreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\tif (loop.linePtr == lastLinePtr) {\n\t    break;\n\t}\n\t*srcPtr = loop;\n    } while (distance > 0);\n\n    return distance;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MeasureUp --\n *\n *\tGiven one index, find the index of the first character on the highest\n *\tdisplay line that would be displayed no more than \"distance\" pixels\n *\tabove the given index.\n *\n *\tIf this function is called with distance=0, it simply finds the first\n *\tindex on the same display line as srcPtr. However, there is a another\n *\tfunction TkTextFindDisplayLineEnd designed just for that task which is\n *\tprobably better to use.\n *\n * Results:\n *\t*dstPtr is filled in with the index of the first character on a\n *\tdisplay line. The display line is found by measuring up \"distance\"\n *\tpixels above the pixel just below an imaginary display line that\n *\tcontains srcPtr. If the display line that covers this coordinate\n *\tactually extends above the coordinate, then return any excess pixels\n *\tin *overlap, if that is non-NULL.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMeasureUp(\n    TkText *textPtr,\t\t/* Text widget in which to measure. */\n    const TkTextIndex *srcPtr,\t/* Index of character from which to start\n\t\t\t\t * measuring. */\n    int distance,\t\t/* Vertical distance in pixels measured from\n\t\t\t\t * the pixel just below the lowest one in\n\t\t\t\t * srcPtr's line. */\n    TkTextIndex *dstPtr,\t/* Index to fill in with result. */\n    int *overlap)\t\t/* Used to store how much of the final index\n\t\t\t\t * returned was not covered by 'distance'. */\n{\n    Tcl_Size lineNum;\t\t/* Number of current line. */\n    Tcl_Size bytesToCount;\t\t/* Maximum number of bytes to measure in\n\t\t\t\t * current line. */\n    TkTextIndex index;\n    DLine *dlPtr, *lowestPtr;\n\n    bytesToCount = srcPtr->byteIndex + 1;\n    index.tree = srcPtr->tree;\n    for (lineNum = TkBTreeLinesTo(textPtr, srcPtr->linePtr); lineNum >= 0;\n\t    lineNum--) {\n\t/*\n\t * Layout an entire text line (potentially > 1 display line).\n\t *\n\t * For the first line, which contains srcPtr, only layout the part up\n\t * through srcPtr (bytesToCount is non-infinite to accomplish this).\n\t * Make a list of all the display lines in backwards order (the lowest\n\t * DLine on the screen is first in the list).\n\t */\n\n\tindex.linePtr = TkBTreeFindLine(srcPtr->tree, textPtr, lineNum);\n\tindex.byteIndex = 0;\n\tTkTextFindDisplayLineEnd(textPtr, &index, 0, NULL);\n\tlineNum = TkBTreeLinesTo(textPtr, index.linePtr);\n\tlowestPtr = NULL;\n\tdo {\n\t    dlPtr = LayoutDLine(textPtr, &index);\n\t    dlPtr->nextPtr = lowestPtr;\n\t    lowestPtr = dlPtr;\n\t    TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index);\n\t    bytesToCount -= dlPtr->byteCount;\n\t} while (bytesToCount>0 && index.linePtr==dlPtr->index.linePtr);\n\n\t/*\n\t * Scan through the display lines to see if we've covered enough\n\t * vertical distance. If so, save the starting index for the line at\n\t * the desired location. If distance was zero to start with then we\n\t * simply get the first index on the same display line as the original\n\t * index.\n\t */\n\n\tfor (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {\n\t    distance -= dlPtr->height;\n\t    if (distance <= 0) {\n\t\t*dstPtr = dlPtr->index;\n\n\t\t/*\n\t\t * dstPtr is the start of a display line that is or is not\n\t\t * the start of a logical line. If it is the start of a\n\t\t * logical line, we must check whether this line is merged\n\t\t * with the previous logical line, and if so we must adjust\n\t\t * dstPtr to the start of the display line since a display\n\t\t * line start needs to be returned.\n\t\t */\n\t\tif (!IsStartOfNotMergedLine(textPtr, dstPtr)) {\n\t\t    TkTextFindDisplayLineEnd(textPtr, dstPtr, 0, NULL);\n\t\t}\n\n\t\tif (overlap != NULL) {\n\t\t    *overlap = -distance;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * Discard the display lines, then either return or prepare for the\n\t * next display line to lay out.\n\t */\n\n\tFreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);\n\tif (distance <= 0) {\n\t    return;\n\t}\n\tbytesToCount = INT_MAX;\t\t/* Consider all chars. in next line. */\n    }\n\n    /*\n     * Ran off the beginning of the text. Return the first character in the\n     * text.\n     */\n\n    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, dstPtr);\n    if (overlap != NULL) {\n\t*overlap = 0;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextSeeCmd --\n *\n *\tThis function is invoked to process the \"see\" option for the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextSeeCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"see\". */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    TkTextIndex index;\n\tTcl_Size byteCount;\n    int x, y, width, height, lineWidth, oneThird, delta;\n    DLine *dlPtr;\n    TkTextDispChunk *chunkPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"index\");\n\treturn TCL_ERROR;\n    }\n    if (TkTextGetObjIndex(interp, textPtr, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * If the specified position is the extra line at the end of the text,\n     * round it back to the last real line.\n     */\n\n    if (TkBTreeLinesTo(textPtr, index.linePtr)\n\t    == TkBTreeNumLines(index.tree, textPtr)) {\n\tTkTextIndexBackChars(textPtr, &index, 1, &index, COUNT_INDICES);\n    }\n\n    /*\n     * First get the desired position into the vertical range of the window.\n     */\n\n    TkTextSetYView(textPtr, &index, TK_TEXT_PICKPLACE);\n\n    /*\n     * Now make sure that the character is in view horizontally.\n     */\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n    lineWidth = dInfoPtr->maxX - dInfoPtr->x;\n    if (dInfoPtr->maxLength < lineWidth) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Find the display line containing the desired index. dlPtr may be NULL\n     * if the widget is not mapped. [Bug #641778]\n     */\n\n    dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, &index);\n    if (dlPtr == NULL) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Find the chunk within the display line that contains the desired\n     * index. The chunks making the display line are skipped up to but not\n     * including the one crossing index. Skipping is done based on a\n     * byteCount offset possibly spanning several logical lines in case\n     * they are elided.\n     */\n\n    byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, &index);\n    for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL ;\n\t    chunkPtr = chunkPtr->nextPtr) {\n\tif (byteCount < chunkPtr->numBytes) {\n\t    break;\n\t}\n\tbyteCount -= chunkPtr->numBytes;\n    }\n\n    /*\n     * Call a chunk-specific function to find the horizontal range of the\n     * character within the chunk. chunkPtr is NULL if trying to see in elided\n     * region.\n     */\n\n    if (chunkPtr != NULL) {\n\tchunkPtr->bboxProc(textPtr, chunkPtr, byteCount,\n\t\tdlPtr->y + dlPtr->spaceAbove,\n\t\tdlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,\n\t\tdlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,\n\t\t&height);\n\tdelta = x - dInfoPtr->curXPixelOffset;\n\toneThird = lineWidth/3;\n\tif (delta < 0) {\n\t    if (delta < -oneThird) {\n\t\tdInfoPtr->newXPixelOffset = x - lineWidth/2;\n\t    } else {\n\t\tdInfoPtr->newXPixelOffset += delta;\n\t    }\n\t} else {\n\t    delta -= lineWidth - width;\n\t    if (delta <= 0) {\n\t\treturn TCL_OK;\n\t    }\n\t    if (delta > oneThird) {\n\t\tdInfoPtr->newXPixelOffset = x - lineWidth/2;\n\t    } else {\n\t\tdInfoPtr->newXPixelOffset += delta;\n\t    }\n\t}\n    }\n    dInfoPtr->flags |= DINFO_OUT_OF_DATE;\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tdInfoPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextXviewCmd --\n *\n *\tThis function is invoked to process the \"xview\" option for the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextXviewCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"xview\". */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    int type, count;\n    double fraction;\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n\n    if (objc == 2) {\n\tGetXView(interp, textPtr, 0);\n\treturn TCL_OK;\n    }\n\n    type = TextGetScrollInfoObj(interp, textPtr, objc, objv,\n\t    &fraction, &count);\n    switch (type) {\n    case TKTEXT_SCROLL_ERROR:\n\treturn TCL_ERROR;\n    case TKTEXT_SCROLL_MOVETO:\n\tif (fraction > 1.0) {\n\t    fraction = 1.0;\n\t}\n\tif (fraction < 0) {\n\t    fraction = 0;\n\t}\n\tdInfoPtr->newXPixelOffset = (int)\n\t\t(fraction * dInfoPtr->maxLength + 0.5);\n\tbreak;\n    case TKTEXT_SCROLL_PAGES: {\n\tint pixelsPerPage;\n\n\tpixelsPerPage = (dInfoPtr->maxX-dInfoPtr->x) - 2*textPtr->charWidth;\n\tif (pixelsPerPage < 1) {\n\t    pixelsPerPage = 1;\n\t}\n\tdInfoPtr->newXPixelOffset += pixelsPerPage * count;\n\tbreak;\n    }\n    case TKTEXT_SCROLL_UNITS:\n\tdInfoPtr->newXPixelOffset += count * textPtr->charWidth;\n\tbreak;\n    case TKTEXT_SCROLL_PIXELS:\n\tdInfoPtr->newXPixelOffset += count;\n\tbreak;\n    }\n\n    dInfoPtr->flags |= DINFO_OUT_OF_DATE;\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tdInfoPtr->flags |= REDRAW_PENDING;\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * YScrollByPixels --\n *\n *\tThis function is called to scroll a text widget up or down by a given\n *\tnumber of pixels.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe view in textPtr's window changes to reflect the value of \"offset\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nYScrollByPixels(\n    TkText *textPtr,\t\t/* Widget to scroll. */\n    int offset)\t\t\t/* Amount by which to scroll, in pixels.\n\t\t\t\t * Positive means that information later in\n\t\t\t\t * text becomes visible, negative means that\n\t\t\t\t * information earlier in the text becomes\n\t\t\t\t * visible. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n\n    if (offset < 0) {\n\t/*\n\t * Now we want to measure up this number of pixels from the top of the\n\t * screen. But the top line may not be totally visible. Note that\n\t * 'count' is negative here.\n\t */\n\n\toffset -= CalculateDisplayLineHeight(textPtr,\n\t\t&textPtr->topIndex, NULL, NULL) - dInfoPtr->topPixelOffset;\n\tMeasureUp(textPtr, &textPtr->topIndex, -offset,\n\t\t&textPtr->topIndex, &dInfoPtr->newTopPixelOffset);\n    } else if (offset > 0) {\n\tDLine *dlPtr;\n\tTkTextLine *lastLinePtr;\n\tTkTextIndex newIdx;\n\n\t/*\n\t * Scrolling down by pixels. Layout lines starting at the top index\n\t * and count through the desired vertical distance.\n\t */\n\n\tlastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));\n\toffset += dInfoPtr->topPixelOffset;\n\tdInfoPtr->newTopPixelOffset = 0;\n\twhile (offset > 0) {\n\t    dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);\n\t    dlPtr->nextPtr = NULL;\n\t    TkTextIndexForwBytes(textPtr, &textPtr->topIndex,\n\t\t    dlPtr->byteCount, &newIdx);\n\t    if (offset <= dlPtr->height) {\n\t\t/*\n\t\t * Adjust the top overlap accordingly.\n\t\t */\n\n\t\tdInfoPtr->newTopPixelOffset = offset;\n\t    }\n\t    offset -= dlPtr->height;\n\t    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\t    if (newIdx.linePtr == lastLinePtr || offset <= 0) {\n\t\tbreak;\n\t    }\n\t    textPtr->topIndex = newIdx;\n\t}\n    } else {\n\t/*\n\t * offset = 0, so no scrolling required.\n\t */\n\n\treturn;\n    }\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * YScrollByLines --\n *\n *\tThis function is called to scroll a text widget up or down by a given\n *\tnumber of lines.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe view in textPtr's window changes to reflect the value of \"offset\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nYScrollByLines(\n    TkText *textPtr,\t\t/* Widget to scroll. */\n    int offset)\t\t\t/* Amount by which to scroll, in display\n\t\t\t\t * lines. Positive means that information\n\t\t\t\t * later in text becomes visible, negative\n\t\t\t\t * means that information earlier in the text\n\t\t\t\t * becomes visible. */\n{\n    Tcl_Size i, bytesToCount, lineNum;\n    TkTextIndex newIdx, index;\n    TkTextLine *lastLinePtr;\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr, *lowestPtr;\n\n    if (offset < 0) {\n\t/*\n\t * Must scroll up (to show earlier information in the text). The code\n\t * below is similar to that in MeasureUp, except that it counts lines\n\t * instead of pixels.\n\t */\n\n\tbytesToCount = textPtr->topIndex.byteIndex + 1;\n\tindex.tree = textPtr->sharedTextPtr->tree;\n\toffset--;\t\t/* Skip line containing topIndex. */\n\tfor (lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr);\n\t\tlineNum >= 0; lineNum--) {\n\t    index.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree,\n\t\t    textPtr, lineNum);\n\t    index.byteIndex = 0;\n\t    lowestPtr = NULL;\n\t    do {\n\t\tdlPtr = LayoutDLine(textPtr, &index);\n\t\tdlPtr->nextPtr = lowestPtr;\n\t\tlowestPtr = dlPtr;\n\t\tTkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount,&index);\n\t\tbytesToCount -= dlPtr->byteCount;\n\t    } while ((bytesToCount > 0)\n\t\t    && (index.linePtr == dlPtr->index.linePtr));\n\n\t    for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {\n\t\toffset++;\n\t\tif (offset == 0) {\n\t\t    textPtr->topIndex = dlPtr->index;\n\n\t\t    /*\n\t\t     * topIndex is the start of a logical line. However, if\n\t\t     * the eol of the previous logical line is elided, then\n\t\t     * topIndex may be elsewhere than the first character of\n\t\t     * a display line, which is unwanted. Adjust to the start\n\t\t     * of the display line, if needed.\n\t\t     * topIndex is the start of a display line that is or is\n\t\t     * not the start of a logical line. If it is the start of\n\t\t     * a logical line, we must check whether this line is\n\t\t     * merged with the previous logical line, and if so we\n\t\t     * must adjust topIndex to the start of the display line.\n\t\t     */\n\t\t    if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) {\n\t\t\tTkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex,\n\t\t\t\t0, NULL);\n\t\t    }\n\n\t\t    break;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Discard the display lines, then either return or prepare for\n\t     * the next display line to lay out.\n\t     */\n\n\t    FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE);\n\t    if (offset >= 0) {\n\t\tgoto scheduleUpdate;\n\t    }\n\t    bytesToCount = INT_MAX;\n\t}\n\n\t/*\n\t * Ran off the beginning of the text. Return the first character in\n\t * the text, and make sure we haven't left anything overlapping the\n\t * top window border.\n\t */\n\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t\t&textPtr->topIndex);\n\tdInfoPtr->newTopPixelOffset = 0;\n    } else {\n\t/*\n\t * Scrolling down, to show later information in the text. Just count\n\t * lines from the current top of the window.\n\t */\n\n\tlastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));\n\tfor (i = 0; i < offset; i++) {\n\t    dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);\n\t    if (dlPtr->length == 0 && dlPtr->height == 0) {\n\t\toffset++;\n\t    }\n\t    dlPtr->nextPtr = NULL;\n\t    TkTextIndexForwBytes(textPtr, &textPtr->topIndex,\n\t\t    dlPtr->byteCount, &newIdx);\n\t    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE);\n\t    if (newIdx.linePtr == lastLinePtr) {\n\t\tbreak;\n\t    }\n\t    textPtr->topIndex = newIdx;\n\t}\n    }\n\n  scheduleUpdate:\n    if (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\tTcl_DoWhenIdle(DisplayText, textPtr);\n    }\n    dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextYviewCmd --\n *\n *\tThis function is invoked to process the \"yview\" option for the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextYviewCmd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"yview\". */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    int pickPlace, type;\n    int pixels, count;\n    Tcl_Size switchLength;\n    double fraction;\n    TkTextIndex index;\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n\n    if (objc == 2) {\n\tGetYView(interp, textPtr, 0);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Next, handle the old syntax: \"pathName yview ?-pickplace? where\"\n     */\n\n    pickPlace = 0;\n    if (Tcl_GetString(objv[2])[0] == '-') {\n\tconst char *switchStr =\n\t\tTcl_GetStringFromObj(objv[2], &switchLength);\n\n\tif ((switchLength >= 2) && (strncmp(switchStr, \"-pickplace\",\n\t\t(unsigned) switchLength) == 0)) {\n\t    pickPlace = 1;\n\t    if (objc != 4) {\n\t\tTcl_WrongNumArgs(interp, 3, objv, \"lineNum|index\");\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n    if ((objc == 3) || pickPlace) {\n\tint lineNum;\n\n\tif (Tcl_GetIntFromObj(interp, objv[2+pickPlace], &lineNum) == TCL_OK) {\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t    lineNum, 0, &index);\n\t    TkTextSetYView(textPtr, &index, 0);\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * The argument must be a regular text index.\n\t */\n\n\tTcl_ResetResult(interp);\n\tif (TkTextGetObjIndex(interp, textPtr, objv[2+pickPlace],\n\t\t&index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTkTextSetYView(textPtr, &index, (pickPlace ? TK_TEXT_PICKPLACE : 0));\n\treturn TCL_OK;\n    }\n\n    /*\n     * New syntax: dispatch based on objv[2].\n     */\n\n    type = TextGetScrollInfoObj(interp, textPtr, objc,objv, &fraction, &count);\n    switch (type) {\n    case TKTEXT_SCROLL_ERROR:\n\treturn TCL_ERROR;\n    case TKTEXT_SCROLL_MOVETO: {\n\tint numPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree,\n\t\ttextPtr);\n\tint topMostPixel;\n\n\tif (numPixels == 0) {\n\t    /*\n\t     * If the window is totally empty no scrolling is needed, and the\n\t     * TkTextMakePixelIndex call below will fail.\n\t     */\n\n\t    break;\n\t}\n\tif (fraction > 1.0) {\n\t    fraction = 1.0;\n\t}\n\tif (fraction < 0) {\n\t    fraction = 0;\n\t}\n\n\t/*\n\t * Calculate the pixel count for the new topmost pixel in the topmost\n\t * line of the window. Note that the interpretation of 'fraction' is\n\t * that it counts from 0 (top pixel in buffer) to 1.0 (one pixel past\n\t * the last pixel in buffer).\n\t */\n\n\ttopMostPixel = (int) (0.5 + fraction * numPixels);\n\tif (topMostPixel >= numPixels) {\n\t    topMostPixel = numPixels -1;\n\t}\n\n\t/*\n\t * This function returns the number of pixels by which the given line\n\t * should overlap the top of the visible screen.\n\t *\n\t * This is then used to provide smooth scrolling.\n\t */\n\n\tpixels = TkTextMakePixelIndex(textPtr, topMostPixel, &index);\n\tTkTextSetYView(textPtr, &index, pixels);\n\tbreak;\n    }\n    case TKTEXT_SCROLL_PAGES: {\n\t/*\n\t * Scroll up or down by screenfuls. Actually, use the window height\n\t * minus two lines, so that there's some overlap between adjacent\n\t * pages.\n\t */\n\n\tint height = dInfoPtr->maxY - dInfoPtr->y;\n\n\tif (textPtr->charHeight * 4 >= height) {\n\t    /*\n\t     * A single line is more than a quarter of the display. We choose\n\t     * to scroll by 3/4 of the height instead.\n\t     */\n\n\t    pixels = 3*height/4;\n\t    if (pixels < textPtr->charHeight) {\n\t\t/*\n\t\t * But, if 3/4 of the height is actually less than a single\n\t\t * typical character height, then scroll by the minimum of the\n\t\t * linespace or the total height.\n\t\t */\n\n\t\tif (textPtr->charHeight < height) {\n\t\t    pixels = textPtr->charHeight;\n\t\t} else {\n\t\t    pixels = height;\n\t\t}\n\t    }\n\t    pixels *= count;\n\t} else {\n\t    pixels = (height - 2*textPtr->charHeight)*count;\n\t}\n\tYScrollByPixels(textPtr, pixels);\n\tbreak;\n    }\n    case TKTEXT_SCROLL_PIXELS:\n\tYScrollByPixels(textPtr, count);\n\tbreak;\n    case TKTEXT_SCROLL_UNITS:\n\tYScrollByLines(textPtr, count);\n\tbreak;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextPendingsync --\n *\n *\tThis function checks if any line heights are not up-to-date.\n *\n * Results:\n *\tReturns a boolean true if it is the case, or false if all line\n *      heights are up-to-date.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nBool\nTkTextPendingsync(\n    TkText *textPtr)\t\t/* Information about text widget. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n\n    return ((dInfoPtr->flags & OUT_OF_SYNC) != 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextScanCmd --\n *\n *\tThis function is invoked to process the \"scan\" option for the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextScanCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"scan\". */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    TkTextIndex index;\n    int c, x, y, totalScroll, gain=10;\n    Tcl_Size length;\n\n    if ((objc != 5) && (objc != 6)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"mark x y\");\n\tTcl_AppendResult(interp, \" or \\\"\", Tcl_GetString(objv[0]),\n\t\t\" scan dragto x y ?gain?\\\"\", (char *)NULL);\n\t/*\n\t * Ought to be:\n\t * Tcl_WrongNumArgs(interp, 2, objc, \"dragto x y ?gain?\");\n\t */\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if ((objc == 6) && (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    c = Tcl_GetStringFromObj(objv[2], &length)[0];\n    if (c=='d' && strncmp(Tcl_GetString(objv[2]), \"dragto\", length)==0) {\n\tint newX, maxX;\n\n\t/*\n\t * Amplify the difference between the current position and the mark\n\t * position to compute how much the view should shift, then update the\n\t * mark position to correspond to the new view. If we run off the edge\n\t * of the text, reset the mark point so that the current position\n\t * continues to correspond to the edge of the window. This means that\n\t * the picture will start dragging as soon as the mouse reverses\n\t * direction (without this reset, might have to slide mouse a long\n\t * ways back before the picture starts moving again).\n\t */\n\n\tnewX = dInfoPtr->scanMarkXPixel + gain*(dInfoPtr->scanMarkX - x);\n\tmaxX = 1 + dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x);\n\tif (newX < 0) {\n\t    newX = 0;\n\t    dInfoPtr->scanMarkXPixel = 0;\n\t    dInfoPtr->scanMarkX = x;\n\t} else if (newX > maxX) {\n\t    newX = maxX;\n\t    dInfoPtr->scanMarkXPixel = maxX;\n\t    dInfoPtr->scanMarkX = x;\n\t}\n\tdInfoPtr->newXPixelOffset = newX;\n\n\ttotalScroll = gain*(dInfoPtr->scanMarkY - y);\n\tif (totalScroll != dInfoPtr->scanTotalYScroll) {\n\t    index = textPtr->topIndex;\n\t    YScrollByPixels(textPtr, totalScroll-dInfoPtr->scanTotalYScroll);\n\t    dInfoPtr->scanTotalYScroll = totalScroll;\n\t    if ((index.linePtr == textPtr->topIndex.linePtr) &&\n\t\t    (index.byteIndex == textPtr->topIndex.byteIndex)) {\n\t\tdInfoPtr->scanTotalYScroll = 0;\n\t\tdInfoPtr->scanMarkY = y;\n\t    }\n\t}\n\tdInfoPtr->flags |= DINFO_OUT_OF_DATE;\n\tif (!(dInfoPtr->flags & REDRAW_PENDING)) {\n\t    dInfoPtr->flags |= REDRAW_PENDING;\n\t    Tcl_DoWhenIdle(DisplayText, textPtr);\n\t}\n    } else if (c=='m' && strncmp(Tcl_GetString(objv[2]), \"mark\", length)==0) {\n\tdInfoPtr->scanMarkXPixel = dInfoPtr->newXPixelOffset;\n\tdInfoPtr->scanMarkX = x;\n\tdInfoPtr->scanTotalYScroll = 0;\n\tdInfoPtr->scanMarkY = y;\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad scan option \\\"%s\\\": must be dragto or mark\",\n\t\tTcl_GetString(objv[2])));\n\tTcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"scan option\",\n\t\tTcl_GetString(objv[2]), (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetXView --\n *\n *\tThis function computes the fractions that indicate what's visible in a\n *\ttext window and, optionally, evaluates a Tcl script to report them to\n *\tthe text's associated scrollbar.\n *\n * Results:\n *\tIf report is zero, then the interp's result is filled in with two real\n *\tnumbers separated by a space, giving the position of the left and\n *\tright edges of the window as fractions from 0 to 1, where 0 means the\n *\tleft edge of the text and 1 means the right edge. If report is\n *\tnon-zero, then the interp's result isn't modified directly, but\n *\tinstead a script is evaluated in interp to report the new horizontal\n *\tscroll position to the scrollbar (if the scroll position hasn't\n *\tchanged then no script is invoked).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetXView(\n    Tcl_Interp *interp,\t\t/* If \"report\" is FALSE, string describing\n\t\t\t\t * visible range gets stored in the interp's\n\t\t\t\t * result. */\n    const TkText *textPtr,\t\t/* Information about text widget. */\n    int report)\t\t\t/* Non-zero means report info to scrollbar if\n\t\t\t\t * it has changed. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    double first, last;\n    int code;\n    Tcl_Obj *listObj;\n\n    if (dInfoPtr->maxLength > 0) {\n\tfirst = ((double) dInfoPtr->curXPixelOffset)\n\t\t/ dInfoPtr->maxLength;\n\tlast = ((double) (dInfoPtr->curXPixelOffset + dInfoPtr->maxX\n\t\t- dInfoPtr->x))/dInfoPtr->maxLength;\n\tif (last > 1.0) {\n\t    last = 1.0;\n\t}\n    } else {\n\tfirst = 0;\n\tlast = 1.0;\n    }\n    if (!report) {\n\tlistObj = Tcl_NewListObj(0, NULL);\n\tTcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first));\n\tTcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last));\n\tTcl_SetObjResult(interp, listObj);\n\treturn;\n    }\n    if (FP_EQUAL_SCALE(first, dInfoPtr->xScrollFirst, dInfoPtr->maxLength) &&\n\t    FP_EQUAL_SCALE(last, dInfoPtr->xScrollLast, dInfoPtr->maxLength)) {\n\treturn;\n    }\n    dInfoPtr->xScrollFirst = first;\n    dInfoPtr->xScrollLast = last;\n    if (textPtr->xScrollCmdObj != NULL) {\n\tchar buf1[TCL_DOUBLE_SPACE+1];\n\tchar buf2[TCL_DOUBLE_SPACE+1];\n\tTcl_DString buf;\n\n\tbuf1[0] = ' ';\n\tbuf2[0] = ' ';\n\tTcl_PrintDouble(NULL, first, buf1+1);\n\tTcl_PrintDouble(NULL, last, buf2+1);\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(textPtr->xScrollCmdObj), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, buf1, TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, buf2, TCL_INDEX_NONE);\n\tcode = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tif (code != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (horizontal scrolling command executed by text)\");\n\t    Tcl_BackgroundException(interp, code);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetYPixelCount --\n *\n *\tHow many pixels are there between the absolute top of the widget and\n *\tthe top of the given DLine.\n *\n *\tWhile this function will work for any valid DLine, it is only ever\n *\tcalled when dlPtr is the first display line in the widget (by\n *\t'GetYView'). This means that usually this function is a very quick\n *\tcalculation, since it can use the pre-calculated linked-list of DLines\n *\tfor height information.\n *\n *\tThe only situation where this breaks down is if dlPtr's logical line\n *\twraps enough times to fill the text widget's current view - in this\n *\tcase we won't have enough dlPtrs in the linked list to be able to\n *\tsubtract off what we want.\n *\n * Results:\n *\tThe number of pixels.\n *\n *\tThis value has a valid range between '0' (the very top of the widget)\n *\tand the number of pixels in the total widget minus the pixel-height of\n *\tthe last line.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetYPixelCount(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    DLine *dlPtr)\t\t/* Information about the layout of a given\n\t\t\t\t * index. */\n{\n    TkTextLine *linePtr = dlPtr->index.linePtr;\n    int count;\n\n    /*\n     * Get the pixel count to the top of dlPtr's logical line. The rest of the\n     * function is then concerned with updating 'count' for any difference\n     * between the top of the logical line and the display line.\n     */\n\n    count = TkBTreePixelsTo(textPtr, linePtr);\n\n    /*\n     * For the common case where this dlPtr is also the start of the logical\n     * line, we can return right away.\n     */\n\n    if (IsStartOfNotMergedLine(textPtr, &dlPtr->index)) {\n\treturn count;\n    }\n\n    /*\n     * Add on the logical line's height to reach one pixel beyond the bottom\n     * of the logical line. And then subtract off the heights of all the\n     * display lines from dlPtr to the end of its logical line.\n     *\n     * A different approach would be to lay things out from the start of the\n     * logical line until we reach dlPtr, but since none of those are\n     * pre-calculated, it'll usually take a lot longer. (But there are cases\n     * where it would be more efficient: say if we're on the second of 1000\n     * wrapped lines all from a single logical line - but that sort of\n     * optimization is left for the future).\n     */\n\n    count += TkBTreeLinePixelCount(textPtr, linePtr);\n\n    do {\n\tcount -= dlPtr->height;\n\tif (dlPtr->nextPtr == NULL) {\n\t    /*\n\t     * We've run out of pre-calculated display lines, so we have to\n\t     * lay them out ourselves until the end of the logical line. Here\n\t     * is where we could be clever and ask: what's faster, to layout\n\t     * all lines from here to line-end, or all lines from the original\n\t     * dlPtr to the line-start? We just assume the former.\n\t     */\n\n\t    TkTextIndex index;\n\t    int notFirst = 0;\n\n\t    while (1) {\n\t\tTkTextIndexForwBytes(textPtr, &dlPtr->index,\n\t\t\tdlPtr->byteCount, &index);\n\t\tif (notFirst) {\n\t\t    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n\t\t}\n\t\tif (index.linePtr != linePtr) {\n\t\t    break;\n\t\t}\n\t\tdlPtr = LayoutDLine(textPtr, &index);\n\n\t\tif (tkTextDebug) {\n\t\t    char string[TK_POS_CHARS];\n\n\t\t    /*\n\t\t     * Debugging is enabled, so keep a log of all the lines\n\t\t     * whose height was recalculated. The test suite uses this\n\t\t     * information.\n\t\t     */\n\n\t\t    TkTextPrintIndex(textPtr, &index, string);\n\t\t    LOG(\"tk_textHeightCalc\", string);\n\t\t}\n\t\tcount -= dlPtr->height;\n\t\tnotFirst = 1;\n\t    }\n\t    break;\n\t}\n\tdlPtr = dlPtr->nextPtr;\n    } while (dlPtr->index.linePtr == linePtr);\n\n    return count;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetYView --\n *\n *\tThis function computes the fractions that indicate what's visible in a\n *\ttext window and, optionally, evaluates a Tcl script to report them to\n *\tthe text's associated scrollbar.\n *\n * Results:\n *\tIf report is zero, then the interp's result is filled in with two real\n *\tnumbers separated by a space, giving the position of the top and\n *\tbottom of the window as fractions from 0 to 1, where 0 means the\n *\tbeginning of the text and 1 means the end. If report is non-zero, then\n *\tthe interp's result isn't modified directly, but a script is evaluated\n *\tin interp to report the new scroll position to the scrollbar (if the\n *\tscroll position hasn't changed then no script is invoked).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetYView(\n    Tcl_Interp *interp,\t\t/* If \"report\" is FALSE, string describing\n\t\t\t\t * visible range gets stored in the interp's\n\t\t\t\t * result. */\n    TkText *textPtr,\t\t/* Information about text widget. */\n    int report)\t\t\t/* Non-zero means report info to scrollbar if\n\t\t\t\t * it has changed. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    double first, last;\n    DLine *dlPtr;\n    int totalPixels, code, count;\n    Tcl_Obj *listObj;\n\n    dlPtr = dInfoPtr->dLinePtr;\n\n    if (dlPtr == NULL) {\n\treturn;\n    }\n\n    totalPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree, textPtr);\n\n    if (totalPixels == 0) {\n\tfirst = 0.0;\n\tlast = 1.0;\n    } else {\n\t/*\n\t * Get the pixel count for the first visible pixel of the first\n\t * visible line. If the first visible line is only partially visible,\n\t * then we use 'topPixelOffset' to get the difference.\n\t */\n\n\tcount = GetYPixelCount(textPtr, dlPtr);\n\tfirst = (count + dInfoPtr->topPixelOffset) / (double) totalPixels;\n\n\t/*\n\t * Add on the total number of visible pixels to get the count to one\n\t * pixel _past_ the last visible pixel. This is how the 'yview'\n\t * command is documented, and also explains why we are dividing by\n\t * 'totalPixels' and not 'totalPixels-1'.\n\t */\n\n\twhile (1) {\n\t    int extra;\n\n\t    count += dlPtr->height;\n\t    extra = dlPtr->y + dlPtr->height - dInfoPtr->maxY;\n\t    if (extra > 0) {\n\t\t/*\n\t\t * This much of the last line is not visible, so don't count\n\t\t * these pixels. Since we've reached the bottom of the window,\n\t\t * we break out of the loop.\n\t\t */\n\n\t\tcount -= extra;\n\t\tbreak;\n\t    }\n\t    if (dlPtr->nextPtr == NULL) {\n\t\tbreak;\n\t    }\n\t    dlPtr = dlPtr->nextPtr;\n\t}\n\n\tif (count > totalPixels) {\n\t    /*\n\t     * It can be possible, if we do not update each line's pixelHeight\n\t     * cache when we lay out individual DLines that the count\n\t     * generated here is more up-to-date than that maintained by the\n\t     * BTree. In such a case, the best we can do here is to fix up\n\t     * 'count' and continue, which might result in small, temporary\n\t     * perturbations to the size of the scrollbar. This is basically\n\t     * harmless, but in a perfect world we would not have this\n\t     * problem.\n\t     *\n\t     * For debugging purposes, if anyone wishes to improve the text\n\t     * widget further, the following 'panic' can be activated. In\n\t     * principle it should be possible to ensure the BTree is always\n\t     * at least as up to date as the display, so in the future we\n\t     * might be able to leave the 'panic' in permanently when we\n\t     * believe we have resolved the cache synchronisation issue.\n\t     *\n\t     * However, to achieve that goal would, I think, require a fairly\n\t     * substantial refactorisation of the code in this file so that\n\t     * there is much more obvious and explicit coordination between\n\t     * calls to LayoutDLine and updating of each TkTextLine's\n\t     * pixelHeight. The complicated bit is that LayoutDLine deals with\n\t     * individual display lines, but pixelHeight is for a logical\n\t     * line.\n\t     */\n\n#if 0\n\t    Tcl_Panic(\"Counted more pixels (%d) than expected (%d) total \"\n\t\t    \"pixels in text widget scroll bar calculation.\", count,\n\t\t    totalPixels);\n#endif\n\t    count = totalPixels;\n\t}\n\n\tlast = ((double) count)/((double)totalPixels);\n    }\n\n    if (!report) {\n\tlistObj = Tcl_NewListObj(0,NULL);\n\tTcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first));\n\tTcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last));\n\tTcl_SetObjResult(interp, listObj);\n\treturn;\n    }\n\n    if (FP_EQUAL_SCALE(first, dInfoPtr->yScrollFirst, totalPixels) &&\n\t    FP_EQUAL_SCALE(last, dInfoPtr->yScrollLast, totalPixels)) {\n\treturn;\n    }\n\n    dInfoPtr->yScrollFirst = first;\n    dInfoPtr->yScrollLast = last;\n    if (textPtr->yScrollCmdObj != NULL) {\n\tchar buf1[TCL_DOUBLE_SPACE+1];\n\tchar buf2[TCL_DOUBLE_SPACE+1];\n\tTcl_DString buf;\n\n\tbuf1[0] = ' ';\n\tbuf2[0] = ' ';\n\tTcl_PrintDouble(NULL, first, buf1+1);\n\tTcl_PrintDouble(NULL, last, buf2+1);\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(textPtr->yScrollCmdObj), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, buf1, TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, buf2, TCL_INDEX_NONE);\n\tcode = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tif (code != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (vertical scrolling command executed by text)\");\n\t    Tcl_BackgroundException(interp, code);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AsyncUpdateYScrollbar --\n *\n *\tThis function is called to update the vertical scrollbar asychronously\n *\tas the pixel height calculations progress for lines in the widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSee 'GetYView'. In particular the scrollbar position and size may be\n *\tchanged.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAsyncUpdateYScrollbar(\n    void *clientData)\t/* Information about widget. */\n{\n    TkText *textPtr = (TkText *)clientData;\n\n    textPtr->dInfoPtr->scrollbarTimer = NULL;\n\n    if (!(textPtr->flags & DESTROYED)) {\n\tGetYView(textPtr->interp, textPtr, 1);\n    }\n\n    if (textPtr->refCount-- <= 1) {\n\tTcl_Free(textPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindDLine --\n *\n *\tThis function is called to find the DLine corresponding to a given\n *\ttext index.\n *\n * Results:\n *\tThe return value is a pointer to the first DLine found in the list\n *\theaded by dlPtr that displays information at or after the specified\n *\tposition. If there is no such line in the list then NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic DLine *\nFindDLine(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    DLine *dlPtr,\t/* Pointer to first in list of DLines to\n\t\t\t\t * search. */\n    const TkTextIndex *indexPtr)/* Index of desired character. */\n{\n    DLine *dlPtrPrev;\n    TkTextIndex indexPtr2;\n\n    if (dlPtr == NULL) {\n\treturn NULL;\n    }\n    if (TkBTreeLinesTo(NULL, indexPtr->linePtr)\n\t    < TkBTreeLinesTo(NULL, dlPtr->index.linePtr)) {\n\t/*\n\t * The first display line is already past the desired line.\n\t */\n\n\treturn dlPtr;\n    }\n\n    /*\n     * The display line containing the desired index is such that the index\n     * of the first character of this display line is at or before the\n     * desired index, and the index of the first character of the next\n     * display line is after the desired index.\n     */\n\n    while (TkTextIndexCmp(&dlPtr->index,indexPtr) < 0) {\n\tdlPtrPrev = dlPtr;\n\tdlPtr = dlPtr->nextPtr;\n\tif (dlPtr == NULL) {\n\t    /*\n\t     * We're past the last display line, either because the desired\n\t     * index lies past the visible text, or because the desired index\n\t     * is on the last display line.\n\t     */\n\t    indexPtr2 = dlPtrPrev->index;\n\t    TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,\n\t\t    &indexPtr2);\n\t    if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {\n\t\t/*\n\t\t * The desired index is on the last display line.\n\t\t * --> return this display line.\n\t\t */\n\t\tdlPtr = dlPtrPrev;\n\t    } else {\n\t\t/*\n\t\t * The desired index is past the visible text. There is no\n\t\t * display line displaying something at the desired index.\n\t\t * --> return NULL.\n\t\t */\n\t    }\n\t    break;\n\t}\n\tif (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) {\n\t    /*\n\t     * If we're here then we would normally expect that:\n\t     *   dlPtrPrev->index  <=  indexPtr  <  dlPtr->index\n\t     * i.e. we have found the searched display line being dlPtr.\n\t     * However it is possible that some DLines were unlinked\n\t     * previously, leading to a situation where going through\n\t     * the list of display lines skips display lines that did\n\t     * exist just a moment ago.\n\t     */\n\t    indexPtr2 = dlPtrPrev->index;\n\t    TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,\n\t\t    &indexPtr2);\n\t    if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {\n\t\t/*\n\t\t * Confirmed:\n\t\t *   dlPtrPrev->index  <=  indexPtr  <  dlPtr->index\n\t\t * --> return dlPtrPrev.\n\t\t */\n\t\tdlPtr = dlPtrPrev;\n\t    } else {\n\t\t/*\n\t\t * The last (rightmost) index shown by dlPtrPrev is still\n\t\t * before the desired index. This may be because there was\n\t\t * previously a display line between dlPtrPrev and dlPtr\n\t\t * and this display line has been unlinked.\n\t\t * --> return dlPtr.\n\t\t */\n\t    }\n\t    break;\n\t}\n    }\n\n    return dlPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IsStartOfNotMergedLine --\n *\n *\tThis function checks whether the given index is the start of a\n *      logical line that is not merged with the previous logical line\n *      (due to elision of the eol of the previous line).\n *\n * Results:\n *\tReturns whether the given index denotes the first index of a\n*       logical line not merged with its previous line.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nIsStartOfNotMergedLine(\n      const TkText *textPtr,\t\t/* Widget record for text widget. */\n      const TkTextIndex *indexPtr)\t/* Index to check. */\n{\n    TkTextIndex indexPtr2;\n\n    if (indexPtr->byteIndex != 0) {\n\t/*\n\t * Not the start of a logical line.\n\t */\n\treturn 0;\n    }\n\n    if (TkTextIndexBackBytes(textPtr, indexPtr, 1, &indexPtr2)) {\n\t/*\n\t * indexPtr is the first index of the text widget.\n\t */\n\treturn 1;\n    }\n\n    if (!TkTextIsElided(textPtr, &indexPtr2, NULL)) {\n\t/*\n\t * The eol of the line just before indexPtr is elided.\n\t */\n\treturn 1;\n    }\n\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextPixelIndex --\n *\n *\tGiven an (x,y) coordinate on the screen, find the location of the\n *\tcharacter closest to that location.\n *\n * Results:\n *\tThe index at *indexPtr is modified to refer to the character on the\n *\tdisplay that is closest to (x,y).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextPixelIndex(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    int x, int y,\t\t/* Pixel coordinates of point in widget's\n\t\t\t\t * window. */\n    TkTextIndex *indexPtr,\t/* This index gets filled in with the index of\n\t\t\t\t * the character nearest to (x,y). */\n    bool *nearest)\t\t/* If non-NULL then gets set to 0 if (x,y) is\n\t\t\t\t * actually over the returned index, and 1 if\n\t\t\t\t * it is just nearby (e.g. if x,y is on the\n\t\t\t\t * border of the widget). */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr, *validDlPtr;\n    bool nearby = false;\n\n    /*\n     * Make sure that all of the layout information about what's displayed\n     * where on the screen is up-to-date.\n     */\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n\n    /*\n     * If the coordinates are above the top of the window, then adjust them to\n     * refer to the upper-right corner of the window. If they're off to one\n     * side or the other, then adjust to the closest side.\n     */\n\n    if (y < dInfoPtr->y) {\n\ty = dInfoPtr->y;\n\tx = dInfoPtr->x;\n\tnearby = true;\n    }\n    if (x >= dInfoPtr->maxX) {\n\tx = dInfoPtr->maxX - 1;\n\tnearby = true;\n    }\n    if (x < dInfoPtr->x) {\n\tx = dInfoPtr->x;\n\tnearby = true;\n    }\n\n    /*\n     * Find the display line containing the desired y-coordinate.\n     */\n\n    if (dInfoPtr->dLinePtr == NULL) {\n\tif (nearest != NULL) {\n\t    *nearest = true;\n\t}\n\t*indexPtr = textPtr->topIndex;\n\treturn;\n    }\n    for (dlPtr = validDlPtr = dInfoPtr->dLinePtr;\n\t    y >= (dlPtr->y + dlPtr->height);\n\t    dlPtr = dlPtr->nextPtr) {\n\tif (dlPtr->chunkPtr != NULL) {\n\t    validDlPtr = dlPtr;\n\t}\n\tif (dlPtr->nextPtr == NULL) {\n\t    /*\n\t     * Y-coordinate is off the bottom of the displayed text. Use the\n\t     * last character on the last line.\n\t     */\n\n\t    x = dInfoPtr->maxX - 1;\n\t    nearby = true;\n\t    break;\n\t}\n    }\n    if (dlPtr->chunkPtr == NULL) {\n\tdlPtr = validDlPtr;\n    }\n\n    if (nearest != NULL) {\n\t*nearest = nearby;\n    }\n\n    DlineIndexOfX(textPtr, dlPtr, x, indexPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DlineIndexOfX --\n *\n *\tGiven an x coordinate in a display line, find the index of the\n *\tcharacter closest to that location.\n *\n *\tThis is effectively the opposite of DlineXOfIndex.\n *\n * Results:\n *\tThe index at *indexPtr is modified to refer to the character on the\n *\tdisplay line that is closest to x.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDlineIndexOfX(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    DLine *dlPtr,\t\t/* Display information for this display\n\t\t\t\t * line. */\n    int x,\t\t\t/* Pixel x coordinate of point in widget's\n\t\t\t\t * window. */\n    TkTextIndex *indexPtr)\t/* This index gets filled in with the index of\n\t\t\t\t * the character nearest to x. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    TkTextDispChunk *chunkPtr;\n\n    /*\n     * Scan through the line's chunks to find the one that contains the\n     * desired x-coordinate. Before doing this, translate the x-coordinate\n     * from the coordinate system of the window to the coordinate system of\n     * the line (to take account of x-scrolling).\n     */\n\n    *indexPtr = dlPtr->index;\n    x = x - dInfoPtr->x + dInfoPtr->curXPixelOffset;\n    chunkPtr = dlPtr->chunkPtr;\n\n    if (chunkPtr == NULL || x == 0) {\n\t/*\n\t * This may occur if everything is elided, or if we're simply already\n\t * at the beginning of the line.\n\t */\n\n\treturn;\n    }\n\n    while (x >= (chunkPtr->x + chunkPtr->width)) {\n\t/*\n\t * Note that this forward then backward movement of the index can be\n\t * problematic at the end of the buffer (we can't move forward, and\n\t * then when we move backward, we do, leading to the wrong position).\n\t * Hence when x == 0 we take special action above.\n\t */\n\n\tif (TkTextIndexForwBytes(NULL,indexPtr,chunkPtr->numBytes,indexPtr)) {\n\t    /*\n\t     * We've reached the end of the text.\n\t     */\n\n\t    TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES);\n\t    return;\n\t}\n\tif (chunkPtr->nextPtr == NULL) {\n\t    /*\n\t     * We've reached the end of the display line.\n\t     */\n\n\t    TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES);\n\t    return;\n\t}\n\tchunkPtr = chunkPtr->nextPtr;\n    }\n\n    /*\n     * If the chunk has more than one byte in it, ask it which character is at\n     * the desired location. In this case we can manipulate\n     * 'indexPtr->byteIndex' directly, because we know we're staying inside a\n     * single logical line.\n     */\n\n    if (chunkPtr->numBytes > 1) {\n\tindexPtr->byteIndex += chunkPtr->measureProc(chunkPtr, x);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextIndexOfX --\n *\n *\tGiven a logical x coordinate (i.e. distance in pixels from the\n *\tbeginning of the display line, not taking into account any information\n *\tabout the window, scrolling etc.) on the display line starting with\n *\tthe given index, adjust that index to refer to the object under the x\n *\tcoordinate.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextIndexOfX(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    int x,\t\t\t/* The x coordinate for which we want the\n\t\t\t\t * index. */\n    TkTextIndex *indexPtr)\t/* Index of display line start, which will be\n\t\t\t\t * adjusted to the index under the given x\n\t\t\t\t * coordinate. */\n{\n    DLine *dlPtr = LayoutDLine(textPtr, indexPtr);\n    DlineIndexOfX(textPtr, dlPtr, x + textPtr->dInfoPtr->x\n\t\t- textPtr->dInfoPtr->curXPixelOffset, indexPtr);\n    FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DlineXOfIndex --\n *\n *\tGiven a relative byte index on a given display line (i.e. the number\n *\tof byte indices from the beginning of the given display line), find\n *\tthe x coordinate of that index within the abstract display line,\n *\twithout adjusting for the x-scroll state of the line.\n *\n *\tThis is effectively the opposite of DlineIndexOfX.\n *\n *\tNB. The 'byteIndex' is relative to the display line, NOT the logical\n *\tline.\n *\n * Results:\n *\tThe x coordinate.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDlineXOfIndex(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    DLine *dlPtr,\t\t/* Display information for this display\n\t\t\t\t * line. */\n    Tcl_Size byteIndex)\t\t/* The byte index for which we want the\n\t\t\t\t * coordinate. */\n{\n    TkTextDispChunk *chunkPtr = dlPtr->chunkPtr;\n    int x = 0;\n\n    if (byteIndex == 0 || chunkPtr == NULL) {\n\treturn x;\n    }\n\n    /*\n     * Scan through the line's chunks to find the one that contains the\n     * desired byte index.\n     */\n\n    chunkPtr = dlPtr->chunkPtr;\n    while (byteIndex > 0) {\n\tif (byteIndex < chunkPtr->numBytes) {\n\t    int y, width, height;\n\n\t    chunkPtr->bboxProc(textPtr, chunkPtr, byteIndex,\n\t\t    dlPtr->y + dlPtr->spaceAbove,\n\t\t    dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,\n\t\t    dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,\n\t\t    &height);\n\t    break;\n\t}\n\tbyteIndex -= chunkPtr->numBytes;\n\tif (chunkPtr->nextPtr == NULL || byteIndex == 0) {\n\t    x = chunkPtr->x + chunkPtr->width;\n\t    break;\n\t}\n\tchunkPtr = chunkPtr->nextPtr;\n    }\n\n    return x;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextIndexBbox --\n *\n *\tGiven an index, find the bounding box of the screen area occupied by\n *\tthe entity (character, window, image) at that index.\n *\n * Results:\n *\tZero is returned if the index is on the screen. -1 means the index is\n *\tnot on the screen. If the return value is 0, then the bounding box of\n *\tthe part of the index that's visible on the screen is returned to\n *\t*xPtr, *yPtr, *widthPtr, and *heightPtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkTextIndexBbox(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    const TkTextIndex *indexPtr,/* Index whose bounding box is desired. */\n    int *xPtr, int *yPtr,\t/* Filled with index's upper-left\n\t\t\t\t * coordinate. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* Filled in with index's dimensions. */\n    int *charWidthPtr,\t\t/* If the 'index' is at the end of a display\n\t\t\t\t * line and therefore takes up a very large\n\t\t\t\t * width, this is used to return the smaller\n\t\t\t\t * width actually desired by the index. */\n    int *cursorWidthPtr)\t/* Receives the same value as 'charWidthPtr'\n\t\t\t\t * except when indexPtr points to a Tab. Then\n\t\t\t\t * 'cursorWidthPtr' gets reduced to the width\n\t\t\t\t * of a single space. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr;\n    TkTextDispChunk *chunkPtr;\n    Tcl_Size byteCount;\n    int dummy;\n\n    if (charWidthPtr == NULL) {\n\tcharWidthPtr = &dummy;\n    }\n\n    /*\n     * Make sure that all of the screen layout information is up to date.\n     */\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n\n    /*\n     * Find the display line containing the desired index.\n     */\n\n    dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);\n\n    /*\n     * Two cases shall be trapped here because the logic later really\n     * needs dlPtr to be the display line containing indexPtr:\n     *   1. if no display line contains the desired index (NULL dlPtr)\n     *   2. if indexPtr is before the first display line, in which case\n     *      dlPtr currently points to the first display line\n     */\n\n    if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) {\n\treturn -1;\n    }\n\n    /*\n     * Find the chunk within the display line that contains the desired\n     * index. The chunks making the display line are skipped up to but not\n     * including the one crossing indexPtr. Skipping is done based on\n     * a byteCount offset possibly spanning several logical lines in case\n     * they are elided.\n     */\n\n    byteCount = TkTextIndexCountBytes(textPtr, &dlPtr->index, indexPtr);\n    for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {\n\tif (chunkPtr == NULL) {\n\t    return -1;\n\t}\n\tif (byteCount < chunkPtr->numBytes) {\n\t    break;\n\t}\n\tbyteCount -= chunkPtr->numBytes;\n    }\n\n    /*\n     * Call a chunk-specific function to find the horizontal range of the\n     * character within the chunk, then fill in the vertical range. The\n     * x-coordinate returned by bboxProc is a coordinate within a line, not a\n     * coordinate on the screen. Translate it to reflect horizontal scrolling.\n     */\n\n    chunkPtr->bboxProc(textPtr, chunkPtr, byteCount,\n\t    dlPtr->y + dlPtr->spaceAbove,\n\t    dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,\n\t    dlPtr->baseline - dlPtr->spaceAbove, xPtr, yPtr, widthPtr,\n\t    heightPtr);\n    *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset;\n    if ((byteCount == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) {\n\t/*\n\t * Last character in display line. Give it all the space up to the\n\t * line.\n\t */\n\n\t*charWidthPtr = dInfoPtr->maxX - *xPtr;\n\tif (*charWidthPtr > textPtr->charWidth) {\n\t    *charWidthPtr = textPtr->charWidth;\n\t}\n\tif (*xPtr > dInfoPtr->maxX) {\n\t    *xPtr = dInfoPtr->maxX;\n\t}\n\t*widthPtr = dInfoPtr->maxX - *xPtr;\n    } else {\n\t*charWidthPtr = *widthPtr;\n    }\n    if (*widthPtr == 0) {\n\t/*\n\t * With zero width (e.g. elided text) we just need to make sure it is\n\t * onscreen, where the '=' case here is ok.\n\t */\n\n\tif (*xPtr < dInfoPtr->x) {\n\t    return -1;\n\t}\n    } else {\n\tif ((*xPtr + *widthPtr) <= dInfoPtr->x) {\n\t    return -1;\n\t}\n    }\n    if ((*xPtr + *widthPtr) > dInfoPtr->maxX) {\n\t*widthPtr = dInfoPtr->maxX - *xPtr;\n\tif (*widthPtr <= 0) {\n\t    return -1;\n\t}\n    }\n    if ((*yPtr + *heightPtr) > dInfoPtr->maxY) {\n\t*heightPtr = dInfoPtr->maxY - *yPtr;\n\tif (*heightPtr <= 0) {\n\t    return -1;\n\t}\n    }\n\n    /*\n     * For a block cursor on a tab, cursorWidthPtr is the whitespace width.\n     */\n\n    if (cursorWidthPtr != NULL) {\n\t*cursorWidthPtr = *charWidthPtr;\n\tif (chunkPtr->bboxProc == CharBboxProc) {\n\t    CharInfo *ciPtr = (CharInfo*)chunkPtr->clientData;\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    BaseCharInfo *bciPtr =\n\t\t    (BaseCharInfo*)ciPtr->baseChunkPtr->clientData;\n\t    char *chars = Tcl_DStringValue(&bciPtr->baseChars);\n\n\t    if (chars[ciPtr->baseOffset + byteCount] == '\\t')\n#else\n\t    if (ciPtr->chars[byteCount] == '\\t')\n#endif\n\t    {\n\t\tCharChunkMeasureChars(chunkPtr, \" \", 1, 0, 1,\n\t\t    0, -1, 0, cursorWidthPtr);\n\t    }\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextDLineInfo --\n *\n *\tGiven an index, return information about the display line containing\n *\tthat character.\n *\n * Results:\n *\tZero is returned if the character is on the screen. -1 means the\n *\tcharacter isn't on the screen. If the return value is 0, then\n *\tinformation is returned in the variables pointed to by xPtr, yPtr,\n *\twidthPtr, heightPtr, and basePtr.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkTextDLineInfo(\n    TkText *textPtr,\t\t/* Widget record for text widget. */\n    const TkTextIndex *indexPtr,/* Index of character whose bounding box is\n\t\t\t\t * desired. */\n    int *xPtr, int *yPtr,\t/* Filled with line's upper-left\n\t\t\t\t * coordinate. */\n    int *widthPtr, int *heightPtr,\n\t\t\t\t/* Filled in with line's dimensions. */\n    int *basePtr)\t\t/* Filled in with the baseline position,\n\t\t\t\t * measured as an offset down from *yPtr. */\n{\n    TextDInfo *dInfoPtr = textPtr->dInfoPtr;\n    DLine *dlPtr;\n    int dlx;\n\n    /*\n     * Make sure that all of the screen layout information is up to date.\n     */\n\n    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {\n\tUpdateDisplayInfo(textPtr);\n    }\n\n    /*\n     * Find the display line containing the desired index.\n     */\n\n    dlPtr = FindDLine(textPtr, dInfoPtr->dLinePtr, indexPtr);\n\n    /*\n     * Two cases shall be trapped here because the logic later really\n     * needs dlPtr to be the display line containing indexPtr:\n     *   1. if no display line contains the desired index (NULL dlPtr)\n     *   2. if indexPtr is before the first display line, in which case\n     *      dlPtr currently points to the first display line\n     */\n\n    if ((dlPtr == NULL) || (TkTextIndexCmp(&dlPtr->index, indexPtr) > 0)) {\n\treturn -1;\n    }\n\n    dlx = (dlPtr->chunkPtr != NULL? dlPtr->chunkPtr->x: 0);\n    *xPtr = dInfoPtr->x - dInfoPtr->curXPixelOffset + dlx;\n    *widthPtr = dlPtr->length - dlx;\n    *yPtr = dlPtr->y;\n    if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) {\n\t*heightPtr = dInfoPtr->maxY - dlPtr->y;\n    } else {\n\t*heightPtr = dlPtr->height;\n    }\n    *basePtr = dlPtr->baseline;\n    return 0;\n}\n\f\n/*\n * Get bounding-box information about an elided chunk.\n */\n\nstatic void\nElideBboxProc(\n    TCL_UNUSED(TkText *),\n    TkTextDispChunk *chunkPtr,\t/* Chunk containing desired char. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Index of desired character within the\n\t\t\t\t * chunk. */\n    int y,\t\t\t/* Topmost pixel in area allocated for this\n\t\t\t\t * line. */\n    TCL_UNUSED(int),\t/* Height of line, in pixels. */\n    TCL_UNUSED(int),\t/* Location of line's baseline, in pixels\n\t\t\t\t * measured down from y. */\n    int *xPtr, int *yPtr,\t/* Gets filled in with coords of character's\n\t\t\t\t * upper-left pixel. X-coord is in same\n\t\t\t\t * coordinate system as chunkPtr->x. */\n    int *widthPtr,\t\t/* Gets filled in with width of character, in\n\t\t\t\t * pixels. */\n    int *heightPtr)\t\t/* Gets filled in with height of character, in\n\t\t\t\t * pixels. */\n{\n\n    *xPtr = chunkPtr->x;\n    *yPtr = y;\n    *widthPtr = *heightPtr = 0;\n}\n\f\n/*\n * Measure an elided chunk.\n */\n\nstatic Tcl_Size\nElideMeasureProc(\n    TCL_UNUSED(TkTextDispChunk *),\t/* Chunk containing desired coord. */\n    TCL_UNUSED(int))\t\t/* X-coordinate, in same coordinate system as\n\t\t\t\t * chunkPtr->x. */\n{\n    return 0 /*chunkPtr->numBytes - 1*/;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextCharLayoutProc --\n *\n *\tThis function is the \"layoutProc\" for character segments.\n *\n * Results:\n *\tIf there is something to display for the chunk then a non-zero value\n *\tis returned and the fields of chunkPtr will be filled in (see the\n *\tdeclaration of TkTextDispChunk in tkText.h for details). If zero is\n *\treturned it means that no characters from this chunk fit in the\n *\twindow. If -1 is returned it means that this segment just doesn't need\n *\tto be displayed (never happens for text).\n *\n * Side effects:\n *\tMemory is allocated to hold additional information about the chunk.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextCharLayoutProc(\n    TCL_UNUSED(TkText *),\t/* Text widget being layed out. */\n    TCL_UNUSED(TkTextIndex *),\t/* Index of first character to lay out\n\t\t\t\t * (corresponds to segPtr and offset). */\n    TkTextSegment *segPtr,\t/* Segment being layed out. */\n    Tcl_Size byteOffset,\t/* Byte offset within segment of first\n\t\t\t\t * character to consider. */\n    int maxX,\t\t\t/* Chunk must not occupy pixels at this\n\t\t\t\t * position or higher. */\n    Tcl_Size maxBytes,\t\t/* Chunk must not include more than this many\n\t\t\t\t * characters. */\n    int noCharsYet,\t\t/* Non-zero means no characters have been\n\t\t\t\t * assigned to this display line yet. */\n    TkWrapMode wrapMode,\t/* How to handle line wrapping:\n\t\t\t\t * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or\n\t\t\t\t * TEXT_WRAPMODE_WORD. */\n    TkTextDispChunk *chunkPtr)\n\t\t\t\t/* Structure to fill in with information about\n\t\t\t\t * this chunk. The x field has already been\n\t\t\t\t * set by the caller. */\n{\n    Tk_Font tkfont;\n    int nextX;\n    Tcl_Size count;\n    Tcl_Size bytesThatFit;\n    CharInfo *ciPtr;\n    char *p;\n    TkTextSegment *nextPtr;\n    Tk_FontMetrics fm;\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    const char *line;\n    int lineOffset;\n    BaseCharInfo *bciPtr;\n    Tcl_DString *baseString;\n#endif\n\n    /*\n     * Figure out how many characters will fit in the space we've got. Include\n     * the next character, even though it won't fit completely, if any of the\n     * following is true:\n     *\t (a) the chunk contains no characters and the display line contains no\n     *\t     characters yet (i.e. the line isn't wide enough to hold even a\n     *\t     single character).\n     *\t (b) at least one pixel of the character is visible, we have not\n     *\t     already exceeded the character limit, and the next character is a\n     *\t     white space character.\n     * In the specific case of 'word' wrapping mode however, include all space\n     * characters following the characters that fit in the space we've got,\n     * even if no pixel of them is visible.\n     */\n\n    p = segPtr->body.chars + byteOffset;\n    tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;\n\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    if (baseCharChunkPtr == NULL) {\n\tbaseCharChunkPtr = chunkPtr;\n\tbciPtr = (BaseCharInfo *)Tcl_Alloc(sizeof(BaseCharInfo));\n\tbaseString = &bciPtr->baseChars;\n\tTcl_DStringInit(baseString);\n\tbciPtr->width = 0;\n\n\tciPtr = &bciPtr->ci;\n    } else {\n\tbciPtr = (BaseCharInfo *)baseCharChunkPtr->clientData;\n\tciPtr = (CharInfo *)Tcl_Alloc(sizeof(CharInfo));\n\tbaseString = &bciPtr->baseChars;\n    }\n\n    lineOffset = Tcl_DStringLength(baseString);\n    line = Tcl_DStringAppend(baseString,p,maxBytes);\n\n    chunkPtr->clientData = ciPtr;\n    ciPtr->baseChunkPtr = baseCharChunkPtr;\n    ciPtr->baseOffset = lineOffset;\n    ciPtr->chars = NULL;\n    ciPtr->numBytes = 0;\n\n    bytesThatFit = CharChunkMeasureChars(chunkPtr, line,\n\t    lineOffset + maxBytes, lineOffset, -1, chunkPtr->x, maxX,\n\t    TK_ISOLATE_END, &nextX);\n#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */\n    bytesThatFit = CharChunkMeasureChars(chunkPtr, p, maxBytes, 0, -1,\n\t    chunkPtr->x, maxX, TK_ISOLATE_END, &nextX);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n    if (bytesThatFit + 1 <= maxBytes) {\n\tif ((bytesThatFit == 0) && (noCharsYet & 1)) {\n\t    int ch;\n\t    Tcl_Size chLen = Tcl_UtfToUniChar(p, &ch);\n\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    bytesThatFit = CharChunkMeasureChars(chunkPtr, line,\n\t\t    lineOffset+chLen, lineOffset, -1, chunkPtr->x, -1, 0,\n\t\t    &nextX);\n#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */\n\t    bytesThatFit = CharChunkMeasureChars(chunkPtr, p, chLen, 0, -1,\n\t\t    chunkPtr->x, -1, 0, &nextX);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\t}\n\tif ((nextX < maxX) && ((p[bytesThatFit] == ' ')\n\t\t|| (p[bytesThatFit] == '\\t'))) {\n\t    /*\n\t     * Space characters are funny, in that they are considered to fit\n\t     * if there is at least one pixel of space left on the line. Just\n\t     * give the space character whatever space is left.\n\t     */\n\n\t    nextX = maxX;\n\t    bytesThatFit++;\n\t}\n\tif (wrapMode == TEXT_WRAPMODE_WORD) {\n\t    while (p[bytesThatFit] == ' ') {\n\t\t/*\n\t\t * Space characters that would go at the beginning of the\n\t\t * next line are allocated to the current line. This gives\n\t\t * the effect of trimming white spaces that would otherwise\n\t\t * be seen at the beginning of wrapped lines.\n\t\t * Note that testing for '\\t' is useless here because the\n\t\t * chunk always includes at most one trailing \\t, see\n\t\t * LayoutDLine.\n\t\t */\n\n\t\tbytesThatFit++;\n\t    }\n\t}\n\tif (p[bytesThatFit] == '\\n') {\n\t    /*\n\t     * A newline character takes up no space, so if the previous\n\t     * character fits then so does the newline.\n\t     */\n\n\t    bytesThatFit++;\n\t}\n\tif (bytesThatFit == 0) {\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\t    chunkPtr->clientData = NULL;\n\t    if (chunkPtr == baseCharChunkPtr) {\n\t\tbaseCharChunkPtr = NULL;\n\t\tTcl_DStringFree(baseString);\n\t    } else {\n\t\tTcl_DStringSetLength(baseString,lineOffset);\n\t    }\n\t    Tcl_Free(ciPtr);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\t    return 0;\n\t}\n    }\n\n    Tk_GetFontMetrics(tkfont, &fm);\n\n    /*\n     * Fill in the chunk structure and allocate and initialize a CharInfo\n     * structure. If the last character is a newline then don't bother to\n     * display it.\n     */\n\n    chunkPtr->displayProc = CharDisplayProc;\n    chunkPtr->undisplayProc = CharUndisplayProc;\n    chunkPtr->measureProc = CharMeasureProc;\n    chunkPtr->bboxProc = CharBboxProc;\n    chunkPtr->numBytes = bytesThatFit;\n    chunkPtr->minAscent = fm.ascent + chunkPtr->stylePtr->sValuePtr->offset;\n    chunkPtr->minDescent = fm.descent - chunkPtr->stylePtr->sValuePtr->offset;\n    chunkPtr->minHeight = 0;\n    chunkPtr->width = nextX - chunkPtr->x;\n    chunkPtr->breakIndex = -1;\n\n#ifndef TK_LAYOUT_WITH_BASE_CHUNKS\n    ciPtr = (CharInfo *)Tcl_Alloc((offsetof(CharInfo, chars) + 1) + bytesThatFit);\n    chunkPtr->clientData = ciPtr;\n    memcpy(ciPtr->chars, p, bytesThatFit);\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n    ciPtr->numBytes = bytesThatFit;\n    if (p[bytesThatFit - 1] == '\\n') {\n\tciPtr->numBytes--;\n    }\n\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n    /*\n     * Final update for the current base chunk data.\n     */\n\n    Tcl_DStringSetLength(baseString,lineOffset+ciPtr->numBytes);\n    bciPtr->width = nextX - baseCharChunkPtr->x;\n\n    /*\n     * Finalize the base chunk if this chunk ends in a tab, which definitly\n     * breaks the context and needs to be handled on a higher level.\n     */\n\n    if (ciPtr->numBytes > 0 && p[ciPtr->numBytes - 1] == '\\t') {\n\tFinalizeBaseChunk(chunkPtr);\n    }\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n    /*\n     * Compute a break location. If we're in word wrap mode, a break can occur\n     * after any space character, or at the end of the chunk if the next\n     * segment (ignoring those with zero size) is not a character segment.\n     */\n\n    if (wrapMode != TEXT_WRAPMODE_WORD) {\n\tchunkPtr->breakIndex = chunkPtr->numBytes;\n    } else {\n\tfor (count = bytesThatFit, p += bytesThatFit - 1; count > 0;\n\t\tcount--, p--) {\n\t    /*\n\t     * Don't use isspace(); effects are unpredictable and can lead to\n\t     * odd word-wrapping problems on some platforms. Also don't use\n\t     * Tcl_UniCharIsSpace here either, as it identifies non-breaking\n\t     * spaces as places to break. What we actually want is only the\n\t     * ASCII space characters, so use them explicitly...\n\t     */\n\n\t    switch (*p) {\n\t    case '\\t': case '\\n': case '\\v': case '\\f': case '\\r': case ' ':\n\t\tchunkPtr->breakIndex = count;\n\t\tgoto checkForNextChunk;\n\t    }\n\t}\n    checkForNextChunk:\n\tif ((bytesThatFit + byteOffset) == segPtr->size) {\n\t    for (nextPtr = segPtr->nextPtr; nextPtr != NULL;\n\t\t    nextPtr = nextPtr->nextPtr) {\n\t\tif (nextPtr->size != 0) {\n\t\t    if (nextPtr->typePtr != &tkTextCharType) {\n\t\t\tchunkPtr->breakIndex = chunkPtr->numBytes;\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    }\n    return 1;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * CharChunkMeasureChars --\n *\n *\tDetermine the number of characters from a char chunk that will fit in\n *\tthe given horizontal span.\n *\n *\tThis is the same as MeasureChars (which see), but in the context of a\n *\tchar chunk, i.e. on a higher level of abstraction. Use this function\n *\twhereever possible instead of plain MeasureChars, so that the right\n *\tcontext is used automatically.\n *\n * Results:\n *\tThe return value is the number of bytes from the range of start to end\n *\tin source that fit in the span given by startX and maxX. *nextXPtr is\n *\tfilled in with the x-coordinate at which the first character that\n *\tdidn't fit would be drawn, if it were to be drawn.\n *\n * Side effects:\n *\tNone.\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Size\nCharChunkMeasureChars(\n    TkTextDispChunk *chunkPtr,\t/* Chunk from which to measure. */\n    const char *chars,\t\t/* Chars to use, instead of the chunk's own.\n\t\t\t\t * Used by the layoutproc during chunk setup.\n\t\t\t\t * All other callers use NULL. Not\n\t\t\t\t * NUL-terminated. */\n    Tcl_Size charsLen,\t\t/* Length of the \"chars\" parameter. */\n    Tcl_Size start, Tcl_Size end,\t\t/* The range of chars to measure inside the\n\t\t\t\t * chunk (or inside the additional chars). */\n    int startX,\t\t\t/* Starting x coordinate where the measured\n\t\t\t\t * span will begin. */\n    int maxX,\t\t\t/* Maximum pixel width of the span. May be -1\n\t\t\t\t * for unlimited. */\n    int flags,\t\t\t/* Flags to pass to MeasureChars. */\n    int *nextXPtr)\t\t/* The function puts the newly calculated\n\t\t\t\t * right border x-position of the span\n\t\t\t\t * here. */\n{\n    Tk_Font tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;\n    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;\n\n#ifndef TK_LAYOUT_WITH_BASE_CHUNKS\n    if (chars == NULL) {\n\tchars = ciPtr->chars;\n\tcharsLen = ciPtr->numBytes;\n    }\n    if (end == -1) {\n\tend = charsLen;\n    }\n\n    return MeasureChars(tkfont, chars, charsLen, start, end-start,\n\t    startX, maxX, flags, nextXPtr);\n#else /* TK_LAYOUT_WITH_BASE_CHUNKS */\n    {\n\tint xDisplacement;\n\tint fit, bstart = start, bend = end;\n\n\tif (chars == NULL) {\n\t    Tcl_DString *baseChars = &((BaseCharInfo *)\n\t\t    ciPtr->baseChunkPtr->clientData)->baseChars;\n\n\t    chars = Tcl_DStringValue(baseChars);\n\t    charsLen = Tcl_DStringLength(baseChars);\n\t    bstart += ciPtr->baseOffset;\n\t    if (bend == -1) {\n\t\tbend = ciPtr->baseOffset + ciPtr->numBytes;\n\t    } else {\n\t\tbend += ciPtr->baseOffset;\n\t    }\n\t} else if (bend == -1) {\n\t    bend = charsLen;\n\t}\n\n\tif (bstart == ciPtr->baseOffset) {\n\t    xDisplacement = startX - chunkPtr->x;\n\t} else {\n\t    int widthUntilStart = 0;\n\n\t    MeasureChars(tkfont, chars, charsLen, 0, bstart,\n\t\t    0, -1, 0, &widthUntilStart);\n\t    xDisplacement = startX - widthUntilStart - ciPtr->baseChunkPtr->x;\n\t}\n\n\tfit = MeasureChars(tkfont, chars, charsLen, 0, bend,\n\t\tciPtr->baseChunkPtr->x + xDisplacement, maxX, flags, nextXPtr);\n\n\tif (fit < bstart) {\n\t    return 0;\n\t} else {\n\t    return fit - bstart;\n\t}\n    }\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharDisplayProc --\n *\n *\tThis function is called to display a character chunk on the screen or\n *\tin an off-screen pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGraphics are drawn.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCharDisplayProc(\n    TCL_UNUSED(TkText *),\n    TkTextDispChunk *chunkPtr,\t/* Chunk that is to be drawn. */\n    int x,\t\t\t/* X-position in dst at which to draw this\n\t\t\t\t * chunk (may differ from the x-position in\n\t\t\t\t * the chunk because of scrolling). */\n    int y,\t\t\t/* Y-position at which to draw this chunk in\n\t\t\t\t * dst. */\n    TCL_UNUSED(int),\t\t/* Total height of line. */\n    int baseline,\t\t/* Offset of baseline from y. */\n    Display *display,\t\t/* Display to use for drawing. */\n    Drawable dst,\t\t/* Pixmap or window in which to draw chunk. */\n    TCL_UNUSED(int))\t/* Y-coordinate in text window that\n\t\t\t\t * corresponds to y. */\n{\n    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;\n    const char *string;\n    TextStyle *stylePtr;\n    StyleValues *sValuePtr;\n    Tcl_Size numBytes, offsetBytes;\n    int offsetX;\n#ifdef TK_DRAW_IN_CONTEXT\n    BaseCharInfo *bciPtr;\n#endif /* TK_DRAW_IN_CONTEXT */\n\n    if ((x + chunkPtr->width) <= 0) {\n\t/*\n\t * The chunk is off-screen.\n\t */\n\n\treturn;\n    }\n\n#ifdef TK_DRAW_IN_CONTEXT\n    bciPtr = (BaseCharInfo *)ciPtr->baseChunkPtr->clientData;\n    numBytes = Tcl_DStringLength(&bciPtr->baseChars);\n    string = Tcl_DStringValue(&bciPtr->baseChars);\n\n#elif defined(TK_LAYOUT_WITH_BASE_CHUNKS)\n    if (ciPtr->baseChunkPtr != chunkPtr) {\n\t/*\n\t * Without context drawing only base chunks display their foreground.\n\t */\n\n\treturn;\n    }\n\n    numBytes = Tcl_DStringLength(&((BaseCharInfo *) ciPtr)->baseChars);\n    string = ciPtr->chars;\n\n#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */\n    numBytes = ciPtr->numBytes;\n    string = ciPtr->chars;\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n    stylePtr = chunkPtr->stylePtr;\n    sValuePtr = stylePtr->sValuePtr;\n\n    /*\n     * If the text sticks out way to the left of the window, skip over the\n     * characters that aren't in the visible part of the window. This is\n     * essential if x is very negative (such as less than 32K); otherwise\n     * overflow problems will occur in servers that use 16-bit arithmetic,\n     * like X.\n     */\n\n    offsetX = x;\n    offsetBytes = 0;\n    if (x < 0) {\n\toffsetBytes = CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1,\n\t\tx, 0, 0, &offsetX);\n    }\n\n    /*\n     * Draw the text, underline, and overstrike for this chunk.\n     */\n\n    if (!sValuePtr->elide && (numBytes > offsetBytes)\n\t    && (stylePtr->fgGC != NULL)) {\n#ifdef TK_DRAW_IN_CONTEXT\n\tint start = ciPtr->baseOffset + offsetBytes;\n\tint len = ciPtr->numBytes - offsetBytes;\n\tint xDisplacement = x - chunkPtr->x;\n\n\tif ((len > 0) && (string[start + len - 1] == '\\t')) {\n\t    len--;\n\t}\n\tif (len <= 0) {\n\t    return;\n\t}\n\n\tTk_DrawCharsInContext(display, dst, stylePtr->fgGC, sValuePtr->tkfont,\n\t\tstring, numBytes, start, len,\n\t\tciPtr->baseChunkPtr->x + xDisplacement,\n\t\ty + baseline - sValuePtr->offset);\n\n\tif (sValuePtr->underline) {\n\t    Tk_UnderlineCharsInContext(display, dst, stylePtr->ulGC,\n\t\t    sValuePtr->tkfont, string, numBytes,\n\t\t    ciPtr->baseChunkPtr->x + xDisplacement,\n\t\t    y + baseline - sValuePtr->offset,\n\t\t    start, start+len);\n\t}\n\tif (sValuePtr->overstrike) {\n\t    Tk_FontMetrics fm;\n\n\t    Tk_GetFontMetrics(sValuePtr->tkfont, &fm);\n\t    Tk_UnderlineCharsInContext(display, dst, stylePtr->ovGC,\n\t\t    sValuePtr->tkfont, string, numBytes,\n\t\t    ciPtr->baseChunkPtr->x + xDisplacement,\n\t\t    y + baseline - sValuePtr->offset\n\t\t\t    - fm.descent - (fm.ascent * 3) / 10,\n\t\t    start, start+len);\n\t}\n#else /* !TK_DRAW_IN_CONTEXT */\n\tstring += offsetBytes;\n\tnumBytes -= offsetBytes;\n\n\tif ((numBytes > 0) && (string[numBytes - 1] == '\\t')) {\n\t    numBytes--;\n\t}\n\tTk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string,\n\t\tnumBytes, offsetX, y + baseline - sValuePtr->offset);\n\tif (sValuePtr->underline) {\n\t    Tk_UnderlineChars(display, dst, stylePtr->ulGC, sValuePtr->tkfont,\n\t\t    string, offsetX,\n\t\t    y + baseline - sValuePtr->offset,\n\t\t    0, numBytes);\n\n\t}\n\tif (sValuePtr->overstrike) {\n\t    Tk_FontMetrics fm;\n\n\t    Tk_GetFontMetrics(sValuePtr->tkfont, &fm);\n\t    Tk_UnderlineChars(display, dst, stylePtr->ovGC, sValuePtr->tkfont,\n\t\t    string, offsetX,\n\t\t    y + baseline - sValuePtr->offset\n\t\t\t    - fm.descent - (fm.ascent * 3) / 10,\n\t\t    0, numBytes);\n\t}\n#endif /* TK_DRAW_IN_CONTEXT */\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharUndisplayProc --\n *\n *\tThis function is called when a character chunk is no longer going to\n *\tbe displayed. It frees up resources that were allocated to display the\n *\tchunk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and other resources get freed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCharUndisplayProc(\n    TCL_UNUSED(TkText *),\t/* Overall information about text widget. */\n    TkTextDispChunk *chunkPtr)\t/* Chunk that is about to be freed. */\n{\n    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;\n\n    if (ciPtr) {\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n\tif (chunkPtr == ciPtr->baseChunkPtr) {\n\t    /*\n\t     * Basechunks are undisplayed first, when DLines are freed or\n\t     * partially freed, so this makes sure we don't access their data\n\t     * any more.\n\t     */\n\n\t    FreeBaseChunk(chunkPtr);\n\t} else if (ciPtr->baseChunkPtr != NULL) {\n\t    /*\n\t     * When other char chunks are undisplayed, drop their characters\n\t     * from the base chunk. This usually happens, when they are last\n\t     * in a line and need to be re-layed out.\n\t     */\n\n\t    RemoveFromBaseChunk(chunkPtr);\n\t}\n\n\tciPtr->baseChunkPtr = NULL;\n\tciPtr->chars = NULL;\n\tciPtr->numBytes = 0;\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\n\tTcl_Free(ciPtr);\n\tchunkPtr->clientData = NULL;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharMeasureProc --\n *\n *\tThis function is called to determine which character in a character\n *\tchunk lies over a given x-coordinate.\n *\n * Results:\n *\tThe return value is the index *within the chunk* of the character that\n *\tcovers the position given by \"x\".\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Size\nCharMeasureProc(\n    TkTextDispChunk *chunkPtr,\t/* Chunk containing desired coord. */\n    int x)\t\t\t/* X-coordinate, in same coordinate system as\n\t\t\t\t * chunkPtr->x. */\n{\n    int endX;\n\n    return CharChunkMeasureChars(chunkPtr, NULL, 0, 0, chunkPtr->numBytes-1,\n\t    chunkPtr->x, x, 0, &endX); /* CHAR OFFSET */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CharBboxProc --\n *\n *\tThis function is called to compute the bounding box of the area\n *\toccupied by a single character.\n *\n * Results:\n *\tThere is no return value. *xPtr and *yPtr are filled in with the\n *\tcoordinates of the upper left corner of the character, and *widthPtr\n *\tand *heightPtr are filled in with the dimensions of the character in\n *\tpixels. Note: not all of the returned bbox is necessarily visible on\n *\tthe screen (the rightmost part might be off-screen to the right, and\n *\tthe bottommost part might be off-screen to the bottom).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nCharBboxProc(\n    TCL_UNUSED(TkText *),\n    TkTextDispChunk *chunkPtr,\t/* Chunk containing desired char. */\n    Tcl_Size byteIndex,\t\t/* Byte offset of desired character within the\n\t\t\t\t * chunk. */\n    int y,\t\t\t/* Topmost pixel in area allocated for this\n\t\t\t\t * line. */\n    TCL_UNUSED(int),\t/* Height of line, in pixels. */\n    int baseline,\t\t/* Location of line's baseline, in pixels\n\t\t\t\t * measured down from y. */\n    int *xPtr, int *yPtr,\t/* Gets filled in with coords of character's\n\t\t\t\t * upper-left pixel. X-coord is in same\n\t\t\t\t * coordinate system as chunkPtr->x. */\n    int *widthPtr,\t\t/* Gets filled in with width of character, in\n\t\t\t\t * pixels. */\n    int *heightPtr)\t\t/* Gets filled in with height of character, in\n\t\t\t\t * pixels. */\n{\n    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;\n    int maxX;\n\n    maxX = chunkPtr->width + chunkPtr->x;\n    CharChunkMeasureChars(chunkPtr, NULL, 0, 0, byteIndex,\n\t    chunkPtr->x, -1, 0, xPtr);\n\n    if (byteIndex == ciPtr->numBytes) {\n\t/*\n\t * This situation only happens if the last character in a line is a\n\t * space character, in which case it absorbs all of the extra space in\n\t * the line (see TkTextCharLayoutProc).\n\t */\n\n\t*widthPtr = maxX - *xPtr;\n    } else if ((ciPtr->chars[byteIndex] == '\\t')\n\t    && (byteIndex == ciPtr->numBytes - 1)) {\n\t/*\n\t * The desired character is a tab character that terminates a chunk;\n\t * give it all the space left in the chunk.\n\t */\n\n\t*widthPtr = maxX - *xPtr;\n    } else {\n\tCharChunkMeasureChars(chunkPtr, NULL, 0, byteIndex, byteIndex+1,\n\t\t*xPtr, -1, 0, widthPtr);\n\tif (*widthPtr > maxX) {\n\t    *widthPtr = maxX - *xPtr;\n\t} else {\n\t    *widthPtr -= *xPtr;\n\t}\n    }\n    *yPtr = y + baseline - chunkPtr->minAscent;\n    *heightPtr = chunkPtr->minAscent + chunkPtr->minDescent;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AdjustForTab --\n *\n *\tThis function is called to move a series of chunks right in order to\n *\talign them with a tab stop.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe width of chunkPtr gets adjusted so that it absorbs the extra space\n *\tdue to the tab. The x locations in all the chunks after chunkPtr are\n *\tadjusted rightward to align with the tab stop given by tabArrayPtr and\n *\tindex.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAdjustForTab(\n    TkText *textPtr,\t\t/* Information about the text widget as a\n\t\t\t\t * whole. */\n    TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply\n\t\t\t\t * to this line. May be NULL to indicate\n\t\t\t\t * default tabbing (every 8 chars). */\n    int index,\t\t\t/* Index of current tab stop. */\n    TkTextDispChunk *chunkPtr)\t/* Chunk whose last character is the tab; the\n\t\t\t\t * following chunks contain information to be\n\t\t\t\t * shifted right. */\n{\n    int x, desired, delta, width;\n    bool gotDigit;\n    Tcl_Size i, decimal;\n    TkTextDispChunk *chunkPtr2, *decimalChunkPtr;\n    CharInfo *ciPtr;\n    int tabX, spaceWidth;\n    const char *p;\n    TkTextTabAlign alignment;\n\n    if (chunkPtr->nextPtr == NULL) {\n\t/*\n\t * Nothing after the actual tab; just return.\n\t */\n\n\treturn;\n    }\n\n    x = chunkPtr->nextPtr->x;\n\n    /*\n     * If no tab information has been given, assuming tab stops are at 8\n     * average-sized characters. Still ensure we respect the tabular versus\n     * wordprocessor tab style.\n     */\n\n    if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {\n\t/*\n\t * No tab information has been given, so use the default\n\t * interpretation of tabs.\n\t */\n\n\tif (textPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR) {\n\t    int tabWidth = Tk_TextWidth(textPtr->tkfont, \"0\", 1) * 8;\n\t    if (tabWidth == 0) {\n\t\ttabWidth = 1;\n\t    }\n\n\t    desired = tabWidth * (index + 1);\n\t} else {\n\t    desired = NextTabStop(textPtr->tkfont, x, 0);\n\t}\n\n\tgoto update;\n    }\n\n    if (index < tabArrayPtr->numTabs) {\n\talignment = tabArrayPtr->tabs[index].alignment;\n\ttabX = tabArrayPtr->tabs[index].location;\n    } else {\n\t/*\n\t * Ran out of tab stops; compute a tab position by extrapolating from\n\t * the last two tab positions.\n\t */\n\n\ttabX = (int) (tabArrayPtr->lastTab +\n\t\t(index + 1 - tabArrayPtr->numTabs)*tabArrayPtr->tabIncrement +\n\t\t0.5);\n\talignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment;\n    }\n\n    if (alignment == LEFT) {\n\tdesired = tabX;\n\tgoto update;\n    }\n\n    if ((alignment == CENTER) || (alignment == RIGHT)) {\n\t/*\n\t * Compute the width of all the information in the tab group, then use\n\t * it to pick a desired location.\n\t */\n\n\twidth = 0;\n\tfor (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;\n\t\tchunkPtr2 = chunkPtr2->nextPtr) {\n\t    width += chunkPtr2->width;\n\t}\n\tif (alignment == CENTER) {\n\t    desired = tabX - width/2;\n\t} else {\n\t    desired = tabX - width;\n\t}\n\tgoto update;\n    }\n\n    /*\n     * Must be numeric alignment. Search through the text to be tabbed,\n     * looking for the last , or . before the first character that isn't a\n     * number, comma, period, or sign.\n     */\n\n    decimalChunkPtr = NULL;\n    decimal = 0;\n    gotDigit = false;\n    for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;\n\t    chunkPtr2 = chunkPtr2->nextPtr) {\n\tif (chunkPtr2->displayProc != CharDisplayProc) {\n\t    continue;\n\t}\n\tciPtr = (CharInfo *)chunkPtr2->clientData;\n\tfor (p = ciPtr->chars, i = 0; i < ciPtr->numBytes; p++, i++) {\n\t    if (isdigit(UCHAR(*p))) {\n\t\tgotDigit = true;\n\t    } else if ((*p == '.') || (*p == ',')) {\n\t\tdecimal = p-ciPtr->chars;\n\t\tdecimalChunkPtr = chunkPtr2;\n\t    } else if (gotDigit) {\n\t\tif (decimalChunkPtr == NULL) {\n\t\t    decimal = p-ciPtr->chars;\n\t\t    decimalChunkPtr = chunkPtr2;\n\t\t}\n\t\tgoto endOfNumber;\n\t    }\n\t}\n    }\n\n  endOfNumber:\n    if (decimalChunkPtr != NULL) {\n\tint curX;\n\n\tciPtr = (CharInfo *)decimalChunkPtr->clientData;\n\tCharChunkMeasureChars(decimalChunkPtr, NULL, 0, 0, decimal,\n\t\tdecimalChunkPtr->x, -1, 0, &curX);\n\tdesired = tabX - (curX - x);\n\tgoto update;\n    }\n\n    /*\n     * There wasn't a decimal point. Right justify the text.\n     */\n\n    width = 0;\n    for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;\n\t    chunkPtr2 = chunkPtr2->nextPtr) {\n\twidth += chunkPtr2->width;\n    }\n    desired = tabX - width;\n\n    /*\n     * Shift all of the chunks to the right so that the left edge is at the\n     * desired location, then expand the chunk containing the tab. Be sure\n     * that the tab occupies at least the width of a space character.\n     */\n\n  update:\n    delta = desired - x;\n    MeasureChars(textPtr->tkfont, \" \", 1, 0, 1, 0, -1, 0, &spaceWidth);\n    if (delta < spaceWidth) {\n\tdelta = spaceWidth;\n    }\n    for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;\n\t    chunkPtr2 = chunkPtr2->nextPtr) {\n\tchunkPtr2->x += delta;\n    }\n    chunkPtr->width += delta;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SizeOfTab --\n *\n *\tThis returns an estimate of the amount of white space that will be\n *\tconsumed by a tab.\n *\n * Results:\n *\tThe return value is the minimum number of pixels that will be occupied\n *\tby the next tab of tabArrayPtr, assuming that the current position on\n *\tthe line is x and the end of the line is maxX. The 'next tab' is\n *\tdetermined by a combination of the current position (x) which it must\n *\tbe equal to or beyond, and the tab count in indexPtr.\n *\n *\tFor numeric tabs, this is a conservative estimate. The return value is\n *\talways >= 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSizeOfTab(\n    TkText *textPtr,\t\t/* Information about the text widget as a\n\t\t\t\t * whole. */\n    TkTextTabStyle tabStyle,\t/* One of TK_TEXT_TABSTYLE_TABULAR\n\t\t\t\t * or TK_TEXT_TABSTYLE_WORDPROCESSOR. */\n    TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply\n\t\t\t\t * to this line. NULL means use default\n\t\t\t\t * tabbing (every 8 chars.) */\n    int *indexPtr,\t\t/* Contains index of previous tab stop, will\n\t\t\t\t * be updated to reflect the number of stops\n\t\t\t\t * used. */\n    int x,\t\t\t/* Current x-location in line. */\n    int maxX)\t\t\t/* X-location of pixel just past the right\n\t\t\t\t * edge of the line. */\n{\n    int tabX, result, index, spaceWidth, tabWidth;\n    TkTextTabAlign alignment;\n\n    index = *indexPtr;\n\n    if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {\n\t/*\n\t * We're using a default tab spacing of 8 characters.\n\t */\n\n\ttabWidth = Tk_TextWidth(textPtr->tkfont, \"0\", 1) * 8;\n\tif (tabWidth == 0) {\n\t    tabWidth = 1;\n\t}\n    } else {\n\ttabWidth = 0;\t\t/* Avoid compiler error. */\n    }\n\n    do {\n\t/*\n\t * We were given the count before this tab, so increment it first.\n\t */\n\n\tindex++;\n\n\tif ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) {\n\t    /*\n\t     * We're using a default tab spacing calculated above.\n\t     */\n\n\t    tabX = tabWidth * (index + 1);\n\t    alignment = LEFT;\n\t} else if (index < tabArrayPtr->numTabs) {\n\t    tabX = tabArrayPtr->tabs[index].location;\n\t    alignment = tabArrayPtr->tabs[index].alignment;\n\t} else {\n\t    /*\n\t     * Ran out of tab stops; compute a tab position by extrapolating.\n\t     */\n\n\t    tabX = (int) (tabArrayPtr->lastTab\n\t\t    + (index + 1 - tabArrayPtr->numTabs)\n\t\t    * tabArrayPtr->tabIncrement + 0.5);\n\t    alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment;\n\t}\n\n\t/*\n\t * If this tab stop is before the current x position, then we have two\n\t * cases:\n\t *\n\t * With 'wordprocessor' style tabs, we must obviously continue until\n\t * we reach the text tab stop.\n\t *\n\t * With 'tabular' style tabs, we always use the index'th tab stop.\n\t */\n    } while (tabX <= x && (tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR));\n\n    /*\n     * Inform our caller of how many tab stops we've used up.\n     */\n\n    *indexPtr = index;\n\n    if (alignment == CENTER) {\n\t/*\n\t * Be very careful in the arithmetic below, because maxX may be the\n\t * largest positive number: watch out for integer overflow.\n\t */\n\n\tif ((maxX-tabX) < (tabX - x)) {\n\t    result = (maxX - x) - 2*(maxX - tabX);\n\t} else {\n\t    result = 0;\n\t}\n\tgoto done;\n    }\n    if (alignment == RIGHT) {\n\tresult = 0;\n\tgoto done;\n    }\n\n    /*\n     * Note: this treats NUMERIC alignment the same as LEFT alignment, which\n     * is somewhat conservative. However, it's pretty tricky at this point to\n     * figure out exactly where the damn decimal point will be.\n     */\n\n    if (tabX > x) {\n\tresult = tabX - x;\n    } else {\n\tresult = 0;\n    }\n\n  done:\n    MeasureChars(textPtr->tkfont, \" \", 1, 0, 1, 0, -1, 0, &spaceWidth);\n    if (result < spaceWidth) {\n\tresult = spaceWidth;\n    }\n    return result;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * NextTabStop --\n *\n *\tGiven the current position, determine where the next default tab stop\n *\twould be located. This function is called when the current chunk in\n *\tthe text has no tabs defined and so the default tab spacing for the\n *\tfont should be used, provided we are using wordprocessor style tabs.\n *\n * Results:\n *\tThe location in pixels of the next tab stop.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nNextTabStop(\n    Tk_Font tkfont,\t\t/* Font in which chunk that contains tab stop\n\t\t\t\t * will be drawn. */\n    int x,\t\t\t/* X-position in pixels where last character\n\t\t\t\t * was drawn. The next tab stop occurs\n\t\t\t\t * somewhere after this location. */\n    int tabOrigin)\t\t/* The origin for tab stops. May be non-zero\n\t\t\t\t * if text has been scrolled. */\n{\n    int tabWidth, rem;\n\n    tabWidth = Tk_TextWidth(tkfont, \"0\", 1) * 8;\n    if (tabWidth == 0) {\n\ttabWidth = 1;\n    }\n\n    x += tabWidth;\n    rem = (x - tabOrigin) % tabWidth;\n    if (rem < 0) {\n\trem += tabWidth;\n    }\n    x -= rem;\n    return x;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * MeasureChars --\n *\n *\tDetermine the number of characters from the string that will fit in\n *\tthe given horizontal span. The measurement is done under the\n *\tassumption that Tk_DrawChars will be used to actually display the\n *\tcharacters.\n *\n *\tIf tabs are encountered in the string, they will be ignored (they\n *\tshould only occur as last character of the string anyway).\n *\n *\tIf a newline is encountered in the string, the line will be broken at\n *\tthat point.\n *\n * Results:\n *\tThe return value is the number of bytes from the range of start to end\n *\tin source that fit in the span given by startX and maxX. *nextXPtr is\n *\tfilled in with the x-coordinate at which the first character that\n *\tdidn't fit would be drawn, if it were to be drawn.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic Tcl_Size\nMeasureChars(\n    Tk_Font tkfont,\t\t/* Font in which to draw characters. */\n    const char *source,\t\t/* Characters to be displayed. Need not be\n\t\t\t\t * NULL-terminated. */\n    Tcl_Size maxBytes,\t\t/* Maximum # of bytes to consider from\n\t\t\t\t * source. */\n    Tcl_Size rangeStart, Tcl_Size rangeLength,\n\t\t\t\t/* Range of bytes to consider in source.*/\n    int startX,\t\t\t/* X-position at which first character will be\n\t\t\t\t * drawn. */\n    int maxX,\t\t\t/* Don't consider any character that would\n\t\t\t\t * cross this x-position. */\n    int flags,\t\t\t/* Flags to pass to Tk_MeasureChars. */\n    int *nextXPtr)\t\t/* Return x-position of terminating character\n\t\t\t\t * here. */\n{\n    int curX, width, ch;\n    const char *special, *end, *start;\n\n    ch = 0;\n    curX = startX;\n    start = source + rangeStart;\n    end = start + rangeLength;\n    special = start;\n    while (start < end) {\n\tif (start >= special) {\n\t    /*\n\t     * Find the next special character in the string.\n\t     */\n\n\t    for (special = start; special < end; special++) {\n\t\tch = *special;\n\t\tif ((ch == '\\t') || (ch == '\\n')) {\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Special points at the next special character (or the end of the\n\t * string). Process characters between start and special.\n\t */\n\n\tif ((maxX >= 0) && (curX >= maxX)) {\n\t    break;\n\t}\n#ifdef TK_DRAW_IN_CONTEXT\n\tstart += Tk_MeasureCharsInContext(tkfont, source, maxBytes,\n\t\tstart - source, special - start,\n\t\tmaxX >= 0 ? maxX - curX : -1, flags, &width);\n#else\n\t(void) maxBytes;\n\tstart += Tk_MeasureChars(tkfont, start, special - start,\n\t\tmaxX >= 0 ? maxX - curX : -1, flags, &width);\n#endif /* TK_DRAW_IN_CONTEXT */\n\tcurX += width;\n\tif (start < special) {\n\t    /*\n\t     * No more chars fit in line.\n\t     */\n\n\t    break;\n\t}\n\tif (special < end) {\n\t    if (ch != '\\t') {\n\t\tbreak;\n\t    }\n\t    start++;\n\t}\n    }\n\n    *nextXPtr = curX;\n    return start - (source+rangeStart);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TextGetScrollInfoObj --\n *\n *\tThis function is invoked to parse \"xview\" and \"yview\" scrolling\n *\tcommands for text widgets using the new scrolling command syntax\n *\t(\"moveto\" or \"scroll\" options). It extends the public\n *\tTk_GetScrollInfoObj function with the addition of \"pixels\" as a valid\n *\tunit alongside \"pages\" and \"units\". It is a shame the core API isn't\n *\tmore flexible in this regard.\n *\n * Results:\n *\tThe return value is either TKTEXT_SCROLL_MOVETO, TKTEXT_SCROLL_PAGES,\n *\tTKTEXT_SCROLL_UNITS, TKTEXT_SCROLL_PIXELS or TKTEXT_SCROLL_ERROR. This\n *\tindicates whether the command was successfully parsed and what form\n *\tthe command took. If TKTEXT_SCROLL_MOVETO, *dblPtr is filled in with\n *\tthe desired position; if TKTEXT_SCROLL_PAGES, TKTEXT_SCROLL_PIXELS or\n *\tTKTEXT_SCROLL_UNITS, *intPtr is filled in with the number of\n *\tpages/pixels/lines to move (may be negative); if TKTEXT_SCROLL_ERROR,\n *\tthe interp's result contains an error message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTextGetScrollInfoObj(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    TkText *textPtr,\t\t/* Information about the text widget. */\n    Tcl_Size objc,\t\t\t/* # arguments for command. */\n    Tcl_Obj *const objv[],\t/* Arguments for command. */\n    double *dblPtr,\t\t/* Filled in with argument \"moveto\" option, if\n\t\t\t\t * any. */\n    int *intPtr)\t\t/* Filled in with number of pages or lines or\n\t\t\t\t * pixels to scroll, if any. */\n{\n    static const char *const subcommands[] = {\n\t\"moveto\", \"scroll\", NULL\n    };\n    enum viewSubcmds {\n\tVIEW_MOVETO, VIEW_SCROLL\n    };\n    static const char *const units[] = {\n\t\"pages\", \"pixels\", \"units\", NULL\n    };\n    enum viewUnits {\n\tVIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS, VIEW_SCROLL_UNITS\n    };\n    int index;\n    double d;\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], subcommands,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TKTEXT_SCROLL_ERROR;\n    }\n\n    switch ((enum viewSubcmds) index) {\n    case VIEW_MOVETO:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"fraction\");\n\t    return TKTEXT_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {\n\t    return TKTEXT_SCROLL_ERROR;\n\t}\n\treturn TKTEXT_SCROLL_MOVETO;\n    case VIEW_SCROLL:\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"number pages|pixels|units\");\n\t    return TKTEXT_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[4], units,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TKTEXT_SCROLL_ERROR;\n\t}\n\tswitch ((enum viewUnits) index) {\n\tcase VIEW_SCROLL_PAGES:\n\t    if (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {\n\t\treturn TKTEXT_SCROLL_ERROR;\n\t    }\n\t    *intPtr = (d > 0) ? ceil(d) : floor(d);\n\t    if (dblPtr) {\n\t\t*dblPtr = d;\n\t    }\n\t    return TKTEXT_SCROLL_PAGES;\n\tcase VIEW_SCROLL_PIXELS:\n\t    if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[3],\n\t\t    intPtr) != TCL_OK) {\n\t\treturn TKTEXT_SCROLL_ERROR;\n\t    }\n\t    if (dblPtr) {\n\t\t*dblPtr = (double)*intPtr;\n\t    }\n\t    return TKTEXT_SCROLL_PIXELS;\n\tcase VIEW_SCROLL_UNITS:\n\t    if (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {\n\t\treturn TKTEXT_SCROLL_ERROR;\n\t    }\n\t    *intPtr = (d > 0) ? ceil(d) : floor(d);\n\t    if (dblPtr) {\n\t\t*dblPtr = d;\n\t    }\n\t    return TKTEXT_SCROLL_UNITS;\n\t}\n    }\n    Tcl_Panic(\"unexpected switch fallthrough\");\n    return TKTEXT_SCROLL_ERROR;\n}\n\f\n#ifdef TK_LAYOUT_WITH_BASE_CHUNKS\n/*\n *----------------------------------------------------------------------\n *\n * FinalizeBaseChunk --\n *\n *\tThis procedure makes sure that all the chunks of the stretch are\n *\tup-to-date. It is invoked when the LayoutProc has been called for all\n *\tchunks and the base chunk is stable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe CharInfo.chars of all dependent chunks point into\n *\tBaseCharInfo.baseChars for easy access (and compatibility).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFinalizeBaseChunk(\n    TkTextDispChunk *addChunkPtr)\n\t\t\t\t/* An additional chunk to add to the stretch,\n\t\t\t\t * even though it may not be in the linked\n\t\t\t\t * list yet. Used by the LayoutProc, otherwise\n\t\t\t\t * NULL. */\n{\n    const char *baseChars;\n    TkTextDispChunk *chunkPtr;\n    CharInfo *ciPtr;\n#ifdef TK_DRAW_IN_CONTEXT\n    int widthAdjust = 0;\n    int newwidth;\n#endif /* TK_DRAW_IN_CONTEXT */\n\n    if (baseCharChunkPtr == NULL) {\n\treturn;\n    }\n\n    baseChars = Tcl_DStringValue(\n\t    &((BaseCharInfo *) baseCharChunkPtr->clientData)->baseChars);\n\n    for (chunkPtr = baseCharChunkPtr; chunkPtr != NULL;\n\t    chunkPtr = chunkPtr->nextPtr) {\n#ifdef TK_DRAW_IN_CONTEXT\n\tchunkPtr->x += widthAdjust;\n#endif /* TK_DRAW_IN_CONTEXT */\n\n\tif (chunkPtr->displayProc != CharDisplayProc) {\n\t    continue;\n\t}\n\tciPtr = (CharInfo *)chunkPtr->clientData;\n\tif (ciPtr->baseChunkPtr != baseCharChunkPtr) {\n\t    break;\n\t}\n\tciPtr->chars = baseChars + ciPtr->baseOffset;\n\n#ifdef TK_DRAW_IN_CONTEXT\n\tnewwidth = 0;\n\tCharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, 0, -1, 0, &newwidth);\n\tif (newwidth < chunkPtr->width) {\n\t    widthAdjust += newwidth - chunkPtr->width;\n\t    chunkPtr->width = newwidth;\n\t}\n#endif /* TK_DRAW_IN_CONTEXT */\n    }\n\n    if (addChunkPtr != NULL) {\n\tciPtr = (CharInfo *)addChunkPtr->clientData;\n\tciPtr->chars = baseChars + ciPtr->baseOffset;\n\n#ifdef TK_DRAW_IN_CONTEXT\n\taddChunkPtr->x += widthAdjust;\n\tCharChunkMeasureChars(addChunkPtr, NULL, 0, 0, -1, 0, -1, 0,\n\t\t&addChunkPtr->width);\n#endif /* TK_DRAW_IN_CONTEXT */\n    }\n\n    baseCharChunkPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeBaseChunk --\n *\n *\tThis procedure makes sure that all the chunks of the stretch are\n *\tdisconnected from the base chunk and the base chunk specific data is\n *\tfreed. It is invoked from the UndisplayProc. The procedure doesn't\n *\tTcl_Free the base chunk clientData itself, that's up to the main\n *\tUndisplayProc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe CharInfo.chars of all dependent chunks are set to NULL. Memory\n *\tthat belongs specifically to the base chunk is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeBaseChunk(\n    TkTextDispChunk *baseChunkPtr)\n\t\t\t\t/* The base chunk of the stretch and head of\n\t\t\t\t * the linked list. */\n{\n    TkTextDispChunk *chunkPtr;\n    CharInfo *ciPtr;\n\n    if (baseCharChunkPtr == baseChunkPtr) {\n\tbaseCharChunkPtr = NULL;\n    }\n\n    for (chunkPtr=baseChunkPtr; chunkPtr!=NULL; chunkPtr=chunkPtr->nextPtr) {\n\tif (chunkPtr->undisplayProc != CharUndisplayProc) {\n\t    continue;\n\t}\n\tciPtr = (CharInfo *)chunkPtr->clientData;\n\tif (ciPtr->baseChunkPtr != baseChunkPtr) {\n\t    break;\n\t}\n\n\tciPtr->baseChunkPtr = NULL;\n\tciPtr->chars = NULL;\n    }\n\n    if (baseChunkPtr) {\n\tTcl_DStringFree(&((BaseCharInfo *) baseChunkPtr->clientData)->baseChars);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IsSameFGStyle --\n *\n *\tCompare the foreground attributes of two styles. Specifically must\n *\tconsider: foreground color, font, font style and font decorations,\n *\telide, \"offset\" and foreground stipple. Do *not* consider: background\n *\tcolor, border, relief or background stipple.\n *\n *\tIf we use Tk_DrawCharsInContext(), we also don't need to check\n *\tforeground color, font decorations, elide, offset and foreground\n *\tstipple, so all that is left is font (including font size and font\n *\tstyle) and \"offset\".\n *\n * Results:\n *\t1 if the two styles match, 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nIsSameFGStyle(\n    TextStyle *style1,\n    TextStyle *style2)\n{\n    StyleValues *sv1;\n    StyleValues *sv2;\n\n    if (style1 == style2) {\n\treturn 1;\n    }\n\n#ifndef TK_DRAW_IN_CONTEXT\n    if (\n#ifdef MAC_OSX_TK\n\t    !TkMacOSXCompareColors(style1->fgGC->foreground,\n\t\t    style2->fgGC->foreground)\n#else\n\t    style1->fgGC->foreground != style2->fgGC->foreground\n#endif\n\t    ) {\n\treturn 0;\n    }\n#endif /* !TK_DRAW_IN_CONTEXT */\n\n    sv1 = style1->sValuePtr;\n    sv2 = style2->sValuePtr;\n\n#ifdef TK_DRAW_IN_CONTEXT\n    return sv1->tkfont == sv2->tkfont && sv1->offset == sv2->offset;\n#else\n    return sv1->tkfont == sv2->tkfont\n\t    && sv1->underline == sv2->underline\n\t    && sv1->overstrike == sv2->overstrike\n\t    && sv1->elide == sv2->elide\n\t    && sv1->offset == sv2->offset\n\t    && sv1->fgStipple == sv2->fgStipple;\n#endif /* TK_DRAW_IN_CONTEXT */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemoveFromBaseChunk --\n *\n *\tThis procedure removes a chunk from the stretch as a result of\n *\tUndisplayProc. The chunk in question should be the last in a stretch.\n *\tThis happens during re-layouting of the break position.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe characters that belong to this chunk are removed from the base\n *\tchunk. It is assumed that LayoutProc and FinalizeBaseChunk are called\n *\tnext to repair any damage that this causes to the integrity of the\n *\tstretch and the other chunks. For that reason the base chunk is also\n *\tput into baseCharChunkPtr automatically, so that LayoutProc can resume\n *\tcorrectly.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemoveFromBaseChunk(\n    TkTextDispChunk *chunkPtr)\t/* The chunk to remove from the end of the\n\t\t\t\t * stretch. */\n{\n    CharInfo *ciPtr;\n    BaseCharInfo *bciPtr;\n\n    if (chunkPtr->displayProc != CharDisplayProc) {\n#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS\n\tfprintf(stderr,\"RemoveFromBaseChunk called with wrong chunk type\\n\");\n#endif\n\treturn;\n    }\n\n    /*\n     * Reinstitute this base chunk for re-layout.\n     */\n\n    ciPtr = (CharInfo *)chunkPtr->clientData;\n    baseCharChunkPtr = ciPtr->baseChunkPtr;\n\n    /*\n     * Remove the chunk data from the base chunk data.\n     */\n\n    bciPtr = (BaseCharInfo *)baseCharChunkPtr->clientData;\n\n#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS\n    if ((ciPtr->baseOffset + ciPtr->numBytes)\n\t    != Tcl_DStringLength(&bciPtr->baseChars)) {\n\tfprintf(stderr,\"RemoveFromBaseChunk called with wrong chunk \"\n\t\t\"(not last)\\n\");\n    }\n#endif\n\n    Tcl_DStringSetLength(&bciPtr->baseChars, ciPtr->baseOffset);\n\n    /*\n     * Invalidate the stored pixel width of the base chunk.\n     */\n\n    bciPtr->width = -1;\n}\n#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextImage.c",
    "content": "/*\n * tkImage.c --\n *\n *\tThis file contains code that allows images to be nested inside text\n *\twidgets. It also implements the \"image\" widget command for texts.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkPort.h\"\n#include \"tkText.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Macro that determines the size of an embedded image segment:\n */\n\n#define EI_SEG_SIZE \\\n\t(offsetof(TkTextSegment, body) + sizeof(TkTextEmbImage))\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic TkTextSegment *\tEmbImageCleanupProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic void\t\tEmbImageCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic void\t\tEmbImageBboxProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, Tcl_Size index, int y,\n\t\t\t    int lineHeight, int baseline, int *xPtr, int *yPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic int\t\tEmbImageConfigure(TkText *textPtr,\n\t\t\t    TkTextSegment *eiPtr, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tEmbImageDeleteProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\nstatic void\t\tEmbImageDisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, int x, int y,\n\t\t\t    int lineHeight, int baseline, Display *display,\n\t\t\t    Drawable dst, int screenY);\nstatic int\t\tEmbImageLayoutProc(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, TkTextSegment *segPtr,\n\t\t\t    Tcl_Size offset, int maxX, Tcl_Size maxChars,\n\t\t\t    int noCharsYet, TkWrapMode wrapMode,\n\t\t\t    TkTextDispChunk *chunkPtr);\nstatic void\t\tEmbImageProc(void *clientData, int x, int y,\n\t\t\t    int width, int height, int imageWidth,\n\t\t\t    int imageHeight);\n\n/*\n * The following structure declares the \"embedded image\" segment type.\n */\n\nconst Tk_SegType tkTextEmbImageType = {\n    \"image\",\t\t\t/* name */\n    0,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    EmbImageDeleteProc,\t\t/* deleteProc */\n    EmbImageCleanupProc,\t/* cleanupProc */\n    NULL,\t\t\t/* lineChangeProc */\n    EmbImageLayoutProc,\t\t/* layoutProc */\n    EmbImageCheckProc\t\t/* checkProc */\n};\n\n/*\n * Definitions for alignment values:\n */\n\nstatic const char *const alignStrings[] = {\n    \"baseline\", \"bottom\", \"center\", \"top\", NULL\n};\n\n/*\n * Information used for parsing image configuration options:\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_STRING_TABLE, \"-align\", NULL, NULL,\n\t\"center\", TCL_INDEX_NONE, offsetof(TkTextEmbImage, align),\n\tTK_OPTION_ENUM_VAR, alignStrings, 0},\n    {TK_OPTION_PIXELS, \"-padx\", NULL, NULL,\n\t\"0\", offsetof(TkTextEmbImage, padXObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", NULL, NULL,\n\t\"0\", offsetof(TkTextEmbImage, padYObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_STRING, \"-image\", NULL, NULL,\n\tNULL, offsetof(TkTextEmbImage, imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-name\", NULL, NULL,\n\tNULL, offsetof(TkTextEmbImage, imageNameObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextImageCmd --\n *\n *\tThis function implements the \"image\" widget command for text widgets.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result or error.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextImageCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"image\". */\n{\n    int idx;\n    TkTextSegment *eiPtr;\n    TkTextIndex index;\n    static const char *const optionStrings[] = {\n\t\"cget\", \"configure\", \"create\", \"names\", NULL\n    };\n    enum opts {\n\tCMD_CGET, CMD_CONF, CMD_CREATE, CMD_NAMES\n    };\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], optionStrings,\n\t    sizeof(char *), \"option\", 0, &idx) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch ((enum opts) idx) {\n    case CMD_CGET: {\n\tTcl_Obj *objPtr;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index option\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\teiPtr = TkTextIndexToSeg(&index, NULL);\n\tif (eiPtr->typePtr != &tkTextEmbImageType) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no embedded image at index \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_IMAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tobjPtr = Tk_GetOptionValue(interp, &eiPtr->body.ei,\n\t\teiPtr->body.ei.optionTable, objv[4], textPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    return TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    return TCL_OK;\n\t}\n    }\n    case CMD_CONF:\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\teiPtr = TkTextIndexToSeg(&index, NULL);\n\tif (eiPtr->typePtr != &tkTextEmbImageType) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no embedded image at index \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_IMAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (objc <= 5) {\n\t    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp,\n\t\t    &eiPtr->body.ei, eiPtr->body.ei.optionTable,\n\t\t    (objc == 5) ? objv[4] : NULL, textPtr->tkwin);\n\n\t    if (objPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    } else {\n\t\tTcl_SetObjResult(interp, objPtr);\n\t\treturn TCL_OK;\n\t    }\n\t} else {\n\t    TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);\n\n\t    /*\n\t     * It's probably not true that all window configuration can change\n\t     * the line height, so we could be more efficient here and only\n\t     * call this when necessary.\n\t     */\n\n\t    TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,\n\t\t    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n\t    return EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4);\n\t}\n    case CMD_CREATE: {\n\tTcl_Size lineIndex;\n\n\t/*\n\t * Add a new image. Find where to put the new image, and mark that\n\t * position for redisplay.\n\t */\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Don't allow insertions on the last (dummy) line of the text.\n\t */\n\n\tlineIndex = TkBTreeLinesTo(textPtr, index.linePtr);\n\tif (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree,\n\t\ttextPtr)) {\n\t    lineIndex--;\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t    lineIndex, 1000000, &index);\n\t}\n\n\t/*\n\t * Create the new image segment and initialize it.\n\t */\n\n\teiPtr = (TkTextSegment *)Tcl_Alloc(EI_SEG_SIZE);\n\teiPtr->typePtr = &tkTextEmbImageType;\n\teiPtr->size = 1;\n\teiPtr->body.ei.sharedTextPtr = textPtr->sharedTextPtr;\n\teiPtr->body.ei.linePtr = NULL;\n\teiPtr->body.ei.imageNameObj = NULL;\n\teiPtr->body.ei.imageObj = NULL;\n\teiPtr->body.ei.name = NULL;\n\teiPtr->body.ei.image = NULL;\n\teiPtr->body.ei.align = TK_ALIGN_CENTER;\n\teiPtr->body.ei.padXObj = eiPtr->body.ei.padYObj = NULL;\n\teiPtr->body.ei.chunkCount = 0;\n\teiPtr->body.ei.optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n\t/*\n\t * Link the segment into the text widget, then configure it (delete it\n\t * again if the configuration fails).\n\t */\n\n\tTkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);\n\tTkBTreeLinkSegment(eiPtr, &index);\n\tif (EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4) != TCL_OK) {\n\t    TkTextIndex index2;\n\n\t    TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);\n\t    TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index, &index2);\n\t    return TCL_ERROR;\n\t}\n\tTkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,\n\t\tindex.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n\treturn TCL_OK;\n    }\n    case CMD_NAMES: {\n\tTcl_HashSearch search;\n\tTcl_HashEntry *hPtr;\n\tTcl_Obj *resultObj;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tfor (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable,\n\t\t&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),\n\t\t    -1));\n\t}\n\tif (resultObj == NULL) {\n\t    return TCL_ERROR;\n\t} else {\n\t    Tcl_SetObjResult(interp, resultObj);\n\t    return TCL_OK;\n\t}\n    }\n    default:\n\tTcl_Panic(\"unexpected switch fallthrough\");\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageConfigure --\n *\n *\tThis function is called to handle configuration options for an\n *\tembedded image, using an objc/objv list.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message..\n *\n * Side effects:\n *\tConfiguration information for the embedded image changes, such as\n *\talignment, or name of the image.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbImageConfigure(\n    TkText *textPtr,\t\t/* Information about text widget that contains\n\t\t\t\t * embedded image. */\n    TkTextSegment *eiPtr,\t/* Embedded image to be configured. */\n    Tcl_Size objc,\t\t\t/* Number of strings in objv. */\n    Tcl_Obj *const objv[])\t/* Array of strings describing configuration\n\t\t\t\t * options. */\n{\n    Tk_Image image;\n    Tcl_DString newName;\n    Tcl_HashEntry *hPtr;\n    char *name;\n\tsize_t length;\n    int dummy;\n\n    if (Tk_SetOptions(textPtr->interp, &eiPtr->body.ei,\n\t    eiPtr->body.ei.optionTable,\n\t    objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Create the image. Save the old image around and don't free it until\n     * after the new one is allocated. This keeps the reference count from\n     * going to zero so the image doesn't have to be recreated if it hasn't\n     * changed.\n     */\n\n    if (eiPtr->body.ei.imageObj != NULL) {\n\timage = Tk_GetImage(textPtr->interp, textPtr->tkwin,\n\t\tTcl_GetString(eiPtr->body.ei.imageObj), EmbImageProc, eiPtr);\n\tif (image == NULL) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\timage = NULL;\n    }\n    if (eiPtr->body.ei.image != NULL) {\n\tTk_FreeImage(eiPtr->body.ei.image);\n    }\n    eiPtr->body.ei.image = image;\n\n    if (eiPtr->body.ei.name != NULL) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Find a unique name for this image. Use imageName (or imageString) if\n     * available, otherwise tack on a #nn and use it. If a name is already\n     * associated with this image, delete the name.\n     */\n\n    if (eiPtr->body.ei.imageNameObj) {\n\tname = Tcl_GetString(eiPtr->body.ei.imageNameObj);\n    } else if (eiPtr->body.ei.imageObj) {\n\tname = Tcl_GetString(eiPtr->body.ei.imageObj);\n    } else {\n\tTcl_SetObjResult(textPtr->interp, Tcl_NewStringObj(\n\t\t\"Either a \\\"-name\\\" or a \\\"-image\\\" argument must be\"\n\t\t\" provided to the \\\"image create\\\" subcommand\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(textPtr->interp, \"TK\", \"TEXT\", \"IMAGE_CREATE_USAGE\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_DStringInit(&newName);\n    while (Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name)) {\n\tchar buf[4 + TCL_INTEGER_SPACE];\n\tsnprintf(buf, sizeof(buf), \"#%d\", ++textPtr->sharedTextPtr->imageCount);\n\tTcl_DStringSetLength(&newName, 0);\n\tTcl_DStringAppend(&newName, name, TCL_INDEX_NONE);\n\tTcl_DStringAppend(&newName, buf, TCL_INDEX_NONE);\n\tname = Tcl_DStringValue(&newName);\n    }\n    length = strlen(name);\n\n    hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->imageTable, name,\n\t    &dummy);\n    Tcl_SetHashValue(hPtr, eiPtr);\n    eiPtr->body.ei.name = (char *)Tcl_Alloc(length + 1);\n    memcpy(eiPtr->body.ei.name, name, length + 1);\n    Tcl_SetObjResult(textPtr->interp, Tcl_NewStringObj(name, TCL_INDEX_NONE));\n    Tcl_DStringFree(&newName);\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageDeleteProc --\n *\n *\tThis function is invoked by the text B-tree code whenever an embedded\n *\timage lies in a range of characters being deleted.\n *\n * Results:\n *\tReturns 0 to indicate that the deletion has been accepted.\n *\n * Side effects:\n *\tThe embedded image is deleted, if it exists, and any resources\n *\tassociated with it are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbImageDeleteProc(\n    TkTextSegment *eiPtr,\t/* Segment being deleted. */\n    TCL_UNUSED(TkTextLine *),\t/* Line containing segment. */\n    TCL_UNUSED(int))\t\t/* Non-zero means the entire tree is being\n\t\t\t\t * deleted, so everything must get cleaned\n\t\t\t\t * up. */\n{\n    Tcl_HashEntry *hPtr;\n\n    if (eiPtr->body.ei.image != NULL) {\n\thPtr = Tcl_FindHashEntry(&eiPtr->body.ei.sharedTextPtr->imageTable,\n\t\teiPtr->body.ei.name);\n\tif (hPtr != NULL) {\n\t    /*\n\t     * (It's possible for there to be no hash table entry for this\n\t     * image, if an error occurred while creating the image segment\n\t     * but before the image got added to the table)\n\t     */\n\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n\tTk_FreeImage(eiPtr->body.ei.image);\n    }\n\n    /*\n     * No need to supply a tkwin argument, since we have no window-specific\n     * options.\n     */\n\n    Tk_FreeConfigOptions(&eiPtr->body.ei, eiPtr->body.ei.optionTable,\n\t    NULL);\n    if (eiPtr->body.ei.name) {\n\tTcl_Free(eiPtr->body.ei.name);\n    }\n    Tcl_Free(eiPtr);\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageCleanupProc --\n *\n *\tThis function is invoked by the B-tree code whenever a segment\n *\tcontaining an embedded image is moved from one line to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe linePtr field of the segment gets updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nEmbImageCleanupProc(\n    TkTextSegment *eiPtr,\t/* Mark segment that's being moved. */\n    TkTextLine *linePtr)\t/* Line that now contains segment. */\n{\n    eiPtr->body.ei.linePtr = linePtr;\n    return eiPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageLayoutProc --\n *\n *\tThis function is the \"layoutProc\" for embedded image segments.\n *\n * Results:\n *\t1 is returned to indicate that the segment should be displayed. The\n *\tchunkPtr structure is filled in.\n *\n * Side effects:\n *\tNone, except for filling in chunkPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbImageLayoutProc(\n    TkText *textPtr,\t\t/* Text widget being layed out. */\n    TCL_UNUSED(TkTextIndex *),\t/* Identifies first character in chunk. */\n    TkTextSegment *eiPtr,\t/* Segment corresponding to indexPtr. */\n    Tcl_Size offset,\t\t\t/* Offset within segPtr corresponding to\n\t\t\t\t * indexPtr (always 0). */\n    int maxX,\t\t\t/* Chunk must not occupy pixels at this\n\t\t\t\t * position or higher. */\n    TCL_UNUSED(Tcl_Size),\t/* Chunk must not include more than this many\n\t\t\t\t * characters. */\n    int noCharsYet,\t\t/* Non-zero means no characters have been\n\t\t\t\t * assigned to this line yet. */\n    TCL_UNUSED(TkWrapMode),\t/* Wrap mode to use for line:\n\t\t\t\t * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or\n\t\t\t\t * TEXT_WRAPMODE_WORD. */\n    TkTextDispChunk *chunkPtr)\n\t\t\t\t/* Structure to fill in with information about\n\t\t\t\t * this chunk. The x field has already been\n\t\t\t\t * set by the caller. */\n{\n    int width, height;\n    int padX = 0, padY = 0;\n\n    if (offset != 0) {\n\tTcl_Panic(\"Non-zero offset in EmbImageLayoutProc\");\n    }\n\n    if (eiPtr->body.ei.padXObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, eiPtr->body.ei.padXObj, &padX);\n    }\n    if (eiPtr->body.ei.padYObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, eiPtr->body.ei.padYObj, &padY);\n    }\n    /*\n     * See if there's room for this image on this line.\n     */\n\n    if (eiPtr->body.ei.image == NULL) {\n\twidth = 0;\n\theight = 0;\n    } else {\n\tTk_SizeOfImage(eiPtr->body.ei.image, &width, &height);\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    }\n    if ((width > (maxX - chunkPtr->x))\n\t    && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {\n\treturn 0;\n    }\n\n    /*\n     * Fill in the chunk structure.\n     */\n\n    chunkPtr->displayProc = EmbImageDisplayProc;\n    chunkPtr->undisplayProc = NULL;\n    chunkPtr->measureProc = NULL;\n    chunkPtr->bboxProc = EmbImageBboxProc;\n    chunkPtr->numBytes = 1;\n    if (eiPtr->body.ei.align == TK_ALIGN_BASELINE) {\n\tchunkPtr->minAscent = height - padY;\n\tchunkPtr->minDescent = padY;\n\tchunkPtr->minHeight = 0;\n    } else {\n\tchunkPtr->minAscent = 0;\n\tchunkPtr->minDescent = 0;\n\tchunkPtr->minHeight = height;\n    }\n    chunkPtr->width = width;\n    chunkPtr->breakIndex = -1;\n    chunkPtr->breakIndex = 1;\n    chunkPtr->clientData = eiPtr;\n    eiPtr->body.ei.chunkCount += 1;\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageCheckProc --\n *\n *\tThis function is invoked by the B-tree code to perform consistency\n *\tchecks on embedded images.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe function panics if it detects anything wrong with the embedded\n *\timage.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbImageCheckProc(\n    TkTextSegment *eiPtr,\t/* Segment to check. */\n    TCL_UNUSED(TkTextLine *))\t/* Line containing segment. */\n{\n    if (eiPtr->nextPtr == NULL) {\n\tTcl_Panic(\"EmbImageCheckProc: embedded image is last segment in line\");\n    }\n    if (eiPtr->size != 1) {\n\tTcl_Panic(\"EmbImageCheckProc: embedded image has size %\" TCL_Z_MODIFIER \"d\",\n\t\teiPtr->size);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageDisplayProc --\n *\n *\tThis function is invoked by the text displaying code when it is time\n *\tto actually draw an embedded image chunk on the screen.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe embedded image gets moved to the correct location and drawn onto\n *\tthe display.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbImageDisplayProc(\n    TkText *textPtr,\n    TkTextDispChunk *chunkPtr,\t/* Chunk that is to be drawn. */\n    int x,\t\t\t/* X-position in dst at which to draw this\n\t\t\t\t * chunk (differs from the x-position in the\n\t\t\t\t * chunk because of scrolling). */\n    int y,\t\t\t/* Top of rectangular bounding box for line:\n\t\t\t\t * tells where to draw this chunk in dst\n\t\t\t\t * (x-position is in the chunk itself). */\n    int lineHeight,\t\t/* Total height of line. */\n    int baseline,\t\t/* Offset of baseline from y. */\n    TCL_UNUSED(Display *),\t/* Display to use for drawing. */\n    Drawable dst,\t\t/* Pixmap or window in which to draw */\n    TCL_UNUSED(int))\t/* Y-coordinate in text window that\n\t\t\t\t * corresponds to y. */\n{\n    TkTextSegment *eiPtr = (TkTextSegment *)chunkPtr->clientData;\n    int lineX, imageX, imageY, width, height;\n    Tk_Image image;\n\n    image = eiPtr->body.ei.image;\n    if (image == NULL) {\n\treturn;\n    }\n    if ((x + chunkPtr->width) <= 0) {\n\treturn;\n    }\n\n    /*\n     * Compute the image's location and size in the text widget, taking into\n     * account the align value for the image.\n     */\n\n    EmbImageBboxProc(textPtr, chunkPtr, 0, y, lineHeight, baseline, &lineX,\n\t    &imageY, &width, &height);\n    imageX = lineX - chunkPtr->x + x;\n\n    Tk_RedrawImage(image, 0, 0, width, height, dst, imageX, imageY);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageBboxProc --\n *\n *\tThis function is called to compute the bounding box of the area\n *\toccupied by an embedded image.\n *\n * Results:\n *\tThere is no return value. *xPtr and *yPtr are filled in with the\n *\tcoordinates of the upper left corner of the image, and *widthPtr and\n *\t*heightPtr are filled in with the dimensions of the image in pixels.\n *\tNote: not all of the returned bbox is necessarily visible on the\n *\tscreen (the rightmost part might be off-screen to the right, and the\n *\tbottommost part might be off-screen to the bottom).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbImageBboxProc(\n    TkText *textPtr,\n    TkTextDispChunk *chunkPtr,\t/* Chunk containing desired char. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Index of desired character within the\n\t\t\t\t * chunk. */\n    int y,\t\t\t/* Topmost pixel in area allocated for this\n\t\t\t\t * line. */\n    int lineHeight,\t\t/* Total height of line. */\n    int baseline,\t\t/* Location of line's baseline, in pixels\n\t\t\t\t * measured down from y. */\n    int *xPtr, int *yPtr,\t/* Gets filled in with coords of character's\n\t\t\t\t * upper-left pixel. */\n    int *widthPtr,\t\t/* Gets filled in with width of image, in\n\t\t\t\t * pixels. */\n    int *heightPtr)\t\t/* Gets filled in with height of image, in\n\t\t\t\t * pixels. */\n{\n    TkTextSegment *eiPtr = (TkTextSegment *)chunkPtr->clientData;\n    Tk_Image image;\n    int padX = 0, padY = 0;\n\n    image = eiPtr->body.ei.image;\n    if (image != NULL) {\n\tTk_SizeOfImage(image, widthPtr, heightPtr);\n    } else {\n\t*widthPtr = 0;\n\t*heightPtr = 0;\n    }\n\n    if (eiPtr->body.ei.padXObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, eiPtr->body.ei.padXObj, &padX);\n    }\n    if (eiPtr->body.ei.padYObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, eiPtr->body.ei.padYObj, &padY);\n    }\n    *xPtr = chunkPtr->x + padX;\n\n    switch (eiPtr->body.ei.align) {\n    case TK_ALIGN_BOTTOM:\n\t*yPtr = y + (lineHeight - *heightPtr - padY);\n\tbreak;\n    case TK_ALIGN_CENTER:\n\t*yPtr = y + (lineHeight - *heightPtr)/2;\n\tbreak;\n    case TK_ALIGN_TOP:\n\t*yPtr = y + padY;\n\tbreak;\n    case TK_ALIGN_BASELINE:\n\t*yPtr = y + (baseline - *heightPtr);\n\tbreak;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextImageIndex --\n *\n *\tGiven the name of an embedded image within a text widget, returns an\n *\tindex corresponding to the image's position in the text.\n *\n * Results:\n *\tThe return value is TCL_OK if there is an embedded image by the given\n *\tname in the text widget, TCL_ERROR otherwise. If the image exists,\n *\t*indexPtr is filled in with its index.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextImageIndex(\n    TkText *textPtr,\t\t/* Text widget containing image. */\n    const char *name,\t\t/* Name of image. */\n    TkTextIndex *indexPtr)\t/* Index information gets stored here. */\n{\n    Tcl_HashEntry *hPtr;\n    TkTextSegment *eiPtr;\n\n    if (textPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name);\n    if (hPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n    eiPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n    indexPtr->tree = textPtr->sharedTextPtr->tree;\n    indexPtr->linePtr = eiPtr->body.ei.linePtr;\n    indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);\n\n    /*\n     * If indexPtr refers to somewhere outside the -startline/-endline\n     * range limits of the widget, error out since the image indeed is not\n     * reachable from this text widget (it may be reachable from a peer).\n     */\n\n    if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, true) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbImageProc --\n *\n *\tThis function is called by the image code whenever an image or its\n *\tcontents changes.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image will be redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbImageProc(\n    void *clientData,\t/* Pointer to widget record. */\n    TCL_UNUSED(int),\t\t/* Upper left pixel (within image) that must\n\t\t\t\t * be redisplayed. */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\t/* Dimensions of area to redisplay (may be\n\t\t\t\t * <= 0). */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),/* New dimensions of image. */\n    TCL_UNUSED(int))\n\n{\n    TkTextSegment *eiPtr = (TkTextSegment *)clientData;\n    TkTextIndex index;\n\n    index.tree = eiPtr->body.ei.sharedTextPtr->tree;\n    index.linePtr = eiPtr->body.ei.linePtr;\n    index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);\n    TkTextChanged(eiPtr->body.ei.sharedTextPtr, NULL, &index, &index);\n\n    /*\n     * It's probably not true that all image changes can change the line\n     * height, so we could be more efficient here and only call this when\n     * necessary.\n     */\n\n    TkTextInvalidateLineMetrics(eiPtr->body.ei.sharedTextPtr, NULL,\n\t    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextIndex.c",
    "content": "/*\n * tkTextIndex.c --\n *\n *\tThis module provides functions that manipulate indices for text\n *\twidgets.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkText.h\"\n#include \"default.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Index to use to select last character in line (very large integer):\n */\n\n#define LAST_CHAR 1000000\n\n/*\n * Modifiers for index parsing: 'display', 'any' or nothing.\n */\n\ntypedef enum {\n    TKINDEX_NONE,\n    TKINDEX_DISPLAY,\n    TKINDEX_ANY\n} indexModifier;\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic const char *\tForwBack(TkText *textPtr, const char *string,\n\t\t\t    TkTextIndex *indexPtr);\nstatic const char *\tStartEnd(TkText *textPtr, const char *string,\n\t\t\t    TkTextIndex *indexPtr);\nstatic int\t\tGetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr,\n\t\t\t    TkText *textPtr, const char *string,\n\t\t\t    TkTextIndex *indexPtr, int *canCachePtr);\nstatic Tcl_Size\t\tIndexCountBytesOrdered(const TkText *textPtr,\n\t\t\t    const TkTextIndex *indexPtr1,\n\t\t\t    const TkTextIndex *indexPtr2);\n\n/*\n * The \"textindex\" Tcl_Obj definition:\n */\n\nstatic void\t\tDupTextIndexInternalRep(Tcl_Obj *srcPtr,\n\t\t\t    Tcl_Obj *copyPtr);\nstatic void\t\tFreeTextIndexInternalRep(Tcl_Obj *listPtr);\nstatic void\t\tUpdateStringOfTextIndex(Tcl_Obj *objPtr);\n\n/*\n * Accessor macros for the \"textindex\" type.\n */\n\n#define GET_TEXTINDEX(objPtr) \\\n\t((TkTextIndex *) (objPtr)->internalRep.twoPtrValue.ptr1)\n#define GET_INDEXEPOCH(objPtr) \\\n\t(PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2))\n#define SET_TEXTINDEX(objPtr, indexPtr) \\\n\t((objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(indexPtr))\n#define SET_INDEXEPOCH(objPtr, epoch) \\\n\t((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (size_t) (epoch))\n\f\n/*\n * Define the 'textindex' object type, which Tk uses to represent indices in\n * text widgets internally.\n */\n\nconst Tcl_ObjType tkTextIndexType = {\n    \"textindex\",\t\t/* name */\n    FreeTextIndexInternalRep,\t/* freeIntRepProc */\n    DupTextIndexInternalRep,\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\nstatic void\nFreeTextIndexInternalRep(\n    Tcl_Obj *indexObjPtr)\t/* TextIndex object with internal rep to\n\t\t\t\t * free. */\n{\n    TkTextIndex *indexPtr = GET_TEXTINDEX(indexObjPtr);\n\n    if (indexPtr->textPtr != NULL) {\n\tif (indexPtr->textPtr->refCount-- <= 1) {\n\t    /*\n\t     * The text widget has been deleted and we need to free it now.\n\t     */\n\n\t    Tcl_Free(indexPtr->textPtr);\n\t}\n    }\n    Tcl_Free(indexPtr);\n    indexObjPtr->typePtr = NULL;\n}\n\nstatic void\nDupTextIndexInternalRep(\n    Tcl_Obj *srcPtr,\t\t/* TextIndex obj with internal rep to copy. */\n    Tcl_Obj *copyPtr)\t\t/* TextIndex obj with internal rep to set. */\n{\n    Tcl_Size epoch;\n    TkTextIndex *dupIndexPtr, *indexPtr;\n\n    dupIndexPtr = (TkTextIndex *)Tcl_Alloc(sizeof(TkTextIndex));\n    indexPtr = GET_TEXTINDEX(srcPtr);\n    epoch = GET_INDEXEPOCH(srcPtr);\n\n    dupIndexPtr->tree = indexPtr->tree;\n    dupIndexPtr->linePtr = indexPtr->linePtr;\n    dupIndexPtr->byteIndex = indexPtr->byteIndex;\n    dupIndexPtr->textPtr = indexPtr->textPtr;\n    if (dupIndexPtr->textPtr != NULL) {\n\tdupIndexPtr->textPtr->refCount++;\n    }\n    SET_TEXTINDEX(copyPtr, dupIndexPtr);\n    SET_INDEXEPOCH(copyPtr, epoch);\n    copyPtr->typePtr = &tkTextIndexType;\n}\n\f\n/*\n * This will not be called except by TkTextNewIndexObj below. This is because\n * if a TkTextIndex is no longer valid, it is not possible to regenerate the\n * string representation.\n */\n\nstatic void\nUpdateStringOfTextIndex(\n    Tcl_Obj *objPtr)\n{\n    char buffer[TK_POS_CHARS];\n    size_t len;\n    const TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr);\n\n    len = TkTextPrintIndex(indexPtr->textPtr, indexPtr, buffer);\n\n    objPtr->bytes = (char *)Tcl_Alloc(len + 1);\n    strcpy(objPtr->bytes, buffer);\n    objPtr->length = len;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * MakeObjIndex --\n *\n *\tThis function generates a Tcl_Obj description of an index, suitable\n *\tfor reading in again later. If the 'textPtr' is NULL then we still\n *\tgenerate an index object, but it's internal description is deemed\n *\tnon-cacheable, and therefore effectively useless (apart from as a\n *\ttemporary memory storage). This is used for indices whose meaning is\n *\tvery temporary (like @0,0 or the name of a mark or tag). The mapping\n *\tfrom such strings/objects to actual TkTextIndex pointers is not stable\n *\tto minor text widget changes which we do not track (we track\n *\tinsertions and deletions).\n *\n * Results:\n *\tA pointer to an allocated TkTextIndex which will be freed\n *\tautomatically when the Tcl_Obj is used for other purposes.\n *\n * Side effects:\n *\tA small amount of memory is allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic TkTextIndex *\nMakeObjIndex(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Obj *objPtr,\t\t/* Object containing description of\n\t\t\t\t * position. */\n    const TkTextIndex *origPtr)\t/* Pointer to index. */\n{\n    TkTextIndex *indexPtr = (TkTextIndex *)Tcl_Alloc(sizeof(TkTextIndex));\n\n    indexPtr->tree = origPtr->tree;\n    indexPtr->linePtr = origPtr->linePtr;\n    indexPtr->byteIndex = origPtr->byteIndex;\n    SET_TEXTINDEX(objPtr, indexPtr);\n    objPtr->typePtr = &tkTextIndexType;\n    indexPtr->textPtr = textPtr;\n\n    if (textPtr != NULL) {\n\ttextPtr->refCount++;\n\tSET_INDEXEPOCH(objPtr, textPtr->sharedTextPtr->stateEpoch);\n    } else {\n\tSET_INDEXEPOCH(objPtr, 0);\n    }\n    return indexPtr;\n}\n\nconst TkTextIndex *\nTkTextGetIndexFromObj(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Obj *objPtr)\t\t/* Object containing description of\n\t\t\t\t * position. */\n{\n    TkTextIndex index;\n    TkTextIndex *indexPtr = NULL;\n    int cache;\n\n    if (objPtr->typePtr == &tkTextIndexType) {\n\tTcl_Size epoch;\n\n\tindexPtr = GET_TEXTINDEX(objPtr);\n\tepoch = GET_INDEXEPOCH(objPtr);\n\n\tif (epoch == textPtr->sharedTextPtr->stateEpoch) {\n\t    if (indexPtr->textPtr == textPtr) {\n\t\treturn indexPtr;\n\t    }\n\t}\n    }\n\n    /*\n     * The object is either not an index type or referred to a different text\n     * widget, or referred to the correct widget, but it is out of date (text\n     * has been added/deleted since).\n     */\n\n    if (GetIndex(interp, NULL, textPtr, Tcl_GetString(objPtr), &index,\n\t    &cache) != TCL_OK) {\n\treturn NULL;\n    }\n\n    if (objPtr->typePtr != NULL) {\n\tif (objPtr->bytes == NULL) {\n\t    objPtr->typePtr->updateStringProc(objPtr);\n\t}\n\tif (objPtr->typePtr->freeIntRepProc != NULL) {\n\t    objPtr->typePtr->freeIntRepProc(objPtr);\n\t}\n    }\n\n    return MakeObjIndex((cache ? textPtr : NULL), objPtr, &index);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextNewIndexObj --\n *\n *\tThis function generates a Tcl_Obj description of an index, suitable\n *\tfor reading in again later. The index generated is effectively stable\n *\tto all except insertion/deletion operations on the widget.\n *\n * Results:\n *\tA new Tcl_Obj with refCount zero.\n *\n * Side effects:\n *\tA small amount of memory is allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkTextNewIndexObj(\n    TkText *textPtr,\t\t/* Text widget for this index */\n    const TkTextIndex *indexPtr)/* Pointer to index. */\n{\n    Tcl_Obj *retVal;\n\n    retVal = Tcl_NewObj();\n    retVal->bytes = NULL;\n\n    /*\n     * Assumption that the above call returns an object with:\n     * retVal->typePtr == NULL\n     */\n\n    MakeObjIndex(textPtr, retVal, indexPtr);\n\n    /*\n     * Unfortunately, it isn't possible for us to regenerate the string\n     * representation so we have to create it here, while we can be sure the\n     * contents of the index are still valid.\n     */\n\n    UpdateStringOfTextIndex(retVal);\n    return retVal;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextMakePixelIndex --\n *\n *\tGiven a pixel index and a byte index, look things up in the B-tree and\n *\tfill in a TkTextIndex structure.\n *\n *\tThe valid input range for pixelIndex is from 0 to the number of pixels\n *\tin the widget-1. Anything outside that range will be rounded to the\n *\tclosest acceptable value.\n *\n * Results:\n *\n *\tThe structure at *indexPtr is filled in with information about the\n *\tcharacter at pixelIndex (or the closest existing character, if the\n *\tspecified one doesn't exist), and the number of excess pixels is\n *\treturned as a result. This means if the given pixel index is exactly\n *\tcorrect for the top-edge of the indexPtr, then zero will be returned,\n *\tand otherwise we will return the calculation 'desired pixelIndex' -\n *\t'actual pixel index of indexPtr'.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextMakePixelIndex(\n    TkText *textPtr,\t\t/* The Text Widget */\n    int pixelIndex,\t\t/* Pixel-index of desired line (0 means first\n\t\t\t\t * pixel of first line of text). */\n    TkTextIndex *indexPtr)\t/* Structure to fill in. */\n{\n    int pixelOffset = 0;\n\n    indexPtr->tree = textPtr->sharedTextPtr->tree;\n    indexPtr->textPtr = textPtr;\n\n    if (pixelIndex < 0) {\n\tpixelIndex = 0;\n    }\n    indexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree,\n\t    textPtr, pixelIndex, &pixelOffset);\n\n    /*\n     * 'pixelIndex' was too large, so we try again, just to find the last\n     * pixel in the window.\n     */\n\n    if (indexPtr->linePtr == NULL) {\n\tint lastMinusOne = TkBTreeNumPixels(textPtr->sharedTextPtr->tree,\n\t\ttextPtr)-1;\n\n\tindexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree,\n\t\ttextPtr, lastMinusOne, &pixelOffset);\n\tindexPtr->byteIndex = 0;\n\treturn pixelOffset;\n    }\n    indexPtr->byteIndex = 0;\n\n    if (pixelOffset <= 0) {\n\treturn 0;\n    }\n    return TkTextMeasureDown(textPtr, indexPtr, pixelOffset);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextMakeByteIndex --\n *\n *\tGiven a line index and a byte index, look things up in the B-tree and\n *\tfill in a TkTextIndex structure.\n *\n * Results:\n *\tThe structure at *indexPtr is filled in with information about the\n *\tcharacter at lineIndex and byteIndex (or the closest existing\n *\tcharacter, if the specified one doesn't exist), and indexPtr is\n *\treturned as result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTkTextIndex *\nTkTextMakeByteIndex(\n    TkTextBTree tree,\t/* Tree that lineIndex and byteIndex refer\n\t\t\t\t * to. */\n    const TkText *textPtr,\n    Tcl_Size lineIndex,\t\t/* Index of desired line (0 means first line\n\t\t\t\t * of text). */\n    Tcl_Size byteIndex,\t\t/* Byte index of desired character. */\n    TkTextIndex *indexPtr)\t/* Structure to fill in. */\n{\n    TkTextSegment *segPtr;\n    Tcl_Size index;\n    const char *p, *start;\n    Tcl_UniChar ch;\n\n    indexPtr->tree = tree;\n    if (lineIndex < 0) {\n\tlineIndex = 0;\n\tbyteIndex = 0;\n    }\n    if (byteIndex < 0) {\n\tbyteIndex = 0;\n    }\n    indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex);\n    if (indexPtr->linePtr == NULL) {\n\tindexPtr->linePtr = TkBTreeFindLine(tree, textPtr,\n\t\tTkBTreeNumLines(tree, textPtr));\n\tbyteIndex = 0;\n    }\n    if (byteIndex == 0) {\n\tindexPtr->byteIndex = byteIndex;\n\treturn indexPtr;\n    }\n\n    /*\n     * Verify that the index is within the range of the line and points to a\n     * valid character boundary.\n     */\n\n    index = 0;\n    for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Use the index of the last character in the line. Since the last\n\t     * character on the line is guaranteed to be a '\\n', we can back\n\t     * up a constant sizeof(char) bytes.\n\t     */\n\n\t    indexPtr->byteIndex = index - sizeof(char);\n\t    break;\n\t}\n\tif (index + segPtr->size > byteIndex) {\n\t    indexPtr->byteIndex = byteIndex;\n\t    if ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) {\n\t\t/*\n\t\t * Prevent UTF-8 character from being split up by ensuring\n\t\t * that byteIndex falls on a character boundary. If the index\n\t\t * falls in the middle of a UTF-8 character, it will be\n\t\t * adjusted to the end of that UTF-8 character.\n\t\t */\n\n\t\tstart = segPtr->body.chars + (byteIndex - index);\n\t\tp = Tcl_UtfPrev(start, segPtr->body.chars);\n\t\tp += Tcl_UtfToUniChar(p, &ch);\n\t\tindexPtr->byteIndex += p - start;\n\t    }\n\t    break;\n\t}\n\tindex += segPtr->size;\n    }\n    return indexPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextMakeCharIndex --\n *\n *\tGiven a line index and a character index, look things up in the B-tree\n *\tand fill in a TkTextIndex structure.\n *\n * Results:\n *\tThe structure at *indexPtr is filled in with information about the\n *\tcharacter at lineIndex and charIndex (or the closest existing\n *\tcharacter, if the specified one doesn't exist), and indexPtr is\n *\treturned as result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTkTextIndex *\nTkTextMakeCharIndex(\n    TkTextBTree tree,\t\t/* Tree that lineIndex and charIndex refer\n\t\t\t\t * to. */\n    TkText *textPtr,\n    Tcl_Size lineIndex,\t\t/* Index of desired line (0 means first line\n\t\t\t\t * of text). */\n    Tcl_Size charIndex,\t\t/* Index of desired character. */\n    TkTextIndex *indexPtr)\t/* Structure to fill in. */\n{\n    TkTextSegment *segPtr;\n    char *p, *start, *end;\n    Tcl_Size index, offset;\n    Tcl_UniChar ch = 0;\n\n    indexPtr->tree = tree;\n    if (lineIndex < 0) {\n\tlineIndex = 0;\n\tcharIndex = 0;\n    }\n    if (charIndex < 0) {\n\tcharIndex = 0;\n    }\n    indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex);\n    if (indexPtr->linePtr == NULL) {\n\tindexPtr->linePtr = TkBTreeFindLine(tree, textPtr,\n\t\tTkBTreeNumLines(tree, textPtr));\n\tcharIndex = 0;\n    }\n\n    /*\n     * Verify that the index is within the range of the line. If not, just use\n     * the index of the last character in the line.\n     */\n\n    index = 0;\n    for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Use the index of the last character in the line. Since the last\n\t     * character on the line is guaranteed to be a '\\n', we can back\n\t     * up a constant sizeof(char) bytes.\n\t     */\n\n\t    indexPtr->byteIndex = index - sizeof(char);\n\t    break;\n\t}\n\tif (segPtr->typePtr == &tkTextCharType) {\n\t    /*\n\t     * Turn character offset into a byte offset.\n\t     */\n\n\t    start = segPtr->body.chars;\n\t    end = start + segPtr->size;\n\t    for (p = start; p < end; p += offset) {\n\t\tif (charIndex == 0) {\n\t\t    indexPtr->byteIndex = index;\n\t\t    return indexPtr;\n\t\t}\n\t\tcharIndex--;\n\t\toffset = Tcl_UtfToUniChar(p, &ch);\n\t\tindex += offset;\n\t    }\n\t} else {\n\t    if (charIndex < segPtr->size) {\n\t\tindexPtr->byteIndex = index;\n\t\tbreak;\n\t    }\n\t    charIndex -= segPtr->size;\n\t    index += segPtr->size;\n\t}\n    }\n    return indexPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexToSeg --\n *\n *\tGiven an index, this function returns the segment and offset within\n *\tsegment for the index.\n *\n * Results:\n *\tThe return value is a pointer to the segment referred to by indexPtr;\n *\tthis will always be a segment with non-zero size. The variable at\n *\t*offsetPtr is set to hold the integer offset within the segment of the\n *\tcharacter given by indexPtr.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTkTextSegment *\nTkTextIndexToSeg(\n    const TkTextIndex *indexPtr,/* Text index. */\n    Tcl_Size *offsetPtr)\t\t/* Where to store offset within segment, or\n\t\t\t\t * NULL if offset isn't wanted. */\n{\n    TkTextSegment *segPtr;\n    Tcl_Size offset;\n\n    for (offset = indexPtr->byteIndex, segPtr = indexPtr->linePtr->segPtr;\n\t    offset >= segPtr->size;\n\t    offset -= segPtr->size, segPtr = segPtr->nextPtr) {\n\t/* Empty loop body. */\n    }\n    if (offsetPtr != NULL) {\n\t*offsetPtr = offset;\n    }\n    return segPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextSegToOffset --\n *\n *\tGiven a segment pointer and the line containing it, this function\n *\treturns the offset of the segment within its line.\n *\n * Results:\n *\tThe return value is the offset (within its line) of the first\n *\tcharacter in segPtr.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Size\nTkTextSegToOffset(\n    const TkTextSegment *segPtr,/* Segment whose offset is desired. */\n    const TkTextLine *linePtr)\t/* Line containing segPtr. */\n{\n    const TkTextSegment *segPtr2;\n    Tcl_Size offset = 0;\n\n    for (segPtr2 = linePtr->segPtr; segPtr2 != segPtr;\n\t    segPtr2 = segPtr2->nextPtr) {\n\toffset += segPtr2->size;\n    }\n    return offset;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextGetObjIndex --\n *\n *\tSimpler wrapper around the string based function, but could be\n *\tenhanced with a new object type in the future.\n *\n * Results:\n *\tsee TkTextGetIndex\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextGetObjIndex(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    TkText *textPtr,\t\t/* Information about text widget. */\n    Tcl_Obj *idxObj,\t\t/* Object containing textual description of\n\t\t\t\t * position. */\n    TkTextIndex *indexPtr)\t/* Index structure to fill in. */\n{\n    return GetIndex(interp, NULL, textPtr, Tcl_GetString(idxObj), indexPtr,\n\t    NULL);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextSharedGetObjIndex --\n *\n *\tSimpler wrapper around the string based function, but could be\n *\tenhanced with a new object type in the future.\n *\n * Results:\n *\tsee TkTextGetIndex\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextSharedGetObjIndex(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    TkSharedText *sharedTextPtr,/* Information about text widget. */\n    Tcl_Obj *idxObj,\t\t/* Object containing textual description of\n\t\t\t\t * position. */\n    TkTextIndex *indexPtr)\t/* Index structure to fill in. */\n{\n    return GetIndex(interp, sharedTextPtr, NULL, Tcl_GetString(idxObj),\n\t    indexPtr, NULL);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextGetIndex --\n *\n *\tGiven a string, return the index that is described.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the index at *indexPtr is\n *\tfilled in; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextGetIndex(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    TkText *textPtr,\t\t/* Information about text widget. */\n    const char *string,\t\t/* Textual description of position. */\n    TkTextIndex *indexPtr)\t/* Index structure to fill in. */\n{\n    return GetIndex(interp, NULL, textPtr, string, indexPtr, NULL);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetIndex --\n *\n *\tGiven a string, return the index that is described.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If TCL_OK is\n *\treturned, then everything went well and the index at *indexPtr is\n *\tfilled in; otherwise TCL_ERROR is returned and an error message is\n *\tleft in the interp's result.\n *\n *\tIf *canCachePtr is non-NULL, and everything went well, the integer it\n *\tpoints to is set to 1 if the indexPtr is something which can be\n *\tcached, and zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetIndex(\n    Tcl_Interp *interp,\t\t/* Use this for error reporting. */\n    TkSharedText *sharedPtr,\n    TkText *textPtr,\t\t/* Information about text widget. */\n    const char *string,\t\t/* Textual description of position. */\n    TkTextIndex *indexPtr,\t/* Index structure to fill in. */\n    int *canCachePtr)\t\t/* Pointer to integer to store whether we can\n\t\t\t\t * cache the index (or NULL). */\n{\n    char *p, *end, *endOfBase;\n    TkTextIndex first, last;\n    int wantLast, result;\n    char c;\n    const char *cp;\n    Tcl_DString copy;\n    int canCache = 0;\n\n    if (sharedPtr == NULL) {\n\tsharedPtr = textPtr->sharedTextPtr;\n    }\n\n    /*\n     *---------------------------------------------------------------------\n     * Stage 1: check to see if the index consists of nothing but a mark\n     * name, an embedded window or an embedded image.  We do this check\n     * now even though it's also done later, in order to allow mark names,\n     * embedded window names or image names that include funny characters\n     * such as spaces or \"+1c\".\n     *---------------------------------------------------------------------\n     */\n\n    if (TkTextMarkNameToIndex(textPtr, string, indexPtr) == TCL_OK) {\n\tgoto done;\n    }\n\n    if (TkTextWindowIndex(textPtr, string, indexPtr) == TCL_OK) {\n\tgoto done;\n    }\n\n    if (TkTextImageIndex(textPtr, string, indexPtr) == TCL_OK) {\n\tgoto done;\n    }\n\n    /*\n     *------------------------------------------------\n     * Stage 2: start again by parsing the base index.\n     *------------------------------------------------\n     */\n\n    indexPtr->tree = sharedPtr->tree;\n\n    /*\n     * First look for the form \"tag.first\" or \"tag.last\" where \"tag\" is the\n     * name of a valid tag. Try to use up as much as possible of the string in\n     * this check (strrchr instead of strchr below). Doing the check now, and\n     * in this way, allows tag names to include funny characters like \"@\" or\n     * \"+1c\".\n     */\n\n    Tcl_DStringInit(&copy);\n    p = strrchr(Tcl_DStringAppend(&copy, string, TCL_INDEX_NONE), '.');\n    if (p != NULL) {\n\tTkTextSearch search;\n\tTkTextTag *tagPtr;\n\tTcl_HashEntry *hPtr = NULL;\n\tconst char *tagName;\n\n\tif ((p[1] == 'f') && (strncmp(p+1, \"first\", 5) == 0)) {\n\t    wantLast = 0;\n\t    endOfBase = p+6;\n\t} else if ((p[1] == 'l') && (strncmp(p+1, \"last\", 4) == 0)) {\n\t    wantLast = 1;\n\t    endOfBase = p+5;\n\t} else {\n\t    goto tryxy;\n\t}\n\n\ttagPtr = NULL;\n\ttagName = Tcl_DStringValue(&copy);\n\tif (((p - tagName) == 3) && !strncmp(tagName, \"sel\", 3)) {\n\t    /*\n\t     * Special case for sel tag which is not stored in the hash table.\n\t     */\n\n\t    tagPtr = textPtr->selTagPtr;\n\t} else {\n\t    *p = 0;\n\t    hPtr = Tcl_FindHashEntry(&sharedPtr->tagTable, tagName);\n\t    *p = '.';\n\t    if (hPtr != NULL) {\n\t\ttagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);\n\t    }\n\t}\n\n\tif (tagPtr == NULL) {\n\t    goto tryxy;\n\t}\n\n\tTkTextMakeByteIndex(sharedPtr->tree, textPtr, 0, 0, &first);\n\tTkTextMakeByteIndex(sharedPtr->tree, textPtr,\n\t\tTkBTreeNumLines(sharedPtr->tree, textPtr), 0, &last);\n\tTkBTreeStartSearch(&first, &last, tagPtr, &search);\n\tif (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) {\n\t    if (tagPtr == textPtr->selTagPtr) {\n\t\ttagName = \"sel\";\n\t    } else if (hPtr != NULL) {\n\t\ttagName = (const char *)Tcl_GetHashKey(&sharedPtr->tagTable, hPtr);\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"text doesn't contain any characters tagged with \\\"%s\\\"\",\n\t\t    tagName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TEXT_INDEX\", tagName,\n\t\t    (char *)NULL);\n\t    Tcl_DStringFree(&copy);\n\t    return TCL_ERROR;\n\t}\n\t*indexPtr = search.curIndex;\n\tif (wantLast) {\n\t    while (TkBTreeNextTag(&search)) {\n\t\t*indexPtr = search.curIndex;\n\t    }\n\t}\n\tgoto gotBase;\n    }\n\n  tryxy:\n    if (string[0] == '@') {\n\t/*\n\t * Find character at a given x,y location in the window.\n\t */\n\n\tint x, y;\n\n\tcp = string+1;\n\tx = strtol(cp, &end, 0);\n\tif ((end == cp) || (*end != ',')) {\n\t    goto error;\n\t}\n\tcp = end+1;\n\ty = strtol(cp, &end, 0);\n\tif (end == cp) {\n\t    goto error;\n\t}\n\tTkTextPixelIndex(textPtr, x, y, indexPtr, NULL);\n\tendOfBase = end;\n\tgoto gotBase;\n    }\n\n    if (isdigit(UCHAR(string[0])) || (string[0] == '-')) {\n\tint lineIndex;\n\tTcl_Size charIndex;\n\n\t/*\n\t * Base is identified with line and character indices.\n\t */\n\n\tlineIndex = strtol(string, &end, 0) - 1;\n\tif ((end == string) || (*end != '.')) {\n\t    goto error;\n\t}\n\tp = end+1;\n\tif ((*p == 'e') && (strncmp(p, \"end\", 3) == 0)) {\n\t    charIndex = LAST_CHAR;\n\t    endOfBase = p+3;\n\t} else {\n\t    charIndex = strtol(p, &end, 0);\n\t    if (end == p) {\n\t\tgoto error;\n\t    }\n\t    endOfBase = end;\n\t}\n\tTkTextMakeCharIndex(sharedPtr->tree, textPtr, lineIndex, charIndex,\n\t\tindexPtr);\n\tcanCache = 1;\n\tgoto gotBase;\n    }\n\n    for (p = Tcl_DStringValue(&copy); *p != 0; p++) {\n\tif (isspace(UCHAR(*p)) || (*p == '+') || (*p == '-')) {\n\t    break;\n\t}\n    }\n    endOfBase = p;\n    if (string[0] == '.') {\n\t/*\n\t * See if the base position is the name of an embedded window.\n\t */\n\n\tc = *endOfBase;\n\t*endOfBase = 0;\n\tresult = TkTextWindowIndex(textPtr, Tcl_DStringValue(&copy), indexPtr);\n\t*endOfBase = c;\n\tif (result == TCL_OK) {\n\t    goto gotBase;\n\t}\n    }\n    if ((string[0] == 'e')\n\t    && (strncmp(string, \"end\",\n\t    endOfBase-Tcl_DStringValue(&copy)) == 0)) {\n\t/*\n\t * Base position is end of text.\n\t */\n\n\tTkTextMakeByteIndex(sharedPtr->tree, textPtr,\n\t\tTkBTreeNumLines(sharedPtr->tree, textPtr), 0, indexPtr);\n\tcanCache = 1;\n\tgoto gotBase;\n    } else {\n\t/*\n\t * See if the base position is the name of a mark.\n\t */\n\n\tc = *endOfBase;\n\t*endOfBase = 0;\n\tresult = TkTextMarkNameToIndex(textPtr, Tcl_DStringValue(&copy),\n\t\tindexPtr);\n\t*endOfBase = c;\n\tif (result == TCL_OK) {\n\t    goto gotBase;\n\t}\n\n\t/*\n\t * See if the base position is the name of an embedded image.\n\t */\n\n\tc = *endOfBase;\n\t*endOfBase = 0;\n\tresult = TkTextImageIndex(textPtr, Tcl_DStringValue(&copy), indexPtr);\n\t*endOfBase = c;\n\tif (result == TCL_OK) {\n\t    goto gotBase;\n\t}\n    }\n    goto error;\n\n    /*\n     *-------------------------------------------------------------------\n     * Stage 3: process zero or more modifiers. Each modifier is either a\n     * keyword like \"wordend\" or \"linestart\", or it has the form \"op count\n     * units\" where op is + or -, count is a number, and units is \"chars\" or\n     * \"lines\".\n     *-------------------------------------------------------------------\n     */\n\n  gotBase:\n    cp = endOfBase;\n    while (1) {\n\twhile (isspace(UCHAR(*cp))) {\n\t    cp++;\n\t}\n\tif (*cp == 0) {\n\t    break;\n\t}\n\n\tif ((*cp == '+') || (*cp == '-')) {\n\t    cp = ForwBack(textPtr, cp, indexPtr);\n\t} else {\n\t    cp = StartEnd(textPtr, cp, indexPtr);\n\t}\n\tif (cp == NULL) {\n\t    goto error;\n\t}\n    }\n    Tcl_DStringFree(&copy);\n\n  done:\n    if (canCachePtr != NULL) {\n\t*canCachePtr = canCache;\n    }\n    if (indexPtr->linePtr == NULL) {\n\tTcl_Panic(\"Bad index created\");\n    }\n    TkTextIndexAdjustToStartEnd(textPtr, indexPtr, false);\n    return TCL_OK;\n\n  error:\n    Tcl_DStringFree(&copy);\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad text index \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"BAD_INDEX\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexAdjustToStartEnd --\n *\n *      Adjust indexPtr to the -startline/-endline range, or just check\n *      if indexPtr is out of this range.\n *\n * Results:\n *\tThe return value is a standard Tcl return result. If check is true,\n *      return TCL_ERROR if indexPtr is outside the -startline/-endline\n *      range (indexPtr is not modified).\n *      If check is false, adjust indexPtr to -startline/-endline.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextIndexAdjustToStartEnd(\n    TkText *textPtr,\n    TkTextIndex *indexPtr,  /* Pointer to index. */\n    bool check)\t\t    /* true means only check indexPtr against\n\t\t\t     * the -startline/-endline range\n\t\t\t     * false means adjust to this range */\n{\n    Tcl_Size bound;\n    TkTextIndex indexBound;\n\n    if (!textPtr) {\n\treturn TCL_OK;\n    }\n    if (textPtr->start != NULL) {\n\tbound = TkBTreeLinesTo(NULL, textPtr->start);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0,\n\t\t&indexBound);\n\tif (TkTextIndexCmp(indexPtr, &indexBound) < 0) {\n\t    if (check) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0,\n\t\t    indexPtr);\n\t}\n    }\n    if (textPtr->end != NULL) {\n\tbound = TkBTreeLinesTo(NULL, textPtr->end);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0,\n\t\t&indexBound);\n\tif (TkTextIndexCmp(indexPtr, &indexBound) > 0) {\n\t    if (check) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0,\n\t\t    indexPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextPrintIndex --\n *\n *\tThis function generates a string description of an index, suitable for\n *\treading in again later.\n *\n * Results:\n *\tThe characters pointed to by string are modified. Returns the number\n *\tof characters in the string.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Size\nTkTextPrintIndex(\n    const TkText *textPtr,\n    const TkTextIndex *indexPtr,/* Pointer to index. */\n    char *string)\t\t/* Place to store the position. Must have at\n\t\t\t\t * least TK_POS_CHARS characters. */\n{\n    TkTextSegment *segPtr;\n    TkTextLine *linePtr;\n    Tcl_Size numBytes, charIndex;\n\n    numBytes = indexPtr->byteIndex;\n    charIndex = 0;\n    linePtr = indexPtr->linePtr;\n\n    for (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) {\n\tif (segPtr == NULL) {\n\t    /*\n\t     * Two logical lines merged into one display line through eliding\n\t     * of a newline.\n\t     */\n\n\t    linePtr = TkBTreeNextLine(NULL, linePtr);\n\t    segPtr = linePtr->segPtr;\n\t}\n\tif (numBytes <= segPtr->size) {\n\t    break;\n\t}\n\tif (segPtr->typePtr == &tkTextCharType) {\n\t    charIndex += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size);\n\t} else {\n\t    charIndex += segPtr->size;\n\t}\n\tnumBytes -= segPtr->size;\n    }\n\n    if (segPtr->typePtr == &tkTextCharType) {\n\tcharIndex += Tcl_NumUtfChars(segPtr->body.chars, numBytes);\n    } else {\n\tcharIndex += numBytes;\n    }\n\n    return snprintf(string, TK_POS_CHARS, \"%\" TCL_Z_MODIFIER \"d.%\" TCL_Z_MODIFIER \"d\",\n\t    TkBTreeLinesTo(textPtr, indexPtr->linePtr) + 1, charIndex);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexCmp --\n *\n *\tCompare two indices to see which one is earlier in the text.\n *\n * Results:\n *\tThe return value is 0 if index1Ptr and index2Ptr refer to the same\n *\tposition in the file, -1 if index1Ptr refers to an earlier position\n *\tthan index2Ptr, and 1 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkTextIndexCmp(\n    const TkTextIndex*index1Ptr,/* First index. */\n    const TkTextIndex*index2Ptr)/* Second index. */\n{\n    Tcl_Size line1, line2;\n\n    if (index1Ptr->linePtr == index2Ptr->linePtr) {\n\tif (index1Ptr->byteIndex < index2Ptr->byteIndex) {\n\t    return -1;\n\t} else if (index1Ptr->byteIndex > index2Ptr->byteIndex) {\n\t    return 1;\n\t} else {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * Assumption here that it is ok for comparisons to reflect the full\n     * B-tree and not just the portion that is available to any client. This\n     * should be true because the only indexPtr's we should be given are ones\n     * which are valid for the current client.\n     */\n\n    line1 = TkBTreeLinesTo(NULL, index1Ptr->linePtr);\n    line2 = TkBTreeLinesTo(NULL, index2Ptr->linePtr);\n    if (line1 < line2) {\n\treturn -1;\n    }\n    if (line1 > line2) {\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ForwBack --\n *\n *\tThis function handles +/- modifiers for indices to adjust the index\n *\tforwards or backwards.\n *\n * Results:\n *\tIf the modifier in string is successfully parsed then the return value\n *\tis the address of the first character after the modifier, and\n *\t*indexPtr is updated to reflect the modifier. If there is a syntax\n *\terror in the modifier then NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic const char *\nForwBack(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    const char *string,\t\t/* String to parse for additional info about\n\t\t\t\t * modifier (count and units). Points to \"+\"\n\t\t\t\t * or \"-\" that starts modifier. */\n    TkTextIndex *indexPtr)\t/* Index to update as specified in string. */\n{\n    const char *p, *units;\n    char *end;\n    Tcl_Size lineIndex;\n    indexModifier modifier;\n    size_t length;\n    int count;\n\n    /*\n     * Get the count (how many units forward or backward).\n     */\n\n    p = string+1;\n    while (isspace(UCHAR(*p))) {\n\tp++;\n    }\n    count = strtol(p, &end, 0);\n    if (end == p) {\n\treturn NULL;\n    }\n    p = end;\n    while (isspace(UCHAR(*p))) {\n\tp++;\n    }\n\n    /*\n     * Find the end of this modifier (next space or + or - character), then\n     * check if there is a textual 'display' or 'any' modifier. These\n     * modifiers can be their own word (in which case they can be abbreviated)\n     * or they can follow on to the actual unit in a single word (in which\n     * case no abbreviation is allowed). So, 'display lines', 'd lines',\n     * 'displaylin' are all ok, but 'dline' is not.\n     */\n\n    units = p;\n    while ((*p != '\\0') && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) {\n\tp++;\n    }\n    length = p - units;\n    if ((*units == 'd') &&\n\t    (strncmp(units, \"display\", (length > 7 ? 7 : length)) == 0)) {\n\tmodifier = TKINDEX_DISPLAY;\n\tif (length > 7) {\n\t    p -= (length - 7);\n\t}\n    } else if ((*units == 'a') &&\n\t    (strncmp(units, \"any\", (length > 3 ? 3 : length)) == 0)) {\n\tmodifier = TKINDEX_ANY;\n\tif (length > 3) {\n\t    p -= (length - 3);\n\t}\n    } else {\n\tmodifier = TKINDEX_NONE;\n    }\n\n    /*\n     * If we had a modifier, which we interpreted ok, so now forward to the\n     * actual units.\n     */\n\n    if (modifier != TKINDEX_NONE) {\n\twhile (isspace(UCHAR(*p))) {\n\t    p++;\n\t}\n\tunits = p;\n\twhile (*p!='\\0' && !isspace(UCHAR(*p)) && *p!='+' && *p!='-') {\n\t    p++;\n\t}\n\tlength = p - units;\n    }\n\n    /*\n     * Finally parse the units.\n     */\n\n    if ((*units == 'c') && (strncmp(units, \"chars\", length) == 0)) {\n\tTkTextCountType type;\n\n\tif (modifier == TKINDEX_NONE) {\n\t    type = COUNT_INDICES;\n\t} else if (modifier == TKINDEX_ANY) {\n\t    type = COUNT_CHARS;\n\t} else {\n\t    type = COUNT_DISPLAY_CHARS;\n\t}\n\n\tif (*string == '+') {\n\t    TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type);\n\t} else {\n\t    TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type);\n\t}\n    } else if ((*units == 'i') && (strncmp(units, \"indices\", length) == 0)) {\n\tTkTextCountType type;\n\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    type = COUNT_DISPLAY_INDICES;\n\t} else {\n\t    type = COUNT_INDICES;\n\t}\n\n\tif (*string == '+') {\n\t    TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type);\n\t} else {\n\t    TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type);\n\t}\n    } else if ((*units == 'l') && (strncmp(units, \"lines\", length) == 0)) {\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    /*\n\t     * Find the appropriate pixel offset of the current position\n\t     * within its display line. This also has the side-effect of\n\t     * moving indexPtr, but that doesn't matter since we will do it\n\t     * again below.\n\t     *\n\t     * Then find the right display line, and finally calculated the\n\t     * index we want in that display line, based on the original pixel\n\t     * offset.\n\t     */\n\n\t    int xOffset, forward;\n\n\t    if (TkTextIsElided(textPtr, indexPtr, NULL)) {\n\t\t/*\n\t\t * Go forward to the first non-elided index.\n\t\t */\n\n\t\tTkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,\n\t\t\tCOUNT_DISPLAY_INDICES);\n\t    }\n\n\t    /*\n\t     * Unlike the Forw/BackChars code, the display line code is\n\t     * sensitive to whether we are genuinely going forwards or\n\t     * backwards. So, we need to determine that. This is important in\n\t     * the case where we have \"+ -3 displaylines\", for example.\n\t     */\n\n\t    if ((count < 0) ^ (*string == '-')) {\n\t\tforward = 0;\n\t    } else {\n\t\tforward = 1;\n\t    }\n\n\t    count = abs(count);\n\t    if (count == 0) {\n\t\treturn p;\n\t    }\n\n\t    if (forward) {\n\t\tTkTextFindDisplayLineEnd(textPtr, indexPtr, 1, &xOffset);\n\t\twhile (count-- > 0) {\n\n\t\t    /*\n\t\t     * Go to the end of the line, then forward one char/byte\n\t\t     * to get to the beginning of the next line.\n\t\t     */\n\n\t\t    TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL);\n\t\t    TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,\n\t\t\t    COUNT_DISPLAY_INDICES);\n\t\t}\n\t    } else {\n\t\tTkTextFindDisplayLineEnd(textPtr, indexPtr, 0, &xOffset);\n\t\twhile (count-- > 0) {\n\t\t    TkTextIndex indexPtr2;\n\n\t\t    /*\n\t\t     * Go to the beginning of the line, then backward one\n\t\t     * char/byte to get to the end of the previous line.\n\t\t     */\n\n\t\t    TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);\n\t\t    TkTextIndexBackChars(textPtr, indexPtr, 1, &indexPtr2,\n\t\t\t    COUNT_DISPLAY_INDICES);\n\n\t\t    /*\n\t\t     * If we couldn't go to the previous line, then we wanted\n\t\t       to go before the start of the text: arrange for returning\n\t\t       the first index of the first display line.\n\t\t     */\n\n\t\t    if (!TkTextIndexCmp(indexPtr, &indexPtr2)) {\n\t\t\txOffset = 0;\n\t\t\tbreak;\n\t\t    }\n\t\t    *indexPtr = indexPtr2;\n\t\t}\n\t    }\n\t    TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);\n\n\t    /*\n\t     * This call assumes indexPtr is the beginning of a display line\n\t     * and moves it to the 'xOffset' position of that line, which is\n\t     * just what we want.\n\t     */\n\n\t    TkTextIndexOfX(textPtr, xOffset, indexPtr);\n\t} else {\n\t    lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr);\n\t    if (*string == '+') {\n\t\tlineIndex += count;\n\t    } else {\n\t\tlineIndex -= count;\n\n\t\t/*\n\t\t * The check below retains the character position, even if the\n\t\t * line runs off the start of the file. Without it, the\n\t\t * character position will get reset to 0 by TkTextMakeIndex.\n\t\t */\n\n\t\tif (lineIndex < 0) {\n\t\t    lineIndex = 0;\n\t\t}\n\t    }\n\n\t    /*\n\t     * This doesn't work quite right if using a proportional font or\n\t     * UTF-8 characters with varying numbers of bytes, or if there are\n\t     * embedded windows, images, etc. The cursor will bop around,\n\t     * keeping a constant number of bytes (not characters) from the\n\t     * left edge (but making sure not to split any UTF-8 characters),\n\t     * regardless of the x-position the index corresponds to. The\n\t     * proper way to do this is to get the x-position of the index and\n\t     * then pick the character at the same x-position in the new line.\n\t     */\n\n\t    TkTextMakeByteIndex(indexPtr->tree, textPtr, lineIndex,\n\t\t    indexPtr->byteIndex, indexPtr);\n\t}\n    } else {\n\treturn NULL;\n    }\n    return p;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexForwBytes --\n *\n *\tGiven an index for a text widget, this function creates a new index\n *\tthat points \"count\" bytes ahead of the source index.\n *\n * Results:\n *\t*dstPtr is modified to refer to the character \"count\" bytes after\n *\tsrcPtr, or to the last character in the TkText if there aren't \"count\"\n *\tbytes left.\n *\n *\tIn this latter case, the function returns true to indicate that not all\n *\tof 'byteCount' could be used.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nbool\nTkTextIndexForwBytes(\n    const TkText *textPtr,\n    const TkTextIndex *srcPtr,\t/* Source index. */\n    Tcl_Size byteCount,\t\t/* How many bytes forward to move. May be\n\t\t\t\t * negative. */\n    TkTextIndex *dstPtr)\t/* Destination index: gets modified. */\n{\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    Tcl_Size lineLength;\n\n    if (byteCount < 0) {\n\tTkTextIndexBackBytes(textPtr, srcPtr, -byteCount, dstPtr);\n\treturn false;\n    }\n\n    *dstPtr = *srcPtr;\n    dstPtr->byteIndex += byteCount;\n    while (1) {\n\t/*\n\t * Compute the length of the current line.\n\t */\n\n\tlineLength = 0;\n\tfor (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    lineLength += segPtr->size;\n\t}\n\n\t/*\n\t * If the new index is in the same line then we're done. Otherwise go\n\t * on to the next line.\n\t */\n\n\tif (dstPtr->byteIndex < lineLength) {\n\t    return false;\n\t}\n\tdstPtr->byteIndex -= lineLength;\n\tlinePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr);\n\tif (linePtr == NULL) {\n\t    dstPtr->byteIndex = lineLength - 1;\n\t    return true;\n\t}\n\tdstPtr->linePtr = linePtr;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexForwChars --\n *\n *\tGiven an index for a text widget, this function creates a new index\n *\tthat points \"count\" items of type given by \"type\" ahead of the source\n *\tindex. \"count\" can be zero, which is useful in the case where one\n *\twishes to move forward by display (non-elided) chars or indices or one\n *\twishes to move forward by chars, skipping any intervening indices. In\n *\tthis case dstPtr will point to the first acceptable index which is\n *\tencountered.\n *\n * Results:\n *\t*dstPtr is modified to refer to the character \"count\" items after\n *\tsrcPtr, or to the last character in the TkText if there aren't\n *\tsufficient items left in the widget.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkTextIndexForwChars(\n    const TkText *textPtr,\t/* Overall information about text widget. */\n    const TkTextIndex *srcPtr,\t/* Source index. */\n    Tcl_Size charCount,\t\t/* How many characters forward to move. May\n\t\t\t\t * be negative. */\n    TkTextIndex *dstPtr,\t/* Destination index: gets modified. */\n    TkTextCountType type)\t/* The type of item to count */\n{\n    TkTextLine *linePtr;\n    TkTextSegment *segPtr;\n    TkTextElideInfo *infoPtr = NULL;\n    Tcl_Size byteOffset;\n    char *start, *end, *p;\n    Tcl_UniChar ch;\n    bool elide = false;\n    bool checkElided = (type & COUNT_DISPLAY) != 0;\n\n    if (charCount < 0) {\n\tTkTextIndexBackChars(textPtr, srcPtr, -charCount, dstPtr, type);\n\treturn;\n    }\n    if (checkElided) {\n\tinfoPtr = (TkTextElideInfo *)Tcl_Alloc(sizeof(TkTextElideInfo));\n\telide = TkTextIsElided(textPtr, srcPtr, infoPtr);\n    }\n\n    *dstPtr = *srcPtr;\n\n    /*\n     * Find seg that contains src byteIndex. Move forward specified number of\n     * chars.\n     */\n\n    if (checkElided) {\n\t/*\n\t * In this case we have already calculated the information we need, so\n\t * no need to use TkTextIndexToSeg()\n\t */\n\n\tsegPtr = infoPtr->segPtr;\n\tbyteOffset = dstPtr->byteIndex - infoPtr->segOffset;\n    } else {\n\tsegPtr = TkTextIndexToSeg(dstPtr, &byteOffset);\n    }\n\n    while (1) {\n\t/*\n\t * Go through each segment in line looking for specified character\n\t * index.\n\t */\n\n\tfor ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\t    /*\n\t     * If we do need to pay attention to the visibility of\n\t     * characters/indices, check that first. If the current segment\n\t     * isn't visible, then we simply continue the loop.\n\t     */\n\n\t    if (checkElided && ((segPtr->typePtr == &tkTextToggleOffType)\n\t\t    || (segPtr->typePtr == &tkTextToggleOnType))) {\n\t\tTkTextTag *tagPtr = segPtr->body.toggle.tagPtr;\n\n\t\t/*\n\t\t * The elide state only changes if this tag is either the\n\t\t * current highest priority tag (and is therefore being\n\t\t * toggled off), or it's a new tag with higher priority.\n\t\t */\n\n\t\tif (tagPtr->elide >= 0) {\n\t\t    infoPtr->tagCnts[tagPtr->priority]++;\n\t\t    if (infoPtr->tagCnts[tagPtr->priority] & 1) {\n\t\t\tinfoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\t    }\n\n\t\t    if (tagPtr->priority >= infoPtr->elidePriority) {\n\t\t\tif (segPtr->typePtr == &tkTextToggleOffType) {\n\t\t\t    /*\n\t\t\t     * If it is being toggled off, and it has an elide\n\t\t\t     * string, it must actually be the current highest\n\t\t\t     * priority tag, so this check is redundant:\n\t\t\t     */\n\n\t\t\t    if (tagPtr->priority != infoPtr->elidePriority) {\n\t\t\t\tTcl_Panic(\"Bad tag priority being toggled off\");\n\t\t\t    }\n\n\t\t\t    /*\n\t\t\t     * Find previous elide tag, if any (if not then\n\t\t\t     * elide will be zero, of course).\n\t\t\t     */\n\n\t\t\t    elide = false;\n\t\t\t    while (--infoPtr->elidePriority > 0) {\n\t\t\t\tif (infoPtr->tagCnts[infoPtr->elidePriority]\n\t\t\t\t\t& 1) {\n\t\t\t\t    elide = infoPtr->tagPtrs\n\t\t\t\t\t    [infoPtr->elidePriority]->elide > 0;\n\t\t\t\t    break;\n\t\t\t\t}\n\t\t\t    }\n\t\t\t} else {\n\t\t\t    elide = tagPtr->elide > 0;\n\t\t\t    infoPtr->elidePriority = tagPtr->priority;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\n\t    if (!elide) {\n\t\tif (segPtr->typePtr == &tkTextCharType) {\n\t\t    start = segPtr->body.chars + byteOffset;\n\t\t    end = segPtr->body.chars + segPtr->size;\n\t\t    for (p = start; p < end; p += Tcl_UtfToUniChar(p, &ch)) {\n\t\t\tif (charCount == 0) {\n\t\t\t    dstPtr->byteIndex += (p - start);\n\t\t\t    goto forwardCharDone;\n\t\t\t}\n\t\t\tcharCount--;\n\t\t    }\n\t\t} else if (type & COUNT_INDICES) {\n\t\t    if (charCount + byteOffset < segPtr->size) {\n\t\t\tdstPtr->byteIndex += charCount;\n\t\t\tgoto forwardCharDone;\n\t\t    }\n\t\t    charCount -= segPtr->size - byteOffset;\n\t\t}\n\t    }\n\n\t    dstPtr->byteIndex += segPtr->size - byteOffset;\n\t    byteOffset = 0;\n\t}\n\n\t/*\n\t * Go to the next line. If we are at the end of the text item, back up\n\t * one byte (for the terminal '\\n' character) and return that index.\n\t */\n\n\tlinePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr);\n\tif (linePtr == NULL) {\n\t    dstPtr->byteIndex -= sizeof(char);\n\t    goto forwardCharDone;\n\t}\n\tdstPtr->linePtr = linePtr;\n\tdstPtr->byteIndex = 0;\n\tsegPtr = dstPtr->linePtr->segPtr;\n    }\n\n  forwardCharDone:\n    if (infoPtr != NULL) {\n\tTkTextFreeElideInfo(infoPtr);\n\tTcl_Free(infoPtr);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexCountBytes --\n *\n *\tGiven a pair of indices in a text widget, this function counts how\n *\tmany bytes are between the two indices. The two indices do not need\n *\tto be ordered.\n *\n * Results:\n *\tThe number of bytes in the given range.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Size\nTkTextIndexCountBytes(\n    const TkText *textPtr,\n    const TkTextIndex *indexPtr1, /* Index describing one location. */\n    const TkTextIndex *indexPtr2) /* Index describing second location. */\n{\n    int compare = TkTextIndexCmp(indexPtr1, indexPtr2);\n\n    if (compare == 0) {\n\treturn 0;\n    } else if (compare > 0) {\n\treturn IndexCountBytesOrdered(textPtr, indexPtr2, indexPtr1);\n    } else {\n\treturn IndexCountBytesOrdered(textPtr, indexPtr1, indexPtr2);\n    }\n}\n\nstatic Tcl_Size\nIndexCountBytesOrdered(\n    const TkText *textPtr,\n    const TkTextIndex *indexPtr1,\n\t\t\t\t/* Index describing location of character from\n\t\t\t\t * which to count. */\n    const TkTextIndex *indexPtr2)\n\t\t\t\t/* Index describing location of last character\n\t\t\t\t * at which to stop the count. */\n{\n    Tcl_Size byteCount, offset;\n    TkTextSegment *segPtr, *segPtr1;\n    TkTextLine *linePtr;\n\n    if (indexPtr1->linePtr == indexPtr2->linePtr) {\n\treturn (indexPtr2->byteIndex - indexPtr1->byteIndex);\n    }\n\n    /*\n     * indexPtr2 is on a line strictly after the line containing indexPtr1.\n     * Add up:\n     *   bytes between indexPtr1 and end of its line\n     *   bytes in lines strictly between indexPtr1 and indexPtr2\n     *   bytes between start of the indexPtr2 line and indexPtr2\n     */\n\n    segPtr1 = TkTextIndexToSeg(indexPtr1, &offset);\n    byteCount = -offset;\n    for (segPtr = segPtr1; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\tbyteCount += segPtr->size;\n    }\n\n    linePtr = TkBTreeNextLine(textPtr, indexPtr1->linePtr);\n    while (linePtr != indexPtr2->linePtr) {\n\tfor (segPtr = linePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    byteCount += segPtr->size;\n\t}\n\tlinePtr = TkBTreeNextLine(textPtr, linePtr);\n\tif (linePtr == NULL) {\n\t    Tcl_Panic(\"TextIndexCountBytesOrdered ran out of lines\");\n\t}\n    }\n\n    byteCount += indexPtr2->byteIndex;\n\n    return byteCount;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexCount --\n *\n *\tGiven an ordered pair of indices in a text widget, this function\n *\tcounts how many characters (not bytes) are between the two indices.\n *\n *\tIt is illegal to call this function with unordered indices.\n *\n *\tNote that 'textPtr' is only used if we need to check for elided\n *\tattributes, i.e. if type is COUNT_DISPLAY_INDICES or\n *\tCOUNT_DISPLAY_CHARS.\n *\n * Results:\n *\tThe number of characters in the given range, which meet the\n *\tappropriate 'type' attributes.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTcl_Size\nTkTextIndexCount(\n    const TkText *textPtr,\t/* Overall information about text widget. */\n    const TkTextIndex *indexPtr1,\n\t\t\t\t/* Index describing location of character from\n\t\t\t\t * which to count. */\n    const TkTextIndex *indexPtr2,\n\t\t\t\t/* Index describing location of last character\n\t\t\t\t * at which to stop the count. */\n    TkTextCountType type)\t/* The kind of indices to count. */\n{\n    TkTextLine *linePtr1;\n    TkTextSegment *segPtr, *seg2Ptr = NULL;\n    TkTextElideInfo *infoPtr = NULL;\n    Tcl_Size byteOffset, maxBytes, count = 0;\n    bool elide = false;\n    bool checkElided = (type & COUNT_DISPLAY) != 0;\n\n    /*\n     * Find seg that contains src index, and remember how many bytes not to\n     * count in the given segment.\n     */\n\n    segPtr = TkTextIndexToSeg(indexPtr1, &byteOffset);\n    linePtr1 = indexPtr1->linePtr;\n\n    seg2Ptr = TkTextIndexToSeg(indexPtr2, &maxBytes);\n\n    if (checkElided) {\n\tinfoPtr = (TkTextElideInfo *)Tcl_Alloc(sizeof(TkTextElideInfo));\n\telide = TkTextIsElided(textPtr, indexPtr1, infoPtr);\n    }\n\n    while (1) {\n\t/*\n\t * Go through each segment in line adding up the number of characters.\n\t */\n\n\tfor ( ; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\t    /*\n\t     * If we do need to pay attention to the visibility of\n\t     * characters/indices, check that first. If the current segment\n\t     * isn't visible, then we simply continue the loop.\n\t     */\n\n\t    if (checkElided) {\n\t\tif ((segPtr->typePtr == &tkTextToggleOffType)\n\t\t\t|| (segPtr->typePtr == &tkTextToggleOnType)) {\n\t\t    TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;\n\n\t\t    /*\n\t\t     * The elide state only changes if this tag is either the\n\t\t     * current highest priority tag (and is therefore being\n\t\t     * toggled off), or it's a new tag with higher priority.\n\t\t     */\n\n\t\t    if (tagPtr->elide >= 0) {\n\t\t\tinfoPtr->tagCnts[tagPtr->priority]++;\n\t\t\tif (infoPtr->tagCnts[tagPtr->priority] & 1) {\n\t\t\t    infoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\t\t}\n\t\t\tif (tagPtr->priority >= infoPtr->elidePriority) {\n\t\t\t    if (segPtr->typePtr == &tkTextToggleOffType) {\n\t\t\t\t/*\n\t\t\t\t * If it is being toggled off, and it has an\n\t\t\t\t * elide string, it must actually be the\n\t\t\t\t * current highest priority tag, so this check\n\t\t\t\t * is redundant:\n\t\t\t\t */\n\n\t\t\t\tif (tagPtr->priority!=infoPtr->elidePriority) {\n\t\t\t\t    Tcl_Panic(\"Bad tag priority being toggled off\");\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * Find previous elide tag, if any (if not\n\t\t\t\t * then elide will be zero, of course).\n\t\t\t\t */\n\n\t\t\t\telide = 0;\n\t\t\t\twhile (--infoPtr->elidePriority > 0) {\n\t\t\t\t    if (infoPtr->tagCnts[\n\t\t\t\t\t    infoPtr->elidePriority] & 1) {\n\t\t\t\t\telide = infoPtr->tagPtrs[\n\t\t\t\t\t\tinfoPtr->elidePriority]->elide > 0;\n\t\t\t\t\tbreak;\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t    } else {\n\t\t\t\telide = tagPtr->elide > 0;\n\t\t\t\tinfoPtr->elidePriority = tagPtr->priority;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t\tif (elide) {\n\t\t    if (segPtr == seg2Ptr) {\n\t\t\tgoto countDone;\n\t\t    }\n\t\t    byteOffset = 0;\n\t\t    continue;\n\t\t}\n\t    }\n\n\t    if (segPtr->typePtr == &tkTextCharType) {\n\t\tTcl_Size byteLen = segPtr->size - byteOffset;\n\t\tunsigned char *str = (unsigned char *)\n\t\t\tsegPtr->body.chars + byteOffset;\n\t\tTcl_Size i;\n\n\t\tif (segPtr == seg2Ptr) {\n\t\t    if (byteLen + byteOffset > maxBytes) {\n\t\t\tbyteLen = maxBytes - byteOffset;\n\t\t    }\n\t\t}\n\t\ti = byteLen;\n\n\t\t/*\n\t\t * This is a speed sensitive function, so run specially over\n\t\t * the string to count continuous ascii characters before\n\t\t * resorting to the Tcl_NumUtfChars call. This is a long form\n\t\t * of:\n\t\t *\n\t\t *   stringPtr->numChars =\n\t\t *\t     Tcl_NumUtfChars(objPtr->bytes, objPtr->length);\n\t\t */\n\n\t\twhile (i && (*str < 0xC0)) {\n\t\t    i--;\n\t\t    str++;\n\t\t}\n\t\tcount += byteLen - i;\n\t\tif (i) {\n\t\t    count += Tcl_NumUtfChars(segPtr->body.chars + byteOffset\n\t\t\t    + (byteLen - i), i);\n\t\t}\n\t    } else {\n\t\tif (type & COUNT_INDICES) {\n\t\t    Tcl_Size byteLen = segPtr->size - byteOffset;\n\n\t\t    if (segPtr == seg2Ptr) {\n\t\t\tif (byteLen + byteOffset > maxBytes) {\n\t\t\t    byteLen = maxBytes - byteOffset;\n\t\t\t}\n\t\t    }\n\t\t    count += byteLen;\n\t\t}\n\t    }\n\t    if (segPtr == seg2Ptr) {\n\t\tgoto countDone;\n\t    }\n\t    byteOffset = 0;\n\t}\n\n\t/*\n\t * Go to the next line. If we are at the end of the text item, back up\n\t * one byte (for the terminal '\\n' character) and return that index.\n\t */\n\n\tlinePtr1 = TkBTreeNextLine(textPtr, linePtr1);\n\tif (linePtr1 == NULL) {\n\t    Tcl_Panic(\"Reached end of text widget when counting characters\");\n\t}\n\tsegPtr = linePtr1->segPtr;\n    }\n\n  countDone:\n    if (infoPtr != NULL) {\n\tTkTextFreeElideInfo(infoPtr);\n\tTcl_Free(infoPtr);\n    }\n    return count;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexBackBytes --\n *\n *\tGiven an index for a text widget, this function creates a new index\n *\tthat points \"count\" bytes earlier than the source index.\n *\n * Results:\n *\t*dstPtr is modified to refer to the character \"count\" bytes before\n *\tsrcPtr, or to the first character in the TkText if there aren't\n *\t\"count\" bytes earlier than srcPtr.\n *\n *\tReturns 1 if we couldn't use all of 'byteCount' because we have run\n *\tinto the beginning or end of the text, and zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nbool\nTkTextIndexBackBytes(\n    const TkText *textPtr,\n    const TkTextIndex *srcPtr,\t/* Source index. */\n    Tcl_Size byteCount,\t\t/* How many bytes backward to move. May be\n\t\t\t\t * negative. */\n    TkTextIndex *dstPtr)\t/* Destination index: gets modified. */\n{\n    TkTextSegment *segPtr;\n    Tcl_Size lineIndex;\n\n    if (byteCount < 0) {\n\treturn TkTextIndexForwBytes(textPtr, srcPtr, -byteCount, dstPtr);\n    }\n\n    *dstPtr = *srcPtr;\n    dstPtr->byteIndex -= byteCount;\n    lineIndex = -1;\n    while (dstPtr->byteIndex < 0) {\n\t/*\n\t * Move back one line in the text. If we run off the beginning of the\n\t * file then just return the first character in the text.\n\t */\n\n\tif (lineIndex < 0) {\n\t    lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr);\n\t}\n\tif (lineIndex == 0) {\n\t    dstPtr->byteIndex = 0;\n\t    return true;\n\t}\n\tlineIndex--;\n\tdstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex);\n\n\t/*\n\t * Compute the length of the line and add that to dstPtr->charIndex.\n\t */\n\n\tfor (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;\n\t\tsegPtr = segPtr->nextPtr) {\n\t    dstPtr->byteIndex += segPtr->size;\n\t}\n    }\n    return false;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkTextIndexBackChars --\n *\n *\tGiven an index for a text widget, this function creates a new index\n *\tthat points \"count\" items of type given by \"type\" earlier than the\n *\tsource index. \"count\" can be zero, which is useful in the case where\n *\tone wishes to move backward by display (non-elided) chars or indices\n *\tor one wishes to move backward by chars, skipping any intervening\n *\tindices. In this case the returned index *dstPtr will point just\n *\t_after_ the first acceptable index which is encountered.\n *\n * Results:\n *\t*dstPtr is modified to refer to the character \"count\" items before\n *\tsrcPtr, or to the first index in the window if there aren't sufficient\n *\titems earlier than srcPtr.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkTextIndexBackChars(\n    const TkText *textPtr,\t/* Overall information about text widget. */\n    const TkTextIndex *srcPtr,\t/* Source index. */\n    Tcl_Size charCount,\t\t/* How many characters backward to move. May\n\t\t\t\t * be negative. */\n    TkTextIndex *dstPtr,\t/* Destination index: gets modified. */\n    TkTextCountType type)\t/* The type of item to count */\n{\n    TkTextSegment *segPtr, *oldPtr;\n    TkTextElideInfo *infoPtr = NULL;\n    Tcl_Size lineIndex;\n    Tcl_Size segSize;\n    const char *p, *start, *end;\n    bool elide = false;\n    bool checkElided = (type & COUNT_DISPLAY) != 0;\n\n    if (charCount < 0) {\n\tTkTextIndexForwChars(textPtr, srcPtr, -charCount, dstPtr, type);\n\treturn;\n    }\n    if (checkElided) {\n\tinfoPtr = (TkTextElideInfo *)Tcl_Alloc(sizeof(TkTextElideInfo));\n\telide = TkTextIsElided(textPtr, srcPtr, infoPtr);\n    }\n\n    *dstPtr = *srcPtr;\n\n    /*\n     * Find offset within seg that contains byteIndex. Move backward specified\n     * number of chars.\n     */\n\n    lineIndex = -1;\n\n    segSize = dstPtr->byteIndex;\n\n    if (checkElided) {\n\tsegPtr = infoPtr->segPtr;\n\tsegSize -= infoPtr->segOffset;\n    } else {\n\tTkTextLine *linePtr = dstPtr->linePtr;\n\tfor (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) {\n\t    if (segPtr == NULL) {\n\t\t/*\n\t\t * Two logical lines merged into one display line through\n\t\t * eliding of a newline.\n\t\t */\n\n\t\tlinePtr = TkBTreeNextLine(NULL, linePtr);\n\t\tsegPtr = linePtr->segPtr;\n\t    }\n\t    if (segSize <= segPtr->size) {\n\t\tbreak;\n\t    }\n\t    segSize -= segPtr->size;\n\t}\n    }\n\n    /*\n     * Now segPtr points to the segment containing the starting index.\n     */\n\n    while (1) {\n\t/*\n\t * If we do need to pay attention to the visibility of\n\t * characters/indices, check that first. If the current segment isn't\n\t * visible, then we simply continue the loop.\n\t */\n\n\tif (checkElided && ((segPtr->typePtr == &tkTextToggleOffType)\n\t\t|| (segPtr->typePtr == &tkTextToggleOnType))) {\n\t    TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;\n\n\t    /*\n\t     * The elide state only changes if this tag is either the current\n\t     * highest priority tag (and is therefore being toggled off), or\n\t     * it's a new tag with higher priority.\n\t     */\n\n\t    if (tagPtr->elide >= 0) {\n\t\tinfoPtr->tagCnts[tagPtr->priority]++;\n\t\tif (infoPtr->tagCnts[tagPtr->priority] & 1) {\n\t\t    infoPtr->tagPtrs[tagPtr->priority] = tagPtr;\n\t\t}\n\t\tif (tagPtr->priority >= infoPtr->elidePriority) {\n\t\t    if (segPtr->typePtr == &tkTextToggleOnType) {\n\t\t\t/*\n\t\t\t * If it is being toggled on, and it has an elide\n\t\t\t * string, it must actually be the current highest\n\t\t\t * priority tag, so this check is redundant:\n\t\t\t */\n\n\t\t\tif (tagPtr->priority != infoPtr->elidePriority) {\n\t\t\t    Tcl_Panic(\"Bad tag priority being toggled on\");\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Find previous elide tag, if any (if not then elide\n\t\t\t * will be zero, of course).\n\t\t\t */\n\n\t\t\telide = false;\n\t\t\twhile (--infoPtr->elidePriority > 0) {\n\t\t\t    if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {\n\t\t\t\telide = infoPtr->tagPtrs[\n\t\t\t\t\tinfoPtr->elidePriority]->elide > 0;\n\t\t\t\tbreak;\n\t\t\t    }\n\t\t\t}\n\t\t    } else {\n\t\t\telide = tagPtr->elide > 0;\n\t\t\tinfoPtr->elidePriority = tagPtr->priority;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\tif (!elide) {\n\t    if (segPtr->typePtr == &tkTextCharType) {\n\t\tstart = segPtr->body.chars;\n\t\tend = segPtr->body.chars + segSize;\n\t\tfor (p = end; ; p = Tcl_UtfPrev(p, start)) {\n\t\t    if (charCount == 0) {\n\t\t\tdstPtr->byteIndex -= (end - p);\n\t\t\tgoto backwardCharDone;\n\t\t    }\n\t\t    if (p == start) {\n\t\t\tbreak;\n\t\t    }\n\t\t    if ((sizeof(Tcl_UniChar) == 2) &&  (unsigned)(UCHAR(*p) - 0xF0) <= 5) {\n\t\t\tcharCount--; /* Characters > U+FFFF count as 2 here */\n\t\t    }\n\t\t    if (charCount != 0) {\n\t\t\tcharCount--;\n\t\t    }\n\t\t}\n\t    } else {\n\t\tif (type & COUNT_INDICES) {\n\t\t    if (charCount <= segSize) {\n\t\t\tdstPtr->byteIndex -= charCount;\n\t\t\tgoto backwardCharDone;\n\t\t    }\n\t\t    charCount -= segSize;\n\t\t}\n\t    }\n\t}\n\tdstPtr->byteIndex -= segSize;\n\n\t/*\n\t * Move back into previous segment.\n\t */\n\n\toldPtr = segPtr;\n\tsegPtr = dstPtr->linePtr->segPtr;\n\tif (segPtr != oldPtr) {\n\t    for ( ; segPtr->nextPtr != oldPtr; segPtr = segPtr->nextPtr) {\n\t\t/* Empty body. */\n\t    }\n\t    segSize = segPtr->size;\n\t    continue;\n\t}\n\n\t/*\n\t * Move back to previous line.\n\t */\n\n\tif (lineIndex < 0) {\n\t    lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr);\n\t}\n\tif (lineIndex == 0) {\n\t    dstPtr->byteIndex = 0;\n\t    goto backwardCharDone;\n\t}\n\tlineIndex--;\n\tdstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex);\n\n\t/*\n\t * Compute the length of the line and add that to dstPtr->byteIndex.\n\t */\n\n\toldPtr = dstPtr->linePtr->segPtr;\n\tfor (segPtr = oldPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {\n\t    dstPtr->byteIndex += segPtr->size;\n\t    oldPtr = segPtr;\n\t}\n\tsegPtr = oldPtr;\n\tsegSize = segPtr->size;\n    }\n\n  backwardCharDone:\n    if (infoPtr != NULL) {\n\tTkTextFreeElideInfo(infoPtr);\n\tTcl_Free(infoPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StartEnd --\n *\n *\tThis function handles modifiers like \"wordstart\" and \"lineend\" to\n *\tadjust indices forwards or backwards.\n *\n * Results:\n *\tIf the modifier is successfully parsed then the return value is the\n *\taddress of the first character after the modifier, and *indexPtr is\n *\tupdated to reflect the modifier. If there is a syntax error in the\n *\tmodifier then NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const char *\nStartEnd(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    const char *string,\t\t/* String to parse for additional info about\n\t\t\t\t * modifier (count and units). Points to first\n\t\t\t\t * character of modifier word. */\n    TkTextIndex *indexPtr)\t/* Index to modify based on string. */\n{\n    const char *p;\n    size_t length;\n    TkTextSegment *segPtr;\n    indexModifier modifier;\n\n    /*\n     * Find the end of the modifier word.\n     */\n\n    for (p = string; isalnum(UCHAR(*p)); p++) {\n\t/* Empty loop body. */\n    }\n\n    length = p-string;\n    if ((*string == 'd') &&\n\t    (strncmp(string, \"display\", (length > 7 ? 7 : length)) == 0)) {\n\tmodifier = TKINDEX_DISPLAY;\n\tif (length > 7) {\n\t    p -= (length - 7);\n\t}\n    } else if ((*string == 'a') &&\n\t    (strncmp(string, \"any\", (length > 3 ? 3 : length)) == 0)) {\n\tmodifier = TKINDEX_ANY;\n\tif (length > 3) {\n\t    p -= (length - 3);\n\t}\n    } else {\n\tmodifier = TKINDEX_NONE;\n    }\n\n    /*\n     * If we had a modifier, which we interpreted ok, so now forward to the\n     * actual units.\n     */\n\n    if (modifier != TKINDEX_NONE) {\n\twhile (isspace(UCHAR(*p))) {\n\t    p++;\n\t}\n\tstring = p;\n\twhile ((*p!='\\0') && !isspace(UCHAR(*p)) && (*p!='+') && (*p!='-')) {\n\t    p++;\n\t}\n\tlength = p - string;\n    }\n\n    if ((*string == 'l') && (strncmp(string, \"lineend\", length) == 0)\n\t    && (length >= 5)) {\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL);\n\t} else {\n\t    indexPtr->byteIndex = 0;\n\t    for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;\n\t\t    segPtr = segPtr->nextPtr) {\n\t\tindexPtr->byteIndex += segPtr->size;\n\t    }\n\n\t    /*\n\t     * We know '\\n' is encoded with a single byte index.\n\t     */\n\n\t    indexPtr->byteIndex -= sizeof(char);\n\t}\n    } else if ((*string == 'l') && (strncmp(string, \"linestart\", length) == 0)\n\t    && (length >= 5)) {\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);\n\t} else {\n\t    indexPtr->byteIndex = 0;\n\t}\n    } else if ((*string == 'w') && (strncmp(string, \"wordend\", length) == 0)\n\t    && (length >= 5)) {\n\tint firstChar = 1;\n\tTcl_Size offset;\n\n\t/*\n\t * If the current character isn't part of a word then just move\n\t * forward one character. Otherwise move forward until finding a\n\t * character that isn't part of a word and stop there.\n\t */\n\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,\n\t\t    COUNT_DISPLAY_INDICES);\n\t}\n\tsegPtr = TkTextIndexToSeg(indexPtr, &offset);\n\twhile (1) {\n\t    Tcl_Size chSize = 1;\n\n\t    if (segPtr->typePtr == &tkTextCharType) {\n\t\tint ch;\n\n\t\tchSize = Tcl_UtfToUniChar(segPtr->body.chars + offset, &ch);\n\t\tif (!Tcl_UniCharIsWordChar(ch)) {\n\t\t    break;\n\t\t}\n\t\tfirstChar = 0;\n\t    }\n\t    offset += chSize;\n\t    indexPtr->byteIndex += chSize;\n\t    if (offset >= segPtr->size) {\n\t\tsegPtr = TkTextIndexToSeg(indexPtr, &offset);\n\t    }\n\t}\n\tif (firstChar) {\n\t    if (modifier == TKINDEX_DISPLAY) {\n\t\tTkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,\n\t\t\tCOUNT_DISPLAY_INDICES);\n\t    } else {\n\t\tTkTextIndexForwChars(NULL, indexPtr, 1, indexPtr,\n\t\t\tCOUNT_INDICES);\n\t    }\n\t}\n    } else if ((*string == 'w') && (strncmp(string, \"wordstart\", length) == 0)\n\t    && (length >= 5)) {\n\tint firstChar = 1;\n\tTcl_Size offset;\n\n\tif (modifier == TKINDEX_DISPLAY) {\n\t    TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,\n\t\t    COUNT_DISPLAY_INDICES);\n\t}\n\n\t/*\n\t * Starting with the current character, look for one that's not part\n\t * of a word and keep moving backward until you find one. Then if the\n\t * character found wasn't the first one, move forward again one\n\t * position.\n\t */\n\n\tsegPtr = TkTextIndexToSeg(indexPtr, &offset);\n\twhile (1) {\n\t    Tcl_Size chSize = 1;\n\n\t    if (segPtr->typePtr == &tkTextCharType) {\n\n\t\tint ch;\n\t\tTcl_UtfToUniChar(segPtr->body.chars + offset, &ch);\n\t\tif (!Tcl_UniCharIsWordChar(ch)) {\n\t\t    break;\n\t\t}\n\t\tif (offset + 1 > 1) {\n\t\t    chSize = (segPtr->body.chars + offset\n\t\t\t    - Tcl_UtfPrev(segPtr->body.chars + offset,\n\t\t\t    segPtr->body.chars));\n\t\t}\n\t\tfirstChar = 0;\n\t    }\n\t    if (offset == 0) {\n\t\tif (indexPtr->byteIndex == 0) {\n\t\t    goto done;\n\t\t}\n\t\tif (modifier == TKINDEX_DISPLAY) {\n\t\t    TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr,\n\t\t\t    COUNT_DISPLAY_INDICES);\n\t\t} else {\n\t\t    TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr,\n\t\t\t    COUNT_INDICES);\n\t\t}\n\t    } else {\n\t\tindexPtr->byteIndex -= chSize;\n\t    }\n\t    offset -= chSize;\n\t    if (offset < 0) {\n\t\tsegPtr = TkTextIndexToSeg(indexPtr, &offset);\n\t    }\n\t}\n\n\tif (!firstChar) {\n\t    if (modifier == TKINDEX_DISPLAY) {\n\t\tTkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr,\n\t\t\tCOUNT_DISPLAY_INDICES);\n\t    } else {\n\t\tTkTextIndexForwChars(NULL, indexPtr, 1, indexPtr,\n\t\t\tCOUNT_INDICES);\n\t    }\n\t}\n    } else {\n\treturn NULL;\n    }\n\n  done:\n    return p;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextMark.c",
    "content": "/*\n * tkTextMark.c --\n *\n *\tThis file contains the functions that implement marks for text\n *\twidgets.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkText.h\"\n#include \"tk3d.h\"\n\n/*\n * Macro that determines the size of a mark segment:\n */\n\n#define MSEG_SIZE (offsetof(TkTextSegment, body) \\\n\t+ sizeof(TkTextMark))\n\n/*\n * Forward references for functions defined in this file:\n */\n\nstatic Tcl_Obj *\tGetMarkName(TkText *textPtr, TkTextSegment *segPtr);\nstatic void\t\tInsertUndisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr);\nstatic int\t\tMarkDeleteProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\nstatic TkTextSegment *\tMarkCleanupProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic void\t\tMarkCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic int\t\tMarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr,\n\t\t\t    TkTextSegment *segPtr, Tcl_Size offset, int maxX,\n\t\t\t    Tcl_Size maxChars, int noCharsYet, TkWrapMode wrapMode,\n\t\t\t    TkTextDispChunk *chunkPtr);\nstatic int\t\tMarkFindNext(Tcl_Interp *interp,\n\t\t\t    TkText *textPtr, Tcl_Obj *markName);\nstatic int\t\tMarkFindPrev(Tcl_Interp *interp,\n\t\t\t    TkText *textPtr, Tcl_Obj *markName);\n\n\n/*\n * The following structures declare the \"mark\" segment types. There are\n * actually two types for marks, one with left gravity and one with right\n * gravity. They are identical except for their gravity property.\n */\n\nconst Tk_SegType tkTextRightMarkType = {\n    \"mark\",\t\t\t/* name */\n    0,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    MarkDeleteProc,\t\t/* deleteProc */\n    MarkCleanupProc,\t\t/* cleanupProc */\n    NULL,\t\t\t/* lineChangeProc */\n    MarkLayoutProc,\t\t/* layoutProc */\n    MarkCheckProc\t\t/* checkProc */\n};\n\nconst Tk_SegType tkTextLeftMarkType = {\n    \"mark\",\t\t\t/* name */\n    1,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    MarkDeleteProc,\t\t/* deleteProc */\n    MarkCleanupProc,\t\t/* cleanupProc */\n    NULL,\t\t\t/* lineChangeProc */\n    MarkLayoutProc,\t\t/* layoutProc */\n    MarkCheckProc\t\t/* checkProc */\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextMarkCmd --\n *\n *\tThis function is invoked to process the \"mark\" options of the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextMarkCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"mark\". */\n{\n    Tcl_HashEntry *hPtr;\n    TkTextSegment *markPtr;\n    Tcl_HashSearch search;\n    TkTextIndex index;\n    const Tk_SegType *newTypePtr;\n    int optionIndex;\n    static const char *const markOptionStrings[] = {\n\t\"gravity\", \"names\", \"next\", \"previous\", \"set\", \"unset\", NULL\n    };\n    enum markOptions {\n\tMARK_GRAVITY, MARK_NAMES, MARK_NEXT, MARK_PREVIOUS, MARK_SET,\n\tMARK_UNSET\n    };\n\n    if (objc + 1 < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], markOptionStrings,\n\t    sizeof(char *), \"mark option\", 0, &optionIndex) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum markOptions) optionIndex) {\n    case MARK_GRAVITY: {\n\tchar c;\n\tTcl_Size length;\n\tconst char *str;\n\n\tif (objc < 4 || objc > 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"markName ?gravity?\");\n\t    return TCL_ERROR;\n\t}\n\tstr = Tcl_GetStringFromObj(objv[3], &length);\n\tif (length == 6 && !strcmp(str, \"insert\")) {\n\t    markPtr = textPtr->insertMarkPtr;\n\t} else if (length == 7 && !strcmp(str, \"current\")) {\n\t    markPtr = textPtr->currentMarkPtr;\n\t} else {\n\t    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, str);\n\t    if (hPtr == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"there is no mark named \\\"%s\\\"\", str));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TEXT_MARK\", str,\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    markPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n\t}\n\tif (objc == 4) {\n\t    const char *typeStr;\n\n\t    if (markPtr->typePtr == &tkTextRightMarkType) {\n\t\ttypeStr = \"right\";\n\t    } else {\n\t\ttypeStr = \"left\";\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, TCL_INDEX_NONE));\n\t    return TCL_OK;\n\t}\n\tstr = Tcl_GetStringFromObj(objv[4],&length);\n\tc = str[0];\n\tif ((c == 'l') && (strncmp(str, \"left\", length) == 0)) {\n\t    newTypePtr = &tkTextLeftMarkType;\n\t} else if ((c == 'r') &&\n\t\t(strncmp(str, \"right\", length) == 0)) {\n\t    newTypePtr = &tkTextRightMarkType;\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad mark gravity \\\"%s\\\": must be left or right\", str));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"MARK_GRAVITY\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTkTextMarkSegToIndex(textPtr, markPtr, &index);\n\tTkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);\n\tmarkPtr->typePtr = newTypePtr;\n\tTkBTreeLinkSegment(markPtr, &index);\n\tbreak;\n    }\n    case MARK_NAMES: {\n\tTcl_Obj *resultObj;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tTcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t\"insert\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t\"current\", TCL_INDEX_NONE));\n\tfor (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->markTable,\n\t\t&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),\n\t\t    -1));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    }\n    case MARK_NEXT:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t    return TCL_ERROR;\n\t}\n\treturn MarkFindNext(interp, textPtr, objv[3]);\n    case MARK_PREVIOUS:\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index\");\n\t    return TCL_ERROR;\n\t}\n\treturn MarkFindPrev(interp, textPtr, objv[3]);\n    case MARK_SET:\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"markName index\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTkTextSetMark(textPtr, Tcl_GetString(objv[3]), &index);\n\treturn TCL_OK;\n    case MARK_UNSET: {\n\tTcl_Size i;\n\n\tfor (i = 3; i < objc; i++) {\n\t    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable,\n\t\t    Tcl_GetString(objv[i]));\n\t    if (hPtr != NULL) {\n\t\tmarkPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n\n\t\t/*\n\t\t * Special case not needed with peer widgets.\n\t\t */\n\n\t\tif ((markPtr == textPtr->insertMarkPtr)\n\t\t\t|| (markPtr == textPtr->currentMarkPtr)) {\n\t\t    continue;\n\t\t}\n\t\tTkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);\n\t\tTcl_DeleteHashEntry(hPtr);\n\t\tTcl_Free(markPtr);\n\t    }\n\t}\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextSetMark --\n *\n *\tSet a mark to a particular position, creating a new mark if one\n *\tdoesn't already exist.\n *\n * Results:\n *\tThe return value is a pointer to the mark that was just set.\n *\n * Side effects:\n *\tA new mark is created, or an existing mark is moved.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextSegment *\nTkTextSetMark(\n    TkText *textPtr,\t\t/* Text widget in which to create mark. */\n    const char *name,\t\t/* Name of mark to set. */\n    TkTextIndex *indexPtr)\t/* Where to set mark. */\n{\n    Tcl_HashEntry *hPtr = NULL;\n    TkTextSegment *markPtr;\n    TkTextIndex insertIndex;\n    int isNew, widgetSpecific;\n\n    if (!strcmp(name, \"insert\")) {\n\twidgetSpecific = 1;\n\tmarkPtr = textPtr->insertMarkPtr;\n\tisNew = (markPtr == NULL ? 1 : 0);\n    } else if (!strcmp(name, \"current\")) {\n\twidgetSpecific = 2;\n\tmarkPtr = textPtr->currentMarkPtr;\n\tisNew = (markPtr == NULL ? 1 : 0);\n    } else {\n\twidgetSpecific = 0;\n\thPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->markTable, name,\n\t\t&isNew);\n\tmarkPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n    }\n    if (!isNew) {\n\t/*\n\t * If this is the insertion point that's being moved, be sure to force\n\t * a display update at the old position. Also, don't let the insertion\n\t * cursor be after the final newline of the file.\n\t */\n\n\tif (markPtr == textPtr->insertMarkPtr) {\n\t    TkTextIndex index, index2;\n\t    Tcl_Size nblines;\n\n\t    TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n\t    TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);\n\n\t    /*\n\t     * While we wish to redisplay, no heights have changed, so no need\n\t     * to call TkTextInvalidateLineMetrics.\n\t     */\n\n\t    TkTextChanged(NULL, textPtr, &index, &index2);\n\n\t    /*\n\t     * The number of lines in the widget is zero if and only if it is\n\t     * a partial peer with -startline == -endline, i.e. an empty\n\t     * peer. In this case the mark shall be set exactly at the given\n\t     * index, and not one character backwards (bug 3487407).\n\t     */\n\n\t    nblines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);\n\t    if ((TkBTreeLinesTo(textPtr, indexPtr->linePtr) == nblines)\n\t\t    && (nblines > 0))  {\n\t\tTkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex,\n\t\t\tCOUNT_INDICES);\n\t\tindexPtr = &insertIndex;\n\t    }\n\t}\n\tTkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);\n    } else {\n\tmarkPtr = (TkTextSegment *)Tcl_Alloc(MSEG_SIZE);\n\tmarkPtr->typePtr = &tkTextRightMarkType;\n\tmarkPtr->size = 0;\n\tmarkPtr->body.mark.textPtr = textPtr;\n\tmarkPtr->body.mark.linePtr = indexPtr->linePtr;\n\tmarkPtr->body.mark.hPtr = hPtr;\n\tif (widgetSpecific == 0) {\n\t    Tcl_SetHashValue(hPtr, markPtr);\n\t} else if (widgetSpecific == 1) {\n\t    textPtr->insertMarkPtr = markPtr;\n\t} else {\n\t    textPtr->currentMarkPtr = markPtr;\n\t}\n    }\n    TkBTreeLinkSegment(markPtr, indexPtr);\n\n    /*\n     * If the mark is the insertion cursor, then update the screen at the\n     * mark's new location.\n     */\n\n    if (markPtr == textPtr->insertMarkPtr) {\n\tTkTextIndex index2;\n\n\tTkTextIndexForwChars(NULL, indexPtr, 1, &index2, COUNT_INDICES);\n\n\t/*\n\t * While we wish to redisplay, no heights have changed, so no need to\n\t * call TkTextInvalidateLineMetrics\n\t */\n\n\tTkTextChanged(NULL, textPtr, indexPtr, &index2);\n    }\n    return markPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextMarkSegToIndex --\n *\n *\tGiven a segment that is a mark, create an index that refers to the\n *\tnext text character (or other text segment with non-zero size) after\n *\tthe mark.\n *\n * Results:\n *\t*IndexPtr is filled in with index information.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextMarkSegToIndex(\n    TkText *textPtr,\t\t/* Text widget containing mark. */\n    TkTextSegment *markPtr,\t/* Mark segment. */\n    TkTextIndex *indexPtr)\t/* Index information gets stored here.  */\n{\n    TkTextSegment *segPtr;\n\n    indexPtr->tree = textPtr->sharedTextPtr->tree;\n    indexPtr->linePtr = markPtr->body.mark.linePtr;\n    indexPtr->byteIndex = 0;\n    for (segPtr = indexPtr->linePtr->segPtr; segPtr != markPtr;\n\t    segPtr = segPtr->nextPtr) {\n\tindexPtr->byteIndex += segPtr->size;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextMarkNameToIndex --\n *\n *\tGiven the name of a mark, return an index corresponding to the mark\n *\tname.\n *\n * Results:\n *\tThe return value is TCL_OK if \"name\" exists as a mark in the text\n *\twidget and is located within its -startline/-endline range. In this\n *\tcase *indexPtr is filled in with the next segment who is after the\n *\tmark whose size is non-zero. TCL_ERROR is returned if the mark\n *\tdoesn't exist in the text widget, or if it is out of its -startline/\n *\t-endline range. In this latter case *indexPtr still contains valid\n *\tinformation, in particular TkTextMarkNameToIndex called with the\n *\t\"insert\" or \"current\" mark name may return TCL_ERROR, but *indexPtr\n *\tcontains the correct index of this mark before -startline or after\n *\t-endline.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextMarkNameToIndex(\n    TkText *textPtr,\t\t/* Text widget containing mark. */\n    const char *name,\t\t/* Name of mark. */\n    TkTextIndex *indexPtr)\t/* Index information gets stored here. */\n{\n    TkTextSegment *segPtr;\n\n    if (textPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    if (!strcmp(name, \"insert\")) {\n\tsegPtr = textPtr->insertMarkPtr;\n    } else if (!strcmp(name, \"current\")) {\n\tsegPtr = textPtr->currentMarkPtr;\n    } else {\n\tTcl_HashEntry *hPtr =\n\t\tTcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, name);\n\n\tif (hPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tsegPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n    }\n    TkTextMarkSegToIndex(textPtr, segPtr, indexPtr);\n\n    /*\n     * If indexPtr refers to somewhere outside the -startline/-endline\n     * range limits of the widget, error out since the mark indeed is not\n     * reachable from this text widget (it may be reachable from a peer)\n     * (bug 1630271).\n     */\n\n    if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, true) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkDeleteProc --\n *\n *\tThis function is invoked by the text B-tree code whenever a mark lies\n *\tin a range of characters being deleted.\n *\n * Results:\n *\tReturns 1 to indicate that deletion has been rejected.\n *\n * Side effects:\n *\tNone (even if the whole tree is being deleted we don't free up the\n *\tmark; it will be done elsewhere).\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMarkDeleteProc(\n    TCL_UNUSED(TkTextSegment *),\t/* Segment being deleted. */\n    TCL_UNUSED(TkTextLine *),\t/* Line containing segment. */\n    TCL_UNUSED(int))\t\t/* Non-zero means the entire tree is being\n\t\t\t\t * deleted, so everything must get cleaned\n\t\t\t\t * up. */\n{\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkCleanupProc --\n *\n *\tThis function is invoked by the B-tree code whenever a mark segment is\n *\tmoved from one line to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe linePtr field of the segment gets updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nMarkCleanupProc(\n    TkTextSegment *markPtr,\t/* Mark segment that's being moved. */\n    TkTextLine *linePtr)\t/* Line that now contains segment. */\n{\n    markPtr->body.mark.linePtr = linePtr;\n    return markPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkLayoutProc --\n *\n *\tThis function is the \"layoutProc\" for mark segments.\n *\n * Results:\n *\tIf the mark isn't the insertion cursor then the return value is -1 to\n *\tindicate that this segment shouldn't be displayed. If the mark is the\n *\tinsertion character then 1 is returned and the chunkPtr structure is\n *\tfilled in.\n *\n * Side effects:\n *\tNone, except for filling in chunkPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMarkLayoutProc(\n    TkText *textPtr,\t\t/* Text widget being layed out. */\n    TCL_UNUSED(TkTextIndex *),\t/* Identifies first character in chunk. */\n    TkTextSegment *segPtr,\t/* Segment corresponding to indexPtr. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Offset within segPtr corresponding to\n\t\t\t\t * indexPtr (always 0). */\n    TCL_UNUSED(int),\t\t\t/* Chunk must not occupy pixels at this\n\t\t\t\t * position or higher. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Chunk must not include more than this many\n\t\t\t\t * characters. */\n    TCL_UNUSED(int),\t\t/* Non-zero means no characters have been\n\t\t\t\t * assigned to this line yet. */\n    TCL_UNUSED(TkWrapMode),\t/* Not used. */\n    TkTextDispChunk *chunkPtr)\n\t\t\t\t/* Structure to fill in with information about\n\t\t\t\t * this chunk. The x field has already been\n\t\t\t\t * set by the caller. */\n{\n    if (segPtr != textPtr->insertMarkPtr) {\n\treturn -1;\n    }\n\n    chunkPtr->displayProc = TkTextInsertDisplayProc;\n    chunkPtr->undisplayProc = InsertUndisplayProc;\n    chunkPtr->measureProc = NULL;\n    chunkPtr->bboxProc = NULL;\n    chunkPtr->numBytes = 0;\n    chunkPtr->minAscent = 0;\n    chunkPtr->minDescent = 0;\n    chunkPtr->minHeight = 0;\n    chunkPtr->width = 0;\n\n    /*\n     * Note: can't break a line after the insertion cursor: this prevents the\n     * insertion cursor from being stranded at the end of a line.\n     */\n\n    chunkPtr->breakIndex = -1;\n    chunkPtr->clientData = textPtr;\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextInsertDisplayProc --\n *\n *\tThis function is called to display the insertion cursor.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGraphics are drawn.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextInsertDisplayProc(\n    TkText *textPtr,\t\t/* The current text widget. */\n    TCL_UNUSED(TkTextDispChunk *),\t/* Chunk that is to be drawn. */\n    int x,\t\t\t/* X-position in dst at which to draw this\n\t\t\t\t * chunk (may differ from the x-position in\n\t\t\t\t * the chunk because of scrolling). */\n    int y,\t\t\t/* Y-position at which to draw this chunk in\n\t\t\t\t * dst (x-position is in the chunk itself). */\n    int height,\t\t\t/* Total height of line. */\n    TCL_UNUSED(int),\t\t/* Offset of baseline from y. */\n    TCL_UNUSED(Display *),\t\t/* Display to use for drawing. */\n    Drawable dst,\t\t/* Pixmap or window in which to draw chunk. */\n    int screenY)\t\t/* Y-coordinate in text window that\n\t\t\t\t * corresponds to y. */\n{\n    /*\n     * We have no need for the clientData.\n     */\n\n    /* TkText *textPtr = chunkPtr->clientData; */\n    TkTextIndex index;\n    int halfWidth, insertWidth, insertBorderWidth;\n    int rightSideWidth;\n    int ix = 0, iy = 0, iw = 0, ih = 0, charWidth = 0, cursorWidth = 0;\n\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertWidthObj, &insertWidth);\n    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, textPtr->insertBorderWidthObj, &insertBorderWidth);\n    halfWidth = insertWidth/2;\n    if (textPtr->insertCursorType) {\n\tTkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index);\n\tTkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih, &charWidth,\n\t\t&cursorWidth);\n\trightSideWidth = charWidth + halfWidth;\n\tcharWidth = cursorWidth;\n    } else {\n\trightSideWidth = halfWidth;\n    }\n\n    if ((x + rightSideWidth) < 0) {\n\t/*\n\t * The insertion cursor is off-screen. Indicate caret at 0,0 and\n\t * return.\n\t */\n\n\tTk_SetCaretPos(textPtr->tkwin, 0, 0, height);\n\treturn;\n    }\n\n    Tk_SetCaretPos(textPtr->tkwin, x - halfWidth, screenY, height);\n\n    /*\n     * As a special hack to keep the cursor visible on mono displays (or\n     * anywhere else that the selection and insertion cursors have the same\n     * color) write the default background in the cursor area (instead of\n     * nothing) when the cursor isn't on. Otherwise the selection might hide\n     * the cursor.\n     */\n\n    if (textPtr->flags & GOT_FOCUS) {\n\tif (textPtr->flags & INSERT_ON) {\n\t    Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,\n\t\t    x - halfWidth, y, charWidth + insertWidth,\n\t\t    height, insertBorderWidth, TK_RELIEF_RAISED);\n\t} else if (textPtr->selBorder == textPtr->insertBorder) {\n\t    Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->border,\n\t\t    x - halfWidth, y, charWidth + insertWidth,\n\t\t    height, 0, TK_RELIEF_FLAT);\n\t}\n    } else if (textPtr->insertUnfocussed == TK_TEXT_INSERT_NOFOCUS_HOLLOW) {\n\tif (insertBorderWidth > 0) {\n\t    Tk_Draw3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,\n\t\t    x - halfWidth, y, charWidth + insertWidth,\n\t\t    height, insertBorderWidth, TK_RELIEF_RAISED);\n\t} else {\n\t    /*\n\t     * Hack to work around the fact that a \"solid\" border always\n\t     * paints in black.\n\t     */\n\n\t    TkBorder *borderPtr = (TkBorder *) textPtr->insertBorder;\n\n\t    XDrawRectangle(Tk_Display(textPtr->tkwin), dst, borderPtr->bgGC,\n\t\t    x - halfWidth, y, charWidth + insertWidth - 1,\n\t\t    height - 1);\n\t}\n    } else if (textPtr->insertUnfocussed == TK_TEXT_INSERT_NOFOCUS_SOLID) {\n\tTk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder,\n\t\tx - halfWidth, y, charWidth + insertWidth, height,\n\t\tinsertBorderWidth, TK_RELIEF_RAISED);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * InsertUndisplayProc --\n *\n *\tThis function is called when the insertion cursor is no longer at a\n *\tvisible point on the display. It does nothing right now.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nInsertUndisplayProc(\n    TCL_UNUSED(TkText *),\t\t/* Overall information about text widget. */\n    TCL_UNUSED(TkTextDispChunk *))\t/* Chunk that is about to be freed. */\n{\n    return;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkCheckProc --\n *\n *\tThis function is invoked by the B-tree code to perform consistency\n *\tchecks on mark segments.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe function panics if it detects anything wrong with\n *\tthe mark.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMarkCheckProc(\n    TkTextSegment *markPtr,\t/* Segment to check. */\n    TkTextLine *linePtr)\t/* Line containing segment. */\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n\n    if (markPtr->body.mark.linePtr != linePtr) {\n\tTcl_Panic(\"MarkCheckProc: markPtr->body.mark.linePtr bogus\");\n    }\n\n    /*\n     * These two marks are not in the hash table\n     */\n\n    if (markPtr->body.mark.textPtr->insertMarkPtr == markPtr) {\n\treturn;\n    }\n    if (markPtr->body.mark.textPtr->currentMarkPtr == markPtr) {\n\treturn;\n    }\n\n    /*\n     * Make sure that the mark is still present in the text's mark hash table.\n     */\n\n    for (hPtr = Tcl_FirstHashEntry(\n\t    &markPtr->body.mark.textPtr->sharedTextPtr->markTable,\n\t    &search); hPtr != markPtr->body.mark.hPtr;\n\t    hPtr = Tcl_NextHashEntry(&search)) {\n\tif (hPtr == NULL) {\n\t    Tcl_Panic(\"MarkCheckProc couldn't find hash table entry for mark\");\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkFindNext --\n *\n *\tThis function searches forward for the next mark.\n *\n * Results:\n *\tA standard Tcl result, which is a mark name or an empty string.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMarkFindNext(\n    Tcl_Interp *interp,\t\t/* For error reporting */\n    TkText *textPtr,\t\t/* The widget */\n    Tcl_Obj *obj)\t\t\t/* The starting index or mark name */\n{\n    TkTextIndex index;\n    Tcl_HashEntry *hPtr;\n    TkTextSegment *segPtr;\n    Tcl_Size offset;\n    const char *string = Tcl_GetString(obj);\n\n    if (!strcmp(string, \"insert\")) {\n\tsegPtr = textPtr->insertMarkPtr;\n\tTkTextMarkSegToIndex(textPtr, segPtr, &index);\n\tsegPtr = segPtr->nextPtr;\n    } else if (!strcmp(string, \"current\")) {\n\tsegPtr = textPtr->currentMarkPtr;\n\tTkTextMarkSegToIndex(textPtr, segPtr, &index);\n\tsegPtr = segPtr->nextPtr;\n    } else {\n\thPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);\n\tif (hPtr != NULL) {\n\t    /*\n\t     * If given a mark name, return the next mark in the list of\n\t     * segments, even if it happens to be at the same character\n\t     * position.\n\t     */\n\n\t    segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n\t    TkTextMarkSegToIndex(textPtr, segPtr, &index);\n\t    segPtr = segPtr->nextPtr;\n\t} else {\n\t    /*\n\t     * For non-mark name indices we want to return any marks that are\n\t     * right at the index.\n\t     */\n\n\t    if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    for (offset = 0, segPtr = index.linePtr->segPtr;\n\t\t    segPtr != NULL && offset < index.byteIndex;\n\t\t    offset += segPtr->size, segPtr = segPtr->nextPtr) {\n\t\t/* Empty loop body */ ;\n\t    }\n\t}\n    }\n\n    while (1) {\n\t/*\n\t * segPtr points at the first possible candidate, or NULL if we ran\n\t * off the end of the line.\n\t */\n\n\tfor ( ; segPtr != NULL ; segPtr = segPtr->nextPtr) {\n\t    if (segPtr->typePtr == &tkTextRightMarkType ||\n\t\t    segPtr->typePtr == &tkTextLeftMarkType) {\n\t\tTcl_Obj *markName = GetMarkName(textPtr, segPtr);\n\n\t\tif (markName != NULL) {\n\t\t    Tcl_SetObjResult(interp, markName);\n\t\t    return TCL_OK;\n\t\t}\n\t    }\n\t}\n\tindex.linePtr = TkBTreeNextLine(textPtr, index.linePtr);\n\tif (index.linePtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tindex.byteIndex = 0;\n\tsegPtr = index.linePtr->segPtr;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MarkFindPrev --\n *\n *\tThis function searches backwards for the previous mark.\n *\n * Results:\n *\tA standard Tcl result, which is a mark name or an empty string.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nMarkFindPrev(\n    Tcl_Interp *interp,\t\t/* For error reporting */\n    TkText *textPtr,\t\t/* The widget */\n    Tcl_Obj *obj)\t\t\t/* The starting index or mark name */\n{\n    TkTextIndex index;\n    Tcl_HashEntry *hPtr;\n    TkTextSegment *segPtr, *seg2Ptr, *prevPtr;\n    Tcl_Size offset;\n    const char *string = Tcl_GetString(obj);\n\n    if (!strcmp(string, \"insert\")) {\n\tsegPtr = textPtr->insertMarkPtr;\n\tTkTextMarkSegToIndex(textPtr, segPtr, &index);\n    } else if (!strcmp(string, \"current\")) {\n\tsegPtr = textPtr->currentMarkPtr;\n\tTkTextMarkSegToIndex(textPtr, segPtr, &index);\n    } else {\n\thPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);\n\tif (hPtr != NULL) {\n\t    /*\n\t     * If given a mark name, return the previous mark in the list of\n\t     * segments, even if it happens to be at the same character\n\t     * position.\n\t     */\n\n\t    segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n\t    TkTextMarkSegToIndex(textPtr, segPtr, &index);\n\t} else {\n\t    /*\n\t     * For non-mark name indices we do not return any marks that are\n\t     * right at the index.\n\t     */\n\n\t    if (TkTextGetObjIndex(interp, textPtr, obj, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    for (offset = 0, segPtr = index.linePtr->segPtr;\n\t\t    segPtr != NULL && offset < index.byteIndex;\n\t\t    offset += segPtr->size, segPtr = segPtr->nextPtr) {\n\t\t/* Empty loop body */\n\t    }\n\t}\n    }\n\n    while (1) {\n\t/*\n\t * segPtr points just past the first possible candidate, or at the\n\t * beginning of the line.\n\t */\n\n\tfor (prevPtr = NULL, seg2Ptr = index.linePtr->segPtr;\n\t\tseg2Ptr != NULL && seg2Ptr != segPtr;\n\t\tseg2Ptr = seg2Ptr->nextPtr) {\n\t    if (seg2Ptr->typePtr == &tkTextRightMarkType ||\n\t\t    seg2Ptr->typePtr == &tkTextLeftMarkType) {\n\t\tif (seg2Ptr->body.mark.hPtr == NULL) {\n\t\t    if (seg2Ptr != textPtr->currentMarkPtr &&\n\t\t\t    seg2Ptr != textPtr->insertMarkPtr) {\n\t\t\t/*\n\t\t\t * This is an insert or current mark from a\n\t\t\t * peer of textPtr.\n\t\t\t */\n\t\t\tcontinue;\n\t\t    }\n\t\t}\n\t\tprevPtr = seg2Ptr;\n\t    }\n\t}\n\tif (prevPtr != NULL) {\n\t    Tcl_Obj *markName = GetMarkName(textPtr, prevPtr);\n\n\t    if (markName != NULL) {\n\t\tTcl_SetObjResult(interp, markName);\n\t\treturn TCL_OK;\n\t    }\n\t}\n\tindex.linePtr = TkBTreePreviousLine(textPtr, index.linePtr);\n\tif (index.linePtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tsegPtr = NULL;\n    }\n}\n\f\n/*\n * ------------------------------------------------------------------------\n *\n * GetMarkName --\n *\tReturns the name of the mark that is the given text segment, or NULL\n *\tif it is unnamed (i.e., a widget-specific mark that isn't \"current\" or\n *\t\"insert\").\n *\n * ------------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetMarkName(\n    TkText *textPtr,\n    TkTextSegment *segPtr)\n{\n    const char *markName;\n\n    if (segPtr == textPtr->currentMarkPtr) {\n\tmarkName = \"current\";\n    } else if (segPtr == textPtr->insertMarkPtr) {\n\tmarkName = \"insert\";\n    } else if (segPtr->body.mark.hPtr == NULL) {\n\t/*\n\t * Ignore widget-specific marks for the other widgets. This is either\n\t * an insert or a current mark (markPtr->body.mark.hPtr actually\n\t * receives NULL for these marks in TkTextSetMark). The insert and\n\t * current marks for textPtr having already been tested above, the\n\t * current segment is an insert or current mark from a peer of\n\t * textPtr, which we don't want to return.\n\t */\n\n\treturn NULL;\n    } else {\n\tmarkName = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,\n\t\tsegPtr->body.mark.hPtr);\n    }\n    return Tcl_NewStringObj(markName, -1);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextTag.c",
    "content": "/*\n * tkTextTag.c --\n *\n *\tThis module implements the \"tag\" subcommand of the widget command for\n *\ttext widgets, plus most of the other high-level functions related to\n *\ttags.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkText.h\"\n#include \"default.h\"\n\nstatic const Tk_OptionSpec tagOptionSpecs[] = {\n    {TK_OPTION_BORDER, \"-background\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BITMAP, \"-bgstipple\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-borderwidth\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, borderWidthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-elide\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, elide),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BITMAP, \"-fgstipple\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_FONT, \"-font\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-foreground\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, justify), TK_OPTION_NULL_OK, 0,0},\n    {TK_OPTION_PIXELS, \"-lmargin1\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, lMargin1Obj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_PIXELS, \"-lmargin2\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, lMargin2Obj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_BORDER, \"-lmargincolor\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-offset\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, offsetObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK|TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-overstrike\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrike),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-overstrikefg\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrikeColor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_RELIEF, \"-relief\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, relief), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-rmargin\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, rMarginObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0,0},\n    {TK_OPTION_BORDER, \"-rmargincolor\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_BORDER, \"-selectbackground\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-selectforeground\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-spacing1\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, spacing1Obj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_PIXELS, \"-spacing2\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, spacing2Obj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_PIXELS, \"-spacing3\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, spacing3Obj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_STRING, \"-tabs\", NULL, NULL,\n\tNULL, offsetof(TkTextTag, tabStringPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-tabstyle\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, tabStyle),\n\tTK_OPTION_NULL_OK|TK_OPTION_ENUM_VAR, tkTextTabStyleStrings, 0},\n    {TK_OPTION_BOOLEAN, \"-underline\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, underline),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_COLOR, \"-underlinefg\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, underlineColor),\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-wrap\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextTag, wrapMode),\n\tTK_OPTION_NULL_OK|TK_OPTION_ENUM_VAR, tkTextWrapStrings, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tChangeTagPriority(TkText *textPtr, TkTextTag *tagPtr,\n\t\t\t    Tcl_Size prio);\nstatic TkTextTag *\tFindTag(Tcl_Interp *interp, TkText *textPtr,\n\t\t\t    Tcl_Obj *tagName);\nstatic void\t\tSortTags(Tcl_Size numTags, TkTextTag **tagArrayPtr);\nstatic int\t\tTagSortProc(const void *first, const void *second);\nstatic void\t\tTagBindEvent(TkText *textPtr, XEvent *eventPtr,\n\t\t\t    Tcl_Size numTags, TkTextTag **tagArrayPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextTagCmd --\n *\n *\tThis function is invoked to process the \"tag\" options of the widget\n *\tcommand for text widgets. See the user documentation for details on\n *\twhat it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextTagCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"tag\". */\n{\n    static const char *const tagOptionStrings[] = {\n\t\"add\", \"bind\", \"cget\", \"configure\", \"delete\", \"lower\", \"names\",\n\t\"nextrange\", \"prevrange\", \"raise\", \"ranges\", \"remove\", NULL\n    };\n    enum tagOptions {\n\tTAG_ADD, TAG_BIND, TAG_CGET, TAG_CONFIGURE, TAG_DELETE, TAG_LOWER,\n\tTAG_NAMES, TAG_NEXTRANGE, TAG_PREVRANGE, TAG_RAISE, TAG_RANGES,\n\tTAG_REMOVE\n    } optionIndex;\n    Tcl_Size i;\n    TkTextTag *tagPtr;\n    TkTextIndex index1, index2;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], tagOptionStrings,\n\t    sizeof(char *), \"tag option\", 0, &optionIndex) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch (optionIndex) {\n    case TAG_ADD:\n    case TAG_REMOVE: {\n\tbool addTag = optionIndex == TAG_ADD;\n\n\tif (objc < 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv,\n\t\t    \"tagName index1 ?index2 index1 index2 ...?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL);\n\tif (tagPtr->elide > 0) {\n\t\t/*\n\t\t* Indices are potentially obsolete after adding or removing\n\t\t* elided character ranges, especially indices having \"display\"\n\t\t* or \"any\" submodifier, therefore increase the epoch.\n\t\t*/\n\t\ttextPtr->sharedTextPtr->stateEpoch++;\n\t}\n\tfor (i = 4; i < objc; i += 2) {\n\t    if (TkTextGetObjIndex(interp, textPtr, objv[i],\n\t\t    &index1) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (objc > (i+1)) {\n\t\tif (TkTextGetObjIndex(interp, textPtr, objv[i+1],\n\t\t\t&index2) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (TkTextIndexCmp(&index1, &index2) >= 0) {\n\t\t    return TCL_OK;\n\t\t}\n\t    } else {\n\t\tindex2 = index1;\n\t\tTkTextIndexForwChars(NULL,&index2, 1, &index2, COUNT_INDICES);\n\t    }\n\n\t    if (tagPtr->affectsDisplay) {\n\t\tTkTextRedrawTag(textPtr->sharedTextPtr, NULL, &index1, &index2,\n\t\t\ttagPtr, !addTag);\n\t    } else {\n\t\t/*\n\t\t * Still need to trigger enter/leave events on tags that have\n\t\t * changed.\n\t\t */\n\n\t\tTkTextEventuallyRepick(textPtr);\n\t    }\n\t    if (TkBTreeTag(&index1, &index2, tagPtr, addTag)) {\n\t\t/*\n\t\t * If the tag is \"sel\", and we actually adjusted something\n\t\t * then grab the selection if we're supposed to export it and\n\t\t * don't already have it.\n\t\t *\n\t\t * Also, invalidate partially-completed selection retrievals.\n\t\t * We only need to check whether the tag is \"sel\" for this\n\t\t * textPtr (not for other peer widget's \"sel\" tags) because we\n\t\t * cannot reach this code path with a different widget's \"sel\"\n\t\t * tag.\n\t\t */\n\n\t\tif (tagPtr == textPtr->selTagPtr) {\n\t\t    /*\n\t\t     * Send an event that the selection changed. This is\n\t\t     * equivalent to:\n\t\t     *\t   event generate $textWidget <<Selection>>\n\t\t     */\n\n\t\t    TkTextSelectionEvent(textPtr);\n\n\t\t    if (addTag && textPtr->exportSelection\n\t\t\t    && (!Tcl_IsSafe(textPtr->interp))\n\t\t\t    && !(textPtr->flags & GOT_SELECTION)) {\n\t\t\tTk_OwnSelection(textPtr->tkwin, XA_PRIMARY,\n\t\t\t\tTkTextLostSelection, textPtr);\n\t\t\ttextPtr->flags |= GOT_SELECTION;\n\t\t    }\n\t\t    textPtr->abortSelections = true;\n\t\t}\n\t    }\n\t}\n\tbreak;\n    }\n    case TAG_BIND:\n\tif ((objc < 4) || (objc > 6)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName ?sequence? ?command?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL);\n\n\t/*\n\t * Make a binding table if the widget doesn't already have one.\n\t */\n\n\tif (textPtr->sharedTextPtr->bindingTable == NULL) {\n\t    textPtr->sharedTextPtr->bindingTable =\n\t\t    Tk_CreateBindingTable(interp);\n\t}\n\n\tif (objc == 6) {\n\t    int append = 0;\n\t    unsigned long mask;\n\t    const char *fifth = Tcl_GetString(objv[5]);\n\n\t    if (fifth[0] == 0) {\n\t\treturn Tk_DeleteBinding(interp,\n\t\t\ttextPtr->sharedTextPtr->bindingTable,\n\t\t\t(void *) tagPtr->name, Tcl_GetString(objv[4]));\n\t    }\n\t    if (fifth[0] == '+') {\n\t\tfifth++;\n\t\tappend = 1;\n\t    }\n\t    mask = Tk_CreateBinding(interp,\n\t\t    textPtr->sharedTextPtr->bindingTable,\n\t\t    (void *) tagPtr->name, Tcl_GetString(objv[4]), fifth,\n\t\t    append);\n\t    if (mask == 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask\n\t\t    |Button2MotionMask|Button3MotionMask|Button4MotionMask\n\t\t    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask\n\t\t    |EnterWindowMask|LeaveWindowMask|KeyPressMask\n\t\t    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {\n\t\tTk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable,\n\t\t\t(void *) tagPtr->name, Tcl_GetString(objv[4]));\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"requested illegal events; only key, button, motion,\"\n\t\t\t\" enter, leave, and virtual events may be used\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"TAG_BIND_EVENT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else if (objc == 5) {\n\t    const char *command;\n\n\t    command = Tk_GetBinding(interp,\n\t\t    textPtr->sharedTextPtr->bindingTable,\n\t\t    (void *) tagPtr->name, Tcl_GetString(objv[4]));\n\t    if (command == NULL) {\n\t\tconst char *string = Tcl_GetString(Tcl_GetObjResult(interp));\n\n\t\t/*\n\t\t * Ignore missing binding errors. This is a special hack that\n\t\t * relies on the error message returned by FindSequence in\n\t\t * tkBind.c.\n\t\t */\n\n\t\tif (string[0] != '\\0') {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tTcl_ResetResult(interp);\n\t    } else {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(command, TCL_INDEX_NONE));\n\t    }\n\t} else {\n\t    Tk_GetAllBindings(interp, textPtr->sharedTextPtr->bindingTable,\n\t\t    (void *) tagPtr->name);\n\t}\n\tbreak;\n    case TAG_CGET:\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"tag cget tagName option\");\n\t    return TCL_ERROR;\n\t} else {\n\t    Tcl_Obj *objPtr;\n\n\t    tagPtr = FindTag(interp, textPtr, objv[3]);\n\t    if (tagPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    objPtr = Tk_GetOptionValue(interp, tagPtr,\n\t\t    tagPtr->optionTable, objv[4], textPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    return TCL_OK;\n\t}\n\tbreak;\n    case TAG_CONFIGURE: {\n\tint newTag;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv,\n\t\t    \"tagName ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), &newTag);\n\tif (objc <= 5) {\n\t    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, tagPtr,\n\t\t    tagPtr->optionTable,\n\t\t    (objc == 5) ? objv[4] : NULL, textPtr->tkwin);\n\n\t    if (objPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    return TCL_OK;\n\t} else {\n\t    if (Tk_SetOptions(interp, tagPtr, tagPtr->optionTable,\n\t\t    objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Some of the configuration options, like -underline and\n\t     * -justify, require additional translation (this is needed\n\t     * because we need to distinguish a particular value of an option\n\t     * from \"unspecified\").\n\t     */\n\n\t    if (tagPtr->tabArrayPtr != NULL) {\n\t\tTcl_Free(tagPtr->tabArrayPtr);\n\t\ttagPtr->tabArrayPtr = NULL;\n\t    }\n\t    if (tagPtr->tabStringPtr != NULL) {\n\t\ttagPtr->tabArrayPtr =\n\t\t\tTkTextGetTabs(interp, textPtr->tkwin, tagPtr->tabStringPtr);\n\t\tif (tagPtr->tabArrayPtr == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    if (tagPtr->elide >= 0) {\n\t\t/*\n\t\t * Indices are potentially obsolete after changing -elide,\n\t\t * especially those computed with \"display\" or \"any\"\n\t\t * submodifier, therefore increase the epoch.\n\t\t */\n\n\t\ttextPtr->sharedTextPtr->stateEpoch++;\n\t    }\n\n\t    /*\n\t     * If the \"sel\" tag was changed, be sure to mirror information\n\t     * from the tag back into the text widget record. NOTE: we don't\n\t     * have to free up information in the widget record before\n\t     * overwriting it, because it was mirrored in the tag and hence\n\t     * freed when the tag field was overwritten.\n\t     */\n\n\t    if (tagPtr == textPtr->selTagPtr) {\n\t\tif (tagPtr->selBorder == NULL) {\n\t\t    textPtr->selBorder = tagPtr->border;\n\t\t} else {\n\t\t    textPtr->selBorder = tagPtr->selBorder;\n\t\t}\n\t\ttextPtr->selBorderWidthObj = tagPtr->borderWidthObj;\n\t\tif (tagPtr->selFgColor == NULL) {\n\t\t    textPtr->selFgColorPtr = tagPtr->fgColor;\n\t\t} else {\n\t\t    textPtr->selFgColorPtr = tagPtr->selFgColor;\n\t\t}\n\t    }\n\n\t    tagPtr->affectsDisplay = false;\n\t    tagPtr->affectsDisplayGeometry = false;\n\t    if ((tagPtr->elide >= 0)\n\t\t    || (tagPtr->tkfont != NULL)\n\t\t    || (tagPtr->justify != TK_JUSTIFY_NULL)\n\t\t    || (tagPtr->lMargin1Obj != NULL)\n\t\t    || (tagPtr->lMargin2Obj != NULL)\n\t\t    || (tagPtr->offsetObj != NULL)\n\t\t    || (tagPtr->rMarginObj != NULL)\n\t\t    || (tagPtr->spacing1Obj != NULL)\n\t\t    || (tagPtr->spacing2Obj != NULL)\n\t\t    || (tagPtr->spacing3Obj != NULL)\n\t\t    || (tagPtr->tabStringPtr != NULL)\n\t\t    || (tagPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR)\n\t\t    || (tagPtr->tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR)\n\t\t    || (tagPtr->wrapMode == TEXT_WRAPMODE_CHAR)\n\t\t    || (tagPtr->wrapMode == TEXT_WRAPMODE_NONE)\n\t\t    || (tagPtr->wrapMode == TEXT_WRAPMODE_WORD)) {\n\t\ttagPtr->affectsDisplay = true;\n\t\ttagPtr->affectsDisplayGeometry = true;\n\t    }\n\t    if ((tagPtr->border != NULL)\n\t\t    || (tagPtr->selBorder != NULL)\n\t\t    || (tagPtr->relief != TK_RELIEF_NULL)\n\t\t    || (tagPtr->bgStipple != None)\n\t\t    || (tagPtr->fgColor != NULL)\n\t\t    || (tagPtr->selFgColor != NULL)\n\t\t    || (tagPtr->fgStipple != None)\n\t\t    || (tagPtr->overstrike >= 0)\n\t\t    || (tagPtr->overstrikeColor != NULL)\n\t\t    || (tagPtr->underline >= 0)\n\t\t    || (tagPtr->underlineColor != NULL)\n\t\t    || (tagPtr->lMarginColor != NULL)\n\t\t    || (tagPtr->rMarginColor != NULL)) {\n\t\ttagPtr->affectsDisplay = true;\n\t    }\n\t    if (!newTag) {\n\t\t/*\n\t\t * This line is not necessary if this is a new tag, since it\n\t\t * can't possibly have been applied to anything yet.\n\t\t */\n\n\t\t/*\n\t\t * VMD: If this is the 'sel' tag, then we don't need to call\n\t\t * this for all peers, unless we actually want to synchronize\n\t\t * sel-style changes across the peers.\n\t\t */\n\n\t\tTkTextRedrawTag(textPtr->sharedTextPtr, NULL,\n\t\t\tNULL, NULL, tagPtr, true);\n\t    }\n\t    return TCL_OK;\n\t}\n\tbreak;\n    }\n    case TAG_DELETE: {\n\tTcl_HashEntry *hPtr;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName ?tagName ...?\");\n\t    return TCL_ERROR;\n\t}\n\tfor (i = 3; i < objc; i++) {\n\t    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable,\n\t\t    Tcl_GetString(objv[i]));\n\t    if (hPtr == NULL) {\n\t\t/*\n\t\t * Either this tag doesn't exist or it's the 'sel' tag (which\n\t\t * is not in the hash table). Either way we don't want to\n\t\t * delete it.\n\t\t */\n\n\t\tcontinue;\n\t    }\n\t    tagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);\n\t    if (tagPtr == textPtr->selTagPtr) {\n\t\tcontinue;\n\t    }\n\t    if (tagPtr->affectsDisplay) {\n\t\tTkTextRedrawTag(textPtr->sharedTextPtr, NULL,\n\t\t\tNULL, NULL, tagPtr, true);\n\t    }\n\t    TkTextDeleteTag(textPtr, tagPtr);\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n\tbreak;\n    }\n    case TAG_LOWER: {\n\tTkTextTag *tagPtr2;\n\tTcl_Size prio;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName ?belowThis?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = FindTag(interp, textPtr, objv[3]);\n\tif (tagPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 5) {\n\t    tagPtr2 = FindTag(interp, textPtr, objv[4]);\n\t    if (tagPtr2 == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (tagPtr->priority < tagPtr2->priority) {\n\t\tprio = tagPtr2->priority - 1;\n\t    } else {\n\t\tprio = tagPtr2->priority;\n\t    }\n\t} else {\n\t    prio = 0;\n\t}\n\tChangeTagPriority(textPtr, tagPtr, prio);\n\n\t/*\n\t * If this is the 'sel' tag, then we don't actually need to call this\n\t * for all peers.\n\t */\n\n\tTkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, true);\n\tbreak;\n    }\n    case TAG_NAMES: {\n\tTkTextTag **arrayPtr;\n\tTcl_Size arraySize;\n\tTcl_Obj *listObj;\n\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"?index?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 3) {\n\t    Tcl_HashSearch search;\n\t    Tcl_HashEntry *hPtr;\n\n\t    arrayPtr = (TkTextTag **)Tcl_Alloc(textPtr->sharedTextPtr->numTags\n\t\t    * sizeof(TkTextTag *));\n\t    for (i=0, hPtr = Tcl_FirstHashEntry(\n\t\t    &textPtr->sharedTextPtr->tagTable, &search);\n\t\t    hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {\n\t\tarrayPtr[i] = (TkTextTag *)Tcl_GetHashValue(hPtr);\n\t    }\n\n\t    /*\n\t     * The 'sel' tag is not in the hash table.\n\t     */\n\n\t    arrayPtr[i] = textPtr->selTagPtr;\n\t    arraySize = ++i;\n\t} else {\n\t    if (TkTextGetObjIndex(interp, textPtr, objv[3],\n\t\t    &index1) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    arrayPtr = TkBTreeGetTags(&index1, textPtr, &arraySize);\n\t    if (arrayPtr == NULL) {\n\t\treturn TCL_OK;\n\t    }\n\t}\n\n\tSortTags(arraySize, arrayPtr);\n\tlistObj = Tcl_NewListObj(0, NULL);\n\n\tfor (i = 0; i < arraySize; i++) {\n\t    tagPtr = arrayPtr[i];\n\t    Tcl_ListObjAppendElement(interp, listObj,\n\t\t    Tcl_NewStringObj(tagPtr->name,-1));\n\t}\n\tTcl_SetObjResult(interp, listObj);\n\tTcl_Free(arrayPtr);\n\tbreak;\n    }\n    case TAG_NEXTRANGE: {\n\tTkTextIndex last;\n\tTkTextSearch tSearch;\n\tchar position[TK_POS_CHARS];\n\tTcl_Obj *resultObj;\n\n\tif ((objc != 5) && (objc != 6)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName index1 ?index2?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = FindTag(NULL, textPtr, objv[3]);\n\tif (tagPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),\n\t\t0, &last);\n\tif (objc == 5) {\n\t    index2 = last;\n\t} else if (TkTextGetObjIndex(interp, textPtr, objv[5],\n\t\t&index2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * The search below is a bit tricky. Rather than use the B-tree\n\t * facilities to stop the search at index2, let it search up until the\n\t * end of the file but check for a position past index2 ourselves.\n\t * The reason for doing it this way is that we only care whether the\n\t * *start* of the range is before index2; once we find the start, we\n\t * don't want TkBTreeNextTag to abort the search because the end of\n\t * the range is after index2.\n\t */\n\n\tTkBTreeStartSearch(&index1, &last, tagPtr, &tSearch);\n\tif (TkBTreeCharTagged(&index1, tagPtr)) {\n\t    TkTextSegment *segPtr;\n\t    Tcl_Size offset;\n\n\t    /*\n\t     * The first character is tagged. See if there is an on-toggle\n\t     * just before the character. If not, then skip to the end of this\n\t     * tagged range.\n\t     */\n\n\t    for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex;\n\t\t    offset >= 0;\n\t\t    offset -= segPtr->size, segPtr = segPtr->nextPtr) {\n\t\tif ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType)\n\t\t\t&& (segPtr->body.toggle.tagPtr == tagPtr)) {\n\t\t    goto gotStart;\n\t\t}\n\t    }\n\t    if (!TkBTreeNextTag(&tSearch)) {\n\t\treturn TCL_OK;\n\t    }\n\t}\n\n\t/*\n\t * Find the start of the tagged range.\n\t */\n\n\tif (!TkBTreeNextTag(&tSearch)) {\n\t    return TCL_OK;\n\t}\n\n    gotStart:\n\tif (TkTextIndexCmp(&tSearch.curIndex, &index2) >= 0) {\n\t    return TCL_OK;\n\t}\n\tresultObj = Tcl_NewObj();\n\tTkTextPrintIndex(textPtr, &tSearch.curIndex, position);\n\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\tTcl_NewStringObj(position, TCL_INDEX_NONE));\n\tTkBTreeNextTag(&tSearch);\n\tTkTextPrintIndex(textPtr, &tSearch.curIndex, position);\n\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\tTcl_NewStringObj(position, TCL_INDEX_NONE));\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    }\n    case TAG_PREVRANGE: {\n\tTkTextIndex last;\n\tTkTextSearch tSearch;\n\tchar position1[TK_POS_CHARS];\n\tchar position2[TK_POS_CHARS];\n\tTcl_Obj *resultObj;\n\n\tif ((objc != 5) && (objc != 6)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName index1 ?index2?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = FindTag(NULL, textPtr, objv[3]);\n\tif (tagPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 5) {\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t\t    &index2);\n\t} else if (TkTextGetObjIndex(interp, textPtr, objv[5],\n\t\t&index2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * The search below is a bit weird. The previous toggle can be either\n\t * an on or off toggle. If it is an on toggle, then we need to turn\n\t * around and search forward for the end toggle. Otherwise we keep\n\t * searching backwards.\n\t */\n\n\tTkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch);\n\n\tif (!TkBTreePrevTag(&tSearch)) {\n\t    /*\n\t     * Special case, there may be a tag off toggle at index1, and a\n\t     * tag on toggle before the start of a partial peer widget. In\n\t     * this case we missed it.\n\t     */\n\n\t    if (textPtr->start != NULL && (textPtr->start == index2.linePtr)\n\t\t    && (index2.byteIndex == 0)\n\t\t    && TkBTreeCharTagged(&index2, tagPtr)\n\t\t    && (TkTextIndexCmp(&index2, &index1) < 0)) {\n\t\t/*\n\t\t * The first character is tagged, so just add the range from\n\t\t * the first char to the start of the range.\n\t\t */\n\n\t\tTkTextPrintIndex(textPtr, &index2, position1);\n\t\tTkTextPrintIndex(textPtr, &index1, position2);\n\t\tgoto gotPrevIndexPair;\n\t    }\n\t    return TCL_OK;\n\t}\n\n\tif (tSearch.segPtr->typePtr == &tkTextToggleOnType) {\n\t    TkTextPrintIndex(textPtr, &tSearch.curIndex, position1);\n\t    if (textPtr->start != NULL) {\n\t\t/*\n\t\t * Make sure the first index is not before the first allowed\n\t\t * text index in this widget.\n\t\t */\n\n\t\tTkTextIndex firstIndex;\n\n\t\tfirstIndex.linePtr = textPtr->start;\n\t\tfirstIndex.byteIndex = 0;\n\t\tfirstIndex.textPtr = NULL;\n\t\tif (TkTextIndexCmp(&tSearch.curIndex, &firstIndex) < 0) {\n\t\t    if (TkTextIndexCmp(&firstIndex, &index1) >= 0) {\n\t\t\t/*\n\t\t\t * But now the new first index is actually too far\n\t\t\t * along in the text, so nothing is returned.\n\t\t\t */\n\n\t\t\treturn TCL_OK;\n\t\t    }\n\t\t    TkTextPrintIndex(textPtr, &firstIndex, position1);\n\t\t}\n\t    }\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),\n\t\t    0, &last);\n\t    TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch);\n\t    TkBTreeNextTag(&tSearch);\n\t    TkTextPrintIndex(textPtr, &tSearch.curIndex, position2);\n\t} else {\n\t    TkTextPrintIndex(textPtr, &tSearch.curIndex, position2);\n\t    TkBTreePrevTag(&tSearch);\n\t    TkTextPrintIndex(textPtr, &tSearch.curIndex, position1);\n\t    if (TkTextIndexCmp(&tSearch.curIndex, &index2) < 0) {\n\t\tif (textPtr->start != NULL && index2.linePtr == textPtr->start\n\t\t\t&& index2.byteIndex == 0) {\n\t\t    /* It's ok */\n\t\t    TkTextPrintIndex(textPtr, &index2, position1);\n\t\t} else {\n\t\t    return TCL_OK;\n\t\t}\n\t    }\n\t}\n\n    gotPrevIndexPair:\n\tresultObj = Tcl_NewObj();\n\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\tTcl_NewStringObj(position1, TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\tTcl_NewStringObj(position2, TCL_INDEX_NONE));\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    }\n    case TAG_RAISE: {\n\tTkTextTag *tagPtr2;\n\tTcl_Size prio;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName ?aboveThis?\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = FindTag(interp, textPtr, objv[3]);\n\tif (tagPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 5) {\n\t    tagPtr2 = FindTag(interp, textPtr, objv[4]);\n\t    if (tagPtr2 == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (tagPtr->priority <= tagPtr2->priority) {\n\t\tprio = tagPtr2->priority;\n\t    } else {\n\t\tprio = tagPtr2->priority + 1;\n\t    }\n\t} else {\n\t    prio = textPtr->sharedTextPtr->numTags-1;\n\t}\n\tChangeTagPriority(textPtr, tagPtr, prio);\n\n\t/*\n\t * If this is the 'sel' tag, then we don't actually need to call this\n\t * for all peers.\n\t */\n\n\tTkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, true);\n\tbreak;\n    }\n    case TAG_RANGES: {\n\tTkTextIndex first, last;\n\tTkTextSearch tSearch;\n\tTcl_Obj *listObj = Tcl_NewListObj(0, NULL);\n\tint count = 0;\n\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"tagName\");\n\t    return TCL_ERROR;\n\t}\n\ttagPtr = FindTag(NULL, textPtr, objv[3]);\n\tif (tagPtr == NULL) {\n\t    return TCL_OK;\n\t}\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0,\n\t\t&first);\n\tTkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\tTkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr),\n\t\t0, &last);\n\tTkBTreeStartSearch(&first, &last, tagPtr, &tSearch);\n\tif (TkBTreeCharTagged(&first, tagPtr)) {\n\t    Tcl_ListObjAppendElement(NULL, listObj,\n\t\t    TkTextNewIndexObj(textPtr, &first));\n\t    count++;\n\t}\n\twhile (TkBTreeNextTag(&tSearch)) {\n\t    Tcl_ListObjAppendElement(NULL, listObj,\n\t\t    TkTextNewIndexObj(textPtr, &tSearch.curIndex));\n\t    count++;\n\t}\n\tif (count % 2 == 1) {\n\t    /*\n\t     * If a text widget uses '-end', it won't necessarily run to the\n\t     * end of the B-tree, and therefore the tag range might not be\n\t     * closed. In this case we add the end of the range.\n\t     */\n\n\t    Tcl_ListObjAppendElement(NULL, listObj,\n\t\t    TkTextNewIndexObj(textPtr, &last));\n\t}\n\tTcl_SetObjResult(interp, listObj);\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextCreateTag --\n *\n *\tFind the record describing a tag within a given text widget, creating\n *\ta new record if one doesn't already exist.\n *\n * Results:\n *\tThe return value is a pointer to the TkTextTag record for tagName.\n *\n * Side effects:\n *\tA new tag record is created if there isn't one already defined for\n *\ttagName.\n *\n *----------------------------------------------------------------------\n */\n\nTkTextTag *\nTkTextCreateTag(\n    TkText *textPtr,\t\t/* Widget in which tag is being used. */\n    const char *tagName,\t/* Name of desired tag. */\n    int *newTag)\t\t/* If non-NULL, then return 1 if new, or 0 if\n\t\t\t\t * already exists. */\n{\n    TkTextTag *tagPtr;\n    Tcl_HashEntry *hPtr = NULL;\n    int isNew;\n    const char *name;\n\n    if (!strcmp(tagName, \"sel\")) {\n\tif (textPtr->selTagPtr != NULL) {\n\t    if (newTag != NULL) {\n\t\t*newTag = 0;\n\t    }\n\t    return textPtr->selTagPtr;\n\t}\n\tif (newTag != NULL) {\n\t    *newTag = 1;\n\t}\n\tname = \"sel\";\n    } else {\n\thPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->tagTable,\n\t\ttagName, &isNew);\n\tif (newTag != NULL) {\n\t    *newTag = isNew;\n\t}\n\tif (!isNew) {\n\t    return (TkTextTag *)Tcl_GetHashValue(hPtr);\n\t}\n\tname = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->tagTable, hPtr);\n    }\n\n    /*\n     * No existing entry. Create a new one, initialize it, and add a pointer\n     * to it to the hash table entry.\n     */\n\n    tagPtr = (TkTextTag *)Tcl_Alloc(sizeof(TkTextTag));\n    tagPtr->name = name;\n    tagPtr->textPtr = NULL;\n    tagPtr->toggleCount = 0;\n    tagPtr->tagRootPtr = NULL;\n    tagPtr->priority = textPtr->sharedTextPtr->numTags;\n    tagPtr->border = NULL;\n    tagPtr->borderWidthObj = NULL;\n    tagPtr->relief = TK_RELIEF_NULL;\n    tagPtr->bgStipple = None;\n    tagPtr->fgColor = NULL;\n    tagPtr->tkfont = NULL;\n    tagPtr->fgStipple = None;\n    tagPtr->justify = TK_JUSTIFY_NULL;\n    tagPtr->lMargin1Obj = NULL;\n    tagPtr->lMargin1 = 0;\n    tagPtr->lMargin2Obj = NULL;\n    tagPtr->lMargin2 = 0;\n    tagPtr->lMarginColor = NULL;\n    tagPtr->offsetObj = NULL;\n    tagPtr->offset = 0;\n    tagPtr->overstrike = -1;\n    tagPtr->overstrikeColor = NULL;\n    tagPtr->rMarginObj = NULL;\n    tagPtr->rMargin = 0;\n    tagPtr->rMarginColor = NULL;\n    tagPtr->selBorder = NULL;\n    tagPtr->selFgColor = NULL;\n    tagPtr->spacing1Obj = NULL;\n    tagPtr->spacing2Obj = NULL;\n    tagPtr->spacing3Obj = NULL;\n    tagPtr->tabStringPtr = NULL;\n    tagPtr->tabArrayPtr = NULL;\n    tagPtr->tabStyle = TK_TEXT_TABSTYLE_NULL;\n    tagPtr->underline = -1;\n    tagPtr->underlineColor = NULL;\n    tagPtr->elide = -1;\n    tagPtr->wrapMode = TEXT_WRAPMODE_NULL;\n    tagPtr->affectsDisplay = false;\n    tagPtr->affectsDisplayGeometry = false;\n    textPtr->sharedTextPtr->numTags++;\n    if (!strcmp(tagName, \"sel\")) {\n\ttagPtr->textPtr = textPtr;\n\ttextPtr->refCount++;\n    } else {\n\tCLANG_ASSERT(hPtr);\n\tTcl_SetHashValue(hPtr, tagPtr);\n    }\n    tagPtr->optionTable =\n\t    Tk_CreateOptionTable(textPtr->interp, tagOptionSpecs);\n    return tagPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindTag --\n *\n *\tSee if tag is defined for a given widget.\n *\n * Results:\n *\tIf tagName is defined in textPtr, a pointer to its TkTextTag structure\n *\tis returned. Otherwise NULL is returned and an error message is\n *\trecorded in the interp's result unless interp is NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkTextTag *\nFindTag(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error message; if\n\t\t\t\t * NULL, then don't record an error\n\t\t\t\t * message. */\n    TkText *textPtr,\t\t/* Widget in which tag is being used. */\n    Tcl_Obj *tagName)\t\t/* Name of desired tag. */\n{\n    Tcl_HashEntry *hPtr;\n    Tcl_Size len;\n    const char *str;\n\n    str = Tcl_GetStringFromObj(tagName, &len);\n    if (len == 3 && !strcmp(str, \"sel\")) {\n\treturn textPtr->selTagPtr;\n    }\n    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable,\n\t    Tcl_GetString(tagName));\n    if (hPtr != NULL) {\n\treturn (TkTextTag *)Tcl_GetHashValue(hPtr);\n    }\n    if (interp != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"tag \\\"%s\\\" isn't defined in text widget\",\n\t\tTcl_GetString(tagName)));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TEXT_TAG\",\n\t\tTcl_GetString(tagName), (char *)NULL);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextDeleteTag --\n *\n *\tThis function is called to carry out most actions associated with the\n *\t'tag delete' sub-command. It will remove all evidence of the tag from\n *\tthe B-tree, and then call TkTextFreeTag to clean up the tag structure\n *\titself.\n *\n *\tThe only actions this doesn't carry out it to check if the deletion of\n *\tthe tag requires something to be re-displayed, and to remove the tag\n *\tfrom the tagTable (hash table) if that is necessary (i.e. if it's not\n *\tthe 'sel' tag). It is expected that the caller carry out both of these\n *\tactions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and other resources are freed, the B-tree is manipulated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextDeleteTag(\n    TkText *textPtr,\t\t/* Info about overall widget. */\n    TkTextTag *tagPtr)\t/* Tag being deleted. */\n{\n    TkTextIndex first, last;\n\n    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, &first);\n    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last),\n    TkBTreeTag(&first, &last, tagPtr, false);\n\n    if (tagPtr == textPtr->selTagPtr) {\n\t/*\n\t * Send an event that the selection changed. This is equivalent to:\n\t *\tevent generate $textWidget <<Selection>>\n\t */\n\n\tTkTextSelectionEvent(textPtr);\n    } else {\n\t/*\n\t * Since all peer widgets have an independent \"sel\" tag, we\n\t * don't want removal of one sel tag to remove bindings which\n\t * are still valid in other peer widgets.\n\t */\n\n\tif (textPtr->sharedTextPtr->bindingTable != NULL) {\n\t    Tk_DeleteAllBindings(textPtr->sharedTextPtr->bindingTable,\n\t\t    (void *) tagPtr->name);\n\t}\n    }\n\n    /*\n     * Update the tag priorities to reflect the deletion of this tag.\n     */\n\n    ChangeTagPriority(textPtr, tagPtr, textPtr->sharedTextPtr->numTags-1);\n    textPtr->sharedTextPtr->numTags -= 1;\n    TkTextFreeTag(textPtr, tagPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTextFreeTag --\n *\n *\tThis function is called when a tag is deleted to free up the memory\n *\tand other resources associated with the tag.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and other resources are freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkTextFreeTag(\n    TkText *textPtr,\t\t/* Info about overall widget. */\n    TkTextTag *tagPtr)\t/* Tag being deleted. */\n{\n    Tcl_Size i;\n\n    /*\n     * Let Tk do most of the hard work for us.\n     */\n\n    Tk_FreeConfigOptions(tagPtr, tagPtr->optionTable,\n\t    textPtr->tkwin);\n\n    /*\n     * This associated information is managed by us.\n     */\n\n    if (tagPtr->tabArrayPtr != NULL) {\n\tTcl_Free(tagPtr->tabArrayPtr);\n    }\n\n    /*\n     * Make sure this tag isn't referenced from the 'current' tag array.\n     */\n\n    for (i = 0; i < textPtr->numCurTags; i++) {\n\tif (textPtr->curTagArrayPtr[i] == tagPtr) {\n\t    for (; i < textPtr->numCurTags-1; i++) {\n\t\ttextPtr->curTagArrayPtr[i] = textPtr->curTagArrayPtr[i+1];\n\t    }\n\t    textPtr->curTagArrayPtr[textPtr->numCurTags-1] = NULL;\n\t    textPtr->numCurTags--;\n\t    break;\n\t}\n    }\n\n    /*\n     * If this tag is widget-specific (peer widgets) then clean up the\n     * refCount it holds.\n     */\n\n    if (tagPtr->textPtr != NULL) {\n\tif (textPtr != tagPtr->textPtr) {\n\t    Tcl_Panic(\"Tag being deleted from wrong widget\");\n\t}\n\tif (textPtr->refCount-- <= 1) {\n\t    Tcl_Free(textPtr);\n\t}\n\ttagPtr->textPtr = NULL;\n    }\n\n    /*\n     * Finally free the tag's memory.\n     */\n\n    Tcl_Free(tagPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SortTags --\n *\n *\tThis function sorts an array of tag pointers in increasing order of\n *\tpriority, optimizing for the common case where the array is small.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSortTags(\n    Tcl_Size numTags,\t\t/* Number of tag pointers at *tagArrayPtr. */\n    TkTextTag **tagArrayPtr)\t/* Pointer to array of pointers. */\n{\n    Tcl_Size i, j, prio;\n    TkTextTag **tagPtrPtr;\n    TkTextTag **maxPtrPtr, *tmp;\n\n    if (numTags < 2) {\n\treturn;\n    }\n    if (numTags < 20) {\n\tfor (i = numTags-1; i > 0; i--, tagArrayPtr++) {\n\t    maxPtrPtr = tagPtrPtr = tagArrayPtr;\n\t    prio = tagPtrPtr[0]->priority;\n\t    for (j = i, tagPtrPtr++; j > 0; j--, tagPtrPtr++) {\n\t\tif (tagPtrPtr[0]->priority < prio) {\n\t\t    prio = tagPtrPtr[0]->priority;\n\t\t    maxPtrPtr = tagPtrPtr;\n\t\t}\n\t    }\n\t    tmp = *maxPtrPtr;\n\t    *maxPtrPtr = *tagArrayPtr;\n\t    *tagArrayPtr = tmp;\n\t}\n    } else {\n\tqsort(tagArrayPtr,(unsigned)numTags,sizeof(TkTextTag *),TagSortProc);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TagSortProc --\n *\n *\tThis function is called by qsort() when sorting an array of tags in\n *\tpriority order.\n *\n * Results:\n *\tThe return value is -1 if the first argument should be before the\n *\tsecond element (i.e. it has lower priority), 0 if it's equivalent\n *\t(this should never happen!), and 1 if it should be after the second\n *\telement.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTagSortProc(\n    const void *first,\n    const void *second)\t\t/* Elements to be compared. */\n{\n    TkTextTag *tagPtr1, *tagPtr2;\n\n    tagPtr1 = * (TkTextTag **) first;\n    tagPtr2 = * (TkTextTag **) second;\n    if (tagPtr1->priority == tagPtr2->priority) {\n\treturn 0;\n    }\n    return (tagPtr1->priority > tagPtr2->priority) ? 1 : -1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ChangeTagPriority --\n *\n *\tThis function changes the priority of a tag by modifying its priority\n *\tand the priorities of other tags that are affected by the change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPriorities may be changed for some or all of the tags in textPtr. The\n *\ttags will be arranged so that there is exactly one tag at each\n *\tpriority level between 0 and textPtr->sharedTextPtr->numTags-1, with\n *\ttagPtr at priority \"prio\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nChangeTagPriority(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    TkTextTag *tagPtr,\t\t/* Tag whose priority is to be changed. */\n    Tcl_Size prio)\t\t\t/* New priority for tag. */\n{\n    Tcl_Size low, high, delta;\n    TkTextTag *tagPtr2;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    if (prio < 0) {\n\tprio = 0;\n    }\n    if (prio >= textPtr->sharedTextPtr->numTags) {\n\tprio = textPtr->sharedTextPtr->numTags-1;\n    }\n    if (prio == tagPtr->priority) {\n\treturn;\n    }\n    if (prio < tagPtr->priority) {\n\tlow = prio;\n\thigh = tagPtr->priority-1;\n\tdelta = 1;\n    } else {\n\tlow = tagPtr->priority+1;\n\thigh = prio;\n\tdelta = -1;\n    }\n\n    /*\n     * Adjust first the 'sel' tag, then all others from the hash table\n     */\n\n    if ((textPtr->selTagPtr->priority >= low)\n\t    && (textPtr->selTagPtr->priority <= high)) {\n\ttextPtr->selTagPtr->priority += delta;\n    }\n    for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->tagTable, &search);\n\t    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\ttagPtr2 = (TkTextTag *)Tcl_GetHashValue(hPtr);\n\tif ((tagPtr2->priority >= low) && (tagPtr2->priority <= high)) {\n\t    tagPtr2->priority += delta;\n\t}\n    }\n    tagPtr->priority = prio;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextBindProc --\n *\n *\tThis function is invoked by the Tk dispatcher to handle events\n *\tassociated with bindings on items.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the command invoked as part of the binding (if there was\n *\tany).\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextBindProc(\n    void *clientData,\t/* Pointer to text widget structure. */\n    XEvent *eventPtr)\t\t/* Pointer to X event that just happened. */\n{\n    TkText *textPtr = (TkText *)clientData;\n    int repick = 0;\n\n    textPtr->refCount++;\n\n    /*\n     * This code simulates grabs for mouse buttons by keeping track of whether\n     * a button is pressed and refusing to pick a new current character while\n     * a button is pressed.\n     */\n\n    if (eventPtr->type == ButtonPress) {\n\ttextPtr->flags |= BUTTON_DOWN;\n    } else if (eventPtr->type == ButtonRelease) {\n\tunsigned long mask;\n\n\tmask = Tk_GetButtonMask(eventPtr->xbutton.button);\n\tif ((eventPtr->xbutton.state & ALL_BUTTONS) == mask) {\n\t    textPtr->flags &= ~BUTTON_DOWN;\n\t    repick = 1;\n\t}\n    } else if ((eventPtr->type == EnterNotify)\n\t    || (eventPtr->type == LeaveNotify)) {\n\tif (eventPtr->xcrossing.state & ALL_BUTTONS) {\n\t    textPtr->flags |= BUTTON_DOWN;\n\t} else {\n\t    textPtr->flags &= ~BUTTON_DOWN;\n\t}\n\tTkTextPickCurrent(textPtr, eventPtr);\n\tgoto done;\n    } else if (eventPtr->type == MotionNotify) {\n\tif (eventPtr->xmotion.state & ALL_BUTTONS) {\n\t    textPtr->flags |= BUTTON_DOWN;\n\t} else {\n\t    textPtr->flags &= ~BUTTON_DOWN;\n\t}\n\tTkTextPickCurrent(textPtr, eventPtr);\n    }\n\n    if ((textPtr->sharedTextPtr->bindingTable != NULL)\n\t    && (textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) {\n\tif (textPtr->numCurTags > 0) {\n\t    /*\n\t     * The mouse is inside the text widget, the 'current' mark was updated.\n\t     */\n\n\t    TagBindEvent(textPtr, eventPtr, textPtr->numCurTags,\n\t\ttextPtr->curTagArrayPtr);\n\t} else if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) {\n\t    /*\n\t     * Key events fire independently of the 'current' mark and use the\n\t     * 'insert' mark.\n\t     */\n\n\t    TkTextIndex index;\n\t    TkTextTag** tagArrayPtr;\n\t    Tcl_Size numTags;\n\n\t    TkTextMarkNameToIndex(textPtr, \"insert\", &index);\n\t    tagArrayPtr = TkBTreeGetTags(&index, textPtr, &numTags);\n\t    SortTags(numTags, tagArrayPtr);\n\t    TagBindEvent(textPtr, eventPtr, numTags, tagArrayPtr);\n\t}\n    }\n    if (repick) {\n\tunsigned int oldState;\n\n\toldState = eventPtr->xbutton.state;\n\teventPtr->xbutton.state &= ~(unsigned long)ALL_BUTTONS;\n\tif (!(textPtr->flags & DESTROYED)) {\n\t    TkTextPickCurrent(textPtr, eventPtr);\n\t}\n\teventPtr->xbutton.state = oldState;\n    }\n\n  done:\n    if (textPtr->refCount-- <= 1) {\n\tTcl_Free(textPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextPickCurrent --\n *\n *\tFind the character containing the coordinates in an event and place\n *\tthe \"current\" mark on that character. If the \"current\" mark has moved\n *\tthen generate a fake leave event on the old current character and a\n *\tfake enter event on the new current character.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe current mark for textPtr may change. If it does, then the commands\n *\tassociated with character entry and leave could do just about\n *\tanything. For example, the text widget might be deleted. It is up to\n *\tthe caller to protect itself by incrementing the refCount of the text\n *\twidget.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextPickCurrent(\n    TkText *textPtr,\t/* Text widget in which to select current\n\t\t\t\t * character. */\n    XEvent *eventPtr)\t\t/* Event describing location of mouse cursor.\n\t\t\t\t * Must be EnterWindow, LeaveWindow,\n\t\t\t\t * ButtonRelease, or MotionNotify. */\n{\n    TkTextIndex index;\n    TkTextTag **oldArrayPtr, **newArrayPtr;\n    TkTextTag **copyArrayPtr = NULL;\n\t\t\t\t/* Initialization needed to prevent compiler\n\t\t\t\t * warning. */\n    Tcl_Size numOldTags, i;\n    Tcl_Size numNewTags, j;\n    size_t size;\n    XEvent event;\n    bool nearby;\n\n    /*\n     * If a button is down, then don't do anything at all; we'll be called\n     * again when all buttons are up, and we can repick then. This implements\n     * a form of mouse grabbing.\n     */\n\n    if (textPtr->flags & BUTTON_DOWN) {\n\tif (((eventPtr->type == EnterNotify)\n\t\t|| (eventPtr->type == LeaveNotify))\n\t\t&& ((eventPtr->xcrossing.mode == NotifyGrab)\n\t\t|| (eventPtr->xcrossing.mode == NotifyUngrab))) {\n\t    /*\n\t     * Special case: the window is being entered or left because of a\n\t     * grab or ungrab. In this case, repick after all. Furthermore,\n\t     * clear BUTTON_DOWN to release the simulated grab.\n\t     */\n\n\t    textPtr->flags &= ~BUTTON_DOWN;\n\t} else {\n\t    return;\n\t}\n    }\n\n    /*\n     * Save information about this event in the widget in case we have to\n     * synthesize more enter and leave events later (e.g. because a character\n     * was deleted, causing a new character to be underneath the mouse\n     * cursor). Also translate MotionNotify events into EnterNotify events,\n     * since that's what gets reported to event handlers when the current\n     * character changes.\n     */\n\n    if (eventPtr != &textPtr->pickEvent) {\n\tif ((eventPtr->type == MotionNotify)\n\t\t|| (eventPtr->type == ButtonRelease)) {\n\t    textPtr->pickEvent.xcrossing.type = EnterNotify;\n\t    textPtr->pickEvent.xcrossing.serial = eventPtr->xmotion.serial;\n\t    textPtr->pickEvent.xcrossing.send_event\n\t\t    = eventPtr->xmotion.send_event;\n\t    textPtr->pickEvent.xcrossing.display = eventPtr->xmotion.display;\n\t    textPtr->pickEvent.xcrossing.window = eventPtr->xmotion.window;\n\t    textPtr->pickEvent.xcrossing.root = eventPtr->xmotion.root;\n\t    textPtr->pickEvent.xcrossing.subwindow = None;\n\t    textPtr->pickEvent.xcrossing.time = eventPtr->xmotion.time;\n\t    textPtr->pickEvent.xcrossing.x = eventPtr->xmotion.x;\n\t    textPtr->pickEvent.xcrossing.y = eventPtr->xmotion.y;\n\t    textPtr->pickEvent.xcrossing.x_root = eventPtr->xmotion.x_root;\n\t    textPtr->pickEvent.xcrossing.y_root = eventPtr->xmotion.y_root;\n\t    textPtr->pickEvent.xcrossing.mode = NotifyNormal;\n\t    textPtr->pickEvent.xcrossing.detail = NotifyNonlinear;\n\t    textPtr->pickEvent.xcrossing.same_screen\n\t\t    = eventPtr->xmotion.same_screen;\n\t    textPtr->pickEvent.xcrossing.focus = False;\n\t    textPtr->pickEvent.xcrossing.state = eventPtr->xmotion.state;\n\t} else {\n\t    textPtr->pickEvent = *eventPtr;\n\t}\n    }\n\n    /*\n     * Find the new current character, then find and sort all of the tags\n     * associated with it.\n     */\n\n    if (textPtr->pickEvent.type != LeaveNotify) {\n\tTkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x,\n\t\ttextPtr->pickEvent.xcrossing.y, &index, &nearby);\n\tif (nearby) {\n\t    newArrayPtr = NULL;\n\t    numNewTags = 0;\n\t} else {\n\t    newArrayPtr = TkBTreeGetTags(&index, textPtr, &numNewTags);\n\t    SortTags(numNewTags, newArrayPtr);\n\t}\n    } else {\n\tnewArrayPtr = NULL;\n\tnumNewTags = 0;\n    }\n\n    /*\n     * Resort the tags associated with the previous marked character (the\n     * priorities might have changed), then make a copy of the new tags, and\n     * compare the old tags to the copy, nullifying any tags that are present\n     * in both groups (i.e. the tags that haven't changed).\n     */\n\n    SortTags(textPtr->numCurTags, textPtr->curTagArrayPtr);\n    if (numNewTags > 0) {\n\tsize = numNewTags * sizeof(TkTextTag *);\n\tcopyArrayPtr = (TkTextTag **)Tcl_Alloc(size);\n\tmemcpy(copyArrayPtr, newArrayPtr, size);\n\tfor (i = 0; i < textPtr->numCurTags; i++) {\n\t    for (j = 0; j < numNewTags; j++) {\n\t\tif (textPtr->curTagArrayPtr[i] == copyArrayPtr[j]) {\n\t\t    textPtr->curTagArrayPtr[i] = NULL;\n\t\t    copyArrayPtr[j] = NULL;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Invoke the binding system with a LeaveNotify event for all of the tags\n     * that have gone away. We have to be careful here, because it's possible\n     * that the binding could do something (like calling tkwait) that\n     * eventually modifies textPtr->curTagArrayPtr. To avoid problems in\n     * situations like this, update curTagArrayPtr to its new value before\n     * invoking any bindings, and don't use it any more here.\n     */\n\n    numOldTags = textPtr->numCurTags;\n    textPtr->numCurTags = numNewTags;\n    oldArrayPtr = textPtr->curTagArrayPtr;\n    textPtr->curTagArrayPtr = newArrayPtr;\n    if (numOldTags != 0) {\n\tif ((textPtr->sharedTextPtr->bindingTable != NULL)\n\t\t&& (textPtr->tkwin != NULL)\n\t\t&& !(textPtr->flags & DESTROYED)) {\n\t    event = textPtr->pickEvent;\n\t    event.type = LeaveNotify;\n\n\t    /*\n\t     * Behaviour before ticket #47d4f29159:\n\t     *   Always use a detail of NotifyAncestor. Besides being\n\t     *   consistent, this avoids problems where the binding code will\n\t     *   discard NotifyInferior events.\n\t     *\n\t     * Behaviour after ticket #47d4f29159:\n\t     *   The binding mechanism doesn't discard events with detail field\n\t     *   NotifyInferior anymore. It would be best to base the detail\n\t     *   field on the ancestry relationship between the old and new\n\t     *   tags. For the time being, retain the choice from before\n\t     *   ticket #47d4f29159, which doesn't harm.\n\t     */\n\n\t    event.xcrossing.detail = NotifyAncestor;\n\t    TagBindEvent(textPtr, &event, numOldTags, oldArrayPtr);\n\t}\n\tTcl_Free(oldArrayPtr);\n    }\n\n    /*\n     * Reset the \"current\" mark (be careful to recompute its location, since\n     * it might have changed during an event binding). Then invoke the binding\n     * system with an EnterNotify event for all of the tags that have just\n     * appeared.\n     */\n\n    TkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x,\n\t    textPtr->pickEvent.xcrossing.y, &index, &nearby);\n    TkTextSetMark(textPtr, \"current\", &index);\n    if (numNewTags != 0) {\n\tif ((textPtr->sharedTextPtr->bindingTable != NULL)\n\t\t&& (textPtr->tkwin != NULL)\n\t\t&& !(textPtr->flags & DESTROYED) && !nearby) {\n\t    event = textPtr->pickEvent;\n\t    event.type = EnterNotify;\n\t    event.xcrossing.detail = NotifyAncestor;\n\t    TagBindEvent(textPtr, &event, numNewTags, copyArrayPtr);\n\t}\n\tTcl_Free(copyArrayPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TagBindEvent --\n *\n *\tTrigger given events for all tags that match the relevant bindings.\n *\tTo handle the \"sel\" tag correctly in all peer widgets, we must use the\n *\tname of the tags as the binding table element.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAlmost anything can be triggered by tag bindings, including deletion\n *\tof the text widget.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTagBindEvent(\n    TkText *textPtr,\t\t/* Text widget to fire bindings in. */\n    XEvent *eventPtr,\t\t/* What actually happened. */\n    Tcl_Size numTags,\t\t/* Number of relevant tags. */\n    TkTextTag **tagArrayPtr)\t/* Array of relevant tags. */\n{\n#   define NUM_BIND_TAGS 10\n    const char *nameArray[NUM_BIND_TAGS];\n    const char **nameArrPtr;\n    Tcl_Size i;\n\n    /*\n     * Try to avoid allocation unless there are lots of tags.\n     */\n\n    if (numTags > NUM_BIND_TAGS) {\n\tnameArrPtr = (const char **)Tcl_Alloc(numTags * sizeof(const char *));\n    } else {\n\tnameArrPtr = nameArray;\n    }\n\n    /*\n     * We use tag names as keys in the hash table. We do this instead of using\n     * the actual tagPtr objects because we want one \"sel\" tag binding for all\n     * peer widgets, despite the fact that each has its own tagPtr object.\n     */\n\n    for (i = 0; i < numTags; i++) {\n\tTkTextTag *tagPtr = tagArrayPtr[i];\n\n\tif (tagPtr != NULL) {\n\t    nameArrPtr[i] = tagPtr->name;\n\t} else {\n\t    /*\n\t     * Tag has been deleted elsewhere, and therefore nulled out in\n\t     * this array. Tk_BindEvent is clever enough to cope with NULLs\n\t     * being thrown at it.\n\t     */\n\n\t    nameArrPtr[i] = NULL;\n\t}\n    }\n    Tk_BindEvent(textPtr->sharedTextPtr->bindingTable, eventPtr,\n\t    textPtr->tkwin, numTags, (void **) nameArrPtr);\n\n    if (numTags > NUM_BIND_TAGS) {\n\tTcl_Free(nameArrPtr);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTextWind.c",
    "content": "/*\n * tkTextWind.c --\n *\n *\tThis file contains code that allows arbitrary windows to be nested\n *\tinside text widgets. It also implements the \"window\" widget command\n *\tfor texts.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkPort.h\"\n#include \"tkText.h\"\n\n/*\n * The following structure is the official type record for the embedded window\n * geometry manager:\n */\n\nstatic void\t\tEmbWinRequestProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\nstatic void\t\tEmbWinLostContentProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\n\nstatic const Tk_GeomMgr textGeomType = {\n    \"text\",\t\t\t/* name */\n    EmbWinRequestProc,\t\t/* requestProc */\n    EmbWinLostContentProc,\t/* lostContentProc */\n};\n\n/*\n * Macro that determines the size of an embedded window segment:\n */\n\n#define EW_SEG_SIZE (offsetof(TkTextSegment, body) \\\n\t+ sizeof(TkTextEmbWindow))\n\n/*\n * Prototypes for functions defined in this file:\n */\n\nstatic TkTextSegment *\tEmbWinCleanupProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic void\t\tEmbWinCheckProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr);\nstatic void\t\tEmbWinBboxProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr, Tcl_Size index, int y,\n\t\t\t    int lineHeight, int baseline, int *xPtr,int *yPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic int\t\tEmbWinConfigure(TkText *textPtr, TkTextSegment *ewPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tEmbWinDelayedUnmap(void *clientData);\nstatic int\t\tEmbWinDeleteProc(TkTextSegment *segPtr,\n\t\t\t    TkTextLine *linePtr, int treeGone);\nstatic int\t\tEmbWinLayoutProc(TkText *textPtr,\n\t\t\t    TkTextIndex *indexPtr, TkTextSegment *segPtr,\n\t\t\t    Tcl_Size offset, int maxX, Tcl_Size maxChars,int noCharsYet,\n\t\t\t    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);\nstatic void\t\tEmbWinStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEmbWinUndisplayProc(TkText *textPtr,\n\t\t\t    TkTextDispChunk *chunkPtr);\nstatic TkTextEmbWindowClient *EmbWinGetClient(const TkText *textPtr,\n\t\t\t    TkTextSegment *ewPtr);\n\n/*\n * The following structure declares the \"embedded window\" segment type.\n */\n\nconst Tk_SegType tkTextEmbWindowType = {\n    \"window\",\t\t\t/* name */\n    0,\t\t\t\t/* leftGravity */\n    NULL,\t\t\t/* splitProc */\n    EmbWinDeleteProc,\t\t/* deleteProc */\n    EmbWinCleanupProc,\t\t/* cleanupProc */\n    NULL,\t\t\t/* lineChangeProc */\n    EmbWinLayoutProc,\t\t/* layoutProc */\n    EmbWinCheckProc\t\t/* checkProc */\n};\n\n/*\n * Definitions for alignment values:\n */\n\nstatic const char *const alignStrings[] = {\n    \"baseline\", \"bottom\", \"center\", \"top\", NULL\n};\n\n/*\n * Information used for parsing window configuration options:\n */\n\nstatic const Tk_OptionSpec optionSpecs[] = {\n    {TK_OPTION_STRING_TABLE, \"-align\", NULL, NULL,\n\t\"center\", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, align),\n\tTK_OPTION_ENUM_VAR, alignStrings, 0},\n    {TK_OPTION_STRING, \"-create\", NULL, NULL,\n\tNULL, offsetof(TkTextEmbWindow, createObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-padx\", NULL, NULL,\n\t\"0\", offsetof(TkTextEmbWindow, padXObj), TCL_INDEX_NONE, TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_PIXELS, \"-pady\", NULL, NULL,\n\t\"0\", offsetof(TkTextEmbWindow, padYObj), TCL_INDEX_NONE, TK_OPTION_NEG_OK, 0, 0},\n    {TK_OPTION_BOOLEAN, \"-stretch\", NULL, NULL,\n\t\"0\", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, stretch), TK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_WINDOW, \"-window\", NULL, NULL,\n\tNULL, TCL_INDEX_NONE, offsetof(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextWindowCmd --\n *\n *\tThis function implements the \"window\" widget command for text widgets.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result or error.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextWindowCmd(\n    TkText *textPtr,\t/* Information about text widget. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. Someone else has already\n\t\t\t\t * parsed this command enough to know that\n\t\t\t\t * objv[1] is \"window\". */\n{\n    int optionIndex;\n    static const char *const windOptionStrings[] = {\n\t\"cget\", \"configure\", \"create\", \"names\", NULL\n    };\n    enum windOptions {\n\tWIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES\n    };\n    TkTextSegment *ewPtr;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], windOptionStrings,\n\t    sizeof(char *), \"window option\", 0, &optionIndex) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch ((enum windOptions) optionIndex) {\n    case WIND_CGET: {\n\tTkTextIndex index;\n\tTcl_Obj *objPtr;\n\tTkTextEmbWindowClient *client;\n\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index option\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tewPtr = TkTextIndexToSeg(&index, NULL);\n\tif (ewPtr->typePtr != &tkTextEmbWindowType) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no embedded window at index \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_WINDOW\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Copy over client specific value before querying.\n\t */\n\n\tclient = EmbWinGetClient(textPtr, ewPtr);\n\tif (client != NULL) {\n\t    ewPtr->body.ew.tkwin = client->tkwin;\n\t} else {\n\t    ewPtr->body.ew.tkwin = NULL;\n\t}\n\n\tobjPtr = Tk_GetOptionValue(interp, &ewPtr->body.ew,\n\t\tewPtr->body.ew.optionTable, objv[4], textPtr->tkwin);\n\tif (objPtr == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\treturn TCL_OK;\n    }\n    case WIND_CONFIGURE: {\n\tTkTextIndex index;\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tewPtr = TkTextIndexToSeg(&index, NULL);\n\tif (ewPtr->typePtr != &tkTextEmbWindowType) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"no embedded window at index \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"TEXT\", \"NO_WINDOW\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (objc <= 5) {\n\t    TkTextEmbWindowClient *client;\n\t    Tcl_Obj *objPtr;\n\n\t    /*\n\t     * Copy over client specific value before querying.\n\t     */\n\n\t    client = EmbWinGetClient(textPtr, ewPtr);\n\t    if (client != NULL) {\n\t\tewPtr->body.ew.tkwin = client->tkwin;\n\t    } else {\n\t\tewPtr->body.ew.tkwin = NULL;\n\t    }\n\n\t    objPtr = Tk_GetOptionInfo(interp, &ewPtr->body.ew,\n\t\t    ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL,\n\t\t    textPtr->tkwin);\n\t    if (objPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    return TCL_OK;\n\t} else {\n\t    TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);\n\n\t    /*\n\t     * It's probably not true that all window configuration can change\n\t     * the line height, so we could be more efficient here and only\n\t     * call this when necessary.\n\t     */\n\n\t    TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,\n\t\t    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n\t    return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);\n\t}\n    }\n    case WIND_CREATE: {\n\tTkTextIndex index;\n\tTcl_Size lineIndex;\n\tTkTextEmbWindowClient *client;\n\tint res;\n\n\t/*\n\t * Add a new window. Find where to put the new window, and mark that\n\t * position for redisplay.\n\t */\n\n\tif (objc < 4) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, \"index ?-option value ...?\");\n\t    return TCL_ERROR;\n\t}\n\tif (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Don't allow insertions on the last (dummy) line of the text.\n\t */\n\n\tlineIndex = TkBTreeLinesTo(textPtr, index.linePtr);\n\tif (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree,\n\t\ttextPtr)) {\n\t    lineIndex--;\n\t    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,\n\t\t    lineIndex, 1000000, &index);\n\t}\n\n\t/*\n\t * Create the new window segment and initialize it.\n\t */\n\n\tewPtr = (TkTextSegment *)Tcl_Alloc(EW_SEG_SIZE);\n\tewPtr->typePtr = &tkTextEmbWindowType;\n\tewPtr->size = 1;\n\tewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr;\n\tewPtr->body.ew.linePtr = NULL;\n\tewPtr->body.ew.tkwin = NULL;\n\tewPtr->body.ew.createObj = NULL;\n\tewPtr->body.ew.align = TK_ALIGN_CENTER;\n\tewPtr->body.ew.padXObj = ewPtr->body.ew.padYObj = NULL;\n\tewPtr->body.ew.stretch = false;\n\tewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n\n\tclient = (TkTextEmbWindowClient *)Tcl_Alloc(sizeof(TkTextEmbWindowClient));\n\tclient->next = NULL;\n\tclient->textPtr = textPtr;\n\tclient->tkwin = NULL;\n\tclient->chunkCount = 0;\n\tclient->displayed = false;\n\tclient->parent = ewPtr;\n\tewPtr->body.ew.clients = client;\n\n\t/*\n\t * Link the segment into the text widget, then configure it (delete it\n\t * again if the configuration fails).\n\t */\n\n\tTkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);\n\tTkBTreeLinkSegment(ewPtr, &index);\n\tres = EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);\n\tclient->tkwin = ewPtr->body.ew.tkwin;\n\tif (res != TCL_OK) {\n\t    TkTextIndex index2;\n\n\t    TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);\n\t    TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index,\n\t\t    &index2);\n\t    return TCL_ERROR;\n\t}\n\tTkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,\n\t\tindex.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n\tbreak;\n    }\n    case WIND_NAMES: {\n\tTcl_HashSearch search;\n\tTcl_HashEntry *hPtr;\n\tTcl_Obj *resultObj;\n\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 3, objv, NULL);\n\t    return TCL_ERROR;\n\t}\n\tresultObj = Tcl_NewObj();\n\tfor (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable,\n\t\t&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),\n\t\t    -1));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinConfigure --\n *\n *\tThis function is called to handle configuration options for an\n *\tembedded window, using an objc/objv list.\n *\n * Results:\n *\tThe return value is a standard Tcl result. If TCL_ERROR is returned,\n *\tthen the interp's result contains an error message..\n *\n * Side effects:\n *\tConfiguration information for the embedded window changes, such as\n *\talignment, stretching, or name of the embedded window.\n *\n *\tNote that this function may leave widget specific client information\n *\twith a NULL tkwin attached to ewPtr. While we could choose to clean up\n *\tthe client data structure here, there is no need to do so, and it is\n *\tlikely that the user is going to adjust the tkwin again soon.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbWinConfigure(\n    TkText *textPtr,\t\t/* Information about text widget that contains\n\t\t\t\t * embedded window. */\n    TkTextSegment *ewPtr,\t/* Embedded window to be configured. */\n    Tcl_Size objc,\t\t\t/* Number of strings in objv. */\n    Tcl_Obj *const objv[])\t/* Array of objects describing configuration\n\t\t\t\t * options. */\n{\n    Tk_Window oldWindow;\n    TkTextEmbWindowClient *client;\n\n    /*\n     * Copy over client specific value before querying or setting.\n     */\n\n    client = EmbWinGetClient(textPtr, ewPtr);\n    if (client != NULL) {\n\tewPtr->body.ew.tkwin = client->tkwin;\n    } else {\n\tewPtr->body.ew.tkwin = NULL;\n    }\n\n    oldWindow = ewPtr->body.ew.tkwin;\n    if (Tk_SetOptions(textPtr->interp, &ewPtr->body.ew,\n\t    ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL,\n\t    NULL) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (oldWindow != ewPtr->body.ew.tkwin) {\n\tif (oldWindow != NULL) {\n\t    Tcl_DeleteHashEntry(Tcl_FindHashEntry(\n\t\t    &textPtr->sharedTextPtr->windowTable,\n\t\t    Tk_PathName(oldWindow)));\n\t    Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,\n\t\t    EmbWinStructureProc, client);\n\t    Tk_ManageGeometry(oldWindow, NULL, NULL);\n\t    if (textPtr->tkwin != Tk_Parent(oldWindow)) {\n\t\tTk_UnmaintainGeometry(oldWindow, textPtr->tkwin);\n\t    } else {\n\t\tTk_UnmapWindow(oldWindow);\n\t    }\n\t}\n\tif (client != NULL) {\n\t    client->tkwin = NULL;\n\t}\n\tif (ewPtr->body.ew.tkwin != NULL) {\n\t    Tk_Window ancestor, parent;\n\t    Tcl_HashEntry *hPtr;\n\t    int isNew;\n\n\t    /*\n\t     * Make sure that the text is either the parent of the embedded\n\t     * window or a descendant of that parent. Also, don't allow a\n\t     * top-level window to be managed inside a text.\n\t     */\n\n\t    parent = Tk_Parent(ewPtr->body.ew.tkwin);\n\t    for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {\n\t\tif (ancestor == parent) {\n\t\t    break;\n\t\t}\n\t\tif (Tk_TopWinHierarchy(ancestor)) {\n\t\tbadContainer:\n\t\t    Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(\n\t\t\t    \"can't embed %s in %s\",\n\t\t\t    Tk_PathName(ewPtr->body.ew.tkwin),\n\t\t\t    Tk_PathName(textPtr->tkwin)));\n\t\t    Tcl_SetErrorCode(textPtr->interp, \"TK\", \"GEOMETRY\",\n\t\t\t    \"HIERARCHY\", (char *)NULL);\n\t\t    ewPtr->body.ew.tkwin = NULL;\n\t\t    if (client != NULL) {\n\t\t\tclient->tkwin = NULL;\n\t\t    }\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)\n\t\t    || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {\n\t\tgoto badContainer;\n\t    }\n\n\t    if (client == NULL) {\n\t\t/*\n\t\t * Have to make the new client.\n\t\t */\n\n\t\tclient = (TkTextEmbWindowClient *)Tcl_Alloc(sizeof(TkTextEmbWindowClient));\n\t\tclient->next = ewPtr->body.ew.clients;\n\t\tclient->textPtr = textPtr;\n\t\tclient->tkwin = NULL;\n\t\tclient->chunkCount = 0;\n\t\tclient->displayed = false;\n\t\tclient->parent = ewPtr;\n\t\tewPtr->body.ew.clients = client;\n\t    }\n\t    client->tkwin = ewPtr->body.ew.tkwin;\n\n\t    /*\n\t     * Take over geometry management for the window, plus create an\n\t     * event handler to find out when it is deleted.\n\t     */\n\n\t    Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, client);\n\t    Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,\n\t\t    EmbWinStructureProc, client);\n\n\t    /*\n\t     * Special trick!  Must enter into the hash table *after* calling\n\t     * Tk_ManageGeometry: if the window was already managed elsewhere\n\t     * in this text, the Tk_ManageGeometry call will cause the entry\n\t     * to be removed, which could potentially lose the new entry.\n\t     */\n\n\t    hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,\n\t\t    Tk_PathName(ewPtr->body.ew.tkwin), &isNew);\n\t    Tcl_SetHashValue(hPtr, ewPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinStructureProc --\n *\n *\tThis function is invoked by the Tk event loop whenever StructureNotify\n *\tevents occur for a window that's embedded in a text widget. This\n *\tfunction's only purpose is to clean up when windows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is disassociated from the window segment, and the portion\n *\tof the text is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinStructureProc(\n    void *clientData,\t/* Pointer to record describing window item. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;\n    TkTextSegment *ewPtr = client->parent;\n    Tcl_HashEntry *hPtr;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n\n    hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,\n\t    Tk_PathName(client->tkwin));\n    if (hPtr != NULL) {\n\t/*\n\t * This may not exist if the entire widget is being deleted.\n\t */\n\n\tTcl_DeleteHashEntry(hPtr);\n    }\n\n    ewPtr->body.ew.tkwin = NULL;\n    client->tkwin = NULL;\n    EmbWinRequestProc(client, NULL);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinRequestProc --\n *\n *\tThis function is invoked whenever a window that's associated with a\n *\twindow canvas item changes its requested dimensions.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size and location on the screen of the window may change,\n *\tdepending on the options specified for the window item.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinRequestProc(\n    void *clientData,\t/* Pointer to record for window item. */\n    TCL_UNUSED(Tk_Window))\t/* Window that changed its desired size. */\n{\n    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;\n    TkTextSegment *ewPtr = client->parent;\n    TkTextIndex index;\n\n    index.tree = ewPtr->body.ew.sharedTextPtr->tree;\n    index.linePtr = ewPtr->body.ew.linePtr;\n\n    /*\n     * ewPtr->body.ew.tkwin == NULL means the embedded window is already\n     * destroyed. The ewPtr segment is no longer linked, TkTextSegToOffset\n     * cannot find it within the line pointed by ewPtr->body.ew.linePtr.\n     */\n\n    index.byteIndex =  ewPtr->body.ew.tkwin ?\n\t    TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr) : 0;\n    TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);\n    TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,\n\t    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinLostContentProc --\n *\n *\tThis function is invoked by the Tk geometry manager when a content\n *\twindow managed by a text widget is claimed away by another geometry\n *\tmanager.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is disassociated from the window segment, and the portion\n *\tof the text is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinLostContentProc(\n    void *clientData,\t/* Pointer to record describing window item. */\n    Tk_Window tkwin)\t\t/* Window that was claimed away by another\n\t\t\t\t * geometry manager. */\n{\n    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;\n    TkTextSegment *ewPtr = client->parent;\n    TkTextIndex index;\n    Tcl_HashEntry *hPtr;\n    TkTextEmbWindowClient *loop;\n\n    Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,\n\t    EmbWinStructureProc, client);\n    Tcl_CancelIdleCall(EmbWinDelayedUnmap, client);\n    if (client->textPtr->tkwin != Tk_Parent(tkwin)) {\n\tTk_UnmaintainGeometry(tkwin, client->textPtr->tkwin);\n    } else {\n\tTk_UnmapWindow(tkwin);\n    }\n    hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,\n\t    Tk_PathName(client->tkwin));\n    Tcl_DeleteHashEntry(hPtr);\n    client->tkwin = NULL;\n    ewPtr->body.ew.tkwin = NULL;\n\n    /*\n     * Free up the memory allocation for this client.\n     */\n\n    loop = ewPtr->body.ew.clients;\n    if (loop == client) {\n\tewPtr->body.ew.clients = client->next;\n    } else {\n\twhile (loop->next != client) {\n\t    loop = loop->next;\n\t}\n\tloop->next = client->next;\n    }\n    Tcl_Free(client);\n\n    index.tree = ewPtr->body.ew.sharedTextPtr->tree;\n    index.linePtr = ewPtr->body.ew.linePtr;\n    index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);\n    TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);\n    TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,\n\t    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextWinFreeClient --\n *\n *\tFree up the hash entry and client information for a given embedded\n *\twindow.\n *\n *\tIt is assumed the caller will manage the linked list of clients\n *\tassociated with the relevant TkTextSegment.\n *\n * Results:\n *\tNothing.\n *\n * Side effects:\n *\tThe embedded window information for a single client is deleted, if it\n *\texists, and any resources associated with it are released.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextWinFreeClient(\n    Tcl_HashEntry *hPtr,\t/* Hash entry corresponding to this client, or\n\t\t\t\t * NULL */\n    TkTextEmbWindowClient *client)\n\t\t\t\t/* Client data structure, with the 'tkwin'\n\t\t\t\t * field to be cleaned up. */\n{\n    if (hPtr != NULL) {\n\t/*\n\t * (It's possible for there to be no hash table entry for this window,\n\t * if an error occurred while creating the window segment but before\n\t * the window got added to the table)\n\t */\n\n\tTcl_DeleteHashEntry(hPtr);\n    }\n\n    /*\n     * Delete the event handler for the window before destroying the window,\n     * so that EmbWinStructureProc doesn't get called (we'll already do\n     * everything that it would have done, and it will just get confused).\n     */\n\n    if (client->tkwin != NULL) {\n\tTk_DeleteEventHandler(client->tkwin, StructureNotifyMask,\n\t\tEmbWinStructureProc, client);\n\tTk_DestroyWindow(client->tkwin);\n    }\n    Tcl_CancelIdleCall(EmbWinDelayedUnmap, client);\n\n    /*\n     * Free up this client.\n     */\n\n    Tcl_Free(client);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinDeleteProc --\n *\n *\tThis function is invoked by the text B-tree code whenever an embedded\n *\twindow lies in a range of characters being deleted.\n *\n * Results:\n *\tReturns 0 to indicate that the deletion has been accepted.\n *\n * Side effects:\n *\tThe embedded window is deleted, if it exists, and any resources\n *\tassociated with it are released.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbWinDeleteProc(\n    TkTextSegment *ewPtr,\t/* Segment being deleted. */\n    TCL_UNUSED(TkTextLine *),\t/* Line containing segment. */\n    TCL_UNUSED(int))\t\t/* Non-zero means the entire tree is being\n\t\t\t\t * deleted, so everything must get cleaned\n\t\t\t\t * up. */\n{\n    TkTextEmbWindowClient *client;\n    client = ewPtr->body.ew.clients;\n\n    while (client != NULL) {\n\tTkTextEmbWindowClient *next = client->next;\n\tTcl_HashEntry *hPtr = NULL;\n\n\tif (client->tkwin != NULL) {\n\t    hPtr = Tcl_FindHashEntry(\n\t\t    &ewPtr->body.ew.sharedTextPtr->windowTable,\n\t\t    Tk_PathName(client->tkwin));\n\t}\n\tTkTextWinFreeClient(hPtr, client);\n\tclient = next;\n    }\n    ewPtr->body.ew.clients = NULL;\n\n    Tk_FreeConfigOptions(&ewPtr->body.ew, ewPtr->body.ew.optionTable,\n\t    NULL);\n\n    /*\n     * Free up all memory allocated.\n     */\n\n    Tcl_Free(ewPtr);\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinCleanupProc --\n *\n *\tThis function is invoked by the B-tree code whenever a segment\n *\tcontaining an embedded window is moved from one line to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe linePtr field of the segment gets updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextSegment *\nEmbWinCleanupProc(\n    TkTextSegment *ewPtr,\t/* Mark segment that's being moved. */\n    TkTextLine *linePtr)\t/* Line that now contains segment. */\n{\n    ewPtr->body.ew.linePtr = linePtr;\n    return ewPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinLayoutProc --\n *\n *\tThis function is the \"layoutProc\" for embedded window segments.\n *\n * Results:\n *\t1 is returned to indicate that the segment should be displayed. The\n *\tchunkPtr structure is filled in.\n *\n * Side effects:\n *\tNone, except for filling in chunkPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nEmbWinLayoutProc(\n    TkText *textPtr,\t\t/* Text widget being layed out. */\n    TCL_UNUSED(TkTextIndex *),\t/* Identifies first character in chunk. */\n    TkTextSegment *ewPtr,\t/* Segment corresponding to indexPtr. */\n    Tcl_Size offset,\t\t\t/* Offset within segPtr corresponding to\n\t\t\t\t * indexPtr (always 0). */\n    int maxX,\t\t\t/* Chunk must not occupy pixels at this\n\t\t\t\t * position or higher. */\n    TCL_UNUSED(Tcl_Size),\t/* Chunk must not include more than this many\n\t\t\t\t * characters. */\n    int noCharsYet,\t\t/* Non-zero means no characters have been\n\t\t\t\t * assigned to this line yet. */\n    TCL_UNUSED(TkWrapMode),\t/* Wrap mode to use for line:\n\t\t\t\t * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or\n\t\t\t\t * TEXT_WRAPMODE_WORD. */\n    TkTextDispChunk *chunkPtr)\n\t\t\t\t/* Structure to fill in with information about\n\t\t\t\t * this chunk. The x field has already been\n\t\t\t\t * set by the caller. */\n{\n    int width, height;\n    TkTextEmbWindowClient *client;\n    int padX = 0, padY = 0;\n\n    if (offset != 0) {\n\tTcl_Panic(\"Non-zero offset in EmbWinLayoutProc\");\n    }\n\n    client = EmbWinGetClient(textPtr, ewPtr);\n    if (client == NULL) {\n\tewPtr->body.ew.tkwin = NULL;\n    } else {\n\tewPtr->body.ew.tkwin = client->tkwin;\n    }\n\n    if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.createObj != NULL)) {\n\tint code, isNew;\n\tTk_Window ancestor;\n\tTcl_HashEntry *hPtr;\n\tconst char *before, *string;\n\tTcl_DString buf, *dsPtr = NULL;\n\tTcl_Obj *nameObj;\n\n\tbefore = Tcl_GetString(ewPtr->body.ew.createObj);\n\n\t/*\n\t * Find everything up to the next % character and append it to the\n\t * result string.\n\t */\n\n\tstring = before;\n\twhile (*string != 0) {\n\t    if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) {\n\t\tif (dsPtr == NULL) {\n\t\t    Tcl_DStringInit(&buf);\n\t\t    dsPtr = &buf;\n\t\t}\n\t\tif (string != before) {\n\t\t    Tcl_DStringAppend(dsPtr, before, string-before);\n\t\t    before = string;\n\t\t}\n\t\tif (string[1] == '%') {\n\t\t    Tcl_DStringAppend(dsPtr, \"%\", 1);\n\t\t} else {\n\t\t    /*\n\t\t     * Substitute string as proper Tcl list element.\n\t\t     */\n\n\t\t    Tcl_Size spaceNeeded, length;\n\t\t    int cvtFlags;\n\t\t    const char *str = Tk_PathName(textPtr->tkwin);\n\n\t\t    spaceNeeded = Tcl_ScanElement(str, &cvtFlags);\n\t\t    length = Tcl_DStringLength(dsPtr);\n\t\t    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\t\t    spaceNeeded = Tcl_ConvertElement(str,\n\t\t\t    Tcl_DStringValue(dsPtr) + length,\n\t\t\t    cvtFlags | TCL_DONT_USE_BRACES);\n\t\t    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\t\t}\n\t\tbefore += 2;\n\t\tstring++;\n\t    }\n\t    string++;\n\t}\n\n\t/*\n\t * The window doesn't currently exist. Create it by evaluating the\n\t * creation script. The script must return the window's path name:\n\t * look up that name to get back to the window token. Then register\n\t * ourselves as the geometry manager for the window.\n\t */\n\n\tif (dsPtr != NULL) {\n\t    Tcl_DStringAppend(dsPtr, before, string-before);\n\t    code = Tcl_EvalEx(textPtr->interp, Tcl_DStringValue(dsPtr), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    Tcl_DStringFree(dsPtr);\n\t} else {\n\t    code = Tcl_EvalEx(textPtr->interp, Tcl_GetString(ewPtr->body.ew.createObj), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t}\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(textPtr->interp, code);\n\t    goto gotWindow;\n\t}\n\tnameObj = Tcl_GetObjResult(textPtr->interp);\n\tTcl_IncrRefCount(nameObj);\n\tTcl_ResetResult(textPtr->interp);\n\tewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,\n\t\tTcl_GetString(nameObj), textPtr->tkwin);\n\tTcl_DecrRefCount(nameObj);\n\tif (ewPtr->body.ew.tkwin == NULL) {\n\t    Tcl_BackgroundException(textPtr->interp, TCL_ERROR);\n\t    goto gotWindow;\n\t}\n\n\tfor (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {\n\t    if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {\n\t\tbreak;\n\t    }\n\t    if (Tk_TopWinHierarchy(ancestor)) {\n\t\tgoto badContainer;\n\t    }\n\t}\n\tif (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)\n\t\t|| (textPtr->tkwin == ewPtr->body.ew.tkwin)) {\n\tbadContainer:\n\t    Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(\n\t\t    \"can't embed %s relative to %s\",\n\t\t    Tk_PathName(ewPtr->body.ew.tkwin),\n\t\t    Tk_PathName(textPtr->tkwin)));\n\t    Tcl_SetErrorCode(textPtr->interp, \"TK\", \"GEOMETRY\", \"HIERARCHY\",\n\t\t    (char *)NULL);\n\t    Tcl_BackgroundException(textPtr->interp, TCL_ERROR);\n\t    ewPtr->body.ew.tkwin = NULL;\n\t    goto gotWindow;\n\t}\n\n\tif (client == NULL) {\n\t    /*\n\t     * We just used a '-create' script to make a new window, which we\n\t     * now need to add to our client list.\n\t     */\n\n\t    client = (TkTextEmbWindowClient *)Tcl_Alloc(sizeof(TkTextEmbWindowClient));\n\t    client->next = ewPtr->body.ew.clients;\n\t    client->textPtr = textPtr;\n\t    client->tkwin = NULL;\n\t    client->chunkCount = 0;\n\t    client->displayed = false;\n\t    client->parent = ewPtr;\n\t    ewPtr->body.ew.clients = client;\n\t}\n\n\tclient->tkwin = ewPtr->body.ew.tkwin;\n\tTk_ManageGeometry(client->tkwin, &textGeomType, client);\n\tTk_CreateEventHandler(client->tkwin, StructureNotifyMask,\n\t\tEmbWinStructureProc, client);\n\n\t/*\n\t * Special trick! Must enter into the hash table *after* calling\n\t * Tk_ManageGeometry: if the window was already managed elsewhere in\n\t * this text, the Tk_ManageGeometry call will cause the entry to be\n\t * removed, which could potentially lose the new entry.\n\t */\n\n\thPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,\n\t\tTk_PathName(client->tkwin), &isNew);\n\tTcl_SetHashValue(hPtr, ewPtr);\n    }\n\n    /*\n     * See if there's room for this window on this line.\n     */\n\n  gotWindow:\n    if (ewPtr->body.ew.tkwin == NULL) {\n\twidth = 0;\n\theight = 0;\n    } else {\n\tif (ewPtr->body.ew.padXObj) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, ewPtr->body.ew.padXObj, &padX);\n\n\t}\n\tif (ewPtr->body.ew.padYObj) {\n\t    Tk_GetPixelsFromObj(NULL, textPtr->tkwin, ewPtr->body.ew.padYObj, &padY);\n\n\t}\n\twidth = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2 * padX;\n\theight = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2 * padY;\n    }\n    if ((width > (maxX - chunkPtr->x))\n\t    && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {\n\treturn 0;\n    }\n\n    /*\n     * Fill in the chunk structure.\n     */\n\n    chunkPtr->displayProc = TkTextEmbWinDisplayProc;\n    chunkPtr->undisplayProc = EmbWinUndisplayProc;\n    chunkPtr->measureProc = NULL;\n    chunkPtr->bboxProc = EmbWinBboxProc;\n    chunkPtr->numBytes = 1;\n    if (ewPtr->body.ew.align == TK_ALIGN_BASELINE) {\n\tchunkPtr->minAscent = height - padY;\n\tchunkPtr->minDescent = padY;\n\tchunkPtr->minHeight = 0;\n    } else {\n\tchunkPtr->minAscent = 0;\n\tchunkPtr->minDescent = 0;\n\tchunkPtr->minHeight = height;\n    }\n    chunkPtr->width = width;\n    chunkPtr->breakIndex = -1;\n    chunkPtr->breakIndex = 1;\n    chunkPtr->clientData = ewPtr;\n    if (client != NULL) {\n\tclient->chunkCount += 1;\n    }\n    return 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinCheckProc --\n *\n *\tThis function is invoked by the B-tree code to perform consistency\n *\tchecks on embedded windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe function panics if it detects anything wrong with the embedded\n *\twindow.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinCheckProc(\n    TkTextSegment *ewPtr,\t/* Segment to check. */\n    TCL_UNUSED(TkTextLine *))\t/* Line containing segment. */\n{\n    if (ewPtr->nextPtr == NULL) {\n\tTcl_Panic(\"EmbWinCheckProc: embedded window is last segment in line\");\n    }\n    if (ewPtr->size != 1) {\n\tTcl_Panic(\"EmbWinCheckProc: embedded window has size %\" TCL_Z_MODIFIER \"d\", ewPtr->size);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextEmbWinDisplayProc --\n *\n *\tThis function is invoked by the text displaying code when it is time\n *\tto actually draw an embedded window chunk on the screen.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe embedded window gets moved to the correct location and mapped onto\n *\tthe screen.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkTextEmbWinDisplayProc(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    TkTextDispChunk *chunkPtr,\t/* Chunk that is to be drawn. */\n    int x,\t\t\t/* X-position in dst at which to draw this\n\t\t\t\t * chunk (differs from the x-position in the\n\t\t\t\t * chunk because of scrolling). */\n    TCL_UNUSED(int),\t/* Top of rectangular bounding box for line:\n\t\t\t\t * tells where to draw this chunk in dst\n\t\t\t\t * (x-position is in the chunk itself). */\n    int lineHeight,\t\t/* Total height of line. */\n    int baseline,\t\t/* Offset of baseline from y. */\n    TCL_UNUSED(Display *),\t/* Display to use for drawing (unused).  */\n    TCL_UNUSED(Drawable),\t/* Pixmap or window in which to draw\n\t\t\t\t * (unused).  */\n    int screenY)\t\t/* Y-coordinate in text window that\n\t\t\t\t * corresponds to y. */\n{\n    int lineX, windowX, windowY, width, height;\n    Tk_Window tkwin;\n    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;\n    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);\n\n    if (client == NULL) {\n\treturn;\n    }\n\n    tkwin = client->tkwin;\n    if (tkwin == NULL) {\n\treturn;\n    }\n\n    if ((x + chunkPtr->width) <= 0) {\n\t/*\n\t * The window is off-screen; just unmap it.\n\t */\n\n\tif (textPtr->tkwin != Tk_Parent(tkwin)) {\n\t    Tk_UnmaintainGeometry(tkwin, textPtr->tkwin);\n\t} else {\n\t    Tk_UnmapWindow(tkwin);\n\t}\n\treturn;\n    }\n\n    /*\n     * Compute the window's location and size in the text widget, taking into\n     * account the align and stretch values for the window.\n     */\n\n    EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline,\n\t    &lineX, &windowY, &width, &height);\n    windowX = lineX - chunkPtr->x + x;\n\n    /*\n     * Mark the window as displayed so that it won't get unmapped.\n     * This needs to be done before the next instruction block because\n     * Tk_MaintainGeometry/Tk_MapWindow will run event handlers, in\n     * particular for the <Map> event, and if the bound script deletes\n     * the embedded window its clients will get freed.\n     */\n\n    client->displayed = true;\n\n    if (textPtr->tkwin == Tk_Parent(tkwin)) {\n\tif ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))\n\t\t|| (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))\n\t\t|| (height != Tk_Height(tkwin))) {\n\t    Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);\n\t}\n\tTk_MapWindow(tkwin);\n    } else {\n\tTk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,\n\t\twidth, height);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinUndisplayProc --\n *\n *\tThis function is called when the chunk for an embedded window is no\n *\tlonger going to be displayed. It arranges for the window associated\n *\twith the chunk to be unmapped.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is scheduled for unmapping.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinUndisplayProc(\n    TkText *textPtr,\t\t/* Overall information about text widget. */\n    TkTextDispChunk *chunkPtr)\t/* Chunk that is about to be freed. */\n{\n    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;\n    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);\n\n    if (client == NULL) {\n\treturn;\n    }\n\n    client->chunkCount--;\n    if (client->chunkCount == 0) {\n\t/*\n\t * Don't unmap the window immediately, since there's a good chance\n\t * that it will immediately be redisplayed, perhaps even in the same\n\t * place. Instead, schedule the window to be unmapped later; the call\n\t * to EmbWinDelayedUnmap will be cancelled in the likely event that\n\t * the unmap becomes unnecessary.\n\t */\n\n\tclient->displayed = false;\n\tTcl_DoWhenIdle(EmbWinDelayedUnmap, client);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinBboxProc --\n *\n *\tThis function is called to compute the bounding box of the area\n *\toccupied by an embedded window.\n *\n * Results:\n *\tThere is no return value. *xPtr and *yPtr are filled in with the\n *\tcoordinates of the upper left corner of the window, and *widthPtr and\n *\t*heightPtr are filled in with the dimensions of the window in pixels.\n *\tNote: not all of the returned bbox is necessarily visible on the\n *\tscreen (the rightmost part might be off-screen to the right, and the\n *\tbottommost part might be off-screen to the bottom).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinBboxProc(\n    TkText *textPtr,\t\t/* Information about text widget. */\n    TkTextDispChunk *chunkPtr,\t/* Chunk containing desired char. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Index of desired character within the\n\t\t\t\t * chunk. */\n    int y,\t\t\t/* Topmost pixel in area allocated for this\n\t\t\t\t * line. */\n    int lineHeight,\t\t/* Total height of line. */\n    int baseline,\t\t/* Location of line's baseline, in pixels\n\t\t\t\t * measured down from y. */\n    int *xPtr, int *yPtr,\t/* Gets filled in with coords of character's\n\t\t\t\t * upper-left pixel. */\n    int *widthPtr,\t\t/* Gets filled in with width of window, in\n\t\t\t\t * pixels. */\n    int *heightPtr)\t\t/* Gets filled in with height of window, in\n\t\t\t\t * pixels. */\n{\n    Tk_Window tkwin;\n    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;\n    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);\n    int padX = 0, padY = 0;\n\n    if (client == NULL) {\n\ttkwin = NULL;\n    } else {\n\ttkwin = client->tkwin;\n    }\n    if (tkwin != NULL) {\n\t*widthPtr = Tk_ReqWidth(tkwin);\n\t*heightPtr = Tk_ReqHeight(tkwin);\n    } else {\n\t*widthPtr = 0;\n\t*heightPtr = 0;\n    }\n    if (ewPtr->body.ew.padXObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, ewPtr->body.ew.padXObj, &padX);\n    }\n    if (ewPtr->body.ew.padYObj) {\n\tTk_GetPixelsFromObj(NULL, textPtr->tkwin, ewPtr->body.ew.padYObj, &padY);\n    }\n    *xPtr = chunkPtr->x + padX;\n    if (ewPtr->body.ew.stretch) {\n\tif (ewPtr->body.ew.align == TK_ALIGN_BASELINE) {\n\t    *heightPtr = baseline - padY;\n\t} else {\n\t    *heightPtr = lineHeight - 2 * padY;\n\t}\n    }\n    switch (ewPtr->body.ew.align) {\n    case TK_ALIGN_BOTTOM:\n\t*yPtr = y + (lineHeight - *heightPtr - padY);\n\tbreak;\n    case TK_ALIGN_CENTER:\n\t*yPtr = y + (lineHeight - *heightPtr)/2;\n\tbreak;\n    case TK_ALIGN_TOP:\n\t*yPtr = y + padY;\n\tbreak;\n    case TK_ALIGN_BASELINE:\n\t*yPtr = y + (baseline - *heightPtr);\n\tbreak;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinDelayedUnmap --\n *\n *\tThis function is an idle handler that does the actual work of\n *\tunmapping an embedded window. See the comment in EmbWinUndisplayProc\n *\tfor details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window gets unmapped, unless its chunk reference count has become\n *\tnon-zero again.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nEmbWinDelayedUnmap(\n    void *clientData)\t/* Token for the window to be unmapped. */\n{\n    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;\n\n    if (!client->displayed && (client->tkwin != NULL)) {\n\tif (client->textPtr->tkwin != Tk_Parent(client->tkwin)) {\n\t    Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin);\n\t} else {\n\t    Tk_UnmapWindow(client->tkwin);\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkTextWindowIndex --\n *\n *\tGiven the name of an embedded window within a text widget, returns an\n *\tindex corresponding to the window's position in the text.\n *\n * Results:\n *\tThe return value is TCL_OK if there is an embedded window by the given\n *\tname in the text widget, TCL_ERROR otherwise. If the window exists,\n *\t*indexPtr is filled in with its index.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkTextWindowIndex(\n    TkText *textPtr,\t\t/* Text widget containing window. */\n    const char *name,\t\t/* Name of window. */\n    TkTextIndex *indexPtr)\t/* Index information gets stored here. */\n{\n    Tcl_HashEntry *hPtr;\n    TkTextSegment *ewPtr;\n\n    if (textPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name);\n    if (hPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    ewPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);\n    indexPtr->tree = textPtr->sharedTextPtr->tree;\n    indexPtr->linePtr = ewPtr->body.ew.linePtr;\n    indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);\n\n    /*\n     * If indexPtr refers to somewhere outside the -startline/-endline\n     * range limits of the widget, error out since the window indeed is not\n     * reachable from this text widget (it may be reachable from a peer).\n     */\n\n    if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, true) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * EmbWinGetClient --\n *\n *\tGiven a text widget and a segment which contains an embedded window,\n *\tfind the text-widget specific information about the embedded window,\n *\tif any.\n *\n *\tThis function performs a completely linear lookup for a matching data\n *\tstructure. If we envisage using this code with dozens of peer widgets,\n *\tthen performance could become an issue and a more sophisticated lookup\n *\tmechanism might be desirable.\n *\n * Results:\n *\tNULL if no widget-specific info exists, otherwise the structure is\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic TkTextEmbWindowClient *\nEmbWinGetClient(\n    const TkText *textPtr,\t/* Information about text widget. */\n    TkTextSegment *ewPtr)\t/* Segment containing embedded window. */\n{\n    TkTextEmbWindowClient *client = ewPtr->body.ew.clients;\n\n    while (client != NULL) {\n\tif (client->textPtr == textPtr) {\n\t    return client;\n\t}\n\tclient = client->next;\n    }\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkTrig.c",
    "content": "/*\n * tkTrig.c --\n *\n *\tThis file contains a collection of trigonometry utility routines that\n *\tare used by Tk and in particular by the canvas code. It also has\n *\tmiscellaneous geometry functions used by canvases.\n *\n * Copyright © 1992-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkCanvas.h\"\n\n#undef MIN\n#define MIN(a,b) (((a) < (b)) ? (a) : (b))\n#undef MAX\n#define MAX(a,b) (((a) > (b)) ? (a) : (b))\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkLineToPoint --\n *\n *\tCompute the distance from a point to a finite line segment.\n *\n * Results:\n *\tThe return value is the distance from the line segment whose\n *\tend-points are *end1Ptr and *end2Ptr to the point given by *pointPtr.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTkLineToPoint(\n    double end1Ptr[],\t\t/* Coordinates of first end-point of line. */\n    double end2Ptr[],\t\t/* Coordinates of second end-point of line. */\n    double pointPtr[])\t\t/* Points to coords for point. */\n{\n    double x, y;\n\n    /*\n     * Compute the point on the line that is closest to the point. This must\n     * be done separately for vertical edges, horizontal edges, and other\n     * edges.\n     */\n\n    if (end1Ptr[0] == end2Ptr[0]) {\n\n\t/*\n\t * Vertical edge.\n\t */\n\n\tx = end1Ptr[0];\n\tif (end1Ptr[1] >= end2Ptr[1]) {\n\t    y = MIN(end1Ptr[1], pointPtr[1]);\n\t    y = MAX(y, end2Ptr[1]);\n\t} else {\n\t    y = MIN(end2Ptr[1], pointPtr[1]);\n\t    y = MAX(y, end1Ptr[1]);\n\t}\n    } else if (end1Ptr[1] == end2Ptr[1]) {\n\n\t/*\n\t * Horizontal edge.\n\t */\n\n\ty = end1Ptr[1];\n\tif (end1Ptr[0] >= end2Ptr[0]) {\n\t    x = MIN(end1Ptr[0], pointPtr[0]);\n\t    x = MAX(x, end2Ptr[0]);\n\t} else {\n\t    x = MIN(end2Ptr[0], pointPtr[0]);\n\t    x = MAX(x, end1Ptr[0]);\n\t}\n    } else {\n\tdouble m1, b1, m2, b2;\n\n\t/*\n\t * The edge is neither horizontal nor vertical. Convert the edge to a\n\t * line equation of the form y = m1*x + b1. Then compute a line\n\t * perpendicular to this edge but passing through the point, also in\n\t * the form y = m2*x + b2.\n\t */\n\n\tm1 = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]);\n\tb1 = end1Ptr[1] - m1*end1Ptr[0];\n\tm2 = -1.0/m1;\n\tb2 = pointPtr[1] - m2*pointPtr[0];\n\tx = (b2 - b1)/(m1 - m2);\n\ty = m1*x + b1;\n\tif (end1Ptr[0] > end2Ptr[0]) {\n\t    if (x > end1Ptr[0]) {\n\t\tx = end1Ptr[0];\n\t\ty = end1Ptr[1];\n\t    } else if (x < end2Ptr[0]) {\n\t\tx = end2Ptr[0];\n\t\ty = end2Ptr[1];\n\t    }\n\t} else {\n\t    if (x > end2Ptr[0]) {\n\t\tx = end2Ptr[0];\n\t\ty = end2Ptr[1];\n\t    } else if (x < end1Ptr[0]) {\n\t\tx = end1Ptr[0];\n\t\ty = end1Ptr[1];\n\t    }\n\t}\n    }\n\n    /*\n     * Compute the distance to the closest point.\n     */\n\n    return hypot(pointPtr[0] - x, pointPtr[1] - y);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkLineToArea --\n *\n *\tDetermine whether a line lies entirely inside, entirely outside, or\n *\toverlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the line given by end1Ptr and end2Ptr is entirely\n *\toutside the rectangle given by rectPtr. 0 is returned if the polygon\n *\toverlaps the rectangle, and 1 is returned if the polygon is entirely\n *\tinside the rectangle.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkLineToArea(\n    double end1Ptr[],\t\t/* X and y coordinates for one endpoint of\n\t\t\t\t * line. */\n    double end2Ptr[],\t\t/* X and y coordinates for other endpoint of\n\t\t\t\t * line. */\n    double rectPtr[])\t\t/* Points to coords for rectangle, in the\n\t\t\t\t * order x1, y1, x2, y2. X1 must be no larger\n\t\t\t\t * than x2, and y1 no larger than y2. */\n{\n    int inside1, inside2;\n\n    /*\n     * First check the two points individually to see whether they are inside\n     * the rectangle or not.\n     */\n\n    inside1 = (end1Ptr[0] >= rectPtr[0]) && (end1Ptr[0] <= rectPtr[2])\n\t    && (end1Ptr[1] >= rectPtr[1]) && (end1Ptr[1] <= rectPtr[3]);\n    inside2 = (end2Ptr[0] >= rectPtr[0]) && (end2Ptr[0] <= rectPtr[2])\n\t    && (end2Ptr[1] >= rectPtr[1]) && (end2Ptr[1] <= rectPtr[3]);\n    if (inside1 != inside2) {\n\treturn 0;\n    }\n    if (inside1 & inside2) {\n\treturn 1;\n    }\n\n    /*\n     * Both points are outside the rectangle, but still need to check for\n     * intersections between the line and the rectangle. Horizontal and\n     * vertical lines are particularly easy, so handle them separately.\n     */\n\n    if (end1Ptr[0] == end2Ptr[0]) {\n\t/*\n\t * Vertical line.\n\t */\n\n\tif (((end1Ptr[1] >= rectPtr[1]) ^ (end2Ptr[1] >= rectPtr[1]))\n\t\t&& (end1Ptr[0] >= rectPtr[0])\n\t\t&& (end1Ptr[0] <= rectPtr[2])) {\n\t    return 0;\n\t}\n    } else if (end1Ptr[1] == end2Ptr[1]) {\n\t/*\n\t * Horizontal line.\n\t */\n\n\tif (((end1Ptr[0] >= rectPtr[0]) ^ (end2Ptr[0] >= rectPtr[0]))\n\t\t&& (end1Ptr[1] >= rectPtr[1])\n\t\t&& (end1Ptr[1] <= rectPtr[3])) {\n\t    return 0;\n\t}\n    } else {\n\tdouble m, x, y, low, high;\n\n\t/*\n\t * Diagonal line. Compute slope of line and use for intersection\n\t * checks against each of the sides of the rectangle: left, right,\n\t * bottom, top.\n\t */\n\n\tm = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]);\n\tif (end1Ptr[0] < end2Ptr[0]) {\n\t    low = end1Ptr[0];\n\t    high = end2Ptr[0];\n\t} else {\n\t    low = end2Ptr[0];\n\t    high = end1Ptr[0];\n\t}\n\n\t/*\n\t * Left edge.\n\t */\n\n\ty = end1Ptr[1] + (rectPtr[0] - end1Ptr[0])*m;\n\tif ((rectPtr[0] >= low) && (rectPtr[0] <= high)\n\t\t&& (y >= rectPtr[1]) && (y <= rectPtr[3])) {\n\t    return 0;\n\t}\n\n\t/*\n\t * Right edge.\n\t */\n\n\ty += (rectPtr[2] - rectPtr[0])*m;\n\tif ((y >= rectPtr[1]) && (y <= rectPtr[3])\n\t\t&& (rectPtr[2] >= low) && (rectPtr[2] <= high)) {\n\t    return 0;\n\t}\n\n\t/*\n\t * Bottom edge.\n\t */\n\n\tif (end1Ptr[1] < end2Ptr[1]) {\n\t    low = end1Ptr[1];\n\t    high = end2Ptr[1];\n\t} else {\n\t    low = end2Ptr[1];\n\t    high = end1Ptr[1];\n\t}\n\tx = end1Ptr[0] + (rectPtr[1] - end1Ptr[1])/m;\n\tif ((x >= rectPtr[0]) && (x <= rectPtr[2])\n\t\t&& (rectPtr[1] >= low) && (rectPtr[1] <= high)) {\n\t    return 0;\n\t}\n\n\t/*\n\t * Top edge.\n\t */\n\n\tx += (rectPtr[3] - rectPtr[1])/m;\n\tif ((x >= rectPtr[0]) && (x <= rectPtr[2])\n\t\t&& (rectPtr[3] >= low) && (rectPtr[3] <= high)) {\n\t    return 0;\n\t}\n    }\n    return -1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkThickPolyLineToArea --\n *\n *\tThis function is called to determine whether a connected series of\n *\tline segments lies entirely inside, entirely outside, or overlapping a\n *\tgiven rectangular area.\n *\n * Results:\n *\t-1 is returned if the lines are entirely outside the area, 0 if they\n *\toverlap, and 1 if they are entirely inside the given area.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkThickPolyLineToArea(\n    double *coordPtr,\t\t/* Points to an array of coordinates for the\n\t\t\t\t * polyline: x0, y0, x1, y1, ... */\n    Tcl_Size numPoints,\t\t/* Total number of points at *coordPtr. */\n    double width,\t\t/* Width of each line segment. */\n    int capStyle,\t\t/* How are end-points of polyline drawn?\n\t\t\t\t * CapRound, CapButt, or CapProjecting. */\n    int joinStyle,\t\t/* How are joints in polyline drawn?\n\t\t\t\t * JoinMiter, JoinRound, or JoinBevel. */\n    double *rectPtr)\t\t/* Rectangular area to check against. */\n{\n    double radius, poly[10];\n    Tcl_Size count;\n    bool changedMiterToBevel;\t/* Non-zero means that a mitered corner had to\n\t\t\t\t * be treated as beveled after all because the\n\t\t\t\t * angle was < 11 degrees. */\n    int inside;\t\t\t/* Tentative guess about what to return, based\n\t\t\t\t * on all points seen so far: one means\n\t\t\t\t * everything seen so far was inside the area;\n\t\t\t\t * -1 means everything was outside the area.\n\t\t\t\t * 0 means overlap has been found. */\n\n    radius = width/2.0;\n    inside = -1;\n\n    if ((coordPtr[0] >= rectPtr[0]) && (coordPtr[0] <= rectPtr[2])\n\t    && (coordPtr[1] >= rectPtr[1]) && (coordPtr[1] <= rectPtr[3])) {\n\tinside = 1;\n    }\n\n    /*\n     * Iterate through all of the edges of the line, computing a polygon for\n     * each edge and testing the area against that polygon. In addition, there\n     * are additional tests to deal with rounded joints and caps.\n     */\n\n    changedMiterToBevel = false;\n    for (count = numPoints; count >= 2; count--, coordPtr += 2) {\n\t/*\n\t * If rounding is done around the first point of the edge then test a\n\t * circular region around the point with the area.\n\t */\n\n\tif (((capStyle == CapRound) && (count == numPoints))\n\t\t|| ((joinStyle == JoinRound) && (count != numPoints))) {\n\t    poly[0] = coordPtr[0] - radius;\n\t    poly[1] = coordPtr[1] - radius;\n\t    poly[2] = coordPtr[0] + radius;\n\t    poly[3] = coordPtr[1] + radius;\n\t    if (TkOvalToArea(poly, rectPtr) != inside) {\n\t\treturn 0;\n\t    }\n\t}\n\n\t/*\n\t * Compute the polygonal shape corresponding to this edge, consisting\n\t * of two points for the first point of the edge and two points for\n\t * the last point of the edge.\n\t */\n\n\tif (count == numPoints) {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width,\n\t\t    capStyle == CapProjecting, poly, poly+2);\n\t} else if ((joinStyle == JoinMiter) && !changedMiterToBevel) {\n\t    poly[0] = poly[6];\n\t    poly[1] = poly[7];\n\t    poly[2] = poly[4];\n\t    poly[3] = poly[5];\n\t} else {\n\t    TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2);\n\n\t    /*\n\t     * If the last joint was beveled, then also check a polygon\n\t     * comprising the last two points of the previous polygon and the\n\t     * first two from this polygon; this checks the wedges that fill\n\t     * the beveled joint.\n\t     */\n\n\t    if ((joinStyle == JoinBevel) || changedMiterToBevel) {\n\t\tpoly[8] = poly[0];\n\t\tpoly[9] = poly[1];\n\t\tif (TkPolygonToArea(poly, 5, rectPtr) != inside) {\n\t\t    return 0;\n\t\t}\n\t\tchangedMiterToBevel = false;\n\t    }\n\t}\n\tif (count == 2) {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width,\n\t\t    capStyle == CapProjecting, poly+4, poly+6);\n\t} else if (joinStyle == JoinMiter) {\n\t    if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,\n\t\t    (double) width, poly+4, poly+6) == 0) {\n\t\tchangedMiterToBevel = true;\n\t\tTkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4,\n\t\t\tpoly+6);\n\t    }\n\t} else {\n\t    TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6);\n\t}\n\tpoly[8] = poly[0];\n\tpoly[9] = poly[1];\n\tif (TkPolygonToArea(poly, 5, rectPtr) != inside) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * If caps are rounded, check the cap around the final point of the line.\n     */\n\n    if (capStyle == CapRound) {\n\tpoly[0] = coordPtr[0] - radius;\n\tpoly[1] = coordPtr[1] - radius;\n\tpoly[2] = coordPtr[0] + radius;\n\tpoly[3] = coordPtr[1] + radius;\n\tif (TkOvalToArea(poly, rectPtr) != inside) {\n\t    return 0;\n\t}\n    }\n\n    return inside;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkPolygonToPoint --\n *\n *\tCompute the distance from a point to a polygon.\n *\n * Results:\n *\tThe return value is 0.0 if the point referred to by pointPtr is within\n *\tthe polygon referred to by polyPtr and numPoints. Otherwise the return\n *\tvalue is the distance of the point from the polygon.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTkPolygonToPoint(\n    double *polyPtr,\t\t/* Points to an array coordinates for closed\n\t\t\t\t * polygon: x0, y0, x1, y1, ... The polygon\n\t\t\t\t * may be self-intersecting. */\n    Tcl_Size numPoints,\t\t/* Total number of points at *polyPtr. */\n    double *pointPtr)\t\t/* Points to coords for point. */\n{\n    double bestDist;\t\t/* Closest distance between point and any edge\n\t\t\t\t * in polygon. */\n    Tcl_Size intersections;\t\t/* Number of edges in the polygon that\n\t\t\t\t * intersect a ray extending vertically\n\t\t\t\t * upwards from the point to infinity. */\n    Tcl_Size count;\n    double *pPtr;\n\n    /*\n     * Iterate through all of the edges in the polygon, updating bestDist and\n     * intersections.\n     *\n     * TRICKY POINT: when computing intersections, include left x-coordinate\n     * of line within its range, but not y-coordinate. Otherwise if the point\n     * lies exactly below a vertex we'll count it as two intersections.\n     */\n\n    bestDist = 1.0e36;\n    intersections = 0;\n\n    for (count = numPoints, pPtr = polyPtr; count > 1; count--, pPtr += 2) {\n\tdouble x, y, dist;\n\n\t/*\n\t * Compute the point on the current edge closest to the point and\n\t * update the intersection count. This must be done separately for\n\t * vertical edges, horizontal edges, and other edges.\n\t */\n\n\tif (pPtr[2] == pPtr[0]) {\n\n\t    /*\n\t     * Vertical edge.\n\t     */\n\n\t    x = pPtr[0];\n\t    if (pPtr[1] >= pPtr[3]) {\n\t\ty = MIN(pPtr[1], pointPtr[1]);\n\t\ty = MAX(y, pPtr[3]);\n\t    } else {\n\t\ty = MIN(pPtr[3], pointPtr[1]);\n\t\ty = MAX(y, pPtr[1]);\n\t    }\n\t} else if (pPtr[3] == pPtr[1]) {\n\n\t    /*\n\t     * Horizontal edge.\n\t     */\n\n\t    y = pPtr[1];\n\t    if (pPtr[0] >= pPtr[2]) {\n\t\tx = MIN(pPtr[0], pointPtr[0]);\n\t\tx = MAX(x, pPtr[2]);\n\t\tif ((pointPtr[1] < y) && (pointPtr[0] < pPtr[0])\n\t\t\t&& (pointPtr[0] >= pPtr[2])) {\n\t\t    intersections++;\n\t\t}\n\t    } else {\n\t\tx = MIN(pPtr[2], pointPtr[0]);\n\t\tx = MAX(x, pPtr[0]);\n\t\tif ((pointPtr[1] < y) && (pointPtr[0] < pPtr[2])\n\t\t\t&& (pointPtr[0] >= pPtr[0])) {\n\t\t    intersections++;\n\t\t}\n\t    }\n\t} else {\n\t    double m1, b1, m2, b2;\n\t    int lower;\t\t/* Non-zero means point below line. */\n\n\t    /*\n\t     * The edge is neither horizontal nor vertical. Convert the edge\n\t     * to a line equation of the form y = m1*x + b1. Then compute a\n\t     * line perpendicular to this edge but passing through the point,\n\t     * also in the form y = m2*x + b2.\n\t     */\n\n\t    m1 = (pPtr[3] - pPtr[1])/(pPtr[2] - pPtr[0]);\n\t    b1 = pPtr[1] - m1*pPtr[0];\n\t    m2 = -1.0/m1;\n\t    b2 = pointPtr[1] - m2*pointPtr[0];\n\t    x = (b2 - b1)/(m1 - m2);\n\t    y = m1*x + b1;\n\t    if (pPtr[0] > pPtr[2]) {\n\t\tif (x > pPtr[0]) {\n\t\t    x = pPtr[0];\n\t\t    y = pPtr[1];\n\t\t} else if (x < pPtr[2]) {\n\t\t    x = pPtr[2];\n\t\t    y = pPtr[3];\n\t\t}\n\t    } else {\n\t\tif (x > pPtr[2]) {\n\t\t    x = pPtr[2];\n\t\t    y = pPtr[3];\n\t\t} else if (x < pPtr[0]) {\n\t\t    x = pPtr[0];\n\t\t    y = pPtr[1];\n\t\t}\n\t    }\n\t    lower = (m1*pointPtr[0] + b1) > pointPtr[1];\n\t    if (lower && (pointPtr[0] >= MIN(pPtr[0], pPtr[2]))\n\t\t    && (pointPtr[0] < MAX(pPtr[0], pPtr[2]))) {\n\t\tintersections++;\n\t    }\n\t}\n\n\t/*\n\t * Compute the distance to the closest point, and see if that is the\n\t * best distance seen so far.\n\t */\n\n\tdist = hypot(pointPtr[0] - x, pointPtr[1] - y);\n\tif (dist < bestDist) {\n\t    bestDist = dist;\n\t}\n    }\n\n    /*\n     * We've processed all of the points. If the number of intersections is\n     * odd, the point is inside the polygon.\n     */\n\n    if (intersections & 0x1) {\n\treturn 0.0;\n    }\n    return bestDist;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkPolygonToArea --\n *\n *\tDetermine whether a polygon lies entirely inside, entirely outside, or\n *\toverlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the polygon given by polyPtr and numPoints is\n *\tentirely outside the rectangle given by rectPtr. 0 is returned if the\n *\tpolygon overlaps the rectangle, and 1 is returned if the polygon is\n *\tentirely inside the rectangle.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkPolygonToArea(\n    double *polyPtr,\t\t/* Points to an array coordinates for closed\n\t\t\t\t * polygon: x0, y0, x1, y1, ... The polygon\n\t\t\t\t * may be self-intersecting. */\n    Tcl_Size numPoints,\t\t/* Total number of points at *polyPtr. */\n    double *rectPtr)\t/* Points to coords for rectangle, in the\n\t\t\t\t * order x1, y1, x2, y2. X1 and y1 must be\n\t\t\t\t * lower-left corner. */\n{\n    int state;\t\t\t/* State of all edges seen so far (-1 means\n\t\t\t\t * outside, 1 means inside, won't ever be\n\t\t\t\t * 0). */\n    Tcl_Size count;\n    double *pPtr;\n\n    /*\n     * Iterate over all of the edges of the polygon and test them against the\n     * rectangle. Can quit as soon as the state becomes \"intersecting\".\n     */\n\n    state = TkLineToArea(polyPtr, polyPtr+2, rectPtr);\n    if (state == 0) {\n\treturn 0;\n    }\n    for (pPtr = polyPtr+2, count = numPoints-1; count >= 2;\n\t    pPtr += 2, count--) {\n\tif (TkLineToArea(pPtr, pPtr+2, rectPtr) != state) {\n\t    return 0;\n\t}\n    }\n\n    /*\n     * If all of the edges were inside the rectangle we're done. If all of the\n     * edges were outside, then the rectangle could still intersect the\n     * polygon (if it's entirely enclosed). Call TkPolygonToPoint to figure\n     * this out.\n     */\n\n    if (state == 1) {\n\treturn 1;\n    }\n    if (TkPolygonToPoint(polyPtr, numPoints, rectPtr) == 0.0) {\n\treturn 0;\n    }\n    return -1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkOvalToPoint --\n *\n *\tComputes the distance from a given point to a given oval, in canvas\n *\tunits.\n *\n * Results:\n *\tThe return value is 0 if the point given by *pointPtr is inside the\n *\toval. If the point isn't inside the oval then the return value is\n *\tapproximately the distance from the point to the oval. If the oval is\n *\tfilled, then anywhere in the interior is considered \"inside\"; if the\n *\toval isn't filled, then \"inside\" means only the area occupied by the\n *\toutline.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\ndouble\nTkOvalToPoint(\n    double ovalPtr[],\t\t/* Pointer to array of four coordinates (x1,\n\t\t\t\t * y1, x2, y2) defining oval's bounding\n\t\t\t\t * box. */\n    double width,\t\t/* Width of outline for oval. */\n    int filled,\t\t\t/* Non-zero means oval should be treated as\n\t\t\t\t * filled; zero means only consider\n\t\t\t\t * outline. */\n    double pointPtr[])\t\t/* Coordinates of point. */\n{\n    double xDelta, yDelta, scaledDistance, distToOutline, distToCenter;\n    double xDiam, yDiam;\n\n    /*\n     * Compute the distance between the center of the oval and the point in\n     * question, using a coordinate system where the oval has been transformed\n     * to a circle with unit radius.\n     */\n\n    xDelta = (pointPtr[0] - (ovalPtr[0] + ovalPtr[2])/2.0);\n    yDelta = (pointPtr[1] - (ovalPtr[1] + ovalPtr[3])/2.0);\n    distToCenter = hypot(xDelta, yDelta);\n    scaledDistance = hypot(xDelta / ((ovalPtr[2] + width - ovalPtr[0])/2.0),\n\t    yDelta / ((ovalPtr[3] + width - ovalPtr[1])/2.0));\n\n    /*\n     * If the scaled distance is greater than 1 then it means no hit. Compute\n     * the distance from the point to the edge of the circle, then scale this\n     * distance back to the original coordinate system.\n     *\n     * Note: this distance isn't completely accurate. It's only an\n     * approximation, and it can overestimate the correct distance when the\n     * oval is eccentric.\n     */\n\n    if (scaledDistance > 1.0) {\n\treturn (distToCenter/scaledDistance) * (scaledDistance - 1.0);\n    }\n\n    /*\n     * Scaled distance less than 1 means the point is inside the outer edge of\n     * the oval. If this is a filled oval, then we have a hit. Otherwise, do\n     * the same computation as above (scale back to original coordinate\n     * system), but also check to see if the point is within the width of the\n     * outline.\n     */\n\n    if (filled) {\n\treturn 0.0;\n    }\n    if (scaledDistance > 1E-10) {\n\tdistToOutline = (distToCenter/scaledDistance) * (1.0 - scaledDistance)\n\t\t- width;\n    } else {\n\t/*\n\t * Avoid dividing by a very small number (it could cause an arithmetic\n\t * overflow). This problem occurs if the point is very close to the\n\t * center of the oval.\n\t */\n\n\txDiam = ovalPtr[2] - ovalPtr[0];\n\tyDiam = ovalPtr[3] - ovalPtr[1];\n\tif (xDiam < yDiam) {\n\t    distToOutline = (xDiam - width)/2;\n\t} else {\n\t    distToOutline = (yDiam - width)/2;\n\t}\n    }\n\n    if (distToOutline < 0.0) {\n\treturn 0.0;\n    }\n    return distToOutline;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkOvalToArea --\n *\n *\tDetermine whether an oval lies entirely inside, entirely outside, or\n *\toverlapping a given rectangular area.\n *\n * Results:\n *\t-1 is returned if the oval described by ovalPtr is entirely outside\n *\tthe rectangle given by rectPtr. 0 is returned if the oval overlaps the\n *\trectangle, and 1 is returned if the oval is entirely inside the\n *\trectangle.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkOvalToArea(\n    double *ovalPtr,\t/* Points to coordinates defining the\n\t\t\t\t * bounding rectangle for the oval: x1, y1,\n\t\t\t\t * x2, y2. X1 must be less than x2 and y1 less\n\t\t\t\t * than y2. */\n    double *rectPtr)\t/* Points to coords for rectangle, in the\n\t\t\t\t * order x1, y1, x2, y2. X1 and y1 must be\n\t\t\t\t * lower-left corner. */\n{\n    double centerX, centerY, radX, radY, deltaX, deltaY;\n\n    /*\n     * First, see if oval is entirely inside rectangle or entirely outside\n     * rectangle.\n     */\n\n    if ((rectPtr[0] <= ovalPtr[0]) && (rectPtr[2] >= ovalPtr[2])\n\t    && (rectPtr[1] <= ovalPtr[1]) && (rectPtr[3] >= ovalPtr[3])) {\n\treturn 1;\n    }\n    if ((rectPtr[2] < ovalPtr[0]) || (rectPtr[0] > ovalPtr[2])\n\t    || (rectPtr[3] < ovalPtr[1]) || (rectPtr[1] > ovalPtr[3])) {\n\treturn -1;\n    }\n\n    /*\n     * Next, go through the rectangle side by side. For each side of the\n     * rectangle, find the point on the side that is closest to the oval's\n     * center, and see if that point is inside the oval. If at least one such\n     * point is inside the oval, then the rectangle intersects the oval.\n     */\n\n    centerX = (ovalPtr[0] + ovalPtr[2])/2;\n    centerY = (ovalPtr[1] + ovalPtr[3])/2;\n    radX = (ovalPtr[2] - ovalPtr[0])/2;\n    radY = (ovalPtr[3] - ovalPtr[1])/2;\n\n    deltaY = rectPtr[1] - centerY;\n    if (deltaY < 0.0) {\n\tdeltaY = centerY - rectPtr[3];\n\tif (deltaY < 0.0) {\n\t    deltaY = 0;\n\t}\n    }\n    deltaY /= radY;\n    deltaY *= deltaY;\n\n    /*\n     * Left side:\n     */\n\n    deltaX = (rectPtr[0] - centerX)/radX;\n    deltaX *= deltaX;\n    if ((deltaX + deltaY) <= 1.0) {\n\treturn 0;\n    }\n\n    /*\n     * Right side:\n     */\n\n    deltaX = (rectPtr[2] - centerX)/radX;\n    deltaX *= deltaX;\n    if ((deltaX + deltaY) <= 1.0) {\n\treturn 0;\n    }\n\n    deltaX = rectPtr[0] - centerX;\n    if (deltaX < 0.0) {\n\tdeltaX = centerX - rectPtr[2];\n\tif (deltaX < 0.0) {\n\t    deltaX = 0;\n\t}\n    }\n    deltaX /= radX;\n    deltaX *= deltaX;\n\n    /*\n     * Bottom side:\n     */\n\n    deltaY = (rectPtr[1] - centerY)/radY;\n    deltaY *= deltaY;\n    if ((deltaX + deltaY) < 1.0) {\n\treturn 0;\n    }\n\n    /*\n     * Top side:\n     */\n\n    deltaY = (rectPtr[3] - centerY)/radY;\n    deltaY *= deltaY;\n    if ((deltaX + deltaY) < 1.0) {\n\treturn 0;\n    }\n\n    return -1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkIncludePoint --\n *\n *\tGiven a point and a generic canvas item header, expand the item's\n *\tbounding box if needed to include the point.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe boudn.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkIncludePoint(\n    Tk_Item *itemPtr,\t/* Item whose bounding box is being\n\t\t\t\t * calculated. */\n    double *pointPtr)\t\t/* Address of two doubles giving x and y\n\t\t\t\t * coordinates of point. */\n{\n    int tmp;\n\n    tmp = (int) (pointPtr[0] + 0.5);\n    if (tmp < itemPtr->x1) {\n\titemPtr->x1 = tmp;\n    }\n    if (tmp > itemPtr->x2) {\n\titemPtr->x2 = tmp;\n    }\n    tmp = (int) (pointPtr[1] + 0.5);\n    if (tmp < itemPtr->y1) {\n\titemPtr->y1 = tmp;\n    }\n    if (tmp > itemPtr->y2) {\n\titemPtr->y2 = tmp;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkBezierScreenPoints --\n *\n *\tGiven four control points, create a larger set of XPoints for a Bezier\n *\tcurve based on the points.\n *\n * Results:\n *\tThe array at *xPointPtr gets filled in with numSteps XPoints\n *\tcorresponding to the Bezier spline defined by the four control points.\n *\tNote: no output point is generated for the first input point, but an\n *\toutput point *is* generated for the last input point.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkBezierScreenPoints(\n    Tk_Canvas canvas,\t\t/* Canvas in which curve is to be drawn. */\n    double control[],\t\t/* Array of coordinates for four control\n\t\t\t\t * points: x0, y0, x1, y1, ... x3 y3. */\n    int numSteps,\t\t/* Number of curve points to generate. */\n    XPoint *xPointPtr)\t/* Where to put new points. */\n{\n    int i;\n    double u, u2, u3, t, t2, t3;\n\n    for (i = 1; i <= numSteps; i++, xPointPtr++) {\n\tt = ((double) i)/((double) numSteps);\n\tt2 = t*t;\n\tt3 = t2*t;\n\tu = 1.0 - t;\n\tu2 = u*u;\n\tu3 = u2*u;\n\tTk_CanvasDrawableCoords(canvas,\n\t\t(control[0]*u3 + 3.0 * (control[2]*t*u2 + control[4]*t2*u)\n\t\t    + control[6]*t3),\n\t\t(control[1]*u3 + 3.0 * (control[3]*t*u2 + control[5]*t2*u)\n\t\t    + control[7]*t3),\n\t\t&xPointPtr->x, &xPointPtr->y);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkBezierPoints --\n *\n *\tGiven four control points, create a larger set of points for a Bezier\n *\tcurve based on the points.\n *\n * Results:\n *\tThe array at *coordPtr gets filled in with 2*numSteps coordinates,\n *\twhich correspond to the Bezier spline defined by the four control\n *\tpoints. Note: no output point is generated for the first input point,\n *\tbut an output point *is* generated for the last input point.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkBezierPoints(\n    double control[],\t\t/* Array of coordinates for four control\n\t\t\t\t * points: x0, y0, x1, y1, ... x3 y3. */\n    int numSteps,\t\t/* Number of curve points to generate. */\n    double *coordPtr)\t/* Where to put new points. */\n{\n    int i;\n    double u, u2, u3, t, t2, t3;\n\n    for (i = 1; i <= numSteps; i++, coordPtr += 2) {\n\tt = ((double) i)/((double) numSteps);\n\tt2 = t*t;\n\tt3 = t2*t;\n\tu = 1.0 - t;\n\tu2 = u*u;\n\tu3 = u2*u;\n\tcoordPtr[0] = control[0]*u3\n\t\t+ 3.0 * (control[2]*t*u2 + control[4]*t2*u) + control[6]*t3;\n\tcoordPtr[1] = control[1]*u3\n\t\t+ 3.0 * (control[3]*t*u2 + control[5]*t2*u) + control[7]*t3;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMakeBezierCurve --\n *\n *\tGiven a set of points, create a new set of points that fit parabolic\n *\tsplines to the line segments connecting the original points. Produces\n *\toutput points in either of two forms.\n *\n *\tNote: the name of this function should *not* be taken to mean that it\n *\tinterprets the input points as directly defining Bezier curves.\n *\tRather, it internally computes a Bezier curve representation of each\n *\tparabolic spline segment. (These Bezier curves are then flattened to\n *\tproduce the points filled into the output arrays.)\n *\n * Results:\n *\tEither or both of the xPoints or dblPoints arrays are filled in. The\n *\treturn value is the number of points placed in the arrays. Note: if\n *\tthe first and last points are the same, then a closed curve is\n *\tgenerated.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkMakeBezierCurve(\n    Tk_Canvas canvas,\t\t/* Canvas in which curve is to be drawn. */\n    double *pointPtr,\t\t/* Array of input coordinates: x0, y0, x1, y1,\n\t\t\t\t * etc.. */\n    int numPoints,\t\t/* Number of points at pointPtr. */\n    int numSteps,\t\t/* Number of steps to use for each spline\n\t\t\t\t * segments (determines smoothness of\n\t\t\t\t * curve). */\n    XPoint xPoints[],\t\t/* Array of XPoints to fill in (e.g. for\n\t\t\t\t * display). NULL means don't fill in any\n\t\t\t\t * XPoints. */\n    double dblPoints[])\t\t/* Array of points to fill in as doubles, in\n\t\t\t\t * the form x0, y0, x1, y1, .... NULL means\n\t\t\t\t * don't fill in anything in this form. Caller\n\t\t\t\t * must make sure that this array has enough\n\t\t\t\t * space. */\n{\n    int closed, outputPoints, i;\n    int numCoords = numPoints*2;\n    double control[8];\n\n    /*\n     * If the curve is a closed one then generate a special spline that spans\n     * the last points and the first ones. Otherwise just put the first point\n     * into the output.\n     */\n\n    if (!pointPtr) {\n\t/*\n\t * Of pointPtr == NULL, this function returns an upper limit of the\n\t * array size to store the coordinates. This can be used to allocate\n\t * storage, before the actual coordinates are calculated.\n\t */\n\n\treturn 1 + numPoints * numSteps;\n    }\n\n    outputPoints = 0;\n    if ((pointPtr[0] == pointPtr[numCoords-2])\n\t    && (pointPtr[1] == pointPtr[numCoords-1])) {\n\tclosed = 1;\n\tcontrol[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0];\n\tcontrol[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1];\n\tcontrol[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0];\n\tcontrol[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1];\n\tcontrol[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2];\n\tcontrol[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3];\n\tcontrol[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];\n\tcontrol[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];\n\tif (xPoints != NULL) {\n\t    Tk_CanvasDrawableCoords(canvas, control[0], control[1],\n\t\t    &xPoints->x, &xPoints->y);\n\t    TkBezierScreenPoints(canvas, control, numSteps, xPoints+1);\n\t    xPoints += numSteps+1;\n\t}\n\tif (dblPoints != NULL) {\n\t    dblPoints[0] = control[0];\n\t    dblPoints[1] = control[1];\n\t    TkBezierPoints(control, numSteps, dblPoints+2);\n\t    dblPoints += 2*(numSteps+1);\n\t}\n\toutputPoints += numSteps+1;\n    } else {\n\tclosed = 0;\n\tif (xPoints != NULL) {\n\t    Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],\n\t\t    &xPoints->x, &xPoints->y);\n\t    xPoints += 1;\n\t}\n\tif (dblPoints != NULL) {\n\t    dblPoints[0] = pointPtr[0];\n\t    dblPoints[1] = pointPtr[1];\n\t    dblPoints += 2;\n\t}\n\toutputPoints += 1;\n    }\n\n    for (i = 2; i < numPoints; i++, pointPtr += 2) {\n\t/*\n\t * Set up the first two control points. This is done differently for\n\t * the first spline of an open curve than for other cases.\n\t */\n\n\tif ((i == 2) && !closed) {\n\t    control[0] = pointPtr[0];\n\t    control[1] = pointPtr[1];\n\t    control[2] = 0.333*pointPtr[0] + 0.667*pointPtr[2];\n\t    control[3] = 0.333*pointPtr[1] + 0.667*pointPtr[3];\n\t} else {\n\t    control[0] = 0.5*pointPtr[0] + 0.5*pointPtr[2];\n\t    control[1] = 0.5*pointPtr[1] + 0.5*pointPtr[3];\n\t    control[2] = 0.167*pointPtr[0] + 0.833*pointPtr[2];\n\t    control[3] = 0.167*pointPtr[1] + 0.833*pointPtr[3];\n\t}\n\n\t/*\n\t * Set up the last two control points. This is done differently for\n\t * the last spline of an open curve than for other cases.\n\t */\n\n\tif ((i == (numPoints-1)) && !closed) {\n\t    control[4] = .667*pointPtr[2] + .333*pointPtr[4];\n\t    control[5] = .667*pointPtr[3] + .333*pointPtr[5];\n\t    control[6] = pointPtr[4];\n\t    control[7] = pointPtr[5];\n\t} else {\n\t    control[4] = .833*pointPtr[2] + .167*pointPtr[4];\n\t    control[5] = .833*pointPtr[3] + .167*pointPtr[5];\n\t    control[6] = 0.5*pointPtr[2] + 0.5*pointPtr[4];\n\t    control[7] = 0.5*pointPtr[3] + 0.5*pointPtr[5];\n\t}\n\n\t/*\n\t * If the first two points coincide, or if the last two points\n\t * coincide, then generate a single straight-line segment by\n\t * outputting the last control point.\n\t */\n\n\tif (((pointPtr[0] == pointPtr[2]) && (pointPtr[1] == pointPtr[3]))\n\t\t|| ((pointPtr[2] == pointPtr[4])\n\t\t&& (pointPtr[3] == pointPtr[5]))) {\n\t    if (xPoints != NULL) {\n\t\tTk_CanvasDrawableCoords(canvas, control[6], control[7],\n\t\t\t&xPoints[0].x, &xPoints[0].y);\n\t\txPoints++;\n\t    }\n\t    if (dblPoints != NULL) {\n\t\tdblPoints[0] = control[6];\n\t\tdblPoints[1] = control[7];\n\t\tdblPoints += 2;\n\t    }\n\t    outputPoints += 1;\n\t    continue;\n\t}\n\n\t/*\n\t * Generate a Bezier spline using the control points.\n\t */\n\n\n\tif (xPoints != NULL) {\n\t    TkBezierScreenPoints(canvas, control, numSteps, xPoints);\n\t    xPoints += numSteps;\n\t}\n\tif (dblPoints != NULL) {\n\t    TkBezierPoints(control, numSteps, dblPoints);\n\t    dblPoints += 2*numSteps;\n\t}\n\toutputPoints += numSteps;\n    }\n    return outputPoints;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMakeRawCurve --\n *\n *\tInterpret the given set of points as the raw knots and control points\n *\tdefining a sequence of cubic Bezier curves. Create a new set of points\n *\tthat fit these Bezier curves. Output points are produced in either of\n *\ttwo forms.\n *\n * Results:\n *\tEither or both of the xPoints or dblPoints arrays are filled in. The\n *\treturn value is the number of points placed in the arrays.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkMakeRawCurve(\n    Tk_Canvas canvas,\t\t/* Canvas in which curve is to be drawn. */\n    double *pointPtr,\t\t/* Array of input coordinates: x0, y0, x1, y1,\n\t\t\t\t * etc.. */\n    int numPoints,\t\t/* Number of points at pointPtr. */\n    int numSteps,\t\t/* Number of steps to use for each curve\n\t\t\t\t * segment (determines smoothness of\n\t\t\t\t * curve). */\n    XPoint xPoints[],\t\t/* Array of XPoints to fill in (e.g. for\n\t\t\t\t * display). NULL means don't fill in any\n\t\t\t\t * XPoints. */\n    double dblPoints[])\t\t/* Array of points to fill in as doubles, in\n\t\t\t\t * the form x0, y0, x1, y1, .... NULL means\n\t\t\t\t * don't fill in anything in this form.\n\t\t\t\t * Caller must make sure that this array has\n\t\t\t\t * enough space. */\n{\n    int outputPoints, i;\n    int numSegments = (numPoints+1)/3;\n    double *segPtr;\n\n    /*\n     * The input describes a curve with s Bezier curve segments if there are\n     * 3s+1, 3s, or 3s-1 input points. In the last two cases, 1 or 2 initial\n     * points from the first curve segment are reused as defining points also\n     * for the last curve segment. In the case of 3s input points, this will\n     * automatically close the curve.\n     */\n\n    if (!pointPtr) {\n\t/*\n\t * If pointPtr == NULL, this function returns an upper limit of the\n\t * array size to store the coordinates. This can be used to allocate\n\t * storage, before the actual coordinates are calculated.\n\t */\n\n\treturn 1 + numSegments * numSteps;\n    }\n\n    outputPoints = 0;\n    if (xPoints != NULL) {\n\tTk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],\n\t\t&xPoints->x, &xPoints->y);\n\txPoints += 1;\n    }\n    if (dblPoints != NULL) {\n\tdblPoints[0] = pointPtr[0];\n\tdblPoints[1] = pointPtr[1];\n\tdblPoints += 2;\n    }\n    outputPoints += 1;\n\n    /*\n     * The next loop handles all curve segments except one that overlaps the\n     * end of the list of coordinates.\n     */\n\n    for (i=numPoints,segPtr=pointPtr ; i>=4 ; i-=3,segPtr+=6) {\n\tif (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] &&\n\t\tsegPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) {\n\t    /*\n\t     * The control points on this segment are equal to their\n\t     * neighbouring knots, so this segment is just a straight line. A\n\t     * single point is sufficient.\n\t     */\n\n\t    if (xPoints != NULL) {\n\t\tTk_CanvasDrawableCoords(canvas, segPtr[6], segPtr[7],\n\t\t\t&xPoints->x, &xPoints->y);\n\t\txPoints += 1;\n\t    }\n\t    if (dblPoints != NULL) {\n\t\tdblPoints[0] = segPtr[6];\n\t\tdblPoints[1] = segPtr[7];\n\t\tdblPoints += 2;\n\t    }\n\t    outputPoints += 1;\n\t} else {\n\t    /*\n\t     * This is a generic Bezier curve segment.\n\t     */\n\n\t    if (xPoints != NULL) {\n\t\tTkBezierScreenPoints(canvas, segPtr, numSteps, xPoints);\n\t\txPoints += numSteps;\n\t    }\n\t    if (dblPoints != NULL) {\n\t\tTkBezierPoints(segPtr, numSteps, dblPoints);\n\t\tdblPoints += 2*numSteps;\n\t    }\n\t    outputPoints += numSteps;\n\t}\n    }\n\n    /*\n     * If at this point i>1, then there is some point which has not yet been\n     * used. Make another curve segment.\n     */\n\n    if (i > 1) {\n\tint j;\n\tdouble control[8];\n\n\t/*\n\t * Copy the relevant coordinates to control[], so that it can be\n\t * passed as a unit to e.g. TkBezierPoints.\n\t */\n\n\tfor (j=0; j<2*i; j++) {\n\t    control[j] = segPtr[j];\n\t}\n\tfor (; j<8; j++) {\n\t    control[j] = pointPtr[j-2*i];\n\t}\n\n\t/*\n\t * Then we just do the same things as above.\n\t */\n\n\tif (control[0]==control[2] && control[1]==control[3] &&\n\t\tcontrol[4]==control[6] && control[5]==control[7]) {\n\t    /*\n\t     * The control points on this segment are equal to their\n\t     * neighbouring knots, so this segment is just a straight line. A\n\t     * single point is sufficient.\n\t     */\n\n\t    if (xPoints != NULL) {\n\t\tTk_CanvasDrawableCoords(canvas, control[6], control[7],\n\t\t\t&xPoints->x, &xPoints->y);\n\t\txPoints += 1;\n\t    }\n\t    if (dblPoints != NULL) {\n\t\tdblPoints[0] = control[6];\n\t\tdblPoints[1] = control[7];\n\t\tdblPoints += 2;\n\t    }\n\t    outputPoints += 1;\n\t} else {\n\t    /*\n\t     * This is a generic Bezier curve segment.\n\t     */\n\n\t    if (xPoints != NULL) {\n\t\tTkBezierScreenPoints(canvas, control, numSteps, xPoints);\n\t\txPoints += numSteps;\n\t    }\n\t    if (dblPoints != NULL) {\n\t\tTkBezierPoints(control, numSteps, dblPoints);\n\t\tdblPoints += 2*numSteps;\n\t    }\n\t    outputPoints += numSteps;\n\t}\n    }\n\n    return outputPoints;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMakeBezierPostscript --\n *\n *\tThis function generates Postscript commands that create a path\n *\tcorresponding to a given Bezier curve.\n *\n * Results:\n *\tNone. Postscript commands to generate the path are appended to the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkMakeBezierPostscript(\n    Tcl_Interp *interp,\t\t/* Interpreter in whose result the Postscript\n\t\t\t\t * is to be stored. */\n    Tk_Canvas canvas,\t\t/* Canvas widget for which the Postscript is\n\t\t\t\t * being generated. */\n    double *pointPtr,\t\t/* Array of input coordinates: x0, y0, x1, y1,\n\t\t\t\t * etc.. */\n    int numPoints)\t\t/* Number of points at pointPtr. */\n{\n    int closed, i;\n    int numCoords = numPoints*2;\n    double control[8];\n    Tcl_Obj *psObj;\n\n    /*\n     * If the curve is a closed one then generate a special spline that spans\n     * the last points and the first ones. Otherwise just put the first point\n     * into the path.\n     */\n\n    if ((pointPtr[0] == pointPtr[numCoords-2])\n\t    && (pointPtr[1] == pointPtr[numCoords-1])) {\n\tclosed = 1;\n\tcontrol[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0];\n\tcontrol[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1];\n\tcontrol[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0];\n\tcontrol[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1];\n\tcontrol[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2];\n\tcontrol[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3];\n\tcontrol[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];\n\tcontrol[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];\n\tpsObj = Tcl_ObjPrintf(\n\t\t\"%.15g %.15g moveto\\n\"\n\t\t\"%.15g %.15g %.15g %.15g %.15g %.15g curveto\\n\",\n\t\tcontrol[0], Tk_CanvasPsY(canvas, control[1]),\n\t\tcontrol[2], Tk_CanvasPsY(canvas, control[3]),\n\t\tcontrol[4], Tk_CanvasPsY(canvas, control[5]),\n\t\tcontrol[6], Tk_CanvasPsY(canvas, control[7]));\n    } else {\n\tclosed = 0;\n\tcontrol[6] = pointPtr[0];\n\tcontrol[7] = pointPtr[1];\n\tpsObj = Tcl_ObjPrintf(\"%.15g %.15g moveto\\n\",\n\t\tcontrol[6], Tk_CanvasPsY(canvas, control[7]));\n    }\n\n    /*\n     * Cycle through all the remaining points in the curve, generating a curve\n     * section for each vertex in the linear path.\n     */\n\n    for (i = numPoints-2, pointPtr += 2; i > 0; i--, pointPtr += 2) {\n\tcontrol[2] = 0.333*control[6] + 0.667*pointPtr[0];\n\tcontrol[3] = 0.333*control[7] + 0.667*pointPtr[1];\n\n\t/*\n\t * Set up the last two control points. This is done differently for\n\t * the last spline of an open curve than for other cases.\n\t */\n\n\tif ((i == 1) && !closed) {\n\t    control[6] = pointPtr[2];\n\t    control[7] = pointPtr[3];\n\t} else {\n\t    control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];\n\t    control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];\n\t}\n\tcontrol[4] = 0.333*control[6] + 0.667*pointPtr[0];\n\tcontrol[5] = 0.333*control[7] + 0.667*pointPtr[1];\n\n\tTcl_AppendPrintfToObj(psObj,\n\t\t\"%.15g %.15g %.15g %.15g %.15g %.15g curveto\\n\",\n\t\tcontrol[2], Tk_CanvasPsY(canvas, control[3]),\n\t\tcontrol[4], Tk_CanvasPsY(canvas, control[5]),\n\t\tcontrol[6], Tk_CanvasPsY(canvas, control[7]));\n    }\n\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMakeRawCurvePostscript --\n *\n *\tThis function interprets the input points as the raw knot and control\n *\tpoints for a curve composed of Bezier curve segments, just like\n *\tTkMakeRawCurve. It generates Postscript commands that create a path\n *\tcorresponding to this given curve.\n *\n * Results:\n *\tNone. Postscript commands to generate the path are appended to the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkMakeRawCurvePostscript(\n    Tcl_Interp *interp,\t\t/* Interpreter in whose result the Postscript\n\t\t\t\t * is to be stored. */\n    Tk_Canvas canvas,\t\t/* Canvas widget for which the Postscript is\n\t\t\t\t * being generated. */\n    double *pointPtr,\t\t/* Array of input coordinates: x0, y0, x1, y1,\n\t\t\t\t * etc.. */\n    int numPoints)\t\t/* Number of points at pointPtr. */\n{\n    int i;\n    double *segPtr;\n    Tcl_Obj *psObj;\n\n    /*\n     * Put the first point into the path.\n     */\n\n    psObj = Tcl_ObjPrintf(\"%.15g %.15g moveto\\n\",\n\t    pointPtr[0], Tk_CanvasPsY(canvas, pointPtr[1]));\n\n    /*\n     * Loop through all the remaining points in the curve, generating a\n     * straight line or curve section for every three of them.\n     */\n\n    for (i=numPoints-1,segPtr=pointPtr ; i>=3 ; i-=3,segPtr+=6) {\n\tif (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] &&\n\t\tsegPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) {\n\t    /*\n\t     * The control points on this segment are equal to their\n\t     * neighbouring knots, so this segment is just a straight line.\n\t     */\n\n\t    Tcl_AppendPrintfToObj(psObj, \"%.15g %.15g lineto\\n\",\n\t\t    segPtr[6], Tk_CanvasPsY(canvas, segPtr[7]));\n\t} else {\n\t    /*\n\t     * This is a generic Bezier curve segment.\n\t     */\n\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%.15g %.15g %.15g %.15g %.15g %.15g curveto\\n\",\n\t\t    segPtr[2], Tk_CanvasPsY(canvas, segPtr[3]),\n\t\t    segPtr[4], Tk_CanvasPsY(canvas, segPtr[5]),\n\t\t    segPtr[6], Tk_CanvasPsY(canvas, segPtr[7]));\n\t}\n    }\n\n    /*\n     * If there are any points left that haven't been used, then build the\n     * last segment and generate Postscript in the same way for that.\n     */\n\n    if (i > 0) {\n\tint j;\n\tdouble control[8];\n\n\tfor (j=0; j<2*i+2; j++) {\n\t    control[j] = segPtr[j];\n\t}\n\tfor (; j<8; j++) {\n\t    control[j] = pointPtr[j-2*i-2];\n\t}\n\n\tif (control[0]==control[2] && control[1]==control[3] &&\n\t\tcontrol[4]==control[6] && control[5]==control[7]) {\n\t    /*\n\t     * Straight line.\n\t     */\n\n\t    Tcl_AppendPrintfToObj(psObj, \"%.15g %.15g lineto\\n\",\n\t\t    control[6], Tk_CanvasPsY(canvas, control[7]));\n\t} else {\n\t    /*\n\t     * Bezier curve segment.\n\t     */\n\n\t    Tcl_AppendPrintfToObj(psObj,\n\t\t    \"%.15g %.15g %.15g %.15g %.15g %.15g curveto\\n\",\n\t\t    control[2], Tk_CanvasPsY(canvas, control[3]),\n\t\t    control[4], Tk_CanvasPsY(canvas, control[5]),\n\t\t    control[6], Tk_CanvasPsY(canvas, control[7]));\n\t}\n    }\n\n    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);\n    Tcl_DecrRefCount(psObj);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkGetMiterPoints --\n *\n *\tGiven three points forming an angle, compute the coordinates of the\n *\tinside and outside points of the mitered corner formed by a line of a\n *\tgiven width at that angle.\n *\n * Results:\n *\tIf the angle formed by the three points is less than 11 degrees then 0\n *\tis returned and m1 and m2 aren't modified. Otherwise 1 is returned and\n *\tthe points at m1 and m2 are filled in with the positions of the points\n *\tof the mitered corner.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nbool\nTkGetMiterPoints(\n    double p1[],\t\t/* Points to x- and y-coordinates of point\n\t\t\t\t * before vertex. */\n    double p2[],\t\t/* Points to x- and y-coordinates of vertex\n\t\t\t\t * for mitered joint. */\n    double p3[],\t\t/* Points to x- and y-coordinates of point\n\t\t\t\t * after vertex. */\n    double width,\t\t/* Width of line. */\n    double m1[],\t\t/* Points to place to put \"left\" vertex point\n\t\t\t\t * (see as you face from p1 to p2). */\n    double m2[])\t\t/* Points to place to put \"right\" vertex\n\t\t\t\t * point. */\n{\n    double theta1;\t\t/* Angle of segment p2-p1. */\n    double theta2;\t\t/* Angle of segment p2-p3. */\n    double theta;\t\t/* Angle between line segments (angle of\n\t\t\t\t * joint). */\n    double theta3;\t\t/* Angle that bisects theta1 and theta2 and\n\t\t\t\t * points to m1. */\n    double dist;\t\t/* Distance of miter points from p2. */\n    double deltaX, deltaY;\t/* X and y offsets cooresponding to dist\n\t\t\t\t * (fudge factors for bounding box). */\n    double p1x, p1y, p2x, p2y, p3x, p3y;\n#ifndef _MSC_VER\n    static const double elevenDegrees = (11.0*2.0*PI)/360.0;\n#else /* msvc8 with -fp:strict requires it this way */\n    static const double elevenDegrees = 0.19198621771937624;\n#endif\n\n    /*\n     * Round the coordinates to integers to mimic what happens when the line\n     * segments are displayed; without this code, the bounding box of a\n     * mitered line can be miscomputed greatly.\n     */\n\n    p1x = floor(p1[0]+0.5);\n    p1y = floor(p1[1]+0.5);\n    p2x = floor(p2[0]+0.5);\n    p2y = floor(p2[1]+0.5);\n    p3x = floor(p3[0]+0.5);\n    p3y = floor(p3[1]+0.5);\n\n    if (p2y == p1y) {\n\ttheta1 = (p2x < p1x) ? 0 : PI;\n    } else if (p2x == p1x) {\n\ttheta1 = (p2y < p1y) ? PI/2.0 : -PI/2.0;\n    } else {\n\ttheta1 = atan2(p1y - p2y, p1x - p2x);\n    }\n\n    if (p3y == p2y) {\n\ttheta2 = (p3x > p2x) ? 0 : PI;\n    } else if (p3x == p2x) {\n\ttheta2 = (p3y > p2y) ? PI/2.0 : -PI/2.0;\n    } else {\n\ttheta2 = atan2(p3y - p2y, p3x - p2x);\n    }\n\n    theta = theta1 - theta2;\n    if (theta > PI) {\n\ttheta -= 2*PI;\n    } else if (theta < -PI) {\n\ttheta += 2*PI;\n    }\n\n    if ((theta < elevenDegrees) && (theta > -elevenDegrees)) {\n\treturn false;\n    }\n\n    dist = 0.5*width/sin(0.5*theta);\n    if (dist < 0.0) {\n\tdist = -dist;\n    }\n\n    /*\n     * Compute theta3 (make sure that it points to the left when looking from\n     * p1 to p2).\n     */\n\n    theta3 = (theta1 + theta2)/2.0;\n    if (sin(theta3 - (theta1 + PI)) < 0.0) {\n\ttheta3 += PI;\n    }\n    deltaX = dist*cos(theta3);\n    m1[0] = p2x + deltaX;\n    m2[0] = p2x - deltaX;\n    deltaY = dist*sin(theta3);\n    m1[1] = p2y + deltaY;\n    m2[1] = p2y - deltaY;\n\n    return true;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkGetButtPoints --\n *\n *\tGiven two points forming a line segment, compute the coordinates of\n *\ttwo endpoints of a rectangle formed by bloating the line segment until\n *\tit is width units wide.\n *\n * Results:\n *\tThere is no return value. M1 and m2 are filled in to correspond to m1\n *\tand m2 in the diagram below:\n *\n *\t\t   ----------------* m1\n *\t\t\t\t   |\n *\t\tp1 *---------------* p2\n *\t\t\t\t   |\n *\t\t   ----------------* m2\n *\n *\tM1 and m2 will be W units apart, with p2 centered between them and\n *\tm1-m2 perpendicular to p1-p2. However, if \"project\" is true then m1\n *\tand m2 will be as follows:\n *\n *\t\t   -------------------* m1\n *\t\t\t\t  p2  |\n *\t\tp1 *---------------*  |\n *\t\t\t\t      |\n *\t\t   -------------------* m2\n *\n *\tIn this case p2 will be width/2 units from the segment m1-m2.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkGetButtPoints(\n    double p1[],\t\t/* Points to x- and y-coordinates of point\n\t\t\t\t * before vertex. */\n    double p2[],\t\t/* Points to x- and y-coordinates of vertex\n\t\t\t\t * for mitered joint. */\n    double width,\t\t/* Width of line. */\n    int project,\t\t/* Non-zero means project p2 by an additional\n\t\t\t\t * width/2 before computing m1 and m2. */\n    double m1[],\t\t/* Points to place to put \"left\" result point,\n\t\t\t\t * as you face from p1 to p2. */\n    double m2[])\t\t/* Points to place to put \"right\" result\n\t\t\t\t * point. */\n{\n    double length;\t\t/* Length of p1-p2 segment. */\n    double deltaX, deltaY;\t/* Increments in coords. */\n\n    width *= 0.5;\n    length = hypot(p2[0] - p1[0], p2[1] - p1[1]);\n    if (length == 0.0) {\n\tm1[0] = m2[0] = p2[0];\n\tm1[1] = m2[1] = p2[1];\n    } else {\n\tdeltaX = -width * (p2[1] - p1[1]) / length;\n\tdeltaY = width * (p2[0] - p1[0]) / length;\n\tm1[0] = p2[0] + deltaX;\n\tm2[0] = p2[0] - deltaX;\n\tm1[1] = p2[1] + deltaY;\n\tm2[1] = p2[1] - deltaY;\n\tif (project) {\n\t    m1[0] += deltaY;\n\t    m2[0] += deltaY;\n\t    m1[1] -= deltaX;\n\t    m2[1] -= deltaX;\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkUndo.c",
    "content": "/*\n * tkUndo.c --\n *\n *\tThis module provides the implementation of an undo stack.\n *\n * Copyright © 2002 Ludwig Callewaert.\n * Copyright © 2003-2004 Vincent Darley.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkUndo.h\"\n\nstatic int\t\tEvaluateActionList(Tcl_Interp *interp,\n\t\t\t    TkUndoSubAtom *action);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoPushStack --\n *\n *\tPush elem on the stack identified by stack.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoPushStack(\n    TkUndoAtom **stack,\n    TkUndoAtom *elem)\n{\n    elem->next = *stack;\n    *stack = elem;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoPopStack --\n *\n *\tRemove and return the top element from the stack identified by stack.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkUndoAtom *\nTkUndoPopStack(\n    TkUndoAtom **stack)\n{\n    TkUndoAtom *elem = NULL;\n\n    if (*stack != NULL) {\n\telem = *stack;\n\t*stack = elem->next;\n    }\n    return elem;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoInsertSeparator --\n *\n *\tInsert a separator on the stack, indicating a border for an undo/redo\n *\tchunk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkUndoInsertSeparator(\n    TkUndoAtom **stack)\n{\n    TkUndoAtom *separator;\n\n    if (*stack!=NULL && (*stack)->type!=TK_UNDO_SEPARATOR) {\n\tseparator = (TkUndoAtom *)Tcl_Alloc(sizeof(TkUndoAtom));\n\tseparator->type = TK_UNDO_SEPARATOR;\n\tTkUndoPushStack(stack,separator);\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoClearStack --\n *\n *\tClear an entire undo or redo stack and destroy all elements in it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoClearStack(\n    TkUndoAtom **stack)\t\t/* An Undo or Redo stack */\n{\n    TkUndoAtom *elem;\n\n    while ((elem = TkUndoPopStack(stack)) != NULL) {\n\tif (elem->type != TK_UNDO_SEPARATOR) {\n\t    TkUndoSubAtom *sub;\n\n\t    sub = elem->apply;\n\t    while (sub != NULL) {\n\t\tTkUndoSubAtom *next = sub->next;\n\n\t\tif (sub->action != NULL) {\n\t\t    Tcl_DecrRefCount(sub->action);\n\t\t}\n\t\tTcl_Free(sub);\n\t\tsub = next;\n\t    }\n\n\t    sub = elem->revert;\n\t    while (sub != NULL) {\n\t\tTkUndoSubAtom *next = sub->next;\n\n\t\tif (sub->action != NULL) {\n\t\t    Tcl_DecrRefCount(sub->action);\n\t\t}\n\t\tTcl_Free(sub);\n\t\tsub = next;\n\t    }\n\t}\n\tTcl_Free(elem);\n    }\n    *stack = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoPushAction --\n *\n *\tPush a new elem on the stack identified by stack. Action and revert\n *\tare given through Tcl_Obj's to which we will retain a reference. (So\n *\tthey can be passed in with a zero refCount if desired).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoPushAction(\n    TkUndoRedoStack *stack,\t/* An Undo or Redo stack */\n    TkUndoSubAtom *apply,\n    TkUndoSubAtom *revert)\n{\n    TkUndoAtom *atom;\n\n    atom = (TkUndoAtom *)Tcl_Alloc(sizeof(TkUndoAtom));\n    atom->type = TK_UNDO_ACTION;\n    atom->apply = apply;\n    atom->revert = revert;\n\n    TkUndoPushStack(&stack->undoStack, atom);\n    TkUndoClearStack(&stack->redoStack);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoMakeCmdSubAtom --\n *\n *\tCreate a new undo/redo step which must later be place into an undo\n *\tstack with TkUndoPushAction. This sub-atom, if evaluated, will take\n *\tthe given command (if non-NULL), find its full Tcl command string, and\n *\tthen evaluate that command with the list elements of 'actionScript'\n *\tappended.\n *\n *\tIf 'subAtomList' is non-NULL, the newly created sub-atom is added onto\n *\tthe end of the linked list of which 'subAtomList' is a part. This\n *\tmakes it easy to build up a sequence of actions which will be pushed\n *\tin one step.\n *\n *\tNote: if the undo stack can persist for longer than the Tcl_Command\n *\tprovided, the stack will cause crashes when actions are evaluated. In\n *\tthis case the 'command' argument should not be used. This is the case\n *\twith peer text widgets, for example.\n *\n * Results:\n *\tThe newly created subAtom is returned. It must be passed to\n *\tTkUndoPushAction otherwise a memory leak will result.\n *\n * Side effects:\n *\tA refCount is retained on 'actionScript'.\n *\n *----------------------------------------------------------------------\n */\n\nTkUndoSubAtom *\nTkUndoMakeCmdSubAtom(\n    Tcl_Command command,\t/* Tcl command token for actions, may be NULL\n\t\t\t\t * if not needed. */\n    Tcl_Obj *actionScript,\t/* The script to append to the command to\n\t\t\t\t * perform the action (may be NULL if the\n\t\t\t\t * command is not-null). */\n    TkUndoSubAtom *subAtomList)\t/* Add to the end of this list of actions if\n\t\t\t\t * non-NULL */\n{\n    TkUndoSubAtom *atom;\n\n    if (command == NULL && actionScript == NULL) {\n\tTcl_Panic(\"NULL command and actionScript in TkUndoMakeCmdSubAtom\");\n    }\n\n    atom = (TkUndoSubAtom *)Tcl_Alloc(sizeof(TkUndoSubAtom));\n    atom->command = command;\n    atom->funcPtr = NULL;\n    atom->clientData = NULL;\n    atom->next = NULL;\n    atom->action = actionScript;\n    if (atom->action != NULL) {\n\tTcl_IncrRefCount(atom->action);\n    }\n\n    if (subAtomList != NULL) {\n\twhile (subAtomList->next != NULL) {\n\t    subAtomList = subAtomList->next;\n\t}\n\tsubAtomList->next = atom;\n    }\n    return atom;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoMakeSubAtom --\n *\n *\tCreate a new undo/redo step which must later be place into an undo\n *\tstack with TkUndoPushAction. This sub-atom, if evaluated, will take\n *\tthe given C-funcPtr (which must be non-NULL), and call it with three\n *\targuments: the undo stack's 'interp', the 'clientData' given and the\n *\t'actionScript'. The callback should return a standard Tcl return code\n *\t(TCL_OK on success).\n *\n *\tIf 'subAtomList' is non-NULL, the newly created sub-atom is added onto\n *\tthe end of the linked list of which 'subAtomList' is a part. This\n *\tmakes it easy to build up a sequence of actions which will be pushed\n *\tin one step.\n *\n * Results:\n *\tThe newly created subAtom is returned. It must be passed to\n *\tTkUndoPushAction otherwise a memory leak will result.\n *\n * Side effects:\n *\tA refCount is retained on 'actionScript'.\n *\n *----------------------------------------------------------------------\n */\n\nTkUndoSubAtom *\nTkUndoMakeSubAtom(\n    TkUndoProc *funcPtr,\t/* Callback function to perform the\n\t\t\t\t * undo/redo. */\n    void *clientData,\t/* Data to pass to the callback function. */\n    Tcl_Obj *actionScript,\t/* Additional Tcl data to pass to the callback\n\t\t\t\t * function (may be NULL). */\n    TkUndoSubAtom *subAtomList)\t/* Add to the end of this list of actions if\n\t\t\t\t * non-NULL */\n{\n    TkUndoSubAtom *atom;\n\n    if (funcPtr == NULL) {\n\tTcl_Panic(\"NULL funcPtr in TkUndoMakeSubAtom\");\n    }\n\n    atom = (TkUndoSubAtom *)Tcl_Alloc(sizeof(TkUndoSubAtom));\n    atom->command = NULL;\n    atom->funcPtr = funcPtr;\n    atom->clientData = clientData;\n    atom->next = NULL;\n    atom->action = actionScript;\n    if (atom->action != NULL) {\n\tTcl_IncrRefCount(atom->action);\n    }\n\n    if (subAtomList != NULL) {\n\twhile (subAtomList->next != NULL) {\n\t    subAtomList = subAtomList->next;\n\t}\n\tsubAtomList->next = atom;\n    }\n    return atom;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoInitStack --\n *\n *\tInitialize a new undo/redo stack.\n *\n * Results:\n *\tAn Undo/Redo stack pointer.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkUndoRedoStack *\nTkUndoInitStack(\n    Tcl_Interp *interp,\t\t/* The interpreter */\n    int maxdepth)\t\t/* The maximum stack depth */\n{\n    TkUndoRedoStack *stack;\t/* An Undo/Redo stack */\n\n    stack = (TkUndoRedoStack *)Tcl_Alloc(sizeof(TkUndoRedoStack));\n    stack->undoStack = NULL;\n    stack->redoStack = NULL;\n    stack->interp = interp;\n    stack->maxdepth = maxdepth;\n    stack->depth = 0;\n    return stack;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoSetMaxDepth --\n *\n *\tSet the maximum depth of stack.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay delete elements from the stack if the new maximum depth is smaller\n *\tthan the number of elements previously in the stack.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoSetMaxDepth(\n    TkUndoRedoStack *stack,\t/* An Undo/Redo stack */\n    int maxdepth)\t\t/* The maximum stack depth */\n{\n    stack->maxdepth = maxdepth;\n\n    if (stack->maxdepth>0 && stack->depth>stack->maxdepth) {\n\tTkUndoAtom *elem, *prevelem;\n\tint sepNumber = 0;\n\n\t/*\n\t * Maximum stack depth exceeded. We have to remove the last compound\n\t * elements on the stack.\n\t */\n\n\telem = stack->undoStack;\n\tprevelem = NULL;\n\twhile ((elem != NULL) && (sepNumber <= stack->maxdepth)) {\n\t    if (elem->type == TK_UNDO_SEPARATOR) {\n\t\tsepNumber++;\n\t    }\n\t    prevelem = elem;\n\t    elem = elem->next;\n\t}\n\tCLANG_ASSERT(prevelem);\n\tprevelem->next = NULL;\n\twhile (elem != NULL) {\n\t    prevelem = elem;\n\t    if (elem->type != TK_UNDO_SEPARATOR) {\n\t\tTkUndoSubAtom *sub = elem->apply;\n\t\twhile (sub != NULL) {\n\t\t    TkUndoSubAtom *next = sub->next;\n\n\t\t    if (sub->action != NULL) {\n\t\t\tTcl_DecrRefCount(sub->action);\n\t\t    }\n\t\t    Tcl_Free(sub);\n\t\t    sub = next;\n\t\t}\n\t\tsub = elem->revert;\n\t\twhile (sub != NULL) {\n\t\t    TkUndoSubAtom *next = sub->next;\n\n\t\t    if (sub->action != NULL) {\n\t\t\tTcl_DecrRefCount(sub->action);\n\t\t    }\n\t\t    Tcl_Free(sub);\n\t\t    sub = next;\n\t\t}\n\t    }\n\t    elem = elem->next;\n\t    Tcl_Free(prevelem);\n\t}\n\tstack->depth = stack->maxdepth;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoClearStacks --\n *\n *\tClear both the undo and redo stack.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoClearStacks(\n    TkUndoRedoStack *stack)\t/* An Undo/Redo stack */\n{\n    TkUndoClearStack(&stack->undoStack);\n    TkUndoClearStack(&stack->redoStack);\n    stack->depth = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoFreeStack\n *\n *\tClear both the undo and redo stack and free the memory allocated to\n *\tthe u/r stack pointer.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoFreeStack(\n    TkUndoRedoStack *stack)\t/* An Undo/Redo stack */\n{\n    TkUndoClearStacks(stack);\n    Tcl_Free(stack);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoCanRedo --\n *\n *\tReturns true if redo is possible, i.e. if the redo stack is not empty.\n *\n * Results:\n *\t A boolean.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkUndoCanRedo(\n    TkUndoRedoStack *stack)\t/* An Undo/Redo stack */\n{\n    return stack->redoStack != NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoCanUndo --\n *\n *\tReturns true if undo is possible, i.e. if the undo stack is not empty.\n *\n * Results:\n *\t A boolean.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkUndoCanUndo(\n    TkUndoRedoStack *stack)\t/* An Undo/Redo stack */\n{\n    return stack->undoStack != NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoInsertUndoSeparator --\n *\n *\tInsert a separator on the undo stack, indicating a border for an\n *\tundo/redo chunk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUndoInsertUndoSeparator(\n    TkUndoRedoStack *stack)\n{\n    if (TkUndoInsertSeparator(&stack->undoStack)) {\n\tstack->depth++;\n\tTkUndoSetMaxDepth(stack, stack->maxdepth);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoRevert --\n *\n *\tUndo a compound action on the stack.\n *\n * Results:\n *\tA Tcl status code\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkUndoRevert(\n    TkUndoRedoStack *stack)\n{\n    TkUndoAtom *elem;\n\n    /*\n     * Insert a separator on the undo and the redo stack.\n     */\n\n    TkUndoInsertUndoSeparator(stack);\n    TkUndoInsertSeparator(&stack->redoStack);\n\n    /*\n     * Pop and skip the first separator if there is one.\n     */\n\n    elem = TkUndoPopStack(&stack->undoStack);\n    if (elem == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    if (elem->type == TK_UNDO_SEPARATOR) {\n\tTcl_Free(elem);\n\telem = TkUndoPopStack(&stack->undoStack);\n    }\n\n    while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) {\n\t/*\n\t * Note that we currently ignore errors thrown here.\n\t */\n\n\tEvaluateActionList(stack->interp, elem->revert);\n\n\tTkUndoPushStack(&stack->redoStack, elem);\n\telem = TkUndoPopStack(&stack->undoStack);\n    }\n\n    /*\n     * Insert a separator on the redo stack.\n     */\n\n    TkUndoInsertSeparator(&stack->redoStack);\n    stack->depth--;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUndoApply --\n *\n *\tRedo a compound action on the stack.\n *\n * Results:\n *\tA Tcl status code\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkUndoApply(\n    TkUndoRedoStack *stack)\n{\n    TkUndoAtom *elem;\n\n    /*\n     * Insert a separator on the undo stack.\n     */\n\n    TkUndoInsertSeparator(&stack->undoStack);\n\n    /*\n     * Pop and skip the first separator if there is one.\n     */\n\n    elem = TkUndoPopStack(&stack->redoStack);\n    if (elem == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    if (elem->type == TK_UNDO_SEPARATOR) {\n\tTcl_Free(elem);\n\telem = TkUndoPopStack(&stack->redoStack);\n    }\n\n    while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) {\n\t/*\n\t * Note that we currently ignore errors thrown here.\n\t */\n\n\tEvaluateActionList(stack->interp, elem->apply);\n\n\tTkUndoPushStack(&stack->undoStack, elem);\n\telem = TkUndoPopStack(&stack->redoStack);\n    }\n\n    /*\n     * Insert a separator on the undo stack.\n     */\n\n    TkUndoInsertSeparator(&stack->undoStack);\n    stack->depth++;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EvaluateActionList --\n *\n *\tExecute a linked list of undo/redo sub-atoms. If any sub-atom returns\n *\ta non TCL_OK value, execution of subsequent sub-atoms is cancelled and\n *\tthe error returned immediately.\n *\n * Results:\n *\tA Tcl status code\n *\n * Side effects:\n *\tThe undo/redo subAtoms can perform arbitrary actions.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nEvaluateActionList(\n    Tcl_Interp *interp,\t\t/* Interpreter to evaluate the action in. */\n    TkUndoSubAtom *action)\t/* Head of linked list of action steps to\n\t\t\t\t * perform. */\n{\n    int result = TCL_OK;\n\n    while (action != NULL) {\n\tif (action->funcPtr != NULL) {\n\t    result = action->funcPtr(interp, action->clientData,\n\t\t    action->action);\n\t} else if (action->command != NULL) {\n\t    Tcl_Obj *cmdNameObj, *evalObj;\n\n\t    cmdNameObj = Tcl_NewObj();\n\t    evalObj = Tcl_NewObj();\n\t    Tcl_IncrRefCount(evalObj);\n\t    Tcl_GetCommandFullName(interp, action->command, cmdNameObj);\n\t    Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj);\n\t    if (action->action != NULL) {\n\t\tTcl_ListObjAppendList(NULL, evalObj, action->action);\n\t    }\n\t    result = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL);\n\t    Tcl_DecrRefCount(evalObj);\n\t} else {\n\t    result = Tcl_EvalObjEx(interp, action->action, TCL_EVAL_GLOBAL);\n\t}\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n\taction = action->next;\n    }\n    return result;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkUndo.h",
    "content": "/*\n * tkUndo.h --\n *\n *\tDeclarations shared among the files that implement an undo stack.\n *\n * Copyright © 2002 Ludwig Callewaert.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKUNDO\n#define _TKUNDO\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Enum defining the types used in an undo stack.\n */\n\ntypedef enum {\n    TK_UNDO_SEPARATOR,\t\t/* Marker */\n    TK_UNDO_ACTION\t\t/* Command */\n} TkUndoAtomType;\n\n/*\n * Callback proc type to carry out an undo or redo action via C code. (Actions\n * can also be defined by Tcl scripts).\n */\n\ntypedef int (TkUndoProc)(Tcl_Interp *interp, void *clientData,\n\t\t\tTcl_Obj *objPtr);\n\n/*\n * Struct defining a single action, one or more of which may be defined (and\n * stored in a linked list) separately for each undo and redo action of an\n * undo atom.\n */\n\ntypedef struct TkUndoSubAtom {\n    Tcl_Command command;\t/* Tcl token used to get the current Tcl\n\t\t\t\t * command name which will be used to execute\n\t\t\t\t * apply/revert scripts. If NULL then it is\n\t\t\t\t * assumed the apply/revert scripts already\n\t\t\t\t * contain everything. */\n    TkUndoProc *funcPtr;\t/* Function pointer for callback to perform\n\t\t\t\t * undo/redo actions. */\n    void *clientData;\t/* Data for 'funcPtr'. */\n    Tcl_Obj *action;\t\t/* Command to apply the action that was\n\t\t\t\t * taken. */\n    struct TkUndoSubAtom *next;\t/* Pointer to the next element in the linked\n\t\t\t\t * list. */\n} TkUndoSubAtom;\n\n/*\n * Struct representing a single undo+redo atom to be placed in the stack.\n */\n\ntypedef struct TkUndoAtom {\n    TkUndoAtomType type;\t/* The type that will trigger the required\n\t\t\t\t * action. */\n    TkUndoSubAtom *apply;\t/* Linked list of 'apply' actions to perform\n\t\t\t\t * for this operation. */\n    TkUndoSubAtom *revert;\t/* Linked list of 'revert' actions to perform\n\t\t\t\t * for this operation. */\n    struct TkUndoAtom *next;\t/* Pointer to the next element in the\n\t\t\t\t * stack. */\n} TkUndoAtom;\n\n/*\n * Struct defining a single undo+redo stack.\n */\n\ntypedef struct TkUndoRedoStack {\n    TkUndoAtom *undoStack;\t/* The undo stack. */\n    TkUndoAtom *redoStack;\t/* The redo stack. */\n    Tcl_Interp *interp;\t\t/* The interpreter in which to execute the\n\t\t\t\t * revert and apply scripts. */\n    int maxdepth;\n    int depth;\n} TkUndoRedoStack;\n\n/*\n * Basic functions.\n */\n\nMODULE_SCOPE void\tTkUndoPushStack(TkUndoAtom **stack, TkUndoAtom *elem);\nMODULE_SCOPE TkUndoAtom *TkUndoPopStack(TkUndoAtom **stack);\nMODULE_SCOPE int\tTkUndoInsertSeparator(TkUndoAtom **stack);\nMODULE_SCOPE void\tTkUndoClearStack(TkUndoAtom **stack);\n\n/*\n * Functions for working on an undo/redo stack.\n */\n\nMODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth);\nMODULE_SCOPE void\tTkUndoSetMaxDepth(TkUndoRedoStack *stack, int maxdepth);\nMODULE_SCOPE void\tTkUndoClearStacks(TkUndoRedoStack *stack);\nMODULE_SCOPE void\tTkUndoFreeStack(TkUndoRedoStack *stack);\nMODULE_SCOPE bool\tTkUndoCanRedo(TkUndoRedoStack *stack);\nMODULE_SCOPE bool\tTkUndoCanUndo(TkUndoRedoStack *stack);\nMODULE_SCOPE void\tTkUndoInsertUndoSeparator(TkUndoRedoStack *stack);\nMODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command,\n\t\t\t    Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList);\nMODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr,\n\t\t\t    void *clientData, Tcl_Obj *actionScript,\n\t\t\t    TkUndoSubAtom *subAtomList);\nMODULE_SCOPE void\tTkUndoPushAction(TkUndoRedoStack *stack,\n\t\t\t    TkUndoSubAtom *apply, TkUndoSubAtom *revert);\nMODULE_SCOPE int\tTkUndoRevert(TkUndoRedoStack *stack);\nMODULE_SCOPE int\tTkUndoApply(TkUndoRedoStack *stack);\n\n#endif /* _TKUNDO */\n"
  },
  {
    "path": "generic/tkUtil.c",
    "content": "/*\n * tkUtil.c --\n *\n *\tThis file contains miscellaneous utility functions that are used by\n *\tthe rest of Tk, such as a function for drawing a focus highlight.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * The structure below defines the implementation of the \"statekey\" Tcl\n * object, used for quickly finding a mapping in a TkStateMap.\n */\n\nconst Tcl_ObjType tkStateKeyObjType = {\n    \"statekey\",\t\t/* name */\n    NULL,\t\t\t/* freeIntRepProc */\n    NULL,\t\t\t/* dupIntRepProc */\n    NULL,\t\t\t/* updateStringProc */\n    NULL,\t\t\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkStateParseProc --\n *\n *\tThis function is invoked during option processing to handle the\n *\t\"-state\" and \"-default\" options.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe state for a given item gets replaced by the state indicated in the\n *\tvalue argument.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkStateParseProc(\n    void *clientData,\t/* some flags.*/\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    int c;\n    int flags = PTR2INT(clientData);\n    size_t length;\n    Tcl_Obj *msgObj;\n    Tk_State *statePtr = (Tk_State *) (widgRec + offset);\n\n    if (value == NULL || *value == 0) {\n\t*statePtr = TK_STATE_NULL;\n\treturn TCL_OK;\n    }\n\n    c = value[0];\n    length = strlen(value);\n\n    if ((c == 'n') && (strncmp(value, \"normal\", length) == 0)) {\n\t*statePtr = TK_STATE_NORMAL;\n\treturn TCL_OK;\n    }\n    if ((c == 'd') && (strncmp(value, \"disabled\", length) == 0)) {\n\t*statePtr = TK_STATE_DISABLED;\n\treturn TCL_OK;\n    }\n    if ((c == 'a') && (flags&1) && (strncmp(value, \"active\", length) == 0)) {\n\t*statePtr = TK_STATE_ACTIVE;\n\treturn TCL_OK;\n    }\n    if ((c == 'h') && (flags&2) && (strncmp(value, \"hidden\", length) == 0)) {\n\t*statePtr = TK_STATE_HIDDEN;\n\treturn TCL_OK;\n    }\n\n    msgObj = Tcl_ObjPrintf(\"bad %s value \\\"%s\\\": must be normal\",\n\t    ((flags & 4) ? \"-default\" : \"state\"), value);\n    if (flags & 1) {\n\tTcl_AppendToObj(msgObj, \", active\", TCL_INDEX_NONE);\n    }\n    if (flags & 2) {\n\tTcl_AppendToObj(msgObj, \", hidden\", TCL_INDEX_NONE);\n    }\n    if (flags & 3) {\n\tTcl_AppendToObj(msgObj, \",\", TCL_INDEX_NONE);\n    }\n    Tcl_AppendToObj(msgObj, \" or disabled\", TCL_INDEX_NONE);\n    Tcl_SetObjResult(interp, msgObj);\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"STATE\", (char *)NULL);\n    *statePtr = TK_STATE_NORMAL;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkStatePrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-state\" configuration option.\n *\n * Results:\n *\tThe return value is a string describing the state for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTkStatePrintProc(\n    TCL_UNUSED(void *),\t/* Ignored. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset into item. */\n    TCL_UNUSED(Tcl_FreeProc **))\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    Tk_State *statePtr = (Tk_State *) (widgRec + offset);\n\n    switch (*statePtr) {\n    case TK_STATE_NORMAL:\n\treturn \"normal\";\n    case TK_STATE_DISABLED:\n\treturn \"disabled\";\n    case TK_STATE_HIDDEN:\n\treturn \"hidden\";\n    case TK_STATE_ACTIVE:\n\treturn \"active\";\n    default:\n\treturn \"\";\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkOrientParseProc --\n *\n *\tThis function is invoked during option processing to handle the\n *\t\"-orient\" option.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tThe orientation for a given item gets replaced by the orientation\n *\tindicated in the value argument.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkOrientParseProc(\n    TCL_UNUSED(void *),\t/* some flags.*/\n    Tcl_Interp *interp,\t\t/* Used for reporting errors. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    const char *value,\t\t/* Value of option. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset)\t\t\t/* Offset into item. */\n{\n    int c;\n    size_t length;\n    int *orientPtr = (int *) (widgRec + offset);\n\n    if (value == NULL || *value == 0) {\n\t*orientPtr = 0;\n\treturn TCL_OK;\n    }\n\n    c = value[0];\n    length = strlen(value);\n\n    if ((c == 'h') && (strncmp(value, \"horizontal\", length) == 0)) {\n\t*orientPtr = 0;\n\treturn TCL_OK;\n    }\n    if ((c == 'v') && (strncmp(value, \"vertical\", length) == 0)) {\n\t*orientPtr = 1;\n\treturn TCL_OK;\n    }\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad orientation \\\"%s\\\": must be vertical or horizontal\",\n\t    value));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"ORIENTATION\", (char *)NULL);\n    *orientPtr = 0;\n    return TCL_ERROR;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkOrientPrintProc --\n *\n *\tThis function is invoked by the Tk configuration code to produce a\n *\tprintable string for the \"-orient\" configuration option.\n *\n * Results:\n *\tThe return value is a string describing the orientation for the item\n *\treferred to by \"widgRec\". In addition, *freeProcPtr is filled in with\n *\tthe address of a function to call to free the result string when it's\n *\tno longer needed (or NULL to indicate that the string doesn't need to\n *\tbe freed).\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTkOrientPrintProc(\n    TCL_UNUSED(void *),\t/* Ignored. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window containing canvas widget. */\n    char *widgRec,\t\t/* Pointer to record for item. */\n    Tcl_Size offset,\t\t\t/* Offset into item. */\n    TCL_UNUSED(Tcl_FreeProc **))\t/* Pointer to variable to fill in with\n\t\t\t\t * information about how to reclaim storage\n\t\t\t\t * for return string. */\n{\n    int *statePtr = (int *) (widgRec + offset);\n\n    if (*statePtr) {\n\treturn \"vertical\";\n    } else {\n\treturn \"horizontal\";\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkOffsetParseProc --\n *\n *\tConverts the offset of a stipple or tile into the Tk_TSOffset\n *\tstructure.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkOffsetParseProc(\n    void *clientData,\t/* not used */\n    Tcl_Interp *interp,\t\t/* Interpreter to send results back to */\n    Tk_Window tkwin,\t\t/* Window on same display as tile */\n    const char *value,\t\t/* Name of image */\n    char *widgRec,\t\t/* Widget structure record */\n    Tcl_Size offset)\t\t\t/* Offset of tile in record */\n{\n    Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);\n    Tk_TSOffset tsoffset;\n    const char *q, *p;\n    int result;\n    Tcl_Obj *msgObj;\n\n    if ((value == NULL) || (*value == 0)) {\n\ttsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;\n\tgoto goodTSOffset;\n    }\n    tsoffset.flags = 0;\n    p = value;\n\n    switch (value[0]) {\n    case '#':\n\tif (PTR2INT(clientData) & TK_OFFSET_RELATIVE) {\n\t    tsoffset.flags = TK_OFFSET_RELATIVE;\n\t    p++;\n\t    break;\n\t}\n\tgoto badTSOffset;\n    case 'e':\n\tswitch(value[1]) {\n\tcase '\\0':\n\t    tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE;\n\t    goto goodTSOffset;\n\tcase 'n':\n\t    if (value[2]!='d' || value[3]!='\\0') {\n\t\tgoto badTSOffset;\n\t    }\n\t    tsoffset.flags = INT_MAX;\n\t    goto goodTSOffset;\n\t}\n\tbreak;\n    case 'w':\n\tif (value[1] != '\\0') {goto badTSOffset;}\n\ttsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE;\n\tgoto goodTSOffset;\n    case 'n':\n\tif ((value[1] != '\\0') && (value[2] != '\\0')) {\n\t    goto badTSOffset;\n\t}\n\tswitch(value[1]) {\n\tcase '\\0':\n\t    tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP;\n\t    goto goodTSOffset;\n\tcase 'w':\n\t    tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP;\n\t    goto goodTSOffset;\n\tcase 'e':\n\t    tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP;\n\t    goto goodTSOffset;\n\t}\n\tgoto badTSOffset;\n    case 's':\n\tif ((value[1] != '\\0') && (value[2] != '\\0')) {\n\t    goto badTSOffset;\n\t}\n\tswitch(value[1]) {\n\tcase '\\0':\n\t    tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM;\n\t    goto goodTSOffset;\n\tcase 'w':\n\t    tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM;\n\t    goto goodTSOffset;\n\tcase 'e':\n\t    tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM;\n\t    goto goodTSOffset;\n\t}\n\tgoto badTSOffset;\n    case 'c':\n\tif (strncmp(value, \"center\", strlen(value)) != 0) {\n\t    goto badTSOffset;\n\t}\n\ttsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;\n\tgoto goodTSOffset;\n    }\n\n    /*\n     * Check for an extra offset.\n     */\n\n    q = strchr(p, ',');\n    if (q == NULL) {\n\tif (PTR2INT(clientData) & TK_OFFSET_INDEX) {\n\t    if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) {\n\t\tTcl_ResetResult(interp);\n\t\tgoto badTSOffset;\n\t    }\n\t    tsoffset.flags |= TK_OFFSET_INDEX;\n\t    goto goodTSOffset;\n\t}\n\tgoto badTSOffset;\n    }\n\n    *((char *) q) = 0;\n    result = Tk_GetPixels(interp, tkwin, (char *) p, &tsoffset.xoffset);\n    *((char *) q) = ',';\n    if (result != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (Tk_GetPixels(interp, tkwin, (char*)q+1, &tsoffset.yoffset) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Below is a hack to allow the stipple/tile offset to be stored in the\n     * internal tile structure. Most of the times, offsetPtr is a pointer to\n     * an already existing tile structure. However if this structure is not\n     * already created, we must do it with Tk_GetTile()!!!!\n     */\n\n  goodTSOffset:\n    memcpy(offsetPtr, &tsoffset, sizeof(Tk_TSOffset));\n    return TCL_OK;\n\n  badTSOffset:\n    msgObj = Tcl_ObjPrintf(\"bad offset \\\"%s\\\": expected \\\"x,y\\\"\", value);\n    if (PTR2INT(clientData) & TK_OFFSET_RELATIVE) {\n\tTcl_AppendToObj(msgObj, \", \\\"#x,y\\\"\", TCL_INDEX_NONE);\n    }\n    if (PTR2INT(clientData) & TK_OFFSET_INDEX) {\n\tTcl_AppendToObj(msgObj, \", <index>\", TCL_INDEX_NONE);\n    }\n    Tcl_AppendToObj(msgObj, \", n, ne, e, se, s, sw, w, nw, or center\", TCL_INDEX_NONE);\n    Tcl_SetObjResult(interp, msgObj);\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"OFFSET\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkOffsetPrintProc --\n *\n *\tReturns the offset of the tile.\n *\n * Results:\n *\tThe offset of the tile is returned.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkOffsetPrintProc(\n    TCL_UNUSED(void *),\t/* not used */\n    TCL_UNUSED(Tk_Window),\t\t/* not used */\n    char *widgRec,\t\t/* Widget structure record */\n    Tcl_Size offset,\t\t\t/* Offset of tile in record */\n    Tcl_FreeProc **freeProcPtr)\t/* not used */\n{\n    Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);\n    char *p, *q;\n\n    if (offsetPtr->flags & TK_OFFSET_INDEX) {\n\tif (offsetPtr->flags >= INT_MAX) {\n\t    return \"end\";\n\t}\n\tp = (char *)Tcl_Alloc(32);\n\tsnprintf(p, 32, \"%d\", offsetPtr->flags & ~TK_OFFSET_INDEX);\n\t*freeProcPtr = TCL_DYNAMIC;\n\treturn p;\n    }\n    if (offsetPtr->flags & TK_OFFSET_TOP) {\n\tif (offsetPtr->flags & TK_OFFSET_LEFT) {\n\t    return \"nw\";\n\t} else if (offsetPtr->flags & TK_OFFSET_CENTER) {\n\t    return \"n\";\n\t} else if (offsetPtr->flags & TK_OFFSET_RIGHT) {\n\t    return \"ne\";\n\t}\n    } else if (offsetPtr->flags & TK_OFFSET_MIDDLE) {\n\tif (offsetPtr->flags & TK_OFFSET_LEFT) {\n\t    return \"w\";\n\t} else if (offsetPtr->flags & TK_OFFSET_CENTER) {\n\t    return \"center\";\n\t} else if (offsetPtr->flags & TK_OFFSET_RIGHT) {\n\t    return \"e\";\n\t}\n    } else if (offsetPtr->flags & TK_OFFSET_BOTTOM) {\n\tif (offsetPtr->flags & TK_OFFSET_LEFT) {\n\t    return \"sw\";\n\t} else if (offsetPtr->flags & TK_OFFSET_CENTER) {\n\t    return \"s\";\n\t} else if (offsetPtr->flags & TK_OFFSET_RIGHT) {\n\t    return \"se\";\n\t}\n    }\n    q = p = (char *)Tcl_Alloc(32);\n    if (offsetPtr->flags & TK_OFFSET_RELATIVE) {\n\t*q++ = '#';\n    }\n    snprintf(q, 32, \"%d,%d\", offsetPtr->xoffset, offsetPtr->yoffset);\n    *freeProcPtr = TCL_DYNAMIC;\n    return p;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPixelParseProc --\n *\n *\tConverts the name of an image into a tile.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPixelParseProc(\n    void *clientData,\t/* If non-NULL, negative values are allowed as\n\t\t\t\t * well. */\n    Tcl_Interp *interp,\t\t/* Interpreter to send results back to */\n    Tk_Window tkwin,\t\t/* Window on same display as tile */\n    const char *value,\t\t/* Name of image */\n    char *widgRec,\t\t/* Widget structure record */\n    Tcl_Size offset)\t\t\t/* Offset of tile in record */\n{\n    double *doublePtr = (double *) (widgRec + offset);\n    int result;\n\n    result = TkGetDoublePixels(interp, tkwin, value, doublePtr);\n\n    if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"expected screen distance but got \\\"%.50s\\\"\", value));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"PIXELS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPixelPrintProc --\n *\n *\tReturns the name of the tile.\n *\n * Results:\n *\tThe name of the tile is returned.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkPixelPrintProc(\n    TCL_UNUSED(void *),\t/* not used */\n    TCL_UNUSED(Tk_Window),\t\t/* not used */\n    char *widgRec,\t\t/* Widget structure record */\n    Tcl_Size offset,\t\t\t/* Offset of tile in record */\n    Tcl_FreeProc **freeProcPtr)\t/* not used */\n{\n    double *doublePtr = (double *) (widgRec + offset);\n    char *p = (char *)Tcl_Alloc(24);\n\n    Tcl_PrintDouble(NULL, *doublePtr, p);\n    *freeProcPtr = TCL_DYNAMIC;\n    return p;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDrawInsetFocusHighlight --\n *\n *\tThis function draws a rectangular ring around the outside of a widget\n *\tto indicate that it has received the input focus. It takes an\n *\tadditional padding argument that specifies how much padding is present\n *\toutside the widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA rectangle \"width\" pixels wide is drawn in \"drawable\", corresponding\n *\tto the outer area of \"tkwin\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDrawInsetFocusHighlight(\n    Tk_Window tkwin,\t\t/* Window whose focus highlight ring is to be\n\t\t\t\t * drawn. */\n    GC gc,\t\t\t/* Graphics context to use for drawing the\n\t\t\t\t * highlight ring. */\n    int width,\t\t\t/* Width of the highlight ring, in pixels. */\n    Drawable drawable,\t\t/* Where to draw the ring (typically a pixmap\n\t\t\t\t * for double buffering). */\n    int padding)\t\t/* Width of padding outside of widget. */\n{\n    XRectangle rects[4];\n\n    rects[0].x = padding;\n    rects[0].y = padding;\n    rects[0].width = Tk_Width(tkwin) - (2 * padding);\n    rects[0].height = width;\n    rects[1].x = padding;\n    rects[1].y = Tk_Height(tkwin) - width - padding;\n    rects[1].width = Tk_Width(tkwin) - (2 * padding);\n    rects[1].height = width;\n    rects[2].x = padding;\n    rects[2].y = width + padding;\n    rects[2].width = width;\n    rects[2].height = Tk_Height(tkwin) - 2*width - 2*padding;\n    rects[3].x = Tk_Width(tkwin) - width - padding;\n    rects[3].y = rects[2].y;\n    rects[3].width = width;\n    rects[3].height = rects[2].height;\n    XFillRectangles(Tk_Display(tkwin), drawable, gc, rects, 4);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DrawFocusHighlight --\n *\n *\tThis function draws a rectangular ring around the outside of a widget\n *\tto indicate that it has received the input focus.\n *\n *\tThis function is now deprecated. Use Tk_DrawHighlightBorder instead,\n *\tsince this function does not handle drawing the Focus ring properly on\n *\tthe Macintosh - you need to know the background GC as well as the\n *\tforeground since the Mac focus ring separated from the widget by a 1\n *\tpixel border.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA rectangle \"width\" pixels wide is drawn in \"drawable\", corresponding\n *\tto the outer area of \"tkwin\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DrawFocusHighlight(\n    Tk_Window tkwin,\t\t/* Window whose focus highlight ring is to be\n\t\t\t\t * drawn. */\n    GC gc,\t\t\t/* Graphics context to use for drawing the\n\t\t\t\t * highlight ring. */\n    int width,\t\t\t/* Width of the highlight ring, in pixels. */\n    Drawable drawable)\t\t/* Where to draw the ring (typically a pixmap\n\t\t\t\t * for double buffering). */\n{\n    TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDrawDottedRect --\n *\n *\tThis function draws a dotted rectangle, used as focus ring of Ttk\n *\twidgets and for rendering the active element of a listbox.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA dotted rectangle is drawn in the specified Drawable.  On the\n *\twindowing systems x11 and aqua the GC components line_style,\n *\tline_width, dashes, and dash_offset are modified as needed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDrawDottedRect(\n    Display *disp,\t\t/* Display containing the dotted rectangle. */\n    Drawable d,\t\t\t/* Where to draw the rectangle (typically a\n\t\t\t\t * pixmap for double buffering). */\n    GC gc,\t\t\t/* Graphics context to use for drawing the\n\t\t\t\t * rectangle. */\n    int x, int y,\t\t/* Coordinates of the top-left corner. */\n    int width, int height)\t/* Width & height, _including the border_. */\n{\n#ifdef _WIN32\n    TkWinDrawDottedRect(disp, d, gc->foreground, x, y, width, height);\n\n#else\n    XGCValues gcValues;\n    int widthMod2 = width % 2, heightMod2 = height % 2;\n    int x2 = x + width - 1, y2 = y + height - 1;\n\n    gcValues.line_style = LineOnOffDash;\n    gcValues.line_width = 1;\n    gcValues.dashes = 1;\n#ifdef MAC_OSX_TK\n    gcValues.dash_offset = 1;\n#else\n    gcValues.dash_offset = 0;\n#endif\n    XChangeGC(disp, gc, GCLineStyle | GCLineWidth | GCDashList | GCDashOffset,\n\t    &gcValues);\n\n    if (widthMod2 == 0 && heightMod2 == 0) {\n\tXDrawLine(disp, d, gc, x+1, y,  x2-1, y);\t/* N */\n\tXDrawLine(disp, d, gc, x+2, y2, x2,   y2);\t/* S */\n\tXDrawLine(disp, d, gc, x,  y+2, x,  y2);\t/* W */\n\tXDrawLine(disp, d, gc, x2, y+1, x2, y2-1);\t/* E */\n    } else {\n\tint dx = 1 - widthMod2, dy = 1 - heightMod2;\n\n\tXDrawLine(disp, d, gc, x+1, y,  x2-dx, y);\t/* N */\n\tXDrawLine(disp, d, gc, x+1, y2, x2-dx, y2);\t/* S */\n\tXDrawLine(disp, d, gc, x,  y+1, x,  y2-dy);\t/* W */\n\tXDrawLine(disp, d, gc, x2, y+1, x2, y2-dy);\t/* E */\n    }\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetScrollInfo --\n *\n *\tThis function is invoked to parse \"xview\" and \"yview\" scrolling\n *\tcommands for widgets using the new scrolling command syntax (\"moveto\"\n *\tor \"scroll\" options).\n *\n * Results:\n *\tThe return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,\n *\tTK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the\n *\tcommand was successfully parsed and what form the command took. If\n *\tTK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if\n *\tTK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the\n *\tnumber of lines to move (may be negative); if TK_SCROLL_ERROR, the\n *\tinterp's result contains an error message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetScrollInfo(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tcl_Size argc,\t\t\t/* # arguments for command. */\n    const char **argv,\t\t/* Arguments for command. */\n    double *dblPtr,\t\t/* Filled in with argument \"moveto\" option, if\n\t\t\t\t * any. */\n    int *intPtr)\t\t/* Filled in with number of pages or lines to\n\t\t\t\t * scroll, if any. */\n{\n    int c = argv[2][0];\n    size_t length = strlen(argv[2]);\n\n    if ((c == 'm') && (strncmp(argv[2], \"moveto\", length) == 0)) {\n\tif (argc != 4) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"wrong # args: should be \\\"%s %s %s\\\"\",\n\t\t    argv[0], argv[1], \"moveto fraction\"));\n\t    Tcl_SetErrorCode(interp, \"TCL\", \"WRONGARGS\", (char *)NULL);\n\t    return TK_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {\n\t    return TK_SCROLL_ERROR;\n\t}\n\treturn TK_SCROLL_MOVETO;\n    } else if ((c == 's')\n\t    && (strncmp(argv[2], \"scroll\", length) == 0)) {\n\tdouble d;\n\tif (argc != 5) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"wrong # args: should be \\\"%s %s %s\\\"\",\n\t\t    argv[0], argv[1], \"scroll number pages|units\"));\n\t    Tcl_SetErrorCode(interp, \"TCL\", \"WRONGARGS\", (char *)NULL);\n\t    return TK_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) {\n\t    return TK_SCROLL_ERROR;\n\t}\n\t*intPtr = (d > 0) ? ceil(d) : floor(d);\n\tlength = strlen(argv[4]);\n\tc = argv[4][0];\n\tif ((c == 'p') && (strncmp(argv[4], \"pages\", length) == 0)) {\n\t    return TK_SCROLL_PAGES;\n\t} else if ((c == 'u') && (strncmp(argv[4], \"units\", length) == 0)) {\n\t    return TK_SCROLL_UNITS;\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad argument \\\"%s\\\": must be pages or units\", argv[4]));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SCROLL_UNITS\", (char *)NULL);\n\treturn TK_SCROLL_ERROR;\n    }\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"unknown option \\\"%s\\\": must be moveto or scroll\", argv[2]));\n    Tcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"option\", argv[2],\n\t    (char *)NULL);\n    return TK_SCROLL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetScrollInfoObj --\n *\n *\tThis function is invoked to parse \"xview\" and \"yview\" scrolling\n *\tcommands for widgets using the new scrolling command syntax (\"moveto\"\n *\tor \"scroll\" options).\n *\n * Results:\n *\tThe return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,\n *\tTK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the\n *\tcommand was successfully parsed and what form the command took. If\n *\tTK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if\n *\tTK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the\n *\tnumber of lines to move (may be negative); if TK_SCROLL_ERROR, the\n *\tinterp's result contains an error message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetScrollInfoObj(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    Tcl_Size objc,\t\t\t/* # arguments for command. */\n    Tcl_Obj *const objv[],\t/* Arguments for command. */\n    double *dblPtr,\t\t/* Filled in with argument \"moveto\" option, if\n\t\t\t\t * any. */\n    int *intPtr)\t\t/* Filled in with number of pages or lines to\n\t\t\t\t * scroll, if any. */\n{\n    Tcl_Size length;\n    const char *arg;\n\n    if (objc + 1 < 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"moveto|scroll args\");\n\treturn TK_SCROLL_ERROR;\n    }\n    arg = Tcl_GetStringFromObj(objv[2], &length);\n#define ArgPfxEq(str) \\\n\t((arg[0] == str[0]) && !strncmp(arg, str, length))\n\n    if (ArgPfxEq(\"moveto\")) {\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"moveto fraction\");\n\t    return TK_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {\n\t    return TK_SCROLL_ERROR;\n\t}\n\treturn TK_SCROLL_MOVETO;\n    } else if (ArgPfxEq(\"scroll\")) {\n\tdouble d;\n\tif (objc != 5) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"scroll number pages|units\");\n\t    return TK_SCROLL_ERROR;\n\t}\n\tif (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {\n\t    return TK_SCROLL_ERROR;\n\t}\n\t*intPtr = (d >= 0) ? ceil(d) : floor(d);\n\tif (dblPtr) {\n\t    *dblPtr = d;\n\t}\n\n\targ = Tcl_GetStringFromObj(objv[4], &length);\n\tif (ArgPfxEq(\"pages\")) {\n\t    return TK_SCROLL_PAGES;\n\t} else if (ArgPfxEq(\"units\")) {\n\t    return TK_SCROLL_UNITS;\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad argument \\\"%s\\\": must be pages or units\", arg));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"SCROLL_UNITS\", (char *)NULL);\n\treturn TK_SCROLL_ERROR;\n    }\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"unknown option \\\"%s\\\": must be moveto or scroll\", arg));\n    Tcl_SetErrorCode(interp, \"TCL\", \"LOOKUP\", \"INDEX\", \"option\", arg, (char *)NULL);\n    return TK_SCROLL_ERROR;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkComputeAnchor --\n *\n *\tDetermine where to place a rectangle so that it will be properly\n *\tanchored with respect to the given window. Used by widgets to align a\n *\tbox of text inside a window. When anchoring with respect to one of the\n *\tsides, the rectangle be placed inside of the internal border of the\n *\twindow.\n *\n * Results:\n *\t*xPtr and *yPtr set to the upper-left corner of the rectangle anchored\n *\tin the window.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkComputeAnchor(\n    Tk_Anchor anchor,\t\t/* Desired anchor. */\n    Tk_Window tkwin,\t\t/* Anchored with respect to this window. */\n    int padX, int padY,\t\t/* Use this extra padding inside window, in\n\t\t\t\t * addition to the internal border. */\n    int innerWidth, int innerHeight,\n\t\t\t\t/* Size of rectangle to anchor in window. */\n    int *xPtr, int *yPtr)\t/* Returns upper-left corner of anchored\n\t\t\t\t * rectangle. */\n{\n    /*\n     * Handle the horizontal parts.\n     */\n\n    switch (anchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_W:\n    case TK_ANCHOR_SW:\n\t*xPtr = Tk_InternalBorderLeft(tkwin) + padX;\n\tbreak;\n\n    case TK_ANCHOR_NE:\n    case TK_ANCHOR_E:\n    case TK_ANCHOR_SE:\n\t*xPtr = Tk_Width(tkwin) - Tk_InternalBorderRight(tkwin) - padX\n\t\t- innerWidth;\n\tbreak;\n\n    default:\n\t*xPtr = (Tk_Width(tkwin) - innerWidth - Tk_InternalBorderLeft(tkwin) -\n\t\tTk_InternalBorderRight(tkwin)) / 2 +\n\t\tTk_InternalBorderLeft(tkwin);\n\tbreak;\n    }\n\n    /*\n     * Handle the vertical parts.\n     */\n\n    switch (anchor) {\n    case TK_ANCHOR_NW:\n    case TK_ANCHOR_N:\n    case TK_ANCHOR_NE:\n\t*yPtr = Tk_InternalBorderTop(tkwin) + padY;\n\tbreak;\n\n    case TK_ANCHOR_SW:\n    case TK_ANCHOR_S:\n    case TK_ANCHOR_SE:\n\t*yPtr = Tk_Height(tkwin) - Tk_InternalBorderBottom(tkwin) - padY\n\t\t- innerHeight;\n\tbreak;\n\n    default:\n\t*yPtr = (Tk_Height(tkwin) - innerHeight- Tk_InternalBorderTop(tkwin) -\n\t\tTk_InternalBorderBottom(tkwin)) / 2 +\n\t\tTk_InternalBorderTop(tkwin);\n\tbreak;\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFindStateString --\n *\n *\tGiven a lookup table, map a number to a string in the table.\n *\n * Results:\n *\tIf numKey was equal to the numeric key of one of the elements in the\n *\ttable, returns the string key of that element. Returns NULL if numKey\n *\twas not equal to any of the numeric keys in the table.\n *\n * Side effects.\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nconst char *\nTkFindStateString(\n    const TkStateMap *mapPtr,\t/* The state table. */\n    int numKey)\t\t\t/* The key to try to find in the table. */\n{\n    for (; mapPtr->strKey!=NULL ; mapPtr++) {\n\tif (numKey == mapPtr->numKey) {\n\t    return mapPtr->strKey;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkFindStateNum, TkFindStateNumObj --\n *\n *\tGiven a lookup table, map a string to a number in the table.\n *\n * Results:\n *\tIf strKey was equal to the string keys of one of the elements in the\n *\ttable, returns the numeric key of that element. Returns the numKey\n *\tassociated with the last element (the NULL string one) in the table if\n *\tstrKey was not equal to any of the string keys in the table. In that\n *\tcase, an error message is also left in the interp's result (if interp\n *\tis not NULL).\n *\n * Side effects.\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTkFindStateNum(\n    Tcl_Interp *interp,\t\t/* Interp for error reporting. */\n    const char *option,\t\t/* String to use when constructing error. */\n    const TkStateMap *mapPtr,\t/* Lookup table. */\n    const char *strKey)\t\t/* String to try to find in lookup table. */\n{\n    const TkStateMap *mPtr;\n\n    /*\n     * See if the value is in the state map.\n     */\n\n    for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {\n\tif (strcmp(strKey, mPtr->strKey) == 0) {\n\t    return mPtr->numKey;\n\t}\n    }\n\n    /*\n     * Not there. Generate an error message (if we can) and return the\n     * default.\n     */\n\n    if (interp != NULL) {\n\tTcl_Obj *msgObj;\n\n\tmPtr = mapPtr;\n\tmsgObj = Tcl_ObjPrintf(\"bad %s value \\\"%s\\\": must be %s\",\n\t\toption, strKey, mPtr->strKey);\n\tfor (mPtr++; mPtr->strKey != NULL; mPtr++) {\n\t    Tcl_AppendPrintfToObj(msgObj, \",%s %s\",\n\t\t    ((mPtr[1].strKey != NULL) ? \"\" : \"or \"), mPtr->strKey);\n\t}\n\tTcl_SetObjResult(interp, msgObj);\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", option, strKey, (char *)NULL);\n    }\n    return mPtr->numKey;\n}\n\nint\nTkFindStateNumObj(\n    Tcl_Interp *interp,\t\t/* Interp for error reporting. */\n    Tcl_Obj *optionPtr,\t\t/* String to use when constructing error. */\n    const TkStateMap *mapPtr,\t/* Lookup table. */\n    Tcl_Obj *keyPtr)\t\t/* String key to find in lookup table. */\n{\n    const TkStateMap *mPtr;\n    const char *key;\n    const Tcl_ObjType *typePtr;\n\n    /*\n     * See if the value is in the object cache.\n     */\n\n    if ((keyPtr->typePtr == &tkStateKeyObjType)\n\t    && (keyPtr->internalRep.twoPtrValue.ptr1 == mapPtr)) {\n\treturn PTR2INT(keyPtr->internalRep.twoPtrValue.ptr2);\n    }\n\n    /*\n     * Not there. Look in the state map.\n     */\n\n    key = Tcl_GetString(keyPtr);\n    for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {\n\tif (strcmp(key, mPtr->strKey) == 0) {\n\t    typePtr = keyPtr->typePtr;\n\t    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {\n\t\ttypePtr->freeIntRepProc(keyPtr);\n\t    }\n\t    keyPtr->internalRep.twoPtrValue.ptr1 = (void *) mapPtr;\n\t    keyPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(mPtr->numKey);\n\t    keyPtr->typePtr = &tkStateKeyObjType;\n\t    return mPtr->numKey;\n\t}\n    }\n\n    /*\n     * Not there either. Generate an error message (if we can) and return the\n     * default.\n     */\n\n    if (interp != NULL) {\n\tTcl_Obj *msgObj;\n\n\tmPtr = mapPtr;\n\tmsgObj = Tcl_ObjPrintf(\n\t\t\"bad %s value \\\"%s\\\": must be %s\",\n\t\tTcl_GetString(optionPtr), key, mPtr->strKey);\n\tfor (mPtr++; mPtr->strKey != NULL; mPtr++) {\n\t    Tcl_AppendPrintfToObj(msgObj, \",%s %s\",\n\t\t    ((mPtr[1].strKey != NULL) ? \"\" : \" or\"), mPtr->strKey);\n\t}\n\tTcl_SetObjResult(interp, msgObj);\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", Tcl_GetString(optionPtr),\n\t\tkey, (char *)NULL);\n    }\n    return mPtr->numKey;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkBackgroundEvalObjv --\n *\n *\tEvaluate a command while ensuring that we do not affect the\n *\tinterpreters state. This is important when evaluating script\n *\tduring background tasks.\n *\n * Results:\n *\tA standard Tcl result code.\n *\n * Side Effects:\n *\tThe interpreters variables and code may be modified by the script\n *\tbut the result will not be modified.\n *\n * ----------------------------------------------------------------------\n */\n\nint\nTkBackgroundEvalObjv(\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    int flags)\n{\n    Tcl_InterpState state;\n    int r = TCL_OK;\n    Tcl_Size n;\n\n    /*\n     * Record the state of the interpreter.\n     */\n\n    Tcl_Preserve(interp);\n    state = Tcl_SaveInterpState(interp, TCL_OK);\n\n    /*\n     * Evaluate the command and handle any error.\n     */\n\n    for (n = 0; n < objc; ++n) {\n\tTcl_IncrRefCount(objv[n]);\n    }\n    r = Tcl_EvalObjv(interp, objc, objv, flags);\n    for (n = 0; n < objc; ++n) {\n\tTcl_DecrRefCount(objv[n]);\n    }\n    if (r == TCL_ERROR) {\n\tTcl_AddErrorInfo(interp, \"\\n    (background event handler)\");\n\tTcl_BackgroundException(interp, r);\n    }\n\n    /*\n     * Restore the state of the interpreter.\n     */\n\n    (void) Tcl_RestoreInterpState(interp, state);\n    Tcl_Release(interp);\n\n    return r;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMakeEnsemble --\n *\n *\tCreate an ensemble from a table of implementation commands. This may\n *\tbe called recursively to create sub-ensembles.\n *\n * Results:\n *\tHandle for the ensemble, or NULL if creation of it fails.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Command\nTkMakeEnsemble(\n    Tcl_Interp *interp,\n    const char *namesp,\n    const char *name,\n    void *clientData,\n    const TkEnsemble map[])\n{\n    Tcl_Namespace *namespacePtr = NULL;\n    Tcl_Command ensemble = NULL;\n    Tcl_Obj *dictObj = NULL, *nameObj;\n    Tcl_DString ds;\n    int i;\n\n    if (map == NULL) {\n\treturn NULL;\n    }\n\n    Tcl_DStringInit(&ds);\n\n    namespacePtr = Tcl_FindNamespace(interp, namesp, NULL, 0);\n    if (namespacePtr == NULL) {\n\tnamespacePtr = Tcl_CreateNamespace(interp, namesp, NULL, NULL);\n\tif (namespacePtr == NULL) {\n\t    Tcl_Panic(\"failed to create namespace \\\"%s\\\"\", namesp);\n\t}\n    }\n\n    nameObj = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n    ensemble = Tcl_FindEnsemble(interp, nameObj, 0);\n    Tcl_DecrRefCount(nameObj);\n    if (ensemble == NULL) {\n\tensemble = Tcl_CreateEnsemble(interp, name, namespacePtr,\n\t\tTCL_ENSEMBLE_PREFIX);\n\tif (ensemble == NULL) {\n\t    Tcl_Panic(\"failed to create ensemble \\\"%s\\\"\", name);\n\t}\n    }\n\n    Tcl_DStringSetLength(&ds, 0);\n    Tcl_DStringAppend(&ds, namesp, TCL_INDEX_NONE);\n    if (!(strlen(namesp) == 2 && namesp[1] == ':')) {\n\tTcl_DStringAppend(&ds, \"::\", TCL_INDEX_NONE);\n    }\n    Tcl_DStringAppend(&ds, name, TCL_INDEX_NONE);\n\n    dictObj = Tcl_NewObj();\n    for (i = 0; map[i].name != NULL ; ++i) {\n\tTcl_Obj *fqdnObj;\n\n\tnameObj = Tcl_NewStringObj(map[i].name, TCL_INDEX_NONE);\n\tfqdnObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),\n\t\tTcl_DStringLength(&ds));\n\tTcl_AppendStringsToObj(fqdnObj, \"::\", map[i].name, (char *)NULL);\n\tTcl_DictObjPut(NULL, dictObj, nameObj, fqdnObj);\n\tif (map[i].proc) {\n\t    Tcl_CreateObjCommand2(interp, Tcl_GetString(fqdnObj),\n\t\t    map[i].proc, clientData, NULL);\n\t} else if (map[i].subensemble) {\n\t    TkMakeEnsemble(interp, Tcl_DStringValue(&ds),\n\t\t    map[i].name, clientData, map[i].subensemble);\n\t}\n    }\n\n    if (ensemble) {\n\tTcl_SetEnsembleMappingDict(interp, ensemble, dictObj);\n    }\n\n    Tcl_DStringFree(&ds);\n    return ensemble;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScalingLevel --\n *\n *\tReturns the display's DPI scaling level as 1.0, 1.25, 1.5, ....\n *\n * Results:\n *      The scaling level.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\n\ndouble\nTkScalingLevel(\n    Tk_Window tkwin)\n{\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    Tcl_Obj *scalingPctPtr = Tcl_GetVar2Ex(interp, \"::tk::scalingPct\", NULL,\n\t    TCL_GLOBAL_ONLY);\n    if (scalingPctPtr == NULL) {\n\treturn 1.0;\n    } else {\n\tint scalingPct;\n\tTcl_GetIntFromObj(interp, scalingPctPtr, &scalingPct);\n\treturn scalingPct / 100.0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SendVirtualEvent --\n *\n *\tSend a virtual event notification to the specified target window.\n *\tEquivalent to:\n *\t    \"event generate $target <<$eventName>> -data $detail\"\n *\n *\tNote that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this\n *\troutine does not reenter the interpreter.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SendVirtualEvent(\n    Tk_Window target,\n    const char *eventName,\n    Tcl_Obj *detail)\n{\n    union {XEvent general; XVirtualEvent virt;} event;\n\n    memset(&event, 0, sizeof(event));\n    event.general.xany.type = VirtualEvent;\n    event.general.xany.serial = NextRequest(Tk_Display(target));\n    event.general.xany.send_event = False;\n    event.general.xany.window = Tk_WindowId(target);\n    event.general.xany.display = Tk_Display(target);\n    event.virt.name = Tk_GetUid(eventName);\n    event.virt.user_data = detail;\n    if (detail) Tcl_IncrRefCount(detail); // Event code will DecrRefCount\n\n    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkVisual.c",
    "content": "/*\n * tkVisual.c --\n *\n *\tThis file contains library procedures for allocating and freeing\n *\tvisuals and colormaps. This code is based on a prototype\n *\timplementation by Paul Mackerras.\n *\n * Copyright © 1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * The table below maps from symbolic names for visual classes to the\n * associated X class symbols.\n */\n\ntypedef struct VisualDictionary {\n    char name[12];\t\t/* Textual name of class. */\n    unsigned short minLength;\t\t/* Minimum # characters that must be specified\n\t\t\t\t * for an unambiguous match. */\n    short c_class;\t\t\t/* X symbol for class. */\n} VisualDictionary;\nstatic const VisualDictionary visualNames[] = {\n    {\"best\",\t\t1,\t0},\n    {\"directcolor\",\t2,\tDirectColor},\n    {\"grayscale\",\t1,\tGrayScale},\n    {\"greyscale\",\t1,\tGrayScale},\n    {\"pseudocolor\",\t1,\tPseudoColor},\n    {\"staticcolor\",\t7,\tStaticColor},\n    {\"staticgray\",\t7,\tStaticGray},\n    {\"staticgrey\",\t7,\tStaticGray},\n    {\"truecolor\",\t1,\tTrueColor},\n    {\"\",\t\t0,\t0},\n};\n\n/*\n * One of the following structures exists for each distinct non-default\n * colormap allocated for a display by Tk_GetColormap.\n */\n\nstruct TkColormap {\n    Colormap colormap;\t\t/* X's identifier for the colormap. */\n    Visual *visual;\t\t/* Visual for which colormap was allocated. */\n    size_t refCount;\t\t/* How many uses of the colormap are still\n\t\t\t\t * outstanding (calls to Tk_GetColormap minus\n\t\t\t\t * calls to Tk_FreeColormap). */\n    int shareable;\t\t/* 0 means this colormap was allocated by a\n\t\t\t\t * call to Tk_GetColormap with \"new\", implying\n\t\t\t\t * that the window wants it all for itself.  1\n\t\t\t\t * means that the colormap was allocated as a\n\t\t\t\t * default for a particular visual, so it can\n\t\t\t\t * be shared. */\n    struct TkColormap *nextPtr;\t/* Next in list of colormaps for this display,\n\t\t\t\t * or NULL for end of list. */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetVisual --\n *\n *\tGiven a string identifying a particular kind of visual, this procedure\n *\treturns a visual and depth that matches the specification.\n *\n * Results:\n *\tThe return value is normally a pointer to a visual. If an error\n *\toccurred in looking up the visual, NULL is returned and an error\n *\tmessage is left in the interp's result. The depth of the visual is\n *\treturned to *depthPtr under normal returns. If colormapPtr is\n *\tnon-NULL, then this procedure also finds a suitable colormap for use\n *\twith the visual in tkwin, and it returns that colormap in *colormapPtr\n *\tunless an error occurs.\n *\n * Side effects:\n *\tA new colormap may be allocated.\n *\n *----------------------------------------------------------------------\n */\n\nVisual *\nTk_GetVisual(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which visual will be used. */\n    const char *string,\t\t/* String describing visual. See manual entry\n\t\t\t\t * for details. */\n    int *depthPtr,\t\t/* The depth of the returned visual is stored\n\t\t\t\t * here. */\n    Colormap *colormapPtr)\t/* If non-NULL, then a suitable colormap for\n\t\t\t\t * visual is placed here. This colormap must\n\t\t\t\t * eventually be freed by calling\n\t\t\t\t * Tk_FreeColormap. */\n{\n    Tk_Window tkwin2;\n    XVisualInfo templ, *visInfoList, *bestPtr;\n    long mask;\n    Visual *visual;\n    size_t length;\n    int c, numVisuals, prio, bestPrio, i;\n    const char *p;\n    const VisualDictionary *dictPtr;\n    TkColormap *cmapPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    /*\n     * Parse string and set up a template for use in searching for an\n     * appropriate visual.\n     */\n\n    c = string[0];\n    if (c == '.') {\n\t/*\n\t * The string must be a window name. If the window is on the same\n\t * screen as tkwin, then just use its visual. Otherwise use the\n\t * information about the visual as a template for the search.\n\t */\n\n\ttkwin2 = Tk_NameToWindow(interp, string, tkwin);\n\tif (tkwin2 == NULL) {\n\t    return NULL;\n\t}\n\tvisual = Tk_Visual(tkwin2);\n\tif (Tk_Screen(tkwin) == Tk_Screen(tkwin2)) {\n\t    *depthPtr = Tk_Depth(tkwin2);\n\t    if (colormapPtr != NULL) {\n\t\t/*\n\t\t * Use the colormap from the other window too (but be sure to\n\t\t * increment its reference count if it's one of the ones\n\t\t * allocated here).\n\t\t */\n\n\t\t*colormapPtr = Tk_Colormap(tkwin2);\n\t\tfor (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;\n\t\t\tcmapPtr = cmapPtr->nextPtr) {\n\t\t    if (cmapPtr->colormap == *colormapPtr) {\n\t\t\tcmapPtr->refCount++;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t    return visual;\n\t}\n\ttempl.depth = Tk_Depth(tkwin2);\n\ttempl.c_class = visual->c_class;\n\ttempl.red_mask = visual->red_mask;\n\ttempl.green_mask = visual->green_mask;\n\ttempl.blue_mask = visual->blue_mask;\n\ttempl.colormap_size = visual->map_entries;\n\ttempl.bits_per_rgb = visual->bits_per_rgb;\n\tmask = VisualDepthMask|VisualClassMask|VisualRedMaskMask\n\t\t|VisualGreenMaskMask|VisualBlueMaskMask|VisualColormapSizeMask\n\t\t|VisualBitsPerRGBMask;\n    } else if ((c == 0) || ((c == 'd') && (string[1] != 0)\n\t    && (strncmp(string, \"default\", strlen(string)) == 0))) {\n\t/*\n\t * Use the default visual for the window's screen.\n\t */\n\n\tif (colormapPtr != NULL) {\n\t    *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));\n\t}\n\t*depthPtr = DefaultDepthOfScreen(Tk_Screen(tkwin));\n\treturn DefaultVisualOfScreen(Tk_Screen(tkwin));\n    } else if (isdigit(UCHAR(c))) {\n\tint visualId;\n\n\t/*\n\t * This is a visual ID.\n\t */\n\n\tif (Tcl_GetInt(interp, string, &visualId) == TCL_ERROR) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad X identifier for visual: \\\"%s\\\"\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"VISUALID\", (char *)NULL);\n\t    return NULL;\n\t}\n\ttempl.visualid = visualId;\n\tmask = VisualIDMask;\n    } else {\n\t/*\n\t * Parse the string into a class name (or \"best\") optionally followed\n\t * by whitespace and a depth.\n\t */\n\n\tfor (p = string; *p != 0; p++) {\n\t    if (isspace(UCHAR(*p)) || isdigit(UCHAR(*p))) {\n\t\tbreak;\n\t    }\n\t}\n\tlength = p - string;\n\ttempl.c_class = -1;\n\tfor (dictPtr = visualNames; dictPtr->minLength; dictPtr++) {\n\t    if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength)\n\t\t    && (strncmp(string, dictPtr->name, length) == 0)) {\n\t\ttempl.c_class = dictPtr->c_class;\n\t\tbreak;\n\t    }\n\t}\n\tif (templ.c_class == -1) {\n\t    Tcl_Obj *msgObj = Tcl_ObjPrintf(\n\t\t    \"unknown or ambiguous visual name \\\"%s\\\": class must be \",\n\t\t    string);\n\n\t    for (dictPtr = visualNames; dictPtr->minLength; dictPtr++) {\n\t\tTcl_AppendPrintfToObj(msgObj, \"%s, \", dictPtr->name);\n\t    }\n\t    Tcl_AppendToObj(msgObj, \"or default\", TCL_INDEX_NONE);\n\t    Tcl_SetObjResult(interp, msgObj);\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"VISUAL\", string, (char *)NULL);\n\t    return NULL;\n\t}\n\twhile (isspace(UCHAR(*p))) {\n\t    p++;\n\t}\n\tif (*p == 0) {\n\t    templ.depth = 10000;\n\t} else if (Tcl_GetInt(interp, p, &templ.depth) != TCL_OK) {\n\t    return NULL;\n\t}\n\tif (c == 'b') {\n\t    mask = 0;\n\t} else {\n\t    mask = VisualClassMask;\n\t}\n    }\n\n    /*\n     * Find all visuals that match the template we've just created, and return\n     * an error if there are none that match.\n     */\n\n    templ.screen = Tk_ScreenNumber(tkwin);\n    mask |= VisualScreenMask;\n    visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &templ,\n\t    &numVisuals);\n    if (visInfoList == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"couldn't find an appropriate visual\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"VISUAL\", \"INAPPROPRIATE\", (char *)NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Search through the visuals that were returned to find the best one.\n     * The choice is based on the following criteria, in decreasing order of\n     * importance:\n     *\n     * 1. Depth: choose a visual with exactly the desired depth, else one with\n     *\t  more bits than requested but as few bits as possible, else one with\n     *\t  fewer bits but as many as possible.\n     * 2. Class: some visual classes are more desirable than others; pick the\n     *    visual with the most desirable class.\n     * 3. Default: the default visual for the screen gets preference over\n     *    other visuals, all else being equal.\n     */\n\n    bestPrio = 0;\n    bestPtr = NULL;\n    for (i = 0; i < numVisuals; i++) {\n\tswitch (visInfoList[i].c_class) {\n\tcase DirectColor:\n\t    prio = 5; break;\n\tcase GrayScale:\n\t    prio = 1; break;\n\tcase PseudoColor:\n\t    prio = 7; break;\n\tcase StaticColor:\n\t    prio = 3; break;\n\tcase StaticGray:\n\t    prio = 1; break;\n\tcase TrueColor:\n\t    prio = 5; break;\n\tdefault:\n\t    prio = 0; break;\n\t}\n\tif (visInfoList[i].visual\n\t\t== DefaultVisualOfScreen(Tk_Screen(tkwin))) {\n\t    prio++;\n\t}\n\tif (bestPtr == NULL) {\n\t    goto newBest;\n\t}\n\tif (visInfoList[i].depth < bestPtr->depth) {\n\t    if (visInfoList[i].depth >= templ.depth) {\n\t\tgoto newBest;\n\t    }\n\t} else if (visInfoList[i].depth > bestPtr->depth) {\n\t    if (bestPtr->depth < templ.depth) {\n\t\tgoto newBest;\n\t    }\n\t} else {\n\t    if (prio > bestPrio) {\n\t\tgoto newBest;\n\t    }\n\t}\n\tcontinue;\n\n    newBest:\n\tbestPtr = &visInfoList[i];\n\tbestPrio = prio;\n    }\n    CLANG_ASSERT(bestPtr);\n    *depthPtr = bestPtr->depth;\n    visual = bestPtr->visual;\n    XFree(visInfoList);\n\n    /*\n     * If we need to find a colormap for this visual, do it now. If the visual\n     * is the default visual for the screen, then use the default colormap.\n     * Otherwise search for an existing colormap that's shareable. If all else\n     * fails, create a new colormap.\n     */\n\n    if (colormapPtr != NULL) {\n\tif (visual == DefaultVisualOfScreen(Tk_Screen(tkwin))) {\n\t    *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));\n\t} else {\n\t    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;\n\t\t    cmapPtr = cmapPtr->nextPtr) {\n\t\tif (cmapPtr->shareable && (cmapPtr->visual == visual)) {\n\t\t    *colormapPtr = cmapPtr->colormap;\n\t\t    cmapPtr->refCount++;\n\t\t    goto done;\n\t\t}\n\t    }\n\t    cmapPtr = (TkColormap *)Tcl_Alloc(sizeof(TkColormap));\n\t    cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),\n\t\t    RootWindowOfScreen(Tk_Screen(tkwin)), visual,\n\t\t    AllocNone);\n\t    cmapPtr->visual = visual;\n\t    cmapPtr->refCount = 1;\n\t    cmapPtr->shareable = 1;\n\t    cmapPtr->nextPtr = dispPtr->cmapPtr;\n\t    dispPtr->cmapPtr = cmapPtr;\n\t    *colormapPtr = cmapPtr->colormap;\n\t}\n    }\n\n  done:\n    return visual;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetColormap --\n *\n *\tGiven a string identifying a colormap, this procedure finds an\n *\tappropriate colormap.\n *\n * Results:\n *\tThe return value is normally the X resource identifier for the\n *\tcolormap. If an error occurs, None is returned and an error message is\n *\tplaced in the interp's result.\n *\n * Side effects:\n *\tA reference count is incremented for the colormap, so Tk_FreeColormap\n *\tmust eventually be called exactly once for each call to\n *\tTk_GetColormap.\n *\n *----------------------------------------------------------------------\n */\n\nColormap\nTk_GetColormap(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window where colormap will be used. */\n    const char *string)\t\t/* String that identifies colormap: either\n\t\t\t\t * \"new\" or the name of another window. */\n{\n    Colormap colormap;\n    TkColormap *cmapPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    Tk_Window other;\n\n    /*\n     * Allocate a new colormap, if that's what is wanted.\n     */\n\n    if (strcmp(string, \"new\") == 0) {\n\tcmapPtr = (TkColormap *)Tcl_Alloc(sizeof(TkColormap));\n\tcmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),\n\t\tRootWindowOfScreen(Tk_Screen(tkwin)), Tk_Visual(tkwin),\n\t\tAllocNone);\n\tcmapPtr->visual = Tk_Visual(tkwin);\n\tcmapPtr->refCount = 1;\n\tcmapPtr->shareable = 0;\n\tcmapPtr->nextPtr = dispPtr->cmapPtr;\n\tdispPtr->cmapPtr = cmapPtr;\n\treturn cmapPtr->colormap;\n    }\n\n    /*\n     * Use a colormap from an existing window. It must have the same visual as\n     * tkwin (which means, among other things, that the other window must be\n     * on the same screen).\n     */\n\n    other = Tk_NameToWindow(interp, string, tkwin);\n    if (other == NULL) {\n\treturn None;\n    }\n    if (Tk_Screen(other) != Tk_Screen(tkwin)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use colormap for %s: not on same screen\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"COLORMAP\", \"SCREEN\", (char *)NULL);\n\treturn None;\n    }\n    if (Tk_Visual(other) != Tk_Visual(tkwin)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use colormap for %s: incompatible visuals\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"COLORMAP\", \"INCOMPATIBLE\", (char *)NULL);\n\treturn None;\n    }\n    colormap = Tk_Colormap(other);\n\n    /*\n     * If the colormap was a special one allocated by code in this file,\n     * increment its reference count.\n     */\n\n    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;\n\t    cmapPtr = cmapPtr->nextPtr) {\n\tif (cmapPtr->colormap == colormap) {\n\t    cmapPtr->refCount++;\n\t}\n    }\n    return colormap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreeColormap --\n *\n *\tThis procedure is called to release a colormap that was previously\n *\tallocated by Tk_GetColormap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe colormap's reference count is decremented. If this was the last\n *\treference to the colormap, then the colormap is freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreeColormap(\n    Display *display,\t\t/* Display for which colormap was\n\t\t\t\t * allocated. */\n    Colormap colormap)\t\t/* Colormap that is no longer needed. Must\n\t\t\t\t * have been returned by previous call to\n\t\t\t\t * Tk_GetColormap, or preserved by a previous\n\t\t\t\t * call to Tk_PreserveColormap. */\n{\n    TkDisplay *dispPtr;\n    TkColormap *cmapPtr, *prevPtr;\n\n    /*\n     * Find Tk's information about the display, then see if this colormap is a\n     * non-default one (if it's a default one, there won't be an entry for it\n     * in the display's list).\n     */\n\n    dispPtr = TkGetDisplay(display);\n    if (dispPtr == NULL) {\n\tTcl_Panic(\"unknown display passed to Tk_FreeColormap\");\n    }\n    for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;\n\t    prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) {\n\tif (cmapPtr->colormap == colormap) {\n\t    if (cmapPtr->refCount-- <= 1) {\n\t\tXFreeColormap(display, colormap);\n\t\tif (prevPtr == NULL) {\n\t\t    dispPtr->cmapPtr = cmapPtr->nextPtr;\n\t\t} else {\n\t\t    prevPtr->nextPtr = cmapPtr->nextPtr;\n\t\t}\n\t\tTcl_Free(cmapPtr);\n\t    }\n\t    return;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PreserveColormap --\n *\n *\tThis procedure is called to indicate to Tk that the specified colormap\n *\tis being referenced from another location and should not be freed\n *\tuntil all extra references are eliminated. The colormap must have been\n *\treturned by Tk_GetColormap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe colormap's reference count is incremented, so Tk_FreeColormap must\n *\teventually be called exactly once for each call to\n *\tTk_PreserveColormap.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_PreserveColormap(\n    Display *display,\t\t/* Display for which colormap was\n\t\t\t\t * allocated. */\n    Colormap colormap)\t\t/* Colormap that should be preserved. */\n{\n    TkDisplay *dispPtr;\n    TkColormap *cmapPtr;\n\n    /*\n     * Find Tk's information about the display, then see if this colormap is a\n     * non-default one (if it's a default one, there won't be an entry for it\n     * in the display's list).\n     */\n\n    dispPtr = TkGetDisplay(display);\n    if (dispPtr == NULL) {\n\tTcl_Panic(\"unknown display passed to Tk_PreserveColormap\");\n    }\n    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;\n\t    cmapPtr = cmapPtr->nextPtr) {\n\tif (cmapPtr->colormap == colormap) {\n\t    cmapPtr->refCount++;\n\t    return;\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/tkWindow.c",
    "content": "/*\n * tkWindow.c --\n *\n *\tThis file provides basic window-manipulation functions, which are\n *\tequivalent to functions in Xlib (and even invoke them) but also\n *\tmaintain the local Tk_Window structure.\n *\n * Copyright © 1989-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkPort.h\"\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif !defined(MAC_OSX_TK)\n#include \"tkUnixInt.h\"\n#endif\n#include \"tkUuid.h\"\n\n/*\n * Type used to keep track of Window objects that were only partially\n * deallocated by Tk_DestroyWindow.\n */\n\n#define HD_CLEANUP\t\t1\n#define HD_FOCUS\t\t2\n#define HD_MAIN_WIN\t\t4\n#define HD_DESTROY_COUNT\t8\n#define HD_DESTROY_EVENT\t0x10\n\ntypedef struct TkHalfdeadWindow {\n    int flags;\n    struct TkWindow *winPtr;\n    struct TkHalfdeadWindow *nextPtr;\n} TkHalfdeadWindow;\n\ntypedef struct {\n    int numMainWindows;\t\t/* Count of number of main windows currently\n\t\t\t\t * open in this thread. */\n    TkMainInfo *mainWindowList;\n\t\t\t\t/* First in list of all main windows managed\n\t\t\t\t * by this thread. */\n    TkHalfdeadWindow *halfdeadWindowList;\n\t\t\t\t/* First in list of partially deallocated\n\t\t\t\t * windows. */\n    TkDisplay *displayList;\t/* List of all displays currently in use by\n\t\t\t\t * the current thread. */\n    bool initialized;\t\t/* false means the structures above need\n\t\t\t\t * initializing. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Default values for \"changes\" and \"atts\" fields of TkWindows. Note that Tk\n * always requests all events for all windows, except StructureNotify events\n * on internal windows: these events are generated internally.\n */\n\nstatic const XWindowChanges defChanges = {\n    0, 0, 1, 1, 0, 0, Above\n};\n#define ALL_EVENTS_MASK \\\n    KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \\\n    EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \\\n    VisibilityChangeMask|PropertyChangeMask|ColormapChangeMask\nstatic const XSetWindowAttributes defAtts= {\n    None,\t\t\t/* background_pixmap */\n    0,\t\t\t\t/* background_pixel */\n    CopyFromParent,\t\t/* border_pixmap */\n    0,\t\t\t\t/* border_pixel */\n    NorthWestGravity,\t\t/* bit_gravity */\n    NorthWestGravity,\t\t/* win_gravity */\n    NotUseful,\t\t\t/* backing_store */\n    (unsigned) ~0,\t\t/* backing_planes */\n    0,\t\t\t\t/* backing_pixel */\n    False,\t\t\t/* save_under */\n    ALL_EVENTS_MASK,\t\t/* event_mask */\n    0,\t\t\t\t/* do_not_propagate_mask */\n    False,\t\t\t/* override_redirect */\n    CopyFromParent,\t\t/* colormap */\n    None\t\t\t/* cursor */\n};\n\n/*\n * The following structure defines all of the commands supported by Tk, and\n * the C functions that execute them.\n */\n\n#define ISSAFE 1\n#define PASSMAINWINDOW 2\n#define WINMACONLY 4\n#define USEINITPROC 8\n#define SAVEUPDATECMD 16 /* better only be one of these! */\n\ntypedef int (TkInitProc)(Tcl_Interp *interp, void *clientData);\ntypedef struct {\n    const char *name;\t\t/* Name of command. */\n    Tcl_ObjCmdProc2 *objProc;\t/* Command's object- (or string-) based\n\t\t\t\t * function, or initProc. */\n    int flags;\n} TkCmd;\n\nstatic const TkCmd commands[] = {\n    /*\n     * Commands that are part of the intrinsics:\n     */\n\n    {\"bell\",\t\tTk_BellObjCmd,\t\tPASSMAINWINDOW},\n    {\"bind\",\t\tTk_BindObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"bindtags\",\tTk_BindtagsObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"clipboard\",\tTk_ClipboardObjCmd,\tPASSMAINWINDOW},\n    {\"destroy\",\t\tTk_DestroyObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"event\",\t\tTk_EventObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"focus\",\t\tTk_FocusObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"font\",\t\tTk_FontObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"grab\",\t\tTk_GrabObjCmd,\t\tPASSMAINWINDOW},\n    {\"grid\",\t\tTk_GridObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"image\",\t\tTk_ImageObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"lower\",\t\tTk_LowerObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"option\",\t\tTk_OptionObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"pack\",\t\tTk_PackObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"place\",\t\tTk_PlaceObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"raise\",\t\tTk_RaiseObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"selection\",\tTk_SelectionObjCmd,\tPASSMAINWINDOW},\n    {\"tk\",\t\t(Tcl_ObjCmdProc2 *)(void *)TkInitTkCmd,  USEINITPROC|PASSMAINWINDOW|ISSAFE},\n    {\"tkwait\",\t\tTk_TkwaitObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"update\",\t\tTk_UpdateObjCmd,\tPASSMAINWINDOW|ISSAFE|SAVEUPDATECMD},\n    {\"winfo\",\t\tTk_WinfoObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"wm\",\t\tTk_WmObjCmd,\t\tPASSMAINWINDOW},\n\n    /*\n     * Default widget class commands.\n     */\n\n    {\"button\",\t\tTk_ButtonObjCmd,\tISSAFE},\n    {\"canvas\",\t\tTk_CanvasObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"checkbutton\",\tTk_CheckbuttonObjCmd,\tISSAFE},\n    {\"entry\",\t\tTk_EntryObjCmd,\t\tISSAFE},\n    {\"frame\",\t\tTk_FrameObjCmd,\t\tISSAFE},\n    {\"label\",\t\tTk_LabelObjCmd,\t\tISSAFE},\n    {\"labelframe\",\tTk_LabelframeObjCmd,\tISSAFE},\n    {\"listbox\",\t\tTk_ListboxObjCmd,\tISSAFE},\n    {\"menu\",\t\tTk_MenuObjCmd,\tPASSMAINWINDOW},\n    {\"menubutton\",\tTk_MenubuttonObjCmd,\tISSAFE},\n    {\"message\",\t\tTk_MessageObjCmd,\tISSAFE},\n    {\"panedwindow\",\tTk_PanedWindowObjCmd,\tISSAFE},\n    {\"radiobutton\",\tTk_RadiobuttonObjCmd,\tISSAFE},\n    {\"scale\",\t\tTk_ScaleObjCmd,\t\tISSAFE},\n    {\"scrollbar\",\tTk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},\n    {\"spinbox\",\t\tTk_SpinboxObjCmd,\tISSAFE},\n    {\"text\",\t\tTk_TextObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"toplevel\",\tTk_ToplevelObjCmd,\t0},\n\n    /*\n     * Classic widget class commands.\n     */\n\n    {\"::tk::button\",\tTk_ButtonObjCmd,\tISSAFE},\n    {\"::tk::canvas\",\tTk_CanvasObjCmd,\tPASSMAINWINDOW|ISSAFE},\n    {\"::tk::checkbutton\",Tk_CheckbuttonObjCmd,\tISSAFE},\n    {\"::tk::entry\",\tTk_EntryObjCmd,\t\tISSAFE},\n    {\"::tk::frame\",\tTk_FrameObjCmd,\t\tISSAFE},\n    {\"::tk::label\",\tTk_LabelObjCmd,\t\tISSAFE},\n    {\"::tk::labelframe\",Tk_LabelframeObjCmd,\tISSAFE},\n    {\"::tk::listbox\",\tTk_ListboxObjCmd,\tISSAFE},\n    {\"::tk::menubutton\",Tk_MenubuttonObjCmd,\tISSAFE},\n    {\"::tk::message\",\tTk_MessageObjCmd,\tISSAFE},\n    {\"::tk::panedwindow\",Tk_PanedWindowObjCmd,\tISSAFE},\n    {\"::tk::radiobutton\",Tk_RadiobuttonObjCmd,\tISSAFE},\n    {\"::tk::scale\",\tTk_ScaleObjCmd,\t\tISSAFE},\n    {\"::tk::scrollbar\",\tTk_ScrollbarObjCmd, PASSMAINWINDOW|ISSAFE},\n    {\"::tk::spinbox\",\tTk_SpinboxObjCmd,\tISSAFE},\n    {\"::tk::text\",\tTk_TextObjCmd,\t\tPASSMAINWINDOW|ISSAFE},\n    {\"::tk::toplevel\",\tTk_ToplevelObjCmd,\t0},\n\n    /*\n     * Standard dialog support. Note that the Unix/X11 platform implements\n     * these commands differently (via the script library).\n     */\n\n#if defined(_WIN32) || defined(MAC_OSX_TK)\n    {\"tk_chooseColor\",\tTk_ChooseColorObjCmd,\tPASSMAINWINDOW},\n    {\"tk_chooseDirectory\", Tk_ChooseDirectoryObjCmd,WINMACONLY|PASSMAINWINDOW},\n    {\"tk_getOpenFile\",\tTk_GetOpenFileObjCmd,\tWINMACONLY|PASSMAINWINDOW},\n    {\"tk_getSaveFile\",\tTk_GetSaveFileObjCmd,\tWINMACONLY|PASSMAINWINDOW},\n    {\"tk_messageBox\",\tTk_MessageBoxObjCmd,\tPASSMAINWINDOW},\n#endif\n\n    /*\n     * Misc.\n     */\n\n#ifdef MAC_OSX_TK\n    {\"::tk::unsupported::MacWindowStyle\",\n\t\t\tTkUnsupported1ObjCmd,\tPASSMAINWINDOW|ISSAFE},\n#endif\n    {NULL,\t\tNULL,\t\t\t0}\n};\n\nextern int TkAccessibility_Init(Tcl_Interp *interp);\n\n/*\n * Forward declarations to functions defined later in this file:\n */\n\nstatic Tk_Window\tCreateTopLevelWindow(Tcl_Interp *interp,\n\t\t\t    Tk_Window parent, const char *name,\n\t\t\t    const char *screenName, unsigned int flags);\nstatic void\t\tDeleteWindowsExitProc(void *clientData);\nstatic TkDisplay *\tGetScreen(Tcl_Interp *interp, const char *screenName,\n\t\t\t    int *screenPtr);\nstatic int\t\tInitialize(Tcl_Interp *interp);\nstatic int\t\tNameWindow(Tcl_Interp *interp, TkWindow *winPtr,\n\t\t\t    TkWindow *parentPtr, const char *name);\nstatic void\t\tUnlinkWindow(TkWindow *winPtr);\n\n/*\n * This static variable only makes sense for macOS and Windows, which never\n * have more than one display.  It is set by TkCloseDisplay, and when set\n * prevents sending Enter and Leave events when all of the windows in the\n * display are being destroyed.  Tk does not send those events on X11; that\n * job is handled by the X server.\n */\n\nstatic int displayBeingClosed = 0;\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCloseDisplay --\n *\n *\tClosing the display can lead to order of deletion problems. We defer\n *\tit until exit handling for Mac/Win, but since Unix can use many\n *\tdisplays, try and clean it up as best as possible.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources associated with the display will be free. The display may\n *\tnot be referenced at all after this.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkCloseDisplay(\n    TkDisplay *dispPtr)\n{\n    displayBeingClosed = 1;\n    TkClipCleanup(dispPtr);\n\n    if (dispPtr->name != NULL) {\n\tTcl_Free(dispPtr->name);\n    }\n\n    if (dispPtr->atomInit) {\n\tTcl_DeleteHashTable(&dispPtr->nameTable);\n\tTcl_DeleteHashTable(&dispPtr->atomTable);\n\tdispPtr->atomInit = 0;\n    }\n\n    if (dispPtr->errorPtr != NULL) {\n\tTkErrorHandler *errorPtr;\n\n\tfor (errorPtr = dispPtr->errorPtr;\n\t\terrorPtr != NULL;\n\t\terrorPtr = dispPtr->errorPtr) {\n\t    dispPtr->errorPtr = errorPtr->nextPtr;\n\t    Tcl_Free(errorPtr);\n\t}\n    }\n\n    TkGCCleanup(dispPtr);\n\n    TkpCloseDisplay(dispPtr);\n\n    /*\n     * Delete winTable after TkpCloseDisplay since special windows may need\n     * call Tk_DestroyWindow and it checks the winTable.\n     */\n\n    Tcl_DeleteHashTable(&dispPtr->winTable);\n\n    Tcl_Free(dispPtr);\n\n    /*\n     * There is more to clean up, we leave it at this for the time being.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateTopLevelWindow --\n *\n *\tMake a new window that will be at top-level (its parent will be the\n *\troot window of a screen).\n *\n * Results:\n *\tThe return value is a token for the new window, or NULL if an error\n *\tprevented the new window from being created. If NULL is returned, an\n *\terror message will be left in the interp's result.\n *\n * Side effects:\n *\tA new window structure is allocated locally. An X window is NOT\n *\tinitially created, but will be created the first time the window is\n *\tmapped.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_Window\nCreateTopLevelWindow(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window parent,\t\t/* Token for logical parent of new window\n\t\t\t\t * (used for naming, options, etc.). May be\n\t\t\t\t * NULL. */\n    const char *name,\t\t/* Name for new window; if parent is non-NULL,\n\t\t\t\t * must be unique among parent's children. */\n    const char *screenName,\t/* Name of screen on which to create window.\n\t\t\t\t * NULL means use DISPLAY environment variable\n\t\t\t\t * to determine. Empty string means use\n\t\t\t\t * parent's screen, or DISPLAY if no\n\t\t\t\t * parent. */\n    unsigned int flags)\t\t/* Additional flags to set on the window. */\n{\n    TkWindow *winPtr;\n    TkDisplay *dispPtr;\n    int screenId;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\n\t/*\n\t * Create built-in image types.\n\t */\n\n\tTk_CreateImageType(&tkBitmapImageType);\n\tTk_CreateImageType(&tkPhotoImageType);\n\n\t/*\n\t * Create built-in photo image formats.\n\t */\n\n\tTk_CreatePhotoImageFormat(&tkImgFmtDefault);\n\tTk_CreatePhotoImageFormatVersion3(&tkImgFmtGIF);\n\tTk_CreatePhotoImageFormatVersion3(&tkImgFmtPNG);\n\tTk_CreatePhotoImageFormat(&tkImgFmtPPM);\n\tTk_CreatePhotoImageFormat(&tkImgFmtSVGnano);\n    }\n\n    if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\\0')) {\n\tdispPtr = ((TkWindow *) parent)->dispPtr;\n\tscreenId = Tk_ScreenNumber(parent);\n    } else {\n\tdispPtr = GetScreen(interp, screenName, &screenId);\n\tif (dispPtr == NULL) {\n\t    return NULL;\n\t}\n    }\n\n    winPtr = TkAllocWindow(dispPtr, screenId, (TkWindow *) parent);\n\n    /*\n     * Set the flags specified in the call.\n     */\n\n    winPtr->ximGeneration = 0;\n    winPtr->flags |= flags;\n\n    /*\n     * Force the window to use a border pixel instead of border pixmap. This\n     * is needed for the case where the window doesn't use the default visual.\n     * In this case, the default border is a pixmap inherited from the root\n     * window, which won't work because it will have the wrong visual.\n     */\n\n    winPtr->dirtyAtts |= CWBorderPixel;\n\n    /*\n     * (Need to set the TK_TOP_HIERARCHY flag immediately here; otherwise\n     * Tk_DestroyWindow will core dump if it is called before the flag has\n     * been set.)\n     */\n\n    winPtr->flags |=\n\t    TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;\n\n    if (parent != NULL) {\n\tif (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {\n\t    Tk_DestroyWindow((Tk_Window) winPtr);\n\t    return NULL;\n\t}\n    }\n    TkWmNewWindow(winPtr);\n\n    return (Tk_Window) winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetScreen --\n *\n *\tGiven a string name for a display-plus-screen, find the TkDisplay\n *\tstructure for the display and return the screen number too.\n *\n * Results:\n *\tThe return value is a pointer to information about the display, or\n *\tNULL if the display couldn't be opened. In this case, an error message\n *\tis left in the interp's result. The location at *screenPtr is\n *\toverwritten with the screen number parsed from screenName.\n *\n * Side effects:\n *\tA new connection is opened to the display if there is no connection\n *\talready. A new TkDisplay data structure is also setup, if necessary.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkDisplay *\nGetScreen(\n    Tcl_Interp *interp,\t\t/* Place to leave error message. */\n    const char *screenName,\t/* Name for screen. NULL or empty means use\n\t\t\t\t * DISPLAY envariable. */\n    int *screenPtr)\t\t/* Where to store screen number. */\n{\n    TkDisplay *dispPtr;\n    const char *p;\n    int screenId;\n    size_t length;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Separate the screen number from the rest of the display name.\n     * ScreenName is assumed to have the syntax <display>.<screen> with the\n     * dot and the screen being optional.\n     */\n\n    screenName = TkGetDefaultScreenName(interp, screenName);\n    if (screenName == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"no display name and no $DISPLAY environment variable\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"NO_DISPLAY\", (char *)NULL);\n\treturn NULL;\n    }\n    length = strlen(screenName);\n    screenId = 0;\n    p = screenName+length-1;\n    while (isdigit(UCHAR(*p)) && (p != screenName)) {\n\tp--;\n    }\n    if ((*p == '.') && (p[1] != '\\0')) {\n\tlength = (size_t)(p - screenName);\n\tscreenId = (int)strtoul(p+1, NULL, 10);\n    }\n\n    /*\n     * See if we already have a connection to this display. If not, then open\n     * a new connection.\n     */\n\n    for (dispPtr = tsdPtr->displayList; ; dispPtr = dispPtr->nextPtr) {\n\tif (dispPtr == NULL) {\n\t    /*\n\t     * The private function zeros out dispPtr when it is created, so\n\t     * we only need to initialize the non-zero items.\n\t     */\n\n\t    dispPtr = TkpOpenDisplay(screenName);\n\t    if (dispPtr == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"couldn't connect to display \\\"%s\\\"\", screenName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"DISPLAY\", \"CONNECT\", (char *)NULL);\n\t\treturn NULL;\n\t    }\n\t    dispPtr->nextPtr = tsdPtr->displayList; /* TkGetDisplayList(); */\n\t    tsdPtr->displayList = dispPtr;\n\n\t    dispPtr->lastEventTime = CurrentTime;\n\t    dispPtr->bindInfoStale = 1;\n\t    dispPtr->cursorFont = None;\n\t    dispPtr->warpWindow = NULL;\n\t    dispPtr->multipleAtom = None;\n\n\t    /*\n\t     * By default we do want to collapse motion events in\n\t     * Tk_QueueWindowEvent.\n\t     */\n\n\t    dispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS;\n\n\t    Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);\n\n\t    dispPtr->name = (char *)Tcl_Alloc(length + 1);\n\t    strncpy(dispPtr->name, screenName, length);\n\t    dispPtr->name[length] = '\\0';\n\t    break;\n\t}\n\tif ((strncmp(dispPtr->name, screenName, length) == 0)\n\t\t&& (dispPtr->name[length] == '\\0')) {\n\t    break;\n\t}\n    }\n    if (screenId >= ScreenCount(dispPtr->display)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad screen number \\\"%d\\\"\", screenId));\n\tTcl_SetErrorCode(interp, \"TK\", \"DISPLAY\", \"SCREEN_NUMBER\", (char *)NULL);\n\treturn NULL;\n    }\n    *screenPtr = screenId;\n    return dispPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetDisplay --\n *\n *\tGiven an X display, TkGetDisplay returns the TkDisplay structure for\n *\tthe display.\n *\n * Results:\n *\tThe return value is a pointer to information about the display, or\n *\tNULL if the display did not have a TkDisplay structure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkDisplay *\nTkGetDisplay(\n    Display *display)\t\t/* X's display pointer */\n{\n    TkDisplay *dispPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (dispPtr = tsdPtr->displayList; dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tif (dispPtr->display == display) {\n\t    break;\n\t}\n    }\n    return dispPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkGetDisplayList --\n *\n *\tThis function returns a pointer to the thread-local list of TkDisplays\n *\tcorresponding to the open displays.\n *\n * Results:\n *\tThe return value is a pointer to the first TkDisplay structure in\n *\tthread-local-storage.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nTkDisplay *\nTkGetDisplayList(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return tsdPtr->displayList;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkGetMainInfoList --\n *\n *\tThis function returns a pointer to the list of structures containing\n *\tinformation about all main windows for the current thread.\n *\n * Results:\n *\tThe return value is a pointer to the first TkMainInfo structure in\n *\tthread local storage.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nTkMainInfo *\nTkGetMainInfoList(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return tsdPtr->mainWindowList;\n}\n/*\n *--------------------------------------------------------------\n *\n * TkAllocWindow --\n *\n *\tThis function creates and initializes a TkWindow structure.\n *\n * Results:\n *\tThe return value is a pointer to the new window.\n *\n * Side effects:\n *\tA new window structure is allocated and all its fields are\n *\tinitialized.\n *\n *--------------------------------------------------------------\n */\n\nTkWindow *\nTkAllocWindow(\n    TkDisplay *dispPtr,\t\t/* Display associated with new window. */\n    int screenNum,\t\t/* Index of screen for new window. */\n    TkWindow *parentPtr)\t/* Parent from which this window should\n\t\t\t\t * inherit visual information. NULL means use\n\t\t\t\t * screen defaults instead of inheriting. */\n{\n    TkWindow *winPtr = (TkWindow *)Tcl_Alloc(sizeof(TkWindow));\n\n    winPtr->display = dispPtr->display;\n    winPtr->dispPtr = dispPtr;\n    winPtr->screenNum = screenNum;\n    if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)\n\t    && (parentPtr->screenNum == winPtr->screenNum)) {\n\twinPtr->visual = parentPtr->visual;\n\twinPtr->depth = parentPtr->depth;\n    } else {\n\twinPtr->visual = DefaultVisual(dispPtr->display, screenNum);\n\twinPtr->depth = DefaultDepth(dispPtr->display, screenNum);\n    }\n    winPtr->window = None;\n    winPtr->childList = NULL;\n    winPtr->lastChildPtr = NULL;\n    winPtr->parentPtr = NULL;\n    winPtr->nextPtr = NULL;\n    winPtr->mainPtr = NULL;\n    winPtr->pathName = NULL;\n    winPtr->nameUid = NULL;\n    winPtr->classUid = NULL;\n    winPtr->changes = defChanges;\n    winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;\n    winPtr->atts = defAtts;\n    if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)\n\t    && (parentPtr->screenNum == winPtr->screenNum)) {\n\twinPtr->atts.colormap = parentPtr->atts.colormap;\n    } else {\n\twinPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);\n    }\n    winPtr->dirtyAtts = CWEventMask|CWColormap|CWBitGravity;\n    winPtr->flags = 0;\n    winPtr->handlerList = NULL;\n    winPtr->ximGeneration = 0;\n    winPtr->inputContext = NULL;\n    winPtr->tagPtr = NULL;\n    winPtr->numTags = 0;\n    winPtr->optionLevel = TCL_INDEX_NONE;\n    winPtr->selHandlerList = NULL;\n    winPtr->geomMgrPtr = NULL;\n    winPtr->geomData = NULL;\n    winPtr->geomMgrName = NULL;\n    winPtr->maintainerPtr = NULL;\n    winPtr->reqWidth = winPtr->reqHeight = 1;\n    winPtr->internalBorderLeft = 0;\n    winPtr->wmInfoPtr = NULL;\n    winPtr->classProcsPtr = NULL;\n    winPtr->instanceData = NULL;\n    winPtr->privatePtr = NULL;\n    winPtr->internalBorderRight = 0;\n    winPtr->internalBorderTop = 0;\n    winPtr->internalBorderBottom = 0;\n    winPtr->minReqWidth = 0;\n    winPtr->minReqHeight = 0;\n\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NameWindow --\n *\n *\tThis function is invoked to give a window a name and insert the window\n *\tinto the hierarchy associated with a particular application.\n *\n * Results:\n *\tA standard Tcl return value.\n *\n * Side effects:\n *\tSee above.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nNameWindow(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    TkWindow *winPtr,\t/* Window that is to be named and inserted. */\n    TkWindow *parentPtr,\t/* Pointer to logical parent for winPtr (used\n\t\t\t\t * for naming, options, etc.). */\n    const char *name)\t\t/* Name for winPtr; must be unique among\n\t\t\t\t * parentPtr's children. */\n{\n#define FIXED_SIZE 200\n    char staticSpace[FIXED_SIZE];\n    char *pathName;\n    int isNew;\n    Tcl_HashEntry *hPtr;\n    size_t length1, length2;\n\n    /*\n     * Setup all the stuff except name right away, then do the name stuff\n     * last. This is so that if the name stuff fails, everything else will be\n     * properly initialized (needed to destroy the window cleanly after the\n     * naming failure).\n     */\n\n    winPtr->parentPtr = parentPtr;\n    winPtr->nextPtr = NULL;\n    if (parentPtr->childList == NULL) {\n\tparentPtr->childList = winPtr;\n    } else {\n\tparentPtr->lastChildPtr->nextPtr = winPtr;\n    }\n    parentPtr->lastChildPtr = winPtr;\n    winPtr->mainPtr = parentPtr->mainPtr;\n    winPtr->mainPtr->refCount++;\n\n    /*\n     * If this is an anonymous window (ie, it has no name), just return OK\n     * now.\n     */\n\n    if (winPtr->flags & TK_ANONYMOUS_WINDOW) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Don't permit names that start with an upper-case letter: this will just\n     * cause confusion with class names in the option database.\n     */\n\n    if (isupper(UCHAR(name[0]))) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window name starts with an upper-case letter: \\\"%s\\\"\",\n\t\tname));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"WINDOW\", \"NOTCLASS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * For non-anonymous windows, set up the window name.\n     */\n\n    winPtr->nameUid = Tk_GetUid(name);\n\n    /*\n     * To permit names of arbitrary length, must be prepared to malloc a\n     * buffer to hold the new path name. To run fast in the common case where\n     * names are short, use a fixed-size buffer on the stack.\n     */\n\n    length1 = strlen(parentPtr->pathName);\n    length2 = strlen(name);\n    if ((length1 + length2 + 2) <= FIXED_SIZE) {\n\tpathName = staticSpace;\n    } else {\n\tpathName = (char *)Tcl_Alloc(length1 + length2 + 2);\n    }\n    if (length1 == 1) {\n\tpathName[0] = '.';\n\tstrcpy(pathName+1, name);\n    } else {\n\tstrcpy(pathName, parentPtr->pathName);\n\tpathName[length1] = '.';\n\tstrcpy(pathName+length1+1, name);\n    }\n    hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName,\n\t    &isNew);\n    if (pathName != staticSpace) {\n\tTcl_Free(pathName);\n    }\n    if (!isNew) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window name \\\"%s\\\" already exists in parent\", name));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"WINDOW\", \"EXISTS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    Tcl_SetHashValue(hPtr, winPtr);\n    winPtr->pathName = (char *)Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateMainWindow --\n *\n *\tMake a new main window. A main window is a special kind of top-level\n *\twindow used as the outermost window in an application.\n *\n * Results:\n *\tThe return value is a token for the new window, or NULL if an error\n *\tprevented the new window from being created. If NULL is returned, an\n *\terror message will be left in the interp's result.\n *\n * Side effects:\n *\tA new window structure is allocated locally; \"interp\" is associated\n *\twith the window and registered for \"send\" commands under \"baseName\".\n *\tBaseName may be extended with an instance number in the form \"#2\" if\n *\tnecessary to make it globally unique. Tk-related commands are bound\n *\tinto interp.\n *\n *----------------------------------------------------------------------\n */\n\n#ifndef STRINGIFY\n#  define STRINGIFY(x) STRINGIFY1(x)\n#  define STRINGIFY1(x) #x\n#endif\n\nTk_Window\nTkCreateMainWindow(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    const char *screenName,\t/* Name of screen on which to create window.\n\t\t\t\t * Empty or NULL string means use DISPLAY\n\t\t\t\t * environment variable. */\n    const char *baseName)\t/* Base name for application; usually of the\n\t\t\t\t * form \"prog instance\". */\n{\n    Tk_Window tkwin;\n    int dummy, isSafe;\n    Tcl_HashEntry *hPtr;\n    TkMainInfo *mainPtr;\n    TkWindow *winPtr;\n    const TkCmd *cmdPtr;\n    void *clientData;\n    Tcl_CmdInfo info;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Panic if someone updated the TkWindow structure without also updating\n     * the Tk_FakeWin structure (or vice versa).\n     */\n\n    if (sizeof(TkWindow) != sizeof(Tk_FakeWin)) {\n\tTcl_Panic(\"TkWindow and Tk_FakeWin are not the same size\");\n    }\n\n    /*\n     * Create the basic TkWindow structure.\n     */\n\n    tkwin = CreateTopLevelWindow(interp, NULL, baseName,\n\t    screenName, /* flags */ 0);\n    if (tkwin == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Create the TkMainInfo structure for this application, and set up\n     * name-related information for the new window.\n     */\n\n    winPtr = (TkWindow *) tkwin;\n    mainPtr = (TkMainInfo *)Tcl_Alloc(sizeof(TkMainInfo));\n    mainPtr->winPtr = winPtr;\n    mainPtr->refCount = 1;\n    mainPtr->interp = interp;\n    Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);\n    mainPtr->deletionEpoch = 0l;\n    TkBindInit(mainPtr);\n    TkFontPkgInit(mainPtr);\n    TkStylePkgInit(mainPtr);\n    mainPtr->tlFocusPtr = NULL;\n    mainPtr->displayFocusPtr = NULL;\n    mainPtr->optionRootPtr = NULL;\n    Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS);\n    mainPtr->strictMotif = 0;\n    mainPtr->alwaysShowSelection = 0;\n    mainPtr->tclUpdateObjProc = NULL;\n    mainPtr->tclUpdateObjProc2 = NULL;\n    if (Tcl_LinkVar(interp, \"tk_strictMotif\", &mainPtr->strictMotif,\n\t    TCL_LINK_BOOLEAN) != TCL_OK) {\n\tTcl_ResetResult(interp);\n    }\n    if (Tcl_CreateNamespace(interp, \"::tk\", NULL, NULL) == NULL) {\n\tTcl_ResetResult(interp);\n    }\n    if (Tcl_LinkVar(interp, \"::tk::AlwaysShowSelection\",\n\t    &mainPtr->alwaysShowSelection,\n\t    TCL_LINK_BOOLEAN) != TCL_OK) {\n\tTcl_ResetResult(interp);\n    }\n    mainPtr->nextPtr = tsdPtr->mainWindowList;\n    tsdPtr->mainWindowList = mainPtr;\n    winPtr->mainPtr = mainPtr;\n    hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, \".\", &dummy);\n    Tcl_SetHashValue(hPtr, winPtr);\n    winPtr->pathName = (char *)Tcl_GetHashKey(&mainPtr->nameTable, hPtr);\n    Tcl_InitHashTable(&mainPtr->busyTable, TCL_ONE_WORD_KEYS);\n\n    /*\n     * We have just created another Tk application; increment the refcount on\n     * the display pointer.\n     */\n\n    winPtr->dispPtr->refCount++;\n\n    /*\n     * Register the interpreter for \"send\" purposes.\n     */\n\n    winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, baseName));\n\n    /*\n     * Bind in Tk's commands.\n     */\n\n    isSafe = Tcl_IsSafe(interp);\n    for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {\n\tTcl_CmdInfo cmdInfo;\n\n\tif (cmdPtr->objProc == NULL) {\n\t    Tcl_Panic(\"TkCreateMainWindow: builtin command with NULL string and object procs\");\n\t}\n\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n\tif ((cmdPtr->flags & WINMACONLY) && tclStubsPtr->tcl_CreateFileHandler) {\n\t    /*\n\t     * We are running on Cygwin, so don't use the win32 dialogs.\n\t     */\n\n\t    continue;\n\t}\n#endif /* _WIN32 && !STATIC_BUILD */\n\n\tif (cmdPtr->flags & PASSMAINWINDOW) {\n\t    clientData = tkwin;\n\t} else {\n\t    clientData = NULL;\n\t}\n\tif ((cmdPtr->flags & SAVEUPDATECMD) &&\n\t    Tcl_GetCommandInfo(interp, cmdPtr->name, &cmdInfo) &&\n\t    cmdInfo.isNativeObjectProc && !cmdInfo.deleteProc) {\n\t    if ((cmdInfo.isNativeObjectProc == 2) && !cmdInfo.objClientData2) {\n\t\tmainPtr->tclUpdateObjProc2 = cmdInfo.objProc2;\n#ifndef TCL_NO_DEPRECATED\n\t    } else if (!cmdInfo.objClientData) {\n\t\tmainPtr->tclUpdateObjProc = (void *)cmdInfo.objProc;\n#endif /* TCL_NO_DEPRECATED */\n\t    }\n\t}\n\tif (cmdPtr->flags & USEINITPROC) {\n\t    ((TkInitProc *)(void *)cmdPtr->objProc)(interp, clientData);\n\t} else {\n\t    Tcl_CreateObjCommand2(interp, cmdPtr->name, cmdPtr->objProc,\n\t\t    clientData, NULL);\n\t}\n\tif (isSafe && !(cmdPtr->flags & ISSAFE)) {\n\t    Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);\n\t}\n    }\n    if (Tcl_GetCommandInfo(interp, \"::tcl::build-info\", &info)) {\n\tstatic const char version[] = TK_PATCH_LEVEL \"+\" STRINGIFY(TK_VERSION_UUID)\n#if defined(MAC_OSX_TK)\n\t\t\".aqua\"\n#endif\n#if defined(__clang__) && defined(__clang_major__)\n\t\t\".clang-\" STRINGIFY(__clang_major__)\n#if __clang_minor__ < 10\n\t\t\"0\"\n#endif\n\t\tSTRINGIFY(__clang_minor__)\n#endif\n#if defined(__cplusplus) && !defined(__OBJC__)\n\t\t\".cplusplus\"\n#endif\n#ifndef NDEBUG\n\t\t\".debug\"\n#endif\n#if !defined(__clang__) && !defined(__INTEL_COMPILER) && defined(__GNUC__)\n\t\t\".gcc-\" STRINGIFY(__GNUC__)\n#if __GNUC_MINOR__ < 10\n\t\t\"0\"\n#endif\n\t\tSTRINGIFY(__GNUC_MINOR__)\n#endif\n#ifdef __INTEL_COMPILER\n\t\t\".icc-\" STRINGIFY(__INTEL_COMPILER)\n#endif\n#ifdef TCL_MEM_DEBUG\n\t\t\".memdebug\"\n#endif\n#if defined(_MSC_VER)\n\t\t\".msvc-\" STRINGIFY(_MSC_VER)\n#endif\n#ifdef USE_NMAKE\n\t\t\".nmake\"\n#endif\n#if !defined(_WIN32) && !defined(MAC_OSX_TK) && !defined(HAVE_ATK)\n\t\t\".no-atk\"\n#endif\n#if !defined(_WIN32) && !defined(MAC_OSX_TK) && !(defined(TK_USE_WAYLAND) || defined(HAVE_BIDI))\n\t\t\".no-bidi\"\n#endif\n#ifdef TK_NO_DEPRECATED\n\t\t\".no-deprecate\"\n#endif\n#ifndef TCL_CFG_OPTIMIZED\n\t\t\".no-optimize\"\n#endif\n#if !defined(_WIN32) && !defined(MAC_OSX_TK) && !defined(TK_USE_WAYLAND) && !defined(HAVE_XFT)\n\t\t\".no-xft\"\n#endif\n#if !defined(_WIN32) && !defined(MAC_OSX_TK) && !defined(TK_USE_WAYLAND) && !defined(HAVE_XSS)\n\t\t\".no-xss\"\n#endif\n#ifdef __OBJC__\n\t\t\".objective-c\"\n#if defined(__cplusplus)\n\t\t\"plusplus\"\n#endif\n#endif\n#ifdef TCL_CFG_PROFILED\n\t\t\".profile\"\n#endif\n#ifdef PURIFY\n\t\t\".purify\"\n#endif\n#ifdef STATIC_BUILD\n\t\t\".static\"\n#endif\n#if (defined(__MSVCRT__) || defined(_UCRT)) && (!defined(__USE_MINGW_ANSI_STDIO) || __USE_MINGW_ANSI_STDIO)\n\t\t\".stdio-mingw\"\n#endif\n#if defined(_WIN32)\n\t\t\".win32\"\n#endif\n#if !defined(_WIN32) && !defined(MAC_OSX_TK) && !defined(TK_USE_WAYLAND)\n\t\t\".x11\"\n#endif\n\t\t;\n\tif (info.isNativeObjectProc) {\n\t    Tcl_CreateObjCommand2(interp, \"::tk::build-info\",\n\t\t    info.objProc2, (void *)version, NULL);\n\n\t}\n    }\n\n    /*\n     * Set variables for the interpreter.\n     */\n\n    Tcl_SetVar2(interp, \"tk_patchLevel\", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);\n    Tcl_SetVar2(interp, \"tk_version\",    NULL, TK_VERSION,     TCL_GLOBAL_ONLY);\n\n    tsdPtr->numMainWindows++;\n    return tkwin;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateWindow --\n *\n *\tCreate a new internal or top-level window as a child of an existing\n *\twindow.\n *\n * Results:\n *\tThe return value is a token for the new window. This is not the same\n *\tas X's token for the window. If an error occurred in creating the\n *\twindow (e.g. no such display or screen), then an error message is left\n *\tin the interp's result and NULL is returned.\n *\n * Side effects:\n *\tA new window structure is allocated locally. An X window is not\n *\tinitially created, but will be created the first time the window is\n *\tmapped.\n *\n *--------------------------------------------------------------\n */\n\nTk_Window\nTk_CreateWindow(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting.\n\t\t\t\t * the interp's result is assumed to be\n\t\t\t\t * initialized by the caller. */\n    Tk_Window parent,\t\t/* Token for parent of new window. */\n    const char *name,\t\t/* Name for new window. Must be unique among\n\t\t\t\t * parent's children. */\n    const char *screenName)\t/* If NULL, new window will be internal on\n\t\t\t\t * same screen as its parent. If non-NULL,\n\t\t\t\t * gives name of screen on which to create new\n\t\t\t\t * window; window will be a top-level\n\t\t\t\t * window. */\n{\n    TkWindow *parentPtr = (TkWindow *) parent;\n\n    if (parentPtr) {\n\tif (parentPtr->flags & TK_ALREADY_DEAD) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't create window: parent has been destroyed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"DEAD_PARENT\", (char *)NULL);\n\t    return NULL;\n\t} else if (parentPtr->flags & TK_CONTAINER) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't create window: its parent has -container = yes\",\n\t\t    TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"CONTAINER\", (char *)NULL);\n\t    return NULL;\n\t} else if (screenName == NULL) {\n\t    TkWindow *winPtr = TkAllocWindow(parentPtr->dispPtr,\n\t\t    parentPtr->screenNum, parentPtr);\n\n\t    if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {\n\t\tTk_DestroyWindow((Tk_Window) winPtr);\n\t\treturn NULL;\n\t    }\n\t    return (Tk_Window) winPtr;\n\t}\n    }\n    return CreateTopLevelWindow(interp, parent, name, screenName,\n\t    /* flags */ 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_CreateAnonymousWindow --\n *\n *\tCreate a new internal or top-level window as a child of an existing\n *\twindow; this window will be anonymous (unnamed), so it will not be\n *\tvisible at the Tcl level.\n *\n * Results:\n *\tThe return value is a token for the new window. This is not the same\n *\tas X's token for the window. If an error occurred in creating the\n *\twindow (e.g. no such display or screen), then an error message is left\n *\tin the interp's result and NULL is returned.\n *\n * Side effects:\n *\tA new window structure is allocated locally. An X window is not\n *\tinitially created, but will be created the first time the window is\n *\tmapped.\n *\n *--------------------------------------------------------------\n */\n\nTk_Window\nTk_CreateAnonymousWindow(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting.\n\t\t\t\t * the interp's result is assumed to be\n\t\t\t\t * initialized by the caller. */\n    Tk_Window parent,\t\t/* Token for parent of new window. */\n    const char *screenName)\t/* If NULL, new window will be internal on\n\t\t\t\t * same screen as its parent. If non-NULL,\n\t\t\t\t * gives name of screen on which to create new\n\t\t\t\t * window; window will be a top-level\n\t\t\t\t * window. */\n{\n    TkWindow *parentPtr = (TkWindow *) parent;\n\n    if (parentPtr) {\n\tif (parentPtr->flags & TK_ALREADY_DEAD) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't create window: parent has been destroyed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"DEAD_PARENT\", (char *)NULL);\n\t    return NULL;\n\t} else if (parentPtr->flags & TK_CONTAINER) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"can't create window: its parent has -container = yes\",\n\t\t    TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"CONTAINER\", (char *)NULL);\n\t    return NULL;\n\t} else if (screenName == NULL) {\n\t    TkWindow *winPtr = TkAllocWindow(parentPtr->dispPtr,\n\t\t    parentPtr->screenNum, parentPtr);\n\t    /*\n\t     * Add the anonymous window flag now, so that NameWindow will\n\t     * behave correctly.\n\t     */\n\n\t    winPtr->flags |= TK_ANONYMOUS_WINDOW;\n\t    if (NameWindow(interp, winPtr, parentPtr, NULL) != TCL_OK) {\n\t\tTk_DestroyWindow((Tk_Window) winPtr);\n\t\treturn NULL;\n\t    }\n\t    return (Tk_Window) winPtr;\n\t}\n    }\n    return CreateTopLevelWindow(interp, parent, NULL, screenName,\n\t    TK_ANONYMOUS_WINDOW);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CreateWindowFromPath --\n *\n *\tThis function is similar to Tk_CreateWindow except that it uses a path\n *\tname to create the window, rather than a parent and a child name.\n *\n * Results:\n *\tThe return value is a token for the new window. This is not the same\n *\tas X's token for the window. If an error occurred in creating the\n *\twindow (e.g. no such display or screen), then an error message is left\n *\tin the interp's result and NULL is returned.\n *\n * Side effects:\n *\tA new window structure is allocated locally. An X window is not\n *\tinitially created, but will be created the first time the window is\n *\tmapped.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_CreateWindowFromPath(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting.\n\t\t\t\t * the interp's result is assumed to be\n\t\t\t\t * initialized by the caller. */\n    Tk_Window tkwin,\t\t/* Token for any window in application that is\n\t\t\t\t * to contain new window. */\n    const char *pathName,\t/* Path name for new window within the\n\t\t\t\t * application of tkwin. The parent of this\n\t\t\t\t * window must already exist, but the window\n\t\t\t\t * itself must not exist. */\n    const char *screenName)\t/* If NULL, new window will be on same screen\n\t\t\t\t * as its parent. If non-NULL, gives name of\n\t\t\t\t * screen on which to create new window;\n\t\t\t\t * window will be a top-level window. */\n{\n#define FIXED_SPACE 5\n    char fixedSpace[FIXED_SPACE+1];\n    char *p;\n    Tk_Window parent;\n    size_t numChars;\n\n    /*\n     * Strip the parent's name out of pathName (it's everything up to the last\n     * dot). There are two tricky parts: (a) must copy the parent's name\n     * somewhere else to avoid modifying the pathName string (for large names,\n     * space for the copy will have to be malloc'ed); (b) must special-case\n     * the situation where the parent is \".\".\n     */\n\n    p = (char *)strrchr(pathName, '.');\n    if (p == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad window path name \\\"%s\\\"\", pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"WINDOW_PATH\", (char *)NULL);\n\treturn NULL;\n    }\n    numChars = (size_t)(p - pathName);\n    if (numChars > FIXED_SPACE) {\n\tp = (char *)Tcl_Alloc(numChars + 1);\n    } else {\n\tp = fixedSpace;\n    }\n    if (numChars == 0) {\n\t*p = '.';\n\tp[1] = '\\0';\n    } else {\n\tstrncpy(p, pathName, numChars);\n\tp[numChars] = '\\0';\n    }\n\n    /*\n     * Find the parent window.\n     */\n\n    parent = Tk_NameToWindow(interp, p, tkwin);\n    if (p != fixedSpace) {\n\tTcl_Free(p);\n    }\n    if (parent == NULL) {\n\treturn NULL;\n    }\n    if (((TkWindow *) parent)->flags & TK_ALREADY_DEAD) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't create window: parent has been destroyed\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"DEAD_PARENT\", (char *)NULL);\n\treturn NULL;\n    } else if (((TkWindow *) parent)->flags & TK_CONTAINER) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't create window: its parent has -container = yes\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CREATE\", \"CONTAINER\", (char *)NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Create the window.\n     */\n\n    if (screenName == NULL) {\n\tTkWindow *parentPtr = (TkWindow *) parent;\n\tTkWindow *winPtr;\n\n\twinPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum,\n\t\tparentPtr);\n\tif (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)\n\t\t!= TCL_OK) {\n\t    Tk_DestroyWindow((Tk_Window) winPtr);\n\t    return NULL;\n\t}\n\treturn (Tk_Window) winPtr;\n    }\n\n    return CreateTopLevelWindow(interp, parent, pathName+numChars+1,\n\t    screenName, /* flags */ 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_DestroyWindow --\n *\n *\tDestroy an existing window. After this call, the caller should never\n *\tagain use the token. Note that this function can be reentered to\n *\tdestroy a window that was only partially destroyed before a call to\n *\texit.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is deleted, along with all of its children. Relevant\n *\tcallback functions are invoked.\n *\n *--------------------------------------------------------------\n */\n\n#if defined(MAC_OSX_TK) || defined(_WIN32)\nstatic void SendEnterLeaveForDestroy(\n    Tk_Window tkwin)\n{\n    int x, y;\n    unsigned int state;\n    Tk_Window pointerWin;\n    TkWindow *containerPtr;\n\n    if (displayBeingClosed) {\n\treturn;\n    }\n    XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y,\n\t\t  NULL, NULL, &state);\n    pointerWin = Tk_CoordsToWindow(x, y, tkwin);\n    if (pointerWin == tkwin) {\n\tif (!Tk_IsTopLevel(tkwin)) {\n\t    containerPtr = TkGetContainer((TkWindow *)pointerWin);\n\t    Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state);\n\t}\n    }\n\n    if (pointerWin && (tkwin == Tk_Parent(pointerWin))) {\n\tTk_UpdatePointer(Tk_Parent(tkwin), x, y, state);\n    }\n}\n#else\nstatic void SendEnterLeaveForDestroy(\n    TCL_UNUSED(Tk_Window))\n{\n}\n#endif\n\nvoid\nTk_DestroyWindow(\n    Tk_Window tkwin)\t\t/* Window to destroy. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    XEvent event;\n    TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->flags & TK_ALREADY_DEAD) {\n\t/*\n\t * A destroy event binding caused the window to be destroyed again.\n\t * Ignore the request.\n\t */\n\n\treturn;\n    }\n    if ((winPtr->flags & TK_DONT_DESTROY_WINDOW) == 0) {\n\tSendEnterLeaveForDestroy(tkwin);\n    }\n\n    winPtr->flags |= TK_ALREADY_DEAD;\n\n    /*\n     * Unless we are cleaning up a half dead window from\n     * DeleteWindowsExitProc, add this window to the half dead list.\n     */\n\n    if (tsdPtr->halfdeadWindowList &&\n\t    (tsdPtr->halfdeadWindowList->flags & HD_CLEANUP) &&\n\t    (tsdPtr->halfdeadWindowList->winPtr == winPtr)) {\n\thalfdeadPtr = tsdPtr->halfdeadWindowList;\n    } else {\n\thalfdeadPtr = (TkHalfdeadWindow *)Tcl_Alloc(sizeof(TkHalfdeadWindow));\n\thalfdeadPtr->flags = 0;\n\thalfdeadPtr->winPtr = winPtr;\n\thalfdeadPtr->nextPtr = tsdPtr->halfdeadWindowList;\n\ttsdPtr->halfdeadWindowList = halfdeadPtr;\n    }\n\n    /*\n     * Some cleanup needs to be done immediately, rather than later, because\n     * it needs information that will be destroyed before we get to the main\n     * cleanup point. For example, TkFocusDeadWindow needs to access the\n     * parentPtr field from a window, but if a Destroy event handler deletes\n     * the window's parent this field will be NULL before the main cleanup\n     * point is reached.\n     */\n\n    if (!(halfdeadPtr->flags & HD_FOCUS)) {\n\thalfdeadPtr->flags |= HD_FOCUS;\n\tTkFocusDeadWindow(winPtr);\n    }\n\n    /*\n     * If this is a main window, remove it from the list of main windows.\n     * This needs to be done now (rather than later with all the other main\n     * window cleanup) to handle situations where a destroy binding for a\n     * window calls \"exit\". In this case the child window cleanup isn't\n     * complete when exit is called. This situation is dealt with using the\n     * half dead window list. Windows that are half dead gets cleaned up\n     * during exit.\n     *\n     * Also decrement the display refcount so that if this is the last Tk\n     * application in this process on this display, the display can be closed\n     * and its data structures deleted.\n     */\n\n    if (!(halfdeadPtr->flags & HD_MAIN_WIN) &&\n\t    winPtr->mainPtr != NULL && winPtr->mainPtr->winPtr == winPtr) {\n\thalfdeadPtr->flags |= HD_MAIN_WIN;\n\tdispPtr->refCount--;\n\tif (tsdPtr->mainWindowList == winPtr->mainPtr) {\n\t    tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr;\n\t} else {\n\t    TkMainInfo *prevPtr;\n\n\t    for (prevPtr = tsdPtr->mainWindowList;\n\t\t    prevPtr->nextPtr != winPtr->mainPtr;\n\t\t    prevPtr = prevPtr->nextPtr) {\n\t\t/* Empty loop body. */\n\t    }\n\t    prevPtr->nextPtr = winPtr->mainPtr->nextPtr;\n\t}\n\ttsdPtr->numMainWindows--;\n    }\n\n    /*\n     * Recursively destroy children. Note that this child window block may\n     * need to be run multiple times in the case where a child window has a\n     * Destroy binding that calls exit.\n     */\n\n    if (!(halfdeadPtr->flags & HD_DESTROY_COUNT)) {\n\thalfdeadPtr->flags |= HD_DESTROY_COUNT;\n    }\n\n    while (winPtr->childList != NULL) {\n\tTkWindow *childPtr = winPtr->childList;\n\n\tchildPtr->flags |= TK_DONT_DESTROY_WINDOW;\n\tTk_DestroyWindow((Tk_Window) childPtr);\n\tif (winPtr->childList == childPtr) {\n\t    /*\n\t     * The child didn't remove itself from the child list, so let's\n\t     * remove it here. This can happen in some strange conditions,\n\t     * such as when a Destroy event handler for a window destroys the\n\t     * window's parent.\n\t     */\n\n\t    winPtr->childList = childPtr->nextPtr;\n\t    childPtr->parentPtr = NULL;\n\t}\n    }\n    if ((winPtr->flags & (TK_CONTAINER|TK_BOTH_HALVES))\n\t    == (TK_CONTAINER|TK_BOTH_HALVES)) {\n\t/*\n\t * This is the container for an embedded application, and the embedded\n\t * application is also in this process. Delete the embedded window\n\t * in-line here, for the same reasons we delete children in-line\n\t * (otherwise, for example, the Tk window may appear to exist even\n\t * though its X window is gone; this could cause errors). Special\n\t * note: it's possible that the embedded window has already been\n\t * deleted, in which case Tk_GetOtherWindow will return NULL.\n\t */\n\n\tTkWindow *childPtr = (TkWindow *)Tk_GetOtherWindow(tkwin);\n\n\tif (childPtr != NULL) {\n\t    childPtr->flags |= TK_DONT_DESTROY_WINDOW;\n\t    Tk_DestroyWindow((Tk_Window) childPtr);\n\t}\n    }\n\n    /*\n     * Generate a DestroyNotify event. In order for the DestroyNotify event to\n     * be processed correctly, need to make sure the window exists. This is a\n     * bit of a kludge, and may be unnecessarily expensive, but without it no\n     * event handlers will get called for windows that don't exist yet.\n     *\n     * Note: if the window's pathName is NULL and the window is not an\n     * anonymous window, it means that the window was not successfully\n     * initialized in the first place, so we should not make the window exist\n     * or generate the event.\n     */\n\n    if (!(halfdeadPtr->flags & HD_DESTROY_EVENT) &&\n\t    winPtr->pathName != NULL &&\n\t    !(winPtr->flags & TK_ANONYMOUS_WINDOW)) {\n\thalfdeadPtr->flags |= HD_DESTROY_EVENT;\n\tif (winPtr->window == None) {\n\t    Tk_MakeWindowExist(tkwin);\n\t}\n\tevent.type = DestroyNotify;\n\tevent.xdestroywindow.serial =\n\t\tLastKnownRequestProcessed(winPtr->display);\n\tevent.xdestroywindow.send_event = False;\n\tevent.xdestroywindow.display = winPtr->display;\n\tevent.xdestroywindow.event = winPtr->window;\n\tevent.xdestroywindow.window = winPtr->window;\n\tTk_HandleEvent(&event);\n    }\n\n    /*\n     * No additional bindings that could call exit should be invoked from this\n     * point on, so it is safe to remove this window from the half dead list.\n     */\n\n    for (prev_halfdeadPtr = NULL,\n\t    halfdeadPtr = tsdPtr->halfdeadWindowList;\n\t    halfdeadPtr != NULL; ) {\n\tif (halfdeadPtr->winPtr == winPtr) {\n\t    if (prev_halfdeadPtr == NULL) {\n\t\ttsdPtr->halfdeadWindowList = halfdeadPtr->nextPtr;\n\t    } else {\n\t\tprev_halfdeadPtr->nextPtr = halfdeadPtr->nextPtr;\n\t    }\n\t    Tcl_Free(halfdeadPtr);\n\t    break;\n\t}\n\tprev_halfdeadPtr = halfdeadPtr;\n\thalfdeadPtr = halfdeadPtr->nextPtr;\n    }\n    if (halfdeadPtr == NULL) {\n\tTcl_Panic(\"window not found on half dead list\");\n    }\n\n    /*\n     * Cleanup the data structures associated with this window.\n     */\n\n    if (winPtr->wmInfoPtr && (winPtr->flags & TK_WIN_MANAGED)) {\n\tTkWmDeadWindow(winPtr);\n    } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {\n\tTkWmRemoveFromColormapWindows(winPtr);\n    }\n    if (winPtr->window != None) {\n#if defined(MAC_OSX_TK) || defined(_WIN32)\n\tXDestroyWindow(winPtr->display, winPtr->window);\n#else\n\tif ((winPtr->flags & TK_TOP_HIERARCHY)\n\t\t|| !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {\n\t    /*\n\t     * The parent has already been destroyed and this isn't a\n\t     * top-level window, so this window will be destroyed implicitly\n\t     * when the parent's X window is destroyed; it's much faster not\n\t     * to do an explicit destroy of this X window.\n\t     */\n\n\t    XDestroyWindow(winPtr->display, winPtr->window);\n\t}\n#endif\n\tTcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable,\n\t\twinPtr->window));\n\twinPtr->window = None;\n    }\n    UnlinkWindow(winPtr);\n    TkEventDeadWindow(winPtr);\n    if (winPtr->inputContext != NULL &&\n\twinPtr->ximGeneration == winPtr->dispPtr->ximGeneration) {\n\tXDestroyIC(winPtr->inputContext);\n    }\n    winPtr->inputContext = NULL;\n    if (winPtr->tagPtr != NULL) {\n\tTkFreeBindingTags(winPtr);\n    }\n    TkOptionDeadWindow(winPtr);\n    TkSelDeadWindow(winPtr);\n    TkGrabDeadWindow(winPtr);\n    if (winPtr->geomMgrName != NULL) {\n\tTcl_Free(winPtr->geomMgrName);\n\twinPtr->geomMgrName = NULL;\n    }\n    if (winPtr->mainPtr != NULL) {\n\tif (winPtr->pathName != NULL) {\n\t    Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,\n\t\t    winPtr->pathName);\n\t    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,\n\t\t    winPtr->pathName));\n\n\t    /*\n\t     * The memory pointed to by pathName has been deallocated. Keep\n\t     * users from accessing it after the window has been destroyed by\n\t     * setting it to NULL.\n\t     */\n\n\t    winPtr->pathName = NULL;\n\n\t    /*\n\t     * Invalidate all objects referring to windows with the same main\n\t     * window.\n\t     */\n\n\t    winPtr->mainPtr->deletionEpoch++;\n\t}\n\tif (winPtr->mainPtr->refCount-- <= 1) {\n\t    const TkCmd *cmdPtr;\n\n\t    /*\n\t     * We just deleted the last window in the application. Delete the\n\t     * TkMainInfo structure too and replace all of Tk's commands with\n\t     * dummy commands that return errors. Also delete the \"send\"\n\t     * command to unregister the interpreter.\n\t     *\n\t     * NOTE: Only replace the commands it if the interpreter is not\n\t     * being deleted. If it *is*, the interpreter cleanup will do all\n\t     * the needed work.\n\t     */\n\n\t    if ((winPtr->mainPtr->interp != NULL) &&\n\t\t!Tcl_InterpDeleted(winPtr->mainPtr->interp)) {\n\t\tfor (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {\n\t\t    if (cmdPtr->flags & SAVEUPDATECMD) {\n\t\t\t/* Restore Tcl's version of [update] */\n\t\t\tif (winPtr->mainPtr->tclUpdateObjProc2 != NULL) {\n\t\t\t    Tcl_CreateObjCommand2(winPtr->mainPtr->interp,\n\t\t\t\t    cmdPtr->name,\n\t\t\t\t    winPtr->mainPtr->tclUpdateObjProc2,\n\t\t\t\t    NULL, NULL);\n#ifndef TCL_NO_DEPRECATED\n\t\t\t} else if (winPtr->mainPtr->tclUpdateObjProc != NULL) {\n\t\t\t    Tcl_CreateObjCommand(winPtr->mainPtr->interp,\n\t\t\t\t    cmdPtr->name,\n\t\t\t\t    (Tcl_ObjCmdProc *)winPtr->mainPtr->tclUpdateObjProc,\n\t\t\t\t    NULL, NULL);\n#endif /* TCL_NO_DEPRECATED */\n\t\t\t}\n\t\t    } else {\n\t\t\tTcl_CreateObjCommand2(winPtr->mainPtr->interp,\n\t\t\t\t\t     cmdPtr->name, TkDeadAppObjCmd,\n\t\t\t\t\t     NULL, NULL);\n\t\t    }\n\t\t}\n\t\tTcl_CreateObjCommand2(winPtr->mainPtr->interp, \"send\",\n\t\t\tTkDeadAppObjCmd, NULL, NULL);\n\t\tTcl_UnlinkVar(winPtr->mainPtr->interp, \"tk_strictMotif\");\n\t\tTcl_UnlinkVar(winPtr->mainPtr->interp,\n\t\t\t\"::tk::AlwaysShowSelection\");\n\t    }\n\n\t    Tcl_DeleteHashTable(&winPtr->mainPtr->busyTable);\n\t    Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);\n\t    TkBindFree(winPtr->mainPtr);\n\t    TkDeleteAllImages(winPtr->mainPtr);\n\t    TkFontPkgFree(winPtr->mainPtr);\n\t    TkFocusFree(winPtr->mainPtr);\n\t    TkStylePkgFree(winPtr->mainPtr);\n\t    Ttk_TkDestroyedHandler(winPtr->mainPtr->interp);\n\n\t    /*\n\t     * When embedding Tk into other applications, make sure that all\n\t     * destroy events reach the server. Otherwise the embedding\n\t     * application may also attempt to destroy the windows, resulting\n\t     * in an X error\n\t     */\n\n\t    if (winPtr->flags & TK_EMBEDDED) {\n\t\tXSync(winPtr->display, False);\n\t    }\n\t    Tcl_Free(winPtr->mainPtr);\n\n\t    /*\n\t     * If no other applications are using the display, close the\n\t     * display now and relinquish its data structures.\n\t     */\n\n#if !defined(_WIN32) && defined(NOT_YET)\n\t    if (dispPtr->refCount <= 0) {\n\t\t/*\n\t\t * I have disabled this code because on Windows there are\n\t\t * still order dependencies in close-down. All displays and\n\t\t * resources will get closed down properly anyway at exit,\n\t\t * through the exit handler. -- jyl\n\t\t *\n\t\t * Ideally this should be enabled, as unix Tk can use multiple\n\t\t * displays. However, there are order issues still, as well as\n\t\t * the handling of queued events and such that must be\n\t\t * addressed before this can be enabled. The current cleanup\n\t\t * works except for send event issues. -- hobbs 04/2002\n\t\t */\n\n\t\tTkDisplay *theDispPtr, *backDispPtr;\n\n\t\t/*\n\t\t * Splice this display out of the list of displays.\n\t\t */\n\n\t\tfor (theDispPtr = tsdPtr->displayList, backDispPtr = NULL;\n\t\t\t(theDispPtr!=winPtr->dispPtr) && (theDispPtr!=NULL);\n\t\t\ttheDispPtr = theDispPtr->nextPtr) {\n\t\t    backDispPtr = theDispPtr;\n\t\t}\n\t\tif (theDispPtr == NULL) {\n\t\t    Tcl_Panic(\"could not find display to close!\");\n\t\t}\n\t\tif (backDispPtr == NULL) {\n\t\t    tsdPtr->displayList = theDispPtr->nextPtr;\n\t\t} else {\n\t\t    backDispPtr->nextPtr = theDispPtr->nextPtr;\n\t\t}\n\n\t\t/*\n\t\t * Calling XSync creates X server traffic, but addresses a\n\t\t * focus issue on close (but not the send issue). -- hobbs\n\t\t *\n\t\t *\tXSync(dispPtr->display, True);\n\t\t */\n\n\t\t/*\n\t\t * Found and spliced it out, now actually do the cleanup.\n\t\t */\n\n\t\tTkCloseDisplay(dispPtr);\n\t    }\n#endif /* !_WIN32 && NOT_YET */\n\t}\n    }\n    Tcl_EventuallyFree(winPtr, TCL_DYNAMIC);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_MapWindow --\n *\n *\tMap a window within its parent. This may require the window and/or its\n *\tparents to actually be created.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe given window will be mapped. Windows may also be created.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_MapWindow(\n    Tk_Window tkwin)\t\t/* Token for window to map. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    XEvent event;\n\n    if (winPtr->flags & TK_MAPPED) {\n\treturn;\n    }\n    if (winPtr->window == None) {\n\tTk_MakeWindowExist(tkwin);\n    }\n    /*\n     * [Bug 2645457]: the previous call permits events to be processed and can\n     * lead to the destruction of the window under some conditions.\n     */\n    if (winPtr->flags & TK_ALREADY_DEAD) {\n\treturn;\n    }\n    if (winPtr->flags & TK_WIN_MANAGED) {\n\t/*\n\t * Lots of special processing has to be done for top-level windows.\n\t * Let tkWm.c handle everything itself.\n\t */\n\n\tTkWmMapWindow(winPtr);\n\treturn;\n    }\n    winPtr->flags |= TK_MAPPED;\n    XMapWindow(winPtr->display, winPtr->window);\n    event.type = MapNotify;\n    event.xmap.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xmap.send_event = False;\n    event.xmap.display = winPtr->display;\n    event.xmap.event = winPtr->window;\n    event.xmap.window = winPtr->window;\n    event.xmap.override_redirect = winPtr->atts.override_redirect;\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_MakeWindowExist --\n *\n *\tEnsure that a particular window actually exists. This function should\n *\tnot normally need to be invoked from outside the Tk package, but may\n *\tbe needed if someone wants to manipulate a window before mapping it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the function returns, the X window associated with tkwin is\n *\tguaranteed to exist. This may require the window's ancestors to be\n *\tcreated also.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_MakeWindowExist(\n    Tk_Window tkwin)\t\t/* Token for window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *winPtr2;\n    Window parent;\n    Tcl_HashEntry *hPtr;\n    Tk_ClassCreateProc *createProc;\n    int isNew;\n\n    if (winPtr->window != None) {\n\treturn;\n    }\n\n    if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_HIERARCHY)) {\n\tparent = XRootWindow(winPtr->display, winPtr->screenNum);\n    } else {\n\tif (winPtr->parentPtr->window == None) {\n\t    Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);\n\t}\n\tparent = winPtr->parentPtr->window;\n    }\n\n    createProc = Tk_GetClassProc(winPtr->classProcsPtr, createProc);\n    if (createProc != NULL && parent != None) {\n\twinPtr->window = createProc(tkwin, parent, winPtr->instanceData);\n    } else {\n\twinPtr->window = Tk_MakeWindow(tkwin, parent);\n    }\n\n    hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,\n\t    (char *) winPtr->window, &isNew);\n    Tcl_SetHashValue(hPtr, winPtr);\n    winPtr->dirtyAtts = 0;\n    winPtr->dirtyChanges = 0;\n\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\t/*\n\t * If any siblings higher up in the stacking order have already been\n\t * created then move this window to its rightful position in the\n\t * stacking order.\n\t *\n\t * NOTE: this code ignores any changes anyone might have made to the\n\t * sibling and stack_mode field of the window's attributes, so it\n\t * really isn't safe for these to be manipulated except by calling\n\t * Tk_RestackWindow.\n\t */\n\n\tfor (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;\n\t\twinPtr2 = winPtr2->nextPtr) {\n\t    if ((winPtr2->window != None)\n\t\t    && !(winPtr2->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))) {\n\t\tXWindowChanges changes;\n\n\t\tchanges.sibling = winPtr2->window;\n\t\tchanges.stack_mode = Below;\n\t\tXConfigureWindow(winPtr->display, winPtr->window,\n\t\t\tCWSibling|CWStackMode, &changes);\n\t\tbreak;\n\t    }\n\t}\n\n\t/*\n\t * If this window has a different colormap than its parent, add the\n\t * window to the WM_COLORMAP_WINDOWS property for its top-level.\n\t */\n\n\tif ((winPtr->parentPtr != NULL) &&\n\t\t(winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) {\n\t    TkWmAddToColormapWindows(winPtr);\n\t    winPtr->flags |= TK_WM_COLORMAP_WINDOW;\n\t}\n    }\n\n    /*\n     * Issue a ConfigureNotify event if there were deferred configuration\n     * changes (but skip it if the window is being deleted; the\n     * ConfigureNotify event could cause problems if we're being called from\n     * Tk_DestroyWindow under some conditions).\n     */\n\n    if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)\n\t    && !(winPtr->flags & TK_ALREADY_DEAD)) {\n\twinPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;\n\tTkDoConfigureNotify(winPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_UnmapWindow, etc. --\n *\n *\tThere are several functions under here, each of which mirrors an\n *\texisting X function. In addition to performing the functions of the\n *\tcorresponding function, each function also updates the local window\n *\tstructure and synthesizes an X event (if the window's structure is\n *\tbeing managed internally).\n *\n * Results:\n *\tSee the manual entries.\n *\n * Side effects:\n *\tSee the manual entries.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_UnmapWindow(\n    Tk_Window tkwin)\t\t/* Token for window to unmap. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (!(winPtr->flags & TK_MAPPED) || (winPtr->flags & TK_ALREADY_DEAD)) {\n\treturn;\n    }\n    if (winPtr->flags & TK_WIN_MANAGED) {\n\t/*\n\t * Special processing has to be done for top-level windows. Let tkWm.c\n\t * handle everything itself.\n\t */\n\n\tTkWmUnmapWindow(winPtr);\n\treturn;\n    }\n    winPtr->flags &= ~TK_MAPPED;\n    XUnmapWindow(winPtr->display, winPtr->window);\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\tXEvent event;\n\n\tevent.type = UnmapNotify;\n\tevent.xunmap.serial = LastKnownRequestProcessed(winPtr->display);\n\tevent.xunmap.send_event = False;\n\tevent.xunmap.display = winPtr->display;\n\tevent.xunmap.event = winPtr->window;\n\tevent.xunmap.window = winPtr->window;\n\tevent.xunmap.from_configure = False;\n\tTk_HandleEvent(&event);\n    }\n}\n\nvoid\nTk_ConfigureWindow(\n    Tk_Window tkwin,\t\t/* Window to re-configure. */\n    unsigned int valueMask,\t/* Mask indicating which parts of *valuePtr\n\t\t\t\t * are to be used. */\n    XWindowChanges *valuePtr)\t/* New values. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (valueMask & CWX) {\n\twinPtr->changes.x = valuePtr->x;\n    }\n    if (valueMask & CWY) {\n\twinPtr->changes.y = valuePtr->y;\n    }\n    if (valueMask & CWWidth) {\n\twinPtr->changes.width = valuePtr->width;\n    }\n    if (valueMask & CWHeight) {\n\twinPtr->changes.height = valuePtr->height;\n    }\n    if (valueMask & CWBorderWidth) {\n\twinPtr->changes.border_width = valuePtr->border_width;\n    }\n    if (valueMask & (CWSibling|CWStackMode)) {\n\tTcl_Panic(\"Can't set sibling or stack mode from Tk_ConfigureWindow\");\n    }\n\n    if (winPtr->window != None) {\n\tXConfigureWindow(winPtr->display, winPtr->window,\n\t\tvalueMask, valuePtr);\n\tTkDoConfigureNotify(winPtr);\n    } else {\n\twinPtr->dirtyChanges |= valueMask;\n\twinPtr->flags |= TK_NEED_CONFIG_NOTIFY;\n    }\n}\n\nvoid\nTk_MoveWindow(\n    Tk_Window tkwin,\t\t/* Window to move. */\n    int x, int y)\t\t/* New location for window (within parent). */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->changes.x = x;\n    winPtr->changes.y = y;\n    if (winPtr->window != None) {\n\tXMoveWindow(winPtr->display, winPtr->window, x, y);\n\tTkDoConfigureNotify(winPtr);\n    } else {\n\twinPtr->dirtyChanges |= CWX|CWY;\n\twinPtr->flags |= TK_NEED_CONFIG_NOTIFY;\n    }\n}\n\nvoid\nTk_ResizeWindow(\n    Tk_Window tkwin,\t\t/* Window to resize. */\n    int width, int height)\t/* New dimensions for window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->changes.width = width;\n    winPtr->changes.height = height;\n    if (winPtr->window != None) {\n\tXResizeWindow(winPtr->display, winPtr->window, (unsigned) width,\n\t\t(unsigned) height);\n\tTkDoConfigureNotify(winPtr);\n    } else {\n\twinPtr->dirtyChanges |= CWWidth|CWHeight;\n\twinPtr->flags |= TK_NEED_CONFIG_NOTIFY;\n    }\n}\n\nvoid\nTk_MoveResizeWindow(\n    Tk_Window tkwin,\t\t/* Window to move and resize. */\n    int x, int y,\t\t/* New location for window (within parent). */\n    int width, int height)\t/* New dimensions for window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->changes.x = x;\n    winPtr->changes.y = y;\n    winPtr->changes.width = width;\n    winPtr->changes.height = height;\n    if (winPtr->window != None) {\n\tXMoveResizeWindow(winPtr->display, winPtr->window, x, y,\n\t\t(unsigned) width, (unsigned) height);\n\tTkDoConfigureNotify(winPtr);\n    } else {\n\twinPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;\n\twinPtr->flags |= TK_NEED_CONFIG_NOTIFY;\n    }\n}\n\nvoid\nTk_SetWindowBorderWidth(\n    Tk_Window tkwin,\t\t/* Window to modify. */\n    int width)\t\t\t/* New border width for window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->changes.border_width = width;\n    if (winPtr->window != None) {\n\tXSetWindowBorderWidth(winPtr->display, winPtr->window,\n\t\t(unsigned) width);\n\tTkDoConfigureNotify(winPtr);\n    } else {\n\twinPtr->dirtyChanges |= CWBorderWidth;\n\twinPtr->flags |= TK_NEED_CONFIG_NOTIFY;\n    }\n}\n\nvoid\nTk_ChangeWindowAttributes(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    unsigned long valueMask,\t/* OR'ed combination of bits, indicating which\n\t\t\t\t * fields of *attsPtr are to be used. */\n    XSetWindowAttributes *attsPtr)\n\t\t\t\t/* New values for some attributes. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (valueMask & CWBackPixmap) {\n\twinPtr->atts.background_pixmap = attsPtr->background_pixmap;\n    }\n    if (valueMask & CWBackPixel) {\n\twinPtr->atts.background_pixel = attsPtr->background_pixel;\n    }\n    if (valueMask & CWBorderPixmap) {\n\twinPtr->atts.border_pixmap = attsPtr->border_pixmap;\n    }\n    if (valueMask & CWBorderPixel) {\n\twinPtr->atts.border_pixel = attsPtr->border_pixel;\n    }\n    if (valueMask & CWBitGravity) {\n\twinPtr->atts.bit_gravity = attsPtr->bit_gravity;\n    }\n    if (valueMask & CWWinGravity) {\n\twinPtr->atts.win_gravity = attsPtr->win_gravity;\n    }\n    if (valueMask & CWBackingStore) {\n\twinPtr->atts.backing_store = attsPtr->backing_store;\n    }\n    if (valueMask & CWBackingPlanes) {\n\twinPtr->atts.backing_planes = attsPtr->backing_planes;\n    }\n    if (valueMask & CWBackingPixel) {\n\twinPtr->atts.backing_pixel = attsPtr->backing_pixel;\n    }\n    if (valueMask & CWOverrideRedirect) {\n\twinPtr->atts.override_redirect = attsPtr->override_redirect;\n    }\n    if (valueMask & CWSaveUnder) {\n\twinPtr->atts.save_under = attsPtr->save_under;\n    }\n    if (valueMask & CWEventMask) {\n\twinPtr->atts.event_mask = attsPtr->event_mask;\n    }\n    if (valueMask & CWDontPropagate) {\n\twinPtr->atts.do_not_propagate_mask\n\t\t= attsPtr->do_not_propagate_mask;\n    }\n    if (valueMask & CWColormap) {\n\twinPtr->atts.colormap = attsPtr->colormap;\n    }\n    if (valueMask & CWCursor) {\n\twinPtr->atts.cursor = attsPtr->cursor;\n    }\n\n    if (winPtr->window != None) {\n\tXChangeWindowAttributes(winPtr->display, winPtr->window,\n\t\tvalueMask, attsPtr);\n    } else {\n\twinPtr->dirtyAtts |= valueMask;\n    }\n}\n\nvoid\nTk_SetWindowBackground(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    unsigned long pixel)\t/* Pixel value to use for window's\n\t\t\t\t * background. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.background_pixel = pixel;\n\n    if (winPtr->window != None) {\n\tXSetWindowBackground(winPtr->display, winPtr->window, pixel);\n    } else {\n\twinPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixmap)\n\t\t| CWBackPixel;\n    }\n}\n\nvoid\nTk_SetWindowBackgroundPixmap(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    Pixmap pixmap)\t\t/* Pixmap to use for window's background. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.background_pixmap = pixmap;\n\n    if (winPtr->window != None) {\n\tXSetWindowBackgroundPixmap(winPtr->display,\n\t\twinPtr->window, pixmap);\n    } else {\n\twinPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixel)\n\t\t| CWBackPixmap;\n    }\n}\n\nvoid\nTk_SetWindowBorder(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    unsigned long pixel)\t/* Pixel value to use for window's border. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.border_pixel = pixel;\n\n    if (winPtr->window != None) {\n\tXSetWindowBorder(winPtr->display, winPtr->window, pixel);\n    } else {\n\twinPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixmap)\n\t\t| CWBorderPixel;\n    }\n}\n\nvoid\nTk_SetWindowBorderPixmap(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    Pixmap pixmap)\t\t/* Pixmap to use for window's border. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.border_pixmap = pixmap;\n\n    if (winPtr->window != None) {\n\tXSetWindowBorderPixmap(winPtr->display,\n\t\twinPtr->window, pixmap);\n    } else {\n\twinPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixel)\n\t\t| CWBorderPixmap;\n    }\n}\n\nvoid\nTk_DefineCursor(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    Tk_Cursor cursor)\t\t/* Cursor to use for window (may be None). */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.cursor = (Cursor) cursor;\n\n    if (winPtr->window != None) {\n\tXDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor);\n    } else {\n\twinPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;\n    }\n}\n\nvoid\nTk_UndefineCursor(\n    Tk_Window tkwin)\t\t/* Window to manipulate. */\n{\n    Tk_DefineCursor(tkwin, NULL);\n}\n\nvoid\nTk_SetWindowColormap(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    Colormap colormap)\t\t/* Colormap to use for window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->atts.colormap = colormap;\n\n    if (winPtr->window != None) {\n\tXSetWindowColormap(winPtr->display, winPtr->window, colormap);\n\tif (!(winPtr->flags & TK_WIN_MANAGED)) {\n\t    TkWmAddToColormapWindows(winPtr);\n\t    winPtr->flags |= TK_WM_COLORMAP_WINDOW;\n\t}\n    } else {\n\twinPtr->dirtyAtts |= CWColormap;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetWindowVisual --\n *\n *\tThis function is called to specify a visual to be used for a Tk window\n *\twhen it is created. This function, if called at all, must be called\n *\tbefore the X window is created (i.e. before Tk_MakeWindowExist is\n *\tcalled).\n *\n * Results:\n *\tThe return value is 1 if successful, or 0 if the X window has been\n *\talready created.\n *\n * Side effects:\n *\tThe information given is stored for when the window is created.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SetWindowVisual(\n    Tk_Window tkwin,\t\t/* Window to manipulate. */\n    Visual *visual,\t\t/* New visual for window. */\n    int depth,\t\t\t/* New depth for window. */\n    Colormap colormap)\t\t/* An appropriate colormap for the visual. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (winPtr->window != None) {\n\t/* Too late! */\n\treturn 0;\n    }\n\n    winPtr->visual = visual;\n    winPtr->depth = depth;\n    winPtr->atts.colormap = colormap;\n    winPtr->dirtyAtts |= CWColormap;\n\n    /*\n     * The following code is needed to make sure that the window doesn't\n     * inherit the parent's border pixmap, which would result in a BadMatch\n     * error.\n     */\n\n    if (!(winPtr->dirtyAtts & CWBorderPixmap)) {\n\twinPtr->dirtyAtts |= CWBorderPixel;\n    }\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkDoConfigureNotify --\n *\n *\tGenerate a ConfigureNotify event describing the current configuration\n *\tof a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn event is generated and processed by Tk_HandleEvent.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkDoConfigureNotify(\n    TkWindow *winPtr)\t/* Window whose configuration was just\n\t\t\t\t * changed. */\n{\n    XEvent event;\n\n    event.type = ConfigureNotify;\n    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xconfigure.send_event = False;\n    event.xconfigure.display = winPtr->display;\n    event.xconfigure.event = winPtr->window;\n    event.xconfigure.window = winPtr->window;\n    event.xconfigure.x = winPtr->changes.x;\n    event.xconfigure.y = winPtr->changes.y;\n    event.xconfigure.width = winPtr->changes.width;\n    event.xconfigure.height = winPtr->changes.height;\n    event.xconfigure.border_width = winPtr->changes.border_width;\n    if (winPtr->changes.stack_mode == Above) {\n\tevent.xconfigure.above = winPtr->changes.sibling;\n    } else {\n\tevent.xconfigure.above = None;\n    }\n    event.xconfigure.override_redirect = winPtr->atts.override_redirect;\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetClass --\n *\n *\tThis function is used to give a window a class.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new class is stored for tkwin, replacing any existing class for it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetClass(\n    Tk_Window tkwin,\t\t/* Token for window to assign class. */\n    const char *className)\t/* New class for tkwin. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->classUid = Tk_GetUid(className);\n    if (winPtr->flags & TK_WIN_MANAGED) {\n\tTkWmSetClass(winPtr);\n    }\n    TkOptionClassChanged(winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetClassProcs --\n *\n *\tThis function is used to set the class functions and instance data for\n *\ta window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new set of class functions and instance data is stored for tkwin,\n *\treplacing any existing values.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetClassProcs(\n    Tk_Window tkwin,\t\t/* Token for window to modify. */\n    const Tk_ClassProcs *procs,\t/* Class procs structure. */\n    void *instanceData)\t/* Data to be passed to class functions. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    winPtr->classProcsPtr = procs;\n    winPtr->instanceData = instanceData;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_NameToWindow --\n *\n *\tGiven a string name for a window, this function returns the token for\n *\tthe window, if there exists a window corresponding to the given name.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\t\"name\", or else NULL to indicate that there is no such window. In this\n *\tcase, an error message is left in the interp's result, unless interp\n *      is NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_NameToWindow(\n    Tcl_Interp *interp,\t\t/* Where to report errors. */\n    const char *pathName,\t/* Path name of window. */\n    Tk_Window tkwin)\t\t/* Token for window: name is assumed to belong\n\t\t\t\t * to the same main window as tkwin. */\n{\n    Tcl_HashEntry *hPtr;\n\n    if (tkwin == NULL) {\n\t/*\n\t * Either we're not really in Tk, or the main window was destroyed and\n\t * we're on our way out of the application.\n\t */\n\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"NULL main window\",TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"NO_MAIN_WINDOW\", (char *)NULL);\n\t}\n\treturn NULL;\n    }\n\n    hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,\n\t    pathName);\n    if (hPtr == NULL) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad window path name \\\"%s\\\"\", pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"WINDOW\", pathName,\n\t\t    (char *)NULL);\n\t}\n\treturn NULL;\n    }\n    return (Tk_Window)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_IdToWindow --\n *\n *\tGiven an X display and window ID, this function returns the Tk token\n *\tfor the window, if there exists a Tk window corresponding to the given\n *\tID.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\tthe given X id, or else NULL to indicate that there is no such window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_IdToWindow(\n    Display *display,\t\t/* X display containing the window. */\n    Window window)\t\t/* X window window id. */\n{\n    TkDisplay *dispPtr;\n    Tcl_HashEntry *hPtr;\n\n    for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {\n\tif (dispPtr == NULL) {\n\t    return NULL;\n\t}\n\tif (dispPtr->display == display) {\n\t    break;\n\t}\n    }\n    if (window == None) {\n\treturn NULL;\n    }\n\n    hPtr = Tcl_FindHashEntry(&dispPtr->winTable, window);\n    if (hPtr == NULL) {\n\treturn NULL;\n    }\n    return (Tk_Window)Tcl_GetHashValue(hPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DisplayName --\n *\n *\tReturn the textual name of a window's display.\n *\n * Results:\n *\tThe return value is the string name of the display associated with\n *\ttkwin.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTk_DisplayName(\n    Tk_Window tkwin)\t\t/* Window whose display name is desired. */\n{\n    return ((TkWindow *) tkwin)->dispPtr->name;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Interp --\n *\n *\tGet the Tcl interpreter from a Tk window.\n *\n * Results:\n *\tA pointer to the interpreter or NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Interp *\nTk_Interp(\n    Tk_Window tkwin)\n{\n    if (tkwin != NULL && ((TkWindow *) tkwin)->mainPtr != NULL) {\n\treturn ((TkWindow *) tkwin)->mainPtr->interp;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UnlinkWindow --\n *\n *\tThis function removes a window from the childList of its parent.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is unlinked from its childList.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUnlinkWindow(\n    TkWindow *winPtr)\t\t/* Child window to be unlinked. */\n{\n    TkWindow *prevPtr;\n\n    if (winPtr->parentPtr == NULL) {\n\treturn;\n    }\n    prevPtr = winPtr->parentPtr->childList;\n    if (prevPtr == winPtr) {\n\twinPtr->parentPtr->childList = winPtr->nextPtr;\n\tif (winPtr->nextPtr == NULL) {\n\t    winPtr->parentPtr->lastChildPtr = NULL;\n\t}\n    } else {\n\twhile (prevPtr->nextPtr != winPtr) {\n\t    prevPtr = prevPtr->nextPtr;\n\t    if (prevPtr == NULL) {\n\t\tTcl_Panic(\"UnlinkWindow couldn't find child in parent\");\n\t    }\n\t}\n\tprevPtr->nextPtr = winPtr->nextPtr;\n\tif (winPtr->nextPtr == NULL) {\n\t    winPtr->parentPtr->lastChildPtr = prevPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_RestackWindow --\n *\n *\tChange a window's position in the stacking order.\n *\n * Results:\n *\tTCL_OK is normally returned. If other is not a descendant of tkwin's\n *\tparent then TCL_ERROR is returned and tkwin is not repositioned.\n *\n * Side effects:\n *\tTkwin is repositioned in the stacking order.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_RestackWindow(\n    Tk_Window tkwin,\t\t/* Token for window whose position in the\n\t\t\t\t * stacking order is to change. */\n    int aboveBelow,\t\t/* Indicates new position of tkwin relative to\n\t\t\t\t * other; must be Above or Below. */\n    Tk_Window other)\t\t/* Tkwin will be moved to a position that puts\n\t\t\t\t * it just above or below this window. If NULL\n\t\t\t\t * then tkwin goes above or below all windows\n\t\t\t\t * in the same parent. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *otherPtr = (TkWindow *) other;\n\n    /*\n     * Special case: if winPtr is a toplevel window then just find the\n     * top-level ancestor of otherPtr and restack winPtr above otherPtr\n     * without changing any of Tk's childLists.\n     */\n\n    if (winPtr->flags & TK_WIN_MANAGED) {\n\twhile ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_HIERARCHY)) {\n\t    otherPtr = otherPtr->parentPtr;\n\t}\n\tTkWmRestackToplevel(winPtr, aboveBelow, otherPtr);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Find an ancestor of otherPtr that is a sibling of winPtr.\n     */\n\n    if (winPtr->parentPtr == NULL) {\n\t/*\n\t * Window is going to be deleted shortly; don't do anything.\n\t */\n\n\treturn TCL_OK;\n    }\n    if (otherPtr == NULL) {\n\tif (aboveBelow == Above) {\n\t    otherPtr = winPtr->parentPtr->lastChildPtr;\n\t} else {\n\t    otherPtr = winPtr->parentPtr->childList;\n\t}\n    } else {\n\twhile (winPtr->parentPtr != otherPtr->parentPtr) {\n\t    if ((otherPtr == NULL) || (otherPtr->flags & TK_TOP_HIERARCHY)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    otherPtr = otherPtr->parentPtr;\n\t}\n    }\n    if (otherPtr == winPtr) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Reposition winPtr in the stacking order.\n     */\n\n    UnlinkWindow(winPtr);\n    if (aboveBelow == Above) {\n\twinPtr->nextPtr = otherPtr->nextPtr;\n\tif (winPtr->nextPtr == NULL) {\n\t    winPtr->parentPtr->lastChildPtr = winPtr;\n\t}\n\totherPtr->nextPtr = winPtr;\n    } else {\n\tTkWindow *prevPtr;\n\n\tprevPtr = winPtr->parentPtr->childList;\n\tif (prevPtr == otherPtr) {\n\t    winPtr->parentPtr->childList = winPtr;\n\t} else {\n\t    while (prevPtr->nextPtr != otherPtr) {\n\t\tprevPtr = prevPtr->nextPtr;\n\t    }\n\t    prevPtr->nextPtr = winPtr;\n\t}\n\twinPtr->nextPtr = otherPtr;\n    }\n\n    /*\n     * Notify the X server of the change. If winPtr hasn't yet been created\n     * then there's no need to tell the X server now, since the stacking order\n     * will be handled properly when the window is finally created.\n     */\n\n    if (winPtr->window != None) {\n\tXWindowChanges changes;\n\tunsigned int mask = CWStackMode;\n\n\tchanges.stack_mode = Above;\n\tfor (otherPtr = winPtr->nextPtr; otherPtr != NULL;\n\t\totherPtr = otherPtr->nextPtr) {\n\t    if ((otherPtr->window != None)\n\t\t    && !(otherPtr->flags & (TK_TOP_HIERARCHY|TK_REPARENTED))){\n\t\tchanges.sibling = otherPtr->window;\n\t\tchanges.stack_mode = Below;\n\t\tmask = CWStackMode|CWSibling;\n\t\tbreak;\n\t    }\n\t}\n\tXConfigureWindow(winPtr->display, winPtr->window, mask, &changes);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MainWindow --\n *\n *\tReturns the main window for an application.\n *\n * Results:\n *\tIf interp has a Tk application associated with it, the main window for\n *\tthe application is returned. Otherwise NULL is returned and an error\n *\tmessage is left in the interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_MainWindow(\n    Tcl_Interp *interp)\t\t/* Interpreter that embodies the application.\n\t\t\t\t * Used for error reporting also. */\n{\n    TkMainInfo *mainPtr;\n    ThreadSpecificData *tsdPtr;\n\n    if (interp == NULL) {\n\treturn NULL;\n    }\n#ifdef USE_TCL_STUBS\n    if (tclStubsPtr == NULL) {\n\treturn NULL;\n    }\n#endif\n    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;\n\t    mainPtr = mainPtr->nextPtr) {\n\tif (mainPtr->interp == interp) {\n\t    return (Tk_Window) mainPtr->winPtr;\n\t}\n    }\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    \"this isn't a Tk application\", TCL_INDEX_NONE));\n    Tcl_SetErrorCode(interp, \"TK\", \"NO_MAIN_WINDOW\", (char *)NULL);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_StrictMotif --\n *\n *\tIndicates whether strict Motif compliance has been specified for the\n *\tgiven window.\n *\n * Results:\n *\tThe return value is 1 if strict Motif compliance has been requested\n *\tfor tkwin's application by setting the tk_strictMotif variable in its\n *\tinterpreter to a true value. 0 is returned if tk_strictMotif has a\n *\tfalse value.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_StrictMotif(\n    Tk_Window tkwin)\t\t/* Window whose application is to be\n\t\t\t\t * checked. */\n{\n    return ((TkWindow *) tkwin)->mainPtr->strictMotif;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetNumMainWindows --\n *\n *\tThis function returns the number of main windows currently open in\n *\tthis process.\n *\n * Results:\n *\tThe number of main windows open in this process.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetNumMainWindows(void)\n{\n    ThreadSpecificData *tsdPtr;\n\n#ifdef USE_TCL_STUBS\n    if (tclStubsPtr == NULL) {\n\treturn 0;\n    }\n#endif\n\n    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return tsdPtr->numMainWindows;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_AlwaysShowSelection --\n *\n *\tIndicates whether text/entry widgets should always display\n *\ttheir selection, regardless of window focus.\n *\n * Results:\n *\tThe return value is 1 if always showing the selection has been\n *\trequested for tkwin's application by setting the\n *\t::tk::AlwaysShowSelection variable in its interpreter to a true value.\n *\t0 is returned if it has a false value.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_AlwaysShowSelection(\n    Tk_Window tkwin)\t\t/* Window whose application is to be\n\t\t\t\t * checked. */\n{\n    return ((TkWindow *) tkwin)->mainPtr->alwaysShowSelection;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteWindowsExitProc --\n *\n *\tThis function is invoked as an exit handler. It deletes all of the\n *\tmain windows in the current thread. We really should be using a thread\n *\tlocal exit handler to delete windows and a process exit handler to\n *\tclose the display but Tcl does not provide support for this usage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteWindowsExitProc(\n    void *clientData)\t/* tsdPtr when handler was created. */\n{\n    TkDisplay *dispPtr, *nextPtr;\n    Tcl_Interp *interp;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;\n\n    if (tsdPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Finish destroying any windows that are in a half-dead state. We must\n     * protect the interpreter while destroying the window, because of\n     * <Destroy> bindings which could destroy the interpreter while the window\n     * is being deleted. This would leave frames on the call stack pointing at\n     * deleted memory, causing core dumps.\n     */\n\n    while (tsdPtr->halfdeadWindowList != NULL) {\n\tinterp = tsdPtr->halfdeadWindowList->winPtr->mainPtr->interp;\n\tTcl_Preserve(interp);\n\ttsdPtr->halfdeadWindowList->flags |= HD_CLEANUP;\n\ttsdPtr->halfdeadWindowList->winPtr->flags &= ~TK_ALREADY_DEAD;\n\tTk_DestroyWindow((Tk_Window) tsdPtr->halfdeadWindowList->winPtr);\n\tTcl_Release(interp);\n    }\n\n    /*\n     * Destroy any remaining main windows.\n     */\n\n    while (tsdPtr->mainWindowList != NULL) {\n\tinterp = tsdPtr->mainWindowList->interp;\n\tTcl_Preserve(interp);\n\tTk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr);\n\tTcl_Release(interp);\n    }\n\n    /*\n     * Let error handlers catch up before actual close of displays.\n     * Must be done before tsdPtr->displayList is cleared, otherwise\n     * ErrorProc() in tkError.c cannot associate the pending X errors\n     * to the remaining error handlers.\n     */\n\n    for (dispPtr = tsdPtr->displayList; dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tXSync(dispPtr->display, False);\n    }\n\n    /*\n     * Iterate destroying the displays until no more displays remain. It is\n     * possible for displays to get recreated during exit by any code that\n     * calls GetScreen, so we must destroy these new displays as well as the\n     * old ones.\n     */\n\n    for (dispPtr = tsdPtr->displayList; dispPtr != NULL;\n\t    dispPtr = tsdPtr->displayList) {\n\t/*\n\t * Now iterate over the current list of open displays, and first set\n\t * the global pointer to NULL so we will be able to notice if any new\n\t * displays got created during deletion of the current set. We must\n\t * also do this to ensure that Tk_IdToWindow does not find the old\n\t * display as it is being destroyed, when it wants to see if it needs\n\t * to dispatch a message.\n\t */\n\n\tfor (tsdPtr->displayList = NULL; dispPtr != NULL; dispPtr = nextPtr) {\n\t    nextPtr = dispPtr->nextPtr;\n\t    TkCloseDisplay(dispPtr);\n\t}\n    }\n\n    tsdPtr->numMainWindows = 0;\n    tsdPtr->mainWindowList = NULL;\n    tsdPtr->initialized = false;\n}\n\f\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n\nstatic HMODULE tkcygwindll = NULL;\n\n/*\n * Run Tk_MainEx from cygtcl9tk9.?.dll\n *\n * This function is only ever called from wish9.?.exe, the cygwin port of Tcl.\n * This means that the system encoding is utf-8, so we don't have to do any\n * encoding conversions.\n */\n\nMODULE_SCOPE void\nTkCygwinMainEx(\n    Tcl_Size argc,\t\t\t/* Number of arguments. */\n    char **argv,\t\t/* Array of argument strings. */\n    Tcl_AppInitProc *appInitProc,\n\t\t\t\t/* Application-specific initialization\n\t\t\t\t * procedure to call after most initialization\n\t\t\t\t * but before starting to execute commands. */\n    Tcl_Interp *interp)\n{\n    WCHAR name[MAX_PATH];\n    size_t len;\n    void (*tkmainex)(Tcl_Size, char **, Tcl_AppInitProc *, Tcl_Interp *);\n\n    /* construct \"<path>/cygtcl9tk9.?.dll\", from \"<path>/tcl9tk9?.dll\" */\n    len = GetModuleFileNameW((HINSTANCE)Tk_GetHINSTANCE(), name, MAX_PATH);\n    name[len-2] = '.';   /* \"<path>/tcl9tk9?.d.l\" */\n    name[len-1] = name[len-5];   /* \"<path>/tcl9tk9?.d.?\" */\n    wcscpy(name+len, L\".dll\");   /* \"<path>/tcl9tk9?.d.?.dll\" */\n    memcpy(name+len-12, L\"cygtcl9tk9\", 10 * sizeof(WCHAR));   /* \"<path>/cygtcl9tk9.?.dll\" */\n\n    tkcygwindll = LoadLibraryW(name);\n    if (tkcygwindll) {\n\ttkmainex = (void (*)(Tcl_Size, char **, Tcl_AppInitProc *, Tcl_Interp *))\n\t\t(void *)GetProcAddress(tkcygwindll, \"Tk_MainEx\");\n\tif (tkmainex) {\n\t    tkmainex(argc, argv, appInitProc, interp);\n\t}\n    }\n}\n#endif /* _WIN32 */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_Init --\n *\n *\tThis function is invoked to add Tk to an interpreter. It incorporates\n *\tall of Tk's commands into the interpreter and creates the main window\n *\tfor a new Tk application. If the interpreter contains a variable\n *\t\"argv\", this function extracts several arguments from that variable,\n *\tuses them to configure the main window, and modifies argv to exclude\n *\tthe arguments (see the \"wish\" documentation for a list of the\n *\targuments that are extracted).\n *\n * Results:\n *\tReturns a standard Tcl completion code and sets the interp's result if\n *\tthere is an error.\n *\n * Side effects:\n *\tDepends on various initialization scripts that get invoked.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_Init(\n    Tcl_Interp *interp)\t\t/* Interpreter to initialize. */\n{\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n    if (tkcygwindll) {\n\tint (*tkinit)(Tcl_Interp *);\n\n\ttkinit = (int(*)(Tcl_Interp *))(void *)GetProcAddress(tkcygwindll,\"Tk_Init\");\n\tif (tkinit) {\n\t    return tkinit(interp);\n\t}\n    }\n#endif /* _WIN32 */\n    return Initialize(interp);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SafeInit --\n *\n *\tThis function is invoked to add Tk to a safe interpreter. It invokes\n *\tthe internal function that does the real work.\n *\n * Results:\n *\tReturns a standard Tcl completion code and sets the interp's result if\n *\tthere is an error.\n *\n * Side effects:\n *\tDepends on various initialization scripts that are invoked.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_SafeInit(\n    Tcl_Interp *interp)\t\t/* Interpreter to initialize. */\n{\n    /*\n     * Initialize the interpreter with Tk, safely. This removes all the Tk\n     * commands that are unsafe.\n     *\n     * Rationale:\n     *\n     * - Toplevel and menu are unsafe because they can be used to cover the\n     *   entire screen and to steal input from the user.\n     * - Continuous ringing of the bell is a nuisance.\n     * - Cannot allow access to the clipboard because a malicious script can\n     *   replace the contents with the string \"rm -r *\" and lead to surprises\n     *   when the contents of the clipboard are pasted. Similarly, the\n     *   selection command is blocked.\n     * - Cannot allow send because it can be used to cause unsafe interpreters\n     *   to execute commands. The tk command recreates the send command, so\n     *   that too must be hidden.\n     * - Focus can be used to grab the focus away from another window, in\n     *   effect stealing user input. Cannot allow that.\n     *   NOTE: We currently do *not* hide focus as it would make it impossible\n     *   to provide keyboard input to Tk in a safe interpreter.\n     * - Grab can be used to block the user from using any other apps on the\n     *   screen.\n     * - Tkwait can block the containing process forever. Use bindings,\n     *   fileevents and split the protocol into before-the-wait and\n     *   after-the-wait parts. More work but necessary.\n     * - Wm is unsafe because (if toplevels are allowed, in the future) it can\n     *   be used to remove decorations, move windows around, cover the entire\n     *   screen etc etc.\n     *\n     * Current risks:\n     *\n     * - No CPU time limit, no memory allocation limits, no color limits.\n     *   CPU time limits can be imposed by an unsafe parent interpreter.\n     *\n     * The actual code called is the same as Tk_Init but Tcl_IsSafe() is\n     * checked at several places to differentiate the two initialisations.\n     */\n\n#if defined(_WIN32) && !defined(STATIC_BUILD)\n    if (tkcygwindll) {\n\tint (*tksafeinit)(Tcl_Interp *);\n\n\ttksafeinit = (int (*)(Tcl_Interp *))\n\t\t(void *)GetProcAddress(tkcygwindll, \"Tk_SafeInit\");\n\tif (tksafeinit) {\n\t    return tksafeinit(interp);\n\t}\n    }\n#endif /* _WIN32 */\n    return Initialize(interp);\n}\n\f\nMODULE_SCOPE const TkStubs tkStubs;\n\n/*\n *----------------------------------------------------------------------\n *\n * Initialize --\n *\n *\tThe core of the initialization code for Tk, called from Tk_Init and\n *\tTk_SafeInit.\n *\n * Results:\n *\tA standard Tcl result. Also leaves an error message in the interp's\n *\tresult if there was an error.\n *\n * Side effects:\n *\tDepends on the initialization scripts that are invoked.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nCopyValue(\n    TCL_UNUSED(void *),\n    Tcl_Obj *objPtr,\n    void *dstPtr)\n{\n    *(Tcl_Obj **)dstPtr = objPtr;\n    return 1;\n}\n\nstatic int\nInitialize(\n    Tcl_Interp *interp)\t\t/* Interpreter to initialize. */\n{\n    int code = TCL_OK;\n    ThreadSpecificData *tsdPtr;\n    Tcl_Obj *value = NULL;\n    Tcl_Obj *cmd;\n\n    Tcl_Obj *nameObj = NULL;\n    Tcl_Obj* appNameObj = NULL;\n    Tcl_Obj *classObj = NULL;\n    Tcl_Obj *displayObj = NULL;\n    Tcl_Obj *colorMapObj = NULL;\n    Tcl_Obj *useObj = NULL;\n    Tcl_Obj *visualObj = NULL;\n    Tcl_Obj *geometryObj = NULL;\n\n    int sync = 0;\n\n    const Tcl_ArgvInfo table[] = {\n\t{TCL_ARGV_CONSTANT, \"-sync\", INT2PTR(1), &sync,\n\t\t\"Use synchronous mode for display server\", NULL},\n\t{TCL_ARGV_FUNC, \"-colormap\", (void *)CopyValue, &colorMapObj,\n\t\t\"Colormap for main window\", NULL},\n\t{TCL_ARGV_FUNC, \"-display\", (void *)CopyValue, &displayObj,\n\t\t\"Display to use\", NULL},\n\t{TCL_ARGV_FUNC, \"-geometry\", (void *)CopyValue, &geometryObj,\n\t\t\"Initial geometry for window\", NULL},\n\t{TCL_ARGV_FUNC, \"-name\", (void *)CopyValue, &nameObj,\n\t\t\"Name to use for application\", NULL},\n\t{TCL_ARGV_FUNC, \"-visual\", (void *)CopyValue, &visualObj,\n\t\t\"Visual for main window\", NULL},\n\t{TCL_ARGV_FUNC, \"-use\", (void *)CopyValue, &useObj,\n\t\t\"Id of window in which to embed application\", NULL},\n\tTCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END\n    };\n\n    /*\n     * Ensure that we are getting a compatible version of Tcl.\n     */\n\n    if (Tcl_InitStubs(interp, \"9.0\", 0) == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * TIP #59: Make embedded configuration information available.\n     */\n\n    TkInitEmbeddedConfigurationInformation(interp);\n\n    /*\n     * Initalize accessibility module.\n     * Must do this early because it is bound to <Map> events,\n     * and will return an error if the commands are not\n     * available.\n     */\n     TkAccessibility_Init(interp);\n\n    /*\n     * Ensure that our obj-types are registered with the Tcl runtime.\n     */\n\n    TkRegisterObjTypes();\n\n    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * We start by resetting the result because it might not be clean.\n     */\n\n    Tcl_ResetResult(interp);\n\n    if (Tcl_IsSafe(interp)) {\n\t/*\n\t * Get the clearance to start Tk and the \"argv\" parameters from the\n\t * parent.\n\t */\n\n\t/*\n\t * Step 1 : find the parent and construct the interp name (could be a\n\t * function if new APIs were ok). We could also construct the path\n\t * while walking, but there is no API to get the name of an interp\n\t * either.\n\t */\n\n\tTcl_Interp *parent = interp;\n\n\twhile (Tcl_IsSafe(parent)) {\n\t    parent = Tcl_GetParent(parent);\n\t    if (parent == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"no controlling parent interpreter\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"NO_PARENT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * Construct the name (rewalk...)\n\t */\n\n\tcode = Tcl_GetInterpPath(parent, interp);\n\tif (code != TCL_OK) {\n\t    Tcl_Panic(\"Tcl_GetInterpPath broken!\");\n\t}\n\n\t/*\n\t * Build the command to eval in trusted parent.\n\t */\n\n\tcmd = Tcl_NewListObj(2, NULL);\n\tTcl_ListObjAppendElement(NULL, cmd,\n\t\tTcl_NewStringObj(\"::safe::TkInit\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(parent));\n\n\t/*\n\t * Step 2 : Eval in the parent. The argument is the *reversed* interp\n\t * path of the child.\n\t */\n\n\tTcl_IncrRefCount(cmd);\n\tcode = Tcl_EvalObjEx(parent, cmd, 0);\n\tTcl_DecrRefCount(cmd);\n\tTcl_TransferResult(parent, code, interp);\n\tif (code != TCL_OK) {\n\t    return code;\n\t}\n\n\t/*\n\t * Use the parent's result as argv. Note: We don't use the Obj\n\t * interfaces to avoid dealing with cross interp refcounting and\n\t * changing the code below.\n\t */\n\n\tvalue = Tcl_GetObjResult(interp);\n    } else {\n\t/*\n\t * If there is an \"argv\" variable, get its value, extract out relevant\n\t * arguments from it, and rewrite the variable without the arguments\n\t * that we used.\n\t */\n\n\tvalue = Tcl_GetVar2Ex(interp, \"argv\", NULL, TCL_GLOBAL_ONLY);\n    }\n\n    if (value) {\n\tTcl_Size objc;\n\tTcl_Obj **objv, **rest;\n\tTcl_Obj *parseList = Tcl_NewListObj(1, NULL);\n\n\tTcl_ListObjAppendElement(NULL, parseList, Tcl_NewObj());\n\n\tTcl_IncrRefCount(value);\n\tif (TCL_OK != Tcl_ListObjAppendList(interp, parseList, value) ||\n\t    TCL_OK != Tcl_ListObjGetElements(NULL, parseList, &objc, &objv) ||\n\t    TCL_OK != Tcl_ParseArgsObjv(interp, table, &objc, objv, &rest)) {\n\t    Tcl_AddErrorInfo(interp,\n\t\t    \"\\n    (processing arguments in argv variable)\");\n\t    code = TCL_ERROR;\n\t}\n\tif (code == TCL_OK) {\n\t    Tcl_SetVar2Ex(interp, \"argv\", NULL,\n\t\t    Tcl_NewListObj(objc-1, rest+1), TCL_GLOBAL_ONLY);\n\t    Tcl_SetVar2Ex(interp, \"argc\", NULL,\n\t\t    Tcl_NewWideIntObj(objc-1), TCL_GLOBAL_ONLY);\n\t    Tcl_Free(rest);\n\t}\n\tTcl_DecrRefCount(parseList);\n\tif (code != TCL_OK) {\n\t    goto done;\n\t}\n    }\n\n    /*\n     * Figure out the application's name and class.\n     */\n\n    /*\n     * If we got no -name argument, fetch from TkpGetAppName().\n     */\n\n    if (nameObj == NULL) {\n\tTcl_DString nameDS;\n\n\tTcl_DStringInit(&nameDS);\n\tTkpGetAppName(interp, &nameDS);\n\tnameObj = Tcl_NewStringObj(Tcl_DStringValue(&nameDS),\n\t\tTcl_DStringLength(&nameDS));\n\tappNameObj = nameObj;\n\tTcl_IncrRefCount(appNameObj);\n\tTcl_DStringFree(&nameDS);\n    }\n\n    /*\n     * The -class argument is always the ToTitle of the -name\n     */\n\n    {\n\tTcl_Size numBytes;\n\tconst char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes);\n\n\tclassObj = Tcl_NewStringObj(bytes, numBytes);\n\n\tnumBytes = Tcl_UtfToTitle(Tcl_GetString(classObj));\n\tTcl_SetObjLength(classObj, numBytes);\n    }\n\n    /*\n     * Create an argument list for creating the top-level window, using the\n     * information parsed from argv, if any.\n     */\n\n    cmd = Tcl_NewStringObj(\"toplevel . -class\", TCL_INDEX_NONE);\n\n    Tcl_ListObjAppendElement(NULL, cmd, classObj);\n    classObj = NULL;\n\n    if (displayObj) {\n\tTcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj(\"-screen\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, cmd, displayObj);\n\n\t/*\n\t * If this is the first application for this process, save the display\n\t * name in the DISPLAY environment variable so that it will be\n\t * available to subprocesses created by us.\n\t */\n\n\tif (tsdPtr->numMainWindows == 0) {\n\t    Tcl_SetVar2Ex(interp, \"env\", \"DISPLAY\", displayObj, TCL_GLOBAL_ONLY);\n\t}\n\tdisplayObj = NULL;\n    }\n    if (colorMapObj) {\n\tTcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj(\"-colormap\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, cmd, colorMapObj);\n\tcolorMapObj = NULL;\n    }\n    if (useObj) {\n\tTcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj(\"-use\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, cmd, useObj);\n\tuseObj = NULL;\n    }\n    if (visualObj) {\n\tTcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj(\"-visual\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, cmd, visualObj);\n\tvisualObj = NULL;\n    }\n\n    Tcl_Size objc;\n    Tcl_Obj **objv;\n\n    if (TCL_OK != Tcl_ListObjGetElements(interp, cmd, &objc, &objv)) {\n\treturn TCL_ERROR;\n    }\n    code = TkCreateFrame(NULL, interp, objc, objv,\n\t    1, nameObj ? Tcl_GetString(nameObj) : NULL);\n\n    Tcl_DecrRefCount(cmd);\n\n    if (code != TCL_OK) {\n\tgoto done;\n    }\n    Tcl_ResetResult(interp);\n    if (sync) {\n\t(void)XSynchronize(Tk_Display(Tk_MainWindow(interp)), True);\n    }\n\n    /*\n     * Set the geometry of the main window, if requested. Put the requested\n     * geometry into the \"geometry\" variable.\n     */\n\n    if (geometryObj) {\n\n\tTcl_SetVar2Ex(interp, \"geometry\", NULL, geometryObj, TCL_GLOBAL_ONLY);\n\n\tcmd = Tcl_NewStringObj(\"wm geometry .\", TCL_INDEX_NONE);\n\tTcl_ListObjAppendElement(NULL, cmd, geometryObj);\n\tTcl_IncrRefCount(cmd);\n\tcode = Tcl_EvalObjEx(interp, cmd, 0);\n\tTcl_DecrRefCount(cmd);\n\tgeometryObj = NULL;\n\tif (code != TCL_OK) {\n\t    goto done;\n\t}\n    }\n\n    /*\n     * Provide \"tk\" and its stub table.\n     */\n\n#ifndef TK_NO_DEPRECATED\n    Tcl_PkgProvideEx(interp, \"Tk\", TK_PATCH_LEVEL,\n\t    (void *)&tkStubs);\n#endif\n    code = Tcl_PkgProvideEx(interp, \"tk\", TK_PATCH_LEVEL,\n\t    (void *)&tkStubs);\n    if (code != TCL_OK) {\n\tgoto done;\n    }\n\n    /*\n     * If we were able to provide ourselves as a package, then set the main\n     * loop function in Tcl to our main loop proc. This will cause tclsh to be\n     * event-aware when Tk is dynamically loaded. This will have no effect in\n     * wish, which already is prepared to run the event loop.\n     */\n\n    Tcl_SetMainLoop(Tk_MainLoop);\n\n    /*\n     * Initialized the themed widget set\n     */\n\n    code = Ttk_Init(interp);\n    if (code != TCL_OK) {\n\tgoto done;\n    }\n\n    /*\n     * Invoke platform-specific initialization. Unlock mutex before entering\n     * TkpInit, as that may run through the Tk_Init routine again for the\n     * console window interpreter.\n     */\n\n    code = TkpInit(interp);\n    if (code == TCL_OK) {\n\n\t/*\n\t * In order to find tk.tcl during initialization, we evaluate the\n\t * following script.  It calls on the Tcl command [tcl_findLibrary]\n\t * to perform the search.  See the docs for that command for details\n\t * on where it looks.\n\t *\n\t * Note that this entire search mechanism can be bypassed by defining\n\t * an alternate [tkInit] command before calling Tk_Init().\n\t */\n\n\tcode = Tcl_EvalEx(interp,\n\"if {[namespace which -command tkInit] eq \\\"\\\"} {\\n\\\n  proc tkInit {} {\\n\\\n    global tk_library tk_version tk_patchLevel\\n\\\n      rename tkInit {}\\n\\\n    tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\\n\\\n  }\\n\\\n}\\n\\\ntkInit\", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    }\n    if (code == TCL_OK) {\n\t/*\n\t * Create exit handlers to delete all windows when the application or\n\t * thread exits. The handler need to be invoked before other platform\n\t * specific cleanups take place to avoid panics in finalization.\n\t */\n\n\tTkCreateThreadExitHandler(DeleteWindowsExitProc, tsdPtr);\n    }\n  done:\n    if (value) {\n\tTcl_DecrRefCount(value);\n\tvalue = NULL;\n    }\n    if (appNameObj) {\n\tTcl_DecrRefCount(appNameObj);\n\tappNameObj = NULL;\n    }\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_PkgInitStubsCheck --\n *\n *\tThis is a replacement routine for Tk_InitStubs() that is called\n *\tfrom code where -DUSE_TK_STUBS has not been enabled.\n *\n * Results:\n *\tReturns the version of a conforming Tk stubs table, or NULL, if\n *\tthe table version doesn't satisfy the requested requirements,\n *\taccording to historical practice.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTk_PkgInitStubsCheck(\n    Tcl_Interp *interp,\n    const char * version,\n    int exact)\n{\n    const char *actualVersion = Tcl_PkgRequireEx(interp, \"tk\", version, 0, NULL);\n\n    if (exact && actualVersion) {\n\tconst char *p = version;\n\tint count = 0;\n\n\twhile (*p) {\n\t    count += !isdigit(UCHAR(*p++));\n\t}\n\tif (count == 1) {\n\t    if (0 != strncmp(version, actualVersion, strlen(version))) {\n\t\t/* Construct error message */\n\t\tTcl_PkgPresentEx(interp, \"tk\", version, 1, NULL);\n\t\treturn NULL;\n\t    }\n\t} else {\n\t    return Tcl_PkgPresentEx(interp, \"tk\", version, 1, NULL);\n\t}\n    }\n    return actualVersion;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "generic/ttk/ttk.decls",
    "content": "library\tttk\ninterface\tttk\nepoch\t\t0\nscspec\t\tTTKAPI\n\ndeclare 0 {\n    Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name)\n}\ndeclare 1 {\n    Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp)\n}\ndeclare 2 {\n    Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp)\n}\ndeclare 3 {\n    Ttk_Theme Ttk_CreateTheme(\n\tTcl_Interp *interp, const char *name, Ttk_Theme parent)\n}\ndeclare 4 {\n    void Ttk_RegisterCleanup(\n\tTcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc)\n}\n\ndeclare 5 {deprecated {Use Ttk_RegisterElement}} {\n    int Ttk_RegisterElementSpec(\n\tTtk_Theme theme,\n\tconst char *elementName,\n\tconst Ttk_ElementSpec *elementSpec,\n\tvoid *clientData)\n}\n\ndeclare 6 {\n    Ttk_ElementClass *Ttk_RegisterElement(\n\tTcl_Interp *interp,\n\tTtk_Theme theme,\n\tconst char *elementName,\n\tconst Ttk_ElementSpec *elementSpec,\n\tvoid *clientData)\n}\n\ndeclare 7 {\n    int Ttk_RegisterElementFactory(\n\tTcl_Interp *interp,\n\tconst char *name,\n\tTtk_ElementFactory factoryProc,\n\tvoid *clientData)\n}\n\ndeclare 8 {\n    void Ttk_RegisterLayout(\n\tTtk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec)\n}\n\n#\n# State maps.\n#\ndeclare 10 {\n    int Ttk_GetStateSpecFromObj(\n\tTcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn)\n}\ndeclare 11 {\n    Tcl_Obj *Ttk_NewStateSpecObj(\n\tunsigned int onbits, unsigned int offbits)\n}\ndeclare 12 {\n    Ttk_StateMap Ttk_GetStateMapFromObj(\n\tTcl_Interp *interp, Tcl_Obj *objPtr)\n}\ndeclare 13 {\n    Tcl_Obj *Ttk_StateMapLookup(\n\tTcl_Interp *interp, Ttk_StateMap map, Ttk_State state)\n}\ndeclare 14 {\n    int Ttk_StateTableLookup(\n\tconst Ttk_StateTable *map, Ttk_State state)\n}\n\n\n#\n# Low-level geometry utilities.\n#\ndeclare 20 {\n    int Ttk_GetPaddingFromObj(\n\tTcl_Interp *interp,\n\tTk_Window tkwin,\n\tTcl_Obj *objPtr,\n\tTtk_Padding *pad_rtn)\n}\ndeclare 21 {\n    int Ttk_GetBorderFromObj(\n\tTcl_Interp *interp,\n\tTcl_Obj *objPtr,\n\tTtk_Padding *pad_rtn)\n}\ndeclare 22 {\n    int Ttk_GetStickyFromObj(\n\tTcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn)\n}\ndeclare 23 {\n    Ttk_Padding Ttk_MakePadding(\n\tshort l, short t, short r, short b)\n}\ndeclare 24 {\n    Ttk_Padding Ttk_UniformPadding(\n\tshort borderWidth)\n}\ndeclare 25 {\n    Ttk_Padding Ttk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2)\n}\ndeclare 26 {\n    Ttk_Padding Ttk_RelievePadding(\n\tTtk_Padding padding, int relief, int n)\n}\ndeclare 27 {\n    Ttk_Box Ttk_MakeBox(int x, int y, int width, int height)\n}\ndeclare 28 {\n    int Ttk_BoxContains(Ttk_Box box, int x, int y)\n}\ndeclare 29 {\n    Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side)\n}\ndeclare 30 {\n    Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky)\n}\ndeclare 31 {\n    Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor)\n}\ndeclare 32 {\n    Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p)\n}\ndeclare 33 {\n    Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p)\n}\ndeclare 34 {\n    Ttk_Box Ttk_PlaceBox(\n\tTtk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky)\n}\ndeclare 35 {\n    Tcl_Obj *Ttk_NewBoxObj(Ttk_Box box)\n}\n\n#\n# Utilities.\n#\ndeclare 40 {\n    int Ttk_GetOrientFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Orient *orient)\n}\n\n\n"
  },
  {
    "path": "generic/ttk/ttkBlink.c",
    "content": "/*\n * Copyright 2004, Joe English.\n *\n * Usage:\n *\tTtkBlinkCursor(corePtr), usually called in a widget's Init hook,\n *\tarranges to periodically toggle the corePtr->flags CURSOR_ON bit\n *\ton and off (and schedule a redisplay) whenever the widget has focus.\n *\n *\tNote: Widgets may have additional logic to decide whether\n *\tto display the cursor or not (e.g., readonly or disabled states);\n *\tTtkBlinkCursor() does not account for this.\n *\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n\n#define DEF_CURSOR_ON_TIME\t600\t\t/* milliseconds */\n#define DEF_CURSOR_OFF_TIME\t300\t\t/* milliseconds */\n\n/* Interp-specific data for tracking cursors:\n */\ntypedef struct\n{\n    WidgetCore\t\t*owner;\t/* Widget that currently has cursor */\n    Tcl_TimerToken\ttimer;\t\t/* Blink timer */\n    int\t\tonTime;\t\t/* #milliseconds to blink cursor on */\n    int\t\toffTime;\t/* #milliseconds to blink cursor off */\n} CursorManager;\n\n/* CursorManagerDeleteProc --\n *\tInterpDeleteProc for cursor manager.\n */\nstatic void CursorManagerDeleteProc(\n    void *clientData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    CursorManager *cm = (CursorManager*)clientData;\n\n    if (cm->timer) {\n\tTcl_DeleteTimerHandler(cm->timer);\n    }\n    Tcl_Free(clientData);\n}\n\n/* GetCursorManager --\n *\tLook up and create if necessary the interp's cursor manager.\n */\nstatic CursorManager *GetCursorManager(Tcl_Interp *interp)\n{\n    static const char *cm_key = \"ttk::CursorManager\";\n    CursorManager *cm = (CursorManager *)Tcl_GetAssocData(interp, cm_key,0);\n    Tk_Window window;\n    Tk_Uid value;\n    int intValue;\n\n    if (!cm) {\n\tcm = (CursorManager *)Tcl_Alloc(sizeof(*cm));\n\tcm->timer = 0;\n\tcm->owner = 0;\n\tcm->onTime = DEF_CURSOR_ON_TIME;\n\tcm->offTime = DEF_CURSOR_OFF_TIME;\n\n\t/* Override on and off default times with values obtained from\n\t * the option database (if such values are specified).\n\t */\n\n\twindow = Tk_MainWindow(interp);\n\tif (window) {\n\t    value = Tk_GetOption(window, \"insertOnTime\", \"OnTime\");\n\t    if (value) {\n\t\tif (Tcl_GetInt(interp, value, &intValue) == TCL_OK) {\n\t\t    cm->onTime = intValue;\n\t\t}\n\t    }\n\t    value = Tk_GetOption(window, \"insertOffTime\", \"OffTime\");\n\t    if (value) {\n\t\tif (Tcl_GetInt(interp, value, &intValue) == TCL_OK) {\n\t\t    cm->offTime = intValue;\n\t\t}\n\t    }\n\t}\n\n\tTcl_SetAssocData(interp, cm_key, CursorManagerDeleteProc, cm);\n    }\n    return cm;\n}\n\n/* CursorBlinkProc --\n *\tTimer handler to blink the insert cursor on and off.\n */\nstatic void\nCursorBlinkProc(void *clientData)\n{\n    CursorManager *cm = (CursorManager *)clientData;\n    int blinkTime;\n\n    if (cm->owner->flags & CURSOR_ON) {\n\tcm->owner->flags &= ~(unsigned)CURSOR_ON;\n\tblinkTime = cm->offTime;\n    } else {\n\tcm->owner->flags |= CURSOR_ON;\n\tblinkTime = cm->onTime;\n    }\n    cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData);\n    TtkRedisplayWidget(cm->owner);\n}\n\n/* LoseCursor --\n *\tTurn cursor off, disable blink timer.\n */\nstatic void LoseCursor(CursorManager *cm, WidgetCore *corePtr)\n{\n    if (corePtr->flags & CURSOR_ON) {\n\tcorePtr->flags &= ~(unsigned)CURSOR_ON;\n\tTtkRedisplayWidget(corePtr);\n    }\n    if (cm->owner == corePtr) {\n\tcm->owner = NULL;\n    }\n    if (cm->timer) {\n\tTcl_DeleteTimerHandler(cm->timer);\n\tcm->timer = 0;\n    }\n}\n\n/* ClaimCursor --\n *\tClaim ownership of the insert cursor and blink on.\n */\nstatic void ClaimCursor(CursorManager *cm, WidgetCore *corePtr)\n{\n    if (cm->owner == corePtr) {\n\treturn;\n    }\n    if (cm->owner) {\n\tLoseCursor(cm, cm->owner);\n    }\n\n    corePtr->flags |= CURSOR_ON;\n    TtkRedisplayWidget(corePtr);\n\n    cm->owner = corePtr;\n    cm->timer = Tcl_CreateTimerHandler(cm->onTime, CursorBlinkProc, cm);\n}\n\n/*\n * CursorEventProc --\n *\tEvent handler for FocusIn and FocusOut events;\n *\tclaim/lose ownership of the insert cursor when the widget\n *\tacquires/loses keyboard focus.\n */\n\n#define CursorEventMask (FocusChangeMask|StructureNotifyMask)\n#define RealFocusEvent(d) \\\n    (d == NotifyInferior || d == NotifyAncestor || d == NotifyNonlinear)\n\nstatic void\nCursorEventProc(void *clientData, XEvent *eventPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    CursorManager *cm = GetCursorManager(corePtr->interp);\n\n    switch (eventPtr->type) {\n\tcase DestroyNotify:\n\t    if (cm->owner == corePtr) {\n\t\tLoseCursor(cm, corePtr);\n\t    }\n\t    Tk_DeleteEventHandler(\n\t\tcorePtr->tkwin, CursorEventMask, CursorEventProc, clientData);\n\t    break;\n\tcase FocusIn:\n\t    if (RealFocusEvent(eventPtr->xfocus.detail)) {\n\t\tClaimCursor(cm, corePtr);\n\t    }\n\t    break;\n\tcase FocusOut:\n\t    if (RealFocusEvent(eventPtr->xfocus.detail)) {\n\t\tLoseCursor(cm, corePtr);\n\t    }\n\t    break;\n    }\n}\n\nvoid TtkSetBlinkCursorOnTime(Tcl_Interp* interp, int onTime)\n{\n    CursorManager* cm = GetCursorManager(interp);\n\n    if (onTime >= 0) {\n\tcm->onTime = onTime;\n    }\n}\n\nvoid TtkSetBlinkCursorOffTime(Tcl_Interp* interp, int offTime)\n{\n    CursorManager* cm = GetCursorManager(interp);\n\n    if (offTime >= 0) {\n\tcm->offTime = offTime;\n    }\n}\n\n/*\n * TtkSetBlinkCursorTimes --\n *\tSet cursor blink on and off times from the \".\" style defaults\n *\t-insertontime and -insertofftime - For instance to set cursor\n *\tblinking off:\n *\t    ttk::style configure . -insertofftime 0\n */\nvoid TtkSetBlinkCursorTimes(Tcl_Interp* interp)\n{\n    Ttk_Theme theme;\n    Ttk_Style style = NULL;\n    Tcl_Obj* result;\n    int timeInterval;\n\n    theme = Ttk_GetCurrentTheme(interp);\n    style = Ttk_GetStyle(theme, \".\");\n    result = Ttk_StyleDefault(style, \"-insertontime\");\n    if (result) {\n\tTcl_GetIntFromObj(interp, result, &timeInterval);\n\tTtkSetBlinkCursorOnTime(interp, timeInterval);\n    }\n    result = Ttk_StyleDefault(style, \"-insertofftime\");\n    if (result) {\n\tTcl_GetIntFromObj(interp, result, &timeInterval);\n\tTtkSetBlinkCursorOffTime(interp, timeInterval);\n    }\n}\n/*\n * TtkBlinkCursor (main routine) --\n *\tArrange to blink the cursor on and off whenever the\n *\twidget has focus.\n */\nvoid TtkBlinkCursor(WidgetCore *corePtr)\n{\n    Tk_CreateEventHandler(\n\tcorePtr->tkwin, CursorEventMask, CursorEventProc, corePtr);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkButton.c",
    "content": "/*\n * Copyright © 2003, Joe English\n *\n * label, button, checkbutton, radiobutton, and menubutton widgets.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n\n/* Bit fields for OptionSpec mask field:\n */\n#define STATE_CHANGED\t\t(0x100)\t\t/* -state option changed */\n#define DEFAULTSTATE_CHANGED\t(0x200)\t\t/* -default option changed */\n\n/*------------------------------------------------------------------------\n * +++ Base resources for labels, buttons, checkbuttons, etc:\n */\ntypedef struct\n{\n    /*\n     * Text element resources:\n     */\n    Tcl_Obj *textObj;\n    Tcl_Obj *justifyObj;\n    Tcl_Obj *textVariableObj;\n    Tcl_Obj *underlineObj;\n    Tcl_Obj *widthObj;\n\n    Ttk_TraceHandle\t*textVariableTrace;\n    Ttk_ImageSpec\t*imageSpec;\n\n    /*\n     * Image element resources:\n     */\n    Tcl_Obj *imageObj;\n\n    /*\n     * Compound label/image resources:\n     */\n    Tcl_Obj *compoundObj;\n    Tcl_Obj *paddingObj;\n\n    /*\n     * Compatibility/legacy options:\n     */\n    Tcl_Obj *stateObj;\n\n} BasePart;\n\ntypedef struct\n{\n    WidgetCore\tcore;\n    BasePart\tbase;\n} Base;\n\nstatic const Tk_OptionSpec BaseOptionSpecs[] =\n{\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\t\"left\", offsetof(Base,base.justifyObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\", \"\",\n\toffsetof(Base,base.textObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\", \"\",\n\toffsetof(Base,base.textVariableObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTTK_OPTION_UNDERLINE_DEF(Base, base.underlineObj), 0},\n    {TK_OPTION_STRING, \"-width\", \"width\", \"Width\",\n\tNULL, offsetof(Base,base.widthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n\n    /*\n     * Image options\n     */\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\", NULL/*default*/,\n\toffsetof(Base,base.imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n\n    /*\n     * Compound base/image options\n     */\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tNULL, offsetof(Base,base.compoundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, ttkCompoundStrings,\n\tGEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Pad\",\n\tNULL, offsetof(Base,base.paddingObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},\n\n    /*\n     * Compatibility/legacy options\n     */\n    {TK_OPTION_STRING, \"-state\", \"state\", \"State\",\n\t\"normal\", offsetof(Base,base.stateObj), TCL_INDEX_NONE,\n\t0,0,STATE_CHANGED },\n\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*\n * Variable trace procedure for -textvariable option:\n */\nstatic void TextVariableChanged(void *clientData, const char *value)\n{\n    Base *basePtr = (Base *)clientData;\n    Tcl_Obj *newText;\n\n    if (WidgetDestroyed(&basePtr->core)) {\n\treturn;\n    }\n\n    newText = value ? Tcl_NewStringObj(value, -1) : Tcl_NewStringObj(\"\", 0);\n\n    Tcl_IncrRefCount(newText);\n    Tcl_DecrRefCount(basePtr->base.textObj);\n    basePtr->base.textObj = newText;\n\n    TtkResizeWidget(&basePtr->core);\n}\n\nstatic void\nBaseInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Base *basePtr = (Base *)recordPtr;\n\n    basePtr->base.textVariableTrace = 0;\n    basePtr->base.imageSpec = NULL;\n}\n\nstatic void\nBaseCleanup(void *recordPtr)\n{\n    Base *basePtr = (Base *)recordPtr;\n    if (basePtr->base.textVariableTrace) {\n\tTtk_UntraceVariable(basePtr->base.textVariableTrace);\n    }\n    if (basePtr->base.imageSpec) {\n\tTtkFreeImageSpec(basePtr->base.imageSpec);\n    }\n}\n\nstatic void\nBaseImageChanged(\n    void *clientData,\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    Base *basePtr = (Base *)clientData;\n\n    TtkResizeWidget(&basePtr->core);\n}\n\nstatic int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Base *basePtr = (Base *)recordPtr;\n    Tcl_Obj *textVarName = basePtr->base.textVariableObj;\n    Ttk_TraceHandle *vt = 0;\n    Ttk_ImageSpec *imageSpec = NULL;\n\n    if (!TkObjIsEmpty(textVarName)) {\n\tvt = Ttk_TraceVariable(interp,textVarName,TextVariableChanged,basePtr);\n\tif (!vt) return TCL_ERROR;\n    }\n\n    if (basePtr->base.imageObj) {\n\timageSpec = TtkGetImageSpecEx(\n\t    interp, basePtr->core.tkwin, basePtr->base.imageObj, BaseImageChanged, basePtr);\n\tif (!imageSpec) {\n\t    goto error;\n\t}\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\nerror:\n\tif (imageSpec) TtkFreeImageSpec(imageSpec);\n\tif (vt) Ttk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    if (basePtr->base.textVariableTrace) {\n\tTtk_UntraceVariable(basePtr->base.textVariableTrace);\n    }\n    basePtr->base.textVariableTrace = vt;\n\n    if (basePtr->base.imageSpec) {\n\tTtkFreeImageSpec(basePtr->base.imageSpec);\n    }\n    basePtr->base.imageSpec = imageSpec;\n\n    if (mask & STATE_CHANGED) {\n\tTtkCheckStateOption(&basePtr->core, basePtr->base.stateObj);\n    }\n\n    return TCL_OK;\n}\n\nstatic int\nBasePostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr,\n    TCL_UNUSED(int))\n{\n    Base *basePtr = (Base *)recordPtr;\n    int status = TCL_OK;\n\n    if (basePtr->base.textVariableTrace) {\n\tstatus = Ttk_FireTrace(basePtr->base.textVariableTrace);\n    }\n\n    return status;\n}\n\n/*------------------------------------------------------------------------\n * +++ Label widget.\n * Just a base widget that adds a few appearance-related options\n */\n\ntypedef struct\n{\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *fontObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *anchorObj;\n    Tcl_Obj *wrapLengthObj;\n} LabelPart;\n\ntypedef struct\n{\n    WidgetCore\tcore;\n    BasePart\tbase;\n    LabelPart\tlabel;\n} Label;\n\nstatic const Tk_OptionSpec LabelOptionSpecs[] =\n{\n    {TK_OPTION_BORDER, \"-background\", \"frameColor\", \"FrameColor\",\n\tNULL, offsetof(Label,label.backgroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_COLOR, \"-foreground\", \"textColor\", \"TextColor\",\n\tNULL, offsetof(Label,label.foregroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tNULL, offsetof(Label,label.fontObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n\tNULL, offsetof(Label,label.borderWidthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n\tNULL, offsetof(Label,label.reliefObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\t\"w\", offsetof(Label,label.anchorObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY_CHANGED},\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\tNULL, offsetof(Label, label.wrapLengthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED /*SB: SIZE_CHANGED*/ },\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)\n};\n\nstatic const Ttk_Ensemble LabelCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec LabelWidgetSpec =\n{\n    \"TLabel\",\t\t\t/* className */\n    sizeof(Label),\t\t/* recordSize */\n    LabelOptionSpecs,\t\t/* optionSpecs */\n    LabelCommands,\t\t/* subcommands */\n    BaseInitialize,\t\t/* initializeProc */\n    BaseCleanup,\t\t/* cleanupProc */\n    BaseConfigure,\t\t/* configureProc */\n    BasePostConfigure,\t\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(LabelLayout)\n    TTK_GROUP(\"Label.border\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Label.padding\", TTK_FILL_BOTH|TTK_BORDER,\n\t    TTK_NODE(\"Label.label\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Button widget.\n * Adds a new subcommand \"invoke\", and options \"-command\" and \"-default\"\n */\n\ntypedef struct\n{\n    Tcl_Obj *commandObj;\n    Tcl_Obj *defaultStateObj;\n} ButtonPart;\n\ntypedef struct\n{\n    WidgetCore\tcore;\n    BasePart\tbase;\n    ButtonPart\tbutton;\n} Button;\n\n/*\n * Option specifications:\n */\nstatic const Tk_OptionSpec ButtonOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\t\"\", offsetof(Button, button.commandObj), TCL_INDEX_NONE, 0,0,0},\n    {TK_OPTION_STRING_TABLE, \"-default\", \"default\", \"Default\",\n\t\"normal\", offsetof(Button, button.defaultStateObj), TCL_INDEX_NONE,\n\t0, ttkDefaultStrings, DEFAULTSTATE_CHANGED},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)\n};\n\nstatic int ButtonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Button *buttonPtr = (Button *)recordPtr;\n\n    if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /* Handle \"-default\" option:\n     */\n    if (mask & DEFAULTSTATE_CHANGED) {\n\tTtk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n\tTtk_GetButtonDefaultStateFromObj(\n\t    NULL, buttonPtr->button.defaultStateObj, &defaultState);\n\tif (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {\n\t    TtkWidgetChangeState(&buttonPtr->core, TTK_STATE_ALTERNATE, 0);\n\t} else {\n\t    TtkWidgetChangeState(&buttonPtr->core, 0, TTK_STATE_ALTERNATE);\n\t}\n    }\n    return TCL_OK;\n}\n\n/* $button invoke --\n *\tEvaluate the button's -command.\n */\nstatic int\nButtonInvokeCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Button *buttonPtr = (Button *)recordPtr;\n    if (objc > 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"invoke\");\n\treturn TCL_ERROR;\n    }\n    if (buttonPtr->core.state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n    return Tcl_EvalObjEx(interp, buttonPtr->button.commandObj, TCL_EVAL_GLOBAL);\n}\n\nstatic const Ttk_Ensemble ButtonCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"invoke\",\t\tButtonInvokeCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec ButtonWidgetSpec =\n{\n    \"TButton\",\t\t\t/* className */\n    sizeof(Button),\t\t/* recordSize */\n    ButtonOptionSpecs,\t\t/* optionSpecs */\n    ButtonCommands,\t\t/* subcommands */\n    BaseInitialize,\t\t/* initializeProc */\n    BaseCleanup,\t\t/* cleanupProc */\n    ButtonConfigure,\t\t/* configureProc */\n    BasePostConfigure,\t\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(ButtonLayout)\n    TTK_GROUP(\"Button.border\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Button.focus\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Checkbutton widget.\n */\ntypedef struct\n{\n    Tcl_Obj *variableObj;\n    Tcl_Obj *onValueObj;\n    Tcl_Obj *offValueObj;\n    Tcl_Obj *commandObj;\n\n    Ttk_TraceHandle *variableTrace;\n\n} CheckbuttonPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    BasePart base;\n    CheckbuttonPart checkbutton;\n} Checkbutton;\n\n/*\n * Option specifications:\n */\nstatic const Tk_OptionSpec CheckbuttonOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\tNULL, offsetof(Checkbutton, checkbutton.variableObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_STRING, \"-onvalue\", \"onValue\", \"OnValue\",\n\t\"1\", offsetof(Checkbutton, checkbutton.onValueObj), TCL_INDEX_NONE,\n\t0,0,0},\n    {TK_OPTION_STRING, \"-offvalue\", \"offValue\", \"OffValue\",\n\t\"0\", offsetof(Checkbutton, checkbutton.offValueObj), TCL_INDEX_NONE,\n\t0,0,0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\t\"\", offsetof(Checkbutton, checkbutton.commandObj), TCL_INDEX_NONE,\n\t0,0,0},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)\n};\n\n/*\n * Variable trace procedure for checkbutton -variable option\n */\nstatic void CheckbuttonVariableChanged(void *clientData, const char *value)\n{\n    Checkbutton *checkPtr = (Checkbutton *)clientData;\n\n    if (WidgetDestroyed(&checkPtr->core)) {\n\treturn;\n    }\n\n    if (!value) {\n\tTtkWidgetChangeState(&checkPtr->core, TTK_STATE_ALTERNATE, 0);\n\treturn;\n    }\n    /* else */\n    TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_ALTERNATE);\n    if (!strcmp(value, Tcl_GetString(checkPtr->checkbutton.onValueObj))) {\n\tTtkWidgetChangeState(&checkPtr->core, TTK_STATE_SELECTED, 0);\n    } else {\n\tTtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_SELECTED);\n    }\n}\n\nstatic void\nCheckbuttonInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Checkbutton *checkPtr = (Checkbutton *)recordPtr;\n    Tcl_Obj *variableObj;\n\n    /* default -variable is the widget name:\n     */\n    variableObj = Tcl_NewStringObj(Tk_PathName(checkPtr->core.tkwin), -1);\n    Tcl_IncrRefCount(variableObj);\n    checkPtr->checkbutton.variableObj = variableObj;\n    BaseInitialize(interp, recordPtr);\n}\n\nstatic void\nCheckbuttonCleanup(void *recordPtr)\n{\n    Checkbutton *checkPtr = (Checkbutton *)recordPtr;\n    Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace);\n    checkPtr->checkbutton.variableTrace = 0;\n    BaseCleanup(recordPtr);\n}\n\nstatic int\nCheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Checkbutton *checkPtr = (Checkbutton *)recordPtr;\n    Tcl_Obj *varName = checkPtr->checkbutton.variableObj;\n    Ttk_TraceHandle *vt = NULL;\n\n    if (!TkObjIsEmpty(varName)) {\n\tvt = Ttk_TraceVariable(interp, varName,\n\t    CheckbuttonVariableChanged, checkPtr);\n\tif (!vt) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (BaseConfigure(interp, recordPtr, mask) != TCL_OK){\n\tTtk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    if (checkPtr->checkbutton.variableTrace) {\n\tTtk_UntraceVariable(checkPtr->checkbutton.variableTrace);\n    }\n    checkPtr->checkbutton.variableTrace = vt;\n\n    return TCL_OK;\n}\n\nstatic int\nCheckbuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Checkbutton *checkPtr = (Checkbutton *)recordPtr;\n    int status = TCL_OK;\n\n    if (checkPtr->checkbutton.variableTrace) {\n\tstatus = Ttk_FireTrace(checkPtr->checkbutton.variableTrace);\n    }\n    if (status == TCL_OK && !WidgetDestroyed(&checkPtr->core)) {\n\tstatus = BasePostConfigure(interp, recordPtr, mask);\n    }\n    return status;\n}\n\n/*\n * Checkbutton 'invoke' subcommand:\n *\tToggles the checkbutton state.\n */\nstatic int\nCheckbuttonInvokeCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Checkbutton *checkPtr = (Checkbutton *)recordPtr;\n    WidgetCore *corePtr = &checkPtr->core;\n    Tcl_Obj *newValue;\n\n    if (objc > 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"invoke\");\n\treturn TCL_ERROR;\n    }\n    if (corePtr->state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n    /*\n     * Toggle the selected state.\n     */\n    if (corePtr->state & TTK_STATE_SELECTED) {\n\tnewValue = checkPtr->checkbutton.offValueObj;\n    } else {\n\tnewValue = checkPtr->checkbutton.onValueObj;\n    }\n\n    if (checkPtr->checkbutton.variableObj == NULL ||\n\tTkObjIsEmpty(checkPtr->checkbutton.variableObj))\n\tCheckbuttonVariableChanged(checkPtr, Tcl_GetString(newValue));\n    else if (Tcl_ObjSetVar2(interp,\n\t\tcheckPtr->checkbutton.variableObj, NULL, newValue,\n\t\tTCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t    == NULL)\n\treturn TCL_ERROR;\n\n    if (WidgetDestroyed(corePtr)) {\n\treturn TCL_ERROR;\n    }\n\n    return Tcl_EvalObjEx(interp,\n\tcheckPtr->checkbutton.commandObj, TCL_EVAL_GLOBAL);\n}\n\nstatic const Ttk_Ensemble CheckbuttonCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"invoke\",\t\tCheckbuttonInvokeCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    /* MISSING: select, deselect, toggle */\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec CheckbuttonWidgetSpec =\n{\n    \"TCheckbutton\",\t\t/* className */\n    sizeof(Checkbutton),\t/* recordSize */\n    CheckbuttonOptionSpecs,\t/* optionSpecs */\n    CheckbuttonCommands,\t/* subcommands */\n    CheckbuttonInitialize,\t/* initializeProc */\n    CheckbuttonCleanup,\t\t/* cleanupProc */\n    CheckbuttonConfigure,\t/* configureProc */\n    CheckbuttonPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(CheckbuttonLayout)\n     TTK_GROUP(\"Checkbutton.padding\", TTK_FILL_BOTH,\n\t TTK_NODE(\"Checkbutton.indicator\", TTK_PACK_LEFT)\n\t TTK_GROUP(\"Checkbutton.focus\", TTK_PACK_LEFT | TTK_STICK_W,\n\t     TTK_NODE(\"Checkbutton.label\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Radiobutton widget.\n */\n\ntypedef struct\n{\n    Tcl_Obj *variableObj;\n    Tcl_Obj *valueObj;\n    Tcl_Obj *commandObj;\n\n    Ttk_TraceHandle\t*variableTrace;\n\n} RadiobuttonPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    BasePart base;\n    RadiobuttonPart radiobutton;\n} Radiobutton;\n\n/*\n * Option specifications:\n */\nstatic const Tk_OptionSpec RadiobuttonOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\t\"::selectedButton\", offsetof(Radiobutton, radiobutton.variableObj),TCL_INDEX_NONE,\n\t0,0,0},\n    {TK_OPTION_STRING, \"-value\", \"Value\", \"Value\",\n\t\"1\", offsetof(Radiobutton, radiobutton.valueObj), TCL_INDEX_NONE,\n\t0,0,0},\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\t\"\", offsetof(Radiobutton, radiobutton.commandObj), TCL_INDEX_NONE,\n\t0,0,0},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)\n};\n\n/*\n * Variable trace procedure for radiobuttons.\n */\nstatic void\nRadiobuttonVariableChanged(void *clientData, const char *value)\n{\n    Radiobutton *radioPtr = (Radiobutton *)clientData;\n\n    if (WidgetDestroyed(&radioPtr->core)) {\n\treturn;\n    }\n\n    if (!value) {\n\tTtkWidgetChangeState(&radioPtr->core, TTK_STATE_ALTERNATE, 0);\n\treturn;\n    }\n    /* else */\n    TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_ALTERNATE);\n    if (!strcmp(value, Tcl_GetString(radioPtr->radiobutton.valueObj))) {\n\tTtkWidgetChangeState(&radioPtr->core, TTK_STATE_SELECTED, 0);\n    } else {\n\tTtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_SELECTED);\n    }\n}\n\nstatic void\nRadiobuttonCleanup(void *recordPtr)\n{\n    Radiobutton *radioPtr = (Radiobutton *)recordPtr;\n    Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace);\n    radioPtr->radiobutton.variableTrace = 0;\n    BaseCleanup(recordPtr);\n}\n\nstatic int\nRadiobuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Radiobutton *radioPtr = (Radiobutton *)recordPtr;\n    Ttk_TraceHandle *vt = Ttk_TraceVariable(\n\tinterp, radioPtr->radiobutton.variableObj,\n\tRadiobuttonVariableChanged, radioPtr);\n\n    if (!vt) {\n\treturn TCL_ERROR;\n    }\n\n    if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) {\n\tTtk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace);\n    radioPtr->radiobutton.variableTrace = vt;\n\n    return TCL_OK;\n}\n\nstatic int\nRadiobuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Radiobutton *radioPtr = (Radiobutton *)recordPtr;\n    int status = TCL_OK;\n\n    if (radioPtr->radiobutton.variableTrace) {\n\tstatus = Ttk_FireTrace(radioPtr->radiobutton.variableTrace);\n    }\n    if (status == TCL_OK && !WidgetDestroyed(&radioPtr->core)) {\n\tstatus = BasePostConfigure(interp, recordPtr, mask);\n    }\n    return status;\n}\n\n/*\n * Radiobutton 'invoke' subcommand:\n *\tSets the radiobutton -variable to the -value, evaluates the -command.\n */\nstatic int\nRadiobuttonInvokeCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Radiobutton *radioPtr = (Radiobutton *)recordPtr;\n    WidgetCore *corePtr = &radioPtr->core;\n\n    if (objc > 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"invoke\");\n\treturn TCL_ERROR;\n    }\n    if (corePtr->state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n\n    if (Tcl_ObjSetVar2(interp,\n\t    radioPtr->radiobutton.variableObj, NULL,\n\t    radioPtr->radiobutton.valueObj,\n\t    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)\n\t== NULL)\n\treturn TCL_ERROR;\n\n    if (WidgetDestroyed(corePtr)) {\n\treturn TCL_ERROR;\n    }\n\n    return Tcl_EvalObjEx(interp,\n\tradioPtr->radiobutton.commandObj, TCL_EVAL_GLOBAL);\n}\n\nstatic const Ttk_Ensemble RadiobuttonCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"invoke\",\t\tRadiobuttonInvokeCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    /* MISSING: select, deselect */\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec RadiobuttonWidgetSpec =\n{\n    \"TRadiobutton\",\t\t/* className */\n    sizeof(Radiobutton),\t/* recordSize */\n    RadiobuttonOptionSpecs,\t/* optionSpecs */\n    RadiobuttonCommands,\t/* subcommands */\n    BaseInitialize,\t\t/* initializeProc */\n    RadiobuttonCleanup,\t\t/* cleanupProc */\n    RadiobuttonConfigure,\t/* configureProc */\n    RadiobuttonPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(RadiobuttonLayout)\n     TTK_GROUP(\"Radiobutton.padding\", TTK_FILL_BOTH,\n\t TTK_NODE(\"Radiobutton.indicator\", TTK_PACK_LEFT)\n\t TTK_GROUP(\"Radiobutton.focus\", TTK_PACK_LEFT,\n\t     TTK_NODE(\"Radiobutton.label\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Menubutton widget.\n */\n\ntypedef struct\n{\n    Tcl_Obj *menuObj;\n    Tcl_Obj *directionObj;\n} MenubuttonPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    BasePart base;\n    MenubuttonPart menubutton;\n} Menubutton;\n\n/*\n * Option specifications:\n */\nstatic const char *const directionStrings[] = {\n    \"above\", \"below\", \"flush\", \"left\", \"right\", NULL\n};\nstatic const Tk_OptionSpec MenubuttonOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-menu\", \"menu\", \"Menu\",\n\t\"\", offsetof(Menubutton, menubutton.menuObj), TCL_INDEX_NONE, 0,0,0},\n    {TK_OPTION_STRING_TABLE, \"-direction\", \"direction\", \"Direction\",\n\t\"below\", offsetof(Menubutton, menubutton.directionObj), TCL_INDEX_NONE,\n\t0, directionStrings, GEOMETRY_CHANGED},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)\n};\n\nstatic const Ttk_Ensemble MenubuttonCommands[] = {\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec MenubuttonWidgetSpec =\n{\n    \"TMenubutton\",\t\t/* className */\n    sizeof(Menubutton),\t/* recordSize */\n    MenubuttonOptionSpecs,\t/* optionSpecs */\n    MenubuttonCommands,\t/* subcommands */\n    BaseInitialize,\t\t/* initializeProc */\n    BaseCleanup,\t\t/* cleanupProc */\n    BaseConfigure,\t\t/* configureProc */\n    BasePostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(MenubuttonLayout)\n    TTK_GROUP(\"Menubutton.border\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Menubutton.focus\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Menubutton.indicator\", TTK_PACK_RIGHT)\n\t    TTK_GROUP(\"Menubutton.padding\", TTK_FILL_X,\n\t\tTTK_NODE(\"Menubutton.label\", TTK_PACK_LEFT))))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkButton_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(theme, \"TLabel\", LabelLayout);\n    Ttk_RegisterLayout(theme, \"TButton\", ButtonLayout);\n    Ttk_RegisterLayout(theme, \"TCheckbutton\", CheckbuttonLayout);\n    Ttk_RegisterLayout(theme, \"TRadiobutton\", RadiobuttonLayout);\n    Ttk_RegisterLayout(theme, \"TMenubutton\", MenubuttonLayout);\n\n    RegisterWidget(interp, \"ttk::label\", &LabelWidgetSpec);\n    RegisterWidget(interp, \"ttk::button\", &ButtonWidgetSpec);\n    RegisterWidget(interp, \"ttk::checkbutton\", &CheckbuttonWidgetSpec);\n    RegisterWidget(interp, \"ttk::radiobutton\", &RadiobuttonWidgetSpec);\n    RegisterWidget(interp, \"ttk::menubutton\", &MenubuttonWidgetSpec);\n}\n"
  },
  {
    "path": "generic/ttk/ttkCache.c",
    "content": "/*\n *      Theme engine resource cache.\n *\n * Copyright © 2004, Joe English\n *\n * The problem:\n *\n * Tk maintains reference counts for fonts, colors, and images,\n * and deallocates them when the reference count goes to zero.\n * With the theme engine, resources are allocated right before\n * drawing an element and released immediately after.\n * This causes a severe performance penalty, and on PseudoColor\n * visuals it causes colormap cycling as colormap entries are\n * released and reused.\n *\n * Solution: Acquire fonts, colors, and objects from a\n * resource cache instead of directly from Tk; the cache\n * holds a semipermanent reference to the resource to keep\n * it from being deallocated.\n *\n * The plumbing and control flow here is quite contorted;\n * it would be better to address this problem in the core instead.\n *\n * @@@ Colormap flashing on PseudoColor visuals is still possible,\n * but this will be a transient effect.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\n#if defined(_WIN32) || defined(MAC_OSX_TK)\n#   define NEED_EXTRA_INFO 0\n#else\n /*\n  * Display, Screen, Visual, and Colormap need be tracked, too.\n  * Required on X11 with multiple display connections or\n  * special visuals/colormaps.\n  */\n#   define NEED_EXTRA_INFO 1\n#endif\n\n#if NEED_EXTRA_INFO\ntypedef struct {\n    Tcl_Obj *objPtr;\t\t/* The cached Tcl_Obj*. */\n    Display *display;\t\t/* Display of (Font|Border|Color)Obj */\n    int screenNum;\t\t/* Screen number of (Font|Border|Color)Obj */\n    Visual *visual;\t\t/* Visual of (Font|Border|Color)Obj */\n    Colormap colormap;\t\t/* Colormap of (Font|Border|Color)Obj */\n} Ttk_Cached;\n#endif\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\nstruct Ttk_ResourceCache_ {\n    Tcl_Interp\t  *interp;\t/* Interpreter for error reporting */\n    Tk_Window\t  tkwin;\t/* Cache window. */\n    Tcl_HashTable fontTable;\t/* Entries: Tcl_Obj* holding FontObjs */\n    Tcl_HashTable colorTable;\t/* Entries: Tcl_Obj* holding ColorObjs */\n    Tcl_HashTable borderTable;\t/* Entries: Tcl_Obj* holding BorderObjs */\n    Tcl_HashTable imageTable;\t/* Entries: Tk_Images */\n\n    Tcl_HashTable namedColors;\t/* Entries: RGB values as Tcl_StringObjs */\n};\n\n/*\n * Ttk_CreateResourceCache --\n *\tInitialize a new resource cache.\n */\nTtk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *interp)\n{\n    Ttk_ResourceCache cache = (Ttk_ResourceCache)Tcl_Alloc(sizeof(*cache));\n\n    cache->tkwin = NULL;\t/* initialized later */\n    cache->interp = interp;\n    Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&cache->namedColors, TCL_STRING_KEYS);\n\n    return cache;\n}\n\n/*\n * Ttk_ClearCache --\n *\tRelease references to all cached resources.\n */\nstatic void Ttk_ClearCache(Ttk_ResourceCache cache)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n\n    /*\n     * Free fonts:\n     */\n    entryPtr = Tcl_FirstHashEntry(&cache->fontTable, &search);\n    while (entryPtr != NULL) {\n#if !NEED_EXTRA_INFO\n\tTcl_Obj *fontObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tif (fontObj) {\n\t    Tk_FreeFontFromObj(cache->tkwin, fontObj);\n\t    Tcl_DecrRefCount(fontObj);\n\t}\n#else\n\tTtk_Cached *cachedPtr = (Ttk_Cached *)Tcl_GetHashValue(entryPtr);\n\tif (cachedPtr) {\n\t    TkWindow fakeWin;\n\t    Tcl_Obj *fontObj = cachedPtr->objPtr;\n\t    fakeWin = *((TkWindow *) cache->tkwin);\n\t    fakeWin.display = cachedPtr->display;\n\t    fakeWin.screenNum = cachedPtr->screenNum;\n\t    fakeWin.visual = cachedPtr->visual;\n\t    fakeWin.atts.colormap = cachedPtr->colormap;\n\t    Tk_FreeFontFromObj((Tk_Window) &fakeWin, fontObj);\n\t    Tcl_DecrRefCount(fontObj);\n\t    Tcl_Free(cachedPtr);\n\t}\n#endif\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&cache->fontTable);\n    Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);\n\n    /*\n     * Free colors:\n     */\n    entryPtr = Tcl_FirstHashEntry(&cache->colorTable, &search);\n    while (entryPtr != NULL) {\n#if !NEED_EXTRA_INFO\n\tTcl_Obj *colorObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tif (colorObj) {\n\t    Tk_FreeColorFromObj(cache->tkwin, colorObj);\n\t    Tcl_DecrRefCount(colorObj);\n\t}\n#else\n\tTtk_Cached *cachedPtr = (Ttk_Cached *)Tcl_GetHashValue(entryPtr);\n\tif (cachedPtr) {\n\t    TkWindow fakeWin;\n\t    Tcl_Obj *colorObj = cachedPtr->objPtr;\n\t    fakeWin = *((TkWindow *) cache->tkwin);\n\t    fakeWin.display = cachedPtr->display;\n\t    fakeWin.screenNum = cachedPtr->screenNum;\n\t    fakeWin.visual = cachedPtr->visual;\n\t    fakeWin.atts.colormap = cachedPtr->colormap;\n\t    Tk_FreeColorFromObj((Tk_Window) &fakeWin, colorObj);\n\t    Tcl_DecrRefCount(colorObj);\n\t    Tcl_Free(cachedPtr);\n\t}\n#endif\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&cache->colorTable);\n    Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);\n\n    /*\n     * Free borders:\n     */\n    entryPtr = Tcl_FirstHashEntry(&cache->borderTable, &search);\n    while (entryPtr != NULL) {\n#if !NEED_EXTRA_INFO\n\tTcl_Obj *borderObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tif (borderObj) {\n\t    Tk_Free3DBorderFromObj(cache->tkwin, borderObj);\n\t    Tcl_DecrRefCount(borderObj);\n\t}\n#else\n\tTtk_Cached *cachedPtr = (Ttk_Cached *)Tcl_GetHashValue(entryPtr);\n\tif (cachedPtr) {\n\t    TkWindow fakeWin;\n\t    Tcl_Obj *borderObj = cachedPtr->objPtr;\n\t    fakeWin = *((TkWindow *) cache->tkwin);\n\t    fakeWin.display = cachedPtr->display;\n\t    fakeWin.screenNum = cachedPtr->screenNum;\n\t    fakeWin.visual = cachedPtr->visual;\n\t    fakeWin.atts.colormap = cachedPtr->colormap;\n\t    Tk_Free3DBorderFromObj((Tk_Window) &fakeWin, borderObj);\n\t    Tcl_DecrRefCount(borderObj);\n\t    Tcl_Free(cachedPtr);\n\t}\n#endif\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&cache->borderTable);\n    Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);\n\n    /*\n     * Free images:\n     */\n    entryPtr = Tcl_FirstHashEntry(&cache->imageTable, &search);\n    while (entryPtr != NULL) {\n\tTk_Image image = (Tk_Image)Tcl_GetHashValue(entryPtr);\n\tif (image) {\n\t    Tk_FreeImage(image);\n\t}\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&cache->imageTable);\n    Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);\n\n    return;\n}\n\n/*\n * Ttk_FreeResourceCache --\n *\tRelease references to all cached resources, delete the cache.\n */\n\nvoid Ttk_FreeResourceCache(Ttk_ResourceCache cache)\n{\n    Tcl_HashEntry *entryPtr;\n    Tcl_HashSearch search;\n\n    Ttk_ClearCache(cache);\n\n    Tcl_DeleteHashTable(&cache->colorTable);\n    Tcl_DeleteHashTable(&cache->fontTable);\n    Tcl_DeleteHashTable(&cache->imageTable);\n\n    /*\n     * Free named colors:\n     */\n    entryPtr = Tcl_FirstHashEntry(&cache->namedColors, &search);\n    while (entryPtr != NULL) {\n\tTcl_Obj *colorNameObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tTcl_DecrRefCount(colorNameObj);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&cache->namedColors);\n\n    Tcl_Free(cache);\n}\n\n/*\n * CacheWinEventHandler --\n *\tDetect when the cache window is destroyed, clear cache.\n */\nstatic void CacheWinEventHandler(void *clientData, XEvent *eventPtr)\n{\n    Ttk_ResourceCache cache = (Ttk_ResourceCache)clientData;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n    Tk_DeleteEventHandler(cache->tkwin, StructureNotifyMask,\n\t    CacheWinEventHandler, clientData);\n    Ttk_ClearCache(cache);\n    cache->tkwin = NULL;\n}\n\n/*\n * InitCacheWindow --\n *\tSpecify the cache window if not already set.\n */\nstatic void InitCacheWindow(Ttk_ResourceCache cache)\n{\n    if (cache->tkwin == NULL) {\n\tcache->tkwin = Tk_MainWindow(cache->interp);\n\tTk_CreateEventHandler(cache->tkwin, StructureNotifyMask,\n\t\tCacheWinEventHandler, cache);\n    }\n}\n\n/*\n * Ttk_RegisterNamedColor --\n *\tSpecify an RGB triplet as a named color.\n *\tOverrides any previous named color specification.\n */\nvoid Ttk_RegisterNamedColor(\n    Ttk_ResourceCache cache,\n    const char *colorName,\n    XColor *colorPtr)\n{\n    int newEntry;\n    Tcl_HashEntry *entryPtr;\n    char nameBuf[14];\n    Tcl_Obj *colorNameObj;\n\n    snprintf(nameBuf, sizeof(nameBuf), \"#%04X%04X%04X\",\n\t    colorPtr->red, colorPtr->green, colorPtr->blue);\n    colorNameObj = Tcl_NewStringObj(nameBuf, -1);\n    Tcl_IncrRefCount(colorNameObj);\n\n    entryPtr = Tcl_CreateHashEntry(&cache->namedColors, colorName, &newEntry);\n    if (!newEntry) {\n\tTcl_Obj *oldColor = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tTcl_DecrRefCount(oldColor);\n    }\n\n    Tcl_SetHashValue(entryPtr, colorNameObj);\n}\n\n/*\n * CheckNamedColor(objPtr) --\n *\tIf objPtr is a registered color name, return a Tcl_Obj *\n *\tcontaining the registered color value specification.\n *\tOtherwise, return the input argument.\n */\nstatic Tcl_Obj *CheckNamedColor(Ttk_ResourceCache cache, Tcl_Obj *objPtr)\n{\n    Tcl_HashEntry *entryPtr =\n\t    Tcl_FindHashEntry(&cache->namedColors, Tcl_GetString(objPtr));\n    if (entryPtr) {\t/* Use named color instead */\n\tobjPtr = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n    }\n    return objPtr;\n}\n\n/*\n * Template for allocation routines:\n */\ntypedef void *(*Allocator)(Tcl_Interp *, Tk_Window, Tcl_Obj *);\n\nstatic void *AllocFont(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) {\n\treturn Tk_AllocFontFromObj(interp, tkwin, objPtr);\n}\nstatic void *AllocColor(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) {\n\treturn Tk_AllocColorFromObj(interp, tkwin, objPtr);\n}\nstatic void *AllocBorder(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) {\n\treturn Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr);\n}\n\nstatic Tcl_Obj *Ttk_Use(\n    Tcl_Interp *interp,\n    Tcl_HashTable *table,\n    Allocator allocate,\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr)\n{\n    int newEntry;\n    Tcl_HashEntry *entryPtr;\n    Tcl_Obj *cacheObj;\n#if !NEED_EXTRA_INFO\n    entryPtr = Tcl_CreateHashEntry(table, Tcl_GetString(objPtr), &newEntry);\n#else\n    Tcl_DString ds;\n    char buffer[64];\n\n    Tcl_DStringInit(&ds);\n    Tcl_DStringAppend(&ds, Tcl_GetString(objPtr), -1);\n    snprintf(buffer, 64, \",%d,%lu,%lu\", ConnectionNumber(Tk_Display(tkwin)),\n\t    Tk_Visual(tkwin)->visualid, (unsigned long)Tk_Colormap(tkwin));\n    Tcl_DStringAppend(&ds, buffer, -1);\n    entryPtr = Tcl_CreateHashEntry(table, Tcl_DStringValue(&ds), &newEntry);\n    Tcl_DStringFree(&ds);\n#endif\n\n    if (!newEntry) {\n#if !NEED_EXTRA_INFO\n\treturn (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n#else\n\tTtk_Cached *cachedPtr = (Ttk_Cached *)Tcl_GetHashValue(entryPtr);\n\treturn cachedPtr ? cachedPtr->objPtr : NULL;\n#endif\n    }\n\n    cacheObj = Tcl_DuplicateObj(objPtr);\n    Tcl_IncrRefCount(cacheObj);\n\n    if (allocate(interp, tkwin, cacheObj)) {\n#if !NEED_EXTRA_INFO\n\tTcl_SetHashValue(entryPtr, cacheObj);\n#else\n\tTtk_Cached *cachedPtr = (Ttk_Cached *)Tcl_Alloc(sizeof(*cachedPtr));\n\tcachedPtr->objPtr = cacheObj;\n\tcachedPtr->display = Tk_Display(tkwin);\n\tcachedPtr->screenNum = Tk_ScreenNumber(tkwin);\n\tcachedPtr->visual = Tk_Visual(tkwin);\n\tcachedPtr->colormap = Tk_Colormap(tkwin);\n\tTcl_SetHashValue(entryPtr, cachedPtr);\n#endif\n\treturn cacheObj;\n    } else {\n\tTcl_DecrRefCount(cacheObj);\n\tTcl_SetHashValue(entryPtr, NULL);\n\tTcl_BackgroundException(interp, TCL_ERROR);\n\treturn NULL;\n    }\n}\n\n/*\n * Ttk_UseFont --\n *\tAcquire a font from the cache.\n */\nTcl_Obj *Ttk_UseFont(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)\n{\n    InitCacheWindow(cache);\n    return Ttk_Use(cache->interp,\n\t&cache->fontTable, AllocFont, tkwin, objPtr);\n}\n\n/*\n * Ttk_UseColor --\n *\tAcquire a color from the cache.\n */\nTcl_Obj *Ttk_UseColor(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)\n{\n    objPtr = CheckNamedColor(cache, objPtr);\n    InitCacheWindow(cache);\n    return Ttk_Use(cache->interp,\n\t&cache->colorTable, AllocColor, tkwin, objPtr);\n}\n\n/*\n * Ttk_UseBorder --\n *\tAcquire a Tk_3DBorder from the cache.\n */\nTcl_Obj *Ttk_UseBorder(\n    Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)\n{\n    objPtr = CheckNamedColor(cache, objPtr);\n    InitCacheWindow(cache);\n    return Ttk_Use(cache->interp,\n\t&cache->borderTable, AllocBorder, tkwin, objPtr);\n}\n\n/* NullImageChanged --\n *\tTk_ImageChangedProc for Ttk_UseImage\n */\n\nstatic void NullImageChanged(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{ /* No-op */\n}\n\n/*\n * Ttk_UseImage --\n *\tAcquire a Tk_Image from the cache.\n */\nTk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)\n{\n    const char *imageName = Tcl_GetString(objPtr);\n    int newEntry;\n    Tcl_HashEntry *entryPtr;\n    Tk_Image image;\n\n    InitCacheWindow(cache);\n#if !NEED_EXTRA_INFO\n    entryPtr = Tcl_CreateHashEntry(&cache->imageTable, imageName, &newEntry);\n#else\n    Tcl_DString ds;\n    char buffer[64];\n\n    Tcl_DStringInit(&ds);\n    Tcl_DStringAppend(&ds, imageName, -1);\n    snprintf(buffer, 64, \",%d,%lu,%lu\", ConnectionNumber(Tk_Display(tkwin)),\n\tTk_Visual(tkwin)->visualid, (unsigned long)Tk_Colormap(tkwin));\n    Tcl_DStringAppend(&ds, buffer, -1);\n    entryPtr = Tcl_CreateHashEntry(&cache->imageTable,\n\tTcl_DStringValue(&ds), &newEntry);\n    Tcl_DStringFree(&ds);\n#endif\n\n    if (!newEntry) {\n\treturn (Tk_Image)Tcl_GetHashValue(entryPtr);\n    }\n\n    image = Tk_GetImage(cache->interp, tkwin, imageName, NullImageChanged,0);\n    Tcl_SetHashValue(entryPtr, image);\n\n    if (!image) {\n\tTcl_BackgroundException(cache->interp, TCL_ERROR);\n    }\n\n    return image;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkClamTheme.c",
    "content": "/*\n * Copyright © 2004 Joe English\n *\n * \"clam\" theme; inspired by the XFCE family of Gnome themes.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n\n/*\n * Under windows, the Tk-provided XDrawLine and XDrawArc have an\n * off-by-one error in the end point. This is especially apparent with this\n * theme. Defining this macro as true handles this case.\n */\n#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)\n  #define WIN32_XDRAWLINE_HACK 1\n#else\n  #define WIN32_XDRAWLINE_HACK 0\n#endif\n\n#define STR(x) StR(x)\n#define StR(x) #x\n\n#define SCROLLBAR_THICKNESS 14\n\n#define FRAME_COLOR\t\"#dcdad5\"\n#define LIGHT_COLOR\t\"#ffffff\"\n#define DARK_COLOR\t\"#cfcdc8\"\n#define DARKER_COLOR\t\"#bab5ab\"\n#define DARKEST_COLOR\t\"#9e9a91\"\n\n/*------------------------------------------------------------------------\n * +++ Utilities.\n */\n\nstatic GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d)\n{\n    GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d);\n\n#ifdef MAC_OSX_TK\n    /*\n     * Workaround for Tk bug under Aqua where the default line width is 0.\n     */\n    Display *display = Tk_Display(tkwin);\n    unsigned long mask = 0ul;\n    XGCValues gcValues;\n\n    gcValues.line_width = 1;\n    mask = GCLineWidth;\n\n    XChangeGC(display, gc, mask, &gcValues);\n#endif\n\n    return gc;\n}\n\nstatic void DrawSmoothBorder(\n    Tk_Window tkwin, Drawable d, Ttk_Box b,\n    Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj)\n{\n    Display *display = Tk_Display(tkwin);\n    int x1 = b.x, x2 = b.x + b.width - 1;\n    int y1 = b.y, y2 = b.y + b.height - 1;\n    const int w = WIN32_XDRAWLINE_HACK;\n    GC gc;\n\n    if (   outerColorObj\n\t&& (gc=Ttk_GCForColor(tkwin,outerColorObj,d)))\n    {\n\tXDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);\t\t/* N */\n\tXDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2);\t\t/* S */\n\tXDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w);\t\t/* W */\n\tXDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w);\t\t/* E */\n    }\n\n    if (   upperColorObj\n\t&& (gc=Ttk_GCForColor(tkwin,upperColorObj,d)))\n    {\n\tXDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);\t/* N */\n\tXDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1);\t\t/* W */\n    }\n\n    if (   lowerColorObj\n\t&& (gc=Ttk_GCForColor(tkwin,lowerColorObj,d)))\n    {\n\tXDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1);\t/* S */\n\tXDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w);\t/* E */\n    }\n}\n\nstatic GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj)\n{\n    Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj);\n    return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC);\n}\n\n/*------------------------------------------------------------------------\n * +++ Border element.\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderColorObj;\n    Tcl_Obj\t*lightColorObj;\n    Tcl_Obj\t*darkColorObj;\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*borderWidthObj;\t/* See <<NOTE-BORDERWIDTH>> */\n} BorderElement;\n\nstatic const Ttk_ElementOptionSpec BorderElementOptions[] = {\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(BorderElement,borderColorObj), DARKEST_COLOR },\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\toffsetof(BorderElement,lightColorObj), LIGHT_COLOR },\n    { \"-darkcolor\", TK_OPTION_COLOR,\n\toffsetof(BorderElement,darkColorObj), DARK_COLOR },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(BorderElement,reliefObj), \"flat\" },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(BorderElement,borderWidthObj), \"2\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:\n * in this theme, borders are always exactly 2 pixels thick.\n * With -borderwidth 0, border is not drawn at all;\n * otherwise a 2-pixel border is used.  For -borderwidth > 2,\n * the excess is used as padding.\n */\n\nstatic void BorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    BorderElement *border = (BorderElement*)elementRecord;\n    int borderWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);\n    if (borderWidth == 1) ++borderWidth;\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void BorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    BorderElement *border = (BorderElement *)elementRecord;\n    int relief = TK_RELIEF_FLAT;\n    int borderWidth = 2;\n    Tcl_Obj *outer = 0, *upper = 0, *lower = 0;\n\n    Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);\n    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);\n\n    if (borderWidth == 0) return;\n\n    switch (relief) {\n\tcase TK_RELIEF_GROOVE :\n\tcase TK_RELIEF_RIDGE :\n\tcase TK_RELIEF_RAISED :\n\t    outer = border->borderColorObj;\n\t    upper = border->lightColorObj;\n\t    lower = border->darkColorObj;\n\t    break;\n\tcase TK_RELIEF_SUNKEN :\n\t    outer = border->borderColorObj;\n\t    upper = border->darkColorObj;\n\t    lower = border->lightColorObj;\n\t    break;\n\tcase TK_RELIEF_FLAT :\n\t    outer = upper = lower = 0;\n\t    break;\n\tcase TK_RELIEF_SOLID :\n\t    outer = upper = lower = border->borderColorObj;\n\t    break;\n    }\n\n    DrawSmoothBorder(tkwin, d, b, outer, upper, lower);\n}\n\nstatic const Ttk_ElementSpec BorderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BorderElement),\n    BorderElementOptions,\n    BorderElementSize,\n    BorderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Field element.\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderColorObj;\n    Tcl_Obj\t*lightColorObj;\n    Tcl_Obj\t*backgroundObj;\n} FieldElement;\n\nstatic const Ttk_ElementOptionSpec FieldElementOptions[] = {\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(FieldElement,borderColorObj), DARKEST_COLOR },\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\toffsetof(FieldElement,lightColorObj), LIGHT_COLOR },\n    { \"-fieldbackground\", TK_OPTION_BORDER,\n\toffsetof(FieldElement,backgroundObj), \"white\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void FieldElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_UniformPadding(2);\n}\n\nstatic void FieldElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);\n    Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));\n    Tcl_Obj *outer = field->borderColorObj,\n\t    *inner = field->lightColorObj;\n\n    DrawSmoothBorder(tkwin, d, b, outer, inner, inner);\n    Tk_Fill3DRectangle(\n\ttkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);\n}\n\nstatic const Ttk_ElementSpec FieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    FieldElementSize,\n    FieldElementDraw\n};\n\n/*\n * Modified field element for comboboxes:\n *\tRight edge is expanded to overlap the dropdown button.\n */\nstatic void ComboboxFieldElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);\n\n    ++b.width;\n    FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);\n\n    XDrawLine(Tk_Display(tkwin), d, gc,\n\t    b.x + b.width - 1, b.y,\n\t    b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);\n}\n\nstatic const Ttk_ElementSpec ComboboxFieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    FieldElementSize,\n    ComboboxFieldElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Indicator elements for check and radio buttons.\n */\n\n/*\n * Indicator image descriptor:\n */\ntypedef struct {\n    int width;\t\t\t\t/* unscaled width */\n    int height;\t\t\t\t/* unscaled height */\n    const char *const offDataPtr;\n    const char *const onDataPtr;\n} IndicatorSpec;\n\nstatic const char checkbtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v16h1v-15h15v-1z' fill='#9e9a91'/>\\n\\\n     <path d='m15 1v14h-14v1h15v-15z' fill='#cfcdc8'/>\\n\\\n     <rect x='1' y='1' width='14' height='14' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char checkbtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v16h1v-15h15v-1z' fill='#9e9a91'/>\\n\\\n     <path d='m15 1v14h-14v1h15v-15z' fill='#cfcdc8'/>\\n\\\n     <rect x='1' y='1' width='14' height='14' fill='#ffffff'/>\\n\\\n     <path d='m5 5 6 6m0-6-6 6' fill='none' stroke='#000000' stroke-linecap='round' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec checkbutton_spec = {\n    16, 16,\n    checkbtnOffData,\n    checkbtnOnData\n};\n\nstatic const char radiobtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradient' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#9e9a91' offset='0'/>\\n\\\n       <stop stop-color='#cfcdc8' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradient)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradient' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#9e9a91' offset='0'/>\\n\\\n       <stop stop-color='#cfcdc8' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradient)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='#ffffff'/>\\n\\\n     <circle cx='8' cy='8' r='4' fill='#000000'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec radiobutton_spec = {\n    16, 16,\n    radiobtnOffData,\n    radiobtnOnData\n};\n\ntypedef struct {\n    Tcl_Obj *marginObj;\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *upperColorObj;\n    Tcl_Obj *lowerColorObj;\n} IndicatorElement;\n\nstatic const Ttk_ElementOptionSpec IndicatorElementOptions[] = {\n    { \"-indicatormargin\", TK_OPTION_STRING,\n\toffsetof(IndicatorElement,marginObj), \"1\" },\n    { \"-indicatorbackground\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,backgroundObj), \"white\" },\n    { \"-indicatorforeground\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,foregroundObj), \"black\" },\n    { \"-upperbordercolor\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,upperColorObj), DARKEST_COLOR },\n    { \"-lowerbordercolor\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,lowerColorObj), DARK_COLOR },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void IndicatorElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    *widthPtr = (int)(spec->width * scalingLevel) + Ttk_PaddingWidth(margins);\n    *heightPtr = (int)(spec->height * scalingLevel) + Ttk_PaddingHeight(margins);\n}\n\nstatic void ColorToStr(\n    const XColor *colorPtr, char *colorStr)\t/* in the format \"RRGGBB\" */\n{\n    snprintf(colorStr, 7, \"%02x%02x%02x\",\n\t     colorPtr->red >> 8, colorPtr->green >> 8, colorPtr->blue >> 8);\n}\n\nstatic void ImageChanged(\t\t/* to be passed to Tk_GetImage() */\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n}\n\nstatic void IndicatorElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding padding;\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int width = (int)(spec->width * scalingLevel);\n    int height = (int)(spec->height * scalingLevel);\n\n    char upperBdColorStr[7], lowerBdColorStr[7], bgColorStr[7], fgColorStr[7];\n    unsigned int selected = (state & TTK_STATE_SELECTED);\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[60];\n    Tk_Image img;\n\n    const char *svgDataPtr;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *upperBdColorPtr, *lowerBdColorPtr, *bgColorPtr, *fgColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);\n    b = Ttk_PadBox(b, padding);\n\n#if 0\n    /*\n     * Sanity check -- not needed and no longer used\n     */\n    if (   b.x < 0\n\t|| b.y < 0\n\t|| Tk_Width(tkwin) < b.x + width\n\t|| Tk_Height(tkwin) < b.y + height)\n    {\n\t/* Oops!  Not enough room to display the image.\n\t * Don't draw anything.\n\t */\n\treturn;\n    }\n#endif\n\n    /*\n     * Construct the color strings upperBdColorStr, lowerBdColorStr,\n     * bgColorStr, and fgColorStr\n     */\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->upperColorObj),\n\t       upperBdColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->lowerColorObj),\n\t       lowerBdColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->backgroundObj),\n\t       bgColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->foregroundObj),\n\t       fgColorStr);\n\n    /*\n     * Check whether there is an SVG image of this size for the indicator's\n     * type (0 = checkbtn, 1 = radiobtn) and these color strings\n     */\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::indicator_clam%d_%d_%s_%s_%s_%s\",\n\t     width, spec->offDataPtr == radiobtnOffData,\n\t     upperBdColorStr, lowerBdColorStr, bgColorStr,\n\t     selected ? fgColorStr : \"XXXXXX\");\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Determine the SVG data to use for the photo image\n\t */\n\tsvgDataPtr = (selected ? spec->onDataPtr : spec->offDataPtr);\n\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\n\tupperBdColorPtr = strstr(svgDataCopy, \"9e9a91\");\n\tlowerBdColorPtr = strstr(svgDataCopy, \"cfcdc8\");\n\tbgColorPtr =\t  strstr(svgDataCopy, \"ffffff\");\n\tfgColorPtr =\t  strstr(svgDataCopy, \"000000\");\n\n\tassert(upperBdColorPtr);\n\tassert(lowerBdColorPtr);\n\tassert(bgColorPtr);\n\n\tmemcpy(upperBdColorPtr, upperBdColorStr, 6);\n\tmemcpy(lowerBdColorPtr, lowerBdColorStr, 6);\n\tmemcpy(bgColorPtr, bgColorStr, 6);\n\tif (fgColorPtr != NULL) {\n\t    memcpy(fgColorPtr, fgColorStr, 6);\n\t}\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Display the image\n     */\n    Tk_RedrawImage(img, 0, 0, width, height, d, b.x, b.y);\n    Tk_FreeImage(img);\n}\n\nstatic const Ttk_ElementSpec IndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(IndicatorElement),\n    IndicatorElementOptions,\n    IndicatorElementSize,\n    IndicatorElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Grips.\n *\n * TODO: factor this with ThumbElementDraw\n */\n\ntypedef struct {\n    Tcl_Obj\t*lightColorObj;\n    Tcl_Obj\t*borderColorObj;\n    Tcl_Obj\t*gripSizeObj;\n} GripElement;\n\nstatic const Ttk_ElementOptionSpec GripElementOptions[] = {\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\toffsetof(GripElement,lightColorObj), LIGHT_COLOR },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(GripElement,borderColorObj), DARKEST_COLOR },\n    { \"-gripsize\", TK_OPTION_PIXELS,\n\toffsetof(GripElement,gripSizeObj), \"7.5p\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void GripElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n    GripElement *grip = (GripElement *)elementRecord;\n    int gripSize = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*widthPtr = gripSize;\n    } else {\n\t*heightPtr = gripSize;\n    }\n}\n\nstatic void GripElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    const int w = WIN32_XDRAWLINE_HACK;\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n    GripElement *grip = (GripElement *)elementRecord;\n    GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);\n    GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);\n    int gripPad = 1, gripSize = 0;\n    int i;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tint x = b.x + (b.width - gripSize) / 2;\n\tint y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;\n\tfor (i=0; i<gripSize; ++i) {\n\t    XDrawLine(Tk_Display(tkwin), d, (i&1)?lightGC:darkGC, x,y1, x,y2);\n\t    ++x;\n\t}\n    } else {\n\tint y = b.y + (b.height - gripSize) / 2;\n\tint x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;\n\tfor (i=0; i<gripSize; ++i) {\n\t    XDrawLine(Tk_Display(tkwin), d, (i&1)?lightGC:darkGC, x1,y, x2,y);\n\t    ++y;\n\t}\n    }\n}\n\nstatic const Ttk_ElementSpec GripElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(GripElement),\n    GripElementOptions,\n    GripElementSize,\n    GripElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Scrollbar elements: trough, arrows, thumb.\n *\n * Notice that the trough element has 0 internal padding;\n * that way the thumb and arrow borders overlap the trough.\n */\n\ntypedef struct { /* Common element record for scrollbar elements */\n    Tcl_Obj\t*orientObj;\n    Tcl_Obj\t*backgroundObj;\n    Tcl_Obj\t*borderColorObj;\n    Tcl_Obj\t*troughColorObj;\n    Tcl_Obj\t*lightColorObj;\n    Tcl_Obj\t*darkColorObj;\n    Tcl_Obj\t*arrowColorObj;\n    Tcl_Obj\t*arrowSizeObj;\n    Tcl_Obj\t*gripSizeObj;\n    Tcl_Obj\t*sliderlengthObj;\n} ScrollbarElement;\n\nstatic const Ttk_ElementOptionSpec ScrollbarElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY,\n\toffsetof(ScrollbarElement, orientObj), \"horizontal\" },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(ScrollbarElement,backgroundObj), FRAME_COLOR },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(ScrollbarElement,borderColorObj), DARKEST_COLOR },\n    { \"-troughcolor\", TK_OPTION_COLOR,\n\toffsetof(ScrollbarElement,troughColorObj), DARKER_COLOR },\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\toffsetof(ScrollbarElement,lightColorObj), LIGHT_COLOR },\n    { \"-darkcolor\", TK_OPTION_COLOR,\n\toffsetof(ScrollbarElement,darkColorObj), DARK_COLOR },\n    { \"-arrowcolor\", TK_OPTION_COLOR,\n\toffsetof(ScrollbarElement,arrowColorObj), \"#000000\" },\n    { \"-arrowsize\", TK_OPTION_PIXELS,\n\toffsetof(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },\n    { \"-gripsize\", TK_OPTION_PIXELS,\n\toffsetof(ScrollbarElement,gripSizeObj), \"7.5p\" },\n    { \"-sliderlength\", TK_OPTION_PIXELS,\n\toffsetof(ScrollbarElement,sliderlengthObj), \"30\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TroughElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);\n    GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);\n\n    XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, (unsigned)b.width-1, (unsigned)b.height-1);\n    XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, (unsigned)b.width-1, (unsigned)b.height-1);\n}\n\nstatic const Ttk_ElementSpec TroughElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    TtkNullElementSize,\n    TroughElementDraw\n};\n\nstatic void ThumbElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    int size = SCROLLBAR_THICKNESS;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->arrowSizeObj, &size);\n    *widthPtr = *heightPtr = size;\n}\n\nstatic void ThumbElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    int gripSize = 0;\n    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;\n    GC lightGC, darkGC;\n    int x1, y1, x2, y2, dx, dy, i;\n    const int w = WIN32_XDRAWLINE_HACK;\n\n    DrawSmoothBorder(tkwin, d, b,\n\tsb->borderColorObj, sb->lightColorObj, sb->darkColorObj);\n    XFillRectangle(\n\tTk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),\n\tb.x+2, b.y+2, (unsigned)b.width-4, (unsigned)b.height-4);\n\n    /*\n     * Draw grip:\n     */\n    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->gripSizeObj, &gripSize);\n    lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);\n    darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tdx = 1; dy = 0;\n\tx1 = x2 = b.x + (b.width - gripSize) / 2;\n\ty1 = b.y + 2;\n\ty2 = b.y + b.height - 3 + w;\n    } else {\n\tdx = 0; dy = 1;\n\ty1 = y2 = b.y + (b.height - gripSize) / 2;\n\tx1 = b.x + 2;\n\tx2 = b.x + b.width - 3 + w;\n    }\n\n    for (i=0; i<gripSize; ++i) {\n\tXDrawLine(Tk_Display(tkwin), d, (i&1)?lightGC:darkGC, x1,y1, x2,y2);\n\tx1 += dx; x2 += dx; y1 += dy; y2 += dy;\n\n    }\n}\n\nstatic const Ttk_ElementSpec ThumbElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    ThumbElementSize,\n    ThumbElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Slider element.\n */\nstatic void SliderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    int length, thickness;\n    Ttk_Orient orient;\n\n    length = thickness = SCROLLBAR_THICKNESS;\n    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->arrowSizeObj, &thickness);\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);\n    if (orient == TTK_ORIENT_VERTICAL) {\n\t*heightPtr = length;\n\t*widthPtr = thickness;\n    } else {\n\t*heightPtr = thickness;\n\t*widthPtr = length;\n    }\n}\n\nstatic const Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    SliderElementSize,\n    ThumbElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Progress bar element\n */\nstatic void PbarElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)\n{\n    SliderElementSize(clientData, elementRecord, tkwin,\n\t    widthPtr, heightPtr, paddingPtr);\n    *paddingPtr = Ttk_UniformPadding(2);\n    *widthPtr += 4;\n    *heightPtr += 4;\n}\n\nstatic void PbarElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n\n    b = Ttk_PadBox(b, Ttk_UniformPadding(2));\n    if (b.width > 4 && b.height > 4) {\n\tDrawSmoothBorder(tkwin, d, b,\n\t    sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);\n\tXFillRectangle(Tk_Display(tkwin), d,\n\t    BackgroundGC(tkwin, sb->backgroundObj),\n\t    b.x+2, b.y+2, (unsigned)b.width-4, (unsigned)b.height-4);\n    }\n}\n\nstatic const Ttk_ElementSpec PbarElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    PbarElementSize,\n    PbarElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Scrollbar arrows.\n */\nstatic void ArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding = Ttk_UniformPadding((short)round(3 * scalingLevel));\n    int size = SCROLLBAR_THICKNESS;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->arrowSizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n    if (*widthPtr < *heightPtr) {\n\t*widthPtr = *heightPtr;\n    } else {\n\t*heightPtr = *widthPtr;\n    }\n}\n\nstatic void ArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding = Ttk_UniformPadding((short)round(3 * scalingLevel));\n    int cx, cy;\n    GC gc = Ttk_GCForColor(tkwin, sb->arrowColorObj, d);\n\n    DrawSmoothBorder(tkwin, d, b,\n\tsb->borderColorObj, sb->lightColorObj, sb->darkColorObj);\n\n    XFillRectangle(\n\tTk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),\n\tb.x+2, b.y+2, (unsigned)b.width-4, (unsigned)b.height-4);\n\n    b = Ttk_PadBox(b, padding);\n\n    switch (direction) {\n\tcase ARROW_UP:\n\tcase ARROW_DOWN:\n\t    TtkArrowSize(b.width/2, direction, &cx, &cy);\n\t    if ((b.height - cy) % 2 == 1) {\n\t\t++cy;\n\t    }\n\t    break;\n\tcase ARROW_LEFT:\n\tcase ARROW_RIGHT:\n\t    TtkArrowSize(b.height/2, direction, &cx, &cy);\n\t    if ((b.width - cx) % 2 == 1) {\n\t\t++cx;\n\t    }\n\t    break;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);\n}\n\nstatic const Ttk_ElementSpec ArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    ArrowElementSize,\n    ArrowElementDraw\n};\n\n/*\n * Modified arrow element for spinboxes:\n *\tThe width and height are different.\n */\nstatic void SpinboxArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding = Ttk_UniformPadding((short)round(3 * scalingLevel));\n    int size = 10;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sb->arrowSizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    size += 2 * round(scalingLevel);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n}\n\nstatic const Ttk_ElementSpec SpinboxArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    SpinboxArrowElementSize,\n    ArrowElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Notebook elements.\n *\n * Note: Tabs, except for the rightmost, overlap the neighbor to\n * their right by one pixel.\n */\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *borderColorObj;\n    Tcl_Obj *lightColorObj;\n    Tcl_Obj *darkColorObj;\n} NotebookElement;\n\nstatic const Ttk_ElementOptionSpec NotebookElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(NotebookElement,backgroundObj), FRAME_COLOR },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(NotebookElement,borderColorObj), DARKEST_COLOR },\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\toffsetof(NotebookElement,lightColorObj), LIGHT_COLOR },\n    { \"-darkcolor\", TK_OPTION_COLOR,\n\toffsetof(NotebookElement,darkColorObj), DARK_COLOR },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TabElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    Ttk_PositionSpec nbTabPlacementStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    int borderWidth = 2;\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlacementStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n    switch (nbTabPlacementStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    paddingPtr->bottom = 0;\n\t    break;\n\tcase TTK_STICK_N:\n\t    paddingPtr->top = 0;\n\t    break;\n\tcase TTK_STICK_E:\n\t    paddingPtr->right = 0;\n\t    break;\n\tcase TTK_STICK_W:\n\t    paddingPtr->left = 0;\n\t    break;\n    }\n}\n\nstatic void TabElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    Ttk_PositionSpec nbTabPosStickBit = TTK_STICK_W;\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    int borderWidth = 2, delta = 0;\n    NotebookElement *tab = (NotebookElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);\n    Display *display = Tk_Display(tkwin);\n    int x1, y1, x2, y2;\n    GC gc;\n    const int w = WIN32_XDRAWLINE_HACK;\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPosStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPosition & 0x0f);\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    if (state & TTK_STATE_SELECTED) {\n\tdelta = borderWidth;\n    }\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    if (state & TTK_STATE_LAST) {\t\t/* rightmost tab */\n\t\t--b.width;\n\t    }\n\n\t    Tk_Fill3DRectangle(tkwin, d, border,\n\t\tb.x+2, b.y+2, b.width-1, b.height-2+delta,\n\t\tborderWidth, TK_RELIEF_FLAT);\n\n\t    x1 = b.x;\t\ty1 = b.y;\t\t/* top left */\n\t    x2 = b.x + b.width; y2 = b.y + b.height-1;\t/* bottom right */\n\n\t    gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d);\n\t    XDrawLine(display, d, gc, x1, y1+1, x1, y2+1+w);\n\t    XDrawLine(display, d, gc, x1+1, y1, x2-1+w, y1);\n\n\t    if ((state & TTK_STATE_LAST) && nbTabPosStickBit == TTK_STICK_E) {\n\t\tXDrawLine(display, d, gc, x2, y1+1, x2, y2+2+w);\n\t    } else {\n\t\tXDrawLine(display, d, gc, x2, y1+1, x2, y2+1+w);\n\t    }\n\n\t    gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d);\n\t    XDrawLine(display, d, gc, x1+1, y1+1, x1+1, y2+delta+w);\n\t    XDrawLine(display, d, gc, x1+1, y1+1, x2-1+w, y1+1);\n\t    break;\n\n\tcase TTK_STICK_N:\n\t    if (state & TTK_STATE_LAST) {\t\t/* rightmost tab */\n\t\t--b.width;\n\t    }\n\n\t    Tk_Fill3DRectangle(tkwin, d, border,\n\t\tb.x+2, b.y-delta, b.width-1, b.height-2+delta,\n\t\tborderWidth, TK_RELIEF_FLAT);\n\n\t    x1 = b.x;\t\ty1 = b.y + b.height-1;\t/* bottom left */\n\t    x2 = b.x + b.width; y2 = b.y;\t\t/* top right */\n\n\t    gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d);\n\t    XDrawLine(display, d, gc, x1, y1-1, x1, y2-1-w);\n\t    XDrawLine(display, d, gc, x1+1, y1, x2-1+w, y1);\n\n\t    if ((state & TTK_STATE_LAST) && nbTabPosStickBit == TTK_STICK_E) {\n\t\tXDrawLine(display, d, gc, x2, y1-1, x2, y2-2-w);\n\t    } else {\n\t\tXDrawLine(display, d, gc, x2, y1-1, x2, y2-1-w);\n\t    }\n\n\t    gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d);\n\t    XDrawLine(display, d, gc, x1+1, y1-1, x1+1, y2-delta-w);\n\t    XDrawLine(display, d, gc, x1+1, y1-1, x2-1+w, y1-1);\n\t    break;\n\n\tcase TTK_STICK_E:\n\t    if (state & TTK_STATE_LAST) {\t\t/* bottommost tab */\n\t\t--b.height;\n\t    }\n\n\t    Tk_Fill3DRectangle(tkwin, d, border,\n\t\tb.x+2, b.y+2, b.width-2+delta, b.height-1,\n\t\tborderWidth, TK_RELIEF_FLAT);\n\n\t    x1 = b.x;\t\t  y1 = b.y;\t\t/* top left */\n\t    x2 = b.x + b.width-1; y2 = b.y + b.height;\t/* bottom right */\n\n\t    gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d);\n\t    XDrawLine(display, d, gc, x1, y1+1, x1, y2-1+w);\n\t    XDrawLine(display, d, gc, x1+1, y1, x2+1+w, y1);\n\n\t    if ((state & TTK_STATE_LAST) && nbTabPosStickBit == TTK_STICK_S) {\n\t\tXDrawLine(display, d, gc, x1+1, y2, x2+2+w, y2);\n\t    } else {\n\t\tXDrawLine(display, d, gc, x1+1, y2, x2+1+w, y2);\n\t    }\n\n\t    gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d);\n\t    XDrawLine(display, d, gc, x1+1, y1+1, x1+1, y2-1+w);\n\t    XDrawLine(display, d, gc, x1+1, y1+1, x2+delta+w, y1+1);\n\t    break;\n\n\tcase TTK_STICK_W:\n\t    if (state & TTK_STATE_LAST) {\t\t/* bottommost tab */\n\t\t--b.height;\n\t    }\n\n\t    Tk_Fill3DRectangle(tkwin, d, border,\n\t\tb.x-delta, b.y+2, b.width-2+delta, b.height-1,\n\t\tborderWidth, TK_RELIEF_FLAT);\n\n\t    x1 = b.x + b.width-1; y1 = b.y;\t\t/* top right */\n\t    x2 = b.x;\t\t  y2 = b.y + b.height;\t/* bottom left */\n\n\t    gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d);\n\t    XDrawLine(display, d, gc, x1, y1+1, x1, y2-1+w);\n\t    XDrawLine(display, d, gc, x1-1, y1, x2-1-w, y1);\n\n\t    if ((state & TTK_STATE_LAST) && nbTabPosStickBit == TTK_STICK_S) {\n\t\tXDrawLine(display, d, gc, x1-1, y2, x2-2-w, y2);\n\t    } else {\n\t\tXDrawLine(display, d, gc, x1-1, y2, x2-1-w, y2);\n\t    }\n\n\t    gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d);\n\t    XDrawLine(display, d, gc, x1-1, y1+1, x1-1, y2-1+w);\n\t    XDrawLine(display, d, gc, x1-1, y1+1, x2-delta-w, y1+1);\n\t    break;\n    }\n}\n\nstatic const Ttk_ElementSpec TabElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NotebookElement),\n    NotebookElementOptions,\n    TabElementSize,\n    TabElementDraw\n};\n\nstatic void ClientElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    int borderWidth = 2;\n\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void ClientElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    NotebookElement *ce = (NotebookElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);\n    int borderWidth = 2;\n\n    Tk_Fill3DRectangle(tkwin, d, border,\n\tb.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);\n    DrawSmoothBorder(tkwin, d, b,\n\tce->borderColorObj, ce->lightColorObj, ce->darkColorObj);\n}\n\nstatic const Ttk_ElementSpec ClientElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NotebookElement),\n    NotebookElementOptions,\n    ClientElementSize,\n    ClientElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Modified widget layouts.\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"TCombobox\",\n    TTK_NODE(\"Combobox.downarrow\", TTK_PACK_RIGHT|TTK_FILL_Y)\n    TTK_GROUP(\"Combobox.field\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Combobox.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Combobox.textarea\", TTK_FILL_BOTH))))\n\nTTK_END_LAYOUT_TABLE\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE int\nTtkClamTheme_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_CreateTheme(interp, \"clam\", 0);\n\n    if (!theme) {\n\treturn TCL_ERROR;\n    }\n\n    Ttk_RegisterElement(interp, theme, \"border\",\n\t    &BorderElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"field\",\n\t    &FieldElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"Combobox.field\",\n\t    &ComboboxFieldElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"trough\",\n\t    &TroughElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"thumb\",\n\t    &ThumbElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"uparrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.uparrow\",\n\t    &SpinboxArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"downarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.downarrow\",\n\t    &SpinboxArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"leftarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_LEFT));\n    Ttk_RegisterElement(interp, theme, \"rightarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));\n    Ttk_RegisterElement(interp, theme, \"arrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n\n    Ttk_RegisterElement(interp, theme, \"Checkbutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&checkbutton_spec);\n    Ttk_RegisterElement(interp, theme, \"Radiobutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&radiobutton_spec);\n\n    Ttk_RegisterElement(interp, theme, \"tab\", &TabElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"client\", &ClientElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"slider\", &SliderElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"bar\", &PbarElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"pbar\", &PbarElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"hgrip\",\n\t    &GripElementSpec,  INT2PTR(TTK_ORIENT_HORIZONTAL));\n    Ttk_RegisterElement(interp, theme, \"vgrip\",\n\t    &GripElementSpec,  INT2PTR(TTK_ORIENT_VERTICAL));\n\n    Ttk_RegisterLayouts(theme, LayoutTable);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::clam\", TTK_VERSION);\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "generic/ttk/ttkClassicTheme.c",
    "content": "/*\n * Copyright © 2004, Joe English\n *\n * \"classic\" theme; implements the classic Motif-like Tk look.\n *\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\n#define DEFAULT_BORDERWIDTH \"2\"\n#define DEFAULT_ARROW_SIZE \"15\"\n\n/*----------------------------------------------------------------------\n * +++ Highlight element implementation.\n *\tDraw a solid highlight border to indicate focus.\n */\n\ntypedef struct {\n    Tcl_Obj\t*highlightColorObj;\n    Tcl_Obj\t*highlightThicknessObj;\n    Tcl_Obj\t*defaultStateObj;\n} HighlightElement;\n\nstatic const Ttk_ElementOptionSpec HighlightElementOptions[] = {\n    { \"-highlightcolor\",TK_OPTION_COLOR,\n\toffsetof(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND },\n    { \"-highlightthickness\",TK_OPTION_PIXELS,\n\toffsetof(HighlightElement,highlightThicknessObj), \"0\" },\n    { \"-default\", TK_OPTION_ANY,\n\toffsetof(HighlightElement,defaultStateObj), \"disabled\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void HighlightElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    HighlightElement *hl = (HighlightElement *)elementRecord;\n    int highlightThickness = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, hl->highlightThicknessObj, &highlightThickness);\n    *paddingPtr = Ttk_UniformPadding((short)highlightThickness);\n}\n\nstatic void HighlightElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    TCL_UNUSED(Ttk_Box),\n    TCL_UNUSED(Ttk_State))\n{\n    HighlightElement *hl = (HighlightElement *)elementRecord;\n    int highlightThickness = 0;\n    XColor *highlightColor = Tk_GetColorFromObj(tkwin, hl->highlightColorObj);\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, hl->highlightThicknessObj, &highlightThickness);\n    if (highlightColor && highlightThickness > 0) {\n\tTtk_GetButtonDefaultStateFromObj(NULL, hl->defaultStateObj,\n\t    &defaultState);\n\tGC gc = Tk_GCForColor(highlightColor, d);\n\tif (defaultState == TTK_BUTTON_DEFAULT_NORMAL) {\n\t    TkDrawInsetFocusHighlight(tkwin, gc, highlightThickness, d,\n\t\t(int)round(5 * TkScalingLevel(tkwin)));\n\t} else {\n\t    Tk_DrawFocusHighlight(tkwin, gc, highlightThickness, d);\n\t}\n    }\n}\n\nstatic const Ttk_ElementSpec HighlightElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(HighlightElement),\n    HighlightElementOptions,\n    HighlightElementSize,\n    HighlightElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Button Border element:\n *\n * The Motif-style button border on X11 consists of (from outside-in):\n *\n * + focus indicator (controlled by -highlightcolor and -highlightthickness),\n * + default ring (if -default active; blank if -default normal)\n * + shaded border (controlled by -background, -borderwidth, and -relief)\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*borderWidthObj;\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*defaultStateObj;\n} ButtonBorderElement;\n\nstatic const Ttk_ElementOptionSpec ButtonBorderElementOptions[] =\n{\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(ButtonBorderElement,reliefObj), \"flat\" },\n    { \"-default\", TK_OPTION_ANY,\n\toffsetof(ButtonBorderElement,defaultStateObj), \"disabled\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void ButtonBorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n    int borderWidth = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n\n    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {\n\tborderWidth += (int)round(5 * TkScalingLevel(tkwin));\n    }\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\n/*\n * (@@@ Note: ButtonBorderElement still still still buggy:\n * padding for default ring is drawn in the wrong color\n * when the button is active.)\n */\nstatic void ButtonBorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;\n    Tk_3DBorder border = NULL;\n    int borderWidth = 1, relief = TK_RELIEF_FLAT;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n    int inset = 0;\n\n    /*\n     * Get option values.\n     */\n    border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n\n    /*\n     * Default ring:\n     */\n    switch (defaultState)\n    {\n\tcase TTK_BUTTON_DEFAULT_DISABLED :\n\t    break;\n\tcase TTK_BUTTON_DEFAULT_NORMAL :\n\t    inset += (int)round(5 * TkScalingLevel(tkwin));\n\t    break;\n\tcase TTK_BUTTON_DEFAULT_ACTIVE :\n\t    Tk_Draw3DRectangle(tkwin, d, border,\n\t\tb.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,\n\t\t2, TK_RELIEF_FLAT);\n\t    inset += 2;\n\t    Tk_Draw3DRectangle(tkwin, d, border,\n\t\tb.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,\n\t\t1, TK_RELIEF_SUNKEN);\n\t    ++inset;\n\t    Tk_Draw3DRectangle(tkwin, d, border,\n\t\tb.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,\n\t\t2, TK_RELIEF_FLAT);\n\t    inset += 2;\n\t    break;\n    }\n\n    /*\n     * 3-D border:\n     */\n    if (border && borderWidth > 0) {\n\tTk_Draw3DRectangle(tkwin, d, border,\n\t    b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,\n\t    borderWidth,relief);\n    }\n}\n\nstatic const Ttk_ElementSpec ButtonBorderElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(ButtonBorderElement),\n    ButtonBorderElementOptions,\n    ButtonBorderElementSize,\n    ButtonBorderElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Indicator element.\n *\n * Draws the on/off indicator for checkbuttons and radiobuttons.\n *\n * Draws a 3-D square (or diamond), raised if off, sunken if on.\n *\n * This is actually a regression from Tk 8.5 back to the ugly old Motif\n * style; use the \"alt\", \"clam\", or \"default\" theme\" for newer, nicer\n * versions.\n */\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *colorObj;\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *marginObj;\n    Tcl_Obj *borderWidthObj;\n} IndicatorElement;\n\nstatic const Ttk_ElementOptionSpec IndicatorElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-indicatorcolor\", TK_OPTION_BORDER,\n\toffsetof(IndicatorElement,colorObj), DEFAULT_BACKGROUND },\n    { \"-indicatorrelief\", TK_OPTION_RELIEF,\n\toffsetof(IndicatorElement,reliefObj), \"raised\" },\n    { \"-indicatorsize\", TK_OPTION_PIXELS,\n\toffsetof(IndicatorElement,sizeObj), \"9p\" },\n    { \"-indicatormargin\", TK_OPTION_STRING,\n\toffsetof(IndicatorElement,marginObj), \"0 2 4 2\" },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * Checkbutton indicators: 3-D square.\n */\nstatic void SquareIndicatorElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    int diameter = 0;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &diameter);\n    *widthPtr = diameter + Ttk_PaddingWidth(margins);\n    *heightPtr = diameter + Ttk_PaddingHeight(margins);\n}\n\nstatic void SquareIndicatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Tk_3DBorder border = 0, interior = 0;\n    int relief = TK_RELIEF_RAISED;\n    Ttk_Padding padding;\n    int borderWidth = 2;\n    int diameter;\n\n    interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);\n    border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->borderWidthObj,&borderWidth);\n    Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);\n    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);\n\n    b = Ttk_PadBox(b, padding);\n\n    diameter = b.width < b.height ? b.width : b.height;\n    Tk_Fill3DRectangle(tkwin, d, interior, b.x, b.y,\n\t    diameter, diameter,borderWidth, TK_RELIEF_FLAT);\n    Tk_Draw3DRectangle(tkwin, d, border, b.x, b.y,\n\t    diameter, diameter, borderWidth, relief);\n}\n\n/*\n * Radiobutton indicators: 3-D diamond.\n */\nstatic void DiamondIndicatorElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    int diameter = 0;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &diameter);\n    *widthPtr = diameter + 3 + Ttk_PaddingWidth(margins);\n    *heightPtr = diameter + 3 + Ttk_PaddingHeight(margins);\n}\n\nstatic void DiamondIndicatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Tk_3DBorder border = 0, interior = 0;\n    int borderWidth = 2;\n    int relief = TK_RELIEF_RAISED;\n    int diameter, radius;\n    XPoint points[4];\n    Ttk_Padding padding;\n\n    interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);\n    border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);\n    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);\n\n    b = Ttk_PadBox(b, padding);\n\n    diameter = b.width < b.height ? b.width : b.height;\n    radius = diameter / 2;\n\n    points[0].x = (short)b.x;\n    points[0].y = (short)(b.y + radius);\n    points[1].x = (short)(b.x + radius);\n    points[1].y = (short)(b.y + 2*radius);\n    points[2].x = (short)(b.x + 2*radius);\n    points[2].y = (short)(b.y + radius);\n    points[3].x = (short)(b.x + radius);\n    points[3].y = (short)b.y;\n\n    Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT);\n    Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief);\n}\n\nstatic const Ttk_ElementSpec CheckbuttonIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(IndicatorElement),\n    IndicatorElementOptions,\n    SquareIndicatorElementSize,\n    SquareIndicatorElementDraw\n};\n\nstatic const Ttk_ElementSpec RadiobuttonIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(IndicatorElement),\n    IndicatorElementOptions,\n    DiamondIndicatorElementSize,\n    DiamondIndicatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Menubutton indicators.\n *\n * These aren't functional like radio/check indicators,\n * they're just affordability indicators.\n *\n * Standard Tk sets the indicator size to 4.0 mm by 1.7 mm.\n * I have no idea where these numbers came from.\n */\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *widthObj;\n    Tcl_Obj *heightObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *marginObj;\n} MenuIndicatorElement;\n\nstatic const Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-indicatorwidth\", TK_OPTION_PIXELS,\n\toffsetof(MenuIndicatorElement,widthObj), \"4.0m\" },\n    { \"-indicatorheight\", TK_OPTION_PIXELS,\n\toffsetof(MenuIndicatorElement,heightObj), \"1.7m\" },\n    { \"-indicatorborderwidth\", TK_OPTION_PIXELS,\n\toffsetof(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { \"-indicatorrelief\", TK_OPTION_RELIEF,\n\toffsetof(MenuIndicatorElement,reliefObj), \"raised\" },\n    { \"-indicatormargin\", TK_OPTION_STRING,\n\toffsetof(MenuIndicatorElement,marginObj), \"5 0\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void MenuIndicatorElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    MenuIndicatorElement *mi = (MenuIndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, mi->widthObj, widthPtr);\n    Tk_GetPixelsFromObj(NULL, tkwin, mi->heightObj, heightPtr);\n    Ttk_GetPaddingFromObj(NULL, tkwin, mi->marginObj, &margins);\n    *widthPtr += Ttk_PaddingWidth(margins);\n    *heightPtr += Ttk_PaddingHeight(margins);\n}\n\nstatic void MenuIndicatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    MenuIndicatorElement *mi = (MenuIndicatorElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, mi->backgroundObj);\n    Ttk_Padding margins;\n    int borderWidth = 2;\n\n    Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj,&margins);\n    b = Ttk_PadBox(b, margins);\n    Tk_GetPixelsFromObj(NULL, tkwin, mi->borderWidthObj, &borderWidth);\n    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    borderWidth, TK_RELIEF_RAISED);\n}\n\nstatic const Ttk_ElementSpec MenuIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(MenuIndicatorElement),\n    MenuIndicatorElementOptions,\n    MenuIndicatorElementSize,\n    MenuIndicatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Arrow element(s).\n *\n * Draws a 3-D shaded triangle.\n * clientData is an enum ArrowDirection pointer.\n */\n\ntypedef struct\n{\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *borderObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n} ArrowElement;\n\nstatic const Ttk_ElementOptionSpec ArrowElementOptions[] =\n{\n    { \"-arrowsize\", TK_OPTION_PIXELS, offsetof(ArrowElement,sizeObj),\n\tDEFAULT_ARROW_SIZE },\n    { \"-background\", TK_OPTION_BORDER, offsetof(ArrowElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS, offsetof(ArrowElement,borderWidthObj),\n\tDEFAULT_BORDERWIDTH },\n    { \"-relief\", TK_OPTION_RELIEF, offsetof(ArrowElement,reliefObj),\"raised\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void ArrowElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    int size = 12;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    *widthPtr = *heightPtr = size;\n}\n\nstatic void ArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);\n    int borderWidth = 2;\n    int relief = TK_RELIEF_RAISED;\n    int size = b.width < b.height ? b.width : b.height;\n    XPoint points[3];\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);\n\n    /*\n     * @@@ There are off-by-one pixel errors in the way these are drawn;\n     * @@@ need to take a look at Tk_Fill3DPolygon and X11 to find the\n     * @@@ exact rules.\n     */\n    switch (direction)\n    {\n\tcase ARROW_UP:\n\t    points[2].x = (short)b.x;\t\tpoints[2].y = (short)(b.y + size);\n\t    points[1].x = (short)(b.x + size/2);\tpoints[1].y = (short)b.y;\n\t    points[0].x = (short)(b.x + size);\tpoints[0].y = (short)(b.y + size);\n\t    break;\n\tcase ARROW_DOWN:\n\t    points[0].x = (short)b.x;\t\tpoints[0].y = (short)b.y;\n\t    points[1].x = (short)(b.x + size/2);\tpoints[1].y = (short)(b.y + size);\n\t    points[2].x = (short)(b.x + size);\tpoints[2].y = (short)b.y;\n\t    break;\n\tcase ARROW_LEFT:\n\t    points[0].x = (short)b.x;\t\tpoints[0].y = (short)(b.y + size / 2);\n\t    points[1].x = (short)(b.x + size);\tpoints[1].y = (short)(b.y + size);\n\t    points[2].x = (short)(b.x + size);\tpoints[2].y = (short)b.y;\n\t    break;\n\tcase ARROW_RIGHT:\n\t    points[0].x = (short)(b.x + size);\tpoints[0].y = (short)(b.y + size / 2);\n\t    points[1].x = (short)b.x;\t\tpoints[1].y = (short)b.y;\n\t    points[2].x = (short)b.x;\t\tpoints[2].y = (short)(b.y + size);\n\t    break;\n    }\n\n    Tk_Fill3DPolygon(tkwin, d, border, points, 3, borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec ArrowElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(ArrowElement),\n    ArrowElementOptions,\n    ArrowElementSize,\n    ArrowElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Slider element.\n *\n * This is the moving part of the scale widget.  Drawn as a raised box.\n */\n\ntypedef struct {\n    Tcl_Obj *orientObj;\t     /* orientation of overall slider */\n    Tcl_Obj *lengthObj;      /* slider length */\n    Tcl_Obj *thicknessObj;   /* slider thickness */\n    Tcl_Obj *reliefObj;      /* the relief for this object */\n    Tcl_Obj *borderObj;      /* the background color */\n    Tcl_Obj *borderWidthObj; /* the size of the border */\n} SliderElement;\n\nstatic const Ttk_ElementOptionSpec SliderElementOptions[] = {\n    { \"-sliderlength\", TK_OPTION_PIXELS,\n\toffsetof(SliderElement,lengthObj), \"30\" },\n    { \"-sliderthickness\",TK_OPTION_PIXELS,\n\toffsetof(SliderElement,thicknessObj), \"15\" },\n    { \"-sliderrelief\", TK_OPTION_RELIEF,\n\toffsetof(SliderElement,reliefObj), \"raised\" },\n    { \"-sliderborderwidth\", TK_OPTION_PIXELS,\n\toffsetof(SliderElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(SliderElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-orient\", TK_OPTION_ANY,\n\toffsetof(SliderElement,orientObj), \"horizontal\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SliderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Ttk_Orient orient;\n    int length, thickness;\n\n    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);\n\n    switch (orient) {\n\tcase TTK_ORIENT_VERTICAL:\n\t    *widthPtr = thickness;\n\t    *heightPtr = length;\n\t    break;\n\n\tcase TTK_ORIENT_HORIZONTAL:\n\t    *widthPtr = length;\n\t    *heightPtr = thickness;\n\t    break;\n    }\n}\n\nstatic void SliderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Tk_3DBorder border = NULL;\n    int relief = TK_RELIEF_RAISED, borderWidth = 2;\n    Ttk_Orient orient;\n\n    border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);\n    Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);\n    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);\n\n    Tk_Fill3DRectangle(tkwin, d, border,\n\tb.x, b.y, b.width, b.height,\n\tborderWidth, relief);\n\n    if (relief != TK_RELIEF_FLAT) {\n\tif (orient == TTK_ORIENT_HORIZONTAL) {\n\t    if (b.width > 4) {\n\t\tb.x += b.width/2;\n\t\tXDrawLine(Tk_Display(tkwin), d,\n\t\t    Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t    b.x-1, b.y+borderWidth, b.x-1, b.y+b.height-borderWidth);\n\t\tXDrawLine(Tk_Display(tkwin), d,\n\t\t    Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t    b.x, b.y+borderWidth, b.x, b.y+b.height-borderWidth);\n\t    }\n\t} else {\n\t    if (b.height > 4) {\n\t\tb.y += b.height/2;\n\t\tXDrawLine(Tk_Display(tkwin), d,\n\t\t    Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t    b.x+borderWidth, b.y-1, b.x+b.width-borderWidth, b.y-1);\n\t\tXDrawLine(Tk_Display(tkwin), d,\n\t\t    Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t    b.x+borderWidth, b.y, b.x+b.width-borderWidth, b.y);\n\t    }\n\t}\n    }\n}\n\nstatic const Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SliderElement),\n    SliderElementOptions,\n    SliderElementSize,\n    SliderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Sash element (for ttk::panedwindow)\n *\n * NOTES:\n *\n * panedwindows with -orient horizontal use vertical sashes, and vice versa.\n *\n * Interpretation of -sashrelief 'groove' and 'ridge' are\n * swapped wrt. the core panedwindow, which (I think) has them backwards.\n *\n * Default -sashrelief is sunken; the core panedwindow has default\n * -sashrelief raised, but that looks wrong to me.\n */\n\ntypedef struct {\n    Tcl_Obj *borderObj;\t/* background color */\n    Tcl_Obj *sashReliefObj;\t/* sash relief */\n    Tcl_Obj *sashThicknessObj;\t/* overall thickness of sash */\n    Tcl_Obj *sashPadObj;\t/* padding on either side of handle */\n    Tcl_Obj *handleSizeObj;\t/* handle width and height */\n    Tcl_Obj *handlePadObj;\t/* handle's distance from edge */\n} SashElement;\n\nstatic const Ttk_ElementOptionSpec SashOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(SashElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-sashrelief\", TK_OPTION_RELIEF,\n\toffsetof(SashElement,sashReliefObj), \"sunken\" },\n    { \"-sashthickness\", TK_OPTION_PIXELS,\n\toffsetof(SashElement,sashThicknessObj), \"6\" },\n    { \"-sashpad\", TK_OPTION_PIXELS,\n\toffsetof(SashElement,sashPadObj), \"2\" },\n    { \"-handlesize\", TK_OPTION_PIXELS,\n\toffsetof(SashElement,handleSizeObj), \"8\" },\n    { \"-handlepad\", TK_OPTION_PIXELS,\n\toffsetof(SashElement,handlePadObj), \"8\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SashElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SashElement *sash = (SashElement *)elementRecord;\n    int sashPad = 2, sashThickness = 6, handleSize = 8;\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->sashThicknessObj, &sashThickness);\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->sashPadObj, &sashPad);\n\n    if (sashThickness < handleSize + 2*sashPad) {\n\tsashThickness = handleSize + 2*sashPad;\n    }\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*heightPtr = sashThickness;\n    } else {\n\t*widthPtr = sashThickness;\n    }\n}\n\nstatic void SashElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SashElement *sash = (SashElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, sash->borderObj);\n    GC gc1,gc2;\n    int relief = TK_RELIEF_RAISED;\n    int handleSize = 8, handlePad = 8;\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n    Ttk_Box hb;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->handlePadObj, &handlePad);\n    Tk_GetReliefFromObj(NULL, sash->sashReliefObj, &relief);\n\n    switch (relief) {\n\tcase TK_RELIEF_RAISED: case TK_RELIEF_RIDGE:\n\t    gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n\t    gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\t    break;\n\tcase TK_RELIEF_SUNKEN: case TK_RELIEF_GROOVE:\n\t    gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\t    gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n\t    break;\n\tcase TK_RELIEF_SOLID:\n\t    gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\t    break;\n\tcase TK_RELIEF_FLAT:\n\tdefault:\n\t    gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);\n\t    break;\n    }\n\n    /* Draw sash line:\n     */\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tint y = b.y + b.height/2 - 1;\n\tXDrawLine(Tk_Display(tkwin), d, gc1, b.x, y, b.x+b.width, y); ++y;\n\tXDrawLine(Tk_Display(tkwin), d, gc2, b.x, y, b.x+b.width, y);\n    } else {\n\tint x = b.x + b.width/2 - 1;\n\tXDrawLine(Tk_Display(tkwin), d, gc1, x, b.y, x, b.y+b.height); ++x;\n\tXDrawLine(Tk_Display(tkwin), d, gc2, x, b.y, x, b.y+b.height);\n    }\n\n    /* Draw handle:\n     */\n    if (handleSize >= 0) {\n\tif (orient == TTK_ORIENT_HORIZONTAL) {\n\t    hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_W);\n\t    hb.x += handlePad;\n\t} else {\n\t    hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_N);\n\t    hb.y += handlePad;\n\t}\n\tTk_Fill3DRectangle(tkwin, d, border,\n\t    hb.x, hb.y, hb.width, hb.height, 1, TK_RELIEF_RAISED);\n    }\n}\n\nstatic const Ttk_ElementSpec SashElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SashElement),\n    SashOptions,\n    SashElementSize,\n    SashElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget layouts.\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"TButton\",\n    TTK_GROUP(\"Button.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Button.border\", TTK_FILL_BOTH|TTK_BORDER,\n\t    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Button.label\", TTK_FILL_BOTH)))))\n\nTTK_LAYOUT(\"TCheckbutton\",\n    TTK_GROUP(\"Checkbutton.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Checkbutton.border\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Checkbutton.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Checkbutton.indicator\", TTK_PACK_LEFT)\n\t\tTTK_NODE(\"Checkbutton.label\", TTK_PACK_LEFT|TTK_FILL_BOTH)))))\n\nTTK_LAYOUT(\"TRadiobutton\",\n    TTK_GROUP(\"Radiobutton.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Radiobutton.border\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Radiobutton.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Radiobutton.indicator\", TTK_PACK_LEFT)\n\t\tTTK_NODE(\"Radiobutton.label\", TTK_PACK_LEFT|TTK_FILL_BOTH)))))\n\nTTK_LAYOUT(\"TMenubutton\",\n    TTK_GROUP(\"Menubutton.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Menubutton.border\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Menubutton.indicator\", TTK_PACK_RIGHT)\n\t    TTK_GROUP(\"Menubutton.padding\", TTK_FILL_X,\n\t\tTTK_NODE(\"Menubutton.label\", 0)))))\n\n/* \"classic\" entry, includes highlight border */\nTTK_LAYOUT(\"TEntry\",\n    TTK_GROUP(\"Entry.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Entry.field\", TTK_FILL_BOTH|TTK_BORDER,\n\t    TTK_GROUP(\"Entry.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Entry.textarea\", TTK_FILL_BOTH)))))\n\n/* \"classic\" combobox, includes highlight border */\nTTK_LAYOUT(\"TCombobox\",\n    TTK_GROUP(\"Combobox.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Combobox.field\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Combobox.downarrow\", TTK_PACK_RIGHT|TTK_FILL_Y)\n\t    TTK_GROUP(\"Combobox.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Combobox.textarea\", TTK_FILL_BOTH)))))\n\n/* \"classic\" spinbox, includes highlight border */\nTTK_LAYOUT(\"TSpinbox\",\n    TTK_GROUP(\"Spinbox.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Spinbox.field\", TTK_FILL_BOTH|TTK_FILL_X,\n\t    TTK_GROUP(\"null\", TTK_PACK_RIGHT,\n\t\tTTK_NODE(\"Spinbox.uparrow\", TTK_PACK_TOP|TTK_STICK_E)\n\t\tTTK_NODE(\"Spinbox.downarrow\", TTK_PACK_BOTTOM|TTK_STICK_E))\n\t    TTK_GROUP(\"Spinbox.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Spinbox.textarea\", TTK_FILL_BOTH)))))\n\n/* \"classic\" scale, includes highlight border */\nTTK_LAYOUT(\"Horizontal.TScale\",\n    TTK_GROUP(\"Horizontal.Scale.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Horizontal.Scale.trough\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Horizontal.Scale.slider\", TTK_PACK_LEFT))))\n\nTTK_LAYOUT(\"Vertical.TScale\",\n    TTK_GROUP(\"Vertical.Scale.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Vertical.Scale.trough\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Vertical.Scale.slider\", TTK_PACK_TOP))))\n\nTTK_LAYOUT(\"Horizontal.Sash\",\n    TTK_NODE(\"Sash.hsash\", TTK_FILL_X))\n\nTTK_LAYOUT(\"Vertical.Sash\",\n    TTK_NODE(\"Sash.vsash\", TTK_FILL_Y))\n\n/* put highlight border around treeview */\nTTK_LAYOUT(\"Treeview\",\n    TTK_GROUP(\"Treeview.highlight\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Treeview.field\", TTK_FILL_BOTH|TTK_BORDER,\n\t    TTK_GROUP(\"Treeview.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Treeview.treearea\", TTK_FILL_BOTH)))))\n\nTTK_END_LAYOUT_TABLE\n\n/*------------------------------------------------------------------------\n * TtkClassicTheme_Init --\n *\tInstall classic theme.\n */\n\nMODULE_SCOPE int\nTtkClassicTheme_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme =  Ttk_CreateTheme(interp, \"classic\", NULL);\n\n    if (!theme) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Register elements:\n     */\n    Ttk_RegisterElement(interp, theme, \"highlight\",\n\t    &HighlightElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"Button.border\",\n\t    &ButtonBorderElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"Checkbutton.indicator\",\n\t    &CheckbuttonIndicatorElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"Radiobutton.indicator\",\n\t    &RadiobuttonIndicatorElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"Menubutton.indicator\",\n\t    &MenuIndicatorElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"uparrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"downarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"leftarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_LEFT));\n    Ttk_RegisterElement(interp, theme, \"rightarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));\n    Ttk_RegisterElement(interp, theme, \"arrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n\n    Ttk_RegisterElement(interp, theme, \"slider\",\n\t    &SliderElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"hsash\",\n\t    &SashElementSpec, INT2PTR(TTK_ORIENT_HORIZONTAL));\n    Ttk_RegisterElement(interp, theme, \"vsash\",\n\t    &SashElementSpec, INT2PTR(TTK_ORIENT_VERTICAL));\n\n    /*\n     * Register layouts:\n     */\n    Ttk_RegisterLayouts(theme, LayoutTable);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::classic\", TTK_VERSION);\n\n    return TCL_OK;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkDecls.h",
    "content": "/*\n * This file is (mostly) automatically generated from ttk.decls.\n */\n\n#ifndef _TTKDECLS\n#define _TTKDECLS\n\n#if defined(USE_TTK_STUBS)\n\nextern const char *TtkInitializeStubs(\n\tTcl_Interp *, const char *version, int epoch, int revision);\n#define Ttk_InitStubs(interp) TtkInitializeStubs( \\\n\tinterp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION)\n#else\n\n#define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, \"ttk\", TTK_VERSION, 0, NULL)\n\n#endif\n\n#if !defined(BUILD_tk)\n# define TTK_DEPRECATED(msg) TTKAPI TCL_DEPRECATED_API(msg)\n#elif defined(TK_NO_DEPRECATED)\n# define TTK_DEPRECATED(msg) MODULE_SCOPE\n#else\n# define TTK_DEPRECATED(msg) TTKAPI\n#endif\n\n\n\n/* !BEGIN!: Do not edit below this line. */\n\n#define TTK_STUBS_EPOCH 0\n#define TTK_STUBS_REVISION 31\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Exported function declarations:\n */\n\n/* 0 */\nTTKAPI Ttk_Theme\tTtk_GetTheme(Tcl_Interp *interp, const char *name);\n/* 1 */\nTTKAPI Ttk_Theme\tTtk_GetDefaultTheme(Tcl_Interp *interp);\n/* 2 */\nTTKAPI Ttk_Theme\tTtk_GetCurrentTheme(Tcl_Interp *interp);\n/* 3 */\nTTKAPI Ttk_Theme\tTtk_CreateTheme(Tcl_Interp *interp, const char *name,\n\t\t\t\tTtk_Theme parent);\n/* 4 */\nTTKAPI void\t\tTtk_RegisterCleanup(Tcl_Interp *interp,\n\t\t\t\tvoid *deleteData,\n\t\t\t\tTtk_CleanupProc *cleanupProc);\n/* 5 */\nTTK_DEPRECATED(\"Use Ttk_RegisterElement\")\nint\t\t\tTtk_RegisterElementSpec(Ttk_Theme theme,\n\t\t\t\tconst char *elementName,\n\t\t\t\tconst Ttk_ElementSpec *elementSpec,\n\t\t\t\tvoid *clientData);\n/* 6 */\nTTKAPI Ttk_ElementClass * Ttk_RegisterElement(Tcl_Interp *interp,\n\t\t\t\tTtk_Theme theme, const char *elementName,\n\t\t\t\tconst Ttk_ElementSpec *elementSpec,\n\t\t\t\tvoid *clientData);\n/* 7 */\nTTKAPI int\t\tTtk_RegisterElementFactory(Tcl_Interp *interp,\n\t\t\t\tconst char *name,\n\t\t\t\tTtk_ElementFactory factoryProc,\n\t\t\t\tvoid *clientData);\n/* 8 */\nTTKAPI void\t\tTtk_RegisterLayout(Ttk_Theme theme,\n\t\t\t\tconst char *className,\n\t\t\t\tTtk_LayoutSpec layoutSpec);\n/* Slot 9 is reserved */\n/* 10 */\nTTKAPI int\t\tTtk_GetStateSpecFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Ttk_StateSpec *spec_rtn);\n/* 11 */\nTTKAPI Tcl_Obj *\tTtk_NewStateSpecObj(unsigned int onbits,\n\t\t\t\tunsigned int offbits);\n/* 12 */\nTTKAPI Ttk_StateMap\tTtk_GetStateMapFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr);\n/* 13 */\nTTKAPI Tcl_Obj *\tTtk_StateMapLookup(Tcl_Interp *interp,\n\t\t\t\tTtk_StateMap map, Ttk_State state);\n/* 14 */\nTTKAPI int\t\tTtk_StateTableLookup(const Ttk_StateTable *map,\n\t\t\t\tTtk_State state);\n/* Slot 15 is reserved */\n/* Slot 16 is reserved */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n/* 20 */\nTTKAPI int\t\tTtk_GetPaddingFromObj(Tcl_Interp *interp,\n\t\t\t\tTk_Window tkwin, Tcl_Obj *objPtr,\n\t\t\t\tTtk_Padding *pad_rtn);\n/* 21 */\nTTKAPI int\t\tTtk_GetBorderFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Ttk_Padding *pad_rtn);\n/* 22 */\nTTKAPI int\t\tTtk_GetStickyFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Ttk_Sticky *sticky_rtn);\n/* 23 */\nTTKAPI Ttk_Padding\tTtk_MakePadding(short l, short t, short r, short b);\n/* 24 */\nTTKAPI Ttk_Padding\tTtk_UniformPadding(short borderWidth);\n/* 25 */\nTTKAPI Ttk_Padding\tTtk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2);\n/* 26 */\nTTKAPI Ttk_Padding\tTtk_RelievePadding(Ttk_Padding padding, int relief,\n\t\t\t\tint n);\n/* 27 */\nTTKAPI Ttk_Box\t\tTtk_MakeBox(int x, int y, int width, int height);\n/* 28 */\nTTKAPI int\t\tTtk_BoxContains(Ttk_Box box, int x, int y);\n/* 29 */\nTTKAPI Ttk_Box\t\tTtk_PackBox(Ttk_Box *cavity, int w, int h,\n\t\t\t\tTtk_Side side);\n/* 30 */\nTTKAPI Ttk_Box\t\tTtk_StickBox(Ttk_Box parcel, int w, int h,\n\t\t\t\tTtk_Sticky sticky);\n/* 31 */\nTTKAPI Ttk_Box\t\tTtk_AnchorBox(Ttk_Box parcel, int w, int h,\n\t\t\t\tTk_Anchor anchor);\n/* 32 */\nTTKAPI Ttk_Box\t\tTtk_PadBox(Ttk_Box b, Ttk_Padding p);\n/* 33 */\nTTKAPI Ttk_Box\t\tTtk_ExpandBox(Ttk_Box b, Ttk_Padding p);\n/* 34 */\nTTKAPI Ttk_Box\t\tTtk_PlaceBox(Ttk_Box *cavity, int w, int h,\n\t\t\t\tTtk_Side side, Ttk_Sticky sticky);\n/* 35 */\nTTKAPI Tcl_Obj *\tTtk_NewBoxObj(Ttk_Box box);\n/* Slot 36 is reserved */\n/* Slot 37 is reserved */\n/* Slot 38 is reserved */\n/* Slot 39 is reserved */\n/* 40 */\nTTKAPI int\t\tTtk_GetOrientFromObj(Tcl_Interp *interp,\n\t\t\t\tTcl_Obj *objPtr, Ttk_Orient *orient);\n\ntypedef struct TtkStubs {\n    int magic;\n    int epoch;\n    int revision;\n    void *hooks;\n\n    Ttk_Theme (*ttk_GetTheme) (Tcl_Interp *interp, const char *name); /* 0 */\n    Ttk_Theme (*ttk_GetDefaultTheme) (Tcl_Interp *interp); /* 1 */\n    Ttk_Theme (*ttk_GetCurrentTheme) (Tcl_Interp *interp); /* 2 */\n    Ttk_Theme (*ttk_CreateTheme) (Tcl_Interp *interp, const char *name, Ttk_Theme parent); /* 3 */\n    void (*ttk_RegisterCleanup) (Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc); /* 4 */\n    TCL_DEPRECATED_API(\"Use Ttk_RegisterElement\") int (*ttk_RegisterElementSpec) (Ttk_Theme theme, const char *elementName, const Ttk_ElementSpec *elementSpec, void *clientData); /* 5 */\n    Ttk_ElementClass * (*ttk_RegisterElement) (Tcl_Interp *interp, Ttk_Theme theme, const char *elementName, const Ttk_ElementSpec *elementSpec, void *clientData); /* 6 */\n    int (*ttk_RegisterElementFactory) (Tcl_Interp *interp, const char *name, Ttk_ElementFactory factoryProc, void *clientData); /* 7 */\n    void (*ttk_RegisterLayout) (Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec); /* 8 */\n    void (*reserved9)(void);\n    int (*ttk_GetStateSpecFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); /* 10 */\n    Tcl_Obj * (*ttk_NewStateSpecObj) (unsigned int onbits, unsigned int offbits); /* 11 */\n    Ttk_StateMap (*ttk_GetStateMapFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 12 */\n    Tcl_Obj * (*ttk_StateMapLookup) (Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state); /* 13 */\n    int (*ttk_StateTableLookup) (const Ttk_StateTable *map, Ttk_State state); /* 14 */\n    void (*reserved15)(void);\n    void (*reserved16)(void);\n    void (*reserved17)(void);\n    void (*reserved18)(void);\n    void (*reserved19)(void);\n    int (*ttk_GetPaddingFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 20 */\n    int (*ttk_GetBorderFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 21 */\n    int (*ttk_GetStickyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn); /* 22 */\n    Ttk_Padding (*ttk_MakePadding) (short l, short t, short r, short b); /* 23 */\n    Ttk_Padding (*ttk_UniformPadding) (short borderWidth); /* 24 */\n    Ttk_Padding (*ttk_AddPadding) (Ttk_Padding pad1, Ttk_Padding pad2); /* 25 */\n    Ttk_Padding (*ttk_RelievePadding) (Ttk_Padding padding, int relief, int n); /* 26 */\n    Ttk_Box (*ttk_MakeBox) (int x, int y, int width, int height); /* 27 */\n    int (*ttk_BoxContains) (Ttk_Box box, int x, int y); /* 28 */\n    Ttk_Box (*ttk_PackBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side); /* 29 */\n    Ttk_Box (*ttk_StickBox) (Ttk_Box parcel, int w, int h, Ttk_Sticky sticky); /* 30 */\n    Ttk_Box (*ttk_AnchorBox) (Ttk_Box parcel, int w, int h, Tk_Anchor anchor); /* 31 */\n    Ttk_Box (*ttk_PadBox) (Ttk_Box b, Ttk_Padding p); /* 32 */\n    Ttk_Box (*ttk_ExpandBox) (Ttk_Box b, Ttk_Padding p); /* 33 */\n    Ttk_Box (*ttk_PlaceBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky); /* 34 */\n    Tcl_Obj * (*ttk_NewBoxObj) (Ttk_Box box); /* 35 */\n    void (*reserved36)(void);\n    void (*reserved37)(void);\n    void (*reserved38)(void);\n    void (*reserved39)(void);\n    int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Orient *orient); /* 40 */\n} TtkStubs;\n\nextern const TtkStubs *ttkStubsPtr;\n\n#ifdef __cplusplus\n}\n#endif\n\n#if defined(USE_TTK_STUBS)\n\n/*\n * Inline function declarations:\n */\n\n#define Ttk_GetTheme \\\n\t(ttkStubsPtr->ttk_GetTheme) /* 0 */\n#define Ttk_GetDefaultTheme \\\n\t(ttkStubsPtr->ttk_GetDefaultTheme) /* 1 */\n#define Ttk_GetCurrentTheme \\\n\t(ttkStubsPtr->ttk_GetCurrentTheme) /* 2 */\n#define Ttk_CreateTheme \\\n\t(ttkStubsPtr->ttk_CreateTheme) /* 3 */\n#define Ttk_RegisterCleanup \\\n\t(ttkStubsPtr->ttk_RegisterCleanup) /* 4 */\n#define Ttk_RegisterElementSpec \\\n\t(ttkStubsPtr->ttk_RegisterElementSpec) /* 5 */\n#define Ttk_RegisterElement \\\n\t(ttkStubsPtr->ttk_RegisterElement) /* 6 */\n#define Ttk_RegisterElementFactory \\\n\t(ttkStubsPtr->ttk_RegisterElementFactory) /* 7 */\n#define Ttk_RegisterLayout \\\n\t(ttkStubsPtr->ttk_RegisterLayout) /* 8 */\n/* Slot 9 is reserved */\n#define Ttk_GetStateSpecFromObj \\\n\t(ttkStubsPtr->ttk_GetStateSpecFromObj) /* 10 */\n#define Ttk_NewStateSpecObj \\\n\t(ttkStubsPtr->ttk_NewStateSpecObj) /* 11 */\n#define Ttk_GetStateMapFromObj \\\n\t(ttkStubsPtr->ttk_GetStateMapFromObj) /* 12 */\n#define Ttk_StateMapLookup \\\n\t(ttkStubsPtr->ttk_StateMapLookup) /* 13 */\n#define Ttk_StateTableLookup \\\n\t(ttkStubsPtr->ttk_StateTableLookup) /* 14 */\n/* Slot 15 is reserved */\n/* Slot 16 is reserved */\n/* Slot 17 is reserved */\n/* Slot 18 is reserved */\n/* Slot 19 is reserved */\n#define Ttk_GetPaddingFromObj \\\n\t(ttkStubsPtr->ttk_GetPaddingFromObj) /* 20 */\n#define Ttk_GetBorderFromObj \\\n\t(ttkStubsPtr->ttk_GetBorderFromObj) /* 21 */\n#define Ttk_GetStickyFromObj \\\n\t(ttkStubsPtr->ttk_GetStickyFromObj) /* 22 */\n#define Ttk_MakePadding \\\n\t(ttkStubsPtr->ttk_MakePadding) /* 23 */\n#define Ttk_UniformPadding \\\n\t(ttkStubsPtr->ttk_UniformPadding) /* 24 */\n#define Ttk_AddPadding \\\n\t(ttkStubsPtr->ttk_AddPadding) /* 25 */\n#define Ttk_RelievePadding \\\n\t(ttkStubsPtr->ttk_RelievePadding) /* 26 */\n#define Ttk_MakeBox \\\n\t(ttkStubsPtr->ttk_MakeBox) /* 27 */\n#define Ttk_BoxContains \\\n\t(ttkStubsPtr->ttk_BoxContains) /* 28 */\n#define Ttk_PackBox \\\n\t(ttkStubsPtr->ttk_PackBox) /* 29 */\n#define Ttk_StickBox \\\n\t(ttkStubsPtr->ttk_StickBox) /* 30 */\n#define Ttk_AnchorBox \\\n\t(ttkStubsPtr->ttk_AnchorBox) /* 31 */\n#define Ttk_PadBox \\\n\t(ttkStubsPtr->ttk_PadBox) /* 32 */\n#define Ttk_ExpandBox \\\n\t(ttkStubsPtr->ttk_ExpandBox) /* 33 */\n#define Ttk_PlaceBox \\\n\t(ttkStubsPtr->ttk_PlaceBox) /* 34 */\n#define Ttk_NewBoxObj \\\n\t(ttkStubsPtr->ttk_NewBoxObj) /* 35 */\n/* Slot 36 is reserved */\n/* Slot 37 is reserved */\n/* Slot 38 is reserved */\n/* Slot 39 is reserved */\n#define Ttk_GetOrientFromObj \\\n\t(ttkStubsPtr->ttk_GetOrientFromObj) /* 40 */\n\n#endif /* defined(USE_TTK_STUBS) */\n\n/* !END!: Do not edit above this line. */\n\n#ifdef TK_NO_DEPRECATED\n#   undef Ttk_RegisterElementSpec\n#endif\n\n#endif /* _TTKDECLS */\n"
  },
  {
    "path": "generic/ttk/ttkDefaultTheme.c",
    "content": "/*\n * Copyright © 2003 Joe English\n *\n * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n\n#if defined(_WIN32)\n  #define WIN32_XDRAWLINE_HACK 1\n#else\n  #define WIN32_XDRAWLINE_HACK 0\n#endif\n\n#if defined(MAC_OSX_TK)\n  #define IGNORES_VISUAL\n#endif\n\n#define BORDERWIDTH     2\n#define SCROLLBAR_WIDTH 14\n#define MIN_THUMB_SIZE  8\n\n/*\n *----------------------------------------------------------------------\n *\n * Helper routines for border drawing:\n *\n * NOTE: MSUE specifies a slightly different arrangement\n * for button borders than for other elements; \"shadowColors\"\n * is for button borders.\n *\n * Please excuse the gross misspelling \"LITE\" for \"LIGHT\",\n * but it makes things line up nicer.\n */\n\nenum BorderColor { FLAT = 1, LITE = 2, DARK = 3, BRDR = 4 };\n\n/* top-left outer, top-left inner, bottom-right inner, bottom-right outer */\nstatic const enum BorderColor shadowColors[6][4] = {\n    { FLAT, FLAT, FLAT, FLAT },\t/* TK_RELIEF_FLAT   = 0*/\n    { DARK, LITE, DARK, LITE },\t/* TK_RELIEF_GROOVE = 1*/\n    { LITE, FLAT, DARK, BRDR },\t/* TK_RELIEF_RAISED = 2*/\n    { LITE, DARK, LITE, DARK },\t/* TK_RELIEF_RIDGE  = 3*/\n    { BRDR, BRDR, BRDR, BRDR },\t/* TK_RELIEF_SOLID  = 4*/\n    { BRDR, DARK, FLAT, LITE }\t/* TK_RELIEF_SUNKEN = 5*/\n};\n\n/* top-left, bottom-right */\nstatic const enum BorderColor thinShadowColors[6][4] = {\n    { FLAT, FLAT },\t/* TK_RELIEF_FLAT   = 0*/\n    { DARK, LITE },\t/* TK_RELIEF_GROOVE = 1*/\n    { LITE, DARK },\t/* TK_RELIEF_RAISED = 2*/\n    { LITE, DARK },\t/* TK_RELIEF_RIDGE  = 3*/\n    { BRDR, BRDR },\t/* TK_RELIEF_SOLID  = 4*/\n    { DARK, LITE }\t/* TK_RELIEF_SUNKEN = 5*/\n};\n\nstatic void DrawCorner(\n    Tk_Window tkwin,\n    Drawable d,\n    Tk_3DBorder border,\t\t\t\t/* get most GCs from here... */\n    GC borderGC,\t\t\t\t/* \"window border\" color GC */\n    int x, int y, int width, int height,\t/* where to draw */\n    bool corner,\t\t/* false => top left; true => bottom right */\n    enum BorderColor color)\n{\n    XPoint points[3];\n    GC gc;\n\n    --width; --height;\n    points[0].x = x;\t\t\t  points[0].y = y+height;\n    points[1].x = corner ? x + width : x; points[1].y = corner ? y + height : y;\n    points[2].x = x+width;\t\t  points[2].y = y;\n\n    if (corner) {\n\tpoints[2].y -= WIN32_XDRAWLINE_HACK;\n    } else {\n\tpoints[2].x += WIN32_XDRAWLINE_HACK;\n    }\n\n    if (color == BRDR) {\n\tgc = borderGC;\n    } else {\n\tgc = Tk_3DBorderGC(tkwin, border, (int)color);\n    }\n\n    XDrawLines(Tk_Display(tkwin), d, gc, points, 3, CoordModeOrigin);\n}\n\nstatic void DrawBorder(\n    Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,\n    Ttk_Box b, int borderWidth, int relief)\n{\n    GC borderGC = Tk_GCForColor(borderColor, d);\n\n    switch (borderWidth) {\n\tcase 2: /* \"thick\" border */\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x, b.y, b.width, b.height, false, shadowColors[relief][0]);\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x+1, b.y+1, b.width-2, b.height-2, false, shadowColors[relief][1]);\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x+1, b.y+1, b.width-2, b.height-2, true, shadowColors[relief][2]);\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x, b.y, b.width, b.height, true, shadowColors[relief][3]);\n\t    break;\n\tcase 1: /* \"thin\" border */\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x, b.y, b.width, b.height, false, thinShadowColors[relief][0]);\n\t    DrawCorner(tkwin, d, border, borderGC,\n\t\tb.x, b.y, b.width, b.height, true, thinShadowColors[relief][1]);\n\t    break;\n\tcase 0:\t/* no border -- do nothing */\n\t    break;\n\tdefault: /* Fall back to Motif-style borders: */\n\t    Tk_Draw3DRectangle(tkwin, d, border,\n\t\tb.x, b.y, b.width, b.height, borderWidth, relief);\n\t    break;\n    }\n}\n\n/* Alternate shadow colors for entry fields:\n * NOTE: FLAT color is normally white, and the LITE color is a darker shade.\n */\nstatic void DrawFieldBorder(\n    Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,\n    Ttk_Box b)\n{\n    GC borderGC = Tk_GCForColor(borderColor, d);\n    DrawCorner(tkwin, d, border, borderGC,\n\tb.x, b.y, b.width, b.height, false, DARK);\n    DrawCorner(tkwin, d, border, borderGC,\n\tb.x+1, b.y+1, b.width-2, b.height-2, false, BRDR);\n    DrawCorner(tkwin, d, border, borderGC,\n\tb.x+1, b.y+1, b.width-2, b.height-2, true, LITE);\n    DrawCorner(tkwin, d, border, borderGC,\n\tb.x, b.y, b.width, b.height, true, FLAT);\n    return;\n}\n\n/*\n * ArrowPoints --\n *\tCompute points of arrow polygon.\n */\nstatic void ArrowPoints(Ttk_Box b, ArrowDirection direction, XPoint points[4])\n{\n    int cx, cy, h;\n\n    switch (direction) {\n\tcase ARROW_UP:\n\t    h = (b.width - 1)/2;\n\t    cx = b.x + h;\n\t    cy = b.y;\n\t    if (b.height <= h) h = b.height - 1;\n\t    points[0].x = cx;\t\tpoints[0].y = cy;\n\t    points[1].x = cx - h;\tpoints[1].y = cy + h;\n\t    points[2].x = cx + h;\tpoints[2].y = cy + h;\n\t    break;\n\tcase ARROW_DOWN:\n\t    h = (b.width - 1)/2;\n\t    cx = b.x + h;\n\t    cy = b.y + b.height - 1;\n\t    if (b.height <= h) h = b.height - 1;\n\t    points[0].x = cx;\t\tpoints[0].y = cy;\n\t    points[1].x = cx - h;\tpoints[1].y = cy - h;\n\t    points[2].x = cx + h;\tpoints[2].y = cy - h;\n\t    break;\n\tcase ARROW_LEFT:\n\t    h = (b.height - 1)/2;\n\t    cx = b.x;\n\t    cy = b.y + h;\n\t    if (b.width <= h) h = b.width - 1;\n\t    points[0].x = cx;\t\tpoints[0].y = cy;\n\t    points[1].x = cx + h;\tpoints[1].y = cy - h;\n\t    points[2].x = cx + h;\tpoints[2].y = cy + h;\n\t    break;\n\tcase ARROW_RIGHT:\n\t    h = (b.height - 1)/2;\n\t    cx = b.x + b.width - 1;\n\t    cy = b.y + h;\n\t    if (b.width <= h) h = b.width - 1;\n\t    points[0].x = cx;\t\tpoints[0].y = cy;\n\t    points[1].x = cx - h;\tpoints[1].y = cy - h;\n\t    points[2].x = cx - h;\tpoints[2].y = cy + h;\n\t    break;\n    }\n\n    points[3].x = points[0].x;\n    points[3].y = points[0].y;\n}\n\n/*public*/\nvoid TtkArrowSize(int h, ArrowDirection direction, int *widthPtr, int *heightPtr)\n{\n    switch (direction) {\n\tcase ARROW_UP:\n\tcase ARROW_DOWN:\t*widthPtr = 2*h+1; *heightPtr = h+1; break;\n\tcase ARROW_LEFT:\n\tcase ARROW_RIGHT:\t*widthPtr = h+1; *heightPtr = 2*h+1;\n    }\n}\n\n/*\n * TtkDrawArrow, TtkFillArrow --\n *\tDraw an arrow in the indicated direction inside the specified box.\n */\n/*public*/\nvoid TtkFillArrow(\n    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection direction)\n{\n    XPoint points[4];\n    ArrowPoints(b, direction, points);\n    XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin);\n    XDrawLines(display, d, gc, points, 4, CoordModeOrigin);\n\n    /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */\n    XDrawPoint(display, d, gc, points[2].x, points[2].y);\n}\n\n/*public*/\nvoid TtkDrawArrow(\n    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection direction)\n{\n    XPoint points[4];\n    ArrowPoints(b, direction, points);\n    XDrawLines(display, d, gc, points, 4, CoordModeOrigin);\n\n    /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */\n    XDrawPoint(display, d, gc, points[2].x, points[2].y);\n}\n\n/*\n *----------------------------------------------------------------------\n * +++ Border element implementation.\n *\n * This border consists of (from outside-in):\n *\n * + a 1-pixel thick default indicator (defaultable widgets only)\n * + 1- or 2- pixel shaded border (controlled by -background and -relief)\n * + 1 pixel padding (???)\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*borderColorObj;\t/* Extra border color */\n    Tcl_Obj\t*borderWidthObj;\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*defaultStateObj;\t/* for buttons */\n} BorderElement;\n\nstatic const Ttk_ElementOptionSpec BorderElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER, offsetof(BorderElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { \"-bordercolor\",TK_OPTION_COLOR,\n\toffsetof(BorderElement,borderColorObj), \"black\" },\n    { \"-default\", TK_OPTION_ANY, offsetof(BorderElement,defaultStateObj),\n\t\"disabled\" },\n    { \"-borderwidth\",TK_OPTION_PIXELS, offsetof(BorderElement,borderWidthObj),\n\tSTRINGIFY(BORDERWIDTH) },\n    { \"-relief\", TK_OPTION_RELIEF, offsetof(BorderElement,reliefObj),\n\t\"flat\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void BorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    BorderElement *bd = (BorderElement *)elementRecord;\n    int borderWidth = 0;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n\n    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {\n\t++borderWidth;\n    }\n\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void BorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    BorderElement *bd = (BorderElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, bd->borderColorObj);\n    int borderWidth = 2;\n    int relief = TK_RELIEF_FLAT;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n\n    /*\n     * Get option values.\n     */\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n\n    if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {\n\tGC gc = Tk_GCForColor(borderColor, d);\n\tXDrawRectangle(Tk_Display(tkwin), d, gc,\n\t\tb.x, b.y, b.width-1, b.height-1);\n    }\n    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {\n\t/* Space for default ring: */\n\tb = Ttk_PadBox(b, Ttk_UniformPadding(1));\n    }\n\n    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec BorderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BorderElement),\n    BorderElementOptions,\n    BorderElementSize,\n    BorderElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Field element:\n *\tUsed for editable fields.\n */\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*borderColorObj;\t/* Extra border color */\n    Tcl_Obj\t*focusWidthObj;\n    Tcl_Obj\t*focusColorObj;\n} FieldElement;\n\nstatic const Ttk_ElementOptionSpec FieldElementOptions[] = {\n    { \"-fieldbackground\", TK_OPTION_BORDER, offsetof(FieldElement,borderObj),\n\t\"white\" },\n    { \"-bordercolor\",TK_OPTION_COLOR, offsetof(FieldElement,borderColorObj),\n\t\"black\" },\n    { \"-focuswidth\", TK_OPTION_PIXELS, offsetof(FieldElement,focusWidthObj),\n\t\"2\" },\n    { \"-focuscolor\", TK_OPTION_COLOR, offsetof(FieldElement,focusColorObj),\n\t\"#4a6984\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void FieldElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_UniformPadding(2);\n}\n\nstatic void FieldElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, field->borderColorObj);\n    int focusWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, field->focusWidthObj, &focusWidth);\n\n    if (focusWidth > 0 && (state & TTK_STATE_FOCUS)) {\n\tDisplay *disp = Tk_Display(tkwin);\n\tXColor *focusColor = Tk_GetColorFromObj(tkwin, field->focusColorObj);\n\tGC focusGC = Tk_GCForColor(focusColor, d);\n\n\tif (focusWidth > 1 && b.width >= 2 && b.height >= 2) {\n\t    int x1 = b.x, x2 = b.x + b.width - 1;\n\t    int y1 = b.y, y2 = b.y + b.height - 1;\n\t    int w = WIN32_XDRAWLINE_HACK;\n\t    GC bgGC = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);\n\n\t    /*\n\t     * Draw the outer rounded rectangle\n\t     */\n\t    XDrawLine(disp, d, focusGC, x1+1, y1, x2-1+w, y1);\t/* N */\n\t    XDrawLine(disp, d, focusGC, x1+1, y2, x2-1+w, y2);\t/* S */\n\t    XDrawLine(disp, d, focusGC, x1, y1+1, x1, y2-1+w);\t/* W */\n\t    XDrawLine(disp, d, focusGC, x2, y1+1, x2, y2-1+w);\t/* E */\n\n\t    /*\n\t     * Draw the inner rectangle\n\t     */\n\t    b.x += 1; b.y += 1; b.width -= 2; b.height -= 2;\n\t    XDrawRectangle(disp, d, focusGC, b.x, b.y, b.width-1, b.height-1);\n\n\t    /*\n\t     * Fill the inner rectangle\n\t     */\n\t    XFillRectangle(disp, d, bgGC, b.x+1, b.y+1, b.width-2, b.height-2);\n\t} else {\n\t    /*\n\t     * Draw the field element as usual\n\t     */\n\t    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t\t0, TK_RELIEF_SUNKEN);\n\t    DrawFieldBorder(tkwin, d, border, borderColor, b);\n\n\t    /*\n\t     * Change the color of the border's outermost pixels\n\t     */\n\t    XDrawRectangle(disp, d, focusGC, b.x, b.y, b.width-1, b.height-1);\n\t}\n    } else {\n\tTk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    0, TK_RELIEF_SUNKEN);\n\tDrawFieldBorder(tkwin, d, border, borderColor, b);\n    }\n}\n\nstatic const Ttk_ElementSpec FieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    FieldElementSize,\n    FieldElementDraw\n};\n\n/*------------------------------------------------------------------------\n * Indicators --\n */\n\n/*\n * Indicator image descriptor:\n */\ntypedef struct {\n    int width;\t\t\t\t/* unscaled width */\n    int height;\t\t\t\t/* unscaled height */\n    const char *const offDataPtr;\n    const char *const onDataPtr;\n} IndicatorSpec;\n\nstatic const char checkbtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v15h1v-14h14v-1z' fill='#888888'/>\\n\\\n     <path d='m1 1v13h1v-12h12v-1z' fill='#414141'/>\\n\\\n     <path d='m14 1v13h-13v1h14v-14z' fill='#d9d9d9'/>\\n\\\n     <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\\n\\\n     <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char checkbtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v15h1v-14h14v-1z' fill='#888888'/>\\n\\\n     <path d='m1 1v13h1v-12h12v-1z' fill='#414141'/>\\n\\\n     <path d='m14 1v13h-13v1h14v-14z' fill='#d9d9d9'/>\\n\\\n     <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\\n\\\n     <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\\n\\\n     <path d='m4.5 8 3 3 4-6' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec checkbutton_spec = {\n    16, 16,\n    checkbtnOffData,\n    checkbtnOnData\n};\n\nstatic const char radiobtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradientOuter' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#888888' offset='0'/>\\n\\\n       <stop stop-color='#eeeeee' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n      <linearGradient id='linearGradientInner' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#414141' offset='0'/>\\n\\\n       <stop stop-color='#d9d9d9' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradientOuter)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='url(#linearGradientInner)'/>\\n\\\n     <circle cx='8' cy='8' r='6' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradientOuter' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#888888' offset='0'/>\\n\\\n       <stop stop-color='#eeeeee' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n      <linearGradient id='linearGradientInner' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#414141' offset='0'/>\\n\\\n       <stop stop-color='#d9d9d9' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradientOuter)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='url(#linearGradientInner)'/>\\n\\\n     <circle cx='8' cy='8' r='6' fill='#ffffff'/>\\n\\\n     <circle cx='8' cy='8' r='3' fill='#000000'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec radiobutton_spec = {\n    16, 16,\n    radiobtnOffData,\n    radiobtnOnData\n};\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *colorObj;\n    Tcl_Obj *lightColorObj;\n    Tcl_Obj *shadeColorObj;\n    Tcl_Obj *borderColorObj;\n    Tcl_Obj *marginObj;\n} IndicatorElement;\n\nstatic const Ttk_ElementOptionSpec IndicatorElementOptions[] = {\n    { \"-indicatorbackground\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-indicatorforeground\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND },\n    { \"-indicatorcolor\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,colorObj), \"#FFFFFF\" },\n    { \"-lightcolor\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,lightColorObj), \"#DDDDDD\" },\n    { \"-shadecolor\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,shadeColorObj), \"#888888\" },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\t    offsetof(IndicatorElement,borderColorObj), \"black\" },\n    { \"-indicatormargin\", TK_OPTION_STRING,\n\t    offsetof(IndicatorElement,marginObj), \"0 2 4 2\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void IndicatorElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    *widthPtr = spec->width * scalingLevel + Ttk_PaddingWidth(margins);\n    *heightPtr = spec->height * scalingLevel + Ttk_PaddingHeight(margins);\n}\n\nstatic void ColorToStr(\n    const XColor *colorPtr, char *colorStr)\t/* in the format \"RRGGBB\" */\n{\n    snprintf(colorStr, 7, \"%02x%02x%02x\",\n\t     colorPtr->red >> 8, colorPtr->green >> 8, colorPtr->blue >> 8);\n}\n\nstatic void ImageChanged(\t\t/* to be passed to Tk_GetImage() */\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n}\n\nstatic void IndicatorElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding padding;\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int width = spec->width * scalingLevel;\n    int height = spec->height * scalingLevel;\n\n    char bgColorStr[7], fgColorStr[7], indicatorColorStr[7],\n\t shadeColorStr[7], borderColorStr[7];\n    unsigned int selected = (state & TTK_STATE_SELECTED);\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[70];\n    Tk_Image img;\n\n    const char *svgDataPtr;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *shadeColorPtr, *highlightColorPtr, *borderColorPtr, *bgColorPtr,\n\t *indicatorColorPtr, *fgColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);\n    b = Ttk_PadBox(b, padding);\n\n#if 0\n    /*\n     * Sanity check -- not needed and no longer used\n     */\n    if (   b.x < 0\n\t|| b.y < 0\n\t|| Tk_Width(tkwin) < b.x + width\n\t|| Tk_Height(tkwin) < b.y + height)\n    {\n\t/* Oops!  Not enough room to display the image.\n\t * Don't draw anything.\n\t */\n\treturn;\n    }\n#endif\n\n    /*\n     * Construct the color strings bgColorStr, fgColorStr,\n     * indicatorColorStr, shadeColorStr, and borderColorStr\n     */\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->backgroundObj),\n\t       bgColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->foregroundObj),\n\t       fgColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->colorObj),\n\t       indicatorColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->shadeColorObj),\n\t       shadeColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->borderColorObj),\n\t       borderColorStr);\n\n    /*\n     * Check whether there is an SVG image of this size for the indicator's\n     * type (0 = checkbtn, 1 = radiobtn) and these color strings\n     */\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::indicator_alt%d_%d_%s_%s_%s_%s_%s\",\n\t     width, spec->offDataPtr == radiobtnOffData,\n\t     shadeColorStr, indicatorColorStr, borderColorStr, bgColorStr,\n\t     selected ? fgColorStr : \"XXXXXX\");\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Determine the SVG data to use for the photo image\n\t */\n\tsvgDataPtr = (selected ? spec->onDataPtr : spec->offDataPtr);\n\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\n\tshadeColorPtr =\t    strstr(svgDataCopy, \"888888\");\n\thighlightColorPtr = strstr(svgDataCopy, \"eeeeee\");\n\tborderColorPtr =    strstr(svgDataCopy, \"414141\");\n\tbgColorPtr =\t    strstr(svgDataCopy, \"d9d9d9\");\n\tindicatorColorPtr = strstr(svgDataCopy, \"ffffff\");\n\tfgColorPtr =\t    strstr(svgDataCopy, \"000000\");\n\n\tassert(shadeColorPtr);\n\tassert(highlightColorPtr);\n\tassert(borderColorPtr);\n\tassert(bgColorPtr);\n\tassert(indicatorColorPtr);\n\n\tmemcpy(shadeColorPtr, shadeColorStr, 6);\n\tmemcpy(highlightColorPtr, indicatorColorStr, 6);\n\tmemcpy(borderColorPtr, borderColorStr, 6);\n\tmemcpy(bgColorPtr, bgColorStr, 6);\n\tmemcpy(indicatorColorPtr, indicatorColorStr, 6);\n\tif (fgColorPtr != NULL) {\n\t    memcpy(fgColorPtr, fgColorStr, 6);\n\t}\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Display the image\n     */\n    Tk_RedrawImage(img, 0, 0, width, height, d, b.x, b.y);\n    Tk_FreeImage(img);\n}\n\nstatic const Ttk_ElementSpec IndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(IndicatorElement),\n    IndicatorElementOptions,\n    IndicatorElementSize,\n    IndicatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Arrow element(s).\n *\n *\tDraws a solid triangle, inside a box.\n *\tclientData is an enum ArrowDirection pointer.\n */\n\ntypedef struct {\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *colorObj;\t\t/* Arrow color */\n    Tcl_Obj *borderObj;\n    Tcl_Obj *borderColorObj;\t/* Extra color for borders */\n    Tcl_Obj *reliefObj;\n} ArrowElement;\n\nstatic const Ttk_ElementOptionSpec ArrowElementOptions[] = {\n    { \"-arrowsize\", TK_OPTION_PIXELS,\n\toffsetof(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) },\n    { \"-arrowcolor\", TK_OPTION_COLOR,\n\toffsetof(ArrowElement,colorObj), \"black\"},\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(ArrowElement,borderColorObj), \"black\" },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(ArrowElement,reliefObj), \"raised\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * Note asymmetric padding:\n * top/left padding is 1 less than bottom/right,\n * since in this theme 2-pixel borders are asymmetric.\n */\nstatic const Ttk_Padding ArrowPadding = { 3,3,4,4 };\n\nstatic void ArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding;\n    int size = SCROLLBAR_WIDTH;\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.right = padding.left + 1;\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.bottom = padding.top + 1;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n    if (*widthPtr < *heightPtr) {\n\t*widthPtr = *heightPtr;\n    } else {\n\t*heightPtr = *widthPtr;\n    }\n}\n\nstatic void ArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj);\n    int borderWidth = 2, relief = TK_RELIEF_RAISED;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cx = 0, cy = 0;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);\n    GC gc = Tk_GCForColor(arrowColor, d);\n\n    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);\n\n    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    0, TK_RELIEF_FLAT);\n    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.right = padding.left + 1;\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.bottom = padding.top + 1;\n\n    b = Ttk_PadBox(b, padding);\n\n    switch (direction) {\n\tcase ARROW_UP:\n\tcase ARROW_DOWN:\n\t    TtkArrowSize(b.width/2, direction, &cx, &cy);\n\t    if ((b.height - cy) % 2 == 1) {\n\t\t++cy;\n\t    }\n\t    break;\n\tcase ARROW_LEFT:\n\tcase ARROW_RIGHT:\n\t    TtkArrowSize(b.height/2, direction, &cx, &cy);\n\t    if ((b.width - cx) % 2 == 1) {\n\t\t++cx;\n\t    }\n\t    break;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);\n}\n\nstatic const Ttk_ElementSpec ArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ArrowElement),\n    ArrowElementOptions,\n    ArrowElementSize,\n    ArrowElementDraw\n};\n\n/*\n * Modified arrow element for comboboxes and spinboxes:\n *\tThe width and height are different, and the left edge is drawn in the\n *\tsame color as the inner part of the right one.\n */\n\nstatic void BoxArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding;\n    int size = 14;\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    size += round(scalingLevel);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n}\n\nstatic void BoxArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj);\n    int borderWidth = 2, relief = TK_RELIEF_RAISED;\n    Display *disp = Tk_Display(tkwin);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n    int w = WIN32_XDRAWLINE_HACK;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cx = 0, cy = 0;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);\n    GC arrowGC = Tk_GCForColor(arrowColor, d);\n\n    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    0, TK_RELIEF_FLAT);\n    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);\n\n    XDrawLine(disp, d, darkGC, b.x, b.y+1, b.x, b.y+b.height-2+w);\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    b = Ttk_PadBox(b, padding);\n\n    TtkArrowSize(b.width/2, direction, &cx, &cy);\n    if ((b.height - cy) % 2 == 1) {\n\t++cy;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    TtkFillArrow(disp, d, arrowGC, b, direction);\n}\n\nstatic const Ttk_ElementSpec BoxArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ArrowElement),\n    ArrowElementOptions,\n    BoxArrowElementSize,\n    BoxArrowElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Menubutton indicator:\n *\tDraw an arrow in the direction where the menu will be posted.\n */\n\n#define MENUBUTTON_ARROW_SIZE 5\n\ntypedef struct {\n    Tcl_Obj *directionObj;\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *colorObj;\n} MenubuttonArrowElement;\n\nstatic const char *const directionStrings[] = {\t/* See also: button.c */\n    \"above\", \"below\", \"flush\", \"left\", \"right\", NULL\n};\nenum { POST_ABOVE, POST_BELOW, POST_FLUSH, POST_LEFT, POST_RIGHT };\n\nstatic const Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = {\n    { \"-direction\", TK_OPTION_STRING,\n\toffsetof(MenubuttonArrowElement,directionObj), \"below\" },\n    { \"-arrowsize\", TK_OPTION_PIXELS,\n\toffsetof(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},\n    { \"-arrowcolor\", TK_OPTION_COLOR,\n\toffsetof(MenubuttonArrowElement,colorObj), \"black\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic const Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 };\n\nstatic void MenubuttonArrowElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    MenubuttonArrowElement *arrow = (MenubuttonArrowElement *)elementRecord;\n    int size = MENUBUTTON_ARROW_SIZE;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n\n    padding.left = round(MenubuttonArrowPadding.left * scalingLevel);\n    padding.top = round(MenubuttonArrowPadding.top * scalingLevel);\n    padding.right = round(MenubuttonArrowPadding.right * scalingLevel);\n    padding.bottom = round(MenubuttonArrowPadding.bottom * scalingLevel);\n\n    *widthPtr = *heightPtr = 2 * size + 1;\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n}\n\nstatic void MenubuttonArrowElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    MenubuttonArrowElement *arrow = (MenubuttonArrowElement *)elementRecord;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);\n    GC gc = Tk_GCForColor(arrowColor, d);\n    int size = MENUBUTTON_ARROW_SIZE;\n    int postDirection = POST_BELOW;\n    ArrowDirection arrowDirection = ARROW_DOWN;\n    int width = 0, height = 0;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    Tcl_GetIndexFromObjStruct(NULL, arrow->directionObj, directionStrings,\n\t   sizeof(char *), \"\"/*message*/, 0/*flags*/, &postDirection);\n\n    /* ... this might not be such a great idea ... */\n    switch (postDirection) {\n\tcase POST_ABOVE:\tarrowDirection = ARROW_UP; break;\n\tcase POST_BELOW:\tarrowDirection = ARROW_DOWN; break;\n\tcase POST_LEFT:\t\tarrowDirection = ARROW_LEFT; break;\n\tcase POST_RIGHT:\tarrowDirection = ARROW_RIGHT; break;\n\tcase POST_FLUSH:\tarrowDirection = ARROW_DOWN; break;\n    }\n\n    TtkArrowSize(size, arrowDirection, &width, &height);\n\n    padding.left = round(MenubuttonArrowPadding.left * scalingLevel);\n    padding.top = round(MenubuttonArrowPadding.top * scalingLevel);\n    padding.right = round(MenubuttonArrowPadding.right * scalingLevel);\n    padding.bottom = round(MenubuttonArrowPadding.bottom * scalingLevel);\n\n    b = Ttk_PadBox(b, padding);\n    b = Ttk_AnchorBox(b, width, height, TK_ANCHOR_CENTER);\n    TtkFillArrow(Tk_Display(tkwin), d, gc, b, arrowDirection);\n}\n\nstatic const Ttk_ElementSpec MenubuttonArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(MenubuttonArrowElement),\n    MenubuttonArrowElementOptions,\n    MenubuttonArrowElementSize,\n    MenubuttonArrowElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Thumb element.\n */\n\ntypedef struct {\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *firstObj;\n    Tcl_Obj *lastObj;\n    Tcl_Obj *borderObj;\n    Tcl_Obj *borderColorObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *orientObj;\n} ThumbElement;\n\nstatic const Ttk_ElementOptionSpec ThumbElementOptions[] = {\n    { \"-width\", TK_OPTION_PIXELS, offsetof(ThumbElement,sizeObj),\n\tSTRINGIFY(SCROLLBAR_WIDTH) },\n    { \"-background\", TK_OPTION_BORDER, offsetof(ThumbElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { \"-bordercolor\", TK_OPTION_COLOR, offsetof(ThumbElement,borderColorObj),\n\t\"black\" },\n    { \"-relief\", TK_OPTION_RELIEF, offsetof(ThumbElement,reliefObj),\"raised\" },\n    { \"-orient\", TK_OPTION_ANY, offsetof(ThumbElement,orientObj),\"horizontal\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void ThumbElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ThumbElement *thumb = (ThumbElement *)elementRecord;\n    Ttk_Orient orient;\n    int size;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size);\n    Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);\n\n    if (orient == TTK_ORIENT_VERTICAL) {\n\t*widthPtr = size;\n\t*heightPtr = MIN_THUMB_SIZE;\n    } else {\n\t*widthPtr = MIN_THUMB_SIZE;\n\t*heightPtr = size;\n    }\n}\n\nstatic void ThumbElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ThumbElement *thumb = (ThumbElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, thumb->borderColorObj);\n    int relief = TK_RELIEF_RAISED;\n    int borderWidth = 2;\n\n    /*\n     * Don't draw the thumb if we are disabled.\n     * This makes it behave like Windows ... if that's what we want.\n    if (state & TTK_STATE_DISABLED) {\n\treturn;\n    }\n     */\n\n    Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);\n\n    Tk_Fill3DRectangle(\n\ttkwin, d, border, b.x,b.y,b.width,b.height, 0, TK_RELIEF_FLAT);\n    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec ThumbElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ThumbElement),\n    ThumbElementOptions,\n    ThumbElementSize,\n    ThumbElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Slider element.\n *\n * This is the moving part of the scale widget.\n *\n * The slider element is the thumb in the scale widget. This is drawn\n * as an arrow-type element that can point up, down, left or right.\n *\n */\n\ntypedef struct {\n    Tcl_Obj *thicknessObj;\t/* Short axis dimension */\n    Tcl_Obj *reliefObj;\t\t/* Relief for this object */\n    Tcl_Obj *borderObj;\t\t/* Border / background color */\n    Tcl_Obj *borderColorObj;\t/* Additional border color */\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *orientObj;\t\t/* Orientation of overall slider */\n} SliderElement;\n\nstatic const Ttk_ElementOptionSpec SliderElementOptions[] = {\n    { \"-sliderthickness\",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj),\n\t\"15\" },\n    { \"-sliderrelief\", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj),\n\t\"raised\" },\n    { \"-background\", TK_OPTION_BORDER, offsetof(SliderElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { \"-bordercolor\", TK_OPTION_COLOR, offsetof(SliderElement,borderColorObj),\n\t\"black\" },\n    { \"-borderwidth\", TK_OPTION_PIXELS, offsetof(SliderElement,borderWidthObj),\n\tSTRINGIFY(BORDERWIDTH) },\n    { \"-orient\", TK_OPTION_ANY, offsetof(SliderElement,orientObj),\n\t\"horizontal\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SliderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Ttk_Orient orient;\n    int thickness, borderWidth;\n\n    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);\n\n    switch (orient) {\n\tcase TTK_ORIENT_VERTICAL:\n\t    *widthPtr = thickness + (borderWidth *2);\n\t    *heightPtr = *widthPtr/2;\n\t    break;\n\tcase TTK_ORIENT_HORIZONTAL:\n\t    *heightPtr = thickness + (borderWidth *2);\n\t    *widthPtr = *heightPtr/2;\n\t    break;\n    }\n}\n\nstatic void SliderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj);\n    int relief = TK_RELIEF_RAISED, borderWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);\n\n    Tk_Fill3DRectangle(tkwin, d, border,\n\tb.x, b.y, b.width, b.height,\n\tborderWidth, TK_RELIEF_FLAT);\n    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SliderElement),\n    SliderElementOptions,\n    SliderElementSize,\n    SliderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Tree indicator element.\n */\n\ntypedef struct {\n    Tcl_Obj *colorObj;\n    Tcl_Obj *marginObj;\n    Tcl_Obj *sizeObj;\n} TreeitemIndicator;\n\nstatic const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {\n    { \"-foreground\", TK_OPTION_COLOR,\n\toffsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },\n    { \"-size\", TK_OPTION_PIXELS,\n\toffsetof(TreeitemIndicator,sizeObj), \"6.75p\" },\n    { \"-indicatormargins\", TK_OPTION_STRING,\n\toffsetof(TreeitemIndicator,marginObj), \"2 2 4 2\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TreeitemIndicatorSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;\n    int size = 0;\n    Ttk_Padding margins;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);\n    if (size % 2 == 0) --size;  /* An odd size is better for the indicator. */\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    *widthPtr = size + Ttk_PaddingWidth(margins);\n    *heightPtr = size + Ttk_PaddingHeight(margins);\n}\n\nstatic void TreeitemIndicatorDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;\n    XColor *color = Tk_GetColorFromObj(tkwin, indicator->colorObj);\n    GC gc = Tk_GCForColor(color, d);\n    Ttk_Padding padding = Ttk_UniformPadding(0);\n    int w = WIN32_XDRAWLINE_HACK;\n    int cx, cy;\n\n    if (state & TTK_STATE_LEAF) {\n\t/* don't draw anything ... */\n\treturn;\n    }\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);\n    b = Ttk_PadBox(b, padding);\n\n    XDrawRectangle(Tk_Display(tkwin), d, gc,\n\t    b.x, b.y, b.width - 1, b.height - 1);\n\n    cx = b.x + (b.width - 1) / 2;\n    cy = b.y + (b.height - 1) / 2;\n    XDrawLine(Tk_Display(tkwin), d, gc, b.x+2, cy, b.x+b.width-3+w, cy);\n\n    if (!(state & TTK_STATE_OPEN)) {\n\t/* turn '-' into a '+' */\n\tXDrawLine(Tk_Display(tkwin), d, gc, cx, b.y+2, cx, b.y+b.height-3+w);\n    }\n}\n\nstatic const Ttk_ElementSpec TreeitemIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TreeitemIndicator),\n    TreeitemIndicatorOptions,\n    TreeitemIndicatorSize,\n    TreeitemIndicatorDraw\n};\n\n/*------------------------------------------------------------------------\n * TtkAltTheme_Init --\n *\tInstall alternate theme.\n */\n\nMODULE_SCOPE int\nTtkAltTheme_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme =  Ttk_CreateTheme(interp, \"alt\", NULL);\n\n    if (!theme) {\n\treturn TCL_ERROR;\n    }\n\n    Ttk_RegisterElement(interp, theme, \"border\", &BorderElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"Checkbutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&checkbutton_spec);\n    Ttk_RegisterElement(interp, theme, \"Radiobutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&radiobutton_spec);\n    Ttk_RegisterElement(interp, theme, \"Menubutton.indicator\",\n\t    &MenubuttonArrowElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"field\", &FieldElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"thumb\", &ThumbElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"slider\", &SliderElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"uparrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.uparrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"downarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.downarrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"Combobox.downarrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"leftarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_LEFT));\n    Ttk_RegisterElement(interp, theme, \"rightarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));\n    Ttk_RegisterElement(interp, theme, \"arrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n\n    Ttk_RegisterElement(interp, theme, \"Treeitem.indicator\",\n\t    &TreeitemIndicatorElementSpec, NULL);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::alt\", TTK_VERSION);\n\n    return TCL_OK;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkElements.c",
    "content": "/*\n * Copyright © 2003 Joe English\n *\n * Default implementation for themed elements.\n *\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n\n#if defined(_WIN32)\n  #define WIN32_XDRAWLINE_HACK 1\n#else\n  #define WIN32_XDRAWLINE_HACK 0\n#endif\n\n#define DEFAULT_BORDERWIDTH \"2\"\n#define DEFAULT_ARROW_SIZE \"15\"\n#define MIN_THUMB_SIZE 10\n\n/*\n *----------------------------------------------------------------------\n *\n * Helper routine for drawing a few style elements:\n *\n * The following function is needed when drawing the trough element\n * (which is used in scrollbars, scales, and progressbars) and the\n * arrow and thumb elements of a scrollbar.  It draws the light or dark\n * border color along the entire bottom and right edges, contrary to\n * the Tk_Fill3DRectangle function, which on the windowing systems x11\n * and aqua draws the light or dark border color along the entire top\n * and left edges instead.\n *\n * An alternative approach would be to modify the function\n * Tk_3DHorizontalBevel in the file unix/tkUnix3d.c.  That function is\n * called in Tk_Draw3DRectangle, which in turn is invoked in\n * Tk_Fill3DRectangle (both functions are implemented in the file\n * generic/tk3d.c).  With that approach there would be no need for the\n * Fill3DRectangle function below, but it would result in some (minor)\n * changes related to the appearance of most Tk and Ttk widgets on x11\n * and aqua.\n */\n\n#if defined(_WIN32)\n#define Fill3DRectangle Tk_Fill3DRectangle\n#else\nstatic void Fill3DRectangle(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y,\t\t/* Upper-left corner of the rectangle. */\n    int width, int height,\t/* The width and height of the rectangle. */\n    int borderWidth,\t\t/* Desired width for border, in pixels. Border\n\t\t\t\t * will be *inside* region. */\n    int relief)\t\t\t/* Indicates 3D effect: TK_RELIEF_FLAT,\n\t\t\t\t * TK_RELIEF_RAISED, TK_RELIEF_SUNKEN, etc. */\n{\n    if (borderWidth == 1 && width >= 2 && height >= 2 &&\n\t    (relief == TK_RELIEF_RAISED || relief == TK_RELIEF_SUNKEN)) {\n\tGC flatGC  = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);\n\tGC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n\tGC darkGC  = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\tGC nGC, wGC, sGC, eGC;\n\tint x1 = x, x2 = x + width - 1;\n\tint y1 = y, y2 = y + height - 1;\n\n\tXFillRectangle(Tk_Display(tkwin), drawable, flatGC,\n\t\tx + 1, y + 1, width - 2, height - 2);\n\n\tnGC = wGC = (relief == TK_RELIEF_RAISED ? lightGC : darkGC);\n\tsGC = eGC = (relief == TK_RELIEF_RAISED ? darkGC : lightGC);\n\n\tXDrawLine(Tk_Display(tkwin), drawable, nGC, x1, y1, x2-1, y1);\t/* N */\n\tXDrawLine(Tk_Display(tkwin), drawable, wGC, x1, y1, x1, y2-1);\t/* W */\n\tXDrawLine(Tk_Display(tkwin), drawable, sGC, x1, y2, x2, y2);\t/* S */\n\tXDrawLine(Tk_Display(tkwin), drawable, eGC, x2, y1, x2, y2);\t/* E */\n    } else {\n\tTk_Fill3DRectangle(tkwin, drawable, border, x, y, width, height,\n\t\tborderWidth, relief);\n    }\n}\n#endif\n\n/*----------------------------------------------------------------------\n * +++ Null element.  Does nothing; used as a stub.\n * Null element methods, option table and element spec are public,\n * and may be used in other engines.\n */\n\n/* public */ const Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, TK_OPTION_BOOLEAN, 0, NULL } };\n\n/* public */ void\nTtkNullElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    TCL_UNUSED(Ttk_Padding *))\n{\n}\n\n/* public */ void\nTtkNullElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(Drawable),\n    TCL_UNUSED(Ttk_Box),\n    TCL_UNUSED(Ttk_State))\n{\n}\n\n/* public */ Ttk_ElementSpec ttkNullElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TtkNullElementSize,\n    TtkNullElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Background and fill elements.\n *\n * The fill element fills its parcel with the background color.\n * The background element ignores the parcel, and fills the entire window.\n *\n * Ttk_GetLayout() automatically includes a background element.\n */\n\ntypedef struct {\n    Tcl_Obj\t*backgroundObj;\n} BackgroundElement;\n\nstatic const Ttk_ElementOptionSpec BackgroundElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\t    offsetof(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void FillElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    BackgroundElement *bg = (BackgroundElement *)elementRecord;\n    Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin, bg->backgroundObj);\n\n    XFillRectangle(Tk_Display(tkwin), d,\n\tTk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),\n\tb.x, b.y, b.width, b.height);\n}\n\nstatic void BackgroundElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d,\n    TCL_UNUSED(Ttk_Box),\n    Ttk_State state)\n{\n    FillElementDraw(\n\tclientData, elementRecord, tkwin,\n\td, Ttk_WinBox(tkwin), state);\n}\n\nstatic const Ttk_ElementSpec FillElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BackgroundElement),\n    BackgroundElementOptions,\n    TtkNullElementSize,\n    FillElementDraw\n};\n\nstatic const Ttk_ElementSpec BackgroundElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BackgroundElement),\n    BackgroundElementOptions,\n    TtkNullElementSize,\n    BackgroundElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Border element.\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*borderWidthObj;\n    Tcl_Obj\t*reliefObj;\n} BorderElement;\n\nstatic const Ttk_ElementOptionSpec BorderElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(BorderElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(BorderElement,reliefObj), \"flat\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void BorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    BorderElement *bd = (BorderElement *)elementRecord;\n    int borderWidth = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void BorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    BorderElement *bd = (BorderElement *)elementRecord;\n    Tk_3DBorder border = NULL;\n    int borderWidth = 1, relief = TK_RELIEF_FLAT;\n\n    border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);\n    Tk_GetPixelsFromObj(NULL, tkwin, bd->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);\n\n    if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) {\n\tTk_Draw3DRectangle(tkwin, d, border,\n\t    b.x, b.y, b.width, b.height, borderWidth, relief);\n    }\n}\n\nstatic const Ttk_ElementSpec BorderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BorderElement),\n    BorderElementOptions,\n    BorderElementSize,\n    BorderElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Field element.\n *\tUsed for editable fields.\n */\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*borderWidthObj;\n    Tcl_Obj\t*focusWidthObj;\n    Tcl_Obj\t*focusColorObj;\n} FieldElement;\n\nstatic const Ttk_ElementOptionSpec FieldElementOptions[] = {\n    { \"-fieldbackground\", TK_OPTION_BORDER,\n\toffsetof(FieldElement,borderObj), \"white\" },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(FieldElement,borderWidthObj), \"2\" },\n    { \"-focuswidth\", TK_OPTION_PIXELS,\n\toffsetof(FieldElement,focusWidthObj), \"2\" },\n    { \"-focuscolor\", TK_OPTION_COLOR,\n\toffsetof(FieldElement,focusColorObj), \"#4a6984\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n\nstatic void FieldElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    int borderWidth = 2, focusWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, field->focusWidthObj, &focusWidth);\n    if (focusWidth > 0 && borderWidth < 2) {\n\tborderWidth += (focusWidth - borderWidth);\n    }\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void FieldElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);\n    int focusWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, field->focusWidthObj, &focusWidth);\n\n    if (focusWidth > 0 && (state & TTK_STATE_FOCUS)) {\n\tDisplay *disp = Tk_Display(tkwin);\n\tXColor *focusColor = Tk_GetColorFromObj(tkwin, field->focusColorObj);\n\tGC focusGC = Tk_GCForColor(focusColor, d);\n\n\tif (focusWidth > 1 && b.width >= 2 && b.height >= 2) {\n\t    int x1 = b.x, x2 = b.x + b.width - 1;\n\t    int y1 = b.y, y2 = b.y + b.height - 1;\n\t    int w = WIN32_XDRAWLINE_HACK;\n\t    GC bgGC = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);\n\n\t    /*\n\t     * Draw the outer rounded rectangle\n\t     */\n\t    XDrawLine(disp, d, focusGC, x1+1, y1, x2-1+w, y1);\t/* N */\n\t    XDrawLine(disp, d, focusGC, x1+1, y2, x2-1+w, y2);\t/* S */\n\t    XDrawLine(disp, d, focusGC, x1, y1+1, x1, y2-1+w);\t/* W */\n\t    XDrawLine(disp, d, focusGC, x2, y1+1, x2, y2-1+w);\t/* E */\n\n\t    /*\n\t     * Draw the inner rectangle\n\t     */\n\t    b.x += 1; b.y += 1; b.width -= 2; b.height -= 2;\n\t    XDrawRectangle(disp, d, focusGC, b.x, b.y, b.width-1, b.height-1);\n\n\t    /*\n\t     * Fill the inner rectangle\n\t     */\n\t    XFillRectangle(disp, d, bgGC, b.x+1, b.y+1, b.width-2, b.height-2);\n\t} else {\n\t    /*\n\t     * Draw the field element as usual\n\t     */\n\t    int borderWidth = 2;\n\t    Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj,\n\t\t    &borderWidth);\n\t    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t\t    borderWidth, TK_RELIEF_SUNKEN);\n\n\t    /*\n\t     * Change the color of the border's outermost pixels\n\t     */\n\t    XDrawRectangle(disp, d, focusGC, b.x, b.y, b.width-1, b.height-1);\n\t}\n    } else {\n\tint borderWidth = 2;\n\tTk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);\n\tTk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t\tborderWidth, TK_RELIEF_SUNKEN);\n    }\n}\n\nstatic const Ttk_ElementSpec FieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    FieldElementSize,\n    FieldElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Padding element.\n *\n * This element has no visual representation, only geometry.\n * It adds a (possibly non-uniform) internal border.\n * In addition, if \"-shiftrelief\" is specified,\n * adds additional pixels to shift child elements \"in\" or \"out\"\n * depending on the -relief.\n */\n\ntypedef struct {\n    Tcl_Obj\t*paddingObj;\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*shiftreliefObj;\n} PaddingElement;\n\nstatic const Ttk_ElementOptionSpec PaddingElementOptions[] = {\n    { \"-padding\", TK_OPTION_STRING,\n\toffsetof(PaddingElement,paddingObj), \"0\" },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(PaddingElement,reliefObj), \"flat\" },\n    { \"-shiftrelief\", TK_OPTION_PIXELS,\n\toffsetof(PaddingElement,shiftreliefObj), \"0\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void PaddingElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    PaddingElement *padding = (PaddingElement *)elementRecord;\n    int shiftRelief = 0;\n    int relief = TK_RELIEF_FLAT;\n    Ttk_Padding pad;\n\n    Tk_GetReliefFromObj(NULL, padding->reliefObj, &relief);\n    Tk_GetPixelsFromObj(NULL, tkwin, padding->shiftreliefObj, &shiftRelief);\n    Ttk_GetPaddingFromObj(NULL, tkwin, padding->paddingObj, &pad);\n    *paddingPtr = Ttk_RelievePadding(pad, relief, shiftRelief);\n}\n\nstatic const Ttk_ElementSpec PaddingElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(PaddingElement),\n    PaddingElementOptions,\n    PaddingElementSize,\n    TtkNullElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Focus ring element.\n *\tDraws a dashed focus ring, if the widget has keyboard focus.\n */\ntypedef struct {\n    Tcl_Obj\t*focusColorObj;\n    Tcl_Obj\t*focusThicknessObj;\n    Tcl_Obj\t*focusSolidObj;\n} FocusElement;\n\n/*\n * DrawFocusRing --\n *\tDraw a dotted rectangle to indicate focus.\n */\nstatic void DrawFocusRing(\n    Tk_Window tkwin, Drawable d, Tcl_Obj *colorObj, int thickness, int solid,\n    Ttk_Box b)\n{\n    XColor *color = Tk_GetColorFromObj(tkwin, colorObj);\n    XGCValues gcValues;\n    GC gc;\n    Display *disp = Tk_Display(tkwin);\n\n    if (thickness < 1 && solid) {\n\tthickness = 1;\n    }\n\n    gcValues.foreground = color->pixel;\n    gc = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\n    if (solid) {\n\tif (b.width >= 2*thickness && b.height >= 2*thickness) {\n\t    XRectangle rects[4] = {\n\t\t{(short)b.x, (short)b.y,\n\t\t (unsigned short)b.width, (unsigned short)thickness},\t/* N */\n\n\t\t{(short)b.x, (short)(b.y + b.height - thickness),\n\t\t (unsigned short)b.width, (unsigned short)thickness},\t/* S */\n\n\t\t{(short)b.x, (short)(b.y + thickness),\n\t\t (unsigned short)thickness,\n\t\t (unsigned short)(b.height - 2*thickness)},\t\t/* W */\n\n\t\t{(short)(b.x + b.width - thickness), (short)(b.y + thickness),\n\t\t (unsigned short)thickness,\n\t\t (unsigned short)(b.height - 2*thickness)}\t\t/* E */\n\t    };\n\n\t    XFillRectangles(disp, d, gc, rects, 4);\n\t}\n    } else {\n\tTkDrawDottedRect(disp, d, gc, b.x, b.y, b.width, b.height);\n    }\n\n    Tk_FreeGC(Tk_Display(tkwin), gc);\n}\n\nstatic const Ttk_ElementOptionSpec FocusElementOptions[] = {\n    { \"-focuscolor\", TK_OPTION_COLOR,\n\toffsetof(FocusElement,focusColorObj), \"black\" },\n    { \"-focusthickness\", TK_OPTION_PIXELS,\n\toffsetof(FocusElement,focusThicknessObj), \"1\" },\n    { \"-focussolid\", TK_OPTION_BOOLEAN,\n\toffsetof(FocusElement,focusSolidObj), \"0\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void FocusElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    FocusElement *focus = (FocusElement *)elementRecord;\n    int focusThickness = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, focus->focusThicknessObj, &focusThickness);\n    *paddingPtr = Ttk_UniformPadding((short)focusThickness);\n}\n\nstatic void FocusElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    FocusElement *focus = (FocusElement *)elementRecord;\n    int focusThickness = 0;\n    int focusSolid = 0;\n\n    if (state & TTK_STATE_FOCUS) {\n\tTk_GetPixelsFromObj(NULL, tkwin, focus->focusThicknessObj, &focusThickness);\n\tTcl_GetBooleanFromObj(NULL, focus->focusSolidObj, &focusSolid);\n\tDrawFocusRing(tkwin, d, focus->focusColorObj, focusThickness,\n\t    focusSolid, b);\n    }\n}\n\nstatic const Ttk_ElementSpec FocusElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FocusElement),\n    FocusElementOptions,\n    FocusElementSize,\n    FocusElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Separator element.\n *\tJust draws a horizontal or vertical bar.\n *\tThree elements are defined: horizontal, vertical, and general;\n *\tthe general separator checks the \"-orient\" option.\n */\n\ntypedef struct {\n    Tcl_Obj\t*orientObj;\n    Tcl_Obj\t*borderObj;\n} SeparatorElement;\n\nstatic const Ttk_ElementOptionSpec SeparatorElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY,\n\toffsetof(SeparatorElement, orientObj), \"horizontal\" },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(SeparatorElement,borderObj), DEFAULT_BACKGROUND },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SeparatorElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    *widthPtr = *heightPtr = 2;\n}\n\nstatic void HorizontalSeparatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SeparatorElement *separator = (SeparatorElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);\n    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\n    XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x + b.width, b.y);\n    XDrawLine(Tk_Display(tkwin), d, lightGC, b.x, b.y+1, b.x + b.width, b.y+1);\n}\n\nstatic void VerticalSeparatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SeparatorElement *separator = (SeparatorElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);\n    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n\n    XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x, b.y + b.height);\n    XDrawLine(Tk_Display(tkwin), d, lightGC, b.x+1, b.y, b.x+1, b.y+b.height);\n}\n\nstatic void GeneralSeparatorElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    SeparatorElement *separator = (SeparatorElement *)elementRecord;\n    Ttk_Orient orient;\n\n    Ttk_GetOrientFromObj(NULL, separator->orientObj, &orient);\n    switch (orient) {\n\tcase TTK_ORIENT_HORIZONTAL:\n\t    HorizontalSeparatorElementDraw(\n\t\tclientData, elementRecord, tkwin, d, b, state);\n\t    break;\n\tcase TTK_ORIENT_VERTICAL:\n\t    VerticalSeparatorElementDraw(\n\t\tclientData, elementRecord, tkwin, d, b, state);\n\t    break;\n    }\n}\n\nstatic const Ttk_ElementSpec HorizontalSeparatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SeparatorElement),\n    SeparatorElementOptions,\n    SeparatorElementSize,\n    HorizontalSeparatorElementDraw\n};\n\nstatic const Ttk_ElementSpec VerticalSeparatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SeparatorElement),\n    SeparatorElementOptions,\n    SeparatorElementSize,\n    HorizontalSeparatorElementDraw\n};\n\nstatic const Ttk_ElementSpec SeparatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SeparatorElement),\n    SeparatorElementOptions,\n    SeparatorElementSize,\n    GeneralSeparatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Sizegrip: lower-right corner grip handle for resizing window.\n */\n\ntypedef struct {\n    Tcl_Obj\t*backgroundObj;\n    Tcl_Obj\t*gripSizeObj;\n} SizegripElement;\n\nstatic const Ttk_ElementOptionSpec SizegripOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(SizegripElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-gripsize\", TK_OPTION_PIXELS,\n\toffsetof(SizegripElement,gripSizeObj), \"11.25p\" },\n    {NULL, TK_OPTION_BOOLEAN, 0, 0}\n};\n\nstatic void SizegripSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SizegripElement *grip = (SizegripElement *)elementRecord;\n    int gripSize = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n    *widthPtr = *heightPtr = gripSize;\n}\n\nstatic void SizegripDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SizegripElement *grip = (SizegripElement *)elementRecord;\n    int gripSize = 0;\n    int gripCount = 3, gripSpace, gripThickness;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->backgroundObj);\n    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n    int x1 = b.x + b.width-1, y1 = b.y + b.height-1, x2 = x1, y2 = y1;\n    int w = WIN32_XDRAWLINE_HACK;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n    gripThickness = gripSize * 3 / (gripCount * 5);\n    gripSpace = gripSize / 3 - gripThickness;\n    while (gripCount--) {\n\tx1 -= gripSpace; y2 -= gripSpace;\n\tfor (int i = 1; i < gripThickness; i++) {\n\t    XDrawLine(Tk_Display(tkwin), d, darkGC,\n\t\t    x1, y1, x2+w, y2-w);\t--x1; --y2;\n\t}\n\tXDrawLine(Tk_Display(tkwin), d, lightGC,\n\t\tx1, y1, x2+w, y2-w);\t\t--x1; --y2;\n    }\n}\n\nstatic const Ttk_ElementSpec SizegripElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SizegripElement),\n    SizegripOptions,\n    SizegripSize,\n    SizegripDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Indicator element.\n *\n * Draws the on/off indicator for checkbuttons and radiobuttons.\n */\n\n/*\n * Indicator image descriptor:\n */\ntypedef struct {\n    int width;\t\t\t\t/* unscaled width */\n    int height;\t\t\t\t/* unscaled height */\n    const char *const offDataPtr;\n    const char *const onDataPtr;\n    const char *const triDataPtr;\n} IndicatorSpec;\n\nstatic const char checkbtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <rect x='.5' y='.5' width='15' height='15' rx='3.5' fill='#ffffff' stroke='#888888'/>\\n\\\n    </svg>\";\n\nstatic const char checkbtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <rect x='0' y='0' width='16' height='16' fill='#4a6984' rx='4'/>\\n\\\n     <path d='m4.5 8 3 3 4-6' fill='none' stroke='#ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const char checkbtnTriData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <rect x='0' y='0' width='16' height='16' fill='#4a6984' rx='4'/>\\n\\\n     <path d='m4 8h8' fill='none' stroke='#ffffff' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec checkbutton_spec = {\n    16, 16,\n    checkbtnOffData,\n    checkbtnOnData,\n    checkbtnTriData\n};\n\nstatic const char radiobtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <circle cx='8' cy='8' r='7.5' fill='#ffffff' stroke='#888888'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <circle cx='8' cy='8' r='8' fill='#4a6984'/>\\n\\\n     <circle cx='8' cy='8' r='3' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnTriData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <circle cx='8' cy='8' r='8' fill='#4a6984'/>\\n\\\n     <path d='m4 8h8' fill='none' stroke='#ffffff' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const IndicatorSpec radiobutton_spec = {\n    16, 16,\n    radiobtnOffData,\n    radiobtnOnData,\n    radiobtnTriData\n};\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *borderColorObj;\n    Tcl_Obj *marginObj;\n} IndicatorElement;\n\n/*\n * Note that the -indicatorbackground and -indicatorforeground options below\n * have the same default value \"#ffffff\", but the -indicatorforeground option\n * will only be used for the alternate and selected states, in which the\n * -indicatorbackground option will have a different value (e.g., \"#4a6984\").\n */\nstatic const Ttk_ElementOptionSpec IndicatorElementOptions[] = {\n    { \"-indicatorbackground\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,backgroundObj), \"#ffffff\" },\n    { \"-indicatorforeground\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,foregroundObj), \"#ffffff\" },\n    { \"-bordercolor\", TK_OPTION_COLOR,\n\toffsetof(IndicatorElement,borderColorObj), \"#888888\" },\n    { \"-indicatormargin\", TK_OPTION_STRING,\n\toffsetof(IndicatorElement,marginObj), \"0 2 4 2\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void IndicatorElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);\n    *widthPtr = spec->width * scalingLevel + Ttk_PaddingWidth(margins);\n    *heightPtr = spec->height * scalingLevel + Ttk_PaddingHeight(margins);\n}\n\nstatic void ColorToStr(\n    const XColor *colorPtr, char *colorStr)     /* in the format \"RRGGBB\" */\n{\n    snprintf(colorStr, 7, \"%02x%02x%02x\",\n\t     colorPtr->red >> 8, colorPtr->green >> 8, colorPtr->blue >> 8);\n}\n\nstatic void ImageChanged(               /* to be passed to Tk_GetImage() */\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n}\n\nstatic void IndicatorElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    IndicatorElement *indicator = (IndicatorElement *)elementRecord;\n    Ttk_Padding padding;\n    const IndicatorSpec *spec = (const IndicatorSpec *)clientData;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int width = spec->width * scalingLevel;\n    int height = spec->height * scalingLevel;\n\n    char bgColorStr[7], fgColorStr[7], borderColorStr[7];\n    unsigned int selected = (state & TTK_STATE_SELECTED);\n    unsigned int tristate = (state & TTK_STATE_ALTERNATE);\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[60];\n    Tk_Image img;\n\n    const char *svgDataPtr;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *bgColorPtr, *fgColorPtr, *borderColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);\n    b = Ttk_PadBox(b, padding);\n\n#if 0\n    /*\n     * Sanity check -- not needed and no longer used\n     */\n    if (   b.x < 0\n\t|| b.y < 0\n\t|| Tk_Width(tkwin) < b.x + width\n\t|| Tk_Height(tkwin) < b.y + height)\n    {\n\t/* Oops!  Not enough room to display the image.\n\t * Don't draw anything.\n\t */\n\treturn;\n    }\n#endif\n\n    /*\n     * Construct the color strings bgColorStr, fgColorStr, and borderColorStr\n     */\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->backgroundObj),\n\t       bgColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->foregroundObj),\n\t       fgColorStr);\n    ColorToStr(Tk_GetColorFromObj(tkwin, indicator->borderColorObj),\n\t       borderColorStr);\n\n    /*\n     * Check whether there is an SVG image of this size for the\n     * indicator's type (0 = checkbtn, 1 = radiobtn), \"state\"\n     * (0 = off, 1 = on, 2 = tristate), and these color strings\n     */\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::indicator_default%d_%d,%d_%s_%s_%s\",\n\t     width,\n\t     spec->offDataPtr == radiobtnOffData,\n\t     tristate ? 2 : (selected ? 1 : 0),\n\t     bgColorStr,\n\t     selected || tristate ? fgColorStr : \"XXXXXX\",\n\t     selected || tristate ? \"XXXXXX\" : borderColorStr);\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Determine the SVG data to use for the photo image\n\t */\n\tsvgDataPtr = (tristate ? spec->triDataPtr :\n\t\t      (selected ? spec->onDataPtr : spec->offDataPtr));\n\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\tif (selected || tristate) {\n\t    bgColorPtr = strstr(svgDataCopy, \"4a6984\");\n\t    fgColorPtr = strstr(svgDataCopy, \"ffffff\");\n\n\t    assert(bgColorPtr);\n\t    assert(fgColorPtr);\n\n\t    memcpy(bgColorPtr, bgColorStr, 6);\n\t    memcpy(fgColorPtr, fgColorStr, 6);\n\t} else {\n\t    bgColorPtr =     strstr(svgDataCopy, \"ffffff\");\n\t    borderColorPtr = strstr(svgDataCopy, \"888888\");\n\n\t    assert(bgColorPtr);\n\t    assert(borderColorPtr);\n\n\t    memcpy(bgColorPtr, bgColorStr, 6);\n\t    memcpy(borderColorPtr, borderColorStr, 6);\n\t}\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Display the image\n     */\n    Tk_RedrawImage(img, 0, 0, width, height, d, b.x, b.y);\n    Tk_FreeImage(img);\n}\n\nstatic const Ttk_ElementSpec IndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(IndicatorElement),\n    IndicatorElementOptions,\n    IndicatorElementSize,\n    IndicatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Arrow element(s).\n *\n *\tDraws a solid triangle inside a box.\n *\tclientData is an enum ArrowDirection pointer.\n */\n\ntypedef struct {\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *colorObj;\n    Tcl_Obj *borderObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n} ArrowElement;\n\nstatic const Ttk_ElementOptionSpec ArrowElementOptions[] = {\n    { \"-arrowsize\", TK_OPTION_PIXELS,\n\toffsetof(ArrowElement,sizeObj), \"14\" },\n    { \"-arrowcolor\", TK_OPTION_COLOR,\n\toffsetof(ArrowElement,colorObj), \"black\"},\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(ArrowElement,borderWidthObj), \"1\" },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(ArrowElement,reliefObj), \"raised\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic const Ttk_Padding ArrowPadding = { 3, 3, 3, 3 };\n\nstatic void ArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding;\n    int size = 14;\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n    if (*widthPtr < *heightPtr) {\n\t*widthPtr = *heightPtr;\n    } else {\n\t*heightPtr = *widthPtr;\n    }\n}\n\nstatic void ArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);\n    int borderWidth = 1, relief = TK_RELIEF_RAISED;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cx = 0, cy = 0;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);\n    GC gc = Tk_GCForColor(arrowColor, d);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);\n\n    Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    borderWidth, relief);\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    b = Ttk_PadBox(b, padding);\n\n    switch (direction) {\n\tcase ARROW_UP:\n\tcase ARROW_DOWN:\n\t    TtkArrowSize(b.width/2, direction, &cx, &cy);\n\t    if ((b.height - cy) % 2 == 1) {\n\t\t++cy;\n\t    }\n\t    break;\n\tcase ARROW_LEFT:\n\tcase ARROW_RIGHT:\n\t    TtkArrowSize(b.height/2, direction, &cx, &cy);\n\t    if ((b.width - cx) % 2 == 1) {\n\t\t++cx;\n\t    }\n\t    break;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);\n}\n\nstatic const Ttk_ElementSpec ArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ArrowElement),\n    ArrowElementOptions,\n    ArrowElementSize,\n    ArrowElementDraw\n};\n\n/*\n * Modified arrow element for comboboxes and spinboxes:\n *\tThe width and height are different, and the left edge is drawn in the\n *\tsame color as the right one.\n */\n\nstatic void BoxArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    double scalingLevel = TkScalingLevel(tkwin);\n    Ttk_Padding padding;\n    int size = 14;\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);\n    size -= Ttk_PaddingWidth(padding);\n    size += 2 * round(scalingLevel);\n    TtkArrowSize(size/2, direction, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(padding);\n    *heightPtr += Ttk_PaddingHeight(padding);\n}\n\nstatic void BoxArrowElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ArrowElement *arrow = (ArrowElement *)elementRecord;\n    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);\n    int borderWidth = 1, relief = TK_RELIEF_RAISED;\n    Display *disp = Tk_Display(tkwin);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n    int w = WIN32_XDRAWLINE_HACK;\n    Ttk_Padding padding;\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cx = 0, cy = 0;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);\n    GC arrowGC = Tk_GCForColor(arrowColor, d);\n\n    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    borderWidth, relief);\n\n    XDrawLine(disp, d, darkGC, b.x, b.y+1, b.x, b.y+b.height-1+w);\n\n    padding.left = round(ArrowPadding.left * scalingLevel);\n    padding.top = round(ArrowPadding.top * scalingLevel);\n    padding.right = round(ArrowPadding.right * scalingLevel);\n    padding.bottom = round(ArrowPadding.bottom * scalingLevel);\n\n    b = Ttk_PadBox(b, padding);\n\n    TtkArrowSize(b.width/2, direction, &cx, &cy);\n    if ((b.height - cy) % 2 == 1) {\n\t++cy;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    TtkFillArrow(disp, d, arrowGC, b, direction);\n}\n\nstatic const Ttk_ElementSpec BoxArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ArrowElement),\n    ArrowElementOptions,\n    BoxArrowElementSize,\n    BoxArrowElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Menubutton indicators.\n *\n * These aren't functional like radio/check indicators,\n * they're just affordability indicators.\n */\n\n#define MENUBUTTON_ARROW_SIZE 5\n\ntypedef struct {\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *colorObj;\n    Tcl_Obj *paddingObj;\n} MenuIndicatorElement;\n\nstatic const Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {\n    { \"-arrowsize\", TK_OPTION_PIXELS,\n\toffsetof(MenuIndicatorElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},\n    { \"-arrowcolor\", TK_OPTION_COLOR,\n\toffsetof(MenuIndicatorElement,colorObj), \"black\" },\n    { \"-arrowpadding\", TK_OPTION_STRING,\n\toffsetof(MenuIndicatorElement,paddingObj), \"3\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void MenuIndicatorElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;\n    Ttk_Padding margins;\n    int size = MENUBUTTON_ARROW_SIZE;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);\n    TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);\n    *widthPtr += Ttk_PaddingWidth(margins);\n    *heightPtr += Ttk_PaddingHeight(margins);\n}\n\nstatic void MenuIndicatorElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;\n    XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);\n    GC gc = Tk_GCForColor(arrowColor, d);\n    int size = MENUBUTTON_ARROW_SIZE;\n    int width, height;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);\n\n    TtkArrowSize(size, ARROW_DOWN, &width, &height);\n    b = Ttk_StickBox(b, width, height, 0);\n    TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);\n}\n\nstatic const Ttk_ElementSpec MenuIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(MenuIndicatorElement),\n    MenuIndicatorElementOptions,\n    MenuIndicatorElementSize,\n    MenuIndicatorElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Trough element.\n *\n * Used in scrollbars and scales in place of \"border\".\n *\n * The -groovewidth option can be used to set the size of the short axis\n * for the drawn area. This will not affect the geometry, but can be used\n * to draw a thin centered trough inside the packet alloted. Use -1 or a\n * large number to use the full area (default).\n */\n\ntypedef struct {\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *colorObj;\n    Tcl_Obj *grooveWidthObj;\n    Tcl_Obj *orientObj;\n} TroughElement;\n\nstatic const Ttk_ElementOptionSpec TroughElementOptions[] = {\n    { \"-troughborderwidth\", TK_OPTION_PIXELS,\n\toffsetof(TroughElement,borderWidthObj), \"1\" },\n    { \"-troughrelief\",TK_OPTION_RELIEF,\n\toffsetof(TroughElement,reliefObj), \"sunken\" },\n    { \"-troughcolor\", TK_OPTION_BORDER,\n\toffsetof(TroughElement,colorObj), DEFAULT_BACKGROUND },\n    { \"-groovewidth\", TK_OPTION_PIXELS,\n\toffsetof(TroughElement,grooveWidthObj), \"-1\" },\n    { \"-orient\", TK_OPTION_ANY,\n\toffsetof(TroughElement, orientObj), \"horizontal\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TroughElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    TroughElement *troughPtr = (TroughElement *)elementRecord;\n    int borderWidth = 1, grooveWidth = -1;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth);\n\n    if (grooveWidth <= 0) {\n\t*paddingPtr = Ttk_UniformPadding((short)borderWidth);\n    }\n}\n\nstatic void TroughElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    TroughElement *troughPtr = (TroughElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);\n    int borderWidth = 1, grooveWidth = -1, relief = TK_RELIEF_SUNKEN;\n    Ttk_Orient orient;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth);\n    Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);\n    Ttk_GetOrientFromObj(NULL, troughPtr->orientObj, &orient);\n\n    if (grooveWidth > 0 && grooveWidth < b.height && grooveWidth < b.width) {\n\tif (orient == TTK_ORIENT_HORIZONTAL) {\n\t    b.y += (b.height - grooveWidth) / 2;\n\t    b.height = grooveWidth;\n\t} else {\n\t    b.x += (b.width - grooveWidth) / 2;\n\t    b.width = grooveWidth;\n\t}\n\n\t/*\n\t * Save the data of the trough's inner box for later\n\t */\n\tif (mainInfoPtr != NULL) {\n\t    mainInfoPtr->troughInnerX = b.x + borderWidth;\n\t    mainInfoPtr->troughInnerY = b.y + borderWidth;\n\t    mainInfoPtr->troughInnerWidth =  b.width -  2*borderWidth;\n\t    mainInfoPtr->troughInnerHeight = b.height - 2*borderWidth;\n\t}\n    }\n\n    Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec TroughElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TroughElement),\n    TroughElementOptions,\n    TroughElementSize,\n    TroughElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Thumb element.\n *\n * Used in scrollbars.\n */\n\ntypedef struct {\n    Tcl_Obj *orientObj;\n    Tcl_Obj *thicknessObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *borderObj;\n    Tcl_Obj *borderWidthObj;\n} ThumbElement;\n\nstatic const Ttk_ElementOptionSpec ThumbElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY,\n\toffsetof(ThumbElement, orientObj), \"horizontal\" },\n    { \"-width\", TK_OPTION_PIXELS,\n\toffsetof(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE },\n    { \"-relief\", TK_OPTION_RELIEF,\n\toffsetof(ThumbElement,reliefObj), \"raised\" },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(ThumbElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void ThumbElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ThumbElement *thumb = (ThumbElement *)elementRecord;\n    Ttk_Orient orient;\n    int thickness;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, thumb->thicknessObj, &thickness);\n    Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);\n\n    if (orient == TTK_ORIENT_VERTICAL) {\n\t*widthPtr = thickness;\n\t*heightPtr = MIN_THUMB_SIZE;\n    } else {\n\t*widthPtr = MIN_THUMB_SIZE;\n\t*heightPtr = thickness;\n    }\n}\n\nstatic void ThumbElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ThumbElement *thumb = (ThumbElement *)elementRecord;\n    Tk_3DBorder  border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);\n    int borderWidth = 2, relief = TK_RELIEF_RAISED;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, thumb->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);\n    Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,\n\t    borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec ThumbElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ThumbElement),\n    ThumbElementOptions,\n    ThumbElementSize,\n    ThumbElementDraw\n};\n\n/*\n *----------------------------------------------------------------------\n * +++ Slider element.\n *\n * This is the moving part of the scale widget.  Drawn as a filled circle.\n */\n\n#define SLIDER_DIM 16\n\nstatic const char sliderData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <circle cx='8' cy='8' r='7.5' fill='#ffffff' stroke='#c3c3c3'/>\\n\\\n     <circle cx='8' cy='8' r='4' fill='#4a6984'/>\\n\\\n    </svg>\";\n\ntypedef struct {\n    Tcl_Obj *innerColorObj;\n    Tcl_Obj *outerColorObj;\n    Tcl_Obj *borderColorObj;\n    Tcl_Obj *orientObj;\t\t/* Orientation of overall slider */\n} SliderElement;\n\nstatic const Ttk_ElementOptionSpec SliderElementOptions[] = {\n    { \"-innercolor\", TK_OPTION_COLOR, offsetof(SliderElement,innerColorObj),\n\t\"#4a6984\" },\n    { \"-outercolor\", TK_OPTION_COLOR, offsetof(SliderElement,outerColorObj),\n\t\"#ffffff\" },\n    { \"-bordercolor\", TK_OPTION_COLOR, offsetof(SliderElement,borderColorObj),\n\t\"#c3c3c3\" },\n    { \"-orient\", TK_OPTION_ANY, offsetof(SliderElement,orientObj),\n\t\"horizontal\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SliderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    double scalingLevel = TkScalingLevel(tkwin);\n    *widthPtr = *heightPtr = SLIDER_DIM * scalingLevel;\n}\n\nstatic void SliderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    double scalingLevel = TkScalingLevel(tkwin);\n    int dim = SLIDER_DIM * scalingLevel;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Ttk_Orient orient;\n    Display *disp = Tk_Display(tkwin);\n    XColor *innerColor = Tk_GetColorFromObj(tkwin, slider->innerColorObj);\n    XColor *outerColor = Tk_GetColorFromObj(tkwin, slider->outerColorObj);\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj);\n    GC gc = Tk_GCForColor(innerColor, d);\n\n    char innerColorStr[7], outerColorStr[7], borderColorStr[7];\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[50];\n    Tk_Image img;\n\n    const char *svgDataPtr = sliderData;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *innerColorPtr, *outerColorPtr, *borderColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n#if 0\n    /*\n     * Sanity check -- not needed and no longer used\n     */\n    if (   b.x < 0\n\t|| b.y < 0\n\t|| Tk_Width(tkwin) < b.x + dim\n\t|| Tk_Height(tkwin) < b.y + dim)\n    {\n\t/* Oops!  Not enough room to display the image.\n\t * Don't draw anything.\n\t */\n\treturn;\n    }\n#endif\n\n    /*\n     * Fill the thin trough area preceding the\n     * slider's center with the inner color\n     */\n    if (mainInfoPtr != NULL) {\n\tTtk_GetOrientFromObj(NULL, slider->orientObj, &orient);\n\tswitch (orient) {\n\t    case TTK_ORIENT_HORIZONTAL:\n\t\tXFillRectangle(disp, d, gc,\n\t\t\tmainInfoPtr->troughInnerX, mainInfoPtr->troughInnerY,\n\t\t\tb.x + dim/2 - mainInfoPtr->troughInnerX,\n\t\t\tmainInfoPtr->troughInnerHeight);\n\t\tbreak;\n\t    case TTK_ORIENT_VERTICAL:\n\t\tXFillRectangle(disp, d, gc,\n\t\t\tmainInfoPtr->troughInnerX, mainInfoPtr->troughInnerY,\n\t\t\tmainInfoPtr->troughInnerWidth,\n\t\t\tb.y + dim/2 - mainInfoPtr->troughInnerY);\n\t\tbreak;\n\t}\n    }\n\n    /*\n     * Construct the color strings innerColorStr,\n     * outerColorStr, and borderColorStr\n     */\n    ColorToStr(innerColor, innerColorStr);\n    ColorToStr(outerColor, outerColorStr);\n    ColorToStr(borderColor, borderColorStr);\n\n    /*\n     * Check whether there is an SVG image of this size for these color strings\n     */\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::slider_default%d_%s_%s_%s\",\n\t     dim, innerColorStr, outerColorStr, borderColorStr);\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\tinnerColorPtr = strstr(svgDataCopy, \"4a6984\");\n\touterColorPtr = strstr(svgDataCopy, \"ffffff\");\n\tborderColorPtr = strstr(svgDataCopy, \"c3c3c3\");\n\tassert(innerColorPtr);\n\tassert(outerColorPtr);\n\tassert(borderColorPtr);\n\tmemcpy(innerColorPtr, innerColorStr, 6);\n\tmemcpy(outerColorPtr, outerColorStr, 6);\n\tmemcpy(borderColorPtr, borderColorStr, 6);\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Display the image\n     */\n    Tk_RedrawImage(img, 0, 0, dim, dim, d, b.x, b.y);\n    Tk_FreeImage(img);\n}\n\nstatic const Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SliderElement),\n    SliderElementOptions,\n    SliderElementSize,\n    SliderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Progress bar element:\n *\tDraws the moving part of the progress bar.\n *\n *\t-thickness specifies the size along the short axis of the bar.\n *\t-length specifies the default size along the long axis;\n *\tthe bar will be this long in indeterminate mode.\n */\n\n#define DEFAULT_PBAR_THICKNESS \"15\"\n#define DEFAULT_PBAR_LENGTH \"30\"\n\ntypedef struct {\n    Tcl_Obj *orientObj;\t/* widget orientation */\n    Tcl_Obj *thicknessObj;\t/* the height/width of the bar */\n    Tcl_Obj *lengthObj;\t\t/* default width/height of the bar */\n    Tcl_Obj *reliefObj;\t/* border relief for this object */\n    Tcl_Obj *borderObj;\t/* background color */\n    Tcl_Obj *borderWidthObj;\t/* thickness of the border */\n} PbarElement;\n\nstatic const Ttk_ElementOptionSpec PbarElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY, offsetof(PbarElement,orientObj),\n\t\"horizontal\" },\n    { \"-thickness\", TK_OPTION_PIXELS, offsetof(PbarElement,thicknessObj),\n\tDEFAULT_PBAR_THICKNESS },\n    { \"-barsize\", TK_OPTION_PIXELS, offsetof(PbarElement,lengthObj),\n\tDEFAULT_PBAR_LENGTH },\n    { \"-pbarrelief\", TK_OPTION_RELIEF, offsetof(PbarElement,reliefObj),\n\t\"raised\" },\n    { \"-borderwidth\", TK_OPTION_PIXELS, offsetof(PbarElement,borderWidthObj),\n\tDEFAULT_BORDERWIDTH },\n    { \"-background\", TK_OPTION_BORDER, offsetof(PbarElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void PbarElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    PbarElement *pbar = (PbarElement *)elementRecord;\n    Ttk_Orient orient;\n    int thickness = 15, length = 30, borderWidth = 2;\n\n    Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orient);\n    Tk_GetPixelsFromObj(NULL, tkwin, pbar->thicknessObj, &thickness);\n    Tk_GetPixelsFromObj(NULL, tkwin, pbar->lengthObj, &length);\n    Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);\n\n    switch (orient) {\n\tcase TTK_ORIENT_HORIZONTAL:\n\t    *widthPtr\t= length + 2 * borderWidth;\n\t    *heightPtr\t= thickness + 2 * borderWidth;\n\t    break;\n\tcase TTK_ORIENT_VERTICAL:\n\t    *widthPtr\t= thickness + 2 * borderWidth;\n\t    *heightPtr\t= length + 2 * borderWidth;\n\t    break;\n    }\n}\n\nstatic void PbarElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    PbarElement *pbar = (PbarElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, pbar->borderObj);\n    int relief = TK_RELIEF_RAISED, borderWidth = 2;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, pbar->reliefObj, &relief);\n\n    Tk_Fill3DRectangle(tkwin, d, border,\n\tb.x, b.y, b.width, b.height,\n\tborderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec PbarElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(PbarElement),\n    PbarElementOptions,\n    PbarElementSize,\n    PbarElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Notebook tabs and client area.\n */\n\ntypedef struct {\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *highlightObj;\n    Tcl_Obj *highlightColorObj;\n} TabElement;\n\nstatic const Ttk_ElementOptionSpec TabElementOptions[] = {\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(TabElement,borderWidthObj), \"1\" },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(TabElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-highlight\", TK_OPTION_BOOLEAN,\n\toffsetof(TabElement,highlightObj), \"0\" },\n    { \"-highlightcolor\", TK_OPTION_COLOR,\n\toffsetof(TabElement,highlightColorObj), \"#4a6984\" },\n    {NULL, TK_OPTION_BOOLEAN, 0, 0}\n};\n\nstatic void TabElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    TabElement *tab = (TabElement *)elementRecord;\n    int borderWidth = 1;\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth);\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    paddingPtr->bottom = 0;\n\t    break;\n\tcase TTK_STICK_N:\n\t    paddingPtr->top = 0;\n\t    break;\n\tcase TTK_STICK_E:\n\t    paddingPtr->right = 0;\n\t    break;\n\tcase TTK_STICK_W:\n\t    paddingPtr->left = 0;\n\t    break;\n    }\n}\n\nstatic void TabElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    TabElement *tab = (TabElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);\n    int highlight = 0;\n    XColor *hlColor = NULL;\n    XPoint pts[6];\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cut = round(2 * scalingLevel);\n    Display *disp = Tk_Display(tkwin);\n    int borderWidth = 1;\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    if (state & TTK_STATE_SELECTED) {\n\t/*\n\t * Draw slightly outside of the allocated parcel,\n\t * to overwrite the client area border.\n\t */\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t\tb.height += 1;\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t\tb.height += 1; b.y -= 1;\n\t\tbreak;\n\t    case TTK_STICK_E:\n\t\tb.width += 1;\n\t\tbreak;\n\t    case TTK_STICK_W:\n\t\tb.width += 1; b.x -= 1;\n\t\tbreak;\n\t}\n\n\tTcl_GetBooleanFromObj(NULL, tab->highlightObj, &highlight);\n\tif (highlight) {\n\t    hlColor = Tk_GetColorFromObj(tkwin, tab->highlightColorObj);\n\t}\n    }\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    pts[0].x = b.x;  pts[0].y = b.y + b.height-1;\n\t    pts[1].x = b.x;  pts[1].y = b.y + cut;\n\t    pts[2].x = b.x + cut;  pts[2].y = b.y;\n\t    pts[3].x = b.x + b.width-1 - cut;  pts[3].y = b.y;\n\t    pts[4].x = b.x + b.width-1;  pts[4].y = b.y + cut;\n\t    pts[5].x = b.x + b.width-1;  pts[5].y = b.y + b.height;\n\t    break;\n\tcase TTK_STICK_N:\n\t    pts[0].x = b.x;  pts[0].y = b.y;\n\t    pts[1].x = b.x;  pts[1].y = b.y + b.height-1 - cut;\n\t    pts[2].x = b.x + cut;  pts[2].y = b.y + b.height-1;\n\t    pts[3].x = b.x + b.width-1 - cut;  pts[3].y = b.y + b.height-1;\n\t    pts[4].x = b.x + b.width-1;  pts[4].y = b.y + b.height-1 - cut;\n\t    pts[5].x = b.x + b.width-1;  pts[5].y = b.y-1;\n\t    break;\n\tcase TTK_STICK_E:\n\t    pts[0].x = b.x + b.width-1;  pts[0].y = b.y;\n\t    pts[1].x = b.x + cut;  pts[1].y = b.y;\n\t    pts[2].x = b.x;  pts[2].y = b.y + cut;\n\t    pts[3].x = b.x;  pts[3].y = b.y + b.height-1 - cut;\n\t    pts[4].x = b.x + cut;  pts[4].y = b.y + b.height-1;\n\t    pts[5].x = b.x + b.width;  pts[5].y = b.y + b.height-1;\n\t    break;\n\tcase TTK_STICK_W:\n\t    pts[0].x = b.x;  pts[0].y = b.y;\n\t    pts[1].x = b.x + b.width-1 - cut;  pts[1].y = b.y;\n\t    pts[2].x = b.x + b.width-1;  pts[2].y = b.y + cut;\n\t    pts[3].x = b.x + b.width-1;  pts[3].y = b.y + b.height-1 - cut;\n\t    pts[4].x = b.x + b.width-1 - cut;  pts[4].y = b.y + b.height-1;\n\t    pts[5].x = b.x-1;  pts[5].y = b.y + b.height-1;\n\t    break;\n    }\n\n    XFillPolygon(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC),\n\t    pts, 6, Convex, CoordModeOrigin);\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    pts[5].y -= 1 - WIN32_XDRAWLINE_HACK;\n\t    break;\n\tcase TTK_STICK_N:\n\t    pts[5].y += 1 - WIN32_XDRAWLINE_HACK;\n\t    break;\n\tcase TTK_STICK_E:\n\t    pts[5].x -= 1 - WIN32_XDRAWLINE_HACK;\n\t    break;\n\tcase TTK_STICK_W:\n\t    pts[5].x += 1 - WIN32_XDRAWLINE_HACK;\n\t    break;\n    }\n\n    Tk_GetPixelsFromObj(NULL, tkwin, tab->borderWidthObj, &borderWidth);\n    while (borderWidth--) {\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t    case TTK_STICK_E:\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t\tpts, 4, CoordModeOrigin);\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t\tpts+3, 3, CoordModeOrigin);\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t    case TTK_STICK_W:\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t\tpts, 2, CoordModeOrigin);\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t\tpts+1, 5, CoordModeOrigin);\n\t\tbreak;\n\t}\n\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t\t++pts[0].x;  ++pts[1].x;  ++pts[2].y;\n\t\t++pts[3].y;  --pts[4].x;  --pts[5].x;\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t\t++pts[0].x;  ++pts[1].x;  --pts[2].y;\n\t\t--pts[3].y;  --pts[4].x;  --pts[5].x;\n\t\tbreak;\n\t    case TTK_STICK_E:\n\t\t++pts[0].y;  ++pts[1].y;  ++pts[2].x;\n\t\t++pts[3].x;  --pts[4].y;  --pts[5].y;\n\t\tbreak;\n\t    case TTK_STICK_W:\n\t\t++pts[0].y;  ++pts[1].y;  --pts[2].x;\n\t\t--pts[3].x;  --pts[4].y;  --pts[5].y;\n\t\tbreak;\n\t}\n    }\n\n    if (highlight) {\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t\tif (b.width >= 2*cut) {\n\t\t    XFillRectangle(disp, d, Tk_GCForColor(hlColor, d),\n\t\t\t    b.x + cut, b.y, b.width - 2*cut, cut);\n\t\t}\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t\tif (b.width >= 2*cut) {\n\t\t    XFillRectangle(disp, d, Tk_GCForColor(hlColor, d),\n\t\t\t    b.x + cut, b.y + b.height - cut,\n\t\t\t    b.width - 2*cut, cut);\n\t\t}\n\t\tbreak;\n\t    case TTK_STICK_E:\n\t\tif (b.height >= 2*cut) {\n\t\t    XFillRectangle(disp, d, Tk_GCForColor(hlColor, d),\n\t\t\t    b.x, b.y + cut, cut, b.height - 2*cut);\n\t\t}\n\t\tbreak;\n\t    case TTK_STICK_W:\n\t\tif (b.height >= 2*cut) {\n\t\t    XFillRectangle(disp, d, Tk_GCForColor(hlColor, d),\n\t\t\t    b.x + b.width - cut, b.y + cut,\n\t\t\t    cut, b.height - 2*cut);\n\t\t}\n\t\tbreak;\n\t}\n    }\n}\n\nstatic const Ttk_ElementSpec TabElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TabElement),\n    TabElementOptions,\n    TabElementSize,\n    TabElementDraw\n};\n\n/*\n * Client area element:\n * Uses same resources as tab element.\n */\ntypedef TabElement ClientElement;\n#define ClientElementOptions TabElementOptions\n\nstatic void ClientElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    ClientElement *ce = (ClientElement *)elementRecord;\n    int borderWidth = 1;\n\n    Tk_GetPixelsFromObj(0, tkwin, ce->borderWidthObj, &borderWidth);\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n}\n\nstatic void ClientElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    ClientElement *ce = (ClientElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);\n    int borderWidth = 1;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, ce->borderWidthObj, &borderWidth);\n\n    Tk_Fill3DRectangle(tkwin, d, border,\n\tb.x, b.y, b.width, b.height, borderWidth, TK_RELIEF_RAISED);\n}\n\nstatic const Ttk_ElementSpec ClientElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ClientElement),\n    ClientElementOptions,\n    ClientElementSize,\n    ClientElementDraw\n};\n\n/*----------------------------------------------------------------------\n * TtkElements_Init --\n *\tRegister default element implementations.\n */\n\nMODULE_SCOPE void\nTtkElements_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme =  Ttk_GetDefaultTheme(interp);\n\n    /*\n     * Elements:\n     */\n    Ttk_RegisterElement(interp, theme, \"background\",\n\t    &BackgroundElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"fill\", &FillElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"border\", &BorderElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"field\", &FieldElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"focus\", &FocusElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"padding\", &PaddingElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"Checkbutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&checkbutton_spec);\n    Ttk_RegisterElement(interp, theme, \"Radiobutton.indicator\",\n\t    &IndicatorElementSpec, (void *)&radiobutton_spec);\n    Ttk_RegisterElement(interp, theme, \"Menubutton.indicator\",\n\t    &MenuIndicatorElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"indicator\", &ttkNullElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"uparrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.uparrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_UP));\n    Ttk_RegisterElement(interp, theme, \"downarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"Spinbox.downarrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"Combobox.downarrow\",\n\t    &BoxArrowElementSpec, INT2PTR(ARROW_DOWN));\n    Ttk_RegisterElement(interp, theme, \"leftarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_LEFT));\n    Ttk_RegisterElement(interp, theme, \"rightarrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));\n    Ttk_RegisterElement(interp, theme, \"arrow\",\n\t    &ArrowElementSpec, INT2PTR(ARROW_UP));\n\n    Ttk_RegisterElement(interp, theme, \"trough\", &TroughElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"thumb\", &ThumbElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"slider\", &SliderElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"pbar\", &PbarElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"separator\",\n\t    &SeparatorElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"hseparator\",\n\t    &HorizontalSeparatorElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"vseparator\",\n\t    &VerticalSeparatorElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"sizegrip\", &SizegripElementSpec, NULL);\n\n    Ttk_RegisterElement(interp, theme, \"tab\", &TabElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"client\", &ClientElementSpec, NULL);\n\n    /*\n     * Register \"default\" as a user-loadable theme (for now):\n     */\n    Tcl_PkgProvideEx(interp, \"ttk::theme::default\", TTK_VERSION, NULL);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkEntry.c",
    "content": "/*\n * DERIVED FROM: tk/generic/tkEntry.c r1.35.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2000 Ajuba Solutions.\n * Copyright © 2002 ActiveState Corporation.\n * Copyright © 2004 Joe English\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Extra bits for core.flags:\n */\n#define GOT_SELECTION\t\t(WIDGET_USER_FLAG<<1)\n#define SYNCING_VARIABLE\t(WIDGET_USER_FLAG<<2)\n#define VALIDATING\t\t(WIDGET_USER_FLAG<<3)\n#define VALIDATION_SET_VALUE\t(WIDGET_USER_FLAG<<4)\n\n/*\n * Definitions for -validate option values:\n */\ntypedef enum validateMode {\n    VMODE_ALL, VMODE_KEY, VMODE_FOCUS, VMODE_FOCUSIN, VMODE_FOCUSOUT, VMODE_NONE\n} VMODE;\n\nstatic const char *const validateStrings[] = {\n    \"all\", \"key\", \"focus\", \"focusin\", \"focusout\", \"none\", NULL\n};\n\n/*\n * Validation reasons:\n */\ntypedef enum validateReason {\n    VALIDATE_INSERT, VALIDATE_DELETE,\n    VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT,\n    VALIDATE_FORCED\n} VREASON;\n\nstatic const char *const validateReasonStrings[] = {\n    \"key\", \"key\", \"focusin\", \"focusout\", \"forced\", NULL\n};\n\n/*------------------------------------------------------------------------\n * +++ Entry widget record.\n *\n * Dependencies:\n *\n * textVariableTrace\t: textVariableObj\n *\n * numBytes,numChars\t: string\n * displayString\t: numChars, showChar\n * layoutHeight,\n * layoutWidth,\n * textLayout\t\t: fontObj, displayString\n * layoutX, layoutY\t: textLayout, justify, xscroll.first\n *\n * Invariants:\n *\n * 0 <= insertPos <= numChars\n * 0 <= selectFirst < selectLast <= numChars || selectFirst == selectLast == -1\n * displayString points to string if showChar == NULL,\n * or to malloc'ed storage if showChar != NULL.\n */\n\n/* Style parameters:\n */\ntypedef struct {\n    Tcl_Obj *placeholderForegroundObj;/* Foreground color for placeholder text */\n    Tcl_Obj *foregroundObj;\t/* Foreground color for normal text */\n    Tcl_Obj *backgroundObj;\t/* Entry widget background color */\n    Tcl_Obj *selBorderObj;\t/* Border and background for selection */\n    Tcl_Obj *selBorderWidthObj;\t/* Width of selection border */\n    Tcl_Obj *selForegroundObj;\t/* Foreground color for selected text */\n    Tcl_Obj *insertColorObj;\t/* Color of insertion cursor */\n    Tcl_Obj *insertWidthObj;\t/* Insert cursor width */\n} EntryStyleData;\n\ntypedef struct {\n    /*\n     * Internal state:\n     */\n    char *string;\t\t/* Storage for string (malloced) */\n    Tcl_Size numBytes;\t\t/* Length of string in bytes. */\n    Tcl_Size numChars;\t\t/* Length of string in characters. */\n\n    Tcl_Size insertPos;\t\t/* Insert index */\n    Tcl_Size selectFirst;\t\t/* Index of start of selection, or TCL_INDEX_NONE */\n    Tcl_Size selectLast;\t\t/* Index of end of selection, or TCL_INDEX_NONE */\n\n    Scrollable xscroll;\t\t/* Current scroll position */\n    ScrollHandle xscrollHandle;\n\n    /*\n     * Options managed by Tk_SetOptions:\n     */\n    Tcl_Obj *textVariableObj;\t/* Name of linked variable */\n    bool exportSelection;\t/* True means tie internal selection to X selection? */\n\n    VMODE validate;\t\t/* Validation mode */\n    Tcl_Obj *validateCmdObj;\t/* Validation script template */\n    Tcl_Obj *invalidCmdObj;\t\t/* Invalid callback script template */\n\n    Tcl_Obj *showCharObj;\t\t/* Used to derive displayString */\n\n    Tcl_Obj *fontObj;\t\t/* Text font to use */\n    Tcl_Obj *widthObj;\t\t/* Desired width of window (in avgchars) */\n    Tk_Justify justify;\t\t/* Text justification */\n\n    EntryStyleData styleData;\t/* Display style data (widget options) */\n    EntryStyleData styleDefaults;/* Style defaults (fallback values) */\n\n    Tcl_Obj *stateObj;\t\t/* Compatibility option -- see CheckStateObj */\n\n    Tcl_Obj *placeholderObj;\t/* Text to display for placeholder text */\n\n    /*\n     * Derived resources:\n     */\n    Ttk_TraceHandle *textVariableTrace;\n\n    char *displayString;\t/* String to use when displaying */\n    Tk_TextLayout textLayout;\t/* Cached text layout information. */\n    int layoutWidth;\t\t/* textLayout width */\n    int layoutHeight;\t\t/* textLayout height */\n\n    int layoutX, layoutY;\t/* Origin for text layout. */\n\n} EntryPart;\n\ntypedef struct {\n    WidgetCore\tcore;\n    EntryPart\tentry;\n} Entry;\n\n/*\n * Extra mask bits for Tk_SetOptions()\n */\n#define STATE_CHANGED\t\t(0x100)\t/* -state option changed */\n#define TEXTVAR_CHANGED\t\t(0x200)\t/* -textvariable option changed */\n#define SCROLLCMD_CHANGED\t(0x400)\t/* -xscrollcommand option changed */\n\n/*\n * Default option values:\n */\n#define DEF_SELECT_BG\t\t\"#000000\"\n#define DEF_SELECT_FG\t\t\"#ffffff\"\n#define DEF_PLACEHOLDER_FG\t\"#b3b3b3\"\n#define DEF_INSERT_BG\t\t\"black\"\n#define DEF_ENTRY_WIDTH\t\t\"20\"\n#define DEF_ENTRY_FONT\t\t\"TkTextFont\"\n#define DEF_LIST_HEIGHT\t\t\"10\"\n\nstatic const Tk_OptionSpec EntryOptionSpecs[] = {\n    {TK_OPTION_BOOLEAN, \"-exportselection\", \"exportSelection\",\n\t\"ExportSelection\", \"1\", TCL_INDEX_NONE, offsetof(Entry, entry.exportSelection),\n\tTK_OPTION_VAR(bool), 0, 0},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEF_ENTRY_FONT, offsetof(Entry, entry.fontObj),TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-invalidcommand\", \"invalidCommand\", \"InvalidCommand\",\n\tNULL, offsetof(Entry, entry.invalidCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\t\"left\", TCL_INDEX_NONE, offsetof(Entry, entry.justify),\n\tTK_OPTION_ENUM_VAR, 0, GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-placeholder\", \"placeHolder\", \"PlaceHolder\",\n\tNULL, offsetof(Entry, entry.placeholderObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-show\", \"show\", \"Show\",\n\tNULL, offsetof(Entry, entry.showCharObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_STRING, \"-state\", \"state\", \"State\",\n\t\"normal\", offsetof(Entry, entry.stateObj), TCL_INDEX_NONE,\n\t0,0,STATE_CHANGED},\n    {TK_OPTION_STRING, \"-textvariable\", \"textVariable\", \"Variable\",\n\tNULL, offsetof(Entry, entry.textVariableObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,TEXTVAR_CHANGED},\n    {TK_OPTION_STRING_TABLE, \"-validate\", \"validate\", \"Validate\",\n\t\"none\", TCL_INDEX_NONE, offsetof(Entry, entry.validate),\n\tTK_OPTION_ENUM_VAR, validateStrings, 0},\n    {TK_OPTION_STRING, \"-validatecommand\", \"validateCommand\", \"ValidateCommand\",\n\tNULL, offsetof(Entry, entry.validateCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\tDEF_ENTRY_WIDTH, offsetof(Entry, entry.widthObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tNULL, offsetof(Entry, entry.xscroll.scrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},\n\n    /* EntryStyleData options:\n     */\n    {TK_OPTION_COLOR, \"-background\", \"windowColor\", \"WindowColor\",\n\tNULL, offsetof(Entry, entry.styleData.backgroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_COLOR, \"-foreground\", \"textColor\", \"TextColor\",\n\tNULL, offsetof(Entry, entry.styleData.foregroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_COLOR, \"-placeholderforeground\", \"placeholderForeground\",\n\t\"PlaceholderForeground\", NULL,\n\toffsetof(Entry, entry.styleData.placeholderForegroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ EntryStyleData management.\n *\tThis is still more awkward than it should be;\n *\tit should be able to use the Element API instead.\n */\n\n/* EntryInitStyleDefaults --\n *\tInitialize EntryStyleData record to fallback values.\n */\nstatic void EntryInitStyleDefaults(EntryStyleData *es)\n{\n#define INIT(member, value) \\\n\tes->member = Tcl_NewStringObj(value, -1); \\\n\tTcl_IncrRefCount(es->member);\n    INIT(placeholderForegroundObj, DEF_PLACEHOLDER_FG)\n    INIT(foregroundObj, DEFAULT_FOREGROUND)\n    INIT(selBorderObj, DEF_SELECT_BG)\n    INIT(selForegroundObj, DEF_SELECT_FG)\n    INIT(insertColorObj, DEFAULT_FOREGROUND)\n    INIT(selBorderWidthObj, \"0\")\n    INIT(insertWidthObj, \"1\")\n#undef INIT\n}\n\nstatic void EntryFreeStyleDefaults(EntryStyleData *es)\n{\n    Tcl_DecrRefCount(es->placeholderForegroundObj);\n    Tcl_DecrRefCount(es->foregroundObj);\n    Tcl_DecrRefCount(es->selBorderObj);\n    Tcl_DecrRefCount(es->selForegroundObj);\n    Tcl_DecrRefCount(es->insertColorObj);\n    Tcl_DecrRefCount(es->selBorderWidthObj);\n    Tcl_DecrRefCount(es->insertWidthObj);\n}\n\n/*\n * EntryInitStyleData --\n *\tLook up style-specific data for an entry widget.\n */\nstatic void EntryInitStyleData(Entry *entryPtr, EntryStyleData *es)\n{\n    Ttk_State state = entryPtr->core.state;\n    Ttk_ResourceCache cache = Ttk_GetResourceCache(entryPtr->core.interp);\n    Tk_Window tkwin = entryPtr->core.tkwin;\n    Tcl_Obj *tmp;\n\n    /* Initialize to fallback values:\n     */\n    *es = entryPtr->entry.styleDefaults;\n\n#   define INIT(member, name) \\\n    if ((tmp=Ttk_QueryOption(entryPtr->core.layout,name,state))) \\\n\tes->member=tmp;\n    INIT(placeholderForegroundObj, \"-placeholderforeground\");\n    INIT(foregroundObj, \"-foreground\");\n    INIT(selBorderObj, \"-selectbackground\")\n    INIT(selBorderWidthObj, \"-selectborderwidth\")\n    INIT(selForegroundObj, \"-selectforeground\")\n    INIT(insertColorObj, \"-insertcolor\")\n    INIT(insertWidthObj, \"-insertwidth\")\n#undef INIT\n\n    /* Reacquire color & border resources from resource cache.\n     */\n    es->placeholderForegroundObj = Ttk_UseColor(cache, tkwin, es->placeholderForegroundObj);\n    es->foregroundObj = Ttk_UseColor(cache, tkwin, es->foregroundObj);\n    es->selForegroundObj = Ttk_UseColor(cache, tkwin, es->selForegroundObj);\n    es->insertColorObj = Ttk_UseColor(cache, tkwin, es->insertColorObj);\n    es->selBorderObj = Ttk_UseBorder(cache, tkwin, es->selBorderObj);\n}\n\n/*------------------------------------------------------------------------\n * +++ Resource management.\n */\n\n/* EntryDisplayString --\n *\tReturn a malloc'ed string consisting of 'numChars' copies\n *\tof (the first character in the string) 'showChar'.\n *\tUsed to compute the displayString if -show is non-NULL.\n */\nstatic char *EntryDisplayString(const char *showChar, Tcl_Size numChars)\n{\n    char *displayString, *p;\n    Tcl_Size size;\n    int ch;\n    char buf[6];\n\n    Tcl_UtfToUniChar(showChar, &ch);\n    size = Tcl_UniCharToUtf(ch, buf);\n    p = displayString = (char *)Tcl_Alloc(numChars * size + 1);\n\n    while (numChars--) {\n\tmemcpy(p, buf, size);\n\tp += size;\n    }\n    *p = '\\0';\n\n    return displayString;\n}\n\n/* EntryUpdateTextLayout --\n *\tRecompute textLayout, layoutWidth, and layoutHeight\n *\tfrom displayString and fontObj.\n */\nstatic void EntryUpdateTextLayout(Entry *entryPtr)\n{\n    Tk_FreeTextLayout(entryPtr->entry.textLayout);\n    if ((entryPtr->entry.numChars != 0) || (entryPtr->entry.placeholderObj == NULL)) {\n\tentryPtr->entry.textLayout = Tk_ComputeTextLayout(\n\t    Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj),\n\t    entryPtr->entry.displayString, entryPtr->entry.numChars,\n\t    0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES,\n\t    &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight);\n    } else {\n\tTcl_Size length = Tcl_GetCharLength(entryPtr->entry.placeholderObj);\n\tentryPtr->entry.textLayout = Tk_ComputeTextLayout(\n\t    Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj),\n\t    Tcl_GetString(entryPtr->entry.placeholderObj), length,\n\t    0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES,\n\t    &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight);\n    }\n}\n\n/* EntryEditable --\n *\tReturns 1 if the entry widget accepts user changes, 0 otherwise\n */\nstatic int\nEntryEditable(Entry *entryPtr)\n{\n    return !(entryPtr->core.state & (TTK_STATE_DISABLED|TTK_STATE_READONLY));\n}\n\n/*------------------------------------------------------------------------\n * +++ Selection management.\n */\n\n/* EntryFetchSelection --\n *\tSelection handler for entry widgets.\n */\nstatic Tcl_Size\nEntryFetchSelection(\n    void *clientData, Tcl_Size offset, char *buffer, Tcl_Size maxBytes)\n{\n    Entry *entryPtr = (Entry *)clientData;\n    Tcl_Size byteCount;\n    const char *string;\n    const char *selStart, *selEnd;\n\n    if (entryPtr->entry.selectFirst < 0 || (!entryPtr->entry.exportSelection)\n\t    || Tcl_IsSafe(entryPtr->core.interp)) {\n\treturn TCL_INDEX_NONE;\n    }\n    string = entryPtr->entry.displayString;\n\n    selStart = Tcl_UtfAtIndex(string, entryPtr->entry.selectFirst);\n    selEnd = Tcl_UtfAtIndex(selStart,\n\t    entryPtr->entry.selectLast - entryPtr->entry.selectFirst);\n    if (selEnd  <= selStart + offset) {\n\treturn 0;\n    }\n    byteCount = selEnd - selStart - offset;\n    if (byteCount > maxBytes) {\n    /* @@@POSSIBLE BUG: Can transfer partial UTF-8 sequences.  Is this OK? */\n\tbyteCount = maxBytes;\n    }\n    memcpy(buffer, selStart + offset, byteCount);\n    buffer[byteCount] = '\\0';\n    return byteCount;\n}\n\n/* EntryLostSelection --\n *\tTk_LostSelProc for Entry widgets; called when an entry\n *\tloses ownership of the selection.\n */\nstatic void EntryLostSelection(void *clientData)\n{\n    Entry *entryPtr = (Entry *)clientData;\n    entryPtr->core.flags &= ~GOT_SELECTION;\n    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;\n    TtkRedisplayWidget(&entryPtr->core);\n}\n\n/* EntryOwnSelection --\n *\tAssert ownership of the PRIMARY selection,\n *\tif -exportselection set and selection is present and interp is unsafe.\n */\nstatic void EntryOwnSelection(Entry *entryPtr)\n{\n    if (entryPtr->entry.exportSelection\n\t&& (!Tcl_IsSafe(entryPtr->core.interp))\n\t&& !(entryPtr->core.flags & GOT_SELECTION)) {\n\tTk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection,\n\t\tentryPtr);\n\tentryPtr->core.flags |= GOT_SELECTION;\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Validation.\n */\n\n/* ExpandPercents --\n *\tExpand an entry validation script template (-validatecommand\n *\tor -invalidcommand).\n */\nstatic void\nExpandPercents(\n     Entry *entryPtr,\t\t/* Entry that needs validation. */\n     const char *templ,\t/* Script template */\n     const char *newValue,\t\t/* Potential new value of entry string */\n     Tcl_Size index,\t\t\t/* index of insert/delete */\n     Tcl_Size count,\t\t\t/* #changed characters */\n     VREASON reason,\t\t/* Reason for change */\n     Tcl_DString *dsPtr)\t/* Result of %-substitutions */\n{\n    Tcl_Size spaceNeeded, length, stringLength;\n    const char *string;\n    int ch, number, cvtFlags;\n    char numStorage[2*TCL_INTEGER_SPACE];\n\n    while (*templ) {\n\t/* Find everything up to the next % character and append it\n\t * to the result string.\n\t */\n\tstring = Tcl_UtfFindFirst(templ, '%');\n\tif (string == NULL) {\n\t    /* No more %-sequences to expand.\n\t     * Copy the rest of the template.\n\t     */\n\t    Tcl_DStringAppend(dsPtr, templ, TCL_INDEX_NONE);\n\t    return;\n\t}\n\tif (string != templ) {\n\t    Tcl_DStringAppend(dsPtr, templ, string - templ);\n\t    templ = string;\n\t}\n\n\t/* There's a percent sequence here.  Process it.\n\t */\n\t++templ; /* skip over % */\n\tif (*templ != '\\0') {\n\t    templ += Tcl_UtfToUniChar(templ, &ch);\n\t} else {\n\t    ch = '%';\n\t}\n\n\tstringLength = -1;\n\tswitch (ch) {\n\t    case 'd': /* Type of call that caused validation */\n\t\tif (reason == VALIDATE_INSERT) {\n\t\t    number = 1;\n\t\t} else if (reason == VALIDATE_DELETE) {\n\t\t    number = 0;\n\t\t} else {\n\t\t    number = -1;\n\t\t}\n\t\tsnprintf(numStorage, sizeof(numStorage), \"%d\", number);\n\t\tstring = numStorage;\n\t\tbreak;\n\t    case 'i': /* index of insert/delete */\n\t\tsnprintf(numStorage, sizeof(numStorage), \"%\" TCL_SIZE_MODIFIER \"d\", index);\n\t\tstring = numStorage;\n\t\tbreak;\n\t    case 'P': /* 'Peeked' new value of the string */\n\t\tstring = newValue;\n\t\tbreak;\n\t    case 's': /* Current string value */\n\t\tstring = entryPtr->entry.string;\n\t\tbreak;\n\t    case 'S': /* string to be inserted/deleted, if any */\n\t\tif (reason == VALIDATE_INSERT) {\n\t\t    string = Tcl_UtfAtIndex(newValue, index);\n\t\t    stringLength = Tcl_UtfAtIndex(string, count) - string;\n\t\t} else if (reason == VALIDATE_DELETE) {\n\t\t    string = Tcl_UtfAtIndex(entryPtr->entry.string, index);\n\t\t    stringLength = Tcl_UtfAtIndex(string, count) - string;\n\t\t} else {\n\t\t    string = \"\";\n\t\t    stringLength = 0;\n\t\t}\n\t\tbreak;\n\t    case 'v': /* type of validation currently set */\n\t\tstring = validateStrings[entryPtr->entry.validate];\n\t\tbreak;\n\t    case 'V': /* type of validation in effect */\n\t\tstring = validateReasonStrings[reason];\n\t\tbreak;\n\t    case 'W': /* widget name */\n\t\tstring = Tk_PathName(entryPtr->core.tkwin);\n\t\tbreak;\n\t    default:\n\t\tlength = Tcl_UniCharToUtf(ch, numStorage);\n\t\tnumStorage[length] = '\\0';\n\t\tstring = numStorage;\n\t\tbreak;\n\t}\n\n\tspaceNeeded = Tcl_ScanCountedElement(string, stringLength, &cvtFlags);\n\tlength = Tcl_DStringLength(dsPtr);\n\tTcl_DStringSetLength(dsPtr, length + spaceNeeded);\n\tspaceNeeded = Tcl_ConvertCountedElement(string, stringLength,\n\t\tTcl_DStringValue(dsPtr) + length,\n\t\tcvtFlags | TCL_DONT_USE_BRACES);\n\tTcl_DStringSetLength(dsPtr, length + spaceNeeded);\n    }\n}\n\n/* RunValidationScript --\n *\tBuild and evaluate an entry validation script.\n *\tIf the script raises an error, disable validation\n *\tby setting '-validate none'\n */\nstatic int RunValidationScript(\n    Tcl_Interp *interp,\t/* Interpreter to use */\n    Entry *entryPtr,\t\t/* Entry being validated */\n    const char *templ,\t/* Script template */\n    const char *optionName,\t/* \"-validatecommand\", \"-invalidcommand\" */\n    const char *newValue,\t/* Potential new value of entry string */\n    Tcl_Size index,\t\t\t/* index of insert/delete */\n    Tcl_Size count,\t\t\t/* #changed characters */\n    VREASON reason)\t\t/* Reason for change */\n{\n    Tcl_DString script;\n    int code;\n\n    Tcl_DStringInit(&script);\n    ExpandPercents(entryPtr, templ, newValue, index, count, reason, &script);\n    code = Tcl_EvalEx(interp,\n\t\tTcl_DStringValue(&script), Tcl_DStringLength(&script),\n\t\tTCL_EVAL_GLOBAL);\n    Tcl_DStringFree(&script);\n    if (WidgetDestroyed(&entryPtr->core)) {\n\treturn TCL_ERROR;\n    }\n\n    if (code != TCL_OK && code != TCL_RETURN) {\n\tTcl_AddErrorInfo(interp, \"\\n\\t(in \");\n\tTcl_AddErrorInfo(interp, optionName);\n\tTcl_AddErrorInfo(interp, \" validation command executed by \");\n\tTcl_AddErrorInfo(interp, Tk_PathName(entryPtr->core.tkwin));\n\tTcl_AddErrorInfo(interp, \")\");\n\tentryPtr->entry.validate = VMODE_NONE;\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\n/* EntryNeedsValidation --\n *\tDetermine whether the specified VREASON should trigger validation\n *\tin the current VMODE.\n */\nstatic int EntryNeedsValidation(VMODE vmode, VREASON reason)\n{\n    return (reason == VALIDATE_FORCED)\n\t|| (vmode == VMODE_ALL)\n\t|| (reason == VALIDATE_FOCUSIN\n\t    && (vmode == VMODE_FOCUSIN || vmode == VMODE_FOCUS))\n\t|| (reason == VALIDATE_FOCUSOUT\n\t    && (vmode == VMODE_FOCUSOUT || vmode == VMODE_FOCUS))\n\t|| (reason == VALIDATE_INSERT && vmode == VMODE_KEY)\n\t|| (reason == VALIDATE_DELETE && vmode == VMODE_KEY)\n\t;\n}\n\n/* EntryValidateChange --\n *\tValidate a proposed change to the entry widget's value if required.\n *\tCall the -invalidcommand if validation fails.\n *\n * Returns:\n *\tTCL_OK if the change is accepted\n *\tTCL_BREAK if the change is rejected\n *\tTCL_ERROR if any errors occurred\n *\n * The change will be rejected if -validatecommand returns 0,\n * or if -validatecommand or -invalidcommand modifies the value.\n */\nstatic int\nEntryValidateChange(\n    Entry *entryPtr,\t\t/* Entry that needs validation. */\n    const char *newValue,\t/* Potential new value of entry string */\n    Tcl_Size index,\t\t\t/* index of insert/delete, TCL_INDEX_NONE otherwise */\n    Tcl_Size count,\t\t\t/* #changed characters */\n    VREASON reason)\t\t/* Reason for change */\n{\n    Tcl_Interp *interp = entryPtr->core.interp;\n    VMODE vmode = entryPtr->entry.validate;\n    int code, change_ok;\n\n    if ((entryPtr->entry.validateCmdObj == NULL)\n\t|| (entryPtr->core.flags & VALIDATING)\n\t|| !EntryNeedsValidation(vmode, reason)) {\n\treturn TCL_OK;\n    }\n\n    entryPtr->core.flags |= VALIDATING;\n\n    /* Run -validatecommand and check return value:\n     */\n    code = RunValidationScript(interp, entryPtr,\n\t    Tcl_GetString(entryPtr->entry.validateCmdObj), \"-validatecommand\",\n\t    newValue, index, count, reason);\n    if (code != TCL_OK) {\n\tgoto done;\n    }\n\n    code = Tcl_GetBooleanFromObj(interp,Tcl_GetObjResult(interp), &change_ok);\n    if (code != TCL_OK) {\n\tentryPtr->entry.validate = VMODE_NONE;\t/* Disable validation */\n\tTcl_AddErrorInfo(interp,\n\t\t\"\\n(validation command did not return valid boolean)\");\n\tgoto done;\n    }\n\n    /* Run the -invalidcommand if validation failed:\n     */\n    if (!change_ok && entryPtr->entry.invalidCmdObj != NULL) {\n\tcode = RunValidationScript(interp, entryPtr,\n\t\tTcl_GetString(entryPtr->entry.invalidCmdObj), \"-invalidcommand\",\n\t\tnewValue, index, count, reason);\n\tif (code != TCL_OK) {\n\t    goto done;\n\t}\n    }\n\n    /* Reject the pending change if validation failed\n     * or if a validation script changed the value.\n     */\n    if (!change_ok || (entryPtr->core.flags & VALIDATION_SET_VALUE)) {\n\tcode = TCL_BREAK;\n    }\n\ndone:\n    entryPtr->core.flags &= ~(VALIDATING|VALIDATION_SET_VALUE);\n    return code;\n}\n\n/* EntryRevalidate --\n *\tRevalidate the current value of an entry widget,\n *\tupdate the TTK_STATE_INVALID bit.\n *\n * Returns:\n *\tTCL_OK if valid, TCL_BREAK if invalid, TCL_ERROR on error.\n */\nstatic int EntryRevalidate(\n    TCL_UNUSED(Tcl_Interp *),\n    Entry *entryPtr,\n    VREASON reason)\n{\n    int code = EntryValidateChange(\n\t\t    entryPtr, entryPtr->entry.string, -1,0, reason);\n\n    if (code == TCL_BREAK) {\n\tTtkWidgetChangeState(&entryPtr->core, TTK_STATE_INVALID, 0);\n    } else if (code == TCL_OK) {\n\tTtkWidgetChangeState(&entryPtr->core, 0, TTK_STATE_INVALID);\n    }\n\n    return code;\n}\n\n/* EntryRevalidateBG --\n *\tRevalidate in the background (called from event handler).\n */\nstatic void EntryRevalidateBG(Entry *entryPtr, VREASON reason)\n{\n    Tcl_Interp *interp = entryPtr->core.interp;\n    VMODE vmode = entryPtr->entry.validate;\n\n    if (EntryNeedsValidation(vmode, reason)) {\n\tif (EntryRevalidate(interp, entryPtr, reason) == TCL_ERROR) {\n\t    Tcl_BackgroundException(interp, TCL_ERROR);\n\t}\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Entry widget modification.\n */\n\n/* AdjustIndex --\n *\tAdjust index to account for insertion (nChars > 0)\n *\tor deletion (nChars < 0) at specified index.\n */\nstatic Tcl_Size AdjustIndex(Tcl_Size i0, Tcl_Size index, Tcl_Size nChars)\n{\n    if (i0 >= index) {\n\ti0 += nChars;\n\tif (i0 < index) { /* index was inside deleted range */\n\t    i0 = index;\n\t}\n    }\n    return i0;\n}\n\n/* AdjustIndices --\n *\tAdjust all internal entry indexes to account for change.\n *\tNote that insertPos, and selectFirst have \"right gravity\",\n *\twhile leftIndex (=xscroll.first) and selectLast have \"left gravity\".\n */\nstatic void AdjustIndices(Entry *entryPtr, Tcl_Size index, Tcl_Size nChars)\n{\n    EntryPart *e = &entryPtr->entry;\n    int g = nChars > 0;\t\t/* left gravity adjustment */\n\n    e->insertPos    = AdjustIndex(e->insertPos, index, nChars);\n    e->selectFirst  = AdjustIndex(e->selectFirst, index, nChars);\n    e->selectLast   = AdjustIndex(e->selectLast, index+g, nChars);\n    e->xscroll.first= AdjustIndex(e->xscroll.first, index+g, nChars);\n\n    if (e->selectLast <= e->selectFirst) {\n\te->selectFirst = e->selectLast = TCL_INDEX_NONE;\n    }\n}\n\n/* EntryStoreValue --\n *\tReplace the contents of a text entry with a given value,\n *\trecompute dependent resources, and schedule a redisplay.\n *\n *\tSee also: EntrySetValue().\n */\nstatic void\nEntryStoreValue(Entry *entryPtr, const char *value)\n{\n    size_t numBytes = strlen(value);\n    Tcl_Size numChars = Tcl_NumUtfChars(value, numBytes);\n\n    if (entryPtr->core.flags & VALIDATING) {\n\tentryPtr->core.flags |= VALIDATION_SET_VALUE;\n    }\n\n    /* Make sure all indices remain in bounds:\n     */\n    if (numChars < entryPtr->entry.numChars) {\n\tAdjustIndices(entryPtr, numChars, numChars - entryPtr->entry.numChars);\n    }\n\n    /* Free old value:\n     */\n    if (entryPtr->entry.displayString != entryPtr->entry.string) {\n\tTcl_Free(entryPtr->entry.displayString);\n    }\n    Tcl_Free(entryPtr->entry.string);\n\n    /* Store new value:\n     */\n    entryPtr->entry.string = (char *)Tcl_Alloc(numBytes + 1);\n    strcpy(entryPtr->entry.string, value);\n    entryPtr->entry.numBytes = numBytes;\n    entryPtr->entry.numChars = numChars;\n\n    entryPtr->entry.displayString\n\t= entryPtr->entry.showCharObj\n\t? EntryDisplayString(Tcl_GetString(entryPtr->entry.showCharObj), numChars)\n\t: entryPtr->entry.string\n\t;\n\n    /* Update layout, schedule redisplay:\n     */\n    EntryUpdateTextLayout(entryPtr);\n    TtkRedisplayWidget(&entryPtr->core);\n}\n\n/* EntrySetValue --\n *\tStores a new value in the entry widget and updates the\n *\tlinked -textvariable, if any.  The write trace on the\n *\ttext variable is temporarily disabled; however, other\n *\twrite traces may change the value of the variable.\n *\tIf so, the widget is updated again with the new value.\n *\n * Returns:\n *\tTCL_OK if successful, TCL_ERROR otherwise.\n */\nstatic int EntrySetValue(Entry *entryPtr, const char *value)\n{\n    EntryStoreValue(entryPtr, value);\n\n    if (entryPtr->entry.textVariableObj) {\n\tconst char *textVarName =\n\t    Tcl_GetString(entryPtr->entry.textVariableObj);\n\tif (textVarName && *textVarName) {\n\t    entryPtr->core.flags |= SYNCING_VARIABLE;\n\t    value = Tcl_SetVar2(entryPtr->core.interp, textVarName,\n\t\t    NULL, value, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);\n\t    entryPtr->core.flags &= ~SYNCING_VARIABLE;\n\t    if (!value || WidgetDestroyed(&entryPtr->core)) {\n\t\treturn TCL_ERROR;\n\t    } else if (strcmp(value, entryPtr->entry.string) != 0) {\n\t\t/* Some write trace has changed the variable value.\n\t\t */\n\t\tEntryStoreValue(entryPtr, value);\n\t    }\n\t}\n    }\n\n    return TCL_OK;\n}\n\n/* EntryTextVariableTrace --\n *\tVariable trace procedure for entry -textvariable\n */\nstatic void EntryTextVariableTrace(void *recordPtr, const char *value)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n\n    if (WidgetDestroyed(&entryPtr->core)) {\n\treturn;\n    }\n\n    if (entryPtr->core.flags & SYNCING_VARIABLE) {\n\t/* Trace was fired due to Tcl_SetVar2 call in EntrySetValue.\n\t * Don't do anything.\n\t */\n\treturn;\n    }\n\n    EntryStoreValue(entryPtr, value ? value : \"\");\n}\n\n/*------------------------------------------------------------------------\n * +++ Insertion and deletion.\n */\n\n/* InsertChars --\n *\tAdd new characters to an entry widget.\n */\nstatic int\nInsertChars(\n    Entry *entryPtr,\t\t/* Entry that is to get the new elements. */\n    Tcl_Size index,\t\t\t/* Insert before this index */\n    Tcl_Obj *obj)\t\t\t/* New characters to add */\n{\n    char *string = entryPtr->entry.string;\n    const char *value = Tcl_GetString(obj);\n    size_t byteIndex = Tcl_UtfAtIndex(string, index) - string;\n    size_t byteCount = strlen(value);\n    Tcl_Size charsAdded = Tcl_NumUtfChars(value, byteCount);\n    size_t newByteCount = entryPtr->entry.numBytes + byteCount + 1;\n    char *newBytes;\n    int code;\n\n    if (byteCount == 0) {\n\treturn TCL_OK;\n    }\n\n    newBytes =  (char *)Tcl_Alloc(newByteCount);\n    memcpy(newBytes, string, byteIndex);\n    strcpy(newBytes + byteIndex, value);\n    strcpy(newBytes + byteIndex + byteCount, string + byteIndex);\n\n    code = EntryValidateChange(\n\t    entryPtr, newBytes, index, charsAdded, VALIDATE_INSERT);\n\n    if (code == TCL_OK) {\n\tAdjustIndices(entryPtr, index, charsAdded);\n\tcode = EntrySetValue(entryPtr, newBytes);\n    } else if (code == TCL_BREAK) {\n\tcode = TCL_OK;\n    }\n\n    Tcl_Free(newBytes);\n    return code;\n}\n\n/* DeleteChars --\n *\tRemove one or more characters from an entry widget.\n */\nstatic int\nDeleteChars(\n    Entry *entryPtr,\t\t/* Entry widget to modify. */\n    Tcl_Size index,\t\t\t/* Index of first character to delete. */\n    Tcl_Size count)\t\t\t/* How many characters to delete. */\n{\n    char *string = entryPtr->entry.string;\n    size_t byteIndex, byteCount, newByteCount;\n    char *newBytes;\n    int code;\n\n    if (index < 0) {\n\tindex = 0;\n    }\n    if (count + index  > entryPtr->entry.numChars) {\n\tcount = entryPtr->entry.numChars - index;\n    }\n    if (count <= 0) {\n\treturn TCL_OK;\n    }\n\n    byteIndex = Tcl_UtfAtIndex(string, index) - string;\n    byteCount = Tcl_UtfAtIndex(string+byteIndex, count) - (string+byteIndex);\n\n    newByteCount = entryPtr->entry.numBytes + 1 - byteCount;\n    newBytes =  (char *)Tcl_Alloc(newByteCount);\n    memcpy(newBytes, string, byteIndex);\n    strcpy(newBytes + byteIndex, string + byteIndex + byteCount);\n\n    code = EntryValidateChange(\n\t    entryPtr, newBytes, index, count, VALIDATE_DELETE);\n\n    if (code == TCL_OK) {\n\tAdjustIndices(entryPtr, index, -count);\n\tcode = EntrySetValue(entryPtr, newBytes);\n    } else if (code == TCL_BREAK) {\n\tcode = TCL_OK;\n    }\n    Tcl_Free(newBytes);\n\n    return code;\n}\n\n/*------------------------------------------------------------------------\n * +++ Event handler.\n */\n\n/* EntryEventProc --\n *\tExtra event handling for entry widgets:\n *\tTriggers validation on FocusIn and FocusOut events.\n */\n#define EntryEventMask (FocusChangeMask)\nstatic void\nEntryEventProc(void *clientData, XEvent *eventPtr)\n{\n    Entry *entryPtr = (Entry *)clientData;\n\n    Tcl_Preserve(clientData);\n    switch (eventPtr->type) {\n\tcase DestroyNotify:\n\t    Tk_DeleteEventHandler(entryPtr->core.tkwin,\n\t\t    EntryEventMask, EntryEventProc, clientData);\n\t    break;\n\tcase FocusIn:\n\t    EntryRevalidateBG(entryPtr, VALIDATE_FOCUSIN);\n\t    break;\n\tcase FocusOut:\n\t    EntryRevalidateBG(entryPtr, VALIDATE_FOCUSOUT);\n\t    break;\n    }\n    Tcl_Release(clientData);\n}\n\n/*------------------------------------------------------------------------\n * +++ Initialization and cleanup.\n */\n\nstatic void\nEntryInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n\n    Tk_CreateEventHandler(\n\tentryPtr->core.tkwin, EntryEventMask, EntryEventProc, entryPtr);\n    Tk_CreateSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING,\n\tEntryFetchSelection, entryPtr, XA_STRING);\n    TtkBlinkCursor(&entryPtr->core);\n\n    entryPtr->entry.string\t\t= (char *)Tcl_Alloc(1);\n    *entryPtr->entry.string\t\t= '\\0';\n    entryPtr->entry.displayString\t= entryPtr->entry.string;\n    entryPtr->entry.textVariableTrace\t= 0;\n    entryPtr->entry.numBytes = entryPtr->entry.numChars = 0;\n\n    EntryInitStyleDefaults(&entryPtr->entry.styleDefaults);\n\n    entryPtr->entry.xscrollHandle =\n\tTtkCreateScrollHandle(&entryPtr->core, &entryPtr->entry.xscroll);\n\n    entryPtr->entry.insertPos\t\t= 0;\n    entryPtr->entry.selectFirst\t= TCL_INDEX_NONE;\n    entryPtr->entry.selectLast\t\t= TCL_INDEX_NONE;\n}\n\nstatic void\nEntryCleanup(void *recordPtr)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n\n    if (entryPtr->entry.textVariableTrace) {\n\tTtk_UntraceVariable(entryPtr->entry.textVariableTrace);\n    }\n\n    TtkFreeScrollHandle(entryPtr->entry.xscrollHandle);\n\n    EntryFreeStyleDefaults(&entryPtr->entry.styleDefaults);\n\n    Tk_DeleteSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING);\n\n    Tk_FreeTextLayout(entryPtr->entry.textLayout);\n    if (entryPtr->entry.displayString != entryPtr->entry.string) {\n\tTcl_Free(entryPtr->entry.displayString);\n    }\n    Tcl_Free(entryPtr->entry.string);\n}\n\n/* EntryConfigure --\n *\tConfigure hook for Entry widgets.\n */\nstatic int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Tcl_Obj *textVarName = entryPtr->entry.textVariableObj;\n    Ttk_TraceHandle *vt = 0;\n\n    if (mask & TEXTVAR_CHANGED) {\n\tif (!TkObjIsEmpty(textVarName)) {\n\t    vt = Ttk_TraceVariable(interp,\n\t\t    textVarName,EntryTextVariableTrace,entryPtr);\n\t    if (!vt) return TCL_ERROR;\n\t}\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\n\tif (vt) Ttk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    /* Update derived resources:\n     */\n    if (mask & TEXTVAR_CHANGED) {\n\tif (entryPtr->entry.textVariableTrace) {\n\t    Ttk_UntraceVariable(entryPtr->entry.textVariableTrace);\n\t}\n\tentryPtr->entry.textVariableTrace = vt;\n    }\n\n    /* Claim the selection, in case we've suddenly started exporting it.\n     */\n    if (entryPtr->entry.exportSelection && (entryPtr->entry.selectFirst >= 0)\n\t    && (!Tcl_IsSafe(entryPtr->core.interp))) {\n\tEntryOwnSelection(entryPtr);\n    }\n\n    /* Handle -state compatibility option:\n     */\n    if (mask & STATE_CHANGED) {\n\tTtkCheckStateOption(&entryPtr->core, entryPtr->entry.stateObj);\n    }\n\n    /* Force scrollbar update if needed:\n     */\n    if (mask & SCROLLCMD_CHANGED) {\n\tTtkScrollbarUpdateRequired(entryPtr->entry.xscrollHandle);\n    }\n\n    /* Recompute the displayString, in case showChar changed:\n     */\n    if (entryPtr->entry.displayString != entryPtr->entry.string) {\n\tTcl_Free(entryPtr->entry.displayString);\n    }\n\n    entryPtr->entry.displayString\n\t= entryPtr->entry.showCharObj\n\t? EntryDisplayString(Tcl_GetString(entryPtr->entry.showCharObj), entryPtr->entry.numChars)\n\t: entryPtr->entry.string\n\t;\n\n    /* Update textLayout:\n     */\n    EntryUpdateTextLayout(entryPtr);\n    return TCL_OK;\n}\n\n/* EntryPostConfigure --\n *\tPost-configuration hook for entry widgets.\n */\nstatic int EntryPostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr,\n    int mask)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    int status = TCL_OK;\n\n    if ((mask & TEXTVAR_CHANGED) && entryPtr->entry.textVariableTrace != NULL) {\n\tstatus = Ttk_FireTrace(entryPtr->entry.textVariableTrace);\n    }\n\n    return status;\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout and display.\n */\n\n/* EntryCharPosition --\n *\tReturn the X coordinate of the specified character index.\n *\tPrecondition: textLayout and layoutX up-to-date.\n */\nstatic int\nEntryCharPosition(Entry *entryPtr, Tcl_Size index)\n{\n    int xPos;\n    Tk_CharBbox(entryPtr->entry.textLayout, index, &xPos, NULL, NULL, NULL);\n    return xPos + entryPtr->entry.layoutX;\n}\n\n/* EntryDoLayout --\n *\tLayout hook for entry widgets.\n *\n *\tDetermine position of textLayout based on xscroll.first, justify,\n *\tand display area.\n *\n *\tRecalculates layoutX, layoutY, and rightIndex,\n *\tand updates xscroll accordingly.\n *\tMay adjust xscroll.first to ensure the maximum #characters are onscreen.\n */\nstatic void\nEntryDoLayout(void *recordPtr)\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    WidgetCore *corePtr = &entryPtr->core;\n    Tk_TextLayout textLayout = entryPtr->entry.textLayout;\n    Tcl_Size leftIndex = entryPtr->entry.xscroll.first;\n    Tcl_Size rightIndex;\n    Ttk_Box textarea;\n\n    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));\n    textarea = Ttk_ClientRegion(corePtr->layout, \"textarea\");\n\n    /* Center the text vertically within the available parcel:\n     */\n    entryPtr->entry.layoutY = textarea.y +\n\t(textarea.height - entryPtr->entry.layoutHeight)/2;\n\n    /* Recompute where the leftmost character on the display will\n     * be drawn (layoutX) and adjust leftIndex if necessary.\n     */\n    if (entryPtr->entry.layoutWidth <= textarea.width) {\n\t/* Everything fits.  Set leftIndex to zero (no need to scroll),\n\t * and compute layoutX based on -justify.\n\t */\n\tint extraSpace = textarea.width - entryPtr->entry.layoutWidth;\n\tleftIndex = 0;\n\trightIndex = entryPtr->entry.numChars;\n\tentryPtr->entry.layoutX = textarea.x;\n\tif (entryPtr->entry.justify == TK_JUSTIFY_RIGHT) {\n\t    entryPtr->entry.layoutX += extraSpace;\n\t} else if (entryPtr->entry.justify == TK_JUSTIFY_CENTER) {\n\t    entryPtr->entry.layoutX += extraSpace / 2;\n\t}\n    } else {\n\t/* The whole string doesn't fit in the window.\n\t * Limit leftIndex to leave at most one character's worth\n\t * of empty space on the right.\n\t */\n\tint overflow = entryPtr->entry.layoutWidth - textarea.width;\n\tTcl_Size maxLeftIndex = 1 + Tk_PointToChar(textLayout, overflow, 0);\n\tint leftX;\n\n\tif (leftIndex > maxLeftIndex) {\n\t    leftIndex = maxLeftIndex;\n\t}\n\n\t/* Compute layoutX and rightIndex.\n\t * rightIndex is set to one past the last fully-visible character.\n\t */\n\tTk_CharBbox(textLayout, leftIndex, &leftX, NULL, NULL, NULL);\n\trightIndex = Tk_PointToChar(textLayout, leftX + textarea.width, 0);\n\tentryPtr->entry.layoutX = textarea.x - leftX;\n    }\n\n    TtkScrolled(entryPtr->entry.xscrollHandle,\n\t    leftIndex, rightIndex, entryPtr->entry.numChars);\n}\n\n/* EntryGetGC -- Helper routine.\n *      Get a GC using the specified foreground color and the entry's font.\n *      Result must be freed with Tk_FreeGC().\n */\nstatic GC EntryGetGC(Entry *entryPtr, Tcl_Obj *colorObj, Region clip)\n{\n    Tk_Window tkwin = entryPtr->core.tkwin;\n    Tk_Font font = Tk_GetFontFromObj(tkwin, entryPtr->entry.fontObj);\n    XColor *colorPtr;\n    unsigned long mask = 0ul;\n    XGCValues gcValues;\n    GC gc;\n\n    gcValues.line_width = 1; mask |= GCLineWidth;\n    gcValues.font = Tk_FontId(font); mask |= GCFont;\n    if (colorObj != 0 && (colorPtr=Tk_GetColorFromObj(tkwin,colorObj)) != 0) {\n\tgcValues.foreground = colorPtr->pixel;\n\tmask |= GCForeground;\n    }\n    gc = Tk_GetGC(entryPtr->core.tkwin, mask, &gcValues);\n    if (clip != NULL) {\n\tXSetRegion(Tk_Display(entryPtr->core.tkwin), gc, clip);\n    }\n    return gc;\n}\n\n/* EntryDisplay --\n *\tRedraws the contents of an entry window.\n */\nstatic void EntryDisplay(void *clientData, Drawable d)\n{\n    Entry *entryPtr = (Entry *)clientData;\n    Tk_Window tkwin = entryPtr->core.tkwin;\n    Tcl_Size leftIndex = entryPtr->entry.xscroll.first,\n\trightIndex = entryPtr->entry.xscroll.last + 1,\n\tselFirst = entryPtr->entry.selectFirst,\n\tselLast = entryPtr->entry.selectLast;\n    EntryStyleData es;\n    GC gc;\n    int showSelection, showCursor;\n    Ttk_Box textarea;\n    Region clipRegion;\n    XRectangle rect;\n    Tcl_Obj *foregroundObj;\n\n    EntryInitStyleData(entryPtr, &es);\n\n    textarea = Ttk_ClientRegion(entryPtr->core.layout, \"textarea\");\n    showCursor =\n\t   (entryPtr->core.flags & CURSOR_ON)\n\t&& EntryEditable(entryPtr)\n\t&& entryPtr->entry.insertPos >= leftIndex\n\t&& entryPtr->entry.insertPos <= rightIndex\n\t;\n    showSelection =\n\t   !(entryPtr->core.state & TTK_STATE_DISABLED)\n\t&& selFirst >= 0\n\t&& selLast > leftIndex\n\t&& selFirst <= rightIndex;\n\n    /* Adjust selection range to keep in display bounds.\n     */\n    if (showSelection) {\n\tif (selFirst < leftIndex) {\n\t    selFirst = leftIndex;\n\t}\n\tif (selLast > rightIndex) {\n\t    selLast = rightIndex;\n\t}\n    }\n\n    /* Draw widget background & border\n     */\n    Ttk_DrawLayout(entryPtr->core.layout, entryPtr->core.state, d);\n\n    /* Draw selection background\n     */\n    if (showSelection && es.selBorderObj) {\n\tTk_3DBorder selBorder = Tk_Get3DBorderFromObj(tkwin, es.selBorderObj);\n\tint selStartX = EntryCharPosition(entryPtr, selFirst);\n\tint selEndX = EntryCharPosition(entryPtr, selLast);\n\tint borderWidth = 0;\n\n\tTk_GetPixelsFromObj(NULL, tkwin, es.selBorderWidthObj, &borderWidth);\n\n\tif (selBorder) {\n\t    int selWidth;\n\t    int textareaEnd = textarea.x + textarea.width;\n\t    if (selEndX > textareaEnd) {\n\t\tselEndX = textareaEnd;\n\t    }\n\t    selWidth = selEndX - selStartX + 2 * borderWidth;\n\t    if (selWidth > 0) {\n\t\tTk_Fill3DRectangle(tkwin, d, selBorder,\n\t\tselStartX - borderWidth, entryPtr->entry.layoutY - borderWidth,\n\t\tselWidth, entryPtr->entry.layoutHeight + 2*borderWidth,\n\t\tborderWidth, TK_RELIEF_RAISED);\n\t    }\n\t}\n    }\n\n    /* Initialize the clip region. Note that Xft does _not_ derive its\n     * clipping area from the GC, so we have to supply that by other means.\n     */\n\n    rect.x = (short)textarea.x;\n    rect.y = (short)textarea.y;\n    rect.width = (unsigned short)textarea.width;\n    rect.height = (unsigned short)textarea.height;\n    clipRegion = XCreateRegion();\n    XUnionRectWithRegion(&rect, clipRegion, clipRegion);\n#ifdef HAVE_XFT\n    TkUnixSetXftClipRegion(clipRegion);\n#endif\n\n    /* Draw cursor:\n     */\n    if (showCursor) {\n\tTtk_Box field = Ttk_ClientRegion(entryPtr->core.layout, \"field\");\n\tint cursorX = EntryCharPosition(entryPtr, entryPtr->entry.insertPos),\n\t    cursorY = entryPtr->entry.layoutY,\n\t    cursorHeight = entryPtr->entry.layoutHeight,\n\t    cursorWidth = 1;\n\n\tTk_GetPixelsFromObj(NULL, tkwin, es.insertWidthObj, &cursorWidth);\n\tif (cursorWidth <= 0) {\n\t    cursorWidth = 1;\n\t}\n\n\t/* @@@ should: maybe: SetCaretPos even when blinked off */\n\tTk_SetCaretPos(tkwin, cursorX, cursorY, cursorHeight);\n\n\tcursorX -= cursorWidth/2;\n\tif (cursorX < field.x) {\n\t    cursorX = field.x;\n\t} else if (cursorX + cursorWidth > field.x + field.width) {\n\t    cursorX = field.x + field.width - cursorWidth;\n\t}\n\n\tgc = EntryGetGC(entryPtr, es.insertColorObj, NULL);\n\tXFillRectangle(Tk_Display(tkwin), d, gc,\n\t    cursorX, cursorY, cursorWidth, cursorHeight);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n    }\n\n    /* Draw the text:\n     */\n    if ((*(entryPtr->entry.displayString) == '\\0')\n\t\t&& (entryPtr->entry.placeholderObj != NULL)) {\n\t/* No text displayed, but -placeholder is given */\n\tif (Tcl_GetCharLength(es.placeholderForegroundObj) > 0) {\n\t    foregroundObj = es.placeholderForegroundObj;\n\t} else {\n\t    foregroundObj = es.foregroundObj;\n\t}\n\t/* Use placeholder text width */\n\tleftIndex = 0;\n\trightIndex = Tcl_GetCharLength(entryPtr->entry.placeholderObj);\n    } else {\n\tforegroundObj = es.foregroundObj;\n    }\n    gc = EntryGetGC(entryPtr, foregroundObj, clipRegion);\n    if (showSelection) {\n\n\t/* Draw the selected and unselected portions separately.\n\t */\n\tif (leftIndex < selFirst) {\n\t    Tk_DrawTextLayout(\n\t\tTk_Display(tkwin), d, gc, entryPtr->entry.textLayout,\n\t\tentryPtr->entry.layoutX, entryPtr->entry.layoutY,\n\t\tleftIndex, selFirst);\n\t}\n\tif (selLast < rightIndex) {\n\t    Tk_DrawTextLayout(\n\t\tTk_Display(tkwin), d, gc, entryPtr->entry.textLayout,\n\t\tentryPtr->entry.layoutX, entryPtr->entry.layoutY,\n\t\tselLast, rightIndex);\n\t}\n\tXSetClipMask(Tk_Display(tkwin), gc, None);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n\n\t/* Draw the selected portion in the -selectforeground color:\n\t */\n\tgc = EntryGetGC(entryPtr, es.selForegroundObj, clipRegion);\n\tTk_DrawTextLayout(\n\t    Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,\n\t    entryPtr->entry.layoutX, entryPtr->entry.layoutY,\n\t    selFirst, selLast);\n\tXSetClipMask(Tk_Display(tkwin), gc, None);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n    } else {\n\n\t/* Draw the entire visible text\n\t */\n\tTk_DrawTextLayout(\n\t    Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,\n\t    entryPtr->entry.layoutX, entryPtr->entry.layoutY,\n\t    leftIndex, rightIndex);\n\tXSetClipMask(Tk_Display(tkwin), gc, None);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n    }\n\n    /* Drop the region. Note that we have to manually remove the reference to\n     * it from the Xft guts (if they're being used).\n     */\n#ifdef HAVE_XFT\n    TkUnixSetXftClipRegion(NULL);\n#endif\n    XDestroyRegion(clipRegion);\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands.\n */\n\n/* EntryIndex --\n *\tParse an index into an entry and return either its value\n *\tor an error.\n *\n * Results:\n *\tA standard Tcl result.  If all went well, then *indexPtr is\n *\tfilled in with the character index (into entryPtr) corresponding to\n *\tstring.  The index value is guaranteed to lie between 0 and\n *\tthe number of characters in the string, inclusive.  If an\n *\terror occurs then an error message is left in the interp's result.\n */\nstatic int\nEntryIndex(\n    Tcl_Interp *interp,\t\t/* For error messages. */\n    Entry *entryPtr,\t\t/* Entry widget to query */\n    Tcl_Obj *indexObj,\t\t/* Symbolic index name */\n    Tcl_Size *indexPtr)\t\t/* Return value */\n{\n#   define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */\n    Tcl_Size length, idx;\n    const char *string;\n\n    if (TCL_OK == TkGetIntForIndex(indexObj, entryPtr->entry.numChars - 1, 1, &idx)) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else if (idx > entryPtr->entry.numChars) {\n\t    idx = entryPtr->entry.numChars;\n\t}\n\t*indexPtr = idx;\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetStringFromObj(indexObj, &length);\n\n    if (strncmp(string, \"insert\", length) == 0) {\n\t*indexPtr = entryPtr->entry.insertPos;\n    } else if (strncmp(string, \"left\", length) == 0) {\t/* for debugging */\n\t*indexPtr = entryPtr->entry.xscroll.first;\n    } else if (strncmp(string, \"right\", length) == 0) {\t/* for debugging */\n\t*indexPtr = entryPtr->entry.xscroll.last;\n    } else if (strncmp(string, \"sel.\", 4) == 0) {\n\tif (entryPtr->entry.selectFirst < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"selection isn't in widget %s\",\n\t\t    Tk_PathName(entryPtr->core.tkwin)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"ENTRY\", \"NO_SELECTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (strncmp(string, \"sel.first\", length) == 0) {\n\t    *indexPtr = entryPtr->entry.selectFirst;\n\t} else if (strncmp(string, \"sel.last\", length) == 0) {\n\t    *indexPtr = entryPtr->entry.selectLast;\n\t} else {\n\t    goto badIndex;\n\t}\n    } else if (string[0] == '@') {\n\tint roundUp = 0;\n\tint maxWidth = EntryWidth(entryPtr);\n\tint x;\n\n\tif (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) {\n\t    goto badIndex;\n\t}\n\tif (x > maxWidth) {\n\t    x = maxWidth;\n\t    roundUp = 1;\n\t}\n\t*indexPtr = Tk_PointToChar(entryPtr->entry.textLayout,\n\t\tx - entryPtr->entry.layoutX, 0);\n\n\tTtkUpdateScrollInfo(entryPtr->entry.xscrollHandle);\n\tif (*indexPtr < entryPtr->entry.xscroll.first) {\n\t    *indexPtr = entryPtr->entry.xscroll.first;\n\t}\n\n\t/*\n\t * Special trick:  if the x-position was off-screen to the right,\n\t * round the index up to refer to the character just after the\n\t * last visible one on the screen.  This is needed to enable the\n\t * last character to be selected, for example.\n\t */\n\n\tif (roundUp && (*indexPtr < entryPtr->entry.numChars)) {\n\t    *indexPtr += 1;\n\t}\n    } else {\n\tgoto badIndex;\n    }\n    return TCL_OK;\n\nbadIndex:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad entry index \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TTK\", \"ENTRY\", \"INDEX\", (char *)NULL);\n    return TCL_ERROR;\n}\n\n/* $entry bbox $index --\n *\tReturn the bounding box of the character at the specified index.\n */\nstatic int\nEntryBBoxCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Ttk_Box b;\n    Tcl_Size index;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"index\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if ((index == entryPtr->entry.numChars) && (index > 0)) {\n\tindex--;\n    }\n    Tk_CharBbox(entryPtr->entry.textLayout, index,\n\t    &b.x, &b.y, &b.width, &b.height);\n    b.x += entryPtr->entry.layoutX;\n    b.y += entryPtr->entry.layoutY;\n    Tcl_SetObjResult(interp, Ttk_NewBoxObj(b));\n    return TCL_OK;\n}\n\n/* $entry delete $from ?$to? --\n *\tDelete the characters in the range [$from,$to).\n *\t$to defaults to $from+1 if not specified.\n */\nstatic int\nEntryDeleteCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Tcl_Size first, last;\n\n    if ((objc < 3) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"firstIndex ?lastIndex?\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[2], &first) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tlast = first + 1;\n    } else if (EntryIndex(interp, entryPtr, objv[3], &last) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (last >= first && EntryEditable(entryPtr)) {\n\treturn DeleteChars(entryPtr, first, last - first);\n    }\n    return TCL_OK;\n}\n\n/* $entry get --\n *\tReturn the current value of the entry widget.\n */\nstatic int\nEntryGetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->entry.string, -1));\n    return TCL_OK;\n}\n\n/* $entry icursor $index --\n *\tSet the insert cursor position.\n */\nstatic int\nEntryICursorCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"pos\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[2],\n\t    &entryPtr->entry.insertPos) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    TtkRedisplayWidget(&entryPtr->core);\n    return TCL_OK;\n}\n\n/* $entry index $index --\n *\tReturn numeric value (0..numChars) of the specified index.\n */\nstatic int\nEntryIndexCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Tcl_Size index;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"string\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, TkNewIndexObj(index));\n    return TCL_OK;\n}\n\n/* $entry insert $index $text --\n *\tInsert $text after position $index.\n *\tSilent no-op if the entry is disabled or read-only.\n */\nstatic int\nEntryInsertCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Tcl_Size index;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"index text\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (EntryEditable(entryPtr)) {\n\treturn InsertChars(entryPtr, index, objv[3]);\n    }\n    return TCL_OK;\n}\n\n/* $entry selection clear --\n *\tClear selection.\n */\nstatic int EntrySelectionClearCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;\n    TtkRedisplayWidget(&entryPtr->core);\n    return TCL_OK;\n}\n\n/* $entry selection present --\n *\tReturns 1 if any characters are selected, 0 otherwise.\n */\nstatic int EntrySelectionPresentCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp,\n\t    Tcl_NewBooleanObj(entryPtr->entry.selectFirst >= 0));\n    return TCL_OK;\n}\n\n/* $entry selection range $start $end --\n *\tExplicitly set the selection range.\n */\nstatic int EntrySelectionRangeCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    Tcl_Size start, end;\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"start end\");\n\treturn TCL_ERROR;\n    }\n    if (EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK\n\t || EntryIndex(interp, entryPtr, objv[4], &end) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (entryPtr->core.state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n\n    if (start >= end) {\n\tentryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;\n    } else {\n\tentryPtr->entry.selectFirst = start;\n\tentryPtr->entry.selectLast = end;\n\tEntryOwnSelection(entryPtr);\n    }\n    TtkRedisplayWidget(&entryPtr->core);\n    return TCL_OK;\n}\n\nstatic const Ttk_Ensemble EntrySelectionCommands[] = {\n    { \"clear\",   EntrySelectionClearCommand,0 },\n    { \"present\", EntrySelectionPresentCommand,0 },\n    { \"range\",   EntrySelectionRangeCommand,0 },\n    { 0,0,0 }\n};\n\n/* $entry set $value\n *\tSets the value of an entry widget.\n */\nstatic int EntrySetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"value\");\n\treturn TCL_ERROR;\n    }\n    EntrySetValue(entryPtr, Tcl_GetString(objv[2]));\n    return TCL_OK;\n}\n\n/* $entry validate --\n *\tTrigger forced validation.  Returns 1/0 if validation succeeds/fails\n *\tor error status from -validatecommand / -invalidcommand.\n */\nstatic int EntryValidateCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    int code;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, NULL);\n\treturn TCL_ERROR;\n    }\n\n    code = EntryRevalidate(interp, entryPtr, VALIDATE_FORCED);\n\n    if (code == TCL_ERROR) {\n\treturn code;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));\n    return TCL_OK;\n}\n\n/* $entry xview\t-- horizontal scrolling interface\n */\nstatic int EntryXViewCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Entry *entryPtr = (Entry *)recordPtr;\n    if (objc == 3) {\n\tTcl_Size newFirst;\n\tif (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, true);\n\treturn TCL_OK;\n    }\n    return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle);\n}\n\nstatic const Ttk_Ensemble EntryCommands[] = {\n    { \"bbox\",\t\tEntryBBoxCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"delete\",\tEntryDeleteCommand,0 },\n    { \"get\",\t\tEntryGetCommand,0 },\n    { \"icursor\",\tEntryICursorCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"index\",\t\tEntryIndexCommand,0 },\n    { \"insert\",\tEntryInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"selection\",\t0,EntrySelectionCommands },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { \"validate\",\tEntryValidateCommand,0 },\n    { \"xview\",\t\tEntryXViewCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Entry widget definition.\n */\n\nstatic const WidgetSpec EntryWidgetSpec = {\n    \"TEntry\",\t\t\t/* className */\n    sizeof(Entry),\t\t/* recordSize */\n    EntryOptionSpecs,\t\t/* optionSpecs */\n    EntryCommands,\t\t/* subcommands */\n    EntryInitialize,\t/* initializeProc */\n    EntryCleanup,\t\t/* cleanupProc */\n    EntryConfigure,\t\t/* configureProc */\n    EntryPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    EntryDoLayout,\t\t/* layoutProc */\n    EntryDisplay\t\t/* displayProc */\n};\n\n/*------------------------------------------------------------------------\n * +++ Combobox widget record.\n */\n\ntypedef struct {\n    Tcl_Obj\t*postCommandObj;\n    Tcl_Obj\t*valuesObj;\n    Tcl_Obj\t*heightObj;\n    Tcl_Size\tcurrentIndex;\n} ComboboxPart;\n\ntypedef struct {\n    WidgetCore core;\n    EntryPart entry;\n    ComboboxPart combobox;\n} Combobox;\n\nstatic const Tk_OptionSpec ComboboxOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-height\", \"height\", \"Height\",\n\tDEF_LIST_HEIGHT, offsetof(Combobox, combobox.heightObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-postcommand\", \"postCommand\", \"PostCommand\",\n\t\"\", offsetof(Combobox, combobox.postCommandObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-values\", \"values\", \"Values\",\n\t\"\", offsetof(Combobox, combobox.valuesObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)\n};\n\n/* ComboboxInitialize --\n *\tInitialization hook for combobox widgets.\n */\nstatic void\nComboboxInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Combobox *cb = (Combobox *)recordPtr;\n\n    cb->combobox.currentIndex = TCL_INDEX_NONE;\n    TtkTrackElementState(&cb->core);\n    EntryInitialize(interp, recordPtr);\n}\n\n/* ComboboxConfigure --\n *\tConfiguration hook for combobox widgets.\n */\nstatic int\nComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Combobox *cbPtr = (Combobox *)recordPtr;\n    Tcl_Size unused;\n\n    /* Make sure -values is a valid list:\n     */\n    if (Tcl_ListObjLength(interp,cbPtr->combobox.valuesObj,&unused) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    return EntryConfigure(interp, recordPtr, mask);\n}\n\n/* $cb current ?newIndex? -- get or set current index.\n *\tSetting the current index updates the combobox value,\n *\tbut the value and -values may be changed independently\n *\tof the index.  Instead of trying to keep currentIndex\n *\tin sync at all times, [$cb current] double-checks\n */\nstatic int ComboboxCurrentCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Combobox *cbPtr = (Combobox *)recordPtr;\n    Tcl_Size currentIndex = cbPtr->combobox.currentIndex;\n    const char *currentValue = cbPtr->entry.string;\n    Tcl_Size nValues;\n    Tcl_Obj **values;\n\n    Tcl_ListObjGetElements(interp, cbPtr->combobox.valuesObj, &nValues, &values);\n\n    if (objc == 2) {\n\t/* Check if currentIndex still valid:\n\t */\n\tif (currentIndex < 0\n\t     || currentIndex >= nValues\n\t     || strcmp(currentValue,Tcl_GetString(values[currentIndex]))\n\t   )\n\t{\n\t    /* Not valid.  Check current value against each element in -values:\n\t     */\n\t    for (currentIndex = 0; currentIndex < nValues; ++currentIndex) {\n\t\tif (!strcmp(currentValue,Tcl_GetString(values[currentIndex]))) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (currentIndex >= nValues) {\n\t\t/* Not found */\n\t\tcurrentIndex = TCL_INDEX_NONE;\n\t    }\n\t}\n\tcbPtr->combobox.currentIndex = currentIndex;\n\tTcl_SetObjResult(interp, TkNewIndexObj(currentIndex));\n\treturn TCL_OK;\n    } else if (objc == 3) {\n\tTcl_Size idx;\n\n\tif (TCL_OK == TkGetIntForIndex(objv[2], nValues - 1, 0, &idx)) {\n\t    if (idx < 0 || idx >= nValues) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"index \\\"%s\\\" out of range\", Tcl_GetString(objv[2])));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"COMBOBOX\", \"IDX_RANGE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    currentIndex = idx;\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad index \\\"%s\\\"\", Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"COMBOBOX\", \"IDX_VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tcbPtr->combobox.currentIndex = currentIndex;\n\n\treturn EntrySetValue((Entry *)recordPtr, Tcl_GetString(values[currentIndex]));\n    } else {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?newIndex?\");\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Combobox widget definition.\n */\nstatic const Ttk_Ensemble ComboboxCommands[] = {\n    { \"bbox\",\t\tEntryBBoxCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"current\",\tComboboxCurrentCommand,0 },\n    { \"delete\",\tEntryDeleteCommand,0 },\n    { \"get\",\t\tEntryGetCommand,0 },\n    { \"icursor\",\tEntryICursorCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"index\",\t\tEntryIndexCommand,0 },\n    { \"insert\",\tEntryInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"selection\",\t0,EntrySelectionCommands },\n    { \"set\",\t\tEntrySetCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { \"validate\",\tEntryValidateCommand,0 },\n    { \"xview\",\t\tEntryXViewCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec ComboboxWidgetSpec = {\n    \"TCombobox\",\t\t/* className */\n    sizeof(Combobox),\t\t/* recordSize */\n    ComboboxOptionSpecs,\t/* optionSpecs */\n    ComboboxCommands,\t\t/* subcommands */\n    ComboboxInitialize,\t/* initializeProc */\n    EntryCleanup,\t\t/* cleanupProc */\n    ComboboxConfigure,\t\t/* configureProc */\n    EntryPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    EntryDoLayout,\t\t/* layoutProc */\n    EntryDisplay\t\t/* displayProc */\n};\n\n/*------------------------------------------------------------------------\n * +++ Spinbox widget.\n */\n\ntypedef struct {\n    Tcl_Obj\t*valuesObj;\n\n    Tcl_Obj\t*fromObj;\n    Tcl_Obj\t*toObj;\n    Tcl_Obj\t*incrementObj;\n    Tcl_Obj\t*formatObj;\n\n    Tcl_Obj\t*wrapObj;\n    Tcl_Obj\t*commandObj;\n} SpinboxPart;\n\ntypedef struct {\n    WidgetCore core;\n    EntryPart entry;\n    SpinboxPart spinbox;\n} Spinbox;\n\nstatic const Tk_OptionSpec SpinboxOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-values\", \"values\", \"Values\",\n\t\"\", offsetof(Spinbox, spinbox.valuesObj), TCL_INDEX_NONE,\n\t0,0,0 },\n\n    {TK_OPTION_DOUBLE, \"-from\", \"from\", \"From\",\n\t\"0.0\", offsetof(Spinbox,spinbox.fromObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_DOUBLE, \"-to\", \"to\", \"To\",\n\t\"0.0\", offsetof(Spinbox,spinbox.toObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_DOUBLE, \"-increment\", \"increment\", \"Increment\",\n\t\"1.0\", offsetof(Spinbox,spinbox.incrementObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-format\", \"format\", \"Format\",\n\t\"\", offsetof(Spinbox, spinbox.formatObj), TCL_INDEX_NONE,\n\t0,0,0 },\n\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\",\n\t\"\", offsetof(Spinbox, spinbox.commandObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_BOOLEAN, \"-wrap\", \"wrap\", \"Wrap\",\n\t\"0\", offsetof(Spinbox,spinbox.wrapObj), TCL_INDEX_NONE,\n\t0,0,0 },\n\n    WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)\n};\n\n/* SpinboxInitialize --\n *\tInitialization hook for spinbox widgets.\n */\nstatic void\nSpinboxInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Spinbox *sb = (Spinbox *)recordPtr;\n\n    /*\n     * Create the WideSpinbox.uparrow and WideSpinbox.downarrow\n     * elements for the Wide.TSpinbox style if necessary\n     */\n    int code = Tcl_EvalEx(interp, \"ttk::wideSpinbox::CondMakeElements\",\n\t    TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_BackgroundException(interp, code);\n    }\n\n    TtkTrackElementState(&sb->core);\n    EntryInitialize(interp, recordPtr);\n}\n\n/* SpinboxConfigure --\n *\tConfiguration hook for spinbox widgets.\n */\nstatic int\nSpinboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Spinbox *sb = (Spinbox *)recordPtr;\n    Tcl_Size unused;\n\n    /* Make sure -values is a valid list:\n     */\n    if (Tcl_ListObjLength(interp,sb->spinbox.valuesObj,&unused) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    return EntryConfigure(interp, recordPtr, mask);\n}\n\nstatic const Ttk_Ensemble SpinboxCommands[] = {\n    { \"bbox\",\t\tEntryBBoxCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"delete\",\tEntryDeleteCommand,0 },\n    { \"get\",\t\tEntryGetCommand,0 },\n    { \"icursor\",\tEntryICursorCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"index\",\t\tEntryIndexCommand,0 },\n    { \"insert\",\tEntryInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"selection\",\t0,EntrySelectionCommands },\n    { \"set\",\t\tEntrySetCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { \"validate\",\tEntryValidateCommand,0 },\n    { \"xview\",\t\tEntryXViewCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec SpinboxWidgetSpec = {\n    \"TSpinbox\",\t\t\t/* className */\n    sizeof(Spinbox),\t\t/* recordSize */\n    SpinboxOptionSpecs,\t\t/* optionSpecs */\n    SpinboxCommands,\t\t/* subcommands */\n    SpinboxInitialize,\t/* initializeProc */\n    EntryCleanup,\t\t/* cleanupProc */\n    SpinboxConfigure,\t\t/* configureProc */\n    EntryPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    EntryDoLayout,\t\t/* layoutProc */\n    EntryDisplay\t\t/* displayProc */\n};\n\n/*------------------------------------------------------------------------\n * +++ Textarea element.\n *\n * Text display area for Entry widgets.\n * Just computes requested size; display is handled by the widget itself.\n */\n\ntypedef struct {\n    Tcl_Obj\t*fontObj;\n    Tcl_Obj\t*widthObj;\n} TextareaElement;\n\nstatic const Ttk_ElementOptionSpec TextareaElementOptions[] = {\n    { \"-font\", TK_OPTION_FONT,\n\toffsetof(TextareaElement,fontObj), DEF_ENTRY_FONT },\n    { \"-width\", TK_OPTION_INT,\n\toffsetof(TextareaElement,widthObj), \"20\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TextareaElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    TextareaElement *textarea = (TextareaElement *)elementRecord;\n    Tk_Font font = Tk_GetFontFromObj(tkwin, textarea->fontObj);\n    int avgWidth = Tk_TextWidth(font, \"0\", 1);\n    Tk_FontMetrics fm;\n    int prefWidth = 1;\n\n    Tk_GetFontMetrics(font, &fm);\n    Tcl_GetIntFromObj(NULL, textarea->widthObj, &prefWidth);\n    if (prefWidth <= 0) {\n\tprefWidth = 1;\n    }\n\n    *heightPtr = fm.linespace;\n    *widthPtr = prefWidth * avgWidth;\n}\n\nstatic const Ttk_ElementSpec TextareaElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TextareaElement),\n    TextareaElementOptions,\n    TextareaElementSize,\n    TtkNullElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget layouts.\n */\n\nTTK_BEGIN_LAYOUT(EntryLayout)\n    TTK_GROUP(\"Entry.field\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Entry.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Entry.textarea\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(ComboboxLayout)\n    TTK_GROUP(\"Combobox.field\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Combobox.downarrow\", TTK_PACK_RIGHT|TTK_FILL_Y)\n\tTTK_GROUP(\"Combobox.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Combobox.textarea\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(SpinboxLayout)\n    TTK_GROUP(\"Spinbox.field\", TTK_PACK_TOP|TTK_FILL_X,\n\tTTK_GROUP(\"null\", TTK_PACK_RIGHT,\n\t    TTK_NODE(\"Spinbox.uparrow\", TTK_PACK_TOP|TTK_STICK_E)\n\t    TTK_NODE(\"Spinbox.downarrow\", TTK_PACK_BOTTOM|TTK_STICK_E))\n\tTTK_GROUP(\"Spinbox.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Spinbox.textarea\", TTK_FILL_BOTH)))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkEntry_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme themePtr =  Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterElement(interp, themePtr, \"textarea\", &TextareaElementSpec, 0);\n\n    Ttk_RegisterLayout(themePtr, \"TEntry\", EntryLayout);\n    Ttk_RegisterLayout(themePtr, \"TCombobox\", ComboboxLayout);\n    Ttk_RegisterLayout(themePtr, \"TSpinbox\", SpinboxLayout);\n\n    RegisterWidget(interp, \"ttk::entry\", &EntryWidgetSpec);\n    RegisterWidget(interp, \"ttk::combobox\", &ComboboxWidgetSpec);\n    RegisterWidget(interp, \"ttk::spinbox\", &SpinboxWidgetSpec);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkFrame.c",
    "content": "/*\n * Copyright © 2004 Joe English\n *\n * ttk::frame and ttk::labelframe widgets.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n#include \"ttkManager.h\"\n\n/* ======================================================================\n * +++ Frame widget:\n */\n\ntypedef struct {\n    Tcl_Obj\t*borderWidthObj;\n    Tcl_Obj\t*paddingObj;\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*widthObj;\n    Tcl_Obj\t*heightObj;\n} FramePart;\n\ntypedef struct {\n    WidgetCore\tcore;\n    FramePart\tframe;\n} Frame;\n\nstatic const Tk_OptionSpec FrameOptionSpecs[] = {\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\", NULL,\n\toffsetof(Frame,frame.borderWidthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Pad\", NULL,\n\toffsetof(Frame,frame.paddingObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\", NULL,\n\toffsetof(Frame,frame.reliefObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\", \"0\",\n\toffsetof(Frame,frame.widthObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\", \"0\",\n\toffsetof(Frame,frame.heightObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\nstatic const Ttk_Ensemble FrameCommands[] = {\n    { \"cget\",\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*\n * FrameMargins --\n *\tCompute internal margins for a frame widget.\n *\tThis includes the -borderWidth, plus any additional -padding.\n */\nstatic Ttk_Padding FrameMargins(Frame *framePtr)\n{\n    Ttk_Padding margins = Ttk_UniformPadding(0);\n\n    /* Check -padding:\n     */\n    if (framePtr->frame.paddingObj) {\n\tTtk_GetPaddingFromObj(NULL,\n\t    framePtr->core.tkwin, framePtr->frame.paddingObj, &margins);\n    }\n\n    /* Add padding for border:\n     */\n    if (framePtr->frame.borderWidthObj) {\n\tint border = 0;\n\tTk_GetPixelsFromObj(NULL,\n\t    framePtr->core.tkwin, framePtr->frame.borderWidthObj, &border);\n\tmargins = Ttk_AddPadding(margins, Ttk_UniformPadding((short)border));\n    }\n\n    return margins;\n}\n\n/* FrameSize procedure --\n *\tThe frame doesn't request a size of its own by default,\n *\tbut it does have an internal border.  See also <<NOTE-SIZE>>\n */\nstatic int FrameSize(\n    void *recordPtr,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *)) /* heightPtr */\n{\n    Frame *framePtr = (Frame *)recordPtr;\n    Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr));\n    return 0;\n}\n\n/*\n * FrameConfigure -- configure hook.\n *\t<<NOTE-SIZE>> Usually the size of a frame is controlled by\n *\ta geometry manager (pack, grid); the -width and -height\n *\toptions are only effective if geometry propagation is turned\n *\toff or if the [place] GM is used for child widgets.\n *\n *\tTo avoid geometry blinking, we issue a geometry request\n *\tin the Configure hook instead of the Size hook, and only\n *\tif -width and/or -height is nonzero and one of them\n *\tor the other size-related options (-borderwidth, -padding)\n *\thas been changed.\n */\n\nstatic int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Frame *framePtr = (Frame *)recordPtr;\n    int width, height;\n\n    /*\n     * Make sure -padding resource, if present, is correct:\n     */\n    if (framePtr->frame.paddingObj) {\n\tTtk_Padding unused;\n\tif (Ttk_GetPaddingFromObj(interp,\n\t\t\tframePtr->core.tkwin,\n\t\t\tframePtr->frame.paddingObj,\n\t\t\t&unused) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /* See <<NOTE-SIZE>>\n     */\n    if (  TCL_OK != Tk_GetPixelsFromObj(\n\t    interp,framePtr->core.tkwin,framePtr->frame.widthObj,&width)\n       || TCL_OK != Tk_GetPixelsFromObj(\n\t    interp,framePtr->core.tkwin,framePtr->frame.heightObj,&height)\n       )\n    {\n\treturn TCL_ERROR;\n    }\n\n    if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) {\n\tTk_GeometryRequest(framePtr->core.tkwin, width, height);\n    }\n\n    return TtkCoreConfigure(interp, recordPtr, mask);\n}\n\nstatic const WidgetSpec FrameWidgetSpec = {\n    \"TFrame\",\t\t\t/* className */\n    sizeof(Frame),\t\t/* recordSize */\n    FrameOptionSpecs,\t\t/* optionSpecs */\n    FrameCommands,\t\t/* subcommands */\n    TtkNullInitialize,\t\t/* initializeProc */\n    TtkNullCleanup,\t\t/* cleanupProc */\n    FrameConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    FrameSize,\t\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(FrameLayout)\n    TTK_NODE(\"Frame.border\", TTK_FILL_BOTH)\nTTK_END_LAYOUT\n\n/* ======================================================================\n * +++ Labelframe widget:\n */\n\n#define DEFAULT_LABELINSET\t8\n#define DEFAULT_BORDERWIDTH\t2\n\nint TtkGetLabelAnchorFromObj(\n    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_PositionSpec *anchorPtr)\n{\n    const char *string = Tcl_GetString(objPtr);\n    char c = *string++;\n    Ttk_PositionSpec flags = 0;\n\n    /* First character determines side:\n     */\n    switch (c) {\n\tcase 'w' : flags = TTK_PACK_LEFT;\tbreak;\n\tcase 'e' : flags = TTK_PACK_RIGHT;\tbreak;\n\tcase 'n' : flags = TTK_PACK_TOP;\tbreak;\n\tcase 's' : flags = TTK_PACK_BOTTOM;\tbreak;\n\tdefault  : goto error;\n    }\n\n    /* Remaining characters are as per -sticky:\n     */\n    while ((c = *string++) != '\\0') {\n\tswitch (c) {\n\t    case 'w' : flags |= TTK_STICK_W; break;\n\t    case 'e' : flags |= TTK_STICK_E; break;\n\t    case 'n' : flags |= TTK_STICK_N; break;\n\t    case 's' : flags |= TTK_STICK_S; break;\n\t    default  : goto error;\n\t}\n    }\n\n    *anchorPtr = flags;\n    return TCL_OK;\n\nerror:\n    if (interp) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Bad label anchor specification %s\", Tcl_GetString(objPtr)));\n\tTcl_SetErrorCode(interp, \"TTK\", \"LABEL\", \"ANCHOR\", (char *)NULL);\n    }\n    return TCL_ERROR;\n}\n\n/* LabelAnchorSide --\n *\tReturns the side corresponding to a LabelAnchor value.\n */\nstatic Ttk_Side LabelAnchorSide(Ttk_PositionSpec flags)\n{\n    if (flags & TTK_PACK_LEFT)\t\treturn TTK_SIDE_LEFT;\n    else if (flags & TTK_PACK_RIGHT)\treturn TTK_SIDE_RIGHT;\n    else if (flags & TTK_PACK_TOP)\treturn TTK_SIDE_TOP;\n    else if (flags & TTK_PACK_BOTTOM)\treturn TTK_SIDE_BOTTOM;\n    /*NOTREACHED*/\n    return TTK_SIDE_TOP;\n}\n\n/*\n * Labelframe widget record:\n */\ntypedef struct {\n    Tcl_Obj\t*labelAnchorObj;\n    Tcl_Obj\t*textObj;\n    Tcl_Obj\t*underlineObj;\n    Tk_Window\tlabelWidget;\n\n    Ttk_Manager\t*mgr;\n    Ttk_Layout\tlabelLayout;\t/* Sublayout for label */\n    Ttk_Box\tlabelParcel;\t/* Set in layoutProc */\n} LabelframePart;\n\ntypedef struct {\n    WidgetCore\tcore;\n    FramePart\tframe;\n    LabelframePart\tlabel;\n} Labelframe;\n\n#define LABELWIDGET_CHANGED 0x100\n\nstatic const Tk_OptionSpec LabelframeOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-labelanchor\", \"labelAnchor\", \"LabelAnchor\",\n\t\"nw\", offsetof(Labelframe, label.labelAnchorObj),TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\", \"\",\n\toffsetof(Labelframe,label.textObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTTK_OPTION_UNDERLINE_DEF(Labelframe, label.underlineObj), 0},\n    {TK_OPTION_WINDOW, \"-labelwidget\", \"labelWidget\", \"LabelWidget\", NULL,\n\tTCL_INDEX_NONE, offsetof(Labelframe,label.labelWidget),\n\tTK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED },\n\n    WIDGET_INHERIT_OPTIONS(FrameOptionSpecs)\n};\n\n/*\n * Labelframe style parameters:\n */\ntypedef struct {\n    int\t\tborderWidth;\t/* border width */\n    Ttk_Padding\tpadding;\t/* internal padding */\n    Ttk_PositionSpec\tlabelAnchor;\t/* corner/side to place label */\n    Ttk_Padding\t\tlabelMargins;\t/* extra space around label */\n    int\t\tlabelOutside;\t/* true=>place label outside border */\n} LabelframeStyle;\n\nstatic void LabelframeStyleOptions(Labelframe *lf, LabelframeStyle *style)\n{\n    Ttk_Layout layout = lf->core.layout;\n    Tcl_Obj *objPtr;\n\n    style->borderWidth = DEFAULT_BORDERWIDTH;\n    style->padding = Ttk_UniformPadding(0);\n    style->labelAnchor = TTK_PACK_TOP | TTK_STICK_W;\n    style->labelOutside = 0;\n\n    if ((objPtr = Ttk_QueryOption(layout, \"-borderwidth\", 0)) != NULL) {\n\tTk_GetPixelsFromObj(NULL, lf->core.tkwin, objPtr, &style->borderWidth);\n    }\n    if ((objPtr = Ttk_QueryOption(layout, \"-padding\", 0)) != NULL) {\n\tTtk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr, &style->padding);\n    }\n    if ((objPtr = Ttk_QueryOption(layout,\"-labelanchor\", 0)) != NULL) {\n\tTtkGetLabelAnchorFromObj(NULL, objPtr, &style->labelAnchor);\n    }\n    if ((objPtr = Ttk_QueryOption(layout,\"-labelmargins\", 0)) != NULL) {\n\tTtk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr,\n\t    &style->labelMargins);\n    } else {\n\tif (style->labelAnchor & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {\n\t    style->labelMargins =\n\t\tTtk_MakePadding(DEFAULT_LABELINSET, 0, DEFAULT_LABELINSET, 0);\n\t} else {\n\t    style->labelMargins =\n\t\tTtk_MakePadding(0, DEFAULT_LABELINSET, 0, DEFAULT_LABELINSET);\n\t}\n    }\n    if ((objPtr = Ttk_QueryOption(layout,\"-labeloutside\", 0)) != NULL) {\n\tTcl_GetBooleanFromObj(NULL, objPtr, &style->labelOutside);\n    }\n\n    return;\n}\n\n/* LabelframeLabelSize --\n *\tExtract the requested width and height of the labelframe's label:\n *\ttaken from the label widget if specified, otherwise the text label.\n */\nstatic void\nLabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr)\n{\n    Tk_Window labelWidget = lframePtr->label.labelWidget;\n    Ttk_Layout labelLayout = lframePtr->label.labelLayout;\n\n    if (labelWidget) {\n\t*widthPtr = Tk_ReqWidth(labelWidget);\n\t*heightPtr = Tk_ReqHeight(labelWidget);\n    } else if (labelLayout) {\n\tTtk_LayoutSize(labelLayout, 0, widthPtr, heightPtr);\n    } else {\n\t*widthPtr = *heightPtr = 0;\n    }\n}\n\n/*\n * LabelframeSize --\n *\tLike the frame, this doesn't request a size of its own\n *\tbut it does have internal padding and a minimum size.\n */\nstatic int LabelframeSize(\n    void *recordPtr,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *)) /* heightPtr */\n{\n    Labelframe *lframePtr = (Labelframe *)recordPtr;\n    WidgetCore *corePtr = &lframePtr->core;\n    Ttk_Padding margins;\n    LabelframeStyle style;\n    int labelWidth, labelHeight;\n\n    LabelframeStyleOptions(lframePtr, &style);\n\n    /* Compute base margins (See also: FrameMargins)\n     */\n    margins = Ttk_AddPadding(\n\t\tstyle.padding, Ttk_UniformPadding((short)style.borderWidth));\n\n    /* Adjust margins based on label size and position:\n     */\n    LabelframeLabelSize(lframePtr, &labelWidth, &labelHeight);\n    labelWidth += Ttk_PaddingWidth(style.labelMargins);\n    labelHeight += Ttk_PaddingHeight(style.labelMargins);\n\n    switch (LabelAnchorSide(style.labelAnchor)) {\n\tcase TTK_SIDE_LEFT:\tmargins.left   += (short)labelWidth;\tbreak;\n\tcase TTK_SIDE_RIGHT:\tmargins.right  += (short)labelWidth;\tbreak;\n\tcase TTK_SIDE_TOP:\tmargins.top    += (short)labelHeight;\tbreak;\n\tcase TTK_SIDE_BOTTOM:\tmargins.bottom += (short)labelHeight;\tbreak;\n    }\n\n    Ttk_SetMargins(corePtr->tkwin,margins);\n\n    /* Request minimum size based on border width and label size:\n     */\n    Tk_SetMinimumRequestSize(corePtr->tkwin,\n\t    labelWidth + 2*style.borderWidth,\n\t    labelHeight + 2*style.borderWidth);\n\n    return 0;\n}\n\n/*\n * LabelframeGetLayout --\n *\tGetlayout widget hook.\n */\n\nstatic Ttk_Layout LabelframeGetLayout(\n    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Labelframe *lf = (Labelframe *)recordPtr;\n    Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr);\n    Ttk_Layout labelLayout;\n\n    if (!frameLayout) {\n\treturn NULL;\n    }\n\n    labelLayout = Ttk_CreateSublayout(\n\tinterp, theme, frameLayout, \".Label\", lf->core.optionTable);\n\n    if (labelLayout) {\n\tif (lf->label.labelLayout) {\n\t    Ttk_FreeLayout(lf->label.labelLayout);\n\t}\n\tTtk_RebindSublayout(labelLayout, recordPtr);\n\tlf->label.labelLayout = labelLayout;\n    }\n\n    return frameLayout;\n}\n\n/*\n * LabelframeDoLayout --\n *\tLabelframe layout hook.\n *\n * Side effects: Computes labelParcel.\n */\n\nstatic void LabelframeDoLayout(void *recordPtr)\n{\n    Labelframe *lframePtr = (Labelframe *)recordPtr;\n    WidgetCore *corePtr = &lframePtr->core;\n    int lw, lh;\t\t\t/* Label width and height */\n    LabelframeStyle style;\n    Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin);\n    Ttk_Box labelParcel;\n\n    /*\n     * Compute label parcel:\n     */\n    LabelframeStyleOptions(lframePtr, &style);\n    LabelframeLabelSize(lframePtr, &lw, &lh);\n    lw += Ttk_PaddingWidth(style.labelMargins);\n    lh += Ttk_PaddingHeight(style.labelMargins);\n\n    labelParcel = Ttk_PadBox(\n\tTtk_PositionBox(&borderParcel, lw, lh, style.labelAnchor),\n\tstyle.labelMargins);\n\n    if (!style.labelOutside) {\n\t/* Move border edge so it's over label:\n\t*/\n\tswitch (LabelAnchorSide(style.labelAnchor)) {\n\t    case TTK_SIDE_LEFT:\tborderParcel.x -= lw / 2;\n\t    /* FALLTHRU */\n\t    case TTK_SIDE_RIGHT:\tborderParcel.width += lw/2;\tbreak;\n\t    case TTK_SIDE_TOP:\tborderParcel.y -= lh / 2;\n\t    /* FALLTHRU */\n\t    case TTK_SIDE_BOTTOM:\tborderParcel.height += lh / 2;\tbreak;\n\t}\n    }\n\n    /*\n     * Place border and label:\n     */\n    Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel);\n    if (lframePtr->label.labelLayout) {\n\tTtk_PlaceLayout(\n\t    lframePtr->label.labelLayout, corePtr->state, labelParcel);\n    }\n    /* labelWidget placed in LabelframePlaceContent GM hook */\n    lframePtr->label.labelParcel = labelParcel;\n}\n\nstatic void LabelframeDisplay(void *recordPtr, Drawable d)\n{\n    Labelframe *lframePtr = (Labelframe *)recordPtr;\n    Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d);\n    if (lframePtr->label.labelLayout) {\n\tTtk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d);\n    }\n}\n\n/* +++ Labelframe geometry manager hooks.\n */\n\n/* LabelframePlaceContent --\n *\tSets the position and size of the labelwidget.\n */\nstatic void LabelframePlaceContent(void *recordPtr)\n{\n    Labelframe *lframe = (Labelframe *)recordPtr;\n\n    if (Ttk_NumberContent(lframe->label.mgr) == 1) {\n\tTtk_Box b;\n\tLabelframeDoLayout(recordPtr);\n\tb = lframe->label.labelParcel;\n\t/* ASSERT: content #0 is lframe->label.labelWidget */\n\tTtk_PlaceContent(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);\n    }\n}\n\nstatic int LabelRequest(\n    TCL_UNUSED(void *), /* managerData */\n    TCL_UNUSED(Tcl_Size), /* index */\n    TCL_UNUSED(int), /* width */\n    TCL_UNUSED(int)) /* height */\n{\n    return 1;\n}\n\n/* LabelRemoved --\n *\tUnset the -labelwidget option.\n *\n * <<NOTE-LABELREMOVED>>:\n *\tThis routine is also called when the widget voluntarily forgets\n *\tthe window in LabelframeConfigure.\n */\nstatic void LabelRemoved(\n    void *managerData,\n    TCL_UNUSED(Tcl_Size)) /* index */\n{\n    Labelframe *lframe = (Labelframe *)managerData;\n\n    lframe->label.labelWidget = 0;\n}\n\nstatic const Ttk_ManagerSpec LabelframeManagerSpec = {\n    { \"labelframe\", Ttk_GeometryRequestProc, Ttk_LostContentProc },\n    LabelframeSize,\n    LabelframePlaceContent,\n    LabelRequest,\n    LabelRemoved\n};\n\n/* LabelframeInitialize --\n *\tInitialization hook.\n */\nstatic void LabelframeInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Labelframe *lframe = (Labelframe *)recordPtr;\n\n    lframe->label.mgr = Ttk_CreateManager(\n\t&LabelframeManagerSpec, lframe, lframe->core.tkwin);\n    lframe->label.labelWidget = 0;\n    lframe->label.labelLayout = 0;\n    lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);\n}\n\n/* LabelframeCleanup --\n *\tCleanup hook.\n */\nstatic void LabelframeCleanup(void *recordPtr)\n{\n    Labelframe *lframe = (Labelframe *)recordPtr;\n    Ttk_DeleteManager(lframe->label.mgr);\n    if (lframe->label.labelLayout) {\n\tTtk_FreeLayout(lframe->label.labelLayout);\n    }\n}\n\n/* RaiseLabelWidget --\n *\tRaise the -labelwidget to ensure that the labelframe doesn't\n *\tobscure it (if it's not a direct child), or bring it to\n *\tthe top of the stacking order (if it is).\n */\nstatic void RaiseLabelWidget(Labelframe *lframe)\n{\n    Tk_Window parent = Tk_Parent(lframe->label.labelWidget);\n    Tk_Window sibling = NULL;\n    Tk_Window w = lframe->core.tkwin;\n\n    while (w && w != parent) {\n\tsibling = w;\n\tw = Tk_Parent(w);\n    }\n\n    Tk_RestackWindow(lframe->label.labelWidget, Above, sibling);\n}\n\n/* LabelframeConfigure --\n *\tConfiguration hook.\n */\nstatic int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask)\n{\n    Labelframe *lframePtr = (Labelframe *)recordPtr;\n    Tk_Window labelWidget = lframePtr->label.labelWidget;\n    Ttk_PositionSpec unused;\n\n    /* Validate options:\n     */\n    if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) {\n\tif (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (TtkGetLabelAnchorFromObj(\n\tinterp, lframePtr->label.labelAnchorObj, &unused) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    /* Base class configuration:\n     */\n    if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /* Update -labelwidget changes, if any:\n     */\n    if (mask & LABELWIDGET_CHANGED) {\n\tif (Ttk_NumberContent(lframePtr->label.mgr) == 1) {\n\t    Ttk_ForgetContent(lframePtr->label.mgr, 0);\n\t    /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>)\n\t     */\n\t    lframePtr->label.labelWidget = labelWidget;\n\t}\n\n\tif (labelWidget) {\n\t\tTtk_InsertContent(lframePtr->label.mgr, 0, labelWidget, NULL);\n\t    RaiseLabelWidget(lframePtr);\n\t}\n    }\n\n    if (mask & GEOMETRY_CHANGED) {\n\tTtk_ManagerSizeChanged(lframePtr->label.mgr);\n\tTtk_ManagerLayoutChanged(lframePtr->label.mgr);\n    }\n\n    return TCL_OK;\n}\n\nstatic const WidgetSpec LabelframeWidgetSpec = {\n    \"TLabelframe\",\t\t/* className */\n    sizeof(Labelframe),\t\t/* recordSize */\n    LabelframeOptionSpecs,\t/* optionSpecs */\n    FrameCommands,\t\t/* subcommands */\n    LabelframeInitialize,\t/* initializeProc */\n    LabelframeCleanup,\t\t/* cleanupProc */\n    LabelframeConfigure,\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    LabelframeGetLayout,\t/* getLayoutProc */\n    LabelframeSize,\t\t/* sizeProc */\n    LabelframeDoLayout,\t\t/* layoutProc */\n    LabelframeDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(LabelframeLayout)\n    TTK_NODE(\"Labelframe.border\", TTK_FILL_BOTH)\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(LabelSublayout)\n    TTK_GROUP(\"Label.fill\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Label.text\", TTK_FILL_BOTH))\nTTK_END_LAYOUT\n\n/* ======================================================================\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkFrame_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme =  Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(theme, \"TFrame\", FrameLayout);\n    Ttk_RegisterLayout(theme, \"TLabelframe\", LabelframeLayout);\n    Ttk_RegisterLayout(theme, \"Label\", LabelSublayout);\n\n    RegisterWidget(interp, \"ttk::frame\", &FrameWidgetSpec);\n    RegisterWidget(interp, \"ttk::labelframe\", &LabelframeWidgetSpec);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkImage.c",
    "content": "/*\n *\tImage specifications and image element factory.\n *\n * Copyright © 2004 Pat Thoyts <patthoyts@users.sf.net>\n * Copyright © 2004 Joe English\n *\n * An imageSpec is a multi-element list; the first element\n * is the name of the default image to use, the remainder of the\n * list is a sequence of statespec/imagename options as per\n * [style map].\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n\n/*------------------------------------------------------------------------\n * +++ ImageSpec management.\n */\n\nstruct TtkImageSpec {\n    Tk_Image\t\tbaseImage;\t/* Base image to use */\n    Tcl_Size\t\tmapCount;\t/* #state-specific overrides */\n    Ttk_StateSpec\t*states;\t/* array[mapCount] of states ... */\n    Tk_Image\t\t*images;\t/* ... per-state images to use */\n    Tk_ImageChangedProc *imageChanged;\n    void\t\t*imageChangedClientData;\n};\n\n/* NullImageChanged --\n *\tDo-nothing Tk_ImageChangedProc.\n */\nstatic void NullImageChanged(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    /* No-op */\n}\n\n/* ImageSpecImageChanged --\n *     Image changes should trigger a repaint.\n */\nstatic void ImageSpecImageChanged(void *clientData,\n    int x, int y, int width, int height, int imageWidth, int imageHeight)\n{\n    Ttk_ImageSpec *imageSpec = (Ttk_ImageSpec *)clientData;\n    if (imageSpec->imageChanged != NULL) {\n\timageSpec->imageChanged(imageSpec->imageChangedClientData,\n\t\tx, y, width, height,\n\t\timageWidth, imageHeight);\n    }\n}\n\n/* TtkGetImageSpec --\n *\tConstructs a Ttk_ImageSpec * from a Tcl_Obj *.\n *\tResult must be released using TtkFreeImageSpec.\n *\n */\nTtk_ImageSpec *\nTtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)\n{\n    return TtkGetImageSpecEx(interp, tkwin, objPtr, NULL, NULL);\n}\n\n/* TtkGetImageSpecEx --\n *\tConstructs a Ttk_ImageSpec * from a Tcl_Obj *.\n *\tResult must be released using TtkFreeImageSpec.\n *\timageChangedProc will be called when not NULL when\n *\tthe image changes to allow widgets to repaint.\n */\nTtk_ImageSpec *\nTtkGetImageSpecEx(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr,\n    Tk_ImageChangedProc *imageChangedProc, void *imageChangedClientData)\n{\n    Ttk_ImageSpec *imageSpec = 0;\n    Tcl_Size i = 0, n = 0;\n    Tcl_Size objc;\n    Tcl_Obj **objv;\n\n    imageSpec = (Ttk_ImageSpec *)Tcl_Alloc(sizeof(*imageSpec));\n    imageSpec->baseImage = 0;\n    imageSpec->mapCount = 0;\n    imageSpec->states = 0;\n    imageSpec->images = 0;\n    imageSpec->imageChanged = imageChangedProc;\n    imageSpec->imageChangedClientData = imageChangedClientData;\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\tgoto error;\n    }\n\n    if ((objc % 2) != 1) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"image specification must contain an odd number of elements\",\n\t\t-1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"IMAGE\", \"SPEC\", (char *)NULL);\n\t}\n\tgoto error;\n    }\n\n    n = (objc - 1) / 2;\n    imageSpec->states = (Ttk_StateSpec *)Tcl_Alloc(n * sizeof(Ttk_StateSpec));\n    imageSpec->images = (Tk_Image *)Tcl_Alloc(n * sizeof(Tk_Image));\n\n    /* Get base image:\n    */\n    imageSpec->baseImage = Tk_GetImage(\n\t    interp, tkwin, Tcl_GetString(objv[0]), ImageSpecImageChanged, imageSpec);\n    if (!imageSpec->baseImage) {\n\tgoto error;\n    }\n\n    /* Extract state and image specifications:\n     */\n    for (i = 0; i < n; ++i) {\n\tTcl_Obj *stateSpec = objv[2*i + 1];\n\tconst char *imageName = Tcl_GetString(objv[2*i + 2]);\n\tTtk_StateSpec state;\n\n\tif (Ttk_GetStateSpecFromObj(interp, stateSpec, &state) != TCL_OK) {\n\t    goto error;\n\t}\n\timageSpec->states[i] = state;\n\n\timageSpec->images[i] = Tk_GetImage(\n\t    interp, tkwin, imageName, NullImageChanged, NULL);\n\tif (imageSpec->images[i] == NULL) {\n\t    goto error;\n\t}\n\timageSpec->mapCount = i+1;\n    }\n\n    return imageSpec;\n\nerror:\n    TtkFreeImageSpec(imageSpec);\n    return NULL;\n}\n\n/* TtkFreeImageSpec --\n *\tDispose of an image specification.\n */\nvoid TtkFreeImageSpec(Ttk_ImageSpec *imageSpec)\n{\n    int i;\n\n    for (i=0; i < imageSpec->mapCount; ++i) {\n\tTk_FreeImage(imageSpec->images[i]);\n    }\n\n    if (imageSpec->baseImage) { Tk_FreeImage(imageSpec->baseImage); }\n    if (imageSpec->states) { Tcl_Free(imageSpec->states); }\n    if (imageSpec->images) { Tcl_Free(imageSpec->images); }\n\n    Tcl_Free(imageSpec);\n}\n\n/* TtkSelectImage --\n *\tReturn a state-specific image from an ImageSpec\n */\nTk_Image TtkSelectImage(\n    Ttk_ImageSpec *imageSpec,\n    TCL_UNUSED(Tk_Window),\n    Ttk_State state)\n{\n    int i;\n    for (i = 0; i < imageSpec->mapCount; ++i) {\n\tif (Ttk_StateMatches(state, imageSpec->states+i)) {\n\t    return imageSpec->images[i];\n\t}\n    }\n    return imageSpec->baseImage;\n}\n\n/*------------------------------------------------------------------------\n * +++ Drawing utilities.\n */\n\n/* LPadding, CPadding, RPadding --\n *\tSplit a box+padding pair into left, center, and right boxes.\n */\nstatic Ttk_Box LPadding(Ttk_Box b, Ttk_Padding p)\n    { return Ttk_MakeBox(b.x, b.y, p.left, b.height); }\n\nstatic Ttk_Box CPadding(Ttk_Box b, Ttk_Padding p)\n    { return Ttk_MakeBox(b.x+p.left, b.y, b.width-p.left-p.right, b.height); }\n\nstatic Ttk_Box RPadding(Ttk_Box b, Ttk_Padding p)\n    { return  Ttk_MakeBox(b.x+b.width-p.right, b.y, p.right, b.height); }\n\n/* TPadding, MPadding, BPadding --\n *\tSplit a box+padding pair into top, middle, and bottom parts.\n */\nstatic Ttk_Box TPadding(Ttk_Box b, Ttk_Padding p)\n    { return Ttk_MakeBox(b.x, b.y, b.width, p.top); }\n\nstatic Ttk_Box MPadding(Ttk_Box b, Ttk_Padding p)\n    { return Ttk_MakeBox(b.x, b.y+p.top, b.width, b.height-p.top-p.bottom); }\n\nstatic Ttk_Box BPadding(Ttk_Box b, Ttk_Padding p)\n    { return Ttk_MakeBox(b.x, b.y+b.height-p.bottom, b.width, p.bottom); }\n\n/* Ttk_Fill --\n *\tFill the destination area of the drawable by replicating\n *\tthe source area of the image.\n */\nstatic void Ttk_Fill(\n    TCL_UNUSED(Tk_Window),\n    Drawable d,\n    Tk_Image image,\n    Ttk_Box src,\n    Ttk_Box dst)\n{\n    int dr = dst.x + dst.width;\n    int db = dst.y + dst.height;\n    int x,y;\n\n    if (!(src.width && src.height && dst.width && dst.height)) {\n\treturn;\n    }\n\n    for (x = dst.x; x < dr; x += src.width) {\n\tint cw = MIN(src.width, dr - x);\n\tfor (y = dst.y; y <= db; y += src.height) {\n\t    int ch = MIN(src.height, db - y);\n\t    Tk_RedrawImage(image, src.x, src.y, cw, ch, d, x, y);\n\t}\n    }\n}\n\n/* Ttk_Stripe --\n *\tFill a horizontal stripe of the destination drawable.\n */\nstatic void Ttk_Stripe(\n    Tk_Window tkwin, Drawable d, Tk_Image image,\n    Ttk_Box src, Ttk_Box dst, Ttk_Padding p)\n{\n    Ttk_Fill(tkwin, d, image, LPadding(src,p), LPadding(dst,p));\n    Ttk_Fill(tkwin, d, image, CPadding(src,p), CPadding(dst,p));\n    Ttk_Fill(tkwin, d, image, RPadding(src,p), RPadding(dst,p));\n}\n\n/* Ttk_Tile --\n *\tFill successive horizontal stripes of the destination drawable.\n */\nstatic void Ttk_Tile(\n    Tk_Window tkwin, Drawable d, Tk_Image image,\n    Ttk_Box src, Ttk_Box dst, Ttk_Padding p)\n{\n    Ttk_Stripe(tkwin, d, image, TPadding(src,p), TPadding(dst,p), p);\n    Ttk_Stripe(tkwin, d, image, MPadding(src,p), MPadding(dst,p), p);\n    Ttk_Stripe(tkwin, d, image, BPadding(src,p), BPadding(dst,p), p);\n}\n\n/*------------------------------------------------------------------------\n * +++ Image element definition.\n */\n\ntypedef struct {\t\t/* ClientData for image elements */\n    Ttk_ImageSpec *imageSpec;\t/* Image(s) to use */\n    int minWidth;\t\t/* Minimum width; overrides image width */\n    int minHeight;\t\t/* Minimum height; overrides image height */\n    Ttk_Sticky sticky;\t\t/* -stickiness specification */\n    Ttk_Padding border;\t\t/* Fixed border region */\n    Ttk_Padding padding;\t/* Internal padding */\n\n#ifdef TILE_07_COMPAT\n    Ttk_ResourceCache cache;\t/* Resource cache for images */\n    Ttk_StateMap imageMap;\t/* State-based lookup table for images */\n#endif\n} ImageData;\n\nstatic void FreeImageData(void *clientData)\n{\n    ImageData *imageData = (ImageData *)clientData;\n    if (imageData->imageSpec)\t{ TtkFreeImageSpec(imageData->imageSpec); }\n#ifdef TILE_07_COMPAT\n    if (imageData->imageMap)\t{ Tcl_DecrRefCount(imageData->imageMap); }\n#endif\n    Tcl_Free(clientData);\n}\n\nstatic void ImageElementSize(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    int *widthPtr,\n    int *heightPtr,\n    Ttk_Padding *paddingPtr)\n{\n    ImageData *imageData = (ImageData *)clientData;\n    Tk_Image image = imageData->imageSpec->baseImage;\n\n    if (image) {\n\tTk_SizeOfImage(image, widthPtr, heightPtr);\n    }\n    if (imageData->minWidth >= 0) {\n\t*widthPtr = imageData->minWidth;\n    }\n    if (imageData->minHeight >= 0) {\n\t*heightPtr = imageData->minHeight;\n    }\n\n    *paddingPtr = imageData->padding;\n}\n\nstatic void ImageElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ImageData *imageData = (ImageData *)clientData;\n    Tk_Image image = 0;\n    int imgWidth, imgHeight;\n    Ttk_Box src, dst;\n\n#ifdef TILE_07_COMPAT\n    if (imageData->imageMap) {\n\tTcl_Obj *imageObj = Ttk_StateMapLookup(NULL,imageData->imageMap,state);\n\tif (imageObj) {\n\t    image = Ttk_UseImage(imageData->cache, tkwin, imageObj);\n\t}\n    }\n    if (!image) {\n\timage = TtkSelectImage(imageData->imageSpec, tkwin, state);\n    }\n#else\n    image = TtkSelectImage(imageData->imageSpec, tkwin, state);\n#endif\n\n    if (!image) {\n\treturn;\n    }\n\n    Tk_SizeOfImage(image, &imgWidth, &imgHeight);\n    src = Ttk_MakeBox(0, 0, imgWidth, imgHeight);\n    dst = Ttk_StickBox(b, imgWidth, imgHeight, imageData->sticky);\n\n    Ttk_Tile(tkwin, d, image, src, dst, imageData->border);\n}\n\nstatic const Ttk_ElementSpec ImageElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    ImageElementSize,\n    ImageElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Image element factory.\n */\nstatic int\nTtk_CreateImageElement(\n    Tcl_Interp *interp,\n    TCL_UNUSED(void *),\n    Ttk_Theme theme,\n    const char *elementName,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    static const char *const optionStrings[] =\n\t { \"-border\",\"-height\",\"-padding\",\"-sticky\",\"-width\",NULL };\n    enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH };\n\n    Ttk_ImageSpec *imageSpec = 0;\n    ImageData *imageData = 0;\n    int padding_specified = 0;\n    Tcl_Size i;\n\n    if (objc + 1 < 2) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Must supply a base image\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"IMAGE\", \"BASE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    imageSpec = TtkGetImageSpec(interp, Tk_MainWindow(interp), objv[0]);\n    if (!imageSpec) {\n\treturn TCL_ERROR;\n    }\n\n    imageData = (ImageData *)Tcl_Alloc(sizeof(*imageData));\n    imageData->imageSpec = imageSpec;\n    imageData->minWidth = imageData->minHeight = -1;\n    imageData->sticky = TTK_FILL_BOTH;\n    imageData->border = imageData->padding = Ttk_UniformPadding(0);\n#ifdef TILE_07_COMPAT\n    imageData->cache = Ttk_GetResourceCache(interp);\n    imageData->imageMap = 0;\n#endif\n\n    for (i = 1; i < objc; i += 2) {\n\tint option;\n\n\tif (i == objc - 1) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"Value for %s missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"IMAGE\", \"VALUE\", (char *)NULL);\n\t    goto error;\n\t}\n\n#ifdef TILE_07_COMPAT\n\tif (!strcmp(\"-map\", Tcl_GetString(objv[i]))) {\n\t    imageData->imageMap = objv[i+1];\n\t    Tcl_IncrRefCount(imageData->imageMap);\n\t    continue;\n\t}\n#endif\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,\n\t\tsizeof(char *), \"option\", 0, &option) != TCL_OK) {\n\t    goto error;\n\t}\n\n\tswitch (option) {\n\t    case O_BORDER:\n\t\tif (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->border)\n\t\t\t!= TCL_OK) {\n\t\t    goto error;\n\t\t}\n\t\tif (!padding_specified) {\n\t\t    imageData->padding = imageData->border;\n\t\t}\n\t\tbreak;\n\t    case O_PADDING:\n\t\tif (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->padding)\n\t\t\t!= TCL_OK) { goto error; }\n\t\tpadding_specified = 1;\n\t\tbreak;\n\t    case O_WIDTH:\n\t\tif (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minWidth)\n\t\t\t!= TCL_OK) { goto error; }\n\t\tbreak;\n\t    case O_HEIGHT:\n\t\tif (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minHeight)\n\t\t\t!= TCL_OK) { goto error; }\n\t\tbreak;\n\t    case O_STICKY:\n\t\tif (Ttk_GetStickyFromObj(interp, objv[i+1], &imageData->sticky)\n\t\t\t!= TCL_OK) { goto error; }\n\t}\n    }\n\n    if (!Ttk_RegisterElement(interp, theme, elementName, &ImageElementSpec,\n\t\timageData))\n    {\n\tgoto error;\n    }\n\n    Ttk_RegisterCleanup(interp, imageData, FreeImageData);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));\n    return TCL_OK;\n\nerror:\n    FreeImageData(imageData);\n    return TCL_ERROR;\n}\n\nMODULE_SCOPE void\nTtkImage_Init(Tcl_Interp *interp)\n{\n    Ttk_RegisterElementFactory(interp, \"image\", Ttk_CreateImageElement, NULL);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkInit.c",
    "content": "/*\n * Copyright © 2003 Joe English\n *\n * Ttk package: initialization routine and miscellaneous utilities.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*\n * Legal values for the button -default option.\n * See also: enum Ttk_ButtonDefaultState.\n */\nconst char *const ttkDefaultStrings[] = {\n    \"active\", \"disabled\", \"normal\", NULL\n};\n\nint Ttk_GetButtonDefaultStateFromObj(\n    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_ButtonDefaultState *statePtr)\n{\n    int state = (int)TTK_BUTTON_DEFAULT_DISABLED;\n    int result = Tcl_GetIndexFromObj(interp, objPtr, ttkDefaultStrings,\n\t    \"default state\", 0, &state);\n\n    *statePtr = (Ttk_ButtonDefaultState)state;\n    return result;\n}\n\n/*\n * Legal values for the -compound option.\n * See also: enum Ttk_Compound.\n */\nconst char *const ttkCompoundStrings[] = {\n    \"none\", \"text\", \"image\", \"center\",\n    \"top\", \"bottom\", \"left\", \"right\", NULL\n};\n\nint Ttk_GetCompoundFromObj(\n    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Compound *compoundPtr)\n{\n    int compound = (int)TTK_COMPOUND_NONE;\n    int result = Tcl_GetIndexFromObj(interp, objPtr, ttkCompoundStrings,\n\t    \"compound layout\", 0, &compound);\n\n    *compoundPtr = (Ttk_Compound)compound;\n    return result;\n}\n\n/*\n * Legal values for the -orient option.\n * See also: enum Ttk_Orient.\n */\nconst char *const ttkOrientStrings[] = {\n    \"horizontal\", \"vertical\", NULL\n};\n\nint Ttk_GetOrientFromObj(\n    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Orient *resultPtr)\n{\n    int orient = (int)TTK_ORIENT_HORIZONTAL;\n    int result = Tcl_GetIndexFromObj(interp, objPtr, ttkOrientStrings,\n\t    \"orientation\", 0, &orient);\n\n    *resultPtr = (Ttk_Orient)orient;\n    return result;\n}\n\n/*\n * Recognized values for the -state compatibility option.\n * Other options are accepted and interpreted as synonyms for \"normal\".\n */\nstatic const char *const ttkStateStrings[] = {\n    \"active\", \"disabled\", \"normal\", \"readonly\", NULL\n};\nenum {\n    TTK_COMPAT_STATE_ACTIVE,\n    TTK_COMPAT_STATE_DISABLED,\n    TTK_COMPAT_STATE_NORMAL,\n    TTK_COMPAT_STATE_READONLY\n};\n\n/* TtkCheckStateOption --\n *\tHandle -state compatibility option.\n *\n *\tNOTE: setting -state disabled / -state enabled affects the\n *\twidget state, but the internal widget state does *not* affect\n *\tthe value of the -state option.\n *\tThis option is present for compatibility only.\n */\nvoid TtkCheckStateOption(WidgetCore *corePtr, Tcl_Obj *objPtr)\n{\n    int stateOption = TTK_COMPAT_STATE_NORMAL;\n    unsigned all = TTK_STATE_DISABLED|TTK_STATE_READONLY|TTK_STATE_ACTIVE;\n#   define SETFLAGS(f) TtkWidgetChangeState(corePtr, f, all^f)\n\n    Tcl_GetIndexFromObj(NULL, objPtr, ttkStateStrings,\n\t    \"\", 0, &stateOption);\n    switch (stateOption) {\n\tcase TTK_COMPAT_STATE_NORMAL:\n\tdefault:\n\t    SETFLAGS(0);\n\t    break;\n\tcase TTK_COMPAT_STATE_READONLY:\n\t    SETFLAGS(TTK_STATE_READONLY);\n\t    break;\n\tcase TTK_COMPAT_STATE_DISABLED:\n\t    SETFLAGS(TTK_STATE_DISABLED);\n\t    break;\n\tcase TTK_COMPAT_STATE_ACTIVE:\n\t    SETFLAGS(TTK_STATE_ACTIVE);\n\t    break;\n    }\n#   undef SETFLAGS\n}\n\n/* TtkEnumerateOptions, TtkGetOptionValue --\n *\tCommon factors for data accessor commands.\n */\nint TtkEnumerateOptions(\n    Tcl_Interp *interp, void *recordPtr, const Tk_OptionSpec *specPtr,\n    Tk_OptionTable optionTable, Tk_Window tkwin)\n{\n    Tcl_Obj *result = Tcl_NewListObj(0,0);\n    while (specPtr->type != TK_OPTION_END)\n    {\n\tTcl_Obj *optionName = Tcl_NewStringObj(specPtr->optionName, -1);\n\tTcl_Obj *optionValue =\n\t    Tk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin);\n\tif (optionValue) {\n\t    Tcl_ListObjAppendElement(interp, result, optionName);\n\t    Tcl_ListObjAppendElement(interp, result, optionValue);\n\t}\n\t++specPtr;\n\n\tif (specPtr->type == TK_OPTION_END && specPtr->clientData != NULL) {\n\t    /* Chain to next option spec array: */\n\t    specPtr = (const Tk_OptionSpec *)specPtr->clientData;\n\t}\n    }\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\nint TtkGetOptionValue(\n    Tcl_Interp *interp, void *recordPtr, Tcl_Obj *optionName,\n    Tk_OptionTable optionTable, Tk_Window tkwin)\n{\n    Tcl_Obj *result =\n\tTk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin);\n    if (result) {\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    }\n    return TCL_ERROR;\n}\n\n\n/*------------------------------------------------------------------------\n * Core Option specifications:\n * type name dbName dbClass default objOffset intOffset flags clientData mask\n */\n\n/* public */\nconst Tk_OptionSpec ttkCoreOptionSpecs[] =\n{\n    {TK_OPTION_CURSOR, \"-cursor\", \"cursor\", \"Cursor\", NULL,\n\toffsetof(WidgetCore, cursorObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_STRING, \"-style\", \"style\", \"Style\", \"\",\n\toffsetof(WidgetCore,styleObj), TCL_INDEX_NONE, 0,0,STYLE_CHANGED},\n    {TK_OPTION_STRING, \"-class\", \"\", \"\", NULL,\n\toffsetof(WidgetCore,classObj), TCL_INDEX_NONE, 0,0,READONLY_OPTION},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\n/*------------------------------------------------------------------------\n * +++ Initialization: elements and element factories.\n */\n\nMODULE_SCOPE void TtkElements_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkLabel_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkImage_Init(Tcl_Interp *);\n\nstatic void RegisterElements(Tcl_Interp *interp)\n{\n    TtkElements_Init(interp);\n    TtkLabel_Init(interp);\n    TtkImage_Init(interp);\n}\n\n/*------------------------------------------------------------------------\n * +++ Initialization: Widget definitions.\n */\n\nMODULE_SCOPE void TtkButton_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkEntry_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkFrame_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkNotebook_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkPanedwindow_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkProgressbar_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkScale_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkScrollbar_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkSeparator_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkToggleswitch_Init(Tcl_Interp *);\nMODULE_SCOPE void TtkTreeview_Init(Tcl_Interp *);\n\n#ifdef TTK_SQUARE_WIDGET\nMODULE_SCOPE int TtkSquareWidget_Init(Tcl_Interp *);\n#endif\n\nstatic void RegisterWidgets(Tcl_Interp *interp)\n{\n    TtkButton_Init(interp);\n    TtkEntry_Init(interp);\n    TtkFrame_Init(interp);\n    TtkNotebook_Init(interp);\n    TtkPanedwindow_Init(interp);\n    TtkProgressbar_Init(interp);\n    TtkScale_Init(interp);\n    TtkScrollbar_Init(interp);\n    TtkSeparator_Init(interp);\n    TtkToggleswitch_Init(interp);\n    TtkTreeview_Init(interp);\n#ifdef TTK_SQUARE_WIDGET\n    TtkSquareWidget_Init(interp);\n#endif\n}\n\n/*------------------------------------------------------------------------\n * +++ Initialization: Built-in themes.\n */\n\nMODULE_SCOPE int TtkAltTheme_Init(Tcl_Interp *);\nMODULE_SCOPE int TtkClassicTheme_Init(Tcl_Interp *);\nMODULE_SCOPE int TtkClamTheme_Init(Tcl_Interp *);\n\nstatic void RegisterThemes(Tcl_Interp *interp)\n{\n\n    TtkAltTheme_Init(interp);\n    TtkClassicTheme_Init(interp);\n    TtkClamTheme_Init(interp);\n}\n\n/*\n * Ttk initialization.\n */\n\nextern const TtkStubs ttkStubs;\n\nMODULE_SCOPE int\nTtk_Init(Tcl_Interp *interp)\n{\n    /*\n     * This will be run for both safe and regular interp init.\n     * Use Tcl_IsSafe if necessary to not initialize unsafe bits.\n     */\n    Ttk_StylePkgInit(interp);\n\n    RegisterElements(interp);\n    RegisterWidgets(interp);\n    RegisterThemes(interp);\n\n    Ttk_PlatformInit(interp);\n\n#ifndef TK_NO_DEPRECATED\n    Tcl_PkgProvideEx(interp, \"Ttk\", TTK_PATCH_LEVEL, (void *)&ttkStubs);\n#endif\n    Tcl_PkgProvideEx(interp, \"ttk\", TTK_PATCH_LEVEL, (void *)&ttkStubs);\n\n    return TCL_OK;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkLabel.c",
    "content": "/*\n * text, image, and label elements.\n *\n * The label element combines text and image elements,\n * with layout determined by the \"-compound\" option.\n *\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\n/*----------------------------------------------------------------------\n * +++ Text element.\n *\n * This element displays a textual label in the foreground color.\n *\n * Optionally underlines the mnemonic character if the -underline resource\n * is present and >= 0.\n */\n\ntypedef struct {\n    /*\n     * Element options:\n     */\n    Tcl_Obj\t*textObj;\n    Tcl_Obj\t*fontObj;\n    Tcl_Obj\t*foregroundObj;\n    Tcl_Obj\t*underlineObj;\n    Tcl_Obj\t*widthObj;\n    Tcl_Obj\t*anchorObj;\n    Tcl_Obj\t*justifyObj;\n    Tcl_Obj\t*wrapLengthObj;\n    Tcl_Obj\t*embossedObj;\n\n    /*\n     * Computed resources:\n     */\n    Tk_Font\t\ttkfont;\n    Tk_TextLayout\ttextLayout;\n    int\t\twidth;\n    int\t\theight;\n    int\t\t\tembossed;\n\n} TextElement;\n\n/* Text element options table.\n * NB: Keep in sync with label element option table.\n */\nstatic const Ttk_ElementOptionSpec TextElementOptions[] = {\n    { \"-text\", TK_OPTION_STRING,\n\toffsetof(TextElement,textObj), \"\" },\n    { \"-font\", TK_OPTION_FONT,\n\toffsetof(TextElement,fontObj), DEFAULT_FONT },\n    { \"-foreground\", TK_OPTION_COLOR,\n\toffsetof(TextElement,foregroundObj), \"black\" },\n    { \"-underline\", TK_OPTION_INDEX,\n\toffsetof(TextElement,underlineObj), NULL},\n    { \"-width\", TK_OPTION_INT,\n\toffsetof(TextElement,widthObj), \"-1\"},\n    { \"-anchor\", TK_OPTION_ANCHOR,\n\toffsetof(TextElement,anchorObj), \"w\"},\n    { \"-justify\", TK_OPTION_JUSTIFY,\n\toffsetof(TextElement,justifyObj), \"left\" },\n    { \"-wraplength\", TK_OPTION_PIXELS,\n\toffsetof(TextElement,wrapLengthObj), \"0\" },\n    { \"-embossed\", TK_OPTION_INT,\n\toffsetof(TextElement,embossedObj), \"0\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic int TextSetup(TextElement *text, Tk_Window tkwin)\n{\n    const char *string = Tcl_GetString(text->textObj);\n    Tk_Justify justify = TK_JUSTIFY_LEFT;\n    int wrapLength = 0;\n\n    text->tkfont = Tk_GetFontFromObj(tkwin, text->fontObj);\n    Tk_GetJustifyFromObj(NULL, text->justifyObj, &justify);\n    Tk_GetPixelsFromObj(NULL, tkwin, text->wrapLengthObj, &wrapLength);\n    Tcl_GetBooleanFromObj(NULL, text->embossedObj, &text->embossed);\n\n    text->textLayout = Tk_ComputeTextLayout(\n\t    text->tkfont, string, -1/*numChars*/, wrapLength, justify,\n\t    0/*flags*/, &text->width, &text->height);\n\n    return 1;\n}\n\n/*\n * TextReqWidth -- compute the requested width of a text element.\n *\n * If -width is positive, use that as the width\n * If -width is negative, use that as the minimum width\n * If not specified or empty, use the natural size of the text\n */\n\nstatic int TextReqWidth(TextElement *text)\n{\n    int reqWidth;\n\n    if (   text->widthObj\n\t&& Tcl_GetIntFromObj(NULL, text->widthObj, &reqWidth) == TCL_OK)\n    {\n\tint avgWidth = Tk_TextWidth(text->tkfont, \"0\", 1);\n\tif (reqWidth <= 0) {\n\t    int specWidth = avgWidth * -reqWidth;\n\t    if (specWidth > text->width) {\n\t\treturn specWidth;\n\t    }\n\t} else {\n\t    return avgWidth * reqWidth;\n\t}\n    }\n    return text->width;\n}\n\nstatic void TextCleanup(TextElement *text)\n{\n    Tk_FreeTextLayout(text->textLayout);\n}\n\n/*\n * TextDraw --\n *\tDraw a text element.\n *\tCalled by TextElementDraw() and LabelElementDraw().\n */\nstatic void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b)\n{\n    XColor *color = Tk_GetColorFromObj(tkwin, text->foregroundObj);\n    Tcl_Size underline = INT_MIN;\n    XGCValues gcValues;\n    GC gc1, gc2;\n    Tk_Anchor anchor = TK_ANCHOR_CENTER;\n    Region clipRegion = NULL;\n\n    gcValues.font = Tk_FontId(text->tkfont);\n    gcValues.foreground = color->pixel;\n    gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);\n    gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));\n    gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);\n\n    /*\n     * Place text according to -anchor:\n     */\n    Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor);\n    b = Ttk_AnchorBox(b, text->width, text->height, anchor);\n\n    /*\n     * Clip text if it's too wide or too high:\n     */\n    if (b.width < text->width || b.height < text->height) {\n\tXRectangle rect;\n\n\tclipRegion = XCreateRegion();\n\trect.x = b.x;\n\trect.y = b.y;\n\trect.width = b.width + (text->embossed ? 1 : 0);\n\trect.height = b.height + (text->embossed ? 1 : 0);\n\tXUnionRectWithRegion(&rect, clipRegion, clipRegion);\n\tXSetRegion(Tk_Display(tkwin), gc1, clipRegion);\n\tXSetRegion(Tk_Display(tkwin), gc2, clipRegion);\n#ifdef HAVE_XFT\n\tTkUnixSetXftClipRegion(clipRegion);\n#endif\n    }\n\n    if (text->embossed) {\n\tTk_DrawTextLayout(Tk_Display(tkwin), d, gc2,\n\t    text->textLayout, b.x+1, b.y+1, 0/*firstChar*/, -1/*lastChar*/);\n    }\n    Tk_DrawTextLayout(Tk_Display(tkwin), d, gc1,\n\t    text->textLayout, b.x, b.y, 0/*firstChar*/, -1/*lastChar*/);\n\n    if (text->underlineObj != NULL) {\n\tTkGetIntForIndex(text->underlineObj, TCL_INDEX_NONE, 0, &underline);\n\tif (underline < INT_MIN) {\n\t    underline = INT_MIN;\n\t} else if (underline > INT_MAX) {\n\t    underline = INT_MAX;\n\t}\n\tif (underline != INT_MIN) {\n\t    if (text->embossed) {\n\t\tTk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2,\n\t\t\ttext->textLayout, b.x+1, b.y+1, underline);\n\t    }\n\t    Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1,\n\t\t    text->textLayout, b.x, b.y, underline);\n\t}\n    }\n\n    if (clipRegion != NULL) {\n#ifdef HAVE_XFT\n\tTkUnixSetXftClipRegion(NULL);\n#endif\n\tXSetClipMask(Tk_Display(tkwin), gc1, None);\n\tXSetClipMask(Tk_Display(tkwin), gc2, None);\n\tXDestroyRegion(clipRegion);\n    }\n    Tk_FreeGC(Tk_Display(tkwin), gc1);\n    Tk_FreeGC(Tk_Display(tkwin), gc2);\n}\n\nstatic void TextElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    TextElement *text = (TextElement *)elementRecord;\n\n    if (!TextSetup(text, tkwin)) {\n\treturn;\n    }\n\n    *heightPtr = text->height;\n    *widthPtr = TextReqWidth(text);\n\n    TextCleanup(text);\n\n    return;\n}\n\nstatic void TextElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    TextElement *text = (TextElement *)elementRecord;\n\n    if (TextSetup(text, tkwin)) {\n\tTextDraw(text, tkwin, d, b);\n\tTextCleanup(text);\n    }\n}\n\nstatic const Ttk_ElementSpec TextElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TextElement),\n    TextElementOptions,\n    TextElementSize,\n    TextElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ cText (collapsing text) element.\n *\n * This element is the same as the Text element, except its dimensions\n * are 0,0 when the text to display is \"\".\n */\n\nstatic int cTextSetup(TextElement *text, Tk_Window tkwin)\n{\n    if (TkObjIsEmpty(text->textObj)) {\n\treturn 0;\n    } else {\n\treturn TextSetup(text, tkwin);\n    }\n}\n\nstatic void cTextElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    TextElement *text = (TextElement *)elementRecord;\n\n    if (!cTextSetup(text, tkwin)) {\n\treturn;\n    }\n\n    *heightPtr = text->height;\n    *widthPtr = TextReqWidth(text);\n\n    TextCleanup(text);\n\n    return;\n}\n\nstatic const Ttk_ElementSpec cTextElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TextElement),\n    TextElementOptions,\n    cTextElementSize,\n    TextElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Image element.\n * Draws an image.\n */\n\ntypedef struct {\n    Tcl_Obj\t*imageObj;\n    Tcl_Obj\t*stippleObj;\t/* For TTK_STATE_DISABLED */\n    Tcl_Obj\t*backgroundObj;\t/* \" \" */\n\n    Ttk_ImageSpec *imageSpec;\n    Tk_Image\ttkimg;\n    int\twidth;\n    int\t\theight;\n} ImageElement;\n\n/* ===> NB: Keep in sync with label element option table.  <===\n */\nstatic const Ttk_ElementOptionSpec ImageElementOptions[] = {\n    { \"-image\", TK_OPTION_STRING,\n\toffsetof(ImageElement,imageObj), \"\" },\n    { \"-stipple\", TK_OPTION_STRING,\t/* Really: TK_OPTION_BITMAP */\n\toffsetof(ImageElement,stippleObj), \"gray50\" },\n    { \"-background\", TK_OPTION_COLOR,\n\toffsetof(ImageElement,backgroundObj), DEFAULT_BACKGROUND },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * ImageSetup() --\n *\tLook up the Tk_Image from the image element's imageObj resource.\n *\tCaller must release the image with ImageCleanup().\n *\n * Returns:\n *\t1 if successful, 0 if there was an error (unreported)\n *\tor the image resource was not specified.\n */\n\nstatic int ImageSetup(\n    ImageElement *image, Tk_Window tkwin, Ttk_State state)\n{\n\n    if (!image->imageObj) {\n\treturn 0;\n    }\n    image->imageSpec = TtkGetImageSpec(NULL, tkwin, image->imageObj);\n    if (!image->imageSpec) {\n\treturn 0;\n    }\n    image->tkimg = TtkSelectImage(image->imageSpec, tkwin, state);\n    if (!image->tkimg) {\n\tTtkFreeImageSpec(image->imageSpec);\n\treturn 0;\n    }\n    Tk_SizeOfImage(image->tkimg, &image->width, &image->height);\n\n    return 1;\n}\n\nstatic void ImageCleanup(ImageElement *image)\n{\n    TtkFreeImageSpec(image->imageSpec);\n}\n\n#ifndef MAC_OSX_TK\n/*\n * StippleOver --\n *\tDraw a stipple over the image area, to make it look \"grayed-out\"\n *\twhen TTK_STATE_DISABLED is set.\n */\nstatic void StippleOver(\n    ImageElement *image, Tk_Window tkwin, Drawable d, int x, int y)\n{\n    Pixmap stipple = Tk_AllocBitmapFromObj(NULL, tkwin, image->stippleObj);\n    XColor *color = Tk_GetColorFromObj(tkwin, image->backgroundObj);\n\n    if (stipple != None) {\n\tunsigned long mask = GCFillStyle | GCStipple | GCForeground;\n\tXGCValues gcvalues;\n\tGC gc;\n\tgcvalues.foreground = color->pixel;\n\tgcvalues.fill_style = FillStippled;\n\tgcvalues.stipple = stipple;\n\tgc = Tk_GetGC(tkwin, mask, &gcvalues);\n\tXFillRectangle(Tk_Display(tkwin),d,gc,x,y,image->width,image->height);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n\tTk_FreeBitmapFromObj(tkwin, image->stippleObj);\n    }\n}\n#endif\n\nstatic void ImageDraw(\n    ImageElement *image, Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state)\n{\n    int width = image->width, height = image->height;\n\n    /* Clip width and height to remain within window bounds:\n     */\n    if (b.x + width > Tk_Width(tkwin)) {\n\twidth = Tk_Width(tkwin) - b.x;\n    }\n    if (b.y + height > Tk_Height(tkwin)) {\n\theight = Tk_Height(tkwin) - b.y;\n    }\n\n    if (height <= 0 || width <= 0) {\n\t/* Completely clipped - bail out.\n\t */\n\treturn;\n    }\n\n    Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y);\n\n    /* If we're disabled there's no state-specific 'disabled' image,\n     * stipple the image.\n     * @@@ Possibly: Don't do disabled-stippling at all;\n     * @@@ it's ugly and out of fashion.\n     * Do not stipple at all under Aqua, just draw the image: it shows up\n     * as a white rectangle otherwise.\n     */\n\n\n    if (state & TTK_STATE_DISABLED) {\n\tif (TtkSelectImage(image->imageSpec, tkwin, 0ul) == image->tkimg) {\n#ifndef MAC_OSX_TK\n\t    StippleOver(image, tkwin, d, b.x,b.y);\n#endif\n\t}\n    }\n}\n\nstatic void ImageElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ImageElement *image = (ImageElement *)elementRecord;\n\n    if (ImageSetup(image, tkwin, 0)) {\n\t*widthPtr = image->width;\n\t*heightPtr = image->height;\n\tImageCleanup(image);\n    }\n}\n\nstatic void ImageElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ImageElement *image = (ImageElement *)elementRecord;\n\n    if (ImageSetup(image, tkwin, state)) {\n\tImageDraw(image, tkwin, d, b, state);\n\tImageCleanup(image);\n    }\n}\n\nstatic const Ttk_ElementSpec ImageElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ImageElement),\n    ImageElementOptions,\n    ImageElementSize,\n    ImageElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Label element.\n *\n * Displays an image and/or text, as determined by the -compound option.\n *\n * Differences from Tk 8.4 compound elements:\n *\n * This adds two new values for the -compound option, \"text\"\n * and \"image\".  (This is useful for configuring toolbars to\n * display icons, text and icons, or text only, as found in\n * many browsers.)\n *\n * \"-compound none\" is supported, but I'd like to get rid of it;\n * it makes the logic more complex, and the only benefit is\n * backwards compatibility with Tk < 8.3.0 scripts.\n *\n * This adds a new resource, -space, for determining how much\n * space to leave between the text and image; Tk 8.4 reuses the\n * -padx or -pady option for this purpose.\n *\n * -width always specifies the length in characters of the text part;\n *  in Tk 8.4 it's either characters or pixels, depending on the\n *  value of -compound.\n *\n * Negative values of -width are interpreted as a minimum width\n * on all platforms, not just on Windows.\n *\n * Tk 8.4 ignores -padx and -pady if -compound is set to \"none\".\n * Here, padding is handled by a different element.\n */\n\ntypedef struct {\n    /*\n     * Element options:\n     */\n    Tcl_Obj\t\t*compoundObj;\n    Tcl_Obj\t\t*spaceObj;\n    TextElement\ttext;\n    ImageElement\timage;\n\n    /*\n     * Computed values (see LabelSetup)\n     */\n    Ttk_Compound\tcompound;\n    int\t\tspace;\n    int\t\ttotalWidth, totalHeight;\n} LabelElement;\n\nstatic const Ttk_ElementOptionSpec LabelElementOptions[] = {\n    { \"-compound\", TK_OPTION_ANY,\n\toffsetof(LabelElement,compoundObj), \"none\" },\n    { \"-space\", TK_OPTION_PIXELS,\n\toffsetof(LabelElement,spaceObj), \"4\" },\n\n    /* Text element part:\n     * NB: Keep in sync with TextElementOptions.\n     */\n    { \"-text\", TK_OPTION_STRING,\n\toffsetof(LabelElement,text.textObj), \"\" },\n    { \"-font\", TK_OPTION_FONT,\n\toffsetof(LabelElement,text.fontObj), DEFAULT_FONT },\n    { \"-foreground\", TK_OPTION_COLOR,\n\toffsetof(LabelElement,text.foregroundObj), \"black\" },\n    { \"-underline\", TK_OPTION_INDEX,\n\toffsetof(LabelElement,text.underlineObj), \"-1\"},\n    { \"-width\", TK_OPTION_INT,\n\toffsetof(LabelElement,text.widthObj), \"\"},\n    { \"-anchor\", TK_OPTION_ANCHOR,\n\toffsetof(LabelElement,text.anchorObj), \"w\"},\n    { \"-justify\", TK_OPTION_JUSTIFY,\n\toffsetof(LabelElement,text.justifyObj), \"left\" },\n    { \"-wraplength\", TK_OPTION_PIXELS,\n\toffsetof(LabelElement,text.wrapLengthObj), \"0\" },\n    { \"-embossed\", TK_OPTION_INT,\n\toffsetof(LabelElement,text.embossedObj), \"0\"},\n\n    /* Image element part:\n     * NB: Keep in sync with ImageElementOptions.\n     */\n    { \"-image\", TK_OPTION_STRING,\n\toffsetof(LabelElement,image.imageObj), \"\" },\n    { \"-stipple\", TK_OPTION_STRING,\t/* Really: TK_OPTION_BITMAP */\n\toffsetof(LabelElement,image.stippleObj), \"gray50\" },\n    { \"-background\", TK_OPTION_COLOR,\n\toffsetof(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * LabelSetup --\n *\tFills in computed fields of the label element.\n *\n *\tCalculate the text, image, and total width and height.\n */\n\n#undef  MAX\n#define MAX(a,b) ((a) > (b) ? (a) : (b));\nstatic void LabelSetup(\n    LabelElement *c, Tk_Window tkwin, Ttk_State state)\n{\n    Ttk_Compound *compoundPtr = &c->compound;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, c->spaceObj, &c->space);\n    Ttk_GetCompoundFromObj(NULL, c->compoundObj, compoundPtr);\n\n    /*\n     * Deal with TTK_COMPOUND_NONE.\n     */\n    if (c->compound == TTK_COMPOUND_NONE) {\n\tif (ImageSetup(&c->image, tkwin, state)) {\n\t    c->compound = TTK_COMPOUND_IMAGE;\n\t} else {\n\t    c->compound = TTK_COMPOUND_TEXT;\n\t}\n    } else if (c->compound != TTK_COMPOUND_TEXT) {\n\tif (!ImageSetup(&c->image, tkwin, state)) {\n\t    c->compound = TTK_COMPOUND_TEXT;\n\t}\n    }\n    if (c->compound != TTK_COMPOUND_IMAGE) {\n\tTextSetup(&c->text, tkwin);\n    }\n\n    /*\n     * ASSERT:\n     * if c->compound != IMAGE, then TextSetup() has been called\n     * if c->compound != TEXT, then ImageSetup() has returned successfully\n     * c->compound != COMPOUND_NONE.\n     */\n\n    switch (c->compound)\n    {\n\tcase TTK_COMPOUND_NONE:\n\t    /* Can't happen */\n\t    break;\n\tcase TTK_COMPOUND_TEXT:\n\t    c->totalWidth  = c->text.width;\n\t    c->totalHeight = c->text.height;\n\t    break;\n\tcase TTK_COMPOUND_IMAGE:\n\t    c->totalWidth  = c->image.width;\n\t    c->totalHeight = c->image.height;\n\t    break;\n\tcase TTK_COMPOUND_CENTER:\n\t    c->totalWidth  = MAX(c->image.width, c->text.width);\n\t    c->totalHeight = MAX(c->image.height, c->text.height);\n\t    break;\n\tcase TTK_COMPOUND_TOP:\n\tcase TTK_COMPOUND_BOTTOM:\n\t    c->totalWidth  = MAX(c->image.width, c->text.width);\n\t    c->totalHeight = c->image.height + c->text.height + c->space;\n\t    break;\n\n\tcase TTK_COMPOUND_LEFT:\n\tcase TTK_COMPOUND_RIGHT:\n\t    c->totalWidth  = c->image.width + c->text.width + c->space;\n\t    c->totalHeight = MAX(c->image.height, c->text.height);\n\t    break;\n    }\n}\n\nstatic void LabelCleanup(LabelElement *c)\n{\n    if (c->compound != TTK_COMPOUND_TEXT) {\n\tImageCleanup(&c->image);\n    }\n    if (c->compound != TTK_COMPOUND_IMAGE) {\n\tTextCleanup(&c->text);\n    }\n}\n\nstatic void LabelElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    LabelElement *label = (LabelElement *)elementRecord;\n    int textReqWidth = 0;\n\n    LabelSetup(label, tkwin, 0);\n\n    *heightPtr = label->totalHeight;\n\n    /* Requested width based on -width option, not actual text width:\n     */\n    if (label->compound != TTK_COMPOUND_IMAGE) {\n\ttextReqWidth = TextReqWidth(&label->text);\n    }\n\n    switch (label->compound)\n    {\n\tcase TTK_COMPOUND_TEXT:\n\t    *widthPtr = textReqWidth;\n\t    break;\n\tcase TTK_COMPOUND_IMAGE:\n\t    *widthPtr = label->image.width;\n\t    break;\n\tcase TTK_COMPOUND_TOP:\n\tcase TTK_COMPOUND_BOTTOM:\n\tcase TTK_COMPOUND_CENTER:\n\t    *widthPtr = MAX(label->image.width, textReqWidth);\n\t    break;\n\tcase TTK_COMPOUND_LEFT:\n\tcase TTK_COMPOUND_RIGHT:\n\t    *widthPtr = label->image.width + textReqWidth + label->space;\n\t    break;\n\tcase TTK_COMPOUND_NONE:\n\t    break; /* Can't happen */\n    }\n\n    LabelCleanup(label);\n}\n\n/*\n * DrawCompound --\n *\tHelper routine for LabelElementDraw;\n *\tHandles layout for -compound {left,right,top,bottom}\n */\nstatic void DrawCompound(\n    LabelElement *l, Ttk_Box b, Tk_Window tkwin, Drawable d, Ttk_State state,\n\tTtk_Side imageSide, Ttk_Side textSide)\n{\n    Ttk_Box imageBox =\n\tTtk_PlaceBox(&b, l->image.width, l->image.height, imageSide, 0);\n    Ttk_Box textBox =\n\tTtk_PlaceBox(&b, l->text.width, l->text.height, textSide, 0);\n    ImageDraw(&l->image,tkwin,d,imageBox,state);\n    TextDraw(&l->text,tkwin,d,textBox);\n}\n\nstatic void LabelElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    LabelElement *l = (LabelElement *)elementRecord;\n    Tk_Anchor anchor = TK_ANCHOR_CENTER;\n\n    LabelSetup(l, tkwin, state);\n\n    /*\n     * Adjust overall parcel based on -anchor:\n     */\n    Tk_GetAnchorFromObj(NULL, l->text.anchorObj, &anchor);\n    b = Ttk_AnchorBox(b, l->totalWidth, l->totalHeight, anchor);\n\n    /*\n     * Draw text and/or image parts based on -compound:\n     */\n    switch (l->compound)\n    {\n\tcase TTK_COMPOUND_NONE:\n\t    /* Can't happen */\n\t    break;\n\tcase TTK_COMPOUND_TEXT:\n\t    TextDraw(&l->text,tkwin,d,b);\n\t    break;\n\tcase TTK_COMPOUND_IMAGE:\n\t    ImageDraw(&l->image,tkwin,d,b,state);\n\t    break;\n\tcase TTK_COMPOUND_CENTER:\n\t{\n\t    Ttk_Box pb = Ttk_AnchorBox(\n\t\tb, l->image.width, l->image.height, TK_ANCHOR_CENTER);\n\t    ImageDraw(&l->image, tkwin, d, pb, state);\n\t    pb = Ttk_AnchorBox(\n\t\tb, l->text.width, l->text.height, TK_ANCHOR_CENTER);\n\t    TextDraw(&l->text, tkwin, d, pb);\n\t    break;\n\t}\n\tcase TTK_COMPOUND_TOP:\n\t    DrawCompound(l, b, tkwin, d, state, TTK_SIDE_TOP, TTK_SIDE_BOTTOM);\n\t    break;\n\tcase TTK_COMPOUND_BOTTOM:\n\t    DrawCompound(l, b, tkwin, d, state, TTK_SIDE_BOTTOM, TTK_SIDE_TOP);\n\t    break;\n\tcase TTK_COMPOUND_LEFT:\n\t    DrawCompound(l, b, tkwin, d, state, TTK_SIDE_LEFT, TTK_SIDE_RIGHT);\n\t    break;\n\tcase TTK_COMPOUND_RIGHT:\n\t    DrawCompound(l, b, tkwin, d, state, TTK_SIDE_RIGHT, TTK_SIDE_LEFT);\n\t    break;\n    }\n\n    LabelCleanup(l);\n}\n\nstatic const Ttk_ElementSpec LabelElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(LabelElement),\n    LabelElementOptions,\n    LabelElementSize,\n    LabelElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkLabel_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme =  Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterElement(interp, theme, \"text\", &TextElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"ctext\", &cTextElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"image\", &ImageElementSpec, NULL);\n    Ttk_RegisterElement(interp, theme, \"label\", &LabelElementSpec, NULL);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkLayout.c",
    "content": "/*\n * ttkLayout.c --\n *\n * Generic layout processing.\n *\n * Copyright © 2003 Joe English.  Freely redistributable.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n\n#define MAX(a,b) ((a) > (b) ? (a) : (b))\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n\n/*------------------------------------------------------------------------\n * +++ Ttk_Box and Ttk_Padding utilities:\n */\n\nTtk_Box\nTtk_MakeBox(int x, int y, int width, int height)\n{\n    Ttk_Box b;\n    b.x = x; b.y = y; b.width = width; b.height = height;\n    return b;\n}\n\nint\nTtk_BoxContains(Ttk_Box box, int x, int y)\n{\n    return box.x <= x && x < box.x + box.width\n\t&& box.y <= y && y < box.y + box.height;\n}\n\nbool\nTtkBoxEqual(Ttk_Box box1, Ttk_Box box2)\n{\n    return box1.x == box2.x && box1.y == box2.y\n\t&& box1.width == box2.width && box1.height == box2.height;\n}\n\nTcl_Obj *\nTtk_NewBoxObj(Ttk_Box box)\n{\n    Tcl_Obj *result[4];\n\n    result[0] = Tcl_NewWideIntObj(box.x);\n    result[1] = Tcl_NewWideIntObj(box.y);\n    result[2] = Tcl_NewWideIntObj(box.width);\n    result[3] = Tcl_NewWideIntObj(box.height);\n\n    return Tcl_NewListObj(4, result);\n}\n\n/*\n * packTop, packBottom, packLeft, packRight --\n *\tCarve out a parcel of the specified height (resp width)\n *\tfrom the specified cavity.\n *\n * Returns:\n *\tThe new parcel.\n *\n * Side effects:\n *\tAdjust the cavity.\n */\n\nstatic Ttk_Box packTop(Ttk_Box *cavity, int height)\n{\n    Ttk_Box parcel;\n    height = MIN(height, cavity->height);\n    parcel = Ttk_MakeBox(cavity->x, cavity->y, cavity->width, height);\n    cavity->y += height;\n    cavity->height -= height;\n    return parcel;\n}\n\nstatic Ttk_Box packBottom(Ttk_Box *cavity, int height)\n{\n    height = MIN(height, cavity->height);\n    cavity->height -= height;\n    return Ttk_MakeBox(\n\tcavity->x, cavity->y + cavity->height,\n\tcavity->width, height);\n}\n\nstatic Ttk_Box packLeft(Ttk_Box *cavity, int width)\n{\n    Ttk_Box parcel;\n    width = MIN(width, cavity->width);\n    parcel = Ttk_MakeBox(cavity->x, cavity->y, width,cavity->height);\n    cavity->x += width;\n    cavity->width -= width;\n    return parcel;\n}\n\nstatic Ttk_Box packRight(Ttk_Box *cavity, int width)\n{\n    width = MIN(width, cavity->width);\n    cavity->width -= width;\n    return Ttk_MakeBox(cavity->x + cavity->width,\n\t    cavity->y, width, cavity->height);\n}\n\n/*\n * Ttk_PackBox --\n *\tCarve out a parcel of the specified size on the specified side\n *\tin the specified cavity.\n *\n * Returns:\n *\tThe new parcel.\n *\n * Side effects:\n *\tAdjust the cavity.\n */\n\nTtk_Box Ttk_PackBox(Ttk_Box *cavity, int width, int height, Ttk_Side side)\n{\n    switch (side) {\n\tdefault:\n\tcase TTK_SIDE_TOP:\treturn packTop(cavity, height);\n\tcase TTK_SIDE_BOTTOM:\treturn packBottom(cavity, height);\n\tcase TTK_SIDE_LEFT:\treturn packLeft(cavity, width);\n\tcase TTK_SIDE_RIGHT:\treturn packRight(cavity, width);\n    }\n}\n\n/*\n * Ttk_PadBox --\n *\tShrink a box by the specified padding amount.\n */\nTtk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p)\n{\n    b.x += p.left;\n    b.y += p.top;\n    b.width -= (p.left + p.right);\n    b.height -= (p.top + p.bottom);\n    if (b.width <= 0) b.width = 1;\n    if (b.height <= 0) b.height = 1;\n    return b;\n}\n\n/*\n * Ttk_ExpandBox --\n *\tGrow a box by the specified padding amount.\n */\nTtk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p)\n{\n    b.x -= p.left;\n    b.y -= p.top;\n    b.width += (p.left + p.right);\n    b.height += (p.top + p.bottom);\n    return b;\n}\n\n/*\n * Ttk_StickBox --\n *\tPlace a box of size w * h in the specified parcel,\n *\taccording to the specified sticky bits.\n */\nTtk_Box Ttk_StickBox(Ttk_Box parcel, int width, int height, unsigned sticky)\n{\n    int dx, dy;\n\n    if (width > parcel.width) width = parcel.width;\n    if (height > parcel.height) height = parcel.height;\n\n    dx = parcel.width - width;\n    dy = parcel.height - height;\n\n    /*\n     * X coordinate adjustment:\n     */\n    switch (sticky & (TTK_STICK_W | TTK_STICK_E))\n    {\n\tcase TTK_STICK_W | TTK_STICK_E:\n\t    /* no-op -- use entire parcel width */\n\t    break;\n\tcase TTK_STICK_W:\n\t    parcel.width = width;\n\t    break;\n\tcase TTK_STICK_E:\n\t    parcel.x += dx;\n\t    parcel.width = width;\n\t    break;\n\tdefault :\n\t    parcel.x += dx / 2;\n\t    parcel.width = width;\n\t    break;\n    }\n\n    /*\n     * Y coordinate adjustment:\n     */\n    switch (sticky & (TTK_STICK_N | TTK_STICK_S))\n    {\n\tcase TTK_STICK_N | TTK_STICK_S:\n\t    /* use entire parcel height */\n\t    break;\n\tcase TTK_STICK_N:\n\t    parcel.height = height;\n\t    break;\n\tcase TTK_STICK_S:\n\t    parcel.y += dy;\n\t    parcel.height = height;\n\t    break;\n\tdefault :\n\t    parcel.y += dy / 2;\n\t    parcel.height = height;\n\t    break;\n    }\n\n    return parcel;\n}\n\n/*\n * AnchorToSticky --\n *\tConvert a Tk_Anchor enum to a TTK_STICKY bitmask.\n */\nstatic Ttk_Sticky AnchorToSticky(Tk_Anchor anchor)\n{\n    switch (anchor)\n    {\n\tcase TK_ANCHOR_N:\treturn TTK_STICK_N;\n\tcase TK_ANCHOR_NE:\treturn TTK_STICK_N | TTK_STICK_E;\n\tcase TK_ANCHOR_E:\treturn TTK_STICK_E;\n\tcase TK_ANCHOR_SE:\treturn TTK_STICK_S | TTK_STICK_E;\n\tcase TK_ANCHOR_S:\treturn TTK_STICK_S;\n\tcase TK_ANCHOR_SW:\treturn TTK_STICK_S | TTK_STICK_W;\n\tcase TK_ANCHOR_W:\treturn TTK_STICK_W;\n\tcase TK_ANCHOR_NW:\treturn TTK_STICK_N | TTK_STICK_W;\n\tdefault:\treturn 0;\n    }\n}\n\n/*\n * Ttk_AnchorBox --\n *\tPlace a box of size w * h in the specified parcel,\n *\taccording to the specified anchor.\n */\nTtk_Box Ttk_AnchorBox(Ttk_Box parcel, int width, int height, Tk_Anchor anchor)\n{\n    return Ttk_StickBox(parcel, width, height, AnchorToSticky(anchor));\n}\n\n/*\n * Ttk_PlaceBox --\n *\tCombine Ttk_PackBox() and Ttk_StickBox().\n */\nTtk_Box Ttk_PlaceBox(\n    Ttk_Box *cavity, int width, int height, Ttk_Side side, unsigned sticky)\n{\n    return Ttk_StickBox(\n\t    Ttk_PackBox(cavity, width, height, side), width, height, sticky);\n}\n\n/*\n * Ttk_PositionBox --\n *\tPack and stick a box according to PositionSpec flags.\n */\n\nMODULE_SCOPE Ttk_Box\nTtk_PositionBox(Ttk_Box *cavity, int width, int height, Ttk_PositionSpec flags)\n{\n    Ttk_Box parcel;\n\n\t if (flags & TTK_EXPAND)\tparcel = *cavity;\n    else if (flags & TTK_PACK_TOP)\tparcel = packTop(cavity, height);\n    else if (flags & TTK_PACK_LEFT)\tparcel = packLeft(cavity, width);\n    else if (flags & TTK_PACK_BOTTOM)\tparcel = packBottom(cavity, height);\n    else if (flags & TTK_PACK_RIGHT)\tparcel = packRight(cavity, width);\n    else\t\t\t\tparcel = *cavity;\n\n    return Ttk_StickBox(parcel, width, height, flags);\n}\n\n/*\n * TTKInitPadding --\n *\tCommon factor of Ttk_GetPaddingFromObj and Ttk_GetBorderFromObj.\n *\tInitializes Ttk_Padding record, supplying default values\n *\tfor missing entries.\n */\nstatic void TTKInitPadding(int padc, int pixels[4], Ttk_Padding *pad)\n{\n    switch (padc)\n    {\n\tcase 0: pixels[0] = 0; /*FALLTHRU*/\n\tcase 1:\tpixels[1] = pixels[0]; /*FALLTHRU*/\n\tcase 2:\tpixels[2] = pixels[0]; /*FALLTHRU*/\n\tcase 3:\tpixels[3] = pixels[1]; /*FALLTHRU*/\n    }\n\n    pad->left\t= (short)pixels[0];\n    pad->top\t= (short)pixels[1];\n    pad->right\t= (short)pixels[2];\n    pad->bottom\t= (short)pixels[3];\n}\n\n/*\n * Ttk_GetPaddingFromObj --\n *\n *\tExtract a padding specification from a Tcl_Obj * scaled\n *\tto work with a particular Tk_Window.\n *\n *\tThe string representation of a Ttk_Padding is a list\n *\tof one to four Tk_Pixel specifications, corresponding\n *\tto the left, top, right, and bottom padding.\n *\n *\tIf the 'bottom' (fourth) element is missing, it defaults to 'top'.\n *\tIf the 'right' (third) element is missing, it defaults to 'left'.\n *\tIf the 'top' (second) element is missing, it defaults to 'left'.\n *\n *\tThe internal representation is a Tcl_ListObj containing\n *\tone to four Tk_PixelObj objects.\n *\n * Returns:\n *\tTCL_OK or TCL_ERROR.  In the latter case an error message is\n *\tleft in 'interp' and '*paddingPtr' is set to all-zeros.\n *\tOtherwise, *paddingPtr is filled in with the padding specification.\n *\n */\nint Ttk_GetPaddingFromObj(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    Tcl_Obj *objPtr,\n    Ttk_Padding *pad)\n{\n    Tcl_Obj **padv;\n    Tcl_Size i, padc;\n    int pixels[4];\n\n    if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {\n\tgoto error;\n    }\n\n    if (padc > 4) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Wrong #elements in padding spec\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"PADDING\", (char *)NULL);\n\t}\n\tgoto error;\n    }\n\n    for (i=0; i < padc; ++i) {\n\tif (Tk_GetPixelsFromObj(interp, tkwin, padv[i], &pixels[i]) != TCL_OK) {\n\t    goto error;\n\t}\n    }\n\n    TTKInitPadding(padc, pixels, pad);\n    return TCL_OK;\n\nerror:\n    pad->left = pad->top = pad->right = pad->bottom = 0;\n    return TCL_ERROR;\n}\n\n/* Ttk_GetBorderFromObj --\n *\tSame as Ttk_GetPaddingFromObj, except padding is a list of integers\n *\tinstead of Tk_Pixel specifications.  Does not require a Tk_Window\n *\tparameter.\n *\n */\nint Ttk_GetBorderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad)\n{\n    Tcl_Obj **padv;\n    Tcl_Size i, padc;\n    int pixels[4];\n\n    if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) {\n\tgoto error;\n    }\n\n    if (padc > 4) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Wrong #elements in padding spec\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"BORDER\", (char *)NULL);\n\t}\n\tgoto error;\n    }\n\n    for (i=0; i < padc; ++i) {\n\tif (Tcl_GetIntFromObj(interp, padv[i], &pixels[i]) != TCL_OK) {\n\t    goto error;\n\t}\n    }\n\n    TTKInitPadding(padc, pixels, pad);\n    return TCL_OK;\n\nerror:\n    pad->left = pad->top = pad->right = pad->bottom = 0;\n    return TCL_ERROR;\n}\n\n/*\n * Ttk_MakePadding --\n *\tReturn an initialized Ttk_Padding structure.\n */\nTtk_Padding Ttk_MakePadding(short left, short top, short right, short bottom)\n{\n    Ttk_Padding pad;\n    pad.left = left;\n    pad.top = top;\n    pad.right = right;\n    pad.bottom = bottom;\n    return pad;\n}\n\n/*\n * Ttk_UniformPadding --\n *\tReturns a uniform Ttk_Padding structure, with the same\n *\tborder width on all sides.\n */\nTtk_Padding Ttk_UniformPadding(short borderWidth)\n{\n    Ttk_Padding pad;\n    pad.left = pad.top = pad.right = pad.bottom = borderWidth;\n    return pad;\n}\n\n/*\n * Ttk_AddPadding --\n *\tCombine two padding records.\n */\nTtk_Padding Ttk_AddPadding(Ttk_Padding p1, Ttk_Padding p2)\n{\n    p1.left += p2.left;\n    p1.top += p2.top;\n    p1.right += p2.right;\n    p1.bottom += p2.bottom;\n    return p1;\n}\n\n/* Ttk_RelievePadding --\n *\tAdd an extra n pixels of padding according to specified relief.\n *\tThis may be used in element geometry procedures to simulate\n *\ta \"pressed-in\" look for pushbuttons.\n */\nTtk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief, int n)\n{\n    switch (relief)\n    {\n\tcase TK_RELIEF_RAISED:\n\t    padding.right += n;\n\t    padding.bottom += n;\n\t    break;\n\tcase TK_RELIEF_SUNKEN:\t/* shift */\n\t    padding.left += n;\n\t    padding.top += n;\n\t    break;\n\tdefault:\n\t{\n\t    int h1 = n/2, h2 = h1 + n % 2;\n\t    padding.left += h1;\n\t    padding.top += h1;\n\t    padding.right += h2;\n\t    padding.bottom += h2;\n\t    break;\n\t}\n    }\n    return padding;\n}\n\n/*\n * Ttk_GetStickyFromObj --\n *\tReturns a stickiness specification from the specified Tcl_Obj*,\n *\tconsisting of any combination of n, s, e, and w.\n *\n * Returns: TCL_OK if objPtr holds a valid stickiness specification,\n *\totherwise TCL_ERROR.  interp is used for error reporting if non-NULL.\n *\n */\nint Ttk_GetStickyFromObj(\n    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *result)\n{\n    const char *string = Tcl_GetString(objPtr);\n    Ttk_Sticky sticky = 0;\n    char c;\n\n    while ((c = *string++) != '\\0') {\n\tswitch (c) {\n\t    case 'w': case 'W': sticky |= TTK_STICK_W; break;\n\t    case 'e': case 'E': sticky |= TTK_STICK_E; break;\n\t    case 'n': case 'N': sticky |= TTK_STICK_N; break;\n\t    case 's': case 'S': sticky |= TTK_STICK_S; break;\n\t    default:\n\t\tif (interp) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"Bad -sticky specification %s\",\n\t\t\tTcl_GetString(objPtr)));\n\t\t    Tcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"STICKY\", (char *)NULL);\n\t\t}\n\t\treturn TCL_ERROR;\n\t}\n    }\n\n    *result = sticky;\n    return TCL_OK;\n}\n\n/* Ttk_NewStickyObj --\n *\tConstruct a new Tcl_Obj * containing a stickiness specification.\n */\nTcl_Obj *Ttk_NewStickyObj(Ttk_Sticky sticky)\n{\n    char buf[5];\n    char *p = buf;\n\n    if (sticky & TTK_STICK_N)\t*p++ = 'n';\n    if (sticky & TTK_STICK_S)\t*p++ = 's';\n    if (sticky & TTK_STICK_W)\t*p++ = 'w';\n    if (sticky & TTK_STICK_E)\t*p++ = 'e';\n\n    *p = '\\0';\n    return Tcl_NewStringObj(buf, p - buf);\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout nodes.\n */\n\ntypedef struct Ttk_LayoutNode_ Ttk_LayoutNode;\nstruct Ttk_LayoutNode_\n{\n    unsigned\t\tflags;\t\t/* Packing and sticky flags */\n    Ttk_ElementClass\t*eclass;\t/* Class record */\n    Ttk_State\t\tstate;\t\t/* Current state */\n    Ttk_Box\t\tparcel;\t\t/* allocated parcel */\n    Ttk_LayoutNode\t*next, *child;\n};\n\nstatic Ttk_LayoutNode *Ttk_NewLayoutNode(\n    unsigned flags, Ttk_ElementClass *elementClass)\n{\n    Ttk_LayoutNode *node = (Ttk_LayoutNode *)Tcl_Alloc(sizeof(*node));\n\n    node->flags = flags;\n    node->eclass = elementClass;\n    node->state = 0u;\n    node->next = node->child = 0;\n    node->parcel = Ttk_MakeBox(0,0,0,0);\n\n    return node;\n}\n\nstatic void Ttk_FreeLayoutNode(Ttk_LayoutNode *node)\n{\n    while (node) {\n\tTtk_LayoutNode *next = node->next;\n\tTtk_FreeLayoutNode(node->child);\n\tTcl_Free(node);\n\tnode = next;\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout templates.\n */\n\nstruct Ttk_TemplateNode_ {\n    char *name;\n    unsigned flags;\n    struct Ttk_TemplateNode_ *next, *child;\n};\n\nstatic Ttk_TemplateNode *Ttk_NewTemplateNode(const char *name, unsigned flags)\n{\n    Ttk_TemplateNode *op = (Ttk_TemplateNode *)Tcl_Alloc(sizeof(*op));\n    op->name = (char *)Tcl_Alloc(strlen(name) + 1); strcpy(op->name, name);\n    op->flags = flags;\n    op->next = op->child = 0;\n    return op;\n}\n\nvoid Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate op)\n{\n    while (op) {\n\tTtk_LayoutTemplate next = op->next;\n\tTtk_FreeLayoutTemplate(op->child);\n\tTcl_Free(op->name);\n\tTcl_Free(op);\n\top = next;\n    }\n}\n\n/* InstantiateLayout --\n *\tCreate a layout tree from a template.\n */\nstatic Ttk_LayoutNode *\nTtk_InstantiateLayout(Ttk_Theme theme, Ttk_TemplateNode *op)\n{\n    Ttk_ElementClass *elementClass = Ttk_GetElement(theme, op->name);\n    Ttk_LayoutNode *node = Ttk_NewLayoutNode(op->flags, elementClass);\n\n    if (op->next) {\n\tnode->next = Ttk_InstantiateLayout(theme,op->next);\n    }\n    if (op->child) {\n\tnode->child = Ttk_InstantiateLayout(theme,op->child);\n    }\n\n    return node;\n}\n\n/*\n * Ttk_ParseLayoutTemplate --\n *\tConvert a Tcl list into a layout template.\n *\n * Syntax:\n *\tlayoutSpec ::= { elementName ?-option value ...? }+\n */\n\n/* NB: This must match bit definitions TTK_PACK_LEFT etc. */\nstatic const char *const packSideStrings[] =\n    { \"left\", \"right\", \"top\", \"bottom\", NULL };\n\nTtk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr)\n{\n    enum {  OP_SIDE, OP_STICKY, OP_EXPAND, OP_BORDER, OP_UNIT, OP_CHILDREN };\n    static const char *const optStrings[] = {\n\t\"-side\", \"-sticky\", \"-expand\", \"-border\", \"-unit\", \"-children\", 0 };\n\n    Tcl_Size i = 0, objc;\n    Tcl_Obj **objv;\n    Ttk_TemplateNode *head = 0, *tail = 0;\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\treturn 0;\n    }\n\n    while (i < objc) {\n\tconst char *elementName = Tcl_GetString(objv[i]);\n\tunsigned flags = 0x0, sticky = TTK_FILL_BOTH;\n\tTcl_Obj *childSpec = 0;\n\n\t/*\n\t * Parse options:\n\t */\n\t++i;\n\twhile (i < objc) {\n\t    const char *optName = Tcl_GetString(objv[i]);\n\t    int option, value;\n\n\t    if (optName[0] != '-') {\n\t\tbreak;\n\t    }\n\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings,\n\t\t    sizeof(char *), \"option\", 0, &option)\n\t\t!= TCL_OK)\n\t    {\n\t\tgoto error;\n\t    }\n\n\t    if (++i >= objc) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"Missing value for option %s\",\n\t\t\tTcl_GetString(objv[i-1])));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"LAYOUT\", (char *)NULL);\n\t\tgoto error;\n\t    }\n\n\t    switch (option) {\n\t\tcase OP_SIDE:\t/* <<NOTE-PACKSIDE>> */\n\t\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], packSideStrings,\n\t\t\t\tsizeof(char *), \"side\", 0, &value) != TCL_OK) {\n\t\t\tgoto error;\n\t\t    }\n\t\t    flags |= (TTK_PACK_LEFT << value);\n\n\t\t    break;\n\t\tcase OP_STICKY:\n\t\t    if (Ttk_GetStickyFromObj(interp,objv[i],&sticky) != TCL_OK) {\n\t\t\tgoto error;\n\t\t    }\n\t\t    break;\n\t\tcase OP_EXPAND:\n\t\t    if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) {\n\t\t\tgoto error;\n\t\t    }\n\t\t    if (value) {\n\t\t\tflags |= TTK_EXPAND;\n\t\t    }\n\t\t    break;\n\t\tcase OP_BORDER:\n\t\t    if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) {\n\t\t\tgoto error;\n\t\t    }\n\t\t    if (value) {\n\t\t\tflags |= TTK_BORDER;\n\t\t    }\n\t\t    break;\n\t\tcase OP_UNIT:\n\t\t    if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) {\n\t\t\tgoto error;\n\t\t    }\n\t\t    if (value) {\n\t\t\tflags |= TTK_UNIT;\n\t\t    }\n\t\t    break;\n\t\tcase OP_CHILDREN:\n\t\t    childSpec = objv[i];\n\t\t    break;\n\t    }\n\t    ++i;\n\t}\n\n\t/*\n\t * Build new node:\n\t */\n\tif (tail) {\n\t    tail->next = Ttk_NewTemplateNode(elementName, flags | sticky);\n\t    tail = tail->next;\n\t} else {\n\t    head = tail = Ttk_NewTemplateNode(elementName, flags | sticky);\n\t}\n\tif (childSpec) {\n\t    tail->child = Ttk_ParseLayoutTemplate(interp, childSpec);\n\t    if (!tail->child) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"Invalid -children value\"));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"CHILDREN\", (char *)NULL);\n\t\tgoto error;\n\t    }\n\t}\n    }\n\n    return head;\n\nerror:\n    Ttk_FreeLayoutTemplate(head);\n    return 0;\n}\n\n/* Ttk_BuildLayoutTemplate --\n *\tBuild a layout template tree from a statically defined\n *\tTtk_LayoutSpec array.\n */\nTtk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec spec)\n{\n    Ttk_TemplateNode *first = 0, *last = 0;\n\n    for ( ; !(spec->opcode & _TTK_LAYOUT_END) ; ++spec) {\n\tif (spec->elementName) {\n\t    Ttk_TemplateNode *node =\n\t\tTtk_NewTemplateNode(spec->elementName, spec->opcode);\n\n\t    if (last) {\n\t\tlast->next = node;\n\t    } else {\n\t\tfirst = node;\n\t    }\n\t    last = node;\n\t}\n\n\tif (spec->opcode & _TTK_CHILDREN && last) {\n\t    int depth = 1;\n\t    last->child = Ttk_BuildLayoutTemplate(spec+1);\n\n\t    /* Skip to end of group:\n\t     */\n\t    while (depth) {\n\t\t++spec;\n\t\tif (spec->opcode & _TTK_CHILDREN) {\n\t\t    ++depth;\n\t\t}\n\t\tif (spec->opcode & _TTK_LAYOUT_END) {\n\t\t    --depth;\n\t\t}\n\t    }\n\t}\n\n    } /* for */\n\n    return first;\n}\n\nvoid Ttk_RegisterLayouts(Ttk_Theme theme, Ttk_LayoutSpec spec)\n{\n    while (!(spec->opcode & _TTK_LAYOUT_END)) {\n\tTtk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(spec+1);\n\tTtk_RegisterLayoutTemplate(theme, spec->elementName, layoutTemplate);\n\tdo {\n\t    ++spec;\n\t} while (!(spec->opcode & _TTK_LAYOUT));\n    }\n}\n\nTcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)\n{\n    Tcl_Obj *result = Tcl_NewListObj(0,0);\n\n#   define APPENDOBJ(obj) Tcl_ListObjAppendElement(NULL, result, obj)\n#   define APPENDSTR(str) APPENDOBJ(Tcl_NewStringObj(str,-1))\n\n    while (node) {\n\tunsigned flags = node->flags;\n\n\tAPPENDSTR(node->name);\n\n\t/* Back-compute -side.  <<NOTE-PACKSIDE>>\n\t * @@@ NOTES: Ick.\n\t */\n\tif (flags & TTK_EXPAND) {\n\t    APPENDSTR(\"-expand\");\n\t    APPENDSTR(\"1\");\n\t} else {\n\t    if (flags & _TTK_MASK_PACK) {\n\t\tint side = 0;\n\t\tunsigned sideFlags = flags & _TTK_MASK_PACK;\n\n\t\twhile (!(sideFlags & TTK_PACK_LEFT)) {\n\t\t    ++side;\n\t\t    sideFlags >>= 1;\n\t\t}\n\t\tAPPENDSTR(\"-side\");\n\t\tAPPENDSTR(packSideStrings[side]);\n\t    }\n\t}\n\n\t/*\n\t * In Ttk_ParseLayoutTemplate, default -sticky is \"nsew\", so always\n\t * include this even if no sticky bits are set.\n\t */\n\n\tAPPENDSTR(\"-sticky\");\n\tAPPENDOBJ(Ttk_NewStickyObj(flags & _TTK_MASK_STICK));\n\n\t/* @@@ Check again: are these necessary? Can't see any effect! */\n\tif (flags & TTK_BORDER)\t{ APPENDSTR(\"-border\"); APPENDSTR(\"1\"); }\n\tif (flags & TTK_UNIT)\t{ APPENDSTR(\"-unit\"); APPENDSTR(\"1\"); }\n\n\tif (node->child) {\n\t    APPENDSTR(\"-children\");\n\t    APPENDOBJ(Ttk_UnparseLayoutTemplate(node->child));\n\t}\n\tnode = node->next;\n    }\n\n#   undef APPENDOBJ\n#   undef APPENDSTR\n\n    return result;\n}\n\n/*------------------------------------------------------------------------\n * +++ Layouts.\n */\nstruct Ttk_Layout_\n{\n    Ttk_Style\t\tstyle;\n    void\t\t*recordPtr;\n    Tk_OptionTable\toptionTable;\n    Tk_Window\t\ttkwin;\n    Ttk_LayoutNode\t*root;\n};\n\nstatic Ttk_Layout TTKNewLayout(\n    Ttk_Style style,\n    void *recordPtr,Tk_OptionTable optionTable, Tk_Window tkwin,\n    Ttk_LayoutNode *root)\n{\n    Ttk_Layout layout = (Ttk_Layout)Tcl_Alloc(sizeof(*layout));\n    layout->style = style;\n    layout->recordPtr = recordPtr;\n    layout->optionTable = optionTable;\n    layout->tkwin = tkwin;\n    layout->root = root;\n    return layout;\n}\n\nvoid Ttk_FreeLayout(Ttk_Layout layout)\n{\n    Ttk_FreeLayoutNode(layout->root);\n    Tcl_Free(layout);\n}\n\n/*\n * Ttk_CreateLayout --\n *\tCreate a layout from the specified theme and style name.\n *\tReturns: New layout, 0 on error.\n *\tLeaves an error message in interp's result if there is an error.\n */\nTtk_Layout Ttk_CreateLayout(\n    Tcl_Interp *interp,\t\t/* where to leave error messages */\n    Ttk_Theme themePtr,\n    const char *styleName,\n    void *recordPtr,\n    Tk_OptionTable optionTable,\n    Tk_Window tkwin)\n{\n    Ttk_Style style = Ttk_GetStyle(themePtr, styleName);\n    Ttk_LayoutTemplate layoutTemplate =\n\tTtk_FindLayoutTemplate(themePtr,styleName);\n    Ttk_ElementClass *bgelement = Ttk_GetElement(themePtr, \"background\");\n    Ttk_LayoutNode *bgnode;\n\n    if (!layoutTemplate) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Layout %s not found\", styleName));\n\tTcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"LAYOUT\", styleName, (char *)NULL);\n\treturn 0;\n    }\n\n    bgnode = Ttk_NewLayoutNode(TTK_FILL_BOTH, bgelement);\n    bgnode->next = Ttk_InstantiateLayout(themePtr, layoutTemplate);\n\n    return TTKNewLayout(style, recordPtr, optionTable, tkwin, bgnode);\n}\n\n/* Ttk_CreateSublayout --\n *\tCreates a new sublayout.\n *\n *\tSublayouts are used to draw subparts of a compound widget.\n *\tThey use the same Tk_Window, but a different option table\n *\tand data record.\n */\nTtk_Layout\nTtk_CreateSublayout(\n    Tcl_Interp *interp,\n    Ttk_Theme themePtr,\n    Ttk_Layout parentLayout,\n    const char *baseName,\n    Tk_OptionTable optionTable)\n{\n    Tcl_DString buf;\n    const char *styleName;\n    Ttk_Style style;\n    Ttk_LayoutTemplate layoutTemplate;\n\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, Ttk_StyleName(parentLayout->style), TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, baseName, TCL_INDEX_NONE);\n    styleName = Tcl_DStringValue(&buf);\n\n    style = Ttk_GetStyle(themePtr, styleName);\n    layoutTemplate = Ttk_FindLayoutTemplate(themePtr, styleName);\n\n    if (!layoutTemplate) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Layout %s not found\", styleName));\n\tTcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"LAYOUT\", styleName, (char *)NULL);\n\treturn 0;\n    }\n\n    Tcl_DStringFree(&buf);\n\n    return TTKNewLayout(\n\t    style, 0, optionTable, parentLayout->tkwin,\n\t    Ttk_InstantiateLayout(themePtr, layoutTemplate));\n}\n\n/* Ttk_RebindSublayout --\n *\tBind sublayout to new data source.\n */\nvoid Ttk_RebindSublayout(Ttk_Layout layout, void *recordPtr)\n{\n    layout->recordPtr = recordPtr;\n}\n\n/*\n * Ttk_QueryOption --\n *\tLook up an option from a layout's associated option.\n */\nTcl_Obj *Ttk_QueryOption(\n    Ttk_Layout layout, const char *optionName, Ttk_State state)\n{\n    return Ttk_QueryStyle(\n\tlayout->style,layout->recordPtr,layout->optionTable,optionName,state);\n}\n\n/*\n * Ttk_LayoutStyle --\n *\tExtract Ttk_Style from Ttk_Layout.\n */\nTtk_Style Ttk_LayoutStyle(Ttk_Layout layout)\n{\n    return layout->style;\n}\n\n/*------------------------------------------------------------------------\n * +++ Size computation.\n */\nstatic void Ttk_NodeListSize(\n    Ttk_Layout layout, Ttk_LayoutNode *node,\n    Ttk_State state, int *widthPtr, int *heightPtr); /* Forward */\n\nstatic void Ttk_NodeSize(\n    Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state,\n    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)\n{\n    int elementWidth, elementHeight, subWidth, subHeight;\n    Ttk_Padding elementPadding;\n\n    Ttk_ElementSize(node->eclass,\n\tlayout->style, layout->recordPtr,layout->optionTable, layout->tkwin,\n\tstate|node->state,\n\t&elementWidth, &elementHeight, &elementPadding);\n\n    Ttk_NodeListSize(layout,node->child,state,&subWidth,&subHeight);\n    subWidth += Ttk_PaddingWidth(elementPadding);\n    subHeight += Ttk_PaddingHeight(elementPadding);\n\n    *widthPtr = MAX(elementWidth, subWidth);\n    *heightPtr = MAX(elementHeight, subHeight);\n    *paddingPtr = elementPadding;\n}\n\nstatic void Ttk_NodeListSize(\n    Ttk_Layout layout, Ttk_LayoutNode *node,\n    Ttk_State state, int *widthPtr, int *heightPtr)\n{\n    if (!node) {\n\t*widthPtr = *heightPtr = 0;\n    } else {\n\tint width, height, restWidth, restHeight;\n\tTtk_Padding unused;\n\n\tTtk_NodeSize(layout, node, state, &width, &height, &unused);\n\tTtk_NodeListSize(layout, node->next, state, &restWidth, &restHeight);\n\n\tif (node->flags & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) {\n\t    *widthPtr = width + restWidth;\n\t} else {\n\t    *widthPtr = MAX(width, restWidth);\n\t}\n\n\tif (node->flags & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {\n\t    *heightPtr = height + restHeight;\n\t} else {\n\t    *heightPtr = MAX(height, restHeight);\n\t}\n    }\n}\n\n/*\n * Ttk_LayoutNodeInternalPadding --\n *\tReturns the internal padding of a layout node.\n */\nTtk_Padding Ttk_LayoutNodeInternalPadding(\n    Ttk_Layout layout, Ttk_LayoutNode *node)\n{\n    int unused;\n    Ttk_Padding padding;\n    Ttk_ElementSize(node->eclass,\n\tlayout->style, layout->recordPtr, layout->optionTable, layout->tkwin,\n\t0/*state*/, &unused, &unused, &padding);\n    return padding;\n}\n\n/*\n * Ttk_LayoutNodeInternalParcel --\n *\tReturns the inner area of a specified layout node,\n *\tbased on current parcel and element's internal padding.\n */\nTtk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout layout, Ttk_LayoutNode *node)\n{\n    Ttk_Padding padding = Ttk_LayoutNodeInternalPadding(layout, node);\n    return Ttk_PadBox(node->parcel, padding);\n}\n\n/* Ttk_LayoutSize --\n *\tCompute requested size of a layout.\n */\nvoid Ttk_LayoutSize(\n    Ttk_Layout layout, Ttk_State state, int *widthPtr, int *heightPtr)\n{\n    Ttk_NodeListSize(layout, layout->root, state, widthPtr, heightPtr);\n}\n\nvoid Ttk_LayoutNodeReqSize(\t/* @@@ Rename this */\n    Ttk_Layout layout, Ttk_LayoutNode *node, int *widthPtr, int *heightPtr)\n{\n    Ttk_Padding unused;\n    Ttk_NodeSize(layout, node, 0/*state*/, widthPtr, heightPtr, &unused);\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout placement.\n */\n\n/* Ttk_PlaceNodeList --\n *\tCompute parcel for each node in a layout tree\n *\taccording to position specification and overall size.\n */\nstatic void Ttk_PlaceNodeList(\n    Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state, Ttk_Box cavity)\n{\n    for (; node; node = node->next)\n    {\n\tint width, height;\n\tTtk_Padding padding;\n\n\t/* Compute node size: (@@@ cache this instead?)\n\t */\n\tTtk_NodeSize(layout, node, state, &width, &height, &padding);\n\n\t/* Compute parcel:\n\t */\n\tnode->parcel = Ttk_PositionBox(&cavity, width, height, node->flags);\n\n\t/* Place child nodes:\n\t */\n\tif (node->child) {\n\t    Ttk_Box childBox = Ttk_PadBox(node->parcel, padding);\n\t    Ttk_PlaceNodeList(layout,node->child, state, childBox);\n\t}\n    }\n}\n\nvoid Ttk_PlaceLayout(Ttk_Layout layout, Ttk_State state, Ttk_Box b)\n{\n    Ttk_PlaceNodeList(layout, layout->root, state,  b);\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout drawing.\n */\n\n/*\n * Ttk_DrawLayout --\n *\tDraw a layout tree.\n */\nstatic void Ttk_DrawNodeList(\n    Ttk_Layout layout, Ttk_State state, Ttk_LayoutNode *node, Drawable d)\n{\n    for (; node; node = node->next)\n    {\n\tint border = node->flags & TTK_BORDER;\n\tint substate = state;\n\n\tif (node->flags & TTK_UNIT) {\n\t    substate |= node->state;\n\t}\n\n\tif (node->child && border) {\n\t    Ttk_DrawNodeList(layout, substate, node->child, d);\n\t}\n\n\tTtk_DrawElement(\n\t    node->eclass,\n\t    layout->style,layout->recordPtr,layout->optionTable,layout->tkwin,\n\t    d, node->parcel, state | node->state);\n\n\tif (node->child && !border) {\n\t    Ttk_DrawNodeList(layout, substate, node->child, d);\n\t}\n    }\n}\n\nvoid Ttk_DrawLayout(Ttk_Layout layout, Ttk_State state, Drawable d)\n{\n    Ttk_DrawNodeList(layout, state, layout->root, d);\n}\n\n/*------------------------------------------------------------------------\n * +++ Inquiry and modification.\n */\n\n/*\n * Ttk_IdentifyElement --\n *\tFind the element at the specified x,y coordinate.\n */\nstatic Ttk_Element IdentifyNode(Ttk_Element node, int x, int y)\n{\n    Ttk_Element closest = NULL;\n\n    for (; node; node = node->next) {\n\tif (Ttk_BoxContains(node->parcel, x, y)) {\n\t    closest = node;\n\t    if (node->child && !(node->flags & TTK_UNIT)) {\n\t\tTtk_Element childNode = IdentifyNode(node->child, x,y);\n\t\tif (childNode) {\n\t\t    closest = childNode;\n\t\t}\n\t    }\n\t}\n    }\n    return closest;\n}\n\nTtk_Element Ttk_IdentifyElement(Ttk_Layout layout, int x, int y)\n{\n    return IdentifyNode(layout->root, x, y);\n}\n\n/*\n * tail --\n *\tReturn the last component of an element name, e.g.,\n *\t\"Scrollbar.thumb\" => \"thumb\"\n */\nstatic const char *tail(const char *elementName)\n{\n    const char *dot;\n    while ((dot=strchr(elementName,'.')) != NULL)\n\telementName = dot + 1;\n    return elementName;\n}\n\n/*\n * Ttk_FindElement --\n *\tLook up an element by name\n */\nstatic Ttk_Element\nFindNode(Ttk_Element node, const char *nodeName)\n{\n    for (; node ; node = node->next) {\n\tif (!strcmp(tail(Ttk_ElementName(node)), nodeName)) {\n\t    return node;\n\t}\n\n\tif (node->child) {\n\t    Ttk_Element childNode = FindNode(node->child, nodeName);\n\t    if (childNode) {\n\t\treturn childNode;\n\t    }\n\t}\n    }\n    return 0;\n}\n\nTtk_Element Ttk_FindElement(Ttk_Layout layout, const char *nodeName)\n{\n    return FindNode(layout->root, nodeName);\n}\n\n/*\n * Ttk_ClientRegion --\n *\tFind the internal parcel of a named element within a given layout.\n *\tIf the element is not present, use the entire window.\n */\nTtk_Box Ttk_ClientRegion(Ttk_Layout layout, const char *elementName)\n{\n    Ttk_Element element = Ttk_FindElement(layout, elementName);\n    return element\n\t? Ttk_LayoutNodeInternalParcel(layout, element)\n\t: Ttk_WinBox(layout->tkwin)\n\t;\n}\n\n/*\n * Ttk_ElementName --\n *\tReturn the name (class name) of the element.\n */\nconst char *Ttk_ElementName(Ttk_Element node)\n{\n    return Ttk_ElementClassName(node->eclass);\n}\n\n/*\n * Ttk_ElementParcel --\n *\tReturn the element's current parcel.\n */\nTtk_Box Ttk_ElementParcel(Ttk_Element node)\n{\n    return node->parcel;\n}\n\n/*\n * Ttk_PlaceElement --\n *\tExplicitly specify an element's parcel.\n */\nvoid Ttk_PlaceElement(Ttk_Layout layout, Ttk_Element node, Ttk_Box b)\n{\n    node->parcel = b;\n    if (node->child) {\n\tTtk_PlaceNodeList(layout, node->child, 0,\n\t    Ttk_PadBox(b, Ttk_LayoutNodeInternalPadding(layout, node)));\n    }\n}\n\n/*\n * AnchorToPosition --\n *\tConvert a Tk_Anchor enum to a position bitmask.\n */\nstatic Ttk_PositionSpec AnchorToPosition(Tk_Anchor anchor)\n{\n    switch (anchor)\n    {\n\tcase TK_ANCHOR_N:\treturn TTK_PACK_TOP;\n\tcase TK_ANCHOR_S:\treturn TTK_PACK_BOTTOM;\n\tcase TK_ANCHOR_NE:\treturn TTK_PACK_RIGHT|TTK_STICK_N;\n\tcase TK_ANCHOR_SE:\treturn TTK_PACK_RIGHT|TTK_STICK_S;\n\tcase TK_ANCHOR_E:\treturn TTK_PACK_RIGHT;\n\tcase TK_ANCHOR_NW:\treturn TTK_PACK_LEFT|TTK_STICK_N;\n\tcase TK_ANCHOR_SW:\treturn TTK_PACK_LEFT|TTK_STICK_S;\n\tcase TK_ANCHOR_W:\treturn TTK_PACK_LEFT;\n\tcase TK_ANCHOR_CENTER:\treturn 0;\n\tdefault:;\n    }\n    return TTK_PACK_LEFT;\n}\n\n/*\n * Ttk_AnchorElement --\n *\tExplicitly specify an element's anchoring.\n */\nvoid Ttk_AnchorElement(Ttk_Element node, Tk_Anchor anchor)\n{\n    node->flags = AnchorToPosition(anchor);\n}\n\n/*\n * Ttk_ChangeElementState --\n */\nvoid Ttk_ChangeElementState(Ttk_LayoutNode *node,unsigned set,unsigned clr)\n{\n    node->state = (node->state | set) & ~clr;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkManager.c",
    "content": "/*\n * Copyright 2005, Joe English.  Freely redistributable.\n *\n * Support routines for geometry managers.\n */\n\n#include \"tkInt.h\"\n#include \"ttkManager.h\"\n\n/*------------------------------------------------------------------------\n * +++ The Geometry Propagation Dance.\n *\n * When a content window requests a new size or some other parameter changes,\n * the manager recomputes the required size for the container window and calls\n * Tk_GeometryRequest().  This is scheduled as an idle handler so multiple\n * updates can be processed as a single batch.\n *\n * If all goes well, the container's manager will process the request\n * (and so on up the chain to the toplevel window), and the container\n * window will eventually receive a <Configure> event.  At this point\n * it recomputes the size and position of all content windows and places them.\n *\n * If all does not go well, however, the container's request may be ignored\n * (typically because the top-level window has a fixed, user-specified size).\n * Tk doesn't provide any notification when this happens; to account for this,\n * we also schedule an idle handler to call the layout procedure\n * after making a geometry request.\n *\n * +++ Content window removal <<NOTE-LOSTCONTENT>>.\n *\n * There are three conditions under which a content window is removed:\n *\n * (1) Another GM claims control\n * (2) Manager voluntarily relinquishes control\n * (3) Content window is destroyed\n *\n * In case (1), Tk calls the manager's lostContentProc.\n * Case (2) is performed by calling Tk_ManageGeometry(window,NULL,0);\n * in this case Tk does _not_ call the lostContentProc (documented behavior).\n * Tk doesn't handle case (3) either; to account for that we\n * register an event handler on the content window to track <Destroy> events.\n */\n\n/* ++ Data structures.\n */\ntypedef struct\n{\n    Tk_Window\t\twindow;\n    Ttk_Manager\t*manager;\n    void\t\t*data;\n    unsigned\t\tflags;\n} Ttk_Content;\n\n/* content->flags bits:\n */\n#define CONTENT_MAPPED\t0x1\t/* content windows to be mapped when container is */\n\nstruct TtkManager_\n{\n    const Ttk_ManagerSpec\t*managerSpec;\n    void\t\t*managerData;\n    Tk_Window\twindow;\n    unsigned\t\tflags;\n    Tcl_Size\t\tnContent;\n    Ttk_Content\t\t**content;\n};\n\n/* manager->flags bits:\n */\n#define MGR_UPDATE_PENDING\t0x1\n#define MGR_RESIZE_REQUIRED\t0x2\n#define MGR_RELAYOUT_REQUIRED\t0x4\n\nstatic void ManagerIdleProc(void *);\t/* forward */\n\n/* ++ ScheduleUpdate --\n *\tSchedule a call to recompute the size and/or layout,\n *\tdepending on flags.\n */\nstatic void ScheduleUpdate(Ttk_Manager *mgr, unsigned flags)\n{\n    if (!(mgr->flags & MGR_UPDATE_PENDING)) {\n\tTcl_DoWhenIdle(ManagerIdleProc, mgr);\n\tmgr->flags |= MGR_UPDATE_PENDING;\n    }\n    mgr->flags |= flags;\n}\n\n/* ++ RecomputeSize --\n *\tRecomputes the required size of the container window,\n *\tmakes geometry request.\n */\nstatic void RecomputeSize(Ttk_Manager *mgr)\n{\n    int width = 1, height = 1;\n\n    if (mgr->managerSpec->RequestedSize(mgr->managerData, &width, &height)) {\n\tTk_GeometryRequest(mgr->window, width, height);\n\tScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);\n    }\n    mgr->flags &= ~MGR_RESIZE_REQUIRED;\n}\n\n/* ++ RecomputeLayout --\n *\tRecompute geometry of all content windows.\n */\nstatic void RecomputeLayout(Ttk_Manager *mgr)\n{\n    mgr->managerSpec->PlaceContent(mgr->managerData);\n    mgr->flags &= ~MGR_RELAYOUT_REQUIRED;\n}\n\n/* ++ ManagerIdleProc --\n *\tDoWhenIdle procedure for deferred updates.\n */\nstatic void ManagerIdleProc(void *clientData)\n{\n    Ttk_Manager *mgr = (Ttk_Manager *)clientData;\n    mgr->flags &= ~MGR_UPDATE_PENDING;\n\n    if (mgr->flags & MGR_RESIZE_REQUIRED) {\n\tRecomputeSize(mgr);\n    }\n    if (mgr->flags & MGR_RELAYOUT_REQUIRED) {\n\tif (mgr->flags & MGR_UPDATE_PENDING) {\n\t    /* RecomputeSize has scheduled another update; relayout later */\n\t    return;\n\t}\n\tRecomputeLayout(mgr);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Event handlers.\n */\n\n/* ++ ManagerEventHandler --\n *\tRecompute content layout when container widget is resized.\n *\tKeep the content's map state in sync with the container's.\n */\nstatic const int ManagerEventMask = StructureNotifyMask;\nstatic void ManagerEventHandler(void *clientData, XEvent *eventPtr)\n{\n    Ttk_Manager *mgr = (Ttk_Manager *)clientData;\n    Tcl_Size i;\n\n    switch (eventPtr->type)\n    {\n\tcase ConfigureNotify:\n\t    RecomputeLayout(mgr);\n\t    break;\n\tcase MapNotify:\n\t    for (i = 0; i < mgr->nContent; ++i) {\n\t\tTtk_Content *content = mgr->content[i];\n\t\tif (content->flags & CONTENT_MAPPED) {\n\t\t    Tk_MapWindow(content->window);\n\t\t}\n\t    }\n\t    break;\n\tcase UnmapNotify:\n\t    for (i = 0; i < mgr->nContent; ++i) {\n\t\tTtk_Content *content = mgr->content[i];\n\t\tTk_UnmapWindow(content->window);\n\t    }\n\t    break;\n    }\n}\n\n/* ++ ContentLostEventHandler --\n *\tNotifies manager when a content window is destroyed\n *\t(see <<NOTE-LOSTCONTENT>>).\n */\nstatic void ContentLostEventHandler(void *clientData, XEvent *eventPtr)\n{\n    Ttk_Content *content = (Ttk_Content *)clientData;\n    if (eventPtr->type == DestroyNotify) {\n\tcontent->manager->managerSpec->tkGeomMgr.lostContentProc(\n\t    content->manager, content->window);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Content initialization and cleanup.\n */\n\nstatic Ttk_Content *NewContent(\n    Ttk_Manager *mgr, Tk_Window window, void *data)\n{\n    Ttk_Content *content = (Ttk_Content *)Tcl_Alloc(sizeof(Ttk_Content));\n\n    content->window = window;\n    content->manager = mgr;\n    content->flags = 0;\n    content->data = data;\n\n    return content;\n}\n\nstatic void DeleteContent(Ttk_Content *content)\n{\n    Tcl_Free(content);\n}\n\n/*------------------------------------------------------------------------\n * +++ Manager initialization and cleanup.\n */\n\nTtk_Manager *Ttk_CreateManager(\n    const Ttk_ManagerSpec *managerSpec, void *managerData, Tk_Window window)\n{\n    Ttk_Manager *mgr = (Ttk_Manager *)Tcl_Alloc(sizeof(*mgr));\n\n    mgr->managerSpec\t= managerSpec;\n    mgr->managerData\t= managerData;\n    mgr->window\t= window;\n    mgr->nContent\t= 0;\n    mgr->content\t= NULL;\n    mgr->flags\t= 0;\n\n    Tk_CreateEventHandler(\n\tmgr->window, ManagerEventMask, ManagerEventHandler, mgr);\n\n    return mgr;\n}\n\nvoid Ttk_DeleteManager(Ttk_Manager *mgr)\n{\n    Tk_DeleteEventHandler(\n\tmgr->window, ManagerEventMask, ManagerEventHandler, mgr);\n\n    while (mgr->nContent > 0) {\n\tTtk_ForgetContent(mgr, mgr->nContent - 1);\n    }\n    if (mgr->content) {\n\tTcl_Free(mgr->content);\n    }\n\n    Tcl_CancelIdleCall(ManagerIdleProc, mgr);\n\n    Tcl_Free(mgr);\n}\n\n/*------------------------------------------------------------------------\n * +++ Content window management.\n */\n\n/* ++ InsertContent --\n *\tAdds content to the list of managed windows.\n */\nstatic void InsertContent(Ttk_Manager *mgr, Ttk_Content *content, Tcl_Size index)\n{\n    Tcl_Size endIndex = mgr->nContent++;\n    mgr->content = (Ttk_Content **)Tcl_Realloc(mgr->content, mgr->nContent * sizeof(Ttk_Content *));\n\n    while (endIndex > index) {\n\tmgr->content[endIndex] = mgr->content[endIndex - 1];\n\t--endIndex;\n    }\n\n    mgr->content[index] = content;\n\n    Tk_ManageGeometry(content->window,\n\t&mgr->managerSpec->tkGeomMgr, mgr);\n\n    Tk_CreateEventHandler(content->window,\n\tStructureNotifyMask, ContentLostEventHandler, content);\n\n    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);\n}\n\n/* RemoveContent --\n *\tUnmanage and delete the content window.\n *\n * NOTES/ASSUMPTIONS:\n *\n * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this\n * routine is called from the content window's DestroyNotify event handler.\n */\nstatic void RemoveContent(Ttk_Manager *mgr, Tcl_Size index)\n{\n    Ttk_Content *content = mgr->content[index];\n    Tcl_Size i;\n\n    /* Notify manager:\n     */\n    mgr->managerSpec->ContentRemoved(mgr->managerData, index);\n\n    /* Remove from array:\n     */\n    --mgr->nContent;\n    for (i = index ; i < mgr->nContent; ++i) {\n\tmgr->content[i] = mgr->content[i+1];\n    }\n\n    /* Clean up:\n     */\n    Tk_DeleteEventHandler(\n\tcontent->window, StructureNotifyMask, ContentLostEventHandler, content);\n\n    /* Note [1] */\n    Tk_UnmaintainGeometry(content->window, mgr->window);\n    Tk_UnmapWindow(content->window);\n\n    DeleteContent(content);\n\n    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);\n}\n\n/*------------------------------------------------------------------------\n * +++ Tk_GeomMgr hooks.\n */\n\nvoid Ttk_GeometryRequestProc(void *clientData, Tk_Window window)\n{\n    Ttk_Manager *mgr = (Ttk_Manager *)clientData;\n    Tcl_Size index = Ttk_ContentIndex(mgr, window);\n\n    if (index >= 0) {\n\tint reqWidth = Tk_ReqWidth(window);\n\tint reqHeight= Tk_ReqHeight(window);\n\tif (mgr->managerSpec->ContentRequest(\n\t    mgr->managerData, index, reqWidth, reqHeight)) {\n\t    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);\n\t}\n    }\n}\n\nvoid Ttk_LostContentProc(void *clientData, Tk_Window window)\n{\n    Ttk_Manager *mgr = (Ttk_Manager *)clientData;\n    Tcl_Size index = Ttk_ContentIndex(mgr, window);\n\n    /* ASSERT: index >= 0 */\n    RemoveContent(mgr, index);\n}\n\n/*------------------------------------------------------------------------\n * +++ Public API.\n */\n\n/* ++ Ttk_InsertContent --\n *\tAdd a new content window at the specified index.\n */\nvoid Ttk_InsertContent(\n    Ttk_Manager *mgr, Tcl_Size index, Tk_Window tkwin, void *data)\n{\n    Ttk_Content *content = NewContent(mgr, tkwin, data);\n    InsertContent(mgr, content, index);\n}\n\n/* ++ Ttk_ForgetContent --\n *\tUnmanage the specified content window.\n */\nvoid Ttk_ForgetContent(Ttk_Manager *mgr, Tcl_Size index)\n{\n    Tk_Window window = mgr->content[index]->window;\n    RemoveContent(mgr, index);\n    Tk_ManageGeometry(window, NULL, 0);\n}\n\n/* ++ Ttk_PlaceContent --\n *\tSet the position and size of the specified content window.\n *\n * NOTES:\n *\tContrary to documentation, Tk_MaintainGeometry doesn't always\n *\tmap the content window.\n */\nvoid Ttk_PlaceContent(\n    Ttk_Manager *mgr, Tcl_Size index, int x, int y, int width, int height)\n{\n    Ttk_Content *content = mgr->content[index];\n    Tk_MaintainGeometry(content->window,mgr->window,x,y,width,height);\n    content->flags |= CONTENT_MAPPED;\n    if (Tk_IsMapped(mgr->window)) {\n\tTk_MapWindow(content->window);\n    }\n}\n\n/* ++ Ttk_UnmapContent --\n *\tUnmap the specified content window, but leave it managed.\n */\nvoid Ttk_UnmapContent(Ttk_Manager *mgr, Tcl_Size index)\n{\n    Ttk_Content *content = mgr->content[index];\n    Tk_UnmaintainGeometry(content->window, mgr->window);\n    content->flags &= ~CONTENT_MAPPED;\n    /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always\n     * unmap the content window:\n     */\n    Tk_UnmapWindow(content->window);\n}\n\n/* LayoutChanged, SizeChanged --\n *\tSchedule a relayout, resp. resize request.\n */\nvoid Ttk_ManagerLayoutChanged(Ttk_Manager *mgr)\n{\n    ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);\n}\n\nvoid Ttk_ManagerSizeChanged(Ttk_Manager *mgr)\n{\n    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);\n}\n\n/* +++ Accessors.\n */\nTcl_Size Ttk_NumberContent(Ttk_Manager *mgr)\n{\n    return mgr->nContent;\n}\nvoid *Ttk_ContentData(Ttk_Manager *mgr, Tcl_Size index)\n{\n    return mgr->content[index]->data;\n}\nTk_Window Ttk_ContentWindow(Ttk_Manager *mgr, Tcl_Size index)\n{\n    return mgr->content[index]->window;\n}\n\n/*------------------------------------------------------------------------\n * +++ Utility routines.\n */\n\n/* ++ Ttk_ContentIndex --\n *\tReturns the index of specified content window, TCL_INDEX_NONE if not found.\n */\nTcl_Size Ttk_ContentIndex(Ttk_Manager *mgr, Tk_Window window)\n{\n    Tcl_Size index;\n    for (index = 0; index < mgr->nContent; ++index)\n\tif (mgr->content[index]->window == window) {\n\t    return index;\n\t}\n    return -1;\n}\n\n/* ++ Ttk_GetContentIndexFromObj(interp, mgr, objPtr, lastOK, indexPtr) --\n *\tReturn the index of the content window specified by objPtr.\n *\tContent windows may be specified as an integer index or\n *\tas the name of the managed window.\n *\n *  The parameter lastOK should be non-0 if the resolved index can be equal to\n *  the current size (i.e. one more than the current highest index) and 0\n *  otherwise.\n *\n * Returns:\n *\tStandard Tcl completion code.  Leaves an error message in case of error.\n */\n\nint Ttk_GetContentIndexFromObj(\n    Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int lastOK, Tcl_Size *indexPtr)\n{\n    const char *string = Tcl_GetString(objPtr);\n    Tcl_Size index = 0;\n    Tk_Window tkwin;\n\n    /* Try interpreting as an integer first:\n     */\n    if (TkGetIntForIndex(objPtr, mgr->nContent - 1, lastOK, &index) == TCL_OK) {\n\t/*\n\t * Note despite passing lastOK above, we still need to check here\n\t * as well as TkGetIntForIndex only uses lastOK for end-relative indices,\n\t * not integers.\n\t */\n\tif (index < 0 || (index - !!lastOK) >= mgr->nContent) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"Managed window index \\\"%s\\\" out of bounds\", Tcl_GetString(objPtr)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"MANAGED\", \"INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\t*indexPtr = index;\n\treturn TCL_OK;\n    }\n\n    /* Try interpreting as a window name;\n     */\n    if ((*string == '.') &&\n\t    (tkwin = Tk_NameToWindow(interp, string, mgr->window))) {\n\tindex = Ttk_ContentIndex(mgr, tkwin);\n\tif (index < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s is not managed by %s\", string,\n\t\t    Tk_PathName(mgr->window)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"MANAGED\", \"MANAGER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\t*indexPtr = index;\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"Invalid managed window specification %s\", string));\n    Tcl_SetErrorCode(interp, \"TTK\", \"MANAGED\", \"SPEC\", (char *)NULL);\n    return TCL_ERROR;\n}\n\n/* ++ Ttk_ReorderContent(mgr, fromIndex, toIndex) --\n *\tChange content window order.\n */\nvoid Ttk_ReorderContent(Ttk_Manager *mgr, Tcl_Size fromIndex, Tcl_Size toIndex)\n{\n    Ttk_Content *moved = mgr->content[fromIndex];\n\n    /* Shuffle down: */\n    while (fromIndex > toIndex) {\n\tmgr->content[fromIndex] = mgr->content[fromIndex - 1];\n\t--fromIndex;\n    }\n    /* Or, shuffle up: */\n    while (fromIndex < toIndex) {\n\tmgr->content[fromIndex] = mgr->content[fromIndex + 1];\n\t++fromIndex;\n    }\n    /* ASSERT: fromIndex == toIndex */\n    mgr->content[fromIndex] = moved;\n\n    /* Schedule a relayout.  In general, rearranging content\n     * may also change the size:\n     */\n    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);\n}\n\n/* ++ Ttk_Maintainable(interp, window, container) --\n *\tUtility routine.  Verifies that 'container' may be used to maintain\n *\tthe geometry of 'window' via Tk_MaintainGeometry:\n *\n *\t+ 'container' is either 'window's parent -OR-\n *\t+ 'container is a descendant of 'window's parent.\n *\t+ 'window' is not a toplevel window\n *\t+ 'window' belongs to the same toplevel as 'container'\n *\n * Returns: 1 if OK; otherwise 0, leaving an error message in 'interp'.\n */\nint Ttk_Maintainable(Tcl_Interp *interp, Tk_Window window, Tk_Window container)\n{\n    Tk_Window ancestor = container, parent = Tk_Parent(window);\n\n    if (Tk_IsTopLevel(window) || window == container) {\n\tgoto badWindow;\n    }\n\n    while (ancestor != parent) {\n\tif (Tk_IsTopLevel(ancestor)) {\n\t    goto badWindow;\n\t}\n\tancestor = Tk_Parent(ancestor);\n    }\n\n    return 1;\n\nbadWindow:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"cannot add \\\"%s\\\" as content of \\\"%s\\\"\",\n\t    Tk_PathName(window), Tk_PathName(container)));\n    Tcl_SetErrorCode(interp, \"TTK\", \"GEOMETRY\", \"MAINTAINABLE\", (char *)NULL);\n    return 0;\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkManager.h",
    "content": "/*\n * Copyright © 2005 Joe English.  Freely redistributable.\n *\n * Geometry manager utilities.\n */\n\n#ifndef _TTKMANAGER\n#define _TTKMANAGER\n\n#include \"ttkTheme.h\"\n\ntypedef struct TtkManager_ Ttk_Manager;\n\n/*\n * Geometry manager specification record:\n *\n * RequestedSize computes the requested size of the container window.\n *\n * PlaceContent sets the position and size of all managed content windows\n * by calling Ttk_PlaceContent().\n *\n * ContentRemoved() is called immediately before a content window is removed.\n * NB: the associated content window may have been destroyed when this\n * routine is called.\n *\n * ContentRequest() is called when a content window requests a size change.\n * It should return 1 if the request should propagate, 0 otherwise.\n */\ntypedef struct {\t\t\t/* Manager hooks */\n    Tk_GeomMgr tkGeomMgr;\t\t/* \"real\" Tk Geometry Manager */\n\n    int  (*RequestedSize)(void *managerData, int *widthPtr, int *heightPtr);\n    void (*PlaceContent)(void *managerData);\n    int  (*ContentRequest)(void *managerData, Tcl_Size index, int width, int height);\n    void (*ContentRemoved)(void *managerData, Tcl_Size index);\n} Ttk_ManagerSpec;\n\n/*\n * Default implementations for Tk_GeomMgr hooks:\n */\n#define Ttk_LostSlaveProc Ttk_LostContentProc\nMODULE_SCOPE void Ttk_GeometryRequestProc(void *, Tk_Window window);\nMODULE_SCOPE void Ttk_LostContentProc(void *, Tk_Window window);\n\n/*\n * Public API:\n */\nMODULE_SCOPE Ttk_Manager *Ttk_CreateManager(\n\tconst Ttk_ManagerSpec *, void *managerData, Tk_Window window);\nMODULE_SCOPE void Ttk_DeleteManager(Ttk_Manager *);\n\n#define  Ttk_InsertSlave Ttk_InsertContent\nMODULE_SCOPE void Ttk_InsertContent(\n    Ttk_Manager *, Tcl_Size position, Tk_Window, void *clientData);\n\n#define Ttk_ForgetSlave Ttk_ForgetContent\nMODULE_SCOPE void Ttk_ForgetContent(Ttk_Manager *, Tcl_Size index);\n\n#define Ttk_ReorderSlave Ttk_ReorderContent\nMODULE_SCOPE void Ttk_ReorderContent(Ttk_Manager *, Tcl_Size fromIndex, Tcl_Size toIndex);\n    /* Rearrange content window positions */\n\n#define Ttk_PlaceSlave Ttk_PlaceContent\nMODULE_SCOPE void Ttk_PlaceContent(\n    Ttk_Manager *, Tcl_Size index, int x, int y, int width, int height);\n    /* Position and map the content window */\n\n#define Ttk_UnmapSlave Ttk_UnmapContent\nMODULE_SCOPE void Ttk_UnmapContent(Ttk_Manager *, Tcl_Size index);\n    /* Unmap the content window */\n\nMODULE_SCOPE void Ttk_ManagerSizeChanged(Ttk_Manager *);\nMODULE_SCOPE void Ttk_ManagerLayoutChanged(Ttk_Manager *);\n    /* Notify manager that size (resp. layout) needs to be recomputed */\n\n/* Utilities:\n */\n#define Ttk_SlaveIndex Ttk_ContentIndex\nMODULE_SCOPE Tcl_Size Ttk_ContentIndex(Ttk_Manager *, Tk_Window);\n    /* Returns: index in content array of specified window, TCL_INDEX_NONE if not found */\n\n#define Ttk_GetSlaveIndexFromObj Ttk_GetContentIndexFromObj\nMODULE_SCOPE int Ttk_GetContentIndexFromObj(\n    Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int lastOK, Tcl_Size *indexPtr);\n\n/* Accessor functions:\n */\n#define Ttk_NumberSlaves Ttk_NumberContent\nMODULE_SCOPE Tcl_Size Ttk_NumberContent(Ttk_Manager *);\n    /* Returns: number of managed content windows */\n\n#define Ttk_SlaveData Ttk_ContentData\nMODULE_SCOPE void *Ttk_ContentData(Ttk_Manager *, Tcl_Size index);\n    /* Returns: client data associated with content window */\n\n#define Ttk_SlaveWindow Ttk_ContentWindow\nMODULE_SCOPE Tk_Window Ttk_ContentWindow(Ttk_Manager *, Tcl_Size index);\n    /* Returns: content window */\n\nMODULE_SCOPE int Ttk_Maintainable(Tcl_Interp *, Tk_Window content, Tk_Window container);\n    /* Returns: 1 if container can manage content; 0 otherwise leaving error msg */\n\n#endif /* _TTKMANAGER */\n"
  },
  {
    "path": "generic/ttk/ttkNotebook.c",
    "content": "/*\n * Copyright © 2004 Joe English\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n#include \"ttkManager.h\"\n\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n#define MAX(a,b) ((a) > (b) ? (a) : (b))\n\n/*------------------------------------------------------------------------\n * +++ Tab resources.\n */\n\n#define DEFAULT_MIN_TAB_WIDTH 24\n\nstatic const char *const TabStateStrings[] = { \"disabled\", \"hidden\", \"normal\", 0 };\ntypedef enum {\n    TAB_STATE_DISABLED, TAB_STATE_HIDDEN, TAB_STATE_NORMAL\n} TAB_STATE;\n\ntypedef struct\n{\n    /* Internal data:\n     */\n    int\t\twidth, height;\t/* Requested size of tab */\n    Ttk_Box\tparcel;\t\t/* Tab position */\n\n    /* Tab options:\n     */\n    TAB_STATE\tstate;\n\n    /* Child window options:\n     */\n    Tcl_Obj\t*paddingObj;\t/* Padding inside pane */\n    Ttk_Padding\tpadding;\n    Tcl_Obj\t*stickyObj;\n    Ttk_Sticky\tsticky;\n\n    /* Label options:\n     */\n    Tcl_Obj *textObj;\n    Tcl_Obj *imageObj;\n    Tcl_Obj *compoundObj;\n    Tcl_Obj *underlineObj;\n\n} Tab;\n\n/* Two different option tables are used for tabs:\n * TabOptionSpecs is used to draw the tab, and only includes resources\n * relevant to the tab.\n *\n * PaneOptionSpecs includes additional options for child window placement\n * and is used to configure the pane.\n */\nstatic const Tk_OptionSpec TabOptionSpecs[] =\n{\n    {TK_OPTION_STRING_TABLE, \"-state\", \"\", \"\",\n\t\"normal\", TCL_INDEX_NONE, offsetof(Tab,state),\n\tTK_OPTION_ENUM_VAR, TabStateStrings, 0 },\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\", \"\",\n\toffsetof(Tab,textObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\", NULL/*default*/,\n\toffsetof(Tab,imageObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_STRING_TABLE, \"-compound\", \"compound\", \"Compound\",\n\tNULL, offsetof(Tab,compoundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, ttkCompoundStrings, GEOMETRY_CHANGED },\n    {TK_OPTION_INDEX, \"-underline\", \"underline\", \"Underline\",\n\tTTK_OPTION_UNDERLINE_DEF(Tab, underlineObj), GEOMETRY_CHANGED},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 }\n};\n\nstatic const Tk_OptionSpec PaneOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Padding\", \"0\",\n\toffsetof(Tab,paddingObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-sticky\", \"sticky\", \"Sticky\", \"nsew\",\n\toffsetof(Tab,stickyObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },\n\n    WIDGET_INHERIT_OPTIONS(TabOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ Notebook resources.\n */\ntypedef struct\n{\n    Tcl_Obj *widthObj;\t\t\t/* Default width */\n    Tcl_Obj *heightObj;\t\t\t/* Default height */\n    Tcl_Obj *paddingObj;\t\t/* Padding around notebook */\n\n    Ttk_Manager *mgr;\t\t\t/* Geometry manager */\n    Tk_OptionTable tabOptionTable;\t/* Tab options */\n    Tk_OptionTable paneOptionTable;\t/* Tab+pane options */\n    Tcl_Size currentIndex;\t\t/* index of currently selected tab */\n    Tcl_Size activeIndex;\t\t/* index of currently active tab */\n    Ttk_Layout tabLayout;\t\t/* Sublayout for tabs */\n\n    Ttk_Box clientArea;\t\t\t/* Where to pack content windows */\n} NotebookPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    NotebookPart notebook;\n} Notebook;\n\nstatic const Tk_OptionSpec NotebookOptionSpecs[] =\n{\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\", \"0\",\n\toffsetof(Notebook,notebook.widthObj),TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\", \"0\",\n\toffsetof(Notebook,notebook.heightObj),TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Padding\", NULL,\n\toffsetof(Notebook,notebook.paddingObj),TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/* Notebook style options:\n */\ntypedef struct\n{\n    Ttk_PositionSpec\ttabPosition;\t/* Where to place tabs */\n    Ttk_Padding\t\ttabMargins;\t/* Margins around tab row */\n    Ttk_PositionSpec\ttabPlacement;\t/* How to pack tabs within tab row */\n    Ttk_Orient\t\ttabOrient;\t/* ... */\n    int\t\t\tminTabWidth;\t/* Minimum tab width */\n    Ttk_Padding\t\tpadding;\t/* External padding */\n} NotebookStyle;\n\nstatic void NotebookStyleOptions(\n    Notebook *nb, NotebookStyle *nbstyle, Tk_Window tkwin)\n{\n    Tcl_Obj *objPtr;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    nbstyle->tabPosition = TTK_PACK_TOP | TTK_STICK_W;\n    if ((objPtr = Ttk_QueryOption(nb->core.layout, \"-tabposition\", 0)) != 0) {\n\tTtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPosition);\n    }\n\n    /* Guess default tabPlacement as function of tabPosition:\n     */\n    if (nbstyle->tabPosition & TTK_PACK_LEFT) {\n\tnbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_E;\n    } else if (nbstyle->tabPosition & TTK_PACK_RIGHT) {\n\tnbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_W;\n    } else if (nbstyle->tabPosition & TTK_PACK_BOTTOM) {\n\tnbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_N;\n    } else { /* Assume TTK_PACK_TOP */\n\tnbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_S;\n    }\n    if ((objPtr = Ttk_QueryOption(nb->core.layout, \"-tabplacement\", 0)) != 0) {\n\tTtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPlacement);\n    }\n\n    /* Save the tabPosition and tabPlacement for later\n     */\n    if (mainInfoPtr != NULL) {\n\tmainInfoPtr->nbTabPosition  = (unsigned int)nbstyle->tabPosition;\n\tmainInfoPtr->nbTabPlacement = (unsigned int)nbstyle->tabPlacement;\n    }\n\n    /* Compute tabOrient as function of tabPlacement:\n     */\n    if (nbstyle->tabPlacement & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) {\n\tnbstyle->tabOrient = TTK_ORIENT_HORIZONTAL;\n    } else {\n\tnbstyle->tabOrient = TTK_ORIENT_VERTICAL;\n    }\n\n    nbstyle->tabMargins = Ttk_UniformPadding(0);\n    if ((objPtr = Ttk_QueryOption(nb->core.layout, \"-tabmargins\", 0)) != 0) {\n\tTtk_GetPaddingFromObj(NULL, tkwin, objPtr, &nbstyle->tabMargins);\n    }\n\n    nbstyle->padding = Ttk_UniformPadding(0);\n    if ((objPtr = Ttk_QueryOption(nb->core.layout, \"-padding\", 0)) != 0) {\n\tTtk_GetPaddingFromObj(NULL, tkwin, objPtr, &nbstyle->padding);\n    }\n\n    nbstyle->minTabWidth = DEFAULT_MIN_TAB_WIDTH;\n    if ((objPtr = Ttk_QueryOption(nb->core.layout, \"-mintabwidth\", 0)) != 0) {\n\tTk_GetPixelsFromObj(NULL, tkwin, objPtr, &nbstyle->minTabWidth);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Tab management.\n */\n\nstatic Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window window)\n{\n    Tk_OptionTable optionTable = nb->notebook.paneOptionTable;\n    Tab *record = (Tab *)Tcl_Alloc(sizeof(Tab));\n    memset(record, 0, sizeof(Tab));\n\n    if (Tk_InitOptions(interp, record, optionTable, window) != TCL_OK) {\n\tTcl_Free(record);\n\treturn NULL;\n    }\n\n    return record;\n}\n\nstatic void DestroyTab(Notebook *nb, Tab *tab)\n{\n    void *record = tab;\n    Tk_FreeConfigOptions(record, nb->notebook.paneOptionTable, nb->core.tkwin);\n    Tcl_Free(record);\n}\n\nstatic int ConfigureTab(\n    Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window window,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Ttk_Sticky sticky = tab->sticky;\n    Ttk_Padding padding = tab->padding;\n    Tk_SavedOptions savedOptions;\n    int mask = 0;\n\n    if (Tk_SetOptions(interp, tab, nb->notebook.paneOptionTable,\n\t    objc, objv, window, &savedOptions, &mask) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /* Check options:\n     * @@@ TODO: validate -image option.\n     */\n    if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK) {\n\tgoto error;\n    }\n    if (Ttk_GetPaddingFromObj(interp, window, tab->paddingObj, &padding)\n\t    != TCL_OK) {\n\tgoto error;\n    }\n\n    tab->sticky = sticky;\n    tab->padding = padding;\n\n    Tk_FreeSavedOptions(&savedOptions);\n    Ttk_ManagerSizeChanged(nb->notebook.mgr);\n    TtkRedisplayWidget(&nb->core);\n\n    return TCL_OK;\nerror:\n    Tk_RestoreSavedOptions(&savedOptions);\n    return TCL_ERROR;\n}\n\n/*\n * IdentifyTab --\n *\tReturn the index of the tab at point x,y,\n *\tor -1 if no tab at that point.\n */\nstatic Tcl_Size IdentifyTab(Notebook *nb, int x, int y)\n{\n    Tcl_Size index;\n    for (index = 0; index < Ttk_NumberContent(nb->notebook.mgr); ++index) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr,index);\n\tif (tab->state != TAB_STATE_HIDDEN\n\t\t&& Ttk_BoxContains(tab->parcel, x,y)) {\n\t    return index;\n\t}\n    }\n    return TCL_INDEX_NONE;\n}\n\n/*\n * ActivateTab --\n *\tSet the active tab index, redisplay if necessary.\n */\nstatic void ActivateTab(Notebook *nb, Tcl_Size index)\n{\n    if (index != nb->notebook.activeIndex) {\n\tnb->notebook.activeIndex = index;\n\tTtkRedisplayWidget(&nb->core);\n    }\n}\n\n/*\n * TabState --\n *\tReturn the state of the specified tab, based on\n *\tnotebook state, currentIndex, activeIndex, and user-specified tab state.\n *\tThe TTK_STATE_FIRST bit is set for the leftmost visible tab, and\n *\tTTK_STATE_LAST is set for the rightmost visible tab.\n */\nstatic Ttk_State TabState(Notebook *nb, Tcl_Size index)\n{\n    Ttk_State state = nb->core.state;\n    Tab *itab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n    Tcl_Size i = 0;\n    int statefirst = TTK_STATE_FIRST;\n    int statelast = TTK_STATE_LAST;\n    \n    if (nb->core.tkwin != NULL) {\n\tTkMainInfo *mainInfoPtr = ((TkWindow *) nb->core.tkwin)->mainPtr;\n\n\tif ((mainInfoPtr->nbTabPlacement & TTK_PACK_BOTTOM) ||\n\t    (mainInfoPtr->nbTabPlacement & TTK_PACK_RIGHT)) {\n\t    statefirst = TTK_STATE_LAST;\n\t    statelast = TTK_STATE_FIRST;\n\t}\n    }\n\n    /*\n     * Flip First/last if tabs are on the bottom or right side.\n     */\n    \n    if (index == nb->notebook.currentIndex) {\n\tstate |= TTK_STATE_SELECTED;\n    } else {\n\tstate &= ~TTK_STATE_FOCUS;\n    }\n\n    if (index == nb->notebook.activeIndex) {\n\tstate |= TTK_STATE_ACTIVE;\n    }\n    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);\n\tif (tab->state == TAB_STATE_HIDDEN) {\n\t    continue;\n\t}\n\tif (index == i) {\n\t    state |= statefirst;\n\t}\n\tbreak;\n    }\n    for (i = Ttk_NumberContent(nb->notebook.mgr) - 1; i >= 0; --i) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);\n\tif (tab->state == TAB_STATE_HIDDEN) {\n\t    continue;\n\t}\n\tif (index == i) {\n\t    state |= statelast;\n\t}\n\tbreak;\n    }\n    if (itab->state == TAB_STATE_DISABLED) {\n\tstate |= TTK_STATE_DISABLED;\n    }\n\n    return state;\n}\n\n/*------------------------------------------------------------------------\n * +++ Geometry management - size computation.\n */\n\n/* TabrowSize --\n *\tCompute max height and total width of all tabs (horizontal layouts)\n *\tor total height and max width (vertical layouts).\n *\tThe -mintabwidth style option is taken into account (for the width\n *\tonly).\n *\n * Side effects:\n *\tSets width and height fields for all tabs.\n *\n * Notes:\n *\tHidden tabs are included in the perpendicular computation\n *\t(max height/width) but not parallel (total width/height).\n */\nstatic void TabrowSize(\n    Notebook *nb, Ttk_Orient orient, int minTabWidth, int *widthPtr, int *heightPtr)\n{\n    Ttk_Layout tabLayout = nb->notebook.tabLayout;\n    int tabrowWidth = 0, tabrowHeight = 0;\n    Tcl_Size i;\n\n    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);\n\tTtk_State tabState = TabState(nb,i);\n\n\tTtk_RebindSublayout(tabLayout, tab);\n\tTtk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height);\n\ttab->width = MAX(tab->width, minTabWidth);\n\n\tif (orient == TTK_ORIENT_HORIZONTAL) {\n\t    tabrowHeight = MAX(tabrowHeight, tab->height);\n\t    if (tab->state != TAB_STATE_HIDDEN) { tabrowWidth += tab->width; }\n\t} else {\n\t    tabrowWidth = MAX(tabrowWidth, tab->width);\n\t    if (tab->state != TAB_STATE_HIDDEN) { tabrowHeight += tab->height; }\n\t}\n    }\n\n    *widthPtr = tabrowWidth;\n    *heightPtr = tabrowHeight;\n}\n\n/* NotebookSize -- GM and widget size hook.\n *\n * Total height is tab height + client area height + pane internal padding\n * Total width is max(client width, tab width) + pane internal padding\n * Client area size determined by max size of content windows,\n * overridden by -width and/or -height if nonzero.\n */\n\nstatic int NotebookSize(void *clientData, int *widthPtr, int *heightPtr)\n{\n    Notebook *nb = (Notebook *)clientData;\n    Tk_Window nbwin = nb->core.tkwin;\n    NotebookStyle nbstyle;\n    Ttk_Padding padding;\n    Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, \"client\");\n    int clientWidth = 0, clientHeight = 0,\n\treqWidth = 0, reqHeight = 0,\n\ttabrowWidth = 0, tabrowHeight = 0;\n    Tcl_Size i;\n\n    NotebookStyleOptions(nb, &nbstyle, nbwin);\n\n    /* Compute max requested size of all content windows:\n     */\n    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {\n\tTk_Window window = Ttk_ContentWindow(nb->notebook.mgr, i);\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);\n\tint width\n\t    = Tk_ReqWidth(window) + Ttk_PaddingWidth(tab->padding);\n\tint height\n\t    = Tk_ReqHeight(window) + Ttk_PaddingHeight(tab->padding);\n\n\tclientWidth = MAX(clientWidth, width);\n\tclientHeight = MAX(clientHeight, height);\n    }\n\n    /* Client width/height overridable by widget options:\n     */\n    Tk_GetPixelsFromObj(NULL, nbwin, nb->notebook.widthObj, &reqWidth);\n    Tk_GetPixelsFromObj(NULL, nbwin, nb->notebook.heightObj, &reqHeight);\n    if (reqWidth > 0) {\n\tclientWidth = reqWidth;\n    }\n    if (reqHeight > 0) {\n\tclientHeight = reqHeight;\n    }\n\n    /* Tab row:\n     */\n    TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight);\n    tabrowHeight += Ttk_PaddingHeight(nbstyle.tabMargins);\n    tabrowWidth += Ttk_PaddingWidth(nbstyle.tabMargins);\n\n    /* Account for exterior and interior padding:\n     */\n    padding = nbstyle.padding;\n    if (clientNode) {\n\tTtk_Padding ipad =\n\t    Ttk_LayoutNodeInternalPadding(nb->core.layout, clientNode);\n\tpadding = Ttk_AddPadding(padding, ipad);\n    }\n\n    if (nbstyle.tabPosition & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {\n\t*widthPtr = MAX(tabrowWidth, clientWidth) + Ttk_PaddingWidth(padding);\n\t*heightPtr = tabrowHeight + clientHeight + Ttk_PaddingHeight(padding);\n    } else {\n\t*widthPtr = tabrowWidth + clientWidth + Ttk_PaddingWidth(padding);\n\t*heightPtr = MAX(tabrowHeight,clientHeight) + Ttk_PaddingHeight(padding);\n    }\n\n    return 1;\n}\n\n/*------------------------------------------------------------------------\n * +++ Geometry management - layout.\n */\n\n/* SqueezeTabs --\n *\tSqueeze or stretch tabs to fit within the tab area parcel.\n *\tThis happens independently of the -mintabwidth style option.\n *\n *\tAll tabs are adjusted by an equal amount.\n *\n * @@@ <<NOTE-TABPOSITION>> bug: only works for horizontal orientations\n * @@@ <<NOTE-SQUEEZE-HIDDEN>> does not account for hidden tabs.\n */\n\nstatic void SqueezeTabs(\n    Notebook *nb, int needed, int available)\n{\n    Tcl_Size nTabs = Ttk_NumberContent(nb->notebook.mgr);\n\n    if (nTabs > 0) {\n\tint difference = available - needed;\n\tdouble delta = (double)difference / (double)needed;\n\tdouble slack = 0;\n\tTcl_Size i;\n\n\tfor (i = 0; i < nTabs; ++i) {\n\t    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr,i);\n\t    double ad = slack + tab->width * delta;\n\t    tab->width += (int)ad;\n\t    slack = ad - (int)ad;\n\t}\n    }\n}\n\n/* PlaceTabs --\n *\tCompute all tab parcels.\n */\nstatic void PlaceTabs(\n    Notebook *nb, Ttk_Box tabrowBox, Ttk_PositionSpec tabPlacement)\n{\n    Ttk_Layout tabLayout = nb->notebook.tabLayout;\n    Tcl_Size nTabs = Ttk_NumberContent(nb->notebook.mgr);\n    Tcl_Size i;\n\n    for (i = 0; i < nTabs; ++i) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);\n\tTtk_State tabState = TabState(nb, i);\n\n\tif (tab->state != TAB_STATE_HIDDEN) {\n\t    Ttk_Padding expand = Ttk_UniformPadding(0);\n\t    Tcl_Obj *expandObj = Ttk_QueryOption(tabLayout,\"-expand\",tabState);\n\n\t    if (expandObj) {\n\t\tTtk_GetPaddingFromObj(NULL, nb->core.tkwin, expandObj, &expand);\n\t    }\n\n\t    tab->parcel =\n\t\tTtk_ExpandBox(\n\t\t    Ttk_PositionBox(&tabrowBox,\n\t\t\ttab->width, tab->height, tabPlacement),\n\t\t    expand);\n\t}\n    }\n}\n\n/*\n * NotebookPlaceContent --\n *\tSet the position and size of a child widget\n *\tbased on the current client area and content window options:\n */\nstatic void NotebookPlaceContent(Notebook* nb, Tcl_Size index)\n{\n    Tab* tab = (Tab*)Ttk_ContentData(nb->notebook.mgr, index);\n    Tk_Window window = Ttk_ContentWindow(nb->notebook.mgr, index);\n    Ttk_Box box =\n\tTtk_StickBox(Ttk_PadBox(nb->notebook.clientArea, tab->padding),\n\t    Tk_ReqWidth(window), Tk_ReqHeight(window), tab->sticky);\n\n    Ttk_PlaceContent(nb->notebook.mgr, index,\n\tbox.x, box.y, box.width, box.height);\n}\n\n/* NotebookDoLayout --\n *\tComputes notebook layout and places tabs.\n *\n * Side effects:\n *\tSets clientArea, used to place panes.\n */\nstatic void NotebookDoLayout(void *recordPtr)\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tk_Window nbwin = nb->core.tkwin;\n    Ttk_Box cavity = Ttk_WinBox(nbwin);\n    int tabrowWidth = 0, tabrowHeight = 0;\n    Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, \"client\");\n    Ttk_Box tabrowBox;\n    NotebookStyle nbstyle;\n    Tcl_Size currentIndex = nb->notebook.currentIndex;\n\n    NotebookStyleOptions(nb, &nbstyle, nbwin);\n\n    /* Notebook internal padding:\n     */\n    cavity = Ttk_PadBox(cavity, nbstyle.padding);\n\n    /* Layout for notebook background (base layout):\n     */\n    Ttk_PlaceLayout(nb->core.layout, nb->core.state, Ttk_WinBox(nbwin));\n\n    /* Place tabs:\n     * Note: TabrowSize() takes into account -mintabwidth, but the tabs will\n     * actually have this minimum size when displayed only if there is enough\n     * space to draw the tabs with this width. Otherwise some of the tabs can\n     * be squeezed to a size smaller than -mintabwidth because we prefer\n     * displaying all tabs than than honoring -mintabwidth for all of them.\n     */\n    TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight);\n    tabrowBox = Ttk_PadBox(\n\t\t    Ttk_PositionBox(&cavity,\n\t\t\ttabrowWidth + Ttk_PaddingWidth(nbstyle.tabMargins),\n\t\t\ttabrowHeight + Ttk_PaddingHeight(nbstyle.tabMargins),\n\t\t\tnbstyle.tabPosition),\n\t\t    nbstyle.tabMargins);\n\n    SqueezeTabs(nb, tabrowWidth, tabrowBox.width);\n    PlaceTabs(nb, tabrowBox, nbstyle.tabPlacement);\n\n    /* Layout for client area frame:\n     */\n    if (clientNode) {\n\tTtk_PlaceElement(nb->core.layout, clientNode, cavity);\n\tcavity = Ttk_LayoutNodeInternalParcel(nb->core.layout, clientNode);\n    }\n\n    if (cavity.height <= 0) cavity.height = 1;\n    if (cavity.width <= 0) cavity.width = 1;\n\n    if (!TtkBoxEqual(nb->notebook.clientArea, cavity)) {\n\tnb->notebook.clientArea = cavity;\n\tif (currentIndex >= 0) {\n\t    NotebookPlaceContent(nb, currentIndex);\n\t}\n    }\n}\n\n/* NotebookPlaceContents --\n *\tGeometry manager hook.\n */\nstatic void NotebookPlaceContents(void *recordPtr)\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tcl_Size currentIndex = nb->notebook.currentIndex;\n    if (currentIndex >= 0) {\n\tNotebookDoLayout(nb);\n\tNotebookPlaceContent(nb, currentIndex);\n    }\n}\n\n/*\n * SelectTab(nb, index) --\n *\tChange the currently-selected tab.\n */\nstatic void SelectTab(Notebook *nb, Tcl_Size index)\n{\n    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n    Tcl_Size currentIndex = nb->notebook.currentIndex;\n\n    if (index == currentIndex) {\n\treturn;\n    }\n\n    if (TabState(nb, index) & TTK_STATE_DISABLED) {\n\treturn;\n    }\n\n    /* Unhide the tab if it is currently hidden and being selected.\n     */\n    if (tab->state == TAB_STATE_HIDDEN) {\n\ttab->state = TAB_STATE_NORMAL;\n    }\n\n    if (currentIndex >= 0) {\n\tTtk_UnmapContent(nb->notebook.mgr, currentIndex);\n    }\n\n    /* Must be set before calling NotebookPlaceContent(), otherwise it may\n     * happen that NotebookPlaceContents(), triggered by an interveaning\n     * geometry request, will swap to old index. */\n    nb->notebook.currentIndex = index;\n\n    NotebookPlaceContent(nb, index);\n    TtkRedisplayWidget(&nb->core);\n\n    Tk_SendVirtualEvent(nb->core.tkwin, \"NotebookTabChanged\", NULL);\n}\n\n/* NextTab --\n *\tReturns the index of the next tab after the specified tab\n *\tin the normal state (e.g., not hidden or disabled),\n *\tor -1 if all tabs are disabled or hidden.\n */\nstatic Tcl_Size NextTab(Notebook *nb, Tcl_Size index)\n{\n    Tcl_Size nTabs = Ttk_NumberContent(nb->notebook.mgr);\n    Tcl_Size nextIndex;\n\n    /* Scan forward for following usable tab:\n     */\n    for (nextIndex = index + 1; nextIndex < nTabs; ++nextIndex) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, nextIndex);\n\tif (tab->state == TAB_STATE_NORMAL) {\n\t    return nextIndex;\n\t}\n    }\n\n    /* Not found -- scan backwards.\n     */\n    for (nextIndex = index - 1; nextIndex >= 0; --nextIndex) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, nextIndex);\n\tif (tab->state == TAB_STATE_NORMAL) {\n\t    return nextIndex;\n\t}\n    }\n\n    /* Still nothing.  Give up.\n     */\n    return -1;\n}\n\n/* SelectNearestTab --\n *\tHandles the case where the current tab is forgotten, hidden,\n *\tor destroyed.\n *\n *\tUnmap the current tab and schedule the next available one\n *\tto be mapped at the next GM update.\n */\nstatic void SelectNearestTab(Notebook *nb)\n{\n    Tcl_Size currentIndex = nb->notebook.currentIndex;\n    Tcl_Size nextIndex = NextTab(nb, currentIndex);\n\n    if (currentIndex >= 0) {\n\tTtk_UnmapContent(nb->notebook.mgr, currentIndex);\n    }\n    if (currentIndex != nextIndex) {\n\tTk_SendVirtualEvent(nb->core.tkwin, \"NotebookTabChanged\", NULL);\n    }\n\n    nb->notebook.currentIndex = nextIndex;\n    Ttk_ManagerLayoutChanged(nb->notebook.mgr);\n    TtkRedisplayWidget(&nb->core);\n}\n\n/* TabRemoved -- GM TabRemoved hook.\n *\tSelect the next tab if the current one is being removed.\n *\tAdjust currentIndex to account for removed content window.\n */\nstatic void TabRemoved(void *managerData, Tcl_Size index)\n{\n    Notebook *nb = (Notebook *)managerData;\n    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n\n    if (index == nb->notebook.currentIndex) {\n\tSelectNearestTab(nb);\n    }\n\n    if (index < nb->notebook.currentIndex) {\n\t--nb->notebook.currentIndex;\n    }\n\n    DestroyTab(nb, tab);\n\n    TtkRedisplayWidget(&nb->core);\n}\n\nstatic int TabRequest(\n    TCL_UNUSED(void *), /* managerData */\n    TCL_UNUSED(Tcl_Size), /* index */\n    TCL_UNUSED(int), /* width */\n    TCL_UNUSED(int)) /* height */\n{\n    return 1;\n}\n\n/* AddTab --\n *\tAdd new tab at specified index.\n */\nstatic int AddTab(\n    Tcl_Interp *interp, Notebook *nb,\n    Tcl_Size destIndex, Tk_Window window,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tab *tab;\n    if (!Ttk_Maintainable(interp, window, nb->core.tkwin)) {\n\treturn TCL_ERROR;\n    }\n#if 0 /* can't happen */\n    if (Ttk_ContentIndex(nb->notebook.mgr, window) >= 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%s already added\",\n\t    Tk_PathName(window)));\n\tTcl_SetErrorCode(interp, \"TTK\", \"NOTEBOOK\", \"PRESENT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n#endif\n\n    /* Create and insert tab.\n     */\n    tab = CreateTab(interp, nb, window);\n    if (!tab) {\n\treturn TCL_ERROR;\n    }\n    if (ConfigureTab(interp, nb, tab, window, objc, objv) != TCL_OK) {\n\tDestroyTab(nb, tab);\n\treturn TCL_ERROR;\n    }\n\n    Ttk_InsertContent(nb->notebook.mgr, destIndex, window, tab);\n\n    /* Adjust indices and/or autoselect first tab:\n     */\n    if (nb->notebook.currentIndex < 0) {\n\tSelectTab(nb, destIndex);\n    } else if (nb->notebook.currentIndex  >= destIndex) {\n\t++nb->notebook.currentIndex;\n    }\n\n    return TCL_OK;\n}\n\nstatic const Ttk_ManagerSpec NotebookManagerSpec = {\n    { \"notebook\", Ttk_GeometryRequestProc, Ttk_LostContentProc },\n    NotebookSize,\n    NotebookPlaceContents,\n    TabRequest,\n    TabRemoved\n};\n\n/*------------------------------------------------------------------------\n * +++ Event handlers.\n */\n\n/* NotebookEventHandler --\n *\tTracks the active tab.\n */\nstatic const int NotebookEventMask\n    = StructureNotifyMask\n    | PointerMotionMask\n    | LeaveWindowMask\n    ;\nstatic void NotebookEventHandler(void *clientData, XEvent *eventPtr)\n{\n    Notebook *nb = (Notebook *)clientData;\n\n    if (eventPtr->type == DestroyNotify) { /* Remove self */\n\tTk_DeleteEventHandler(nb->core.tkwin,\n\t    NotebookEventMask, NotebookEventHandler, clientData);\n    } else if (eventPtr->type == MotionNotify) {\n\tTcl_Size index = IdentifyTab(nb, eventPtr->xmotion.x, eventPtr->xmotion.y);\n\tActivateTab(nb, index);\n    } else if (eventPtr->type == LeaveNotify) {\n\tActivateTab(nb, -1);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Utilities.\n */\n\n/* FindTabIndex --\n *\tFind the index of the specified tab.\n *\tTab identifiers are one of:\n *\n *\t+ positional specifications @x,y,\n *\t+ \"current\",\n *\t+ numeric indices [0..nTabs],\n *\t+ content window names\n *\n *\tStores index of specified tab in *index_rtn, -1 if not found.\n *\n *\tReturns TCL_ERROR and leaves an error message in interp->result\n *\tif the tab identifier was incorrect.\n *\n *\tSee also: GetTabIndex.\n */\nstatic int FindTabIndex(\n    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, Tcl_Size *index_rtn)\n{\n    const char *string = Tcl_GetString(objPtr);\n    int x, y;\n\n    *index_rtn = TCL_INDEX_NONE;\n\n    /* Check for @x,y ...\n     */\n    if (string[0] == '@' && sscanf(string, \"@%d,%d\",&x,&y) == 2) {\n\t*index_rtn = IdentifyTab(nb, x, y);\n\treturn TCL_OK;\n    }\n\n    /* ... or \"current\" ...\n     */\n    if (!strcmp(string, \"current\")) {\n\t*index_rtn = nb->notebook.currentIndex;\n\treturn TCL_OK;\n    }\n\n    /* ... or integer index or content window name:\n     */\n    if (Ttk_GetContentIndexFromObj(\n\t    interp, nb->notebook.mgr, objPtr, 1, index_rtn) == TCL_OK)\n    {\n\treturn TCL_OK;\n    }\n    if (*index_rtn == Ttk_NumberContent(nb->notebook.mgr)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Invalid tab specification %s\", string));\n\tTcl_SetErrorCode(interp, \"TTK\", \"NOTEBOOK\", \"SPEC\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* Nothing matched; Ttk_GetContentIndexFromObj will have left error message.\n     */\n    return TCL_ERROR;\n}\n\n/* GetTabIndex --\n *\tGet the index of an existing tab.\n *\tTab identifiers are as per FindTabIndex.\n *\tReturns TCL_ERROR if the tab does not exist.\n */\nstatic int GetTabIndex(\n    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, Tcl_Size *index_rtn)\n{\n    int status = FindTabIndex(interp, nb, objPtr, index_rtn);\n\tif (status == TCL_OK && *index_rtn  >= Ttk_NumberContent(nb->notebook.mgr)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Tab index \\\"%s\\\" out of bounds\", Tcl_GetString(objPtr)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"NOTEBOOK\", \"INDEX\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n    if (status == TCL_OK && *index_rtn < 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"Tab '%s' not found\", Tcl_GetString(objPtr)));\n\tTcl_SetErrorCode(interp, \"TTK\", \"NOTEBOOK\", \"TAB\", (char *)NULL);\n\tstatus = TCL_ERROR;\n    }\n    return status;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget command routines.\n */\n\n/* $nb add window ?options ... ?\n */\nstatic int NotebookAddCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tk_Window window;\n    Tcl_Size index;\n    Tab *tab;\n\n    if (objc <= 2 || objc % 2 != 1) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    window = Tk_NameToWindow(interp,Tcl_GetString(objv[2]),nb->core.tkwin);\n    if (!window) {\n\treturn TCL_ERROR;\n    }\n    index = Ttk_ContentIndex(nb->notebook.mgr, window);\n\n    if (index < 0) { /* New tab */\n\treturn AddTab(interp, nb, Ttk_NumberContent(nb->notebook.mgr), window, objc-3,objv+3);\n    }\n\n    tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n    if (tab->state == TAB_STATE_HIDDEN) {\n\ttab->state = TAB_STATE_NORMAL;\n    }\n    if (ConfigureTab(interp, nb, tab, window, objc-3,objv+3) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    TtkRedisplayWidget(&nb->core);\n\n    return TCL_OK;\n}\n\n/* $nb insert $index $tab ?-option value ...?\n *\tInsert new tab, or move existing one.\n */\nstatic int NotebookInsertCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tcl_Size current = nb->notebook.currentIndex;\n    Tcl_Size nContent = Ttk_NumberContent(nb->notebook.mgr);\n    Tcl_Size srcIndex, destIndex;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"index window ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetString(objv[3])[0] == '.') {\n\t/* Window name -- could be new or existing content window.\n\t */\n\tTk_Window window =\n\t    Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin);\n\n\tif (!window) {\n\t    return TCL_ERROR;\n\t}\n\n\tsrcIndex = Ttk_ContentIndex(nb->notebook.mgr, window);\n\tif (srcIndex < 0) {\t/* New content window */\n\t    if (TCL_OK != Ttk_GetContentIndexFromObj(\n\t\tinterp, nb->notebook.mgr, objv[2], 1, &destIndex)) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    return AddTab(interp, nb, destIndex, window, objc-4,objv+4);\n\t}\n    } else if (Ttk_GetContentIndexFromObj(\n\t\tinterp, nb->notebook.mgr, objv[3], 0, &srcIndex) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    } else if (srcIndex  >= Ttk_NumberContent(nb->notebook.mgr)) {\n\tsrcIndex = Ttk_NumberContent(nb->notebook.mgr) - 1;\n    }\n\n    if (TCL_OK != Ttk_GetContentIndexFromObj(\n\tinterp, nb->notebook.mgr, objv[2], 0, &destIndex)) {\n\treturn TCL_ERROR;\n    }\n\n    /* Move existing content window:\n     */\n    if (ConfigureTab(interp, nb,\n\t     (Tab *)Ttk_ContentData(nb->notebook.mgr, srcIndex),\n\t\t Ttk_ContentWindow(nb->notebook.mgr, srcIndex),\n\t     objc-4,objv+4) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    if (destIndex  >= nContent) {\n\tdestIndex  = nContent - 1;\n    }\n    Ttk_ReorderContent(nb->notebook.mgr, srcIndex, destIndex);\n\n    /* Adjust internal indexes:\n     */\n    nb->notebook.activeIndex = TCL_INDEX_NONE;\n    if (current == srcIndex) {\n\tnb->notebook.currentIndex = destIndex;\n    } else if (destIndex <= current && current < srcIndex) {\n\t++nb->notebook.currentIndex;\n    } else if (srcIndex < current && current <= destIndex) {\n\t--nb->notebook.currentIndex;\n    }\n\n    TtkRedisplayWidget(&nb->core);\n\n    return TCL_OK;\n}\n\n/* $nb forget $tab --\n *\tRemoves the specified tab.\n */\nstatic int NotebookForgetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tcl_Size index;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"tab\");\n\treturn TCL_ERROR;\n    }\n\n    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    Ttk_ForgetContent(nb->notebook.mgr, index);\n    TtkRedisplayWidget(&nb->core);\n\n    return TCL_OK;\n}\n\n/* $nb hide $tab --\n *\tHides the specified tab.\n */\nstatic int NotebookHideCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tcl_Size index;\n    Tab *tab;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"tab\");\n\treturn TCL_ERROR;\n    }\n\n    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n    tab->state = TAB_STATE_HIDDEN;\n    if (index == nb->notebook.currentIndex) {\n\tSelectNearestTab(nb);\n    } else {\n\tTtkRedisplayWidget(&nb->core);\n    }\n\n    return TCL_OK;\n}\n\n/* $nb identify $x $y --\n *\tReturns name of tab element at $x,$y; empty string if none.\n */\nstatic int NotebookIdentifyCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    static const char *const whatTable[] = { \"element\", \"tab\", NULL };\n    enum { IDENTIFY_ELEMENT, IDENTIFY_TAB };\n    int what = IDENTIFY_ELEMENT;\n    Notebook *nb = (Notebook *)recordPtr;\n    Ttk_Element element = NULL;\n    int x, y;\n    Tcl_Size tabIndex;\n\n    if (objc < 4 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"?what? x y\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK\n\t|| Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK\n\t|| (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,\n\t\tsizeof(char *), \"option\", 0, &what) != TCL_OK)\n    ) {\n\treturn TCL_ERROR;\n    }\n\n    tabIndex = IdentifyTab(nb, x, y);\n    if (tabIndex >= 0) {\n\tTab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, tabIndex);\n\tTtk_State state = TabState(nb, tabIndex);\n\tTtk_Layout tabLayout = nb->notebook.tabLayout;\n\n\tTtk_RebindSublayout(tabLayout, tab);\n\tTtk_PlaceLayout(tabLayout, state, tab->parcel);\n\n\telement = Ttk_IdentifyElement(tabLayout, x, y);\n    }\n\n    switch (what) {\n\tcase IDENTIFY_ELEMENT:\n\t    if (element) {\n\t\tconst char *elementName = Ttk_ElementName(element);\n\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));\n\t    }\n\t    break;\n\tcase IDENTIFY_TAB:\n\t    if (tabIndex >= 0) {\n\t\tTcl_SetObjResult(interp, TkNewIndexObj(tabIndex));\n\t    }\n\t    break;\n    }\n    return TCL_OK;\n}\n\n/* $nb index $item --\n *\tReturns the integer index of the tab specified by $item,\n *\tthe empty string if $item does not identify a tab.\n *\tSee above for valid item formats.\n */\nstatic int NotebookIndexCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Tcl_Size index;\n    int status;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"tab\");\n\treturn TCL_ERROR;\n    }\n\n    status = FindTabIndex(interp, nb, objv[2], &index);\n\tif (status == TCL_OK) {\n\t    if (index >= 0) {\n\t\tTcl_SetObjResult(interp, TkNewIndexObj(index));\n\t    }\n    }\n\n    return status;\n}\n\n/* $nb select ?$item? --\n *\tSelect the specified tab, or return the widget path of\n *\tthe currently-selected pane.\n */\nstatic int NotebookSelectCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n\n    if (objc == 2) {\n\tif (nb->notebook.currentIndex >= 0) {\n\t    Tk_Window pane = Ttk_ContentWindow(\n\t\tnb->notebook.mgr, nb->notebook.currentIndex);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(pane), -1));\n\t}\n\treturn TCL_OK;\n    } else if (objc == 3) {\n\tTcl_Size index;\n\tint status = GetTabIndex(interp, nb, objv[2], &index);\n\tif (status == TCL_OK) {\n\t    SelectTab(nb, index);\n\t}\n\treturn status;\n    } /*else*/\n    Tcl_WrongNumArgs(interp, 2, objv, \"?tab?\");\n    return TCL_ERROR;\n}\n\n/* $nb tabs --\n *\tReturn list of tabs.\n */\nstatic int NotebookTabsCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Ttk_Manager *mgr = nb->notebook.mgr;\n    Tcl_Obj *result;\n    Tcl_Size i;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    result = Tcl_NewListObj(0, NULL);\n    for (i = 0; i < Ttk_NumberContent(mgr); ++i) {\n\tconst char *pathName = Tk_PathName(Ttk_ContentWindow(mgr,i));\n\n\tTcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(pathName,-1));\n    }\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\n/* $nb tab $tab ?-option ?value -option value...??\n */\nstatic int NotebookTabCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Ttk_Manager *mgr = nb->notebook.mgr;\n    Tcl_Size index;\n    Tk_Window window;\n    Tab *tab;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"tab ?-option ?value??...\");\n\treturn TCL_ERROR;\n    }\n\n    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    tab = (Tab *)Ttk_ContentData(mgr, index);\n    window = Ttk_ContentWindow(mgr, index);\n\n    if (objc == 3) {\n\treturn TtkEnumerateOptions(interp, tab,\n\t    PaneOptionSpecs, nb->notebook.paneOptionTable, window);\n    } else if (objc == 4) {\n\treturn TtkGetOptionValue(interp, tab, objv[3],\n\t    nb->notebook.paneOptionTable, window);\n    } /* else */\n\n    if (ConfigureTab(interp, nb, tab, window, objc-3,objv+3) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /* If the current tab has become disabled or hidden,\n     * select the next nondisabled, unhidden one:\n     */\n    if (index == nb->notebook.currentIndex && tab->state != TAB_STATE_NORMAL) {\n\tSelectNearestTab(nb);\n    }\n\n    return TCL_OK;\n}\n\n/* Subcommand table:\n */\nstatic const Ttk_Ensemble NotebookCommands[] = {\n    { \"add\",\t\tNotebookAddCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"forget\",\t\tNotebookForgetCommand,0 },\n    { \"hide\",\t\tNotebookHideCommand,0 },\n    { \"identify\",\tNotebookIdentifyCommand,0 },\n    { \"index\",\t\tNotebookIndexCommand,0 },\n    { \"insert\",\t\tNotebookInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"select\",\t\tNotebookSelectCommand,0 },\n    { \"state\",\t\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { \"tab\",\t\tNotebookTabCommand,0 },\n    { \"tabs\",\t\tNotebookTabsCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget class hooks.\n */\n\nstatic void NotebookInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Notebook *nb = (Notebook *)recordPtr;\n\n    nb->notebook.mgr = Ttk_CreateManager(\n\t    &NotebookManagerSpec, recordPtr, nb->core.tkwin);\n\n    nb->notebook.tabOptionTable = Tk_CreateOptionTable(interp,TabOptionSpecs);\n    nb->notebook.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);\n\n    nb->notebook.currentIndex = TCL_INDEX_NONE;\n    nb->notebook.activeIndex = TCL_INDEX_NONE;\n    nb->notebook.tabLayout = 0;\n\n    nb->notebook.clientArea = Ttk_MakeBox(0,0,1,1);\n\n    Tk_CreateEventHandler(\n\tnb->core.tkwin, NotebookEventMask, NotebookEventHandler, recordPtr);\n}\n\nstatic void NotebookCleanup(void *recordPtr)\n{\n    Notebook *nb = (Notebook *)recordPtr;\n\n    Ttk_DeleteManager(nb->notebook.mgr);\n    if (nb->notebook.tabLayout) {\n\tTtk_FreeLayout(nb->notebook.tabLayout);\n    }\n}\n\nstatic int NotebookConfigure(Tcl_Interp *interp, void *clientData, int mask)\n{\n    Notebook *nb = (Notebook *)clientData;\n\n    /*\n     * Error-checks:\n     */\n    if (nb->notebook.paddingObj) {\n\t/* Check for valid -padding: */\n\tTtk_Padding unused;\n\tif (Ttk_GetPaddingFromObj(\n\t\t    interp, nb->core.tkwin, nb->notebook.paddingObj, &unused)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    return TtkCoreConfigure(interp, clientData, mask);\n}\n\n/* NotebookGetLayout  --\n *\tGetLayout widget hook.\n */\nstatic Ttk_Layout NotebookGetLayout(\n    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Notebook *nb = (Notebook *)recordPtr;\n    Ttk_Layout notebookLayout = TtkWidgetGetLayout(interp, theme, recordPtr);\n    Ttk_Layout tabLayout;\n\n    if (!notebookLayout) {\n\treturn NULL;\n    }\n\n    tabLayout = Ttk_CreateSublayout(\n\tinterp, theme, notebookLayout, \".Tab\",\tnb->notebook.tabOptionTable);\n\n    if (tabLayout) {\n\tif (nb->notebook.tabLayout) {\n\t    Ttk_FreeLayout(nb->notebook.tabLayout);\n\t}\n\tnb->notebook.tabLayout = tabLayout;\n    }\n\n    return notebookLayout;\n}\n\n/*------------------------------------------------------------------------\n * +++ Display routines.\n */\n\nstatic void DisplayTab(Notebook *nb, Tcl_Size index, Drawable d)\n{\n    Ttk_Layout tabLayout = nb->notebook.tabLayout;\n    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);\n    Ttk_State state = TabState(nb, index);\n\n    if (tab->state != TAB_STATE_HIDDEN) {\n\tTtk_RebindSublayout(tabLayout, tab);\n\tTtk_PlaceLayout(tabLayout, state, tab->parcel);\n\tTtk_DrawLayout(tabLayout, state, d);\n    }\n}\n\nstatic void NotebookDisplay(void *clientData, Drawable d)\n{\n    Notebook *nb = (Notebook *)clientData;\n    Tcl_Size nContent = Ttk_NumberContent(nb->notebook.mgr);\n    Tcl_Size index;\n\n    /* Draw notebook background (base layout):\n     */\n    Ttk_DrawLayout(nb->core.layout, nb->core.state, d);\n\n    /* Draw tabs from left to right, but draw the current tab last\n     * so it will overwrite its neighbors.\n     */\n    for (index = 0; index < nContent; ++index) {\n\tif (index != nb->notebook.currentIndex) {\n\t    DisplayTab(nb, index, d);\n\t}\n    }\n    if (nb->notebook.currentIndex >= 0) {\n\tDisplayTab(nb, nb->notebook.currentIndex, d);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget specification and layout definitions.\n */\n\nstatic const WidgetSpec NotebookWidgetSpec =\n{\n    \"TNotebook\",\t\t/* className */\n    sizeof(Notebook),\t\t/* recordSize */\n    NotebookOptionSpecs,\t/* optionSpecs */\n    NotebookCommands,\t\t/* subcommands */\n    NotebookInitialize,\t\t/* initializeProc */\n    NotebookCleanup,\t\t/* cleanupProc */\n    NotebookConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    NotebookGetLayout,\t\t/* getLayoutProc */\n    NotebookSize,\t\t/* geometryProc */\n    NotebookDoLayout,\t\t/* layoutProc */\n    NotebookDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(NotebookLayout)\n    TTK_NODE(\"Notebook.client\", TTK_FILL_BOTH)\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(TabLayout)\n    TTK_GROUP(\"Notebook.tab\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Notebook.padding\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Notebook.focus\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Notebook.label\", TTK_FILL_BOTH))))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkNotebook_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(themePtr, \"Tab\", TabLayout);\n    Ttk_RegisterLayout(themePtr, \"TNotebook\", NotebookLayout);\n\n    RegisterWidget(interp, \"ttk::notebook\", &NotebookWidgetSpec);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkPanedwindow.c",
    "content": "/*\n * Copyright © 2005 Joe English.  Freely redistributable.\n *\n * ttk::panedwindow widget implementation.\n *\n * TODO: track active/pressed sash.\n */\n\n#include \"tkInt.h\"\n#include \"ttkManager.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*------------------------------------------------------------------------\n * +++ Layout algorithm.\n *\n * (pos=x/y, size=width/height, depending on -orient=horizontal/vertical)\n *\n * Each pane carries two pieces of state: the request size and the\n * position of the following sash.  (The final pane has no sash,\n * its sash position is used as a sentinel value).\n *\n * Pane geometry is determined by the sash positions.\n * When resizing, sash positions are computed from the request sizes,\n * the available space, and pane weights (see PlaceSashes()).\n * This ensures continuous resize behavior (that is: changing\n * the size by X pixels then changing the size by Y pixels\n * gives the same result as changing the size by X+Y pixels\n * in one step).\n *\n * The request size is initially set to the content window's requested size.\n * When the user drags a sash, each pane's request size is set to its\n * actual size.  This ensures that panes \"stay put\" on the next resize.\n *\n * If reqSize == 0, use 0 for the weight as well.  This ensures that\n * \"collapsed\" panes stay collapsed during a resize, regardless of\n * their nominal -weight.\n *\n * +++ Invariants.\n *\n * #sash\t\t=  #pane - 1\n * pos(pane[0])\t=  0\n * pos(sash[i])\t=  pos(pane[i]) + size(pane[i]), 0 <= i <= #sash\n * pos(pane[i+1])\t=  pos(sash[i]) + size(sash[i]), 0 <= i <  #sash\n * pos(sash[#sash])\t=  size(pw)   // sentinel value, constraint\n *\n * size(pw)\t\t=  sum(size(pane(0..#pane))) + sum(size(sash(0..#sash)))\n * size(pane[i])\t>= 0,  for 0 <= i < #pane\n * size(sash[i])\t>= 0,  for 0 <= i < #sash\n * ==> pos(pane[i]) <= pos(sash[i]) <= pos(pane[i+1]), for 0 <= i < #sash\n *\n * Assumption: all sashes are the same size.\n */\n\n/*------------------------------------------------------------------------\n * +++ Widget record.\n */\n\ntypedef struct {\n    Tcl_Obj\t*orientObj;\n    int\torient;\n    int\twidth;\n    int\theight;\n    Ttk_Manager\t*mgr;\n    Tk_OptionTable paneOptionTable;\n    Ttk_Layout\tsashLayout;\n    int\tsashThickness;\n} PanedPart;\n\ntypedef struct {\n    WidgetCore\tcore;\n    PanedPart\tpaned;\n} Paned;\n\n/* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI\n */\nstatic const Tk_OptionSpec PanedOptionSpecs[] = {\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\", \"vertical\",\n\toffsetof(Paned,paned.orientObj), offsetof(Paned,paned.orient),\n\t0, ttkOrientStrings, READONLY_OPTION|STYLE_CHANGED },\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\", \"0\",\n\tTCL_INDEX_NONE, offsetof(Paned, paned.width),\n\t0, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_INT, \"-height\", \"height\", \"Height\", \"0\",\n\tTCL_INDEX_NONE, offsetof(Paned, paned.height),\n\t0, 0, GEOMETRY_CHANGED },\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ Pane record.\n */\ntypedef struct {\n    int\treqSize;\t\t/* Pane request size */\n    int\tsashPos;\t\t/* Folowing sash position */\n    int\tweight;\t\t/* Pane -weight, for resizing */\n} Pane;\n\nstatic const Tk_OptionSpec PaneOptionSpecs[] = {\n    {TK_OPTION_INT, \"-weight\", \"weight\", \"Weight\", \"0\",\n\tTCL_INDEX_NONE, offsetof(Pane,weight), 0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}\n};\n\n/* CreatePane --\n *\tCreate a new pane record.\n */\nstatic Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window window)\n{\n    Tk_OptionTable optionTable = pw->paned.paneOptionTable;\n    void *record = Tcl_Alloc(sizeof(Pane));\n    Pane *pane = (Pane *)record;\n\n    memset(record, 0, sizeof(Pane));\n    if (Tk_InitOptions(interp, record, optionTable, window) != TCL_OK) {\n\tTcl_Free(record);\n\treturn NULL;\n    }\n\n    pane->reqSize\n\t= pw->paned.orient == TTK_ORIENT_HORIZONTAL\n\t? Tk_ReqWidth(window) : Tk_ReqHeight(window);\n\n    return pane;\n}\n\n/* DestroyPane --\n *\tFree pane record.\n */\nstatic void DestroyPane(Paned *pw, Pane *pane)\n{\n    void *record = pane;\n    Tk_FreeConfigOptions(record, pw->paned.paneOptionTable, pw->core.tkwin);\n    Tcl_Free(record);\n}\n\n/* ConfigurePane --\n *\tSet pane options.\n */\nstatic int ConfigurePane(\n    Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window window,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Ttk_Manager *mgr = pw->paned.mgr;\n    Tk_SavedOptions savedOptions;\n    int mask = 0;\n\n    if (Tk_SetOptions(interp, pane, pw->paned.paneOptionTable,\n\t    objc, objv, window, &savedOptions, &mask) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    /* Sanity-check:\n     */\n    if (pane->weight < 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"-weight must be non-negative\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"PANE\", \"WEIGHT\", (char *)NULL);\n\tgoto error;\n    }\n\n    /* Done.\n     */\n    Tk_FreeSavedOptions(&savedOptions);\n    Ttk_ManagerSizeChanged(mgr);\n    return TCL_OK;\n\nerror:\n    Tk_RestoreSavedOptions(&savedOptions);\n    return TCL_ERROR;\n}\n\n\n/*------------------------------------------------------------------------\n * +++ Sash adjustment.\n */\n\n/* ShoveUp --\n *\tPlace sash i at specified position, recursively shoving\n *\tprevious sashes upwards as needed, until hitting the top\n *\tof the window.  If that happens, shove back down.\n *\n *\tReturns: final position of sash i.\n */\n\nstatic int ShoveUp(Paned *pw, int i, int pos)\n{\n    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, i);\n    int sashThickness = pw->paned.sashThickness;\n\n    if (i == 0) {\n\tif (pos < 0) {\n\t    pos = 0;\n\t}\n    } else {\n\tPane *prevPane = (Pane *)Ttk_ContentData(pw->paned.mgr, i-1);\n\tif (pos < prevPane->sashPos + sashThickness) {\n\t    pos = ShoveUp(pw, i-1, pos - sashThickness) + sashThickness;\n\t}\n    }\n    return pane->sashPos = pos;\n}\n\n/* ShoveDown --\n *\tSame as ShoveUp, but going in the opposite direction\n *\tand stopping at the sentinel sash.\n */\nstatic int ShoveDown(Paned *pw, Tcl_Size i, int pos)\n{\n    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr,i);\n    int sashThickness = pw->paned.sashThickness;\n\n    if (i == Ttk_NumberContent(pw->paned.mgr) - 1) {\n\tpos = pane->sashPos; /* Sentinel value == container window size */\n    } else {\n\tPane *nextPane = (Pane *)Ttk_ContentData(pw->paned.mgr,i+1);\n\tif (pos + sashThickness > nextPane->sashPos) {\n\t    pos = ShoveDown(pw, i+1, pos + sashThickness) - sashThickness;\n\t}\n    }\n    return pane->sashPos = pos;\n}\n\n/* PanedSize --\n *\tCompute the requested size of the paned widget\n *\tfrom the individual pane request sizes.\n *\n *\tUsed as the WidgetSpec sizeProc and the ManagerSpec sizeProc.\n */\nstatic int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr)\n{\n    Paned *pw = (Paned *)recordPtr;\n    int nPanes = Ttk_NumberContent(pw->paned.mgr);\n    int nSashes = nPanes - 1;\n    int sashThickness = pw->paned.sashThickness;\n    int width = 0, height = 0;\n    int index;\n\n    if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) {\n\tfor (index = 0; index < nPanes; ++index) {\n\t    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n\t    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);\n\n\t    if (height < Tk_ReqHeight(window)) {\n\t\theight = Tk_ReqHeight(window);\n\t    }\n\t    width += pane->reqSize;\n\t}\n\twidth += nSashes * sashThickness;\n    } else {\n\tfor (index = 0; index < nPanes; ++index) {\n\t    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n\t    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);\n\n\t    if (width < Tk_ReqWidth(window)) {\n\t\twidth = Tk_ReqWidth(window);\n\t    }\n\t    height += pane->reqSize;\n\t}\n\theight += nSashes * sashThickness;\n    }\n\n    *widthPtr = pw->paned.width > 0 ? pw->paned.width : width;\n    *heightPtr = pw->paned.height > 0 ? pw->paned.height : height;\n    return 1;\n}\n\n/* AdjustPanes --\n *\tSet pane request sizes from sash positions.\n *\n * NOTE:\n *\tAdjustPanes followed by PlaceSashes (called during relayout)\n *\twill leave the sashes in the same place, as long as available size\n *\tremains contant.\n */\nstatic void AdjustPanes(Paned *pw)\n{\n    int sashThickness = pw->paned.sashThickness;\n    int pos = 0;\n    Tcl_Size index;\n\n    for (index = 0; index < Ttk_NumberContent(pw->paned.mgr); ++index) {\n\tPane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n\tint size = pane->sashPos - pos;\n\tpane->reqSize = size >= 0 ? size : 0;\n\tpos = pane->sashPos + sashThickness;\n    }\n}\n\n/* PlaceSashes --\n *\tSet sash positions from pane request sizes and available space.\n *\tThe sentinel sash position is set to the available space.\n *\n *\tAllocate pane->reqSize pixels to each pane, and distribute\n *\tthe difference = available size - requested size according\n *\tto pane->weight.\n *\n *\tIf there's still some left over, squeeze panes from the bottom up\n *\t(This can happen if all weights are zero, or if one or more panes\n *\tare too small to absorb the required shrinkage).\n *\n * Notes:\n *\tThis doesn't distribute the remainder pixels as evenly as it could\n *\twhen more than one pane has weight > 1.\n */\nstatic void PlaceSashes(Paned *pw, int width, int height)\n{\n    Ttk_Manager *mgr = pw->paned.mgr;\n    int nPanes = Ttk_NumberContent(mgr);\n    int sashThickness = pw->paned.sashThickness;\n    int available = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? width : height;\n    int reqSize = 0, totalWeight = 0;\n    int difference, delta, remainder, pos, i;\n\n    if (nPanes == 0) {\n\treturn;\n    }\n\n    /* Compute total required size and total available weight:\n     */\n    for (i = 0; i < nPanes; ++i) {\n\tPane *pane = (Pane *)Ttk_ContentData(mgr, i);\n\treqSize += pane->reqSize;\n\ttotalWeight += pane->weight * (pane->reqSize != 0);\n    }\n\n    /* Compute difference to be redistributed:\n     */\n    difference = available - reqSize - sashThickness*(nPanes-1);\n    if (totalWeight != 0) {\n\tdelta = difference / totalWeight;\n\tremainder = difference % totalWeight;\n\tif (remainder < 0) {\n\t    --delta;\n\t    remainder += totalWeight;\n\t}\n    } else {\n\tdelta = remainder = 0;\n    }\n    /* ASSERT: 0 <= remainder < totalWeight */\n\n    /* Place sashes:\n     */\n    pos = 0;\n    for (i = 0; i < nPanes; ++i) {\n\tPane *pane = (Pane *)Ttk_ContentData(mgr, i);\n\tint weight = pane->weight * (pane->reqSize != 0);\n\tint size = pane->reqSize + delta * weight;\n\n\tif (weight > remainder) {\n\t    weight = remainder;\n\t}\n\tremainder -= weight;\n\tsize += weight;\n\n\tif (size < 0) {\n\t    size = 0;\n\t}\n\n\tpane->sashPos = (pos += size);\n\tpos += sashThickness;\n    }\n\n    /* Handle emergency shrink/emergency stretch:\n     * Set sentinel sash position to end of widget,\n     * shove preceding sashes up.\n     */\n    ShoveUp(pw, nPanes - 1, available);\n}\n\n/* PlacePanes --\n *\tPlaces panes based on sash positions.\n */\nstatic void PlacePanes(Paned *pw)\n{\n    int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;\n    int width = Tk_Width(pw->core.tkwin), height = Tk_Height(pw->core.tkwin);\n    int sashThickness = pw->paned.sashThickness;\n    int pos = 0;\n    Tcl_Size index;\n\n    for (index = 0; index < Ttk_NumberContent(pw->paned.mgr); ++index) {\n\tPane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n\tint size = pane->sashPos - pos;\n\n\tif (size > 0) {\n\t    if (horizontal) {\n\t\tTtk_PlaceContent(pw->paned.mgr, index, pos, 0, size, height);\n\t    } else {\n\t\tTtk_PlaceContent(pw->paned.mgr, index, 0, pos, width, size);\n\t    }\n\t} else {\n\t    Ttk_UnmapContent(pw->paned.mgr, index);\n\t}\n\n\tpos = pane->sashPos + sashThickness;\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Manager specification.\n */\n\nstatic void PanedPlaceContent(void *managerData)\n{\n    Paned *pw = (Paned *)managerData;\n    PlaceSashes(pw, Tk_Width(pw->core.tkwin), Tk_Height(pw->core.tkwin));\n    PlacePanes(pw);\n}\n\nstatic void PaneRemoved(void *managerData, Tcl_Size index)\n{\n    Paned *pw = (Paned *)managerData;\n    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n    DestroyPane(pw, pane);\n}\n\nstatic int AddPane(\n    Tcl_Interp *interp, Paned *pw,\n    int destIndex, Tk_Window window,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Pane *pane;\n    if (!Ttk_Maintainable(interp, window, pw->core.tkwin)) {\n\treturn TCL_ERROR;\n    }\n    if (Ttk_ContentIndex(pw->paned.mgr, window) >= 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"%s already added\", Tk_PathName(window)));\n\tTcl_SetErrorCode(interp, \"TTK\", \"PANE\", \"PRESENT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    pane = CreatePane(interp, pw, window);\n    if (!pane) {\n\treturn TCL_ERROR;\n    }\n    if (ConfigurePane(interp, pw, pane, window, objc, objv) != TCL_OK) {\n\tDestroyPane(pw, pane);\n\treturn TCL_ERROR;\n    }\n\n    Ttk_InsertContent(pw->paned.mgr, destIndex, window, pane);\n    return TCL_OK;\n}\n\n/* PaneRequest --\n *\tOnly update pane request size if pane is currently unmapped.\n *\tGeometry requests from mapped panes are not directly honored\n *\tin order to avoid unexpected pane resizes (esp. while the\n *\tuser is dragging a sash [#1325286]).\n */\nstatic int PaneRequest(void *managerData, Tcl_Size index, int width, int height)\n{\n    Paned *pw = (Paned *)managerData;\n    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);\n    int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;\n\n    if (!Tk_IsMapped(window)) {\n\tpane->reqSize = horizontal ? width : height;\n    }\n    return 1;\n}\n\nstatic const Ttk_ManagerSpec PanedManagerSpec = {\n    { \"panedwindow\", Ttk_GeometryRequestProc, Ttk_LostContentProc },\n    PanedSize,\n    PanedPlaceContent,\n    PaneRequest,\n    PaneRemoved\n};\n\n/*------------------------------------------------------------------------\n * +++ Event handler.\n *\n * This event handler generates an <<EnteredChild>> virtual event\n * on LeaveNotify/NotifyInferior.\n * This was originally introduced because Tk used to discard events with\n * detail field NotifyInferior. The <<EnteredChild>> event was then used\n * to reset the cursor when the pointer crosses from a parent to a child.\n * Since ticket #47d4f29159, LeaveNotify/NotifyInferior are no longer\n * discarded: the <Leave> event will trigger even with NotifyInferior\n * detail field. The generated <<EnteredChild>> is nevertheless kept for\n * backwards compatibility purpose since it is publicly documented,\n * meaning that someone could bind to it.\n */\n\nstatic const unsigned PanedEventMask = LeaveWindowMask;\nstatic void PanedEventProc(void *clientData, XEvent *eventPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    if (   eventPtr->type == LeaveNotify\n\t&& eventPtr->xcrossing.detail == NotifyInferior)\n    {\n\tTk_SendVirtualEvent(corePtr->tkwin, \"EnteredChild\", NULL);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Initialization and cleanup hooks.\n */\n\nstatic void PanedInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Paned *pw = (Paned *)recordPtr;\n\n    Tk_CreateEventHandler(pw->core.tkwin,\n\tPanedEventMask, PanedEventProc, recordPtr);\n    pw->paned.mgr = Ttk_CreateManager(&PanedManagerSpec, pw, pw->core.tkwin);\n    pw->paned.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);\n    pw->paned.sashLayout = 0;\n    pw->paned.sashThickness = 1;\n}\n\nstatic void PanedCleanup(void *recordPtr)\n{\n    Paned *pw = (Paned *)recordPtr;\n\n    if (pw->paned.sashLayout) {\n\tTtk_FreeLayout(pw->paned.sashLayout);\n    }\n    Tk_DeleteEventHandler(pw->core.tkwin,\n\tPanedEventMask, PanedEventProc, recordPtr);\n    Ttk_DeleteManager(pw->paned.mgr);\n}\n\n/* Post-configuration hook.\n */\nstatic int PanedPostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *clientData,\n    int mask)\n{\n    Paned *pw = (Paned *)clientData;\n\n    if (mask & GEOMETRY_CHANGED) {\n\t/* User has changed -width or -height.\n\t * Recalculate sash positions based on requested size.\n\t */\n\tTk_Window tkwin = pw->core.tkwin;\n\tPlaceSashes(pw,\n\t    pw->paned.width > 0 ? pw->paned.width : Tk_Width(tkwin),\n\t    pw->paned.height > 0 ? pw->paned.height : Tk_Height(tkwin));\n    }\n\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Layout management hooks.\n */\nstatic Ttk_Layout PanedGetLayout(\n    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)\n{\n    Paned *pw = (Paned *)recordPtr;\n    Ttk_Layout panedLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);\n\n    if (panedLayout) {\n\tint horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;\n\tconst char *layoutName =\n\t    horizontal ? \".Vertical.Sash\" : \".Horizontal.Sash\";\n\tTtk_Layout sashLayout = Ttk_CreateSublayout(\n\t    interp, themePtr, panedLayout, layoutName, pw->core.optionTable);\n\n\tif (sashLayout) {\n\t    int sashWidth, sashHeight;\n\n\t    Ttk_LayoutSize(sashLayout, 0, &sashWidth, &sashHeight);\n\t    pw->paned.sashThickness = horizontal ? sashWidth : sashHeight;\n\n\t    if (pw->paned.sashLayout) {\n\t\tTtk_FreeLayout(pw->paned.sashLayout);\n\t    }\n\t    pw->paned.sashLayout = sashLayout;\n\t} else {\n\t    Ttk_FreeLayout(panedLayout);\n\t    return 0;\n\t}\n    }\n\n    return panedLayout;\n}\n\n/*------------------------------------------------------------------------\n * +++ Drawing routines.\n */\n\n/* SashLayout --\n *\tPlace the sash sublayout after the specified pane,\n *\tin preparation for drawing.\n */\nstatic Ttk_Layout SashLayout(Paned *pw, int index)\n{\n    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n    int thickness = pw->paned.sashThickness,\n\theight = Tk_Height(pw->core.tkwin),\n\twidth = Tk_Width(pw->core.tkwin),\n\tsashPos = pane->sashPos;\n\n    Ttk_PlaceLayout(\n\tpw->paned.sashLayout, pw->core.state,\n\tpw->paned.orient == TTK_ORIENT_HORIZONTAL\n\t    ? Ttk_MakeBox(sashPos, 0, thickness, height)\n\t    : Ttk_MakeBox(0, sashPos, width, thickness));\n\n    return pw->paned.sashLayout;\n}\n\nstatic void DrawSash(Paned *pw, int index, Drawable d)\n{\n    Ttk_DrawLayout(SashLayout(pw, index), pw->core.state, d);\n}\n\nstatic void PanedDisplay(void *recordPtr, Drawable d)\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tcl_Size i, nContent = Ttk_NumberContent(pw->paned.mgr);\n\n    TtkWidgetDisplay(recordPtr, d);\n    for (i = 1; i < nContent; ++i) {\n\tDrawSash(pw, i - 1, d);\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands.\n */\n\n/* $pw add window [ options ... ]\n */\nstatic int PanedAddCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tk_Window window;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    window = Tk_NameToWindow(\n\tinterp, Tcl_GetString(objv[2]), pw->core.tkwin);\n\n    if (!window) {\n\treturn TCL_ERROR;\n    }\n\n    return AddPane(interp, pw, Ttk_NumberContent(pw->paned.mgr), window,\n\t    objc - 3, objv + 3);\n}\n\n/* $pw insert $index $window ?-option value ...?\n *\tInsert new content window, or move existing one.\n */\nstatic int PanedInsertCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tcl_Size nContent = Ttk_NumberContent(pw->paned.mgr);\n    Tcl_Size srcIndex, destIndex;\n    Tk_Window window;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"index window ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    window = Tk_NameToWindow(\n\tinterp, Tcl_GetString(objv[3]), pw->core.tkwin);\n    if (!window) {\n\treturn TCL_ERROR;\n    }\n\n    if (TCL_OK != Ttk_GetContentIndexFromObj(\n\t\tinterp,pw->paned.mgr, objv[2], 1, &destIndex))\n    {\n\treturn TCL_ERROR;\n    }\n\n    srcIndex = Ttk_ContentIndex(pw->paned.mgr, window);\n    if (srcIndex < 0) { /* New content: */\n\treturn AddPane(interp, pw, destIndex, window, objc-4, objv+4);\n    } /* else -- move existing content: */\n\n    if (destIndex >= nContent) {\n\tdestIndex  = nContent - 1;\n    }\n    Ttk_ReorderContent(pw->paned.mgr, srcIndex, destIndex);\n\n    return objc == 4 ? TCL_OK :\n\tConfigurePane(interp, pw,\n\t\t(Pane *)Ttk_ContentData(pw->paned.mgr, destIndex),\n\t\tTtk_ContentWindow(pw->paned.mgr, destIndex),\n\t\tobjc-4, objv+4);\n}\n\n/* $pw forget $pane\n */\nstatic int PanedForgetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tcl_Size paneIndex;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"pane\");\n\treturn TCL_ERROR;\n    }\n\n    if (TCL_OK != Ttk_GetContentIndexFromObj(\n\t\t    interp, pw->paned.mgr, objv[2], 0, &paneIndex))\n    {\n\treturn TCL_ERROR;\n    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {\n\tpaneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;\n    }\n    Ttk_ForgetContent(pw->paned.mgr, paneIndex);\n\n    return TCL_OK;\n}\n\n/* $pw identify ?what? $x $y --\n *\tReturn index of sash at $x,$y\n */\nstatic int PanedIdentifyCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    static const char *const whatTable[] = { \"element\", \"sash\", NULL };\n    enum { IDENTIFY_ELEMENT, IDENTIFY_SASH };\n    int what = IDENTIFY_SASH;\n    Paned *pw = (Paned *)recordPtr;\n    int sashThickness = pw->paned.sashThickness;\n    int nSashes = Ttk_NumberContent(pw->paned.mgr) - 1;\n    int x, y, pos;\n    int index;\n\n    if (objc < 4 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"?what? x y\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK\n\t    || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK\n\t    || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,\n\t    sizeof(char *), \"option\", 0, &what) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n\n    pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y;\n    for (index = 0; index < nSashes; ++index) {\n\tPane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);\n\tif (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) {\n\t    /* Found it. */\n\t    switch (what) {\n\t\tcase IDENTIFY_SASH:\n\t\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index));\n\t\t    return TCL_OK;\n\t\tcase IDENTIFY_ELEMENT:\n\t\t{\n\t\t    Ttk_Element element =\n\t\t\tTtk_IdentifyElement(SashLayout(pw, index), x, y);\n\t\t    if (element) {\n\t\t\tTcl_SetObjResult(interp,\n\t\t\t    Tcl_NewStringObj(Ttk_ElementName(element), -1));\n\t\t    }\n\t\t    return TCL_OK;\n\t\t}\n\t    }\n\t}\n    }\n\n    return TCL_OK; /* nothing found - return empty string */\n}\n\n/* $pw pane $pane ?-option ?value -option value ...??\n *\tQuery/modify pane options.\n */\nstatic int PanedPaneCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tcl_Size paneIndex;\n    Tk_Window window;\n    Pane *pane;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"pane ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (TCL_OK != Ttk_GetContentIndexFromObj(\n\t\t    interp,pw->paned.mgr, objv[2], 0, &paneIndex))\n    {\n\treturn TCL_ERROR;\n    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {\n\tpaneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;\n    }\n\n    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, paneIndex);\n    window = Ttk_ContentWindow(pw->paned.mgr, paneIndex);\n\n    switch (objc) {\n\tcase 3:\n\t    return TtkEnumerateOptions(interp, pane, PaneOptionSpecs,\n\t\t\tpw->paned.paneOptionTable, window);\n\tcase 4:\n\t    return TtkGetOptionValue(interp, pane, objv[3],\n\t\t\tpw->paned.paneOptionTable, window);\n\tdefault:\n\t    return ConfigurePane(interp, pw, pane, window, objc-3,objv+3);\n    }\n}\n\n/* $pw panes --\n *\tReturn list of managed panes.\n */\nstatic int PanedPanesCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Ttk_Manager *mgr = pw->paned.mgr;\n    Tcl_Obj *panes;\n    Tcl_Size i;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    panes = Tcl_NewListObj(0, NULL);\n    for (i = 0; i < Ttk_NumberContent(mgr); ++i) {\n\tconst char *pathName = Tk_PathName(Ttk_ContentWindow(mgr,i));\n\tTcl_ListObjAppendElement(interp, panes, Tcl_NewStringObj(pathName,-1));\n    }\n    Tcl_SetObjResult(interp, panes);\n\n    return TCL_OK;\n}\n\n\n/* $pw sashpos $index ?$newpos?\n *\tQuery or modify sash position.\n */\nstatic int PanedSashposCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Paned *pw = (Paned *)recordPtr;\n    Tcl_WideInt sashIndex, position = -1;\n    Pane *pane;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"index ?newpos?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetWideIntFromObj(interp, objv[2], &sashIndex) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (sashIndex < 0 || sashIndex >= Ttk_NumberContent(pw->paned.mgr) - 1) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"sash index %\" TCL_LL_MODIFIER \"d out of range\", sashIndex));\n\tTcl_SetErrorCode(interp, \"TTK\", \"PANE\", \"SASH_INDEX\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, sashIndex);\n\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(pane->sashPos));\n\treturn TCL_OK;\n    }\n    /* else -- set new sash position */\n\n    if (Tcl_GetWideIntFromObj(interp, objv[3], &position) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (position < pane->sashPos) {\n\tShoveUp(pw, sashIndex, position);\n    } else {\n\tShoveDown(pw, sashIndex, position);\n    }\n\n    AdjustPanes(pw);\n    Ttk_ManagerLayoutChanged(pw->paned.mgr);\n\n    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pane->sashPos));\n    return TCL_OK;\n}\n\nstatic const Ttk_Ensemble PanedCommands[] = {\n    { \"add\",\t\tPanedAddCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"forget\",\tPanedForgetCommand,0 },\n    { \"identify\",\tPanedIdentifyCommand,0 },\n    { \"insert\",\tPanedInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"pane\",\tPanedPaneCommand,0 },\n    { \"panes\",\tPanedPanesCommand,0 },\n    { \"sashpos\",\tPanedSashposCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget specification.\n */\n\nstatic const WidgetSpec PanedWidgetSpec =\n{\n    \"TPanedwindow\",\t\t/* className */\n    sizeof(Paned),\t\t/* recordSize */\n    PanedOptionSpecs,\t\t/* optionSpecs */\n    PanedCommands,\t\t/* subcommands */\n    PanedInitialize,\t\t/* initializeProc */\n    PanedCleanup,\t\t/* cleanupProc */\n    TtkCoreConfigure,\t\t/* configureProc */\n    PanedPostConfigure,\t/* postConfigureProc */\n    PanedGetLayout,\t\t/* getLayoutProc */\n    PanedSize,\t\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    PanedDisplay\t\t/* displayProc */\n};\n\n/*------------------------------------------------------------------------\n * +++ Elements and layouts.\n */\n\nstatic const int DEFAULT_SASH_THICKNESS = 5;\n\ntypedef struct {\n    Tcl_Obj *thicknessObj;\n} SashElement;\n\nstatic const Ttk_ElementOptionSpec SashElementOptions[] = {\n    { \"-sashthickness\", TK_OPTION_PIXELS,\n\toffsetof(SashElement,thicknessObj), \"3.75p\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SashElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SashElement *sash = (SashElement *)elementRecord;\n    int thickness = DEFAULT_SASH_THICKNESS;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, sash->thicknessObj, &thickness);\n    *widthPtr = *heightPtr = thickness;\n}\n\nstatic const Ttk_ElementSpec SashElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SashElement),\n    SashElementOptions,\n    SashElementSize,\n    TtkNullElementDraw\n};\n\nstatic const int DEFAULT_GRIP_SIZE = 20;\n\ntypedef struct {\n    Tcl_Obj\t*borderObj;\n    Tcl_Obj\t*gripSizeObj;\n} GripElement;\n\nstatic const Ttk_ElementOptionSpec GripElementOptions[] = {\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(GripElement,borderObj), DEFAULT_BACKGROUND },\n    { \"-gripsize\", TK_OPTION_PIXELS,\n\toffsetof(GripElement,gripSizeObj), \"15p\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void GripElementSize(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n    GripElement *grip = (GripElement *)elementRecord;\n    int gripSize = DEFAULT_GRIP_SIZE;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*widthPtr = gripSize;\n    } else {\n\t*heightPtr = gripSize;\n    }\n}\n\nstatic void GripElementDraw(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);\n    GripElement *grip = (GripElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->borderObj);\n    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);\n    int gripSize = DEFAULT_GRIP_SIZE, gripPad = 1;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, grip->gripSizeObj, &gripSize);\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tXFillRectangle(Tk_Display(tkwin), d, darkGC,\n\t\tb.x + (b.width - gripSize) / 2, b.y + gripPad,\n\t\tgripSize, b.height - 2 * gripPad);\n    } else {\n\tXFillRectangle(Tk_Display(tkwin), d, darkGC,\n\t\tb.x + gripPad, b.y + (b.height - gripSize) / 2,\n\t\tb.width - 2 * gripPad, gripSize);\n    }\n}\n\nstatic const Ttk_ElementSpec GripElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(GripElement),\n    GripElementOptions,\n    GripElementSize,\n    GripElementDraw\n};\n\nTTK_BEGIN_LAYOUT(PanedLayout)\n    TTK_NODE(\"Panedwindow.background\", 0)/* @@@ BUG: empty layouts don't work */\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(HorizontalSashLayout)\n    TTK_GROUP(\"Sash.hsash\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Sash.hgrip\", TTK_FILL_BOTH))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(VerticalSashLayout)\n    TTK_GROUP(\"Sash.vsash\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Sash.vgrip\", TTK_FILL_BOTH))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Registration routine.\n */\n\nMODULE_SCOPE void\nTtkPanedwindow_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);\n    RegisterWidget(interp, \"ttk::panedwindow\", &PanedWidgetSpec);\n\n    Ttk_RegisterElement(interp, themePtr, \"hsash\", &SashElementSpec, 0);\n    Ttk_RegisterElement(interp, themePtr, \"vsash\", &SashElementSpec, 0);\n    Ttk_RegisterElement(interp, themePtr, \"hgrip\",\n\t    &GripElementSpec,  INT2PTR(TTK_ORIENT_HORIZONTAL));\n    Ttk_RegisterElement(interp, themePtr, \"vgrip\",\n\t    &GripElementSpec,  INT2PTR(TTK_ORIENT_VERTICAL));\n\n    Ttk_RegisterLayout(themePtr, \"TPanedwindow\", PanedLayout);\n    Ttk_RegisterLayout(themePtr, \"Horizontal.Sash\", HorizontalSashLayout);\n    Ttk_RegisterLayout(themePtr, \"Vertical.Sash\", VerticalSashLayout);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkProgress.c",
    "content": "/*\n * Copyright © Joe English, Pat Thoyts, Michael Kirkham\n *\n * ttk::progressbar widget.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*------------------------------------------------------------------------\n * +++ Widget record:\n */\n\n#define DEF_PROGRESSBAR_LENGTH \"100\"\nenum {\n    TTK_PROGRESSBAR_DETERMINATE, TTK_PROGRESSBAR_INDETERMINATE\n};\nstatic const char *const ProgressbarModeStrings[] = {\n    \"determinate\", \"indeterminate\", NULL\n};\n\ntypedef struct {\n    Tcl_Obj\t*anchorObj;\n    Tcl_Obj\t*fontObj;\n    Tcl_Obj\t*foregroundObj;\n    Tcl_Obj\t*justifyObj;\n    Tcl_Obj\t*lengthObj;\n    Tcl_Obj\t*maximumObj;\n    Tcl_Obj\t*modeObj;\n    Tcl_Obj\t*orientObj;\n    Tcl_Obj\t*phaseObj;\n    Tcl_Obj\t*textObj;\n    Tcl_Obj\t*valueObj;\n    Tcl_Obj\t*variableObj;\n    Tcl_Obj\t*wrapLengthObj;\n\n    int\tmode;\n    Ttk_TraceHandle *variableTrace;\t/* Trace handle for -variable option */\n    int\tperiod;\t\t\t/* Animation period */\n    int\tmaxPhase;\t\t/* Max animation phase */\n    Tcl_TimerToken timer;\t\t/* Animation timer */\n\n} ProgressbarPart;\n\ntypedef struct {\n    WidgetCore\t\tcore;\n    ProgressbarPart\tprogress;\n} Progressbar;\n\nstatic const Tk_OptionSpec ProgressbarOptionSpecs[] =\n{\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\t\"w\", offsetof(Progressbar,progress.anchorObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tDEFAULT_FONT, offsetof(Progressbar,progress.fontObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_COLOR, \"-foreground\", \"textColor\", \"TextColor\",\n\t\"black\", offsetof(Progressbar,progress.foregroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_JUSTIFY, \"-justify\", \"justify\", \"Justify\",\n\t\"left\", offsetof(Progressbar,progress.justifyObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_PIXELS, \"-length\", \"length\", \"Length\",\n\tDEF_PROGRESSBAR_LENGTH, offsetof(Progressbar,progress.lengthObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_DOUBLE, \"-maximum\", \"maximum\", \"Maximum\",\n\t\"100.0\", offsetof(Progressbar,progress.maximumObj), TCL_INDEX_NONE,\n\t0, 0, 0 },\n    {TK_OPTION_STRING_TABLE, \"-mode\", \"mode\", \"ProgressMode\", \"determinate\",\n\toffsetof(Progressbar,progress.modeObj),\n\toffsetof(Progressbar,progress.mode),\n\t0, ProgressbarModeStrings, 0 },\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\",\n\t\"horizontal\", offsetof(Progressbar,progress.orientObj), TCL_INDEX_NONE,\n\t0, ttkOrientStrings, STYLE_CHANGED },\n    {TK_OPTION_INT, \"-phase\", \"phase\", \"Phase\",\n\t\"0\", offsetof(Progressbar,progress.phaseObj), TCL_INDEX_NONE,\n\t0, 0, 0 },\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\", \"\",\n\toffsetof(Progressbar,progress.textObj), TCL_INDEX_NONE,\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_DOUBLE, \"-value\", \"value\", \"Value\",\n\t\"0.0\", offsetof(Progressbar,progress.valueObj), TCL_INDEX_NONE,\n\t0, 0, 0 },\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\",\n\tNULL, offsetof(Progressbar,progress.variableObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0 },\n    {TK_OPTION_PIXELS, \"-wraplength\", \"wrapLength\", \"WrapLength\",\n\t\"0\", offsetof(Progressbar, progress.wrapLengthObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ Animation procedures:\n */\n\n/* AnimationEnabled --\n *\tReturns 1 if animation should be active, 0 otherwise.\n */\nstatic int AnimationEnabled(Progressbar *pb)\n{\n    double maximum = 100, value = 0;\n\n    Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);\n    Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);\n\n    return (pb->progress.period > 0\n\t    && pb->progress.mode == TTK_PROGRESSBAR_INDETERMINATE);\n}\n\n/* AnimateProgressProc --\n *\tTimer callback for progress bar animation.\n *\tIncrements the -phase option, redisplays the widget,\n *\tand reschedules itself if animation still enabled.\n */\nstatic void AnimateProgressProc(void *clientData)\n{\n    Progressbar *pb = (Progressbar *)clientData;\n\n    pb->progress.timer = 0;\n    if (AnimationEnabled(pb)) {\n\tint phase = 0;\n\tTcl_GetIntFromObj(NULL, pb->progress.phaseObj, &phase);\n\n\t/*\n\t * Update -phase:\n\t */\n\n\t++phase;\n\tif (phase > pb->progress.maxPhase) {\n\t    phase = 0;\n\t}\n\tTcl_DecrRefCount(pb->progress.phaseObj);\n\tpb->progress.phaseObj = Tcl_NewWideIntObj(phase);\n\tTcl_IncrRefCount(pb->progress.phaseObj);\n\n\t/*\n\t * Reschedule:\n\t */\n\n\tpb->progress.timer = Tcl_CreateTimerHandler(\n\t    pb->progress.period, AnimateProgressProc, clientData);\n\tTtkRedisplayWidget(&pb->core);\n    }\n}\n\n/* CheckAnimation --\n *\tIf animation is enabled and not scheduled, schedule it.\n *\tIf animation is disabled but scheduled, cancel it.\n */\nstatic void CheckAnimation(Progressbar *pb)\n{\n    if (AnimationEnabled(pb)) {\n\tif (pb->progress.timer == 0) {\n\t    pb->progress.timer = Tcl_CreateTimerHandler(\n\t\tpb->progress.period, AnimateProgressProc, pb);\n\t}\n    } else {\n\tif (pb->progress.timer != 0) {\n\t    Tcl_DeleteTimerHandler(pb->progress.timer);\n\t    pb->progress.timer = 0;\n\t}\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Trace hook for progressbar -variable option:\n */\n\nstatic void VariableChanged(void *recordPtr, const char *value)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    Tcl_Obj *newValue;\n    double scratch;\n\n    if (WidgetDestroyed(&pb->core)) {\n\treturn;\n    }\n\n    if (!value) {\n\t/* Linked variable is unset -- disable widget */\n\tTtkWidgetChangeState(&pb->core, TTK_STATE_DISABLED, 0);\n\treturn;\n    }\n    TtkWidgetChangeState(&pb->core, 0, TTK_STATE_DISABLED);\n\n    newValue = Tcl_NewStringObj(value, -1);\n    Tcl_IncrRefCount(newValue);\n    if (Tcl_GetDoubleFromObj(NULL, newValue, &scratch) != TCL_OK) {\n\tTtkWidgetChangeState(&pb->core, TTK_STATE_INVALID, 0);\n\treturn;\n    }\n    TtkWidgetChangeState(&pb->core, 0, TTK_STATE_INVALID);\n    Tcl_DecrRefCount(pb->progress.valueObj);\n    pb->progress.valueObj = newValue;\n\n    CheckAnimation(pb);\n    TtkRedisplayWidget(&pb->core);\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget class methods:\n */\n\nstatic void ProgressbarInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n\n    pb->progress.variableTrace = 0;\n    pb->progress.timer = 0;\n}\n\nstatic void ProgressbarCleanup(void *recordPtr)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    if (pb->progress.variableTrace) {\n\tTtk_UntraceVariable(pb->progress.variableTrace);\n    }\n    if (pb->progress.timer) {\n\tTcl_DeleteTimerHandler(pb->progress.timer);\n    }\n}\n\n/*\n * Configure hook:\n *\n * @@@ TODO: deal with [$pb configure -value ... -variable ...]\n */\nstatic int ProgressbarConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    Tcl_Obj *varName = pb->progress.variableObj;\n    Ttk_TraceHandle *vt = 0;\n\n    if (!TkObjIsEmpty(varName)) {\n\tvt = Ttk_TraceVariable(interp, varName, VariableChanged, recordPtr);\n\tif (!vt) return TCL_ERROR;\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\n\tif (vt) Ttk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    if (pb->progress.variableTrace) {\n\tTtk_UntraceVariable(pb->progress.variableTrace);\n    }\n    pb->progress.variableTrace = vt;\n\n    return TCL_OK;\n}\n\n/*\n * Post-configuration hook:\n */\nstatic int ProgressbarPostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr,\n    TCL_UNUSED(int))\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    int status = TCL_OK;\n\n    if (pb->progress.variableTrace) {\n\tstatus = Ttk_FireTrace(pb->progress.variableTrace);\n\tif (WidgetDestroyed(&pb->core)) {\n\t    return TCL_ERROR;\n\t}\n\tif (status != TCL_OK) {\n\t    /* Unset -variable: */\n\t    Ttk_UntraceVariable(pb->progress.variableTrace);\n\t    Tcl_DecrRefCount(pb->progress.variableObj);\n\t    pb->progress.variableTrace = 0;\n\t    pb->progress.variableObj = NULL;\n\t    return TCL_ERROR;\n\t}\n    }\n\n    CheckAnimation(pb);\n\n    return status;\n}\n\n/*\n * Size hook:\n *\tCompute base layout size, overrid\n */\nstatic int ProgressbarSize(void *recordPtr, int *widthPtr, int *heightPtr)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    int length = 100;\n    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;\n\n    TtkWidgetSize(recordPtr, widthPtr, heightPtr);\n\n    /* Override requested width (height) based on -length and -orient\n     */\n    Tk_GetPixelsFromObj(NULL, pb->core.tkwin, pb->progress.lengthObj, &length);\n    Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*widthPtr = length;\n    } else {\n\t*heightPtr = length;\n    }\n\n    return 1;\n}\n\n/*\n * Layout hook:\n *\tAdjust size and position of pbar element, if present.\n */\n\nstatic void ProgressbarDeterminateLayout(\n    Progressbar *pb,\n    Ttk_Element pbar,\n    Ttk_Box parcel,\n    double fraction,\n    Ttk_Orient orient)\n{\n    if (fraction < 0.0) fraction = 0.0;\n    if (fraction > 1.0) fraction = 1.0;\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tparcel.width = (int)(parcel.width * fraction);\n    } else {\n\tint newHeight = (int)(parcel.height * fraction);\n\tparcel.y += (parcel.height - newHeight);\n\tparcel.height = newHeight;\n    }\n    Ttk_PlaceElement(pb->core.layout, pbar, parcel);\n}\n\nstatic void ProgressbarIndeterminateLayout(\n    Progressbar *pb,\n    Ttk_Element pbar,\n    Ttk_Box parcel,\n    double fraction,\n    Ttk_Orient orient)\n{\n    Ttk_Box pbarBox = Ttk_ElementParcel(pbar);\n\n    fraction = fmod(fabs(fraction), 2.0);\n    if (fraction > 1.0) {\n\tfraction = 2.0 - fraction;\n    }\n\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tpbarBox.x = parcel.x + (int)(fraction * (parcel.width-pbarBox.width));\n    } else {\n\tpbarBox.y = parcel.y + (int)(fraction * (parcel.height-pbarBox.height));\n    }\n    Ttk_PlaceElement(pb->core.layout, pbar, pbarBox);\n}\n\nstatic void ProgressbarDoLayout(void *recordPtr)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    WidgetCore *corePtr = &pb->core;\n    Ttk_Element pbar = Ttk_FindElement(corePtr->layout, \"pbar\");\n    double value = 0.0, maximum = 100.0;\n    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;\n\n    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));\n\n    /* Adjust the bar size:\n     */\n\n    Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);\n    Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);\n    Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);\n\n    if (pbar) {\n\tdouble fraction = value / maximum;\n\tTtk_Box parcel = Ttk_ClientRegion(corePtr->layout, \"trough\");\n\n\tif (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) {\n\t    ProgressbarDeterminateLayout(\n\t\tpb, pbar, parcel, fraction, orient);\n\t} else {\n\t    ProgressbarIndeterminateLayout(\n\t\tpb, pbar, parcel, fraction, orient);\n\t}\n    }\n}\n\nstatic Ttk_Layout ProgressbarGetLayout(\n    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    Ttk_Layout layout = TtkWidgetGetOrientedLayout(\n\tinterp, theme, recordPtr, pb->progress.orientObj);\n\n    /*\n     * Check if the style supports animation:\n     */\n    pb->progress.period = 0;\n    pb->progress.maxPhase = 0;\n    if (layout) {\n\tTcl_Obj *periodObj = Ttk_QueryOption(layout, \"-period\", 0);\n\tTcl_Obj *maxPhaseObj = Ttk_QueryOption(layout, \"-maxphase\", 0);\n\tif (periodObj) {\n\t    Tcl_GetIntFromObj(NULL, periodObj, &pb->progress.period);\n\t}\n\tif (maxPhaseObj) {\n\t    Tcl_GetIntFromObj(NULL, maxPhaseObj, &pb->progress.maxPhase);\n\t}\n    }\n\n    return layout;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands:\n */\n\n/* $sb step ?amount?\n */\nstatic int ProgressbarStepCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Progressbar *pb = (Progressbar *)recordPtr;\n    double value = 0.0, stepAmount = 1.0;\n    Tcl_Obj *newValueObj;\n\n    if (objc == 3) {\n\tif (Tcl_GetDoubleFromObj(interp, objv[2], &stepAmount) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    } else if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2,objv, \"?stepAmount?\");\n\treturn TCL_ERROR;\n    }\n\n    (void)Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);\n    value += stepAmount;\n\n    /* In determinate mode, wrap around if value exceeds maximum:\n     */\n    if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) {\n\tdouble maximum = 100.0;\n\t(void)Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);\n\tvalue = fmod(value, maximum);\n    }\n\n    newValueObj = Tcl_NewDoubleObj(value);\n    Tcl_IncrRefCount(newValueObj);\n\n    TtkRedisplayWidget(&pb->core);\n\n    /* Update value by setting the linked -variable, if there is one:\n     */\n    if (pb->progress.variableTrace) {\n\tint result = Tcl_ObjSetVar2(\n\t\t\tinterp, pb->progress.variableObj, 0, newValueObj,\n\t\t\tTCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG)\n\t\t? TCL_OK : TCL_ERROR;\n\tTcl_DecrRefCount(newValueObj);\n\treturn result;\n    }\n\n    /* Otherwise, change the -value directly:\n     */\n    Tcl_DecrRefCount(pb->progress.valueObj);\n    pb->progress.valueObj = newValueObj;\n    CheckAnimation(pb);\n\n    return TCL_OK;\n}\n\n/* $sb start|stop ?args? --\n * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...]\n * and pass to interpreter.\n */\nstatic int ProgressbarStartStopCommand(\n    Tcl_Interp *interp, const char *cmdName, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tcl_Obj *cmd = Tcl_NewListObj(objc, objv);\n    Tcl_Obj *prefix[2];\n    int status;\n\n    /* ASSERT: objc >= 2 */\n\n    prefix[0] = Tcl_NewStringObj(cmdName, -1);\n    prefix[1] = objv[0];\n    Tcl_ListObjReplace(interp, cmd, 0, 2, 2,prefix);\n\n    Tcl_IncrRefCount(cmd);\n    status = Tcl_EvalObjEx(interp, cmd, 0);\n    Tcl_DecrRefCount(cmd);\n\n    return status;\n}\n\nstatic int ProgressbarStartCommand(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    return ProgressbarStartStopCommand(\n\t    interp, \"::ttk::progressbar::start\", objc, objv);\n}\n\nstatic int ProgressbarStopCommand(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    return ProgressbarStartStopCommand(\n\t    interp, \"::ttk::progressbar::stop\", objc, objv);\n}\n\nstatic const Ttk_Ensemble ProgressbarCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"start\",\t\tProgressbarStartCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"step\",\t\tProgressbarStepCommand,0 },\n    { \"stop\",\t\tProgressbarStopCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*\n * Widget specification:\n */\nstatic const WidgetSpec ProgressbarWidgetSpec =\n{\n    \"TProgressbar\",\t\t/* className */\n    sizeof(Progressbar),\t/* recordSize */\n    ProgressbarOptionSpecs,\t/* optionSpecs */\n    ProgressbarCommands,\t/* subcommands */\n    ProgressbarInitialize,\t/* initializeProc */\n    ProgressbarCleanup,\t\t/* cleanupProc */\n    ProgressbarConfigure,\t/* configureProc */\n    ProgressbarPostConfigure,\t/* postConfigureProc */\n    ProgressbarGetLayout,\t/* getLayoutProc */\n    ProgressbarSize,\t\t/* sizeProc */\n    ProgressbarDoLayout,\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\n/*\n * Layouts:\n */\nTTK_BEGIN_LAYOUT(VerticalProgressbarLayout)\n    TTK_GROUP(\"Vertical.Progressbar.trough\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Vertical.Progressbar.pbar\", TTK_PACK_BOTTOM|TTK_FILL_X))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(HorizontalProgressbarLayout)\n    TTK_GROUP(\"Horizontal.Progressbar.trough\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Horizontal.Progressbar.pbar\", TTK_PACK_LEFT|TTK_FILL_Y)\n\tTTK_NODE(\"Horizontal.Progressbar.ctext\", TTK_PACK_LEFT))\nTTK_END_LAYOUT\n\n/*\n * Initialization:\n */\n\nMODULE_SCOPE void\nTtkProgressbar_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(themePtr,\n\t\"Vertical.TProgressbar\", VerticalProgressbarLayout);\n    Ttk_RegisterLayout(themePtr,\n\t\"Horizontal.TProgressbar\", HorizontalProgressbarLayout);\n\n    RegisterWidget(interp, \"ttk::progressbar\", &ProgressbarWidgetSpec);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkScale.c",
    "content": "/*\n * Copyright © 2004 Pat Thoyts <patthoyts@users.sourceforge.net>\n *\n * ttk::scale widget.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n#define DEF_SCALE_LENGTH \"100\"\n\n#define MAX(a,b) ((a) > (b) ? (a) : (b))\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n\n/* Bit fields for OptionSpec mask field:\n */\n#define STATE_CHANGED\t\t(0x100)\t\t/* -state option changed */\n\n/*\n * Scale widget record\n */\ntypedef struct\n{\n    /* slider element options */\n    Tcl_Obj *fromObj;         /* minimum value */\n    Tcl_Obj *toObj;           /* maximum value */\n    Tcl_Obj *valueObj;        /* current value */\n    Tcl_Obj *lengthObj;       /* length of the long axis of the scale */\n    Tcl_Obj *orientObj;       /* widget orientation */\n    int orient;\n\n    /* widget options */\n    Tcl_Obj *commandObj;\n    Tcl_Obj *variableObj;\n\n    /* internal state */\n    Ttk_TraceHandle *variableTrace;\n\n    /*\n     * Compatibility/legacy options:\n     */\n    Tcl_Obj *stateObj;\n\n} ScalePart;\n\ntypedef struct\n{\n    WidgetCore core;\n    ScalePart  scale;\n} Scale;\n\nstatic const Tk_OptionSpec ScaleOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\", \"\",\n\toffsetof(Scale,scale.commandObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0},\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\", \"\",\n\toffsetof(Scale,scale.variableObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\", \"horizontal\",\n\toffsetof(Scale,scale.orientObj),\n\toffsetof(Scale,scale.orient),\n\t0, ttkOrientStrings, STYLE_CHANGED },\n\n    {TK_OPTION_DOUBLE, \"-from\", \"from\", \"From\", \"0.0\",\n\toffsetof(Scale,scale.fromObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-to\", \"to\", \"To\", \"1.0\",\n\toffsetof(Scale,scale.toObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_DOUBLE, \"-value\", \"value\", \"Value\", \"0.0\",\n\toffsetof(Scale,scale.valueObj), TCL_INDEX_NONE, 0, 0, 0},\n    {TK_OPTION_PIXELS, \"-length\", \"length\", \"Length\",\n\tDEF_SCALE_LENGTH, offsetof(Scale,scale.lengthObj), TCL_INDEX_NONE, 0, 0,\n\tGEOMETRY_CHANGED},\n\n    {TK_OPTION_STRING, \"-state\", \"state\", \"State\",\n\t\"normal\", offsetof(Scale,scale.stateObj), TCL_INDEX_NONE,\n\t0, 0, STATE_CHANGED},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\nstatic XPoint ValueToPoint(Scale *scalePtr, double value);\nstatic double PointToValue(Scale *scalePtr, int x, int y);\n\n/* ScaleVariableChanged --\n *\tVariable trace procedure for scale -variable;\n *\tUpdates the scale's value.\n *\tIf the linked variable is not a valid double,\n *\tsets the 'invalid' state.\n */\nstatic void ScaleVariableChanged(void *recordPtr, const char *value)\n{\n    Scale *scale = (Scale *)recordPtr;\n    double v;\n\n    if (value == NULL || Tcl_GetDouble(0, value, &v) != TCL_OK) {\n\tTtkWidgetChangeState(&scale->core, TTK_STATE_INVALID, 0);\n    } else {\n\tTcl_Obj *valueObj = Tcl_NewDoubleObj(v);\n\tTcl_IncrRefCount(valueObj);\n\tTcl_DecrRefCount(scale->scale.valueObj);\n\tscale->scale.valueObj = valueObj;\n\tTtkWidgetChangeState(&scale->core, 0, TTK_STATE_INVALID);\n    }\n    TtkRedisplayWidget(&scale->core);\n}\n\n/* ScaleInitialize --\n *\tScale widget initialization hook.\n */\nstatic void ScaleInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Scale *scalePtr = (Scale *)recordPtr;\n\n    TtkTrackElementState(&scalePtr->core);\n}\n\nstatic void ScaleCleanup(void *recordPtr)\n{\n    Scale *scale = (Scale *)recordPtr;\n\n    if (scale->scale.variableTrace) {\n\tTtk_UntraceVariable(scale->scale.variableTrace);\n\tscale->scale.variableTrace = 0;\n    }\n}\n\n/* ScaleConfigure --\n *\tConfiguration hook.\n */\nstatic int ScaleConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Scale *scale = (Scale *)recordPtr;\n    Tcl_Obj *varName = scale->scale.variableObj;\n    Ttk_TraceHandle *vt = 0;\n\n    if (!TkObjIsEmpty(varName)) {\n\tvt = Ttk_TraceVariable(interp,varName, ScaleVariableChanged,recordPtr);\n\tif (!vt) return TCL_ERROR;\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\n\tif (vt) Ttk_UntraceVariable(vt);\n\treturn TCL_ERROR;\n    }\n\n    if (scale->scale.variableTrace) {\n\tTtk_UntraceVariable(scale->scale.variableTrace);\n    }\n    scale->scale.variableTrace = vt;\n\n    if (mask & STATE_CHANGED) {\n\tTtkCheckStateOption(&scale->core, scale->scale.stateObj);\n    }\n\n    return TCL_OK;\n}\n\n/* ScalePostConfigure --\n *\tPost-configuration hook.\n */\nstatic int ScalePostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr,\n    TCL_UNUSED(int))\n{\n    Scale *scale = (Scale *)recordPtr;\n    int status = TCL_OK;\n\n    if (scale->scale.variableTrace) {\n\tstatus = Ttk_FireTrace(scale->scale.variableTrace);\n\tif (WidgetDestroyed(&scale->core)) {\n\t    return TCL_ERROR;\n\t}\n\tif (status != TCL_OK) {\n\t    /* Unset -variable: */\n\t    Ttk_UntraceVariable(scale->scale.variableTrace);\n\t    Tcl_DecrRefCount(scale->scale.variableObj);\n\t    scale->scale.variableTrace = 0;\n\t    scale->scale.variableObj = NULL;\n\t    status = TCL_ERROR;\n\t}\n    }\n\n    return status;\n}\n\n/* ScaleGetLayout --\n *\tgetLayout hook.\n */\nstatic Ttk_Layout\nScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Scale *scalePtr = (Scale *)recordPtr;\n    return TtkWidgetGetOrientedLayout(\n\tinterp, theme, recordPtr, scalePtr->scale.orientObj);\n}\n\n/*\n * TroughBox --\n *\tReturns the inner area of the trough element.\n */\nstatic Ttk_Box TroughBox(Scale *scalePtr)\n{\n    return Ttk_ClientRegion(scalePtr->core.layout, \"trough\");\n}\n\n/*\n * TroughRange --\n *\tReturn the value area of the trough element, adjusted\n *\tfor slider size.\n */\nstatic Ttk_Box TroughRange(Scale *scalePtr)\n{\n    Ttk_Box troughBox = TroughBox(scalePtr);\n    Ttk_Element slider = Ttk_FindElement(scalePtr->core.layout,\"slider\");\n\n    /*\n     * If this is a scale widget, adjust range for slider:\n     */\n    if (slider) {\n\tTtk_Box sliderBox = Ttk_ElementParcel(slider);\n\tif (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {\n\t    troughBox.x += sliderBox.width / 2;\n\t    troughBox.width -= sliderBox.width;\n\t} else {\n\t    troughBox.y += sliderBox.height / 2;\n\t    troughBox.height -= sliderBox.height;\n\t}\n    }\n\n    return troughBox;\n}\n\n/*\n * ScaleFraction --\n */\nstatic double ScaleFraction(Scale *scalePtr, double value)\n{\n    double from = 0, to = 1, fraction;\n\n    Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from);\n    Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to);\n\n    if (from == to) {\n\treturn 1.0;\n    }\n\n    fraction = (value - from) / (to - from);\n\n    return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;\n}\n\n/* $scale get ?x y? --\n *\tReturns the current value of the scale widget, or if $x and\n *\t$y are specified, the value represented by point @x,y.\n */\nstatic int\nScaleGetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scale *scalePtr = (Scale *)recordPtr;\n    int x, y, r = TCL_OK;\n    double value = 0;\n\n    if (objc == 2) {\n\tTcl_SetObjResult(interp, scalePtr->scale.valueObj);\n    } else if (objc == 4) {\n\tr = Tcl_GetIntFromObj(interp, objv[2], &x);\n\tif (r == TCL_OK) {\n\t    r = Tcl_GetIntFromObj(interp, objv[3], &y);\n\t}\n\tif (r == TCL_OK) {\n\t    value = PointToValue(scalePtr, x, y);\n\t    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));\n\t}\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"get ?x y?\");\n\treturn TCL_ERROR;\n    }\n    return r;\n}\n\n/* $scale set $newValue\n */\nstatic int\nScaleSetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scale *scalePtr = (Scale *)recordPtr;\n    double from = 0.0, to = 1.0, value;\n    int result = TCL_OK;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"set value\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (scalePtr->core.state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n\n    /* ASSERT: fromObj and toObj are valid doubles.\n     */\n    Tcl_GetDoubleFromObj(interp, scalePtr->scale.fromObj, &from);\n    Tcl_GetDoubleFromObj(interp, scalePtr->scale.toObj, &to);\n\n    /* Limit new value to between 'from' and 'to':\n     */\n    if (from < to) {\n\tvalue = value < from ? from : value > to ? to : value;\n    } else {\n\tvalue = value < to ? to : value > from ? from : value;\n    }\n\n    /*\n     * Set value:\n     */\n    Tcl_DecrRefCount(scalePtr->scale.valueObj);\n    scalePtr->scale.valueObj = Tcl_NewDoubleObj(value);\n    Tcl_IncrRefCount(scalePtr->scale.valueObj);\n    TtkRedisplayWidget(&scalePtr->core);\n\n    /*\n     * Set attached variable, if any:\n     */\n    if (scalePtr->scale.variableObj != NULL) {\n\tTcl_ObjSetVar2(interp, scalePtr->scale.variableObj, NULL,\n\t    scalePtr->scale.valueObj, TCL_GLOBAL_ONLY);\n    }\n    if (WidgetDestroyed(&scalePtr->core)) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Invoke -command, if any:\n     */\n    if (scalePtr->scale.commandObj != NULL) {\n\tTcl_Obj *cmdObj = Tcl_DuplicateObj(scalePtr->scale.commandObj);\n\tTcl_IncrRefCount(cmdObj);\n\tTcl_AppendToObj(cmdObj, \" \", 1);\n\tTcl_AppendObjToObj(cmdObj, scalePtr->scale.valueObj);\n\tresult = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);\n\tTcl_DecrRefCount(cmdObj);\n    }\n\n    return result;\n}\n\nstatic int\nScaleCoordsCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scale *scalePtr = (Scale *)recordPtr;\n    double value;\n    int r = TCL_OK;\n\n    if (objc == 3) {\n\tr = Tcl_GetDoubleFromObj(interp, objv[2], &value);\n    } else if (objc == 2) {\n\tr = Tcl_GetDoubleFromObj(interp, scalePtr->scale.valueObj, &value);\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"coords ?value?\");\n\treturn TCL_ERROR;\n    }\n\n    if (r == TCL_OK) {\n\tTcl_Obj *point[2];\n\tXPoint pt = ValueToPoint(scalePtr, value);\n\tpoint[0] = Tcl_NewWideIntObj(pt.x);\n\tpoint[1] = Tcl_NewWideIntObj(pt.y);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, point));\n    }\n    return r;\n}\n\nstatic void ScaleDoLayout(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    Ttk_Element slider = Ttk_FindElement(corePtr->layout, \"slider\");\n\n    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));\n\n    /* Adjust the slider position:\n     */\n    if (slider) {\n\tScale *scalePtr = (Scale *)clientData;\n\tTtk_Box troughBox = TroughBox(scalePtr);\n\tTtk_Box sliderBox = Ttk_ElementParcel(slider);\n\tdouble value = 0.0;\n\tdouble fraction;\n\tint range;\n\n\tTcl_GetDoubleFromObj(NULL, scalePtr->scale.valueObj, &value);\n\tfraction = ScaleFraction(scalePtr, value);\n\n\tif (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {\n\t    range = troughBox.width - sliderBox.width;\n\t    sliderBox.x += (int)(fraction * range);\n\t} else {\n\t    range = troughBox.height - sliderBox.height;\n\t    sliderBox.y += (int)(fraction * range);\n\t}\n\tTtk_PlaceElement(corePtr->layout, slider, sliderBox);\n    }\n}\n\n/*\n * ScaleSize --\n *\tCompute requested size of scale.\n */\nstatic int ScaleSize(void *clientData, int *widthPtr, int *heightPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    Scale *scalePtr = (Scale *)clientData;\n    int length;\n\n    Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);\n\n    /* Assert the -length configuration option */\n    Tk_GetPixelsFromObj(NULL, corePtr->tkwin,\n\t    scalePtr->scale.lengthObj, &length);\n    if (scalePtr->scale.orient == TTK_ORIENT_VERTICAL) {\n\t*heightPtr = MAX(*heightPtr, length);\n    } else {\n\t*widthPtr = MAX(*widthPtr, length);\n    }\n\n    return 1;\n}\n\nstatic double\nPointToValue(Scale *scalePtr, int x, int y)\n{\n    Ttk_Box troughBox = TroughRange(scalePtr);\n    double value = 0, from = 0, to = 1, fraction;\n\n    Tcl_GetDoubleFromObj(NULL, scalePtr->scale.valueObj, &value);\n    Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from);\n    Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to);\n\n    if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {\n\t/*\n\t * Bug d25b721f: drag when trough not shown due to missing display place\n\t */\n\tif (troughBox.width <= 0) {\n\t    return value;\n\t}\n\tfraction = (double)(x - troughBox.x) / (double)troughBox.width;\n    } else {\n\t/*\n\t * Bug d25b721f: drag when trough not shown due to missing display place\n\t */\n\tif (troughBox.height <= 0) {\n\t    return value;\n\t}\n\tfraction = (double)(y - troughBox.y) / (double)troughBox.height;\n    }\n\n    fraction = fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;\n\n    return from + fraction * (to-from);\n}\n\n/*\n * Return the center point in the widget corresponding to the given\n * value. This point can be used to center the slider.\n */\n\nstatic XPoint\nValueToPoint(Scale *scalePtr, double value)\n{\n    Ttk_Box troughBox = TroughRange(scalePtr);\n    double fraction = ScaleFraction(scalePtr, value);\n    XPoint pt = {0, 0};\n\n    if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) {\n\tpt.x = troughBox.x + (int)(fraction * troughBox.width);\n\tpt.y = troughBox.y + troughBox.height / 2;\n    } else {\n\tpt.x = troughBox.x + troughBox.width / 2;\n\tpt.y = troughBox.y + (int)(fraction * troughBox.height);\n    }\n    return pt;\n}\n\nstatic const Ttk_Ensemble ScaleCommands[] = {\n    { \"cget\",        TtkWidgetCgetCommand,0 },\n    { \"configure\",   TtkWidgetConfigureCommand,0 },\n    { \"coords\",      ScaleCoordsCommand,0 },\n    { \"get\",         ScaleGetCommand,0 },\n    { \"identify\",    TtkWidgetIdentifyCommand,0 },\n    { \"instate\",     TtkWidgetInstateCommand,0 },\n    { \"set\",         ScaleSetCommand,0 },\n    { \"state\",       TtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec ScaleWidgetSpec =\n{\n    \"TScale\",\t\t\t/* Class name */\n    sizeof(Scale),\t\t/* record size */\n    ScaleOptionSpecs,\t\t/* option specs */\n    ScaleCommands,\t\t/* widget commands */\n    ScaleInitialize,\t\t/* initialization proc */\n    ScaleCleanup,\t\t/* cleanup proc */\n    ScaleConfigure,\t\t/* configure proc */\n    ScalePostConfigure,\t\t/* postConfigure */\n    ScaleGetLayout,\t\t/* getLayoutProc */\n    ScaleSize,\t\t\t/* sizeProc */\n    ScaleDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(VerticalScaleLayout)\n    TTK_GROUP(\"Vertical.Scale.focus\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Vertical.Scale.padding\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Vertical.Scale.trough\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Vertical.Scale.slider\", TTK_PACK_TOP))))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(HorizontalScaleLayout)\n    TTK_GROUP(\"Horizontal.Scale.focus\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Horizontal.Scale.padding\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Horizontal.Scale.trough\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Horizontal.Scale.slider\", TTK_PACK_LEFT))))\nTTK_END_LAYOUT\n\n/*\n * Initialization.\n */\n\nMODULE_SCOPE void\nTtkScale_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(theme, \"Vertical.TScale\", VerticalScaleLayout);\n    Ttk_RegisterLayout(theme, \"Horizontal.TScale\", HorizontalScaleLayout);\n\n    RegisterWidget(interp, \"ttk::scale\", &ScaleWidgetSpec);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkScroll.c",
    "content": "/*\n * Copyright 2004, Joe English\n *\n * Support routines for scrollable widgets.\n *\n * (This is sort of half-baked; needs some work)\n *\n * Scrollable interface:\n *\n *\t+ 'first' is controlled by [xy]view widget command\n *\t  and other scrolling commands like 'see';\n *      + 'total' depends on widget contents;\n *      + 'last' depends on first, total, and widget size.\n *\n * Choreography (typical usage):\n *\n *\t1. User adjusts scrollbar, scrollbar widget calls its -command\n *\t2. Scrollbar -command invokes the scrollee [xy]view widget method\n *\t3. TtkScrollviewCommand calls TtkScrollTo(), which updates\n *\t   'first' and schedules a redisplay.\n *\t4. Once the scrollee knows 'total' and 'last' (typically in\n *\t   the LayoutProc), call TtkScrolled(h,first,last,total) to\n *\t   synchronize the scrollbar.\n *\t5. The scrollee -[xy]scrollcommand is called (in an idle callback)\n *\t6. Which calls the scrollbar 'set' method and redisplays the scrollbar.\n *\n * If the scrollee has internal scrolling (e.g., a 'see' method),\n * it should TtkScrollTo() directly (step 2).\n *\n * If the widget value changes, it should call TtkScrolled() (step 4).\n * (This usually happens automatically when the widget is redisplayed).\n *\n * If the scrollee's -[xy]scrollcommand changes, it should call\n * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this)\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/* Private data:\n */\n#define SCROLL_UPDATE_PENDING  (0x1)\n#define SCROLL_UPDATE_REQUIRED (0x2)\n\nstruct ScrollHandleRec\n{\n    unsigned\tflags;\n    WidgetCore\t*corePtr;\n    Scrollable\t*scrollPtr;\n};\n\n/* TtkCreateScrollHandle --\n *\tInitialize scroll handle.\n */\nScrollHandle TtkCreateScrollHandle(WidgetCore *corePtr, Scrollable *scrollPtr)\n{\n    ScrollHandle h = (ScrollHandle)Tcl_Alloc(sizeof(*h));\n\n    h->flags = 0;\n    h->corePtr = corePtr;\n    h->scrollPtr = scrollPtr;\n\n    scrollPtr->first = 0;\n    scrollPtr->last = 1;\n    scrollPtr->total = 1;\n    return h;\n}\n\n/* UpdateScrollbar --\n *\tCall the -scrollcommand callback to sync the scrollbar.\n *\tReturns: Whatever the -scrollcommand does.\n */\nstatic int UpdateScrollbar(Tcl_Interp *interp, ScrollHandle h)\n{\n    Scrollable *s = h->scrollPtr;\n    WidgetCore *corePtr = h->corePtr;\n    char arg1[TCL_DOUBLE_SPACE + 2];\n    char arg2[TCL_DOUBLE_SPACE + 2];\n    int code;\n    Tcl_DString buf;\n\n    h->flags &= ~SCROLL_UPDATE_REQUIRED;\n\n    if (s->scrollCmdObj == NULL) {\n\treturn TCL_OK;\n    }\n\n    arg1[0] = arg2[0] = ' ';\n    Tcl_PrintDouble(interp, (double)s->first / (double)s->total, arg1+1);\n    Tcl_PrintDouble(interp, (double)s->last / (double)s->total, arg2+1);\n    Tcl_DStringInit(&buf);\n    Tcl_DStringAppend(&buf, Tcl_GetString(s->scrollCmdObj), TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, arg1, TCL_INDEX_NONE);\n    Tcl_DStringAppend(&buf, arg2, TCL_INDEX_NONE);\n\n    Tcl_Preserve(corePtr);\n    code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);\n    Tcl_DStringFree(&buf);\n    if (WidgetDestroyed(corePtr)) {\n\tTcl_Release(corePtr);\n\treturn TCL_ERROR;\n    }\n    Tcl_Release(corePtr);\n\n    if (code != TCL_OK && !Tcl_InterpDeleted(interp)) {\n\t/* Add error to stack trace.\n\t * Also set the SCROLL_UPDATE_REQUIRED flag so that a later call to\n\t * TtkScrolled has an effect. Indeed, the error in the -scrollcommand\n\t * callback may later be gone, for instance the callback proc got\n\t * defined in the meantime.\n\t */\n\n\tTcl_AddErrorInfo(interp, /* @@@ \"horizontal\" / \"vertical\" */\n\t\t\"\\n    (scrolling command executed by \");\n\tTcl_AddErrorInfo(interp, Tk_PathName(h->corePtr->tkwin));\n\tTcl_AddErrorInfo(interp, \")\");\n\tTtkScrollbarUpdateRequired(h);\n    }\n    return code;\n}\n\n/* UpdateScrollbarBG --\n *\tIdle handler to update the scrollbar.\n */\nstatic void UpdateScrollbarBG(void *clientData)\n{\n    ScrollHandle h = (ScrollHandle)clientData;\n    Tcl_Interp *interp = h->corePtr->interp;\n    int code;\n\n    h->flags &= ~SCROLL_UPDATE_PENDING;\n    Tcl_Preserve(interp);\n    code = UpdateScrollbar(interp, h);\n    if (code == TCL_ERROR && !Tcl_InterpDeleted(interp)) {\n\tTcl_BackgroundException(interp, code);\n    }\n    Tcl_Release(interp);\n}\n\n/* TtkScrolled --\n *\tUpdate scroll info, schedule scrollbar update.\n */\nvoid TtkScrolled(ScrollHandle h, Tcl_Size first, Tcl_Size last, Tcl_Size total)\n{\n    Scrollable *s = h->scrollPtr;\n\n    /* Sanity-check inputs:\n     */\n    if (total <= 0) {\n\tfirst = 0;\n\tlast = 1;\n\ttotal = 1;\n    }\n\n    if (last > total) {\n\tfirst -= (last - total);\n\tif (first < 0) first = 0;\n\tlast = total;\n    }\n\n    if (s->first != first || s->last != last || s->total != total\n\t    || (h->flags & SCROLL_UPDATE_REQUIRED))\n    {\n\ts->first = first;\n\ts->last = last;\n\ts->total = total;\n\n\tif (!(h->flags & SCROLL_UPDATE_PENDING)) {\n\t    Tcl_DoWhenIdle(UpdateScrollbarBG, h);\n\t    h->flags |= SCROLL_UPDATE_PENDING;\n\t}\n    }\n}\n\n/* TtkScrollbarUpdateRequired --\n *\tForce a scrollbar update at the next call to TtkScrolled(),\n *\teven if scroll parameters haven't changed (e.g., if\n *\t-yscrollcommand has changed).\n */\n\nvoid TtkScrollbarUpdateRequired(ScrollHandle h)\n{\n    h->flags |= SCROLL_UPDATE_REQUIRED;\n}\n\n/* TtkUpdateScrollInfo --\n *\tCall the layoutProc to update the scroll info first, last, and total.\n *\tDo it only if needed, that is when a redisplay is pending (which\n *\tindicates scroll info are possibly out of date).\n */\n\nvoid TtkUpdateScrollInfo(ScrollHandle h)\n{\n    if (h->corePtr->flags & REDISPLAY_PENDING) {\n\th->corePtr->widgetSpec->layoutProc(h->corePtr);\n    }\n}\n\n/* TtkScrollviewCommand --\n *\tWidget [xy]view command implementation.\n *\n *  $w [xy]view -- return current view region\n *  $w [xy]view $index -- set topmost item\n *  $w [xy]view moveto $fraction\n *  $w [xy]view scroll $number $what -- scrollbar interface\n */\nint TtkScrollviewCommand(\n    Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], ScrollHandle h)\n{\n    Scrollable *s = h->scrollPtr;\n    Tcl_Size newFirst;\n\n    TtkUpdateScrollInfo(h);\n    newFirst = s->first;\n\n    if (objc == 2) {\n\tTcl_Obj *result[2];\n\tresult[0] = Tcl_NewDoubleObj((double)s->first / (double)s->total);\n\tresult[1] = Tcl_NewDoubleObj((double)s->last / (double)s->total);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, result));\n\treturn TCL_OK;\n    } else if (objc == 3) {\n\tif (Tcl_GetSizeIntFromObj(interp, objv[2], &newFirst) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tdouble fraction;\n\tint count;\n\n\tswitch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) {\n\t    case TK_SCROLL_MOVETO:\n\t\tnewFirst = (Tcl_Size) ((fraction * (double)s->total) + 0.5);\n\t\tbreak;\n\t    case TK_SCROLL_UNITS:\n\t\tnewFirst = s->first + count;\n\t\tbreak;\n\t    case TK_SCROLL_PAGES: {\n\t\tTcl_Size perPage = s->last - s->first;\t/* @@@ */\n\t\tnewFirst = s->first + count * perPage;\n\t\tbreak;\n\t    }\n\t    default:\n\t\treturn TCL_ERROR;\n\t}\n    }\n\n    TtkScrollTo(h, newFirst, false);\n\n    return TCL_OK;\n}\n\nvoid TtkScrollTo(ScrollHandle h, Tcl_Size newFirst, bool updateScrollInfo)\n{\n    Scrollable *s = h->scrollPtr;\n\n    if (updateScrollInfo) {\n\tTtkUpdateScrollInfo(h);\n    }\n\n    if (newFirst >= s->total) {\n\tnewFirst = s->total - 1;\n    }\n    if (newFirst > s->first && s->last >= s->total) {/* don't scroll past end */\n\tnewFirst = s->first;\n    }\n    if (newFirst < 0) {\n\tnewFirst = 0;\n    }\n\n    if (newFirst != s->first) {\n\ts->first = newFirst;\n\tTtkRedisplayWidget(h->corePtr);\n    }\n}\n\nvoid TtkFreeScrollHandle(ScrollHandle h)\n{\n    if (h->flags & SCROLL_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateScrollbarBG, h);\n    }\n    Tcl_Free(h);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkScrollbar.c",
    "content": "/*\n * Copyright © 2003 Joe English\n *\n * ttk::scrollbar widget.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*------------------------------------------------------------------------\n * +++ Scrollbar widget record.\n */\ntypedef struct\n{\n    Tcl_Obj\t*commandObj;\n\n    int\torient;\n    Tcl_Obj\t*orientObj;\n\n    double\tfirst;\t\t\t/* top fraction */\n    double\tlast;\t\t\t/* bottom fraction */\n\n    Ttk_Box\ttroughBox;\t\t/* trough parcel */\n    int\tminSize;\t\t/* minimum size of thumb */\n} ScrollbarPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    ScrollbarPart scrollbar;\n} Scrollbar;\n\nstatic const Tk_OptionSpec ScrollbarOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\", \"\",\n\toffsetof(Scrollbar, scrollbar.commandObj), TCL_INDEX_NONE, 0, 0, 0},\n\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\", \"vertical\",\n\toffsetof(Scrollbar, scrollbar.orientObj),\n\toffsetof(Scrollbar, scrollbar.orient),\n\t0, ttkOrientStrings, STYLE_CHANGED },\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget hooks.\n */\n\nstatic void\nScrollbarInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr)\n{\n    Scrollbar *sb = (Scrollbar *)recordPtr;\n\n    sb->scrollbar.first = 0.0;\n    sb->scrollbar.last = 1.0;\n\n    TtkTrackElementState(&sb->core);\n}\n\nstatic Ttk_Layout ScrollbarGetLayout(\n    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Scrollbar *sb = (Scrollbar *)recordPtr;\n    return TtkWidgetGetOrientedLayout(\n\tinterp, theme, recordPtr, sb->scrollbar.orientObj);\n}\n\n/*\n * ScrollbarDoLayout --\n *\tLayout hook.  Adjusts the position of the scrollbar thumb.\n *\n * Side effects:\n *\tSets sb->troughBox and sb->minSize.\n */\nstatic void ScrollbarDoLayout(void *recordPtr)\n{\n    Scrollbar *sb = (Scrollbar *)recordPtr;\n    WidgetCore *corePtr = &sb->core;\n    Ttk_Element thumb;\n    Ttk_Box thumbBox;\n    int thumbWidth, thumbHeight;\n    double first, last, size;\n    int minSize;\n\n    /*\n     * Use generic layout manager to compute initial layout:\n     */\n    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));\n\n    /*\n     * Locate thumb element, extract parcel and requested minimum size:\n     */\n    thumb = Ttk_FindElement(corePtr->layout, \"thumb\");\n    if (!thumb)\t/* Something has gone wrong -- bail */\n\treturn;\n\n    sb->scrollbar.troughBox = thumbBox = Ttk_ElementParcel(thumb);\n    Ttk_LayoutNodeReqSize(\n\tcorePtr->layout, thumb, &thumbWidth,&thumbHeight);\n\n    /*\n     * Adjust thumb element parcel:\n     */\n    first = sb->scrollbar.first;\n    last  = sb->scrollbar.last;\n\n    if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {\n\tminSize = thumbHeight;\n\tsize = thumbBox.height - minSize;\n\tthumbBox.y += (int)(size * first);\n\tthumbBox.height = (int)(size * last) + minSize - (int)(size * first);\n    } else {\n\tminSize = thumbWidth;\n\tsize = thumbBox.width - minSize;\n\tthumbBox.x += (int)(size * first);\n\tthumbBox.width = (int)(size * last) + minSize - (int)(size * first);\n    }\n    sb->scrollbar.minSize = minSize;\n    Ttk_PlaceElement(corePtr->layout, thumb, thumbBox);\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands.\n */\n\n/* $sb set $first $last --\n *\tSet the position of the scrollbar.\n */\nstatic int\nScrollbarSetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scrollbar *scrollbar = (Scrollbar *)recordPtr;\n    Tcl_Obj *firstObj, *lastObj;\n    double first, last;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"first last\");\n\treturn TCL_ERROR;\n    }\n\n    firstObj = objv[2];\n    lastObj = objv[3];\n    if (Tcl_GetDoubleFromObj(interp, firstObj, &first) != TCL_OK\n\t|| Tcl_GetDoubleFromObj(interp, lastObj, &last) != TCL_OK)\n\treturn TCL_ERROR;\n\n    /* Range-checks:\n     */\n    if (first < 0.0) {\n\tfirst = 0.0;\n    } else if (first > 1.0) {\n\tfirst = 1.0;\n    }\n\n    if (last < first) {\n\tlast = first;\n    } else if (last > 1.0) {\n\tlast = 1.0;\n    }\n\n    /* ASSERT: 0.0 <= first <= last <= 1.0 */\n\n    scrollbar->scrollbar.first = first;\n    scrollbar->scrollbar.last = last;\n    if (first <= 0.0 && last >= 1.0) {\n\tscrollbar->core.state |= TTK_STATE_DISABLED;\n    } else {\n\tscrollbar->core.state &= ~TTK_STATE_DISABLED;\n    }\n\n    TtkRedisplayWidget(&scrollbar->core);\n\n    return TCL_OK;\n}\n\n/* $sb get --\n *\tReturns the last thing passed to 'set'.\n */\nstatic int\nScrollbarGetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scrollbar *scrollbar = (Scrollbar *)recordPtr;\n    Tcl_Obj *result[2];\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    result[0] = Tcl_NewDoubleObj(scrollbar->scrollbar.first);\n    result[1] = Tcl_NewDoubleObj(scrollbar->scrollbar.last);\n    Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));\n\n    return TCL_OK;\n}\n\n/* $sb delta $dx $dy --\n *\tReturns the percentage change corresponding to a mouse movement\n *\tof $dx, $dy.\n */\nstatic int\nScrollbarDeltaCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scrollbar *sb = (Scrollbar *)recordPtr;\n    double dx, dy;\n    double delta = 0.0;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"dx dy\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &dx) != TCL_OK\n\t|| Tcl_GetDoubleFromObj(interp, objv[3], &dy) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    delta = 0.0;\n    if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {\n\tint size = sb->scrollbar.troughBox.height - sb->scrollbar.minSize;\n\tif (size > 0) {\n\t    delta = (double)dy / (double)size;\n\t}\n    } else {\n\tint size = sb->scrollbar.troughBox.width - sb->scrollbar.minSize;\n\tif (size > 0) {\n\t    delta = (double)dx / (double)size;\n\t}\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(delta));\n    return TCL_OK;\n}\n\n/* $sb fraction $x $y --\n *\tReturns a real number between 0 and 1 indicating  where  the\n *\tpoint given by x and y lies in the trough area of the scrollbar.\n */\nstatic int\nScrollbarFractionCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Scrollbar *sb = (Scrollbar *)recordPtr;\n    Ttk_Box b = sb->scrollbar.troughBox;\n    int minSize = sb->scrollbar.minSize;\n    double x, y;\n    double fraction = 0.0;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"x y\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK\n\t|| Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    fraction = 0.0;\n    if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) {\n\tif (b.height > minSize) {\n\t    fraction = (double)(y - b.y) / (double)(b.height - minSize);\n\t}\n    } else {\n\tif (b.width > minSize) {\n\t    fraction = (double)(x - b.x) / (double)(b.width - minSize);\n\t}\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));\n    return TCL_OK;\n}\n\nstatic const Ttk_Ensemble ScrollbarCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"delta\",\tScrollbarDeltaCommand,0 },\n    { \"fraction\",\tScrollbarFractionCommand,0 },\n    { \"get\",\tScrollbarGetCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"set\",\t\tScrollbarSetCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget specification.\n */\nstatic const WidgetSpec ScrollbarWidgetSpec =\n{\n    \"TScrollbar\",\t\t/* className */\n    sizeof(Scrollbar),\t\t/* recordSize */\n    ScrollbarOptionSpecs,\t/* optionSpecs */\n    ScrollbarCommands,\t\t/* subcommands */\n    ScrollbarInitialize,\t/* initializeProc */\n    TtkNullCleanup,\t\t/* cleanupProc */\n    TtkCoreConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    ScrollbarGetLayout,\t\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    ScrollbarDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(VerticalScrollbarLayout)\n    TTK_GROUP(\"Vertical.Scrollbar.trough\", TTK_FILL_Y,\n\tTTK_NODE(\"Vertical.Scrollbar.uparrow\", TTK_PACK_TOP)\n\tTTK_NODE(\"Vertical.Scrollbar.downarrow\", TTK_PACK_BOTTOM)\n\tTTK_NODE(\"Vertical.Scrollbar.thumb\", TTK_FILL_BOTH))\nTTK_END_LAYOUT\n\nTTK_BEGIN_LAYOUT(HorizontalScrollbarLayout)\n    TTK_GROUP(\"Horizontal.Scrollbar.trough\", TTK_FILL_X,\n\tTTK_NODE(\"Horizontal.Scrollbar.leftarrow\", TTK_PACK_LEFT)\n\tTTK_NODE(\"Horizontal.Scrollbar.rightarrow\", TTK_PACK_RIGHT)\n\tTTK_NODE(\"Horizontal.Scrollbar.thumb\", TTK_FILL_BOTH))\nTTK_END_LAYOUT\n\n/*------------------------------------------------------------------------\n * +++ Initialization.\n */\n\nMODULE_SCOPE void\nTtkScrollbar_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(theme,\"Vertical.TScrollbar\",VerticalScrollbarLayout);\n    Ttk_RegisterLayout(theme,\"Horizontal.TScrollbar\",HorizontalScrollbarLayout);\n\n    RegisterWidget(interp, \"ttk::scrollbar\", &ScrollbarWidgetSpec);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkSeparator.c",
    "content": "/*\n * Copyright © 2004 Joe English\n *\n * ttk::separator and ttk::sizegrip widgets.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/* +++ Separator widget record:\n */\ntypedef struct\n{\n    Tcl_Obj\t*orientObj;\n    int\torient;\n} SeparatorPart;\n\ntypedef struct\n{\n    WidgetCore core;\n    SeparatorPart separator;\n} Separator;\n\nstatic const Tk_OptionSpec SeparatorOptionSpecs[] = {\n    {TK_OPTION_STRING_TABLE, \"-orient\", \"orient\", \"Orient\", \"horizontal\",\n\toffsetof(Separator,separator.orientObj),\n\toffsetof(Separator,separator.orient),\n\t0, ttkOrientStrings, STYLE_CHANGED },\n\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*\n * GetLayout hook --\n *\tChoose layout based on -orient option.\n */\nstatic Ttk_Layout SeparatorGetLayout(\n    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)\n{\n    Separator *sep = (Separator *)recordPtr;\n    return TtkWidgetGetOrientedLayout(\n\tinterp, theme, recordPtr, sep->separator.orientObj);\n}\n\n/*\n * Widget commands:\n */\nstatic const Ttk_Ensemble SeparatorCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*\n * Widget specification:\n */\nstatic const WidgetSpec SeparatorWidgetSpec =\n{\n    \"TSeparator\",\t\t/* className */\n    sizeof(Separator),\t\t/* recordSize */\n    SeparatorOptionSpecs,\t/* optionSpecs */\n    SeparatorCommands,\t\t/* subcommands */\n    TtkNullInitialize,\t\t/* initializeProc */\n    TtkNullCleanup,\t\t/* cleanupProc */\n    TtkCoreConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    SeparatorGetLayout,\t\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(SeparatorLayout)\n    TTK_NODE(\"Separator.separator\", TTK_FILL_BOTH)\nTTK_END_LAYOUT\n\n/* +++ Sizegrip widget:\n *\tHas no options or methods other than the standard ones.\n */\n\nstatic const Tk_OptionSpec SizegripOptionSpecs[] = {\n    WIDGET_TAKEFOCUS_FALSE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\nstatic const Ttk_Ensemble SizegripCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const WidgetSpec SizegripWidgetSpec =\n{\n    \"TSizegrip\",\t\t/* className */\n    sizeof(WidgetCore),\t\t/* recordSize */\n    SizegripOptionSpecs,\t/* optionSpecs */\n    SizegripCommands,\t\t/* subcommands */\n    TtkNullInitialize,\t\t/* initializeProc */\n    TtkNullCleanup,\t\t/* cleanupProc */\n    TtkCoreConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TtkWidgetDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\nTTK_BEGIN_LAYOUT(SizegripLayout)\n    TTK_NODE(\"Sizegrip.sizegrip\", TTK_PACK_BOTTOM|TTK_STICK_S|TTK_STICK_E)\nTTK_END_LAYOUT\n\n/* +++ Initialization:\n */\n\nMODULE_SCOPE void\nTtkSeparator_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    Ttk_RegisterLayout(theme, \"TSeparator\", SeparatorLayout);\n    Ttk_RegisterLayout(theme, \"TSizegrip\", SizegripLayout);\n\n    RegisterWidget(interp, \"ttk::separator\", &SeparatorWidgetSpec);\n    RegisterWidget(interp, \"ttk::sizegrip\", &SizegripWidgetSpec);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkSquare.c",
    "content": "/* square.c - Copyright © 2004 Pat Thoyts <patthoyts@users.sourceforge.net>\n *\n * Minimal sample ttk widget.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n#if defined(TTK_SQUARE_WIDGET) || 1\n\n#ifndef DEFAULT_BORDERWIDTH\n#define DEFAULT_BORDERWIDTH \"2\"\n#endif\n\n/*\n * First, we setup the widget record. The Ttk package provides a structure\n * that contains standard widget data so it is only necessary to define\n * a structure that holds the data required for our widget. We do this by\n * defining a widget part and then specifying the widget record as the\n * concatenation of the two structures.\n */\n\ntypedef struct\n{\n    Tcl_Obj *widthObj;\n    Tcl_Obj *heightObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *paddingObj;\n    Tcl_Obj *anchorObj;\n} SquarePart;\n\ntypedef struct\n{\n    WidgetCore core;\n    SquarePart square;\n} Square;\n\n/*\n * Widget options.\n *\n * This structure is the same as the option specification structure used\n * for Tk widgets. For each option we provide the type, name and options\n * database name and class name and the position in the structure and\n * default values. At the bottom we bring in the standard widget option\n * defined for all widgets.\n */\n\nstatic const Tk_OptionSpec SquareOptionSpecs[] =\n{\n    {TK_OPTION_PIXELS, \"-borderwidth\", \"borderWidth\", \"BorderWidth\",\n     DEFAULT_BORDERWIDTH, offsetof(Square,square.borderWidthObj), TCL_INDEX_NONE,\n     0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_BORDER, \"-foreground\", \"foreground\", \"Foreground\",\n     DEFAULT_BACKGROUND, offsetof(Square,square.foregroundObj),\n     TCL_INDEX_NONE, 0, 0, 0},\n\n    {TK_OPTION_PIXELS, \"-width\", \"width\", \"Width\",\n     \"50\", offsetof(Square,square.widthObj), TCL_INDEX_NONE, 0, 0,\n     GEOMETRY_CHANGED},\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\",\n     \"50\", offsetof(Square,square.heightObj), TCL_INDEX_NONE, 0, 0,\n     GEOMETRY_CHANGED},\n\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Pad\", NULL,\n     offsetof(Square,square.paddingObj), TCL_INDEX_NONE,\n     TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n\n    {TK_OPTION_RELIEF, \"-relief\", \"relief\", \"Relief\",\n     NULL, offsetof(Square,square.reliefObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},\n\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n     \"center\", offsetof(Square,square.anchorObj), TCL_INDEX_NONE, 0, 0, 0},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*\n * Almost all of the widget functionality is handled by the default Ttk\n * widget code and the contained element. The one thing that we must handle\n * is the -anchor option which positions the square element within the parcel\n * of space available for the widget.\n * To do this we must find out the layout preferences for the square\n * element and adjust its position within our region.\n *\n * Note that if we do not have a \"square\" elememt then just the default\n * layout will be done. So if someone places a label element into the\n * widget layout it will still be handled but the -anchor option will be\n * passed onto the label element instead of handled here.\n */\n\nstatic void\nSquareDoLayout(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    Ttk_Box winBox;\n    Ttk_Element squareNode;\n\n    squareNode = Ttk_FindElement(corePtr->layout, \"square\");\n    winBox = Ttk_WinBox(corePtr->tkwin);\n    Ttk_PlaceLayout(corePtr->layout, corePtr->state, winBox);\n\n    /*\n     * Adjust the position of the square element within the widget according\n     * to the -anchor option.\n     */\n\n    if (squareNode) {\n\tSquare *squarePtr = (Square *)clientData;\n\tTk_Anchor anchor = TK_ANCHOR_CENTER;\n\tTtk_Box b;\n\n\tb = Ttk_ElementParcel(squareNode);\n\tif (squarePtr->square.anchorObj != NULL) {\n\t    Tk_GetAnchorFromObj(NULL, squarePtr->square.anchorObj, &anchor);\n\t}\n\tb = Ttk_AnchorBox(winBox, b.width, b.height, anchor);\n\n\tTtk_PlaceElement(corePtr->layout, squareNode, b);\n    }\n}\n\n/*\n * Widget commands. A widget is impelemented as an ensemble and the\n * subcommands are listed here. Ttk provides default implementations\n * that are sufficient for our needs.\n */\n\nstatic const Ttk_Ensemble SquareCommands[] = {\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { 0,0,0 }\n};\n\n/*\n * The Widget specification structure holds all the implementation\n * information about this widget and this is what must be registered\n * with Tk in the package initialization code (see bottom).\n */\n\nstatic const WidgetSpec SquareWidgetSpec =\n{\n    \"TSquare\",\t\t\t/* className */\n    sizeof(Square),\t\t/* recordSize */\n    SquareOptionSpecs,\t\t/* optionSpecs */\n    SquareCommands,\t\t/* subcommands */\n    TtkNullInitialize,\t\t/* initializeProc */\n    TtkNullCleanup,\t\t/* cleanupProc */\n    TtkCoreConfigure,\t\t/* configureProc */\n    TtkNullPostConfigure,\t\t/* postConfigureProc */\n    TtkWidgetGetLayout,\t\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    SquareDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\n/* ----------------------------------------------------------------------\n * Square element\n *\n * In this section we demonstrate what is required to create a new themed\n * element.\n */\n\ntypedef struct\n{\n    Tcl_Obj *borderObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *reliefObj;\n    Tcl_Obj *widthObj;\n    Tcl_Obj *heightObj;\n} SquareElement;\n\nstatic const Ttk_ElementOptionSpec SquareElementOptions[] =\n{\n    { \"-background\", TK_OPTION_BORDER, offsetof(SquareElement,borderObj),\n\tDEFAULT_BACKGROUND },\n    { \"-foreground\", TK_OPTION_BORDER, offsetof(SquareElement,foregroundObj),\n\tDEFAULT_BACKGROUND },\n    { \"-borderwidth\", TK_OPTION_PIXELS, offsetof(SquareElement,borderWidthObj),\n\tDEFAULT_BORDERWIDTH },\n    { \"-relief\", TK_OPTION_RELIEF, offsetof(SquareElement,reliefObj),\n\t\"raised\" },\n    { \"-width\",  TK_OPTION_PIXELS, offsetof(SquareElement,widthObj), \"20\"},\n    { \"-height\", TK_OPTION_PIXELS, offsetof(SquareElement,heightObj), \"20\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\n/*\n * The element geometry function is called when the layout code wishes to\n * find out how big this element wants to be. We must return our preferred\n * size and padding information\n */\n\nstatic void SquareElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    Ttk_Padding *paddingPtr)\n{\n    SquareElement *square = (SquareElement *)elementRecord;\n    int borderWidth = 0;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, square->borderWidthObj, &borderWidth);\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, square->widthObj, widthPtr);\n    Tk_GetPixelsFromObj(NULL, tkwin, square->heightObj, heightPtr);\n}\n\n/*\n * Draw the element in the box provided.\n */\n\nstatic void SquareElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    SquareElement *square = (SquareElement *)elementRecord;\n    Tk_3DBorder foreground = NULL;\n    int borderWidth = 1, relief = TK_RELIEF_FLAT;\n\n    foreground = Tk_Get3DBorderFromObj(tkwin, square->foregroundObj);\n    Tk_GetPixelsFromObj(NULL, tkwin, square->borderWidthObj, &borderWidth);\n    Tk_GetReliefFromObj(NULL, square->reliefObj, &relief);\n\n    Tk_Fill3DRectangle(tkwin, d, foreground,\n\tb.x, b.y, b.width, b.height, borderWidth, relief);\n}\n\nstatic const Ttk_ElementSpec SquareElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(SquareElement),\n    SquareElementOptions,\n    SquareElementSize,\n    SquareElementDraw\n};\n\n/* ----------------------------------------------------------------------\n *\n * Layout section.\n *\n * Every widget class needs a layout style that specifies which elements\n * are part of the widget and how they should be placed. The element layout\n * engine is similar to the Tk pack geometry manager. Read the documentation\n * for the details. In this example we just need to have the square element\n * that has been defined for this widget placed on a background. We will\n * also need some padding to keep it away from the edges.\n */\n\nTTK_BEGIN_LAYOUT(SquareLayout)\n     TTK_NODE(\"Square.background\", TTK_FILL_BOTH)\n     TTK_GROUP(\"Square.padding\", TTK_FILL_BOTH,\n\t TTK_NODE(\"Square.square\", 0))\nTTK_END_LAYOUT\n\n/* ----------------------------------------------------------------------\n *\n * Widget initialization.\n *\n * This file defines a new element and a new widget. We need to register\n * the element with the themes that will need it. In this case we will\n * register with the default theme that is the root of the theme inheritance\n * tree. This means all themes will find this element.\n * We then need to register the widget class style. This is the layout\n * specification. If a different theme requires an alternative layout, we\n * could register that here. For instance, in some themes the scrollbars have\n * one uparrow, in other themes there are two uparrow elements.\n * Finally we register the widget itself. This step creates a tcl command so\n * that we can actually create an instance of this class. The widget is\n * linked to a particular style by the widget class name. This is important\n * to realise as the programmer may change the classname when creating a\n * new instance. If this is done, a new layout will need to be created (which\n * can be done at script level). Some widgets may require particular elements\n * to be present but we try to avoid this where possible. In this widget's C\n * code, no reference is made to any particular elements. The programmer is\n * free to specify a new style using completely different elements.\n */\n\n/* public */ MODULE_SCOPE int\nTtkSquareWidget_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    /* register the new elements for this theme engine */\n    Ttk_RegisterElement(interp, theme, \"square\", &SquareElementSpec, NULL);\n\n    /* register the layout for this theme */\n    Ttk_RegisterLayout(theme, \"TSquare\", SquareLayout);\n\n    /* register the widget */\n    RegisterWidget(interp, \"ttk::square\", &SquareWidgetSpec);\n\n    return TCL_OK;\n}\n\n#endif /* TTK_SQUARE_WIDGET */\n\n"
  },
  {
    "path": "generic/ttk/ttkState.c",
    "content": "/*\n * Tk widget state utilities.\n *\n * Copyright © 2003 Joe English.  Freely redistributable.\n *\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\n/*\n * Table of state names.\n */\nstatic const struct {\n    char name[12];\n    int value;\n} stateNames[] = {\n    {\"active\", TTK_STATE_ACTIVE},\t\t/* Mouse cursor is over widget or element */\n    {\"alternate\", TTK_STATE_ALTERNATE},\t\t/* Widget-specific alternate display style */\n    {\"background\", TTK_STATE_BACKGROUND},\t/* Top-level window lost focus (Mac,Win \"inactive\") */\n    {\"disabled\", TTK_STATE_DISABLED},\t\t/* Widget is disabled */\n    {\"first\", TTK_STATE_FIRST},\t\t\t/* First */\n    {\"focus\", TTK_STATE_FOCUS},\t\t\t/* Widget has keyboard focus */\n    {\"hover\", TTK_STATE_HOVER},\t\t\t/* Mouse cursor is over widget */\n    {\"invalid\", TTK_STATE_INVALID},\t\t/* Bad value */\n    {\"last\", TTK_STATE_LAST},\t\t\t/* Last */\n    {\"leaf\", TTK_STATE_LEAF},\t\t\t/* Leaf */\n    {\"open\", TTK_STATE_OPEN},\t\t\t/* Open */\n    {\"pressed\", TTK_STATE_PRESSED},\t\t/* Pressed or \"armed\" */\n    {\"readonly\", TTK_STATE_READONLY},\t\t/* Editing/modification disabled */\n    {\"selected\", TTK_STATE_SELECTED},\t\t/* \"on\", \"true\", \"current\", etc. */\n    {\"user1\", TTK_STATE_USER1},\t\t/* User-definable state */\n    {\"user2\", TTK_STATE_USER2},\t\t/* User-definable state */\n    {\"user3\", TTK_STATE_USER3},\t\t/* User-definable state */\n    {\"user4\", TTK_STATE_USER4},\t\t/* User-definable state */\n    {\"user5\", TTK_STATE_USER5},\t\t/* User-definable state */\n    {\"user6\", TTK_STATE_USER6},\t\t/* User-definable state */\n    {\"\", 0}\n};\n\n/*------------------------------------------------------------------------\n * +++ StateSpec object type:\n *\n * The string representation consists of a list of state names,\n * each optionally prefixed by an exclamation point (!).\n *\n * The internal representation uses the upper half of the wideValue\n * to store the on bits and the lower half to store the off bits.\n * If we ever get more than 32 states, this will need to be reconsidered...\n */\n\nstatic int  StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);\nstatic void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);\nstatic void StateSpecUpdateString(Tcl_Obj *);\n\nstatic const\nTcl_ObjType StateSpecObjType =\n{\n    \"StateSpec\",\t\t/* name */\n    NULL,\t\t\t/* freeIntRepProc */\n    StateSpecDupIntRep,\t/* dupIntRepProc */\n    StateSpecUpdateString,\t/* updateStringProc */\n    StateSpecSetFromAny,\t/* setFromAnyProc */\n    TCL_OBJTYPE_V0\n};\n\nstatic void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)\n{\n    copyPtr->internalRep.wideValue = srcPtr->internalRep.wideValue;\n    copyPtr->typePtr = &StateSpecObjType;\n}\n\nstatic int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)\n{\n    int status;\n    Tcl_Size i, objc;\n    Tcl_Obj **objv;\n    unsigned int onbits = 0, offbits = 0;\n\n    status = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);\n    if (status != TCL_OK) {\n\treturn status;\n    }\n\n    for (i = 0; i < objc; ++i) {\n\tconst char *stateName = Tcl_GetString(objv[i]);\n\tint on, j;\n\n\tif (*stateName == '!') {\n\t    ++stateName;\n\t    on = 0;\n\t} else {\n\t    on = 1;\n\t}\n\n\tfor (j = 0; stateNames[j].value; ++j) {\n\t    if (strcmp(stateName, stateNames[j].name) == 0) {\n\t\tbreak;\n\t    }\n\t}\n\n\tif (stateNames[j].value == 0) {\n\t    if (interp) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"Invalid state name %s\", stateName));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"STATE\", (char *)NULL);\n\t    }\n\t    return TCL_ERROR;\n\t}\n\n\tif (on) {\n\t    onbits |= stateNames[j].value;\n\t} else {\n\t    offbits |= stateNames[j].value;\n\t}\n    }\n\n    /* Invalidate old intrep, but make sure there's a string rep, see [7231bf9941].\n     */\n    if (objPtr->typePtr) {\n\t(void)Tcl_GetString(objPtr);\n\tif (objPtr->typePtr->freeIntRepProc) {\n\t    objPtr->typePtr->freeIntRepProc(objPtr);\n\t}\n    }\n\n    objPtr->typePtr = &StateSpecObjType;\n    objPtr->internalRep.wideValue = ((Tcl_WideInt)onbits << 32) | offbits;\n\n    return TCL_OK;\n}\n\nstatic void StateSpecUpdateString(Tcl_Obj *objPtr)\n{\n    unsigned int onbits = objPtr->internalRep.wideValue >> 32;\n    unsigned int offbits = objPtr->internalRep.wideValue & 0xFFFFFFFFLL;\n    unsigned int mask = onbits | offbits;\n    Tcl_DString result;\n    Tcl_Size len;\n    int i;\n\n    Tcl_DStringInit(&result);\n\n    for (i=0; stateNames[i].value; ++i) {\n\tif (mask & stateNames[i].value) {\n\t    if (offbits & stateNames[i].value) {\n\t\tTcl_DStringAppend(&result, \"!\", 1);\n\t    }\n\t    Tcl_DStringAppend(&result, stateNames[i].name, TCL_INDEX_NONE);\n\t    Tcl_DStringAppend(&result, \" \", 1);\n\t}\n    }\n\n    len = Tcl_DStringLength(&result);\n    if (len) {\n\t/* 'len' includes extra trailing ' ' */\n\tobjPtr->bytes = (char *)Tcl_Alloc(len);\n\tobjPtr->length = len-1;\n\tstrncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);\n\tobjPtr->bytes[len-1] = '\\0';\n    } else {\n\t/* empty string */\n\tobjPtr->length = 0;\n\tobjPtr->bytes = (char *)Tcl_Alloc(1);\n\t*objPtr->bytes = '\\0';\n    }\n\n    Tcl_DStringFree(&result);\n}\n\nTcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)\n{\n    Tcl_Obj *objPtr = Tcl_NewObj();\n\n    Tcl_InvalidateStringRep(objPtr);\n    objPtr->typePtr = &StateSpecObjType;\n    objPtr->internalRep.wideValue = ((Tcl_WideInt)onbits << 32) | offbits;\n\n    return objPtr;\n}\n\nint Ttk_GetStateSpecFromObj(\n    Tcl_Interp *interp,\n    Tcl_Obj *objPtr,\n    Ttk_StateSpec *spec)\n{\n    if (objPtr->typePtr != &StateSpecObjType) {\n\tint status = StateSpecSetFromAny(interp, objPtr);\n\tif (status != TCL_OK) {\n\t    return status;\n\t}\n    }\n\n    spec->onbits = objPtr->internalRep.wideValue >> 32;\n    spec->offbits = objPtr->internalRep.wideValue & 0xFFFFFFFFLL;\n    return TCL_OK;\n}\n\n\n/*\n * Tk_StateMapLookup --\n *\n *\tA state map is a paired list of StateSpec / value pairs.\n *\tReturns the value corresponding to the first matching state\n *\tspecification, or NULL if not found or an error occurs.\n */\nTcl_Obj *Ttk_StateMapLookup(\n    Tcl_Interp *interp,\t\t/* Where to leave error messages; may be NULL */\n    Ttk_StateMap map,\t\t/* State map */\n    Ttk_State state)\t/* State to look up */\n{\n    Tcl_Obj **specs;\n    Tcl_Size j, nSpecs;\n    int status;\n\n    status = Tcl_ListObjGetElements(interp, map, &nSpecs, &specs);\n    if (status != TCL_OK) {\n\treturn NULL;\n    }\n\n    for (j = 0; j < nSpecs; j += 2) {\n\tTtk_StateSpec spec;\n\tstatus = Ttk_GetStateSpecFromObj(interp, specs[j], &spec);\n\tif (status != TCL_OK) {\n\t    return NULL;\n\t}\n\tif (Ttk_StateMatches(state, &spec)) {\n\t    return specs[j+1];\n\t}\n    }\n    if (interp) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"No match in state map\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"STATE\", \"UNMATCHED\", (char *)NULL);\n    }\n    return NULL;\n}\n\n/* Ttk_GetStateMapFromObj --\n *\tReturns a Ttk_StateMap from a Tcl_Obj*.\n *\tSince a Ttk_StateMap is just a specially-formatted Tcl_Obj,\n *\tthis basically just checks for errors.\n */\nTtk_StateMap Ttk_GetStateMapFromObj(\n    Tcl_Interp *interp,\t\t/* Where to leave error messages; may be NULL */\n    Tcl_Obj *mapObj)\t\t/* State map */\n{\n    Tcl_Obj **specs;\n    Tcl_Size j, nSpecs;\n    int status;\n\n    status = Tcl_ListObjGetElements(interp, mapObj, &nSpecs, &specs);\n    if (status != TCL_OK) {\n\treturn NULL;\n    }\n\n    if (nSpecs % 2 != 0) {\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"State map must have an even number of elements\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"VALUE\", \"STATEMAP\", (char *)NULL);\n\t}\n\treturn 0;\n    }\n\n    for (j = 0; j < nSpecs; j += 2) {\n\tTtk_StateSpec spec;\n\tif (Ttk_GetStateSpecFromObj(interp, specs[j], &spec) != TCL_OK) {\n\t    return NULL;\n\t}\n    }\n\n    return mapObj;\n}\n\n/*\n * Ttk_StateTableLooup --\n *\tLook up an index from a statically allocated state table.\n */\nint Ttk_StateTableLookup(const Ttk_StateTable *map, Ttk_State state)\n{\n    while ((state & map->onBits) != map->onBits\n\t    || (~state & map->offBits) != map->offBits)\n    {\n\t++map;\n    }\n    return map->index;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkStubInit.c",
    "content": "/*\n * This file is (mostly) automatically generated from ttk.decls.\n * It is compiled and linked in with the ttk package proper.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n\nMODULE_SCOPE const TtkStubs ttkStubs;\n\n\n#ifdef TK_NO_DEPRECATED\n#   define Ttk_RegisterElementSpec 0\n#endif /* TK_NO_DEPRECATED */\n\n#ifdef __GNUC__\n/*\n * The rest of this file shouldn't warn about deprecated functions; they're\n * there because we intend them to be so and know that this file is OK to\n * touch those fields.\n */\n#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\n/* !BEGIN!: Do not edit below this line. */\n\nconst TtkStubs ttkStubs = {\n    TCL_STUB_MAGIC,\n    TTK_STUBS_EPOCH,\n    TTK_STUBS_REVISION,\n    0,\n    Ttk_GetTheme, /* 0 */\n    Ttk_GetDefaultTheme, /* 1 */\n    Ttk_GetCurrentTheme, /* 2 */\n    Ttk_CreateTheme, /* 3 */\n    Ttk_RegisterCleanup, /* 4 */\n    Ttk_RegisterElementSpec, /* 5 */\n    Ttk_RegisterElement, /* 6 */\n    Ttk_RegisterElementFactory, /* 7 */\n    Ttk_RegisterLayout, /* 8 */\n    0, /* 9 */\n    Ttk_GetStateSpecFromObj, /* 10 */\n    Ttk_NewStateSpecObj, /* 11 */\n    Ttk_GetStateMapFromObj, /* 12 */\n    Ttk_StateMapLookup, /* 13 */\n    Ttk_StateTableLookup, /* 14 */\n    0, /* 15 */\n    0, /* 16 */\n    0, /* 17 */\n    0, /* 18 */\n    0, /* 19 */\n    Ttk_GetPaddingFromObj, /* 20 */\n    Ttk_GetBorderFromObj, /* 21 */\n    Ttk_GetStickyFromObj, /* 22 */\n    Ttk_MakePadding, /* 23 */\n    Ttk_UniformPadding, /* 24 */\n    Ttk_AddPadding, /* 25 */\n    Ttk_RelievePadding, /* 26 */\n    Ttk_MakeBox, /* 27 */\n    Ttk_BoxContains, /* 28 */\n    Ttk_PackBox, /* 29 */\n    Ttk_StickBox, /* 30 */\n    Ttk_AnchorBox, /* 31 */\n    Ttk_PadBox, /* 32 */\n    Ttk_ExpandBox, /* 33 */\n    Ttk_PlaceBox, /* 34 */\n    Ttk_NewBoxObj, /* 35 */\n    0, /* 36 */\n    0, /* 37 */\n    0, /* 38 */\n    0, /* 39 */\n    Ttk_GetOrientFromObj, /* 40 */\n};\n\n/* !END!: Do not edit above this line. */\n"
  },
  {
    "path": "generic/ttk/ttkStubLib.c",
    "content": "/*\n * We need to ensure that we use the tcl stub macros so that this file\n * contains no references to any of the tcl stub functions.\n */\n\n#undef USE_TCL_STUBS\n#define USE_TCL_STUBS\n\n#include \"tkInt.h\"\n\n#define USE_TTK_STUBS 1\n#include \"ttkTheme.h\"\n\nMODULE_SCOPE const TtkStubs *ttkStubsPtr;\nconst TtkStubs *ttkStubsPtr = NULL;\n\n/*\n *----------------------------------------------------------------------\n *\n * TtkInitializeStubs --\n *\tLoad the Ttk package, initialize stub table pointer.\n *\tDo not call this function directly, use Ttk_InitStubs() macro instead.\n *\n * Results:\n *\tThe actual version of the package that satisfies the request, or\n *\tNULL to indicate that an error occurred.\n *\n * Side effects:\n *\tSets the stub table pointer.\n *\n */\nMODULE_SCOPE const char *\nTtkInitializeStubs(\n    Tcl_Interp *interp, const char *version, int epoch, int revision)\n{\n    int exact = 0;\n    const char *packageName = \"ttk\";\n    const char *errMsg = NULL;\n    void *pkgClientData = NULL;\n    const char *actualVersion = Tcl_PkgRequireEx(\n\tinterp, packageName, version, exact, &pkgClientData);\n    const TtkStubs *stubsPtr;\n\n    if (!actualVersion) {\n\tpackageName = \"Ttk\";\n\tactualVersion = Tcl_PkgRequireEx(\n\t\tinterp, packageName, version, exact, &pkgClientData);\n\tif (!actualVersion) {\n\t    return NULL;\n\t}\n    }\n\n    stubsPtr = (const TtkStubs *)pkgClientData;\n    if (!stubsPtr) {\n\terrMsg = \"missing stub table pointer\";\n\tgoto error;\n    }\n    if (stubsPtr->epoch != epoch) {\n\terrMsg = \"epoch number mismatch\";\n\tgoto error;\n    }\n    if (stubsPtr->revision < revision) {\n\terrMsg = \"require later revision\";\n\tgoto error;\n    }\n\n    ttkStubsPtr = stubsPtr;\n    return actualVersion;\n\nerror:\n    Tcl_ResetResult(interp);\n    Tcl_AppendResult(interp,\n\t\"Error loading \", packageName, \" package\",\n\t\" (requested version '\", version,\n\t\"', loaded version '\", actualVersion, \"'): \",\n\terrMsg,\n\tNULL);\n    return NULL;\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkTagSet.c",
    "content": "/*\n * Tag tables.  3/4-baked, work in progress.\n *\n * Copyright © 2005, Joe English.  Freely redistributable.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*------------------------------------------------------------------------\n * +++ Internal data structures.\n */\nstruct TtkTag {\n    Tcl_Size\tpriority;\t\t/* 1=>highest */\n    const char\t*tagName;\t\t/* Back-pointer to hash table entry */\n    void\t*tagRecord;\t\t/* User data */\n};\n\nstruct TtkTagTable {\n    Tk_Window\t\ttkwin;\t\t/* owner window */\n    const Tk_OptionSpec\t*optionSpecs;\t/* ... */\n    Tk_OptionTable\toptionTable;\t/* ... */\n    size_t\t\t\t\trecordSize;\t/* size of tag record */\n    Tcl_Size\t\tnTags;\t\t/* #tags defined so far */\n    Tcl_HashTable\ttags;\t\t/* defined tags */\n};\n\n/*------------------------------------------------------------------------\n * +++ Tags.\n */\nstatic Ttk_Tag NewTag(Ttk_TagTable tagTable, const char *tagName)\n{\n    Ttk_Tag tag = (Ttk_Tag)Tcl_Alloc(sizeof(*tag));\n    tag->tagRecord = Tcl_Alloc(tagTable->recordSize);\n    memset(tag->tagRecord, 0, tagTable->recordSize);\n    /* Don't need Tk_InitOptions() here, all defaults should be NULL. */\n    tag->priority = ++tagTable->nTags;\n    tag->tagName = tagName;\n    return tag;\n}\n\nstatic void DeleteTag(Ttk_TagTable tagTable, Ttk_Tag tag)\n{\n    Tk_FreeConfigOptions(tag->tagRecord,tagTable->optionTable,tagTable->tkwin);\n    Tcl_Free(tag->tagRecord);\n    Tcl_Free(tag);\n}\n\n/*------------------------------------------------------------------------\n * +++ Tag tables.\n */\n\nTtk_TagTable Ttk_CreateTagTable(\n    Tcl_Interp *interp, Tk_Window tkwin,\n    const Tk_OptionSpec *optionSpecs, size_t recordSize)\n{\n    Ttk_TagTable tagTable = (Ttk_TagTable)Tcl_Alloc(sizeof(*tagTable));\n    tagTable->tkwin = tkwin;\n    tagTable->optionSpecs = optionSpecs;\n    tagTable->optionTable = Tk_CreateOptionTable(interp, optionSpecs);\n    tagTable->recordSize = recordSize;\n    tagTable->nTags = 0;\n    Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS);\n    return tagTable;\n}\n\nvoid Ttk_DeleteTagTable(Ttk_TagTable tagTable)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n\n    entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search);\n    while (entryPtr != NULL) {\n\tDeleteTag(tagTable, (Ttk_Tag)Tcl_GetHashValue(entryPtr));\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n\n    Tcl_DeleteHashTable(&tagTable->tags);\n    Tcl_Free(tagTable);\n}\n\nvoid Ttk_DeleteTagFromTable(Ttk_TagTable tagTable, Ttk_Tag tag)\n{\n    Tcl_HashEntry *entryPtr;\n\n    entryPtr = Tcl_FindHashEntry(&tagTable->tags, tag->tagName);\n    if (entryPtr != NULL) {\n\tDeleteTag(tagTable, tag);\n\tTcl_DeleteHashEntry(entryPtr);\n    }\n}\n\nTtk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName)\n{\n    int isNew = 0;\n    Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(\n\t&tagTable->tags, tagName, &isNew);\n\n    if (isNew) {\n\ttagName = (char *)Tcl_GetHashKey(&tagTable->tags, entryPtr);\n\tTcl_SetHashValue(entryPtr, NewTag(tagTable,tagName));\n    }\n    return (Ttk_Tag)Tcl_GetHashValue(entryPtr);\n}\n\nTtk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr)\n{\n    return Ttk_GetTag(tagTable, Tcl_GetString(objPtr));\n}\n\n/*------------------------------------------------------------------------\n * +++ Tag sets.\n */\n\n/* Ttk_GetTagSetFromObj --\n *\tExtract an array of pointers to Ttk_Tags from a Tcl_Obj.\n *\tobjPtr may be NULL, in which case a new empty tag set is returned.\n *\n * Returns NULL and leaves an error message in interp->result on error.\n *\n * Non-NULL results must be passed to Ttk_FreeTagSet().\n */\nTtk_TagSet Ttk_GetTagSetFromObj(\n    Tcl_Interp *interp, Ttk_TagTable tagTable, Tcl_Obj *objPtr)\n{\n    Ttk_TagSet tagset = (Ttk_TagSet)Tcl_Alloc(sizeof(*tagset));\n    Tcl_Obj **objv;\n    Tcl_Size i, objc;\n\n    if (objPtr == NULL) {\n\ttagset->tags = NULL;\n\ttagset->nTags = 0;\n\treturn tagset;\n    }\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\tTcl_Free(tagset);\n\treturn NULL;\n    }\n\n    tagset->tags = (Ttk_Tag *)Tcl_Alloc((objc+1) * sizeof(Ttk_Tag));\n    for (i = 0; i < objc; ++i) {\n\ttagset->tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);\n    }\n    tagset->tags[i] = NULL;\n    tagset->nTags = objc;\n\n    return tagset;\n}\n\n/* Ttk_NewTagSetObj --\n *\tConstruct a fresh Tcl_Obj * from a tag set.\n */\nTcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet tagset)\n{\n    Tcl_Obj *result = Tcl_NewListObj(0,0);\n    Tcl_Size i;\n\n    for (i = 0; i < tagset->nTags; ++i) {\n\tTcl_ListObjAppendElement(\n\t    NULL, result, Tcl_NewStringObj(tagset->tags[i]->tagName, -1));\n    }\n    return result;\n}\n\nvoid Ttk_FreeTagSet(Ttk_TagSet tagset)\n{\n    Tcl_Free(tagset->tags);\n    Tcl_Free(tagset);\n}\n\n/* Ttk_TagSetContains -- test if tag set contains a tag.\n */\nbool Ttk_TagSetContains(Ttk_TagSet tagset, Ttk_Tag tag)\n{\n    Tcl_Size i;\n    for (i = 0; i < tagset->nTags; ++i) {\n\tif (tagset->tags[i] == tag) {\n\t    return true;\n\t}\n    }\n    return false;\n}\n\n/* Ttk_TagSetAdd -- add a tag to a tag set.\n *\n * Returns: false if tagset already contained tag,\n * true if tagset was modified.\n */\nbool Ttk_TagSetAdd(Ttk_TagSet tagset, Ttk_Tag tag)\n{\n    Tcl_Size i;\n    for (i = 0; i < tagset->nTags; ++i) {\n\tif (tagset->tags[i] == tag) {\n\t    return false;\n\t}\n    }\n    tagset->tags = (Ttk_Tag *)Tcl_Realloc(tagset->tags,\n\t    (tagset->nTags+1)*sizeof(tagset->tags[0]));\n    tagset->tags[tagset->nTags++] = tag;\n    return true;\n}\n\n/* Ttk_TagSetAddSet -- add a tag set to a tag set.\n *\n */\nvoid Ttk_TagSetAddSet(Ttk_TagSet tagset, Ttk_TagSet tagsetFrom)\n{\n    Tcl_Size i, j, total, nTags = tagset->nTags;\n    bool found;\n    Ttk_Tag tag;\n\n    total = tagsetFrom->nTags + tagset->nTags;\n    tagset->tags = (Ttk_Tag *)Tcl_Realloc(tagset->tags,\n\t    (total)*sizeof(tagset->tags[0]));\n    for (j = 0; j < tagsetFrom->nTags; ++j) {\n\ttag = tagsetFrom->tags[j];\n\tfound = false;\n\tfor (i = 0; i < nTags; ++i) {\n\t    if (tagset->tags[i] == tag) {\n\t\tfound = true;\n\t\tbreak;\n\t    }\n\t}\n\tif (found) continue;\n\ttagset->tags[tagset->nTags++] = tag;\n    }\n}\n\n/* Ttk_TagSetRemove -- remove a tag from a tag set.\n *\n * Returns: false if tagset did not contain tag,\n * true if tagset was modified.\n */\nbool Ttk_TagSetRemove(Ttk_TagSet tagset, Ttk_Tag tag)\n{\n    Tcl_Size i = 0, j = 0;\n    while (i < tagset->nTags) {\n\tif ((tagset->tags[j] = tagset->tags[i]) != tag) {\n\t    ++j;\n\t}\n\t++i;\n    }\n    tagset->nTags = j;\n    return j != i;\n}\n\n/*------------------------------------------------------------------------\n * +++ Utilities for widget commands.\n */\n\n/* Ttk_EnumerateTags -- implements [$w tag names]\n */\nint Ttk_EnumerateTags(\n    Tcl_Interp *interp, Ttk_TagTable tagTable)\n{\n    return TtkEnumerateHashTable(interp, &tagTable->tags);\n}\n\n/* Ttk_EnumerateTagOptions -- implements [$w tag configure $tag]\n */\nint Ttk_EnumerateTagOptions(\n    Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag)\n{\n    return TtkEnumerateOptions(interp, tag->tagRecord,\n\ttagTable->optionSpecs, tagTable->optionTable, tagTable->tkwin);\n}\n\n/* Ttk_TagOptionValue -- implements [$w tag configure $tag -option]\n */\nTcl_Obj *Ttk_TagOptionValue(\n    Tcl_Interp *interp,\n    Ttk_TagTable tagTable,\n    Ttk_Tag tag,\n    Tcl_Obj *optionName)\n{\n    return Tk_GetOptionValue(interp,\n\ttag->tagRecord, tagTable->optionTable, optionName, tagTable->tkwin);\n}\n\n/* Ttk_ConfigureTag -- implements [$w tag configure $tag -option value...]\n */\nint Ttk_ConfigureTag(\n    Tcl_Interp *interp,\n    Ttk_TagTable tagTable,\n    Ttk_Tag tag,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    return Tk_SetOptions(\n\tinterp, tag->tagRecord, tagTable->optionTable,\n\tobjc, objv, tagTable->tkwin, NULL/*savedOptions*/, NULL/*mask*/);\n}\n\n/*------------------------------------------------------------------------\n * +++ Tag values.\n */\n\n#define OBJ_AT(record, offset) (*(Tcl_Obj**)(((char*)record)+offset))\n\nvoid Ttk_TagSetDefaults(Ttk_TagTable tagTable, Ttk_Style style, void *record)\n{\n    const Tk_OptionSpec *optionSpec = tagTable->optionSpecs;\n    memset(record, 0, tagTable->recordSize);\n\n    while (optionSpec->type != TK_OPTION_END) {\n\tTcl_Size offset = optionSpec->objOffset;\n\tconst char *optionName = optionSpec->optionName;\n\tOBJ_AT(record, offset) = Ttk_StyleDefault(style, optionName);\n\t++optionSpec;\n    }\n}\n\nvoid Ttk_TagSetValues(Ttk_TagTable tagTable, Ttk_TagSet tagSet, void *record)\n{\n    Tcl_Size i, j;\n\n    for (i = 0; tagTable->optionSpecs[i].type != TK_OPTION_END; ++i) {\n\tconst Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i;\n\tTcl_Size offset = optionSpec->objOffset;\n\tTcl_Size prio = TCL_SIZE_MAX;\n\n\tfor (j = 0; j < tagSet->nTags; ++j) {\n\t    Ttk_Tag tag = tagSet->tags[j];\n\t    if (OBJ_AT(tag->tagRecord, offset) != 0 && tag->priority < prio) {\n\t\tOBJ_AT(record, offset) = OBJ_AT(tag->tagRecord, offset);\n\t\tprio = tag->priority;\n\t    }\n\t}\n    }\n}\n\nvoid Ttk_TagSetApplyStyle(\n    Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record)\n{\n    const Tk_OptionSpec *optionSpec = tagTable->optionSpecs;\n\n    while (optionSpec->type != TK_OPTION_END) {\n\tTcl_Size offset = optionSpec->objOffset;\n\tconst char *optionName = optionSpec->optionName;\n\tTcl_Obj *val = Ttk_StyleMap(style, optionName, state);\n\tif (val) {\n\t    OBJ_AT(record, offset) = val;\n\t}\n\t++optionSpec;\n    }\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkTheme.c",
    "content": "/*\n * ttkTheme.c --\n *\n *\tThis file implements the widget styles and themes support.\n *\n * Copyright © 2002 Frederic Bonnet\n * Copyright © 2003 Joe English\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n\n#define PKG_ASSOC_KEY \"Ttk\"\n\n/*------------------------------------------------------------------------\n * +++ Styles.\n *\n * Invariants:\n *\tIf styleName contains a dot, parentStyle->styleName is everything\n *\tafter the first dot; otherwise, parentStyle is the theme's root\n *\tstyle \".\".  The root style's parentStyle is NULL.\n *\n */\n\ntypedef struct Ttk_Style_\n{\n    const char\t\t*styleName;\t/* points to hash table key */\n    Tcl_HashTable\tsettingsTable;\t/* KEY: string; VALUE: StateMap */\n    Tcl_HashTable\tdefaultsTable;\t/* KEY: string; VALUE: resource */\n    Ttk_LayoutTemplate\tlayoutTemplate;\t/* Layout template for style, or NULL */\n    Ttk_Style\t\tparentStyle;\t/* Previous style in chain */\n    Ttk_ResourceCache\tcache;\t\t/* Back-pointer to resource cache */\n} Style;\n\nstatic Style *NewStyle(void)\n{\n    Style *stylePtr = (Style *)Tcl_Alloc(sizeof(Style));\n\n    stylePtr->styleName = NULL;\n    stylePtr->parentStyle = NULL;\n    stylePtr->layoutTemplate = NULL;\n    stylePtr->cache = NULL;\n    Tcl_InitHashTable(&stylePtr->settingsTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&stylePtr->defaultsTable, TCL_STRING_KEYS);\n\n    return stylePtr;\n}\n\nstatic void FreeStyle(Style *stylePtr)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n\n    entryPtr = Tcl_FirstHashEntry(&stylePtr->settingsTable, &search);\n    while (entryPtr != NULL) {\n\tTtk_StateMap stateMap = (Ttk_StateMap)Tcl_GetHashValue(entryPtr);\n\tTcl_DecrRefCount(stateMap);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&stylePtr->settingsTable);\n\n    entryPtr = Tcl_FirstHashEntry(&stylePtr->defaultsTable, &search);\n    while (entryPtr != NULL) {\n\tTcl_Obj *defaultValue = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tTcl_DecrRefCount(defaultValue);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&stylePtr->defaultsTable);\n\n    Ttk_FreeLayoutTemplate(stylePtr->layoutTemplate);\n\n    Tcl_Free(stylePtr);\n}\n\n/*\n * Ttk_StyleMap --\n *\tLook up state-specific option value from specified style.\n */\nTcl_Obj *Ttk_StyleMap(Ttk_Style style, const char *optionName, Ttk_State state)\n{\n    while (style) {\n\tTcl_HashEntry *entryPtr =\n\t    Tcl_FindHashEntry(&style->settingsTable, optionName);\n\tif (entryPtr) {\n\t    Ttk_StateMap stateMap = (Ttk_StateMap)Tcl_GetHashValue(entryPtr);\n\t    return Ttk_StateMapLookup(NULL, stateMap, state);\n\t}\n\tstyle = style->parentStyle;\n    }\n    return 0;\n}\n\n/*\n * Ttk_StyleDefault --\n *\tLook up default resource setting in the specified style.\n */\nTcl_Obj *Ttk_StyleDefault(Ttk_Style style, const char *optionName)\n{\n    while (style) {\n\tTcl_HashEntry *entryPtr =\n\t    Tcl_FindHashEntry(&style->defaultsTable, optionName);\n\tif (entryPtr) {\n\t    return (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\t}\n\tstyle= style->parentStyle;\n    }\n    return 0;\n}\n\n/*------------------------------------------------------------------------\n * +++ Elements.\n */\ntypedef const Tk_OptionSpec **OptionMap;\n    /* array of Tk_OptionSpecs mapping widget options to element options */\n\nstruct Ttk_ElementClass_ {\n    const char *name;\t\t/* Points to hash table key */\n    const Ttk_ElementSpec *specPtr;\t/* Template provided during registration. */\n    void *clientData;\t\t/* Client data passed in at registration time */\n    void *elementRecord;\t/* Scratch buffer for element record storage */\n    int nResources;\t\t/* #Element options */\n    Tcl_Obj **defaultValues;\t/* Array of option default values */\n    Tcl_HashTable optMapCache;\t/* Map: Tk_OptionTable * -> OptionMap */\n};\n\n/* TTKGetOptionSpec --\n *\tLook up a Tk_OptionSpec by name from a Tk_OptionTable,\n *\tand verify that it's compatible with the specified Tk_OptionType,\n *\talong with other constraints (see below).\n */\nstatic const Tk_OptionSpec *TTKGetOptionSpec(\n    const char *optionName,\n    Tk_OptionTable optionTable,\n    Tk_OptionType optionType)\n{\n    const Tk_OptionSpec *optionSpec = TkGetOptionSpec(optionName, optionTable);\n\n    if (!optionSpec) {\n\treturn 0;\n    }\n\n    /* Make sure widget option has a Tcl_Obj* entry:\n     */\n    if (optionSpec->objOffset < 0) {\n\treturn 0;\n    }\n\n    /* Grrr.  Ignore accidental mismatches caused by prefix-matching:\n     */\n    if (strcmp(optionSpec->optionName, optionName)) {\n\treturn 0;\n    }\n\n    /* Ensure that the widget option type is compatible with\n     * the element option type.\n     *\n     * TK_OPTION_STRING element options are compatible with anything.\n     * As a workaround for the workaround for Bug #967209,\n     * TK_OPTION_STRING widget options are also compatible with anything\n     * (see <<NOTE-NULLOPTIONS>>).\n     */\n    if (   optionType != TK_OPTION_STRING\n\t&& optionSpec->type != TK_OPTION_STRING\n\t&& optionType != optionSpec->type)\n    {\n\treturn 0;\n    }\n\n    return optionSpec;\n}\n\n/* BuildOptionMap --\n *\tConstruct the mapping from element options to widget options.\n */\nstatic OptionMap\nBuildOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable)\n{\n    OptionMap optionMap = (OptionMap)Tcl_Alloc(\n\t    sizeof(const Tk_OptionSpec) * elementClass->nResources + 1);\n    int i;\n\n    for (i = 0; i < elementClass->nResources; ++i) {\n\tconst Ttk_ElementOptionSpec *e = elementClass->specPtr->options+i;\n\toptionMap[i] = TTKGetOptionSpec(e->optionName, optionTable, e->type);\n    }\n\n    return optionMap;\n}\n\n/* GetOptionMap --\n *\tReturn a cached OptionMap matching the specified optionTable\n *\tfor the specified element, creating it if necessary.\n */\nstatic OptionMap\nGetOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable)\n{\n    OptionMap optionMap;\n    int isNew;\n    Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(\n\t&elementClass->optMapCache, (void*)optionTable, &isNew);\n\n    if (isNew) {\n\toptionMap = BuildOptionMap(elementClass, optionTable);\n\tTcl_SetHashValue(entryPtr, optionMap);\n    } else {\n\toptionMap = (OptionMap)Tcl_GetHashValue(entryPtr);\n    }\n\n    return optionMap;\n}\n\n/*\n * NewElementClass --\n *\tAllocate and initialize an element class record\n *\tfrom the specified element specification.\n */\nstatic Ttk_ElementClass *\nNewElementClass(const char *name, const Ttk_ElementSpec *specPtr, void *clientData)\n{\n    Ttk_ElementClass *elementClass = (Ttk_ElementClass *)Tcl_Alloc(sizeof(Ttk_ElementClass));\n    int i;\n\n    elementClass->name = name;\n    elementClass->specPtr = specPtr;\n    elementClass->clientData = clientData;\n    elementClass->elementRecord = Tcl_Alloc(specPtr->elementSize);\n\n    /* Count #element resources:\n     */\n    for (i = 0; specPtr->options[i].optionName != 0; ++i)\n\tcontinue;\n    elementClass->nResources = i;\n\n    /* Initialize default values:\n     */\n    elementClass->defaultValues = (Tcl_Obj **)\n\tTcl_Alloc(elementClass->nResources * sizeof(Tcl_Obj *) + 1);\n    for (i=0; i < elementClass->nResources; ++i) {\n\tconst char *defaultValue = specPtr->options[i].defaultValue;\n\tif (defaultValue) {\n\t    elementClass->defaultValues[i] = Tcl_NewStringObj(defaultValue,-1);\n\t    Tcl_IncrRefCount(elementClass->defaultValues[i]);\n\t} else {\n\t    elementClass->defaultValues[i] = 0;\n\t}\n    }\n\n    /* Initialize option map cache:\n     */\n    Tcl_InitHashTable(&elementClass->optMapCache, TCL_ONE_WORD_KEYS);\n\n    return elementClass;\n}\n\n/*\n * FreeElementClass --\n *\tRelease resources associated with an element class record.\n */\nstatic void FreeElementClass(Ttk_ElementClass *elementClass)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n    int i;\n\n    /*\n     * Free default values:\n     */\n    for (i = 0; i < elementClass->nResources; ++i) {\n\tif (elementClass->defaultValues[i]) {\n\t    Tcl_DecrRefCount(elementClass->defaultValues[i]);\n\t}\n    }\n    Tcl_Free(elementClass->defaultValues);\n\n    /*\n     * Free option map cache:\n     */\n    entryPtr = Tcl_FirstHashEntry(&elementClass->optMapCache, &search);\n    while (entryPtr != NULL) {\n\tTcl_Free(Tcl_GetHashValue(entryPtr));\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&elementClass->optMapCache);\n\n    Tcl_Free(elementClass->elementRecord);\n    Tcl_Free(elementClass);\n}\n\n/*------------------------------------------------------------------------\n * +++ Themes.\n */\n\nstatic int ThemeEnabled(\n    TCL_UNUSED(Ttk_Theme),\n    TCL_UNUSED(void *))\n{\n    /* Default ThemeEnabledProc -- always return true */\n    return 1;\n}\n\ntypedef struct Ttk_Theme_\n{\n    Ttk_Theme parentPtr;\t\t\t/* Parent theme. */\n    Tcl_HashTable elementTable;\t\t/* Map element names to class records */\n    Tcl_HashTable styleTable;\t\t\t/* Map style names to Styles */\n    Ttk_Style rootStyle;\t\t/* \".\" style, root of chain */\n    Ttk_ThemeEnabledProc *enabledProc;\t/* Function called by SetTheme */\n    void *enabledData;\t\t\t\t\t/* ClientData for enabledProc */\n    Ttk_ResourceCache cache;\t\t/* Back-pointer to resource cache */\n} Theme;\n\nstatic Theme *NewTheme(Ttk_ResourceCache cache, Ttk_Theme parent)\n{\n    Theme *themePtr = (Theme *)Tcl_Alloc(sizeof(Theme));\n    Tcl_HashEntry *entryPtr;\n    int unused;\n\n    themePtr->parentPtr = parent;\n    themePtr->enabledProc = ThemeEnabled;\n    themePtr->enabledData = NULL;\n    themePtr->cache = cache;\n    Tcl_InitHashTable(&themePtr->elementTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&themePtr->styleTable, TCL_STRING_KEYS);\n\n    /*\n     * Create root style \".\"\n     */\n    entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, \".\", &unused);\n    themePtr->rootStyle = NewStyle();\n    themePtr->rootStyle->styleName =\n\t(const char *)Tcl_GetHashKey(&themePtr->styleTable, entryPtr);\n    themePtr->rootStyle->cache = themePtr->cache;\n    Tcl_SetHashValue(entryPtr, themePtr->rootStyle);\n\n    return themePtr;\n}\n\nstatic void FreeTheme(Theme *themePtr)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n\n    /*\n     * Free element table:\n     */\n    entryPtr = Tcl_FirstHashEntry(&themePtr->elementTable, &search);\n    while (entryPtr != NULL) {\n\tTtk_ElementClass *elementClass = (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);\n\tFreeElementClass(elementClass);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&themePtr->elementTable);\n\n    /*\n     * Free style table:\n     */\n    entryPtr = Tcl_FirstHashEntry(&themePtr->styleTable, &search);\n    while (entryPtr != NULL) {\n\tStyle *stylePtr = (Style *)Tcl_GetHashValue(entryPtr);\n\tFreeStyle(stylePtr);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&themePtr->styleTable);\n\n    /*\n     * Free theme record:\n     */\n    Tcl_Free(themePtr);\n\n    return;\n}\n\n/*\n * Element constructors.\n */\ntypedef struct {\n    Ttk_ElementFactory\tfactory;\n    void\t\t*clientData;\n} FactoryRec;\n\n/*\n * Cleanup records:\n */\ntypedef struct CleanupStruct {\n    void *clientData;\n    Ttk_CleanupProc *cleanupProc;\n    struct CleanupStruct *next;\n} Cleanup;\n\n/*------------------------------------------------------------------------\n * +++ Style package data structure.\n */\ntypedef struct\n{\n    Tcl_Interp *interp;\t\t\t/* Owner interp */\n    Tcl_HashTable themeTable;\t\t/* KEY: name; VALUE: Theme pointer */\n    Tcl_HashTable factoryTable;\t/* KEY: name; VALUE: FactoryRec ptr */\n    Theme *defaultTheme;\t\t/* Default theme; global fallback*/\n    Theme *currentTheme;\t\t/* Currently-selected theme */\n    Cleanup *cleanupList;\t\t/* Cleanup records */\n    Ttk_ResourceCache cache;\t\t/* Resource cache */\n    int themeChangePending;\t\t/* scheduled ThemeChangedProc call? */\n} StylePackageData;\n\n/* Ttk_StylePkgFree --\n *\tCleanup procedure for StylePackageData.\n */\nstatic void Ttk_StylePkgFree(\n    void *clientData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr;\n    Cleanup *cleanup;\n\n    /*\n     * Free themes.\n     */\n    entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);\n    while (entryPtr != NULL) {\n\tTheme *themePtr = (Theme *)Tcl_GetHashValue(entryPtr);\n\tFreeTheme(themePtr);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&pkgPtr->themeTable);\n\n    /*\n     * Free element constructor table:\n     */\n    entryPtr = Tcl_FirstHashEntry(&pkgPtr->factoryTable, &search);\n    while (entryPtr != NULL) {\n\tTcl_Free(Tcl_GetHashValue(entryPtr));\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_DeleteHashTable(&pkgPtr->factoryTable);\n\n    /*\n     * Release cache:\n     */\n    Ttk_FreeResourceCache(pkgPtr->cache);\n\n    /*\n     * Call all registered cleanup procedures:\n     */\n    cleanup = pkgPtr->cleanupList;\n    while (cleanup) {\n\tCleanup *next = cleanup->next;\n\tcleanup->cleanupProc(cleanup->clientData);\n\tTcl_Free(cleanup);\n\tcleanup = next;\n    }\n\n    Tcl_Free(pkgPtr);\n}\n\n/*\n * GetStylePackageData --\n *\tLook up the package data registered with the interp.\n */\n\nstatic StylePackageData *GetStylePackageData(Tcl_Interp *interp)\n{\n    return (StylePackageData *)Tcl_GetAssocData(interp, PKG_ASSOC_KEY, NULL);\n}\n\n/*\n * Ttk_RegisterCleanup --\n *\n *\tRegister a function to be called when a theme engine is deleted.\n *\t(This only happens when the main interp is destroyed). The cleanup\n *\tfunction is called with the current Tcl interpreter and the client\n *\tdata provided here.\n *\n */\nvoid Ttk_RegisterCleanup(\n    Tcl_Interp *interp, void *clientData, Ttk_CleanupProc *cleanupProc)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    Cleanup *cleanup = (Cleanup *)Tcl_Alloc(sizeof(*cleanup));\n\n    cleanup->clientData = clientData;\n    cleanup->cleanupProc = cleanupProc;\n    cleanup->next = pkgPtr->cleanupList;\n    pkgPtr->cleanupList = cleanup;\n}\n\n/* ThemeChangedProc --\n *\tNotify all widgets that the theme has been changed.\n *\tScheduled as an idle callback; clientData is a StylePackageData *.\n *\n *\tSends a <<ThemeChanged>> event to every widget in the hierarchy.\n *\tWidgets respond to this by calling the  WorldChanged class proc,\n *\twhich in turn recreates the layout.\n *\n *\tThe Tk C API doesn't doesn't provide an easy way to traverse\n *\tthe widget hierarchy, so this is done by evaluating a Tcl script.\n */\n\nstatic void ThemeChangedProc(void *clientData)\n{\n    static char ThemeChangedScript[] = \"ttk::ThemeChanged\";\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n\n    int code = Tcl_EvalEx(pkgPtr->interp, ThemeChangedScript, -1, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_BackgroundException(pkgPtr->interp, code);\n    }\n    pkgPtr->themeChangePending = 0;\n}\n\n/*\n * ThemeChanged --\n *\tSchedule a call to ThemeChanged if one is not already pending.\n */\nstatic void ThemeChanged(StylePackageData *pkgPtr)\n{\n    TtkSetBlinkCursorTimes(pkgPtr->interp);\n\n    if (!pkgPtr->themeChangePending) {\n\tTcl_DoWhenIdle(ThemeChangedProc, pkgPtr);\n\tpkgPtr->themeChangePending = 1;\n    }\n}\n\n/* Ttk_TkDestroyedHandler --\n *\tSee bug [310c74ecf440]: idle calls to ThemeChangedProc()\n *\tneed to be canceled when Tk is destroyed, since the interp\n *\tmay still be active afterward; canceling them from\n *\tTtk_StylePkgFree() would be too late.\n */\nvoid Ttk_TkDestroyedHandler(\n    Tcl_Interp* interp)\n{\n    StylePackageData* pkgPtr = GetStylePackageData(interp);\n\n    /*\n     * Cancel any pending ThemeChanged calls. We might be called\n     * before Ttk is initialized. See bug [3981091ed336].\n     */\n    if (pkgPtr && pkgPtr->themeChangePending) {\n\tTcl_CancelIdleCall(ThemeChangedProc, pkgPtr);\n    }\n}\n\n/*\n * Ttk_CreateTheme --\n *\tCreate a new theme and register it in the global theme table.\n *\n * Returns:\n *\tPointer to new Theme structure; NULL if named theme already exists.\n *\tLeaves an error message in interp's result on error.\n */\n\nTtk_Theme\nTtk_CreateTheme(\n    Tcl_Interp *interp,\t\t/* Interpreter in which to create theme */\n    const char *name,\t\t/* Name of the theme to create. */\n    Ttk_Theme parent)\t\t/* Parent/fallback theme, NULL for default */\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    Tcl_HashEntry *entryPtr;\n    int newEntry;\n    Theme *themePtr;\n\n    entryPtr = Tcl_CreateHashEntry(&pkgPtr->themeTable, name, &newEntry);\n    if (!newEntry) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Theme %s already exists\", name));\n\tTcl_SetErrorCode(interp, \"TTK\", \"THEME\", \"EXISTS\", (char *)NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Initialize new theme:\n     */\n    if (!parent) parent = pkgPtr->defaultTheme;\n\n    themePtr = NewTheme(pkgPtr->cache, parent);\n    Tcl_SetHashValue(entryPtr, themePtr);\n\n    return themePtr;\n}\n\n/*\n * Ttk_SetThemeEnabledProc --\n *\tSets a procedure that is used to check that this theme is available.\n */\n\nvoid Ttk_SetThemeEnabledProc(\n    Ttk_Theme theme, Ttk_ThemeEnabledProc enabledProc, void *enabledData)\n{\n    theme->enabledProc = enabledProc;\n    theme->enabledData = enabledData;\n}\n\n/*\n * LookupTheme --\n *\tRetrieve a registered theme by name.  If not found,\n *\treturns NULL and leaves an error message in interp's result.\n */\n\nstatic Ttk_Theme LookupTheme(\n    Tcl_Interp *interp,\t\t/* where to leave error messages */\n    StylePackageData *pkgPtr,\t/* style package record */\n    const char *name)\t\t/* theme name */\n{\n    Tcl_HashEntry *entryPtr;\n\n    entryPtr = Tcl_FindHashEntry(&pkgPtr->themeTable, name);\n    if (!entryPtr) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"theme \\\"%s\\\" does not exist\", name));\n\tTcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"THEME\", name, (char *)NULL);\n\treturn NULL;\n    }\n\n    return (Ttk_Theme)Tcl_GetHashValue(entryPtr);\n}\n\n/*\n * Ttk_GetTheme --\n *\tPublic interface to LookupTheme.\n */\nTtk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *themeName)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n\n    return LookupTheme(interp, pkgPtr, themeName);\n}\n\nTtk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    return pkgPtr->currentTheme;\n}\n\nTtk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    return pkgPtr->defaultTheme;\n}\n\n/*\n * Ttk_UseTheme --\n *\tSet the current theme, notify all widgets that the theme has changed.\n */\nint Ttk_UseTheme(Tcl_Interp *interp, Ttk_Theme  theme)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n\n    /*\n     * Check if selected theme is enabled:\n     */\n    while (theme && !theme->enabledProc(theme, theme->enabledData)) {\n\ttheme = theme->parentPtr;\n    }\n    if (!theme) {\n\t/* This shouldn't happen -- default theme should always work */\n\tTcl_Panic(\"No themes available?\");\n\treturn TCL_ERROR;\n    }\n\n    pkgPtr->currentTheme = theme;\n    ThemeChanged(pkgPtr);\n    return TCL_OK;\n}\n\n/*\n * Ttk_GetResourceCache --\n *\tReturn the resource cache associated with 'interp'\n */\nTtk_ResourceCache\nTtk_GetResourceCache(Tcl_Interp *interp)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    return pkgPtr->cache;\n}\n\n/*\n * Register a new layout specification with a style.\n * @@@ TODO: Make sure layoutName is not \".\", root style must not have a layout\n */\nMODULE_SCOPE void\nTtk_RegisterLayoutTemplate(\n    Ttk_Theme theme,\t\t\t/* Target theme */\n    const char *layoutName,\t\t/* Name of new layout */\n    Ttk_LayoutTemplate layoutTemplate)\t/* Template */\n{\n    Ttk_Style style = Ttk_GetStyle(theme, layoutName);\n    if (style->layoutTemplate) {\n\tTtk_FreeLayoutTemplate(style->layoutTemplate);\n    }\n    style->layoutTemplate = layoutTemplate;\n}\n\nvoid Ttk_RegisterLayout(\n    Ttk_Theme themePtr,\t\t/* Target theme */\n    const char *layoutName,\t/* Name of new layout */\n    Ttk_LayoutSpec specPtr)\t/* Static layout information */\n{\n    Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(specPtr);\n    Ttk_RegisterLayoutTemplate(themePtr, layoutName, layoutTemplate);\n}\n\n/*\n * Ttk_GetStyle --\n *\tLook up a Style from a Theme, create new style if not found.\n */\nTtk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName)\n{\n    Tcl_HashEntry *entryPtr;\n    int newStyle;\n\n    entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, styleName, &newStyle);\n    if (newStyle) {\n\tTtk_Style stylePtr = NewStyle();\n\tconst char *dot = strchr(styleName, '.');\n\n\tif (dot) {\n\t    stylePtr->parentStyle = Ttk_GetStyle(themePtr, dot + 1);\n\t} else {\n\t    stylePtr->parentStyle = themePtr->rootStyle;\n\t}\n\n\tstylePtr->styleName = (const char *)Tcl_GetHashKey(&themePtr->styleTable, entryPtr);\n\tstylePtr->cache = stylePtr->parentStyle->cache;\n\tTcl_SetHashValue(entryPtr, stylePtr);\n\treturn stylePtr;\n    }\n    return (Ttk_Style)Tcl_GetHashValue(entryPtr);\n}\n\n/* FindLayoutTemplate --\n *\tLocate a layout template in the layout table, checking\n *\tgeneric names to specific names first, then looking for\n *\tthe full name in the parent theme.\n */\nTtk_LayoutTemplate\nTtk_FindLayoutTemplate(Ttk_Theme themePtr, const char *layoutName)\n{\n    while (themePtr) {\n\tTtk_Style stylePtr = Ttk_GetStyle(themePtr, layoutName);\n\twhile (stylePtr) {\n\t    if (stylePtr->layoutTemplate) {\n\t\treturn stylePtr->layoutTemplate;\n\t    }\n\t    stylePtr = stylePtr->parentStyle;\n\t}\n\tthemePtr = themePtr->parentPtr;\n    }\n    return NULL;\n}\n\nconst char *Ttk_StyleName(Ttk_Style stylePtr)\n{\n    return stylePtr->styleName;\n}\n\n/*\n * Ttk_GetElement --\n *\tLook up an element class by name in a given theme.\n *\tIf not found, try generic element names in this theme, then\n *\trepeat the lookups in the parent theme.\n *\tIf not found, return the null element.\n */\nTtk_ElementClass *Ttk_GetElement(Ttk_Theme themePtr, const char *elementName)\n{\n    Tcl_HashEntry *entryPtr;\n    const char *dot = elementName;\n\n    /*\n     * Check if element has already been registered:\n     */\n    entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, elementName);\n    if (entryPtr) {\n\treturn (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);\n    }\n\n    /*\n     * Check generic names:\n     */\n    while (!entryPtr && ((dot = strchr(dot, '.')) != NULL)) {\n\tdot++;\n\tentryPtr = Tcl_FindHashEntry(&themePtr->elementTable, dot);\n    }\n    if (entryPtr) {\n\treturn (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);\n    }\n\n    /*\n     * Check parent theme:\n     */\n    if (themePtr->parentPtr) {\n\treturn Ttk_GetElement(themePtr->parentPtr, elementName);\n    }\n\n    /*\n     * Not found, and this is the root theme; return null element, \"\".\n     * (@@@ SHOULD: signal a background error)\n     */\n    entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, \"\");\n    /* ASSERT: entryPtr != 0 */\n    return (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);\n}\n\nconst char *Ttk_ElementClassName(Ttk_ElementClass *elementClass)\n{\n    return elementClass->name;\n}\n\n/*\n * Ttk_RegisterElementFactory --\n *\tRegister a new element factory.\n */\nint Ttk_RegisterElementFactory(\n    Tcl_Interp *interp,\tconst char *name,\n    Ttk_ElementFactory factory, void *clientData)\n{\n    StylePackageData *pkgPtr = GetStylePackageData(interp);\n    FactoryRec *recPtr = (FactoryRec *)Tcl_Alloc(sizeof(*recPtr));\n    Tcl_HashEntry *entryPtr;\n    int newEntry;\n\n    recPtr->factory = factory;\n    recPtr->clientData = clientData;\n\n    entryPtr = Tcl_CreateHashEntry(&pkgPtr->factoryTable, name, &newEntry);\n    if (!newEntry) {\n\t/* Free old factory: */\n\tTcl_Free(Tcl_GetHashValue(entryPtr));\n    }\n    Tcl_SetHashValue(entryPtr, recPtr);\n\n    return TCL_OK;\n}\n\n/* Ttk_CloneElement -- element factory procedure.\n *\t(style element create $name) \"from\" $theme ?$element?\n */\nstatic int Ttk_CloneElement(\n    Tcl_Interp *interp, TCL_UNUSED(void *),\n    Ttk_Theme theme, const char *elementName,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Ttk_Theme fromTheme;\n    Ttk_ElementClass *fromElement;\n\n    if (objc <= 0 || objc > 2) {\n\tTcl_WrongNumArgs(interp, 0, objv, \"theme ?element?\");\n\treturn TCL_ERROR;\n    }\n\n    fromTheme = Ttk_GetTheme(interp, Tcl_GetString(objv[0]));\n    if (!fromTheme) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 2) {\n\tfromElement = Ttk_GetElement(fromTheme, Tcl_GetString(objv[1]));\n    } else {\n\tfromElement = Ttk_GetElement(fromTheme, elementName);\n    }\n    if (!fromElement) {\n\treturn TCL_ERROR;\n    }\n\n    if (Ttk_RegisterElement(interp, theme, elementName,\n\t\tfromElement->specPtr, fromElement->clientData) == NULL)\n    {\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\n/* Ttk_RegisterElement--\n *\tRegister an element in the given theme.\n *\tReturns: Element handle if successful, NULL otherwise.\n *\tOn failure, leaves an error message in interp's result\n *\tif interp is non-NULL.\n */\n\nTtk_ElementClass *Ttk_RegisterElement(\n    Tcl_Interp *interp,\t\t/* Where to leave error messages */\n    Ttk_Theme theme,\t\t/* Style engine providing the implementation. */\n    const char *name,\t\t/* Name of new element */\n    const Ttk_ElementSpec *specPtr,\t/* Static template information */\n    void *clientData)\t\t/* application-specific data */\n{\n    Ttk_ElementClass *elementClass;\n    Tcl_HashEntry *entryPtr;\n    int newEntry;\n\n    if (specPtr->version != TK_STYLE_VERSION_2) {\n\t/* Version mismatch */\n\tif (interp) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Internal error: Ttk_RegisterElement (%s): invalid version\",\n\t\tname));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"REGISTER_ELEMENT\", \"VERSION\",\n\t\t(char *)NULL);\n\t}\n\treturn 0;\n    }\n\n    entryPtr = Tcl_CreateHashEntry(&theme->elementTable, name, &newEntry);\n    if (!newEntry) {\n\tif (interp) {\n\t    Tcl_ResetResult(interp);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Duplicate element %s\", name));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"REGISTER_ELEMENT\", \"DUPE\", (char *)NULL);\n\t}\n\treturn 0;\n    }\n\n    name = (char *)Tcl_GetHashKey(&theme->elementTable, entryPtr);\n    elementClass = NewElementClass(name, specPtr, clientData);\n    Tcl_SetHashValue(entryPtr, elementClass);\n\n    return elementClass;\n}\n\n#ifndef TK_NO_DEPRECATED\n/* Ttk_RegisterElementSpec (deprecated) --\n *\tRegister a new element.\n */\nint Ttk_RegisterElementSpec(Ttk_Theme theme,\n    const char *name, const Ttk_ElementSpec *specPtr, void *clientData)\n{\n    return Ttk_RegisterElement(NULL, theme, name, specPtr, clientData)\n\t   ? TCL_OK : TCL_ERROR;\n}\n#endif /* TK_NO_DEPRECATED */\n\n/*------------------------------------------------------------------------\n * +++ Element record initialization.\n */\n\n/*\n * AllocateResource --\n *\tExtra initialization for element options like TK_OPTION_COLOR, etc.\n *\n * Returns: 1 if OK, 0 on failure.\n *\n * Note: if resource allocation fails at this point (just prior\n * to drawing an element), there's really no good place to\n * report the error.  Instead we just silently fail.\n */\n\nstatic int AllocateResource(\n    Ttk_ResourceCache cache,\n    Tk_Window tkwin,\n    Tcl_Obj **destPtr,\n    int optionType)\n{\n    Tcl_Obj *resource = *destPtr;\n\n    switch (optionType)\n    {\n\tcase TK_OPTION_FONT:\n\t    return (*destPtr = Ttk_UseFont(cache, tkwin, resource)) != NULL;\n\tcase TK_OPTION_COLOR:\n\t    return (*destPtr = Ttk_UseColor(cache, tkwin, resource)) != NULL;\n\tcase TK_OPTION_BORDER:\n\t    return (*destPtr = Ttk_UseBorder(cache, tkwin, resource)) != NULL;\n\tdefault:\n\t    /* no-op; always succeeds */\n\t    return 1;\n    }\n}\n\n/*\n * InitializeElementRecord --\n *\n *\tFill in the element record based on the element's option table.\n *\tResources are initialized from:\n *\tthe corresponding widget option if present and non-NULL,\n *\totherwise the dynamic state map if specified,\n *\totherwise from the corresponding widget resource if present,\n *\totherwise the default value specified at registration time.\n *\n * Returns:\n *\t1 if OK, 0 if an error is detected.\n *\n * NOTES:\n *\tTcl_Obj * reference counts are _NOT_ adjusted.\n */\n\nstatic\nint InitializeElementRecord(\n    Ttk_ElementClass *eclass,\t/* Element instance to initialize */\n    Ttk_Style style,\t\t/* Style table */\n    void *widgetRecord,\t\t/* Source of widget option values */\n    Tk_OptionTable optionTable,\t/* Option table describing widget record */\n    Tk_Window tkwin,\t\t/* Corresponding window */\n    Ttk_State state)\t/* Widget or element state */\n{\n    void *elementRecord = eclass->elementRecord;\n    OptionMap optionMap = GetOptionMap(eclass,optionTable);\n    int nResources = eclass->nResources;\n    Ttk_ResourceCache cache = style->cache;\n    const Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options;\n\n    int i;\n    for (i=0; i<nResources; ++i, ++elementOption) {\n\tTcl_Obj **dest = (Tcl_Obj **)\n\t    ((char *)elementRecord + elementOption->offset);\n\tconst char *optionName = elementOption->optionName;\n\tTcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state);\n\tTcl_Obj *widgetValue = 0;\n\tTcl_Obj *elementDefault = eclass->defaultValues[i];\n\n\tif (optionMap[i]) {\n\t    widgetValue = *(Tcl_Obj **)\n\t\t((char *)widgetRecord + optionMap[i]->objOffset);\n\t}\n\n\tif (widgetValue) {\n\t    *dest = widgetValue;\n\t} else if (dynamicSetting) {\n\t    *dest = dynamicSetting;\n\t} else {\n\t    Tcl_Obj *styleDefault = Ttk_StyleDefault(style, optionName);\n\t    *dest = styleDefault ? styleDefault : elementDefault;\n\t}\n\n\tif (!AllocateResource(cache, tkwin, dest, elementOption->type)) {\n\t    return 0;\n\t}\n    }\n\n    return 1;\n}\n\n/*------------------------------------------------------------------------\n * +++ Public API.\n */\n\n/*\n * Ttk_QueryStyle --\n *\tLook up a style option based on the current state.\n */\nTcl_Obj *Ttk_QueryStyle(\n    Ttk_Style style,\t\t/* Style to query */\n    void *recordPtr,\t\t/* Widget record */\n    Tk_OptionTable optionTable,\t/* Option table describing widget record */\n    const char *optionName,\t/* Option name */\n    Ttk_State state)\t\t/* Current state */\n{\n    const Tk_OptionSpec *optionSpec;\n    Tcl_Obj *result;\n\n    /*\n     * Check widget record:\n     */\n    optionSpec = TTKGetOptionSpec(optionName, optionTable, TK_OPTION_ANY);\n    if (optionSpec) {\n\tresult = *(Tcl_Obj**)(((char*)recordPtr) + optionSpec->objOffset);\n\tif (result) {\n\t    return result;\n\t}\n    }\n\n    /*\n     * Check dynamic settings:\n     */\n    result = Ttk_StyleMap(style, optionName, state);\n    if (result) {\n\treturn result;\n    }\n\n    /*\n     * Use style default:\n     */\n    return Ttk_StyleDefault(style, optionName);\n}\n\n/*\n * Ttk_ElementSize --\n *\tCompute the requested size of the given element.\n */\n\nvoid\nTtk_ElementSize(\n    Ttk_ElementClass *eclass,\t\t/* Element to query */\n    Ttk_Style style,\t\t\t/* Style settings */\n    void *recordPtr,\t\t\t/* The widget record. */\n    Tk_OptionTable optionTable,\t\t/* Description of widget record */\n    Tk_Window tkwin,\t\t\t/* The widget window. */\n    Ttk_State state,\t\t\t/* Current widget state */\n    int *widthPtr,\t\t\t/* Requested width */\n    int *heightPtr,\t\t\t/* Reqested height */\n    Ttk_Padding *paddingPtr)\t\t/* Requested inner border */\n{\n    paddingPtr->left = paddingPtr->right = paddingPtr->top = paddingPtr->bottom\n\t= *widthPtr = *heightPtr = 0;\n\n    if (!InitializeElementRecord(\n\t    eclass, style, recordPtr, optionTable, tkwin,  state))\n    {\n\treturn;\n    }\n    eclass->specPtr->size(\n\teclass->clientData, eclass->elementRecord,\n\ttkwin, widthPtr, heightPtr, paddingPtr);\n}\n\n/*\n * Ttk_DrawElement --\n *\tDraw the given widget element in a given drawable area.\n */\n\nvoid\nTtk_DrawElement(\n    Ttk_ElementClass *eclass,\t\t/* Element instance */\n    Ttk_Style style,\t\t\t/* Style settings */\n    void *recordPtr,\t\t\t/* The widget record. */\n    Tk_OptionTable optionTable,\t\t/* Description of option table */\n    Tk_Window tkwin,\t\t\t/* The widget window. */\n    Drawable d,\t\t\t\t/* Where to draw element. */\n    Ttk_Box b,\t\t\t\t/* Element area */\n    Ttk_State state)\t\t\t/* Widget or element state flags. */\n{\n    if (b.width <= 0 || b.height <= 0) {\n\treturn;\n    }\n    if (!InitializeElementRecord(\n\t    eclass, style, recordPtr, optionTable, tkwin,  state)) {\n\treturn;\n    }\n    eclass->specPtr->draw(\n\teclass->clientData, eclass->elementRecord,\n\ttkwin, d, b, state);\n}\n\n/*------------------------------------------------------------------------\n * +++ 'style' command ensemble procedures.\n */\n\n/*\n * TtkEnumerateHashTable --\n *\tHelper routine.  Sets interp's result to the list of all keys\n *\tin the hash table.\n *\n * Returns: TCL_OK.\n * Side effects: Sets interp's result.\n */\n\nMODULE_SCOPE int\nTtkEnumerateHashTable(Tcl_Interp *interp, Tcl_HashTable *ht)\n{\n    Tcl_HashSearch search;\n    Tcl_Obj *result = Tcl_NewListObj(0, NULL);\n    Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);\n\n    while (entryPtr != NULL) {\n\tTcl_Obj *nameObj = Tcl_NewStringObj((const char *)Tcl_GetHashKey(ht, entryPtr),-1);\n\tTcl_ListObjAppendElement(interp, result, nameObj);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\n/* HashTableToDict --\n *\tHelper routine.  Converts a TCL_STRING_KEYS Tcl_HashTable\n *\twith Tcl_Obj * entries into a dictionary.\n */\nstatic Tcl_Obj* HashTableToDict(Tcl_HashTable *ht)\n{\n    Tcl_HashSearch search;\n    Tcl_Obj *result = Tcl_NewListObj(0, NULL);\n    Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);\n\n    while (entryPtr != NULL) {\n\tTcl_Obj *nameObj = Tcl_NewStringObj((const char *)Tcl_GetHashKey(ht, entryPtr),-1);\n\tTcl_Obj *valueObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);\n\tTcl_ListObjAppendElement(NULL, result, nameObj);\n\tTcl_ListObjAppendElement(NULL, result, valueObj);\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n\n    return result;\n}\n\n/* + style map $style ? -resource statemap ... ?\n *\n *\tNote that resource names are unconstrained; the Style\n *\tdoesn't know what resources individual elements may use.\n */\nstatic int\nStyleMapCmd(\n    void *clientData,\t\t/* StylePackageData pointer */\n    Tcl_Interp *interp,\t\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t\t/* Argument objects */\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    const char *styleName;\n    Style *stylePtr;\n    Tcl_Size i;\n\n    if (objc < 3) {\nusage:\n\tTcl_WrongNumArgs(interp,2,objv,\"style ?-option ?value...??\");\n\treturn TCL_ERROR;\n    }\n\n    styleName = Tcl_GetString(objv[2]);\n    stylePtr = Ttk_GetStyle(theme, styleName);\n\n    /* NOTE: StateMaps are actually Tcl_Obj *s, so HashTableToDict works\n     * for settingsTable.\n     */\n    if (objc == 3) {\t\t/* style map $styleName */\n\tTcl_SetObjResult(interp, HashTableToDict(&stylePtr->settingsTable));\n\treturn TCL_OK;\n    } else if (objc == 4) {\t/* style map $styleName -option */\n\tconst char *optionName = Tcl_GetString(objv[3]);\n\tTcl_HashEntry *entryPtr =\n\t    Tcl_FindHashEntry(&stylePtr->settingsTable, optionName);\n\tif (entryPtr) {\n\t    Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr));\n\t}\n\treturn TCL_OK;\n    } else if (objc % 2 != 1) {\n\tgoto usage;\n    }\n\n    for (i = 3; i < objc; i += 2) {\n\tconst char *optionName = Tcl_GetString(objv[i]);\n\tTcl_Obj *stateMap = objv[i+1];\n\tTcl_HashEntry *entryPtr;\n\tint newEntry;\n\n\t/* Make sure 'stateMap' is legal:\n\t * (@@@ SHOULD: check for valid resource values as well,\n\t * but we don't know what types they should be at this level.)\n\t */\n\tif (!Ttk_GetStateMapFromObj(interp, stateMap)) {\n\t    return TCL_ERROR;\n\t}\n\n\tentryPtr = Tcl_CreateHashEntry(\n\t\t&stylePtr->settingsTable,optionName,&newEntry);\n\n\tTcl_IncrRefCount(stateMap);\n\tif (!newEntry) {\n\t    Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr));\n\t}\n\tTcl_SetHashValue(entryPtr, stateMap);\n    }\n    ThemeChanged(pkgPtr);\n    return TCL_OK;\n}\n\n/* + style configure $style -option ?value...\n */\nstatic int StyleConfigureCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    const char *styleName;\n    Style *stylePtr;\n    Tcl_Size i;\n\n    if (objc < 3) {\nusage:\n\tTcl_WrongNumArgs(interp,2,objv,\"style ?-option ?value...??\");\n\treturn TCL_ERROR;\n    }\n\n    styleName = Tcl_GetString(objv[2]);\n    stylePtr = Ttk_GetStyle(theme, styleName);\n\n    if (objc == 3) {\t\t/* style configure $styleName */\n\tTcl_SetObjResult(interp, HashTableToDict(&stylePtr->defaultsTable));\n\treturn TCL_OK;\n    } else if (objc == 4) {\t/* style configure $styleName -option */\n\tconst char *optionName = Tcl_GetString(objv[3]);\n\tTcl_HashEntry *entryPtr =\n\t    Tcl_FindHashEntry(&stylePtr->defaultsTable, optionName);\n\tif (entryPtr) {\n\t    Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr));\n\t}\n\treturn TCL_OK;\n    } else if (objc % 2 != 1) {\n\tgoto usage;\n    }\n\n    for (i = 3; i < objc; i += 2) {\n\tconst char *optionName = Tcl_GetString(objv[i]);\n\tTcl_Obj *value = objv[i+1];\n\tTcl_HashEntry *entryPtr;\n\tint newEntry;\n\n\tentryPtr = Tcl_CreateHashEntry(\n\t\t&stylePtr->defaultsTable,optionName,&newEntry);\n\n\tTcl_IncrRefCount(value);\n\tif (!newEntry) {\n\t    Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr));\n\t}\n\tTcl_SetHashValue(entryPtr, value);\n    }\n\n    ThemeChanged(pkgPtr);\n    return TCL_OK;\n}\n\n/* + style lookup $style -option ?statespec? ?defaultValue?\n */\nstatic int StyleLookupCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    Ttk_Style style = NULL;\n    const char *optionName;\n    Ttk_State state = 0ul;\n    Tcl_Obj *result;\n\n    if (objc < 4 || objc > 6) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"style -option ?state? ?default?\");\n\treturn TCL_ERROR;\n    }\n\n    style = Ttk_GetStyle(theme, Tcl_GetString(objv[2]));\n    if (!style) {\n\treturn TCL_ERROR;\n    }\n    optionName = Tcl_GetString(objv[3]);\n\n    if (objc >= 5) {\n\tTtk_StateSpec stateSpec;\n\t/* @@@ SB: Ttk_GetStateFromObj(); 'offbits' spec is ignored */\n\tif (Ttk_GetStateSpecFromObj(interp, objv[4], &stateSpec) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tstate = stateSpec.onbits;\n    }\n\n    result = Ttk_QueryStyle(style, NULL,NULL, optionName, state);\n    if (result == NULL && objc >= 6) { /* Use caller-supplied fallback */\n\tresult = objv[5];\n    }\n\n    if (result) {\n\tTcl_SetObjResult(interp, result);\n    }\n\n    return TCL_OK;\n}\n\nstatic int StyleThemeCurrentCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr = NULL;\n    const char *name = NULL;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);\n    while (entryPtr != NULL) {\n\tTheme *ptr = (Theme *)Tcl_GetHashValue(entryPtr);\n\tif (ptr == pkgPtr->currentTheme) {\n\t    name = (char *)Tcl_GetHashKey(&pkgPtr->themeTable, entryPtr);\n\t    break;\n\t}\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n\n    if (name == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"error: failed to get theme name\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"THEME\", \"NAMELESS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));\n    return TCL_OK;\n}\n\n/* + style theme create name ?-parent $theme? ?-settings { script }?\n */\nstatic int StyleThemeCreateCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    static const char *const optStrings[] =\n\t { \"-parent\", \"-settings\", NULL };\n    enum { OP_PARENT, OP_SETTINGS };\n    Ttk_Theme parentTheme = pkgPtr->defaultTheme, newTheme;\n    Tcl_Obj *settingsScript = NULL;\n    const char *themeName;\n    Tcl_Size i;\n\n    if (objc < 4 || objc % 2 != 0) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"name ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    themeName = Tcl_GetString(objv[3]);\n\n    for (i=4; i < objc; i +=2) {\n\tint option;\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], optStrings,\n\t    sizeof(char *), \"option\", 0, &option) != TCL_OK)\n\t{\n\t    return TCL_ERROR;\n\t}\n\n\tswitch (option) {\n\t    case OP_PARENT:\n\t\tparentTheme = LookupTheme(\n\t\t    interp, pkgPtr, Tcl_GetString(objv[i+1]));\n\t\tif (!parentTheme) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    case OP_SETTINGS:\n\t\tsettingsScript = objv[i+1];\n\t\tbreak;\n\t}\n    }\n\n    newTheme = Ttk_CreateTheme(interp, themeName, parentTheme);\n    if (!newTheme) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Evaluate the -settings script, if supplied:\n     */\n    if (settingsScript) {\n\tTtk_Theme oldTheme = pkgPtr->currentTheme;\n\tint status;\n\n\tpkgPtr->currentTheme = newTheme;\n\tstatus = Tcl_EvalObjEx(interp, settingsScript, 0);\n\tpkgPtr->currentTheme = oldTheme;\n\treturn status;\n    } else {\n\treturn TCL_OK;\n    }\n}\n\n/* + style theme names --\n *\tReturn list of registered themes.\n */\nstatic int StyleThemeNamesCmd(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    TCL_UNUSED(Tcl_Obj *const *)) /* objv */\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n\n    return TtkEnumerateHashTable(interp, &pkgPtr->themeTable);\n}\n\n/* + style theme settings $theme $script\n *\n *\tTemporarily sets the current theme to $themeName,\n *\tevaluates $script, then restores the old theme.\n */\nstatic int\nStyleThemeSettingsCmd(\n    void *clientData,\t\t/* StylePackageData pointer */\n    Tcl_Interp *interp,\t\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t\t/* Argument objects */\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme oldTheme = pkgPtr->currentTheme;\n    Ttk_Theme newTheme;\n    int status;\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"theme script\");\n\treturn TCL_ERROR;\n    }\n\n    newTheme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3]));\n    if (!newTheme) {\n\treturn TCL_ERROR;\n    }\n\n    pkgPtr->currentTheme = newTheme;\n    status = Tcl_EvalObjEx(interp, objv[4], 0);\n    pkgPtr->currentTheme = oldTheme;\n\n    return status;\n}\n\n/* + style element create name type ? ...args ?\n */\nstatic int StyleElementCreateCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    const char *elementName, *factoryName;\n    Tcl_HashEntry *entryPtr;\n    FactoryRec *recPtr;\n\n    if (objc < 5) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"name type ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    elementName = Tcl_GetString(objv[3]);\n    factoryName = Tcl_GetString(objv[4]);\n\n    entryPtr = Tcl_FindHashEntry(&pkgPtr->factoryTable, factoryName);\n    if (!entryPtr) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"No such element type %s\", factoryName));\n\tTcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"ELEMENT_TYPE\", factoryName,\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    recPtr = (FactoryRec *)Tcl_GetHashValue(entryPtr);\n\n    return recPtr->factory(interp, recPtr->clientData,\n\t    theme, elementName, objc - 5, objv + 5);\n}\n\n/* + style element names --\n *\tReturn a list of elements defined in the current theme.\n */\nstatic int StyleElementNamesCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 3, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    return TtkEnumerateHashTable(interp, &theme->elementTable);\n}\n\n/* + style element options $element --\n *\tReturn list of element options for specified element\n */\nstatic int StyleElementOptionsCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    const char *elementName;\n    Ttk_ElementClass *elementClass;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"element\");\n\treturn TCL_ERROR;\n    }\n\n    elementName = Tcl_GetString(objv[3]);\n    elementClass = Ttk_GetElement(theme, elementName);\n    if (elementClass) {\n\tconst Ttk_ElementSpec *specPtr = elementClass->specPtr;\n\tconst Ttk_ElementOptionSpec *option = specPtr->options;\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\n\twhile (option->optionName) {\n\t    Tcl_ListObjAppendElement(\n\t\tinterp, result, Tcl_NewStringObj(option->optionName,-1));\n\t    ++option;\n\t}\n\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\"element %s not found\", elementName));\n    Tcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"ELEMENT\", elementName, (char *)NULL);\n    return TCL_ERROR;\n}\n\n/* + style layout name ?spec?\n */\nstatic int StyleLayoutCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme = pkgPtr->currentTheme;\n    const char *layoutName;\n    Ttk_LayoutTemplate layoutTemplate;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"name ?spec?\");\n\treturn TCL_ERROR;\n    }\n\n    layoutName = Tcl_GetString(objv[2]);\n\n    if (objc == 3) {\n\tlayoutTemplate = Ttk_FindLayoutTemplate(theme, layoutName);\n\tif (!layoutTemplate) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Layout %s not found\", layoutName));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"LOOKUP\", \"LAYOUT\", layoutName,\n\t\t(char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Ttk_UnparseLayoutTemplate(layoutTemplate));\n    } else {\n\tlayoutTemplate = Ttk_ParseLayoutTemplate(interp, objv[3]);\n\tif (!layoutTemplate) {\n\t    return TCL_ERROR;\n\t}\n\tTtk_RegisterLayoutTemplate(theme, layoutName, layoutTemplate);\n\tThemeChanged(pkgPtr);\n    }\n    return TCL_OK;\n}\n\n/* + style theme styles ?$theme? --\n *\tReturn list of styles available in $theme.\n *      Use the current theme if $theme is omitted.\n */\nstatic int StyleThemeStylesCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Ttk_Theme themePtr;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"?theme?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tthemePtr = Ttk_GetCurrentTheme(interp);\n    } else {\n\tthemePtr = Ttk_GetTheme(interp, Tcl_GetString(objv[3]));\n    }\n    if (!themePtr) {\n\treturn TCL_ERROR;\n    }\n\n    return TtkEnumerateHashTable(interp, &themePtr->styleTable);\n}\n\n/* + style theme use $theme --\n *\tSets the current theme to $theme\n */\nstatic int\nStyleThemeUseCmd(\n    void *clientData,\t\t/* StylePackageData pointer */\n    Tcl_Interp *interp,\t\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t\t/* Argument objects */\n{\n    StylePackageData *pkgPtr = (StylePackageData *)clientData;\n    Ttk_Theme theme;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"?theme?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\treturn StyleThemeCurrentCmd(clientData, interp, objc, objv);\n    }\n\n    theme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3]));\n    if (!theme) {\n\treturn TCL_ERROR;\n    }\n\n    return Ttk_UseTheme(interp, theme);\n}\n\n/*\n * StyleObjCmd --\n *\tImplementation of the [style] command.\n */\n\nstatic const Ttk_Ensemble StyleThemeEnsemble[] = {\n    { \"create\", StyleThemeCreateCmd, 0 },\n    { \"names\", StyleThemeNamesCmd, 0 },\n    { \"settings\", StyleThemeSettingsCmd, 0 },\n    { \"styles\", StyleThemeStylesCmd, 0 },\n    { \"use\", StyleThemeUseCmd, 0 },\n    { NULL, 0, 0 }\n};\n\nstatic const Ttk_Ensemble StyleElementEnsemble[] = {\n    { \"create\", StyleElementCreateCmd, 0 },\n    { \"names\", StyleElementNamesCmd, 0 },\n    { \"options\", StyleElementOptionsCmd, 0 },\n    { NULL, 0, 0 }\n};\n\nstatic const Ttk_Ensemble StyleEnsemble[] = {\n    { \"configure\", StyleConfigureCmd, 0 },\n    { \"map\", StyleMapCmd, 0 },\n    { \"lookup\", StyleLookupCmd, 0 },\n    { \"layout\", StyleLayoutCmd, 0 },\n    { \"theme\", 0, StyleThemeEnsemble },\n    { \"element\", 0, StyleElementEnsemble },\n    { NULL, 0, 0 }\n};\n\nstatic int\nStyleObjCmd(\n    void *clientData,\t\t/* StylePackageData pointer */\n    Tcl_Interp *interp,\t\t\t/* Current interpreter */\n    Tcl_Size objc,\t\t\t\t/* Number of arguments */\n    Tcl_Obj *const objv[])\t\t/* Argument objects */\n{\n    return Ttk_InvokeEnsemble(StyleEnsemble, 1, clientData,interp,objc,objv);\n}\n\nMODULE_SCOPE int\nTtk_InvokeEnsemble(\t/* Run an ensemble command */\n    const Ttk_Ensemble *ensemble, Tcl_Size cmdIndex,\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    while (cmdIndex < objc) {\n\tint index;\n\tif (Tcl_GetIndexFromObjStruct(interp,\n\t\tobjv[cmdIndex], ensemble, sizeof(ensemble[0]),\n\t\t\"command\", 0, &index)\n\t    != TCL_OK)\n\t{\n\t    return TCL_ERROR;\n\t}\n\n\tif (ensemble[index].command) {\n\t    return ensemble[index].command(clientData, interp, objc, objv);\n\t}\n\tensemble = ensemble[index].ensemble;\n\t++cmdIndex;\n    }\n    Tcl_WrongNumArgs(interp, cmdIndex, objv, \"option ?arg ...?\");\n    return TCL_ERROR;\n}\n\n/*\n * Ttk_StylePkgInit --\n *\tInitializes all the structures that are used by the style\n *\tpackage on a per-interp basis.\n */\n\nvoid Ttk_StylePkgInit(Tcl_Interp *interp)\n{\n    Tcl_Namespace *nsPtr;\n\n    StylePackageData *pkgPtr = (StylePackageData *)Tcl_Alloc(sizeof(StylePackageData));\n\n    pkgPtr->interp = interp;\n    Tcl_InitHashTable(&pkgPtr->themeTable, TCL_STRING_KEYS);\n    Tcl_InitHashTable(&pkgPtr->factoryTable, TCL_STRING_KEYS);\n    pkgPtr->cleanupList = NULL;\n    pkgPtr->cache = Ttk_CreateResourceCache(interp);\n    pkgPtr->themeChangePending = 0;\n\n    Tcl_SetAssocData(interp, PKG_ASSOC_KEY, Ttk_StylePkgFree, pkgPtr);\n\n    /*\n     * Create the default system theme:\n     *\n     * pkgPtr->defaultTheme must be initialized to 0 before\n     * calling Ttk_CreateTheme for the first time, since it's used\n     * as the parent theme.\n     */\n    pkgPtr->defaultTheme = 0;\n    pkgPtr->defaultTheme = pkgPtr->currentTheme =\n\tTtk_CreateTheme(interp, \"default\", NULL);\n\n    /*\n     * Register null element, used as a last-resort fallback:\n     */\n    Ttk_RegisterElement(interp, pkgPtr->defaultTheme, \"\", &ttkNullElementSpec, 0);\n\n    /*\n     * Register commands:\n     */\n    Tcl_CreateObjCommand2(interp, \"::ttk::style\", StyleObjCmd, pkgPtr, 0);\n\n    nsPtr = Tcl_FindNamespace(interp, \"::ttk\", NULL, TCL_LEAVE_ERR_MSG);\n    Tcl_Export(interp, nsPtr, \"style\", 0 /* dontResetList */);\n\n    Ttk_RegisterElementFactory(interp, \"from\", Ttk_CloneElement, 0);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkTheme.h",
    "content": "/*\n * Copyright © 2003 Joe English.  Freely redistributable.\n *\n * Declarations for Tk theme engine.\n */\n\n#ifndef _TTKTHEME\n#define _TTKTHEME\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#\tdefine MODULE_SCOPE extern \"C\"\n#   else\n#\tdefine MODULE_SCOPE extern\n#   endif\n#endif\n\n#define TTKAPI MODULE_SCOPE\n\n/* Ttk syncs to the Tk version & patchlevel */\n#define TTK_VERSION    TK_VERSION\n#define TTK_PATCH_LEVEL TK_PATCH_LEVEL\n\n/*------------------------------------------------------------------------\n * +++ Defaults for element option specifications.\n */\n#define DEFAULT_FONT\t\t\"TkDefaultFont\"\n#ifdef MAC_OSX_TK\n#define DEFAULT_BACKGROUND\t\"systemTextBackgroundColor\"\n#define DEFAULT_FOREGROUND\t\"systemTextColor\"\n#else\n#define DEFAULT_BACKGROUND\t\"#d9d9d9\"\n#define DEFAULT_FOREGROUND\t\"black\"\n#endif\n/*------------------------------------------------------------------------\n * +++ Widget states.\n *\tKeep in sync with stateNames[] in tkstate.c.\n */\n\ntypedef unsigned int Ttk_State;\n\n#define TTK_STATE_ACTIVE\t(1<<0)\n#define TTK_STATE_DISABLED\t(1<<1)\n#define TTK_STATE_FOCUS\t\t(1<<2)\n#define TTK_STATE_PRESSED\t(1<<3)\n#define TTK_STATE_SELECTED\t(1<<4)\n#define TTK_STATE_BACKGROUND\t(1<<5)\n#define TTK_STATE_ALTERNATE\t(1<<6)\n#define TTK_STATE_INVALID\t(1<<7)\n#define TTK_STATE_READONLY\t(1<<8)\n#define TTK_STATE_HOVER\t\t(1<<9)\n#define TTK_STATE_USER6\t\t(1<<10)\n#define TTK_STATE_USER5\t\t(1<<11)\n#define TTK_STATE_USER4\t\t(1<<12)\n#define TTK_STATE_USER3\t\t(1<<13)\n#define TTK_STATE_USER2\t\t(1<<14)\n#define TTK_STATE_USER1\t\t(1<<15)\n#define TTK_STATE_OPEN\t\t(1<<16)\n#define TTK_STATE_LEAF\t\t(1<<17)\n#define TTK_STATE_FIRST\t\t(1<<18)\n#define TTK_STATE_LAST\t\t(1<<19)\n\n/* Maintenance note: if you get all the way to \"USER1\",\n * see tkstate.c\n */\ntypedef struct\n{\n    unsigned int onbits;\t/* bits to turn on */\n    unsigned int offbits;\t/* bits to turn off */\n} Ttk_StateSpec;\n\n#define Ttk_StateMatches(state, spec) \\\n    (((state) & ((spec)->onbits|(spec)->offbits)) == (spec)->onbits)\n\n#define Ttk_ModifyState(state, spec) \\\n    (((state) & ~(spec)->offbits) | (spec)->onbits)\n\n/*------------------------------------------------------------------------\n * +++ State maps and state tables.\n */\ntypedef Tcl_Obj *Ttk_StateMap;\n\n/*\n * Table for looking up an integer index based on widget state:\n */\ntypedef struct\n{\n    int index;\t\t\t/* Value to return if this entry matches */\n    unsigned int onBits;\t/* Bits which must be set */\n    unsigned int offBits;\t/* Bits which must be cleared */\n} Ttk_StateTable;\n\n/*------------------------------------------------------------------------\n * +++ Padding.\n *\tUsed to represent internal padding and borders.\n */\ntypedef struct\n{\n    short left;\n    short top;\n    short right;\n    short bottom;\n} Ttk_Padding;\n\n#define Ttk_PaddingWidth(p) ((p).left + (p).right)\n#define Ttk_PaddingHeight(p) ((p).top + (p).bottom)\n\n#define Ttk_SetMargins(tkwin, pad) \\\n    Tk_SetInternalBorderEx(tkwin, pad.left, pad.right, pad.top, pad.bottom)\n\n/*------------------------------------------------------------------------\n * +++ Boxes.\n *\tUsed to represent rectangular regions\n */\ntypedef struct\t/* Hey, this is an XRectangle! */\n{\n    int x;\n    int y;\n    int width;\n    int height;\n} Ttk_Box;\n\n#define Ttk_WinBox(tkwin) Ttk_MakeBox(0,0,Tk_Width(tkwin),Tk_Height(tkwin))\n\n/*------------------------------------------------------------------------\n * +++ Layout utilities.\n */\ntypedef enum {\n    TTK_SIDE_LEFT, TTK_SIDE_TOP, TTK_SIDE_RIGHT, TTK_SIDE_BOTTOM\n} Ttk_Side;\n\ntypedef unsigned int Ttk_Sticky;\n\n/*\n * -sticky bits for Ttk_StickBox:\n */\n#define TTK_STICK_W\t(0x1)\n#define TTK_STICK_E\t(0x2)\n#define TTK_STICK_N\t(0x4)\n#define TTK_STICK_S\t(0x8)\n\n/*\n * Aliases and useful combinations:\n */\n#define TTK_FILL_X\t(0x3)\t/* -sticky ew */\n#define TTK_FILL_Y\t(0xC)\t/* -sticky ns */\n#define TTK_FILL_BOTH\t(0xF)\t/* -sticky nswe */\n\nTTKAPI Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky);\n\n/*\n * Extra bits for position specifications (combine -side and -sticky)\n */\n\ntypedef unsigned int Ttk_PositionSpec;\t/* See below */\n\n#define TTK_PACK_LEFT\t(0x10)\t/* pack at left of current parcel */\n#define TTK_PACK_RIGHT\t(0x20)\t/* pack at right of current parcel */\n#define TTK_PACK_TOP\t(0x40)\t/* pack at top of current parcel */\n#define TTK_PACK_BOTTOM\t(0x80)\t/* pack at bottom of current parcel */\n#define TTK_EXPAND\t(0x100)\t/* use entire parcel */\n#define TTK_BORDER\t(0x200)\t/* draw this element after children */\n#define TTK_UNIT\t(0x400)\t/* treat descendants as a part of element */\n\n/*\n * Extra bits for layout specifications\n */\n#define _TTK_CHILDREN\t(0x1000)/* for LayoutSpecs -- children follow */\n#define _TTK_LAYOUT_END\t(0x2000)/* for LayoutSpecs -- end of child list */\n#define _TTK_LAYOUT\t(0x4000)/* for LayoutSpec tables -- define layout */\n\n#define _TTK_MASK_STICK (0x0F)\t/* See Ttk_UnparseLayout() */\n#define _TTK_MASK_PACK\t(0xF0)\t/* See Ttk_UnparseLayout(), packStrings */\n\nTTKAPI Ttk_Box Ttk_PositionBox(Ttk_Box *cavity, int w, int h, Ttk_PositionSpec);\n\n/*------------------------------------------------------------------------\n * +++ Themes.\n */\nMODULE_SCOPE void Ttk_StylePkgInit(Tcl_Interp *);\n\ntypedef struct Ttk_Theme_ *Ttk_Theme;\ntypedef struct Ttk_ElementClass_ Ttk_ElementClass;\ntypedef struct Ttk_Layout_ *Ttk_Layout;\ntypedef struct Ttk_LayoutNode_ *Ttk_Element;\ntypedef struct Ttk_Style_ *Ttk_Style;\n\ntypedef int (Ttk_ThemeEnabledProc)(Ttk_Theme theme, void *clientData);\nMODULE_SCOPE void Ttk_SetThemeEnabledProc(Ttk_Theme, Ttk_ThemeEnabledProc, void *);\n\nMODULE_SCOPE int Ttk_UseTheme(Tcl_Interp *, Ttk_Theme);\n\ntypedef void (Ttk_CleanupProc)(void *clientData);\n\n/*------------------------------------------------------------------------\n * +++ Elements.\n */\n\nenum TTKStyleVersion2 { TK_STYLE_VERSION_2 = 2 };\n\ntypedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord,\n\tTk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding*);\ntypedef void (Ttk_ElementDrawProc)(void *clientData, void *elementRecord,\n\tTk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);\n\ntypedef struct Ttk_ElementOptionSpec\n{\n    const char *optionName;\t\t/* Command-line name of the widget option */\n    Tk_OptionType type;\t/* Accepted option types */\n    Tcl_Size offset;\t\t\t/* Offset of Tcl_Obj* field in element record */\n    const char *defaultValue;\t\t/* Default value to used if resource missing */\n} Ttk_ElementOptionSpec;\n\n#define TK_OPTION_ANY TK_OPTION_STRING\n\ntypedef struct Ttk_ElementSpec {\n    enum TTKStyleVersion2 version;\t/* Version of the style support. */\n    size_t elementSize;\t\t\t/* Size of element record */\n    const Ttk_ElementOptionSpec *options;\t/* List of options, NULL-terminated */\n    Ttk_ElementSizeProc *size;\t\t/* Compute min size and padding */\n    Ttk_ElementDrawProc *draw;\t/* Draw the element */\n} Ttk_ElementSpec;\n\ntypedef int (*Ttk_ElementFactory)\n\t(Tcl_Interp *, void *clientData,\n\t Ttk_Theme, const char *elementName, Tcl_Size objc, Tcl_Obj *const objv[]);\n\n/*\n * Null element implementation:\n * has no geometry or layout; may be used as a stub or placeholder.\n */\n\ntypedef struct {\n    Tcl_Obj\t*unused;\n} NullElement;\n\nMODULE_SCOPE Ttk_ElementSizeProc TtkNullElementSize;\nMODULE_SCOPE Ttk_ElementDrawProc TtkNullElementDraw;\nMODULE_SCOPE const Ttk_ElementOptionSpec TtkNullElementOptions[];\nMODULE_SCOPE Ttk_ElementSpec ttkNullElementSpec;\n\n/*------------------------------------------------------------------------\n * +++ Layout templates.\n */\ntypedef struct {\n    const char *\telementName;\n    unsigned\t\topcode;\n} TTKLayoutInstruction, *Ttk_LayoutSpec;\n\n#define TTK_BEGIN_LAYOUT_TABLE(name) \\\n\t\t\t\tstatic TTKLayoutInstruction name[] = {\n#define TTK_LAYOUT(name, content) \\\n\t\t\t\t{ name, _TTK_CHILDREN|_TTK_LAYOUT }, \\\n\t\t\t\tcontent \\\n\t\t\t\t{ 0, _TTK_LAYOUT_END },\n#define TTK_GROUP(name, flags, children) \\\n\t\t\t\t{ name, flags | _TTK_CHILDREN }, \\\n\t\t\t\tchildren \\\n\t\t\t\t{ 0, _TTK_LAYOUT_END },\n#define TTK_NODE(name, flags)\t{ name, flags },\n#define TTK_END_LAYOUT_TABLE\t{ 0, _TTK_LAYOUT | _TTK_LAYOUT_END } };\n\n#define TTK_BEGIN_LAYOUT(name)\tstatic TTKLayoutInstruction name[] = {\n#define TTK_END_LAYOUT\t\t{ 0, _TTK_LAYOUT_END } };\n\nTTKAPI void Ttk_RegisterLayouts(\n    Ttk_Theme theme, Ttk_LayoutSpec layoutTable);\n\n/*------------------------------------------------------------------------\n * +++ Layout instances.\n */\n\nMODULE_SCOPE Ttk_Layout Ttk_CreateLayout(\n    Tcl_Interp *, Ttk_Theme, const char *name,\n    void *recordPtr, Tk_OptionTable, Tk_Window tkwin);\n\nMODULE_SCOPE Ttk_Layout Ttk_CreateSublayout(\n    Tcl_Interp *, Ttk_Theme, Ttk_Layout, const char *name, Tk_OptionTable);\n\nMODULE_SCOPE void Ttk_FreeLayout(Ttk_Layout);\n\nMODULE_SCOPE void Ttk_LayoutSize(Ttk_Layout,Ttk_State,int *widthPtr,int *heightPtr);\nMODULE_SCOPE void Ttk_PlaceLayout(Ttk_Layout, Ttk_State, Ttk_Box);\nMODULE_SCOPE void Ttk_DrawLayout(Ttk_Layout, Ttk_State, Drawable);\n\nMODULE_SCOPE void Ttk_RebindSublayout(Ttk_Layout, void *recordPtr);\n\nMODULE_SCOPE Ttk_Element Ttk_IdentifyElement(Ttk_Layout, int x, int y);\nMODULE_SCOPE Ttk_Element Ttk_FindElement(Ttk_Layout, const char *nodeName);\n\nMODULE_SCOPE const char *Ttk_ElementName(Ttk_Element);\nMODULE_SCOPE Ttk_Box Ttk_ElementParcel(Ttk_Element);\n\nMODULE_SCOPE Ttk_Box Ttk_ClientRegion(Ttk_Layout, const char *elementName);\n\nMODULE_SCOPE Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout,Ttk_Element);\nMODULE_SCOPE Ttk_Padding Ttk_LayoutNodeInternalPadding(Ttk_Layout,Ttk_Element);\nMODULE_SCOPE void Ttk_LayoutNodeReqSize(Ttk_Layout, Ttk_Element, int *w, int *h);\n\nMODULE_SCOPE void Ttk_PlaceElement(Ttk_Layout, Ttk_Element, Ttk_Box);\nMODULE_SCOPE void Ttk_AnchorElement(Ttk_Element node, Tk_Anchor anchor);\nMODULE_SCOPE void Ttk_ChangeElementState(Ttk_Element,unsigned set,unsigned clr);\n\nMODULE_SCOPE Tcl_Obj *Ttk_QueryOption(Ttk_Layout, const char *, Ttk_State);\n\nTTKAPI Ttk_Style Ttk_LayoutStyle(Ttk_Layout);\nTTKAPI Tcl_Obj *Ttk_StyleDefault(Ttk_Style, const char *optionName);\nTTKAPI Tcl_Obj *Ttk_StyleMap(Ttk_Style, const char *optionName, Ttk_State);\n\n/*------------------------------------------------------------------------\n * +++ Resource cache.\n *\tSee resource.c for explanation.\n */\n\ntypedef struct Ttk_ResourceCache_ *Ttk_ResourceCache;\nMODULE_SCOPE Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *);\nMODULE_SCOPE void Ttk_FreeResourceCache(Ttk_ResourceCache);\n\nMODULE_SCOPE Ttk_ResourceCache Ttk_GetResourceCache(Tcl_Interp*);\nMODULE_SCOPE Tcl_Obj *Ttk_UseFont(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);\nMODULE_SCOPE Tcl_Obj *Ttk_UseColor(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);\nMODULE_SCOPE Tcl_Obj *Ttk_UseBorder(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);\nMODULE_SCOPE Tk_Image Ttk_UseImage(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);\n\nMODULE_SCOPE void Ttk_RegisterNamedColor(Ttk_ResourceCache, const char *, XColor *);\n\n/*------------------------------------------------------------------------\n * +++ Image specifications.\n */\n\ntypedef struct TtkImageSpec Ttk_ImageSpec;\nTTKAPI Ttk_ImageSpec *TtkGetImageSpec(Tcl_Interp *, Tk_Window, Tcl_Obj *);\nTTKAPI Ttk_ImageSpec *TtkGetImageSpecEx(Tcl_Interp *, Tk_Window, Tcl_Obj *,\n\t\t\t\t\tTk_ImageChangedProc *, void *);\nTTKAPI void TtkFreeImageSpec(Ttk_ImageSpec *);\nTTKAPI Tk_Image TtkSelectImage(Ttk_ImageSpec *, Tk_Window, Ttk_State);\n\n/*------------------------------------------------------------------------\n * +++ Miscellaneous enumerations.\n *\tOther stuff that element implementations need to know about.\n */\ntypedef enum\t\t\t/* -default option values */\n{\n    TTK_BUTTON_DEFAULT_ACTIVE,\t/* currently the default widget */\n    TTK_BUTTON_DEFAULT_DISABLED,\t/* not defaultable */\n    TTK_BUTTON_DEFAULT_NORMAL\t/* widget defaultable */\n} Ttk_ButtonDefaultState;\n\nTTKAPI int Ttk_GetButtonDefaultStateFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_ButtonDefaultState *);\n\ntypedef enum\t\t\t/* -compound option values */\n{\n    TTK_COMPOUND_NONE,\t/* image if specified, otherwise text */\n    TTK_COMPOUND_TEXT,\t/* text only */\n    TTK_COMPOUND_IMAGE,\t/* image only */\n    TTK_COMPOUND_CENTER,\t/* text overlays image */\n    TTK_COMPOUND_TOP,\t/* image above text */\n    TTK_COMPOUND_BOTTOM,\t/* image below text */\n    TTK_COMPOUND_LEFT,\t/* image to left of text */\n    TTK_COMPOUND_RIGHT\t/* image to right of text */\n} Ttk_Compound;\n\nTTKAPI int Ttk_GetCompoundFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_Compound *);\n\ntypedef enum {\t\t/* -orient option values */\n    TTK_ORIENT_HORIZONTAL,\n    TTK_ORIENT_VERTICAL\n} Ttk_Orient;\n\n/*------------------------------------------------------------------------\n * +++ Utilities.\n */\n\ntypedef struct TtkEnsemble {\n    const char *name;\t\t\t/* subcommand name */\n    Tcl_ObjCmdProc2 *command;\t\t/* subcommand implementation, OR: */\n    const struct TtkEnsemble *ensemble;\t/* subcommand ensemble */\n} Ttk_Ensemble;\n\nMODULE_SCOPE int Ttk_InvokeEnsemble(\t/* Run an ensemble command */\n    const Ttk_Ensemble *commands, Tcl_Size cmdIndex,\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\n\nMODULE_SCOPE int TtkEnumerateHashTable(Tcl_Interp *, Tcl_HashTable *);\n\n/*------------------------------------------------------------------------\n * +++ Stub table declarations.\n */\n\n#include \"ttkDecls.h\"  /* IWYU pragma: export */\n\n/*\n * Drawing utilities for theme code:\n * (@@@ find a better home for this)\n */\ntypedef enum { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT } ArrowDirection;\nMODULE_SCOPE void TtkArrowSize(int h, ArrowDirection, int *widthPtr, int *heightPtr);\nMODULE_SCOPE void TtkDrawArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection);\nMODULE_SCOPE void TtkFillArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection);\n\n#ifdef __cplusplus\n}\n#endif\n#endif /* _TTKTHEME */\n"
  },
  {
    "path": "generic/ttk/ttkThemeInt.h",
    "content": "/*\n * Theme engine: private definitions.\n *\n * Copyright © 2004 Joe English.  Freely redistributable.\n */\n\n#ifndef _TTKTHEMEINT\n#define _TTKTHEMEINT\n\n#include \"ttkTheme.h\"\n\ntypedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;\n\nMODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name);\nMODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *);\n\nMODULE_SCOPE void Ttk_ElementSize(\n\tTtk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable,\n\tTk_Window tkwin, Ttk_State state,\n\tint *widthPtr, int *heightPtr, Ttk_Padding*);\nMODULE_SCOPE void Ttk_DrawElement(\n\tTtk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable,\n\tTk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);\n\nMODULE_SCOPE Tcl_Obj *Ttk_QueryStyle(\n    Ttk_Style, void *, Tk_OptionTable, const char *, Ttk_State state);\n\nMODULE_SCOPE Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(\n\tTcl_Interp *, Tcl_Obj *);\nMODULE_SCOPE Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_LayoutTemplate);\nMODULE_SCOPE Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec);\nMODULE_SCOPE void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate);\nMODULE_SCOPE void Ttk_RegisterLayoutTemplate(\n    Ttk_Theme theme, const char *layoutName, Ttk_LayoutTemplate);\n\nMODULE_SCOPE Ttk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName);\nMODULE_SCOPE Ttk_LayoutTemplate Ttk_FindLayoutTemplate(\n    Ttk_Theme themePtr, const char *layoutName);\n\nMODULE_SCOPE const char *Ttk_StyleName(Ttk_Style);\n\nMODULE_SCOPE void TtkSetBlinkCursorTimes(Tcl_Interp* interp);\n\nMODULE_SCOPE bool TtkBoxEqual(Ttk_Box, Ttk_Box);\n\n#define TTK_OPTION_UNDERLINE_DEF(type, field) NULL, offsetof(type, field), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL\n\n#endif /* _TTKTHEMEINT */\n"
  },
  {
    "path": "generic/ttk/ttkToggleswitch.c",
    "content": "/*\n * Copyright © 2025 Csaba Nemethi <csaba.nemethi@t-online.de>\n *\n * ttk::toggleswitch widget.\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\n/*\n * Tglswitch widget record\n */\ntypedef struct\n{\n    /* widget options */\n    Tcl_Obj *commandObj;\n    Tcl_Obj *offValueObj;\n    Tcl_Obj *onValueObj;\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *variableObj;\n\n    /* internal state */\n    Tcl_Obj *minValObj;\t\t/* minimum value */\n    Tcl_Obj *maxValObj;\t\t/* maximum value */\n    Tcl_Obj *curValObj;\t\t/* current value */\n    Ttk_TraceHandle *varTrace;\n    double minVal, maxVal;\n} TglswitchPart;\n\ntypedef struct\n{\n    WidgetCore\t  core;\n    TglswitchPart tglsw;\n} Tglswitch;\n\nstatic const char *const sizeStrings[] = { \"1\", \"2\", \"3\", NULL };\n\nstatic const Tk_OptionSpec TglswitchOptionSpecs[] =\n{\n    {TK_OPTION_STRING, \"-command\", \"command\", \"Command\", \"\",\n\toffsetof(Tglswitch, tglsw.commandObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING, \"-offvalue\", \"offValue\", \"OffValue\", \"0\",\n\toffsetof(Tglswitch, tglsw.offValueObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING, \"-onvalue\", \"onValue\", \"OnValue\", \"1\",\n\toffsetof(Tglswitch, tglsw.onValueObj), TCL_INDEX_NONE,\n\t0, 0, 0},\n    {TK_OPTION_STRING_TABLE, \"-size\", \"size\", \"Size\", \"2\",\n\toffsetof(Tglswitch, tglsw.sizeObj), TCL_INDEX_NONE,\n\t0, sizeStrings, GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-variable\", \"variable\", \"Variable\", NULL,\n\toffsetof(Tglswitch, tglsw.variableObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, 0},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*\n * TglswitchVariableChanged --\n *\tVariable trace procedure for the ttk::toggleswitch -variable option.\n *\tUpdates the ttk::toggleswitch widget's switch state.\n */\nstatic void TglswitchVariableChanged(void *clientData, const char *value)\n{\n    Tglswitch *tglswPtr = (Tglswitch *)clientData;\n\n    if (WidgetDestroyed(&tglswPtr->core)) {\n\treturn;\n    }\n\n    if (value == NULL) {\n\tTtkWidgetChangeState(&tglswPtr->core, TTK_STATE_INVALID, 0);\n    } else {\n\tTcl_DecrRefCount(tglswPtr->tglsw.curValObj);\n\tif (!strcmp(value, Tcl_GetString(tglswPtr->tglsw.onValueObj))) {\n\t    TtkWidgetChangeState(&tglswPtr->core, TTK_STATE_SELECTED, 0);\n\t    tglswPtr->tglsw.curValObj = tglswPtr->tglsw.maxValObj;\n\t} else {\n\t    TtkWidgetChangeState(&tglswPtr->core, 0, TTK_STATE_SELECTED);\n\t    tglswPtr->tglsw.curValObj = tglswPtr->tglsw.minValObj;\n\t}\n\tTcl_IncrRefCount(tglswPtr->tglsw.curValObj);\n\n\tTtkWidgetChangeState(&tglswPtr->core, 0, TTK_STATE_INVALID);\n    }\n\n    TtkRedisplayWidget(&tglswPtr->core);\n}\n\n/*\n * TglswitchInitialize --\n *\tttk::toggleswitch widget initialization hook.\n */\nstatic void TglswitchInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n\n    /*\n     * Create the *Tglswitch*.trough and *Tglswitch*.slider\n     * elements for the Toggleswitch* styles if necessary\n     */\n    int code = Tcl_EvalEx(interp, \"ttk::toggleswitch::CondMakeElements\",\n\t    TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_BackgroundException(interp, code);\n    }\n\n    /*\n     * Initialize the minimum, maximum, and current values\n     */\n\n    tglswPtr->tglsw.minVal = 0.0;\n    tglswPtr->tglsw.minValObj = Tcl_NewDoubleObj(tglswPtr->tglsw.minVal);\n    Tcl_IncrRefCount(tglswPtr->tglsw.minValObj);\n\n    tglswPtr->tglsw.maxVal = 20.0;\n    tglswPtr->tglsw.maxValObj = Tcl_NewDoubleObj(tglswPtr->tglsw.maxVal);\n    Tcl_IncrRefCount(tglswPtr->tglsw.maxValObj);\n\n    tglswPtr->tglsw.curValObj = Tcl_NewDoubleObj(0.0);\n    Tcl_IncrRefCount(tglswPtr->tglsw.curValObj);\n\n    /*\n     * Set the -variable option to the widget's path name\n     */\n    tglswPtr->tglsw.variableObj =\n\t    Tcl_NewStringObj(Tk_PathName(tglswPtr->core.tkwin), -1);\n    Tcl_IncrRefCount(tglswPtr->tglsw.variableObj);\n\n    TtkTrackElementState(&tglswPtr->core);\n}\n\n/*\n * TglswitchCleanup --\n *\tCleanup hook.\n */\nstatic void TglswitchCleanup(void *recordPtr)\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n\n    if (tglswPtr->tglsw.varTrace) {\n\tTtk_UntraceVariable(tglswPtr->tglsw.varTrace);\n\ttglswPtr->tglsw.varTrace = 0;\n    }\n}\n\n/*\n * TglswitchConfigure --\n *\tConfiguration hook.\n */\nstatic int TglswitchConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    Tcl_Obj *variableObj = tglswPtr->tglsw.variableObj;\n    Ttk_TraceHandle *varTrace = NULL;\n\n    if (mask & GEOMETRY_CHANGED) {\n\t/*\n\t * Processing the \"-size\" option:  Set the \"-style\" option to\n\t * \"(*.)Toggleswitch{1|2|3}\" if its value is of the same form.\n\t */\n\n\tconst char *styleName = 0, *lastDot = 0, *nameTail = 0;\n\n\tif (tglswPtr->core.styleObj) {\n\t    styleName = Tcl_GetString(tglswPtr->core.styleObj);\n\t}\n\tif (!styleName || *styleName == '\\0') {\n\t    styleName = \"Toggleswitch2\";\n\t}\n\tlastDot = strrchr(styleName, '.');\n\tnameTail = lastDot ? lastDot + 1 : styleName;\n\n\tif (!strcmp(nameTail, \"Toggleswitch1\")\n\t\t|| !strcmp(nameTail, \"Toggleswitch2\")\n\t\t|| !strcmp(nameTail, \"Toggleswitch3\")) {\n\t    size_t length = strlen(styleName);\n\t    char *styleName2 = (char *)Tcl_Alloc(length + 1);\n\t    const char *sizeStr = Tcl_GetString(tglswPtr->tglsw.sizeObj);\n\n\t    memcpy(styleName2, styleName, length + 1);\n\t    styleName2[length-1] = *sizeStr;\n\n\t    Tcl_DecrRefCount(tglswPtr->core.styleObj);\n\t    tglswPtr->core.styleObj = Tcl_NewStringObj(styleName2, -1);\n\t    Tcl_IncrRefCount(tglswPtr->core.styleObj);\n\n\t    Tcl_Free(styleName2);\n\n\t    /*\n\t     * Update the layout according to the new style\n\t     */\n\t    TtkCoreConfigure(interp, recordPtr, STYLE_CHANGED);\n\t}\n    } else if (mask & STYLE_CHANGED) {\t\t/* intentionally \"else if\" */\n\t/*\n\t * Processing the \"-style\" option:  Set the \"-size\" option\n\t * to \"1|2|3\" if the style is \"(*.)Toggleswitch{1|2|3}\"\n\t */\n\n\tconst char *sizeStr = 0;\n\tconst char *styleName = Tcl_GetString(tglswPtr->core.styleObj);\n\tconst char *lastDot = strrchr(styleName, '.');\n\tconst char *nameTail = lastDot ? lastDot + 1 : styleName;\n\n\tif (!strcmp(nameTail, \"Toggleswitch1\")) {\n\t    sizeStr = \"1\";\n\t} else if (!strcmp(nameTail, \"Toggleswitch2\")) {\n\t    sizeStr = \"2\";\n\t} else if (!strcmp(nameTail, \"Toggleswitch3\")) {\n\t    sizeStr = \"3\";\n\t}\n\n\tif (sizeStr) {\n\t    Tcl_DecrRefCount(tglswPtr->tglsw.sizeObj);\n\t    tglswPtr->tglsw.sizeObj = Tcl_NewStringObj(sizeStr, -1);\n\t    Tcl_IncrRefCount(tglswPtr->tglsw.sizeObj);\n\t}\n    }\n\n    if (!TkObjIsEmpty(variableObj)) {\n\tvarTrace = Ttk_TraceVariable(interp, variableObj,\n\t\tTglswitchVariableChanged, recordPtr);\n\tif (!varTrace) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\n\tTtk_UntraceVariable(varTrace);\n\treturn TCL_ERROR;\n    }\n\n    if (tglswPtr->tglsw.varTrace) {\n\tTtk_UntraceVariable(tglswPtr->tglsw.varTrace);\n    }\n    tglswPtr->tglsw.varTrace = varTrace;\n\n    return TCL_OK;\n}\n\n/*\n * TglswitchPostConfigure --\n *\tPost-configuration hook.\n */\nstatic int TglswitchPostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    void *recordPtr,\n    TCL_UNUSED(int))\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    int status = TCL_OK;\n\n    if (tglswPtr->tglsw.varTrace) {\n\tstatus = Ttk_FireTrace(tglswPtr->tglsw.varTrace);\n\tif (WidgetDestroyed(&tglswPtr->core)) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    return status;\n}\n\n/*\n * TglswitchGetLayout --\n *\tgetLayout hook.\n */\nstatic Ttk_Layout TglswitchGetLayout(\n    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    const char *styleName = 0;\n    Tcl_DString dsStyleName;\n    Ttk_Layout layout;\n\n    Tcl_DStringInit(&dsStyleName);\n\n    if (tglswPtr->core.styleObj) {\n\tstyleName = Tcl_GetString(tglswPtr->core.styleObj);\n\tTcl_DStringAppend(&dsStyleName, styleName, TCL_INDEX_NONE);\n    }\n    if (!styleName || *styleName == '\\0') {\n\tconst char *sizeStr = Tcl_GetString(tglswPtr->tglsw.sizeObj);\n\n\tstyleName = tglswPtr->core.widgetSpec->className;\n\tTcl_DStringAppend(&dsStyleName, styleName, TCL_INDEX_NONE);\n\tTcl_DStringAppend(&dsStyleName, sizeStr, TCL_INDEX_NONE);\n    }\n\n    layout = Ttk_CreateLayout(interp, themePtr, Tcl_DStringValue(&dsStyleName),\n\t    recordPtr, tglswPtr->core.optionTable, tglswPtr->core.tkwin);\n\n    Tcl_DStringFree(&dsStyleName);\n\n    return layout;\n}\n\n/*\n * TroughRange --\n *\tReturns the value area of the trough element, adjusted for slider size.\n */\nstatic Ttk_Box TroughRange(Tglswitch *tglswPtr)\n{\n    Ttk_Box troughBox = Ttk_ClientRegion(tglswPtr->core.layout, \"trough\");\n    Ttk_Element slider = Ttk_FindElement(tglswPtr->core.layout, \"slider\");\n\n    if (slider) {\n\tTtk_Box sliderBox = Ttk_ElementParcel(slider);\n\ttroughBox.x += sliderBox.width / 2;\n\ttroughBox.width -= sliderBox.width;\n    }\n\n    return troughBox;\n}\n\n/*\n * ValueToFraction --\n *\tReturns the fraction corresponding to a given value.\n */\nstatic double ValueToFraction(Tglswitch *tglswPtr, double value)\n{\n    double minVal = tglswPtr->tglsw.minVal;\n    double maxVal = tglswPtr->tglsw.maxVal;\n    double fraction = (value - minVal) / (maxVal - minVal);\n\n    return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;\n}\n\n/*\n * ValueToPoint --\n *\tReturns the x coordinate corresponding to a given value.\n */\nstatic int ValueToPoint(Tglswitch *tglswPtr, double value)\n{\n    Ttk_Box troughBox = TroughRange(tglswPtr);\n    double fraction = ValueToFraction(tglswPtr, value);\n\n    return troughBox.x + (int)(fraction * troughBox.width);\n}\n\n/*\n * PointToValue --\n *\tReturns the value corresponding to a given x coordinate.\n */\nstatic double PointToValue(Tglswitch *tglswPtr, int x)\n{\n    Ttk_Box troughBox = TroughRange(tglswPtr);\n    double minVal = tglswPtr->tglsw.minVal;\n    double maxVal = tglswPtr->tglsw.maxVal;\n    double value = 0.0, fraction;\n\n    Tcl_GetDoubleFromObj(NULL, tglswPtr->tglsw.curValObj, &value);\n    if (troughBox.width <= 0) {\n\treturn value;\n    }\n\n    fraction = (double)(x - troughBox.x) / (double)troughBox.width;\n    fraction = fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;\n\n    return minVal + fraction * (maxVal - minVal);\n}\n\n/*\n * TglswitchDoLayout --\n */\nstatic void TglswitchDoLayout(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    Ttk_Element slider = Ttk_FindElement(corePtr->layout, \"slider\");\n\n    Ttk_PlaceLayout(corePtr->layout, corePtr->state,\n\t    Ttk_WinBox(corePtr->tkwin));\n\n    /*\n     * Adjust the slider position\n     */\n    if (slider) {\n\tTglswitch *tglswPtr = (Tglswitch *)clientData;\n\tTtk_Box troughBox = Ttk_ClientRegion(tglswPtr->core.layout, \"trough\");\n\tTtk_Box sliderBox = Ttk_ElementParcel(slider);\n\tdouble value = 0.0;\n\tdouble fraction;\n\tint range;\n\n\tTcl_GetDoubleFromObj(NULL, tglswPtr->tglsw.curValObj, &value);\n\tfraction = ValueToFraction(tglswPtr, value);\n\trange = troughBox.width - sliderBox.width;\n\n\tsliderBox.x += (int)(fraction * range);\n\tTtk_PlaceElement(corePtr->layout, slider, sliderBox);\n    }\n}\n\n/*\n * $toggleswitch get ?min|max|$x? --\n *\tReturns the ttk::toggleswitch widget's current/minimum/maximum value,\n *\tor the value corresponding to $x.\n */\nstatic int TglswitchGetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    char *arg2 = NULL;\n    int x, res = TCL_OK;\n    double value = 0.0;\n\n    if (objc == 2) {\n\tTcl_SetObjResult(interp, tglswPtr->tglsw.curValObj);\n    } else if (objc == 3) {\n\targ2 = Tcl_GetString(objv[2]);\n\tif (!strcmp(arg2, \"min\")) {\n\t    Tcl_SetObjResult(interp, tglswPtr->tglsw.minValObj);\n\t} else if (!strcmp(arg2, \"max\")) {\n\t    Tcl_SetObjResult(interp, tglswPtr->tglsw.maxValObj);\n\t} else {\n\t    res = Tcl_GetIntFromObj(interp, objv[2], &x);\n\t    if (res == TCL_OK) {\n\t\tvalue = PointToValue(tglswPtr, x);\n\t\tTcl_SetObjResult(interp, Tcl_NewDoubleObj(value));\n\t    }\n\t}\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"get ?min|max|x?\");\n\treturn TCL_ERROR;\n    }\n\n    return res;\n}\n\n/*\n * $toggleswitch set $newValue\n *\tSets the ttk::toggleswitch widget's value to $newValue.\n */\nstatic int TglswitchSetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    double minVal = tglswPtr->tglsw.minVal;\n    double maxVal = tglswPtr->tglsw.maxVal;\n    double value;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"set value\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (tglswPtr->core.state & TTK_STATE_DISABLED) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Limit new value to between minVal and maxVal\n     */\n    value = value < minVal ? minVal : value > maxVal ? maxVal : value;\n\n    /*\n     * Set value\n     */\n    Tcl_DecrRefCount(tglswPtr->tglsw.curValObj);\n    tglswPtr->tglsw.curValObj = Tcl_NewDoubleObj(value);\n    Tcl_IncrRefCount(tglswPtr->tglsw.curValObj);\n    TtkRedisplayWidget(&tglswPtr->core);\n\n    if (WidgetDestroyed(&tglswPtr->core)) {\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n/*\n * $toggleswitch switchstate ?$boolean? --\n *\tModifies or inquires the widget's switch state.\n */\nstatic int TglswitchSwitchstateCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    Ttk_State selState = (tglswPtr->core.state & TTK_STATE_SELECTED);\n    Tcl_Obj *variableObj = tglswPtr->tglsw.variableObj;\n    int arg2 = 0;\n\n    if (objc == 2) {\n\t/*\n\t * Return the widget's current switch state\n\t */\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(selState));\n    } else if (objc == 3) {\n\tif (Tcl_GetBooleanFromObj(interp, objv[2], &arg2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (tglswPtr->core.state & TTK_STATE_DISABLED) {\n\t    return TCL_OK;\n\t}\n\n\t/*\n\t * Update the widget's selected state and current value\n\t */\n\tTcl_DecrRefCount(tglswPtr->tglsw.curValObj);\n\tif (arg2) {\n\t    TtkWidgetChangeState(&tglswPtr->core, TTK_STATE_SELECTED, 0);\n\t    tglswPtr->tglsw.curValObj = tglswPtr->tglsw.maxValObj;\n\t} else {\n\t    TtkWidgetChangeState(&tglswPtr->core, 0, TTK_STATE_SELECTED);\n\t    tglswPtr->tglsw.curValObj = tglswPtr->tglsw.minValObj;\n\t}\n\tTcl_IncrRefCount(tglswPtr->tglsw.curValObj);\n\n\tif (!TkObjIsEmpty(variableObj)) {\n\t    /*\n\t     * Update the associated variable\n\t     */\n\t    Tcl_Obj *newOnOffValueObj = arg2 ? tglswPtr->tglsw.onValueObj\n\t\t    : tglswPtr->tglsw.offValueObj;\n\t    if (Tcl_ObjSetVar2(interp, variableObj, NULL, newOnOffValueObj,\n\t\t    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\tif (WidgetDestroyed(&tglswPtr->core)) {\n\t    return TCL_ERROR;\n\t}\n\n\tif ((tglswPtr->core.state & TTK_STATE_SELECTED) != selState) {\n\t    /*\n\t     * Evaluate the associated command at global scope\n\t     */\n\t    return Tcl_EvalObjEx(interp, tglswPtr->tglsw.commandObj,\n\t\t    TCL_EVAL_GLOBAL);\n\t}\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"switchstate ?boolean?\");\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n/*\n * $toggleswitch toggle --\n *\tToggles the widget's switch state.\n */\nstatic int TglswitchToggleCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    static Tcl_Obj *newObjv[3];\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"toggle\");\n\treturn TCL_ERROR;\n    }\n\n    newObjv[0] = objv[0];\n    newObjv[1] = Tcl_NewStringObj(\"switchstate\", -1);\n    newObjv[2] = (tglswPtr->core.state & TTK_STATE_SELECTED) ?\n\t\t Tcl_NewBooleanObj(0) : Tcl_NewBooleanObj(1);\n\n    return TglswitchSwitchstateCommand(recordPtr, interp, 3, newObjv);\n}\n\n/*\n * $toggleswitch xcoord ?$value? --\n *\tReturns the x coordinate corresponding to $value, or to the current\n *\tvalue if $value is omitted.\n */\nstatic int TglswitchXcoordCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tglswitch *tglswPtr = (Tglswitch *)recordPtr;\n    double value;\n    int res = TCL_OK;\n\n    if (objc == 3) {\n\tres = Tcl_GetDoubleFromObj(interp, objv[2], &value);\n    } else if (objc == 2) {\n\tres = Tcl_GetDoubleFromObj(interp, tglswPtr->tglsw.curValObj, &value);\n    } else {\n\tTcl_WrongNumArgs(interp, 1, objv, \"xcoord ?value?\");\n\treturn TCL_ERROR;\n    }\n\n    if (res == TCL_OK) {\n\tint x = ValueToPoint(tglswPtr, value);\n\tTcl_SetObjResult(interp, Tcl_NewIntObj(x));\n    }\n\n    return res;\n}\n\nstatic const Ttk_Ensemble TglswitchCommands[] =\n{\n    { \"cget\",\t\tTtkWidgetCgetCommand, 0 },\n    { \"configure\",\tTtkWidgetConfigureCommand, 0 },\n    { \"get\",\t\tTglswitchGetCommand, 0 },\n    { \"identify\",\tTtkWidgetIdentifyCommand, 0 },\n    { \"instate\",\tTtkWidgetInstateCommand, 0 },\n    { \"set\",\t\tTglswitchSetCommand, 0 },\n    { \"state\",\t\tTtkWidgetStateCommand, 0 },\n    { \"style\",\t\tTtkWidgetStyleCommand, 0 },\n    { \"switchstate\",\tTglswitchSwitchstateCommand, 0 },\n    { \"toggle\",\t\tTglswitchToggleCommand, 0 },\n    { \"xcoord\",\t\tTglswitchXcoordCommand, 0 },\n    { 0, 0, 0 }\n};\n\nstatic const WidgetSpec TglswitchWidgetSpec =\n{\n    \"Toggleswitch\",\t\t/* Class name */\n    sizeof(Tglswitch),\t\t/* record size */\n    TglswitchOptionSpecs,\t/* option specs */\n    TglswitchCommands,\t\t/* widget commands */\n    TglswitchInitialize,\t/* initialization proc */\n    TglswitchCleanup,\t\t/* cleanup proc */\n    TglswitchConfigure,\t\t/* configure proc */\n    TglswitchPostConfigure,\t/* postConfigure */\n    TglswitchGetLayout,\t\t/* getLayoutProc */\n    TtkWidgetSize,\t\t/* sizeProc */\n    TglswitchDoLayout,\t\t/* layoutProc */\n    TtkWidgetDisplay\t\t/* displayProc */\n};\n\n/*\n * Initialization.\n */\nMODULE_SCOPE void TtkToggleswitch_Init(Tcl_Interp *interp)\n{\n    RegisterWidget(interp, \"ttk::toggleswitch\", &TglswitchWidgetSpec);\n}\n"
  },
  {
    "path": "generic/ttk/ttkTrace.c",
    "content": "/*\n * Copyright 2003, Joe English\n *\n * Simplified interface to Tcl_TraceVariable.\n *\n * PROBLEM: Can't distinguish \"variable does not exist\" (which is OK)\n * from other errors (which are not).\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\nstruct TtkTraceHandle_\n{\n    Tcl_Interp\t\t*interp;\t/* Containing interpreter */\n    Tcl_Obj\t\t*varnameObj;\t/* Name of variable being traced */\n    Ttk_TraceProc\tcallback;\t/* Callback procedure */\n    void\t\t*clientData;\t/* Data to pass to callback */\n};\n\n/*\n * Tcl_VarTraceProc for trace handles.\n */\nstatic char *\nVarTraceProc(\n    void *clientData,\t/* Widget record pointer */\n    Tcl_Interp *interp,\t/* Interpreter containing variable. */\n    TCL_UNUSED(const char *),\t/* name1 */\n    TCL_UNUSED(const char *),\t/* name2 */\n    int flags)\t\t\t/* Information about what happened. */\n{\n    Ttk_TraceHandle *tracePtr = (Ttk_TraceHandle *)clientData;\n    const char *name, *value;\n    Tcl_Obj *valuePtr;\n\n    if (Tcl_InterpDeleted(interp)) {\n\treturn NULL;\n    }\n\n    name = Tcl_GetString(tracePtr->varnameObj);\n\n    /*\n     * If the variable is being unset, then re-establish the trace:\n     */\n    if (flags & TCL_TRACE_DESTROYED) {\n\t/*\n\t * If a prior call to Ttk_UntraceVariable() left behind an\n\t * indicator that we wanted this handler to be deleted (see below),\n\t * cleanup the ClientData bits and exit.\n\t */\n\tif (tracePtr->interp == NULL) {\n\t    Tcl_DecrRefCount(tracePtr->varnameObj);\n\t    Tcl_Free(tracePtr);\n\t    return NULL;\n\t}\n\tTcl_TraceVar2(interp, name, NULL,\n\t\tTCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tVarTraceProc, clientData);\n\ttracePtr->callback(tracePtr->clientData, NULL);\n\treturn NULL;\n    }\n\n    /*\n     * Call the callback:\n     */\n    valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);\n    value = valuePtr ?  Tcl_GetString(valuePtr) : NULL;\n    tracePtr->callback(tracePtr->clientData, value);\n\n    return NULL;\n}\n\n/* Ttk_TraceVariable(interp, varNameObj, callback, clientdata) --\n *\tAttach a write trace to the specified variable,\n *\twhich will pass the variable's value to 'callback'\n *\twhenever the variable is set.\n *\n *\tWhen the variable is unset, passes NULL to the callback\n *\tand reattaches the trace.\n */\nTtk_TraceHandle *Ttk_TraceVariable(\n    Tcl_Interp *interp,\n    Tcl_Obj *varnameObj,\n    Ttk_TraceProc callback,\n    void *clientData)\n{\n    Ttk_TraceHandle *h = (Ttk_TraceHandle *)Tcl_Alloc(sizeof(*h));\n    int status;\n\n    h->interp = interp;\n    h->varnameObj = Tcl_DuplicateObj(varnameObj);\n    Tcl_IncrRefCount(h->varnameObj);\n    h->clientData = clientData;\n    h->callback = callback;\n\n    status = Tcl_TraceVar2(interp, Tcl_GetString(varnameObj),\n\t    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t    VarTraceProc, h);\n\n    if (status != TCL_OK) {\n\tTcl_DecrRefCount(h->varnameObj);\n\tTcl_Free(h);\n\treturn NULL;\n    }\n\n    return h;\n}\n\n/*\n * Ttk_UntraceVariable --\n *\tRemove previously-registered trace and free the handle.\n */\nvoid Ttk_UntraceVariable(Ttk_TraceHandle *h)\n{\n    if (h) {\n\tvoid *cd = NULL;\n\n\t/*\n\t * Workaround for Tcl Bug 3062331.  The trace design problem is\n\t * that when variable unset traces fire, Tcl documents that the\n\t * traced variable has already been unset.  It's already gone.\n\t * So from within an unset trace, if you try to call\n\t * Tcl_UntraceVar() on that variable, it will do nothing, because\n\t * the variable by that name can no longer be found.  It's gone.\n\t * This means callers of Tcl_UntraceVar() that might be running\n\t * in response to an unset trace have to handle the possibility\n\t * that their Tcl_UntraceVar() call will do nothing.  In this case,\n\t * we have to support the possibility that Tcl_UntraceVar() will\n\t * leave the trace in place, so we need to leave the ClientData\n\t * untouched so when that trace does fire it will not crash.\n\t */\n\n\t/*\n\t * Search the traces on the variable to see if the one we are tasked\n\t * with removing is present.\n\t */\n\twhile ((cd = Tcl_VarTraceInfo(h->interp, Tcl_GetString(h->varnameObj),\n\t\tTCL_GLOBAL_ONLY, VarTraceProc, cd)) != NULL) {\n\t    if (cd == h) {\n\t\tbreak;\n\t    }\n\t}\n\t/*\n\t * If the trace we wish to delete is not visible, Tcl_UntraceVar\n\t * will do nothing, so don't try to call it.  Instead set an\n\t * indicator in the Ttk_TraceHandle that we need to cleanup later.\n\t */\n\tif (cd == NULL) {\n\t    h->interp = NULL;\n\t    return;\n\t}\n\tTcl_UntraceVar2(h->interp, Tcl_GetString(h->varnameObj),\n\t\tNULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,\n\t\tVarTraceProc, h);\n\tTcl_DecrRefCount(h->varnameObj);\n\tTcl_Free(h);\n    }\n}\n\n/*\n * Ttk_FireTrace --\n *\tExecutes a trace handle as if the variable has been written.\n *\n *\tNote: may reenter the interpreter.\n */\nint Ttk_FireTrace(Ttk_TraceHandle *tracePtr)\n{\n    Tcl_Interp *interp = tracePtr->interp;\n    void *clientData = tracePtr->clientData;\n    const char *name = Tcl_GetString(tracePtr->varnameObj);\n    Ttk_TraceProc callback = tracePtr->callback;\n    Tcl_Obj *valuePtr;\n    const char *value;\n\n    /* Read the variable.\n     * Note that this can reenter the interpreter, and anything can happen --\n     * including the current trace handle being freed!\n     */\n    valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY);\n    value = valuePtr ? Tcl_GetString(valuePtr) : NULL;\n\n    /* Call callback.\n     */\n    callback(clientData, value);\n\n    return TCL_OK;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkTrack.c",
    "content": "/*\n * Copyright © 2004, Joe English\n *\n * TtkTrackElementState() -- helper routine for widgets\n * like scrollbars in which individual elements may\n * be active or pressed instead of the widget as a whole.\n *\n * Usage:\n *\tTtkTrackElementState(&recordPtr->core);\n *\n * Registers an event handler on the widget that tracks pointer\n * events and updates the state of the element under the\n * mouse cursor.\n *\n * The \"active\" element is the one under the mouse cursor,\n * and is normally set to the ACTIVE state unless another element\n * is currently being pressed.\n *\n * The active element becomes \"pressed\" on <Button> events,\n * and remains \"active\" and \"pressed\" until the corresponding\n * <ButtonRelease> event.\n *\n * TODO: Handle \"chords\" properly (e.g., <B1-Button-2>)\n */\n\n#include \"tkInt.h\"\n#include \"ttkTheme.h\"\n#include \"ttkWidget.h\"\n\ntypedef struct {\n    WidgetCore\t\t*corePtr;\t/* widget to track */\n    Ttk_Layout\t\ttracking;\t/* current layout being tracked */\n    Ttk_Element\tactiveElement;\t/* element under the mouse cursor */\n    Ttk_Element\tpressedElement; /* currently pressed element */\n} ElementStateTracker;\n\n/*\n * ActivateElement(es, node) --\n *\tMake 'node' the active element if non-NULL.\n *\tDeactivates the currently active element if different.\n *\n *\tThe active element has TTK_STATE_ACTIVE set _unless_\n *\tanother element is 'pressed'\n */\nstatic void ActivateElement(ElementStateTracker *es, Ttk_Element element)\n{\n    if (es->activeElement == element) {\n\t/* No change */\n\treturn;\n    }\n\n    if (!es->pressedElement) {\n\tif (es->activeElement) {\n\t    /* Deactivate old element */\n\t    Ttk_ChangeElementState(es->activeElement, 0,TTK_STATE_ACTIVE);\n\t}\n\tif (element) {\n\t    /* Activate new element */\n\t    Ttk_ChangeElementState(element, TTK_STATE_ACTIVE,0);\n\t}\n\tTtkRedisplayWidget(es->corePtr);\n    }\n\n    es->activeElement = element;\n}\n\n/* ReleaseElement --\n *\tReleases the currently pressed element, if any.\n */\nstatic void ReleaseElement(ElementStateTracker *es)\n{\n    if (!es->pressedElement) {\n\treturn;\n    }\n\n    Ttk_ChangeElementState(\n\tes->pressedElement, 0,TTK_STATE_PRESSED|TTK_STATE_ACTIVE);\n    es->pressedElement = 0;\n\n    /* Reactivate element under the mouse cursor:\n     */\n    if (es->activeElement) {\n\tTtk_ChangeElementState(es->activeElement, TTK_STATE_ACTIVE, 0);\n    }\n\n    TtkRedisplayWidget(es->corePtr);\n}\n\n/* PressElement --\n *\tPresses the specified element.\n */\nstatic void PressElement(ElementStateTracker *es, Ttk_Element element)\n{\n    if (es->pressedElement) {\n\tReleaseElement(es);\n    }\n\n    if (element) {\n\tTtk_ChangeElementState(\n\t    element, TTK_STATE_PRESSED|TTK_STATE_ACTIVE, 0);\n    }\n\n    es->pressedElement = element;\n    TtkRedisplayWidget(es->corePtr);\n}\n\n/* ElementStateEventProc --\n *\tEvent handler for tracking element states.\n */\n\nstatic const unsigned ElementStateMask =\n      ButtonPressMask\n    | ButtonReleaseMask\n    | PointerMotionMask\n    | LeaveWindowMask\n    | EnterWindowMask\n    | StructureNotifyMask\n    ;\n\nstatic void\nElementStateEventProc(void *clientData, XEvent *ev)\n{\n    ElementStateTracker *es = (ElementStateTracker *)clientData;\n    Ttk_Layout layout = es->corePtr->layout;\n    Ttk_Element element;\n\n    /* Guard against dangling pointers [#2431428]\n     */\n    if (es->tracking != layout) {\n\tes->pressedElement = es->activeElement = 0;\n\tes->tracking = layout;\n    }\n\n    switch (ev->type)\n    {\n\tcase MotionNotify :\n\t    element = Ttk_IdentifyElement(\n\t\tlayout, ev->xmotion.x, ev->xmotion.y);\n\t    ActivateElement(es, element);\n\t    break;\n\tcase LeaveNotify:\n\t    ActivateElement(es, 0);\n\t    if (ev->xcrossing.mode == NotifyGrab) {\n\t\tPressElement(es, 0);\n\t    }\n\t    break;\n\tcase EnterNotify:\n\t    element = Ttk_IdentifyElement(\n\t\tlayout, ev->xcrossing.x, ev->xcrossing.y);\n\t    ActivateElement(es, element);\n\t    break;\n\tcase ButtonPress:\n\t    element = Ttk_IdentifyElement(\n\t\tlayout, ev->xbutton.x, ev->xbutton.y);\n\t    if (element) {\n\t\tPressElement(es, element);\n\t    }\n\t    break;\n\tcase ButtonRelease:\n\t    ReleaseElement(es);\n\t    break;\n\tcase DestroyNotify:\n\t    /* Unregister this event handler and free client data.\n\t     */\n\t    Tk_DeleteEventHandler(es->corePtr->tkwin,\n\t\t    ElementStateMask, ElementStateEventProc, es);\n\t    Tcl_Free(clientData);\n\t    break;\n    }\n}\n\n/*\n * TtkTrackElementState --\n *\tRegister an event handler to manage the 'pressed'\n *\tand 'active' states of individual widget elements.\n */\n\nvoid TtkTrackElementState(WidgetCore *corePtr)\n{\n    ElementStateTracker *es = (ElementStateTracker *)Tcl_Alloc(sizeof(*es));\n    es->corePtr = corePtr;\n    es->tracking = 0;\n    es->activeElement = es->pressedElement = 0;\n    Tk_CreateEventHandler(corePtr->tkwin,\n\t    ElementStateMask,ElementStateEventProc,es);\n}\n\n"
  },
  {
    "path": "generic/ttk/ttkTreeview.c",
    "content": "/*\n * Copyright © 2004, Joe English\n *\n * ttk::treeview widget implementation.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#elif defined(MAC_OSX_TK)\n#include \"tkMacOSXPrivate.h\"\n#endif\n\n#define DEF_TREE_ROWS\t\t\"10\"\n#define DEF_TITLECOLUMNS\t\"0\"\n#define DEF_TITLEITEMS\t\t\"0\"\n#define DEF_STRIPED\t\t\"0\"\n#define DEF_COLWIDTH\t\t\"200\"\n#define DEF_MINWIDTH\t\t\"20\"\n\nstatic const Tk_Anchor DEFAULT_IMAGEANCHOR = TK_ANCHOR_W;\nstatic const int DEFAULT_INDENT = 20;\nstatic const int HALO\t= 4;\t/* heading separator */\n\n#define STATE_CHANGED\t\t(0x100)\t/* item state option changed */\n\n/*------------------------------------------------------------------------\n * +++ Tree items.\n *\n * INVARIANTS:\n *\titem->children\t==> item->children->parent == item\n *\titem->next\t==> item->next->parent == item->parent\n *\titem->next\t==> item->next->prev == item\n *\titem->prev\t==> item->prev->next == item\n */\n\ntypedef struct TreeItemRec TreeItem;\nstruct TreeItemRec {\n    Tcl_HashEntry *entryPtr;\t/* Back-pointer to hash table entry */\n    TreeItem\t*parent;\t/* Parent item */\n    TreeItem\t*children;\t/* Linked list of child items */\n    TreeItem\t*next;\t\t/* Next sibling */\n    TreeItem\t*prev;\t\t/* Previous sibling */\n\n    /*\n     * Options and instance data:\n     */\n    Ttk_State\tstate;\n    Tcl_Obj\t*textObj;\n    Tcl_Obj\t*imageObj;\n    Tcl_Obj\t*valuesObj;\n    Tcl_Obj\t*openObj;\n    Tcl_Obj\t*tagsObj;\n    Tcl_Obj\t*selObj;\n    Tcl_Obj\t*imageAnchorObj;\n    int\thidden;\n    int\t\theight;\t/* Height is in number of row heights */\n\n    Ttk_TagSet  *cellTagSets;\n    Tcl_Size\tnTagSets;\n\n    /*\n     * Derived resources:\n     */\n    Ttk_TagSet\ttagset;\n    Ttk_ImageSpec *imagespec;\n    int itemPos;\t\t/* Counting items */\n    int visiblePos;\t\t/* Counting visible items */\n    int rowPos;\t\t\t/* Counting rows (visible physical space) */\n};\n\n#define ITEM_OPTION_TAGS_CHANGED\t0x100\n#define ITEM_OPTION_IMAGE_CHANGED\t0x200\n\nstatic const Tk_OptionSpec ItemOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\t\"\", offsetof(TreeItem,textObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_INT, \"-height\", \"height\", \"Height\",\n\t\"1\", TCL_INDEX_NONE, offsetof(TreeItem,height),\n\t0,0,0 },\n    {TK_OPTION_BOOLEAN, \"-hidden\", \"hidden\", \"Hidden\",\n\t\"0\", TCL_INDEX_NONE, offsetof(TreeItem,hidden),\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tNULL, offsetof(TreeItem,imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED },\n    {TK_OPTION_ANCHOR, \"-imageanchor\", \"imageAnchor\", \"ImageAnchor\",\n\tNULL, offsetof(TreeItem,imageAnchorObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_STRING, \"-values\", \"values\", \"Values\",\n\tNULL, offsetof(TreeItem,valuesObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_BOOLEAN, \"-open\", \"open\", \"Open\",\n\t\"0\", offsetof(TreeItem,openObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-tags\", \"tags\", \"Tags\",\n\tNULL, offsetof(TreeItem,tagsObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED },\n\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}\n};\n\n/* Forward declarations */\nstatic void RemoveTag(TreeItem *, Ttk_Tag);\nstatic void RemoveTagFromCellsAtItem(TreeItem *, Ttk_Tag);\n\n/* + NewItem --\n *\tAllocate a new, uninitialized, unlinked item\n */\nstatic TreeItem *NewItem(void)\n{\n    TreeItem *item = (TreeItem *)Tcl_Alloc(sizeof(*item));\n\n    item->entryPtr = 0;\n    item->parent = item->children = item->next = item->prev = NULL;\n\n    item->state = 0ul;\n    item->textObj = NULL;\n    item->imageObj = NULL;\n    item->valuesObj = NULL;\n    item->openObj = NULL;\n    item->tagsObj = NULL;\n    item->selObj = NULL;\n    item->imageAnchorObj = NULL;\n    item->hidden = 0;\n    item->height = 1;\n    item->cellTagSets = NULL;\n    item->nTagSets = 0;\n\n    item->tagset = NULL;\n    item->imagespec = NULL;\n\n    return item;\n}\n\n/* + FreeItem --\n *\tDestroy an item\n */\nstatic void FreeItem(TreeItem *item)\n{\n    Tcl_Size i;\n    if (item->textObj) { Tcl_DecrRefCount(item->textObj); }\n    if (item->imageObj) { Tcl_DecrRefCount(item->imageObj); }\n    if (item->valuesObj) { Tcl_DecrRefCount(item->valuesObj); }\n    if (item->openObj) { Tcl_DecrRefCount(item->openObj); }\n    if (item->tagsObj) { Tcl_DecrRefCount(item->tagsObj); }\n    if (item->selObj) { Tcl_DecrRefCount(item->selObj); }\n    if (item->imageAnchorObj) { Tcl_DecrRefCount(item->imageAnchorObj); }\n\n    if (item->tagset)\t{ Ttk_FreeTagSet(item->tagset); }\n    if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }\n    if (item->cellTagSets) {\n\tfor (i = 0; i < item->nTagSets; ++i) {\n\t    if (item->cellTagSets[i] != NULL) {\n\t\tTtk_FreeTagSet(item->cellTagSets[i]);\n\t    }\n\t}\n\tTcl_Free(item->cellTagSets);\n    }\n\n    Tcl_Free(item);\n}\n\nstatic void FreeItemCB(void *clientData) { FreeItem((TreeItem *)clientData); }\n\n/* + DetachItem --\n *\tUnlink an item from the tree.\n */\nstatic void DetachItem(TreeItem *item)\n{\n    if (item->parent && item->parent->children == item) {\n\titem->parent->children = item->next;\n    }\n    if (item->prev) {\n\titem->prev->next = item->next;\n    }\n    if (item->next) {\n\titem->next->prev = item->prev;\n    }\n    item->next = item->prev = item->parent = NULL;\n}\n\n/* + InsertItem --\n *\tInsert an item into the tree after the specified item.\n *\n * Preconditions:\n *\t+ item is currently detached\n *\t+ prev != NULL ==> prev->parent == parent.\n */\nstatic void InsertItem(TreeItem *parent, TreeItem *prev, TreeItem *item)\n{\n    item->parent = parent;\n    item->prev = prev;\n    if (prev) {\n\titem->next = prev->next;\n\tprev->next = item;\n    } else {\n\titem->next = parent->children;\n\tparent->children = item;\n    }\n    if (item->next) {\n\titem->next->prev = item;\n    }\n}\n\n/* + NextPreorder --\n *\tReturn the next item in preorder traversal order.\n */\n\nstatic TreeItem *NextPreorder(TreeItem *item)\n{\n    if (item->children) {\n\treturn item->children;\n    }\n    while (!item->next) {\n\titem = item->parent;\n\tif (!item) {\n\t    return 0;\n\t}\n    }\n    return item->next;\n}\n\n/*------------------------------------------------------------------------\n * +++ Display items and tag options.\n */\n\ntypedef struct {\n    Tcl_Obj *textObj;\t\t/* taken from item / data cell */\n    Tcl_Obj *imageObj;\t\t/* taken from item or tag*/\n    Tcl_Obj *imageAnchorObj;\t/* taken from item or tag */\n    Tcl_Obj *anchorObj;\t\t/* from column <<NOTE-ANCHOR>> */\n    Tcl_Obj *backgroundObj;\t/* remainder from tag */\n    Tcl_Obj *stripedBgObj;\n    Tcl_Obj *foregroundObj;\n    Tcl_Obj *fontObj;\n    Tcl_Obj *paddingObj;\n} DisplayItem;\n\nstatic const Tk_OptionSpec DisplayOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\tNULL, offsetof(DisplayItem,textObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\t\"center\", offsetof(DisplayItem,anchorObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY_CHANGED},\t/* <<NOTE-ANCHOR>> */\n    /* From here down are the tags options. The index in TagOptionSpecs\n     * below should be kept in synch with this position.\n     */\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\tNULL, offsetof(DisplayItem,imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_ANCHOR, \"-imageanchor\", \"imageAnchor\", \"ImageAnchor\",\n\tNULL, offsetof(DisplayItem,imageAnchorObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_COLOR, \"-background\", \"windowColor\", \"WindowColor\",\n\tNULL, offsetof(DisplayItem,backgroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_COLOR, \"-stripedbackground\", \"windowColor\", \"WindowColor\",\n\tNULL, offsetof(DisplayItem,stripedBgObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_COLOR, \"-foreground\", \"textColor\", \"TextColor\",\n\tNULL, offsetof(DisplayItem,foregroundObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_FONT, \"-font\", \"font\", \"Font\",\n\tNULL, offsetof(DisplayItem,fontObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Pad\",\n\tNULL, offsetof(DisplayItem,paddingObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },\n\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}\n};\n\nstatic const Tk_OptionSpec *TagOptionSpecs = &DisplayOptionSpecs[2];\n\n/*------------------------------------------------------------------------\n * +++ Columns.\n *\n * There are separate option tables associated with the column record:\n * ColumnOptionSpecs is for configuring the column,\n * and HeadingOptionSpecs is for drawing headings.\n */\ntypedef struct {\n    int\twidth;\t\t/* Column width, in pixels */\n    int\tminWidth;\t/* Minimum column width, in pixels */\n    int\tstretch;\t/* Should column stretch while resizing? */\n    int\t\tseparator;\t/* Should this column have a separator? */\n    Tcl_Obj\t*idObj;\t\t/* Column identifier, from -columns option */\n\n    Tcl_Obj\t*anchorObj;\t/* -anchor for cell data <<NOTE-ANCHOR>> */\n\n    /* Column heading data:\n     */\n    Tcl_Obj\t*headingObj;\t\t/* Heading label */\n    Tcl_Obj\t*headingImageObj;\t/* Heading image */\n    Tcl_Obj\t*headingAnchorObj;\t/* -anchor for heading label */\n    Tcl_Obj\t*headingCommandObj;\t/* Command to execute */\n    Tcl_Obj\t*headingStateObj;\t/* @@@ testing ... */\n    Ttk_State\theadingState;\t\t/* ... */\n\n    /* Temporary storage for cell data\n     */\n    Tcl_Obj\t*data;\n    int\t\tselected;\n    Ttk_TagSet\ttagset;\n} TreeColumn;\n\nstatic void InitColumn(TreeColumn *column)\n{\n    column->width = atoi(DEF_COLWIDTH);\n    column->minWidth = atoi(DEF_MINWIDTH);\n    column->stretch = 1;\n    column->separator = 0;\n    column->idObj = 0;\n    column->anchorObj = 0;\n\n    column->headingState = 0;\n    column->headingObj = 0;\n    column->headingImageObj = 0;\n    column->headingAnchorObj = 0;\n    column->headingStateObj = 0;\n    column->headingCommandObj = 0;\n\n    column->data = 0;\n    column->tagset = NULL;\n}\n\nstatic void FreeColumn(TreeColumn *column)\n{\n    if (column->idObj) { Tcl_DecrRefCount(column->idObj); }\n    if (column->anchorObj) { Tcl_DecrRefCount(column->anchorObj); }\n\n    if (column->headingObj) { Tcl_DecrRefCount(column->headingObj); }\n    if (column->headingImageObj) { Tcl_DecrRefCount(column->headingImageObj); }\n    if (column->headingAnchorObj) { Tcl_DecrRefCount(column->headingAnchorObj); }\n    if (column->headingStateObj) { Tcl_DecrRefCount(column->headingStateObj); }\n    if (column->headingCommandObj) { Tcl_DecrRefCount(column->headingCommandObj); }\n\n    /* Don't touch column->data, it's scratch storage */\n}\n\nstatic const Tk_OptionSpec ColumnOptionSpecs[] = {\n    {TK_OPTION_INT, \"-width\", \"width\", \"Width\",\n\tDEF_COLWIDTH, TCL_INDEX_NONE, offsetof(TreeColumn,width),\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_INT, \"-minwidth\", \"minWidth\", \"MinWidth\",\n\tDEF_MINWIDTH, TCL_INDEX_NONE, offsetof(TreeColumn,minWidth),\n\t0,0,0 },\n    {TK_OPTION_BOOLEAN, \"-separator\", \"separator\", \"Separator\",\n\t\"0\", TCL_INDEX_NONE, offsetof(TreeColumn,separator),\n\t0,0,0 },\n    {TK_OPTION_BOOLEAN, \"-stretch\", \"stretch\", \"Stretch\",\n\t\"1\", TCL_INDEX_NONE, offsetof(TreeColumn,stretch),\n\t0,0,GEOMETRY_CHANGED },\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\t\"w\", offsetof(TreeColumn,anchorObj), TCL_INDEX_NONE,\t/* <<NOTE-ANCHOR>> */\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-id\", \"id\", \"ID\",\n\tNULL, offsetof(TreeColumn,idObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,READONLY_OPTION },\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}\n};\n\nstatic const Tk_OptionSpec HeadingOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-text\", \"text\", \"Text\",\n\t\"\", offsetof(TreeColumn,headingObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-image\", \"image\", \"Image\",\n\t\"\", offsetof(TreeColumn,headingImageObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_ANCHOR, \"-anchor\", \"anchor\", \"Anchor\",\n\t\"center\", offsetof(TreeColumn,headingAnchorObj), TCL_INDEX_NONE,\n\t0,0,0 },\n    {TK_OPTION_STRING, \"-command\", \"\", \"\",\n\t\"\", offsetof(TreeColumn,headingCommandObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK,0,0 },\n    {TK_OPTION_STRING, \"state\", \"\", \"\",\n\t\"\", offsetof(TreeColumn,headingStateObj), TCL_INDEX_NONE,\n\t0,0,STATE_CHANGED },\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}\n};\n\n/*------------------------------------------------------------------------\n * +++ -show option:\n * TODO: Implement SHOW_BRANCHES.\n */\n\n#define SHOW_TREE\t(0x1)\t/* Show tree column? */\n#define SHOW_HEADINGS\t(0x2)\t/* Show heading row? */\n\n#define DEFAULT_SHOW\t\"tree headings\"\n\nstatic const char *const showStrings[] = {\n    \"tree\", \"headings\", NULL\n};\n\nstatic int GetEnumSetFromObj(\n    Tcl_Interp *interp,\n    Tcl_Obj *objPtr,\n    const char *const table[],\n    unsigned *resultPtr)\n{\n    unsigned result = 0;\n    Tcl_Size i, objc;\n    Tcl_Obj **objv;\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    for (i = 0; i < objc; ++i) {\n\tint index;\n\tif (TCL_OK != Tcl_GetIndexFromObjStruct(interp, objv[i], table,\n\t\tsizeof(char *), \"value\", TCL_EXACT, &index))\n\t{\n\t    return TCL_ERROR;\n\t}\n\tresult |= (1 << index);\n    }\n\n    *resultPtr = result;\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Treeview widget record.\n *\n * Dependencies:\n *\tcolumns, columnNames: -columns\n *\tdisplayColumns:\t-columns, -displaycolumns\n *\theadingHeight: [layout]\n *\trowHeight, indent: style\n */\ntypedef struct {\n    /* Resources acquired at initialization-time:\n     */\n    Tk_OptionTable itemOptionTable;\n    Tk_OptionTable columnOptionTable;\n    Tk_OptionTable headingOptionTable;\n    Tk_OptionTable displayOptionTable;\n    Tk_BindingTable bindingTable;\n    Ttk_TagTable tagTable;\n\n    /* Acquired in GetLayout hook:\n     */\n    Ttk_Layout itemLayout;\n    Ttk_Layout cellLayout;\n    Ttk_Layout headingLayout;\n    Ttk_Layout rowLayout;\n    Ttk_Layout separatorLayout;\n\n    int headingHeight;\t\t/* Space for headings */\n    int rowHeight;\t\t/* Height of each item */\n    int colSeparatorWidth;\t/* Width of column separator, if used (screen units) */\n    int indent;\t\t\t/* Horizontal offset for child items (screen units) */\n\n    /* Tree data:\n     */\n    Tcl_HashTable items;\t/* Map: item name -> item */\n    int serial;\t\t\t/* Next item # for autogenerated names */\n    TreeItem *root;\t\t/* Root item */\n\n    TreeColumn column0;\t\t/* Column options for display column #0 */\n    TreeColumn *columns;\t/* Array of column options for data columns */\n\n    TreeItem *focus;\t\t/* Current focus item */\n    TreeItem *endPtr;\t\t/* See EndPosition() */\n\n    /* Widget options:\n     */\n    Tcl_Obj *columnsObj;\t/* List of symbolic column names */\n    Tcl_Obj *displayColumnsObj;\t/* List of columns to display */\n\n    Tcl_Obj *heightObj;\t\t/* height (rows) */\n    Tcl_Obj *paddingObj;\t/* internal padding */\n    Tcl_Size nTitleColumns;\t/* -titlecolumns */\n    Tcl_Size nTitleItems;\t\t/* -titleitems */\n    int striped;\t\t/* -striped option */\n\n    Tcl_Obj *showObj;\t\t/* -show list */\n    Tcl_Obj *selectModeObj;\t/* -selectmode option */\n    Tcl_Obj *selectTypeObj;\t/* -selecttype option */\n\n    Scrollable xscroll;\n    ScrollHandle xscrollHandle;\n    Scrollable yscroll;\n    ScrollHandle yscrollHandle;\n\n    /* Derived resources:\n     */\n    Tcl_HashTable columnNames;\t/* Map: column name -> column table entry */\n    Tcl_Size nColumns;\t\t/* #columns */\n    Tcl_Size nDisplayColumns;\t/* #display columns */\n    TreeColumn **displayColumns; /* List of columns for display (incl tree) */\n    int titleWidth;\t\t/* Width of non-scrolled columns */\n    int titleRows;\t\t/* Height of non-scrolled items, in rows */\n    int totalRows;\t\t/* Height of non-hidden items, in rows */\n    int rowPosNeedsUpdate;\t/* Internal rowPos data needs update */\n    Ttk_Box headingArea;\t/* Display area for column headings */\n    Ttk_Box treeArea;\t/* Display area for tree */\n    int slack;\t\t\t/* Slack space (see Resizing section) */\n    unsigned showFlags;\t\t/* bitmask of subparts to display */\n} TreePart;\n\ntypedef struct {\n    WidgetCore core;\n    TreePart tree;\n} Treeview;\n\n#define USER_MASK\t\t0x0100\n#define COLUMNS_CHANGED\t(USER_MASK)\n#define DCOLUMNS_CHANGED\t(USER_MASK<<1)\n#define SCROLLCMD_CHANGED\t(USER_MASK<<2)\n#define SHOW_CHANGED\t\t(USER_MASK<<3)\n\nstatic const char *const SelectModeStrings[] = { \"none\", \"browse\", \"extended\", NULL };\nstatic const char *const SelectTypeStrings[] = { \"item\", \"cell\", NULL };\n\nstatic const Tk_OptionSpec TreeviewOptionSpecs[] = {\n    {TK_OPTION_STRING, \"-columns\", \"columns\", \"Columns\",\n\t\"\", offsetof(Treeview,tree.columnsObj), TCL_INDEX_NONE,\n\t0, 0, COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ },\n    {TK_OPTION_STRING, \"-displaycolumns\",\"displayColumns\",\"DisplayColumns\",\n\t\"#all\", offsetof(Treeview,tree.displayColumnsObj), TCL_INDEX_NONE,\n\t0, 0, DCOLUMNS_CHANGED | GEOMETRY_CHANGED },\n    {TK_OPTION_STRING, \"-show\", \"show\", \"Show\",\n\tDEFAULT_SHOW, offsetof(Treeview,tree.showObj), TCL_INDEX_NONE,\n\t0, 0, SHOW_CHANGED | GEOMETRY_CHANGED },\n\n    {TK_OPTION_STRING_TABLE, \"-selectmode\", \"selectMode\", \"SelectMode\",\n\t\"extended\", offsetof(Treeview,tree.selectModeObj), TCL_INDEX_NONE,\n\t0, SelectModeStrings, 0 },\n    {TK_OPTION_STRING_TABLE, \"-selecttype\", \"selectType\", \"SelectType\",\n\t\"item\", offsetof(Treeview,tree.selectTypeObj), TCL_INDEX_NONE,\n\t0, SelectTypeStrings, 0 },\n\n    {TK_OPTION_PIXELS, \"-height\", \"height\", \"Height\",\n\tDEF_TREE_ROWS, offsetof(Treeview,tree.heightObj), TCL_INDEX_NONE,\n\t0, 0, GEOMETRY_CHANGED},\n    {TK_OPTION_STRING, \"-padding\", \"padding\", \"Pad\",\n\tNULL, offsetof(Treeview,tree.paddingObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED },\n    {TK_OPTION_INT, \"-titlecolumns\", \"titlecolumns\", \"Titlecolumns\",\n\tDEF_TITLECOLUMNS, TCL_INDEX_NONE, offsetof(Treeview,tree.nTitleColumns),\n\tTK_OPTION_VAR(Tcl_Size), 0, GEOMETRY_CHANGED},\n    {TK_OPTION_INT, \"-titleitems\", \"titleitems\", \"Titleitems\",\n\tDEF_TITLEITEMS, TCL_INDEX_NONE, offsetof(Treeview,tree.nTitleItems),\n\tTK_OPTION_VAR(Tcl_Size), 0, GEOMETRY_CHANGED},\n    {TK_OPTION_BOOLEAN, \"-striped\", \"striped\", \"Striped\",\n\tDEF_STRIPED, TCL_INDEX_NONE, offsetof(Treeview,tree.striped),\n\t0, 0, GEOMETRY_CHANGED},\n\n    {TK_OPTION_STRING, \"-xscrollcommand\", \"xScrollCommand\", \"ScrollCommand\",\n\tNULL, offsetof(Treeview, tree.xscroll.scrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},\n    {TK_OPTION_STRING, \"-yscrollcommand\", \"yScrollCommand\", \"ScrollCommand\",\n\tNULL, offsetof(Treeview, tree.yscroll.scrollCmdObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},\n\n    WIDGET_TAKEFOCUS_TRUE,\n    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)\n};\n\n/*------------------------------------------------------------------------\n * +++ Utilities.\n */\ntypedef void (*HashEntryIterator)(void *hashValue);\n\nstatic void foreachHashEntry(Tcl_HashTable *ht, HashEntryIterator func)\n{\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);\n    while (entryPtr != NULL) {\n\tfunc(Tcl_GetHashValue(entryPtr));\n\tentryPtr = Tcl_NextHashEntry(&search);\n    }\n}\n\nstatic int CellSelectionClear(Treeview *tv)\n{\n    TreeItem *item;\n    int anyChange = 0;\n    for (item=tv->tree.root; item; item = NextPreorder(item)) {\n\tif (item->selObj != NULL) {\n\t    Tcl_DecrRefCount(item->selObj);\n\t    item->selObj = NULL;\n\t    anyChange = 1;\n\t}\n    }\n    return anyChange;\n}\n\n/* + unshareObj(objPtr) --\n *\tEnsure that a Tcl_Obj * has refcount 1 -- either return objPtr\n *\titself,\tor a duplicated copy.\n */\nstatic Tcl_Obj *unshareObj(Tcl_Obj *objPtr)\n{\n    if (Tcl_IsShared(objPtr)) {\n\tTcl_Obj *newObj = Tcl_DuplicateObj(objPtr);\n\tTcl_DecrRefCount(objPtr);\n\tTcl_IncrRefCount(newObj);\n\treturn newObj;\n    }\n    return objPtr;\n}\n\n/* DisplayLayout --\n *\tRebind, place, and draw a layout + object combination.\n */\nstatic void DisplayLayout(\n    Ttk_Layout layout, void *recordPtr, Ttk_State state, Ttk_Box b, Drawable d)\n{\n    Ttk_RebindSublayout(layout, recordPtr);\n    Ttk_PlaceLayout(layout, state, b);\n    Ttk_DrawLayout(layout, state, d);\n}\n\n/* DisplayLayoutTree --\n *\tLike DisplayLayout, but for the tree column.\n */\nstatic void DisplayLayoutTree(\n    Tk_Anchor imageAnchor, Tk_Anchor textAnchor,\n    Ttk_Layout layout, void *recordPtr, Ttk_State state, Ttk_Box b, Drawable d)\n{\n    Ttk_Element elem;\n    Ttk_RebindSublayout(layout, recordPtr);\n\n    elem = Ttk_FindElement(layout, \"image\");\n    if (elem != NULL) {\n\tTtk_AnchorElement(elem, imageAnchor);\n    }\n    elem = Ttk_FindElement(layout, \"text\");\n    if (elem != NULL) {\n\tTtk_AnchorElement(elem, textAnchor);\n    }\n    elem = Ttk_FindElement(layout, \"focus\");\n    if (elem != NULL) {\n\tTtk_AnchorElement(elem, textAnchor);\n    }\n\n    Ttk_PlaceLayout(layout, state, b);\n    Ttk_DrawLayout(layout, state, d);\n}\n\n/* + GetColumn --\n *\tLook up column by name or number.\n *\tReturns: pointer to column table entry, NULL if not found.\n *\tLeaves an error message in interp->result on error.\n */\nstatic TreeColumn *GetColumn(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj)\n{\n    Tcl_HashEntry *entryPtr;\n    Tcl_Size columnIndex;\n\n    /* Check for named column:\n     */\n    entryPtr = Tcl_FindHashEntry(\n\t    &tv->tree.columnNames, Tcl_GetString(columnIDObj));\n    if (entryPtr) {\n\treturn (TreeColumn *)Tcl_GetHashValue(entryPtr);\n    }\n\n    /* Check for index:\n     */\n    if (TkGetIntForIndex(columnIDObj, tv->tree.nColumns - 1, 1, &columnIndex) == TCL_OK) {\n\tif (columnIndex < 0 || columnIndex >= tv->tree.nColumns) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"Column index \\\"%s\\\" out of bounds\",\n\t\t    Tcl_GetString(columnIDObj)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"COLBOUND\", (char *)NULL);\n\t    return NULL;\n\t}\n\n\treturn tv->tree.columns + columnIndex;\n    }\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\"Invalid column index \\\"%s\\\"\", Tcl_GetString(columnIDObj)));\n    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"COLUMN\", (char *)NULL);\n    return NULL;\n}\n\n/* + FindColumn --\n *\tLook up column by name, number, or display index.\n */\nstatic TreeColumn *FindColumn(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj)\n{\n    Tcl_WideInt colno;\n\n    if (sscanf(Tcl_GetString(columnIDObj), \"#%\" TCL_LL_MODIFIER \"d\", &colno) == 1) {\n\t/* Display column specification, #n */\n\tif (colno >= 0 && colno < tv->tree.nDisplayColumns) {\n\t    return tv->tree.displayColumns[colno];\n\t}\n\t/* else */\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"Column %s out of range\", Tcl_GetString(columnIDObj)));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"COLUMN\", (char *)NULL);\n\treturn NULL;\n    }\n\n    return GetColumn(interp, tv, columnIDObj);\n}\n\n/* + FindItem --\n *\tLocates the item with the specified identifier in the tree.\n *\tIf there is no such item, leaves an error message in interp.\n */\nstatic TreeItem *FindItem(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *itemNameObj)\n{\n    const char *itemName = Tcl_GetString(itemNameObj);\n    Tcl_HashEntry *entryPtr =  Tcl_FindHashEntry(&tv->tree.items, itemName);\n\n    if (!entryPtr) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Item %s not found\", itemName));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"ITEM\", (char *)NULL);\n\treturn 0;\n    }\n    return (TreeItem *)Tcl_GetHashValue(entryPtr);\n}\n\n/* + GetItemListFromObj --\n *\tParse a Tcl_Obj * as a list of items.\n *\tReturns a NULL-terminated array of items; result must\n *\tbe Tcl_Free()d. On error, returns NULL and leaves an error\n *\tmessage in interp.\n */\n\nstatic TreeItem **GetItemListFromObj(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *objPtr)\n{\n    TreeItem **items;\n    Tcl_Obj **elements;\n    Tcl_Size i, nElements;\n\n    if (Tcl_ListObjGetElements(interp,objPtr,&nElements,&elements) != TCL_OK) {\n\treturn NULL;\n    }\n\n    items = (TreeItem **)Tcl_Alloc((nElements + 1)*sizeof(TreeItem*));\n    for (i = 0; i < nElements; ++i) {\n\titems[i] = FindItem(interp, tv, elements[i]);\n\tif (!items[i]) {\n\t    Tcl_Free(items);\n\t    return NULL;\n\t}\n    }\n    items[i] = NULL;\n    return items;\n}\n\n/* + ItemName --\n *\tReturns the item's ID.\n */\nstatic const char *ItemName(Treeview *tv, TreeItem *item)\n{\n    return (const char *)Tcl_GetHashKey(&tv->tree.items, item->entryPtr);\n}\n\n/* + ItemID --\n *\tReturns a fresh Tcl_Obj * (refcount 0) holding the\n *\titem identifier of the specified item.\n */\nstatic Tcl_Obj *ItemID(Treeview *tv, TreeItem *item)\n{\n    return Tcl_NewStringObj(ItemName(tv, item), -1);\n}\n\n/*------------------------------------------------------------------------\n * +++ Column configuration.\n */\n\n/* + TreeviewFreeColumns --\n *\tFree column data.\n */\nstatic void TreeviewFreeColumns(Treeview *tv)\n{\n    Tcl_Size i;\n\n    Tcl_DeleteHashTable(&tv->tree.columnNames);\n    Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS);\n\n    if (tv->tree.columns) {\n\tfor (i = 0; i < tv->tree.nColumns; ++i)\n\t    FreeColumn(tv->tree.columns + i);\n\tTcl_Free(tv->tree.columns);\n\ttv->tree.columns = 0;\n    }\n}\n\n/* + TreeviewInitColumns --\n *\tInitialize column data when -columns changes.\n *\tReturns: TCL_OK or TCL_ERROR;\n */\nstatic int TreeviewInitColumns(Tcl_Interp *interp, Treeview *tv)\n{\n    Tcl_Obj **columns;\n    Tcl_Size i, ncols;\n\n    if (Tcl_ListObjGetElements(\n\t    interp, tv->tree.columnsObj, &ncols, &columns) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Free old values:\n     */\n    TreeviewFreeColumns(tv);\n\n    /*\n     * Initialize columns array and columnNames hash table:\n     */\n    tv->tree.nColumns = ncols;\n    tv->tree.columns = (TreeColumn *)Tcl_Alloc(tv->tree.nColumns * sizeof(TreeColumn));\n\n    for (i = 0; i < ncols; ++i) {\n\tint isNew;\n\tTcl_Obj *columnName = Tcl_DuplicateObj(columns[i]);\n\n\tTcl_HashEntry *entryPtr = Tcl_CreateHashEntry(\n\t    &tv->tree.columnNames, Tcl_GetString(columnName), &isNew);\n\tTcl_SetHashValue(entryPtr, tv->tree.columns + i);\n\n\tInitColumn(tv->tree.columns + i);\n\tTk_InitOptions(\n\t    interp, tv->tree.columns + i,\n\t    tv->tree.columnOptionTable, tv->core.tkwin);\n\tTk_InitOptions(\n\t    interp, tv->tree.columns + i,\n\t    tv->tree.headingOptionTable, tv->core.tkwin);\n\tTcl_IncrRefCount(columnName);\n\ttv->tree.columns[i].idObj = columnName;\n    }\n\n    return TCL_OK;\n}\n\n/* + TreeviewInitDisplayColumns --\n *\tInitializes the 'displayColumns' array.\n *\n *\tNote that displayColumns[0] is always the tree column,\n *\teven when SHOW_TREE is not set.\n *\n * @@@ TODO: disallow duplicated columns\n */\nstatic int TreeviewInitDisplayColumns(Tcl_Interp *interp, Treeview *tv)\n{\n    Tcl_Obj **dcolumns;\n    Tcl_Size index, ndcols;\n    TreeColumn **displayColumns = 0;\n\n    if (Tcl_ListObjGetElements(interp,\n\t    tv->tree.displayColumnsObj, &ndcols, &dcolumns) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (!strcmp(Tcl_GetString(tv->tree.displayColumnsObj), \"#all\")) {\n\tndcols = tv->tree.nColumns;\n\tdisplayColumns = (TreeColumn **)Tcl_Alloc((ndcols+1) * sizeof(TreeColumn*));\n\tfor (index = 0; index < ndcols; ++index) {\n\t    displayColumns[index+1] = tv->tree.columns + index;\n\t}\n    } else {\n\tdisplayColumns = (TreeColumn **)Tcl_Alloc((ndcols+1) * sizeof(TreeColumn*));\n\tfor (index = 0; index < ndcols; ++index) {\n\t    displayColumns[index+1] = GetColumn(interp, tv, dcolumns[index]);\n\t    if (!displayColumns[index+1]) {\n\t\tTcl_Free(displayColumns);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n    displayColumns[0] = &tv->tree.column0;\n\n    if (tv->tree.displayColumns) {\n\tTcl_Free(tv->tree.displayColumns);\n    }\n    tv->tree.displayColumns = displayColumns;\n    tv->tree.nDisplayColumns = ndcols + 1;\n\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Resizing.\n *\tslack invariant: TreeWidth(tree) + slack = treeArea.width\n */\n\n#define FirstColumn(tv)  ((tv->tree.showFlags&SHOW_TREE) ? 0 : 1)\n\n/* + TreeWidth --\n *\tCompute the requested tree width from the sum of visible column widths.\n */\nstatic int TreeWidth(Treeview *tv)\n{\n    Tcl_Size i = FirstColumn(tv);\n    int width = 0;\n\n    tv->tree.titleWidth = 0;\n    while (i < tv->tree.nDisplayColumns) {\n\tif (i == tv->tree.nTitleColumns) {\n\t    tv->tree.titleWidth = width;\n\t}\n\twidth += tv->tree.displayColumns[i++]->width;\n    }\n    if (tv->tree.nTitleColumns >= tv->tree.nDisplayColumns) {\n\ttv->tree.titleWidth = width;\n    }\n    return width;\n}\n\n/* + RecomputeSlack --\n */\nstatic void RecomputeSlack(Treeview *tv)\n{\n    tv->tree.slack = tv->tree.treeArea.width - TreeWidth(tv);\n}\n\n/* + PickupSlack/DepositSlack --\n *\tWhen resizing columns, distribute extra space to 'slack' first,\n *\tand only adjust column widths if 'slack' goes to zero.\n *\tThat is, don't bother changing column widths if the tree\n *\tis already scrolled or short.\n */\nstatic int PickupSlack(Treeview *tv, int extra)\n{\n    int newSlack = tv->tree.slack + extra;\n\n    if ((newSlack < 0 && 0 <= tv->tree.slack)\n\t    || (newSlack > 0 && 0 >= tv->tree.slack)) {\n\ttv->tree.slack = 0;\n\treturn newSlack;\n    } else {\n\ttv->tree.slack = newSlack;\n\treturn 0;\n    }\n}\n\nstatic void DepositSlack(Treeview *tv, int extra)\n{\n    tv->tree.slack += extra;\n}\n\n/* + Stretch --\n *\tAdjust width of column by N pixels, down to minimum width.\n *\tReturns: #pixels actually moved.\n */\nstatic int Stretch(TreeColumn *c, int n)\n{\n    int newWidth = n + c->width;\n    if (newWidth < c->minWidth) {\n\tn = c->minWidth - c->width;\n\tc->width = c->minWidth;\n    } else {\n\tc->width = newWidth;\n    }\n    return n;\n}\n\n/* + ShoveLeft --\n *\tAdjust width of (stretchable) columns to the left by N pixels.\n *\tReturns: leftover slack.\n */\nstatic int ShoveLeft(Treeview *tv, Tcl_Size i, int n)\n{\n    Tcl_Size first = FirstColumn(tv);\n    while (n != 0 && i >= first) {\n\tTreeColumn *c = tv->tree.displayColumns[i];\n\tif (c->stretch) {\n\t    n -= Stretch(c, n);\n\t}\n\t--i;\n    }\n    return n;\n}\n\n/* + ShoveRight --\n *\tAdjust width of (stretchable) columns to the right by N pixels.\n *\tReturns: leftover slack.\n */\nstatic int ShoveRight(Treeview *tv, Tcl_Size i, int n)\n{\n    while (n != 0 && i < tv->tree.nDisplayColumns) {\n\tTreeColumn *c = tv->tree.displayColumns[i];\n\tif (c->stretch) {\n\t    n -= Stretch(c, n);\n\t}\n\t++i;\n    }\n    return n;\n}\n\n/* + DistributeWidth --\n *\tDistribute n pixels evenly across all stretchable display columns.\n *\tReturns: leftover slack.\n * Notes:\n *\tThe \"((++w % m) < r)\" term is there so that the remainder r = n % m\n *\tis distributed round-robin.\n */\nstatic int DistributeWidth(Treeview *tv, int n)\n{\n    int w = TreeWidth(tv);\n    int m = 0;\n    Tcl_Size  i;\n    int d, r;\n\n    for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) {\n\tif (tv->tree.displayColumns[i]->stretch) {\n\t    ++m;\n\t}\n    }\n    if (m == 0) {\n\treturn n;\n    }\n\n    d = n / m;\n    r = n % m;\n    if (r < 0) { r += m; --d; }\n\n    for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) {\n\tTreeColumn *c = tv->tree.displayColumns[i];\n\tif (c->stretch) {\n\t    n -= Stretch(c, d + ((++w % m) < r));\n\t}\n    }\n    return n;\n}\n\n/* + ResizeColumns --\n *\tRecompute column widths based on available width.\n *\tPick up slack first;\n *\tDistribute the remainder evenly across stretchable columns;\n *\tIf any is still left over due to minwidth constraints, shove left.\n */\nstatic void ResizeColumns(Treeview *tv, int newWidth)\n{\n    int delta = newWidth - (TreeWidth(tv) + tv->tree.slack);\n    DepositSlack(tv,\n\tShoveLeft(tv, tv->tree.nDisplayColumns - 1,\n\t    DistributeWidth(tv, PickupSlack(tv, delta))));\n}\n\n/* + DragColumn --\n *\tMove the separator to the right of specified column,\n *\tadjusting other column widths as necessary.\n */\nstatic void DragColumn(Treeview *tv, Tcl_Size i, int delta)\n{\n    TreeColumn *c = tv->tree.displayColumns[i];\n    int dl = delta - ShoveLeft(tv, i-1, delta - Stretch(c, delta));\n    int dr = ShoveRight(tv, i+1, PickupSlack(tv, -dl));\n    DepositSlack(tv, dr);\n}\n\n/*------------------------------------------------------------------------\n * +++ Cells.\n */\n\ntypedef struct {\n    TreeItem *item;\n    TreeColumn *column;\n    Tcl_Obj *colObj;\n} TreeCell;\n\n/* + GetCellFromObj\n *\tGet Row and Column from a cell ID.\n */\nstatic int GetCellFromObj(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *obj,\n    bool displayColumnOnly, int *displayColumn,\n    TreeCell *cell)\n{\n    Tcl_Size nElements;\n    Tcl_Obj **elements;\n\n    if (Tcl_ListObjGetElements(interp, obj, &nElements, &elements) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (nElements != 2) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Cell id must be a list of two elements\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"CELL\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    /* Valid item/column in each pair? */\n    cell->item = FindItem(interp, tv, elements[0]);\n    if (!cell->item) {\n\treturn TCL_ERROR;\n    }\n    cell->column = FindColumn(interp, tv, elements[1]);\n    if (!cell->column) {\n\treturn TCL_ERROR;\n    }\n    /* colObj is short lived and do not keep a reference counted */\n    cell->colObj = elements[1];\n    if (displayColumnOnly) {\n\tTcl_Size i = FirstColumn(tv);\n\twhile (i < tv->tree.nDisplayColumns) {\n\t    if (tv->tree.displayColumns[i] == cell->column) {\n\t\tbreak;\n\t    }\n\t    ++i;\n\t}\n\tif (i == tv->tree.nDisplayColumns) { /* specified column unviewable */\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Cell id must be in a visible column\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"CELL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (displayColumn != NULL) {\n\t    *displayColumn = i;\n\t}\n    }\n    return TCL_OK;\n}\n\n/* + GetCellListFromObj --\n *\tParse a Tcl_Obj * as a list of cells.\n *\tReturns an array of cells; result must be Tcl_Free()d.\n *      On error, returns NULL and leaves an error\n *\tmessage in interp.\n */\n\nstatic TreeCell *GetCellListFromObj(\n\tTcl_Interp *interp, Treeview *tv, Tcl_Obj *objPtr, Tcl_Size *nCells)\n{\n    TreeCell *cells;\n    TreeCell cell;\n    Tcl_Obj **elements;\n    Tcl_Obj *oneCell;\n    Tcl_Size i, n;\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &n, &elements) != TCL_OK) {\n\treturn NULL;\n    }\n\n    /* A two element list might be a single cell */\n    if (n == 2) {\n\tif (GetCellFromObj(interp, tv, objPtr, false, NULL, &cell)\n\t\t== TCL_OK) {\n\t    n = 1;\n\t    oneCell = objPtr;\n\t    elements = &oneCell;\n\t} else {\n\t    Tcl_ResetResult(interp);\n\t}\n    }\n\n    cells = (TreeCell *)Tcl_Alloc(n * sizeof(TreeCell));\n    for (i = 0; i < n; ++i) {\n\tif (GetCellFromObj(interp, tv, elements[i], false, NULL, &cells[i]) != TCL_OK) {\n\t    Tcl_Free(cells);\n\t    return NULL;\n\t}\n    }\n\n    if (nCells) {\n\t*nCells = n;\n    }\n    return cells;\n}\n\n/*------------------------------------------------------------------------\n * +++ Event handlers.\n */\n\nstatic TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/\nstatic Tcl_Size IdentifyDisplayColumn(Treeview *tv, int x, int *x1); /*forward*/\n\nstatic const unsigned long TreeviewBindEventMask =\n      KeyPressMask|KeyReleaseMask\n    | ButtonPressMask|ButtonReleaseMask\n    | PointerMotionMask|ButtonMotionMask\n    | VirtualEventMask\n    ;\n\nstatic void TreeviewBindEventProc(void *clientData, XEvent *event)\n{\n    Treeview *tv = (Treeview *)clientData;\n    TreeItem *item = NULL;\n    Ttk_TagSet tagset;\n    int unused;\n    Tcl_Size colno = TCL_INDEX_NONE;\n    TreeColumn *column = NULL;\n\n    /*\n     * Figure out where to deliver the event.\n     */\n    switch (event->type)\n    {\n\tcase KeyPress:\n\tcase KeyRelease:\n\tcase VirtualEvent:\n\t    item = tv->tree.focus;\n\t    break;\n\tcase ButtonPress:\n\tcase ButtonRelease:\n\t    item = IdentifyItem(tv, event->xbutton.y);\n\t    colno = IdentifyDisplayColumn(tv, event->xbutton.x, &unused);\n\t    break;\n\tcase MotionNotify:\n\t    item = IdentifyItem(tv, event->xmotion.y);\n\t    colno = IdentifyDisplayColumn(tv, event->xmotion.x, &unused);\n\t    break;\n\tdefault:\n\t    break;\n    }\n\n    if (!item) {\n\treturn;\n    }\n\n    /* ASSERT: Ttk_GetTagSetFromObj succeeds.\n     * NB: must use a local copy of the tagset,\n     * in case a binding script stomps on -tags.\n     */\n    tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, item->tagsObj);\n\n    /*\n     * Pick up any cell tags.\n     */\n    if (colno >= 0) {\n\tcolumn = tv->tree.displayColumns[colno];\n\tif (column == &tv->tree.column0) {\n\t    colno = 0;\n\t} else {\n\t    colno = column - tv->tree.columns + 1;\n\t}\n\tif (colno < item->nTagSets) {\n\t    if (item->cellTagSets[colno] != NULL) {\n\t\tTtk_TagSetAddSet(tagset, item->cellTagSets[colno]);\n\t    }\n\t}\n    }\n\n    /*\n     * Fire binding:\n     */\n    Tcl_Preserve(clientData);\n    Tk_BindEvent(tv->tree.bindingTable, event, tv->core.tkwin,\n\t    tagset->nTags, (void **)tagset->tags);\n    Tcl_Release(clientData);\n\n    Ttk_FreeTagSet(tagset);\n}\n\n/*------------------------------------------------------------------------\n * +++ Initialization and cleanup.\n */\n\nstatic void TreeviewInitialize(Tcl_Interp *interp, void *recordPtr)\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    int unused;\n\n    tv->tree.itemOptionTable =\n\tTk_CreateOptionTable(interp, ItemOptionSpecs);\n    tv->tree.columnOptionTable =\n\tTk_CreateOptionTable(interp, ColumnOptionSpecs);\n    tv->tree.headingOptionTable =\n\tTk_CreateOptionTable(interp, HeadingOptionSpecs);\n    tv->tree.displayOptionTable =\n\tTk_CreateOptionTable(interp, DisplayOptionSpecs);\n\n    tv->tree.tagTable = Ttk_CreateTagTable(\n\tinterp, tv->core.tkwin, TagOptionSpecs, sizeof(DisplayItem));\n    tv->tree.bindingTable = Tk_CreateBindingTable(interp);\n    Tk_CreateEventHandler(tv->core.tkwin,\n\tTreeviewBindEventMask, TreeviewBindEventProc, tv);\n\n    tv->tree.itemLayout\n\t= tv->tree.cellLayout\n\t= tv->tree.headingLayout\n\t= tv->tree.rowLayout\n\t= tv->tree.separatorLayout\n\t= 0;\n    tv->tree.headingHeight = tv->tree.rowHeight = 0;\n    tv->tree.colSeparatorWidth = 1;\n    tv->tree.indent = DEFAULT_INDENT;\n\n    Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS);\n    tv->tree.nColumns = tv->tree.nDisplayColumns = 0;\n    tv->tree.nTitleColumns = 0;\n    tv->tree.nTitleItems = 0;\n    tv->tree.titleWidth = 0;\n    tv->tree.titleRows = 0;\n    tv->tree.totalRows = 0;\n    tv->tree.rowPosNeedsUpdate = 1;\n    tv->tree.striped = 0;\n    tv->tree.columns = NULL;\n    tv->tree.displayColumns = NULL;\n    tv->tree.showFlags = ~0;\n\n    InitColumn(&tv->tree.column0);\n    tv->tree.column0.idObj = Tcl_NewStringObj(\"#0\", 2);\n    Tcl_IncrRefCount(tv->tree.column0.idObj);\n    Tk_InitOptions(\n\tinterp, &tv->tree.column0,\n\ttv->tree.columnOptionTable, tv->core.tkwin);\n    Tk_InitOptions(\n\tinterp, &tv->tree.column0,\n\ttv->tree.headingOptionTable, tv->core.tkwin);\n\n    Tcl_InitHashTable(&tv->tree.items, TCL_STRING_KEYS);\n    tv->tree.serial = 0;\n\n    tv->tree.focus = tv->tree.endPtr = 0;\n\n    /* Create root item \"\":\n     */\n    tv->tree.root = NewItem();\n    Tk_InitOptions(interp, tv->tree.root,\n\ttv->tree.itemOptionTable, tv->core.tkwin);\n    tv->tree.root->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);\n    tv->tree.root->entryPtr = Tcl_CreateHashEntry(&tv->tree.items, \"\", &unused);\n    Tcl_SetHashValue(tv->tree.root->entryPtr, tv->tree.root);\n\n    /* Scroll handles:\n     */\n    tv->tree.xscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.xscroll);\n    tv->tree.yscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.yscroll);\n\n    /* Size parameters:\n     */\n    tv->tree.treeArea = tv->tree.headingArea = Ttk_MakeBox(0,0,0,0);\n    tv->tree.slack = 0;\n}\n\nstatic void TreeviewCleanup(void *recordPtr)\n{\n    Treeview *tv = (Treeview *)recordPtr;\n\n    Tk_DeleteEventHandler(tv->core.tkwin,\n\t    TreeviewBindEventMask,  TreeviewBindEventProc, tv);\n    Tk_DeleteBindingTable(tv->tree.bindingTable);\n    Ttk_DeleteTagTable(tv->tree.tagTable);\n\n    if (tv->tree.itemLayout) Ttk_FreeLayout(tv->tree.itemLayout);\n    if (tv->tree.cellLayout) Ttk_FreeLayout(tv->tree.cellLayout);\n    if (tv->tree.headingLayout) Ttk_FreeLayout(tv->tree.headingLayout);\n    if (tv->tree.rowLayout) Ttk_FreeLayout(tv->tree.rowLayout);\n    if (tv->tree.separatorLayout) Ttk_FreeLayout(tv->tree.separatorLayout);\n\n    FreeColumn(&tv->tree.column0);\n    TreeviewFreeColumns(tv);\n\n    if (tv->tree.displayColumns) {\n\tTcl_Free(tv->tree.displayColumns);\n    }\n\n    foreachHashEntry(&tv->tree.items, FreeItemCB);\n    Tcl_DeleteHashTable(&tv->tree.items);\n\n    TtkFreeScrollHandle(tv->tree.xscrollHandle);\n    TtkFreeScrollHandle(tv->tree.yscrollHandle);\n}\n\n/* + TreeviewConfigure --\n *\tConfiguration widget hook.\n *\n *\tBUG: If user sets -columns and -displaycolumns, but -displaycolumns\n *\thas an error, the widget is left in an inconsistent state.\n */\nstatic int\nTreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask)\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    unsigned showFlags = tv->tree.showFlags;\n\n    if (mask & COLUMNS_CHANGED) {\n\tif (TreeviewInitColumns(interp, tv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tmask |= DCOLUMNS_CHANGED;\n    }\n    if (mask & DCOLUMNS_CHANGED) {\n\tif (TreeviewInitDisplayColumns(interp, tv) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (mask & COLUMNS_CHANGED) {\n\tCellSelectionClear(tv);\n    }\n    if (tv->tree.nTitleColumns < 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"\\\"#%\" TCL_SIZE_MODIFIER \"d\\\" is out of range\",\n\t\ttv->tree.nTitleColumns));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"TITLECOLUMNS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (tv->tree.nTitleItems < 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"\\\"%\" TCL_SIZE_MODIFIER \"d\\\" is out of range\",\n\t\ttv->tree.nTitleItems));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"TITLEITEMS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (mask & SCROLLCMD_CHANGED) {\n\tTtkScrollbarUpdateRequired(tv->tree.xscrollHandle);\n\tTtkScrollbarUpdateRequired(tv->tree.yscrollHandle);\n    }\n    if ((mask & SHOW_CHANGED)\n\t    && GetEnumSetFromObj(\n\t\t    interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    tv->tree.rowPosNeedsUpdate = 1;\n    tv->tree.showFlags = showFlags;\n\n    if (mask & (SHOW_CHANGED | DCOLUMNS_CHANGED)) {\n\tRecomputeSlack(tv);\n    }\n    return TCL_OK;\n}\n\n/* + ConfigureItem --\n *\tSet item options.\n */\nstatic int ConfigureItem(\n    Tcl_Interp *interp, Treeview *tv, TreeItem *item,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tk_SavedOptions savedOptions;\n    int mask;\n    Ttk_ImageSpec *newImageSpec = NULL;\n    Ttk_TagSet newTagSet = NULL;\n\n    if (Tk_SetOptions(interp, item, tv->tree.itemOptionTable,\n\t\tobjc, objv, tv->core.tkwin, &savedOptions, &mask)\n\t\t!= TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    /* Make sure that -values is a valid list:\n     */\n    if (item->valuesObj) {\n\tTcl_Size unused;\n\tif (Tcl_ListObjLength(interp, item->valuesObj, &unused) != TCL_OK) {\n\t    goto error;\n\t}\n    }\n\n    /* Check -height\n     */\n    if (item->height < 1) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Invalid item height %d\", item->height));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"HEIGHT\", (char *)NULL);\n\tgoto error;\n    }\n\n    /* Check -image.\n     */\n    if ((mask & ITEM_OPTION_IMAGE_CHANGED) && item->imageObj) {\n\tnewImageSpec = TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj);\n\tif (!newImageSpec) {\n\t    goto error;\n\t}\n    }\n\n    /* Check -tags.\n     * Side effect: may create new tags.\n     */\n    if (mask & ITEM_OPTION_TAGS_CHANGED) {\n\tnewTagSet = Ttk_GetTagSetFromObj(\n\t\tinterp, tv->tree.tagTable, item->tagsObj);\n\tif (!newTagSet) {\n\t    goto error;\n\t}\n    }\n\n    /* Keep TTK_STATE_OPEN flag in sync with item->openObj.\n     * We use both a state flag and a Tcl_Obj* resource so elements\n     * can access the value in either way.\n     */\n    if (item->openObj) {\n\tint isOpen;\n\tif (Tcl_GetBooleanFromObj(interp, item->openObj, &isOpen) != TCL_OK) {\n\t    goto error;\n\t}\n\tif (isOpen) {\n\t    item->state |= TTK_STATE_OPEN;\n\t} else {\n\t    item->state &= ~TTK_STATE_OPEN;\n\t}\n    }\n\n    /* All OK.\n     */\n    Tk_FreeSavedOptions(&savedOptions);\n    if (mask & ITEM_OPTION_TAGS_CHANGED) {\n\tif (item->tagset) { Ttk_FreeTagSet(item->tagset); }\n\titem->tagset = newTagSet;\n    }\n    if (mask & ITEM_OPTION_IMAGE_CHANGED) {\n\tif (item->imagespec) { TtkFreeImageSpec(item->imagespec); }\n\titem->imagespec = newImageSpec;\n    }\n    tv->tree.rowPosNeedsUpdate = 1;\n    TtkRedisplayWidget(&tv->core);\n    return TCL_OK;\n\nerror:\n    Tk_RestoreSavedOptions(&savedOptions);\n    if (newTagSet) { Ttk_FreeTagSet(newTagSet); }\n    if (newImageSpec) { TtkFreeImageSpec(newImageSpec); }\n    return TCL_ERROR;\n}\n\n/* + ConfigureColumn --\n *\tSet column options.\n */\nstatic int ConfigureColumn(\n    Tcl_Interp *interp, Treeview *tv, TreeColumn *column,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tk_SavedOptions savedOptions;\n    int mask;\n\n    if (Tk_SetOptions(interp, column,\n\t    tv->tree.columnOptionTable, objc, objv, tv->core.tkwin,\n\t    &savedOptions,&mask) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    if (mask & READONLY_OPTION) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Attempt to change read-only option\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"READONLY\", (char *)NULL);\n\tgoto error;\n    }\n\n    /* Propagate column width changes to overall widget request width,\n     * but only if the widget is currently unmapped, in order to prevent\n     * geometry jumping during interactive column resize.\n     */\n    if (mask & GEOMETRY_CHANGED) {\n\tif (!Tk_IsMapped(tv->core.tkwin)) {\n\t    TtkResizeWidget(&tv->core);\n\t} else {\n\t    RecomputeSlack(tv);\n\t    ResizeColumns(tv, TreeWidth(tv));\n\t}\n    }\n    TtkRedisplayWidget(&tv->core);\n\n    Tk_FreeSavedOptions(&savedOptions);\n    return TCL_OK;\n\nerror:\n    Tk_RestoreSavedOptions(&savedOptions);\n    return TCL_ERROR;\n}\n\n/* + ConfigureHeading --\n *\tSet heading options.\n */\nstatic int ConfigureHeading(\n    Tcl_Interp *interp, Treeview *tv, TreeColumn *column,\n    Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Tk_SavedOptions savedOptions;\n    int mask;\n\n    if (Tk_SetOptions(interp, column,\n\t    tv->tree.headingOptionTable, objc, objv, tv->core.tkwin,\n\t    &savedOptions,&mask) != TCL_OK)\n    {\n\treturn TCL_ERROR;\n    }\n\n    /* @@@ testing ... */\n    if ((mask & STATE_CHANGED) && column->headingStateObj) {\n\tTtk_StateSpec stateSpec;\n\tif (Ttk_GetStateSpecFromObj(\n\t\tinterp, column->headingStateObj, &stateSpec) != TCL_OK)\n\t{\n\t    goto error;\n\t}\n\tcolumn->headingState = Ttk_ModifyState(column->headingState,&stateSpec);\n\tTcl_DecrRefCount(column->headingStateObj);\n\tcolumn->headingStateObj = Ttk_NewStateSpecObj(column->headingState,0);\n\tTcl_IncrRefCount(column->headingStateObj);\n    }\n\n    TtkRedisplayWidget(&tv->core);\n    Tk_FreeSavedOptions(&savedOptions);\n    return TCL_OK;\n\nerror:\n    Tk_RestoreSavedOptions(&savedOptions);\n    return TCL_ERROR;\n}\n\n/*------------------------------------------------------------------------\n * +++ Geometry routines.\n */\n\n/* + UpdatePositionItem --\n *\tUpdate position data for all visible items.\n */\nstatic void UpdatePositionItem(\n    Treeview *tv, TreeItem *item, int hidden,\n    int *rowPos, int *itemPos, int *visiblePos)\n{\n    TreeItem *child = item->children;\n    item->itemPos = *itemPos;\n    *itemPos += 1;\n\n    if (item->hidden) {\n\thidden = 1;\n    }\n\n    if (hidden) {\n\titem->rowPos = -1;\n\titem->visiblePos = -1;\n    } else {\n\titem->rowPos = *rowPos;\n\titem->visiblePos = *visiblePos;\n\tif (*visiblePos == tv->tree.nTitleItems) {\n\t    tv->tree.titleRows = *rowPos;\n\t}\n\n\t*visiblePos += 1;\n\t*rowPos += item->height;\n    }\n\n    if (!(item->state & TTK_STATE_OPEN)) {\n\thidden = 1;\n    }\n    while (child) {\n\tUpdatePositionItem(tv, child, hidden, rowPos, itemPos, visiblePos);\n\tchild = child->next;\n    }\n}\n\n/* + UpdatePositionTree --\n *\tUpdate position data for all visible items.\n */\nstatic void UpdatePositionTree(Treeview *tv)\n{\n    /* -1 for the invisible root */\n    int rowPos = -1, itemPos = -1, visiblePos = -1;\n    tv->tree.titleRows = 0;\n    UpdatePositionItem(tv, tv->tree.root, 0, &rowPos, &itemPos, &visiblePos);\n    tv->tree.totalRows = rowPos;\n    tv->tree.rowPosNeedsUpdate = 0;\n}\n\n/* + IdentifyItem --\n *\tLocate the item at the specified y position, if any.\n */\nstatic TreeItem *IdentifyItem(Treeview *tv, int y)\n{\n    TreeItem *item;\n    int rowHeight = tv->tree.rowHeight;\n    int ypos = tv->tree.treeArea.y;\n    int nextRow, row;\n    if (y < ypos) {\n\treturn NULL;\n    }\n    if (tv->tree.rowPosNeedsUpdate) {\n\tUpdatePositionTree(tv);\n    }\n    row = (y - ypos) / rowHeight;\n    if (row >= tv->tree.titleRows) {\n\trow += tv->tree.yscroll.first;\n    }\n    for (item = tv->tree.root->children; item; item = NextPreorder(item)) {\n\tnextRow = item->rowPos + item->height;\n\tif (item->rowPos <= row && row < nextRow) break;\n    }\n    return item;\n}\n\n/* + IdentifyDisplayColumn --\n *\tReturns the display column number at the specified x position,\n *\tor -1 if x is outside any columns.\n */\nstatic Tcl_Size IdentifyDisplayColumn(Treeview *tv, int x, int *x1)\n{\n    Tcl_Size colno = FirstColumn(tv);\n    int xpos = tv->tree.treeArea.x;\n    int scaledHALO = round(HALO * TkScalingLevel(tv->core.tkwin));\n\n    if (tv->tree.nTitleColumns <= colno) {\n\txpos -= tv->tree.xscroll.first;\n    }\n\n    while (colno < tv->tree.nDisplayColumns) {\n\tTreeColumn *column = tv->tree.displayColumns[colno];\n\tint next_xpos = xpos + column->width;\n\tif (xpos <= x && x <= next_xpos + scaledHALO) {\n\t    *x1 = next_xpos;\n\t    return colno;\n\t}\n\t++colno;\n\txpos = next_xpos;\n\tif (tv->tree.nTitleColumns == colno) {\n\t    xpos -= tv->tree.xscroll.first;\n\t}\n    }\n\n    return TCL_INDEX_NONE;\n}\n\n/* + ItemDepth -- return the depth of a tree item.\n *\tThe depth of an item is equal to the number of proper ancestors,\n *\tnot counting the root node.\n */\nstatic int ItemDepth(TreeItem *item)\n{\n    int depth = 0;\n    while (item->parent) {\n\t++depth;\n\titem = item->parent;\n    }\n    return depth-1;\n}\n\n/* + DisplayRow --\n *\tReturns the position row has on screen, or -1 if off-screen.\n */\nstatic int DisplayRow(int row, Treeview *tv)\n{\n    int visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight\n\t    - tv->tree.titleRows;\n    if (row < tv->tree.titleRows) {\n\treturn row;\n    }\n    row -= tv->tree.titleRows;\n    if (row < tv->tree.yscroll.first\n\t    || row > tv->tree.yscroll.first + visibleRows) {\n\t/* not viewable, or off-screen */\n\treturn -1;\n    }\n    return row - tv->tree.yscroll.first + tv->tree.titleRows;\n}\n\n/* Is an item detached? The root is never detached. */\nstatic int IsDetached(Treeview* tv, TreeItem* item)\n{\n    return item->next == NULL && item->prev == NULL &&\n\titem->parent == NULL && item != tv->tree.root;\n}\n\n/* Is an item or one of its ancestors detached? */\nstatic int IsItemOrAncestorDetached(Treeview* tv, TreeItem* item)\n{\n    TreeItem *parent;\n\n    for (parent = item; parent; parent = parent->parent) {\n\tif (IsDetached(tv, parent)) {\n\t    return 1;\n\t}\n    }\n    return 0;\n}\n\n/* + BoundingBox --\n *\tCompute the parcel of the specified column of the specified item,\n *\t(or the entire item if column is NULL)\n *\tReturns: 0 if item or column is not viewable, 1 otherwise.\n */\nstatic int BoundingBox(\n    Treeview *tv,\t\t/* treeview widget */\n    TreeItem *item,\t\t/* desired item */\n    TreeColumn *column,\t\t/* desired column */\n    Ttk_Box *bbox_rtn)\t\t/* bounding box of item */\n{\n    int dispRow;\n    Ttk_Box bbox = tv->tree.treeArea;\n\n    /* Make sure the scroll information is current before use */\n    TtkUpdateScrollInfo(tv->tree.xscrollHandle);\n    TtkUpdateScrollInfo(tv->tree.yscrollHandle);\n\n    if (tv->tree.rowPosNeedsUpdate) {\n\tUpdatePositionTree(tv);\n    }\n    dispRow = DisplayRow(item->rowPos, tv);\n    if (dispRow < 0) {\n\t/* not viewable, or off-screen */\n\treturn 0;\n    }\n    if (IsItemOrAncestorDetached(tv, item)) {\n\treturn 0;\n    }\n\n    bbox.y += dispRow * tv->tree.rowHeight;\n    bbox.height = tv->tree.rowHeight * item->height;\n\n    bbox.x -= tv->tree.xscroll.first;\n    bbox.width = TreeWidth(tv);\n\n    if (column) {\n\tint xpos = 0;\n\tTcl_Size i = FirstColumn(tv);\n\twhile (i < tv->tree.nDisplayColumns) {\n\t    if (tv->tree.displayColumns[i] == column) {\n\t\tbreak;\n\t    }\n\t    xpos += tv->tree.displayColumns[i]->width;\n\t    ++i;\n\t}\n\tif (i == tv->tree.nDisplayColumns) { /* specified column unviewable */\n\t    return 0;\n\t}\n\tbbox.x += xpos;\n\tbbox.width = column->width;\n\n\tif (i < tv->tree.nTitleColumns) {\n\t    /* Unscrollable column, remove scroll shift */\n\t    bbox.x += tv->tree.xscroll.first;\n\t}\n\n\t/* Account for indentation in tree column:\n\t */\n\tif (column == &tv->tree.column0) {\n\t    int indent = tv->tree.indent * ItemDepth(item);\n\t    bbox.x += indent;\n\t    bbox.width -= indent;\n\t}\n    }\n    *bbox_rtn = bbox;\n    return 1;\n}\n\n/* + IdentifyRegion --\n */\n\ntypedef enum {\n    REGION_NOTHING = 0,\n    REGION_HEADING,\n    REGION_SEPARATOR,\n    REGION_TREE,\n    REGION_CELL\n} TreeRegion;\n\nstatic const char *const regionStrings[] = {\n    \"nothing\", \"heading\", \"separator\", \"tree\", \"cell\", 0\n};\n\nstatic TreeRegion IdentifyRegion(Treeview *tv, int x, int y)\n{\n    int x1 = 0;\n    Tcl_Size colno = IdentifyDisplayColumn(tv, x, &x1);\n    int scaledHALO = round(HALO * TkScalingLevel(tv->core.tkwin));\n\n    if (Ttk_BoxContains(tv->tree.headingArea, x, y)) {\n\tif (colno < 0) {\n\t    return REGION_NOTHING;\n\t} else if (-scaledHALO <= x1 - x  && x1 - x <= scaledHALO) {\n\t    return REGION_SEPARATOR;\n\t} else {\n\t    return REGION_HEADING;\n\t}\n    } else if (Ttk_BoxContains(tv->tree.treeArea, x, y)) {\n\tTreeItem *item = IdentifyItem(tv, y);\n\tif (item && colno > 0) {\n\t    return REGION_CELL;\n\t} else if (item) {\n\t    return REGION_TREE;\n\t}\n    }\n    return REGION_NOTHING;\n}\n\n/*------------------------------------------------------------------------\n * +++ Display routines.\n */\n\n/* + GetSublayout --\n *\tUtility routine; acquires a sublayout for items, cells, etc.\n */\nstatic Ttk_Layout GetSublayout(\n    Tcl_Interp *interp,\n    Ttk_Theme themePtr,\n    Ttk_Layout parentLayout,\n    const char *layoutName,\n    Tk_OptionTable optionTable,\n    Ttk_Layout *layoutPtr)\n{\n    Ttk_Layout newLayout = Ttk_CreateSublayout(\n\t    interp, themePtr, parentLayout, layoutName, optionTable);\n\n    if (newLayout) {\n\tif (*layoutPtr) {\n\t    Ttk_FreeLayout(*layoutPtr);\n\t}\n\t*layoutPtr = newLayout;\n    }\n    return newLayout;\n}\n\n/* + TreeviewGetLayout --\n *\tGetLayout() widget hook.\n */\nstatic Ttk_Layout TreeviewGetLayout(\n    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_Layout treeLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);\n    Tcl_Obj *objPtr;\n    int unused, cellHeight;\n    DisplayItem displayItem;\n    Ttk_Style style;\n\n    if (!(\n\ttreeLayout\n     && GetSublayout(interp, themePtr, treeLayout, \".Item\",\n\t    tv->tree.displayOptionTable, &tv->tree.itemLayout)\n     && GetSublayout(interp, themePtr, treeLayout, \".Cell\",\n\t    tv->tree.displayOptionTable, &tv->tree.cellLayout)\n     && GetSublayout(interp, themePtr, treeLayout, \".Heading\",\n\t    tv->tree.headingOptionTable, &tv->tree.headingLayout)\n     && GetSublayout(interp, themePtr, treeLayout, \".Row\",\n\t    tv->tree.displayOptionTable, &tv->tree.rowLayout)\n     && GetSublayout(interp, themePtr, treeLayout, \".Separator\",\n\t    tv->tree.displayOptionTable, &tv->tree.separatorLayout)\n    )) {\n\treturn 0;\n    }\n\n    /* Compute heading height.\n     */\n    Ttk_RebindSublayout(tv->tree.headingLayout, &tv->tree.column0);\n    Ttk_LayoutSize(tv->tree.headingLayout, 0, &unused, &tv->tree.headingHeight);\n\n    /* Get row height from style, or compute it to fit Item and Cell.\n     * Pick up default font from the Treeview style.\n     */\n    style = Ttk_LayoutStyle(treeLayout);\n    Ttk_TagSetDefaults(tv->tree.tagTable, style, &displayItem);\n\n    Ttk_RebindSublayout(tv->tree.itemLayout, &displayItem);\n    Ttk_LayoutSize(tv->tree.itemLayout, 0, &unused, &tv->tree.rowHeight);\n\n    Ttk_RebindSublayout(tv->tree.cellLayout, &displayItem);\n    Ttk_LayoutSize(tv->tree.cellLayout, 0, &unused, &cellHeight);\n\n    if (cellHeight > tv->tree.rowHeight) {\n\ttv->tree.rowHeight = cellHeight;\n    }\n\n    if ((objPtr = Ttk_QueryOption(treeLayout, \"-rowheight\", 0))) {\n\t(void)Tk_GetPixelsFromObj(NULL, tv->core.tkwin, objPtr, &tv->tree.rowHeight);\n    }\n    if (tv->tree.rowHeight < 1) {\n\ttv->tree.rowHeight = 1;\n    }\n\n    if ((objPtr = Ttk_QueryOption(treeLayout, \"-columnseparatorwidth\", 0))) {\n\t(void)Tk_GetPixelsFromObj(NULL, tv->core.tkwin, objPtr, &tv->tree.colSeparatorWidth);\n    }\n\n    /* Get item indent from style:\n     */\n    tv->tree.indent = DEFAULT_INDENT;\n    if ((objPtr = Ttk_QueryOption(treeLayout, \"-indent\", 0))) {\n\t(void)Tk_GetPixelsFromObj(NULL, tv->core.tkwin, objPtr, &tv->tree.indent);\n    }\n\n    return treeLayout;\n}\n\n/* + TreeviewDoLayout --\n *\tDoLayout() widget hook.  Computes widget layout.\n *\n * Side effects:\n *\tComputes headingArea and treeArea.\n *\tComputes subtree height.\n *\tInvokes scroll callbacks.\n */\nstatic void TreeviewDoLayout(void *clientData)\n{\n    Treeview *tv = (Treeview *)clientData;\n    int visibleRows;\n    int first, last, total;\n\n    Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin));\n    tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, \"treearea\");\n\n    ResizeColumns(tv, tv->tree.treeArea.width);\n\n    first = tv->tree.xscroll.first;\n    last = first + tv->tree.treeArea.width - tv->tree.titleWidth;\n    total = TreeWidth(tv) - tv->tree.titleWidth;\n    TtkScrolled(tv->tree.xscrollHandle, first, last, total);\n\n    if (tv->tree.showFlags & SHOW_HEADINGS) {\n\ttv->tree.headingArea = Ttk_PackBox(\n\t    &tv->tree.treeArea, 1, tv->tree.headingHeight, TTK_SIDE_TOP);\n    } else {\n\ttv->tree.headingArea = Ttk_MakeBox(0,0,0,0);\n    }\n\n    visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight;\n    tv->tree.root->state |= TTK_STATE_OPEN;\n    UpdatePositionTree(tv);\n    first = tv->tree.yscroll.first;\n    last = tv->tree.yscroll.first + visibleRows - tv->tree.titleRows;\n    total = tv->tree.totalRows - tv->tree.titleRows;\n    TtkScrolled(tv->tree.yscrollHandle, first, last, total);\n}\n\n/* + TreeviewSize --\n *\tSizeProc() widget hook.  Size is determined by\n *\t-height option and column widths.\n */\nstatic int TreeviewSize(void *clientData, int *widthPtr, int *heightPtr)\n{\n    Treeview *tv = (Treeview *)clientData;\n    int nRows, padHeight, padWidth;\n\n    Ttk_LayoutSize(tv->core.layout, tv->core.state, &padWidth, &padHeight);\n    Tcl_GetIntFromObj(NULL, tv->tree.heightObj, &nRows);\n\n    *widthPtr = padWidth + TreeWidth(tv);\n    *heightPtr = padHeight + tv->tree.rowHeight * nRows;\n\n    if (tv->tree.showFlags & SHOW_HEADINGS) {\n\t*heightPtr += tv->tree.headingHeight;\n    }\n\n    return 1;\n}\n\n/* + ItemState --\n *\tReturns the state of the specified item, based\n *\ton widget state, item state, and other information.\n */\nstatic Ttk_State ItemState(Treeview *tv, TreeItem *item)\n{\n    Ttk_State state = tv->core.state | item->state;\n    if (!item->children) {\n\tstate |= TTK_STATE_LEAF;\n    }\n    if (item != tv->tree.focus) {\n\tstate &= ~TTK_STATE_FOCUS;\n    }\n\n    if (!(tv->core.state & TTK_STATE_FOCUS) &&\n\t(item->state & TTK_STATE_SELECTED)) {\n\tstate |= TTK_STATE_BACKGROUND;\n    } else {\n\tstate &= ~TTK_STATE_BACKGROUND;\n    }\n    return state;\n}\n\n/* + DrawHeadings --\n *\tDraw tree headings.\n */\nstatic void DrawHeadings(Treeview *tv, Drawable d)\n{\n    int x0 = tv->tree.headingArea.x - tv->tree.xscroll.first;\n    const int y0 = tv->tree.headingArea.y;\n    const int h0 = tv->tree.headingArea.height;\n    Tcl_Size i = FirstColumn(tv);\n    int x = 0;\n\n    if (tv->tree.nTitleColumns > i) {\n\tx = tv->tree.titleWidth;\n\ti = tv->tree.nTitleColumns;\n    }\n\n    while (i < tv->tree.nDisplayColumns) {\n\tTreeColumn *column = tv->tree.displayColumns[i];\n\tTtk_Box parcel = Ttk_MakeBox(x0+x, y0, column->width, h0);\n\tif (x0+x+column->width > tv->tree.titleWidth) {\n\t    DisplayLayout(tv->tree.headingLayout,\n\t\t    column, column->headingState, parcel, d);\n\t}\n\tx += column->width;\n\t++i;\n    }\n\n    x0 = tv->tree.headingArea.x;\n    i = FirstColumn(tv);\n    x = 0;\n    while ((i < tv->tree.nTitleColumns) && (i < tv->tree.nDisplayColumns)) {\n\tTreeColumn *column = tv->tree.displayColumns[i];\n\tTtk_Box parcel = Ttk_MakeBox(x0+x, y0, column->width, h0);\n\tDisplayLayout(tv->tree.headingLayout,\n\t    column, column->headingState, parcel, d);\n\tx += column->width;\n\t++i;\n    }\n}\n\n/* + DrawSeparators --\n *\tDraw separators between columns\n */\nstatic void DrawSeparators(Treeview *tv, Drawable d)\n{\n    const int y0 = tv->tree.treeArea.y;\n    const int h0 = tv->tree.treeArea.height;\n    DisplayItem displayItem;\n    Ttk_Style style = Ttk_LayoutStyle(tv->tree.separatorLayout);\n    int x = tv->tree.treeArea.x;\n    Tcl_Size i;\n\n    Ttk_TagSetDefaults(tv->tree.tagTable, style, &displayItem);\n\n    for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) {\n\tTreeColumn *column = tv->tree.displayColumns[i];\n\tTtk_Box parcel;\n\tint xDraw = x + column->width;\n\tx += column->width;\n\n\tif (!column->separator) continue;\n\n\tif (i >= tv->tree.nTitleColumns) {\n\t    xDraw -= tv->tree.xscroll.first;\n\t    if (xDraw < tv->tree.titleWidth) continue;\n\t}\n\n\tparcel = Ttk_MakeBox(xDraw - (tv->tree.colSeparatorWidth+1)/2, y0,\n\t\ttv->tree.colSeparatorWidth, h0);\n\tDisplayLayout(tv->tree.separatorLayout, &displayItem, 0, parcel, d);\n    }\n}\n\n/* + OverrideStriped --\n *\tEach level of settings might add stripedbackground, and it should\n *\toverride background if this is indeed on a striped item.\n *\tBy copying it between each level, and NULL-ing stripedBgObj,\n *\tit can be detected if the next level overrides it.\n */\n static void OverrideStriped(\n    Treeview *tv, TreeItem *item, DisplayItem *displayItem)\n{\n    int striped = item->visiblePos % 2 && tv->tree.striped;\n    if (striped && displayItem->stripedBgObj) {\n\tdisplayItem->backgroundObj = displayItem->stripedBgObj;\n\tdisplayItem->stripedBgObj = NULL;\n    }\n}\n\n/* + PrepareItem --\n *\tFill in a displayItem record.\n */\nstatic void PrepareItem(\n    Treeview *tv, TreeItem *item, DisplayItem *displayItem, Ttk_State state)\n{\n    Ttk_Style style = Ttk_LayoutStyle(tv->core.layout);\n\n    Ttk_TagSetDefaults(tv->tree.tagTable, style, displayItem);\n    OverrideStriped(tv, item, displayItem);\n    Ttk_TagSetValues(tv->tree.tagTable, item->tagset, displayItem);\n    OverrideStriped(tv, item, displayItem);\n    Ttk_TagSetApplyStyle(tv->tree.tagTable, style, state, displayItem);\n}\n\n/* Fill in data from item to temporary storage in columns. */\nstatic void PrepareCells(\n   Treeview *tv, TreeItem *item)\n{\n    Tcl_Size i, nValues = 0;\n    Tcl_Obj **values = NULL;\n    TreeColumn *column;\n\n    if (item->valuesObj) {\n\tTcl_ListObjGetElements(NULL, item->valuesObj, &nValues, &values);\n    }\n    for (i = 0; i < tv->tree.nColumns; ++i) {\n\ttv->tree.columns[i].data = (i < nValues) ? values[i] : 0;\n\ttv->tree.columns[i].selected = 0;\n\ttv->tree.columns[i].tagset = NULL;\n    }\n    tv->tree.column0.data = NULL;\n    tv->tree.column0.selected = 0;\n    tv->tree.column0.tagset = NULL;\n\n    if (item->selObj != NULL) {\n\tTcl_ListObjGetElements(NULL, item->selObj, &nValues, &values);\n\tfor (i = 0; i < nValues; ++i) {\n\t    column = FindColumn(NULL, tv, values[i]);\n\t    /* Just in case. It should not be possible for column to be NULL */\n\t    if (column != NULL) {\n\t\tcolumn->selected = 1;\n\t    }\n\t}\n    }\n    if (item->nTagSets > 0) {\n\ttv->tree.column0.tagset = item->cellTagSets[0];\n    }\n    for (i = 1; i < item->nTagSets && i <= tv->tree.nColumns; ++i) {\n\ttv->tree.columns[i-1].tagset = item->cellTagSets[i];\n    }\n}\n\n/* + DrawCells --\n *\tDraw data cells for specified item.\n */\nstatic void DrawCells(\n    Treeview *tv, TreeItem *item,\n    DisplayItem *displayItem, DisplayItem *displayItemSel,\n    Drawable d, int x, int y, int title)\n{\n    Ttk_Layout layout = tv->tree.cellLayout;\n    Ttk_Style style = Ttk_LayoutStyle(tv->core.layout);\n    Ttk_State state = ItemState(tv, item);\n    short horizPad = round(4 * TkScalingLevel(tv->core.tkwin));\n    Ttk_Padding cellPadding = {horizPad, 0, horizPad, 0};\n    DisplayItem displayItemLocal;\n    DisplayItem displayItemCell, displayItemCellSel;\n    int rowHeight = tv->tree.rowHeight * item->height;\n    int xPad = 0, defaultPadding = 1;\n    Tcl_Size i;\n\n    /* Adjust if the tree column has a separator */\n    if (tv->tree.showFlags & SHOW_TREE && tv->tree.column0.separator) {\n\txPad = tv->tree.colSeparatorWidth/2;\n    }\n\n    /* An Item's image should not propagate to a Cell.\n       A Cell's image can only be set by cell tags. */\n    displayItemCell = *displayItem;\n    displayItemCellSel = *displayItemSel;\n    displayItemCell.imageObj = NULL;\n    displayItemCellSel.imageObj = NULL;\n    displayItemCell.imageAnchorObj = NULL;\n    displayItemCellSel.imageAnchorObj = NULL;\n\n    /* If explicit padding was asked for, skip default. */\n    if (Ttk_QueryStyle(Ttk_LayoutStyle(tv->tree.cellLayout), &displayItemCell,\n\t\t    tv->tree.displayOptionTable, \"-padding\", state) != NULL) {\n\tdefaultPadding = 0;\n    }\n\n    for (i = 1; i < tv->tree.nDisplayColumns; ++i) {\n\tTreeColumn *column = tv->tree.displayColumns[i];\n\tint parcelX = x + xPad;\n\tint parcelWidth = column->separator ?\n\t\tcolumn->width - tv->tree.colSeparatorWidth : column->width;\n\tTtk_Box parcel = Ttk_MakeBox(parcelX, y, parcelWidth, rowHeight);\n\tDisplayItem *displayItemUsed = &displayItemCell;\n\tTtk_State stateCell = state;\n\tTk_Anchor textAnchor, imageAnchor;\n\txPad = column->separator ? tv->tree.colSeparatorWidth/2 : 0;\n\n\tx += column->width;\n\tif (title  && i >= tv->tree.nTitleColumns) break;\n\tif (!title && i <  tv->tree.nTitleColumns) continue;\n\tif (!title && x <  tv->tree.titleWidth) continue;\n\n\tif (column->selected) {\n\t    displayItemUsed = &displayItemCellSel;\n\t    stateCell |= TTK_STATE_SELECTED;\n\t}\n\n\tif (column->tagset) {\n\t    displayItemLocal = *displayItemUsed;\n\t    displayItemUsed = &displayItemLocal;\n\t    Ttk_TagSetValues(tv->tree.tagTable, column->tagset,\n\t\t    displayItemUsed);\n\t    OverrideStriped(tv, item, displayItemUsed);\n\t    Ttk_TagSetApplyStyle(tv->tree.tagTable, style, stateCell,\n\t\t    displayItemUsed);\n\t}\n\n\tdisplayItemUsed->textObj = column->data;\n\tdisplayItemUsed->anchorObj = column->anchorObj;/* <<NOTE-ANCHOR>> */\n\tTk_GetAnchorFromObj(NULL, column->anchorObj, &textAnchor);\n\n\timageAnchor = DEFAULT_IMAGEANCHOR;\n\tif (displayItemUsed->imageAnchorObj) {\n\t    Tk_GetAnchorFromObj(NULL, displayItemUsed->imageAnchorObj,\n\t\t    &imageAnchor);\n\t}\n\t/* displayItem was used to draw the full item backgound.\n\t   Redraw cell background if needed. */\n\tif (displayItemUsed != &displayItemCell) {\n\t    DisplayLayout(tv->tree.rowLayout, displayItemUsed, stateCell,\n\t\t    parcel, d);\n\t}\n\n\tif (defaultPadding && displayItemUsed->paddingObj == NULL) {\n\t    /* If no explicit padding was asked for, add some default. */\n\t    parcel = Ttk_PadBox(parcel, cellPadding);\n\t}\n\n\tDisplayLayoutTree(imageAnchor, textAnchor,\n\t\tlayout, displayItemUsed, state, parcel, d);\n    }\n}\n\n/* + DrawItem --\n *\tDraw an item (row background, tree label, and cells).\n */\nstatic void DrawItem(\n    Treeview *tv, TreeItem *item, Drawable d, int depth)\n{\n    Ttk_Style style = Ttk_LayoutStyle(tv->core.layout);\n    Ttk_State state = ItemState(tv, item);\n    DisplayItem displayItem, displayItemSel, displayItemLocal;\n    int x, y, h, xTitle, dispRow, rowHeight;\n\n    dispRow = DisplayRow(item->rowPos, tv);\n    h = tv->tree.rowHeight * dispRow;\n    if (h >= tv->tree.treeArea.height) {\n\t/* The item is outside the visible area */\n\treturn;\n    }\n\n    rowHeight = tv->tree.rowHeight * item->height;\n    x = tv->tree.treeArea.x - tv->tree.xscroll.first;\n    xTitle = tv->tree.treeArea.x;\n    y = tv->tree.treeArea.y + h;\n\n    PrepareItem(tv, item, &displayItem, state);\n    PrepareItem(tv, item, &displayItemSel, state | TTK_STATE_SELECTED);\n\n    /* Draw row background:\n     */\n    {\n\tTtk_Box rowBox = Ttk_MakeBox(tv->tree.treeArea.x, y,\n\t\t\t\t     TreeWidth(tv), rowHeight);\n\tDisplayLayout(tv->tree.rowLayout, &displayItem, state, rowBox, d);\n    }\n\n    /* Make room for tree label:\n     */\n    if (tv->tree.showFlags & SHOW_TREE) {\n\tx += tv->tree.column0.width;\n    }\n\n    /* Draw data cells:\n     */\n    PrepareCells(tv, item);\n    DrawCells(tv, item, &displayItem, &displayItemSel, d, x, y, 0);\n\n    /* Draw row background for non-scrolled area:\n     */\n    if (tv->tree.nTitleColumns >= 1) {\n\tTtk_Box rowBox = Ttk_MakeBox(tv->tree.treeArea.x, y,\n\t\ttv->tree.titleWidth, rowHeight);\n\tDisplayLayout(tv->tree.rowLayout, &displayItem, state, rowBox, d);\n    }\n\n    /* Draw tree label:\n     */\n    x = tv->tree.treeArea.x - tv->tree.xscroll.first;\n    if (tv->tree.showFlags & SHOW_TREE) {\n\tTreeColumn *column = &tv->tree.column0;\n\tint indent = depth * tv->tree.indent;\n\tint colwidth = tv->tree.column0.width -\n\t\t(tv->tree.column0.separator ? tv->tree.colSeparatorWidth/2 : 0);\n\tint xTree = tv->tree.nTitleColumns >= 1 ? xTitle : x;\n\tTtk_Box parcel = Ttk_MakeBox(xTree, y, colwidth, rowHeight);\n\tDisplayItem *displayItemUsed = &displayItem;\n\tTtk_State stateCell = state;\n\tTk_Anchor textAnchor, imageAnchor = DEFAULT_IMAGEANCHOR;\n\tTtk_Padding cellPadding = {(short)indent, 0, 0, 0};\n\n\tif (column->selected) {\n\t    displayItemUsed = &displayItemSel;\n\t    stateCell |= TTK_STATE_SELECTED;\n\t}\n\n\tif (column->tagset) {\n\t    displayItemLocal = *displayItemUsed;\n\t    displayItemUsed = &displayItemLocal;\n\t    Ttk_TagSetValues(tv->tree.tagTable, column->tagset,\n\t\t    displayItemUsed);\n\t    OverrideStriped(tv, item, displayItemUsed);\n\t    Ttk_TagSetApplyStyle(tv->tree.tagTable, style, stateCell,\n\t\t    displayItemUsed);\n\t}\n\n\tdisplayItem.anchorObj = tv->tree.column0.anchorObj;\n\tTk_GetAnchorFromObj(NULL, column->anchorObj, &textAnchor);\n\tdisplayItemUsed->textObj = item->textObj;\n\t/* Item's image can be null, and may come from the tag */\n\tif (item->imageObj) {\n\t    displayItemUsed->imageObj = item->imageObj;\n\t}\n\tif (item->imageAnchorObj) {\n\t    displayItemUsed->imageAnchorObj = item->imageAnchorObj;\n\t}\n\tif (displayItemUsed->imageAnchorObj) {\n\t    Tk_GetAnchorFromObj(NULL, displayItemUsed->imageAnchorObj,\n\t\t    &imageAnchor);\n\t}\n\n\tif (displayItemUsed != &displayItem) {\n\t    DisplayLayout(tv->tree.rowLayout, displayItemUsed, stateCell,\n\t\t    parcel, d);\n\t}\n\n\tparcel = Ttk_PadBox(parcel, cellPadding);\n\tDisplayLayoutTree(imageAnchor, textAnchor,\n\t\ttv->tree.itemLayout, displayItemUsed, state, parcel, d);\n\txTitle += colwidth;\n    }\n\n    /* Draw non-scrolled data cells:\n     */\n    if (tv->tree.nTitleColumns > 1) {\n\tDrawCells(tv, item, &displayItem, &displayItemSel, d, xTitle, y, 1);\n    }\n}\n\n/* + DrawSubtree --\n *\tDraw an item and all of its (viewable) descendants.\n */\n\nstatic void DrawForest(\t/* forward */\n    Treeview *tv, TreeItem *item, Drawable d, int depth);\n\nstatic void DrawSubtree(\n    Treeview *tv, TreeItem *item, Drawable d, int depth)\n{\n    int dispRow = DisplayRow(item->rowPos, tv);\n    if (dispRow >= 0) {\n\tDrawItem(tv, item, d, depth);\n    }\n\n    if (item->state & TTK_STATE_OPEN) {\n\tDrawForest(tv, item->children, d, depth + 1);\n    }\n}\n\n/* + DrawForest --\n *\tDraw a sequence of items and their visible descendants.\n */\nstatic void DrawForest(\n    Treeview *tv, TreeItem *item, Drawable d, int depth)\n{\n    while (item) {\n\tDrawSubtree(tv, item, d, depth);\n\titem = item->next;\n    }\n}\n\n/* + DrawTreeArea --\n *     Draw the tree area including the headings, if any\n */\nstatic void DrawTreeArea(Treeview *tv, Drawable d) {\n    if (tv->tree.showFlags & SHOW_HEADINGS) {\n\tDrawHeadings(tv, d);\n    }\n    DrawForest(tv, tv->tree.root->children, d, 0);\n    DrawSeparators(tv, d);\n}\n\n/* + TreeviewDisplay --\n *\tDisplay() widget hook.  Draw the widget contents.\n */\nstatic void TreeviewDisplay(void *clientData, Drawable d)\n{\n    Treeview *tv = (Treeview *)clientData;\n    Tk_Window tkwin = tv->core.tkwin;\n    int width, height, winWidth, winHeight;\n\n    /* Draw the general layout of the treeview widget */\n    Ttk_DrawLayout(tv->core.layout, tv->core.state, d);\n\n    /* When the tree area does not fit in the available space, there is a\n     * risk that it will be drawn over other areas of the layout.\n     */\n\n    winWidth = Tk_Width(tkwin);\n    winHeight = Tk_Height(tkwin);\n    width = tv->tree.treeArea.width;\n    height = tv->tree.headingArea.height + tv->tree.treeArea.height;\n\n    if ((width == winWidth && height == winHeight)\n      || (tv->tree.treeArea.height % tv->tree.rowHeight == 0\n\t&& TreeWidth(tv) <= width)) {\n\t/* No protection is needed; either the tree area fills the entire\n\t * widget, or everything fits within the available area.\n\t */\n\tDrawTreeArea(tv, d);\n    } else {\n\t/* The tree area needs to be clipped\n\t */\n\n\tint x, y;\n\n\tx = tv->tree.treeArea.x;\n\tif (tv->tree.showFlags & SHOW_HEADINGS) {\n\t    y = tv->tree.headingArea.y;\n\t} else {\n\t    y = tv->tree.treeArea.y;\n\t}\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n\tDrawable p;\n\tXGCValues gcValues;\n\tGC gc;\n\n\t/* Create a temporary helper drawable */\n\tp = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t  winWidth, winHeight, Tk_Depth(tkwin));\n\n\t/* Get a graphics context for copying the drawable content */\n\tgcValues.function = GXcopy;\n\tgcValues.graphics_exposures = False;\n\tgc = Tk_GetGC(tkwin, GCFunction|GCGraphicsExposures, &gcValues);\n\n\t/* Copy the widget background into the helper */\n\tXCopyArea(Tk_Display(tkwin), d, p, gc, 0, 0,\n\t  (unsigned) winWidth, (unsigned) winHeight, 0, 0);\n\n\t/* Draw the tree onto the helper without regard for borders */\n\tDrawTreeArea(tv, p);\n\n\t/* Copy only the tree area inside the borders back */\n\tXCopyArea(Tk_Display(tkwin), p, d, gc, x, y,\n\t  (unsigned) width, (unsigned) height, x, y);\n\n\t/* Clean up the temporary resources */\n\tTk_FreePixmap(Tk_Display(tkwin), p);\n\tTk_FreeGC(Tk_Display(tkwin), gc);\n#else\n\tTtk_Theme currentTheme = Ttk_GetCurrentTheme(tv->core.interp);\n\tTtk_Theme aquaTheme = Ttk_GetTheme(tv->core.interp, \"aqua\");\n\tif (currentTheme == aquaTheme && [NSApp macOSVersion] > 100800) {\n\t    y -= 4;\n\t    height += 4;\n\t}\n\n\tTk_ClipDrawableToRect(Tk_Display(tkwin), d, x, y, width, height);\n\tDrawTreeArea(tv, d);\n\tTk_ClipDrawableToRect(Tk_Display(tkwin), d, 0, 0, -1, -1);\n#endif\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Utilities for widget commands\n */\n\n/* + InsertPosition --\n *\tLocate the previous sibling for [$tree insert].\n *\n *\tReturns a pointer to the item just before the specified index,\n *\tor 0 if the item is to be inserted at the beginning.\n */\nstatic TreeItem *InsertPosition(TreeItem *parent, int index)\n{\n    TreeItem *prev = 0, *next = parent->children;\n\n    while (next != 0 && index > 0) {\n\t--index;\n\tprev = next;\n\tnext = prev->next;\n    }\n\n    return prev;\n}\n\n/* + EndPosition --\n *\tLocate the last child of the specified node.\n *\n *\tTo avoid quadratic-time behavior in the common cases\n *\twhere the treeview is populated in breadth-first or\n *\tdepth-first order using [$tv insert $parent end ...],\n *\twe cache the result from the last call to EndPosition()\n *\tand start the search from there on a cache hit.\n *\n */\nstatic TreeItem *EndPosition(Treeview *tv, TreeItem *parent)\n{\n    TreeItem *endPtr = tv->tree.endPtr;\n\n    while (endPtr && endPtr->parent != parent) {\n\tendPtr = endPtr->parent;\n    }\n    if (!endPtr) {\n\tendPtr = parent->children;\n    }\n\n    if (endPtr) {\n\twhile (endPtr->next) {\n\t    endPtr = endPtr->next;\n\t}\n\ttv->tree.endPtr = endPtr;\n    }\n\n    return endPtr;\n}\n\n/* + AncestryCheck --\n *\tVerify that specified item is not an ancestor of the specified parent;\n *\treturns 1 if OK, 0 and leaves an error message in interp otherwise.\n */\nstatic int AncestryCheck(\n    Tcl_Interp *interp, Treeview *tv, TreeItem *item, TreeItem *parent)\n{\n    TreeItem *p = parent;\n    while (p) {\n\tif (p == item) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"Cannot insert %s as descendant of %s\",\n\t\t    ItemName(tv, item), ItemName(tv, parent)));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"ANCESTRY\", (char *)NULL);\n\t    return 0;\n\t}\n\tp = p->parent;\n    }\n    return 1;\n}\n\n/* + DeleteItems --\n *\tRemove an item and all of its descendants from the hash table\n *\tand detach them from the tree; returns a linked list (chained\n *\talong the ->next pointer) of deleted items.\n */\nstatic TreeItem *DeleteItems(TreeItem *item, TreeItem *delq)\n{\n    if (item->entryPtr) {\n\tDetachItem(item);\n\twhile (item->children) {\n\t    delq = DeleteItems(item->children, delq);\n\t}\n\tTcl_DeleteHashEntry(item->entryPtr);\n\titem->entryPtr = 0;\n\titem->next = delq;\n\tdelq = item;\n    } /* else -- item has already been unlinked */\n    return delq;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- item inquiry.\n */\n\n/* + $tv children $item ?newchildren? --\n *\tReturn the list of children associated with $item\n */\nstatic int TreeviewChildrenCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n    Tcl_Obj *result;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item ?newchildren?\");\n\treturn TCL_ERROR;\n    }\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tresult = Tcl_NewListObj(0,0);\n\tfor (item = item->children; item; item = item->next) {\n\t    Tcl_ListObjAppendElement(interp, result, ItemID(tv, item));\n\t}\n\tTcl_SetObjResult(interp, result);\n    } else {\n\tTreeItem **newChildren = GetItemListFromObj(interp, tv, objv[3]);\n\tTreeItem *child;\n\tint i;\n\n\tif (!newChildren) {\n\t    return TCL_ERROR;\n\t}\n\n\t/* Sanity-check:\n\t */\n\tfor (i = 0; newChildren[i]; ++i) {\n\t    if (!AncestryCheck(interp, tv, newChildren[i], item)) {\n\t\tTcl_Free(newChildren);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/* Detach old children:\n\t */\n\tchild = item->children;\n\twhile (child) {\n\t    TreeItem *next = child->next;\n\t    DetachItem(child);\n\t    child = next;\n\t}\n\n\t/* Detach new children from their current locations:\n\t */\n\tfor (i = 0; newChildren[i]; ++i) {\n\t    DetachItem(newChildren[i]);\n\t}\n\n\t/* Reinsert new children:\n\t * Note: it is not an error for an item to be listed more than once,\n\t * though it probably should be...\n\t */\n\tchild = 0;\n\tfor (i = 0; newChildren[i]; ++i) {\n\t    if (newChildren[i]->parent) {\n\t\t/* This is a duplicate element which has already been\n\t\t * inserted.  Ignore it.\n\t\t */\n\t\tcontinue;\n\t    }\n\t    InsertItem(item, child, newChildren[i]);\n\t    child = newChildren[i];\n\t}\n\n\tTcl_Free(newChildren);\n\ttv->tree.rowPosNeedsUpdate = 1;\n\tTtkRedisplayWidget(&tv->core);\n    }\n\n    return TCL_OK;\n}\n\n/* + $tv parent $item --\n *\tReturn the item ID of $item's parent.\n */\nstatic int TreeviewParentCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n\n    if (item->parent) {\n\tTcl_SetObjResult(interp, ItemID(tv, item->parent));\n    } else {\n\t/* This is the root item.  @@@ Return an error? */\n\tTcl_ResetResult(interp);\n    }\n\n    return TCL_OK;\n}\n\n/* + $tv next $item\n *\tReturn the ID of $item's next sibling.\n */\nstatic int TreeviewNextCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n\n    if (item->next) {\n\tTcl_SetObjResult(interp, ItemID(tv, item->next));\n    } /* else -- leave interp-result empty */\n\n    return TCL_OK;\n}\n\n/* + $tv prev $item\n *\tReturn the ID of $item's previous sibling.\n */\nstatic int TreeviewPrevCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n\n    if (item->prev) {\n\tTcl_SetObjResult(interp, ItemID(tv, item->prev));\n    } /* else -- leave interp-result empty */\n\n    return TCL_OK;\n}\n\n/* + $tv index $item --\n *\tReturn the index of $item within its parent.\n */\nstatic int TreeviewIndexCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n    Tcl_Size index = 0;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n\n    while (item->prev) {\n\t++index;\n\titem = item->prev;\n    }\n\n    Tcl_SetObjResult(interp, TkNewIndexObj(index));\n    return TCL_OK;\n}\n\n/* + $tv exists $itemid --\n *\tTest if the specified item id is present in the tree.\n */\nstatic int TreeviewExistsCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Tcl_HashEntry *entryPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"itemid\");\n\treturn TCL_ERROR;\n    }\n\n    entryPtr = Tcl_FindHashEntry(&tv->tree.items, Tcl_GetString(objv[2]));\n    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(entryPtr != 0));\n    return TCL_OK;\n}\n\n/* + $tv bbox $itemid ?$column? --\n *\tReturn bounding box [x y width height] of specified item.\n */\nstatic int TreeviewBBoxCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item = 0;\n    TreeColumn *column = 0;\n    Ttk_Box bbox;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"itemid ?column\");\n\treturn TCL_ERROR;\n    }\n\n    item = FindItem(interp, tv, objv[2]);\n    if (!item) {\n\treturn TCL_ERROR;\n    }\n    if (objc >= 4 && (column = FindColumn(interp,tv,objv[3])) == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    if (BoundingBox(tv, item, column, &bbox)) {\n\tTcl_SetObjResult(interp, Ttk_NewBoxObj(bbox));\n    }\n\n    return TCL_OK;\n}\n\n/* + $tv identify $x $y -- (obsolescent)\n *\tImplements the old, horrible, 2-argument form of [$tv identify].\n *\n * Returns: one of\n *\theading #n\n *\tcell itemid #n\n *\titem itemid element\n *\trow itemid\n */\nstatic int TreeviewHorribleIdentify(\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    Tcl_Obj *const objv[],\n    Treeview *tv)\n{\n    const char *what = \"nothing\", *detail = NULL;\n    TreeItem *item = 0;\n    Tcl_Obj *result;\n    Tcl_Size dColumnNumber;\n    char dcolbuf[32];\n    int x, y, x1;\n    int scaledHALO = round(HALO * TkScalingLevel(tv->core.tkwin));\n\n    /* ASSERT: objc == 4 */\n\n    if (Tk_GetPixelsFromObj(interp, tv->core.tkwin, objv[2], &x) != TCL_OK\n\t    || Tk_GetPixelsFromObj(interp, tv->core.tkwin, objv[3], &y) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    dColumnNumber = IdentifyDisplayColumn(tv, x, &x1);\n    if (dColumnNumber < 0) {\n\tgoto done;\n    }\n    snprintf(dcolbuf, sizeof(dcolbuf), \"#%\" TCL_SIZE_MODIFIER \"d\", dColumnNumber);\n\n    if (Ttk_BoxContains(tv->tree.headingArea,x,y)) {\n\tif (-scaledHALO <= x1 - x  && x1 - x <= scaledHALO) {\n\t    what = \"separator\";\n\t} else {\n\t    what = \"heading\";\n\t}\n\tdetail = dcolbuf;\n    } else if (Ttk_BoxContains(tv->tree.treeArea,x,y)) {\n\titem = IdentifyItem(tv, y);\n\tif (item && dColumnNumber > 0) {\n\t    what = \"cell\";\n\t    detail = dcolbuf;\n\t} else if (item) {\n\t    Ttk_Layout layout = tv->tree.itemLayout;\n\t    Ttk_Box itemBox;\n\t    DisplayItem displayItem;\n\t    Ttk_Element element;\n\t    Ttk_State state = ItemState(tv, item);\n\n\t    BoundingBox(tv, item, NULL, &itemBox);\n\t    PrepareItem(tv, item, &displayItem, state);\n\t    if (item->textObj) { displayItem.textObj = item->textObj; }\n\t    if (item->imageObj) { displayItem.imageObj = item->imageObj; }\n\t    Ttk_RebindSublayout(layout, &displayItem);\n\t    Ttk_PlaceLayout(layout, state, itemBox);\n\t    element = Ttk_IdentifyElement(layout, x, y);\n\n\t    if (element) {\n\t\twhat = \"item\";\n\t\tdetail = Ttk_ElementName(element);\n\t    } else {\n\t\twhat = \"row\";\n\t    }\n\t}\n    }\n\ndone:\n    result = Tcl_NewListObj(0,0);\n    Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(what, -1));\n    if (item) {\n\tTcl_ListObjAppendElement(NULL, result, ItemID(tv, item));\n    }\n    if (detail) {\n\tTcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(detail, -1));\n    }\n\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\n/* + $tv identify $component $x $y --\n *\tIdentify the component at position x,y.\n */\n\nstatic int TreeviewIdentifyCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    static const char *const submethodStrings[] =\n\t { \"region\", \"item\", \"column\", \"row\", \"element\", \"cell\", NULL };\n    enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT, I_CELL };\n\n    Treeview *tv = (Treeview *)recordPtr;\n    int submethod;\n    int x, y;\n\n    TreeRegion region;\n    Ttk_Box bbox;\n    TreeItem *item;\n    TreeColumn *column = 0;\n    Tcl_Size colno;\n    int x1;\n\n    if (objc == 4) {\t/* Old form */\n\treturn TreeviewHorribleIdentify(interp, objc, objv, tv);\n    } else if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"command x y\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], submethodStrings,\n\t\tsizeof(char *), \"command\", TCL_EXACT, &submethod) != TCL_OK\n\t|| Tk_GetPixelsFromObj(interp, tv->core.tkwin, objv[3], &x) != TCL_OK\n\t|| Tk_GetPixelsFromObj(interp, tv->core.tkwin, objv[4], &y) != TCL_OK\n    ) {\n\treturn TCL_ERROR;\n    }\n\n    /* Make sure the scroll information is current before use */\n    TtkUpdateScrollInfo(tv->tree.xscrollHandle);\n    TtkUpdateScrollInfo(tv->tree.yscrollHandle);\n\n    region = IdentifyRegion(tv, x, y);\n    item = IdentifyItem(tv, y);\n    colno = IdentifyDisplayColumn(tv, x, &x1);\n    column = (colno >= 0) ?  tv->tree.displayColumns[colno] : NULL;\n\n    switch (submethod)\n    {\n\tcase I_REGION :\n\t    Tcl_SetObjResult(interp,Tcl_NewStringObj(regionStrings[region],-1));\n\t    break;\n\n\tcase I_ITEM :\n\tcase I_ROW :\n\t    if (item) {\n\t\tTcl_SetObjResult(interp, ItemID(tv, item));\n\t    }\n\t    break;\n\n\tcase I_COLUMN :\n\t    if (colno >= 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"#%\" TCL_SIZE_MODIFIER \"d\", colno));\n\t    }\n\t    break;\n\n\tcase I_CELL :\n\t    if (item && colno >= 0) {\n\t\tTcl_Obj *elem[2];\n\t\telem[0] = ItemID(tv, item);\n\t\telem[1] = Tcl_ObjPrintf(\"#%\" TCL_SIZE_MODIFIER \"d\", colno);\n\t\tTcl_SetObjResult(interp, Tcl_NewListObj(2, elem));\n\t    }\n\t    break;\n\n\tcase I_ELEMENT :\n\t{\n\t    Ttk_Layout layout = 0;\n\t    DisplayItem displayItem;\n\t    Ttk_Element element;\n\t    Ttk_State state;\n\n\t    switch (region) {\n\t\tcase REGION_NOTHING:\n\t\t    layout = tv->core.layout;\n\t\t    return TCL_OK; /* @@@ NYI */\n\t\tcase REGION_HEADING:\n\t\tcase REGION_SEPARATOR:\n\t\t    layout = tv->tree.headingLayout;\n\t\t    return TCL_OK; /* @@@ NYI */\n\t\tcase REGION_TREE:\n\t\t    layout = tv->tree.itemLayout;\n\t\t    break;\n\t\tcase REGION_CELL:\n\t\t    layout = tv->tree.cellLayout;\n\t\t    break;\n\t    }\n\n\t    if (item == NULL) {\n\t\treturn TCL_OK;\n\t    }\n\t    if (!BoundingBox(tv, item, column, &bbox)) {\n\t\treturn TCL_OK;\n\t    }\n\t    state = ItemState(tv, item);\n\t    PrepareItem(tv, item, &displayItem, state);\n\t    if (item->textObj) { displayItem.textObj = item->textObj; }\n\t    if (item->imageObj) { displayItem.imageObj = item->imageObj; }\n\t    Ttk_RebindSublayout(layout, &displayItem);\n\t    Ttk_PlaceLayout(layout, state, bbox);\n\t    element = Ttk_IdentifyElement(layout, x, y);\n\n\t    if (element) {\n\t\tconst char *elementName = Ttk_ElementName(element);\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));\n\t    }\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- item and column configuration.\n */\n\n/* + $tv item $item ?options ....?\n *\tQuery or configure item options.\n */\nstatic int TreeviewItemCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item ?-option ?value??...\");\n\treturn TCL_ERROR;\n    }\n    if (!(item = FindItem(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\treturn TtkEnumerateOptions(interp, item, ItemOptionSpecs,\n\t    tv->tree.itemOptionTable,  tv->core.tkwin);\n    } else if (objc == 4) {\n\treturn TtkGetOptionValue(interp, item, objv[3],\n\t    tv->tree.itemOptionTable, tv->core.tkwin);\n    } else {\n\treturn ConfigureItem(interp, tv, item, objc-3, objv+3);\n    }\n}\n\n/* + $tv column column ?options ....?\n *\tColumn data accessor\n */\nstatic int TreeviewColumnCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeColumn *column;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"column -option value...\");\n\treturn TCL_ERROR;\n    }\n    if (!(column = FindColumn(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\treturn TtkEnumerateOptions(interp, column, ColumnOptionSpecs,\n\t    tv->tree.columnOptionTable, tv->core.tkwin);\n    } else if (objc == 4) {\n\treturn TtkGetOptionValue(interp, column, objv[3],\n\t    tv->tree.columnOptionTable, tv->core.tkwin);\n    } else {\n\treturn ConfigureColumn(interp, tv, column, objc-3, objv+3);\n    }\n}\n\n/* + $tv heading column ?options ....?\n *\tHeading data accessor\n */\nstatic int TreeviewHeadingCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Tk_OptionTable optionTable = tv->tree.headingOptionTable;\n    Tk_Window tkwin = tv->core.tkwin;\n    TreeColumn *column;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"column -option value...\");\n\treturn TCL_ERROR;\n    }\n    if (!(column = FindColumn(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\treturn TtkEnumerateOptions(\n\t    interp, column, HeadingOptionSpecs, optionTable, tkwin);\n    } else if (objc == 4) {\n\treturn TtkGetOptionValue(\n\t    interp, column, objv[3], optionTable, tkwin);\n    } else {\n\treturn ConfigureHeading(interp, tv, column, objc-3,objv+3);\n    }\n}\n\n/* + $tv set $item ?$column ?value??\n *\tQuery or configure cell values\n */\nstatic int TreeviewSetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n    TreeColumn *column;\n    Tcl_Size columnNumber;\n\n    if (objc < 3 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item ?column ?value??\");\n\treturn TCL_ERROR;\n    }\n    if (!(item = FindItem(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    /* Make sure -values exists:\n     */\n    if (!item->valuesObj) {\n\titem->valuesObj = Tcl_NewListObj(0,0);\n\tTcl_IncrRefCount(item->valuesObj);\n    }\n\n    if (objc == 3) {\n\t/* Return dictionary:\n\t */\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\tTcl_Obj *value;\n\tfor (columnNumber = 0; columnNumber < tv->tree.nColumns; ++columnNumber) {\n\t    Tcl_ListObjIndex(interp, item->valuesObj, columnNumber, &value);\n\t    if (value) {\n\t\tTcl_ListObjAppendElement(NULL, result,\n\t\t\ttv->tree.columns[columnNumber].idObj);\n\t\tTcl_ListObjAppendElement(NULL, result, value);\n\t    }\n\t}\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    }\n\n    /* else -- get or set column\n     */\n    if (!(column = FindColumn(interp, tv, objv[3]))) {\n\treturn TCL_ERROR;\n    }\n\n    if (column == &tv->tree.column0) {\n\t/* @@@ Maybe set -text here instead? */\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Display column #0 cannot be set\", -1));\n\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"COLUMN_0\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* Note: we don't do any error checking in the list operations,\n     * since item->valuesObj is guaranteed to be a list.\n     */\n    columnNumber = column - tv->tree.columns;\n\n    if (objc == 4) {\t/* get column */\n\tTcl_Obj *result = 0;\n\tTcl_ListObjIndex(interp, item->valuesObj, columnNumber, &result);\n\tif (!result) {\n\t    result = Tcl_NewStringObj(\"\",0);\n\t}\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    } else {\t\t/* set column */\n\tTcl_Size length;\n\n\titem->valuesObj = unshareObj(item->valuesObj);\n\n\t/* Make sure -values is fully populated:\n\t */\n\tTcl_ListObjLength(interp, item->valuesObj, &length);\n\twhile (length < tv->tree.nColumns) {\n\t    Tcl_Obj *empty = Tcl_NewStringObj(\"\",0);\n\t    Tcl_ListObjAppendElement(interp, item->valuesObj, empty);\n\t    ++length;\n\t}\n\n\t/* Set value:\n\t */\n\tTcl_ListObjReplace(interp,item->valuesObj,columnNumber,1,1,objv+4);\n\tTtkRedisplayWidget(&tv->core);\n\treturn TCL_OK;\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- tree modification.\n */\n\n/* + $tv insert $parent $index ?-id id? ?-option value ...?\n *\tInsert a new item.\n */\nstatic int TreeviewInsertCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *parent, *sibling, *newItem;\n    Tcl_HashEntry *entryPtr;\n    int isNew;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"parent index ?-id id? -options...\");\n\treturn TCL_ERROR;\n    }\n\n    /* Get parent node:\n     */\n    if ((parent = FindItem(interp, tv, objv[2])) == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /* Locate previous sibling based on $index:\n     */\n    if (!strcmp(Tcl_GetString(objv[3]), \"end\")) {\n\tsibling = EndPosition(tv, parent);\n    } else {\n\tint index;\n\tif (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tsibling = InsertPosition(parent, index);\n    }\n\n    /* Get node name:\n     *     If -id supplied and does not already exist, use that;\n     *     Otherwise autogenerate new one.\n     */\n    objc -= 4; objv += 4;\n    if (objc >= 2 && !strcmp(\"-id\", Tcl_GetString(objv[0]))) {\n\tconst char *itemName = Tcl_GetString(objv[1]);\n\n\tentryPtr = Tcl_CreateHashEntry(&tv->tree.items, itemName, &isNew);\n\tif (!isNew) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Item %s already exists\", itemName));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"ITEM_EXISTS\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tobjc -= 2; objv += 2;\n    } else {\n\tchar idbuf[16];\n\tdo {\n\t    ++tv->tree.serial;\n\t    snprintf(idbuf, sizeof(idbuf), \"I%03X\", tv->tree.serial);\n\t    entryPtr = Tcl_CreateHashEntry(&tv->tree.items, idbuf, &isNew);\n\t} while (!isNew);\n    }\n\n    /* Create and configure new item:\n     */\n    newItem = NewItem();\n    Tk_InitOptions(\n\tinterp, newItem, tv->tree.itemOptionTable, tv->core.tkwin);\n    newItem->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);\n    if (ConfigureItem(interp, tv, newItem, objc, objv) != TCL_OK) {\n\tTcl_DeleteHashEntry(entryPtr);\n\tFreeItem(newItem);\n\treturn TCL_ERROR;\n    }\n\n    /* Store in hash table, link into tree:\n     */\n    Tcl_SetHashValue(entryPtr, newItem);\n    newItem->entryPtr = entryPtr;\n    InsertItem(parent, sibling, newItem);\n    tv->tree.rowPosNeedsUpdate = 1;\n    TtkRedisplayWidget(&tv->core);\n\n    Tcl_SetObjResult(interp, ItemID(tv, newItem));\n    return TCL_OK;\n}\n\n/* + $tv detach $items --\n *\tUnlink each item in $items from the tree.\n */\nstatic int TreeviewDetachCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem **items;\n    Tcl_Size i;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    if (!(items = GetItemListFromObj(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    /* Sanity-check */\n    for (i = 0; items[i]; ++i) {\n\tif (items[i] == tv->tree.root) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Cannot detach root item\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"ROOT\", (char *)NULL);\n\t    Tcl_Free(items);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    for (i = 0; items[i]; ++i) {\n\tDetachItem(items[i]);\n    }\n\n    tv->tree.rowPosNeedsUpdate = 1;\n    TtkRedisplayWidget(&tv->core);\n    Tcl_Free(items);\n    return TCL_OK;\n}\n\n/* + $tv detached ?$item? --\n *\tList detached items (in arbitrary order) or query the detached state of\n *\t$item.\n */\nstatic int TreeviewDetachedCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item;\n\n    if (objc == 2) {\n\t/* List detached items */\n\tTcl_HashSearch search;\n\tTcl_HashEntry *entryPtr = Tcl_FirstHashEntry(&tv->tree.items, &search);\n\tTcl_Obj *objPtr = Tcl_NewObj();\n\n\twhile (entryPtr != NULL) {\n\t    item = (TreeItem *)Tcl_GetHashValue(entryPtr);\n\t    entryPtr = Tcl_NextHashEntry(&search);\n\t    if (IsDetached(tv, item)) {\n\t\tTcl_ListObjAppendElement(NULL, objPtr, ItemID(tv, item));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\treturn TCL_OK;\n    } else if (objc == 3) {\n\t/* Query; the root is never reported as detached */\n\tif (!(item = FindItem(interp, tv, objv[2]))) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(IsDetached(tv, item)));\n\treturn TCL_OK;\n    } else {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?item?\");\n\treturn TCL_ERROR;\n    }\n}\n/* + $tv delete $items --\n *\tDelete each item in $items.\n *\n *\tDo this in two passes:\n *\tFirst detach the item and all its descendants and remove them\n *\tfrom the hash table.  Free the items themselves in a second pass.\n *\n *\tIt's done this way because an item may appear more than once\n *\tin the list of items to delete (either directly or as a descendant\n *\tof a previously deleted item.)\n */\n\nstatic int TreeviewDeleteCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem **items, *delq;\n    Tcl_Size i;\n    int selChange = 0;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"items\");\n\treturn TCL_ERROR;\n    }\n\n    if (!(items = GetItemListFromObj(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    /* Sanity-check:\n     */\n    for (i = 0; items[i]; ++i) {\n\tif (items[i] == tv->tree.root) {\n\t    Tcl_Free(items);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Cannot delete root item\", -1));\n\t    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"ROOT\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /* Remove items from hash table.\n     */\n    delq = 0;\n    for (i = 0; items[i]; ++i) {\n\tif (items[i]->state & TTK_STATE_SELECTED) {\n\t    selChange = 1;\n\t} else if (items[i]->selObj != NULL) {\n\t    Tcl_Size length;\n\t    Tcl_ListObjLength(interp, items[i]->selObj, &length);\n\t    if (length > 0) {\n\t\tselChange = 1;\n\t    }\n\t}\n\tdelq = DeleteItems(items[i], delq);\n    }\n\n    /* Free items:\n     */\n    while (delq) {\n\tTreeItem *next = delq->next;\n\tif (tv->tree.focus == delq) {\n\t    tv->tree.focus = 0;\n\t}\n\tif (tv->tree.endPtr == delq) {\n\t    tv->tree.endPtr = 0;\n\t}\n\tFreeItem(delq);\n\tdelq = next;\n    }\n\n    Tcl_Free(items);\n    if (selChange) {\n\tTk_SendVirtualEvent(tv->core.tkwin, \"TreeviewSelect\", NULL);\n    }\n    tv->tree.rowPosNeedsUpdate = 1;\n    TtkRedisplayWidget(&tv->core);\n    return TCL_OK;\n}\n\n/* + $tv move $item $parent $index\n *\tMove $item to the specified $index in $parent's child list.\n */\nstatic int TreeviewMoveCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item, *parent;\n    TreeItem *sibling;\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item parent index\");\n\treturn TCL_ERROR;\n    }\n    if ((item = FindItem(interp, tv, objv[2])) == 0\n\t    || (parent = FindItem(interp, tv, objv[3])) == 0) {\n\treturn TCL_ERROR;\n    }\n\n    /* Locate previous sibling based on $index:\n     */\n    if (!strcmp(Tcl_GetString(objv[4]), \"end\")) {\n\tsibling = EndPosition(tv, parent);\n    } else {\n\tTreeItem *p;\n\tint index;\n\n\tif (Tcl_GetIntFromObj(interp, objv[4], &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tsibling = 0;\n\tfor (p = parent->children; p != NULL && index > 0; p = p->next) {\n\t    if (p != item) {\n\t\t--index;\n\t    } /* else -- moving node forward, count index+1 nodes  */\n\t    sibling = p;\n\t}\n    }\n\n    /* Check ancestry:\n     */\n    if (!AncestryCheck(interp, tv, item, parent)) {\n\treturn TCL_ERROR;\n    }\n\n    /* Moving an item after itself is a no-op:\n     */\n    if (item == sibling) {\n\treturn TCL_OK;\n    }\n\n    /* Move item:\n     */\n    DetachItem(item);\n    InsertItem(parent, sibling, item);\n\n    tv->tree.rowPosNeedsUpdate = 1;\n    TtkRedisplayWidget(&tv->core);\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- scrolling\n */\n\nstatic int TreeviewXViewCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    return TtkScrollviewCommand(interp, objc, objv, tv->tree.xscrollHandle);\n}\n\nstatic int TreeviewYViewCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    return TtkScrollviewCommand(interp, objc, objv, tv->tree.yscrollHandle);\n}\n\n/* $tree see $item --\n *\tEnsure that $item is visible.\n */\nstatic int TreeviewSeeCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeItem *item, *parent;\n    int scrollRow1, scrollRow2, visibleRows;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"item\");\n\treturn TCL_ERROR;\n    }\n    if (!(item = FindItem(interp, tv, objv[2]))) {\n\treturn TCL_ERROR;\n    }\n\n    /* The item cannot be moved into view if any ancestor (or itself) is detached.\n     */\n    if (IsItemOrAncestorDetached(tv, item)) {\n\treturn TCL_OK;\n    }\n\n    /* Make sure all ancestors are open:\n     */\n    for (parent = item->parent; parent; parent = parent->parent) {\n\tif (!(parent->state & TTK_STATE_OPEN)) {\n\t    parent->openObj = unshareObj(parent->openObj);\n\t    Tcl_SetBooleanObj(parent->openObj, 1);\n\t    parent->state |= TTK_STATE_OPEN;\n\t    tv->tree.rowPosNeedsUpdate = 1;\n\t    TtkRedisplayWidget(&tv->core);\n\t}\n    }\n    if (tv->tree.rowPosNeedsUpdate) {\n\tUpdatePositionTree(tv);\n    }\n\n    /* Update the scroll information, if necessary */\n    TtkUpdateScrollInfo(tv->tree.yscrollHandle);\n\n    /* Make sure item is visible:\n     */\n    if (item->rowPos < tv->tree.titleRows) {\n\treturn TCL_OK;\n    }\n    visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight\n\t    - tv->tree.titleRows;\n    scrollRow1 = item->rowPos - tv->tree.titleRows;\n    scrollRow2 = scrollRow1 + item->height - 1;\n\n    if (scrollRow2 >= tv->tree.yscroll.first + visibleRows) {\n\tscrollRow2 = 1 + scrollRow2 - visibleRows;\n\tTtkScrollTo(tv->tree.yscrollHandle, scrollRow2, true);\n    }\n\n    /* On small widgets (shorter than one row high, which is also the case\n     * before the widget is initially mapped) the above command will have\n     * scrolled down too far. This is why both conditions must be checked.\n     */\n    if (scrollRow1 < tv->tree.yscroll.first || item->height > visibleRows) {\n\tTtkScrollTo(tv->tree.yscrollHandle, scrollRow1, true);\n    }\n\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- interactive column resize\n */\n\n/* + $tree drag $column $newX --\n *\tSet right edge of display column $column to x position $X\n */\nstatic int TreeviewDragCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    int left = tv->tree.treeArea.x - tv->tree.xscroll.first;\n    Tcl_Size i = FirstColumn(tv);\n    TreeColumn *column;\n    int newx;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"column xposition\");\n\treturn TCL_ERROR;\n    }\n\n    if ((column = FindColumn(interp, tv, objv[2])) == 0\n\t    || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    for (;i < tv->tree.nDisplayColumns; ++i) {\n\tTreeColumn *c = tv->tree.displayColumns[i];\n\tint right = left + c->width;\n\tif (c == column) {\n\t    if (i < tv->tree.nTitleColumns) {\n\t\t/* Unscrollable column, remove scroll shift */\n\t\tright += tv->tree.xscroll.first;\n\t    }\n\t    DragColumn(tv, i, newx - right);\n\t    TtkRedisplayWidget(&tv->core);\n\t    return TCL_OK;\n\t}\n\tleft = right;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\"column %s is not displayed\", Tcl_GetString(objv[2])));\n    Tcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"COLUMN_INVISIBLE\", (char *)NULL);\n    return TCL_ERROR;\n}\n\nstatic int TreeviewDropCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"drop\");\n\treturn TCL_ERROR;\n    }\n    ResizeColumns(tv, TreeWidth(tv));\n    TtkRedisplayWidget(&tv->core);\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- focus and selection\n */\n\n/* + $tree focus ?item?\n */\nstatic int TreeviewFocusCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n\n    if (objc == 2) {\n\tif (tv->tree.focus) {\n\t    Tcl_SetObjResult(interp, ItemID(tv, tv->tree.focus));\n\t}\n\treturn TCL_OK;\n    } else if (objc == 3) {\n\tTreeItem *newFocus = FindItem(interp, tv, objv[2]);\n\tif (!newFocus) {\n\t    return TCL_ERROR;\n\t}\n\ttv->tree.focus = newFocus;\n\tTtkRedisplayWidget(&tv->core);\n\treturn TCL_OK;\n    } else {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?newFocus?\");\n\treturn TCL_ERROR;\n    }\n}\n\n/* + $tree selection ?add|remove|set|toggle $items?\n */\nstatic int TreeviewSelectionCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    enum {\n\tSELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE\n    };\n    static const char *const selopStrings[] = {\n\t\"set\", \"add\", \"remove\", \"toggle\", NULL\n    };\n\n    Treeview *tv = (Treeview *)recordPtr;\n    int selop, i, selChange = 0;\n    TreeItem *item, **items;\n\n    if (objc == 2) {\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\tfor (item = tv->tree.root->children; item; item = NextPreorder(item)) {\n\t    if (item->state & TTK_STATE_SELECTED) {\n\t\tTcl_ListObjAppendElement(NULL, result, ItemID(tv, item));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    }\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?add|remove|set|toggle items?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], selopStrings,\n\t    sizeof(char *), \"selection operation\", 0, &selop) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    items = GetItemListFromObj(interp, tv, objv[3]);\n    if (!items) {\n\treturn TCL_ERROR;\n    }\n\n    switch (selop)\n    {\n\tcase SELECTION_SET:\n\t    /* Clear */\n\t    for (item=tv->tree.root; item; item = NextPreorder(item)) {\n\t\tif (item->state & TTK_STATE_SELECTED) {\n\t\t    item->state &= ~TTK_STATE_SELECTED;\n\t\t    selChange = 1;\n\t\t}\n\t    }\n\t    for (i=0; items[i]; ++i) {\n\t\titems[i]->state |= TTK_STATE_SELECTED;\n\t\tselChange = 1;\n\t    }\n\t    break;\n\tcase SELECTION_ADD:\n\t    for (i=0; items[i]; ++i) {\n\t\tif (!(items[i]->state & TTK_STATE_SELECTED)) {\n\t\t    items[i]->state |= TTK_STATE_SELECTED;\n\t\t    selChange = 1;\n\t\t}\n\t    }\n\t    break;\n\tcase SELECTION_REMOVE:\n\t    for (i=0; items[i]; ++i) {\n\t\tif (items[i]->state & TTK_STATE_SELECTED) {\n\t\t    items[i]->state &= ~TTK_STATE_SELECTED;\n\t\t    selChange = 1;\n\t\t}\n\t    }\n\t    break;\n\tcase SELECTION_TOGGLE:\n\t    for (i=0; items[i]; ++i) {\n\t\titems[i]->state ^= TTK_STATE_SELECTED;\n\t\tselChange = 1;\n\t    }\n\t    break;\n    }\n\n    Tcl_Free(items);\n    if (selChange) {\n\tTk_SendVirtualEvent(tv->core.tkwin, \"TreeviewSelect\", NULL);\n    }\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/* + SelObjChangeElement --\n *\tChange an element in a cell selection list.\n */\nstatic int SelObjChangeElement(\n    Treeview *tv, Tcl_Obj *listPtr, Tcl_Obj *elemPtr,\n    int add,\n    TCL_UNUSED(int) /*remove*/,\n    int toggle)\n{\n    Tcl_Size i, nElements;\n    int anyChange = 0;\n    TreeColumn *column, *elemColumn;\n    Tcl_Obj **elements;\n\n    elemColumn = FindColumn(NULL, tv, elemPtr);\n    Tcl_ListObjGetElements(NULL, listPtr, &nElements, &elements);\n    for (i = 0; i < nElements; i++) {\n\tcolumn = FindColumn(NULL, tv, elements[i]);\n\tif (column == elemColumn) {\n\t    if (add) {\n\t\treturn anyChange;\n\t    }\n\t    Tcl_ListObjReplace(NULL, listPtr, i, 1, 0, NULL);\n\t    anyChange = 1;\n\t    return anyChange;\n\t}\n    }\n    if (add || toggle) {\n\tTcl_ListObjAppendElement(NULL, listPtr, elemColumn->idObj);\n\tanyChange = 1;\n    }\n    return anyChange;\n}\n\n/* + $tree cellselection ?add|remove|set|toggle $items?\n */\nstatic int CellSelectionRange(\n    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *fromCell, Tcl_Obj *toCell,\n    int add, int remove, int toggle)\n{\n    TreeCell cellFrom, cellTo;\n    TreeItem *item;\n    Tcl_Obj *columns, **elements;\n    int colno, fromNo, toNo, anyChange = 0;\n    Tcl_Size i, nElements;\n    int set = !(add || remove || toggle);\n\n    if (GetCellFromObj(interp, tv, fromCell, true, &fromNo, &cellFrom)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (GetCellFromObj(interp, tv, toCell, true, &toNo, &cellTo)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    /* Correct order.\n     */\n    if (fromNo > toNo) {\n\tcolno = fromNo;\n\tfromNo = toNo;\n\ttoNo = colno;\n    }\n\n    /* Make a list of columns in this rectangle.\n     */\n    columns = Tcl_NewListObj(0, 0);\n    Tcl_IncrRefCount(columns);\n    for (colno = fromNo; colno <= toNo; colno++) {\n\tTcl_ListObjAppendElement(NULL, columns,\n\t\ttv->tree.displayColumns[colno]->idObj);\n    }\n\n    /* Set is the only operation that affects items outside its rectangle.\n     * Start with clearing out.\n     */\n    if (set) {\n\tanyChange = CellSelectionClear(tv);\n    }\n\n    /* Correct order.\n     */\n    if (tv->tree.rowPosNeedsUpdate) {\n\tUpdatePositionTree(tv);\n    }\n    if (cellFrom.item->itemPos > cellTo.item->itemPos) {\n\titem = cellFrom.item;\n\tcellFrom.item = cellTo.item;\n\tcellTo.item = item;\n    }\n\n    /* Go through all items in this rectangle.\n     */\n    for (item = cellFrom.item; item; item = NextPreorder(item)) {\n\tif (item->selObj != NULL) {\n\t    item->selObj = unshareObj(item->selObj);\n\n\t    Tcl_ListObjGetElements(NULL, columns, &nElements, &elements);\n\t    for (i = 0; i < nElements; ++i) {\n\t\tanyChange |= SelObjChangeElement(tv, item->selObj, elements[i],\n\t\t\tadd, remove, toggle);\n\t    }\n\t} else {\n\t    /* Set, add and toggle do the same thing when empty before.\n\t     */\n\t    if (!remove) {\n\t\titem->selObj = columns;\n\t\tTcl_IncrRefCount(item->selObj);\n\t\tanyChange = 1;\n\t    }\n\t}\n\tif (item == cellTo.item) {\n\t    break;\n\t}\n    }\n\n    Tcl_DecrRefCount(columns);\n\n    if (anyChange) {\n\tTk_SendVirtualEvent(tv->core.tkwin, \"TreeviewSelect\", NULL);\n    }\n    TtkRedisplayWidget(&tv->core);\n    return TCL_OK;\n}\n\n/* + $tree cellselection ?add|remove|set|toggle $items?\n */\nstatic int TreeviewCellSelectionCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    enum {\n\tSELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE\n    };\n    static const char *const selopStrings[] = {\n\t\"set\", \"add\", \"remove\", \"toggle\", NULL\n    };\n\n    Treeview *tv = (Treeview *)recordPtr;\n    int selop, anyChange = 0;\n    Tcl_Size i, nCells;\n    TreeCell *cells;\n    TreeItem *item;\n\n    if (objc == 2) {\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\tfor (item = tv->tree.root->children; item; item = NextPreorder(item)) {\n\t    if (item->selObj != NULL) {\n\t\tTcl_Size n, elemc;\n\t\tTcl_Obj **elemv;\n\n\t\tTcl_ListObjGetElements(interp, item->selObj, &n, &elemv);\n\t\telemc = n;\n\t\tfor (i = 0; i < elemc; ++i) {\n\t\t    Tcl_Obj *elem[2];\n\t\t    elem[0] = ItemID(tv, item);\n\t\t    elem[1] = elemv[i];\n\t\t    Tcl_ListObjAppendElement(NULL, result,\n\t\t\t    Tcl_NewListObj(2, elem));\n\t\t}\n\t    }\n\t}\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    }\n\n    if (objc < 4 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?add|remove|set|toggle arg...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[2], selopStrings,\n\t    sizeof(char *), \"cellselection operation\", 0, &selop) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 5) {\n\tswitch (selop)\n\t{\n\t    case SELECTION_SET:\n\t\treturn CellSelectionRange(interp, tv, objv[3], objv[4], 0, 0, 0);\n\t    case SELECTION_ADD:\n\t\treturn CellSelectionRange(interp, tv, objv[3], objv[4], 1, 0, 0);\n\t    case SELECTION_REMOVE:\n\t\treturn CellSelectionRange(interp, tv, objv[3], objv[4], 0, 1, 0);\n\t    case SELECTION_TOGGLE:\n\t\treturn CellSelectionRange(interp, tv, objv[3], objv[4], 0, 0, 1);\n\t}\n    }\n\n    cells = GetCellListFromObj(interp, tv, objv[3], &nCells);\n    if (cells == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    switch (selop)\n    {\n\tcase SELECTION_SET:\n\t    anyChange = CellSelectionClear(tv);\n\t    /*FALLTHRU*/\n\tcase SELECTION_ADD:\n\t    for (i = 0; i < nCells; i++) {\n\t\titem = cells[i].item;\n\t\tif (item->selObj == NULL) {\n\t\t    item->selObj = Tcl_NewListObj(0, 0);\n\t\t    Tcl_IncrRefCount(item->selObj);\n\t\t}\n\t\titem->selObj = unshareObj(item->selObj);\n\t\tanyChange |= SelObjChangeElement(tv, item->selObj,\n\t\t\tcells[i].colObj, 1, 0, 0);\n\t    }\n\t    break;\n\tcase SELECTION_REMOVE:\n\t    for (i = 0; i < nCells; i++) {\n\t\titem = cells[i].item;\n\t\tif (item->selObj == NULL) {\n\t\t    continue;\n\t\t}\n\t\titem->selObj = unshareObj(item->selObj);\n\t\tanyChange |= SelObjChangeElement(tv, item->selObj,\n\t\t\tcells[i].colObj, 0, 1, 0);\n\t    }\n\t    break;\n\tcase SELECTION_TOGGLE:\n\t    for (i = 0; i < nCells; i++) {\n\t\titem = cells[i].item;\n\t\tif (item->selObj == NULL) {\n\t\t    item->selObj = Tcl_NewListObj(0, 0);\n\t\t    Tcl_IncrRefCount(item->selObj);\n\t\t}\n\t\titem->selObj = unshareObj(item->selObj);\n\t\tanyChange = SelObjChangeElement(tv, item->selObj,\n\t\t\tcells[i].colObj, 0, 0, 1);\n\t    }\n\t    break;\n    }\n\n    Tcl_Free(cells);\n    if (anyChange) {\n\tTk_SendVirtualEvent(tv->core.tkwin, \"TreeviewSelect\", NULL);\n    }\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget commands -- tags and bindings.\n */\n\n/* + $tv tag bind $tag ?$sequence ?$script??\n */\nstatic int TreeviewTagBindCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_TagTable tagTable = tv->tree.tagTable;\n    Tk_BindingTable bindingTable = tv->tree.bindingTable;\n    Ttk_Tag tag;\n\n    if (objc < 4 || objc > 6) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName ?sequence? ?script?\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tagTable, objv[3]);\n    if (!tag) { return TCL_ERROR; }\n\n    if (objc == 4) {\t\t/* $tv tag bind $tag */\n\tTk_GetAllBindings(interp, bindingTable, tag);\n    } else if (objc == 5) {\t/* $tv tag bind $tag $sequence */\n\t/* TODO: distinguish \"no such binding\" (OK) from \"bad pattern\" (ERROR)\n\t */\n\tconst char *script = Tk_GetBinding(interp,\n\t\tbindingTable, tag, Tcl_GetString(objv[4]));\n\tif (script != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(script,-1));\n\t}\n    } else if (objc == 6) {\t/* $tv tag bind $tag $sequence $script */\n\tconst char *sequence = Tcl_GetString(objv[4]);\n\tconst char *script = Tcl_GetString(objv[5]);\n\n\tif (!*script) { /* Delete existing binding */\n\t    Tk_DeleteBinding(interp, bindingTable, tag, sequence);\n\t} else {\n\t    unsigned long mask = Tk_CreateBinding(interp,\n\t\t    bindingTable, tag, sequence, script, 0);\n\n\t    /* Test mask to make sure event is supported:\n\t     */\n\t    if (mask & (~TreeviewBindEventMask)) {\n\t\tTk_DeleteBinding(interp, bindingTable, tag, sequence);\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"unsupported event %s\\nonly key, button, motion, and\"\n\t\t    \" virtual events supported\", sequence));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"TREE\", \"BIND_EVENTS\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\n/* + $tv tag configure $tag ?-option ?value -option value...??\n */\nstatic int TreeviewTagConfigureCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_TagTable tagTable = tv->tree.tagTable;\n    Ttk_Tag tag;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName ?-option ?value ...??\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tagTable, objv[3]);\n\n    if (objc == 4) {\n\treturn Ttk_EnumerateTagOptions(interp, tagTable, tag);\n    } else if (objc == 5) {\n\tTcl_Obj *result = Ttk_TagOptionValue(interp, tagTable, tag, objv[4]);\n\tif (result) {\n\t    Tcl_SetObjResult(interp, result);\n\t    return TCL_OK;\n\t} /* else */\n\treturn TCL_ERROR;\n    }\n    /* else */\n    TtkRedisplayWidget(&tv->core);\n    return Ttk_ConfigureTag(interp, tagTable, tag, objc - 4, objv + 4);\n}\n\n/* + $tv tag delete $tag\n */\nstatic int TreeviewTagDeleteCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_TagTable tagTable = tv->tree.tagTable;\n    TreeItem *item = tv->tree.root;\n    Ttk_Tag tag;\n\n    if (objc != 4) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tagTable, objv[3]);\n    /* remove the tag from all cells and items */\n    while (item) {\n\tRemoveTagFromCellsAtItem(item, tag);\n\tRemoveTag(item, tag);\n\titem = NextPreorder(item);\n    }\n    /* then remove the tag from the tag table */\n    Tk_DeleteAllBindings(tv->tree.bindingTable, tag);\n    Ttk_DeleteTagFromTable(tagTable, tag);\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/* + $tv tag has $tag ?$item?\n */\nstatic int TreeviewTagHasCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n\n    if (objc == 4) {\t/* Return list of all items with tag */\n\tTtk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);\n\tTreeItem *item = tv->tree.root;\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\n\twhile (item) {\n\t    if (Ttk_TagSetContains(item->tagset, tag)) {\n\t\tTcl_ListObjAppendElement(NULL, result, ItemID(tv, item));\n\t    }\n\t    item = NextPreorder(item);\n\t}\n\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    } else if (objc == 5) {\t/* Test if item has specified tag */\n\tTtk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);\n\tTreeItem *item = FindItem(interp, tv, objv[4]);\n\tif (!item) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp,\n\t    Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag)));\n\treturn TCL_OK;\n    } else {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName ?item?\");\n\treturn TCL_ERROR;\n    }\n}\n\n/* + $tv tag cell has $tag ?$cell?\n */\nstatic int TreeviewCtagHasCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    TreeCell cell;\n    Tcl_Size i, columnNumber;\n\n    if (objc == 5) {\t/* Return list of all cells with tag */\n\tTtk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[4]);\n\tTreeItem *item = tv->tree.root;\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\n\twhile (item) {\n\t    for (i = 0; i < item->nTagSets && i <= tv->tree.nColumns; ++i) {\n\t\tif (item->cellTagSets[i] != NULL) {\n\t\t    if (Ttk_TagSetContains(item->cellTagSets[i], tag)) {\n\t\t\tTcl_Obj *elem[2];\n\t\t\telem[0] = ItemID(tv, item);\n\t\t\tif (i == 0) {\n\t\t\t    elem[1] = tv->tree.column0.idObj;\n\t\t\t} else {\n\t\t\t    elem[1] = tv->tree.columns[i-1].idObj;\n\t\t\t}\n\t\t\tTcl_ListObjAppendElement(NULL, result,\n\t\t\t\tTcl_NewListObj(2, elem));\n\t\t    }\n\t\t}\n\t    }\n\t    item = NextPreorder(item);\n\t}\n\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    } else if (objc == 6) {\t/* Test if cell has specified tag */\n\tTtk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[4]);\n\tbool result = false;\n\tif (GetCellFromObj(interp, tv, objv[5], false, NULL, &cell) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (cell.column == &tv->tree.column0) {\n\t    columnNumber = 0;\n\t} else {\n\t    columnNumber = cell.column - tv->tree.columns + 1;\n\t}\n\tif (columnNumber < cell.item->nTagSets) {\n\t    if (cell.item->cellTagSets[columnNumber] != NULL) {\n\t\tresult = Ttk_TagSetContains(\n\t\t\tcell.item->cellTagSets[columnNumber],\n\t\t\ttag);\n\t    }\n\t}\n\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(result));\n\treturn TCL_OK;\n    } else {\n\tTcl_WrongNumArgs(interp, 4, objv, \"tagName ?cell?\");\n\treturn TCL_ERROR;\n    }\n}\n\n/* + $tv tag names\n */\nstatic int TreeviewTagNamesCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    return Ttk_EnumerateTags(interp, tv->tree.tagTable);\n}\n\n/* + $tv tag add $tag $items\n */\nstatic void AddTag(TreeItem *item, Ttk_Tag tag)\n{\n    if (Ttk_TagSetAdd(item->tagset, tag)) {\n\tif (item->tagsObj) Tcl_DecrRefCount(item->tagsObj);\n\titem->tagsObj = Ttk_NewTagSetObj(item->tagset);\n\tTcl_IncrRefCount(item->tagsObj);\n    }\n}\n\nstatic int TreeviewTagAddCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_Tag tag;\n    TreeItem **items;\n    Tcl_Size i;\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName items\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);\n    items = GetItemListFromObj(interp, tv, objv[4]);\n\n    if (!items) {\n\treturn TCL_ERROR;\n    }\n\n    for (i = 0; items[i]; ++i) {\n\tAddTag(items[i], tag);\n    }\n    Tcl_Free(items);\n\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/* Make sure tagset at column is allocated and initialised */\nstatic void AllocCellTagSets(Treeview *tv, TreeItem *item, Tcl_Size columnNumber)\n{\n    Tcl_Size i, newSize = columnNumber + 1;\n    if (newSize < tv->tree.nColumns + 1) {\n\tnewSize = tv->tree.nColumns + 1;\n    }\n    if (item->nTagSets < newSize) {\n\tif (item->cellTagSets == NULL) {\n\t    item->cellTagSets = (Ttk_TagSet *)\n\t\t    Tcl_Alloc(sizeof(Ttk_TagSet)*newSize);\n\t} else {\n\t    item->cellTagSets = (Ttk_TagSet *)\n\t\t    Tcl_Realloc(item->cellTagSets, sizeof(Ttk_TagSet) * newSize);\n\t}\n\tfor (i = item->nTagSets; i < newSize; i++) {\n\t    item->cellTagSets[i] = NULL;\n\t}\n\titem->nTagSets = newSize;\n    }\n\n    if (item->cellTagSets[columnNumber] == NULL) {\n\titem->cellTagSets[columnNumber] =\n\t\tTtk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);\n    }\n}\n\n/* + $tv tag cell add $tag $cells\n */\nstatic int TreeviewCtagAddCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_Tag tag;\n    TreeCell *cells;\n    TreeItem *item;\n    Tcl_Size i, nCells, columnNumber;\n\n    if (objc != 6) {\n\tTcl_WrongNumArgs(interp, 4, objv, \"tagName cells\");\n\treturn TCL_ERROR;\n    }\n\n    cells = GetCellListFromObj(interp, tv, objv[5], &nCells);\n    if (cells == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[4]);\n\n    for (i = 0; i < nCells; i++) {\n\tif (cells[i].column == &tv->tree.column0) {\n\t    columnNumber = 0;\n\t} else {\n\t    columnNumber = cells[i].column - tv->tree.columns  + 1;\n\t}\n\titem = cells[i].item;\n\tAllocCellTagSets(tv, item, columnNumber);\n\tTtk_TagSetAdd(item->cellTagSets[columnNumber], tag);\n    }\n\n    Tcl_Free(cells);\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/* + $tv tag remove $tag ?$items?\n */\nstatic void RemoveTag(TreeItem *item, Ttk_Tag tag)\n{\n    if (Ttk_TagSetRemove(item->tagset, tag)) {\n\tif (item->tagsObj) Tcl_DecrRefCount(item->tagsObj);\n\titem->tagsObj = Ttk_NewTagSetObj(item->tagset);\n\tTcl_IncrRefCount(item->tagsObj);\n    }\n}\n\n/* Remove tag from all cells at row 'item'\n */\nstatic void RemoveTagFromCellsAtItem(TreeItem *item, Ttk_Tag tag)\n{\n    Tcl_Size i;\n\n    for (i = 0; i < item->nTagSets; i++) {\n\tif (item->cellTagSets[i] != NULL) {\n\t    Ttk_TagSetRemove(item->cellTagSets[i], tag);\n\t}\n    }\n}\n\nstatic int TreeviewTagRemoveCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_Tag tag;\n\n    if (objc < 4 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 3, objv, \"tagName ?items?\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);\n\n    if (objc == 5) {\n\tTreeItem **items = GetItemListFromObj(interp, tv, objv[4]);\n\tint i;\n\n\tif (!items) {\n\t    return TCL_ERROR;\n\t}\n\tfor (i = 0; items[i]; ++i) {\n\t    RemoveTag(items[i], tag);\n\t}\n\tTcl_Free(items);\n    } else if (objc == 4) {\n\tTreeItem *item = tv->tree.root;\n\twhile (item) {\n\t    RemoveTag(item, tag);\n\t    item = NextPreorder(item);\n\t}\n    }\n\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\n/* + $tv tag cell remove $tag ?$cells?\n */\nstatic int TreeviewCtagRemoveCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    Treeview *tv = (Treeview *)recordPtr;\n    Ttk_Tag tag;\n    TreeCell *cells;\n    TreeItem *item;\n    Tcl_Size i, nCells, columnNumber;\n\n    if (objc < 5 || objc > 6) {\n\tTcl_WrongNumArgs(interp, 4, objv, \"tagName ?cells?\");\n\treturn TCL_ERROR;\n    }\n\n    tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[4]);\n\n    if (objc == 6) {\n\tcells = GetCellListFromObj(interp, tv, objv[5], &nCells);\n\tif (cells == NULL) {\n\t    return TCL_ERROR;\n\t}\n\n\tfor (i = 0; i < nCells; i++) {\n\t    if (cells[i].column == &tv->tree.column0) {\n\t\tcolumnNumber = 0;\n\t    } else {\n\t\tcolumnNumber = cells[i].column - tv->tree.columns  + 1;\n\t    }\n\t    item = cells[i].item;\n\t    AllocCellTagSets(tv, item, columnNumber);\n\t    Ttk_TagSetRemove(item->cellTagSets[columnNumber], tag);\n\t}\n\tTcl_Free(cells);\n    } else {\n\titem = tv->tree.root;\n\twhile (item) {\n\t    RemoveTagFromCellsAtItem(item, tag);\n\t    item = NextPreorder(item);\n\t}\n    }\n\n    TtkRedisplayWidget(&tv->core);\n\n    return TCL_OK;\n}\n\nstatic const Ttk_Ensemble TreeviewCtagCommands[] = {\n    { \"add\",\t\tTreeviewCtagAddCommand,0 },\n    { \"has\",\t\tTreeviewCtagHasCommand,0 },\n    { \"remove\",\t\tTreeviewCtagRemoveCommand,0 },\n    { 0,0,0 }\n};\n\nstatic const Ttk_Ensemble TreeviewTagCommands[] = {\n    { \"add\",\t\tTreeviewTagAddCommand,0 },\n    { \"bind\",\t\tTreeviewTagBindCommand,0 },\n    { \"cell\",\t0,TreeviewCtagCommands },\n    { \"configure\",\tTreeviewTagConfigureCommand,0 },\n    { \"delete\",\t\tTreeviewTagDeleteCommand,0 },\n    { \"has\",\t\tTreeviewTagHasCommand,0 },\n    { \"names\",\t\tTreeviewTagNamesCommand,0 },\n    { \"remove\",\t\tTreeviewTagRemoveCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget commands record.\n */\nstatic const Ttk_Ensemble TreeviewCommands[] = {\n    { \"bbox\",\t\tTreeviewBBoxCommand,0 },\n    { \"cellselection\",\tTreeviewCellSelectionCommand,0 },\n    { \"children\",\tTreeviewChildrenCommand,0 },\n    { \"cget\",\t\tTtkWidgetCgetCommand,0 },\n    { \"column\",\tTreeviewColumnCommand,0 },\n    { \"configure\",\tTtkWidgetConfigureCommand,0 },\n    { \"delete\",\tTreeviewDeleteCommand,0 },\n    { \"detach\",\tTreeviewDetachCommand,0 },\n    { \"detached\",\tTreeviewDetachedCommand,0 },\n    { \"drag\",\tTreeviewDragCommand,0 },\n    { \"drop\",\tTreeviewDropCommand,0 },\n    { \"exists\",\tTreeviewExistsCommand,0 },\n    { \"focus\",\t\tTreeviewFocusCommand,0 },\n    { \"heading\",\tTreeviewHeadingCommand,0 },\n    { \"identify\",\tTreeviewIdentifyCommand,0 },\n    { \"index\",\tTreeviewIndexCommand,0 },\n    { \"insert\",\tTreeviewInsertCommand,0 },\n    { \"instate\",\tTtkWidgetInstateCommand,0 },\n    { \"item\",\t\tTreeviewItemCommand,0 },\n    { \"move\",\t\tTreeviewMoveCommand,0 },\n    { \"next\",\t\tTreeviewNextCommand,0 },\n    { \"parent\",\tTreeviewParentCommand,0 },\n    { \"prev\",\t\tTreeviewPrevCommand,0 },\n    { \"see\",\t\tTreeviewSeeCommand,0 },\n    { \"selection\",\tTreeviewSelectionCommand,0 },\n    { \"set\",\t\tTreeviewSetCommand,0 },\n    { \"state\",\tTtkWidgetStateCommand,0 },\n    { \"style\",\t\tTtkWidgetStyleCommand,0 },\n    { \"tag\",\t0,TreeviewTagCommands },\n    { \"xview\",\tTreeviewXViewCommand,0 },\n    { \"yview\",\tTreeviewYViewCommand,0 },\n    { 0,0,0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ Widget definition.\n */\n\nstatic const WidgetSpec TreeviewWidgetSpec = {\n    \"Treeview\",\t\t\t/* className */\n    sizeof(Treeview),\t/* recordSize */\n    TreeviewOptionSpecs,\t/* optionSpecs */\n    TreeviewCommands,\t/* subcommands */\n    TreeviewInitialize,\t/* initializeProc */\n    TreeviewCleanup,\t\t/* cleanupProc */\n    TreeviewConfigure,\t/* configureProc */\n    TtkNullPostConfigure,\t/* postConfigureProc */\n    TreeviewGetLayout,\t\t/* getLayoutProc */\n    TreeviewSize,\t\t/* sizeProc */\n    TreeviewDoLayout,\t\t/* layoutProc */\n    TreeviewDisplay\t\t/* displayProc */\n};\n\n/*------------------------------------------------------------------------\n * +++ Layout specifications.\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"Treeview\",\n    TTK_GROUP(\"Treeview.field\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Treeview.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Treeview.treearea\", TTK_FILL_BOTH))))\n\nTTK_LAYOUT(\"Item\",\n    TTK_GROUP(\"Treeitem.padding\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Treeitem.indicator\", TTK_PACK_LEFT)\n\tTTK_NODE(\"Treeitem.image\", TTK_PACK_LEFT)\n\tTTK_NODE(\"Treeitem.text\", TTK_FILL_BOTH)))\n\nTTK_LAYOUT(\"Cell\",\n    TTK_GROUP(\"Treedata.padding\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Treeitem.image\", TTK_PACK_LEFT)\n\tTTK_NODE(\"Treeitem.text\", TTK_FILL_BOTH)))\n\nTTK_LAYOUT(\"Heading\",\n    TTK_NODE(\"Treeheading.cell\", TTK_FILL_BOTH)\n    TTK_GROUP(\"Treeheading.border\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Treeheading.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Treeheading.image\", TTK_PACK_RIGHT)\n\t    TTK_NODE(\"Treeheading.text\", TTK_FILL_X))))\n\nTTK_LAYOUT(\"Row\",\n    TTK_NODE(\"Treeitem.row\", TTK_FILL_BOTH))\n\nTTK_LAYOUT(\"Separator\",\n    TTK_NODE(\"Treeitem.separator\", TTK_FILL_BOTH))\n\nTTK_END_LAYOUT_TABLE\n\n/*------------------------------------------------------------------------\n * +++ Tree indicator element.\n */\n\ntypedef struct {\n    Tcl_Obj *colorObj;\n    Tcl_Obj *sizeObj;\n    Tcl_Obj *marginsObj;\n} TreeitemIndicator;\n\nstatic const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {\n    { \"-foreground\", TK_OPTION_COLOR,\n\toffsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },\n    { \"-indicatorsize\", TK_OPTION_PIXELS,\n\toffsetof(TreeitemIndicator,sizeObj), \"12\" },\n    { \"-indicatormargins\", TK_OPTION_STRING,\n\toffsetof(TreeitemIndicator,marginsObj), \"2 2 4 2\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void TreeitemIndicatorSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;\n    int size = 0;\n    Ttk_Padding margins;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);\n    if (size % 2 == 0) --size;\t/* An odd size is better for the indicator. */\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginsObj, &margins);\n\n    *widthPtr = size + Ttk_PaddingWidth(margins);\n    *heightPtr = size + Ttk_PaddingHeight(margins);\n}\n\nstatic void TreeitemIndicatorDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;\n    ArrowDirection direction =\n\t(state & TTK_STATE_OPEN) ? ARROW_DOWN : ARROW_RIGHT;\n    Ttk_Padding margins;\n    int cx, cy;\n    XColor *borderColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);\n    XGCValues gcvalues; GC gc; unsigned mask;\n\n    if (state & TTK_STATE_LEAF) /* don't draw anything */\n\treturn;\n\n    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginsObj, &margins);\n    b = Ttk_PadBox(b, margins);\n\n    switch (direction) {\n\tcase ARROW_DOWN:\n\t    TtkArrowSize(b.width/2, direction, &cx, &cy);\n\t    if ((b.height - cy) % 2 == 1) {\n\t\t++cy;\n\t    }\n\t    break;\n\tcase ARROW_RIGHT:\n\tdefault:\n\t    TtkArrowSize(b.height/2, direction, &cx, &cy);\n\t    if ((b.width - cx) % 2 == 1) {\n\t\t++cx;\n\t    }\n\t    break;\n    }\n\n    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);\n\n    gcvalues.foreground = borderColor->pixel;\n    gcvalues.line_width = 1;\n    mask = GCForeground | GCLineWidth;\n    gc = Tk_GetGC(tkwin, mask, &gcvalues);\n\n    TtkDrawArrow(Tk_Display(tkwin), d, gc, b, direction);\n\n    Tk_FreeGC(Tk_Display(tkwin), gc);\n}\n\nstatic const Ttk_ElementSpec TreeitemIndicatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TreeitemIndicator),\n    TreeitemIndicatorOptions,\n    TreeitemIndicatorSize,\n    TreeitemIndicatorDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Row element.\n */\n\ntypedef struct {\n    Tcl_Obj *backgroundObj;\n    Tcl_Obj *rowNumberObj;\n} RowElement;\n\nstatic const Ttk_ElementOptionSpec RowElementOptions[] = {\n    { \"-background\", TK_OPTION_COLOR,\n\toffsetof(RowElement,backgroundObj), DEFAULT_BACKGROUND },\n    { \"-rownumber\", TK_OPTION_INT,\n\toffsetof(RowElement,rowNumberObj), \"0\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void RowElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    RowElement *row = (RowElement *)elementRecord;\n    XColor *color = Tk_GetColorFromObj(tkwin, row->backgroundObj);\n    GC gc = Tk_GCForColor(color, d);\n\n    XFillRectangle(Tk_Display(tkwin), d, gc,\n\t    b.x, b.y, b.width, b.height);\n}\n\nstatic const Ttk_ElementSpec RowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(RowElement),\n    RowElementOptions,\n    TtkNullElementSize,\n    RowElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Initialisation.\n */\n\nMODULE_SCOPE void\nTtkTreeview_Init(Tcl_Interp *interp)\n{\n    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);\n\n    RegisterWidget(interp, \"ttk::treeview\", &TreeviewWidgetSpec);\n\n    Ttk_RegisterElement(interp, theme, \"Treeitem.indicator\",\n\t    &TreeitemIndicatorElementSpec, 0);\n    Ttk_RegisterElement(interp, theme, \"Treeitem.row\", &RowElementSpec, 0);\n    Ttk_RegisterElement(interp, theme, \"Treeitem.separator\", &RowElementSpec, 0);\n    Ttk_RegisterElement(interp, theme, \"Treeheading.cell\", &RowElementSpec, 0);\n    Ttk_RegisterElement(interp, theme, \"treearea\", &ttkNullElementSpec, 0);\n\n    Ttk_RegisterLayouts(theme, LayoutTable);\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkWidget.c",
    "content": "/*\n * Copyright © 2003, Joe English\n *\n * Core widget utilities.\n */\n\n#include \"tkInt.h\"\n#include \"ttkThemeInt.h\"\n#include \"ttkWidget.h\"\n\n/*------------------------------------------------------------------------\n * +++ Internal helper routines.\n */\n\n/* UpdateLayout --\n *\tCall the widget's get-layout hook to recompute corePtr->layout.\n *\tReturns TCL_OK if successful, returns TCL_ERROR and leaves\n *\tthe layout unchanged otherwise.\n */\nstatic int UpdateLayout(Tcl_Interp *interp, WidgetCore *corePtr)\n{\n    Ttk_Theme themePtr = Ttk_GetCurrentTheme(interp);\n    Ttk_Layout newLayout =\n\tcorePtr->widgetSpec->getLayoutProc(interp, themePtr,corePtr);\n\n    if (newLayout) {\n\tif (corePtr->layout) {\n\t    Ttk_FreeLayout(corePtr->layout);\n\t}\n\tcorePtr->layout = newLayout;\n\treturn TCL_OK;\n    }\n    return TCL_ERROR;\n}\n\n/* SizeChanged --\n *\tCall the widget's sizeProc to compute new requested size\n *\tand pass it to the geometry manager.\n */\nstatic void SizeChanged(WidgetCore *corePtr)\n{\n    int reqWidth = 1, reqHeight = 1;\n\n    if (corePtr->widgetSpec->sizeProc(corePtr,&reqWidth,&reqHeight)) {\n\tTk_GeometryRequest(corePtr->tkwin, reqWidth, reqHeight);\n    }\n}\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n\n/* BeginDrawing --\n *\tReturns a Drawable for drawing the widget contents.\n *\tThis is normally an off-screen Pixmap, copied to\n *\tthe window by EndDrawing().\n */\nstatic Drawable BeginDrawing(Tk_Window tkwin)\n{\n    return Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n}\n\n/* EndDrawing --\n *\tCopy the drawable contents to the screen and release resources.\n */\nstatic void EndDrawing(Tk_Window tkwin, Drawable d)\n{\n    XGCValues gcValues;\n    GC gc;\n\n    gcValues.function = GXcopy;\n    gcValues.graphics_exposures = False;\n    gc = Tk_GetGC(tkwin, GCFunction|GCGraphicsExposures, &gcValues);\n\n    XCopyArea(Tk_Display(tkwin), d, Tk_WindowId(tkwin), gc,\n\t    0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),\n\t    0, 0);\n\n    Tk_FreePixmap(Tk_Display(tkwin), d);\n    Tk_FreeGC(Tk_Display(tkwin), gc);\n}\n#else\n/* No double-buffering: draw directly into the window. */\nstatic Drawable BeginDrawing(Tk_Window tkwin) { return Tk_WindowId(tkwin); }\nstatic void EndDrawing(\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(Drawable))\n{\n}\n#endif\n\n/* DrawWidget --\n *\tRedraw a widget.  Called as an idle handler.\n */\nstatic void DrawWidget(void *recordPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n\n    corePtr->flags &= ~REDISPLAY_PENDING;\n    if (Tk_IsMapped(corePtr->tkwin)) {\n\tDrawable d = BeginDrawing(corePtr->tkwin);\n\tcorePtr->widgetSpec->layoutProc(recordPtr);\n\tcorePtr->widgetSpec->displayProc(recordPtr, d);\n\tEndDrawing(corePtr->tkwin, d);\n    }\n}\n\n/* TtkRedisplayWidget --\n *\tSchedule redisplay as an idle handler.\n */\nvoid TtkRedisplayWidget(WidgetCore *corePtr)\n{\n    if (corePtr->flags & WIDGET_DESTROYED) {\n\treturn;\n    }\n\n    if (!(corePtr->flags & REDISPLAY_PENDING)) {\n\tTcl_DoWhenIdle(DrawWidget, corePtr);\n\tcorePtr->flags |= REDISPLAY_PENDING;\n    }\n}\n\n/*\n * WidgetWorldChanged --\n *\tDefault Tk_ClassWorldChangedProc() for widgets.\n *\tInvoked whenever fonts or other system resources are changed;\n *\trecomputes geometry.\n */\nstatic void WidgetWorldChanged(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    (void)UpdateLayout(corePtr->interp, corePtr);\n    SizeChanged(corePtr);\n    TtkRedisplayWidget(corePtr);\n}\n\n/* TtkResizeWidget --\n *\tRecompute widget size, schedule geometry propagation and redisplay.\n */\nvoid TtkResizeWidget(WidgetCore *corePtr)\n{\n    if (corePtr->flags & WIDGET_DESTROYED) {\n\treturn;\n    }\n\n    WidgetWorldChanged(corePtr);\n}\n\n/* TtkWidgetChangeState --\n *\tSet / clear the specified bits in the 'state' flag,\n */\nvoid TtkWidgetChangeState(WidgetCore *corePtr,\n    unsigned int setBits, unsigned int clearBits)\n{\n    Ttk_State oldState = corePtr->state;\n    corePtr->state = (oldState & ~clearBits) | setBits;\n    if (corePtr->state ^ oldState) {\n\tTtkRedisplayWidget(corePtr);\n    }\n}\n\n/* WidgetInstanceObjCmd --\n *\tWidget instance command implementation.\n */\nstatic int\nWidgetInstanceObjCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    const Ttk_Ensemble *commands = corePtr->widgetSpec->commands;\n    int status;\n\n    Tcl_Preserve(clientData);\n    status = Ttk_InvokeEnsemble(commands,1, clientData,interp,objc,objv);\n    Tcl_Release(clientData);\n\n    return status;\n}\n\n/*------------------------------------------------------------------------\n * +++ Widget destruction.\n *\n * A widget can be destroyed when the application explicitly\n * destroys the window or one of its ancestors via [destroy]\n * or Tk_DestroyWindow(); when the application deletes the widget\n * instance command; when there is an error in the widget constructor;\n * or when another application calls XDestroyWindow on the window ID.\n *\n * The window receives a <DestroyNotify> event in all cases,\n * so we do the bulk of the cleanup there.  See [#2207435] for\n * further notes (esp. re: Tk_FreeConfigOptions).\n *\n * Widget code that reenters the interp should only do so\n * when the widtget is Tcl_Preserve()d, and should check\n * the WIDGET_DESTROYED flag bit upon return.\n */\n\n/* WidgetInstanceObjCmdDeleted --\n *\tWidget instance command\tdeletion callback.\n */\nstatic void\nWidgetInstanceObjCmdDeleted(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    corePtr->widgetCmd = NULL;\n    if (corePtr->tkwin != NULL) {\n\tTk_DestroyWindow(corePtr->tkwin);\n    }\n}\n\n/* DestroyWidget --\n *\tMain widget destructor; called from <DestroyNotify> event handler.\n */\nstatic void\nDestroyWidget(WidgetCore *corePtr)\n{\n    corePtr->flags |= WIDGET_DESTROYED;\n\n    corePtr->widgetSpec->cleanupProc(corePtr);\n\n    Tk_FreeConfigOptions(\n\t    corePtr, corePtr->optionTable, corePtr->tkwin);\n\n    if (corePtr->layout) {\n\tTtk_FreeLayout(corePtr->layout);\n    }\n\n    if (corePtr->flags & REDISPLAY_PENDING) {\n\tTcl_CancelIdleCall(DrawWidget, corePtr);\n    }\n\n    corePtr->tkwin = NULL;\n    if (corePtr->widgetCmd) {\n\tTcl_Command cmd = corePtr->widgetCmd;\n\tcorePtr->widgetCmd = 0;\n\t/* NB: this can reenter the interpreter via a command traces */\n\tTcl_DeleteCommandFromToken(corePtr->interp, cmd);\n    }\n    Tcl_EventuallyFree(corePtr, TCL_DYNAMIC);\n}\n\n/*\n * CoreEventProc --\n *\tEvent handler for basic events.\n *\tProcesses Expose, Configure, FocusIn/Out, and Destroy events.\n *\tAlso handles <<ThemeChanged>> virtual events.\n *\n *\tFor Expose and Configure, simply schedule the widget for redisplay.\n *\tFor Destroy events, handle the cleanup process.\n *\n *\tFor Focus events, set/clear the focus bit in the state field.\n *\n *\tFor Deactivate/Activate pseudo-events, set/clear the background state\n *\tflag.\n */\n\nstatic const unsigned CoreEventMask\n    = ExposureMask\n    | StructureNotifyMask\n    | FocusChangeMask\n    | VirtualEventMask\n    | ActivateMask\n    | EnterWindowMask\n    | LeaveWindowMask\n    ;\n\nstatic void CoreEventProc(void *clientData, XEvent *eventPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n\n    switch (eventPtr->type)\n    {\n\tcase ConfigureNotify :\n\t    TtkRedisplayWidget(corePtr);\n\t    break;\n\tcase Expose :\n\t    if (eventPtr->xexpose.count == 0) {\n\t\tTtkRedisplayWidget(corePtr);\n\t    }\n\t    break;\n\tcase DestroyNotify :\n\t    Tk_DeleteEventHandler(\n\t\tcorePtr->tkwin, CoreEventMask,CoreEventProc,clientData);\n\t    DestroyWidget(corePtr);\n\t    break;\n\tcase FocusIn:\n\tcase FocusOut:\n\t    /* Don't process \"virtual crossing\" events */\n\t    if (   eventPtr->xfocus.detail == NotifyInferior\n\t\t|| eventPtr->xfocus.detail == NotifyAncestor\n\t\t|| eventPtr->xfocus.detail == NotifyNonlinear)\n\t    {\n\t\tif (eventPtr->type == FocusIn) {\n\t\t    corePtr->state |= TTK_STATE_FOCUS;\n\t\t} else {\n\t\t    corePtr->state &= ~TTK_STATE_FOCUS;\n\t\t}\n\t\tTtkRedisplayWidget(corePtr);\n\t    }\n\t    break;\n\tcase ActivateNotify:\n\t    corePtr->state &= ~TTK_STATE_BACKGROUND;\n\t    TtkRedisplayWidget(corePtr);\n\t    break;\n\tcase DeactivateNotify:\n\t    corePtr->state |= TTK_STATE_BACKGROUND;\n\t    TtkRedisplayWidget(corePtr);\n\t    break;\n\tcase LeaveNotify:\n\t    corePtr->state &= ~TTK_STATE_HOVER;\n\t    TtkRedisplayWidget(corePtr);\n\t    break;\n\tcase EnterNotify:\n\t    corePtr->state |= TTK_STATE_HOVER;\n\t    TtkRedisplayWidget(corePtr);\n\t    break;\n\tcase VirtualEvent: {\n\t    const char *name = ((XVirtualEvent *)eventPtr)->name;\n\t    if ((name != NULL) && !strcmp(\"ThemeChanged\", name)) {\n\t\tWidgetWorldChanged(corePtr);\n\t    }\n\t    break;\n\t}\n\tdefault:\n\t    /* can't happen... */\n\t    break;\n    }\n}\n\nstatic const Tk_ClassProcs widgetClassProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    WidgetWorldChanged,\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n/*\n * TtkWidgetConstructorObjCmd --\n *\tGeneral-purpose widget constructor command implementation.\n *\tClientData is a WidgetSpec *.\n */\nint TtkWidgetConstructorObjCmd(\n    void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetSpec *widgetSpec = (WidgetSpec *)clientData;\n    const char *className = widgetSpec->className;\n    Tk_OptionTable optionTable =\n\tTk_CreateOptionTable(interp, widgetSpec->optionSpecs);\n    Tk_Window tkwin;\n    void *recordPtr;\n    WidgetCore *corePtr;\n    Tk_SavedOptions savedOptions;\n    Tcl_Size i;\n\n    if (objc < 2 || objc % 2 == 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?-option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /* Check if a -class option has been specified.\n     * We have to do this before the InitOptions() call,\n     * since InitOptions() is affected by the widget class.\n     */\n    for (i = 2; i < objc; i += 2) {\n\tif (!strcmp(Tcl_GetString(objv[i]), \"-class\")) {\n\t    className = Tcl_GetString(objv[i+1]);\n\t    break;\n\t}\n    }\n\n    tkwin = Tk_CreateWindowFromPath(\n\tinterp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), NULL);\n    if (tkwin == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Allocate and initialize the widget record.\n     */\n    recordPtr = Tcl_Alloc(widgetSpec->recordSize);\n    memset(recordPtr, 0, widgetSpec->recordSize);\n    corePtr = (WidgetCore *)recordPtr;\n\n    corePtr->tkwin\t= tkwin;\n    corePtr->interp\t= interp;\n    corePtr->widgetSpec\t= widgetSpec;\n    corePtr->widgetCmd\t= Tcl_CreateObjCommand2(interp, Tk_PathName(tkwin),\n\tWidgetInstanceObjCmd, recordPtr, WidgetInstanceObjCmdDeleted);\n    corePtr->optionTable = optionTable;\n    corePtr->layout\t= NULL;\n    corePtr->flags\t= 0;\n    corePtr->state\t= 0;\n\n    Tk_SetClass(tkwin, className);\n    Tk_SetClassProcs(tkwin, &widgetClassProcs, recordPtr);\n    Tk_SetWindowBackgroundPixmap(tkwin, ParentRelative);\n\n    widgetSpec->initializeProc(interp, recordPtr);\n\n    Tk_CreateEventHandler(tkwin, CoreEventMask, CoreEventProc, recordPtr);\n\n    /*\n     * Initial configuration.\n     */\n\n    Tcl_Preserve(corePtr);\n    if (Tk_InitOptions(interp, recordPtr, optionTable, tkwin) != TCL_OK) {\n\tgoto error;\n    }\n\n    if (Tk_SetOptions(interp, recordPtr, optionTable,\n\t    objc - 2, objv + 2, tkwin, &savedOptions, NULL) != TCL_OK) {\n\tTk_RestoreSavedOptions(&savedOptions);\n\tgoto error;\n    } else {\n\tTk_FreeSavedOptions(&savedOptions);\n    }\n    if (widgetSpec->configureProc(interp, recordPtr, ~0) != TCL_OK) {\n\tgoto error;\n    }\n    if (widgetSpec->postConfigureProc(interp, recordPtr, ~0) != TCL_OK) {\n\tgoto error;\n    }\n\n    if (WidgetDestroyed(corePtr)) {\n\tgoto error;\n    }\n\n    Tcl_Release(corePtr);\n\n    SizeChanged(corePtr);\n    Tk_MakeWindowExist(tkwin);\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1));\n    return TCL_OK;\n\nerror:\n    if (WidgetDestroyed(corePtr)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"widget has been destroyed\", -1));\n    } else {\n\tTk_DestroyWindow(tkwin);\n    }\n    Tcl_Release(corePtr);\n    return TCL_ERROR;\n}\n\n/*------------------------------------------------------------------------\n * +++ Default implementations for widget hook procedures.\n */\n\n/* TtkWidgetGetLayout --\n *\tDefault getLayoutProc.\n *\tLooks up the layout based on the -style resource (if specified),\n *\totherwise use the widget class.\n */\nTtk_Layout TtkWidgetGetLayout(\n    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    const char *styleName = 0;\n\n    if (corePtr->styleObj) {\n\tstyleName = Tcl_GetString(corePtr->styleObj);\n    }\n\n    if (!styleName || *styleName == '\\0') {\n\tstyleName = corePtr->widgetSpec->className;\n    }\n\n    return Ttk_CreateLayout(interp, themePtr, styleName,\n\trecordPtr, corePtr->optionTable, corePtr->tkwin);\n}\n\n/*\n * TtkWidgetGetOrientedLayout --\n *\tHelper routine.  Same as TtkWidgetGetLayout, but prefixes\n *\t\"Horizontal.\" or \"Vertical.\" to the style name, depending\n *\ton the value of the 'orient' option.\n */\nTtk_Layout TtkWidgetGetOrientedLayout(\n    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr, Tcl_Obj *orientObj)\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    const char *baseStyleName = 0;\n    Tcl_DString styleName;\n    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;\n    Ttk_Layout layout;\n\n    Tcl_DStringInit(&styleName);\n\n    /* Prefix:\n     */\n    Ttk_GetOrientFromObj(NULL, orientObj, &orient);\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\tTcl_DStringAppend(&styleName, \"Horizontal.\", TCL_INDEX_NONE);\n    } else {\n\tTcl_DStringAppend(&styleName, \"Vertical.\", TCL_INDEX_NONE);\n    }\n\n    /* Add base style name:\n     */\n    if (corePtr->styleObj) {\n\tbaseStyleName = Tcl_GetString(corePtr->styleObj);\n    }\n    if (!baseStyleName || *baseStyleName == '\\0') {\n\tbaseStyleName = corePtr->widgetSpec->className;\n    }\n\n    Tcl_DStringAppend(&styleName, baseStyleName, TCL_INDEX_NONE);\n\n    /* Create layout:\n     */\n    layout= Ttk_CreateLayout(interp, themePtr, Tcl_DStringValue(&styleName),\n\trecordPtr, corePtr->optionTable, corePtr->tkwin);\n\n    Tcl_DStringFree(&styleName);\n\n    return layout;\n}\n\n/* TtkNullInitialize --\n *\tDefault widget initializeProc (no-op)\n */\nvoid TtkNullInitialize(\n    TCL_UNUSED(Tcl_Interp *),\n    TCL_UNUSED(void *))\n{\n}\n\n/* TtkNullPostConfigure --\n *\tDefault widget postConfigureProc (no-op)\n */\nint TtkNullPostConfigure(\n    TCL_UNUSED(Tcl_Interp *),\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int))\n{\n    return TCL_OK;\n}\n\n/* TtkCoreConfigure --\n *\tDefault widget configureProc.\n *\tHandles -style option.\n */\nint TtkCoreConfigure(Tcl_Interp *interp, void *clientData, int mask)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    int status = TCL_OK;\n\n    if (mask & STYLE_CHANGED) {\n\tstatus = UpdateLayout(interp, corePtr);\n    }\n\n    return status;\n}\n\n/* TtkNullCleanup --\n *\tDefault widget cleanupProc (no-op)\n */\nvoid TtkNullCleanup(\n    TCL_UNUSED(void *))\n{\n    return;\n}\n\n/* TtkWidgetDoLayout --\n *\tDefault widget layoutProc.\n */\nvoid TtkWidgetDoLayout(void *clientData)\n{\n    WidgetCore *corePtr = (WidgetCore *)clientData;\n    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));\n}\n\n/* TtkWidgetDisplay --\n *\tDefault widget displayProc.\n */\nvoid TtkWidgetDisplay(void *recordPtr, Drawable d)\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Ttk_DrawLayout(corePtr->layout, corePtr->state, d);\n}\n\n/* TtkWidgetSize --\n *\tDefault widget sizeProc()\n */\nint TtkWidgetSize(void *recordPtr, int *widthPtr, int *heightPtr)\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);\n    return 1;\n}\n\n/*------------------------------------------------------------------------\n * +++ Default implementations for widget subcommands.\n */\n\n/* $w cget -option\n */\nint TtkWidgetCgetCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Tcl_Obj *result;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"option\");\n\treturn TCL_ERROR;\n    }\n    result = Tk_GetOptionValue(interp, recordPtr,\n\t\tcorePtr->optionTable, objv[2], corePtr->tkwin);\n    if (result == NULL) {\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\n/* $w configure ?-option ?value ....??\n */\nint TtkWidgetConfigureCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Tcl_Obj *result;\n\n    if (objc == 2) {\n\tresult = Tk_GetOptionInfo(interp, recordPtr,\n\t\tcorePtr->optionTable, NULL, corePtr->tkwin);\n    } else if (objc == 3) {\n\tresult = Tk_GetOptionInfo(interp, recordPtr,\n\t\tcorePtr->optionTable, objv[2], corePtr->tkwin);\n    } else {\n\tTk_SavedOptions savedOptions;\n\tint status;\n\tint mask = 0;\n\n\tstatus = Tk_SetOptions(interp, recordPtr,\n\t\tcorePtr->optionTable, objc - 2, objv + 2,\n\t\tcorePtr->tkwin, &savedOptions, &mask);\n\tif (status != TCL_OK) {\n\t    return status;\n\t}\n\n\tif (mask & READONLY_OPTION) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"attempt to change read-only option\", -1));\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t    return TCL_ERROR;\n\t}\n\n\tstatus = corePtr->widgetSpec->configureProc(interp, recordPtr, mask);\n\tif (status != TCL_OK) {\n\t    Tk_RestoreSavedOptions(&savedOptions);\n\t    return status;\n\t}\n\tTk_FreeSavedOptions(&savedOptions);\n\n\tstatus = corePtr->widgetSpec->postConfigureProc(interp,recordPtr,mask);\n\tif (WidgetDestroyed(corePtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"widget has been destroyed\", -1));\n\t    status = TCL_ERROR;\n\t}\n\tif (status != TCL_OK) {\n\t    return status;\n\t}\n\n\tif (mask & (STYLE_CHANGED | GEOMETRY_CHANGED)) {\n\t    SizeChanged(corePtr);\n\t}\n\n\tTtkRedisplayWidget(corePtr);\n\tresult = Tcl_NewObj();\n    }\n\n    if (result == 0) {\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n}\n\n/* $w state ? $stateSpec ?\n *\n *\tIf $stateSpec is specified, modify the widget state accordingly,\n *\treturn a new stateSpec representing the changed bits.\n *\n *\tOtherwise, return a statespec matching all the currently-set bits.\n */\n\nint TtkWidgetStateCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Ttk_StateSpec spec;\n    int status;\n    Ttk_State oldState, changed;\n\n    if (objc == 2) {\n\tTcl_SetObjResult(interp,\n\t    Ttk_NewStateSpecObj(corePtr->state, 0ul));\n\treturn TCL_OK;\n    }\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"state-spec\");\n\treturn TCL_ERROR;\n    }\n    status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec);\n    if (status != TCL_OK) {\n\treturn status;\n    }\n\n    oldState = corePtr->state;\n    corePtr->state = Ttk_ModifyState(corePtr->state, &spec);\n    changed = corePtr->state ^ oldState;\n\n    TtkRedisplayWidget(corePtr);\n\n    Tcl_SetObjResult(interp,\n\tTtk_NewStateSpecObj(oldState & changed, ~oldState & changed));\n    return status;\n}\n\n/* $w instate $stateSpec ?$script?\n *\n *\tTests if widget state matches $stateSpec.\n *\tIf $script is specified, execute script if state matches.\n *\tOtherwise, return true/false\n */\n\nint TtkWidgetInstateCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Ttk_State state = corePtr->state;\n    Ttk_StateSpec spec;\n    int status = TCL_OK;\n\n    if (objc < 3 || objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"state-spec ?script?\");\n\treturn TCL_ERROR;\n    }\n    status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec);\n    if (status != TCL_OK) {\n\treturn status;\n    }\n\n    if (objc == 3) {\n\tTcl_SetObjResult(interp,\n\t    Tcl_NewBooleanObj(Ttk_StateMatches(state,&spec)));\n    } else if (objc == 4) {\n\tif (Ttk_StateMatches(state,&spec)) {\n\t    status = Tcl_EvalObjEx(interp, objv[3], 0);\n\t}\n    }\n    return status;\n}\n\n/* $w identify $x $y\n * $w identify element $x $y\n *\tReturns: name of element at $x, $y\n */\nint TtkWidgetIdentifyCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n    Ttk_Element element;\n    static const char *const whatTable[] = { \"element\", NULL };\n    int x, y, what;\n\n    if (objc < 4 || objc > 5) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"?what? x y\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 5) {\n\t/* $w identify element $x $y */\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,\n\t\tsizeof(char *), \"option\", 0, &what) != TCL_OK)\n\t{\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK\n\t    || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    element = Ttk_IdentifyElement(corePtr->layout, x, y);\n    if (element) {\n\tconst char *elementName = Ttk_ElementName(element);\n\tTcl_SetObjResult(interp,Tcl_NewStringObj(elementName,-1));\n    }\n\n    return TCL_OK;\n}\n\n/* $w style\n *\tReturn the style currently applied to the widget.\n */\n\nint TtkWidgetStyleCommand(\n    void *recordPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[])\n{\n    WidgetCore *corePtr = (WidgetCore *)recordPtr;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"\");\n\treturn TCL_ERROR;\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    Ttk_StyleName(Ttk_LayoutStyle(corePtr->layout)), -1));\n\n    return TCL_OK;\n}\n\n/*EOF*/\n"
  },
  {
    "path": "generic/ttk/ttkWidget.h",
    "content": "/*\n * Copyright © 2003 Joe English\n * Helper routines for widget implementations.\n */\n\n#ifndef _TTKWIDGET\n#define _TTKWIDGET\n\n/*\n * State flags for 'flags' field.\n */\n#define WIDGET_DESTROYED\t0x0001\n#define REDISPLAY_PENDING\t0x0002\t/* scheduled call to RedisplayWidget */\n#define CURSOR_ON\t\t0x0020\t/* See TtkBlinkCursor() */\n#define WIDGET_USER_FLAG        0x0100  /* 0x0100 - 0x8000 for user flags */\n\n/*\n * Bit fields for OptionSpec 'mask' field:\n */\n#define READONLY_OPTION\t0x1\n#define STYLE_CHANGED\t0x2\n#define GEOMETRY_CHANGED\t0x4\n\n/*\n * Core widget elements\n */\ntypedef struct WidgetSpec_ WidgetSpec;\t/* Forward */\n\ntypedef struct\n{\n    Tk_Window tkwin;\t\t/* Window associated with widget */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with widget. */\n    WidgetSpec *widgetSpec;\t/* Widget class hooks */\n    Tcl_Command widgetCmd;\t/* Token for widget command. */\n    Tk_OptionTable optionTable;\t/* Option table */\n    Ttk_Layout layout;\t/* Widget layout */\n\n    /*\n     * Storage for resources:\n     */\n    Tcl_Obj *takeFocusPtr;\t/* Storage for -takefocus option */\n    Tcl_Obj *cursorObj;\t\t/* Storage for -cursor option */\n    Tcl_Obj *styleObj;\t\t/* Name of currently-applied style */\n    Tcl_Obj *classObj;\t\t/* Class name (readonly option) */\n\n    Ttk_State state;\t\t/* Current widget state */\n    unsigned int flags;\t\t/* internal flags, see above */\n\n} WidgetCore;\n\n/*\n * Widget specifications:\n */\nstruct WidgetSpec_\n{\n    const char\t\t*className;\t/* Widget class name */\n    size_t\t\trecordSize;\t/* #bytes in widget record */\n    const Tk_OptionSpec\t*optionSpecs;\t/* Option specifications */\n    const Ttk_Ensemble\t*commands;\t/* Widget instance subcommands */\n\n    /*\n     * Hooks:\n     */\n    void\t(*initializeProc)(Tcl_Interp *, void *recordPtr);\n    void\t(*cleanupProc)(void *recordPtr);\n    int\t(*configureProc)(Tcl_Interp *, void *recordPtr, int flags);\n    int\t(*postConfigureProc)(Tcl_Interp *, void *recordPtr, int flags);\n    Ttk_Layout\t(*getLayoutProc)(Tcl_Interp *,Ttk_Theme, void *recordPtr);\n    int\t(*sizeProc)(void *recordPtr, int *widthPtr, int *heightPtr);\n    void\t(*layoutProc)(void *recordPtr);\n    void\t(*displayProc)(void *recordPtr, Drawable d);\n};\n\n/*\n * Common factors for widget implementations:\n */\nMODULE_SCOPE void TtkNullInitialize(Tcl_Interp *, void *);\nMODULE_SCOPE int  TtkNullPostConfigure(Tcl_Interp *, void *, int);\nMODULE_SCOPE void TtkNullCleanup(void *recordPtr);\nMODULE_SCOPE Ttk_Layout TtkWidgetGetLayout(\n\tTcl_Interp *, Ttk_Theme, void *recordPtr);\nMODULE_SCOPE Ttk_Layout TtkWidgetGetOrientedLayout(\n\tTcl_Interp *, Ttk_Theme, void *recordPtr, Tcl_Obj *orientObj);\nMODULE_SCOPE int  TtkWidgetSize(void *recordPtr, int *w, int *h);\nMODULE_SCOPE void TtkWidgetDoLayout(void *recordPtr);\nMODULE_SCOPE void TtkWidgetDisplay(void *recordPtr, Drawable);\n\nMODULE_SCOPE int TtkCoreConfigure(Tcl_Interp*, void *, int mask);\n\n/* Common widget commands:\n */\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetCgetCommand;\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetConfigureCommand;\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetIdentifyCommand;\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetInstateCommand;\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetStateCommand;\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetStyleCommand;\n\n/* Widget constructor:\n */\nMODULE_SCOPE Tcl_ObjCmdProc2 TtkWidgetConstructorObjCmd;\n\n#define RegisterWidget(interp, name, specPtr) \\\n    Tcl_CreateObjCommand2(interp, name, \\\n\tTtkWidgetConstructorObjCmd, (void *)specPtr,NULL)\n\n/* WIDGET_TAKEFOCUS_TRUE --\n * WIDGET_TAKEFOCUS_FALSE --\n *\tAdd one or the other of these to each OptionSpecs table\n *\tto indicate whether the widget should take focus\n *\tduring keyboard traversal.\n */\n#define WIDGET_TAKEFOCUS_TRUE \\\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\", \\\n\t\"ttk::takefocus\", offsetof(WidgetCore, takeFocusPtr), TCL_INDEX_NONE, 0,0,0 }\n#define WIDGET_TAKEFOCUS_FALSE \\\n    {TK_OPTION_STRING, \"-takefocus\", \"takeFocus\", \"TakeFocus\", \\\n\t\"\", offsetof(WidgetCore, takeFocusPtr), TCL_INDEX_NONE, 0,0,0 }\n\n/* WIDGET_INHERIT_OPTIONS(baseOptionSpecs) --\n * Add this at the end of an OptionSpecs table to inherit\n * the options from 'baseOptionSpecs'.\n */\n#define WIDGET_INHERIT_OPTIONS(baseOptionSpecs) \\\n    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0, baseOptionSpecs, 0}\n\n/* All widgets should inherit from ttkCoreOptionSpecs[].\n */\nMODULE_SCOPE const Tk_OptionSpec ttkCoreOptionSpecs[];\n\n/*\n * Useful routines for use inside widget implementations:\n */\n/* extern int WidgetDestroyed(WidgetCore *); */\n#define WidgetDestroyed(corePtr) ((corePtr)->flags & WIDGET_DESTROYED)\n\nMODULE_SCOPE void TtkWidgetChangeState(WidgetCore *,\n\tunsigned int setBits, unsigned int clearBits);\n\nMODULE_SCOPE void TtkRedisplayWidget(WidgetCore *);\nMODULE_SCOPE void TtkResizeWidget(WidgetCore *);\n\nMODULE_SCOPE void TtkTrackElementState(WidgetCore *);\nMODULE_SCOPE void TtkBlinkCursor(WidgetCore *);\n\n/*\n * -state option values (compatibility)\n */\nMODULE_SCOPE void TtkCheckStateOption(WidgetCore *, Tcl_Obj *);\n\n/*\n * Variable traces:\n */\ntypedef void (*Ttk_TraceProc)(void *recordPtr, const char *value);\ntypedef struct TtkTraceHandle_ Ttk_TraceHandle;\n\nMODULE_SCOPE Ttk_TraceHandle *Ttk_TraceVariable(\n    Tcl_Interp*, Tcl_Obj *varnameObj, Ttk_TraceProc callback, void *clientData);\nMODULE_SCOPE void Ttk_UntraceVariable(Ttk_TraceHandle *);\nMODULE_SCOPE int Ttk_FireTrace(Ttk_TraceHandle *);\n\n/*\n * Helper routines for data accessor commands:\n */\nMODULE_SCOPE int TtkEnumerateOptions(\n    Tcl_Interp *, void *, const Tk_OptionSpec *, Tk_OptionTable, Tk_Window);\nMODULE_SCOPE int TtkGetOptionValue(\n    Tcl_Interp *, void *, Tcl_Obj *optName, Tk_OptionTable, Tk_Window);\n\n/*\n * Helper routines for scrolling widgets (see scroll.c).\n */\ntypedef struct {\n    Tcl_Size\tfirst;\t\t/* First visible item */\n    Tcl_Size\tlast;\t\t/* Last visible item */\n    Tcl_Size\ttotal;\t\t/* Total #items */\n    Tcl_Obj\t*scrollCmdObj;\t/* Widget option */\n} Scrollable;\n\ntypedef struct ScrollHandleRec *ScrollHandle;\n\nMODULE_SCOPE ScrollHandle TtkCreateScrollHandle(WidgetCore *, Scrollable *);\nMODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle);\n\nMODULE_SCOPE int TtkScrollviewCommand(\n    Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], ScrollHandle);\n\nMODULE_SCOPE void TtkUpdateScrollInfo(ScrollHandle h);\nMODULE_SCOPE void TtkScrollTo(ScrollHandle, Tcl_Size newFirst, bool updateScrollInfo);\nMODULE_SCOPE void TtkScrolled(ScrollHandle, Tcl_Size first, Tcl_Size last, Tcl_Size total);\nMODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle);\n\n/*\n * Tag sets (work in progress, half-baked)\n */\n\ntypedef struct TtkTag *Ttk_Tag;\ntypedef struct TtkTagTable *Ttk_TagTable;\ntypedef struct TtkTagSet {\t/* TODO: make opaque */\n    Ttk_Tag\t*tags;\n    Tcl_Size\tnTags;\n} *Ttk_TagSet;\n\nMODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable(\n\tTcl_Interp *, Tk_Window tkwin, const Tk_OptionSpec *, size_t recordSize);\nMODULE_SCOPE void Ttk_DeleteTagTable(Ttk_TagTable);\n\nMODULE_SCOPE Ttk_Tag Ttk_GetTag(Ttk_TagTable, const char *tagName);\nMODULE_SCOPE Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable, Tcl_Obj *);\n\nMODULE_SCOPE Tcl_Obj *Ttk_TagOptionValue(\n    Tcl_Interp *, Ttk_TagTable, Ttk_Tag, Tcl_Obj *optionName);\n\nMODULE_SCOPE int Ttk_EnumerateTagOptions(\n    Tcl_Interp *, Ttk_TagTable, Ttk_Tag);\n\nMODULE_SCOPE int Ttk_EnumerateTags(Tcl_Interp *, Ttk_TagTable);\n\nMODULE_SCOPE void Ttk_DeleteTagFromTable(Ttk_TagTable, Ttk_Tag);\n\nMODULE_SCOPE int Ttk_ConfigureTag(\n    Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag,\n    Tcl_Size objc, Tcl_Obj *const objv[]);\n\nMODULE_SCOPE Ttk_TagSet Ttk_GetTagSetFromObj(\n    Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr);\nMODULE_SCOPE Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet);\n\nMODULE_SCOPE void Ttk_FreeTagSet(Ttk_TagSet);\n\nMODULE_SCOPE bool Ttk_TagSetContains(Ttk_TagSet, Ttk_Tag tag);\nMODULE_SCOPE bool Ttk_TagSetAdd(Ttk_TagSet, Ttk_Tag tag);\nMODULE_SCOPE void Ttk_TagSetAddSet(Ttk_TagSet, Ttk_TagSet);\nMODULE_SCOPE bool Ttk_TagSetRemove(Ttk_TagSet, Ttk_Tag tag);\n\nMODULE_SCOPE void Ttk_TagSetDefaults(Ttk_TagTable, Ttk_Style, void *);\nMODULE_SCOPE void Ttk_TagSetValues(Ttk_TagTable, Ttk_TagSet, void *record);\nMODULE_SCOPE void Ttk_TagSetApplyStyle(Ttk_TagTable,Ttk_Style,Ttk_State,void*);\n\n/*\n * String tables for widget resource specifications:\n */\n\nMODULE_SCOPE const char *const ttkOrientStrings[];\nMODULE_SCOPE const char *const ttkCompoundStrings[];\nMODULE_SCOPE const char *const ttkDefaultStrings[];\n\n/*\n * ... other option types...\n */\nMODULE_SCOPE int TtkGetLabelAnchorFromObj(\n\tTcl_Interp*, Tcl_Obj*, Ttk_PositionSpec *);\n\n/*\n * Platform-specific initialization.\n */\n\n#ifdef _WIN32\n#define Ttk_PlatformInit Ttk_WinPlatformInit\nMODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *);\n#elif defined(MAC_OSX_TK)\n#define Ttk_PlatformInit Ttk_MacOSXPlatformInit\nMODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *);\n#else\n#define Ttk_PlatformInit(interp) /* TTK_X11PlatformInit() */\n#endif\n\n#endif /* _TTKWIDGET */\n"
  },
  {
    "path": "library/accessibility.tcl",
    "content": "# accessibility.tcl --\n\n# This file defines the 'tk accessible' command for screen reader support\n# on X11, Windows, and macOS. It implements an abstraction layer that\n# presents a consistent API across the three platforms.\n\n# Copyright © 2009 Allen B. Taylor\n# Copyright © 2024-2025 Kevin Walzer\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\nif {[info commands ::tk::accessible::check_screenreader] eq \"\" || [::tk::accessible::check_screenreader] eq 0 || [::tk::accessible::check_screenreader] eq \"\"} {\n    # Do not load if screen reader is not running or command is unavailable\n    proc ::tk::accessible args {\n\treturn 0\n    }\n} else {\n    if {[tk windowingsystem] eq \"x11\" && [::tk::accessible::check_screenreader] eq 1} {\n\n\t# Add border to all X11 widgets with accessible focus. A highlight rectangle\n\t# is drawn over focused widgets by the screen reader app on\n\t# macOS and Windows (VoiceOver, NVDA), but not on X11. Configuring\n\t# \"-relief groove\" and binding to FocusIn/Out events is the cleanest\n\t# way to accomplish this.\n\n\tnamespace eval ::tk::accessible {\n\t    variable origConfig\n\t    array set origConfig {}\n\n\t    # Apply to classic Tk widgets\n\t    proc ClassicFocusIn {w} {\n\t\tvariable origConfig\n\t\tif {![info exists origConfig($w)]} {\n\t\t    set origConfig($w) [list [$w cget -relief] [$w cget -borderwidth]]\n\t\t}\n\t\t$w configure -relief groove -borderwidth 2\n\t    }\n\n\t    proc ClassicFocusOut {w} {\n\t\tvariable origConfig\n\t\tif {[info exists origConfig($w)]} {\n\t\t    lassign $origConfig($w) relief border\n\t\t    $w configure -relief $relief -borderwidth $border\n\t\t}\n\t    }\n\n\t    # Apply focus bindings to a widget\n\t    proc AddClassic {w} {\n\t\tbindtags $w [linsert [bindtags $w] 0 FocusBorder]\n\t    }\n\n\t    # Setup global ttk styles\n\t    proc InitTtk {} {\n\t\tforeach class {TButton TEntry TCombobox TCheckbutton TRadiobutton \\\n\t\t\t\t   Treeview TScrollbar TScale TSpinbox TLabel} {\n\t\t    ttk::style map $class \\\n\t\t\t-relief {focus groove !focus flat} \\\n\t\t\t-borderwidth {focus 2 !focus 1}\n\t\t}\n\t    }\n\n\t    # Install focusborder bindtag for classic widgets\n\t    bind FocusBorder <FocusIn>  {+::tk::accessible::ClassicFocusIn %W}\n\t    bind FocusBorder <FocusOut> {+::tk::accessible::ClassicFocusOut %W}\n\n\t    # Install ttk mappings\n\t    ::tk::accessible::InitTtk\n\n\t    # Save the original widget commands and replace with wrappers\n\t    foreach wtype {button entry text listbox scale spinbox scrollbar label radiobutton checkbutton} {\n\t\tif {[llength [info commands ::tk::accessible::orig_$wtype]] == 0} {\n\t\t    rename ::$wtype ::tk::accessible::orig_$wtype\n\t\t    proc ::$wtype {args} [string map [list %TYPE% $wtype] {\n\t\t\t# Create the widget with the original command\n\t\t\tset w [::tk::accessible::orig_%TYPE% {*}$args]\n\t\t\t# Add focus bindings\n\t\t\t::tk::accessible::AddClassic $w\n\t\t\treturn $w\n\t\t    }]\n\t\t}\n\t    }\n\t}\n    }\n\n    namespace eval ::tk::accessible {\n\n\tif {[tk windowingsystem] eq \"x11\" } {\n\t    # ATK/Orca's API does not align well with Tk text, entry, and menu\n\t    # widgets, and non-window elements such as listbox and tree/table\n\t    # rows. There is too much of a mismatch between how Tk is\n\t    # structured and what ATK expects. Managing this data at the\n\t    # C level is fragile and complex.  In these cases, we do not\n\t    # address those widgets in C but instead use Tk's script-level\n\t    # bindings to manage the interaction by shelling out to\n\t    # Speech Dispatcher (the same engine powering Orca's voice) to\n\t    # vocalize text data and communicate state/data changes.\n\t    # Windows and macOS have functions built in to their accessibility\n\t    # API's to post custom announcements, but ATK does not, so we\n\t    # must use this as a fallback.\n\t    proc speak {text} {\n\t\tif {[::tk::accessible::check_screenreader] eq \"1\"} {\n\t\t    # Escape quotes in the text.\n\t\t    set safe_text [string map {\"\\\"\" \"\\\\\\\"\"} $text]\n\n\t\t    # Try spd-say first.\n\t\t    if {[catch {exec spd-say $safe_text} result]} {\n\t\t\t# fallback to espeak if spd-say fails\n\t\t\tcatch {exec espeak $safe_text} result\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t# Attach a variable trace to run _updateselection when a button changes.\n\tproc _attach_trace {w} {\n\t    # Radiobuttons/Checkbuttons always have a -variable.\n\t    set var [$w cget -variable]\n\t    if {$var ne \"\"} {\n\t\t# Avoid multiple traces on the same variable.\n\t\tcatch {trace remove variable $var write [list ::tk::accessible::_vartrace $w]}\n\t\ttrace add variable ::$var write [list ::tk::accessible::_vartrace $w]\n\t    }\n\t}\n\n\t# Trace handler.\n\tproc _vartrace {w args} {\n\t    if {![winfo exists $w]} {\n\t\treturn\n\t    }\n\n\t    # Use after idle to ensure variable has been updated\n\t    after idle [list ::tk::accessible::_announce_button_state $w]\n\t}\n\n\t# Announce button state after variable change\n\tproc _announce_button_state {w} {\n\t    if {![winfo exists $w]} {\n\t\treturn\n\t    }\n\n\t    set class [winfo class $w]\n\n\t    if {$class eq \"Radiobutton\" || $class eq \"TRadiobutton\"} {\n\t\tset state [::tk::accessible::_getradiodata $w]\n\t\tset description [::tk::accessible::get_acc_description $w]\n\n\t\t::tk::accessible::set_acc_value $w $state\n\t\t::tk::accessible::emit_selection_change $w\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak \"$description $state\"\n\t\t}\n\t    } elseif {$class eq \"Checkbutton\" || $class eq \"TCheckbutton\" || $class eq \"Toggleswitch\"} {\n\t\tset state [::tk::accessible::_getcheckdata $w]\n\t\tset description [::tk::accessible::get_acc_description $w]\n\n\t\t::tk::accessible::set_acc_value $w $state\n\t\t::tk::accessible::emit_selection_change $w\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak \"$description $state\"\n\t\t}\n\t    }\n\t}\n\n\t# Check message text on dialog.\n\tproc _getdialogtext {w} {\n\t    if {[winfo exists $w.msg]} {\n\t\treturn [$w.msg cget -text]\n\t    }\n\t}\n\n\t# Get text in text widget.\n\tproc _gettext {w} {\n\t    if {[winfo class $w] ne \"Text\"} {\n\t\treturn \"\"\n\t    }\n\t    if {[$w tag ranges sel] eq \"\"} {\n\t\tset data [$w get 1.0 end]\n\t    }  else {\n\t\tset data [$w get sel.first sel.last]\n\t    }\n\t    return $data\n\t}\n\n\t# Get text in entry widget.\n\tproc _getentrytext {w} {\n\t    set data [$w get]\n\t    return $data\n\t}\n\n\t# Create keypress/word bindings once for all supported widgets.\n\tproc install_keycapture {w} {\n\t    # Ensure we don’t double-bind\n\t    if {[lsearch -exact [bindtags $w] KeyCaptureTag] == -1} {\n\t\tbindtags $w [linsert [bindtags $w] 1 KeyCaptureTag]\n\t    }\n\t}\n\n\t# Core binding tag (shared by text, entry, ttk::entry).\n\tbind KeyCaptureTag <KeyPress> {+::tk::accessible::_handle_keypress %W %K}\n\tbind KeyCaptureTag <KeyRelease-space> {+ after 10 [list ::tk::accessible::_get_prev_word %W]}\n\n\t# Handle each keypress event.\n\tproc _handle_keypress {w key} {\n\t    # Ignore modifier keys and non-printables\n\t    if {$key eq \"\" || [string length $key] > 1} {\n\t\treturn\n\t    }\n\n\t    # If user pressed space, do nothing here — handled on KeyRelease.\n\t    if {$key eq \"space\"} {\n\t\treturn\n\t    }\n\n\t    # Otherwise emit single-character updates.\n\t    ::tk::accessible::set_acc_value $w $key\n\t    if {[tk windowingsystem] eq \"x11\"} {\n\t\t::tk::accessible::speak $key\n\t\t# Windows speaks the individual keypress by default\n\t    } elseif {[tk windowingsystem] eq \"aqua\"}  {\n\t\t::tk::accessible::emit_selection_change $w\n\t    }\n\t}\n\n\t# Retrieve the previous word before the cursor (called after space release).\n\tproc _get_prev_word {w} {\n\t    update idletasks   ;# ensure buffer is current\n\t    set class [winfo class $w]\n\t    set before \"\"\n\n\t    if {$class eq \"Text\"} {\n\t\t# For text widgets.\n\t\tset start [$w index \"insert linestart\"]\n\t\tif {[$w compare insert == $start]} {\n\t\t    # nothing before cursor at start of line.\n\t\t    return\n\t\t}\n\t\tset before [$w get $start \"insert -1c\"]\n\t    } elseif {$class eq \"Entry\" || $class eq \"TEntry\"} {\n\t\t# For entry/ttk::entry widgets.\n\t\tset full [$w get]\n\t\tset pos [$w index insert]\n\t\tif {$pos > 0} {\n\t\t    set before [string range $full 0 [expr {$pos - 2}]]\n\t\t}\n\t    } else {\n\t\treturn\n\t    }\n\n\t    # Extract last word before the space.\n\t    if {[regexp -nocase -- {\\S+$} $before match]} {\n\t\t::tk::accessible::set_acc_value $w $match\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $match\n\t\t} else {\n\t\t    ::tk::accessible::emit_selection_change $w\n\t\t}\n\t    }\n\t}\n\n\t# Attempt to verify if treeview is tree or table. This works\n\t# for simple cases but may not be perfect.\n\tproc _checktree {w} {\n\t    if {[expr {\"tree\" in [$w cget -show]}] eq 1} {\n\t\treturn \"Tree\"\n\t    } else {\n\t\treturn \"Table\"\n\t    }\n\t}\n\n\t# Get data from ttk::treeview.\n\tproc _gettreeviewdata {w} {\n\t    set values [$w item [lindex [$w selection] 0] -values]\n\t    return $values\n\t}\n\n\t# Get data from listbox.\n\tproc _getlistboxdata {w} {\n\t    set data [$w get [$w curselection]]\n\t    return $data\n\t}\n\n\t# Get treeview column names.\n\tproc _getcolumnnames {w} {\n\t    set columns [$w cget -columns]\n\t    foreach col $columns {\n\t\tset text [$w heading $col -text]\n\t\tlappend headerlist $text\n\t    }\n\t    return $headerlist\n\t}\n\n\t# Get selection status from radiobuttons.\n\tproc _getradiodata {w} {\n\t    if {![winfo exists $w]} {\n\t\treturn \"\"\n\t    }\n\n\t    set var [$w cget -variable]\n\t    if {$var eq \"\" || ![uplevel #0 info exists $var]} {\n\t\treturn \"not selected\"\n\t    }\n\n\t    set currentValue [uplevel #0 set $var]\n\t    set buttonValue [$w cget -value]\n\n\t    # Return the actual state\n\t    if {$currentValue eq $buttonValue} {\n\t\treturn \"selected\"\n\t    } else {\n\t\treturn \"not selected\"\n\t    }\n\t}\n\n\t# Get selection status from checkbuttons.\n\tproc _getcheckdata {w} {\n\t    if {![winfo exists $w]} {\n\t\treturn \"\"\n\t    }\n\n\t    set var [$w cget -variable]\n\t    if {$var eq \"\" || ![uplevel #0 info exists $var]} {\n\t\treturn \"not selected\"\n\t    }\n\n\t    set currentValue [uplevel #0 set $var]\n\t    set onValue [$w cget -onvalue]\n\n\t    # Check current state (not predicted state)\n\t    if {$currentValue eq $onValue} {\n\t\treturn \"selected\"\n\t    } else {\n\t\treturn \"not selected\"\n\t    }\n\t}\n\n\t# Update data selection for various widgets.\n\tproc _updateselection {w} {\n\t    if {[winfo class $w] eq \"Radiobutton\" || [winfo class $w] eq \"TRadiobutton\"} {\n\t\tset state [::tk::accessible::_getradiodata $w]\n\t\tset description [::tk::accessible::get_acc_description $w]\n\n\t\t::tk::accessible::set_acc_value $w $state\n\t\t::tk::accessible::emit_selection_change $w\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    # Announce: description, role, state\n\t\t    ::tk::accessible::speak \"$description radiobutton $state\"\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"Checkbutton\" || [winfo class $w] eq \"TCheckbutton\" || [winfo class $w] eq \"Toggleswitch\"} {\n\t\tset state [::tk::accessible::_getcheckdata $w]\n\t\tset description [::tk::accessible::get_acc_description $w]\n\n\t\t::tk::accessible::set_acc_value $w $state\n\t\t::tk::accessible::emit_selection_change $w\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    # Announce: description, role, state\n\t\t    if {[winfo class $w] eq \"Toggleswitch\"} {\n\t\t\t::tk::accessible::speak \"$description toggleswitch $state\"\n\t\t    } else {\n\t\t\t::tk::accessible::speak \"$description checkbox $state\"\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"Listbox\"} {\n\t\tset data [$w get [$w curselection]]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\t::tk::accessible::emit_selection_change $w\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $data\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"Treeview\"} {\n\t\tset data [::tk::accessible::_gettreeviewdata $w]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\t::tk::accessible::emit_selection_change $w\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $data\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"Entry\" || [winfo class $w] eq \"TEntry\"}  {\n\t\tset data [::tk::accessible::_getentrytext $w]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\t::tk::accessible::emit_selection_change $w\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    # Only speak if there's content\n\t\t    if {$data ne \"\"} {\n\t\t\t::tk::accessible::speak $data\n\t\t    } else {\n\t\t\t::tk::accessible::speak \"entry blank\"\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TCombobox\"} {\n\t\tset data [$w get]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\t::tk::accessible::emit_selection_change $w\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $data\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TNotebook\"}  {\n\t\tset data  [$w tab current -text]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\t::tk::accessible::emit_selection_change $w\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $data\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"Text\"}  {\n\t\tset data [::tk::accessible::_gettext $w]\n\t\t::tk::accessible::set_acc_value $w $data\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    ::tk::accessible::speak $data\n\t\t}\n\t\tif {[winfo class $w] eq \"TProgressbar\"}  {\n\t\t    set data [::tk::accessible::_getpbvalue $w]\n\t\t    ::tk::accessible::set_acc_value $w $data\n\t\t    ::tk::accessible::emit_selection_change $w\n\t\t    if {[tk windowingsystem] eq \"x11\"} {\n\t\t\t::tk::accessible::speak $data\n\t\t    }\n\t\t}\n\n\t\t# Some widgets need special handling on X11\n\t\t# because ATK does not align well with their\n\t\t# configuration.\n\n\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t    if {[winfo class $w] eq \"Menu\"} {\n\t\t\tset data [$w entrycget active -label]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::speak $data\n\t\t    }\n\t\t    if {[winfo class $w] eq \"Spinbox\" || \\\n\t\t\t    [winfo class $w] eq \"TSpinbox\" \\\n\t\t\t    || [winfo class $w] eq \"Scale\" || \\\n\t\t\t    [winfo class $w] eq \"TScale\" ||\\\n\t\t\t    [winfo class $w] eq \"TCombobox\"} {\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::speak $data\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t# Increment values in various widgets in response to keypress events.\n\tproc _updatescale {w key} {\n\t    if {[winfo class $w] eq \"Scale\"} {\n\t\tswitch -- $key {\n\t\t    Right {\n\t\t\ttk::ScaleIncrement $w down little noRepeat\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t    Left {\n\t\t\ttk::ScaleIncrement $w up little noRepeat\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TScale\"} {\n\t\tswitch -- $key {\n\t\t    Right {\n\t\t\tttk::scale::Increment $w 1\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t    Left {\n\t\t\tttk::scale::Increment $w -1\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\n\t    if {[winfo class $w] eq \"Spinbox\"} {\n\t\tswitch -- $key {\n\t\t    Up {\n\t\t\t$w invoke buttonup\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t    Down {\n\t\t\t$w invoke buttondown\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TSpinbox\"} {\n\t\tswitch -- $key {\n\t\t    Up {\n\t\t\tttk::spinbox::Spin $w +1\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t    Down {\n\t\t\tttk::spinbox::Spin $w -1\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TCombobox\"} {\n\t\tswitch -- $key {\n\t\t    Down {\n\t\t\tttk::combobox::Post $w\n\t\t\tset data [$w get]\n\t\t    }\n\t\t    Escape {\n\t\t\tttk::combobox::Unpost $w\n\t\t\t$w selection range 0 end\n\t\t\tif {[tk windowingsystem] eq \"aqua\"} {\n\t\t\t    event generate <Command-a>\n\t\t\t} else {\n\t\t\t    event generate <Control-a>\n\t\t\t}\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t    if {[winfo class $w] eq \"TNotebook\"} {\n\t\tswitch -- $key {\n\t\t    Right {\n\t\t\t{ ttk::notebook::CycleTab %W  1; break }\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t    Left {\n\t\t\tttk::scale::Increment $w -1\n\t\t\tset data [$w get]\n\t\t\t::tk::accessible::set_acc_value $w $data\n\t\t\t::tk::accessible::emit_selection_change $w\n\t\t\tif {[tk windowingsystem] eq \"x11\"} {\n\t\t\t    ::tk::accessible::speak $data\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t# Get value of progress bar.\n\tproc _getpbvalue  {pb} {\n\t    # Make sure widget exists\n\t    if {![winfo exists $pb]} { return \"\" }\n\n\t    set mode [$pb cget -mode]\n\n\t    if {$mode eq \"indeterminate\"} {\n\t\t# Any indeterminate bar is considered busy\n\t\treturn \"busy\"\n\t    } else {\n\t\t# Determinate: busy if value < maximum\n\t\tif {[$pb cget -value] < [$pb cget -maximum]} {\n\t\t    return \"busy\"\n\t\t} else {\n\t\t    return \"\"\n\t\t}\n\t    }\n\t}\n\n\n\t# Some widgets will not respond to keypress events unless\n\t# they have focus. Force Tk focus on the widget that currently has\n\t# accessibility focus if needed.\n\n\tproc _forceTkFocus {w} {\n\t    # Check to make sure window is not destroyed.\n\t    if {[winfo exists $w]} {\n\t\tif {[tk windowingsystem] eq \"aqua\"} {\n\t\t    if {[winfo class $w] in {Scale TScale Spinbox TSpinbox Listbox Treeview TProgressbar}} {\n\t\t\tif {[focus] ne $w} {\n\t\t\t    focus -force $w\n\t\t\t}\n\t\t    }\n\t\t} elseif {[tk windowingsystem] eq \"win32\"} {\n\t\t    ::tk::accessible::emit_focus_change $w\n\t\t}\n\t    }\n\t}\n\n\t# Set initial accessible attributes and add binding to <Map> event.\n\t# If the accessibility role is already set, return because\n\t# we only want these to fire once.\n\tproc _init {w role name description value state action} {\n\t    if {[catch {::tk::accessible::get_acc_role $w} msg]} {\n\t\tif {$msg == $role} {\n\t\t    return\n\t\t}\n\t    }\n\t    if {[tk windowingsystem] ne \"aqua\"} {\n\t\t# This is necessary to ensure correct accessible keyboard navigation\n\t\tif [winfo exists $w] {\n\t\t    $w configure -takefocus 1\n\t\t}\n\t    }\n\n\t    ::tk::accessible::set_acc_role $w $role\n\t    ::tk::accessible::set_acc_name $w $name\n\t    ::tk::accessible::set_acc_description $w $description\n\t    ::tk::accessible::set_acc_value $w $value\n\t    ::tk::accessible::set_acc_state $w $state\n\t    ::tk::accessible::set_acc_action $w $action\n\n\t}\n\n\t# Toplevel bindings.\n\tbind Toplevel <Map> {+::tk::accessible::_init \\\n\t\t\t\t %W \\\n\t\t\t\t Toplevel \\\n\t\t\t\t [wm title %W] \\\n\t\t\t\t {}  \\\n\t\t\t\t {} \\\n\t\t\t\t {} \\\n\t\t\t\t {} \\\n\t\t\t     }\n\n\t# Button/TButton bindings.\n\tbind Button <Map> {+::tk::accessible::_init \\\n\t\t\t       %W \\\n\t\t\t       Button \\\n\t\t\t       Button \\\n\t\t\t       [%W cget -text] \\\n\t\t\t       {} \\\n\t\t\t       [%W cget -state] \\\n\t\t\t       {%W invoke}\\\n\t\t\t   }\n\tbind TButton <Map> {+::tk::accessible::_init \\\n\t\t\t\t%W \\\n\t\t\t\tButton \\\n\t\t\t\tButton \\\n\t\t\t\t[%W cget -text] \\\n\t\t\t\t{}\\\n\t\t\t\t[%W cget -state] \\\n\t\t\t\t{%W invoke}\\\n\t\t\t    }\n\n\t# Menubutton/TMButton bindings.\n\tbind Menubutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t   %W \\\n\t\t\t\t   Button \\\n\t\t\t\t   Button \\\n\t\t\t\t   [%W cget -text] \\\n\t\t\t\t   {} \\\n\t\t\t\t   [%W cget -state] \\\n\t\t\t\t   {%W invoke}\\\n\t\t\t       }\n\tbind TMenubutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t    %W \\\n\t\t\t\t    Button \\\n\t\t\t\t    Button \\\n\t\t\t\t    [%W cget -text] \\\n\t\t\t\t    {} \\\n\t\t\t\t    [%W cget -state] \\\n\t\t\t\t    {%W invoke}\\\n\t\t\t\t}\n\n\t# Canvas bindings.\n\tbind Canvas <Map> {+::tk::accessible::_init \\\n\t\t\t       %W \\\n\t\t\t       Canvas \\\n\t\t\t       Canvas \\\n\t\t\t       Canvas \\\n\t\t\t       {} \\\n\t\t\t       {} \\\n\t\t\t       {}\\\n\t\t\t   }\n\n\t# Checkbutton/TCheckbutton/Toggleswitch bindings.\n\tbind Checkbutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t    %W \\\n\t\t\t\t    Checkbutton \\\n\t\t\t\t    Checkbutton \\\n\t\t\t\t    [%W cget -text] \\\n\t\t\t\t    [set [%W cget -variable]] \\\n\t\t\t\t    [%W cget -state] \\\n\t\t\t\t    {%W invoke}\\\n\t\t\t\t}\n\tbind TCheckbutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t     %W \\\n\t\t\t\t     Checkbutton \\\n\t\t\t\t     Checkbutton \\\n\t\t\t\t     [%W cget -text] \\\n\t\t\t\t     [set [%W cget -variable]] \\\n\t\t\t\t     [%W cget -state] \\\n\t\t\t\t     {%W invoke}\\\n\t\t\t\t }\n\tbind Toggleswitch <Map> {+::tk::accessible::_init \\\n\t\t\t\t     %W \\\n\t\t\t\t     Toggleswitch \\\n\t\t\t\t     Toggleswitch \\\n\t\t\t\t     Toggleswitch \\\n\t\t\t\t     [%W switchstate] \\\n\t\t\t\t     {} \\\n\t\t\t\t     {%W toggle}\\\n\t\t\t\t }\n\n\t# Combobox bindings.\n\tbind TCombobox <Map> {+::tk::accessible::_init \\\n\t\t\t\t  %W \\\n\t\t\t\t  Combobox \\\n\t\t\t\t  Combobox \\\n\t\t\t\t  Combobox \\\n\t\t\t\t  [%W get] \\\n\t\t\t\t  [%W cget -state] \\\n\t\t\t\t  {} \\\n\t\t\t      }\n\n\t# Dialog bindings.\n\tbind Dialog <Map> {+::tk::accessible::_init\\\n\t\t\t       %W \\\n\t\t\t       Dialog \\\n\t\t\t       [wm title %W] \\\n\t\t\t       [::tk::accessible::_getdialogtext %W] \\\n\t\t\t       {} \\\n\t\t\t       {} \\\n\t\t\t       {}\\\n\t\t\t   }\n\n\t# Entry/TEntry bindings.\n\tbind Entry <Map> {+::tk::accessible::_init \\\n\t\t\t      %W \\\n\t\t\t      Entry \\\n\t\t\t      Entry \\\n\t\t\t      Entry \\\n\t\t\t      [%W get] \\\n\t\t\t      [%W cget -state] \\\n\t\t\t      {} \\\n\t\t\t      ; ::tk::accessible::install_keycapture %W}\n\n\n\tbind TEntry <Map> {+::tk::accessible::_init \\\n\t\t\t       %W \\\n\t\t\t       Entry \\\n\t\t\t       Entry \\\n\t\t\t       Entry \\\n\t\t\t       [%W get] \\\n\t\t\t       [%W state]\\\n\t\t\t       {} \\\n\t\t\t       ; ::tk::accessible::install_keycapture %W}\n\n\n\t# Listbox bindings.\n\tbind Listbox <Map> {+::tk::accessible::_init \\\n\t\t\t\t%W \\\n\t\t\t\tListbox \\\n\t\t\t\tListbox \\\n\t\t\t\tListbox \\\n\t\t\t\t[%W get [%W curselection]] \\\n\t\t\t\t[%W cget -state]\\\n\t\t\t\t{%W invoke}\\\n\t\t\t    }\n\n\t# Progressbar bindings.\n\tbind TProgressbar <Map> {+::tk::accessible::_init \\\n\t\t\t\t     %W \\\n\t\t\t\t     Progressbar \\\n\t\t\t\t     Progressbar \\\n\t\t\t\t     Progressbar \\\n\t\t\t\t     [::tk::accessible::_getpbvalue %W] \\\n\t\t\t\t     [%W state] \\\n\t\t\t\t     {}\\\n\t\t\t\t }\n\n\t# Radiobutton/TRadiobutton bindings.\n\tbind Radiobutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t    %W \\\n\t\t\t\t    Radiobutton \\\n\t\t\t\t    Radiobutton \\\n\t\t\t\t    [%W cget -text] \\\n\t\t\t\t    [%W cget -variable] \\\n\t\t\t\t    [%W cget -state] \\\n\t\t\t\t    {%W invoke}\\\n\t\t\t\t}\n\tbind TRadiobutton <Map> {+::tk::accessible::_init \\\n\t\t\t\t     %W \\\n\t\t\t\t     Radiobutton \\\n\t\t\t\t     Radiobutton \\\n\t\t\t\t     [%W cget -text] \\\n\t\t\t\t     [%W cget -variable] \\\n\t\t\t\t     [%W cget -state] \\\n\t\t\t\t     {%W invoke}\\\n\t\t\t\t }\n\n\t# Scale/TScale bindings.\n\tbind Scale <Map> {+::tk::accessible::_init \\\n\t\t\t      %W \\\n\t\t\t      Scale \\\n\t\t\t      Scale \\\n\t\t\t      Scale \\\n\t\t\t      [%W get] \\\n\t\t\t      [%W cget -state]\\\n\t\t\t      {%W set}\\\n\t\t\t  }\n\tbind TScale <Map> {+::tk::accessible::_init \\\n\t\t\t       %W \\\n\t\t\t       Scale \\\n\t\t\t       Scale \\\n\t\t\t       Scale \\\n\t\t\t       [%W get] \\\n\t\t\t       [%W cget -state] \\\n\t\t\t       {%W set} \\\n\t\t\t   }\n\n\t# Menu accessibility bindings for X11 only. Menus are native\n\t# on macOS/Windows, so we don’t expose them here.\n\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    variable prevActiveIndex\n\t    set prevActiveIndex \"\"\n\n\t    # Update the accessible notifications after idle.\n\t    proc _update_active_entry {menuWidget} {\n\t\tvariable prevActiveIndex\n\n\t\t# Determine if this is a menubar or submenu.\n\t\tset isMenubar [expr {[winfo manager $menuWidget] eq \"menubar\"}]\n\n\t\t# Get current active index.\n\t\tset idx [$menuWidget index active]\n\t\tif {$idx eq \"none\" || $idx eq \"\"} {\n\t\t    return\n\t\t}\n\n\t\t# Build a safer unique key (include parent to avoid collisions).\n\t\tset currentKey \"[winfo parent $menuWidget]-$menuWidget-$idx\"\n\n\t\t# Prevent duplicate processing of the same index.\n\t\tif {[info exists prevActiveIndex] && $prevActiveIndex eq $currentKey} {\n\t\t    return\n\t\t}\n\t\tset prevActiveIndex $currentKey\n\n\t\t# Get the label of the active entry safely.\n\t\tif {[catch {set label [$menuWidget entrycget $idx -label]} err]} {\n\t\t    set label \"\"\n\t\t}\n\n\t\t# Announce menubar immediately.\n\t\tif $isMenubar {\n\t\t    ::tk::accessible::speak $label\n\n\t\t    # Clear dedupe cache so submenu index 1 is NOT skipped.\n\t\t    unset -nocomplain prevActiveIndex\n\t\t} else {\n\t\t    # Submenu - add gentle pause before announcing.\n\t\t    if {$label ne \"\" && [$menuWidget type $idx] ne \"separator\"} {\n\t\t\tafter 100 [list ::tk::accessible::speak $label]\n\t\t    }\n\t\t}\n\n\t\t# Update accessible object.\n\t\t::tk::accessible::set_acc_name   $menuWidget $label\n\t\t::tk::accessible::set_acc_action $menuWidget [list $menuWidget invoke $idx]\n\t\t::tk::accessible::emit_selection_change $menuWidget\n\t\t::tk::accessible::emit_focus_change     $menuWidget\n\t    }\n\n\n\t    # Bind <<MenuSelect>> for mouse/keyboard navigation.\n\t    bind Menu <<MenuSelect>> {\n\t\tafter idle [list ::tk::accessible::_update_active_entry %W]\n\t    }\n\n\t    # Key bindings - handle navigation AND announcement together\n\t    bind Menu <Up> {+\n\t\t# Only process if this is a submenu (not menubar)\n\t\tif {[winfo manager %W] ne \"menubar\"} {\n\t\t    set current [%W index active]\n\t\t    if {$current eq \"\"} {\n\t\t\tset idx [%W index last]\n\t\t    } else {\n\t\t\tset idx [expr {$current - 1}]\n\t\t    }\n\t\t    set lastIndex [%W index last]\n\t\t    while {$idx >= 0} {\n\t\t\tif {[%W type $idx] ne \"separator\" && [%W entrycget $idx -state] ne \"disabled\"} {\n\t\t\t    %W activate $idx\n\t\t\t    after idle [list ::tk::accessible::_update_active_entry %W]\n\t\t\t    break\n\t\t\t}\n\t\t\tincr idx -1\n\t\t    }\n\t\t}\n\t    }\n\n\t    bind Menu <Down> {+\n\t\t# Only process if this is a submenu (not menubar)\n\t\tif {[winfo manager %W] ne \"menubar\"} {\n\t\t    set current [%W index active]\n\t\t    if {$current eq \"\"} {\n\t\t\tset idx 0\n\t\t    } else {\n\t\t\tset idx [expr {$current + 1}]\n\t\t    }\n\t\t    set lastIndex [%W index last]\n\t\t    while {$idx <= $lastIndex} {\n\t\t\tif {[%W type $idx] ne \"separator\" && [%W entrycget $idx -state] ne \"disabled\"} {\n\t\t\t    %W activate $idx\n\t\t\t    after idle [list ::tk::accessible::_update_active_entry %W]\n\t\t\t    break\n\t\t\t}\n\t\t\tincr idx\n\t\t    }\n\t\t}\n\t    }\n\n\t    bind Menu <Return> {+\n\t\tset idx [%W index active]\n\t\tif {$idx ne \"\" && [%W type $idx] ne \"separator\" && [%W entrycget $idx -state] ne \"disabled\"} {\n\t\t    %W invoke $idx\n\t\t}\n\t    }\n\n\t    # Add bindings to catch when menus are posted/unposted.\n\t    bind Menu <Map> {+\n\t\t# Determine role based on whether this is a menubar.\n\t\tif {[winfo manager %W] eq \"menubar\"} {\n\t\t    set role Menubar ;# ATK_ROLE_MENU_BAR\n\t\t} else {\n\t\t    set role Menu ;# ATK_ROLE_MENU\n\t\t}\n\n\t\t::tk::accessible::_init \\\n\t\t\t\t %W \\\n\t\t\t\t $role \\\n\t\t\t\t $role \\\n\t\t\t\t {} \\\n\t\t\t\t {} \\\n\t\t\t\t {} \\\n\t\t\t\t {}\n\n\t\t# Handle initial vocalization based on menu type.\n\t\tif {$role eq \"Menubar\"} {\n\t\t    focus %W\n\t\t    after idle {\n\t\t\tset idx [%W index active]\n\t\t\tif {$idx eq \"none\" || $idx eq \"\"} {\n\t\t\t    %W activate 0\n\t\t\t}\n\t\t\t::tk::accessible::_update_active_entry %W\n\t\t    }\n\t\t} else {\n\t\t    # For submenus, announce the active entry when mapped.\n\t\t    after idle [list ::tk::accessible::_update_active_entry %W]\n\t\t}\n\t    }\n\n\t    # Handle initial menubar focus.\n\t    bind Menu <FocusIn> {+\n\t\tif {[winfo manager %W] eq \"menubar\"} {\n\t\t    set idx [%W index active]\n\t\t    if {$idx eq \"none\" || $idx eq \"\"} {\n\t\t\t%W activate 0\n\t\t    }\n\t\t    after idle [list ::tk::accessible::_update_active_entry %W]\n\t\t}\n\t    }\n\t}\n\n\t# Scrollbar/TScrollbar bindings.\n\tbind Scrollbar <Map> {+::tk::accessible::_init \\\n\t\t\t\t  %W \\\n\t\t\t\t  Scrollbar \\\n\t\t\t\t  Scrollbar \\\n\t\t\t\t  Scrollbar \\\n\t\t\t\t  {} \\\n\t\t\t\t  {} \\\n\t\t\t\t  {}\\\n\t\t\t      }\n\tbind TScrollbar <Map> {+::tk::accessible::_init \\\n\t\t\t\t   %W \\\n\t\t\t\t   Scrollbar \\\n\t\t\t\t   Scrollbar \\\n\t\t\t\t   Scrollbar \\\n\t\t\t\t   {} \\\n\t\t\t\t   {} \\\n\t\t\t\t   {}\\\n\t\t\t       }\n\n\t# Spinbox/TSpinbox bindings.\n\tbind Spinbox <Map> {+::tk::accessible::_init \\\n\t\t\t\t%W \\\n\t\t\t\tSpinbox \\\n\t\t\t\tSpinbox \\\n\t\t\t\tSpinbox \\\n\t\t\t\t[%W get] \\\n\t\t\t\t[%W cget -state] \\\n\t\t\t\t{%W cget -command}\\\n\t\t\t    }\n\tbind TSpinbox <Map> {+::tk::accessible::_init \\\n\t\t\t\t %W \\\n\t\t\t\t Spinbox \\\n\t\t\t\t Spinbox \\\n\t\t\t\t Spinbox \\\n\t\t\t\t [%W get] \\\n\t\t\t\t [%W state] \\\n\t\t\t\t {%W cget -command}\\\n\t\t\t     }\n\n\n\t# Treeview bindings.\n\tbind Treeview <Map> {+::tk::accessible::_init \\\n\t\t\t\t %W \\\n\t\t\t\t [::tk::accessible::_checktree %W] \\\n\t\t\t\t [::tk::accessible::_checktree %W] \\\n\t\t\t\t [::tk::accessible::_getcolumnnames %W] \\\n\t\t\t\t [::tk::accessible::_gettreeviewdata %W] \\\n\t\t\t\t [%W state] \\\n\t\t\t\t {ttk::treeview::Press %W %x %y }\\\n\t\t\t     }\n\n\t# Text bindings.\n\tbind Text <Map> {+::tk::accessible::_init \\\n\t\t\t     %W \\\n\t\t\t     Text \\\n\t\t\t     Text \\\n\t\t\t     Text \\\n\t\t\t     [::tk::accessible::_gettext %W] \\\n\t\t\t     [%W cget -state] \\\n\t\t\t     {}\\\n\t\t\t     ; ::tk::accessible::install_keycapture %W}\n\n\t# Label/TLabel bindings.\n\tbind Label <Map>  {+::tk::accessible::_init \\\n\t\t\t       %W \\\n\t\t\t       Label \\\n\t\t\t       Label \\\n\t\t\t       {} \\\n\t\t\t       [%W cget -text] \\\n\t\t\t       {}\\\n\t\t\t       {}\\\n\t\t\t   }\n\n\tbind TLabel <Map>    {+::tk::accessible::_init \\\n\t\t\t\t  %W \\\n\t\t\t\t  Label \\\n\t\t\t\t  Label \\\n\t\t\t\t  {} \\\n\t\t\t\t  [%W cget -text] \\\n\t\t\t\t  {}\\\n\t\t\t\t  {}\\\n\t\t\t      }\n\n\t# Notebook bindings - bind to the <<NotebookTabChanged>> event rather\n\t# than <Map> because this event is generated before the <Map> event,\n\t# which returns an error because the accessibility data has not been\n\t# initialized yet.\n\tbind TNotebook <<NotebookTabChanged>> {+::tk::accessible::_init \\\n\t\t\t\t\t\t   %W \\\n\t\t\t\t\t\t   Notebook \\\n\t\t\t\t\t\t   Notebook \\\n\t\t\t\t\t\t   Notebook \\\n\t\t\t\t\t\t   [%W tab current -text] \\\n\t\t\t\t\t\t   {} \\\n\t\t\t\t\t\t   {}\\\n\t\t\t\t\t       }\n\n\tbind all <Map> {+::tk::accessible::add_acc_object %W}\n\n\t# Various bindings to capture data/selection changes for\n\t# widgets that support returning a value.\n\n\t# Selection changes.\n\tbind Listbox <<ListboxSelect>> {+::tk::accessible::_updateselection %W}\n\tbind Treeview <<TreeviewSelect>> {+::tk::accessible::_updateselection %W}\n\tbind TCombobox <<ComboboxSelected>> {+::tk::accessible::_updateselection %W}\n\tbind Text <<Selection>> {+::tk::accessible::_updateselection %W}\n\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    # Attach variable traces for state monitoring\n\t    bind Radiobutton   <Map> {+::tk::accessible::_attach_trace %W}\n\t    bind TRadiobutton  <Map> {+::tk::accessible::_attach_trace %W}\n\t    bind Checkbutton   <Map> {+::tk::accessible::_attach_trace %W}\n\t    bind TCheckbutton  <Map> {+::tk::accessible::_attach_trace %W}\n\t    bind Toggleswitch  <Map> {+::tk::accessible::_attach_trace %W}\n\n\t    # Announce state on focus (initial state)\n\t    bind Radiobutton <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TRadiobutton <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Checkbutton <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TCheckbutton <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Toggleswitch <FocusIn> {+::tk::accessible::_updateselection %W}\n\n\t    # Announce state on invoke (after button press)\n\t    # Use after idle to ensure variable has been updated\n\t    bind Radiobutton <<Invoke>> {+after idle [list ::tk::accessible::_announce_button_state %W]}\n\t    bind TRadiobutton <<Invoke>> {+after idle [list ::tk::accessible::_announce_button_state %W]}\n\t    bind Checkbutton <<Invoke>> {+after idle [list ::tk::accessible::_announce_button_state %W]}\n\t    bind TCheckbutton <<Invoke>> {+after idle [list ::tk::accessible::_announce_button_state %W]}\n\t    bind Toggleswitch <<Invoke>> {+after idle [list ::tk::accessible::_announce_button_state %W]}\n\n\t    # Entry widgets - announce content on focus\n\t    bind Entry <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TEntry <FocusIn> {+::tk::accessible::_updateselection %W}\n\n\t    # Other X11 focus bindings\n\t    bind Listbox <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Treeview <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TNotebook <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TCombobox <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Text <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TProgressbar <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Spinbox <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TSpinbox <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind Scale <FocusIn> {+::tk::accessible::_updateselection %W}\n\t    bind TScale <FocusIn> {+::tk::accessible::_updateselection %W}\n\t}\n\n\n\t# Capture value changes from scale widgets.\n\tbind Scale <Right> {+::tk::accessible::_updatescale %W Right}\n\tbind Scale <Left> {+::tk::accessible::_updatescale %W Left}\n\tbind TScale <Right> {+::tk::accessible::_updatescale %W Right}\n\tbind TScale <Left> {+::tk::accessible::_updatescale %W Left}\n\n\t# In some contexts, the accessibility API is confused about widget\n\t# roles because of the way the widget is constructed. For instance,\n\t# VoiceOver and Orca misread the ttk::spinbox as an entry because\n\t# of how it is constructed. In such cases, let's re-use an old trick\n\t# that we used with the Aqua scrollbar when the ttk widgets were first\n\t# developed - map the ttk widget to its classic equivalent. There may\n\t# be a visual conflict but it is more important that the AT be able\n\t# to correctly identify widget and its value.\n\n\tif {[tk windowingsystem] eq \"aqua\" || [tk windowingsystem] eq \"x11\"} {\n\t    set result [::tk::accessible::check_screenreader]\n\t    if {$result > 0} {\n\t\tinterp alias {} ::ttk::spinbox {} ::tk::spinbox\n\t    }\n\t}\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    set result [::tk::accessible::check_screenreader]\n\t    if {$result > 0} {\n\t\tinterp alias {} ::ttk::radiobutton {} ::tk::radiobutton\n\t\tinterp alias {} ::ttk::checkbutton {} ::tk::checkbutton\n\t\tinterp alias {} ::ttk::scale {} ::tk::scale\n\n\t    }\n\t}\n\n\tif {[tk windowingsystem] eq \"win32\"} {\n\t    set result [::tk::accessible::check_screenreader]\n\t    if {$result > 0} {\n\t\tinterp alias {} ::ttk::radiobutton {} ::tk::radiobutton\n\t\tinterp alias {} ::ttk::checkbutton {} ::tk::checkbutton\n\t\tinterp alias {} ::ttk::spinbox {} ::tk::spinbox\n\t    }\n\t}\n\n\t# Capture value changes from spinbox widgets.\n\tbind Spinbox <Up> {+::tk::accessible::_updatescale %W Up}\n\tbind Spinbox <Down> {+::tk::accessible::_updatescale %W Down}\n\tbind TSpinbox <Up> {+::tk::accessible::_updatescale %W Up}\n\tbind TSpinbox <Down> {+::tk::accessible::_updatescale %W Down}\n\n\t# Capture notebook selection.\n\tbind TNotebook <Map> {+::ttk::notebook::enableTraversal %W}\n\tbind TNotebook <<NotebookTabChanged>> {+::tk::accessible::_updateselection %W}\n\n\t# Capture text selection in entry widgets.\n\tbind Entry <KeyPress> {+::tk::accessible::_updateselection %W}\n\tbind TEntry <KeyPress> {+::tk::accessible::_updateselection %W}\n\tbind Entry <FocusIn> {+::tk::accessible::_updateselection %W}\n\tbind TEntry {+::tk::accessible::_updateselection %W}\n\tbind Entry <Left> {+::tk::accessible::_updateselection %W}\n\tbind TEntry <Left> {+::tk::accessible::_updateselection %W}\n\tbind Entry <Right> {+::tk::accessible::_updateselection %W}\n\tbind TEntry <Right> {+::tk::accessible::_updateselection %W}\n\tbind Entry <<Selection>> {+::tk::accessible::_updateselection %W}\n\tbind TEntry <<Selection>> {+::tk::accessible::_updateselection %W}\n\n\t# Progressbar updates.\n\tbind TProgressbar <FocusIn> {+::tk::accessible::_updateselection %W}\n\n\tbind Scrollbar <Up> {+%W set [expr {[%W get] - 0.1}]; ::tk::accessible::emit_selection_change %W}\n\tbind Scrollbar <Down> {+%W set [expr {[%W get] + 0.1}]; ::tk::accessible::emit_selection_change %W}\n\tbind TScrollbar <Up> {+%W set [expr {[%W get] - 0.1}]; ::tk::accessible::emit_selection_change %W}\n\tbind TScrollbar <Down> {+%W set [expr {[%W get] + 0.1}]; ::tk::accessible::emit_selection_change %W}\n\n\tbind Dialog <Return> {+::tk::dialog::OK %W; ::tk::accessible::emit_selection_change %W}\n\tbind Dialog <Escape> {+::tk::dialog::Cancel %W; ::tk::accessible::emit_selection_change %W}\n\n\t# Help text for widgets that require additional direction\n\t# on keyboard navigation - these widgets will use standard keyboard\n\t# navigation when they obtain focus rather than the accessibility\n\t# keyboard shortcuts. We are mostly limiting the accessibility tree to one\n\t# level - toplevel window and child windows - to reduce the complexity of\n\t# the implementation, which is tied tighly to Tk windows. Component\n\t# elements of many widgets such listbox or treeview rows are not exposed as\n\t# Tk windows, and there is no simple way to expose them to the platforms'\n\t# accessibility API's directly, but they can be navigated via the keyboard\n\t# and their data (obtained via selection events) can be piped to the\n\t# screen reader for vocalization. The help text here assists the user\n\t# in switching to the standard keys for navigation as needed.\n\n\tbind Listbox <Map> {+::tk::accessible::set_acc_help %W \"To navigate, click the mouse or trackpad and then use the standard Up-Arrow and Down-Arrow keys.\"}\n\tbind Treeview <Map> {+::tk::accessible::set_acc_help %W \"To navigate, click the mouse or trackpad and then use the standard Up-Arrow and Down-Arrow keys. To open or close a tree node, click the Space key.\"}\n\tbind Entry <Map> {+::tk::accessible::set_acc_help %W \"To navigate, click the mouse or trackpad and then use standard keyboard navigation. To hear the contents of the entry field, select all.\"}\n\tbind TEntry <Map> {+::tk::accessible::set_acc_help %W \"To navigate, click the mouse or trackpad and then use standard keyboard navigation. To hear the contents of the entry field, select all.\"}\n\tbind Scale <Map> {+::tk::accessible::set_acc_help %W \"Click the right or left arrows to move the scale.\"}\n\tbind TScale <Map> {+::tk::accessible::set_acc_help %W \"Click the right or left arrows to move the scale.\"}\n\tbind Spinbox <Map> {+::tk::accessible::set_acc_help %W \"Click the up or down arrows to change the value.\"}\n\tbind TSpinbox <Map> {+::tk::accessible::set_acc_help %W \"Click the up or down arrows to change the value.\"}\n\tbind Canvas <Map> {+::tk::accessible::set_acc_help %W \"The canvas widget is not accessible.\"}\n\tbind Scrollbar <Map> {+::tk::accessible::set_acc_help %W \"Use the touchpad or mouse wheel to move the scrollbar.\"}\n\tbind TScrollbar <Map> {+::tk::accessible::set_acc_help %W \"Use the touchpad or mouse wheel to move the scrollbar.\"}\n\tbind Menubutton <Map> {+::tk::accessible::set_acc_help %W \"Use the touchpad or mouse wheel to pop up the menu.\"}\n\tbind TMenubutton <Map> {+::tk::accessible::set_acc_help %W \"Use the touchpad or mouse wheel to pop up the menu.\"}\n\tbind TNotebook <Map> {+::tk::accessible::set_acc_help %W \"Use the Tab and Right/Left arrow keys to navigate between notebook tabs.\"}\n\tbind Text <Map> {+::tk::accessible::set_acc_help %W \"Use normal keyboard shortcuts to navigate the text widget.\"}\n\n\tif {[tk windowingsystem] eq \"win32\"} {\n\t    bind all <FocusIn> {+::tk::accessible::_forceTkFocus %W}\n\t}\n\n\t# Finally, export the main commands.\n\tnamespace export set_acc_role set_acc_name set_acc_description set_acc_value set_acc_state set_acc_action set_acc_help get_acc_role get_acc_name get_acc_description get_acc_value get_acc_state get_acc_action get_acc_help add_acc_object emit_selection_change check_screenreader emit_focus_change\n\tnamespace ensemble create\n    }\n}\n\n# Add these commands to the tk command ensemble: tk accessible.\nnamespace ensemble configure tk -map \\\n    [dict merge [namespace ensemble configure tk -map] \\\n\t {accessible ::tk::accessible}]\n\n"
  },
  {
    "path": "library/bgerror.tcl",
    "content": "# bgerror.tcl --\n#\n#\tImplementation of the bgerror procedure.  It posts a dialog box with\n#\tthe error message and gives the user a chance to see a more detailed\n#\tstack trace, and possible do something more interesting with that\n#\ttrace (like save it to a log).  This is adapted from work done by\n#\tDonal K. Fellows.\n#\n# Copyright © 1998-2000 Ajuba Solutions.\n# Copyright © 2007 ActiveState Software Inc.\n# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>\n# Copyright © 2009 Pat Thoyts <patthoyts@users.sourceforge.net>\n\nnamespace eval ::tk::dialog::error {\n    namespace import -force ::tk::msgcat::*\n    namespace export bgerror\n    option add *ErrorDialog.function.text [mc \"Save To Log\"] \\\n\twidgetDefault\n    option add *ErrorDialog.function.command [namespace code SaveToLog]\n    option add *ErrorDialog*Label.font TkCaptionFont widgetDefault\n    if {[tk windowingsystem] eq \"aqua\"} {\n\toption add *ErrorDialog*background systemAlertBackgroundActive \\\n\t\twidgetDefault\n\toption add *ErrorDialog*info.text.background \\\n\t\tsystemTextBackgroundColor widgetDefault\n\toption add *ErrorDialog*Button.highlightBackground \\\n\t\tsystemAlertBackgroundActive widgetDefault\n    }\n}\n\nproc ::tk::dialog::error::Return {which code} {\n    variable button\n\n    .bgerrorDialog.$which state {active selected focus}\n    update idletasks\n    after 100\n    set button $code\n}\n\nproc ::tk::dialog::error::Details {} {\n    set w .bgerrorDialog\n    set caption [option get $w.function text {}]\n    set command [option get $w.function command {}]\n    if {($caption eq \"\") || ($command eq \"\")} {\n\tgrid forget $w.function\n    }\n    lappend command [$w.top.info.text get 1.0 end-1c]\n    $w.function configure -text $caption -command $command\n    grid $w.top.info - -sticky nsew -padx 3m -pady 3m\n}\n\nproc ::tk::dialog::error::SaveToLog {text} {\n    if {$::tcl_platform(platform) eq \"windows\"} {\n\tset allFiles *.*\n    } else {\n\tset allFiles *\n    }\n    set types [list \\\n\t    [list [mc \"Log Files\"] .log]      \\\n\t    [list [mc \"Text Files\"] .txt]     \\\n\t    [list [mc \"All Files\"] $allFiles] \\\n\t    ]\n    set filename [tk_getSaveFile -title [mc \"Select Log File\"] \\\n\t    -filetypes $types -defaultextension .log -parent .bgerrorDialog]\n    if {$filename ne {}} {\n\tset f [open $filename w]\n\tputs -nonewline $f $text\n\tclose $f\n    }\n    return\n}\n\nproc ::tk::dialog::error::Destroy {w} {\n    if {$w eq \".bgerrorDialog\"} {\n\tvariable button\n\tset button -1\n    }\n}\n\nproc ::tk::dialog::error::DeleteByProtocol {} {\n    variable button\n    set button 1\n}\n\nproc ::tk::dialog::error::ReturnInDetails w {\n    bind $w <Return> {}; # Remove this binding\n    $w invoke\n    return -code break\n}\n\n# ::tk::dialog::error::bgerror --\n#\n#\tThis is the default version of bgerror.\n#\tIt tries to execute tkerror, if that fails it posts a dialog box\n#\tcontaining the error message and gives the user a chance to ask\n#\tto see a stack trace.\n#\n# Arguments:\n#\terr - The error message.\n#\nproc ::tk::dialog::error::bgerror {err {flag 1}} {\n    global errorInfo\n    variable button\n\n    set info $errorInfo\n\n    set ret [catch {::tkerror $err} msg];\n    if {$ret != 1} {return -code $ret $msg}\n\n    # The application's tkerror either failed or was not found\n    # so we use the default dialog.  But on Aqua we cannot display\n    # the dialog if the background error occurs in an idle task\n    # being processed inside of [NSView drawRect].  In that case\n    # we post the dialog as an after task instead.\n    set windowingsystem [tk windowingsystem]\n    if {$windowingsystem eq \"aqua\"} {\n\tif $flag {\n\t    set errorInfo $info\n\t    after 500 [list bgerror \"$err\" 0]\n\t    return\n\t}\n    }\n\n    set ok [mc OK]\n    # Truncate the message if it is too wide (>maxLine characters) or\n    # too tall (>maxRows lines).  Truncation occurs at the first point at\n    # which one of those conditions is met. No trailing newline.\n    set displayedErr \"\"\n    set lines 0\n    set maxLine 45\n    set maxRows 5\n    foreach line [split $err \\n] {\n\tif {$lines > $maxRows - 1} {\n\t    # No more lines.  Append to previous line.\n\t    append displayedErr { ...}\n\t    break\n\t}\n\tif {[string length $line] > $maxLine} {\n\t    append displayedErr \"[string range $line 0 $maxLine-3]...\"\n\t    break\n\t}\n\tif {$lines > $maxRows - 2 && [string length $line] > $maxLine-4} {\n\t    append displayedErr \"[string range $line 0 $maxLine-3]...\"\n\t    break\n\t} elseif {$lines > $maxRows - 2} {\n\t    # Last line, but no break or newline.  Room to add 4 chars.\n\t    append displayedErr \"${line}\"\n\t} else {\n\t    append displayedErr \"${line}\\n\"\n\t}\n\tincr lines\n    }\n    set displayedErr [string trim $displayedErr]\n\n    set title [mc \"Application Error\"]\n    set text [mc \"Error: %1\\$s\" $displayedErr]\n    set buttons [list ok $ok dismiss [mc \"Skip Messages\"] \\\n\t\t     function [mc \"Details >>\"]]\n\n    # 1. Create the top-level window and divide it into top\n    # and bottom parts.\n\n    set dlg .bgerrorDialog\n    set bg [ttk::style lookup . -background]\n    destroy $dlg\n    toplevel $dlg -class ErrorDialog -background $bg\n    wm withdraw $dlg\n    wm title $dlg $title\n    wm iconname $dlg ErrorDialog\n    wm protocol $dlg WM_DELETE_WINDOW [namespace code DeleteByProtocol]\n\n    if {$windowingsystem eq \"aqua\"} {\n\t::tk::unsupported::MacWindowStyle style $dlg moveableAlert {}\n    } elseif {$windowingsystem eq \"x11\"} {\n\twm attributes $dlg -type dialog\n    }\n\n    ttk::frame $dlg.bot\n    ttk::frame $dlg.top\n    pack $dlg.bot -side bottom -fill both\n    pack $dlg.top -side top -fill both -expand 1\n\n    set W [ttk::frame $dlg.top.info]\n    text $W.text -setgrid 0 -height 10 -wrap char \\\n\t-yscrollcommand [list $W.scroll set]\n    if {$windowingsystem ne \"aqua\"} {\n\t$W.text configure -width 40\n    }\n\n    ttk::scrollbar $W.scroll -command [list $W.text yview]\n    pack $W.scroll -side right -fill y\n    pack $W.text -side left -expand yes -fill both\n    $W.text insert 0.0 \"$err\\n$info\"\n    $W.text mark set insert 0.0\n    bind $W.text <Button-1> {focus %W}\n    $W.text configure -state disabled\n\n    # 2. Fill the top part with bitmap and message\n\n    # Max-width of message is the width of the screen...\n    set wrapwidth [winfo screenwidth $dlg]\n    # ...minus the width of the icon, padding and a fudge factor for\n    # the window manager decorations and aesthetics.\n    set wrapwidth [expr {$wrapwidth-60-[winfo pixels $dlg 9m]}]\n    ttk::label $dlg.msg -justify left -text $text -wraplength $wrapwidth\n    ttk::label $dlg.bitmap -image ::tk::icons::error\n\n    grid $dlg.bitmap $dlg.msg -in $dlg.top -row 0 -padx 3m -pady 3m\n    grid configure       $dlg.bitmap -sticky ne\n    grid configure\t $dlg.msg -sticky nsw -padx {0 3m}\n    grid rowconfigure\t $dlg.top 1 -weight 1\n    grid columnconfigure $dlg.top 1 -weight 1\n\n    # 3. Create a row of buttons at the bottom of the dialog.\n\n    set i 0\n    foreach {name caption} $buttons {\n\tttk::button $dlg.$name -text $caption -default normal \\\n\t    -command [namespace code [list set button $i]]\n\tgrid $dlg.$name -in $dlg.bot -column $i -row 0 -sticky ew -padx 7.5p\n\tgrid columnconfigure $dlg.bot $i -weight 1\n\t# We boost the size of some Mac buttons for l&f\n\tif {$windowingsystem eq \"aqua\"} {\n\t    if {($name eq \"ok\") || ($name eq \"dismiss\")} {\n\t\tgrid columnconfigure $dlg.bot $i -minsize 90\n\t    }\n\t    grid configure $dlg.$name -pady 7\n\t}\n\tincr i\n    }\n    # The \"OK\" button is the default for this dialog.\n    $dlg.ok configure -default active\n\n    bind $dlg <Return>\t[namespace code {Return ok 0}]\n    bind $dlg <Escape>\t[namespace code {Return dismiss 1}]\n    bind $dlg <Destroy>\t[namespace code {Destroy %W}]\n    bind $dlg.function <Return>\t[namespace code {ReturnInDetails %W}]\n    $dlg.function configure -command [namespace code Details]\n\n    # 6. Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $dlg\n\n    # 7. Set a grab and claim the focus too.\n\n    ::tk::SetFocusGrab $dlg $dlg.ok\n\n    # 8. Ensure that we are topmost.\n\n    raise $dlg\n    if {[tk windowingsystem] eq \"win32\"} {\n\t# Place it topmost if we aren't at the top of the stacking\n\t# order to ensure that it's seen\n\tif {[lindex [wm stackorder .] end] ne \"$dlg\"} {\n\t    wm attributes $dlg -topmost 1\n\t}\n    }\n\n    # 9. Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait [namespace which -variable button]\n    set copy $button; # Save a copy...\n\n    ::tk::RestoreFocusGrab $dlg $dlg.ok destroy\n\n    if {$copy == 1} {\n\treturn -code break\n    }\n}\n\nnamespace eval :: {\n    # Fool the indexer\n    proc bgerror err {}\n    rename bgerror {}\n    namespace import ::tk::dialog::error::bgerror\n}\n"
  },
  {
    "path": "library/button.tcl",
    "content": "# button.tcl --\n#\n# This file defines the default bindings for Tk label, button,\n# checkbutton, and radiobutton widgets and provides procedures\n# that help in implementing those bindings.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 2002 ActiveState Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for buttons.\n#-------------------------------------------------------------------------\n\nif {[tk windowingsystem] eq \"aqua\"} {\n\n    bind Radiobutton <Enter> {\n\ttk::ButtonEnter %W\n    }\n    bind Radiobutton <Button-1> {\n\ttk::ButtonDown %W\n    }\n    bind Radiobutton <ButtonRelease-1> {\n\ttk::ButtonUp %W\n    }\n    bind Checkbutton <Enter> {\n\ttk::ButtonEnter %W\n    }\n    bind Checkbutton <Button-1> {\n\ttk::ButtonDown %W\n    }\n    bind Checkbutton <ButtonRelease-1> {\n\ttk::ButtonUp %W\n    }\n    bind Checkbutton <Leave> {\n\ttk::ButtonLeave %W\n    }\n}\nif {\"win32\" eq [tk windowingsystem]} {\n    bind Checkbutton <=> {\n\ttk::CheckRadioInvoke %W select\n    }\n    bind Checkbutton <+> {\n\ttk::CheckRadioInvoke %W select\n    }\n    bind Checkbutton <minus> {\n\ttk::CheckRadioInvoke %W deselect\n    }\n    bind Checkbutton <Button-1> {\n\ttk::CheckRadioDown %W\n    }\n    bind Checkbutton <ButtonRelease-1> {\n\ttk::ButtonUp %W\n    }\n    bind Checkbutton <Enter> {\n\ttk::CheckRadioEnter %W\n    }\n    bind Checkbutton <Leave> {\n\ttk::ButtonLeave %W\n    }\n\n    bind Radiobutton <Button-1> {\n\ttk::CheckRadioDown %W\n    }\n    bind Radiobutton <ButtonRelease-1> {\n\ttk::ButtonUp %W\n    }\n    bind Radiobutton <Enter> {\n\ttk::CheckRadioEnter %W\n    }\n}\nif {\"x11\" eq [tk windowingsystem]} {\n    bind Checkbutton <Return> {\n\tif {!$tk_strictMotif} {\n\t    tk::CheckInvoke %W\n\t}\n    }\n    bind Radiobutton <Return> {\n\tif {!$tk_strictMotif} {\n\t    tk::CheckRadioInvoke %W\n\t}\n    }\n    bind Checkbutton <Button-1> {\n\ttk::CheckInvoke %W\n    }\n    bind Radiobutton <Button-1> {\n\ttk::CheckRadioInvoke %W\n    }\n    bind Checkbutton <Enter> {\n\ttk::CheckEnter %W\n    }\n    bind Radiobutton <Enter> {\n\ttk::ButtonEnter %W\n    }\n    bind Checkbutton <Leave> {\n\ttk::CheckLeave %W\n    }\n}\n\nbind Button <space> {\n    tk::ButtonInvoke %W\n}\nbind Checkbutton <space> {\n    tk::CheckRadioInvoke %W\n}\nbind Radiobutton <space> {\n    tk::CheckRadioInvoke %W\n}\nbind Button <<Invoke>> {\n    tk::ButtonInvoke %W\n}\nbind Checkbutton <<Invoke>> {\n    tk::CheckRadioInvoke %W\n}\nbind Radiobutton <<Invoke>> {\n    tk::CheckRadioInvoke %W\n}\n\nbind Button <FocusIn> {}\nbind Button <Enter> {\n    tk::ButtonEnter %W\n}\nbind Button <Leave> {\n    tk::ButtonLeave %W\n}\nbind Button <Button-1> {\n    tk::ButtonDown %W\n}\nbind Button <ButtonRelease-1> {\n    tk::ButtonUp %W\n}\n\nbind Checkbutton <FocusIn> {}\n\nbind Radiobutton <FocusIn> {}\nbind Radiobutton <Leave> {\n    tk::ButtonLeave %W\n}\n\nif {\"win32\" eq [tk windowingsystem]} {\n\n#########################\n# Windows implementation\n#########################\n\n# ::tk::ButtonEnter --\n# The procedure below is invoked when the mouse pointer enters a\n# button widget.  It records the button we're in and changes the\n# state of the button to active unless the button is disabled.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonEnter w {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\n\t# If the mouse button is down, set the relief to sunken on entry.\n\t# Overwise, if there's an -overrelief value, set the relief to that.\n\n\tset Priv($w,relief) [$w cget -relief]\n\tif {$Priv(buttonWindow) eq $w} {\n\t    $w configure -relief sunken -state active\n\t    set Priv($w,prelief) sunken\n\t} elseif {[set over [$w cget -overrelief]] ne \"\"} {\n\t    $w configure -relief $over\n\t    set Priv($w,prelief) $over\n\t}\n    }\n    set Priv(window) $w\n}\n\n# ::tk::ButtonLeave --\n# The procedure below is invoked when the mouse pointer leaves a\n# button widget.  It changes the state of the button back to inactive.\n# Restore any modified relief too.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonLeave w {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t$w configure -state normal\n    }\n\n    # Restore the original button relief if it was changed by Tk.\n    # That is signaled by the existence of Priv($w,prelief).\n\n    if {[info exists Priv($w,relief)]} {\n\tif {[info exists Priv($w,prelief)] && \\\n\t\t$Priv($w,prelief) eq [$w cget -relief]} {\n\t    $w configure -relief $Priv($w,relief)\n\t}\n\tunset -nocomplain Priv($w,relief) Priv($w,prelief)\n    }\n\n    set Priv(window) \"\"\n}\n\n# ::tk::ButtonDown --\n# The procedure below is invoked when the mouse button is pressed in\n# a button widget.  It records the fact that the mouse is in the button,\n# saves the button's relief so it can be restored later, and changes\n# the relief to sunken.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonDown w {\n    variable ::tk::Priv\n\n    # Only save the button's relief if it does not yet exist.  If there\n    # is an overrelief setting, Priv($w,relief) will already have been set,\n    # and the current value of the -relief option will be incorrect.\n\n    if {![info exists Priv($w,relief)]} {\n\tset Priv($w,relief) [$w cget -relief]\n    }\n\n    if {[$w cget -state] ne \"disabled\"} {\n\tset Priv(buttonWindow) $w\n\t$w configure -relief sunken -state active\n\tset Priv($w,prelief) sunken\n\n\t# If this button has a repeatdelay set up, get it going with an after\n\tafter cancel $Priv(afterId)\n\tset delay [$w cget -repeatdelay]\n\tset Priv(repeated) 0\n\tif {$delay > 0} {\n\t    set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]\n\t}\n    }\n}\n\n# ::tk::ButtonUp --\n# The procedure below is invoked when the mouse button is released\n# in a button widget.  It restores the button's relief and invokes\n# the command as long as the mouse hasn't left the button.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonUp w {\n    variable ::tk::Priv\n    if {$Priv(buttonWindow) eq $w} {\n\tset Priv(buttonWindow) \"\"\n\n\t# Restore the button's relief if it was cached.\n\n\tif {[info exists Priv($w,relief)]} {\n\t    if {[info exists Priv($w,prelief)] && \\\n\t\t    $Priv($w,prelief) eq [$w cget -relief]} {\n\t\t$w configure -relief $Priv($w,relief)\n\t    }\n\t    unset -nocomplain Priv($w,relief) Priv($w,prelief)\n\t}\n\n\t# Clean up the after event from the auto-repeater\n\tafter cancel $Priv(afterId)\n\n\tif {$Priv(window) eq $w && [$w cget -state] ne \"disabled\"} {\n\t    $w configure -state normal\n\n\t    # Only invoke the command if it wasn't already invoked by the\n\t    # auto-repeater functionality\n\t    if { $Priv(repeated) == 0 } {\n\t\tuplevel #0 [list $w invoke]\n\t    }\n\t}\n    }\n}\n\n# ::tk::CheckRadioEnter --\n# The procedure below is invoked when the mouse pointer enters a\n# checkbutton or radiobutton widget.  It records the button we're in\n# and changes the state of the button to active unless the button is\n# disabled.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::CheckRadioEnter w {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\tif {$Priv(buttonWindow) eq $w} {\n\t    $w configure -state active\n\t}\n\tif {[set over [$w cget -overrelief]] ne \"\"} {\n\t    set Priv($w,relief)  [$w cget -relief]\n\t    set Priv($w,prelief) $over\n\t    $w configure -relief $over\n\t}\n    }\n    set Priv(window) $w\n}\n\n# ::tk::CheckRadioDown --\n# The procedure below is invoked when the mouse button is pressed in\n# a button widget.  It records the fact that the mouse is in the button,\n# saves the button's relief so it can be restored later, and changes\n# the relief to sunken.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::CheckRadioDown w {\n    variable ::tk::Priv\n    if {![info exists Priv($w,relief)]} {\n\tset Priv($w,relief) [$w cget -relief]\n    }\n    if {[$w cget -state] ne \"disabled\"} {\n\tset Priv(buttonWindow) $w\n\tset Priv(repeated) 0\n\t$w configure -state active\n    }\n}\n\n}\n\nif {\"x11\" eq [tk windowingsystem]} {\n\n#####################\n# Unix implementation\n#####################\n\n# ::tk::ButtonEnter --\n# The procedure below is invoked when the mouse pointer enters a\n# button widget.  It records the button we're in and changes the\n# state of the button to active unless the button is disabled.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonEnter {w} {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t# On unix the state is active just with mouse-over\n\t$w configure -state active\n\n\t# If the mouse button is down, set the relief to sunken on entry.\n\t# Overwise, if there's an -overrelief value, set the relief to that.\n\n\tset Priv($w,relief) [$w cget -relief]\n\tif {$Priv(buttonWindow) eq $w} {\n\t    $w configure -relief sunken\n\t    set Priv($w,prelief) sunken\n\t} elseif {[set over [$w cget -overrelief]] ne \"\"} {\n\t    $w configure -relief $over\n\t    set Priv($w,prelief) $over\n\t}\n    }\n    set Priv(window) $w\n}\n\n# ::tk::ButtonLeave --\n# The procedure below is invoked when the mouse pointer leaves a\n# button widget.  It changes the state of the button back to inactive.\n# Restore any modified relief too.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonLeave w {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t$w configure -state normal\n    }\n\n    # Restore the original button relief if it was changed by Tk.\n    # That is signaled by the existence of Priv($w,prelief).\n\n    if {[info exists Priv($w,relief)]} {\n\tif {[info exists Priv($w,prelief)] && \\\n\t\t$Priv($w,prelief) eq [$w cget -relief]} {\n\t    $w configure -relief $Priv($w,relief)\n\t}\n\tunset -nocomplain Priv($w,relief) Priv($w,prelief)\n    }\n\n    set Priv(window) \"\"\n}\n\n# ::tk::ButtonDown --\n# The procedure below is invoked when the mouse button is pressed in\n# a button widget.  It records the fact that the mouse is in the button,\n# saves the button's relief so it can be restored later, and changes\n# the relief to sunken.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonDown w {\n    variable ::tk::Priv\n\n    # Only save the button's relief if it does not yet exist.  If there\n    # is an overrelief setting, Priv($w,relief) will already have been set,\n    # and the current value of the -relief option will be incorrect.\n\n    if {![info exists Priv($w,relief)]} {\n\tset Priv($w,relief) [$w cget -relief]\n    }\n\n    if {[$w cget -state] ne \"disabled\"} {\n\tset Priv(buttonWindow) $w\n\t$w configure -relief sunken\n\tset Priv($w,prelief) sunken\n\n\t# If this button has a repeatdelay set up, get it going with an after\n\tafter cancel $Priv(afterId)\n\tset delay [$w cget -repeatdelay]\n\tset Priv(repeated) 0\n\tif {$delay > 0} {\n\t    set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]\n\t}\n    }\n}\n\n# ::tk::ButtonUp --\n# The procedure below is invoked when the mouse button is released\n# in a button widget.  It restores the button's relief and invokes\n# the command as long as the mouse hasn't left the button.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonUp w {\n    variable ::tk::Priv\n    if {$w eq $Priv(buttonWindow)} {\n\tset Priv(buttonWindow) \"\"\n\n\t# Restore the button's relief if it was cached.\n\n\tif {[info exists Priv($w,relief)]} {\n\t    if {[info exists Priv($w,prelief)] && \\\n\t\t    $Priv($w,prelief) eq [$w cget -relief]} {\n\t\t$w configure -relief $Priv($w,relief)\n\t    }\n\t    unset -nocomplain Priv($w,relief) Priv($w,prelief)\n\t}\n\n\t# Clean up the after event from the auto-repeater\n\tafter cancel $Priv(afterId)\n\n\tif {$Priv(window) eq $w && [$w cget -state] ne \"disabled\"} {\n\t    # Only invoke the command if it wasn't already invoked by the\n\t    # auto-repeater functionality\n\t    if { $Priv(repeated) == 0 } {\n\t\tuplevel #0 [list $w invoke]\n\t    }\n\t}\n    }\n}\n\n}\n\nif {[tk windowingsystem] eq \"aqua\"} {\n\n####################\n# Mac implementation\n####################\n\n# ::tk::ButtonEnter --\n# The procedure below is invoked when the mouse pointer enters a\n# button widget.  It records the button we're in and changes the\n# state of the button to active unless the button is disabled.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonEnter {w} {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\n\t# If there's an -overrelief value, set the relief to that.\n\n\tif {$Priv(buttonWindow) eq $w} {\n\t    $w configure -state active\n\t} elseif {[set over [$w cget -overrelief]] ne \"\"} {\n\t    set Priv($w,relief)  [$w cget -relief]\n\t    set Priv($w,prelief) $over\n\t    $w configure -relief $over\n\t}\n    }\n    set Priv(window) $w\n}\n\n# ::tk::ButtonLeave --\n# The procedure below is invoked when the mouse pointer leaves a\n# button widget.  It changes the state of the button back to\n# inactive.  If we're leaving the button window with a mouse button\n# pressed (Priv(buttonWindow) == $w), restore the relief of the\n# button too.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonLeave w {\n    variable ::tk::Priv\n    if {$w eq $Priv(buttonWindow)} {\n\t$w configure -state normal\n    }\n\n    # Restore the original button relief if it was changed by Tk.\n    # That is signaled by the existence of Priv($w,prelief).\n\n    if {[info exists Priv($w,relief)]} {\n\tif {[info exists Priv($w,prelief)] && \\\n\t\t$Priv($w,prelief) eq [$w cget -relief]} {\n\t    $w configure -relief $Priv($w,relief)\n\t}\n\tunset -nocomplain Priv($w,relief) Priv($w,prelief)\n    }\n\n    set Priv(window) \"\"\n}\n\n# ::tk::ButtonDown --\n# The procedure below is invoked when the mouse button is pressed in\n# a button widget.  It records the fact that the mouse is in the button,\n# saves the button's relief so it can be restored later, and changes\n# the relief to sunken.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonDown w {\n    variable ::tk::Priv\n\n    if {[$w cget -state] ne \"disabled\"} {\n\tset Priv(buttonWindow) $w\n\t$w configure -state active\n\n\t# If this button has a repeatdelay set up, get it going with an after\n\tafter cancel $Priv(afterId)\n\tset Priv(repeated) 0\n\tif { ![catch {$w cget -repeatdelay} delay] } {\n\t    if {$delay > 0} {\n\t\tset Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]\n\t    }\n\t}\n    }\n}\n\n# ::tk::ButtonUp --\n# The procedure below is invoked when the mouse button is released\n# in a button widget.  It restores the button's relief and invokes\n# the command as long as the mouse hasn't left the button.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonUp w {\n    variable ::tk::Priv\n    if {$Priv(buttonWindow) eq $w} {\n\tset Priv(buttonWindow) \"\"\n\t$w configure -state normal\n\n\t# Restore the button's relief if it was cached.\n\n\tif {[info exists Priv($w,relief)]} {\n\t    if {[info exists Priv($w,prelief)] && \\\n\t\t    $Priv($w,prelief) eq [$w cget -relief]} {\n\t\t$w configure -relief $Priv($w,relief)\n\t    }\n\t    unset -nocomplain Priv($w,relief) Priv($w,prelief)\n\t}\n\n\t# Clean up the after event from the auto-repeater\n\tafter cancel $Priv(afterId)\n\n\tif {$Priv(window) eq $w && [$w cget -state] ne \"disabled\"} {\n\t    # Only invoke the command if it wasn't already invoked by the\n\t    # auto-repeater functionality\n\t    if { $Priv(repeated) == 0 } {\n\t\tuplevel #0 [list $w invoke]\n\t    }\n\t}\n    }\n}\n\n}\n\n##################\n# Shared routines\n##################\n\n# ::tk::ButtonInvoke --\n# The procedure below is called when a button is invoked through\n# the keyboard.  It simulate a press of the button via the mouse.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::ButtonInvoke w {\n    if {[winfo exists $w] && [$w cget -state] ne \"disabled\"} {\n\tset oldRelief [$w cget -relief]\n\tset oldState [$w cget -state]\n\t$w configure -state active -relief sunken\n\tafter 100 [list ::tk::ButtonInvokeEnd $w $oldState $oldRelief]\n    }\n}\n\n# ::tk::ButtonInvokeEnd --\n# The procedure below is called after a button is invoked through\n# the keyboard.  It simulate a release of the button via the mouse.\n#\n# Arguments:\n# w -         The name of the widget.\n# oldState -  Old state to be set back.\n# oldRelief - Old relief to be set back.\n\nproc ::tk::ButtonInvokeEnd {w oldState oldRelief} {\n    if {[winfo exists $w]} {\n\t$w configure -state $oldState -relief $oldRelief\n\tuplevel #0 [list $w invoke]\n    }\n}\n\n# ::tk::ButtonAutoInvoke --\n#\n#\tInvoke an auto-repeating button, and set it up to continue to repeat.\n#\n# Arguments:\n#\tw\tbutton to invoke.\n#\n# Results:\n#\tNone.\n#\n# Side effects:\n#\tMay create an after event to call ::tk::ButtonAutoInvoke.\n\nproc ::tk::ButtonAutoInvoke {w} {\n    variable ::tk::Priv\n    after cancel $Priv(afterId)\n    set delay [$w cget -repeatinterval]\n    if {$Priv(window) eq $w} {\n\tincr Priv(repeated)\n\tuplevel #0 [list $w invoke]\n    }\n    if {$delay > 0} {\n\tset Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]\n    }\n}\n\n# ::tk::CheckRadioInvoke --\n# The procedure below is invoked when the mouse button is pressed in\n# a checkbutton or radiobutton widget, or when the widget is invoked\n# through the keyboard.  It invokes the widget if it\n# isn't disabled.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n# cmd -\t\tThe subcommand to invoke (one of invoke, select, or deselect).\n\nproc ::tk::CheckRadioInvoke {w {cmd invoke}} {\n    if {[$w cget -state] ne \"disabled\"} {\n\tuplevel #0 [list $w $cmd]\n    }\n}\n\n# Special versions of the handlers for checkbuttons on Unix that do the magic\n# to make things work right when the checkbutton indicator is hidden;\n# radiobuttons don't need this complexity.\n\n# ::tk::CheckInvoke --\n# The procedure below invokes the checkbutton, like ButtonInvoke, but handles\n# what to do when the checkbutton indicator is missing. Only used on Unix.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::CheckInvoke {w} {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t# Additional logic to switch the \"selected\" colors around if necessary\n\t# (when we're indicator-less).\n\n\tif {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {\n\t    if {[$w cget -selectcolor] eq $Priv($w,aselectcolor)} {\n\t\t$w configure -selectcolor $Priv($w,selectcolor)\n\t    } else {\n\t\t$w configure -selectcolor $Priv($w,aselectcolor)\n\t    }\n\t}\n\tuplevel #0 [list $w invoke]\n    }\n}\n\n# ::tk::CheckEnter --\n# The procedure below enters the checkbutton, like ButtonEnter, but handles\n# what to do when the checkbutton indicator is missing. Only used on Unix.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::CheckEnter {w} {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t# On unix the state is active just with mouse-over\n\t$w configure -state active\n\n\t# If the mouse button is down, set the relief to sunken on entry.\n\t# Overwise, if there's an -overrelief value, set the relief to that.\n\n\tset Priv($w,relief) [$w cget -relief]\n\tif {$Priv(buttonWindow) eq $w} {\n\t    $w configure -relief sunken\n\t    set Priv($w,prelief) sunken\n\t} elseif {[set over [$w cget -overrelief]] ne \"\"} {\n\t    $w configure -relief $over\n\t    set Priv($w,prelief) $over\n\t}\n\n\t# Compute what the \"selected and active\" color should be.\n\n\tif {![$w cget -indicatoron] && [$w cget -selectcolor] ne \"\"} {\n\t    set Priv($w,selectcolor) [$w cget -selectcolor]\n\t    lassign [winfo rgb $w [$w cget -selectcolor]]      r1 g1 b1\n\t    lassign [winfo rgb $w [$w cget -activebackground]] r2 g2 b2\n\t    set Priv($w,aselectcolor) \\\n\t\t[format \"#%04x%04x%04x\" [expr {($r1+$r2)/2}] \\\n\t\t     [expr {($g1+$g2)/2}] [expr {($b1+$b2)/2}]]\n\t    # use uplevel to work with other var resolvers\n\t    if {[uplevel #0 [list set [$w cget -variable]]]\n\t\t eq [$w cget -onvalue]} {\n\t\t$w configure -selectcolor $Priv($w,aselectcolor)\n\t    }\n\t}\n    }\n    set Priv(window) $w\n}\n\n# ::tk::CheckLeave --\n# The procedure below leaves the checkbutton, like ButtonLeave, but handles\n# what to do when the checkbutton indicator is missing. Only used on Unix.\n#\n# Arguments:\n# w -\t\tThe name of the widget.\n\nproc ::tk::CheckLeave {w} {\n    variable ::tk::Priv\n    if {[$w cget -state] ne \"disabled\"} {\n\t$w configure -state normal\n    }\n\n    # Restore the original button \"selected\" color; but only if the user\n    # has not changed it in the meantime.\n\n    if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {\n\tif {[$w cget -selectcolor] eq $Priv($w,selectcolor)\n\t\t|| ([info exist Priv($w,aselectcolor)] &&\n\t\t    [$w cget -selectcolor] eq $Priv($w,aselectcolor))} {\n\t    $w configure -selectcolor $Priv($w,selectcolor)\n\t}\n    }\n    unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor)\n\n    # Restore the original button relief if it was changed by Tk. That is\n    # signaled by the existence of Priv($w,prelief).\n\n    if {[info exists Priv($w,relief)]} {\n\tif {[info exists Priv($w,prelief)] && \\\n\t\t$Priv($w,prelief) eq [$w cget -relief]} {\n\t    $w configure -relief $Priv($w,relief)\n\t}\n\tunset -nocomplain Priv($w,relief) Priv($w,prelief)\n    }\n\n    set Priv(window) \"\"\n}\n\nreturn\n\f\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "library/choosedir.tcl",
    "content": "# choosedir.tcl --\n#\n#\tChoose directory dialog implementation for Unix/Mac.\n#\n# Copyright © 1998-2000 Scriptics Corporation.\n# All rights reserved.\n\n# Make sure the tk::dialog namespace, in which all dialogs should live, exists\nnamespace eval ::tk::dialog {}\nnamespace eval ::tk::dialog::file {}\n\n# Make the chooseDir namespace inside the dialog namespace\nnamespace eval ::tk::dialog::file::chooseDir {\n    namespace import -force ::tk::msgcat::*\n}\n\n# ::tk::dialog::file::chooseDir:: --\n#\n#\tImplements the TK directory selection dialog.\n#\n# Arguments:\n#\targs\t\tOptions parsed by the procedure.\n#\nproc ::tk::dialog::file::chooseDir:: {args} {\n    variable ::tk::Priv\n    set dataName __tk_choosedir\n    upvar ::tk::dialog::file::$dataName data\n    Config $dataName $args\n\n    if {$data(-parent) eq \".\"} {\n\tset w .$dataName\n    } else {\n\tset w $data(-parent).$dataName\n    }\n\n    # (re)create the dialog box if necessary\n    #\n    if {![winfo exists $w]} {\n\t::tk::dialog::file::Create $w TkChooseDir\n    } elseif {[winfo class $w] ne \"TkChooseDir\"} {\n\tdestroy $w\n\t::tk::dialog::file::Create $w TkChooseDir\n    } else {\n\tset data(dirMenuBtn) $w.contents.f1.menu\n\tset data(dirMenu) $w.contents.f1.menu.menu\n\tset data(upBtn) $w.contents.f1.up\n\tset data(icons) $w.contents.icons\n\tset data(ent) $w.contents.f2.ent\n\tset data(okBtn) $w.contents.f2.ok\n\tset data(cancelBtn) $w.contents.f2.cancel\n\tset data(hiddenBtn) $w.contents.f2.hidden\n    }\n    if {$::tk::dialog::file::showHiddenBtn} {\n\t$data(hiddenBtn) configure -state normal\n\tgrid $data(hiddenBtn)\n    } else {\n\t$data(hiddenBtn) configure -state disabled\n\tgrid remove $data(hiddenBtn)\n    }\n\n    # When using -mustexist, manage the OK button state for validity\n    $data(okBtn) configure -state normal\n    if {$data(-mustexist)} {\n\t$data(ent) configure -validate key \\\n\t    -validatecommand [list ::tk::dialog::file::chooseDir::IsOK? $w %P]\n    } else {\n\t$data(ent) configure -validate none\n    }\n\n    # Dialog boxes should be transient with respect to their parent,\n    # so that they will always stay on top of their parent window.  However,\n    # some window managers will create the window as withdrawn if the parent\n    # window is withdrawn or iconified.  Combined with the grab we put on the\n    # window, this can hang the entire application.  Therefore we only make\n    # the dialog transient if the parent is viewable.\n\n    if {[winfo viewable [winfo toplevel $data(-parent)]] } {\n\twm transient $w $data(-parent)\n    }\n\n    trace add variable data(selectPath) write \\\n\t    [list ::tk::dialog::file::SetPath $w]\n    $data(dirMenuBtn) configure \\\n\t    -textvariable ::tk::dialog::file::${dataName}(selectPath)\n\n    set data(filter) \"*\"\n    set data(previousEntryText) \"\"\n    ::tk::dialog::file::UpdateWhenIdle $w\n\n    # Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w widget $data(-parent)\n    wm title $w $data(-title)\n\n    # Set a grab and claim the focus too.\n\n    ::tk::SetFocusGrab $w $data(ent)\n    $data(ent) delete 0 end\n    $data(ent) insert 0 $data(selectPath)\n    $data(ent) selection range 0 end\n    $data(ent) icursor end\n\n    # Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait ::tk::Priv(selectFilePath)\n\n    ::tk::RestoreFocusGrab $w $data(ent) withdraw\n\n    # Cleanup traces on selectPath variable\n    #\n\n    foreach trace [trace info variable data(selectPath)] {\n\ttrace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]\n    }\n    if {[winfo exists $data(dirMenuBtn)]} {\n\t$data(dirMenuBtn) configure -textvariable {}\n    }\n\n    # Return value to user\n    #\n\n    return $Priv(selectFilePath)\n}\n\n# ::tk::dialog::file::chooseDir::Config --\n#\n#\tConfigures the Tk choosedir dialog according to the argument list\n#\nproc ::tk::dialog::file::chooseDir::Config {dataName argList} {\n    upvar ::tk::dialog::file::$dataName data\n\n    # 0: Delete all variable that were set on data(selectPath) the\n    # last time the file dialog is used. The traces may cause troubles\n    # if the dialog is now used with a different -parent option.\n    #\n    foreach trace [trace info variable data(selectPath)] {\n\ttrace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]\n    }\n\n    # 1: the configuration specs\n    #\n    set specs {\n\t{-mustexist \"\" \"\" 0}\n\t{-initialdir \"\" \"\" \"\"}\n\t{-parent \"\" \"\" \".\"}\n\t{-title \"\" \"\" \"\"}\n    }\n\n    # 2: default values depending on the type of the dialog\n    #\n    if {![info exists data(selectPath)]} {\n\t# first time the dialog has been popped up\n\tset data(selectPath) [pwd]\n    }\n\n    # 3: parse the arguments\n    #\n    tclParseConfigSpec ::tk::dialog::file::$dataName $specs \"\" $argList\n\n    if {$data(-title) eq \"\"} {\n\tset data(-title) \"[mc \"Choose Directory\"]\"\n    }\n\n    # Stub out the -multiple value for the dialog; it doesn't make sense for\n    # choose directory dialogs, but we have to have something there because we\n    # share so much code with the file dialogs.\n    set data(-multiple) 0\n\n    # 4: set the default directory and selection according to the -initial\n    #    settings\n    #\n    if {$data(-initialdir) ne \"\"} {\n\t# Ensure that initialdir is an absolute path name.\n\tif {[file isdirectory $data(-initialdir)]} {\n\t    set old [pwd]\n\t    cd $data(-initialdir)\n\t    set data(selectPath) [pwd]\n\t    cd $old\n\t} else {\n\t    set data(selectPath) [pwd]\n\t}\n    }\n\n    if {![winfo exists $data(-parent)]} {\n\treturn -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \\\n\t    \"bad window path name \\\"$data(-parent)\\\"\"\n    }\n}\n\n# Gets called when user presses Return in the \"Selection\" entry or presses OK.\n#\nproc ::tk::dialog::file::chooseDir::OkCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    # This is the brains behind selecting non-existant directories.  Here's\n    # the flowchart:\n    # 1.  If the icon list has a selection, join it with the current dir,\n    #     and return that value.\n    # 1a.  If the icon list does not have a selection ...\n    # 2.  If the entry is empty, do nothing.\n    # 3.  If the entry contains an invalid directory, then...\n    # 3a.   If the value is the same as last time through here, end dialog.\n    # 3b.   If the value is different than last time, save it and return.\n    # 4.  If entry contains a valid directory, then...\n    # 4a.   If the value is the same as the current directory, end dialog.\n    # 4b.   If the value is different from the current directory, change to\n    #       that directory.\n\n    set selection [$data(icons) selection get]\n    if {[llength $selection] != 0} {\n\tset iconText [$data(icons) get [lindex $selection 0]]\n\tset iconText [file join $data(selectPath) $iconText]\n\tDone $w $iconText\n    } else {\n\tset text [$data(ent) get]\n\tif {$text eq \"\"} {\n\t    return\n\t}\n\tset text [file join {*}[file split [string trim $text]]]\n\tif {![file exists $text] || ![file isdirectory $text]} {\n\t    # Entry contains an invalid directory.  If it's the same as the\n\t    # last time they came through here, reset the saved value and end\n\t    # the dialog.  Otherwise, save the value (so we can do this test\n\t    # next time).\n\t    if {$text eq $data(previousEntryText)} {\n\t\tset data(previousEntryText) \"\"\n\t\tDone $w $text\n\t    } else {\n\t\tset data(previousEntryText) $text\n\t    }\n\t} else {\n\t    # Entry contains a valid directory.  If it is the same as the\n\t    # current directory, end the dialog.  Otherwise, change to that\n\t    # directory.\n\t    if {$text eq $data(selectPath)} {\n\t\tDone $w $text\n\t    } else {\n\t\tset data(selectPath) $text\n\t    }\n\t}\n    }\n    return\n}\n\n# Change state of OK button to match -mustexist correctness of entry\n#\nproc ::tk::dialog::file::chooseDir::IsOK? {w text} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set ok [file isdirectory $text]\n    $data(okBtn) configure -state [expr {$ok ? \"normal\" : \"disabled\"}]\n\n    # always return 1\n    return 1\n}\n\nproc ::tk::dialog::file::chooseDir::DblClick {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    set selection [$data(icons) selection get]\n    if {[llength $selection] != 0} {\n\tset filenameFragment [$data(icons) get [lindex $selection 0]]\n\tset file $data(selectPath)\n\tif {[file isdirectory $file]} {\n\t    ::tk::dialog::file::ListInvoke $w [list $filenameFragment]\n\t    return\n\t}\n    }\n}\n\n# Gets called when user browses the IconList widget (dragging mouse, arrow\n# keys, etc)\n#\nproc ::tk::dialog::file::chooseDir::ListBrowse {w text} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {$text eq \"\"} {\n\treturn\n    }\n\n    set file [::tk::dialog::file::JoinFile $data(selectPath) $text]\n    $data(ent) delete 0 end\n    $data(ent) insert 0 $file\n}\n\n# ::tk::dialog::file::chooseDir::Done --\n#\n#\tGets called when user has input a valid filename.  Pops up a\n#\tdialog box to confirm selection when necessary. Sets the\n#\tPriv(selectFilePath) variable, which will break the \"vwait\"\n#\tloop in tk_chooseDirectory and return the selected filename to the\n#\tscript that calls tk_getOpenFile or tk_getSaveFile\n#\nproc ::tk::dialog::file::chooseDir::Done {w {selectFilePath \"\"}} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    variable ::tk::Priv\n\n    if {$selectFilePath eq \"\"} {\n\tset selectFilePath $data(selectPath)\n    }\n    if {$data(-mustexist) && ![file isdirectory $selectFilePath]} {\n\treturn\n    }\n    set Priv(selectFilePath) $selectFilePath\n}\n"
  },
  {
    "path": "library/clrpick.tcl",
    "content": "# clrpick.tcl --\n#\n#\tColor selection dialog for platforms that do not support a\n#\tstandard color selection dialog.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n# ToDo:\n#\n#\t(1): Find out how many free colors are left in the colormap and\n#\t     don't allocate too many colors.\n#\t(2): Implement HSV color selection.\n#\n\n# Make sure namespaces exist\nnamespace eval ::tk {}\nnamespace eval ::tk::dialog {}\nnamespace eval ::tk::dialog::color {\n    namespace import ::tk::msgcat::*\n}\n\n# ::tk::dialog::color:: --\n#\n#\tCreate a color dialog and let the user choose a color. This function\n#\tshould not be called directly. It is called by the tk_chooseColor\n#\tfunction when a native color selector widget does not exist\n#\nproc ::tk::dialog::color:: {args} {\n    variable ::tk::Priv\n    set dataName __tk__color\n    upvar ::tk::dialog::color::$dataName data\n    set w .$dataName\n\n    # The lines variables track the start and end indices of the line\n    # elements in the colorbar canvases.\n    set data(lines,red,start)   0\n    set data(lines,red,last)   -1\n    set data(lines,green,start) 0\n    set data(lines,green,last) -1\n    set data(lines,blue,start)  0\n    set data(lines,blue,last)  -1\n\n    # This is the actual number of lines that are drawn in each color strip.\n    # Note that the bars may be of any width.\n    # However, NUM_COLORBARS must be a number that evenly divides 256.\n    # Such as 256, 128, 64, etc.\n    set data(NUM_COLORBARS) 16\n\n    # BARS_WIDTH is the number of pixels wide the color bar portion of the\n    # canvas is. BARS_WIDTH, BARS_WIDTH * 1.25, BARS_WIDTH * 1.5, and\n    # BARS_WIDTH * 1.75 must be multiples of NUM_COLORBARS.\n    set data(BARS_WIDTH) [::tk::ScaleNum 192]\n\n    # PLGN_WIDTH is the number of pixels wide of the triangular selection\n    # polygon. This also results in the definition of the padding on the\n    # left and right sides which is half of PLGN_WIDTH. PLGN_WIDTH,\n    # PLGN_WIDTH * 1.25, PLGN_WIDTH * 1.5, and PLGN_WIDTH * 1.75 must be even.\n    set data(PLGN_WIDTH) [::tk::ScaleNum 8]\n\n    # PLGN_HEIGHT is the height of the selection polygon and the height of the\n    # selection rectangle at the bottom of the color bar. No restrictions.\n    set data(PLGN_HEIGHT) [::tk::ScaleNum 8]\n\n    Config $dataName $args\n    InitValues $dataName\n\n    set sc [winfo screen $data(-parent)]\n    set winExists [winfo exists $w]\n    if {!$winExists || $sc ne [winfo screen $w]} {\n\tif {$winExists} {\n\t    destroy $w\n\t}\n\ttoplevel $w -class TkColorDialog -screen $sc\n\tif {[tk windowingsystem] eq \"x11\"} {wm attributes $w -type dialog}\n\tBuildDialog $w\n    }\n\n    # Dialog boxes should be transient with respect to their parent,\n    # so that they will always stay on top of their parent window.  However,\n    # some window managers will create the window as withdrawn if the parent\n    # window is withdrawn or iconified.  Combined with the grab we put on the\n    # window, this can hang the entire application.  Therefore we only make\n    # the dialog transient if the parent is viewable.\n\n    if {[winfo viewable [winfo toplevel $data(-parent)]] } {\n\twm transient $w $data(-parent)\n    }\n\n    # 5. Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w widget $data(-parent)\n    wm title $w $data(-title)\n\n    # 6. Set a grab and claim the focus too.\n\n    ::tk::SetFocusGrab $w $data(okBtn)\n\n    # 7. Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait ::tk::Priv(selectColor)\n    set result $Priv(selectColor)\n    ::tk::RestoreFocusGrab $w $data(okBtn)\n    unset data\n\n    return $result\n}\n\n# ::tk::dialog::color::InitValues --\n#\n#\tGet called during initialization or when user resets NUM_COLORBARS\n#\nproc ::tk::dialog::color::InitValues {dataName} {\n    upvar ::tk::dialog::color::$dataName data\n\n    # IntensityIncr is the difference in color intensity between a colorbar\n    # and its neighbors.\n    set data(intensityIncr) [expr {256 / $data(NUM_COLORBARS)}]\n\n    # ColorbarWidth is the width of each colorbar\n    set data(colorbarWidth) [expr {$data(BARS_WIDTH) / $data(NUM_COLORBARS)}]\n\n    # Indent is the width of the space at the left and right side of the\n    # colorbar. It is always half the selector polygon width, because the\n    # polygon extends into the space.\n    set data(indent) [expr {$data(PLGN_WIDTH) / 2}]\n\n    set data(colorPad) 2\n    set data(selPad)   [expr {$data(PLGN_WIDTH) / 2}]\n\n    #\n    # minX is the x coordinate of the first colorbar\n    #\n    set data(minX) $data(indent)\n\n    #\n    # maxX is the x coordinate of the last colorbar\n    #\n    set data(maxX) [expr {$data(BARS_WIDTH) + $data(indent)-1}]\n\n    #\n    # canvasWidth is the width of the entire canvas, including the indents\n    #\n    set data(canvasWidth) [expr {$data(BARS_WIDTH) + $data(PLGN_WIDTH)}]\n\n    # Set the initial color, specified by -initialcolor, or the\n    # color chosen by the user the last time.\n    set data(selection) $data(-initialcolor)\n    set data(finalColor)  $data(-initialcolor)\n    set rgb [winfo rgb . $data(selection)]\n\n    set data(red,intensity)   [expr {[lindex $rgb 0]/0x100}]\n    set data(green,intensity) [expr {[lindex $rgb 1]/0x100}]\n    set data(blue,intensity)  [expr {[lindex $rgb 2]/0x100}]\n}\n\n# ::tk::dialog::color::Config  --\n#\n#\tParses the command line arguments to tk_chooseColor\n#\nproc ::tk::dialog::color::Config {dataName argList} {\n    variable ::tk::Priv\n    upvar ::tk::dialog::color::$dataName data\n\n    # 1: the configuration specs\n    #\n    if {[info exists Priv(selectColor)] && $Priv(selectColor) ne \"\"} {\n\tset defaultColor $Priv(selectColor)\n    } else {\n\tset defaultColor [. cget -background]\n    }\n\n    set specs [list \\\n\t    [list -initialcolor \"\" \"\" $defaultColor] \\\n\t    [list -parent \"\" \"\" \".\"] \\\n\t    [list -title \"\" \"\" [mc \"Color\"]] \\\n\t    ]\n\n    # 2: parse the arguments\n    #\n    tclParseConfigSpec ::tk::dialog::color::$dataName $specs \"\" $argList\n\n    if {$data(-title) eq \"\"} {\n\tset data(-title) \" \"\n    }\n    if {[catch {winfo rgb . $data(-initialcolor)} err]} {\n\treturn -code error -errorcode [list TK LOOKUP COLOR $data(-initialcolor)] \\\n\t    $err\n    }\n\n    if {![winfo exists $data(-parent)]} {\n\treturn -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \\\n\t    \"bad window path name \\\"$data(-parent)\\\"\"\n    }\n}\n\n# ::tk::dialog::color::BuildDialog --\n#\n#\tBuild the dialog.\n#\nproc ::tk::dialog::color::BuildDialog {w} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    # TopFrame contains the color strips and the color selection\n    #\n    set topFrame [frame $w.top -relief raised -bd 1]\n\n    # StripsFrame contains the colorstrips and the individual RGB entries\n    set stripsFrame [frame $topFrame.colorStrip]\n\n    set maxWidth [::tk::mcmaxamp &Red &Green &Blue]\n    set maxWidth [expr {$maxWidth<6 ? 6 : $maxWidth}]\n    set colorList {\n\tred   \"&Red\"\n\tgreen \"&Green\"\n\tblue  \"&Blue\"\n    }\n    foreach {color l} $colorList {\n\t# each f frame contains an [R|G|B] entry and the equiv. color strip.\n\tset f [frame $stripsFrame.$color]\n\n\t# The box frame contains the label and entry widget for an [R|G|B]\n\tset box [frame $f.box]\n\n\t::tk::AmpWidget label $box.label -text \"[mc $l]:\" \\\n\t\t-width $maxWidth -anchor ne\n\tbind $box.label <<AltUnderlined>> [list focus $box.entry]\n\n\tentry $box.entry -textvariable \\\n\t\t::tk::dialog::color::[winfo name $w]($color,intensity) \\\n\t\t-width 4\n\tpack $box.label -side left -fill y -padx 1.5p -pady 2p\n\tpack $box.entry -side left -anchor n -pady 0\n\tpack $box -side left -fill both\n\n\tset height [expr {\n\t    [winfo reqheight $box.entry] -\n\t    2*([$box.entry cget -highlightthickness] + [$box.entry cget -bd])\n\t}]\n\n\tcanvas $f.color -height $height \\\n\t\t-width $data(BARS_WIDTH) -relief sunken -bd 2\n\tcanvas $f.sel -height $data(PLGN_HEIGHT) \\\n\t\t-width $data(canvasWidth) -highlightthickness 0\n\tpack $f.color -expand yes -fill both\n\tpack $f.sel -expand yes -fill both\n\n\tpack $f -side top -fill x -padx 0 -pady 1.5p\n\n\tset data($color,entry) $box.entry\n\tset data($color,col) $f.color\n\tset data($color,sel) $f.sel\n\n\tbind $data($color,col) <Configure> \\\n\t\t[list tk::dialog::color::DrawColorScale $w $color 1]\n\tbind $data($color,col) <Enter> \\\n\t\t[list tk::dialog::color::EnterColorBar $w $color]\n\tbind $data($color,col) <Leave> \\\n\t\t[list tk::dialog::color::LeaveColorBar $w $color]\n\n\tbind $data($color,sel) <Enter> \\\n\t\t[list tk::dialog::color::EnterColorBar $w $color]\n\tbind $data($color,sel) <Leave> \\\n\t\t[list tk::dialog::color::LeaveColorBar $w $color]\n\n\tbind $box.entry <Return> [list tk::dialog::color::HandleRGBEntry $w]\n    }\n\n    pack $stripsFrame -side left -fill both -padx 3p -pady 7.5p\n\n    # The selFrame contains a frame that demonstrates the currently\n    # selected color\n    #\n    set selFrame [frame $topFrame.sel]\n    set lab [::tk::AmpWidget label $selFrame.lab \\\n\t    -text [mc \"&Selection:\"] -anchor sw]\n    set ent [entry $selFrame.ent \\\n\t    -textvariable ::tk::dialog::color::[winfo name $w](selection) \\\n\t    -width 16]\n    set f1  [frame $selFrame.f1 -relief sunken -bd 2]\n    set data(finalCanvas) [frame $f1.demo -bd 0 -width 75p -height 51p]\n\n    pack $lab $ent -side top -fill x -padx 3p -pady 1.5p\n    pack $f1 -expand yes -anchor nw -fill both -padx 4.5p -pady 7.5p\n    pack $data(finalCanvas) -expand yes -fill both\n\n    bind $ent <Return> [list tk::dialog::color::HandleSelEntry $w]\n\n    pack $selFrame -side left -fill none -anchor nw\n    pack $topFrame -side top -expand yes -fill both -anchor nw\n\n    # the botFrame frame contains the buttons\n    #\n    set botFrame [frame $w.bot -relief raised -bd 1]\n\n    ::tk::AmpWidget button $botFrame.ok     -text [mc \"&OK\"]\t\t\\\n\t    -command [list tk::dialog::color::OkCmd $w]\n    ::tk::AmpWidget button $botFrame.cancel -text [mc \"&Cancel\"]\t\\\n\t    -command [list tk::dialog::color::CancelCmd $w]\n\n    set data(okBtn)      $botFrame.ok\n    set data(cancelBtn)  $botFrame.cancel\n\n    grid x $botFrame.ok x $botFrame.cancel x -sticky ew\n    grid configure $botFrame.ok $botFrame.cancel -padx 7.5p -pady 7.5p\n    grid columnconfigure $botFrame {0 4} -weight 1 -uniform space\n    grid columnconfigure $botFrame {1 3} -weight 1 -uniform button\n    grid columnconfigure $botFrame 2 -weight 2 -uniform space\n    pack $botFrame -side bottom -fill x\n\n    # Accelerator bindings\n    bind $lab <<AltUnderlined>> [list focus $ent]\n    bind $w <Escape> [list tk::ButtonInvoke $data(cancelBtn)]\n    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]\n\n    wm protocol $w WM_DELETE_WINDOW [list tk::dialog::color::CancelCmd $w]\n}\n\n# ::tk::dialog::color::SetRGBValue --\n#\n#\tSets the current selection of the dialog box\n#\nproc ::tk::dialog::color::SetRGBValue {w color} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set data(red,intensity)   [lindex $color 0]\n    set data(green,intensity) [lindex $color 1]\n    set data(blue,intensity)  [lindex $color 2]\n\n    RedrawColorBars $w all\n\n    # Now compute the new x value of each colorbars pointer polygon\n    foreach color {red green blue} {\n\tset x [RgbToX $w $data($color,intensity)]\n\tMoveSelector $w $data($color,sel) $color $x 0\n    }\n}\n\n# ::tk::dialog::color::XToRgb --\n#\n#\tConverts a screen coordinate to intensity\n#\nproc ::tk::dialog::color::XToRgb {w x} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set x [expr {($x * $data(intensityIncr))/ $data(colorbarWidth)}]\n    if {$x > 255} {\n\tset x 255\n    }\n    return $x\n}\n\n# ::tk::dialog::color::RgbToX\n#\n#\tConverts an intensity to screen coordinate.\n#\nproc ::tk::dialog::color::RgbToX {w color} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    return [expr {($color * $data(colorbarWidth)/ $data(intensityIncr))}]\n}\n\n# ::tk::dialog::color::DrawColorScale --\n#\n#\tDraw color scale is called whenever the size of one of the color\n#\tscale canvases is changed.\n#\nproc ::tk::dialog::color::DrawColorScale {w c {create 0}} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    # col: color bar canvas\n    # sel: selector canvas\n    set col $data($c,col)\n    set sel $data($c,sel)\n\n    # First handle the case that we are creating everything for the first time.\n    if {$create} {\n\t# First remove all the lines that already exist.\n\tif { $data(lines,$c,last) > $data(lines,$c,start)} {\n\t    for {set i $data(lines,$c,start)} \\\n\t\t    {$i <= $data(lines,$c,last)} {incr i} {\n\t\t$sel delete $i\n\t    }\n\t}\n\t# Delete the selector if it exists\n\tif {[info exists data($c,index)]} {\n\t    $sel delete $data($c,index)\n\t}\n\n\t# Draw the selection polygons\n\tCreateSelector $w $sel $c\n\t$sel bind $data($c,index) <Button-1> \\\n\t\t[list tk::dialog::color::StartMove $w $sel $c %x $data(selPad) 1]\n\t$sel bind $data($c,index) <B1-Motion> \\\n\t\t[list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]\n\t$sel bind $data($c,index) <ButtonRelease-1> \\\n\t\t[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]\n\n\tset height [winfo height $col]\n\t# Create an invisible region under the colorstrip to catch mouse clicks\n\t# that aren't on the selector.\n\tset data($c,clickRegion) [$sel create rectangle 0 0 \\\n\t\t$data(canvasWidth) $height -fill {} -outline {}]\n\n\tbind $col <Button-1> \\\n\t\t[list tk::dialog::color::StartMove $w $sel $c %x $data(colorPad)]\n\tbind $col <B1-Motion> \\\n\t\t[list tk::dialog::color::MoveSelector $w $sel $c %x $data(colorPad)]\n\tbind $col <ButtonRelease-1> \\\n\t\t[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(colorPad)]\n\n\t$sel bind $data($c,clickRegion) <Button-1> \\\n\t\t[list tk::dialog::color::StartMove $w $sel $c %x $data(selPad)]\n\t$sel bind $data($c,clickRegion) <B1-Motion> \\\n\t\t[list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]\n\t$sel bind $data($c,clickRegion) <ButtonRelease-1> \\\n\t\t[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]\n    } else {\n\t# l is the canvas index of the first colorbar.\n\tset l $data(lines,$c,start)\n    }\n\n    # Draw the color bars.\n    set highlightW [expr {[$col cget -highlightthickness] + [$col cget -bd]}]\n    for {set i 0} { $i < $data(NUM_COLORBARS)} { incr i} {\n\tset intensity [expr {$i * $data(intensityIncr)}]\n\tset startx [expr {$i * $data(colorbarWidth) + $highlightW}]\n\tif {$c eq \"red\"} {\n\t    set color [format \"#%02x%02x%02x\" \\\n\t\t    $intensity $data(green,intensity) $data(blue,intensity)]\n\t} elseif {$c eq \"green\"} {\n\t    set color [format \"#%02x%02x%02x\" \\\n\t\t    $data(red,intensity) $intensity $data(blue,intensity)]\n\t} else {\n\t    set color [format \"#%02x%02x%02x\" \\\n\t\t    $data(red,intensity) $data(green,intensity) $intensity]\n\t}\n\n\tif {$create} {\n\t    set index [$col create rect $startx $highlightW \\\n\t\t    [expr {$startx +$data(colorbarWidth)}] \\\n\t\t    [expr {[winfo height $col] + $highlightW}] \\\n\t\t    -fill $color -outline $color]\n\t} else {\n\t    $col itemconfigure $l -fill $color -outline $color\n\t    incr l\n\t}\n    }\n    $sel raise $data($c,index)\n\n    if {$create} {\n\tset data(lines,$c,last) $index\n\tset data(lines,$c,start) [expr {$index - $data(NUM_COLORBARS) + 1}]\n    }\n\n    RedrawFinalColor $w\n}\n\n# ::tk::dialog::color::CreateSelector --\n#\n#\tCreates and draws the selector polygon at the position\n#\t$data($c,intensity).\n#\nproc ::tk::dialog::color::CreateSelector {w sel c } {\n    upvar ::tk::dialog::color::[winfo name $w] data\n    set data($c,index) [$sel create polygon \\\n\t    0 $data(PLGN_HEIGHT) \\\n\t    $data(PLGN_WIDTH) $data(PLGN_HEIGHT) \\\n\t    $data(indent) 0]\n    set data($c,x) [RgbToX $w $data($c,intensity)]\n    $sel move $data($c,index) $data($c,x) 0\n}\n\n# ::tk::dialog::color::RedrawFinalColor\n#\n#\tCombines the intensities of the three colors into the final color\n#\nproc ::tk::dialog::color::RedrawFinalColor {w} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set color [format \"#%02x%02x%02x\" $data(red,intensity) \\\n\t    $data(green,intensity) $data(blue,intensity)]\n\n    $data(finalCanvas) configure -bg $color\n    set data(finalColor) $color\n    set data(selection) $color\n    set data(finalRGB) [list \\\n\t    $data(red,intensity) \\\n\t    $data(green,intensity) \\\n\t    $data(blue,intensity)]\n}\n\n# ::tk::dialog::color::RedrawColorBars --\n#\n# Only redraws the colors on the color strips that were not manipulated.\n# Params: color of colorstrip that changed. If color is not [red|green|blue]\n#         Then all colorstrips will be updated\n#\nproc ::tk::dialog::color::RedrawColorBars {w colorChanged} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    switch $colorChanged {\n\tred {\n\t    DrawColorScale $w green\n\t    DrawColorScale $w blue\n\t}\n\tgreen {\n\t    DrawColorScale $w red\n\t    DrawColorScale $w blue\n\t}\n\tblue {\n\t    DrawColorScale $w red\n\t    DrawColorScale $w green\n\t}\n\tdefault {\n\t    DrawColorScale $w red\n\t    DrawColorScale $w green\n\t    DrawColorScale $w blue\n\t}\n    }\n    RedrawFinalColor $w\n}\n\n#----------------------------------------------------------------------\n#\t\t\tEvent handlers\n#----------------------------------------------------------------------\n\n# ::tk::dialog::color::StartMove --\n#\n#\tHandles a mousedown button event over the selector polygon.\n#\tAdds the bindings for moving the mouse while the button is\n#\tpressed.  Sets the binding for the button-release event.\n#\n# Params: sel is the selector canvas window, color is the color of the strip.\n#\nproc ::tk::dialog::color::StartMove {w sel color x delta {dontMove 0}} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    if {!$dontMove} {\n\tMoveSelector $w $sel $color $x $delta\n    }\n}\n\n# ::tk::dialog::color::MoveSelector --\n#\n# Moves the polygon selector so that its middle point has the same\n# x value as the specified x. If x is outside the bounds [0,255],\n# the selector is set to the closest endpoint.\n#\n# Params: sel is the selector canvas, c is [red|green|blue]\n#         x is a x-coordinate.\n#\nproc ::tk::dialog::color::MoveSelector {w sel color x delta} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    incr x -$delta\n\n    if { $x < 0 } {\n\tset x 0\n    } elseif { $x > $data(BARS_WIDTH)} {\n\tset x $data(BARS_WIDTH)\n    }\n    set diff [expr {$x - $data($color,x)}]\n    $sel move $data($color,index) $diff 0\n    set data($color,x) [expr {$data($color,x) + $diff}]\n\n    # Return the x value that it was actually set at\n    return $x\n}\n\n# ::tk::dialog::color::ReleaseMouse\n#\n# Removes mouse tracking bindings, updates the colorbars.\n#\n# Params: sel is the selector canvas, color is the color of the strip,\n#         x is the x-coord of the mouse.\n#\nproc ::tk::dialog::color::ReleaseMouse {w sel color x delta} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set x [MoveSelector $w $sel $color $x $delta]\n\n    # Determine exactly what color we are looking at.\n    set data($color,intensity) [XToRgb $w $x]\n\n    RedrawColorBars $w $color\n}\n\n# ::tk::dialog::color::ResizeColorbars --\n#\n#\tCompletely redraws the colorbars, including resizing the\n#\tcolorstrips\n#\nproc ::tk::dialog::color::ResizeColorBars {w} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    if {\n\t($data(BARS_WIDTH) < $data(NUM_COLORBARS)) ||\n\t(($data(BARS_WIDTH) % $data(NUM_COLORBARS)) != 0)\n    } then {\n\tset data(BARS_WIDTH) $data(NUM_COLORBARS)\n    }\n    InitValues [winfo name $w]\n    foreach color {red green blue} {\n\t$data($color,col) configure -width $data(canvasWidth)\n\tDrawColorScale $w $color 1\n    }\n}\n\n# ::tk::dialog::color::HandleSelEntry --\n#\n#\tHandles the return keypress event in the \"Selection:\" entry\n#\nproc ::tk::dialog::color::HandleSelEntry {w} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set text [string trim $data(selection)]\n    # Check to make sure that the color is valid\n    if {[catch {set color [winfo rgb . $text]} ]} {\n\tset data(selection) $data(finalColor)\n\treturn\n    }\n\n    set R [expr {[lindex $color 0]/0x100}]\n    set G [expr {[lindex $color 1]/0x100}]\n    set B [expr {[lindex $color 2]/0x100}]\n\n    SetRGBValue $w \"$R $G $B\"\n    set data(selection) $text\n}\n\n# ::tk::dialog::color::HandleRGBEntry --\n#\n#\tHandles the return keypress event in the R, G or B entry\n#\nproc ::tk::dialog::color::HandleRGBEntry {w} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    foreach c {red green blue} {\n\tif {[catch {\n\t    set data($c,intensity) [expr {int($data($c,intensity))}]\n\t}]} {\n\t    set data($c,intensity) 0\n\t}\n\n\tif {$data($c,intensity) < 0} {\n\t    set data($c,intensity) 0\n\t}\n\tif {$data($c,intensity) > 255} {\n\t    set data($c,intensity) 255\n\t}\n    }\n\n    SetRGBValue $w \"$data(red,intensity) \\\n\t$data(green,intensity) $data(blue,intensity)\"\n}\n\n# mouse cursor enters a color bar\n#\nproc ::tk::dialog::color::EnterColorBar {w color} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    $data($color,sel) itemconfigure $data($color,index) -fill red\n}\n\n# mouse leaves enters a color bar\n#\nproc ::tk::dialog::color::LeaveColorBar {w color} {\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    $data($color,sel) itemconfigure $data($color,index) -fill black\n}\n\n# user hits OK button\n#\nproc ::tk::dialog::color::OkCmd {w} {\n    variable ::tk::Priv\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    set Priv(selectColor) $data(finalColor)\n}\n\n# user hits Cancel button or destroys window\n#\nproc ::tk::dialog::color::CancelCmd {w} {\n    variable ::tk::Priv\n    set Priv(selectColor) \"\"\n}\n"
  },
  {
    "path": "library/comdlg.tcl",
    "content": "# comdlg.tcl --\n#\n#\tSome functions needed for the common dialog boxes. Probably need to go\n#\tin a different file.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# tclParseConfigSpec --\n#\n#\tParses a list of \"-option value\" pairs. If all options and\n#\tvalues are legal, the values are stored in\n#\t$data($option). Otherwise an error message is returned. When\n#\tan error happens, the data() array may have been partially\n#\tmodified, but all the modified members of the data(0 array are\n#\tguaranteed to have valid values. This is different than\n#\tTk_ConfigureWidget() which does not modify the value of a\n#\twidget record if any error occurs.\n#\n# Arguments:\n#\n# w = widget record to modify. Must be the pathname of a widget.\n#\n# specs = {\n#    {-commandlineswitch resourceName ResourceClass defaultValue verifier}\n#    {....}\n# }\n#\n# flags = a list of flags. Currently supported flags are:\n#     DONTSETDEFAULTS = skip default values setting\n#\n# argList = The list of  \"-option value\" pairs.\n#\nproc tclParseConfigSpec {w specs flags argList} {\n    upvar #0 $w data\n\n    # 1: Put the specs in associative arrays for faster access\n    #\n    foreach spec $specs {\n\tif {[llength $spec] < 4} {\n\t    return -code error -errorcode {TK VALUE CONFIG_SPEC} \\\n\t\t\"\\\"spec\\\" should contain 5 or 4 elements\"\n\t}\n\tset cmdsw [lindex $spec 0]\n\tset cmd($cmdsw) \"\"\n\tset rname($cmdsw)   [lindex $spec 1]\n\tset rclass($cmdsw)  [lindex $spec 2]\n\tset def($cmdsw)     [lindex $spec 3]\n\tset verproc($cmdsw) [lindex $spec 4]\n    }\n\n    if {[llength $argList] & 1} {\n\tset cmdsw [lindex $argList end]\n\tif {![info exists cmd($cmdsw)]} {\n\t    return -code error -errorcode [list TK LOOKUP OPTION $cmdsw] \\\n\t\t\"bad option \\\"$cmdsw\\\": must be [tclListValidFlags cmd]\"\n\t}\n\treturn -code error -errorcode {TK VALUE_MISSING} \\\n\t    \"value for \\\"$cmdsw\\\" missing\"\n    }\n\n    # 2: set the default values\n    #\n    if {\"DONTSETDEFAULTS\" ni $flags} {\n\tforeach cmdsw [array names cmd] {\n\t    set data($cmdsw) $def($cmdsw)\n\t}\n    }\n\n    # 3: parse the argument list\n    #\n    foreach {cmdsw value} $argList {\n\tif {![info exists cmd($cmdsw)]} {\n\t    return -code error -errorcode [list TK LOOKUP OPTION $cmdsw] \\\n\t\t\"bad option \\\"$cmdsw\\\": must be [tclListValidFlags cmd]\"\n\t}\n\tset data($cmdsw) $value\n    }\n\n    # Done!\n}\n\nproc tclListValidFlags {v} {\n    upvar $v cmd\n\n    set len [llength [array names cmd]]\n    set i 1\n    set separator \"\"\n    set errormsg \"\"\n    foreach cmdsw [lsort [array names cmd]] {\n\tappend errormsg \"$separator$cmdsw\"\n\tincr i\n\tif {$i == $len} {\n\t    set separator \", or \"\n\t} else {\n\t    set separator \", \"\n\t}\n    }\n    return $errormsg\n}\n\n#----------------------------------------------------------------------\n#\n#\t\t\tFocus Group\n#\n# Focus groups are used to handle the user's focusing actions inside a\n# toplevel.\n#\n# One example of using focus groups is: when the user focuses on an\n# entry, the text in the entry is highlighted and the cursor is put to\n# the end of the text. When the user changes focus to another widget,\n# the text in the previously focused entry is validated.\n#\n#----------------------------------------------------------------------\n\n\n# ::tk::FocusGroup_Create --\n#\n#\tCreate a focus group. All the widgets in a focus group must be\n#\twithin the same focus toplevel. Each toplevel can have only\n#\tone focus group, which is identified by the name of the\n#\ttoplevel widget.\n#\nproc ::tk::FocusGroup_Create {t} {\n    variable ::tk::Priv\n    if {[winfo toplevel $t] ne $t} {\n\treturn -code error -errorcode [list TK LOOKUP TOPLEVEL $t] \\\n\t    \"$t is not a toplevel window\"\n    }\n    if {![info exists Priv(fg,$t)]} {\n\tset Priv(fg,$t) 1\n\tset Priv(focus,$t) \"\"\n\tbind $t <FocusIn>  [list tk::FocusGroup_In  $t %W %d]\n\tbind $t <FocusOut> [list tk::FocusGroup_Out $t %W %d]\n\tbind $t <Destroy>  [list tk::FocusGroup_Destroy $t %W]\n    }\n}\n\n# ::tk::FocusGroup_BindIn --\n#\n# Add a widget into the \"FocusIn\" list of the focus group. The $cmd will be\n# called when the widget is focused on by the user.\n#\nproc ::tk::FocusGroup_BindIn {t w cmd} {\n    variable FocusIn\n    variable ::tk::Priv\n    if {![info exists Priv(fg,$t)]} {\n\treturn -code error -errorcode [list TK LOOKUP FOCUS_GROUP $t] \\\n\t    \"focus group \\\"$t\\\" does not exist\"\n    }\n    set FocusIn($t,$w) $cmd\n}\n\n\n# ::tk::FocusGroup_BindOut --\n#\n#\tAdd a widget into the \"FocusOut\" list of the focus group. The\n#\t$cmd will be called when the widget loses the focus (User\n#\ttypes Tab or click on another widget).\n#\nproc ::tk::FocusGroup_BindOut {t w cmd} {\n    variable FocusOut\n    variable ::tk::Priv\n    if {![info exists Priv(fg,$t)]} {\n\treturn -code error -errorcode [list TK LOOKUP FOCUS_GROUP $t] \\\n\t    \"focus group \\\"$t\\\" does not exist\"\n    }\n    set FocusOut($t,$w) $cmd\n}\n\n# ::tk::FocusGroup_Destroy --\n#\n#\tCleans up when members of the focus group is deleted, or when the\n#\ttoplevel itself gets deleted.\n#\nproc ::tk::FocusGroup_Destroy {t w} {\n    variable FocusIn\n    variable FocusOut\n    variable ::tk::Priv\n\n    if {$t eq $w} {\n\tunset Priv(fg,$t)\n\tunset Priv(focus,$t)\n\n\tforeach name [array names FocusIn $t,*] {\n\t    unset FocusIn($name)\n\t}\n\tforeach name [array names FocusOut $t,*] {\n\t    unset FocusOut($name)\n\t}\n    } else {\n\tif {[info exists Priv(focus,$t)] && ($Priv(focus,$t) eq $w)} {\n\t    set Priv(focus,$t) \"\"\n\t}\n\tunset -nocomplain FocusIn($t,$w) FocusOut($t,$w)\n    }\n}\n\n# ::tk::FocusGroup_In --\n#\n#\tHandles the <FocusIn> event. Calls the FocusIn command for the newly\n#\tfocused widget in the focus group.\n#\nproc ::tk::FocusGroup_In {t w detail} {\n    variable FocusIn\n    variable ::tk::Priv\n\n    if {$detail ne \"NotifyNonlinear\" && $detail ne \"NotifyNonlinearVirtual\"} {\n\t# This is caused by mouse moving out&in of the window *or*\n\t# ordinary keypresses some window managers (ie: CDE [Bug: 2960]).\n\treturn\n    }\n    if {![info exists FocusIn($t,$w)]} {\n\tset FocusIn($t,$w) \"\"\n\treturn\n    }\n    if {![info exists Priv(focus,$t)]} {\n\treturn\n    }\n    if {$Priv(focus,$t) eq $w} {\n\t# This is already in focus\n\t#\n\treturn\n    } else {\n\tset Priv(focus,$t) $w\n\teval $FocusIn($t,$w)\n    }\n}\n\n# ::tk::FocusGroup_Out --\n#\n#\tHandles the <FocusOut> event. Checks if this is really a lose\n#\tfocus event, not one generated by the mouse moving out of the\n#\ttoplevel window.  Calls the FocusOut command for the widget\n#\twho loses its focus.\n#\nproc ::tk::FocusGroup_Out {t w detail} {\n    variable FocusOut\n    variable ::tk::Priv\n\n    if {$detail ne \"NotifyNonlinear\" && $detail ne \"NotifyNonlinearVirtual\"} {\n\t# This is caused by mouse moving out of the window\n\treturn\n    }\n    if {![info exists Priv(focus,$t)]} {\n\treturn\n    }\n    if {![info exists FocusOut($t,$w)]} {\n\treturn\n    } else {\n\teval $FocusOut($t,$w)\n\tset Priv(focus,$t) \"\"\n    }\n}\n\n# ::tk::FDGetFileTypes --\n#\n#\tProcess the string given by the -filetypes option of the file\n#\tdialogs. Similar to the C function TkGetFileFilters() on the Mac\n#\tand Windows platform.\n#\nproc ::tk::FDGetFileTypes {string} {\n    foreach t $string {\n\tif {[llength $t] < 2 || [llength $t] > 3} {\n\t    return -code error -errorcode {TK VALUE FILE_TYPE} \\\n\t\t\"bad file type \\\"$t\\\", should be \\\"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\\\"\"\n\t}\n\tlappend fileTypes([lindex $t 0]) {*}[lindex $t 1]\n    }\n\n    set types {}\n    foreach t $string {\n\tset label [lindex $t 0]\n\tset exts {}\n\n\tif {[info exists hasDoneType($label)]} {\n\t    continue\n\t}\n\n\t# Validate each macType.  This is to agree with the\n\t# behaviour of TkGetFileFilters().  This list may be\n\t# empty.\n\tforeach macType [lindex $t 2] {\n\t    if {[string length $macType] != 4} {\n\t\treturn -code error -errorcode {TK VALUE MAC_TYPE} \\\n\t\t    \"bad Macintosh file type \\\"$macType\\\"\"\n\t    }\n\t}\n\n\tset name \"$label \\(\"\n\tset sep \"\"\n\tset doAppend 1\n\tforeach ext $fileTypes($label) {\n\t    if {$ext eq \"\"} {\n\t\tcontinue\n\t    }\n\t    regsub {^[.]} $ext \"*.\" ext\n\t    if {![info exists hasGotExt($label,$ext)]} {\n\t\tif {$doAppend} {\n\t\t    if {[string length $sep] && [string length $name]>40} {\n\t\t\tset doAppend 0\n\t\t\tappend name $sep...\n\t\t    } else {\n\t\t\tappend name $sep$ext\n\t\t    }\n\t\t}\n\t\tlappend exts $ext\n\t\tset hasGotExt($label,$ext) 1\n\t    }\n\t    set sep \",\"\n\t}\n\tappend name \"\\)\"\n\tlappend types [list $name $exts]\n\n\tset hasDoneType($label) 1\n    }\n\n    return $types\n}\n"
  },
  {
    "path": "library/console.tcl",
    "content": "# console.tcl --\n#\n# This code constructs the console window for an application.  It\n# can be used by non-unix systems that do not have built-in support\n# for shells.\n#\n# Copyright © 1995-1997 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Ajuba Solutions.\n# Copyright © 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# TODO: history - remember partially written command\n\nnamespace eval ::tk::console {\n    variable blinkTime   500 ; # msecs to blink braced range for\n    variable blinkRange  1   ; # enable blinking of the entire braced range\n    variable magicKeys   1   ; # enable brace matching and proc/var recognition\n    variable maxLines    600 ; # maximum # of lines buffered in console\n    variable showMatches 1   ; # show multiple expand matches\n    variable useFontchooser [llength [info command ::tk::fontchooser]]\n    variable inPlugin [info exists embed_args]\n    variable defaultPrompt   ; # default prompt if tcl_prompt1 isn't used\n\n    if {$inPlugin} {\n\tset defaultPrompt {subst {[history nextid] % }}\n    } else {\n\tset defaultPrompt {subst {([file tail [pwd]]) [history nextid] % }}\n    }\n}\n\n# simple compat function for tkcon code added for this console\ninterp alias {} EvalAttached {} consoleinterp eval\n\n# ::tk::ConsoleInit --\n# This procedure constructs and configures the console windows.\n#\n# Arguments:\n#\tNone.\n\nproc ::tk::ConsoleInit {} {\n    if {![consoleinterp eval {set tcl_interactive}]} {\n\twm withdraw .\n    }\n\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tset mod \"Cmd\"\n    } else {\n\tset mod \"Ctrl\"\n    }\n\n    if {[catch {menu .menubar} err]} {\n\tbgerror \"INIT: $err\"\n    }\n    AmpMenuArgs .menubar add cascade -label [mc &File] -menu .menubar.file\n    AmpMenuArgs .menubar add cascade -label [mc &Edit] -menu .menubar.edit\n\n    menu .menubar.file -tearoff 0\n    AmpMenuArgs .menubar.file add command -label [mc \"&Source...\"] \\\n\t    -command {tk::ConsoleSource}\n    AmpMenuArgs .menubar.file add command -label [mc \"&Hide Console\"] \\\n\t    -command {wm withdraw .}\n    AmpMenuArgs .menubar.file add command -label [mc \"&Clear Console\"] \\\n\t    -command {.console delete 1.0 \"promptEnd linestart\"}\n    if {[tk windowingsystem] ne \"aqua\"} {\n\tAmpMenuArgs .menubar.file add command -label [mc E&xit] -command {exit}\n    }\n\n    menu .menubar.edit -tearoff 0\n    AmpMenuArgs\t.menubar.edit add command -label [mc Cu&t]   -accel \"$mod+X\"\\\n\t    -command {event generate .console <<Cut>>}\n    AmpMenuArgs\t.menubar.edit add command -label [mc &Copy]  -accel \"$mod+C\"\\\n\t    -command {event generate .console <<Copy>>}\n    AmpMenuArgs\t.menubar.edit add command -label [mc P&aste] -accel \"$mod+V\"\\\n\t    -command {event generate .console <<Paste>>}\n\n    if {[tk windowingsystem] ne \"win32\"} {\n\tAmpMenuArgs .menubar.edit add command -label [mc Cl&ear] \\\n\t\t-command {event generate .console <<Clear>>}\n    } else {\n\tAmpMenuArgs .menubar.edit add command -label [mc &Delete] \\\n\t\t-command {event generate .console <<Clear>>} -accel \"Del\"\n\n\tAmpMenuArgs .menubar add cascade -label [mc &Help] -menu .menubar.help\n\tmenu .menubar.help -tearoff 0\n\tAmpMenuArgs .menubar.help add command -label [mc &About...] \\\n\t\t-command tk::ConsoleAbout\n    }\n\n    AmpMenuArgs .menubar.edit add separator\n    if {$::tk::console::useFontchooser} {\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    .menubar.edit add command -label tk_choose_font_marker\n\t    set index [.menubar.edit index tk_choose_font_marker]\n\t    .menubar.edit entryconfigure $index \\\n\t\t-label [mc \"Show Fonts\"]\\\n\t\t-accelerator \"$mod-T\"\\\n\t\t-command [list ::tk::console::FontchooserToggle]\n\t    bind Console <<TkFontchooserVisibility>> \\\n\t\t[list ::tk::console::FontchooserVisibility $index]\n\t    ::tk::console::FontchooserVisibility $index\n\t} else {\n\t    AmpMenuArgs .menubar.edit add command -label [mc \"&Font...\"] \\\n\t\t-command [list ::tk::console::FontchooserToggle]\n\t}\n\tbind Console <FocusIn>  [list ::tk::console::FontchooserFocus %W 1]\n\tbind Console <FocusOut> [list ::tk::console::FontchooserFocus %W 0]\n    }\n    AmpMenuArgs .menubar.edit add command -label [mc \"&Increase Font Size\"] \\\n\t-accel \"$mod++\" -command {event generate .console <<Console_FontSizeIncr>>}\n    AmpMenuArgs .menubar.edit add command -label [mc \"&Decrease Font Size\"] \\\n\t-accel \"$mod+-\" -command {event generate .console <<Console_FontSizeDecr>>}\n    AmpMenuArgs .menubar.edit add command -label [mc \"Fit To Screen Width\"] \\\n\t-command {event generate .console <<Console_FitScreenWidth>>}\n\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t.menubar add cascade -label [mc Window] -menu [menu .menubar.window]\n\t.menubar add cascade -label [mc Help] -menu [menu .menubar.help]\n    }\n\n    . configure -menu .menubar\n\n    # See if we can find a better font than the TkFixedFont\n    catch {font create TkConsoleFont {*}[font configure TkFixedFont]}\n    set families [font families]\n    switch -exact -- [tk windowingsystem] {\n\taqua { set preferred {Monaco 10} }\n\twin32 { set preferred {ProFontWindows 8 Consolas 8} }\n\tdefault { set preferred {} }\n    }\n    foreach {family size} $preferred {\n\tif {$family in $families} {\n\t    font configure TkConsoleFont -family $family -size $size\n\t    break\n\t}\n    }\n\n    # Provide the right border for the text widget (platform dependent).\n    ::ttk::style layout ConsoleFrame {\n\tEntry.field -sticky news -border 1 -children {\n\t    ConsoleFrame.padding -sticky news\n\t}\n    }\n    ::ttk::frame .consoleframe -style ConsoleFrame\n\n    set con [text .console -yscrollcommand [list .sb set] -setgrid 1 \\\n\t\t -borderwidth 0 -highlightthickness 0 -font TkConsoleFont]\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tscrollbar .sb -command [list $con yview]\n    } else {\n\t::ttk::scrollbar .sb -command [list $con yview]\n    }\n    pack .sb  -in .consoleframe -fill both -side right -padx 1 -pady 1\n    pack $con -in .consoleframe -fill both -expand 1 -side left -padx 1 -pady 1\n    pack .consoleframe -fill both -expand 1 -side left\n\n    ConsoleBind $con\n\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t$con tag configure stdin -foreground systemLinkColor\n    } else {\n\t$con tag configure stdin -foreground blue\n    }\n\n    $con tag configure stderr\t-foreground red\n    $con tag configure prompt\t-foreground \\#8F4433\n    $con tag configure proc\t-foreground \\#008800\n    $con tag configure var\t-background \\#FFC0D0\n    $con tag raise sel\n    $con tag configure blink\t-background \\#FFFF00\n    $con tag configure find\t-background \\#FFFF00\n\n    focus $con\n\n    # Avoid listing this console in [winfo interps]\n    if {[info command ::send] eq \"::send\"} {rename ::send {}}\n\n    wm protocol . WM_DELETE_WINDOW { wm withdraw . }\n    wm title . [mc \"Console\"]\n    flush stdout\n    $con mark set output [$con index \"end - 1 char\"]\n    tk::TextSetCursor $con end\n    $con mark set promptEnd insert\n    $con mark gravity promptEnd left\n\n    # A variant of ConsolePrompt to avoid a 'puts' call\n    set w $con\n    set temp [$w index \"end - 1 char\"]\n    $w mark set output end\n    if {![consoleinterp eval \"info exists tcl_prompt1\"]} {\n\tset string [EvalAttached $::tk::console::defaultPrompt]\n\t$w insert output $string stdout\n    }\n    $w mark set output $temp\n    ::tk::TextSetCursor $w end\n    $w mark set promptEnd insert\n    $w mark gravity promptEnd left\n\n    if {[tk windowingsystem] ne \"aqua\"} {\n\t# Subtle work-around to erase the '% ' that tclMain.c prints out\n\tafter idle [subst -nocommand {\n\t    if {[$con get 1.0 output] eq \"% \"} { $con delete 1.0 output }\n\t}]\n    }\n}\n\n# ::tk::ConsoleSource --\n#\n# Prompts the user for a file to source in the main interpreter.\n#\n# Arguments:\n# None.\n\nproc ::tk::ConsoleSource {} {\n    set filename [tk_getOpenFile -defaultextension .tcl -parent . \\\n\t    -title [mc \"Select a file to source\"] \\\n\t    -filetypes [list \\\n\t    [list [mc \"Tcl Scripts\"] .tcl] \\\n\t    [list [mc \"All Files\"] *]]]\n    if {$filename ne \"\"} {\n\tset cmd [list source $filename]\n\tif {[catch {consoleinterp eval $cmd} result]} {\n\t    ConsoleOutput stderr \"$result\\n\"\n\t}\n    }\n}\n\n# ::tk::ConsoleInvoke --\n# Processes the command line input.  If the command is complete it\n# is evaled in the main interpreter.  Otherwise, the continuation\n# prompt is added and more input may be added.\n#\n# Arguments:\n# None.\n\nproc ::tk::ConsoleInvoke {args} {\n    set ranges [.console tag ranges input]\n    set cmd \"\"\n    if {[llength $ranges]} {\n\tset pos 0\n\twhile {[lindex $ranges $pos] ne \"\"} {\n\t    set start [lindex $ranges $pos]\n\t    set end [lindex $ranges [incr pos]]\n\t    append cmd [.console get $start $end]\n\t    incr pos\n\t}\n    }\n    if {$cmd eq \"\"} {\n\tConsolePrompt\n    } elseif {[info complete $cmd]} {\n\t.console mark set output end\n\t.console tag delete input\n\tset result [consoleinterp record $cmd]\n\tif {$result ne \"\"} {\n\t    puts $result\n\t}\n\tConsoleHistory reset\n\tConsolePrompt\n    } else {\n\tConsolePrompt partial\n    }\n    .console yview -pickplace insert\n}\n\n# ::tk::ConsoleHistory --\n# This procedure implements command line history for the\n# console.  In general is evals the history command in the\n# main interpreter to obtain the history.  The variable\n# ::tk::HistNum is used to store the current location in the history.\n#\n# Arguments:\n# cmd -\tWhich action to take: prev, next, reset.\n\nset ::tk::HistNum 1\nproc ::tk::ConsoleHistory {cmd} {\n    variable HistNum\n\n    switch $cmd {\n\tprev {\n\t    incr HistNum -1\n\t    if {$HistNum == 0} {\n\t\tset cmd {history event [expr {[history nextid] -1}]}\n\t    } else {\n\t\tset cmd \"history event $HistNum\"\n\t    }\n\t    if {[catch {consoleinterp eval $cmd} cmd]} {\n\t\tincr HistNum\n\t\treturn\n\t    }\n\t    .console delete promptEnd end\n\t    .console insert promptEnd $cmd {input stdin}\n\t    .console see end\n\t}\n\tnext {\n\t    incr HistNum\n\t    if {$HistNum == 0} {\n\t\tset cmd {history event [expr {[history nextid] -1}]}\n\t    } elseif {$HistNum > 0} {\n\t\tset cmd \"\"\n\t\tset HistNum 1\n\t    } else {\n\t\tset cmd \"history event $HistNum\"\n\t    }\n\t    if {$cmd ne \"\"} {\n\t\tcatch {consoleinterp eval $cmd} cmd\n\t    }\n\t    .console delete promptEnd end\n\t    .console insert promptEnd $cmd {input stdin}\n\t    .console see end\n\t}\n\treset {\n\t    set HistNum 1\n\t}\n    }\n}\n\n# ::tk::ConsolePrompt --\n# This procedure draws the prompt.  If tcl_prompt1 or tcl_prompt2\n# exists in the main interpreter it will be called to generate the\n# prompt.  Otherwise, a hard coded default prompt is printed.\n#\n# Arguments:\n# partial -\tFlag to specify which prompt to print.\n\nproc ::tk::ConsolePrompt {{partial normal}} {\n    set w .console\n    if {$partial eq \"normal\"} {\n\tset temp [$w index \"end - 1 char\"]\n\t$w mark set output end\n\tif {[consoleinterp eval \"info exists tcl_prompt1\"]} {\n\t    consoleinterp eval \"eval \\[set tcl_prompt1\\]\"\n\t} else {\n\t    puts -nonewline [EvalAttached $::tk::console::defaultPrompt]\n\t}\n    } else {\n\tset temp [$w index output]\n\t$w mark set output end\n\tif {[consoleinterp eval \"info exists tcl_prompt2\"]} {\n\t    consoleinterp eval \"eval \\[set tcl_prompt2\\]\"\n\t} else {\n\t    puts -nonewline \"> \"\n\t}\n    }\n    flush stdout\n    $w mark set output $temp\n    ::tk::TextSetCursor $w end\n    $w mark set promptEnd insert\n    $w mark gravity promptEnd left\n    ::tk::console::ConstrainBuffer $w $::tk::console::maxLines\n    $w see end\n}\n\n# Copy selected text from the console\nproc ::tk::console::Copy {w} {\n    if {![catch {set data [$w get sel.first sel.last]}]} {\n\tclipboard clear -displayof $w\n\tclipboard append -displayof $w $data\n    }\n}\n# Copies selected text. If the selection is within the current active edit\n# region then it will be cut, if not it is only copied.\nproc ::tk::console::Cut {w} {\n    if {![catch {set data [$w get sel.first sel.last]}]} {\n\tclipboard clear -displayof $w\n\tclipboard append -displayof $w $data\n\tif {[$w compare sel.first >= output]} {\n\t    $w delete sel.first sel.last\n\t}\n    }\n}\n# Paste text from the clipboard\nproc ::tk::console::Paste {w} {\n    catch {\n\tset clip [::tk::GetSelection $w CLIPBOARD]\n\tset list [split $clip \\n\\r]\n\ttk::ConsoleInsert $w [lindex $list 0]\n\tforeach x [lrange $list 1 end] {\n\t    $w mark set insert {end - 1c}\n\t    tk::ConsoleInsert $w \"\\n\"\n\t    tk::ConsoleInvoke\n\t    tk::ConsoleInsert $w $x\n\t}\n    }\n}\n\n# Fit TkConsoleFont to window width\nproc ::tk::console::FitScreenWidth {w} {\n    set width [winfo screenwidth $w]\n    set cwidth [$w cget -width]\n    set s -50\n    set fit 0\n    array set fi [font configure TkConsoleFont]\n    while {$s < 0} {\n\tset fi(-size) $s\n\tset f [font create {*}[array get fi]]\n\tset c [font measure $f \"eM\"]\n\tfont delete $f\n\tif {$c * $cwidth < 1.667 * $width} {\n\t    font configure TkConsoleFont -size $s\n\t    break\n\t}\n\tincr s 2\n    }\n}\n\n# ::tk::ConsoleBind --\n# This procedure first ensures that the default bindings for the Text\n# class have been defined.  Then certain bindings are overridden for\n# the class.\n#\n# Arguments:\n# None.\n\nproc ::tk::ConsoleBind {w} {\n    bindtags $w [list $w Console PostConsole [winfo toplevel $w] all]\n\n    ## Get all Text bindings into Console\n    foreach ev [bind Text] {\n\tbind Console $ev [bind Text $ev]\n    }\n    ## We really didn't want the newline insertion...\n    bind Console <Control-o> {}\n    ## ...or any Control-v binding (would block <<Paste>>)\n    bind Console <Control-v> {}\n\n    # For the moment, transpose isn't enabled until the console\n    # gets and overhaul of how it handles input -- hobbs\n    bind Console <Control-t> {}\n\n    # Ignore all Alt, Meta, Control, Command, and Fn keypresses unless explicitly bound.\n    # Otherwise, if a widget binding for one of these is defined, the\n    # <Keypress> class binding will also fire and insert the character\n    # which is wrong.\n\n    bind Console <Alt-Key> {# nothing }\n    bind Console <Meta-Key> {# nothing}\n    bind Console <Control-Key> {# nothing}\n    bind Console <Command-Key> {# nothing}\n    bind Console <Fn-Key> {# nothing}\n\n    foreach {ev key} {\n\t<<Console_NextImmediate>>\t<Control-n>\n\t<<Console_PrevImmediate>>\t<Control-p>\n\t<<Console_PrevSearch>>\t\t<Control-r>\n\t<<Console_NextSearch>>\t\t<Control-s>\n\n\t<<Console_Expand>>\t\t<Tab>\n\t<<Console_Expand>>\t\t<Escape>\n\t<<Console_ExpandFile>>\t\t<Control-Shift-F>\n\t<<Console_ExpandProc>>\t\t<Control-Shift-P>\n\t<<Console_ExpandVar>>\t\t<Control-Shift-V>\n\t<<Console_Tab>>\t\t\t<Control-i>\n\t<<Console_Tab>>\t\t\t<Meta-i>\n\t<<Console_Eval>>\t\t<Return>\n\t<<Console_Eval>>\t\t<KP_Enter>\n\n\t<<Console_Clear>>\t\t<Control-l>\n\t<<Console_KillLine>>\t\t<Control-k>\n\t<<Console_Transpose>>\t\t<Control-t>\n\t<<Console_ClearLine>>\t\t<Control-u>\n\t<<Console_SaveCommand>>\t\t<Control-z>\n\t<<Console_FontSizeIncr>>\t<Control-+>\n\t<<Console_FontSizeIncr>>\t<Control-=>\n\t<<Console_FontSizeDecr>>\t<Control-minus>\n\t<<Console_FontSizeDecr>>\t<Control-_>\n\t<<Console_FontSizeIncr>>\t<Command-+>\n\t<<Console_FontSizeIncr>>\t<Command-=>\n\t<<Console_FontSizeDecr>>\t<Command-minus>\n\t<<Console_FontSizeDecr>>\t<Command-_>\n    } {\n\tevent add $ev $key\n\tbind Console $key {}\n    }\n    if {$::tk::console::useFontchooser} {\n\tbind Console <Command-t> [list ::tk::console::FontchooserToggle]\n    }\n    bind Console <<Console_Expand>> {\n\tif {[%W compare insert > promptEnd]} {\n\t    ::tk::console::Expand %W\n\t}\n    }\n    bind Console <<Console_ExpandFile>> {\n\tif {[%W compare insert > promptEnd]} {\n\t    ::tk::console::Expand %W path\n\t}\n    }\n    bind Console <<Console_ExpandProc>> {\n\tif {[%W compare insert > promptEnd]} {\n\t    ::tk::console::Expand %W proc\n\t}\n    }\n    bind Console <<Console_ExpandVar>> {\n\tif {[%W compare insert > promptEnd]} {\n\t    ::tk::console::Expand %W var\n\t}\n    }\n    bind Console <<Console_Eval>> {\n\t%W mark set insert {end - 1c}\n\ttk::ConsoleInsert %W \"\\n\"\n\ttk::ConsoleInvoke\n\tbreak\n    }\n    bind Console <Delete> {\n\tif {{} ne [%W tag nextrange sel 1.0 end] \\\n\t\t&& [%W compare sel.first >= promptEnd]} {\n\t    %W delete sel.first sel.last\n\t} elseif {[%W compare insert >= promptEnd]} {\n\t    %W delete insert\n\t    %W see insert\n\t}\n    }\n    bind Console <BackSpace> {\n\tif {{} ne [%W tag nextrange sel 1.0 end] \\\n\t\t&& [%W compare sel.first >= promptEnd]} {\n\t    %W delete sel.first sel.last\n\t} elseif {[%W compare insert != 1.0] && \\\n\t\t[%W compare insert > promptEnd]} {\n\t    %W delete insert-1c\n\t    %W see insert\n\t}\n    }\n    bind Console <Control-h> [bind Console <BackSpace>]\n\n    bind Console <<LineStart>> {\n\tif {[%W compare insert < promptEnd]} {\n\t    tk::TextSetCursor %W {insert linestart}\n\t} else {\n\t    tk::TextSetCursor %W promptEnd\n\t}\n    }\n    bind Console <<LineEnd>> {\n\ttk::TextSetCursor %W {insert lineend}\n    }\n    bind Console <Control-d> {\n\tif {[%W compare insert < promptEnd]} {\n\t    break\n\t}\n\t%W delete insert\n    }\n    bind Console <<Console_KillLine>> {\n\tif {[%W compare insert < promptEnd]} {\n\t    break\n\t}\n\tif {[%W compare insert == {insert lineend}]} {\n\t    %W delete insert\n\t} else {\n\t    %W delete insert {insert lineend}\n\t}\n    }\n    bind Console <<Console_Clear>> {\n\t## Clear console display\n\t%W delete 1.0 \"promptEnd linestart\"\n    }\n    bind Console <<Console_ClearLine>> {\n\t## Clear command line (Unix shell staple)\n\t%W delete promptEnd end\n    }\n    bind Console <Meta-d> {\n\tif {[%W compare insert >= promptEnd]} {\n\t    %W delete insert {insert wordend}\n\t}\n    }\n    bind Console <Meta-BackSpace> {\n\tif {[%W compare {insert -1c wordstart} >= promptEnd]} {\n\t    %W delete {insert -1c wordstart} insert\n\t}\n    }\n    bind Console <Meta-d> {\n\tif {[%W compare insert >= promptEnd]} {\n\t    %W delete insert {insert wordend}\n\t}\n    }\n    bind Console <Meta-BackSpace> {\n\tif {[%W compare {insert -1c wordstart} >= promptEnd]} {\n\t    %W delete {insert -1c wordstart} insert\n\t}\n    }\n    bind Console <Meta-Delete> {\n\tif {[%W compare insert >= promptEnd]} {\n\t    %W delete insert {insert wordend}\n\t}\n    }\n    bind Console <<PrevLine>> {\n\ttk::ConsoleHistory prev\n    }\n    bind Console <<NextLine>> {\n\ttk::ConsoleHistory next\n    }\n    bind Console <Insert> {\n\tcatch {tk::ConsoleInsert %W [::tk::GetSelection %W PRIMARY]}\n    }\n    bind Console <Key> {\n\ttk::ConsoleInsert %W %A\n    }\n    bind Console <F9> {\n\tdestroy {*}[winfo children .]\n\tsource [file join $tk_library console.tcl]\n    }\n    bind Console <Command-q> {\n\texit\n    }\n    bind Console <<Cut>> { ::tk::console::Cut %W }\n    bind Console <<Copy>> { ::tk::console::Copy %W }\n    bind Console <<Paste>> { ::tk::console::Paste %W }\n\n    foreach modifier {Control Command} {\n\tbind Console <$modifier-MouseWheel> {\n\t    if {%D > 0} {\n\t\tevent generate %W <<Console_FontSizeIncr>>\n\t    } else {\n\t\tevent generate %W <<Console_FontSizeDecr>>\n\t    }\n\t}\n\tbind Console <$modifier-TouchpadScroll> {\n\t    lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n\t    # TouchpadScroll events fire about 60 times per second.\n\t    if {$tk::Priv(deltaY) != 0 && %# %% 15 == 0} {\n\t\tif {$tk::Priv(deltaY) > 0} {\n\t\t    event generate %W <<Console_FontSizeIncr>>\n\t\t} else {\n\t\t    event generate %W <<Console_FontSizeDecr>>\n\t\t}\n\t    }\n\t}\n    }\n\n    bind Console <<Console_FontSizeIncr>> {\n\tset size [font configure TkConsoleFont -size]\n\tif {$size < 0} {set sign -1} else {set sign 1}\n\tset size [expr {(abs($size) + 1) * $sign}]\n\tfont configure TkConsoleFont -size $size\n\tif {$::tk::console::useFontchooser} {\n\t    tk fontchooser configure -font TkConsoleFont\n\t}\n    }\n    bind Console <<Console_FontSizeDecr>> {\n\tset size [font configure TkConsoleFont -size]\n\tif {abs($size) < 2} { return }\n\tif {$size < 0} {set sign -1} else {set sign 1}\n\tset size [expr {(abs($size) - 1) * $sign}]\n\tfont configure TkConsoleFont -size $size\n\tif {$::tk::console::useFontchooser} {\n\t    tk fontchooser configure -font TkConsoleFont\n\t}\n    }\n    bind Console <<Console_FitScreenWidth>> {\n\t::tk::console::FitScreenWidth %W\n    }\n\n    ##\n    ## Bindings for doing special things based on certain keys\n    ##\n    bind PostConsole <)> {\n\tif {\"\\\\\" ne [%W get insert-2c]} {\n\t    ::tk::console::MatchPair %W \\( \\) promptEnd\n\t}\n    }\n    bind PostConsole <bracketright> {\n\tif {\"\\\\\" ne [%W get insert-2c]} {\n\t    ::tk::console::MatchPair %W \\[ \\] promptEnd\n\t}\n    }\n    bind PostConsole <braceright> {\n\tif {\"\\\\\" ne [%W get insert-2c]} {\n\t    ::tk::console::MatchPair %W \\{ \\} promptEnd\n\t}\n    }\n    bind PostConsole <quotedbl> {\n\tif {\"\\\\\" ne [%W get insert-2c]} {\n\t    ::tk::console::MatchQuote %W promptEnd\n\t}\n    }\n\n    bind PostConsole <Key> {\n\tif {\"%A\" ne \"\"} {\n\t    ::tk::console::TagProc %W\n\t}\n    }\n}\n\n# ::tk::ConsoleInsert --\n# Insert a string into a text at the point of the insertion cursor.\n# If there is a selection in the text, and it covers the point of the\n# insertion cursor, then delete the selection before inserting.  Insertion\n# is restricted to the prompt area.\n#\n# Arguments:\n# w -\t\tThe text window in which to insert the string\n# s -\t\tThe string to insert (usually just a single character)\n\nproc ::tk::ConsoleInsert {w s} {\n    if {$s eq \"\"} {\n\treturn\n    }\n    catch {\n\tif {[$w compare sel.first <= insert] \\\n\t\t&& [$w compare sel.last >= insert]} {\n\t    $w tag remove sel sel.first promptEnd\n\t    $w delete sel.first sel.last\n\t}\n    }\n    if {[$w compare insert < promptEnd]} {\n\t$w mark set insert end\n    }\n    $w insert insert $s {input stdin}\n    $w see insert\n}\n\n# ::tk::ConsoleOutput --\n#\n# This routine is called directly by ConsolePutsCmd to cause a string\n# to be displayed in the console.\n#\n# Arguments:\n# dest -\tThe output tag to be used: either \"stderr\" or \"stdout\".\n# string -\tThe string to be displayed.\n\nproc ::tk::ConsoleOutput {dest string} {\n    set w .console\n    $w insert output $string $dest\n    ::tk::console::ConstrainBuffer $w $::tk::console::maxLines\n    $w see insert\n}\n\n# ::tk::ConsoleExit --\n#\n# This routine is called by ConsoleEventProc when the main window of\n# the application is destroyed.  Don't call exit - that probably already\n# happened.  Just delete our window.\n#\n# Arguments:\n# None.\n\nproc ::tk::ConsoleExit {} {\n    destroy .\n}\n\n# ::tk::ConsoleAbout --\n#\n# This routine displays an About box to show Tcl/Tk version info.\n#\n# Arguments:\n# None.\n\nproc ::tk::ConsoleAbout {} {\n    tk_messageBox -type ok -message \"[mc {Tcl for Windows}]\n\nTcl $::tcl_patchLevel\nTk $::tk_patchLevel\"\n}\n\n# ::tk::console::Fontchooser* --\n#\tLet the user select the console font (TIP 324).\n\nproc ::tk::console::FontchooserToggle {} {\n    if {[tk fontchooser configure -visible]} {\n\ttk fontchooser hide\n    } else {\n\ttk fontchooser show\n    }\n}\nproc ::tk::console::FontchooserVisibility {index} {\n    if {[tk fontchooser configure -visible]} {\n\t.menubar.edit entryconfigure $index -label [::tk::msgcat::mc \"Hide Fonts\"]\n    } else {\n\t.menubar.edit entryconfigure $index -label [::tk::msgcat::mc \"Show Fonts\"]\n    }\n}\nproc ::tk::console::FontchooserFocus {w isFocusIn} {\n    if {$isFocusIn} {\n\ttk fontchooser configure -parent $w -font TkConsoleFont \\\n\t\t-command [namespace code [list FontchooserApply]]\n    } else {\n\ttk fontchooser configure -parent $w -font {} -command {}\n    }\n}\nproc ::tk::console::FontchooserApply {font args} {\n    catch {font configure TkConsoleFont {*}[font actual $font]}\n}\n\n# ::tk::console::TagProc --\n#\n# Tags a procedure in the console if it's recognized\n# This procedure is not perfect.  However, making it perfect wastes\n# too much CPU time...\n#\n# Arguments:\n#\tw\t- console text widget\n\nproc ::tk::console::TagProc w {\n    if {!$::tk::console::magicKeys} {\n\treturn\n    }\n    set exp \"\\[^\\\\\\\\\\]\\[\\[ \\t\\n\\r\\;{}\\\"\\$\\]\"\n    set i [$w search -backwards -regexp $exp insert-1c promptEnd-1c]\n    if {$i eq \"\"} {\n\tset i promptEnd\n    } else {\n\tappend i +2c\n    }\n    regsub -all \"\\[\\[\\\\\\\\\\\\?\\\\*\\]\" [$w get $i \"insert-1c wordend\"] {\\\\\\0} c\n    if {[llength [EvalAttached [list info commands $c]]]} {\n\t$w tag add proc $i \"insert-1c wordend\"\n    } else {\n\t$w tag remove proc $i \"insert-1c wordend\"\n    }\n    if {[llength [EvalAttached [list info vars $c]]]} {\n\t$w tag add var $i \"insert-1c wordend\"\n    } else {\n\t$w tag remove var $i \"insert-1c wordend\"\n    }\n}\n\n# ::tk::console::MatchPair --\n#\n# Blinks a matching pair of characters\n# c2 is assumed to be at the text index 'insert'.\n# This proc is really loopy and took me an hour to figure out given\n# all possible combinations with escaping except for escaped \\'s.\n# It doesn't take into account possible commenting... Oh well.  If\n# anyone has something better, I'd like to see/use it.  This is really\n# only efficient for small contexts.\n#\n# Arguments:\n#\tw\t- console text widget\n#\tc1\t- first char of pair\n#\tc2\t- second char of pair\n#\n# Calls:\t::tk::console::Blink\n\nproc ::tk::console::MatchPair {w c1 c2 {lim 1.0}} {\n    if {!$::tk::console::magicKeys} {\n\treturn\n    }\n    if {{} ne [set ix [$w search -back $c1 insert $lim]]} {\n\twhile {\n\t    [string match {\\\\} [$w get $ix-1c]] &&\n\t    [set ix [$w search -back $c1 $ix-1c $lim]] ne {}\n\t} {}\n\tset i1 insert-1c\n\twhile {$ix ne {}} {\n\t    set i0 $ix\n\t    set j 0\n\t    while {[set i0 [$w search $c2 $i0 $i1]] ne {}} {\n\t\tappend i0 +1c\n\t\tif {[string match {\\\\} [$w get $i0-2c]]} {\n\t\t    continue\n\t\t}\n\t\tincr j\n\t    }\n\t    if {!$j} {\n\t\tbreak\n\t    }\n\t    set i1 $ix\n\t    while {$j && [set ix [$w search -back $c1 $ix $lim]] ne {}} {\n\t\tif {[string match {\\\\} [$w get $ix-1c]]} {\n\t\t    continue\n\t\t}\n\t\tincr j -1\n\t    }\n\t}\n\tif {[string match {} $ix]} {\n\t    set ix [$w index $lim]\n\t}\n    } else {\n\tset ix [$w index $lim]\n    }\n    if {$::tk::console::blinkRange} {\n\tBlink $w $ix [$w index insert]\n    } else {\n\tBlink $w $ix $ix+1c [$w index insert-1c] [$w index insert]\n    }\n}\n\n# ::tk::console::MatchQuote --\n#\n# Blinks between matching quotes.\n# Blinks just the quote if it's unmatched, otherwise blinks quoted string\n# The quote to match is assumed to be at the text index 'insert'.\n#\n# Arguments:\n#\tw\t- console text widget\n#\n# Calls:\t::tk::console::Blink\n\nproc ::tk::console::MatchQuote {w {lim 1.0}} {\n    if {!$::tk::console::magicKeys} {\n\treturn\n    }\n    set i insert-1c\n    set j 0\n    while {[set i [$w search -back \\\" $i $lim]] ne {}} {\n\tif {[string match {\\\\} [$w get $i-1c]]} {\n\t    continue\n\t}\n\tif {!$j} {\n\t    set i0 $i\n\t}\n\tincr j\n    }\n    if {$j&1} {\n\tif {$::tk::console::blinkRange} {\n\t    Blink $w $i0 [$w index insert]\n\t} else {\n\t    Blink $w $i0 $i0+1c [$w index insert-1c] [$w index insert]\n\t}\n    } else {\n\tBlink $w [$w index insert-1c] [$w index insert]\n    }\n}\n\n# ::tk::console::Blink --\n#\n# Blinks between n index pairs for a specified duration.\n#\n# Arguments:\n#\tw\t- console text widget\n#\ti1\t- start index to blink region\n#\ti2\t- end index of blink region\n#\tdur\t- duration in usecs to blink for\n#\n# Outputs:\n#\tblinks selected characters in $w\n\nproc ::tk::console::Blink {w args} {\n    eval [list $w tag add blink] $args\n    after $::tk::console::blinkTime [list $w] tag remove blink $args\n}\n\n# ::tk::console::ConstrainBuffer --\n#\n# This limits the amount of data in the text widget\n# Called by Prompt and ConsoleOutput\n#\n# Arguments:\n#\tw\t- console text widget\n#\tsize\t- # of lines to constrain to\n#\n# Outputs:\n#\tmay delete data in console widget\n\nproc ::tk::console::ConstrainBuffer {w size} {\n    if {[$w index end] > $size} {\n\t$w delete 1.0 [expr {int([$w index end])-$size}].0\n    }\n}\n\n# ::tk::console::Expand --\n#\n# Arguments:\n# ARGS:\tw\t- text widget in which to expand str\n#\ttype\t- type of expansion (path / proc / variable)\n#\n# Calls:\t::tk::console::Expand(Pathname|Procname|Variable)\n#\n# Outputs:\tThe string to match is expanded to the longest possible match.\n#\t\tIf ::tk::console::showMatches is non-zero and the longest match\n#\t\tequaled the string to expand, then all possible matches are\n#\t\toutput to stdout.  Triggers bell if no matches are found.\n#\n# Returns:\tnumber of matches found\n\nproc ::tk::console::Expand {w {type \"\"}} {\n    set exp \"\\[^\\\\\\\\\\]\\[\\[ \\t\\n\\r\\\\\\{\\\"\\\\\\\\\\$\\]\"\n    set tmp [$w search -backwards -regexp $exp insert-1c promptEnd-1c]\n    if {$tmp eq \"\"} {\n\tset tmp promptEnd\n    } else {\n\tappend tmp +2c\n    }\n    if {[$w compare $tmp >= insert]} {\n\treturn\n    }\n    set str [$w get $tmp insert]\n    switch -glob $type {\n\tpath* {\n\t    set res [ExpandPathname $str]\n\t}\n\tproc* {\n\t    set res [ExpandProcname $str]\n\t}\n\tvar* {\n\t    set res [ExpandVariable $str]\n\t}\n\tdefault {\n\t    set res {}\n\t    foreach t {Pathname Procname Variable} {\n\t\tif {![catch {Expand$t $str} res] && ($res ne \"\")} {\n\t\t    break\n\t\t}\n\t    }\n\t}\n    }\n    set len [llength $res]\n    if {$len} {\n\tset repl [lindex $res 0]\n\t$w delete $tmp insert\n\t$w insert $tmp $repl {input stdin}\n\tif {($len > 1) && ($::tk::console::showMatches) && ($repl eq $str)} {\n\t    puts stdout [lsort [lreplace $res 0 0]]\n\t}\n    } else {\n\tbell\n    }\n    return [incr len -1]\n}\n\n# ::tk::console::ExpandPathname --\n#\n# Expand a file pathname based on $str\n# This is based on UNIX file name conventions\n#\n# Arguments:\n#\tstr\t- partial file pathname to expand\n#\n# Calls:\t::tk::console::ExpandBestMatch\n#\n# Returns:\tlist containing longest unique match followed by all the\n#\t\tpossible further matches\n\nproc ::tk::console::ExpandPathname str {\n    set pwd [EvalAttached pwd]\n    if {[catch {EvalAttached [list cd [file dirname $str]]} err opt]} {\n\treturn -options $opt $err\n    }\n    set dir [file tail $str]\n    ## Check to see if it was known to be a directory and keep the trailing\n    ## slash if so (file tail cuts it off)\n    if {[string match */ $str]} {\n\tappend dir /\n    }\n    if {[catch {lsort [EvalAttached [list glob $dir*]]} m]} {\n\tset match {}\n    } else {\n\tif {[llength $m] > 1} {\n\t    if { $::tcl_platform(platform) eq \"windows\" } {\n\t\t## Windows is screwy because it's case insensitive\n\t\tset tmp [ExpandBestMatch [string tolower $m] \\\n\t\t\t[string tolower $dir]]\n\t\t## Don't change case if we haven't changed the word\n\t\tif {[string length $dir]==[string length $tmp]} {\n\t\t    set tmp $dir\n\t\t}\n\t    } else {\n\t\tset tmp [ExpandBestMatch $m $dir]\n\t    }\n\t    if {[string match ?*/* $str]} {\n\t\tset tmp [file dirname $str]/$tmp\n\t    } elseif {[string match /* $str]} {\n\t\tset tmp /$tmp\n\t    }\n\t    regsub -all { } $tmp {\\\\ } tmp\n\t    set match [linsert $m 0 $tmp]\n\t} else {\n\t    ## This may look goofy, but it handles spaces in path names\n\t    eval append match $m\n\t    if {[file isdir $match]} {\n\t\tappend match /\n\t    }\n\t    if {[string match ?*/* $str]} {\n\t\tset match [file dirname $str]/$match\n\t    } elseif {[string match /* $str]} {\n\t\tset match /$match\n\t    }\n\t    regsub -all { } $match {\\\\ } match\n\t    ## Why is this one needed and the ones below aren't!!\n\t    set match [list $match]\n\t}\n    }\n    EvalAttached [list cd $pwd]\n    return $match\n}\n\n# ::tk::console::ExpandProcname --\n#\n# Expand a tcl proc name based on $str\n#\n# Arguments:\n#\tstr\t- partial proc name to expand\n#\n# Calls:\t::tk::console::ExpandBestMatch\n#\n# Returns:\tlist containing longest unique match followed by all the\n#\t\tpossible further matches\n\nproc ::tk::console::ExpandProcname str {\n    set match [EvalAttached [list info commands $str*]]\n    if {[llength $match] == 0} {\n\tset ns [EvalAttached \\\n\t\t\"namespace children \\[namespace current\\] [list $str*]\"]\n\tif {[llength $ns]==1} {\n\t    set match [EvalAttached [list info commands ${ns}::*]]\n\t} else {\n\t    set match $ns\n\t}\n    }\n    if {[llength $match] > 1} {\n\tregsub -all { } [ExpandBestMatch $match $str] {\\\\ } str\n\tset match [linsert $match 0 $str]\n    } else {\n\tregsub -all { } $match {\\\\ } match\n    }\n    return $match\n}\n\n# ::tk::console::ExpandVariable --\n#\n# Expand a tcl variable name based on $str\n#\n# Arguments:\n#\tstr\t- partial tcl var name to expand\n#\n# Calls:\t::tk::console::ExpandBestMatch\n#\n# Returns:\tlist containing longest unique match followed by all the\n#\t\tpossible further matches\n\nproc ::tk::console::ExpandVariable str {\n    if {[regexp {([^\\(]*)\\((.*)} $str -> ary str]} {\n\t## Looks like they're trying to expand an array.\n\tset match [EvalAttached [list array names $ary $str*]]\n\tif {[llength $match] > 1} {\n\t    set vars $ary\\([ExpandBestMatch $match $str]\n\t    foreach var $match {\n\t\tlappend vars $ary\\($var\\)\n\t    }\n\t    return $vars\n\t} elseif {[llength $match] == 1} {\n\t    set match $ary\\($match\\)\n\t}\n\t## Space transformation avoided for array names.\n    } else {\n\tset match [EvalAttached [list info vars $str*]]\n\tif {[llength $match] > 1} {\n\t    regsub -all { } [ExpandBestMatch $match $str] {\\\\ } str\n\t    set match [linsert $match 0 $str]\n\t} else {\n\t    regsub -all { } $match {\\\\ } match\n\t}\n    }\n    return $match\n}\n\n# ::tk::console::ExpandBestMatch --\n#\n# Finds the best unique match in a list of names.\n# The extra $e in this argument allows us to limit the innermost loop a little\n# further.  This improves speed as $l becomes large or $e becomes long.\n#\n# Arguments:\n#\tl\t- list to find best unique match in\n#\te\t- currently best known unique match\n#\n# Returns:\tlongest unique match in the list\n\nproc ::tk::console::ExpandBestMatch {l {e {}}} {\n    set ec [lindex $l 0]\n    if {[llength $l]>1} {\n\tset e [expr {[string length $e] - 1}]\n\tset ei [expr {[string length $ec] - 1}]\n\tforeach l $l {\n\t    while {$ei>=$e && [string first $ec $l]} {\n\t\tset ec [string range $ec 0 [incr ei -1]]\n\t    }\n\t}\n    }\n    return $ec\n}\n\n# now initialize the console\n::tk::ConsoleInit\n"
  },
  {
    "path": "library/demos/README",
    "content": "This directory contains a collection of programs to demonstrate\nthe features of the Tk toolkit.  The programs are all scripts for\n\"wish\", a windowing shell.  If wish has been installed on your path\nthen you can invoke any of the programs in this directory just\nby typing its file name to your command shell under Unix.  Otherwise\ninvoke wish with the file as its first argument, e.g., \"wish hello\".\nThe rest of this file contains a brief description of each program.\nFiles with names ending in \".tcl\" are procedure packages used by one\nor more of the demo programs;  they can't be used as programs by\nthemselves so they aren't described below.\n\nhello -\t\tCreates a single button;  if you click on it, a message\n\t\tis typed and the application terminates.\n\nwidget -\tContains a collection of demonstrations of the widgets\n\t\tcurrently available in the Tk library.  Most of the .tcl\n\t\tfiles are scripts for individual demos available through\n\t\tthe \"widget\" program.\n\nixset -\t\tA simple Tk-based wrapper for the \"xset\" program, which\n\t\tallows you to interactively query and set various X options\n\t\tsuch as mouse acceleration and bell volume.  Thanks to\n\t\tPierre David for contributing this example.\n\nrolodex -\tA mock-up of a simple rolodex application.  It has much of\n\t\tthe user interface for such an application but no back-end\n\t\tdatabase.  This program was written in response to Tom\n\t\tLaStrange's toolkit benchmark challenge.\n\ntcolor -\tA color editor.  Allows you to edit colors in several\n\t\tdifferent ways, and will also perform automatic updates\n\t\tusing \"send\".\n\nrmt -\t\tAllows you to \"hook-up\" remotely to any Tk application\n\t\ton the display.  Select an application with the menu,\n\t\tthen just type commands:  they'll go to that application.\n\ntimer -\t\tDisplays a seconds timer with start and stop buttons.\n\t\tControl-c and control-q cause it to exit.\n\nbrowse -\tA simple directory browser.  Invoke it with and argument\n\t\tgiving the name of the directory you'd like to browse.\n\t\tDouble-click on files or subdirectories to browse them.\n\t\tControl-c and control-q cause the program to exit.\n"
  },
  {
    "path": "library/demos/accessiblewidget",
    "content": "set widgetDemo 1\n\nwm withdraw .\n\nset _w  [toplevel .acc]\nwm title $_w \"Accessible Widget Demo\"\nwm resizable $_w 0 0\nset tk_demoDirectory [file join [pwd] [file dirname [info script]]]\n\nttk::label $_w.x -text \"This is a demonstration of accessible widgets in Tcl/Tk. Please click on the buttons\nbelow to interact with the different widgets and see how they support accessibility.\" -padding 5\n\npack $_w.x -side top -fill x -expand no\n\npack [ttk::frame $_w.f] -side bottom -fill x -expand no\n\nset data {\n{{Buttons} button.tcl}\n{{Check-buttons (select any of a group)} check.tcl}\n{{Radio-buttons (select one of a group)} radio.tcl}\n{{The simple Themed Tk widgets}  ttkbut.tcl}\n{{Color picker} clrpick.tcl}\n{{File selection dialog}  filebox.tcl}\n{{Font selection dialog} fontchoose.tcl}\n{{Message boxes} msgbox.tcl}\n{{A list of the 50 states} states.tcl}\n{{A table of countries} mclist.tcl}\n{{A directory browser tree} tree.tcl}\n{{Combo-boxes} combo.tcl}\n{{Entry} entry1.tcl}\n{{Editable text} text.tcl}\n{{Spin-box} ttkspin.tcl}\n{{Menus} menu.tcl}\n{{Notebook} ttknote.tcl}\n{{Paned window} ttkpane.tcl}\n{{Scale} hscale.tcl}\n}\n\nforeach item $data {\nset name [file rootname [file tail [lindex $item 1]]]\nset srcfile [file join $tk_demoDirectory [file tail [lindex $item 1]]]\nset btn [ttk::button $_w.f.$name -text [lindex $item 0] -padding 5 -command [list source $srcfile]]\npack $btn -fill x -expand no\n}\n\nreturn\n\n\n# Local Variables:\n# mode: tcl\n# End:\n\n\n\n\n\n\n\n"
  },
  {
    "path": "library/demos/anilabel.tcl",
    "content": "# anilabel.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several animated label widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .anilabel\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Animated Label Demonstration\"\nwm iconname $w \"anilabel\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Four animated labels are displayed below; each of the labels on the left is animated by making the text message inside it appear to scroll, and the label on the right is animated by animating the image that it displays.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Ensure that this this is an array\narray set animationCallbacks {}\n\n## This callback is the core of how to do animation in Tcl/Tk; all\n## animations work in basically the same way, with a procedure that\n## uses the [after] command to reschedule itself at some point in the\n## future. Of course, the details of how to update the state will vary\n## according to what is being animated.\nproc RotateLabelText {w interval} {\n    global animationCallbacks\n\n    # Schedule the calling of this procedure again in the future\n    set animationCallbacks($w) [after $interval RotateLabelText $w $interval]\n\n    # We do marquee-like scrolling text by chopping characters off the\n    # front of the text and sticking them on the end.\n    set text [$w cget -text]\n    set newText [string range $text 1 end][string index $text 0]\n    $w configure -text $newText\n}\n\n## A helper procedure to start the animation happening.\nproc animateLabelText {w text interval} {\n    global animationCallbacks\n\n    # Install the text into the widget\n    $w configure -text $text\n\n    # Schedule the start of the animation loop\n    set animationCallbacks($w) [after $interval RotateLabelText $w $interval]\n\n    # Make sure that the animation stops and is cleaned up after itself\n    # when the animated label is destroyed.  Note that at this point we\n    # cannot manipulate the widget itself, as that has already died.\n    bind $w <Destroy> {\n\tafter cancel $animationCallbacks(%W)\n\tunset animationCallbacks(%W)\n    }\n}\n\n## Next, a similar pair of procedures to animate a GIF loaded into a\n## photo image.\nproc SelectNextImageFrame {w interval} {\n    global animationCallbacks image zoomFactor\n    set animationCallbacks($w) \\\n\t    [after $interval SelectNextImageFrame $w $interval]\n    set image2 [$w cget -image]\n\n    # The easy way to animate a GIF!\n    set idx -1\n    scan [$image cget -format] \"GIF -index %d\" idx\n    if {[catch {\n\t# Note that we get an error if the index is out of range\n\t$image configure -format \"GIF -index [incr idx]\"\n    }]} then {\n\t$image configure -format \"GIF -index 0\"\n    }\n    $image2 copy $image -zoom $zoomFactor\n}\nproc animateLabelImage {w imageData interval} {\n    global animationCallbacks image zoomFactor\n\n    # Create a multi-frame GIF from base-64-encoded data\n    set image [image create photo -format GIF -data $imageData]\n\n    # Create a copy of the image just created, magnified according to the\n    # display's DPI scaling level.  Since the zooom factor must be an integer,\n    # the copy will only be effectively magnified if $tk::scalingPct >= 200.\n    set image2 [image create photo]\n    set zoomFactor [expr {$tk::scalingPct / 100}]\n    $image2 copy $image -zoom $zoomFactor\n\n    # Install the image copy into the widget\n    $w configure -image $image2\n\n    # Schedule the start of the animation loop\n    set animationCallbacks($w) \\\n\t    [after $interval SelectNextImageFrame $w $interval]\n\n    # Make sure that the animation stops and is cleaned up after itself\n    # when the animated label is destroyed.  Note that at this point we\n    # cannot manipulate the widget itself, as that has already died.\n    # Also note that this script is in double-quotes; this is always OK\n    # because image names are chosen automatically to be simple words.\n    bind $w <Destroy> \"\n\tafter cancel \\$animationCallbacks(%W)\n\tunset animationCallbacks(%W)\n\trename $image {}\n    \"\n}\n\n# Make some widgets to contain the animations\nlabelframe $w.left -text \"Scrolling Texts\"\nlabelframe $w.right -text \"GIF Image\"\npack $w.left $w.right -side left -padx 7.5p -pady 7.5p -expand yes\n\n# This method of scrolling text looks far better with a fixed-width font\nlabel $w.left.l1 -bd 3p -relief ridge -font fixedFont\nlabel $w.left.l2 -bd 3p -relief groove -font fixedFont\nlabel $w.left.l3 -bd 3p -relief flat -font fixedFont -width 18\npack $w.left.l1 $w.left.l2 $w.left.l3 -side top -expand yes -padx 7.5p -pady 7.5p -anchor w\n# Don't need to do very much with this label except turn off the border\nlabel $w.right.l -bd 0\npack $w.right.l -side top -expand yes -padx 7.5p -pady 7.5p\n\n# This is a base-64-encoded animated GIF file.\nset tclPoweredData {\n    R0lGODlhKgBAAPQAAP//////zP//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM\n    zMyZmcyZZsxmZsxmAMwzAJnMzJmZzJmZmZlmmZlmZplmM5kzM2aZzGZmzGZm\n    mWZmZmYzZmYzMzNmzDMzZgAzmSH+IE1hZGUgd2l0aCBHSU1QIGJ5IExARGVt\n    YWlsbHkuY29tACH5BAVkAAEALAAAAAAqAEAAAAX+YCCOZEkyTKM2jOm66yPP\n    dF03bx7YcuHIDkGBR7SZeIyhTID4FZ+4Es8nQyCe2EeUNJ0peY2s9mi7PhAM\n    ngEAMGRbUpvzSxskLh1J+Hkg134OdDIDEB+GHxtYMEQMTjMGEYeGFoomezaC\n    DZGSHFmLXTQKkh8eNQVpZ2afmDQGHaOYSoEyhhcklzVmMpuHnaZmDqiGJbg0\n    qFqvh6UNAwB7VA+OwydEjgujkgrPNhbTI8dFvNgEYcHcHx0lB1kX2IYeA2G6\n    NN0YfkXJ2BsAMuAzHB9cZMk3qoEbRzUACsRCUBK5JxsC3iMiKd8GN088SIyT\n    0RAFSROyeEg38caDiB/+JEgqxsODrZJ1BkT0oHKSmI0ceQxo94HDpg0qsuDk\n    UmRAMgu8OgwQ+uIJgUMVeGXA+IQkzEeHGvD8cIGlDXsLiRjQ+EHroQhea7xY\n    8IQBSgYYDi1IS+OFBCgaDMGVS3fGi5BPJpBaENdQ0EomKGD56IHwO39EXiSC\n    Ysgxor5+Xfgq0qByYUpiXmwuoredB2aYH4gWWda0B7SeNENpEJHC1ghi+pS4\n    AJpIAwWvKPBi+8YEht5EriEqpFfMlhEdkBNpx0HUhwypx5T4IB1MBg/Ws2sn\n    wV3MSQOkzI8fUd48Aw3dOZto71x85hHtHijYv18Gf/3GqCdDCXHNoICBobSo\n    IqBqJLyCoH8JPrLgdh88CKCFD0CGmAiGYPgffwceZh6FC2ohIIklnkhehTNY\n    4CIHHGzgwYw01ujBBhvAqKOLLq5AAk9kuSPkkKO40NB+h1gnypJIIvkBf09a\n    N5QIRz5p5ZJXJpmlIVhOGQA2TmIJZZhKKmmll2BqyWSXWUrZpQtpatlmk1c2\n    KaWRHeTZEJF8SqLDn/hhsOeQgBbqAh6DGqronxeARUIIACH5BAUeAAAALAUA\n    LgAFAAUAAAUM4CeKz/OV5YmqaRkCACH5BAUeAAEALAUALgAKAAUAAAUUICCK\n    z/OdJVCaa7p+7aOWcDvTZwgAIfkEBR4AAQAsCwAuAAkABQAABRPgA4zP95zA\n    eZqoWqqpyqLkZ38hACH5BAUKAAEALAcALgANAA4AAAU7ICA+jwiUJEqeKau+\n    r+vGaTmac63v/GP9HM7GQyx+jsgkkoRUHJ3Qx0cK/VQVTKtWwbVKn9suNunc\n    WkMAIfkEBQoAAAAsBwA3AAcABQAABRGgIHzk842j+Yjlt5KuO8JmCAAh+QQF\n    CgAAACwLADcABwAFAAAFEeAnfN9TjqP5oOWziq05lmUIACH5BAUKAAAALA8A\n    NwAHAAUAAAUPoPCJTymS3yiQj4qOcPmEACH5BAUKAAAALBMANwAHAAUAAAUR\n    oCB+z/MJX2o+I2miKimiawgAIfkEBQoAAAAsFwA3AAcABQAABRGgIHzfY47j\n    Q4qk+aHl+pZmCAAh+QQFCgAAACwbADcABwAFAAAFEaAgfs/zCV9qPiNJouo7\n    ll8IACH5BAUKAAAALB8ANwADAAUAAAUIoCB8o0iWZggAOw==\n}\n\n# Finally, set up the text scrolling animation\nanimateLabelText $w.left.l1 \"* Slow Animation *\" 300\nanimateLabelText $w.left.l2 \"* Fast Animation *\" 80\nanimateLabelText $w.left.l3 \"This is a longer scrolling text in a widget that will not show the whole message at once. \" 150\nanimateLabelImage $w.right.l $tclPoweredData 100\n"
  },
  {
    "path": "library/demos/aniwave.tcl",
    "content": "# aniwave.tcl --\n#\n# This demonstration script illustrates how to adjust canvas item\n# coordinates in a way that does something fairly similar to waveform\n# display.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .aniwave\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Animated Wave Demonstration\"\nwm iconname $w \"aniwave\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This demonstration contains a canvas widget with a line item inside it. The animation routines work by adjusting the coordinates list of the line; a trace on a variable is used so updates to the variable result in a change of position of the line.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Create a canvas large enough to hold the wave. In fact, the wave\n# sticks off both sides of the canvas to prevent visual glitches.\npack [canvas $w.c -width 225p -height 150p -background black] -padx 7.5p -pady 7.5p -expand yes\n\n# Ensure that this this is an array\narray set animationCallbacks {}\n\n# Creates a coordinates list of a wave. This code does a very sketchy\n# job and relies on Tk's line smoothing to make things look better.\nset waveCoords {}\nfor {set x -10} {$x<=300} {incr x 5} {\n    lappend waveCoords $x 100\n}\nlappend waveCoords $x 0 [incr x 5] 200\n\n# Create a smoothed line and arrange for its coordinates to be the\n# contents of the variable waveCoords.\n$w.c create line $waveCoords -tags wave -width 0.75p -fill green -smooth 1\nproc waveCoordsTracer {w args} {\n    global waveCoords\n    # Actual visual update will wait until we have finished\n    # processing; Tk does that for us automatically.\n    $w.c coords wave $waveCoords\n\n    set scaleFactor [expr {$tk::scalingPct / 100.0}]\n    $w.c scale wave 0 0 $scaleFactor $scaleFactor\n}\ntrace add variable waveCoords write [list waveCoordsTracer $w]\n\n# Basic motion handler. Given what direction the wave is travelling\n# in, it advances the y coordinates in the coordinate-list one step in\n# that direction.\nproc basicMotion {} {\n    global waveCoords direction\n    set oc $waveCoords\n    for {set i 1} {$i<[llength $oc]} {incr i 2} {\n\tif {$direction eq \"left\"} {\n\t    lset waveCoords $i [lindex $oc \\\n\t\t    [expr {$i+2>[llength $oc] ? 1 : $i+2}]]\n\t} else {\n\t    lset waveCoords $i \\\n\t\t    [lindex $oc [expr {$i-2<0 ? \"end\" : $i-2}]]\n\t}\n    }\n}\n\n# Oscillation handler. This detects whether to reverse the direction\n# of the wave by checking to see if the peak of the wave has moved off\n# the screen (whose size we know already.)\nproc reverser {} {\n    global waveCoords direction\n    if {[lindex $waveCoords 1] < 10} {\n\tset direction \"right\"\n    } elseif {[lindex $waveCoords end] < 10} {\n\tset direction \"left\"\n    }\n}\n\n# Main animation \"loop\". This calls the two procedures that handle the\n# movement repeatedly by scheduling asynchronous calls back to itself\n# using the [after] command. This procedure is the fundamental basis\n# for all animated effect handling in Tk.\nproc move {} {\n    basicMotion\n    reverser\n\n    # Theoretically 100 frames-per-second (==10ms between frames)\n    global animationCallbacks\n    set animationCallbacks(simpleWave) [after 10 move]\n}\n\n# Initialise our remaining animation variables\nset direction \"left\"\nset animateAfterCallback {}\n# Arrange for the animation loop to stop when the canvas is deleted\nbind $w.c <Destroy> {\n    after cancel $animationCallbacks(simpleWave)\n    unset animationCallbacks(simpleWave)\n}\n# Start the animation processing\nmove\n"
  },
  {
    "path": "library/demos/arrow.tcl",
    "content": "# arrow.tcl --\n#\n# This demonstration script creates a canvas widget that displays a\n# large line with an arrowhead whose shape can be edited interactively.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# scl --\n# Scales an integer according to the display's current scaling percentage.\n#\n# Arguments:\n#   num -\tAn integer.\n\nproc scl num {\n    return [expr {round($num*$tk::scalingPct/100.0)}]\n}\n\n# arrowSetup --\n# This procedure regenerates all the text and graphics in the canvas\n# window.  It's called when the canvas is initially created, and also\n# whenever any of the parameters of the arrow head are changed\n# interactively.\n#\n# Arguments:\n# c -\t\tName of the canvas widget.\n\nproc arrowSetup c {\n    upvar #0 demo_arrowInfo v\n\n    # Remember the current box, if there is one.\n\n    set tags [$c gettags current]\n    if {$tags != \"\"} {\n\tset cur [lindex $tags [lsearch -glob $tags box?]]\n    } else {\n\tset cur \"\"\n    }\n\n    # Create the arrow and outline.\n\n    $c delete all\n    $c create line $v(x1) $v(y) $v(x2) $v(y) -arrow last \\\n\t    -width [expr {10*$v(width)}] -arrowshape [list \\\n\t    [expr {10*$v(a)}] [expr {10*$v(b)}] [expr {10*$v(c)}]] \\\n\t    {*}$v(bigLineStyle)\n    set xtip [expr {$v(x2)-10*$v(b)}]\n    set deltaY [expr {10*$v(c)+5*$v(width)}]\n    $c create line $v(x2) $v(y) $xtip [expr {$v(y)+$deltaY}] \\\n\t    [expr {$v(x2)-10*$v(a)}] $v(y) $xtip [expr {$v(y)-$deltaY}] \\\n\t    $v(x2) $v(y) -width 1.5p -capstyle round -joinstyle round\n\n    # Create the boxes for reshaping the line and arrowhead.\n\n    set _5 [scl 5]\n    $c create rect [expr {$v(x2)-10*$v(a)-$_5}] [expr {$v(y)-$_5}] \\\n\t    [expr {$v(x2)-10*$v(a)+$_5}] [expr {$v(y)+$_5}] \\\n\t    -tags {box1 box} {*}$v(boxStyle)\n    $c create rect [expr {$xtip-$_5}] [expr {$v(y)-$deltaY-$_5}] \\\n\t    [expr {$xtip+$_5}] [expr {$v(y)-$deltaY+$_5}] \\\n\t    -tags {box2 box} {*}$v(boxStyle)\n    $c create rect [expr {$v(x1)-$_5}] [expr {$v(y)-5*$v(width)-$_5}] \\\n\t    [expr {$v(x1)+$_5}] [expr {$v(y)-5*$v(width)+$_5}] \\\n\t    -tags {box3 box} {*}$v(boxStyle)\n    if {$cur != \"\"} {\n\t$c itemconfigure $cur {*}$v(activeStyle)\n    }\n\n    # Create three arrows in actual size with the same parameters.\n\n    set _10  [scl 10]\n    set _15  [scl 15]\n    set _25  [scl 25]\n    set _50  [scl 50]\n    set _75  [scl 75]\n    set _125 [scl 125]\n    $c create line [expr {$v(x2)+$_50}] 0 [expr {$v(x2)+$_50}] 750p -width 1.5p\n    set tmp [expr {$v(x2)+[scl 100]}]\n    $c create line $tmp [expr {$v(y)-$_125}] $tmp [expr {$v(y)-$_75}] \\\n\t    -width $v(width) -arrow both -arrowshape \"$v(a) $v(b) $v(c)\"\n    $c create line [expr {$tmp-$_25}] $v(y) [expr {$tmp+$_25}] $v(y) \\\n\t    -width $v(width) -arrow both -arrowshape \"$v(a) $v(b) $v(c)\"\n    $c create line [expr {$tmp-$_25}] [expr {$v(y)+$_75}] \\\n\t    [expr {$tmp+$_25}] [expr {$v(y)+$_125}] \\\n\t    -width $v(width) -arrow both -arrowshape \"$v(a) $v(b) $v(c)\"\n\n    # Create a bunch of other arrows and text items showing the\n    # current dimensions.\n\n    set tmp [expr {$v(x2)+$_10}]\n    $c create line $tmp [expr {$v(y)-5*$v(width)}] \\\n\t    $tmp [expr {$v(y)-$deltaY}] \\\n\t    -arrow both -arrowshape $v(smallTips)\n    $c create text [expr {$v(x2)+$_15}] [expr {$v(y)-$deltaY+5*$v(c)}] \\\n\t    -text $v(c) -anchor w\n    set tmp [expr {$v(x1)-$_10}]\n    $c create line $tmp [expr {$v(y)-5*$v(width)}] \\\n\t    $tmp [expr {$v(y)+5*$v(width)}] \\\n\t    -arrow both -arrowshape $v(smallTips)\n    $c create text [expr {$v(x1)-$_15}] $v(y) -text $v(width) -anchor e\n    set tmp [expr {$v(y)+5*$v(width)+10*$v(c)+$_10}]\n    $c create line [expr {$v(x2)-10*$v(a)}] $tmp $v(x2) $tmp \\\n\t    -arrow both -arrowshape $v(smallTips)\n    $c create text [expr {$v(x2)-5*$v(a)}] [expr {$tmp+$_5}] \\\n\t    -text $v(a) -anchor n\n    set tmp [expr {$tmp+$_25}]\n    $c create line [expr {$v(x2)-10*$v(b)}] $tmp $v(x2) $tmp \\\n\t    -arrow both -arrowshape $v(smallTips)\n    $c create text [expr {$v(x2)-5*$v(b)}] [expr {$tmp+$_5}] \\\n\t    -text $v(b) -anchor n\n\n    $c create text $v(x1) 232.5p -text \"-width  $v(width)\" \\\n\t    -anchor w -font {Helvetica 18}\n    $c create text $v(x1) 247.5p -text \"-arrowshape  {$v(a)  $v(b)  $v(c)}\" \\\n\t    -anchor w -font {Helvetica 18}\n\n    incr v(count)\n}\n\nset w .arrow\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Arrowhead Editor Demonstration\"\nwm iconname $w \"arrow\"\npositionWindow $w\nset c $w.c\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"This widget allows you to experiment with different widths and arrowhead shapes for lines in canvases.  To change the line width or the shape of the arrowhead, drag any of the three boxes attached to the oversized arrow.  The arrows on the right give examples at normal scale.  The text at the bottom shows the configuration options as you'd enter them for a canvas line item.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\ncanvas $c -width 375p -height 262.5p -relief sunken -borderwidth 2\npack $c -expand yes -fill both\n\nset demo_arrowInfo(a)\t  [scl 8]\nset demo_arrowInfo(b)\t  [scl 10]\nset demo_arrowInfo(c)\t  [scl 3]\nset demo_arrowInfo(width) [scl 2]\nset demo_arrowInfo(motionProc) arrowMoveNull\nset demo_arrowInfo(x1)\t  [scl 40]\nset demo_arrowInfo(x2)\t  [scl 350]\nset demo_arrowInfo(y)\t  [scl 150]\nset demo_arrowInfo(smallTips) {3.75p 3.75p 1.5p}\nset demo_arrowInfo(count) 0\nif {[winfo depth $c] > 1} {\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tset demo_arrowInfo(bigLineStyle) \"-fill systemSelectedTextBackgroundColor\"\n    } else {\n\tset demo_arrowInfo(bigLineStyle) \"-fill LightSeaGreen\"\n    }\n    set demo_arrowInfo(boxStyle) \"-fill {} -width 0.75p\"\n    set demo_arrowInfo(activeStyle) \"-fill red -width 0.75p\"\n} else {\n    # Main widget program sets variable tk_demoDirectory\n    set demo_arrowInfo(bigLineStyle) \"-fill black \\\n\t-stipple @[file join $tk_demoDirectory images grey.25]\"\n    set demo_arrowInfo(boxStyle) \"-fill {} -outline black -width 0.75p\"\n    set demo_arrowInfo(activeStyle) \"-fill black -outline black -width 0.75p\"\n}\narrowSetup $c\n$c bind box <Enter> \"$c itemconfigure current $demo_arrowInfo(activeStyle)\"\n$c bind box <Leave> \"$c itemconfigure current $demo_arrowInfo(boxStyle)\"\n$c bind box <B1-Enter> \" \"\n$c bind box <B1-Leave> \" \"\n$c bind box1 <Button-1> {set demo_arrowInfo(motionProc) arrowMove1}\n$c bind box2 <Button-1> {set demo_arrowInfo(motionProc) arrowMove2}\n$c bind box3 <Button-1> {set demo_arrowInfo(motionProc) arrowMove3}\n$c bind box <B1-Motion> \"\\$demo_arrowInfo(motionProc) $c %x %y\"\nbind $c <ButtonRelease-1> \"arrowSetup $c\"\n\n# arrowMove1 --\n# This procedure is called for each mouse motion event on box1 (the\n# one at the vertex of the arrow).  It updates the controlling parameters\n# for the line and arrowhead.\n#\n# Arguments:\n# c -\t\tThe name of the canvas window.\n# x, y -\tThe coordinates of the mouse.\n\nproc arrowMove1 {c x y} {\n    upvar #0 demo_arrowInfo v\n    set newA [expr {($v(x2)+[scl 5]-round([$c canvasx $x]))/10}]\n    if {$newA < 0} {\n\tset newA 0\n    }\n    set _25 [scl 25]\n    if {$newA > $_25} {\n\tset newA $_25\n    }\n    if {$newA != $v(a)} {\n\t$c move box1 [expr {10*($v(a)-$newA)}] 0\n\tset v(a) $newA\n    }\n}\n\n# arrowMove2 --\n# This procedure is called for each mouse motion event on box2 (the\n# one at the trailing tip of the arrowhead).  It updates the controlling\n# parameters for the line and arrowhead.\n#\n# Arguments:\n# c -\t\tThe name of the canvas window.\n# x, y -\tThe coordinates of the mouse.\n\nproc arrowMove2 {c x y} {\n    upvar #0 demo_arrowInfo v\n    set _5 [scl 5]\n    set newB [expr {($v(x2)+$_5-round([$c canvasx $x]))/10}]\n    if {$newB < 0} {\n\tset newB 0\n    }\n    set _25 [scl 25]\n    if {$newB > $_25} {\n\tset newB $_25\n    }\n    set newC [expr {($v(y)+$_5-round([$c canvasy $y])-5*$v(width))/10}]\n    if {$newC < 0} {\n\tset newC 0\n    }\n    set _20 [scl 20]\n    if {$newC > $_20} {\n\tset newC $_20\n    }\n    if {($newB != $v(b)) || ($newC != $v(c))} {\n\t$c move box2 [expr {10*($v(b)-$newB)}] [expr {10*($v(c)-$newC)}]\n\tset v(b) $newB\n\tset v(c) $newC\n    }\n}\n\n# arrowMove3 --\n# This procedure is called for each mouse motion event on box3 (the\n# one that controls the thickness of the line).  It updates the\n# controlling parameters for the line and arrowhead.\n#\n# Arguments:\n# c -\t\tThe name of the canvas window.\n# x, y -\tThe coordinates of the mouse.\n\nproc arrowMove3 {c x y} {\n    upvar #0 demo_arrowInfo v\n    set newWidth [expr {($v(y)+[scl 2]-round([$c canvasy $y]))/5}]\n    if {$newWidth < 0} {\n\tset newWidth 0\n    }\n    set _20 [scl 20]\n    if {$newWidth > $_20} {\n\tset newWidth $_20\n    }\n    if {$newWidth != $v(width)} {\n\t$c move box3 0 [expr {5*($v(width)-$newWidth)}]\n\tset v(width) $newWidth\n    }\n}\n"
  },
  {
    "path": "library/demos/bind.tcl",
    "content": "# bind.tcl --\n#\n# This demonstration script creates a text widget with bindings set\n# up for hypertext-like effects.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .bind\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Demonstration - Tag Bindings\"\nwm iconname $w \"bind\"\npositionWindow $w\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\ntext $w.text -yscrollcommand \"$w.scroll set\" -setgrid 1 \\\n\t-width 60 -height 24 -font $font -wrap word\nttk::scrollbar $w.scroll -command \"$w.text yview\"\npack $w.scroll -side right -fill y\npack $w.text -expand yes -fill both\n\n# Set up display styles.\n\nif {[winfo depth $w] > 1} {\n    set bold \"-background #43ce80 -relief raised -borderwidth 1\"\n    set normal \"-background {} -relief flat\"\n} else {\n    set bold \"-foreground white -background black\"\n    set normal \"-foreground {} -background {}\"\n}\n\n# Add text to widget.\n\n$w.text insert 0.0 {\\\nThe same tag mechanism that controls display styles in text widgets can also be used to associate Tcl commands with regions of text, so that mouse or keyboard actions on the text cause particular Tcl commands to be invoked.  For example, in the text below the descriptions of the canvas demonstrations have been tagged.  When you move the mouse over a demo description the description lights up, and when you press button 1 over a description then that particular demonstration is invoked.\n\n}\n$w.text insert end \\\n{1. Samples of all the different types of items that can be created in canvas widgets.} d1\n$w.text insert end \\n\\n\n$w.text insert end \\\n{2. A simple two-dimensional plot that allows you to adjust the positions of the data points.} d2\n$w.text insert end \\n\\n\n$w.text insert end \\\n{3. Anchoring and justification modes for text items.} d3\n$w.text insert end \\n\\n\n$w.text insert end \\\n{4. An editor for arrow-head shapes for line items.} d4\n$w.text insert end \\n\\n\n$w.text insert end \\\n{5. A ruler with facilities for editing tab stops.} d5\n$w.text insert end \\n\\n\n$w.text insert end \\\n{6. A grid that demonstrates how canvases can be scrolled.} d6\n\n# Create bindings for tags.\n\nforeach tag {d1 d2 d3 d4 d5 d6} {\n    $w.text tag bind $tag <Enter> \"$w.text tag configure $tag $bold\"\n    $w.text tag bind $tag <Leave> \"$w.text tag configure $tag $normal\"\n}\n# Main widget program sets variable tk_demoDirectory\n$w.text tag bind d1 <Button-1> {source [file join $tk_demoDirectory items.tcl]}\n$w.text tag bind d2 <Button-1> {source [file join $tk_demoDirectory plot.tcl]}\n$w.text tag bind d3 <Button-1> {source [file join $tk_demoDirectory ctext.tcl]}\n$w.text tag bind d4 <Button-1> {source [file join $tk_demoDirectory arrow.tcl]}\n$w.text tag bind d5 <Button-1> {source [file join $tk_demoDirectory ruler.tcl]}\n$w.text tag bind d6 <Button-1> {source [file join $tk_demoDirectory cscroll.tcl]}\n\n$w.text mark set insert 0.0\n$w.text configure -state disabled\n"
  },
  {
    "path": "library/demos/bitmap.tcl",
    "content": "# bitmap.tcl --\n#\n# This demonstration script creates a toplevel window that displays\n# all of Tk's built-in bitmaps.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# bitmapRow --\n# Create a row of bitmap items in a window.\n#\n# Arguments:\n# w -\t\tThe window that is to contain the row.\n# args -\tThe names of one or more bitmaps, which will be displayed\n#\t\tin a new row across the bottom of w along with their\n#\t\tnames.\n\nproc bitmapRow {w args} {\n    frame $w\n    pack $w -side top -fill both\n    set i 0\n    foreach bitmap $args {\n\tframe $w.$i\n\tpack $w.$i -side left -fill both -pady .25c -padx .25c\n\tlabel $w.$i.bitmap -bitmap $bitmap\n\tlabel $w.$i.label -text $bitmap -width 9\n\tpack $w.$i.label $w.$i.bitmap -side bottom\n\tincr i\n    }\n}\n\nset w .bitmap\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Bitmap Demonstration\"\nwm iconname $w \"bitmap\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This window displays all of Tk's built-in bitmaps, along with the names you can use for them in Tcl scripts.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame\nbitmapRow $w.frame.0 error gray12 gray25 gray50 gray75\nbitmapRow $w.frame.1 hourglass info question questhead warning\npack $w.frame -side top -expand yes -fill both\n"
  },
  {
    "path": "library/demos/browse",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# browse --\n# This script generates a directory browser, which lists the working\n# directory and allows you to open files or subdirectories by\n# double-clicking.\n\npackage require tk\n\n# Create a scrollbar on the right side of the main window and a listbox\n# on the left side.\n\nscrollbar .scroll -command \".list yview\"\npack .scroll -side right -fill y\nlistbox .list -yscroll \".scroll set\" -relief sunken -width 20 -height 20 \\\n\t-setgrid 1\npack .list -side left -fill both -expand yes\nwm minsize . 1 1\n\n# The procedure below is invoked to open a browser on a given file;  if the\n# file is a directory then another instance of this program is invoked; if\n# the file is a regular file then the Mx editor is invoked to display\n# the file.\n\nset browseScript [file join [pwd] $argv0]\nproc browse {dir file} {\n    global env browseScript\n    if {[string compare $dir \".\"] != 0} {set file $dir/$file}\n    switch [file type $file] {\n\tdirectory {\n\t    exec [info nameofexecutable] $browseScript $file &\n\t}\n\tfile {\n\t    if {[info exists env(EDITOR)]} {\n\t\teval exec $env(EDITOR) $file &\n\t    } else {\n\t\texec xedit $file &\n\t    }\n\t}\n\tdefault {\n\t    puts stdout \"\\\"$file\\\" isn't a directory or regular file\"\n\t}\n    }\n}\n\n# Fill the listbox with a list of all the files in the directory.\n\nif {$argc>0} {set dir [lindex $argv 0]} else {set dir \".\"}\nforeach i [lsort [glob * .* *.*]] {\n    if {[file type $i] eq \"directory\"} {\n\t# Safe to do since it is still a directory.\n\tappend i /\n    }\n    .list insert end $i\n}\n\n# Set up bindings for the browser.\n\nbind all <Control-c> {destroy .}\nbind .list <Double-Button-1> {foreach i [selection get] {browse $dir $i}}\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/button.tcl",
    "content": "# button.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several button widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .button\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Button Demonstration\"\nwm iconname $w \"button\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"If you click on any of the four buttons below, the background of the button area will change to the color indicated in the button.  You can press Tab to move among the buttons, then press Space to invoke the current button.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\nproc colorrefresh {w col} {\n    $w configure -bg $col\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t# set highlightbackground of all buttons in $w\n\tset l [list $w]\n\twhile {[llength $l]} {\n\t    set l [concat [lassign $l b] [winfo children $b]]\n\t    if {[winfo class $b] eq \"Button\"} {\n\t\t$b configure -highlightbackground $col\n\t    }\n\t}\n    }\n}\n\nbutton $w.b1 -text \"Peach Puff\" -width 10 \\\n    -command [list colorrefresh $w PeachPuff1]\nbutton $w.b2 -text \"Light Blue\" -width 10 \\\n    -command [list colorrefresh $w LightBlue1]\nbutton $w.b3 -text \"Sea Green\" -width 10 \\\n    -command [list colorrefresh $w SeaGreen2]\nbutton $w.b4 -text \"Yellow\" -width 10 \\\n    -command [list colorrefresh $w Yellow1]\npack $w.b1 $w.b2 $w.b3 $w.b4 -side top -expand yes -pady 1.5p\n"
  },
  {
    "path": "library/demos/check.tcl",
    "content": "# check.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several checkbuttons.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .check\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Checkbutton Demonstration\"\nwm iconname $w \"check\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Four checkbuttons are displayed below.  If you click on a button, it will toggle the button's selection state and set a Tcl variable to a value indicating the state of the checkbutton.  The first button also follows the state of the other three.  If only some of the three are checked, the first button will display the tri-state mode. Click the \\\"See Variables\\\" button to see the current values of the variables.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w [list safety wipers brakes sober]]\npack $btns -side bottom -fill x\n\ncheckbutton $w.b0 -text \"Safety Check\" -variable safety -relief flat \\\n    -onvalue \"all\" \\\n    -offvalue \"none\" \\\n    -tristatevalue \"partial\"\ncheckbutton $w.b1 -text \"Wipers OK\" -variable wipers -relief flat\ncheckbutton $w.b2 -text \"Brakes OK\" -variable brakes -relief flat\ncheckbutton $w.b3 -text \"Driver Sober\" -variable sober -relief flat\npack $w.b0 -side top -pady 1.5p -anchor w\npack $w.b1 $w.b2 $w.b3 -side top -pady 1.5p -anchor w -padx 12p\n\n## This code makes $w.b0 function as a tri-state button; it's not\n## needed at all for just straight yes/no buttons.\n\nset in_check 0\nproc tristate_check {n1 n2 op} {\n    global safety wipers brakes sober in_check\n    if {$in_check} {\n\treturn\n    }\n    set in_check 1\n    if {$n1 eq \"safety\"} {\n\tif {$safety eq \"none\"} {\n\t    set wipers 0\n\t    set brakes 0\n\t    set sober 0\n\t} elseif {$safety eq \"all\"} {\n\t    set wipers 1\n\t    set brakes 1\n\t    set sober 1\n\t}\n    } else {\n\tif {$wipers == 1 && $brakes == 1 && $sober == 1} {\n\t    set safety all\n\t} elseif {$wipers == 1 || $brakes == 1 || $sober == 1} {\n\t    set safety partial\n\t} else {\n\t    set safety none\n\t}\n    }\n    set in_check 0\n}\n\ntrace add variable wipers write tristate_check\ntrace add variable brakes write tristate_check\ntrace add variable sober  write tristate_check\ntrace add variable safety write tristate_check\n"
  },
  {
    "path": "library/demos/clrpick.tcl",
    "content": "# clrpick.tcl --\n#\n# This demonstration script prompts the user to select a color.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .clrpick\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Color Selection Dialog\"\nwm iconname $w \"colors\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Press the buttons below to choose the foreground and background colors for the widgets in this window.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nbutton $w.back -text \"Set background color ...\" \\\n    -command \\\n    \"setColor $w $w.back background {-background -highlightbackground}\"\nbutton $w.fore -text \"Set foreground color ...\" \\\n    -command \\\n    \"setColor $w $w.back foreground -foreground\"\n\npack $w.back $w.fore -side top -anchor c -pady 2m\n\nproc setColor {w button name options} {\n    grab $w\n    set initialColor [$button cget -$name]\n    set color [tk_chooseColor -title \"Choose a $name color\" -parent $w \\\n\t-initialcolor $initialColor]\n    if {[string compare $color \"\"]} {\n\tsetColor_helper $w $options $color\n    }\n    grab release $w\n}\n\nproc setColor_helper {w options color} {\n    foreach option $options {\n\tcatch {\n\t    $w config $option $color\n\t}\n    }\n    foreach child [winfo children $w] {\n\tsetColor_helper $child $options $color\n    }\n}\n"
  },
  {
    "path": "library/demos/colors.tcl",
    "content": "# colors.tcl --\n#\n# This demonstration script creates a listbox widget that displays\n# many of the colors from the X color database.  You can click on\n# a color to change the application's palette.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .colors\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Listbox Demonstration (colors)\"\nwm iconname $w \"Listbox\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"A listbox containing several color names is displayed below, along with a scrollbar.  You can scan the list either using the scrollbar or by dragging in the listbox window with button 2 pressed.  If you double-click button 1 on a color, then the application's color palette will be set to match that color\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth 7.5p\npack $w.frame -side top -expand yes -fill y\n\nttk::scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\nlistbox $w.frame.list -yscroll \"$w.frame.scroll set\" \\\n\t-width 20 -height 16 -setgrid 1\npack $w.frame.list $w.frame.scroll -side left -fill y -expand 1\n\nbind $w.frame.list <Double-Button-1> {\n    tk_setPalette [selection get]\n}\n$w.frame.list insert 0 gray60 gray70 gray80 gray85 gray90 gray95 \\\n    snow1 snow2 snow3 snow4 seashell1 seashell2 \\\n    seashell3 seashell4 AntiqueWhite1 AntiqueWhite2 AntiqueWhite3 \\\n    AntiqueWhite4 bisque1 bisque2 bisque3 bisque4 PeachPuff1 \\\n    PeachPuff2 PeachPuff3 PeachPuff4 NavajoWhite1 NavajoWhite2 \\\n    NavajoWhite3 NavajoWhite4 LemonChiffon1 LemonChiffon2 \\\n    LemonChiffon3 LemonChiffon4 cornsilk1 cornsilk2 cornsilk3 \\\n    cornsilk4 ivory1 ivory2 ivory3 ivory4 honeydew1 honeydew2 \\\n    honeydew3 honeydew4 LavenderBlush1 LavenderBlush2 \\\n    LavenderBlush3 LavenderBlush4 MistyRose1 MistyRose2 \\\n    MistyRose3 MistyRose4 azure1 azure2 azure3 azure4 \\\n    SlateBlue1 SlateBlue2 SlateBlue3 SlateBlue4 RoyalBlue1 \\\n    RoyalBlue2 RoyalBlue3 RoyalBlue4 blue1 blue2 blue3 blue4 \\\n    DodgerBlue1 DodgerBlue2 DodgerBlue3 DodgerBlue4 SteelBlue1 \\\n    SteelBlue2 SteelBlue3 SteelBlue4 DeepSkyBlue1 DeepSkyBlue2 \\\n    DeepSkyBlue3 DeepSkyBlue4 SkyBlue1 SkyBlue2 SkyBlue3 \\\n    SkyBlue4 LightSkyBlue1 LightSkyBlue2 LightSkyBlue3 \\\n    LightSkyBlue4 SlateGray1 SlateGray2 SlateGray3 SlateGray4 \\\n    LightSteelBlue1 LightSteelBlue2 LightSteelBlue3 \\\n    LightSteelBlue4 LightBlue1 LightBlue2 LightBlue3 \\\n    LightBlue4 LightCyan1 LightCyan2 LightCyan3 LightCyan4 \\\n    PaleTurquoise1 PaleTurquoise2 PaleTurquoise3 PaleTurquoise4 \\\n    CadetBlue1 CadetBlue2 CadetBlue3 CadetBlue4 turquoise1 \\\n    turquoise2 turquoise3 turquoise4 cyan1 cyan2 cyan3 cyan4 \\\n    DarkSlateGray1 DarkSlateGray2 DarkSlateGray3 \\\n    DarkSlateGray4 aquamarine1 aquamarine2 aquamarine3 \\\n    aquamarine4 DarkSeaGreen1 DarkSeaGreen2 DarkSeaGreen3 \\\n    DarkSeaGreen4 SeaGreen1 SeaGreen2 SeaGreen3 SeaGreen4 \\\n    PaleGreen1 PaleGreen2 PaleGreen3 PaleGreen4 SpringGreen1 \\\n    SpringGreen2 SpringGreen3 SpringGreen4 green1 green2 \\\n    green3 green4 chartreuse1 chartreuse2 chartreuse3 \\\n    chartreuse4 OliveDrab1 OliveDrab2 OliveDrab3 OliveDrab4 \\\n    DarkOliveGreen1 DarkOliveGreen2 DarkOliveGreen3 \\\n    DarkOliveGreen4 khaki1 khaki2 khaki3 khaki4 \\\n    LightGoldenrod1 LightGoldenrod2 LightGoldenrod3 \\\n    LightGoldenrod4 LightYellow1 LightYellow2 LightYellow3 \\\n    LightYellow4 yellow1 yellow2 yellow3 yellow4 gold1 gold2 \\\n    gold3 gold4 goldenrod1 goldenrod2 goldenrod3 goldenrod4 \\\n    DarkGoldenrod1 DarkGoldenrod2 DarkGoldenrod3 DarkGoldenrod4 \\\n    RosyBrown1 RosyBrown2 RosyBrown3 RosyBrown4 IndianRed1 \\\n    IndianRed2 IndianRed3 IndianRed4 sienna1 sienna2 sienna3 \\\n    sienna4 burlywood1 burlywood2 burlywood3 burlywood4 wheat1 \\\n    wheat2 wheat3 wheat4 tan1 tan2 tan3 tan4 chocolate1 \\\n    chocolate2 chocolate3 chocolate4 firebrick1 firebrick2 \\\n    firebrick3 firebrick4 brown1 brown2 brown3 brown4 salmon1 \\\n    salmon2 salmon3 salmon4 LightSalmon1 LightSalmon2 \\\n    LightSalmon3 LightSalmon4 orange1 orange2 orange3 orange4 \\\n    DarkOrange1 DarkOrange2 DarkOrange3 DarkOrange4 coral1 \\\n    coral2 coral3 coral4 tomato1 tomato2 tomato3 tomato4 \\\n    OrangeRed1 OrangeRed2 OrangeRed3 OrangeRed4 red1 red2 red3 \\\n    red4 DeepPink1 DeepPink2 DeepPink3 DeepPink4 HotPink1 \\\n    HotPink2 HotPink3 HotPink4 pink1 pink2 pink3 pink4 \\\n    LightPink1 LightPink2 LightPink3 LightPink4 PaleVioletRed1 \\\n    PaleVioletRed2 PaleVioletRed3 PaleVioletRed4 maroon1 \\\n    maroon2 maroon3 maroon4 VioletRed1 VioletRed2 VioletRed3 \\\n    VioletRed4 magenta1 magenta2 magenta3 magenta4 orchid1 \\\n    orchid2 orchid3 orchid4 plum1 plum2 plum3 plum4 \\\n    MediumOrchid1 MediumOrchid2 MediumOrchid3 MediumOrchid4 \\\n    DarkOrchid1 DarkOrchid2 DarkOrchid3 DarkOrchid4 purple1 \\\n    purple2 purple3 purple4 MediumPurple1 MediumPurple2 \\\n    MediumPurple3 MediumPurple4 thistle1 thistle2 thistle3 \\\n    thistle4\n"
  },
  {
    "path": "library/demos/combo.tcl",
    "content": "# combo.tcl --\n#\n# This demonstration script creates several combobox widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .combo\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Combobox Demonstration\"\nwm iconname $w \"combo\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 5i -justify left -text \"Three different\\\n\tcombo-boxes are displayed below. You can add characters to the first\\\n\tone by pointing, clicking and typing, just as with an entry; pressing\\\n\tReturn will cause the current value to be added to the list that is\\\n\tselectable from the drop-down list, and you can choose other values\\\n\tby pressing the Down key, using the arrow keys to pick another one,\\\n\tand pressing Return again. The second combo-box is fixed to a\\\n\tparticular value, and cannot be modified at all. The third one only\\\n\tallows you to select values from its drop-down list of Australian\\\n\tcities.\"\npack $w.msg -side top -fill x\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w {firstValue secondValue ozCity}]\npack $btns -side bottom -fill x\n\nttk::frame $w.f\npack $w.f -fill both -expand 1\nset w $w.f\n\nset australianCities {\n    Canberra Sydney Melbourne Perth Adelaide Brisbane\n    Hobart Darwin \"Alice Springs\"\n}\nset secondValue unchangable\nset ozCity Sydney\n\nttk::labelframe $w.c1 -text \"Fully Editable\"\nttk::combobox $w.c1.c -textvariable firstValue -placeholder {Enter text here}\nttk::style configure TEntry -placeholderforeground gray50\nttk::labelframe $w.c2 -text Disabled\nttk::combobox $w.c2.c -textvariable secondValue -state disabled\nttk::labelframe $w.c3 -text \"Defined List Only\"\nttk::combobox $w.c3.c -textvariable ozCity -state readonly \\\n\t-values $australianCities\nbind $w.c1.c <Return> {\n    if {[%W get] ni [%W cget -values]} {\n\t%W configure -values [concat [%W cget -values] [list [%W get]]]\n    }\n}\n\npack $w.c1 $w.c2 $w.c3 -side top -pady 3p -padx 7.5p\npack $w.c1.c -pady 3p -padx 7.5p\npack $w.c2.c -pady 3p -padx 7.5p\npack $w.c3.c -pady 3p -padx 7.5p\n"
  },
  {
    "path": "library/demos/cscroll.tcl",
    "content": "# cscroll.tcl --\n#\n# This demonstration script creates a simple canvas that can be\n# scrolled in two dimensions.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .cscroll\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Scrollable Canvas Demonstration\"\nwm iconname $w \"cscroll\"\npositionWindow $w\nset c $w.c\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This window displays a canvas widget that can be scrolled by using the scrollbars, by dragging with button 2 in the canvas, by using a mouse wheel, or with the two-finger gesture on a touchpad.  If you click button 1 on one of the rectangles, its indices will be printed on stdout.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.grid\nscrollbar $w.hscroll -orient horizontal -command \"$c xview\"\nscrollbar $w.vscroll -command \"$c yview\"\ncanvas $c -relief sunken -borderwidth 2 -scrollregion {-11c -11c 50c 20c} \\\n\t-xscrollcommand \"$w.hscroll set\" \\\n\t-yscrollcommand \"$w.vscroll set\"\npack $w.grid -expand yes -fill both -padx 1 -pady 1\ngrid rowconfig    $w.grid 0 -weight 1 -minsize 0\ngrid columnconfig $w.grid 0 -weight 1 -minsize 0\n\ngrid $c -padx 1 -in $w.grid -pady 1 \\\n    -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.vscroll -in $w.grid -padx 1 -pady 1 \\\n    -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.hscroll -in $w.grid -padx 1 -pady 1 \\\n    -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news\n\n\nset bg [lindex [$c config -bg] 4]\nfor {set i 0} {$i < 20} {incr i} {\n    set x [expr {-10 + 3*$i}]\n    for {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {\n\t$c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \\\n\t\t-fill $bg -tags rect\n\t$c create text [expr {$x+1}]c [expr {$y+1}]c -text \"$i,$j\" \\\n\t    -anchor center -tags text\n    }\n}\n\n$c bind all <Enter> \"scrollEnter $c\"\n$c bind all <Leave> \"scrollLeave $c\"\n$c bind all <Button-1> \"scrollButton $c\"\nbind $c <Button-2> \"$c scan mark %x %y\"\nbind $c <B2-Motion> \"$c scan dragto %x %y\"\n\n# We must make sure that positive and negative movements are rounded\n# equally to integers, avoiding the problem that\n#     (int)1/-40 = -1,\n# but\n#     (int)-1/-40 = 0\n# The following code ensures equal +/- behaviour.\nbind $c <MouseWheel> {\n    if {%D >= 0} {\n\t%W yview scroll [expr {%D/-40}] units\n    } else {\n\t%W yview scroll [expr {(%D-39)/-40}] units\n    }\n}\nbind $c <Option-MouseWheel> {\n    if {%D >= 0} {\n\t%W yview scroll [expr {%D/-12}] units\n    } else {\n\t%W yview scroll [expr {(%D-11)/-12}] units\n    }\n}\nbind $c <Shift-MouseWheel> {\n    if {%D >= 0} {\n\t%W xview scroll [expr {%D/-40}] units\n    } else {\n\t%W xview scroll [expr {(%D-39)/-40}] units\n    }\n}\nbind $c <Shift-Option-MouseWheel> {\n    if {%D >= 0} {\n\t%W xview scroll [expr {%D/-12}] units\n    } else {\n\t%W xview scroll [expr {(%D-11)/-12}] units\n    }\n}\nbind $c <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] deltaX deltaY\n    if {$deltaX != 0 || $deltaY != 0} {\n\ttk::ScrollByPixels %W $deltaX $deltaY\n    }\n}\n\nproc scrollEnter canvas {\n    global oldFill\n    set id [$canvas find withtag current]\n    if {[lsearch [$canvas gettags current] text] >= 0} {\n\tset id [expr {$id-1}]\n    }\n    set oldFill [lindex [$canvas itemconfig $id -fill] 4]\n    if {[winfo depth $canvas] > 1} {\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    $canvas itemconfigure $id -fill systemSelectedTextBackgroundColor\n\t} else {\n\t    $canvas itemconfigure $id -fill LightSeaGreen\n\t}\n    }\n}\n\nproc scrollLeave canvas {\n    global oldFill\n    set id [$canvas find withtag current]\n    if {[lsearch [$canvas gettags current] text] >= 0} {\n\tset id [expr {$id-1}]\n    }\n    $canvas itemconfigure $id -fill $oldFill\n}\n\nproc scrollButton canvas {\n    set id [$canvas find withtag current]\n    if {[lsearch [$canvas gettags current] text] < 0} {\n\tset id [expr {$id+1}]\n    }\n    puts stdout \"You buttoned at [lindex [$canvas itemconf $id -text] 4]\"\n}\n"
  },
  {
    "path": "library/demos/ctext.tcl",
    "content": "# ctext.tcl --\n#\n# This demonstration script creates a canvas widget with a text\n# item that can be edited and reconfigured in various ways.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ctext\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Canvas Text Demonstration\"\nwm iconname $w \"Text\"\npositionWindow $w\nset c $w.c\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"This window displays a string of text to demonstrate the text facilities of canvas widgets.  You can click in the boxes to adjust the position of the text relative to its positioning point or change its justification, and on a pie slice to change its angle.  The text also supports the following simple bindings for editing:\n  1. You can point, click, and type.\n  2. You can also select with button 1.\n  3. You can copy the selection to the mouse position with button 2.\n  4. Backspace and Control+h delete the selection if there is one;\n     otherwise they delete the character just before the insertion cursor.\n  5. Delete deletes the selection if there is one; otherwise it deletes\n     the character just after the insertion cursor.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\ncanvas $c -relief flat -borderwidth 0 -width 375p -height 262.5p\npack $w.c -side top -expand yes -fill both\n\nset textFont {Helvetica 24}\n\n$c create rectangle 183.75p 122.25p 191.25p 129.75p -outline black -fill red\n\n# First, create the text item and give it bindings so it can be edited.\n\n$c addtag text withtag [$c create text 187.5p 126p -text \"This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been defined to support editing (see above).\" -width 330p -anchor n -font $textFont -justify left]\n$c bind text <Button-1> \"textB1Press $c %x %y\"\n$c bind text <B1-Motion> \"textB1Move $c %x %y\"\n$c bind text <Shift-Button-1> \"$c select adjust current @%x,%y\"\n$c bind text <Shift-B1-Motion> \"textB1Move $c %x %y\"\n$c bind text <Key> \"textInsert $c %A\"\n$c bind text <Return> \"textInsert $c \\\\n\"\n$c bind text <Control-h> \"textBs $c\"\n$c bind text <BackSpace> \"textBs $c\"\n$c bind text <Delete> \"textDel $c\"\n$c bind text <Button-2> \"textPaste $c @%x,%y\"\n\n# Next, create some items that allow the text's anchor position\n# to be edited.\n\nproc mkTextConfigBox {w x y option value color} {\t;# x, y are in points\n    set item [$w create rect ${x}p ${y}p [expr {$x+22.5}]p [expr {$y+22.5}]p \\\n\t    -outline black -fill $color -width 0.75p]\n    $w bind $item <Button-1> \"$w itemconf text $option $value\"\n    $w addtag config withtag $item\n}\nproc mkTextConfigPie {w x y a option value color} {\t;# x, y are in points\n    set item [$w create arc ${x}p ${y}p [expr {$x+67.5}]p [expr {$y+67.5}]p \\\n\t    -start [expr {$a-15}] -extent 30 -outline black -fill $color \\\n\t    -width 0.75p]\n    $w bind $item <Button-1> \"$w itemconf text $option $value\"\n    $w addtag config withtag $item\n}\n\nset x 37.5\t;# in points\nset y 37.5\t;# in points\nset color LightSkyBlue1\nmkTextConfigBox $c $x $y -anchor se $color\nmkTextConfigBox $c [expr {$x+22.5}] [expr {$y     }] -anchor s      $color\nmkTextConfigBox $c [expr {$x+45  }] [expr {$y     }] -anchor sw     $color\nmkTextConfigBox $c [expr {$x     }] [expr {$y+22.5}] -anchor e      $color\nmkTextConfigBox $c [expr {$x+22.5}] [expr {$y+22.5}] -anchor center $color\nmkTextConfigBox $c [expr {$x+45  }] [expr {$y+22.5}] -anchor w      $color\nmkTextConfigBox $c [expr {$x     }] [expr {$y+45  }] -anchor ne     $color\nmkTextConfigBox $c [expr {$x+22.5}] [expr {$y+45  }] -anchor n      $color\nmkTextConfigBox $c [expr {$x+45  }] [expr {$y+45  }] -anchor nw     $color\nset item [$c create rect \\\n\t[expr {$x+30}]p [expr {$y+30}]p [expr {$x+37.5}]p [expr {$y+37.5}]p \\\n\t-outline black -fill red]\n$c bind $item <Button-1> \"$c itemconf text -anchor center\"\n$c create text [expr {$x+33.75}]p [expr {$y-3.75}]p \\\n\t-text {Text Position}  -anchor s  -font {Times 20}  -fill brown\n\n# Now create some items that allow the text's angle to be changed.\n\nset x 153.75\t;# in points\nset y 37.5\t;# in points\nset color Yellow\nmkTextConfigPie $c $x $y   0 -angle  90 $color\nmkTextConfigPie $c $x $y  30 -angle 120 $color\nmkTextConfigPie $c $x $y  60 -angle 150 $color\nmkTextConfigPie $c $x $y  90 -angle 180 $color\nmkTextConfigPie $c $x $y 120 -angle 210 $color\nmkTextConfigPie $c $x $y 150 -angle 240 $color\nmkTextConfigPie $c $x $y 180 -angle 270 $color\nmkTextConfigPie $c $x $y 210 -angle 300 $color\nmkTextConfigPie $c $x $y 240 -angle 330 $color\nmkTextConfigPie $c $x $y 270 -angle   0 $color\nmkTextConfigPie $c $x $y 300 -angle  30 $color\nmkTextConfigPie $c $x $y 330 -angle  60 $color\n$c create text [expr {$x+33.75}]p [expr {$y-3.75}]p \\\n\t-text {Text Angle}     -anchor s  -font {Times 20}  -fill brown\n\n# Lastly, create some items that allow the text's justification to be\n# changed.\n\nset x 262.5\t;# in points\nset y 37.5\t;# in points\nset color SeaGreen2\nmkTextConfigBox $c $x $y -justify left $color\nmkTextConfigBox $c [expr {$x+22.5}] $y -justify center $color\nmkTextConfigBox $c [expr {$x+45}] $y -justify right $color\n$c create text [expr {$x+33.75}]p [expr {$y-3.75}]p \\\n\t-text {Justification}  -anchor s  -font {Times 20}  -fill brown\n\n$c bind config <Enter> \"textEnter $c\"\n$c bind config <Leave> \"$c itemconf current -fill \\$textConfigFill\"\n\nset textConfigFill {}\n\nproc textEnter {w} {\n    global textConfigFill\n    set textConfigFill [lindex [$w itemconfig current -fill] 4]\n    $w itemconfig current -fill black\n}\n\nproc textInsert {w string} {\n    if {$string == \"\"} {\n\treturn\n    }\n    catch {$w dchars text sel.first sel.last}\n    $w insert text insert $string\n}\n\nproc textPaste {w pos} {\n    catch {\n\t$w insert text $pos [selection get]\n    }\n}\n\nproc textB1Press {w x y} {\n    $w icursor current @$x,$y\n    $w focus current\n    focus $w\n    $w select from current @$x,$y\n}\n\nproc textB1Move {w x y} {\n    $w select to current @$x,$y\n}\n\nproc textBs {w} {\n    if {![catch {$w dchars text sel.first sel.last}]} {\n\treturn\n    }\n    set char [expr {[$w index text insert] - 1}]\n    if {$char >= 0} {$w dchar text $char}\n}\n\nproc textDel {w} {\n    if {![catch {$w dchars text sel.first sel.last}]} {\n\treturn\n    }\n    $w dchars text insert\n}\n"
  },
  {
    "path": "library/demos/dialog1.tcl",
    "content": "# dialog1.tcl --\n#\n# This demonstration script creates a dialog box with a local grab.\n\ninterp create child\nload {} Tk child\nchild eval {\n    wm title . child\n    wm geometry . +700+30\n    pack [text .t -width 30 -height 10]\n}\n\nafter idle {.dialog1.msg configure -wraplength 4i}\nset i [tk_dialog .dialog1 \"Dialog with local grab\" {This is a modal dialog box.  It uses Tk's \"grab\" command to create a \"local grab\" on the dialog box.  The grab prevents any mouse or keyboard events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below.  However, you can still interact with other applications.  For example, you should be able to edit text in the window named \"child\" which was created by a child interpreter.} \\\ninfo 0 OK Cancel {Show Code}]\n\nswitch $i {\n    0 {puts \"You pressed OK\"}\n    1 {puts \"You pressed Cancel\"}\n    2 {showCode .dialog1}\n}\n\nif {[interp exists child]} {\n    interp delete child\n}\n"
  },
  {
    "path": "library/demos/dialog2.tcl",
    "content": "# dialog2.tcl --\n#\n# This demonstration script creates a dialog box with a global grab.\n\nafter idle {\n    .dialog2.msg configure -wraplength 4i\n}\nafter 100 {\n    grab -global .dialog2\n}\nset i [tk_dialog .dialog2 \"Dialog with global grab\" {This dialog box uses a global grab. If you are using an X11 window manager you will be prevented from interacting with anything on your display until you invoke one of the buttons below.  This is almost always a bad idea; don't use global grabs with X11 unless you're truly desperate.  On macOS systems you will not be able to interact with any window belonging to this process, but interaction with other macOS Applications will still be possible.}\\\nwarning 0 OK Cancel {Show Code}]\n\nswitch $i {\n    0 {puts \"You pressed OK\"}\n    1 {puts \"You pressed Cancel\"}\n    2 {showCode .dialog2}\n}\n"
  },
  {
    "path": "library/demos/en.msg",
    "content": "::msgcat::mcset en \"Widget Demonstration\"\n::msgcat::mcset en \"tkWidgetDemo\"\n::msgcat::mcset en \"&File\"\n::msgcat::mcset en \"About...\"\n::msgcat::mcset en \"&About...\"\n::msgcat::mcset en \"<F1>\"\n::msgcat::mcset en \"&Quit\"\n::msgcat::mcset en \"Meta+Q\"\t\t;# Displayed hotkey\n::msgcat::mcset en \"Meta-q\"\t\t;# Actual binding sequence\n::msgcat::mcset en \"Ctrl+Q\"\t\t;# Displayed hotkey\n::msgcat::mcset en \"Control-q\"\t\t;# Actual binding sequence\n::msgcat::mcset en \"See Variables\"\n::msgcat::mcset en \"Variable values\"\n::msgcat::mcset en \"Variable values:\"\n::msgcat::mcset en \"OK\"\n::msgcat::mcset en \"Run the \\\"%s\\\" sample program\"\n::msgcat::mcset en \"Dismiss\"\n::msgcat::mcset en \"Rerun Demo\"\n::msgcat::mcset en \"Print Code\"\n::msgcat::mcset en \"Demo code: %s\"\n::msgcat::mcset en \"About Widget Demo\"\n::msgcat::mcset en \"Tk widget demonstration\"\n::msgcat::mcset en \"Copyright © %s\"\n\n::msgcat::mcset en \"Tk Widget Demonstrations\"\n::msgcat::mcset en \"This application provides a front end for several short scripts\"\n::msgcat::mcset en \"that demonstrate what you can do with Tk widgets.  Each of the\"\n::msgcat::mcset en \"numbered lines below describes a demonstration;  you can click on\"\n::msgcat::mcset en \"it to invoke the demonstration.  Once the demonstration window\"\n::msgcat::mcset en \"appears, you can click the\"\n::msgcat::mcset en \"See Code\"  \"See Code\"\t;# This is also button text!\n::msgcat::mcset en \"button to see the Tcl/Tk code that created the demonstration.  If\"\n::msgcat::mcset en \"you wish, you can edit the code and click the\"\n::msgcat::mcset en \"button in the code window to reinvoke the demonstration with the\"\n::msgcat::mcset en \"modified code.\"\n\n::msgcat::mcset en \"Labels, buttons, checkbuttons, and radiobuttons\"\n::msgcat::mcset en \"Labels (text and bitmaps)\"\n::msgcat::mcset en \"Labels and UNICODE text\"\n::msgcat::mcset en \"Buttons\"\n::msgcat::mcset en \"Check-buttons (select any of a group)\"\n::msgcat::mcset en \"Radio-buttons (select one of a group)\"\n::msgcat::mcset en \"A 15-puzzle game made out of buttons\"\n::msgcat::mcset en \"Iconic buttons that use bitmaps\"\n::msgcat::mcset en \"Two labels displaying images\"\n::msgcat::mcset en \"A simple user interface for viewing images\"\n::msgcat::mcset en \"Labelled frames\"\n\n::msgcat::mcset en \"Listboxes\"\n::msgcat::mcset en \"The 50 states\"\n::msgcat::mcset en \"Colors: change the color scheme for the application\"\n::msgcat::mcset en \"A collection of famous and infamous sayings\"\n\n::msgcat::mcset en \"Entries and Spin-boxes\"\n::msgcat::mcset en \"Entries without scrollbars\"\n::msgcat::mcset en \"Entries with scrollbars\"\n::msgcat::mcset en \"Validated entries and password fields\"\n::msgcat::mcset en \"Spin-boxes\"\n::msgcat::mcset en \"Simple Rolodex-like form\"\n\n::msgcat::mcset en \"Text\"\n::msgcat::mcset en \"Basic editable text\"\n::msgcat::mcset en \"Text display styles\"\n::msgcat::mcset en \"Hypertext (tag bindings)\"\n::msgcat::mcset en \"A text widget with embedded windows\"\n::msgcat::mcset en \"A search tool built with a text widget\"\n\n::msgcat::mcset en \"Canvases\"\n::msgcat::mcset en \"The canvas item types\"\n::msgcat::mcset en \"A simple 2-D plot\"\n::msgcat::mcset en \"Text items in canvases\"\n::msgcat::mcset en \"An editor for arrowheads on canvas lines\"\n::msgcat::mcset en \"A ruler with adjustable tab stops\"\n::msgcat::mcset en \"A building floor plan\"\n::msgcat::mcset en \"A simple scrollable canvas\"\n\n::msgcat::mcset en \"Scales\"\n::msgcat::mcset en \"Horizontal scale\"\n::msgcat::mcset en \"Vertical scale\"\n\n::msgcat::mcset en \"Paned Windows\"\n::msgcat::mcset en \"Horizontal paned window\"\n::msgcat::mcset en \"Vertical paned window\"\n::msgcat::mcset en \"Menus\"\n::msgcat::mcset en \"Menus and cascades (sub-menus)\"\n::msgcat::mcset en \"Menu-buttons\"\n::msgcat::mcset en \"Common Dialogs\"\n::msgcat::mcset en \"Message boxes\"\n::msgcat::mcset en \"File selection dialog\"\n::msgcat::mcset en \"Color picker\"\n::msgcat::mcset en \"Font selection dialog\"\n::msgcat::mcset en \"System tray icon and notification\"\n::msgcat::mcset en \"Printing from canvas and text widgets\"\n::msgcat::mcset en \"Animation\"\n::msgcat::mcset en \"Animated labels\"\n::msgcat::mcset en \"Animated wave\"\n::msgcat::mcset en \"Pendulum simulation\"\n::msgcat::mcset en \"A celebration of Rube Goldberg\"\n::msgcat::mcset en \"Miscellaneous\"\n::msgcat::mcset en \"The built-in bitmaps\"\n::msgcat::mcset en \"A dialog box with a local grab\"\n::msgcat::mcset en \"A dialog box with a global grab\"\n::msgcat::mcset en \"Window icons and badges\"\n"
  },
  {
    "path": "library/demos/entry1.tcl",
    "content": "# entry1.tcl --\n#\n# This demonstration script creates several entry widgets without\n# scrollbars.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .entry1\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Entry Demonstration (no scrollbars)\"\nwm iconname $w \"entry1\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"Three different entries are displayed below.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries by dragging with mouse the middle mouse button pressed.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nentry $w.e1\nentry $w.e2\nentry $w.e3 -placeholder {Enter text here} -placeholderforeground gray75\npack $w.e1 $w.e2 $w.e3 -side top -pady 3p -padx 7.5p -fill x\n\n$w.e1 insert 0 \"Initial value\"\n$w.e2 insert end \"This entry contains a long value, much too long \"\n$w.e2 insert end \"to fit in the window at one time, so long in fact \"\n$w.e2 insert end \"that you'll have to scan or scroll to see the end.\"\n"
  },
  {
    "path": "library/demos/entry2.tcl",
    "content": "# entry2.tcl --\n#\n# This demonstration script is the same as the entry1.tcl script\n# except that it creates scrollbars for the entries.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .entry2\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Entry Demonstration (with scrollbars)\"\nwm iconname $w \"entry2\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"Three different entries are displayed below, with a scrollbar for each entry.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries with the scrollbars, or by dragging with the middle mouse button pressed.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth 7.5p\npack $w.frame -side top -fill x -expand 1\n\nentry $w.frame.e1 -xscrollcommand \"$w.frame.s1 set\"\nttk::scrollbar $w.frame.s1 -orient horizontal -command \\\n\t\"$w.frame.e1 xview\"\nframe $w.frame.spacer1 -width 15p -height 7.5p\nentry $w.frame.e2 -xscrollcommand \"$w.frame.s2 set\"\nttk::scrollbar $w.frame.s2 -orient horizontal -command \\\n\t\"$w.frame.e2 xview\"\nframe $w.frame.spacer2 -width 15p -height 7.5p\nentry $w.frame.e3 -xscrollcommand \"$w.frame.s3 set\"\nttk::scrollbar $w.frame.s3 -orient horizontal -command \\\n\t\"$w.frame.e3 xview\"\npack $w.frame.e1 $w.frame.s1 $w.frame.spacer1 $w.frame.e2 $w.frame.s2 \\\n\t$w.frame.spacer2 $w.frame.e3 $w.frame.s3 -side top -fill x\n\n$w.frame.e1 insert 0 \"Initial value\"\n$w.frame.e2 insert end \"This entry contains a long value, much too long \"\n$w.frame.e2 insert end \"to fit in the window at one time, so long in fact \"\n$w.frame.e2 insert end \"that you'll have to scan or scroll to see the end.\"\n$w.frame.e3 configure -placeholder {Enter text here} -placeholderforeground gray75\n"
  },
  {
    "path": "library/demos/entry3.tcl",
    "content": "# entry3.tcl --\n#\n# This demonstration script creates several entry widgets whose\n# permitted input is constrained in some way.  It also shows off a\n# password entry.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .entry3\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Constrained Entry Demonstration\"\nwm iconname $w \"entry3\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"Four different\\\n\tentries are displayed below.  You can add characters by pointing,\\\n\tclicking and typing, though each is constrained in what it will\\\n\taccept.  The first only accepts 32-bit integers or the empty string\\\n\t(checking when focus leaves it) and will flash to indicate any\\\n\tproblem.  The second only accepts strings with fewer than ten\\\n\tcharacters and sounds the bell when an attempt to go over the limit\\\n\tis made.  The third accepts US phone numbers, mapping letters to\\\n\ttheir digit equivalent and sounding the bell on encountering an\\\n\tillegal character or if trying to type over a character that is not\\\n\ta digit.  The fourth is a password field that accepts up to eight\\\n\tcharacters (silently ignoring further ones), and displaying them as\\\n\tasterisk characters.\"\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# focusAndFlash --\n# Error handler for entry widgets that forces the focus onto the\n# widget and makes the widget flash by exchanging the foreground and\n# background colours at intervals of 200ms (i.e. at approximately\n# 2.5Hz).\n#\n# Arguments:\n# W -\t\tName of entry widget to flash\n# fg -\t\tInitial foreground colour\n# bg -\t\tInitial background colour\n# count -\tCounter to control the number of times flashed\n\nproc focusAndFlash {W fg bg {count 9}} {\n    focus -force $W\n    if {$count<1} {\n\t$W configure -foreground $fg -background $bg\n    } else {\n\tif {$count%2} {\n\t    $W configure -foreground $bg -background $fg\n\t} else {\n\t    $W configure -foreground $fg -background $bg\n\t}\n\tafter 200 [list focusAndFlash $W $fg $bg [expr {$count-1}]]\n    }\n}\n\nlabelframe $w.l1 -text \"Integer Entry\"\n# Alternatively try using {string is digit} for arbitrary length numbers,\n# and not just 32-bit ones.\nentry $w.l1.e -validate focus -validatecommand {string is integer %P}\n$w.l1.e configure -invalidcommand \\\n\t\"focusAndFlash %W [$w.l1.e cget -fg] [$w.l1.e cget -bg]\"\npack $w.l1.e -fill x -expand 1 -padx 1m -pady 1m\n\nlabelframe $w.l2 -text \"Length-Constrained Entry\"\nentry $w.l2.e -validate key -invcmd bell -validatecommand {expr {[string length %P]<10}}\npack $w.l2.e -fill x -expand 1 -padx 1m -pady 1m\n\n### PHONE NUMBER ENTRY ###\n# Note that the source to this is quite a bit longer as the behaviour\n# demonstrated is a lot more ambitious than with the others.\n\n# Initial content for the third entry widget\nset entry3content \"1-(000)-000-0000\"\n# Mapping from alphabetic characters to numbers.  This is probably\n# wrong, but it is the only mapping I have; the UK doesn't really go\n# for associating letters with digits for some reason.\nset phoneNumberMap {}\nforeach {chars digit} {abc 2 def 3 ghi 4 jkl 5 mno 6 pqrs 7 tuv 8 wxyz 9} {\n    foreach char [split $chars \"\"] {\n\tlappend phoneNumberMap $char $digit [string toupper $char] $digit\n    }\n}\n\n# validatePhoneChange --\n# Checks that the replacement (mapped to a digit) of the given\n# character in an entry widget at the given position will leave a\n# valid phone number in the widget.\n#\n# W -\t  The entry widget to validate\n# vmode - The widget's validation mode\n# idx -\t  The index where replacement is to occur\n# char -  The character (or string, though that will always be\n#\t  refused) to be overwritten at that point.\n\nproc validatePhoneChange {W vmode idx char} {\n    global phoneNumberMap entry3content\n    if {$idx < 0} {return 1}\n    after idle [list $W configure -validate $vmode -invcmd bell]\n    if {\n\t!($idx<3 || $idx==6 || $idx==7 || $idx==11 || $idx>15) &&\n\t[string match {[0-9A-Za-z]} $char]\n    } then {\n\t$W delete $idx\n\t$W insert $idx [string map $phoneNumberMap $char]\n\tafter idle [list phoneSkipRight $W -1]\n\treturn 1\n    }\n    return 0\n}\n\n# phoneSkipLeft --\n# Skip over fixed characters in a phone-number string when moving left.\n#\n# Arguments:\n# W -\tThe entry widget containing the phone-number.\n\nproc phoneSkipLeft {W} {\n    set idx [$W index insert]\n    if {$idx == 8} {\n\t# Skip back two extra characters\n\t$W icursor [incr idx -2]\n    } elseif {$idx == 7 || $idx == 12} {\n\t# Skip back one extra character\n\t$W icursor [incr idx -1]\n    } elseif {$idx <= 3} {\n\t# Can't move any further\n\tbell\n\treturn -code break\n    }\n}\n\n# phoneSkipRight --\n# Skip over fixed characters in a phone-number string when moving right.\n#\n# Arguments:\n# W -\tThe entry widget containing the phone-number.\n# add - Offset to add to index before calculation (used by validation.)\n\nproc phoneSkipRight {W {add 0}} {\n    set idx [$W index insert]\n    if {$idx+$add == 5} {\n\t# Skip forward two extra characters\n\t$W icursor [incr idx 2]\n    } elseif {$idx+$add == 6 || $idx+$add == 10} {\n\t# Skip forward one extra character\n\t$W icursor [incr idx]\n    } elseif {$idx+$add == 15 && !$add} {\n\t# Can't move any further\n\tbell\n\treturn -code break\n    }\n}\n\nlabelframe $w.l3 -text \"US Phone-Number Entry\"\nentry $w.l3.e -validate key  -invcmd bell  -textvariable entry3content \\\n\t-validatecommand {validatePhoneChange %W %v %i %S}\n# Click to focus goes to the first editable character...\nbind $w.l3.e <FocusIn> {\n    if {\"%d\" ne \"NotifyAncestor\"} {\n\t%W icursor 3\n\tafter idle {%W selection clear}\n    }\n}\nbind $w.l3.e <<PrevChar>> {phoneSkipLeft  %W}\nbind $w.l3.e <<NextChar>> {phoneSkipRight %W}\npack $w.l3.e -fill x -expand 1 -padx 1m -pady 1m\n\nlabelframe $w.l4 -text \"Password Entry\"\nentry $w.l4.e -validate key -show \"*\" -validatecommand {expr {[string length %P]<=8}}\npack $w.l4.e -fill x -expand 1 -padx 1m -pady 1m\n\nlower [frame $w.mid]\ngrid $w.l1 $w.l2 -in $w.mid -padx 3m -pady 1m -sticky ew\ngrid $w.l3 $w.l4 -in $w.mid -padx 3m -pady 1m -sticky ew\ngrid columnconfigure $w.mid {0 1} -uniform 1\npack $w.msg -side top\npack $w.mid -fill both -expand 1\n"
  },
  {
    "path": "library/demos/filebox.tcl",
    "content": "# filebox.tcl --\n#\n# This demonstration script prompts the user to select a file.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .filebox\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"File Selection Dialogs\"\nwm iconname $w \"filebox\"\npositionWindow $w\n\nttk::frame $w._bg\nplace $w._bg -x 0 -y 0 -relwidth 1 -relheight 1\n\nttk::label $w.msg -font $font -wraplength 4i -justify left -text \"Enter a file name in the entry box or click on the \\\"Browse\\\" buttons to select a file name using the file selection dialog.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nset f [ttk::frame $w.f]\nforeach i {open save} {\n    ttk::label $f.lab_$i -text \"Select a file to $i:\"\n    ttk::entry $f.ent_$i -width 20\n    ttk::button $f.but_$i -text \"Browse ...\" -command \\\n\t    \"fileDialog $w $f.ent_$i $i\"\n    grid $f.lab_$i $f.ent_$i $f.but_$i -pady 3p -sticky w\n    grid configure $f.ent_$i -padx 3p -sticky ew\n}\ngrid columnconfigure $f 1 -weight 1\npack $f -fill x -padx 1c\n\nif {[tk windowingsystem] eq \"x11\"} {\n    ttk::checkbutton $w.strict -text \"Use Motif Style Dialog\" \\\n\t-variable tk_strictMotif -onvalue 1 -offvalue 0\n    pack $w.strict -anchor c\n\n    # This binding ensures that we don't run the rest of the demos\n    # with motif style interactions\n    bind $w.strict <Destroy> {set tk_strictMotif 0}\n}\n\nproc fileDialog {w ent operation} {\n    #   Type names\t\tExtension(s)\tMac File Type(s)\n    #\n    #---------------------------------------------------------\n    set types {\n\t{\"Text files\"\t\t{.txt .doc}\t}\n\t{\"Text files\"\t\t{}\t\tTEXT}\n\t{\"Tcl Scripts\"\t\t{.tcl}\t\tTEXT}\n\t{\"C Source Files\"\t{.c .h}\t\t}\n\t{\"All Source Files\"\t{.tcl .c .h}\t}\n\t{\"Image Files\"\t\t{.gif}\t\t}\n\t{\"Image Files\"\t\t{.jpeg .jpg}\t}\n\t{\"Image Files\"\t\t\"\"\t\t{GIFF JPEG}}\n\t{\"All files\"\t\t*}\n    }\n    if {$operation == \"open\"} {\n\tglobal selected_type\n\tif {![info exists selected_type]} {\n\t    set selected_type \"Tcl Scripts\"\n\t}\n\tset file [tk_getOpenFile -filetypes $types -parent $w \\\n\t\t-typevariable selected_type]\n\tputs \"You selected filetype \\\"$selected_type\\\"\"\n    } else {\n\tset file [tk_getSaveFile -filetypes $types -parent $w \\\n\t\t-initialfile Untitled -defaultextension .txt]\n    }\n    if {[string compare $file \"\"]} {\n\t$ent delete 0 end\n\t$ent insert 0 $file\n\t$ent xview end\n    }\n}\n"
  },
  {
    "path": "library/demos/floor.tcl",
    "content": "# floor.tcl --\n#\n# This demonstration script creates a canvas widet that displays the\n# floorplan for DEC's Western Research Laboratory.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# floorDisplay --\n# Recreate the floorplan display in the canvas given by \"w\".  The\n# floor given by \"active\" is displayed on top with its office structure\n# visible.\n#\n# Arguments:\n# w -\t\tName of the canvas window.\n# active -\tNumber of active floor (1, 2, or 3).\n\nproc floorDisplay {w active} {\n    global floorLabels floorItems colors activeFloor\n\n    if {$activeFloor == $active} {\n\treturn\n    }\n\n    $w delete all\n    set activeFloor $active\n\n    # First go through the three floors, displaying the backgrounds for\n    # each floor.\n\n    bg1 $w $colors(bg1) $colors(outline1)\n    bg2 $w $colors(bg2) $colors(outline2)\n    bg3 $w $colors(bg3) $colors(outline3)\n\n    # Raise the background for the active floor so that it's on top.\n\n    $w raise floor$active\n\n    # Create a dummy item just to mark this point in the display list,\n    # so we can insert highlights here.\n\n    $w create rect 0 100 1 101 -fill {} -outline {} -tags marker\n\n    # Add the walls and labels for the active floor, along with\n    # transparent polygons that define the rooms on the floor.\n    # Make sure that the room polygons are on top.\n\n    catch {unset floorLabels}\n    catch {unset floorItems}\n    fg$active $w $colors(offices)\n    $w raise room\n\n    # Rescale the coordinates in pixels of all of the\n    # items according to the display's DPI scaling level.\n\n    set scaleFactor [expr {$tk::scalingPct / 100.0}]\n    $w scale all 0 0 $scaleFactor $scaleFactor\n\n    # Offset the floors diagonally from each other.\n\n    $w move floor1 2c 2c\n    $w move floor2 1c 1c\n\n    # Create items for the room entry and its label.\n\n    $w create window 450p 75p -anchor w -window $w.entry\n    $w create text 450p 75p -anchor e -text \"Room: \"\n\n    # Configure the canvas.\n\n    set bbox [$w bbox all]\n    lassign $bbox x1 y1 x2 y2\n    set morePx [expr {round(20 * $tk::scalingPct / 100.0)}]\n    set width  [expr {$x2 - $x1 + $morePx}]\n    set height [expr {$y2 - $y1 + $morePx}]\n    $w configure -scrollregion $bbox -width $width -height $height\n}\n\n# newRoom --\n# This procedure is invoked whenever the mouse enters a room\n# in the floorplan.  It changes tags so that the current room is\n# highlighted.\n#\n# Arguments:\n# w  -\t\tThe name of the canvas window.\n\nproc newRoom w {\n    global currentRoom floorLabels\n\n    set id [$w find withtag current]\n    if {$id != \"\"} {\n\tset currentRoom $floorLabels($id)\n    }\n    update idletasks\n}\n\n# roomChanged --\n# This procedure is invoked whenever the currentRoom variable changes.\n# It highlights the current room and unhighlights any previous room.\n#\n# Arguments:\n# w -\t\tThe canvas window displaying the floorplan.\n# args -\tNot used.\n\nproc roomChanged {w args} {\n    global currentRoom floorItems colors\n    $w delete highlight\n    if {[catch {set item $floorItems($currentRoom)}]} {\n\treturn\n    }\n    set new [eval \\\n\t\"$w create polygon [$w coords $item] -fill $colors(active) \\\n\t-outline {} -tags highlight\"]\n    $w raise $new marker\n}\n\n# bg1 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the background information for the first\n# floor.\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# fill -\tFill color to use for the floor's background.\n# outline -\tColor to use for the floor's outline.\n\nproc bg1 {w fill outline} {\n    $w create polygon 347 80 349 82 351 84 353 85 363 92 375 99 386 104 \\\n\t386 129 398 129 398 162 484 162 484 129 559 129 559 133 725 \\\n\t133 725 129 802 129 802 389 644 389 644 391 559 391 559 327 \\\n\t508 327 508 311 484 311 484 278 395 278 395 288 400 288 404 \\\n\t288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 \\\n\t411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 \\\n\t342 331 347 332 351 334 354 336 357 341 359 340 360 335 363 \\\n\t331 365 326 366 304 366 304 355 258 355 258 387 60 387 60 391 \\\n\t0 391 0 337 3 337 3 114 8 114 8 25 30 25 30 5 93 5 98 5 104 7 \\\n\t110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 34 221 \\\n\t22 223 17 227 13 231 8 236 4 242 2 246 0 260 0 283 1 300 5 \\\n\t321 14 335 22 348 25 365 29 363 39 358 48 352 56 337 70 \\\n\t344 76 347 80 \\\n\t-tags {floor1 bg} -fill $fill -outline {}\n    $w create line 386 129 398 129 -fill $outline -tags {floor1 bg}\n    $w create line 258 355 258 387 -fill $outline -tags {floor1 bg}\n    $w create line 60 387 60 391 -fill $outline -tags {floor1 bg}\n    $w create line 0 337 0 391 -fill $outline -tags {floor1 bg}\n    $w create line 60 391 0 391 -fill $outline -tags {floor1 bg}\n    $w create line 3 114 3 337 -fill $outline -tags {floor1 bg}\n    $w create line 258 387 60 387 -fill $outline -tags {floor1 bg}\n    $w create line 484 162 398 162 -fill $outline -tags {floor1 bg}\n    $w create line 398 162 398 129 -fill $outline -tags {floor1 bg}\n    $w create line 484 278 484 311 -fill $outline -tags {floor1 bg}\n    $w create line 484 311 508 311 -fill $outline -tags {floor1 bg}\n    $w create line 508 327 508 311 -fill $outline -tags {floor1 bg}\n    $w create line 559 327 508 327 -fill $outline -tags {floor1 bg}\n    $w create line 644 391 559 391 -fill $outline -tags {floor1 bg}\n    $w create line 644 389 644 391 -fill $outline -tags {floor1 bg}\n    $w create line 559 129 484 129 -fill $outline -tags {floor1 bg}\n    $w create line 484 162 484 129 -fill $outline -tags {floor1 bg}\n    $w create line 725 133 559 133 -fill $outline -tags {floor1 bg}\n    $w create line 559 129 559 133 -fill $outline -tags {floor1 bg}\n    $w create line 725 129 802 129 -fill $outline -tags {floor1 bg}\n    $w create line 802 389 802 129 -fill $outline -tags {floor1 bg}\n    $w create line 3 337 0 337 -fill $outline -tags {floor1 bg}\n    $w create line 559 391 559 327 -fill $outline -tags {floor1 bg}\n    $w create line 802 389 644 389 -fill $outline -tags {floor1 bg}\n    $w create line 725 133 725 129 -fill $outline -tags {floor1 bg}\n    $w create line 8 25 8 114 -fill $outline -tags {floor1 bg}\n    $w create line 8 114 3 114 -fill $outline -tags {floor1 bg}\n    $w create line 30 25 8 25 -fill $outline -tags {floor1 bg}\n    $w create line 484 278 395 278 -fill $outline -tags {floor1 bg}\n    $w create line 30 25 30 5 -fill $outline -tags {floor1 bg}\n    $w create line 93 5 30 5 -fill $outline -tags {floor1 bg}\n    $w create line 98 5 93 5 -fill $outline -tags {floor1 bg}\n    $w create line 104 7 98 5 -fill $outline -tags {floor1 bg}\n    $w create line 110 10 104 7 -fill $outline -tags {floor1 bg}\n    $w create line 116 16 110 10 -fill $outline -tags {floor1 bg}\n    $w create line 119 20 116 16 -fill $outline -tags {floor1 bg}\n    $w create line 122 28 119 20 -fill $outline -tags {floor1 bg}\n    $w create line 123 32 122 28 -fill $outline -tags {floor1 bg}\n    $w create line 123 68 123 32 -fill $outline -tags {floor1 bg}\n    $w create line 220 68 123 68 -fill $outline -tags {floor1 bg}\n    $w create line 386 129 386 104 -fill $outline -tags {floor1 bg}\n    $w create line 386 104 375 99 -fill $outline -tags {floor1 bg}\n    $w create line 375 99 363 92 -fill $outline -tags {floor1 bg}\n    $w create line 353 85 363 92 -fill $outline -tags {floor1 bg}\n    $w create line 220 68 220 34 -fill $outline -tags {floor1 bg}\n    $w create line 337 70 352 56 -fill $outline -tags {floor1 bg}\n    $w create line 352 56 358 48 -fill $outline -tags {floor1 bg}\n    $w create line 358 48 363 39 -fill $outline -tags {floor1 bg}\n    $w create line 363 39 365 29 -fill $outline -tags {floor1 bg}\n    $w create line 365 29 348 25 -fill $outline -tags {floor1 bg}\n    $w create line 348 25 335 22 -fill $outline -tags {floor1 bg}\n    $w create line 335 22 321 14 -fill $outline -tags {floor1 bg}\n    $w create line 321 14 300 5 -fill $outline -tags {floor1 bg}\n    $w create line 300 5 283 1 -fill $outline -tags {floor1 bg}\n    $w create line 283 1 260 0 -fill $outline -tags {floor1 bg}\n    $w create line 260 0 246 0 -fill $outline -tags {floor1 bg}\n    $w create line 246 0 242 2 -fill $outline -tags {floor1 bg}\n    $w create line 242 2 236 4 -fill $outline -tags {floor1 bg}\n    $w create line 236 4 231 8 -fill $outline -tags {floor1 bg}\n    $w create line 231 8 227 13 -fill $outline -tags {floor1 bg}\n    $w create line 223 17 227 13 -fill $outline -tags {floor1 bg}\n    $w create line 221 22 223 17 -fill $outline -tags {floor1 bg}\n    $w create line 220 34 221 22 -fill $outline -tags {floor1 bg}\n    $w create line 340 360 335 363 -fill $outline -tags {floor1 bg}\n    $w create line 335 363 331 365 -fill $outline -tags {floor1 bg}\n    $w create line 331 365 326 366 -fill $outline -tags {floor1 bg}\n    $w create line 326 366 304 366 -fill $outline -tags {floor1 bg}\n    $w create line 304 355 304 366 -fill $outline -tags {floor1 bg}\n    $w create line 395 288 400 288 -fill $outline -tags {floor1 bg}\n    $w create line 404 288 400 288 -fill $outline -tags {floor1 bg}\n    $w create line 409 290 404 288 -fill $outline -tags {floor1 bg}\n    $w create line 413 292 409 290 -fill $outline -tags {floor1 bg}\n    $w create line 418 297 413 292 -fill $outline -tags {floor1 bg}\n    $w create line 421 302 418 297 -fill $outline -tags {floor1 bg}\n    $w create line 422 309 421 302 -fill $outline -tags {floor1 bg}\n    $w create line 421 318 422 309 -fill $outline -tags {floor1 bg}\n    $w create line 421 318 417 325 -fill $outline -tags {floor1 bg}\n    $w create line 417 325 411 330 -fill $outline -tags {floor1 bg}\n    $w create line 411 330 405 332 -fill $outline -tags {floor1 bg}\n    $w create line 405 332 397 333 -fill $outline -tags {floor1 bg}\n    $w create line 397 333 344 333 -fill $outline -tags {floor1 bg}\n    $w create line 344 333 340 334 -fill $outline -tags {floor1 bg}\n    $w create line 340 334 336 336 -fill $outline -tags {floor1 bg}\n    $w create line 336 336 335 338 -fill $outline -tags {floor1 bg}\n    $w create line 335 338 332 342 -fill $outline -tags {floor1 bg}\n    $w create line 331 347 332 342 -fill $outline -tags {floor1 bg}\n    $w create line 332 351 331 347 -fill $outline -tags {floor1 bg}\n    $w create line 334 354 332 351 -fill $outline -tags {floor1 bg}\n    $w create line 336 357 334 354 -fill $outline -tags {floor1 bg}\n    $w create line 341 359 336 357 -fill $outline -tags {floor1 bg}\n    $w create line 341 359 340 360 -fill $outline -tags {floor1 bg}\n    $w create line 395 288 395 278 -fill $outline -tags {floor1 bg}\n    $w create line 304 355 258 355 -fill $outline -tags {floor1 bg}\n    $w create line 347 80 344 76 -fill $outline -tags {floor1 bg}\n    $w create line 344 76 337 70 -fill $outline -tags {floor1 bg}\n    $w create line 349 82 347 80 -fill $outline -tags {floor1 bg}\n    $w create line 351 84 349 82 -fill $outline -tags {floor1 bg}\n    $w create line 353 85 351 84 -fill $outline -tags {floor1 bg}\n}\n\n# bg2 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the background information for the second\n# floor.\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# fill -\tFill color to use for the floor's background.\n# outline -\tColor to use for the floor's outline.\n\nproc bg2 {w fill outline} {\n    $w create polygon 559 129 484 129 484 162 398 162 398 129 315 129 \\\n\t315 133 176 133 176 129 96 129 96 133 3 133 3 339 0 339 0 391 \\\n\t60 391 60 387 258 387 258 329 350 329 350 311 395 311 395 280 \\\n\t484 280 484 311 508 311 508 327 558 327 558 391 644 391 644 \\\n\t367 802 367 802 129 725 129 725 133 559 133 559 129 \\\n\t-tags {floor2 bg} -fill $fill -outline {}\n    $w create line 350 311 350 329 -fill $outline -tags {floor2 bg}\n    $w create line 398 129 398 162 -fill $outline -tags {floor2 bg}\n    $w create line 802 367 802 129 -fill $outline -tags {floor2 bg}\n    $w create line 802 129 725 129 -fill $outline -tags {floor2 bg}\n    $w create line 725 133 725 129 -fill $outline -tags {floor2 bg}\n    $w create line 559 129 559 133 -fill $outline -tags {floor2 bg}\n    $w create line 559 133 725 133 -fill $outline -tags {floor2 bg}\n    $w create line 484 162 484 129 -fill $outline -tags {floor2 bg}\n    $w create line 559 129 484 129 -fill $outline -tags {floor2 bg}\n    $w create line 802 367 644 367 -fill $outline -tags {floor2 bg}\n    $w create line 644 367 644 391 -fill $outline -tags {floor2 bg}\n    $w create line 644 391 558 391 -fill $outline -tags {floor2 bg}\n    $w create line 558 327 558 391 -fill $outline -tags {floor2 bg}\n    $w create line 558 327 508 327 -fill $outline -tags {floor2 bg}\n    $w create line 508 327 508 311 -fill $outline -tags {floor2 bg}\n    $w create line 484 311 508 311 -fill $outline -tags {floor2 bg}\n    $w create line 484 280 484 311 -fill $outline -tags {floor2 bg}\n    $w create line 398 162 484 162 -fill $outline -tags {floor2 bg}\n    $w create line 484 280 395 280 -fill $outline -tags {floor2 bg}\n    $w create line 395 280 395 311 -fill $outline -tags {floor2 bg}\n    $w create line 258 387 60 387 -fill $outline -tags {floor2 bg}\n    $w create line 3 133 3 339 -fill $outline -tags {floor2 bg}\n    $w create line 3 339 0 339 -fill $outline -tags {floor2 bg}\n    $w create line 60 391 0 391 -fill $outline -tags {floor2 bg}\n    $w create line 0 339 0 391 -fill $outline -tags {floor2 bg}\n    $w create line 60 387 60 391 -fill $outline -tags {floor2 bg}\n    $w create line 258 329 258 387 -fill $outline -tags {floor2 bg}\n    $w create line 350 329 258 329 -fill $outline -tags {floor2 bg}\n    $w create line 395 311 350 311 -fill $outline -tags {floor2 bg}\n    $w create line 398 129 315 129 -fill $outline -tags {floor2 bg}\n    $w create line 176 133 315 133 -fill $outline -tags {floor2 bg}\n    $w create line 176 129 96 129 -fill $outline -tags {floor2 bg}\n    $w create line 3 133 96 133 -fill $outline -tags {floor2 bg}\n    $w create line 315 133 315 129 -fill $outline -tags {floor2 bg}\n    $w create line 176 133 176 129 -fill $outline -tags {floor2 bg}\n    $w create line 96 133 96 129 -fill $outline -tags {floor2 bg}\n}\n\n# bg3 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the background information for the third\n# floor.\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# fill -\tFill color to use for the floor's background.\n# outline -\tColor to use for the floor's outline.\n\nproc bg3 {w fill outline} {\n    $w create polygon 159 300 107 300 107 248 159 248 159 129 96 129 96 \\\n\t133 21 133 21 331 0 331 0 391 60 391 60 370 159 370 159 300 \\\n\t-tags {floor3 bg} -fill $fill -outline {}\n    $w create polygon 258 370 258 329 350 329 350 311 399 311 399 129 \\\n\t315 129 315 133 176 133 176 129 159 129 159 370 258 370 \\\n\t-tags {floor3 bg} -fill $fill -outline {}\n    $w create line 96 133 96 129 -fill $outline -tags {floor3 bg}\n    $w create line 176 129 96 129 -fill $outline -tags {floor3 bg}\n    $w create line 176 129 176 133 -fill $outline -tags {floor3 bg}\n    $w create line 315 133 176 133 -fill $outline -tags {floor3 bg}\n    $w create line 315 133 315 129 -fill $outline -tags {floor3 bg}\n    $w create line 399 129 315 129 -fill $outline -tags {floor3 bg}\n    $w create line 399 311 399 129 -fill $outline -tags {floor3 bg}\n    $w create line 399 311 350 311 -fill $outline -tags {floor3 bg}\n    $w create line 350 329 350 311 -fill $outline -tags {floor3 bg}\n    $w create line 350 329 258 329 -fill $outline -tags {floor3 bg}\n    $w create line 258 370 258 329 -fill $outline -tags {floor3 bg}\n    $w create line 60 370 258 370 -fill $outline -tags {floor3 bg}\n    $w create line 60 370 60 391 -fill $outline -tags {floor3 bg}\n    $w create line 60 391 0 391 -fill $outline -tags {floor3 bg}\n    $w create line 0 391 0 331 -fill $outline -tags {floor3 bg}\n    $w create line 21 331 0 331 -fill $outline -tags {floor3 bg}\n    $w create line 21 331 21 133 -fill $outline -tags {floor3 bg}\n    $w create line 96 133 21 133 -fill $outline -tags {floor3 bg}\n    $w create line 107 300 159 300 159 248 107 248 107 300 \\\n\t    -fill $outline -tags {floor3 bg}\n}\n\n# fg1 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the foreground information for the first\n# floor (office outlines and numbers).\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# color -\tColor to use for drawing foreground information.\n\nproc fg1 {w color} {\n    global floorLabels floorItems\n    set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 101\n    set {floorItems(101)} $i\n    $w create text 358 209 -text 101 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {Pub Lift1}\n    set {floorItems(Pub Lift1)} $i\n    $w create text 323 223 -text {Pub Lift1} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {Priv Lift1}\n    set {floorItems(Priv Lift1)} $i\n    $w create text 323 188 -text {Priv Lift1} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 42 389 42 337 1 337 1 389 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 110\n    set {floorItems(110)} $i\n    $w create text 21.5 363 -text 110 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 59 389 59 385 90 385 90 337 44 337 44 389 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 109\n    set {floorItems(109)} $i\n    $w create text 67 363 -text 109 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 51 300 51 253 6 253 6 300 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 111\n    set {floorItems(111)} $i\n    $w create text 28.5 276.5 -text 111 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 98 248 98 309 79 309 79 248 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 117B\n    set {floorItems(117B)} $i\n    $w create text 88.5 278.5 -text 117B -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 51 251 51 204 6 204 6 251 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 112\n    set {floorItems(112)} $i\n    $w create text 28.5 227.5 -text 112 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 6 156 51 156 51 203 6 203 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 113\n    set {floorItems(113)} $i\n    $w create text 28.5 179.5 -text 113 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 85 169 79 169 79 192 85 192 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 117A\n    set {floorItems(117A)} $i\n    $w create text 82 180.5 -text 117A -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 77 302 77 168 53 168 53 302 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 117\n    set {floorItems(117)} $i\n    $w create text 65 235 -text 117 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 51 155 51 115 6 115 6 155 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 114\n    set {floorItems(114)} $i\n    $w create text 28.5 135 -text 114 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 95 115 53 115 53 168 95 168 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 115\n    set {floorItems(115)} $i\n    $w create text 74 141.5 -text 115 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 87 113 87 27 10 27 10 113 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 116\n    set {floorItems(116)} $i\n    $w create text 48.5 70 -text 116 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 89 91 128 91 128 113 89 113 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 118\n    set {floorItems(118)} $i\n    $w create text 108.5 102 -text 118 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 178 128 178 132 216 132 216 91 163 91 163 112 149 112 149 128 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 120\n    set {floorItems(120)} $i\n    $w create text 189.5 111.5 -text 120 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 79 193 87 193 87 169 136 169 136 192 156 192 156 169 175 169 175 246 79 246 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 122\n    set {floorItems(122)} $i\n    $w create text 131 207.5 -text 122 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 138 169 154 169 154 191 138 191 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 121\n    set {floorItems(121)} $i\n    $w create text 146 180 -text 121 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 99 300 126 300 126 309 99 309 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 106A\n    set {floorItems(106A)} $i\n    $w create text 112.5 304.5 -text 106A -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 128 299 128 309 150 309 150 248 99 248 99 299 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 105\n    set {floorItems(105)} $i\n    $w create text 124.5 278.5 -text 105 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 174 309 174 300 152 300 152 309 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 106B\n    set {floorItems(106B)} $i\n    $w create text 163 304.5 -text 106B -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 176 299 176 309 216 309 216 248 152 248 152 299 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 104\n    set {floorItems(104)} $i\n    $w create text 184 278.5 -text 104 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 138 385 138 337 91 337 91 385 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 108\n    set {floorItems(108)} $i\n    $w create text 114.5 361 -text 108 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 256 337 140 337 140 385 256 385 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 107\n    set {floorItems(107)} $i\n    $w create text 198 361 -text 107 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 300 353 300 329 260 329 260 353 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) Smoking\n    set {floorItems(Smoking)} $i\n    $w create text 280 341 -text Smoking -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 314 135 314 170 306 170 306 246 177 246 177 135 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 123\n    set {floorItems(123)} $i\n    $w create text 245.5 190.5 -text 123 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 217 248 301 248 301 326 257 326 257 310 217 310 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 103\n    set {floorItems(103)} $i\n    $w create text 259 287 -text 103 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 396 188 377 188 377 169 316 169 316 131 396 131 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 124\n    set {floorItems(124)} $i\n    $w create text 356 150 -text 124 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 397 226 407 226 407 189 377 189 377 246 397 246 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 125\n    set {floorItems(125)} $i\n    $w create text 392 217.5 -text 125 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 399 187 409 187 409 207 474 207 474 164 399 164 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 126\n    set {floorItems(126)} $i\n    $w create text 436.5 185.5 -text 126 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 409 209 409 229 399 229 399 253 486 253 486 239 474 239 474 209 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 127\n    set {floorItems(127)} $i\n    $w create text 436.5 231 -text 127 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 501 164 501 174 495 174 495 188 490 188 490 204 476 204 476 164 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) MShower\n    set {floorItems(MShower)} $i\n    $w create text 488.5 184 -text MShower -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 497 176 513 176 513 204 492 204 492 190 497 190 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) Closet\n    set {floorItems(Closet)} $i\n    $w create text 502.5 190 -text Closet -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 476 237 476 206 513 206 513 254 488 254 488 237 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) WShower\n    set {floorItems(WShower)} $i\n    $w create text 494.5 230 -text WShower -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 486 131 558 131 558 135 724 135 724 166 697 166 697 275 553 275 531 254 515 254 515 174 503 174 503 161 486 161 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 130\n    set {floorItems(130)} $i\n    $w create text 638.5 205 -text 130 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 308 242 339 242 339 248 342 248 342 246 397 246 397 276 393 276 393 309 300 309 300 248 308 248 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 102\n    set {floorItems(102)} $i\n    $w create text 367.5 278.5 -text 102 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 397 255 486 255 486 276 397 276 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 128\n    set {floorItems(128)} $i\n    $w create text 441.5 265.5 -text 128 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 510 309 486 309 486 255 530 255 552 277 561 277 561 325 510 325 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 129\n    set {floorItems(129)} $i\n    $w create text 535.5 293 -text 129 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 696 281 740 281 740 387 642 387 642 389 561 389 561 277 696 277 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 133\n    set {floorItems(133)} $i\n    $w create text 628.5 335 -text 133 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 742 387 742 281 800 281 800 387 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 132\n    set {floorItems(132)} $i\n    $w create text 771 334 -text 132 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 800 168 800 280 699 280 699 168 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 134\n    set {floorItems(134)} $i\n    $w create text 749.5 224 -text 134 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 726 131 726 166 800 166 800 131 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 135\n    set {floorItems(135)} $i\n    $w create text 763 148.5 -text 135 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 340 360 335 363 331 365 326 366 304 366 304 312 396 312 396 288 400 288 404 288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 342 331 347 332 351 334 354 336 357 341 359 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {Ramona Stair}\n    set {floorItems(Ramona Stair)} $i\n    $w create text 368 323 -text {Ramona Stair} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 30 23 30 5 93 5 98 5 104 7 110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 87 90 87 90 23 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {University Stair}\n    set {floorItems(University Stair)} $i\n    $w create text 155 77.5 -text {University Stair} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 282 37 295 40 312 49 323 56 337 70 352 56 358 48 363 39 365 29 348 25 335 22 321 14 300 5 283 1 260 0 246 0 242 2 236 4 231 8 227 13 223 17 221 22 220 34 260 34 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {Plaza Stair}\n    set {floorItems(Plaza Stair)} $i\n    $w create text 317.5 28.5 -text {Plaza Stair} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 220 34 260 34 282 37 295 40 312 49 323 56 337 70 350 83 365 94 377 100 386 104 386 128 220 128 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) {Plaza Deck}\n    set {floorItems(Plaza Deck)} $i\n    $w create text 303 81 -text {Plaza Deck} -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 257 336 77 336 6 336 6 301 77 301 77 310 257 310 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 106\n    set {floorItems(106)} $i\n    $w create text 131.5 318.5 -text 106 -fill $color -anchor c -tags {floor1 label}\n    set i [$w create polygon 146 110 162 110 162 91 130 91 130 115 95 115 95 128 114 128 114 151 157 151 157 153 112 153 112 130 97 130 97 168 175 168 175 131 146 131 -fill {} -outline {} -tags {floor1 room}]\n    set floorLabels($i) 119\n    set {floorItems(119)} $i\n    $w create text 143.5 133 -text 119 -fill $color -anchor c -tags {floor1 label}\n    $w create line 155 191 155 189 -fill $color -tags {floor1 wall}\n    $w create line 155 177 155 169 -fill $color -tags {floor1 wall}\n    $w create line 96 129 96 169 -fill $color -tags {floor1 wall}\n    $w create line 78 169 176 169 -fill $color -tags {floor1 wall}\n    $w create line 176 247 176 129 -fill $color -tags {floor1 wall}\n    $w create line 340 206 307 206 -fill $color -tags {floor1 wall}\n    $w create line 340 187 340 170 -fill $color -tags {floor1 wall}\n    $w create line 340 210 340 201 -fill $color -tags {floor1 wall}\n    $w create line 340 247 340 224 -fill $color -tags {floor1 wall}\n    $w create line 340 241 307 241 -fill $color -tags {floor1 wall}\n    $w create line 376 246 376 170 -fill $color -tags {floor1 wall}\n    $w create line 307 247 307 170 -fill $color -tags {floor1 wall}\n    $w create line 376 170 307 170 -fill $color -tags {floor1 wall}\n    $w create line 315 129 315 170 -fill $color -tags {floor1 wall}\n    $w create line 147 129 176 129 -fill $color -tags {floor1 wall}\n    $w create line 202 133 176 133 -fill $color -tags {floor1 wall}\n    $w create line 398 129 315 129 -fill $color -tags {floor1 wall}\n    $w create line 258 352 258 387 -fill $color -tags {floor1 wall}\n    $w create line 60 387 60 391 -fill $color -tags {floor1 wall}\n    $w create line 0 337 0 391 -fill $color -tags {floor1 wall}\n    $w create line 60 391 0 391 -fill $color -tags {floor1 wall}\n    $w create line 3 114 3 337 -fill $color -tags {floor1 wall}\n    $w create line 258 387 60 387 -fill $color -tags {floor1 wall}\n    $w create line 52 237 52 273 -fill $color -tags {floor1 wall}\n    $w create line 52 189 52 225 -fill $color -tags {floor1 wall}\n    $w create line 52 140 52 177 -fill $color -tags {floor1 wall}\n    $w create line 395 306 395 311 -fill $color -tags {floor1 wall}\n    $w create line 531 254 398 254 -fill $color -tags {floor1 wall}\n    $w create line 475 178 475 238 -fill $color -tags {floor1 wall}\n    $w create line 502 162 398 162 -fill $color -tags {floor1 wall}\n    $w create line 398 129 398 188 -fill $color -tags {floor1 wall}\n    $w create line 383 188 376 188 -fill $color -tags {floor1 wall}\n    $w create line 408 188 408 194 -fill $color -tags {floor1 wall}\n    $w create line 398 227 398 254 -fill $color -tags {floor1 wall}\n    $w create line 408 227 398 227 -fill $color -tags {floor1 wall}\n    $w create line 408 222 408 227 -fill $color -tags {floor1 wall}\n    $w create line 408 206 408 210 -fill $color -tags {floor1 wall}\n    $w create line 408 208 475 208 -fill $color -tags {floor1 wall}\n    $w create line 484 278 484 311 -fill $color -tags {floor1 wall}\n    $w create line 484 311 508 311 -fill $color -tags {floor1 wall}\n    $w create line 508 327 508 311 -fill $color -tags {floor1 wall}\n    $w create line 559 327 508 327 -fill $color -tags {floor1 wall}\n    $w create line 644 391 559 391 -fill $color -tags {floor1 wall}\n    $w create line 644 389 644 391 -fill $color -tags {floor1 wall}\n    $w create line 514 205 475 205 -fill $color -tags {floor1 wall}\n    $w create line 496 189 496 187 -fill $color -tags {floor1 wall}\n    $w create line 559 129 484 129 -fill $color -tags {floor1 wall}\n    $w create line 484 162 484 129 -fill $color -tags {floor1 wall}\n    $w create line 725 133 559 133 -fill $color -tags {floor1 wall}\n    $w create line 559 129 559 133 -fill $color -tags {floor1 wall}\n    $w create line 725 149 725 167 -fill $color -tags {floor1 wall}\n    $w create line 725 129 802 129 -fill $color -tags {floor1 wall}\n    $w create line 802 389 802 129 -fill $color -tags {floor1 wall}\n    $w create line 739 167 802 167 -fill $color -tags {floor1 wall}\n    $w create line 396 188 408 188 -fill $color -tags {floor1 wall}\n    $w create line 0 337 9 337 -fill $color -tags {floor1 wall}\n    $w create line 58 337 21 337 -fill $color -tags {floor1 wall}\n    $w create line 43 391 43 337 -fill $color -tags {floor1 wall}\n    $w create line 105 337 75 337 -fill $color -tags {floor1 wall}\n    $w create line 91 387 91 337 -fill $color -tags {floor1 wall}\n    $w create line 154 337 117 337 -fill $color -tags {floor1 wall}\n    $w create line 139 387 139 337 -fill $color -tags {floor1 wall}\n    $w create line 227 337 166 337 -fill $color -tags {floor1 wall}\n    $w create line 258 337 251 337 -fill $color -tags {floor1 wall}\n    $w create line 258 328 302 328 -fill $color -tags {floor1 wall}\n    $w create line 302 355 302 311 -fill $color -tags {floor1 wall}\n    $w create line 395 311 302 311 -fill $color -tags {floor1 wall}\n    $w create line 484 278 395 278 -fill $color -tags {floor1 wall}\n    $w create line 395 294 395 278 -fill $color -tags {floor1 wall}\n    $w create line 473 278 473 275 -fill $color -tags {floor1 wall}\n    $w create line 473 256 473 254 -fill $color -tags {floor1 wall}\n    $w create line 533 257 531 254 -fill $color -tags {floor1 wall}\n    $w create line 553 276 551 274 -fill $color -tags {floor1 wall}\n    $w create line 698 276 553 276 -fill $color -tags {floor1 wall}\n    $w create line 559 391 559 327 -fill $color -tags {floor1 wall}\n    $w create line 802 389 644 389 -fill $color -tags {floor1 wall}\n    $w create line 741 314 741 389 -fill $color -tags {floor1 wall}\n    $w create line 698 280 698 167 -fill $color -tags {floor1 wall}\n    $w create line 707 280 698 280 -fill $color -tags {floor1 wall}\n    $w create line 802 280 731 280 -fill $color -tags {floor1 wall}\n    $w create line 741 280 741 302 -fill $color -tags {floor1 wall}\n    $w create line 698 167 727 167 -fill $color -tags {floor1 wall}\n    $w create line 725 137 725 129 -fill $color -tags {floor1 wall}\n    $w create line 514 254 514 175 -fill $color -tags {floor1 wall}\n    $w create line 496 175 514 175 -fill $color -tags {floor1 wall}\n    $w create line 502 175 502 162 -fill $color -tags {floor1 wall}\n    $w create line 475 166 475 162 -fill $color -tags {floor1 wall}\n    $w create line 496 176 496 175 -fill $color -tags {floor1 wall}\n    $w create line 491 189 496 189 -fill $color -tags {floor1 wall}\n    $w create line 491 205 491 189 -fill $color -tags {floor1 wall}\n    $w create line 487 238 475 238 -fill $color -tags {floor1 wall}\n    $w create line 487 240 487 238 -fill $color -tags {floor1 wall}\n    $w create line 487 252 487 254 -fill $color -tags {floor1 wall}\n    $w create line 315 133 304 133 -fill $color -tags {floor1 wall}\n    $w create line 256 133 280 133 -fill $color -tags {floor1 wall}\n    $w create line 78 247 270 247 -fill $color -tags {floor1 wall}\n    $w create line 307 247 294 247 -fill $color -tags {floor1 wall}\n    $w create line 214 133 232 133 -fill $color -tags {floor1 wall}\n    $w create line 217 247 217 266 -fill $color -tags {floor1 wall}\n    $w create line 217 309 217 291 -fill $color -tags {floor1 wall}\n    $w create line 217 309 172 309 -fill $color -tags {floor1 wall}\n    $w create line 154 309 148 309 -fill $color -tags {floor1 wall}\n    $w create line 175 300 175 309 -fill $color -tags {floor1 wall}\n    $w create line 151 300 175 300 -fill $color -tags {floor1 wall}\n    $w create line 151 247 151 309 -fill $color -tags {floor1 wall}\n    $w create line 78 237 78 265 -fill $color -tags {floor1 wall}\n    $w create line 78 286 78 309 -fill $color -tags {floor1 wall}\n    $w create line 106 309 78 309 -fill $color -tags {floor1 wall}\n    $w create line 130 309 125 309 -fill $color -tags {floor1 wall}\n    $w create line 99 309 99 247 -fill $color -tags {floor1 wall}\n    $w create line 127 299 99 299 -fill $color -tags {floor1 wall}\n    $w create line 127 309 127 299 -fill $color -tags {floor1 wall}\n    $w create line 155 191 137 191 -fill $color -tags {floor1 wall}\n    $w create line 137 169 137 191 -fill $color -tags {floor1 wall}\n    $w create line 78 171 78 169 -fill $color -tags {floor1 wall}\n    $w create line 78 190 78 218 -fill $color -tags {floor1 wall}\n    $w create line 86 192 86 169 -fill $color -tags {floor1 wall}\n    $w create line 86 192 78 192 -fill $color -tags {floor1 wall}\n    $w create line 52 301 3 301 -fill $color -tags {floor1 wall}\n    $w create line 52 286 52 301 -fill $color -tags {floor1 wall}\n    $w create line 52 252 3 252 -fill $color -tags {floor1 wall}\n    $w create line 52 203 3 203 -fill $color -tags {floor1 wall}\n    $w create line 3 156 52 156 -fill $color -tags {floor1 wall}\n    $w create line 8 25 8 114 -fill $color -tags {floor1 wall}\n    $w create line 63 114 3 114 -fill $color -tags {floor1 wall}\n    $w create line 75 114 97 114 -fill $color -tags {floor1 wall}\n    $w create line 108 114 129 114 -fill $color -tags {floor1 wall}\n    $w create line 129 114 129 89 -fill $color -tags {floor1 wall}\n    $w create line 52 114 52 128 -fill $color -tags {floor1 wall}\n    $w create line 132 89 88 89 -fill $color -tags {floor1 wall}\n    $w create line 88 25 88 89 -fill $color -tags {floor1 wall}\n    $w create line 88 114 88 89 -fill $color -tags {floor1 wall}\n    $w create line 218 89 144 89 -fill $color -tags {floor1 wall}\n    $w create line 147 111 147 129 -fill $color -tags {floor1 wall}\n    $w create line 162 111 147 111 -fill $color -tags {floor1 wall}\n    $w create line 162 109 162 111 -fill $color -tags {floor1 wall}\n    $w create line 162 96 162 89 -fill $color -tags {floor1 wall}\n    $w create line 218 89 218 94 -fill $color -tags {floor1 wall}\n    $w create line 218 89 218 119 -fill $color -tags {floor1 wall}\n    $w create line 8 25 88 25 -fill $color -tags {floor1 wall}\n    $w create line 258 337 258 328 -fill $color -tags {floor1 wall}\n    $w create line 113 129 96 129 -fill $color -tags {floor1 wall}\n    $w create line 302 355 258 355 -fill $color -tags {floor1 wall}\n    $w create line 386 104 386 129 -fill $color -tags {floor1 wall}\n    $w create line 377 100 386 104 -fill $color -tags {floor1 wall}\n    $w create line 365 94 377 100 -fill $color -tags {floor1 wall}\n    $w create line 350 83 365 94 -fill $color -tags {floor1 wall}\n    $w create line 337 70 350 83 -fill $color -tags {floor1 wall}\n    $w create line 337 70 323 56 -fill $color -tags {floor1 wall}\n    $w create line 312 49 323 56 -fill $color -tags {floor1 wall}\n    $w create line 295 40 312 49 -fill $color -tags {floor1 wall}\n    $w create line 282 37 295 40 -fill $color -tags {floor1 wall}\n    $w create line 260 34 282 37 -fill $color -tags {floor1 wall}\n    $w create line 253 34 260 34 -fill $color -tags {floor1 wall}\n    $w create line 386 128 386 104 -fill $color -tags {floor1 wall}\n    $w create line 113 152 156 152 -fill $color -tags {floor1 wall}\n    $w create line 113 152 156 152 -fill $color -tags {floor1 wall}\n    $w create line 113 152 113 129 -fill $color -tags {floor1 wall}\n}\n\n# fg2 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the foreground information for the second\n# floor (office outlines and numbers).\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# color -\tColor to use for drawing foreground information.\n\nproc fg2 {w color} {\n    global floorLabels floorItems\n    set i [$w create polygon 748 188 755 188 755 205 758 205 758 222 800 222 800 168 748 168 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 238\n    set {floorItems(238)} $i\n    $w create text 774 195 -text 238 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 726 188 746 188 746 166 800 166 800 131 726 131 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 237\n    set {floorItems(237)} $i\n    $w create text 763 148.5 -text 237 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 497 187 497 204 559 204 559 324 641 324 643 324 643 291 641 291 641 205 696 205 696 291 694 291 694 314 715 314 715 291 715 205 755 205 755 190 724 190 724 187 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 246\n    set {floorItems(246)} $i\n    $w create text 600 264 -text 246 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 694 279 643 279 643 314 694 314 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 247\n    set {floorItems(247)} $i\n    $w create text 668.5 296.5 -text 247 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 232 250 308 250 308 242 339 242 339 246 397 246 397 255 476 255 476 250 482 250 559 250 559 274 482 274 482 278 396 278 396 274 232 274 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 202\n    set {floorItems(202)} $i\n    $w create text 285.5 260 -text 202 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 53 228 53 338 176 338 233 338 233 196 306 196 306 180 175 180 175 169 156 169 156 196 176 196 176 228 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 206\n    set {floorItems(206)} $i\n    $w create text 143 267 -text 206 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 51 277 6 277 6 338 51 338 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 212\n    set {floorItems(212)} $i\n    $w create text 28.5 307.5 -text 212 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 557 276 486 276 486 309 510 309 510 325 557 325 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 245\n    set {floorItems(245)} $i\n    $w create text 521.5 300.5 -text 245 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 560 389 599 389 599 326 560 326 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 244\n    set {floorItems(244)} $i\n    $w create text 579.5 357.5 -text 244 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 601 389 601 326 643 326 643 389 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 243\n    set {floorItems(243)} $i\n    $w create text 622 357.5 -text 243 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 688 316 645 316 645 365 688 365 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 242\n    set {floorItems(242)} $i\n    $w create text 666.5 340.5 -text 242 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 802 367 759 367 759 226 802 226 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) {Barbecue Deck}\n    set {floorItems(Barbecue Deck)} $i\n    $w create text 780.5 296.5 -text {Barbecue Deck} -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 755 262 755 314 717 314 717 262 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 240\n    set {floorItems(240)} $i\n    $w create text 736 288 -text 240 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 755 316 689 316 689 365 755 365 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 241\n    set {floorItems(241)} $i\n    $w create text 722 340.5 -text 241 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 755 206 717 206 717 261 755 261 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 239\n    set {floorItems(239)} $i\n    $w create text 736 233.5 -text 239 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 695 277 643 277 643 206 695 206 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 248\n    set {floorItems(248)} $i\n    $w create text 669 241.5 -text 248 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 676 135 676 185 724 185 724 135 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 236\n    set {floorItems(236)} $i\n    $w create text 700 160 -text 236 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 675 135 635 135 635 145 628 145 628 185 675 185 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 235\n    set {floorItems(235)} $i\n    $w create text 651.5 160 -text 235 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 626 143 633 143 633 135 572 135 572 143 579 143 579 185 626 185 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 234\n    set {floorItems(234)} $i\n    $w create text 606 160 -text 234 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 557 135 571 135 571 145 578 145 578 185 527 185 527 131 557 131 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 233\n    set {floorItems(233)} $i\n    $w create text 552.5 158 -text 233 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 476 249 557 249 557 205 476 205 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 230\n    set {floorItems(230)} $i\n    $w create text 516.5 227 -text 230 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 476 164 486 164 486 131 525 131 525 185 476 185 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 232\n    set {floorItems(232)} $i\n    $w create text 500.5 158 -text 232 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 476 186 495 186 495 204 476 204 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 229\n    set {floorItems(229)} $i\n    $w create text 485.5 195 -text 229 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 474 207 409 207 409 187 399 187 399 164 474 164 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 227\n    set {floorItems(227)} $i\n    $w create text 436.5 185.5 -text 227 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 399 228 399 253 474 253 474 209 409 209 409 228 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 228\n    set {floorItems(228)} $i\n    $w create text 436.5 231 -text 228 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 397 246 397 226 407 226 407 189 377 189 377 246 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 226\n    set {floorItems(226)} $i\n    $w create text 392 217.5 -text 226 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 377 169 316 169 316 131 397 131 397 188 377 188 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 225\n    set {floorItems(225)} $i\n    $w create text 356.5 150 -text 225 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 234 198 306 198 306 249 234 249 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 224\n    set {floorItems(224)} $i\n    $w create text 270 223.5 -text 224 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 270 179 306 179 306 170 314 170 314 135 270 135 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 223\n    set {floorItems(223)} $i\n    $w create text 292 157 -text 223 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 268 179 221 179 221 135 268 135 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 222\n    set {floorItems(222)} $i\n    $w create text 244.5 157 -text 222 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 177 179 219 179 219 135 177 135 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 221\n    set {floorItems(221)} $i\n    $w create text 198 157 -text 221 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 299 327 349 327 349 284 341 284 341 276 299 276 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 204\n    set {floorItems(204)} $i\n    $w create text 324 301.5 -text 204 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 234 276 297 276 297 327 257 327 257 338 234 338 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 205\n    set {floorItems(205)} $i\n    $w create text 265.5 307 -text 205 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 256 385 256 340 212 340 212 385 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 207\n    set {floorItems(207)} $i\n    $w create text 234 362.5 -text 207 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 210 340 164 340 164 385 210 385 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 208\n    set {floorItems(208)} $i\n    $w create text 187 362.5 -text 208 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 115 340 162 340 162 385 115 385 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 209\n    set {floorItems(209)} $i\n    $w create text 138.5 362.5 -text 209 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 89 228 89 156 53 156 53 228 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 217\n    set {floorItems(217)} $i\n    $w create text 71 192 -text 217 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 89 169 97 169 97 190 89 190 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 217A\n    set {floorItems(217A)} $i\n    $w create text 93 179.5 -text 217A -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 89 156 89 168 95 168 95 135 53 135 53 156 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 216\n    set {floorItems(216)} $i\n    $w create text 71 145.5 -text 216 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 51 179 51 135 6 135 6 179 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 215\n    set {floorItems(215)} $i\n    $w create text 28.5 157 -text 215 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 51 227 6 227 6 180 51 180 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 214\n    set {floorItems(214)} $i\n    $w create text 28.5 203.5 -text 214 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 51 275 6 275 6 229 51 229 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 213\n    set {floorItems(213)} $i\n    $w create text 28.5 252 -text 213 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 114 340 67 340 67 385 114 385 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 210\n    set {floorItems(210)} $i\n    $w create text 90.5 362.5 -text 210 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 59 389 59 385 65 385 65 340 1 340 1 389 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 211\n    set {floorItems(211)} $i\n    $w create text 33 364.5 -text 211 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 393 309 350 309 350 282 342 282 342 276 393 276 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 203\n    set {floorItems(203)} $i\n    $w create text 367.5 292.5 -text 203 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 99 191 91 191 91 226 174 226 174 198 154 198 154 192 109 192 109 169 99 169 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 220\n    set {floorItems(220)} $i\n    $w create text 132.5 208.5 -text 220 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) {Priv Lift2}\n    set {floorItems(Priv Lift2)} $i\n    $w create text 323 188 -text {Priv Lift2} -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) {Pub Lift 2}\n    set {floorItems(Pub Lift 2)} $i\n    $w create text 323 223 -text {Pub Lift 2} -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 218\n    set {floorItems(218)} $i\n    $w create text 136 149.5 -text 218 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 219\n    set {floorItems(219)} $i\n    $w create text 132.5 180 -text 219 -fill $color -anchor c -tags {floor2 label}\n    set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -outline {} -tags {floor2 room}]\n    set floorLabels($i) 201\n    set {floorItems(201)} $i\n    $w create text 358 209 -text 201 -fill $color -anchor c -tags {floor2 label}\n    $w create line 641 186 678 186 -fill $color -tags {floor2 wall}\n    $w create line 757 350 757 367 -fill $color -tags {floor2 wall}\n    $w create line 634 133 634 144 -fill $color -tags {floor2 wall}\n    $w create line 634 144 627 144 -fill $color -tags {floor2 wall}\n    $w create line 572 133 572 144 -fill $color -tags {floor2 wall}\n    $w create line 572 144 579 144 -fill $color -tags {floor2 wall}\n    $w create line 398 129 398 162 -fill $color -tags {floor2 wall}\n    $w create line 174 197 175 197 -fill $color -tags {floor2 wall}\n    $w create line 175 197 175 227 -fill $color -tags {floor2 wall}\n    $w create line 757 206 757 221 -fill $color -tags {floor2 wall}\n    $w create line 396 188 408 188 -fill $color -tags {floor2 wall}\n    $w create line 727 189 725 189 -fill $color -tags {floor2 wall}\n    $w create line 747 167 802 167 -fill $color -tags {floor2 wall}\n    $w create line 747 167 747 189 -fill $color -tags {floor2 wall}\n    $w create line 755 189 739 189 -fill $color -tags {floor2 wall}\n    $w create line 769 224 757 224 -fill $color -tags {floor2 wall}\n    $w create line 802 224 802 129 -fill $color -tags {floor2 wall}\n    $w create line 802 129 725 129 -fill $color -tags {floor2 wall}\n    $w create line 725 189 725 129 -fill $color -tags {floor2 wall}\n    $w create line 725 186 690 186 -fill $color -tags {floor2 wall}\n    $w create line 676 133 676 186 -fill $color -tags {floor2 wall}\n    $w create line 627 144 627 186 -fill $color -tags {floor2 wall}\n    $w create line 629 186 593 186 -fill $color -tags {floor2 wall}\n    $w create line 579 144 579 186 -fill $color -tags {floor2 wall}\n    $w create line 559 129 559 133 -fill $color -tags {floor2 wall}\n    $w create line 725 133 559 133 -fill $color -tags {floor2 wall}\n    $w create line 484 162 484 129 -fill $color -tags {floor2 wall}\n    $w create line 559 129 484 129 -fill $color -tags {floor2 wall}\n    $w create line 526 129 526 186 -fill $color -tags {floor2 wall}\n    $w create line 540 186 581 186 -fill $color -tags {floor2 wall}\n    $w create line 528 186 523 186 -fill $color -tags {floor2 wall}\n    $w create line 511 186 475 186 -fill $color -tags {floor2 wall}\n    $w create line 496 190 496 186 -fill $color -tags {floor2 wall}\n    $w create line 496 205 496 202 -fill $color -tags {floor2 wall}\n    $w create line 475 205 527 205 -fill $color -tags {floor2 wall}\n    $w create line 558 205 539 205 -fill $color -tags {floor2 wall}\n    $w create line 558 205 558 249 -fill $color -tags {floor2 wall}\n    $w create line 558 249 475 249 -fill $color -tags {floor2 wall}\n    $w create line 662 206 642 206 -fill $color -tags {floor2 wall}\n    $w create line 695 206 675 206 -fill $color -tags {floor2 wall}\n    $w create line 695 278 642 278 -fill $color -tags {floor2 wall}\n    $w create line 642 291 642 206 -fill $color -tags {floor2 wall}\n    $w create line 695 291 695 206 -fill $color -tags {floor2 wall}\n    $w create line 716 208 716 206 -fill $color -tags {floor2 wall}\n    $w create line 757 206 716 206 -fill $color -tags {floor2 wall}\n    $w create line 757 221 757 224 -fill $color -tags {floor2 wall}\n    $w create line 793 224 802 224 -fill $color -tags {floor2 wall}\n    $w create line 757 262 716 262 -fill $color -tags {floor2 wall}\n    $w create line 716 220 716 264 -fill $color -tags {floor2 wall}\n    $w create line 716 315 716 276 -fill $color -tags {floor2 wall}\n    $w create line 757 315 703 315 -fill $color -tags {floor2 wall}\n    $w create line 757 325 757 224 -fill $color -tags {floor2 wall}\n    $w create line 757 367 644 367 -fill $color -tags {floor2 wall}\n    $w create line 689 367 689 315 -fill $color -tags {floor2 wall}\n    $w create line 647 315 644 315 -fill $color -tags {floor2 wall}\n    $w create line 659 315 691 315 -fill $color -tags {floor2 wall}\n    $w create line 600 325 600 391 -fill $color -tags {floor2 wall}\n    $w create line 627 325 644 325 -fill $color -tags {floor2 wall}\n    $w create line 644 391 644 315 -fill $color -tags {floor2 wall}\n    $w create line 615 325 575 325 -fill $color -tags {floor2 wall}\n    $w create line 644 391 558 391 -fill $color -tags {floor2 wall}\n    $w create line 563 325 558 325 -fill $color -tags {floor2 wall}\n    $w create line 558 391 558 314 -fill $color -tags {floor2 wall}\n    $w create line 558 327 508 327 -fill $color -tags {floor2 wall}\n    $w create line 558 275 484 275 -fill $color -tags {floor2 wall}\n    $w create line 558 302 558 275 -fill $color -tags {floor2 wall}\n    $w create line 508 327 508 311 -fill $color -tags {floor2 wall}\n    $w create line 484 311 508 311 -fill $color -tags {floor2 wall}\n    $w create line 484 275 484 311 -fill $color -tags {floor2 wall}\n    $w create line 475 208 408 208 -fill $color -tags {floor2 wall}\n    $w create line 408 206 408 210 -fill $color -tags {floor2 wall}\n    $w create line 408 222 408 227 -fill $color -tags {floor2 wall}\n    $w create line 408 227 398 227 -fill $color -tags {floor2 wall}\n    $w create line 398 227 398 254 -fill $color -tags {floor2 wall}\n    $w create line 408 188 408 194 -fill $color -tags {floor2 wall}\n    $w create line 383 188 376 188 -fill $color -tags {floor2 wall}\n    $w create line 398 188 398 162 -fill $color -tags {floor2 wall}\n    $w create line 398 162 484 162 -fill $color -tags {floor2 wall}\n    $w create line 475 162 475 254 -fill $color -tags {floor2 wall}\n    $w create line 398 254 475 254 -fill $color -tags {floor2 wall}\n    $w create line 484 280 395 280 -fill $color -tags {floor2 wall}\n    $w create line 395 311 395 275 -fill $color -tags {floor2 wall}\n    $w create line 307 197 293 197 -fill $color -tags {floor2 wall}\n    $w create line 278 197 233 197 -fill $color -tags {floor2 wall}\n    $w create line 233 197 233 249 -fill $color -tags {floor2 wall}\n    $w create line 307 179 284 179 -fill $color -tags {floor2 wall}\n    $w create line 233 249 278 249 -fill $color -tags {floor2 wall}\n    $w create line 269 179 269 133 -fill $color -tags {floor2 wall}\n    $w create line 220 179 220 133 -fill $color -tags {floor2 wall}\n    $w create line 155 191 110 191 -fill $color -tags {floor2 wall}\n    $w create line 90 190 98 190 -fill $color -tags {floor2 wall}\n    $w create line 98 169 98 190 -fill $color -tags {floor2 wall}\n    $w create line 52 133 52 165 -fill $color -tags {floor2 wall}\n    $w create line 52 214 52 177 -fill $color -tags {floor2 wall}\n    $w create line 52 226 52 262 -fill $color -tags {floor2 wall}\n    $w create line 52 274 52 276 -fill $color -tags {floor2 wall}\n    $w create line 234 275 234 339 -fill $color -tags {floor2 wall}\n    $w create line 226 339 258 339 -fill $color -tags {floor2 wall}\n    $w create line 211 387 211 339 -fill $color -tags {floor2 wall}\n    $w create line 214 339 177 339 -fill $color -tags {floor2 wall}\n    $w create line 258 387 60 387 -fill $color -tags {floor2 wall}\n    $w create line 3 133 3 339 -fill $color -tags {floor2 wall}\n    $w create line 165 339 129 339 -fill $color -tags {floor2 wall}\n    $w create line 117 339 80 339 -fill $color -tags {floor2 wall}\n    $w create line 68 339 59 339 -fill $color -tags {floor2 wall}\n    $w create line 0 339 46 339 -fill $color -tags {floor2 wall}\n    $w create line 60 391 0 391 -fill $color -tags {floor2 wall}\n    $w create line 0 339 0 391 -fill $color -tags {floor2 wall}\n    $w create line 60 387 60 391 -fill $color -tags {floor2 wall}\n    $w create line 258 329 258 387 -fill $color -tags {floor2 wall}\n    $w create line 350 329 258 329 -fill $color -tags {floor2 wall}\n    $w create line 395 311 350 311 -fill $color -tags {floor2 wall}\n    $w create line 398 129 315 129 -fill $color -tags {floor2 wall}\n    $w create line 176 133 315 133 -fill $color -tags {floor2 wall}\n    $w create line 176 129 96 129 -fill $color -tags {floor2 wall}\n    $w create line 3 133 96 133 -fill $color -tags {floor2 wall}\n    $w create line 66 387 66 339 -fill $color -tags {floor2 wall}\n    $w create line 115 387 115 339 -fill $color -tags {floor2 wall}\n    $w create line 163 387 163 339 -fill $color -tags {floor2 wall}\n    $w create line 234 275 276 275 -fill $color -tags {floor2 wall}\n    $w create line 288 275 309 275 -fill $color -tags {floor2 wall}\n    $w create line 298 275 298 329 -fill $color -tags {floor2 wall}\n    $w create line 341 283 350 283 -fill $color -tags {floor2 wall}\n    $w create line 321 275 341 275 -fill $color -tags {floor2 wall}\n    $w create line 375 275 395 275 -fill $color -tags {floor2 wall}\n    $w create line 315 129 315 170 -fill $color -tags {floor2 wall}\n    $w create line 376 170 307 170 -fill $color -tags {floor2 wall}\n    $w create line 307 250 307 170 -fill $color -tags {floor2 wall}\n    $w create line 376 245 376 170 -fill $color -tags {floor2 wall}\n    $w create line 340 241 307 241 -fill $color -tags {floor2 wall}\n    $w create line 340 245 340 224 -fill $color -tags {floor2 wall}\n    $w create line 340 210 340 201 -fill $color -tags {floor2 wall}\n    $w create line 340 187 340 170 -fill $color -tags {floor2 wall}\n    $w create line 340 206 307 206 -fill $color -tags {floor2 wall}\n    $w create line 293 250 307 250 -fill $color -tags {floor2 wall}\n    $w create line 271 179 238 179 -fill $color -tags {floor2 wall}\n    $w create line 226 179 195 179 -fill $color -tags {floor2 wall}\n    $w create line 176 129 176 179 -fill $color -tags {floor2 wall}\n    $w create line 182 179 176 179 -fill $color -tags {floor2 wall}\n    $w create line 174 169 176 169 -fill $color -tags {floor2 wall}\n    $w create line 162 169 90 169 -fill $color -tags {floor2 wall}\n    $w create line 96 169 96 129 -fill $color -tags {floor2 wall}\n    $w create line 175 227 90 227 -fill $color -tags {floor2 wall}\n    $w create line 90 190 90 227 -fill $color -tags {floor2 wall}\n    $w create line 52 179 3 179 -fill $color -tags {floor2 wall}\n    $w create line 52 228 3 228 -fill $color -tags {floor2 wall}\n    $w create line 52 276 3 276 -fill $color -tags {floor2 wall}\n    $w create line 155 177 155 169 -fill $color -tags {floor2 wall}\n    $w create line 110 191 110 169 -fill $color -tags {floor2 wall}\n    $w create line 155 189 155 197 -fill $color -tags {floor2 wall}\n    $w create line 350 283 350 329 -fill $color -tags {floor2 wall}\n    $w create line 162 197 155 197 -fill $color -tags {floor2 wall}\n    $w create line 341 275 341 283 -fill $color -tags {floor2 wall}\n}\n\n# fg3 --\n# This procedure represents part of the floorplan database.  When\n# invoked, it instantiates the foreground information for the third\n# floor (office outlines and numbers).\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# color -\tColor to use for drawing foreground information.\n\nproc fg3 {w color} {\n    global floorLabels floorItems\n    set i [$w create polygon 89 228 89 180 70 180 70 228 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 316\n    set {floorItems(316)} $i\n    $w create text 79.5 204 -text 316 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 115 368 162 368 162 323 115 323 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 309\n    set {floorItems(309)} $i\n    $w create text 138.5 345.5 -text 309 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 164 323 164 368 211 368 211 323 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 308\n    set {floorItems(308)} $i\n    $w create text 187.5 345.5 -text 308 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 256 368 212 368 212 323 256 323 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 307\n    set {floorItems(307)} $i\n    $w create text 234 345.5 -text 307 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 244 276 297 276 297 327 260 327 260 321 244 321 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 305\n    set {floorItems(305)} $i\n    $w create text 270.5 301.5 -text 305 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 251 219 251 203 244 203 244 219 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 324B\n    set {floorItems(324B)} $i\n    $w create text 247.5 211 -text 324B -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 251 249 244 249 244 232 251 232 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 324A\n    set {floorItems(324A)} $i\n    $w create text 247.5 240.5 -text 324A -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 223 135 223 179 177 179 177 135 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 320\n    set {floorItems(320)} $i\n    $w create text 200 157 -text 320 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 114 368 114 323 67 323 67 368 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 310\n    set {floorItems(310)} $i\n    $w create text 90.5 345.5 -text 310 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 23 277 23 321 68 321 68 277 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 312\n    set {floorItems(312)} $i\n    $w create text 45.5 299 -text 312 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 23 229 68 229 68 275 23 275 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 313\n    set {floorItems(313)} $i\n    $w create text 45.5 252 -text 313 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 68 227 23 227 23 180 68 180 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 314\n    set {floorItems(314)} $i\n    $w create text 45.5 203.5 -text 314 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 95 179 95 135 23 135 23 179 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 315\n    set {floorItems(315)} $i\n    $w create text 59 157 -text 315 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 99 226 99 204 91 204 91 226 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 316B\n    set {floorItems(316B)} $i\n    $w create text 95 215 -text 316B -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 91 202 99 202 99 180 91 180 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 316A\n    set {floorItems(316A)} $i\n    $w create text 95 191 -text 316A -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 97 169 109 169 109 192 154 192 154 198 174 198 174 226 101 226 101 179 97 179 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 319\n    set {floorItems(319)} $i\n    $w create text 141.5 209 -text 319 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 65 368 58 368 58 389 1 389 1 333 23 333 23 323 65 323 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 311\n    set {floorItems(311)} $i\n    $w create text 29.5 361 -text 311 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 318\n    set {floorItems(318)} $i\n    $w create text 132.5 180 -text 318 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 317\n    set {floorItems(317)} $i\n    $w create text 136 149.5 -text 317 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 274 194 274 221 306 221 306 194 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 323\n    set {floorItems(323)} $i\n    $w create text 290 207.5 -text 323 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 306 222 274 222 274 249 306 249 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 325\n    set {floorItems(325)} $i\n    $w create text 290 235.5 -text 325 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 263 179 224 179 224 135 263 135 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 321\n    set {floorItems(321)} $i\n    $w create text 243.5 157 -text 321 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 314 169 306 169 306 192 273 192 264 181 264 135 314 135 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 322\n    set {floorItems(322)} $i\n    $w create text 293.5 163.5 -text 322 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) {Pub Lift3}\n    set {floorItems(Pub Lift3)} $i\n    $w create text 323 223 -text {Pub Lift3} -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) {Priv Lift3}\n    set {floorItems(Priv Lift3)} $i\n    $w create text 323 188 -text {Priv Lift3} -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 350 284 376 284 376 276 397 276 397 309 350 309 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 303\n    set {floorItems(303)} $i\n    $w create text 373.5 292.5 -text 303 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 272 203 272 249 252 249 252 230 244 230 244 221 252 221 252 203 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 324\n    set {floorItems(324)} $i\n    $w create text 262 226 -text 324 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 299 276 299 327 349 327 349 284 341 284 341 276 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 304\n    set {floorItems(304)} $i\n    $w create text 324 301.5 -text 304 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 301\n    set {floorItems(301)} $i\n    $w create text 358 209 -text 301 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 397 246 377 246 377 185 397 185 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 327\n    set {floorItems(327)} $i\n    $w create text 387 215.5 -text 327 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 316 131 316 169 377 169 377 185 397 185 397 131 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 326\n    set {floorItems(326)} $i\n    $w create text 356.5 150 -text 326 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 308 251 242 251 242 274 342 274 342 282 375 282 375 274 397 274 397 248 339 248 339 242 308 242 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 302\n    set {floorItems(302)} $i\n    $w create text 319.5 261 -text 302 -fill $color -anchor c -tags {floor3 label}\n    set i [$w create polygon 70 321 242 321 242 200 259 200 259 203 272 203 272 193 263 180 242 180 175 180 175 169 156 169 156 196 177 196 177 228 107 228 70 228 70 275 107 275 107 248 160 248 160 301 107 301 107 275 70 275 -fill {} -outline {} -tags {floor3 room}]\n    set floorLabels($i) 306\n    set {floorItems(306)} $i\n    $w create text 200.5 284.5 -text 306 -fill $color -anchor c -tags {floor3 label}\n    $w create line 341 275 341 283 -fill $color -tags {floor3 wall}\n    $w create line 162 197 155 197 -fill $color -tags {floor3 wall}\n    $w create line 396 247 399 247 -fill $color -tags {floor3 wall}\n    $w create line 399 129 399 311 -fill $color -tags {floor3 wall}\n    $w create line 258 202 243 202 -fill $color -tags {floor3 wall}\n    $w create line 350 283 350 329 -fill $color -tags {floor3 wall}\n    $w create line 251 231 243 231 -fill $color -tags {floor3 wall}\n    $w create line 243 220 251 220 -fill $color -tags {floor3 wall}\n    $w create line 243 250 243 202 -fill $color -tags {floor3 wall}\n    $w create line 155 197 155 190 -fill $color -tags {floor3 wall}\n    $w create line 110 192 110 169 -fill $color -tags {floor3 wall}\n    $w create line 155 192 110 192 -fill $color -tags {floor3 wall}\n    $w create line 155 177 155 169 -fill $color -tags {floor3 wall}\n    $w create line 176 197 176 227 -fill $color -tags {floor3 wall}\n    $w create line 69 280 69 274 -fill $color -tags {floor3 wall}\n    $w create line 21 276 69 276 -fill $color -tags {floor3 wall}\n    $w create line 69 262 69 226 -fill $color -tags {floor3 wall}\n    $w create line 21 228 69 228 -fill $color -tags {floor3 wall}\n    $w create line 21 179 75 179 -fill $color -tags {floor3 wall}\n    $w create line 69 179 69 214 -fill $color -tags {floor3 wall}\n    $w create line 90 220 90 227 -fill $color -tags {floor3 wall}\n    $w create line 90 204 90 202 -fill $color -tags {floor3 wall}\n    $w create line 90 203 100 203 -fill $color -tags {floor3 wall}\n    $w create line 90 187 90 179 -fill $color -tags {floor3 wall}\n    $w create line 90 227 176 227 -fill $color -tags {floor3 wall}\n    $w create line 100 179 100 227 -fill $color -tags {floor3 wall}\n    $w create line 100 179 87 179 -fill $color -tags {floor3 wall}\n    $w create line 96 179 96 129 -fill $color -tags {floor3 wall}\n    $w create line 162 169 96 169 -fill $color -tags {floor3 wall}\n    $w create line 173 169 176 169 -fill $color -tags {floor3 wall}\n    $w create line 182 179 176 179 -fill $color -tags {floor3 wall}\n    $w create line 176 129 176 179 -fill $color -tags {floor3 wall}\n    $w create line 195 179 226 179 -fill $color -tags {floor3 wall}\n    $w create line 224 133 224 179 -fill $color -tags {floor3 wall}\n    $w create line 264 179 264 133 -fill $color -tags {floor3 wall}\n    $w create line 238 179 264 179 -fill $color -tags {floor3 wall}\n    $w create line 273 207 273 193 -fill $color -tags {floor3 wall}\n    $w create line 273 235 273 250 -fill $color -tags {floor3 wall}\n    $w create line 273 224 273 219 -fill $color -tags {floor3 wall}\n    $w create line 273 193 307 193 -fill $color -tags {floor3 wall}\n    $w create line 273 222 307 222 -fill $color -tags {floor3 wall}\n    $w create line 273 250 307 250 -fill $color -tags {floor3 wall}\n    $w create line 384 247 376 247 -fill $color -tags {floor3 wall}\n    $w create line 340 206 307 206 -fill $color -tags {floor3 wall}\n    $w create line 340 187 340 170 -fill $color -tags {floor3 wall}\n    $w create line 340 210 340 201 -fill $color -tags {floor3 wall}\n    $w create line 340 247 340 224 -fill $color -tags {floor3 wall}\n    $w create line 340 241 307 241 -fill $color -tags {floor3 wall}\n    $w create line 376 247 376 170 -fill $color -tags {floor3 wall}\n    $w create line 307 250 307 170 -fill $color -tags {floor3 wall}\n    $w create line 376 170 307 170 -fill $color -tags {floor3 wall}\n    $w create line 315 129 315 170 -fill $color -tags {floor3 wall}\n    $w create line 376 283 366 283 -fill $color -tags {floor3 wall}\n    $w create line 376 283 376 275 -fill $color -tags {floor3 wall}\n    $w create line 399 275 376 275 -fill $color -tags {floor3 wall}\n    $w create line 341 275 320 275 -fill $color -tags {floor3 wall}\n    $w create line 341 283 350 283 -fill $color -tags {floor3 wall}\n    $w create line 298 275 298 329 -fill $color -tags {floor3 wall}\n    $w create line 308 275 298 275 -fill $color -tags {floor3 wall}\n    $w create line 243 322 243 275 -fill $color -tags {floor3 wall}\n    $w create line 243 275 284 275 -fill $color -tags {floor3 wall}\n    $w create line 258 322 226 322 -fill $color -tags {floor3 wall}\n    $w create line 212 370 212 322 -fill $color -tags {floor3 wall}\n    $w create line 214 322 177 322 -fill $color -tags {floor3 wall}\n    $w create line 163 370 163 322 -fill $color -tags {floor3 wall}\n    $w create line 165 322 129 322 -fill $color -tags {floor3 wall}\n    $w create line 84 322 117 322 -fill $color -tags {floor3 wall}\n    $w create line 71 322 64 322 -fill $color -tags {floor3 wall}\n    $w create line 115 322 115 370 -fill $color -tags {floor3 wall}\n    $w create line 66 322 66 370 -fill $color -tags {floor3 wall}\n    $w create line 52 322 21 322 -fill $color -tags {floor3 wall}\n    $w create line 21 331 0 331 -fill $color -tags {floor3 wall}\n    $w create line 21 331 21 133 -fill $color -tags {floor3 wall}\n    $w create line 96 133 21 133 -fill $color -tags {floor3 wall}\n    $w create line 176 129 96 129 -fill $color -tags {floor3 wall}\n    $w create line 315 133 176 133 -fill $color -tags {floor3 wall}\n    $w create line 315 129 399 129 -fill $color -tags {floor3 wall}\n    $w create line 399 311 350 311 -fill $color -tags {floor3 wall}\n    $w create line 350 329 258 329 -fill $color -tags {floor3 wall}\n    $w create line 258 322 258 370 -fill $color -tags {floor3 wall}\n    $w create line 60 370 258 370 -fill $color -tags {floor3 wall}\n    $w create line 60 370 60 391 -fill $color -tags {floor3 wall}\n    $w create line 0 391 0 331 -fill $color -tags {floor3 wall}\n    $w create line 60 391 0 391 -fill $color -tags {floor3 wall}\n    $w create line 307 250 307 242 -fill $color -tags {floor3 wall}\n    $w create line 273 250 307 250 -fill $color -tags {floor3 wall}\n    $w create line 258 250 243 250 -fill $color -tags {floor3 wall}\n}\n\n# Below is the \"main program\" that creates the floorplan demonstration.\n\nset w .floor\nglobal c currentRoom colors activeFloor\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Floorplan Canvas Demonstration\"\nwm iconname $w \"Floorplan\"\nwm geometry $w +20+20\nwm minsize $w 75p 75p\n\nlabel $w.msg -font $font -wraplength 8i -justify left  -text \"This window contains a canvas widget showing the floorplan of Digital Equipment Corporation's Western Research Laboratory.  It has three levels.  At any given time one of the levels is active, meaning that you can see its room structure.  To activate a level, click the left mouse button anywhere on it.  As the mouse moves over the active level, the room under the mouse lights up and its room number appears in the \\\"Room:\\\" entry.  You can also type a room number in the entry and the room will light up.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nset f [frame $w.frame]\npack $f -side top -fill both -expand yes\nset h [ttk::scrollbar $f.hscroll -orient horizontal]\nset v [ttk::scrollbar $f.vscroll -orient vertical]\nset f1 [frame $f.f1 -borderwidth 2 -relief sunken]\nset c [canvas $f1.c -highlightthickness 0 \\\n\t   -xscrollcommand [list $h set] -yscrollcommand [list $v set]]\npack $c -expand yes -fill both\ngrid $f1 -padx 1 -pady 1 -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid $v -padx 1 -pady 1 -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news\ngrid $h -padx 1 -pady 1 -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid rowconfig    $f 0 -weight 1 -minsize 0\ngrid columnconfig $f 0 -weight 1 -minsize 0\npack $f -expand yes -fill both -padx 1 -pady 1\n\n$v configure -command [list $c yview]\n$h configure -command [list $c xview]\n\n# Create an entry for displaying and typing in current room.\n\nentry $c.entry -width 10 -textvariable currentRoom\n\n# Choose colors, then fill in the floorplan.\n\nif {[winfo depth $c] > 1} {\n    set colors(bg1) #a9c1da\n    set colors(outline1) #77889a\n    set colors(bg2) #9ab0c6\n    set colors(outline2) #687786\n    set colors(bg3) #8ba0b3\n    set colors(outline3) #596673\n    set colors(offices) Black\n    set colors(active) #c4d1df\n} else {\n    set colors(bg1) white\n    set colors(outline1) black\n    set colors(bg2) white\n    set colors(outline2) black\n    set colors(bg3) white\n    set colors(outline3) black\n    set colors(offices) Black\n    set colors(active) black\n}\nset activeFloor \"\"\nfloorDisplay $c 3\n\n# Set up event bindings for canvas:\n\n$c bind floor1 <Button-1> \"floorDisplay $c 1\"\n$c bind floor2 <Button-1> \"floorDisplay $c 2\"\n$c bind floor3 <Button-1> \"floorDisplay $c 3\"\n$c bind room <Enter> \"newRoom $c\"\n$c bind room <Leave> {set currentRoom \"\"}\nbind $c <Button-2> \"$c scan mark %x %y\"\nbind $c <B2-Motion> \"$c scan dragto %x %y\"\nbind $c <Destroy> \"unset currentRoom\"\nset currentRoom \"\"\ntrace add variable currentRoom write \"roomChanged $c\"\n"
  },
  {
    "path": "library/demos/fontchoose.tcl",
    "content": "# fontchoose.tcl --\n#\n# Show off the stock font selector dialog\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .fontchoose\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Font Selection Dialog\"\nwm iconname $w \"fontchooser\"\npositionWindow $w\n\ncatch {font create FontchooseDemoFont {*}[font actual TkDefaultFont]}\n\n# The font chooser needs to be configured and then shown.\nproc SelectFont {parent} {\n    tk fontchooser configure -font FontchooseDemoFont \\\n\t-command ApplyFont -parent $parent\n    tk fontchooser show\n}\n\nproc ApplyFont {font} {\n    font configure FontchooseDemoFont {*}[font actual $font]\n}\n\n# When the visibility of the fontchooser changes, the following event is fired\n# to the parent widget.\n#\nbind $w <<TkFontchooserVisibility>> {\n    if {[tk fontchooser configure -visible]} {\n\t%W.f.font state disabled\n    } else {\n\t%W.f.font state !disabled\n    }\n}\n\n\nset f [ttk::frame $w.f -relief sunken -padding 1.5p]\n\ntext $f.msg -font FontchooseDemoFont -width 40 -height 6 -borderwidth 0 \\\n    -yscrollcommand [list $f.vs set]\nttk::scrollbar $f.vs -command [list $f.msg yview]\n\n$f.msg insert end \"Press the buttons below to choose a new font for the\\\n  text shown in this window.\\n\" {}\n\nttk::button $f.font -text \"Set font ...\" -command [list SelectFont $w]\n\ngrid $f.msg $f.vs -sticky news\ngrid $f.font -    -sticky e\ngrid columnconfigure $f 0 -weight 1\ngrid rowconfigure $f 0 -weight 1\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\n\ngrid $f -sticky news\ngrid $btns -sticky ew\ngrid columnconfigure $w 0 -weight 1\ngrid rowconfigure $w 0 -weight 1\nupdate idletasks\ngrid propagate $f 0\n"
  },
  {
    "path": "library/demos/form.tcl",
    "content": "# form.tcl --\n#\n# This demonstration script creates a simple form with a bunch\n# of entry widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .form\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Form Demonstration\"\nwm iconname $w \"form\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This window contains a simple form where you can type in the various entries and use tabs to move circularly between the entries.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nforeach i {f1 f2 f3 f4 f5} {\n    frame $w.$i -bd 2\n    entry $w.$i.entry -relief sunken -width 40\n    label $w.$i.label\n    pack $w.$i.entry -side right\n    pack $w.$i.label -side left\n}\n$w.f1.label config -text Name:\n$w.f2.label config -text Address:\n$w.f5.label config -text Phone:\npack $w.msg $w.f1 $w.f2 $w.f3 $w.f4 $w.f5 -side top -fill x\nbind $w <Return> \"destroy $w\"\nfocus $w.f1.entry\n"
  },
  {
    "path": "library/demos/goldberg.tcl",
    "content": "##+#################################################################\n#\n# TkGoldberg.tcl\n# by Keith Vetter, March 13, 2003\n#\n# \"Man will always find a difficult means to perform a simple task\"\n# Rube Goldberg\n#\n# Reproduced here with permission.\n#\n##+#################################################################\n#\n# Keith Vetter 2003-03-21: this started out as a simple little program\n# but was so much fun that it grew and grew. So I apologize about the\n# size but I just couldn't resist sharing it.\n#\n# This is a whizzlet that does a Rube Goldberg type animation, the\n# design of which comes from an New Years e-card from IncrediMail.\n# That version had nice sound effects which I eschewed. On the other\n# hand, that version was in black and white (actually dark blue and\n# light blue) and this one is fully colorized.\n#\n# One thing I learned from this project is that drawing filled complex\n# objects on a canvas is really hard. More often than not I had to\n# draw each item twice--once with the desired fill color but no\n# outline, and once with no fill but with the outline. Another trick\n# is erasing by drawing with the background color. Having a flood fill\n# command would have been extremely helpful.\n#\n# Two wiki pages were extremely helpful: Drawing rounded rectangles\n# which I generalized into Drawing rounded polygons, and regular\n# polygons which allowed me to convert ovals and arcs into polygons\n# which could then be rotated (see Canvas Rotation). I also wrote\n# Named Colors to aid in the color selection.\n#\n# I could comment on the code, but it's just 26 state machines with\n# lots of canvas create and move calls.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .goldberg\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Tk Goldberg (demonstration)\"\nwm iconname $w \"goldberg\"\nwm resizable $w 0 0\n#positionWindow $w\n\nproc StartMessage {w} {\n    set msg1 \"This\\\n\t    is a demonstration of just how complex you can make your animations\\\n\t    become. Close this dialog and click the ball to start things\\\n\t    moving!\\n\\n\\\"Man will always find a difficult means to perform a\\\n\t    simple task\\\"\\n - Rube Goldberg\"\n    PlacedDialog $w.c.messframe $msg1 {Helvetica 12}\n}\n###--- End of Boilerplate ---###\n\narray set BaseDimensions {\n    CanX    675\n    CanY    540\n    ScrX    750\n    ScrY    750\n    MsgX    338\n    MsgY    573\n    MovX     10\n    MovY    -45\n}\n\n# The original value was 1.0 but this can make the demo\n# too large for the screen.  Try a smaller value.\nset overallFactor 0.75\n\nforeach el [array names BaseDimensions] {\n    set Dims($el) [expr {$BaseDimensions($el) * $overallFactor}]p\n}\n\nset scaleFactor [expr {$::tk::scalingPct / 100.0 * $overallFactor}]\n\n# Ensure that this is an array\narray set animationCallbacks {}\nbind $w <Destroy> {\n    if {\"%W\" eq [winfo toplevel %W]} {\n\tunset S C delays\n    }\n}\n\nset S(title) \"Tk Goldberg\"\nset S(speed) 5\nset S(cnt) 0\nset S(message) \"\\\\nWelcome\\\\nto\\\\nTcl/Tk!\"\narray set delays \\\n\t{1 500  2 400  3 300  4 200  5 150  6 100  7 80  8 50  9 20  10 10}\n\nset MSTART 0; set MGO 1; set MPAUSE 2; set MSSTEP 3; set MBSTEP 4; set MDONE 5\nset S(mode) $::MSTART\n\n# Colors for everything\nset C(fg) black\nset C(bg) cornflowerblue\n\nset C(0) white;\t\tset C(1a) darkgreen;\tset C(1b) yellow\nset C(2) red;\t\tset C(3a) green;\tset C(3b) darkblue\nset C(4) $C(fg);\tset C(5a) brown;\tset C(5b) white\nset C(6) magenta;\tset C(7) green;\t\tset C(8) $C(fg)\nset C(9) blue4;\t\tset C(10a) white;\tset C(10b) cyan\nset C(11a) yellow;\tset C(11b) mediumblue;\tset C(12) tan2\nset C(13a) yellow;\tset C(13b) red;\t\tset C(14) white\nset C(15a) green;\tset C(15b) yellow;\tset C(16) gray65\nset C(17) \\#A65353;\tset C(18) $C(fg);\tset C(19) gray50\nset C(20) cyan;\t\tset C(21) gray65;\tset C(22) $C(20)\nset C(23a) blue;\tset C(23b) red;\t\tset C(23c) yellow\nset C(24a) red;\t\tset C(24b) white;\nset C(24c) black;\tset C(26) $C(0);\n\nproc DoDisplay {w} {\n    global S C Dims\n\n    ttk::frame $w.ctrl -relief ridge -borderwidth 1 -padding 3p\n    pack [frame $w.screen -bd 1 -relief raised] \\\n\t    -side left -fill both -expand 1\n\n    canvas $w.c -width $Dims(CanX) -height $Dims(CanY) -bg $C(bg) \\\n\t    -highlightthickness 0\n    $w.c config -scrollregion [list 0 0 $Dims(ScrX) $Dims(ScrY)]\n    $w.c yview moveto .06\t\t\t;# Kludge: move everything up\n    pack $w.c -in $w.screen -side top -fill both -expand 1\n\n    bind $w.c <Configure> { %W yview moveto .06 }\n    bind $w.c <Button-3> [list $w.pause invoke]\n    bind $w.c <Destroy> {\n\tafter cancel $animationCallbacks(goldberg)\n\tunset animationCallbacks(goldberg)\n    }\n    DoCtrlFrame $w\n    DoDetailFrame $w\n    if {[tk windowingsystem] ne \"aqua\"} {\n\tttk::button $w.show -text \"▶\" -command [list ShowCtrl $w] -width 2\n    } else {\n\tbutton $w.show -text \"▶\" -command [list ShowCtrl $w] -width 1 \\\n\t\t-borderwidth 1 -highlightthickness 0 -padx 0 -pady 0 \\\n\t\t-highlightbackground $C(bg)\n    }\n    place $w.show -in $w.c -relx 1 -rely 0 -anchor ne\n    update\n}\n\nproc DoCtrlFrame {w} {\n    global S\n    ttk::button $w.start -text \"Start\" -command [list DoButton $w 0]\n    ttk::checkbutton $w.pause -text \"Pause\" -command [list DoButton $w 1] \\\n\t    -variable S(pause)\n    ttk::button $w.step -text \"Single Step\" -command [list DoButton $w 2]\n    ttk::button $w.bstep -text \"Big Step\" -command [list DoButton $w 4]\n    ttk::button $w.reset -text \"Reset\" -command [list DoButton $w 3]\n    ttk::labelframe $w.details\n    raise $w.details\n    set S(details) 0\n    ttk::checkbutton $w.details.cb -text \"Details\" -variable S(details)\n    ttk::labelframe $w.message -text \"Message\"\n    ttk::entry $w.message.e -textvariable S(message) -justify center\n    ttk::labelframe $w.speed -text \"Speed: 0\"\n    ttk::scale $w.speed.scale -orient horizontal -from 1 -to 10 \\\n\t    -variable S(speed)\n    ttk::button $w.about -text About -command [list About $w]\n\n    grid $w.start -in $w.ctrl -row 0 -sticky ew\n    grid rowconfigure $w.ctrl 1 -minsize 3p\n    grid $w.pause -in $w.ctrl -row 2 -sticky ew\n    grid $w.step  -in $w.ctrl -sticky ew -pady 1.5p\n    grid $w.bstep -in $w.ctrl -sticky ew\n    grid $w.reset -in $w.ctrl -sticky ew -pady 1.5p\n    grid rowconfigure $w.ctrl 10 -minsize 3p\n    grid $w.details -in $w.ctrl -row 11 -sticky ew\n    grid rowconfigure $w.ctrl 11 -minsize 3p\n    $w.details configure -labelwidget $w.details.cb\n    grid [ttk::frame $w.details.b -height 1]\t;# Work around minor bug\n    raise $w.details\n    raise $w.details.cb\n    grid rowconfigure $w.ctrl 50 -weight 1\n    trace add variable ::S(mode) write\t  [list ActiveGUI $w]\n    trace add variable ::S(details) write [list ActiveGUI $w]\n    trace add variable ::S(speed) write\t  [list ActiveGUI $w]\n\n    grid $w.message -in $w.ctrl -row 98 -sticky ew -pady {0 3p}\n    grid $w.message.e -sticky nsew\n    grid $w.speed -in $w.ctrl -row 99 -sticky ew -pady {0 3p}\n    pack $w.speed.scale -fill both -expand 1\n    grid $w.about -in $w.ctrl -row 100 -sticky ew\n    bind $w.reset <Button-3> {set S(mode) -1}\t\t;# Debugging\n\n    ## See Code / Dismiss buttons hack!\n    grid [ttk::separator $w.ctrl.sep] -sticky ew -pady {3p 1.5p}\n    set btns {}\n    foreach b [winfo children [addSeeDismiss $w.ctrl.buttons $w]] {\n\tif {[winfo class $b] eq \"TButton\"} {\n\t    set btns [linsert $btns 0 $b]\t\t;# Prepend\n\t}\n    }\n    set i 0\n    foreach b $btns {\n\tgrid [set b2 [ttk::button $w.ctrl.b[incr i]]] -sticky ew -pady {1.5p 0}\n\tforeach b3 [$b configure] {\n\t    set b3 [lindex $b3 0]\n\t    # Some options are read-only; ignore those errors\n\t    catch {$b2 configure $b3 [$b cget $b3]}\n\t}\n    }\n    destroy $btns\n}\n\nproc DoDetailFrame {w} {\n    set w2 $w.details.f\n    ttk::frame $w2\n\n    ttk::label $w2.l -textvariable S(cnt) -background white\n    grid $w2.l - - - -sticky ew -row 0\n    for {set i 1} {1} {incr i} {\n\tif {[info procs \"Move$i\"] eq \"\"} break\n\tttk::label $w2.l$i -text $i -anchor e -width 2 -background white\n\tttk::label $w2.ll$i -textvariable STEP($i) -width 5 -background white\n\tset row [expr {($i + 1) / 2}]\n\tset col [expr {(($i + 1) & 1) * 2}]\n\tgrid $w2.l$i -sticky ew -row $row -column $col\n\tgrid $w2.ll$i -sticky ew -row $row -column [incr col]\n    }\n    grid columnconfigure $w2 1 -weight 1\n}\n\n# Map or unmap the ctrl window\nproc ShowCtrl {w} {\n    if {[winfo ismapped $w.ctrl]} {\n\tpack forget $w.ctrl\n\t$w.show config -text \"▶\"\n    } else {\n\tpack $w.ctrl -side right -fill both -ipady 5\n\t$w.show config -text \"◀\"\n    }\n}\n\nproc DrawAll {w} {\n    global scaleFactor\n    ResetStep\n    $w.c delete all\n    for {set i 0} {1} {incr i} {\n\tset p \"Draw$i\"\n\tif {[info procs $p] eq \"\"} break\n\t$p $w\n    }\n\n    $w.c scale all 0 0 $scaleFactor $scaleFactor\n\n    # Tile the strike box with a 4x4 bitmap image derived\n    # from Tk's built-in 16x16 bitmap gray25.  Adjust\n    # x1, y2 to make dimensions multiples of 4 pixels.\n\n    image create bitmap smallGray25 -data {\n\t#define smallGray25_width 4\n\t#define smallGray25_height 4\n\tstatic unsigned char smallGray25_bits[] = {\n\t    0x08, 0x02, 0x08, 0x02};\n    } -foreground $::C(fg)\n\n    lassign [$w.c coords StrikeBox] x1 y1 x2 y2\n    set oldMidY [expr {round(($y1 + $y2) / 2.0)}]\n\n    set rowCount [expr {round(($y2 - $y1) / 4.0)}]\n    set colCount [expr {round(($x2 - $x1) / 4.0)}]\n    set x2 [expr {round($x2)}]\n    set x1 [expr {$x2 - $colCount * 4}]\n    set y1 [expr {round($y1)}]\n    set y2 [expr {$y1 + $rowCount * 4}]\n\n    set newMidY [expr {round(($y1 + $y2) / 2.0)}]\n    set deltaY [expr {$oldMidY - $newMidY}]\n    incr y1 $deltaY; incr y2 $deltaY\n    $w.c coords StrikeBox $x1 $y1 $x2 $y2\n\n    for {set row 0; set y $y1} {$row < $rowCount} {incr row; incr y 4} {\n\tfor {set col 0; set x $x1} {$col < $colCount} {incr col; incr x 4} {\n\t    $w.c create image $x $y -image smallGray25 -anchor nw\n\t}\n    }\n}\n\nproc ActiveGUI {w var1 var2 op} {\n    global S MGO MSTART MDONE\n    array set z {0 disabled 1 normal}\n\n    set m $S(mode)\n    set S(pause) [expr {$m == 2}]\n    $w.start  config -state $z([expr {$m != $MGO}])\n    $w.pause  config -state $z([expr {$m != $MSTART && $m != $MDONE}])\n    $w.step   config -state $z([expr {$m != $MGO && $m != $MDONE}])\n    $w.bstep  config -state $z([expr {$m != $MGO && $m != $MDONE}])\n    $w.reset  config -state $z([expr {$m != $MSTART}])\n\n    if {$S(details)} {\n\tgrid $w.details.f -sticky ew\n    } else {\n\tgrid forget $w.details.f\n    }\n    set S(speed) [expr {round($S(speed))}]\n    $w.speed config -text \"Speed: $S(speed)\"\n}\n\nproc Start {} {\n    global S MGO\n    set S(mode) $MGO\n}\n\nproc DoButton {w what} {\n    global S MDONE MGO MSSTEP MBSTEP MPAUSE\n\n    if {$what == 0} {\t\t\t\t;# Start\n\tif {$S(mode) == $MDONE} {\n\t    Reset $w\n\t}\n\tset S(mode) $MGO\n    } elseif {$what == 1} {\t\t\t;# Pause\n\tset S(mode) [expr {$S(pause) ? $MPAUSE : $MGO}]\n    } elseif {$what == 2} {\t\t\t;# Step\n\tset S(mode) $MSSTEP\n    } elseif {$what == 3} {\t\t\t;# Reset\n\tReset $w\n    } elseif {$what == 4} {\t\t\t;# Big step\n\tset S(mode) $MBSTEP\n    }\n}\n\nproc Go {w {who {}}} {\n    global S delays animationCallbacks MGO MPAUSE MSSTEP MBSTEP\n\n    set now [clock clicks -milliseconds]\n    catch {after cancel $animationCallbacks(goldberg)}\n    if {$who ne \"\"} {\t\t\t\t;# Start here for debugging\n\tset S(active) $who\n\tset S(mode) $MGO\n    }\n    if {$S(mode) == -1} return\t\t\t;# Debugging\n    set n 0\n    if {$S(mode) != $MPAUSE} {\t\t\t;# Not paused\n\tset n [NextStep $w]\t\t\t;# Do the next move\n    }\n    if {$S(mode) == $MSSTEP} {\t\t\t;# Single step\n\tset S(mode) $MPAUSE\n    }\n    if {$S(mode) == $MBSTEP && $n} {\t\t;# Big step\n\tset S(mode) $MSSTEP\n    }\n\n    set elapsed [expr {[clock click -milliseconds] - $now}]\n    set delay [expr {$delays($S(speed)) - $elapsed}]\n    if {$delay <= 0} {\n\tset delay 1\n    }\n    set animationCallbacks(goldberg) [after $delay [list Go $w]]\n}\n\n# NextStep: drives the next step of the animation\nproc NextStep {w} {\n    global S MSTART MDONE\n    set rval 0\t\t\t\t\t;# Return value\n\n    if {$S(mode) != $MSTART && $S(mode) != $MDONE} {\n\tincr S(cnt)\n    }\n    set alive {}\n    foreach {who} $S(active) {\n\tset n [\"Move$who\" $w]\n\tif {$n & 1} {\t\t\t\t;# This guy still alive\n\t    lappend alive $who\n\t}\n\tif {$n & 2} {\t\t\t\t;# Next guy is active\n\t    lappend alive [expr {$who + 1}]\n\t    set rval 1\n\t}\n\tif {$n & 4} {\t\t\t\t;# End of puzzle flag\n\t    set S(mode) $MDONE\t\t\t;# Done mode\n\t    set S(active) {}\t\t\t;# No more animation\n\t    return 1\n\t}\n    }\n    set S(active) $alive\n    return $rval\n}\n\nproc About {w} {\n    set msg \"$::S(title)\\nby Keith Vetter, March 2003\\n(Reproduced by kind\\\n\t    permission of the author)\\n\\n\\\"Man will always find a difficult\\\n\t    means to perform a simple task.\\\"\\n - Rube Goldberg\"\n    PlacedDialog $w.c.messframe $msg {Helvetica 12 bold}\n    return\n}\n################################################################\n#\n# All the drawing and moving routines\n#\n\n# START HERE! banner\nproc Draw0 {w} {\n    set color $::C(0)\n    set xy {699 119}\n    $w.c create text $xy -text \"START HERE!\" -fill $color -anchor e \\\n\t    -tag {I0 I0_0} -font {Times 12 italic bold}\n    set xy {719 119 763 119}\n    $w.c create line $xy -tag {I0 I0_1} -fill $color -width 3.75p -arrow last \\\n\t    -arrowshape {13.5p 13.5p 3.75p}\n    $w.c bind I0 <Button-1> Start\n}\nproc Move0 {w {step {}}} {\n    set step [GetStep 0 $step]\n\n    if {$::S(mode) > $::MSTART} {\t\t;# Start the ball rolling\n\tMoveAbs $w I0 {-100 -100}\t\t;# Hide the banner\n\treturn 2\n    }\n\n    set pos [scl {\n\t{719 119} {724 119} {729 119} {734 119}\n\t{739 119} {734 119} {729 119} {724 119}\n    }]\n    set step [expr {$step % [llength $pos]}]\n    lassign [lindex $pos $step] x y\n    $w.c coords I0_0 [expr {$x - [scl 20]}] $y\n    $w.c coords I0_1 $x $y [expr {$x + [scl 44]}] $y\n    return 1\n}\n\n# Dropping ball\nproc Draw1 {w} {\n    set color $::C(1a)\n    set color2 $::C(1b)\n    set xy {844 133 800 133 800 346 820 346 820 168 844 168 844 133}\n    $w.c create poly $xy -width 2.25p -fill $color -outline {}\n    set xy {771 133 685 133 685 168 751 168 751 346 771 346 771 133}\n    $w.c create poly $xy -width 2.25p -fill $color -outline {}\n\n    set xy [box 812 122 9]\n    $w.c create oval $xy -tag I1 -fill $color2 -outline {}\n    $w.c bind I1 <Button-1> Start\n}\nproc Move1 {w {step {}}} {\n    set step [GetStep 1 $step]\n    set pos [scl {\n\t{807 122} {802 122} {797 123} {793 124} {789 129} {785 153}\n\t{785 203} {785 278 x} {785 367} {810 392} {816 438} {821 503}\n\t{824 585 y} {838 587} {848 593} {857 601} {-100 -100}\n    }]\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n    set where [lindex $pos $step]\n    MoveAbs $w I1 $where\n\n    if {[lindex $where 2] eq \"y\"} {\n\tMove15a $w\n    }\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Lighting the match\nproc Draw2 {w} {\n    set color red\n    set color $::C(2)\n    set xy  {750 369 740 392 760 392}\t\t;# Fulcrum\n    $w.c create poly $xy -fill $::C(fg) -outline $::C(fg)\n    set xy {628 335 660 383}\t\t\t;# Strike box\n    $w.c create rect $xy -fill {} -outline $::C(fg) -tag StrikeBox\n\n    set xy {702 366 798 366}\t\t\t;# Lever\n    $w.c create line $xy -fill $::C(fg) -width 5.25p -tag I2_0\n    set xy {712 363 712 355}\t\t\t;# R strap\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I2_1\n    set xy {705 363 705 355}\t\t\t;# L strap\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I2_2\n    set xy {679 356 679 360 717 360 717 356 679 356}\t;# Match stick\n    $w.c create line $xy -fill $::C(fg) -tag I2_3\n\n    #set xy {662 352 680 365}\t\t\t;# Match head\n    set xy {\n\t671 352 677.4 353.9 680 358.5 677.4 363.1 671 365 664.6 363.1\n\t662 358.5 664.6 353.9\n    }\n    $w.c create poly $xy -fill $color -outline $color -tag I2_4\n}\nproc Move2 {w {step {}}} {\n    set step [GetStep 2 $step]\n\n    set stages {0 0 1 2 0 2 1 0 1 2 0 2 1}\n    set xy(0) [scl {\n\t686 333 692 323 682 316 674 309 671 295 668 307 662 318 662 328\n\t671 336\n    }]\n    set xy(1) [scl {\n\t687 331 698 322 703 295 680 320 668 297 663 311 661 327 671 335}]\n    set xy(2) [scl {\n\t686 331 704 322 688 300 678 283 678 283 674 298 666 309 660 324\n\t672 336\n    }]\n\n    if {$step >= [llength $stages]} {\n\t$w.c delete I2\n\treturn 0\n    }\n\n    if {$step == 0} {\t\t\t\t;# Rotate the match\n\tset beta 20\n\tlassign [Anchor $w I2_0 s] Ox Oy\t;# Where to pivot\n\tfor {set i 0} {[$w.c find withtag I2_$i] ne \"\"} {incr i} {\n\t    RotateItem $w I2_$i $Ox $Oy $beta\n\t}\n\t$w.c create poly -tag I2 -smooth 1 -fill $::C(2) ;# For the flame\n\treturn 1\n    }\n    $w.c coords I2 $xy([lindex $stages $step])\n    return [expr {$step == 7 ? 3 : 1}]\n}\n\n# Weight and pulleys\nproc Draw3 {w} {\n    set color $::C(3a)\n    set color2 $::C(3b)\n\n    set xy {602 296 577 174 518 174}\n    foreach {x y} $xy {\t\t\t\t;# 3 Pulleys\n\t$w.c create oval [box $x $y 13] -fill $color -outline $::C(fg) \\\n\t\t-width 2.25p\n\t$w.c create oval [box $x $y 2] -fill $::C(fg) -outline $::C(fg)\n    }\n\n    set xy {750 309 670 309}\t\t\t;# Wall to flame\n    $w.c create line $xy -tag I3_s -width 2.25p -fill $::C(fg) -smooth 1\n    set xy {670 309 650 309}\t\t\t;# Flame to pulley 1\n    $w.c create line $xy -tag I3_0 -width 2.25p -fill $::C(fg)\n    set xy {650 309 600 309}\t\t\t;# Flame to pulley 1\n    $w.c create line $xy -tag I3_1 -width 2.25p -fill $::C(fg)\n    set xy {589 296 589 235}\t\t\t;# Pulley 1 half way to 2\n    $w.c create line $xy -tag I3_2 -width 2.25p -fill $::C(fg)\n    set xy {589 235 589 174}\t\t\t;# Pulley 1 other half to 2\n    $w.c create line $xy -width 2.25p -fill $::C(fg)\n    set xy {577 161 518 161}\t\t\t;# Across the top\n    $w.c create line $xy -width 2.25p -fill $::C(fg)\n    set xy {505 174 505 205}\t\t\t;# Down to weight\n    $w.c create line $xy -tag I3_w -width 2.25p -fill $::C(fg)\n\n    # Draw the weight as 2 circles, two rectangles and 1 rounded rectangle\n    set xy {515 207 495 207}\n    foreach {x1 y1 x2 y2} $xy {\n\t$w.c create oval [box $x1 $y1 6] -tag I3_ -fill $color2 \\\n\t\t-outline $color2\n\t$w.c create oval [box $x2 $y2 6] -tag I3_ -fill $color2 \\\n\t\t-outline $color2\n\tincr y1 -6; incr y2 6\n\t$w.c create rect $x1 $y1 $x2 $y2 -tag I3_ -fill $color2 \\\n\t\t-outline $color2\n    }\n    set xy {492 220 518 263}\n    set xy [RoundRect $w $xy 15]\n    $w.c create poly $xy -smooth 1 -tag I3_ -fill $color2 -outline $color2\n    set xy {500 217 511 217}\n    $w.c create line $xy -tag I3_ -fill $color2 -width 7.5p\n\n    set xy {502 393 522 393 522 465}\t\t;# Bottom weight target\n    $w.c create line $xy -tag I3__ -fill $::C(fg) -join miter -width 7.5p\n}\nproc Move3 {w {step {}}} {\n    set step [GetStep 3 $step]\n\n    set pos [scl {{505 247} {505 297} {505 386.5} {505 386.5}}]\n    set rope(0) [scl {750 309 729 301 711 324 690 300}]\n    set rope(1) [scl {750 309 737 292 736 335 717 315 712 320}]\n    set rope(2) [scl {750 309 737 309 740 343 736 351 725 340}]\n    set rope(3) [scl {750 309 738 321 746 345 742 356}]\n\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n\n    $w.c delete \"I3_$step\"\t\t\t;# Delete part of the rope\n    MoveAbs $w I3_ [lindex $pos $step]\t\t;# Move weight down\n    $w.c coords I3_s $rope($step)\t\t;# Flapping rope end\n    $w.c coords I3_w [concat [scl {505 174}] [lindex $pos $step]]\n    if {$step == 2} {\n\t$w.c move I3__ 0 30\n\treturn 2\n    }\n    return 1\n}\n\n# Cage and door\nproc Draw4 {w} {\n    set color $::C(4)\n    lassign {527 356 611 464} x0 y0 x1 y1\n\n    for {set y $y0} {$y <= $y1} {incr y 12} {\t;# Horizontal bars\n\t$w.c create line $x0 $y $x1 $y -fill $color -width 0.75p\n    }\n    for {set x $x0} {$x <= $x1} {incr x 12} {\t;# Vertical bars\n\t$w.c create line $x $y0 $x $y1 -fill $color -width 0.75p\n    }\n\n    set xy {518 464 518 428}\t\t\t;# Swing gate\n    $w.c create line $xy -tag I4 -fill $color -width 2.25p\n}\nproc Move4 {w {step {}}} {\n    set step [GetStep 4 $step]\n\n    set angles {-10 -20 -30 -30}\n    if {$step >= [llength $angles]} {\n\treturn 0\n    }\n    RotateItem $w I4 [scl 518] [scl 464] [lindex $angles $step]\n    $w.c raise I4\n    return [expr {$step == 3 ? 3 : 1}]\n}\n\n# Mouse\nproc Draw5 {w} {\n    set color $::C(5a)\n    set color2 $::C(5b)\n    set xy {377 248 410 248 410 465 518 465}\t;# Mouse course\n    lappend xy 518 428 451 428 451 212 377 212\n    $w.c create poly $xy -fill $color2 -outline $::C(fg) -width 2.25p\n\n    set xy {\n\t534.5 445.5 541 440 552 436 560 436 569 440 574 446 575 452 574 454\n\t566 456 554 456 545 456 537 454 530 452\n    }\n    $w.c create poly $xy -tag {I5 I5_0} -fill $color\n    set xy {573 452 592 458 601 460 613 456}\t;# Tail\n    $w.c create line $xy -tag {I5 I5_1} -fill $color -smooth 1 -width 2.25p\n    set xy [box 540 446 2]\t\t\t;# Eye\n    set xy {540 444 541 445 541 447 540 448 538 447 538 445}\n    #.c create oval $xy -tag {I5 I5_2} -fill $::C(bg) -outline {}\n    $w.c create poly $xy -tag {I5 I5_2} -fill $::C(bg) -outline {} -smooth 1\n    set xy {538 454 535 461}\t\t\t;# Front leg\n    $w.c create line $xy -tag {I5 I5_3} -fill $color -width 1.5p\n    set xy {566 455 569 462}\t\t\t;# Back leg\n    $w.c create line $xy -tag {I5 I5_4} -fill $color -width 1.5p\n    set xy {544 455 545 460}\t\t\t;# 2nd front leg\n    $w.c create line $xy -tag {I5 I5_5} -fill $color -width 1.5p\n    set xy {560 455 558 460}\t\t\t;# 2nd back leg\n    $w.c create line $xy -tag {I5 I5_6}\t -fill $color -width 1.5p\n}\nproc Move5 {w {step {}}} {\n    set step [GetStep 5 $step]\n\n    set pos [scl {\n\t{553 452} {533 452} {513 452} {493 452} {473 452}\n\t{463 442 30} {445.5 441.5 30} {425.5 434.5 30} {422 414} {422 394}\n\t{422 374} {422 354} {422 334} {422 314} {422 294}\n\t{422 274 -30} {422 260.5 -30 x} {422.5 248.5 -28} {425 237}\n    }]\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n\n    lassign [lindex $pos $step] x y beta next\n    MoveAbs $w I5 [list $x $y]\n    if {$beta ne \"\"} {\n\tlassign [Centroid $w I5_0] Ox Oy\n\tforeach id {0 1 2 3 4 5 6} {\n\t    RotateItem $w I5_$id $Ox $Oy $beta\n\t}\n    }\n    if {$next eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Dropping gumballs\narray set XY6 {\n    -1 {366 207} -2 {349 204} -3 {359 193} -4 {375 192} -5 {340 190}\n    -6 {349 177} -7 {366 177} -8 {380 176} -9 {332 172} -10 {342 161}\n    -11 {357 164} -12 {372 163} -13 {381 149} -14 {364 151} -15 {349 146}\n    -16 {333 148} 0 {357 219}\n    1 {359 261} 2 {359 291} 3 {359 318}\t 4 {361 324}  5 {365 329}  6 {367 334}\n    7 {367 340} 8 {366 346} 9 {364 350} 10 {361 355} 11 {359 370} 12 {359 391}\n    13,0 {360 456}  13,1 {376 456}  13,2 {346 456}  13,3 {330 456}\n    13,4 {353 444}  13,5 {368 443}  13,6 {339 442}  13,7 {359 431}\n    13,8 {380 437}  13,9 {345 428}  13,10 {328 434} 13,11 {373 424}\n    13,12 {331 420} 13,13 {360 417} 13,14 {345 412} 13,15 {376 410}\n    13,16 {360 403}\n}\nproc Draw6 {w} {\n    set color $::C(6)\n    set xy {324 130 391 204}\t\t\t;# Ball holder\n    set xy [RoundRect $w $xy 10]\n    $w.c create poly $xy -smooth 1 -outline $::C(fg) -width 2.25p -fill $color\n    set xy {339 204 376 253}\t\t\t;# Below the ball holder\n    $w.c create rect $xy -fill {} -outline $::C(fg) -width 2.25p -fill $color \\\n\t    -tag I6c\n    set xy [box 346 339 28]\n    $w.c create oval $xy -fill $color -outline {}\t;# Rotor\n    $w.c create arc $xy -outline $::C(fg) -width 1.5p -style arc \\\n\t    -start 80 -extent 205\n    $w.c create arc $xy -outline $::C(fg) -width 1.5p -style arc \\\n\t    -start -41 -extent 85\n\n    set xy [box 346 339 15]\t\t\t;# Center of rotor\n    $w.c create oval $xy -outline $::C(fg) -fill $::C(fg) -tag I6m\n    set xy {352 312 352 254 368 254 368 322}\t;# Top drop to rotor\n    $w.c create poly $xy -fill $color -outline {}\n    $w.c create line $xy -fill $::C(fg) -width 1.5p\n\n    set xy {353 240 367 300}\t\t\t;# Poke bottom hole\n    $w.c create rect $xy -fill $color -outline {}\n    set xy {341 190 375 210}\t\t\t;# Poke another hole\n    $w.c create rect $xy -fill $color -outline {}\n\n    set xy {368 356 368 403 389 403 389 464 320 464 320 403 352 403 352 366}\n    $w.c create poly $xy -fill $color -outline {} -width 1.5p\t;# Below rotor\n    $w.c create line $xy -fill $::C(fg) -width 1.5p\n    set xy [box 275 342 7]\t\t\t;# On/off rotor\n    $w.c create oval $xy -outline $::C(fg) -fill $::C(fg)\n    set xy {276 334 342 325}\t\t\t;# Fan belt top\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n    set xy {276 349 342 353}\t\t\t;# Fan belt bottom\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n\n    set xy {337 212 337 247}\t\t\t;# What the mouse pushes\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I6_\n    set xy {392 212 392 247}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I6_\n    set xy {337 230 392 230}\n    $w.c create line $xy -fill $::C(fg) -width 5.25p -tag I6_\n\n    set who -1\t\t\t\t\t;# All the balls\n    set colors {red cyan orange green blue darkblue}\n    lappend colors {*}$colors {*}$colors\n\n    for {set i 0} {$i < 17} {incr i} {\n\tset loc [expr {-1 * $i}]\n\tset color [lindex $colors $i]\n\t$w.c create oval [box {*}$::XY6($loc) 5] -fill $color \\\n\t\t-outline $color -tag I6_b$i\n    }\n    Draw6a $w 12\t\t\t\t;# The wheel\n}\nproc Draw6a {w beta {scale 0}} {\n    $w.c delete I6_0\n    if {$scale} {\n\tlassign [scl {346 339}] Ox Oy\n    } else {\n\tlassign {346 339} Ox Oy\n    }\n    for {set i 0} {$i < 4} {incr i} {\n\tset b [expr {$beta + $i * 45}]\n\tif {$scale} {\n\t    lassign [RotateC [scl 28] 0 0 0 $b] x y\n\t} else {\n\t    lassign [RotateC 28 0 0 0 $b] x y\n\t}\n\tset xy [list [expr {$Ox+$x}] [expr {$Oy+$y}] \\\n\t\t[expr {$Ox-$x}] [expr {$Oy-$y}]]\n\t$w.c create line $xy -tag I6_0 -fill $::C(fg) -width 1.5p\n    }\n}\nproc Move6 {w {step {}}} {\n    set step [GetStep 6 $step]\n    if {$step > 62} {\n\treturn 0\n    }\n\n    if {$step < 2} {\t\t\t\t;# Open gate for balls to drop\n\t$w.c move I6_ -5.25p 0\n\tif {$step == 1} {\t\t\t;# Poke a hole\n\t    set xy [scl {348 226 365 240}]\n\t    $w.c create rect $xy -fill [$w.c itemcget I6c -fill] -outline {}\n\t}\n\treturn 1\n    }\n\n    set s [expr {$step - 1}]\t\t\t;# Do the gumball drop dance\n    for {set i 0} {$i <= int(($s-1) / 3)} {incr i} {\n\tset tag \"I6_b$i\"\n\tif {[$w.c find withtag $tag] eq \"\"} break\n\tset loc [expr {$s - 3 * $i}]\n\n\tif {[info exists ::XY6($loc,$i)]} {\n\t    MoveAbs $w $tag [scl $::XY6($loc,$i)]\n\t} elseif {[info exists ::XY6($loc)]} {\n\t    MoveAbs $w $tag [scl $::XY6($loc)]\n\t}\n    }\n    if {($s % 3) == 1} {\n\tset first [expr {($s + 2) / 3}]\n\tfor {set i $first} {1} {incr i} {\n\t    set tag \"I6_b$i\"\n\t    if {[$w.c find withtag $tag] eq \"\"} break\n\t    set loc [expr {$first - $i}]\n\t    MoveAbs $w $tag [scl $::XY6($loc)]\n\t}\n    }\n    if {$s >= 3} {\t\t\t\t;# Rotate the motor\n\tset idx [expr {$s % 3}]\n\t#Draw6a $w [lindex {12 35 64} $idx]\n\tDraw6a $w [expr {12 + $s * 15}] 1\n    }\n    return [expr {$s == 3 ? 3 : 1}]\n}\n\n# On/off switch\nproc Draw7 {w} {\n    set color $::C(7)\n    set xy {198 306 277 374}\t\t\t;# Box\n    $w.c create rect $xy -outline $::C(fg) -width 1.5p -fill $color -tag I7z\n    $w.c lower I7z\n    set xy {275 343 230 349}\n    $w.c create line $xy -tag I7 -fill $::C(fg) -arrow last \\\n\t    -arrowshape {17.25p 17.25p 6p} -width 4.5p\n    set xy {225 324}\t\t\t\t;# On button\n    $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)\n    set xy {218 323}\t\t\t\t;# On text\n    set font {Times 8}\n    $w.c create text $xy -text \"on\" -anchor e -fill $::C(fg) -font $font\n    set xy {225 350}\t\t\t\t;# Off button\n    $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)\n    set xy {218 349}\t\t\t\t;# Off button\n    $w.c create text $xy -text \"off\" -anchor e -fill $::C(fg) -font $font\n}\nproc Move7 {w {step {}}} {\n    set step [GetStep 7 $step]\n    set numsteps 30\n    if {$step > $numsteps} {\n\treturn 0\n    }\n    set beta [expr {30.0 / $numsteps}]\n    RotateItem $w I7 [scl 275] [scl 343] $beta\n\n    return [expr {$step == $numsteps ? 3 : 1}]\n}\n\n# Electricity to the fan\nproc Draw8 {w} {\n    Sine $w 271 248 271 306 5 8 -tag I8_s -fill $::C(8) -width 2.25p\n}\nproc Move8 {w {step {}}} {\n    set step [GetStep 8 $step]\n\n    if {$step > 3} {\n\treturn 0\n    }\n    if {$step == 0} {\n\tSparkle $w [Anchor $w I8_s s] I8\n\treturn 1\n\n    } elseif {$step == 1} {\n\tMoveAbs $w I8 [Anchor $w I8_s c]\n    } elseif {$step == 2} {\n\tMoveAbs $w I8 [Anchor $w I8_s n]\n    } else {\n\t$w.c delete I8\n    }\n    return [expr {$step == 2 ? 3 : 1}]\n}\n\n# Fan\nproc Draw9 {w} {\n    set color $::C(9)\n    set xy {266 194 310 220}\n    $w.c create oval $xy -outline $color -fill $color\n    set xy {280 209 296 248}\n    $w.c create oval $xy -outline $color -fill $color\n    set xy {288 249 252 249 260 240 280 234 296 234 316 240 324 249 288 249}\n    $w.c create poly $xy -fill $color -smooth 1\n\n    set xy {248 205 265 214 264 205 265 196}\t;# Spinner\n    $w.c create poly $xy -fill $color\n\n    set xy {255 206 265 234}\t\t\t;# Fan blades\n    $w.c create oval $xy -fill {} -outline $::C(fg) -width 2.25p -tag I9_0\n    set xy {255 176 265 204}\n    $w.c create oval $xy -fill {} -outline $::C(fg) -width 2.25p -tag I9_0\n    set xy {255 206 265 220}\n    $w.c create oval $xy -fill {} -outline $::C(fg) -width 0.75p -tag I9_1\n    set xy {255 190 265 204}\n    $w.c create oval $xy -fill {} -outline $::C(fg) -width 0.75p -tag I9_1\n}\nproc Move9 {w {step {}}} {\n    set step [GetStep 9 $step]\n\n    if {$step & 1} {\n\t$w.c itemconfig I9_0 -width 3p\n\t$w.c itemconfig I9_1 -width 0.75p\n\t$w.c lower I9_1 I9_0\n    } else {\n\t$w.c itemconfig I9_0 -width 0.75p\n\t$w.c itemconfig I9_1 -width 3p\n\t$w.c lower I9_0 I9_1\n    }\n    if {$step == 0} {\n\treturn 3\n    }\n    return 1\n}\n\n# Boat\nproc Draw10 {w} {\n    set color $::C(10a)\n    set color2 $::C(10b)\n    set xy {191 230 233 230 233 178 191 178}\t;# Sail\n    $w.c create poly $xy -fill $color -width 2.25p -outline $::C(fg) -tag I10\n    set xy [box 209 204 31]\t\t\t;# Front\n    $w.c create arc $xy -outline {} -fill $color -style pie \\\n\t    -start 120 -extent 120 -tag I10\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc \\\n\t    -start 120 -extent 120 -tag I10\n    set xy [box 249 204 31]\t\t\t;# Back\n    $w.c create arc $xy -outline {} -fill $::C(bg) -width 2.25p -style pie \\\n\t    -start 120 -extent 120 -tag I10\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc \\\n\t    -start 120 -extent 120 -tag I10\n\n    set xy {200 171 200 249}\t\t\t;# Mast\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I10\n    set xy {159 234 182 234}\t\t\t;# Bow sprit\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I10\n    set xy {180 234 180 251 220 251}\t\t;# Hull\n    $w.c create line $xy -fill $::C(fg) -width 4.5p -tag I10\n\n    set xy {92 255 221 255}\t\t\t;# Waves\n    Sine $w {*}$xy 2 25 -fill $color2 -width 0.75p -tag I10w\n\n    set xy [lrange [$w.c coords I10w] 4 end-4]\t;# Water\n    set xy [concat $xy 222 266 222 277 99 277]\n    $w.c create poly $xy -fill $color2 -outline $color2\n    set xy {222 266 222 277 97 277 97 266}\t;# Water bottom\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n\n    set xy [box 239 262 17]\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc \\\n\t    -start 95 -extent 103\n    set xy [box 76 266 21]\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc -extent 190\n}\nproc Move10 {w {step {}}} {\n    set step [GetStep 10 $step]\n    set pos [scl {\n\t{195 212} {193 212} {190 212} {186 212} {181 212} {176 212}\n\t{171 212} {166 212} {161 212} {156 212} {151 212} {147 212} {142 212}\n\t{137 212} {132 212 x} {127 212} {121 212} {116 212} {111 212}\n    }]\n\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n    set where [lindex $pos $step]\n    MoveAbs $w I10 $where\n\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# 2nd ball drop\nproc Draw11 {w} {\n    set color $::C(11a)\n    set color2 $::C(11b)\n    set xy {23 264 55 591}\t\t\t;# Color the down tube\n    $w.c create rect $xy -fill $color -outline {}\n    set xy [box 71 460 48]\t\t\t;# Color the outer loop\n    $w.c create oval $xy -fill $color -outline {}\n\n    set xy {55 264 55 458}\t\t\t;# Top right side\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n    set xy {55 504 55 591}\t\t\t;# Bottom right side\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n    set xy [box 71 460 48]\t\t\t;# Outer loop\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc \\\n\t    -start 110 -extent -290 -tag I11i\n    set xy [box 71 460 16]\t\t\t;# Inner loop\n    $w.c create oval $xy -outline $::C(fg) -fill {} -width 2.25p -tag I11i\n    $w.c create oval $xy -outline $::C(fg) -fill $::C(bg) -width 2.25p\n\n    set xy {23 264 23 591}\t\t\t;# Left side\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n    set xy [box 1 266 23]\t\t\t;# Top left curve\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc -extent 90\n\n    set xy [box 75 235 9]\t\t\t;# The ball\n    $w.c create oval $xy -fill $color2 -outline {} -width 2.25p -tag I11\n}\nproc Move11 {w {step {}}} {\n    set step [GetStep 11 $step]\n    set pos [scl {\n\t{75 235} {70 235} {65 237} {56 240} {46 247} {38 266} {38 296}\n\t{38 333} {38 399} {38 475} {74 496} {105 472} {100 437} {65 423}\n\t{-100 -100} {38 505} {38 527 x} {38 591}\n    }]\n\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n    set where [lindex $pos $step]\n    MoveAbs $w I11 $where\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Hand\nproc Draw12 {w} {\n    set xy {20 637 20 617 20 610 20 590 40 590 40 590 60 590 60 610 60 610}\n    lappend xy 60 610 65 620 60 631\t\t;# Thumb\n    lappend xy 60 631 60 637 60 662 60 669 52 669 56 669 50 669 50 662 50 637\n\n    set y0 637\t\t\t\t\t;# Bumps for fingers\n    set y1 645\n    for {set x 50} {$x > 20} {incr x -10} {\n\tset x1 [expr {$x - 5}]\n\tset x2 [expr {$x - 10}]\n\tlappend xy $x $y0 $x1 $y1 $x2 $y0\n    }\n    $w.c create poly $xy -fill $::C(12) -outline $::C(fg) -smooth 1 -tag I12 \\\n\t    -width 2.25p\n}\nproc Move12 {w {step {}}} {\n    set step [GetStep 12 $step]\n    set pos [scl {{42 641 x}}]\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n\n    set where [lindex $pos $step]\n    MoveAbs $w I12 $where\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Fax\nproc Draw13 {w} {\n    set color $::C(13a)\n    set xy {86 663 149 663 149 704 50 704 50 681 64 681 86 671}\n    set xy2 {784 663 721 663 721 704 820 704 820 681 806 681 784 671}\n    set radii {2 9 9 8 5 5 2}\n\n    RoundPoly $w.c $xy $radii -width 2.25p -outline $::C(fg) -fill $color\n    RoundPoly $w.c $xy2 $radii -width 2.25p -outline $::C(fg) -fill $color\n\n    set xy {56 677}\n    $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 2.25p \\\n\t    -tag I13\n    set xy {809 677}\n    $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 2.25p \\\n\t    -tag I13R\n\n    set xy {112 687}\t\t\t\t;# Label\n    $w.c create text $xy -text \"FAX\" -fill $::C(fg) -font {Times 12 bold}\n    set xy {762 687}\n    $w.c create text $xy -text \"FAX\" -fill $::C(fg) -font {Times 12 bold}\n\n    set xy {138 663 148 636 178 636}\t\t;# Paper guide\n    $w.c create line $xy -smooth 1 -fill $::C(fg) -width 2.25p\n    set xy {732 663 722 636 692 636}\n    $w.c create line $xy -smooth 1 -fill $::C(fg) -width 2.25p\n\n    Sine $w 149 688 720 688 5 15 -tag I13_s -fill $::C(fg) -width 2.25p\n}\nproc Move13 {w {step {}}} {\n    set step [GetStep 13 $step]\n    set numsteps 7\n\n    if {$step == $numsteps+2} {\n\tMoveAbs $w I13_star {-100 -100}\n\t$w.c itemconfig I13R -fill $::C(13b) -width 1.5p\n\treturn 2\n    }\n    if {$step == 0} {\t\t\t\t;# Button down\n\t$w.c delete I13\n\tSparkle $w {-100 -100} I13_star\t\t;# Create off screen\n\treturn 1\n    }\n    lassign [Anchor $w I13_s w] x0 y0\n    lassign [Anchor $w I13_s e] x1 y1\n    set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]\n    MoveAbs $w I13_star [list $x $y0]\n    return 1\n}\n\n# Paper in fax\nproc Draw14 {w} {\n    set color $::C(14)\n    set xy {102 661 113 632 130 618}\t\t;# Left paper edge\n    $w.c create line $xy -smooth 1 -fill $color -width 2.25p -tag I14L_0\n    set xy {148 629 125 640 124 662}\t\t;# Right paper edge\n    $w.c create line $xy -smooth 1 -fill $color -width 2.25p -tag I14L_1\n    Draw14a $w L\n\n    set xy {\n\t768.0 662.5 767.991316225 662.433786215 767.926187912 662.396880171\n    }\n    $w.c create line $xy -smooth 1 -fill $color -width 2.25p -tag I14R_0\n    $w.c lower I14R_0\n    # NB. these numbers are VERY sensitive, you must start with final size\n    # and shrink down to get the values\n    set xy {\n\t745.947897349 662.428358855 745.997829056 662.452239237 746.0 662.5\n    }\n    $w.c create line $xy -smooth 1 -fill $color -width 2.25p -tag I14R_1\n    $w.c lower I14R_1\n}\nproc Draw14a {w side} {\n    set color $::C(14)\n    set xy [$w.c coords I14${side}_0]\n    set xy2 [$w.c coords I14${side}_1]\n    lassign $xy x0 y0 x1 y1 x2 y2\n    lassign $xy2 x3 y3 x4 y4 x5 y5\n    set zz [concat \\\n\t    $x0 $y0 $x0 $y0 $xy $x2 $y2 $x2 $y2 \\\n\t    $x3 $y3 $x3 $y3 $xy2 $x5 $y5 $x5 $y5]\n    $w.c delete I14$side\n    $w.c create poly $zz -tag I14$side -smooth 1 -fill $color -outline $color \\\n\t    -width 2.25p\n    $w.c lower I14$side\n}\nproc Move14 {w {step {}}} {\n    set step [GetStep 14 $step]\n\n    # Paper going down\n    set sc [expr {.9 - .05*$step}]\n    if {$sc < .3} {\n\t$w.c delete I14L\n\treturn 0\n    }\n\n    lassign [$w.c coords I14L_0] Ox Oy\n    $w.c scale I14L_0 $Ox $Oy $sc $sc\n    lassign [lrange [$w.c coords I14L_1] end-1 end] Ox Oy\n    $w.c scale I14L_1 $Ox $Oy $sc $sc\n    Draw14a $w L\n\n    # Paper going up\n    set sc [expr {.35 + .05*$step}]\n    set sc [expr {1 / $sc}]\n\n    lassign [$w.c coords I14R_0] Ox Oy\n    $w.c scale I14R_0 $Ox $Oy $sc $sc\n    lassign [lrange [$w.c coords I14R_1] end-1 end] Ox Oy\n    $w.c scale I14R_1 $Ox $Oy $sc $sc\n    Draw14a $w R\n\n    return [expr {$step == 10 ? 3 : 1}]\n}\n\n# Light beam\nproc Draw15 {w} {\n    set color $::C(15a)\n    set xy {824 599 824 585 820 585 829 585}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I15a\n    set xy {789 599 836 643}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n    set xy {778 610 788 632}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n    set xy {766 617 776 625}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n\n    set xy {633 600 681 640}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n    set xy {635 567 657 599}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n    set xy {765 557 784 583}\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 2.25p\n\n    Sine $w 658 580 765 580 3 15 -tag I15_s -fill $::C(fg) -width 2.25p\n}\nproc Move15a {w} {\n    set color $::C(15b)\n    $w.c scale I15a [scl 824] [scl 599] 1 .3\t\t;# Button down\n    set xy [scl {765 621 681 621}]\n    $w.c create line $xy -dash \"-\" -width 2.25p -fill $color -tag I15\n}\nproc Move15 {w {step {}}} {\n    set step [GetStep 15 $step]\n    set numsteps 6\n\n    if {$step == $numsteps+2} {\n\tMoveAbs $w I15_star {-100 -100}\n\treturn 2\n    }\n    if {$step == 0} {\t\t\t\t;# Break the light beam\n\tSparkle $w {-100 -100} I15_star\n\tset xy [scl {765 621 745 621}]\n\t$w.c coords I15 $xy\n\treturn 1\n    }\n    lassign [Anchor $w I15_s w] x0 y0\n    lassign [Anchor $w I15_s e] x1 y1\n    set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]\n    MoveAbs $w I15_star [list $x $y0]\n    return 1\n}\n\n# Bell\nproc Draw16 {w} {\n    set color $::C(16)\n    set xy {722 485 791 556}\n    $w.c create rect $xy -fill {} -outline $::C(fg) -width 2.25p\n    set xy [box 752 515 25]\t\t\t;# Bell\n    $w.c create oval $xy -fill $color -outline black -tag I16b -width 1.5p\n    set xy [box 752 515 5]\t\t\t;# Bell button\n    $w.c create oval $xy -fill black -outline black -tag I16b\n\n    set xy {784 523 764 549}\t\t\t;# Clapper\n    $w.c create line $xy -width 2.25p -tag I16c -fill $::C(fg)\n    set xy [box 784 523 4]\n    $w.c create oval $xy -fill $::C(fg) -outline $::C(fg) -tag I16d\n}\nproc Move16 {w {step {}}} {\n    set step [GetStep 16 $step]\n\n    # Note: we never stop\n    lassign [scl {760 553}] Ox Oy\n    if {$step & 1} {\n\tset beta 12\n\t$w.c move I16b 2.25p 0\n    } else {\n\tset beta -12\n\t$w.c move I16b -2.25p 0\n    }\n    RotateItem $w I16c $Ox $Oy $beta\n    RotateItem $w I16d $Ox $Oy $beta\n\n    return [expr {$step == 1 ? 3 : 1}]\n}\n\n# Cat\nproc Draw17 {w} {\n    set color $::C(17)\n\n    set xy {584 556 722 556}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n    set xy {584 485 722 485}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p\n\n    set xy {664 523 717 549}\t\t\t;# Body\n    $w.c create arc $xy -outline $::C(fg) -fill $color -width 2.25p \\\n\t    -style chord -start 128 -extent -260 -tag I17\n\n    set xy {709 554 690 543}\t\t\t;# Paw\n    $w.c create oval $xy -outline $::C(fg) -fill $color -width 2.25p -tag I17\n    set xy {657 544 676 555}\n    $w.c create oval $xy -outline $::C(fg) -fill $color -width 2.25p -tag I17\n\n    set xy [box 660 535 15]\t\t\t;# Lower face\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -style arc \\\n\t    -start 150 -extent 240 -tag I17_\n    $w.c create arc $xy -outline {} -fill $color -width 0.75p -style chord \\\n\t    -start 150 -extent 240 -tag I17_\n    set xy {674 529 670 513 662 521 658 521 650 513 647 529}\t;# Ears\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n    $w.c create poly $xy -fill $color -outline {} -width 0.75p -tag {I17_ I17_c}\n    set xy {652 542 628 539}\t\t\t;# Whiskers\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n    set xy {652 543 632 545}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n    set xy {652 546 632 552}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n\n    set xy {668 543 687 538}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag {I17_ I17w}\n    set xy {668 544 688 546}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag {I17_ I17w}\n    set xy {668 547 688 553}\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag {I17_ I17w}\n\n    set xy {649 530 654 538 659 530}\t\t;# Left eye\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -smooth 1 -tag I17\n    set xy {671 530 666 538 661 530}\t\t;# Right eye\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -smooth 1 -tag I17\n    set xy {655 543 660 551 665 543}\t\t;# Mouth\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -smooth 1 -tag I17\n}\nproc Move17 {w {step {}}} {\n    set step [GetStep 17 $step]\n\n    if {$step == 0} {\n\t$w.c delete I17\t\t\t\t;# Delete most of the cat\n\tset xy [scl {655 543 660 535 665 543}]\t;# Mouth\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -smooth 1 -tag I17_\n\tset xy [box [scl 654] [scl 530] [scl 4]]\t;# Left eye\n\t$w.c create oval $xy -outline $::C(fg) -width 2.25p -fill {} -tag I17_\n\tset xy [box [scl 666] [scl 530] [scl 4]]\t;# Right eye\n\t$w.c create oval $xy -outline $::C(fg) -width 2.25p -fill {} -tag I17_\n\n\t$w.c move I17_ 0 -15p\t\t\t;# Move face up\n\tset xy [scl {652 528 652 554}]\t\t;# Front leg\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n\tset xy [scl {670 528 670 554}]\t\t;# 2nd front leg\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n\n\tset xy [scl {\n\t    675 506 694 489 715 513 715 513 715 513 716 525 716 525 716 525\n\t    706 530 695 530 679 535 668 527 668 527 668 527 675 522 676 517\n\t    677 512\n\t}]\t\t\t\t\t;# Body\n\t$w.c create poly $xy -fill [$w.c itemcget I17_c -fill] \\\n\t\t-outline $::C(fg) -width 2.25p -smooth 1 -tag I17_\n\tset xy [scl {716 514 716 554}]\t\t;# Back leg\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n\tset xy [scl {694 532 694 554}]\t\t;# 2nd back leg\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -tag I17_\n\tset xy [scl {715 514 718 506 719 495 716 488}]\t;# Tail\n\t$w.c create line $xy -fill $::C(fg) -width 2.25p -smooth 1 -tag I17_\n\n\t$w.c raise I17w\t\t\t\t;# Make whiskers visible\n\t$w.c move I17_ -3.75p 0\t\t\t;# Move away from wall a bit\n\treturn 2\n    }\n    return 0\n}\n\n# Sling shot\nproc Draw18 {w} {\n    set color $::C(18)\n    set xy {721 506 627 506}\t\t\t;# Sling hold\n    $w.c create line $xy -width 3p -fill $::C(fg) -tag I18\n\n    set xy {607 500 628 513}\t\t\t;# Sling rock\n    $w.c create oval $xy -fill $color -outline {} -tag I18a\n\n    set xy {526 513 606 507 494 502}\t\t;# Sling band\n    $w.c create line $xy -fill $::C(fg) -width 3p -tag I18b\n    set xy { 485 490 510 540 510 575 510 540 535 491 }\t;# Sling\n    $w.c create line $xy -fill $::C(fg) -width 4.5p\n}\nproc Move18 {w {step {}}} {\n    set step [GetStep 18 $step]\n\n    set pos [scl {\n\t{587 506} {537 506} {466 506} {376 506} {266 506 x} {136 506}\n\t{16 506} {-100 -100}\n    }]\n\n    set b(0) [scl {490 502 719 507 524 512}]\t\t;# Band collapsing\n    set b(1) [scl {\n\t491 503 524 557 563 505 559 496 546 506 551 525 553 536 538 534\n\t532 519 529 499\n    }]\n    set b(2) [scl {491 503 508 563 542 533 551 526 561 539 549 550 530 500}]\n    set b(3) [scl {491 503 508 563 530 554 541 562 525 568 519 544 530 501}]\n\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n\n    if {$step == 0} {\n\t$w.c delete I18\n\t$w.c itemconfig I18b -smooth 1\n    }\n    if {[info exists b($step)]} {\n\t$w.c coords I18b $b($step)\n    }\n\n    set where [lindex $pos $step]\n    MoveAbs $w I18a $where\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Water pipe\nproc Draw19 {w} {\n    set color $::C(19)\n    set xx {249 181 155 118  86 55 22 0}\n    foreach {x1 x2} $xx {\n\t$w.c create rect $x1 453 $x2 467 -fill $color -outline {} -tag I19\n\t$w.c create line $x1 453 $x2 453 -fill $::C(fg) -width 0.75p;# Pipe top\n\t$w.c create line $x1 467 $x2 467 -fill $::C(fg) -width 0.75p;# Pipe btm\n    }\n    $w.c raise I11i\n\n    set xy [box 168 460 16]\t\t\t;# Bulge by the joint\n    $w.c create oval $xy -fill $color -outline {}\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p -style arc \\\n\t    -start 21 -extent 136\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p -style arc \\\n\t    -start -21 -extent -130\n\n    set xy {249 447 255 473}\t\t\t;# First joint 26x6\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n\n    set xy [box 257 433 34]\t\t\t;# Bend up\n    $w.c create arc $xy -outline {} -fill $color -width 0.75p \\\n\t    -style pie -start 0 -extent -91\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 0 -extent -90\n    set xy [box 257 433 20]\n    $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \\\n\t    -style pie -start 0 -extent -92\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 0 -extent -90\n    set xy [box 257 421 34]\t\t\t;# Bend left\n    $w.c create arc $xy -outline {} -fill $color -width 0.75p \\\n\t    -style pie -start 1 -extent 91\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 0 -extent 90\n    set xy [box 257 421 20]\n    $w.c create arc $xy -outline {} -fill $::C(bg) -width 0.75p \\\n\t    -style pie -start 0 -extent 90\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 0 -extent 90\n    set xy [box 243 421 34]\t\t\t;# Bend down\n    $w.c create arc $xy -outline {} -fill $color -width 0.75p \\\n\t    -style pie -start 90 -extent 90\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 90 -extent 90\n    set xy [box 243 421 20]\n    $w.c create arc $xy -outline {} -fill $::C(bg) -width 0.75p \\\n\t    -style pie -start 90 -extent 90\n    $w.c create arc $xy -outline $::C(fg) -width 0.75p \\\n\t    -style arc -start 90 -extent 90\n\n    set xy {270 427 296 433}\t\t\t;# 2nd joint bottom\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n    set xy {270 421 296 427}\t\t\t;# 2nd joint top\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n    set xy {249 382 255 408}\t\t\t;# Third joint right\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n    set xy {243 382 249 408}\t\t\t;# Third joint left\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n    set xy {203 420 229 426}\t\t\t;# Last joint\n    $w.c create rect $xy -fill $color -outline $::C(fg) -width 0.75p\n\n    set xy [box 168 460 6]\t\t\t;# Handle joint\n    $w.c create oval $xy -fill $::C(fg) -outline {} -tag I19a\n    set xy {168 460 168 512}\t\t\t;# Handle bar\n    $w.c create line $xy -fill $::C(fg) -width 3.75p -tag I19b\n}\nproc Move19 {w {step {}}} {\n    set step [GetStep 19 $step]\n\n    set angles {30 30 30}\n    if {$step == [llength $angles]} {\n\treturn 2\n    }\n\n    RotateItem $w I19b {*}[Centroid $w I19a] [lindex $angles $step]\n    return 1\n}\n\n# Water pouring\nproc Draw20 {w} {\n}\nproc Move20 {w {step {}}} {\n    set step [GetStep 20 $step]\n\n    set pos [scl {451 462 473 484 496 504 513 523 532}]\n    set freq {20 40   40  40  40  40  40  40  40}\n    set pos [scl {\n\t{451 20} {462 40} {473 40} {484 40} {496 40} {504 40} {513 40}\n\t{523 40} {532 40 x}\n    }]\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n\n    $w.c delete I20\n    set where [lindex $pos $step]\n    lassign $where y f\n    H2O $w $y $f\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\nproc H2O {w y f} {\n    set color $::C(20)\n    $w.c delete I20\n\n    Sine $w [scl 208] [scl 428] [scl 208] $y 4 $f -tag {I20 I20s} \\\n\t    -width 2.25p -fill $color -smooth 1\n    $w.c create line [$w.c coords I20s] -width 2.25p -fill $color -smooth 1 \\\n\t    -tag {I20 I20a}\n    $w.c create line [$w.c coords I20s] -width 2.25p -fill $color -smooth 1 \\\n\t    -tag {I20 I20b}\n    $w.c move I20a 6p 0\n    $w.c move I20b 12p 0\n}\n\n# Bucket\nproc Draw21 {w} {\n    set color $::C(21)\n    set xy {217 451 244 490}\t\t\t;# Right handle\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -tag I21_a\n    set xy {201 467 182 490}\t\t\t;# Left handle\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -tag I21_a\n\n    set xy {245 490 237 535}\t\t\t;# Right side\n    set xy2 {189 535 181 490}\t\t\t;# Left side\n    $w.c create poly [concat $xy $xy2] -fill $color -outline {} \\\n\t    -tag {I21 I21f}\n    $w.c create line $xy -fill $::C(fg) -width 1.5p -tag I21\n    $w.c create line $xy2 -fill $::C(fg) -width 1.5p -tag I21\n\n    set xy {182 486 244 498}\t\t\t;# Top\n    $w.c create oval $xy -fill $color -outline {} -width 1.5p -tag {I21 I21f}\n    $w.c create oval $xy -fill {} -outline $::C(fg) -width 1.5p -tag {I21 I21t}\n    set xy {189 532 237 540}\t\t\t;# Bottom\n    $w.c create oval $xy -fill $color -outline $::C(fg) -width 1.5p \\\n\t    -tag {I21 I21b}\n}\nproc Move21 {w {step {}}} {\n    set step [GetStep 21 $step]\n\n    set numsteps 30\n    if {$step  >= $numsteps} {\n\treturn 0\n    }\n\n    lassign [$w.c coords I21b] x1 y1 x2 y2\n    #lassign [$w.c coords I21t] X1 Y1 X2 Y2\n    lassign [scl {183 492 243 504}] X1 Y1 X2 Y2\n\n    set f [expr {$step / double($numsteps)}]\n    set y2 [expr {$y2 - [scl 3]}]\n    set xx1 [expr {$x1 + ($X1 - $x1) * $f}]\n    set yy1 [expr {$y1 + ($Y1 - $y1) * $f}]\n    set xx2 [expr {$x2 + ($X2 - $x2) * $f}]\n    set yy2 [expr {$y2 + ($Y2 - $y2) * $f}]\n    #H2O $w $yy1 40\n\n    $w.c itemconfig I21b -fill $::C(20)\n    $w.c delete I21w\n    $w.c create poly $x2 $y2 $x1 $y1 $xx1 $yy1 $xx2 $yy1 -tag {I21 I21w} \\\n\t    -outline {} -fill $::C(20)\n    $w.c lower I21w I21\n    $w.c raise I21b\n    $w.c lower I21f\n\n    return [expr {$step == $numsteps-1 ? 3 : 1}]\n}\n\n# Bucket drop\nproc Draw22 {w} {\n}\nproc Move22 {w {step {}}} {\n    set step [GetStep 22 $step]\n    set pos [scl {{213 513} {213 523} {213 543 x} {213 583} {213 593}}]\n\n    if {$step == 0} {$w.c itemconfig I21f -fill $::C(22)}\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n    set where [lindex $pos $step]\n    MoveAbs $w I21 $where\n    H2O $w [lindex $where 1] 40\n    $w.c delete I21_a\t\t\t\t;# Delete handles\n\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Blow dart\nproc Draw23 {w} {\n    set color  $::C(23a)\n    set color2 $::C(23b)\n    set color3 $::C(23c)\n\n    set xy {185 623 253 650}\t\t\t;# Block\n    $w.c create rect $xy -fill black -outline $::C(fg) -width 1.5p -tag I23a\n    set xy {187 592 241 623}\t\t\t;# Balloon\n    $w.c create oval $xy -outline {} -fill $color -tag I23b\n    $w.c create arc $xy -outline $::C(fg) -width 2.25p -tag I23b \\\n\t    -style arc -start 12 -extent 336\n    set xy {239 604  258 589 258 625 239 610}\t;# Balloon nozzle\n    $w.c create poly $xy -outline {} -fill $color -tag I23b\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I23b\n\n    set xy {285 611 250 603}\t\t\t;# Dart body\n    $w.c create oval $xy -fill $color2 -outline $::C(fg) -width 2.25p -tag I23d\n    set xy {249 596 249 618 264 607 249 596}\t;# Dart tail\n    $w.c create poly $xy -fill $color3 -outline $::C(fg) -width 2.25p -tag I23d\n    set xy {249 607 268 607}\t\t\t;# Dart detail\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I23d\n    set xy {285 607 305 607}\t\t\t;# Dart needle\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I23d\n}\nproc Move23 {w {step {}}} {\n    set step [GetStep 23 $step]\n\n    set pos [scl {\n\t{277 607} {287 607} {307 607 x} {347 607} {407 607} {487 607}\n\t{587 607} {687 607} {787 607} {-100 -100}\n    }]\n\n    if {$step >= [llength $pos]} {\n\treturn 0\n    }\n    if {$step <= 1} {\n\t$w.c scale I23b {*}[Anchor $w I23a n] .9 .5\n    }\n    set where [lindex $pos $step]\n    MoveAbs $w I23d $where\n\n    if {[lindex $where 2] eq \"x\"} {\n\treturn 3\n    }\n    return 1\n}\n\n# Balloon\nproc Draw24 {w} {\n    set color $::C(24a)\n    set xy {366 518 462 665}\t\t\t;# Balloon\n    $w.c create oval $xy -fill $color -outline $::C(fg) -width 2.25p -tag I24\n    set xy {414 666 414 729}\t\t\t;# String\n    $w.c create line $xy -fill $::C(fg) -width 2.25p -tag I24\n    set xy {410 666 404 673 422 673 418 666}\t;# Nozzle\n    $w.c create poly $xy -fill $color -outline $::C(fg) -width 2.25p -tag I24\n\n    set xy {387 567 390 549 404 542}\t\t;# Reflections\n    $w.c create line $xy -fill $::C(fg) -smooth 1 -width 1.5p -tag I24\n    set xy {395 568 399 554 413 547}\n    $w.c create line $xy -fill $::C(fg) -smooth 1 -width 1.5p -tag I24\n    set xy {403 570 396 555 381 553}\n    $w.c create line $xy -fill $::C(fg) -smooth 1 -width 1.5p -tag I24\n    set xy {408 564 402 547 386 545}\n    $w.c create line $xy -fill $::C(fg) -smooth 1 -width 1.5p -tag I24\n}\nproc Move24 {w {step {}}} {\n    global S Dims\n    set step [GetStep 24 $step]\n\n    if {$step > 4} {\n\treturn 0\n    } elseif {$step == 4} {\n\treturn 2\n    }\n\n    if {$step == 0} {\n\t$w.c delete I24\t\t\t\t;# Exploding balloon\n\tset xy [scl {\n\t    347 465 361 557 271 503 272 503 342 574 259 594 259 593 362 626\n\t    320 737 320 740 398 691 436 738 436 739 476 679 528 701 527 702\n\t    494 627 548 613 548 613 480 574 577 473 577 473 474 538 445 508\n\t    431 441 431 440 400 502 347 465 347 465\n\t}]\n\t$w.c create poly $xy -tag I24 -fill $::C(24b) -outline $::C(24a) \\\n\t\t-width 7.5p -smooth 1\n\tset msg [subst $S(message)]\n\t$w.c create text [Centroid $w I24] -text $msg -tag {I24 I24t} \\\n\t\t-fill $::C(24c) -justify center -font {Times 18 bold}\n\treturn 1\n    }\n\n    $w.c itemconfig I24t -font [list Times [expr {18 + 6*$step}] bold]\n    $w.c move I24 $Dims(MovX) $Dims(MovY)\n    $w.c scale I24 {*}[Centroid $w I24] 1.25 1.25\n    return 1\n}\n\n# Displaying the message\nproc Move25 {w {step {}}} {\n    global S\n    set step [GetStep 25 $step]\n    if {$step == 0} {\n\tset ::XY(25) [clock clicks -milliseconds]\n\treturn 1\n    }\n    set elapsed [expr {[clock clicks -milliseconds] - $::XY(25)}]\n    if {$elapsed < 5000} {\n\treturn 1\n    }\n    return 2\n}\n\n# Collapsing balloon\nproc Move26 {w {step {}}} {\n    global S Dims\n    set step [GetStep 26 $step]\n\n    if {$step >= 3} {\n\t$w.c delete I24 I26\n\t$w.c create text $Dims(MsgX) $Dims(MsgY) -anchor s -tag I26 \\\n\t\t-fill $::C(26) -text \"click to continue\" -font {Times 24 bold}\n\tbind $w.c <Button-1> [list Reset $w]\n\treturn 4\n    }\n\n    $w.c scale I24 {*}[Centroid $w I24] .8 .8\n    $w.c move I24 0 45p\n    $w.c itemconfig I24t -font [list Times [expr {30 - 6*$step}] bold]\n    return 1\n}\n\n################################################################\n#\n# Helper functions\n#\n\nproc box {x y r} {\n    return [list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]]\n}\n\nproc MoveAbs {w item xy} {\n    lassign $xy x y\n    lassign [Centroid $w $item] Ox Oy\n    set dx [expr {$x - $Ox}]\n    set dy [expr {$y - $Oy}]\n    $w.c move $item $dx $dy\n}\n\nproc RotateItem {w item Ox Oy beta} {\n    set xy [$w.c coords $item]\n    set xy2 {}\n    foreach {x y} $xy {\n\tlappend xy2 {*}[RotateC $x $y $Ox $Oy $beta]\n    }\n    $w.c coords $item $xy2\n}\n\nproc RotateC {x y Ox Oy beta} {\n    # rotates vector (Ox,Oy)->(x,y) by beta degrees clockwise\n\n    set x [expr {$x - $Ox}]\t\t\t;# Shift to origin\n    set y [expr {$y - $Oy}]\n\n    set beta [expr {$beta * atan(1) * 4 / 180.0}]\t;# Radians\n    set xx [expr {$x * cos($beta) - $y * sin($beta)}]\t;# Rotate\n    set yy [expr {$x * sin($beta) + $y * cos($beta)}]\n\n    set xx [expr {$xx + $Ox}]\t\t\t;# Shift back\n    set yy [expr {$yy + $Oy}]\n\n    return [list $xx $yy]\n}\n\nproc Reset {w} {\n    global S\n    DrawAll $w\n    bind $w.c <Button-1> {}\n    set S(mode) $::MSTART\n    set S(active) 0\n}\n\n# Each Move## keeps its state info in STEP, this retrieves and increments it\nproc GetStep {who step} {\n    global STEP\n    if {$step ne \"\"} {\n\tset STEP($who) $step\n    } elseif {![info exists STEP($who)] || $STEP($who) eq \"\"} {\n\tset STEP($who) 0\n    } else {\n\tincr STEP($who)\n    }\n    return $STEP($who)\n}\n\nproc ResetStep {} {\n    global STEP\n    set ::S(cnt) 0\n    foreach a [array names STEP] {\n\tset STEP($a) \"\"\n    }\n}\n\nproc Sine {w x0 y0 x1 y1 amp freq args} {\n    set PI [expr {4 * atan(1)}]\n    set step 2\n    set xy {}\n    if {$y0 == $y1} {\t\t\t\t;# Horizontal\n\tfor {set x $x0} {$x <= $x1} {incr x $step} {\n\t    set beta [expr {($x - $x0) * 2 * $PI / $freq}]\n\t    set y [expr {$y0 + $amp * sin($beta)}]\n\t    lappend xy $x $y\n\t}\n    } else {\n\tfor {set y $y0} {$y <= $y1} {incr y $step} {\n\t    set beta [expr {($y - $y0) * 2 * $PI / $freq}]\n\t    set x [expr {$x0 + $amp * sin($beta)}]\n\t    lappend xy $x $y\n\t}\n    }\n    return [$w.c create line $xy {*}$args]\n}\n\nproc RoundRect {w xy radius args} {\n    lassign $xy x0 y0 x3 y3\n    set r [winfo pixels $w.c $radius]\n    set d [expr {2 * $r}]\n\n    # Make sure that the radius of the curve is less than 3/8 size of the box!\n    set maxr 0.75\n    if {$d > $maxr * ($x3 - $x0)} {\n\tset d [expr {$maxr * ($x3 - $x0)}]\n    }\n    if {$d > $maxr * ($y3 - $y0)} {\n\tset d [expr {$maxr * ($y3 - $y0)}]\n    }\n\n    set x1 [expr { $x0 + $d }]\n    set x2 [expr { $x3 - $d }]\n    set y1 [expr { $y0 + $d }]\n    set y2 [expr { $y3 - $d }]\n\n    set xy [list $x0 $y0 $x1 $y0 $x2 $y0 $x3 $y0 $x3 $y1 $x3 $y2]\n    lappend xy $x3 $y3 $x2 $y3 $x1 $y3 $x0 $y3 $x0 $y2 $x0 $y1\n    return $xy\n}\n\nproc RoundPoly {canv xy radii args} {\n    set lenXY [llength $xy]\n    set lenR [llength $radii]\n    if {$lenXY != 2*$lenR} {\n\terror \"wrong number of vertices and radii\"\n    }\n\n    set knots {}\n    lassign [lrange $xy end-1 end] x0 y0\n    lassign $xy x1 y1\n    lappend xy {*}[lrange $xy 0 1]\n\n    for {set i 0} {$i < $lenXY} {incr i 2} {\n\tset radius [lindex $radii [expr {$i/2}]]\n\tset r [winfo pixels $canv $radius]\n\n\tlassign [lrange $xy [expr {$i + 2}] [expr {$i + 3}]] x2 y2\n\tset z [_RoundPoly2 $x0 $y0 $x1 $y1 $x2 $y2 $r]\n\tlappend knots {*}$z\n\n\tlassign [list $x1 $y1] x0 y0\n\tlassign [list $x2 $y2] x1 y1\n    }\n    set n [$canv create polygon $knots -smooth 1 {*}$args]\n    return $n\n}\n\nproc _RoundPoly2 {x0 y0 x1 y1 x2 y2 radius} {\n    set d [expr {2 * $radius}]\n    set maxr 0.75\n\n    set v1x [expr {$x0 - $x1}]\n    set v1y [expr {$y0 - $y1}]\n    set v2x [expr {$x2 - $x1}]\n    set v2y [expr {$y2 - $y1}]\n\n    set vlen1 [expr {sqrt($v1x*$v1x + $v1y*$v1y)}]\n    set vlen2 [expr {sqrt($v2x*$v2x + $v2y*$v2y)}]\n    if {$d > $maxr * $vlen1} {\n\tset d [expr {$maxr * $vlen1}]\n    }\n    if {$d > $maxr * $vlen2} {\n\tset d [expr {$maxr * $vlen2}]\n    }\n\n    lappend xy [expr {$x1 + $d * $v1x/$vlen1}] [expr {$y1 + $d * $v1y/$vlen1}]\n    lappend xy $x1 $y1\n    lappend xy [expr {$x1 + $d * $v2x/$vlen2}] [expr {$y1 + $d * $v2y/$vlen2}]\n\n    return $xy\n}\n\nproc Sparkle {w Oxy tag} {\n    set xy {299 283 298 302 295 314 271 331 239 310 242 292 256 274 281 273}\n    foreach {x y} $xy {\n\t$w.c create line 271 304 $x $y -fill white -width 3 -tag $tag\n    }\n    MoveAbs $w $tag $Oxy\n}\n\nproc Centroid {w item} {\n    return [Anchor $w $item c]\n}\n\nproc Anchor {w item where} {\n    lassign [$w.c bbox $item] x1 y1 x2 y2\n    if {[string match *n* $where]} {\n\tset y $y1\n    } elseif {[string match *s* $where]} {\n\tset y $y2\n    } else {\n\tset y [expr {($y1 + $y2) / 2.0}]\n    }\n    if {[string match *w* $where]} {\n\tset x $x1\n    } elseif {[string match *e* $where]} {\n\tset x $x2\n    } else {\n\tset x [expr {($x1 + $x2) / 2.0}]\n    }\n    return [list $x $y]\n}\n\nproc scl {lst} {\n    global scaleFactor\n    set lst2 {}\n    foreach elem $lst {\n\tset elem2 {}\n\tset idx 0\n\tforeach val $elem {\n\t    if {$idx < 2} {\n\t\tset val [expr {round($val * $scaleFactor)}]\n\t    }\n\t    lappend elem2 $val\n\t    incr idx\n\t}\n\n\tlappend lst2 $elem2\n    }\n\n    return $lst2\n}\n\n# Simple placed dialog - stacked dialogs are not allowed,\n# the command does nothing if another grab already exists.\n\nproc PlacedDialog {w msg {labelFnt {Helvetica 10}}} {\n    if {[grab current] ne {}} {\n\treturn\n    }\n    destroy $w\n\n    frame $w -relief raised -bd 3p\n    label $w.lab -font $labelFnt -wraplength 3i -justify left -text $msg\n    ttk::button $w.but -text \"OK\" -underline 0 \\\n\t    -command [list ClosePlacedDialog $w]\n\n    foreach key {Escape Return o O} {\n\tbind $w.but \"<KeyPress-${key}>\" { ClosePlacedDialog [winfo parent %W] }\n    }\n    foreach child {{} .but .lab} {\n\tbind $w$child <<NextWindow>> break\n\tbind $w$child <<PrevWindow>> break\n    }\n\n    pack $w.lab -padx 10p -pady {10p 5p}\n    pack $w.but -padx 10p -pady {0p 10p}\n    place $w -anchor center -relx 0.5 -rely 0.5\n\n    set tl [winfo toplevel $w]\n    set ::PlacedDialogOldFocus [focus -lastfor $tl]\n    focus $w.but\n    grab set $w\n    return\n}\n\nproc ClosePlacedDialog {w} {\n    set tl [winfo toplevel $w]\n    if {![winfo exists $::PlacedDialogOldFocus]} {\n\tset ::PlacedDialogOldFocus $tl\n    }\n    focus $::PlacedDialogOldFocus\n    set ::PlacedDialogOldFocus {}\n    grab release $w\n    destroy $w\n    return\n}\n\n\nDoDisplay $w\nReset $w\nGo $w\t\t\t\t\t\t;# Start everything going\nStartMessage $w\t\t\t\t\t;# Message box at startup\n"
  },
  {
    "path": "library/demos/hello",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# hello --\n# Simple Tk script to create a button that prints \"Hello, world\".\n# Click on the button to terminate the program.\n\npackage require tk\n\n# The first line below creates the button, and the second line\n# asks the packer to shrink-wrap the application's main window\n# around the button.\n\nbutton .hello -text \"Hello, world\" -command {\n    puts stdout \"Hello, world\"; destroy .\n}\npack .hello\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/hscale.tcl",
    "content": "# hscale.tcl --\n#\n# This demonstration script shows an example with a horizontal scale.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .hscale\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Horizontal Scale Demonstration\"\nwm iconname $w \"hscale\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 3.5i -justify left -text \"An arrow and a horizontal scale are displayed below.  If you click or drag mouse button 1 in the scale, you can change the length of the arrow.\"\npack $w.msg -side top -padx .5c\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth 7.5p\npack $w.frame -side top -fill x\n\ncanvas $w.frame.canvas -width 37.5p -height 37.5p -bd 0 -highlightthickness 0\n$w.frame.canvas create polygon 0 0 1 1 2 2 -fill DeepSkyBlue3 -tags poly\n$w.frame.canvas create line 0 0 1 1 2 2 0 0 -fill black -tags line\nscale $w.frame.scale -orient horizontal -length 213p -from 0 -to 250 \\\n\t-command \"setWidth $w.frame.canvas\" -tickinterval 50\npack $w.frame.canvas -side top -expand yes -anchor s -fill x -padx 12p\npack $w.frame.scale -side bottom -expand yes -anchor n\n$w.frame.scale set 75\n\nproc setWidth {w width} {\n    incr width 21\n    set x2 [expr {$width - 30}]\n    if {$x2 < 21} {\n\tset x2 21\n    }\n    $w coords poly 20 15 20 35 $x2 35 $x2 45 $width 25 $x2 5 $x2 15 20 15\n    $w coords line 20 15 20 35 $x2 35 $x2 45 $width 25 $x2 5 $x2 15 20 15\n\n    set scaleFactor [expr {$tk::scalingPct / 100.0}]\n    $w scale poly 0 0 $scaleFactor $scaleFactor\n    $w scale line 0 0 $scaleFactor $scaleFactor\n}\n"
  },
  {
    "path": "library/demos/icon.tcl",
    "content": "# icon.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# buttons that display bitmaps instead of text.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .icon\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Iconic Button Demonstration\"\nwm iconname $w \"icon\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"This window shows three ways of using bitmaps or images in radiobuttons and checkbuttons.  On the left are two radiobuttons, each of which displays a bitmap and an indicator.  In the middle is a checkbutton that displays a different image depending on whether it is selected or not.  On the right is a checkbutton that displays a single bitmap but changes its background color to indicate whether or not it is selected.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Main widget program sets variable tk_demoDirectory\nimage create bitmap flagup \\\n\t-file [file join $tk_demoDirectory images flagup.xbm] \\\n\t-maskfile [file join $tk_demoDirectory images flagup.xbm]\nimage create bitmap flagdown \\\n\t-file [file join $tk_demoDirectory images flagdown.xbm] \\\n\t-maskfile [file join $tk_demoDirectory images flagdown.xbm]\nframe $w.frame -borderwidth 7.5p\npack $w.frame -side top\n\ncheckbutton $w.frame.b1 -image flagdown -selectimage flagup \\\n\t-indicatoron 0\n$w.frame.b1 configure -selectcolor [$w.frame.b1 cget -background]\ncheckbutton $w.frame.b2 \\\n\t-bitmap @[file join $tk_demoDirectory images letters.xbm] \\\n\t-indicatoron 0 -selectcolor SeaGreen1\nframe $w.frame.left\npack $w.frame.left $w.frame.b1 $w.frame.b2 -side left -expand yes -padx 5m\n\nradiobutton $w.frame.left.b3 \\\n\t-bitmap @[file join $tk_demoDirectory images letters.xbm] \\\n\t-variable letters -value full\nradiobutton $w.frame.left.b4 \\\n\t-bitmap @[file join $tk_demoDirectory images noletter.xbm] \\\n\t-variable letters -value empty\npack $w.frame.left.b3 $w.frame.left.b4 -side top -expand yes\n"
  },
  {
    "path": "library/demos/image1.tcl",
    "content": "# image1.tcl --\n#\n# This demonstration script displays two image widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .image1\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Image Demonstration #1\"\nwm iconname $w \"Image1\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This demonstration displays two images, each in a separate label widget.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Main widget program sets variable tk_demoDirectory\ncatch {image delete image1a}\nimage create photo image1a -file [file join $tk_demoDirectory images earth.gif]\ncatch {image delete image1b}\nimage create photo image1b \\\n\t-file [file join $tk_demoDirectory images earthris.gif]\n\n# Create copies of the images just created, magnified according to the\n# display's DPI scaling level.  Since the zooom factor must be an integer,\n# the copies will only be effectively magnified if $tk::scalingPct >= 200.\nset zoomFactor [expr {$tk::scalingPct / 100}]\nimage create photo image1a2\nimage1a2 copy image1a -zoom $zoomFactor\nimage create photo image1b2\nimage1b2 copy image1b -zoom $zoomFactor\n\nlabel $w.l1 -image image1a2 -bd 1 -relief sunken\nlabel $w.l2 -image image1b2 -bd 1 -relief sunken\n\npack $w.l1 $w.l2 -side top -padx .5m -pady .5m\n"
  },
  {
    "path": "library/demos/image2.tcl",
    "content": "# image2.tcl --\n#\n# This demonstration script creates a simple collection of widgets\n# that allow you to select and view images in a Tk label.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# loadDir --\n# This procedure reloads the directory listbox from the directory\n# named in the demo's entry.\n#\n# Arguments:\n# w -\t\t\tName of the toplevel window of the demo.\n\nproc loadDir w {\n    global dirName\n\n    $w.f.list delete 0 end\n    foreach i [lsort [glob -type f -directory $dirName *]] {\n\t$w.f.list insert end [file tail $i]\n    }\n}\n\n# selectAndLoadDir --\n# This procedure pops up a dialog to ask for a directory to load into\n# the listobx and (if the user presses OK) reloads the directory\n# listbox from the directory named in the demo's entry.\n#\n# Arguments:\n# w -\t\t\tName of the toplevel window of the demo.\n\nproc selectAndLoadDir w {\n    global dirName\n    set dir [tk_chooseDirectory -initialdir $dirName -parent $w -mustexist 1]\n    if {$dir ne \"\"} {\n\tset dirName $dir\n\tloadDir $w\n    }\n}\n\n# loadImage --\n# Given the name of the toplevel window of the demo and the mouse\n# position, extracts the directory entry under the mouse and loads\n# that file into a photo image for display.\n#\n# Arguments:\n# w -\t\t\tName of the toplevel window of the demo.\n# x, y-\t\t\tMouse position within the listbox.\n\nproc loadImage {w x y} {\n    global dirName\n\n    set file [file join $dirName [$w.f.list get @$x,$y]]\n    set opts [list -file $file]\n    if {[string tolower [file extension $file]] eq \".svg\"} {\n\tlappend opts -format $tk::svgFmt\n    } else {\n\tlappend opts -format {}\n    }\n    if {[catch {\n\timage2a configure {*}$opts\n    }]} then {\n\t# Mark the file as not loadable\n\t$w.f.list itemconfigure @$x,$y -bg \\#c00000 -selectbackground \\#ff0000\n    }\n\n\tset filename [file nativename [file normalize $file]]\n\tset icon [tk fileicon $filename 48]\n\t$w.label configure -image $icon -compound top\n}\n\nset w .image2\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Image Demonstration #2\"\nwm iconname $w \"Image2\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This demonstration allows you to view images using a Tk \\\"photo\\\" image.  First type a directory name in the listbox, then type Return to load the directory into the listbox.  Then double-click on a file name in the listbox to see that image.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.mid\npack $w.mid -fill both -expand 1\n\nlabelframe $w.dir -text \"Directory:\"\n# Main widget program sets variable tk_demoDirectory\nset dirName [file join $tk_demoDirectory images]\nentry $w.dir.e -width 30 -textvariable dirName\nbutton $w.dir.b -pady 0 -padx 2m -text \"Select Dir.\" \\\n\t-command \"selectAndLoadDir $w\"\nbind $w.dir.e <Return> \"loadDir $w\"\npack $w.dir.e -side left -fill both -padx 2m     -pady 2m -expand true\npack $w.dir.b -side left -fill y    -padx {0 2m} -pady 2m\nlabelframe $w.f -text \"File:\" -padx 2m -pady 2m\n\nlistbox $w.f.list -width 20 -height 10 -yscrollcommand \"$w.f.scroll set\"\nttk::scrollbar $w.f.scroll -command \"$w.f.list yview\"\npack $w.f.list $w.f.scroll -side left -fill y -expand 1\n$w.f.list insert 0 earth.gif earthris.gif teapot.ppm Tcl.svg\nbind $w.f.list <Double-Button-1> \"loadImage $w %x %y\"\n\nlabel $w.label -text \"Icon for Selected Image\" -relief groove\npack $w.label -side bottom -fill both -expand 1\n\ncatch {image delete image2a}\nimage create photo image2a\nlabelframe $w.image -text \"Image:\"\nlabel $w.image.image -image image2a\npack $w.image.image -padx 2m -pady 2m\n\ngrid $w.dir -        -sticky ew -padx 1m -pady 1m -in $w.mid\ngrid $w.f   $w.image -sticky nw -padx 1m -pady 1m -in $w.mid\ngrid columnconfigure $w.mid 1 -weight 1\n"
  },
  {
    "path": "library/demos/images/flagdown.xbm",
    "content": "#define flagdown_width 48\n#define flagdown_height 48\nstatic char flagdown_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,\n   0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00,\n   0x00, 0x00, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00,\n   0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04,\n   0x00, 0x00, 0x03, 0x00, 0x06, 0x06, 0x00, 0x80, 0x01, 0x00, 0x06, 0x07,\n   0x00, 0xc0, 0x1f, 0x00, 0x87, 0x07, 0x00, 0xe0, 0x7f, 0x80, 0xc7, 0x07,\n   0x00, 0x70, 0xe0, 0xc0, 0xe5, 0x07, 0x00, 0x38, 0x80, 0xe1, 0x74, 0x07,\n   0x00, 0x18, 0x80, 0x71, 0x3c, 0x07, 0x00, 0x0c, 0x00, 0x3b, 0x1e, 0x03,\n   0x00, 0x0c, 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x86, 0x1f, 0x8e, 0x07, 0x00,\n   0x00, 0x06, 0x06, 0xc6, 0x05, 0x00, 0x00, 0x06, 0x00, 0xc6, 0x05, 0x00,\n   0x00, 0x06, 0x00, 0xc6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,\n   0x7f, 0x06, 0x00, 0x06, 0xe4, 0xff, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,\n   0x00, 0x06, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00,\n   0x00, 0x06, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,\n   0x00, 0x06, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00,\n   0x00, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,\n   0x00, 0xfe, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x27, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0xf7, 0xbf, 0x8e, 0xfc, 0xdf, 0xf8, 0x9d, 0xeb, 0x9b, 0x76, 0xd2, 0x7a,\n   0x46, 0x30, 0xe2, 0x0f, 0xe1, 0x47, 0x55, 0x84, 0x48, 0x11, 0x84, 0x19};\n"
  },
  {
    "path": "library/demos/images/flagup.xbm",
    "content": "#define flagup_width 48\n#define flagup_height 48\nstatic char flagup_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,\n   0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,\n   0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,\n   0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,\n   0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,\n   0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,\n   0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,\n   0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,\n   0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,\n   0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,\n   0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,\n   0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,\n   0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,\n   0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,\n   0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,\n   0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,\n   0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,\n   0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,\n   0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,\n   0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,\n   0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\n"
  },
  {
    "path": "library/demos/images/gray25.xbm",
    "content": "#define grey_width 16\n#define grey_height 16\nstatic char grey_bits[] = {\n   0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,\n   0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,\n   0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44};\n"
  },
  {
    "path": "library/demos/images/letters.xbm",
    "content": "#define letters_width 48\n#define letters_height 48\nstatic char letters_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20,\n   0x00, 0xfa, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2a,\n   0x00, 0x3a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2e,\n   0xe0, 0xff, 0xff, 0xff, 0xff, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21,\n   0xa0, 0x03, 0x00, 0x00, 0x70, 0x21, 0x20, 0x00, 0x00, 0x00, 0x50, 0x21,\n   0xa0, 0x1f, 0x00, 0x00, 0x50, 0x21, 0x20, 0x00, 0x00, 0x00, 0x70, 0x21,\n   0xfe, 0xff, 0xff, 0xff, 0x0f, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,\n   0xfa, 0x01, 0x00, 0x80, 0x0b, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0a, 0x21,\n   0xba, 0x01, 0x00, 0x80, 0x0a, 0x21, 0x02, 0x00, 0x00, 0x80, 0x0b, 0x21,\n   0x3a, 0x00, 0x00, 0x00, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x21,\n   0x02, 0xc0, 0xfb, 0x03, 0x08, 0x21, 0x02, 0x00, 0x00, 0x00, 0x08, 0x3f,\n   0x02, 0xc0, 0xbd, 0x0f, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,\n   0x02, 0xc0, 0x7f, 0x7b, 0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01,\n   0x02, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,\n   0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,\n   0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00,\n   0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\n"
  },
  {
    "path": "library/demos/images/noletter.xbm",
    "content": "#define noletters_width 48\n#define noletters_height 48\nstatic char noletters_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,\n   0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,\n   0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,\n   0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,\n   0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07,\n   0xe0, 0x01, 0x00, 0x00, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x78, 0x0e,\n   0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x1e, 0x1c,\n   0x38, 0x00, 0x00, 0x00, 0x0f, 0x38, 0x38, 0x00, 0x00, 0x80, 0x07, 0x38,\n   0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x1c, 0x04, 0x00, 0xe0, 0x41, 0x70,\n   0x1c, 0x04, 0x00, 0xf0, 0x40, 0x70, 0x1c, 0x74, 0x00, 0x78, 0x4e, 0x70,\n   0x0e, 0x04, 0x00, 0x3c, 0x4a, 0xe0, 0x0e, 0x74, 0x03, 0x1e, 0x4a, 0xe0,\n   0x0e, 0x04, 0x00, 0x0f, 0x4e, 0xe0, 0x0e, 0x04, 0x80, 0x07, 0x40, 0xe0,\n   0x0e, 0x04, 0xf8, 0x0f, 0x40, 0xe0, 0x0e, 0x04, 0xe0, 0x01, 0x40, 0xe0,\n   0x0e, 0x04, 0xf8, 0x00, 0x40, 0xe0, 0x0e, 0x04, 0x78, 0x00, 0x40, 0xe0,\n   0x0e, 0x04, 0xfc, 0xf3, 0x40, 0xe0, 0x1c, 0x04, 0x1e, 0x00, 0x40, 0x70,\n   0x1c, 0x04, 0x0f, 0x00, 0x40, 0x70, 0x1c, 0x84, 0x07, 0x00, 0x40, 0x70,\n   0x3c, 0xfc, 0xff, 0xff, 0x7f, 0x78, 0x38, 0xe0, 0x01, 0x00, 0x00, 0x38,\n   0x38, 0xf0, 0x00, 0x00, 0x00, 0x38, 0x70, 0x78, 0x00, 0x00, 0x00, 0x1c,\n   0xf0, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x1e, 0x00, 0x00, 0x00, 0x0e,\n   0xe0, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x07,\n   0x80, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x01,\n   0x00, 0x3e, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x7f, 0x00,\n   0x00, 0xf0, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,\n   0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00};\n"
  },
  {
    "path": "library/demos/images/pattern.xbm",
    "content": "#define foo_width 16\n#define foo_height 16\nstatic char foo_bits[] = {\n   0x60, 0x06, 0x90, 0x09, 0x90, 0x09, 0xb0, 0x0d, 0x4e, 0x72, 0x49, 0x92,\n   0x71, 0x8e, 0x8e, 0x71, 0x8e, 0x71, 0x71, 0x8e, 0x49, 0x92, 0x4e, 0x72,\n   0xb0, 0x0d, 0x90, 0x09, 0x90, 0x09, 0x60, 0x06};\n"
  },
  {
    "path": "library/demos/images/teapot.ppm",
    "content": "P6\n256 256\n255\n\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[7 eOLjQLmSMoTMnSMlRMhPL_9 \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\nSMtVMzYN~[N~[N\\N\\O\\O]O]O]O]O\\O\\O}[NyYNtVM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\G-\u001ewXN}[N]O^O_O`O`O`O`OaOaOaOaOaOaOaOaO`O_O^O\\N\u000b\u000f\u0018\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aMLyYN_OaPbPcPcPdPdPdPdPdPdPdPdPdPePePePePePdPcP_OpUM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\wXN_OdPfPgQhQhQiQiQiQiQiQjQjQjQjQjQjQjQjQjQjQiQfP`O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJiQLbPhQkQmRnRoRoRoRoRoRoRoRoRpRpSqSqSrSrSrSqSoRjQ]O\\KK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fOLrUMcPlRqStSuTwTxTxTyTyTzTzUzUzUzUzUyTxTwTtSmRaOhPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\a0\tcNLqUM\\OfQpSwVzV|V}VVVǀVɂW̅[ՏewꪅĈgqTfQ{ZNYIK9\u001c\u0005\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\O1\u001e{G#J\u0011kRMqUMtVNiSv\\dbzZvUuTsSqSnRjQeP^OrUMH\u0011h>!T4\u001f\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\G-\u001eV5\u001fwE\"~I#M%U+e7l:g2b*a(`(^(])^-]1S,qC$`9 R3\u001fG-\u001e\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@)\u001dJ/\u001ei>!pA\"tD\"wF$yH&xH&tE$wE#yG%}M+T4S5mE*Z7!K/\u001eB*\u001d;'\u001c\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aOoR{UǀVυX<(\u001dF-\u001ea: e<!h>!j@#k@$h>\"d<!c=$hD-fF2[<)K0\u001f@)\u001d;'\u001c5$\u001c˂VǀV|U_LKYIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\_OxTɂW֒k|X>f-^(Z'W&T&N\u000f>)\u001dF-\u001eJ/\u001eb; g>#nD(jB&c<!b=%jH2_A/I0!<(\u001d8&\u001c5$\u001cJ\u000eY\u001dS%8&\u001c;'\u001c?)\u001dE,\u001d<:HA=HE?IJAISFJYIKXIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\nR}UܘqʊevUe,V&V\u0018C\r@\f|>\fy<\fu:\u000br9\u000bo7\u000bl6\nj5\nh4\ng3\n5$\u001cD,\u001dK/\u001eb; h>\"wM1tK.e=\"a<#cA,U8&E-\u001e<(\u001d9&\u001c.!\u001ba0\tb1\tc1\t\u0011\b\u0001\u0011\b\u0001\u0011\b\u0001\u0011\b\u0001\u0012\t\u0001\u0012\t\u0001\u0012\t\u0001\u0014\n\u0002\u001d\u0012\n+\u001f\u001b3#\u001c@)\u001d46G<:HMCIXHK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\U*\bvT~X{Yk+W&N$|>\fu:\u000bp8\u000bk5\nf3\na0\t_/\t].\t[-\tI\u0011\\*_(L\u0016kRMmSMmSMnSMnSMD,\u001dR3\u001fW5\u001fmA\"|O0|P1j?\"c<!a=%Y7\"N1\u001eF,\u001e;'\u001cNCJNCJNDJODJODJODJh>!a: X/\u0010K%\u0007\u0005\u0002\u0000\u0005\u0002\u0000\u0000\u0000\u0000\u0006\u0003\u0001\u0002\u0001\u0000\u0003\u0001\u0000\u0004\u0002\u0000\u0006\u0003\u0000\u0017\u0015\u0019&\u001d\u001a4$\u001c+2F=;HPEJL&\u0007\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\lRxTsTd)O$w;\u000bm6\ng3\na0\tZ-\t\\/\fT*\bQ(\bH\u0015m8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5\u001a\u0005^9 d<!yF#O+N,rC#qB\"pB#k?\"a: Z7 6\u001b\u0005ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0004\b\u0000\u0000\u0000\u0002\u000b\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0001\u0000\u0015\u0014\u0019- \u001b'0FqSgQ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPtSmRR%B\u000ff3\n^/\tV+\bQ(\bL&\u0007I$\u0007r9\u000bT\u0018lRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F\u0000\u0000\u0000oA\"N$O%S)R)T&T%R%O$J#xE#\u0003\u0001\u0000PDJQEJREJRFJSFJTFJTFJTGJUGJUGJUGJUGJVGJVGJVGJVGJVGJVGJY6\u001fN'\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000\u0000t;\u000eO$dPoRdP\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\pSkQS%x=\u000e[-\tR)\bI$\u0007E\"\u0006@ \u0006\u0000\u0000\u0000M\u0017]'pTM68G78G78G78G78G78G78G78G78G68G67G67G57G57G47G36G36G25Gp9\u000e8\u001c\u0005eOLpUMtVMn7\u000bf+i,i*i*h*B\r`O~[NqUM[-\tH\u0016UGJUGJVGJVGJVHJWHJWHJWHKWHKXHKXHKXHKXHKXHKXIKXIKXIKXIKXIKh>!Y0\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000\u0000W+\b].\ts=\u0013M$dPlR\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\oTMoRdPvE\"V+\bK%\u0007A \u00069\u001c\u00059\u001c\u0005\u0000\u0000\u0000F\u0015['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\\JKmSMwXN|ZNy[ᦆ֘u{WyU]btUnRhQaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXNL$f3\n\u0000\u0000\u0000I$\u0007L&\u0007P(\bU*\b\\.\tJ#\\OjQ\b\u000e\u0017\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\kRaOo9\rL&\u0007C!\u0006:\u001d\u00054\u001a\u0005\u0000\u0000\u0000f3\nX&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQLpRuTzU~VȁW˂X֎csҎe{VvTpSkRgQbP_O^O]O\\O\\O\\O\\O]O]O]O]O]O]O]O]O]O]O]O\\O\\O~\\N}[N|ZNxXNT%H$\u0007\u0000\u0000\u0000G#\u0007K%\u0007Q(\bW+\bzG#nTMiQ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\dOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM\u0002\u000b\u0017\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\`OcPnA\"M&\u0007@ \u00068\u001c\u0005F#\u0007\u0000\u0000\u0000m6\nW&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHKhQlRpRb(i*n+|7|6r,q+p-l+g)b(sSpSlRiQgQePcPaPaO`O`O_O_O_O_O_O_O_O_O_O_O^O^O^O^O]O]O\\O~[N{ZNT%\u0000\u0000\u0000F#\u0007B!\u0006Y,\bL&\u0007U*\b~I#^O`O\u0013\\\u0013\\\u0013\\\u0013\\cNLrUMzYN\\O^O`ObPcPdPePfPfPfQfQfQePcPaP~[N\u0000\u0003\b\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPsVM^/\tC!\u00067\u001b\u0005\u001b\r\u0002\u0000\u0000\u0000\u0000\u0000\u0000Q%tVMwXNzYN|ZN}[N\\N\\O\\O]O]O]O]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIcPdPePgQiQlRnR\\'d)i*m+s/s/o+n+l*i*g)c(_(qSoRmRkQiQgQfPePdPcPbPbPbPaPaPaOaOaO`O`O`O`O`O`O_O_O^O^O]O\\O}[NQ\u0017\u0001\u0000\u0000D\"\u0006?\u001f\u0006D\"\u0006K%\u0007_/\tkRLfPODJSFJ_ObPcPePfQgQiQjQkRlRmRnRnRoRoRoRnRmRlRiQeP_O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\B+\u001dePI#L&\u00079\u001c\u00050\u0018\u0004\u0000\u0000\u0000\u001c\u000e\u0002y<\fP\u0017xXN{ZN}[N\\N\\O]O]O^O^O^O_O_O_O_O`O`O`O`OaOaPbPbPcPdPePfPgQhQiQkRmRZ'_(e)h)k*n,n,m*l*j*f)e)c(_(]'pRnRmRkRjQiQgQgQfPePdPdPdPcPcPcPbPbPbPbPbPaPaPaOaO`O`O_O_O^O]O_(@\f\u0000\u0000\u0000B!\u0006I$\u0007B!\u0006N'\u0007w=\u000feP`LKbNLeOLkRmRnRoRpSqSrSsStStStSuSuStStSsSrSpSmRjQbPjQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\bPpTME\"\u00065\u001a\u0005\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000M$tVM{ZN}[N\\O]O^O^O_O_O_O`O`O`O`OaOaPaPbPbPbPcPcPdPdPePfPgQhQiQjQkRlRmRZ'`(d)g)g\u001bj*j*i*i*g)d)c(a(_(\\'pRoRnRmRkRjQiQiQhQgQgQfPePePePdPdPdPcPcPcPcPcPbPbPbPbPaPaO`O_O^O\\NQ\u0017\u0000\u0000\u0000\b\u0004\u0000@ \u0006<\u001e\u0006G#\u0007_LKcPlSMnTMpUMsVMtSuTvTwTwTxTxTwTwTvTuTtSsSqSpSoRnRkRhQbPeOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\wXN\\NJ%\u00070\u0018\u0004\u0000\u0000\u0000\u0000\u0000\u00001\u0018\u0004J\u0016vWN}[N\\O]O^O_O_O`O`O`OaOaPaPbPbPbPbPcPcPdPdPdPePePfQgQgQhQiQjQkQlRmRY&]'`(c(e)c\u001b\\\u0012\\\u0012\\\u0012]\u0012]\u0013^\u001aa(`(^'['['oRnRmRlRkRkQjQiQiQhQgQgQgQfQfPePePePePdPdPdPdPdPcPcPcPbPbPaPaO`O]OO\u0017\u0000\u0000\u0000\u0000\u0000\u0000G#\u00077\u001b\u0005F#\u0007uWM^OwXNxXNzYN{ZN|ZNyTyTxTwTuTsSpSmRjQgQdPbPaPaPbPcPePcP|ZN\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[JKbP^/\t1\u0018\u0004\f\u0006\u00010\u0018\u00041\u0018\u0004|>\fwXN}[N]O^O_O`O`OaOaPaPbPbPbPcPcPcPcPdPdPdPePePfPfQgQgQhQhQiQjQkQkRlRmRY&]'`(b([\u0012g\u001ci\u001dh\u001df\u001bd\u001be\u001bc\u001bU\u0011_(]'['Z'nRnRmRmRlRkRkQjQjQiQiQhQhQgQgQgQfQfQfPfPePePePePePdPdPdPcPcPbPbP`O^OD\r\u0000\u0000\u0000\u0000\u0003\b\u0000\u0003\b4\u001a\u0005M&\u0007dPnSM|[N|[O|[OzZOxXNrSnRhQcP^OvXNiQL^KKRFJMCJJAIKBISFJ\\JKnSMxYN_O\\OaMK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\B!\u0006qUMaPC!\u0006/\u0017\u00040\u0018\u00040\u0018\u0004a0\tuWN}[N]O_O`O`OaPaPbPbPcPcPcPcPdPdPdPePePePfPfQfQgQgQhQhQiQiQjQjQkRlRlRX&['^'`(Z\u0012d\u001bf\u001ci\u001eg\u001dd\u001bc\u001bc\u001ba\u001a_\u001aT\u0010\\'['Z'Y&nRmRmRlRlRkRkQjQjQjQiQiQhQhQhQhQgQgQgQgQfQfQfQfPfPePePePdPdPcPbPaO^Ox<\f\u0000\u0000\u0000\u0004\u0002\u0000\u0000\u0000\u0000:\u001d\u0005aP]Oj8\u0012sVMmSMfOL^KKUGJIAIQEJ?<H*1F(\u001e\u001b\u0015\u000e\n\n\b\t\b\u0007\b\u0007\u0006\b\u0011\n\u0005@%\u0010<-$G?@pfdNLuWM\\NdNL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TFJvWNaP.\u0017\u0004/\u0017\u00040\u0018\u00041\u0018\u0004E\u0015}[N]O_O`OaPbPbPcPcPcPdPdPdPePePePePfPfQfQgQgQgQhQhQhQiQiQjQjQkQkRlRlRY&\\'^'^\u001ab\u001ac\u001be\u001ci g\u001ec\u001bb\u001aa\u001b`\u001a^\u001a]\u001aX\u0014['Z'Y&mRmRmRlRlRlRkRkQkQjQjQjQiQiQiQiQhQhQhQhQgQgQgQgQgQfQfQfQfPePePdPcPaPO\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`O`OoTMQEJC>IeZY638*\u0019\u000e\u0005\f\u0017\u0006 B\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u000e\u001b,\u0001\u0005\u000b\u0001\u0005\u000b4\u001c\t.\u0017\u0004G1!\\TUrsVM{ZN`MK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[JKyYNbP/\u0017\u00040\u0018\u0004\u0000\u0000\u0000\u0000\u0000\u0000N$]O_O`ObPbPcPcPdPdPdPePePePfPfPfQfQgQgQgQgQhQhQhQiQiQiQjQjQkQkRkRlRO\u0012Z'\\'^'V\u0011a\u001ab\u001be\u001di!f\u001eb\u001ba\u001a`\u001a_\u001b]\u001a\\\u0019Z\u0012['Z'Y&Q\u0017mRmRmRlRlRlRkRkRkQkQjQjQjQjQiQiQiQiQiQhQhQhQhQhQhQgQgQgQgQfQfPdPcPW&\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000dPaPrUM\u001b\u0011\n\u0006 B\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0019%7\u0003\u0010!\u0003\u0010!C*\u0019F#\u0007P)\f{dYzep\\OgPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ`LKvWNaPm6\n\f\u0006\u0001\u0000\u0000\u0000X,\buWM]O`ObPcPdPdPdPePePfPfPfQfQgQgQgQgQgQhQhQhQiQiQiQiQjQjQjQkQkQkRlRlRZ'\\']'_\u001a`\u001aa\u001ab\u001be\u001ei\"e\u001ea\u001b`\u001a_\u001b_\u001b]\u001a\\\u0019\\\u0019Y\u0019Z'Z'Z'mRmRmRlRlRlRlRlRkRkRkRkQkQjQjQjQjQjQjQiQiQiQiQiQiQiQhQhQhQgQgQfQdP_Oq8\u000b\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000gQ`OuWMT%\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0003\u0010!\u0003\u0010!T,\u000ec5\u0011F\u0016T3ț~Ɠq^OfOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XHK_LKsVM`OcP\u0000\u0000\u0000\u0000\u0000\u0000\u0013\t\u0001S%]ObPcPdPePePfPfQfQgQgQgQgQgQhQhQhQhQiQiQiQiQiQjQjQjQjQkQkRkRlRlRlR\\']'^'V\u0011`\u001aa\u001ab\u001bf\u001ei\"e\u001ea\u001b`\u001a_\u001b_\u001b]\u001a\\\u0019\\\u0019R\u0010Z'Z'['mRmRmRmRmRlRlRlRlRlRlRkRkRkRkRkQkQjQjQjQjQjQjQjQjQjQjQiQiQiQhQgQePS\u0010q8\u000b\u0000\u0000\u0000\u0000\u0000\u0000aOgQ`OtVMX&\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0006 B\u0002\u000b\u0017l@!{A\u0014L$Y'afPaO]KK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ODJ[JKaMKqUM\\OcP^O\u0000\u0000\u0000\u0000\u0000\u0000vE\"]OaPdPePfPfQgQgQgQhQhQhQhQhQiQiQiQiQiQjQjQjQjQjQkQkQkRkRkRlRlRlRlR^'^'_(W\u0011a\u001aa\u001ac\u001cg i\"e\u001ea\u001b`\u001a_\u001b_\u001c^\u001b\\\u001a\\\u0019R\u0010['[']'mRmRmRmRmRmRmRlRlRlRlRlRlRlRlRlRlRkRkRkRkRkRkRkRkRkQkQkQjQjQiQhQePW&M&\u0007\u0000\u0000\u0000oTMiQeP_OtVMmSMdOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0006 B\u0002\u000b\u0017\u001a\u0017\u0019J\u0011Z'_(kQiQ`OSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TFJ\\JKcNLlRMzYN`OePzZN\u0000\u0000\u0000\t\u0004\u0000\\N`OdPfQgQgQhQhQhQiQiQiQiQiQiQjQjQjQjQjQjQkQkQkRkRkRlRlRlRlRlRlRmRa(`(`([\u0012a\u001ab\u001bd\u001ch!i\"d\u001da\u001b`\u001a_\u001b_\u001b^\u001b]\u001a]\u0019S\u0010\\']'_(nRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRlRlRlRlRlRlRlRlRlRlRlRlRlRkRkQiQePt:\u000b\u0000\u0000\u0000\u0000\u0000\u0000kQhQcP]OtVMlSMa2\r\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\n\u000f\u0018\u0012\u0013\u0018$\u001c\u001a5 \u000f`(e)nRjQ^OJAI\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XIK^KKdNLhPLuWM]ObPfQeP\r\u0006\u0001m6\n`OcPfQhQhQiQiQjQjQjQjQjQjQjQkQkQkQkRkRkRkRlRlRlRlRlRlRlRmRmRmRmRg)c(c(b(V\u0011c\u001be\u001di!i!d\u001db\u001b`\u001a`\u001a_\u001b_\u001b^\u001aQ\u0010]'_(`(f)nRnRnRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRmRmRmRmRnRmRmRnRmRmRmRmRkRhQG\u0015a0\tbPmRjQfQaP}[NrUMmSML$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\r#C\u0012\u0013\u0018\u0018\u0016\u0019, \u001b8&\u001cH.\u001fZ7 pRjQ{ZN\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QEJ[JK`LKdNLhQLqUM{ZN_OcPgQhQ\u0000\u0000\u0000\u0018\u000f\nbPePhQiQjQjQkQkQkRkRkRlRlRlRlRlRlRlRlRlRlRmRmRmRmRmRmRmRmRmRnRnRj*g)e)d)d\u001bX\u0011g\u001dh\u001fe\u001cc\u001bb\u001ab\u001bb\u001bU\u0011`(a(a(c(i*oRoRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRoRoRoRoRoRoRoRoRoRoRoRoRnRmRjQQ%Z-\tjQnRlRhQdP_OuWMpTMnSMkRLa: \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0013&D\u001b\u0017\u0019\u001e\u0019\u001a2\u001c\r@*\u001dS6#G@IPDJhQmSM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ]KKbMLeOLiQLlRMvWN\\OaOePhQjQgQ\u0007\u0003\u0000oTMgQiQkQlRlRlRmRmRmRmRmRmRmRmRmRmRmRmRmRmRnRnRnRnRnRnRnRnRnRnRnRnRl*l+j+g)f)e)d)e)e)e)e)f)i*s0s.oRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRpRpRpRpRpRpSpSpSqSqSqSqSpSqSpSnRlRI\u0011hQpRoRmRiQePaP\\OsVMpTMnTMlRMX)\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0011%C\u001a)D\u001d\u0018\u0019$\u001c\u001a;\u001d\u0005J/\u001f[8\"LBITGJYIKWHK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK_LKcNLgPLjQLlRMpUMzYN^ObPePhQkQlRfQ- \u001bhQjQlRmRnRnRnRnRnRnRnRnRnRnRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRpRpRpRp\u0016y-w-w-y.{-u\u001epSpSpSpSpSpSpSpSpSpSpSpSpSpSpSqSqSqSqSqSqSqSqSqSrSrSrSrSrSrSrSsSrSqSoRiQiQqSqSpRmRjQgQcP_O{ZNtVMpUMoTMmSMjQL_9 \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u000b\"C\u0017(D\u001b\u0017\u0019#\u001b\u001a*\u001f\u001bA$\u000e[<)d<!QEJWHKXHKD>I\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N_ObPePhQkRmRnRkR!-EkRmRnRoRpRpRpSpSpSpSpSpSpSpRpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSrSrSrSrSrSrSrSrSrSrSsSsSsSsStStStStStSuStSsSrSnRoRsSsSrSpRmRjQgQdPaO\\OyYNuWMqUMoTMnSMkRLo8\r\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0015'D\u001e+E$\u001c\u001a(\u001e\u001b1\u001b\u000bJ/\u001ejH1NCJUGJYIKUGJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\\N_ObPfPhQkQmRoRpSpRhQmRoRpSqSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSsSsSsSsSsSsSsSsSsSsSsSsStStStSuSuSuTuTuTuTuTvTwTvTvTuTtSmRtSuTuStSrSpRmRkQhQePaP^O\\N{ZNvXNqUMpTMnSMlRMP%\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u000e#C\u001b*E$.E- \u001b.!\u001bG$\u0007Y:%d<\"SFJYIKZIKNCJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\PDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN\\O`OcPfPhQjQmRoRqSrSrSrSmR\u0002\u0001\u0000rSsStStStStStStStStStStStStStStStSsSsSsSsSsSsSsSsSsStStStStStStStStStStStStStStStStSuSuSuTuTvTvTvTvTvTwTwTwTwTxTxTxTyTyUxU\\'qSvTwTwTvTuTtTrSoRmRkQhQePbP`O^O\\O|ZNxXNtVMpTMoTMmSMjQLh7\u0012\u0013\\\u0013\\\u0013\\\u0006 B\u0018(D\"-E*1F, \u001b4#\u001cK)\u000fpL5PEJWHK[JKXHK:9H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UGJ\\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O`OcPePhQjQlRnRpSqSsStSuStSsSmR^/\tvTvTvTwTwTwTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTwTwTwTwTwTwTwTxTxTxTxTxTxTxTyTyTzUzU{U{V|VgQrSwTxTyUyUzVyVxVvUtTqSoSmRjQhQePcPbP`O_O]O}[NyYNuWMpUMoTMmSMkRL}H#\u0013\\\u0013\\\u0002\u000b\u0017\u0012&D -E(1F/!\u001b2#\u001c8\u001d\tW7\"iA&UGJ[JK\\JKREJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N\\O^O`ObPePgQjQkRmRoRqSrStSuSvTvTwTwTuTsSlR_(yTyTyTyTyTyTyTyTyTyTxTxTxTxTxTxTyTyTyTyTyTyTyTyTyTyTyTyTyTyTyTzTzTzU{U{U{U|U|U}V~VWÀYiQrSwTyTzU|V}XZ]]]~[zYwWtUqSnSlRjQgQfPePcPbP`O_O]O~\\NzZNvXNqUMoTMnSMlRMiQLg=!\u0013\\\n!C\u001d+E'0F.4F7%\u001c8%\u001cU/\u0012lG.SFJZIK]KKZIKB=H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\REJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O^O`OaObPdPgQiQkQlRnRpSrSsStTuTvTwTxTyTyTyTyTyTxTvTrSnRhQ|U|U|U|U|U|U|U|U|U|U|U|U|U|U}U}U}U}U}U}U}U~U~U~V~VVŀWƁXa(lRrSvTyTzU|U~VXƂ[Ɇ_΋dӑjԓmԓnБlʌhĆd_{[vWsUpSnRkRiQhQgQfQePdPbPaO_O^O\\O|ZNxXNsVMpTMnTMmSMjQLC\u0015\u0006 B\u0019)D&/F-3F47G6%\u001c>\"\fY7 kA$YIK]KK^KKSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ\\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\\N]O_O`OaPbPcPePfPhQjQlRnRoSqTsTuUvUwVxVyVyUzUzU{U{U{U|U|U|U|U|U{U{U{UzUzTyTyTxTwTvTvTvTvTwTwTwTxTyTzTzU{U{U|U|U}UVŀWǂYɄ\\͈_ьdٔlu|쩂ﬅ명榁ޟ{՗sˎld^yZuWqUoSlRkRjQiQhQgQfQePdPcPaP`O^O]O}[NyYNuWMpTMoTMmSMkRLgPL\u0013&D#.E,3F46G;'\u001c<(\u001dD\"\u0007iB(VGJ]KK`LK[JKB>H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N\\O^O_O`OaPcPdPePfQgQhQiQkRmSoTrUtWwYzZ}\\]^^^^\\ZYX~W~W~V~V~V~V~U~U~U~UUUVVVVVƀVƀVǀWǁWȂXɃZ˅[͇^ЊaӍdؒiܗntz驅~֘vˏmÇf`z[vXrUpToSnSlRkRkRjQiQhQfQePdPcPbP`O_O]O~[NzYNvWNpTMoTMnSMkRMhQLo7\u000b,2F36G99HC+\u001d@ \u0006]8 nA\"\\JK`ML_LKSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N]O^O_OaObPcPdPePfQgQhQiQjRlRmSoUrWvZ{]afŊjˏnГqӕsՖsՖrՖqՔoӒmяjύg͊cˈaɆ^Ȅ\\ǂ[ƁYŀXŀWWWVVWŀWƀWǁXȂYɃ[ʅ\\͇_ϊaҍeՑhٕmݙqvz}꧀멃몄騃奀ߠ|ٛwӕȑmƉhc~^yZvXtWsVqUpToSnSmRlRkRjQiQhQgQfPePcPbPaO_O^O\\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*\u001dE$\ti@$ZIKaMLbML[JK;:H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\WHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\\N]O^O`OaObPcPdPePfQgQhQiQkRlSmToUrWuZy]~afl˒sԚzܡ㧆諉뮋묈訄~ߞyڙt֕oҐjΌfˈbȅ_ƃ\\ŁZĀYXW~W~W~WXÀXĀYŁZƃ\\ǅ^Ɇ`ˈb̊d͋f΍gΎiΎjΎj͎jˌiǉgÆda^}]|\\{[yZxYvXtWsVqUpToSnSmRlRkRjQiQhQgQfPePdPbPaO_O^O\\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-\u001eE&\u000eb;!YIK`MLdOM`LKNCJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\lRyT~UʂXʃYX{WtUW'[(hQlRcP\\OhQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\\N]O_O`OaPbPcPdPfPgQhQiQjRkRlSnTpUsWvZz]bglɑsИy؞ޤ㩊譍챐ﳑﳑ뭊穅⣀ݞzؘtғn΍iɉdƅ`Â][~Y}X|W|V{V{V{V{V{V|W|W}X}Y~Z~Z~Z}[}[}[~\\~\\~]~]~]~]}]|\\z[yZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPaP`O^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2\u001fP+\u0010XHK_LLfQOcNLXIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\qSyT~VΈ`遲ޜv]qSL\u0011G\u000e|>\fg3\nS)\b?\u001f\u0006*\u0015\u0004%\u0012\u0003.\u0017\u0004hQhQeP`OuWM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N\\O^O_O`OaPbPdPePfPgQhQiQjRkRlSnTpVsXvZz^bgËmʒsјz؟ޤ㩊譍ꯏ및ꯎ謋娇ं۞|֙wѓq̎lǉgÅb_\\}Z{XzWyVyUxUxUxTxTxUxUxUyVyVyWzW{X{Y|Z}[}[}\\~\\~]~]}]|\\{\\z[yZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPbP`O_O]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(\u000fh>!]KKfQOgQN_LKD>I\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\iQtSyT{UYΌeרּ՗u|\\Z'L\u000fD\r|>\f\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000ePoRqSoRmRjQeP^OhPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\WHJ\\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N]O^O_O`ObPcPdPePfQgQhQiQjRkRmSnTqVsXw[{_chČn˒tҙz؟ޥ㩉筍ꯎꯎꮍ竊䧆ߣ۞|՘vГpˎkǉfÅb_\\}Y{XzWyVxUxUxTxTxTxUxUxUxUyVyVzWzX{Y|Y|Z}[}[}\\}\\}\\}\\|\\{[zZyZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPbP`O_O^O\\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(\u000fV.\u0010]KKePNkUQcNLQEJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]OmRqSrStSvTwTxU{WĆbғqךxʏo\u0012\n\u0004\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000K\u0016rSvTwTvTuTsSqSnRkQgQ`OuWNY,\b\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O^O_OaObPcPdPePfQgQhQiQjRkRmSoTqVtXw[|_diČn˓tҙz؟ޥ㩉笌鮎ꮎ魌檉㧅ߢڝ{՗uϒpˍjƈfb^\\|Y{XzVyVxUxUxTxTxTxUxUxUxUyVyVyWzW{X{Y|Z|Z|[}[}\\}\\|\\|[{[zZxYwXvXtWsVrUpToSnSmRlRkRjQjQiQhQgQfPdPcPbPaO_O^O\\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\\JKcOMoXUgPMZIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPgQgQhQiQkQlRnRpRqSsStS\u0000\u0000\u0000\u0000\u0000\u0000:\"\u0010r<\u0010zYNsSyT|U~WƄ^ˊeˋgƈeaz[tVpSmRkQgQbPzYNkRL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\\N]O^O`OaObPcPdPePfQgQhQiQjRlRmSoUqVtYx\\|`diōo˓uҙ{ٟޥ㩉笌鮍鮍謋婈⦄ޡٜzԗtϑoʌjƈea^~[|Y{XzVyVxUxUxTxTxTxTxUxUxUxVyVyWzWzX{Y{Y|Z|Z|[|[|[|[{[z[yZxYwXvWtWsVrUpToSnSmRlRkRkRjQiQhQgQfPePdPbPaP`O^O]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\jQ`O{ZN^'^'`(e)h)k*o+b(nRyT~UǁXҍdw詅ݟ}Ԙvȍme}_x[y\\x[tWqTmRjQgQbP}[NlRM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ\\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\\O]O_O`OaPbPcPdPePfQgQhQiQjRlSmSoUrWuYx\\|`djōo̓uҚ{٠ޥ㩉欋譍譌竊婇᥃ݠ~؛yӖtΑoʌjňea^~[|Y{WzVyVxUxUxTxTxTxTxUxUxUxUxVyVyWzXzX{Y{Z{Z|Z|[|[{[{[zZyZxYwXuWtVsVrUpToSnSmRlRkRkRjQiQhQgQfQePdPcPaP`O^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\:9H\\NhQ}\\uUsTtTtSqSnRnRnRlRjQiQhQhQgQfQePePhQkRmSpUtXuYsWqUmSjQgQB\u000fS%jQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N\\O^O_O`OaPbPcPePfPfQgQhQiRkRlSnTpUrWuYy]}`ejŎp̔vӚ{٠ޤ⨉櫋笌笋櫊䨆ंܟ~ךxҕsΐnɌiŇea^~[|Y{WyVyVxUxUxTwTwTwTxTxUxUxUxVyVyWzWzXzY{Y{Z{Z{Z{Z{ZzZyZyYxYvXuWtVsUrUpToSnSmRlRlRkRjQiQhQgQfQePdPcPaP`O_O]O\\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ (6BFP>=DKHMqjktrwf`~kcndqesete{w`v[\\N_OcPfPiQjRlSoTqVqVoTlRiQ^\u0015`OQ%hPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O^O_O`OaPcPdPePfPgQhQiQjRkRlSnTpUrWuZy]}aekƎp̔vӚ{ٟޤ⨈媊櫋櫊婈⦅ߣ۞}֚xѕr͐mȋićda]~[|YzWyVyUxUxUwTwTwTwTwTxUxUxUxUxVyVyWzXzXzYzY{Y{Z{ZzZzZyYxYwXvXuWtVsUrUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbP`O_O]O\\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0010\b\u0001\u001a%5 (6\u001f$/79CEEKjgkrc_{uf{w_q]O`OcPfQhQjRlRnToTnTkRhQdP]'Q%\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]O^O_O`ObPcPdP['d)gQhQiQjRkRlSnTpUrWvZy]~afkƎp̔vӚ{؟ݤᧇ䩉媊媉䨇᥄ޡڝ|՘wДȑmȊhĆd`]}[|YzWyVxUxUxUwTwTwTwTwTwUwUxUxUxVxVyWyWyXzXzYzYzYzYzYyYyYxYwXvWuWtVsUqUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbPaO_O^O\\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\#*6+.8;:AHEJmgjd\\]pe}xcw^p^OaPePgQiQlRmSnTmSjRgQh*X&M$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\C+\u001dWHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\\N]O^O_OaObPcPY&_(c(gQhQiQjRkRlSnTpVsXvZz^~bfkƎp̔vҚ{؟ݣই㩉䩉䩈⧆ःܠ؜{ԗvϓqˎlǉgÆc`]}Z{YzWyVxUxUwUwTwTwTwTwTwTwUwUxUxVxVxVyWyWyXyXyYzYyYyYyYxYwXwXvWuVtVrUqUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbPaO_O^O\\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\\1\u000f\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\+.775;ICFphhztre}yavZ]OaPePgQiQkRlSnTlSiQq.b*S%zG#\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\\N]O^O`OaObPU&\\'a(g)r/hQiQjRkRmSnTpVsXv[z^~bfkƎp̔vҙ{מܣআ⨈㨈㨇ᦅޣ۟~כyӖuΒpʍkƉgc_]}Z{XzWyVxUxUwTwTwTwTwTwTwTwUwUwUxUxVxVxWyWyWyXyXyXyYyYxXxXwXvWuWtVsVrUqTpToSnSmRmRlRkRjQiQhQgQfQePdPcPbPaO`O^O]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\,)/ZTVXONuqod}ybs]OaPePgQiQkRlRlSkRhQg*\\(Q%`LK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\\O]O_O`OaOQ%Y&^'b(i*{8hQiQjRkRmSnTqVsXv[z^~bfkƎp̔vҙ{מۢߥᧇ⧇ᦆऄݢڞ}֚xҕt͑oɌjňfb_\\}Z{XzWyVxUxUwTwTwTwTwTwTwTwTwUwUwUxVxVxVxWxWyWyXyXxXxXxXwXwWvWuWtVsUrUqTpToSnSmRmRlRkRjQiQhQgQgQfPdPcPbPaP`O^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\HFLXQRTJH~pmla}zcttTaPdPgQiQjRlRlSjR|:e*V&N$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N\\O]O_O`OaPW&['_(d)l,݃@t.iQjRkRmSoUqVsXw[z^bgkƎp̔uљz֝~ڡޤॆআॅޣܠ؝{ՙwєs̐nȌjňfb_~\\|Z{XyWyVxUwUwTwTwTwTwTwTwTwTwUwUwUwUwVxVxVxWxWxWxWxXxXwXwWvWuWuVtVsUrUqTpToSnSmRlRlRkRjQiQhQhQgQfPdPcPbPaP`O^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O+O+O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\6./fZXeVRHAIZIKiQLuWMtUaOdPgQjQkRlRkRiQn/b,R%rC\"\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\"Fx\"Fx!Fx!Fx\u0006 B\u0006 B\u0006 BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N\\O^O_O`OS%X&\\'a(g+s2{9j*iQjRkSmSoUqVsXw[z^bgkƎp˓uИy՜}٠ܢޤߤޣݡڟ~כzӗvϓrˏmǋićea^~\\|ZzXyWxVxUwUwTwTwTwTwTwTwTwTwTwUwUwUwUwVwVxVxWxWwWwWwWwWvWvWuVtVsUsUrTqTpToSnSmRlRlRkRjQiQhQgQgQfPePcPbPaP`O_O]O~\\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL\u0005\t\u000f+O+O+P+P+P\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@89dWT@<HE?IXHKiQLvWN]ObPePhQjQlRlRkRp+f*[)O$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\:^:^:^:^\"Fx\"Fx\"Fx\u0006 B\u0006 B\u0006 B\u0006 BeOLhPLjQLlRMnSMoTMqUMrUMuWMxXN{ZN~[N\\O^O_OO$V&Z']'d+g+}<h*hQiQjRkSmSoUqVtYw[z_bgkōpʒtЗyԛ}؟ۡݣݣܢ۠؝|՚yҖuΒpʎlƊhÆda^~[|YzXyWxVxUwUwTwTwTvTvTvTvTvTvTvTwUwUwUwUwVwVwVwVwWwWwWvWvWuVuVtVsUrUqTqTpSoSnSmRlRlRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNxXNtVMpTMlRMjRLiQLgPLcNL\\JK+P+P+P+P+P+P,P\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\D::hZUC>IIAI\\JKlRMyYN^OcPgQiQkRlRkRiRt3d-S%I#\u0013\\\u0013\\\u0013\\:^:^:^:^:^:^:^:^:^\"Fx\"Fx\u0006 B\u0006 B\u0006 B\u0006 BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N]O^O_OS%W&['^(k2i+{:gQhQiQjRkSmToUqVtYw[{_bfkčoʒtϖxӚ|ם~٠ۡۡ۠ٞ~כ{ԘwДs̐oɌkŉgc`]}[{YzXyVxVwUwUwTwTvTvTvTvTvTvTvTvTvUvUvUwUwUwVwVwVwVvVvVvVuVuVtVtUsUrUqTpTpSoSnSmRlRlRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P+P+P,P,P,P,P,PNr\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]QNl\\VG@IMCI_LKoTM|ZN`OdPgQjQkRlRkRhQh*^,P%X3\u0019:_:_:_:_:_:_:_:_:^:^:^:^\"Fx\u0006 B\u0006 B\u0006 B\u0006 BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N]O^OP%U&X&['`)n4n/j*gQhQiQjRkSmToUqWtYw[z^~bfjČoɑsΕwҙ{՜}؞ٟڟٞ~ל|՚yҗvϓrˏnǋjĈfc`]}[{YzWxVxUwUwTwTvTvTvTvTvTvTvTvTvTvTvUvUvUvUvUvVvVvVvVvVuVuVuVtUsUrUrTqTpToSoSnSmRlRkRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P,P,P,P,PNrNrNrNrNrNr\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aSOD>IJAIQEJbNLrUM~[NaOePhQjQkRlRjRs0e,T&K$;_;_;_;_;_;_;_:_:_:_:_:_:_\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]OM$S%V&Y&\\'e-j/z:fQgQhQiRjRkSmToUqWtYw[z^~bfjÌnȐr͔vјyԛ|֝~מ~؞~ם}՛{ӘxЕt͒qʎmƊiÇeb_~\\|Z{YyWxVxUwUwTvTvTvTvTvTvTvTvTvTvTvTvTvUvUvUvUvUvUvVvVuVuVuVtUsUsUrUqTqTpSoSnSnRmRlRkRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P,PNrNrNrNrNrNrNrNsNsNsNs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\dUOG@IMCITFJeOLtWM]ObPfPiQkRlRkRiQj,c/P%[JK;_;_;_;_;_;_;_;_;_;_;_;_\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#Q%T%W&Z']'m5f*v5fQgQhQiRjRkSmToUqWsYv[z^~beinǏq˓uϖxҙzԛ|֜}֜|՛{ԙyіvϓs̐oȍlŉhea_~\\|ZzXyWxVwUwUvTvTvTvTvTvTvTvTvTvTvTvTvTvTvUvUvUuUuUuUuUuUtUtUtUsUrUrTqTpTpSoSnSmRmRlRkRjRjQiQhQgQfQfPePcPbPaP`O_O^O\\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNrNrNrNrNrNsNsNsNsOsOsOsOsOsOs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\2#\u001cTB<JBIODJXHKiQLxXN^OcPgQjQlRlRkRo,d+U'L$;_;_;_;_;_;_;_;_;_;_;_\u0007\u000b\u0011\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRMmSMoTMpUMrUMsVMtVMyYN|ZN~[NO$S%U&X&['_(s;h+`\u001afQgQhQiRjRkSmToUqWsYv[z^}aeimŎpʒt͕wЗyҙzӚ{Ԛzәyїwϔt͒qʏnǋjĈgda^}\\{ZzXyWxVwUwUvTvTvTvTvTvTvTvTuTuTuTuTuTuTuTuUuUuUuUuUuUtUtUtUsUsUrTqTqTpSoSoSnSmRmRlRkRjQjQiQhQgQfQePdPcPbPaP`O_O]O\\O|ZNyYNuWNqUMmSMiQLhPLfOLdNL`LKkPANrNsNsNsNsOsOsOsOsOsOsOsOsOsOsOs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\#Gy#GybSNP<3NCJRFJ^LKoTM}[NaOePiQkQlRlRiQm-g2Q%]8 ;_;_;_;_;_;_;_;_;_;_\u0014!2\u0006 B\u0006 B\u0006 B\u0006 BgPLjQLlRMmSMoTMpUMrUMsVMtVMyYN|ZNM$Q%T%V&Y&['b+q8r3ePfQgQhQiRjRkSmToUqVsYv[y^}adhlčoȐr˓uΖwЗxјyјxїwϕu͒rːpȍlŊifc`~]|[{YyXxWwVwUvUvTvTvTvTuTuTuTuTuTuTuTuTuTuTuTuTuTuUuUtUtUtUtUsUsTrTrTqTqTpSoSoSnSmRlRlRkRjQiQiQhQgQfQePdPcPbPaP`O_O]O\\N|ZNyYNvWNqUMmSMiQLhPLfOLdNL`LKZIKNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOtOt\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d#Gy#Gy#Gy#Gy#GyhVPKBIQEJUGJeOLtVM]ObPgQjQlRlRkRgQd*X)N$;`;`;`;`;`;`;`\"Gy\"Gy\"Gy\u0014!2\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMsVMtVMyYNK$P%S%U&W&Y&\\'i2h.x8ePfQgQhQiQjRkSmTnUqVsXv[y]|`dgkËnƏqʒs̔uΕvϖwϖvΕu͓sˑqɎnƋkÈheb_~]|[zYyWxVwVwUvTvTvTuTuTuTuTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTsTsTrTrTqTqTpSpSoSnSnRmRlRkRkRjQiQiQhQgQfQePdPcPbPaP`O_O]O\\N|ZNyYNuWNqUMmSMiQLgPLfOLcNL`MKZIKOsOsOsOsOsOsOsOsOsOsOsOsOtOtOtOtPtPtPtPt\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvv#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GyYE<NDJTFJYIKkRLyYN_OdPhQkQlRlRjRo.h2R%c; <`<`#Gy#Gy#Gy#Gy\"Gy\"Gy\"Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMqUMrUMsVMtVM~I#N$R%T%V&X&Z'^(q9e*j+ePfQgQhQiQjRkSmTnUpVsXuZx]|`cfjmōpȐrʒt̓u͔u͓t̒sˑqɏoǌlĊifda^}\\{ZzXxWwVwUvUvTvTuTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTtTtTsTsTsTrTrTrTqTpSpSoSoSnSmRmRlRkRkRjQiQhQhQgQfQePdPcPbPaO`O_O]O\\N|ZNyYNuWNqUMmSMhQLgPLeOLcNL`LKZIK,P,POsOsOsOsOsOsOsOtOtOtOtPtPtPtPt-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvvv=a#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GygUOT>3REJVGJ`LKpTM}[NaOePiQkRlRlRhQe)^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMsVMxF#M$Q%S%U&W&Y&['a+s;g+dPePfQgQhQiQjRkSlSnUpVrXuZx]{_~beikÌnƎpȐrʑs˒sˑrʐqɏoǍmŋkÈheb`~^|[{ZyXxWwVvUvUvTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTtTtTsTsTsTsTrTrTrTqTqSpSpSoSnSnRmRlRlRkRjQjQiQhQgQgQfPePdPcPbPaO`O^O]O\\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,P,P,QOsOsOtOtOtOtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvvvvww=a=a=a#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM]OcPgQjQlRmRkRp.g0T&N$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMv>\u0013L$P%R%T%V&X&Z'\\'f0m5q3dPePfQgQgQhQjRkSlSnTpVrXtZw\\z_}adgjlČnƎpǏqȏqȏpǎoƍmŋkÉigda_}]|[zYyXxWwVvUvUuTuTuTuTuTuTuSuStStStStStTtTtTtTtTsTsTsTsTsTrTrTrTqTqSpSpSoSoSnSmRmRlRlRkRjQjQiQhQgQfQfPePdPcPbPaO`O^O]O~\\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Q,Q,Q,Q,QOtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvwwwwwwww=a=a=a=a=a#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN`OePiQkRmRlRiQh*h4R%N$^9 [JK#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMI#L$O$Q%S%U&W&X&Z'](l5f,t5dPePfPfQgQhQiRkRlSmToVqWtYv[y^|acfhklÌnōnōoōnŌmċkigec`~^|\\{ZyYxWwVvUvUuTuTuTuTuTtStStStStStStStStStStSsSsTsTsTsTrTrTrTrSqSqSpSpSoSoSnSnRmRmRlRkRkRjQiQiQhQgQfQePePdPcPbP`O_O^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Q,Q,Q,Q-Q-Q-QPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@dwwwwwwwwwwwwww=a=a=a=a=a=a=a#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\\NbPfQjQlRmRlRp,e+\\+R%N$b; ]8 [7 XHKO+\u000fN1\u001eL/\u001eL/\u001eL/\u001eK/\u001eK/\u001e\u0002\u000b\u0017e<!J#{=\fJ$L$N$O$P%S%T%V&X&Y&['`+m7d)h*dPdPePfQgQhQiRjRlSmToUqWsYv[x]{`~begijllËlÊlkihfca_}]{[zYxXwWwVvUuUuTuTuTtTtTtStStStStStStStStSsSsSsSsSsSsSrSrSrSrSqSqSqSpSpSoSoSnRnRmRlRlRkRjQjQiQhQhQgQfQePdPcPbPaP`O_O^O]O~[NzZNwXNtVMpTMgPLfOLeOLcNLaMK^KKbE6,Q-Q-Q-Q-Q-QPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-R-R\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@d@d@dwwwwwwwwwwwxx=b=b=b=b=b=b=b=b#Hz#Hz#Hz#Hz=a=agUOS=2RFJWHKZJKiQLvXN^OcPhQkRmRmRkRm-j3W(R%O$e<!c; a: ^9 ]8 [7 X6\u001fX6\u001fX6\u001fK$M$_(yF#U&N$N$O$P%R%S%U&W&X&Z'\\(d.j2f*bPcPdPePfQgQhQiRjRkSmTnUpWsXuZw\\z_}acegijjjjigfdb`~^|\\zZyYxXwWvVuUuUuTtTtTtTtStStStStStStSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSpSpSoSoSnRnRmRmRlRkRkRjQiQiQhQgQgQfPePdPcPbPaP`O_O^O\\O}[NzYNwXNsVMoTMgPLfOLdOLcNL`MK]KKaE6-Q-Q-QPtPtPtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-R-R-R-R-R-R-R\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@d@d@d@e@e@e@e@ewwwxxxxxxxx>b>b>b>b>b>b>b>b=b=b=b=b=b=b=b=bYE<bJ>UGJYIK_LKnSM|ZN`OePiQlRmRmRiQg*j4W'R%Q%h>!g=!f=!d<!c; b; `: N$`(b(d)f)|H#X&X&W&Q%R%T%V&W&Y&['](d.e,n1bPcPdPePfQgQhQiRjRkSlTnUpVrXtZv\\y^{`~bdeghhhhgfdba~_|]{[yZxXwWvVvUuUuTtTtTtTtStStStStStSsSsSsSsSsSsSsSsSrSrSrSrSqSqSqSqSpSpSoSoSnRnRmRmRlRlRkRkQjQiQiQhQgQfQfPePdPcPbPaO`O^O]O\\O}[NyYNvWNrVMoTMfOLeOLdNLbML`LK\\KKaE6PtPtPtPtPtPtPtPtPuPuPuQuQu-Q-Q-Q-Q-Q-Q-Q-Q-R-R-R-R-R-R-R-R-R.R.R~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@e@e@e@e@e@e@e@eAeAeAexxxxxxxxxx>b>b>b>b>b>b>b$Hz$Hz$Hz$Hz$Hz>b>b>b>b>bgVOS=2RFJWHK[JKeOLsVM]ObPgQjQlRmRlRr/g*h2U&S%R%Q%Q%P%[']'`(b(d)f)g)i*j*I#Z'Z'Z'Z'Z'['['\\']'_)d,d)q3bPcPdPePfQfQgQhQiRkSlSmUoVqWsYu[x]z^|`~bdeffffedba~_}^{\\zZyYwXwWvVuUuUtTtTtTtStStSsSsSsSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSpSpSpSoSoSoRnRnRmRmRlRkRkRjQjQiQhQhQgQfQePdPcPcPbP`O_O^O]O\\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6PtPtPtPtPtPuPuPuPuQuQuQuQuQuQu-Q-Q-Q-R-R-R-R-R-R-R-R-R.R.RRvRvRv~~~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@e@e@e@eAeAeAeAeAeAeAeAeAeAeAexxxxxxxyy>b>b>b$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>b>bYD<W?3UGJYIK\\JKjRLxXN_OdPhQkRmRmRkRp.h,f/[(X&X&Z'\\'^'`(c(e)g)i*j*l*m*o+\\'\\'\\'\\'\\']']'^'_(a)c*e*i+bPcPdPdPePfQgQhQiRjRkSmTnUpWrXtZv[x]z_|`~bcddddcba~_}^{\\z[yZxXwWvVuUuUtTtTtTtTsSsSsSsSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSqSpSpSpSoSoSoRnRnRmRmRlRlRkRkQjQiQiQhQgQfQfPePdPcPbPaP`O_O^O]O~[N{ZNxXNtWMqUMmSMiQLcNLbML`LK^KKbR_D5PtPtPuPuPuPuQuQuQuQuQuQuQuQuQuQuQu-R-R-R-R-R-R-R.R.RRvRvRvRvRv~~~~~~~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeyyyyyyyAe$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>bQ@:R<2fL@WHJZJKaMKoTM|ZN`OePiQlRmRmRjRo-i-h0`)]']'`(b(d)f)h)j*k*m*n+p+q+r,]']']'^'_(_(`(`(b)c)i.`OaPbPcPdPePfQgQhQiRjRkSlTnUoVqWsYuZw\\y]{_|`}a~bbbba~`}_|^{]z[yZxYwXvWuVuUtUtTtTsTsSsSsSsSsSsSsSsSsSrSrSrSrSrSrSrSqSqSqSqSpSpSpSoSoRoRnRnRmRmRlRlRkRkRjQjQiQhQhQgQfQePdPdPcPbPaO`O_O]O\\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5PuPuPuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQv-R-R.R.R.RRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeyyyAfAfAf$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>bWD<V>3TFJXHK[JKfOLsVM]ObPgQjQlRmRmRkRm,i,j/d+c)c(e)f)h*j*l*n+o+q+r+s,t,K$^(_(_(`(a(a)b)d*f+m1`OaPbPcPdPePfQfQgQhRiRkSlTmToVpWrXtYv[w\\y]z^{_|`}`}`}`}_|^{^{\\z[yZxYwXvWuVtUtUtTsTsTsSsSsSsSsSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSpSpSpSoSoRoRnRnRmRmRmRlRlRkRjQjQiQiQhQgQfQfPePdPcPbPaP`O_O^O]O\\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\\JK~aR[B5PuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAfAfAfyAfAfAfAfAfBf$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c>c>b>bO?:[E<dK?UGJYIK\\KKjRLxXN^OcPhQkQlRmRmRt.q.j+k-i,h*h*j*k*l*n+p+q+s,t,u,v,w,`(`(a)b)c*d+f+g,k0m1`OaObPcPcPdPePfQgQhQiRjRkSlTnUoVqWsXtZv[w\\y]z^z^{^{^{^{^z]z\\y[xZwYvXvWuVtVtUsTsTsTsTsSrSrSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSpSpSpSpSoRoRoRnRnRmRmRmRlRlRkRkQjQiQiQhQgQgQfQePePdPcPbPaP`O_O^O\\O~[N{ZNxYNuWNqUMmSMiQLeOLaMK_LK]KKlN>|aRZA5-QQuQuQuQuQuQuQuQuQuQuQvQvQvQvRvRvRvRv.R.R.R.RRvRvRvRvRvRw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAfAfAfAfAfyyyzzzBfBfBfBfBf$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c>c>c>cVC<T=3}cVWHJZIKaMLoTM|ZN`OePhQkQlRnRnSt.v2m+l+l+l+m+n+o+p+r+s,u,u,v,w-x-y-b*c+e,g-i/k0m2p4i-_O`OaPbPcPdPePfQfQgQhRiRjSlTmTnUpVqWsYtZv[w[x\\y]y]y]y]y\\y\\x[xZwYvXuWuWtVtUsUsTsTrTrSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSqSpSpSpSpSpRoRoRoRnRnRmRmRmRlRlRkRkQjQjQiQhQhQgQfQfPePdPcPbPaP`O_O^O]O\\O}[NzYNwXNtVMpTMlRMhPLdNL`LK^KKmO?kN>^C6W@5-Q-QQuQuQuQuQuQuQvQvQvQvRvRvRvRv.R.R.R.R.R.R.R.R.RRvRwRwRwրրրրրրրրրրր\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AfAfAfAfAfAfAfAfzzzzzzzzzzzBfBfBfBf$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz\u0007\u000b\u0011YE<W?4gYXHKZJKfOLsVM\\NaOePiQkRmRnSnSmS|7s/o,o,p+q+r,s,t,v,w-x-y-z.{/|/e-g/j1m3o5o5r7n3c)_O`OaPbPcPdPdPeQfQgQhQiRjRkSlTmUoVpVqWsXtYuZv[w[w[w[w[w[wZwZvYvXuWtWtVsUsUsTrTrTrSrSrSrSrSrSrSqSqSqSqSqSqSqSqSqSpSpSpSpSpRoRoRoRnRnRnRmRmRmRlRlRkRkQjQjQiQiQhQgQgQfQePdPdPcPbPaO`O_O^O]O~[N{ZNyYNvWNsVMoTMkRLgPLbML^LKnP?lO?iM>\\C6T>4-Q-Q-Q-RQuQuQvQvQvQvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.RRwSwրրրրրրրրրրրրրրրրրEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AfAfBfBfBfzzzzzzzzzzzzzzzBfBfBf$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c?c?c?c$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN\\OaPfPiQlRmRnSnSpT99w2w0v/v.x/z0z0|1~235688m4o7q8u;s9s8j0]O^O_O`OaPbPcPdPePfQfQgQhRiRjSkSlTnUoVpVqWrXsYtYuYuZuZvZvYuYuXuXtWtVsVsUsUrTrTrTrSqSqSqSqSqSqSqSqSqSqSqSqSqSqSpSpSpSpRpRoRoRoRoRnRnRnRmRmRmRlRlRkRkRjQjQiQiQhQgQgQfQePePdPcPbPaP`O_O^O]O\\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R-R-R-R-R-RQvRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R׀׀׀׀׀׀׀׀׀׀׀׀׀׀׀EiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\Bfzzzzzzzzzzzzz{{{{{{BfBfBf%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c?c?c?c?c?c?c?c?c$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN]ObPfQiQkRmRnSpTqUrU;>?<9;==>ADHKEr:t;t;t<t:n4f,]O^O_O`OaObPcPcPdPePfQgQhQiRjRkSlSmTnUoVpVqWrWrXsXtXtXtXtXtXtWsWsVsVrUrUrTqTqTqSqSqSqSqSqSqSqSqSqSqSpSpSpSpSpSpSpRpRoRoRoRoRnRnRnRnRmRmRmRlRlRkRkRjQjQiQiQhQhQgQfQfPePdPcPcPbPaO`O_O^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNLgUeUlO?~bT{`SW@5-R-R-R-R-R-R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.REiEiEi׀׀׀׀׀׀׀׀׀׀׀EiEiEiEiEiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\zzzzzzzz{{{{{{{{{{{{{BgBgBg%I{%I{%I{%I{%I{%I{%I{@d?d?d?d?d?d?d?d?d?c?c?c?c$I{$I{L=:WD<v_TgZuZLWHKYIKmSMyYN^OcPfQiQkQmRnSpTqTsVwX8CIJNRTUVZ_Su=t=s;q9o6h.a)\\O]O_O_O`OaPbPcPdPePeQfQgQhRiRjRkSlTmTnUoUpVpVqWrWrWrWrWrWrWrVrVrUrUqUqTqTqTqSqSpSpSpSpSpSpSpSpSpSpSpSpSpRpRpRoRoRoRoRoRoRnRnRnRmRmRmRlRlRlRkRkQjQjQiQiQhQhQgQfQfPePdPdPcPbPaP`O_O^O]O\\O}[NzYNwXNtWMqUMnSMjQLeOLiVfUeUcT|bTcK>`KA-R-R-R.R.R.R.RRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.REiEiEiEiEiEiׁׁׁׁׁׁEiEiEiEiEiEiEiEiEiEiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\zz{{{{{{{{{{{{{{{{{{{|CgCg%I{%I{%I{@d@d@d@d@d@d@d@d@d@d@d@d?d?d?d?d?d?d$I{$I{dUPYE<xaVlSGw]OVHJbMLoTMzYN^OvRePhQjQmRnRpSqTuVyZ{[^acʌiΏlђnX_aSUq:n7k3h0c*^(\\N]O^O_O`OaObPbPcPdPePfQfQgQhRiRjRkSlSmTmTnUoUpVpVqVqVqVqVqVqUqUqUqTqTpTpTpSpSpSpSpSpSpSpSpSpRpRpRpRpRpRoRoRoRoRoRoRoRnRnRnRnRmRmRmRlRlRlRkRkQjQjQiQiQhQhQgQfQfPePdPdPcPbPaP`O_O^O]O\\O~[N{ZNyYNvWNrVMoTMlRM|WBwUAhVfVlO@~cTzaTaI>XG@-R.R.R.RRvRvRvRvRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.SEiEiEiEjEjEjEjEjׁׁEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\{{{{{{{{{{{{{{|||||||||Cg@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d?d$I{$I{RA;P<3zcXnVIuh~pdNLpUMwzZvSePgQjQlRmRoSpTuVvWxY|\\_ÆdƉgȊhʌi̎kΏlRFk4g1d-b+_(Z'}[N\\O]O^O_O`OaPbPcPcPdPeQfQgQgQhRiRjRkSkSlTmTnTnUoUoUpUpUpUpUpUpTpTpTpTpSpSoSoSoSoSoSoSoRoRoRoRoRoRoRoRoRoRoRoRoRnRnRnRnRnRmRmRmRlRlRlRkRkRkQjQjQiQiQhQhQgQgQfPePePdPcPbPbPaO`O_O^O]O~\\N|[NzYNwXNtVMpUMpYoXzWBuUBgVlP@jO@|bUx`TcMB3!\u0014.RRvRvRvRvRvRvRvRvRvRvRwRwRw.R.R.R.R.R.R.R.R.R.S.S.SEjEjEjEjEjEjEjEjEj؁EjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEj\u0013\\\u0013\\\u0013\\\u0013\\Bg{{{{{{{||||||||||||CgCgCgCg|@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d%I{;0/SB;R=4fODpXLxkrvbzx{[ÏldPgQiQjQlRnRpSqTrTtUwW{Z}\\|\\}\\~]]}+~6d.a+_)^(\\'zYN|ZN~\\N]O^O_O_O`OaPbPcPdPdPeQfQgQgQhRiRjRjSkSlSlTmTmTnTnTnToToToToToToSoSoSoSoSoSoSoRoRoRoRoRoRoRoRoRoRoRoRnRnRnRnRnRnRmRmRmRmRlRlRlRlRkRkQjQjQjQiQiQhQhQgQgQfQePePdPcPbPbPaO`O_O^O]O\\N}[NzZNxXNuWMrUMrZpY|XCxVCsTBmQAkOA~cVzaU`I>\\IARvRvRvRvRvRvRvRvRvRvRwRwRwSwSwSwSw.R.R.R.R.R.S.S.S.SFjFjFjFjFjFjFjFj؂؂؂؂؂FjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFj\u0013\\\u0013\\Bg{||||||||||||||CgCgCgCgCgCgCgCg}@e@e@e@e@e@e@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d%I{<1/J82^I@gQFqYNxlsvc{dy{\\wUčiePgQhQkQmRmRnRoSpSrTtUtUtUtUtUtUt.L&](['Z'Y&xYN{ZN}[N\\N]O^O_O`OaOaPbPcPdPePeQfQgQgQhRiRiRjRkSkSlSlSmSmSmSnSnSnSnSnSnSnSnSnSnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRlRlRlRlRkRkRkQjQjQiQiQiQhQhQgQfQfPePePdPcPbPbPaO`O_O^O]O\\O}[N{ZNxYNvWNsVMs[rZ~ZDnYkYqSBkPAiOA|cVbK?\\G>NB?RvRvRvRvRvRvRvRvRwRwRwSwSwSwSwSwSwSwSw.S.S.S.S.S.SFjFjFjFjFjFj؂؂؂؂؂؂؂؂؂؂FjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjCgCg|||||||||||CgCgCgCgCgCgCgCgCgCgCgCg}AeAeAe@e@e@e@e@e@e@e@e@d@d@d@d@d@d@d@d@d@d%I{@d@d<1/H72\\I@ePGpYNxmtvc{ezupwUuQePgQiQjQjQlRmRnRnRoRoRoRoRoRg\u001cb; Z'Y&W&S%vXNyYN{ZN~[N\\O]O^O_O`OaOaPbPcPdPdPeQfQgQgQhQiRiRjRjRkSkSlSlSlSlSmSmSmSmSmSmRmRmRmRmRmRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRmRmRmRlRlRlRlRkRkRkQjQjQjQiQiQhQhQgQgQfQfPePdPdPcPbPbPaO`O_O^O]O\\O}[N{ZNyYNvXNtVMu\\]E[EoZmZkYnRBjOB}cVdL@`I?XGARvRvRvRvRvRvRwRwRwRwSwSwSwSwSwSwSwSwSwSwSw.S.S.S.S/SFjFjFjFjققققققققققققققFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjقCgCg|||||||CgCgCgCgCgCgCgCgCgCgCgCgChChChChCh}AeAeAeAeAeAeAeAeAe@e@e@e@e@e@e@e@d%I{%I{%I{%I{%I{@d@d<10F61o]Vye]oexmuud{e}d|atpÏluQdPePfQgQiQjQjQjQjQjQkQkQkQ_9 X&V&T%rUMuWMwXNzYN|ZN~[N\\O]O^O_O`OaObPbPcPdPdPeQfQfQgQhQhRiRiRjRjRkRkRkRlRlRlRlRlRlRlRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRlRlRlRlRlRkRkRkRkQjQjQjQiQiQiQhQhQgQgQfQfPePdPdPcPbPbPaO`O_O^O]O\\O~[N{ZNyYNwXNtVMrUM^F]Fq\\o[lZqTDfX}dWeMAbK@O=6NB@RvRvRvRvRwRwRwRwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSx/S/SFjFjFjككككككككككككككككككFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjكككCgCgCg}}}CgCgCgCgCgCgCgCgChChChChChChChChChChDhDhDh~AeAeAeAeAeAeAeAeAeAeAeAeAe%I{%I{%I{%I{%I{%I{%I{%I{%I{@d@dE:9D61m\\Vwe]lXOuaXk_z||e|c|`z]yXnÏlĎkĎidPePfPfPfPfPfPfPfP[7 U&T%P%pTMsVMuWMxXNzYN|ZN~[N\\O]O^O_O`OaObPbPcPdPdPePeQfQgQgQhQhQiRiRjRjRjRkRkRkRkRkRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRkRkRkRkQkQjQjQjQiQiQiQhQhQgQgQfQfPePePdPdPcPbPbPaO`O_O^O]O\\O~[N|ZNyYNwXNuWMrUM`G^Gr]|ZFxXFtVEgY~eY{cXbLA[H?REA.R.RRvRwRwRwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxSxTxTxTxككككككككككككككككككككككككFjFjFjFjFjFjFjFjFjFjFjكككككCgCg}}CgCgCgCgChChChChChChChChChDhDhDhDhDhDhDhDhDhDh~AeAeAeAeAeAeAeAeAe%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e@eB99B51k[Vud]iWPr_Wye]y|}|e|cw{^z\\yZpxWwUwUwUwUÎlÎlllkD(S%P%nSMoTMqUMsVMvWNxXNzYN|ZN~[N\\O]O^O_O`OaOaPbPcPcPdPePeQfQfQgQgQhQhQiQiRiRjRjRjRjRkRkRkRkRkRkRkRlRlRlRlRlRlRlRlRlRlRlRlRkRkRkRkRkQkQkQjQjQjQjQiQiQiQhQhQgQgQgQfQfPePePdPcPcPbPaPaO`O_O^O]O\\O~[N|ZNyYNwXNuWMrUMw_v_t^~\\GzYGvWFj[fZ|dYybX\\I@VGB5/2.R.R.R.RSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxSxTxTxTxTxFkFkFkFkڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃFkFkFkFkFkFkFkFkڃڃڃڃڃڃڃ}}}}ChChChChChChChDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDh~AeAeAeAeAe%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e@e<68?31gYVpa\\bRMjYTq`Zj`z}}|{zxwz^tsssrrrrh2O$L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N\\O]O^O_O`OaOaPbPcPcPdPdPePeQfQfQgQgQhQhQhQiQiQiQiQjQjQjQjQjQkQkQkQkRkRkRkRkRkRkRkRkRkQkQkQkQjQjQjQjQjQjQiQiQiQhQhQhQgQgQgQfQfPePePdPdPcPbPbPaP`O`O_O^O]O\\O~[N|ZNyYNwXNtWMz`y`w`u_]I|[HwXGl\\i[}eZycYr_WjZU;23.R.R.R.R.R.R.RSwSwSwSwSwSwSwSwSxSxSxTxTxTxTx/S/SGkGkGkGkGkGkGkڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃGkGkGkڃڃڃڃڃڃڃڃڃڃ}}}}~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhAf%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{AeAeAe?89H=<gZXpb_aSPi[Vud]x{ufwfyf||{yyzbzbzayayaya^=%V)kRLlRMmSMmSMnSMoTMoTMvWNxXNzYN|ZN~[N\\O]O^O_O`O`OaPbPbPcPdPdPePePfQfQfQgQgQhQhQhQhQiQiQiQiQiQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQiQiQiQiQiQhQhQhQgQgQgQfQfPePePdPdPcPcPbPaPaO`O_O^O^O]O\\O}[N{ZNyYNwXNtVM{bzaxawa_J~\\IyZItWHj]g[dNDr`Xj[VOCB.R.R.R.R.R.R.R.R.SSwSwSwSwSxSxSxSxTxTxTxTx/S/S/SGkGkGkGkGkGkGkGkGkڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄGkڄڄڄڄڄڄڄڄڄڄڄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDh%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|AeAeAe4285.0G??g\\[XMK`TRg[Yyt{h`lbodreufvfwfwewe{{{zzbD.T+\\EkRLkRMlRMmSMnSMnSMsVMvWNxXNzYN|ZN~[N\\O]O^O_O_O`OaOaPbPcPcPdPdPePePfQfQfQgQgQgQhQhQhQhQhQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQhQhQhQhQgQgQgQfQfQfPePePdPdPcPcPbPbPaP`O`O_O^O]O]O\\N}[N{ZNyYNvXNtVMfLdLcLbLvbtar`o_pVHkSGcOE]KDj[WNCB\u0000\u0000\u0000.R.R.R.R.R.S.S.S.S.S.SSxSxSxSxTxTxTx/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄGkGkGkGkGkڄڄڄڄڄڄڄڄڄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDi&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|AeAeAe\u001a\u0015\u0014-*.3-0G@Ae\\]jabs`Ssjk|qovrtd_{halcmcmcncncyyyy\\A.~ZE[F]G^GkRLlRMlSMmSMqUMsVMuWNwXNyYN{ZN}[N\\O]O]O^O_O`O`OaPaPbPcPcPdPdPdPePePfQfQfQgQgQgQgQhQhQhQhQhQhQhQiQiQiQiQiQiQiQiQiQhQhQhQhQhQhQgQgQgQgQfQfQfPePePePdPdPcPcPbPbPaPaO`O_O_O^O]O\\O~[N|ZNzYNxXNvWNsVMgNfMdMcMwcubsbparWIkSHbOF]KEj\\X_UT@<?.R.R.R.R.S.S.S.S.S.S/S/S/S/STxTxTx/S/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkۄۄۄۄۄۄۄۄۄۄۄۄۄۄGkGkGkGkGkGkGkGkGkۄۄۄۄۄۄۄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDiDiրրրEiEi&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|('.,*/>:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsqtqr_=1+xJ)o[~[F\\G^H_I`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\\N\\O]O^O_O_O`O`OaPbPbPcPcPcPdPdPePePePfPfQfQfQgQgQgQgQgQgQgQhQhQhQhQhQhQhQhQhQgQgQgQgQgQgQfQfQfQfPePePePdPdPdPcPcPbPbPaPaO`O_O_O^O]O\\O~\\N}[N{ZNyYNwXNuWMiOhOgOeOzeydwdtcrbtYKjTIaOG[KFj]Y^UU?;@.R.R.S.S.S.S.S.S/S/S/S/S/S/S/S/S/S/S/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkۅۅۅۅۅۅۅۅۅۅGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅۅۅDhDhDhDhDiDiDiDiDiրրրրրրրրրրրEiEi&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|AfAeAe%J|%J|%J|%I|%I|%I|%I|\u0000\u0000\u0000\u001f#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%\u001e\"\u001d\u001blYn[p\\r]]H_I`JwaybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\\N]O]O^O_O_O`OaOaPaPbPbPcPcPdPdPdPePePePePfPfPfQfQfQfQfQgQgQgQgQgQgQgQgQfQfQfQfQfQfPfPePePePePdPdPdPcPcPcPbPbPaPaO`O_O_O^O]O]O\\O}[N|ZNzYNxXNvWNggghPfP|fzfxevdscsYLiTK_NHYKFh\\Z]UV=;@.R.S.S.S.S.S.S/S/S/S/S/S/S/STxTxTxTxTx/S/S/S/SGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅۅۅۅGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅDiDiDiDiDiDiրրրրրրրրրրրրրրր׀׀׀Ei&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfAfAfAfAfAf%J|%J|%J|%J|%J|%J|%I|%I|%I|\u0007\u0006\u0005\u0017\u001e,\r\u001a+\u000e\u001b,\u001b!.\u0018\u0016\u0018! \"\u0016\u0015\u0018\u0015\u0015\u0018\u0014\u0014\u0017\u0014\u0015\u0018\u0015\u0017\u0019`E6iYlZo\\q]s^^Jvawbyczd{e}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\\O]O]O^O_O_O`O`OaOaPbPbPcPcPcPdPdPdPdPePePePePePePePePfPfPfPfPfPfPfPePePePePePePePdPdPdPdPcPcPcPbPbPaPaO`O`O_O_O^O]O]O\\O~[N|[N{ZNyYNwXNiiiihhRfQdQbPwfx]Opdkbtd_m`]OEDG?A;:@.S.S.S.S.S/S/S/S/S/S/S/S/STxTxTxTxTxTxTxTxTy/SGlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܅܅HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܅Eiրրրրրրրրրրրր׀׀׀׀׀׀BgBgBgBgBg&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfBfBfBfBfBfBfBfAfAf%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|\u0000\u0000\u0000\u0014\u0018\u001e\r\u001a+\u000e\u001b,YA5jPBpSDl[o]q^t`_Kwbycze{f}ghilSrVMtWMvWNxXNyYN{ZN|[N~[N\\O]O]O^O_O_O`O`O`OaPaPbPbPbPcPcPcPcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPcPcPcPcPbPbPbPaPaO`O`O`O_O^O^O]O]O\\O~[N|[N{ZNyYNxXNjjjjjjhSgSeRcR|`Qsfoe}jcrd`k_]LCDC=@,,3(4F(4F.S.S/S/S/S/S/S/S/STxTxTxTxTxTxTxTxTxTyTyTyHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlChChրրրրEiEiEiրրրրրր׀׀׀CgCgCgCgCgCgCgCgCgCgCgCgBgBg&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfBfBfBfBfBfBfBfBfBfBfBfBfBf&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|\u0017#5H71O;3V?4iOBoSDsVFo]{[I^K`LbNdO{f}g~hjkTmUoVqWrWwXNxXNzYN{ZN}[N~[N\\O]O]O^O^O_O_O`O`O`OaOaPaPbPbPbPbPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPbPbPbPbPaPaPaO`O`O_O_O_O^O^O]O\\O\\N~[N|ZN{ZNyYNoToToTnTllljUiThTfTcSvirgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S/S/S/S/STxTxTxTxTxTxTxTxTyTyTyTyUy܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlDhDhDhCh&K}&K}&K}&K}&K}&K}ChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|&J|&J|&J|&J|&J|BgBgBgBfBfBfBfBfBfBfBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRDk\\n^z[J~^LaNcOdPfQgRhTjUlVnWpXrXsYqqrrrsz[z[z[{[{[{ZœrŒqŒqŒpŒpőoyVxVxUwTwTaPbPbPbPbPbPbPbPbPbPbPbPbPbPaPaPaPaPaOaO`O`O`O_O_O^O^O^O]O]O\\O~\\N}[N|ZNzYNpTpUpUpUoVoVnVmVlVkVjVhVfU~cUujqh~mfugdkaad\\^E@D98?$(2minffm^blV^lMYk(5F(5F/STxTxTxTxTxTxTxTxTxTyTyTyUyUy܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݆݆݆݆݆݆݆݆݆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChChChChChChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|CgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|AeAe;GY<68I=:I82Q=4XA6~fZj\\m^p`|]L`NcPeQgSjlmnoXqYrZt[rsstttz]{]{]{\\{\\{\\{[ēsērĒrĒqĒpđpyWĐoÐnÏmÏllkkaOaOaOaOaOaOaO`O`O`O`O`O`O_O_O_O_O^O^O]O]O]O\\O~\\N}[N|ZNllmqVqVqVpWpWoWnnnnn~neWxltkpiykfodcf_`JDG@>C*,5\u001d$1MYktr~tstmolinadmX_lNZkMZkTxTxTxTxTxTxTxTyTyTyUyUyUy݆݆݆݆݆݆݆݆݆HlHlHmHmHmHmHmHmHmHmHmHm݆݆݇݇݇݇݇݇݇݇݇݇HmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhChChChChChChChCgCgCgCgCgCgCgCgCgCgCg&J}&J}&J}CgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|AfAfAfAf;GY;GY;GY1'!D:9N?;N;3]I?zdYh[l^oascuebQdRfTlmnopqrsv]w]uuuuv{^{^|^|]|]{\\{\\{[{[zZzZyYyXxXonnmmuTuStStStRsRsQ_O_O_O^O^O^O^O^O]O]O]OrSrSrSkllmmmnnqWqXqXooppppp}o{cXv`Vp]U}nishfhaba\\_DAF::B$)4\u0002\u0001\u0000MYkMYkMYktctq\\QPPIKFDI;>H/8GMZkTxTxTxTxTyTyTyUyUyUy݆݆݇݇݇݇݇݇݇݇݇݇݇HmHmHmImImImImIm݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇ImImImImImImImImImImImImImImImImImIm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhChChChChChChChChCgCg&K}&K}&K}&K}&J}&J}CgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|BfBfBfBfBfBf;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[j]n`qctewgyi|k~lnopqssu]v^w^x_y_z_z_{_wwvvvuut{\\{\\z[zZyZyYxXpowWvVvVuUuUuTtTlkkkkkksTrTrTrTrTrUrUrVnnnoooppqYqqrrrrqgZ{dYvaXp^WiYU`TRVNOb]aEBH<<D36@\u0019\u0019\u001cMYkMYkMYkMYkMZk-.1W>+[NL^SQWNNKFJ?AI2:HTxTyTyTyUyUyUyUyUy݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇ImImImIm݇݇݇݇އއއއއއއއއއއއއއއއImImImImImImImImImImImImImImImIm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhDhDhDhDhDhCh&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBf&J|&J|BfBfBfBfBfBfBfBfBf;HY;HY;HY;HY;HY;HY;GY3(\"D::B41RB=YG@wcZ}g\\k_nbrdug}aRdTgViXkYqrstp^q^w`x`y`z`za{axxwwwvvvuutssrrqqppoovWnnnnnnmtVsVsVsVsVsWsWsXsXpppsYsYrZr[r\\q\\p]ttssh\\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((\u000f\u0013\u0019MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/TUyUyUyUyUyUy݇݇݇݇݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއވވވވވވވImImImImImImImImImImImImވ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhDhDhDh'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBg&J|&J|BfBfBfBfBfBfBfBfBf;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&\u001aB52I94ZHAxd[}g^k`ncrey_R}bTeVgXiYk[l\\n]o^vvvawaxaybzb{b{axx|a|a|`{`{_{_{^z^uttssrrwZwZvYvYvYuXuXuXuXpppppppqqtZt[s\\s\\s]r]r^q^p^o^n^l^j^h]{f\\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?\u0015\u0017\u001cJJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T/TUyUyUyއއއއއއއއއއއވވވވވވވImImImImވވވވވވވވވވވވވވވވވވވވވވވވވImImImImImImImImވވވ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|&J|&J|&J|&J|BgBgBgBfBfBfBfBfBf;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$\u001d0\"\u00198&\u001a?*\u001cG/\u001fV=+w[F{g^kanXMs\\Px_S{bU~dWfYhZj\\l]m^vwxyyzzzzz{b{b{b{b{a{a{`{`z_z_z^uy]y]x]x\\w\\w[w[v[v[v[v[rrrsssstuut^s_s_r_r`q`p`wvvu~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)\u0010\u0012\u0015RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\\\TLMIFJ:>I0T0TImވވވވވވވވވވވވވވވވވImImInInInInInInވވވވވވވވވ߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈InInInInIn߈߈߈߈߈'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DiDiDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChChChChChCgCgCgCgCgCgCgCgCgCgCg&J}&J}&J}&J}&J|&J|&J|&J|&J|BgBgBgBgBgBfBf<HZ<HZ<HZ<HZ;HY;HYCIR>EM>EMCIR;HY;HYCIRCIR)\u001d\u00156&\u001a8&\u001b@*\u0019H0\u001dI1!\\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[i\\k^m_vwxyzz{{{{{zdzdzczczcyyyxxxwwwww_w_w_vvvvwwwwwwxxxxxxxxwv~v|tysvrh\\YcXX[TUSNRIHOUXaNS^JFE>>A')+\"%(\u0001\b\u00104:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJImImImImވވވވވވވވވވވ߈߈߈InInInInInInJnJnJnJnJn߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߉߉߉߉߉Jn߉߉߉߈߈߈߈'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhChChChChChChCgCgCgCg&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|CgCgCgBgBgBg<HZ<HZ<HZ<HZ<HZMS\\CIR>EMCIRCIRCIR888DGNCJRCIRBBB(\u001d\u00150 \u00158&\u001b<)\u001cG0\u001fM5\"X@0z^KbFkUlXPp[Rs^TvaVzcX}fZg\\i]uvwxyzz{{vevewewe||{{{{{{zzzzzyvbvbvbububuctctcsbscrcqcyyyxxww|uytvs~sqyooslmVQTOLR[\\dQU`KHHAAD:<@68;\u001c &\u0001\u0001\u0001\u0000\u0002\u0005Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dInInInInInIn߈߈߈߈߈߈߈߈߈JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJn߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉JnJnJn߉߉߉߉߉߉'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~EiEiEiEi'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhChChCh&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}CgCgCgCg<IZ<IZ<HZ<HZ<HZ<HZ?EN?ENCJRCJRCJRCJRCJRUU\\CJRCJRBDG''''''(\u001c\u0014. \u00159(\u001c:(\u001cB-\u001eO8'kUFt[IhQyic}leogrjtlwnypzq|s|g]~h_j`kalaobpcqdrdrdseteteue||||||||ueududtdtdsdsdrdrdqdqdpcocncyyx~w}w{vyuvs}srxopqknkgkdbhGGOVYcPLLBCF;>B9;>68;\u001b\u001d\u001f\u0000\u0000\u0000\u0002\u0002\u0002\u0000\u0002\u0005Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg{{ypqhbeVYcJnJnJnJnJnJnJn߉߉߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJn߉߉߉߉߉߉JnJnJnJnJnJnJn'L~'L~'L~'L~'L~'L~'K~'K~'K~EiEiEiEiEiEiEiEi'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDh'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}CgCgCg<IZ<IZ<IZ<IZ<IZ<IZ?ENDJSDJSDJS?EN?EN?EN<HZ04?'.6'.6&(+''''''\u001d\u001d\u001d,\u001f\u0018)\u001d\u00151#\u00187&\u0019;)\u001dM8)S;+mVGdKseawhc{kfnhpjrltmvotaZvc[wd]yf^zg_{h`|i`~jakblbmcncodpdpdpdpdpe{pepepepepdododndmdmclckc}jc|jbyhb}w{wyvwuut}sryqqunpojmhfkKKRDFOD><535=AG=?D?AD<?B&(+\"$'\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0005KRZTZcMZkKOVRYaSYb.4=.4=4:C.4=4:C)6G)6G)6G)6G)6G)6GWMFaRGhbe{su}}kde_^dJnJnJnJnJnJnJnJn߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJoJoJoJoJoJoJoJoJoJoFjFjFjFjFj'L~EiEiEiEiEiEiEiEiEiEiEi'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}Cg>==<IZ<IZ<IZ<IZ<IZMT\\DJS?ENDJS?EN?EN?EN\")1\")1C5+//3(.7&),'''''''''\"\"\"\u001c\u001c\u001c\u001a\u0012\r.\u001e\u0011, \u00187(\u001d8'\u001bA1&F4(L8*oXIw]Jpdasfcvhexkg{mi~ojqll\\Xn^Yp`Zpa[qa\\rb]rc^sc^sd_ue`wf`xgayhayhayhbxyyyyyy~ywgbvfateasd`qd`pc`nb_la_ut|ssxqrunpZUXVRWROUMMSHIRIC@967-/3'+0(*-ACF?AD;=@#%(\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001JMPU[dSYbKPVW]fY`hSYbSYb.4=4;C4:C.4=)6G)6G)6GCPaCPaCPaFED]PGdaesmomefb_dJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoFjFjكككڃڃڃڃEiEiEiEiEiEiEiEi'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}@K[=IZ<IZ<IZ<IZ<IZNT]DJS?ENDJS#)2#)2#)2#)2#)2'.6A4+028(.7'),)))######\"\"\"\u001c\u001c\u001c6$\u0016nP?\u001a\u0013\r.\u001e\u0011+\u001f\u0017>1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\\Zi]Zi][j^\\usususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:=\u001e\"(\u0000\u0000\u00003@Q\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001JMPV\\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhknfgeaeJnJnJnJnJnJnJoJoJoJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoኮኮኮኮኮኮKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoڃڃڃڃڃڃڃڄڄڄڄڄڄEjEiEiEiEi'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}DiDiDiDiDhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[<IZ<IZ<IZ?FN'.6#)2#)2#)2#)2#)2#)2(.7#)2\u001f,=@<A348)/8\"$'\"$'######\"\"\"\u001c\u001c\u001c\u001c\u001c\u001c\"\u0014\tkF+;(\u0019\u001a\u0013\r\"\u001b\u00166*#5*\">2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%(\u001b &\u0000\u0000\u0000\u0000\u0000\u000015;5BS\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbLS[V]eDPbDPbDPbDPbDPbDPbWMF^^dieirkeaeJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoኯኯኯKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoڃڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄۄGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~EiEiEiEiEiDiDiDiDiDi'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%(\"$'###\"\"\"\"\"\"&&&\u001c\u001c\u001c888888cB*}\\I@!\b\u001b\u0017\u0014%\u001e\u0019+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+\"%(\u001c!'\t\t\t\u0000\u0000\u0000\u000f\u0010\u0012\"&,KXi04:\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0003\u0003JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[ajW]fDPbDPbDPbDPbDPbDPbnSw|mqjKoKoKoኮኮኮኮኮኯኯኯKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpڄڄڄڄڄڄڄڄڄڄڄۄۄۄۄۄۄۄۄGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~EiEiEiEiEiEiEiEiEiEiEiEiDiDi'K}'K}'K}'K}HlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######\"\"\"\"\"\"\u001c\u001c\u001c8888888887'\u001avS:jW;)\u001c\b\u0004\u0000\u000f\f\n\u0016\u0011\r\u0019\u0013\u000e\u001e\u0016\u0011&\u001e\u001a3#\u0018.$\u001e-% .% .& /&!,#\u001d,#\u001d@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+\u001e\"(\u001d!'\u0013\u0016\u0019\u000b\u000b\u000b\t\t\t\u0000\u0000\u0000\u0014\u0018\u001e\u0013\u0014\u001615;6CT37=\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000MMMKMP^ad_enY`hNZlNZlU\\dV\\eDQbDQbDQbDQbDQbMUcyl|oiKoኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKp⋯⋯⋯LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpڄڄڄڄڄۄۄۄۄۄۄۄۄۄۅۅۅۅۅۅGkGkGkGkGkGkGkGkGkۅ܅܅܅܅܅܅܅܅܅܅܅܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######\"\"\"(((8888888888888884\"\u0014nO9gXjZE/ (\u0019\u000e\u0007\u0003\u0000-\"\u001c\r\u000b\n\u0012\u000f\f\u0015\u0011\u000e\u0016\u0012\u000e\u0018\u0013\u000f\u0019\u0014\u0010\u001c\u0017\u0012\u001c\u0019\u0017%\u001f\u001b' \u001c%\u001a\u0012$\u0019\u0012#\u0019\u0011\"\u0018\u0011 \u0017\u0011\u001f\u0016\u0010\u001c\u0019\u0018\u001b\u0019\u0018\u001a\u0019\u0018!\u001f \u001f!$\u0017\u001a\u001d\r\r\r\f\f\f\f\f\f\u000b\u000b\u000b\t\t\t\t\t\t\u0004\u0006\b\u0001\u0001\u0001\u0000\u0000\u0000\u0013\u0015\u001748>7CU:GX\u000b\u000f\u0015\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000JJJLLLKMPagp_enNZlLPVDQbDQbDQbDQbNVcuorjѼዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp⋰⋰⋰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpۄۄۄۄۄۄۄۄۅۅۅۅۅۅۅۅۅۅۅۅGkGkGkGlGlGl܅܅܅܅܅܅܅܅܆܆܆܆܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}DhDhDhIP\\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB888888888\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c0 \u0014cF1w]OcS{`QS;+5\u001b\u00067'\u001c\u0017\r\u0004\r\u0006\u0001\u0017\r\u0005\u001c\u0011\b* \u001b\u001f\u0016\u000f\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\u0005\u0003\u0001\u0004\u0002\u0000\u0004\u0002\u0000\t\u0007\u0004\f\r\u000f\f\u0010\u0016\b\b\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u0007\t\u0011\u0014\u0017;?E7CU;HY=I[\f\u0011\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000JJJMMMKMPacfbhqEQcHScNVdȵዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⋰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpۄۄۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅ܅܅GlGl܅܅܅܅܅܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇DhDhDhDh=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u0000\u0000\u0000\"\u0018\u0010>-\"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;,\u001b &\u001b\u001f%\u001a\u001e%#'-\"'-&3DS_qP\\nR_p>J\\?K]<AG\u0010\u0015\u001b\u000e\u0010\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000%%%DDDACF⋯⋯⋰⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLp⌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰LqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqۅۅۅۅۅۅۅۅۅۅۅۅ܅܅܅܅܅܅܅܅GlGl܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆݆݆݆݆݆݆݆݆HlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇DhDh=J[=J[=J[=J[=J[=J[=J[(/739B#)2(.7(/7(/7#*2$*3)/8)/8)/8)08*09+19(-5*.5/16437D>AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b@@@FFFACFZ\\_[ajagpEQcGRcKTdPWd⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌰LpLpLqLqLqLqLqLqLq㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMqMqMqMqMqMqMqMqMqMqMqMqMqMqۅۅۅۅۅۅ܅܅܅܅܅܅܅܅܅܅܆HlHlHlHlHl܆܆܆܆܆܆܆܆܆܆܆݆݆݆݆݆݆݆݆݆݆݆݇݇݇݇݇HlHlHlHlHlHlHl݇݇݇݇݇݇݇݇އއއށ>J\\>J\\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b777777777777777777777\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001bAAAFFFACFACF\\^aeltbhqDQbDQbDQbERcERcERcERcHScLUdRXd|nj⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌰㌱㌱㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱MqMqMqMqMqMq㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMqMqMqMqMqMqMqMqMqMqMqMq܅܅܅܅܅܅܅܅܅܅܆܆܆܆HlHlHlHlHlHlHlHlHl܆܆܆݆݆݆݆݆݆݆݆݆݆݆݇݇݇݇݇݇݇݇݇݇݇݇HlHlHlHlHl݇݇݇އއއއއއއއއއށ>J\\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b777777777\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001bBBBEEEACGADGFIL\\ckZ`iTZcDQbDQbDQbagpbiqcircirY`hY_hERcERcERcGSdJTdNVdTYeLpLp㌰㌰㌰㌱㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMq㍱㍱㍱䍱䍱䍱䍱䍱䍱䍱䍱䍱䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲MqMqMqMqMqMqMqMqMqMqMq܅܅܅܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHl݆݆݆݆݆݆݆݆݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇HmއއއއއއއއއއއވވވވވށFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\\a_aY\\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b%%%%%%%%%%%%\"\"\"\"\"\"\"\"\"KKKJJJFFFGIL]_b^dm\\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLpLqLqLq㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱䍱䍱䍱䍱䍱䍲䍲䍲Mq䍲䍲䍲䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲MrMrMrMrMrMrMrMrMrMr܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇އއއއHmHmHmއއއއވވވވވވވވވވވވށ-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr\\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\\fLqMqMqMqMq㍱㍱㍱㍱㍱䍱䍱䍱䍱䍲䍲䍲䍲䍲䍲䍲䍲䎲䎲䎲䎲䎲MrMrMrMrMr䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲厲厲厲厲厲厲厲厲NrNrNrNrNrNrNrNr܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇݇݇݇݇݇݇އއއއއއއއHmHmHmHmImImImވވވވވވވވވވވވވވވނPT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\\bk\\bkgnvgnvgmvgmvfluflueltektdksdjscjrcirTZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMqMqMqMqMqMqMq䍲䍲䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲NrNrNrNrNrNrNrNrNr厲厲厲厳厳厳厳厳厳厳厳厳厳厳厳厳厳厳厳右右右右右右右NrNrNrNrNr右冪܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇އއއއއއއއއއއއImImImImImImImImImImވވވވވވވވވ߈߈߈߈߈߈߂LPVLPWKPWFLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;<A17@06?/6>/5>.4=-4<IOXHOWMS\\QX`EQcEQcEQcEQcEQcEQc`fo[bj\\bk]cl]dl^dm^dm]dlhnwhnwgnvgmvgmvfluflueltektdksdjscircirV\\eU[d_fn^emSYbRXaQX`[bjPV_OV^FSdGSdITeLVeNWeRYfW[f\\^gMqMqMqMqMqMqMqMq䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲厲厲厲厲NrNrNrNrNrNrNrNrNrNrNrNr右右右右右右右右右右右右右右右右右右右右右右右右右右右Ns右右右HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHmHmHmއއއއއއއއއވވވވވImImImImImImImImImImImImImވ߈߈߈߈߈߈߈߈߈߈߈߈߉߂JPXJPXKQYQW_RW_SX`TY`UZaW[bZ]c\\^c^_dCDHDDHTRSWQO@=BNHKbYZ^VWUNPMGJFAEgcgcafEQc`go[aj]cl]cl^dm^em_en_en_en_en^em^dm^dmioxhnwhnwgnvgmvgmvfluflueltektdjsdjscirW]fagp`go`fo_enSYbRXa\\ck[bj[ajFSdGSdITeKUeNWeQXfTZfY]g``gMqMqMrMrMrMrMrMrNr厲厲厲厲厳厳厳厳厳厳右右NrNrNrNrNrNrNrNrNrNrNrNrNsNsNsNs右右右右右揳揳揳揳揳揳揳揳揳揳揳揳援援援援援援援援OsOs援援HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmއވވވވވވވވވImImImImImImImImImImImImImImImImIm߈߈߈߈߈߉߉߉߉߉߉߉߉߂PRWOQWTW\\`dkbek^af_ag`bgabgiko_en^emhnw`fo`fo`fo`fo`fo`fo`fo_fn_fn_en_en^em^dm^dmioxhowhnwgnvgmvgmvflufluektektahpagp`foTZcSYbRYa\\ck\\bkPV_GSeITeKUeMWePXfSZfW[f\\^gdbhMrNrNrNrNrNrNrNrNrNrNr右右右右右右右右NrNrNrNsNsNsNsNsNsNsNsOsOsOsOsOsOsOsOs援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴OsOsOsOsOs搴HlHlHlHlHlHlHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmHmHmImImImImވވވވވވވImImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉߉߃CPaCPaOVbRSWQRWPRWUW]U[dU\\dW]eW]eX]eV\\eagpagp`go`go`fo`fo`fo`fo_fn_en_en^em^dmioxioxhowhnwgnvgmvgmv`foTZcSZbRYaQX`\\bkGSeITeKUeMWfPXfSYfV[gZ]g_`hNrNrNrNrNrNrNrNrNrNrNrNrNr右右右右右NsNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴OsOsOsOsOsOsOsOsOsHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmHmHmImImImImImImImImImImImވވވImImImImImImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉CPaCPaCPaCPaCPaQWcYY\\XX\\RSXWX]bdiU[dU[dU[dagpagpagp`go`go`fo`fo`fo_fn_en_en_enipxioxioxhowhnwTZcSYbRYa\\ck\\bjIUeKVeMWfOXfRYfU[gX\\g\\^gcbhNrNrNrNrNrNrNrNrNsNsNsNsNsNsOs援OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOt琴琴琵琵琵琵琵琵琵琵琵琵琵琵琵PtPtPtPtPtPtPtPtPtPtPt\u0013\\HmHmHmHmHmHmHmHmHmHmHmImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImIm߉߉߉KQZFLUFMUCPaCPaCPaCPaSXcRWcddgddhddiceicejU[dagpagpagp`go`fo`fo`fo_fn_en_enjpyipxioxSYbRXa]ckIUeKVfMWfOXfQYfT[gX\\g[^h_`hgdiNrNrNsNsNsNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOtOtOtOtOtOtOtPtPtPtPtPtPtPtPt瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPt\u0013\\HmHmHmHmHmImImImImImImImImImImImImImImImImImImImImIm߈߈ImImImImImImImImImImImImImImImImImImImImImImInInInInInInInCPaCPaKQZFMUKRZKRZCPaCPaCPaCPaUYcTXcRWceeheeieeiefjefkZ`iZ`iZ`iU[dagpagpagp`go`fo`fo`fo_fn_enjpyJUfKVfMWfOXfRYgTZgW\\g[^h^`hcbijfiNsOsOsOsOsOsOsOsOsOsOsOs搴搴搴琴OsOsOsOtOtOtOtOtOtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPt瑵瑵葵葵葵葵葵葵PtPtPtPtPtPtPtPtPtPtPtPtPtPtPt\u0013\\\u0013\\ImImImImImImImImImImImImImImImImImImImImImImIm߈߈߈߈߉ImImImImImImImImImImImImImImImInInInInInInInInInInInInJnJnCPaCPaT[cKQZFMUKRZKRZLR[GMV@BDCPaDPbWZcVYcTXcSXcgfi\\[_ggjggkfglioxioxipxjpyjpyjqy`foagpagpagp`go`fo`foNWfPXgRYgT[gW\\gZ]h^_hbaigdimgjOsOsOsOsOsOsOsOsOsOs琵琵琵琵琵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPuPuPuPu蒶蒶蒶蒶PuPuPuPuPuPuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\ImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉ImImImImImImImImInInInInInInInInInInInInInJnJnJnJnJnJnJnJnJnJnCPaCPaU[dKRZGMVLR[LR[LR[GMVGNVHNWDPbDPbY[dWZdVZdUYcTYchgi]\\_hhkhhl]^bjowjpxjpxjpxjpyjpykqykqzkqzkqz`foagpagpagpRZgU[gW\\hZ^h]_haaiecijfjOsOsOsOsOsOsOsOtOt瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPuPuPuPuPuPuPuPuQuQuQuQuQuQuQuQuQu蒶QuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\\u0013\\ImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉ImImInInInInInInInInInInInInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnCPaCPaCPaKRZV\\eGMVLR[LR[LR[GNVHNWHOWIOXIOXDPb[\\dZ[dX[dWZdVZdUYd_]__]`jil_^b__clpwlpwlpxlqxlqylqylqylqylqzlrzlrzlr{lr{agpW\\hZ^h]_i`aidciiejmgjOsOtOtOtOtPtPt瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶葶PtPuPuPuPuPuPuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\\u0013\\ImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉߉߉InInInInInInInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኮJnJnAFLCPaDPbLR[LR[V]eLR[LR[LS[HNWHOWIOXIPXJPYKQZBFL^]d\\]d[\\dY[dX[dWZdVZd`^``_akjma`ca`dmpvmpwmqwmqxmqxmqxmrymrymrymrzmrzmrzmr{ms{ms{ms{ahpms|ahpagplr{`aiccihejlgjpikPtPtPtPtPt瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶QuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQv铷铷铷QvQvQvQvQvQvQvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\ImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉InInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኮኮኯኯኯJnDPbDPbLR[LR[W]fLR[LS[MS\\HNWIOXIPXJPYKQZLR[PRUQSVDQb^^e]]e\\]eZ\\dY[dX[dWZdb_ab`bb`cbadcekcfkoqwoqworxorxoryoryosyoszoszoszns{ns{ns{ns{chpchqchqchqnt|bhqms|ms|ls{lr{lr{gejlgkohkPtPtPtPt葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷QuQuQuQuQuQuQuQuQuQvQvQvQvQvQvQvQvRvRvRvRvRv铷ꓷꓷꓷꓷꓷꓷRvRvRvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ImImImImImIm߉߉߉߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኯኯኯኯዯዯዯᄑDPbDPbV\\eW]fLR[GNVHNWHOWIOXJPYQW`RXaSYbRYaTUXTUXBFLa_e`^e^^e]]e\\]eZ\\eY[eX[dW[dnlmomndbdeeiefjefkefkegleglegmpsxpsypsypszptzptzpt{pt{pt{pt{pt|diqdiqdiqdiqdiqdiqot}bhqbhqms|ms|ms|ls{lr{lr{krzkqzkqznhkqjkPtPt蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷钷钷铷铷铷铷铷铷铷铷QvQvQvQvRvRvRvRvRvRvRvRvRvRvRvRvRvRvꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸRvRvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ImImIm߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኯዯዯዯዯዯዯዯዯᄑU\\dV]eLS[HNWHNWIOXOU^JQYQW`RYaTZcagpacfmjiflugnvaVPb`ea_e_^e^^e]]e[]eZ\\eZ\\eY[epmnpnoecefehffigfjggjggkgglghlghmghmghnrtyrtzrtzrtzru{ru{ru{qu{fjpfjqfjqejqejqejqejqejrdjrou}mt|bhqms|ms|ms|ls{ls{lr{lr{krzkqzkqzjqyjpyPu蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓷRvRvRvRvRvRvRvRvRvRvRvRvRvRvRvꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸSwSwSwSwSwSwSwSwSwSwSwSwSw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\JnJnJnJnJnJnJnJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯዯᄑLR[GNVHNWHNWIOXOU^[ajRXaSYbU[dahpcirektgmvioxjpyBGMbWPc`fb`f`_e_^e^^e]]e\\]e[\\eZ\\eY[eropgegsqssqtsruhgjhhkhhlhhlhimhimhinhjnhjosuzsu{su{sv{hjphkqgkqgkqgkqgkqgkqfkrfkrfjrfjrejrpu}mt|bhqbhqbhqms|ls{ls{lr{lr{krzkqzkqzjqyjpyjpyioxioxsklQuQu钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸRvRvRvRvRvRwRwRwRwRwRw딸딸딸딹딹딹딹딹딹딹딹딹딹땹땹땹땹SwSwSwSwSwSwSwSwSwSwSwSw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮJnJnJnJnJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯዯዯዯ⅑HNWHNWIOXOU^\\bk]cl^emU\\dbhqdjsfluhnwipxkqzlr{ahpeXPdWPdafc`fa`f`_f__f^^e]^eifgtrsurtusuutvjiljiljimjjmjjnjjnjkojkojkpikpikpikpikqikqikqhkqhkqhkqhkrgkrgkrgkrgkrfkrqv}bhqbhqbhqahpahpagpagplr{lr{krzkqzkqzjqyjpyjpyioxiox]cl\\ckgnvpjlrklulmQuQuQu铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸RwSwSwSwSwSwSwSw땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹SwSwSwSxSxSxSxSxSxSx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋰⅑NT]OV^[bj]cl_enagpX^gdksfmuhnwjpykrzagpbhqahphZQfYQgcfebfdafc`fb`fjghkgivsuvtvvtwvuwkjmkjmkknkknkkovwzvw{vw{vw{klpjlqjlqjlqjlqilqilqilqhkrhkrhkrhkrgkrgkrfkrbhqbhqahpahpbhpagpagp`go`go`fokqzkqzjqyjpyjpyipxioxiox]cl\\ck\\bk[bjfmuflunilpjlrklulmQuQuQuQuQv铷ꓷꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딸딸딹딹딹딹딹땹땹땹SwSwSwSwSwSw땹땹땹땹땹땹땹앹앹앹앹앹앹앺앺앺앺앺앺앺앺앺앺앺TxTxTxTxTxTxTxTx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯዯዯዯዯዯዯJnJnJnJnዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰→[aj]cl_enagpX^gZ`i\\bkioxjqylr{ahpbhqahpagp_fnj[QiZQhcgkghlhiwtuxuvxuwxvxxvxmkmxwyxwzxwzxw{ww{ww{ww{wx|klqklqklqjlqjlqjlqjlqilqikqhkqhkqhkqgkqgjqeiqeipdipdipchpchpbhobgoagoafo_en_en_enjpyipxioxiox]cl]cl\\bk\\bk[aj[ajfluZ`iY_hZ_hlhlnilpjlrkmtlmwnmQvQvRvRvRvRvRvꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딸딹딹딹딹땹땹땹땹땹땹땹땹땹땹땹땹땹땹SxSx앺앺앺앺앺앺앺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺TxTxTxTxTxTxTx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯJoዯዯዯዯ⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⅒QX`_emagpY_gZai\\bk^dm`folr{ahpahpchpbgolqyhnwl\\Q\\]fmiimijmjknjknklnkmnkmywyywzywzyx{xx{xx{xx{xx{wx|llpklpklqklqjlqjlqjkqikqikqhkpsv|sv|su|ru{fipfipeipeiodhodhocgocgnbgnbfnafn^dm^dm]dliox]cl^cl]ck]bk\\bj[aj[aifltektY_hX_gIVgMXhNXhlhmojmqjmpjmskmtlmvmmRvRvRvRvRvRvRvRvRvꔸ딸딸딹딹딹딹땹땹땹땹땹땹땹땹땹땹땹땹앹앹앹앺앺앺앺앺얺Tx얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺햺햺햺햺햺햺햺햻햻햻햻햻햻햻햻TyTyTyTyTy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኯኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯJoJoJo⋯⋯⋯⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⋕choZ_g\\ai^dk^dm`folr{ls{agpdipchomqx]^f]^f\\^fzvvzvwoklokmolmolnnlnzxzzxzyxzyx{yx{xx{xx{xx{llpllpklpklpvw{uw{uv{tv{tv{ruzfiofhnehnehndgncgmcgmbfmbfmaellpxlpwkpwkov^cj^cj]bj]bihmugltgltfksKWhKWhOYhPYhQZhR[iS[iU\\ilimojmrknslmtlmrkmvmmvmnyonRvRvRvRvRvRvRwRwRwRw땹땹땹땹땹땹땹땹땹땹앹앹앹앺앺앺앺얺얺얺얺얺얺얺얺TxTxTxTxTx햺햺햺햺햻햻햻햻햻햻햻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻UyUyUyUy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯ⋯⋯JoJoJoJoJo⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰→^bi`dkbfmdhokrzlr{lr{qt{psy__g^_g^_g]^g{vv{ww{wxolmolmolmolnzxzzxzzxzyxzyxzmlomlollolkowwzvwzvvzrtyqsyegmegmdglorxoqwnqwmqwmpvlpvlovkouknu_bijntimtimthlsNXhNXhPZhQZhR[iS[iT\\iU\\iW]iX^jY^j[_jnjnpkorlotmnumnvmnvnnwnnxnnyonRvRvRwRwRwRwSwSwSwSwSwSw땹땹땹앹앹앺앺앺얺얺얺얺얺얺얺얺얺얺얺얺얺햺TxTxTxTyTyTyTyTy헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻UyUy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯JoJoJoKoKoKoKoKoKo⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㏗dglfhnru{krzsu{rtzªĬ©baga`g``g``g__g^_g]_gpkkpklpll{wx{wx{wyzwynlmnlnnlnmknmknlknlknfglegkefkdfkoqvoqvnpunpumoumou`ci`bh_bh_bhPYhPYhQZhRZiS[iT[iU\\iV]iW]iX^jY^jZ_j[_j\\`j^ak`bkackokormpunpvopwoownoxnnxonyonzon{pn{poRwSwSwSwSwSwSwSwSwSwSwSwSwSx얺얺얺얺얺얺얺얺얺얺얺햺햺햻햻햻햻헻TyTyUyUyUyUyUyUyUyUyUy헻헻Vz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰KoKoKoKoKoKoKoKoKoKoKoKoKo⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌱㌱㌱㌱㌱㑘rtyhjotv{Ȯϳϳǫdbhcbhbahaaha`h``h_`g__g^_g]_gokkokk{wxzwxzwxzwxyvxmjlefjeeideioptoptnotbchachabgS[hS[hS[iT[iU\\iU\\iV\\iW]iW]iX^jY^jZ_j[_j\\`j]aj_ak`bkbckcdkeelgfligmqlptoqwpryqrzqqzppzppzpozpo{po|po|qo|qoSwSwSwSwSwSwSwSwSwSxSxSxTxTxTxTx얺얺얺햺햺햻햻햻햻헻헻헻헻헻헻UyUyUyUyUyUyUyUyUyUyUyUyUyUyUz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⋰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKo⌰⌰⌰㌰㌰㌰㌱㌱㌱㌱㌱㌱㍱㍱㍱㌇ͱҵҳаfciechdbhcbhbahbahaahaah``h_`h_`h^_h]_hzvvzvvqptppsV\\iV\\iV\\iU\\iU\\iV\\iV]iW]iX]iX^iY^jZ_jZ_j[_j\\`j]`j^aj_ak`bkbckcckddkeelgfligmkinnjoqlpwpszst}tu~tt}ss}rr|rq|qp}qo}qo~qo~ro~roSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTx햻헻헻헻헻헻헻헻헻헻헻헻UyUyUyUyUyUyUyUyUzUzUzUzUzVzVzVzVzVz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⋰⋰⋰⋰⋰⋰⋰⋰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKo㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㔚TYeSYekjmvvyŸĬҳұұѰiejhejfdieciecidbicbicbhbahaahaahY^iX^iY^iY^iY^iZ^iZ_i[_j\\_j\\`j]`j^aj^aj_aj`bkabkbckcdkddkfelgflhfljgmkhmnjnplo¹xxwvvuustrsqrprpspspspspSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUy헻헻헻UyUyUzUzUzUzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⋰⌰⌰⌰⌰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKo㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㗛VZeVZeVZeVZeVZeVZeVZe̾ĢұԬήѰmilkgljfkhejgejfdjfdieci]`j]`j^`j^aj^aj_aj`aj`bjabkbckcckcdkddkedkfelgflifljglkhmmimnjnpkosmpżȾʿɾȽǻwuustrtqtptptptptpSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{V{W{W{\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⌰⌰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKp㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱䍱䍱䍱䙜Y\\eY\\eX\\eX\\eX\\fX\\fX\\fX\\fX\\fY\\fY\\fŷþźֲŪɬ̮ٲrmqpkoojnmimkhlbcjbckcckcckddkedkeekfekgelhflifljgljglkhmmimnjmpknrlotnpwprż¿ʾɼǺvruququpupuquqTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{W{W{W{W{W{W{W{W{W{W{W{W{\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKp㍱㍱㍱㍱䍱䍱䍱䍱䍲䍲䍲䍲䛞[]f[]f[]f[]f[]f[]f[]f[]f[]f[]f[]f[]fa`g˼ɾ꽛ĥ˭ѰӳúĻżĽüztvxruhfkhfkiflifljglkgllhllhlmimnimojmpjmqknsmovopyqr|st¹Ƽ̾ʼɺȹvqvqvqvqvqvqTxTxTxTxTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W|W|W|W|W|\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpLpLp䍱䍱䍱䍲䍲䍲䍲䍲䎲䎲䎲䘜]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^fdbghdhmfhõ÷ؾͮղĹƽɿňƿýnilnilnilojmpjmqkmrkmslntmnvnowopzqq}sswvǽÿ;˼ʺɺɹwqwqwqwqTxTyTyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W|W|W|W|W|X|X|X|X|X|X|X|X|X|\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLp䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䛞]^f^^f^_f^_f^_f__f__f__f__f__g__g__g__g__g__gfchkehoghtjizmjƶüǼٿ۾öŹȻ˿žºslmtlmumnvnnwnoyoo{qp|rrtsvuzx½Ͽͽ̼˻˺˺˺xrxrUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzVzV{W{W{W{W{W{W{W{W{W{W|W|W|W|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X}X}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLp䎲䎲䎲䎲䎲䎲䎲䎲Lp[]f^^f__f``f``g``ga`ga`ga`ga`ga`ga`gbagbagbaghdhmfiqiivki|okvpz¶پ搴濱´öŷǺzw~z~ɿƽúzpo|qo}rptrusxu{x~{ľпνμͼͻͻͻͻxrUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{W|W|W|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X}X}X}X}X}Y}Y}Y}Y}Y}Y}Y}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKpKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp䎲䎲䎲䎲䎲LpLpLqLq]^f__f``ga`gbagbagcagcagcagcagdbgdbhdbhechieiogisjixljpkxqz}ۿ°搴搴濱²²³³³³³³óóôôĵtpvrxt{w~z}¿˿ȼƺĸ¶µöķvsxu{w~y|ž¼оϽϽϼϼϼμͼUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{X|X|X|X|X|X|X|X|X|X|X|X}X}X}X}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp厲厲LqLqLqLqLqLq__fa`gb`gcagcagdbgdbgebgebhfchfchhdihejlgkqikukjzmjqkxqzy}o}m搴搴搴搴搴²óóĴĴĴŴĴŴŴŴrlsmsntoupwqys{v}x{~þͿ˽ɻǹƸŷŷĶĶĶõõĶĶŷƷǸȹɺʻ̼ξ~y{ƿüҿѾѾѾѽннϽVzVzVzVzVzVzVzVzV{V{V{W{W{W{W{W{W{X|X|X|X}X}X}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y~Y~Y~Y~Y~Y~Z~Z~Z~Z~Z~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLqMqMqMqMq``gbagcagdbgebgfchfchgchgdhhdijfjlhlpjnumnxml|olqkwpyv|n}nNrNr琴琴琵琵琵ĳŴŴƵƵƵƵǵslslsmsmtmtnuovpwqys{u}wy{}~Ŀýξ̽˼ʻʺɹɹȸȸȸȸȸɹʹʺ˻̼νϿ¼|ǿļºӿӿҿҾҾҾѾVzVzVzV{V{W{W{W{W{W{W{W{W{W{Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y~Y~Y~Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLq厳右MqMqMqMqMqMqMqMqa`gcagdbgebhfchgchhdhidhjeikgjnjmqmpzrr}rq~qnrlwowu|n~nNrNrNrNr琵瑵瑵瑵瑵ĴŴƵǵȶȶtltmtmtmtmtmtmununvowoxpyrzs|u}wxy{{ſƿƿſľý¼пνͼͼ̻̻˺˺˺˺˺̺̻ͼνϾѿ»z}ǿżúԿԿӿҿV{W{W{W{W{W{W{W{W{W|W|Y}Y}Y}Y}Y~Y~Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~ZZZ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLq右右右右右右MqMqMqMqMqMqMqa`gdbgfchfchhdhhdhjehkfilgjpknups~vwwvuqsmvnuu|nNrNrNrNrNrNrNr瑵瑵瑵瑵盖ŵǶȶtmtmumumumumumumumvnvnvnwowoxpyqzr{s|t}v~wwxûüû»ºҿѿоϽϽμμμλλμμϼнѾҿºyz|Ⱦżú¹ѾW{W{W{W{W|W|W|X|Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~ZZZZZ[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLqLqLqMq右右右右右右右右右MqMqMqMqMq[QIbagebhgchhdhidhjehkfimgjqkmwqs~wz~}{wuovm}rt|nNrNrNrNrNrNsNsNs瑵瑵葵葶葶qlsltmumumumvmvmvmvnvnvnvnwnwnwoxoxoypyqzq{r{s|t}t}u~uӿҿҾѾѽѽнннѽѽѾҾӿwxz|~ȾƼĺù¸¸W|W|X|X|X|Z~Z~Z~Z~Z~ZZZZ[[[[[[[[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLqLqLqLqLqLqLqLqMqMqMq右右右右右右右揳揳揳援MqMqMqMqMq]^gcahechgdhiehjeikfimgioikvoqyz{uvnzpt|nNrNrNrNsNsNsNsOsOsOs葶葶OsOsOsrltmumvmvmvnwnwnwnwnwnwnxnxnxoxoxoyoypzpzq{q{r|r|s|s}sԿԿԿԿӿӾӾӾӾӾӾӾӾԿԿvwxy{}~ʿȽƻźĹøø¸¸¸¸X|X|Z[[[[[[[[[[[[[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLqLqLqLqLqLqLqLqLqMqMqMqMqMq右右右右右揳揳揳援援援援援搴搴MqMqMrMr^_gdbhfchhdhjeilfimgiohjslm|uw|xpyot}o{nNsNsNsNsOsOsOsOsOsOsOsOsOsOsOsOtOtsmumvmvnwnwnxnxnxnxnxoxoyoyoyoyoyozpzpzp{q{q{q|r|r|r|rտտտտտտտտտտտտտtuvwxz{}~ɾȽƻźĹĸøøøøø¸X|X|[[[[[[[[[[\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LqLqLqLqLqLqMqMqMqMqMqMqMqMq右右揳揳揳援援援援援搴搴搴搴搴搴搴搴MrMrNr_`gdbhgdhieikfimgiohjqjkxpq|}}vxn}r~q{nNsNsOsOsOsOsOsOsOsOs蒶蒶OsOtOtOtPtPttmvnwnwnxnxnxnyoyoyoyozozozozozpzp{p{p{p{q|q|q|q|q|r|rֿ~ttuvvwxz{|}~~˿ʾɽȼǻƺŹĹĸĸĸĸøø¸X}X}Y}Y}[\\\\\\\\\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMqMqMqMqMqMqMq揳揳揳援援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴NrNrNr``hechhdijeilfingipijtlm~uv~yp{or{nOsOsOsOsOsOsOsOs蒶蒶蒶蒶蒶OtPtPtPtPtPtPtunwnxnxnyoyoyozozozozo{o{p{p{p{p{p|p|p|q|q|q}q}q}q}r}rssttuvvwxyz{|}}}~}}}|{zȼȻǻƺƹŹŹŹŹĹĹĹùY}Y}Y}Y}Y}Y}Y}\\\\\\\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMqMqMqMq援援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵NrNraahechheikfimgiohjrjkxop}|~vynr|oYTROsOsOsOsOsOs蒶蒶蒶钶钷钷钷铷PtPtPtPtPtPtPtvnxnxoyozozozo{o{p{p{p|p|p|p|p|p|q}q}q}q}q}q}q~q~r~rµ¶ssssttuuvvwxyyz{{{{{{{{zyxxǺǺƺƹƹƹŹŹŹŹĹY}Y}Y}Y}Y}Y}Y~Y~Y~Z~\\\\]]]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMq援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琵琵琵琵琵瑵瑵瑵Nraahfciieilfingjpijtlm}tu~zp|pqznOsOsOsOsOs蒶蒶钶钷钷钷铷铷铷铷铷PtPtPtPtPuPuPuwnxoyozozo{p{p|p|p|p|p}p}q}q}q}q}q~q~q~q~q~r~rrrrµµ¶¶ssssstttuuvvwwxxyyzzzzyyyxxwwwǺǺƹƹƹƹƹŹĹY}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMq搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵X\\gbahfdiieilgjohjqjkvno{{vzor|oOsOsOsOs钶钷钷钷铷铷铷铷铷铷铷铷铷ꓷPuPuPuQuQuQuQuxoyozo{p{p|p|p|p}p}q}q~q~q~q~q~q~qrrrrrrrrrösssssttttuuuvvvwwxxxxyyxxxxwwwwwvǺǺǺǺƺƺźY}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵蝡bbigdijeimgjohjskl{rr~{q|p~qynOs钶钷钷钷铷铷铷铷铷铷铷铷铷ꓷꓸꓸꓸQuQuQuQuQuQuQuQuxozp{p{p|p}p}q}q~q~q~q~qqrrrrrrrrrssĶĶsssstttttuuuvvvwwwwxxxxxxxwwwwwwwwȺǺǺǺƺĺY}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\搴搴搴搴搴琴琴琴琵琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葶葶蠢cbigdijfjmgjpikvmnyyvzor|o钷钷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꔸꔸꔸꔸꔸQuQuQuQuQuQuQvQvypzp{p|q}q}q~q~q~qqrrrrrrrrsssŶŶŶŷŷttttttuuuuuvvvvwwwwwwwwwwwwwwwwwwwȺǺƺY}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[[\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\琴琴琴琵琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葶葶葶葶蒶蒶蒶蠢hdikfjnhjrjlyqr{q|p´Լ铷铷铷铷铷铷铷铷ꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸ딸QuQuQvQvQvRvRvRvzp{p|q}q~q~qqrrrrrrrssssŶŷŷƷƷƷƷƷtttuuuuuuvvvvvwwwwwwwwwwwwwwwwwwwwǻY~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒍lgjohktlnvwwվµʸ铷铷铷铷ꓷꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹땹땹QvRvRvRvRvRvRvRvzp|q}q~q~rrrrrrsssssŷƷƷƷƷƷǷǷǸǸǸuuuuuuuvvvvvwwwwwwwwwwwwwwwwxxxxxY}Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\\\\\\]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蚟lgjpikwoqԿõ־铷铷ꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹땹땹땹땹땹땹RvRvRvRvRvRvRwRw|q|q~r~rrrrrssssƷƷƷƷǷǷǷǸǸȸȸȸȸȸuuuuvvvvvvwwwwwwwwwwxxxxxxxxxxY}Y}Y}Y}Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷霡rkmûԾµлꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹RvRvRvRvRwRwSwSwSwSw}r~rrrssssŷƷƷƷǷǷǸǸȸȸȸȸȸɹɹɹɹvvvvvvvwwwwwwwwxxxxxxxxxxxxxY}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]]^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\葵葵葶葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷钷铷锜mhkunqӾöؿꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺얺얺RwRwRwSwSwSwSwSwSwSwSwrsssŷŷƷƷǷǸǸȸȸȸȸɸɹɹɹɹʹʹʹʹvvvvwwwwwwwwxxxxxxxxxxxxxY}Y}Y~Y~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]]^^^^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷闞edjifknilzsuԾöԽꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺SwSwSwSwSwSwSwSxSxTxTxTxķŷŷƷƷǸǸǸȸȸȸɸɹɹɹʹʹʹʹʺ˺˺vvwwwwwwwxxxxxxxxxxxyyyY}Y}Y~Y~Z~Z~[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^^^_\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷铷铷铷铷鍙\\_iabjfdjjfkpkn~xzҽķꔸꔸ딸딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺햺햻햻SwSwSwSwSxSxTxTxTxŷƷƸǸǸȸȸɹɹɹɹʹʹʹʺ˺˺˺˺˺̺wwwwwwxxxxxxxxxyyyyyY}Y~Y~Z~Z~Z~[[[[\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^^______\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\蒶蒶蒶钶钶钶钷钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷ꓷPtPYhW]i]`ibbjfekkgltnr{tӾĸµվ딹딹딹땹땹땹땹땹땹땹땹땹앹앺앺얺얺얺얺얺얺얺얺햺햻햻헻헻헻SwSxSxTxTxTxTxɸǸȸȹɹɹɹʹʹʺʺ˺˺˺˺̺̻̻̻̻wwxxxxxxxxyyyyyyY}Y}Y~Z~Z~Z~Z~\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^__________`\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\钶钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸPtPtJVhRZhX]i]`jbcjgekmimwru~|wyp·ķ땹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺얺햺햻햻헻헻헻헻헻헻헻TxTxTxTxɹɹʹʺʺ˺˺˺˺̺̻̻̻ͻͻͻͻxxxxxxyyyyyyY}Y}Y~Y~Z~Z~Z~Z~\\\\\\\\]]]]]]]]^^^^^^^^_________``````\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸPtPtPtJVhMXhT[iY^i^ajccjgeknjo}uwzwxq{rvֿ땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻Tx̺˺˺̻̻̻̻ͻͻͻͼͼμμxxxyyyyY}Y}Y}Y}Y~Z~Z~Z~Z~Z~Z~]]]]]]]]^^^^^^^^________`````````aa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷铷铷铷铷铷铷ꓷꓷꓷꓸꓸꓸꓸꔸꔸPtPtPtPuJVhJVhOYiU\\iZ_j_ajcckhflpkputvqxpws}p땹땹땹앹앺앺앺얺얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻TxTx򕓒мѼѽѽѽX}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~]]]]^^^^^^^^________`````````aaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷ꓷꓷꓷꓸꓸꓸꓸꔸꔸꔸꔸPtPuPuPuPuPuJWhJWhJWhQZiV]i[_j`bkddkhglunpsqvpuv~qQv앹앺앺얺얺얺얺얺얺얺얺얺햺햻햻헻헻헻헻헻헻헻헻TxTxTyTyUyY}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z^^^^^^^^________````````aaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸPuPuPuPuQuQuQuJWhJWhJWhJWhR[iW]j\\`jabkedknjmzpoto|ty~qRvRvRv얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻TxTyTyUyUyUyUyY~Y~Z~Z~Z~Z~Z~Z~Z^^^^________````````aaaaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꔸꔸꔸꔸꔸꔸꔸPuPuQuQuQuQuQuQuJWhJWhJWhKWiKWiS\\iX^j]`kackgeltlnroyrzrIMSRvRvRv얺얺얺얺햺햻햻헻헻헻헻헻헻헻헻TxTyTyTyUyUyUyUyUyUyUyZ~Z~Z~Z~Z~Z________````````aaaaaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꔸꔸꔸꔸ딸QuQuQuQuQuQuQuQuQuKWiKWiKWiKWiKWiOZiT\\jY_j^akbcknimzonvp|sqRvRvRvRvRw햻햻햻헻헻헻헻헻헻헻헻TxTyTyUyUyUyUyUyUyUyUyUzUzVzZ~ZZ____````````aaaaaaaab\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\딹QuQuQuQuQuQuQuQuQuQuQuKWiKWiKWiKWiKWiMXiQ[jV]jZ_k_akbclumntp|trRvRvRwRwRwSwSw헻헻헻헻헻헻TyTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVz[````````aaaaaaabbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QuQuQuQuQuQuQuQuQuQuQuQvKWiKWiKXiKXiKXiKXiNYjS\\jW^k\\`k_bkqkm~ro{vRwRwRwRwSwSwSwSwSw헻헻헻TyTyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVz[````aaaaaaabbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QuQuQuQuQuQuQvQvQvQvKXiKXiKXiKXiKXiKXiLXiPZjT]jY_k]akmim{pozuRwSwSwSwSwSwSwSwSwSwSwTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzV{V{W{W{[[[[aaaaaaabbbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QvQvQvQvQvRvRvRvKXiKXiKXiKXiKXiKXiLXjMYjQ[jV]kZ`kigmwnn|sSwSwSwSwSwSwSwSwSwSxSxSxTxUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{[[[[\\\\\\aaabbbbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRvRvRvKXiKXiLXjLXjLXjLXjLXjOZjS\\kW^kigmtpsSwSwSwSwSwSwSwSwSxSxSxTxTxTxTxUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|[[[[\\\\\\\\\\\\bbbbbbbc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRvRvLXjLXjLXjLXjLXjMYjR[kW^k]alrosSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|[[[[\\\\\\\\\\\\\\]]bbbcc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRwRwLYjLYjLYjLYjT]kZ_lhfmuqSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|[[[\\\\\\\\\\\\\\]]]]]]cc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RwRwRwRwSwSwSwddmaclupr{SwSwSwSwSwSxSxSxSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}Y}Y}[[[\\\\\\\\\\\\\\]]]]]]]^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}[[[\\\\\\\\\\\\\\]]]]]]]^^^^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}Y}Y}Y}Y}Y}Y}Y}Y~Y~[\\\\\\\\\\\\\\]]]]]]]^^^^^^^__\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSxSxSxSxTxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyVzVzVzVzVzV{V{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~[\\\\\\\\\\\\\\]]]]]]]^^^^^^^____\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SxSxTxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyVzV{V{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~[\\\\\\\\\\\\\\]]]]]]]^^^^^^_______`\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzW{W{W{W{W{W{W{W|W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[\\\\\\\\\\\\\\]]]]]]]^^^^^^^_______````\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzUzW{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Z~Z~Z~Z~Z~Z~Z~Z[[[[[[\\\\\\\\\\\\\\]]]]]]]^^^^^^^______```````a\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUyUzUzVzVzW{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[\\\\\\\\\\\\\\\\]]]]]]]^^^^^^_______``````aaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzX|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~Z[[[[[[[[\\\\\\\\]]]]]]]^^^^^^^_______``````aaaaaabb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUyUyUyUyUyUzUzUzVzVzVzVzX|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\]]]]]]]^^^^^^^______```````aaaaaabbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUzUzUzVzVzVzVzVzVzX}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\]]]]^^^^^^_______``````aaaaaaabbbbbbcc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UzVzVzVzVzVzVzVzVzY}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\^^^^^^^_______``````aaaaaabbbbbbbccccc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VzVzVzVzVzVzY}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\^^^^^______```````aaaaaabbbbbbcccccccd\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VzVzVzV{Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\^_______``````aaaaaaabbbbbbccccccddddd\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\V{Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\_____``````aaaaaabbbbbbbccccccddddddee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\Z~ZZ[[[[[[[[\\\\\\\\\\\\_```````aaaaaabbbbbbcccccccddddddee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[[[[[[[\\\\\\\\\\\\\\`````aaaaaaabbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[[[[[\\\\\\\\\\\\\\\\``aaaaaaabbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[\\\\\\\\\\\\\\\\]aaaaabbbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\\\\\\\\\\]]aabbbbbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\\\\]]]bbbbbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]bbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]ccccccddddddeeeeeef\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]]ccddddddeeeeeeff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]^^^^dddddeeeeeeff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^dddeeeeeefff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^^__eeeeeffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^______eeffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^________`ffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^________`````ff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\"
  },
  {
    "path": "library/demos/items.tcl",
    "content": "# items.tcl --\n#\n# This demonstration script creates a canvas that displays the\n# canvas item types.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .items\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Canvas Item Demonstration\"\nwm iconname $w \"Items\"\npositionWindow $w\nset c $w.frame.c\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"This window contains a canvas widget with examples of the various kinds of items supported by canvases.  The following operations are supported:\\n  Left-Button drag:\\tmoves item under pointer.\\n  Middle-Button drag:\\trepositions view.\\n  Right-Button drag:\\tstrokes out area.\\n  Ctrl+f:\\t\\tprints items under area.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame\npack $w.frame -side top -fill both -expand yes\n\ncanvas $c -scrollregion {0c 0c 30c 24c} -width 15c -height 10c \\\n\t-relief sunken -borderwidth 2 \\\n\t-xscrollcommand \"$w.frame.hscroll set\" \\\n\t-yscrollcommand \"$w.frame.vscroll set\"\nttk::scrollbar $w.frame.vscroll -command \"$c yview\"\nttk::scrollbar $w.frame.hscroll -orient horizontal -command \"$c xview\"\n\nbind $c <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] deltaX deltaY\n    if {$deltaX != 0 || $deltaY != 0} {\n\ttk::ScrollByPixels %W $deltaX $deltaY\n    }\n}\n\ngrid $c -in $w.frame \\\n    -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.frame.vscroll \\\n    -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.frame.hscroll \\\n    -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid rowconfig    $w.frame 0 -weight 1 -minsize 0\ngrid columnconfig $w.frame 0 -weight 1 -minsize 0\n\n# Display a 3x3 rectangular grid.\n\n$c create rect 0c 0c 30c 24c -width 1.5p\n$c create line 0c 8c 30c 8c -width 1.5p\n$c create line 0c 16c 30c 16c -width 1.5p\n$c create line 10c 0c 10c 24c -width 1.5p\n$c create line 20c 0c 20c 24c -width 1.5p\n\nset font1 {Helvetica 12}\nset font2 {Helvetica 24 bold}\nif {[winfo depth $c] > 1} {\n    set blue DeepSkyBlue3\n    set red red\n    set bisque bisque3\n    set green SeaGreen3\n} else {\n    set blue black\n    set red black\n    set bisque black\n    set green black\n}\n\n# Set up demos within each of the areas of the grid.\n\n$c create text 5c .2c -text Lines -anchor n\n$c create line 1c 1c 3c 1c 1c 4c 3c 4c -width 2m -fill $blue \\\n\t-cap butt -join miter -tags item\n$c create line 4.67c 1c 4.67c 4c -arrow last -tags item\n$c create line 6.33c 1c 6.33c 4c -arrow both -tags item\n$c create line 5c 6c 9c 6c 9c 1c 8c 1c 8c 4.8c 8.8c 4.8c 8.8c 1.2c \\\n\t8.2c 1.2c 8.2c 4.6c 8.6c 4.6c 8.6c 1.4c 8.4c 1.4c 8.4c 4.4c \\\n\t-width 2.25p -fill $red -tags item\n# Main widget program sets variable tk_demoDirectory\n$c create line 1c 5c 7c 5c 7c 7c 9c 7c -width .5c \\\n\t-stipple @[file join $tk_demoDirectory images gray25.xbm] \\\n\t-arrow both -arrowshape {15 15 7} -tags item\n$c create line 1c 7c 1.75c 5.8c 2.5c 7c 3.25c 5.8c 4c 7c -width .5c \\\n\t-cap round -join round -tags item\n\n$c create text 15c .2c -text \"Curves (smoothed lines)\" -anchor n\n$c create line 11c 4c 11.5c 1c 13.5c 1c 14c 4c -smooth on \\\n\t-fill $blue -tags item\n$c create line 15.5c 1c 19.5c 1.5c 15.5c 4.5c 19.5c 4c -smooth on \\\n\t-arrow both -width 2.25p -tags item\n$c create line 12c 6c 13.5c 4.5c 16.5c 7.5c 18c 6c \\\n\t16.5c 4.5c 13.5c 7.5c 12c 6c -smooth on -width 3m -cap round \\\n\t-stipple @[file join $tk_demoDirectory images gray25.xbm] \\\n\t-fill $red -tags item\n\n$c create text 25c .2c -text Polygons -anchor n\n$c create polygon 21c 1.0c 22.5c 1.75c 24c 1.0c 23.25c 2.5c \\\n\t24c 4.0c 22.5c 3.25c 21c 4.0c 21.75c 2.5c -fill $green \\\n\t-outline {} -width 3p -tags item\n$c create polygon 25c 4c 25c 4c 25c 1c 26c 1c 27c 4c 28c 1c \\\n\t29c 1c 29c 4c 29c 4c -fill $red -outline {} -smooth on -tags item\n$c create polygon 22c 4.5c 25c 4.5c 25c 6.75c 28c 6.75c \\\n\t28c 5.25c 24c 5.25c 24c 6.0c 26c 6c 26c 7.5c 22c 7.5c \\\n\t-stipple @[file join $tk_demoDirectory images gray25.xbm] \\\n\t-fill $blue -outline {} -tags item\n\n$c create text 5c 8.2c -text Rectangles -anchor n\n$c create rectangle 1c 9.5c 4c 12.5c -outline $red -width 3m -tags item\n$c create rectangle 0.5c 13.5c 4.5c 15.5c -fill $green -tags item\n$c create rectangle 6c 10c 9c 15c -outline {} \\\n\t-stipple @[file join $tk_demoDirectory images gray25.xbm] \\\n\t-fill $blue -tags item\n\n$c create text 15c 8.2c -text Ovals -anchor n\n$c create oval 11c 9.5c 14c 12.5c -outline $red -width 3m -tags item\n$c create oval 10.5c 13.5c 14.5c 15.5c -fill $green -tags item\n$c create oval 16c 10c 19c 15c -outline {} \\\n\t-stipple @[file join $tk_demoDirectory images gray25.xbm] \\\n\t-fill $blue -tags item\n\n$c create text 25c 8.2c -text Text -anchor n\n$c create rectangle 22.4c 8.9c 22.6c 9.1c\n$c create text 22.5c 9c -anchor n -font $font1 -width 4c \\\n\t-text \"A short string of text, word-wrapped, justified left, and anchored north (at the top).  The rectangles show the anchor points for each piece of text.\" -tags item\n$c create rectangle 25.4c 10.9c 25.6c 11.1c\n$c create text 25.5c 11c -anchor w -font $font1 -fill $blue \\\n\t-text \"Several lines,\\n each centered\\nindividually,\\nand all anchored\\nat the left edge.\" \\\n\t-justify center -tags item\n$c create rectangle 24.9c 13.9c 25.1c 14.1c\ncatch {\n$c create text 25c 14c -font $font2 -anchor c -fill $red -angle 15 \\\n\t-text \"Angled characters\" -tags item\n}\n\n$c create text 5c 16.2c -text Arcs -anchor n\n$c create arc 0.5c 17c 7c 20c -fill $green -outline black \\\n\t-start 45 -extent 270 -style pieslice -tags item\n$c create arc 6.5c 17c 9.5c 20c -width 4m -style arc \\\n\t-outline $blue -start -135 -extent 270 -tags item \\\n\t-outlinestipple @[file join $tk_demoDirectory images gray25.xbm]\n$c create arc 0.5c 20c 9.5c 24c -width 4m -style pieslice \\\n\t-fill {} -outline $red -start 225 -extent -90 -tags item\n$c create arc 5.5c 20.5c 9.5c 23.5c -width 4m -style chord \\\n\t-fill $blue -outline {} -start 45 -extent 270  -tags item\n\n$c create text 15c 16.2c -text \"Bitmaps and Images\" -anchor n\ncatch {\nimage create photo items.ousterhout \\\n    -file [file join $tk_demoDirectory images ouster.png]\nimage create photo items.ousterhout.active -format \"png -alpha 0.5\" \\\n    -file [file join $tk_demoDirectory images ouster.png]\nset zoomFactor [expr {$tk::scalingPct / 100}]\nforeach img {items.ousterhout items.ousterhout.active} {\n    image create photo ${img}2\n    ${img}2 copy $img -zoom $zoomFactor\n}\n$c create image 13c 20c -tags item -image items.ousterhout2 \\\n    -activeimage items.ousterhout.active2\n}\n$c create bitmap 17c 18.5c -tags item \\\n\t-bitmap @[file join $tk_demoDirectory images noletter.xbm]\n$c create bitmap 17c 21.5c -tags item \\\n\t-bitmap @[file join $tk_demoDirectory images letters.xbm]\n\n$c create text 25c 16.2c -text Windows -anchor n\nbutton $c.button -text \"Press Me\" -command \"butPress $c $red\"\n$c create window 21c 18c -window $c.button -anchor nw -tags item\nentry $c.entry -width 20 -relief sunken\n$c.entry insert end \"Edit this text\"\n$c create window 21c 21c -window $c.entry -anchor nw -tags item\nscale $c.scale -from 0 -to 100 -length 6c -sliderlength .4c \\\n\t-width .5c -tickinterval 0\n$c create window 28.5c 17.5c -window $c.scale -anchor n -tags item\n$c create text 21c 17.9c -text Button: -anchor sw\n$c create text 21c 20.9c -text Entry: -anchor sw\n$c create text 28.5c 17.4c -text Scale: -anchor s\n\n# Set up event bindings for canvas:\n\n$c bind item <Enter> \"itemEnter $c\"\n$c bind item <Leave> \"itemLeave $c\"\nbind $c <Button-2> \"$c scan mark %x %y\"\nbind $c <B2-Motion> \"$c scan dragto %x %y\"\nbind $c <Button-3> \"itemMark $c %x %y\"\nbind $c <B3-Motion> \"itemStroke $c %x %y\"\nbind $c <<NextChar>> \"itemsUnderArea $c\"\nbind $c <Button-1> \"itemStartDrag $c %x %y\"\nbind $c <B1-Motion> \"itemDrag $c %x %y\"\n\n# Utility procedures for highlighting the item under the pointer:\n\nproc itemEnter {c} {\n    global restoreCmd\n\n    if {[winfo depth $c] == 1} {\n\tset restoreCmd {}\n\treturn\n    }\n    set type [$c type current]\n    if {$type == \"window\" || $type == \"image\"} {\n\tset restoreCmd {}\n\treturn\n    } elseif {$type == \"bitmap\"} {\n\tset bg [lindex [$c itemconf current -background] 4]\n\tset restoreCmd [list $c itemconfig current -background $bg]\n\t$c itemconfig current -background SteelBlue2\n\treturn\n    } elseif {$type == \"image\"} {\n\tset restoreCmd [list $c itemconfig current -state normal]\n\t$c itemconfig current -state active\n\treturn\n    }\n    set fill [lindex [$c itemconfig current -fill] 4]\n    if {(($type == \"rectangle\") || ($type == \"oval\") || ($type == \"arc\"))\n\t    && ($fill == \"\")} {\n\tset outline [lindex [$c itemconfig current -outline] 4]\n\tset restoreCmd \"$c itemconfig current -outline $outline\"\n\t$c itemconfig current -outline SteelBlue2\n    } else {\n\tset restoreCmd \"$c itemconfig current -fill $fill\"\n\t$c itemconfig current -fill SteelBlue2\n    }\n}\n\nproc itemLeave {c} {\n    global restoreCmd\n\n    eval $restoreCmd\n}\n\n# Utility procedures for stroking out a rectangle and printing what's\n# underneath the rectangle's area.\n\nproc itemMark {c x y} {\n    global areaX1 areaY1\n    set areaX1 [$c canvasx $x]\n    set areaY1 [$c canvasy $y]\n    $c delete area\n}\n\nproc itemStroke {c x y} {\n    global areaX1 areaY1 areaX2 areaY2\n    set x [$c canvasx $x]\n    set y [$c canvasy $y]\n    if {($areaX1 != $x) && ($areaY1 != $y)} {\n\t$c delete area\n\t$c addtag area withtag [$c create rect $areaX1 $areaY1 $x $y \\\n\t\t-outline black]\n\tset areaX2 $x\n\tset areaY2 $y\n    }\n}\n\nproc itemsUnderArea {c} {\n    global areaX1 areaY1 areaX2 areaY2\n    set area [$c find withtag area]\n    set items \"\"\n    foreach i [$c find enclosed $areaX1 $areaY1 $areaX2 $areaY2] {\n\tif {[lsearch [$c gettags $i] item] >= 0} {\n\t    lappend items $i\n\t}\n    }\n    puts stdout \"Items enclosed by area: $items\"\n    set items \"\"\n    foreach i [$c find overlapping $areaX1 $areaY1 $areaX2 $areaY2] {\n\tif {[lsearch [$c gettags $i] item] >= 0} {\n\t    lappend items $i\n\t}\n    }\n    puts stdout \"Items overlapping area: $items\"\n}\n\nset areaX1 0\nset areaY1 0\nset areaX2 0\nset areaY2 0\n\n# Utility procedures to support dragging of items.\n\nproc itemStartDrag {c x y} {\n    global lastX lastY\n    set lastX [$c canvasx $x]\n    set lastY [$c canvasy $y]\n}\n\nproc itemDrag {c x y} {\n    global lastX lastY\n    set x [$c canvasx $x]\n    set y [$c canvasy $y]\n    $c move current [expr {$x-$lastX}] [expr {$y-$lastY}]\n    set lastX $x\n    set lastY $y\n}\n\n# Procedure that's invoked when the button embedded in the canvas\n# is invoked.\n\nproc butPress {w color} {\n    set i [$w create text 25c 18.1c -text \"Oooohhh!!\" -fill $color -anchor n]\n    after 500 \"$w delete $i\"\n}\n"
  },
  {
    "path": "library/demos/ixset",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# ixset --\n# A nice interface to \"xset\" to change X server settings\n#\n# History :\n#   91/11/23 : pda@masi.ibp.fr, jt@ratp.fr : design\n#   92/08/01 : pda@masi.ibp.fr : cleaning\n\npackage require tk\n\n#\n# Button actions\n#\n\nproc quit {} {\n    destroy .\n}\n\nproc ok {} {\n    writesettings\n    quit\n}\n\nproc cancel {} {\n    readsettings\n    dispsettings\n    .buttons.apply configure -state disabled\n    .buttons.cancel configure -state disabled\n}\n\nproc apply {} {\n    writesettings\n    .buttons.apply configure -state disabled\n    .buttons.cancel configure -state disabled\n}\n\n#\n# Read current settings\n#\n\nproc readsettings {} {\n    global kbdrep ;\tset kbdrep\t\"on\"\n    global kbdcli ;\tset kbdcli\t0\n    global bellvol ;\tset bellvol\t100\n    global bellpit ;\tset bellpit\t440\n    global belldur ;\tset belldur\t100\n    global mouseacc ;\tset mouseacc\t\"3/1\"\n    global mousethr ;\tset mousethr\t4\n    global screenbla ;\tset screenbla\t\"blank\"\n    global screentim ;\tset screentim\t600\n    global screencyc ;\tset screencyc\t600\n\n    set xfd [open \"|xset q\" r]\n    while {[gets $xfd line] >= 0} {\n\tswitch -- [lindex $line 0] {\n\t    auto {\n\t\tset rpt [lindex $line 1]\n\t\tif {$rpt eq \"repeat:\"} {\n\t\t    set kbdrep [lindex $line 2]\n\t\t    set kbdcli [lindex $line 6]\n\t\t}\n\t    }\n\t    bell {\n\t\tset bellvol [lindex $line 2]\n\t\tset bellpit [lindex $line 5]\n\t\tset belldur [lindex $line 8]\n\t    }\n\t    acceleration: {\n\t\tset mouseacc [lindex $line 1]\n\t\tset mousethr [lindex $line 3]\n\t    }\n\t    prefer {\n\t\tset bla [lindex $line 2]\n\t\tset screenbla [expr {$bla eq \"yes\" ? \"blank\" : \"noblank\"}]\n\t    }\n\t    timeout: {\n\t\tset screentim [lindex $line 1]\n\t\tset screencyc [lindex $line 3]\n\t    }\n\t}\n    }\n    close $xfd\n\n    # puts stdout [format \"Key REPEAT = %s\\n\" $kbdrep]\n    # puts stdout [format \"Key CLICK  = %s\\n\" $kbdcli]\n    # puts stdout [format \"Bell VOLUME = %s\\n\" $bellvol]\n    # puts stdout [format \"Bell PITCH = %s\\n\" $bellpit]\n    # puts stdout [format \"Bell DURATION = %s\\n\" $belldur]\n    # puts stdout [format \"Mouse ACCELERATION = %s\\n\" $mouseacc]\n    # puts stdout [format \"Mouse THRESHOLD = %s\\n\" $mousethr]\n    # puts stdout [format \"Screen BLANCK = %s\\n\" $screenbla]\n    # puts stdout [format \"Screen TIMEOUT = %s\\n\" $screentim]\n    # puts stdout [format \"Screen CYCLE = %s\\n\" $screencyc]\n}\n\n\n#\n# Write settings into the X server\n#\n\nproc writesettings {} {\n    global kbdrep kbdcli  bellvol bellpit belldur\n    global mouseacc mousethr  screenbla screentim screencyc\n\n    set bellvol\t\t[.bell.vol get]\n    set bellpit\t\t[.bell.val.pit.entry get]\n    set belldur\t\t[.bell.val.dur.entry get]\n\n    if {$kbdrep eq \"on\"} {\n\tset kbdcli\t[.kbd.val.cli get]\n    } else {\n\tset kbdcli\t\"off\"\n    }\n\n    set mouseacc\t[.mouse.hor.acc.entry get]\n    set mousethr\t[.mouse.hor.thr.entry get]\n\n    set screentim\t[.screen.tim.entry get]\n    set screencyc\t[.screen.cyc.entry get]\n\n    exec xset \\\n\tb $bellvol $bellpit $belldur \\\n\tc $kbdcli \\\n\tr $kbdrep \\\n\tm $mouseacc $mousethr \\\n\ts $screentim $screencyc \\\n\ts $screenbla\n}\n\n\n#\n# Sends all settings to the window\n#\n\nproc dispsettings {} {\n    global kbdrep kbdcli  bellvol bellpit belldur\n    global mouseacc mousethr  screenbla screentim screencyc\n\n    .bell.vol set $bellvol\n    .bell.val.pit.entry delete 0 end\n    .bell.val.pit.entry insert 0 $bellpit\n    .bell.val.dur.entry delete 0 end\n    .bell.val.dur.entry insert 0 $belldur\n\n    .kbd.val.onoff [expr {$kbdrep eq \"on\" ? \"select\" : \"deselect\"}]\n    .kbd.val.cli set $kbdcli\n\n    .mouse.hor.acc.entry delete 0 end\n    .mouse.hor.acc.entry insert 0 $mouseacc\n    .mouse.hor.thr.entry delete 0 end\n    .mouse.hor.thr.entry insert 0 $mousethr\n\n    .screen.blank [expr {$screenbla eq \"blank\" ? \"select\" : \"deselect\"}]\n    .screen.pat   [expr {$screenbla ne \"blank\" ? \"select\" : \"deselect\"}]\n    .screen.tim.entry delete 0 end\n    .screen.tim.entry insert 0 $screentim\n    .screen.cyc.entry delete 0 end\n    .screen.cyc.entry insert 0 $screencyc\n}\n\n\n#\n# Create all windows, and pack them\n#\n\nproc labelentry {path text length {range {}}} {\n    frame $path\n    label $path.label -text $text\n    if {[llength $range]} {\n\tspinbox $path.entry -width $length -relief sunken \\\n\t\t-from [lindex $range 0] -to [lindex $range 1]\n    } else {\n\tentry $path.entry -width $length -relief sunken\n    }\n    pack $path.label -side left\n    pack $path.entry -side right -expand y -fill x\n}\n\nproc createwindows {} {\n    #\n    # Buttons\n    #\n\n    frame .buttons\n    button .buttons.ok\t   -default active -command ok     -text \"Ok\"\n    button .buttons.apply  -default normal -command apply  -text \"Apply\" \\\n\t    -state disabled\n    button .buttons.cancel -default normal -command cancel -text \"Cancel\" \\\n\t    -state disabled\n    button .buttons.quit   -default normal -command quit   -text \"Quit\"\n\n    pack .buttons.ok .buttons.apply .buttons.cancel .buttons.quit \\\n\t    -side left -expand yes -pady 3p\n\n    bind . <Return> {.buttons.ok   flash; .buttons.ok   invoke}\n    bind . <Escape> {.buttons.quit flash; .buttons.quit invoke}\n    bind . <Button-1> {\n\tif {![string match .buttons* %W]} {\n\t    .buttons.apply  configure -state normal\n\t    .buttons.cancel configure -state normal\n\t}\n    }\n    bind . <Key> {\n\tif {![string match .buttons* %W]} {\n\t    switch -glob %K {\n\t\tReturn - Escape - Tab - *Shift* {}\n\t\tdefault {\n\t\t    .buttons.apply  configure -state normal\n\t\t    .buttons.cancel configure -state normal\n\t\t}\n\t    }\n\t}\n    }\n\n    #\n    # Bell settings\n    #\n\n    labelframe .bell -text \"Bell Settings\" -padx 1.5m -pady 1.5m\n    scale .bell.vol \\\n\t    -from 0 -to 100 -length 150p -tickinterval 20 \\\n\t    -label \"Volume (%)\" -orient horizontal\n\n    frame .bell.val\n    labelentry .bell.val.pit \"Pitch (Hz)\"    6 {25 20000}\n    labelentry .bell.val.dur \"Duration (ms)\" 6 {1 10000}\n    pack .bell.val.pit -side left -padx 3p\n    pack .bell.val.dur -side right -padx 3p\n    pack .bell.vol .bell.val -side top -expand yes\n\n    #\n    # Keyboard settings\n    #\n\n    labelframe .kbd -text \"Keyboard Repeat Settings\" -padx 1.5m -pady 1.5m\n\n    frame .kbd.val\n    checkbutton .kbd.val.onoff \\\n\t    -text \"On\" \\\n\t    -onvalue \"on\" -offvalue \"off\" -variable kbdrep \\\n\t    -relief flat\n    scale .kbd.val.cli \\\n\t    -from 0 -to 100 -length 150p -tickinterval 20 \\\n\t    -label \"Click Volume (%)\" -orient horizontal\n    pack .kbd.val.onoff -side left -fill x -expand yes -padx {0 1m}\n    pack .kbd.val.cli -side left -expand yes -fill x -padx {1m 0}\n\n    pack .kbd.val -side top -expand yes -pady 1.5p -fill x\n\n    #\n    # Mouse settings\n    #\n\n    labelframe .mouse -text \"Mouse Settings\" -padx 1.5m -pady 1.5m\n\n    frame .mouse.hor\n    labelentry .mouse.hor.acc \"Acceleration\" 5\n    labelentry .mouse.hor.thr \"Threshold (pixels)\" 3 {1 2000}\n\n    pack .mouse.hor.acc -side left -padx {0 1m}\n    pack .mouse.hor.thr -side right -padx {1m 0}\n\n    pack .mouse.hor -side top -expand yes\n\n    #\n    # Screen Saver settings\n    #\n\n    labelframe .screen -text \"Screen-saver Settings\" -padx 1.5m -pady 1.5m\n\n    radiobutton .screen.blank \\\n\t    -variable screenblank -text \"Blank\" -relief flat \\\n\t    -value \"blank\" -variable screenbla -anchor w\n    radiobutton .screen.pat \\\n\t    -variable screenblank -text \"Pattern\" -relief flat \\\n\t    -value \"noblank\" -variable screenbla -anchor w\n    labelentry .screen.tim \"Timeout (s)\" 5 {1 100000}\n    labelentry .screen.cyc \"Cycle (s)\" 5 {1 100000}\n\n    grid .screen.blank .screen.tim -sticky e\n    grid .screen.pat   .screen.cyc -sticky e\n    grid configure .screen.blank .screen.pat -sticky ew\n\n    #\n    # Main window\n    #\n\n    pack .buttons -side top -fill both\n    pack .bell .kbd .mouse .screen -side top -fill both -expand yes \\\n\t    -padx 1m -pady 1m\n\n    #\n    # Let the user resize our window\n    #\n    wm minsize . 10 10\n}\n\n##############################################################################\n# Main program\n\n#\n# Listen what \"xset\" tells us...\n#\n\nreadsettings\n\n#\n# Create all windows\n#\n\ncreatewindows\n\n#\n# Write xset parameters\n#\n\ndispsettings\n\n#\n# Now, wait for user actions...\n#\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/knightstour.tcl",
    "content": "# Copyright © 2008 Pat Thoyts <patthoyts@users.sourceforge.net>\n#\n#\tCalculate a Knight's tour of a chessboard.\n#\n#\tThis uses Warnsdorff's rule to calculate the next square each\n#\ttime. This specifies that the next square should be the one that\n#\thas the least number of available moves.\n#\n#\tUsing this rule it is possible to get to a position where\n#\tthere are no squares available to move into. In this implementation\n#\tthis occurs when the starting square is d6.\n#\n#\tTo solve this fault an enhancement to the rule is that if we\n#\thave a choice of squares with an equal score, we should choose\n#\tthe one nearest the edge of the board.\n#\n#\tIf the call to the Edgemost function is commented out you can see\n#\tthis occur.\n#\n#\tYou can drag the knight to a specific square to start if you wish.\n#\tIf you let it repeat then it will choose random start positions\n#\tfor each new tour.\n\npackage require tk\n\n# Return a list of accessible squares from a given square\nproc ValidMoves {square} {\n    set moves {}\n    foreach pair {{-1 -2} {-2 -1} {-2 1} {-1 2} {1 2} {2 1} {2 -1} {1 -2}} {\n\tset col [expr {($square % 8) + [lindex $pair 0]}]\n\tset row [expr {($square / 8) + [lindex $pair 1]}]\n\tif {$row >= 0 && $row < 8 && $col >= 0 && $col < 8} {\n\t    lappend moves [expr {$row * 8 + $col}]\n\t}\n    }\n    return $moves\n}\n\n# Return the number of available moves for this square\nproc CheckSquare {square} {\n    variable visited\n    set moves 0\n    foreach test [ValidMoves $square] {\n\tif {[lsearch -exact -integer $visited $test] < 0} {\n\t    incr moves\n\t}\n    }\n    return $moves\n}\n\n# Select the next square to move to. Returns -1 if there are no available\n# squares remaining that we can move to.\nproc Next {square} {\n    variable visited\n    set minimum 9\n    set nextSquare -1\n    foreach testSquare [ValidMoves $square] {\n\tif {[lsearch -exact -integer $visited $testSquare] < 0} {\n\t    set count [CheckSquare $testSquare]\n\t    if {$count < $minimum} {\n\t\tset minimum $count\n\t\tset nextSquare $testSquare\n\t    } elseif {$count == $minimum} {\n\t\t# to remove the enhancement to Warnsdorff's rule\n\t\t# remove the next line:\n\t\tset nextSquare [Edgemost $nextSquare $testSquare]\n\t    }\n\t}\n    }\n    return $nextSquare\n}\n\n# Select the square nearest the edge of the board\nproc Edgemost {a b} {\n    set colA [expr {3-int(abs(3.5-($a%8)))}]\n    set colB [expr {3-int(abs(3.5-($b%8)))}]\n    set rowA [expr {3-int(abs(3.5-($a/8)))}]\n    set rowB [expr {3-int(abs(3.5-($b/8)))}]\n    return [expr {($colA * $rowA) < ($colB * $rowB) ? $a : $b}]\n}\n\n# Display a square number as a standard chess square notation.\nproc N {square} {\n    return [format %c%d [expr {97 + $square % 8}] [expr {$square / 8 + 1}]]\n}\n\n# Perform a Knight's move and schedule the next move.\nproc MovePiece {dlg last square} {\n    variable visited\n    variable delay\n    variable continuous\n    set line [format \"%2d. %s .. %s\" [llength $visited] [N $last] [N $square]]\n    $dlg.f.txt insert end $line\\n\n    $dlg.f.txt see end\n    $dlg.f.c itemconfigure [expr {1+$last}] -state normal -outline black\n    $dlg.f.c itemconfigure [expr {1+$square}] -state normal -outline red\n    $dlg.f.c moveto knight {*}[lrange [$dlg.f.c coords [expr {1+$square}]] 0 1]\n    lappend visited $square\n    set next [Next $square]\n    if {$next ne -1} {\n\tvariable aid [after $delay [list MovePiece $dlg $square $next]]\n    } else {\n\t$dlg.tf.b1 configure -state normal\n\tif {[llength $visited] == 64} {\n\t    variable initial\n\t    if {$initial == $square} {\n\t\t$dlg.f.txt insert end \"Closed tour!\"\n\t    } else {\n\t\t$dlg.f.txt insert end \"Success\"\n\t\tif {$continuous} {\n\t\t    after [expr {$delay * 2}] [namespace code \\\n\t\t\t[list Tour $dlg [expr {int(rand() * 64)}]]]\n\t\t}\n\t    }\n\t} else {\n\t    $dlg.f.txt insert end \"FAILED!\"\n\t}\n    }\n}\n\n# Begin a new tour of the board given a random start position\nproc Tour {dlg {square {}}} {\n    variable visited {}\n    $dlg.f.txt delete 1.0 end\n    $dlg.tf.b1 configure -state disabled\n    for {set n 0} {$n < 64} {incr n} {\n\t$dlg.f.c itemconfigure $n -state disabled -outline black\n    }\n    if {$square eq {}} {\n\tset coords [lrange [$dlg.f.c coords knight] 0 1]\n\tset square [expr {[$dlg.f.c find closest {*}$coords 0 65]-1}]\n    }\n    variable initial $square\n    after idle [list MovePiece $dlg $initial $initial]\n}\n\nproc Stop {} {\n    variable aid\n    catch {after cancel $aid}\n}\n\nproc Exit {dlg} {\n    Stop\n    destroy $dlg\n}\n\nproc SetDelay {newSpeed} {\n    variable speed [expr {int($newSpeed)}]\n    variable delay [expr {2000 - $speed}]\n}\n\nproc DragStart {w x y} {\n    $w dtag selected\n    $w addtag selected withtag current\n    variable dragging [list $x $y]\n}\nproc DragMotion {w x y} {\n    variable dragging\n    if {[info exists dragging]} {\n\t$w move selected [expr {$x - [lindex $dragging 0]}] \\\n\t    [expr {$y - [lindex $dragging 1]}]\n\tvariable dragging [list $x $y]\n    }\n}\nproc DragEnd {w x y} {\n    set square [$w find closest $x $y 0 65]\n    $w moveto selected {*}[lrange [$w coords $square] 0 1]\n    $w dtag selected\n    variable dragging ; unset dragging\n}\n\nproc CreateGUI {} {\n    catch {destroy .knightstour}\n    set dlg [toplevel .knightstour]\n    wm title $dlg \"Knight's Tour\"\n    wm withdraw $dlg\n    set f [ttk::frame $dlg.f]\n    set c [canvas $f.c -width 192p -height 192p]\n    text $f.txt -width 12 -height 1 -padx 3p \\\n\t-yscrollcommand [list $f.vs set] -font TkFixedFont\n    ttk::scrollbar $f.vs -command [list $f.txt yview]\n\n    variable speed 1400\n    variable delay [expr {2000 - $speed}]\n    variable continuous 0\n    ttk::frame $dlg.tf\n    ttk::label $dlg.tf.ls -text Speed\n    ttk::scale $dlg.tf.sc  -from 0 -to 1992 -command [list SetDelay] \\\n\t-variable [namespace which -variable speed]\n    ttk::checkbutton $dlg.tf.cc -text Repeat \\\n\t-variable [namespace which -variable continuous]\n    ttk::button $dlg.tf.b1 -text Start -command [list Tour $dlg]\n    ttk::button $dlg.tf.b2 -text Exit -command [list Exit $dlg]\n    set square 0\n    for {set row 7} {$row >= 0} {incr row -1} {\n\tfor {set col 0} {$col < 8} {incr col} {\n\t    if {(($col & 1) ^ ($row & 1))} {\n\t\tset fill tan3 ; set dfill tan4\n\t    } else {\n\t\tset fill bisque ; set dfill bisque3\n\t    }\n\t    set coords [list [expr {$col * 24 + 3}]p \\\n\t\t\t     [expr {$row * 24 + 3}]p \\\n\t\t\t     [expr {$col * 24 + 24}]p \\\n\t\t\t     [expr {$row * 24 + 24}]p]\n\t    $c create rectangle $coords -fill $fill -disabledfill $dfill \\\n\t\t-width 1.5p -state disabled -outline black\n\t}\n    }\n    if {[tk windowingsystem] ne \"x11\"} {\n\tcatch {eval font create KnightFont -size 18}\n\t$c create text 0 0 -font KnightFont -text \"♞\" \\\n\t    -anchor nw -tags knight -fill black -activefill \"#600000\"\n    } else {\n\t# On X11 we cannot reliably tell if the ♞ glyph is available\n\t# so just use a polygon\n\tset pts {\n\t    2 25   24 25  21 19   20 8   14 0   10 0    0 13  0 16\n\t    2 17    4 14   5 15    3 17   5 17   9 14  10 15  5 21\n\t}\n\t$c create polygon $pts -tag knight -offset 8 \\\n\t    -fill black -activefill \"#600000\"\n\tset scaleFactor [expr {$tk::scalingPct / 100.0}]\n\t$c scale knight 0 0 $scaleFactor $scaleFactor\n    }\n    $c moveto knight {*}[lrange [$c coords [expr {1 + int(rand() * 64)}]] 0 1]\n    $c bind knight <Button-1> [namespace code [list DragStart %W %x %y]]\n    $c bind knight <Motion> [namespace code [list DragMotion %W %x %y]]\n    $c bind knight <ButtonRelease-1> [namespace code [list DragEnd %W %x %y]]\n\n    grid $c $f.txt $f.vs  -sticky news\n    grid rowconfigure    $f 0 -weight 1\n    grid columnconfigure $f 1 -weight 1\n\n    grid $f - - - - - -sticky news\n    set things [list $dlg.tf.b1 $dlg.tf.cc $dlg.tf.sc $dlg.tf.ls]\n    if {![info exists ::widgetDemo]} {\n\tset things [linsert $things 0 $dlg.tf.b2]\n\tif {[tk windowingsystem] ne \"aqua\"} {\n\t    set things [linsert $things 0 [ttk::sizegrip $dlg.tf.sg]]\n\t}\n    }\n    pack {*}$things -side right -padx 1.5p -pady 1.5p\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tpack configure {*}$things -padx {4 4} -pady {12 12}\n\tpack configure [lindex $things 0] -padx {4 24}\n\tpack configure [lindex $things end] -padx {16 4}\n    }\n    grid $dlg.tf  - - - - - -sticky ew\n    if {[info exists ::widgetDemo]} {\n\tgrid [addSeeDismiss $dlg.buttons $dlg] - - - - - -sticky ew\n    }\n\n    grid rowconfigure $dlg 0 -weight 1\n    grid columnconfigure $dlg 0 -weight 1\n\n    bind $dlg <Control-F2> {console show}\n    bind $dlg <Return> [list $dlg.tf.b1 invoke]\n    bind $dlg <Escape> [list $dlg.tf.b2 invoke]\n    bind $dlg <Destroy> [namespace code [list Stop]]\n    wm protocol $dlg WM_DELETE_WINDOW [namespace code [list Exit $dlg]]\n\n    wm deiconify $dlg\n    tkwait window $dlg\n}\n\nif {![winfo exists .knightstour]} {\n    if {![info exists widgetDemo]} { wm withdraw . }\n    set r [catch [linsert $argv 0 CreateGUI] err]\n    if {$r} {\n\ttk_messageBox -icon error -title \"Error\" -message $err\n    }\n    if {![info exists widgetDemo]} { exit $r }\n}\n"
  },
  {
    "path": "library/demos/label.tcl",
    "content": "# label.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several label widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .label\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Label Demonstration\"\nwm iconname $w \"label\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Five labels are displayed below: three textual ones on the left, and an image label and a text label on the right.  Labels are pretty boring because you can't do anything with them.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.left\nframe $w.right\npack $w.left $w.right -side left -expand yes -padx 7.5p -pady 7.5p -fill both\n\nlabel $w.left.l1 -text \"First label\"\nlabel $w.left.l2 -text \"Second label, raised\" -relief raised\nlabel $w.left.l3 -text \"Third label, sunken\" -relief sunken\npack $w.left.l1 $w.left.l2 $w.left.l3 -side top -expand yes -pady 1.5p -anchor w\n\n# Main widget program sets variable tk_demoDirectory\nimage create photo label.ousterhout \\\n    -file [file join $tk_demoDirectory images ouster.png]\n\n# Create a copy of the image just created, magnified according to the\n# display's DPI scaling level.  Since the zooom factor must be an integer,\n# the copy will only be effectively magnified if $tk::scalingPct >= 200.\nimage create photo label.ousterhout2\nlabel.ousterhout2 copy label.ousterhout -zoom [expr {$tk::scalingPct / 100}]\n\nlabel $w.right.picture -borderwidth 2 -relief sunken -image label.ousterhout2\nlabel $w.right.caption -text \"Tcl/Tk Creator\"\npack $w.right.picture $w.right.caption -side top\n"
  },
  {
    "path": "library/demos/labelframe.tcl",
    "content": "# labelframe.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several labelframe widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .labelframe\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Labelframe Demonstration\"\nwm iconname $w \"labelframe\"\npositionWindow $w\n\n# Some information\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Labelframes are\\\n\tused to group related widgets together.  The label may be either \\\n\tplain text or another widget.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Demo area\n\nframe $w.f\npack $w.f -side bottom -fill both -expand 1\nset w $w.f\n\n# A group of radiobuttons in a labelframe\n\nlabelframe $w.f -text \"Value\" -padx 1.5p -pady 1.5p\ngrid $w.f -row 0 -column 0 -pady 2m -padx 2m\n\nforeach value {1 2 3 4} {\n    radiobutton $w.f.b$value -text \"This is value $value\" \\\n\t    -variable lfdummy -value $value\n    pack $w.f.b$value -side top -fill x -pady 1.5p\n}\n\n\n# Using a label window to control a group of options.\n\nproc lfEnableButtons {w} {\n    foreach child [winfo children $w] {\n\tif {$child == \"$w.cb\"} continue\n\tif {$::lfdummy2} {\n\t    $child configure -state normal\n\t} else {\n\t    $child configure -state disabled\n\t}\n    }\n}\n\nlabelframe $w.f2 -pady 1.5p -padx 1.5p\ncheckbutton $w.f2.cb -text \"Use this option.\" -variable lfdummy2 \\\n\t-command \"lfEnableButtons $w.f2\" -padx 0\n$w.f2 configure -labelwidget $w.f2.cb\ngrid $w.f2 -row 0 -column 1 -pady 2m -padx 2m\n\nset t 0\nforeach str {Option1 Option2 Option3} {\n    checkbutton $w.f2.b$t -text $str\n    pack $w.f2.b$t -side top -fill x -pady 1.5p\n    incr t\n}\nlfEnableButtons $w.f2\n\n\ngrid columnconfigure $w {0 1} -weight 1\n"
  },
  {
    "path": "library/demos/mac_styles.tcl",
    "content": "# mac_styles.tcl --\n#\n# This demonstration script creates a toplevel window containing a notebook\n# whose pages provide examples of the various mac-specific widgets that are\n# provided via special values for the -style option.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\nset w .mac_styles\ncatch {destroy $w}\ntoplevel $w\npackage require tk\nwm title $w \"Tk Aqua Widgets\"\nwm iconname $w \"mac_styles\"\npositionWindow $w\n##\n# System images we use in our buttons\n\nset featherImg [file join $tk_demoDirectory images Tk_feather.png]\nset starryImg [file join $tk_demoDirectory images starry_night.png]\nset fieldImg [file join $tk_demoDirectory images plowed_field.png]\nimage create nsimage action -source NSAction -width 48 -height 48\nimage create nsimage bonjour -source NSBonjour -width 48 -height 48\nimage create nsimage bonjour1 -source NSBonjour -width 48 -height 48 -pressed 1\nimage create nsimage tkfeather -source $featherImg -as file -width 48 -height 48\nimage create nsimage tkfeather1 -source $featherImg -as file -width 48 -height 48 -pressed 1\nimage create nsimage starry -source $starryImg -as file -width 96 -radius 10\nimage create nsimage starry1 -source $starryImg -as file -width 96 -radius 10 -pressed 1\nimage create nsimage starry2 -source $starryImg -as file -width 96 -radius 10 -ring 3\nimage create nsimage field -source $fieldImg -as file -width 96 -radius 10\nimage create nsimage field1 -source $fieldImg -as file -width 96 -radius 10 -pressed 1\nimage create nsimage field2 -source $fieldImg -as file -width 96 -radius 10 -ring 3\nimage create nsimage add -source NSAddTemplate -width 20 -height 20\nimage create nsimage remove -source NSRemoveTemplate -width 18 -height 4\n\n# Off state and variables for checkbuttons and radio buttons\nset off {!selected !alternate}\nvariable $w.checkVar\nvariable $w.radioVar\nvariable $w.triangleVar\nvariable $w.popupVar\nvariable $w.stepVar\nvariable $w.comboVar\n\n# Make a disclosure triangle change state when clicked.\nproc toggleTriangle {tri} {\n    $tri instate {user1} {\n\t$tri state {!user1}\n\treturn\n    }\n    $tri instate {!user1} {\n\t$tri state {user1}\n    }\n}\n\nproc popupButton {win varName firstValue args} {\n    upvar #0 $varName var\n    if {![info exists var]} {\n\tset var $firstValue\n    }\n    ttk::menubutton $win -textvariable $varName -menu $win.menu -direction flush\n    menu $win.menu -tearoff 0\n    $win.menu add radiobutton -label $firstValue -variable $varName\n    foreach i $args {\n\t$win.menu add radiobutton -label $i -variable $varName\n    }\n    return $win.menu\n}\n\nset mag [encoding convertfrom utf-8 \"\\xf0\\x9f\\x94\\x8d\"]\n\nproc searchFocusOut {e} {\n    global mag\n    if {[$e get] eq \"\"} {\n\t$e configure -foreground gray60\n\t$e insert 0 \"Search\"\n    }\n}\n\nproc searchFocusIn {e} {\n    if {[$e cget -foreground] == {gray60}} {\n\t$e delete 0 end\n\t$e configure -foreground black\n    }\n}\n\n## Make the notebook and set up Ctrl+Tab traversal\nttk::notebook $w.notebook\nttk::notebook::enableTraversal $w.notebook\n\n# Frames pane\nset framesFrame [ttk::frame $w.notebook.frames -padding {40 35 40 50}]\n$w.notebook add $framesFrame -text \"Frames\"\npack [ttk::labelframe $framesFrame.darker -text Darker -padding {50 30 50 50}] \\\n    -fill both -expand 1\npack [ttk::label $framesFrame.darker.label -padding {0 0 0 6} \\\n\t  -text \"This Group Box is nested to depth 2\"] \\\n    -fill x\npack [ttk::labelframe $framesFrame.darker.darker -text \"Darker Still\" -padding 24] \\\n    -fill both -expand 1\npack [ttk::label $framesFrame.darker.darker.label \\\n\t  -text \"This Group Box is nested to depth 3\"] -fill x\npack [button $framesFrame.darker.darker.tkbutton -text \"Tk Button\" -width 7 \\\n\t  -highlightbackground systemWindowBackgroundColor3] -pady 10\npack [ttk::button $framesFrame.darker.darker.ttkbutton -text \"Ttk Button\" \\\n\t  -width 7 -padding {-4 0 -4 0}] \\\n\t  -pady 3\n# Button pane\nset buttonFrame [ttk::frame $w.notebook.buttons -padding {100 20 0 20}]\n$w.notebook add $buttonFrame -text \"Buttons\"\ngrid columnconfigure $buttonFrame 0 -minsize 100\ngrid columnconfigure $buttonFrame 1 -minsize 100\n\nset plain [ttk::button $buttonFrame.plain -text Button -padding {-12 0}]\npopupButton $buttonFrame.options .popupVar \"Item 1\" \"Item 2\" \"Item 3\"\nset options $buttonFrame.options\nset check [ttk::checkbutton $buttonFrame.check -text Check -variable .checkVar]\nset radio [ttk::frame $buttonFrame.radio]\npack [ttk::radiobutton $radio.r1 -text \"Radio 1\" -variable .radioVar -value 1] -pady 4\npack [ttk::radiobutton $radio.r2 -text \"Radio 2\" -variable .radioVar -value 2] -pady 4\nset triangle [ttk::checkbutton $buttonFrame.triangle -style Item -variable TriangleVar]\nbind $triangle <Button-1> {toggleTriangle %W}\nset bonjour [ttk::button $buttonFrame.bonjour -style ImageButton -text Bonjour \\\n\t\t     -image {bonjour pressed bonjour1}]\nset feather [ttk::button $buttonFrame.feather -style ImageButton -text Tk \\\n\t\t      -image {tkfeather pressed tkfeather1}]\nset gradient [ttk::frame $buttonFrame.gradient]\npack [ttk::button $buttonFrame.gradient.add -style GradientButton \\\n\t  -image add -padding {2 0}] -side left\npack [ttk::button $buttonFrame.gradient.remove -style GradientButton \\\n\t  -image remove -padding {2 8}] -side left\nset disclosure [ttk::checkbutton $buttonFrame.disclosure -style DisclosureButton]\nset help [ttk::button $buttonFrame.help -style HelpButton];\n\n$check state $off\n$radio.r1 state $off\n$radio.r2 state $off\n\ngrid [ttk::label $buttonFrame.plainLabel -text \"Push Button:\"]\\\n    -row 0 -column 0 -padx 4 -sticky e\ngrid $plain -pady 4 -row 0 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.optionsLabel -text \"Pop-up Button:\"]\\\n    -row 1 -column 0 -padx 4 -sticky e\ngrid $options  -pady 4 -row 1 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.checkLabel -text \"Check Button:\"]\\\n    -row 2 -column 0 -padx 4 -sticky e\ngrid $check    -pady 4 -row 2 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.radioLabel -text \"Radio Buttons:\"]\\\n    -row 3 -column 0 -padx 4 -sticky e\ngrid $radio    -pady 4 -row 3 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.triangleLabel -text \"Disclosure Triangle:\"]\\\n    -row 4 -column 0 -padx 4 -sticky e\ngrid $triangle -pady 4 -row 4 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.disclosureLabel -text \"Disclosure Button:\"]\\\n    -row 5 -column 0 -padx 4 -sticky e\ngrid $disclosure -row 5 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.imageLabel -text \"Image Buttons:\"]\\\n    -row 7 -column 0 -padx 4 -sticky e\ngrid $bonjour -pady 4 -row 6 -rowspan 4 -column 1 -sticky w\ngrid $feather -padx 10 -pady 4 -row 6 -rowspan 4 -column 2\ngrid [ttk::label $buttonFrame.gradentLabel -text \"Gradient Buttons:\"]\\\n-row 10 -column 0 -padx 4 -sticky e\ngrid $gradient -pady 4 -row 10 -column 1 -sticky w\ngrid [ttk::label $buttonFrame.helpLabel -text \"Help Button:\"]\\\n-row 11 -column 0 -padx 4 -sticky e\ngrid $help -row 11 -column 1 -sticky w\n\n#ttk::button .f.b1 -style Toolbutton -image action\n#pack $buttonFrame\n\n# Entries Frame\nset entryFrame [ttk::frame $w.notebook.entries -padding {0 30 80 0}]\ngrid columnconfigure $entryFrame 0 -minsize 200\n$w.notebook add $entryFrame -text \"Entries\"\n\nset textfield [ttk::entry $entryFrame.text -width 17]\nset searchfield [ttk::entry $entryFrame.search -width 1]\nset combo [ttk::combobox $entryFrame.combo -width 1 -textvariable comboVar \\\n\t   -values {\"Item 1\" \"Item 2\" \"Item 3\"}]\nset stepper [ttk::spinbox $entryFrame.stepper -width 1 -textvariable stepVar \\\n\t\t -from 99000 -to 101000 -increment 1]\nset stepVar 100000\nsearchFocusOut $searchfield\nbind $searchfield <FocusIn> {searchFocusIn %W}\nbind $searchfield <FocusOut> {searchFocusOut %W}\n\ngrid [ttk::label $entryFrame.l0 -text \"Text Field\"] -row 0 -column 0 -padx 20 -sticky e\ngrid $textfield -sticky ew -row 0 -column 1 -pady 13\ngrid [ttk::label $entryFrame.l1 -text \"Search Field\"] -row 1 -column 0 -padx 20 -sticky e\ngrid $searchfield -sticky ew -row 1 -column 1 -pady 13\ngrid [ttk::label $entryFrame.l2 -text \"Combo Box\"] -row 2 -column 0 -padx 20 -sticky e\ngrid $combo -sticky ew -row 2 -column 1 -pady 13\ngrid [ttk::label $entryFrame.l3 -text \"Stepper\"] -row 3 -column 0 -padx 20 -sticky e\ngrid $stepper -sticky ew -row 3 -column 1 -pady 13\n\n#Scales Frame\nset scaleFrame [ttk::frame $w.notebook.scales -padding {0 40 0 80}]\n$w.notebook add $scaleFrame -text \"Scales\"\n\nvariable topVar 50\nset topSlider [ttk::scale $scaleFrame.topSlider -from 0 -to 100 \\\n\t\t   -length 280 -variable topVar]\nset topProgress [ttk::progressbar $scaleFrame.topProgress \\\n\t\t     -maximum 100 -variable topVar]\n\nvariable bottomVar 50\nset bottomSlider [ttk::scale $scaleFrame.bottomSlider -from 0 -to 100 \\\n\t\t      -length 280 -variable bottomVar]\n$bottomSlider state alternate\nset bottomProgress [ttk::progressbar $scaleFrame.bottomProgress \\\n\t\t    -maximum 100 -variable bottomVar]\n\n\ngrid $topSlider -padx 80 -pady 12 -sticky ew -row 0 -column 0 -columnspan 2\ngrid $topProgress -padx 120 -pady 15 -sticky ew -row 1 -column 0 -columnspan 2\ngrid [ttk::frame $scaleFrame.spacer] -row 2 -column 0 -columnspan 2 -pady 32\n\ngrid $bottomSlider -padx 80 -sticky new -row 3 -column 0 -columnspan 2\ngrid [ttk::label $scaleFrame.low -text Low -padding {70 0 0 0}] \\\n    -row 4 -column 0 -sticky sw\ngrid [ttk::label $scaleFrame.high -text High -padding {0 0 70 0}] \\\n    -row 4 -column 1 -sticky se\ngrid $bottomProgress -padx 120 -pady 15 -sticky ew -row 5 -column 0 -columnspan 2\n\n#Appearance Frame\nset appearanceFrame [ttk::frame $w.notebook.appearance -padding {0 40 0 80}]\ngrid [ttk::label $w.notebook.appearance.info -justify left -padding {0 20 0 40}\\\n\t  -text \"Use the image buttons below to view this demo in light or dark mode.\"] \\\n    -row 0 -column 0 -columnspan 3\nset light [ttk::button $appearanceFrame.light -style ImageButton -text Light \\\n\t       -image {field pressed field1 selected field2} \\\n\t       -command \"beLight $appearanceFrame $w\"]\ngrid columnconfigure $appearanceFrame 1 -minsize 10\ngrid $light -row 1 -column 0 -sticky e\nset dark [ttk::button $appearanceFrame.dark -style ImageButton -text Dark \\\n\t      -image {starry pressed starry1 selected starry2} \\\n\t      -command \"beDark $appearanceFrame $w\"]\ngrid $dark -row 1 -column 2 -sticky w\nif { [wm attributes $w -isdark] } {\n    $dark state selected\n} else {\n    $light state selected\n}\nproc beLight {f w} {\n    wm attributes $w -appearance aqua\n    # A small delay is needed for the appearance change to complete.\n    after 20 [list $f.dark state !selected]\n    after 20 [list $f.light state selected]\n}\n\nproc beDark {f w} {\n    wm attributes $w -appearance darkaqua\n    # A small delay is needed for the appearance change to complete.\n    after 20 [list $f.light state !selected]\n    after 20 [list $f.dark state selected]\n}\n$w.notebook add $appearanceFrame -text \"Appearance\"\n\n## See Code / Dismiss\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\n## Notebook\npack $w.notebook -side bottom -fill both -expand 1 -padx 16 -pady 16\n\n"
  },
  {
    "path": "library/demos/mac_tabs.tcl",
    "content": "# mac_tabs.tcl --\n#\n# This demonstration script creates three tabbable windows and allows the\n# wm attributes tabbingid and tabbingmode to be manipulated for the third\n# window, to demonstrate the effects of those attributes.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\ncatch {font create giant -family {Times New Roman} -size 64}\nset w .mac_tabs\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Tabbed Windows in Aqua\"\nwm iconname $w \"mac_tabs\"\npositionWindow $w\nset suffix 0\nset winlist {}\n##\n\n## See Code / Dismiss\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n##\nset info \"\\\nThis demo shows 3 toplevels, A, B, and C.  \\\nEach of these has tabbingmode set to preferred. \\\nThe tabbingid of Window A is groupA, the \\\ntabbingid of Window B is groupB and the tabbingid \\\nof Window C is groupC.  Use the menubuttons below \\\nto see the effect of changing the tabbingid and \\\ntabbingmode attributes for Window C. \\\n\"\npack [message $w.info -text $info -width 300]\nwm geometry $w +450+350\n\nttk::frame $w.f\nmenu $w.idmenu -tearoff 0\nforeach id {groupA groupB groupC} {\n    $w.idmenu add command -label $id \\\n\t-command [list wm attributes $w.c -tabbingid $id]\n}\nmenu $w.modemenu -tearoff 0\nforeach mode {auto preferred disallowed} {\n    $w.modemenu add command -label $mode \\\n\t-command [list wm attributes $w.c -tabbingmode $mode]\n}\nttk::menubutton $w.f.idbutton -menu $w.idmenu -text \"tabbingid\"\\\n    -direction below\ngrid $w.f.idbutton -row 0 -column 0\nttk::menubutton $w.f.modebutton -menu $w.modemenu -text \"tabbingmode\"\\\n    -direction below\ngrid $w.f.modebutton -row 1 -column 0\npack $w.f\n\nwm attributes $w.a -tabbingid groupA\nwm attributes $w.a -tabbingmode preferred\ntoplevel $w.a\nwm geometry $w.a +50+100\nwm title $w.a \"Window A\"\npack [ttk::label $w.a.l -text A -font giant] -padx 100 -pady 30\n\nwm attributes $w.b -tabbingid groupB\nwm attributes $w.b -tabbingmode preferred\ntoplevel $w.b\nwm geometry $w.b +400+100\nwm title $w.b \"Window B\"\npack [ttk::label $w.b.l -text B -font giant] -padx 100 -pady 30\n\nwm attributes $w.c -tabbingid groupC\nwm attributes $w.c -tabbingmode preferred\ntoplevel $w.c\nwm geometry $w.c +750+100\nwm title $w.c \"Window C\"\npack [ttk::label $w.c.l -text C -font giant] -padx 100 -pady 30\n"
  },
  {
    "path": "library/demos/mac_wm.tcl",
    "content": "# mac_window_styles.tcl --\n#\n# This demonstration script creates a toplevel window containing a notebook\n# whose pages provide examples of the various mac-specific widgets that are\n# provided via special values for the -style option.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .mac_wm\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Tk Aqua Window Styles\"\nwm iconname $w \"mac_wm\"\npositionWindow $w\nset suffix 0\nset winlist {}\n##\n\n## See Code / Dismiss\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\nproc launch {name windowInfo class} {\n    if {[winfo exists $name]} {\n\twm deiconify $name\n\tfocus -force $name\n\treturn\n    }\n    wm attributes $name -class $class; toplevel $name\n    wm title $name $class\n    set f $name.f\n    ttk::frame $f\n    set t $f.t\n    text $t -background systemWindowBackgroundColor \\\n\t-highlightcolor systemWindowBackgroundColor \\\n\t-font systemDefaultFont\\\n\t-wrap word -width 50 -height 6\n    $t insert insert $windowInfo\n    $t configure -state disabled\n    grid columnconfigure $f 0 -weight 1\n    grid $t -row 0 -column 0 -columnspan 2 -sticky NSEW\n    ttk::labelframe $f.stylemask -text \"styleMask bits\"\n    # titled\n    if {$class == \"nswindow\"} {\n       ttk::checkbutton $f.stylemask.titled -text titled -variable $name.titled \\\n\t  -command [list setbit $name $f.stylemask.titled titled]\n       $f.stylemask.titled state selected\n       grid $f.stylemask.titled -row 0 -column 0 -sticky w\n    }\n    # closable\n    ttk::checkbutton $f.stylemask.closable -text closable -variable $name.closable \\\n\t-command [list setbit $name $f.stylemask.closable closable]\n    $f.stylemask.closable state selected\n    grid $f.stylemask.closable -row 1 -column 0 -sticky w\n    # miniaturizableable\n    ttk::checkbutton $f.stylemask.miniaturizable -text miniaturizable \\\n\t-variable $name.miniaturizable \\\n\t-command [list setbit $name $f.stylemask.miniaturizable miniaturizable]\n    if {$class == \"nswindow\"} {\n\t$f.stylemask.miniaturizable state selected\n    } else {\n\t$f.stylemask.miniaturizable state !alternate\n    }\n    grid $f.stylemask.miniaturizable -row 2 -column 0 -sticky w\n    # resizable\n    ttk::checkbutton $f.stylemask.resizable -text resizable -variable $name.resizable \\\n\t-command [list setbit $name $f.stylemask.resizable resizable]\n    $f.stylemask.resizable state selected\n    grid $f.stylemask.resizable -row 3 -column 0 -sticky w\n    # docmodal\n    ttk::checkbutton $f.stylemask.docmodal -text docmodal -variable $name.docmodal \\\n\t-command [list setbit $name $f.stylemask.docmodal docmodal]\n    $f.stylemask.docmodal state !alternate\n    grid $f.stylemask.docmodal -row 4 -column 0 -sticky w\n\n    grid $f.stylemask -row 1 -column 0\n    pack $name.f -side bottom -fill both -expand 1 -padx 16 -pady 16\n}\n\nset info \"The command wm attributes window -stylemask ?bitnames? can \\\nbe used to modify bits in the stylemask property of the NSWindow or \\\nNSPanel underlying a Tk Window.  Changing these bits causes the \\\nstyle of the window to change.  This demo allows you to see the \\\neffects of changing the bits.  (Note that buttons in the title bar \\\ncan also be enabled or disabled with the ::tk::unsupported::MacWindowStyle \\\ncommand.)\"\n\nset panelInfo \"A toplevel based on an NSPanel has a narrower title bar\\\nthan one based on an NSWindow.  In addition the panel remains above all\\\nwindows on the screen, regardless of which app is active. These are\\\nintended to be used as modal windows.\"\n\nset windowInfo \"This is a standard Apple document window, based on an\\\nNSWindow.  It has a larger title bar and behaves normally with respect\\\nto other windows from the same or another app.\"\n\n## background frame\nset f $w.f\nttk::frame $f\nset t $f.t\ntext $t -background systemWindowBackgroundColor \\\n    -highlightcolor systemWindowBackgroundColor \\\n    -font systemDefaultFont\\\n    -wrap word -width 50 -height 8\n$t insert insert $info\n$t configure -state disabled\ngrid columnconfigure $f 0 -weight 1\ngrid $t -row 0 -column 0 -columnspan 2 -sticky NSEW\nttk::labelframe $f.stylemask -text \"styleMask\"\ngrid $f.stylemask -row 1 -column 0\ngrid [ttk::button $f.wbw -text \"Open an NSWindow\" -width 20 \\\n\t  -command [list launch .nswindow $windowInfo nswindow]] -row 2 -column 0\ngrid [ttk::button $f.wbp -text \"Open an NSPanel\" -width 20 \\\n\t  -command [list launch .nspanel $panelInfo nspanel]] -row 3 -column 0\ngrid [ttk::button $f.wbm -text \"Open a modern window\" -width 20 \\\n\t  -command launchModernWindow] -row 4 -column 0\npack $w.f -side bottom -fill both -expand 1 -padx 16 -pady 16\n\nproc setbit {win cb bitname} {\n    set state [$cb instate selected]\n    set bits [wm attributes $win -stylemask]\n    set index [lsearch $bits $bitname]\n    if {$index >= 0 && !$state} {\n\tset bits [lreplace $bits $index $index]\n    }\n    if {$index < 0 && $state} {\n\tlappend bits $bitname\n    }\n    wm attributes $win -stylemask $bits\n}\n\nset aboutText \\\n\"Most of the apps which ship with a contemporary version of macOS \\\nfeature a window similar to this one, with a left sidebar that \\\nallows selecting the content to be shown on the right hand side of \\\nthe window.  These windows do not have a (visible) titlebar.\\\n\\n\\nApps that use such windows include the Finder and the App Store as \\\nwell as Notes, Messages, Books, Maps and many others.\\\n\\n\\nTo create a window like this one in Tk simply set the fullsizecontent bit \\\nin the stylemask. For example:\\n\\n\"\n\nset aboutCode \\\n\"wm attributes .t -stylemask {titled \\\\\\\n\\nfullsizecontent closable miniaturizable \\\\\\\n\\nresizable}\\n\\n\"\n\nset detailsText \\\n\"(1) In the Apple API, setting the fullsizecontent bit in the stylemask \\\nonly allows content to be drawn in the part of the window covered by \\\nthe titlebar.  In order for that content to be visible the title bar \\\nmust be transparent.  Since it would be pointless to draw content under \\\nan opaque title bar, Tk makes the title bar transparent whenever the \\\nfullsizecontent bit is set.\\\n\n\\n\\n\\(2) Each radio button in the sidebar is a standard ttk::radiobutton \\\nbut created with a special value for its -style option.  The value of the \\\n-style option used to create these buttons is SidebarButton.\\n\"\n\nset whichPage 1\ntrace add variable whichPage write \"flipPage whichPage\"\nproc flipPage {varname args} {\n    global whichPage\n    set newpage [set $varname]\n    grid remove [grid content .mod.right -row 0 -column 0]\n    switch $newpage\\\n\t1 {grid .mod.right.about -padx 30 -pady 30 -row 0 -column 0 -sticky nsew}\\\n\t2 {grid .mod.right.details -padx 30 -pady 30 -row 0 -column 0 -sticky nsew}\n    update idletasks\n}\n\nproc launchModernWindow {} {\n    global whichPage\n    global aboutText\n    global aboutCode\n    global detailsText\n    if {[winfo exists .mod]} {\n\twm deiconify .mod\n\tfocus -force .mod\n\treturn\n    }\n    toplevel .mod\n    wm title .mod {}\n    wm attributes .mod -stylemask {titled fullsizecontent closable \\\n\t\t\t\t       miniaturizable resizable}\n    .mod configure -background white\n    grid columnconfigure .mod 0 -weight 0\n    grid columnconfigure .mod 1 -weight 1\n    grid rowconfigure .mod 0 -weight 1\n    frame .mod.left -width 220 -height 400 -background systemWindowBackgroundColor\n    catch {\n\tfont create leftFont -family .AppleSystemUIFont -size 11\n\tfont create rightFont -family .AppleSystemUIFont -size 16\n\tfont create codeFont -family Courier -size 16\n    }\n    grid [ttk::label .mod.left.spacer -padding {220 30 0 0}] -row 0 -column 0\n    grid [ttk::radiobutton .mod.left.about -text About -style SidebarButton \\\n\t      -variable whichPage -value 1] \\\n\t-row 1 -column 0 -sticky nsew -padx 14\n    grid [ttk::radiobutton .mod.left.details -text Details -style SidebarButton \\\n\t-variable whichPage -value 2] \\\n\t-row 2 -column 0 -sticky nsew -padx 14\n    grid .mod.left -row 0 -column 0 -sticky nsew\n    frame .mod.right -width 500 -background systemTextBackgroundColor\n    grid rowconfigure .mod.right 0 -weight 0\n    text .mod.right.about -highlightcolor systemTextBackgroundColor \\\n\t-background systemTextBackgroundColor -font rightFont \\\n\t-highlightthickness 0 -wrap word -width 40\n    .mod.right.about tag configure code -font codeFont\n    .mod.right.about insert end $aboutText\n    .mod.right.about insert end $aboutCode code\n    .mod.right.about configure -state disabled\n\n    text .mod.right.details -highlightcolor systemTextBackgroundColor \\\n\t-background systemTextBackgroundColor -font rightFont\\\n\t-highlightthickness 0 -wrap word -width 40\n    .mod.right.details insert end $detailsText\n    .mod.right.details configure -state disabled\n\n    grid .mod.right.about -padx 30 -pady 30 -row 0 -column 0 -sticky nsew\n    grid .mod.right -row 0 -column 1 -sticky nsew\n    wm geometry .mod 800x500\n    update idletasks\n}\n\n"
  },
  {
    "path": "library/demos/mclist.tcl",
    "content": "# mclist.tcl --\n#\n# This demonstration script creates a toplevel window containing a Ttk\n# tree widget configured as a multi-column listbox.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .mclist\ncatch {destroy $w}\ntoplevel $w -class MCList\nwm title $w \"Multi-Column List\"\nwm iconname $w \"mclist\"\npositionWindow $w\n\n## Explanatory text\nttk::label $w.msg -font $font -wraplength 4i -justify left -anchor n -padding {10 2 10 6} -text \"Ttk is the new Tk themed widget set. One of the widgets it includes is a tree widget, which can be configured to display multiple columns of informational data without displaying the tree itself. This is a simple way to build a listbox that has multiple columns. Clicking on the heading for a column will sort the data by that column. You can also change the width of the columns by dragging the boundary between them.\"\npack $w.msg -fill x\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w {} {\n    ttk::checkbutton $w.seeDismiss.cb1 -text Grid -variable mclistGrid -command tglGrid\n}] -side bottom -fill x\n\n\nttk::frame $w.container\nttk::treeview $w.tree -columns {country capital currency} -show headings \\\n    -yscroll \"$w.vsb set\" -xscroll \"$w.hsb set\"\nttk::scrollbar $w.vsb -orient vertical -command \"$w.tree yview\"\nttk::scrollbar $w.hsb -orient horizontal -command \"$w.tree xview\"\npack $w.container -fill both -expand 1\ngrid $w.tree $w.vsb -in $w.container -sticky nsew\ngrid $w.hsb         -in $w.container -sticky nsew\ngrid column $w.container 0 -weight 1\ngrid row    $w.container 0 -weight 1\n\nset upArrowData {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"4\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"m4 4 4-4 4 4z\" fill=\"%s\"/>\n    </svg>\n}\n\nset downArrowData {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"4\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"m4 0 4 4 4-4z\" fill=\"%s\"/>\n    </svg>\n}\n\nproc createArrowImages {} {\n    set fgColor [ttk::style lookup . -foreground {} black]\n    lassign [winfo rgb . $fgColor] r g b\n    set fgColor [format \"#%02x%02x%02x\" \\\n\t    [expr {$r >> 8}] [expr {$g >> 8}] [expr {$b >> 8}]]\n\n    foreach dir {up down} {\n\tupvar ${dir}ArrowData imgData\n\tset data [format $imgData $fgColor]\n\timage create photo ${dir}Arrow -format $::tk::svgFmt -data $data]\n    }\n}\n\ncreateArrowImages\nforeach event {<<ThemeChanged>> <<LightAqua>> <<DarkAqua>>} {\n    bind MCList $event { createArrowImages }\n}\nunset event\n\nimage create photo noArrow -format $tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"4\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    </svg>\n}\n\n## The data we're going to insert\nset data {\n    Argentina\t\t{Buenos Aires}\t\tARS\n    Australia\t\tCanberra\t\tAUD\n    Brazil\t\tBrazilia\t\tBRL\n    Canada\t\tOttawa\t\t\tCAD\n    China\t\tBeijing\t\t\tCNY\n    France\t\tParis\t\t\tEUR\n    Germany\t\tBerlin\t\t\tEUR\n    India\t\t{New Delhi}\t\tINR\n    Italy\t\tRome\t\t\tEUR\n    Japan\t\tTokyo\t\t\tJPY\n    Mexico\t\t{Mexico City}\t\tMXN\n    Russia\t\tMoscow\t\t\tRUB\n    {South Africa}\tPretoria\t\tZAR\n    {United Kingdom}\tLondon\t\t\tGBP\n    {United States}\t{Washington, D.C.}\tUSD\n}\n\n## Code to insert the data nicely\nset font [ttk::style lookup Heading -font {} TkDefaultFont]\nset morePx [expr {[image width noArrow] + round(4 * $tk::scalingPct / 100.0)}]\nforeach col {country capital currency} name {Country Capital Currency} {\n    $w.tree heading $col -text $name -image noArrow -anchor w \\\n\t-command [list SortBy $w.tree $col 1]\n    $w.tree column $col -width [expr {[font measure $font $name] + $morePx}]\n}\nset font [ttk::style lookup Treeview -font {} TkDefaultFont]\nforeach {country capital currency} $data {\n    $w.tree insert {} end -values [list $country $capital $currency]\n    foreach col {country capital currency} {\n\tset len [font measure $font \"[set $col]  \"]\n\tif {[$w.tree column $col -width] < $len} {\n\t    $w.tree column $col -width $len\n\t}\n    }\n}\n\n## Code to do the sorting of the tree contents when clicked on\nproc SortBy {tree col direction} {\n    # Determine currently sorted column and its sort direction\n    foreach c {country capital currency} {\n\tset s [$tree heading $c state]\n\tif {(\"selected\" in $s || \"alternate\" in $s) && $col ne $c} {\n\t    # Sorted column has changed\n\t    $tree heading $c -image noArrow state {!selected !alternate !user1}\n\t    set direction [expr {\"alternate\" in $s}]\n\t}\n    }\n\n    # Build something we can sort\n    set data {}\n    foreach row [$tree children {}] {\n\tlappend data [list [$tree set $row $col] $row]\n    }\n\n    set dir [expr {$direction ? \"-increasing\" : \"-decreasing\"}]\n    set r -1\n\n    # Now reshuffle the rows into the sorted order\n    foreach info [lsort -dictionary -index 0 $dir $data] {\n\t$tree move [lindex $info 1] {} [incr r]\n    }\n\n    # Switch the heading so that it will sort in the opposite direction\n    $tree heading $col -command [list SortBy $tree $col [expr {!$direction}]] \\\n\tstate [expr {$direction?\"!selected alternate\":\"selected !alternate\"}]\n    if {[ttk::style theme use] eq \"aqua\"} {\n\t# Aqua theme displays native sort arrows when user1 state is set\n\t$tree heading $col state \"user1\"\n    } else {\n\t$tree heading $col -image [expr {$direction?\"upArrow\":\"downArrow\"}]\n    }\n}\n\nset mclistGrid 0\nproc tglGrid {} {\n    if {$::mclistGrid} {\n\t.mclist.tree configure -stripe 1\n\tforeach col [.mclist.tree cget -columns] {\n\t    .mclist.tree column $col -separator 1\n\t}\n    } else {\n\t.mclist.tree configure -stripe 0\n\tforeach col [.mclist.tree cget -columns] {\n\t    .mclist.tree column $col -separator 0\n\t}\n    }\n}\n"
  },
  {
    "path": "library/demos/menu.tcl",
    "content": "# menu.tcl --\n#\n# This demonstration script creates a window with a bunch of menus\n# and cascaded menus using menubars.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .menu\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Menu Demonstration\"\nwm iconname $w \"menu\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left\nif {[tk windowingsystem] eq \"aqua\"} {\n    $w.msg configure -text \"This window has a menubar with cascaded menus.  You can invoke entries with an accelerator by typing Command+x, where \\\"x\\\" is the character next to the command key symbol. The rightmost menu can be torn off into a palette by selecting the first item in the menu.\"\n} else {\n    $w.msg configure -text \"This window contains a menubar with cascaded menus.  You can post a menu from the keyboard by typing Alt+x, where \\\"x\\\" is the character underlined on the menu.  You can then traverse among the menus using the arrow keys.  When a menu is posted, you can invoke the current entry by typing space, or you can invoke any entry by typing its underlined character.  If a menu entry has an accelerator, you can invoke the entry without posting the menu just by typing the accelerator. The rightmost menu can be torn off into a palette by selecting the first item in the menu.\"\n}\npack $w.msg -side top\n\nset menustatus \"    \"\nframe $w.statusBar\nlabel $w.statusBar.label -textvariable menustatus -relief sunken -bd 1 -font \"Helvetica 10\" -anchor w\npack $w.statusBar.label -side left -padx 2 -expand yes -fill both\npack $w.statusBar -side bottom -fill x -pady 2\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nmenu $w.menu -tearoff 0\n\nset m $w.menu.file\nmenu $m -tearoff 0\n$w.menu add cascade -label \"File\" -menu $m -underline 0\n$m add command -label \"Open...\" -command {error \"this is just a demo: no action has been defined for the \\\"Open...\\\" entry\"}\n$m add command -label \"New\" -command {error \"this is just a demo: no action has been defined for the \\\"New\\\" entry\"}\n$m add command -label \"Save\" -command {error \"this is just a demo: no action has been defined for the \\\"Save\\\" entry\"}\n$m add command -label \"Save As...\" -command {error \"this is just a demo: no action has been defined for the \\\"Save As...\\\" entry\"}\n$m add separator\n$m add command -label \"Print Setup...\" -command {error \"this is just a demo: no action has been defined for the \\\"Print Setup...\\\" entry\"}\n$m add command -label \"Print...\" -command {error \"this is just a demo: no action has been defined for the \\\"Print...\\\" entry\"}\n$m add separator\n$m add command -label \"Dismiss Menus Demo\" -command \"destroy $w\"\n\nset m $w.menu.basic\n$w.menu add cascade -label \"Basic\" -menu $m -underline 0\nmenu $m -tearoff 0\n$m add command -label \"Long entry that does nothing\"\nif {[tk windowingsystem] eq \"aqua\"} {\n    set modifier Command\n} elseif {[tk windowingsystem] eq \"win32\"} {\n    set modifier Control\n} else {\n    set modifier Meta\n}\nforeach i {A B C D E F} {\n    $m add command -label \"Print letter \\\"$i\\\"\" -underline 14 \\\n\t    -accelerator $modifier+$i -command \"puts $i\"\n    bind $w <$modifier-[string tolower $i]> \"puts $i\"\n}\n\nset m $w.menu.cascade\n$w.menu add cascade -label \"Cascades\" -menu $m -underline 0\nmenu $m -tearoff 0\n$m add command -label \"Print hello\" \\\n\t-command {puts stdout \"Hello\"} -accelerator $modifier+H -underline 6\nbind $w <$modifier-h> {puts stdout \"Hello\"}\n$m add command -label \"Print goodbye\" -command {\\\n    puts stdout \"Goodbye\"} -accelerator $modifier+G -underline 6\nbind $w <$modifier-g> {puts stdout \"Goodbye\"}\n$m add cascade -label \"Check buttons\" \\\n\t-menu $w.menu.cascade.check -underline 0\n$m add cascade -label \"Radio buttons\" \\\n\t-menu $w.menu.cascade.radio -underline 0\n\nset m $w.menu.cascade.check\nmenu $m -tearoff 0\n$m add check -label \"Oil checked\" -variable oil\n$m add check -label \"Transmission checked\" -variable trans\n$m add check -label \"Brakes checked\" -variable brakes\n$m add check -label \"Lights checked\" -variable lights\n$m add separator\n$m add command -label \"Show current values\" \\\n    -command \"showVars $w.menu.cascade.dialog oil trans brakes lights\"\n$m invoke 1\n$m invoke 3\n\nset m $w.menu.cascade.radio\nmenu $m -tearoff 0\n$m add radio -label \"10 point\" -variable pointSize -value 10\n$m add radio -label \"14 point\" -variable pointSize -value 14\n$m add radio -label \"18 point\" -variable pointSize -value 18\n$m add radio -label \"24 point\" -variable pointSize -value 24\n$m add radio -label \"32 point\" -variable pointSize -value 32\n$m add sep\n$m add radio -label \"Roman\" -variable style -value roman\n$m add radio -label \"Bold\" -variable style -value bold\n$m add radio -label \"Italic\" -variable style -value italic\n$m add sep\n$m add command -label \"Show current values\" \\\n\t-command \"showVars $w.menu.cascade.dialog pointSize style\"\n$m invoke 1\n$m invoke 7\n\nset m $w.menu.icon\n$w.menu add cascade -label \"Icons\" -menu $m -underline 0\nmenu $m -tearoff 0\n# Main widget program sets variable tk_demoDirectory\nimage create photo lilearth -file [file join $tk_demoDirectory \\\nimages earthmenu.png]\n$m add command -image lilearth \\\n    -hidemargin 1 -command [list \\\n\ttk_dialog $w.pattern {Bitmap Menu Entry} \\\n\t\t\"The menu entry you invoked displays a photoimage rather than\\\n\t\ta text string.  Other than this, it is just like any other\\\n\t\tmenu entry.\" {} 0 OK ]\nforeach i {info questhead error} {\n    $m add command -bitmap $i -hidemargin 1 -command [list \\\n\t    puts \"You invoked the $i bitmap\" ]\n}\n$m entryconfigure 2 -columnbreak 1\n\nset m $w.menu.more\n$w.menu add cascade -label \"More\" -menu $m -underline 0\nmenu $m -tearoff 0\nforeach i {{An entry} {Another entry} {Does nothing} {Does almost nothing} {Does almost nothing also} {Make life meaningful}} {\n    $m add command -label $i -command [list puts \"You invoked \\\"$i\\\"\"]\n}\nset emojiLabel [encoding convertfrom utf-8 \"\\xF0\\x9F\\x98\\x8D Make friends\"]\n$m add command -label $emojiLabel -command [list puts \"Menu labels can include non-BMP characters.\"]\n$m entryconfigure \"Does almost nothing\" -bitmap questhead -compound left \\\n\t-command [list \\\n\ttk_dialog $w.compound {Compound Menu Entry} \\\n\t\t\"The menu entry you invoked displays both a bitmap and a\\\n\t\ttext string.  Other than this, it is just like any other\\\n\t\tmenu entry.\" {} 0 OK ]\n\n$m entryconfigure \"Does almost nothing also\" -image lilearth -compound left \\\n\t-command [list \\\n\ttk_dialog $w.compound {Compound Menu Entry} \\\n\t\t\"The menu entry you invoked displays both a image and a\\\n\t\ttext string.  Other than this, it is just like any other\\\n\t\tmenu entry.\" {} 0 OK ]\n\nset m $w.menu.colors\n$w.menu add cascade -label \"Colors\" -menu $m -underline 1\nmenu $m -tearoff 1\nif {[tk windowingsystem] eq \"aqua\"} {\n    # Aqua ignores the -background and -foreground options, but a compound\n    # button can be used for selecting colors.\n    foreach i {red orange yellow green blue} {\n\timage create photo image_$i -height 16 -width 16\n\timage_$i put black -to 0 0 16 1\n\timage_$i put black -to 0 1 1 16\n\timage_$i put black -to 0 15 16 16\n\timage_$i put black -to 15 1 16 16\n\timage_$i put $i -to 1 1 15 15\n\t$m add command -label $i -image image_$i -compound left -command [list \\\n\tputs \"You invoked \\\"$i\\\"\" ]\n    }\n} else {\n    foreach i {red orange yellow green blue} {\n\t$m add command -label $i -background $i -command [list \\\n\tputs \"You invoked \\\"$i\\\"\" ]\n    }\n}\n\n$w configure -menu $w.menu\n\nbind Menu <<MenuSelect>> {\n    global $menustatus\n    if {[catch {%W entrycget active -label} label]} {\n\tset label \"    \"\n    }\n    set menustatus $label\n    update idletasks\n}\n"
  },
  {
    "path": "library/demos/menubu.tcl",
    "content": "# menubu.tcl --\n#\n# This demonstration script creates a window with a bunch of menus\n# and cascaded menus using menubuttons.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .menubu\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Menu Button Demonstration\"\nwm iconname $w \"menubutton\"\npositionWindow $w\n\nframe $w.body\npack $w.body -expand 1 -fill both\n\nmenubutton $w.body.below -text \"Below\" -underline 0 -direction below -menu $w.body.below.m -relief raised\nmenu $w.body.below.m -tearoff 0\n$w.body.below.m add command -label \"Below menu: first item\" -command \"puts \\\"You have selected the first item from the Below menu.\\\"\"\n$w.body.below.m add command -label \"Below menu: second item\" -command \"puts \\\"You have selected the second item from the Below menu.\\\"\"\ngrid $w.body.below -row 0 -column 1 -sticky n\nmenubutton $w.body.right -text \"Right\" -underline 0 -direction right -menu $w.body.right.m -relief raised\nmenu $w.body.right.m -tearoff 0\n$w.body.right.m add command -label \"Right menu: first item\" -command \"puts \\\"You have selected the first item from the Right menu.\\\"\"\n$w.body.right.m add command -label \"Right menu: second item\" -command \"puts \\\"You have selected the second item from the Right menu.\\\"\"\nframe $w.body.center\nmenubutton $w.body.left -text \"Left\" -underline 0 -direction left -menu $w.body.left.m -relief raised\nmenu $w.body.left.m -tearoff 0\n$w.body.left.m add command -label \"Left menu: first item\" -command \"puts \\\"You have selected the first item from the Left menu.\\\"\"\n$w.body.left.m add command -label \"Left menu: second item\" -command \"puts \\\"You have selected the second item from the Left menu.\\\"\"\ngrid $w.body.right -row 1 -column 0 -sticky w\ngrid $w.body.center -row 1 -column 1 -sticky news\ngrid $w.body.left -row 1 -column 2 -sticky e\nmenubutton $w.body.above -text \"Above\" -underline 0 -direction above -menu $w.body.above.m -relief raised\nmenu $w.body.above.m -tearoff 0\n$w.body.above.m add command -label \"Above menu: first item\" -command \"puts \\\"You have selected the first item from the Above menu.\\\"\"\n$w.body.above.m add command -label \"Above menu: second item\" -command \"puts \\\"You have selected the second item from the Above menu.\\\"\"\ngrid $w.body.above -row 2 -column 1 -sticky s\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nset body $w.body.center\nlabel $body.label -wraplength 225p -font \"Helvetica 14\" -justify left -text \"This is a demonstration of menubuttons. The \\\"Below\\\" menubutton pops its menu below the button; the \\\"Right\\\" button pops to the right, etc. There are two option menus directly below this text; one is just a standard menu and the other is a 16-color palette.\"\npack $body.label -side top -padx 18p -pady 18p\nframe $body.buttons\npack $body.buttons -padx 18p -pady 18p\ntk_optionMenu $body.buttons.options menubuttonoptions one two three\npack $body.buttons.options -side left -padx 18p -pady 18p\nset m [tk_optionMenu $body.buttons.colors paletteColor Black red4 DarkGreen NavyBlue gray75 Red Green Blue gray50 Yellow Cyan Magenta White Brown DarkSeaGreen DarkViolet]\nif {[tk windowingsystem] eq \"aqua\"} {\n    set topBorderColor Black\n    set bottomBorderColor Black\n} else {\n    set topBorderColor gray50\n    set bottomBorderColor gray75\n}\nset dim  [expr {round(16 * $tk::scalingPct / 100.0)}]\nset dim1 [expr {$dim - 1}]\nset dim2 [expr {$dim - 2}]\nfor {set i 0} {$i <= [$m index last]} {incr i} {\n    set name [$m entrycget $i -label]\n    image create photo image_$name -height $dim -width $dim\n    image_$name put $topBorderColor -to 0 0 $dim 1\n    image_$name put $topBorderColor -to 0 1 1 $dim\n    image_$name put $bottomBorderColor -to 0 $dim1 $dim $dim\n    image_$name put $bottomBorderColor -to $dim1 1 $dim $dim\n    image_$name put $name -to 1 1 $dim1 $dim1\n\n    image create photo image_${name}_s -height $dim -width $dim\n    image_${name}_s put Black -to 0 0 $dim 2\n    image_${name}_s put Black -to 0 2 2 $dim\n    image_${name}_s put Black -to 2 $dim2 $dim $dim\n    image_${name}_s put Black -to $dim2 2 $dim $dim2\n    image_${name}_s put $name -to 2 2 $dim2 $dim2\n\n    $m entryconfigure $i -image image_$name -selectimage image_${name}_s -hidemargin 1\n}\n$m configure -tearoff 1\nforeach i {Black gray75 gray50 White} {\n\t$m entryconfigure $i -columnbreak 1\n}\n\npack $body.buttons.colors -side left -padx 18p -pady 18p\n"
  },
  {
    "path": "library/demos/msgbox.tcl",
    "content": "# msgbox.tcl --\n#\n# This demonstration script creates message boxes of various type\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .msgbox\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Message Box Demonstration\"\nwm iconname $w \"messagebox\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"Choose the icon and type option of the message box. Then press the \\\"Message Box\\\" button to see the message box.\"\npack $w.msg -side top\n\npack [addSeeDismiss $w.buttons $w {} {\n    ttk::button $w.buttons.vars -text \"Message Box\" -command \"showMessageBox $w\"\n}] -side bottom -fill x\n#pack $w.buttons.dismiss $w.buttons.code $w.buttons.vars -side left -expand 1\n\nframe $w.left\nframe $w.right\npack $w.left $w.right -side left -expand yes -fill y  -pady .5c -padx .5c\n\nlabel $w.left.label -text \"Icon\"\nframe $w.left.sep -relief ridge -bd 1 -height 2\npack $w.left.label -side top\npack $w.left.sep -side top -fill x -expand no\n\nset msgboxIcon info\nforeach i {error info question warning} {\n    radiobutton $w.left.b$i -text $i -variable msgboxIcon \\\n\t-relief flat -value $i -width 16 -anchor w\n    pack $w.left.b$i  -side top -pady 1.5p -anchor w -fill x\n}\n\nlabel $w.right.label -text \"Type\"\nframe $w.right.sep -relief ridge -bd 1 -height 2\npack $w.right.label -side top\npack $w.right.sep -side top -fill x -expand no\n\nset msgboxType ok\nforeach t {abortretryignore ok okcancel retrycancel yesno yesnocancel} {\n    radiobutton $w.right.$t -text $t -variable msgboxType \\\n\t-relief flat -value $t -width 16 -anchor w\n    pack $w.right.$t -side top -pady 1.5p -anchor w -fill x\n}\n\nproc showMessageBox {w} {\n    global msgboxIcon msgboxType\n    set button [tk_messageBox -icon $msgboxIcon -type $msgboxType \\\n\t-title Message -parent $w\\\n\t-message \"This is a \\\"$msgboxType\\\" type messagebox with the \\\"$msgboxIcon\\\" icon\"]\n\n    tk_messageBox -icon info -message \"You have selected \\\"$button\\\"\" -type ok\\\n\t-parent $w\n}\n"
  },
  {
    "path": "library/demos/nl.msg",
    "content": "::msgcat::mcset nl \"Widget Demonstration\" \"Demonstratie van widgets\"\n::msgcat::mcset nl \"tkWidgetDemo\"\n::msgcat::mcset nl \"&File\"     \"&Bestand\"\n::msgcat::mcset nl \"About...\"  \"Info...\"\n::msgcat::mcset nl \"&About...\" \"&Info...\"\n::msgcat::mcset nl \"<F1>\"      \"<F1>\"\n::msgcat::mcset nl \"&Quit\"     \"&Einde\"\n::msgcat::mcset nl \"Meta+Q\"    \"Meta+E\"\t\t;# Displayed hotkey\n::msgcat::mcset nl \"Meta-q\"    \"Meta-e\"\t\t;# Actual binding sequence\n::msgcat::mcset nl \"Ctrl+Q\"    \"Ctrl+E\"\t\t;# Displayed hotkey\n::msgcat::mcset nl \"Control-q\" \"Control-e\"\t;# Actual binding sequence\n::msgcat::mcset nl \"See Variables\"    \"Bekijk Variabelen\"\n::msgcat::mcset nl \"Variable values\"  \"Waarden variabelen\"\n::msgcat::mcset nl \"Variable values:\"  \"Waarden variabelen\"\n::msgcat::mcset nl \"OK\"\n::msgcat::mcset nl \"Run the \\\"%s\\\" sample program\" \"Start voorbeeld \\\"%s\\\"\"\n::msgcat::mcset nl \"Dismiss\"   \"Sluiten\"\n::msgcat::mcset nl \"Rerun Demo\" \"Herstart Demo\"\t;# This is also button text!\n::msgcat::mcset nl \"Print Code\" \"Code Afdrukken\"\n::msgcat::mcset nl \"Demo code: %s\" \"Code van Demo %s\"\n::msgcat::mcset nl \"About Widget Demo\" \"Over deze demonstratie\"\n::msgcat::mcset nl \"Tk widget demonstration\" \"Demonstratie van Tk widgets\"\n::msgcat::mcset nl \"Copyright © %s\"\n\n::msgcat::mcset nl \"Tk Widget Demonstrations\" \"Demonstratie van Tk widgets\"\n::msgcat::mcset nl \"This application provides a front end for several short scripts\" \\\n    \"Dit programma is een schil rond enkele korte scripts waarmee\"\n::msgcat::mcset nl \"that demonstrate what you can do with Tk widgets.  Each of the\" \\\n    \"gedemonstreerd wordt wat je kunt doen met Tk widgets.  Elk van de\"\n::msgcat::mcset nl \"numbered lines below describes a demonstration;  you can click on\" \\\n    \"genummerde regels hieronder omschrijft een demonstratie;  je kunt de\"\n::msgcat::mcset nl \"it to invoke the demonstration.  Once the demonstration window\" \\\n    \"demonstratie starten door op de regel te klikken.\"\n::msgcat::mcset nl \"appears, you can click the\" \\\n    \"Zodra het nieuwe venster verschijnt, kun je op de knop\"\n::msgcat::mcset nl \"See Code\"  \"Bekijk Code\"\t;# This is also button text!\n::msgcat::mcset nl \"button to see the Tcl/Tk code that created the demonstration.  If\" \\\n    \"drukken om de achterliggende Tcl/Tk code te zien.  Als je dat wilt,\"\n::msgcat::mcset nl \"you wish, you can edit the code and click the\" \\\n    \"kun je de code wijzigen en op de knop\"\n::msgcat::mcset nl \"button in the code window to reinvoke the demonstration with the\" \\\n    \"drukken in het codevenster om de demonstratie uit te voeren met de\"\n::msgcat::mcset nl \"modified code.\" \\\n    \"nieuwe code.\"\n\n::msgcat::mcset nl \"Labels, buttons, checkbuttons, and radiobuttons\" \\\n    \"Labels, knoppen, vinkjes/aankruishokjes en radioknoppen\"\n::msgcat::mcset nl \"Labels (text and bitmaps)\" \"Labels (tekst en plaatjes)\"\n::msgcat::mcset nl \"Labels and UNICODE text\"   \"Labels en tekst in UNICODE\"\n::msgcat::mcset nl \"Buttons\" \"Buttons (drukknoppen)\"\n::msgcat::mcset nl \"Check-buttons (select any of a group)\" \\\n    \"Check-buttons (een of meer uit een groep)\"\n::msgcat::mcset nl \"Radio-buttons (select one of a group)\" \\\n    \"Radio-buttons (een van een groep)\"\n::msgcat::mcset nl \"A 15-puzzle game made out of buttons\" \\\n    \"Een schuifpuzzel van buttons\"\n::msgcat::mcset nl \"Iconic buttons that use bitmaps\" \\\n    \"Buttons met pictogrammen\"\n::msgcat::mcset nl \"Two labels displaying images\" \\\n    \"Twee labels met plaatjes in plaats van tekst\"\n::msgcat::mcset nl \"A simple user interface for viewing images\" \\\n    \"Een eenvoudige user-interface voor het bekijken van plaatjes\"\n::msgcat::mcset nl \"Labelled frames\" \\\n    \"Kaders met bijschrift\"\n\n::msgcat::mcset nl \"Listboxes\" \"Keuzelijsten\"\n::msgcat::mcset nl \"The 50 states\" \"De 50 staten van de VS\"\n::msgcat::mcset nl \"Colors: change the color scheme for the application\" \\\n    \"Kleuren: verander het kleurenschema voor het programma\"\n::msgcat::mcset nl \"A collection of famous and infamous sayings\" \\\n    \"Beroemde en beruchte citaten en gezegden\"\n\n::msgcat::mcset nl \"Entries and Spin-boxes\"     \"Invulvelden en Spinboxen\"\n::msgcat::mcset nl \"Entries without scrollbars\" \"Invulvelden zonder schuifbalk\"\n::msgcat::mcset nl \"Entries with scrollbars\"    \"Invulvelden met schuifbalk\"\n::msgcat::mcset nl \"Validated entries and password fields\" \\\n    \"Invulvelden met controle of wachtwoorden\"\n::msgcat::mcset nl \"Spin-boxes\" \"Spinboxen\"\n::msgcat::mcset nl \"Simple Rolodex-like form\" \"Simpel kaartsysteem\"\n\n::msgcat::mcset nl \"Text\" \"Tekst\"\n::msgcat::mcset nl \"Basic editable text\" \"Voorbeeld met te wijzigen tekst\"\n::msgcat::mcset nl \"Text display styles\" \"Tekst met verschillende stijlen\"\n::msgcat::mcset nl \"Hypertext (tag bindings)\" \\\n    \"Hypertext (verwijzingen via \\\"tags\\\")\"\n::msgcat::mcset nl \"A text widget with embedded windows\" \\\n    \"Tekstwidget met windows erin\"\n::msgcat::mcset nl \"A search tool built with a text widget\" \\\n    \"Zoeken in tekst met behulp van een tekstwidget\"\n\n::msgcat::mcset nl \"Canvases\" \"Canvaswidgets\"\n::msgcat::mcset nl \"The canvas item types\"     \"Objecten in een canvas\"\n::msgcat::mcset nl \"A simple 2-D plot\"         \"Eenvoudige 2D-grafiek\"\n::msgcat::mcset nl \"Text items in canvases\"    \"Tekstobjecten in een canvas\"\n::msgcat::mcset nl \"An editor for arrowheads on canvas lines\" \\\n    \"Editor voor de vorm van de pijl (begin/eind van een lijn)\"\n::msgcat::mcset nl \"A ruler with adjustable tab stops\" \\\n    \"Een meetlat met aanpasbare ruiters\"\n::msgcat::mcset nl \"A building floor plan\"     \"Plattegrond van een gebouw\"\n::msgcat::mcset nl \"A simple scrollable canvas\" \"Een schuifbaar canvas\"\n\n::msgcat::mcset nl \"Scales\" \"Schaalverdelingen\"\n::msgcat::mcset nl \"Horizontal scale\"          \"Horizontale schaal\"\n::msgcat::mcset nl \"Vertical scale\"          \"Verticale schaal\"\n\n::msgcat::mcset nl \"Paned Windows\" \"Vensters opgedeeld in stukken\"\n::msgcat::mcset nl \"Horizontal paned window\"   \"Horizontaal gedeeld venster\"\n::msgcat::mcset nl \"Vertical paned window\"     \"Verticaal gedeeld venster\"\n::msgcat::mcset nl \"Menus\" \"Menu's\"\n::msgcat::mcset nl \"Menus and cascades (sub-menus)\" \\\n    \"Menu's en cascades (submenu's)\"\n::msgcat::mcset nl \"Menu-buttons\" \"Menu-buttons\"\n::msgcat::mcset nl \"Common Dialogs\" \"Veel voorkomende dialoogvensters\"\n::msgcat::mcset nl \"Message boxes\"  \"Mededeling (message box)\"\n::msgcat::mcset nl \"File selection dialog\"     \"Selectie van bestanden\"\n::msgcat::mcset nl \"Color picker\"              \"Kleurenpalet\"\n::msgcat::mcset nl \"Font selection dialog\"     \"Selectie van fonts\"\n::msgcat::mcset nl \"System tray icon and notification\" \"Systeemvakpictogram en melding\"\n::msgcat::mcset nl \"Printing from canvas and text widgets\" \"Afdrukken van canvas en tekst widgets\"\n::msgcat::mcset nl \"Animation\" \"Animaties\"\n::msgcat::mcset nl \"Animated labels\" \"Geanimeerde labels\"\n::msgcat::mcset nl \"Animated wave\" \"Geanimeerde golf\"\n::msgcat::mcset nl \"Pendulum simulation\" \"Pendulum simulatie\"\n::msgcat::mcset nl \"A celebration of Rube Goldberg\" \"Een viering van Rube Goldberg\"\n::msgcat::mcset nl \"Miscellaneous\"             \"Diversen\"\n::msgcat::mcset nl \"The built-in bitmaps\"      \"Ingebouwde plaatjes\"\n::msgcat::mcset nl \"A dialog box with a local grab\" \\\n    \"Een dialoogvenster met een locale \\\"grab\\\"\"\n::msgcat::mcset nl \"A dialog box with a global grab\" \\\n    \"Een dialoogvenster met een globale \\\"grab\\\"\"\n::msgcat::mcset nl \"Window icons and badges\" \"Vensterpictogrammen en badges\"\n\n"
  },
  {
    "path": "library/demos/paned1.tcl",
    "content": "# paned1.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# a paned window that separates two windows horizontally.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .paned1\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Horizontal Paned Window Demonstration\"\nwm iconname $w \"paned1\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"The sash between the two coloured windows below can be used to divide the area between them.  Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\npanedwindow $w.pane\npack $w.pane -side top -expand yes -fill both -pady 1.5p -padx 2m\n\nlabel $w.pane.left  -text \"This is the\\nleft side\"  -fg black -bg yellow\nlabel $w.pane.right -text \"This is the\\nright side\" -fg black -bg cyan\n\n$w.pane add $w.pane.left $w.pane.right -stretch always\n"
  },
  {
    "path": "library/demos/paned2.tcl",
    "content": "# paned2.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# a paned window that separates two windows vertically.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .paned2\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Vertical Paned Window Demonstration\"\nwm iconname $w \"paned2\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"The sash between the two scrolled windows below can be used to divide the area between them.  Use the left mouse button to resize without redrawing by just moving the sash, and use the middle mouse button to resize opaquely (always redrawing the windows in each position.)\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Create the pane itself\npanedwindow $w.pane -orient vertical\npack $w.pane -side top -expand yes -fill both -pady 1.5p -padx 2m\n\n# The top window is a listbox with scrollbar\nset paneList {\n    {List of Tk Widgets}\n    button\n    canvas\n    checkbutton\n    entry\n    frame\n    label\n    labelframe\n    listbox\n    menu\n    menubutton\n    message\n    panedwindow\n    radiobutton\n    scale\n    scrollbar\n    spinbox\n    text\n    toplevel\n}\nset f [frame $w.pane.top]\nlistbox $f.list -listvariable paneList -yscrollcommand \"$f.scr set\"\n# Invert the first item to highlight it\n$f.list itemconfigure 0 \\\n\t-background [$f.list cget -fg] -foreground [$f.list cget -bg]\nttk::scrollbar $f.scr -orient vertical -command \"$f.list yview\"\npack $f.scr -side right -fill y\npack $f.list -fill both -expand 1\n\n# The bottom window is a text widget with scrollbar\nset f [frame $w.pane.bottom]\ntext $f.text -xscrollcommand \"$f.xscr set\" -yscrollcommand \"$f.yscr set\" \\\n\t-width 30 -height 8 -wrap none\nttk::scrollbar $f.xscr -orient horizontal -command \"$f.text xview\"\nttk::scrollbar $f.yscr -orient vertical -command \"$f.text yview\"\ngrid $f.text $f.yscr -sticky nsew\ngrid $f.xscr         -sticky nsew\ngrid columnconfigure $f 0 -weight 1\ngrid rowconfigure    $f 0 -weight 1\n$f.text insert 1.0 \"This is just a normal text widget\"\n\n# Now add our contents to the paned window\n$w.pane add $w.pane.top $w.pane.bottom -stretch always\n"
  },
  {
    "path": "library/demos/pendulum.tcl",
    "content": "# pendulum.tcl --\n#\n# This demonstration illustrates how Tcl/Tk can be used to construct\n# simulations of physical systems.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .pendulum\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Pendulum Animation Demonstration\"\nwm iconname $w \"pendulum\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This demonstration shows how Tcl/Tk can be used to carry out animations that are linked to simulations of physical systems. In the left canvas is a graphical representation of the physical system itself, a simple pendulum, and in the right canvas is a graph of the phase space of the system, which is a plot of the angle (relative to the vertical) against the angular velocity. The pendulum bob may be repositioned by clicking and dragging anywhere on the left canvas.\"\npack $w.msg\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Create some structural widgets\npack [panedwindow $w.p] -fill both -expand 1\n$w.p add [labelframe $w.p.l1 -text \"Pendulum Simulation\"] -stretch always\n$w.p add [labelframe $w.p.l2 -text \"Phase Space\"] -stretch always\n\n# Create the canvas containing the graphical representation of the\n# simulated system.\ncanvas $w.c -width 240p -height 150p -background white -bd 1.5p -relief sunken\n$w.c create text 3p 3p -anchor nw -text \"Click to Adjust Bob Start Position\"\n# Coordinates of these items don't matter; they will be set properly below\n$w.c create line 0 25 320 25   -tags plate -fill grey50 -width 1.5p\n$w.c create oval 155 20 165 30 -tags pivot -fill grey50 -outline {}\n$w.c create line 1 1 1 1       -tags rod   -fill black  -width 2.25p\n$w.c create oval 1 1 2 2       -tags bob   -fill yellow -outline black\npack $w.c -in $w.p.l1 -fill both -expand true\n\n# Create the canvas containing the phase space graph; this consists of\n# a line that gets gradually paler as it ages, which is an extremely\n# effective visual trick.\ncanvas $w.k -width 240p -height 150p -background white -bd 1.5p -relief sunken\n$w.k create line 120p 150p 120p 0 -fill grey75 -arrow last -tags y_axis\n$w.k create line 0 75p 240p 75p -fill grey75 -arrow last -tags x_axis\nfor {set i 90} {$i>=0} {incr i -10} {\n    # Coordinates of these items don't matter; they will be set properly below\n    $w.k create line 0 0 1 1 -smooth true -tags graph$i -fill grey$i\n}\n\n$w.k create text 0 0 -anchor ne -text \"θ\"  -tags label_theta\n$w.k create text 0 0 -anchor ne -text \"δθ\" -tags label_dtheta\npack $w.k -in $w.p.l2 -fill both -expand true\n\n# Initialize some variables\nset points {}\nset Theta  45.0\nset dTheta  0.0\nset pi      3.1415926535897933\nset tkScl  [tk scaling]\nset length [expr {round(111*$tkScl)}]\t\t\t;# 111p -> pixels\nset xHome  [expr {round(120*$tkScl)}]\t\t\t;# 120p -> pixels\nset yHome  [expr {round( 18*$tkScl)}]\t\t\t;#  18p -> pixels\nset rBob   [expr {round( 12*$tkScl)}]\t\t\t;#  12p -> pixels\nset rPivot [expr {round(  3*$tkScl)}]\t\t\t;#   3p -> pixels\n\n# This procedure makes the pendulum appear at the correct place on the\n# canvas. If the additional arguments \"at $x $y\" are passed (the 'at'\n# is really just syntactic sugar) instead of computing the position of\n# the pendulum from the length of the pendulum rod and its angle, the\n# length and angle are computed in reverse from the given location\n# (which is taken to be the centre of the pendulum bob.)\nproc showPendulum {canvas {at {}} {x {}} {y {}}} {\n    global Theta dTheta pi length xHome yHome rBob\n\n    if {$at eq \"at\" && ($x!=$xHome || $y!=$yHome)} {\n\tset dTheta 0.0\n\tset x2 [expr {$x - $xHome}]\n\tset y2 [expr {$y - $yHome}]\n\tset length [expr {hypot($x2, $y2)}]\n\tset Theta  [expr {atan2($x2, $y2) * 180/$pi}]\n    } else {\n\tset angle [expr {$Theta * $pi/180}]\n\tset x [expr {$xHome + $length*sin($angle)}]\n\tset y [expr {$yHome + $length*cos($angle)}]\n    }\n    $canvas coords rod $xHome $yHome $x $y\n    $canvas coords bob [expr {$x - $rBob}] [expr {$y - $rBob}] \\\n\t\t       [expr {$x + $rBob}] [expr {$y + $rBob}]\n}\nshowPendulum $w.c\n\n# Update the phase-space graph according to the current angle and the\n# rate at which the angle is changing (the first derivative with\n# respect to time.)\nproc showPhase {canvas} {\n    global Theta dTheta points psw psh\n    set sclFactor [expr {$tk::scalingPct / 100.0}]\n\n    lappend points [expr {$Theta + $psw}] [expr {-20*$sclFactor*$dTheta + $psh}]\n    if {[llength $points] > 100} {\n\tset points [lrange $points end-99 end]\n    }\n    for {set i 0} {$i<100} {incr i 10} {\n\tset list [lrange $points end-[expr {$i-1}] end-[expr {$i-12}]]\n\tif {[llength $list] >= 4} {\n\t    $canvas coords graph$i $list\n\t    $canvas scale graph$i $psw $psh $sclFactor $sclFactor\n\t}\n    }\n}\n\n# Set up some bindings on the canvases.  Note that when the user\n# clicks we stop the animation until they release the mouse\n# button. Also note that both canvases are sensitive to <Configure>\n# events, which allows them to find out when they have been resized by\n# the user.\nbind $w.c <Destroy> {\n    after cancel $animationCallbacks(pendulum)\n    unset animationCallbacks(pendulum)\n}\nbind $w.c <Button-1> {\n    after cancel $animationCallbacks(pendulum)\n    showPendulum %W at %x %y\n}\nbind $w.c <B1-Motion> {\n    showPendulum %W at %x %y\n}\nbind $w.c <ButtonRelease-1> {\n    showPendulum %W at %x %y\n    set animationCallbacks(pendulum) [after 15 repeat [winfo toplevel %W]]\n}\nbind $w.c <Configure> {\n    %W coords plate 0 18p %w 18p\n    set xHome [expr {%w/2}]\n    %W coords pivot [expr {$xHome - $rPivot}] 15p [expr {$xHome + $rPivot}] 21p\n}\nbind $w.k <Configure> {\n    set psh [expr {%h/2}]\n    set psw [expr {%w/2}]\n    %W coords x_axis\t   1.5p $psh [expr {%w - round(1.5*$tkScl)}] $psh\n    %W coords y_axis\t   $psw [expr {%h - round(1.5*$tkScl)}] $psw 1.5p\n    %W coords label_dtheta [expr {$psw - round(3*$tkScl)}] 4.5p\n    %W coords label_theta  [expr {%w - round(4.5*$tkScl)}] \\\n\t\t\t   [expr {$psh + round(3*$tkScl)}]\n}\n\n# This procedure is the \"business\" part of the simulation that does\n# simple numerical integration of the formula for a simple rotational\n# pendulum.\nproc recomputeAngle {} {\n    global Theta dTheta pi length\n    set scaling [expr {3000.0/$length/$length}]\n\n    # To estimate the integration accurately, we really need to\n    # compute the end-point of our time-step.  But to do *that*, we\n    # need to estimate the integration accurately!  So we try this\n    # technique, which is inaccurate, but better than doing it in a\n    # single step.  What we really want is bound up in the\n    # differential equation:\n    #       ..             - sin theta\n    #      theta + theta = -----------\n    #                         length\n    # But my math skills are not good enough to solve this!\n\n    # first estimate\n    set firstDDTheta [expr {-sin($Theta * $pi/180)*$scaling}]\n    set midDTheta [expr {$dTheta + $firstDDTheta}]\n    set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}]\n    # second estimate\n    set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}]\n    set midDTheta [expr {$dTheta + ($firstDDTheta + $midDDTheta)/2}]\n    set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}]\n    # Now we do a double-estimate approach for getting the final value\n    # first estimate\n    set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}]\n    set lastDTheta [expr {$midDTheta + $midDDTheta}]\n    set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}]\n    # second estimate\n    set lastDDTheta [expr {-sin($lastTheta * $pi/180)*$scaling}]\n    set lastDTheta [expr {$midDTheta + ($midDDTheta + $lastDDTheta)/2}]\n    set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}]\n    # Now put the values back in our globals\n    set dTheta $lastDTheta\n    set Theta $lastTheta\n}\n\n# This method ties together the simulation engine and the graphical\n# display code that visualizes it.\nproc repeat w {\n    global animationCallbacks\n\n    # Simulate\n    recomputeAngle\n\n    # Update the display\n    showPendulum $w.c\n    showPhase $w.k\n\n    # Reschedule ourselves\n    set animationCallbacks(pendulum) [after 15 [list repeat $w]]\n}\n# Start the simulation after a short pause\nset animationCallbacks(pendulum) [after 500 [list repeat $w]]\n"
  },
  {
    "path": "library/demos/plot.tcl",
    "content": "# plot.tcl --\n#\n# This demonstration script creates a canvas widget showing a 2-D\n# plot with data points that can be dragged with the mouse.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .plot\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Plot Demonstration\"\nwm iconname $w \"Plot\"\npositionWindow $w\nset c $w.c\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"This window displays a canvas widget containing a simple 2-dimensional plot.  You can doctor the data by dragging any of the points with mouse button 1.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\ncanvas $c -relief raised -width 337.5p -height 225p\npack $w.c -side top -fill x\n\nset plotFont {Helvetica 16}\n\n$c create line 75p 187.5p 300p 187.5p -width 1.5p\n$c create line 75p 187.5p 75p 37.5p -width 1.5p\n$c create text 168.75p 15p -text \"A Simple Plot\" -font $plotFont -fill brown\n\nfor {set i 0} {$i <= 10} {incr i} {\n    set x [expr {75 + ($i*22.5)}]\t\t\t;# in points\n    $c create line ${x}p 187.5p ${x}p 183.75p -width 1.5p\n    $c create text ${x}p 190.5p -text [expr {10*$i}] -anchor n -font $plotFont\n}\nfor {set i 0} {$i <= 5} {incr i} {\n    set y [expr {187.5 - ($i*30)}]\t\t\t;# in points\n    $c create line 75p ${y}p 78.75p ${y}p -width 1.5p\n    $c create text 72p ${y}p -text [expr {$i*50}].0 -anchor e -font $plotFont\n}\n\nforeach point {\n    {9 42} {15 70.5} {24.75 73.5} {24 90} {45.75 135} {56.25 120} {73.5 167.25}\n} {\n    set x [expr {75 + (2.25*[lindex $point 0])}]\t;# in points\n    set y [expr {187.5 - (3*[lindex $point 1])/5}]\t;# in points\n    set item [$c create oval [expr {$x-4.5}]p [expr {$y-4.5}]p \\\n\t    [expr {$x+4.5}]p [expr {$y+4.5}]p -width 0.75p -outline black \\\n\t    -fill SkyBlue2]\n    $c addtag point withtag $item\n}\n\n$c bind point <Enter> \"$c itemconfig current -fill red\"\n$c bind point <Leave> \"$c itemconfig current -fill SkyBlue2\"\n$c bind point <Button-1> \"plotDown $c %x %y\"\n$c bind point <ButtonRelease-1> \"$c dtag selected\"\nbind $c <B1-Motion> \"plotMove $c %x %y\"\n\nset plot(lastX) 0\nset plot(lastY) 0\n\n# plotDown --\n# This procedure is invoked when the mouse is pressed over one of the\n# data points.  It sets up state to allow the point to be dragged.\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# x, y -\tThe coordinates of the mouse press.\n\nproc plotDown {w x y} {\n    global plot\n    $w dtag selected\n    $w addtag selected withtag current\n    $w raise current\n    set plot(lastX) $x\n    set plot(lastY) $y\n}\n\n# plotMove --\n# This procedure is invoked during mouse motion events.  It drags the\n# current item.\n#\n# Arguments:\n# w -\t\tThe canvas window.\n# x, y -\tThe coordinates of the mouse.\n\nproc plotMove {w x y} {\n    global plot\n    $w move selected [expr {$x-$plot(lastX)}] [expr {$y-$plot(lastY)}]\n    set plot(lastX) $x\n    set plot(lastY) $y\n}\n"
  },
  {
    "path": "library/demos/print.tcl",
    "content": "# print.tcl --\n#\n# This demonstration script showcases the tk print commands.\n#\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\nset w .print\ndestroy $w\ntoplevel $w\nwm title $w \"Printing Demonstration\"\npositionWindow $w\n\npack [label $w.l -text \"This demonstration showcases\nthe tk print command. Clicking the buttons below\nprints the data from the canvas and text widgets\nusing platform-native dialogs.\"] -side top\n\n## See Code / Dismiss buttons\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\nframe $w.m\n\nimage create photo logo -data {\nR0lGODlhMABLAPUAAP//////zP//mf//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM/8zMzMyZzMyZ\nmcyZZsyZAMxmZsxmM8xmAMwzM8wzAJnMzJmZzJmZmZlmmZlmZplmM5kzZpkzM5kzAGaZzGZmzGZm\nmWYzZmYzMzNmzDNmmTMzmTMzZgAzmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+BSAtZGwtACH5BAEKAAIALAAAAAAw\nAEsAAAb+QIFwSCwahY9HRMI8Op/JJVNSqVqv2OvjyRU8slbIJGwYg60S5ZR6jRi/4ITBOhkYIOd8\ndltEnAdmFQMJeoVXCEd/VnKGjRVOZ3NVgHlsjpBxVRCEYBIEAAARl4lgZmVgEQAKFx8Mo0ZnpqgA\nFyi2JqKGmGebWRIAILbCIo27cYFWASTCtievRXqSVwQfzLYeeYESxlnSVRIW1igjWHJmjBXbpKXe\nFQTizlh1eJNVHbYf0LGc39XW2PIoVZE0whasWPSqFBBHrkKEA3QG0DFTEMXBUsjCWesg4oMFAGwg\ntKsiwqA+jGiCiRPGAM6pLCVLGKHQ6EGJlc0IuDxzAgX+CCOW9DjAaUsEyAoT+GHpeSRoHgxEUWgA\nUEUpFhMWgTbKEPUBAU15TBZxekYD0RMEqCDLIpYIWTAcmGEd9rWQBxQyjeQqdK/ZTWEO3mK5l+9N\no75SrcHhm9WwnlzNoA5zdM+JHz0HCPQdUauZowoFnSw+c2CBvw6dUXT4LMKE6EIHUqMexgCiIREk\nnOwl7Q+FhNQoLuzOc6Kw3kIIVOLqjYKBYCwinmgo9CBEswfMAziK7mRDoQhcUZxwoBKFibq3n3jX\nI0GyCPLC0DrS8GR1oaEoRBRYVhT99/qG4DcCA/yNU4Ajbjhhnx4P2DJggR3YZog6RyyYxwM9PSgM\nBaP+sQdgIRL0JAKBwnTooRMAFWLdiPyJ8JwvTnyQoh5midCASh149ZkTIFAmHnzOZOBfIU6U4Mhd\n4zF34DNEoDAhARGY50BvJkioyxFOGkKAShGkFsJwejiR5Xf8aZAaBp89coQJjuDXAQOApekEm45A\nNaAtIbyYxREf0OlICCK841uaahZBQjyfjXCACYjuaASjhFagRKSFNtloHg+hYWIxRohnBQWCSSAh\nBVZ+hkgRnlbxwJIVgIqGlaU6wkeTxHxjm6gVLImrFbHWVEQ1taZjWxJX7KqqnqgUEUxDwtqajrOa\nRkqhEDcxWwECbEjxTYe9gojqOJQ6JO231ob72bSqAjh4RgfsjiDCCfDCK8K8I9TL7r33nvGtCO7C\nO1dUAONk3LcBFxzwwEMwZ/DC4iAsRIE+CWNCbzeV8FfEtoDwVwnlacxMkcKQYIE/F5TQ2QcedUZC\nagyc3NsFGrXVZMipWVBCzKv4Q0JvCviDsjAwf4ylxBeX0KcwGs81ccgqGS3MBxc3RjDDVAvdBRcf\neFy1MFd3bcQHJEQdlddkP5E1Cf9yXfbaV2d9RBAAOw==\n}\n\n# Create a copy of the image just created, magnified according to the\n# display's DPI scaling level.  Since the zooom factor must be an integer,\n# the copy will only be effectively magnified if $tk::scalingPct >= 200.\nimage create photo logo2\nlogo2 copy logo -zoom [expr {$tk::scalingPct / 100}]\n\nset c [canvas $w.m.c -bg white]\npack $c -fill both -expand yes -fill both -side left\n\n# For scaling-awareness specify the coordinates of the canvas items in points\n# rather than pixels.  Create the items with a left and top padding of 15 pt.\n$c create rectangle 15p 15p 165p 60p -fill blue -outline black\t;# 150p x 45p\n$c create oval 15p 75p 165p 120p -fill green\t\t\t;# 150p x 45p\nset imgId [$c create image 90p 135p -image logo2 -anchor n]\n\n# Compute the scaled y coordinate of the next canvas item's top edge in pixels\nlassign [$c bbox $imgId] x1 y1 x2 y2\t\t;# x1, y1, x2, y2 are in pixels\nincr y2 [expr {round(15 * [tk scaling])}]\t;# convert 15 pt to pixels\n\n$c create text 15p $y2 -anchor nw -font {Helvetica 12} \\\n\t-fill black \\\n\t-text \"A short demo of simple canvas elements.\"\n\nset txt {\nTcl, or Tool Command Language, is an open-source multi-purpose C library which includes a powerful dynamic scripting language. Together they provide ideal cross-platform development environment for any programming project. It has served for decades as an essential system component in organizations ranging from NASA to Cisco Systems, is a must-know language in the fields of EDA, and powers companies such as FlightAware and F5 Networks.\n\nTcl is fit for both the smallest and largest programming tasks, obviating the need to decide whether it is overkill for a given job or whether a system written in Tcl will scale up as needed. Wherever a shell script might be used Tcl is a better choice, and entire web ecosystems and mission-critical control and testing systems have also been written in Tcl. Tcl excels in all these roles due to the minimal syntax of the language, the unique programming paradigm exposed at the script level, and the careful engineering that has gone into the design of the Tcl internals.\n}\n\nset t [text $w.m.t -wrap word]\npack $t -side right -expand yes -fill both\n$t insert end $txt\n\nframe $w.f\n\npack [button $w.f.c -text \"Print Canvas\" -command [list tk print $w.m.c]] \\\n\t-side left -anchor w -padx 3p\npack [button $w.f.t -text \"Print Text\" -command [list tk print $w.m.t]] \\\n\t-side right -anchor e -padx 3p\n\npack $w.f -side bottom -fill x\npack $w.m -expand yes -fill both -side top\n"
  },
  {
    "path": "library/demos/puzzle.tcl",
    "content": "# puzzle.tcl --\n#\n# This demonstration script creates a 15-puzzle game using a collection\n# of buttons.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# puzzleSwitch --\n# This procedure is invoked when the user clicks on a particular button;\n# if the button is next to the empty space, it moves the button into the\n# empty space.\n\nproc puzzleSwitch {w num} {\n    global xpos ypos\n    if {(($ypos($num) >= ($ypos(space) - .01))\n\t    && ($ypos($num) <= ($ypos(space) + .01))\n\t    && ($xpos($num) >= ($xpos(space) - .26))\n\t    && ($xpos($num) <= ($xpos(space) + .26)))\n\t    || (($xpos($num) >= ($xpos(space) - .01))\n\t    && ($xpos($num) <= ($xpos(space) + .01))\n\t    && ($ypos($num) >= ($ypos(space) - .26))\n\t    && ($ypos($num) <= ($ypos(space) + .26)))} {\n\tset tmp $xpos(space)\n\tset xpos(space) $xpos($num)\n\tset xpos($num) $tmp\n\tset tmp $ypos(space)\n\tset ypos(space) $ypos($num)\n\tset ypos($num) $tmp\n\tplace $w.frame.$num -relx $xpos($num) -rely $ypos($num)\n    }\n}\n\nset w .puzzle\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"15-Puzzle Demonstration\"\nwm iconname $w \"15-Puzzle\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"A 15-puzzle appears below as a collection of buttons.  Click on any of the pieces next to the space, and that piece will slide over the space.  Continue this until the pieces are arranged in numerical order from upper-left to lower-right.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Special trick: select a darker color for the space by creating a\n# scrollbar widget and using its trough color.\n\nscrollbar $w.s\n\n# The button metrics are a bit bigger in Aqua, and since we are\n# using place which doesn't autosize, then we need to have a\n# slightly larger frame here...\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    set frameSize 126p\n} else {\n    set frameSize 90p\n}\n\nframe $w.frame -width $frameSize -height $frameSize -borderwidth 2 \\\n\t-relief sunken -bg [$w.s cget -troughcolor]\npack $w.frame -side top -pady 1c -padx 1c\ndestroy $w.s\n\nset order {3 1 6 2 5 7 15 13 4 11 8 9 14 10 12}\nfor {set i 0} {$i < 15} {set i [expr {$i+1}]} {\n    set num [lindex $order $i]\n    set xpos($num) [expr {($i%4)*.25}]\n    set ypos($num) [expr {($i/4)*.25}]\n    button $w.frame.$num -relief raised -text $num -bd 0 -highlightthickness 0 \\\n\t    -command \"puzzleSwitch $w $num\"\n    place $w.frame.$num -relx $xpos($num) -rely $ypos($num) \\\n\t-relwidth .25 -relheight .25\n}\nset xpos(space) .75\nset ypos(space) .75\n"
  },
  {
    "path": "library/demos/radio.tcl",
    "content": "# radio.tcl --\n#\n# This demonstration script creates a toplevel window containing\n# several radiobutton widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .radio\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Radiobutton Demonstration\"\nwm iconname $w \"radio\"\npositionWindow $w\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"Three groups of radiobuttons are displayed below.  If you click on a button then the button will become selected exclusively among all the buttons in its group.  A Tcl variable is associated with each group to indicate which of the group's buttons is selected.  When the 'Tristate' button is pressed, the radio buttons will display the tri-state mode. Selecting any radio button will return the buttons to their respective on/off state. Click the \\\"See Variables\\\" button to see the current values of the variables.\"\ngrid $w.msg -row 0 -column 0 -columnspan 3 -sticky nsew\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w [list size color align]]\ngrid $btns -row 3 -column 0 -columnspan 3 -sticky ew\n\nlabelframe $w.left -pady 1.5p -text \"Point Size\" -padx 1.5p\nlabelframe $w.mid -pady 1.5p -text \"Color\" -padx 1.5p\nlabelframe $w.right -pady 1.5p -text \"Alignment\" -padx 1.5p\nbutton $w.tristate -text Tristate -command \"set size multi; set color multi\" \\\n    -pady 1.5p -padx 1.5p\nif {[tk windowingsystem] eq \"aqua\"} {\n    $w.tristate configure -padx 7.5p\n}\ngrid $w.left     -column 0 -row 1 -pady .5c -padx .5c -rowspan 2\ngrid $w.mid      -column 1 -row 1 -pady .5c -padx .5c -rowspan 2\ngrid $w.right    -column 2 -row 1 -pady .5c -padx .5c\ngrid $w.tristate -column 2 -row 2 -pady .5c -padx .5c\n\nforeach i {10 12 14 18 24} {\n    radiobutton $w.left.b$i -text \"Point Size $i\" -variable size \\\n\t    -relief flat -value $i -tristatevalue \"multi\"\n    pack $w.left.b$i  -side top -pady 1.5p -anchor w -fill x\n}\n\nforeach c {Red Green Blue Yellow Orange Purple} {\n    set lower [string tolower $c]\n    radiobutton $w.mid.$lower -text $c -variable color \\\n\t    -relief flat -value $lower -anchor w \\\n\t    -command \"$w.mid configure -fg \\$color\" \\\n\t-tristatevalue \"multi\"\n    pack $w.mid.$lower -side top -pady 1.5p -fill x\n}\n\n\nlabel $w.right.l -text \"Label\" -bitmap questhead -compound left\n$w.right.l configure -width [winfo reqwidth $w.right.l] -compound top\n$w.right.l configure -height [winfo reqheight $w.right.l]\nforeach a {Top Left Right Bottom} {\n    set lower [string tolower $a]\n    radiobutton $w.right.$lower -text $a -variable align \\\n\t    -relief flat -value $lower -indicatoron 0 -width 7 \\\n\t    -command \"$w.right.l configure -compound \\$align\"\n}\n\ngrid x $w.right.top\ngrid $w.right.left $w.right.l $w.right.right\ngrid x $w.right.bottom\n"
  },
  {
    "path": "library/demos/rmt",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# rmt --\n# This script implements a simple remote-control mechanism for\n# Tk applications.  It allows you to select an application and\n# then type commands to that application.\n\npackage require tk\n\nwm title . \"Tk Remote Controller\"\nwm iconname . \"Tk Remote\"\nwm minsize . 1 1\n\n# The global variable below keeps track of the remote application\n# that we're sending to.  If it's an empty string then we execute\n# the commands locally.\n\nset app \"local\"\n\n# The global variable below keeps track of whether we're in the\n# middle of executing a command entered via the text.\n\nset executing 0\n\n# The global variable below keeps track of the last command executed,\n# so it can be re-executed in response to !! commands.\n\nset lastCommand \"\"\n\n# Create menu bar.  Arrange to recreate all the information in the\n# applications sub-menu whenever it is cascaded to.\n\n. configure -menu [menu .menu]\nmenu .menu.file\nmenu .menu.file.apps  -postcommand fillAppsMenu\n.menu add cascade  -label \"File\"  -underline 0  -menu .menu.file\n.menu.file add cascade  -label \"Select Application\"  -underline 0 \\\n\t-menu .menu.file.apps\n.menu.file add command  -label \"Quit\"  -command \"destroy .\"  -underline 0\n\n# Create text window and scrollbar.\n\ntext .t -yscrollcommand \".s set\" -setgrid 1\nscrollbar .s -command \".t yview\"\ngrid .t .s -sticky nsew\ngrid rowconfigure . 0 -weight 1\ngrid columnconfigure . 0 -weight 1\n\n# Create a binding to forward commands to the target application,\n# plus modify many of the built-in bindings so that only information\n# in the current command can be deleted (can still set the cursor\n# earlier in the text and select and insert;  just can't delete).\n\nbindtags .t {.t Text . all}\nbind .t <Return> {\n    .t mark set insert {end - 1c}\n    .t insert insert \\n\n    invoke\n    break\n}\nbind .t <Delete> {\n    catch {.t tag remove sel sel.first promptEnd}\n    if {[.t tag nextrange sel 1.0 end] eq \"\"} {\n\tif {[.t compare insert < promptEnd]} {\n\t    break\n\t}\n    }\n}\nbind .t <BackSpace> {\n    catch {.t tag remove sel sel.first promptEnd}\n    if {[.t tag nextrange sel 1.0 end] eq \"\"} {\n\tif {[.t compare insert <= promptEnd]} {\n\t    break\n\t}\n    }\n}\nbind .t <Control-d> {\n    if {[.t compare insert < promptEnd]} {\n\tbreak\n    }\n}\nbind .t <Control-k> {\n    if {[.t compare insert < promptEnd]} {\n\t.t mark set insert promptEnd\n    }\n}\nbind .t <Control-t> {\n    if {[.t compare insert < promptEnd]} {\n\tbreak\n    }\n}\nbind .t <Meta-d> {\n    if {[.t compare insert < promptEnd]} {\n\tbreak\n    }\n}\nbind .t <Meta-BackSpace> {\n    if {[.t compare insert <= promptEnd]} {\n\tbreak\n    }\n}\nbind .t <Control-h> {\n    if {[.t compare insert <= promptEnd]} {\n\tbreak\n    }\n}\n### This next bit *isn't* nice - DKF ###\nauto_load tk::TextInsert\nproc tk::TextInsert {w s} {\n    if {$s eq \"\"} {\n\treturn\n    }\n    catch {\n\tif {\n\t    [$w compare sel.first <= insert] && [$w compare sel.last >= insert]\n\t} then {\n\t    $w tag remove sel sel.first promptEnd\n\t    $w delete sel.first sel.last\n\t}\n    }\n    $w insert insert $s\n    $w see insert\n}\n\n.t configure -font {Courier 12}\n.t tag configure bold -font {Courier 12 bold}\n\n# The procedure below is used to print out a prompt at the\n# insertion point (which should be at the beginning of a line\n# right now).\n\nproc prompt {} {\n    global app\n    .t insert insert \"$app: \"\n    .t mark set promptEnd {insert}\n    .t mark gravity promptEnd left\n    .t tag add bold {promptEnd linestart} promptEnd\n}\n\n# The procedure below executes a command (it takes everything on the\n# current line after the prompt and either sends it to the remote\n# application or executes it locally, depending on \"app\".\n\nproc invoke {} {\n    global app executing lastCommand\n    set cmd [.t get promptEnd insert]\n    incr executing 1\n    if {[info complete $cmd]} {\n\tif {$cmd eq \"!!\\n\"} {\n\t    set cmd $lastCommand\n\t} else {\n\t    set lastCommand $cmd\n\t}\n\tif {$app eq \"local\"} {\n\t    set result [catch [list uplevel #0 $cmd] msg]\n\t} else {\n\t    set result [catch [list send $app $cmd] msg]\n\t}\n\tif {$result != 0} {\n\t    .t insert insert \"Error: $msg\\n\"\n\t} elseif {$msg ne \"\"} {\n\t    .t insert insert $msg\\n\n\t}\n\tprompt\n\t.t mark set promptEnd insert\n    }\n    incr executing -1\n    .t yview -pickplace insert\n}\n\n# The following procedure is invoked to change the application that\n# we're talking to.  It also updates the prompt for the current\n# command, unless we're in the middle of executing a command from\n# the text item (in which case a new prompt is about to be output\n# so there's no need to change the old one).\n\nproc newApp appName {\n    global app executing\n    set app $appName\n    if {!$executing} {\n\t.t mark gravity promptEnd right\n\t.t delete \"promptEnd linestart\" promptEnd\n\t.t insert promptEnd \"$appName: \"\n\t.t tag add bold \"promptEnd linestart\" promptEnd\n\t.t mark gravity promptEnd left\n    }\n    return\n}\n\n# The procedure below will fill in the applications sub-menu with a list\n# of all the applications that currently exist.\n\nproc fillAppsMenu {} {\n    set m .menu.file.apps\n    catch {$m delete 0 last}\n    foreach i [lsort [winfo interps]] {\n\t$m add command -label $i -command [list newApp $i]\n    }\n    $m add command -label local -command {newApp local}\n}\n\nset app [winfo name .]\nprompt\nfocus .t\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/rolodex",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# rolodex --\n# This script was written as an entry in Tom LaStrange's rolodex\n# benchmark.  It creates something that has some of the look and\n# feel of a rolodex program, although it's lifeless and doesn't\n# actually do the rolodex application.\n\npackage require tk\n\nforeach i [winfo children .] {\n    catch {destroy $i}\n}\n\nset version 1.2\n\n#------------------------------------------\n# Phase 0: create the front end.\n#------------------------------------------\n\nframe .frame -relief flat\npack .frame -side top -fill y -anchor center\n\nset names {{} Name: Address: {} {} {Home Phone:} {Work Phone:} Fax:}\nforeach i {1 2 3 4 5 6 7} {\n    label .frame.label$i -text [lindex $names $i] -anchor e\n    entry .frame.entry$i -width 35\n    grid .frame.label$i .frame.entry$i -sticky ew -pady 1.5p -padx 0.75p\n}\n\nframe .buttons\npack .buttons -side bottom -pady 1.5p -anchor center\nbutton .buttons.clear -text Clear\nbutton .buttons.add -text Add\nbutton .buttons.search -text Search\nbutton .buttons.delete -text \"Delete ...\"\npack .buttons.clear .buttons.add .buttons.search .buttons.delete \\\n\t-side left -padx 1.5p\n\n#------------------------------------------\n# Phase 1: Add menus, dialog boxes\n#------------------------------------------\n\n# DKF - note that this is an old-style menu bar; I just have not yet\n# got around to converting the context help code to work with the new\n# menu system and its <<MenuSelect>> virtual event.\n\nframe .menu -relief raised -borderwidth 1\npack .menu -before .frame -side top -fill x\n\nmenubutton .menu.file -text \"File\" -menu .menu.file.m -underline 0\nmenu .menu.file.m\n.menu.file.m add command -label \"Load ...\" -command fileAction -underline 0\n.menu.file.m add command -label \"Exit\" -command {destroy .} -underline 0\npack .menu.file -side left\n\nmenubutton .menu.help -text \"Help\" -menu .menu.help.m -underline 0\nmenu .menu.help.m\npack .menu.help -side right\n\nproc deleteAction {} {\n    if {[tk_dialog .delete {Confirm Action} {Are you sure?} {} 0  Cancel]\n\t    == 0} {\n\tclearAction\n    }\n}\n.buttons.delete config -command deleteAction\n\nproc fileAction {} {\n    tk_dialog .fileSelection {File Selection} {This is a dummy file selection dialog box, which is used because there isn't a good file selection dialog built into Tk yet.} {} 0 OK\n    puts stderr {dummy file name}\n}\n\n#------------------------------------------\n# Phase 3: Print contents of card\n#------------------------------------------\n\nproc addAction {} {\n    global names\n    foreach i {1 2 3 4 5 6 7} {\n\tputs stderr [format \"%-12s %s\" [lindex $names $i] [.frame.entry$i get]]\n    }\n}\n.buttons.add config -command addAction\n\n#------------------------------------------\n# Phase 4: Miscellaneous other actions\n#------------------------------------------\n\nproc clearAction {} {\n    foreach i {1 2 3 4 5 6 7} {\n\t.frame.entry$i delete 0 end\n    }\n}\n.buttons.clear config -command clearAction\n\nproc fillCard {} {\n    clearAction\n    .frame.entry1 insert 0 \"John Ousterhout\"\n    .frame.entry2 insert 0 \"CS Division, Department of EECS\"\n    .frame.entry3 insert 0 \"University of California\"\n    .frame.entry4 insert 0 \"Berkeley, CA 94720\"\n    .frame.entry5 insert 0 \"private\"\n    .frame.entry6 insert 0 \"510-642-0865\"\n    .frame.entry7 insert 0 \"510-642-5775\"\n}\n.buttons.search config -command \"addAction; fillCard\"\n\n#----------------------------------------------------\n# Phase 5: Accelerators, mnemonics, command-line info\n#----------------------------------------------------\n\n.buttons.clear config -text \"Clear    Ctrl+C\"\nbind . <Control-c> clearAction\n.buttons.add config -text \"Add    Ctrl+A\"\nbind . <Control-a> addAction\n.buttons.search config -text \"Search    Ctrl+S\"\nbind . <Control-s> \"addAction; fillCard\"\n.buttons.delete config -text \"Delete...    Ctrl+D\"\nbind . <Control-d> deleteAction\n\n.menu.file.m entryconfig 1 -accel Ctrl+F\nbind . <Control-f> fileAction\n.menu.file.m entryconfig 2 -accel Ctrl+Q\nbind . <Control-q> {destroy .}\n\nfocus .frame.entry1\n\n#----------------------------------------------------\n# Phase 6: help\n#----------------------------------------------------\n\nproc Help {topic {x 0} {y 0}} {\n    global helpTopics helpCmds\n    if {$topic == \"\"} return\n    while {[info exists helpCmds($topic)]} {\n\tset topic [eval $helpCmds($topic)]\n    }\n    if [info exists helpTopics($topic)] {\n\tset msg $helpTopics($topic)\n    } else {\n\tset msg \"Sorry, but no help is available for this topic\"\n    }\n    tk_dialog .help {Rolodex Help} \"Information on $topic:\\n\\n$msg\" \\\n\t    {} 0 OK\n}\n\nproc getMenuTopic {w x y} {\n    return $w.[$w index @[expr {$y-[winfo rooty $w]}]]\n}\n\nevent add <<Help>> <F1> <Help>\nbind .    <<Help>> {Help [winfo containing %X %Y] %X %Y}\nbind Menu <<Help>> {Help [winfo containing %X %Y] %X %Y}\n\n# Help text and commands follow:\n\nset helpTopics(.menu.file) {This is the \"file\" menu.  It can be used to invoke some overall operations on the rolodex applications, such as loading a file or exiting.}\n\nset helpCmds(.menu.file.m) {getMenuTopic $topic $x $y}\nset helpTopics(.menu.file.m.1) {The \"Load\" entry in the \"File\" menu posts a dialog box that you can use to select a rolodex file}\nset helpTopics(.menu.file.m.2) {The \"Exit\" entry in the \"File\" menu causes the rolodex application to terminate}\nset helpCmds(.menu.file.m.none) {set topic \".menu.file\"}\n\nset helpTopics(.frame.entry1) {In this field of the rolodex entry you should type the person's name}\nset helpTopics(.frame.entry2) {In this field of the rolodex entry you should type the first line of the person's address}\nset helpTopics(.frame.entry3) {In this field of the rolodex entry you should type the second line of the person's address}\nset helpTopics(.frame.entry4) {In this field of the rolodex entry you should type the third line of the person's address}\nset helpTopics(.frame.entry5) {In this field of the rolodex entry you should type the person's home phone number, or \"private\" if the person doesn't want his or her number publicized}\nset helpTopics(.frame.entry6) {In this field of the rolodex entry you should type the person's work phone number}\nset helpTopics(.frame.entry7) {In this field of the rolodex entry you should type the phone number for the person's FAX machine}\n\nset helpCmds(.frame.label1) {set topic .frame.entry1}\nset helpCmds(.frame.label2) {set topic .frame.entry2}\nset helpCmds(.frame.label3) {set topic .frame.entry3}\nset helpCmds(.frame.label4) {set topic .frame.entry4}\nset helpCmds(.frame.label5) {set topic .frame.entry5}\nset helpCmds(.frame.label6) {set topic .frame.entry6}\nset helpCmds(.frame.label7) {set topic .frame.entry7}\n\nset helpTopics(context) {Unfortunately, this application doesn't support context-sensitive help in the usual way, because when this demo was written Tk didn't have a grab mechanism and this is needed for context-sensitive help.  Instead, you can achieve much the same effect by simply moving the mouse over the window you're curious about and pressing the Help or F1 keys.  You can do this anytime.}\nset helpTopics(help) {This application provides only very crude help.  Besides the entries in this menu, you can get help on individual windows by moving the mouse cursor over the window and pressing the Help or F1 keys.}\nset helpTopics(window) {This window is a dummy rolodex application created as part of Tom LaStrange's toolkit benchmark.  It doesn't really do anything useful except to demonstrate a few features of the Tk toolkit.}\nset helpTopics(keys) \"The following accelerator keys are defined for this application (in addition to those already available for the entry windows):\\n\\nCtrl+A:\\t\\tAdd\\nCtrl+C:\\t\\tClear\\nCtrl+D:\\t\\tDelete\\nCtrl+F:\\t\\tEnter file name\\nCtrl+Q:\\t\\tExit application (quit)\\nCtrl+S:\\t\\tSearch (dummy operation)\"\nset helpTopics(version) \"This is version $version.\"\n\n# Entries in \"Help\" menu\n\n.menu.help.m add command -label \"On Context...\" -command {Help context} \\\n\t-underline 3\n.menu.help.m add command -label \"On Help...\" -command {Help help} \\\n\t-underline 3\n.menu.help.m add command -label \"On Window...\" -command {Help window} \\\n\t-underline 3\n.menu.help.m add command -label \"On Keys...\" -command {Help keys} \\\n\t-underline 3\n.menu.help.m add command -label \"On Version...\" -command {Help version}  \\\n\t-underline 3\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/ruler.tcl",
    "content": "# ruler.tcl --\n#\n# This demonstration script creates a canvas widget that displays a ruler\n# with tab stops that can be set, moved, and deleted.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# rulerMkTab --\n# This procedure creates a new triangular polygon in a canvas to\n# represent a tab stop.\n#\n# Arguments:\n# c -\t\tThe canvas window.\n# x, y -\tCoordinates at which to create the tab stop.\n\nproc rulerMkTab {c x y} {\n    upvar #0 demo_rulerInfo v\n    set newTab [$c create polygon $x $y \\\n\t    [expr {$x+$v(size)}] [expr {$y+$v(size)}] \\\n\t    [expr {$x-$v(size)}] [expr {$y+$v(size)}]]\n    set fill [$c itemcget $newTab -outline]\n    $c itemconfigure $newTab -fill $fill -outline {}\n    set v(normalStyle) \"-fill $fill\"\n    return $newTab\n}\n\nset w .ruler\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Ruler Demonstration\"\nwm iconname $w \"ruler\"\npositionWindow $w\nset c $w.c\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"This canvas widget shows a mock-up of a ruler.  You can create tab stops by dragging them out of the well to the right of the ruler.  You can also drag existing tab stops.  If you drag a tab stop far enough up or down so that it turns dim, it will be deleted when you release the mouse button.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\ncanvas $c -width 14.8c -height 2.5c\npack $w.c -side top -fill x\n\nset demo_rulerInfo(grid) .25c\nset demo_rulerInfo(left) [winfo fpixels $c 1c]\nset demo_rulerInfo(right) [winfo fpixels $c 13c]\nset demo_rulerInfo(top) [winfo fpixels $c 1c]\nset demo_rulerInfo(bottom) [winfo fpixels $c 1.5c]\nset demo_rulerInfo(size) [winfo fpixels $c .2c]\n# Main widget program sets variable tk_demoDirectory\nif {[winfo depth $c] > 1} {\n    set demo_rulerInfo(activeStyle) \"-fill red -stipple {}\"\n    set demo_rulerInfo(deleteStyle) [list -fill red \\\n\t    -stipple @[file join $tk_demoDirectory images gray25.xbm]]\n} else {\n    set demo_rulerInfo(activeStyle) \"-fill black -stipple {}\"\n    set demo_rulerInfo(deleteStyle) [list -fill black \\\n\t    -stipple @[file join $tk_demoDirectory images gray25.xbm]]\n}\n\n$c create line 1c 0.5c 1c 1c 13c 1c 13c 0.5c -width 1\nfor {set i 0} {$i < 12} {incr i} {\n    set x [expr {$i+1}]\n    $c create line ${x}c 1c ${x}c 0.6c -width 1\n    $c create line $x.25c 1c $x.25c 0.8c -width 1\n    $c create line $x.5c 1c $x.5c 0.7c -width 1\n    $c create line $x.75c 1c $x.75c 0.8c -width 1\n    $c create text $x.15c .75c -text $i -anchor sw\n}\n$c addtag well withtag [$c create rect 13.2c 1c 13.8c 0.5c \\\n\t-fill [lindex [$c config -bg] 4]]\n$c addtag well withtag [rulerMkTab $c [winfo pixels $c 13.5c] \\\n\t[winfo pixels $c .65c]]\n\n$c bind well <Button-1> \"rulerNewTab $c %x %y\"\n$c bind tab <Button-1> \"rulerSelectTab $c %x %y\"\nbind $c <B1-Motion> \"rulerMoveTab $c %x %y\"\nbind $c <ButtonRelease-1> \"rulerReleaseTab $c\"\n\n# rulerNewTab --\n# Does all the work of creating a tab stop, including creating the\n# triangle object and adding tags to it to give it tab behavior.\n#\n# Arguments:\n# c -\t\tThe canvas window.\n# x, y -\tThe coordinates of the tab stop.\n\nproc rulerNewTab {c x y} {\n    upvar #0 demo_rulerInfo v\n    $c addtag active withtag [rulerMkTab $c $x $y]\n    $c addtag tab withtag active\n    set v(x) $x\n    set v(y) $y\n    rulerMoveTab $c $x $y\n}\n\n# rulerSelectTab --\n# This procedure is invoked when mouse button 1 is pressed over\n# a tab.  It remembers information about the tab so that it can\n# be dragged interactively.\n#\n# Arguments:\n# c -\t\tThe canvas widget.\n# x, y -\tThe coordinates of the mouse (identifies the point by\n#\t\twhich the tab was picked up for dragging).\n\nproc rulerSelectTab {c x y} {\n    upvar #0 demo_rulerInfo v\n    set v(x) [$c canvasx $x $v(grid)]\n    set v(y) [expr {$v(top)+2}]\n    $c addtag active withtag current\n    eval \"$c itemconf active $v(activeStyle)\"\n    $c raise active\n}\n\n# rulerMoveTab --\n# This procedure is invoked during mouse motion events to drag a tab.\n# It adjusts the position of the tab, and changes its appearance if\n# it is about to be dragged out of the ruler.\n#\n# Arguments:\n# c -\t\tThe canvas widget.\n# x, y -\tThe coordinates of the mouse.\n\nproc rulerMoveTab {c x y} {\n    upvar #0 demo_rulerInfo v\n    if {[$c find withtag active] == \"\"} {\n\treturn\n    }\n    set cx [$c canvasx $x $v(grid)]\n    set cy [$c canvasy $y]\n    if {$cx < $v(left)} {\n\tset cx $v(left)\n    }\n    if {$cx > $v(right)} {\n\tset cx $v(right)\n    }\n    if {($cy >= $v(top)) && ($cy <= $v(bottom))} {\n\tset cy [expr {$v(top)+2}]\n\teval \"$c itemconf active $v(activeStyle)\"\n    } else {\n\tset cy [expr {$cy-$v(size)-2}]\n\teval \"$c itemconf active $v(deleteStyle)\"\n    }\n    $c move active [expr {$cx-$v(x)}] [expr {$cy-$v(y)}]\n    set v(x) $cx\n    set v(y) $cy\n}\n\n# rulerReleaseTab --\n# This procedure is invoked during button release events that end\n# a tab drag operation.  It deselects the tab and deletes the tab if\n# it was dragged out of the ruler.\n#\n# Arguments:\n# c -\t\tThe canvas widget.\n# x, y -\tThe coordinates of the mouse.\n\nproc rulerReleaseTab c {\n    upvar #0 demo_rulerInfo v\n    if {[$c find withtag active] == {}} {\n\treturn\n    }\n    if {$v(y) != $v(top)+2} {\n\t$c delete active\n    } else {\n\teval \"$c itemconf active $v(normalStyle)\"\n\t$c dtag active\n    }\n}\n"
  },
  {
    "path": "library/demos/sayings.tcl",
    "content": "# sayings.tcl --\n#\n# This demonstration script creates a listbox that can be scrolled\n# both horizontally and vertically.  It displays a collection of\n# well-known sayings.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .sayings\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Listbox Demonstration (well-known sayings)\"\nwm iconname $w \"sayings\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"The listbox below contains a collection of well-known sayings.  You can scan the list using either of the scrollbars or by dragging in the listbox window with button 2 pressed.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth 7.5p\npack $w.frame -side top -expand yes -fill both -padx 1c\n\n\nttk::scrollbar $w.frame.yscroll -command \"$w.frame.list yview\"\nttk::scrollbar $w.frame.xscroll -orient horizontal \\\n    -command \"$w.frame.list xview\"\nlistbox $w.frame.list -width 20 -height 10 -setgrid 1 \\\n    -yscroll \"$w.frame.yscroll set\" -xscroll \"$w.frame.xscroll set\"\n\ngrid $w.frame.list -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.frame.yscroll -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news\ngrid $w.frame.xscroll -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news\ngrid rowconfig    $w.frame 0 -weight 1 -minsize 0\ngrid columnconfig $w.frame 0 -weight 1 -minsize 0\n\n\n$w.frame.list insert 0 \"Don't speculate, measure\" \"Waste not, want not\" \"Early to bed and early to rise makes a man healthy, wealthy, and wise\" \"Ask not what your country can do for you, ask what you can do for your country\" \"I shall return\" \"NOT\" \"A picture is worth a thousand words\" \"User interfaces are hard to build\" \"Thou shalt not steal\" \"A penny for your thoughts\" \"Fool me once, shame on you;  fool me twice, shame on me\" \"Every cloud has a silver lining\" \"Where there's smoke there's fire\" \"It takes one to know one\" \"Curiosity killed the cat\" \"Take this job and shove it\" \"Up a creek without a paddle\" \"I'm mad as hell and I'm not going to take it any more\" \"An apple a day keeps the doctor away\" \"Don't look a gift horse in the mouth\" \"Measure twice, cut once\"\n"
  },
  {
    "path": "library/demos/search.tcl",
    "content": "# search.tcl --\n#\n# This demonstration script creates a collection of widgets that\n# allow you to load a file into a text widget, then perform searches\n# on that file.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# textLoadFile --\n# This procedure below loads a file into a text widget, discarding\n# the previous contents of the widget. Tags for the old widget are\n# not affected, however.\n#\n# Arguments:\n# w -\t\tThe window into which to load the file.  Must be a\n#\t\ttext widget.\n# file -\tThe name of the file to load.  Must be readable.\n\nproc textLoadFile {w file} {\n    set f [open $file]\n    $w delete 1.0 end\n    while {![eof $f]} {\n\t$w insert end [read $f 10000]\n    }\n    close $f\n}\n\n# textSearch --\n# Search for all instances of a given string in a text widget and\n# apply a given tag to each instance found.\n#\n# Arguments:\n# w -\t\tThe window in which to search.  Must be a text widget.\n# string -\tThe string to search for.  The search is done using\n#\t\texact matching only;  no special characters.\n# tag -\t\tTag to apply to each instance of a matching string.\n\nproc textSearch {w string tag} {\n    $w tag remove search 0.0 end\n    if {$string == \"\"} {\n\treturn\n    }\n    set cur 1.0\n    while 1 {\n\tset cur [$w search -count length $string $cur end]\n\tif {$cur == \"\"} {\n\t    break\n\t}\n\t$w tag add $tag $cur \"$cur + $length char\"\n\tset cur [$w index \"$cur + $length char\"]\n    }\n}\n\n# textToggle --\n# This procedure is invoked repeatedly to invoke two commands at\n# periodic intervals.  It normally reschedules itself after each\n# execution but if an error occurs (e.g. because the window was\n# deleted) then it doesn't reschedule itself.\n#\n# Arguments:\n# cmd1 -\tCommand to execute when procedure is called.\n# sleep1 -\tMs to sleep after executing cmd1 before executing cmd2.\n# cmd2 -\tCommand to execute in the *next* invocation of this\n#\t\tprocedure.\n# sleep2 -\tMs to sleep after executing cmd2 before executing cmd1 again.\n\nproc textToggle {cmd1 sleep1 cmd2 sleep2} {\n    catch {\n\teval $cmd1\n\tafter $sleep1 [list textToggle $cmd2 $sleep2 $cmd1 $sleep1]\n    }\n}\n\nset w .search\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Demonstration - Search and Highlight\"\nwm iconname $w \"search\"\npositionWindow $w\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.file\nlabel $w.file.label -text \"File name:\" -width 13 -anchor w\nentry $w.file.entry -width 40 -textvariable fileName\nbutton $w.file.button -text \"Load File\" \\\n\t-command \"textLoadFile $w.text \\$fileName\"\npack $w.file.label $w.file.entry -side left\npack $w.file.button -side left -pady 3p -padx 7.5p\nbind $w.file.entry <Return> \"\n    textLoadFile $w.text \\$fileName\n    focus $w.string.entry\n\"\nfocus $w.file.entry\n\nframe $w.string\nlabel $w.string.label -text \"Search string:\" -width 13 -anchor w\nentry $w.string.entry -width 40 -textvariable searchString\nbutton $w.string.button -text \"Highlight\" \\\n\t-command \"textSearch $w.text \\$searchString search\"\npack $w.string.label $w.string.entry -side left\npack $w.string.button -side left -pady 3p -padx 7.5p\nbind $w.string.entry <Return> \"textSearch $w.text \\$searchString search\"\n\ntext $w.text -yscrollcommand \"$w.scroll set\" -setgrid 1\nttk::scrollbar $w.scroll -command \"$w.text yview\"\npack $w.file $w.string -side top -fill x\npack $w.scroll -side right -fill y\npack $w.text -expand yes -fill both\n\n# Set up display styles for text highlighting.\n\nif {[winfo depth $w] > 1} {\n    textToggle \"$w.text tag configure search -background \\\n\t    #ce5555 -foreground white\" 800 \"$w.text tag configure \\\n\t    search -background {} -foreground {}\" 200\n} else {\n    textToggle \"$w.text tag configure search -background \\\n\t    black -foreground white\" 800 \"$w.text tag configure \\\n\t    search -background {} -foreground {}\" 200\n}\n$w.text insert 1.0 \\\n{This window demonstrates how to use the tagging facilities in text\nwidgets to implement a searching mechanism.  First, type a file name\nin the top entry, then type <Return> or click on \"Load File\".  Then\ntype a string in the lower entry and type <Return> or click on\n\"Load File\".  This will cause all of the instances of the string to\nbe tagged with the tag \"search\", and it will arrange for the tag's\ndisplay attributes to change to make all of the strings blink.}\n$w.text mark set insert 0.0\n\nset fileName \"\"\nset searchString \"\"\n"
  },
  {
    "path": "library/demos/spin.tcl",
    "content": "# spin.tcl --\n#\n# This demonstration script creates several spinbox widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .spin\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Spinbox Demonstration\"\nwm iconname $w \"spin\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 5i -justify left -text \"Three different\\\n\tspin-boxes are displayed below.  You can add characters by pointing,\\\n\tclicking and typing.  The normal Motif editing characters are\\\n\tsupported, along with many Emacs bindings.  For example, Backspace\\\n\tand Control-h delete the character to the left of the insertion\\\n\tcursor and Delete and Control-d delete the chararacter to the right\\\n\tof the insertion cursor.  For values that are too large to fit in the\\\n\twindow all at once, you can scan through the value by dragging with\\\n\tmouse button2 pressed.  Note that the first spin-box will only permit\\\n\tyou to type in integers, and the third selects from a list of\\\n\tAustralian cities.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nset australianCities {\n    Canberra Sydney Melbourne Perth Adelaide Brisbane\n    Hobart Darwin \"Alice Springs\"\n}\n\nspinbox $w.s1 -from 1 -to 10 -width 10 -validate key \\\n\t-validatecommand {string is integer %P}\nspinbox $w.s2 -from 0 -to 3 -increment .5 -format %05.2f -width 10\nspinbox $w.s3 -values $australianCities -width 10\n\npack $w.s1 $w.s2 $w.s3 -side top -pady 3p -padx 7.5p\n"
  },
  {
    "path": "library/demos/square",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# square --\n# This script generates a demo application containing only a \"square\"\n# widget.  It's only usable in the \"tktest\" application or if Tk has\n# been compiled with tkSquare.c. This demo arranges the following\n# bindings for the widget:\n#\n# Button-1 press/drag:\t\tmoves square to mouse\n# \"a\":\t\t\t\ttoggle size animation on/off\n\npackage require tk\t\t;# We use Tk generally, and...\npackage require tk::test\t;# ... we use the square widget too.\n\nsquare .s\npack .s -expand yes -fill both\nwm minsize . 1 1\n\nbind .s <Button-1> {center %x %y}\nbind .s <B1-Motion> {center %x %y}\nbind .s a animate\nfocus .s\n\n# The procedure below centers the square on a given position.\n\nproc center {x y} {\n    set a [.s size]\n    .s position [expr {$x-($a/2)}] [expr {$y-($a/2)}]\n}\n\n# The procedures below provide a simple form of animation where\n# the box changes size in a pulsing pattern: larger, smaller, larger,\n# and so on.\n\nset inc 0\nproc animate {} {\n    global inc\n    if {$inc == 0} {\n\tset inc 3\n\ttimer\n    } else {\n\tset inc 0\n    }\n}\n\nproc timer {} {\n    global inc\n    set s [.s size]\n    if {$inc == 0} return\n    if {$s >= 40} {set inc -3}\n    if {$s <= 10} {set inc 3}\n    .s size [expr {$s+$inc}]\n    after 30 timer\n}\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/states.tcl",
    "content": "# states.tcl --\n#\n# This demonstration script creates a listbox widget that displays\n# the names of the 50 states in the United States of America.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .states\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Listbox Demonstration (50 states)\"\nwm iconname $w \"states\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -justify left -text \"A listbox containing the 50 states is displayed below, along with a scrollbar.  You can scan the list either using the scrollbar or by scanning.  To scan, press button 2 in the widget and drag up or down.\"\npack $w.msg -side top\n\nlabelframe $w.justif -text Justification\nforeach c {Left Center Right} {\n    set lower [string tolower $c]\n    radiobutton $w.justif.$lower -text $c -variable just \\\n\t-relief flat -value $lower -anchor w \\\n\t-command \"$w.frame.list configure -justify \\$just\" \\\n\t-tristatevalue \"multi\"\n    pack $w.justif.$lower -side left -pady 1.5p -fill x\n}\npack $w.justif\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth .5c\npack $w.frame -side top -expand yes -fill y\n\nttk::scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\nlistbox $w.frame.list -yscroll \"$w.frame.scroll set\" -setgrid 1 -height 12\npack $w.frame.scroll -side right -fill y\npack $w.frame.list -side left -expand 1 -fill both\n\n$w.frame.list insert 0 Alabama Alaska Arizona Arkansas California \\\n    Colorado Connecticut Delaware Florida Georgia Hawaii Idaho Illinois \\\n    Indiana Iowa Kansas Kentucky Louisiana Maine Maryland \\\n    Massachusetts Michigan Minnesota Mississippi Missouri \\\n    Montana Nebraska Nevada \"New Hampshire\" \"New Jersey\" \"New Mexico\" \\\n    \"New York\" \"North Carolina\" \"North Dakota\" \\\n    Ohio Oklahoma Oregon Pennsylvania \"Rhode Island\" \\\n    \"South Carolina\" \"South Dakota\" \\\n    Tennessee Texas Utah Vermont Virginia Washington \\\n    \"West Virginia\" Wisconsin Wyoming\n"
  },
  {
    "path": "library/demos/style.tcl",
    "content": "# style.tcl --\n#\n# This demonstration script creates a text widget that illustrates the\n# various display styles that may be set for tags.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .style\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Demonstration - Display Styles\"\nwm iconname $w \"style\"\npositionWindow $w\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n# Only set the font family in one place for simplicity and consistency\n\nset family Courier\n\ntext $w.text -yscrollcommand \"$w.scroll set\" -setgrid 1 \\\n\t-width 70 -height 32 -wrap word -font \"$family 12\"\nttk::scrollbar $w.scroll -command \"$w.text yview\"\npack $w.scroll -side right -fill y\npack $w.text -expand yes -fill both\n\n# Set up display styles\n\n$w.text tag configure bold -font \"$family 12 bold italic\"\n$w.text tag configure big -font \"$family 14 bold\"\n$w.text tag configure verybig -font \"Helvetica 24 bold\"\n$w.text tag configure tiny -font \"Times 8 bold\"\nif {[winfo depth $w] > 1} {\n    $w.text tag configure color1 -background #a0b7ce\n    $w.text tag configure color2 -foreground red\n    $w.text tag configure raised -relief raised -borderwidth 1\n    $w.text tag configure sunken -relief sunken -borderwidth 1\n} else {\n    $w.text tag configure color1 -background black -foreground white\n    $w.text tag configure color2 -background black -foreground white\n    $w.text tag configure raised -background white -relief raised \\\n\t    -borderwidth 1\n    $w.text tag configure sunken -background white -relief sunken \\\n\t    -borderwidth 1\n}\n$w.text tag configure bgstipple -background black -borderwidth 0 \\\n\t-bgstipple gray12\n$w.text tag configure fgstipple -fgstipple gray50\n$w.text tag configure underline -underline 1\n$w.text tag configure overstrike -overstrike 1\n$w.text tag configure right -justify right\n$w.text tag configure center -justify center\n$w.text tag configure super -offset 4p -font \"$family 10\"\n$w.text tag configure sub -offset -2p -font \"$family 10\"\n$w.text tag configure margins -lmargin1 12m -lmargin2 6m -rmargin 10m\n$w.text tag configure spacing -spacing1 10p -spacing2 2p \\\n\t-lmargin1 12m -lmargin2 6m -rmargin 10m\n\n$w.text insert end {Text widgets like this one allow you to display information in a\nvariety of styles.  Display styles are controlled using a mechanism\ncalled }\n$w.text insert end tags bold\n$w.text insert end {.  Tags are just textual names that you can apply to one\nor more ranges of characters within a text widget.  You can configure\ntags with various display styles.  If you do this, then the tagged\ncharacters will be displayed with the styles you chose.  The\navailable display styles are:\n}\n$w.text insert end \"\\n1. Font.\" big\n$w.text insert end \"  You can choose any system font, \"\n$w.text insert end large verybig\n$w.text insert end \" or \"\n$w.text insert end \"small\" tiny \".\\n\"\n$w.text insert end \"\\n2. Color.\" big\n$w.text insert end \"  You can change either the \"\n$w.text insert end background color1\n$w.text insert end \" or \"\n$w.text insert end foreground color2\n$w.text insert end \"\\ncolor, or \"\n$w.text insert end both {color1 color2}\n$w.text insert end \".\\n\"\n$w.text insert end \"\\n3. Stippling.\" big\n$w.text insert end \"  You can cause either the \"\n$w.text insert end background bgstipple\n$w.text insert end \" or \"\n$w.text insert end foreground fgstipple\n$w.text insert end {\ninformation to be drawn with a stipple fill instead of a solid fill.\n}\n$w.text insert end \"\\n4. Underlining.\" big\n$w.text insert end \"  You can \"\n$w.text insert end underline underline\n$w.text insert end \" ranges of text.\\n\"\n$w.text insert end \"\\n5. Overstrikes.\" big\n$w.text insert end \"  You can \"\n$w.text insert end \"draw lines through\" overstrike\n$w.text insert end \" ranges of text.\\n\"\n$w.text insert end \"\\n6. 3-D effects.\" big\n$w.text insert end {  You can arrange for the background to be drawn\nwith a border that makes characters appear either }\n$w.text insert end raised raised\n$w.text insert end \" or \"\n$w.text insert end sunken sunken\n$w.text insert end \".\\n\"\n$w.text insert end \"\\n7. Justification.\" big\n$w.text insert end \" You can arrange for lines to be displayed\\n\"\n$w.text insert end \"left-justified,\\n\"\n$w.text insert end \"right-justified, or\\n\" right\n$w.text insert end \"centered.\\n\" center\n$w.text insert end \"\\n8. Superscripts and subscripts.\"  big\n$w.text insert end \" You can control the vertical\\n\"\n$w.text insert end \"position of text to generate superscript effects like 10\"\n$w.text insert end \"n\" super\n$w.text insert end \" or\\nsubscript effects like X\"\n$w.text insert end \"i\" sub\n$w.text insert end \".\\n\"\n$w.text insert end \"\\n9. Margins.\" big\n$w.text insert end \" You can control the amount of extra space left\"\n$w.text insert end \" on\\neach side of the text:\\n\"\n$w.text insert end \"This paragraph is an example of the use of \" margins\n$w.text insert end \"margins.  It consists of a single line of text \" margins\n$w.text insert end \"that wraps around on the screen.  There are two \" margins\n$w.text insert end \"separate left margin values, one for the first \" margins\n$w.text insert end \"display line associated with the text line, \" margins\n$w.text insert end \"and one for the subsequent display lines, which \" margins\n$w.text insert end \"occur because of wrapping.  There is also a \" margins\n$w.text insert end \"separate specification for the right margin, \" margins\n$w.text insert end \"which is used to choose wrap points for lines.\\n\" margins\n$w.text insert end \"\\n10. Spacing.\" big\n$w.text insert end \" You can control the spacing of lines with three\\n\"\n$w.text insert end \"separate parameters.  \\\"Spacing1\\\" tells how much \"\n$w.text insert end \"extra space to leave\\nabove a line, \\\"spacing3\\\" \"\n$w.text insert end \"tells how much space to leave below a line,\\nand \"\n$w.text insert end \"if a text line wraps, \\\"spacing2\\\" tells how much \"\n$w.text insert end \"space to leave\\nbetween the display lines that \"\n$w.text insert end \"make up the text line.\\n\"\n$w.text insert end \"These indented paragraphs illustrate how spacing \" spacing\n$w.text insert end \"can be used.  Each paragraph is actually a \" spacing\n$w.text insert end \"single line in the text widget, which is \" spacing\n$w.text insert end \"word-wrapped by the widget.\\n\" spacing\n$w.text insert end \"Spacing1 is set to 10 points for this text, \" spacing\n$w.text insert end \"which results in relatively large gaps between \" spacing\n$w.text insert end \"the paragraphs.  Spacing2 is set to 2 points, \" spacing\n$w.text insert end \"which results in just a bit of extra space \" spacing\n$w.text insert end \"within a pararaph.  Spacing3 isn't used \" spacing\n$w.text insert end \"in this example.\\n\" spacing\n$w.text insert end \"To see where the space is, select ranges of \" spacing\n$w.text insert end \"text within these paragraphs.  The selection \" spacing\n$w.text insert end \"highlight will cover the extra space.\" spacing\n"
  },
  {
    "path": "library/demos/systray.tcl",
    "content": "# systray.tcl --\n#\n# This demonstration script showcases the tk systray and tk sysnotify commands.\n#\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\nset w .systray\ndestroy $w\ntoplevel $w\nwm title $w \"System Tray Demonstration\"\npositionWindow $w\n\n## See Code / Dismiss buttons\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\ncatch {tk systray destroy}\nset trayIconExists false\n\nset iconmenu .menubar\ndestroy $iconmenu\nmenu $iconmenu\n$iconmenu add command -label \"Status\" -command { puts \"status icon clicked\" }\n$iconmenu add command -label \"Exit\" -command exit\n\npack [label $w.l -text \"This demonstration showcases\n\tthe tk systray and tk sysnotify commands.\n\tRunning this demo creates the systray icon.\n\tClicking the buttons below modifies and destroys the icon\n\tand displays the notification.\"]\n\nimage create photo book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n\nlabelframe $w.f -text \"Tray Icon\"\nbutton $w.f.b0 -text \"Create\" -command create\nbutton $w.f.b1 -text \"Modify\" -command modify\nbutton $w.f.b2 -text \"Destroy\" -command remove\npack $w.f.b0 $w.f.b1 $w.f.b2 -padx 3p -pady 3p -side left -expand true -fill x\n\nbutton $w.b3 -text \"Display Notification\" -command notify\npack $w.f $w.b3 -fill x -padx 3p -pady 3p\n\nproc create {} {\n    global trayIconExists\n    if {$trayIconExists} {\n\ttk_messageBox -message \"Systray icon already exists\"\n\treturn\n    }\n    tk systray create -image book -text \"Systray sample\" \\\n\t    -button1 {puts \"foo\"} \\\n\t    -button3 {tk_popup $iconmenu [winfo pointerx .] [winfo pointery .]}\n    set trayIconExists true\n}\n\nproc modify {} {\n    global trayIconExists\n    if {!$trayIconExists} {\n\ttk_messageBox -message \"Please create systray icon first\"\n\treturn\n    }\n    image create photo page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7\n    tk systray configure -image page\n    tk systray configure -text \"Modified text\"\n    tk systray configure -button1 {puts \"this is a different output\"}\n    tk systray configure -button3 {puts \"hello yall\"}\n}\n\nproc notify {} {\n    global trayIconExists\n    if {!$trayIconExists} {\n\ttk_messageBox -message \"Please create systray icon first\"\n\treturn\n    }\n    tk sysnotify  \"Alert\" \"This is an alert\"\n}\n\nproc remove {} {\n    global trayIconExists\n    if {!$trayIconExists} {\n\ttk_messageBox -message \"Systray icon was already destroyed\"\n\treturn\n    }\n    tk systray destroy\n    set trayIconExists false\n}\n\ncreate\n"
  },
  {
    "path": "library/demos/tclIndex",
    "content": "# Tcl autoload index file, version 2.0\n# This file is generated by the \"auto_mkindex\" command\n# and sourced to set up indexing information for one or\n# more commands.  Typically each line is a command that\n# sets an element in the auto_index array, where the\n# element name is the name of a command and the value is\n# a script that loads the command.\n\nset auto_index(arrowSetup) [list source [file join $dir arrow.tcl]]\nset auto_index(arrowMove1) [list source [file join $dir arrow.tcl]]\nset auto_index(arrowMove2) [list source [file join $dir arrow.tcl]]\nset auto_index(arrowMove3) [list source [file join $dir arrow.tcl]]\nset auto_index(textLoadFile) [list source [file join $dir search.tcl]]\nset auto_index(textSearch) [list source [file join $dir search.tcl]]\nset auto_index(textToggle) [list source [file join $dir search.tcl]]\nset auto_index(itemEnter) [list source [file join $dir items.tcl]]\nset auto_index(itemLeave) [list source [file join $dir items.tcl]]\nset auto_index(itemMark) [list source [file join $dir items.tcl]]\nset auto_index(itemStroke) [list source [file join $dir items.tcl]]\nset auto_index(itemsUnderArea) [list source [file join $dir items.tcl]]\nset auto_index(itemStartDrag) [list source [file join $dir items.tcl]]\nset auto_index(itemDrag) [list source [file join $dir items.tcl]]\nset auto_index(butPress) [list source [file join $dir items.tcl]]\nset auto_index(loadDir) [list source [file join $dir image2.tcl]]\nset auto_index(loadImage) [list source [file join $dir image2.tcl]]\nset auto_index(rulerMkTab) [list source [file join $dir ruler.tcl]]\nset auto_index(rulerNewTab) [list source [file join $dir ruler.tcl]]\nset auto_index(rulerSelectTab) [list source [file join $dir ruler.tcl]]\nset auto_index(rulerMoveTab) [list source [file join $dir ruler.tcl]]\nset auto_index(rulerReleaseTab) [list source [file join $dir ruler.tcl]]\nset auto_index(mkTextConfig) [list source [file join $dir ctext.tcl]]\nset auto_index(textEnter) [list source [file join $dir ctext.tcl]]\nset auto_index(textInsert) [list source [file join $dir ctext.tcl]]\nset auto_index(textPaste) [list source [file join $dir ctext.tcl]]\nset auto_index(textB1Press) [list source [file join $dir ctext.tcl]]\nset auto_index(textB1Move) [list source [file join $dir ctext.tcl]]\nset auto_index(textBs) [list source [file join $dir ctext.tcl]]\nset auto_index(textDel) [list source [file join $dir ctext.tcl]]\nset auto_index(bitmapRow) [list source [file join $dir bitmap.tcl]]\nset auto_index(scrollEnter) [list source [file join $dir cscroll.tcl]]\nset auto_index(scrollLeave) [list source [file join $dir cscroll.tcl]]\nset auto_index(scrollButton) [list source [file join $dir cscroll.tcl]]\nset auto_index(textWindOn) [list source [file join $dir twind.tcl]]\nset auto_index(textWindOff) [list source [file join $dir twind.tcl]]\nset auto_index(textWindPlot) [list source [file join $dir twind.tcl]]\nset auto_index(embPlotDown) [list source [file join $dir twind.tcl]]\nset auto_index(embPlotMove) [list source [file join $dir twind.tcl]]\nset auto_index(textWindDel) [list source [file join $dir twind.tcl]]\nset auto_index(embDefBg) [list source [file join $dir twind.tcl]]\nset auto_index(floorDisplay) [list source [file join $dir floor.tcl]]\nset auto_index(newRoom) [list source [file join $dir floor.tcl]]\nset auto_index(roomChanged) [list source [file join $dir floor.tcl]]\nset auto_index(bg1) [list source [file join $dir floor.tcl]]\nset auto_index(bg2) [list source [file join $dir floor.tcl]]\nset auto_index(bg3) [list source [file join $dir floor.tcl]]\nset auto_index(fg1) [list source [file join $dir floor.tcl]]\nset auto_index(fg2) [list source [file join $dir floor.tcl]]\nset auto_index(fg3) [list source [file join $dir floor.tcl]]\nset auto_index(setWidth) [list source [file join $dir hscale.tcl]]\nset auto_index(plotDown) [list source [file join $dir plot.tcl]]\nset auto_index(plotMove) [list source [file join $dir plot.tcl]]\nset auto_index(puzzleSwitch) [list source [file join $dir puzzle.tcl]]\nset auto_index(setHeight) [list source [file join $dir vscale.tcl]]\nset auto_index(showMessageBox) [list source [file join $dir msgbox.tcl]]\nset auto_index(setColor) [list source [file join $dir clrpick.tcl]]\nset auto_index(setColor_helper) [list source [file join $dir clrpick.tcl]]\nset auto_index(fileDialog) [list source [file join $dir filebox.tcl]]\nset auto_index(systray) [list source [file join $dir systray.tcl]]\nset auto_index(windoicons [list source [file join $dir windowicons.tcl]]\n\n"
  },
  {
    "path": "library/demos/tcolor",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# tcolor --\n# This script implements a simple color editor, where you can\n# create colors using either the RGB, HSB, or CYM color spaces\n# and apply the color to existing applications.\n\npackage require tk\nwm title . \"Color Editor\"\n\n# Global variables that control the program:\n#\n# colorSpace -\t\t\tColor space currently being used for\n#\t\t\t\tediting.  Must be \"rgb\", \"cmy\", or \"hsb\".\n# label1, label2, label3 -\tLabels for the scales.\n# red, green, blue -\t\tCurrent color intensities in decimal\n#\t\t\t\ton a scale of 0-65535.\n# color -\t\t\tA string giving the current color value\n#\t\t\t\tin the proper form for x:\n#\t\t\t\t#RRRRGGGGBBBB\n# updating -\t\t\tNon-zero means that we're in the middle of\n#\t\t\t\tupdating the scales to load a new color,so\n#\t\t\t\tinformation shouldn't be propagating back\n#\t\t\t\tfrom the scales to other elements of the\n#\t\t\t\tprogram:  this would make an infinite loop.\n# command -\t\t\tHolds the command that has been typed\n#\t\t\t\tinto the \"Command\" entry.\n# autoUpdate -\t\t\t1 means execute the update command\n#\t\t\t\tautomatically whenever the color changes.\n# name -\t\t\tName for new color, typed into entry.\n\nset colorSpace hsb\nset red 65535\nset green 0\nset blue 0\nset color #ffff00000000\nset updating 0\nset autoUpdate 1\nset name \"\"\n\n# Create the menu bar at the top of the window.\n\n. configure -menu [menu .menu]\nmenu .menu.file\n.menu add cascade  -menu .menu.file  -label File  -underline 0\n.menu.file add radio -label \"RGB color space\" -variable colorSpace \\\n\t-value rgb -underline 0 -command {changeColorSpace rgb}\n.menu.file add radio -label \"CMY color space\" -variable colorSpace \\\n\t-value cmy -underline 0 -command {changeColorSpace cmy}\n.menu.file add radio -label \"HSB color space\" -variable colorSpace \\\n\t-value hsb -underline 0 -command {changeColorSpace hsb}\n.menu.file add separator\n.menu.file add radio -label \"Automatic updates\" -variable autoUpdate \\\n\t-value 1 -underline 0\n.menu.file add radio -label \"Manual updates\" -variable autoUpdate \\\n\t-value 0 -underline 0\n.menu.file add separator\n.menu.file add command -label \"Exit program\" -underline 0 -command {exit}\n\n# Create the command entry window at the bottom of the window, along\n# with the update button.\n\nlabelframe .command -text \"Command:\" -padx {1m 0}\nentry .command.e -textvariable command\nbutton .command.update -text Update -command doUpdate\npack .command.update -side right -pady .1c -padx {.25c 0}\npack .command.e -expand yes -fill x -ipadx 0.25c\n\n\n# Create the listbox that holds all of the color names in rgb.txt,\n# if an rgb.txt file can be found.\n\ngrid .command -sticky nsew -row 2 -columnspan 3 -padx 1m -pady {0 1m}\n\ngrid columnconfigure . {1 2} -weight 1\ngrid rowconfigure . 0 -weight 1\nforeach i {\n    /usr/local/lib/X11/rgb.txt /usr/lib/X11/rgb.txt\n    /X11/R5/lib/X11/rgb.txt /X11/R4/lib/rgb/rgb.txt\n    /usr/openwin/lib/X11/rgb.txt\n} {\n    if {![file readable $i]} {\n\tcontinue;\n    }\n    set f [open $i]\n    labelframe .names -text \"Select:\" -padx .1c -pady .1c\n    grid .names -row 0 -column 0 -sticky nsew -padx .15c -pady .15c -rowspan 2\n    grid columnconfigure . 0 -weight 1\n    listbox .names.lb -width 20 -height 12 -yscrollcommand \".names.s set\" \\\n\t-exportselection false\n    bind .names.lb <Double-Button-1> {\n\t    tc_loadNamedColor [.names.lb get [.names.lb curselection]]\n    }\n    scrollbar .names.s -orient vertical -command \".names.lb yview\"\n    pack .names.lb .names.s -side left -fill y -expand 1\n    while {[gets $f line] >= 0} {\n\tif {[regexp {^\\s*\\d+\\s+\\d+\\s+\\d+\\s+(\\S+)$} $line -> col]} {\n\t    .names.lb insert end $col\n\t}\n    }\n    close $f\n    break\n}\n\n# Create the three scales for editing the color, and the entry for\n# typing in a color value.\n\nframe .adjust\nforeach i {1 2 3} {\n    label .adjust.l$i -textvariable label$i -pady 0\n    labelframe .adjust.$i -labelwidget .adjust.l$i -padx 1m -pady 1m\n    scale .scale$i -from 0 -to 1000 -length 6c -orient horizontal \\\n\t    -command tc_scaleChanged\n    pack .scale$i -in .adjust.$i\n    pack .adjust.$i\n}\ngrid .adjust -row 0 -column 1 -sticky nsew -padx .15c -pady .15c\n\nlabelframe .name -text \"Name:\" -padx 1m -pady 1m\nentry .name.e -textvariable name -width 10\npack .name.e -side right -expand 1 -fill x\nbind .name.e <Return> {tc_loadNamedColor $name}\ngrid .name   -column 1 -row 1 -sticky nsew -padx .15c -pady .15c\n\n# Create the color display swatch on the right side of the window.\n\nlabelframe .sample -text \"Color:\" -padx 1m -pady 1m\nframe .sample.swatch -width 2c -height 5c -background $color\nlabel .sample.value -textvariable color -width 13 -font {Courier 12}\npack .sample.swatch -side top -expand yes -fill both\npack .sample.value -side bottom -pady .25c\ngrid .sample -row 0 -column 2 -sticky nsew -padx .15c -pady .15c -rowspan 2\n\n\n# The procedure below is invoked when one of the scales is adjusted.\n# It propagates color information from the current scale readings\n# to everywhere else that it is used.\n\nproc tc_scaleChanged args {\n    global red green blue colorSpace color updating autoUpdate\n    if {$updating} {\n\treturn\n    }\n    switch $colorSpace {\n\trgb {\n\t    set red   [format %.0f [expr {[.scale1 get]*65.535}]]\n\t    set green [format %.0f [expr {[.scale2 get]*65.535}]]\n\t    set blue  [format %.0f [expr {[.scale3 get]*65.535}]]\n\t}\n\tcmy {\n\t    set red   [format %.0f [expr {65535 - [.scale1 get]*65.535}]]\n\t    set green [format %.0f [expr {65535 - [.scale2 get]*65.535}]]\n\t    set blue  [format %.0f [expr {65535 - [.scale3 get]*65.535}]]\n\t}\n\thsb {\n\t    set list [hsbToRgb [expr {[.scale1 get]/1000.0}] \\\n\t\t    [expr {[.scale2 get]/1000.0}] \\\n\t\t    [expr {[.scale3 get]/1000.0}]]\n\t    set red [lindex $list 0]\n\t    set green [lindex $list 1]\n\t    set blue [lindex $list 2]\n\t}\n    }\n    set color [format \"#%04x%04x%04x\" $red $green $blue]\n    .sample.swatch config -bg $color\n    if {$autoUpdate} doUpdate\n    update idletasks\n}\n\n# The procedure below is invoked to update the scales from the\n# current red, green, and blue intensities.  It's invoked after\n# a change in the color space and after a named color value has\n# been loaded.\n\nproc tc_setScales {} {\n    global red green blue colorSpace updating\n    set updating 1\n    switch $colorSpace {\n\trgb {\n\t    .scale1 set [format %.0f [expr {$red/65.535}]]\n\t    .scale2 set [format %.0f [expr {$green/65.535}]]\n\t    .scale3 set [format %.0f [expr {$blue/65.535}]]\n\t}\n\tcmy {\n\t    .scale1 set [format %.0f [expr {(65535-$red)/65.535}]]\n\t    .scale2 set [format %.0f [expr {(65535-$green)/65.535}]]\n\t    .scale3 set [format %.0f [expr {(65535-$blue)/65.535}]]\n\t}\n\thsb {\n\t    set list [rgbToHsv $red $green $blue]\n\t    .scale1 set [format %.0f [expr {[lindex $list 0] * 1000.0}]]\n\t    .scale2 set [format %.0f [expr {[lindex $list 1] * 1000.0}]]\n\t    .scale3 set [format %.0f [expr {[lindex $list 2] * 1000.0}]]\n\t}\n    }\n    set updating 0\n}\n\n# The procedure below is invoked when a named color has been\n# selected from the listbox or typed into the entry.  It loads\n# the color into the editor.\n\nproc tc_loadNamedColor name {\n    global red green blue color autoUpdate\n\n    if {[string index $name 0] != \"#\"} {\n\tset list [winfo rgb .sample.swatch $name]\n\tset red [lindex $list 0]\n\tset green [lindex $list 1]\n\tset blue [lindex $list 2]\n    } else {\n\tswitch [string length $name] {\n\t    4  {set format \"#%1x%1x%1x\"; set shift 12}\n\t    7  {set format \"#%2x%2x%2x\"; set shift 8}\n\t    10 {set format \"#%3x%3x%3x\"; set shift 4}\n\t    13 {set format \"#%4x%4x%4x\"; set shift 0}\n\t    default {error \"syntax error in color name \\\"$name\\\"\"}\n\t}\n\tif {[scan $name $format red green blue] != 3} {\n\t    error \"syntax error in color name \\\"$name\\\"\"\n\t}\n\tset red   [expr {$red<<$shift}]\n\tset green [expr {$green<<$shift}]\n\tset blue  [expr {$blue<<$shift}]\n    }\n    tc_setScales\n    set color [format \"#%04x%04x%04x\" $red $green $blue]\n    .sample.swatch config -bg $color\n    if {$autoUpdate} doUpdate\n}\n\n# The procedure below is invoked when a new color space is selected.\n# It changes the labels on the scales and re-loads the scales with\n# the appropriate values for the current color in the new color space\n\nproc changeColorSpace space {\n    global label1 label2 label3\n    switch $space {\n\trgb {\n\t    set label1 \"Adjust Red:\"\n\t    set label2 \"Adjust Green:\"\n\t    set label3 \"Adjust Blue:\"\n\t    tc_setScales\n\t    return\n\t}\n\tcmy {\n\t    set label1 \"Adjust Cyan:\"\n\t    set label2 \"Adjust Magenta:\"\n\t    set label3 \"Adjust Yellow:\"\n\t    tc_setScales\n\t    return\n\t}\n\thsb {\n\t    set label1 \"Adjust Hue:\"\n\t    set label2 \"Adjust Saturation:\"\n\t    set label3 \"Adjust Brightness:\"\n\t    tc_setScales\n\t    return\n\t}\n    }\n}\n\n# The procedure below converts an RGB value to HSB.  It takes red, green,\n# and blue components (0-65535) as arguments, and returns a list containing\n# HSB components (floating-point, 0-1) as result.  The code here is a copy\n# of the code on page 615 of \"Fundamentals of Interactive Computer Graphics\"\n# by Foley and Van Dam.\n\nproc rgbToHsv {red green blue} {\n    if {$red > $green} {\n\tset max [expr {double($red)}]\n\tset min [expr {double($green)}]\n    } else {\n\tset max [expr {double($green)}]\n\tset min [expr {double($red)}]\n    }\n    if {$blue > $max} {\n\tset max [expr {double($blue)}]\n    } elseif {$blue < $min} {\n\tset min [expr {double($blue)}]\n    }\n    set range [expr {$max-$min}]\n    if {$max == 0} {\n\tset sat 0\n    } else {\n\tset sat [expr {($max-$min)/$max}]\n    }\n    if {$sat == 0} {\n\tset hue 0\n    } else {\n\tset rc [expr {($max - $red)/$range}]\n\tset gc [expr {($max - $green)/$range}]\n\tset bc [expr {($max - $blue)/$range}]\n\tif {$red == $max} {\n\t    set hue [expr {($bc - $gc)/6.0}]\n\t} elseif {$green == $max} {\n\t    set hue [expr {(2 + $rc - $bc)/6.0}]\n\t} else {\n\t    set hue [expr {(4 + $gc - $rc)/6.0}]\n\t}\n\tif {$hue < 0.0} {\n\t    set hue [expr {$hue + 1.0}]\n\t}\n    }\n    return [list $hue $sat [expr {$max/65535}]]\n}\n\n# The procedure below converts an HSB value to RGB.  It takes hue, saturation,\n# and value components (floating-point, 0-1.0) as arguments, and returns a\n# list containing RGB components (integers, 0-65535) as result.  The code\n# here is a copy of the code on page 616 of \"Fundamentals of Interactive\n# Computer Graphics\" by Foley and Van Dam.\n\nproc hsbToRgb {hue sat value} {\n    set v [format %.0f [expr {65535.0*$value}]]\n    if {$sat == 0} {\n\treturn \"$v $v $v\"\n    } else {\n\tset hue [expr {$hue*6.0}]\n\tif {$hue >= 6.0} {\n\t    set hue 0.0\n\t}\n\tscan $hue. %d i\n\tset f [expr {$hue-$i}]\n\tset p [format %.0f [expr {65535.0*$value*(1 - $sat)}]]\n\tset q [format %.0f [expr {65535.0*$value*(1 - ($sat*$f))}]]\n\tset t [format %.0f [expr {65535.0*$value*(1 - ($sat*(1 - $f)))}]]\n\tswitch $i {\n\t    0 {return \"$v $t $p\"}\n\t    1 {return \"$q $v $p\"}\n\t    2 {return \"$p $v $t\"}\n\t    3 {return \"$p $q $v\"}\n\t    4 {return \"$t $p $v\"}\n\t    5 {return \"$v $p $q\"}\n\t    default {error \"i value $i is out of range\"}\n\t}\n    }\n}\n\n# The procedure below is invoked when the \"Update\" button is pressed,\n# and whenever the color changes if update mode is enabled.  It\n# propagates color information as determined by the command in the\n# Command entry.\n\nproc doUpdate {} {\n    global color command\n    set newCmd $command\n    regsub -all %% $command $color newCmd\n    eval $newCmd\n}\n\nchangeColorSpace hsb\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/text.tcl",
    "content": "# text.tcl --\n#\n# This demonstration script creates a text widget that describes\n# the basic editing functions.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .text\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Demonstration - Basic Facilities\"\nwm iconname $w \"text\"\npositionWindow $w\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w {} \\\n\t{ttk::button $w.buttons.fontchooser -command fontchooserToggle}]\npack $btns -side bottom -fill x\n\ntext $w.text -yscrollcommand [list $w.scroll set] -setgrid 1 \\\n\t-height 30 -undo 1 -autosep 1\nttk::scrollbar $w.scroll -command [list $w.text yview]\npack $w.scroll -side right -fill y\npack $w.text -expand yes -fill both\n\n# TIP 324 Demo: [tk fontchooser]\nproc fontchooserToggle {} {\n    tk fontchooser [expr {[tk fontchooser configure -visible] ?\n\t    \"hide\" : \"show\"}]\n}\nproc fontchooserVisibility {w} {\n    $w configure -text [expr {[tk fontchooser configure -visible] ?\n\t    \"Hide Font Dialog\" : \"Show Font Dialog\"}]\n}\nproc fontchooserFocus {w} {\n    tk fontchooser configure -font [$w cget -font] \\\n\t    -command [list fontchooserFontSel $w]\n}\nproc fontchooserFontSel {w font args} {\n    $w configure -font [font actual $font]\n}\ntk fontchooser configure -parent $w\nbind $w.text <FocusIn> [list fontchooserFocus $w.text]\nfontchooserVisibility $w.buttons.fontchooser\nbind $w <<TkFontchooserVisibility>> [list \\\n\tfontchooserVisibility $w.buttons.fontchooser]\nfocus $w.text\n\n$w.text insert 0.0 \\\n{This window is a text widget.  It displays one or more lines of text\nand allows you to edit the text.  Here is a summary of the things you\ncan do to a text widget:\n\n1. Scrolling. Use the scrollbar to adjust the view in the text window.\n\n2. Scanning. Press the middle mouse button in the text window and drag up\nor down. This will drag the text at high speed to allow you to scan its\ncontents.\n\n3. Insert text. Press mouse button 1 to set the insertion cursor, then\ntype text.  What you type will be added to the widget.\n\n4. Select. Press mouse button 1 and drag to select a range of characters.\nOnce you've released the button, you can adjust the selection by pressing\nbutton 1 with the shift key down.  This will reset the end of the\nselection nearest the mouse cursor and you can drag that end of the\nselection by dragging the mouse before releasing the mouse button.\nYou can double-click to select whole words or triple-click to select\nwhole lines.\n\n5. Delete and replace. To delete text, select the characters you'd like\nto delete and type Backspace or Delete.  Alternatively, you can type new\ntext, in which case it will replace the selected text.\n\n6. Copy the selection. To copy the selection into this window, select\nwhat you want to copy (either here or in another application), then\nclick the middle mouse button to copy the selection to the point of the\nmouse cursor.\n\n7. Edit.  Text widgets support the standard Motif editing characters\nplus many Emacs editing characters.  Backspace and Control-h erase the\ncharacter to the left of the insertion cursor.  Delete and Control-d\nerase the character to the right of the insertion cursor.  Meta-backspace\ndeletes the word to the left of the insertion cursor, and Meta-d deletes\nthe word to the right of the insertion cursor.  Control-k deletes from\nthe insertion cursor to the end of the line, or it deletes the newline\ncharacter if that is the only thing left on the line.  Control-o opens\na new line by inserting a newline character to the right of the insertion\ncursor.  Control-t transposes the two characters on either side of the\ninsertion cursor.  Control-z undoes the last editing action performed,\nand }\n\nswitch [tk windowingsystem] {\n    \"aqua\" - \"x11\" {\n\t$w.text insert end \"Control-Shift-z\"\n    }\n    \"win32\" {\n\t$w.text insert end \"Control-y\"\n    }\n}\n\n$w.text insert end { redoes undone edits.\n\n7. Resize the window.  This widget has been configured with the \"setGrid\"\noption on, so that if you resize the window it will always resize to an\neven number of characters high and wide.  Also, if you make the window\nnarrow you can see that long lines automatically wrap around onto\nadditional lines so that all the information is always visible.}\n$w.text mark set insert 0.0\n"
  },
  {
    "path": "library/demos/textpeer.tcl",
    "content": "# textpeer.tcl --\n#\n# This demonstration script creates a pair of text widgets that can edit a\n# single logical buffer. This is particularly useful when editing related text\n# in two (or more) parts of the same file.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .textpeer\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Widget Peering Demonstration\"\nwm iconname $w \"textpeer\"\npositionWindow $w\n\nset count 0\n\n## Define a widget that we peer from; it won't ever actually be shown though\nset first [text $w.text[incr count]]\n$first insert end \"This is a coupled pair of text widgets; they are peers to \"\n$first insert end \"each other. They have the same underlying data model, but \"\n$first insert end \"can show different locations, have different current edit \"\n$first insert end \"locations, and have different selections. You can also \"\n$first insert end \"create additional peers of any of these text widgets using \"\n$first insert end \"the Make Peer button beside the text widget to clone, and \"\n$first insert end \"delete a particular peer widget using the Delete Peer \"\n$first insert end \"button.\"\n\n## Procedures to make and kill clones; most of this is just so that the demo\n## looks nice...\nproc makeClone {w parent} {\n    global count\n    set t [$parent peer create $w.text[incr count] -yscroll \"$w.sb$count set\"\\\n\t\t  -height 10 -wrap word]\n    set sb [ttk::scrollbar $w.sb$count -command \"$t yview\" -orient vertical]\n    set b1 [button $w.clone$count -command \"makeClone $w $t\" \\\n\t\t    -text \"Make Peer\"]\n    set b2 [button $w.kill$count -command \"killClone $w $count\" \\\n\t\t    -text \"Delete Peer\"]\n    set row [expr {$count * 2}]\n    grid $t $sb $b1 -sticky nsew -row $row\n    grid ^  ^   $b2 -row [incr row]\n    grid configure $b1 $b2 -sticky new\n    grid rowconfigure $w $b2 -weight 1\n}\nproc killClone {w count} {\n    destroy $w.text$count $w.sb$count\n    destroy $w.clone$count $w.kill$count\n}\n\n## Now set up the GUI\nmakeClone $w $first\nmakeClone $w $first\ndestroy $first\n\n## See Code / Dismiss buttons\ngrid [addSeeDismiss $w.buttons $w] - - -sticky ew -row 5000\ngrid columnconfigure $w 0 -weight 1\n"
  },
  {
    "path": "library/demos/timer",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# timer --\n# This script generates a counter with start and stop buttons.\n\npackage require tk\n\nlabel .counter -text 0.00 -relief raised -width 10 -padx 2m -pady 1m\nbutton .start -text Start -command {\n    if {$stopped} {\n\tset stopped 0\n\tset startMoment [clock clicks -milliseconds]\n\ttick\n\t.stop configure -state normal\n\t.start configure -state disabled\n    }\n}\nbutton .stop -text Stop -state disabled -command {\n    set stopped 1\n    .stop configure -state disabled\n    .start configure -state normal\n}\npack .counter -side bottom -fill both\npack .start -side left -fill both -expand yes\npack .stop -side right -fill both -expand yes\n\nset startMoment {}\n\nset stopped 1\n\nproc tick {} {\n    global startMoment stopped\n    if {$stopped} {return}\n    after 50 tick\n    set elapsedMS [expr {[clock clicks -milliseconds] - $startMoment}]\n    .counter config -text [format \"%.2f\" [expr {double($elapsedMS)/1000}]]\n}\n\nbind . <Control-c> {destroy .}\nbind . <Control-q> {destroy .}\nfocus .\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/toolbar.tcl",
    "content": "# toolbar.tcl --\n#\n# This demonstration script creates a toolbar that can be torn off.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .toolbar\ndestroy $w\ntoplevel $w\nwm title $w \"Toolbar Demonstration\"\nwm iconname $w \"toolbar\"\npositionWindow $w\n\nttk::label $w.msg -wraplength 4i -text \"This is a demonstration of how to do\\\n\ta toolbar that is styled correctly and which can be torn off. The\\\n\tbuttons are configured to be “toolbar style” buttons by\\\n\ttelling them that they are to use the Toolbutton style. At the left\\\n\tend of the toolbar is a simple marker that the cursor changes to a\\\n\tmovement icon over; drag that away from the toolbar to tear off the\\\n\twhole toolbar into a separate toplevel widget. When the dragged-off\\\n\ttoolbar is no longer needed, just close it like any normal toplevel\\\n\tand it will reattach to the window it was torn off from.\"\n\n## Set up the toolbar hull\nset t [frame $w.toolbar]\t\t;# Must be a frame!\nttk::separator $w.sep\nttk::frame $t.tearoff -cursor fleur\nttk::separator $t.tearoff.to -orient vertical\nttk::separator $t.tearoff.to2 -orient vertical\npack $t.tearoff.to -fill y -expand 1 -padx 3p -side left\npack $t.tearoff.to2 -fill y -expand 1 -side left\nttk::frame $t.contents\ngrid $t.tearoff $t.contents -sticky nsew\ngrid columnconfigure $t $t.contents -weight 1\ngrid columnconfigure $t.contents 1000 -weight 1\n\n## Bindings so that the toolbar can be torn off and reattached\nbind $t.tearoff     <B1-Motion> [list tearoff $t %X %Y]\nbind $t.tearoff.to  <B1-Motion> [list tearoff $t %X %Y]\nbind $t.tearoff.to2 <B1-Motion> [list tearoff $t %X %Y]\nproc tearoff {w x y} {\n    if {[string match $w* [winfo containing $x $y]]} {\n\treturn\n    }\n    grid remove $w\n    grid remove $w.tearoff\n    wm manage $w\n    wm protocol $w WM_DELETE_WINDOW [list untearoff $w]\n}\nproc untearoff {w} {\n    wm forget $w\n    grid $w.tearoff\n    grid $w\n}\n\n## Toolbar contents\nttk::button $t.button -text \"Button\" -style Toolbutton -command [list \\\n\t$w.txt insert end \"Button Pressed\\n\"]\nttk::checkbutton $t.check -text \"Check\" -variable check -style Toolbutton \\\n\t-command [concat [list $w.txt insert end] {\"check is $check\\n\"}]\nttk::menubutton $t.menu -text \"Menu\" -menu $t.menu.m\nttk::combobox $t.combo -value [lsort [font families]] -state readonly\nmenu $t.menu.m\n$t.menu.m add command -label \"Just\" -command [list $w.txt insert end Just\\n]\n$t.menu.m add command -label \"An\" -command [list $w.txt insert end An\\n]\n$t.menu.m add command -label \"Example\" \\\n\t-command [list $w.txt insert end Example\\n]\nbind $t.combo <<ComboboxSelected>> [list changeFont $w.txt $t.combo]\nproc changeFont {txt combo} {\n    $txt configure -font [list [$combo get] 10]\n}\n\n## Some content for the rest of the toplevel\ntext $w.txt -width 40 -height 10\ninterp alias {} doInsert {} $w.txt insert end\t;# Make bindings easy to write\n\n## Arrange contents\ngrid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 1.5p -pady 3p -sticky ns\ngrid $t -sticky ew\ngrid $w.sep -sticky ew\ngrid $w.msg -sticky ew\ngrid $w.txt -sticky nsew\ngrid rowconfigure $w $w.txt -weight 1\ngrid columnconfigure $w $w.txt -weight 1\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\ngrid $btns -sticky ew\n"
  },
  {
    "path": "library/demos/tree.tcl",
    "content": "# tree.tcl --\n#\n# This demonstration script creates a toplevel window containing a Ttk\n# tree widget.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .tree\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Directory Browser\"\nwm iconname $w \"tree\"\npositionWindow $w\n\n## Explanatory text\nttk::label $w.msg -font $font -wraplength 4i -justify left -anchor n -padding {10 2 10 6} -text \"Ttk is the new Tk themed widget set. One of the widgets it includes is a tree widget, which allows the user to browse a hierarchical data-set such as a filesystem. The tree widget not only allows for the tree part itself, but it also supports an arbitrary number of additional columns which can show additional data (in this case, the size of the files found in your filesystem). You can also change the width of the columns by dragging the boundary between them.\"\npack $w.msg -fill x\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x\n\n## Code to populate the roots of the tree (can be more than one on Windows)\nproc populateRoots {tree} {\n    foreach dir [lsort -dictionary [file volumes]] {\n\tpopulateTree $tree [$tree insert {} end -text $dir \\\n\t\t-image [tk fileicon [file normalize $dir] 16] \\\n\t\t-values [list $dir directory]]\n    }\n}\n\n## Code to populate a node of the tree\nproc populateTree {tree node} {\n    if {[$tree set $node type] ne \"directory\"} {\n\treturn\n    }\n    set path [$tree set $node fullpath]\n    $tree delete [$tree children $node]\n    foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] {\n\tset f [file normalize $f]\n\tset type [file type $f]\n\tset id [$tree insert $node end -text [file tail $f] \\\n\t\t-image [tk fileicon $f 16] \\\n\t\t-values [list $f $type]]\n\n\tif {$type eq \"directory\"} {\n\t    if {[file readable $f]} {\n\t\t## Make it so that this node is openable\n\t\t$tree insert $id 0 -text dummy ;# a dummy\n\t    }\n\t    $tree item $id -text [file tail $f]/\n\n\t} elseif {$type eq \"file\"} {\n\t    set size [file size $f]\n\t    ## Format the file size nicely\n\t    if {$size >= 1024*1024*1024} {\n\t\tset size [format %.1f\\ GB [expr {$size/1024/1024/1024.}]]\n\t    } elseif {$size >= 1024*1024} {\n\t\tset size [format %.1f\\ MB [expr {$size/1024/1024.}]]\n\t    } elseif {$size >= 1024} {\n\t\tset size [format %.1f\\ kB [expr {$size/1024.}]]\n\t    } else {\n\t\tappend size \" bytes\"\n\t    }\n\t    $tree set $id size $size\n\t}\n    }\n\n    # Stop this code from rerunning on the current node\n    $tree set $node type processedDirectory\n}\n\n## Create the tree and set it up\nttk::treeview $w.tree -columns {fullpath type size} -displaycolumns {size} \\\n\t-yscroll \"$w.vsb set\" -xscroll \"$w.hsb set\"\nttk::scrollbar $w.vsb -orient vertical -command \"$w.tree yview\"\nttk::scrollbar $w.hsb -orient horizontal -command \"$w.tree xview\"\n$w.tree heading \\#0 -text \"Directory Structure\"\n$w.tree heading size -text \"File Size\"\n$w.tree column size -width 70\npopulateRoots $w.tree\nbind $w.tree <<TreeviewOpen>> {populateTree %W [%W focus]}\n\n## Arrange the tree and its scrollbars in the toplevel\nlower [ttk::frame $w.dummy]\npack $w.dummy -fill both -expand 1\ngrid $w.tree $w.vsb -sticky nsew -in $w.dummy\ngrid $w.hsb -sticky nsew -in $w.dummy\ngrid columnconfigure $w.dummy 0 -weight 1\ngrid rowconfigure $w.dummy 0 -weight 1\n"
  },
  {
    "path": "library/demos/ttkbut.tcl",
    "content": "# ttkbut.tcl --\n#\n# This demonstration script creates a toplevel window containing several\n# simple Ttk widgets, such as labels, labelframes, buttons, checkbuttons,\n# radiobuttons, a separator and a toggleswitch.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkbut\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Simple Ttk Widgets\"\nwm iconname $w \"ttkbut\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 4i -justify left -text \"Ttk is the new Tk themed widget set. This is a Ttk themed label, and below are four groups of Ttk widgets in Ttk labelframes. The first group are all buttons that set the current application theme when pressed. The second group contains two sets of checkbuttons, with a separator widget between the sets. The third group has a collection of linked radiobuttons. Finally, the toggleswitch in the fourth labelframe controls whether all the themed widgets in this toplevel, except that labelframe and its children, are in the disabled state.\"\npack $w.msg -side top -fill x\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happiness}]\\\n\t-side bottom -fill x\n\n## Add buttons for setting the theme\nttk::labelframe $w.buttons -text \"Buttons\"\nforeach theme [lsort [ttk::themes]] {\n    ttk::button $w.buttons.$theme -text $theme \\\n\t    -command [list ttk::setTheme $theme]\n    pack $w.buttons.$theme -pady 1.5p\n}\n\n## Set up the checkbutton group\nttk::labelframe $w.checks -text \"Checkbuttons\"\nttk::checkbutton $w.checks.c1 -text Cheese  -variable cheese\nttk::checkbutton $w.checks.c2 -text Tomato  -variable tomato\nttk::separator   $w.checks.sep\nttk::checkbutton $w.checks.c3 -text Basil   -variable basil\nttk::checkbutton $w.checks.c4 -text Oregano -variable oregano\n### pack $w.checks.e $w.checks.sep1 $w.checks.c1 $w.checks.c2 $w.checks.sep2 \\\n\t$w.checks.c3 $w.checks.c4   -fill x -pady 1.5p\npack $w.checks.c1 $w.checks.c2 $w.checks.sep $w.checks.c3 $w.checks.c4 \\\n\t-fill x -pady 1.5p\n\n## Set up the radiobutton group\nttk::labelframe $w.radios -text \"Radiobuttons\"\nttk::radiobutton $w.radios.r1 -text \"Great\" -variable happiness -value great\nttk::radiobutton $w.radios.r2 -text \"Good\" -variable happiness -value good\nttk::radiobutton $w.radios.r3 -text \"OK\" -variable happiness -value ok\nttk::radiobutton $w.radios.r4 -text \"Poor\" -variable happiness -value poor\nttk::radiobutton $w.radios.r5 -text \"Awful\" -variable happiness -value awful\npack $w.radios.r1 $w.radios.r2 $w.radios.r3 $w.radios.r4 $w.radios.r5 \\\n\t-fill x -padx 3p -pady 1.5p\n\n## Helper procedure for the toggleswitch\nproc setState {rootWidget exceptThese value} {\n    if {$rootWidget in $exceptThese} {\n\treturn\n    }\n    ## Non-Ttk widgets (e.g. the toplevel) will fail, so make it silent\n    catch {\n\t$rootWidget state $value\n    }\n    ## Recursively invoke on all children of this root that are in the same\n    ## toplevel widget\n    foreach w [winfo children $rootWidget] {\n\tif {[winfo toplevel $w] eq [winfo toplevel $rootWidget]} {\n\t    setState $w $exceptThese $value\n\t}\n    }\n}\n\n## Set up the labelframe containing a label and a toggleswitch\nttk::labelframe $w.toggle -text Toggleswitch\nttk::label $w.toggle.l -text \"Enable/disable widgets\"\nttk::toggleswitch $w.toggle.sw -variable enabled -command {\n    setState $w [list $w.toggle $w.toggle.l $w.toggle.sw] \\\n\t    [expr {$enabled ? \"!disabled\" : \"disabled\"}]\n}\nset enabled 1\n## See ttk_widget(n) for other possible state flags\npack $w.toggle.sw -side right -padx 3p -pady 1.5p\npack $w.toggle.l -side left -padx 3p -pady 1.5p\n\n## Arrange things neatly\npack [ttk::frame $w.f] -fill both -expand 1\nlower $w.f\ngrid $w.buttons $w.checks $w.radios -in $w.f -sticky nwe -pady 1.5p -padx 3p\ngrid $w.toggle -in $w.f -column 1 -columnspan 2 -sticky nwe -pady 1.5p -padx 3p\ngrid configure $w.buttons -rowspan 2\ngrid columnconfigure $w.f {0 1 2} -weight 1 -uniform yes\ngrid rowconfigure $w.f 1 -weight 1\n"
  },
  {
    "path": "library/demos/ttkmenu.tcl",
    "content": "# ttkmenu.tcl --\n#\n# This demonstration script creates a toplevel window containing several Ttk\n# menubutton widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkmenu\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Ttk Menu Buttons\"\nwm iconname $w \"ttkmenu\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 4i -justify left -text \"Ttk is the new Tk themed widget set, and one widget that is available in themed form is the menubutton. Below are some themed menu buttons that allow you to pick the current theme in use. Notice how picking a theme changes the way that the menu buttons themselves look, and that the central menu button is styled differently (in a way that is normally suitable for toolbars). However, there are no themed menus; the standard Tk menus were judged to have a sufficiently good look-and-feel on all platforms, especially as they are implemented as native controls in many places.\"\npack $w.msg [ttk::separator $w.msgSep] -side top -fill x\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x\n\nttk::menubutton $w.m1 -menu $w.m1.menu -text \"Select a theme\" -direction above\nttk::menubutton $w.m2 -menu $w.m1.menu -text \"Select a theme\" -direction left\nttk::menubutton $w.m3 -menu $w.m1.menu -text \"Select a theme\" -direction right\nttk::menubutton $w.m4 -menu $w.m1.menu -text \"Select a theme\" \\\n\t-direction flush -style TMenubutton.Toolbutton\nttk::menubutton $w.m5 -menu $w.m1.menu -text \"Select a theme\" -direction below\n\nmenu $w.m1.menu -tearoff 0\nmenu $w.m2.menu -tearoff 0\nmenu $w.m3.menu -tearoff 0\nmenu $w.m4.menu -tearoff 0\nmenu $w.m5.menu -tearoff 0\n\nforeach theme [lsort [ttk::themes]] {\n    $w.m1.menu add command -label $theme -command [list ttk::setTheme $theme]\n    $w.m2.menu add command -label $theme -command [list ttk::setTheme $theme]\n    $w.m3.menu add command -label $theme -command [list ttk::setTheme $theme]\n    $w.m4.menu add command -label $theme -command [list ttk::setTheme $theme]\n    $w.m5.menu add command -label $theme -command [list ttk::setTheme $theme]\n}\n\npack [ttk::frame $w.f] -fill x\npack [ttk::frame $w.f1] -fill both -expand yes\nlower $w.f\n\ngrid anchor $w.f center\ngrid   x   $w.m1   x    -in $w.f -padx 2.25p -pady 1.5p\ngrid $w.m2 $w.m4 $w.m3  -in $w.f -padx 2.25p -pady 1.5p\ngrid   x   $w.m5   x    -in $w.f -padx 2.25p -pady 1.5p\n"
  },
  {
    "path": "library/demos/ttknote.tcl",
    "content": "# ttknote.tcl --\n#\n# This demonstration script creates a toplevel window containing a Ttk\n# notebook widget.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttknote\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Ttk Notebook Widget\"\nwm iconname $w \"ttknote\"\npositionWindow $w\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x\n\nttk::frame $w.f\npack $w.f -fill both -expand 1\nset w $w.f\n\n## Make the notebook and set up Ctrl+Tab traversal\nttk::notebook $w.note\npack $w.note -fill both -expand 1 -padx 1.5p -pady 3p\nttk::notebook::enableTraversal $w.note\n\n## Popuplate the first pane\nttk::frame $w.note.msg\nttk::label $w.note.msg.m -font $font -wraplength 4i -justify left -anchor n -text \"Ttk is the new Tk themed widget set. One of the widgets it includes is the notebook widget, which provides a set of tabs that allow the selection of a group of panels, each with distinct content. They are a feature of many modern user interfaces. Not only can the tabs be selected with the mouse, but they can also be switched between using Ctrl+Tab when the notebook page heading itself is selected. Note that the second tab is disabled, and cannot be selected.\"\nttk::button $w.note.msg.b -text \"Neat!\" -underline 0 -command {\n    set neat \"Yeah, I know...\"\n    after 500 {set neat {}}\n}\nbind $w <Alt-n> \"focus $w.note.msg.b; $w.note.msg.b invoke\"\nttk::label $w.note.msg.l -textvariable neat\n$w.note add $w.note.msg -text \"Description\" -underline 0 -padding 1.5p\ngrid $w.note.msg.m - -sticky new -pady 1.5p\ngrid $w.note.msg.b $w.note.msg.l -pady {1.5p 3p}\ngrid rowconfigure $w.note.msg 1 -weight 1\ngrid columnconfigure $w.note.msg {0 1} -weight 1 -uniform 1\n\n## Populate the second pane. Note that the content doesn't really matter\nttk::frame $w.note.disabled\n$w.note add $w.note.disabled -text \"Disabled\" -state disabled\n\n## Popuplate the third pane\nttk::frame $w.note.editor\n$w.note add $w.note.editor -text \"Text Editor\" -underline 0\ntext $w.note.editor.t -width 40 -height 10 -wrap char \\\n\t-yscroll \"$w.note.editor.s set\"\nttk::scrollbar $w.note.editor.s -orient vertical -command \"$w.note.editor.t yview\"\npack $w.note.editor.s -side right -fill y -padx {0 1.5p} -pady 1.5p\npack $w.note.editor.t -fill both -expand 1 -pady 1.5p -padx {1.5p 0}\n"
  },
  {
    "path": "library/demos/ttkpane.tcl",
    "content": "# ttkpane.tcl --\n#\n# This demonstration script creates a Ttk pane with some content.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkpane\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Themed Nested Panes\"\nwm iconname $w \"ttkpane\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 4i -justify left -text \"This demonstration shows off a nested set of themed paned windows. Their sizes can be changed by grabbing the area between each contained pane and dragging the divider.\"\npack $w.msg [ttk::separator $w.msgSep] -side top -fill x\n\n## See Code / Dismiss\npack [addSeeDismiss $w.seeDismiss $w] -side bottom -fill x\n\nttk::frame $w.f\npack $w.f -fill both -expand 1\nset w $w.f\nttk::panedwindow $w.outer -orient horizontal\n$w.outer add [ttk::panedwindow $w.outer.inLeft -orient vertical]\n$w.outer add [ttk::panedwindow $w.outer.inRight -orient vertical]\n$w.outer.inLeft  add [ttk::labelframe $w.outer.inLeft.top  -text Button]\n$w.outer.inLeft  add [ttk::labelframe $w.outer.inLeft.bot  -text Clocks]\n$w.outer.inRight add [ttk::labelframe $w.outer.inRight.top -text Progress]\n$w.outer.inRight add [ttk::labelframe $w.outer.inRight.bot -text Text]\nif {[tk windowingsystem] eq \"aqua\"} {\n    foreach i [list inLeft.top inLeft.bot inRight.top inRight.bot] {\n\t$w.outer.$i configure -padding 3\n    }\n}\n\n# Fill the button pane\nttk::button $w.outer.inLeft.top.b -text \"Press Me\" -command {\n    tk_messageBox -type ok -icon info -message \"Ouch!\" -detail \"That hurt...\" \\\n\t    -parent .ttkpane -title \"Button Pressed\"\n}\npack $w.outer.inLeft.top.b -padx 1.5p -pady 3p\n\n# Fill the clocks pane\nset i 0\nproc every {delay script} {\n    uplevel #0 $script\n    after $delay [list every $delay $script]\n}\nset testzones {\n    :Europe/Berlin\n    :America/Argentina/Buenos_Aires\n    :Africa/Johannesburg\n    :Europe/London\n    :America/Los_Angeles\n    :Europe/Moscow\n    :America/New_York\n    :Asia/Singapore\n    :Australia/Sydney\n    :Asia/Tokyo\n}\n# Force a pre-load of all the timezones needed; otherwise can end up\n# poor-looking synch problems!\nset zones {}\nforeach zone $testzones {\n    if {![catch {clock format 0 -timezone $zone}]} {\n\tlappend zones $zone\n    }\n}\nif {[llength $zones] < 2} { lappend zones -0200 :GMT :UTC +0200 }\nforeach zone $zones {\n    set city [string map {_ \" \"} [regexp -inline {[^/]+$} $zone]]\n    if {$i} {\n\tpack [ttk::separator $w.outer.inLeft.bot.s$i] -fill x\n    }\n    ttk::label $w.outer.inLeft.bot.l$i -text $city -anchor w\n    ttk::label $w.outer.inLeft.bot.t$i -textvariable time($zone) -anchor w\n    pack $w.outer.inLeft.bot.l$i $w.outer.inLeft.bot.t$i -fill x\n    every 1000 \"set time($zone) \\[clock format \\[clock seconds\\] -timezone $zone -format %T\\]\"\n    incr i\n}\n\n# Fill the progress pane\nttk::progressbar $w.outer.inRight.top.progress -mode indeterminate\npack $w.outer.inRight.top.progress -fill both -expand 1\n$w.outer.inRight.top.progress start\n\n# Fill the text pane\nif {[tk windowingsystem] ne \"aqua\"} {\n    # The trick with the ttk::frame makes the text widget look like it fits with\n    # the current Ttk theme despite not being a themed widget itself. It is done\n    # by styling the frame like an entry, turning off the border in the text\n    # widget, and putting the text widget in the frame with enough space to allow\n    # the surrounding border to show through (2 pixels seems to be enough).\n    ttk::frame $w.outer.inRight.bot.f\t\t\t\t-style TEntry\n    text $w.txt -wrap word -yscroll \"$w.sb set\" -width 30\t-borderwidth 0\n    pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot.f\t-pady 1.5p -padx 1.5p\n    ttk::scrollbar $w.sb -orient vertical -command \"$w.txt yview\"\n    pack $w.sb -side right -fill y -in $w.outer.inRight.bot\n    pack $w.outer.inRight.bot.f -fill both -expand 1\n    pack $w.outer -fill both -expand 1\n} else {\n    text $w.txt -wrap word -yscroll \"$w.sb set\" -width 30 -borderwidth 0\n    ttk::scrollbar $w.sb -orient vertical -command \"$w.txt yview\"\n    pack $w.sb -side right -fill y -in $w.outer.inRight.bot\n    pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot\n    pack $w.outer -fill both -expand 1 -padx 10 -pady {6 10}\n}\n\n"
  },
  {
    "path": "library/demos/ttkprogress.tcl",
    "content": "# ttkprogress.tcl --\n#\n# This demonstration script creates several progress bar widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkprogress\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Progress Bar Demonstration\"\nwm iconname $w \"ttkprogress\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 4i -justify left -text \"Below are two progress bars. The top one is a “determinate” progress bar, which is used for showing how far through a defined task the program has got. The bottom one is an “indeterminate” progress bar, which is used to show that the program is busy but does not know how long for. Both are run here in self-animated mode, which can be turned on and off using the buttons underneath.\"\npack $w.msg -side top -fill x\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nttk::frame $w.f\npack $w.f -fill both -expand 1\nset w $w.f\n\nproc doBars {op args} {\n    foreach w $args {\n\t$w $op\n    }\n}\nttk::progressbar $w.p1 -mode determinate\nttk::progressbar $w.p2 -mode indeterminate\nttk::button $w.start -text \"Start Progress\" -command [list \\\n\tdoBars start $w.p1 $w.p2]\nttk::button $w.stop -text \"Stop Progress\" -command [list \\\n\tdoBars stop $w.p1 $w.p2]\n\ngrid $w.p1 - -pady 3p -padx 7.5p\ngrid $w.p2 - -pady 3p -padx 7.5p\ngrid $w.start $w.stop -padx 7.5p -pady 3p\ngrid configure $w.start -sticky e\ngrid configure $w.stop -sticky w\ngrid columnconfigure $w all -weight 1\n"
  },
  {
    "path": "library/demos/ttkscale.tcl",
    "content": "# ttkscale.tcl --\n#\n# This demonstration script shows an example with a horizontal scale.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkscale\ncatch {destroy $w}\ntoplevel $w -bg [ttk::style lookup TLabel -background]\nwm title $w \"Themed Scale Demonstration\"\nwm iconname $w \"ttkscale\"\npositionWindow $w\n\npack [ttk::frame [set w $w.contents]] -fill both -expand 1\n\nttk::label $w.msg -font $font -wraplength 3.5i -justify left -text \"A label tied to a horizontal scale is displayed below.  If you click or drag mouse button 1 in the scale, you can change the contents of the label; a callback command is used to couple the slider to both the text and the coloring of the label.\"\npack $w.msg -side top -padx .5c\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons [winfo toplevel $w]]\npack $btns -side bottom -fill x\n\nttk::frame $w.frame -borderwidth 7.5p\npack $w.frame -side top -fill x\n\n# List of colors from rainbow; \"Indigo\" is not a standard color\nset colorList {Red Orange Yellow Green Blue Violet}\nttk::label $w.frame.label\nttk::scale $w.frame.scale -from 0 -to 5 -command [list apply {{w idx} {\n    set c [lindex $::colorList [tcl::mathfunc::int $idx]]\n    $w.frame.label configure -foreground $c -text \"Color: $c\"\n}} $w]\n# Trigger the setting of the label's text\n$w.frame.scale set 0\npack $w.frame.label $w.frame.scale\n"
  },
  {
    "path": "library/demos/ttkspin.tcl",
    "content": "# ttkspin.tcl --\n#\n# This demonstration script creates several Ttk spinbox widgets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .ttkspin\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Themed Spinbox Demonstration\"\nwm iconname $w \"ttkspin\"\npositionWindow $w\n\nttk::label $w.msg -font $font -wraplength 5i -justify left -text \"Three different\\\n\tthemed spin-boxes are displayed below.  You can add characters by\\\n\tpointing, clicking and typing.  The normal Motif editing characters\\\n\tare supported, along with many Emacs bindings.  For example, Backspace\\\n\tand Control-h delete the character to the left of the insertion\\\n\tcursor and Delete and Control-d delete the chararacter to the right\\\n\tof the insertion cursor.  For values that are too large to fit in the\\\n\twindow all at once, you can scan through the value by dragging with\\\n\tmouse button2 pressed.  Note that the first spin-box will only permit\\\n\tyou to type in integers, and the third selects from a list of\\\n\tAustralian cities.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nttk::frame $w.f\npack $w.f -fill both -expand 1\nset w $w.f\n\nset australianCities {\n    Canberra Sydney Melbourne Perth Adelaide Brisbane\n    Hobart Darwin \"Alice Springs\"\n}\n\nttk::spinbox $w.s1 -from 1 -to 10 -width 10 -validate key \\\n\t-validatecommand {string is integer %P}\nttk::spinbox $w.s2 -from 0 -to 3 -increment .5 -format %05.2f -width 10\nttk::spinbox $w.s3 -values $australianCities -width 10\n\n$w.s1 set 1\n$w.s2 set 00.00\n$w.s3 set Canberra\n\npack $w.s1 $w.s2 $w.s3 -side top -pady 3p -padx 7.5p\n"
  },
  {
    "path": "library/demos/twind.tcl",
    "content": "# twind.tcl --\n#\n# This demonstration script creates a text widget with a bunch of\n# embedded windows.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\n# Make an Aqua button's fill color match its parent's background\nproc blend {bt} {\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t$bt configure -highlightbackground [[winfo parent $bt] cget -background]\n    }\n    return $bt\n}\n\nset w .twind\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Text Demonstration - Embedded Windows and Other Features\"\nwm iconname $w \"Embedded Windows\"\npositionWindow $w\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.f -highlightthickness 1 -borderwidth 1 -relief sunken\nset t $w.f.text\ntext $t -yscrollcommand \"$w.scroll set\" -font $font -width 70 \\\n\t-height 35 -wrap word -highlightthickness 0 -borderwidth 0\npack $t -expand  yes -fill both\nttk::scrollbar $w.scroll -command \"$t yview\"\npack $w.scroll -side right -fill y\npanedwindow $w.pane\npack $w.pane -expand yes -fill both\n$w.pane add $w.f -stretch always\n# Import to raise given creation order above\nraise $w.f\n\n$t tag configure center -justify center -spacing1 5m -spacing3 5m\n$t tag configure buttons -lmargin1 1c -lmargin2 1c -rmargin 1c \\\n\t-spacing1 3m -spacing2 0 -spacing3 0\n\nbutton $t.on -text \"Turn On\" -command \"textWindOn $w\" \\\n\t-cursor top_left_arrow\nbutton $t.off -text \"Turn Off\" -command \"textWindOff $w\" \\\n\t-cursor top_left_arrow\n\n$t insert end \"A text widget can contain many different kinds of items, \"\n$t insert end \"both active and passive.  It can lay these out in various \"\n$t insert end \"ways, with wrapping, tabs, centering, etc.  In addition, \"\n$t insert end \"when the contents are too big for the window, smooth \"\n$t insert end \"scrolling in all directions is provided.\\n\\n\"\n\n$t insert end \"A text widget can contain other widgets embedded \"\n$t insert end \"it.  These are called \\\"embedded windows\\\", \"\n$t insert end \"and they can consist of arbitrary widgets.  \"\n$t insert end \"For example, here are two embedded button \"\n$t insert end \"widgets.  You can click on the first button to \"\n$t window create end -window [blend $t.on]\n$t insert end \" horizontal scrolling, which also turns off \"\n$t insert end \"word wrapping.  Or, you can click on the second \"\n$t insert end \"button to\\n\"\n$t window create end -window [blend $t.off]\n$t insert end \" horizontal scrolling and turn back on word wrapping.\\n\\n\"\n\n$t insert end \"Or, here is another example.  If you \"\n$t window create end -create {\n    button %W.click -text \"Click Here\" -command \"textWindPlot %W\" \\\n\t-cursor top_left_arrow\n    blend %W.click\n}\n\n$t insert end \" a canvas displaying an x-y plot will appear right here.\"\n$t mark set plot insert\n$t mark gravity plot left\n$t insert end \"  You can drag the data points around with the mouse, \"\n$t insert end \"or you can click here to \"\n$t window create end -create {\n    button %W.delete -text \"Delete\" -command \"textWindDel %W\" \\\n\t-cursor top_left_arrow\n    blend %W.delete\n}\n$t insert end \" the plot again.\\n\\n\"\n\n$t insert end \"You can also create multiple text widgets each of which \"\n$t insert end \"display the same underlying text. Click this button to \"\n$t window create end \\\n  -create {button %W.peer -text \"Make A Peer\" -command \"textMakePeer %W\" \\\n\t       -cursor top_left_arrow\n      blend %W.peer} -padx 3p\n$t insert end \" widget.  Notice how peer widgets can have different \"\n$t insert end \"font settings, and by default contain all the images \"\n$t insert end \"of the 'parent', but that the embedded windows, \"\n$t insert end \"such as buttons may not appear in the peer.  To ensure \"\n$t insert end \"that embedded windows appear in all peers you can set the \"\n$t insert end \"'-create' option to a script or a string containing %W.  \"\n$t insert end \"(The plot above and the 'Make A Peer' button are \"\n$t insert end \"designed to show up in all peers.)  A good use of \"\n$t insert end \"peers is for \"\n$t window create end \\\n  -create {button %W.split -text \"Split Windows\" -command \"textSplitWindow %W\" \\\n\t       -cursor top_left_arrow\n      blend %W.split} -padx 3p\n$t insert end \" \\n\\n\"\n\n$t insert end \"Users of previous versions of Tk will also be interested \"\n$t insert end \"to note that now cursor movement is now by visual line by \"\n$t insert end \"default, and that all scrolling of this widget is by pixel.\\n\\n\"\n\n$t insert end \"You may also find it useful to put embedded windows in \"\n$t insert end \"a text without any actual text.  In this case the \"\n$t insert end \"text widget acts like a geometry manager.  For \"\n$t insert end \"example, here is a collection of buttons laid out \"\n$t insert end \"neatly into rows by the text widget.  These buttons \"\n$t insert end \"can be used to change the background color of the \"\n$t insert end \"text widget (\\\"Default\\\" restores the color to \"\n$t insert end \"its default).  If you click on the button labeled \"\n$t insert end \"\\\"Short\\\", it changes to a longer string so that \"\n$t insert end \"you can see how the text widget automatically \"\n$t insert end \"changes the layout.  Click on the button again \"\n$t insert end \"to restore the short string.\\n\"\n\n$t insert end \"\\nNOTE: these buttons will not appear in peers!\\n\" \"peer_warning\"\nbutton $t.default -text Default -command \"embDefBg $t\" \\\n\t-cursor top_left_arrow\n$t window create end -window $t.default -padx 3p\nglobal embToggle\nset embToggle Short\ncheckbutton $t.toggle -textvariable embToggle -indicatoron 0 \\\n\t-variable embToggle -onvalue \"A much longer string\" \\\n\t-offvalue \"Short\" -cursor top_left_arrow -pady 3p -padx 1.5p\n$t window create end -window $t.toggle -padx 3p -pady 1.5p\nset i 1\nforeach color {AntiqueWhite3 Bisque1 Bisque2 Bisque3 Bisque4\n\tSlateBlue3 RoyalBlue1 SteelBlue2 DeepSkyBlue3 LightBlue1\n\tDarkSlateGray1 Aquamarine2 DarkSeaGreen2 SeaGreen1\n\tYellow1 IndianRed1 IndianRed2 Tan1 Tan4} {\n    button $t.color$i -text $color -cursor top_left_arrow -command \\\n\t    \"changeBg $t $color\"\n    $t window create end -window [blend $t.color$i] -padx 3p -pady 1.5p\n    incr i\n}\n$t tag add buttons [blend $t.default] end\n\nbutton $t.bigB -text \"Big borders\" -command \"textWindBigB $t\" \\\n  -cursor top_left_arrow\nbutton $t.smallB -text \"Small borders\" -command \"textWindSmallB $t\" \\\n  -cursor top_left_arrow\nbutton $t.bigH -text \"Big highlight\" -command \"textWindBigH $t\" \\\n  -cursor top_left_arrow\nbutton $t.smallH -text \"Small highlight\" -command \"textWindSmallH $t\" \\\n  -cursor top_left_arrow\nbutton $t.bigP -text \"Big pad\" -command \"textWindBigP $t\" \\\n  -cursor top_left_arrow\nbutton $t.smallP -text \"Small pad\" -command \"textWindSmallP $t\" \\\n  -cursor top_left_arrow\n\nset text_normal(border) [$t cget -borderwidth]\nset text_normal(highlight) [$t cget -highlightthickness]\nset text_normal(pad) [$t cget -padx]\n\n$t insert end \"\\nYou can also change the usual border width and \"\n$t insert end \"highlightthickness and padding.\\n\"\n$t window create end -window [blend $t.bigB]\n$t window create end -window [blend $t.smallB]\n$t window create end -window [blend $t.bigH]\n$t window create end -window [blend $t.smallH]\n$t window create end -window [blend $t.bigP]\n$t window create end -window [blend $t.smallP]\n\n$t insert end \"\\n\\nFinally, images fit comfortably in text widgets too:\"\n\nimage create photo img -file [file join $tk_demoDirectory images ouster.png]\n\n# Create a copy of the image just created, magnified according to the\n# display's DPI scaling level.  Since the zooom factor must be an integer,\n# the copy will only be effectively magnified if $tk::scalingPct >= 200.\nimage create photo img2\nimg2 copy img -zoom [expr {$tk::scalingPct / 100}]\n\n$t image create end -image img2\n\nproc textWindBigB w {\n    $w configure -borderwidth 12p\n}\n\nproc textWindBigH w {\n    $w configure -highlightthickness 12p\n}\n\nproc textWindBigP w {\n    $w configure -padx 12p -pady 12p\n}\n\nproc textWindSmallB w {\n    $w configure -borderwidth $::text_normal(border)\n}\n\nproc textWindSmallH w {\n    $w configure -highlightthickness $::text_normal(highlight)\n}\n\nproc textWindSmallP w {\n    $w configure -padx $::text_normal(pad) -pady $::text_normal(pad)\n}\n\nproc textWindOn w {\n    catch {destroy $w.scroll2}\n    set t $w.f.text\n    ttk::scrollbar $w.scroll2 -orient horizontal -command \"$t xview\"\n    pack $w.scroll2 -after $w.buttons -side bottom -fill x\n    $t configure -xscrollcommand \"$w.scroll2 set\" -wrap none\n}\n\nproc textWindOff w {\n    catch {destroy $w.scroll2}\n    set t $w.f.text\n    $t configure -xscrollcommand {} -wrap word\n}\n\nproc textWindPlot t {\n    set c $t.c\n    if {[winfo exists $c]} {\n\treturn\n    }\n\n    while {[string first [$t get plot] \" \\t\\n\"] >= 0} {\n\t$t delete plot\n    }\n    $t insert plot \"\\n\"\n\n    $t window create plot -create {createPlot %W}\n    $t tag add center plot\n    $t insert plot \"\\n\"\n}\n\nproc createPlot {t} {\n    set c $t.c\n\n    canvas $c -relief sunken -width 450 -height 300 -cursor top_left_arrow\n\n    set font {Helvetica 18}\n\n    $c create line 100 250 400 250 -width 2\n    $c create line 100 250 100 50 -width 2\n    $c create text 225 20 -text \"A Simple Plot\" -font $font -fill brown\n\n    for {set i 0} {$i <= 10} {incr i} {\n\tset x [expr {100 + ($i*30)}]\n\t$c create line $x 250 $x 245 -width 2\n\t$c create text $x 254 -text [expr {10*$i}] -anchor n -font $font\n    }\n    for {set i 0} {$i <= 5} {incr i} {\n\tset y [expr {250 - ($i*40)}]\n\t$c create line 100 $y 105 $y -width 2\n\t$c create text 96 $y -text [expr {$i*50}].0 -anchor e -font $font\n    }\n\n    foreach point {\n\t{12 56} {20 94} {33 98} {32 120} {61 180} {75 160} {98 223}\n    } {\n\tset x [expr {100 + (3*[lindex $point 0])}]\n\tset y [expr {250 - (4*[lindex $point 1])/5}]\n\tset item [$c create oval [expr {$x-6}] [expr {$y-6}] \\\n\t\t[expr {$x+6}] [expr {$y+6}] -width 1 -outline black \\\n\t\t-fill SkyBlue2]\n\t$c addtag point withtag $item\n    }\n\n    $c bind point <Enter> \"$c itemconfig current -fill red\"\n    $c bind point <Leave> \"$c itemconfig current -fill SkyBlue2\"\n    $c bind point <Button-1> \"embPlotDown $c %x %y\"\n    $c bind point <ButtonRelease-1> \"$c dtag selected\"\n    bind $c <B1-Motion> \"embPlotMove $c %x %y\"\n    return $c\n}\n\nset embPlot(lastX) 0\nset embPlot(lastY) 0\n\nproc embPlotDown {w x y} {\n    global embPlot\n    $w dtag selected\n    $w addtag selected withtag current\n    $w raise current\n    set embPlot(lastX) $x\n    set embPlot(lastY) $y\n}\n\nproc embPlotMove {w x y} {\n    global embPlot\n    $w move selected [expr {$x-$embPlot(lastX)}] [expr {$y-$embPlot(lastY)}]\n    set embPlot(lastX) $x\n    set embPlot(lastY) $y\n}\n\nproc textWindDel t {\n    if {[winfo exists $t.c]} {\n\t$t delete $t.c\n\twhile {[string first [$t get plot] \" \\t\\n\"] >= 0} {\n\t    $t delete plot\n\t}\n\t$t insert plot \"  \"\n    }\n}\n\nproc changeBg {t c} {\n    $t configure -background $c\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tforeach b [$t window names] {\n\t    if {[winfo class $b] eq \"Button\"} {\n\t\t$b configure -highlightbackground $c\n\t    }\n\t}\n    }\n}\n\nproc embDefBg t {\n    set bg [lindex [$t configure -background] 3]\n    changeBg $t $bg\n}\n\nproc textMakePeer {parent} {\n    set n 1\n    while {[winfo exists .peer$n]} { incr n }\n    set w [toplevel .peer$n]\n    wm title $w \"Text Peer #$n\"\n    frame $w.f -highlightthickness 1 -borderwidth 1 -relief sunken\n    set t [$parent peer create $w.f.text -yscrollcommand \"$w.scroll set\" \\\n\t       -borderwidth 0 -highlightthickness 0]\n    $t tag configure peer_warning -font boldFont\n    pack $t -expand  yes -fill both\n    ttk::scrollbar $w.scroll -command \"$t yview\"\n    pack $w.scroll -side right -fill y\n    pack $w.f -expand yes -fill both\n}\n\nproc textSplitWindow {textW} {\n    if {$textW eq \".twind.f.text\"} {\n\tif {[winfo exists .twind.peer]} {\n\t    destroy .twind.peer\n\t} else {\n\t    set parent [winfo parent $textW]\n\t    set w [winfo parent $parent]\n\t    set t [$textW peer create $w.peer \\\n\t      -yscrollcommand \"$w.scroll set\"]\n\t    $t tag configure peer_warning -font boldFont\n\t    $w.pane add $t -stretch always\n\t}\n    } else {\n\treturn\n    }\n}\n"
  },
  {
    "path": "library/demos/unicodeout.tcl",
    "content": "# unicodeout.tcl --\n#\n# This demonstration script shows how you can produce output (in label\n# widgets) using many different alphabets.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .unicodeout\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Unicode Label Demonstration\"\nwm iconname $w \"unicodeout\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 4i -anchor w -justify left \\\n\t-text \"This is a sample of Tk's support for languages that use\\\n\tnon-Western character sets.  However, what you will actually see\\\n\tbelow depends largely on what character sets you have installed,\\\n\tand what you see for characters that are not present varies greatly\\\n\tbetween platforms as well.\"\npack $w.msg -side top\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\n## The frame that will contain the sample texts.\npack [frame $w.f] -side bottom -expand 1 -fill both -padx 2m -pady 1m\ngrid columnconfigure $w.f 1 -weight 1\nset i 0\nproc addSample {w language args} {\n    global font i\n    set sample [join $args \"\"]\n    set j [incr i]\n    label $w.f.l$j -font $font -text \"${language}:\" -anchor nw -pady 0\n    label $w.f.s$j -font $font -text $sample -anchor nw -width 30 -pady 0\n    grid $w.f.l$j $w.f.s$j -sticky ew -pady 0\n    grid configure $w.f.l$j -padx 1m\n}\n\n## Processing when some characters are not currently cached by the display\n## engine might take a while, so make sure we're displaying something in the\n## meantime...\npack [label $w.wait -text \"Please wait while loading fonts...\" \\\n\t-font {Helvetica 12 italic}]\nset oldCursor [$w cget -cursor]\n$w conf -cursor watch\nupdate\n\n## Add the samples...\nif {[tk::build-info no-bidi]} {\n    # Using presentation forms (pre-layouted)\n    addSample $w Arabic \"ﺔﻴﺑﺮﻌﻟﺍ ﺔﻤﻠﻜﻟﺍ\"\n} else {\n    # Using standard text characters\naddSample $w Arabic \"الكلمة العربية\"\n}\naddSample $w \"Trad. Chinese\"  \"中國的漢字\"\naddSample $w \"Simpl. Chinese\" \"汉语\"\naddSample $w French \"Langue française\"\naddSample $w Greek \"Ελληνική γλώσσα\"\nif {[tk::build-info no-bidi]} {\n    # Visual order (pre-layouted)\n    addSample $w Hebrew \"תירבע בתכ\"\n} else {\n    # Standard logical order\naddSample $w Hebrew \"כתב עברית\"\n}\naddSample $w Hindi \"हिन्दी भाषा\"\naddSample $w Icelandic \"Íslenska\"\naddSample $w Japanese \"日本語のひらがな, 漢字とカタカナ\"\naddSample $w Korean \"대한민국의 한글\"\naddSample $w Russian \"Русский язык\"\nif {![tk::build-info no-xft]} {\n    addSample $w Emoji \"😀💩👍🇳🇱\"\n}\n\n## We're done processing, so change things back to normal running...\ndestroy $w.wait\n$w conf -cursor $oldCursor\n"
  },
  {
    "path": "library/demos/vscale.tcl",
    "content": "# vscale.tcl --\n#\n# This demonstration script shows an example with a vertical scale.\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\npackage require tk\n\nset w .vscale\ncatch {destroy $w}\ntoplevel $w\nwm title $w \"Vertical Scale Demonstration\"\nwm iconname $w \"vscale\"\npositionWindow $w\n\nlabel $w.msg -font $font -wraplength 3.5i -justify left -text \"An arrow and a vertical scale are displayed below.  If you click or drag mouse button 1 in the scale, you can change the size of the arrow.\"\npack $w.msg -side top -padx .5c\n\n## See Code / Dismiss buttons\nset btns [addSeeDismiss $w.buttons $w]\npack $btns -side bottom -fill x\n\nframe $w.frame -borderwidth 7.5p\npack $w.frame\n\nscale $w.frame.scale -orient vertical -length 213p -from 0 -to 250 \\\n\t-command \"setHeight $w.frame.canvas\" -tickinterval 50\ncanvas $w.frame.canvas -width 37.5p -height 37.5p -bd 0 -highlightthickness 0\n$w.frame.canvas create polygon 0 0 1 1 2 2 -fill SeaGreen3 -tags poly\n$w.frame.canvas create line 0 0 1 1 2 2 0 0 -fill black -tags line\nframe $w.frame.right -borderwidth 11.25p\npack $w.frame.scale -side left -anchor ne\npack $w.frame.canvas -side left -anchor nw -fill y\n$w.frame.scale set 75\n\nproc setHeight {w height} {\n    incr height 21\n    set y2 [expr {$height - 30}]\n    if {$y2 < 21} {\n\tset y2 21\n    }\n    $w coords poly 15 20 35 20 35 $y2 45 $y2 25 $height 5 $y2 15 $y2 15 20\n    $w coords line 15 20 35 20 35 $y2 45 $y2 25 $height 5 $y2 15 $y2 15 20\n\n    set scaleFactor [expr {$tk::scalingPct / 100.0}]\n    $w scale poly 0 0 $scaleFactor $scaleFactor\n    $w scale line 0 0 $scaleFactor $scaleFactor\n}\n"
  },
  {
    "path": "library/demos/widget",
    "content": "#!/bin/sh\n# the next line restarts using wish \\\nexec wish \"$0\" ${1+\"$@\"}\n\n# widget --\n# This script demonstrates the various widgets provided by Tk, along with many\n# of the features of the Tk toolkit. This file only contains code to generate\n# the main window for the application, which invokes individual\n# demonstrations. The code for the actual demonstrations is contained in\n# separate \".tcl\" files is this directory, which are sourced by this script as\n# needed.\n\npackage require tk\t9.0\npackage require msgcat\n\ndestroy {*}[winfo children .]\nset tk_demoDirectory [file join [pwd] [file dirname [info script]]]\n::msgcat::mcload $tk_demoDirectory\nnamespace import ::msgcat::mc\n\n# Divert to the accessible widget demo if screen reader is on.\nif {[info commands ::tk::accessible::check_screenreader] ne \"\"}  {\n\tif {[::tk::accessible::check_screenreader] eq \"1\"} {\n\t    source [file join $tk_demoDirectory accessiblewidget]\n\t}\n}\n\n\nwm title . [mc \"Widget Demonstration\"]\nif {[tk windowingsystem] eq \"x11\"} {\n    # This won't work everywhere, but there's no other way in core Tk at the\n    # moment to display a coloured icon.\n    image create photo TclPowered \\\n\t    -file [file join $tk_library images logo64.gif]\n    wm iconwindow . [toplevel ._iconWindow]\n    pack [label ._iconWindow.i -image TclPowered]\n    wm iconname . [mc \"tkWidgetDemo\"]\n}\n\nif {\"defaultFont\" ni [font names]} {\n    # TIP #145 defines some standard named fonts\n    if {\"TkDefaultFont\" in [font names] && \"TkFixedFont\" in [font names]} {\n\t# FIX ME: the following technique of cloning the font to copy it works\n\t#         fine but means that if the system font is changed by Tk\n\t#         cannot update the copied font. font alias might be useful\n\t#         here -- or fix the app to use TkDefaultFont etc.\n\tfont create mainFont   {*}[font configure TkDefaultFont]\n\tfont create fixedFont  {*}[font configure TkFixedFont]\n\tfont create boldFont   {*}[font configure TkDefaultFont] -weight bold\n\tfont create titleFont  {*}[font configure TkDefaultFont] -weight bold\n\tfont create statusFont {*}[font configure TkDefaultFont]\n\tfont create varsFont   {*}[font configure TkDefaultFont]\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    font configure titleFont -size 17\n\t}\n    } else {\n\tfont create mainFont   -family Helvetica -size 12\n\tfont create fixedFont  -family Courier   -size 10\n\tfont create boldFont   -family Helvetica -size 12 -weight bold\n\tfont create titleFont  -family Helvetica -size 18 -weight bold\n\tfont create statusFont -family Helvetica -size 10\n\tfont create varsFont   -family Helvetica -size 14\n    }\n}\n\nset widgetDemo 1\nset font mainFont\n\n# The SVG images used below are based on some icons provided by the\n# official open source SVG icon library for the Bootstrap project,\n# licensed under the MIT license (https://opensource.org/licenses/MIT).\n#\n# See https://github.com/twbs/icons.\n\nset viewData {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z\" fill=\"#000000\"/>\n    </svg>\n}\n\nset refreshData {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"M11 5.466V4H5a4 4 0 0 0-3.584 5.777.5.5 0 1 1-.896.446A5 5 0 0 1 5 3h6V1.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384l-2.36 1.966a.25.25 0 0 1-.41-.192Zm3.81.086a.5.5 0 0 1 .67.225A5 5 0 0 1 11 13H5v1.466a.25.25 0 0 1-.41.192l-2.36-1.966a.25.25 0 0 1 0-.384l2.36-1.966a.25.25 0 0 1 .41.192V12h6a4 4 0 0 0 3.585-5.777.5.5 0 0 1 .225-.67Z\" fill=\"#000000\"/>\n    </svg>\n}\n\nset printData {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"M2.5 8a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1z\" fill=\"#000000\"/>\n     <path d=\"M5 1a2 2 0 0 0-2 2v2H2a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h1v1a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-1h1a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-1V3a2 2 0 0 0-2-2H5zM4 3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2H4V3zm1 5a2 2 0 0 0-2 2v1H2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v-1a2 2 0 0 0-2-2H5zm7 2v3a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1z\" fill=\"#000000\"/>\n    </svg>\n}\n\nproc images {arg} {\n    set fgColor [ttk::style lookup . -foreground {} black]\n    lassign [winfo rgb . $fgColor] r g b\n    set fgColor [format \"#%02x%02x%02x\" \\\n\t    [expr {$r >> 8}] [expr {$g >> 8}] [expr {$b >> 8}]]\n\n    foreach action {view refresh print} {\n\tupvar ${action}Data imgData\n\tfor {set data $imgData; set startIdx 0} \\\n\t\t{[set idx1 [string first \"#000000\" $data $startIdx]] >= 0} \\\n\t\t{set startIdx [expr {$idx1 + 7}]} {\n\t    set idx2 [expr {$idx1 + 6}]\n\t    set data [string replace $data $idx1 $idx2 $fgColor]\n\t}\n\n\tswitch $arg {\n\t    create {\n\t\timage create photo ::img::$action -format $::tk::svgFmt \\\n\t\t\t-data $data\n\t    }\n\t    configure { ::img::$action configure -data $data }\n\t}\n    }\n}\n\nimages create\nset mainClass [winfo class .]\nforeach event {<<ThemeChanged>> <<LightAqua>> <<DarkAqua>>} {\n    bind $mainClass $event { images configure }\n}\nunset mainClass event\n\nimage create photo ::img::delete -format $::tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\" fill=\"#d00000\"/>\n    </svg>\n}\n\n#----------------------------------------------------------------\n# The code below creates the main window, consisting of a menu bar and a text\n# widget that explains how to use the program, plus lists all of the demos as\n# hypertext items.\n#----------------------------------------------------------------\n\nmenu .menuBar -tearoff 0\n\n# On Aqua, just use the default menu.\nif {[tk windowingsystem] ne \"aqua\"} {\n    # This is a tk-internal procedure to make i18n easier\n    ::tk::AmpMenuArgs .menuBar add cascade -label [mc \"&File\"] \\\n\t    -menu .menuBar.file\n    menu .menuBar.file -tearoff 0\n    ::tk::AmpMenuArgs .menuBar.file add command -label [mc \"&About...\"] \\\n\t    -command {tkAboutDialog} -accelerator [mc \"<F1>\"]\n    bind . <F1> {tkAboutDialog}\n    .menuBar.file add sep\n    if {[tk windowingsystem] eq \"win32\"} {\n\t# Windows doesn't usually have a Meta key\n\t::tk::AmpMenuArgs .menuBar.file add command -label [mc \"&Quit\"] \\\n\t\t-command {exit} -accelerator [mc \"Ctrl+Q\"]\n\tbind . <[mc \"Control-q\"]> {exit}\n    } else {\n\t::tk::AmpMenuArgs .menuBar.file add command -label [mc \"&Quit\"] \\\n\t\t-command {exit} -accelerator [mc \"Meta-Q\"]\n\tbind . <[mc \"Meta-q\"]> {exit}\n    }\n    . configure -menu .menuBar\n}\n\nttk::frame .statusBar\nttk::label .statusBar.lab -text \"   \" -anchor w\nif {[tk windowingsystem] eq \"aqua\"} {\n    ttk::separator .statusBar.sep\n    pack .statusBar.sep -side top -expand yes -fill x -pady 0\n}\npack .statusBar.lab -side left -padx 1.5p -expand yes -fill both\nif {[tk windowingsystem] ne \"aqua\"} {\n    ttk::sizegrip .statusBar.foo\n    pack .statusBar.foo -side left -padx 1.5p\n}\npack .statusBar -side bottom -fill x -pady 1.5p\n\nset textheight 30\ncatch {\n    set textheight [expr {\n\t([winfo screenheight .] * 0.7) /\n\t[font metrics mainFont -displayof . -linespace]\n    }]\n}\n\nttk::frame .textFrame\nttk::scrollbar .s -orient vertical -command {.t yview} -takefocus 1\npack .s -in .textFrame -side right -fill y\ntext .t -yscrollcommand {.s set} -wrap word -width 70 -height $textheight \\\n\t-font mainFont -setgrid 1 -highlightthickness 0 \\\n\t-padx 3p -pady 1.5p -takefocus 0\npack .t -in .textFrame -expand y -fill both -padx 1\npack .textFrame -expand yes -fill both\nif {[tk windowingsystem] eq \"aqua\"} {\n    pack configure .statusBar.lab -padx {10 18} -pady {4 6}\n    pack configure .statusBar -pady 0\n    .t configure -padx 10 -pady 0\n}\n\n# Create a bunch of tags to use in the text widget, such as those for section\n# titles and demo descriptions. Also define the bindings for tags.\n\n.t tag configure title -font titleFont\n.t tag configure subtitle -font titleFont\n.t tag configure bold  -font boldFont\nif {[tk windowingsystem] eq \"aqua\"} {\n    .t tag configure title -spacing1 8\n    .t tag configure subtitle -spacing3 3\n}\n\n# We put some \"space\" characters to the left and right of each demo\n# description so that the descriptions are highlighted only when the mouse\n# cursor is right over them (but not when the cursor is to their left or\n# right).\n#\n.t tag configure demospace -lmargin1 1c -lmargin2 1c\n\nif {[winfo depth .] == 1} {\n    .t tag configure demo -lmargin1 1c -lmargin2 1c \\\n\t-underline 1\n    .t tag configure visited -lmargin1 1c -lmargin2 1c \\\n\t-underline 1\n    .t tag configure hot -background black -foreground white\n} else {\n    .t tag configure demo -lmargin1 1c -lmargin2 1c \\\n\t-foreground blue -underline 1\n    .t tag configure visited -lmargin1 1c -lmargin2 1c \\\n\t-foreground #303080 -underline 1\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t.t tag configure demo -foreground systemLinkColor\n\t.t tag configure visited -foreground purple\n    }\n    .t tag configure hot -foreground red -underline 1\n}\n\n# The tag \"new\" must be the one having the highest priority.\n#\n.t tag configure new -foreground #c00000 -underline 0 -font boldFont\n\n.t tag bind demo <ButtonRelease-1> {\n    invoke [.t index {@%x,%y}]\n}\nset lastLine \"\"\n.t tag bind demo <Enter> {\n    set lastLine [.t index {@%x,%y linestart}]\n    .t tag add hot \"$lastLine +1 chars\" \"$lastLine lineend -1 chars\"\n    .t config -cursor [::ttk::cursor link]\n    showStatus [.t index {@%x,%y}]\n}\n.t tag bind demo <Leave> {\n    .t tag remove hot 1.0 end\n    .t config -cursor [::ttk::cursor text]\n    .statusBar.lab config -text \"\"\n}\n.t tag bind demo <Motion> {\n    set newLine [.t index {@%x,%y linestart}]\n    if {$newLine ne $lastLine} {\n\t.t tag remove hot 1.0 end\n\tset lastLine $newLine\n\n\tset tags [.t tag names {@%x,%y}]\n\tset i [lsearch -glob $tags demo-*]\n\tif {$i >= 0} {\n\t    .t tag add hot \"$lastLine +1 chars\" \"$lastLine lineend -1 chars\"\n\t}\n    }\n    showStatus [.t index {@%x,%y}]\n}\n\f\n##############################################################################\n# Create the text for the text widget.\n\n# addFormattedText --\n#\n#\tAdd formatted text (but not hypertext) to the text widget after first\n#\tpassing it through the message catalog to allow for localization.\n#\tLines starting with @@ are formatting directives (insert title, insert\n#\tdemo hyperlink, begin newline, or change style) and all other lines\n#\tare literal strings to be inserted. Substitutions are performed,\n#\tallowing processing pieces through the message catalog. Blank lines\n#\tare ignored.\n#\nproc addFormattedText {formattedText} {\n    set style normal\n    set isNL 1\n    set demoCount 0\n    set new 0\n    foreach line [split $formattedText \\n] {\n\tset line [string trim $line]\n\tif {$line eq \"\"} {\n\t    continue\n\t}\n\tif {[string match @@* $line]} {\n\t    set data [string range $line 2 end]\n\t    set key [lindex $data 0]\n\t    set values [lrange $data 1 end]\n\t    switch -exact -- $key {\n\t\ttitle {\n\t\t    .t insert end [mc $values]\\n title \\n normal\n\t\t}\n\t\tnewline {\n\t\t    .t insert end \\n $style\n\t\t    set isNL 1\n\t\t}\n\t\tsubtitle {\n\t\t    .t insert end \"\\n\" {} [mc $values] subtitle \\\n\t\t\t    \" \\n \" demospace\n\t\t    set demoCount 0\n\t\t}\n\t\tdemo {\n\t\t    set description [lassign $values name]\n\t\t    .t insert end \"[incr demoCount]. [mc $description]\" \\\n\t\t\t    [list demo demo-$name]\n\t\t    if {$new} {\n\t\t\t.t insert end \" [mc NEW]\" new\n\t\t\tset new 0\n\t\t    }\n\t\t    .t insert end \" \\n \" demospace\n\t\t}\n\t\tnew {\n\t\t    set new 1\n\t\t}\n\t\tdefault {\n\t\t    set style $key\n\t\t}\n\t    }\n\t    continue\n\t}\n\tif {!$isNL} {\n\t    .t insert end \" \" $style\n\t}\n\tset isNL 0\n\t.t insert end [mc $line] $style\n    }\n}\n\naddFormattedText {\n    @@title\tTk Widget Demonstrations\n\n    This application provides a front end for several short scripts\n    that demonstrate what you can do with Tk widgets.  Each of the\n    numbered lines below describes a demonstration; you can click on\n    it to invoke the demonstration.  Once the demonstration window\n    appears, you can click the\n    @@bold\n    See Code\n    @@normal\n    button to see the Tcl/Tk code that created the demonstration.  If\n    you wish, you can edit the code and click the\n    @@bold\n    Rerun Demo\n    @@normal\n    button in the code window to reinvoke the demonstration with the\n    modified code.\n    @@newline\n\n    @@subtitle\tLabels, buttons, checkbuttons, and radiobuttons\n    @@demo label\tLabels (text and bitmaps)\n    @@demo unicodeout\tLabels and UNICODE text\n    @@demo button\tButtons\n    @@demo check\tCheck-buttons (select any of a group)\n    @@demo radio\tRadio-buttons (select one of a group)\n    @@demo puzzle\tA 15-puzzle game made out of buttons\n    @@demo icon\t\tIconic buttons that use bitmaps\n    @@demo image1\tTwo labels displaying images\n    @@demo image2\tA simple user interface for viewing images\n    @@demo labelframe\tLabelled frames\n    @@demo ttkbut\tThe simple Themed Tk widgets\n}\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    addFormattedText {\n\t@@subtitle Mac-Specific Widgets and Window Styles\n\t@@demo mac_styles\tSpecial widgets for macOS\n\t@@demo mac_wm\tWindow styles for macOS\n\t@@demo mac_tabs\tTabbed Windows on macOS\n    }\n}\n\naddFormattedText {\n    @@subtitle\tListboxes and Trees\n    @@demo states\tThe 50 states\n    @@demo colors\tColors: change the color scheme for the application\n    @@demo sayings\tA collection of famous and infamous sayings\n    @@demo mclist\tA multi-column list of countries\n    @@demo tree\t\tA directory browser tree\n\n    @@subtitle\tEntries, Spin-boxes and Combo-boxes\n    @@demo entry1\tEntries without scrollbars\n    @@demo entry2\tEntries with scrollbars\n    @@demo entry3\tValidated entries and password fields\n    @@demo spin\t\tSpin-boxes\n    @@demo ttkspin\tThemed spin-boxes\n    @@demo combo\tCombo-boxes\n    @@demo form\t\tSimple Rolodex-like form\n\n    @@subtitle\tText\n    @@demo text\t\tBasic editable text\n    @@demo style\tText display styles\n    @@demo bind\t\tHypertext (tag bindings)\n    @@demo twind\tA text widget with embedded windows and other features\n    @@demo search\tA search tool built with a text widget\n    @@demo textpeer\tPeering text widgets\n\n    @@subtitle\tCanvases\n    @@demo items\tThe canvas item types\n    @@demo plot\t\tA simple 2-D plot\n    @@demo ctext\tText items in canvases\n    @@demo arrow\tAn editor for arrowheads on canvas lines\n    @@demo ruler\tA ruler with adjustable tab stops\n    @@demo floor\tA building floor plan\n    @@demo cscroll\tA simple scrollable canvas\n    @@demo knightstour  A Knight's tour of the chess board\n\n    @@subtitle\tScales and Progress Bars\n    @@demo hscale\tHorizontal scale\n    @@demo vscale\tVertical scale\n    @@demo ttkscale\tThemed scale linked to a label with traces\n    @@demo ttkprogress\tProgress bar\n\n    @@subtitle\tPaned Windows and Notebooks\n    @@demo paned1\tHorizontal paned window\n    @@demo paned2\tVertical paned window\n    @@demo ttkpane\tThemed nested panes\n    @@demo ttknote\tNotebook widget\n\n    @@subtitle\tMenus and Toolbars\n    @@demo menu\t\tMenus and cascades (sub-menus)\n    @@demo menubu\tMenu-buttons\n    @@demo ttkmenu\tThemed menu buttons\n    @@demo toolbar\tThemed toolbar\n\n    @@subtitle\tCommon Dialogs\n    @@demo msgbox\tMessage boxes\n    @@demo filebox\tFile selection dialog\n    @@demo clrpick\tColor picker\n    @@demo fontchoose\tFont selection dialog\n    @@demo systray      System tray icon and notification\n    @@demo print        Printing from canvas and text widgets\n\n    @@subtitle\tAnimation\n    @@demo anilabel\tAnimated labels\n    @@demo aniwave\tAnimated wave\n    @@demo pendulum\tPendulum simulation\n    @@demo goldberg\tA celebration of Rube Goldberg\n\n    @@subtitle\tMiscellaneous\n    @@demo bitmap\tThe built-in bitmaps\n    @@demo dialog1\tA dialog box with a local grab\n    @@demo dialog2\tA dialog box with a global grab\n    @@demo windowicons  Window icons and badges\n}\n\f\n##############################################################################\n\n.t configure -state disabled\nfocus .s\n\n# addSeeDismiss --\n# Add \"See Code\" and \"Dismiss\" button frame, with optional \"See Vars\"\n#\n# Arguments:\n# w -\t\tThe name of the frame to use.\n\nproc addSeeDismiss {w show {vars {}} {extra {}}} {\n    ## See Code / Dismiss buttons\n    ttk::frame $w\n    #ttk::frame $w.sep -height 2 -relief sunken\n    ttk::separator $w.sep\n    grid $w.sep -columnspan 4 -row 0 -sticky ew -pady 1.5p\n    ttk::button $w.dismiss -text [mc \"Dismiss\"] \\\n\t-image ::img::delete -compound left \\\n\t-command [list destroy [winfo toplevel $w]]\n    ttk::button $w.code -text [mc \"See Code\"] \\\n\t-image ::img::view -compound left \\\n\t-command [list showCode $show]\n    set buttons [list x $w.code $w.dismiss]\n    if {[llength $vars]} {\n\tttk::button $w.vars -text [mc \"See Variables\"] \\\n\t    -image ::img::view -compound left \\\n\t    -command [concat [list showVars $w.dialog] $vars]\n\tset buttons [linsert $buttons 1 $w.vars]\n    }\n    if {$extra ne \"\"} {\n\tset buttons [linsert $buttons 1 [uplevel 1 $extra]]\n    }\n    grid {*}$buttons -padx 3p -pady 3p\n    grid columnconfigure $w 0 -weight 1\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tforeach b [lrange $buttons 1 end] {$b configure -takefocus 0}\n\tgrid configure $w.sep -pady 0\n\tgrid configure {*}$buttons -pady {10 12}\n\tgrid configure [lindex $buttons 1] -padx {16 4}\n\tgrid configure [lindex $buttons end] -padx {4 18}\n    }\n    return $w\n}\n\n# positionWindow --\n# This procedure is invoked by most of the demos to position a new demo\n# window.\n#\n# Arguments:\n# w -\t\tThe name of the window to position.\n\nproc positionWindow w {\n    wm geometry $w +300+300\n}\n\n# showVars --\n# Displays the values of one or more variables in a window, and updates the\n# display whenever any of the variables changes.\n#\n# Arguments:\n# w -\t\tName of new window to create for display.\n# args -\tAny number of names of variables.\n\nproc showVars {w args} {\n    catch {destroy $w}\n    toplevel $w\n    if {[tk windowingsystem] eq \"x11\"} {wm attributes $w -type dialog}\n    wm title $w [mc \"Variable values\"]\n\n    set b [ttk::frame $w.frame]\n    grid $b -sticky news\n    set f [ttk::labelframe $b.title -text [mc \"Variable values:\"]]\n    foreach var $args {\n\tttk::label $f.n$var -text \"$var:\" -anchor w\n\tttk::label $f.v$var -textvariable $var -anchor w\n\tgrid $f.n$var $f.v$var -padx 1.5p -pady 1.5p -sticky w\n    }\n    ttk::button $b.ok -text [mc \"OK\"] \\\n\t-command [list destroy $w] -default active\n    bind $w <Return> [list $b.ok invoke]\n    bind $w <Escape> [list $b.ok invoke]\n\n    grid $f -sticky news -padx 3p\n    grid $b.ok -sticky e -padx 3p -pady {4.5p 3p}\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t$b.ok configure -takefocus 0\n\tgrid configure $b.ok -pady {10 12} -padx {16 18}\n\tgrid configure $f -padx 10 -pady {10 0}\n    }\n    grid columnconfig $f 1 -weight 1\n    grid rowconfigure $f 100 -weight 1\n    grid columnconfig $b 0 -weight 1\n    grid rowconfigure $b 0 -weight 1\n    grid columnconfig $w 0 -weight 1\n    grid rowconfigure $w 0 -weight 1\n}\n\n# invoke --\n# This procedure is called when the user clicks on a demo description. It is\n# responsible for invoking the demonstration.\n#\n# Arguments:\n# index -\tThe index of the character that the user clicked on.\n\nproc invoke index {\n    global tk_demoDirectory\n    set tags [.t tag names $index]\n    set i [lsearch -glob $tags demo-*]\n    if {$i < 0} {\n\treturn\n    }\n    set cursor [.t cget -cursor]\n    .t configure -cursor [::ttk::cursor busy]\n    update\n    set demo [string range [lindex $tags $i] 5 end]\n    uplevel 1 [list source [file join $tk_demoDirectory $demo.tcl]]\n    update\n    .t configure -cursor $cursor\n\n    .t tag add visited \"$index linestart +1 chars\" \"$index lineend -1 chars\"\n}\n\n# showStatus --\n#\n#\tShow the name of the demo program in the status bar. This procedure is\n#\tcalled when the user moves the cursor over a demo description.\n#\nproc showStatus index {\n    set tags [.t tag names $index]\n    set i [lsearch -glob $tags demo-*]\n    set cursor [.t cget -cursor]\n    if {$i < 0} {\n\t.statusBar.lab config -text \" \"\n\tset newcursor [::ttk::cursor text]\n    } else {\n\tset demo [string range [lindex $tags $i] 5 end]\n\t.statusBar.lab config -text [mc \"Run the \\\"%s\\\" sample program\" $demo]\n\tset newcursor [::ttk::cursor link]\n    }\n    if {$cursor ne $newcursor} {\n\t.t config -cursor $newcursor\n    }\n}\n\n# evalShowCode --\n#\n# Arguments:\n# w -\t\tName of text widget containing code to eval\n\nproc evalShowCode {w} {\n    set code [$w get 1.0 end-1c]\n    uplevel #0 $code\n}\n\n# showCode --\n# This procedure creates a toplevel window that displays the code for a\n# demonstration and allows it to be edited and reinvoked.\n#\n# Arguments:\n# w -\t\tThe name of the demonstration's window, which can be used to\n#\t\tderive the name of the file containing its code.\n\nproc showCode w {\n    global tk_demoDirectory\n    set file [string range $w 1 end].tcl\n    set top .code\n    if {![winfo exists $top]} {\n\ttoplevel $top\n\tif {[tk windowingsystem] eq \"x11\"} {wm attributes $top -type dialog}\n\n\tset t [frame $top.f]\n\tset text [text $t.text -font fixedFont -height 24 -wrap word \\\n\t\t      -xscrollcommand [list $t.xscroll set] \\\n\t\t      -yscrollcommand [list $t.yscroll set] \\\n\t\t      -setgrid 1 -highlightthickness 0 -padx 3p -pady 1.5p \\\n\t\t      -tabstyle wordprocessor]\n\tttk::scrollbar $t.xscroll -command [list $t.text xview] \\\n\t    -orient horizontal\n\tttk::scrollbar $t.yscroll -command [list $t.text yview] \\\n\t    -orient vertical\n\n\tgrid $t.text $t.yscroll -sticky news\n\t#grid $t.xscroll\n\tgrid rowconfigure $t 0 -weight 1\n\tgrid columnconfig $t 0 -weight 1\n\n\tset btns [ttk::frame $top.btns]\n\tttk::separator $btns.sep\n\tgrid $btns.sep -columnspan 4 -row 0 -sticky ew -pady 1.5p\n\tttk::button $btns.dismiss -text [mc \"Dismiss\"] \\\n\t    -default active -command [list destroy $top] \\\n\t    -image ::img::delete -compound left\n\tttk::button $btns.print   -text [mc \"Print Code\"] \\\n\t    -command [list printCode $text $file] \\\n\t    -image ::img::print -compound left\n\tttk::button $btns.rerun   -text [mc \"Rerun Demo\"] \\\n\t    -command [list evalShowCode $text] \\\n\t    -image ::img::refresh -compound left\n\tset buttons [list x $btns.rerun $btns.print $btns.dismiss]\n\tgrid {*}$buttons -padx 3p -pady 3p\n\tgrid columnconfigure $btns 0 -weight 1\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    foreach b [lrange $buttons 1 end] {$b configure -takefocus 0}\n\t    grid configure $btns.sep -pady 0\n\t    grid configure {*}$buttons -pady {10 12}\n\t    grid configure [lindex $buttons 1] -padx {16 4}\n\t    grid configure [lindex $buttons end] -padx {4 18}\n\t}\n\tgrid $t    -sticky news\n\tgrid $btns -sticky ew\n\tgrid rowconfigure $top 0 -weight 1\n\tgrid columnconfig $top 0 -weight 1\n\n\tbind $top <Return> {\n\t    if {[winfo class %W] ne \"Text\"} { .code.btns.dismiss invoke }\n\t}\n\tbind $top <Escape> [bind $top <Return>]\n    } else {\n\twm deiconify $top\n\traise $top\n    }\n    wm title $top [mc \"Demo code: %s\" [file join $tk_demoDirectory $file]]\n    wm iconname $top $file\n    set id [open [file join $tk_demoDirectory $file]]\n    fconfigure $id -encoding utf-8 -eofchar \"\\032 {}\"\n    $top.f.text delete 1.0 end\n    $top.f.text insert 1.0 [read $id]\n    $top.f.text mark set insert 1.0\n    close $id\n}\n\n# printCode --\n# Prints the source code currently displayed in the See Code dialog. Much\n# thanks to Arjen Markus for this.\n#\n# Arguments:\n# w -\t\tName of text widget containing code to print\n# file -\t\tName of the original file (implicitly for title)\n\nproc printCode {w file} {\n    tk print $w\n}\n\n# tkAboutDialog --\n#\n#\tPops up a message box with an \"about\" message\n#\nproc tkAboutDialog {} {\n    tk_messageBox -icon info -type ok -title [mc \"About Widget Demo\"] \\\n\t    -message [mc \"Tk widget demonstration application\"] -detail \\\n\"[mc \"Copyright © %s\" {1996-1997 Sun Microsystems, Inc.}]\n[mc \"Copyright © %s\" {1997-2000 Ajuba Solutions, Inc.}]\n[mc \"Copyright © %s\" {2001-2009 Donal K. Fellows}]\n[mc \"Copyright © %s\" {2002-2007 Daniel A. Steffen}]\n[mc \"Copyright © %s\" {2021 Kevin Walzer}]\"\n}\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "library/demos/windowicons.tcl",
    "content": "# windowicons.tcl --\n#\n# This demonstration script showcases the wm iconphoto and wm iconbadge commands.\n#\n\nif {![info exists widgetDemo]} {\n    error \"This script should be run from the \\\"widget\\\" demo.\"\n}\n\nset w .windowicons\ndestroy $w\ntoplevel $w\nwm title $w \"Window Icon Demonstration\"\npositionWindow $w\n\n## See Code / Dismiss buttons\npack [addSeeDismiss $w.buttons $w] -side bottom -fill x\n\nimage create photo icon -data {\n    iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGP\n    C/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3Cc\n    ulE8AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAArQNAAK0DQEdFIm+AAAJ\n    QElEQVRYw+WXW2xdV5nHf/ty7lcf2/FxYsdOnMSNC0HTpDiRKJWAQjWCEQNU\n    SEAFfUOiQqrEC2+IxwpemDLSzNBBCCQeQEKqRJgBSikiuGlN22TqhsR27OPL\n    8eWc43Pdt7X22osHHydOm4FBPM6Slr69paX9/32Xtb614f/7MP6vC3O5f8L3\n    G7HJyZPHBwfz5wrF7HQ6nRwxLTOhQuU4PW+z3eq9Xa+33rq9cms7k8pHjvfS\n    3w8wOfk52u1u8oHpiUff897JJ8+dO/nI6LHho6OjQ3ahkMYwTTZ2O2zXutS3\n    G/7ayubq7Vtr/7Ve2f7RytLam4ViXq1t/vRvB0ilPsjzz3+LZ5/9j7MzM5Nf\n    /8hj5//5H97/YNbK5hkfTFLMxAEQQvD766v0yBGIEBEEuPUGi9dv7lx77cb3\n    Vm9vfqc0WNi9evUKWr/xLh3rfuLj45+l0bjM7m768U98/OJ/fulLH/3wiemx\n    eCafxRcKw7TJxKC+12RpbYdAx7HsOCrSRNpg+sQQj1w8nS0N5h8JAvm+rWr9\n    9ZmZB2qWdZq9vWt/GWBm5im+9rUn6HRGPv7EE4/++2P/eOFkV0FkJTDQgCaX\n    TbO1tcV2R2EmCxBJQixs2+R9EwV00MFAceJE2ZiZOT7VaTsPLyxU5orFTK1c\n    fphq9bX7A8zOfoV8Ps3c3NsXPvWpD37vc5//0ETNt8gNjDAzlsdAE0vliTCR\n    xEhnC2CaRIZNMmZiaonv9mh1PcrDJQZzCfK5OGNjQ8e2tvZO37y5+ctk0naq\n    1fn7A4yOnmd5uVp4/PGHn/vylz8xe+zoEIP5JAMpA0OHeK6DG4TEk2li8Tha\n    QxRpIg0q6DGUNjg6UuLYSInhYoYoigiCgHQ6TrGYnlpd3Q1ffvk3L128+ITe\n    2Hj1XoBLl55menqcbDb1haeeevyrDz102tJaE7ctLBMqG1X23Ag7kcKOJzAA\n    DSilCVWEZdmMDaXJJCxSiRimaaK1RkqJ7/uUSlk6Hed0oxG9HI9bm+Pjs2xs\n    vIp5AKC15oUX/lA8f/7MF2dnz8YADMNASslypYqrUxSHyqSy+f31hzaRZRpM\n    DKVYr+7y4usVri1WWavWCWSIZZkYhoFSIRcuTI1MTAw9OTf33Tu7zz54SCRi\n    nD17/Pzs7AMPFQqZPlTE8vo2DlmGhgbo12BffD/8SmukitiuNxHKoDwyzPJG\n    nTdXmtiWwdnRNCN5GxWGDA/nOH26/NGpqSfHgPU7AJcuPc0nP/kBrl698YGZ\n    mYmMEIJmx6Hn+my0DUZGC6gIzEOnhu4Lh2GEbRocGyxRSO/7c3QgiRuEVOtd\n    EvEQrSN8IVEq5MSJ4YlSKX3OMKJ14G4KnnnmM9bkZPk92VyKy3M3eentJjd3\n    FUYyjxuEeELt7/NoP+eBVAipCFXEsYE4xcydYFIeSHKynOXhUwM0mh32egH1\n    tsdL16oo007kcskHs7kYly49fRcALqby+fQopklkZ4jHY3g6gQgjHF/QcgQd\n    V+7DHJoGmnzSQuvD0QGlIsJQkU4luLXR4kgxxcRgjM1mQCyZHrv0sUe4JwKF\n    XMmu7/VSXV9xaXqI0YzC8328QOJ4gq4raHQDGt2AtitwfIEbSAwibOvdJ7pS\n    CiElR3IxGh2X5Y0GV66v0wnAsq3MN5759L1FqKMoCkQoX19u0QkkD47lKSYi\n    Th1NoSLYafu0ehrTNNBaE2mNUop2z+DEUJKBbPxecSEIgoAoUjwwmmZpdZPl\n    muL4oIFWkbx8rXIvQMfZ9p2e1xBCstOJcFe6nB1NcWokhW1ZHMkazK90qXXD\n    fZFII0NFIBW/XQiZHraoNbsU81mmjhbxfZ8gCAiCgELKQitJGCoIQ6SQO//2\n    ze/fm4Kf/Px50dzr3Aoch1Ap2o4kn8tgW/sHynAxzcVTBQYzFp4v6boBjidw\n    fcFCpcmPf7/Oz+ZrvPBalb12D9/370DUGk1evr6NacWIfD/yveDmXq3F3Nxz\n    dwH+5dkfUq8155rb9dA2QcqQcjFx57DRGgaySR47d4RHZ0pYeh/C9QSOJ3EE\n    CGWw3fJZ323j+x6e5xH4Pgu3d6g0FMWUjdvu7bo9/5oK1d0IzM09hwhCGrvN\n    ubXFylI2pum4AZXtDqEURFGE1hoNxGMW5ZyB22nS8wQ9r1+QvsDzBc1uQGW7\n    jee6eN4+RMfxMdHkYgatWmtur9ZaOnD8TgQMA27c+uH68s3KT8O9BoYBv3pj\n    kxuVGo7Tw+1/MAh83lreYm1P9r3fT4XjSVxf4voC1/NwHAfXdXFcB891KGVj\n    hO2e16q3fzR2cjQwDPPeZrSx8SqXL2/RqDU2EnH7I8dPjQ8v7Tqs1RwmSzEs\n    QoQQSBHw1lKVha0AEUb4IiQQIb4I8YUkkCHTQwa5WIjne9xY2mT+VouRfI7N\n    xfVfrK8sfTuRSAavXP3Xd7fjavWPRq1+3TeiQTVcGnh0oHwktlZzmBq0SNsR\n    QgiuXLvNL/+nQU/aBFL1xSW+kAghEb5PEkE5q3Bdl7dv72LGCrTXdzf+9Nb8\n    N5dXfrG6Wf1jeNDP3nkjigOFWm2xpvx0+tjI8LnMYMnMxQT5eIjruVye36LS\n    TRAqRSD3vZdCIqUgEj5R4CEDj2O5kMZei3rHoLXV6Sy88cp3Fhf/ew6IAAGE\n    9wOIARmtw9Tu7vKa1yY+Wiqeee+ZYdsi4HdvrjK/HiKUiZQhoZREQhDJAC18\n    tPSIhEfouwSuQ9cx2VxpNK/PX/n+4uKvXwQdAAHgA/J+AAaQABJRJOydnVsr\n    zZ1O13eMcSuezC61LJzQRgY+KvCJhI+WPpH0IAywIkEhaVIupAhdHS0t3F66\n    Nv/iD9bW/nAFtAM4QA9wAXX3RnEvQBoYODSL+fzEmalTsx+emjl3YWjsaMlM\n    pcwg0ggZEimFoSNsI8JSCtF1wtpmdWt1aeGVSuW133leYwNoA01gr297BzVw\n    v/8CA0gBBaDYtzkw87ns6PhI+czM0JHjp/PFUjmZSmUM07RCKUPP6XVae/Vq\n    fbdys1ZbvOX5ja2+ULcP0Opbt18H/G8Ah+shDWQPzVQ/RSnLTGRsO5U0TMuM\n    VKjC0PUjLd1+fgPAOxTybl9YcvdC9VcBDobV3x0JINm3MfYbmdX/hu57FfZF\n    Dgot6Fe8eqfw3wLwzvVmX9jsvx8AHEAcnn91/BlySEFKTpuCtgAAABN0RVh0\n    QXV0aG9yAHdhcnN6YXdpYW5rYQy+S5cAAABYdEVYdENvcHlyaWdodABDQzAg\n    UHVibGljIERvbWFpbiBEZWRpY2F0aW9uIGh0dHA6Ly9jcmVhdGl2ZWNvbW1v\n    bnMub3JnL3B1YmxpY2RvbWFpbi96ZXJvLzEuMC/G4735AAAAIXRFWHRDcmVh\n    dGlvbiBUaW1lADIwMTAtMDMtMjlUMDg6MDg6MzD47LxwAAAAJXRFWHRkYXRl\n    OmNyZWF0ZQAyMDIxLTA4LTE1VDIwOjU0OjM5LTA0OjAwNBT3DQAAACV0RVh0\n    ZGF0ZTptb2RpZnkAMjAyMS0wOC0xNVQyMDo1NDoxMS0wNDowMDSDBqsAAADI\n    elRYdERlc2NyaXB0aW9uAAAY042OwQqCQBCGn6B3GOy+Cl0qTAjEc1HRJVhW\n    HXUrd2pmLXr7tDrVpcMP838w/F+wxxxyprsgB2ALclAxtRAbaBirRdB4f5mH\n    oTeuJlUxYoly8nRRxHW4HahO30SvmI5Y+CCBF4dPhzg0CYwOLs45GdKfG+sK\n    hBuy2H4xUlM1i76+BhcBwwirLj/bAlJqjXXzP9UyxmuHzp8feiknLPW6Q/H9\n    moy3yK1oqvROUE2yH99suX45PwEyf2MTOoCNrQAAABl0RVh0U29mdHdhcmUA\n    d3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABWdEVYdFNvdXJjZQBodHRwczovL29w\n    ZW5jbGlwYXJ0Lm9yZy9kZXRhaWwvMzUyMzMvdGFuZ28taW5ldHJuZXQtd2Vi\n    LWJyb3dzZXItYnktd2Fyc3phd2lhbmth5nAuRgAAACB0RVh0VGl0bGUAdGF\n    uZ28gaW5ldHJuZXQgd2ViIGJyb3dzZXLyr62TAAAAAElFTkSuQmCC\n}\n\nset ::tk::icons::base_icon(.) icon\n\n# Create a copy of the image just created, magnified according to the\n# display's DPI scaling level.  Since the zooom factor must be an integer,\n# the copy will only be effectively magnified if $tk::scalingPct >= 200.\nimage create photo icon2\nicon2 copy icon -zoom [expr {$tk::scalingPct / 100}]\n\npack [button $w.i -text \"Set Window Icon to Globe\" -image icon2 \\\n\t-compound top -command {wm iconphoto . icon}] -fill x -padx 3p\npack [button $w.b -text \"Set Badge to 3\" -command {wm iconbadge . 3}] \\\n\t-fill x -padx 3p\npack [button $w.e -text \"Set Badge to 11\" -command {wm iconbadge . 11}] \\\n\t-fill x -padx 3p\npack [button $w.f -text \"Reset Badge\" -command {wm iconbadge . \"\"}] \\\n\t-fill x -padx 3p\n"
  },
  {
    "path": "library/dialog.tcl",
    "content": "# dialog.tcl --\n#\n# This file defines the procedure tk_dialog, which creates a dialog\n# box containing a bitmap, a message, and one or more buttons.\n#\n# Copyright © 1992-1993 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#\n# ::tk_dialog:\n#\n# This procedure displays a dialog box, waits for a button in the dialog\n# to be invoked, then returns the index of the selected button.  If the\n# dialog somehow gets destroyed, -1 is returned.\n#\n# Arguments:\n# w -\t\tWindow to use for dialog top-level.\n# title -\tTitle to display in dialog's decorative frame.\n# text -\tMessage to display in dialog.\n# bitmap -\tBitmap to display in dialog (empty string means none).\n# default -\tIndex of button that is to display the default ring\n#\t\t(-1 means none).\n# args -\tOne or more strings to display in buttons across the\n#\t\tbottom of the dialog box.\n\nproc ::tk_dialog {w title text bitmap default args} {\n    variable ::tk::Priv\n\n    # Check that $default was properly given\n    if {[string is integer -strict $default]} {\n\tif {$default >= [llength $args]} {\n\t    return -code error -errorcode {TK DIALOG BAD_DEFAULT} \\\n\t\t\"default button index greater than number of buttons\\\n\t\tspecified for tk_dialog\"\n\t}\n    } elseif {\"\" eq $default} {\n\tset default -1\n    } else {\n\tset default [lsearch -exact $args $default]\n    }\n\n    set windowingsystem [tk windowingsystem]\n\n    # 1. Create the top-level window and divide it into top\n    # and bottom parts.\n\n    destroy $w\n    toplevel $w -class Dialog\n    wm title $w $title\n    wm iconname $w Dialog\n    wm protocol $w WM_DELETE_WINDOW { }\n\n    # Dialog boxes should be transient with respect to their parent,\n    # so that they will always stay on top of their parent window.  However,\n    # some window managers will create the window as withdrawn if the parent\n    # window is withdrawn or iconified.  Combined with the grab we put on the\n    # window, this can hang the entire application.  Therefore we only make\n    # the dialog transient if the parent is viewable.\n    #\n    if {[winfo viewable [winfo toplevel [winfo parent $w]]] } {\n\twm transient $w [winfo toplevel [winfo parent $w]]\n    }\n\n    if {$windowingsystem eq \"aqua\"} {\n\t::tk::unsupported::MacWindowStyle style $w moveableModal {}\n    } elseif {$windowingsystem eq \"x11\"} {\n\twm attributes $w -type dialog\n    }\n\n    frame $w.bot\n    frame $w.top\n    if {$windowingsystem eq \"x11\"} {\n\t$w.bot configure -relief raised -bd 1\n\t$w.top configure -relief raised -bd 1\n    }\n    pack $w.bot -side bottom -fill both\n    pack $w.top -side top -fill both -expand 1\n    grid anchor $w.bot center\n\n    # 2. Fill the top part with bitmap and message (use the option\n    # database for -wraplength and -font so that they can be\n    # overridden by the caller).\n\n    option add *Dialog.msg.wrapLength 3i widgetDefault\n    option add *Dialog.msg.font TkCaptionFont widgetDefault\n\n    label $w.msg -justify left -text $text\n    pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m\n    if {$bitmap ne \"\"} {\n\tif {$windowingsystem eq \"aqua\" && $bitmap eq \"error\"} {\n\t    set bitmap \"stop\"\n\t}\n\tlabel $w.bitmap -bitmap $bitmap\n\tpack $w.bitmap -in $w.top -side left -padx 3m -pady 3m\n    }\n\n    # 3. Create a row of buttons at the bottom of the dialog.\n\n    set i 0\n    foreach but $args {\n\tbutton $w.button$i -text $but -command [list set ::tk::Priv(button) $i]\n\tif {$i == $default} {\n\t    $w.button$i configure -default active\n\t} else {\n\t    $w.button$i configure -default normal\n\t}\n\tgrid $w.button$i -in $w.bot -column $i -row 0 -sticky ew \\\n\t\t-padx 7.5p -pady 3p\n\tgrid columnconfigure $w.bot $i\n\t# We boost the size of some Mac buttons for l&f\n\tif {$windowingsystem eq \"aqua\"} {\n\t    set tmp [string tolower $but]\n\t    if {$tmp eq \"ok\" || $tmp eq \"cancel\"} {\n\t\tgrid columnconfigure $w.bot $i -minsize 90\n\t    }\n\t    grid configure $w.button$i -pady 7\n\t}\n\tincr i\n    }\n\n    # 4. Create a binding for <Return> on the dialog if there is a\n    # default button.\n    # Convention also dictates that if the keyboard focus moves among the\n    # the buttons that the <Return> binding affects the button with the focus.\n\n    if {$default >= 0} {\n\tbind $w <Return> [list $w.button$default invoke]\n    }\n    bind $w <<PrevWindow>> [list bind $w <Return> {[tk_focusPrev %W] invoke}]\n    bind $w <<NextWindow>> [list bind $w <Return> {[tk_focusNext %W] invoke}]\n\n    # 5. Create a <Destroy> binding for the window that sets the\n    # button variable to -1;  this is needed in case something happens\n    # that destroys the window, such as its parent window being destroyed.\n\n    bind $w <Destroy> {set ::tk::Priv(button) -1}\n\n    # 6. Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w\n    tkwait visibility $w\n\n    # 7. Set a grab and claim the focus too.\n\n    if {$default >= 0} {\n\tset focus $w.button$default\n    } else {\n\tset focus $w\n    }\n    tk::SetFocusGrab $w $focus\n\n    # 8. Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait ::tk::Priv(button)\n\n    catch {\n\t# It's possible that the window has already been destroyed,\n\t# hence this \"catch\".  Delete the Destroy handler so that\n\t# Priv(button) doesn't get reset by it.\n\n\tbind $w <Destroy> {}\n    }\n    tk::RestoreFocusGrab $w $focus\n    return $Priv(button)\n}\n"
  },
  {
    "path": "library/entry.tcl",
    "content": "# entry.tcl --\n#\n# This file defines the default bindings for Tk entry widgets and provides\n# procedures that help in implementing those bindings.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# Elements of tk::Priv that are used in this file:\n#\n# afterId -\t\tIf non-null, it means that auto-scanning is underway\n#\t\t\tand it gives the \"after\" id for the next auto-scan\n#\t\t\tcommand to be executed.\n# mouseMoved -\t\tNon-zero means the mouse has moved a significant\n#\t\t\tamount since the button went down (so, for example,\n#\t\t\tstart dragging out a selection).\n# pressX -\t\tX-coordinate at which the mouse button was pressed.\n# selectMode -\t\tThe style of selection currently underway:\n#\t\t\tchar, word, or line.\n# x, y -\t\tLast known mouse coordinates for scanning\n#\t\t\tand auto-scanning.\n# data -\t\tUsed for Cut and Copy\n#-------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for entries.\n#-------------------------------------------------------------------------\nbind Entry <<Cut>> {\n    if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {\n\tclipboard clear -displayof %W\n\tclipboard append -displayof %W $tk::Priv(data)\n\t%W delete sel.first sel.last\n\tunset tk::Priv(data)\n    }\n}\nbind Entry <<Copy>> {\n    if {![catch {tk::EntryGetSelection %W} tk::Priv(data)]} {\n\tclipboard clear -displayof %W\n\tclipboard append -displayof %W $tk::Priv(data)\n\tunset tk::Priv(data)\n    }\n}\nbind Entry <<Paste>> {\n    catch {\n\tif {[tk windowingsystem] ne \"x11\"} {\n\t    catch {\n\t\t%W delete sel.first sel.last\n\t    }\n\t}\n\t%W insert insert [::tk::GetSelection %W CLIPBOARD]\n\ttk::EntrySeeInsert %W\n    }\n}\nbind Entry <<Clear>> {\n    # ignore if there is no selection\n    catch {%W delete sel.first sel.last}\n}\nbind Entry <<PasteSelection>> {\n    if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]\n\t|| !$tk::Priv(mouseMoved)} {\n\ttk::EntryPaste %W %x\n    }\n}\n\nbind Entry <<TraverseIn>> {\n    %W selection range 0 end\n    %W icursor end\n}\n\n# Standard Motif bindings:\n\nbind Entry <Button-1> {\n    tk::EntryButton1 %W %x\n    %W selection clear\n}\nbind Entry <B1-Motion> {\n    set tk::Priv(x) %x\n    tk::EntryMouseSelect %W %x\n}\nbind Entry <Double-Button-1> {\n    set tk::Priv(selectMode) word\n    tk::EntryMouseSelect %W %x\n    catch {%W icursor sel.last}\n}\nbind Entry <Triple-Button-1> {\n    set tk::Priv(selectMode) line\n    tk::EntryMouseSelect %W %x\n    catch {%W icursor sel.last}\n}\nbind Entry <Shift-Button-1> {\n    set tk::Priv(selectMode) char\n    %W selection adjust @%x\n}\nbind Entry <Double-Shift-Button-1>\t{\n    set tk::Priv(selectMode) word\n    tk::EntryMouseSelect %W %x\n}\nbind Entry <Triple-Shift-Button-1>\t{\n    set tk::Priv(selectMode) line\n    tk::EntryMouseSelect %W %x\n}\nbind Entry <B1-Leave> {\n    set tk::Priv(x) %x\n    tk::EntryAutoScan %W\n}\nbind Entry <B1-Enter> {\n    tk::CancelRepeat\n}\nbind Entry <ButtonRelease-1> {\n    tk::CancelRepeat\n}\nbind Entry <Control-Button-1> {\n    %W icursor @%x\n}\n\nbind Entry <<PrevChar>> {\n    tk::EntrySetCursor %W [tk::EntryPreviousChar %W insert]\n}\nbind Entry <<NextChar>> {\n    tk::EntrySetCursor %W [tk::EntryNextChar %W insert]\n}\nbind Entry <<SelectPrevChar>> {\n    tk::EntryKeySelect %W [tk::EntryPreviousChar %W insert]\n    tk::EntrySeeInsert %W\n}\nbind Entry <<SelectNextChar>> {\n    tk::EntryKeySelect %W [tk::EntryNextChar %W insert]\n    tk::EntrySeeInsert %W\n}\nbind Entry <<PrevWord>> {\n    tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]\n}\nbind Entry <<NextWord>> {\n    tk::EntrySetCursor %W [tk::EntryNextWord %W insert]\n}\nbind Entry <<SelectPrevWord>> {\n    tk::EntryKeySelect %W [tk::EntryPreviousWord %W insert]\n    tk::EntrySeeInsert %W\n}\nbind Entry <<SelectNextWord>> {\n    tk::EntryKeySelect %W [tk::EntrySelectNextWord %W insert]\n    tk::EntrySeeInsert %W\n}\nbind Entry <<LineStart>> {\n    tk::EntrySetCursor %W 0\n}\nbind Entry <<SelectLineStart>> {\n    tk::EntryKeySelect %W 0\n    tk::EntrySeeInsert %W\n}\nbind Entry <<LineEnd>> {\n    tk::EntrySetCursor %W end\n}\nbind Entry <<SelectLineEnd>> {\n    tk::EntryKeySelect %W end\n    tk::EntrySeeInsert %W\n}\n\nbind Entry <Delete> {\n    if {[%W selection present]} {\n\t%W delete sel.first sel.last\n    } else {\n\t%W delete [tk::startOfCluster [%W get] [%W index insert]] \\\n\t\t[tk::endOfCluster [%W get] [%W index insert]]\n    }\n}\nbind Entry <BackSpace> {\n    tk::EntryBackspace %W\n}\n\nbind Entry <Control-space> {\n    %W selection from insert\n}\nbind Entry <Select> {\n    %W selection from insert\n}\nbind Entry <Control-Shift-space> {\n    %W selection adjust insert\n}\nbind Entry <Shift-Select> {\n    %W selection adjust insert\n}\nbind Entry <<SelectAll>> {\n    %W selection range 0 end\n}\nbind Entry <<SelectNone>> {\n    %W selection clear\n}\nbind Entry <Key> {\n    tk::CancelRepeat\n    tk::EntryInsert %W %A\n}\n\n# Ignore all Alt, Meta, Control, Command, and Fn keypresses unless explicitly bound.\n# Otherwise, if a widget binding for one of these is defined, the\n# <Key> class binding will also fire and insert the character,\n# which is wrong.  Ditto for Escape, Return, and Tab.\n\nbind Entry <Alt-Key> {# nothing}\nbind Entry <Meta-Key> {# nothing}\nbind Entry <Control-Key> {# nothing}\nbind Entry <Escape> {# nothing}\nbind Entry <Return> {# nothing}\nbind Entry <KP_Enter> {# nothing}\nbind Entry <Tab> {# nothing}\nbind Entry <Prior> {# nothing}\nbind Entry <Next> {# nothing}\nbind Entry <Command-Key> {# nothing}\nbind Entry <Fn-Key> {# nothing}\n# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]\nbind Entry <<NextLine>> {# nothing}\nbind Entry <<PrevLine>> {# nothing}\n\n# On Windows, paste is done using Shift-Insert.  Shift-Insert already\n# generates the <<Paste>> event, so we don't need to do anything here.\nif {[tk windowingsystem] ne \"win32\"} {\n    bind Entry <Insert> {\n\tcatch {tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}\n    }\n}\n\n# Additional emacs-like bindings:\n\nbind Entry <Control-d> {\n    if {!$tk_strictMotif} {\n\t%W delete insert\n    }\n}\nbind Entry <Control-h> {\n    if {!$tk_strictMotif} {\n\ttk::EntryBackspace %W\n    }\n}\nbind Entry <Control-k> {\n    if {!$tk_strictMotif} {\n\t%W delete insert end\n    }\n}\nbind Entry <Control-t> {\n    if {!$tk_strictMotif} {\n\ttk::EntryTranspose %W\n    }\n}\nbind Entry <Meta-b> {\n    if {!$tk_strictMotif} {\n\ttk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]\n    }\n}\nbind Entry <Meta-d> {\n    if {!$tk_strictMotif} {\n\t%W delete insert [tk::EntryNextWord %W insert]\n    }\n}\nbind Entry <Meta-f> {\n    if {!$tk_strictMotif} {\n\ttk::EntrySetCursor %W [tk::EntryNextWord %W insert]\n    }\n}\nbind Entry <Meta-BackSpace> {\n    if {!$tk_strictMotif} {\n\t%W delete [tk::EntryPreviousWord %W insert] insert\n    }\n}\nbind Entry <Meta-Delete> {\n    if {!$tk_strictMotif} {\n\t%W delete [tk::EntryPreviousWord %W insert] insert\n    }\n}\n\n# Bindings for IME text input and accents.\n\nbind Entry <<TkStartIMEMarkedText>> {\n    dict set ::tk::Priv(IMETextMark) \"%W\" [%W index insert]\n}\nbind Entry <<TkEndIMEMarkedText>> {\n    ::tk::EntryEndIMEMarkedText %W\n}\nbind Entry <<TkClearIMEMarkedText>> {\n    %W delete [dict get $::tk::Priv(IMETextMark) \"%W\"] [%W index insert]\n}\nbind Entry <<TkAccentBackspace>> {\n    tk::EntryBackspace %W\n}\n\n# ::tk::EntryEndIMEMarkedText --\n# Handles input method text marking in an entry\n#\n# Arguments:\n# w -\t\tThe entry window.\n\nproc ::tk::EntryEndIMEMarkedText {w} {\n    variable Priv\n    if {[catch {\n\tset mark [dict get $Priv(IMETextMark) $w]\n    }]} {\n\tbell\n\treturn\n    }\n    $w selection range $mark insert\n}\n\n# A few additional bindings of my own.\n\nbind Entry <Button-2> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryScanMark %W %x\n    }\n}\nbind Entry <B2-Motion> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryScanDrag %W %x\n     }\n}\nbind Entry <Enter> {+\n    set tk::Priv(xWheelEvents) 0; set tk::Priv(yWheelEvents) 0\n}\nbind Entry <MouseWheel> {\n    tk::EntryScrollByUnits %W y %D -40.0\n}\nbind Entry <Option-MouseWheel> {\n    tk::EntryScrollByUnits %W y %D -12.0\n}\nbind Entry <Shift-MouseWheel> {\n    tk::EntryScrollByUnits %W x %D -40.0\n}\nbind Entry <Shift-Option-MouseWheel> {\n    tk::EntryScrollByUnits %W x %D -12.0\n}\nbind Entry <TouchpadScroll> {\n    if {%# %% 5 == 0} {\n\tlassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n\tif {$tk::Priv(deltaX) != 0} {\n\t    %W xview scroll [expr {-$tk::Priv(deltaX)}] units\n\t}\n    }\n}\n\n# ::tk::EntryClosestGap --\n# Given x and y coordinates, this procedure finds the closest boundary\n# between characters to the given coordinates and returns the index\n# of the character just after the boundary.\n#\n# Arguments:\n# w -\t\tThe entry window.\n# x -\t\tX-coordinate within the window.\n\nproc ::tk::EntryClosestGap {w x} {\n    set pos [$w index @$x]\n    set bbox [$w bbox $pos]\n    if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {\n\treturn $pos\n    }\n    incr pos\n}\n\n# ::tk::EntryButton1 --\n# This procedure is invoked to handle button-1 presses in entry\n# widgets.  It moves the insertion cursor, sets the selection anchor,\n# and claims the input focus.\n#\n# Arguments:\n# w -\t\tThe entry window in which the button was pressed.\n# x -\t\tThe x-coordinate of the button press.\n\nproc ::tk::EntryButton1 {w x} {\n    variable ::tk::Priv\n\n    set Priv(selectMode) char\n    set Priv(mouseMoved) 0\n    set Priv(pressX) $x\n    $w icursor [EntryClosestGap $w $x]\n    $w selection from insert\n    if {\"disabled\" ne [$w cget -state]} {\n\tfocus $w\n    }\n}\n\n# ::tk::EntryMouseSelect --\n# This procedure is invoked when dragging out a selection with\n# the mouse.  Depending on the selection mode (character, word,\n# line) it selects in different-sized units.  This procedure\n# ignores mouse motions initially until the mouse has moved from\n# one character to another or until there have been multiple clicks.\n#\n# Arguments:\n# w -\t\tThe entry window in which the button was pressed.\n# x -\t\tThe x-coordinate of the mouse.\n\nproc ::tk::EntryMouseSelect {w x} {\n    variable ::tk::Priv\n\n    set cur [EntryClosestGap $w $x]\n    set anchor [$w index anchor]\n    if {($cur != $anchor) || (abs($Priv(pressX) - $x) >= 3)} {\n\tset Priv(mouseMoved) 1\n    }\n    switch $Priv(selectMode) {\n\tchar {\n\t    if {$Priv(mouseMoved)} {\n\t\tif {$cur < $anchor} {\n\t\t    $w selection range $cur $anchor\n\t\t} elseif {$cur > $anchor} {\n\t\t    $w selection range $anchor $cur\n\t\t} else {\n\t\t    $w selection clear\n\t\t}\n\t    }\n\t}\n\tword {\n\t    if {$cur < $anchor} {\n\t\tset before [tk::wordBreakBefore [$w get] $cur]\n\t\tset after [tk::wordBreakAfter [$w get] $anchor-1]\n\t    } elseif {$cur > $anchor} {\n\t\tset before [tk::wordBreakBefore [$w get] $anchor]\n\t\tset after [tk::wordBreakAfter [$w get] $cur-1]\n\t    } else {\n\t\tif {[$w index @$Priv(pressX)] < $anchor} {\n\t\t      incr anchor -1\n\t\t}\n\t\tset before [tk::wordBreakBefore [$w get] $anchor]\n\t\tset after [tk::wordBreakAfter [$w get] $anchor]\n\t    }\n\t    if {$before < 0} {\n\t\tset before 0\n\t    }\n\t    if {$after < 0} {\n\t\tset after end\n\t    }\n\t    $w selection range $before $after\n\t}\n\tline {\n\t    $w selection range 0 end\n\t}\n    }\n    if {$Priv(mouseMoved)} {\n\t$w icursor $cur\n    }\n    update idletasks\n}\n\n# ::tk::EntryPaste --\n# This procedure sets the insertion cursor to the current mouse position,\n# pastes the selection there, and sets the focus to the window.\n#\n# Arguments:\n# w -\t\tThe entry window.\n# x -\t\tX position of the mouse.\n\nproc ::tk::EntryPaste {w x} {\n    $w icursor [EntryClosestGap $w $x]\n    catch {$w insert insert [::tk::GetSelection $w PRIMARY]}\n    if {\"disabled\" ne [$w cget -state]} {\n\tfocus $w\n    }\n}\n\n# ::tk::EntryAutoScan --\n# This procedure is invoked when the mouse leaves an entry window\n# with button 1 down.  It scrolls the window left or right,\n# depending on where the mouse is, and reschedules itself as an\n# \"after\" command so that the window continues to scroll until the\n# mouse moves back into the window or the mouse button is released.\n#\n# Arguments:\n# w -\t\tThe entry window.\n\nproc ::tk::EntryAutoScan {w} {\n    variable ::tk::Priv\n    set x $Priv(x)\n    if {![winfo exists $w]} {\n\treturn\n    }\n    if {$x >= [winfo width $w]} {\n\t$w xview scroll 2 units\n\tEntryMouseSelect $w $x\n    } elseif {$x < 0} {\n\t$w xview scroll -2 units\n\tEntryMouseSelect $w $x\n    }\n    set Priv(afterId) [after 50 [list tk::EntryAutoScan $w]]\n}\n\n# ::tk::EntryKeySelect --\n# This procedure is invoked when stroking out selections using the\n# keyboard.  It moves the cursor to a new position, then extends\n# the selection to that position.\n#\n# Arguments:\n# w -\t\tThe entry window.\n# new -\t\tA new position for the insertion cursor (the cursor hasn't\n#\t\tactually been moved to this position yet).\n\nproc ::tk::EntryKeySelect {w new} {\n    if {![$w selection present]} {\n\t$w selection from insert\n\t$w selection to $new\n    } else {\n\t$w selection adjust $new\n    }\n    $w icursor $new\n}\n\n# ::tk::EntryInsert --\n# Insert a string into an entry at the point of the insertion cursor.\n# If there is a selection in the entry, and it covers the point of the\n# insertion cursor, then delete the selection before inserting.\n#\n# Arguments:\n# w -\t\tThe entry window in which to insert the string\n# s -\t\tThe string to insert (usually just a single character)\n\nproc ::tk::EntryInsert {w s} {\n    if {$s eq \"\"} {\n\treturn\n    }\n    catch {\n\tset insert [$w index insert]\n\tif {([$w index sel.first] <= $insert)\n\t\t&& ([$w index sel.last] >= $insert)} {\n\t    $w delete sel.first sel.last\n\t}\n    }\n    $w insert insert $s\n    EntrySeeInsert $w\n}\n\n# ::tk::EntryBackspace --\n# Backspace over the character just before the insertion cursor.\n# If backspacing would move the cursor off the left edge of the\n# window, reposition the cursor at about the middle of the window.\n#\n# Arguments:\n# w -\t\tThe entry window in which to backspace.\n\nproc ::tk::EntryBackspace w {\n    if {[$w selection present]} {\n\t$w delete sel.first sel.last\n    } else {\n\tset x [expr {[$w index insert] - 1}]\n\tif {$x >= 0} {\n\t    $w delete [tk::startOfCluster [$w get] $x] \\\n\t\t      [tk::endOfCluster [$w get] $x]\n\t}\n\tif {[$w index @0] >= [$w index insert]} {\n\t    set range [$w xview]\n\t    set left [lindex $range 0]\n\t    set right [lindex $range 1]\n\t    $w xview moveto [expr {$left - ($right - $left)/2.0}]\n\t}\n    }\n}\n\n# ::tk::EntrySeeInsert --\n# Make sure that the insertion cursor is visible in the entry window.\n# If not, adjust the view so that it is.\n#\n# Arguments:\n# w -\t\tThe entry window.\n\nproc ::tk::EntrySeeInsert w {\n    set c [$w index insert]\n    if {($c < [$w index @0]) || ($c > [$w index @[winfo width $w]])} {\n\t$w xview $c\n    }\n}\n\n# ::tk::EntrySetCursor -\n# Move the insertion cursor to a given position in an entry.  Also\n# clears the selection, if there is one in the entry, and makes sure\n# that the insertion cursor is visible.\n#\n# Arguments:\n# w -\t\tThe entry window.\n# pos -\t\tThe desired new position for the cursor in the window.\n\nproc ::tk::EntrySetCursor {w pos} {\n    $w icursor $pos\n    $w selection clear\n    EntrySeeInsert $w\n}\n\n# ::tk::EntryTranspose -\n# This procedure implements the \"transpose\" function for entry widgets.\n# It tranposes the characters on either side of the insertion cursor,\n# unless the cursor is at the end of the line.  In this case it\n# transposes the two characters to the left of the cursor.  In either\n# case, the cursor ends up to the right of the transposed characters.\n#\n# Arguments:\n# w -\t\tThe entry window.\n\nproc ::tk::EntryTranspose w {\n    set i [$w index insert]\n    if {$i < [$w index end]} {\n\tincr i\n    }\n    if {$i < 2} {\n\treturn\n    }\n    set first $i-2\n    set data [$w get]\n    set new [string index $data $i-1][string index $data $first]\n    $w delete $first $i\n    $w insert insert $new\n    EntrySeeInsert $w\n}\n\n# ::tk::EntryNextWord --\n# Returns the index of the next start-of-word position after the next\n# end-of-word position after a given position in the text.\n#\n# Arguments:\n# w -\t\tThe entry window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::EntryNextWord {w start} {\n    # the check on [winfo class] is because the spinbox also uses this proc\n    if {[winfo class $w] eq \"Entry\" && [$w cget -show] ne \"\"} {\n\treturn end\n    }\n    set pos [tk::endOfWord [$w get] [$w index $start]]\n    if {$pos >= 0} {\n\tset pos [tk::startOfNextWord [$w get] $pos]\n    }\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\n# ::tk::EntrySelectNextWord --\n# Returns the index of the next end-of-word position after a given\n# position in the text.\n#\n# Arguments:\n# w -\t\tThe entry window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::EntrySelectNextWord {w start} {\n    # the check on [winfo class] is because the spinbox also uses this proc\n    if {[winfo class $w] eq \"Entry\" && [$w cget -show] ne \"\"} {\n\treturn end\n    }\n    set pos [tk::endOfWord [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\n# ::tk::EntryPreviousWord --\n#\n# Returns the index of the previous word position before a given\n# position in the entry.\n#\n# Arguments:\n# w -\t\tThe entry window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::EntryPreviousWord {w start} {\n    # the check on [winfo class] is because the spinbox also uses this proc\n    if {[winfo class $w] eq \"Entry\" && [$w cget -show] ne \"\"} {\n\treturn 0\n    }\n    set pos [tk::startOfPreviousWord [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn 0\n    }\n    return $pos\n}\n\nproc ::tk::EntryNextChar {w start} {\n    set pos [tk::endOfCluster [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\nproc ::tk::EntryPreviousChar {w start} {\n    set pos [tk::startOfCluster [$w get] [expr {[$w index $start]-1}]]\n    if {$pos < 0} {\n\treturn 0\n    }\n    return $pos\n}\n\n# ::tk::EntryScanMark --\n#\n# Marks the start of a possible scan drag operation\n#\n# Arguments:\n# w -\tThe entry window from which to get the text\n# x -\tx location on screen\n\nproc ::tk::EntryScanMark {w x} {\n    $w scan mark $x\n    set ::tk::Priv(x) $x\n    set ::tk::Priv(y) 0 ; # not used\n    set ::tk::Priv(mouseMoved) 0\n}\n\n# ::tk::EntryScanDrag --\n#\n# Marks the start of a possible scan drag operation\n#\n# Arguments:\n# w -\tThe entry window from which to get the text\n# x -\tx location on screen\n\nproc ::tk::EntryScanDrag {w x} {\n    # Make sure these exist, as some weird situations can trigger the\n    # motion binding without the initial press.  [Bug #220269]\n    if {![info exists ::tk::Priv(x)]} {set ::tk::Priv(x) $x}\n    # allow for a delta\n    if {abs($x-$::tk::Priv(x)) > 2} {\n\tset ::tk::Priv(mouseMoved) 1\n    }\n    $w scan dragto $x\n}\n\n# ::tk::EntryGetSelection --\n#\n# Returns the selected text of the entry with respect to the -show option.\n#\n# Arguments:\n# w -\tThe entry window from which to get the text\n\nproc ::tk::EntryGetSelection {w} {\n    set entryString [string range [$w get] [$w index sel.first] \\\n\t    [$w index sel.last]-1]\n    if {[$w cget -show] ne \"\"} {\n\treturn [string repeat [string index [$w cget -show] 0] \\\n\t\t[string length $entryString]]\n    }\n    return $entryString\n}\n\n# ::tk::EntryScrollByUnits --\n#\n# Scrolls the entry by units.\n#\n# Arguments:\n# w -\t\tThe entry window that received a mouse wheel event.\n# axis -\tx if the event contains the Shift modifier and y otherwise.\n# amount -\tDelta value from the mouse wheel event.\n# factor -\t$amount/$factor = number of scroll units for $w xview scroll.\n\nproc ::tk::EntryScrollByUnits {w axis amount factor} {\n    # Count both the <MouseWheel> and <Shift-MouseWheel>\n    # events, and ignore the non-dominant ones\n    variable ::tk::Priv\n    incr Priv(${axis}WheelEvents)\n    if {($Priv(xWheelEvents) + $Priv(yWheelEvents) > 10) &&\n\t    ($axis eq \"x\" && $Priv(xWheelEvents) < $Priv(yWheelEvents) ||\n\t     $axis eq \"y\" && $Priv(yWheelEvents) < $Priv(xWheelEvents))} {\n\treturn\n    }\n\n    tk::MouseWheel $w x $amount $factor units\n}\n"
  },
  {
    "path": "library/fileicon.tcl",
    "content": "#   fileicons.tcl --\n#\n#   Procedures for retrieving system-native file icons if\n#   such functions are available, and a fallback set set\n#   of stock file icons for use in Tk. The SVG icons\n#   are from the Tango Project and have been placed in the public\n#   domain: http://creativecommons.org/publicdomain/zero/1.0/\n#\n\nnamespace eval ::tk::icons {\n    variable svgData\n}\n\nset ::tk::icons::svgData(archive) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   sodipodi:docname=\"package-x-generic.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg2963\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\package-x-generic.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title98\">Package Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2884\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2886\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2888\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient2869\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2871\" />\n      <stop\n         style=\"stop-color:#cccccc;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop2873\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4995\">\n      <stop\n         id=\"stop4997\"\n         offset=\"0\"\n         style=\"stop-color:#de9523;stop-opacity:1;\" />\n      <stop\n         id=\"stop4999\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#a36d18;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4987\"\n       inkscape:collect=\"always\">\n      <stop\n         id=\"stop4989\"\n         offset=\"0\"\n         style=\"stop-color:#a0670c;stop-opacity:1;\" />\n      <stop\n         id=\"stop4991\"\n         offset=\"1\"\n         style=\"stop-color:#a0670c;stop-opacity:0;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4979\">\n      <stop\n         id=\"stop4981\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fbf0e0;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4983\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f0ce99;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4222\">\n      <stop\n         id=\"stop4224\"\n         offset=\"0\"\n         style=\"stop-color:#ffffff;stop-opacity:1;\" />\n      <stop\n         id=\"stop4226\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:0.68639052;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4210\">\n      <stop\n         id=\"stop4212\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#eaba6f;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4214\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#b97a1b;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4192\">\n      <stop\n         id=\"stop4194\"\n         offset=\"0\"\n         style=\"stop-color:#e9b96e;stop-opacity:1;\" />\n      <stop\n         id=\"stop4196\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f1d19e;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4182\">\n      <stop\n         id=\"stop4184\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a36d18;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4186\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#d79020;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4979\"\n       id=\"linearGradient2269\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"30.062469\"\n       y1=\"13.444801\"\n       x2=\"17.696169\"\n       y2=\"12.333632\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4995\"\n       id=\"linearGradient2274\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"36.288929\"\n       y1=\"14.661557\"\n       x2=\"47.065835\"\n       y2=\"15.267649\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4192\"\n       id=\"linearGradient2277\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,0.986355,0,0.316638)\"\n       x1=\"25.381256\"\n       y1=\"24.720648\"\n       x2=\"24.119167\"\n       y2=\"16.170370\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4182\"\n       id=\"linearGradient2280\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,1.039184,0,-0.04057054)\"\n       x1=\"16.148972\"\n       y1=\"12.636667\"\n       x2=\"34.193642\"\n       y2=\"12.636667\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4987\"\n       id=\"linearGradient2282\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"21.906841\"\n       y1=\"9.7577486\"\n       x2=\"22.071806\"\n       y2=\"16.020695\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4222\"\n       id=\"linearGradient2285\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"18.706615\"\n       y1=\"19.912336\"\n       x2=\"30.014812\"\n       y2=\"47.388485\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4210\"\n       id=\"linearGradient2288\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"24.990499\"\n       y1=\"34.004856\"\n       x2=\"24.990499\"\n       y2=\"22.585211\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2884\"\n       id=\"radialGradient2896\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.353283,0,0,0.635968,-8.45889,3.41347)\"\n       cx=\"23.943670\"\n       cy=\"20.800287\"\n       fx=\"23.943670\"\n       fy=\"20.800287\"\n       r=\"6.4286140\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2869\"\n       id=\"radialGradient2898\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.74942,0,0,0.394055,6.226925,10.09253)\"\n       cx=\"21.578989\"\n       cy=\"9.0255041\"\n       fx=\"21.578989\"\n       fy=\"9.0255041\"\n       r=\"9.5862970\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2884\"\n       id=\"radialGradient2906\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.353283,0,0,0.635968,-8.45889,3.41347)\"\n       cx=\"23.943670\"\n       cy=\"20.800287\"\n       fx=\"23.943670\"\n       fy=\"20.800287\"\n       r=\"6.4286140\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2869\"\n       id=\"radialGradient2908\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.74942,0,0,0.394055,6.226925,10.09253)\"\n       cx=\"21.578989\"\n       cy=\"9.8105707\"\n       fx=\"21.578989\"\n       fy=\"9.8105707\"\n       r=\"9.5862970\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"142\"\n     inkscape:window-x=\"392\"\n     inkscape:window-height=\"706\"\n     inkscape:window-width=\"1207\"\n     stroke=\"#c17d11\"\n     fill=\"#e9b96e\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer1\"\n     inkscape:cy=\"159.00402\"\n     inkscape:cx=\"74.637005\"\n     inkscape:zoom=\"1\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.16470588\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Package Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>package</rdf:li>\n            <rdf:li>archive</rdf:li>\n            <rdf:li>tarball</rdf:li>\n            <rdf:li>tar</rdf:li>\n            <rdf:li>bzip</rdf:li>\n            <rdf:li>gzip</rdf:li>\n            <rdf:li>zip</rdf:li>\n            <rdf:li>arj</rdf:li>\n            <rdf:li>tar</rdf:li>\n            <rdf:li>jar</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-certificate.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-executable.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A package icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     inkscape:label=\"Layer 1\"\n     id=\"layer1\">\n    <g\n       id=\"g96\"\n       transform=\"matrix(5.3975689,0,0,5.3975749,0.95978225,-10.194381)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.60172,35.4036)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         ry=\"2.394444\"\n         rx=\"2.4241352\"\n         y=\"15.275433\"\n         x=\"7.4623847\"\n         height=\"23.112879\"\n         width=\"31.978371\"\n         id=\"rect3115\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2288);fill-opacity:1;fill-rule:nonzero;stroke:#a0670c;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.481013;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2285);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect4220\"\n         width=\"29.804138\"\n         height=\"21.075352\"\n         x=\"8.4989996\"\n         y=\"16.243698\"\n         rx=\"1.2846882\"\n         ry=\"1.2846882\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         id=\"path4162\"\n         d=\"M 8.7697819,16.547178 13.819731,9.7363408 32.615291,9.6353255 37.835264,16.408941 Z\"\n         style=\"fill:url(#linearGradient2280);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2282);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         id=\"path4164\"\n         d=\"m 38.276321,16.325703 5.192948,7.194661 H 3.9609455 l 4.6640688,-7.199601 z\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2277);fill-opacity:1;fill-rule:nonzero;stroke:#a0670c;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         id=\"path4178\"\n         d=\"m 32.849333,9.6141009 4.682886,6.9222691 9.033616,4.384827 -8.114506,-8.912652 z\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2274);fill-opacity:1;fill-rule:nonzero;stroke:#a0670c;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:#f8e8cf;fill-opacity:1;fill-rule:nonzero;stroke:#a0670c;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 13.617702,9.7151161 9.6419233,16.435355 0.50729183,20.820182 8.6217973,11.90753 Z\"\n         id=\"path4180\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#f4e3ca;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 37.024959,16.43605 4.453912,6.056961 H 5.6482792 l 4.141019,-6.180317 z\"\n         id=\"path4954\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <g\n         id=\"g2892\"\n         transform=\"matrix(0.676538,0,0,1,3.994869,0)\">\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient2896);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m 23.926073,12.101621 c -5.338008,0 -9.643504,2.028188 -9.643504,4.540192 h 19.322204 c 0,-2.512004 -4.340692,-4.540192 -9.6787,-4.540192 z\"\n           id=\"path2882\" />\n        <path\n           id=\"path2141\"\n           d=\"m 23.931961,12.861168 c -3.551975,0 -6.416904,1.34958 -6.416904,3.021098 h 12.857228 c 0,-1.671518 -2.888349,-3.021098 -6.440324,-3.021098 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient2898);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <g\n         transform=\"matrix(0.676538,0,0,1,10.49487,0)\"\n         id=\"g2900\">\n        <path\n           id=\"path2902\"\n           d=\"m 23.926073,12.101621 c -5.338008,0 -9.643504,2.028188 -9.643504,4.540192 h 19.322204 c 0,-2.512004 -4.340692,-4.540192 -9.6787,-4.540192 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient2906);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient2908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m 23.931961,12.861168 c -3.551975,0 -6.416904,1.34958 -6.416904,3.021098 h 12.857228 c 0,-1.671518 -2.888349,-3.021098 -6.440324,-3.021098 z\"\n           id=\"path2904\" />\n      </g>\n      <path\n         style=\"opacity:0.879747;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2269);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"\n         d=\"M 9.6523127,16.371803 13.036643,10.59302 33.514841,10.5178 37.356782,16.369881 Z\"\n         id=\"path4966\"\n         sodipodi:nodetypes=\"ccccc\" />\n    </g>\n  </g>\n</svg>\n}\n\n\nset ::tk::icons::svgData(audio) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   sodipodi:docname=\"audio-x-generic.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg7032\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\audio-x-generic.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title29\">Generic Audio Icon</title>\n  <defs\n     id=\"defs3\">\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2072\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2074\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2076\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2315\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2317\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2319\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2315\"\n       id=\"radialGradient1358\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,0.509804,0,16.05392)\"\n       cx=\"4.3920336\"\n       cy=\"32.307854\"\n       fx=\"4.3920336\"\n       fy=\"32.307854\"\n       r=\"6.3750000\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2315\"\n       id=\"radialGradient1360\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,0.509804,0,16.05392)\"\n       cx=\"4.3920336\"\n       cy=\"32.307854\"\n       fx=\"4.3920336\"\n       fy=\"32.307854\"\n       r=\"6.3750000\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2072\"\n       id=\"radialGradient2078\"\n       cx=\"23.250000\"\n       cy=\"35.375000\"\n       fx=\"23.250000\"\n       fy=\"35.375000\"\n       r=\"18.500000\"\n       gradientTransform=\"matrix(1,0,0,0.398649,0,21.2728)\"\n       gradientUnits=\"userSpaceOnUse\" />\n  </defs>\n  <sodipodi:namedview\n     fill=\"#9db029\"\n     inkscape:window-y=\"160\"\n     inkscape:window-x=\"219\"\n     inkscape:window-height=\"688\"\n     inkscape:window-width=\"1363\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer1\"\n     inkscape:cy=\"107.23623\"\n     inkscape:cx=\"73.976692\"\n     inkscape:zoom=\"1.4142136\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.22745098\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Generic Audio Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/audio-x-generic.svg</dc:identifier>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-executable.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>audio</rdf:li>\n            <rdf:li>music</rdf:li>\n            <rdf:li>note</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for audio or music.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     inkscape:label=\"Layer 1\"\n     id=\"layer1\">\n    <g\n       id=\"g27\"\n       transform=\"matrix(6.6336623,0,0,6.6336747,-26.352024,-47.393711)\">\n      <ellipse\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.3;fill:url(#radialGradient2078);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path1344\"\n         transform=\"translate(0,2.834646)\"\n         cx=\"23.25\"\n         cy=\"35.375\"\n         rx=\"18.5\"\n         ry=\"7.375\" />\n      <path\n         sodipodi:nodetypes=\"cccccccccccccc\"\n         id=\"path7042\"\n         d=\"m 41.625,7.7951523 c 0,0 -23.0625,2.8346457 -23.0625,2.8346457 v 21.78125 c -1.645955,-0.557651 -3.931785,-0.703429 -6.4375,-0.1875 -4.356314,0.896969 -7.4778602,3.299487 -7,5.34375 0.4778601,2.044263 4.393685,2.99072 8.75,2.09375 4.116641,-0.84762 7.684123,-3.037802 7.602633,-5 l 0.15625,-19.03125 c 0,0 16.930457,-2.895306 16.930457,-2.895306 v 17.284614 c -10.25,-1.5 -13.292201,2.893236 -12.81434,4.9375 0.47786,2.044263 4.393686,2.990719 8.75,2.09375 3.865376,-0.795885 6.63241,-2.763211 6.90625,-4.625 z\"\n         style=\"color:#000000;display:block;visibility:visible;fill:#9db029;fill-opacity:1;fill-rule:nonzero;stroke:#596616;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:block;visibility:visible;opacity:0.511765;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 40.729036,8.8956383 c 0,0 -21.181769,2.8346457 -21.181769,2.8346457 V 33.568621 C 11.982012,31.663311 5.8141632,35.40303 6.2685944,37.347065 6.9730255,40.6661 20.646969,38.449299 20.569474,34.208305 l 0.148589,-19.473166 c 0,0 18.850374,-2.892332 18.850374,-2.892332 v 19.437166 c -7.566284,-1.926647 -13.265498,1.376384 -12.811066,3.32042 0.579431,3.194035 12.378226,2.113362 13.76364,-2.657146 z\"\n         id=\"path2311\"\n         sodipodi:nodetypes=\"ccccccccccc\" />\n      <ellipse\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.511765;fill:url(#radialGradient1358);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path2313\"\n         transform=\"matrix(0.734516,-0.111645,0.111645,0.734516,3.903362,12.22551)\"\n         cx=\"5.875\"\n         cy=\"32.75\"\n         rx=\"6.375\"\n         ry=\"3.25\" />\n      <ellipse\n         transform=\"matrix(0.734516,-0.111645,0.111645,0.734516,23.74587,9.390864)\"\n         id=\"path2323\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.511765;fill:url(#radialGradient1360);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"5.875\"\n         cy=\"32.75\"\n         rx=\"6.375\"\n         ry=\"3.25\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(binary) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg249\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"text-x-generic-template.svg\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\text-x-generic-template.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title115\">Document Template Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       id=\"linearGradient3531\">\n      <stop\n         id=\"stop3533\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#000000;stop-opacity:0.092783503;\" />\n      <stop\n         id=\"stop3535\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#000000;stop-opacity:0.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient3519\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop3521\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop3523\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop15664\" />\n      <stop\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop15666\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop270\" />\n      <stop\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop271\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop260\" />\n      <stop\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop261\" />\n    </linearGradient>\n    <radialGradient\n       r=\"37.751713\"\n       fy=\"3.7561285\"\n       fx=\"8.8244190\"\n       cy=\"3.7561285\"\n       cx=\"8.8244190\"\n       gradientTransform=\"matrix(5.4842984,0,0,5.8495924,10.418489,-13.159996)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15656\"\n       xlink:href=\"#linearGradient269\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"86.708450\"\n       fy=\"35.736916\"\n       fx=\"33.966679\"\n       cy=\"35.736916\"\n       cx=\"33.966679\"\n       gradientTransform=\"matrix(5.4402324,0,0,5.8969718,-8.576036,-16.821472)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15658\"\n       xlink:href=\"#linearGradient259\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"38.158695\"\n       fy=\"7.2678967\"\n       fx=\"8.1435566\"\n       cy=\"7.2678967\"\n       cx=\"8.1435566\"\n       gradientTransform=\"matrix(5.4842984,0,0,5.8495924,10.418489,-13.159996)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15668\"\n       xlink:href=\"#linearGradient15662\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient3519\"\n       id=\"linearGradient3525\"\n       gradientTransform=\"matrix(3.7866389,0,0,8.4721264,-8.576036,-16.821472)\"\n       x1=\"57.643562\"\n       y1=\"8.6012535\"\n       x2=\"34.242393\"\n       y2=\"21.033955\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient3531\"\n       id=\"linearGradient3529\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-3.7866389,0,0,8.4721264,262.76633,-16.821472)\"\n       x1=\"57.643562\"\n       y1=\"8.6012535\"\n       x2=\"39.081673\"\n       y2=\"20.923300\" />\n  </defs>\n  <sodipodi:namedview\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.21568627\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"2\"\n     inkscape:cx=\"-4.6258547\"\n     inkscape:cy=\"128.3816\"\n     inkscape:current-layer=\"layer5\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:window-width=\"1696\"\n     inkscape:window-height=\"861\"\n     inkscape:window-x=\"130\"\n     inkscape:window-y=\"30\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Document Template Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>certificate</rdf:li>\n            <rdf:li>stamp</rdf:li>\n            <rdf:li>seal</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic-template.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A document template icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     style=\"display:inline\"\n     inkscape:label=\"Text\"\n     id=\"layer5\"\n     inkscape:groupmode=\"layer\">\n    <g\n       style=\"display:inline\"\n       transform=\"matrix(0.11925331,0,0,0.11819398,234.13612,216.27252)\"\n       id=\"g6707\">\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect6709\"\n         width=\"1339.6335\"\n         height=\"478.35718\"\n         x=\"-1559.2523\"\n         y=\"-150.69685\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n         id=\"path6711\"\n         sodipodi:nodetypes=\"cccc\" />\n      <path\n         sodipodi:nodetypes=\"cccc\"\n         id=\"path6713\"\n         d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n    </g>\n    <rect\n       ry=\"6.5082111\"\n       y=\"3.832\"\n       x=\"28.826488\"\n       height=\"231.77368\"\n       width=\"197.532\"\n       id=\"rect15391\"\n       style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:5.664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n    <rect\n       rx=\"0.8442111\"\n       ry=\"0.8442111\"\n       y=\"9.1420002\"\n       x=\"34.844494\"\n       height=\"220.59233\"\n       width=\"185.64262\"\n       id=\"rect15660\"\n       style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:5.664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n    <g\n       id=\"g3405\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,-16.821472)\">\n      <circle\n         id=\"path3401\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3403\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3409\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,5.8345284)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3411\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3413\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,28.490529)\"\n       id=\"g3415\">\n      <circle\n         id=\"path3417\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3419\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3421\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,51.14653)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3423\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3425\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,73.80253)\"\n       id=\"g3427\">\n      <circle\n         id=\"path3429\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3431\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3433\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,96.458531)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3435\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3437\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,119.11453)\"\n       id=\"g3439\">\n      <circle\n         id=\"path3441\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3443\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3445\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,141.77053)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3447\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3449\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-15.084227,164.42653)\"\n       id=\"g3451\">\n      <circle\n         id=\"path3453\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3455\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3457\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-28.41474,17.162529)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3459\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3461\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-1.7537025,17.162529)\"\n       id=\"g3463\">\n      <circle\n         id=\"path3465\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3467\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3469\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,9.5742977,51.14653)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3471\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3473\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,20.902298,85.130531)\"\n       id=\"g3475\">\n      <circle\n         id=\"path3477\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3479\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3481\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,32.230298,119.11453)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3483\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3485\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,43.558151,153.09853)\"\n       id=\"g3487\">\n      <circle\n         id=\"path3489\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3491\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-39.742865,51.14653)\"\n       id=\"g3493\">\n      <circle\n         id=\"path3495\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3497\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3499\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-51.070865,85.130531)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3501\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3503\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       transform=\"matrix(5.6640001,0,0,5.6640001,-62.398888,119.11453)\"\n       id=\"g3505\">\n      <circle\n         id=\"path3507\"\n         style=\"fill:#ffffff;fill-opacity:1\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         transform=\"translate(-0.353553,-0.265165)\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         id=\"path3509\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <g\n       id=\"g3511\"\n       transform=\"matrix(5.6640001,0,0,5.6640001,-73.726934,153.09853)\">\n      <circle\n         style=\"fill:#ffffff;fill-opacity:1\"\n         id=\"path3513\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n      <circle\n         id=\"path3515\"\n         style=\"fill:#000000;fill-opacity:0.111111\"\n         transform=\"translate(-0.353553,-0.265165)\"\n         cx=\"25.19068\"\n         cy=\"8.5787964\"\n         r=\"1.1490486\" />\n    </g>\n    <path\n       style=\"fill:url(#linearGradient3525);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.664px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n       d=\"M 121.08756,10.742307 195.18104,230.01895 220.21262,229.51832 219.71199,8.2391485 Z\"\n       id=\"path3517\" />\n    <path\n       id=\"path3527\"\n       d=\"M 126.5945,11.743571 51.499753,227.01516 H 36.98144 l -2e-6,-215.27159 z\"\n       style=\"fill:url(#linearGradient3529);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.664px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n       sodipodi:nodetypes=\"ccccc\" />\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(calendar) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\x-office-calendar.png\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg11300\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"x-office-calendar.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title165\">Calendar Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       id=\"linearGradient4604\">\n      <stop\n         style=\"stop-color:#383936;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4606\" />\n      <stop\n         style=\"stop-color:#555753;stop-opacity:1;\"\n         offset=\"1\"\n         id=\"stop4608\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient6105\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6107\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop6109\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient6087\">\n      <stop\n         style=\"stop-color:#2e3436;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6089\" />\n      <stop\n         style=\"stop-color:#2e3436;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop6091\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient2224\">\n      <stop\n         style=\"stop-color:#7c7c7c;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2226\" />\n      <stop\n         style=\"stop-color:#b8b8b8;stop-opacity:1;\"\n         offset=\"1\"\n         id=\"stop2228\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2224\"\n       id=\"linearGradient6055\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.734574,0,0,0.73094,13.14657,3.97815)\"\n       x1=\"35.996582\"\n       y1=\"40.458221\"\n       x2=\"33.664921\"\n       y2=\"37.770721\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2251\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2253\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2255\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2251\"\n       id=\"linearGradient6052\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.734574,0,0,0.73094,13.35394,3.76021)\"\n       x1=\"33.396004\"\n       y1=\"36.921333\"\n       x2=\"34.170048\"\n       y2=\"38.070381\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4776\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4778\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop4780\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4748\">\n      <stop\n         style=\"stop-color:#999a98;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4750\" />\n      <stop\n         id=\"stop4760\"\n         offset=\"0.5\"\n         style=\"stop-color:#caccc8;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:#616161;stop-opacity:1;\"\n         offset=\"1\"\n         id=\"stop4752\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4693\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4695\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop4697\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4537\">\n      <stop\n         id=\"stop6075\"\n         offset=\"0\"\n         style=\"stop-color:#ffffff;stop-opacity:1;\" />\n      <stop\n         id=\"stop6073\"\n         offset=\"1\"\n         style=\"stop-color:#e6e6e6;stop-opacity:1;\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4537\"\n       id=\"linearGradient4543\"\n       x1=\"37.270947\"\n       y1=\"27.272932\"\n       x2=\"35.871902\"\n       y2=\"22.67392\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.125982,0,0,1.272791,-4.167995,-7.706526)\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4693\"\n       id=\"radialGradient4699\"\n       cx=\"12.887021\"\n       cy=\"16.771133\"\n       fx=\"12.887021\"\n       fy=\"16.771133\"\n       r=\"1.5909903\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.944444,0,0,1.944444,-12.77212,-16.7839)\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4693\"\n       id=\"radialGradient4705\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.944444,0,0,1.944444,-12.77212,-16.7839)\"\n       cx=\"12.887021\"\n       cy=\"16.771133\"\n       fx=\"12.887021\"\n       fy=\"16.771133\"\n       r=\"1.5909903\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4693\"\n       id=\"radialGradient4712\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.944444,0,0,1.944444,-12.77212,-16.7839)\"\n       cx=\"12.887021\"\n       cy=\"16.771133\"\n       fx=\"12.887021\"\n       fy=\"16.771133\"\n       r=\"1.5909903\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4748\"\n       id=\"linearGradient4744\"\n       x1=\"10.998293\"\n       y1=\"11.928971\"\n       x2=\"14.539844\"\n       y2=\"13.486036\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4748\"\n       id=\"linearGradient4764\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"10.998293\"\n       y1=\"11.928971\"\n       x2=\"14.539844\"\n       y2=\"13.486036\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4748\"\n       id=\"linearGradient4772\"\n       x1=\"24.03125\"\n       y1=\"7.53125\"\n       x2=\"24.03125\"\n       y2=\"15.53125\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.125982,0,0,1.126747,-4.079607,-5.365805)\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4776\"\n       id=\"radialGradient4782\"\n       cx=\"13.832776\"\n       cy=\"17.903767\"\n       fx=\"13.832776\"\n       fy=\"17.903767\"\n       r=\"1.8119612\"\n       gradientTransform=\"matrix(1,0,0,2.02439,0,-18.34044)\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4776\"\n       id=\"radialGradient4786\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,2.02439,0,-18.34044)\"\n       cx=\"13.832776\"\n       cy=\"17.903767\"\n       fx=\"13.832776\"\n       fy=\"17.903767\"\n       r=\"1.8119612\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4776\"\n       id=\"radialGradient4790\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1,0,0,2.02439,0,-18.34044)\"\n       cx=\"13.832776\"\n       cy=\"17.903767\"\n       fx=\"13.832776\"\n       fy=\"17.903767\"\n       r=\"1.8119612\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6087\"\n       id=\"linearGradient6093\"\n       x1=\"23.20356\"\n       y1=\"24.077753\"\n       x2=\"30.741646\"\n       y2=\"36.054375\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6105\"\n       id=\"radialGradient6111\"\n       cx=\"12.993087\"\n       cy=\"18.399908\"\n       fx=\"12.993087\"\n       fy=\"18.399908\"\n       r=\"2.1617265\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6105\"\n       id=\"radialGradient6115\"\n       gradientUnits=\"userSpaceOnUse\"\n       cx=\"12.993087\"\n       cy=\"18.399908\"\n       fx=\"12.993087\"\n       fy=\"18.399908\"\n       r=\"2.1617265\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6105\"\n       id=\"radialGradient6119\"\n       gradientUnits=\"userSpaceOnUse\"\n       cx=\"12.993087\"\n       cy=\"18.399908\"\n       fx=\"12.993087\"\n       fy=\"18.399908\"\n       r=\"2.1617265\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4604\"\n       id=\"linearGradient4610\"\n       x1=\"25.348972\"\n       y1=\"37.548233\"\n       x2=\"25.348972\"\n       y2=\"39.750675\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.951156,0,0,1,1.172114,0)\" />\n  </defs>\n  <sodipodi:namedview\n     stroke=\"#ef2929\"\n     fill=\"#eeeeec\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.25490196\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"2\"\n     inkscape:cx=\"102.3483\"\n     inkscape:cy=\"127.91627\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:window-width=\"1265\"\n     inkscape:window-height=\"818\"\n     inkscape:window-x=\"0\"\n     inkscape:window-y=\"30\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:title>Calendar Icon</dc:title>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-calendar.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-document.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>calendar</rdf:li>\n            <rdf:li>date</rdf:li>\n            <rdf:li>diary</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A calendar, date or diary icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Layer 1\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g163\"\n       transform=\"matrix(5.9029717,0,0,5.9029652,-13.189671,-12.63677)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.67494,38.5019)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient4610);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 7.1903818,30.619256 6.9579435,41.499992 H 41.036463 L 40.503612,28.827804 Z\"\n         id=\"path4535\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.230769;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 7.5296067,37.613897 7.3305593,41 H 41.314314 L 7.8281776,40.502043 Z\"\n         id=\"path6079\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path8616\"\n         d=\"M 6.8123473,11.277009 H 39.685523 l 3.333144,25.687105 H 5.0307392 Z\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:#cacaca;fill-opacity:1;fill-rule:evenodd;stroke:#686868;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient4543);fill-opacity:1;fill-rule:evenodd;stroke:#868a84;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 6.1824687,8.5000038 H 39.920999 L 43.341885,35.500012 H 4.3539614 Z\"\n         id=\"path3660\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path4545\"\n         d=\"M 7.12847,9.5000031 H 39.02851 L 42.073547,34.500001 H 5.423245 Z\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.208791;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 42.811018,35.038881 42.089624,29.15164 35.826652,35.061723 Z\"\n         id=\"path6077\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"cccc\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.335165;fill:url(#radialGradient4790);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path4788\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(1.620316,0,0,1.126747,0.837299,-7.689396)\"\n         cx=\"13.832776\"\n         cy=\"17.903767\"\n         rx=\"1.8119612\"\n         ry=\"3.6681163\" />\n      <path\n         transform=\"matrix(1.125982,0,0,0.958072,19.31959,-5.288202)\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path4784\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.335165;fill:url(#radialGradient4786);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"13.832776\"\n         cy=\"17.903767\"\n         rx=\"1.8119612\"\n         ry=\"3.6681163\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.335165;fill:url(#radialGradient4782);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path4774\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(1.125982,0,0,1.054458,-4.566089,-6.660313)\"\n         cx=\"13.832776\"\n         cy=\"17.903767\"\n         rx=\"1.8119612\"\n         ry=\"3.6681163\" />\n      <path\n         style=\"font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:14px;line-height:100%;font-family:Segoe;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient6093);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         d=\"M 19.718956,29.3237 H 17.369387 V 18.734619 l -2.985543,0.901573 v -1.988767 l 5.335112,-1.467268 V 29.3237 m 12.30432,0 H 23.967612 V 27.441 c 2.632219,-2.66347 4.124989,-4.180826 4.478314,-4.552069 0.3592,-0.37712 0.6448,-0.771927 0.856797,-1.18442 0.217873,-0.41837 0.326813,-0.872103 0.32682,-1.361201 -7e-6,-0.565684 -0.185499,-1.019417 -0.556477,-1.361201 -0.365102,-0.347655 -0.877414,-0.521488 -1.536937,-0.521498 -0.429874,10e-6 -0.90391,0.114916 -1.422107,0.344718 -0.518203,0.223931 -0.986348,0.539188 -1.404441,0.94577 v -2.377682 c 1.16006,-0.671748 2.258291,-1.007629 3.294696,-1.007643 1.23072,1.4e-5 2.193513,0.330002 2.88838,0.989965 0.70074,0.654096 1.051113,1.558615 1.051122,2.713563 -9e-6,0.713018 -0.200222,1.434867 -0.600642,2.165547 -0.394546,0.730694 -0.992243,1.467273 -1.793092,2.209741 l -3.118037,2.90802 h 5.591268 v 1.97109\"\n         id=\"text4581\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <path\n         transform=\"matrix(1.1813,0,0,1.182048,-4.864643,-6.422489)\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path6095\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient6111);stroke-width:0.846257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4699);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path4691\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(0.875764,0,0,0.876359,-0.916889,-1.31427)\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n      <path\n         transform=\"matrix(0.875764,0,0,0.876359,23.09141,-1.31427)\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path4703\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4705);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n      <path\n         transform=\"matrix(-0.783152,0,0,1.126747,45.83291,-5.199614)\"\n         sodipodi:end=\"0.0068021928\"\n         sodipodi:start=\"1.6592322\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         d=\"m 14.411076,16.251658 a 1.4584079,4.3310289 0 0 1 -1.326868,-4.579104 1.4584079,4.3310289 0 0 1 1.505271,-4.0635235 1.4584079,4.3310289 0 0 1 1.408779,4.3579845 l -1.458374,-0.02946 z\"\n         sodipodi:ry=\"4.3310289\"\n         sodipodi:rx=\"1.4584079\"\n         sodipodi:cy=\"11.937554\"\n         sodipodi:cx=\"14.539884\"\n         id=\"path4701\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4744);stroke-width:1.59682;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         sodipodi:type=\"arc\"\n         sodipodi:arc-type=\"slice\" />\n      <path\n         sodipodi:type=\"arc\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4764);stroke-width:1.33172;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path4762\"\n         sodipodi:cx=\"14.539884\"\n         sodipodi:cy=\"11.937554\"\n         sodipodi:rx=\"1.4584079\"\n         sodipodi:ry=\"4.3310289\"\n         d=\"m 14.411076,16.251658 a 1.4584079,4.3310289 0 0 1 -1.326868,-4.579104 1.4584079,4.3310289 0 0 1 1.505271,-4.0635235 1.4584079,4.3310289 0 0 1 1.408779,4.3579845 l -1.458374,-0.02946 z\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:start=\"1.6592322\"\n         sodipodi:end=\"0.0068021928\"\n         transform=\"matrix(1.125982,0,0,1.126747,-5.884205,-5.199614)\"\n         sodipodi:arc-type=\"slice\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:#868a84;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect4707\"\n         width=\"24.582342\"\n         height=\"1\"\n         x=\"10.417658\"\n         y=\"8\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4712);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path4710\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(0.875764,0,0,0.876359,11.61742,-1.366726)\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient4772);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect4714\"\n         width=\"2.3223372\"\n         height=\"11.47873\"\n         x=\"21.817968\"\n         y=\"2.3101559\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         rx=\"1.03125\"\n         ry=\"1.03125\" />\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient6055);fill-opacity:1;fill-rule:evenodd;stroke:#868a84;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 34.917822,35.178277 c 2.33118,0.152747 7.618199,-2.824971 7.129444,-6.609161 -1.148332,1.771138 -3.495486,0.85214 -6.513672,0.968367 0,0 0.378815,5.098548 -0.615772,5.640794 z\"\n         id=\"path2210\"\n         sodipodi:nodetypes=\"cccc\" />\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         sodipodi:nodetypes=\"cccc\"\n         id=\"path2247\"\n         d=\"m 36.5,33.5 c 1.006203,-0.499838 3.252875,-1.568937 4.207366,-2.943838 -1.216643,0.276108 -2.12119,0.06474 -4.144591,0.05079 0,0 0.07504,2.326596 -0.06278,2.893052 z\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.369318;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6052);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.554945;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path6081\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(0.592592,0,0,0.592592,9.076399,1.51852)\"\n         cx=\"22.96875\"\n         cy=\"5.03125\"\n         r=\"0.84375\" />\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path6083\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.554945;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         transform=\"matrix(0.62963,0,0,0.62963,-4.993064,1.363424)\"\n         cx=\"22.96875\"\n         cy=\"5.03125\"\n         r=\"0.84375\" />\n      <path\n         transform=\"matrix(0.62963,0,0,0.62963,20.88194,1.363424)\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.554945;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path6085\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         cx=\"22.96875\"\n         cy=\"5.03125\"\n         r=\"0.84375\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient6115);stroke-width:0.846257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path6113\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(1.1813,0,0,1.182048,7.664405,-6.422489)\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n      <path\n         transform=\"matrix(1.1813,0,0,1.182048,19.17699,-6.422489)\"\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path6117\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient6119);stroke-width:0.846257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"12.993087\"\n         cy=\"16.710526\"\n         r=\"1.5909903\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(drawing) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\x-office-drawing.png\"\n   sodipodi:docname=\"x-office-drawing.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg249\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title160\">Office Drawing Document Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient14019\">\n      <stop\n         style=\"stop-color:white;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop14021\" />\n      <stop\n         style=\"stop-color:white;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop14023\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient7648\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"21.9326\"\n       y1=\"24.6274\"\n       x2=\"21.9326\"\n       y2=\"7.1091\"\n       style=\"stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#8595bc;stop-opacity:1;\"\n         id=\"stop7650\" />\n      <stop\n         offset=\"1\"\n         style=\"stop-color:#041a3b;stop-opacity:1;\"\n         id=\"stop7652\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         id=\"stop15664\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop15666\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         id=\"stop270\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop271\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         id=\"stop260\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop261\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient269\"\n       id=\"radialGradient15656\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(5.4842984,0,0,5.8495924,6.1685035,-13.159996)\"\n       cx=\"8.8244190\"\n       cy=\"3.7561285\"\n       fx=\"8.8244190\"\n       fy=\"3.7561285\"\n       r=\"37.751713\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient259\"\n       id=\"radialGradient15658\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(5.4402324,0,0,5.8969718,-12.826021,-16.821472)\"\n       cx=\"33.966679\"\n       cy=\"35.736916\"\n       fx=\"33.966679\"\n       fy=\"35.736916\"\n       r=\"86.708450\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient15662\"\n       id=\"radialGradient15668\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(5.4842984,0,0,5.8495924,6.1685035,-13.159996)\"\n       cx=\"8.1435566\"\n       cy=\"7.2678967\"\n       fx=\"8.1435566\"\n       fy=\"7.2678967\"\n       r=\"38.158695\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7648\"\n       id=\"linearGradient14055\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.098989,0,0,-0.797757,-1.953865,37.324)\"\n       x1=\"21.9326\"\n       y1=\"24.627399\"\n       x2=\"21.9326\"\n       y2=\"7.1090999\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient14019\"\n       id=\"linearGradient14085\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"28.125\"\n       y1=\"9.5398483\"\n       x2=\"29.341478\"\n       y2=\"40.882267\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"37\"\n     inkscape:window-x=\"151\"\n     inkscape:window-height=\"931\"\n     inkscape:window-width=\"1370\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"true\"\n     inkscape:current-layer=\"layer5\"\n     inkscape:cy=\"110.28706\"\n     inkscape:cx=\"99.627404\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.25490196\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:showpageshadow=\"false\"\n     fill=\"#729fcf\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Office Drawing Document Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>rich</rdf:li>\n            <rdf:li>text</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>pdf</rdf:li>\n            <rdf:li>openoffice</rdf:li>\n            <rdf:li>word</rdf:li>\n            <rdf:li>rtf</rdf:li>\n            <rdf:li>office</rdf:li>\n            <rdf:li>template</rdf:li>\n            <rdf:li>drawing</rdf:li>\n            <rdf:li>edit</rdf:li>\n            <rdf:li>editing</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-drawing.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-document.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for a drawing document.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     id=\"layer5\"\n     inkscape:label=\"Text\"\n     style=\"display:inline\">\n    <g\n       id=\"g158\"\n       transform=\"translate(4.249985)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.11925331,0,0,0.11819398,229.88613,216.27252)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:5.664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15391\"\n         width=\"197.532\"\n         height=\"231.77368\"\n         x=\"24.576504\"\n         y=\"3.832\"\n         ry=\"6.5082111\" />\n      <g\n         id=\"g5376\"\n         style=\"display:inline;opacity:1\"\n         transform=\"matrix(5.6640001,0,0,5.6640001,-40.481538,46.535014)\">\n        <g\n           transform=\"matrix(0.608982,0,0,0.606219,12.8233,10.5572)\"\n           id=\"g7654\">\n          <path\n             style=\"fill:url(#linearGradient14055);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n             d=\"M 5.512695,30 H 39.643234 V 19.627375 H 5.512695 Z\"\n             id=\"path7644\" />\n          <path\n             id=\"path16203\"\n             d=\"M 5.512695,5.6791358 H 39.643234 V 19.627375 H 5.512695 Z\"\n             style=\"fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <g\n             transform=\"matrix(1.189217,0,0,1.189217,-3.525355,-6.535408)\"\n             style=\"fill-rule:nonzero;stroke:#000000;stroke-width:2.00242;stroke-miterlimit:4\"\n             id=\"g16205\">\n            <g\n               id=\"g16207\">\n              <path\n                 id=\"path16209\"\n                 d=\"m 18.4,15.4 c 0,2.2 -1.8,4.1 -4.1,4.1 -2.2,0 -4.1,-1.8 -4.1,-4.1 0,-2.2 1.8,-4.1 4.1,-4.1 2.2,0 4.1,1.8 4.1,4.1 z\"\n                 style=\"opacity:0.0499999;fill:#e8f52f;stroke:none\" />\n              <path\n                 id=\"path16211\"\n                 d=\"m 18,15.4 c 0,2 -1.6,3.7 -3.7,3.7 -2,0 -3.7,-1.6 -3.7,-3.7 0,-2 1.6,-3.7 3.7,-3.7 2,0 3.7,1.6 3.7,3.7 z\"\n                 style=\"opacity:0.2083;fill:#ecf751;stroke:none\" />\n              <path\n                 id=\"path16213\"\n                 d=\"m 17.6,15.4 c 0,1.8 -1.5,3.3 -3.3,3.3 -1.8,0 -3.3,-1.5 -3.3,-3.3 0,-1.8 1.5,-3.3 3.3,-3.3 1.8,0 3.3,1.5 3.3,3.3 z\"\n                 style=\"opacity:0.3667;fill:#f0f972;stroke:none\" />\n              <path\n                 id=\"path16215\"\n                 d=\"m 17.2,15.4 c 0,1.6 -1.3,2.9 -2.9,2.9 -1.6,0 -2.9,-1.3 -2.9,-2.9 0,-1.6 1.3,-2.9 2.9,-2.9 1.6,0 2.9,1.3 2.9,2.9 z\"\n                 style=\"opacity:0.525;fill:#f4fa95;stroke:none\" />\n              <path\n                 id=\"path16217\"\n                 d=\"m 16.8,15.4 c 0,1.4 -1.1,2.5 -2.5,2.5 -1.4,0 -2.5,-1.1 -2.5,-2.5 0,-1.4 1.1,-2.5 2.5,-2.5 1.4,0 2.5,1.1 2.5,2.5 z\"\n                 style=\"opacity:0.6833;fill:#f7fcb7;stroke:none\" />\n              <path\n                 id=\"path16219\"\n                 d=\"m 16.4,15.4 c 0,1.2 -1,2.1 -2.1,2.1 -1.1,0 -2.1,-1 -2.1,-2.1 0,-1.1 1,-2.1 2.1,-2.1 1.1,0 2.1,1 2.1,2.1 z\"\n                 style=\"opacity:0.8417;fill:#fbfddb;stroke:none\" />\n              <path\n                 id=\"path16221\"\n                 d=\"m 16,15.4 c 0,1 -0.8,1.8 -1.8,1.8 -1,0 -1.8,-0.8 -1.8,-1.8 0,-1 0.8,-1.8 1.8,-1.8 1,0 1.8,0.8 1.8,1.8 z\"\n                 style=\"fill:#ffffff;stroke:none\" />\n            </g>\n          </g>\n          <path\n             id=\"path16223\"\n             d=\"m 25.015859,21.649044 h 8.681289 l 1.664904,0.475688 h -2.854121 c 0,0 2.854121,0.237842 4.281184,2.021669 1.427059,1.664904 -1.664905,3.686575 -1.664905,3.686575 0,0 0,0 0,0 -0.118922,-0.356766 -0.832454,-3.210889 -2.259514,-4.400106 -1.070297,-0.951374 -2.259514,-1.189218 -2.259514,-1.189218 h -5.589323 v -0.475686 z\"\n             style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16225\"\n             d=\"m 30.724106,22.362574 h -4.994715 l 9.275897,5.232557 z\"\n             style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16227\"\n             d=\"m 25.015859,21.767966 h 8.681289 l 1.30814,-0.832453 h -2.854121 c 0,0 2.616276,-0.475686 2.973043,-3.448731 0.356763,-2.973043 -4.043341,-6.302851 -4.043341,-6.302851 0,0 0,0 0,0.118922 0.118921,0.71353 1.308138,5.708243 0.475688,7.610993 -0.356767,1.664901 -1.427062,2.021667 -1.427062,2.021667 h -5.470401 l 0.237844,0.832453 z\"\n             style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16229\"\n             d=\"M 30.248418,20.459827 H 25.253704 L 31.19979,11.421773 Z\"\n             style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n        </g>\n        <rect\n           y=\"14.485752\"\n           x=\"16.508501\"\n           height=\"13.997463\"\n           width=\"19.995502\"\n           id=\"rect8163\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#9e9e9e;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:5.664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15660\"\n         width=\"185.64262\"\n         height=\"220.59233\"\n         x=\"30.594509\"\n         y=\"9.1420002\"\n         ry=\"0.8442111\"\n         rx=\"0.8442111\" />\n      <g\n         id=\"g14073\"\n         style=\"opacity:0.601124\"\n         transform=\"matrix(5.6640001,0,0,5.6640001,-18.490021,-11.157472)\">\n        <rect\n           y=\"7\"\n           x=\"15\"\n           height=\"1.9999999\"\n           width=\"2\"\n           id=\"rect14027\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect14029\"\n           width=\"2\"\n           height=\"1.9999999\"\n           x=\"37\"\n           y=\"7\" />\n        <rect\n           y=\"29\"\n           x=\"37\"\n           height=\"1.9999999\"\n           width=\"2\"\n           id=\"rect14031\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect14035\"\n           width=\"2\"\n           height=\"1.9999999\"\n           x=\"15\"\n           y=\"29\" />\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect14057\"\n           width=\"1\"\n           height=\"1\"\n           x=\"15.116116\"\n           y=\"18\" />\n        <rect\n           y=\"18\"\n           x=\"38\"\n           height=\"1\"\n           width=\"1\"\n           id=\"rect14059\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           transform=\"rotate(90)\"\n           y=\"-28\"\n           x=\"7\"\n           height=\"1\"\n           width=\"1\"\n           id=\"rect14061\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           transform=\"rotate(90)\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect14063\"\n           width=\"1\"\n           height=\"1\"\n           x=\"29.883884\"\n           y=\"-28\" />\n        <circle\n           transform=\"matrix(0.974684,0,0,0.974684,-0.412975,2.183544)\"\n           id=\"path14015\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#73d216;fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1.02597;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           cx=\"28.125\"\n           cy=\"17.125\"\n           r=\"9.875\" />\n        <circle\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.280899;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient14085);stroke-width:1.14493;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"path14017\"\n           transform=\"matrix(0.873417,0,0,0.873417,2.43515,3.917736)\"\n           cx=\"28.125\"\n           cy=\"17.125\"\n           r=\"9.875\" />\n      </g>\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(executable) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg53383\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"application-x-executable.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\application-x-executable.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title59\">Executable Icon</title>\n  <defs\n     id=\"defs3\">\n    <linearGradient\n       id=\"linearGradient2300\">\n      <stop\n         id=\"stop2302\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#000000;stop-opacity:0.32673267;\" />\n      <stop\n         id=\"stop2304\"\n         offset=\"1\"\n         style=\"stop-color:#000000;stop-opacity:0;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"aigrd1\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"99.7773\"\n       y1=\"15.4238\"\n       x2=\"153.0005\"\n       y2=\"248.6311\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#184375\"\n         id=\"stop53300\" />\n      <stop\n         offset=\"1\"\n         style=\"stop-color:#C8BDDC\"\n         id=\"stop53302\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd1\"\n       id=\"linearGradient53551\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"99.7773\"\n       y1=\"15.4238\"\n       x2=\"153.0005\"\n       y2=\"248.6311\"\n       gradientTransform=\"matrix(0.200685,0,0,0.200685,-0.585758,-1.050787)\" />\n    <radialGradient\n       gradientUnits=\"userSpaceOnUse\"\n       r=\"11.689870\"\n       fy=\"72.568001\"\n       fx=\"14.287618\"\n       cy=\"68.872971\"\n       cx=\"14.287618\"\n       gradientTransform=\"matrix(1.399258,-2.234445e-7,8.196178e-8,0.513264,4.365074,4.839285)\"\n       id=\"radialGradient2308\"\n       xlink:href=\"#linearGradient2300\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       gradientUnits=\"userSpaceOnUse\"\n       r=\"11.68987\"\n       fy=\"72.568001\"\n       fx=\"14.287618\"\n       cy=\"68.872971\"\n       cx=\"14.287618\"\n       gradientTransform=\"matrix(7.9986369,-7.6544412e-7,4.6852155e-7,1.7582661,13.364939,91.95326)\"\n       id=\"radialGradient2308-6\"\n       xlink:href=\"#linearGradient2300\"\n       inkscape:collect=\"always\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:showpageshadow=\"false\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"1.0\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"1.4142136\"\n     inkscape:cx=\"96.810364\"\n     inkscape:cy=\"111.58696\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:window-width=\"1481\"\n     inkscape:window-height=\"737\"\n     inkscape:window-x=\"414\"\n     inkscape:window-y=\"151\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Executable Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>executable</rdf:li>\n            <rdf:li>program</rdf:li>\n            <rdf:li>binary</rdf:li>\n            <rdf:li>bin</rdf:li>\n            <rdf:li>script</rdf:li>\n            <rdf:li>shell</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-executable.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-certificate.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>Am icon for a program or executable resource.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Layer 1\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g57\"\n       transform=\"matrix(1.0596739,0,0,1.0596738,-7.5471033,-1.1193476)\">\n      <g\n         id=\"g30\"\n         transform=\"matrix(5.3716008,0,0,5.3715967,-2.8368372,-13.444145)\">\n        <path\n           style=\"fill:url(#linearGradient53551);fill-rule:nonzero;stroke:#3f4561;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1\"\n           d=\"M 24.285801,43.196358 4.3751874,23.285744 24.285801,3.3751291 44.196415,23.285744 Z\"\n           id=\"path53304\" />\n        <path\n           sodipodi:nodetypes=\"ccccccc\"\n           style=\"opacity:0.72;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"M 43.505062,23.285744 24.285801,4.0664819 5.0665401,23.285744 5.8476076,23.910676 24.45724,5.4825431 43.505256,23.285744 Z\"\n           id=\"path53359\" />\n        <path\n           style=\"opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 8.9257729,27.145172 0.7384498,-1.024184 c 0.6367493,0.268492 1.3006183,0.485069 1.9861833,0.644885 l -0.0058,1.576858 c 0.427728,0.08834 0.86301,0.156136 1.304105,0.204371 l 0.481774,-1.501889 c 0.344041,0.02848 0.691764,0.04417 1.043361,0.04417 0.351209,0 0.699124,-0.0155 1.043166,-0.04417 l 0.481775,1.501889 c 0.441288,-0.04823 0.876376,-0.116036 1.304104,-0.204371 l -0.006,-1.577051 c 0.685758,-0.159623 1.349433,-0.3762 1.986182,-0.644692 l 0.92248,1.279502 c 0.402351,-0.182094 0.794241,-0.382591 1.174895,-0.600522 l -0.492817,-1.498016 c 0.59723,-0.36225 1.161723,-0.773319 1.687471,-1.227972 l 1.272141,0.931779 c 0.325638,-0.296581 0.637329,-0.608272 0.933716,-0.93391 l -0.931585,-1.271947 c 0.454847,-0.525748 0.865916,-1.090047 1.228166,-1.687665 l 1.498015,0.493011 C 26.79347,21.2244 26.994161,20.832316 27.175867,20.43016 l -1.279308,-0.922287 c 0.268492,-0.636749 0.485068,-1.300618 0.645079,-1.986376 l 1.576663,0.0058 c 0.08834,-0.427727 0.156137,-0.86301 0.204178,-1.304298 l -1.501695,-0.481774 c 0.02886,-0.343848 0.04417,-0.691764 0.04417,-1.043167 0,-0.351403 -0.01569,-0.699125 -0.04417,-1.043361 l 1.501695,-0.481774 C 28.274632,12.73184 28.206442,12.296751 28.118495,11.86883 l -1.577051,0.006 C 26.381627,11.189076 26.165051,10.525208 25.896753,9.8886539 L 27.176061,8.9663652 C 26.994354,8.5640139 26.79347,8.1721237 26.575926,7.7912754 L 25.077717,8.2842867 C 24.715466,7.6868623 24.304398,7.1225635 23.849744,6.5970095 L 24.78133,5.3248686 C 24.502958,5.0189892 24.210252,4.7268638 23.905922,4.4467488 L 5.0669275,23.285938 6.0738693,24.29288 6.3725811,24.074174 c 0.5257484,0.454653 1.0900465,0.865722 1.6874698,1.227972 l -0.2419526,0.735157 1.1080622,1.108062 z\"\n           id=\"path53361\" />\n        <path\n           style=\"opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 28.448976,32.191116 c 0,-6.484682 4.233883,-11.979469 10.08724,-13.874023 l -2.226972,-2.227167 c -0.01685,0.007 -0.0339,0.01298 -0.05056,0.02015 L 36.077171,15.858244 34.665167,14.44624 c -0.463178,0.2189 -0.91667,0.45446 -1.359314,0.707648 l 0.694089,2.109193 c -0.841314,0.509669 -1.635748,1.08869 -2.375747,1.728732 l -1.79111,-1.311659 c -0.458721,0.41746 -0.897297,0.856036 -1.314564,1.314565 l 1.311465,1.790914 c -0.640041,0.740195 -1.218868,1.534628 -1.728731,2.375748 l -2.109387,-0.694089 c -0.306654,0.536403 -0.589093,1.088304 -0.844994,1.654732 l 1.801182,1.298293 c -0.377942,0.896329 -0.682852,1.831014 -0.907758,2.796501 l -2.219999,-0.0085 c -0.124172,0.602266 -0.219869,1.215188 -0.287476,1.836051 l 2.114423,0.678398 c -0.04029,0.484293 -0.06199,0.97401 -0.06199,1.46857 0,0.494753 0.0217,0.98447 0.06199,1.468763 l -2.114423,0.677816 c 0.06761,0.621251 0.163304,1.233979 0.28767,1.836245 l 2.219805,-0.0083 c 0.224906,0.965487 0.529816,1.900172 0.907758,2.796502 l -1.801182,1.298486 c 0.142382,0.31479 0.293869,0.624931 0.452136,0.930423 l 3.804023,-3.803636 c -0.61602,-1.614245 -0.95425,-3.365836 -0.95425,-5.196269 z\"\n           id=\"path53363\" />\n        <path\n           sodipodi:nodetypes=\"ccccccc\"\n           style=\"opacity:0.35;fill:#000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"M 5.2050478,23.424252 24.285801,42.505005 43.505062,23.285744 42.789963,22.603525 24.310314,41.041677 5.2050478,23.424059 Z\"\n           id=\"path53365\" />\n        <path\n           transform=\"matrix(1.18638,0,0,1.18638,-4.539687,-7.794678)\"\n           id=\"path1538\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient2308);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           cx=\"24.357143\"\n           cy=\"38.714287\"\n           rx=\"19.928572\"\n           ry=\"9.837245\"\n           d=\"\" />\n      </g>\n      <ellipse\n         id=\"path1538-3\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient2308-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.2126;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"127.64644\"\n         cy=\"207.99739\"\n         rx=\"113.91853\"\n         ry=\"33.69902\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(folder) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256\"\n   height=\"256\"\n   id=\"svg97\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"folder.svg\"\n   inkscape:export-filename=\"..\\..\\256x256\\places\\folder.png\"\n   inkscape:export-xdpi=\"96.000008\"\n   inkscape:export-ydpi=\"96.000008\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <defs\n     id=\"defs3\">\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient9766\">\n      <stop\n         style=\"stop-color:#6194cb;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop9768\" />\n      <stop\n         style=\"stop-color:#729fcf;stop-opacity:1;\"\n         offset=\"1\"\n         id=\"stop9770\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient3096\">\n      <stop\n         id=\"stop3098\"\n         offset=\"0\"\n         style=\"stop-color:#424242;stop-opacity:1;\" />\n      <stop\n         id=\"stop3100\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#777777;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient1789\">\n      <stop\n         style=\"stop-color:#202020;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop1790\" />\n      <stop\n         style=\"stop-color:#b9b9b9;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop1791\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient3983\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0.87628865;\"\n         offset=\"0.0000000\"\n         id=\"stop3984\" />\n      <stop\n         style=\"stop-color:#fffffe;stop-opacity:0.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop3985\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient1789\"\n       id=\"radialGradient238\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.055022,-0.02734504,0.177703,1.190929,-3.572177,-7.125301)\"\n       cx=\"20.706017\"\n       cy=\"37.517986\"\n       fx=\"20.706017\"\n       fy=\"37.517986\"\n       r=\"30.905205\" />\n    <linearGradient\n       gradientUnits=\"userSpaceOnUse\"\n       y2=\"6.1802502\"\n       x2=\"15.514889\"\n       y1=\"31.36775\"\n       x1=\"18.112709\"\n       id=\"linearGradient3104\"\n       xlink:href=\"#linearGradient3096\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient3983\"\n       id=\"linearGradient491\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.516844,0,0,0.708978,-0.879573,-1.318166)\"\n       x1=\"6.2297964\"\n       y1=\"13.773066\"\n       x2=\"9.8980894\"\n       y2=\"66.834053\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient9766\"\n       id=\"linearGradient9772\"\n       x1=\"22.175976\"\n       y1=\"36.987999\"\n       x2=\"22.065331\"\n       y2=\"32.050499\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       gradientUnits=\"userSpaceOnUse\"\n       y2=\"46.689312\"\n       x2=\"12.853771\"\n       y1=\"32.567184\"\n       x1=\"13.035696\"\n       gradientTransform=\"matrix(1.317489,0,0,0.816256,-0.879573,-1.318166)\"\n       id=\"linearGradient322\"\n       xlink:href=\"#linearGradient319\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       id=\"linearGradient319\"\n       inkscape:collect=\"always\">\n      <stop\n         id=\"stop320\"\n         offset=\"0\"\n         style=\"stop-color:#ffffff;stop-opacity:1;\" />\n      <stop\n         id=\"stop321\"\n         offset=\"1\"\n         style=\"stop-color:#ffffff;stop-opacity:0;\" />\n    </linearGradient>\n  </defs>\n  <sodipodi:namedview\n     fill=\"#729fcf\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.10196078\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"2\"\n     inkscape:cx=\"54.359127\"\n     inkscape:cy=\"116.1963\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:window-width=\"1561\"\n     inkscape:window-height=\"961\"\n     inkscape:window-x=\"1954\"\n     inkscape:window-y=\"73\"\n     inkscape:showpageshadow=\"false\"\n     stroke=\"#3465a4\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Folder Icon</dc:title>\n        <dc:date>2009-01-13, 2020-12-28</dc:date>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>folder</rdf:li>\n            <rdf:li>directory</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/places/folder.svg</dc:identifier>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A representation of a folder for file storage.</dc:description>\n        <dc:language>en-GB</dc:language>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/places/folder-remote.svg</dc:relation>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Folder\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g95\"\n       transform=\"matrix(5.5294093,0,0,5.5293987,-0.61953982,-5.1472721)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02262383,0,0,0.02086758,43.38343,36.36962)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <path\n         d=\"m 4.5217805,38.687417 c 0.021796,0.416304 0.4599049,0.832609 0.8762095,0.832609 h 31.327021 c 0.416302,0 0.810812,-0.416305 0.789016,-0.832609 L 36.577584,11.460682 c -0.0218,-0.416303 -0.459897,-0.832616 -0.876201,-0.832616 H 22.43051 c -0.485057,0 -1.234473,-0.315589 -1.401644,-1.1066322 L 20.417475,6.6283628 C 20.262006,5.8926895 19.535261,5.5904766 19.118957,5.5904766 H 4.3400975 c -0.4163128,0 -0.8108208,0.4163041 -0.7890249,0.8326083 z\"\n         id=\"path216\"\n         style=\"fill:url(#radialGradient238);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3104);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"\n         sodipodi:nodetypes=\"ccccccssssccc\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9788\"\n         d=\"M 5.2265927,22.5625 H 35.492173\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9784\"\n         d=\"M 5.0421736,18.5625 H 35.489104\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 4.9806965,12.5625 H 35.488057\"\n         id=\"path9778\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.3861577,32.5625 H 35.494881\"\n         id=\"path9798\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9800\"\n         d=\"M 5.5091398,34.5625 H 35.496893\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.0421736,16.5625 H 35.489104\"\n         id=\"path9782\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9780\"\n         d=\"M 5.0114345,14.5625 H 35.48858\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9776\"\n         d=\"M 4.9220969,10.5625 H 20.202912\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 4.8737534,8.5624999 H 19.657487\"\n         id=\"path9774\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.3246666,28.5625 H 35.493876\"\n         id=\"path9794\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9792\"\n         d=\"M 5.2880638,26.5625 H 35.493184\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.2265927,24.5625 H 35.492173\"\n         id=\"path9790\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.1958537,20.5625 H 35.491649\"\n         id=\"path9786\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path9796\"\n         d=\"M 5.3246666,30.5625 H 35.493876\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.113636;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 5.5091398,36.5625 H 35.496893\"\n         id=\"path9802\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.451429;fill:url(#linearGradient491);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2138;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 6.068343,38.864023 c 0.016343,0.312228 -0.1809113,0.520379 -0.4985848,0.416303 v 0 C 5.2520766,39.176251 5.033027,38.968099 5.0166756,38.65587 L 4.068956,6.5913839 C 4.0526131,6.2791558 4.2341418,6.0906134 4.5463699,6.0906134 L 18.96842,6.0429196 c 0.312228,0 0.931943,0.3004727 1.132936,1.3221818 l 0.573489,2.8155346 C 20.247791,9.715379 20.255652,9.7010175 20.037287,9.0239299 L 19.631192,7.7647478 C 19.412142,7.0371009 18.932991,6.9328477 18.620763,6.9328477 H 5.7329889 c -0.3122276,0 -0.5094814,0.2081522 -0.4931306,0.5203887 L 6.1778636,38.968099 Z\"\n         id=\"path219\"\n         sodipodi:nodetypes=\"cccccccccscccccc\" />\n      <g\n         style=\"fill:#ffffff;fill-opacity:0.757062;fill-rule:nonzero;stroke:none;stroke-width:0.999465;stroke-miterlimit:4\"\n         id=\"g220\"\n         transform=\"matrix(1.040764,0,0.05449252,1.040764,-8.670199,2.670594)\"\n         inkscape:export-filename=\"/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png\"\n         inkscape:export-xdpi=\"74.800003\"\n         inkscape:export-ydpi=\"74.800003\">\n        <path\n           style=\"fill:#ffffff;fill-opacity:0.508475\"\n           d=\"m 42.417183,8.5151772 c 0.0051,-0.097113 -0.128161,-0.2469882 -0.235117,-0.2470056 l -13.031401,-0.00212 c 0,0 0.911714,0.5879545 2.201812,0.5962436 l 11.053497,0.07102 c 0.01109,-0.2117278 0.0027,-0.2560322 0.01121,-0.4181395 z\"\n           id=\"path221\"\n           sodipodi:nodetypes=\"cscscs\" />\n      </g>\n      <path\n         style=\"color:#000000;display:block;visibility:visible;fill:url(#linearGradient9772);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 39.783532,39.51062 c 1.143894,-0.04406 1.963076,-1.096299 2.047035,-2.321005 0.791787,-11.548687 1.65936,-21.231949 1.65936,-21.231949 0.07215,-0.247484 -0.167911,-0.494967 -0.48014,-0.494967 H 8.6386304 c 0,0 -1.8503191,21.866892 -1.8503191,21.866892 -0.1145551,0.982066 -0.4660075,1.804718 -1.5498358,2.183713 z\"\n         id=\"path233\"\n         sodipodi:nodetypes=\"cscccscc\"\n         inkscape:export-filename=\"/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png\"\n         inkscape:export-xdpi=\"74.800003\"\n         inkscape:export-ydpi=\"74.800003\" />\n      <path\n         sodipodi:nodetypes=\"ccsscsc\"\n         id=\"path304\"\n         d=\"m 9.6202444,16.463921 32.7910986,0.06481 -1.574046,20.001979 c -0.08432,1.071511 -0.450678,1.428215 -1.872656,1.428215 -1.871502,0 -28.677968,-0.03241 -31.394742,-0.03241 0.2335983,-0.320811 0.3337557,-0.988623 0.3350963,-1.004612 z\"\n         style=\"opacity:0.465909;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient322);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1\" />\n      <path\n         sodipodi:nodetypes=\"ccccc\"\n         id=\"path323\"\n         d=\"M 9.6202481,16.223182 8.4536014,31.866453 c 0,0 8.2961546,-4.148078 18.6663476,-4.148078 10.370193,0 15.55529,-11.495193 15.55529,-11.495193 z\"\n         style=\"fill:#ffffff;fill-opacity:0.0892857;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />\n    </g>\n  </g>\n  <g\n     inkscape:groupmode=\"layer\"\n     id=\"layer2\"\n     inkscape:label=\"pattern\" />\n</svg>\n}\n\nset ::tk::icons::svgData(font) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg1306\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"font-x-generic.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\font-x-generic.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title119\">Font Icon</title>\n  <defs\n     id=\"defs1308\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4767\">\n      <stop\n         style=\"stop-color:#729fcf\"\n         offset=\"0\"\n         id=\"stop4769\" />\n      <stop\n         style=\"stop-color:#3465a4\"\n         offset=\"1\"\n         id=\"stop4771\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4755\">\n      <stop\n         style=\"stop-color:#eeeeec;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4757\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000\"\n         offset=\"1\"\n         id=\"stop4759\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4755\"\n       id=\"linearGradient4761\"\n       x1=\"36.668537\"\n       y1=\"36.383247\"\n       x2=\"10.303555\"\n       y2=\"7.4928832\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4767\"\n       id=\"linearGradient4773\"\n       x1=\"18.561554\"\n       y1=\"12.998214\"\n       x2=\"30.935921\"\n       y2=\"33.681091\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"translate(-1,-1)\" />\n  </defs>\n  <sodipodi:namedview\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.11372549\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"1\"\n     inkscape:cx=\"56.344977\"\n     inkscape:cy=\"12.600577\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     fill=\"#2e3436\"\n     stroke=\"#888a85\"\n     showguides=\"true\"\n     inkscape:guide-bbox=\"true\"\n     inkscape:window-width=\"1148\"\n     inkscape:window-height=\"746\"\n     inkscape:window-x=\"357\"\n     inkscape:window-y=\"41\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata1311\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Font Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Andreas Nilsson, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:contributor>\n          <cc:Agent>\n            <dc:title>The oxygen guys.</dc:title>\n          </cc:Agent>\n        </dc:contributor>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>font</rdf:li>\n            <rdf:li>type</rdf:li>\n            <rdf:li>letter</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/font-x-generic.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-executable.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A font selection icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Layer 1\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g117\"\n       transform=\"matrix(5.0547274,0,0,5.054731,6.0546866,0.89191186)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.0247484,0,0,0.02086758,46.13711,41.50715)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"opacity:1;fill:url(#linearGradient4761);fill-opacity:1;stroke:#888a85;stroke-width:1.02493;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"rect1314\"\n         width=\"41.011471\"\n         height=\"42.98724\"\n         x=\"3.4883704\"\n         y=\"2.5121932\"\n         rx=\"0.99906075\"\n         ry=\"0.99914879\" />\n      <path\n         style=\"font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:46.6005px;line-height:125%;font-family:'Nimbus Roman No9 L';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient4773);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         d=\"m 39,39.008527 c -2.656226,-0.233002 -2.935832,-0.23081 -3.541638,-3.632643 L 31.077914,8.9999998 H 30.241301 L 16.352156,32.300251 c -3.681436,6.19786 -4.553697,6.335472 -6.417715,6.708276 v 1.120608 h 9.120544 v -1.120608 c -2.376623,-0.233002 -2.74943,-0.09101 -2.74943,-1.256017 0,-0.885409 0.139803,-1.304816 0.93201,-2.889232 l 2.656229,-4.703356 h 10.25211 l 0.93201,5.542165 c 0.0466,0.419405 0.0932,0.83881 0.0932,1.211613 0,1.770818 -0.24616,1.815224 -3.228589,2.094827 v 1.120608 H 39 V 39.008527 M 20.872404,27.919804 27.86248,15.803673 29.912902,27.919804 h -9.040498\"\n         id=\"text2044\"\n         sodipodi:nodetypes=\"cccccccccsccccscccccccc\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4633\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.52006,11.81453)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4635\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520061,13.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4639\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520065,17.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4641\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520061,19.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4643\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520056,21.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4645\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520057,23.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4647\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520061,25.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4649\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520061,27.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4651\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520057,29.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4653\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520065,31.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4655\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520066,33.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4657\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.52007,35.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4659\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.52007,37.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4661\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520066,39.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4663\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520061,15.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4665\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520065,41.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4667\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.520066,43.81455)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4669\"\n         transform=\"matrix(0.45255,0,0,-0.532412,-2.52007,45.81454)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4675\"\n         transform=\"matrix(-0.45255,0,0,0.532412,15.52001,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4679\"\n         transform=\"matrix(-0.45255,0,0,0.532412,21.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4681\"\n         transform=\"matrix(-0.45255,0,0,0.532412,23.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4683\"\n         transform=\"matrix(-0.45255,0,0,0.532412,25.52002,1.185486)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4685\"\n         transform=\"matrix(-0.45255,0,0,0.532412,27.52003,1.185486)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4687\"\n         transform=\"matrix(-0.45255,0,0,0.532412,29.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4689\"\n         transform=\"matrix(-0.45255,0,0,0.532412,31.52003,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4691\"\n         transform=\"matrix(-0.45255,0,0,0.532412,33.52003,1.185486)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4693\"\n         transform=\"matrix(-0.45255,0,0,0.532412,35.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4695\"\n         transform=\"matrix(-0.45255,0,0,0.532412,37.52003,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4697\"\n         transform=\"matrix(-0.45255,0,0,0.532412,39.52002,1.185506)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4699\"\n         transform=\"matrix(-0.45255,0,0,0.532412,41.52003,1.185506)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4701\"\n         transform=\"matrix(-0.45255,0,0,0.532412,43.52003,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4703\"\n         transform=\"matrix(-0.45255,0,0,0.532412,19.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4705\"\n         transform=\"matrix(-0.45255,0,0,0.532412,45.52002,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4707\"\n         transform=\"matrix(-0.45255,0,0,0.532412,47.52003,1.185496)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4709\"\n         transform=\"matrix(-0.45255,0,0,0.532412,49.52002,1.185506)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <path\n         style=\"display:inline;opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"path4751\"\n         transform=\"matrix(-0.45255,0,0,0.532412,17.52,-0.814489)\"\n         cx=\"22.141281\"\n         cy=\"9.9819622\"\n         rx=\"1.1048543\"\n         ry=\"0.93912619\" />\n      <rect\n         style=\"opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.025;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"\n         id=\"rect4753\"\n         width=\"39.013622\"\n         height=\"41.033813\"\n         x=\"4.4870877\"\n         y=\"3.5124998\"\n         rx=\"0.0000000\"\n         ry=\"0.0000000\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(html) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg249\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"text-html.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\text-html.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title373\">HTML Document Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       id=\"linearGradient4126\">\n      <stop\n         id=\"stop4128\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4130\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:0.16494845;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4750\">\n      <stop\n         id=\"stop4752\"\n         offset=\"0\"\n         style=\"stop-color:#ffffff;stop-opacity:1;\" />\n      <stop\n         id=\"stop4758\"\n         offset=\"0.37931034\"\n         style=\"stop-color:#fefefe;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4754\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#1d1d1d;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4350\"\n       inkscape:collect=\"always\">\n      <stop\n         id=\"stop4352\"\n         offset=\"0\"\n         style=\"stop-color:#ffffff;stop-opacity:1;\" />\n      <stop\n         id=\"stop4354\"\n         offset=\"1\"\n         style=\"stop-color:#ffffff;stop-opacity:0;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient3962\">\n      <stop\n         id=\"stop3964\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#d3e9ff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4134\"\n         offset=\"0.15517241\"\n         style=\"stop-color:#d3e9ff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop4346\"\n         offset=\"0.75000000\"\n         style=\"stop-color:#4074ae;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop3966\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#36486c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient4114\"\n       inkscape:collect=\"always\">\n      <stop\n         id=\"stop4116\"\n         offset=\"0\"\n         style=\"stop-color:#000000;stop-opacity:1;\" />\n      <stop\n         id=\"stop4118\"\n         offset=\"1\"\n         style=\"stop-color:#000000;stop-opacity:0;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop15664\" />\n      <stop\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop15666\" />\n    </linearGradient>\n    <radialGradient\n       gradientUnits=\"userSpaceOnUse\"\n       fy=\"64.5679\"\n       fx=\"20.8921\"\n       r=\"5.257\"\n       cy=\"64.5679\"\n       cx=\"20.8921\"\n       id=\"aigrd3\">\n      <stop\n         id=\"stop15573\"\n         style=\"stop-color:#F0F0F0\"\n         offset=\"0\" />\n      <stop\n         id=\"stop15575\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\" />\n    </radialGradient>\n    <radialGradient\n       gradientUnits=\"userSpaceOnUse\"\n       fy=\"114.5684\"\n       fx=\"20.8921\"\n       r=\"5.256\"\n       cy=\"114.5684\"\n       cx=\"20.8921\"\n       id=\"aigrd2\">\n      <stop\n         id=\"stop15566\"\n         style=\"stop-color:#F0F0F0\"\n         offset=\"0\" />\n      <stop\n         id=\"stop15568\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\" />\n    </radialGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop270\" />\n      <stop\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop271\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop260\" />\n      <stop\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop261\" />\n    </linearGradient>\n    <radialGradient\n       r=\"37.751713\"\n       fy=\"3.7561285\"\n       fx=\"8.8244190\"\n       cy=\"3.7561285\"\n       cx=\"8.8244190\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15656\"\n       xlink:href=\"#linearGradient269\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"86.708450\"\n       fy=\"35.736916\"\n       fx=\"33.966679\"\n       cy=\"35.736916\"\n       cx=\"33.966679\"\n       gradientTransform=\"scale(0.960493,1.041132)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15658\"\n       xlink:href=\"#linearGradient259\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"38.158695\"\n       fy=\"7.2678967\"\n       fx=\"8.1435566\"\n       cy=\"7.2678967\"\n       cx=\"8.1435566\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient15668\"\n       xlink:href=\"#linearGradient15662\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd2\"\n       id=\"radialGradient2283\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       cx=\"20.8921\"\n       cy=\"114.5684\"\n       fx=\"20.8921\"\n       fy=\"114.5684\"\n       r=\"5.256\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd3\"\n       id=\"radialGradient2285\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       cx=\"20.8921\"\n       cy=\"64.5679\"\n       fx=\"20.8921\"\n       fy=\"64.5679\"\n       r=\"5.257\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7214\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7216\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7220\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7224\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7228\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7232\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7236\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7240\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7244\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7248\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7252\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7256\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7260\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7264\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7268\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7272\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7276\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7280\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7282\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7286\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7290\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7292\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7296\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7300\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7304\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7308\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7312\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4114\"\n       id=\"radialGradient7422\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.64399,0.608276)\"\n       cx=\"15.115514\"\n       cy=\"63.965388\"\n       fx=\"15.115514\"\n       fy=\"63.965388\"\n       r=\"12.289036\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient3962\"\n       id=\"radialGradient7424\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.58713,0,0,0.587142,11.29919,10.42967)\"\n       cx=\"18.247644\"\n       cy=\"15.716079\"\n       fx=\"18.247644\"\n       fy=\"15.716079\"\n       r=\"29.993349\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4350\"\n       id=\"radialGradient7426\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.179536,0.847791)\"\n       cx=\"11.826907\"\n       cy=\"10.476453\"\n       fx=\"11.826907\"\n       fy=\"10.476453\"\n       r=\"32.664848\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7428\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7430\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7432\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7434\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7436\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7438\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7440\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7442\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7444\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7446\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7448\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7450\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7452\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4750\"\n       id=\"radialGradient7454\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(1.036822,0.964486)\"\n       cx=\"18.633780\"\n       cy=\"17.486208\"\n       fx=\"18.934305\"\n       fy=\"17.810213\"\n       r=\"40.692665\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4126\"\n       id=\"radialGradient7456\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.58713,0,0,0.587142,11.29919,10.42967)\"\n       cx=\"15.601279\"\n       cy=\"12.142302\"\n       fx=\"15.601279\"\n       fy=\"12.142302\"\n       r=\"43.526714\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:showpageshadow=\"false\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"1.0\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"1.4142136\"\n     inkscape:cx=\"35.072186\"\n     inkscape:cy=\"96.990295\"\n     inkscape:current-layer=\"layer5\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:window-width=\"1263\"\n     inkscape:window-height=\"688\"\n     inkscape:window-x=\"188\"\n     inkscape:window-y=\"122\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>HTML Document Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>HTML</rdf:li>\n            <rdf:li>hypertext</rdf:li>\n            <rdf:li>web</rdf:li>\n            <rdf:li>page</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-html.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/font-x-generic.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A HTML document icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     style=\"display:inline\"\n     inkscape:label=\"Text\"\n     id=\"layer5\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g371\"\n       transform=\"matrix(5.6640035,0,0,5.6640001,-9.5760347,-16.821471)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         ry=\"1.1490486\"\n         y=\"3.6464462\"\n         x=\"6.6035528\"\n         height=\"40.920494\"\n         width=\"34.875\"\n         id=\"rect15391\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         rx=\"0.14904857\"\n         ry=\"0.14904857\"\n         y=\"4.5839462\"\n         x=\"7.6660538\"\n         height=\"38.946384\"\n         width=\"32.775887\"\n         id=\"rect15660\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <g\n         id=\"g2270\"\n         transform=\"translate(0.646447,-0.03798933)\"\n         style=\"display:inline\">\n        <g\n           transform=\"matrix(0.229703,0,0,0.229703,4.967081,4.244972)\"\n           style=\"fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4\"\n           id=\"g1440\">\n          <radialGradient\n             gradientUnits=\"userSpaceOnUse\"\n             fy=\"114.5684\"\n             fx=\"20.892099\"\n             r=\"5.256\"\n             cy=\"114.5684\"\n             cx=\"20.892099\"\n             id=\"radialGradient1442\">\n            <stop\n               id=\"stop1444\"\n               style=\"stop-color:#F0F0F0\"\n               offset=\"0\" />\n            <stop\n               id=\"stop1446\"\n               style=\"stop-color:#474747\"\n               offset=\"1\" />\n          </radialGradient>\n          <path\n             id=\"path1448\"\n             d=\"m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             style=\"stroke:none\" />\n          <radialGradient\n             gradientUnits=\"userSpaceOnUse\"\n             fy=\"64.567902\"\n             fx=\"20.892099\"\n             r=\"5.257\"\n             cy=\"64.567902\"\n             cx=\"20.892099\"\n             id=\"radialGradient1450\">\n            <stop\n               id=\"stop1452\"\n               style=\"stop-color:#F0F0F0\"\n               offset=\"0\" />\n            <stop\n               id=\"stop1454\"\n               style=\"stop-color:#474747\"\n               offset=\"1\" />\n          </radialGradient>\n          <path\n             id=\"path1456\"\n             d=\"m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             style=\"stroke:none\" />\n        </g>\n        <path\n           id=\"path15570\"\n           d=\"m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           style=\"fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\" />\n        <path\n           id=\"path15577\"\n           d=\"m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           style=\"fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\" />\n      </g>\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path15672\"\n         d=\"M 11.505723,5.4942766 V 43.400869\"\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.988553;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.0175438\" />\n      <path\n         sodipodi:nodetypes=\"cc\"\n         id=\"path15674\"\n         d=\"M 12.5,5.0205154 V 43.038228\"\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.204678\" />\n      <g\n         id=\"g2253\"\n         transform=\"matrix(0.909091,0,0,1,2.363628,0)\">\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"9\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15686\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"11\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15688\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"13\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15690\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"15\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15692\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"17\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15694\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"19\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15696\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"21\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15698\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"23\"\n           x=\"15.000002\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15700\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.068204239\"\n           y=\"25\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"9.9000053\"\n           id=\"rect15732\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"29\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15736\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"31\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15738\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"33\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15740\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.15156493\"\n           y=\"35\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"22.000004\"\n           id=\"rect15742\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n        <rect\n           ry=\"0.065390877\"\n           rx=\"0.10609552\"\n           y=\"37\"\n           x=\"14.999992\"\n           height=\"1\"\n           width=\"15.400014\"\n           id=\"rect15744\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <g\n         id=\"g7314\"\n         transform=\"matrix(1.160511,0,0,1.160511,1.847713,3.119486)\">\n        <ellipse\n           style=\"fill:url(#radialGradient7422);fill-opacity:1;stroke:none;stroke-opacity:1\"\n           id=\"path4112\"\n           transform=\"matrix(0.587136,0,0,0.729954,11.29919,4.398359)\"\n           cx=\"24.849752\"\n           cy=\"38.908627\"\n           rx=\"20.203051\"\n           ry=\"7.4751287\" />\n        <path\n           style=\"fill:url(#radialGradient7424);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-width:1.72338;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"\n           d=\"m 37.109606,24.218856 c 0,6.288063 -5.097577,11.385582 -11.384775,11.385582 -6.287774,0 -11.385064,-5.097577 -11.385064,-11.385582 0,-6.287775 5.09729,-11.384775 11.385064,-11.384775 6.287198,0 11.384775,5.097 11.384775,11.384775 z\"\n           id=\"path3214\" />\n        <ellipse\n           style=\"opacity:0.421594;fill:url(#radialGradient7426);fill-opacity:1;stroke:none;stroke-opacity:1\"\n           id=\"path4348\"\n           transform=\"matrix(0.490809,0,0,0.587136,17.10413,10.42967)\"\n           cx=\"17.778685\"\n           cy=\"15.271057\"\n           rx=\"12.929953\"\n           ry=\"9.2934036\" />\n        <g\n           id=\"g4136\"\n           style=\"fill:#000000;fill-opacity:0.71345;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           transform=\"matrix(0.576786,0,0,0.576786,11.37028,10.56642)\">\n          <g\n             id=\"g4138\">\n            <g\n               id=\"g4142\">\n              <path\n                 d=\"m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z\"\n                 id=\"path4144\" />\n            </g>\n          </g>\n          <g\n             id=\"g4146\">\n            <g\n               id=\"g4150\">\n              <path\n                 d=\"m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825\"\n                 id=\"path4152\" />\n            </g>\n          </g>\n          <g\n             id=\"g4154\">\n            <g\n               id=\"g4158\">\n              <path\n                 d=\"m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212\"\n                 id=\"path4160\" />\n            </g>\n          </g>\n          <g\n             id=\"g4162\">\n            <g\n               id=\"g4166\">\n              <path\n                 d=\"m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281\"\n                 id=\"path4168\" />\n            </g>\n          </g>\n          <g\n             id=\"g4170\">\n            <g\n               id=\"g4174\">\n              <path\n                 d=\"m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402\"\n                 id=\"path4176\" />\n            </g>\n          </g>\n          <g\n             id=\"g4178\">\n            <g\n               id=\"g4182\">\n              <path\n                 d=\"m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242\"\n                 id=\"path4184\" />\n            </g>\n          </g>\n          <g\n             id=\"g4186\">\n            <g\n               id=\"g4190\">\n              <path\n                 d=\"m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111\"\n                 id=\"path4192\" />\n            </g>\n          </g>\n          <g\n             id=\"g4194\">\n            <g\n               id=\"g4198\">\n              <path\n                 d=\"M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494\"\n                 id=\"path4200\" />\n            </g>\n          </g>\n          <g\n             id=\"g4202\">\n            <g\n               style=\"opacity:0.75\"\n               id=\"g4204\">\n              <path\n                 id=\"path4206\"\n                 d=\"\" />\n            </g>\n            <g\n               id=\"g4208\">\n              <path\n                 id=\"path4210\"\n                 d=\"\" />\n            </g>\n          </g>\n          <g\n             id=\"g4212\">\n            <g\n               style=\"opacity:0.75\"\n               id=\"g4214\">\n              <path\n                 id=\"path4216\"\n                 d=\"\" />\n            </g>\n            <g\n               id=\"g4218\">\n              <path\n                 id=\"path4220\"\n                 d=\"\" />\n            </g>\n          </g>\n          <g\n             id=\"g4222\">\n            <g\n               id=\"g4226\">\n              <path\n                 d=\"M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641\"\n                 id=\"path4228\" />\n            </g>\n          </g>\n          <g\n             id=\"g4230\">\n            <g\n               id=\"g4234\">\n              <path\n                 d=\"m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514\"\n                 id=\"path4236\" />\n            </g>\n          </g>\n        </g>\n        <g\n           id=\"g3216\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7214);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.01795;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           transform=\"matrix(0.576786,0,0,0.576786,11.25166,10.4478)\">\n          <g\n             id=\"g3218\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7216);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3222\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7220);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z\"\n                 id=\"path3224\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7428);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3226\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7224);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3230\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7228);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825\"\n                 id=\"path3232\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7430);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3234\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7232);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3238\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7236);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212\"\n                 id=\"path3240\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7432);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3242\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7240);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3246\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7244);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281\"\n                 id=\"path3248\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7434);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3250\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7248);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3254\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7252);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402\"\n                 id=\"path3256\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7436);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3258\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7256);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3262\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7260);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242\"\n                 id=\"path3264\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7438);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3266\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7264);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3270\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7268);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111\"\n                 id=\"path3272\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7440);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3274\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7272);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3278\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7276);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494\"\n                 id=\"path3280\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7442);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3282\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7280);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient7282);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n               id=\"g3284\">\n              <path\n                 d=\"\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7444);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n                 id=\"path3286\" />\n            </g>\n            <g\n               id=\"g3288\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7286);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"\"\n                 id=\"path3290\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7446);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3292\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7290);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient7292);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n               id=\"g3294\">\n              <path\n                 d=\"\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7448);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n                 id=\"path3296\" />\n            </g>\n            <g\n               id=\"g3298\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7296);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"\"\n                 id=\"path3300\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7450);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3302\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7300);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3306\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7304);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641\"\n                 id=\"path3308\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7452);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n          <g\n             id=\"g3310\"\n             style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7308);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n            <g\n               id=\"g3314\"\n               style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7312);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\">\n              <path\n                 d=\"m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514\"\n                 id=\"path3316\"\n                 style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient7454);stroke-dashoffset:0;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n            </g>\n          </g>\n        </g>\n        <path\n           style=\"fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient7456);stroke-miterlimit:4;stroke-opacity:1\"\n           d=\"m 36.531418,24.218876 c 0,5.968721 -4.838694,10.807361 -10.806594,10.807361 -5.968447,0 -10.806868,-4.838694 -10.806868,-10.807361 0,-5.968447 4.838421,-10.806594 10.806868,-10.806594 5.9679,0 10.806594,4.838147 10.806594,10.806594 z\"\n           id=\"path4122\" />\n      </g>\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(image) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   width=\"256px\"\n   height=\"256px\"\n   xml:space=\"preserve\"\n   id=\"svg16168\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"image-x-generic.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\image-x-generic.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n<title\n   id=\"title109\">Generic Image Icon</title><metadata\n   id=\"metadata16236\">\n  <rdf:RDF>\n    <cc:Work\n   rdf:about=\"\">\n      <dc:format>image/svg+xml</dc:format>\n\n\n\n      <dc:type\n   rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n\n\n\n    <dc:title>Generic Image Icon</dc:title>\n<dc:creator>\n  <cc:Agent>\n    <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n  </cc:Agent>\n</dc:creator>\n<dc:subject>\n  <rdf:Bag><rdf:li>image</rdf:li><rdf:li>picture</rdf:li><rdf:li>snapshot</rdf:li><rdf:li>photo</rdf:li><rdf:li>computer</rdf:li><rdf:li>icon</rdf:li></rdf:Bag>\n</dc:subject>\n<cc:license\n   rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n<dc:date> 2020-12-29</dc:date><dc:rights><cc:Agent><dc:title>Public Domain</dc:title></cc:Agent></dc:rights><dc:publisher><cc:Agent><dc:title>https://tekeye.uk/</dc:title></cc:Agent></dc:publisher><dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/image-x-generic.svg</dc:identifier><dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source><dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/application-x-executable.svg</dc:relation><dc:language>en-GB</dc:language><dc:coverage>computing</dc:coverage><dc:description>An image icon.</dc:description></cc:Work>\n\n\n\n\n<cc:License\n   rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\"><cc:permits\n     rdf:resource=\"http://creativecommons.org/ns#Reproduction\" /><cc:permits\n     rdf:resource=\"http://creativecommons.org/ns#Distribution\" /><cc:permits\n     rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" /></cc:License></rdf:RDF>\n\n\n\n</metadata>\n\n\n\n<defs\n   id=\"defs16234\"><radialGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient5060\"\n     id=\"radialGradient6719\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n     cx=\"605.71429\"\n     cy=\"486.64789\"\n     fx=\"605.71429\"\n     fy=\"486.64789\"\n     r=\"117.14286\" /><linearGradient\n     inkscape:collect=\"always\"\n     id=\"linearGradient5060\"><stop\n       style=\"stop-color:black;stop-opacity:1;\"\n       offset=\"0\"\n       id=\"stop5062\" /><stop\n       style=\"stop-color:black;stop-opacity:0;\"\n       offset=\"1\"\n       id=\"stop5064\" /></linearGradient><radialGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient5060\"\n     id=\"radialGradient6717\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n     cx=\"605.71429\"\n     cy=\"486.64789\"\n     fx=\"605.71429\"\n     fy=\"486.64789\"\n     r=\"117.14286\" /><linearGradient\n     id=\"linearGradient5048\"><stop\n       style=\"stop-color:black;stop-opacity:0;\"\n       offset=\"0\"\n       id=\"stop5050\" /><stop\n       id=\"stop5056\"\n       offset=\"0.5\"\n       style=\"stop-color:black;stop-opacity:1;\" /><stop\n       style=\"stop-color:black;stop-opacity:0;\"\n       offset=\"1\"\n       id=\"stop5052\" /></linearGradient><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient5048\"\n     id=\"linearGradient6715\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n     x1=\"302.85715\"\n     y1=\"366.64789\"\n     x2=\"302.85715\"\n     y2=\"609.50507\" /><linearGradient\n     id=\"linearGradient8171\"><stop\n       style=\"stop-color:#bbbdba;stop-opacity:1;\"\n       offset=\"0\"\n       id=\"stop8173\" /><stop\n       style=\"stop-color:#70746e;stop-opacity:1;\"\n       offset=\"1\"\n       id=\"stop8175\" /></linearGradient><linearGradient\n     inkscape:collect=\"always\"\n     id=\"linearGradient8155\"><stop\n       style=\"stop-color:#ffffff;stop-opacity:1;\"\n       offset=\"0\"\n       id=\"stop8157\" /><stop\n       style=\"stop-color:#ffffff;stop-opacity:0;\"\n       offset=\"1\"\n       id=\"stop8159\" /></linearGradient><linearGradient\n     id=\"linearGradient2224\"><stop\n       style=\"stop-color:#7c7c7c;stop-opacity:1;\"\n       offset=\"0\"\n       id=\"stop2226\" /><stop\n       style=\"stop-color:#b8b8b8;stop-opacity:1;\"\n       offset=\"1\"\n       id=\"stop2228\" /></linearGradient><linearGradient\n     inkscape:collect=\"always\"\n     id=\"linearGradient2251\"><stop\n       style=\"stop-color:#ffffff;stop-opacity:1;\"\n       offset=\"0\"\n       id=\"stop2253\" /><stop\n       style=\"stop-color:#ffffff;stop-opacity:0;\"\n       offset=\"1\"\n       id=\"stop2255\" /></linearGradient><linearGradient\n     id=\"linearGradient7648\"\n     gradientUnits=\"userSpaceOnUse\"\n     x1=\"21.9326\"\n     y1=\"24.6274\"\n     x2=\"21.9326\"\n     y2=\"7.1091\"\n     style=\"stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\">\n\t\t\t<stop\n   offset=\"0\"\n   style=\"stop-color:#8595bc;stop-opacity:1;\"\n   id=\"stop7650\" />\n\n\n\n\n\t\t\t<stop\n   offset=\"1\"\n   style=\"stop-color:#041a3b;stop-opacity:1;\"\n   id=\"stop7652\" />\n\n\n\n\n\t\t</linearGradient><linearGradient\n     style=\"stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n     y2=\"36.0328\"\n     x2=\"31.0813\"\n     y1=\"3.7319\"\n     x1=\"12.4873\"\n     gradientUnits=\"userSpaceOnUse\"\n     id=\"aigrd1\">\n\t\t\t<stop\n   id=\"stop16177\"\n   style=\"stop-color:#D2D2D2;stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n   offset=\"0\" />\n\n\n\n\n\t\t\t<stop\n   id=\"stop16179\"\n   style=\"stop-color:#EDEDED;stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n   offset=\"1\" />\n\n\n\n\n\t\t</linearGradient><linearGradient\n     style=\"stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n     y2=\"7.1091\"\n     x2=\"21.9326\"\n     y1=\"24.6274\"\n     x1=\"21.9326\"\n     gradientUnits=\"userSpaceOnUse\"\n     id=\"aigrd3\">\n\t\t\t<stop\n   id=\"stop16199\"\n   style=\"stop-color:#D0D6E5;stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n   offset=\"0\" />\n\n\n\n\n\t\t\t<stop\n   id=\"stop16201\"\n   style=\"stop-color:#093A80;stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\"\n   offset=\"1\" />\n\n\n\n\n\t\t</linearGradient><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient7648\"\n     id=\"linearGradient7671\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(1.098989,0,0,-0.797757,-1.953865,37.324)\"\n     x1=\"21.9326\"\n     y1=\"24.627399\"\n     x2=\"21.9326\"\n     y2=\"7.1090999\" /><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#aigrd3\"\n     id=\"linearGradient7673\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(1.098989,0,0,1.106697,-1.953865,-4.922453)\"\n     x1=\"21.9326\"\n     y1=\"24.6274\"\n     x2=\"21.9326\"\n     y2=\"7.1091\" /><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#aigrd1\"\n     id=\"linearGradient8148\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"matrix(1.434003,0,0,0.990087,52.32167,2.838918)\"\n     x1=\"12.4873\"\n     y1=\"3.7319\"\n     x2=\"31.0813\"\n     y2=\"36.0328\" /><radialGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient8155\"\n     id=\"radialGradient8161\"\n     cx=\"12.700491\"\n     cy=\"10.404876\"\n     fx=\"12.700491\"\n     fy=\"10.404876\"\n     r=\"19.96875\"\n     gradientTransform=\"matrix(1.710531,0,0,1.124849,-11.56833,1.802582)\"\n     gradientUnits=\"userSpaceOnUse\" /><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient2251\"\n     id=\"linearGradient8166\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"translate(5.14757,-3.409792)\"\n     x1=\"33.396004\"\n     y1=\"36.921333\"\n     x2=\"34.170048\"\n     y2=\"38.070381\" /><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient2224\"\n     id=\"linearGradient8169\"\n     gradientUnits=\"userSpaceOnUse\"\n     gradientTransform=\"translate(5.14757,-3.034792)\"\n     x1=\"35.996582\"\n     y1=\"40.458221\"\n     x2=\"33.664921\"\n     y2=\"37.770721\" /><linearGradient\n     inkscape:collect=\"always\"\n     xlink:href=\"#linearGradient8171\"\n     id=\"linearGradient8177\"\n     x1=\"42.1875\"\n     y1=\"31\"\n     x2=\"45\"\n     y2=\"39.984692\"\n     gradientUnits=\"userSpaceOnUse\" /></defs>\n\n\n\n<sodipodi:namedview\n   inkscape:window-height=\"818\"\n   inkscape:window-width=\"1657\"\n   inkscape:pageshadow=\"2\"\n   inkscape:pageopacity=\"0.0\"\n   borderopacity=\"0.23137255\"\n   bordercolor=\"#666666\"\n   pagecolor=\"#ffffff\"\n   id=\"base\"\n   inkscape:zoom=\"2\"\n   inkscape:cx=\"49.378608\"\n   inkscape:cy=\"113.68626\"\n   inkscape:window-x=\"0\"\n   inkscape:window-y=\"30\"\n   inkscape:current-layer=\"svg16168\"\n   showgrid=\"false\"\n   inkscape:showpageshadow=\"false\"\n   inkscape:document-rotation=\"0\"\n   inkscape:pagecheckerboard=\"true\"\n   inkscape:window-maximized=\"0\" />\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\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\n\n\n\n\n\n\n<g\n   id=\"g107\"\n   transform=\"matrix(5.7029726,0,0,5.7029704,-3.5379124,-10.959905)\"><g\n     style=\"display:inline\"\n     transform=\"matrix(0.0219353,0,0,0.02678038,42.574834,34.08962)\"\n     id=\"g6707\"><rect\n       style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n       id=\"rect6709\"\n       width=\"1339.6335\"\n       height=\"478.35718\"\n       x=\"-1559.2523\"\n       y=\"-150.69685\" /><path\n       style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n       d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n       id=\"path6711\"\n       sodipodi:nodetypes=\"cccc\" /><path\n       sodipodi:nodetypes=\"cccc\"\n       id=\"path6713\"\n       d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n       style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" /></g><path\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient8148);fill-opacity:1;fill-rule:nonzero;stroke:#bbbfbb;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n     d=\"M 2.7177715,6.4547749 H 43.379544 c 0.623249,0 1.124999,0.5017498 1.124999,1.1249996 V 31.480581 c 0,0.62325 -8.456701,8.019291 -9.07995,8.019291 H 2.7177715 c -0.6232494,0 -1.1249988,-0.50175 -1.1249988,-1.125 V 7.5797745 c 0,-0.6232498 0.5017494,-1.1249996 1.1249988,-1.1249996 z\"\n     id=\"rect7603\"\n     sodipodi:nodetypes=\"ccccccccc\" /><g\n     id=\"g7654\"\n     transform=\"matrix(1.054774,0,0,1.049989,-0.814647,4.485012)\"><path\n       id=\"path7644\"\n       d=\"M 5.512695,30 H 39.643234 V 19.627375 H 5.512695 Z\"\n       style=\"fill:url(#linearGradient7671);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" /><path\n       style=\"fill:url(#linearGradient7673);fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n       d=\"M 5.512695,5.237844 H 39.643234 V 19.627375 H 5.512695 Z\"\n       id=\"path16203\" /><g\n       id=\"g16205\"\n       style=\"fill-rule:nonzero;stroke:#000000;stroke-width:1.15611;stroke-miterlimit:4\"\n       transform=\"matrix(1.189217,0,0,1.189217,-3.525355,-6.535408)\">\n\t\t\t<g\n   id=\"g16207\">\n\t\t\t\t<path\n   style=\"opacity:0.0499999;fill:#e8f52f;stroke:none\"\n   d=\"m 18.4,15.4 c 0,2.2 -1.8,4.1 -4.1,4.1 -2.2,0 -4.1,-1.8 -4.1,-4.1 0,-2.2 1.8,-4.1 4.1,-4.1 2.2,0 4.1,1.8 4.1,4.1 z\"\n   id=\"path16209\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"opacity:0.2083;fill:#ecf751;stroke:none\"\n   d=\"m 18,15.4 c 0,2 -1.6,3.7 -3.7,3.7 -2,0 -3.7,-1.6 -3.7,-3.7 0,-2 1.6,-3.7 3.7,-3.7 2,0 3.7,1.6 3.7,3.7 z\"\n   id=\"path16211\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"opacity:0.3667;fill:#f0f972;stroke:none\"\n   d=\"m 17.6,15.4 c 0,1.8 -1.5,3.3 -3.3,3.3 -1.8,0 -3.3,-1.5 -3.3,-3.3 0,-1.8 1.5,-3.3 3.3,-3.3 1.8,0 3.3,1.5 3.3,3.3 z\"\n   id=\"path16213\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"opacity:0.525;fill:#f4fa95;stroke:none\"\n   d=\"m 17.2,15.4 c 0,1.6 -1.3,2.9 -2.9,2.9 -1.6,0 -2.9,-1.3 -2.9,-2.9 0,-1.6 1.3,-2.9 2.9,-2.9 1.6,0 2.9,1.3 2.9,2.9 z\"\n   id=\"path16215\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"opacity:0.6833;fill:#f7fcb7;stroke:none\"\n   d=\"m 16.8,15.4 c 0,1.4 -1.1,2.5 -2.5,2.5 -1.4,0 -2.5,-1.1 -2.5,-2.5 0,-1.4 1.1,-2.5 2.5,-2.5 1.4,0 2.5,1.1 2.5,2.5 z\"\n   id=\"path16217\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"opacity:0.8417;fill:#fbfddb;stroke:none\"\n   d=\"m 16.4,15.4 c 0,1.2 -1,2.1 -2.1,2.1 -1.1,0 -2.1,-1 -2.1,-2.1 0,-1.1 1,-2.1 2.1,-2.1 1.1,0 2.1,1 2.1,2.1 z\"\n   id=\"path16219\" />\n\n\n\n\n\t\t\t\t<path\n   style=\"fill:#ffffff;stroke:none\"\n   d=\"m 16,15.4 c 0,1 -0.8,1.8 -1.8,1.8 -1,0 -1.8,-0.8 -1.8,-1.8 0,-1 0.8,-1.8 1.8,-1.8 1,0 1.8,0.8 1.8,1.8 z\"\n   id=\"path16221\" />\n\n\n\n\n\t\t\t</g>\n\n\n\n\n\t\t</g><path\n       style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n       d=\"m 25.015859,21.649044 h 8.681289 l 1.664904,0.475688 h -2.854121 c 0,0 2.854121,0.237842 4.281184,2.021669 1.427059,1.664904 -1.664905,3.686575 -1.664905,3.686575 0,0 0,0 0,0 -0.118922,-0.356766 -0.832454,-3.210889 -2.259514,-4.400106 -1.070297,-0.951374 -2.259514,-1.189218 -2.259514,-1.189218 h -5.589323 v -0.475686 z\"\n       id=\"path16223\" /><path\n       style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n       d=\"m 30.724106,22.362574 h -4.994715 l 9.275897,5.232557 z\"\n       id=\"path16225\" /><path\n       style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n       d=\"m 25.015859,21.767966 h 8.681289 l 1.30814,-0.832453 h -2.854121 c 0,0 2.616276,-0.475686 2.973043,-3.448731 0.356763,-2.973043 -4.043341,-6.302851 -4.043341,-6.302851 0,0 0,0 0,0.118922 0.118921,0.71353 1.308138,5.708243 0.475688,7.610993 -0.356767,1.664901 -1.427062,2.021667 -1.427062,2.021667 h -5.470401 l 0.237844,0.832453 z\"\n       id=\"path16227\" /><path\n       style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n       d=\"M 30.248418,20.459827 H 25.253704 L 31.19979,11.421773 Z\"\n       id=\"path16229\" /></g><path\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n     d=\"M 2.8042317,7.4528585 H 43.233985 c 0.150381,0 0.271446,0.1210649 0.271446,0.271446 V 31.422651 c 0,0.945876 -7.103744,7.077349 -7.254125,7.077349 H 2.8042317 c -0.150381,0 -0.2714459,-0.121065 -0.2714459,-0.271446 V 7.7243045 c 0,-0.1503811 0.1210649,-0.271446 0.2714459,-0.271446 z\"\n     id=\"rect7675\"\n     sodipodi:nodetypes=\"ccccccccc\" /><rect\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.846591;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#4f4f4f;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n     id=\"rect8163\"\n     width=\"35.0625\"\n     height=\"25.0625\"\n     x=\"5.5\"\n     y=\"10.5\" /><path\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient8169);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient8177);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n     d=\"m 35.206652,39.468763 c 2.030418,0.329898 9.588793,-4.529929 9.284411,-8.497844 -1.563262,2.423097 -4.758522,1.286738 -8.86728,1.445748 0,0 0.395369,6.552096 -0.417131,7.052096 z\"\n     id=\"path2210\"\n     sodipodi:nodetypes=\"cccc\" /><path\n     sodipodi:nodetypes=\"cccc\"\n     id=\"path2247\"\n     d=\"m 36.657089,37.277261 c 1.369779,-0.683829 4.428249,-2.146465 5.72763,-4.027469 -1.596094,0.680055 -2.94781,0.209496 -5.702334,0.190405 0,0 0.162322,3.062094 -0.0253,3.837064 z\"\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.369318;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient8166);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" /><path\n     style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.301136;fill:url(#radialGradient8161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n     d=\"M 3.0625,8 V 30.0625 C 25.388579,30.950861 27.884634,17 43,17 V 8 Z\"\n     id=\"rect8150\"\n     sodipodi:nodetypes=\"ccccc\" /></g></svg>\n}\n\nset ::tk::icons::svgData(mail) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   sodipodi:docname=\"internet-mail.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg5816\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\apps\\internet-mail.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n  <title\n     id=\"title93\">Mail App Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       id=\"linearGradient2274\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0.12871288;\"\n         offset=\"0.0000000\"\n         id=\"stop2276\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop2278\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient9749\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop9751\" />\n      <stop\n         style=\"stop-color:#ededed;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop9753\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient2152\">\n      <stop\n         style=\"stop-color:#9aa29a;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop2154\" />\n      <stop\n         style=\"stop-color:#b5beb5;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop2156\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient2166\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2168\" />\n      <stop\n         style=\"stop-color:#dcdcdc;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop2170\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient18913\">\n      <stop\n         style=\"stop-color:#ededed;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop18915\" />\n      <stop\n         style=\"stop-color:#c8c8c8;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop18917\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient2136\">\n      <stop\n         style=\"stop-color:#989690;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop2138\" />\n      <stop\n         style=\"stop-color:#656460;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop2140\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15107\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop15109\" />\n      <stop\n         style=\"stop-color:#e2e2e2;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop15111\" />\n    </linearGradient>\n    <linearGradient\n       y2=\"32.203162\"\n       x2=\"9.7619219\"\n       y1=\"37.784682\"\n       x1=\"8.7803760\"\n       gradientTransform=\"matrix(2.3949,0,0,0.781058,2.879512,0.343005)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27463\"\n       xlink:href=\"#linearGradient2274\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"24.132717\"\n       x2=\"21.111549\"\n       y1=\"13.686079\"\n       x1=\"11.233107\"\n       gradientTransform=\"matrix(1.370928,0,0,1.443758,2.431133,-0.140786)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27468\"\n       xlink:href=\"#linearGradient9749\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"52.090678\"\n       x2=\"9.8855033\"\n       y1=\"37.197018\"\n       x1=\"8.9156475\"\n       gradientTransform=\"matrix(2.454781,0,0,0.762004,2.879512,0.343005)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27471\"\n       xlink:href=\"#linearGradient2152\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"52.090678\"\n       x2=\"9.8855033\"\n       y1=\"37.197018\"\n       x1=\"8.9156475\"\n       gradientTransform=\"matrix(2.454781,0,0,0.762004,2.879512,0.343005)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27474\"\n       xlink:href=\"#linearGradient2152\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"29.568739\"\n       x2=\"15.310744\"\n       y1=\"15.148383\"\n       x1=\"10.184240\"\n       gradientTransform=\"matrix(1.819266,0,0,1.028193,2.879512,0.343005)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27477\"\n       xlink:href=\"#linearGradient2166\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"17.876846\"\n       x2=\"13.467486\"\n       y1=\"7.2310905\"\n       x1=\"5.8266134\"\n       gradientTransform=\"matrix(1.570607,0,0,1.190976,2.879512,0.343005)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27483\"\n       xlink:href=\"#linearGradient18913\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"26.022910\"\n       x2=\"18.475286\"\n       y1=\"4.7461626\"\n       x1=\"11.572842\"\n       gradientTransform=\"matrix(1.343475,0,0,1.417854,2.879511,0.314599)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27486\"\n       xlink:href=\"#linearGradient15107\"\n       inkscape:collect=\"always\" />\n    <linearGradient\n       y2=\"15.257116\"\n       x2=\"30.599684\"\n       y1=\"15.257116\"\n       x1=\"2.0618774\"\n       gradientTransform=\"matrix(1.343475,0,0,1.417854,2.879511,0.314599)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"linearGradient27488\"\n       xlink:href=\"#linearGradient2136\"\n       inkscape:collect=\"always\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"105\"\n     inkscape:window-x=\"331\"\n     inkscape:window-height=\"836\"\n     inkscape:window-width=\"1317\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer1\"\n     inkscape:cy=\"138.81617\"\n     inkscape:cx=\"104.03245\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"1.0\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Mail App Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:contributor>\n          <cc:Agent>\n            <dc:title>Andreas Nilsson</dc:title>\n          </cc:Agent>\n        </dc:contributor>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>mail</rdf:li>\n            <rdf:li>e-mail</rdf:li>\n            <rdf:li>mua</rdf:li>\n            <rdf:li>email</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:date> 2021-01-02</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/apps/internet-mail.svg</dc:identifier>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/apps/accessories-character-map.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for a mail app.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     inkscape:label=\"Layer 1\"\n     id=\"layer1\">\n    <g\n       id=\"g91\"\n       transform=\"matrix(5.5109233,0,0,5.5109314,-8.6667191,-1.9326354)\">\n      <g\n         transform=\"matrix(0.02269972,0,0,0.02297929,44.98918,37.78447)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <path\n         style=\"fill:url(#linearGradient27486);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient27488);stroke-width:0.856604;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"M 6.3334395,16.972251 V 41.481799 H 43.305555 l -0.06106,-24.39194 C 43.24105,15.712272 31.395999,2.412111 29.210877,2.412111 h -8.551486 c -2.297319,0 -14.3259515,13.261842 -14.3259515,14.56014 z\"\n         id=\"path12723\"\n         sodipodi:nodetypes=\"ccczzzz\" />\n      <path\n         style=\"fill:url(#linearGradient27483);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         d=\"M 6.923061,16.787103 C 6.5250222,16.356975 18.809966,3.0935378 20.66721,3.0935378 h 8.375755 c 1.747484,0 14.036602,13.1280652 13.427114,13.8854182 L 31.608858,30.47515 19.295373,30.156846 Z\"\n         id=\"path18153\"\n         sodipodi:nodetypes=\"czzzccz\" />\n      <path\n         style=\"fill:#000000;fill-opacity:0.146199;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 19.07753,30.01759 -7.333004,-8.746004 24.818425,-6.936073 3.02927,6.216453 -7.416265,9.440332\"\n         id=\"path2164\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"fill:#000000;fill-opacity:0.146199;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 18.291767,29.836259 -7.4826,-8.810113 24.64747,-6.893334 3.174077,6.270999 -7.240521,9.407157\"\n         id=\"path2162\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"fill:#000000;fill-opacity:0.146199;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 18.775313,29.957146 -7.674927,-8.660522 24.968019,-7.064295 3.285709,6.592397 -7.480375,9.107129\"\n         id=\"path2160\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"fill:url(#linearGradient27477);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 18.593984,30.440693 -7.333009,-8.746004 24.711579,-6.893334 3.110815,6.387415 -7.120171,8.985931\"\n         id=\"path15105\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"fill:url(#linearGradient27474);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"M 20.488434,29.064331 7.0924698,40.036319 21.001312,30.432013 H 30.01947 L 42.438517,39.914206 30.575092,29.064331 Z\"\n         id=\"path14245\"\n         sodipodi:nodetypes=\"ccccccc\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient27471);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 6.9634751,16.885144 11.5161729,14.31619 1.068503,-0.854802 z\"\n         id=\"path14339\"\n         sodipodi:nodetypes=\"cccc\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:url(#linearGradient27468);stroke-width:0.856604;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 7.3077115,17.131415 0.031153,23.211006 H 42.283659 L 42.221353,17.257512 C 42.219329,16.508413 31.005032,3.4591863 28.837233,3.4591863 h -7.895654 c -2.252266,0 -13.6349135,12.8918807 -13.6338675,13.6722287 z\"\n         id=\"path15103\"\n         sodipodi:nodetypes=\"ccczzzz\" />\n      <path\n         style=\"fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 20.957271,30.452732 -11.9414988,8.270856 2.2194328,0.0061 9.998125,-6.86894 8.821908,-1.422838 z\"\n         id=\"path17393\"\n         sodipodi:nodetypes=\"cccccc\" />\n      <path\n         style=\"fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         d=\"m 11.427536,21.670296 1.324943,1.410423 22.790832,-6.88419 2.915134,5.682367 0.614051,-0.711915 -3.069415,-6.377836 z\"\n         id=\"path2174\"\n         sodipodi:nodetypes=\"ccccccc\" />\n      <path\n         style=\"fill:url(#linearGradient27463);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         d=\"m 13.308098,23.63634 6.026352,6.453753 1.196724,-1.025762 10.086657,0.04274 0.812062,0.72658 3.974828,-4.744149 C 34.25074,23.679081 13.308098,23.63634 13.308098,23.63634 Z\"\n         id=\"path2272\"\n         sodipodi:nodetypes=\"ccccccc\" />\n      <path\n         sodipodi:nodetypes=\"cccc\"\n         id=\"path27492\"\n         d=\"M 41.812936,17.847945 31.861315,30.479232 30.792812,29.624431 Z\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b1b1b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(presentation) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\x-office-presentation.png\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg11300\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"x-office-presentation.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title116\">Office Presentation Icon</title>\n  <defs\n     id=\"defs3\">\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient10020\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop10022\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop10024\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2456\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2458\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2460\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2456\"\n       id=\"radialGradient2462\"\n       gradientTransform=\"scale(1.164226,0.85894)\"\n       cx=\"28.283663\"\n       cy=\"47.400623\"\n       fx=\"28.283663\"\n       fy=\"47.400623\"\n       r=\"13.804391\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient6687\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6689\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop6691\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient6719\">\n      <stop\n         style=\"stop-color:#73d216;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6721\" />\n      <stop\n         style=\"stop-color:#d5f7b3;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6723\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient6711\">\n      <stop\n         style=\"stop-color:#5b8ccb;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop6713\" />\n      <stop\n         style=\"stop-color:#3465a4;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6715\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient6699\">\n      <stop\n         style=\"stop-color:#ff7171;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop6701\" />\n      <stop\n         style=\"stop-color:#cc0000;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6703\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient9214\">\n      <stop\n         style=\"stop-color:#5b5b5b;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop9216\" />\n      <stop\n         style=\"stop-color:#5b5b5b;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop9218\" />\n    </linearGradient>\n    <linearGradient\n       y2=\"11.0039\"\n       x2=\"20.9453\"\n       y1=\"25.4727\"\n       x1=\"27.2949\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"aigrd5\">\n      <stop\n         id=\"stop13012\"\n         style=\"stop-color:#f5f5f5;stop-opacity:1;\"\n         offset=\"0\" />\n      <stop\n         id=\"stop13014\"\n         style=\"stop-color:#e1e1e1;stop-opacity:1;\"\n         offset=\"1\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd5\"\n       id=\"linearGradient1553\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.868867,0,0,1.5088,-20.39097,-10.01652)\"\n       x1=\"27.2949\"\n       y1=\"25.4727\"\n       x2=\"20.9453\"\n       y2=\"11.0039\" />\n    <linearGradient\n       y2=\"10.4377\"\n       x2=\"24.6035\"\n       y1=\"9.3433\"\n       x1=\"24.6035\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"aigrd6\">\n      <stop\n         id=\"stop13035\"\n         style=\"stop-color:#F0F0F0\"\n         offset=\"0\" />\n      <stop\n         id=\"stop13037\"\n         style=\"stop-color:#686868\"\n         offset=\"1\" />\n    </linearGradient>\n    <radialGradient\n       gradientUnits=\"userSpaceOnUse\"\n       fy=\"30.9912\"\n       fx=\"24.7744\"\n       r=\"0.5902\"\n       cy=\"30.9912\"\n       cx=\"24.7744\"\n       id=\"aigrd7\">\n      <stop\n         id=\"stop13046\"\n         style=\"stop-color:#F0F0F0\"\n         offset=\"0\" />\n      <stop\n         id=\"stop13048\"\n         style=\"stop-color:#848484\"\n         offset=\"1\" />\n    </radialGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd7\"\n       id=\"radialGradient1537\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(3.502527,0,0,3.502527,-61.93009,-72.87696)\"\n       cx=\"24.7744\"\n       cy=\"30.9912\"\n       fx=\"24.7744\"\n       fy=\"30.9912\"\n       r=\"0.5902\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient9214\"\n       id=\"radialGradient9220\"\n       cx=\"26.162951\"\n       cy=\"44.022526\"\n       fx=\"26.162951\"\n       fy=\"44.022526\"\n       r=\"12.197592\"\n       gradientTransform=\"matrix(1,0,0,0.181159,0,36.04743)\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd6\"\n       id=\"linearGradient9224\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.905258,0,0,2.521777,-22.82065,-13.24604)\"\n       x1=\"24.919374\"\n       y1=\"6.1478682\"\n       x2=\"24.919374\"\n       y2=\"7.4600263\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6687\"\n       id=\"linearGradient10002\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-20.750000\"\n       y1=\"29.000000\"\n       x2=\"-19.500000\"\n       y2=\"18.750000\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6699\"\n       id=\"linearGradient10012\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-22.976406\"\n       y1=\"18.516047\"\n       x2=\"-14.360273\"\n       y2=\"33.016045\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6711\"\n       id=\"linearGradient10014\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-16.387411\"\n       y1=\"24.453547\"\n       x2=\"-9.7352734\"\n       y2=\"28.195539\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6719\"\n       id=\"linearGradient10016\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-17.863041\"\n       y1=\"30.827509\"\n       x2=\"-20.821646\"\n       y2=\"25.015009\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient10020\"\n       id=\"linearGradient10026\"\n       x1=\"23.379572\"\n       y1=\"28.369167\"\n       x2=\"24.24518\"\n       y2=\"6.0000024\"\n       gradientUnits=\"userSpaceOnUse\" />\n  </defs>\n  <sodipodi:namedview\n     stroke=\"#ef2929\"\n     fill=\"#eeeeec\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.25490196\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"2\"\n     inkscape:cx=\"95.591611\"\n     inkscape:cy=\"104.23137\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:window-width=\"1270\"\n     inkscape:window-height=\"858\"\n     inkscape:window-x=\"462\"\n     inkscape:window-y=\"30\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:title>Office Presentation Icon</dc:title>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-presentation.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-document.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>rich</rdf:li>\n            <rdf:li>text</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>pdf</rdf:li>\n            <rdf:li>openoffice</rdf:li>\n            <rdf:li>word</rdf:li>\n            <rdf:li>rtf</rdf:li>\n            <rdf:li>office</rdf:li>\n            <rdf:li>presentation</rdf:li>\n            <rdf:li>slides</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for an office presentation.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Layer 1\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g114\"\n       transform=\"matrix(5.5559141,0,0,5.5559141,-12.478949,-4.5559141)\">\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path10010\"\n         d=\"M 26.482036,37.621562 H 24.499994 V 6 h 1.982042 v 31.620112 z\"\n         style=\"fill:#a4a4a4;fill-rule:nonzero;stroke:#555753;stroke-miterlimit:4;stroke-opacity:1\" />\n      <path\n         style=\"fill:#a4a4a4;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n         d=\"M 26,37.621562 H 24.982042 V 6 H 26 v 31.620112 z\"\n         id=\"path13009\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <path\n         style=\"fill:url(#linearGradient1553);fill-rule:nonzero;stroke:#888a85;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"M 43.499996,32.499982 H 7.5000001 V 5.4999944 H 43.499996 Z\"\n         id=\"path13016\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.39011;fill:url(#radialGradient9220);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path8339\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         transform=\"matrix(1.749254,0,0,1.452548,-20.38301,-20.43749)\"\n         cx=\"26.162951\"\n         cy=\"44.022526\"\n         rx=\"12.197592\"\n         ry=\"2.2097087\" />\n      <g\n         transform=\"matrix(1.539016,0,0,1.539016,-12.89862,-11.05731)\"\n         style=\"fill:#a4a4a4;fill-rule:nonzero;stroke:#555753;stroke-miterlimit:4;stroke-opacity:1\"\n         id=\"g13020\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\">\n        <path\n           d=\"M 31.492,35.959 25.217,31.321 25.151306,31.665948 30.016,35.955 Z\"\n           id=\"path13022\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\"\n           style=\"stroke:#555753;stroke-opacity:1\"\n           sodipodi:nodetypes=\"ccccc\" />\n        <path\n           d=\"M 18.408,35.959 24.683,31.321 24.63283,31.72338 19.883,35.955 Z\"\n           id=\"path13024\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\"\n           style=\"stroke:#555753;stroke-opacity:1\"\n           sodipodi:nodetypes=\"ccccc\" />\n      </g>\n      <path\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path10018\"\n         d=\"M 42.483508,31.500001 H 8.4999999 V 6.5000025 H 42.483508 Z\"\n         style=\"fill:none;fill-rule:nonzero;stroke:url(#linearGradient10026);stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\" />\n      <path\n         style=\"opacity:0.16;fill:#000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n         d=\"M 37.64607,5.8376811 H 8 V 8 C 9.671372,5.6514612 37.64607,5.8376811 37.64607,5.8376811 Z\"\n         id=\"path13041\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect13420\"\n         width=\"9\"\n         height=\"1\"\n         x=\"31\"\n         y=\"9\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient9224);fill-opacity:1;fill-rule:nonzero;stroke:#555753;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect9222\"\n         width=\"40.779099\"\n         height=\"4\"\n         x=\"5.1403117\"\n         y=\"1.5\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         rx=\"1.941476\"\n         ry=\"1.9414761\" />\n      <rect\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         y=\"11\"\n         x=\"31\"\n         height=\"1\"\n         width=\"9\"\n         id=\"rect9226\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect9228\"\n         width=\"9\"\n         height=\"1\"\n         x=\"31\"\n         y=\"13\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <rect\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         y=\"15\"\n         x=\"31\"\n         height=\"1\"\n         width=\"9\"\n         id=\"rect9230\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect9232\"\n         width=\"6\"\n         height=\"1\"\n         x=\"31\"\n         y=\"17\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <rect\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         y=\"22\"\n         x=\"11\"\n         height=\"1\"\n         width=\"23\"\n         id=\"rect9234\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect9236\"\n         width=\"23\"\n         height=\"1\"\n         x=\"11\"\n         y=\"24\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <rect\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         y=\"26\"\n         x=\"11\"\n         height=\"1\"\n         width=\"23\"\n         id=\"rect9238\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.22807;fill-rule:nonzero;stroke:none;stroke-width:0.998131;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect9240\"\n         width=\"16\"\n         height=\"1\"\n         x=\"11\"\n         y=\"28\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <path\n         style=\"display:inline;fill:url(#radialGradient2462);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         id=\"path1693\"\n         transform=\"matrix(0.512138,0,0,0.512138,2.997478,-5.778852)\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         cx=\"32.92857\"\n         cy=\"40.714287\"\n         rx=\"16.071428\"\n         ry=\"11.857142\" />\n      <g\n         style=\"display:inline\"\n         id=\"g6727\"\n         transform=\"matrix(0.587368,0,0,0.587368,30.84597,-1.301179)\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\">\n        <path\n           id=\"path3931\"\n           d=\"m -27.528542,18.092794 c -2.569034,1.698331 -3.982933,4.005039 -3.982933,6.497902 v 2.069292 c 0,2.49084 1.413899,4.798223 3.982933,6.496553 2.426489,1.603904 5.633126,2.487468 9.029183,2.487468 3.394772,0 6.601409,-0.883564 9.0291816,-2.487468 2.5677499,-1.69833 3.9816497,-4.005038 3.9816497,-6.496553 v -2.069292 c 0,-2.492863 -1.4145419,-4.800246 -3.9816497,-6.497902 -2.4271306,-1.602555 -5.6337676,-2.486793 -9.0291816,-2.486793 -3.396057,0 -6.602694,0.884238 -9.029183,2.486793 z\"\n           style=\"fill:#670000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3933\"\n           d=\"m -7.0244261,24.453547 c -1.3785844,-3.386544 -6.0530579,-5.880082 -11.6123419,-5.880082 -5.559285,0 -10.233758,2.493538 -11.612343,5.880082 h -0.414795 v 2.069967 c 0,4.390164 5.385276,7.948699 12.027138,7.948699 6.642503,0 12.0264951,-3.558535 12.0264951,-7.948699 v -2.069967 z\"\n           style=\"fill:#a40000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3935\"\n           d=\"m -6.6102729,24.453547 c 0,4.390838 -5.3839921,7.949374 -12.0264951,7.949374 -6.642504,0 -12.027138,-3.558536 -12.027138,-7.949374 0,-4.390839 5.385276,-7.949374 12.027138,-7.949374 6.642503,0 12.0264951,3.558535 12.0264951,7.949374 z\"\n           style=\"fill:url(#linearGradient10012);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3937\"\n           d=\"m -6.6102729,26.833098 -0.01541,-2.166417 c -1.304101,4.500778 -4.2365631,6.407522 -7.9234901,7.340997 v 1.994425 c 3.990639,-1.00362 7.561989,-3.288745 7.9389001,-7.169005 z\"\n           style=\"fill:#204a87;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3939\"\n           d=\"m -6.6102729,24.453547 c -0.27546,5.079478 -6.5577471,7.395629 -7.9613731,7.483985 l -4.065765,-7.483985 h 12.026496 z\"\n           style=\"fill:url(#linearGradient10014);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3941\"\n           d=\"m -21.154435,34.298198 v -2.069292 c 2.263396,0.294746 4.339941,0.346681 6.582789,-0.213809 l 0.02247,1.987681 c -1.87942,0.616471 -4.819587,0.645473 -6.605262,0.296095 z\"\n           style=\"fill:#4e9a06;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3943\"\n           d=\"m -18.637411,24.454221 4.065765,7.483311 c -2.489414,0.948988 -6.582789,0.291374 -6.582789,0.291374 z\"\n           style=\"fill:url(#linearGradient10016);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           transform=\"matrix(0.946982,0,0,0.889701,-0.987461,2.688545)\"\n           id=\"path5959\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.311111;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient10002);stroke-width:1.8548;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\"\n           cx=\"-18.625\"\n           cy=\"24.375\"\n           rx=\"11.75\"\n           ry=\"7.75\" />\n      </g>\n      <g\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"g10004\"\n         style=\"fill:#a4a4a4;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n         transform=\"matrix(1.539016,0,0,1.539016,-12.89862,-11.05731)\">\n        <path\n           inkscape:r_cy=\"true\"\n           inkscape:r_cx=\"true\"\n           id=\"path10006\"\n           d=\"m 30.015,35.956 1.477,0.003 -6.275,-4.638 -0.439,-0.014 5.238,4.648 z\" />\n        <path\n           inkscape:r_cy=\"true\"\n           inkscape:r_cx=\"true\"\n           id=\"path10008\"\n           d=\"m 19.884,35.956 -1.476,0.003 6.275,-4.638 0.438,-0.014 -5.238,4.648 z\" />\n      </g>\n      <path\n         style=\"fill:url(#radialGradient1537);fill-rule:nonzero;stroke:#555753;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 27.839689,36.499985 c 0,1.292433 -1.047259,2.339691 -2.339691,2.339691 -1.292433,0 -2.33969,-1.047258 -2.33969,-2.339691 0,-1.288928 1.047257,-2.339685 2.33969,-2.339685 1.292432,0 2.339691,1.050757 2.339691,2.339685 z\"\n         id=\"path13050\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(script) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\text-x-script.png\"\n   sodipodi:docname=\"text-x-script.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg249\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title124\">Generic Script Icon</title>\n  <defs\n     id=\"defs3\">\n    <inkscape:perspective\n       sodipodi:type=\"inkscape:persp3d\"\n       inkscape:vp_x=\"0 : 24 : 1\"\n       inkscape:vp_y=\"0 : 1000 : 0\"\n       inkscape:vp_z=\"48 : 24 : 1\"\n       inkscape:persp3d-origin=\"24 : 16 : 1\"\n       id=\"perspective76\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient3082\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop3084\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop3086\" />\n    </linearGradient>\n    <linearGradient\n       id=\"aigrd1\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"99.7773\"\n       y1=\"15.4238\"\n       x2=\"153.0005\"\n       y2=\"248.6311\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#464646;stop-opacity:1\"\n         id=\"stop53300\" />\n      <stop\n         offset=\"1\"\n         style=\"stop-color:#cdcdcd;stop-opacity:1\"\n         id=\"stop53302\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4542\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4544\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop4546\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         id=\"stop15664\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop15666\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       id=\"aigrd3\"\n       cx=\"20.8921\"\n       cy=\"64.5679\"\n       r=\"5.257\"\n       fx=\"20.8921\"\n       fy=\"64.5679\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15573\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15575\" />\n    </radialGradient>\n    <radialGradient\n       id=\"aigrd2\"\n       cx=\"20.8921\"\n       cy=\"114.5684\"\n       r=\"5.256\"\n       fx=\"20.8921\"\n       fy=\"114.5684\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15566\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15568\" />\n    </radialGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         id=\"stop270\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop271\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         id=\"stop260\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop261\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient269\"\n       id=\"radialGradient15656\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.8244190\"\n       cy=\"3.7561285\"\n       fx=\"8.8244190\"\n       fy=\"3.7561285\"\n       r=\"37.751713\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient259\"\n       id=\"radialGradient15658\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(0.960493,1.041132)\"\n       cx=\"33.966679\"\n       cy=\"35.736916\"\n       fx=\"33.966679\"\n       fy=\"35.736916\"\n       r=\"86.708450\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient15662\"\n       id=\"radialGradient15668\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.1435566\"\n       cy=\"7.2678967\"\n       fx=\"8.1435566\"\n       fy=\"7.2678967\"\n       r=\"38.158695\" />\n    <radialGradient\n       r=\"5.256\"\n       fy=\"114.5684\"\n       fx=\"20.8921\"\n       cy=\"114.5684\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2283\"\n       xlink:href=\"#aigrd2\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"5.257\"\n       fy=\"64.5679\"\n       fx=\"20.8921\"\n       cy=\"64.5679\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2285\"\n       xlink:href=\"#aigrd3\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4542\"\n       id=\"radialGradient4548\"\n       cx=\"24.306795\"\n       cy=\"42.07798\"\n       fx=\"24.306795\"\n       fy=\"42.07798\"\n       r=\"15.821514\"\n       gradientTransform=\"matrix(1.000000,0.000000,0.000000,0.284916,0.000000,30.08928)\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#aigrd1\"\n       id=\"linearGradient2193\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.200685,0,0,0.200685,25.33302,3.157373)\"\n       x1=\"99.7773\"\n       y1=\"15.4238\"\n       x2=\"153.0005\"\n       y2=\"248.6311\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient3082\"\n       id=\"linearGradient3088\"\n       x1=\"44.592766\"\n       y1=\"9.9124937\"\n       x2=\"65.862885\"\n       y2=\"43.31715\"\n       gradientUnits=\"userSpaceOnUse\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"42\"\n     inkscape:window-x=\"333\"\n     inkscape:window-height=\"886\"\n     inkscape:window-width=\"1572\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer5\"\n     inkscape:cy=\"119.73769\"\n     inkscape:cx=\"45.372094\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.25490196\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Generic Script Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>text</rdf:li>\n            <rdf:li>plaintext</rdf:li>\n            <rdf:li>regular</rdf:li>\n            <rdf:li>script</rdf:li>\n            <rdf:li>shell</rdf:li>\n            <rdf:li>bash</rdf:li>\n            <rdf:li>python</rdf:li>\n            <rdf:li>perl</rdf:li>\n            <rdf:li>php</rdf:li>\n            <rdf:li>ruby</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-script.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for a script.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     id=\"layer5\"\n     inkscape:label=\"Text\"\n     style=\"display:inline\">\n    <g\n       id=\"g122\"\n       transform=\"matrix(5.6226375,0,0,5.6226457,-14.462278,-15.691352)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15391\"\n         width=\"34.875\"\n         height=\"40.920494\"\n         x=\"6.6035528\"\n         y=\"3.6464462\"\n         ry=\"1.1490486\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15660\"\n         width=\"32.775887\"\n         height=\"38.946384\"\n         x=\"7.6660538\"\n         y=\"4.5839462\"\n         ry=\"0.14904857\"\n         rx=\"0.14904857\" />\n      <g\n         transform=\"translate(0.646447,-0.03798933)\"\n         id=\"g2270\"\n         style=\"display:inline\">\n        <g\n           id=\"g1440\"\n           style=\"fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4\"\n           transform=\"matrix(0.229703,0,0,0.229703,4.967081,4.244972)\">\n          <radialGradient\n             id=\"radialGradient1442\"\n             cx=\"20.892099\"\n             cy=\"114.5684\"\n             r=\"5.256\"\n             fx=\"20.892099\"\n             fy=\"114.5684\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1444\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1446\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1448\" />\n          <radialGradient\n             id=\"radialGradient1450\"\n             cx=\"20.892099\"\n             cy=\"64.567902\"\n             r=\"5.257\"\n             fx=\"20.892099\"\n             fy=\"64.567902\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1452\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1454\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1456\" />\n        </g>\n        <path\n           style=\"fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15570\" />\n        <path\n           style=\"fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15577\" />\n      </g>\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.988553;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.0175438\"\n         d=\"M 11.505723,5.4942766 V 43.400869\"\n         id=\"path15672\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.204678\"\n         d=\"M 12.5,5.0205154 V 43.038228\"\n         id=\"path15674\"\n         sodipodi:nodetypes=\"cc\" />\n      <g\n         id=\"g2186\"\n         transform=\"matrix(0.703833,0,0,0.703833,-1.924835,14.32997)\">\n        <path\n           id=\"path53304\"\n           d=\"M 50.204582,47.404518 30.293968,27.493904 50.204582,7.5832887 70.115196,27.493904 Z\"\n           style=\"fill:url(#linearGradient2193);fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1.42079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" />\n        <path\n           id=\"path53361\"\n           d=\"m 34.844554,31.353332 0.738449,-1.024184 c 0.63675,0.268492 1.300619,0.485069 1.986184,0.644885 l -0.0058,1.576858 c 0.427728,0.08834 0.86301,0.156136 1.304105,0.204371 l 0.481774,-1.501889 c 0.344041,0.02848 0.691764,0.04417 1.043361,0.04417 0.351209,0 0.699124,-0.0155 1.043166,-0.04417 l 0.481775,1.501889 c 0.441288,-0.04824 0.876376,-0.116036 1.304104,-0.204371 l -0.006,-1.577051 c 0.685758,-0.159623 1.349433,-0.3762 1.986182,-0.644692 l 0.92248,1.279502 c 0.402351,-0.182094 0.794241,-0.382591 1.174895,-0.600522 l -0.492817,-1.498016 c 0.59723,-0.36225 1.161723,-0.773319 1.687471,-1.227972 l 1.272141,0.931779 c 0.325638,-0.296581 0.637329,-0.608272 0.933716,-0.93391 l -0.931585,-1.271947 c 0.454847,-0.525748 0.865916,-1.090047 1.228166,-1.687665 l 1.498015,0.493011 c 0.217932,-0.380848 0.418623,-0.772932 0.600329,-1.175088 L 51.81534,23.716033 c 0.268492,-0.636749 0.485068,-1.300618 0.645079,-1.986376 l 1.576663,0.0058 c 0.08834,-0.427727 0.156137,-0.86301 0.204178,-1.304298 l -1.501695,-0.481774 c 0.02886,-0.343848 0.04417,-0.691764 0.04417,-1.043167 0,-0.351403 -0.01569,-0.699125 -0.04417,-1.043361 L 54.24126,17.381094 C 54.193413,16.94 54.125223,16.504911 54.037276,16.07699 l -1.577051,0.006 c -0.159817,-0.685759 -0.376393,-1.349627 -0.644691,-1.986181 l 1.279308,-0.922289 c -0.181707,-0.402351 -0.382591,-0.794242 -0.600135,-1.17509 l -1.498209,0.493011 C 50.634247,11.895022 50.223179,11.330723 49.768525,10.805169 L 50.700111,9.5330282 C 50.421739,9.2271488 50.129033,8.9350234 49.824703,8.6549084 L 30.985708,27.494098 31.99265,28.50104 32.291362,28.282334 c 0.525748,0.454653 1.090046,0.865722 1.68747,1.227972 l -0.241953,0.735157 1.108062,1.108062 z\"\n           style=\"opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\" />\n        <path\n           id=\"path53363\"\n           d=\"m 54.367757,36.399276 c 0,-6.484682 4.233883,-11.979469 10.08724,-13.874023 l -2.226972,-2.227167 c -0.01685,0.007 -0.0339,0.01298 -0.05056,0.02015 L 61.995952,20.066404 60.583948,18.6544 c -0.463178,0.2189 -0.91667,0.45446 -1.359314,0.707648 l 0.694089,2.109193 c -0.841314,0.509669 -1.635748,1.08869 -2.375747,1.728732 l -1.79111,-1.311659 c -0.458721,0.41746 -0.897297,0.856036 -1.314564,1.314565 l 1.311465,1.790914 c -0.640041,0.740195 -1.218868,1.534628 -1.728731,2.375748 l -2.109387,-0.694089 c -0.306654,0.536403 -0.589093,1.088304 -0.844994,1.654732 l 1.801182,1.298293 c -0.377942,0.896329 -0.682852,1.831014 -0.907758,2.796501 l -2.219999,-0.0085 c -0.124172,0.602266 -0.219869,1.215188 -0.287476,1.836051 l 2.114423,0.678398 c -0.04029,0.484293 -0.06199,0.97401 -0.06199,1.46857 0,0.494753 0.0217,0.98447 0.06199,1.468763 l -2.114423,0.677816 c 0.06761,0.621251 0.163304,1.233979 0.28767,1.836245 l 2.219805,-0.0083 c 0.224906,0.965487 0.529816,1.900172 0.907758,2.796502 l -1.801182,1.298486 c 0.142382,0.31479 0.293869,0.624931 0.452136,0.930423 l 3.804023,-3.803636 c -0.61602,-1.614245 -0.95425,-3.365836 -0.95425,-5.196269 z\"\n           style=\"opacity:0.5;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\" />\n        <path\n           style=\"opacity:0.520468;fill:none;fill-rule:nonzero;stroke:url(#linearGradient3088);stroke-width:1.42079;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"\n           d=\"M 50.204564,45.706929 31.991529,27.493894 50.204564,9.2808575 68.417599,27.493894 Z\"\n           id=\"path3078\" />\n      </g>\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(spreadsheet) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   sodipodi:docname=\"x-office-spreadsheet.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg13684\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\x-office-spreadsheet.png\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-ydpi=\"96\">\n\n  <title\n     id=\"title163\">Office Spreadsheet Document Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6687\"\n       id=\"linearGradient6746\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-20.750000\"\n       y1=\"29.000000\"\n       x2=\"-19.500000\"\n       y2=\"18.750000\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient6687\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6689\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop6691\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6687\"\n       id=\"linearGradient6744\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-20.750000\"\n       y1=\"29.000000\"\n       x2=\"-19.500000\"\n       y2=\"18.750000\" />\n    <linearGradient\n       id=\"linearGradient6719\">\n      <stop\n         style=\"stop-color:#73d216;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop6721\" />\n      <stop\n         style=\"stop-color:#d5f7b3;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6723\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6719\"\n       id=\"linearGradient6742\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-17.863041\"\n       y1=\"30.827509\"\n       x2=\"-20.821646\"\n       y2=\"25.015009\" />\n    <linearGradient\n       id=\"linearGradient6711\">\n      <stop\n         style=\"stop-color:#5b8ccb;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop6713\" />\n      <stop\n         style=\"stop-color:#3465a4;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6715\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6711\"\n       id=\"linearGradient6740\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-16.387411\"\n       y1=\"24.453547\"\n       x2=\"-9.7352734\"\n       y2=\"28.195539\" />\n    <linearGradient\n       id=\"linearGradient6699\">\n      <stop\n         style=\"stop-color:#ff7171;stop-opacity:1.0000000;\"\n         offset=\"0.0000000\"\n         id=\"stop6701\" />\n      <stop\n         style=\"stop-color:#cc0000;stop-opacity:1.0000000;\"\n         offset=\"1.0000000\"\n         id=\"stop6703\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient6699\"\n       id=\"linearGradient6738\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"-22.976406\"\n       y1=\"18.516047\"\n       x2=\"-14.360273\"\n       y2=\"33.016045\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient2456\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop2458\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop2460\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         id=\"stop270\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop271\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient269\"\n       id=\"radialGradient15656\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.971646,0,0,1.034707,3.240408,0.495684)\"\n       cx=\"8.8244190\"\n       cy=\"3.7561285\"\n       fx=\"8.8244190\"\n       fy=\"3.7561285\"\n       r=\"37.751713\" />\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         id=\"stop260\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop261\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient259\"\n       id=\"radialGradient15658\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.963839,0,0,1.043088,-0.124825,-0.15197)\"\n       cx=\"33.966679\"\n       cy=\"35.736916\"\n       fx=\"33.966679\"\n       fy=\"35.736916\"\n       r=\"86.708450\" />\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         id=\"stop15664\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop15666\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient15662\"\n       id=\"radialGradient15668\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.974777,0,0,1.034091,3.161873,0.559274)\"\n       cx=\"8.1435566\"\n       cy=\"7.2678967\"\n       fx=\"8.1435566\"\n       fy=\"7.2678967\"\n       r=\"38.158695\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient2456\"\n       id=\"radialGradient2462\"\n       gradientTransform=\"scale(1.164226,0.85894)\"\n       cx=\"28.283663\"\n       cy=\"47.400623\"\n       fx=\"28.283663\"\n       fy=\"47.400623\"\n       r=\"13.804391\"\n       gradientUnits=\"userSpaceOnUse\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:showpageshadow=\"false\"\n     inkscape:window-y=\"30\"\n     inkscape:window-x=\"0\"\n     inkscape:window-height=\"818\"\n     inkscape:window-width=\"1363\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer1\"\n     inkscape:cy=\"128.78603\"\n     inkscape:cx=\"125.03966\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"1.0\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:grid-points=\"true\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Office Spreadsheet Document Icon</dc:title>\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>spreadsheet</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>office</rdf:li>\n            <rdf:li>openoffice</rdf:li>\n            <rdf:li>excel</rdf:li>\n            <rdf:li>rtf</rdf:li>\n            <rdf:li>chart</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-spreadsheet.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-document.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An icon for an office spreadsheet document.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     inkscape:label=\"Layer 1\"\n     id=\"layer1\"\n     style=\"display:inline\">\n    <g\n       id=\"g161\"\n       transform=\"matrix(5.6457375,0,0,5.6457296,-8.9696513,-15.944647)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02144924,0,0,0.02086758,43.32772,41.1536)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15391\"\n         width=\"34.996506\"\n         height=\"40.997345\"\n         x=\"6.5017405\"\n         y=\"3.5013213\"\n         ry=\"1.1490481\"\n         rx=\"1.1490482\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15660\"\n         width=\"32.996056\"\n         height=\"38.996326\"\n         x=\"7.5033512\"\n         y=\"4.5018268\"\n         ry=\"0.14904855\"\n         rx=\"0.14904846\" />\n      <path\n         id=\"rect13655\"\n         d=\"m 10,6.002203 v 4.964094 30.035906 L 20,41 V 11 H 38 V 6.002203 Z\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0.210526;fill-rule:evenodd;stroke:none;stroke-width:0.607876;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         sodipodi:nodetypes=\"cccccccc\" />\n      <path\n         id=\"path13660\"\n         d=\"M 37.500415,10.502203 H 10.499583\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path13662\"\n         d=\"M 37.500755,16.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path13664\"\n         d=\"M 37.500755,22.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path13666\"\n         d=\"M 37.500755,28.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path13668\"\n         d=\"M 37.501332,34.5 H 10.499823\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path13682\"\n         d=\"M 37.500755,40.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path2464\"\n         d=\"M 37.511644,13.5 H 10.5\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path2466\"\n         d=\"M 37.500755,19.5 H 10.49923\"\n         style=\"fill:none;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path2468\"\n         d=\"M 37.500755,25.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path2470\"\n         d=\"M 37.500755,31.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         id=\"path2472\"\n         d=\"M 37.500755,37.5 H 10.49923\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.157895\"\n         d=\"M 37.5,6.4997386 V 40.5003\"\n         id=\"path2485\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.157895\"\n         d=\"M 31.5,6.4996867 V 40.500315\"\n         id=\"path2487\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.157895\"\n         d=\"M 25.5,6.4996865 V 40.500314\"\n         id=\"path2489\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.157895\"\n         d=\"M 19.5,6.4996867 V 40.500315\"\n         id=\"path2491\" />\n      <path\n         style=\"fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.157895\"\n         d=\"M 10.5,6.4996867 V 40.500315\"\n         id=\"path2493\" />\n      <path\n         id=\"path2495\"\n         d=\"M 37.500227,6.502203 H 10.49946\"\n         style=\"fill:#000000;fill-opacity:0.157895;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.192982\" />\n      <ellipse\n         style=\"display:inline;fill:url(#radialGradient2462);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\"\n         id=\"path1693\"\n         transform=\"matrix(0.861667,0,0,0.851476,3.760476,2.091696)\"\n         cx=\"32.92857\"\n         cy=\"40.714287\"\n         rx=\"16.071428\"\n         ry=\"11.857142\" />\n      <g\n         id=\"g6727\"\n         transform=\"translate(51,9.12499)\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         style=\"display:inline\">\n        <path\n           id=\"path3931\"\n           d=\"m -27.528542,18.092794 c -2.569034,1.698331 -3.982933,4.005039 -3.982933,6.497902 v 2.069292 c 0,2.49084 1.413899,4.798223 3.982933,6.496553 2.426489,1.603904 5.633126,2.487468 9.029183,2.487468 3.394772,0 6.601409,-0.883564 9.0291816,-2.487468 2.5677499,-1.69833 3.9816497,-4.005038 3.9816497,-6.496553 v -2.069292 c 0,-2.492863 -1.4145419,-4.800246 -3.9816497,-6.497902 -2.4271306,-1.602555 -5.6337676,-2.486793 -9.0291816,-2.486793 -3.396057,0 -6.602694,0.884238 -9.029183,2.486793 z\"\n           style=\"fill:#670000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3933\"\n           d=\"m -7.0244261,24.453547 c -1.3785844,-3.386544 -6.0530579,-5.880082 -11.6123419,-5.880082 -5.559285,0 -10.233758,2.493538 -11.612343,5.880082 h -0.414795 v 2.069967 c 0,4.390164 5.385276,7.948699 12.027138,7.948699 6.642503,0 12.0264951,-3.558535 12.0264951,-7.948699 v -2.069967 z\"\n           style=\"fill:#a40000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3935\"\n           d=\"m -6.6102729,24.453547 c 0,4.390838 -5.3839921,7.949374 -12.0264951,7.949374 -6.642504,0 -12.027138,-3.558536 -12.027138,-7.949374 0,-4.390839 5.385276,-7.949374 12.027138,-7.949374 6.642503,0 12.0264951,3.558535 12.0264951,7.949374 z\"\n           style=\"fill:url(#linearGradient6738);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3937\"\n           d=\"m -6.6102729,26.833098 -0.01541,-2.166417 c -1.304101,4.500778 -4.2365631,6.407522 -7.9234901,7.340997 v 1.994425 c 3.990639,-1.00362 7.561989,-3.288745 7.9389001,-7.169005 z\"\n           style=\"fill:#204a87;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3939\"\n           d=\"m -6.6102729,24.453547 c -0.27546,5.079478 -6.5577471,7.395629 -7.9613731,7.483985 l -4.065765,-7.483985 h 12.026496 z\"\n           style=\"fill:url(#linearGradient6740);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3941\"\n           d=\"m -21.154435,34.298198 v -2.069292 c 2.263396,0.294746 4.339941,0.346681 6.582789,-0.213809 l 0.02247,1.987681 c -1.87942,0.616471 -4.819587,0.645473 -6.605262,0.296095 z\"\n           style=\"fill:#4e9a06;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <path\n           id=\"path3943\"\n           d=\"m -18.637411,24.454221 4.065765,7.483311 c -2.489414,0.948988 -6.582789,0.291374 -6.582789,0.291374 z\"\n           style=\"fill:url(#linearGradient6742);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\" />\n        <ellipse\n           transform=\"matrix(0.979592,0,0,0.979592,-0.380102,0.497449)\"\n           id=\"path5959\"\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.311111;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6744);stroke-width:1.02083;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\"\n           cx=\"-18.625\"\n           cy=\"24.375\"\n           rx=\"11.75\"\n           ry=\"7.75\" />\n        <ellipse\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;opacity:0.133333;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6746);stroke-width:1.02083;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"path6707\"\n           transform=\"matrix(0.979592,0,0,0.979592,-0.380102,2.497449)\"\n           inkscape:r_cx=\"true\"\n           inkscape:r_cy=\"true\"\n           cx=\"-18.625\"\n           cy=\"24.375\"\n           rx=\"11.75\"\n           ry=\"7.75\" />\n      </g>\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(text) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\text-x-generic.png\"\n   sodipodi:docname=\"text-x-generic.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg249\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title136\">Generic Text Icon</title>\n  <defs\n     id=\"defs3\">\n    <inkscape:perspective\n       sodipodi:type=\"inkscape:persp3d\"\n       inkscape:vp_x=\"0 : 24 : 1\"\n       inkscape:vp_y=\"0 : 1000 : 0\"\n       inkscape:vp_z=\"48 : 24 : 1\"\n       inkscape:persp3d-origin=\"24 : 16 : 1\"\n       id=\"perspective78\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient4542\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop4544\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop4546\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         id=\"stop15664\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop15666\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       id=\"aigrd3\"\n       cx=\"20.8921\"\n       cy=\"64.5679\"\n       r=\"5.257\"\n       fx=\"20.8921\"\n       fy=\"64.5679\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15573\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15575\" />\n    </radialGradient>\n    <radialGradient\n       id=\"aigrd2\"\n       cx=\"20.8921\"\n       cy=\"114.5684\"\n       r=\"5.256\"\n       fx=\"20.8921\"\n       fy=\"114.5684\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15566\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15568\" />\n    </radialGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         id=\"stop270\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop271\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         id=\"stop260\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop261\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient269\"\n       id=\"radialGradient15656\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.8244190\"\n       cy=\"3.7561285\"\n       fx=\"8.8244190\"\n       fy=\"3.7561285\"\n       r=\"37.751713\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient259\"\n       id=\"radialGradient15658\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(0.960493,1.041132)\"\n       cx=\"33.966679\"\n       cy=\"35.736916\"\n       fx=\"33.966679\"\n       fy=\"35.736916\"\n       r=\"86.708450\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient15662\"\n       id=\"radialGradient15668\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.1435566\"\n       cy=\"7.2678967\"\n       fx=\"8.1435566\"\n       fy=\"7.2678967\"\n       r=\"38.158695\" />\n    <radialGradient\n       r=\"5.256\"\n       fy=\"114.5684\"\n       fx=\"20.8921\"\n       cy=\"114.5684\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2283\"\n       xlink:href=\"#aigrd2\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"5.257\"\n       fy=\"64.5679\"\n       fx=\"20.8921\"\n       cy=\"64.5679\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2285\"\n       xlink:href=\"#aigrd3\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient4542\"\n       id=\"radialGradient4548\"\n       cx=\"24.306795\"\n       cy=\"42.07798\"\n       fx=\"24.306795\"\n       fy=\"42.07798\"\n       r=\"15.821514\"\n       gradientTransform=\"matrix(1.000000,0.000000,0.000000,0.284916,0.000000,30.08928)\"\n       gradientUnits=\"userSpaceOnUse\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"160\"\n     inkscape:window-x=\"325\"\n     inkscape:window-height=\"787\"\n     inkscape:window-width=\"1579\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer5\"\n     inkscape:cy=\"113.81592\"\n     inkscape:cx=\"79.144538\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.25490196\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Generic Text Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>text</rdf:li>\n            <rdf:li>plaintext</rdf:li>\n            <rdf:li>regular</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-html.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A general text document icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     id=\"layer5\"\n     inkscape:label=\"Text\"\n     style=\"display:inline\">\n    <g\n       id=\"g134\"\n       transform=\"matrix(5.6640009,0,0,5.6640001,-8.5760275,-16.821472)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15391\"\n         width=\"34.875\"\n         height=\"40.920494\"\n         x=\"6.6035528\"\n         y=\"3.6464462\"\n         ry=\"1.1490486\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15660\"\n         width=\"32.775887\"\n         height=\"38.946384\"\n         x=\"7.6660538\"\n         y=\"4.5839462\"\n         ry=\"0.14904857\"\n         rx=\"0.14904857\" />\n      <g\n         transform=\"translate(0.646447,-0.03798933)\"\n         id=\"g2270\"\n         style=\"display:inline\">\n        <g\n           id=\"g1440\"\n           style=\"fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4\"\n           transform=\"matrix(0.229703,0,0,0.229703,4.967081,4.244972)\">\n          <radialGradient\n             id=\"radialGradient1442\"\n             cx=\"20.892099\"\n             cy=\"114.5684\"\n             r=\"5.256\"\n             fx=\"20.892099\"\n             fy=\"114.5684\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1444\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1446\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1448\" />\n          <radialGradient\n             id=\"radialGradient1450\"\n             cx=\"20.892099\"\n             cy=\"64.567902\"\n             r=\"5.257\"\n             fx=\"20.892099\"\n             fy=\"64.567902\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1452\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1454\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1456\" />\n        </g>\n        <path\n           style=\"fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15570\" />\n        <path\n           style=\"fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15577\" />\n      </g>\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.988553;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.0175438\"\n         d=\"M 11.505723,5.4942766 V 43.400869\"\n         id=\"path15672\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.204678\"\n         d=\"M 12.5,5.0205154 V 43.038228\"\n         id=\"path15674\"\n         sodipodi:nodetypes=\"cc\" />\n      <g\n         transform=\"matrix(0.909091,0,0,1,2.363628,0)\"\n         id=\"g2253\">\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15686\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"9\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15688\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"11\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15690\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"13\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15692\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"15\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15694\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"17\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15696\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"19\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15698\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"21\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15700\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"15.000002\"\n           y=\"23\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15732\"\n           width=\"9.9000053\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"25\"\n           rx=\"0.068204239\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15736\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"29\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15738\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"31\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15740\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"33\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15742\"\n           width=\"22.000004\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"35\"\n           rx=\"0.15156493\"\n           ry=\"0.065390877\" />\n        <rect\n           style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect15744\"\n           width=\"15.400014\"\n           height=\"1\"\n           x=\"14.999992\"\n           y=\"37\"\n           rx=\"0.10609552\"\n           ry=\"0.065390877\" />\n      </g>\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(video) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\video-x-generic.png\"\n   width=\"256px\"\n   height=\"256px\"\n   id=\"svg11300\"\n   sodipodi:version=\"0.32\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:docname=\"video-x-generic.svg\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title72\">Generic Video Icon</title>\n  <defs\n     id=\"defs3\">\n    <inkscape:perspective\n       sodipodi:type=\"inkscape:persp3d\"\n       inkscape:vp_x=\"0 : 24 : 1\"\n       inkscape:vp_y=\"0 : 1000 : 0\"\n       inkscape:vp_z=\"48 : 24 : 1\"\n       inkscape:persp3d-origin=\"24 : 16 : 1\"\n       id=\"perspective40\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient7138\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop7140\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop7142\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient7087\">\n      <stop\n         style=\"stop-color:#888a85;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop7089\" />\n      <stop\n         style=\"stop-color:#b8b9b6;stop-opacity:1;\"\n         offset=\"1\"\n         id=\"stop7091\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient7079\">\n      <stop\n         style=\"stop-color:#000000;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop7081\" />\n      <stop\n         style=\"stop-color:#000000;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop7083\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient7069\">\n      <stop\n         style=\"stop-color:#888a85;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop7071\" />\n      <stop\n         style=\"stop-color:#888a85;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop7073\" />\n    </linearGradient>\n    <radialGradient\n       id=\"aigrd4\"\n       cx=\"9.3418\"\n       cy=\"22.6138\"\n       r=\"14.1515\"\n       fx=\"9.3418\"\n       fy=\"22.6138\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#767676\"\n         id=\"stop6452\" />\n      <stop\n         offset=\"1\"\n         style=\"stop-color:#484848\"\n         id=\"stop6454\" />\n    </radialGradient>\n    <radialGradient\n       r=\"14.1515\"\n       fy=\"24.735121\"\n       fx=\"20.655508\"\n       cy=\"24.735121\"\n       cx=\"20.655508\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient6540\"\n       xlink:href=\"#aigrd4\"\n       inkscape:collect=\"always\"\n       gradientTransform=\"matrix(5.5835717,0,0,5.6792201,-4.7736916,40.385156)\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient7054\">\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop7056\" />\n      <stop\n         style=\"stop-color:#ffffff;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop7058\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7054\"\n       id=\"linearGradient7060\"\n       x1=\"21.03167\"\n       y1=\"31.867859\"\n       x2=\"21.107563\"\n       y2=\"-4.5986342\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(5.3982798,0,0,5.3242688,-8.8306446,6.8804835)\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7069\"\n       id=\"linearGradient7075\"\n       x1=\"46.54464\"\n       y1=\"35.24506\"\n       x2=\"40.820396\"\n       y2=\"34.140205\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(4.6909649,0,0,5.0254169,25.756895,21.774454)\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7079\"\n       id=\"radialGradient7085\"\n       cx=\"23.157747\"\n       cy=\"26.963573\"\n       fx=\"23.157747\"\n       fy=\"26.963573\"\n       r=\"21.566757\"\n       gradientTransform=\"matrix(5.8395127,0,0,3.5145971,-8.290615,57.244313)\"\n       gradientUnits=\"userSpaceOnUse\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7087\"\n       id=\"linearGradient7093\"\n       x1=\"23.816254\"\n       y1=\"12.75\"\n       x2=\"29.049412\"\n       y2=\"25.772396\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(4.3217054,0,0,5.6034763,-0.57276718,-8.6598731)\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7138\"\n       id=\"linearGradient7144\"\n       x1=\"43.6875\"\n       y1=\"32.133045\"\n       x2=\"26.625\"\n       y2=\"32.133045\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(5.5457221,0,0,5.6792201,-13.959136,-0.6196138)\" />\n  </defs>\n  <sodipodi:namedview\n     stroke=\"#ef2929\"\n     fill=\"#eeeeec\"\n     id=\"base\"\n     pagecolor=\"#ffffff\"\n     bordercolor=\"#666666\"\n     borderopacity=\"0.25490196\"\n     inkscape:pageopacity=\"0.0\"\n     inkscape:pageshadow=\"2\"\n     inkscape:zoom=\"1.4142136\"\n     inkscape:cx=\"76.913299\"\n     inkscape:cy=\"99.009961\"\n     inkscape:current-layer=\"layer1\"\n     showgrid=\"false\"\n     inkscape:grid-bbox=\"true\"\n     inkscape:document-units=\"px\"\n     inkscape:showpageshadow=\"false\"\n     inkscape:window-width=\"1209\"\n     inkscape:window-height=\"727\"\n     inkscape:window-x=\"400\"\n     inkscape:window-y=\"37\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:title>Generic Video Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>video</rdf:li>\n            <rdf:li>audio</rdf:li>\n            <rdf:li>multimedia</rdf:li>\n            <rdf:li>movie</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic-template.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/text-x-generic.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>A video, film, or movie icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     id=\"layer1\"\n     inkscape:label=\"Layer 1\"\n     inkscape:groupmode=\"layer\">\n    <g\n       id=\"g70\"\n       transform=\"matrix(1.008422,0,0,1.0084201,-0.008422,-1.2441707)\">\n      <ellipse\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.703297;fill:url(#radialGradient7085);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.55983;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path7077\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         cx=\"126.93934\"\n         cy=\"152.01048\"\n         rx=\"125.93934\"\n         ry=\"75.798515\" />\n      <ellipse\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path7028\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#a1a39f;fill-opacity:1;fill-rule:evenodd;stroke:#6d6f6a;stroke-width:5.67922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"110.71111\"\n         cy=\"136.25481\"\n         rx=\"105.06542\"\n         ry=\"72.244728\" />\n      <ellipse\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.54105;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path7042\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         cx=\"107.7793\"\n         cy=\"121.94464\"\n         rx=\"63.999977\"\n         ry=\"46.938557\" />\n      <path\n         style=\"fill:url(#radialGradient6540);fill-rule:nonzero;stroke:#3b3d39;stroke-width:5.6312;stroke-miterlimit:4;stroke-opacity:1\"\n         d=\"m 241.20567,222.1548 c 0,0 -46.47705,-21.22329 -76.24924,-18.55241 -31.73151,2.84664 -84.740621,4.75599 -105.518879,-28.61952 88.209809,27.05845 128.907869,-17.8654 188.609589,7.43702 0,0 -6.84147,39.73491 -6.84147,39.73491 z\"\n         id=\"path6456\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"czccc\" />\n      <ellipse\n         inkscape:r_cy=\"true\"\n         inkscape:r_cx=\"true\"\n         id=\"path7026\"\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7093);fill-opacity:1;fill-rule:evenodd;stroke:#757972;stroke-width:6.073;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         cx=\"110.71114\"\n         cy=\"109.01313\"\n         rx=\"63.745155\"\n         ry=\"46.22868\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:5.67922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"M 102.72475,31.858426 C 48.445552,34.843843 5.6456996,68.288465 5.645699,108.70537 c 0,42.37293 47.069339,76.84696 105.065451,76.84695 57.99612,0 105.06545,-34.47403 105.06545,-76.84695 0,-42.372919 -47.06933,-76.846944 -105.06545,-76.846944 -0.22655,0 -0.4837,-0.001 -0.7099,0 -1.35197,0.0062 -2.74253,-0.04339 -4.08194,0 -0.654,0.02118 -1.30139,-0.02993 -1.95223,0 -0.42878,0.01971 -0.81493,-0.02351 -1.24233,0 z M 94.915836,44.28172 c 0.35921,-0.02902 0.7019,0.01971 1.064853,0 0.761605,-0.04134 1.530798,0 2.30718,0 16.562811,10e-7 29.993351,9.667186 29.993351,21.474551 0,11.807366 -13.43054,21.297075 -29.993351,21.297075 -16.562807,0 -29.993346,-9.489709 -29.993346,-21.297075 0,-10.990131 11.653485,-20.266087 26.621313,-21.474551 z m 65.310954,26.088917 c 0.37852,-0.03408 0.68256,0.02442 1.06485,0 0.66306,-0.04203 1.2786,0.01193 1.95223,0 0.27374,-0.005 0.43452,0 0.70991,0 17.62517,0 31.94557,10.303259 31.94557,22.894356 0,12.591097 -14.3204,22.716877 -31.94557,22.716877 -17.62518,1e-5 -31.94558,-10.12578 -31.94558,-22.716877 -10e-6,-11.631059 12.4476,-21.483393 28.21859,-22.894356 z M 51.079407,88.295676 c 1.23708,-0.101204 2.629675,0 3.904459,0 18.130259,0 32.832953,10.4631 32.832953,23.426784 0,12.96368 -14.702694,23.42678 -32.832953,23.42678 -18.130254,0 -32.832953,-10.4631 -32.832953,-23.42678 0,-12.052169 12.571531,-22.088396 28.928494,-23.426784 z m 65.488433,29.106004 c 0.13619,-0.0159 0.21831,0.0148 0.35495,0 0.0153,-6.7e-4 0.16299,-1.9e-4 0.17747,0 0.0148,2.5e-4 0.1618,5.6e-4 0.17748,0 0.0352,6e-4 0.15936,6.5e-4 0.17747,0 0.14852,0.001 0.38341,-0.002 0.53243,0 0.0182,-4.4e-4 0.14209,-4.7e-4 0.17748,0 1.36855,-0.11234 2.67167,0 4.08193,0 20.05709,0 36.38246,11.52632 36.38246,25.91144 0,14.38512 -16.32537,26.08892 -36.38246,26.08892 -20.05708,0 -36.38246,-11.7038 -36.38246,-26.08892 0,-12.9598 13.411144,-23.9022 30.70325,-25.91144 z\"\n         id=\"path7012\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\" />\n      <ellipse\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient7060);stroke-width:5.67922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"path7044\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         cx=\"110.93275\"\n         cy=\"108.08749\"\n         rx=\"99.72332\"\n         ry=\"71.531708\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7075);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.48699;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 246.0606,183.92043 -5.73364,34.35923 c -13.83107,-4.9718 -22.17011,-8.90591 -37.48607,-12.81721 l 1.75911,-27.9 c 10.06461,-1.14326 25.78149,0.80494 41.4606,6.35798 z\"\n         id=\"path7067\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"ccccc\" />\n      <path\n         style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.703297;fill:url(#linearGradient7144);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.61208;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         d=\"m 245.99659,182.89019 -1.03982,4.96931 c -44.94753,-17.20171 -86.32508,-1.28758 -129.63126,0 58.84596,-5.01236 78.14057,-21.10203 130.67108,-4.96931 z\"\n         id=\"path7136\"\n         inkscape:r_cx=\"true\"\n         inkscape:r_cy=\"true\"\n         sodipodi:nodetypes=\"cccc\" />\n    </g>\n  </g>\n</svg>\n}\n\nset ::tk::icons::svgData(word) {\n<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n   xmlns:cc=\"http://creativecommons.org/ns#\"\n   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n   xmlns:svg=\"http://www.w3.org/2000/svg\"\n   xmlns=\"http://www.w3.org/2000/svg\"\n   xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n   xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n   xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n   inkscape:export-ydpi=\"96\"\n   inkscape:export-xdpi=\"96\"\n   inkscape:export-filename=\"..\\..\\256x256\\mimetypes\\x-office-document.png\"\n   sodipodi:docname=\"x-office-document.svg\"\n   inkscape:version=\"1.0.1 (3bc2e813f5, 2020-09-07)\"\n   sodipodi:version=\"0.32\"\n   id=\"svg249\"\n   height=\"256px\"\n   width=\"256px\"\n   inkscape:output_extension=\"org.inkscape.output.svg.inkscape\"\n   version=\"1.1\">\n  <title\n     id=\"title158\">Office Document Icon</title>\n  <defs\n     id=\"defs3\">\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6719\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       inkscape:collect=\"always\"\n       id=\"linearGradient5060\">\n      <stop\n         style=\"stop-color:black;stop-opacity:1;\"\n         offset=\"0\"\n         id=\"stop5062\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5064\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5060\"\n       id=\"radialGradient6717\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)\"\n       cx=\"605.71429\"\n       cy=\"486.64789\"\n       fx=\"605.71429\"\n       fy=\"486.64789\"\n       r=\"117.14286\" />\n    <linearGradient\n       id=\"linearGradient5048\">\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"0\"\n         id=\"stop5050\" />\n      <stop\n         id=\"stop5056\"\n         offset=\"0.5\"\n         style=\"stop-color:black;stop-opacity:1;\" />\n      <stop\n         style=\"stop-color:black;stop-opacity:0;\"\n         offset=\"1\"\n         id=\"stop5052\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient5048\"\n       id=\"linearGradient6715\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)\"\n       x1=\"302.85715\"\n       y1=\"366.64789\"\n       x2=\"302.85715\"\n       y2=\"609.50507\" />\n    <linearGradient\n       id=\"linearGradient7648\"\n       gradientUnits=\"userSpaceOnUse\"\n       x1=\"21.9326\"\n       y1=\"24.6274\"\n       x2=\"21.9326\"\n       y2=\"7.1091\"\n       style=\"stroke-dasharray:none;stroke-miterlimit:4.0000000;stroke-width:1.2166667\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#8595bc;stop-opacity:1;\"\n         id=\"stop7650\" />\n      <stop\n         offset=\"1\"\n         style=\"stop-color:#041a3b;stop-opacity:1;\"\n         id=\"stop7652\" />\n    </linearGradient>\n    <linearGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient7648\"\n       id=\"linearGradient7671\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(1.098989,0,0,-0.797757,-1.953865,37.324)\"\n       x1=\"21.9326\"\n       y1=\"24.627399\"\n       x2=\"21.9326\"\n       y2=\"7.1090999\" />\n    <linearGradient\n       id=\"linearGradient15662\">\n      <stop\n         id=\"stop15664\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#ffffff;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop15666\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#f8f8f8;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       id=\"aigrd3\"\n       cx=\"20.8921\"\n       cy=\"64.5679\"\n       r=\"5.257\"\n       fx=\"20.8921\"\n       fy=\"64.5679\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15573\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15575\" />\n    </radialGradient>\n    <radialGradient\n       id=\"aigrd2\"\n       cx=\"20.8921\"\n       cy=\"114.5684\"\n       r=\"5.256\"\n       fx=\"20.8921\"\n       fy=\"114.5684\"\n       gradientUnits=\"userSpaceOnUse\">\n      <stop\n         offset=\"0\"\n         style=\"stop-color:#F0F0F0\"\n         id=\"stop15566\" />\n      <stop\n         offset=\"1.0000000\"\n         style=\"stop-color:#9a9a9a;stop-opacity:1.0000000;\"\n         id=\"stop15568\" />\n    </radialGradient>\n    <linearGradient\n       id=\"linearGradient269\">\n      <stop\n         id=\"stop270\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#a3a3a3;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop271\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#4c4c4c;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <linearGradient\n       id=\"linearGradient259\">\n      <stop\n         id=\"stop260\"\n         offset=\"0.0000000\"\n         style=\"stop-color:#fafafa;stop-opacity:1.0000000;\" />\n      <stop\n         id=\"stop261\"\n         offset=\"1.0000000\"\n         style=\"stop-color:#bbbbbb;stop-opacity:1.0000000;\" />\n    </linearGradient>\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient269\"\n       id=\"radialGradient15656\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.8244190\"\n       cy=\"3.7561285\"\n       fx=\"8.8244190\"\n       fy=\"3.7561285\"\n       r=\"37.751713\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient259\"\n       id=\"radialGradient15658\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"scale(0.960493,1.041132)\"\n       cx=\"33.966679\"\n       cy=\"35.736916\"\n       fx=\"33.966679\"\n       fy=\"35.736916\"\n       r=\"86.708450\" />\n    <radialGradient\n       inkscape:collect=\"always\"\n       xlink:href=\"#linearGradient15662\"\n       id=\"radialGradient15668\"\n       gradientUnits=\"userSpaceOnUse\"\n       gradientTransform=\"matrix(0.968273,0,0,1.032767,3.353553,0.646447)\"\n       cx=\"8.1435566\"\n       cy=\"7.2678967\"\n       fx=\"8.1435566\"\n       fy=\"7.2678967\"\n       r=\"38.158695\" />\n    <radialGradient\n       r=\"5.256\"\n       fy=\"114.5684\"\n       fx=\"20.8921\"\n       cy=\"114.5684\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2283\"\n       xlink:href=\"#aigrd2\"\n       inkscape:collect=\"always\" />\n    <radialGradient\n       r=\"5.257\"\n       fy=\"64.5679\"\n       fx=\"20.8921\"\n       cy=\"64.5679\"\n       cx=\"20.8921\"\n       gradientTransform=\"matrix(0.229703,0,0,0.229703,4.613529,3.979808)\"\n       gradientUnits=\"userSpaceOnUse\"\n       id=\"radialGradient2285\"\n       xlink:href=\"#aigrd3\"\n       inkscape:collect=\"always\" />\n  </defs>\n  <sodipodi:namedview\n     inkscape:window-y=\"30\"\n     inkscape:window-x=\"0\"\n     inkscape:window-height=\"791\"\n     inkscape:window-width=\"1605\"\n     inkscape:document-units=\"px\"\n     inkscape:grid-bbox=\"true\"\n     showgrid=\"false\"\n     inkscape:current-layer=\"layer5\"\n     inkscape:cy=\"120.31049\"\n     inkscape:cx=\"3.6341803\"\n     inkscape:zoom=\"2\"\n     inkscape:pageshadow=\"2\"\n     inkscape:pageopacity=\"0.0\"\n     borderopacity=\"0.25490196\"\n     bordercolor=\"#666666\"\n     pagecolor=\"#ffffff\"\n     id=\"base\"\n     inkscape:showpageshadow=\"false\"\n     fill=\"#729fcf\"\n     inkscape:document-rotation=\"0\"\n     inkscape:pagecheckerboard=\"true\"\n     inkscape:window-maximized=\"0\" />\n  <metadata\n     id=\"metadata4\">\n    <rdf:RDF>\n      <cc:Work\n         rdf:about=\"\">\n        <dc:format>image/svg+xml</dc:format>\n        <dc:type\n           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\n        <dc:title>Office Document Icon</dc:title>\n        <dc:subject>\n          <rdf:Bag>\n            <rdf:li>rich</rdf:li>\n            <rdf:li>text</rdf:li>\n            <rdf:li>document</rdf:li>\n            <rdf:li>pdf</rdf:li>\n            <rdf:li>openoffice</rdf:li>\n            <rdf:li>word</rdf:li>\n            <rdf:li>rtf</rdf:li>\n            <rdf:li>computer</rdf:li>\n            <rdf:li>icon</rdf:li>\n          </rdf:Bag>\n        </dc:subject>\n        <cc:license\n           rdf:resource=\"http://creativecommons.org/publicdomain/zero/1.0/\" />\n        <dc:creator>\n          <cc:Agent>\n            <dc:title>Jakub Steiner, Daniel S. Fowler</dc:title>\n          </cc:Agent>\n        </dc:creator>\n        <dc:source>https://tekeye.uk/free_resources/tango_desktop_project/index</dc:source>\n        <dc:date> 2020-12-29</dc:date>\n        <dc:rights>\n          <cc:Agent>\n            <dc:title>Public Domain</dc:title>\n          </cc:Agent>\n        </dc:rights>\n        <dc:publisher>\n          <cc:Agent>\n            <dc:title>https://tekeye.uk/</dc:title>\n          </cc:Agent>\n        </dc:publisher>\n        <dc:identifier>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-document.svg</dc:identifier>\n        <dc:relation>https://tekeye.uk/free_resources/tango_desktop_project/images/svg/mimetypes/x-office-drawing.svg</dc:relation>\n        <dc:language>en-GB</dc:language>\n        <dc:coverage>computing</dc:coverage>\n        <dc:description>An address book icon.</dc:description>\n      </cc:Work>\n      <cc:License\n         rdf:about=\"http://creativecommons.org/publicdomain/zero/1.0/\">\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Reproduction\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#Distribution\" />\n        <cc:permits\n           rdf:resource=\"http://creativecommons.org/ns#DerivativeWorks\" />\n      </cc:License>\n    </rdf:RDF>\n  </metadata>\n  <g\n     inkscape:groupmode=\"layer\"\n     id=\"layer5\"\n     inkscape:label=\"Text\"\n     style=\"display:inline\">\n    <g\n       id=\"g156\"\n       transform=\"matrix(5.6640009,0,0,5.6640001,-8.5760275,-16.821472)\">\n      <g\n         style=\"display:inline\"\n         transform=\"matrix(0.02105461,0,0,0.02086758,42.85172,41.1536)\"\n         id=\"g6707\">\n        <rect\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           id=\"rect6709\"\n           width=\"1339.6335\"\n           height=\"478.35718\"\n           x=\"-1559.2523\"\n           y=\"-150.69685\" />\n        <path\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n           d=\"m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z\"\n           id=\"path6711\"\n           sodipodi:nodetypes=\"cccc\" />\n        <path\n           sodipodi:nodetypes=\"cccc\"\n           id=\"path6713\"\n           d=\"m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.402062;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15391\"\n         width=\"34.875\"\n         height=\"40.920494\"\n         x=\"6.6035528\"\n         y=\"3.6464462\"\n         ry=\"1.1490486\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect15660\"\n         width=\"32.775887\"\n         height=\"38.946384\"\n         x=\"7.6660538\"\n         y=\"4.5839462\"\n         ry=\"0.14904857\"\n         rx=\"0.14904857\" />\n      <g\n         transform=\"translate(0.646447,-0.03798933)\"\n         id=\"g2270\"\n         style=\"display:inline\">\n        <g\n           id=\"g1440\"\n           style=\"fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4\"\n           transform=\"matrix(0.229703,0,0,0.229703,4.967081,4.244972)\">\n          <radialGradient\n             id=\"radialGradient1442\"\n             cx=\"20.892099\"\n             cy=\"114.5684\"\n             r=\"5.256\"\n             fx=\"20.892099\"\n             fy=\"114.5684\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1444\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1446\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1448\" />\n          <radialGradient\n             id=\"radialGradient1450\"\n             cx=\"20.892099\"\n             cy=\"64.567902\"\n             r=\"5.257\"\n             fx=\"20.892099\"\n             fy=\"64.567902\"\n             gradientUnits=\"userSpaceOnUse\">\n            <stop\n               offset=\"0\"\n               style=\"stop-color:#F0F0F0\"\n               id=\"stop1452\" />\n            <stop\n               offset=\"1\"\n               style=\"stop-color:#474747\"\n               id=\"stop1454\" />\n          </radialGradient>\n          <path\n             style=\"stroke:none\"\n             d=\"m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z\"\n             id=\"path1456\" />\n        </g>\n        <path\n           style=\"fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15570\" />\n        <path\n           style=\"fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4\"\n           d=\"m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z\"\n           id=\"path15577\" />\n      </g>\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.988553;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.0175438\"\n         d=\"M 11.505723,5.4942766 V 43.400869\"\n         id=\"path15672\"\n         sodipodi:nodetypes=\"cc\" />\n      <path\n         style=\"display:inline;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.204678\"\n         d=\"M 12.5,5.0205154 V 43.038228\"\n         id=\"path15674\"\n         sodipodi:nodetypes=\"cc\" />\n      <rect\n         ry=\"0.065390877\"\n         rx=\"0.13778631\"\n         y=\"31\"\n         x=\"15.999986\"\n         height=\"1\"\n         width=\"20.000006\"\n         id=\"rect15738\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         ry=\"0.065390877\"\n         rx=\"0.13778631\"\n         y=\"33\"\n         x=\"15.999986\"\n         height=\"1\"\n         width=\"20.000006\"\n         id=\"rect15740\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         ry=\"0.065390877\"\n         rx=\"0.13778631\"\n         y=\"35\"\n         x=\"15.999986\"\n         height=\"1\"\n         width=\"20.000006\"\n         id=\"rect15742\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <rect\n         ry=\"0.065390877\"\n         rx=\"0.096450485\"\n         y=\"37\"\n         x=\"15.999986\"\n         height=\"1\"\n         width=\"14.000014\"\n         id=\"rect15744\"\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      <g\n         id=\"g5376\"\n         style=\"opacity:0.664773\">\n        <g\n           transform=\"matrix(0.608982,0,0,0.606219,12.8233,10.5572)\"\n           id=\"g7654\">\n          <path\n             style=\"fill:url(#linearGradient7671);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\"\n             d=\"M 5.512695,30 H 39.643234 V 19.627375 H 5.512695 Z\"\n             id=\"path7644\" />\n          <path\n             id=\"path16203\"\n             d=\"M 5.512695,5.6791358 H 39.643234 V 19.627375 H 5.512695 Z\"\n             style=\"fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <g\n             transform=\"matrix(1.189217,0,0,1.189217,-3.525355,-6.535408)\"\n             style=\"fill-rule:nonzero;stroke:#000000;stroke-width:2.00242;stroke-miterlimit:4\"\n             id=\"g16205\">\n            <g\n               id=\"g16207\">\n              <path\n                 id=\"path16209\"\n                 d=\"m 18.4,15.4 c 0,2.2 -1.8,4.1 -4.1,4.1 -2.2,0 -4.1,-1.8 -4.1,-4.1 0,-2.2 1.8,-4.1 4.1,-4.1 2.2,0 4.1,1.8 4.1,4.1 z\"\n                 style=\"opacity:0.0499999;fill:#e8f52f;stroke:none\" />\n              <path\n                 id=\"path16211\"\n                 d=\"m 18,15.4 c 0,2 -1.6,3.7 -3.7,3.7 -2,0 -3.7,-1.6 -3.7,-3.7 0,-2 1.6,-3.7 3.7,-3.7 2,0 3.7,1.6 3.7,3.7 z\"\n                 style=\"opacity:0.2083;fill:#ecf751;stroke:none\" />\n              <path\n                 id=\"path16213\"\n                 d=\"m 17.6,15.4 c 0,1.8 -1.5,3.3 -3.3,3.3 -1.8,0 -3.3,-1.5 -3.3,-3.3 0,-1.8 1.5,-3.3 3.3,-3.3 1.8,0 3.3,1.5 3.3,3.3 z\"\n                 style=\"opacity:0.3667;fill:#f0f972;stroke:none\" />\n              <path\n                 id=\"path16215\"\n                 d=\"m 17.2,15.4 c 0,1.6 -1.3,2.9 -2.9,2.9 -1.6,0 -2.9,-1.3 -2.9,-2.9 0,-1.6 1.3,-2.9 2.9,-2.9 1.6,0 2.9,1.3 2.9,2.9 z\"\n                 style=\"opacity:0.525;fill:#f4fa95;stroke:none\" />\n              <path\n                 id=\"path16217\"\n                 d=\"m 16.8,15.4 c 0,1.4 -1.1,2.5 -2.5,2.5 -1.4,0 -2.5,-1.1 -2.5,-2.5 0,-1.4 1.1,-2.5 2.5,-2.5 1.4,0 2.5,1.1 2.5,2.5 z\"\n                 style=\"opacity:0.6833;fill:#f7fcb7;stroke:none\" />\n              <path\n                 id=\"path16219\"\n                 d=\"m 16.4,15.4 c 0,1.2 -1,2.1 -2.1,2.1 -1.1,0 -2.1,-1 -2.1,-2.1 0,-1.1 1,-2.1 2.1,-2.1 1.1,0 2.1,1 2.1,2.1 z\"\n                 style=\"opacity:0.8417;fill:#fbfddb;stroke:none\" />\n              <path\n                 id=\"path16221\"\n                 d=\"m 16,15.4 c 0,1 -0.8,1.8 -1.8,1.8 -1,0 -1.8,-0.8 -1.8,-1.8 0,-1 0.8,-1.8 1.8,-1.8 1,0 1.8,0.8 1.8,1.8 z\"\n                 style=\"fill:#ffffff;stroke:none\" />\n            </g>\n          </g>\n          <path\n             id=\"path16223\"\n             d=\"m 25.015859,21.649044 h 8.681289 l 1.664904,0.475688 h -2.854121 c 0,0 2.854121,0.237842 4.281184,2.021669 1.427059,1.664904 -1.664905,3.686575 -1.664905,3.686575 0,0 0,0 0,0 -0.118922,-0.356766 -0.832454,-3.210889 -2.259514,-4.400106 -1.070297,-0.951374 -2.259514,-1.189218 -2.259514,-1.189218 h -5.589323 v -0.475686 z\"\n             style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16225\"\n             d=\"m 30.724106,22.362574 h -4.994715 l 9.275897,5.232557 z\"\n             style=\"opacity:0.3;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16227\"\n             d=\"m 25.015859,21.767966 h 8.681289 l 1.30814,-0.832453 h -2.854121 c 0,0 2.616276,-0.475686 2.973043,-3.448731 0.356763,-2.973043 -4.043341,-6.302851 -4.043341,-6.302851 0,0 0,0 0,0.118922 0.118921,0.71353 1.308138,5.708243 0.475688,7.610993 -0.356767,1.664901 -1.427062,2.021667 -1.427062,2.021667 h -5.470401 l 0.237844,0.832453 z\"\n             style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n          <path\n             id=\"path16229\"\n             d=\"M 30.248418,20.459827 H 25.253704 L 31.19979,11.421773 Z\"\n             style=\"fill:#515151;fill-rule:nonzero;stroke:none;stroke-width:1.21667;stroke-miterlimit:4\" />\n        </g>\n        <rect\n           y=\"14.485752\"\n           x=\"16.508501\"\n           height=\"13.997463\"\n           width=\"19.995502\"\n           id=\"rect8163\"\n           style=\"color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#9e9e9e;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none\" />\n      </g>\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect1768\"\n         width=\"20.000006\"\n         height=\"1\"\n         x=\"15.999986\"\n         y=\"9\"\n         rx=\"0.13778631\"\n         ry=\"0.065390877\" />\n      <rect\n         style=\"color:#000000;display:block;overflow:visible;visibility:visible;fill:#9b9b9b;fill-opacity:0.549708;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.0818714;marker:none;marker-start:none;marker-mid:none;marker-end:none\"\n         id=\"rect1770\"\n         width=\"14.000014\"\n         height=\"1\"\n         x=\"15.999986\"\n         y=\"11\"\n         rx=\"0.096450485\"\n         ry=\"0.065390877\" />\n    </g>\n  </g>\n</svg>\n}\n\nproc ::tk::icons::svgPhoto {name size} {\n    variable svgData\n    variable cache\n\n    if {![info exists svgData($name)]} {\n        error \"No SVG icon named \\\"$name\\\"\"\n    }\n\n    set key \"${name}@${size}\"\n\n    if {[info exists cache($key)] && [lsearch [image names] $cache($key)] >= 0} {\n        return $cache($key)\n    }\n\n    set img [image create photo \\\n        -format [list svg -scaletoheight $size] \\\n        -data $svgData($name)\n    ]\n\n    set cache($key) $img\n    return $img\n}\n\nproc ::tk::fileicon {filename size} {\n    if {[tk windowingsystem] eq \"win32\"} {\n        # Snap to closest standard Windows icon size: 16, 32, 48, 256\n        set sizes {16 32 48 256}\n        set newsize [lindex $sizes 0]\n        set mindiff [expr {abs($size - $newsize)}]\n        foreach s $sizes {\n            set diff [expr {abs($size - $s)}]\n            if {$diff < $mindiff} {\n                set mindiff $diff\n                set newsize $s\n            }\n        }\n\n\t# Return the same icon for all volumes, incl. the virtual filesystems\n\tif {$filename in [file volumes]} {\n\t    set filename \"C:/\"\n\t}\n        return [::tk::fileicon::_getwinicon $filename $newsize]\n    }\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t# Return the same icon for all volumes, incl. the virtual filesystems\n\tif {$filename in [file volumes]} {\n\t    set filename \"/\"\n\t}\n        return [image create nsimage [expr {rand()}] -source $filename -as path -height $size]\n    }\n    if {[tk windowingsystem] eq \"x11\"} {\n\tset ext [string tolower [file extension $filename]]\n\tif {[file isdirectory $filename]} {\n\t    return [::tk::icons::svgPhoto folder $size]\n\t}\n\tif {[file executable $filename]} {\n\t    return [::tk::icons::svgPhoto executable $size]\n\t}\n\tswitch -glob -- $ext {\n\t    .svg {\n\t\tset icon drawing\n\t    }\n\t    .bmp - .gif - .ico - .icns - .jpg - .jpeg - .png - .tif - .tiff - .webp - .pdf {\n\t\tset icon image\n\t    }\n\t    .aac - .aiff - .mid - .midi - .mp3 - .wav - .oga - .opus - .weba {\n\t\tset icon audio\n\t    }\n\t    .ics {\n\t\tset icon calendar\n\t    }\n\t    .abw - .odt - .doc - .docx - .rtf {\n\t\tset icon word\n\t    }\n\t    .odp - .ppt - .pptx {\n\t\tset icon presentation\n\t    }\n\t    .csv - .ods - .xls - .xlsx {\n\t\tset icon spreadsheet\n\t    }\n\t    .arc - .bz - .bz2 - .jar - .mpkg - .rar - .tar - .zip - .tz - .tgz - .7z {\n\t\tset icon archive\n\t    }\n\t    .css - .js - .html - .htm - .epub - .json - .swf - .xhtml - .xml {\n\t\tset icon html\n\t    }\n\t    .csh - .php - .sh - .py - .pl - .tcl - .rb {\n\t\tset icon script\n\t    }\n\t    .bin - .db - .so - .dll - .dylib {\n\t\tset icon binary\n\t    }\n\t    .eot - .otf - .ttf - .woff - .woff2 {\n\t\tset icon font\n\t    }\n\t    .eml - .msg - .mbox - .pst - .oft {\n\t\tset icon mail\n\t    }\n\t    default {\n\t\tset icon text\n\t    }\n\t}\n\treturn [::tk::icons::svgPhoto $icon $size]\n    }\n}\n\n# Add these commands to the tk command ensemble: tk accessible.\nnamespace ensemble configure tk -map \\\n    [dict merge [namespace ensemble configure tk -map] \\\n\t {fileicon ::tk::fileicon}]\n\n\n"
  },
  {
    "path": "library/focus.tcl",
    "content": "# focus.tcl --\n#\n# This file defines several procedures for managing the input\n# focus.\n#\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# ::tk_focusNext --\n# This procedure returns the name of the next window after \"w\" in\n# \"focus order\" (the window that should receive the focus next if\n# Tab is typed in w).  \"Next\" is defined by a pre-order search\n# of a top-level and its non-top-level descendants, with the stacking\n# order determining the order of siblings.  The \"-takefocus\" options\n# on windows determine whether or not they should be skipped.\n#\n# Arguments:\n# w -\t\tName of a window.\n\nproc ::tk_focusNext w {\n    set cur $w\n    while {1} {\n\n\t# Descend to just before the first child of the current widget.\n\n\tset parent $cur\n\tset children [winfo children $cur]\n\tset i -1\n\n\t# Look for the next sibling that isn't a top-level.\n\n\twhile {1} {\n\t    incr i\n\t    if {$i < [llength $children]} {\n\t\tset cur [lindex $children $i]\n\t\tif {[winfo toplevel $cur] eq $cur} {\n\t\t    continue\n\t\t} else {\n\t\t    break\n\t\t}\n\t    }\n\n\t    # No more siblings, so go to the current widget's parent.\n\t    # If it's a top-level, break out of the loop, otherwise\n\t    # look for its next sibling.\n\n\t    set cur $parent\n\t    if {[winfo toplevel $cur] eq $cur} {\n\t\tbreak\n\t    }\n\t    set parent [winfo parent $parent]\n\t    set children [winfo children $parent]\n\t    set i [lsearch -exact $children $cur]\n\t}\n\tif {$w eq $cur || [tk::FocusOK $cur]} {\n\t    return $cur\n\t}\n    }\n}\n\n# ::tk_focusPrev --\n# This procedure returns the name of the previous window before \"w\" in\n# \"focus order\" (the window that should receive the focus next if\n# Shift-Tab is typed in w).  \"Next\" is defined by a pre-order search\n# of a top-level and its non-top-level descendants, with the stacking\n# order determining the order of siblings.  The \"-takefocus\" options\n# on windows determine whether or not they should be skipped.\n#\n# Arguments:\n# w -\t\tName of a window.\n\nproc ::tk_focusPrev w {\n    set cur $w\n    while {1} {\n\n\t# Collect information about the current window's position\n\t# among its siblings.  Also, if the window is a top-level,\n\t# then reposition to just after the last child of the window.\n\n\tif {[winfo toplevel $cur] eq $cur}  {\n\t    set parent $cur\n\t    set children [winfo children $cur]\n\t    set i [llength $children]\n\t} else {\n\t    set parent [winfo parent $cur]\n\t    set children [winfo children $parent]\n\t    set i [lsearch -exact $children $cur]\n\t}\n\n\t# Go to the previous sibling, then descend to its last descendant\n\t# (highest in stacking order.  While doing this, ignore top-levels\n\t# and their descendants.  When we run out of descendants, go up\n\t# one level to the parent.\n\n\twhile {$i > 0} {\n\t    incr i -1\n\t    set cur [lindex $children $i]\n\t    if {[winfo toplevel $cur] eq $cur} {\n\t\tcontinue\n\t    }\n\t    set parent $cur\n\t    set children [winfo children $parent]\n\t    set i [llength $children]\n\t}\n\tset cur $parent\n\tif {$w eq $cur || [tk::FocusOK $cur]} {\n\t    return $cur\n\t}\n    }\n}\n\n# ::tk::FocusOK --\n#\n# This procedure is invoked to decide whether or not to focus on\n# a given window.  It returns 1 if it's OK to focus on the window,\n# 0 if it's not OK.  The code first checks whether the window is\n# viewable.  If not, then it never focuses on the window.  Then it\n# checks the -takefocus option for the window and uses it if it's\n# set.  If there's no -takefocus option, the procedure checks to\n# see if (a) the widget isn't disabled, and (b) it has some key\n# bindings.  If all of these are true, then 1 is returned.\n#\n# Arguments:\n# w -\t\tName of a window.\n\nproc ::tk::FocusOK w {\n    set code [catch {$w cget -takefocus} value]\n    if {($code == 0) && ($value ne \"\")} {\n\tif {$value == 0} {\n\t    return 0\n\t} elseif {$value == 1} {\n\t    return [winfo viewable $w]\n\t} else {\n\t    set value [uplevel #0 $value [list $w]]\n\t    if {$value ne \"\"} {\n\t\treturn $value\n\t    }\n\t}\n    }\n    if {![winfo viewable $w]} {\n\treturn 0\n    }\n    set code [catch {$w cget -state} value]\n    if {($code == 0) && $value eq \"disabled\"} {\n\treturn 0\n    }\n    regexp Key|Focus \"[bind $w] [bind [winfo class $w]]\"\n}\n\n# ::tk_focusFollowsMouse --\n#\n# If this procedure is invoked, Tk will enter \"focus-follows-mouse\"\n# mode, where the focus is always on whatever window contains the\n# mouse.  If this procedure isn't invoked, then the user typically\n# has to click on a window to give it the focus.\n#\n# Arguments:\n# None.\n\nproc ::tk_focusFollowsMouse {} {\n    set old [bind all <Enter>]\n    set script {\n\tif {\"%d\" eq \"NotifyAncestor\" || \"%d\" eq \"NotifyNonlinear\" \\\n\t\t|| \"%d\" eq \"NotifyInferior\"} {\n\t    if {[tk::FocusOK %W]} {\n\t\tfocus %W\n\t    }\n\t}\n    }\n    if {$old ne \"\"} {\n\tbind all <Enter> \"$old; $script\"\n    } else {\n\tbind all <Enter> $script\n    }\n}\n"
  },
  {
    "path": "library/fontchooser.tcl",
    "content": "# fontchooser.tcl -\n#\n#\tA themeable Tk font selection dialog. See TIP #324.\n#\n# Copyright © 2008 Keith Vetter\n# Copyright © 2008 Pat Thoyts <patthoyts@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nnamespace eval ::tk::fontchooser {\n    variable S\n\n    set S(W) .__tk__fontchooser\n    set S(fonts) [lsort -dictionary -unique [font families]]\n    set S(styles) [list \\\n\t    [::msgcat::mc Regular] \\\n\t    [::msgcat::mc Italic] \\\n\t    [::msgcat::mc Bold] \\\n\t    [::msgcat::mc {Bold Italic}] \\\n    ]\n    set S(sizes) {8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72}\n    set S(strike) 0\n    set S(under) 0\n    set S(first) 1\n    set S(-parent) .\n    set S(-title) {}\n    set S(-command) \"\"\n    set S(-font) TkDefaultFont\n    set S(bad) [list ]\n}\n\nproc ::tk::fontchooser::Canonical {} {\n    variable S\n\n    foreach style $S(styles) {\n\tlappend S(styles,lcase) [string tolower $style]\n    }\n    set S(sizes,lcase) $S(sizes)\n    set S(sampletext) [::msgcat::mc \"AaBbYyZz01\"]\n\n    # Canonical versions of font families, styles, etc. for easier searching\n    set S(fonts,lcase) {}\n    foreach font $S(fonts) {\n\tlappend S(fonts,lcase) [string tolower $font]\n    }\n    set S(styles,lcase) {}\n    foreach style $S(styles) {\n\tlappend S(styles,lcase) [string tolower $style]\n    }\n}\n\nproc ::tk::fontchooser::Setup {} {\n    variable S\n\n    Canonical\n\n    ::ttk::style layout FontchooserFrame {\n\tEntry.field -sticky news -border true -children {\n\t    FontchooserFrame.padding -sticky news\n\t}\n    }\n    bind [winfo class .] <<ThemeChanged>> \\\n\t    [list +ttk::style layout FontchooserFrame \\\n\t\t    [ttk::style layout FontchooserFrame]]\n\n    namespace ensemble create -map {\n\tshow ::tk::fontchooser::Show\n\thide ::tk::fontchooser::Hide\n\tconfigure ::tk::fontchooser::Configure\n    }\n}\n::tk::fontchooser::Setup\n\nproc ::tk::fontchooser::Show {} {\n    variable S\n\n    Canonical\n\n    if {![winfo exists $S(W)]} {\n\tCreate\n\twm transient $S(W) [winfo toplevel $S(-parent)]\n\ttk::PlaceWindow $S(W) widget $S(-parent)\n\tif {[string trim $S(-title)] eq \"\"} {\n\t    wm title $S(W) [::msgcat::mc \"Font\"]\n\t} else {\n\t    wm title $S(W) $S(-title)\n\t}\n    }\n    set S(fonts) [lsort -dictionary -unique [font families]]\n    set S(fonts,lcase) {}\n    foreach font $S(fonts) {\n\tlappend S(fonts,lcase) [string tolower $font]\n    }\n    wm deiconify $S(W)\n}\n\nproc ::tk::fontchooser::Hide {} {\n    variable S\n    wm withdraw $S(W)\n}\n\nproc ::tk::fontchooser::Configure {args} {\n    variable S\n\n    set specs {\n\t{-parent  \"\" \"\" . }\n\t{-title   \"\" \"\" \"\"}\n\t{-font    \"\" \"\" \"\"}\n\t{-command \"\" \"\" \"\"}\n    }\n\n    if {[llength $args] == 0} {\n\tset result {}\n\tforeach spec $specs {\n\t    foreach {name xx yy default} $spec break\n\t    lappend result $name \\\n\t\t    [expr {[info exists S($name)] ? $S($name) : $default}]\n\t}\n\tlappend result -visible \\\n\t\t[expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}]\n\treturn $result\n    }\n    if {[llength $args] == 1} {\n\tset option [lindex $args 0]\n\tif {[string equal $option \"-visible\"]} {\n\t    return [expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}]\n\t} elseif {[info exists S($option)]} {\n\t    return $S($option)\n\t}\n\treturn -code error -errorcode [list TK LOOKUP OPTION $option] \\\n\t\t\"bad option \\\"$option\\\": must be\\\n\t\t-command, -font, -parent, -title or -visible\"\n    }\n    set cache [dict create -parent $S(-parent) -title $S(-title) \\\n\t    -font $S(-font) -command $S(-command)]\n    set r [tclParseConfigSpec [namespace which -variable S] $specs DONTSETDEFAULTS $args]\n    if {![winfo exists $S(-parent)]} {\n\tset code [list TK LOOKUP WINDOW $S(-parent)]\n\tset err \"bad window path name \\\"$S(-parent)\\\"\"\n\tarray set S $cache\n\treturn -code error -errorcode $code $err\n    }\n\n    if {[winfo exists $S(W)]} {\n\tif {{-font} in $args} {\n\t    Init $S(-font)\n\t    event generate $S(-parent) <<TkFontchooserFontChanged>>\n\t}\n\n\tif {[string trim $S(-title)] eq {}} {\n\t    wm title $S(W) [::msgcat::mc Font]\n\t} else {\n\t    wm title $S(W) $S(-title)\n\t}\n\t$S(W).ok configure -state $S(nstate)\n\t$S(W).apply configure -state $S(nstate)\n    }\n    return $r\n}\n\nproc ::tk::fontchooser::Create {} {\n    variable S\n    set windowName __tk__fontchooser\n    if {$S(-parent) eq \".\"} {\n\tset S(W) .$windowName\n    } else {\n\tset S(W) $S(-parent).$windowName\n    }\n\n    # Now build the dialog\n    if {![winfo exists $S(W)]} {\n\ttoplevel $S(W) -class TkFontDialog\n\tif {[package provide tcltest] ne {}} {\n\t    set ::tk::test::dialog::testDialog $S(W)\n\t}\n\twm withdraw $S(W)\n\twm title $S(W) $S(-title)\n\twm transient $S(W) [winfo toplevel $S(-parent)]\n\n\tset outer [::ttk::frame $S(W).outer -padding {7.5p 7.5p}]\n\t::tk::AmpWidget ::ttk::label $S(W).font -text [::msgcat::mc \"&Font:\"]\n\t::tk::AmpWidget ::ttk::label $S(W).style -text [::msgcat::mc \"Font st&yle:\"]\n\t::tk::AmpWidget ::ttk::label $S(W).size -text [::msgcat::mc \"&Size:\"]\n\tttk::entry $S(W).efont -width 18 \\\n\t\t-textvariable [namespace which -variable S](font)\n\tttk::entry $S(W).estyle -width 10 \\\n\t\t-textvariable [namespace which -variable S](style)\n\tttk::entry $S(W).esize -textvariable [namespace which -variable S](size) \\\n\t\t-width 3 -validate key -validatecommand {regexp -- {^-*[0-9]*$} %P}\n\n\tttk_slistbox $S(W).lfonts -height 7 -exportselection 0 \\\n\t\t-selectmode browse -activestyle none \\\n\t\t-listvariable [namespace which -variable S](fonts)\n\tttk_slistbox $S(W).lstyles -width 5 -height 7 -exportselection 0 \\\n\t\t-selectmode browse -activestyle none \\\n\t\t-listvariable [namespace which -variable S](styles)\n\tttk_slistbox $S(W).lsizes -width 4 -height 7 -exportselection 0 \\\n\t\t-selectmode browse -activestyle none \\\n\t\t-listvariable [namespace which -variable S](sizes)\n\n\tset WE $S(W).effects\n\t::ttk::labelframe $WE -text [::msgcat::mc \"Effects\"]\n\t::tk::AmpWidget ::ttk::checkbutton $WE.strike \\\n\t\t-variable [namespace which -variable S](strike) \\\n\t\t-text [::msgcat::mc \"Stri&keout\"] \\\n\t\t-command [namespace code [list Click strike]]\n\t::tk::AmpWidget ::ttk::checkbutton $WE.under \\\n\t\t-variable [namespace which -variable S](under) \\\n\t\t-text [::msgcat::mc \"&Underline\"] \\\n\t\t-command [namespace code [list Click under]]\n\n\tset bbox [::ttk::frame $S(W).bbox]\n\t::ttk::button $S(W).ok -text [::msgcat::mc OK] -default active\\\n\t\t-command [namespace code [list Done 1]]\n\t::ttk::button $S(W).cancel -text [::msgcat::mc Cancel] \\\n\t\t-command [namespace code [list Done 0]]\n\t::tk::AmpWidget ::ttk::button $S(W).apply -text [::msgcat::mc \"&Apply\"] \\\n\t\t-command [namespace code [list Apply]]\n\twm protocol $S(W) WM_DELETE_WINDOW [namespace code [list Done 0]]\n\n\t# Calculate minimum sizes\n\tttk::scrollbar $S(W).tmpvs\n\tset scroll_width [winfo reqwidth $S(W).tmpvs]\n\tdestroy $S(W).tmpvs\n\tset minsize(gap) [::tk::ScaleNum 10]\n\tset minsize(bbox) [winfo reqwidth $S(W).ok]\n\tset minsize(fonts) \\\n\t\t[expr {[font measure TkDefaultFont \"Helvetica\"] + $scroll_width}]\n\tset minsize(styles) \\\n\t\t[expr {[font measure TkDefaultFont \"Bold Italic\"] + $scroll_width}]\n\tset minsize(sizes) \\\n\t\t[expr {[font measure TkDefaultFont \"-99\"] + $scroll_width}]\n\tset min [expr {$minsize(gap) * 4}]\n\tforeach {what width} [array get minsize] {\n\t    incr min $width\n\t}\n\twm minsize $S(W) $min [::tk::ScaleNum 260]\n\n\tbind $S(W) <Return> [namespace code [list Done 1]]\n\tbind $S(W) <Escape> [namespace code [list Done 0]]\n\tbind $S(W) <Map> [namespace code [list Visibility %W 1]]\n\tbind $S(W) <Unmap> [namespace code [list Visibility %W 0]]\n\tbind $S(W) <Destroy> [namespace code [list Visibility %W 0]]\n\tbind $S(W).lfonts.list <<ListboxSelect>> [namespace code [list Click font]]\n\tbind $S(W).lstyles.list <<ListboxSelect>> [namespace code [list Click style]]\n\tbind $S(W).lsizes.list <<ListboxSelect>> [namespace code [list Click size]]\n\tbind $S(W) <Alt-Key> [list ::tk::AltKeyInDialog $S(W) %A]\n\tbind $S(W).font <<AltUnderlined>> [list ::focus $S(W).efont]\n\tbind $S(W).style <<AltUnderlined>> [list ::focus $S(W).estyle]\n\tbind $S(W).size <<AltUnderlined>> [list ::focus $S(W).esize]\n\tbind $S(W).apply <<AltUnderlined>> [namespace code [list Apply]]\n\tbind $WE.strike <<AltUnderlined>> [list $WE.strike invoke]\n\tbind $WE.under <<AltUnderlined>> [list $WE.under invoke]\n\n\tset WS $S(W).sample\n\t::ttk::labelframe $WS -text [::msgcat::mc \"Sample\"]\n\t::ttk::label $WS.sample -relief sunken -anchor center \\\n\t\t-textvariable [namespace which -variable S](sampletext)\n\tset S(sample) $WS.sample\n\tgrid $WS.sample -sticky news -padx 4.5p -pady 3p\n\tgrid rowconfigure $WS 0 -weight 1\n\tgrid columnconfigure $WS 0 -weight 1\n\tgrid propagate $WS 0\n\n\tgrid $S(W).ok     -in $bbox -sticky new -pady {0 1.5p}\n\tgrid $S(W).cancel -in $bbox -sticky new -pady 1.5p\n\tgrid $S(W).apply  -in $bbox -sticky new -pady 1.5p\n\tgrid columnconfigure $bbox 0 -weight 1\n\n\tgrid $WE.strike -sticky w -padx 7.5p\n\tgrid $WE.under -sticky w -padx 7.5p -pady {0 22.5p}\n\tgrid columnconfigure $WE 1 -weight 1\n\n\tgrid $S(W).font   x $S(W).style   x $S(W).size   x       -in $outer -sticky w\n\tgrid $S(W).efont  x $S(W).estyle  x $S(W).esize  x $bbox -in $outer -sticky ew\n\tgrid $S(W).lfonts x $S(W).lstyles x $S(W).lsizes x ^     -in $outer -sticky news\n\tgrid $WE          x $WS           - -            x ^     -in $outer -sticky news -pady {11p 22.5p}\n\tgrid configure $bbox -sticky n\n\tgrid rowconfigure $outer 2 -weight 1\n\tgrid columnconfigure $outer {1 3 5} -minsize $minsize(gap)\n\tgrid columnconfigure $outer {0 2 4} -weight 1\n\tgrid columnconfigure $outer 0 -minsize $minsize(fonts)\n\tgrid columnconfigure $outer 2 -minsize $minsize(styles)\n\tgrid columnconfigure $outer 4 -minsize $minsize(sizes)\n\tgrid columnconfigure $outer 6 -minsize $minsize(bbox)\n\n\tgrid $outer -sticky news\n\tgrid rowconfigure $S(W) 0 -weight 1\n\tgrid columnconfigure $S(W) 0 -weight 1\n\n\tInit $S(-font)\n\n\ttrace add variable [namespace which -variable S](size) \\\n\t\twrite [namespace code [list Tracer]]\n\ttrace add variable [namespace which -variable S](style) \\\n\t\twrite [namespace code [list Tracer]]\n\ttrace add variable [namespace which -variable S](font) \\\n\t\twrite [namespace code [list Tracer]]\n\ttrace add variable [namespace which -variable S](strike) \\\n\t\twrite [namespace code [list Tracer]]\n\ttrace add variable [namespace which -variable S](under) \\\n\t\twrite [namespace code [list Tracer]]\n    }\n\n    Init $S(-font)\n\n    return\n}\n\n# ::tk::fontchooser::Done --\n#\n#       Handles teardown of the dialog, calling -command if needed\n#\n# Arguments:\n#       ok              true if user pressed OK\n#\nproc ::tk::fontchooser::Done {ok} {\n    variable S\n\n    if {! $ok} {\n\tset S(result) \"\"\n    }\n    trace remove variable S(size) write [namespace code [list Tracer]]\n    trace remove variable S(style) write [namespace code [list Tracer]]\n    trace remove variable S(font) write [namespace code [list Tracer]]\n    trace remove variable S(strike) write [namespace code [list Tracer]]\n    trace remove variable S(under) write [namespace code [list Tracer]]\n    destroy $S(W)\n    if {$ok} {\n\tif {$S(-command) ne \"\"} {\n\t    uplevel #0 $S(-command) [list $S(result)]\n\t}\n\tevent generate $S(-parent) <<TkFontchooserFontChanged>>\n    }\n}\n\n# ::tk::fontchooser::Apply --\n#\n#\tCall the -command procedure appending the current font\n#\tErrors are reported via the background error mechanism\n#\nproc ::tk::fontchooser::Apply {} {\n    variable S\n    if {$S(-command) ne \"\"} {\n\tif {[catch {uplevel #0 $S(-command) [list $S(result)]} err]} {\n\t    ::bgerror $err\n\t}\n    }\n    event generate $S(-parent) <<TkFontchooserFontChanged>>\n}\n\n# ::tk::fontchooser::Init --\n#\n#       Initializes dialog to a default font\n#\n# Arguments:\n#       defaultFont     font to use as the default\n#\nproc ::tk::fontchooser::Init {{defaultFont \"\"}} {\n    variable S\n\n    if {$S(first) || $defaultFont ne \"\"} {\n\tCanonical\n\tif {$defaultFont eq \"\"} {\n\t    set defaultFont [[entry .___e] cget -font]\n\t    destroy .___e\n\t}\n\tarray set F [font actual $defaultFont]\n\tset S(font) $F(-family)\n\tset S(style) [::msgcat::mc \"Regular\"]\n\tset S(size) $F(-size)\n\tset S(strike) $F(-overstrike)\n\tset S(under) $F(-underline)\n\tif {$F(-weight) eq \"bold\" && $F(-slant) eq \"italic\"} {\n\t    set S(style) [::msgcat::mc \"Bold Italic\"]\n\t} elseif {$F(-weight) eq \"bold\"} {\n\t    set S(style) [::msgcat::mc \"Bold\"]\n\t} elseif {$F(-slant) eq \"italic\"} {\n\t    set S(style) [::msgcat::mc \"Italic\"]\n\t}\n\tset S(first) 0\n    }\n}\n\n# ::tk::fontchooser::Click --\n#\n#       Handles all button clicks, updating the appropriate widgets\n#\n# Arguments:\n#       who             which widget got pressed\n#\nproc ::tk::fontchooser::Click {who} {\n    variable S\n    if {$who eq \"font\"} {\n\tset S(font) [$S(W).lfonts get [$S(W).lfonts curselection]]\n    } elseif {$who eq \"style\"} {\n\tset S(style) [$S(W).lstyles get [$S(W).lstyles curselection]]\n    } elseif {$who eq \"size\"} {\n\tset S(size) [$S(W).lsizes get [$S(W).lsizes curselection]]\n    }\n}\n\n# ::tk::fontchooser::Tracer --\n#\n#       Handles traces on key variables, updating the appropriate widgets\n#\n# Arguments:\n#       standard trace arguments (not used)\n#\nproc ::tk::fontchooser::Tracer {var1 var2 op} {\n    variable S\n    # We don't need to process strike and under\n    if {$var2 ni [list strike under]} {\n\t# Make selection in listbox\n\tset value [string tolower $S($var2)]\n\t$S(W).l${var2}s selection clear 0 end\n\tset n [lsearch -exact $S(${var2}s,lcase) $value]\n\t$S(W).l${var2}s selection set $n\n\tif {$n >= 0} {\n\t    set S($var2) [lindex $S(${var2}s) $n]\n\t    $S(W).e$var2 icursor end\n\t    $S(W).e$var2 selection clear\n\t    if {[set i [lsearch $S(bad) $var2]] >= 0} {\n\t\tset S(bad) [lreplace $S(bad) $i $i]\n\t    }\n\t} else {\n\t    # No match, try prefix\n\t    set n [lsearch -glob $S(${var2}s,lcase) \"$value*\"]\n\t    if {$var2 ne \"size\" || !([regexp -- {^(-[0-9]+|[0-9]+)$} $value] && $value >= -4096 && $value <= 4096)} {\n\t\t if {[lsearch $S(bad) $var2] < 0} {\n\t\t     lappend S(bad) $var2\n\t\t }\n\t    } else {\n\t\tif {[set i [lsearch $S(bad) $var2]] >= 0} {\n\t\t    set S(bad) [lreplace $S(bad) $i $i]\n\t\t}\n\t    }\n\t}\n\t$S(W).l${var2}s see $n\n    }\n    if {[llength $S(bad)] == 0} {\n\tset S(nstate) normal\n\tUpdate\n    } else {\n\tset S(nstate) disabled\n    }\n    $S(W).ok configure -state $S(nstate)\n    $S(W).apply configure -state $S(nstate)\n}\n\n# ::tk::fontchooser::Update --\n#\n#       Shows a sample of the currently selected font\n#\nproc ::tk::fontchooser::Update {} {\n    variable S\n\n    set S(result) [list $S(font) $S(size)]\n    if {$S(style) eq [::msgcat::mc \"Bold\"]} {\n\tlappend S(result) bold\n    }\n    if {$S(style) eq [::msgcat::mc \"Italic\"]} {\n\tlappend S(result) italic\n    }\n    if {$S(style) eq [::msgcat::mc \"Bold Italic\"]} {\n\tlappend S(result) bold italic\n    }\n    if {$S(strike)} {\n\tlappend S(result) overstrike\n    }\n    if {$S(under)} {\n\tlappend S(result) underline\n    }\n\n    $S(sample) configure -font $S(result)\n    set S(-font) $S(result)\n}\n\n# ::tk::fontchooser::Visibility --\n#\n#\tNotify the parent when the dialog visibility changes\n#\nproc ::tk::fontchooser::Visibility {w visible} {\n    variable S\n    if {$w eq $S(W)} {\n\tevent generate $S(-parent) <<TkFontchooserVisibility>>\n    }\n}\n\n# ::tk::fontchooser::ttk_slistbox --\n#\n#\tCreate a properly themed scrolled listbox.\n#\tThis is exactly right on XP but may need adjusting on other platforms.\n#\nproc ::tk::fontchooser::ttk_slistbox {w args} {\n    set f [ttk::frame $w -style FontchooserFrame -padding 1.5p]\n    if {[catch {\n\tlistbox $f.list -relief flat -highlightthickness 0 -borderwidth 0 {*}$args\n\tttk::scrollbar $f.vs -command [list $f.list yview]\n\t$f.list configure -yscrollcommand [list $f.vs set]\n\tgrid $f.list $f.vs -sticky news\n\tgrid rowconfigure $f 0 -weight 1\n\tgrid columnconfigure $f 0 -weight 1\n\tinterp hide {} $w\n\tinterp alias {} $w {} $f.list\n    } err opt]} {\n\tdestroy $f\n\treturn -options $opt $err\n    }\n    return $w\n}\n"
  },
  {
    "path": "library/iconbadges.tcl",
    "content": "# iconbadges.tcl --\n#\n#\tNotification badges for Tk applications.\n#\n#\n# Copyright © 2021 Kevin Walzer\n\nnamespace eval ::tk::icons {}\n\nimage create photo ::tk::icons::1-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    kFBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/HBz/V1f/Rkb/BQX/Dw//oKD/////y8v/Bgb/Pz//ra3/+/v/\n    zMz/Li7/5ub/+vr/8fH/Ly//uLj/Zmb/n5//Bwf/Dg7/kpL/YWH/rq7/h4f/Cgr/\n    AQH/AgLXmjE+AAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRBib\n    aYUeAAAAnElEQVQY022Q5w6DMBCD78hi03RQuvegg77/25ULCakq/MenT4piGwAQ\n    A8aFlIKzABGAiAojbRSFihhinOheSdwyVKn+UaoQsry7x5PpjDzPgBWGlPNqUdJR\n    MODky9V6U20N0hwE2W5/ODokQJKdzperQ7JDt7uuPRL299o/5P+IuxA9akO4qI/n\n    622jukLNp3GFBmoPjOMnHNkJv3kDExXHctm+AAAAJXRFWHRkYXRlOmNyZWF0ZQAy\n    MDIxLTA4LTEwVDA4OjM1OjE0LTA0OjAw0aX6GwAAACV0RVh0ZGF0ZTptb2RpZnkA\n    MjAyMS0wOC0xMFQwODozNToxNC0wNDowMKD4QqcAAAAASUVORK5CYII=\n}\nimage create photo ::tk::icons::2-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    21BMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/Cwv/ODj/UlL/UFD/MjL/CAj/ExP/oKD/8fH//v7//f3/7u7/\n    kJD/DAz/ZWX/9fX/jIz/lpb/+vr/9/f/TEz/TU3/m5v/iYn/Ly//6+v/////YmL/\n    nJz/5OT/MDD/KSn/srL/7Oz/ZGT/AQH/Nzf/zs7/zc3/SUn/AgL/ICD/ysr/7e3/\n    gYH/VVX/WVn/Kir/fX3/eXn/AwP/dnb/rKz/qan/q6vjChO4AAAAEXRSTlMAAA5V\n    q9/4NK/0St3cDa7z4Pnet34AAAABYktHRCy63XGrAAAAwElEQVQY021Q1xLCMAxz\n    uktpS9hQoOwZ9t57/P8XUSesB/RinXz2SQIAQiRZUTVNVWSJEABUdMOkHKaho0ZI\n    yKIfWKFAI3qY/iCsE7AdZNFYPJFMIXNskN1gpjNZL5cv+AF1ZVBwVfRK5Uq1Vkeu\n    gIqj0Wz57Q7rIldBe/1N91h/gER7S8ORN55MhcQP6WzOFssVFYf8/XrDtrv94Sje\n    cxMnxnEWJtDq5Xq7B3gkhFUeaCUwFYH+xP5TzrfCyKvCJ3EzGUFH/1QDAAAAJXRF\n    WHRkYXRlOmNyZWF0ZQAyMDIxLTA4LTEwVDA4OjM1OjE0LTA0OjAw0aX6GwAAACV0\n    RVh0ZGF0ZTptb2RpZnkAMjAyMS0wOC0xMFQwODozNToxNC0wNDowMKD4QqcAAAAA\n    SUVORK5CYII=\n}\nimage create photo ::tk::icons::3-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    +VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/CQn/NTX/UlL/Tk7/Kir/BAT/ERH/mZn/8PD/+Pj/+vr/5ub/\n    cHD/AgL/Vlb/9PT/5eX/X1//nZ3/////29v/HR3/Fhb/QED/RET/Cwv/f3//1dX/\n    Ghr/Bwf/mpr/9vb/+fn/b2//lZX/2tr//Pz/wsL/Jyf/Dg7/Bgb/MzP/c3P/XV3/\n    wMD/qqr/ExP/KSn/4+P/bm7/Q0P/6ur/vb3/x8f/19f/KCj/SEj/qan/zc3/y8v/\n    oKD/ODj/BQX/DQ3/AwON+4wDAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34A\n    AAABYktHRCXDAckPAAAAx0lEQVQY021Q1RLCQBDbo4qW4l7ssOLu7g7//zH07oo8\n    kJfNZGczyQIAQhaOF0RR4DkLQgBEkWSrSmGVJaIhZLOrH9hthoYkh/oDh4TA6SLM\n    4/X5A0HCXE7gFGOGwpFoLJ7QDKpwwJNVMpXOZHEuTzgPAhmFYkkv40qVcAFEZlur\n    N5otysS3pLc73V6fSfRQ8wyGozges0NqP5nO5oslXjF7GmK96W53eH9gIWhU7Xg6\n    X643M6pZ6D54PN+F/tT+85zvC93mC1+z9hl5VNGhJwAAACV0RVh0ZGF0ZTpjcmVh\n    dGUAMjAyMS0wOC0xMFQwODozNToxNC0wNDowMNGl+hsAAAAldEVYdGRhdGU6bW9k\n    aWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTQtMDQ6MDCg+EKnAAAAAElFTkSuQmCC\n}\nimage create photo ::tk::icons::4-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    1VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/AgL/OTn/W1v/ODj/QED/4uL/////oaH/AQH/KSn/zs7/oqL/\n    Fhb/tbX/9PT/1NT/Cgr/l5f//Pz/h4f/fHz/dXX/+/v/trb/HBz/fX3/qKj/DAz/\n    EBD/ysr/4eH/zc3/5eX/8fH/lJT/BAT/Dw//uLj/5+f/5ub/8vL/+vr/paX/BQX/\n    HR3/JCT/ISH/iYn/sLD/Ghr/Tk7/rq7/a2vT0ZXAAAAAEXRSTlMAAA5Vq9/4NK/0\n    St3cDa7z4Pnet34AAAABYktHRBibaYUeAAAAvklEQVQY022QVRPCMBCEL1RSg5Ji\n    Ibi7W9Hi//8n0aRBHtiXvflm7mZvAQChmKJquq6pSgwhAE6wYRIh08CcIWTZ5CPb\n    ChnCDvmRgxHEE9HspdIZ7ok4KG6EsjmaZ6G7CqgRKRQpLXFEVNAEKVeqNYk00LnV\n    G81WWyJdINbp9voDOhxFiC+OJ3Q6m9PFciUW+fn1xt/6O7o/HMV5HsI7BcH5Qq83\n    JkK8o5L74ymjfh5iHpMP/Xn7TznfCpOywhdM6Ra8aC+AYwAAACV0RVh0ZGF0ZTpj\n    cmVhdGUAMjAyMS0wOC0xMFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6\n    bW9kaWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC\n}\nimage create photo ::tk::icons::5-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    7VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/ICD/MjL/Li7/CQn/Bgb/q6v/8/P/8vL/9PT/4uL/FRX/0tL/\n    ////wsL/xcX/uLj/Jib/Kyv/6ur/8fH/aGj/XV3/SUn/Fhb/AQH/+Pj//Pz/7Oz/\n    +fn/l5f/Dg7/ODj/qan/sLD/W1v/fn7/9/f/+vr/WVn/EBD/Ghr/2dn/gID/X1//\n    oKD/EhL/5OT/Y2P/S0v/7e3/vb3/ycn/yMj/HR3/AwP/Skr/zc3/LCz/BQX/DAz/\n    AgKLBoLHAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRB5yCiAr\n    AAAAyUlEQVQY021Q1RLDMAxzVhp1XcbYMXXMzIz//zmLk9HD9GKdzvZJAgBCbJKs\n    qKoiSzZCAFDR7A7K4bBrqBHidNEPXE6mEc1Nf+DWCOgeZD4/QyDImEcHyWAzFI5E\n    I7F4gFFDAhmXEkkzmUpnsshlUHDk8oViqVyxkCug4ihXa/VGtNlCrgqp3en2+oPh\n    SEj80AqO6WRqzsQhfz/PLJa5lbkW77mJzba225uHozDBrZ7Oncu+eaXC6ivQrXV/\n    vAP9if2nnG+F3leFT2jDGOnV8F/uAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTA4\n    LTEwVDA4OjM1OjE1LTA0OjAwd9LxrwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0w\n    OC0xMFQwODozNToxNS0wNDowMAaPSRMAAAAASUVORK5CYII=\n}\nimage create photo ::tk::icons::6-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    9lBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/AQH/ICD/S0v/UlL/NDT/CAj/WVn/2dn/+Pj/+fn/8PD/jY3/\n    Cgr/LCz/4OD//f3/hob/cHD/5eX/1NT/NTX/bGz/////39//T0//Bwf/j4//5ub/\n    wcH/7+//4uL/f3//CQn/lpb/+/v/n5//iIj/8vL/9/f/UVH/hYX/3t7/Hx//vb3/\n    VVX/6Oj/MzP/ExP/x8f/e3v/EhL/t7f/0tL/wMD/MTH/IiL/xsb/zc3/qKj/QkL/\n    AgL/Cwv/Dg7/BQWiS7IgAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAAB\n    YktHRCi9sLWyAAAAyklEQVQY021Q1RLCQBDbowalBYq7y+FWirs7/P/PwPawB/Ky\n    mezsThIAIMTC8YIoCjxnIQQAFclq00zYrBJqhMh27QO7/NSIpGg/UCQCqgOZ2+P1\n    +QPIHCpwTlSCoXAkGos/qZMDHleJZCqdyebyyHkQcBRoMeEvecrIBRBxVGi1Vm80\n    W8hFJrWp3jG6vT6TzMMBHY4CY2qwQ/P9RJ/O5gu6ZO9NE6s13Wz14o6ZYFb3scPx\n    dHYzq69Al+vt/g70J/afcr4Vul4VPgDLCRmO3FuJegAAACV0RVh0ZGF0ZTpjcmVh\n    dGUAMjAyMS0wOC0xMFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9k\n    aWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC\n}\nimage create photo ::tk::icons::7-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    xlBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/Hh7/Njb/NTX/Ghr/i4v/9/f/8/P/8vL/8fH/9PT/eHj/fHz/\n    3Nz/2Nj/19f/6Oj/////+Pj/YGD/DQ3/Fxf/FRX/IiL/trb/j4//CQn/Zmb/+/v/\n    xsb/GBj/HR3/0tL//f3/Xl7/ZGT/1dX/BAT/p6f/n5//AQH/Fhb/09P/c3P/GRn/\n    mZn/qqr/PT3/AgKXVg1iAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAAB\n    YktHRCJdZVysAAAAu0lEQVQY022Q1xKCMBBFN5LQixFR7Bp77wU7//9TJgTFB+7L\n    njmTydxdAECooGCiqgQrBYQAhNF0gyYxdE04hEyL/mKZ3CHNpn+xNQSOy6Hkl3n8\n    gKPrgOLxWamGYa3eaHL0FMDieavd6fZYfyAYAxFjOBpPpmw2F0xATf9dLFfrBNSv\n    2mx3e5oqIuHAjoEkIr+npzO7RFJhWYJeb+wuDS+RVKWP5+stFa8qF4riOFsoZ+2c\n    42QnLKYn/ADYChWCRPB9rQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0xMFQw\n    ODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgtMTBU\n    MDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC\n}\nimage create photo ::tk::icons::8-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    6lBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/Bwf/MjL/UVH/TU3/Kir/BAT/DAz/j4//7e3/+Pj/5+f/eXn/\n    BQX/Skr/9/f/7+//Z2f/fn7/+/v/6ur/MDD/UFD/4uL/Jib/QUH/9PT/NTX/EhL/\n    srL/////09P/2tr/m5v/CAj/ycn//f3/y8v/1dX/s7P/GBj/hYX/HR3/Zmb/0dH/\n    LCz/5eX/dHT/S0v/wsL/NDT/V1f/sLD/zc3/ysr/paX/RUX/AQH/Bgb/Dg7/DQ3m\n    iTf5AAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRC8j1CARAAAA\n    yklEQVQY021Q1RLCQBDbowZFSpEWh+J+xd3d/v936N5hD+QlmezsTrIAQIhLECVZ\n    lkTBRQgAOorbozN43Ap6hKhe/QOv6nhE8ek/8CkE/AFUoXAkapioAn4QNIdj8UQy\n    mUpnHKkJIOIom7PyhWKpjFoECalSrNbqDauJWgIZqdWmdod2e6hlbhn9wXBExxNu\n    scUptWfhFJ3zRXY+TheT5Yqu+XkWYmMNtkNa3fEQLGpmfziezpcrj/oqdLs/zHeh\n    P7X/POf7wuDrhU+46hlBGTVCQgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0x\n    MFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgt\n    MTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC\n}\nimage create photo ::tk::icons::9-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    8FBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/DAz/OTn/U1P/R0f/HBz/AQH/Fhb/oqL/8/P/+fn/+Pj/1NT/\n    S0v/cXH/////29v/W1v/mJj/0ND/AgL/paX/np7/Ly//7e3//Pz/lZX/vr7/GBj/\n    VVX/9fX/c3P/QED/5ub//f3/19f/4OD/+/v/eXn/Pz//mZn/oaH/dXX/6Oj/Z2f/\n    Kir/cHD/enr/FRX/TU3/8PD/Ojr/Ozv/2tr/nJz/CAj/Tk7/sbH/z8//wcH/Bgb/\n    Dw//CgoJOUsyAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRCCz\n    az2AAAAAy0lEQVQY022Q1RLCQAxFs9QovlAozuLu7u72/39D0y3yQB6SO2cmmXsD\n    AITYBFGSZUkUbIQAIFHsKjVLtSvICHE46aecDoMRxUV/yqUQcHtQ+QNaMKSj8rhB\n    8BozHInG4okkIq8AIs4US2eyLBdCLYJk9HyBFWmpXNEQSSDjqLJavdFkLdQyR+1O\n    t9cfsCFHuEj10XgynbE5XzTPL5ar9Sa+3fHzpon9rFI7sOOJmzCt5s+X6221tqxa\n    ge6Pp/4O9Cf2n+d8X+izXvgCm5cZM7QQ1AwAAAAldEVYdGRhdGU6Y3JlYXRlADIw\n    MjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDB30vGvAAAAJXRFWHRkYXRlOm1vZGlmeQAy\n    MDIxLTA4LTEwVDA4OjM1OjE1LTA0OjAwBo9JEwAAAABJRU5ErkJggg==\n}\n\nimage create photo ::tk::icons::9plus-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB\n    OFBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/ERH/AAD/NDT/AQH/AAD/AAD/Cgr/Nzf/U1P/SUn/Hx//AQH/mJj/8fH/+fn/\n    2dn/VFT/BAT/YmL//f3/4uL/YGD/j4//IyP/GBj/xsb/xcX/Fxf/lZX/////rKz/\n    JSX/5eX/3t7/3Nz/AgL/hob/yMj/Hh7/Skr/fn7/MTH/srL/vr7/9fX/NDT/NTX/\n    39///v7/3d3/+vr/g4P/RET/9PT/+/v/8/P/R0f/OTn/lpb/pKT/c3P/4eH/dHT/\n    Dw//Pz//VVX/5ub/ExP/JCT/bW3/fX3/Ghr/QUH/Rkb/Gxv/wsL/1dX/p6f/DAz/\n    e3v/enr/Dg7/ra3/zs7/w8P/gYH/GRn/Bgb/CwuphzIHAAAAFHRSTlMAAA5Vq9/4\n    NK/0St3cDa7z8/Ou4A5hHfoAAAABYktHRCy63XGrAAAA+ElEQVQY02NgYGBkZGJm\n    YWVjY2VhZmJkZGAAibBzcIqAAScHO0iMkZGLWwQOuLmAYozsPCJIgIedkYGXT1RM\n    XEJSCibGx8vAzC8tIysrJw/kKUhKKogIMDOwKCopq6gqyamJiKhraGqJiLAwsGrr\n    6Erp6euoABUZGEoqGLEysBnrmJiayeiYW1haWVtbWdqwMbDZ2tnLOTjqODm7uNrb\n    u7q5szGwinh4enn76Pj6+QcE6gf4B7EysASHhIaFu1lHiIhEGhiGgYxnFvSxj4rW\n    iYkVEfGLi08AOYJXKCIxKTklFcmpQA+lJaRLIXsIi7exBA4iCIWhQQgAiNMk9J5+\n    e/MAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDgtMTBUMDg6MzU6MTYtMDQ6MDBG\n    OusyAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTA4LTEwVDA4OjM1OjE2LTA0OjAw\n    N2dTjgAAAABJRU5ErkJggg==\n}\nimage create photo ::tk::icons::!-badge -data {\n    iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh\n    BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA\n    olBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/\n    AAD/AAD/AAD/AAD/Fhb/QED/Pj7/ExP/VVX/9PT/8PD/SUn/WFj//v7/+fn/S0v/\n    SEj/PDz/MjL/6Oj/Jyf/ICD/4+P/2Nj/Fxf/Dw//qKj/nZ3/Cgr/IyP/hIT/gYH/\n    Hh7/PT3/Ly//paX/oqL/KCj/AgL///8V6AjgAAAAEXRSTlMAAA5Vq9/4NK/0St3c\n    Da7z4Pnet34AAAABYktHRDXettlrAAAAoElEQVQY022QxxKCQBBEZ9hERkygophz\n    lv//NmF3Bz0wp1dd1V3dAwCIDuNCSsGZgwjQKMr1Un2eqxoN0Q/S9gK/1lCF6d+F\n    CiGKNfYHw5GGOAKWaBpn+URDwoAbw3RWzA1xEAYWRVYaEiANLPPV2pAkabPd7Umy\n    xsPxdCajjb9cb3eKtyXq+AeVsFWfr/eHqtKgqmoHdczueM7vhT37wi9PRRMHXNeq\n    aAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0xMFQwODozNToxNi0wNDowMEY6\n    6zIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTYtMDQ6MDA3\n    Z1OOAAAAAElFTkSuQmCC\n}\n\n\nif {[tk windowingsystem] eq \"x11\"} {\n\n    # ::tk::icons::IconBadge --\n    # This procedure creates an icon with an overlay badge on systems that\n    # do not have a native icon/badge API.\n    #\n    # Arguments:\n    # win - window name\n    # badgenumber - badge number to draw over the window icon\n\n    proc ::tk::icons::IconBadge {win badgenumber} {\n\n\tvariable ::tk::icons::base_icon\n\n\tif {![info exists ::tk::icons::base_icon]} {\n\t    return -code error \"::tk::icons::base_icon($win) must be set on X11\"\n\t}\n\n\tif {![info exists ::tk::icons::base_icon($win)]} {\n\t    return -code error \"::tk::icons::base_icon($win) must be set on X11\"\n\t}\n\n\tif {[lsearch -exact [image names] $::tk::icons::base_icon($win)] <= 0} {\n\t    return -code error \"can't use \\\"$::tk::icons::base_icon($win)\\\" as iconphoto: not a photo image\"\n\t}\n\n\tif {!([string is integer -strict $badgenumber] && $badgenumber > 0)\n\t\t&& $badgenumber ne \"!\" && $badgenumber ne \"\"} {\n\t    return -code error \"can't use \\\"$badgenumber\\\" as icon badge\"\n\t}\n\n\twm iconphoto $win $::tk::icons::base_icon($win)\n\n\tif {$badgenumber eq \"\"} {\n\t    return\n\t}\n\n\timage create photo overlay\n\n\tswitch -glob -- $badgenumber {\n\t    ! {\n\t\tset badge ::tk::icons::!-badge\n\t    }\n\t    [1-9] {\n\t\tset badge ::tk::icons::$badgenumber-badge\n\t    }\n\t    default {\n\t\tset badge ::tk::icons::9plus-badge\n\t    }\n\n\t}\n\n\toverlay copy $::tk::icons::base_icon($win)\n\toverlay copy $badge -from 0 0 18 18 -to 18 0\n\twm iconphoto $win overlay\n\n    }\n}\n"
  },
  {
    "path": "library/iconlist.tcl",
    "content": "# iconlist.tcl\n#\n#\tImplements the icon-list megawidget used in the \"Tk\" standard file\n#\tselection dialog boxes.\n#\n# Copyright © 1994-1998 Sun Microsystems, Inc.\n# Copyright © 2009 Donal K. Fellows\n#\n# See the file \"license.terms\" for information on usage and redistribution of\n# this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n# API Summary:\n#\ttk::IconList <path> ?<option> <value>? ...\n#\t<path> add <imageName> <itemList>\n#\t<path> cget <option>\n#\t<path> configure ?<option>? ?<value>? ...\n#\t<path> deleteall\n#\t<path> destroy\n#\t<path> get <itemIndex>\n#\t<path> index <index>\n#\t<path> invoke\n#\t<path> see <index>\n#\t<path> selection anchor ?<int>?\n#\t<path> selection clear <first> ?<last>?\n#\t<path> selection get\n#\t<path> selection includes <item>\n#\t<path> selection set <first> ?<last>?\n\f\npackage require tk\n\n::tk::Megawidget create ::tk::IconList ::tk::FocusableWidget {\n    variable w canvas sbar accel accelCB fill font index \\\n\titemList itemsPerColumn list maxIH maxIW maxTH maxTW noScroll \\\n\tnumItems oldX oldY options rect selected selection textList\n    constructor args {\n\tnext {*}$args\n\tset accelCB {}\n    }\n    destructor {\n\tmy Reset\n\tnext\n    }\n\n    method GetSpecs {} {\n\tconcat [next] {\n\t    {-command \"\" \"\" \"\"}\n\t    {-font \"\" \"\" \"TkIconFont\"}\n\t    {-multiple \"\" \"\" \"0\"}\n\t}\n    }\n\n    # ----------------------------------------------------------------------\n\n    method index i {\n\tif {![info exist list]} {\n\t    set list {}\n\t}\n\tswitch -regexp -- $i {\n\t    \"^-?[0-9]+$\" {\n\t\tif {$i < 0} {\n\t\t    set i 0\n\t\t}\n\t\tif {$i >= [llength $list]} {\n\t\t    set i [expr {[llength $list] - 1}]\n\t\t}\n\t\treturn $i\n\t    }\n\t    \"^anchor$\" {\n\t\treturn $index(anchor)\n\t    }\n\t    \"^end$\" {\n\t\treturn [llength $list]\n\t    }\n\t    \"@-?[0-9]+,-?[0-9]+\" {\n\t\tscan $i \"@%d,%d\" x y\n\t\tset item [$canvas find closest \\\n\t\t\t[$canvas canvasx $x] [$canvas canvasy $y]]\n\t\treturn [lindex [$canvas itemcget $item -tags] 1]\n\t    }\n\t}\n    }\n\n    method selection {op args} {\n\tswitch -exact -- $op {\n\t    anchor {\n\t\tif {[llength $args] == 1} {\n\t\t    set index(anchor) [$w index [lindex $args 0]]\n\t\t} else {\n\t\t    return $index(anchor)\n\t\t}\n\t    }\n\t    clear {\n\t\tswitch [llength $args] {\n\t\t    2 {\n\t\t\tlassign $args first last\n\t\t    }\n\t\t    1 {\n\t\t\tset first [set last [lindex $args 0]]\n\t\t    }\n\t\t    default {\n\t\t\treturn -code error -errorcode {TCL WRONGARGS} \\\n\t\t\t    \"wrong # args: should be\\\n\t\t\t    \\\"[lrange [info level 0] 0 1] first ?last?\\\"\"\n\t\t    }\n\t\t}\n\n\t\tset first [$w index $first]\n\t\tset last [$w index $last]\n\t\tif {$first > $last} {\n\t\t    set tmp $first\n\t\t    set first $last\n\t\t    set last $tmp\n\t\t}\n\t\tset ind 0\n\t\tforeach item $selection {\n\t\t    if {$item >= $first} {\n\t\t\tset first $ind\n\t\t\tbreak\n\t\t    }\n\t\t    incr ind\n\t\t}\n\t\tset ind [expr {[llength $selection] - 1}]\n\t\tfor {} {$ind >= 0} {incr ind -1} {\n\t\t    set item [lindex $selection $ind]\n\t\t    if {$item <= $last} {\n\t\t\tset last $ind\n\t\t\tbreak\n\t\t    }\n\t\t}\n\n\t\tif {$first > $last} {\n\t\t    return\n\t\t}\n\t\tset selection [lreplace $selection $first $last]\n\t\tevent generate $w <<ListboxSelect>>\n\t\tmy DrawSelection\n\t    }\n\t    get {\n\t\treturn $selection\n\t    }\n\t    includes {\n\t\treturn [expr {[lindex $args 0] in $selection}]\n\t    }\n\t    set {\n\t\tswitch [llength $args] {\n\t\t    2 {\n\t\t\tlassign $args first last\n\t\t    }\n\t\t    1 {\n\t\t\tset first [set last [lindex $args 0]]\n\t\t    }\n\t\t    default {\n\t\t\treturn -code error -errorcode {TCL WRONGARGS} \\\n\t\t\t    \"wrong # args: should be\\\n\t\t\t    \\\"[lrange [info level 0] 0 1] first ?last?\\\"\"\n\t\t    }\n\t\t}\n\n\t\tset first [$w index $first]\n\t\tset last [$w index $last]\n\t\tif {$first > $last} {\n\t\t    set tmp $first\n\t\t    set first $last\n\t\t    set last $tmp\n\t\t}\n\n\t\tfor {set i $first} {$i <= $last} {incr i} {\n\t\t    lappend selection $i\n\t\t}\n\t\tset selection [lsort -integer -unique $selection]\n\t\tevent generate $w <<ListboxSelect>>\n\t\tmy DrawSelection\n\t    }\n\t}\n    }\n\n    method get item {\n\tset rTag [lindex $list $item 2]\n\tlassign $itemList($rTag) iTag tTag text serial\n\treturn $text\n    }\n\n    #\tDeletes all the items inside the canvas subwidget and reset the\n    #\ticonList's state.\n    #\n    method deleteall {} {\n\t$canvas delete all\n\tunset -nocomplain selected rect list itemList\n\tset maxIW 1\n\tset maxIH 1\n\tset maxTW 1\n\tset maxTH 1\n\tset numItems 0\n\tset noScroll 1\n\tset selection {}\n\tset index(anchor) \"\"\n\t$sbar set 0.0 1.0\n\t$canvas xview moveto 0\n    }\n\n    #\tAdds an icon into the IconList with the designated image and text\n    #\n    method add {image items} {\n\tforeach text $items {\n\t    set iID item$numItems\n\t    set iTag [$canvas create image 0 0 -image $image -anchor nw \\\n\t\t\t  -tags [list icon $numItems $iID]]\n\t    set tTag [$canvas create text  0 0 -text  $text  -anchor nw \\\n\t\t\t  -font $options(-font) -fill $fill \\\n\t\t\t  -tags [list text $numItems $iID]]\n\t    set rTag [$canvas create rect  0 0 0 0 -fill \"\" -outline \"\" \\\n\t\t\t  -tags [list rect $numItems $iID]]\n\n\t    lassign [$canvas bbox $iTag] x1 y1 x2 y2\n\t    set iW [expr {$x2 - $x1}]\n\t    set iH [expr {$y2 - $y1}]\n\t    if {$maxIW < $iW} {\n\t\tset maxIW $iW\n\t    }\n\t    if {$maxIH < $iH} {\n\t\tset maxIH $iH\n\t    }\n\n\t    lassign [$canvas bbox $tTag] x1 y1 x2 y2\n\t    set tW [expr {$x2 - $x1}]\n\t    set tH [expr {$y2 - $y1}]\n\t    if {$maxTW < $tW} {\n\t\tset maxTW $tW\n\t    }\n\t    if {$maxTH < $tH} {\n\t\tset maxTH $tH\n\t    }\n\n\t    lappend list [list $iTag $tTag $rTag $iW $iH $tW $tH $numItems]\n\t    set itemList($rTag) [list $iTag $tTag $text $numItems]\n\t    set textList($numItems) [string tolower $text]\n\t    incr numItems\n\t}\n\tmy WhenIdle Arrange\n\treturn\n    }\n\n    #\tGets called when the user invokes the IconList (usually by\n    #\tdouble-clicking or pressing the Return key).\n    #\n    method invoke {} {\n\tif {$options(-command) ne \"\" && [llength $selection]} {\n\t    uplevel #0 $options(-command)\n\t}\n    }\n\n    #\tIf the item is not (completely) visible, scroll the canvas so that it\n    #\tbecomes visible.\n    #\n    method see rTag {\n\tif {$noScroll} {\n\t    return\n\t}\n\tset sRegion [$canvas cget -scrollregion]\n\tif {$sRegion eq \"\"} {\n\t    return\n\t}\n\n\tif {$rTag < 0 || $rTag >= [llength $list]} {\n\t    return\n\t}\n\n\tset bbox [$canvas bbox item$rTag]\n\tset pad [expr {[$canvas cget -highlightthickness]+[$canvas cget -bd]}]\n\n\tset x1 [lindex $bbox 0]\n\tset x2 [lindex $bbox 2]\n\tincr x1 [expr {$pad * -2}]\n\tincr x2 [expr {$pad * -1}]\n\n\tset cW [expr {[winfo width $canvas] - $pad*2}]\n\n\tset scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]\n\tset dispX [expr {int([lindex [$canvas xview] 0]*$scrollW)}]\n\tset oldDispX $dispX\n\n\t# check if out of the right edge\n\t#\n\tif {($x2 - $dispX) >= $cW} {\n\t    set dispX [expr {$x2 - $cW}]\n\t}\n\t# check if out of the left edge\n\t#\n\tif {($x1 - $dispX) < 0} {\n\t    set dispX $x1\n\t}\n\n\tif {$oldDispX ne $dispX} {\n\t    set fraction [expr {double($dispX) / double($scrollW)}]\n\t    $canvas xview moveto $fraction\n\t}\n    }\n\n    # ----------------------------------------------------------------------\n\n    #\tPlaces the icons in a column-major arrangement.\n    #\n    method Arrange {} {\n\tif {![info exists list]} {\n\t    if {[info exists canvas] && [winfo exists $canvas]} {\n\t\tset noScroll 1\n\t\t$sbar configure -command \"\"\n\t    }\n\t    return\n\t}\n\n\tset W [winfo width  $canvas]\n\tset H [winfo height $canvas]\n\tset pad [expr {[$canvas cget -highlightthickness]+[$canvas cget -bd]}]\n\tif {$pad < 2} {\n\t    set pad 2\n\t}\n\n\tincr W [expr {$pad*-2}]\n\tincr H [expr {$pad*-2}]\n\n\tset dx [expr {$maxIW + $maxTW + 8}]\n\tif {$maxTH > $maxIH} {\n\t    set dy $maxTH\n\t} else {\n\t    set dy $maxIH\n\t}\n\tincr dy 2\n\tset shift [expr {$maxIW + 4}]\n\n\tset x [expr {$pad * 2}]\n\tset y [expr {$pad * 1}] ; # Why * 1 ?\n\tset usedColumn 0\n\tforeach sublist $list {\n\t    set usedColumn 1\n\t    lassign $sublist iTag tTag rTag iW iH tW tH\n\n\t    set i_dy [expr {($dy - $iH)/2}]\n\t    set t_dy [expr {($dy - $tH)/2}]\n\n\t    $canvas coords $iTag $x [expr {$y + $i_dy}]\n\t    $canvas coords $tTag [expr {$x + $shift}] [expr {$y + $t_dy}]\n\t    $canvas coords $rTag $x $y [expr {$x+$dx}] [expr {$y+$dy}]\n\n\t    incr y $dy\n\t    if {($y + $dy) > $H} {\n\t\tset y [expr {$pad * 1}] ; # *1 ?\n\t\tincr x $dx\n\t\tset usedColumn 0\n\t    }\n\t}\n\n\tif {$usedColumn} {\n\t    set sW [expr {$x + $dx}]\n\t} else {\n\t    set sW $x\n\t}\n\n\tif {$sW < $W} {\n\t    $canvas configure -scrollregion [list $pad $pad $sW $H]\n\t    $sbar configure -command \"\"\n\t    $canvas xview moveto 0\n\t    set noScroll 1\n\t} else {\n\t    $canvas configure -scrollregion [list $pad $pad $sW $H]\n\t    $sbar configure -command [list $canvas xview]\n\t    set noScroll 0\n\t}\n\n\tset itemsPerColumn [expr {($H-$pad) / $dy}]\n\tif {$itemsPerColumn < 1} {\n\t    set itemsPerColumn 1\n\t}\n\n\tmy DrawSelection\n    }\n\n    method DrawSelection {} {\n\t$canvas delete selection\n\t$canvas itemconfigure selectionText -fill $fill\n\t$canvas dtag selectionText\n\tset cbg [ttk::style lookup TEntry -selectbackground focus]\n\tset cfg [ttk::style lookup TEntry -selectforeground focus]\n\tforeach item $selection {\n\t    set rTag [lindex $list $item 2]\n\t    foreach {iTag tTag text serial} $itemList($rTag) {\n\t\tbreak\n\t    }\n\n\t    set bbox [$canvas bbox $tTag]\n\t    $canvas create rect $bbox -fill $cbg -outline $cbg \\\n\t\t-tags selection\n\t    $canvas itemconfigure $tTag -fill $cfg -tags selectionText\n\t}\n\t$canvas lower selection\n\treturn\n    }\n\n    #\tCreates an IconList widget by assembling a canvas widget and a\n    #\tscrollbar widget. Sets all the bindings necessary for the IconList's\n    #\toperations.\n    #\n    method Create {} {\n\tvariable hull\n\tset sbar [ttk::scrollbar $hull.sbar -orient horizontal -takefocus 0]\n\tcatch {$sbar configure -highlightthickness 0}\n\tset canvas [canvas $hull.canvas -highlightthick 0 -takefocus 1 \\\n\t\t\t-width 300p -height 90p \\\n\t\t\t-background [ttk::style lookup Treeview -background {} white]]\n\tpack $sbar -side bottom -fill x -padx 1.5p -pady {0 1.5p}\n\tpack $canvas -expand yes -fill both -padx 1.5p -pady {1.5p 0}\n\n\t$sbar configure -command [list $canvas xview]\n\t$canvas configure -xscrollcommand [list $sbar set]\n\n\t# Initializes the max icon/text width and height and other variables\n\t#\n\tset maxIW 1\n\tset maxIH 1\n\tset maxTW 1\n\tset maxTH 1\n\tset numItems 0\n\tset noScroll 1\n\tset selection {}\n\tset index(anchor) \"\"\n\tset fill [ttk::style lookup Treeview -foreground {} black]\n\n\t# Creates the event bindings.\n\t#\n\tbind $canvas <Configure>\t[namespace code {my WhenIdle Arrange}]\n\n\tbind $canvas <Button-1>\t\t[namespace code {my Btn1 %x %y}]\n\tbind $canvas <B1-Motion>\t[namespace code {my Motion1 %x %y}]\n\tbind $canvas <B1-Leave>\t\t[namespace code {my Leave1 %x %y}]\n\tbind $canvas <Control-Button-1>\t[namespace code {my CtrlBtn1 %x %y}]\n\tbind $canvas <Shift-Button-1>\t[namespace code {my ShiftBtn1 %x %y}]\n\tbind $canvas <B1-Enter>\t\t[list tk::CancelRepeat]\n\tbind $canvas <ButtonRelease-1>\t[list tk::CancelRepeat]\n\tbind $canvas <Double-ButtonRelease-1> \\\n\t    [namespace code {my Double1 %x %y}]\n\n\tbind $canvas <Control-B1-Motion> {;}\n\tbind $canvas <Shift-B1-Motion>\t[namespace code {my ShiftMotion1 %x %y}]\n\n\tbind $canvas <Shift-MouseWheel>\t[namespace code {my MouseWheel %D}]\n\tbind $canvas <Option-Shift-MouseWheel>\t[namespace code {my MouseWheel %D -12}]\n\n\n\tbind $canvas <<PrevLine>>\t[namespace code {my UpDown -1}]\n\tbind $canvas <<NextLine>>\t[namespace code {my UpDown  1}]\n\tbind $canvas <<PrevChar>>\t[namespace code {my LeftRight -1}]\n\tbind $canvas <<NextChar>>\t[namespace code {my LeftRight  1}]\n\tbind $canvas <Return>\t\t[namespace code {my ReturnKey}]\n\tbind $canvas <Key>\t\t[namespace code {my KeyPress %A}]\n\tbind $canvas <Alt-Key>\t\t{# nothing}\n\tbind $canvas <Meta-Key>\t\t{# nothing}\n\tbind $canvas <Control-Key>\t{# nothing}\n\tbind $canvas <Command-Key>\t{# nothing}\n\tbind $canvas <Fn-Key>\t\t{# nothing}\n\n\tbind $canvas <FocusIn>\t\t[namespace code {my FocusIn}]\n\tbind $canvas <FocusOut>\t\t[namespace code {my FocusOut}]\n\n\treturn $w\n    }\n\n    #\tThis procedure is invoked when the mouse leaves an entry window with\n    #\tbutton 1 down.  It scrolls the window up, down, left, or right,\n    #\tdepending on where the mouse left the window, and reschedules itself\n    #\tas an \"after\" command so that the window continues to scroll until the\n    #\tmouse moves back into the window or the mouse button is released.\n    #\n    method AutoScan {} {\n\tif {![winfo exists $w]} return\n\tset x $oldX\n\tset y $oldY\n\tif {$noScroll} {\n\t    return\n\t}\n\tif {$x >= [winfo width $canvas]} {\n\t    $canvas xview scroll 1 units\n\t} elseif {$x < 0} {\n\t    $canvas xview scroll -1 units\n\t} elseif {$y >= [winfo height $canvas]} {\n\t    # do nothing\n\t} elseif {$y < 0} {\n\t    # do nothing\n\t} else {\n\t    return\n\t}\n\tmy Motion1 $x $y\n\tset ::tk::Priv(afterId) [after 50 [namespace code {my AutoScan}]]\n    }\n\n    # ----------------------------------------------------------------------\n\n    # Event handlers\n    method MouseWheel {amount {factor -120.0}} {\n\tif {$noScroll || $::tk_strictMotif} {\n\t    return\n\t}\n\t$canvas xview scroll [expr {$amount/$factor}] units\n    }\n    method Btn1 {x y} {\n\tfocus $canvas\n\tset i [$w index @$x,$y]\n\tif {$i eq \"\"} {\n\t    return\n\t}\n\t$w selection clear 0 end\n\t$w selection set $i\n\t$w selection anchor $i\n    }\n    method CtrlBtn1 {x y} {\n\tif {$options(-multiple)} {\n\t    focus $canvas\n\t    set i [$w index @$x,$y]\n\t    if {$i eq \"\"} {\n\t\treturn\n\t    }\n\t    if {[$w selection includes $i]} {\n\t\t$w selection clear $i\n\t    } else {\n\t\t$w selection set $i\n\t\t$w selection anchor $i\n\t    }\n\t}\n    }\n    method ShiftBtn1 {x y} {\n\tif {$options(-multiple)} {\n\t    focus $canvas\n\t    set i [$w index @$x,$y]\n\t    if {$i eq \"\"} {\n\t\treturn\n\t    }\n\t    if {[$w index anchor] eq \"\"} {\n\t\t$w selection anchor $i\n\t    }\n\t    $w selection clear 0 end\n\t    $w selection set anchor $i\n\t}\n    }\n\n    #\tGets called on button-1 motions\n    #\n    method Motion1 {x y} {\n\tset oldX $x\n\tset oldY $y\n\tset i [$w index @$x,$y]\n\tif {$i eq \"\"} {\n\t    return\n\t}\n\t$w selection clear 0 end\n\t$w selection set $i\n    }\n    method ShiftMotion1 {x y} {\n\tset oldX $x\n\tset oldY $y\n\tset i [$w index @$x,$y]\n\tif {$i eq \"\"} {\n\t    return\n\t}\n\t$w selection clear 0 end\n\t$w selection set anchor $i\n    }\n    method Double1 {x y} {\n\tif {[llength $selection]} {\n\t    $w invoke\n\t}\n    }\n    method ReturnKey {} {\n\t$w invoke\n    }\n    method Leave1 {x y} {\n\tset oldX $x\n\tset oldY $y\n\tmy AutoScan\n    }\n    method FocusIn {} {\n\t$w state focus\n\tif {![info exists list]} {\n\t    return\n\t}\n\tif {[llength $selection]} {\n\t    my DrawSelection\n\t}\n    }\n    method FocusOut {} {\n\t$w state !focus\n\t$w selection clear 0 end\n    }\n\n    #\tMoves the active element up or down by one element\n    #\n    # Arguments:\n    #\tamount -\t+1 to move down one item, -1 to move back one item.\n    #\n    method UpDown amount {\n\tif {![info exists list]} {\n\t    return\n\t}\n\tset curr [$w selection get]\n\tif {[llength $curr] == 0} {\n\t    set i 0\n\t} else {\n\t    set i [$w index anchor]\n\t    if {$i eq \"\"} {\n\t\treturn\n\t    }\n\t    incr i $amount\n\t}\n\t$w selection clear 0 end\n\t$w selection set $i\n\t$w selection anchor $i\n\t$w see $i\n    }\n\n    #\tMoves the active element left or right by one column\n    #\n    # Arguments:\n    #\tamount -\t+1 to move right one column, -1 to move left one\n    #\t\t\tcolumn\n    #\n    method LeftRight amount {\n\tif {![info exists list]} {\n\t    return\n\t}\n\tset curr [$w selection get]\n\tif {[llength $curr] == 0} {\n\t    set i 0\n\t} else {\n\t    set i [$w index anchor]\n\t    if {$i eq \"\"} {\n\t\treturn\n\t    }\n\t    incr i [expr {$amount * $itemsPerColumn}]\n\t}\n\t$w selection clear 0 end\n\t$w selection set $i\n\t$w selection anchor $i\n\t$w see $i\n    }\n\n    #\tGets called when user enters an arbitrary key in the listbox.\n    #\n    method KeyPress key {\n\tappend accel $key\n\tmy Goto $accel\n\tafter cancel $accelCB\n\tset accelCB [after 500 [namespace code {my Reset}]]\n    }\n\n    method Goto text {\n\tif {![info exists list]} {\n\t    return\n\t}\n\tif {$text eq \"\" || $numItems == 0} {\n\t    return\n\t}\n\n\tif {[llength [$w selection get]]} {\n\t    set start [$w index anchor]\n\t} else {\n\t    set start 0\n\t}\n\tset theIndex -1\n\tset less 0\n\tset len [string length $text]\n\tset len0 [expr {$len - 1}]\n\tset i $start\n\n\t# Search forward until we find a filename whose prefix is a\n\t# case-insensitive match with $text\n\twhile {1} {\n\t    if {[string equal -nocase -length $len0 $textList($i) $text]} {\n\t\tset theIndex $i\n\t\tbreak\n\t    }\n\t    incr i\n\t    if {$i == $numItems} {\n\t\tset i 0\n\t    }\n\t    if {$i == $start} {\n\t\tbreak\n\t    }\n\t}\n\n\tif {$theIndex >= 0} {\n\t    $w selection clear 0 end\n\t    $w selection set $theIndex\n\t    $w selection anchor $theIndex\n\t    $w see $theIndex\n\t}\n    }\n    method Reset {} {\n\tunset -nocomplain accel\n    }\n}\n\f\nreturn\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "library/icons.tcl",
    "content": "# icons.tcl --\n#\n#\tA set of stock icons for use in Tk dialogs. The icons used here\n#\twere provided by the Vimix Icon Theme project, which provides a\n#\tunified set of high quality icons licensed under the\n#\tCreative Commons Attribution Share-Alike license\n#\t(https://creativecommons.org/licenses/by-sa/4.0/)\n#\n#\tSee https://github.com/vinceliuice/vimix-icon-theme\n#\n# Copyright © 2009 Pat Thoyts <patthoyts@users.sourceforge.net>\n# Copyright © 2022 Harald Oehlmann <harald.oehlmann@elmicron.de>\n# Copyright © 2022 Csaba Nemethi <csaba.nemethi@t-online.de>\n\nnamespace eval ::tk::icons {}\n\nvariable ::tk::svgFmt [list svg -scale [expr {[::tk::ScalingPct] / 100.0}]]\n\nimage create photo ::tk::icons::error -format $::tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"32\" height=\"32\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <circle cx=\"16\" cy=\"16\" r=\"16\" fill=\"#d32f2f\"/>\n     <g transform=\"rotate(45,16,16)\" fill=\"#fff\">\n      <rect x=\"6\" y=\"14\" width=\"20\" height=\"4\"/>\n      <rect x=\"14\" y=\"6\" width=\"4\" height=\"20\"/>\n     </g>\n    </svg>\n}\n\nimage create photo ::tk::icons::warning -format $::tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"32\" height=\"32\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <circle cx=\"16\" cy=\"16\" r=\"16\" fill=\"#f67400\"/>\n     <circle cx=\"16\" cy=\"24\" r=\"2\" fill=\"#fff\"/>\n     <path d=\"m14 20h4v-14h-4z\" fill=\"#fff\"/>\n    </svg>\n}\n\nimage create photo ::tk::icons::information -format $::tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"32\" height=\"32\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <circle cx=\"16\" cy=\"16\" r=\"16\" fill=\"#2091df\"/>\n     <circle cx=\"16\" cy=\"8\" r=\"2\" fill=\"#fff\"/>\n     <path d=\"m14 12h4v14h-4z\" fill=\"#fff\"/>\n    </svg>\n}\n\nimage create photo ::tk::icons::question -format $::tk::svgFmt -data {\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <svg width=\"32\" height=\"32\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n     <circle cx=\"16\" cy=\"16\" r=\"16\" fill=\"#5c6bc0\"/>\n     <path d=\"m17.6 27.2h-3.2v-3.2h3.2zm3.312-12.4-1.44 1.472c-1.152 1.168-1.872 2.128-1.872 4.528h-3.2v-0.8c0-1.76 0.72-3.36 1.872-4.528l1.984-2.016a3.128 3.128 0 0 0 0.944-2.256c0-1.76-1.44-3.2-3.2-3.2s-3.2 1.44-3.2 3.2h-3.2c0-3.536 2.864-6.4 6.4-6.4s6.4 2.864 6.4 6.4c0 1.408-0.576 2.688-1.488 3.6z\" fill=\"#fff\"/>\n    </svg>\n}\n"
  },
  {
    "path": "library/images/README",
    "content": "README - images directory\n\nThis directory includes images for the Tcl Logo and the Tcl Powered\nLogo.  Please feel free to use the Tcl Powered Logo on any of your\nproducts that employ the use of Tcl or Tk.  The Tcl logo may also be\nused to promote Tcl in your product documentation, web site or other\nplaces you so desire.\n"
  },
  {
    "path": "library/images/logo.eps",
    "content": "%!PS-Adobe-3.0 EPSF-3.0\n%%Creator: Adobe Illustrator(TM) 5.5\n%%For: (Bud Northern) (Mark Anderson Design)\n%%Title: (TCL/TK LOGO.ILLUS)\n%%CreationDate: (8/1/96) (4:58 PM)\n%%BoundingBox: 251 331 371 512\n%%HiResBoundingBox: 251.3386 331.5616 370.5213 511.775\n%%DocumentProcessColors: Cyan Magenta Yellow\n%%DocumentSuppliedResources: procset Adobe_level2_AI5 1.0 0\n%%+ procset Adobe_IllustratorA_AI5 1.0 0\n%AI5_FileFormat 1.2\n%AI3_ColorUsage: Color\n%%DocumentCustomColors: (TCL RED)\n%%CMYKCustomColor: 0 0.45 1 0 (Orange)\n%%+ 0 0.25 1 0 (Orange Yellow)\n%%+ 0 0.79 0.91 0 (TCL RED)\n%AI3_TemplateBox: 306 396 306 396\n%AI3_TileBox: 12 12 600 780\n%AI3_DocumentPreview: Macintosh_ColorPic\n%AI5_ArtSize: 612 792\n%AI5_RulerUnits: 0\n%AI5_ArtFlags: 1 0 0 1 0 0 1 1 0\n%AI5_TargetResolution: 800\n%AI5_NumLayers: 1\n%AI5_OpenToView: 90 576 2 938 673 18 1 1 2 40\n%AI5_OpenViewLayers: 7\n%%EndComments\n%%BeginProlog\n%%BeginResource: procset Adobe_level2_AI5 1.0 0\n%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)\n%%Version: 1.0\n%%CreationDate: (04/10/93) ()\n%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)\nuserdict /Adobe_level2_AI5 21 dict dup begin\n\tput\n\t/packedarray where not\n\t{\n\t\tuserdict begin\n\t\t/packedarray\n\t\t{\n\t\t\tarray astore readonly\n\t\t} bind def\n\t\t/setpacking /pop load def\n\t\t/currentpacking false def\n\t end\n\t\t0\n\t} if\n\tpop\n\tuserdict /defaultpacking currentpacking put true setpacking\n\t/initialize\n\t{\n\t\tAdobe_level2_AI5 begin\n\t} bind def\n\t/terminate\n\t{\n\t\tcurrentdict Adobe_level2_AI5 eq\n\t\t{\n\t\t end\n\t\t} if\n\t} bind def\n\tmark\n\t/setcustomcolor where not\n\t{\n\t\t/findcmykcustomcolor\n\t\t{\n\t\t\t5 packedarray\n\t\t} bind def\n\t\t/setcustomcolor\n\t\t{\n\t\t\texch aload pop pop\n\t\t\t4\n\t\t\t{\n\t\t\t\t4 index mul 4 1 roll\n\t\t\t} repeat\n\t\t\t5 -1 roll pop\n\t\t\tsetcmykcolor\n\t\t}\n\t\tdef\n\t} if\n\n\t/gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def\n\tuserdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put\n\tuserdict /level2?\n\tsystemdict /languagelevel known dup\n\t{\n\t\tpop systemdict /languagelevel get 2 ge\n\t} if\n\tput\n\tlevel2? not\n\t{\n\t\t/setcmykcolor where not\n\t\t{\n\t\t\t/setcmykcolor\n\t\t\t{\n\t\t\t\texch .11 mul add exch .59 mul add exch .3 mul add\n\t\t\t\t1 exch sub setgray\n\t\t\t} def\n\t\t} if\n\t\t/currentcmykcolor where not\n\t\t{\n\t\t\t/currentcmykcolor\n\t\t\t{\n\t\t\t\t0 0 0 1 currentgray sub\n\t\t\t} def\n\t\t} if\n\t\t/setoverprint where not\n\t\t{\n\t\t\t/setoverprint /pop load def\n\t\t} if\n\t\t/selectfont where not\n\t\t{\n\t\t\t/selectfont\n\t\t\t{\n\t\t\t\texch findfont exch\n\t\t\t\tdup type /arraytype eq\n\t\t\t\t{\n\t\t\t\t\tmakefont\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tscalefont\n\t\t\t\t} ifelse\n\t\t\t\tsetfont\n\t\t\t} bind def\n\t\t} if\n\t\t/cshow where not\n\t\t{\n\t\t\t/cshow\n\t\t\t{\n\t\t\t\t[\n\t\t\t\t0 0 5 -1 roll aload pop\n\t\t\t\t] cvx bind forall\n\t\t\t} bind def\n\t\t} if\n\t} if\n\tcleartomark\n\t/anyColor?\n\t{\n\t\tadd add add 0 ne\n\t} bind def\n\t/testColor\n\t{\n\t\tgsave\n\t\tsetcmykcolor currentcmykcolor\n\t\tgrestore\n\t} bind def\n\t/testCMYKColorThrough\n\t{\n\t\ttestColor anyColor?\n\t} bind def\n\tuserdict /composite?\n\tlevel2?\n\t{\n\t\tgsave 1 1 1 1 setcmykcolor currentcmykcolor grestore\n\t\tadd add add 4 eq\n\t}\n\t{\n\t\t1 0 0 0 testCMYKColorThrough\n\t\t0 1 0 0 testCMYKColorThrough\n\t\t0 0 1 0 testCMYKColorThrough\n\t\t0 0 0 1 testCMYKColorThrough\n\t\tand and and\n\t} ifelse\n\tput\n\tcomposite? not\n\t{\n\t\tuserdict begin\n\t\tgsave\n\t\t/cyan? 1 0 0 0 testCMYKColorThrough def\n\t\t/magenta? 0 1 0 0 testCMYKColorThrough def\n\t\t/yellow? 0 0 1 0 testCMYKColorThrough def\n\t\t/black? 0 0 0 1 testCMYKColorThrough def\n\t\tgrestore\n\t\t/isCMYKSep? cyan? magenta? yellow? black? or or or def\n\t\t/customColor? isCMYKSep? not def\n\t end\n\t} if\n end defaultpacking setpacking\n%%EndResource\n%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0\n%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)\n%%Version: 1.1\n%%CreationDate: (3/7/1994) ()\n%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)\ncurrentpacking true setpacking\nuserdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin\nput\n/_lp /none def\n/_pf\n{\n} def\n/_ps\n{\n} def\n/_psf\n{\n} def\n/_pss\n{\n} def\n/_pjsf\n{\n} def\n/_pjss\n{\n} def\n/_pola 0 def\n/_doClip 0 def\n/cf currentflat def\n/_tm matrix def\n/_renderStart\n[\n/e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0\n] def\n/_renderEnd\n[\nnull null null null /i1 /i1 /i1 /i1\n] def\n/_render -1 def\n/_rise 0 def\n/_ax 0 def\n/_ay 0 def\n/_cx 0 def\n/_cy 0 def\n/_leading\n[\n0 0\n] def\n/_ctm matrix def\n/_mtx matrix def\n/_sp 16#020 def\n/_hyphen (-) def\n/_fScl 0 def\n/_cnt 0 def\n/_hs 1 def\n/_nativeEncoding 0 def\n/_useNativeEncoding 0 def\n/_tempEncode 0 def\n/_pntr 0 def\n/_tDict 2 dict def\n/_wv 0 def\n/Tx\n{\n} def\n/Tj\n{\n} def\n/CRender\n{\n} def\n/_AI3_savepage\n{\n} def\n/_gf null def\n/_cf 4 array def\n/_if null def\n/_of false def\n/_fc\n{\n} def\n/_gs null def\n/_cs 4 array def\n/_is null def\n/_os false def\n/_sc\n{\n} def\n/discardSave null def\n/buffer 256 string def\n/beginString null def\n/endString null def\n/endStringLength null def\n/layerCnt 1 def\n/layerCount 1 def\n/perCent (%) 0 get def\n/perCentSeen? false def\n/newBuff null def\n/newBuffButFirst null def\n/newBuffLast null def\n/clipForward? false def\nend\nuserdict /Adobe_IllustratorA_AI5 74 dict dup begin\nput\n/initialize\n{\n\tAdobe_IllustratorA_AI5 dup begin\n\tAdobe_IllustratorA_AI5_vars begin\n\tdiscardDict\n\t{\n\t\tbind pop pop\n\t} forall\n\tdup /nc get begin\n\t{\n\t\tdup xcheck 1 index type /operatortype ne and\n\t\t{\n\t\t\tbind\n\t\t} if\n\t\tpop pop\n\t} forall\n end\n\tnewpath\n} def\n/terminate\n{\n end\n end\n} def\n/_\nnull def\n/ddef\n{\n\tAdobe_IllustratorA_AI5_vars 3 1 roll put\n} def\n/xput\n{\n\tdup load dup length exch maxlength eq\n\t{\n\t\tdup dup load dup\n\t\tlength 2 mul dict copy def\n\t} if\n\tload begin\n\tdef\n end\n} def\n/npop\n{\n\t{\n\t\tpop\n\t} repeat\n} def\n/sw\n{\n\tdup length exch stringwidth\n\texch 5 -1 roll 3 index mul add\n\t4 1 roll 3 1 roll mul add\n} def\n/swj\n{\n\tdup 4 1 roll\n\tdup length exch stringwidth\n\texch 5 -1 roll 3 index mul add\n\t4 1 roll 3 1 roll mul add\n\t6 2 roll /_cnt 0 ddef\n\t{\n\t\t1 index eq\n\t\t{\n\t\t\t/_cnt _cnt 1 add ddef\n\t\t} if\n\t} forall\n\tpop\n\texch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop\n} def\n/ss\n{\n\t4 1 roll\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put pop\n\t\tgsave\n\t\tfalse charpath currentpoint\n\t\t4 index setmatrix\n\t\tstroke\n\t\tgrestore\n\t\tmoveto\n\t\t2 copy rmoveto\n\t} exch cshow\n\t3 npop\n} def\n/jss\n{\n\t4 1 roll\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put\n\t\tgsave\n\t\t_sp eq\n\t\t{\n\t\t\texch 6 index 6 index 6 index 5 -1 roll widthshow\n\t\t\tcurrentpoint\n\t\t}\n\t\t{\n\t\t\tfalse charpath currentpoint\n\t\t\t4 index setmatrix stroke\n\t\t} ifelse\n\t\tgrestore\n\t\tmoveto\n\t\t2 copy rmoveto\n\t} exch cshow\n\t6 npop\n} def\n/sp\n{\n\t{\n\t\t2 npop (0) exch\n\t\t2 copy 0 exch put pop\n\t\tfalse charpath\n\t\t2 copy rmoveto\n\t} exch cshow\n\t2 npop\n} def\n/jsp\n{\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put\n\t\t_sp eq\n\t\t{\n\t\t\texch 5 index 5 index 5 index 5 -1 roll widthshow\n\t\t}\n\t\t{\n\t\t\tfalse charpath\n\t\t} ifelse\n\t\t2 copy rmoveto\n\t} exch cshow\n\t5 npop\n} def\n/pl\n{\n\ttransform\n\t0.25 sub round 0.25 add exch\n\t0.25 sub round 0.25 add exch\n\titransform\n} def\n/setstrokeadjust where\n{\n\tpop true setstrokeadjust\n\t/c\n\t{\n\t\tcurveto\n\t} def\n\t/C\n\t/c load def\n\t/v\n\t{\n\t\tcurrentpoint 6 2 roll curveto\n\t} def\n\t/V\n\t/v load def\n\t/y\n\t{\n\t\t2 copy curveto\n\t} def\n\t/Y\n\t/y load def\n\t/l\n\t{\n\t\tlineto\n\t} def\n\t/L\n\t/l load def\n\t/m\n\t{\n\t\tmoveto\n\t} def\n}\n{\n\t/c\n\t{\n\t\tpl curveto\n\t} def\n\t/C\n\t/c load def\n\t/v\n\t{\n\t\tcurrentpoint 6 2 roll pl curveto\n\t} def\n\t/V\n\t/v load def\n\t/y\n\t{\n\t\tpl 2 copy curveto\n\t} def\n\t/Y\n\t/y load def\n\t/l\n\t{\n\t\tpl lineto\n\t} def\n\t/L\n\t/l load def\n\t/m\n\t{\n\t\tpl moveto\n\t} def\n} ifelse\n/d\n{\n\tsetdash\n} def\n/cf\n{\n} def\n/i\n{\n\tdup 0 eq\n\t{\n\t\tpop cf\n\t} if\n\tsetflat\n} def\n/j\n{\n\tsetlinejoin\n} def\n/J\n{\n\tsetlinecap\n} def\n/M\n{\n\tsetmiterlimit\n} def\n/w\n{\n\tsetlinewidth\n} def\n/H\n{\n} def\n/h\n{\n\tclosepath\n} def\n/N\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tclip /_doClip 0 ddef\n\t\t} if\n\t\tnewpath\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tN\n\t\t} ddef\n\t} ifelse\n} def\n/n\n{\n\tN\n} def\n/F\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tgsave _pf grestore clip newpath /_lp /none ddef _fc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\t_pf\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tF\n\t\t} ddef\n\t} ifelse\n} def\n/f\n{\n\tclosepath\n\tF\n} def\n/S\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tgsave _ps grestore clip newpath /_lp /none ddef _sc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\t_ps\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tS\n\t\t} ddef\n\t} ifelse\n} def\n/s\n{\n\tclosepath\n\tS\n} def\n/B\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\tgsave F grestore\n\t\t{\n\t\t\tgsave S grestore clip newpath /_lp /none ddef _sc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\tS\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tB\n\t\t} ddef\n\t} ifelse\n} def\n/b\n{\n\tclosepath\n\tB\n} def\n/W\n{\n\t/_doClip 1 ddef\n} def\n/*\n{\n\tcount 0 ne\n\t{\n\t\tdup type /stringtype eq\n\t\t{\n\t\t\tpop\n\t\t} if\n\t} if\n\tnewpath\n} def\n/u\n{\n} def\n/U\n{\n} def\n/q\n{\n\t_pola 0 eq\n\t{\n\t\tgsave\n\t} if\n} def\n/Q\n{\n\t_pola 0 eq\n\t{\n\t\tgrestore\n\t} if\n} def\n/*u\n{\n\t_pola 1 add /_pola exch ddef\n} def\n/*U\n{\n\t_pola 1 sub /_pola exch ddef\n\t_pola 0 eq\n\t{\n\t\tCRender\n\t} if\n} def\n/D\n{\n\tpop\n} def\n/*w\n{\n} def\n/*W\n{\n} def\n/`\n{\n\t/_i save ddef\n\tclipForward?\n\t{\n\t\tnulldevice\n\t} if\n\t6 1 roll 4 npop\n\tconcat pop\n\tuserdict begin\n\t/showpage\n\t{\n\t} def\n\t0 setgray\n\t0 setlinecap\n\t1 setlinewidth\n\t0 setlinejoin\n\t10 setmiterlimit\n\t[] 0 setdash\n\t/setstrokeadjust where {pop false setstrokeadjust} if\n\tnewpath\n\t0 setgray\n\tfalse setoverprint\n} def\n/~\n{\n end\n\t_i restore\n} def\n/O\n{\n\t0 ne\n\t/_of exch ddef\n\t/_lp /none ddef\n} def\n/R\n{\n\t0 ne\n\t/_os exch ddef\n\t/_lp /none ddef\n} def\n/g\n{\n\t/_gf exch ddef\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_gf setgray\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/G\n{\n\t/_gs exch ddef\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_gs setgray\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/k\n{\n\t_cf astore pop\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_cf aload pop setcmykcolor\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/K\n{\n\t_cs astore pop\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_cs aload pop setcmykcolor\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/x\n{\n\t/_gf exch ddef\n\tfindcmykcustomcolor\n\t/_if exch ddef\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_if _gf 1 exch sub setcustomcolor\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/X\n{\n\t/_gs exch ddef\n\tfindcmykcustomcolor\n\t/_is exch ddef\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_is _gs 1 exch sub setcustomcolor\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/A\n{\n\tpop\n} def\n/annotatepage\n{\nuserdict /annotatepage 2 copy known {get exec} {pop pop} ifelse\n} def\n/discard\n{\n\tsave /discardSave exch store\n\tdiscardDict begin\n\t/endString exch store\n\tgt38?\n\t{\n\t\t2 add\n\t} if\n\tload\n\tstopped\n\tpop\n end\n\tdiscardSave restore\n} bind def\nuserdict /discardDict 7 dict dup begin\nput\n/pre38Initialize\n{\n\t/endStringLength endString length store\n\t/newBuff buffer 0 endStringLength getinterval store\n\t/newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store\n\t/newBuffLast newBuff endStringLength 1 sub 1 getinterval store\n} def\n/shiftBuffer\n{\n\tnewBuff 0 newBuffButFirst putinterval\n\tnewBuffLast 0\n\tcurrentfile read not\n\t{\n\tstop\n\t} if\n\tput\n} def\n0\n{\n\tpre38Initialize\n\tmark\n\tcurrentfile newBuff readstring exch pop\n\t{\n\t\t{\n\t\t\tnewBuff endString eq\n\t\t\t{\n\t\t\t\tcleartomark stop\n\t\t\t} if\n\t\t\tshiftBuffer\n\t\t} loop\n\t}\n\t{\n\tstop\n\t} ifelse\n} def\n1\n{\n\tpre38Initialize\n\t/beginString exch store\n\tmark\n\tcurrentfile newBuff readstring exch pop\n\t{\n\t\t{\n\t\t\tnewBuff beginString eq\n\t\t\t{\n\t\t\t\t/layerCount dup load 1 add store\n\t\t\t}\n\t\t\t{\n\t\t\t\tnewBuff endString eq\n\t\t\t\t{\n\t\t\t\t\t/layerCount dup load 1 sub store\n\t\t\t\t\tlayerCount 0 eq\n\t\t\t\t\t{\n\t\t\t\t\t\tcleartomark stop\n\t\t\t\t\t} if\n\t\t\t\t} if\n\t\t\t} ifelse\n\t\t\tshiftBuffer\n\t\t} loop\n\t}\n\t{\n\tstop\n\t} ifelse\n} def\n2\n{\n\tmark\n\t{\n\t\tcurrentfile buffer readline not\n\t\t{\n\t\tstop\n\t\t} if\n\t\tendString eq\n\t\t{\n\t\t\tcleartomark stop\n\t\t} if\n\t} loop\n} def\n3\n{\n\t/beginString exch store\n\t/layerCnt 1 store\n\tmark\n\t{\n\t\tcurrentfile buffer readline not\n\t\t{\n\t\tstop\n\t\t} if\n\t\tdup beginString eq\n\t\t{\n\t\t\tpop /layerCnt dup load 1 add store\n\t\t}\n\t\t{\n\t\t\tendString eq\n\t\t\t{\n\t\t\t\tlayerCnt 1 eq\n\t\t\t\t{\n\t\t\t\t\tcleartomark stop\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\t/layerCnt dup load 1 sub store\n\t\t\t\t} ifelse\n\t\t\t} if\n\t\t} ifelse\n\t} loop\n} def\nend\nuserdict /clipRenderOff 15 dict dup begin\nput\n{\n\t/n /N /s /S /f /F /b /B\n}\n{\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\t/_doClip 0 ddef clip\n\t\t} if\n\t\tnewpath\n\t} def\n} forall\n/Tr /pop load def\n/Bb {} def\n/BB /pop load def\n/Bg {12 npop} def\n/Bm {6 npop} def\n/Bc /Bm load def\n/Bh {4 npop} def\nend\n/Lb\n{\n\t4 npop\n\t6 1 roll\n\tpop\n\t4 1 roll\n\tpop pop pop\n\t0 eq\n\t{\n\t\t0 eq\n\t\t{\n\t\t\t(%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard\n\t\t}\n\t\t{\n\t\t\t/clipForward? true def\n\n\t\t\t/Tx /pop load def\n\t\t\t/Tj /pop load def\n\t\t\tcurrentdict end clipRenderOff begin begin\n\t\t} ifelse\n\t}\n\t{\n\t\t0 eq\n\t\t{\n\t\t\tsave /discardSave exch store\n\t\t} if\n\t} ifelse\n} bind def\n/LB\n{\n\tdiscardSave dup null ne\n\t{\n\t\trestore\n\t}\n\t{\n\t\tpop\n\t\tclipForward?\n\t\t{\n\t\t\tcurrentdict\n\t\t end\n\t\t end\n\t\t begin\n\n\t\t\t/clipForward? false ddef\n\t\t} if\n\t} ifelse\n} bind def\n/Pb\n{\n\tpop pop\n\t0 (%AI5_EndPalette) discard\n} bind def\n/Np\n{\n\t0 (%AI5_End_NonPrinting--) discard\n} bind def\n/Ln /pop load def\n/Ap\n/pop load def\n/Ar\n{\n\t72 exch div\n\t0 dtransform dup mul exch dup mul add sqrt\n\tdup 1 lt\n\t{\n\t\tpop 1\n\t} if\n\tsetflat\n} def\n/Mb\n{\n\tq\n} def\n/Md\n{\n} def\n/MB\n{\n\tQ\n} def\n/nc 3 dict def\nnc begin\n/setgray\n{\n\tpop\n} bind def\n/setcmykcolor\n{\n\t4 npop\n} bind def\n/setcustomcolor\n{\n\t2 npop\n} bind def\ncurrentdict readonly pop\nend\ncurrentdict readonly pop\nend\nsetpacking\n%%EndResource\n%%EndProlog\n%%BeginSetup\nAdobe_level2_AI5 /initialize get exec\nAdobe_IllustratorA_AI5 /initialize get exec\n%AI5_Begin_NonPrinting\nNp\n%AI3_BeginPattern: (Yellow Stripe)\n(Yellow Stripe) 8.4499 4.6 80.4499 76.6 [\n%AI3_Tile\n(0 O 0 R 0 0.4 1 0 k 0 0.4 1 0 K) @\n(\n800 Ar\n0 J 0 j 3.6 w 4 M []0 d\n%AI3_Note:\n0 D\n8.1999 8.1999 m\n80.6999 8.1999 L\nS\n8.1999 22.6 m\n80.6999 22.6 L\nS\n8.1999 37.0001 m\n80.6999 37.0001 L\nS\n8.1999 51.3999 m\n80.6999 51.3999 L\nS\n8.1999 65.8 m\n80.6999 65.8 L\nS\n8.1999 15.3999 m\n80.6999 15.3999 L\nS\n8.1999 29.8 m\n80.6999 29.8 L\nS\n8.1999 44.1999 m\n80.6999 44.1999 L\nS\n8.1999 58.6 m\n80.6999 58.6 L\nS\n8.1999 73.0001 m\n80.6999 73.0001 L\nS\n) &\n] E\n%AI3_EndPattern\n%AI5_End_NonPrinting--\n%AI5_Begin_NonPrinting\nNp\n3 Bn\n%AI5_BeginGradient: (Black & White)\n(Black & White) 0 2 Bd\n[\n<\nFFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8\nD7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0\nAFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A8988\n87868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160\n5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A3938\n37363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A19181716151413121110\n0F0E0D0C0B0A09080706050403020100\n>\n0 %_Br\n[\n0 0 50 100 %_Bs\n1 0 50 0 %_Bs\nBD\n%AI5_EndGradient\n%AI5_BeginGradient: (Red & Yellow)\n(Red & Yellow) 0 2 Bd\n[\n0\n<\n000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627\n28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F\n505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677\n78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\nA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nC8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF\nF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\n>\n<\nFFFFFEFEFDFDFDFCFCFBFBFBFAFAF9F9F9F8F8F7F7F7F6F6F5F5F5F4F4F3F3F3F2F2F1F1F1F0F0EF\nEFEFEEEEEDEDEDECECEBEBEBEAEAE9E9E9E8E8E7E7E7E6E6E5E5E5E4E4E3E3E3E2E2E1E1E1E0E0DF\nDFDFDEDEDDDDDDDCDCDBDBDBDADAD9D9D9D8D8D7D7D7D6D6D5D5D5D4D4D3D3D3D2D2D1D1D1D0D0CF\nCFCFCECECDCDCDCCCCCBCBCBCACAC9C9C9C8C8C7C7C7C6C6C5C5C5C4C4C3C3C3C2C2C1C1C1C0C0BF\nBFBFBEBEBDBDBDBCBCBBBBBBBABAB9B9B9B8B8B7B7B7B6B6B5B5B5B4B4B3B3B3B2B2B1B1B1B0B0AF\nAFAFAEAEADADADACACABABABAAAAA9A9A9A8A8A7A7A7A6A6A5A5A5A4A4A3A3A3A2A2A1A1A1A0A09F\n9F9F9E9E9D9D9D9C9C9B9B9B9A9A9999\n>\n0\n1 %_Br\n[\n0 1 0.6 0 1 50 100 %_Bs\n0 0 1 0 1 50 0 %_Bs\nBD\n%AI5_EndGradient\n%AI5_BeginGradient: (Yellow & Blue Radial)\n(Yellow & Blue Radial) 1 2 Bd\n[\n<\n000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627\n28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F\n505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677\n78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\nA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nC8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF\nF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\n>\n<\n1415161718191A1B1C1D1E1F1F202122232425262728292A2A2B2C2D2E2F30313233343536363738\n393A3B3C3D3E3F40414142434445464748494A4B4C4D4D4E4F50515253545556575858595A5B5C5D\n5E5F60616263646465666768696A6B6C6D6E6F6F707172737475767778797A7B7B7C7D7E7F808182\n83848586868788898A8B8C8D8E8F90919292939495969798999A9B9C9D9D9E9FA0A1A2A3A4A5A6A7\nA8A9A9AAABACADAEAFB0B1B2B3B4B4B5B6B7B8B9BABBBCBDBEBFC0C0C1C2C3C4C5C6C7C8C9CACBCB\nCCCDCECFD0D1D2D3D4D5D6D7D7D8D9DADBDCDDDEDFE0E1E2E2E3E4E5E6E7E8E9EAEBECEDEEEEEFF0\nF1F2F3F4F5F6F7F8F9F9FAFBFCFDFEFF\n>\n<\nABAAAAA9A8A7A7A6A5A5A4A3A3A2A1A1A09F9F9E9D9D9C9B9B9A9999989797969595949393929191\n908F8F8E8D8D8C8B8B8A8989888787868585848383828181807F7F7E7D7D7C7B7B7A797978777776\n7575747373727171706F6F6E6D6D6C6B6B6A6969686767666565646362626160605F5E5E5D5C5C5B\n5A5A5958585756565554545352525150504F4E4E4D4C4C4B4A4A4948484746464544444342424140\n403F3E3E3D3C3C3B3A3A3938383736363534343332323130302F2E2E2D2C2C2B2A2A292828272626\n25242423222121201F1F1E1D1D1C1B1B1A1919181717161515141313121111100F0F0E0D0D0C0B0B\n0A090908070706050504030302010100\n>\n0\n1 %_Br\n[\n0 0.08 0.67 0 1 50 14 %_Bs\n1 1 0 0 1 50 100 %_Bs\nBD\n%AI5_EndGradient\n%AI5_End_NonPrinting--\n%AI5_BeginPalette\n144 170 Pb\nPn\nPc\n1 g\nPc\n0 g\nPc\n0 0 0 0 k\nPc\n0.75 g\nPc\n0.5 g\nPc\n0.25 g\nPc\n0 g\nPc\nBb\n2 (Black & White) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0.25 0 0 0 k\nPc\n0.5 0 0 0 k\nPc\n0.75 0 0 0 k\nPc\n1 0 0 0 k\nPc\n0.25 0.25 0 0 k\nPc\n0.5 0.5 0 0 k\nPc\n0.75 0.75 0 0 k\nPc\n1 1 0 0 k\nPc\nBb\n2 (Red & Yellow) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0 0.25 0 0 k\nPc\n0 0.5 0 0 k\nPc\n0 0.75 0 0 k\nPc\n0 1 0 0 k\nPc\n0 0.25 0.25 0 k\nPc\n0 0.5 0.5 0 k\nPc\n0 0.75 0.75 0 k\nPc\n0 1 1 0 k\nPc\nBb\n0 0 0 0 Bh\n2 (Yellow & Blue Radial) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0 0 0.25 0 k\nPc\n0 0 0.5 0 k\nPc\n0 0 0.75 0 k\nPc\n0 0 1 0 k\nPc\n0.25 0 0.25 0 k\nPc\n0.5 0 0.5 0 k\nPc\n0.75 0 0.75 0 k\nPc\n1 0 1 0 k\nPc\n(Yellow Stripe) 0 0 1 1 0 0 0 0 0 [1 0 0 1 0 0] p\nPc\n0.25 0.125 0 0 k\nPc\n0.5 0.25 0 0 k\nPc\n0.75 0.375 0 0 k\nPc\n1 0.5 0 0 k\nPc\n0.125 0.25 0 0 k\nPc\n0.25 0.5 0 0 k\nPc\n0.375 0.75 0 0 k\nPc\n0.5 1 0 0 k\nPc\n0.375 0.375 0.75 0 k\nPc\n0 0.25 0.125 0 k\nPc\n0 0.5 0.25 0 k\nPc\n0 0.75 0.375 0 k\nPc\n0 1 0.5 0 k\nPc\n0 0.125 0.25 0 k\nPc\n0 0.25 0.5 0 k\nPc\n0 0.375 0.75 0 k\nPc\n0 0.5 1 0 k\nPc\n0 0.79 0.91 0 (TCL RED) 0 x\nPc\n0.125 0 0.25 0 k\nPc\n0.25 0 0.5 0 k\nPc\n0.375 0 0.75 0 k\nPc\n0.5 0 1 0 k\nPc\n0.25 0 0.125 0 k\nPc\n0.5 0 0.25 0 k\nPc\n0.75 0 0.375 0 k\nPc\n1 0 0.5 0 k\nPc\n0.5 1 0 0 k\nPc\n0.25 0.125 0.125 0 k\nPc\n0.5 0.25 0.25 0 k\nPc\n0.75 0.375 0.375 0 k\nPc\n1 0.5 0.5 0 k\nPc\n0.25 0.25 0.125 0 k\nPc\n0.5 0.5 0.25 0 k\nPc\n0.75 0.75 0.375 0 k\nPc\n1 1 0.5 0 k\nPc\n0 1 0.5 0 k\nPc\n0.125 0.25 0.125 0 k\nPc\n0.25 0.5 0.25 0 k\nPc\n0.375 0.75 0.375 0 k\nPc\n0.5 1 0.5 0 k\nPc\n0.125 0.25 0.25 0 k\nPc\n0.25 0.5 0.5 0 k\nPc\n0.375 0.75 0.75 0 k\nPc\n0.5 1 1 0 k\nPc\n0.75 0.75 0.375 0 k\nPc\n0.125 0.125 0.25 0 k\nPc\n0.25 0.25 0.5 0 k\nPc\n0.375 0.375 0.75 0 k\nPc\n0.5 0.5 1 0 k\nPc\n0.25 0.125 0.25 0 k\nPc\n0.5 0.25 0.5 0 k\nPc\n0.75 0.375 0.75 0 k\nPc\n1 0.5 1 0 k\nPc\n0 0.79 0.91 0 (TCL RED) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0.5 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.25 1 0 (Orange Yellow) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 1 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.45 1 0 (Orange) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0.375 0.375 0.75 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.79 0.91 0 (TCL RED) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0.65 0 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0 1 0 k\nPc\nPB\n%AI5_EndPalette\n%%EndSetup\n%AI5_BeginLayer\n1 1 1 1 0 0 0 79 128 255 Lb\n(Layer 1) Ln\n0 A\nu\n1 Ap\n0 O\n0 0.79 0.91 0 (TCL RED) 0 x\n800 Ar\n0 J 0 j 1.25 w 4 M []0 d\n%AI3_Note:\n0 D\n294.5207 335.3041 m\n368.2181 333.001 L\n363.6121 423.9713 L\n370.5213 507.1689 L\n336.5513 505.4417 L\n320.7179 511.775 L\n251.3386 508.0325 L\n254.7931 425.9866 L\n251.3386 331.5616 L\n294.5207 335.3041 L\nf\nu\n0 Ap\n1 0.65 0 0 k\n1 w\n318.1366 400.9627 m\n311.8663 399.2526 l\n315.2864 407.5177 l\n318.7064 430.6032 l\n314.4314 431.4581 l\n319.5616 438.5832 l\n325.9526 462.6014 l\n314.7164 460.2436 l\n320.6412 471.0911 326.9284 478.1557 v\n318.7064 484.469 l\n292.2183 472.8011 299.3434 434.8954 v\n293.8679 435.8542 l\n299.1189 396.1175 l\n294.6797 394.9775 l\n299.2277 385.6974 305.5963 381.2973 v\n306.1744 380.8979 297.6162 412.3629 306.7363 443.7133 c\n307.5914 441.7183 l\n300.3238 408.3015 307.5914 381.2973 v\n307.9261 380.656 311.5598 381.0836 v\n318.1366 393.4813 318.1366 400.9627 v\nf\nu\n*u\n1 g\n271.4311 372.5074 m\n272.7184 372.5074 L\n272.7184 375.1913 L\n273.2858 375.1913 273.8313 375.1913 274.3768 375.2786 c\n274.3768 372.5074 L\n276.2969 372.5074 L\n276.2969 372.0056 L\n274.3768 372.0056 L\n274.3768 365.3286 L\n274.3768 364.9359 274.3768 364.3467 275.2059 364.3467 c\n275.7733 364.3467 276.0787 364.7395 276.4279 365.1541 c\n276.777 364.9141 L\n276.3624 364.0849 275.2932 363.583 274.4204 363.583 c\n272.8494 363.583 272.6748 364.434 272.6748 365.4814 c\n272.6748 372.0056 L\n271.4311 372.0056 L\n271.4311 372.5074 l\nf\n*U\n*u\n290.5617 366.5724 m\n290.0598 365.0232 289.187 363.6703 286.9178 363.583 c\n283.5356 363.583 282.5101 366.3978 282.5101 367.9034 c\n282.5101 371.7874 285.6304 372.7256 286.8741 372.7256 c\n288.2924 372.7256 290.2999 372.071 290.2999 370.3909 c\n290.2999 369.8018 289.9289 369.2344 289.318 369.2344 c\n288.7288 369.2344 288.2924 369.6272 288.2924 370.26 c\n288.2924 371.111 288.9907 371.2201 288.9907 371.4601 c\n288.9907 372.0492 287.616 372.2892 287.136 372.2892 c\n285.0412 372.2892 284.4957 370.7618 284.4957 367.9034 c\n284.4957 366.5942 284.823 365.5905 284.9539 365.285 c\n285.2812 364.5649 285.9577 364.1067 287.0923 364.0413 c\n288.3579 363.9758 289.5798 365.0013 290.1035 366.5724 C\n290.5617 366.5724 l\nf\n*U\n*u\n296.6 363.8667 m\n296.6 364.3686 L\n298.2802 364.3686 L\n298.2802 378.3989 L\n296.6 378.3989 L\n296.6 378.9007 L\n297.5383 378.9007 L\n298.3457 378.9007 299.1966 378.9444 299.9822 379.0971 c\n299.9822 364.3686 L\n301.6623 364.3686 L\n301.6623 363.8667 L\n296.6 363.8667 l\nf\n*U\n*u\n317.4527 372.5074 m\n318.7401 372.5074 L\n318.7401 375.1913 L\n319.3074 375.1913 319.8529 375.1913 320.3984 375.2786 c\n320.3984 372.5074 L\n322.3186 372.5074 L\n322.3186 372.0056 L\n320.3984 372.0056 L\n320.3984 365.3286 L\n320.3984 364.9359 320.3984 364.3467 321.2276 364.3467 c\n321.7949 364.3467 322.1004 364.7395 322.4495 365.1541 c\n322.7986 364.9141 L\n322.384 364.0849 321.3148 363.583 320.442 363.583 c\n318.871 363.583 318.6964 364.434 318.6964 365.4814 c\n318.6964 372.0056 L\n317.4527 372.0056 L\n317.4527 372.5074 l\nf\n*U\n*u\n333.7467 372.0056 m\n333.7467 372.5074 L\n337.3252 372.5074 L\n337.3252 372.0056 L\n335.9942 372.0056 L\n332.983 369.3872 L\n337.1288 364.3686 L\n338.0453 364.3686 L\n338.0453 363.8667 L\n333.8995 363.8667 L\n333.8995 364.3686 L\n334.9905 364.3686 L\n331.3465 368.798 L\n335.0341 371.9401 L\n335.0341 372.0056 L\n333.7467 372.0056 l\nf\n328.4881 363.8667 m\n328.4881 364.3686 L\n329.6227 364.3686 L\n329.6227 378.3989 L\n328.4881 378.3989 L\n328.4881 378.9007 L\n328.8809 378.9007 L\n329.6882 378.9007 330.5392 378.9444 331.3247 379.0971 c\n331.3247 364.3686 L\n332.6339 364.3686 L\n332.6339 363.8667 L\n328.4881 363.8667 l\nf\n*U\nu\n309.5341 446.5364 m\n305.6878 429.3874 306.7947 401.5837 v\n307.1266 393.2441 308.0387 385.5779 309.1527 378.9301 C\n309.1587 378.9297 L\n309.8832 373.0923 310.3679 370.9791 312.2568 363.9454 C\n312.1466 359.4091 L\n297.0216 407.7015 309.5341 446.5364 V\nf\n318.8187 461.4058 m\n322.2203 463.1 327.0966 463.7165 v\n332.427 453.9463 319.3087 437.2655 v\n327.1346 454.735 325.2889 460.2079 v\n323.225 461.4903 318.8187 461.4058 v\nf\n317.2065 432.0795 m\n320.2613 431.3723 321.7279 432.5601 v\n318.8383 421.2839 319.5958 415.0813 v\n320.3533 408.8787 314.8881 404.9079 y\n319.5435 410.7982 318.0802 415.5959 v\n317.0657 418.9214 318.2006 427.4326 319.4809 430.1349 c\n318.2853 430.3025 317.2065 432.0795 v\nf\n314.1861 402.3703 m\n319.2343 402.9744 319.7646 405.5244 v\n320.3824 390.2725 313.3689 383.9873 v\n318.7204 392.3347 317.8807 400.9697 v\n314.1861 402.3703 l\nf\n299.9864 396.0219 m\n298.3586 394.1986 293.4739 398.2203 v\n295.0301 387.9694 304.6978 383.2767 v\n298.0444 388.2897 296.2519 393.7045 v\n298.6029 394.3966 299.9864 396.0219 v\nf\n298.4281 399.9096 m\n291.8229 416.6749 293.2382 439.3286 v\n294.7808 435.2261 299.738 433.7875 v\n297.4026 433.3101 296.0372 433.517 v\n292.5816 423.9535 298.4281 399.9096 v\nf\n326.1736 477.812 m\n323.6983 496.0028 308.2122 477.6066 v\n295.8813 462.9582 297.3508 450.5217 298.1072 443.5831 c\n298.3007 441.8079 295.8131 462.1138 309.3231 475.4768 c\n322.8328 488.8398 325.8846 478.5879 326.1736 477.812 c\nf\nU\n0 0 1 0 k\n303.3623 493.3274 m\n291.211 496.7978 287.3437 456.5222 v\n284.3599 468.9535 292.0777 486.5353 v\n299.7955 504.1172 303.3623 493.3274 y\nf\n288.2873 496.2718 m\n282.0897 486.9502 283.4958 477.0213 v\n278.7953 495.712 288.2873 496.2718 v\nf\n333.8987 470.1328 m\n341.2276 472.8361 330.7334 445.5571 v\n336.1654 453.5292 339.5844 466.0531 v\n341.7789 474.0903 333.8987 470.1328 y\nf\n345.752 472.2583 m\n350.9334 467.5681 347.2615 461.3636 v\n356.4779 471.0481 345.752 472.2583 v\nf\nU\n*u\n273.1765 354.3318 m\n273.1765 353.7507 273.1305 353.2908 272.5159 353.2908 c\n271.8846 353.2908 271.8554 353.7674 271.8554 354.3318 c\n271.8554 356.485 L\n272.148 356.485 L\n272.148 354.3486 L\n272.148 353.8259 272.1773 353.5751 272.5159 353.5751 c\n272.8504 353.5751 272.8839 353.8259 272.8839 354.3486 c\n272.8839 356.485 L\n273.1765 356.485 L\n273.1765 354.3318 l\nf\n*U\n*u\n277.1612 356.485 m\n276.9062 356.485 L\n276.9062 354.3862 l\n276.9062 354.2482 276.9271 354.1061 276.9355 353.9681 C\n276.9229 353.9681 l\n276.8937 354.0768 276.8644 354.1855 276.8268 354.2942 C\n276.1035 356.485 L\n275.8484 356.485 L\n275.8484 353.3326 L\n276.1035 353.3326 L\n276.1035 355.2474 l\n276.1035 355.4523 276.0826 355.653 276.07 355.8579 C\n276.0867 355.8579 l\n276.1244 355.7241 276.1495 355.5819 276.1954 355.4523 C\n276.9062 353.3326 L\n277.1612 353.3326 l\n277.1612 356.485 L\nf\n*U\n*u\n280.1421 353.3326 m\n279.8494 353.3326 L\n279.8494 356.485 L\n280.1421 356.485 L\n280.1421 353.3326 l\nf\n*U\n*u\n283.5141 353.3326 m\n283.2549 353.3326 L\n282.6194 356.485 L\n282.9205 356.485 L\n283.3344 354.1897 L\n283.3511 354.1102 283.3678 353.9054 283.3845 353.7632 c\n283.4013 353.7632 L\n283.4138 353.9054 283.4305 354.1144 283.4431 354.1897 c\n283.8528 356.485 L\n284.1496 356.485 L\n283.5141 353.3326 l\nf\n*U\n*u\n287.6238 356.2174 m\n286.9256 356.2174 L\n286.9256 355.1053 L\n287.6029 355.1053 L\n287.6029 354.8377 L\n286.9256 354.8377 L\n286.9256 353.6002 L\n287.6238 353.6002 L\n287.6238 353.3326 L\n286.6329 353.3326 L\n286.6329 356.485 L\n287.6238 356.485 L\n287.6238 356.2174 l\nf\n*U\n*u\n290.2278 353.3326 m\n290.2278 356.485 L\n290.5414 356.485 L\n290.9804 356.485 291.4026 356.4515 291.4026 355.6823 c\n291.4026 355.2809 291.3148 354.8879 290.8089 354.8712 c\n291.5072 353.3326 L\n291.1978 353.3326 L\n290.5288 354.8753 L\n290.5205 354.8753 L\n290.5205 353.3326 L\n290.2278 353.3326 l\nf\n290.5205 355.1137 m\n290.625 355.1137 L\n291.0347 355.1137 291.1016 355.2558 291.1016 355.6697 c\n291.1016 356.1672 290.9511 356.2174 290.579 356.2174 c\n290.5205 356.2174 L\n290.5205 355.1137 l\nf\n*U\n*u\n295.0981 355.9875 m\n294.9727 356.1296 294.8347 356.2425 294.634 356.2425 c\n294.3414 356.2425 294.1783 356 294.1783 355.7324 c\n294.1783 355.3645 294.4459 355.1931 294.7176 355.0091 c\n294.9852 354.821 295.2528 354.6203 295.2528 354.1855 c\n295.2528 353.7256 294.9559 353.2908 294.4626 353.2908 c\n294.287 353.2908 294.1072 353.341 293.9651 353.4497 c\n293.9651 353.8301 L\n294.0989 353.688 294.2745 353.5751 294.4751 353.5751 c\n294.7845 353.5751 294.9559 353.8468 294.9518 354.1311 c\n294.9559 354.4991 294.6842 354.6621 294.4166 354.8503 c\n294.149 355.0342 293.8773 355.2391 293.8773 355.6906 c\n293.8773 356.1129 294.1365 356.5268 294.6006 356.5268 c\n294.7887 356.5268 294.9476 356.4641 295.0981 356.3596 C\n295.0981 355.9875 l\nf\n*U\n*u\n299.0865 353.3326 m\n298.773 353.3326 L\n298.6559 353.9806 L\n297.9869 353.9806 L\n297.8741 353.3326 L\n297.5605 353.3326 L\n298.1793 356.485 L\n298.4552 356.485 L\n299.0865 353.3326 l\nf\n298.6099 354.2357 m\n298.4009 355.444 L\n298.3632 355.6572 298.3465 355.8746 298.3214 356.0878 c\n298.3047 356.0878 L\n298.2754 355.8746 298.2545 355.6572 298.2211 355.444 c\n298.0371 354.2357 L\n298.6099 354.2357 l\nf\n*U\n*u\n301.8124 353.6002 m\n302.4981 353.6002 L\n302.4981 353.3326 L\n301.5198 353.3326 L\n301.5198 356.485 L\n301.8124 356.485 L\n301.8124 353.6002 l\nf\n*U\n*u\n309.0754 355.9875 m\n308.95 356.1296 308.812 356.2425 308.6114 356.2425 c\n308.3187 356.2425 308.1556 356 308.1556 355.7324 c\n308.1556 355.3645 308.4232 355.1931 308.695 355.0091 c\n308.9626 354.821 309.2301 354.6203 309.2301 354.1855 c\n309.2301 353.7256 308.9333 353.2908 308.4399 353.2908 c\n308.2643 353.2908 308.0846 353.341 307.9424 353.4497 c\n307.9424 353.8301 L\n308.0762 353.688 308.2518 353.5751 308.4525 353.5751 c\n308.7619 353.5751 308.9333 353.8468 308.9291 354.1311 c\n308.9333 354.4991 308.6615 354.6621 308.3939 354.8503 c\n308.1264 355.0342 307.8546 355.2391 307.8546 355.6906 c\n307.8546 356.1129 308.1138 356.5268 308.5779 356.5268 c\n308.766 356.5268 308.9249 356.4641 309.0754 356.3596 C\n309.0754 355.9875 l\nf\n*U\n*u\n312.9468 353.7172 m\n312.8339 353.6378 312.7001 353.5751 312.558 353.5751 c\n311.9977 353.5751 311.9977 354.5492 311.9977 354.9172 c\n311.9977 355.5025 312.0688 356.2425 312.5789 356.2425 c\n312.7252 356.2425 312.8297 356.184 312.9468 356.1045 C\n312.9468 356.4265 l\n312.8506 356.4975 312.6918 356.5268 312.5747 356.5268 c\n311.7134 356.5268 311.6967 355.306 311.6967 354.7959 c\n311.6967 354.2566 311.8054 353.2908 312.5454 353.2908 c\n312.6834 353.2908 312.8381 353.3451 312.9468 353.4204 c\n312.9468 353.7172 L\nf\n*U\n*u\n315.5053 353.3326 m\n315.5053 356.485 L\n315.8188 356.485 L\n316.2578 356.485 316.6801 356.4515 316.6801 355.6823 c\n316.6801 355.2809 316.5923 354.8879 316.0864 354.8712 c\n316.7846 353.3326 L\n316.4752 353.3326 L\n315.8063 354.8753 L\n315.7979 354.8753 L\n315.7979 353.3326 L\n315.5053 353.3326 l\nf\n315.7979 355.1137 m\n315.9025 355.1137 L\n316.3122 355.1137 316.3791 355.2558 316.3791 355.6697 c\n316.3791 356.1672 316.2286 356.2174 315.8565 356.2174 c\n315.7979 356.2174 L\n315.7979 355.1137 l\nf\n*U\n*u\n319.5728 353.3326 m\n319.2802 353.3326 L\n319.2802 356.485 L\n319.5728 356.485 L\n319.5728 353.3326 l\nf\n*U\n*u\n322.2551 353.3326 m\n322.2551 356.485 L\n322.5812 356.485 L\n323.0327 356.485 323.4341 356.4432 323.4341 355.6655 c\n323.4341 355.0551 323.2209 354.8419 322.623 354.8419 c\n322.5477 354.8419 L\n322.5477 353.3326 L\n322.2551 353.3326 l\nf\n322.5477 355.1095 m\n322.6606 355.1095 L\n323.0703 355.1095 323.1205 355.26 323.1331 355.6655 c\n323.1331 356.1004 323.016 356.2174 322.6063 356.2174 c\n322.5477 356.2174 L\n322.5477 355.1095 l\nf\n*U\n*u\n326.9539 356.485 m\n325.7164 356.485 L\n325.7164 356.2174 L\n326.1888 356.2174 L\n326.1888 353.3326 L\n326.4815 353.3326 L\n326.4815 356.2174 L\n326.9539 356.2174 l\n326.9539 356.485 L\nf\n*U\n*u\n329.7077 353.3326 m\n329.4151 353.3326 L\n329.4151 356.485 L\n329.7077 356.485 L\n329.7077 353.3326 l\nf\n*U\n*u\n333.7028 353.3326 m\n333.4477 353.3326 L\n332.737 355.4523 L\n332.691 355.5819 332.6659 355.7241 332.6283 355.8579 c\n332.6116 355.8579 L\n332.6241 355.653 332.645 355.4523 332.645 355.2474 c\n332.645 353.3326 L\n332.39 353.3326 L\n332.39 356.485 L\n332.645 356.485 L\n333.3683 354.2942 L\n333.4059 354.1855 333.4352 354.0768 333.4645 353.9681 c\n333.477 353.9681 L\n333.4686 354.1061 333.4477 354.2482 333.4477 354.3862 c\n333.4477 356.485 L\n333.7028 356.485 L\n333.7028 353.3326 l\nf\n*U\n*u\n336.9846 354.9966 m\n337.7037 354.9966 L\n337.7037 354.4154 L\n337.7037 353.9179 337.6787 353.2908 337.0264 353.2908 c\n336.3617 353.2908 336.299 353.989 336.299 354.9841 c\n336.299 355.7283 336.3868 356.5268 337.0557 356.5268 c\n337.432 356.5268 337.6201 356.276 337.6996 355.9331 c\n337.4111 355.8202 L\n337.3776 356.0084 337.2982 356.2425 337.0682 356.2425 c\n336.6334 356.2383 336.6 355.5652 336.6 355.0091 c\n336.6 353.8427 336.7463 353.5751 337.0515 353.5751 c\n337.3818 353.5751 337.4111 353.8176 337.4111 354.4907 c\n337.4111 354.729 L\n336.9846 354.729 L\n336.9846 354.9966 l\nf\n*U\nU\nU\n337.6667 -3924 m\n(N) *\n337.6667 4716 m\n(N) *\nLB\n%AI5_EndLayer--\n%%PageTrailer\ngsave annotatepage grestore showpage\n%%Trailer\nAdobe_IllustratorA_AI5 /terminate get exec\nAdobe_level2_AI5 /terminate get exec\n%%EOF\n"
  },
  {
    "path": "library/images/pwrdLogo.eps",
    "content": "%!PS-Adobe-3.0 EPSF-3.0\n%%Creator: Adobe Illustrator(TM) 5.5\n%%For: (Bud Northern) (Mark Anderson Design)\n%%Title: (TCL PWRD LOGO.ILLUS)\n%%CreationDate: (8/1/96) (4:59 PM)\n%%BoundingBox: 242 302 377 513\n%%HiResBoundingBox: 242.0523 302.5199 376.3322 512.5323\n%%DocumentProcessColors: Cyan Magenta Yellow\n%%DocumentSuppliedResources: procset Adobe_level2_AI5 1.0 0\n%%+ procset Adobe_IllustratorA_AI5 1.0 0\n%AI5_FileFormat 1.2\n%AI3_ColorUsage: Color\n%%CMYKCustomColor: 0 0.45 1 0 (Orange)\n%%+ 0 0.25 1 0 (Orange Yellow)\n%%+ 0 0.79 0.91 0 (PANTONE Warm Red CV)\n%%+ 0 0.79 0.91 0 (TCL RED)\n%AI3_TemplateBox: 306 396 306 396\n%AI3_TileBox: 12 12 600 780\n%AI3_DocumentPreview: Macintosh_ColorPic\n%AI5_ArtSize: 612 792\n%AI5_RulerUnits: 0\n%AI5_ArtFlags: 1 0 0 1 0 0 1 1 0\n%AI5_TargetResolution: 800\n%AI5_NumLayers: 1\n%AI5_OpenToView: 102 564 2 938 673 18 1 1 2 40\n%AI5_OpenViewLayers: 7\n%%EndComments\n%%BeginProlog\n%%BeginResource: procset Adobe_level2_AI5 1.0 0\n%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)\n%%Version: 1.0\n%%CreationDate: (04/10/93) ()\n%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)\nuserdict /Adobe_level2_AI5 21 dict dup begin\n\tput\n\t/packedarray where not\n\t{\n\t\tuserdict begin\n\t\t/packedarray\n\t\t{\n\t\t\tarray astore readonly\n\t\t} bind def\n\t\t/setpacking /pop load def\n\t\t/currentpacking false def\n\t end\n\t\t0\n\t} if\n\tpop\n\tuserdict /defaultpacking currentpacking put true setpacking\n\t/initialize\n\t{\n\t\tAdobe_level2_AI5 begin\n\t} bind def\n\t/terminate\n\t{\n\t\tcurrentdict Adobe_level2_AI5 eq\n\t\t{\n\t\t end\n\t\t} if\n\t} bind def\n\tmark\n\t/setcustomcolor where not\n\t{\n\t\t/findcmykcustomcolor\n\t\t{\n\t\t\t5 packedarray\n\t\t} bind def\n\t\t/setcustomcolor\n\t\t{\n\t\t\texch aload pop pop\n\t\t\t4\n\t\t\t{\n\t\t\t\t4 index mul 4 1 roll\n\t\t\t} repeat\n\t\t\t5 -1 roll pop\n\t\t\tsetcmykcolor\n\t\t}\n\t\tdef\n\t} if\n\n\t/gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def\n\tuserdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put\n\tuserdict /level2?\n\tsystemdict /languagelevel known dup\n\t{\n\t\tpop systemdict /languagelevel get 2 ge\n\t} if\n\tput\n\tlevel2? not\n\t{\n\t\t/setcmykcolor where not\n\t\t{\n\t\t\t/setcmykcolor\n\t\t\t{\n\t\t\t\texch .11 mul add exch .59 mul add exch .3 mul add\n\t\t\t\t1 exch sub setgray\n\t\t\t} def\n\t\t} if\n\t\t/currentcmykcolor where not\n\t\t{\n\t\t\t/currentcmykcolor\n\t\t\t{\n\t\t\t\t0 0 0 1 currentgray sub\n\t\t\t} def\n\t\t} if\n\t\t/setoverprint where not\n\t\t{\n\t\t\t/setoverprint /pop load def\n\t\t} if\n\t\t/selectfont where not\n\t\t{\n\t\t\t/selectfont\n\t\t\t{\n\t\t\t\texch findfont exch\n\t\t\t\tdup type /arraytype eq\n\t\t\t\t{\n\t\t\t\t\tmakefont\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tscalefont\n\t\t\t\t} ifelse\n\t\t\t\tsetfont\n\t\t\t} bind def\n\t\t} if\n\t\t/cshow where not\n\t\t{\n\t\t\t/cshow\n\t\t\t{\n\t\t\t\t[\n\t\t\t\t0 0 5 -1 roll aload pop\n\t\t\t\t] cvx bind forall\n\t\t\t} bind def\n\t\t} if\n\t} if\n\tcleartomark\n\t/anyColor?\n\t{\n\t\tadd add add 0 ne\n\t} bind def\n\t/testColor\n\t{\n\t\tgsave\n\t\tsetcmykcolor currentcmykcolor\n\t\tgrestore\n\t} bind def\n\t/testCMYKColorThrough\n\t{\n\t\ttestColor anyColor?\n\t} bind def\n\tuserdict /composite?\n\tlevel2?\n\t{\n\t\tgsave 1 1 1 1 setcmykcolor currentcmykcolor grestore\n\t\tadd add add 4 eq\n\t}\n\t{\n\t\t1 0 0 0 testCMYKColorThrough\n\t\t0 1 0 0 testCMYKColorThrough\n\t\t0 0 1 0 testCMYKColorThrough\n\t\t0 0 0 1 testCMYKColorThrough\n\t\tand and and\n\t} ifelse\n\tput\n\tcomposite? not\n\t{\n\t\tuserdict begin\n\t\tgsave\n\t\t/cyan? 1 0 0 0 testCMYKColorThrough def\n\t\t/magenta? 0 1 0 0 testCMYKColorThrough def\n\t\t/yellow? 0 0 1 0 testCMYKColorThrough def\n\t\t/black? 0 0 0 1 testCMYKColorThrough def\n\t\tgrestore\n\t\t/isCMYKSep? cyan? magenta? yellow? black? or or or def\n\t\t/customColor? isCMYKSep? not def\n\t end\n\t} if\n end defaultpacking setpacking\n%%EndResource\n%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0\n%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)\n%%Version: 1.1\n%%CreationDate: (3/7/1994) ()\n%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)\ncurrentpacking true setpacking\nuserdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin\nput\n/_lp /none def\n/_pf\n{\n} def\n/_ps\n{\n} def\n/_psf\n{\n} def\n/_pss\n{\n} def\n/_pjsf\n{\n} def\n/_pjss\n{\n} def\n/_pola 0 def\n/_doClip 0 def\n/cf currentflat def\n/_tm matrix def\n/_renderStart\n[\n/e0 /r0 /a0 /o0 /e1 /r1 /a1 /i0\n] def\n/_renderEnd\n[\nnull null null null /i1 /i1 /i1 /i1\n] def\n/_render -1 def\n/_rise 0 def\n/_ax 0 def\n/_ay 0 def\n/_cx 0 def\n/_cy 0 def\n/_leading\n[\n0 0\n] def\n/_ctm matrix def\n/_mtx matrix def\n/_sp 16#020 def\n/_hyphen (-) def\n/_fScl 0 def\n/_cnt 0 def\n/_hs 1 def\n/_nativeEncoding 0 def\n/_useNativeEncoding 0 def\n/_tempEncode 0 def\n/_pntr 0 def\n/_tDict 2 dict def\n/_wv 0 def\n/Tx\n{\n} def\n/Tj\n{\n} def\n/CRender\n{\n} def\n/_AI3_savepage\n{\n} def\n/_gf null def\n/_cf 4 array def\n/_if null def\n/_of false def\n/_fc\n{\n} def\n/_gs null def\n/_cs 4 array def\n/_is null def\n/_os false def\n/_sc\n{\n} def\n/discardSave null def\n/buffer 256 string def\n/beginString null def\n/endString null def\n/endStringLength null def\n/layerCnt 1 def\n/layerCount 1 def\n/perCent (%) 0 get def\n/perCentSeen? false def\n/newBuff null def\n/newBuffButFirst null def\n/newBuffLast null def\n/clipForward? false def\nend\nuserdict /Adobe_IllustratorA_AI5 74 dict dup begin\nput\n/initialize\n{\n\tAdobe_IllustratorA_AI5 dup begin\n\tAdobe_IllustratorA_AI5_vars begin\n\tdiscardDict\n\t{\n\t\tbind pop pop\n\t} forall\n\tdup /nc get begin\n\t{\n\t\tdup xcheck 1 index type /operatortype ne and\n\t\t{\n\t\t\tbind\n\t\t} if\n\t\tpop pop\n\t} forall\n end\n\tnewpath\n} def\n/terminate\n{\n end\n end\n} def\n/_\nnull def\n/ddef\n{\n\tAdobe_IllustratorA_AI5_vars 3 1 roll put\n} def\n/xput\n{\n\tdup load dup length exch maxlength eq\n\t{\n\t\tdup dup load dup\n\t\tlength 2 mul dict copy def\n\t} if\n\tload begin\n\tdef\n end\n} def\n/npop\n{\n\t{\n\t\tpop\n\t} repeat\n} def\n/sw\n{\n\tdup length exch stringwidth\n\texch 5 -1 roll 3 index mul add\n\t4 1 roll 3 1 roll mul add\n} def\n/swj\n{\n\tdup 4 1 roll\n\tdup length exch stringwidth\n\texch 5 -1 roll 3 index mul add\n\t4 1 roll 3 1 roll mul add\n\t6 2 roll /_cnt 0 ddef\n\t{\n\t\t1 index eq\n\t\t{\n\t\t\t/_cnt _cnt 1 add ddef\n\t\t} if\n\t} forall\n\tpop\n\texch _cnt mul exch _cnt mul 2 index add 4 1 roll 2 index add 4 1 roll pop pop\n} def\n/ss\n{\n\t4 1 roll\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put pop\n\t\tgsave\n\t\tfalse charpath currentpoint\n\t\t4 index setmatrix\n\t\tstroke\n\t\tgrestore\n\t\tmoveto\n\t\t2 copy rmoveto\n\t} exch cshow\n\t3 npop\n} def\n/jss\n{\n\t4 1 roll\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put\n\t\tgsave\n\t\t_sp eq\n\t\t{\n\t\t\texch 6 index 6 index 6 index 5 -1 roll widthshow\n\t\t\tcurrentpoint\n\t\t}\n\t\t{\n\t\t\tfalse charpath currentpoint\n\t\t\t4 index setmatrix stroke\n\t\t} ifelse\n\t\tgrestore\n\t\tmoveto\n\t\t2 copy rmoveto\n\t} exch cshow\n\t6 npop\n} def\n/sp\n{\n\t{\n\t\t2 npop (0) exch\n\t\t2 copy 0 exch put pop\n\t\tfalse charpath\n\t\t2 copy rmoveto\n\t} exch cshow\n\t2 npop\n} def\n/jsp\n{\n\t{\n\t\t2 npop\n\t\t(0) exch 2 copy 0 exch put\n\t\t_sp eq\n\t\t{\n\t\t\texch 5 index 5 index 5 index 5 -1 roll widthshow\n\t\t}\n\t\t{\n\t\t\tfalse charpath\n\t\t} ifelse\n\t\t2 copy rmoveto\n\t} exch cshow\n\t5 npop\n} def\n/pl\n{\n\ttransform\n\t0.25 sub round 0.25 add exch\n\t0.25 sub round 0.25 add exch\n\titransform\n} def\n/setstrokeadjust where\n{\n\tpop true setstrokeadjust\n\t/c\n\t{\n\t\tcurveto\n\t} def\n\t/C\n\t/c load def\n\t/v\n\t{\n\t\tcurrentpoint 6 2 roll curveto\n\t} def\n\t/V\n\t/v load def\n\t/y\n\t{\n\t\t2 copy curveto\n\t} def\n\t/Y\n\t/y load def\n\t/l\n\t{\n\t\tlineto\n\t} def\n\t/L\n\t/l load def\n\t/m\n\t{\n\t\tmoveto\n\t} def\n}\n{\n\t/c\n\t{\n\t\tpl curveto\n\t} def\n\t/C\n\t/c load def\n\t/v\n\t{\n\t\tcurrentpoint 6 2 roll pl curveto\n\t} def\n\t/V\n\t/v load def\n\t/y\n\t{\n\t\tpl 2 copy curveto\n\t} def\n\t/Y\n\t/y load def\n\t/l\n\t{\n\t\tpl lineto\n\t} def\n\t/L\n\t/l load def\n\t/m\n\t{\n\t\tpl moveto\n\t} def\n} ifelse\n/d\n{\n\tsetdash\n} def\n/cf\n{\n} def\n/i\n{\n\tdup 0 eq\n\t{\n\t\tpop cf\n\t} if\n\tsetflat\n} def\n/j\n{\n\tsetlinejoin\n} def\n/J\n{\n\tsetlinecap\n} def\n/M\n{\n\tsetmiterlimit\n} def\n/w\n{\n\tsetlinewidth\n} def\n/H\n{\n} def\n/h\n{\n\tclosepath\n} def\n/N\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tclip /_doClip 0 ddef\n\t\t} if\n\t\tnewpath\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tN\n\t\t} ddef\n\t} ifelse\n} def\n/n\n{\n\tN\n} def\n/F\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tgsave _pf grestore clip newpath /_lp /none ddef _fc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\t_pf\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tF\n\t\t} ddef\n\t} ifelse\n} def\n/f\n{\n\tclosepath\n\tF\n} def\n/S\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\tgsave _ps grestore clip newpath /_lp /none ddef _sc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\t_ps\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tS\n\t\t} ddef\n\t} ifelse\n} def\n/s\n{\n\tclosepath\n\tS\n} def\n/B\n{\n\t_pola 0 eq\n\t{\n\t\t_doClip 1 eq\n\t\tgsave F grestore\n\t\t{\n\t\t\tgsave S grestore clip newpath /_lp /none ddef _sc\n\t\t\t/_doClip 0 ddef\n\t\t}\n\t\t{\n\t\t\tS\n\t\t} ifelse\n\t}\n\t{\n\t\t/CRender\n\t\t{\n\t\t\tB\n\t\t} ddef\n\t} ifelse\n} def\n/b\n{\n\tclosepath\n\tB\n} def\n/W\n{\n\t/_doClip 1 ddef\n} def\n/*\n{\n\tcount 0 ne\n\t{\n\t\tdup type /stringtype eq\n\t\t{\n\t\t\tpop\n\t\t} if\n\t} if\n\tnewpath\n} def\n/u\n{\n} def\n/U\n{\n} def\n/q\n{\n\t_pola 0 eq\n\t{\n\t\tgsave\n\t} if\n} def\n/Q\n{\n\t_pola 0 eq\n\t{\n\t\tgrestore\n\t} if\n} def\n/*u\n{\n\t_pola 1 add /_pola exch ddef\n} def\n/*U\n{\n\t_pola 1 sub /_pola exch ddef\n\t_pola 0 eq\n\t{\n\t\tCRender\n\t} if\n} def\n/D\n{\n\tpop\n} def\n/*w\n{\n} def\n/*W\n{\n} def\n/`\n{\n\t/_i save ddef\n\tclipForward?\n\t{\n\t\tnulldevice\n\t} if\n\t6 1 roll 4 npop\n\tconcat pop\n\tuserdict begin\n\t/showpage\n\t{\n\t} def\n\t0 setgray\n\t0 setlinecap\n\t1 setlinewidth\n\t0 setlinejoin\n\t10 setmiterlimit\n\t[] 0 setdash\n\t/setstrokeadjust where {pop false setstrokeadjust} if\n\tnewpath\n\t0 setgray\n\tfalse setoverprint\n} def\n/~\n{\n end\n\t_i restore\n} def\n/O\n{\n\t0 ne\n\t/_of exch ddef\n\t/_lp /none ddef\n} def\n/R\n{\n\t0 ne\n\t/_os exch ddef\n\t/_lp /none ddef\n} def\n/g\n{\n\t/_gf exch ddef\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_gf setgray\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/G\n{\n\t/_gs exch ddef\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_gs setgray\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/k\n{\n\t_cf astore pop\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_cf aload pop setcmykcolor\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/K\n{\n\t_cs astore pop\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_cs aload pop setcmykcolor\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/x\n{\n\t/_gf exch ddef\n\tfindcmykcustomcolor\n\t/_if exch ddef\n\t/_fc\n\t{\n\t\t_lp /fill ne\n\t\t{\n\t\t\t_of setoverprint\n\t\t\t_if _gf 1 exch sub setcustomcolor\n\t\t\t/_lp /fill ddef\n\t\t} if\n\t} ddef\n\t/_pf\n\t{\n\t\t_fc\n\t\tfill\n\t} ddef\n\t/_psf\n\t{\n\t\t_fc\n\t\tashow\n\t} ddef\n\t/_pjsf\n\t{\n\t\t_fc\n\t\tawidthshow\n\t} ddef\n\t/_lp /none ddef\n} def\n/X\n{\n\t/_gs exch ddef\n\tfindcmykcustomcolor\n\t/_is exch ddef\n\t/_sc\n\t{\n\t\t_lp /stroke ne\n\t\t{\n\t\t\t_os setoverprint\n\t\t\t_is _gs 1 exch sub setcustomcolor\n\t\t\t/_lp /stroke ddef\n\t\t} if\n\t} ddef\n\t/_ps\n\t{\n\t\t_sc\n\t\tstroke\n\t} ddef\n\t/_pss\n\t{\n\t\t_sc\n\t\tss\n\t} ddef\n\t/_pjss\n\t{\n\t\t_sc\n\t\tjss\n\t} ddef\n\t/_lp /none ddef\n} def\n/A\n{\n\tpop\n} def\n/annotatepage\n{\nuserdict /annotatepage 2 copy known {get exec} {pop pop} ifelse\n} def\n/discard\n{\n\tsave /discardSave exch store\n\tdiscardDict begin\n\t/endString exch store\n\tgt38?\n\t{\n\t\t2 add\n\t} if\n\tload\n\tstopped\n\tpop\n end\n\tdiscardSave restore\n} bind def\nuserdict /discardDict 7 dict dup begin\nput\n/pre38Initialize\n{\n\t/endStringLength endString length store\n\t/newBuff buffer 0 endStringLength getinterval store\n\t/newBuffButFirst newBuff 1 endStringLength 1 sub getinterval store\n\t/newBuffLast newBuff endStringLength 1 sub 1 getinterval store\n} def\n/shiftBuffer\n{\n\tnewBuff 0 newBuffButFirst putinterval\n\tnewBuffLast 0\n\tcurrentfile read not\n\t{\n\tstop\n\t} if\n\tput\n} def\n0\n{\n\tpre38Initialize\n\tmark\n\tcurrentfile newBuff readstring exch pop\n\t{\n\t\t{\n\t\t\tnewBuff endString eq\n\t\t\t{\n\t\t\t\tcleartomark stop\n\t\t\t} if\n\t\t\tshiftBuffer\n\t\t} loop\n\t}\n\t{\n\tstop\n\t} ifelse\n} def\n1\n{\n\tpre38Initialize\n\t/beginString exch store\n\tmark\n\tcurrentfile newBuff readstring exch pop\n\t{\n\t\t{\n\t\t\tnewBuff beginString eq\n\t\t\t{\n\t\t\t\t/layerCount dup load 1 add store\n\t\t\t}\n\t\t\t{\n\t\t\t\tnewBuff endString eq\n\t\t\t\t{\n\t\t\t\t\t/layerCount dup load 1 sub store\n\t\t\t\t\tlayerCount 0 eq\n\t\t\t\t\t{\n\t\t\t\t\t\tcleartomark stop\n\t\t\t\t\t} if\n\t\t\t\t} if\n\t\t\t} ifelse\n\t\t\tshiftBuffer\n\t\t} loop\n\t}\n\t{\n\tstop\n\t} ifelse\n} def\n2\n{\n\tmark\n\t{\n\t\tcurrentfile buffer readline not\n\t\t{\n\t\tstop\n\t\t} if\n\t\tendString eq\n\t\t{\n\t\t\tcleartomark stop\n\t\t} if\n\t} loop\n} def\n3\n{\n\t/beginString exch store\n\t/layerCnt 1 store\n\tmark\n\t{\n\t\tcurrentfile buffer readline not\n\t\t{\n\t\tstop\n\t\t} if\n\t\tdup beginString eq\n\t\t{\n\t\t\tpop /layerCnt dup load 1 add store\n\t\t}\n\t\t{\n\t\t\tendString eq\n\t\t\t{\n\t\t\t\tlayerCnt 1 eq\n\t\t\t\t{\n\t\t\t\t\tcleartomark stop\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\t/layerCnt dup load 1 sub store\n\t\t\t\t} ifelse\n\t\t\t} if\n\t\t} ifelse\n\t} loop\n} def\nend\nuserdict /clipRenderOff 15 dict dup begin\nput\n{\n\t/n /N /s /S /f /F /b /B\n}\n{\n\t{\n\t\t_doClip 1 eq\n\t\t{\n\t\t\t/_doClip 0 ddef clip\n\t\t} if\n\t\tnewpath\n\t} def\n} forall\n/Tr /pop load def\n/Bb {} def\n/BB /pop load def\n/Bg {12 npop} def\n/Bm {6 npop} def\n/Bc /Bm load def\n/Bh {4 npop} def\nend\n/Lb\n{\n\t4 npop\n\t6 1 roll\n\tpop\n\t4 1 roll\n\tpop pop pop\n\t0 eq\n\t{\n\t\t0 eq\n\t\t{\n\t\t\t(%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard\n\t\t}\n\t\t{\n\t\t\t/clipForward? true def\n\n\t\t\t/Tx /pop load def\n\t\t\t/Tj /pop load def\n\t\t\tcurrentdict end clipRenderOff begin begin\n\t\t} ifelse\n\t}\n\t{\n\t\t0 eq\n\t\t{\n\t\t\tsave /discardSave exch store\n\t\t} if\n\t} ifelse\n} bind def\n/LB\n{\n\tdiscardSave dup null ne\n\t{\n\t\trestore\n\t}\n\t{\n\t\tpop\n\t\tclipForward?\n\t\t{\n\t\t\tcurrentdict\n\t\t end\n\t\t end\n\t\t begin\n\n\t\t\t/clipForward? false ddef\n\t\t} if\n\t} ifelse\n} bind def\n/Pb\n{\n\tpop pop\n\t0 (%AI5_EndPalette) discard\n} bind def\n/Np\n{\n\t0 (%AI5_End_NonPrinting--) discard\n} bind def\n/Ln /pop load def\n/Ap\n/pop load def\n/Ar\n{\n\t72 exch div\n\t0 dtransform dup mul exch dup mul add sqrt\n\tdup 1 lt\n\t{\n\t\tpop 1\n\t} if\n\tsetflat\n} def\n/Mb\n{\n\tq\n} def\n/Md\n{\n} def\n/MB\n{\n\tQ\n} def\n/nc 3 dict def\nnc begin\n/setgray\n{\n\tpop\n} bind def\n/setcmykcolor\n{\n\t4 npop\n} bind def\n/setcustomcolor\n{\n\t2 npop\n} bind def\ncurrentdict readonly pop\nend\ncurrentdict readonly pop\nend\nsetpacking\n%%EndResource\n%%EndProlog\n%%BeginSetup\nAdobe_level2_AI5 /initialize get exec\nAdobe_IllustratorA_AI5 /initialize get exec\n%AI5_Begin_NonPrinting\nNp\n%AI3_BeginPattern: (Yellow Stripe)\n(Yellow Stripe) 8.4499 4.6 80.4499 76.6 [\n%AI3_Tile\n(0 O 0 R 0 0.4 1 0 k 0 0.4 1 0 K) @\n(\n800 Ar\n0 J 0 j 3.6 w 4 M []0 d\n%AI3_Note:\n0 D\n8.1999 8.1999 m\n80.6999 8.1999 L\nS\n8.1999 22.6 m\n80.6999 22.6 L\nS\n8.1999 37.0001 m\n80.6999 37.0001 L\nS\n8.1999 51.3999 m\n80.6999 51.3999 L\nS\n8.1999 65.8 m\n80.6999 65.8 L\nS\n8.1999 15.3999 m\n80.6999 15.3999 L\nS\n8.1999 29.8 m\n80.6999 29.8 L\nS\n8.1999 44.1999 m\n80.6999 44.1999 L\nS\n8.1999 58.6 m\n80.6999 58.6 L\nS\n8.1999 73.0001 m\n80.6999 73.0001 L\nS\n) &\n] E\n%AI3_EndPattern\n%AI5_End_NonPrinting--\n%AI5_Begin_NonPrinting\nNp\n3 Bn\n%AI5_BeginGradient: (Black & White)\n(Black & White) 0 2 Bd\n[\n<\nFFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8\nD7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0\nAFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A8988\n87868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160\n5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A3938\n37363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A19181716151413121110\n0F0E0D0C0B0A09080706050403020100\n>\n0 %_Br\n[\n0 0 50 100 %_Bs\n1 0 50 0 %_Bs\nBD\n%AI5_EndGradient\n%AI5_BeginGradient: (Red & Yellow)\n(Red & Yellow) 0 2 Bd\n[\n0\n<\n000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627\n28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F\n505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677\n78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\nA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nC8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF\nF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\n>\n<\nFFFFFEFEFDFDFDFCFCFBFBFBFAFAF9F9F9F8F8F7F7F7F6F6F5F5F5F4F4F3F3F3F2F2F1F1F1F0F0EF\nEFEFEEEEEDEDEDECECEBEBEBEAEAE9E9E9E8E8E7E7E7E6E6E5E5E5E4E4E3E3E3E2E2E1E1E1E0E0DF\nDFDFDEDEDDDDDDDCDCDBDBDBDADAD9D9D9D8D8D7D7D7D6D6D5D5D5D4D4D3D3D3D2D2D1D1D1D0D0CF\nCFCFCECECDCDCDCCCCCBCBCBCACAC9C9C9C8C8C7C7C7C6C6C5C5C5C4C4C3C3C3C2C2C1C1C1C0C0BF\nBFBFBEBEBDBDBDBCBCBBBBBBBABAB9B9B9B8B8B7B7B7B6B6B5B5B5B4B4B3B3B3B2B2B1B1B1B0B0AF\nAFAFAEAEADADADACACABABABAAAAA9A9A9A8A8A7A7A7A6A6A5A5A5A4A4A3A3A3A2A2A1A1A1A0A09F\n9F9F9E9E9D9D9D9C9C9B9B9B9A9A9999\n>\n0\n1 %_Br\n[\n0 1 0.6 0 1 50 100 %_Bs\n0 0 1 0 1 50 0 %_Bs\nBD\n%AI5_EndGradient\n%AI5_BeginGradient: (Yellow & Blue Radial)\n(Yellow & Blue Radial) 1 2 Bd\n[\n<\n000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627\n28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F\n505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677\n78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\nA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7\nC8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF\nF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\n>\n<\n1415161718191A1B1C1D1E1F1F202122232425262728292A2A2B2C2D2E2F30313233343536363738\n393A3B3C3D3E3F40414142434445464748494A4B4C4D4D4E4F50515253545556575858595A5B5C5D\n5E5F60616263646465666768696A6B6C6D6E6F6F707172737475767778797A7B7B7C7D7E7F808182\n83848586868788898A8B8C8D8E8F90919292939495969798999A9B9C9D9D9E9FA0A1A2A3A4A5A6A7\nA8A9A9AAABACADAEAFB0B1B2B3B4B4B5B6B7B8B9BABBBCBDBEBFC0C0C1C2C3C4C5C6C7C8C9CACBCB\nCCCDCECFD0D1D2D3D4D5D6D7D7D8D9DADBDCDDDEDFE0E1E2E2E3E4E5E6E7E8E9EAEBECEDEEEEEFF0\nF1F2F3F4F5F6F7F8F9F9FAFBFCFDFEFF\n>\n<\nABAAAAA9A8A7A7A6A5A5A4A3A3A2A1A1A09F9F9E9D9D9C9B9B9A9999989797969595949393929191\n908F8F8E8D8D8C8B8B8A8989888787868585848383828181807F7F7E7D7D7C7B7B7A797978777776\n7575747373727171706F6F6E6D6D6C6B6B6A6969686767666565646362626160605F5E5E5D5C5C5B\n5A5A5958585756565554545352525150504F4E4E4D4C4C4B4A4A4948484746464544444342424140\n403F3E3E3D3C3C3B3A3A3938383736363534343332323130302F2E2E2D2C2C2B2A2A292828272626\n25242423222121201F1F1E1D1D1C1B1B1A1919181717161515141313121111100F0F0E0D0D0C0B0B\n0A090908070706050504030302010100\n>\n0\n1 %_Br\n[\n0 0.08 0.67 0 1 50 14 %_Bs\n1 1 0 0 1 50 100 %_Bs\nBD\n%AI5_EndGradient\n%AI5_End_NonPrinting--\n%AI5_BeginPalette\n144 161 Pb\nPn\nPc\n1 g\nPc\n0 g\nPc\n0 0 0 0 k\nPc\n0.75 g\nPc\n0.5 g\nPc\n0.25 g\nPc\n0 g\nPc\nBb\n2 (Black & White) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0.25 0 0 0 k\nPc\n0.5 0 0 0 k\nPc\n0.75 0 0 0 k\nPc\n1 0 0 0 k\nPc\n0.25 0.25 0 0 k\nPc\n0.5 0.5 0 0 k\nPc\n0.75 0.75 0 0 k\nPc\n1 1 0 0 k\nPc\nBb\n2 (Red & Yellow) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0 0.25 0 0 k\nPc\n0 0.5 0 0 k\nPc\n0 0.75 0 0 k\nPc\n0 1 0 0 k\nPc\n0 0.25 0.25 0 k\nPc\n0 0.5 0.5 0 k\nPc\n0 0.75 0.75 0 k\nPc\n0 1 1 0 k\nPc\nBb\n0 0 0 0 Bh\n2 (Yellow & Blue Radial) -4014 4716 0 0 1 0 0 1 0 0 Bg\n0 BB\nPc\n0 0 0.25 0 k\nPc\n0 0 0.5 0 k\nPc\n0 0 0.75 0 k\nPc\n0 0 1 0 k\nPc\n0.25 0 0.25 0 k\nPc\n0.5 0 0.5 0 k\nPc\n0.75 0 0.75 0 k\nPc\n1 0 1 0 k\nPc\n(Yellow Stripe) 0 0 1 1 0 0 0 0 0 [1 0 0 1 0 0] p\nPc\n0.25 0.125 0 0 k\nPc\n0.5 0.25 0 0 k\nPc\n0.75 0.375 0 0 k\nPc\n1 0.5 0 0 k\nPc\n0.125 0.25 0 0 k\nPc\n0.25 0.5 0 0 k\nPc\n0.375 0.75 0 0 k\nPc\n0.5 1 0 0 k\nPc\n0.375 0.375 0.75 0 k\nPc\n0 0.25 0.125 0 k\nPc\n0 0.5 0.25 0 k\nPc\n0 0.75 0.375 0 k\nPc\n0 1 0.5 0 k\nPc\n0 0.125 0.25 0 k\nPc\n0 0.25 0.5 0 k\nPc\n0 0.375 0.75 0 k\nPc\n0 0.5 1 0 k\nPc\n0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x\nPc\n0.125 0 0.25 0 k\nPc\n0.25 0 0.5 0 k\nPc\n0.375 0 0.75 0 k\nPc\n0.5 0 1 0 k\nPc\n0.25 0 0.125 0 k\nPc\n0.5 0 0.25 0 k\nPc\n0.75 0 0.375 0 k\nPc\n1 0 0.5 0 k\nPc\n0.5 1 0 0 k\nPc\n0.25 0.125 0.125 0 k\nPc\n0.5 0.25 0.25 0 k\nPc\n0.75 0.375 0.375 0 k\nPc\n1 0.5 0.5 0 k\nPc\n0.25 0.25 0.125 0 k\nPc\n0.5 0.5 0.25 0 k\nPc\n0.75 0.75 0.375 0 k\nPc\n1 1 0.5 0 k\nPc\n0 1 0.5 0 k\nPc\n0.125 0.25 0.125 0 k\nPc\n0.25 0.5 0.25 0 k\nPc\n0.375 0.75 0.375 0 k\nPc\n0.5 1 0.5 0 k\nPc\n0.125 0.25 0.25 0 k\nPc\n0.25 0.5 0.5 0 k\nPc\n0.375 0.75 0.75 0 k\nPc\n0.5 1 1 0 k\nPc\n0.75 0.75 0.375 0 k\nPc\n0.125 0.125 0.25 0 k\nPc\n0.25 0.25 0.5 0 k\nPc\n0.375 0.375 0.75 0 k\nPc\n0.5 0.5 1 0 k\nPc\n0.25 0.125 0.25 0 k\nPc\n0.5 0.25 0.5 0 k\nPc\n0.75 0.375 0.75 0 k\nPc\n1 0.5 1 0 k\nPc\n0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0.5 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.25 1 0 (Orange Yellow) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 1 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0 0.5 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.45 1 0 (Orange) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0.375 0.375 0.75 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0.79 0.91 0 (PANTONE Warm Red CV) 0 x\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n1 0.65 0 0 k\nPc\n0 0 0 0 k\nPc\nPc\nPc\nPc\nPc\nPc\nPc\nPc\n0 0 1 0 k\nPc\nPB\n%AI5_EndPalette\n%%EndSetup\n%AI5_BeginLayer\n1 1 1 1 0 0 0 79 128 255 Lb\n(Layer 1) Ln\n0 A\n1 Ap\n0 O\n1 0.65 0 0 k\n800 Ar\n0 J 0 j 1 w 4 M []0 d\n%AI3_Note:\n0 D\n285.0121 311.7976 m\n357.5043 302.5199 L\n361.6071 392.7105 L\n376.3322 474.1377 L\n342.6527 475.6628 L\n327.6333 483.4165 L\n258.8269 486.3189 L\n254.4361 405.0427 L\n242.0523 312.2099 L\n285.0121 311.7976 L\nf\n0 0.79 0.91 0 k\n1.25 w\n295.4466 337.6172 m\n368.4943 335.3343 L\n363.9288 425.5026 L\n370.7771 507.9667 L\n337.1066 506.2547 L\n321.4128 512.5323 L\n252.6452 508.8228 L\n256.0692 427.5002 L\n252.6452 333.9077 L\n295.4466 337.6172 L\nf\nu\n0 Ap\n1 0.65 0 0 k\n1 w\n320.532 390.6149 m\n312.9017 388.534 l\n317.0637 398.5921 l\n321.2256 426.6854 l\n316.0232 427.7258 l\n322.2662 436.3965 l\n330.0436 465.6249 l\n316.3701 462.7557 l\n323.5798 475.9563 331.2311 484.5534 v\n321.2256 492.2363 l\n288.9913 478.0373 297.6622 431.9088 v\n290.9988 433.0755 l\n297.3888 384.7188 l\n291.9867 383.3315 l\n297.5214 372.0383 305.2714 366.6837 v\n305.9749 366.1976 295.5601 404.4882 306.6587 442.6395 c\n307.6992 440.2117 l\n298.855 399.5459 307.6992 366.6837 v\n308.1064 365.9033 312.5286 366.4235 v\n320.532 381.5106 320.532 390.6149 v\nf\nu\n*u\n1 g\n263.6948 355.9856 m\n265.2612 355.9856 L\n265.2612 359.2513 L\n265.9515 359.2513 266.6153 359.2513 267.2791 359.3575 c\n267.2791 355.9856 L\n269.6155 355.9856 L\n269.6155 355.3749 L\n267.2791 355.3749 L\n267.2791 347.2505 L\n267.2791 346.7726 267.2791 346.0558 268.288 346.0558 c\n268.9783 346.0558 269.35 346.5337 269.7748 347.0381 c\n270.1996 346.7461 L\n269.6951 345.7372 268.3942 345.1265 267.3322 345.1265 c\n265.4205 345.1265 265.2081 346.162 265.2081 347.4364 c\n265.2081 355.3749 L\n263.6948 355.3749 L\n263.6948 355.9856 l\nf\n*U\n*u\n285.7796 348.7639 m\n285.1689 346.8788 284.1069 345.2327 281.3457 345.1265 c\n277.2304 345.1265 275.9825 348.5515 275.9825 350.3835 c\n275.9825 355.1094 279.7792 356.2511 281.2926 356.2511 c\n283.0184 356.2511 285.461 355.4546 285.461 353.4102 c\n285.461 352.6934 285.0096 352.003 284.2662 352.003 c\n283.5494 352.003 283.0184 352.481 283.0184 353.2509 c\n283.0184 354.2864 283.868 354.4191 283.868 354.7112 c\n283.868 355.428 282.1953 355.7201 281.6112 355.7201 c\n279.0624 355.7201 278.3986 353.8616 278.3986 350.3835 c\n278.3986 348.7905 278.7969 347.5691 278.9562 347.1974 c\n279.3544 346.3213 280.1775 345.7637 281.5581 345.6841 c\n283.098 345.6044 284.5848 346.8523 285.222 348.7639 C\n285.7796 348.7639 l\nf\n*U\n*u\n291.9344 345.4717 m\n291.9344 346.0823 L\n293.9788 346.0823 L\n293.9788 363.1542 L\n291.9344 363.1542 L\n291.9344 363.7648 L\n293.0761 363.7648 L\n294.0585 363.7648 295.0939 363.8179 296.0497 364.0038 c\n296.0497 346.0823 L\n298.0941 346.0823 L\n298.0941 345.4717 L\n291.9344 345.4717 l\nf\n*U\nu\n310.0634 446.075 m\n305.3828 425.2059 306.7298 391.3708 v\n307.1338 381.222 308.2436 371.8929 309.5993 363.8029 C\n309.6066 363.8025 L\n310.4883 356.6987 311.0781 354.1272 313.3768 345.5676 C\n313.2426 340.0473 L\n294.8367 398.8155 310.0634 446.075 V\nf\n321.3622 464.1699 m\n325.5016 466.2317 331.4359 466.9819 v\n337.9224 455.0924 321.9584 434.793 v\n331.4821 456.0522 329.2358 462.7122 v\n326.7243 464.2727 321.3622 464.1699 v\nf\n319.4002 428.4819 m\n323.1177 427.6214 324.9024 429.0668 v\n321.386 415.3445 322.3077 407.7964 v\n323.2297 400.2483 316.5788 395.4159 y\n322.2441 402.584 320.4635 408.4226 v\n319.2289 412.4694 320.6101 422.8271 322.1681 426.1155 c\n320.7131 426.3196 319.4002 428.4819 v\nf\n315.7246 392.3281 m\n321.8677 393.0631 322.5131 396.1662 v\n323.265 377.6058 314.7299 369.9571 v\n321.2425 380.1152 320.2206 390.6235 v\n315.7246 392.3281 l\nf\n298.4445 384.6023 m\n296.4635 382.3836 290.5192 387.2778 v\n292.4131 374.803 304.1781 369.0924 v\n296.0814 375.1928 293.9 381.7824 v\n296.7611 382.6245 298.4445 384.6023 v\nf\n296.5483 389.3335 m\n288.5102 409.7356 290.2325 437.3036 v\n292.1098 432.3112 298.1424 430.5604 v\n295.3003 429.9794 293.6387 430.2313 v\n289.4335 418.5932 296.5483 389.3335 v\nf\n330.3126 484.1353 m\n327.3003 506.2722 308.4549 483.8853 v\n293.4491 466.0592 295.2373 450.9247 296.1578 442.4811 c\n296.3932 440.3206 293.366 465.0316 309.8067 481.2933 c\n326.2471 497.5553 329.9609 485.0794 330.3126 484.1353 c\nf\nU\n0 0 1 0 k\n302.5528 503.0164 m\n287.7656 507.2395 283.0593 458.227 v\n279.4282 473.3549 288.8204 494.7509 v\n298.2122 516.1468 302.5528 503.0164 y\nf\n284.2076 506.5994 m\n276.6655 495.2557 278.3767 483.1729 v\n272.6565 505.9183 284.2076 506.5994 v\nf\n339.7135 474.7902 m\n348.6321 478.0799 335.8615 444.8834 v\n342.4718 454.5848 346.6326 469.8253 v\n349.303 479.6062 339.7135 474.7902 y\nf\n354.1382 477.3767 m\n360.4435 471.669 355.9752 464.1187 v\n367.1908 475.904 354.1382 477.3767 v\nf\nU\nU\n*u\n1 g\n258.2029 317.4593 m\n256.6821 317.4593 L\n256.6821 325.2598 L\n258.7512 325.2598 L\n260.3858 325.2598 261.4514 324.608 261.4514 322.839 c\n261.4514 321.1837 260.5513 320.3767 258.9581 320.3767 c\n258.2029 320.3767 L\n258.2029 317.4593 l\nf\n1 D\n258.2029 321.6389 m\n258.5132 321.6389 L\n259.4133 321.6389 259.8995 321.8354 259.8995 322.8493 c\n259.8995 323.8528 259.3202 323.9976 258.4719 323.9976 c\n258.2029 323.9976 L\n258.2029 321.6389 l\nf\n*U\n*u\n0 D\n269.0694 321.3699 m\n269.0694 323.5528 270.6523 325.4667 272.9283 325.4667 c\n275.2043 325.4667 276.7871 323.5528 276.7871 321.3699 c\n276.7871 319.1353 275.2043 317.2524 272.9283 317.2524 c\n270.6523 317.2524 269.0694 319.1353 269.0694 321.3699 c\nf\n1 D\n270.6419 321.432 m\n270.6419 320.2526 271.6351 318.7525 272.9283 318.7525 c\n274.2215 318.7525 275.2146 320.2526 275.2146 321.432 c\n275.2146 322.6941 274.2628 323.9666 272.9283 323.9666 c\n271.5937 323.9666 270.6419 322.6941 270.6419 321.432 c\nf\n*U\n*u\n0 D\n287.2943 319.9422 m\n287.315 319.9422 L\n288.8668 325.3632 L\n289.7668 325.3632 L\n291.3807 319.9422 L\n291.4014 319.9422 L\n292.9326 325.2598 L\n294.5258 325.2598 L\n291.8877 317.3041 L\n290.7704 317.3041 L\n289.2185 322.4044 L\n289.1978 322.4044 L\n287.7288 317.3041 L\n286.6115 317.3041 L\n284.1286 325.2598 L\n285.7218 325.2598 L\n287.2943 319.9422 l\nf\n*U\n*u\n303.7595 323.9356 m\n303.7595 322.2182 L\n306.1803 322.2182 L\n306.1803 320.894 L\n303.7595 320.894 L\n303.7595 318.7835 L\n306.2734 318.7835 L\n306.2734 317.4593 L\n302.2387 317.4593 L\n302.2387 325.2598 L\n306.2734 325.2598 L\n306.2734 323.9356 L\n303.7595 323.9356 l\nf\n*U\n*u\n319.8602 317.4593 m\n318.0187 317.4593 L\n316.1255 320.6043 L\n316.1048 320.6043 L\n316.1048 317.4593 L\n314.5841 317.4593 L\n314.5841 325.2598 L\n316.6428 325.2598 L\n318.1843 325.2598 319.2499 324.577 319.2499 322.9114 c\n319.2499 321.9182 318.7015 320.925 317.6567 320.7492 C\n319.8602 317.4593 l\nf\n1 D\n316.1048 321.6699 m\n316.3014 321.6699 L\n317.1394 321.6699 317.7291 321.9182 317.7291 322.87 c\n317.7291 323.8321 317.1187 324.0183 316.3117 324.0183 c\n316.1048 324.0183 L\n316.1048 321.6699 l\nf\n*U\n*u\n0 D\n329.1754 323.9356 m\n329.1754 322.2182 L\n331.5962 322.2182 L\n331.5962 320.894 L\n329.1754 320.894 L\n329.1754 318.7835 L\n331.6894 318.7835 L\n331.6894 317.4593 L\n327.6546 317.4593 L\n327.6546 325.2598 L\n331.6894 325.2598 L\n331.6894 323.9356 L\n329.1754 323.9356 l\nf\n*U\n*u\n340 325.2598 m\n342.1725 325.2598 L\n344.4279 325.2598 345.9383 323.5735 345.9383 321.3492 c\n345.9383 319.156 344.3865 317.4593 342.1622 317.4593 c\n340 317.4593 L\n340 325.2598 l\nf\n1 D\n341.5208 318.7835 m\n341.7691 318.7835 L\n343.6416 318.7835 344.3658 319.8181 344.3658 321.3596 c\n344.3658 323.0562 343.4968 323.9356 341.7691 323.9356 c\n341.5208 323.9356 L\n341.5208 318.7835 l\nf\n*U\nLB\n%AI5_EndLayer--\n%%PageTrailer\ngsave annotatepage grestore showpage\n%%Trailer\nAdobe_IllustratorA_AI5 /terminate get exec\nAdobe_level2_AI5 /terminate get exec\n%%EOF\n"
  },
  {
    "path": "library/listbox.tcl",
    "content": "# listbox.tcl --\n#\n# This file defines the default bindings for Tk listbox widgets\n# and provides procedures that help in implementing those bindings.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998 Scriptics Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n#--------------------------------------------------------------------------\n# tk::Priv elements used in this file:\n#\n# afterId -\t\tToken returned by \"after\" for autoscanning.\n# listboxPrev -\t\tThe last element to be selected or deselected\n#\t\t\tduring a selection operation.\n# listboxSelection -\tAll of the items that were selected before the\n#\t\t\tcurrent selection operation (such as a mouse\n#\t\t\tdrag) started;  used to cancel an operation.\n#--------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for listboxes.\n#-------------------------------------------------------------------------\n\n# Note: the check for existence of %W below is because this binding\n# is sometimes invoked after a window has been deleted (e.g. because\n# there is a double-click binding on the widget that deletes it).  Users\n# can put \"break\"s in their bindings to avoid the error, but this check\n# makes that unnecessary.\n\nbind Listbox <Button-1> {\n    if {[winfo exists %W]} {\n\ttk::ListboxBeginSelect %W [%W index @%x,%y] 1\n    }\n}\n\n# Ignore double clicks so that users can define their own behaviors.\n# Among other things, this prevents errors if the user deletes the\n# listbox on a double click.\n\nbind Listbox <Double-Button-1> {\n    # Empty script\n}\n\nbind Listbox <B1-Motion> {\n    set tk::Priv(x) %x\n    set tk::Priv(y) %y\n    tk::ListboxMotion %W [%W index @%x,%y]\n}\nbind Listbox <ButtonRelease-1> {\n    tk::CancelRepeat\n    %W activate @%x,%y\n}\nbind Listbox <Shift-Button-1> {\n    tk::ListboxBeginExtend %W [%W index @%x,%y]\n}\nbind Listbox <Control-Button-1> {\n    tk::ListboxBeginToggle %W [%W index @%x,%y]\n}\nbind Listbox <B1-Leave> {\n    set tk::Priv(x) %x\n    set tk::Priv(y) %y\n    tk::ListboxAutoScan %W\n}\nbind Listbox <B1-Enter> {\n    tk::CancelRepeat\n}\n\nbind Listbox <<PrevLine>> {\n    tk::ListboxUpDown %W -1\n}\nbind Listbox <<SelectPrevLine>> {\n    tk::ListboxExtendUpDown %W -1\n}\nbind Listbox <<NextLine>> {\n    tk::ListboxUpDown %W 1\n}\nbind Listbox <<SelectNextLine>> {\n    tk::ListboxExtendUpDown %W 1\n}\nbind Listbox <<PrevChar>> {\n    %W xview scroll -1 units\n}\nbind Listbox <<PrevWord>> {\n    %W xview scroll -1 pages\n}\nbind Listbox <<NextChar>> {\n    %W xview scroll 1 units\n}\nbind Listbox <<NextWord>> {\n    %W xview scroll 1 pages\n}\nbind Listbox <Prior> {\n    %W yview scroll -1 pages\n    %W activate @0,0\n}\nbind Listbox <Next> {\n    %W yview scroll 1 pages\n    %W activate @0,0\n}\nbind Listbox <Control-Prior> {\n    %W xview scroll -1 pages\n}\nbind Listbox <Control-Next> {\n    %W xview scroll 1 pages\n}\nbind Listbox <<LineStart>> {\n    %W xview moveto 0\n}\nbind Listbox <<LineEnd>> {\n    %W xview moveto 1\n}\nbind Listbox <Control-Home> {\n    %W activate 0\n    %W see 0\n    %W selection clear 0 end\n    %W selection set 0\n    tk::FireListboxSelectEvent %W\n}\nbind Listbox <Control-Shift-Home> {\n    tk::ListboxDataExtend %W 0\n}\nbind Listbox <Control-End> {\n    %W activate end\n    %W see end\n    %W selection clear 0 end\n    %W selection set end\n    tk::FireListboxSelectEvent %W\n}\nbind Listbox <Control-Shift-End> {\n    tk::ListboxDataExtend %W [%W index end]\n}\nbind Listbox <<Copy>> {\n    if {[selection own -displayof %W] eq \"%W\"} {\n\tclipboard clear -displayof %W\n\tclipboard append -displayof %W [selection get -displayof %W]\n    }\n}\nbind Listbox <space> {\n    tk::ListboxBeginSelect %W [%W index active]\n}\nbind Listbox <<Invoke>> {\n    tk::ListboxBeginSelect %W [%W index active]\n}\nbind Listbox <Select> {\n    tk::ListboxBeginSelect %W [%W index active]\n}\nbind Listbox <Control-Shift-space> {\n    tk::ListboxBeginExtend %W [%W index active]\n}\nbind Listbox <Shift-Select> {\n    tk::ListboxBeginExtend %W [%W index active]\n}\nbind Listbox <Escape> {\n    tk::ListboxCancel %W\n}\nbind Listbox <<SelectAll>> {\n    tk::ListboxSelectAll %W\n}\nbind Listbox <<SelectNone>> {\n    if {[%W cget -selectmode] ne \"browse\"} {\n\t%W selection clear 0 end\n\ttk::FireListboxSelectEvent %W\n    }\n}\n\n# Additional Tk bindings that aren't part of the Motif look and feel:\n\nbind Listbox <Button-2> {\n    %W scan mark %x %y\n}\nbind Listbox <B2-Motion> {\n    %W scan dragto %x %y\n}\nbind Listbox <MouseWheel> {\n    tk::MouseWheel %W y %D -40.0 units\n}\nbind Listbox <Option-MouseWheel> {\n    tk::MouseWheel %W y %D -12.0 units\n}\nbind Listbox <Shift-MouseWheel> {\n    tk::MouseWheel %W x %D -40.0 units\n}\nbind Listbox <Shift-Option-MouseWheel> {\n    tk::MouseWheel %W x %D -12.0 units\n}\nbind Listbox <TouchpadScroll> {\n    if {%# %% 5 == 0} {\n\tlassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n\tif {$tk::Priv(deltaX) != 0} {\n\t    %W xview scroll [expr {-$tk::Priv(deltaX)}] units\n\t}\n\tif {$tk::Priv(deltaY) != 0} {\n\t    %W yview scroll [expr {-$tk::Priv(deltaY)}] units\n\t}\n    }\n}\n\n# ::tk::ListboxBeginSelect --\n#\n# This procedure is typically invoked on button-1 presses.  It begins\n# the process of making a selection in the listbox.  Its exact behavior\n# depends on the selection mode currently in effect for the listbox;\n# see the Motif documentation for details.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# el -\t\tThe element for the selection operation (typically the\n#\t\tone under the pointer).  Must be in numerical form.\n\nproc ::tk::ListboxBeginSelect {w el {focus 1}} {\n    variable ::tk::Priv\n    if {[$w cget -selectmode] eq \"multiple\"} {\n\tif {[$w selection includes $el]} {\n\t    $w selection clear $el\n\t} else {\n\t    $w selection set $el\n\t}\n    } else {\n\t$w selection clear 0 end\n\t$w selection set $el\n\t$w selection anchor $el\n\tset Priv(listboxSelection) {}\n\tset Priv(listboxPrev) $el\n    }\n    tk::FireListboxSelectEvent $w\n    # check existence as ListboxSelect may destroy us\n    if {$focus && [winfo exists $w] && [$w cget -state] eq \"normal\"} {\n\tfocus $w\n    }\n}\n\n# ::tk::ListboxMotion --\n#\n# This procedure is called to process mouse motion events while\n# button 1 is down.  It may move or extend the selection, depending\n# on the listbox's selection mode.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# el -\t\tThe element under the pointer (must be a number).\n\nproc ::tk::ListboxMotion {w el} {\n    variable ::tk::Priv\n    if {$el == $Priv(listboxPrev)} {\n\treturn\n    }\n    set anchor [$w index anchor]\n    switch [$w cget -selectmode] {\n\tbrowse {\n\t    $w selection clear 0 end\n\t    $w selection set $el\n\t    set Priv(listboxPrev) $el\n\t    tk::FireListboxSelectEvent $w\n\t}\n\textended {\n\t    set i $Priv(listboxPrev)\n\t    if {$i < 0} {\n\t\tset i $el\n\t\t$w selection set $el\n\t    }\n\t    if {[$w selection includes anchor]} {\n\t\t$w selection clear $i $el\n\t\t$w selection set anchor $el\n\t    } else {\n\t\t$w selection clear $i $el\n\t\t$w selection clear anchor $el\n\t    }\n\t    if {![info exists Priv(listboxSelection)]} {\n\t\tset Priv(listboxSelection) [$w curselection]\n\t    }\n\t    while {($i < $el) && ($i < $anchor)} {\n\t\tif {$i in $Priv(listboxSelection)} {\n\t\t    $w selection set $i\n\t\t}\n\t\tincr i\n\t    }\n\t    while {($i > $el) && ($i > $anchor)} {\n\t\tif {$i in $Priv(listboxSelection)} {\n\t\t    $w selection set $i\n\t\t}\n\t\tincr i -1\n\t    }\n\t    set Priv(listboxPrev) $el\n\t    tk::FireListboxSelectEvent $w\n\t}\n    }\n}\n\n# ::tk::ListboxBeginExtend --\n#\n# This procedure is typically invoked on shift-button-1 presses.  It\n# begins the process of extending a selection in the listbox.  Its\n# exact behavior depends on the selection mode currently in effect\n# for the listbox;  see the Motif documentation for details.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# el -\t\tThe element for the selection operation (typically the\n#\t\tone under the pointer).  Must be in numerical form.\n\nproc ::tk::ListboxBeginExtend {w el} {\n    if {[$w cget -selectmode] eq \"extended\"} {\n\tif {[$w selection includes anchor]} {\n\t    ListboxMotion $w $el\n\t} else {\n\t    # No selection yet; simulate the begin-select operation.\n\t    ListboxBeginSelect $w $el\n\t}\n    }\n}\n\n# ::tk::ListboxBeginToggle --\n#\n# This procedure is typically invoked on control-button-1 presses.  It\n# begins the process of toggling a selection in the listbox.  Its\n# exact behavior depends on the selection mode currently in effect\n# for the listbox;  see the Motif documentation for details.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# el -\t\tThe element for the selection operation (typically the\n#\t\tone under the pointer).  Must be in numerical form.\n\nproc ::tk::ListboxBeginToggle {w el} {\n    variable ::tk::Priv\n    if {[$w cget -selectmode] eq \"extended\"} {\n\tset Priv(listboxSelection) [$w curselection]\n\tset Priv(listboxPrev) $el\n\t$w selection anchor $el\n\tif {[$w selection includes $el]} {\n\t    $w selection clear $el\n\t} else {\n\t    $w selection set $el\n\t}\n\ttk::FireListboxSelectEvent $w\n    }\n}\n\n# ::tk::ListboxAutoScan --\n# This procedure is invoked when the mouse leaves an entry window\n# with button 1 down.  It scrolls the window up, down, left, or\n# right, depending on where the mouse left the window, and reschedules\n# itself as an \"after\" command so that the window continues to scroll until\n# the mouse moves back into the window or the mouse button is released.\n#\n# Arguments:\n# w -\t\tThe entry window.\n\nproc ::tk::ListboxAutoScan {w} {\n    variable ::tk::Priv\n    if {![winfo exists $w]} return\n    set x $Priv(x)\n    set y $Priv(y)\n    if {$y >= [winfo height $w]} {\n\t$w yview scroll 1 units\n    } elseif {$y < 0} {\n\t$w yview scroll -1 units\n    } elseif {$x >= [winfo width $w]} {\n\t$w xview scroll 2 units\n    } elseif {$x < 0} {\n\t$w xview scroll -2 units\n    } else {\n\treturn\n    }\n    ListboxMotion $w [$w index @$x,$y]\n    set Priv(afterId) [after 50 [list tk::ListboxAutoScan $w]]\n}\n\n# ::tk::ListboxUpDown --\n#\n# Moves the location cursor (active element) up or down by one element,\n# and changes the selection if we're in browse or extended selection\n# mode.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# amount -\t+1 to move down one item, -1 to move back one item.\n\nproc ::tk::ListboxUpDown {w amount} {\n    variable ::tk::Priv\n    $w activate [expr {[$w index active] + $amount}]\n    $w see active\n    switch [$w cget -selectmode] {\n\tbrowse {\n\t    $w selection clear 0 end\n\t    $w selection set active\n\t    tk::FireListboxSelectEvent $w\n\t}\n\textended {\n\t    $w selection clear 0 end\n\t    $w selection set active\n\t    $w selection anchor active\n\t    set Priv(listboxPrev) [$w index active]\n\t    set Priv(listboxSelection) {}\n\t    tk::FireListboxSelectEvent $w\n\t}\n    }\n}\n\n# ::tk::ListboxExtendUpDown --\n#\n# Does nothing unless we're in extended selection mode;  in this\n# case it moves the location cursor (active element) up or down by\n# one element, and extends the selection to that point.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# amount -\t+1 to move down one item, -1 to move back one item.\n\nproc ::tk::ListboxExtendUpDown {w amount} {\n    variable ::tk::Priv\n    if {[$w cget -selectmode] ne \"extended\"} {\n\treturn\n    }\n    set active [$w index active]\n    if {![info exists Priv(listboxSelection)]} {\n\t$w selection set $active\n\tset Priv(listboxSelection) [$w curselection]\n    }\n    $w activate [expr {$active + $amount}]\n    $w see active\n    ListboxMotion $w [$w index active]\n}\n\n# ::tk::ListboxDataExtend\n#\n# This procedure is called for key-presses such as Shift-KEndData.\n# If the selection mode isn't multiple or extend then it does nothing.\n# Otherwise it moves the active element to el and, if we're in\n# extended mode, extends the selection to that point.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n# el -\t\tAn integer element number.\n\nproc ::tk::ListboxDataExtend {w el} {\n    set mode [$w cget -selectmode]\n    if {$mode eq \"extended\"} {\n\t$w activate $el\n\t$w see $el\n\tif {[$w selection includes anchor]} {\n\t    ListboxMotion $w $el\n\t}\n    } elseif {$mode eq \"multiple\"} {\n\t$w activate $el\n\t$w see $el\n    }\n}\n\n# ::tk::ListboxCancel\n#\n# This procedure is invoked to cancel an extended selection in\n# progress.  If there is an extended selection in progress, it\n# restores all of the items between the active one and the anchor\n# to their previous selection state.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n\nproc ::tk::ListboxCancel w {\n    variable ::tk::Priv\n    if {[$w cget -selectmode] ne \"extended\"} {\n\treturn\n    }\n    set first [$w index anchor]\n    set last $Priv(listboxPrev)\n    if {$last < 0} {\n\t# Not actually doing any selection right now\n\treturn\n    }\n    if {$first > $last} {\n\tset tmp $first\n\tset first $last\n\tset last $tmp\n    }\n    $w selection clear $first $last\n    while {$first <= $last} {\n\tif {$first in $Priv(listboxSelection)} {\n\t    $w selection set $first\n\t}\n\tincr first\n    }\n    tk::FireListboxSelectEvent $w\n}\n\n# ::tk::ListboxSelectAll\n#\n# This procedure is invoked to handle the \"select all\" operation.\n# For single and browse mode, it just selects the active element.\n# Otherwise it selects everything in the widget.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n\nproc ::tk::ListboxSelectAll w {\n    set mode [$w cget -selectmode]\n    if {$mode eq \"single\" || $mode eq \"browse\"} {\n\t$w selection clear 0 end\n\t$w selection set active\n    } else {\n\t$w selection set 0 end\n    }\n    tk::FireListboxSelectEvent $w\n}\n\n# ::tk::FireListboxSelectEvent\n#\n# Fire the <<ListboxSelect>> event if the listbox is not in disabled\n# state.\n#\n# Arguments:\n# w -\t\tThe listbox widget.\n\nproc ::tk::FireListboxSelectEvent w {\n    if {[$w cget -state] eq \"normal\"} {\n\tevent generate $w <<ListboxSelect>>\n    }\n}\n"
  },
  {
    "path": "library/megawidget.tcl",
    "content": "# megawidget.tcl\n#\n#\tBasic megawidget support classes. Experimental for any use other than\n#\tthe ::tk::IconList megawdget, which is itself only designed for use in\n#\tthe Unix file dialogs.\n#\n# Copyright © 2009-2010 Donal K. Fellows\n#\n# See the file \"license.terms\" for information on usage and redistribution of\n# this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\npackage require tk\n\f\n::oo::class create ::tk::Megawidget {\n    superclass ::oo::class\n    method unknown {w args} {\n\tif {[string match .* $w]} {\n\t    [self] create $w {*}$args\n\t    return $w\n\t}\n\tnext $w {*}$args\n    }\n    unexport new unknown\n    self method create {name superclasses body} {\n\tnext $name [list \\\n\t\tsuperclass ::tk::MegawidgetClass {*}$superclasses]\\;$body\n    }\n}\n\n::oo::class create ::tk::MegawidgetClass {\n    variable w hull options IdleCallbacks\n    constructor args {\n\t# Extract the \"widget name\" from the object name\n\tset w [namespace tail [self]]\n\n\t# Configure things\n\ttclParseConfigSpec [my varname options] [my GetSpecs] \"\" $args\n\n\t# Move the object out of the way of the hull widget\n\trename [self] _tmp\n\n\t# Make the hull widget(s)\n\tmy CreateHull\n\tbind $hull <Destroy> [list [namespace which my] destroy]\n\n\t# Rename things into their final places\n\trename ::$w theWidget\n\trename [self] ::$w\n\n\t# Make the contents\n\tmy Create\n    }\n    destructor {\n\tforeach {name cb} [array get IdleCallbacks] {\n\t    after cancel $cb\n\t    unset IdleCallbacks($name)\n\t}\n\tif {[winfo exists $w]} {\n\t    bind $hull <Destroy> {}\n\t    destroy $w\n\t}\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::configure --\n    #\n    #\tImplementation of 'configure' for megawidgets. Emulates the operation\n    #\tof the standard Tk configure method fairly closely, which makes things\n    #\tsubstantially more complex than they otherwise would be.\n    #\n    #\tThis method assumes that the 'GetSpecs' method returns a description\n    #\tof all the specifications of the options (i.e., as Tk returns except\n    #\twith the actual values removed). It also assumes that the 'options'\n    #\tarray in the class holds all options; it is up to subclasses to set\n    #\ttraces on that array if they want to respond to configuration changes.\n    #\n    #\tTODO: allow unambiguous abbreviations.\n    #\n    method configure args {\n\t# Configure behaves differently depending on the number of arguments\n\tset argc [llength $args]\n\tif {$argc == 0} {\n\t    return [lmap spec [my GetSpecs] {\n\t\tlappend spec $options([lindex $spec 0])\n\t    }]\n\t} elseif {$argc == 1} {\n\t    set opt [lindex $args 0]\n\t    if {[info exists options($opt)]} {\n\t\tset spec [lsearch -inline -index 0 -exact [my GetSpecs] $opt]\n\t\treturn [linsert $spec end $options($opt)]\n\t    }\n\t} elseif {$argc == 2} {\n\t    # Special case for where we're setting a single option. This\n\t    # avoids some of the costly operations. We still do the [array\n\t    # get] as this gives a sufficiently-consistent trace.\n\t    set opt [lindex $args 0]\n\t    if {[dict exists [array get options] $opt]} {\n\t\t# Actually set the new value of the option. Use a catch to\n\t\t# allow a megawidget user to throw an error from a write trace\n\t\t# on the options array to reject invalid values.\n\t\ttry {\n\t\t    array set options $args\n\t\t} on error {ret info} {\n\t\t    # Rethrow the error to get a clean stack trace\n\t\t    return -code error -errorcode [dict get $info -errorcode] $ret\n\t\t}\n\t\treturn\n\t    }\n\t} elseif {$argc % 2 == 0} {\n\t    # Check that all specified options exist. Any unknown option will\n\t    # cause the merged dictionary to be bigger than the options array\n\t    set merge [dict merge [array get options] $args]\n\t    if {[dict size $merge] == [array size options]} {\n\t\t# Actually set the new values of the options. Use a catch to\n\t\t# allow a megawidget user to throw an error from a write trace\n\t\t# on the options array to reject invalid values\n\t\ttry {\n\t\t    array set options $args\n\t\t} on error {ret info} {\n\t\t    # Rethrow the error to get a clean stack trace\n\t\t    return -code error -errorcode [dict get $info -errorcode] $ret\n\t\t}\n\t\treturn\n\t    }\n\t    # Due to the order of the merge, the unknown options will be at\n\t    # the end of the dict. This makes the first unknown option easy to\n\t    # find.\n\t    set opt [lindex [dict keys $merge] [array size options]]\n\t} else {\n\t    set opt [lindex $args end]\n\t    return -code error -errorcode [list TK VALUE_MISSING] \\\n\t\t\"value for \\\"$opt\\\" missing\"\n\t}\n\treturn -code error -errorcode [list TK LOOKUP OPTION $opt] \\\n\t    \"bad option \\\"$opt\\\": must be [tclListValidFlags options]\"\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::cget --\n    #\n    #\tImplementation of 'cget' for megawidgets. Emulates the operation of\n    #\tthe standard Tk cget method fairly closely.\n    #\n    #\tThis method assumes that the 'options' array in the class holds all\n    #\toptions; it is up to subclasses to set traces on that array if they\n    #\twant to respond to configuration reads.\n    #\n    #\tTODO: allow unambiguous abbreviations.\n    #\n    method cget option {\n\treturn $options($option)\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::TraceOption --\n    #\n    #\tSets up the tracing of an element of the options variable.\n    #\n    method TraceOption {option method args} {\n\tset callback [list my $method {*}$args]\n\ttrace add variable options($option) write [namespace code $callback]\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::GetSpecs --\n    #\n    #\tReturn a list of descriptions of options supported by this\n    #\tmegawidget. Each option is described by the 4-tuple list, consisting\n    #\tof the name of the option, the \"option database\" name, the \"option\n    #\tdatabase\" class-name, and the default value of the option. These are\n    #\tthe same values returned by calling the configure method of a widget,\n    #\texcept without the current values of the options.\n    #\n    method GetSpecs {} {\n\treturn {\n\t    {-takefocus takeFocus TakeFocus {}}\n\t}\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::CreateHull --\n    #\n    #\tCreates the real main widget of the megawidget. This is often a frame\n    #\tor toplevel widget, but isn't always (lightweight megawidgets might\n    #\tuse a content widget directly).\n    #\n    #\tThe name of the hull widget is given by the 'w' instance variable. The\n    #\tname should be written into the 'hull' instance variable. The command\n    #\tcreated by this method will be renamed.\n    #\n    method CreateHull {} {\n\treturn -code error -errorcode {TCL OO ABSTRACT_METHOD} \\\n\t    \"method must be overridden\"\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::Create --\n    #\n    #\tCreates the content of the megawidget. The name of the widget to\n    #\tcreate the content in will be in the 'hull' instance variable.\n    #\n    method Create {} {\n\treturn -code error -errorcode {TCL OO ABSTRACT_METHOD} \\\n\t    \"method must be overridden\"\n    }\n\n    ####################################################################\n    #\n    # MegawidgetClass::WhenIdle --\n    #\n    #\tArrange for a method to be called on the current instance when Tk is\n    #\tidle. Only one such method call per method will be queued; subsequent\n    #\tqueuing actions before the callback fires will be silently ignored.\n    #\tThe additional args will be passed to the callback, and the callbacks\n    #\twill be properly cancelled if the widget is destroyed.\n    #\n    method WhenIdle {method args} {\n\tif {![info exists IdleCallbacks($method)]} {\n\t    set IdleCallbacks($method) [after idle [list \\\n\t\t    [namespace which my] DoWhenIdle $method $args]]\n\t}\n    }\n    method DoWhenIdle {method arguments} {\n\tunset IdleCallbacks($method)\n\ttailcall my $method {*}$arguments\n    }\n}\n\n####################################################################\n#\n# tk::SimpleWidget --\n#\n#\tSimple megawidget class that makes it easy create widgets that behave\n#\tlike a ttk widget. It creates the hull as a ttk::frame and maps the\n#\tstate manipulation methods of the overall megawidget to the equivalent\n#\toperations on the ttk::frame.\n#\n::tk::Megawidget create ::tk::SimpleWidget {} {\n    variable w hull options\n    method GetSpecs {} {\n\treturn {\n\t    {-cursor cursor Cursor {}}\n\t    {-takefocus takeFocus TakeFocus {}}\n\t}\n    }\n    method CreateHull {} {\n\tset hull [::ttk::frame $w -cursor $options(-cursor)]\n\tmy TraceOption -cursor UpdateCursorOption\n    }\n    method UpdateCursorOption args {\n\t$hull configure -cursor $options(-cursor)\n    }\n    # Not fixed names, so can't forward\n    method state args {\n\ttailcall $hull state {*}$args\n    }\n    method instate args {\n\ttailcall $hull instate {*}$args\n    }\n}\n\n####################################################################\n#\n# tk::FocusableWidget --\n#\n#\tSimple megawidget class that makes a ttk-like widget that has a focus\n#\tring.\n#\n::tk::Megawidget create ::tk::FocusableWidget ::tk::SimpleWidget {\n    variable w hull options\n    method GetSpecs {} {\n\treturn {\n\t    {-cursor cursor Cursor {}}\n\t    {-takefocus takeFocus TakeFocus ::ttk::takefocus}\n\t}\n    }\n    method CreateHull {} {\n\tttk::frame $w\n\tset hull [ttk::entry $w.cHull -takefocus 0 -cursor $options(-cursor)]\n\tpack $hull -expand yes -fill both -ipadx 1.5p -ipady 1.5p\n\tmy TraceOption -cursor UpdateCursorOption\n    }\n}\n\f\nreturn\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "library/menu.tcl",
    "content": "# menu.tcl --\n#\n# This file defines the default bindings for Tk menus and menubuttons.\n# It also implements keyboard traversal of menus and implements a few\n# other utility procedures related to menus.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# Elements of tk::Priv that are used in this file:\n#\n# cursor -\t\tSaves the -cursor option for the posted menubutton.\n# focus -\t\tSaves the focus during a menu selection operation.\n#\t\t\tFocus gets restored here when the menu is unposted.\n# grabGlobal -\t\tUsed in conjunction with tk::Priv(oldGrab):  if\n#\t\t\ttk::Priv(oldGrab) is non-empty, then tk::Priv(grabGlobal)\n#\t\t\tcontains either an empty string or \"-global\" to\n#\t\t\tindicate whether the old grab was a local one or\n#\t\t\ta global one.\n# inMenubutton -\tThe name of the menubutton widget containing\n#\t\t\tthe mouse, or an empty string if the mouse is\n#\t\t\tnot over any menubutton.\n# menuBar -\t\tThe name of the menubar that is the root\n#\t\t\tof the cascade hierarchy which is currently\n#\t\t\tposted. This is null when there is no menu currently\n#\t\t\tbeing pulled down from a menu bar.\n# oldGrab -\t\tWindow that had the grab before a menu was posted.\n#\t\t\tUsed to restore the grab state after the menu\n#\t\t\tis unposted.  Empty string means there was no\n#\t\t\tgrab previously set.\n# popup -\t\tIf a menu has been popped up via tk_popup, this\n#\t\t\tgives the name of the menu.  Otherwise this\n#\t\t\tvalue is empty.\n# postedMb -\t\tName of the menubutton whose menu is currently\n#\t\t\tposted, or an empty string if nothing is posted\n#\t\t\tA grab is set on this widget.\n# relief -\t\tUsed to save the original relief of the current\n#\t\t\tmenubutton.\n# window -\t\tWhen the mouse is over a menu, this holds the\n#\t\t\tname of the menu;  it's cleared when the mouse\n#\t\t\tleaves the menu.\n# tearoff -\t\tWhether the last menu posted was a tearoff or not.\n#\t\t\tThis is true always for unix, for tearoffs for Mac\n#\t\t\tand Windows.\n# activeMenu -\t\tThis is the last active menu for use\n#\t\t\twith the <<MenuSelect>> virtual event.\n# activeItem -\t\tThis is the last active menu item for\n#\t\t\tuse with the <<MenuSelect>> virtual event.\n#-------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------\n# Overall note:\n# This file is tricky because there are five different ways that menus\n# can be used:\n#\n# 1. As a pulldown from a menubutton. In this style, the variable\n#    tk::Priv(postedMb) identifies the posted menubutton.\n# 2. As a torn-off menu copied from some other menu.  In this style\n#    tk::Priv(postedMb) is empty, and menu's type is \"tearoff\".\n# 3. As an option menu, triggered from an option menubutton.  In this\n#    style tk::Priv(postedMb) identifies the posted menubutton.\n# 4. As a popup menu.  In this style tk::Priv(postedMb) is empty and\n#    the top-level menu's type is \"normal\".\n# 5. As a pulldown from a menubar. The variable tk::Priv(menubar) has\n#    the owning menubar, and the menu itself is of type \"normal\".\n#\n# The various binding procedures use the  state described above to\n# distinguish the various cases and take different actions in each\n# case.\n#-------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for menus\n# and menubuttons.\n#-------------------------------------------------------------------------\n\nbind Menubutton <FocusIn> {}\nbind Menubutton <Enter> {\n    tk::MbEnter %W\n}\nbind Menubutton <Leave> {\n    tk::MbLeave %W\n}\nbind Menubutton <Button-1> {\n    if {$tk::Priv(inMenubutton) ne \"\"} {\n\ttk::MbPost $tk::Priv(inMenubutton) %X %Y\n    }\n}\nbind Menubutton <Motion> {\n    tk::MbMotion %W up %X %Y\n}\nbind Menubutton <B1-Motion> {\n    tk::MbMotion %W down %X %Y\n}\nbind Menubutton <ButtonRelease-1> {\n    tk::MbButtonUp %W\n}\nbind Menubutton <space> {\n    tk::MbPost %W\n    tk::MenuFirstEntry [%W cget -menu]\n}\nbind Menubutton <<Invoke>> {\n    tk::MbPost %W\n    tk::MenuFirstEntry [%W cget -menu]\n}\n\n# Must set focus when mouse enters a menu, in order to allow\n# mixed-mode processing using both the mouse and the keyboard.\n# Don't set the focus if the event comes from a grab release,\n# though:  such an event can happen after as part of unposting\n# a cascaded chain of menus, after the focus has already been\n# restored to wherever it was before menu selection started.\n\nbind Menu <FocusIn> {}\n\nbind Menu <Enter> {\n    set tk::Priv(window) %W\n    if {[%W cget -type] eq \"tearoff\"} {\n\tif {\"%m\" ne \"NotifyUngrab\"} {\n\t    if {[tk windowingsystem] eq \"x11\"} {\n\t\ttk_menuSetFocus %W\n\t    }\n\t}\n    }\n    tk::MenuMotion %W %x %y %s\n}\n\nbind Menu <Leave> {\n    tk::MenuLeave %W %X %Y %s\n}\nbind Menu <Motion> {\n    tk::MenuMotion %W %x %y %s\n}\nbind Menu <Button> {\n    tk::MenuButtonDown %W\n}\nbind Menu <ButtonRelease> {\n   tk::MenuInvoke %W 1\n}\nbind Menu <space> {\n    tk::MenuInvoke %W 0\n}\nbind Menu <<Invoke>> {\n    tk::MenuInvoke %W 0\n}\nbind Menu <Return> {\n    tk::MenuInvoke %W 0\n}\nbind Menu <Escape> {\n    tk::MenuEscape %W\n}\nbind Menu <<PrevChar>> {\n    tk::MenuLeftArrow %W\n}\nbind Menu <<NextChar>> {\n    tk::MenuRightArrow %W\n}\nbind Menu <<PrevLine>> {\n    tk::MenuUpArrow %W\n}\nbind Menu <<NextLine>> {\n    tk::MenuDownArrow %W\n}\nbind Menu <Key> {\n    tk::TraverseWithinMenu %W %A\n    break\n}\n\n# The following bindings apply to all windows, and are used to\n# implement keyboard menu traversal.\n\nif {[tk windowingsystem] eq \"x11\"} {\n    bind all <Alt-Key> {\n\ttk::TraverseToMenu %W %A\n    }\n\n    bind all <F10> {\n\ttk::FirstMenu %W\n    }\n} else {\n    bind Menubutton <Alt-Key> {\n\ttk::TraverseToMenu %W %A\n    }\n\n    bind Menubutton <F10> {\n\ttk::FirstMenu %W\n    }\n}\n\n# ::tk::MbEnter --\n# This procedure is invoked when the mouse enters a menubutton\n# widget.  It activates the widget unless it is disabled.  Note:\n# this procedure is only invoked when mouse button 1 is *not* down.\n# The procedure ::tk::MbB1Enter is invoked if the button is down.\n#\n# Arguments:\n# w -\t\t\tThe  name of the widget.\n\nproc ::tk::MbEnter w {\n    variable ::tk::Priv\n\n    if {$Priv(inMenubutton) ne \"\"} {\n\tMbLeave $Priv(inMenubutton)\n    }\n    set Priv(inMenubutton) $w\n    if {[$w cget -state] ne \"disabled\" && [tk windowingsystem] ne \"aqua\"} {\n\t$w configure -state active\n    }\n}\n\n# ::tk::MbLeave --\n# This procedure is invoked when the mouse leaves a menubutton widget.\n# It de-activates the widget, if the widget still exists.\n#\n# Arguments:\n# w -\t\t\tThe  name of the widget.\n\nproc ::tk::MbLeave w {\n    variable ::tk::Priv\n\n    set Priv(inMenubutton) {}\n    if {![winfo exists $w]} {\n\treturn\n    }\n    if {[$w cget -state] eq \"active\" && [tk windowingsystem] ne \"aqua\"} {\n\t$w configure -state normal\n    }\n}\n\n\n# ::tk::MbPost --\n# Given a menubutton, this procedure does all the work of posting\n# its associated menu and unposting any other menu that is currently\n# posted.\n#\n# Arguments:\n# w -\t\t\tThe name of the menubutton widget whose menu\n#\t\t\tis to be posted.\n# x, y -\t\tRoot coordinates of cursor, used for positioning\n#\t\t\toption menus.  If not specified, then the center\n#\t\t\tof the menubutton is used for an option menu.\n\nproc ::tk::MbPost {w {x {}} {y {}}} {\n    global errorInfo\n    variable ::tk::Priv\n\n    if {[$w cget -state] eq \"disabled\" || $w eq $Priv(postedMb)} {\n\treturn\n    }\n    set menu [$w cget -menu]\n    if {$menu eq \"\"} {\n\treturn\n    }\n    set tearoff [expr {[tk windowingsystem] eq \"x11\" \\\n\t    || [$menu cget -type] eq \"tearoff\"}]\n    if {[string first $w $menu] != 0} {\n\treturn -code error -errorcode {TK MENUBUTTON POST_NONCHILD} \\\n\t    \"can't post $menu: it isn't a descendant of $w\"\n    }\n    set cur $Priv(postedMb)\n    if {$cur ne \"\"} {\n\tMenuUnpost {}\n    }\n    if {$::tk_strictMotif} {\n\tset Priv(cursor) [$w cget -cursor]\n\t$w configure -cursor arrow\n    }\n    if {[tk windowingsystem] ne \"aqua\"} {\n\tset Priv(relief) [$w cget -relief]\n\t$w configure -relief raised\n    } else {\n\t$w configure -state active\n    }\n\n    set Priv(postedMb) $w\n    set Priv(focus) [focus]\n    $menu activate {}\n    GenerateMenuSelect $menu\n    update idletasks\n\n    if {[catch {PostMenubuttonMenu $w $menu $x $y} msg opt]} {\n\t# Error posting menu (e.g. bogus -postcommand). Unpost it and\n\t# reflect the error.\n\tMenuUnpost {}\n\treturn -options $opt $msg\n    }\n\n    set Priv(tearoff) $tearoff\n    if {$tearoff != 0 && [tk windowingsystem] ne \"aqua\"} {\n\tfocus $menu\n\tif {[winfo viewable $w]} {\n\t    SaveGrabInfo $w\n\t    grab -global $w\n\t}\n    }\n}\n\n# ::tk::MenuUnpost --\n# This procedure unposts a given menu, plus all of its ancestors up\n# to (and including) a menubutton, if any.  It also restores various\n# values to what they were before the menu was posted, and releases\n# a grab if there's a menubutton involved.  Special notes:\n# 1. It's important to unpost all menus before releasing the grab, so\n#    that any Enter-Leave events (e.g. from menu back to main\n#    application) have mode NotifyGrab.\n# 2. Be sure to enclose various groups of commands in \"catch\" so that\n#    the procedure will complete even if the menubutton or the menu\n#    or the grab window has been deleted.\n#\n# Arguments:\n# menu -\t\tName of a menu to unpost.  Ignored if there\n#\t\t\tis a posted menubutton.\n\nproc ::tk::MenuUnpost menu {\n    variable ::tk::Priv\n    set mb $Priv(postedMb)\n\n    # Restore focus right away (otherwise X will take focus away when\n    # the menu is unmapped and under some window managers (e.g. olvwm)\n    # we'll lose the focus completely).\n\n    catch {focus $Priv(focus)}\n    set Priv(focus) \"\"\n\n    # Unpost menu(s) and restore some stuff that's dependent on\n    # what was posted.\n\n    after cancel [array get Priv menuActivatedTimer]\n    unset -nocomplain Priv(menuActivated)\n    after cancel [array get Priv menuDeactivatedTimer]\n    unset -nocomplain Priv(menuDeactivated)\n\n    catch {\n\tif {$mb ne \"\"} {\n\t    set menu [$mb cget -menu]\n\t    $menu unpost\n\t    set Priv(postedMb) {}\n\t    if {$::tk_strictMotif} {\n\t\t$mb configure -cursor $Priv(cursor)\n\t    }\n\t    if {[tk windowingsystem] ne \"aqua\"} {\n\t\t$mb configure -relief $Priv(relief)\n\t    } else {\n\t\t$mb configure -state normal\n\t    }\n\t} elseif {$Priv(popup) ne \"\"} {\n\t    $Priv(popup) unpost\n\t    set Priv(popup) {}\n\t} elseif {[$menu cget -type] ne \"menubar\" && [$menu cget -type] ne \"tearoff\"} {\n\t    # We're in a cascaded sub-menu from a torn-off menu or popup.\n\t    # Unpost all the menus up to the toplevel one (but not\n\t    # including the top-level torn-off one) and deactivate the\n\t    # top-level torn off menu if there is one.\n\n\t    while {1} {\n\t\tset parent [winfo parent $menu]\n\t\tif {[winfo class $parent] ne \"Menu\" || ![winfo ismapped $parent]} {\n\t\t    break\n\t\t}\n\t\t$parent activate {}\n\t\t$parent postcascade {}\n\t\tGenerateMenuSelect $parent\n\t\tset type [$parent cget -type]\n\t\tif {$type eq \"menubar\" || $type eq \"tearoff\"} {\n\t\t    break\n\t\t}\n\t\tset menu $parent\n\t    }\n\t    if {[$menu cget -type] ne \"menubar\"} {\n\t\t$menu unpost\n\t    }\n\t}\n    }\n\n    if {($Priv(tearoff) != 0) || $Priv(menuBar) ne \"\"} {\n\t# Release grab, if any, and restore the previous grab, if there\n\t# was one.\n\tif {$menu ne \"\"} {\n\t    set grab [grab current $menu]\n\t    if {$grab ne \"\"} {\n\t\tgrab release $grab\n\t    }\n\t}\n\tRestoreOldGrab\n\tif {$Priv(menuBar) ne \"\"} {\n\t    if {$::tk_strictMotif} {\n\t\t$Priv(menuBar) configure -cursor $Priv(cursor)\n\t    }\n\t    set Priv(menuBar) {}\n\t}\n\tif {[tk windowingsystem] ne \"x11\"} {\n\t    set Priv(tearoff) 0\n\t}\n    }\n}\n\n# ::tk::MbMotion --\n# This procedure handles mouse motion events inside menubuttons, and\n# also outside menubuttons when a menubutton has a grab (e.g. when a\n# menu selection operation is in progress).\n#\n# Arguments:\n# w -\t\t\tThe name of the menubutton widget.\n# upDown -\t\t\"down\" means button 1 is pressed, \"up\" means\n#\t\t\tit isn't.\n# rootx, rooty -\tCoordinates of mouse, in (virtual?) root window.\n\nproc ::tk::MbMotion {w upDown rootx rooty} {\n    variable ::tk::Priv\n\n    if {$Priv(inMenubutton) eq $w} {\n\treturn\n    }\n    set new [winfo containing $rootx $rooty]\n    if {$new ne $Priv(inMenubutton) \\\n\t    && ($new eq \"\" || [winfo toplevel $new] eq [winfo toplevel $w])} {\n\tif {$Priv(inMenubutton) ne \"\"} {\n\t    MbLeave $Priv(inMenubutton)\n\t}\n\tif {$new ne \"\" \\\n\t\t&& [winfo class $new] eq \"Menubutton\" \\\n\t\t&& ([$new cget -indicatoron] == 0) \\\n\t\t&& ([$w cget -indicatoron] == 0)} {\n\t    if {$upDown eq \"down\"} {\n\t\tMbPost $new $rootx $rooty\n\t    } else {\n\t\tMbEnter $new\n\t    }\n\t}\n    }\n}\n\n# ::tk::MbButtonUp --\n# This procedure is invoked to handle button 1 releases for menubuttons.\n# If the release happens inside the menubutton then leave its menu\n# posted with element 0 activated.  Otherwise, unpost the menu.\n#\n# Arguments:\n# w -\t\t\tThe name of the menubutton widget.\n\nproc ::tk::MbButtonUp w {\n    variable ::tk::Priv\n\n    set menu [$w cget -menu]\n    set tearoff [expr {[tk windowingsystem] eq \"x11\" || \\\n\t    ($menu ne \"\" && [$menu cget -type] eq \"tearoff\")}]\n    if {($tearoff != 0) && $Priv(postedMb) eq $w \\\n\t    && $Priv(inMenubutton) eq $w} {\n\tMenuFirstEntry [$Priv(postedMb) cget -menu]\n    } else {\n\tMenuUnpost {}\n    }\n}\n\n# ::tk::MenuMotion --\n# This procedure is called to handle mouse motion events for menus.\n# It does two things.  First, it resets the active element in the\n# menu, if the mouse is over the menu.  Second, if a mouse button\n# is down, it posts and unposts cascade entries to match the mouse\n# position.\n#\n# Arguments:\n# menu -\t\tThe menu window.\n# x -\t\t\tThe x position of the mouse.\n# y -\t\t\tThe y position of the mouse.\n# state -\t\tModifier state (tells whether buttons are down).\n\nproc ::tk::MenuMotion {menu x y state} {\n    variable ::tk::Priv\n    if {$menu eq $Priv(window)} {\n\tset activeindex [$menu index active]\n\tif {[$menu cget -type] eq \"menubar\"} {\n\t    if {[info exists Priv(focus)] && $menu ne $Priv(focus)} {\n\t\t$menu activate @$x,$y\n\t\tGenerateMenuSelect $menu\n\t    }\n\t} else {\n\t    $menu activate @$x,$y\n\t    GenerateMenuSelect $menu\n\t}\n\tset index [$menu index @$x,$y]\n\tif {[info exists Priv(menuActivated)] \\\n\t\t&& $index >= 0 \\\n\t\t&& $index ne $activeindex} {\n\t    set mode [option get $menu clickToFocus ClickToFocus]\n\t    if {[string is false $mode]} {\n\t\tset delay [expr {[$menu cget -type] eq \"menubar\" ? 0 : 50}]\n\t\tif {[$menu type $index] eq \"cascade\"} {\n\t\t    # Catch these postcascade commands since the menu could be\n\t\t    # destroyed before they run.\n\t\t    set Priv(menuActivatedTimer) \\\n\t\t\t[after $delay [list catch [list \\\n\t\t\t    $menu postcascade active]]]\n\t\t} else {\n\t\t    set Priv(menuDeactivatedTimer) \\\n\t\t\t[after $delay [list catch [list\n\t\t\t    $menu postcascade {}]]]\n\t\t}\n\t    }\n\t}\n    }\n}\n\n# ::tk::MenuButtonDown --\n# Handles button presses in menus.  There are a couple of tricky things\n# here:\n# 1. Change the posted cascade entry (if any) to match the mouse position.\n# 2. If there is a posted menubutton, must grab to the menubutton;  this\n#    overrrides the implicit grab on button press, so that the menu\n#    button can track mouse motions over other menubuttons and change\n#    the posted menu.\n# 3. If there's no posted menubutton (e.g. because we're a torn-off menu\n#    or one of its descendants) must grab to the top-level menu so that\n#    we can track mouse motions across the entire menu hierarchy.\n#\n# Arguments:\n# menu -\t\tThe menu window.\n\nproc ::tk::MenuButtonDown menu {\n    variable ::tk::Priv\n\n    if {![winfo viewable $menu]} {\n\treturn\n    }\n    if {[$menu index active] < 0} {\n\tif {[$menu cget -type] ne \"menubar\" } {\n\t    set Priv(window) {}\n\t}\n\treturn\n    }\n    $menu postcascade active\n    if {$Priv(postedMb) ne \"\" && [winfo viewable $Priv(postedMb)]} {\n\tgrab -global $Priv(postedMb)\n    } else {\n\twhile {[$menu cget -type] eq \"normal\" \\\n\t\t&& [winfo class [winfo parent $menu]] eq \"Menu\" \\\n\t\t&& [winfo ismapped [winfo parent $menu]]} {\n\t    set menu [winfo parent $menu]\n\t}\n\n\tif {$Priv(menuBar) eq {}} {\n\t    set Priv(menuBar) $menu\n\t    if {$::tk_strictMotif} {\n\t\tset Priv(cursor) [$menu cget -cursor]\n\t\t$menu configure -cursor arrow\n\t    }\n\t    if {[$menu type active] eq \"cascade\"} {\n\t\tset Priv(menuActivated) 1\n\t    }\n\t}\n\n\t# Don't update grab information if the grab window isn't changing.\n\t# Otherwise, we'll get an error when we unpost the menus and\n\t# restore the grab, since the old grab window will not be viewable\n\t# anymore.\n\n\tif {$menu ne [grab current $menu]} {\n\t    SaveGrabInfo $menu\n\t}\n\n\t# Must re-grab even if the grab window hasn't changed, in order\n\t# to release the implicit grab from the button press.\n\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    grab -global $menu\n\t}\n    }\n}\n\n# ::tk::MenuLeave --\n# This procedure is invoked to handle Leave events for a menu.  It\n# deactivates everything unless the active element is a cascade element\n# and the mouse is now over the submenu.\n#\n# Arguments:\n# menu -\t\tThe menu window.\n# rootx, rooty -\tRoot coordinates of mouse.\n# state -\t\tModifier state.\n\nproc ::tk::MenuLeave {menu rootx rooty state} {\n    variable ::tk::Priv\n    set Priv(window) {}\n    if {[$menu index active] < 0} {\n\treturn\n    }\n    if {[$menu type active] eq \"cascade\" \\\n\t    && [winfo containing $rootx $rooty] eq \\\n\t\t[$menu entrycget active -menu]} {\n\treturn\n    }\n    $menu activate {}\n    GenerateMenuSelect $menu\n}\n\n# ::tk::MenuInvoke --\n# This procedure is invoked when button 1 is released over a menu.\n# It invokes the appropriate menu action and unposts the menu if\n# it came from a menubutton.\n#\n# Arguments:\n# w -\t\t\tName of the menu widget.\n# buttonRelease -\t1 means this procedure is called because of\n#\t\t\ta button release;  0 means because of keystroke.\n\nproc ::tk::MenuInvoke {w buttonRelease} {\n    variable ::tk::Priv\n\n    if {$buttonRelease && $Priv(window) eq \"\"} {\n\t# Mouse was pressed over a menu without a menu button, then\n\t# dragged off the menu (possibly with a cascade posted) and\n\t# released.  Unpost everything and quit.\n\n\t$w postcascade {}\n\t$w activate {}\n\tevent generate $w <<MenuSelect>>\n\tMenuUnpost $w\n\treturn\n    }\n    if {[$w type active] eq \"cascade\"} {\n\t$w postcascade active\n\tset menu [$w entrycget active -menu]\n\tMenuFirstEntry $menu\n    } elseif {[$w type active] eq \"tearoff\"} {\n\t::tk::TearOffMenu $w\n\tMenuUnpost $w\n    } elseif {[$w cget -type] eq \"menubar\"} {\n\t$w postcascade {}\n\tset activeindex [$w index active]\n\tset isCascade [string equal [$w type $activeindex] \"cascade\"]\n\n\t# Only de-activate the active item if it's a cascade; this prevents\n\t# the annoying \"activation flicker\" you otherwise get with\n\t# checkbuttons/commands/etc. on menubars\n\n\tif { $isCascade } {\n\t    $w activate {}\n\t    event generate $w <<MenuSelect>>\n\t}\n\n\tMenuUnpost $w\n\n\t# If the active item is not a cascade, invoke it.  This enables\n\t# the use of checkbuttons/commands/etc. on menubars (which is legal,\n\t# but not recommended)\n\n\tif { !$isCascade } {\n\t    uplevel #0 [list $w invoke $activeindex]\n\t}\n    } else {\n\tif {$Priv(popup) eq \"\" || [$w index active] >= 0} {\n\t    MenuUnpost $w\n\t}\n\tuplevel #0 [list $w invoke active]\n    }\n}\n\n# ::tk::MenuEscape --\n# This procedure is invoked for the Cancel (or Escape) key.  It unposts\n# the given menu and, if it is the top-level menu for a menu button,\n# unposts the menu button as well.\n#\n# Arguments:\n# menu -\t\tName of the menu window.\n\nproc ::tk::MenuEscape menu {\n    set parent [winfo parent $menu]\n    if {[winfo class $parent] ne \"Menu\"} {\n\tMenuUnpost $menu\n    } elseif {[$parent cget -type] eq \"menubar\"} {\n\tMenuUnpost $menu\n\tRestoreOldGrab\n    } else {\n\tMenuNextMenu $menu left\n    }\n}\n\n# The following routines handle arrow keys. Arrow keys behave\n# differently depending on whether the menu is a menu bar or not.\n\nproc ::tk::MenuUpArrow {menu} {\n    if {[$menu cget -type] eq \"menubar\"} {\n\tMenuNextMenu $menu left\n    } else {\n\tMenuNextEntry $menu -1\n    }\n}\n\nproc ::tk::MenuDownArrow {menu} {\n    if {[$menu cget -type] eq \"menubar\"} {\n\tMenuNextMenu $menu right\n    } else {\n\tMenuNextEntry $menu 1\n    }\n}\n\nproc ::tk::MenuLeftArrow {menu} {\n    if {[$menu cget -type] eq \"menubar\"} {\n\tMenuNextEntry $menu -1\n    } else {\n\tMenuNextMenu $menu left\n    }\n}\n\nproc ::tk::MenuRightArrow {menu} {\n    if {[$menu cget -type] eq \"menubar\"} {\n\tMenuNextEntry $menu 1\n    } else {\n\tMenuNextMenu $menu right\n    }\n}\n\n# ::tk::MenuNextMenu --\n# This procedure is invoked to handle \"left\" and \"right\" traversal\n# motions in menus.  It traverses to the next menu in a menu bar,\n# or into or out of a cascaded menu.\n#\n# Arguments:\n# menu -\t\tThe menu that received the keyboard\n#\t\t\tevent.\n# direction -\t\tDirection in which to move: \"left\" or \"right\"\n\nproc ::tk::MenuNextMenu {menu direction} {\n    variable ::tk::Priv\n\n    # First handle traversals into and out of cascaded menus.\n\n    if {$direction eq \"right\"} {\n\tset count 1\n\tset parent [winfo parent $menu]\n\tset class [winfo class $parent]\n\tif {[$menu type active] eq \"cascade\"} {\n\t    $menu postcascade active\n\t    set m2 [$menu entrycget active -menu]\n\t    if {$m2 ne \"\"} {\n\t\tMenuFirstEntry $m2\n\t    }\n\t    return\n\t} else {\n\t    set parent [winfo parent $menu]\n\t    while {$parent ne \".\"} {\n\t\tif {[winfo class $parent] eq \"Menu\" \\\n\t\t\t&& [$parent cget -type] eq \"menubar\"} {\n\t\t    tk_menuSetFocus $parent\n\t\t    MenuNextEntry $parent 1\n\t\t    return\n\t\t}\n\t\tset parent [winfo parent $parent]\n\t    }\n\t}\n    } else {\n\tset count -1\n\tset m2 [winfo parent $menu]\n\tif {[winfo class $m2] eq \"Menu\"} {\n\t    $menu activate {}\n\t    GenerateMenuSelect $menu\n\t    tk_menuSetFocus $m2\n\n\t    $m2 postcascade {}\n\n\t    if {[$m2 cget -type] ne \"menubar\"} {\n\t\treturn\n\t    }\n\t}\n    }\n\n    # Can't traverse into or out of a cascaded menu. Go to the next\n    # or previous menubutton, if that makes sense.\n\n    set m2 [winfo parent $menu]\n    if {[winfo class $m2] eq \"Menu\" && [$m2 cget -type] eq \"menubar\"} {\n\ttk_menuSetFocus $m2\n\tMenuNextEntry $m2 -1\n\treturn\n    }\n\n    set w $Priv(postedMb)\n    if {$w eq \"\"} {\n\treturn\n    }\n    set buttons [winfo children [winfo parent $w]]\n    set length [llength $buttons]\n    set i [expr {[lsearch -exact $buttons $w] + $count}]\n    while {1} {\n\twhile {$i < 0} {\n\t    incr i $length\n\t}\n\twhile {$i >= $length} {\n\t    incr i -$length\n\t}\n\tset mb [lindex $buttons $i]\n\tif {[winfo class $mb] eq \"Menubutton\" \\\n\t\t&& [$mb cget -state] ne \"disabled\" \\\n\t\t&& [$mb cget -menu] ne \"\" \\\n\t\t&& [[$mb cget -menu] index last] >= 0} {\n\t    break\n\t}\n\tif {$mb eq $w} {\n\t    return\n\t}\n\tincr i $count\n    }\n    MbPost $mb\n    MenuFirstEntry [$mb cget -menu]\n}\n\n# ::tk::MenuNextEntry --\n# Activate the next higher or lower entry in the posted menu,\n# wrapping around at the ends.  Disabled entries are skipped.\n#\n# Arguments:\n# menu -\t\t\tMenu window that received the keystroke.\n# count -\t\t\t1 means go to the next lower entry,\n#\t\t\t\t-1 means go to the next higher entry.\n\nproc ::tk::MenuNextEntry {menu count} {\n    set last [$menu index last]\n    if {$last < 0} {\n\treturn\n    }\n    set length [expr {$last+1}]\n    set quitAfter $length\n    set activeindex [$menu index active]\n    if {$activeindex < 0} {\n\tset i 0\n    } else {\n\tset i [expr {$activeindex + $count}]\n    }\n    while {1} {\n\tif {$quitAfter <= 0} {\n\t    # We've tried every entry in the menu.  Either there are\n\t    # none, or they're all disabled.  Just give up.\n\n\t    return\n\t}\n\twhile {$i < 0} {\n\t    incr i $length\n\t}\n\twhile {$i >= $length} {\n\t    incr i -$length\n\t}\n\tif {[catch {$menu entrycget $i -state} state] == 0} {\n\t    if {$state ne \"disabled\" && \\\n\t\t    ($i!=0 || [$menu cget -type] ne \"tearoff\" \\\n\t\t    || [$menu type 0] ne \"tearoff\")} {\n\t\tbreak\n\t    }\n\t}\n\tif {$i == $activeindex} {\n\t    return\n\t}\n\tincr i $count\n\tincr quitAfter -1\n    }\n    $menu activate $i\n    GenerateMenuSelect $menu\n\n    if {[$menu type $i] eq \"cascade\" && [$menu cget -type] eq \"menubar\"} {\n\tset cascade [$menu entrycget $i -menu]\n\tif {$cascade ne \"\"} {\n\t    # Here we auto-post a cascade.  This is necessary when\n\t    # we traverse left/right in the menubar, but undesirable when\n\t    # we traverse up/down in a menu.\n\t    $menu postcascade $i\n\t    MenuFirstEntry $cascade\n\t}\n    }\n}\n\n# ::tk::MenuFind --\n# This procedure searches the entire window hierarchy under w for\n# a menubutton that isn't disabled and whose underlined character\n# is \"char\" or an entry in a menubar that isn't disabled and whose\n# underlined character is \"char\".\n# It returns the name of that window, if found, or an\n# empty string if no matching window was found.  If \"char\" is an\n# empty string then the procedure returns the name of the first\n# menubutton found that isn't disabled.\n#\n# Arguments:\n# w -\t\t\t\tName of window where key was typed.\n# char -\t\t\tUnderlined character to search for;\n#\t\t\t\tmay be either upper or lower case, and\n#\t\t\t\twill match either upper or lower case.\n\nproc ::tk::MenuFind {w char} {\n    set char [string tolower $char]\n    set windowlist [winfo children $w]\n\n    foreach child $windowlist {\n\t# Don't descend into other toplevels.\n\tif {[winfo toplevel $w] ne [winfo toplevel $child]} {\n\t    continue\n\t}\n\tif {[winfo class $child] eq \"Menu\" && \\\n\t\t[$child cget -type] eq \"menubar\"} {\n\t    if {$char eq \"\"} {\n\t\treturn $child\n\t    }\n\t    set last [$child index last]\n\t    for {set i [$child cget -tearoff]} {$i <= $last} {incr i} {\n\t\tif {([$child type $i] eq \"separator\") || ([$child entrycget $i -state] eq \"disabled\")} {\n\t\t    continue\n\t\t}\n\t\tset underline [$child entrycget $i -underline]\n\t\tif {$underline >= 0} {\n\t\t    if {$char eq [string tolower [string index [$child entrycget $i -label] $underline]]} {\n\t\t\treturn $child\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    foreach child $windowlist {\n\t# Don't descend into other toplevels.\n\tif {[winfo toplevel $w] ne [winfo toplevel $child]} {\n\t    continue\n\t}\n\tswitch -- [winfo class $child] {\n\t    Menubutton {\n\t\tif {[$child cget -underline] < 0} {\n\t\t    set char2 \"\"\n\t\t} else {\n\t\t    set char2 [string index [$child cget -text] \\\n\t\t\t    [$child cget -underline]]\n\t\t}\n\t\tif {$char eq [string tolower $char2] || $char eq \"\"} {\n\t\t    if {[$child cget -state] ne \"disabled\"} {\n\t\t\treturn $child\n\t\t    }\n\t\t}\n\t    }\n\n\t    default {\n\t\tset match [MenuFind $child $char]\n\t\tif {$match ne \"\"} {\n\t\t    return $match\n\t\t}\n\t    }\n\t}\n    }\n    return {}\n}\n\n# ::tk::TraverseToMenu --\n# This procedure implements keyboard traversal of menus.  Given an\n# ASCII character \"char\", it looks for a menubutton with that character\n# underlined.  If one is found, it posts the menubutton's menu\n#\n# Arguments:\n# w -\t\t\t\tWindow in which the key was typed (selects\n#\t\t\t\ta toplevel window).\n# char -\t\t\tCharacter that selects a menu.  The case\n#\t\t\t\tis ignored.  If an empty string, nothing\n#\t\t\t\thappens.\n\nproc ::tk::TraverseToMenu {w char} {\n    variable ::tk::Priv\n    if {![winfo exists $w] || $char eq \"\"} {\n\treturn\n    }\n    while {[winfo class $w] eq \"Menu\"} {\n\tif {[$w cget -type] eq \"menubar\"} {\n\t    break\n\t} elseif {$Priv(postedMb) eq \"\"} {\n\t    return\n\t}\n\tset w [winfo parent $w]\n    }\n    set w [MenuFind [winfo toplevel $w] $char]\n    if {$w ne \"\"} {\n\tif {[winfo class $w] eq \"Menu\"} {\n\t    tk_menuSetFocus $w\n\t    set Priv(window) $w\n\t    SaveGrabInfo $w\n\t    grab -global $w\n\t    TraverseWithinMenu $w $char\n\t} else {\n\t    MbPost $w\n\t    MenuFirstEntry [$w cget -menu]\n\t}\n    }\n}\n\n# ::tk::FirstMenu --\n# This procedure traverses to the first menubutton in the toplevel\n# for a given window, and posts that menubutton's menu.\n#\n# Arguments:\n# w -\t\t\t\tName of a window.  Selects which toplevel\n#\t\t\t\tto search for menubuttons.\n\nproc ::tk::FirstMenu w {\n    variable ::tk::Priv\n    set w [MenuFind [winfo toplevel $w] \"\"]\n    if {$w ne \"\"} {\n\tif {[winfo class $w] eq \"Menu\"} {\n\t    tk_menuSetFocus $w\n\t    set Priv(window) $w\n\t    SaveGrabInfo $w\n\t    grab -global $w\n\t    MenuFirstEntry $w\n\t} else {\n\t    MbPost $w\n\t    MenuFirstEntry [$w cget -menu]\n\t}\n    }\n}\n\n# ::tk::TraverseWithinMenu\n# This procedure implements keyboard traversal within a menu.  It\n# searches for an entry in the menu that has \"char\" underlined.  If\n# such an entry is found, it is invoked and the menu is unposted.\n#\n# Arguments:\n# w -\t\t\t\tThe name of the menu widget.\n# char -\t\t\tThe character to look for;  case is\n#\t\t\t\tignored.  If the string is empty then\n#\t\t\t\tnothing happens.\n\nproc ::tk::TraverseWithinMenu {w char} {\n    if {$char eq \"\"} {\n\treturn\n    }\n    set char [string tolower $char]\n    set last [$w index last]\n    for {set i 0} {$i <= $last} {incr i} {\n\tif {[catch {set char2 [string index \\\n\t\t[$w entrycget $i -label] [$w entrycget $i -underline]]}]} {\n\t    continue\n\t}\n\tif {$char eq [string tolower $char2]} {\n\t    if {[$w type $i] eq \"cascade\"} {\n\t\t$w activate $i\n\t\t$w postcascade active\n\t\tevent generate $w <<MenuSelect>>\n\t\tset m2 [$w entrycget $i -menu]\n\t\tif {$m2 ne \"\"} {\n\t\t    MenuFirstEntry $m2\n\t\t}\n\t    } else {\n\t\tMenuUnpost $w\n\t\tuplevel #0 [list $w invoke $i]\n\t    }\n\t    return\n\t}\n    }\n}\n\n# ::tk::MenuFirstEntry --\n# Given a menu, this procedure finds the first entry that isn't\n# disabled or a tear-off or separator, and activates that entry.\n# However, if there is already an active entry in the menu (e.g.,\n# because of a previous call to tk::PostOverPoint) then the active\n# entry isn't changed.  This procedure also sets the input focus\n# to the menu.\n#\n# Arguments:\n# menu -\t\tName of the menu window (possibly empty).\n\nproc ::tk::MenuFirstEntry menu {\n    if {$menu eq \"\"} {\n\treturn\n    }\n    tk_menuSetFocus $menu\n    if {[$menu index active] >= 0} {\n\treturn\n    }\n    set last [$menu index last]\n    for {set i 0} {$i <= $last} {incr i} {\n\tif {([catch {set state [$menu entrycget $i -state]}] == 0) \\\n\t\t&& $state ne \"disabled\" && [$menu type $i] ne \"tearoff\"} {\n\t    $menu activate $i\n\t    GenerateMenuSelect $menu\n\t    # Only post the cascade if the current menu is a menubar;\n\t    # otherwise, if the first entry of the cascade is a cascade,\n\t    # we can get an annoying cascading effect resulting in a bunch of\n\t    # menus getting posted (bug 676)\n\t    if {[$menu type $i] eq \"cascade\" && [$menu cget -type] eq \"menubar\"} {\n\t\tset cascade [$menu entrycget $i -menu]\n\t\tif {$cascade ne \"\"} {\n\t\t    $menu postcascade $i\n\t\t    MenuFirstEntry $cascade\n\t\t}\n\t    }\n\t    return\n\t}\n    }\n}\n\n# ::tk::MenuFindName --\n# Given a menu and a text string, return the index of the menu entry\n# that displays the string as its label.  If there is no such entry,\n# return an empty string.  This procedure is tricky because some names\n# like \"active\" have a special meaning in menu commands, so we can't\n# always use the \"index\" widget command.\n#\n# Arguments:\n# menu -\t\tName of the menu widget.\n# s -\t\t\tString to look for.\n\nproc ::tk::MenuFindName {menu s} {\n    set i \"\"\n    if {![regexp {^active$|^last$|^none$|^[0-9]|^@} $s]} {\n\tcatch {set i [$menu index $s]}\n\treturn $i\n    }\n    set last [$menu index last]\n    for {set i 0} {$i <= $last} {incr i} {\n\tif {![catch {$menu entrycget $i -label} label]} {\n\t    if {$label eq $s} {\n\t\treturn $i\n\t    }\n\t}\n    }\n    return \"\"\n}\n\n# ::tk::PostMenubuttonMenu --\n#\n# Given a menubutton and a menu, this procedure posts the menu at the\n# appropriate location.  If the menubutton looks like an option\n# menubutton, meaning that the indicator is on and the direction is\n# neither above nor below, then the menu is posted so that the current\n# entry is vertically aligned with the menubutton.  On the Mac this\n# will expose a small amount of the blue indicator on the right hand\n# side.  On other platforms the entry is centered over the button.\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    proc ::tk::PostMenubuttonMenu {button menu cx cy} {\n\tset entry \"\"\n\tif {[$button cget -indicatoron]} {\n\t    set entry [MenuFindName $menu [$button cget -text]]\n\t    if {$entry eq \"\"} {\n\t\tset entry 0\n\t    }\n\t}\n\tset x [winfo rootx $button]\n\tset y [expr {2 + [winfo rooty $button]}]\n\tswitch [$button cget -direction] {\n\t    above {\n\t\tset entry \"\"\n\t\tincr y [expr {4 - [winfo reqheight $menu]}]\n\t    }\n\t    below {\n\t\tset entry \"\"\n\t\tincr y [expr {2 + [winfo height $button]}]\n\t    }\n\t    left {\n\t\tincr x [expr {-[winfo reqwidth $menu]}]\n\t    }\n\t    right {\n\t\tincr x [winfo width $button]\n\t    }\n\t    default {  # flush\n\t\tincr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}]\n\t    }\n\t}\n\tPostOverPoint $menu $x $y $entry\n    }\n} else {\n    proc ::tk::PostMenubuttonMenu {button menu cx cy} {\n\tset entry \"\"\n\tif {[$button cget -indicatoron]} {\n\t    set entry [MenuFindName $menu [$button cget -text]]\n\t    if {$entry eq \"\"} {\n\t\tset entry 0\n\t    }\n\t}\n\tset x [winfo rootx $button]\n\tset y [winfo rooty $button]\n\tswitch [$button cget -direction] {\n\t    above {\n\t\tincr y [expr {-[winfo reqheight $menu]}]\n\t\t# if we go offscreen to the top, show as 'below'\n\t\tif {$y < [winfo vrooty $button]} {\n\t\t    set y [expr {[winfo vrooty $button] + [winfo rooty $button]\\\n\t\t\t   + [winfo reqheight $button]}]\n\t\t}\n\t\tset entry {}\n\t    }\n\t    below {\n\t\tincr y [winfo height $button]\n\t\t# if we go offscreen to the bottom, show as 'above'\n\t\tset mh [winfo reqheight $menu]\n\t\tif {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} {\n\t\t    set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \\\n\t\t\t   + [winfo rooty $button] - $mh}]\n\t\t}\n\t\tset entry {}\n\t    }\n\t    left {\n\t\tincr x [expr {- [winfo reqwidth $menu]}]\n\t    }\n\t    right {\n\t\tincr x [expr {[winfo width $button]}]\n\t    }\n\t    default {  # flush\n\t\tif {[$button cget -indicatoron]} {\n\t\t    if {$cx ne \"\"} {\n\t\t\tset x [expr {$cx - [winfo reqwidth $menu] / 2}]\n\t\t\tset l [font metrics [$menu cget -font] -linespace]\n\t\t\tset y [expr {$cy - $l/2 - 2}]\n\t\t    } else {\n\t\t\tincr x [expr {([winfo width $button] - \\\n\t\t\t\t[winfo reqwidth $menu])/ 2}]\n\t\t    }\n\t\t} else {\n\t\t    incr y [winfo height $button]\n\t\t}\n\t    }\n\t}\n\tPostOverPoint $menu $x $y $entry\n    }\n}\n\n# ::tk::PostOverPoint --\n#\n# This procedure posts a menu on the screen so that a given entry in\n# the menu is positioned with its upper left corner at a given point\n# in the root window.  The procedure also activates that entry.  If no\n# entry is specified the upper left corner of the entire menu is\n# placed at the point.\n#\n# Arguments:\n# menu -\t\tMenu to post.\n# x, y -\t\tRoot coordinates of point.\n# entry -\t\tIndex of entry within menu to center over (x,y).\n#\t\t\tIf omitted or specified as {}, then the menu's\n#\t\t\tupper-left corner goes at (x,y).\n\nif {[tk windowingsystem] ne \"win32\"} {\n    proc ::tk::PostOverPoint {menu x y {entry {}}}  {\n\tif {$entry ne \"\"} {\n\t    $menu post $x $y $entry\n\t    if {[$menu type $entry] ni {separator tearoff} &&\n\t\t[$menu entrycget $entry -state] ne \"disabled\"} {\n\t\t$menu activate $entry\n\t\tGenerateMenuSelect $menu\n\t    }\n\t} else {\n\t    $menu post $x $y\n\t}\n\treturn\n    }\n} else {\n    proc ::tk::PostOverPoint {menu x y {entry {}}}  {\n\tif {$entry ne \"\"} {\n\t    incr y [expr {-[$menu yposition $entry]}]\n\t}\n\t# osVersion is not available in safe interps\n\tset ver 5\n\tif {[info exists ::tcl_platform(osVersion)]} {\n\t    scan $::tcl_platform(osVersion) %d ver\n\t}\n\n\t# We need to fix some problems with menu posting on Windows,\n\t# where, if the menu would overlap top or bottom of screen,\n\t# Windows puts it in the wrong place for us.  We must also\n\t# subtract an extra amount for half the height of the current\n\t# entry.  To be safe we subtract an extra 10.\n\t# NOTE: this issue appears to have been resolved in the Window\n\t# manager provided with Vista and Windows 7.\n\tif {$ver < 6} {\n\t    set yoffset [expr {[winfo screenheight $menu] \\\n\t\t\t\t   - $y - [winfo reqheight $menu] - 10}]\n\t    if {$yoffset < [winfo vrooty $menu]} {\n\t\t# The bottom of the menu is offscreen, so adjust upwards\n\t\tincr y [expr {$yoffset - [winfo vrooty $menu]}]\n\t    }\n\t    # If we're off the top of the screen (either because we were\n\t    # originally or because we just adjusted too far upwards),\n\t    # then make the menu popup on the top edge.\n\t    if {$y < [winfo vrooty $menu]} {\n\t\tset y [winfo vrooty $menu]\n\t    }\n\t}\n\t$menu post $x $y\n\tif {$entry ne \"\" && [$menu entrycget $entry -state] ne \"disabled\"} {\n\t    $menu activate $entry\n\t    GenerateMenuSelect $menu\n\t}\n    }\n}\n\n# ::tk::SaveGrabInfo --\n# Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record\n# the state of any existing grab on the w's display.\n#\n# Arguments:\n# w -\t\t\tName of a window;  used to select the display\n#\t\t\twhose grab information is to be recorded.\n\nproc tk::SaveGrabInfo w {\n    variable ::tk::Priv\n    set Priv(oldGrab) [grab current $w]\n    if {$Priv(oldGrab) ne \"\"} {\n\tset Priv(grabStatus) [grab status $Priv(oldGrab)]\n    }\n}\n\n# ::tk::RestoreOldGrab --\n# Restores the grab to what it was before TkSaveGrabInfo was called.\n#\n\nproc ::tk::RestoreOldGrab {} {\n    variable ::tk::Priv\n\n    if {$Priv(oldGrab) ne \"\"} {\n\t# Be careful restoring the old grab, since it's window may not\n\t# be visible anymore.\n\n\tcatch {\n\t    if {$Priv(grabStatus) eq \"global\"} {\n\t\tgrab set -global $Priv(oldGrab)\n\t    } else {\n\t\tgrab set $Priv(oldGrab)\n\t    }\n\t}\n\tset Priv(oldGrab) \"\"\n    }\n}\n\nproc ::tk_menuSetFocus {menu} {\n    variable ::tk::Priv\n    if {![info exists Priv(focus)] || $Priv(focus) eq \"\"} {\n\tset Priv(focus) [focus]\n    }\n    focus $menu\n}\n\nproc ::tk::GenerateMenuSelect {menu} {\n    variable ::tk::Priv\n\n    if {$Priv(activeMenu) ne $menu \\\n\t    || $Priv(activeItem) ne [$menu index active]} {\n\tset Priv(activeMenu) $menu\n\tset Priv(activeItem) [$menu index active]\n\tevent generate $menu <<MenuSelect>>\n    }\n}\n\n# ::tk_popup --\n# This procedure pops up a menu and sets things up for traversing\n# the menu and its submenus.\n#\n# Arguments:\n# menu -\t\tName of the menu to be popped up.\n# x, y -\t\tRoot coordinates at which to pop up the\n#\t\t\tmenu.\n# entry -\t\tIndex of a menu entry to center over (x,y).\n#\t\t\tIf omitted or specified as {}, then menu's\n#\t\t\tupper-left corner goes at (x,y).\n\nproc ::tk_popup {menu x y {entry {}}} {\n    variable ::tk::Priv\n    if {$Priv(popup) ne \"\" || $Priv(postedMb) ne \"\"} {\n\ttk::MenuUnpost {}\n    }\n    tk::PostOverPoint $menu $x $y $entry\n    if {[tk windowingsystem] eq \"x11\" && [winfo viewable $menu]} {\n\ttk::SaveGrabInfo $menu\n\tgrab -global $menu\n\tset Priv(popup) $menu\n\tset Priv(window) $menu\n\tset Priv(menuActivated) 1\n\ttk_menuSetFocus $menu\n    }\n}\n"
  },
  {
    "path": "library/mkpsenc.tcl",
    "content": "# mkpsenc.tcl --\n#\n# This file generates the postscript prolog used by Tk.\n\nnamespace eval ::tk {\n    # Creates Postscript encoding vector for ISO-8859-1 (could theoretically\n    # handle any 8-bit encoding, but Tk never generates characters outside\n    # ASCII).\n    #\n    proc CreatePostscriptEncoding {} {\n\tvariable psglyphs\n\t# Now check for known. Even if it is known, it can be other than we\n\t# need. GhostScript seems to be happy with such approach\n\tset result \"\\[\\n\"\n\tfor {set i 0} {$i<256} {incr i 8} {\n\t    for {set j 0} {$j<8} {incr j} {\n\t\tset enc [encoding convertfrom \"iso8859-1\" \\\n\t\t\t[format %c [expr {$i+$j}]]]\n\t\tcatch {\n\t\t    set hexcode {}\n\t\t    set hexcode [format %04X [scan $enc %c]]\n\t\t}\n\t\tif {[info exists psglyphs($hexcode)]} {\n\t\t    append result \"/$psglyphs($hexcode)\"\n\t\t} else {\n\t\t    append result \"/space\"\n\t\t}\n\t    }\n\t    append result \"\\n\"\n\t}\n\tappend result \"\\]\"\n\treturn $result\n    }\n\n    # List of adobe glyph names. Converted from glyphlist.txt, downloaded from\n    # Adobe.\n\n    variable psglyphs\n    array set psglyphs {\n\t0020 space\n\t0021 exclam\n\t0022 quotedbl\n\t0023 numbersign\n\t0024 dollar\n\t0025 percent\n\t0026 ampersand\n\t0027 quotesingle\n\t0028 parenleft\n\t0029 parenright\n\t002A asterisk\n\t002B plus\n\t002C comma\n\t002D hyphen\n\t002E period\n\t002F slash\n\t0030 zero\n\t0031 one\n\t0032 two\n\t0033 three\n\t0034 four\n\t0035 five\n\t0036 six\n\t0037 seven\n\t0038 eight\n\t0039 nine\n\t003A colon\n\t003B semicolon\n\t003C less\n\t003D equal\n\t003E greater\n\t003F question\n\t0040 at\n\t0041 A\n\t0042 B\n\t0043 C\n\t0044 D\n\t0045 E\n\t0046 F\n\t0047 G\n\t0048 H\n\t0049 I\n\t004A J\n\t004B K\n\t004C L\n\t004D M\n\t004E N\n\t004F O\n\t0050 P\n\t0051 Q\n\t0052 R\n\t0053 S\n\t0054 T\n\t0055 U\n\t0056 V\n\t0057 W\n\t0058 X\n\t0059 Y\n\t005A Z\n\t005B bracketleft\n\t005C backslash\n\t005D bracketright\n\t005E asciicircum\n\t005F underscore\n\t0060 grave\n\t0061 a\n\t0062 b\n\t0063 c\n\t0064 d\n\t0065 e\n\t0066 f\n\t0067 g\n\t0068 h\n\t0069 i\n\t006A j\n\t006B k\n\t006C l\n\t006D m\n\t006E n\n\t006F o\n\t0070 p\n\t0071 q\n\t0072 r\n\t0073 s\n\t0074 t\n\t0075 u\n\t0076 v\n\t0077 w\n\t0078 x\n\t0079 y\n\t007A z\n\t007B braceleft\n\t007C bar\n\t007D braceright\n\t007E asciitilde\n\t00A0 space\n\t00A1 exclamdown\n\t00A2 cent\n\t00A3 sterling\n\t00A4 currency\n\t00A5 yen\n\t00A6 brokenbar\n\t00A7 section\n\t00A8 dieresis\n\t00A9 copyright\n\t00AA ordfeminine\n\t00AB guillemotleft\n\t00AC logicalnot\n\t00AD hyphen\n\t00AE registered\n\t00AF macron\n\t00B0 degree\n\t00B1 plusminus\n\t00B2 twosuperior\n\t00B3 threesuperior\n\t00B4 acute\n\t00B5 mu\n\t00B6 paragraph\n\t00B7 periodcentered\n\t00B8 cedilla\n\t00B9 onesuperior\n\t00BA ordmasculine\n\t00BB guillemotright\n\t00BC onequarter\n\t00BD onehalf\n\t00BE threequarters\n\t00BF questiondown\n\t00C0 Agrave\n\t00C1 Aacute\n\t00C2 Acircumflex\n\t00C3 Atilde\n\t00C4 Adieresis\n\t00C5 Aring\n\t00C6 AE\n\t00C7 Ccedilla\n\t00C8 Egrave\n\t00C9 Eacute\n\t00CA Ecircumflex\n\t00CB Edieresis\n\t00CC Igrave\n\t00CD Iacute\n\t00CE Icircumflex\n\t00CF Idieresis\n\t00D0 Eth\n\t00D1 Ntilde\n\t00D2 Ograve\n\t00D3 Oacute\n\t00D4 Ocircumflex\n\t00D5 Otilde\n\t00D6 Odieresis\n\t00D7 multiply\n\t00D8 Oslash\n\t00D9 Ugrave\n\t00DA Uacute\n\t00DB Ucircumflex\n\t00DC Udieresis\n\t00DD Yacute\n\t00DE Thorn\n\t00DF germandbls\n\t00E0 agrave\n\t00E1 aacute\n\t00E2 acircumflex\n\t00E3 atilde\n\t00E4 adieresis\n\t00E5 aring\n\t00E6 ae\n\t00E7 ccedilla\n\t00E8 egrave\n\t00E9 eacute\n\t00EA ecircumflex\n\t00EB edieresis\n\t00EC igrave\n\t00ED iacute\n\t00EE icircumflex\n\t00EF idieresis\n\t00F0 eth\n\t00F1 ntilde\n\t00F2 ograve\n\t00F3 oacute\n\t00F4 ocircumflex\n\t00F5 otilde\n\t00F6 odieresis\n\t00F7 divide\n\t00F8 oslash\n\t00F9 ugrave\n\t00FA uacute\n\t00FB ucircumflex\n\t00FC udieresis\n\t00FD yacute\n\t00FE thorn\n\t00FF ydieresis\n\t0100 Amacron\n\t0101 amacron\n\t0102 Abreve\n\t0103 abreve\n\t0104 Aogonek\n\t0105 aogonek\n\t0106 Cacute\n\t0107 cacute\n\t0108 Ccircumflex\n\t0109 ccircumflex\n\t010A Cdotaccent\n\t010B cdotaccent\n\t010C Ccaron\n\t010D ccaron\n\t010E Dcaron\n\t010F dcaron\n\t0110 Dcroat\n\t0111 dcroat\n\t0112 Emacron\n\t0113 emacron\n\t0114 Ebreve\n\t0115 ebreve\n\t0116 Edotaccent\n\t0117 edotaccent\n\t0118 Eogonek\n\t0119 eogonek\n\t011A Ecaron\n\t011B ecaron\n\t011C Gcircumflex\n\t011D gcircumflex\n\t011E Gbreve\n\t011F gbreve\n\t0120 Gdotaccent\n\t0121 gdotaccent\n\t0122 Gcommaaccent\n\t0123 gcommaaccent\n\t0124 Hcircumflex\n\t0125 hcircumflex\n\t0126 Hbar\n\t0127 hbar\n\t0128 Itilde\n\t0129 itilde\n\t012A Imacron\n\t012B imacron\n\t012C Ibreve\n\t012D ibreve\n\t012E Iogonek\n\t012F iogonek\n\t0130 Idotaccent\n\t0131 dotlessi\n\t0132 IJ\n\t0133 ij\n\t0134 Jcircumflex\n\t0135 jcircumflex\n\t0136 Kcommaaccent\n\t0137 kcommaaccent\n\t0138 kgreenlandic\n\t0139 Lacute\n\t013A lacute\n\t013B Lcommaaccent\n\t013C lcommaaccent\n\t013D Lcaron\n\t013E lcaron\n\t013F Ldot\n\t0140 ldot\n\t0141 Lslash\n\t0142 lslash\n\t0143 Nacute\n\t0144 nacute\n\t0145 Ncommaaccent\n\t0146 ncommaaccent\n\t0147 Ncaron\n\t0148 ncaron\n\t0149 napostrophe\n\t014A Eng\n\t014B eng\n\t014C Omacron\n\t014D omacron\n\t014E Obreve\n\t014F obreve\n\t0150 Ohungarumlaut\n\t0151 ohungarumlaut\n\t0152 OE\n\t0153 oe\n\t0154 Racute\n\t0155 racute\n\t0156 Rcommaaccent\n\t0157 rcommaaccent\n\t0158 Rcaron\n\t0159 rcaron\n\t015A Sacute\n\t015B sacute\n\t015C Scircumflex\n\t015D scircumflex\n\t015E Scedilla\n\t015F scedilla\n\t0160 Scaron\n\t0161 scaron\n\t0162 Tcommaaccent\n\t0163 tcommaaccent\n\t0164 Tcaron\n\t0165 tcaron\n\t0166 Tbar\n\t0167 tbar\n\t0168 Utilde\n\t0169 utilde\n\t016A Umacron\n\t016B umacron\n\t016C Ubreve\n\t016D ubreve\n\t016E Uring\n\t016F uring\n\t0170 Uhungarumlaut\n\t0171 uhungarumlaut\n\t0172 Uogonek\n\t0173 uogonek\n\t0174 Wcircumflex\n\t0175 wcircumflex\n\t0176 Ycircumflex\n\t0177 ycircumflex\n\t0178 Ydieresis\n\t0179 Zacute\n\t017A zacute\n\t017B Zdotaccent\n\t017C zdotaccent\n\t017D Zcaron\n\t017E zcaron\n\t017F longs\n\t0192 florin\n\t01A0 Ohorn\n\t01A1 ohorn\n\t01AF Uhorn\n\t01B0 uhorn\n\t01E6 Gcaron\n\t01E7 gcaron\n\t01FA Aringacute\n\t01FB aringacute\n\t01FC AEacute\n\t01FD aeacute\n\t01FE Oslashacute\n\t01FF oslashacute\n\t0218 Scommaaccent\n\t0219 scommaaccent\n\t021A Tcommaaccent\n\t021B tcommaaccent\n\t02BC afii57929\n\t02BD afii64937\n\t02C6 circumflex\n\t02C7 caron\n\t02C9 macron\n\t02D8 breve\n\t02D9 dotaccent\n\t02DA ring\n\t02DB ogonek\n\t02DC tilde\n\t02DD hungarumlaut\n\t0300 gravecomb\n\t0301 acutecomb\n\t0303 tildecomb\n\t0309 hookabovecomb\n\t0323 dotbelowcomb\n\t0384 tonos\n\t0385 dieresistonos\n\t0386 Alphatonos\n\t0387 anoteleia\n\t0388 Epsilontonos\n\t0389 Etatonos\n\t038A Iotatonos\n\t038C Omicrontonos\n\t038E Upsilontonos\n\t038F Omegatonos\n\t0390 iotadieresistonos\n\t0391 Alpha\n\t0392 Beta\n\t0393 Gamma\n\t0394 Delta\n\t0395 Epsilon\n\t0396 Zeta\n\t0397 Eta\n\t0398 Theta\n\t0399 Iota\n\t039A Kappa\n\t039B Lambda\n\t039C Mu\n\t039D Nu\n\t039E Xi\n\t039F Omicron\n\t03A0 Pi\n\t03A1 Rho\n\t03A3 Sigma\n\t03A4 Tau\n\t03A5 Upsilon\n\t03A6 Phi\n\t03A7 Chi\n\t03A8 Psi\n\t03A9 Omega\n\t03AA Iotadieresis\n\t03AB Upsilondieresis\n\t03AC alphatonos\n\t03AD epsilontonos\n\t03AE etatonos\n\t03AF iotatonos\n\t03B0 upsilondieresistonos\n\t03B1 alpha\n\t03B2 beta\n\t03B3 gamma\n\t03B4 delta\n\t03B5 epsilon\n\t03B6 zeta\n\t03B7 eta\n\t03B8 theta\n\t03B9 iota\n\t03BA kappa\n\t03BB lambda\n\t03BC mu\n\t03BD nu\n\t03BE xi\n\t03BF omicron\n\t03C0 pi\n\t03C1 rho\n\t03C2 sigma1\n\t03C3 sigma\n\t03C4 tau\n\t03C5 upsilon\n\t03C6 phi\n\t03C7 chi\n\t03C8 psi\n\t03C9 omega\n\t03CA iotadieresis\n\t03CB upsilondieresis\n\t03CC omicrontonos\n\t03CD upsilontonos\n\t03CE omegatonos\n\t03D1 theta1\n\t03D2 Upsilon1\n\t03D5 phi1\n\t03D6 omega1\n\t0401 afii10023\n\t0402 afii10051\n\t0403 afii10052\n\t0404 afii10053\n\t0405 afii10054\n\t0406 afii10055\n\t0407 afii10056\n\t0408 afii10057\n\t0409 afii10058\n\t040A afii10059\n\t040B afii10060\n\t040C afii10061\n\t040E afii10062\n\t040F afii10145\n\t0410 afii10017\n\t0411 afii10018\n\t0412 afii10019\n\t0413 afii10020\n\t0414 afii10021\n\t0415 afii10022\n\t0416 afii10024\n\t0417 afii10025\n\t0418 afii10026\n\t0419 afii10027\n\t041A afii10028\n\t041B afii10029\n\t041C afii10030\n\t041D afii10031\n\t041E afii10032\n\t041F afii10033\n\t0420 afii10034\n\t0421 afii10035\n\t0422 afii10036\n\t0423 afii10037\n\t0424 afii10038\n\t0425 afii10039\n\t0426 afii10040\n\t0427 afii10041\n\t0428 afii10042\n\t0429 afii10043\n\t042A afii10044\n\t042B afii10045\n\t042C afii10046\n\t042D afii10047\n\t042E afii10048\n\t042F afii10049\n\t0430 afii10065\n\t0431 afii10066\n\t0432 afii10067\n\t0433 afii10068\n\t0434 afii10069\n\t0435 afii10070\n\t0436 afii10072\n\t0437 afii10073\n\t0438 afii10074\n\t0439 afii10075\n\t043A afii10076\n\t043B afii10077\n\t043C afii10078\n\t043D afii10079\n\t043E afii10080\n\t043F afii10081\n\t0440 afii10082\n\t0441 afii10083\n\t0442 afii10084\n\t0443 afii10085\n\t0444 afii10086\n\t0445 afii10087\n\t0446 afii10088\n\t0447 afii10089\n\t0448 afii10090\n\t0449 afii10091\n\t044A afii10092\n\t044B afii10093\n\t044C afii10094\n\t044D afii10095\n\t044E afii10096\n\t044F afii10097\n\t0451 afii10071\n\t0452 afii10099\n\t0453 afii10100\n\t0454 afii10101\n\t0455 afii10102\n\t0456 afii10103\n\t0457 afii10104\n\t0458 afii10105\n\t0459 afii10106\n\t045A afii10107\n\t045B afii10108\n\t045C afii10109\n\t045E afii10110\n\t045F afii10193\n\t0462 afii10146\n\t0463 afii10194\n\t0472 afii10147\n\t0473 afii10195\n\t0474 afii10148\n\t0475 afii10196\n\t0490 afii10050\n\t0491 afii10098\n\t04D9 afii10846\n\t05B0 afii57799\n\t05B1 afii57801\n\t05B2 afii57800\n\t05B3 afii57802\n\t05B4 afii57793\n\t05B5 afii57794\n\t05B6 afii57795\n\t05B7 afii57798\n\t05B8 afii57797\n\t05B9 afii57806\n\t05BB afii57796\n\t05BC afii57807\n\t05BD afii57839\n\t05BE afii57645\n\t05BF afii57841\n\t05C0 afii57842\n\t05C1 afii57804\n\t05C2 afii57803\n\t05C3 afii57658\n\t05D0 afii57664\n\t05D1 afii57665\n\t05D2 afii57666\n\t05D3 afii57667\n\t05D4 afii57668\n\t05D5 afii57669\n\t05D6 afii57670\n\t05D7 afii57671\n\t05D8 afii57672\n\t05D9 afii57673\n\t05DA afii57674\n\t05DB afii57675\n\t05DC afii57676\n\t05DD afii57677\n\t05DE afii57678\n\t05DF afii57679\n\t05E0 afii57680\n\t05E1 afii57681\n\t05E2 afii57682\n\t05E3 afii57683\n\t05E4 afii57684\n\t05E5 afii57685\n\t05E6 afii57686\n\t05E7 afii57687\n\t05E8 afii57688\n\t05E9 afii57689\n\t05EA afii57690\n\t05F0 afii57716\n\t05F1 afii57717\n\t05F2 afii57718\n\t060C afii57388\n\t061B afii57403\n\t061F afii57407\n\t0621 afii57409\n\t0622 afii57410\n\t0623 afii57411\n\t0624 afii57412\n\t0625 afii57413\n\t0626 afii57414\n\t0627 afii57415\n\t0628 afii57416\n\t0629 afii57417\n\t062A afii57418\n\t062B afii57419\n\t062C afii57420\n\t062D afii57421\n\t062E afii57422\n\t062F afii57423\n\t0630 afii57424\n\t0631 afii57425\n\t0632 afii57426\n\t0633 afii57427\n\t0634 afii57428\n\t0635 afii57429\n\t0636 afii57430\n\t0637 afii57431\n\t0638 afii57432\n\t0639 afii57433\n\t063A afii57434\n\t0640 afii57440\n\t0641 afii57441\n\t0642 afii57442\n\t0643 afii57443\n\t0644 afii57444\n\t0645 afii57445\n\t0646 afii57446\n\t0647 afii57470\n\t0648 afii57448\n\t0649 afii57449\n\t064A afii57450\n\t064B afii57451\n\t064C afii57452\n\t064D afii57453\n\t064E afii57454\n\t064F afii57455\n\t0650 afii57456\n\t0651 afii57457\n\t0652 afii57458\n\t0660 afii57392\n\t0661 afii57393\n\t0662 afii57394\n\t0663 afii57395\n\t0664 afii57396\n\t0665 afii57397\n\t0666 afii57398\n\t0667 afii57399\n\t0668 afii57400\n\t0669 afii57401\n\t066A afii57381\n\t066D afii63167\n\t0679 afii57511\n\t067E afii57506\n\t0686 afii57507\n\t0688 afii57512\n\t0691 afii57513\n\t0698 afii57508\n\t06A4 afii57505\n\t06AF afii57509\n\t06BA afii57514\n\t06D2 afii57519\n\t06D5 afii57534\n\t1E80 Wgrave\n\t1E81 wgrave\n\t1E82 Wacute\n\t1E83 wacute\n\t1E84 Wdieresis\n\t1E85 wdieresis\n\t1EF2 Ygrave\n\t1EF3 ygrave\n\t200C afii61664\n\t200D afii301\n\t200E afii299\n\t200F afii300\n\t2012 figuredash\n\t2013 endash\n\t2014 emdash\n\t2015 afii00208\n\t2017 underscoredbl\n\t2018 quoteleft\n\t2019 quoteright\n\t201A quotesinglbase\n\t201B quotereversed\n\t201C quotedblleft\n\t201D quotedblright\n\t201E quotedblbase\n\t2020 dagger\n\t2021 daggerdbl\n\t2022 bullet\n\t2024 onedotenleader\n\t2025 twodotenleader\n\t2026 ellipsis\n\t202C afii61573\n\t202D afii61574\n\t202E afii61575\n\t2030 perthousand\n\t2032 minute\n\t2033 second\n\t2039 guilsinglleft\n\t203A guilsinglright\n\t203C exclamdbl\n\t2044 fraction\n\t2070 zerosuperior\n\t2074 foursuperior\n\t2075 fivesuperior\n\t2076 sixsuperior\n\t2077 sevensuperior\n\t2078 eightsuperior\n\t2079 ninesuperior\n\t207D parenleftsuperior\n\t207E parenrightsuperior\n\t207F nsuperior\n\t2080 zeroinferior\n\t2081 oneinferior\n\t2082 twoinferior\n\t2083 threeinferior\n\t2084 fourinferior\n\t2085 fiveinferior\n\t2086 sixinferior\n\t2087 seveninferior\n\t2088 eightinferior\n\t2089 nineinferior\n\t208D parenleftinferior\n\t208E parenrightinferior\n\t20A1 colonmonetary\n\t20A3 franc\n\t20A4 lira\n\t20A7 peseta\n\t20AA afii57636\n\t20AB dong\n\t20AC Euro\n\t2105 afii61248\n\t2111 Ifraktur\n\t2113 afii61289\n\t2116 afii61352\n\t2118 weierstrass\n\t211C Rfraktur\n\t211E prescription\n\t2122 trademark\n\t2126 Omega\n\t212E estimated\n\t2135 aleph\n\t2153 onethird\n\t2154 twothirds\n\t215B oneeighth\n\t215C threeeighths\n\t215D fiveeighths\n\t215E seveneighths\n\t2190 arrowleft\n\t2191 arrowup\n\t2192 arrowright\n\t2193 arrowdown\n\t2194 arrowboth\n\t2195 arrowupdn\n\t21A8 arrowupdnbse\n\t21B5 carriagereturn\n\t21D0 arrowdblleft\n\t21D1 arrowdblup\n\t21D2 arrowdblright\n\t21D3 arrowdbldown\n\t21D4 arrowdblboth\n\t2200 universal\n\t2202 partialdiff\n\t2203 existential\n\t2205 emptyset\n\t2206 Delta\n\t2207 gradient\n\t2208 element\n\t2209 notelement\n\t220B suchthat\n\t220F product\n\t2211 summation\n\t2212 minus\n\t2215 fraction\n\t2217 asteriskmath\n\t2219 periodcentered\n\t221A radical\n\t221D proportional\n\t221E infinity\n\t221F orthogonal\n\t2220 angle\n\t2227 logicaland\n\t2228 logicalor\n\t2229 intersection\n\t222A union\n\t222B integral\n\t2234 therefore\n\t223C similar\n\t2245 congruent\n\t2248 approxequal\n\t2260 notequal\n\t2261 equivalence\n\t2264 lessequal\n\t2265 greaterequal\n\t2282 propersubset\n\t2283 propersuperset\n\t2284 notsubset\n\t2286 reflexsubset\n\t2287 reflexsuperset\n\t2295 circleplus\n\t2297 circlemultiply\n\t22A5 perpendicular\n\t22C5 dotmath\n\t2302 house\n\t2310 revlogicalnot\n\t2320 integraltp\n\t2321 integralbt\n\t2329 angleleft\n\t232A angleright\n\t2500 SF100000\n\t2502 SF110000\n\t250C SF010000\n\t2510 SF030000\n\t2514 SF020000\n\t2518 SF040000\n\t251C SF080000\n\t2524 SF090000\n\t252C SF060000\n\t2534 SF070000\n\t253C SF050000\n\t2550 SF430000\n\t2551 SF240000\n\t2552 SF510000\n\t2553 SF520000\n\t2554 SF390000\n\t2555 SF220000\n\t2556 SF210000\n\t2557 SF250000\n\t2558 SF500000\n\t2559 SF490000\n\t255A SF380000\n\t255B SF280000\n\t255C SF270000\n\t255D SF260000\n\t255E SF360000\n\t255F SF370000\n\t2560 SF420000\n\t2561 SF190000\n\t2562 SF200000\n\t2563 SF230000\n\t2564 SF470000\n\t2565 SF480000\n\t2566 SF410000\n\t2567 SF450000\n\t2568 SF460000\n\t2569 SF400000\n\t256A SF540000\n\t256B SF530000\n\t256C SF440000\n\t2580 upblock\n\t2584 dnblock\n\t2588 block\n\t258C lfblock\n\t2590 rtblock\n\t2591 ltshade\n\t2592 shade\n\t2593 dkshade\n\t25A0 filledbox\n\t25A1 H22073\n\t25AA H18543\n\t25AB H18551\n\t25AC filledrect\n\t25B2 triagup\n\t25BA triagrt\n\t25BC triagdn\n\t25C4 triaglf\n\t25CA lozenge\n\t25CB circle\n\t25CF H18533\n\t25D8 invbullet\n\t25D9 invcircle\n\t25E6 openbullet\n\t263A smileface\n\t263B invsmileface\n\t263C sun\n\t2640 female\n\t2642 male\n\t2660 spade\n\t2663 club\n\t2665 heart\n\t2666 diamond\n\t266A musicalnote\n\t266B musicalnotedbl\n\tF6BE dotlessj\n\tF6BF LL\n\tF6C0 ll\n\tF6C1 Scedilla\n\tF6C2 scedilla\n\tF6C3 commaaccent\n\tF6C4 afii10063\n\tF6C5 afii10064\n\tF6C6 afii10192\n\tF6C7 afii10831\n\tF6C8 afii10832\n\tF6C9 Acute\n\tF6CA Caron\n\tF6CB Dieresis\n\tF6CC DieresisAcute\n\tF6CD DieresisGrave\n\tF6CE Grave\n\tF6CF Hungarumlaut\n\tF6D0 Macron\n\tF6D1 cyrBreve\n\tF6D2 cyrFlex\n\tF6D3 dblGrave\n\tF6D4 cyrbreve\n\tF6D5 cyrflex\n\tF6D6 dblgrave\n\tF6D7 dieresisacute\n\tF6D8 dieresisgrave\n\tF6D9 copyrightserif\n\tF6DA registerserif\n\tF6DB trademarkserif\n\tF6DC onefitted\n\tF6DD rupiah\n\tF6DE threequartersemdash\n\tF6DF centinferior\n\tF6E0 centsuperior\n\tF6E1 commainferior\n\tF6E2 commasuperior\n\tF6E3 dollarinferior\n\tF6E4 dollarsuperior\n\tF6E5 hypheninferior\n\tF6E6 hyphensuperior\n\tF6E7 periodinferior\n\tF6E8 periodsuperior\n\tF6E9 asuperior\n\tF6EA bsuperior\n\tF6EB dsuperior\n\tF6EC esuperior\n\tF6ED isuperior\n\tF6EE lsuperior\n\tF6EF msuperior\n\tF6F0 osuperior\n\tF6F1 rsuperior\n\tF6F2 ssuperior\n\tF6F3 tsuperior\n\tF6F4 Brevesmall\n\tF6F5 Caronsmall\n\tF6F6 Circumflexsmall\n\tF6F7 Dotaccentsmall\n\tF6F8 Hungarumlautsmall\n\tF6F9 Lslashsmall\n\tF6FA OEsmall\n\tF6FB Ogoneksmall\n\tF6FC Ringsmall\n\tF6FD Scaronsmall\n\tF6FE Tildesmall\n\tF6FF Zcaronsmall\n\tF721 exclamsmall\n\tF724 dollaroldstyle\n\tF726 ampersandsmall\n\tF730 zerooldstyle\n\tF731 oneoldstyle\n\tF732 twooldstyle\n\tF733 threeoldstyle\n\tF734 fouroldstyle\n\tF735 fiveoldstyle\n\tF736 sixoldstyle\n\tF737 sevenoldstyle\n\tF738 eightoldstyle\n\tF739 nineoldstyle\n\tF73F questionsmall\n\tF760 Gravesmall\n\tF761 Asmall\n\tF762 Bsmall\n\tF763 Csmall\n\tF764 Dsmall\n\tF765 Esmall\n\tF766 Fsmall\n\tF767 Gsmall\n\tF768 Hsmall\n\tF769 Ismall\n\tF76A Jsmall\n\tF76B Ksmall\n\tF76C Lsmall\n\tF76D Msmall\n\tF76E Nsmall\n\tF76F Osmall\n\tF770 Psmall\n\tF771 Qsmall\n\tF772 Rsmall\n\tF773 Ssmall\n\tF774 Tsmall\n\tF775 Usmall\n\tF776 Vsmall\n\tF777 Wsmall\n\tF778 Xsmall\n\tF779 Ysmall\n\tF77A Zsmall\n\tF7A1 exclamdownsmall\n\tF7A2 centoldstyle\n\tF7A8 Dieresissmall\n\tF7AF Macronsmall\n\tF7B4 Acutesmall\n\tF7B8 Cedillasmall\n\tF7BF questiondownsmall\n\tF7E0 Agravesmall\n\tF7E1 Aacutesmall\n\tF7E2 Acircumflexsmall\n\tF7E3 Atildesmall\n\tF7E4 Adieresissmall\n\tF7E5 Aringsmall\n\tF7E6 AEsmall\n\tF7E7 Ccedillasmall\n\tF7E8 Egravesmall\n\tF7E9 Eacutesmall\n\tF7EA Ecircumflexsmall\n\tF7EB Edieresissmall\n\tF7EC Igravesmall\n\tF7ED Iacutesmall\n\tF7EE Icircumflexsmall\n\tF7EF Idieresissmall\n\tF7F0 Ethsmall\n\tF7F1 Ntildesmall\n\tF7F2 Ogravesmall\n\tF7F3 Oacutesmall\n\tF7F4 Ocircumflexsmall\n\tF7F5 Otildesmall\n\tF7F6 Odieresissmall\n\tF7F8 Oslashsmall\n\tF7F9 Ugravesmall\n\tF7FA Uacutesmall\n\tF7FB Ucircumflexsmall\n\tF7FC Udieresissmall\n\tF7FD Yacutesmall\n\tF7FE Thornsmall\n\tF7FF Ydieresissmall\n\tF8E5 radicalex\n\tF8E6 arrowvertex\n\tF8E7 arrowhorizex\n\tF8E8 registersans\n\tF8E9 copyrightsans\n\tF8EA trademarksans\n\tF8EB parenlefttp\n\tF8EC parenleftex\n\tF8ED parenleftbt\n\tF8EE bracketlefttp\n\tF8EF bracketleftex\n\tF8F0 bracketleftbt\n\tF8F1 bracelefttp\n\tF8F2 braceleftmid\n\tF8F3 braceleftbt\n\tF8F4 braceex\n\tF8F5 integralex\n\tF8F6 parenrighttp\n\tF8F7 parenrightex\n\tF8F8 parenrightbt\n\tF8F9 bracketrighttp\n\tF8FA bracketrightex\n\tF8FB bracketrightbt\n\tF8FC bracerighttp\n\tF8FD bracerightmid\n\tF8FE bracerightbt\n\tFB00 ff\n\tFB01 fi\n\tFB02 fl\n\tFB03 ffi\n\tFB04 ffl\n\tFB1F afii57705\n\tFB2A afii57694\n\tFB2B afii57695\n\tFB35 afii57723\n\tFB4B afii57700\n    }\n\n    variable ps_preamble {}\n\n    namespace eval ps {\n\tnamespace ensemble create\n\tnamespace export {[a-z]*}\n\tproc literal {string} {\n\t    upvar 0 ::tk::ps_preamble preamble\n\t    foreach line [split $string \\n] {\n\t\tset line [string trim $line]\n\t\tif {$line eq \"\"} continue\n\t\tappend preamble $line \\n\n\t    }\n\t    return\n\t}\n\tproc variable {name value} {\n\t    upvar 0 ::tk::ps_preamble preamble\n\t    append preamble \"/$name $value def\\n\"\n\t    return\n\t}\n\tproc function {name body} {\n\t    upvar 0 ::tk::ps_preamble preamble\n\t    append preamble \"/$name \\{\"\n\t    foreach line [split $body \\n] {\n\t\tset line [string trim $line]\n\t\t# Strip blank lines and comments from the bodies of functions\n\t\tif {$line eq \"\" } continue\n\t\tif {[string match {[%#]*} $line]} continue\n\t\tappend preamble $line \" \"\n\t    }\n\t    append preamble \"\\} bind def\\n\"\n\t    return\n\t}\n    }\n\n    ps literal {\n\t%%BeginProlog\n\t% This is a standard prolog for Postscript generated by Tk's canvas\n\t% widget.\n    }\n    ps variable CurrentEncoding [CreatePostscriptEncoding]\n    ps literal {50 dict begin}\n\n    # The definitions below just define all of the variables used in any of\n    # the procedures here. This is needed for obscure reasons explained on\n    # p. 716 of the Postscript manual (Section H.2.7, \"Initializing\n    # Variables,\" in the section on Encapsulated Postscript).\n    ps variable baseline 0\n    ps variable stipimage 0\n    ps variable height 0\n    ps variable justify 0\n    ps variable lineLength 0\n    ps variable spacing 0\n    ps variable stipple 0\n    ps variable strings 0\n    ps variable xoffset 0\n    ps variable yoffset 0\n    ps variable tmpstip null\n    ps variable baselineSampler \"( TXygqPZ)\"\n    # Put an extra-tall character in; done this way to avoid encoding trouble\n    ps literal {baselineSampler 0 196 put}\n\n    ps function cstringshow {\n\t{\n\t    dup type /stringtype eq\n\t    { show } { glyphshow }\n\t    ifelse\n\t} forall\n    }\n\n    ps function cstringwidth {\n\t0 exch 0 exch\n\t{\n\t    dup type /stringtype eq\n\t    { stringwidth } {\n\t\tcurrentfont /Encoding get exch 1 exch put (\\001)\n\t\tstringwidth\n\t    }\n\t    ifelse\n\t    exch 3 1 roll add 3 1 roll add exch\n\t} forall\n    }\n\n    # font ISOEncode font\n    #\n    # This procedure changes the encoding of a font from the default\n    # Postscript encoding to current system encoding. It's typically invoked\n    # just before invoking \"setfont\". The body of this procedure comes from\n    # Section 5.6.1 of the Postscript book.\n    ps function ISOEncode {\n\tdup length dict begin\n\t{1 index /FID ne {def} {pop pop} ifelse} forall\n\t/Encoding CurrentEncoding def\n\tcurrentdict\n\tend\n\t% I'm not sure why it's necessary to use \"definefont\" on this new\n\t% font, but it seems to be important; just use the name \"Temporary\"\n\t% for the font.\n\t/Temporary exch definefont\n    }\n\n    # StrokeClip\n    #\n    # This procedure converts the current path into a clip area under the\n    # assumption of stroking. It's a bit tricky because some Postscript\n    # interpreters get errors during strokepath for dashed lines. If this\n    # happens then turn off dashes and try again.\n    ps function StrokeClip {\n\t{strokepath} stopped {\n\t    (This Postscript printer gets limitcheck overflows when) =\n\t    (stippling dashed lines;  lines will be printed solid instead.) =\n\t    [] 0 setdash strokepath} if\n\tclip\n    }\n\n    # desiredSize EvenPixels closestSize\n    #\n    # The procedure below is used for stippling. Given the optimal size of a\n    # dot in a stipple pattern in the current user coordinate system, compute\n    # the closest size that is an exact multiple of the device's pixel\n    # size. This allows stipple patterns to be displayed without aliasing\n    # effects.\n    ps function EvenPixels {\n\t% Compute exact number of device pixels per stipple dot.\n\tdup 0 matrix currentmatrix dtransform\n\tdup mul exch dup mul add sqrt\n\t% Round to an integer, make sure the number is at least 1, and\n\t% compute user coord distance corresponding to this.\n\tdup round dup 1 lt {pop 1} if\n\texch div mul\n    }\n\n    # width height string StippleFill --\n    #\n    # Given a path already set up and a clipping region generated from it,\n    # this procedure will fill the clipping region with a stipple pattern.\n    # \"String\" contains a proper image description of the stipple pattern and\n    # \"width\" and \"height\" give its dimensions. Each stipple dot is assumed to\n    # be about one unit across in the current user coordinate system. This\n    # procedure trashes the graphics state.\n    ps function StippleFill {\n\t% The following code is needed to work around a NeWSprint bug.\n\t/tmpstip 1 index def\n\t% Change the scaling so that one user unit in user coordinates\n\t% corresponds to the size of one stipple dot.\n\t1 EvenPixels dup scale\n\t% Compute the bounding box occupied by the path (which is now the\n\t% clipping region), and round the lower coordinates down to the\n\t% nearest starting point for the stipple pattern. Be careful about\n\t% negative numbers, since the rounding works differently on them.\n\tpathbbox\n\t4 2 roll\n\t5 index div dup 0 lt {1 sub} if cvi 5 index mul 4 1 roll\n\t6 index div dup 0 lt {1 sub} if cvi 6 index mul 3 2 roll\n\t% Stack now: width height string y1 y2 x1 x2\n\t% Below is a doubly-nested for loop to iterate across this area\n\t% in units of the stipple pattern size, going up columns then\n\t% across rows, blasting out a stipple-pattern-sized rectangle at\n\t% each position\n\t6 index exch {\n\t    2 index 5 index 3 index {\n\t\t% Stack now: width height string y1 y2 x y\n\t\tgsave\n\t\t1 index exch translate\n\t\t5 index 5 index true matrix tmpstip imagemask\n\t\tgrestore\n\t    } for\n\t    pop\n\t} for\n\tpop pop pop pop pop\n    }\n\n    # -- AdjustColor --\n    #\n    # Given a color value already set for output by the caller, adjusts that\n    # value to a grayscale or mono value if requested by the CL variable.\n    ps function AdjustColor {\n\tCL 2 lt {\n\t    currentgray\n\t    CL 0 eq {\n\t\t.5 lt {0} {1} ifelse\n\t    } if\n\t    setgray\n\t} if\n    }\n\n    # x y strings spacing xoffset yoffset justify stipple DrawText --\n    #\n    # This procedure does all of the real work of drawing text. The color and\n    # font must already have been set by the caller, and the following\n    # arguments must be on the stack:\n    #\n    # x, y -\tCoordinates at which to draw text.\n    # strings - An array of strings, one for each line of the text item, in\n    #\t\torder from top to bottom.\n    # spacing -\tSpacing between lines.\n    # xoffset - Horizontal offset for text bbox relative to x and y: 0 for\n    #\t\tnw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se.\n    # yoffset - Vertical offset for text bbox relative to x and y: 0 for\n    #\t\tnw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se.\n    # justify - 0 for left justification, 0.5 for center, 1 for right justify.\n    # stipple - Boolean value indicating whether or not text is to be drawn in\n    #\t\tstippled fashion. If text is stippled, function StippleText\n    #\t\tmust have been defined to call StippleFill in the right way.\n    #\n    # Also, when this procedure is invoked, the color and font must already\n    # have been set for the text.\n    ps function DrawText {\n\t/stipple exch def\n\t/justify exch def\n\t/yoffset exch def\n\t/xoffset exch def\n\t/spacing exch def\n\t/strings exch def\n\t% First scan through all of the text to find the widest line.\n\t/lineLength 0 def\n\tstrings {\n\t    cstringwidth pop\n\t    dup lineLength gt {/lineLength exch def} {pop} ifelse\n\t    newpath\n\t} forall\n\t% Compute the baseline offset and the actual font height.\n\t0 0 moveto baselineSampler false charpath\n\tpathbbox dup /baseline exch def\n\texch pop exch sub /height exch def pop\n\tnewpath\n\t% Translate and rotate coordinates first so that the origin is at\n\t% the upper-left corner of the text's bounding box. Remember that\n\t% angle for rotating, and x and y for positioning are still on the\n\t% stack.\n\ttranslate\n\trotate\n\tlineLength xoffset mul\n\tstrings length 1 sub spacing mul height add yoffset mul translate\n\t% Now use the baseline and justification information to translate\n\t% so that the origin is at the baseline and positioning point for\n\t% the first line of text.\n\tjustify lineLength mul baseline neg translate\n\t% Iterate over each of the lines to output it.  For each line,\n\t% compute its width again so it can be properly justified, then\n\t% display it.\n\tstrings {\n\t    dup cstringwidth pop\n\t    justify neg mul 0 moveto\n\t    stipple {\n\t\t% The text is stippled, so turn it into a path and print\n\t\t% by calling StippledText, which in turn calls\n\t\t% StippleFill. Unfortunately, many Postscript interpreters\n\t\t% will get overflow errors if we try to do the whole\n\t\t% string at once, so do it a character at a time.\n\t\tgsave\n\t\t/char (X) def\n\t\t{\n\t\t    dup type /stringtype eq {\n\t\t\t% This segment is a string.\n\t\t\t{\n\t\t\t    char 0 3 -1 roll put\n\t\t\t    currentpoint\n\t\t\t    gsave\n\t\t\t    char true charpath clip StippleText\n\t\t\t    grestore\n\t\t\t    char stringwidth translate\n\t\t\t    moveto\n\t\t\t} forall\n\t\t    } {\n\t\t\t% This segment is glyph name\n\t\t\t% Temporary override\n\t\t\tcurrentfont /Encoding get exch 1 exch put\n\t\t\tcurrentpoint\n\t\t\tgsave (\\001) true charpath clip StippleText\n\t\t\tgrestore\n\t\t\t(\\001) stringwidth translate\n\t\t\tmoveto\n\t\t    } ifelse\n\t\t} forall\n\t\tgrestore\n\t    } {cstringshow} ifelse\n\t    0 spacing neg translate\n\t} forall\n    }\n\n    # Define the \"TkPhoto\" function variants, which are modified versions\n    # of the original \"transparentimage\" function posted by ian@five-d.com\n    # (Ian Kemmish) to comp.lang.postscript. For a monochrome colorLevel\n    # this is a slightly different version that uses the imagemask command\n    # instead of image.\n\n    ps function TkPhotoColor {\n\tgsave\n\t32 dict begin\n\t/tinteger exch def\n\t/transparent 1 string def\n\ttransparent 0 tinteger put\n\t/olddict exch def\n\tolddict /DataSource get dup type /filetype ne {\n\t    olddict /DataSource 3 -1 roll\n\t    0 () /SubFileDecode filter put\n\t} {\n\t    pop\n\t} ifelse\n\t/newdict olddict maxlength dict def\n\tolddict newdict copy pop\n\t/w newdict /Width get def\n\t/crpp newdict /Decode get length 2 idiv def\n\t/str w string def\n\t/pix w crpp mul string def\n\t/substrlen 2 w log 2 log div floor exp cvi def\n\t/substrs [ {\n\t    substrlen string\n\t    0 1 substrlen 1 sub {\n\t\t1 index exch tinteger put\n\t    } for\n\t    /substrlen substrlen 2 idiv def\n\t    substrlen 0 eq {exit} if\n\t} loop ] def\n\t/h newdict /Height get def\n\t1 w div 1 h div matrix scale\n\tolddict /ImageMatrix get exch matrix concatmatrix\n\tmatrix invertmatrix concat\n\tnewdict /Height 1 put\n\tnewdict /DataSource pix put\n\t/mat [w 0 0 h 0 0] def\n\tnewdict /ImageMatrix mat put\n\t0 1 h 1 sub {\n\t    mat 5 3 -1 roll neg put\n\t    olddict /DataSource get str readstring pop pop\n\t    /tail str def\n\t    /x 0 def\n\t    olddict /DataSource get pix readstring pop pop\n\t    {\n\t\ttail transparent search dup /done exch not def\n\t\t{exch pop exch pop} if\n\t\t/w1 exch length def\n\t\tw1 0 ne {\n\t\t    newdict /DataSource\n\t\t    pix x crpp mul w1 crpp mul getinterval put\n\t\t    newdict /Width w1 put\n\t\t    mat 4 x neg put\n\t\t    /x x w1 add def\n\t\t    newdict image\n\t\t    /tail tail w1 tail length w1 sub getinterval def\n\t\t} if\n\t\tdone {exit} if\n\t\ttail substrs {\n\t\t    anchorsearch {pop} if\n\t\t} forall\n\t\t/tail exch def\n\t\ttail length 0 eq {exit} if\n\t\t/x w tail length sub def\n\t    } loop\n\t} for\n\tend\n\tgrestore\n    }\n    ps function TkPhotoMono {\n\tgsave\n\t32 dict begin\n\t/dummyInteger exch def\n\t/olddict exch def\n\tolddict /DataSource get dup type /filetype ne {\n\t    olddict /DataSource 3 -1 roll\n\t    0 () /SubFileDecode filter put\n\t} {\n\t    pop\n\t} ifelse\n\t/newdict olddict maxlength dict def\n\tolddict newdict copy pop\n\t/w newdict /Width get def\n\t/pix w 7 add 8 idiv string def\n\t/h newdict /Height get def\n\t1 w div 1 h div matrix scale\n\tolddict /ImageMatrix get exch matrix concatmatrix\n\tmatrix invertmatrix concat\n\tnewdict /Height 1 put\n\tnewdict /DataSource pix put\n\t/mat [w 0 0 h 0 0] def\n\tnewdict /ImageMatrix mat put\n\t0 1 h 1 sub {\n\t    mat 5 3 -1 roll neg put\n\t    0.000 0.000 0.000 setrgbcolor\n\t    olddict /DataSource get pix readstring pop pop\n\t    newdict /DataSource pix put\n\t    newdict imagemask\n\t    1.000 1.000 1.000 setrgbcolor\n\t    olddict /DataSource get pix readstring pop pop\n\t    newdict /DataSource pix put\n\t    newdict imagemask\n\t} for\n\tend\n\tgrestore\n    }\n\n    ps literal %%EndProlog\n}\n\nproc tk::ensure_psenc_is_loaded {} {\n}\n"
  },
  {
    "path": "library/msgbox.tcl",
    "content": "# msgbox.tcl --\n#\n#\tImplements messageboxes for platforms that do not have native\n#\tmessagebox support.\n#\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# Ensure existence of ::tk::dialog namespace\n#\nnamespace eval ::tk::dialog {}\n\nimage create bitmap ::tk::dialog::b1 -foreground black \\\n-data \"#define b1_width 32\\n#define b1_height 32\nstatic unsigned char q1_bits[] = {\n   0x00, 0xf8, 0x1f, 0x00, 0x00, 0x07, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x03,\n   0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10,\n   0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40,\n   0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,\n   0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,\n   0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40,\n   0x04, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08,\n   0x60, 0x00, 0x00, 0x04, 0x80, 0x03, 0x80, 0x03, 0x00, 0x0c, 0x78, 0x00,\n   0x00, 0x30, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x40, 0x04, 0x00,\n   0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::b2 -foreground white \\\n-data \"#define b2_width 32\\n#define b2_height 32\nstatic unsigned char b2_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x00,\n   0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f,\n   0xf8, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,\n   0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,\n   0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,\n   0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,\n   0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0x07,\n   0x80, 0xff, 0xff, 0x03, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xf0, 0x07, 0x00,\n   0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00,\n   0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::q -foreground blue \\\n-data \"#define q_width 32\\n#define q_height 32\nstatic unsigned char q_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00,\n   0x00, 0x10, 0x0f, 0x00, 0x00, 0x18, 0x1e, 0x00, 0x00, 0x38, 0x1e, 0x00,\n   0x00, 0x38, 0x1e, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x80, 0x07, 0x00,\n   0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00,\n   0x00, 0xe0, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::i -foreground blue \\\n-data \"#define i_width 32\\n#define i_height 32\nstatic unsigned char i_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0xe0, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00,\n   0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,\n   0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,\n   0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,\n   0x00, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::w1 -foreground black \\\n-data \"#define w1_width 32\\n#define w1_height 32\nstatic unsigned char w1_bits[] = {\n   0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20, 0x04, 0x00,\n   0x00, 0x10, 0x04, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00,\n   0x00, 0x08, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x20, 0x00,\n   0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00,\n   0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01,\n   0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02,\n   0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08,\n   0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x10,\n   0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x40,\n   0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20,\n   0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::w2 -foreground yellow \\\n-data \"#define w2_width 32\\n#define w2_height 32\nstatic unsigned char w2_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00,\n   0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x07, 0x00,\n   0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00,\n   0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x3f, 0x00,\n   0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00,\n   0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x01,\n   0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,\n   0xf0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,\n   0xf8, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x3f,\n   0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\nimage create bitmap ::tk::dialog::w3 -foreground black \\\n-data \"#define w3_width 32\\n#define w3_height 32\nstatic unsigned char w3_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,\n   0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,\n   0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,\n   0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00,\n   0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\"\n\f\n# ::tk::MessageBox --\n#\n#\tPops up a messagebox with an application-supplied message with\n#\tan icon and a list of buttons. This procedure will be called\n#\tby tk_messageBox if the platform does not have native\n#\tmessagebox support, or if the particular type of messagebox is\n#\tnot supported natively.\n#\n#\tColor icons are used on Unix displays that have a color\n#\tdepth of 4 or more and $tk_strictMotif is not on.\n#\n#\tUses ::tk::Priv.${disp}(button) instead of ::tk::Priv(button) to\n#\tavoid adverse effects of [::tk::ScreenChanged]. Bug [e2cec2fa41].\n#\n#\tThis procedure is a private procedure shouldn't be called\n#\tdirectly. Call tk_messageBox instead.\n#\n#\tSee the user documentation for details on what tk_messageBox does.\n#\nproc ::tk::MessageBox {args} {\n    global tk_strictMotif\n    variable ::tk::Priv\n\n    set w ::tk::PrivMsgBox\n    upvar $w data\n\n    #\n    # The default value of the title is space (\" \") not the empty string\n    # because for some window managers, a\n    #\t\twm title .foo \"\"\n    # causes the window title to be \"foo\" instead of the empty string.\n    #\n    set specs {\n\t{-default \"\" \"\" \"\"}\n\t{-detail \"\" \"\" \"\"}\n\t{-icon \"\" \"\" \"info\"}\n\t{-message \"\" \"\" \"\"}\n\t{-parent \"\" \"\" .}\n\t{-title \"\" \"\" \" \"}\n\t{-type \"\" \"\" \"ok\"}\n    }\n\n    tclParseConfigSpec $w $specs \"\" $args\n\n    if {$data(-icon) ni {info warning error question}} {\n\treturn -code error -errorcode [list TK LOOKUP ICON $data(-icon)] \\\n\t    \"bad -icon value \\\"$data(-icon)\\\": must be error, info, question, or warning\"\n    }\n    set windowingsystem [tk windowingsystem]\n    if {$windowingsystem eq \"aqua\"} {\n\tswitch -- $data(-icon) {\n\t    \"error\"     {set data(-icon) \"stop\"}\n\t    \"warning\"   {set data(-icon) \"caution\"}\n\t    \"info\"      {set data(-icon) \"note\"}\n\t}\n    }\n\n    if {![winfo exists $data(-parent)]} {\n\treturn -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \\\n\t    \"bad window path name \\\"$data(-parent)\\\"\"\n    }\n\n    # Select the vwait variable carefully.\n    set oldScreen $Priv(screen)\n    set screen [winfo screen $data(-parent)]\n\n    # Extract the display name (cf. ScreenChanged, including [Bug 2912473] fix).\n    set disp [string range $screen 0 [string last . $screen]-1]\n\n    # Ensure that namespace separators never occur in the display name (as\n    # they cause problems in variable names). Double-colons exist in some VNC\n    # display names. [Bug 2912473]\n    set disp [string map {:: _doublecolon_} $disp]\n\n    if {![info exists ::tk::Priv.${disp}]} {\n\t# Use ScreenChanged to create ::tk::Priv.${disp}, then change back to old\n\t# screen to avoid interfering with Tk expectations for bindings.\n\tScreenChanged $screen\n\tScreenChanged $oldScreen\n    }\n\n    variable ::tk::Priv.${disp}\n    # Now in place of ::tk::Priv(button), use ::tk::Priv.${disp}(button) which\n    # is the intended target variable of upvar and will not be redefined when\n    # ::tk::ScreenChanged is called.\n\n    switch -- $data(-type) {\n\tabortretryignore {\n\t    set names [list abort retry ignore]\n\t    set labels [list &Abort &Retry &Ignore]\n\t    set cancel abort\n\t}\n\tok {\n\t    set names [list ok]\n\t    set labels {&OK}\n\t    set cancel ok\n\t}\n\tokcancel {\n\t    set names [list ok cancel]\n\t    set labels [list &OK &Cancel]\n\t    set cancel cancel\n\t}\n\tretrycancel {\n\t    set names [list retry cancel]\n\t    set labels [list &Retry &Cancel]\n\t    set cancel cancel\n\t}\n\tyesno {\n\t    set names [list yes no]\n\t    set labels [list &Yes &No]\n\t    set cancel no\n\t}\n\tyesnocancel {\n\t    set names [list yes no cancel]\n\t    set labels [list &Yes &No &Cancel]\n\t    set cancel cancel\n\t}\n\tdefault {\n\t    return -code error -errorcode [list TK LOOKUP DLG_TYPE $data(-type)] \\\n\t\t\"bad -type value \\\"$data(-type)\\\": must be\\\n\t\tabortretryignore, ok, okcancel, retrycancel,\\\n\t\tyesno, or yesnocancel\"\n\t}\n    }\n\n    set buttons {}\n    foreach name $names lab $labels {\n\tlappend buttons [list $name -text [mc $lab]]\n    }\n\n    # If no default button was specified, the default default is the\n    # first button (Bug: 2218).\n\n    if {$data(-default) eq \"\"} {\n\tset data(-default) [lindex [lindex $buttons 0] 0]\n    }\n\n    set valid 0\n    foreach btn $buttons {\n\tif {[lindex $btn 0] eq $data(-default)} {\n\t    set valid 1\n\t    break\n\t}\n    }\n    if {!$valid} {\n\treturn -code error -errorcode {TK MSGBOX DEFAULT} \\\n\t    \"bad -default value \\\"$data(-default)\\\": must be\\\n\t    abort, retry, ignore, ok, cancel, no, or yes\"\n    }\n\n    # 2. Set the dialog to be a child window of $parent\n    #\n    #\n    if {$data(-parent) ne \".\"} {\n\tset w $data(-parent).__tk__messagebox\n    } else {\n\tset w .__tk__messagebox\n    }\n\n    # There is only one background colour for the whole dialog\n    set bg [ttk::style lookup . -background]\n\n    # 3. Create the top-level window and divide it into top\n    # and bottom parts.\n\n    catch {destroy $w}\n    toplevel $w -class Dialog -bg $bg\n    wm title $w $data(-title)\n    wm iconname $w Dialog\n    wm protocol $w WM_DELETE_WINDOW [list $w.$cancel invoke]\n\n    # Message boxes should be transient with respect to their parent so that\n    # they always stay on top of the parent window.  But some window managers\n    # will simply create the child window as withdrawn if the parent is not\n    # viewable (because it is withdrawn or iconified).  This is not good for\n    # \"grab\"bed windows.  So only make the message box transient if the parent\n    # is viewable.\n    #\n    if {[winfo viewable [winfo toplevel $data(-parent)]] } {\n\twm transient $w $data(-parent)\n    }\n\n    if {$windowingsystem eq \"aqua\"} {\n\t::tk::unsupported::MacWindowStyle style $w moveableModal {}\n    } elseif {$windowingsystem eq \"x11\"} {\n\twm attributes $w -type dialog\n    }\n\n    ttk::frame $w.bot\n    grid anchor $w.bot center\n    pack $w.bot -side bottom -fill both\n    ttk::frame $w.top\n    pack $w.top -side top -fill both -expand 1\n\n    # 4. Fill the top part with bitmap, message and detail (use the\n    # option database for -wraplength and -font so that they can be\n    # overridden by the caller).\n\n    option add *Dialog.msg.wrapLength 3i widgetDefault\n    option add *Dialog.dtl.wrapLength 3i widgetDefault\n    option add *Dialog.msg.font TkCaptionFont widgetDefault\n    option add *Dialog.dtl.font TkDefaultFont widgetDefault\n\n    ttk::label $w.msg -anchor nw -justify left -text $data(-message)\n    if {$data(-detail) ne \"\"} {\n\tttk::label $w.dtl -anchor nw -justify left -text $data(-detail)\n    }\n    if {$data(-icon) ne \"\"} {\n\tif {([winfo depth $w] < 4) || $tk_strictMotif} {\n\t    # ttk::label has no -bitmap option\n\t    label $w.bitmap -bitmap $data(-icon) -background $bg\n\t} else {\n\t    switch $data(-icon) {\n\t\terror {\n\t\t    ttk::label $w.bitmap -image ::tk::icons::error\n\t\t}\n\t\tinfo {\n\t\t    ttk::label $w.bitmap -image ::tk::icons::information\n\t\t}\n\t\tquestion {\n\t\t    ttk::label $w.bitmap -image ::tk::icons::question\n\t\t}\n\t\tdefault {\n\t\t    ttk::label $w.bitmap -image ::tk::icons::warning\n\t\t}\n\t    }\n\t}\n    }\n    grid $w.bitmap $w.msg -in $w.top -sticky news -padx 2m -pady 2m\n    grid configure $w.bitmap -sticky nw\n    grid columnconfigure $w.top 1 -weight 1\n    if {$data(-detail) ne \"\"} {\n\tgrid ^ $w.dtl -in $w.top -sticky news -padx 2m -pady {0 2m}\n\tgrid rowconfigure $w.top 1 -weight 1\n    } else {\n\tgrid rowconfigure $w.top 0 -weight 1\n    }\n\n    # 5. Create a row of buttons at the bottom of the dialog.\n\n    set i 0\n    foreach but $buttons {\n\tset name [lindex $but 0]\n\tset opts [lrange $but 1 end]\n\tif {![llength $opts]} {\n\t    # Capitalize the first letter of $name\n\t    set capName [string toupper $name 0]\n\t    set opts [list -text $capName]\n\t}\n\n\teval [list tk::AmpWidget ttk::button $w.$name] $opts \\\n\t\t[list -command [list set tk::Priv.${disp}(button) $name]]\n\n\tif {$name eq $data(-default)} {\n\t    $w.$name configure -default active\n\t} else {\n\t    $w.$name configure -default normal\n\t}\n\tgrid $w.$name -in $w.bot -row 0 -column $i -padx 3m -pady 2m -sticky ew\n\tgrid columnconfigure $w.bot $i -uniform buttons\n\t# We boost the size of some Mac buttons for l&f\n\tif {$windowingsystem eq \"aqua\"} {\n\t    set tmp [string tolower $name]\n\t    if {$tmp eq \"ok\" || $tmp eq \"cancel\" || $tmp eq \"yes\" ||\n\t\t    $tmp eq \"no\" || $tmp eq \"abort\" || $tmp eq \"retry\" ||\n\t\t    $tmp eq \"ignore\"} {\n\t\tgrid columnconfigure $w.bot $i -minsize 90\n\t    }\n\t    grid configure $w.$name -pady 7\n\t}\n\tincr i\n\n\t# create the binding for the key accelerator, based on the underline\n\t#\n\t# set underIdx [$w.$name cget -under]\n\t# if {$underIdx >= 0} {\n\t#     set key [string index [$w.$name cget -text] $underIdx]\n\t#     bind $w <Alt-[string tolower $key]>  [list $w.$name invoke]\n\t#     bind $w <Alt-[string toupper $key]>  [list $w.$name invoke]\n\t# }\n    }\n    bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]\n\n    if {$data(-default) ne \"\"} {\n\tbind $w <FocusIn> {\n\t    if {[winfo class %W] in \"Button TButton\"} {\n\t\t%W configure -default active\n\t    }\n\t}\n\tbind $w <FocusOut> {\n\t    if {[winfo class %W] in \"Button TButton\"} {\n\t\t%W configure -default normal\n\t    }\n\t}\n    }\n\n    # 6. Create bindings for <Return>, <Escape> and <Destroy> on the dialog\n\n    bind $w <Return> {\n\tif {[winfo class %W] in \"Button TButton\"} {\n\t    %W invoke\n\t}\n    }\n\n    # Invoke the designated cancelling operation\n    bind $w <Escape> [list $w.$cancel invoke]\n\n    # At <Destroy> the buttons have vanished, so must do this directly.\n    bind $w.msg <Destroy> [list set tk::Priv.${disp}(button) $cancel]\n\n    # 7. Limit window width by that of physical screen.\n    # On small screens the message widget's width may exceed the screen's\n    # width.  In this case, change the message label's wrap length so the\n    # window fits on the physical screen. Tk Ticket e19f1d89\n    set frameWidth [::tk::WMFrameWidth]\n    wm withdraw $w\n    update idletasks\n    if {[winfo reqwidth $w] + 2*$frameWidth > [winfo screenwidth $w]} {\n\t# Calculate the wrap length as the screen width minus the\n\t# width requested by the dialog without the message label and\n\t# window decoration frame\n\tset wraplength [expr {[winfo screenwidth $w] - 2*$frameWidth\n\t\t- ([winfo reqwidth $w] - [winfo reqwidth $w.msg])}]\n\t# Make sure that the wrap length is no less than the width\n\t# of 20 average-size characters in the message label's font\n\tset msgFont [$w.msg cget -font]\n\tset str [string repeat \"0\" 20]\n\tset minWraplength [font measure $msgFont -displayof $w $str]\n\tif {$wraplength < $minWraplength} {\t;# this is rather unprobable\n\t    set wraplength $minWraplength\n\t}\n\t# Apply the wrap length\n\t$w.msg configure -wraplength $wraplength\n\tif {[winfo exists $w.dtl]} {\n\t    $w.dtl configure -wraplength $wraplength\n\t}\n    }\n\n    # 8. Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w widget $data(-parent)\n\n    # 9. Set a grab and claim the focus too.\n\n    if {$data(-default) ne \"\"} {\n\tset focus $w.$data(-default)\n    } else {\n\tset focus $w\n    }\n    ::tk::SetFocusGrab $w $focus\n\n    # 10. Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait ::tk::Priv.${disp}(button)\n    # Copy the result now so any <Destroy> that happens won't cause\n    # trouble\n    set result [set Priv.${disp}(button)]\n\n    ::tk::RestoreFocusGrab $w $focus\n\n    return $result\n}\n"
  },
  {
    "path": "library/msgs/cs.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset cs \"&Abort\" \"&Přerušit\"\n    ::msgcat::mcset cs \"&About...\" \"&O programu...\"\n    ::msgcat::mcset cs \"All Files\" \"Všechny soubory\"\n    ::msgcat::mcset cs \"Application Error\" \"Chyba programu\"\n    ::msgcat::mcset cs \"Bold Italic\"\n    ::msgcat::mcset cs \"&Blue\" \"&Modá\"\n    ::msgcat::mcset cs \"Cancel\" \"Zrušit\"\n    ::msgcat::mcset cs \"&Cancel\" \"&Zrušit\"\n    ::msgcat::mcset cs \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Nemohu změnit atkálí adreář na \\\"%1\\$s\\\".\\nPístup odítnut.\"\n    ::msgcat::mcset cs \"Choose Directory\" \"ýběr adreáře\"\n    ::msgcat::mcset cs \"Cl&ear\" \"Sma&zat\"\n    ::msgcat::mcset cs \"&Clear Console\" \"&Smazat konzolu\"\n    ::msgcat::mcset cs \"Color\" \"Barva\"\n    ::msgcat::mcset cs \"Console\" \"Konzole\"\n    ::msgcat::mcset cs \"&Copy\" \"&Koírovat\"\n    ::msgcat::mcset cs \"Cu&t\" \"V&yíznout\"\n    ::msgcat::mcset cs \"&Delete\" \"&Smazat\"\n    ::msgcat::mcset cs \"Details >>\" \"Detaily >>\"\n    ::msgcat::mcset cs \"Directory \\\"%1\\$s\\\" does not exist.\" \"Adreář \\\"%1\\$s\\\" neexistuje.\"\n    ::msgcat::mcset cs \"&Directory:\" \"&Adreář:\"\n    ::msgcat::mcset cs \"&Edit\" \"Úpravy\"\n    ::msgcat::mcset cs \"Error: %1\\$s\" \"Chyba: %1\\$s\"\n    ::msgcat::mcset cs \"E&xit\" \"&Konec\"\n    ::msgcat::mcset cs \"&File\" \"&Soubor\"\n    ::msgcat::mcset cs \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Soubor \\\"%1\\$s\\\" již existuje.\\nChcete jej přepsat?\"\n    ::msgcat::mcset cs \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Soubor \\\"%1\\$s\\\" již existuje.\\n\\n\"\n    ::msgcat::mcset cs \"File \\\"%1\\$s\\\" does not exist.\" \"Soubor \\\"%1\\$s\\\" neexistuje.\"\n    ::msgcat::mcset cs \"File &name:\" \"&Jéno souboru:\"\n    ::msgcat::mcset cs \"File &names:\" \"&Jéna souborů:\"\n    ::msgcat::mcset cs \"Files of &type:\" \"&Typy souborů:\"\n    ::msgcat::mcset cs \"Fi&les:\" \"Sou&bory:\"\n    ::msgcat::mcset cs \"&Filter\" \"&Filtr\"\n    ::msgcat::mcset cs \"Fil&ter:\" \"Fil&tr:\"\n    ::msgcat::mcset cs \"Font st&yle:\"\n    ::msgcat::mcset cs \"&Green\" \"Ze&leá\"\n    ::msgcat::mcset cs \"&Help\" \"&ápověda\"\n    ::msgcat::mcset cs \"Hi\" \"Ahoj\"\n    ::msgcat::mcset cs \"&Hide Console\" \"&Schovat Konzolu\"\n    ::msgcat::mcset cs \"&Ignore\" \"&Ignorovat\"\n    ::msgcat::mcset cs \"Invalid file name \\\"%1\\$s\\\".\" \"Špaté jéno souboru \\\"%1\\$s\\\".\"\n    ::msgcat::mcset cs \"Log Files\" \"Log soubory\"\n    ::msgcat::mcset cs \"&No\" \"&Ne\"\n    ::msgcat::mcset cs \"&OK\"\n    ::msgcat::mcset cs \"OK\"\n    ::msgcat::mcset cs \"Ok\"\n    ::msgcat::mcset cs \"Open\" \"Otevít\"\n    ::msgcat::mcset cs \"&Open\" \"&Otevít\"\n    ::msgcat::mcset cs \"Open Multiple Files\" \"Otevít íce souborů\"\n    ::msgcat::mcset cs \"P&aste\" \"&Vložit\"\n    ::msgcat::mcset cs \"&Quit\" \"&Ukončit\"\n    ::msgcat::mcset cs \"&Red\" \"Če&rveá\"\n    ::msgcat::mcset cs \"Replace existing file?\" \"Nahradit sávaíí soubor?\"\n    ::msgcat::mcset cs \"&Retry\" \"Z&novu\"\n    ::msgcat::mcset cs \"&Save\" \"&Uložit\"\n    ::msgcat::mcset cs \"Save As\" \"Uložit jako\"\n    ::msgcat::mcset cs \"Save To Log\" \"Uložit do logu\"\n    ::msgcat::mcset cs \"Select Log File\" \"Vybrat log soubor\"\n    ::msgcat::mcset cs \"Select a file to source\" \"Vybrat soubor k naháí\"\n    ::msgcat::mcset cs \"&Selection:\" \"&ýběr:\"\n    ::msgcat::mcset cs \"Skip Messages\" \"Přeskočit zpávy\"\n    ::msgcat::mcset cs \"&Source...\" \"&Zdroj...\"\n    ::msgcat::mcset cs \"Tcl Scripts\" \"Tcl skripty\"\n    ::msgcat::mcset cs \"Tcl for Windows\" \"Tcl pro Windows\"\n    ::msgcat::mcset cs \"Text Files\" \"Textoé soubory\"\n    ::msgcat::mcset cs \"abort\" \"přerušit\"\n    ::msgcat::mcset cs \"blue\" \"modá\"\n    ::msgcat::mcset cs \"cancel\" \"zrušit\"\n    ::msgcat::mcset cs \"extension\" \"pípona\"\n    ::msgcat::mcset cs \"extensions\" \"pípony\"\n    ::msgcat::mcset cs \"green\" \"zeleá\"\n    ::msgcat::mcset cs \"ignore\" \"ignorovat\"\n    ::msgcat::mcset cs \"ok\"\n    ::msgcat::mcset cs \"red\" \"červeá\"\n    ::msgcat::mcset cs \"retry\" \"znovu\"\n    ::msgcat::mcset cs \"yes\" \"ano\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  cs \"Print\" \"Tisknout\"\n    ::msgcat::mcset  cs \"Printer\" \"Tiskárna\"\n    ::msgcat::mcset  cs \"Letter \" \"Dopis \"\n    ::msgcat::mcset  cs \"Legal \" \"Legální \"\n    ::msgcat::mcset  cs \"A4\" \"A4\"\n    ::msgcat::mcset  cs \"Grayscale\" \"Stupně Šedi\"\n    ::msgcat::mcset  cs \"RGB\" \"RGB\"\n    ::msgcat::mcset  cs \"Options\" \"Možnosti\"\n    ::msgcat::mcset  cs \"Copies\" \"Kopie\"\n    ::msgcat::mcset  cs \"Paper\" \"Papír\"\n    ::msgcat::mcset  cs \"Scale\" \"Škála\"\n    ::msgcat::mcset  cs \"Orientation\" \"Orientace\"\n    ::msgcat::mcset  cs \"Portrait\" \"Portrét\"\n    ::msgcat::mcset  cs \"Landscape\" \"Krajina\"\n    ::msgcat::mcset  cs \"Output\" \"Výstup\"\n}"
  },
  {
    "path": "library/msgs/da.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset da \"&Abort\" \"&Afbryd\"\n    ::msgcat::mcset da \"&About...\" \"&Om...\"\n    ::msgcat::mcset da \"All Files\" \"Alle filer\"\n    ::msgcat::mcset da \"Application Error\" \"Programfejl\"\n    ::msgcat::mcset da \"&Blue\" \"&Blå\"\n    ::msgcat::mcset da \"Cancel\" \"Annuller\"\n    ::msgcat::mcset da \"&Cancel\" \"&Annuller\"\n    ::msgcat::mcset da \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Kan ikke skifte til katalog \\\"%1\\$s\\\".\\nIngen rettigheder.\"\n    ::msgcat::mcset da \"Choose Directory\" \"Vælg katalog\"\n    ::msgcat::mcset da \"Cl&ear\" \"&Ryd\"\n    ::msgcat::mcset da \"&Clear Console\" \"&Ryd konsolen\"\n    ::msgcat::mcset da \"Color\" \"Farve\"\n    ::msgcat::mcset da \"Console\" \"Konsol\"\n    ::msgcat::mcset da \"&Copy\" \"&Kopier\"\n    ::msgcat::mcset da \"Cu&t\" \"Kli&p\"\n    ::msgcat::mcset da \"&Delete\" \"&Slet\"\n    ::msgcat::mcset da \"Details >>\" \"Detailer\"\n    ::msgcat::mcset da \"Directory \\\"%1\\$s\\\" does not exist.\" \"Katalog \\\"%1\\$s\\\" findes ikke.\"\n    ::msgcat::mcset da \"&Directory:\" \"&Katalog:\"\n    ::msgcat::mcset da \"&Edit\" \"&Rediger\"\n    ::msgcat::mcset da \"Error: %1\\$s\" \"Fejl: %1\\$s\"\n    ::msgcat::mcset da \"E&xit\" \"&Afslut\"\n    ::msgcat::mcset da \"&File\" \"&Fil\"\n    ::msgcat::mcset da \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Filen \\\"%1\\$s\\\" findes allerede.\\nSkal den overskrives?\"\n    ::msgcat::mcset da \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Filen \\\"%1\\$s\\\" findes allerede.\\n\\n\"\n    ::msgcat::mcset da \"File \\\"%1\\$s\\\" does not exist.\" \"Filen \\\"%1\\$s\\\" findes ikke.\"\n    ::msgcat::mcset da \"File &name:\" \"Fil&navn:\"\n    ::msgcat::mcset da \"File &names:\" \"Fil&navne:\"\n    ::msgcat::mcset da \"Files of &type:\" \"Fil&typer:\"\n    ::msgcat::mcset da \"Fi&les:\" \"Fi&ler:\"\n    ::msgcat::mcset da \"&Filter\"\n    ::msgcat::mcset da \"Fil&ter:\"\n    ::msgcat::mcset da \"&Green\" \"&Grøn\"\n    ::msgcat::mcset da \"&Help\" \"&Hjælp\"\n    ::msgcat::mcset da \"Hi\" \"Hej\"\n    ::msgcat::mcset da \"&Hide Console\" \"Skjul &konsol\"\n    ::msgcat::mcset da \"&Ignore\" \"&Ignorer\"\n    ::msgcat::mcset da \"Invalid file name \\\"%1\\$s\\\".\" \"Ugyldig fil navn \\\"%1\\$s\\\".\"\n    ::msgcat::mcset da \"Log Files\" \"Logfiler\"\n    ::msgcat::mcset da \"&No\" \"&Nej\"\n    ::msgcat::mcset da \"&OK\" \"&O.K.\"\n    ::msgcat::mcset da \"OK\" \"O.K.\"\n    ::msgcat::mcset da \"Ok\"\n    ::msgcat::mcset da \"Open\" \"Åbn\"\n    ::msgcat::mcset da \"&Open\" \"&Åbn\"\n    ::msgcat::mcset da \"Open Multiple Files\" \"Åbn flere filer\"\n    ::msgcat::mcset da \"P&aste\" \"&Indsæt\"\n    ::msgcat::mcset da \"&Quit\" \"&Afslut\"\n    ::msgcat::mcset da \"&Red\" \"&Rød\"\n    ::msgcat::mcset da \"Replace existing file?\" \"Erstat eksisterende fil?\"\n    ::msgcat::mcset da \"&Retry\" \"&Gentag\"\n    ::msgcat::mcset da \"&Save\" \"&Gem\"\n    ::msgcat::mcset da \"Save As\" \"Gem som\"\n    ::msgcat::mcset da \"Save To Log\" \"Gem i log\"\n    ::msgcat::mcset da \"Select Log File\" \"Vælg logfil\"\n    ::msgcat::mcset da \"Select a file to source\" \"Vælg kørbar fil\"\n    ::msgcat::mcset da \"&Selection:\" \"&Udvalg:\"\n    ::msgcat::mcset da \"Show &Hidden Directories\" \"Vis &skjulte kataloger\"\n    ::msgcat::mcset da \"Show &Hidden Files and Directories\" \"Vis &skjulte filer og kataloger\"\n    ::msgcat::mcset da \"Skip Messages\" \"Overspring beskeder\"\n    ::msgcat::mcset da \"&Source...\" \"&Kør...\"\n    ::msgcat::mcset da \"Tcl Scripts\" \"Tcl-Skripter\"\n    ::msgcat::mcset da \"Tcl for Windows\" \"Tcl for Windows\"\n    ::msgcat::mcset da \"Text Files\" \"Tekstfiler\"\n    ::msgcat::mcset da \"&Yes\" \"&Ja\"\n    ::msgcat::mcset da \"abort\" \"afbryd\"\n    ::msgcat::mcset da \"blue\" \"blå\"\n    ::msgcat::mcset da \"cancel\" \"afbryd\"\n    ::msgcat::mcset da \"extension\"\n    ::msgcat::mcset da \"extensions\"\n    ::msgcat::mcset da \"green\" \"grøn\"\n    ::msgcat::mcset da \"ignore\" \"ignorer\"\n    ::msgcat::mcset da \"ok\"\n    ::msgcat::mcset da \"red\" \"rød\"\n    ::msgcat::mcset da \"retry\" \"gentag\"\n    ::msgcat::mcset da \"yes\" \"ja\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  da \"Print\" \"Trykke\"\n    ::msgcat::mcset  da \"Printer\" \"Printer\"\n    ::msgcat::mcset  da \"Letter \" \"Brev\"\n    ::msgcat::mcset  da \"Legal \" \"Juridisk\"\n    ::msgcat::mcset  da \"A4\" \"A4\"\n    ::msgcat::mcset  da \"Grayscale\" \"Gråtoneskala\"\n    ::msgcat::mcset  da \"RGB\" \"Rgb\"\n    ::msgcat::mcset  da \"Options\" \"Indstillinger\"\n    ::msgcat::mcset  da \"Copies\" \"Kopier\"\n    ::msgcat::mcset  da \"Paper\" \"Papir\"\n    ::msgcat::mcset  da \"Scale\" \"Skalere\"\n    ::msgcat::mcset  da \"Orientation\" \"Orientering\"\n    ::msgcat::mcset  da \"Portrait\" \"Portræt\"\n    ::msgcat::mcset  da \"Landscape\" \"Landskab\"\n    ::msgcat::mcset  da \"Output\" \"Udskriv Publikation\"\n}"
  },
  {
    "path": "library/msgs/de.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset de \"&Abort\" \"&Abbruch\"\n    ::msgcat::mcset de \"&About...\" \"&Über...\"\n    ::msgcat::mcset de \"All Files\" \"Alle Dateien\"\n    ::msgcat::mcset de \"Application Error\" \"Applikationsfehler\"\n    ::msgcat::mcset de \"&Apply\" \"&Anwenden\"\n    ::msgcat::mcset de \"Bold\" \"Fett\"\n    ::msgcat::mcset de \"Bold Italic\" \"Fett kursiv\"\n    ::msgcat::mcset de \"&Blue\" \"&Blau\"\n    ::msgcat::mcset de \"Cancel\" \"Abbruch\"\n    ::msgcat::mcset de \"&Cancel\" \"&Abbruch\"\n    ::msgcat::mcset de \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Kann nicht in das Verzeichnis \\\"%1\\$s\\\" wechseln.\\nKeine Rechte vorhanden.\"\n    ::msgcat::mcset de \"Choose Directory\" \"Wähle Verzeichnis\"\n    ::msgcat::mcset de \"Cl&ear\" \"&Rücksetzen\"\n    ::msgcat::mcset de \"&Clear Console\" \"&Konsole löschen\"\n    ::msgcat::mcset de \"Color\" \"Farbe\"\n    ::msgcat::mcset de \"Console\" \"Konsole\"\n    ::msgcat::mcset de \"&Copy\" \"&Kopieren\"\n    ::msgcat::mcset de \"Cu&t\" \"Aus&schneiden\"\n    ::msgcat::mcset de \"&Delete\" \"&Löschen\"\n    ::msgcat::mcset de \"Details >>\"\n    ::msgcat::mcset de \"Directory \\\"%1\\$s\\\" does not exist.\" \"Das Verzeichnis \\\"%1\\$s\\\" existiert nicht.\"\n    ::msgcat::mcset de \"&Directory:\" \"&Verzeichnis:\"\n    ::msgcat::mcset de \"&Edit\" \"&Bearbeiten\"\n    ::msgcat::mcset de \"Effects\" \"Effekte\"\n    ::msgcat::mcset de \"Error: %1\\$s\" \"Fehler: %1\\$s\"\n    ::msgcat::mcset de \"E&xit\" \"&Ende\"\n    ::msgcat::mcset de \"&File\" \"&Datei\"\n    ::msgcat::mcset de \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Die Datei \\\"%1\\$s\\\" ist bereits vorhanden.\\nWollen sie diese Datei überschreiben ?\"\n    ::msgcat::mcset de \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Die Datei \\\"%1\\$s\\\" ist bereits vorhanden.\\n\\n\"\n    ::msgcat::mcset de \"File \\\"%1\\$s\\\" does not exist.\" \"Die Datei \\\"%1\\$s\\\" existiert nicht.\"\n    ::msgcat::mcset de \"File &name:\" \"Datei&name:\"\n    ::msgcat::mcset de \"File &names:\" \"Datei&namen:\"\n    ::msgcat::mcset de \"Files of &type:\" \"Dateien des &Typs:\"\n    ::msgcat::mcset de \"Fi&les:\" \"Dat&eien:\"\n    ::msgcat::mcset de \"&Filter\"\n    ::msgcat::mcset de \"Fil&ter:\"\n    ::msgcat::mcset de \"Font\" \"Schriftart\"\n    ::msgcat::mcset de \"&Font:\" \"Schriftart:\"\n    ::msgcat::mcset de \"Font st&yle:\" \"Schriftschnitt:\"\n    ::msgcat::mcset de \"&Green\" \"&Grün\"\n    ::msgcat::mcset de \"&Help\" \"&Hilfe\"\n    ::msgcat::mcset de \"Hi\" \"Hallo\"\n    ::msgcat::mcset de \"&Hide Console\" \"&Konsole unsichtbar machen\"\n    ::msgcat::mcset de \"&Ignore\" \"&Ignorieren\"\n    ::msgcat::mcset de \"Invalid file name \\\"%1\\$s\\\".\" \"Ungültiger Dateiname \\\"%1\\$s\\\".\"\n    ::msgcat::mcset de \"Italic\" \"Kursiv\"\n    ::msgcat::mcset de \"Log Files\" \"Protokolldatei\"\n    ::msgcat::mcset de \"&No\" \"&Nein\"\n    ::msgcat::mcset de \"&OK\"\n    ::msgcat::mcset de \"OK\"\n    ::msgcat::mcset de \"Ok\"\n    ::msgcat::mcset de \"Open\" \"Öffnen\"\n    ::msgcat::mcset de \"&Open\" \"Ö&ffnen\"\n    ::msgcat::mcset de \"Open Multiple Files\" \"Mehrere Dateien Öffnen\"\n    ::msgcat::mcset de \"P&aste\" \"E&infügen\"\n    ::msgcat::mcset de \"&Quit\" \"&Beenden\"\n    ::msgcat::mcset de \"&Red\" \"&Rot\"\n    ::msgcat::mcset de \"Regular\" \"Standard\"\n    ::msgcat::mcset de \"Replace existing file?\" \"Existierende Datei ersetzen?\"\n    ::msgcat::mcset de \"&Retry\" \"&Wiederholen\"\n    ::msgcat::mcset de \"Sample\" \"Beispiel\"\n    ::msgcat::mcset de \"&Save\" \"&Speichern\"\n    ::msgcat::mcset de \"Save As\" \"Speichern unter\"\n    ::msgcat::mcset de \"Save To Log\" \"In Protokoll speichern\"\n    ::msgcat::mcset de \"Select Log File\" \"Protokolldatei auswählen\"\n    ::msgcat::mcset de \"Select a file to source\" \"Auszuführende Datei auswählen\"\n    ::msgcat::mcset de \"&Selection:\" \"Auswah&l:\"\n    ::msgcat::mcset de \"&Size:\" \"Schriftgrad:\"\n    ::msgcat::mcset de \"Show &Hidden Directories\" \"Zeige versteckte Dateien\"\n    ::msgcat::mcset de \"Show &Hidden Files and Directories\" \"Zeige versteckte Dateien und Verzeichnisse\"\n    ::msgcat::mcset de \"Skip Messages\" \"Weitere Nachrichten überspringen\"\n    ::msgcat::mcset de \"&Source...\" \"&Ausführen...\"\n    ::msgcat::mcset de \"Stri&keout\" \"&Durchgestrichen\"\n    ::msgcat::mcset de \"Tcl Scripts\" \"Tcl-Skripte\"\n    ::msgcat::mcset de \"Tcl for Windows\" \"Tcl für Windows\"\n    ::msgcat::mcset de \"Text Files\" \"Textdateien\"\n    ::msgcat::mcset de \"&Underline\" \"&Unterstrichen\"\n    ::msgcat::mcset de \"&Yes\" \"&Ja\"\n    ::msgcat::mcset de \"abort\" \"abbrechen\"\n    ::msgcat::mcset de \"blue\" \"blau\"\n    ::msgcat::mcset de \"cancel\" \"abbrechen\"\n    ::msgcat::mcset de \"extension\" \"Erweiterung\"\n    ::msgcat::mcset de \"extensions\" \"Erweiterungen\"\n    ::msgcat::mcset de \"green\" \"grün\"\n    ::msgcat::mcset de \"ignore\" \"ignorieren\"\n    ::msgcat::mcset de \"ok\"\n    ::msgcat::mcset de \"red\" \"rot\"\n    ::msgcat::mcset de \"retry\" \"wiederholen\"\n    ::msgcat::mcset de \"yes\" \"ja\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  de \"Print\" \"Drucken\"\n    ::msgcat::mcset  de \"Printer\" \"Drucker\"\n    ::msgcat::mcset  de \"Letter \" \"Letter\"\n    ::msgcat::mcset  de \"Legal \" \"Legal\"\n    ::msgcat::mcset  de \"A4\" \"A4\"\n    ::msgcat::mcset  de \"Grayscale\" \"Graustufen\"\n    ::msgcat::mcset  de \"RGB\" \"RGB\"\n    ::msgcat::mcset  de \"Options\" \"Optionen\"\n    ::msgcat::mcset  de \"Copies\" \"Kopien\"\n    ::msgcat::mcset  de \"Paper\" \"Papier\"\n    ::msgcat::mcset  de \"Scale\" \"Skalierung\"\n    ::msgcat::mcset  de \"Orientation\" \"Ausrichtung\"\n    ::msgcat::mcset  de \"Portrait\" \"Hochformat\"\n    ::msgcat::mcset  de \"Landscape\" \"Querformat\"\n    ::msgcat::mcset  de \"Output\" \"Ausgabe\"\n}\n"
  },
  {
    "path": "library/msgs/el.msg",
    "content": "## Messages for the Greek (Hellenic - \"el\") language.\n## Please report any changes/suggestions to:\n##    petasis@iit.demokritos.gr\n\nnamespace eval ::tk {\n    ::msgcat::mcset el \"&Abort\"              \"Τερματισμός\"\n    ::msgcat::mcset el \"About...\"           \"Σχετικά...\"\n    ::msgcat::mcset el \"All Files\"          \"Όλα τα Αρχεία\"\n    ::msgcat::mcset el \"Application Error\"  \"Λάθος Εφαρμογής\"\n    ::msgcat::mcset el \"&Blue\"               \"Μπλε\"\n    ::msgcat::mcset el \"&Cancel\"             \"Ακύρωση\"\n    ::msgcat::mcset el \\\n\"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \\\n\"Δεν είναι δυνατή η αλλαγή καταλόγου σε \\\"%1\\$s\\\".\\nΗ πρόσβαση δεν επιτρέπεται.\"\n    ::msgcat::mcset el \"Choose Directory\"   \"Επιλογή Καταλόγου\"\n    ::msgcat::mcset el \"Clear\"              \"Καθαρισμός\"\n    ::msgcat::mcset el \"Color\"              \"Χρώμα\"\n    ::msgcat::mcset el \"Console\"            \"Κονσόλα\"\n    ::msgcat::mcset el \"Copy\"               \"Αντιγραφή\"\n    ::msgcat::mcset el \"Cut\"                \"Αποκοπή\"\n    ::msgcat::mcset el \"Delete\"             \"Διαγραφή\"\n    ::msgcat::mcset el \"Details >>\"         \"Λεπτομέρειες >>\"\n    ::msgcat::mcset el \"Directory \\\"%1\\$s\\\" does not exist.\" \\\n\t\t\t\t\t\"Ο κατάλογος \\\"%1\\$s\\\" δεν υπάρχει.\"\n    ::msgcat::mcset el \"&Directory:\"         \"&Κατάλογος:\"\n    ::msgcat::mcset el \"Error: %1\\$s\"       \"Λάθος: %1\\$s\"\n    ::msgcat::mcset el \"Exit\"               \"Έξοδος\"\n    ::msgcat::mcset el \\\n\t       \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \\\n\t       \"Το αρχείο \\\"%1\\$s\\\" ήδη υπάρχει.\\nΘέλετε να επικαλυφθεί;\"\n    ::msgcat::mcset el \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \\\n\t\t   \"Το αρχείο \\\"%1\\$s\\\" ήδη υπάρχει.\\n\\n\"\n    ::msgcat::mcset el \"File \\\"%1\\$s\\\" does not exist.\" \\\n\t\t   \"Το αρχείο \\\"%1\\$s\\\" δεν υπάρχει.\"\n    ::msgcat::mcset el \"File &name:\"         \"Ό&νομα αρχείου:\"\n    ::msgcat::mcset el \"File &names:\"        \"Ό&νομα αρχείων:\"\n    ::msgcat::mcset el \"Files of &type:\"     \"Αρχεία του &τύπου:\"\n    ::msgcat::mcset el \"Fi&les:\"             \"Αρχεία:\"\n    ::msgcat::mcset el \"&Filter\"             \"Φίλτρο\"\n    ::msgcat::mcset el \"Fil&ter:\"            \"Φίλτρο:\"\n    ::msgcat::mcset el \"&Green\"              \"Πράσινο\"\n    ::msgcat::mcset el \"Hi\"                 \"Γεια\"\n    ::msgcat::mcset el \"Hide Console\"       \"Απόκρυψη κονσόλας\"\n    ::msgcat::mcset el \"&Ignore\"             \"Αγνόηση\"\n    ::msgcat::mcset el \"Invalid file name \\\"%1\\$s\\\".\" \\\n\t\t   \"Άκυρο όνομα αρχείου \\\"%1\\$s\\\".\"\n    ::msgcat::mcset el \"Log Files\"          \"Αρχεία Καταγραφής\"\n    ::msgcat::mcset el \"&No\"                 \"Όχι\"\n    ::msgcat::mcset el \"&OK\"                 \"Εντάξει\"\n    ::msgcat::mcset el \"OK\"                 \"Εντάξει\"\n    ::msgcat::mcset el \"Ok\"                 \"Εντάξει\"\n    ::msgcat::mcset el \"Open\"               \"Άνοιγμα\"\n    ::msgcat::mcset el \"&Open\"               \"Άνοιγμα\"\n    ::msgcat::mcset el \"Open Multiple Files\" \\\n\t\t\t\t\t\"Άνοιγμα πολλαπλών αρχείων\"\n    ::msgcat::mcset el \"P&aste\"              \"Επικόλληση\"\n    ::msgcat::mcset el \"Quit\"               \"Έξοδος\"\n    ::msgcat::mcset el \"&Red\"                \"Κόκκινο\"\n    ::msgcat::mcset el \"Replace existing file?\" \\\n\t\t\t\t\t\"Επικάλυψη υπάρχοντος αρχείου;\"\n    ::msgcat::mcset el \"&Retry\"              \"Προσπάθησε ξανά\"\n    ::msgcat::mcset el \"&Save\"               \"Αποθήκευση\"\n    ::msgcat::mcset el \"Save As\"            \"Αποθήκευση σαν\"\n    ::msgcat::mcset el \"Save To Log\"        \"Αποθήκευση στο αρχείο καταγραφής\"\n    ::msgcat::mcset el \"Select Log File\"    \"Επιλογή αρχείου καταγραφής\"\n    ::msgcat::mcset el \"Select a file to source\" \\\n\t\t\t\t\t\"Επιλέξτε αρχείο για εκτέλεση\"\n    ::msgcat::mcset el \"&Selection:\"         \"Επιλογή:\"\n    ::msgcat::mcset el \"Skip Messages\"      \"Αποφυγήμηνυμάτων\"\n    ::msgcat::mcset el \"&Source...\"          \"Εκτέλεση...\"\n    ::msgcat::mcset el \"Tcl Scripts\"        \"Tcl Scripts\"\n    ::msgcat::mcset el \"Tcl for Windows\"    \"Tcl για Windows\"\n    ::msgcat::mcset el \"Text Files\"         \"Αρχεία Κειμένου\"\n    ::msgcat::mcset el \"&Yes\"                \"Ναι\"\n    ::msgcat::mcset el \"abort\"              \"τερματισμός\"\n    ::msgcat::mcset el \"blue\"               \"μπλε\"\n    ::msgcat::mcset el \"cancel\"             \"ακύρωση\"\n    ::msgcat::mcset el \"extension\"          \"επέκταση\"\n    ::msgcat::mcset el \"extensions\"         \"επεκτάσεις\"\n    ::msgcat::mcset el \"green\"              \"πράσινο\"\n    ::msgcat::mcset el \"ignore\"             \"αγνόηση\"\n    ::msgcat::mcset el \"ok\"                 \"εντάξει\"\n    ::msgcat::mcset el \"red\"                \"κόκκινο\"\n    ::msgcat::mcset el \"retry\"              \"προσπάθησε ξανά\"\n    ::msgcat::mcset el \"yes\"                \"ναι\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  el \"Print\" \"Τυπώνω\"\n    ::msgcat::mcset  el \"Printer\" \"Εκτυπωτής\"\n    ::msgcat::mcset  el \"Letter \" \"Γράμμα\"\n    ::msgcat::mcset  el \"Legal \" \"Νομικός\"\n    ::msgcat::mcset  el \"A4\" \"Α4\"\n    ::msgcat::mcset  el \"Grayscale\" \"Κλίμακα Του Γκρι\"\n    ::msgcat::mcset  el \"RGB\" \"Rgb\"\n    ::msgcat::mcset  el \"Options\" \"Επιλογές\"\n    ::msgcat::mcset  el \"Copies\" \"Αντίγραφα\"\n    ::msgcat::mcset  el \"Paper\" \"Χαρτί\"\n    ::msgcat::mcset  el \"Scale\" \"Κλίμακα\"\n    ::msgcat::mcset  el \"Orientation\" \"Προσανατολισμός\"\n    ::msgcat::mcset  el \"Portrait\" \"Προσωπογραφία\"\n    ::msgcat::mcset  el \"Landscape\" \"Τοπίο\"\n    ::msgcat::mcset  el \"Output\" \"Έξοδος\"\n}"
  },
  {
    "path": "library/msgs/en.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset en \"&Abort\"\n    ::msgcat::mcset en \"&About...\"\n    ::msgcat::mcset en \"All Files\"\n    ::msgcat::mcset en \"Application Error\"\n    ::msgcat::mcset en \"&Apply\"\n    ::msgcat::mcset en \"Bold\"\n    ::msgcat::mcset en \"Bold Italic\"\n    ::msgcat::mcset en \"&Blue\"\n    ::msgcat::mcset en \"Cancel\"\n    ::msgcat::mcset en \"&Cancel\"\n    ::msgcat::mcset en \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\"\n    ::msgcat::mcset en \"Choose Directory\"\n    ::msgcat::mcset en \"Cl&ear\"\n    ::msgcat::mcset en \"&Clear Console\"\n    ::msgcat::mcset en \"Color\"\n    ::msgcat::mcset en \"Console\"\n    ::msgcat::mcset en \"&Copy\"\n    ::msgcat::mcset en \"Cu&t\"\n    ::msgcat::mcset en \"&Delete\"\n    ::msgcat::mcset en \"Details >>\"\n    ::msgcat::mcset en \"Directory \\\"%1\\$s\\\" does not exist.\"\n    ::msgcat::mcset en \"&Directory:\"\n    ::msgcat::mcset en \"&Edit\"\n    ::msgcat::mcset en \"Effects\"\n    ::msgcat::mcset en \"Error: %1\\$s\"\n    ::msgcat::mcset en \"E&xit\"\n    ::msgcat::mcset en \"&File\"\n    ::msgcat::mcset en \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\"\n    ::msgcat::mcset en \"File \\\"%1\\$s\\\" already exists.\\n\\n\"\n    ::msgcat::mcset en \"File \\\"%1\\$s\\\" does not exist.\"\n    ::msgcat::mcset en \"File &name:\"\n    ::msgcat::mcset en \"File &names:\"\n    ::msgcat::mcset en \"Files of &type:\"\n    ::msgcat::mcset en \"Fi&les:\"\n    ::msgcat::mcset en \"&Filter\"\n    ::msgcat::mcset en \"Fil&ter:\"\n    ::msgcat::mcset en \"Font\"\n    ::msgcat::mcset en \"&Font:\"\n    ::msgcat::mcset en \"Font st&yle:\"\n    ::msgcat::mcset en \"&Green\"\n    ::msgcat::mcset en \"&Help\"\n    ::msgcat::mcset en \"Hi\"\n    ::msgcat::mcset en \"&Hide Console\"\n    ::msgcat::mcset en \"&Ignore\"\n    ::msgcat::mcset en \"Invalid file name \\\"%1\\$s\\\".\"\n    ::msgcat::mcset en \"Italic\"\n    ::msgcat::mcset en \"Log Files\"\n    ::msgcat::mcset en \"&No\"\n    ::msgcat::mcset en \"&OK\"\n    ::msgcat::mcset en \"OK\"\n    ::msgcat::mcset en \"Ok\"\n    ::msgcat::mcset en \"Open\"\n    ::msgcat::mcset en \"&Open\"\n    ::msgcat::mcset en \"Open Multiple Files\"\n    ::msgcat::mcset en \"P&aste\"\n    ::msgcat::mcset en \"&Quit\"\n    ::msgcat::mcset en \"&Red\"\n    ::msgcat::mcset en \"Regular\"\n    ::msgcat::mcset en \"Replace existing file?\"\n    ::msgcat::mcset en \"&Retry\"\n    ::msgcat::mcset en \"Sample\"\n    ::msgcat::mcset en \"&Save\"\n    ::msgcat::mcset en \"Save As\"\n    ::msgcat::mcset en \"Save To Log\"\n    ::msgcat::mcset en \"Select Log File\"\n    ::msgcat::mcset en \"Select a file to source\"\n    ::msgcat::mcset en \"&Selection:\"\n    ::msgcat::mcset en \"&Size:\"\n    ::msgcat::mcset en \"Show &Hidden Directories\"\n    ::msgcat::mcset en \"Show &Hidden Files and Directories\"\n    ::msgcat::mcset en \"Skip Messages\"\n    ::msgcat::mcset en \"&Source...\"\n    ::msgcat::mcset en \"Stri&keout\"\n    ::msgcat::mcset en \"Tcl Scripts\"\n    ::msgcat::mcset en \"Tcl for Windows\"\n    ::msgcat::mcset en \"Text Files\"\n    ::msgcat::mcset en \"&Underline\"\n    ::msgcat::mcset en \"&Yes\"\n    ::msgcat::mcset en \"abort\"\n    ::msgcat::mcset en \"blue\"\n    ::msgcat::mcset en \"cancel\"\n    ::msgcat::mcset en \"extension\"\n    ::msgcat::mcset en \"extensions\"\n    ::msgcat::mcset en \"green\"\n    ::msgcat::mcset en \"ignore\"\n    ::msgcat::mcset en \"ok\"\n    ::msgcat::mcset en \"red\"\n    ::msgcat::mcset en \"retry\"\n    ::msgcat::mcset en \"yes\"\n}\n\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  en \"Print\"\n    ::msgcat::mcset  en \"Printer\"\n    ::msgcat::mcset  en \"Letter \"\n    ::msgcat::mcset  en \"Legal \"\n    ::msgcat::mcset  en \"A4\"\n    ::msgcat::mcset  en \"Grayscale\"\n    ::msgcat::mcset  en \"RGB\"\n    ::msgcat::mcset  en \"Options\"\n    ::msgcat::mcset  en \"Copies\"\n    ::msgcat::mcset  en \"Paper\"\n    ::msgcat::mcset  en \"Scale\"\n    ::msgcat::mcset  en \"Orientation\"\n    ::msgcat::mcset  en \"Portrait\"\n    ::msgcat::mcset  en \"Landscape\"\n    ::msgcat::mcset  en \"Output\"\n}\n"
  },
  {
    "path": "library/msgs/en_gb.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset en_gb Color Colour\n}\n"
  },
  {
    "path": "library/msgs/eo.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset eo \"&Abort\" \"&Ĉesigu\"\n    ::msgcat::mcset eo \"&About...\" \"Pri...\"\n    ::msgcat::mcset eo \"All Files\" \"Ĉiuj dosieroj\"\n    ::msgcat::mcset eo \"Application Error\" \"Aplikoeraro\"\n    ::msgcat::mcset eo \"&Blue\" \"&Blua\"\n    ::msgcat::mcset eo \"Cancel\" \"Rezignu\"\n    ::msgcat::mcset eo \"&Cancel\" \"&Rezignu\"\n    ::msgcat::mcset eo \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Neeble ŝanĝi al dosierujo \\\"%1\\$s\\\".\\nVi ne rajtas tion.\"\n    ::msgcat::mcset eo \"Choose Directory\" \"Elektu Dosierujon\"\n    ::msgcat::mcset eo \"Cl&ear\" \"&Vakigu\"\n    ::msgcat::mcset eo \"&Clear Console\" \"&Vakigu konzolon\"\n    ::msgcat::mcset eo \"Color\" \"Koloro\"\n    ::msgcat::mcset eo \"Console\" \"Konzolo\"\n    ::msgcat::mcset eo \"&Copy\" \"&Kopiu\"\n    ::msgcat::mcset eo \"Cu&t\" \"&Eltondu\"\n    ::msgcat::mcset eo \"&Delete\" \"&Forigu\"\n    ::msgcat::mcset eo \"Details >>\" \"Detaloj >>\"\n    ::msgcat::mcset eo \"Directory \\\"%1\\$s\\\" does not exist.\" \"La dosierujo \\\"%1\\$s\\\" ne ekzistas.\"\n    ::msgcat::mcset eo \"&Directory:\" \"&Dosierujo:\"\n    ::msgcat::mcset eo \"&Edit\" \"&Redaktu\"\n    ::msgcat::mcset eo \"Error: %1\\$s\" \"Eraro: %1\\$s\"\n    ::msgcat::mcset eo \"E&xit\" \"&Eliru\"\n    ::msgcat::mcset eo \"&File\" \"&Dosiero\"\n    ::msgcat::mcset eo \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"La dosiero \\\"%1\\$s\\\" jam ekzistas.\\nĈu vi volas anstataŭigi la dosieron?\"\n    ::msgcat::mcset eo \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"La dosiero \\\"%1\\$s\\\" jam ekzistas. \\n\\n\"\n    ::msgcat::mcset eo \"File \\\"%1\\$s\\\" does not exist.\" \"La dosiero \\\"%1\\$s\\\" ne ekzistas.\"\n    ::msgcat::mcset eo \"File &name:\" \"Dosiero&nomo:\"\n    ::msgcat::mcset eo \"File &names:\" \"Dosiero&nomoj:\"\n    ::msgcat::mcset eo \"Files of &type:\" \"Dosieroj de &Tipo:\"\n    ::msgcat::mcset eo \"Fi&les:\" \"Do&sieroj:\"\n    ::msgcat::mcset eo \"&Filter\" \"&Filtrilo\"\n    ::msgcat::mcset eo \"Fil&ter:\" \"&Filtrilo:\"\n    ::msgcat::mcset eo \"&Green\" \"&Verda\"\n    ::msgcat::mcset eo \"&Help\" \"&Helpu\"\n    ::msgcat::mcset eo \"Hi\" \"Saluton\"\n    ::msgcat::mcset eo \"&Hide Console\" \"&Kaŝu konzolon\"\n    ::msgcat::mcset eo \"&Ignore\" \"&Ignoru\"\n    ::msgcat::mcset eo \"Invalid file name \\\"%1\\$s\\\".\" \"Malvalida dosieronomo \\\"%1\\$s\\\".\"\n    ::msgcat::mcset eo \"Log Files\" \"Protokolaj dosieroj\"\n    ::msgcat::mcset eo \"&No\" \"&Ne\"\n    ::msgcat::mcset eo \"&OK\" \"&Bone\"\n    ::msgcat::mcset eo \"OK\" \"Bone\"\n    ::msgcat::mcset eo \"Ok\" \"Bone\"\n    ::msgcat::mcset eo \"Open\" \"Malfermu\"\n    ::msgcat::mcset eo \"&Open\" \"&Malfermu\"\n    ::msgcat::mcset eo \"Open Multiple Files\" \"Malfermu plurajn dosierojn\"\n    ::msgcat::mcset eo \"P&aste\" \"&Algluu\"\n    ::msgcat::mcset eo \"&Quit\" \"&Forlasu\"\n    ::msgcat::mcset eo \"&Red\" \"&Ruĝa\"\n    ::msgcat::mcset eo \"Replace existing file?\" \"Ĉu anstataŭigi ekzistantan dosieron?\"\n    ::msgcat::mcset eo \"&Retry\" \"&Reprovu\"\n    ::msgcat::mcset eo \"&Save\" \"&Konservu\"\n    ::msgcat::mcset eo \"Save As\" \"Konservu kiel\"\n    ::msgcat::mcset eo \"Save To Log\" \"Konservu en protokolon\"\n    ::msgcat::mcset eo \"Select Log File\" \"Elektu prokolodosieron\"\n    ::msgcat::mcset eo \"Select a file to source\" \"Elektu dosieron por interpreti\"\n    ::msgcat::mcset eo \"&Selection:\" \"&Elekto:\"\n    ::msgcat::mcset eo \"Skip Messages\" \"transsaltu mesaĝojn\"\n    ::msgcat::mcset eo \"&Source...\" \"&Fontoprogramo...\"\n    ::msgcat::mcset eo \"Tcl Scripts\" \"Tcl-skriptoj\"\n    ::msgcat::mcset eo \"Tcl for Windows\" \"Tcl por Vindozo\"\n    ::msgcat::mcset eo \"Text Files\" \"Tekstodosieroj\"\n    ::msgcat::mcset eo \"&Yes\" \"&Jes\"\n    ::msgcat::mcset eo \"abort\" \"ĉesigu\"\n    ::msgcat::mcset eo \"blue\" \"blua\"\n    ::msgcat::mcset eo \"cancel\" \"rezignu\"\n    ::msgcat::mcset eo \"extension\" \"kromprogramo\"\n    ::msgcat::mcset eo \"extensions\" \"kromprogramoj\"\n    ::msgcat::mcset eo \"green\" \"verda\"\n    ::msgcat::mcset eo \"ignore\" \"ignoru\"\n    ::msgcat::mcset eo \"red\" \"ruĝa\"\n    ::msgcat::mcset eo \"retry\" \"reprovu\"\n    ::msgcat::mcset eo \"yes\" \"jes\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  eo \"Print\" \"Presi\"\n    ::msgcat::mcset  eo \"Printer\" \"Presilo\"\n    ::msgcat::mcset  eo \"Letter \" \"Letero\"\n    ::msgcat::mcset  eo \"Legal \" \"Laŭleĝa\"\n    ::msgcat::mcset  eo \"A4\" \"A4\"\n    ::msgcat::mcset  eo \"Grayscale\" \"Grizskalo\"\n    ::msgcat::mcset  eo \"RGB\" \"RGB\"\n    ::msgcat::mcset  eo \"Options\" \"Opcioj\"\n    ::msgcat::mcset  eo \"Copies\" \"Kopioj\"\n    ::msgcat::mcset  eo \"Paper\" \"Papero\"\n    ::msgcat::mcset  eo \"Scale\" \"Skalo\"\n    ::msgcat::mcset  eo \"Orientation\" \"Orientiĝo\"\n    ::msgcat::mcset  eo \"Portrait\" \"Portreto\"\n    ::msgcat::mcset  eo \"Landscape\" \"Pejzaĝo\"\n    ::msgcat::mcset  eo \"Output\" \"Eligo\"\n}\n"
  },
  {
    "path": "library/msgs/es.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset es \"&Abort\" \"&Abortar\"\n    ::msgcat::mcset es \"&About...\" \"&Acerca de ...\"\n    ::msgcat::mcset es \"All Files\" \"Todos los archivos\"\n    ::msgcat::mcset es \"Application Error\" \"Error de la aplicación\"\n    ::msgcat::mcset es \"&Blue\" \"&Azul\"\n    ::msgcat::mcset es \"Cancel\" \"Cancelar\"\n    ::msgcat::mcset es \"&Cancel\" \"&Cancelar\"\n    ::msgcat::mcset es \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"No es posible acceder al directorio \\\"%1\\$s\\\".\\nPermiso denegado.\"\n    ::msgcat::mcset es \"Choose Directory\" \"Elegir directorio\"\n    ::msgcat::mcset es \"Cl&ear\" \"&Borrar\"\n    ::msgcat::mcset es \"&Clear Console\" \"&Borrar consola\"\n    ::msgcat::mcset es \"Color\"\n    ::msgcat::mcset es \"Console\" \"Consola\"\n    ::msgcat::mcset es \"&Copy\" \"&Copiar\"\n    ::msgcat::mcset es \"Cu&t\" \"Cor&tar\"\n    ::msgcat::mcset es \"&Delete\" \"&Borrar\"\n    ::msgcat::mcset es \"Details >>\" \"Detalles >>\"\n    ::msgcat::mcset es \"Directory \\\"%1\\$s\\\" does not exist.\" \"El directorio \\\"%1\\$s\\\" no existe.\"\n    ::msgcat::mcset es \"&Directory:\" \"&Directorio:\"\n    ::msgcat::mcset es \"&Edit\" \"&Editar\"\n    ::msgcat::mcset es \"Error: %1\\$s\"\n    ::msgcat::mcset es \"E&xit\" \"Salir\"\n    ::msgcat::mcset es \"&File\" \"&Archivo\"\n    ::msgcat::mcset es \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"El archivo \\\"%1\\$s\\\" ya existe.\\n¿Desea sobreescribirlo?\"\n    ::msgcat::mcset es \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"El archivo \\\"%1\\$s\\\" ya existe.\\n\\n\"\n    ::msgcat::mcset es \"File \\\"%1\\$s\\\" does not exist.\" \"El archivo \\\"%1\\$s\\\" no existe.\"\n    ::msgcat::mcset es \"File &name:\" \"&Nombre de archivo:\"\n    ::msgcat::mcset es \"File &names:\" \"&Nombres de archivo:\"\n    ::msgcat::mcset es \"Files of &type:\" \"Archivos de &tipo:\"\n    ::msgcat::mcset es \"Fi&les:\" \"&Archivos:\"\n    ::msgcat::mcset es \"&Filter\" \"&Filtro\"\n    ::msgcat::mcset es \"Fil&ter:\" \"Fil&tro:\"\n    ::msgcat::mcset es \"&Green\" \"&Verde\"\n    ::msgcat::mcset es \"&Help\" \"&Ayuda\"\n    ::msgcat::mcset es \"Hi\"  \"Hola\"\n    ::msgcat::mcset es \"&Hide Console\" \"&Esconder la consola\"\n    ::msgcat::mcset es \"&Ignore\" \"&Ignorar\"\n    ::msgcat::mcset es \"Invalid file name \\\"%1\\$s\\\".\" \"Nombre de archivo inválido \\\"%1\\$s\\\".\"\n    ::msgcat::mcset es \"Log Files\"  \"Ficheros de traza\"\n    ::msgcat::mcset es \"&No\"\n    ::msgcat::mcset es \"&OK\"\n    ::msgcat::mcset es \"OK\"\n    ::msgcat::mcset es \"Ok\"\n    ::msgcat::mcset es \"Open\" \"Abrir\"\n    ::msgcat::mcset es \"&Open\" \"&Abrir\"\n    ::msgcat::mcset es \"Open Multiple Files\" \"Abrir múltiples archivos\"\n    ::msgcat::mcset es \"P&aste\" \"Peg&ar\"\n    ::msgcat::mcset es \"&Quit\" \"&Abandonar\"\n    ::msgcat::mcset es \"&Red\" \"&Rojo\"\n    ::msgcat::mcset es \"Replace existing file?\" \"¿Reemplazar el archivo existente?\"\n    ::msgcat::mcset es \"&Retry\" \"&Reintentar\"\n    ::msgcat::mcset es \"&Save\" \"&Guardar\"\n    ::msgcat::mcset es \"Save As\" \"Guardar como\"\n    ::msgcat::mcset es \"Save To Log\" \"Guardar al archivo de traza\"\n    ::msgcat::mcset es \"Select Log File\"  \"Elegir un archivo de traza\"\n    ::msgcat::mcset es \"Select a file to source\" \"Seleccionar un archivo a evaluar\"\n    ::msgcat::mcset es \"&Selection:\" \"&Selección:\"\n    ::msgcat::mcset es \"Skip Messages\" \"Omitir los mensajes\"\n    ::msgcat::mcset es \"&Source...\" \"E&valuar...\"\n    ::msgcat::mcset es \"Tcl Scripts\" \"Scripts Tcl\"\n    ::msgcat::mcset es \"Tcl for Windows\" \"Tcl para Windows\"\n    ::msgcat::mcset es \"Text Files\" \"Archivos de texto\"\n    ::msgcat::mcset es \"&Yes\" \"&Sí\"\n    ::msgcat::mcset es \"abort\" \"abortar\"\n    ::msgcat::mcset es \"blue\" \"azul\"\n    ::msgcat::mcset es \"cancel\" \"cancelar\"\n    ::msgcat::mcset es \"extension\"  \"extensión\"\n    ::msgcat::mcset es \"extensions\" \"extensiones\"\n    ::msgcat::mcset es \"green\" \"verde\"\n    ::msgcat::mcset es \"ignore\" \"ignorar\"\n    ::msgcat::mcset es \"ok\"\n    ::msgcat::mcset es \"red\" \"rojo\"\n    ::msgcat::mcset es \"retry\" \"reintentar\"\n    ::msgcat::mcset es \"yes\" \"sí\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n\t::msgcat::mcset  es \"Print\" \"Imprimir\"\n\t::msgcat::mcset  es \"Printer\" \"Impresora\"\n\t::msgcat::mcset  es \"Letter\" \"Carta\"\n\t::msgcat::mcset  es \"Legal\" \"Legal\"\n\t::msgcat::mcset  es \"A4\" \"A4\"\n\t::msgcat::mcset  es \"Grayscale\" \"Escala De Grises\"\n\t::msgcat::mcset  es \"RGB\" \"Color\"\n\t::msgcat::mcset  es \"Options\" \"Opciones\"\n\t::msgcat::mcset  es \"Copies\" \"Copias\"\n\t::msgcat::mcset  es \"Paper\" \"Papel\"\n\t::msgcat::mcset  es \"Scale\" \"Escala\"\n\t::msgcat::mcset  es \"Orientation\" \"Orientación\"\n\t::msgcat::mcset  es \"Portrait\" \"Retrato\"\n\t::msgcat::mcset  es \"Landscape\" \"Paisaje\"\n\t::msgcat::mcset  es \"Output\" \"Salida\"\n}"
  },
  {
    "path": "library/msgs/fi.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset fi \"AaBbYyZz01\" \"AaBbÄäÖö01\"\n    ::msgcat::mcset fi \"&Abort\" \"&Keskeytä\"\n    ::msgcat::mcset fi \"&About...\" \"&Tietoja...\"\n    ::msgcat::mcset fi \"All Files\" \"Kaikki tiedostot\"\n    ::msgcat::mcset fi \"&Apply\" \"Kä&ytä\"\n    ::msgcat::mcset fi \"Application Error\" \"Ohjelmavirhe\"\n    ::msgcat::mcset fi \"&Blue\" \"&Sininen\"\n    ::msgcat::mcset fi \"Bold\" \"Lihavoitu\"\n    ::msgcat::mcset fi \"Bold Italic\" \"Lihavoitu, kursivoitu\"\n    ::msgcat::mcset fi \"Cancel\" \"Peruuta\"\n    ::msgcat::mcset fi \"&Cancel\" \"&Peruuta\"\n    ::msgcat::mcset fi \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Ei voitu vaihtaa hakemistoon \\\"%1\\$s\\\".\\nLupa evätty.\"\n    ::msgcat::mcset fi \"Choose Directory\" \"Valitse hakemisto\"\n    ::msgcat::mcset fi \"Cl&ear\" \"&Tyhjennä\"\n    ::msgcat::mcset fi \"&Clear Console\" \"&Tyhjennä konsoli\"\n    ::msgcat::mcset fi \"Color\" \"Väri\"\n    ::msgcat::mcset fi \"Console\" \"Konsoli\"\n    ::msgcat::mcset fi \"&Copy\" \"K&opioi\"\n    ::msgcat::mcset fi \"Cu&t\" \"&Leikkaa\"\n    ::msgcat::mcset fi \"&Decrease Font Size\" \"&Pienennä kirjasinkokoa\"\n    ::msgcat::mcset fi \"&Delete\" \"&Poista\"\n    ::msgcat::mcset fi \"Details >>\" \"Lisätiedot >>\"\n    ::msgcat::mcset fi \"Directory \\\"%1\\$s\\\" does not exist.\" \"Hakemistoa \\\"%1\\$s\\\" ei ole olemassa.\"\n    ::msgcat::mcset fi \"&Directory:\" \"&Hakemisto:\"\n    ::msgcat::mcset fi \"&Edit\" \"&Muokkaa\"\n    ::msgcat::mcset fi \"Effects\" \"Tehosteet\"\n    ::msgcat::mcset fi \"Error: %1\\$s\" \"Virhe: %1\\$s\"\n    ::msgcat::mcset fi \"E&xit\" \"&Lopeta\"\n    ::msgcat::mcset fi \"&File\" \"&Tiedosto\"\n    ::msgcat::mcset fi \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Tiedosto \\\"%1\\$s\\\" on jo olemassa.\\nHaluatko korvata sen?\"\n    ::msgcat::mcset fi \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Tiedosto \\\"%1\\$s\\\" on jo olemassa.\\n\\n\"\n    ::msgcat::mcset fi \"File \\\"%1\\$s\\\" does not exist.\" \"Tiedostoa \\\"%1\\$s\\\" ei ole olemassa.\"\n    ::msgcat::mcset fi \"File &name:\" \"Tiedosto&nimi:\"\n    ::msgcat::mcset fi \"File &names:\" \"Tiedosto&nimet:\"\n    ::msgcat::mcset fi \"Files of &type:\" \"T&yyppi:\"\n    ::msgcat::mcset fi \"Fi&les:\" \"Ti&edostot:\"\n    ::msgcat::mcset fi \"&Filter\" \"&Suodata\"\n    ::msgcat::mcset fi \"Fil&ter:\" \"Suo&data:\"\n    ::msgcat::mcset fi \"Fit To Screen Width\" \"Sovita ruudun kokoon\"\n    ::msgcat::mcset fi \"Font\" \"Kirjasin\"\n    ::msgcat::mcset fi \"&Font...\" \"Kir&jasin...\"\n    ::msgcat::mcset fi \"&Font:\" \"&Kirjasin:\"\n    ::msgcat::mcset fi \"Font st&yle:\" \"Kirjasint&yyli:\"\n    ::msgcat::mcset fi \"&Green\" \"&Vihreä\"\n    ::msgcat::mcset fi \"Help\" \"Ohje\"\n    ::msgcat::mcset fi \"&Help\" \"&Ohje\"\n    ::msgcat::mcset fi \"Hi\" \"Hei\"\n    ::msgcat::mcset fi \"&Hide Console\" \"P&iilota konsoli\"\n    ::msgcat::mcset fi \"Hide Fonts\" \"Piilota kirjasimet\"\n    ::msgcat::mcset fi \"&Ignore\" \"&Ohita\"\n    ::msgcat::mcset fi \"&Increase Font Size\" \"&Suurenna kirjasinkokoa\"\n    ::msgcat::mcset fi \"Invalid file name \\\"%1\\$s\\\".\" \"Virheellinen tiedostonimi \\\"%1\\$s\\\".\"\n    ::msgcat::mcset fi \"Italic\" \"Kursivoitu\"\n    ::msgcat::mcset fi \"Log Files\" \"Lokitiedostot\"\n    ::msgcat::mcset fi \"&No\" \"&Ei\"\n    ::msgcat::mcset fi \"&OK\"\n    ::msgcat::mcset fi \"OK\"\n    ::msgcat::mcset fi \"Ok\" \"OK\"\n    ::msgcat::mcset fi \"Open\" \"Avaa\"\n    ::msgcat::mcset fi \"&Open\" \"&Avaa\"\n    ::msgcat::mcset fi \"Open Multiple Files\" \"Avaa monta tiedostoa\"\n    ::msgcat::mcset fi \"P&aste\" \"L&iitä\"\n    ::msgcat::mcset fi \"&Quit\" \"&Lopeta\"\n    ::msgcat::mcset fi \"&Red\" \"&Punainen\"\n    ::msgcat::mcset fi \"Regular\" \"Tavallinen\"\n    ::msgcat::mcset fi \"Replace existing file?\" \"Korvataanko olemassaoleva tiedosto?\"\n    ::msgcat::mcset fi \"&Retry\" \"&Yritä uudelleen\"\n    ::msgcat::mcset fi \"Sample\" \"Malli\"\n    ::msgcat::mcset fi \"&Save\" \"&Tallenna\"\n    ::msgcat::mcset fi \"Save As\" \"Tallenna nimellä\"\n    ::msgcat::mcset fi \"Save To Log\" \"Tallenna lokiin\"\n    ::msgcat::mcset fi \"Select Log File\" \"Valitse lokitiedosto\"\n    ::msgcat::mcset fi \"Select a file to source\" \"Valitse lähdetiedosto\"\n    ::msgcat::mcset fi \"&Selection:\" \"&Valinta:\"\n    ::msgcat::mcset fi \"Show Fonts\" \"Näytä kirjasimet\"\n    ::msgcat::mcset fi \"Skip Messages\" \"Jätä viestit huomiotta\"\n    ::msgcat::mcset fi \"&Size:\" \"K&oko:\"\n    ::msgcat::mcset fi \"&Source...\" \"L&ähde...\"\n    ::msgcat::mcset fi \"Stri&keout\" \"&Yliviivaa\"\n    ::msgcat::mcset fi \"Tcl Scripts\" \"Tcl-skriptit\"\n    ::msgcat::mcset fi \"Tcl for Windows\" \"Tcl Windowsille\"\n    ::msgcat::mcset fi \"Text Files\" \"Tekstitiedostot\"\n    ::msgcat::mcset fi \"&Underline\" \"&Alleviivaa\"\n    ::msgcat::mcset fi \"Window\" \"Ikkuna\"\n    ::msgcat::mcset fi \"&Yes\" \"&Kyllä\"\n    ::msgcat::mcset fi \"abort\" \"keskeytä\"\n    ::msgcat::mcset fi \"blue\" \"sininen\"\n    ::msgcat::mcset fi \"cancel\" \"peruuta\"\n    ::msgcat::mcset fi \"extension\" \"lisäosa\"\n    ::msgcat::mcset fi \"extensions\" \"lisäosat\"\n    ::msgcat::mcset fi \"green\" \"vihreä\"\n    ::msgcat::mcset fi \"ignore\" \"ohita\"\n    ::msgcat::mcset fi \"ok\"\n    ::msgcat::mcset fi \"red\" \"punainen\"\n    ::msgcat::mcset fi \"retry\" \"yritä uudelleen\"\n    ::msgcat::mcset fi \"yes\" \"kyllä\"\n\n    ::msgcat::mcset fi \"Print\" \"Tulosta\"\n    ::msgcat::mcset fi \"Printer\" \"Tulostin\"\n    ::msgcat::mcset fi \"Letter \" \"Letter\"\n    ::msgcat::mcset fi \"Legal \" \"Legal\"\n    ::msgcat::mcset fi \"A4\" \"A4\"\n    ::msgcat::mcset fi \"Grayscale\" \"Harmaasävy\"\n    ::msgcat::mcset fi \"RGB\" \"RGB\"\n    ::msgcat::mcset fi \"Options\" \"Asetukset\"\n    ::msgcat::mcset fi \"Copies\" \"Tulosteita\"\n    ::msgcat::mcset fi \"Paper\" \"Paperikoko\"\n    ::msgcat::mcset fi \"Scale\" \"Skaalaus\"\n    ::msgcat::mcset fi \"Orientation\" \"Suunta\"\n    ::msgcat::mcset fi \"Portrait\" \"Pysty\"\n    ::msgcat::mcset fi \"Landscape\" \"Vaaka\"\n    ::msgcat::mcset fi \"Output\" \"Tulos\"\n}\n"
  },
  {
    "path": "library/msgs/fr.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset fr \"&Abort\" \"&Annuler\"\n    ::msgcat::mcset fr \"About...\" \"À propos...\"\n    ::msgcat::mcset fr \"All Files\" \"Tous les fichiers\"\n    ::msgcat::mcset fr \"Application Error\" \"Erreur d'application\"\n    ::msgcat::mcset fr \"&Blue\" \"&Bleu\"\n    ::msgcat::mcset fr \"Cancel\" \"Annuler\"\n    ::msgcat::mcset fr \"&Cancel\" \"&Annuler\"\n    ::msgcat::mcset fr \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Impossible d'accéder au répertoire \\\"%1\\$s\\\".\\nPermission refusée.\"\n    ::msgcat::mcset fr \"Choose Directory\" \"Choisir répertoire\"\n    ::msgcat::mcset fr \"Cl&ear\" \"Effacer\"\n    ::msgcat::mcset fr \"Color\" \"Couleur\"\n    ::msgcat::mcset fr \"Console\"\n    ::msgcat::mcset fr \"Copy\" \"Copier\"\n    ::msgcat::mcset fr \"Cu&t\" \"Couper\"\n    ::msgcat::mcset fr \"Delete\" \"Effacer\"\n    ::msgcat::mcset fr \"Details >>\" \"Détails >>\"\n    ::msgcat::mcset fr \"Directory \\\"%1\\$s\\\" does not exist.\" \"Le répertoire \\\"%1\\$s\\\" n'existe pas.\"\n    ::msgcat::mcset fr \"&Directory:\" \"&Répertoire:\"\n    ::msgcat::mcset fr \"Error: %1\\$s\" \"Erreur: %1\\$s\"\n    ::msgcat::mcset fr \"E&xit\" \"Quitter\"\n    ::msgcat::mcset fr \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Le fichier \\\"%1\\$s\\\" existe déjà.\\nVoulez-vous l'écraser?\"\n    ::msgcat::mcset fr \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Le fichier \\\"%1\\$s\\\" existe déjà.\\n\\n\"\n    ::msgcat::mcset fr \"File \\\"%1\\$s\\\" does not exist.\" \"Le fichier \\\"%1\\$s\\\" n'existe pas.\"\n    ::msgcat::mcset fr \"File &name:\" \"&Nom de fichier:\"\n    ::msgcat::mcset fr \"File &names:\" \"&Noms de fichiers:\"\n    ::msgcat::mcset fr \"Files of &type:\" \"&Type de fichiers:\"\n    ::msgcat::mcset fr \"Fi&les:\" \"Fich&iers:\"\n    ::msgcat::mcset fr \"&Filter\" \"&Filtre\"\n    ::msgcat::mcset fr \"Fil&ter:\" \"Fil&tre:\"\n    ::msgcat::mcset fr \"&Green\" \"&Vert\"\n    ::msgcat::mcset fr \"Hi\" \"Salut\"\n    ::msgcat::mcset fr \"&Hide Console\" \"Cacher la Console\"\n    ::msgcat::mcset fr \"&Ignore\" \"&Ignorer\"\n    ::msgcat::mcset fr \"Invalid file name \\\"%1\\$s\\\".\" \"Nom de fichier invalide \\\"%1\\$s\\\".\"\n    ::msgcat::mcset fr \"Log Files\" \"Fichiers de trace\"\n    ::msgcat::mcset fr \"&No\" \"&Non\"\n    ::msgcat::mcset fr \"&OK\"\n    ::msgcat::mcset fr \"OK\"\n    ::msgcat::mcset fr \"Ok\"\n    ::msgcat::mcset fr \"Open\" \"Ouvrir\"\n    ::msgcat::mcset fr \"&Open\" \"&Ouvrir\"\n    ::msgcat::mcset fr \"Open Multiple Files\" \"Ouvrir plusieurs fichiers\"\n    ::msgcat::mcset fr \"P&aste\" \"Coller\"\n    ::msgcat::mcset fr \"&Quit\" \"&Quitter\"\n    ::msgcat::mcset fr \"&Red\" \"&Rouge\"\n    ::msgcat::mcset fr \"Replace existing file?\" \"Remplacer le fichier existant?\"\n    ::msgcat::mcset fr \"&Retry\" \"&Ré-essayer\"\n    ::msgcat::mcset fr \"&Save\" \"&Sauvegarder\"\n    ::msgcat::mcset fr \"Save As\" \"Sauvegarder sous\"\n    ::msgcat::mcset fr \"Save To Log\" \"Sauvegarde au fichier de trace\"\n    ::msgcat::mcset fr \"Select Log File\" \"Choisir un fichier de trace\"\n    ::msgcat::mcset fr \"Select a file to source\" \"Choisir un fichier à évaluer\"\n    ::msgcat::mcset fr \"&Selection:\" \"&Sélection:\"\n    ::msgcat::mcset fr \"Skip Messages\" \"Omettre les messages\"\n    ::msgcat::mcset fr \"&Source...\" \"Évaluer...\"\n    ::msgcat::mcset fr \"Tcl Scripts\" \"Scripts Tcl\"\n    ::msgcat::mcset fr \"Tcl for Windows\" \"Tcl pour Windows\"\n    ::msgcat::mcset fr \"Text Files\" \"Fichiers texte\"\n    ::msgcat::mcset fr \"&Yes\" \"&Oui\"\n    ::msgcat::mcset fr \"abort\" \"abandonner\"\n    ::msgcat::mcset fr \"blue\" \"bleu\"\n    ::msgcat::mcset fr \"cancel\" \"annuler\"\n    ::msgcat::mcset fr \"extension\"\n    ::msgcat::mcset fr \"extensions\"\n    ::msgcat::mcset fr \"green\" \"vert\"\n    ::msgcat::mcset fr \"ignore\" \"ignorer\"\n    ::msgcat::mcset fr \"ok\"\n    ::msgcat::mcset fr \"red\" \"rouge\"\n    ::msgcat::mcset fr \"retry\" \"réessayer\"\n    ::msgcat::mcset fr \"yes\" \"oui\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  fr \"Print\" \"Imprimer\"\n    ::msgcat::mcset  fr \"Printer\" \"Imprimante\"\n    ::msgcat::mcset  fr \"Letter \" \"Lettre\"\n    ::msgcat::mcset  fr \"Legal \" \"Légal\"\n    ::msgcat::mcset  fr \"A4\" \"A4\"\n    ::msgcat::mcset  fr \"Grayscale\" \"Niveaux de Gris\"\n    ::msgcat::mcset  fr \"RGB\" \"RVB\"\n    ::msgcat::mcset  fr \"Options\" \"Options\"\n    ::msgcat::mcset  fr \"Copies\" \"Nombre d'exemplaires\"\n    ::msgcat::mcset  fr \"Paper\" \"Papier\"\n    ::msgcat::mcset  fr \"Scale\" \"Échelle\"\n    ::msgcat::mcset  fr \"Orientation\" \"Orientation\"\n    ::msgcat::mcset  fr \"Portrait\" \"Portrait\"\n    ::msgcat::mcset  fr \"Landscape\" \"Paysage\"\n    ::msgcat::mcset  fr \"Output\" \"Sortie\"\n}"
  },
  {
    "path": "library/msgs/hu.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset hu \"&Abort\" \"&Megszakítás\"\n    ::msgcat::mcset hu \"&About...\" \"Névjegy...\"\n    ::msgcat::mcset hu \"All Files\" \"Minden fájl\"\n    ::msgcat::mcset hu \"Application Error\" \"Alkalmazás hiba\"\n    ::msgcat::mcset hu \"&Blue\" \"&Kék\"\n    ::msgcat::mcset hu \"Cancel\" \"Mégsem\"\n    ::msgcat::mcset hu \"&Cancel\" \"Még&sem\"\n    ::msgcat::mcset hu \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"A könyvtárváltás nem sikerült: \\\"%1\\$s\\\".\\nHozzáférés megtagadva.\"\n    ::msgcat::mcset hu \"Choose Directory\" \"Könyvtár kiválasztása\"\n    ::msgcat::mcset hu \"Cl&ear\" \"Törlés\"\n    ::msgcat::mcset hu \"&Clear Console\" \"&Törlés Konzol\"\n    ::msgcat::mcset hu \"Color\" \"Szín\"\n    ::msgcat::mcset hu \"Console\" \"Konzol\"\n    ::msgcat::mcset hu \"&Copy\" \"&Másolás\"\n    ::msgcat::mcset hu \"Cu&t\" \"&Kivágás\"\n    ::msgcat::mcset hu \"&Delete\" \"&Törlés\"\n    ::msgcat::mcset hu \"Details >>\" \"Részletek >>\"\n    ::msgcat::mcset hu \"Directory \\\"%1\\$s\\\" does not exist.\" \"\\\"%1\\$s\\\" könyvtár nem létezik.\"\n    ::msgcat::mcset hu \"&Directory:\" \"&Könyvtár:\"\n    #::msgcat::mcset hu \"&Edit\"\n    ::msgcat::mcset hu \"Error: %1\\$s\" \"Hiba: %1\\$s\"\n    ::msgcat::mcset hu \"E&xit\" \"Kilépés\"\n    ::msgcat::mcset hu \"&File\" \"&Fájl\"\n    ::msgcat::mcset hu \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"\\\"%1\\$s\\\" fájl már létezik.\\nFelülírjam?\"\n    ::msgcat::mcset hu \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"\\\"%1\\$s\\\" fájl már létezik.\\n\\n\"\n    ::msgcat::mcset hu \"File \\\"%1\\$s\\\" does not exist.\" \"\\\"%1\\$s\\\" fájl nem létezik.\"\n    ::msgcat::mcset hu \"File &name:\" \"Fájl &neve:\"\n    ::msgcat::mcset hu \"File &names:\" \"Fájlok &nevei:\"\n    ::msgcat::mcset hu \"Files of &type:\" \"Fájlok &típusa:\"\n    ::msgcat::mcset hu \"Fi&les:\" \"Fáj&lok:\"\n    ::msgcat::mcset hu \"&Filter\" \"&Szűrő\"\n    ::msgcat::mcset hu \"Fil&ter:\" \"S&zűrő:\"\n    ::msgcat::mcset hu \"&Green\" \"&Zöld\"\n    #::msgcat::mcset hu \"&Help\"\n    ::msgcat::mcset hu \"Hi\" \"Üdv\"\n    ::msgcat::mcset hu \"&Hide Console\" \"Konzol &elrejtése\"\n    ::msgcat::mcset hu \"&Ignore\" \"K&ihagyás\"\n    ::msgcat::mcset hu \"Invalid file name \\\"%1\\$s\\\".\" \"Érvénytelen fájlnév: \\\"%1\\$s\\\".\"\n    ::msgcat::mcset hu \"Log Files\" \"Log fájlok\"\n    ::msgcat::mcset hu \"&No\" \"&Nem\"\n    ::msgcat::mcset hu \"&OK\"\n    ::msgcat::mcset hu \"OK\"\n    ::msgcat::mcset hu \"Ok\"\n    ::msgcat::mcset hu \"Open\" \"Megnyitás\"\n    ::msgcat::mcset hu \"&Open\" \"&Megnyitás\"\n    ::msgcat::mcset hu \"Open Multiple Files\" \"Több fájl megnyitása\"\n    ::msgcat::mcset hu \"P&aste\" \"&Beillesztés\"\n    ::msgcat::mcset hu \"&Quit\" \"&Kilépés\"\n    ::msgcat::mcset hu \"&Red\" \"&Vörös\"\n    ::msgcat::mcset hu \"Replace existing file?\" \"Meglévő fájl cseréje?\"\n    ::msgcat::mcset hu \"&Retry\" \"Új&ra\"\n    ::msgcat::mcset hu \"&Save\" \"&Mentés\"\n    ::msgcat::mcset hu \"Save As\" \"Mentés másként\"\n    ::msgcat::mcset hu \"Save To Log\" \"Mentés log fájlba\"\n    ::msgcat::mcset hu \"Select Log File\" \"Log fájl kiválasztása\"\n    ::msgcat::mcset hu \"Select a file to source\" \"Forrásfájl kiválasztása\"\n    ::msgcat::mcset hu \"&Selection:\" \"&Kijelölés:\"\n    ::msgcat::mcset hu \"Show &Hidden Directories\" \"&Rejtett könyvtárak megjelenítése\"\n    ::msgcat::mcset hu \"Show &Hidden Files and Directories\" \"&Rejtett fájlok és könyvtárak megjelenítése\"\n    ::msgcat::mcset hu \"Skip Messages\" \"Üzenetek kihagyása\"\n    ::msgcat::mcset hu \"&Source...\" \"&Forrás...\"\n    ::msgcat::mcset hu \"Tcl Scripts\" \"Tcl scriptek\"\n    ::msgcat::mcset hu \"Tcl for Windows\" \"Tcl Windows-hoz\"\n    ::msgcat::mcset hu \"Text Files\" \"Szövegfájlok\"\n    ::msgcat::mcset hu \"&Yes\" \"&Igen\"\n    ::msgcat::mcset hu \"abort\" \"megszakítás\"\n    ::msgcat::mcset hu \"blue\" \"kék\"\n    ::msgcat::mcset hu \"cancel\" \"mégsem\"\n    ::msgcat::mcset hu \"extension\" \"kiterjesztés\"\n    ::msgcat::mcset hu \"extensions\" \"kiterjesztések\"\n    ::msgcat::mcset hu \"green\" \"zöld\"\n    ::msgcat::mcset hu \"ignore\" \"ignorer\"\n    ::msgcat::mcset hu \"ok\"\n    ::msgcat::mcset hu \"red\" \"vörös\"\n    ::msgcat::mcset hu \"retry\" \"újra\"\n    ::msgcat::mcset hu \"yes\" \"igen\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  hu \"Print\" \"Nyomtat\"\n    ::msgcat::mcset  hu \"Printer\" \"Nyomtató\"\n    ::msgcat::mcset  hu \"Letter \" \"Levél\"\n    ::msgcat::mcset  hu \"Legal \" \"Törvényes\"\n    ::msgcat::mcset  hu \"A4\" \"A4\"\n    ::msgcat::mcset  hu \"Grayscale\" \"Szürkeárnyalatos\"\n    ::msgcat::mcset  hu \"RGB\" \"Rgb\"\n    ::msgcat::mcset  hu \"Options\" \"Beállítások\"\n    ::msgcat::mcset  hu \"Copies\" \"Másolatok\"\n    ::msgcat::mcset  hu \"Paper\" \"Papír\"\n    ::msgcat::mcset  hu \"Scale\" \"Hangsor\"\n    ::msgcat::mcset  hu \"Orientation\" \"Tájékozódás\"\n    ::msgcat::mcset  hu \"Portrait\" \"Portré\"\n    ::msgcat::mcset  hu \"Landscape\" \"Táj\"\n    ::msgcat::mcset  hu \"Output\" \"Hozam\"\n}"
  },
  {
    "path": "library/msgs/it.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset it \"&Abort\" \"&Interrompi\"\n    ::msgcat::mcset it \"&About...\" \"Informazioni...\"\n    ::msgcat::mcset it \"All Files\" \"Tutti i file\"\n    ::msgcat::mcset it \"Application Error\" \"Errore dell' applicazione\"\n    ::msgcat::mcset it \"&Blue\" \"&Blu\"\n    ::msgcat::mcset it \"Cancel\" \"Annulla\"\n    ::msgcat::mcset it \"&Cancel\" \"&Annulla\"\n    ::msgcat::mcset it \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Impossibile accedere alla directory \\\"%1\\$s\\\".\\nPermesso negato.\"\n    ::msgcat::mcset it \"Choose Directory\" \"Scegli una directory\"\n    ::msgcat::mcset it \"Cl&ear\" \"Azzera\"\n    ::msgcat::mcset it \"&Clear Console\" \"Azzera Console\"\n    ::msgcat::mcset it \"Color\" \"Colore\"\n    ::msgcat::mcset it \"Console\"\n    ::msgcat::mcset it \"&Copy\" \"Copia\"\n    ::msgcat::mcset it \"Cu&t\" \"Taglia\"\n    ::msgcat::mcset it \"Delete\" \"Cancella\"\n    ::msgcat::mcset it \"Details >>\" \"Dettagli >>\"\n    ::msgcat::mcset it \"Directory \\\"%1\\$s\\\" does not exist.\" \"La directory \\\"%1\\$s\\\" non esiste.\"\n    ::msgcat::mcset it \"&Directory:\"\n    ::msgcat::mcset it \"Error: %1\\$s\" \"Errore: %1\\$s\"\n    ::msgcat::mcset it \"E&xit\" \"Esci\"\n    ::msgcat::mcset it \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Il file \\\"%1\\$s\\\" esiste già.\\nVuoi sovrascriverlo?\"\n    ::msgcat::mcset it \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Il file \\\"%1\\$s\\\" esiste già.\\n\\n\"\n    ::msgcat::mcset it \"File \\\"%1\\$s\\\" does not exist.\" \"Il file \\\"%1\\$s\\\" non esiste.\"\n    ::msgcat::mcset it \"File &name:\" \"&Nome del file:\"\n    ::msgcat::mcset it \"File &names:\" \"&Nomi dei file:\"\n    ::msgcat::mcset it \"Files of &type:\" \"File di &tipo:\"\n    ::msgcat::mcset it \"Fi&les:\" \"Fi&le:\"\n    ::msgcat::mcset it \"&Filter\" \"&Filtro\"\n    ::msgcat::mcset it \"Fil&ter:\" \"Fil&tro:\"\n    ::msgcat::mcset it \"&Green\" \"&Verde\"\n    ::msgcat::mcset it \"Hi\" \"Salve\"\n    ::msgcat::mcset it \"&Hide Console\" \"Nascondi la console\"\n    ::msgcat::mcset it \"&Ignore\" \"&Ignora\"\n    ::msgcat::mcset it \"Invalid file name \\\"%1\\$s\\\".\" \"Nome di file non valido \\\"%1\\$s\\\".\"\n    ::msgcat::mcset it \"Log Files\" \"File di log\"\n    ::msgcat::mcset it \"&No\"\n    ::msgcat::mcset it \"&OK\"\n    ::msgcat::mcset it \"OK\"\n    ::msgcat::mcset it \"Ok\"\n    ::msgcat::mcset it \"Open\" \"Apri\"\n    ::msgcat::mcset it \"&Open\" \"A&pri\"\n    ::msgcat::mcset it \"Open Multiple Files\" \"Apri file multipli\"\n    ::msgcat::mcset it \"P&aste\" \"Incolla\"\n    ::msgcat::mcset it \"&Quit\" \"Esci\"\n    ::msgcat::mcset it \"&Red\" \"&Rosso\"\n    ::msgcat::mcset it \"Replace existing file?\" \"Sostituisci il file esistente?\"\n    ::msgcat::mcset it \"&Retry\" \"&Riprova\"\n    ::msgcat::mcset it \"&Save\" \"&Salva\"\n    ::msgcat::mcset it \"Save As\" \"Salva come\"\n    ::msgcat::mcset it \"Save To Log\" \"Salva il log\"\n    ::msgcat::mcset it \"Select Log File\" \"Scegli un file di log\"\n    ::msgcat::mcset it \"Select a file to source\" \"Scegli un file da eseguire\"\n    ::msgcat::mcset it \"&Selection:\" \"&Selezione:\"\n    ::msgcat::mcset it \"Skip Messages\" \"Salta i messaggi\"\n    ::msgcat::mcset it \"Source...\" \"Esegui...\"\n    ::msgcat::mcset it \"Tcl Scripts\" \"Script Tcl\"\n    ::msgcat::mcset it \"Tcl for Windows\" \"Tcl per Windows\"\n    ::msgcat::mcset it \"Text Files\" \"File di testo\"\n    ::msgcat::mcset it \"&Yes\" \"&Sì\"\n    ::msgcat::mcset it \"abort\" \"interrompi\"\n    ::msgcat::mcset it \"blue\" \"blu\"\n    ::msgcat::mcset it \"cancel\" \"annulla\"\n    ::msgcat::mcset it \"extension\" \"estensione\"\n    ::msgcat::mcset it \"extensions\" \"estensioni\"\n    ::msgcat::mcset it \"green\" \"verde\"\n    ::msgcat::mcset it \"ignore\" \"ignora\"\n    ::msgcat::mcset it \"ok\"\n    ::msgcat::mcset it \"red\" \"rosso\"\n    ::msgcat::mcset it \"retry\" \"riprova\"\n    ::msgcat::mcset it \"yes\" \"sì\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  it \"Print\" \"Stampare\"\n    ::msgcat::mcset  it \"Printer\" \"Stampante\"\n    ::msgcat::mcset  it \"Letter \" \"Lettera\"\n    ::msgcat::mcset  it \"Legal \" \"Legale\"\n    ::msgcat::mcset  it \"A4\" \"A4\"\n    ::msgcat::mcset  it \"Grayscale\" \"Scala Di Grigi\"\n    ::msgcat::mcset  it \"RGB\" \"Rgb\"\n    ::msgcat::mcset  it \"Options\" \"Opzioni\"\n    ::msgcat::mcset  it \"Copies\" \"Copie\"\n    ::msgcat::mcset  it \"Paper\" \"Carta\"\n    ::msgcat::mcset  it \"Scale\" \"Scala\"\n    ::msgcat::mcset  it \"Orientation\" \"Orientamento\"\n    ::msgcat::mcset  it \"Portrait\" \"Ritratto\"\n    ::msgcat::mcset  it \"Landscape\" \"Paesaggio\"\n    ::msgcat::mcset  it \"Output\" \"Prodotto\"\n}"
  },
  {
    "path": "library/msgs/nl.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset nl \"&Abort\" \"&Afbreken\"\n    ::msgcat::mcset nl \"&About...\" \"Over...\"\n    ::msgcat::mcset nl \"All Files\" \"Alle Bestanden\"\n    ::msgcat::mcset nl \"Application Error\" \"Toepassingsfout\"\n    ::msgcat::mcset nl \"&Apply\" \"Toepassen\"\n    ::msgcat::mcset nl \"Bold\" \"Vet\"\n    ::msgcat::mcset nl \"Bold Italic\" \"Vet Cursief\"\n    ::msgcat::mcset nl \"&Blue\" \"&Blauw\"\n    ::msgcat::mcset nl \"Cancel\" \"Annuleren\"\n    ::msgcat::mcset nl \"&Cancel\" \"&Annuleren\"\n    ::msgcat::mcset nl \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Kan niet naar map \\\"%1\\$s\\\" gaan.\\nU heeft hiervoor geen toestemming.\"\n    ::msgcat::mcset nl \"Choose Directory\" \"Kies map\"\n    ::msgcat::mcset nl \"Cl&ear\" \"Wissen\"\n    ::msgcat::mcset nl \"&Clear Console\" \"&Wis Console\"\n    ::msgcat::mcset nl \"Color\" \"Kleur\"\n    ::msgcat::mcset nl \"Console\"\n    ::msgcat::mcset nl \"&Copy\" \"Kopiëren\"\n    ::msgcat::mcset nl \"Cu&t\" \"Knippen\"\n    ::msgcat::mcset nl \"&Delete\" \"Wissen\"\n    ::msgcat::mcset nl \"Details >>\"\n    ::msgcat::mcset nl \"Directory \\\"%1\\$s\\\" does not exist.\" \"Map \\\"%1\\$s\\\" bestaat niet.\"\n    ::msgcat::mcset nl \"&Directory:\" \"&Map:\"\n    ::msgcat::mcset nl \"&Edit\" \"Bewerken\"\n    ::msgcat::mcset nl \"Effects\" \"Effecten\"\n    ::msgcat::mcset nl \"Error: %1\\$s\" \"Fout: %1\\$s\"\n    ::msgcat::mcset nl \"E&xit\" \"Beëindigen\"\n    ::msgcat::mcset nl \"&File\" \"Bestand\"\n    ::msgcat::mcset nl \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Bestand \\\"%1\\$s\\\" bestaat al.\\nWilt u het overschrijven?\"\n    ::msgcat::mcset nl \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Bestand \\\"%1\\$s\\\" bestaat al.\\n\\n\"\n    ::msgcat::mcset nl \"File \\\"%1\\$s\\\" does not exist.\" \"Bestand \\\"%1\\$s\\\" bestaat niet.\"\n    ::msgcat::mcset nl \"File &name:\" \"Bestands&naam:\"\n    ::msgcat::mcset nl \"File &names:\" \"Bestands&namen:\"\n    ::msgcat::mcset nl \"Files of &type:\" \"Bestanden van het &type:\"\n    ::msgcat::mcset nl \"Fi&les:\" \"&Bestanden:\"\n    ::msgcat::mcset nl \"&Filter\"\n    ::msgcat::mcset nl \"Fil&ter:\"\n    ::msgcat::mcset nl \"Font\"\n    ::msgcat::mcset nl \"&Font:\"\n    ::msgcat::mcset nl \"Font st&yle:\" \"Font stijl:\"\n    ::msgcat::mcset nl \"&Green\" \"&Groen\"\n    ::msgcat::mcset nl \"&Help\"\n    ::msgcat::mcset nl \"Hi\" \"Hé\"\n    ::msgcat::mcset nl \"&Hide Console\" \"Verberg Console\"\n    ::msgcat::mcset nl \"&Ignore\" \"&Negeren\"\n    ::msgcat::mcset nl \"Invalid file name \\\"%1\\$s\\\".\" \"Ongeldige bestandsnaam \\\"%1\\$s\\\".\"\n    ::msgcat::mcset nl \"Italic\" \"Cursief\"\n    ::msgcat::mcset nl \"Log Files\" \"Log Bestanden\"\n    ::msgcat::mcset nl \"&No\" \"&Nee\"\n    ::msgcat::mcset nl \"&OK\"\n    ::msgcat::mcset nl \"OK\"\n    ::msgcat::mcset nl \"Ok\"\n    ::msgcat::mcset nl \"Open\" \"Openen\"\n    ::msgcat::mcset nl \"&Open\" \"&Openen\"\n    ::msgcat::mcset nl \"Open Multiple Files\" \"Open meerdere bestanden\"\n    ::msgcat::mcset nl \"P&aste\" \"Pl&akken\"\n    ::msgcat::mcset nl \"&Quit\" \"Stoppen\"\n    ::msgcat::mcset nl \"&Red\" \"&Rood\"\n    ::msgcat::mcset nl \"Regular\" \"Standaard\"\n    ::msgcat::mcset nl \"Replace existing file?\" \"Vervang bestaand bestand?\"\n    ::msgcat::mcset nl \"&Retry\" \"&Herhalen\"\n    ::msgcat::mcset nl \"Sample\"\n    ::msgcat::mcset nl \"&Save\" \"Op&slaan\"\n    ::msgcat::mcset nl \"Save As\" \"Opslaan als\"\n    ::msgcat::mcset nl \"Save To Log\" \"Opslaan naar Log\"\n    ::msgcat::mcset nl \"Select Log File\" \"Selecteer Log bestand\"\n    ::msgcat::mcset nl \"Select a file to source\" \"Selecteer bronbestand\"\n    ::msgcat::mcset nl \"&Selection:\" \"&Selectie:\"\n    ::msgcat::mcset nl \"&Size:\" \"Grootte\"\n    ::msgcat::mcset nl \"Show &Hidden Directories\" \"Laat verborgen mappen zien\"\n    ::msgcat::mcset nl \"Show &Hidden Files and Directories\" \"Laat verborgen bestanden mappen zien\"\n    ::msgcat::mcset nl \"Skip Messages\" \"Berichten overslaan\"\n    ::msgcat::mcset nl \"&Source...\" \"Bron...\"\n    ::msgcat::mcset nl \"Stri&keout\"\n    ::msgcat::mcset nl \"Tcl Scripts\"\n    ::msgcat::mcset nl \"Tcl for Windows\" \"Tcl voor Windows\"\n    ::msgcat::mcset nl \"Text Files\" \"Tekstbestanden\"\n    ::msgcat::mcset nl \"&Underline\" \"Onderstreept\"\n    ::msgcat::mcset nl \"&Yes\" \"&Ja\"\n    ::msgcat::mcset nl \"abort\" \"afbreken\"\n    ::msgcat::mcset nl \"blue\" \"blauw\"\n    ::msgcat::mcset nl \"cancel\" \"annuleren\"\n    ::msgcat::mcset nl \"extension\"\n    ::msgcat::mcset nl \"extensions\"\n    ::msgcat::mcset nl \"green\" \"groen\"\n    ::msgcat::mcset nl \"ignore\" \"negeren\"\n    ::msgcat::mcset nl \"ok\"\n    ::msgcat::mcset nl \"red\" \"rood\"\n    ::msgcat::mcset nl \"retry\" \"opnieuw\"\n    ::msgcat::mcset nl \"yes\" \"ja\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  nl \"Print\" \"Afdrukken\"\n    ::msgcat::mcset  nl \"Printer\" \"Printer\"\n    ::msgcat::mcset  nl \"Letter \" \"Brief\"\n    ::msgcat::mcset  nl \"Legal \" \"Legaal\"\n    ::msgcat::mcset  nl \"A4\" \"A4\"\n    ::msgcat::mcset  nl \"Grayscale\" \"Grijswaarden\"\n    ::msgcat::mcset  nl \"RGB\" \"Rgb\"\n    ::msgcat::mcset  nl \"Options\" \"Opties\"\n    ::msgcat::mcset  nl \"Copies\" \"Kopieën\"\n    ::msgcat::mcset  nl \"Paper\" \"Papier\"\n    ::msgcat::mcset  nl \"Scale\" \"Schub\"\n    ::msgcat::mcset  nl \"Orientation\" \"Oriëntatie\"\n    ::msgcat::mcset  nl \"Portrait\" \"Portret\"\n    ::msgcat::mcset  nl \"Landscape\" \"Landschap\"\n    ::msgcat::mcset  nl \"Output\" \"Uitvoer\"\n}"
  },
  {
    "path": "library/msgs/pl.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset pl \"&Abort\" \"&Przerwij\"\n    ::msgcat::mcset pl \"&About...\" \"O programie...\"\n    ::msgcat::mcset pl \"All Files\" \"Wszystkie pliki\"\n    ::msgcat::mcset pl \"Application Error\" \"Błąd w programie\"\n    ::msgcat::mcset pl \"&Apply\" \"Zastosuj\"\n    ::msgcat::mcset pl \"Bold\" \"Pogrubienie\"\n    ::msgcat::mcset pl \"Bold Italic\" \"Pogrubiona kursywa\"\n    ::msgcat::mcset pl \"&Blue\" \"&Niebieski\"\n    ::msgcat::mcset pl \"Cancel\" \"Anuluj\"\n    ::msgcat::mcset pl \"&Cancel\" \"&Anuluj\"\n    ::msgcat::mcset pl \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Nie można otworzyć katalogu \\\"%1\\$s\\\".\\nOdmowa dostępu.\"\n    ::msgcat::mcset pl \"Choose Directory\" \"Wybierz katalog\"\n    ::msgcat::mcset pl \"Cl&ear\" \"&Wyczyść\"\n    ::msgcat::mcset pl \"&Clear Console\" \"&Wyczyść konsolę\"\n    ::msgcat::mcset pl \"Color\" \"Kolor\"\n    ::msgcat::mcset pl \"Console\" \"Konsola\"\n    ::msgcat::mcset pl \"&Copy\" \"&Kopiuj\"\n    ::msgcat::mcset pl \"Cu&t\" \"&Wytnij\"\n    ::msgcat::mcset pl \"&Delete\" \"&Usuń\"\n    ::msgcat::mcset pl \"Details >>\" \"Szczegóły >>\"\n    ::msgcat::mcset pl \"Directory \\\"%1\\$s\\\" does not exist.\" \"Katalog \\\"%1\\$s\\\" nie istnieje.\"\n    ::msgcat::mcset pl \"&Directory:\" \"&Katalog:\"\n    ::msgcat::mcset pl \"&Edit\" \"&Edytuj\"\n    ::msgcat::mcset pl \"Effects\" \"Efekty\"\n    ::msgcat::mcset pl \"Error: %1\\$s\" \"Błąd: %1\\$s\"\n    ::msgcat::mcset pl \"E&xit\" \"&Wyjdź\"\n    ::msgcat::mcset pl \"&File\" \"&Plik\"\n    ::msgcat::mcset pl \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Plik \\\"%1\\$s\\\" już istnieje.\\nCzy chcesz go nadpisać?\"\n    ::msgcat::mcset pl \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Plik \\\"%1\\$s\\\" już istnieje.\\n\\n\"\n    ::msgcat::mcset pl \"File \\\"%1\\$s\\\" does not exist.\" \"Plik \\\"%1\\$s\\\" nie istnieje.\"\n    ::msgcat::mcset pl \"File &name:\" \"Nazwa &pliku:\"\n    ::msgcat::mcset pl \"File &names:\" \"Nazwy &plików:\"\n    ::msgcat::mcset pl \"Files of &type:\" \"Pliki &typu:\"\n    ::msgcat::mcset pl \"Fi&les:\" \"Pli&ki:\"\n    ::msgcat::mcset pl \"&Filter\" \"&Filtr\"\n    ::msgcat::mcset pl \"Fil&ter:\" \"&Filtr:\"\n    ::msgcat::mcset pl \"Font\" \"Czcionka\"\n    ::msgcat::mcset pl \"&Font:\" \"Czcio&nka:\"\n    ::msgcat::mcset pl \"Font st&yle:\" \"&Styl czcionki:\"\n    ::msgcat::mcset pl \"&Green\" \"&Zielony\"\n    ::msgcat::mcset pl \"&Help\" \"&Pomoc\"\n    ::msgcat::mcset pl \"Hi\" \"Witaj\"\n    ::msgcat::mcset pl \"&Hide Console\" \"&Ukryj konsolę\"\n    ::msgcat::mcset pl \"&Ignore\" \"&Ignoruj\"\n    ::msgcat::mcset pl \"Invalid file name \\\"%1\\$s\\\".\" \"Niewłaściwa nazwa pliku \\\"%1\\$s\\\".\"\n    ::msgcat::mcset pl \"Italic\" \"Kursywa\"\n    ::msgcat::mcset pl \"Log Files\" \"Pliki dziennika\"\n    ::msgcat::mcset pl \"&No\" \"&Nie\"\n    ::msgcat::mcset pl \"&OK\"\n    ::msgcat::mcset pl \"OK\"\n    ::msgcat::mcset pl \"Ok\"\n    ::msgcat::mcset pl \"Open\" \"Otwórz\"\n    ::msgcat::mcset pl \"&Open\" \"&Otwórz\"\n    ::msgcat::mcset pl \"Open Multiple Files\" \"Otwórz wiele plików\"\n    ::msgcat::mcset pl \"P&aste\" \"&Wklej\"\n    ::msgcat::mcset pl \"&Quit\" \"&Zakończ\"\n    ::msgcat::mcset pl \"&Red\" \"&Czerwony\"\n    ::msgcat::mcset pl \"Regular\" \"Regularne\"\n    ::msgcat::mcset pl \"Replace existing file?\" \"Czy zastąpić istniejący plik?\"\n    ::msgcat::mcset pl \"&Retry\" \"&Ponów\"\n    ::msgcat::mcset pl \"Sample\" \"Przykład\"\n    ::msgcat::mcset pl \"&Save\" \"&Zapisz\"\n    ::msgcat::mcset pl \"Save As\" \"Zapisz jako\"\n    ::msgcat::mcset pl \"Save To Log\" \"Wpisz do dziennika\"\n    ::msgcat::mcset pl \"Select Log File\" \"Wybierz plik dziennika\"\n    ::msgcat::mcset pl \"Select a file to source\" \"Wybierz plik do wykonania\"\n    ::msgcat::mcset pl \"&Selection:\" \"&Wybór:\"\n    ::msgcat::mcset pl \"&Size:\" \"&Rozmiar:\"\n    ::msgcat::mcset pl \"Show &Hidden Directories\" \"Pokaż &ukryte katalogi\"\n    ::msgcat::mcset pl \"Show &Hidden Files and Directories\" \"Pokaż &ukryte pliki i katalogi\"\n    ::msgcat::mcset pl \"Skip Messages\" \"Pomiń pozostałe komunikaty\"\n    ::msgcat::mcset pl \"&Source...\" \"&Kod źródłowy...\"\n    ::msgcat::mcset pl \"Stri&keout\" \"&Przekreślenie\"\n    ::msgcat::mcset pl \"Tcl Scripts\" \"Skrypty Tcl\"\n    ::msgcat::mcset pl \"Tcl for Windows\" \"Tcl dla Windows\"\n    ::msgcat::mcset pl \"Text Files\" \"Pliki tekstowe\"\n    ::msgcat::mcset pl \"&Underline\" \"Po&dkreślenie\"\n    ::msgcat::mcset pl \"&Yes\" \"&Tak\"\n    ::msgcat::mcset pl \"abort\" \"przerwij\"\n    ::msgcat::mcset pl \"blue\" \"niebieski\"\n    ::msgcat::mcset pl \"cancel\" \"anuluj\"\n    ::msgcat::mcset pl \"extension\" \"rozszerzenie\"\n    ::msgcat::mcset pl \"extensions\" \"rozszerzenia\"\n    ::msgcat::mcset pl \"green\" \"zielony\"\n    ::msgcat::mcset pl \"ignore\" \"ignoruj\"\n    ::msgcat::mcset pl \"ok\"\n    ::msgcat::mcset pl \"red\" \"czerwony\"\n    ::msgcat::mcset pl \"retry\" \"ponów\"\n    ::msgcat::mcset pl \"yes\" \"tak\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  pl \"Print\" \"Drukować\"\n    ::msgcat::mcset  pl \"Printer\" \"Drukarka\"\n    ::msgcat::mcset  pl \"Letter \" \"Litera\"\n    ::msgcat::mcset  pl \"Legal \" \"Legalny\"\n    ::msgcat::mcset  pl \"A4\" \"A4\"\n    ::msgcat::mcset  pl \"Grayscale\" \"Skala Szarości\"\n    ::msgcat::mcset  pl \"RGB\" \"Rgb\"\n    ::msgcat::mcset  pl \"Options\" \"Opcje\"\n    ::msgcat::mcset  pl \"Copies\" \"Kopie\"\n    ::msgcat::mcset  pl \"Paper\" \"Papier\"\n    ::msgcat::mcset  pl \"Scale\" \"Skala\"\n    ::msgcat::mcset  pl \"Orientation\" \"Orientacja\"\n    ::msgcat::mcset  pl \"Portrait\" \"Portret\"\n    ::msgcat::mcset  pl \"Landscape\" \"Krajobraz\"\n    ::msgcat::mcset  pl \"Output\" \"Produkt Wyjściowy\"\n}"
  },
  {
    "path": "library/msgs/pt.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset pt \"&Abort\" \"&Abortar\"\n    ::msgcat::mcset pt \"About...\" \"Sobre ...\"\n    ::msgcat::mcset pt \"All Files\" \"Todos os arquivos\"\n    ::msgcat::mcset pt \"Application Error\" \"Erro de aplicação\"\n    ::msgcat::mcset pt \"&Blue\" \"&Azul\"\n    ::msgcat::mcset pt \"Cancel\" \"Cancelar\"\n    ::msgcat::mcset pt \"&Cancel\" \"&Cancelar\"\n    ::msgcat::mcset pt \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Não foi possível mudar para o diretório \\\"%1\\$s\\\".\\nPermissão negada.\"\n    ::msgcat::mcset pt \"Choose Directory\" \"Escolha um diretório\"\n    ::msgcat::mcset pt \"Cl&ear\" \"Apagar\"\n    ::msgcat::mcset pt \"&Clear Console\" \"Apagar Console\"\n    ::msgcat::mcset pt \"Color\" \"Cor\"\n    ::msgcat::mcset pt \"Console\"\n    ::msgcat::mcset pt \"&Copy\" \"Copiar\"\n    ::msgcat::mcset pt \"Cu&t\" \"Recortar\"\n    ::msgcat::mcset pt \"&Delete\" \"Excluir\"\n    ::msgcat::mcset pt \"Details >>\" \"Detalhes >>\"\n    ::msgcat::mcset pt \"Directory \\\"%1\\$s\\\" does not exist.\" \"O diretório \\\"%1\\$s\\\" não existe.\"\n    ::msgcat::mcset pt \"&Directory:\" \"&Diretório:\"\n    ::msgcat::mcset pt \"Error: %1\\$s\" \"Erro: %1\\$s\"\n    ::msgcat::mcset pt \"E&xit\" \"Sair\"\n    ::msgcat::mcset pt \"&File\" \"Arquivo\"\n    ::msgcat::mcset pt \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"O arquivo \\\"%1\\$s\\\" já existe.\\nDeseja sobrescreve-lo?\"\n    ::msgcat::mcset pt \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"O arquivo \\\"%1\\$s\\\" já existe.\\n\\n\"\n    ::msgcat::mcset pt \"File \\\"%1\\$s\\\" does not exist.\" \"Arquivo \\\"%1\\$s\\\" não existe.\"\n    ::msgcat::mcset pt \"File &name:\" \"&Nome do arquivo:\"\n    ::msgcat::mcset pt \"File &names:\" \"&Nomes dos arquivos:\"\n    ::msgcat::mcset pt \"Files of &type:\" \"Arquivos do &tipo:\"\n    ::msgcat::mcset pt \"Fi&les:\" \"&Arquivos:\"\n    ::msgcat::mcset pt \"&Filter\" \"&Filtro\"\n    ::msgcat::mcset pt \"Fil&ter:\" \"Fil&tro:\"\n    ::msgcat::mcset pt \"&Green\" \"&Verde\"\n    ::msgcat::mcset pt \"Hi\" \"Oi\"\n    ::msgcat::mcset pt \"&Hide Console\" \"Ocultar console\"\n    ::msgcat::mcset pt \"&Ignore\" \"&Ignorar\"\n    ::msgcat::mcset pt \"Invalid file name \\\"%1\\$s\\\".\" \"O nome do arquivo é inválido \\\"%1\\$s\\\".\"\n    ::msgcat::mcset pt \"Log Files\" \"Arquivos de log\"\n    ::msgcat::mcset pt \"&No\" \"&Não\"\n    ::msgcat::mcset pt \"&OK\"\n    ::msgcat::mcset pt \"OK\"\n    ::msgcat::mcset pt \"Ok\"\n    ::msgcat::mcset pt \"Open\" \"Abrir\"\n    ::msgcat::mcset pt \"&Open\" \"&Abrir\"\n    ::msgcat::mcset pt \"Open Multiple Files\" \"Abrir múltiplos arquivos\"\n    ::msgcat::mcset pt \"P&aste\" \"Col&ar\"\n    ::msgcat::mcset pt \"Quit\" \"Encerrar\"\n    ::msgcat::mcset pt \"&Red\" \"&Vermelho\"\n    ::msgcat::mcset pt \"Replace existing file?\" \"Substituir arquivo existente?\"\n    ::msgcat::mcset pt \"&Retry\" \"Tenta&r novamente\"\n    ::msgcat::mcset pt \"&Save\" \"&Salvar\"\n    ::msgcat::mcset pt \"Save As\" \"Salvar como\"\n    ::msgcat::mcset pt \"Save To Log\" \"Salvar arquivo de log\"\n    ::msgcat::mcset pt \"Select Log File\" \"Selecionar arquivo de log\"\n    ::msgcat::mcset pt \"Select a file to source\" \"Selecione um arquivo como fonte\"\n    ::msgcat::mcset pt \"&Selection:\" \"&Seleção:\"\n    ::msgcat::mcset pt \"Skip Messages\" \"Omitir as mensagens\"\n    ::msgcat::mcset pt \"&Source...\" \"&Fonte...\"\n    ::msgcat::mcset pt \"Tcl Scripts\" \"Scripts Tcl\"\n    ::msgcat::mcset pt \"Tcl for Windows\" \"Tcl para Windows\"\n    ::msgcat::mcset pt \"Text Files\" \"Arquivos de texto\"\n    ::msgcat::mcset pt \"&Yes\" \"&Sim\"\n    ::msgcat::mcset pt \"abort\" \"abortar\"\n    ::msgcat::mcset pt \"blue\" \"azul\"\n    ::msgcat::mcset pt \"cancel\" \"cancelar\"\n    ::msgcat::mcset pt \"extension\" \"extensão\"\n    ::msgcat::mcset pt \"extensions\" \"extensões\"\n    ::msgcat::mcset pt \"green\" \"verde\"\n    ::msgcat::mcset pt \"ignore\" \"ignorar\"\n    ::msgcat::mcset pt \"ok\"\n    ::msgcat::mcset pt \"red\" \"vermelho\"\n    ::msgcat::mcset pt \"retry\" \"tentar novamente\"\n    ::msgcat::mcset pt \"yes\" \"sim\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  pt \"Print\" \"Imprimir\"\n    ::msgcat::mcset  pt \"Printer\" \"Impressora\"\n    ::msgcat::mcset  pt \"Letter \" \"Letra\"\n    ::msgcat::mcset  pt \"Legal \" \"Legal\"\n    ::msgcat::mcset  pt \"A4\" \"A4\"\n    ::msgcat::mcset  pt \"Grayscale\" \"Escala De Cinza\"\n    ::msgcat::mcset  pt \"RGB\" \"Rgb\"\n    ::msgcat::mcset  pt \"Options\" \"Opções\"\n    ::msgcat::mcset  pt \"Copies\" \"Exemplares\"\n    ::msgcat::mcset  pt \"Paper\" \"Papel\"\n    ::msgcat::mcset  pt \"Scale\" \"Escala\"\n    ::msgcat::mcset  pt \"Orientation\" \"Orientação\"\n    ::msgcat::mcset  pt \"Portrait\" \"Retrato\"\n    ::msgcat::mcset  pt \"Landscape\" \"Paisagem\"\n    ::msgcat::mcset  pt \"Output\" \"Saída\"\n}"
  },
  {
    "path": "library/msgs/ru.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset ru \"&Abort\" \"&Отменить\"\n    ::msgcat::mcset ru \"&About...\" \"Про...\"\n    ::msgcat::mcset ru \"All Files\" \"Все файлы\"\n    ::msgcat::mcset ru \"Application Error\" \"Ошибка в программе\"\n    ::msgcat::mcset ru \"&Apply\" \"&Применить\"\n    ::msgcat::mcset ru \"Bold\" \"Bold\"\n    ::msgcat::mcset ru \"Bold Italic\" \"Bold Italic\"\n    ::msgcat::mcset ru \"&Blue\" \" &Голубой\"\n    ::msgcat::mcset ru \"Cancel\" \"Отмена\"\n    ::msgcat::mcset ru \"&Cancel\" \"От&мена\"\n    ::msgcat::mcset ru \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \\\n\t\t\t\"Не могу перейти в каталог \\\"%1\\$s\\\".\\nНедостаточно прав доступа\"\n    ::msgcat::mcset ru \"Choose Directory\" \"Выберите каталог\"\n    ::msgcat::mcset ru \"Cl&ear\" \"Очистить\"\n    ::msgcat::mcset ru \"&Clear Console\" \"&Clear Console\"\n    ::msgcat::mcset ru \"Color\" \"Цвет\"\n    ::msgcat::mcset ru \"Console\" \"Консоль\"\n    ::msgcat::mcset ru \"&Copy\" \"Копировать\"\n    ::msgcat::mcset ru \"Cu&t\" \"Вырезать\"\n    ::msgcat::mcset ru \"&Delete\" \"Удалить\"\n    ::msgcat::mcset ru \"Details >>\" \"Подробнее >>\"\n    ::msgcat::mcset ru \"Directory \\\"%1\\$s\\\" does not exist.\" \"Каталога \\\"%1\\$s\\\" не существует.\"\n    ::msgcat::mcset ru \"&Directory:\" \"&Каталог:\"\n    ::msgcat::mcset ru \"&Edit\" \"&Edit\"\n    ::msgcat::mcset ru \"Effects\" \"Эффекты\"\n    ::msgcat::mcset ru \"Error: %1\\$s\" \"Ошибка: %1\\$s\"\n    ::msgcat::mcset ru \"E&xit\" \"Выход\"\n    ::msgcat::mcset ru \"&File\" \"&File\"\n    ::msgcat::mcset ru \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \\\n\t\t\t    \"Файл \\\"%1\\$s\\\" уже существует.\\nЗаменить его?\"\n    ::msgcat::mcset ru \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Файл \\\"%1\\$s\\\" уже существует.\\n\\n\"\n    ::msgcat::mcset ru \"File \\\"%1\\$s\\\" does not exist.\" \"Файл \\\"%1\\$s\\\" не найден.\"\n    ::msgcat::mcset ru \"File &name:\" \"&Имя файла:\"\n    ::msgcat::mcset ru \"File &names:\" \"&Имена файлов:\"\n    ::msgcat::mcset ru \"Files of &type:\" \"&Тип файлов:\"\n    ::msgcat::mcset ru \"Fi&les:\" \"Фай&лы:\"\n    ::msgcat::mcset ru \"&Filter\" \"&Фильтр\"\n    ::msgcat::mcset ru \"Fil&ter:\" \"Филь&тр:\"\n    ::msgcat::mcset ru \"Font\" \"Шрифт\"\n    ::msgcat::mcset ru \"&Font:\" \"&Шрифт\"\n    ::msgcat::mcset ru \"Font st&yle:\" \"&Стиль шрифта:\"\n    ::msgcat::mcset ru \"&Green\" \" &Зеленый\"\n    ::msgcat::mcset ru \"&Help\" \"&Help\"\n    ::msgcat::mcset ru \"Hi\" \"Привет\"\n    ::msgcat::mcset ru \"&Hide Console\" \"Спрятать консоль\"\n    ::msgcat::mcset ru \"&Ignore\" \"&Игнорировать\"\n    ::msgcat::mcset ru \"Invalid file name \\\"%1\\$s\\\".\" \"Неверное имя файла \\\"%1\\$s\\\".\"\n    ::msgcat::mcset ru \"Italic\" \"Italic\"\n    ::msgcat::mcset ru \"Log Files\" \"Файлы журнала\"\n    ::msgcat::mcset ru \"&No\" \"&Нет\"\n    ::msgcat::mcset ru \"&OK\" \"&ОК\"\n    ::msgcat::mcset ru \"OK\" \"ОК\"\n    ::msgcat::mcset ru \"Ok\" \"Да\"\n    ::msgcat::mcset ru \"Open\" \"Открыть\"\n    ::msgcat::mcset ru \"&Open\" \"&Открыть\"\n    ::msgcat::mcset ru \"Open Multiple Files\" \"Открыть несколько файлов\"\n    ::msgcat::mcset ru \"P&aste\" \"Вставить\"\n    ::msgcat::mcset ru \"&Quit\" \"Выход\"\n    ::msgcat::mcset ru \"&Red\" \" &Красный\"\n    ::msgcat::mcset ru \"Replace existing file?\" \"Заменить существующий файл?\"\n    ::msgcat::mcset ru \"Regular\" \"Regular\"\n    ::msgcat::mcset ru \"&Retry\" \"&Повторить\"\n    ::msgcat::mcset ru \"Sample\" \"Пример\"\n    ::msgcat::mcset ru \"&Save\" \"&Сохранить\"\n    ::msgcat::mcset ru \"Save As\" \"Сохранить как\"\n    ::msgcat::mcset ru \"Save To Log\" \"Сохранить в журнал\"\n    ::msgcat::mcset ru \"Select Log File\" \"Выбрать журнал\"\n    ::msgcat::mcset ru \"Select a file to source\" \"Выберите файл для интерпретации\"\n    ::msgcat::mcset ru \"&Selection:\"\n    ::msgcat::mcset ru \"&Size:\" \"&Размер:\"\n    ::msgcat::mcset ru \"Show &Hidden Directories\" \"Show &Hidden Directories\"\n    ::msgcat::mcset ru \"Show &Hidden Files and Directories\" \"Show &Hidden Files and Directories\"\n    ::msgcat::mcset ru \"Skip Messages\" \"Пропустить сообщения\"\n    ::msgcat::mcset ru \"&Source...\" \"Интерпретировать файл...\"\n    ::msgcat::mcset ru \"Stri&keout\" \"П&еречёркнутый\"\n    ::msgcat::mcset ru \"Tcl Scripts\" \"Программа на языке TCL\"\n    ::msgcat::mcset ru \"Tcl for Windows\" \"TCL для Windows\"\n    ::msgcat::mcset ru \"Text Files\" \"Текстовые файлы\"\n    ::msgcat::mcset ru \"&Underline\" \"По&дчеркнутый\"\n    ::msgcat::mcset ru \"&Yes\" \"&Да\"\n    ::msgcat::mcset ru \"abort\" \"отмена\"\n    ::msgcat::mcset ru \"blue\" \" голубой\"\n    ::msgcat::mcset ru \"cancel\" \"отмена\"\n    ::msgcat::mcset ru \"extension\" \"расширение\"\n    ::msgcat::mcset ru \"extensions\" \"расширения\"\n    ::msgcat::mcset ru \"green\" \" зеленый\"\n    ::msgcat::mcset ru \"ignore\" \"пропустить\"\n    ::msgcat::mcset ru \"ok\" \"ок\"\n    ::msgcat::mcset ru \"red\" \" красный\"\n    ::msgcat::mcset ru \"retry\" \"повторить\"\n    ::msgcat::mcset ru \"yes\" \"да\"\n}\n\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  ru \"Print\" \"Печатать\"\n    ::msgcat::mcset  ru \"Printer\" \"Принтер\"\n    ::msgcat::mcset  ru \"Letter \" \"Письмо\"\n    ::msgcat::mcset  ru \"Legal \" \"Законный\"\n    ::msgcat::mcset  ru \"A4\" \"A4\"\n    ::msgcat::mcset  ru \"Grayscale\" \"Серый Масштаб\"\n    ::msgcat::mcset  ru \"RGB\" \"Ргб\"\n    ::msgcat::mcset  ru \"Options\" \"Параметры\"\n    ::msgcat::mcset  ru \"Copies\" \"Копии\"\n    ::msgcat::mcset  ru \"Paper\" \"Бумага\"\n    ::msgcat::mcset  ru \"Scale\" \"Шкала\"\n    ::msgcat::mcset  ru \"Orientation\" \"Ориентация\"\n    ::msgcat::mcset  ru \"Portrait\" \"Портрет\"\n    ::msgcat::mcset  ru \"Landscape\" \"Ландшафт\"\n    ::msgcat::mcset  ru \"Output\" \"Выпуск\"\n}"
  },
  {
    "path": "library/msgs/sv.msg",
    "content": "namespace eval ::tk {\n    ::msgcat::mcset sv \"&Abort\" \"&Avsluta\"\n    ::msgcat::mcset sv \"&About...\" \"&Om...\"\n    ::msgcat::mcset sv \"All Files\" \"Samtliga filer\"\n    ::msgcat::mcset sv \"Application Error\" \"Programfel\"\n    ::msgcat::mcset sv \"&Blue\" \"&Blå\"\n    ::msgcat::mcset sv \"Cancel\" \"Avbryt\"\n    ::msgcat::mcset sv \"&Cancel\" \"&Avbryt\"\n    ::msgcat::mcset sv \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"Kan ej nå mappen \\\"%1\\$s\\\".\\nSaknar rättigheter.\"\n    ::msgcat::mcset sv \"Choose Directory\" \"Välj mapp\"\n    ::msgcat::mcset sv \"Cl&ear\" \"&Radera\"\n    ::msgcat::mcset sv \"&Clear Console\" \"&Radera konsollen\"\n    ::msgcat::mcset sv \"Color\" \"Färg\"\n    ::msgcat::mcset sv \"Console\" \"Konsoll\"\n    ::msgcat::mcset sv \"&Copy\" \"&Kopiera\"\n    ::msgcat::mcset sv \"Cu&t\" \"Klipp u&t\"\n    ::msgcat::mcset sv \"&Delete\" \"&Radera\"\n    ::msgcat::mcset sv \"Details >>\" \"Detaljer >>\"\n    ::msgcat::mcset sv \"Directory \\\"%1\\$s\\\" does not exist.\" \"Mappen \\\"%1\\$s\\\" finns ej.\"\n    ::msgcat::mcset sv \"&Directory:\" \"&Mapp:\"\n    ::msgcat::mcset sv \"&Edit\" \"R&edigera\"\n    ::msgcat::mcset sv \"Error: %1\\$s\" \"Fel: %1\\$s\"\n    ::msgcat::mcset sv \"E&xit\" \"&Avsluta\"\n    ::msgcat::mcset sv \"&File\" \"&Fil\"\n    ::msgcat::mcset sv \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"Filen \\\"%1\\$s\\\" finns redan.\\nVill du skriva över den?\"\n    ::msgcat::mcset sv \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"Filen \\\"%1\\$s\\\" finns redan.\\n\\n\"\n    ::msgcat::mcset sv \"File \\\"%1\\$s\\\" does not exist.\" \"Filen \\\"%1\\$s\\\" finns ej.\"\n    ::msgcat::mcset sv \"File &name:\" \"Fil&namn:\"\n    ::msgcat::mcset sv \"File &names:\" \"Fil&namn:\"\n    ::msgcat::mcset sv \"Files of &type:\" \"Filer av &typ:\"\n    ::msgcat::mcset sv \"Fi&les:\" \"Fi&ler:\"\n    ::msgcat::mcset sv \"&Filter\"\n    ::msgcat::mcset sv \"Fil&ter:\"\n    ::msgcat::mcset sv \"&Green\" \"&Grön\"\n    ::msgcat::mcset sv \"&Help\" \"&Hjälp\"\n    ::msgcat::mcset sv \"Hi\" \"Hej\"\n    ::msgcat::mcset sv \"&Hide Console\" \"&Göm konsollen\"\n    ::msgcat::mcset sv \"&Ignore\" \"&Ignorera\"\n    ::msgcat::mcset sv \"Invalid file name \\\"%1\\$s\\\".\" \"Ogiltigt filnamn \\\"%1\\$s\\\".\"\n    ::msgcat::mcset sv \"Log Files\" \"Loggfiler\"\n    ::msgcat::mcset sv \"&No\" \"&Nej\"\n    ::msgcat::mcset sv \"&OK\"\n    ::msgcat::mcset sv \"OK\"\n    ::msgcat::mcset sv \"Ok\"\n    ::msgcat::mcset sv \"Open\" \"Öppna\"\n    ::msgcat::mcset sv \"&Open\" \"&Öppna\"\n    ::msgcat::mcset sv \"Open Multiple Files\" \"Öppna flera filer\"\n    ::msgcat::mcset sv \"P&aste\" \"&Klistra in\"\n    ::msgcat::mcset sv \"&Quit\" \"&Avsluta\"\n    ::msgcat::mcset sv \"&Red\" \"&Röd\"\n    ::msgcat::mcset sv \"Replace existing file?\" \"Ersätt existerande fil?\"\n    ::msgcat::mcset sv \"&Retry\" \"&Försök igen\"\n    ::msgcat::mcset sv \"&Save\" \"&Spara\"\n    ::msgcat::mcset sv \"Save As\" \"Spara som\"\n    ::msgcat::mcset sv \"Save To Log\" \"Spara till logg\"\n    ::msgcat::mcset sv \"Select Log File\" \"Välj loggfil\"\n    ::msgcat::mcset sv \"Select a file to source\" \"Välj källfil\"\n    ::msgcat::mcset sv \"&Selection:\" \"&Val:\"\n    ::msgcat::mcset sv \"Skip Messages\" \"Hoppa över meddelanden\"\n    ::msgcat::mcset sv \"&Source...\" \"&Källa...\"\n    ::msgcat::mcset sv \"Tcl Scripts\" \"Tcl skript\"\n    ::msgcat::mcset sv \"Tcl for Windows\" \"Tcl för Windows\"\n    ::msgcat::mcset sv \"Text Files\" \"Textfiler\"\n    ::msgcat::mcset sv \"&Yes\" \"&Ja\"\n    ::msgcat::mcset sv \"abort\" \"avbryt\"\n    ::msgcat::mcset sv \"blue\" \"blå\"\n    ::msgcat::mcset sv \"cancel\" \"avbryt\"\n    ::msgcat::mcset sv \"extension\" \"utvidgning\"\n    ::msgcat::mcset sv \"extensions\" \"utvidgningar\"\n    ::msgcat::mcset sv \"green\" \"grön\"\n    ::msgcat::mcset sv \"ignore\" \"ignorera\"\n    ::msgcat::mcset sv \"ok\"\n    ::msgcat::mcset sv \"red\" \"röd\"\n    ::msgcat::mcset sv \"retry\" \"försök igen\"\n    ::msgcat::mcset sv \"yes\" \"ja\"\n}\n#localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  sv \"Print\" \"Trycka\"\n    ::msgcat::mcset  sv \"Printer\" \"Skrivare\"\n    ::msgcat::mcset  sv \"Letter \" \"Brev\"\n    ::msgcat::mcset  sv \"Legal \" \"Laglig\"\n    ::msgcat::mcset  sv \"A4\" \"A4 (På 199\"\n    ::msgcat::mcset  sv \"Grayscale\" \"Gråskala\"\n    ::msgcat::mcset  sv \"RGB\" \"Rgb\"\n    ::msgcat::mcset  sv \"Options\" \"Alternativ\"\n    ::msgcat::mcset  sv \"Copies\" \"Kopior\"\n    ::msgcat::mcset  sv \"Paper\" \"Papper\"\n    ::msgcat::mcset  sv \"Scale\" \"Skala\"\n    ::msgcat::mcset  sv \"Orientation\" \"Orientering\"\n    ::msgcat::mcset  sv \"Portrait\" \"Porträtt\"\n    ::msgcat::mcset  sv \"Landscape\" \"Landskap\"\n    ::msgcat::mcset  sv \"Output\" \"Utdata\"\n}"
  },
  {
    "path": "library/msgs/zh_cn.msg",
    "content": "# Ticket c992660e: keyboard shortcuts like (&A) should be for an English keyboard added in parenthesis\nnamespace eval ::tk {\n    ::msgcat::mcset zh_cn \"&Abort\" \"中止(&A)\"\n    ::msgcat::mcset zh_cn \"&About...\" \"关于……(&A)\"\n    ::msgcat::mcset zh_cn \"All Files\" \"所有文件\"\n    ::msgcat::mcset zh_cn \"Application Error\" \"应用程序错误\"\n    ::msgcat::mcset zh_cn \"&Apply\" \"添加(&A)\"\n    ::msgcat::mcset zh_cn \"Bold\" \"粗体\"\n    ::msgcat::mcset zh_cn \"Bold Italic\" \"加粗斜体\"\n    ::msgcat::mcset zh_cn \"&Blue\" \"蓝色(&B)\"\n    ::msgcat::mcset zh_cn \"Cancel\" \"取消\"\n    ::msgcat::mcset zh_cn \"&Cancel\" \"取消(&C)\"\n    ::msgcat::mcset zh_cn \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" \"无法更改目录 \\\"%1\\$s\\\"。\\n访问被拒绝。\"\n    ::msgcat::mcset zh_cn \"Choose Directory\" \"选择文件夹\"\n    ::msgcat::mcset zh_cn \"Cl&ear\" \"清除(&E)\"\n    ::msgcat::mcset zh_cn \"&Clear Console\" \"清除终端(&C)\"\n    ::msgcat::mcset zh_cn \"Color\" \"颜色\"\n    ::msgcat::mcset zh_cn \"Console\" \"终端\"\n    ::msgcat::mcset zh_cn \"&Copy\" \"复制(&C)\"\n    ::msgcat::mcset zh_cn \"Cu&t\" \"剪切(&T)\"\n    ::msgcat::mcset zh_cn \"&Delete\" \"删除(&D)\"\n    ::msgcat::mcset zh_cn \"Details >>\" \"详细信息 >>\"\n    ::msgcat::mcset zh_cn \"Directory \\\"%1\\$s\\\" does not exist.\" \"目录 \\\"%1\\$s\\\" 不存在。\"\n    ::msgcat::mcset zh_cn \"&Directory:\" \"目录(&D)：\"\n    ::msgcat::mcset zh_cn \"&Edit\" \"编辑(&E)\"\n    ::msgcat::mcset zh_cn \"Effects\" \"效果\"\n    ::msgcat::mcset zh_cn \"Error: %1\\$s\" \"错误： %1\\$s\"\n    ::msgcat::mcset zh_cn \"E&xit\" \"退出(&X)\"\n    ::msgcat::mcset zh_cn \"&File\" \"文件(&F)\"\n    ::msgcat::mcset zh_cn \"File \\\"%1\\$s\\\" already exists.\\nDo you want to overwrite it?\" \"文件 \\\"%1\\$s\\\" 已经存在。\\n您想要覆盖它吗？\"\n    ::msgcat::mcset zh_cn \"File \\\"%1\\$s\\\" already exists.\\n\\n\" \"文件 \\\"%1\\$s\\\" 已经存在。\\n\\n\"\n    ::msgcat::mcset zh_cn \"File \\\"%1\\$s\\\" does not exist.\" \"文件 \\\"%1\\$s\\\" 不存在。\"\n    ::msgcat::mcset zh_cn \"File &name:\" \"文件名(&N)：\"\n    ::msgcat::mcset zh_cn \"File &names:\" \"文件&名(&N)：\"\n    ::msgcat::mcset zh_cn \"Files of &type:\" \"文件类型(&T)：\"\n    ::msgcat::mcset zh_cn \"Fi&les:\" \"文件(&L)：\"\n    ::msgcat::mcset zh_cn \"&Filter\" \"过滤(&F)\"\n    ::msgcat::mcset zh_cn \"Fil&ter:\" \"过滤(&T)：\"\n    ::msgcat::mcset zh_cn \"Font\" \"字体\"\n    ::msgcat::mcset zh_cn \"&Font:\" \"字体(&G)：\"\n    ::msgcat::mcset zh_cn \"Font st&yle:\" \"字体样式(&Y)：\"\n    ::msgcat::mcset zh_cn \"&Green\" \"绿色(&G)\"\n    ::msgcat::mcset zh_cn \"&Help\" \"帮助(&H)\"\n    ::msgcat::mcset zh_cn \"Hi\" \"你好\"\n    ::msgcat::mcset zh_cn \"&Hide Console\" \"隐藏终端(&H)\"\n    ::msgcat::mcset zh_cn \"&Ignore\" \"忽略(&I)\"\n    ::msgcat::mcset zh_cn \"Invalid file name \\\"%1\\$s\\\".\" \"无效的文件名 \\\"%1\\$s\\\"。\"\n    ::msgcat::mcset zh_cn \"Italic\" \"斜体\"\n    ::msgcat::mcset zh_cn \"Log Files\" \"日志文件\"\n    ::msgcat::mcset zh_cn \"&No\" \"否(&N)\"\n    ::msgcat::mcset zh_cn \"&OK\" \"确定(&O)\"\n    ::msgcat::mcset zh_cn \"OK\" \"确定\"\n    ::msgcat::mcset zh_cn \"Ok\" \"确定\"\n    ::msgcat::mcset zh_cn \"Open\" \"打开\"\n    ::msgcat::mcset zh_cn \"&Open\" \"打开(&O)\"\n    ::msgcat::mcset zh_cn \"Open Multiple Files\" \"打开多个文件\"\n    ::msgcat::mcset zh_cn \"P&aste\" \"粘贴(&A)\"\n    ::msgcat::mcset zh_cn \"&Quit\" \"退出(&Q)\"\n    ::msgcat::mcset zh_cn \"&Red\" \"红色(&R)\"\n    ::msgcat::mcset zh_cn \"Regular\" \"规则\"\n    ::msgcat::mcset zh_cn \"Replace existing file?\" \"替换已有文件？\"\n    ::msgcat::mcset zh_cn \"&Retry\" \"重试(&R)\"\n    ::msgcat::mcset zh_cn \"Sample\" \"样式\"\n    ::msgcat::mcset zh_cn \"&Save\" \"保存(&S)\"\n    ::msgcat::mcset zh_cn \"Save As\" \"另存为\"\n    ::msgcat::mcset zh_cn \"Save To Log\" \"保存到日志\"\n    ::msgcat::mcset zh_cn \"Select Log File\" \"选择日志文件\"\n    ::msgcat::mcset zh_cn \"Select a file to source\" \"选择一个源文件\"\n    ::msgcat::mcset zh_cn \"&Selection:\" \"选择(&S)：\"\n    ::msgcat::mcset zh_cn \"&Size:\" \"大小(&S)：\"\n    ::msgcat::mcset zh_cn \"Show &Hidden Directories\" \"显示隐藏目录(&H)\"\n    ::msgcat::mcset zh_cn \"Show &Hidden Files and Directories\" \"显示隐藏文件和目录(&H)\"\n    ::msgcat::mcset zh_cn \"Skip Messages\" \"跳过信息\"\n    ::msgcat::mcset zh_cn \"&Source...\" \"来源……(&S)\"\n    ::msgcat::mcset zh_cn \"Stri&keout\" \"删除线(&K)\"\n    ::msgcat::mcset zh_cn \"Tcl Scripts\" \"Tcl脚本\"\n    ::msgcat::mcset zh_cn \"Tcl for Windows\" \"适用于Windows的Tcl\"\n    ::msgcat::mcset zh_cn \"Text Files\" \"文本文档\"\n    ::msgcat::mcset zh_cn \"&Underline\" \"下划线(&U)\"\n    ::msgcat::mcset zh_cn \"&Yes\" \"确定(&Y)\"\n    ::msgcat::mcset zh_cn \"abort\" \"中止\"\n    ::msgcat::mcset zh_cn \"blue\" \"蓝色\"\n    ::msgcat::mcset zh_cn \"cancel\" \"取消\"\n    ::msgcat::mcset zh_cn \"extension\" \"拓展\"\n    ::msgcat::mcset zh_cn \"extensions\" \"拓展\"\n    ::msgcat::mcset zh_cn \"green\" \"绿色\"\n    ::msgcat::mcset zh_cn \"ignore\" \"忽略\"\n    ::msgcat::mcset zh_cn \"ok\" \"确定\"\n    ::msgcat::mcset zh_cn \"red\" \"红色\"\n    ::msgcat::mcset zh_cn \"retry\" \"重试\"\n    ::msgcat::mcset zh_cn \"yes\" \"确认\"\n}\n\n#Kevin Walzer通过微软翻译对打印内容进行本地化    localization of print terms by Kevin Walzer via Microsoft Translator\nnamespace eval ::tk {\n    ::msgcat::mcset  zh_cn \"Print\" \"输出\"\n    ::msgcat::mcset  zh_cn \"Printer\" \"输出器\"\n    ::msgcat::mcset  zh_cn \"Letter \" \"信 \"\n    ::msgcat::mcset  zh_cn \"Legal \" \"合法的 \"\n    ::msgcat::mcset  zh_cn \"A4\" \"A4\"\n    ::msgcat::mcset  zh_cn \"Grayscale\" \"灰度\"\n    ::msgcat::mcset  zh_cn \"RGB\" \"RGB\"\n    ::msgcat::mcset  zh_cn \"Options\" \"设置\"\n    ::msgcat::mcset  zh_cn \"Copies\" \"复制\"\n    ::msgcat::mcset  zh_cn \"Paper\" \"纸\"\n    ::msgcat::mcset  zh_cn \"Scale\" \"规模\"\n    ::msgcat::mcset  zh_cn \"Orientation\" \"方向\"\n    ::msgcat::mcset  zh_cn \"Portrait\" \"竖向\"\n    ::msgcat::mcset  zh_cn \"Landscape\" \"横向\"\n    ::msgcat::mcset  zh_cn \"Output\" \"输出\"\n}"
  },
  {
    "path": "library/optMenu.tcl",
    "content": "# optMenu.tcl --\n#\n# This file defines the procedure tk_optionMenu, which creates\n# an option button and its associated menu.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# ::tk_optionMenu --\n# This procedure creates an option button named $w and an associated\n# menu.  Together they provide the functionality of Motif option menus:\n# they can be used to select one of many values, and the current value\n# appears in the global variable varName, as well as in the text of\n# the option menubutton.  The name of the menu is returned as the\n# procedure's result, so that the caller can use it to change configuration\n# options on the menu or otherwise manipulate it.\n#\n# Arguments:\n# w -\t\t\tThe name to use for the menubutton.\n# varName -\t\tGlobal variable to hold the currently selected value.\n# firstValue -\t\tFirst of legal values for option (must be >= 1).\n# args -\t\tAny number of additional values.\n\nproc ::tk_optionMenu {w varName firstValue args} {\n    upvar #0 $varName var\n\n    if {![info exists var]} {\n\tset var $firstValue\n    }\n    menubutton $w -textvariable $varName -indicatoron 1 -menu $w.menu \\\n\t    -relief raised -highlightthickness 1 -anchor c \\\n\t    -direction flush\n    menu $w.menu -tearoff 0\n    $w.menu add radiobutton -label $firstValue -variable $varName\n    foreach i $args {\n\t$w.menu add radiobutton -label $i -variable $varName\n    }\n    return $w.menu\n}\n"
  },
  {
    "path": "library/palette.tcl",
    "content": "# palette.tcl --\n#\n# This file contains procedures that change the color palette used\n# by Tk.\n#\n# Copyright © 1995-1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# ::tk_setPalette --\n# Changes the default color scheme for a Tk application by setting\n# default colors in the option database and by modifying all of the\n# color options for existing widgets that have the default value.\n#\n# Arguments:\n# The arguments consist of either a single color name, which\n# will be used as the new background color (all other colors will\n# be computed from this) or an even number of values consisting of\n# option names and values.  The name for an option is the one used\n# for the option database, such as activeForeground, not -activeforeground.\n\nproc ::tk_setPalette {args} {\n    if {[winfo depth .] == 1} {\n\t# Just return on monochrome displays, otherwise errors will occur\n\treturn\n    }\n\n    # Create an array that has the complete new palette.  If some colors\n    # aren't specified, compute them from other colors that are specified.\n\n    if {[llength $args] == 1} {\n\tset new(background) [lindex $args 0]\n    } else {\n\tarray set new $args\n    }\n    if {![info exists new(background)]} {\n\treturn -code error -errorcode {TK SET_PALETTE BACKGROUND} \\\n\t    \"must specify a background color\"\n    }\n    set bg [winfo rgb . $new(background)]\n    if {![info exists new(foreground)]} {\n\t# Note that the range of each value in the triple returned by\n\t# [winfo rgb] is 0-65535, and your eyes are more sensitive to\n\t# green than to red, and more to red than to blue.\n\tforeach {r g b} $bg {break}\n\tif {$r+1.5*$g+0.5*$b > 100000} {\n\t    set new(foreground) black\n\t} else {\n\t    set new(foreground) white\n\t}\n    }\n    lassign [winfo rgb . $new(foreground)] fg_r fg_g fg_b\n    lassign $bg bg_r bg_g bg_b\n    set darkerBg [format #%02x%02x%02x [expr {(9*$bg_r)/2560}] \\\n\t    [expr {(9*$bg_g)/2560}] [expr {(9*$bg_b)/2560}]]\n\n    foreach i {activeForeground insertBackground selectForeground \\\n\t    highlightColor} {\n\tif {![info exists new($i)]} {\n\t    set new($i) $new(foreground)\n\t}\n    }\n    if {![info exists new(disabledForeground)]} {\n\tset new(disabledForeground) [format #%02x%02x%02x \\\n\t\t[expr {(3*$bg_r + $fg_r)/1024}] \\\n\t\t[expr {(3*$bg_g + $fg_g)/1024}] \\\n\t\t[expr {(3*$bg_b + $fg_b)/1024}]]\n    }\n    if {![info exists new(highlightBackground)]} {\n\tset new(highlightBackground) $new(background)\n    }\n    # 'buttonBackground' is the background color of the buttons in\n    # the spinbox widget.\n    if {![info exists new(buttonBackground)]} {\n\tset new(buttonBackground) $new(background)\n    }\n    # 'selectColor' is the background of check & radio buttons.\n    if {![info exists new(selectColor)]} {\n\tforeach {r g b} $bg {break}\n\tif {$r+1.5*$g+0.5*$b > 100000} {\n\t    set new(selectColor) white\n\t} else {\n\t    set new(selectColor) black\n\t}\n    }\n    if {![info exists new(activeBackground)]} {\n\t# Pick a default active background that islighter than the\n\t# normal background.  To do this, round each color component\n\t# up by 15% or 1/3 of the way to full white, whichever is\n\t# greater.\n\n\tforeach i {0 1 2} color $bg {\n\t    set light($i) [expr {$color/256}]\n\t    set inc1 [expr {($light($i)*15)/100}]\n\t    set inc2 [expr {(255-$light($i))/3}]\n\t    if {$inc1 > $inc2} {\n\t\tincr light($i) $inc1\n\t    } else {\n\t\tincr light($i) $inc2\n\t    }\n\t    if {$light($i) > 255} {\n\t\tset light($i) 255\n\t    }\n\t}\n\tset new(activeBackground) [format #%02x%02x%02x $light(0) \\\n\t\t$light(1) $light(2)]\n    }\n    if {![info exists new(selectBackground)]} {\n\tset new(selectBackground) $darkerBg\n    }\n    if {![info exists new(troughColor)]} {\n\tset new(troughColor) $darkerBg\n    }\n\n    # let's make one of each of the widgets so we know what the\n    # defaults are currently for this platform.\n    toplevel .___tk_set_palette\n    wm withdraw .___tk_set_palette\n    foreach q {\n\tbutton canvas checkbutton entry frame label labelframe\n\tlistbox menubutton menu message radiobutton scale scrollbar\n\tspinbox text\n    } {\n\t$q .___tk_set_palette.$q\n    }\n\n    # Walk the widget hierarchy, recoloring all existing windows.\n    # The option database must be set according to what we do here,\n    # but it breaks things if we set things in the database while\n    # we are changing colors...so, ::tk::RecolorTree now returns the\n    # option database changes that need to be made, and they\n    # need to be evalled here to take effect.\n    # We have to walk the whole widget tree instead of just\n    # relying on the widgets we've created above to do the work\n    # because different extensions may provide other kinds\n    # of widgets that we don't currently know about, so we'll\n    # walk the whole hierarchy just in case.\n\n    eval [tk::RecolorTree . new]\n\n    destroy .___tk_set_palette\n\n    # Change the option database so that future windows will get the\n    # same colors.\n\n    foreach option [array names new] {\n\toption add *$option $new($option) widgetDefault\n    }\n\n    # Save the options in the variable ::tk::Palette, for use the\n    # next time we change the options.\n\n    array set ::tk::Palette [array get new]\n\n    if {[tk windowingsystem] ne \"x11\" || [ttk::style theme use] ne \"default\"} {\n\treturn\n    }\n\n    # Update the 'default' ttk theme with the new palette,\n    # and then set 'default' as the current ttk theme,\n    # in order to apply the new palette to the ttk widgets.\n\n    foreach option [array names new] {\n\tif {[info exists ttk::theme::default::colorOptionLookup($option)]} {\n\t    foreach colorName $ttk::theme::default::colorOptionLookup($option) {\n\t\tset ttk::theme::default::colors($colorName) $new($option)\n\t    }\n\t}\n    }\n    ttk::theme::default::reconfigureDefaultTheme\n    ttk::setTheme default\n\n    return\n}\n\n# ::tk::RecolorTree --\n# This procedure changes the colors in a window and all of its\n# descendants, according to information provided by the colors\n# argument. This looks at the defaults provided by the option\n# database, if it exists, and if not, then it looks at the default\n# value of the widget itself.\n#\n# Arguments:\n# w -\t\t\tThe name of a window.  This window and all its\n#\t\t\tdescendants are recolored.\n# colors -\t\tThe name of an array variable in the caller,\n#\t\t\twhich contains color information.  Each element\n#\t\t\tis named after a widget configuration option, and\n#\t\t\teach value is the value for that option.\n# Return Value:\n#                       A list of commands which can be run to update\n#                       the defaults database when exec'ed.\n\nproc ::tk::RecolorTree {w colors} {\n    upvar $colors c\n    set result {}\n    set prototype .___tk_set_palette.[string tolower [winfo class $w]]\n    if {![winfo exists $prototype]} {\n\tunset prototype\n    }\n    foreach dbOption [array names c] {\n\tset option -[string tolower $dbOption]\n\tset class [string replace $dbOption 0 0 [string toupper \\\n\t     [string index $dbOption 0]]]\n\t# Make sure this option is valid for this window.\n\tif {![catch {$w configure $option} value]} {\n\t    # Update the option for this window.\n\t    $w configure $option $c($dbOption)\n\t    # Retrieve a default value for this option.  First check\n\t    # the option database. If it is not in the database use\n\t    # the value for the temporary prototype widget.\n\t    set defaultcolor [option get $w $dbOption $class]\n\t    if {$defaultcolor eq \"\" || \\\n\t\t    ([info exists prototype] && \\\n\t\t    [$prototype cget $option] ne \"$defaultcolor\")} {\n\t\tset defaultcolor [lindex $value 3]\n\t    }\n\t    if {$defaultcolor ne \"\"} {\n\t\tset defaultcolor [winfo rgb . $defaultcolor]\n\t    }\n\t    # If the color requested for this option differs from\n\t    # the default, append a command to update the default.\n\t    set requestcolor [lindex $value 4]\n\t    if {$requestcolor ne \"\"} {\n\t\tset requestcolor [winfo rgb . $requestcolor]\n\t    }\n\t    if {![string match $defaultcolor $requestcolor]} {\n\t\tappend result \";\\noption add [list \\\n\t\t    *[winfo class $w].$dbOption $c($dbOption) 60]\"\n\t    }\n\t}\n    }\n    foreach child [winfo children $w] {\n\tappend result \";\\n[::tk::RecolorTree $child c]\"\n    }\n    return $result\n}\n\n# ::tk::Darken --\n# Given a color name, computes a new color value that darkens (or\n# brightens) the given color by a given percent.\n#\n# Arguments:\n# color -\tName of starting color.\n# percent -\tInteger telling how much to brighten or darken as a\n#\t\tpercent: 50 means darken by 50%, 110 means brighten\n#\t\tby 10%.\n\nproc ::tk::Darken {color percent} {\n    if {$percent < 0} {\n\treturn #000000\n    } elseif {$percent > 200} {\n\treturn #ffffff\n    } elseif {$percent <= 100} {\n\tlassign [winfo rgb . $color] r g b\n\tset r [expr {($r/256)*$percent/100}]\n\tset g [expr {($g/256)*$percent/100}]\n\tset b [expr {($b/256)*$percent/100}]\n    } elseif {$percent > 100} {\n\tlassign [winfo rgb . $color] r g b\n\tset r [expr {255 - ((65535-$r)/256)*(200-$percent)/100}]\n\tset g [expr {255 - ((65535-$g)/256)*(200-$percent)/100}]\n\tset b [expr {255 - ((65535-$b)/256)*(200-$percent)/100}]\n    }\n    return [format #%02x%02x%02x $r $g $b]\n}\n\n# ::tk_bisque --\n# Reset the Tk color palette to the old \"bisque\" colors.\n#\n# Arguments:\n# None.\n\nproc ::tk_bisque {} {\n    tk_setPalette activeBackground #e6ceb1 activeForeground black \\\n\t    background #ffe4c4 disabledForeground #b0b0b0 foreground black \\\n\t    highlightBackground #ffe4c4 highlightColor black \\\n\t    insertBackground black \\\n\t    selectBackground #e6ceb1 selectForeground black \\\n\t    troughColor #cdb79e\n}\n"
  },
  {
    "path": "library/panedwindow.tcl",
    "content": "# panedwindow.tcl --\n#\n# This file defines the default bindings for Tk panedwindow widgets and\n# provides procedures that help in implementing those bindings.\n\nbind Panedwindow <Button-1> { ::tk::panedwindow::MarkSash %W %x %y 1 }\nbind Panedwindow <Button-2> { ::tk::panedwindow::MarkSash %W %x %y 0 }\n\nbind Panedwindow <B1-Motion> { ::tk::panedwindow::DragSash %W %x %y 1 }\nbind Panedwindow <B2-Motion> { ::tk::panedwindow::DragSash %W %x %y 0 }\n\nbind Panedwindow <ButtonRelease-1> {::tk::panedwindow::ReleaseSash %W 1}\nbind Panedwindow <ButtonRelease-2> {::tk::panedwindow::ReleaseSash %W 0}\n\nbind Panedwindow <Motion> { ::tk::panedwindow::Motion %W %x %y }\n\nbind Panedwindow <Leave> { ::tk::panedwindow::Leave %W }\n\n# Initialize namespace\nnamespace eval ::tk::panedwindow {}\n\n# ::tk::panedwindow::MarkSash --\n#\n#   Handle marking the correct sash for possible dragging\n#\n# Arguments:\n#   w\t\tthe widget\n#   x\t\twidget local x coord\n#   y\t\twidget local y coord\n#   proxy\twhether this should be a proxy sash\n# Results:\n#   None\n#\nproc ::tk::panedwindow::MarkSash {w x y proxy} {\n    variable ::tk::Priv\n    if {[$w cget -opaqueresize]} {\n\tset proxy 0\n    }\n    set what [$w identify $x $y]\n    if { [llength $what] == 2 } {\n\tlassign $what index which\n\tif {!$::tk_strictMotif || $which eq \"handle\"} {\n\t    if {!$proxy} {\n\t\t$w sash mark $index $x $y\n\t    }\n\t    set Priv(sash) $index\n\t    lassign [$w sash coord $index] sx sy\n\t    set Priv(dx) [expr {$sx-$x}]\n\t    set Priv(dy) [expr {$sy-$y}]\n\t    # Do this to init the proxy location\n\t    DragSash $w $x $y $proxy\n\t}\n    }\n}\n\n# ::tk::panedwindow::DragSash --\n#\n#   Handle dragging of the correct sash\n#\n# Arguments:\n#   w\t\tthe widget\n#   x\t\twidget local x coord\n#   y\t\twidget local y coord\n#   proxy\twhether this should be a proxy sash\n# Results:\n#   Moves sash\n#\nproc ::tk::panedwindow::DragSash {w x y proxy} {\n    variable ::tk::Priv\n    if {[$w cget -opaqueresize]} {\n\tset proxy 0\n    }\n    if {[info exists Priv(sash)]} {\n\tif {$proxy} {\n\t    $w proxy place [expr {$x+$Priv(dx)}] [expr {$y+$Priv(dy)}]\n\t} else {\n\t    $w sash place $Priv(sash) \\\n\t\t    [expr {$x+$Priv(dx)}] [expr {$y+$Priv(dy)}]\n\t}\n    }\n}\n\n# ::tk::panedwindow::ReleaseSash --\n#\n#   Handle releasing of the sash\n#\n# Arguments:\n#   w\t\tthe widget\n#   proxy\twhether this should be a proxy sash\n# Results:\n#   Returns ...\n#\nproc ::tk::panedwindow::ReleaseSash {w proxy} {\n    variable ::tk::Priv\n    if {[$w cget -opaqueresize]} {\n\tset proxy 0\n    }\n    if {[info exists Priv(sash)]} {\n\tif {$proxy} {\n\t    lassign [$w proxy coord] x y\n\t    $w sash place $Priv(sash) $x $y\n\t    $w proxy forget\n\t}\n\tunset Priv(sash) Priv(dx) Priv(dy)\n    }\n}\n\n# ::tk::panedwindow::Motion --\n#\n#   Handle motion on the widget.  This is used to change the cursor\n#   when the user moves over the sash area.\n#\n# Arguments:\n#   w\t\tthe widget\n#   x\t\twidget local x coord\n#   y\t\twidget local y coord\n# Results:\n#   May change the cursor.  Sets up a timer to verify that we are still\n#   over the widget.\n#\nproc ::tk::panedwindow::Motion {w x y} {\n    variable ::tk::Priv\n    set id [$w identify $x $y]\n    if {([llength $id] == 2) && \\\n\t    (!$::tk_strictMotif || [lindex $id 1] eq \"handle\")} {\n\tif {![info exists Priv($w,panecursor)]} {\n\t    set Priv($w,panecursor) [$w cget -cursor]\n\t    if {[$w cget -sashcursor] ne \"\"} {\n\t\t$w configure -cursor [$w cget -sashcursor]\n\t    } elseif {[$w cget -orient] eq \"horizontal\"} {\n\t\t$w configure -cursor sb_h_double_arrow\n\t    } else {\n\t\t$w configure -cursor sb_v_double_arrow\n\t    }\n\t    if {[info exists Priv($w,pwAfterId)]} {\n\t\tafter cancel $Priv($w,pwAfterId)\n\t    }\n\t    set Priv($w,pwAfterId) [after 150 \\\n\t\t    [list ::tk::panedwindow::Cursor $w]]\n\t}\n\treturn\n    }\n    if {[info exists Priv($w,panecursor)]} {\n\t$w configure -cursor $Priv($w,panecursor)\n\tunset Priv($w,panecursor)\n    }\n}\n\n# ::tk::panedwindow::Cursor --\n#\n#   Handles returning the normal cursor when we are no longer over the\n#   sash area.  This needs to be done this way, because the panedwindow\n#   won't see Leave events when the mouse moves from the sash to a\n#   paned child, although the child does receive an Enter event.\n#\n# Arguments:\n#   w\t\tthe widget\n# Results:\n#   May restore the default cursor, or schedule a timer to do it.\n#\nproc ::tk::panedwindow::Cursor {w} {\n    variable ::tk::Priv\n    # Make sure to check window existence in case it is destroyed.\n    if {[info exists Priv($w,panecursor)] && [winfo exists $w]} {\n\tif {[winfo containing [winfo pointerx $w] [winfo pointery $w]] eq $w} {\n\t    set Priv($w,pwAfterId) [after 150 \\\n\t\t    [list ::tk::panedwindow::Cursor $w]]\n\t} else {\n\t    $w configure -cursor $Priv($w,panecursor)\n\t    unset Priv($w,panecursor)\n\t    if {[info exists Priv($w,pwAfterId)]} {\n\t\tafter cancel $Priv($w,pwAfterId)\n\t\tunset Priv($w,pwAfterId)\n\t    }\n\t}\n    }\n}\n\n# ::tk::panedwindow::Leave --\n#\n#   Return to default cursor when leaving the pw widget.\n#\n# Arguments:\n#   w\t\tthe widget\n# Results:\n#   Restores the default cursor\n#\nproc ::tk::panedwindow::Leave {w} {\n    variable ::tk::Priv\n    if {[info exists Priv($w,panecursor)]} {\n\t$w configure -cursor $Priv($w,panecursor)\n\tunset Priv($w,panecursor)\n    }\n}\n"
  },
  {
    "path": "library/print.tcl",
    "content": "# print.tcl --\n\n# This file defines the 'tk print' command for printing of the canvas\n# widget and text on X11, Windows, and macOS. It implements an abstraction\n# layer that presents a consistent API across the three platforms.\n\n# Copyright © 2009 Michael I. Schwartz\n# Copyright © 2021 Kevin Walzer\n# Copyright © 2021 Harald Oehlmann, Elmicron GmbH\n# Copyright © 2022 Emiliano Gavilan\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nnamespace eval ::tk::print {\n    namespace import -force ::tk::msgcat::*\n\n    # margins for printing text, in mm\n    variable margin\n    set margin(top)    15\n    set margin(left)   25\n    set margin(right)  15\n    set margin(bottom) 15\n\n    # makeTempFile:\n    #    Create a temporary file and populate its contents\n    # Arguments:\n    #\t filename - base of the name of the file to create\n    #    contents - what to put in the file; defaults to empty\n    # Returns:\n    #    Full filename for created file\n    #\n    proc makeTempFile {filename {contents \"\"}} {\n\tset dumpfile [file join /tmp rawprint.txt]\n\tset tmpfile [file join /tmp $filename]\n\tset f [open $dumpfile w]\n\ttry {\n\t    puts -nonewline $f $contents\n\t} finally {\n\t    close $f\n\t    if {[file extension $filename] == \".ps\"} {\n\t\t#don't apply formatting to PostScript\n\t\tfile rename -force $dumpfile $tmpfile\n\t    } else {\n\t    #Make text fixed width for improved printed output\n\t\texec fmt -w 75 $dumpfile > $tmpfile\n\t    }\n\t    return $tmpfile\n\t}\n    }\n\n    # _wrapLines -\n    #   wrap long lines into lines of at most length wl at word boundaries\n    # Arguments:\n    #   str   - string to be wrapped\n    #   wl    - wrap length\n    #\n    proc _wrapLines {str wl} {\n\t# This is a really simple algorithm: it breaks a line on space or tab\n\t# character, collapsing them only at the breaking point.\n\t# Leading space is left as-is.\n\t# For a full fledged line breaking algorithm see\n\t# Unicode® Standard Annex #14 \"Unicode Line Breaking Algorithm\"\n\tset res {}\n\tincr wl -1\n\tset re [format {((?:^|[^[:blank:]]).{0,%d})(?:[[:blank:]]|$)} $wl]\n\tforeach line [split $str \\n] {\n\t    lappend res {*}[lmap {_ l} [regexp -all -inline -- $re $line] {\n\t\tset l\n\t    }]\n\t}\n\t# the return value is a list of lines\n\treturn $res\n    }\n\n    if {[tk windowingsystem] eq \"win32\"} {\n\tvariable printer_name\n\tvariable copies\n\tvariable dpi_x\n\tvariable dpi_y\n\tvariable paper_width\n\tvariable paper_height\n\tvariable margin_left\n\tvariable margin_top\n\tvariable printargs\n\tarray set printargs {}\n\n\t# Multiple utility procedures for printing text based on the\n\t# C printer primitives.\n\n\t# _set_dc:\n\t# Select printer and set device context and other parameters\n\t# for print job.\n\t#\n\tproc _set_dc {} {\n\t    variable margin\n\t    variable printargs\n\t    variable printer_name\n\t    variable paper_width\n\t    variable paper_height\n\t    variable dpi_x\n\t    variable dpi_y\n\t    variable copies\n\n\t    #First, we select the printer.\n\t    _selectprinter\n\n\t    #Next, set values. Some are taken from the printer,\n\t    #some are sane defaults.\n\n\t    if {[info exists printer_name]} {\n\t\tset printargs(hDC) $printer_name\n\t\tset printargs(pw) $paper_width\n\t\tset printargs(ph) $paper_height\n\t\tset printargs(resx) $dpi_x\n\t\tset printargs(resy) $dpi_y\n\t\tset printargs(copies) $copies\n\t\tset printargs(resolution) [list $dpi_x $dpi_y]\n\t    }\n\t}\n\n\t# _print\n\t# Main entry of the print subsystem for Win32.\n\t# Set the print job name and delegate to the right procedure\n\tproc _print {w} {\n\t    variable jobname\n\n\t    set class [winfo class $w]\n\t    if {$class ni {Text Canvas}} {\n\t\treturn -code error \"can not print widget of class \\\"$class\\\":\\\n\t\t    should be Canvas or Text\"\n\t    }\n\t    set jobname \"[tk appname]: Tk widget $w\"\n\t    switch -- $class {\n\t\tText {\n\t\t    _print_data2 [$w get 1.0 end] {{Courier New} 11}\n\t\t}\n\t\tCanvas {\n\t\t    _print_widget $w\n\t\t}\n\t    }\n\t}\n\n\t# _print_data2\n\t# This function prints multiple-page files, using a line-oriented\n\t# function, taking advantage of knowing the character widths.\n\t# Arguments:\n\t# data -       Text data for printing\n\t# font -       Font for printing\n\tproc _print_data2 { data font } {\n\t    variable printargs\n\t    variable printer_name\n\t    variable jobname\n\n\t    _set_dc\n\n\t    if {![info exists printer_name]} {\n\t\treturn\n\t    }\n\n\t    set maxwidth [expr {\n\t\t($printargs(pw) - $printargs(lm) - $printargs(rm)) *\n\t\t$printargs(resx) / 1000\n\t    }]\n\t    set maxheight [expr {\n\t\t($printargs(ph) - $printargs(tm) - $printargs(bm)) *\n\t\t$printargs(resy) / 1000\n\t    }]\n\t    set lm [expr {$printargs(lm) * $printargs(resx) / 1000}]\n\t    set tm [expr {$printargs(tm) * $printargs(resy) / 1000}]\n\t    set curheight $tm\n\n\t    lassign [_opendoc $jobname $font] charwidth charheight\n\t    _openpage\n\n\t    set wl [expr {($maxwidth / $charwidth) + 1}]\n\t    foreach line [_wrapLines $data $wl] {\n\t\t_gdi textplain $printargs(hDC) $lm $curheight $line\n\t\tincr curheight $charheight\n\t\tif {$curheight + $charheight > $maxheight} {\n\t\t    _closepage\n\t\t    _openpage\n\t\t    set curheight $tm\n\t\t}\n\t    }\n\t    _closepage\n\t    _closedoc\n\t    return\n\t}\n\n\t# _print_data\n\t# This function prints multiple-page files, using a line-oriented\n\t# function, taking advantage of knowing the character widths.\n\t# Arguments:\n\t# data -       Text data for printing\n\t# font -       Font for printing\n\tproc _print_data { data font } {\n\t    variable printargs\n\t    variable printer_name\n\t    variable charwidths\n\n\t    _set_dc\n\n\t    if {![info exists printer_name]} {\n\t\treturn\n\t    }\n\n\t    _gdi characters $printargs(hDC) -font $font \\\n\t\t-array ::tk::print::charwidths\n\t    array default set ::tk::print::charwidths $charwidths(x)\n\t    # check for a monospaced font\n\t    set mono 0\n\t    if {$charwidths(i) == $charwidths(m)} {\n\t\tset mono $charwidths(m)\n\t    }\n\t    set maxwidth [expr {\n\t\t($printargs(pw) - $printargs(lm) - $printargs(rm)) *\n\t\t$printargs(resx) / 1000\n\t    }]\n\t    set maxhgt [expr {\n\t\t($printargs(ph) - $printargs(tm) - $printargs(bm)) *\n\t\t$printargs(resy) / 1000\n\t    }]\n\t    set lm [expr {$printargs(lm) * $printargs(resx) / 1000}]\n\t    set tm [expr {$printargs(tm) * $printargs(resy) / 1000}]\n\t    set curhgt $tm\n\n\t    _opendoc \"[tk appname]: Tk Print Job\"\n\t    _openpage\n\n\t    # if a monospaced font is used, things are a bit easier\n\t    # handle this case here\n\t    if {$mono > 0} {\n\t\t# can use the same line breaking algorithm as X11\n\t\tset wl [expr {($maxwidth / $mono) + 1}]\n\t\tforeach line [_wrapLines $data $wl] {\n\t\t    set hgt [_gdi text $printargs(hDC) $lm $curhgt \\\n\t\t\t-anchor nw -justify left \\\n\t\t\t-text $line -font $font]\n\t\t    incr curhgt $hgt\n#\t\t    puts \"height: $hgt\"\n\t\t    if {$curhgt + $hgt > $maxhgt} {\n\t\t\t_closepage\n\t\t\t_openpage\n\t\t\tset curhgt $tm\n\t\t    }\n\t\t}\n\t\t_closepage\n\t\t_closedoc\n\t\treturn\n\t    }\n\n\t    # proportional font\n\t    set totallen [string length $data]\n\t    set curlen 0\n\t    set breaklines 1\n\t    while {$curlen < $totallen} {\n\t\tset linestring [string range $data $curlen end]\n\t\tif {$breaklines} {\n\t\t    set endind [string first \"\\n\" $linestring]\n\t\t    if {$endind >= 0} {\n\t\t\tset linestring [string range $linestring 0 $endind]\n\t\t\t# handle blank lines....\n\t\t\tif {$linestring eq \"\"} {\n\t\t\t    set linestring \" \"\n\t\t\t}\n\t\t    }\n\t\t}\n\t\tlassign [_print_page_nextline $linestring $curhgt $font \\\n\t\t    $lm $maxwidth] len hgt\n\t\tincr curlen $len\n\t\tincr curhgt $hgt\n\t\tif {$curhgt + $hgt > $maxhgt} {\n\t\t    _closepage\n\t\t    _openpage\n\t\t    set curhgt $zerohgt\n\t\t}\n\t    }\n\t    _closepage\n\t    _closedoc\n\t}\n\n\t# _print_page_nextline\n\t# Returns the pair \"chars y\"\n\t# where chars is the number of characters printed on the line\n\t# and y is the height of the line printed\n\t# Arguments:\n\t#   string -         Data to print\n\t#   y -              Y value to begin printing at, in logical units\n\t#   font -           if non-empty specifies a font to draw the line in\n\t#   lm -             left margin, in logical units\n\t#   maxwidth -       line length limit in logical units\n\tproc _print_page_nextline {string y font lm maxwidth} {\n\t    variable charwidths\n\t    variable printargs\n\n\t    set endindex 0\n\t    set totwidth 0\n\t    set maxstring [string length $string]\n\n\t    for {set i 0} {($i < $maxstring) && ($totwidth < $maxwidth)} {incr i} {\n\t\tincr totwidth $charwidths([string index $string $i])\n\t    }\n\n\t    set endindex $i\n\t    set startindex $endindex\n\n\t    if {$i < $maxstring} {\n\t\t# In this case, the whole data string is not used up, and we\n\t\t# wish to break on a word. Since we have all the partial\n\t\t# widths calculated, this should be easy.\n\n\t\tset endindex [expr {[string wordstart $string $endindex] - 1}]\n\t\tset startindex [expr {$endindex + 1}]\n\n\t\t# If the line is just too long (no word breaks), print as much\n\t\t# as you can....\n\t\tif {$endindex <= 1} {\n\t\t    set endindex $i\n\t\t    set startindex $i\n\t\t}\n\t    }\n\n\t    set txt [string trimright [string range $string 0 $endindex] \"\\r\\n\"]\n\t    if {$font ne \"\"} {\n\t\tset height [_gdi text $printargs(hDC) $lm $y \\\n\t\t\t\t -anchor nw -justify left \\\n\t\t\t\t -text $txt -font $font]\n\t    } else {\n\t\tset height [_gdi text $printargs(hDC) $lm $y \\\n\t\t\t\t -anchor nw -justify left -text $txt]\n\t    }\n\t    return [list $startindex $height]\n\t}\n\n\t# These procedures read in the canvas widget, and write all of\n\t# its contents out to the Windows printer.\n\n\tproc _init_print {} {\n\t    variable margin\n\t    variable printargs\n\t    variable vtgPrint\n\n\t    set vtgPrint(printer.bg) white\n\n\t    # convert margins to windows DC units (1000 point per inch)\n\t    set printargs(tm) [expr {int($margin(top) / 25.4 * 1000)}]\n\t    set printargs(lm) [expr {int($margin(left) / 25.4 * 1000)}]\n\t    set printargs(rm) [expr {int($margin(right) / 25.4 * 1000)}]\n\t    set printargs(bm) [expr {int($margin(bottom) / 25.4 * 1000)}]\n\t}\n\n\t# _print_widget\n\t# Main procedure for printing a widget.  Currently supports\n\t# canvas widgets.  Handles opening and closing of printer.\n\t# Arguments:\n\t#   wid -              The widget to be printed.\n\t#   name  -            App name to pass to printer.\n\n\tproc _print_widget {w} {\n\t    variable printargs\n\t    variable printer_name\n\t    variable jobname\n\n\t    # provide an early exit if the widget is not a canvas\n\t    set class [winfo class $w]\n\t    if {$class ne \"Canvas\"} {\n\t\treturn -code error \"Can't print items of type $class.\\\n\t\t     No handler registered\"\n\t    }\n\n\t    _set_dc\n\n\t    if {![info exists printer_name]} {\n\t\treturn\n\t    }\n\n\t    _opendoc $jobname\n\t    _openpage\n\n\t    # Here is where any scaling/gdi mapping should take place\n\t    # For now, scale so the dimensions of the window are sized to the\n\t    # width of the page. Scale evenly.\n\n\t    # For normal windows, this may be fine--but for a canvas, one\n\t    # wants the canvas dimensions, and not the WINDOW dimensions.\n\t    if {$class eq \"Canvas\"} {\n\t\tset sc [$w cget -scrollregion]\n\t\t# if there is no scrollregion, use width and height.\n\t\tif {$sc eq \"\"} {\n\t\t    set window_x [winfo pixels $w [$w cget -width]]\n\t\t    set window_y [winfo pixels $w [$w cget -height]]\n\t\t} else {\n\t\t    set window_x [winfo pixels $w [lindex $sc 2]]\n\t\t    set window_y [winfo pixels $w [lindex $sc 3]]\n\t\t}\n\t    } else {\n\t\tset window_x [winfo width $w]\n\t\tset window_y [winfo height $w]\n\t    }\n\n\t    set printer_x [expr {\n\t\t( $printargs(pw) - $printargs(lm) - $printargs(rm) ) *\n\t\t$printargs(resx)  / 1000.0\n\t    }]\n\t    set printer_y [expr {\n\t\t( $printargs(ph) - $printargs(tm) - $printargs(bm) ) *\n\t\t$printargs(resy) / 1000.0\n\t    }]\n\t    set factor_x [expr {$window_x / $printer_x}]\n\t    set factor_y [expr {$window_y / $printer_y}]\n\n\t    if {$factor_x < $factor_y} {\n\t\tset lo $window_y\n\t\tset ph $printer_y\n\t    } else {\n\t\tset lo $window_x\n\t\tset ph $printer_x\n\t    }\n\n\t    _gdi map $printargs(hDC) -logical $lo -physical $ph \\\n\t\t-offset $printargs(resolution)\n\n\t    # Handling of canvas widgets.\n\t    _print_canvas $printargs(hDC) $w\n\n\t    # End printing process.\n\t    _closepage\n\t    _closedoc\n\t}\n\n\t#  _print_canvas\n\t# Main procedure for writing canvas widget items to printer.\n\t# Arguments:\n\t#    hdc -              The printer handle.\n\t#    cw  -              The canvas widget.\n\tproc _print_canvas {hdc cw} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    # Get information about page being printed to\n\t    # print_canvas.CalcSizing $cw\n\t    set vtgPrint(canvas.bg) [string tolower [$cw cget -background]]\n\n\t    # Re-write each widget from cw to printer\n\t    foreach id [$cw find all] {\n\t\tif {[$cw itemcget $id -state] eq \"hidden\"} {\n\t\t    # don't display hidden items\n\t\t    continue\n\t\t}\n\t\tset type [$cw type $id]\n\t\tif {[info commands _print_canvas.$type] eq \"_print_canvas.$type\"} {\n\t\t    _print_canvas.$type $printargs(hDC) $cw $id\n\t\t} else {\n\t\t    # should we use puts?\n\t\t    # puts \"Omitting canvas item of type $type since there is no handler registered for it\"\n\t\t}\n\t    }\n\t}\n\n\t# These procedures support the various canvas item types, reading the\n\t# information about the item on the real canvas and then writing a\n\t# similar item to the printer.\n\n\t# _print_canvas.line\n\t# Description:\n\t#   Prints a line item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.line {hdc cw id} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    set color [_print_canvas.TransColor [$cw itemcget $id -fill]]\n\t    if {[string match $vtgPrint(printer.bg) $color]} {\n\t\treturn\n\t    }\n\n\t    set coords [$cw coords $id]\n\t    set wdth   [$cw itemcget $id -width]\n\t    set arrow  [$cw itemcget $id -arrow]\n\t    set arwshp [$cw itemcget $id -arrowshape]\n\t    set dash   [$cw itemcget $id -dash]\n\t    set smooth [$cw itemcget $id -smooth]\n\t    set splinesteps [$cw itemcget $id -splinesteps]\n\t    set capstyle    [$cw itemcget $id -capstyle]\n\t    set joinstyle   [$cw itemcget $id -joinstyle]\n\n\t    set cmdargs {}\n\n\t    if {$wdth > 1} {\n\t\tlappend cmdargs -width $wdth\n\t    }\n\t    if {$dash ne \"\"} {\n\t\tlappend cmdargs -dash $dash\n\t    }\n\t    if {$smooth ne \"\"} {\n\t\tlappend cmdargs -smooth $smooth\n\t    }\n\t    if {$splinesteps ne \"\"} {\n\t\tlappend cmdargs -splinesteps $splinesteps\n\t    }\n\n\t    set result [_gdi line $hdc {*}$coords \\\n\t\t\t    -fill $color -arrow $arrow -arrowshape $arwshp \\\n\t\t\t    -capstyle $capstyle -joinstyle $joinstyle \\\n\t\t\t    {*}$cmdargs]\n\t    if {$result ne \"\"} {\n\t\tputs $result\n\t    }\n\t}\n\n\t# _print_canvas.arc\n\t#   Prints a arc item.\n\t# Args:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.arc {hdc cw id} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    set color [_print_canvas.TransColor [$cw itemcget $id -outline]]\n\t    if {[string match $vtgPrint(printer.bg) $color]} {\n\t\treturn\n\t    }\n\t    set coords  [$cw coords $id]\n\t    set wdth    [$cw itemcget $id -width]\n\t    set style   [$cw itemcget $id -style]\n\t    set start   [$cw itemcget $id -start]\n\t    set extent  [$cw itemcget $id -extent]\n\t    set fill    [$cw itemcget $id -fill]\n\n\t    set cmdargs {}\n\t    if {$wdth > 1} {\n\t\tlappend cmdargs -width $wdth\n\t    }\n\t    if {$fill ne \"\"} {\n\t\tlappend cmdargs -fill $fill\n\t    }\n\n\t    _gdi arc $hdc {*}$coords \\\n\t\t-outline $color -style $style -start $start -extent $extent \\\n\t\t{*}$cmdargs\n\t}\n\n\t# _print_canvas.polygon\n\t#   Prints a polygon item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.polygon {hdc cw id} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]]\n\t    if {$fcolor eq \"\"} {\n\t\tset fcolor $vtgPrint(printer.bg)\n\t    }\n\t    set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]]\n\t    if {$ocolor eq \"\"} {\n\t\tset ocolor $vtgPrint(printer.bg)\n\t    }\n\t    set coords  [$cw coords $id]\n\t    set wdth [$cw itemcget $id -width]\n\t    set smooth  [$cw itemcget $id -smooth]\n\t    set splinesteps [$cw itemcget $id -splinesteps]\n\n\t    set cmdargs {}\n\t    if {$smooth ne \"\"} {\n\t\tlappend cmdargs -smooth $smooth\n\t    }\n\t    if {$splinesteps ne \"\"} {\n\t\tlappend cmdargs -splinesteps $splinesteps\n\t    }\n\n\t    _gdi polygon $hdc {*}$coords \\\n\t\t-width $wdth -fill $fcolor -outline $ocolor {*}$cmdargs\n\t}\n\n\t# _print_canvas.oval\n\t#   Prints an oval item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.oval {hdc cw id} {\n\t    variable vtgPrint\n\n\t    set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]]\n\t    if {$fcolor eq \"\"} {\n\t\tset fcolor $vtgPrint(printer.bg)\n\t    }\n\t    set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]]\n\t    if {$ocolor eq \"\"} {\n\t\tset ocolor $vtgPrint(printer.bg)\n\t    }\n\t    set coords  [$cw coords $id]\n\t    set wdth [$cw itemcget $id -width]\n\n\t    _gdi oval $hdc {*}$coords \\\n\t\t-width $wdth -fill $fcolor -outline $ocolor\n\t}\n\n\t# _print_canvas.rectangle\n\t#   Prints a rectangle item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.rectangle {hdc cw id} {\n\t    variable vtgPrint\n\n\t    set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]]\n\t    if {$fcolor eq \"\"} {\n\t\tset fcolor $vtgPrint(printer.bg)\n\t    }\n\t    set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]]\n\t    if {$ocolor eq \"\"} {\n\t\tset ocolor $vtgPrint(printer.bg)\n\t    }\n\t    set coords  [$cw coords $id]\n\t    set wdth [$cw itemcget $id -width]\n\n\t    _gdi rectangle $hdc {*}$coords \\\n\t\t-width $wdth -fill $fcolor -outline $ocolor\n\t}\n\n\t# _print_canvas.text\n\t#   Prints a text item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.text {hdc cw id} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    set color [_print_canvas.TransColor [$cw itemcget $id -fill]]\n#\t    if {\"white\" eq [string tolower $color]} {\n#\t\treturn\n#\t    }\n\t    # set color black\n\t    set txt [$cw itemcget $id -text]\n\t    if {$txt eq \"\"} {\n\t\treturn\n\t    }\n\t    set coords [$cw coords $id]\n\t    set anchr [$cw itemcget $id -anchor]\n\n\t    set angle [$cw itemcget $id -angle]\n\t    set wdth [winfo pixels $cw [$cw itemcget $id -width]]\n\t    set just [$cw itemcget $id -justify]\n\n\t    # Get the real canvas font info suitable for printer\n\t    set font [_make_gdi_cfont $cw [$cw itemcget $id -font]]\n\n\t    _gdi text $hdc {*}$coords \\\n\t\t-fill $color -text $txt -font $font \\\n\t\t-anchor $anchr -width $wdth -justify $just -angle $angle\n\t}\n\n\tproc _make_gdi_cfont {w fname} {\n\t    set fa [font actual $fname]\n\t    # Transform to the third documented format in font(n)\n\t    # {family size style style style style}\n\t    set font [lmap k { -family -size -weight -slant } {\n\t\tdict get $fa $k\n\t    }]\n\t    # add underline and overstrike\n\t    foreach k { -underline -overstrike } v { underline overstrike } {\n\t\tif {[dict get $fa $k]} {\n\t\t    lappend font $v\n\t\t}\n\t    }\n\t    # make sure size is in pixels (negative)\n\t    if {[set size [lindex $font 1]] > 0} {\n\t\tlset font 1 [winfo pixels $w -${size}p]\n\t    }\n\t    return $font\n\t}\n\n\t# _print_canvas.image\n\t# Prints an image item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.image {hdc cw id} {\n\t    # First, we have to get the image name.\n\t    set imagename [$cw itemcget $id -image]\n\t    if {[image type $imagename] ne \"photo\"} {\n\t\treturn\n\t    }\n\n\t    # Next, we get the location and anchor\n\t    lassign [$cw coords $id] ix iy\n\t    set anchor [$cw itemcget $id -anchor]\n\n\t    _gdi photo $hdc $ix $iy -anchor $anchor -photo $imagename\n\t}\n\n\t# _print_canvas.bitmap\n\t#   Prints a bitmap item.\n\t# Arguments:\n\t#   hdc -              The printer handle.\n\t#   cw  -              The canvas widget.\n\t#   id  -              The id of the canvas item.\n\tproc _print_canvas.bitmap {hdc cw id} {\n\t    # bitmap is not yet supported !!\n\t    # do nothing until it is (if ever).\n\t    return\n\t    variable option\n\t    variable vtgPrint\n\n\t    # First, we have to get the bitmap name.\n\t    set name [$cw itemcget $id -bitmap]\n\n\t    # Now we get the size.\n#\t    set wid [image width $imagename]\n#\t    set hgt [image height $imagename]\n\t    set bbox [$cw bbox $id]\n\t    set wid [expr {[lindex $bbox 2] - [lindex $bbox 0]}]\n\t    set hgt [expr {[lindex $bbox 3] - [lindex $bbox 1]}]\n\n\t    #Next, we get the location and anchor.\n\t    set anchor [$cw itemcget $id -anchor]\n\t    set coords [$cw coords $id]\n\n\t    # Since the GDI commands don't yet support images and bitmaps,\n\t    # and since this represents a rendered bitmap, we CAN use\n\t    # copybits IF we create a new temporary toplevel to hold the beast.\n\t    # If this is too ugly, change the option!\n\n\t    if {[info exist option(use_copybits)]} {\n\t\tset firstcase $option(use_copybits)\n\t    } else {\n\t\tset firstcase 0\n\t    }\n\t    if {$firstcase > 0} {\n\t\tset tl [toplevel .tmptop[expr {int( rand() * 65535 )}] \\\n\t\t\t    -height $hgt -width $wid \\\n\t\t\t    -background $vtgPrint(canvas.bg)]\n\t\tcanvas $tl.canvas -width $wid -height $hgt\n\t\t$tl.canvas create bitmap 0 0 -bitmap $name -anchor nw\n\t\tpack $tl.canvas -side left -expand false -fill none\n\t\ttkwait visibility $tl.canvas\n\t\tupdate\n\t\tset srccoords [list 0 0 [expr {$wid - 1}] [expr {$hgt - 1}]]\n\t\tset dstcoords [list [lindex $coords 0] [lindex $coords 1] [expr {$wid - 1}] [expr {$hgt - 1}]]\n\t\t_gdi copybits $hdc -window $tl -client \\\n\t\t    -source $srccoords -destination $dstcoords\n\t\tdestroy $tl\n\t    } else {\n\t\t_gdi bitmap $hdc {*}$coords \\\n\t\t    -anchor $anchor -bitmap $name\n\t    }\n\t}\n\n\t# These procedures transform attribute setting from the real\n\t# canvas to the appropriate setting for printing to paper.\n\n\t# _print_canvas.TransColor\n\t#   Does the actual transformation of colors from the\n\t#   canvas widget to paper.\n\t# Arguments:\n\t#   color -            The color value to be transformed.\n\tproc _print_canvas.TransColor {color} {\n\t    variable vtgPrint\n\t    variable printargs\n\n\t    switch [string toupper $color] {\n\t\t$vtgPrint(canvas.bg)       {return $vtgPrint(printer.bg)}\n\t    }\n\t    return $color\n\t}\n\n\t# Initialize all the variables once.\n\t_init_print\n    }\n    #end win32 procedures\n}\n\n# Begin X11 procedures. They depends on Cups being installed.\n# X11 procedures abstracts print management with a \"cups\" ensemble command\n\n#\tcups defaultprinter\treturns the default printer\n#\tcups getprinters\treturns a dictionary of printers along\n#\t\t\t\twith printer info\n#\tcups print $printer $data ?$options?\n#\t\t\t\tprint the data (binary) on a given printer\n#\t\t\t\twith the provided (supported) options:\n#\t\t\t\t-colormode -copies -format -margins\n#\t\t\t\t-media -nup -orientation\n#\t\t\t\t-prettyprint -title -tzoom\n\n# Some output configuration that on other platforms is managed through\n# the printer driver/dialog is configured through the canvas postscript command.\nif {[tk windowingsystem] eq \"x11\"} {\n    if {[info commands ::tk::print::cups] eq \"\"} {\n\tnamespace eval ::tk::print::cups {\n\t    # Pure Tcl cups ensemble command implementation\n\t    variable pcache\n\t}\n\n\tproc ::tk::print::cups::defaultprinter {} {\n\t    set default {}\n\t    regexp {: ([^[:space:]]+)$} [exec lpstat -d] _ default\n\t    return $default\n\t}\n\n\tproc ::tk::print::cups::getprinters {} {\n\t    variable pcache\n\t    # Test for existence of lpstat command to obtain the list of\n\t    # printers.\n\t    # Return an error if not found.\n\t    set res {}\n\t    try {\n\t\tset printers [lsort -unique [split [exec lpstat -e] \\n]]\n\t\tforeach printer $printers {\n\t\t    set options [Parseoptions [exec lpoptions -p $printer]]\n\t\t    dict set res $printer $options\n\t\t}\n\t    } trap {POSIX ENOENT} {e o} {\n\t\t# no such command in PATH\n\t\tset cmd [lindex [dict get $o -errorstack ] 1 2]\n\t\treturn -code error \"Unable to obtain the list of printers.\\\n\t\t    Command \\\"$cmd\\\" not found.\\\n\t\t    Please install the CUPS package for your system.\"\n\t    } trap {CHILDSTATUS} {e o} {\n\t\t# command returns a non-0 exit status. Wrong print system?\n\t\tset cmd [lindex [dict get $o -errorstack ] 1 2]\n\t\treturn -code error \"Command \\\"$cmd\\\" return with errors\"\n\t    }\n\t    return [set pcache $res]\n\t}\n\n\t# Parseoptions\n\t#   Parse lpoptions -d output. It has three forms\n\t#     option-key\n\t#     option-key=option-value\n\t#     option-key='option value with spaces'\n\t# Arguments:\n\t#   data - data to process.\n\t#\n\tproc ::tk::print::cups::Parseoptions {data} {\n\t    set res {}\n\t    set re {[^ =]+|[^ ]+='[^']+'|[^ ]+=[^ ']+}\n\t    foreach tok [regexp -inline -all $re $data] {\n\t\tlassign [split $tok \"=\"] k v\n\t\tdict set res $k [string trim $v \"'\"]\n\t    }\n\t    return $res\n\t}\n\n\tproc ::tk::print::cups::print {printer data args} {\n\t    variable pcache\n\t    if {$printer ni [dict keys $pcache]} {\n\t\treturn -code error \"unknown printer or class \\\"$printer\\\"\"\n\t    }\n\t    set title \"Tk print job\"\n\t    set options {\n\t\t-colormode -copies -format -margins -media -nup -orientation\n\t\t-prettyprint -title -tzoom\n\t    }\n\t    while {[llength $args]} {\n\t\tset opt [tcl::prefix match $options [lpop args 0]]\n\t\tswitch  $opt {\n\t\t    -colormode {\n\t\t\tset opts {auto monochrome color}\n\t\t\tset val [tcl::prefix match $opts [lpop args 0]]\n\t\t\tlappend printargs -o print-color-mode=$val\n\t\t    }\n\t\t    -copies {\n\t\t\tset val [lpop args 0]\n\t\t\tif {![string is integer -strict $val] ||\n\t\t\t    $val < 0 || $val > 100\n\t\t\t} {\n\t\t\t    # save paper !!\n\t\t\t    return -code error \"copies must be an integer\\\n\t\t\t\tbetween 0 and 100\"\n\t\t\t}\n\t\t\tlappend printargs -o copies=$val\n\t\t    }\n\t\t    -format {\n\t\t\tset opts {auto pdf postscript text}\n\t\t\tset val [tcl::prefix match $opts [lpop args 0]]\n\t\t\t# lpr uses auto always\n\t\t    }\n\t\t    -margins {\n\t\t\tset val [lpop args 0]\n\t\t\tif {[llength $val] != 4 ||\n\t\t\t    ![string is integer -strict [lindex $val 0]] ||\n\t\t\t    ![string is integer -strict [lindex $val 1]] ||\n\t\t\t    ![string is integer -strict [lindex $val 2]] ||\n\t\t\t    ![string is integer -strict [lindex $val 3]]\n\t\t\t} {\n\t\t\t    return -code error \"margins must be a list of 4\\\n\t\t\t\tintegers: top left bottom right\"\n\t\t\t}\n\t\t\tlappend printargs -o page-top=[lindex $val 0]\n\t\t\tlappend printargs -o page-left=[lindex $val 1]\n\t\t\tlappend printargs -o page-bottom=[lindex $val 2]\n\t\t\tlappend printargs -o page-right=[lindex $val 3]\n\t\t    }\n\t\t    -media {\n\t\t\tset opts {a4 legal letter}\n\t\t\tset val [tcl::prefix match $opts [lpop args 0]]\n\t\t\tlappend printargs -o media=$val\n\t\t    }\n\t\t    -nup {\n\t\t\tset val [lpop args 0]\n\t\t\tif {$val ni {1 2 4 6 9 16}} {\n\t\t\t    return -code error \"number-up must be 1, 2, 4, 6, 9 or\\\n\t\t\t\t16\"\n\t\t\t}\n\t\t\tlappend printargs -o number-up=$val\n\t\t    }\n\t\t    -orientation {\n\t\t\tset opts {portrait landscape}\n\t\t\tset val [tcl::prefix match $opts [lpop args 0]]\n\t\t\tif {$val eq \"landscape\"}\n\t\t\tlappend printargs -o landscape=true\n\t\t    }\n\t\t    -prettyprint {\n\t\t\tlappend printargs -o prettyprint=true\n\t\t\t# prettyprint mess with these default values if set\n\t\t\t# so we force them.\n\t\t\t# these will be overriden if set after this point\n\t\t\tif {[lsearch $printargs {cpi=*}] == -1} {\n\t\t\t    lappend printargs -o cpi=10.0\n\t\t\t    lappend printargs -o lpi=6.0\n\t\t\t}\n\t\t    }\n\t\t    -title {\n\t\t\tset title [lpop args 0]\n\t\t    }\n\t\t    -tzoom {\n\t\t\tset val [lpop args 0]\n\t\t\tif {![string is double -strict $val] ||\n\t\t\t    $val < 0.5 || $val > 2.0\n\t\t\t } {\n\t\t\t    return -code error \"text zoom must be a number between\\\n\t\t\t\t0.5 and 2.0\"\n\t\t\t}\n\t\t\t# CUPS text filter defaults to lpi=6 and cpi=10\n\t\t\tlappend printargs -o cpi=[expr {10.0 / $val}]\n\t\t\tlappend printargs -o lpi=[expr {6.0 / $val}]\n\t\t    }\n\t\t    default {\n\t\t\t# shouldn't happen\n\t\t    }\n\t\t}\n\t    }\n\t    # build our options\n\t    lappend printargs -T $title\n\t    lappend printargs -P $printer\n\t    # open temp file\n\t    set fd [file tempfile fname tk_print]\n\t    chan configure $fd -translation binary\n\t    chan puts $fd $data\n\t    chan close $fd\n\t    # add -r to automatically delete temp files\n\t    exec lpr {*}$printargs -r $fname &\n\t}\n\n\tnamespace eval ::tk::print::cups {\n\t    namespace export defaultprinter getprinters print\n\t    namespace ensemble create\n\t}\n    };# ::tk::print::cups\n\n    namespace eval ::tk::print {\n\n\tvariable mcmap\n\tset mcmap(media) [dict create \\\n\t    [mc \"Letter\"]\tletter \\\n\t    [mc \"Legal\"]\tlegal \\\n\t    [mc \"A4\"]\t\ta4]\n\tset mcmap(orient) [dict create \\\n\t    [mc \"Portrait\"]\tportrait \\\n\t    [mc \"Landscape\"]\tlandscape]\n\tset mcmap(color) [dict create \\\n\t    [mc \"RGB\"]\t\tcolor \\\n\t    [mc \"Grayscale\"]\tgray]\n\n\t# available print options\n\tvariable optlist\n\tset optlist(printer)\t{}\n\tset optlist(media)\t[dict keys $mcmap(media)]\n\tset optlist(orient)\t[dict keys $mcmap(orient)]\n\tset optlist(color)\t[dict keys $mcmap(color)]\n\tset optlist(number-up)\t{1 2 4 6 9 16}\n\n\t# selected options\n\tvariable option\n\tset option(printer)\t{}\n\t# Initialize with sane defaults.\n\tset option(copies)\t1\n\tset option(media)\t[mc \"A4\"]\n\t# Canvas options\n\tset option(orient)\t[mc \"Portrait\"]\n\tset option(color)\t[mc \"RGB\"]\n\tset option(czoom)\t100\n\t# Text options.\n\t# See libcupsfilter's cfFilterTextToPDF() and cups-filters's texttopdf\n\t# known options:\n\t# prettyprint, wrap, columns, lpi, cpi\n\tset option(number-up)\t1\n\tset option(tzoom)\t100; # we derive lpi and cpi from this value\n\tset option(pprint)\t0  ; # pretty print\n\t# convert margins from mm to points\n\tvariable margin\n\tset option(margin-top)    [expr {int($margin(top) * 72 / 25.4)}]\n\tset option(margin-left)   [expr {int($margin(left) * 72 / 25.4)}]\n\tset option(margin-right)  [expr {int($margin(right) * 72 / 25.4)}]\n\tset option(margin-bottom) [expr {int($margin(bottom) * 72 / 25.4)}]\n\n\t# array to collect printer information\n\tvariable pinfo\n\tarray set pinfo {}\n\n\t# a map for printer state -> human readable message\n\tvariable statemap\n\tdict set statemap 3 [mc \"Idle\"]\n\tdict set statemap 4 [mc \"Printing\"]\n\tdict set statemap 5 [mc \"Printer stopped\"]\n    }\n\n    # ttk version of [tk_optionMenu]\n    # var should be a full qualified varname\n    proc ::tk::print::ttk_optionMenu {w var args} {\n\tttk::menubutton $w -textvariable $var -menu $w.menu\n\tmenu $w.menu\n\tforeach option $args {\n\t    $w.menu add command \\\n\t\t-label $option \\\n\t\t-command [list set $var $option]\n\t}\n\t# return the same value as tk_optionMenu\n\treturn $w.menu\n    }\n\n    # _setprintenv\n    #   Set the print environtment - list of printers, state and options.\n    # Arguments:\n    #   none.\n    #\n    proc ::tk::print::_setprintenv {} {\n\tvariable option\n\tvariable optlist\n\tvariable pinfo\n\n\tset optlist(printer) {}\n\tdict for {printer options} [cups getprinters] {\n\t    lappend optlist(printer) $printer\n\t    set pinfo($printer) $options\n\t}\n\n\t# It's an error to not have any printer configured\n\tif {[llength $optlist(printer)] == 0} {\n\t    return -code error \"No installed printers found.\\\n\t    Please check or update your CUPS installation.\"\n\t}\n\n\t# If no printer is selected, check for the default one\n\t# If none found, use the first one from the list\n\tif {$option(printer) eq \"\"} {\n\t    set option(printer) [cups defaultprinter]\n\t    if {$option(printer) eq \"\"} {\n\t\tset option(printer) [lindex $optlist(printer) 0]\n\t    }\n\t}\n    }\n\n    # _print\n    #   Main printer dialog.\n    #   Select printer, set options, and fire print command.\n    # Arguments:\n    #   w - widget with contents to print.\n    #\n    proc ::tk::print::_print {w} {\n\tvariable optlist\n\tvariable option\n\tvariable pinfo\n\tvariable statemap\n\n\t# default values for dialog widgets\n\toption add *Printdialog*TLabel.anchor e\n\toption add *Printdialog*TMenubutton.Menu.tearOff 0\n\toption add *Printdialog*TMenubutton.width 12\n\toption add *Printdialog*TSpinbox.width 12\n\t# this is tempting to add, but it's better to leave it to\n\t# user's taste.\n\t# option add *Printdialog*Menu.background snow\n\n\tset class [winfo class $w]\n\tif {$class ni {Text Canvas}} {\n\t    return -code error \"printing windows of class \\\"$class\\\"\\\n\t\tis not supported\"\n\t}\n\t# Should this be called with every invocaton?\n\t# Yes. It allows dynamic discovery of newly added printers\n\t# whithout having to restart the app\n\t_setprintenv\n\n\tset p ._print\n\tdestroy $p\n\n\t# Copy the current values to a dialog's temporary variable.\n\t# This allow us to cancel the dialog discarding any changes\n\t# made to the options\n\tnamespace eval dlg {variable option}\n\tarray set dlg::option [array get option]\n\tset var [namespace which -variable dlg::option]\n\n\t# The toplevel of our dialog\n\ttoplevel $p -class Printdialog\n\tplace [ttk::frame $p.background] -x 0 -y 0 -relwidth 1.0 -relheight 1.0\n\twm title $p [mc \"Print\"]\n\twm resizable $p 0 0\n\twm attributes $p -type dialog\n\twm transient $p [winfo toplevel $w]\n\n\t# The printer to use\n\tset pf [ttk::frame $p.printerf]\n\tpack $pf -side top -fill x -expand no -padx 9p -pady 9p\n\n\tttk::label $pf.printerl -text \"[mc \"Printer\"]\"\n\tset tv [ttk::treeview $pf.prlist -height 5 \\\n\t    -columns {printer location state} \\\n\t    -show headings \\\n\t    -selectmode browse]\n\t$tv configure \\\n\t    -yscrollcommand [namespace code [list _scroll $pf.sy]] \\\n\t    -xscrollcommand [namespace code [list _scroll $pf.sx]]\n\tttk::scrollbar $pf.sy -command [list $tv yview]\n\tttk::scrollbar $pf.sx -command [list $tv xview] -orient horizontal\n\t$tv heading printer  -text [mc \"Printer\"]\n\t$tv heading location -text [mc \"Location\"]\n\t$tv heading state    -text [mc \"State\"]\n\t$tv column printer  -width 200 -stretch 0\n\t$tv column location -width 100 -stretch 0\n\t$tv column state    -width 250 -stretch 0\n\n\tforeach printer $optlist(printer) {\n\t    set location [dict getdef $pinfo($printer) printer-location \"\"]\n\t    set nstate [dict getdef $pinfo($printer) printer-state 0]\n\t    set state [dict getdef $statemap $nstate \"\"]\n\t    switch -- $nstate {\n\t\t3 - 4 {\n\t\t    set accepting [dict getdef $pinfo($printer) \\\n\t\t\tprinter-is-accepting-jobs \"\"]\n\t\t    if {$accepting ne \"\"} {\n\t\t\tappend state \". \" [mc \"Printer is accepting jobs\"]\n\t\t    }\n\t\t}\n\t\t5 {\n\t\t    set reason [dict getdef $pinfo($printer) \\\n\t\t\tprinter-state-reasons \"\"]\n\t\t    if {$reason ne \"\"} {\n\t\t\t    append state \". (\" $reason \")\"\n\t\t    }\n\t\t}\n\t    }\n\t    set id [$tv insert {} end \\\n\t\t-values [list $printer $location $state]]\n\t    if {$option(printer) eq $printer} {\n\t\t$tv selection set $id\n\t    }\n\t}\n\n\tgrid $pf.printerl -sticky w\n\tgrid $pf.prlist $pf.sy -sticky news\n\tgrid $pf.sx -sticky ew\n\tgrid remove $pf.sy $pf.sx\n\tbind $tv <<TreeviewSelect>> [namespace code {_onselect %W}]\n\n\t# Start of printing options\n\tset of [ttk::labelframe $p.optionsframe -text [mc \"Options\"]]\n\tpack $of -fill x -padx 9p -pady {0 9p} -ipadx 2p -ipady 2p\n\n\t# COPIES\n\tttk::label $of.copiesl -text \"[mc \"Copies\"] :\"\n\tttk::spinbox $of.copies -textvariable ${var}(copies) \\\n\t    -from 1 -to 1000\n\tgrid $of.copiesl $of.copies -sticky ew -padx 2p -pady 2p\n\t$of.copies state readonly\n\n\t# PAPER SIZE\n\tttk::label $of.medial -text \"[mc \"Paper\"] :\"\n\tttk_optionMenu $of.media ${var}(media) {*}$optlist(media)\n\tgrid $of.medial $of.media -sticky ew -padx 2p -pady 2p\n\n\tif {$class eq \"Canvas\"} {\n\t    # additional options for Canvas output\n\t    # SCALE\n\t    ttk::label $of.percentl -text \"[mc \"Scale\"] :\"\n\t    ttk::spinbox $of.percent -textvariable ${var}(czoom) \\\n\t\t-from 5 -to 500 -increment 5\n\t    grid $of.percentl $of.percent -sticky ew -padx 2p -pady 2p\n\t    $of.percent state readonly\n\n\t    # ORIENT\n\t    ttk::label $of.orientl -text \"[mc \"Orientation\"] :\"\n\t    ttk_optionMenu $of.orient ${var}(orient) {*}$optlist(orient)\n\t    grid $of.orientl $of.orient -sticky ew -padx 2p -pady 2p\n\n\t    # COLOR\n\t    ttk::label $of.colorl -text \"[mc \"Output\"] :\"\n\t    ttk_optionMenu $of.color ${var}(color) {*}$optlist(color)\n\t    grid $of.colorl $of.color -sticky ew -padx 2p -pady 2p\n\t} elseif {$class eq \"Text\"} {\n\t    # additional options for Text output\n\t    # NUMBER-UP\n\t    ttk::label $of.nupl -text \"[mc \"Pages per sheet\"] :\"\n\t    ttk_optionMenu $of.nup ${var}(number-up) {*}$optlist(number-up)\n\t    grid $of.nupl $of.nup -sticky ew -padx 2p -pady 2p\n\n\t    # TEXT SCALE\n\t    ttk::label $of.tzooml -text \"[mc \"Text scale\"] :\"\n\t    ttk::spinbox $of.tzoom -textvariable ${var}(tzoom) \\\n\t\t-from 50 -to 200 -increment 5\n\t    grid $of.tzooml $of.tzoom -sticky ew -padx 2p -pady 2p\n\t    $of.tzoom state readonly\n\n\t    # PRETTY PRINT (banner on top)\n\t    ttk::checkbutton $of.pprint -onvalue 1 -offvalue 0 \\\n\t\t-text [mc \"Pretty print\"] \\\n\t\t-variable ${var}(pprint)\n\t    grid $of.pprint - -sticky ew -padx 2p -pady 2p\n\t}\n\n\t# The buttons frame.\n\tset bf [ttk::frame $p.buttonf]\n\tpack $bf -fill x -expand no -side bottom -padx 9p -pady {0 9p}\n\n\tttk::button $bf.print -text [mc \"Print\"] \\\n\t    -command [namespace code [list _runprint $w $class $p]]\n\tttk::button $bf.cancel -text [mc \"Cancel\"] \\\n\t    -command [list destroy $p]\n\tpack $bf.print  -side right\n\tpack $bf.cancel -side right -padx {0 4.5p}\n\n\t# cleanup binding\n\tbind $bf <Destroy> [namespace code [list _cleanup $p]]\n\n\t# Center the window as a dialog.\n\t::tk::PlaceWindow $p\n    }\n\n    # _onselect\n    #   Updates the selected printer when treeview selection changes.\n    # Arguments:\n    #   tv - treeview pathname.\n    #\n    proc ::tk::print::_onselect {tv} {\n\tvariable dlg::option\n\tset id [$tv selection]\n\tif {$id eq \"\"} {\n\t    # is this even possible?\n\t    set option(printer) \"\"\n\t} else {\n\t    set option(printer) [$tv set $id printer]\n\t}\n    }\n\n    # _scroll\n    #   Implements autoscroll for the printers view\n    #\n    proc ::tk::print::_scroll {sbar from to} {\n\tif {$from == 0.0 && $to == 1.0} {\n\t    grid remove $sbar\n\t} else {\n\t    grid $sbar\n\t    $sbar set $from $to\n\t}\n    }\n\n    # _cleanup\n    #   Perform cleanup when the dialog is destroyed.\n    # Arguments:\n    #   p - print dialog pathname (not used).\n    #\n    proc ::tk::print::_cleanup {p} {\n\tnamespace delete dlg\n    }\n\n    # _runprint -\n    #   Execute the print command--print the file.\n    # Arguments:\n    #   w     - widget with contents to print.\n    #   class - class of the widget to print (Canvas or Text).\n    #   p     - print dialog pathname.\n    #\n    proc ::tk::print::_runprint {w class p} {\n\tvariable option\n\tvariable mcmap\n\n\t# copy the values back from the dialog\n\tarray set option [array get dlg::option]\n\n\t# get (back) name of media from the translated one\n\tset media [dict get $mcmap(media) $option(media)]\n\tset printargs {}\n\tlappend printargs -title \"[tk appname]: Tk window $w\"\n\tlappend printargs -copies $option(copies)\n\tlappend printargs -media $media\n\n\tif {$class eq \"Canvas\"} {\n\t    set colormode [dict get $mcmap(color) $option(color)]\n\t    set rotate 0\n\t    if {[dict get $mcmap(orient) $option(orient)] eq \"landscape\"} {\n\t\tset rotate 1\n\t    }\n\t    # Scale based on size of widget, not size of paper.\n\t    set args {}\n\t    set sr [$w cget -scrollregion]\n\t    if {$sr != \"\"} {\n\t\tset sr [lmap x $sr {\n\t\t    winfo pixels $w $x\n\t\t}]\n\t\tforeach k {-x -y -width -height} x $sr {\n\t\t    lappend args $k $x\n\t\t}\n\t    }\n\t    # TODO: is this correct??\n\t    set printwidth [expr {\n\t\t$option(czoom) / 100.0 * [winfo width $w]\n\t    }]\n\t    set data [encoding convertto iso8859-1 [$w postscript \\\n\t\t-colormode $colormode -rotate $rotate -pagewidth $printwidth \\\n\t\t{*}$args]]\n\t} elseif {$class eq \"Text\"} {\n\t    set tzoom [expr {$option(tzoom) / 100.0}]\n\t    if {$option(tzoom) != 100} {\n\t\tlappend printargs -tzoom $tzoom\n\t    }\n\t    if {$option(pprint)} {\n\t\tlappend printargs -prettyprint\n\t    }\n\t    if {$option(number-up) != 1} {\n\t\tlappend printargs -nup $option(number-up)\n\t    }\n\t    # these are hardcoded. Should we allow the user to control\n\t    # margins?\n\t    lappend printargs -margins [list \\\n\t\t$option(margin-top)    $option(margin-left) \\\n\t\t$option(margin-bottom) $option(margin-right) ]\n\t    # get the data in shape. Cupsfilter's text filter wraps lines\n\t    # at character level, not words, so we do it by ourselves.\n\t    # compute usable page width in inches\n\t    set pw [dict get {a4 8.27 legal 8.5 letter 8.5} $media]\n\t    set pw [expr {\n\t\t$pw - ($option(margin-left) + $option(margin-right)) / 72.0\n\t    }]\n\t    # set the wrap length at 98% of computed page width in chars\n\t    # the 9.8 constant is the product 10.0 (default cpi) * 0.98\n\t    set wl [expr {int( 9.8 * $pw / $tzoom )}]\n\t    set data [encoding convertto utf-8 \\\n\t\t[join [_wrapLines [$w get 1.0 end] $wl] \"\\n\"]]\n\t}\n\n\t# launch the job in the background\n\tafter idle [namespace code \\\n\t    [list cups print $option(printer) $data {*}$printargs]]\n\tdestroy $p\n    }\n}\n#end X11 procedures\n\nnamespace eval ::tk::print {\n    #begin macOS Aqua procedures\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t# makePDF -\n\t#   Convert a file to PDF\n\t# Arguments:\n\t#   inFilename -  file containing the data to convert; format is\n\t#                 autodetected.\n\t#   outFilename - base for filename to write to; conventionally should\n\t#                 have .pdf as suffix\n\t# Returns:\n\t#   The full pathname of the generated PDF.\n\t#\n\tproc makePDF {inFilename outFilename} {\n\t    set out [::tk::print::makeTempFile $outFilename]\n\t    try {\n\t\texec /usr/sbin/cupsfilter $inFilename > $out\n\t    } trap NONE {msg} {\n\t\t# cupsfilter produces a lot of debugging output, which we\n\t\t# don't want.\n\t\tregsub -all -line {^(?:DEBUG|INFO):.*$} $msg \"\" msg\n\t\tset msg [string trimleft [regsub -all {\\n+} $msg \"\\n\"] \"\\n\"]\n\t\tif {$msg ne \"\"} {\n\t\t    # Lines should be prefixed with WARN or ERROR now\n\t\t    puts $msg\n\t\t}\n\t    }\n\t    return $out\n\t}\n    }\n    #end macOS Aqua procedures\n\n    namespace export canvas text\n    namespace ensemble create\n}\n\n# tk print --\n# This procedure prints the canvas and text widgets using platform-\n# native API's.\n#   Arguments:\n#      w: Widget to print.\nproc ::tk::print {w} {\n    switch [winfo class $w],[tk windowingsystem] {\n\t\"Canvas,win32\" -\n\t\"Text,win32\" {\n\t    tailcall ::tk::print::_print $w\n\t}\n\t\"Canvas,x11\" -\n\t\"Text,x11\" {\n\t    tailcall ::tk::print::_print $w\n\t}\n\t\"Canvas,aqua\" {\n\t    ::tk::print::_printcanvas $w\n\t    set printfile /tmp/tk_canvas.pdf\n\t    ::tk::print::_print $printfile\n\t}\n\t\"Text,aqua\" {\n\t    set txtfile [::tk::print::makeTempFile tk_text.txt [$w get 1.0 end]]\n\t    try {\n\t\tset printfile [::tk::print::makePDF $txtfile [file join /tmp tk_text.pdf]]\n\t\t::tk::print::_print $printfile\n\t    } finally {\n\t\tfile delete $txtfile\n\t    }\n\t}\n\n\tdefault {\n\t    return -code error -errorcode {TK PRINT CLASS_UNSUPPORTED} \\\n\t\t\"widgets of class [winfo class $w] are not supported on\\\n\t\tthis platform\"\n\t}\n    }\n}\n\n#Add this command to the tk command ensemble: tk print\n#Thanks to Christian Gollwitzer for the guidance here\nnamespace ensemble configure tk -map \\\n    [dict merge [namespace ensemble configure tk -map] \\\n\t {print ::tk::print}]\n\f\nreturn\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "library/safetk.tcl",
    "content": "# safetk.tcl --\n#\n# Support procs to use Tk in safe interpreters.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n# see safetk.n for documentation\n\n#\n#\n# Note: It is now ok to let untrusted code being executed\n#       between the creation of the interp and the actual loading\n#       of Tk in that interp because the C side Tk_Init will\n#       now look up the parent interp and ask its safe::TkInit\n#       for the actual parameters to use for it's initialization (if allowed),\n#       not relying on the child state.\n#\n\n# We use opt (optional arguments parsing)\npackage require opt 0.4.1;\n\nnamespace eval ::safe {\n\n    # counter for safe toplevels\n    variable tkSafeId 0\n}\n\n#\n# tkInterpInit : prepare the child interpreter for tk loading\n#                most of the real job is done by loadTk\n# returns the child name (tkInterpInit does)\n#\nproc ::safe::tkInterpInit {child argv} {\n    global env tk_library\n\n    # We have to make sure that the tk_library variable is normalized.\n    set tk_library [file normalize $tk_library]\n\n    # Clear Tk's access for that interp (path).\n    allowTk $child $argv\n\n    # Ensure tk_library and subdirs (eg, ttk) are on the access path\n    ::interp eval $child [list set tk_library [::safe::interpAddToAccessPath $child $tk_library]]\n    foreach subdir [::safe::AddSubDirs [list $tk_library]] {\n\t::safe::interpAddToAccessPath $child $subdir\n    }\n    return $child\n}\n\n\n# tkInterpLoadTk:\n# Do additional configuration as needed (calling tkInterpInit)\n# and actually load Tk into the child.\n#\n# Either contained in the specified windowId (-use) or\n# creating a decorated toplevel for it.\n\n# empty definition for auto_mkIndex\nproc ::safe::loadTk {} {}\n\n::tcl::OptProc ::safe::loadTk {\n    {child -interp \"name of the child interpreter\"}\n    {-use  -windowId {} \"window Id to use (new toplevel otherwise)\"}\n    {-display -displayName {} \"display name to use (current one otherwise)\"}\n} {\n    set displayGiven [::tcl::OptProcArgGiven \"-display\"]\n    if {!$displayGiven} {\n\t# Try to get the current display from \".\"\n\t# (which might not exist if the parent is tk-less)\n\tif {[catch {set display [winfo screen .]}]} {\n\t    if {[info exists ::env(DISPLAY)]} {\n\t\tset display $::env(DISPLAY)\n\t    } else {\n\t\tLog $child \"no winfo screen . nor env(DISPLAY)\" WARNING\n\t\tset display \":0.0\"\n\t    }\n\t}\n    }\n\n    # Get state for access to the cleanupHook.\n    namespace upvar ::safe S$child state\n\n    if {![::tcl::OptProcArgGiven \"-use\"]} {\n\t# create a decorated toplevel\n\tlassign [tkTopLevel $child $display] w use\n\n\t# set our delete hook (child arg is added by interpDelete)\n\t# to clean up both window related code and tkInit(child)\n\tset state(cleanupHook) [list tkDelete {} $w]\n    } else {\n\t# set our delete hook (child arg is added by interpDelete)\n\t# to clean up tkInit(child)\n\tset state(cleanupHook) [list disallowTk]\n\n\t# Let's be nice and also accept tk window names instead of ids\n\tif {[string match \".*\" $use]} {\n\t    set windowName $use\n\t    set use [winfo id $windowName]\n\t    set nDisplay [winfo screen $windowName]\n\t} else {\n\t    # Check for a better -display value\n\t    # (works only for multi screens on single host, but not\n\t    #  cross hosts, for that a tk window name would be better\n\t    #  but embeding is also usefull for non tk names)\n\t    if {![catch {winfo pathname $use} name]} {\n\t\tset nDisplay [winfo screen $name]\n\t    } else {\n\t\t# Can't have a better one\n\t\tset nDisplay $display\n\t    }\n\t}\n\tif {$nDisplay ne $display} {\n\t    if {$displayGiven} {\n\t\treturn -code error -errorcode {TK DISPLAY SAFE} \\\n\t\t    \"conflicting -display $display and -use $use -> $nDisplay\"\n\t    } else {\n\t\tset display $nDisplay\n\t    }\n\t}\n    }\n\n    # Prepares the child for tk with those parameters\n    tkInterpInit $child [list \"-use\" $use \"-display\" $display]\n\n    load {} Tk $child\n\n    return $child\n}\n\nproc ::safe::TkInit {interpPath} {\n    variable tkInit\n    if {[info exists tkInit($interpPath)]} {\n\tset value $tkInit($interpPath)\n\tLog $interpPath \"TkInit called, returning \\\"$value\\\"\" NOTICE\n\treturn $value\n    } else {\n\tLog $interpPath \"TkInit called for interp with clearance:\\\n\t\tpreventing Tk init\" ERROR\n\treturn -code error -errorcode {TK SAFE PERMISSION} \"not allowed\"\n    }\n}\n\n# safe::allowTk --\n#\n#\tSet tkInit(interpPath) to allow Tk to be initialized in\n#\tsafe::TkInit.\n#\n# Arguments:\n#\tinterpPath\tchild interpreter handle\n#\targv\t\targuments passed to safe::TkInterpInit\n#\n# Results:\n#\tnone.\n\nproc ::safe::allowTk {interpPath argv} {\n    variable tkInit\n    set tkInit($interpPath) $argv\n    return\n}\n\n\n# safe::disallowTk --\n#\n#\tUnset tkInit(interpPath) to disallow Tk from getting initialized\n#\tin safe::TkInit.\n#\n# Arguments:\n#\tinterpPath\tchild interpreter handle\n#\n# Results:\n#\tnone.\n\nproc ::safe::disallowTk {interpPath} {\n    variable tkInit\n    # This can already be deleted by the DeleteHook of the interp\n    if {[info exists tkInit($interpPath)]} {\n\tunset tkInit($interpPath)\n    }\n    return\n}\n\n\n# safe::tkDelete --\n#\n#\tClean up the window associated with the interp being deleted.\n#\n# Arguments:\n#\tinterpPath\tchild interpreter handle\n#\n# Results:\n#\tnone.\n\nproc ::safe::tkDelete {W window child} {\n\n    # we are going to be called for each widget... skip untill it's\n    # top level\n\n    Log $child \"Called tkDelete $W $window\" NOTICE\n    if {[::interp exists $child]} {\n\tif {[catch {::safe::interpDelete $child} msg]} {\n\t    Log $child \"Deletion error : $msg\"\n\t}\n    }\n    if {[winfo exists $window]} {\n\tLog $child \"Destroy toplevel $window\" NOTICE\n\tdestroy $window\n    }\n\n    # clean up tkInit(child)\n    disallowTk $child\n    return\n}\n\nproc ::safe::tkTopLevel {child display} {\n    variable tkSafeId\n    incr tkSafeId\n    set w \".safe$tkSafeId\"\n    if {[catch {toplevel $w -screen $display -class SafeTk} msg]} {\n\treturn -code error -errorcode {TK TOPLEVEL SAFE} \\\n\t    \"Unable to create toplevel for \\\"$child\\\" ($msg)\"\n    }\n    Log $child \"New toplevel $w\" NOTICE\n\n    set msg \"Untrusted Tcl applet ($child)\"\n    wm title $w $msg\n\n    # Control frame (we must create a style for it)\n    ttk::style layout TWarningFrame {WarningFrame.border -sticky nswe}\n    ttk::style configure TWarningFrame -background red\n\n    set wc $w.fc\n    ttk::frame $wc -relief ridge -borderwidth 4 -style TWarningFrame\n\n    # We will destroy the interp when the window is destroyed\n    bindtags $wc [concat Safe$wc [bindtags $wc]]\n    bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $child]\n\n    ttk::label $wc.l -text $msg -anchor w\n\n    # We want the button to be the last visible item\n    # (so be packed first) and at the right and not resizing horizontally\n\n    # frame the button so it does not expand horizontally\n    # but still have the default background instead of red one from the parent\n    ttk::frame  $wc.fb -borderwidth 0\n    ttk::button $wc.fb.b -text \"Delete\" \\\n\t    -command [list ::safe::tkDelete $w $w $child]\n    pack $wc.fb.b -side right -fill both\n    pack $wc.fb -side right -fill both -expand 1\n    pack $wc.l -side left -fill both -expand 1 -ipady 1.5p\n    pack $wc -side bottom -fill x\n\n    # Container frame\n    frame $w.c -container 1\n    pack $w.c -fill both -expand 1\n\n    # return both the toplevel window name and the id to use for embedding\n    list $w [winfo id $w.c]\n}\n"
  },
  {
    "path": "library/scale.tcl",
    "content": "# scale.tcl --\n#\n# This file defines the default bindings for Tk scale widgets and provides\n# procedures that help in implementing the bindings.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for entries.\n#-------------------------------------------------------------------------\n\n# Standard Motif bindings:\n\nbind Scale <Enter> {\n    if {$tk_strictMotif} {\n\tset tk::Priv(activeBg) [%W cget -activebackground]\n\t%W configure -activebackground [%W cget -background]\n    }\n    tk::ScaleActivate %W %x %y\n}\nbind Scale <Motion> {\n    tk::ScaleActivate %W %x %y\n}\nbind Scale <Leave> {\n    if {$tk_strictMotif} {\n\t%W configure -activebackground $tk::Priv(activeBg)\n    }\n    if {[%W cget -state] eq \"active\"} {\n\t%W configure -state normal\n    }\n}\nbind Scale <Button-1> {\n    tk::ScaleButtonDown %W %x %y\n}\nbind Scale <B1-Motion> {\n    tk::ScaleDrag %W %x %y\n}\nbind Scale <B1-Leave> { }\nbind Scale <B1-Enter> { }\nbind Scale <ButtonRelease-1> {\n    tk::CancelRepeat\n    tk::ScaleEndDrag %W\n    tk::ScaleActivate %W %x %y\n}\nbind Scale <Button-2> {\n    tk::ScaleButton2Down %W %x %y\n}\nbind Scale <B2-Motion> {\n    tk::ScaleDrag %W %x %y\n}\nbind Scale <B2-Leave> { }\nbind Scale <B2-Enter> { }\nbind Scale <ButtonRelease-2> {\n    tk::CancelRepeat\n    tk::ScaleEndDrag %W\n    tk::ScaleActivate %W %x %y\n}\nbind Scale <Control-Button-1> {\n    tk::ScaleControlPress %W %x %y\n}\nbind Scale <<PrevLine>> {\n    tk::ScaleIncrement %W up little noRepeat\n}\nbind Scale <<NextLine>> {\n    tk::ScaleIncrement %W down little noRepeat\n}\nbind Scale <<PrevChar>> {\n    tk::ScaleIncrement %W up little noRepeat\n}\nbind Scale <<NextChar>> {\n    tk::ScaleIncrement %W down little noRepeat\n}\nbind Scale <<PrevPara>> {\n    tk::ScaleIncrement %W up big noRepeat\n}\nbind Scale <<NextPara>> {\n    tk::ScaleIncrement %W down big noRepeat\n}\nbind Scale <<PrevWord>> {\n    tk::ScaleIncrement %W up big noRepeat\n}\nbind Scale <<NextWord>> {\n    tk::ScaleIncrement %W down big noRepeat\n}\nbind Scale <<LineStart>> {\n    %W set [%W cget -from]\n}\nbind Scale <<LineEnd>> {\n    %W set [%W cget -to]\n}\n\n# ::tk::ScaleActivate --\n# This procedure is invoked to check a given x-y position in the\n# scale and activate the slider if the x-y position falls within\n# the slider.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n# x, y -\tMouse coordinates.\n\nproc ::tk::ScaleActivate {w x y} {\n    if {[$w cget -state] eq \"disabled\"} {\n\treturn\n    }\n    if {[$w identify $x $y] eq \"slider\"} {\n\tset state active\n    } else {\n\tset state normal\n    }\n    if {[$w cget -state] ne $state} {\n\t$w configure -state $state\n    }\n}\n\n# ::tk::ScaleButtonDown --\n# This procedure is invoked when a button is pressed in a scale.  It\n# takes different actions depending on where the button was pressed.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n# x, y -\tMouse coordinates of button press.\n\nproc ::tk::ScaleButtonDown {w x y} {\n    variable ::tk::Priv\n    set Priv(dragging) 0\n    set el [$w identify $x $y]\n\n    # save the relief\n    set Priv($w,relief) [$w cget -sliderrelief]\n\n    if {$el eq \"trough1\"} {\n\tScaleIncrement $w up little initial\n    } elseif {$el eq \"trough2\"} {\n\tScaleIncrement $w down little initial\n    } elseif {$el eq \"slider\"} {\n\tset Priv(dragging) 1\n\tset Priv(initValue) [$w get]\n\tset coords [$w coords]\n\tset Priv(deltaX) [expr {$x - [lindex $coords 0]}]\n\tset Priv(deltaY) [expr {$y - [lindex $coords 1]}]\n\tswitch -exact -- $Priv($w,relief) {\n\t    \"raised\" { $w configure -sliderrelief sunken }\n\t    \"ridge\"  { $w configure -sliderrelief groove }\n\t}\n    }\n}\n\n# ::tk::ScaleDrag --\n# This procedure is called when the mouse is dragged with\n# mouse button 1 down.  If the drag started inside the slider\n# (i.e. the scale is active) then the scale's value is adjusted\n# to reflect the mouse's position.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n# x, y -\tMouse coordinates.\n\nproc ::tk::ScaleDrag {w x y} {\n    variable ::tk::Priv\n    if {!$Priv(dragging)} {\n\treturn\n    }\n    $w set [$w get [expr {$x-$Priv(deltaX)}] [expr {$y-$Priv(deltaY)}]]\n}\n\n# ::tk::ScaleEndDrag --\n# This procedure is called to end an interactive drag of the\n# slider.  It just marks the drag as over.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n\nproc ::tk::ScaleEndDrag {w} {\n    variable ::tk::Priv\n    set Priv(dragging) 0\n    if {[info exists Priv($w,relief)]} {\n\t$w configure -sliderrelief $Priv($w,relief)\n\tunset Priv($w,relief)\n    }\n}\n\n# ::tk::ScaleIncrement --\n# This procedure is invoked to increment the value of a scale and\n# to set up auto-repeating of the action if that is desired.  The\n# way the value is incremented depends on the \"dir\" and \"big\"\n# arguments.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n# dir -\t\t\"up\" means move value towards -from, \"down\" means\n#\t\tmove towards -to.\n# big -\t\tSize of increments: \"big\" or \"little\".\n# repeat -\tWhether and how to auto-repeat the action:  \"noRepeat\"\n#\t\tmeans don't auto-repeat, \"initial\" means this is the\n#\t\tfirst action in an auto-repeat sequence, and \"again\"\n#\t\tmeans this is the second repetition or later.\n\nproc ::tk::ScaleIncrement {w dir big repeat} {\n    variable ::tk::Priv\n\n    if {![winfo exists $w]} return\n\n    # give the cancel callback a chance to be serviced if the execution time of\n    # the -command script lasts longer than -repeatdelay\n    set clockms [clock milliseconds]\n    if {$repeat eq \"again\" &&\n\t    [expr {$clockms - $Priv(clockms)}] > [expr {[$w cget -repeatinterval] * 1.1}]} {\n\tset Priv(clockms) $clockms\n\tset Priv(afterId) [after [$w cget -repeatinterval] \\\n\t\t[list tk::ScaleIncrement $w $dir $big again]]\n\treturn\n    }\n\n    if {$big eq \"big\"} {\n\tset inc [$w cget -bigincrement]\n\tif {$inc == 0} {\n\t    set inc [expr {abs([$w cget -to] - [$w cget -from])/10.0}]\n\t}\n\tif {$inc < [$w cget -resolution]} {\n\t    set inc [$w cget -resolution]\n\t}\n    } else {\n\tset inc [$w cget -resolution]\n    }\n    if {([$w cget -from] > [$w cget -to]) ^ ($dir eq \"up\")} {\n\tif {$inc > 0} {\n\t    set inc [expr {-$inc}]\n\t}\n    } else {\n\tif {$inc < 0} {\n\t    set inc [expr {-$inc}]\n\t}\n    }\n    # this will run the -command script (if any) during the redrawing\n    # of the scale at idle time\n    $w set [expr {[$w get] + $inc}]\n\n    if {$repeat eq \"again\"} {\n\tset Priv(clockms) $clockms\n\tset Priv(afterId) [after [$w cget -repeatinterval] \\\n\t\t[list tk::ScaleIncrement $w $dir $big again]]\n    } elseif {$repeat eq \"initial\"} {\n\tset delay [$w cget -repeatdelay]\n\tif {$delay > 0} {\n\t    set Priv(clockms) $clockms\n\t    set Priv(afterId) [after $delay \\\n\t\t    [list tk::ScaleIncrement $w $dir $big again]]\n\t}\n    }\n}\n\n# ::tk::ScaleControlPress --\n# This procedure handles button presses that are made with the Control\n# key down.  Depending on the mouse position, it adjusts the scale\n# value to one end of the range or the other.\n#\n# Arguments:\n# w -\t\tThe scale widget.\n# x, y -\tMouse coordinates where the button was pressed.\n\nproc ::tk::ScaleControlPress {w x y} {\n    set el [$w identify $x $y]\n    if {$el eq \"trough1\"} {\n\t$w set [$w cget -from]\n    } elseif {$el eq \"trough2\"} {\n\t$w set [$w cget -to]\n    }\n}\n\n# ::tk::ScaleButton2Down\n# This procedure is invoked when button 2 is pressed over a scale.\n# It sets the value to correspond to the mouse position and starts\n# a slider drag.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tMouse coordinates within the widget.\n\nproc ::tk::ScaleButton2Down {w x y} {\n    variable ::tk::Priv\n\n    if {[$w cget -state] eq \"disabled\"} {\n\treturn\n    }\n\n    $w configure -state active\n    $w set [$w get $x $y]\n    set Priv(dragging) 1\n    set Priv(initValue) [$w get]\n    set Priv($w,relief) [$w cget -sliderrelief]\n    set coords \"$x $y\"\n    set Priv(deltaX) 0\n    set Priv(deltaY) 0\n}\n"
  },
  {
    "path": "library/scaling.tcl",
    "content": "# scaling.tcl --\n#\n# Contains scaling-related utility procedures.\n#\n# Copyright © 2022 Csaba Nemethi <csaba.nemethi@t-online.de>\n\n# ::tk::ScalingPct --\n#\n# Returns the display's \"scaling percentage\" (the display resolution expressed\n# as a percentage of 96dpi), rounded to the nearest multiple of 25 that is at\n# least 100.\n#\n# On X11 systems (but not on SDL systems that claim to be X11), the first call\n# of the command also sets [tk scaling] and ::tk::fontScalingFactor to values\n# extracted from the X11 configuration.\n#\n# The command is called during Tk initialization, from icons.tcl, when the\n# latter is sourced by tk.tcl.\n\nproc ::tk::ScalingPct {} {\n    set pct [expr {[tk scaling] * 75}]\n\n    variable doneScalingInitX11\n    if {![info exists doneScalingInitX11]} {\n\tset pct [::tk::ScalingInitX11 $pct]\n\tset doneScalingInitX11 1\n    }\n\n    #\n    # Save the value of pct rounded to the nearest multiple\n    # of 25 that is at least 100, in the variable scalingPct.\n    # See \"man n tk_scalingPct\" for use of ::tk::scalingPct.\n    #\n    variable scalingPct\n    for {set scalingPct 100} {1} {incr scalingPct 25} {\n\tif {$pct < $scalingPct + 12.5} {\n\t    break\n\t}\n    }\n\n    return $scalingPct\n}\n\nproc ::tk::ScalingInitX11 {pct} {\n    set onX11 [expr {[tk windowingsystem] eq \"x11\"}]\n    set usingSDL [expr {[info exists ::tk::sdltk] && $::tk::sdltk}]\n\n    if {$onX11 && !$usingSDL} {\n\tset origPct $pct\n\n\t#\n\t# Try to get the window scaling factor (1 or 2), partly\n\t# based on https://wiki.archlinux.org/title/HiDPI\n\t#\n\tset winScalingFactor 1\n\tvariable fontScalingFactor 1\t\t;# needed in the file ttk/fonts\n\tif {[catch {exec ps -e | grep xfce4-session}] == 0} {\t\t;# Xfce\n\t    if {[catch {exec xfconf-query -c xsettings \\\n\t\t -p /Gdk/WindowScalingFactor} result] == 0} {\n\t\tset winScalingFactor $result\n\t\tif {$winScalingFactor >= 2} {\n\t\t    set fontScalingFactor 2\n\t\t}\n\t    }\n\n\t    #\n\t    # The DPI value can be set in the \"Fonts\" tab of the \"Appearance\"\n\t    # dialog or (on Linux Lite 5+) via the \"HiDPI Settings\" dialog.\n\t    #\n\t} elseif {[catch {exec ps -e | grep mate-session}] == 0} {\t;# MATE\n\t    if {[catch {exec gsettings get org.mate.interface \\\n\t\t window-scaling-factor} result] == 0} {\n\t\tif {$result == 0} {\t\t\t;# means: \"Auto-detect\"\n\t\t    #\n\t\t    # Try to get winScalingFactor from the cursor size\n\t\t    #\n\t\t    if {[catch {exec xrdb -query | grep Xcursor.size} result]\n\t\t\t== 0 &&\n\t\t\t[catch {exec gsettings get org.mate.peripherals-mouse \\\n\t\t\t cursor-size} defCursorSize] == 0} {\n\t\t\tset cursorSize [lindex $result 1]\n\t\t\tset winScalingFactor \\\n\t\t\t    [expr {($cursorSize + $defCursorSize - 1) /\n\t\t\t\t   $defCursorSize}]\n\t\t    }\n\t\t} else {\n\t\t    set winScalingFactor $result\n\t\t}\n\t    }\n\n\t    #\n\t    # The DPI value can be set via the \"Font Rendering Details\"\n\t    # dialog, which can be opened using the \"Details...\" button\n\t    # in the \"Fonts\" tab of the \"Appearance Preferences\" dialog.\n\t    #\n\t} elseif {[catch {exec ps -e | grep gnome-session}] == 0 &&\n\t\t  [catch {exec gsettings get \\\n\t\t   org.gnome.settings-daemon.plugins.xsettings overrides} \\\n\t\t   result] == 0 &&\n\t\t  [set idx \\\n\t\t   [string first \"'Gdk/WindowScalingFactor'\" $result]] >= 0} {\n\t    scan [string range $result $idx end] \"%*s <%d>\" winScalingFactor\n\t}\n\n\t#\n\t# Get the scaling percentage\n\t#\n\tif {$winScalingFactor >= 2} {\n\t    set pct 200\n\t} elseif {[catch {exec xrdb -query | grep Xft.dpi} result] == 0} {\n\t    #\n\t    # Derive the value of pct from that of the font DPI\n\t    #\n\t    set dpi [lindex $result 1]\n\t    set pct [expr {100.0 * $dpi / 96}]\n\t} elseif {[catch {exec ps -e | grep gnome-session}] == 0 &&\n\t\t  ![info exists ::env(WAYLAND_DISPLAY)] &&\n\t\t  [catch {exec xrandr | grep \" connected\"} result] == 0 &&\n\t\t  [catch {open $::env(HOME)/.config/monitors.xml} chan] == 0} {\n\t    #\n\t    # Update pct by scanning the file ~/.config/monitors.xml\n\t    #\n\t    ScanMonitorsFile $result $chan pct\n\t}\n\n\tif {($pct != 100) && ($pct != $origPct) && (![interp issafe])} {\n\t    #\n\t    # Set Tk's scaling factor according to $pct\n\t    #\n\t    tk scaling [expr {$pct / 75.0}]\n\t}\n    }\n    return $pct\n}\n\n# ::tk::ScaleNum --\n#\n# Scales an integer according to the display's current scaling percentage.\n#\n# Arguments:\n#   num - An integer.\n\nproc ::tk::ScaleNum num {\n    return [expr {round($num * [tk scaling] * 0.75)}]\n}\n\n# ::tk::FontScalingFactor --\n#\n# Accessor command for variable ::tk::fontScalingFactor.\n\nproc ::tk::FontScalingFactor {} {\n    variable fontScalingFactor\n    if {[info exists fontScalingFactor]} {\n\treturn $fontScalingFactor\n    } else {\n\treturn 1\n    }\n}\n\n# ::tk::ScanMonitorsFile --\n#\n# Updates the scaling percentage by scanning the file ~/.config/monitors.xml.\n#\n# Arguments:\n#   xrandrResult - The output of 'xrandr | grep \" connected\"'.\n#   chan -\t   Returned from 'open ~/.config/monitors.xml'.\n#   pctName -\t   The name of a variable containing the scaling percentage.\n\nproc ::tk::ScanMonitorsFile {xrandrResult chan pctName} {\n    upvar $pctName pct\n\n    #\n    # Get the list of connected outputs reported by xrandr\n    #\n    set outputList {}\n    foreach line [split $xrandrResult \"\\n\"] {\n\tset idx [string first \" \" $line]\n\tset output [string range $line 0 [incr idx -1]]\n\tlappend outputList $output\n    }\n    set outputList [lsort $outputList]\n\n    #\n    # Get the content of the file ~/.config/monitors.xml\n    #\n    set str [read $chan]\n    close $chan\n\n    #\n    # Run over the file's \"configuration\" sections\n    #\n    set idx 0\n    while {[set idx2 [string first \"<configuration>\" $str $idx]] >= 0} {\n\tset idx2 [string first \">\" $str $idx2]\n\tset idx [string first \"</configuration>\" $str $idx2]\n\tset config [string range $str [incr idx2] [incr idx -1]]\n\n\t#\n\t# Get the list of connectors within this configuration\n\t#\n\tset connectorList {}\n\tforeach {dummy connector} [regexp -all -inline \\\n\t\t{<connector>([^<]+)</connector>} $config] {\n\t    lappend connectorList $connector\n\t}\n\tset connectorList [lsort $connectorList]\n\n\t#\n\t# If $outputList and $connectorList are identical then set the\n\t# variable pct to 100, 200, 300, 400, or 500, depending on the\n\t# max. scaling within this configuration, and exit the loop\n\t#\n\tif {$outputList eq $connectorList} {\n\t    set maxScaling 1.0\n\t    foreach {dummy scaling} [regexp -all -inline \\\n\t\t    {<scale>([^<]+)</scale>} $config] {\n\t\tif {$scaling > $maxScaling} {\n\t\t    set maxScaling $scaling\n\t\t}\n\t    }\n\n\t    foreach n {4 3 2 1 0} {\n\t\tif {$maxScaling > $n} {\n\t\t    set pct [expr {($n + 1) * 100}]\n\t\t    break\n\t\t}\n\t    }\n\n\t    break\n\t}\n    }\n}\n"
  },
  {
    "path": "library/scrlbar.tcl",
    "content": "# scrlbar.tcl --\n#\n# This file defines the default bindings for Tk scrollbar widgets.\n# It also provides procedures that help in implementing the bindings.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for scrollbars.\n#-------------------------------------------------------------------------\n\n# Standard Motif bindings:\nif {[tk windowingsystem] eq \"x11\" || [tk windowingsystem] eq \"aqua\"} {\n\nbind Scrollbar <Enter> {\n    if {$tk_strictMotif} {\n\tset tk::Priv(activeBg) [%W cget -activebackground]\n\t%W configure -activebackground [%W cget -background]\n    }\n    %W activate [%W identify %x %y]\n}\nbind Scrollbar <Motion> {\n    %W activate [%W identify %x %y]\n}\n\n# The \"info exists\" command in the following binding handles the\n# situation where a Leave event occurs for a scrollbar without the Enter\n# event.  This seems to happen on some systems (such as Solaris 2.4) for\n# unknown reasons.\n\nbind Scrollbar <Leave> {\n    if {$tk_strictMotif && [info exists tk::Priv(activeBg)]} {\n\t%W configure -activebackground $tk::Priv(activeBg)\n    }\n    %W activate {}\n}\nbind Scrollbar <Button-1> {\n    tk::ScrollButtonDown %W %x %y\n}\nbind Scrollbar <B1-Motion> {\n    tk::ScrollDrag %W %x %y\n}\nbind Scrollbar <B1-B2-Motion> {\n    tk::ScrollDrag %W %x %y\n}\nbind Scrollbar <ButtonRelease-1> {\n    tk::ScrollButtonUp %W %x %y\n}\nbind Scrollbar <B1-Leave> {\n    # Prevents <Leave> binding from being invoked.\n}\nbind Scrollbar <B1-Enter> {\n    # Prevents <Enter> binding from being invoked.\n}\nbind Scrollbar <Button-2> {\n    tk::ScrollButton2Down %W %x %y\n}\nbind Scrollbar <B1-Button-2> {\n    # Do nothing, since button 1 is already down.\n}\nbind Scrollbar <B2-Button-1> {\n    # Do nothing, since button 2 is already down.\n}\nbind Scrollbar <B2-Motion> {\n    tk::ScrollDrag %W %x %y\n}\nbind Scrollbar <ButtonRelease-2> {\n    tk::ScrollButtonUp %W %x %y\n}\nbind Scrollbar <B1-ButtonRelease-2> {\n    # Do nothing:  B1 release will handle it.\n}\nbind Scrollbar <B2-ButtonRelease-1> {\n    # Do nothing:  B2 release will handle it.\n}\nbind Scrollbar <B2-Leave> {\n    # Prevents <Leave> binding from being invoked.\n}\nbind Scrollbar <B2-Enter> {\n    # Prevents <Enter> binding from being invoked.\n}\nbind Scrollbar <Control-Button-1> {\n    tk::ScrollTopBottom %W %x %y\n}\nbind Scrollbar <Control-Button-2> {\n    tk::ScrollTopBottom %W %x %y\n}\n\nbind Scrollbar <<PrevLine>> {\n    tk::ScrollByUnits %W v -1\n}\nbind Scrollbar <<NextLine>> {\n    tk::ScrollByUnits %W v 1\n}\nbind Scrollbar <<PrevPara>> {\n    tk::ScrollByPages %W v -1\n}\nbind Scrollbar <<NextPara>> {\n    tk::ScrollByPages %W v 1\n}\nbind Scrollbar <<PrevChar>> {\n    tk::ScrollByUnits %W h -1\n}\nbind Scrollbar <<NextChar>> {\n    tk::ScrollByUnits %W h 1\n}\nbind Scrollbar <<PrevWord>> {\n    tk::ScrollByPages %W h -1\n}\nbind Scrollbar <<NextWord>> {\n    tk::ScrollByPages %W h 1\n}\nbind Scrollbar <Prior> {\n    tk::ScrollByPages %W hv -1\n}\nbind Scrollbar <Next> {\n    tk::ScrollByPages %W hv 1\n}\nbind Scrollbar <<LineStart>> {\n    tk::ScrollToPos %W 0\n}\nbind Scrollbar <<LineEnd>> {\n    tk::ScrollToPos %W 1\n}\n}\n\nbind Scrollbar <Enter> {+\n    set tk::Priv(xEvents) 0; set tk::Priv(yEvents) 0\n}\nbind Scrollbar <MouseWheel> {\n    tk::ScrollByUnits %W vh %D -40.0\n}\nbind Scrollbar <Option-MouseWheel> {\n    tk::ScrollByUnits %W vh %D -12.0\n}\nbind Scrollbar <Shift-MouseWheel> {\n    tk::ScrollByUnits %W hv %D -40.0\n}\nbind Scrollbar <Shift-Option-MouseWheel> {\n    tk::ScrollByUnits %W hv %D -12.0\n}\nbind Scrollbar <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n    if {$tk::Priv(deltaX) != 0 && [%W cget -orient] eq \"horizontal\"} {\n\ttk::ScrollbarScrollByPixels %W h $tk::Priv(deltaX)\n    }\n    if {$tk::Priv(deltaY) != 0 && [%W cget -orient] eq \"vertical\"} {\n\ttk::ScrollbarScrollByPixels %W v $tk::Priv(deltaY)\n    }\n}\n\n# tk::ScrollButtonDown --\n# This procedure is invoked when a button is pressed in a scrollbar.\n# It changes the way the scrollbar is displayed and takes actions\n# depending on where the mouse is.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tMouse coordinates.\n\nproc tk::ScrollButtonDown {w x y} {\n    variable ::tk::Priv\n    set Priv(relief) [$w cget -activerelief]\n    $w configure -activerelief sunken\n    set element [$w identify $x $y]\n    if {$element eq \"slider\"} {\n\tScrollStartDrag $w $x $y\n    } else {\n\tScrollSelect $w $element initial\n    }\n}\n\n# ::tk::ScrollButtonUp --\n# This procedure is invoked when a button is released in a scrollbar.\n# It cancels scans and auto-repeats that were in progress, and restores\n# the way the active element is displayed.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tMouse coordinates.\n\nproc ::tk::ScrollButtonUp {w x y} {\n    variable ::tk::Priv\n    tk::CancelRepeat\n    if {[info exists Priv(relief)]} {\n\t# Avoid error due to spurious release events\n\t$w configure -activerelief $Priv(relief)\n\tScrollEndDrag $w $x $y\n\t$w activate [$w identify $x $y]\n    }\n}\n\n# ::tk::ScrollSelect --\n# This procedure is invoked when a button is pressed over the scrollbar.\n# It invokes one of several scrolling actions depending on where in\n# the scrollbar the button was pressed.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# element -\tThe element of the scrollbar that was selected, such\n#\t\tas \"arrow1\" or \"trough2\".  Shouldn't be \"slider\".\n# repeat -\tWhether and how to auto-repeat the action:  \"noRepeat\"\n#\t\tmeans don't auto-repeat, \"initial\" means this is the\n#\t\tfirst action in an auto-repeat sequence, and \"again\"\n#\t\tmeans this is the second repetition or later.\n\nproc ::tk::ScrollSelect {w element repeat} {\n    variable ::tk::Priv\n    if {![winfo exists $w]} return\n    switch -- $element {\n\t\"arrow1\"\t{ScrollByUnits $w hv -1}\n\t\"trough1\"\t{ScrollByPages $w hv -1}\n\t\"trough2\"\t{ScrollByPages $w hv 1}\n\t\"arrow2\"\t{ScrollByUnits $w hv 1}\n\tdefault\t\t{return}\n    }\n    if {$repeat eq \"again\"} {\n\tset Priv(afterId) [after [$w cget -repeatinterval] \\\n\t\t[list tk::ScrollSelect $w $element again]]\n    } elseif {$repeat eq \"initial\"} {\n\tset delay [$w cget -repeatdelay]\n\tif {$delay > 0} {\n\t    set Priv(afterId) [after $delay \\\n\t\t    [list tk::ScrollSelect $w $element again]]\n\t}\n    }\n}\n\n# ::tk::ScrollStartDrag --\n# This procedure is called to initiate a drag of the slider.  It just\n# remembers the starting position of the mouse and slider.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tThe mouse position at the start of the drag operation.\n\nproc ::tk::ScrollStartDrag {w x y} {\n    variable ::tk::Priv\n\n    if {[$w cget -command] eq \"\"} {\n\treturn\n    }\n    set Priv(pressX) $x\n    set Priv(pressY) $y\n    set Priv(initValues) [$w get]\n    set iv0 [lindex $Priv(initValues) 0]\n    if {[llength $Priv(initValues)] == 2} {\n\tset Priv(initPos) $iv0\n    } elseif {$iv0 == 0} {\n\tset Priv(initPos) 0.0\n    } else {\n\tset Priv(initPos) [expr {(double([lindex $Priv(initValues) 2])) \\\n\t\t/ [lindex $Priv(initValues) 0]}]\n    }\n}\n\n# ::tk::ScrollDrag --\n# This procedure is called for each mouse motion even when the slider\n# is being dragged.  It notifies the associated widget if we're not\n# jump scrolling, and it just updates the scrollbar if we are jump\n# scrolling.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tThe current mouse position.\n\nproc ::tk::ScrollDrag {w x y} {\n    variable ::tk::Priv\n\n    if {$Priv(initPos) eq \"\"} {\n\treturn\n    }\n    set delta [$w delta [expr {$x - $Priv(pressX)}] [expr {$y - $Priv(pressY)}]]\n    if {[$w cget -jump]} {\n\tif {[llength $Priv(initValues)] == 2} {\n\t    $w set [expr {[lindex $Priv(initValues) 0] + $delta}] \\\n\t\t    [expr {[lindex $Priv(initValues) 1] + $delta}]\n\t} else {\n\t    set delta [expr {round($delta * [lindex $Priv(initValues) 0])}]\n\t    eval [list $w] set [lreplace $Priv(initValues) 2 3 \\\n\t\t    [expr {[lindex $Priv(initValues) 2] + $delta}] \\\n\t\t    [expr {[lindex $Priv(initValues) 3] + $delta}]]\n\t}\n    } else {\n\tScrollToPos $w [expr {$Priv(initPos) + $delta}]\n    }\n}\n\n# ::tk::ScrollEndDrag --\n# This procedure is called to end an interactive drag of the slider.\n# It scrolls the window if we're in jump mode, otherwise it does nothing.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tThe mouse position at the end of the drag operation.\n\nproc ::tk::ScrollEndDrag {w x y} {\n    variable ::tk::Priv\n\n    if {$Priv(initPos) eq \"\"} {\n\treturn\n    }\n    if {[$w cget -jump]} {\n\tset delta [$w delta [expr {$x - $Priv(pressX)}] \\\n\t\t[expr {$y - $Priv(pressY)}]]\n\tScrollToPos $w [expr {$Priv(initPos) + $delta}]\n    }\n    set Priv(initPos) \"\"\n}\n\n# ::tk::ScrollbarScrollByPixels --\n# This procedure tells the scrollbar's associated widget to scroll up\n# or down by a given number of pixels.  It only works with scrollbars\n# because it uses the delta command.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# orient -\tWhich kind of scrollbar this applies to: \"h\" for\n#\t\thorizontal, \"v\" for vertical.\n# amount -\tHow many pixels to scroll.\n\nproc ::tk::ScrollbarScrollByPixels {w orient amount} {\n    set cmd [$w cget -command]\n    if {$cmd eq \"\"} {\n\treturn\n    }\n    set xyview [lindex [split $cmd] end]\n    if {$orient eq \"v\"} {\n\tif {$xyview eq \"xview\"} {\n\t    return\n\t}\n    }\n    if {$orient eq \"h\"} {\n\tif {$xyview eq \"yview\"} {\n\t    return\n\t}\n    }\n\n    # The code below works with both the current and old syntax for\n    # the scrollbar get command.\n\n    set info [$w get]\n    if {[llength $info] == 2} {\n\tset first [lindex $info 0]\n    } else {\n\tset first [lindex $info 2]\n    }\n    set pixels [expr {-$amount}]\n    uplevel #0 $cmd moveto [expr $first + [$w delta $pixels $pixels]]\n}\n\n# ::tk::ScrollByUnits --\n# This procedure tells the scrollbar's associated widget to scroll up\n# or down by a given number of units.  It notifies the associated widget\n# in different ways for old and new command syntaxes.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# orient -\tWhich kinds of scrollbars this applies to:  \"h\" for\n#\t\thorizontal, \"v\" for vertical, \"hv\" or \"vh\" for both.\n# amount -\tHow many units to scroll:  typically 1 or -1.\n\nproc ::tk::ScrollByUnits {w orient amount {factor 1.0}} {\n    set cmd [$w cget -command]\n    if {$cmd eq \"\" || ([string first \\\n\t    [string index [$w cget -orient] 0] $orient] < 0)} {\n\treturn\n    }\n\n    if {[string length $orient] == 2 && $factor != 1.0} {\n\t# Count both the <MouseWheel> and <Shift-MouseWheel>\n\t# events, and ignore the non-dominant ones\n\n\tvariable ::tk::Priv\n\tset axis [expr {[string index $orient 0] eq \"h\" ? \"x\" : \"y\"}]\n\tincr Priv(${axis}Events)\n\tif {($Priv(xEvents) + $Priv(yEvents) > 10) &&\n\t\t($axis eq \"x\" && $Priv(xEvents) < $Priv(yEvents) ||\n\t\t $axis eq \"y\" && $Priv(yEvents) < $Priv(xEvents))} {\n\t    return\n\t}\n    }\n\n    set info [$w get]\n    if {[llength $info] == 2} {\n\tuplevel #0 $cmd scroll [expr {$amount/$factor}] units\n    } else {\n\tuplevel #0 $cmd [expr {[lindex $info 2] + [expr {$amount/$factor}]}]\n    }\n}\n\n# ::tk::ScrollByPages --\n# This procedure tells the scrollbar's associated widget to scroll up\n# or down by a given number of screenfuls.  It notifies the associated\n# widget in different ways for old and new command syntaxes.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# orient -\tWhich kinds of scrollbars this applies to:  \"h\" for\n#\t\thorizontal, \"v\" for vertical, \"hv\" for both.\n# amount -\tHow many screens to scroll:  typically 1 or -1.\n\nproc ::tk::ScrollByPages {w orient amount} {\n    set cmd [$w cget -command]\n    if {$cmd eq \"\" || ([string first \\\n\t    [string index [$w cget -orient] 0] $orient] < 0)} {\n\treturn\n    }\n    set info [$w get]\n    if {[llength $info] == 2} {\n\tuplevel #0 $cmd scroll $amount pages\n    } else {\n\tuplevel #0 $cmd [expr {[lindex $info 2] + $amount*([lindex $info 1] - 1)}]\n    }\n}\n\n# ::tk::ScrollToPos --\n# This procedure tells the scrollbar's associated widget to scroll to\n# a particular location, given by a fraction between 0 and 1.  It notifies\n# the associated widget in different ways for old and new command syntaxes.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# pos -\t\tA fraction between 0 and 1 indicating a desired position\n#\t\tin the document.\n\nproc ::tk::ScrollToPos {w pos} {\n    set cmd [$w cget -command]\n    if {$cmd eq \"\"} {\n\treturn\n    }\n    set info [$w get]\n    if {[llength $info] == 2} {\n\tuplevel #0 $cmd moveto $pos\n    } else {\n\tuplevel #0 $cmd [expr {round([lindex $info 0]*$pos)}]\n    }\n}\n\n# ::tk::ScrollTopBottom\n# Scroll to the top or bottom of the document, depending on the mouse\n# position.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tMouse coordinates within the widget.\n\nproc ::tk::ScrollTopBottom {w x y} {\n    variable ::tk::Priv\n    set element [$w identify $x $y]\n    if {[string match *1 $element]} {\n\tScrollToPos $w 0\n    } elseif {[string match *2 $element]} {\n\tScrollToPos $w 1\n    }\n\n    # Set Priv(relief), since it's needed by tk::ScrollButtonUp.\n\n    set Priv(relief) [$w cget -activerelief]\n}\n\n# ::tk::ScrollButton2Down\n# This procedure is invoked when button 2 is pressed over a scrollbar.\n# If the button is over the trough or slider, it sets the scrollbar to\n# the mouse position and starts a slider drag.  Otherwise it just\n# behaves the same as button 1.\n#\n# Arguments:\n# w -\t\tThe scrollbar widget.\n# x, y -\tMouse coordinates within the widget.\n\nproc ::tk::ScrollButton2Down {w x y} {\n    variable ::tk::Priv\n    if {![winfo exists $w]} {\n\treturn\n    }\n    set element [$w identify $x $y]\n    if {[string match {arrow[12]} $element]} {\n\tScrollButtonDown $w $x $y\n\treturn\n    }\n    ScrollToPos $w [$w fraction $x $y]\n    set Priv(relief) [$w cget -activerelief]\n\n    # Need the \"update idletasks\" below so that the widget calls us\n    # back to reset the actual scrollbar position before we start the\n    # slider drag.\n\n    update idletasks\n    if {[winfo exists $w]} {\n\t$w configure -activerelief sunken\n\t$w activate slider\n\tScrollStartDrag $w $x $y\n    }\n}\n"
  },
  {
    "path": "library/spinbox.tcl",
    "content": "# spinbox.tcl --\n#\n# This file defines the default bindings for Tk spinbox widgets and provides\n# procedures that help in implementing those bindings.  The spinbox builds\n# off the entry widget, so it can reuse Entry bindings and procedures.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1999-2000 Jeffrey Hobbs\n# Copyright © 2000 Ajuba Solutions\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# Elements of tk::Priv that are used in this file:\n#\n# afterId -\t\tIf non-null, it means that auto-scanning is underway\n#\t\t\tand it gives the \"after\" id for the next auto-scan\n#\t\t\tcommand to be executed.\n# mouseMoved -\t\tNon-zero means the mouse has moved a significant\n#\t\t\tamount since the button went down (so, for example,\n#\t\t\tstart dragging out a selection).\n# pressX -\t\tX-coordinate at which the mouse button was pressed.\n# selectMode -\t\tThe style of selection currently underway:\n#\t\t\tchar, word, or line.\n# x, y -\t\tLast known mouse coordinates for scanning\n#\t\t\tand auto-scanning.\n# data -\t\tUsed for Cut and Copy\n#-------------------------------------------------------------------------\n\n# Initialize namespace\nnamespace eval ::tk::spinbox {}\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for entries.\n#-------------------------------------------------------------------------\nbind Spinbox <<Cut>> {\n    if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {\n\tclipboard clear -displayof %W\n\tclipboard append -displayof %W $tk::Priv(data)\n\t%W delete sel.first sel.last\n\tunset tk::Priv(data)\n    }\n}\nbind Spinbox <<Copy>> {\n    if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {\n\tclipboard clear -displayof %W\n\tclipboard append -displayof %W $tk::Priv(data)\n\tunset tk::Priv(data)\n    }\n}\nbind Spinbox <<Paste>> {\n    catch {\n\tif {[tk windowingsystem] ne \"x11\"} {\n\t    catch {\n\t\t%W delete sel.first sel.last\n\t    }\n\t}\n\t%W insert insert [::tk::GetSelection %W CLIPBOARD]\n\t::tk::EntrySeeInsert %W\n    }\n}\nbind Spinbox <<Clear>> {\n    %W delete sel.first sel.last\n}\nbind Spinbox <<PasteSelection>> {\n    if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]\n\t|| !$tk::Priv(mouseMoved)} {\n\t::tk::spinbox::Paste %W %x\n    }\n}\n\nbind Spinbox <<TraverseIn>> {\n    %W selection range 0 end\n    %W icursor end\n}\n\n# Standard Motif bindings:\n\nbind Spinbox <Button-1> {\n    ::tk::spinbox::ButtonDown %W %x %y\n}\nbind Spinbox <B1-Motion> {\n    ::tk::spinbox::Motion %W %x %y\n}\nbind Spinbox <Double-Button-1> {\n    ::tk::spinbox::ArrowPress %W %x %y\n    set tk::Priv(selectMode) word\n    ::tk::spinbox::MouseSelect %W %x sel.first\n}\nbind Spinbox <Triple-Button-1> {\n    ::tk::spinbox::ArrowPress %W %x %y\n    set tk::Priv(selectMode) line\n    ::tk::spinbox::MouseSelect %W %x 0\n}\nbind Spinbox <Shift-Button-1> {\n    set tk::Priv(selectMode) char\n    %W selection adjust @%x\n}\nbind Spinbox <Double-Shift-Button-1> {\n    set tk::Priv(selectMode) word\n    ::tk::spinbox::MouseSelect %W %x\n}\nbind Spinbox <Triple-Shift-Button-1> {\n    set tk::Priv(selectMode) line\n    ::tk::spinbox::MouseSelect %W %x\n}\nbind Spinbox <B1-Leave> {\n    set tk::Priv(x) %x\n    ::tk::spinbox::AutoScan %W\n}\nbind Spinbox <B1-Enter> {\n    tk::CancelRepeat\n}\nbind Spinbox <ButtonRelease-1> {\n    ::tk::spinbox::ButtonUp %W %x %y\n}\nbind Spinbox <Control-Button-1> {\n    %W icursor @%x\n}\n\nbind Spinbox <<PrevLine>> {\n    %W invoke buttonup\n}\nbind Spinbox <<NextLine>> {\n    %W invoke buttondown\n}\n\nbind Spinbox <<PrevChar>> {\n    ::tk::EntrySetCursor %W [tk::EntryPreviousChar %W insert]\n}\nbind Spinbox <<NextChar>> {\n    ::tk::EntrySetCursor %W [tk::EntryNextChar %W insert]\n}\nbind Spinbox <<SelectPrevChar>> {\n    ::tk::EntryKeySelect %W [tk::EntryPreviousChar %W insert]\n    ::tk::EntrySeeInsert %W\n}\nbind Spinbox <<SelectNextChar>> {\n    ::tk::EntryKeySelect %W [tk::EntryNextChar %W insert]\n    ::tk::EntrySeeInsert %W\n}\nbind Spinbox <<PrevWord>> {\n    ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]\n}\nbind Spinbox <<NextWord>> {\n    ::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]\n}\nbind Spinbox <<SelectPrevWord>> {\n    ::tk::EntryKeySelect %W [::tk::EntryPreviousWord %W insert]\n    ::tk::EntrySeeInsert %W\n}\nbind Spinbox <<SelectNextWord>> {\n    ::tk::EntryKeySelect %W [::tk::EntrySelectNextWord %W insert]\n    ::tk::EntrySeeInsert %W\n}\nbind Spinbox <<LineStart>> {\n    ::tk::EntrySetCursor %W 0\n}\nbind Spinbox <<SelectLineStart>> {\n    ::tk::EntryKeySelect %W 0\n    ::tk::EntrySeeInsert %W\n}\nbind Spinbox <<LineEnd>> {\n    ::tk::EntrySetCursor %W end\n}\nbind Spinbox <<SelectLineEnd>> {\n    ::tk::EntryKeySelect %W end\n    ::tk::EntrySeeInsert %W\n}\n\nbind Spinbox <Delete> {\n    if {[%W selection present]} {\n\t%W delete sel.first sel.last\n    } else {\n\t%W delete [tk::startOfCluster [%W get] [%W index insert]] \\\n\t\t[tk::endOfCluster [%W get] [%W index insert]]\n    }\n}\nbind Spinbox <BackSpace> {\n    ::tk::EntryBackspace %W\n}\n\nbind Spinbox <Control-space> {\n    %W selection from insert\n}\nbind Spinbox <Select> {\n    %W selection from insert\n}\nbind Spinbox <Control-Shift-space> {\n    %W selection adjust insert\n}\nbind Spinbox <Shift-Select> {\n    %W selection adjust insert\n}\nbind Spinbox <<SelectAll>> {\n    %W selection range 0 end\n}\nbind Spinbox <<SelectNone>> {\n    %W selection clear\n}\nbind Spinbox <Key> {\n    ::tk::EntryInsert %W %A\n}\n\n# Ignore all Alt, Meta, Control, Command, and Fn keypresses unless explicitly bound.\n# Otherwise, if a widget binding for one of these is defined, the\n# <Key> class binding will also fire and insert the character,\n# which is wrong.  Ditto for Escape, Return, and Tab.\n\nbind Spinbox <Alt-Key> {# nothing}\nbind Spinbox <Meta-Key> {# nothing}\nbind Spinbox <Control-Key> {# nothing}\nbind Spinbox <Escape> {# nothing}\nbind Spinbox <Return> {# nothing}\nbind Spinbox <KP_Enter> {# nothing}\nbind Spinbox <Tab> {# nothing}\nbind Spinbox <Prior> {# nothing}\nbind Spinbox <Next> {# nothing}\nbind Spinbox <Command-Key> {# nothing}\nbind Spinbox <Fn-Key> {# nothing}\n\n# On Windows, paste is done using Shift-Insert.  Shift-Insert already\n# generates the <<Paste>> event, so we don't need to do anything here.\nif {[tk windowingsystem] ne \"win32\"} {\n    bind Spinbox <Insert> {\n\tcatch {::tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}\n    }\n}\n\n# Additional emacs-like bindings:\n\nbind Spinbox <Control-d> {\n    if {!$tk_strictMotif} {\n\t%W delete insert\n    }\n}\nbind Spinbox <Control-h> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryBackspace %W\n    }\n}\nbind Spinbox <Control-k> {\n    if {!$tk_strictMotif} {\n\t%W delete insert end\n    }\n}\nbind Spinbox <Control-t> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryTranspose %W\n    }\n}\nbind Spinbox <Meta-b> {\n    if {!$tk_strictMotif} {\n\t::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]\n    }\n}\nbind Spinbox <Meta-d> {\n    if {!$tk_strictMotif} {\n\t%W delete insert [::tk::EntryNextWord %W insert]\n    }\n}\nbind Spinbox <Meta-f> {\n    if {!$tk_strictMotif} {\n\t::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]\n    }\n}\nbind Spinbox <Meta-BackSpace> {\n    if {!$tk_strictMotif} {\n\t%W delete [::tk::EntryPreviousWord %W insert] insert\n    }\n}\nbind Spinbox <Meta-Delete> {\n    if {!$tk_strictMotif} {\n\t%W delete [::tk::EntryPreviousWord %W insert] insert\n    }\n}\n\n# A few additional bindings of my own.\n\nbind Spinbox <Button-2> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryScanMark %W %x\n    }\n}\nbind Spinbox <B2-Motion> {\n    if {!$tk_strictMotif} {\n\t::tk::EntryScanDrag %W %x\n    }\n}\n\n# ::tk::spinbox::Invoke --\n# Invoke an element of the spinbox\n#\n# Arguments:\n# w -\t\tThe spinbox window.\n# elem -\tElement to invoke\n\nproc ::tk::spinbox::Invoke {w elem} {\n    variable ::tk::Priv\n\n    if {![winfo exists $w]} {\n      return\n    }\n\n    if {![info exists Priv(outsideElement)]} {\n\t$w invoke $elem\n\tincr Priv(repeated)\n    }\n    set delay [$w cget -repeatinterval]\n    if {$delay > 0} {\n\tset Priv(afterId) [after $delay \\\n\t\t[list ::tk::spinbox::Invoke $w $elem]]\n    }\n}\n\n# ::tk::spinbox::ClosestGap --\n# Given x and y coordinates, this procedure finds the closest boundary\n# between characters to the given coordinates and returns the index\n# of the character just after the boundary.\n#\n# Arguments:\n# w -\t\tThe spinbox window.\n# x -\t\tX-coordinate within the window.\n\nproc ::tk::spinbox::ClosestGap {w x} {\n    set pos [$w index @$x]\n    set bbox [$w bbox $pos]\n    if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {\n\treturn $pos\n    }\n    incr pos\n}\n\n# ::tk::spinbox::ArrowPress --\n# This procedure is invoked to handle button-1 presses in buttonup\n# or buttondown elements of spinbox widgets.\n#\n# Arguments:\n# w -\t\tThe spinbox window in which the button was pressed.\n# x -\t\tThe x-coordinate of the button press.\n# y -\t\tThe y-coordinate of the button press.\n\nproc ::tk::spinbox::ArrowPress {w x y} {\n    variable ::tk::Priv\n\n    if {[$w cget -state] ne \"disabled\" && \\\n\t    [string match \"button*\" $Priv(element)]} {\n\t$w selection element $Priv(element)\n\tset Priv(repeated) 0\n\tset Priv(relief) [$w cget -$Priv(element)relief]\n\tcatch {after cancel $Priv(afterId)}\n\tset delay [$w cget -repeatdelay]\n\tif {$delay > 0} {\n\t    set Priv(afterId) [after $delay \\\n\t\t    [list ::tk::spinbox::Invoke $w $Priv(element)]]\n\t}\n\tif {[info exists Priv(outsideElement)]} {\n\t    unset Priv(outsideElement)\n\t}\n    }\n}\n\n# ::tk::spinbox::ButtonDown --\n# This procedure is invoked to handle button-1 presses in spinbox\n# widgets.  It moves the insertion cursor, sets the selection anchor,\n# and claims the input focus.\n#\n# Arguments:\n# w -\t\tThe spinbox window in which the button was pressed.\n# x -\t\tThe x-coordinate of the button press.\n# y -\t\tThe y-coordinate of the button press.\n\nproc ::tk::spinbox::ButtonDown {w x y} {\n    variable ::tk::Priv\n\n    # Get the element that was clicked in.  If we are not directly over\n    # the spinbox, default to entry.  This is necessary for spinbox grabs.\n    #\n    set Priv(element) [$w identify $x $y]\n    if {$Priv(element) eq \"\"} {\n\tset Priv(element) \"entry\"\n    }\n\n    switch -exact $Priv(element) {\n\t\"buttonup\" - \"buttondown\" {\n\t    ::tk::spinbox::ArrowPress $w $x $y\n\t}\n\t\"entry\" {\n\t    set Priv(selectMode) char\n\t    set Priv(mouseMoved) 0\n\t    set Priv(pressX) $x\n\t    $w icursor [::tk::spinbox::ClosestGap $w $x]\n\t    $w selection from insert\n\t    if {\"disabled\" ne [$w cget -state]} {focus $w}\n\t    $w selection clear\n\t}\n\tdefault {\n\t    return -code error -errorcode {TK SPINBOX UNKNOWN_ELEMENT} \\\n\t\t\"unknown spinbox element \\\"$Priv(element)\\\"\"\n\t}\n    }\n}\n\n# ::tk::spinbox::ButtonUp --\n# This procedure is invoked to handle button-1 releases in spinbox\n# widgets.\n#\n# Arguments:\n# w -\t\tThe spinbox window in which the button was pressed.\n# x -\t\tThe x-coordinate of the button press.\n# y -\t\tThe y-coordinate of the button press.\n\nproc ::tk::spinbox::ButtonUp {w x y} {\n    variable ::tk::Priv\n\n    ::tk::CancelRepeat\n\n    # Priv(relief) may not exist if the ButtonUp is not paired with\n    # a preceding ButtonDown\n    #\n    if {[info exists Priv(element)] && [info exists Priv(relief)] && \\\n\t    [string match \"button*\" $Priv(element)]} {\n\tif {[info exists Priv(repeated)] && !$Priv(repeated)} {\n\t    $w invoke $Priv(element)\n\t}\n\n\t# If the value of the -command option is a nonempty string then\n\t# the \"$w invoke $Priv(element)\" line above triggers an invocation\n\t# of that command, which in turn, as a side effect, might set\n\t# Priv(element) to \"entry\" (see bug [fe5549bad8]).  Guard against\n\t# such cases by checking the value of Priv(element) again.\n\t#\n\tif {[string match \"button*\" $Priv(element)]} {\n\t    $w configure -$Priv(element)relief $Priv(relief)\n\t    $w selection element none\n\t}\n    }\n}\n\n# ::tk::spinbox::MouseSelect --\n# This procedure is invoked when dragging out a selection with\n# the mouse.  Depending on the selection mode (character, word,\n# line) it selects in different-sized units.  This procedure\n# ignores mouse motions initially until the mouse has moved from\n# one character to another or until there have been multiple clicks.\n#\n# Arguments:\n# w -\t\tThe spinbox window in which the button was pressed.\n# x -\t\tThe x-coordinate of the mouse.\n# cursor -\toptional place to set cursor.\n\nproc ::tk::spinbox::MouseSelect {w x {cursor {}}} {\n    variable ::tk::Priv\n\n    if {$Priv(element) ne \"entry\"} {\n\t# The ButtonUp command triggered by ButtonRelease-1 handles\n\t# invoking one of the spinbuttons.\n\treturn\n    }\n    set cur [::tk::spinbox::ClosestGap $w $x]\n    set anchor [$w index anchor]\n    if {($cur ne $anchor) || (abs($Priv(pressX) - $x) >= 3)} {\n\tset Priv(mouseMoved) 1\n    }\n    switch $Priv(selectMode) {\n\tchar {\n\t    if {$Priv(mouseMoved)} {\n\t\tif {$cur < $anchor} {\n\t\t    $w selection range $cur $anchor\n\t\t} elseif {$cur > $anchor} {\n\t\t    $w selection range $anchor $cur\n\t\t} else {\n\t\t    $w selection clear\n\t\t}\n\t    }\n\t}\n\tword {\n\t    if {$cur < [$w index anchor]} {\n\t\tset before [tk::wordBreakBefore [$w get] $cur]\n\t\tset after [tk::wordBreakAfter [$w get] $anchor-1]\n\t    } else {\n\t\tset before [tk::wordBreakBefore [$w get] $anchor]\n\t\tset after [tk::wordBreakAfter [$w get] $cur-1]\n\t    }\n\t    if {$before < 0} {\n\t\tset before 0\n\t    }\n\t    if {$after < 0} {\n\t\tset after end\n\t    }\n\t    $w selection range $before $after\n\t}\n\tline {\n\t    $w selection range 0 end\n\t}\n    }\n    if {$cursor ne {} && $cursor ne \"ignore\"} {\n\tcatch {$w icursor $cursor}\n    }\n    update idletasks\n}\n\n# ::tk::spinbox::Paste --\n# This procedure sets the insertion cursor to the current mouse position,\n# pastes the selection there, and sets the focus to the window.\n#\n# Arguments:\n# w -\t\tThe spinbox window.\n# x -\t\tX position of the mouse.\n\nproc ::tk::spinbox::Paste {w x} {\n    $w icursor [::tk::spinbox::ClosestGap $w $x]\n    catch {$w insert insert [::tk::GetSelection $w PRIMARY]}\n    if {\"disabled\" eq [$w cget -state]} {\n\tfocus $w\n    }\n}\n\n# ::tk::spinbox::Motion --\n# This procedure is invoked when the mouse moves in a spinbox window\n# with button 1 down.\n#\n# Arguments:\n# w -\t\tThe spinbox window.\n# x -\t\tThe x-coordinate of the mouse.\n# y -\t\tThe y-coordinate of the mouse.\n\nproc ::tk::spinbox::Motion {w x y} {\n    variable ::tk::Priv\n\n    if {![info exists Priv(element)]} {\n\tset Priv(element) [$w identify $x $y]\n    }\n\n    set Priv(x) $x\n    if {\"entry\" eq $Priv(element)} {\n\t::tk::spinbox::MouseSelect $w $x ignore\n    } elseif {[$w identify $x $y] ne $Priv(element)} {\n\tif {![info exists Priv(outsideElement)]} {\n\t    # We've wandered out of the spin button\n\t    # setting outside element will cause ::tk::spinbox::Invoke to\n\t    # loop without doing anything\n\t    set Priv(outsideElement) \"\"\n\t    $w selection element none\n\t}\n    } elseif {[info exists Priv(outsideElement)]} {\n\tunset Priv(outsideElement)\n\t$w selection element $Priv(element)\n    }\n}\n\n# ::tk::spinbox::AutoScan --\n# This procedure is invoked when the mouse leaves an spinbox window\n# with button 1 down.  It scrolls the window left or right,\n# depending on where the mouse is, and reschedules itself as an\n# \"after\" command so that the window continues to scroll until the\n# mouse moves back into the window or the mouse button is released.\n#\n# Arguments:\n# w -\t\tThe spinbox window.\n\nproc ::tk::spinbox::AutoScan {w} {\n    variable ::tk::Priv\n\n    set x $Priv(x)\n    if {$x >= [winfo width $w]} {\n\t$w xview scroll 2 units\n\t::tk::spinbox::MouseSelect $w $x ignore\n    } elseif {$x < 0} {\n\t$w xview scroll -2 units\n\t::tk::spinbox::MouseSelect $w $x ignore\n    }\n    set Priv(afterId) [after 50 [list ::tk::spinbox::AutoScan $w]]\n}\n\n# ::tk::spinbox::GetSelection --\n#\n# Returns the selected text of the spinbox.  Differs from entry in that\n# a spinbox has no -show option to obscure contents.\n#\n# Arguments:\n# w -         The spinbox window from which the text to get\n\nproc ::tk::spinbox::GetSelection {w} {\n    return [string range [$w get] [$w index sel.first] \\\n\t    [$w index sel.last]-1]\n}\n"
  },
  {
    "path": "library/systray.tcl",
    "content": "# systray.tcl --\n\n# This file defines the 'tk systray' command for icon display and manipulation\n# in the system tray on X11, Windows, and macOS, and the 'tk sysnotify' command\n# for system alerts on each platform. It implements an abstraction layer that\n# presents a consistent API across the three platforms.\n\n# Copyright © 2020 Kevin Walzer\n# Copyright © 2020 Eric Boudaillier\n# Copyright © 2020 Francois Vogel\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n# Pure-Tcl system tooltip window for use with system tray icon if native\n# implementation not available.\n\nnamespace eval ::tk::systray {\n    variable _created 0\n    variable _options {-image \"\" -text \"\" -button1 \"\" -button3 \"\"}\n    variable _current {}\n    variable _ico\n\n    proc _balloon {w help} {\n\tbind $w <Any-Enter> \"after 100 [list [namespace current]::_balloon_show %W [list $help] cursor]\"\n\tbind $w <Any-Leave> \"destroy %W._balloon\"\n    }\n\n    proc _balloon_show {w msg i} {\n\tif {![winfo exists $w]} { return }\n\n\t# Use string match to allow that the help will be shown when\n\t# the pointer is in any child of the desired widget\n\tif {([winfo class $w] ne \"Menu\") && ![string match $w* [eval [list winfo containing] \\\n\t\t\t\t\t\t\t\t    [winfo pointerxy $w]]]} {\n\t    return\n\t}\n\n\tset top $w._balloon\n\t::destroy $top\n\ttoplevel $top -bg black -bd 1\n\twm overrideredirect $top 1\n\twm state $top withdrawn\n\tif {[tk windowingsystem] eq \"aqua\"}  {\n\t    ::tk::unsupported::MacWindowStyle style $top help none\n\t}\n\tpack [message $top._txt -aspect 10000 -text $msg]\n\n\tupdate idletasks\n\tset screenw [winfo screenwidth $w]\n\tset screenh [winfo screenheight $w]\n\tset reqw [winfo reqwidth $top]\n\tset reqh [winfo reqheight $top]\n\t# When adjusting for being on the screen boundary, check that we are\n\t# near the \"edge\" already, as Tk handles multiple monitors oddly\n\tif {$i eq \"cursor\"} {\n\t    set y [expr {[winfo pointery $w]+20}]\n\t    if {($y < $screenh) && ($y+$reqh) > $screenh} {\n\t\tset y [expr {[winfo pointery $w]-$reqh-5}]\n\t    }\n\t} elseif {$i ne \"\"} {\n\t    set y [expr {[winfo rooty $w]+[winfo vrooty $w]+[$w yposition $i]+25}]\n\t    if {($y < $screenh) && ($y+$reqh) > $screenh} {\n\t\t# show above if we would be offscreen\n\t\tset y [expr {[winfo rooty $w]+[$w yposition $i]-$reqh-5}]\n\t    }\n\t} else {\n\t    set y [expr {[winfo rooty $w]+[winfo vrooty $w]+[winfo height $w]+5}]\n\t    if {($y < $screenh) && ($y+$reqh) > $screenh} {\n\t\t# show above if we would be offscreen\n\t\tset y [expr {[winfo rooty $w]-$reqh-5}]\n\t    }\n\t}\n\tif {$i eq \"cursor\"} {\n\t    set x [winfo pointerx $w]\n\t} else {\n\t    set x [expr {[winfo rootx $w]+[winfo vrootx $w]+ ([winfo width $w]-$reqw)/2}]\n\t}\n\t# only readjust when we would appear right on the screen edge\n\tif {$x<0 && ($x+$reqw)>0} {\n\t    set x 0\n\t} elseif {($x < $screenw) && ($x+$reqw) > $screenw} {\n\t    set x [expr {$screenw-$reqw}]\n\t}\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    set focus [focus]\n\t}\n\n\twm geometry $top +$x+$y\n\twm deiconify $top\n\traise $top\n\n\tif {[tk windowingsystem] eq \"aqua\" && $focus ne \"\"} {\n\t    # Aqua's help window steals focus on display\n\t    after idle [list focus -force $focus]\n\t}\n    }\n\n    proc _win_callback {msg} {\n\tvariable _current\n\t# The API at the Tk level does not feature bindings to double  clicks. Whatever\n\t# the speed the user clicks with, he expects the single click binding to fire.\n\t# Therefore we need to bind to both WM_*BUTTONDOWN and to WM_*BUTTONDBLCLK.\n\tswitch -exact -- $msg {\n\t    WM_LBUTTONDOWN - WM_LBUTTONDBLCLK {\n\t\tuplevel #0 [dict get $_current -button1]\n\t    }\n\t    WM_RBUTTONDOWN - WM_RBUTTONDBLCLK {\n\t\tuplevel #0 [dict get $_current -button3]\n\t    }\n\t}\n    }\n\n    namespace export create configure destroy exists\n    namespace ensemble create\n}\n\n\n# Pure-Tcl system notification window for use if native implementation not available.\n# This is supposed to happen only on X11 when libnotify is not present.\nnamespace eval ::tk::sysnotify:: {\n    # These defaults mimic the default behaviour of gnome and xfce notifications.\n    # These are hardcoded defaults.\n    variable defaults {\n\tpadX            3\n\tpadY            3\n\tbackground      gray15\n\tforeground      white\n\tdelay           10000\n\talpha           0.85\n    }\n    # These options are meant to be \"public\". The user could tinker with\n    # these values to adjust the system notification appearance/behaviour.\n    option add *Sysnotify.padX       [dict get $defaults padX]\n    option add *Sysnotify.padY       [dict get $defaults padY]\n    option add *Sysnotify.background [dict get $defaults background]\n    option add *Sysnotify.foreground [dict get $defaults foreground]\n    option add *Sysnotify.delay      [dict get $defaults delay]\n    option add *Sysnotify.alpha      [dict get $defaults alpha]\n\n    proc _notifywindow {title msg} {\n\tvariable defaults\n\n\t# cleanup any previous notify window and create a new one\n\tset w ._notify\n\t_notifyDestroy $w\n\ttoplevel $w -class Sysnotify\n\n\t# read the option database to check out whether the user has set\n\t# some options; fall back to our hardcoded defaults otherwise\n\tdict for {option value} [dict remove $defaults alpha] {\n\t    set $option [option get $w $option \"\"]\n\t    if {[set $option] eq \"\"} {\n\t\tset $option $value\n\t    }\n\t}\n\n\tset xpos [tk::ScaleNum 16]\n\tset ypos [tk::ScaleNum 48]\n\t# position from the \"ne\" corner\n\twm geometry $w -$xpos+$ypos\n\twm overrideredirect $w true\n\n\t# internal options\n\toption add *Sysnotify.Label.anchor     w\n\toption add *Sysnotify.Label.justify    left\n\toption add *Sysnotify.Label.wrapLength [expr {[winfo screenwidth .] / 4}]\n\tforeach option {padX padY foreground background} {\n\t    option add *Sysnotify.Label.$option [set $option]\n\t}\n\tset icon ::tk::icons::information\n\tset width [expr {[image width $icon] + 2 * $padX}]\n\tset height [expr {[image height $icon] + 2 * $padY}]\n\tlabel $w.icon -image $icon -width $width -height $height -anchor c\n\tlabel $w.title -text $title -font TkHeadingFont\n\tlabel $w.message -text [_filterMarkup $msg] -font TkTooltipFont\n\n\tgrid $w.icon $w.title -sticky news\n\tgrid ^       $w.message -sticky news\n\n\tbind Sysnotify <Map> [namespace code {\n\t    # set the wm attribute here; it is ignored if set\n\t    # before the window is mapped\n\t    wm attributes %W -alpha 0.0\n\t    if {[wm attributes %W -alpha] == 0.0} {\n\t\t_fadeIn %W\n\t    }\n\t}]\n\tbind Sysnotify <Enter> [namespace code {_onEnter %W}]\n\tbind Sysnotify <Leave> [namespace code {_onLeave %W}]\n\tbind $w <Button-1> [namespace code [list _notifyDestroy $w]]\n\tafter $delay [namespace code [list _fadeOut $w]]\n\treturn\n    }\n\n    # Fade the window into view.\n    proc _fadeIn {w} {\n\tvariable defaults\n\tif {![winfo exists $w]} {return}\n\tif {[set alpha  [option get $w alpha \"\"]] eq \"\"} {\n\t    set alpha [dict get $defaults alpha]\n\t}\n\traise $w\n\tset before [wm attributes $w -alpha]\n\tset new    [expr { min($alpha, $before + 0.10) }]\n\twm attributes $w -alpha $new\n\tset after  [wm attributes $w -alpha]\n\tif {($before == 1.0) || ($before == $after)} {\n\t    # not supported or we're done\n\t    return\n\t}\n\tafter 40 [namespace code [list _fadeIn $w]]\n    }\n\n    # Fade out and destroy window.\n    proc _fadeOut {w} {\n\tif {![winfo exists $w]} {return}\n\tset before [wm attributes $w -alpha]\n\tset new    [expr { $before - 0.02 }]\n\twm attributes $w -alpha $new\n\tset after  [wm attributes $w -alpha]\n\tif {($after == 1.0) || ($before == $after)} {\n\t    _notifyDestroy $w\n\t    return\n\t}\n\tafter 40 [namespace code [list _fadeOut $w]]\n    }\n\n    proc _notifyDestroy {w} {\n\t# cancel any pending fade in or fade out\n\t_cancelFading $w\n\tdestroy $w\n    }\n\n    proc _onEnter {w} {\n\twm attributes $w -alpha 1.0\n\t_cancelFading $w\n    }\n\n    proc _onLeave {w} {\n\tvariable defaults\n\tif {[set alpha [option get $w alpha \"\"]] eq \"\"} {\n\t    set alpha [dict get $defaults alpha]\n\t}\n\tif {[set delay [option get $w delay \"\"]] eq \"\"} {\n\t    set delay [dict get $defaults delay]\n\t}\n\twm attributes $w -alpha $alpha\n\tafter $delay [namespace code [list _fadeOut $w]]\n    }\n\n    proc _cancelFading {w} {\n\tafter cancel [namespace code [list _fadeOut $w]]\n\tafter cancel [namespace code [list _fadeIn $w]]\n    }\n\n    # The Desktop Notifications Specification allow for some markup\n    # in the message to display. It also specifies\n    # \"Notification servers that do not support these tags should\n    # filter them out\"\n    # See https://specifications.freedesktop.org/notification-spec/latest/ar01s04.html\n    # We don't event try to render those properly\n    proc _filterMarkup {txt} {\n\t# remove fixed tags\n\tset maplist {<b> \"\" </b> \"\" <i> \"\" </i> \"\" <u> \"\" </u> \"\" </a> \"\"}\n\tset txt [string map $maplist $txt]\n\t# remove <img> tags leaving (possible) alt text\n\tset txt [regsub -- {<img *src=\"[^\"]*\" *(alt=\"([^\"]*)\")? */?>} $txt {\\2}]\n\t# remove <a href=\"\"> variable tag\n\tset txt [regsub -- {<a[^>]*>} $txt {}]\n\treturn $txt\n    }\n}\n\n\n# tk systray --\n# This procedure creates an icon display in the platform-specific system tray.\n#\n# Subcommands:\n#\n#     create - create systray icon.\n#         Arguments:\n#             -image - Tk image to display.\n#             -text - string to display in tooltip over image.\n#             -button1 - Tcl proc to invoke on <Button-1> event.\n#             -button3 - Tcl proc to invoke on <Button-3> event.\n#\n#     configure - change one of the systray properties.\n#         Arguments (Any or all can be called):\n#             -image - Tk image to update.\n#             -text - string to update.\n#             -button1 - Tcl proc to change for <Button-1> event.\n#             -button3  - Tcl proc to change for <Button-3> event.\n#\n#     destroy - destroy systray icon.\n#         Arguments:\n#             none.\nproc ::tk::systray::create {args} {\n    variable _created\n    variable _options\n    variable _current\n    variable _ico\n\n    if {$_created} {\n\treturn -code error -errorcode {TK SYSTRAY CREATE} \"only one system tray icon supported per interpeter\"\n    }\n    _check_options $args 0\n    if {![dict exists $args -image]} {\n\treturn -code error -errorcode {TK SYSTRAY CREATE} \"missing required option \\\"-image\\\"\"\n    }\n    set values [dict merge $_options $args]\n    try {\n\tswitch -- [tk windowingsystem] {\n\t    \"win32\" {\n\t\tset _ico [_systray add -image [dict get $values -image] \\\n\t\t\t-text [dict get $values -text] \\\n\t\t\t-callback [list ::tk::systray::_win_callback %m]]\n\t    }\n\t    \"x11\" {\n\t\t_systray ._tray -image [dict get $values -image] -visible true\n\t\t_balloon ._tray [dict get $values -text]\n\t\tbind ._tray <Button-1> [dict get $values -button1]\n\t\tbind ._tray <Button-3> [dict get $values -button3]\n\t    }\n\t    \"aqua\" {\n\t\t_systray create [dict get $values -image] [dict get $values -text] \\\n\t\t\t[dict get $values -button1] [dict get $values -button3]\n\t    }\n\t}\n    } on ok {} {\n\tset _current $values\n\tset _created 1\n\treturn\n    } on error {msg opts} {\n\treturn -code error -errorcode [dict get $opts -errorcode] $msg\n    }\n}\n\n# Modify the systray icon.\nproc ::tk::systray::configure {args} {\n    variable _created\n    variable _options\n    variable _current\n    variable _ico\n\n    if {!$_created} {\n\treturn -code error -errorcode {TK SYSTRAY CREATE} \"systray not created\"\n    }\n    _check_options $args 1\n    if {[llength $args] == 0} {\n\treturn $_current\n    } elseif {[llength $args] == 1} {\n\treturn [dict get $_current [lindex $args 0]]\n    }\n    set values [dict merge $_current $args]\n    try {\n\tswitch -- [tk windowingsystem] {\n\t    \"win32\" {\n\t\tif {[dict exists $args -image]} {\n\t\t    _systray modify $_ico -image [dict get $args -image]\n\t\t}\n\t\tif {[dict exists $args -text]} {\n\t\t    _systray modify $_ico -text [dict get $args -text]\n\t\t}\n\t    }\n\t    \"x11\" {\n\t\tif {[dict exists $args -image]} {\n\t\t    ._tray configure -image [dict get $args -image]\n\t\t}\n\t\tif {[dict exists $args -text]} {\n\t\t    _balloon ._tray [dict get $args -text]\n\t\t}\n\t\tif {[dict exists $args -button1]} {\n\t\t    bind ._tray <Button-1> [dict get $args -button1]\n\t\t}\n\t\tif {[dict exists $args -button3]} {\n\t\t    bind ._tray <Button-3> [dict get $args -button3]\n\t\t}\n\t    }\n\t    \"aqua\" {\n\t\tforeach {key opt} {image -image text \\\n\t\t\t-text b1_callback -button1 b3_callback -button3} {\n\t\t    if {[dict exists $args $opt]} {\n\t\t\t_systray modify $key [dict get $args $opt]\n\t\t    }\n\t\t}\n\t    }\n\t}\n    } on ok {} {\n\tset _current $values\n\treturn\n    } on error {msg opts} {\n\treturn -code error -errorcode [dict get $opts -errorcode] $msg\n    }\n}\n\n# Remove the systray icon.\nproc ::tk::systray::destroy {} {\n    variable _created\n    variable _current\n    variable _ico\n\n    if {!$_created} {\n\treturn -code error -errorcode {TK SYSTRAY DESTROY} \"systray not created\"\n    }\n    switch -- [tk windowingsystem] {\n\t\"win32\" {\n\t    _systray delete $_ico\n\t    set _ico \"\"\n\t}\n\t\"x11\" {\n\t    ::destroy ._tray\n\t}\n\t\"aqua\" {\n\t    _systray destroy\n\t}\n    }\n    set _created 0\n    set _current {}\n    return\n}\n\n# Check systray icon existence.\nproc tk::systray::exists {} {\n    variable _created\n    return $_created\n}\n\n# Check systray options\nproc ::tk::systray::_check_options {argsList singleOk} {\n    variable _options\n\n    set len [llength $argsList]\n    while {[llength $argsList] > 0} {\n\tset opt [lindex $argsList 0]\n\tif {![dict exists $_options $opt]} {\n\t    tailcall return -code error -errorcode {TK SYSTRAY OPTION} \\\n\t\t\"unknown option \\\"$opt\\\": must be -image, -text, -button1 or -button3\"\n\t}\n\tif {[llength $argsList] == 1 && !($len == 1 && $singleOk)} {\n\t    tailcall return -code error -errorcode {TK SYSTRAY OPTION} \\\n\t\t\"missing value for option \\\"$opt\\\"\"\n\t}\n\tset argsList [lrange $argsList 2 end]\n    }\n}\n\n# tk sysnotify --\n# This procedure implements a platform-specific system notification alert.\n#\n#   Arguments:\n#       title - main text of alert.\n#       message - body text of alert.\n\nproc ::tk::sysnotify::sysnotify {title message} {\n\n    switch -- [tk windowingsystem] {\n\t\"win32\" {\n\t    if {!$::tk::systray::_created} {\n\t\terror \"must create a system tray icon with the \\\"tk systray\\\" command first\"\n\t    }\n\t    _sysnotify notify $::tk::systray::_ico $title $message\n\t}\n\t\"x11\" {\n\t    if {[info commands ::tk::sysnotify::_sysnotify] eq \"\"} {\n\t\t_notifywindow $title $message\n\t    } else {\n\t\t_sysnotify $title $message\n\t    }\n\t}\n\t\"aqua\" {\n\t    _sysnotify $title $message\n\t}\n    }\n    return\n}\n\n#Add these commands to the tk command ensemble: tk systray, tk sysnotify\n#Thanks to Christian Gollwitzer for the guidance here\nnamespace ensemble configure tk -map \\\n    [dict merge [namespace ensemble configure tk -map] \\\n\t{systray ::tk::systray sysnotify ::tk::sysnotify::sysnotify}]\n\n"
  },
  {
    "path": "library/tclIndex",
    "content": "# Tcl autoload index file, version 2.0\n# This file is generated by the \"auto_mkindex\" command\n# and sourced to set up indexing information for one or\n# more commands.  Typically each line is a command that\n# sets an element in the auto_index array, where the\n# element name is the name of a command and the value is\n# a script that loads the command.\n\nset auto_index(::tk::dialog::error::Return) [list source [file join $dir bgerror.tcl]]\nset auto_index(::tk::dialog::error::Details) [list source [file join $dir bgerror.tcl]]\nset auto_index(::tk::dialog::error::SaveToLog) [list source [file join $dir bgerror.tcl]]\nset auto_index(::tk::dialog::error::Destroy) [list source [file join $dir bgerror.tcl]]\nset auto_index(::tk::dialog::error::bgerror) [list source [file join $dir bgerror.tcl]]\nset auto_index(bgerror) [list source [file join $dir bgerror.tcl]]\nset auto_index(::tk::ButtonInvoke) [list source [file join $dir button.tcl]]\nset auto_index(::tk::ButtonAutoInvoke) [list source [file join $dir button.tcl]]\nset auto_index(::tk::CheckRadioInvoke) [list source [file join $dir button.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::Config) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::OkCmd) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::DblClick) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::ListBrowse) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::file::chooseDir::Done) [list source [file join $dir choosedir.tcl]]\nset auto_index(::tk::dialog::color::) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::InitValues) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::Config) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::BuildDialog) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::SetRGBValue) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::XToRgb) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::RgbToX) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::DrawColorScale) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::CreateSelector) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::RedrawFinalColor) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::RedrawColorBars) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::StartMove) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::MoveSelector) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::ReleaseMouse) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::ResizeColorBars) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::HandleSelEntry) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::HandleRGBEntry) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::EnterColorBar) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::LeaveColorBar) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::OkCmd) [list source [file join $dir clrpick.tcl]]\nset auto_index(::tk::dialog::color::CancelCmd) [list source [file join $dir clrpick.tcl]]\nset auto_index(tclParseConfigSpec) [list source [file join $dir comdlg.tcl]]\nset auto_index(tclListValidFlags) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_Create) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_BindIn) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_BindOut) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_Destroy) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_In) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FocusGroup_Out) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::FDGetFileTypes) [list source [file join $dir comdlg.tcl]]\nset auto_index(::tk::ConsoleInit) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleSource) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleInvoke) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleHistory) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsolePrompt) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleBind) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleInsert) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleOutput) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleExit) [list source [file join $dir console.tcl]]\nset auto_index(::tk::ConsoleAbout) [list source [file join $dir console.tcl]]\nset auto_index(tk_dialog) [list source [file join $dir dialog.tcl]]\nset auto_index(::tk::EntryClosestGap) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryButton1) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryMouseSelect) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryPaste) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryAutoScan) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryKeySelect) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryInsert) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryBackspace) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntrySeeInsert) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntrySetCursor) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryTranspose) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryPreviousWord) [list source [file join $dir entry.tcl]]\nset auto_index(::tk::EntryGetSelection) [list source [file join $dir entry.tcl]]\nset auto_index(tk_focusNext) [list source [file join $dir focus.tcl]]\nset auto_index(tk_focusPrev) [list source [file join $dir focus.tcl]]\nset auto_index(::tk::FocusOK) [list source [file join $dir focus.tcl]]\nset auto_index(tk_focusFollowsMouse) [list source [file join $dir focus.tcl]]\nset auto_index(::tk::fontchooser) [list source [file join $dir fontchooser.tcl]]\nset auto_index(::tk::IconList) [list source [file join $dir iconlist.tcl]]\nset auto_index(::tk::ListboxBeginSelect) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxMotion) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxBeginExtend) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxBeginToggle) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxAutoScan) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxUpDown) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxExtendUpDown) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxDataExtend) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxCancel) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::ListboxSelectAll) [list source [file join $dir listbox.tcl]]\nset auto_index(::tk::Megawidget) [list source [file join $dir megawidget.tcl]]\nset auto_index(::tk::MbEnter) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MbLeave) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MbPost) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuUnpost) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MbMotion) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MbButtonUp) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuMotion) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuButtonDown) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuLeave) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuInvoke) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuEscape) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuUpArrow) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuDownArrow) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuLeftArrow) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuRightArrow) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuNextMenu) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuNextEntry) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuFind) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::TraverseToMenu) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::FirstMenu) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::TraverseWithinMenu) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuFirstEntry) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::MenuFindName) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::PostOverPoint) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::SaveGrabInfo) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::RestoreOldGrab) [list source [file join $dir menu.tcl]]\nset auto_index(tk_menuSetFocus) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::GenerateMenuSelect) [list source [file join $dir menu.tcl]]\nset auto_index(tk_popup) [list source [file join $dir menu.tcl]]\nset auto_index(::tk::ensure_psenc_is_loaded) [list source [file join $dir mkpsenc.tcl]]\nset auto_index(::tk::MessageBox) [list source [file join $dir msgbox.tcl]]\nset auto_index(tk_optionMenu) [list source [file join $dir optMenu.tcl]]\nset auto_index(tk_setPalette) [list source [file join $dir palette.tcl]]\nset auto_index(::tk::RecolorTree) [list source [file join $dir palette.tcl]]\nset auto_index(::tk::Darken) [list source [file join $dir palette.tcl]]\nset auto_index(tk_bisque) [list source [file join $dir palette.tcl]]\nset auto_index(::safe::tkInterpInit) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::loadTk) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::TkInit) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::allowTk) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::disallowTk) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::tkDelete) [list source [file join $dir safetk.tcl]]\nset auto_index(::safe::tkTopLevel) [list source [file join $dir safetk.tcl]]\nset auto_index(::tk::ScaleActivate) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleButtonDown) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleDrag) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleEndDrag) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleIncrement) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleControlPress) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScaleButton2Down) [list source [file join $dir scale.tcl]]\nset auto_index(::tk::ScalingPct) [list source [file join $dir scaling.tcl]]\nset auto_index(::tk::ScaleNum) [list source [file join $dir scaling.tcl]]\nset auto_index(::tk::FontScalingFactor) [list source [file join $dir scaling.tcl]]\nset auto_index(::tk::ScanMonitorsFile) [list source [file join $dir scaling.tcl]]\nset auto_index(::tk::ScrollButtonDown) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollButtonUp) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollSelect) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollStartDrag) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollDrag) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollEndDrag) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollByUnits) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollByPages) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollToPos) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollTopBottom) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::ScrollButton2Down) [list source [file join $dir scrlbar.tcl]]\nset auto_index(::tk::spinbox::Invoke) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::ClosestGap) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::ButtonDown) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::ButtonUp) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::MouseSelect) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::Paste) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::Motion) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::AutoScan) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::KeySelect) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::Insert) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::Backspace) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::SeeInsert) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::SetCursor) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::Transpose) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::PreviousWord) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::spinbox::GetSelection) [list source [file join $dir spinbox.tcl]]\nset auto_index(::tk::TearOffMenu) [list source [file join $dir tearoff.tcl]]\nset auto_index(::tk::MenuDup) [list source [file join $dir tearoff.tcl]]\nset auto_index(::tk::TextClosestGap) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextButton1) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextSelectTo) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextKeyExtend) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextPaste) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextAutoScan) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextSetCursor) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextKeySelect) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextResetAnchor) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextInsert) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextUpDownLine) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextPrevPara) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextNextPara) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextScrollPages) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextTranspose) [list source [file join $dir text.tcl]]\nset auto_index(tk_textCopy) [list source [file join $dir text.tcl]]\nset auto_index(tk_textCut) [list source [file join $dir text.tcl]]\nset auto_index(tk_textPaste) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextNextPos) [list source [file join $dir text.tcl]]\nset auto_index(::tk::TextPrevPos) [list source [file join $dir text.tcl]]\nset auto_index(::tk::PlaceWindow) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::SetFocusGrab) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::RestoreFocusGrab) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::ScreenChanged) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::EventMotifBindings) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::CancelRepeat) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::MouseWheel) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::TabToWindow) [list source [file join $dir tk.tcl]]\nset auto_index(::tk::dialog::file::) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::Config) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::Create) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::SetSelectMode) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::UpdateWhenIdle) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::Update) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::SetPathSilently) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::SetPath) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::SetFilter) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::ResolveFile) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::EntFocusIn) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::EntFocusOut) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::ActivateEnt) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::VerifyFileName) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::InvokeBtn) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::UpDirCmd) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::JoinFile) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::OkCmd) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::CancelCmd) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::ListBrowse) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::ListInvoke) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::dialog::file::Done) [list source [file join $dir tkfbox.tcl]]\nset auto_index(::tk::MotifFDialog) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_Create) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_FileTypes) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_SetFilter) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_Config) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_BuildUI) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_SetListMode) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_MakeSList) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_InterpFilter) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_Update) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_LoadFiles) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_BrowseDList) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_ActivateDList) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_BrowseFList) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_ActivateFList) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_ActivateFEnt) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_ActivateSEnt) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_OkCmd) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_FilterCmd) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::MotifFDialog_CancelCmd) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::ListBoxKeyAccel_Set) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::ListBoxKeyAccel_Unset) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::ListBoxKeyAccel_Key) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::ListBoxKeyAccel_Goto) [list source [file join $dir xmfbox.tcl]]\nset auto_index(::tk::ListBoxKeyAccel_Reset) [list source [file join $dir xmfbox.tcl]]\n"
  },
  {
    "path": "library/tearoff.tcl",
    "content": "# tearoff.tcl --\n#\n# This file contains procedures that implement tear-off menus.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# ::tk::TearoffMenu --\n# Given the name of a menu, this procedure creates a torn-off menu\n# that is identical to the given menu (including nested submenus).\n# The new torn-off menu exists as a toplevel window managed by the\n# window manager.  The return value is the name of the new menu.\n# The window is created at the point specified by x and y\n#\n# Arguments:\n# w -\t\t\tThe menu to be torn-off (duplicated).\n# x -\t\t\tx coordinate where window is created\n# y -\t\t\ty coordinate where window is created\n\nproc ::tk::TearOffMenu {w {x 0} {y 0}} {\n    # Find a unique name to use for the torn-off menu.  Find the first\n    # ancestor of w that is a toplevel but not a menu, and use this as\n    # the parent of the new menu.  This guarantees that the torn off\n    # menu will be on the same screen as the original menu.  By making\n    # it a child of the ancestor, rather than a child of the menu, it\n    # can continue to live even if the menu is deleted;  it will go\n    # away when the toplevel goes away.\n\n    if {$x == 0} {\n\tset x [winfo rootx $w]\n    }\n    if {$y == 0} {\n\tset y [winfo rooty $w]\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    # Shift by height of tearoff entry minus height of window titlebar\n\t    catch {incr y [expr {[$w yposition 1] - 16}]}\n\t    # Avoid the native menu bar which sits on top of everything.\n\t    if {$y < 22} {set y 22}\n\t}\n    }\n\n    set parent [winfo parent $w]\n    while {[winfo toplevel $parent] ne $parent \\\n\t    || [winfo class $parent] eq \"Menu\"} {\n\tset parent [winfo parent $parent]\n    }\n    if {$parent eq \".\"} {\n\tset parent \"\"\n    }\n    for {set i 1} 1 {incr i} {\n\tset menu $parent.tearoff$i\n\tif {![winfo exists $menu]} {\n\t    break\n\t}\n    }\n\n    $w clone $menu tearoff\n\n    # Pick a title for the new menu by looking at the parent of the\n    # original: if the parent is a menu, then use the text of the active\n    # entry.  If it's a menubutton then use its text.\n\n    set parent [winfo parent $w]\n    if {[$menu cget -title] ne \"\"} {\n\twm title $menu [$menu cget -title]\n    } else {\n\tswitch -- [winfo class $parent] {\n\t    Menubutton {\n\t\twm title $menu [$parent cget -text]\n\t    }\n\t    Menu {\n\t\twm title $menu [$parent entrycget active -label]\n\t    }\n\t}\n    }\n\n    if {[tk windowingsystem] eq \"win32\"} {\n\t# [Bug 3181181]: Find the toplevel window for the menu\n\tset parent [winfo toplevel $parent]\n\twhile {[winfo class $parent] eq \"Menu\"} {\n\t    set parent [winfo toplevel [winfo parent $parent]]\n\t}\n\twm transient $menu [winfo toplevel $parent]\n\twm attributes $menu -toolwindow 1\n    }\n\n    $menu post $x $y\n\n    if {[winfo exists $menu] == 0} {\n\treturn \"\"\n    }\n\n    # Set tk::Priv(focus) on entry:  otherwise the focus will get lost\n    # after keyboard invocation of a sub-menu (it will stay on the\n    # submenu).\n\n    bind $menu <Enter> {\n\tset tk::Priv(focus) %W\n    }\n\n    # If there is a -tearoffcommand option for the menu, invoke it\n    # now.\n\n    set cmd [$w cget -tearoffcommand]\n    if {$cmd ne \"\"} {\n\tuplevel #0 $cmd [list $w $menu]\n    }\n    return $menu\n}\n\n# ::tk::MenuDup --\n# Given a menu (hierarchy), create a duplicate menu (hierarchy)\n# in a given window.\n#\n# Arguments:\n# src -\t\t\tSource window.  Must be a menu.  It and its\n#\t\t\tmenu descendants will be duplicated at dst.\n# dst -\t\t\tName to use for topmost menu in duplicate\n#\t\t\thierarchy.\n\nproc ::tk::MenuDup {src dst type} {\n    set cmd [list menu $dst -type $type]\n    foreach option [$src configure] {\n\tif {[llength $option] == 2} {\n\t    continue\n\t}\n\tif {[lindex $option 0] eq \"-type\"} {\n\t    continue\n\t}\n\tlappend cmd [lindex $option 0] [lindex $option 4]\n    }\n    eval $cmd\n\n    # Copy the meny entries, if any\n\n    set last [$src index last]\n    for {set i [$src cget -tearoff]} {$i <= $last} {incr i} {\n\tset cmd [list $dst add [$src type $i] [$src id $i]]\n\tforeach option [$src entryconfigure $i]  {\n\t    lappend cmd [lindex $option 0] [lindex $option 4]\n\t}\n\teval $cmd\n    }\n\n    # Duplicate the binding tags from the source menu, replacing src with dst\n\n    set tags [bindtags $src]\n    set x [lsearch -exact $tags $src]\n    if {$x >= 0} {lset tags $x $dst}\n    bindtags $dst $tags\n}\n"
  },
  {
    "path": "library/text.tcl",
    "content": "# text.tcl --\n#\n# This file defines the default bindings for Tk text widgets and provides\n# procedures that help in implementing the bindings.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998 Scriptics Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n#-------------------------------------------------------------------------\n# Elements of ::tk::Priv that are used in this file:\n#\n# afterId -\t\tIf non-null, it means that auto-scanning is underway\n#\t\t\tand it gives the \"after\" id for the next auto-scan\n#\t\t\tcommand to be executed.\n# char -\t\tCharacter position on the line;  kept in order\n#\t\t\tto allow moving up or down past short lines while\n#\t\t\tstill remembering the desired position.\n# mouseMoved -\t\tNon-zero means the mouse has moved a significant\n#\t\t\tamount since the button went down (so, for example,\n#\t\t\tstart dragging out a selection).\n# prevPos -\t\tUsed when moving up or down lines via the keyboard.\n#\t\t\tKeeps track of the previous insert position, so\n#\t\t\twe can distinguish a series of ups and downs, all\n#\t\t\tin a row, from a new up or down.\n# selectMode -\t\tThe style of selection currently underway:\n#\t\t\tchar, word, or line.\n# x, y -\t\tLast known mouse coordinates for scanning\n#\t\t\tand auto-scanning.\n#\n#-------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------\n# The code below creates the default class bindings for text widgets.\n#-------------------------------------------------------------------------\n\n\n\n# Standard Motif bindings:\n\nbind Text <Button-1> {\n    tk::TextButton1 %W %x %y\n    %W tag remove sel 0.0 end\n}\nbind Text <B1-Motion> {\n    set tk::Priv(x) %x\n    set tk::Priv(y) %y\n    tk::TextSelectTo %W %x %y\n}\nbind Text <Double-Button-1> {\n    set tk::Priv(selectMode) word\n    tk::TextSelectTo %W %x %y\n    catch {%W mark set insert sel.first}\n}\nbind Text <Triple-Button-1> {\n    set tk::Priv(selectMode) line\n    tk::TextSelectTo %W %x %y\n    catch {%W mark set insert sel.first}\n}\nbind Text <Shift-Button-1> {\n    tk::TextResetAnchor %W @%x,%y\n    set tk::Priv(selectMode) char\n    tk::TextSelectTo %W %x %y\n}\nbind Text <Double-Shift-Button-1>\t{\n    set tk::Priv(selectMode) word\n    tk::TextSelectTo %W %x %y 1\n}\nbind Text <Triple-Shift-Button-1>\t{\n    set tk::Priv(selectMode) line\n    tk::TextSelectTo %W %x %y\n}\nbind Text <B1-Leave> {\n    set tk::Priv(x) %x\n    set tk::Priv(y) %y\n    tk::TextAutoScan %W\n}\nbind Text <B1-Enter> {\n    tk::CancelRepeat\n}\nbind Text <ButtonRelease-1> {\n    tk::CancelRepeat\n}\n\nbind Text <Control-Button-1> {\n    %W mark set insert @%x,%y\n    # An operation that moves the insert mark without making it\n    # one end of the selection must insert an autoseparator\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n}\n# stop an accidental double click triggering <Double-Button-1>\nbind Text <Double-Control-Button-1> { # nothing }\n# stop an accidental movement triggering <B1-Motion>\nbind Text <Control-B1-Motion> { # nothing }\nbind Text <<PrevChar>> {\n    tk::TextSetCursor %W [tk::TextPrevPos %W insert tk::startOfCluster]\n}\nbind Text <<NextChar>> {\n    tk::TextSetCursor %W [tk::TextNextPos %W insert tk::endOfCluster]\n}\nbind Text <<PrevLine>> {\n    tk::TextSetCursor %W [tk::TextUpDownLine %W -1]\n}\nbind Text <<NextLine>> {\n    tk::TextSetCursor %W [tk::TextUpDownLine %W 1]\n}\nbind Text <<SelectPrevChar>> {\n    tk::TextKeySelect %W [tk::TextPrevPos %W insert tk::startOfCluster]\n}\nbind Text <<SelectNextChar>> {\n    tk::TextKeySelect %W [tk::TextNextPos %W insert tk::endOfCluster]\n}\nbind Text <<SelectPrevLine>> {\n    tk::TextKeySelect %W [tk::TextUpDownLine %W -1]\n}\nbind Text <<SelectNextLine>> {\n    tk::TextKeySelect %W [tk::TextUpDownLine %W 1]\n}\nbind Text <<PrevWord>> {\n    tk::TextSetCursor %W [tk::TextPrevPos %W insert tk::startOfPreviousWord]\n}\nbind Text <<NextWord>> {\n    tk::TextSetCursor %W [tk::TextNextWord %W insert]\n}\nbind Text <<PrevPara>> {\n    tk::TextSetCursor %W [tk::TextPrevPara %W insert]\n}\nbind Text <<NextPara>> {\n    tk::TextSetCursor %W [tk::TextNextPara %W insert]\n}\nbind Text <<SelectPrevWord>> {\n    tk::TextKeySelect %W [tk::TextPrevPos %W insert tk::startOfPreviousWord]\n}\nbind Text <<SelectNextWord>> {\n    tk::TextKeySelect %W [tk::TextSelectNextWord %W insert]\n}\nbind Text <<SelectPrevPara>> {\n    tk::TextKeySelect %W [tk::TextPrevPara %W insert]\n}\nbind Text <<SelectNextPara>> {\n    tk::TextKeySelect %W [tk::TextNextPara %W insert]\n}\nbind Text <Prior> {\n    tk::TextSetCursor %W [tk::TextScrollPages %W -1]\n}\nbind Text <Shift-Prior> {\n    tk::TextKeySelect %W [tk::TextScrollPages %W -1]\n}\nbind Text <Next> {\n    tk::TextSetCursor %W [tk::TextScrollPages %W 1]\n}\nbind Text <Shift-Next> {\n    tk::TextKeySelect %W [tk::TextScrollPages %W 1]\n}\nbind Text <Control-Prior> {\n    %W xview scroll -1 page\n}\nbind Text <Control-Next> {\n    %W xview scroll 1 page\n}\n\nbind Text <<LineStart>> {\n    tk::TextSetCursor %W {insert display linestart}\n}\nbind Text <<SelectLineStart>> {\n    tk::TextKeySelect %W {insert display linestart}\n}\nbind Text <<LineEnd>> {\n    tk::TextSetCursor %W {insert display lineend}\n}\nbind Text <<SelectLineEnd>> {\n    tk::TextKeySelect %W {insert display lineend}\n}\nbind Text <Control-Home> {\n    tk::TextSetCursor %W 1.0\n}\nbind Text <Control-Shift-Home> {\n    tk::TextKeySelect %W 1.0\n}\nbind Text <Control-End> {\n    tk::TextSetCursor %W {end - 1 indices}\n}\nbind Text <Control-Shift-End> {\n    tk::TextKeySelect %W {end - 1 indices}\n}\n\nbind Text <Tab> {\n    if {[%W cget -state] eq \"normal\"} {\n\ttk::TextInsert %W \\t\n\tfocus %W\n\tbreak\n    }\n}\nbind Text <Shift-Tab> {\n    # Needed only to keep <Tab> binding from triggering;  doesn't\n    # have to actually do anything.\n    break\n}\nbind Text <Control-Tab> {\n    focus [tk_focusNext %W]\n}\nbind Text <Control-Shift-Tab> {\n    focus [tk_focusPrev %W]\n}\nbind Text <Control-i> {\n    tk::TextInsert %W \\t\n}\nbind Text <Return> {\n    tk::TextInsert %W \\n\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n}\nbind Text <Delete> {\n    if {[tk::TextCursorInSelection %W]} {\n\t%W delete sel.first sel.last\n    } else {\n\tif {[%W compare end != insert+1c]} {\n\t    %W delete [tk::TextPrevPos %W insert+1c tk::startOfCluster] \\\n\t\t    [tk::TextNextPos %W insert tk::endOfCluster]\n\t}\n\t%W see insert\n    }\n}\nbind Text <BackSpace> {\n    if {[tk::TextCursorInSelection %W]} {\n\t%W delete sel.first sel.last\n    } else {\n\tif {[%W compare insert != 1.0]} {\n\t    %W delete [tk::TextPrevPos %W insert tk::startOfCluster] \\\n\t\t    [tk::TextNextPos %W insert-1c tk::endOfCluster]\n\t}\n\t%W see insert\n    }\n}\n\nbind Text <Control-space> {\n    %W mark set [tk::TextAnchor %W] insert\n}\nbind Text <Select> {\n    %W mark set [tk::TextAnchor %W] insert\n}\nbind Text <Control-Shift-space> {\n    set tk::Priv(selectMode) char\n    tk::TextKeyExtend %W insert\n}\nbind Text <Shift-Select> {\n    set tk::Priv(selectMode) char\n    tk::TextKeyExtend %W insert\n}\nbind Text <<SelectAll>> {\n    %W tag add sel 1.0 end\n}\nbind Text <<SelectNone>> {\n    %W tag remove sel 1.0 end\n    # An operation that clears the selection must insert an autoseparator,\n    # because the selection operation may have moved the insert mark\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n}\nbind Text <<Cut>> {\n    tk_textCut %W\n}\nbind Text <<Copy>> {\n    tk_textCopy %W\n}\nbind Text <<Paste>> {\n    tk_textPaste %W\n}\nbind Text <<Clear>> {\n    # Make <<Clear>> an atomic operation on the Undo stack,\n    # i.e. separate it from other delete operations on either side\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n    catch {%W delete sel.first sel.last}\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n}\nbind Text <<PasteSelection>> {\n    if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]\n\t    || !$tk::Priv(mouseMoved)} {\n\ttk::TextPasteSelection %W %x %y\n    }\n}\nbind Text <Insert> {\n    catch {tk::TextInsert %W [::tk::GetSelection %W PRIMARY]}\n}\nbind Text <Key> {\n    tk::TextInsert %W %A\n}\n\n# Ignore all Alt, Meta, Control, Command, and Fn keypresses unless explicitly bound.\n# Otherwise, if a widget binding for one of these is defined, the\n# <Key> class binding will also fire and insert the character,\n# which is wrong.  Ditto for <Escape>.\n\nbind Text <Alt-Key> {# nothing }\nbind Text <Meta-Key> {# nothing}\nbind Text <Control-Key> {# nothing}\nbind Text <Escape> {# nothing}\nbind Text <KP_Enter> {# nothing}\nbind Text <Command-Key> {# nothing}\nbind Text <Fn-Key> {# nothing}\n\n# Additional emacs-like bindings:\n\nbind Text <Control-d> {\n    if {!$tk_strictMotif && [%W compare end != insert+1c]} {\n\t%W delete insert\n    }\n}\nbind Text <Control-k> {\n    if {!$tk_strictMotif && [%W compare end != insert+1c]} {\n\tif {[%W compare insert == {insert lineend}]} {\n\t    %W delete insert\n\t} else {\n\t    %W delete insert {insert lineend}\n\t}\n    }\n}\nbind Text <Control-o> {\n    if {!$tk_strictMotif} {\n\t%W insert insert \\n\n\t%W mark set insert insert-1c\n    }\n}\nbind Text <Control-t> {\n    if {!$tk_strictMotif} {\n\ttk::TextTranspose %W\n    }\n}\n\nbind Text <<Undo>> {\n    # An Undo operation may remove the separator at the top of the Undo stack.\n    # Then the item at the top of the stack gets merged with the subsequent changes.\n    # Place separators before and after Undo to prevent this.\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n    catch { %W edit undo }\n    if {[%W cget -autoseparators]} {\n\t%W edit separator\n    }\n}\n\nbind Text <<Redo>> {\n    catch { %W edit redo }\n}\n\nbind Text <Meta-b> {\n    if {!$tk_strictMotif} {\n\ttk::TextSetCursor %W [tk::TextPrevPos %W insert tk::startOfPreviousWord]\n    }\n}\nbind Text <Meta-d> {\n    if {!$tk_strictMotif && [%W compare end != insert+1c]} {\n\t%W delete insert [tk::TextNextWord %W insert]\n    }\n}\nbind Text <Meta-f> {\n    if {!$tk_strictMotif} {\n\ttk::TextSetCursor %W [tk::TextNextWord %W insert]\n    }\n}\nbind Text <Meta-less> {\n    if {!$tk_strictMotif} {\n\ttk::TextSetCursor %W 1.0\n    }\n}\nbind Text <Meta-greater> {\n    if {!$tk_strictMotif} {\n\ttk::TextSetCursor %W end-1c\n    }\n}\nbind Text <Meta-BackSpace> {\n    if {!$tk_strictMotif} {\n\t%W delete [tk::TextPrevPos %W insert tk::startOfPreviousWord] insert\n    }\n}\nbind Text <Meta-Delete> {\n    if {!$tk_strictMotif} {\n\t%W delete [tk::TextPrevPos %W insert tk::startOfPreviousWord] insert\n    }\n}\n\n# Bindings for IME text input.\n\nbind Text <<TkStartIMEMarkedText>> {\n    dict set ::tk::Priv(IMETextMark) \"%W\" [%W index insert]\n}\nbind Text <<TkEndIMEMarkedText>> {\n    ::tk::TextEndIMEMarkedText %W\n}\nbind Text <<TkClearIMEMarkedText>> {\n    %W delete IMEmarkedtext.first IMEmarkedtext.last\n}\nbind Text <<TkAccentBackspace>> {\n    %W delete insert-1c\n}\n\n# ::tk::TextEndIMEMarkedText --\n#\n# Handles input method text marking in a text widget.\n#\n# Arguments:\n# w -\tThe text widget\n\nproc ::tk::TextEndIMEMarkedText {w} {\n    variable Priv\n    if {[catch {\n\tset mark [dict get $Priv(IMETextMark) $w]\n    }]} {\n\tbell\n\treturn\n    }\n    $w tag add IMEmarkedtext $mark insert\n    $w tag configure IMEmarkedtext -underline 1\n}\n\n# Macintosh only bindings:\n\nif {[tk windowingsystem] eq \"aqua\"} {\nbind Text <Control-v> {\n    tk::TextScrollPages %W 1\n}\n\n# End of Mac only bindings\n}\n\n# A few additional bindings of my own.\n\nbind Text <Control-h> {\n    if {!$tk_strictMotif && [%W compare insert != 1.0]} {\n\t%W delete insert-1c\n\t%W see insert\n    }\n}\nbind Text <Button-2> {\n    if {!$tk_strictMotif} {\n\ttk::TextScanMark %W %x %y\n    }\n}\nbind Text <B2-Motion> {\n    if {!$tk_strictMotif} {\n\ttk::TextScanDrag %W %x %y\n    }\n}\nset ::tk::Priv(prevPos) {}\n\nbind Text <MouseWheel> {\n    tk::MouseWheel %W y [tk::ScaleNum %D] -4.0 pixels\n}\nbind Text <Option-MouseWheel> {\n    tk::MouseWheel %W y [tk::ScaleNum %D] -1.2 pixels\n}\nbind Text <Shift-MouseWheel> {\n    tk::MouseWheel %W x [tk::ScaleNum %D] -4.0 pixels\n}\nbind Text <Shift-Option-MouseWheel> {\n    tk::MouseWheel %W x [tk::ScaleNum %D] -1.2 pixels\n}\nbind Text <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n    if {$tk::Priv(deltaX) != 0} {\n\t%W xview scroll [tk::ScaleNum [expr {-$tk::Priv(deltaX)}]] pixels\n    }\n    if {$tk::Priv(deltaY) != 0} {\n\t%W yview scroll [tk::ScaleNum [expr {-$tk::Priv(deltaY)}]] pixels\n    }\n}\n\n# ::tk::TextClosestGap --\n# Given x and y coordinates, this procedure finds the closest boundary\n# between characters to the given coordinates and returns the index\n# of the character just after the boundary.\n#\n# Arguments:\n# w -\t\tThe text window.\n# x -\t\tX-coordinate within the window.\n# y -\t\tY-coordinate within the window.\n\nproc ::tk::TextClosestGap {w x y} {\n    set pos [$w index @$x,$y]\n    set bbox [$w bbox $pos]\n    if {$bbox eq \"\"} {\n\treturn $pos\n    }\n    # The check on y coord of the line bbox with dlineinfo is to fix\n    # [a9cf210a42] to properly handle selecting and moving the mouse\n    # out of the widget.\n    if {$y < [lindex [$w dlineinfo $pos] 1] ||\n\t    $x - [lindex $bbox 0] < [lindex $bbox 2]/2} {\n\treturn $pos\n    }\n    $w index \"$pos + 1 char\"\n}\n\n# ::tk::TextButton1 --\n# This procedure is invoked to handle button-1 presses in text\n# widgets.  It moves the insertion cursor, sets the selection anchor,\n# and claims the input focus.\n#\n# Arguments:\n# w -\t\tThe text window in which the button was pressed.\n# x -\t\tThe x-coordinate of the button press.\n# y -\t\tThe x-coordinate of the button press.\n\nproc ::tk::TextButton1 {w x y} {\n    variable ::tk::Priv\n\n    set Priv(selectMode) char\n    set Priv(mouseMoved) 0\n    set Priv(pressX) $x\n    set anchorname [tk::TextAnchor $w]\n    $w mark set insert [TextClosestGap $w $x $y]\n    $w mark set $anchorname insert\n    # Set the anchor mark's gravity depending on the click position\n    # relative to the gap\n    set bbox [$w bbox [$w index $anchorname]]\n    if {$x > [lindex $bbox 0]} {\n\t$w mark gravity $anchorname right\n    } else {\n\t$w mark gravity $anchorname left\n    }\n    focus $w\n    if {[$w cget -autoseparators]} {\n\t$w edit separator\n    }\n}\n\n# ::tk::TextSelectTo --\n# This procedure is invoked to extend the selection, typically when\n# dragging it with the mouse.  Depending on the selection mode (character,\n# word, line) it selects in different-sized units.  This procedure\n# ignores mouse motions initially until the mouse has moved from\n# one character to another or until there have been multiple clicks.\n#\n# Note that the 'anchor' is implemented programmatically using\n# a text widget mark, and uses a name that will be unique for each\n# text widget (even when there are multiple peers).  Currently the\n# anchor is considered private to Tk, hence the name 'tk::anchor$w'.\n#\n# Arguments:\n# w -\t\tThe text window in which the button was pressed.\n# x -\t\tMouse x position.\n# y -\t\tMouse y position.\n\nset ::tk::Priv(textanchoruid) 0\n\nproc ::tk::TextAnchor {w} {\n    variable Priv\n    if {![info exists Priv(textanchor,$w)]} {\n\tset Priv(textanchor,$w) tk::anchor[incr Priv(textanchoruid)]\n    }\n    return $Priv(textanchor,$w)\n}\n\nproc ::tk::TextSelectTo {w x y {extend 0}} {\n    variable ::tk::Priv\n\n    set anchorname [tk::TextAnchor $w]\n    set cur [TextClosestGap $w $x $y]\n    if {[catch {$w index $anchorname}]} {\n\t$w mark set $anchorname $cur\n    }\n    set anchor [$w index $anchorname]\n    if {[$w compare $cur != $anchor] || (abs($Priv(pressX) - $x) >= 3)} {\n\tset Priv(mouseMoved) 1\n    }\n    switch -- $Priv(selectMode) {\n\tchar {\n\t    if {[$w compare $cur < $anchorname]} {\n\t\tset first $cur\n\t\tset last $anchorname\n\t    } else {\n\t\tset first $anchorname\n\t\tset last $cur\n\t    }\n\t}\n\tword {\n\t    # Set initial range based only on the anchor (1 char min width)\n\t    if {[$w mark gravity $anchorname] eq \"right\"} {\n\t\tset first $anchorname\n\t\tset last \"$anchorname + 1c\"\n\t    } else {\n\t\tset first \"$anchorname - 1c\"\n\t\tset last $anchorname\n\t    }\n\t    # Extend range (if necessary) based on the current point\n\t    if {[$w compare $cur < $first]} {\n\t\tset first $cur\n\t    } elseif {[$w compare $cur > $last]} {\n\t\tset last $cur\n\t    }\n\n\t    # Now find word boundaries\n\t    set first [TextPrevPos $w \"$first + 1c\" tk::wordBreakBefore]\n\t    set last [TextNextPos $w \"$last - 1c\" tk::wordBreakAfter]\n\t}\n\tline {\n\t    # Set initial range based only on the anchor\n\t    set first \"$anchorname linestart\"\n\t    set last \"$anchorname lineend\"\n\n\t    # Extend range (if necessary) based on the current point\n\t    if {[$w compare $cur < $first]} {\n\t\tset first \"$cur linestart\"\n\t    } elseif {[$w compare $cur > $last]} {\n\t\tset last \"$cur lineend\"\n\t    }\n\t    set first [$w index $first]\n\t    set last [$w index \"$last + 1c\"]\n\t}\n    }\n    if {$Priv(mouseMoved) || ($Priv(selectMode) ne \"char\")} {\n\t$w tag remove sel 0.0 end\n\t$w mark set insert $cur\n\t$w tag add sel $first $last\n\t$w tag remove sel $last end\n\tupdate idletasks\n    }\n}\n\n# ::tk::TextKeyExtend --\n# This procedure handles extending the selection from the keyboard,\n# where the point to extend to is really the boundary between two\n# characters rather than a particular character.\n#\n# Arguments:\n# w -\t\tThe text window.\n# index -\tThe point to which the selection is to be extended.\n\nproc ::tk::TextKeyExtend {w index} {\n\n    set anchorname [tk::TextAnchor $w]\n    set cur [$w index $index]\n    if {[catch {$w index $anchorname}]} {\n\t$w mark set $anchorname $cur\n    }\n    set anchor [$w index $anchorname]\n    if {[$w compare $cur < $anchorname]} {\n\tset first $cur\n\tset last $anchorname\n    } else {\n\tset first $anchorname\n\tset last $cur\n    }\n    $w tag remove sel 0.0 $first\n    $w tag add sel $first $last\n    $w tag remove sel $last end\n}\n\n# ::tk::TextPasteSelection --\n# This procedure sets the insertion cursor to the mouse position,\n# inserts the selection, and sets the focus to the window.\n#\n# Arguments:\n# w -\t\tThe text window.\n# x, y -\tPosition of the mouse.\n\nproc ::tk::TextPasteSelection {w x y} {\n    $w mark set insert [TextClosestGap $w $x $y]\n    if {![catch {::tk::GetSelection $w PRIMARY} sel]} {\n\tset oldSeparator [$w cget -autoseparators]\n\tif {$oldSeparator} {\n\t    $w configure -autoseparators 0\n\t    $w edit separator\n\t}\n\t$w insert insert $sel\n\tif {$oldSeparator} {\n\t    $w edit separator\n\t    $w configure -autoseparators 1\n\t}\n    }\n    if {[$w cget -state] eq \"normal\"} {\n\tfocus $w\n    }\n}\n\n# ::tk::TextAutoScan --\n# This procedure is invoked when the mouse leaves a text window\n# with button 1 down.  It scrolls the window up, down, left, or right,\n# depending on where the mouse is (this information was saved in\n# ::tk::Priv(x) and ::tk::Priv(y)), and reschedules itself as an \"after\"\n# command so that the window continues to scroll until the mouse\n# moves back into the window or the mouse button is released.\n#\n# Arguments:\n# w -\t\tThe text window.\n\nproc ::tk::TextAutoScan {w} {\n    variable ::tk::Priv\n    if {![winfo exists $w]} {\n\treturn\n    }\n    if {$Priv(y) >= [winfo height $w]} {\n\t$w yview scroll [expr {1 + $Priv(y) - [winfo height $w]}] pixels\n    } elseif {$Priv(y) < 0} {\n\t$w yview scroll [expr {-1 + $Priv(y)}] pixels\n    } elseif {$Priv(x) >= [winfo width $w]} {\n\t$w xview scroll 2 units\n    } elseif {$Priv(x) < 0} {\n\t$w xview scroll -2 units\n    } else {\n\treturn\n    }\n    TextSelectTo $w $Priv(x) $Priv(y)\n    set Priv(afterId) [after 50 [list tk::TextAutoScan $w]]\n}\n\n# ::tk::TextSetCursor\n# Move the insertion cursor to a given position in a text.  Also\n# clears the selection, if there is one in the text, and makes sure\n# that the insertion cursor is visible.  Also, don't let the insertion\n# cursor appear on the dummy last line of the text.\n#\n# Arguments:\n# w -\t\tThe text window.\n# pos -\t\tThe desired new position for the cursor in the window.\n\nproc ::tk::TextSetCursor {w pos} {\n    if {[$w compare $pos == end]} {\n\tset pos {end - 1 chars}\n    }\n    $w mark set insert $pos\n    $w tag remove sel 1.0 end\n    $w see insert\n    if {[$w cget -autoseparators]} {\n\t$w edit separator\n    }\n}\n\n# ::tk::TextKeySelect\n# This procedure is invoked when stroking out selections using the\n# keyboard.  It moves the cursor to a new position, then extends\n# the selection to that position.\n#\n# Arguments:\n# w -\t\tThe text window.\n# new -\t\tA new position for the insertion cursor (the cursor hasn't\n#\t\tactually been moved to this position yet).\n\nproc ::tk::TextKeySelect {w new} {\n    set anchorname [tk::TextAnchor $w]\n    if {[$w tag nextrange sel 1.0 end] eq \"\"} {\n\tif {[$w compare $new < insert]} {\n\t    $w tag add sel $new insert\n\t} else {\n\t    $w tag add sel insert $new\n\t}\n\t$w mark set $anchorname insert\n    } else {\n\tif {[catch {$w index $anchorname}]} {\n\t    $w mark set $anchorname insert\n\t}\n\tif {[$w compare $new < $anchorname]} {\n\t    set first $new\n\t    set last $anchorname\n\t} else {\n\t    set first $anchorname\n\t    set last $new\n\t}\n\t$w tag remove sel 1.0 $first\n\t$w tag add sel $first $last\n\t$w tag remove sel $last end\n    }\n    $w mark set insert $new\n    $w see insert\n    update idletasks\n}\n\n# ::tk::TextResetAnchor --\n# Set the selection anchor to whichever end is farthest from the\n# index argument.  One special trick: if the selection has two or\n# fewer characters, just leave the anchor where it is.  In this\n# case it doesn't matter which point gets chosen for the anchor,\n# and for the things like Shift-Left and Shift-Right this produces\n# better behavior when the cursor moves back and forth across the\n# anchor.\n#\n# Arguments:\n# w -\t\tThe text widget.\n# index -\tPosition at which mouse button was pressed, which determines\n#\t\twhich end of selection should be used as anchor point.\n\nproc ::tk::TextResetAnchor {w index} {\n    if {[$w tag ranges sel] eq \"\"} {\n\t# Don't move the anchor if there is no selection now; this\n\t# makes the widget behave \"correctly\" when the user clicks\n\t# once, then shift-clicks somewhere -- ie, the area between\n\t# the two clicks will be selected. [Bug: 5929].\n\treturn\n    }\n    set anchorname [tk::TextAnchor $w]\n    set a [$w index $index]\n    set b [$w index sel.first]\n    set c [$w index sel.last]\n    if {[$w compare $a < $b]} {\n\t$w mark set $anchorname sel.last\n\treturn\n    }\n    if {[$w compare $a > $c]} {\n\t$w mark set $anchorname sel.first\n\treturn\n    }\n    scan $a \"%d.%d\" lineA chA\n    scan $b \"%d.%d\" lineB chB\n    scan $c \"%d.%d\" lineC chC\n    if {$lineB < $lineC+2} {\n\tset total [string length [$w get $b $c]]\n\tif {$total <= 2} {\n\t    return\n\t}\n\tif {[string length [$w get $b $a]] < ($total/2)} {\n\t    $w mark set $anchorname sel.last\n\t} else {\n\t    $w mark set $anchorname sel.first\n\t}\n\treturn\n    }\n    if {($lineA-$lineB) < ($lineC-$lineA)} {\n\t$w mark set $anchorname sel.last\n    } else {\n\t$w mark set $anchorname sel.first\n    }\n}\n\n# ::tk::TextCursorInSelection --\n# Check whether the selection exists and contains the insertion cursor. Note\n# that it assumes that the selection is contiguous.\n#\n# Arguments:\n# w -\t\tThe text widget whose selection is to be checked\n\nproc ::tk::TextCursorInSelection {w} {\n    expr {\n\t[llength [$w tag ranges sel]]\n\t&& [$w compare sel.first <= insert]\n\t&& [$w compare sel.last >= insert]\n    }\n}\n\n# ::tk::TextInsert --\n# Insert a string into a text at the point of the insertion cursor.\n# If there is a selection in the text, and it covers the point of the\n# insertion cursor, then delete the selection before inserting.\n#\n# Arguments:\n# w -\t\tThe text window in which to insert the string\n# s -\t\tThe string to insert (usually just a single character)\n\nproc ::tk::TextInsert {w s} {\n    if {$s eq \"\" || [$w cget -state] eq \"disabled\"} {\n\treturn\n    }\n    set compound 0\n    if {[TextCursorInSelection $w]} {\n\tset oldSeparator [$w cget -autoseparators]\n\tif {$oldSeparator} {\n\t    $w configure -autoseparators 0\n\t    $w edit separator\n\t    set compound 1\n\t}\n\t$w delete sel.first sel.last\n    }\n    $w insert insert $s\n    $w see insert\n    if {$compound && $oldSeparator} {\n\t$w edit separator\n\t$w configure -autoseparators 1\n    }\n}\n\n# ::tk::TextUpDownLine --\n# Returns the index of the character one display line above or below the\n# insertion cursor.  There is a tricky thing here: we want to maintain the\n# original x position across repeated operations, even though some lines\n# that will get passed through don't have enough characters to cover the\n# original column.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# n -\t\tThe number of display lines to move: -1 for up one line,\n#\t\t+1 for down one line.\n\nproc ::tk::TextUpDownLine {w n} {\n    variable ::tk::Priv\n\n    set i [$w index insert]\n    if {$Priv(prevPos) ne $i} {\n\tset Priv(textPosOrig) $i\n    }\n    set lines [$w count -displaylines $Priv(textPosOrig) $i]\n    set new [$w index \\\n\t    \"$Priv(textPosOrig) + [expr {$lines + $n}] displaylines\"]\n    set Priv(prevPos) $new\n    if {[$w compare $new == \"end display lineend\"] \\\n\t    || [$w compare $new == \"insert display linestart\"]} {\n\tset Priv(textPosOrig) $new\n    }\n    return $new\n}\n\n# ::tk::TextPrevPara --\n# Returns the index of the beginning of the paragraph just before a given\n# position in the text (the beginning of a paragraph is the first non-blank\n# character after a blank line).\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# pos -\t\tPosition at which to start search.\n\nproc ::tk::TextPrevPara {w pos} {\n    set pos [$w index \"$pos linestart\"]\n    while {1} {\n\tif {([$w get \"$pos - 1 line\"] eq \"\\n\" && ([$w get $pos] ne \"\\n\")) \\\n\t\t|| $pos eq \"1.0\"} {\n\t    if {[regexp -indices -- {^[ \\t]+(.)} \\\n\t\t    [$w get $pos \"$pos lineend\"] -> index]} {\n\t\tset pos [$w index \"$pos + [lindex $index 0] chars\"]\n\t    }\n\t    if {[$w compare $pos != insert] || [lindex [split $pos .] 0]==1} {\n\t\treturn $pos\n\t    }\n\t}\n\tset pos [$w index \"$pos - 1 line\"]\n    }\n}\n\n# ::tk::TextNextPara --\n# Returns the index of the beginning of the paragraph just after a given\n# position in the text (the beginning of a paragraph is the first non-blank\n# character after a blank line).\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::TextNextPara {w start} {\n    set pos [$w index \"$start linestart + 1 line\"]\n    while {[$w get $pos] ne \"\\n\"} {\n\tif {[$w compare $pos == end]} {\n\t    return [$w index \"end - 1c\"]\n\t}\n\tset pos [$w index \"$pos + 1 line\"]\n    }\n    while {[$w get $pos] eq \"\\n\"} {\n\tset pos [$w index \"$pos + 1 line\"]\n\tif {[$w compare $pos == end]} {\n\t    return [$w index \"end - 1c\"]\n\t}\n    }\n    if {[regexp -indices -- {^[ \\t]+(.)} \\\n\t    [$w get $pos \"$pos lineend\"] -> index]} {\n\treturn [$w index \"$pos + [lindex $index 0] chars\"]\n    }\n    return $pos\n}\n\n# ::tk::TextScrollPages --\n# This is a utility procedure used in bindings for moving up and down\n# pages and possibly extending the selection along the way.  It scrolls\n# the view in the widget by the number of pages, and it returns the\n# index of the character that is at the same position in the new view\n# as the insertion cursor used to be in the old view.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# count -\tNumber of pages forward to scroll;  may be negative\n#\t\tto scroll backwards.\n\nproc ::tk::TextScrollPages {w count} {\n    set bbox [$w bbox insert]\n    $w yview scroll $count pages\n    if {$bbox eq \"\"} {\n\treturn [$w index @[expr {[winfo height $w]/2}],0]\n    }\n    return [$w index @[lindex $bbox 0],[lindex $bbox 1]]\n}\n\n# ::tk::TextTranspose --\n# This procedure implements the \"transpose\" function for text widgets.\n# It tranposes the characters on either side of the insertion cursor,\n# unless the cursor is at the end of the line.  In this case it\n# transposes the two characters to the left of the cursor.  In either\n# case, the cursor ends up to the right of the transposed characters.\n#\n# Arguments:\n# w -\t\tText window in which to transpose.\n\nproc ::tk::TextTranspose w {\n    set pos insert\n    if {[$w compare $pos != \"$pos lineend\"]} {\n\tset pos [$w index \"$pos + 1 char\"]\n    }\n    set new [$w get \"$pos - 1 char\"][$w get  \"$pos - 2 char\"]\n    if {[$w compare \"$pos - 1 char\" == 1.0]} {\n\treturn\n    }\n    # ensure this is seen as an atomic op to undo\n    set autosep [$w cget -autoseparators]\n    if {$autosep} {\n\t$w configure -autoseparators 0\n\t$w edit separator\n    }\n    $w delete \"$pos - 2 char\" $pos\n    $w insert insert $new\n    $w see insert\n    if {$autosep} {\n\t$w edit separator\n\t$w configure -autoseparators $autosep\n    }\n}\n\n# ::tk_textCopy --\n# This procedure copies the selection from a text widget into the\n# clipboard.\n#\n# Arguments:\n# w -\t\tName of a text widget.\n\nproc ::tk_textCopy w {\n    if {![catch {set data [$w get sel.first sel.last]}]} {\n\tclipboard clear -displayof $w\n\tclipboard append -displayof $w $data\n    }\n}\n\n# ::tk_textCut --\n# This procedure copies the selection from a text widget into the\n# clipboard, then deletes the selection (if it exists in the given\n# widget).\n#\n# Arguments:\n# w -\t\tName of a text widget.\n\nproc ::tk_textCut w {\n    if {![catch {set data [$w get sel.first sel.last]}]} {\n\t# make <<Cut>> an atomic operation on the Undo stack,\n\t# i.e. separate it from other delete operations on either side\n\tset oldSeparator [$w cget -autoseparators]\n\tif {([$w cget -state] eq \"normal\") && $oldSeparator} {\n\t    $w edit separator\n\t}\n\tclipboard clear -displayof $w\n\tclipboard append -displayof $w $data\n\t$w delete sel.first sel.last\n\tif {([$w cget -state] eq \"normal\") && $oldSeparator} {\n\t    $w edit separator\n\t}\n    }\n}\n\n# ::tk_textPaste --\n# This procedure pastes the contents of the clipboard to the insertion\n# point in a text widget.\n#\n# Arguments:\n# w -\t\tName of a text widget.\n\nproc ::tk_textPaste w {\n    if {![catch {::tk::GetSelection $w CLIPBOARD} sel]} {\n\tset oldSeparator [$w cget -autoseparators]\n\tif {$oldSeparator} {\n\t    $w configure -autoseparators 0\n\t    $w edit separator\n\t}\n\tif {[tk windowingsystem] ne \"x11\"} {\n\t    catch { $w delete sel.first sel.last }\n\t}\n\t$w insert insert $sel\n\tif {$oldSeparator} {\n\t    $w edit separator\n\t    $w configure -autoseparators 1\n\t}\n    }\n}\n\n# ::tk::TextNextWord --\n# Returns the index of the next start-of-word position after the next\n# end-of-word position after a given position in the text.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::TextNextWord {w start} {\n    TextNextPos $w [TextNextPos $w $start tk::endOfWord] \\\n\t    tk::startOfNextWord\n}\n\n# ::tk::TextSelectNextWord --\n# Returns the index of the next end-of-word position after a given\n# position in the text.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# start -\tPosition at which to start search.\n\nproc ::tk::TextSelectNextWord {w start} {\n    TextNextPos $w $start tk::endOfWord\n}\n\n\n# ::tk::TextNextPos --\n# Returns the index of the next position after the given starting\n# position in the text as computed by a specified function.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# start -\tPosition at which to start search.\n# op -\t\tFunction to use to find next position.\n\nproc ::tk::TextNextPos {w start op} {\n    set text \"\"\n    set cur $start\n    while {[$w compare $cur < end]} {\n\tset text $text[$w get -displaychars $cur \"$cur lineend + 1c\"]\n\tset pos [$op $text 0]\n\tif {$pos >= 0} {\n\t    return [$w index \"$start + $pos display chars\"]\n\t}\n\tset cur [$w index \"$cur lineend +1c\"]\n    }\n    return end\n}\n\n# ::tk::TextPrevPos --\n# Returns the index of the previous position before the given starting\n# position in the text as computed by a specified function.\n#\n# Arguments:\n# w -\t\tThe text window in which the cursor is to move.\n# start -\tPosition at which to start search.\n# op -\t\tFunction to use to find next position.\n\nproc ::tk::TextPrevPos {w start op} {\n    set text \"\"\n    set cur $start\n    while {[$w compare $cur > 0.0]} {\n\tset text [$w get -displaychars \"$cur linestart - 1c\" $cur]$text\n\tset pos [$op $text end]\n\tif {$pos >= 0} {\n\t    return [$w index \"$cur linestart - 1c + $pos display chars\"]\n\t}\n\tset cur [$w index \"$cur linestart - 1c\"]\n    }\n    return 0.0\n}\n\n# ::tk::TextScanMark --\n#\n# Marks the start of a possible scan drag operation\n#\n# Arguments:\n# w -\tThe text window from which the text to get\n# x -\tx location on screen\n# y -\ty location on screen\n\nproc ::tk::TextScanMark {w x y} {\n    variable ::tk::Priv\n    $w scan mark $x $y\n    set Priv(x) $x\n    set Priv(y) $y\n    set Priv(mouseMoved) 0\n}\n\n# ::tk::TextScanDrag --\n#\n# Marks the start of a possible scan drag operation\n#\n# Arguments:\n# w -\tThe text window from which the text to get\n# x -\tx location on screen\n# y -\ty location on screen\n\nproc ::tk::TextScanDrag {w x y} {\n    variable ::tk::Priv\n    # Make sure these exist, as some weird situations can trigger the\n    # motion binding without the initial press.  [Bug #220269]\n    if {![info exists Priv(x)]} {\n\tset Priv(x) $x\n    }\n    if {![info exists Priv(y)]} {\n\tset Priv(y) $y\n    }\n    if {($x != $Priv(x)) || ($y != $Priv(y))} {\n\tset Priv(mouseMoved) 1\n    }\n    if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} {\n\t$w scan dragto $x $y\n    }\n}\n# ::tk::TextUndoRedoProcessMarks --\n#\n# This proc is executed after an undo or redo action.\n# It processes the list of undo/redo marks temporarily set in the\n# text widget to positions delimiting where changes happened, and\n# returns a flat list of ranges. The temporary marks are removed\n# from the text widget.\n#\n# Arguments:\n# w -\tThe text widget\n\nproc ::tk::TextUndoRedoProcessMarks {w} {\n    set indices {}\n    set undoMarks {}\n\n    # only consider the temporary marks set by an undo/redo action\n    foreach mark [$w mark names] {\n\tif {[string range $mark 0 11] eq \"tk::undoMark\"} {\n\t    lappend undoMarks $mark\n\t}\n    }\n\n    # transform marks into indices\n    # the number of undo/redo marks is always even, each right mark\n    # completes a left mark to give a range\n    # this is true because:\n    #   - undo/redo only deals with insertions and deletions of text\n    #   - insertions may move marks but not delete them\n    #   - when deleting text, marks located inside the deleted range\n    #     are not erased but moved to the start of the deletion range\n    #         . this is done in TkBTreeDeleteIndexRange (\"This segment\n    #           refuses to die...\")\n    #         . because MarkDeleteProc does nothing else than returning\n    #           a value indicating that marks are not deleted by this\n    #           deleteProc\n    #         . mark deletion rather happen through [.text mark unset xxx]\n    #           which was not used _up to this point of the code_ (it\n    #           is a bit later just before exiting the present proc)\n    set nUndoMarks [llength $undoMarks]\n    set n [expr {$nUndoMarks / 2}]\n    set undoMarks [lsort -dictionary $undoMarks]\n    if {$n > 0} {\n\tset Lmarks [lrange $undoMarks 0 [expr {$n - 1}]]\n    } else {\n\tset Lmarks {}\n    }\n    set Rmarks [lrange $undoMarks $n [llength $undoMarks]]\n    foreach Lmark $Lmarks Rmark $Rmarks {\n\tlappend indices [$w index $Lmark] [$w index $Rmark]\n\t$w mark unset $Lmark $Rmark\n    }\n\n    # process ranges to:\n    #   - remove those already fully included in another range\n    #   - merge overlapping ranges\n    set ind [lsort -dictionary -stride 2 $indices]\n    set indices {}\n\n    for {set i 0} {$i < $nUndoMarks} {incr i 2} {\n\tset il1 [lindex $ind $i]\n\tset ir1 [lindex $ind [expr {$i + 1}]]\n\tlappend indices $il1 $ir1\n\n\tfor {set j [expr {$i + 2}]} {$j < $nUndoMarks} {incr j 2} {\n\t    set il2 [lindex $ind $j]\n\t    set ir2 [lindex $ind [expr {$j + 1}]]\n\n\t    if {[$w compare $il2 > $ir1]} {\n\t\t# second range starts after the end of first range\n\t\t# -> further second ranges do not need to be considered\n\t\t#    because ranges were sorted by increasing first index\n\t\tset j $nUndoMarks\n\t    } else {\n\t\tif {[$w compare $ir2 > $ir1]} {\n\t\t    # second range overlaps first range\n\t\t    # -> merge them into a single range\n\t\t    set indices [lreplace $indices end-1 end]\n\t\t    lappend indices $il1 $ir2\n\t\t} else {\n\t\t    # second range is fully included in first range\n\t\t    # -> ignore it\n\t\t}\n\t\t# in both cases above, the second range shall be\n\t\t# trimmed out from the list of ranges\n\t\tset ind [lreplace $ind $j [expr {$j + 1}]]\n\t\tincr j -2\n\t\tincr nUndoMarks -2\n\t    }\n\t}\n    }\n\n    return $indices\n}\n"
  },
  {
    "path": "library/tk.tcl",
    "content": "# tk.tcl --\n#\n# Initialization script normally executed in the interpreter for each Tk-based\n# application.  Arranges class bindings for widgets.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Ajuba Solutions.\n#\n# See the file \"license.terms\" for information on usage and redistribution of\n# this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n# Verify that we have Tk binary and script components from the same release\npackage require -exact tk  9.1a2\n\f\n# Create a ::tk namespace\nnamespace eval ::tk {\n    # Set up the msgcat commands\n    namespace eval msgcat {\n\tnamespace export mc mcmax\n\tif {[interp issafe] || [catch {package require msgcat}]} {\n\t    # The msgcat package is not available.  Supply our own\n\t    # minimal replacement.\n\t    proc mc {src args} {\n\t\treturn [format $src {*}$args]\n\t    }\n\t    proc mcmax {args} {\n\t\tset max 0\n\t\tforeach string $args {\n\t\t    set len [string length $string]\n\t\t    if {$len>$max} {\n\t\t\tset max $len\n\t\t    }\n\t\t}\n\t\treturn $max\n\t    }\n\t} else {\n\t    # Get the commands from the msgcat package that Tk uses.\n\t    namespace import ::msgcat::mc\n\t    namespace import ::msgcat::mcmax\n\t    ::msgcat::mcload [file join $::tk_library msgs]\n\t}\n    }\n    namespace import ::tk::msgcat::*\n}\n# and a ::ttk namespace\nnamespace eval ::ttk {\n    if {$::tk_library ne \"\"} {\n\t# avoid file join to work in safe interps, but this is also x-plat ok\n\tvariable library $::tk_library/ttk\n    }\n}\n\n# Add Ttk & Tk's directory to the end of the auto-load search path, if it\n# isn't already on the path:\n\nif {[info exists ::auto_path] && ($::tk_library ne \"\")\n    && ($::tk_library ni $::auto_path)\n} then {\n    lappend ::auto_path $::tk_library $::ttk::library\n}\n\n# Turn off strict Motif look and feel as a default.\n\nset ::tk_strictMotif 0\n\n# Turn on useinputmethods (X Input Methods) by default.\n# We catch this because safe interpreters may not allow the call.\n\ncatch {tk useinputmethods 1}\n\f\n# ::tk::PlaceWindow --\n#   place a toplevel at a particular position\n# Arguments:\n#   toplevel\tname of toplevel window\n#   ?placement?\tpointer ?center? ; places $w centered on the pointer\n#\t\twidget widgetPath ; centers $w over widget_name\n#\t\tdefaults to placing toplevel in the middle of the screen\n#   ?anchor?\tcenter or widgetPath\n# Results:\n#   Returns nothing\n#\nproc ::tk::PlaceWindow {w {place \"\"} {anchor \"\"}} {\n    wm withdraw $w\n    update idletasks\n\n    set screenWidth [winfo screenwidth $w]\n    set screenHeight [winfo screenheight $w]\n    set width [winfo reqwidth $w]\n    set height [winfo reqheight $w]\n    ## \"wm geometry\" operates in window manager coordinates and thus includes\n    ## a possible decoration frame and the title bar.\n    set frameWidth [WMFrameWidth]\n    set titleHeight [WMTitleHeight]\n    set constrain 0\n    if {$width + 2*$frameWidth > $screenWidth} {\n\tset width [expr {$screenWidth - 2*$frameWidth}]\n\tset constrain 1\n    }\n    if {$height + $titleHeight + $frameWidth > $screenHeight} {\n\tset height [expr {$screenHeight - $titleHeight - $frameWidth}]\n\tset constrain 1\n    }\n\n    set checkBounds 1\n    if {$place eq \"\"} {\n\tset x [expr {($screenWidth - $width)/2}]\n\tset y [expr {($screenHeight - $height)/2}]\n\tset checkBounds 0\n    } elseif {[string equal -length [string length $place] $place \"pointer\"]} {\n\t## place at POINTER (centered if $anchor == center)\n\tif {[string equal -length [string length $anchor] $anchor \"center\"]} {\n\t    set x [expr {[winfo pointerx $w] - $width/2}]\n\t    set y [expr {[winfo pointery $w] - $height/2}]\n\t} else {\n\t    set x [winfo pointerx $w]\n\t    set y [winfo pointery $w]\n\t}\n    } elseif {[string equal -length [string length $place] $place \"widget\"] && \\\n\t    [winfo exists $anchor] && [winfo ismapped $anchor]} {\n\t## center about WIDGET $anchor, widget must be mapped\n\tset x [expr {[winfo rootx $anchor] +\n\t\t([winfo width $anchor] - $width)/2}]\n\tset y [expr {[winfo rooty $anchor] +\n\t\t([winfo height $anchor] - $height)/2}]\n    } else {\n\tset x [expr {($screenWidth - $width)/2}]\n\tset y [expr {($screenHeight - $height)/2}]\n\tset checkBounds 0\n    }\n\n    if {$checkBounds} {\n\tset vrootX [winfo vrootx $w]; set vrootWidth [winfo vrootwidth $w]\n\tif {$x + $width + $frameWidth > $vrootX + $vrootWidth} {\n\t    set x [expr {$vrootX + $vrootWidth - $width - $frameWidth}]\n\t}\n\tif {$x < $vrootX + $frameWidth} {\n\t    set x [expr {$vrootX + $frameWidth}]\n\t}\n\n\tset vrootY [winfo vrooty $w]; set vrootHeight [winfo vrootheight $w]\n\tif {$y + $height + $frameWidth > $vrootY + $vrootHeight} {\n\t    set y [expr {$vrootY + $vrootHeight - $height - $frameWidth}]\n\t}\n\tif {$y < $vrootY + $titleHeight} {\n\t    set y [expr {$vrootY + $titleHeight}]\n\t}\n\n\tif {[tk windowingsystem] eq \"aqua\"} {\n\t    # Avoid the native menu bar which sits on top of everything.\n\t    if {$y < 22 + $titleHeight} {\n\t\tset y [expr {22 + $titleHeight}]\n\t    }\n\t}\n    }\n\n    wm maxsize $w [winfo vrootwidth $w] [winfo vrootheight $w]\n    ## Set geometry and show window\n    set geom [expr {$constrain ? \"${width}x${height}\" : \"\"}]\n    incr x -$frameWidth\n    incr y -$titleHeight\n    append geom +$x+$y\n    wm geometry $w $geom\n    wm deiconify $w\n}\n\f\n# ::tk::SetFocusGrab --\n#   swap out current focus and grab temporarily (for dialogs)\n# Arguments:\n#   grab\tnew window to grab\n#   focus\twindow to give focus to\n# Results:\n#   Returns nothing\n#\nproc ::tk::SetFocusGrab {grab {focus {}}} {\n    set index \"$grab,$focus\"\n    upvar ::tk::FocusGrab($index) data\n\n    lappend data [focus]\n    set oldGrab [grab current $grab]\n    lappend data $oldGrab\n    if {[winfo exists $oldGrab]} {\n\tlappend data [grab status $oldGrab]\n    }\n    # The \"grab\" command will fail if another application\n    # already holds the grab.  So catch it.\n    catch {grab $grab}\n    if {[winfo exists $focus]} {\n\tfocus $focus\n    }\n}\n\n# ::tk::RestoreFocusGrab --\n#   restore old focus and grab (for dialogs)\n# Arguments:\n#   grab\twindow that had taken grab\n#   focus\twindow that had taken focus\n#   destroy\tdestroy|withdraw - how to handle the old grabbed window\n# Results:\n#   Returns nothing\n#\nproc ::tk::RestoreFocusGrab {grab focus {destroy destroy}} {\n    set index \"$grab,$focus\"\n    if {[info exists ::tk::FocusGrab($index)]} {\n\tforeach {oldFocus oldGrab oldStatus} $::tk::FocusGrab($index) { break }\n\tunset ::tk::FocusGrab($index)\n    } else {\n\tset oldGrab \"\"\n    }\n\n    catch {focus $oldFocus}\n    grab release $grab\n    if {[winfo exists $grab]} {\n\tif {$destroy eq \"withdraw\"} {\n\t    wm withdraw $grab\n\t} else {\n\t    destroy $grab\n\t}\n    }\n    if {[winfo exists $oldGrab] && [winfo ismapped $oldGrab]} {\n\t# The \"grab\" command will fail if another application\n\t# already holds the grab on a window with the same name.\n\t# So catch it. See [7447ed20ec] for an example.\n\tif {$oldStatus eq \"global\"} {\n\t    catch {grab -global $oldGrab}\n\t} else {\n\t    catch {grab $oldGrab}\n\t}\n    }\n}\n\f\n# ::tk::GetSelection --\n#   This tries to obtain the default selection.  On Unix, we first try\n#   and get a UTF8_STRING, a type supported by modern Unix apps for\n#   passing Unicode data safely.  We fall back on the default STRING\n#   type otherwise.  On Windows, only the STRING type is necessary.\n# Arguments:\n#   w\tThe widget for which the selection will be retrieved.\n#\tImportant for the -displayof property.\n#   sel\tThe source of the selection (PRIMARY or CLIPBOARD)\n# Results:\n#   Returns the selection, or an error if none could be found\n#\nif {[tk windowingsystem] ne \"win32\"} {\n    proc ::tk::GetSelection {w {sel PRIMARY}} {\n\tif {[catch {\n\t    selection get -displayof $w -selection $sel -type UTF8_STRING\n\t} txt] && [catch {\n\t    selection get -displayof $w -selection $sel\n\t} txt]} then {\n\t    return -code error -errorcode {TK SELECTION NONE} \\\n\t\t\"could not find default selection\"\n\t} else {\n\t    return $txt\n\t}\n    }\n} else {\n    proc ::tk::GetSelection {w {sel PRIMARY}} {\n\tif {[catch {\n\t    selection get -displayof $w -selection $sel\n\t} txt]} then {\n\t    return -code error -errorcode {TK SELECTION NONE} \\\n\t\t\"could not find default selection\"\n\t} else {\n\t    return $txt\n\t}\n    }\n}\n\f\n# ::tk::ScreenChanged --\n# This procedure is invoked by the binding mechanism whenever the\n# \"current\" screen is changing.  The procedure does two things.\n# First, it uses \"upvar\" to make variable \"::tk::Priv\" point at an\n# array variable that holds state for the current display.  Second,\n# it initializes the array if it didn't already exist.\n#\n# Arguments:\n# screen -\t\tThe name of the new screen.\n\nproc ::tk::ScreenChanged screen {\n    # Extract the display name.\n    set disp [string range $screen 0 [string last . $screen]-1]\n\n    # Ensure that namespace separators never occur in the display name (as\n    # they cause problems in variable names). Double-colons exist in some VNC\n    # display names. [Bug 2912473]\n    set disp [string map {:: _doublecolon_} $disp]\n\n    uplevel #0 [list upvar #0 ::tk::Priv.$disp ::tk::Priv]\n    variable ::tk::Priv\n\n    if {[info exists Priv]} {\n\tset Priv(screen) $screen\n\treturn\n    }\n    array set Priv {\n\tactiveMenu\t{}\n\tactiveItem\t{}\n\tafterId\t\t{}\n\tbuttons\t\t0\n\tbuttonWindow\t{}\n\tdragging\t0\n\tfocus\t\t{}\n\tgrab\t\t{}\n\tinitPos\t\t{}\n\tinMenubutton\t{}\n\tlistboxPrev\t{}\n\tmenuBar\t\t{}\n\tmouseMoved\t0\n\toldGrab\t\t{}\n\tpopup\t\t{}\n\tpostedMb\t{}\n\tpressX\t\t0\n\tpressY\t\t0\n\tprevPos\t\t0\n\tselectMode\tchar\n    }\n    set Priv(screen) $screen\n    set Priv(tearoff) [string equal [tk windowingsystem] \"x11\"]\n    set Priv(window) {}\n}\n\n# Do initial setup for Priv, so that it is always bound to something\n# (otherwise, if someone references it, it may get set to a non-upvar-ed\n# value, which will cause trouble later).\n\ntk::ScreenChanged [winfo screen .]\n\f\n# ::tk::EventMotifBindings --\n# This procedure is invoked as a trace whenever ::tk_strictMotif is\n# changed.  It is used to turn on or turn off the motif virtual\n# bindings.\n#\n# Arguments:\n# n1 - the name of the variable being changed (\"::tk_strictMotif\").\n\nproc ::tk::EventMotifBindings {n1 dummy dummy} {\n    upvar $n1 name\n\n    if {$name} {\n\tset op delete\n    } else {\n\tset op add\n    }\n\n    event $op <<Cut>> <Control-w> <Control-Lock-W> <Shift-Delete>\n    event $op <<Copy>> <Meta-w> <Meta-Lock-W> <Control-Insert>\n    event $op <<Paste>> <Control-y> <Control-Lock-Y> <Shift-Insert>\n    event $op <<PrevChar>> <Control-b> <Control-Lock-B>\n    event $op <<NextChar>> <Control-f> <Control-Lock-F>\n    event $op <<PrevLine>> <Control-p> <Control-Lock-P>\n    event $op <<NextLine>> <Control-n> <Control-Lock-N>\n    event $op <<LineStart>> <Control-a> <Control-Lock-A>\n    event $op <<LineEnd>> <Control-e> <Control-Lock-E>\n    event $op <<SelectPrevChar>> <Control-B> <Control-Lock-b>\n    event $op <<SelectNextChar>> <Control-F> <Control-Lock-f>\n    event $op <<SelectPrevLine>> <Control-P> <Control-Lock-p>\n    event $op <<SelectNextLine>> <Control-N> <Control-Lock-n>\n    event $op <<SelectLineStart>> <Control-A> <Control-Lock-a>\n    event $op <<SelectLineEnd>> <Control-E> <Control-Lock-e>\n}\n\f\n#----------------------------------------------------------------------\n# Define common dialogs on platforms where they are not implemented\n# using compiled code.\n#----------------------------------------------------------------------\n\nif {![llength [info commands tk_chooseColor]]} {\n    proc ::tk_chooseColor {args} {\n\treturn [::tk::dialog::color:: {*}$args]\n    }\n}\nif {![llength [info commands tk_getOpenFile]]} {\n    proc ::tk_getOpenFile {args} {\n\tif {$::tk_strictMotif} {\n\t    return [::tk::MotifFDialog open {*}$args]\n\t} else {\n\t    return [::tk::dialog::file:: open {*}$args]\n\t}\n    }\n}\nif {![llength [info commands tk_getSaveFile]]} {\n    proc ::tk_getSaveFile {args} {\n\tif {$::tk_strictMotif} {\n\t    return [::tk::MotifFDialog save {*}$args]\n\t} else {\n\t    return [::tk::dialog::file:: save {*}$args]\n\t}\n    }\n}\nif {![llength [info commands tk_messageBox]]} {\n    proc ::tk_messageBox {args} {\n\treturn [::tk::MessageBox {*}$args]\n    }\n}\nif {![llength [info command tk_chooseDirectory]]} {\n    proc ::tk_chooseDirectory {args} {\n\treturn [::tk::dialog::file::chooseDir:: {*}$args]\n    }\n}\n\f\n#----------------------------------------------------------------------\n# Define the set of common virtual events.\n#----------------------------------------------------------------------\n\nevent add <<ContextMenu>>\t<Button-3>\nevent add <<PasteSelection>>\t<ButtonRelease-2>\n\nswitch -exact -- [tk windowingsystem] {\n    \"x11\" {\n\tevent add <<Cut>>\t\t<Control-x> <F20> <Control-Lock-X>\n\tevent add <<Copy>>\t\t<Control-c> <F16> <Control-Lock-C>\n\tevent add <<Paste>>\t\t<Control-v> <F18> <Control-Lock-V>\n\tevent add <<Undo>>\t\t<Control-z> <Control-Lock-Z> <Undo>\n\tevent add <<Redo>>\t\t<Control-Z> <Control-Lock-z> <Redo>\n\tevent add <<SelectAll>>\t\t<Control-/>\n\tevent add <<SelectNone>>\t<Control-backslash>\n\tevent add <<NextChar>>\t\t<Right>\n\tevent add <<SelectNextChar>>\t<Shift-Right>\n\tevent add <<PrevChar>>\t\t<Left>\n\tevent add <<SelectPrevChar>>\t<Shift-Left>\n\tevent add <<NextWord>>\t\t<Control-Right>\n\tevent add <<SelectNextWord>>\t<Control-Shift-Right>\n\tevent add <<PrevWord>>\t\t<Control-Left>\n\tevent add <<SelectPrevWord>>\t<Control-Shift-Left>\n\tevent add <<LineStart>>\t\t<Home>\n\tevent add <<SelectLineStart>>\t<Shift-Home>\n\tevent add <<LineEnd>>\t\t<End>\n\tevent add <<SelectLineEnd>>\t<Shift-End>\n\tevent add <<PrevLine>>\t\t<Up>\n\tevent add <<NextLine>>\t\t<Down>\n\tevent add <<SelectPrevLine>>\t<Shift-Up>\n\tevent add <<SelectNextLine>>\t<Shift-Down>\n\tevent add <<PrevPara>>\t\t<Control-Up>\n\tevent add <<NextPara>>\t\t<Control-Down>\n\tevent add <<SelectPrevPara>>\t<Control-Shift-Up>\n\tevent add <<SelectNextPara>>\t<Control-Shift-Down>\n\tevent add <<ToggleSelection>>\t<Control-Button-1>\n\n\t# Some OS's define a goofy (as in, not <Shift-Tab>) keysym that is\n\t# returned when the user presses <Shift-Tab>. In order for tab\n\t# traversal to work, we have to add these keysyms to the PrevWindow\n\t# event. We use catch just in case the keysym isn't recognized.\n\n\t# This is needed for XFree86 systems\n\tcatch { event add <<PrevWindow>> <ISO_Left_Tab> }\n\tcatch {\n\t    event add <<Cut>> <XF86Cut>\n\t    event add <<Copy>> <XF86Copy>\n\t    event add <<Paste>> <XF86Paste>\n\t}\n\t# This seems to be correct on *some* HP systems.\n\tcatch { event add <<PrevWindow>> <hpBackTab> }\n\n\ttrace add variable ::tk_strictMotif write ::tk::EventMotifBindings\n\tset ::tk_strictMotif $::tk_strictMotif\n\t# On unix, we want to always display entry/text selection,\n\t# regardless of which window has focus\n\tset ::tk::AlwaysShowSelection 1\n    }\n    \"win32\" {\n\tevent add <<Cut>>\t\t<Control-x> <Shift-Delete> <Control-Lock-X> <XF86Cut>\n\tevent add <<Copy>>\t\t<Control-c> <Control-Insert> <Control-Lock-C> <XF86Copy>\n\tevent add <<Paste>>\t\t<Control-v> <Shift-Insert> <Control-Lock-V> <XF86Paste>\n\tevent add <<Undo>>\t\t<Control-z> <Control-Lock-Z> <Undo>\n\tevent add <<Redo>>\t\t<Control-y> <Control-Lock-Y> <Redo>\n\n\tevent add <<SelectAll>>\t\t<Control-/> <Control-a> <Control-Lock-A>\n\tevent add <<SelectNone>>\t<Control-backslash>\n\tevent add <<NextChar>>\t\t<Right>\n\tevent add <<SelectNextChar>>\t<Shift-Right>\n\tevent add <<PrevChar>>\t\t<Left>\n\tevent add <<SelectPrevChar>>\t<Shift-Left>\n\tevent add <<NextWord>>\t\t<Control-Right>\n\tevent add <<SelectNextWord>>\t<Control-Shift-Right>\n\tevent add <<PrevWord>>\t\t<Control-Left>\n\tevent add <<SelectPrevWord>>\t<Control-Shift-Left>\n\tevent add <<LineStart>>\t\t<Home>\n\tevent add <<SelectLineStart>>\t<Shift-Home>\n\tevent add <<LineEnd>>\t\t<End>\n\tevent add <<SelectLineEnd>>\t<Shift-End>\n\tevent add <<PrevLine>>\t\t<Up>\n\tevent add <<NextLine>>\t\t<Down>\n\tevent add <<SelectPrevLine>>\t<Shift-Up>\n\tevent add <<SelectNextLine>>\t<Shift-Down>\n\tevent add <<PrevPara>>\t\t<Control-Up>\n\tevent add <<NextPara>>\t\t<Control-Down>\n\tevent add <<SelectPrevPara>>\t<Control-Shift-Up>\n\tevent add <<SelectNextPara>>\t<Control-Shift-Down>\n\tevent add <<ToggleSelection>>\t<Control-Button-1>\n    }\n    \"aqua\" {\n\tevent add <<Cut>>\t\t<Command-x> <F2> <Command-Lock-X> <XF86Cut>\n\tevent add <<Copy>>\t\t<Command-c> <F3> <Command-Lock-C> <XF86Copy>\n\tevent add <<Paste>>\t\t<Command-v> <F4> <Command-Lock-V> <XF86Paste>\n\tevent add <<Clear>>\t\t<Clear>\n\n\t# Official bindings\n\t# See https://support.apple.com/en-us/HT201236\n\tevent add <<SelectAll>>\t\t<Command-a>\n\tevent add <<Undo>>\t\t<Command-Key-z> <Command-Lock-Key-Z> <Undo>\n\tevent add <<Redo>>\t\t<Shift-Command-Key-z> <Shift-Command-Lock-Key-z> <Redo>\n\tevent add <<NextChar>>\t\t<Right> <Control-Key-f> <Control-Lock-Key-F>\n\tevent add <<SelectNextChar>>\t<Shift-Right> <Shift-Control-Key-F> <Shift-Control-Lock-Key-F>\n\tevent add <<PrevChar>>\t\t<Left> <Control-Key-b> <Control-Lock-Key-B>\n\tevent add <<SelectPrevChar>>\t<Shift-Left> <Shift-Control-Key-B> <Shift-Control-Lock-Key-B>\n\tevent add <<NextWord>>\t\t<Option-Right>\n\tevent add <<SelectNextWord>>\t<Shift-Option-Right>\n\tevent add <<PrevWord>>\t\t<Option-Left>\n\tevent add <<SelectPrevWord>>\t<Shift-Option-Left>\n\tevent add <<LineStart>>\t\t<Home> <Command-Left> <Control-a> <Control-Lock-A>\n\tevent add <<SelectLineStart>>\t<Shift-Home> <Shift-Command-Left> <Shift-Control-A> <Shift-Control-Lock-A>\n\tevent add <<LineEnd>>\t\t<End> <Command-Right> <Control-e> <Control-Lock-E>\n\tevent add <<SelectLineEnd>>\t<Shift-End> <Shift-Command-Right> <Shift-Control-E> <Shift-Control-Lock-E>\n\tevent add <<PrevLine>>\t\t<Up> <Control-p> <Control-Lock-P>\n\tevent add <<SelectPrevLine>>\t<Shift-Up> <Shift-Control-P> <Shift-Control-Lock-P>\n\tevent add <<NextLine>>\t\t<Down> <Control-n> <Control-Lock-N>\n\tevent add <<SelectNextLine>>\t<Shift-Down> <Shift-Control-N> <Shift-Control-Lock-N>\n\t# Not official, but logical extensions of above. Also derived from\n\t# bindings present in MS Word on OSX.\n\tevent add <<PrevPara>>\t\t<Option-Up>\n\tevent add <<NextPara>>\t\t<Option-Down>\n\tevent add <<SelectPrevPara>>\t<Shift-Option-Up>\n\tevent add <<SelectNextPara>>\t<Shift-Option-Down>\n\tevent add <<ToggleSelection>>\t<Command-Button-1>\n    }\n}\n\f\n# ----------------------------------------------------------------------\n# Read in files that define all of the class bindings.\n# ----------------------------------------------------------------------\n\nif {$::tk_library ne \"\"} {\n    proc ::tk::SourceLibFile {file} {\n\tnamespace eval :: [list source [file join $::tk_library $file.tcl]]\n    }\n    namespace eval ::tk {\n\n\t# Do not load accessibility.tcl if running in a safe interpreter,\n\t# under XQuartz on macOS, or if Tk on X11 was compiled without\n\t# accessibility support. These cause interpreter failures or Tk to\n\t# crash.\n\tif {![interp issafe] &&\n\t\t!($::tcl_platform(os) eq \"Darwin\" && [tk windowingsystem] eq \"x11\") &&\n\t\t![catch {tk::accessible::check_screenreader} r] &&\n\t\t![string match -nocase \"*warning*\" $r]} {\n\t    SourceLibFile accessibility\n\t}\n\tSourceLibFile fileicon\n\tSourceLibFile icons\n\tSourceLibFile iconbadges\n\tSourceLibFile button\n\tSourceLibFile entry\n\tSourceLibFile listbox\n\tSourceLibFile menu\n\tSourceLibFile panedwindow\n\tSourceLibFile print\n\tSourceLibFile scale\n\tSourceLibFile scrlbar\n\tSourceLibFile spinbox\n\tif {![interp issafe]} {\n\t    SourceLibFile systray\n\t}\n\tSourceLibFile text\n    }\n}\n\n# ----------------------------------------------------------------------\n# Default bindings for keyboard traversal.\n# ----------------------------------------------------------------------\n\nevent add <<PrevWindow>> <Shift-Tab>\nevent add <<NextWindow>> <Tab>\nbind all <<NextWindow>> {tk::TabToWindow [tk_focusNext %W]}\nbind all <<PrevWindow>> {tk::TabToWindow [tk_focusPrev %W]}\n\f\n# ::tk::CancelRepeat --\n# This procedure is invoked to cancel an auto-repeat action described\n# by ::tk::Priv(afterId).  It's used by several widgets to auto-scroll\n# the widget when the mouse is dragged out of the widget with a\n# button pressed.\n#\n# Arguments:\n# None.\n\nproc ::tk::CancelRepeat {} {\n    variable ::tk::Priv\n    after cancel $Priv(afterId)\n    set Priv(afterId) {}\n}\n\f\n## ::tk::MouseWheel $w $dir $amount $factor $units\n\nproc ::tk::MouseWheel {w dir amount {factor -120.0} {units units}} {\n    $w ${dir}view scroll [expr {$amount/$factor}] $units\n}\n\n## ::tk::PreciseScrollDeltas $dxdy\n\nproc ::tk::PreciseScrollDeltas {dxdy} {\n    set deltaX [expr {$dxdy >> 16}]\n    set low [expr {$dxdy & 0xffff}]\n    set deltaY [expr {$low < 0x8000 ? $low : $low - 0x10000}]\n    return [list $deltaX $deltaY]\n}\n\n## Helper for smooth scrolling of widgets that support xview moveto and\n## yview moveto.\n\nproc ::tk::ScrollByPixels {w deltaX deltaY} {\n    set fracX [lindex [$w xview] 0]\n    set fracY [lindex [$w yview] 0]\n    set width [expr {1.0 * [winfo width $w]}]\n    set height [expr {1.0 * [winfo height $w]}]\n    $w xview moveto [expr {$fracX - $deltaX / $width}]\n    $w yview moveto [expr {$fracY - $deltaY / $height}]\n}\n\n# ::tk::TabToWindow --\n# This procedure moves the focus to the given widget.\n# It sends a <<TraverseOut>> virtual event to the previous focus window,\n# if any, before changing the focus, and a <<TraverseIn>> event\n# to the new focus window afterwards.\n#\n# Arguments:\n# w - Window to which focus should be set.\n\nproc ::tk::TabToWindow {w} {\n    set focus [focus]\n    if {$focus ne \"\"} {\n\tevent generate $focus <<TraverseOut>>\n    }\n    focus $w\n    event generate $w <<TraverseIn>>\n}\n\f\n# ::tk::UnderlineAmpersand --\n#\tThis procedure takes some text with ampersand and returns text w/o\n#\tampersand and position of the ampersand.  Double ampersands are\n#\tconverted to single ones.  Position returned is -1 when there is no\n#\tampersand.\n#\nproc ::tk::UnderlineAmpersand {text} {\n    set s [string map {&& & & \\ufeff} $text]\n    set idx [string first \\ufeff $s]\n    return [list [string map {\\ufeff {}} $s] $idx]\n}\n\n# ::tk::SetAmpText --\n#\tGiven widget path and text with \"magic ampersands\", sets -text and\n#\t-underline options for the widget\n#\nproc ::tk::SetAmpText {widget text} {\n    lassign [UnderlineAmpersand $text] newtext under\n    $widget configure -text $newtext -underline $under\n}\n\n# ::tk::AmpWidget --\n#\tCreates new widget, turning -text option into -text and -underline\n#\toptions, returned by ::tk::UnderlineAmpersand.\n#\nproc ::tk::AmpWidget {class path args} {\n    set options {}\n    foreach {opt val} $args {\n\tif {$opt eq \"-text\"} {\n\t    lassign [UnderlineAmpersand $val] newtext under\n\t    lappend options -text $newtext -underline $under\n\t} else {\n\t    lappend options $opt $val\n\t}\n    }\n    set result [$class $path {*}$options]\n    if {[string match \"*button\" $class]} {\n\tbind $path <<AltUnderlined>> [list $path invoke]\n    }\n    return $result\n}\n\n# ::tk::AmpMenuArgs --\n#\tProcesses arguments for a menu entry, turning -label option into\n#\t-label and -underline options, returned by ::tk::UnderlineAmpersand.\n#      The cmd argument is supposed to be either \"add\" or \"entryconfigure\"\n#\nproc ::tk::AmpMenuArgs {widget cmd type args} {\n    set options {}\n    foreach {opt val} $args {\n\tif {$opt eq \"-label\"} {\n\t    lassign [UnderlineAmpersand $val] newlabel under\n\t    lappend options -label $newlabel -underline $under\n\t} else {\n\t    lappend options $opt $val\n\t}\n    }\n    $widget $cmd $type {*}$options\n}\n\n# ::tk::FindAltKeyTarget --\n#\tSearch recursively through the hierarchy of visible widgets to find\n#\tbutton or label which has $char as underlined character.\n#\nproc ::tk::FindAltKeyTarget {path char} {\n    set class [winfo class $path]\n    if {$class in {\n\tButton Checkbutton Label Radiobutton\n\tTButton TCheckbutton TLabel TRadiobutton\n    } && ([$path cget -underline] >= 0) && [string equal -nocase $char \\\n\t    [string index [$path cget -text] [$path cget -underline]]]} {\n\treturn $path\n    }\n    set subwins [concat [grid content $path] [pack content $path] \\\n\t    [place content $path]]\n    if {$class eq \"Canvas\"} {\n\tforeach item [$path find all] {\n\t    if {[$path type $item] eq \"window\"} {\n\t\tset w [$path itemcget $item -window]\n\t\tif {$w ne \"\"} {lappend subwins $w}\n\t    }\n\t}\n    } elseif {$class eq \"Text\"} {\n\tlappend subwins {*}[$path window names]\n    }\n    foreach child $subwins {\n\tset target [FindAltKeyTarget $child $char]\n\tif {$target ne \"\"} {\n\t    return $target\n\t}\n    }\n}\n\n# ::tk::AltKeyInDialog --\n#\t<Alt-Key> event handler for standard dialogs. Sends <<AltUnderlined>>\n#\tto button or label which has appropriate underlined character.\n#\nproc ::tk::AltKeyInDialog {path key} {\n    set target [FindAltKeyTarget $path $key]\n    if {$target ne \"\"} {\n\tevent generate $target <<AltUnderlined>>\n    }\n}\n\n# ::tk::WMFrameWidth --\n#\tReturn window manager frame width if known, else 0.\n#\nproc ::tk::WMFrameWidth {} {\n    set frameWidth 0\n    # In SDL2 Tk, the frame width is a number between 6 and 27, depending on\n    # the screen's DPI value.\n    if {[info exists ::tk::sdltk] && $::tk::sdltk} {\n\tvariable dpi\n\tif {$dpi < 140} {\n\t    set frameWidth 6\n\t} elseif {$dpi < 190} {\n\t    set frameWidth 9\n\t} elseif {$dpi < 240} {\n\t    set frameWidth 12\n\t} elseif {$dpi < 320} {\n\t    set frameWidth 15\n\t} elseif {$dpi < 420} {\n\t    set frameWidth 21\n\t} else {\n\t    set frameWidth 27\n\t}\n    }\n    return $frameWidth\n}\n\n# ::tk::WMTitleHeight --\n#\tReturn window manager height of window title bar if known, else 0.\n#\nproc ::tk::WMTitleHeight {} {\n    set titleHeight 0\n    # In SDL2 Tk, the title height is a number between 20 and 78, depending on\n    # the screen's DPI value.\n    if {[info exists ::tk::sdltk] && $::tk::sdltk} {\n\tvariable dpi\n\tif {$dpi < 140} {\n\t    set titleHeight 20\n\t} elseif {$dpi < 190} {\n\t    set titleHeight 30\n\t} elseif {$dpi < 240} {\n\t    set titleHeight 38\n\t} elseif {$dpi < 320} {\n\t    set titleHeight 46\n\t} elseif {$dpi < 420} {\n\t    set titleHeight 60\n\t} else {\n\t    set titleHeight 78\n\t}\n    }\n    return $titleHeight\n}\n\n# ::tk::mcmaxamp --\n#\tReplacement for mcmax, used for texts with \"magic ampersand\" in it.\n#\nproc ::tk::mcmaxamp {args} {\n    set maxlen 0\n    foreach arg $args {\n\t# Should we run [mc] in caller's namespace?\n\tlassign [UnderlineAmpersand [mc $arg]] msg\n\tset length [string length $msg]\n\tif {$length > $maxlen} {\n\t    set maxlen $length\n\t}\n    }\n    return $maxlen\n}\n\f\nif {[tk windowingsystem] eq \"aqua\"} {\n    #stub procedures to respond to \"do script\" Apple Events\n    proc ::tk::mac::DoScriptFile {file} {\n\tuplevel #0 source $file\n    }\n    proc ::tk::mac::DoScriptText {script} {\n\tuplevel #0 $script\n    }\n    #This procedure is required to silence warnings generated\n    #by inline AppleScript execution.\n    proc ::tk::mac::GetDynamicSdef {} {\n\tputs \"\"\n    }\n}\n\nif {[info commands ::tk::endOfWord] eq \"\"} {\n    proc ::tk::endOfWord {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t}\n\tset start [tcl_endOfWord $str $start]\n\tif {$start < 0} {\n\t    set start \"\"\n\t}\n\treturn $start\n    }\n}\nif {[info commands ::tk::startOfNextWord] eq \"\"} {\n    proc ::tk::startOfNextWord {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t}\n\tset start [tcl_startOfNextWord $str $start]\n\tif {$start < 0} {\n\t    set start \"\"\n\t}\n\treturn $start\n    }\n}\nif {[info commands ::tk::startOfPreviousWord] eq \"\"} {\n    proc ::tk::startOfPreviousWord {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t}\n\tset start [tcl_startOfPreviousWord $str $start]\n\tif {$start < 0} {\n\t    set start \"\"\n\t}\n\treturn $start\n    }\n}\nif {[info commands ::tk::wordBreakBefore] eq \"\"} {\n    proc ::tk::wordBreakBefore {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t}\n\tset start [tcl_wordBreakBefore $str $start]\n\tif {$start < 0} {\n\t    set start \"\"\n\t}\n\treturn $start\n    }\n}\nif {[info commands ::tk::wordBreakAfter] eq \"\"} {\n    proc ::tk::wordBreakAfter {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t}\n\tset start [tcl_wordBreakAfter $str $start]\n\tif {$start < 0} {\n\t    set start \"\"\n\t}\n\treturn $start\n    }\n}\nif {[info commands ::tk::endOfCluster] eq \"\"} {\n    proc ::tk::endOfCluster {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t} elseif {$start eq \"end\"} {\n\t    set start [expr {[string length $str]-1}]\n\t} elseif {[string match end-* $start]} {\n\t    set start [expr {[string length $str]-1-[string range $start 4 end]}]\n\t} elseif {$start >= [string length $str]} {\n\t    return \"\"\n\t}\n\tincr start\n\treturn $start\n    }\n}\nif {[info commands ::tk::startOfCluster] eq \"\"} {\n    proc ::tk::startOfCluster {str start {locale {}}} {\n\tif {$start < 0} {\n\t    set start -1\n\t} elseif {$start eq \"end\"} {\n\t    set start [expr {[string length $str]-1}]\n\t} elseif {[string match end-* $start]} {\n\t    set start [expr {[string length $str]-1-[string range $start 4 end]}]\n\t} elseif {$start >= [string length $str]} {\n\t    return [string length $str]\n\t}\n\tif {$start < 0} {\n\t    return \"\"\n\t}\n\treturn $start\n    }\n}\n\n# Create a dictionary to store the starting index of the IME marked\n# text in an Entry or Text widget.\n\nset ::tk::Priv(IMETextMark) [dict create]\n\n# Scale the default parameters of the panedwindow sash\noption add *Panedwindow.handlePad\t6p widgetDefault\noption add *Panedwindow.handleSize\t6p widgetDefault\noption add *Panedwindow.sashWidth\t2.25p widgetDefault\n\n# Scale the default size of the scale widget and its slider\noption add *Scale.length\t\t75p widgetDefault\noption add *Scale.sliderLength\t\t22.5p widgetDefault\noption add *Scale.width\t\t\t11.25p widgetDefault\n\n# Scale the default scrollbar width on X11\nif {[tk windowingsystem] eq \"x11\"} {\n    option add *Scrollbar.width\t\t8.25p widgetDefault\n}\n\n# Run the Ttk themed widget set initialization\nif {$::ttk::library ne \"\"} {\n    uplevel \\#0 [list source $::ttk::library/ttk.tcl]\n}\n\n\f\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "library/tkfbox.tcl",
    "content": "# tkfbox.tcl --\n#\n#\tImplements the \"TK\" standard file selection dialog box.  This dialog\n#\tbox is used on the Unix platforms whenever the tk_strictMotif flag is\n#\tnot set.\n#\n#\tThe \"TK\" standard file selection dialog box is similar to the file\n#\tselection dialog box on Win95(TM).  The user can navigate the\n#\tdirectories by clicking on the folder icons or by selecting the\n#\t\"Directory\" option menu.  The user can select files by clicking on the\n#\tfile icons or by entering a filename in the \"Filename:\" entry.\n#\n# Copyright © 1994-1998 Sun Microsystems, Inc.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\nnamespace eval ::tk::dialog {}\nnamespace eval ::tk::dialog::file {\n    namespace import -force ::tk::msgcat::*\n    variable showHiddenBtn 0\n    variable showHiddenVar 1\n\n    # Based on Vimix/16/actions/go-up.svg\n    # See https://github.com/vinceliuice/vimix-icon-theme\n    variable updirImageData {\n\t<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\t<svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n\t <path d=\"m7 14v-9l-4 4-1-1 6-6 6 6-1 1-4-4v9z\" fill=\"#000000\"/>\n\t</svg>\n    }\n\n    proc UpdateUpdirImageData {} {\n\tvariable updirImageData\n\tset idx1 [string first \"#000000\" $updirImageData]\n\tset idx2 [expr {$idx1 + 6}]\n\n\tset fgColor [ttk::style lookup . -foreground {} black]\n\tlassign [winfo rgb . $fgColor] r g b\n\tset fgColor [format \"#%02x%02x%02x\" \\\n\t\t[expr {$r >> 8}] [expr {$g >> 8}] [expr {$b >> 8}]]\n\n\treturn [string replace $updirImageData $idx1 $idx2 $fgColor]\n    }\n\n    # Based on https://icons8.com/icon/JXYalxb9XWWd/folder\n    variable folderImageData {\n\t<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\t<svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n\t <path d=\"m0.5 13.5v-12h4.293l2 2h8.707v10z\" fill=\"#59afff\"/>\n\t <path d=\"m4.586 2 2 2h8.414v9h-14v-11h3.586m0.414-1h-5v13h16v-11h-9l-2-2z\" fill=\"#2d8cff\"/>\n\t <path d=\"m0.5 14.5v-10h4.618l2-1h8.382v11z\" fill=\"#8cc5ff\"/>\n\t <path d=\"m15 4v10h-14v-9h4.236l0.211-0.106 1.789-0.894h7.764m1-1h-9l-2 1h-5v11h16z\" fill=\"#2d8cff\"/>\n\t</svg>\n    }\n\n    # Based on https://icons8.com/icon/mEF_vyjYlnE3/file\n    variable fileImageData {\n\t<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\t<svg width=\"16\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n\t <path d=\"m2 1h8l4 4v11h-12z\" fill=\"#808080\"/>\n\t <path d=\"m3 2h6.5l3.5 3.5v9.5h-10z\" fill=\"#f0f0f0\"/>\n\t <path d=\"m9 1v5h5v-1h-4v-4h-1z\" fill=\"#808080\"/>\n\t</svg>\n    }\n\n    # Create the images if they did not already exist.\n    if {![info exists ::tk::Priv(updirImage)] ||\n\t    $::tk::Priv(updirImage) ni [image names]} {\n\tset ::tk::Priv(updirImage)  [image create photo \\\n\t\t-format $::tk::svgFmt -data [UpdateUpdirImageData]]\n\n\tif {\"TkFileDialog\" ni [bindtags .]} {\n\t    bindtags . [linsert [bindtags .] 1 TkFileDialog]\n\t    bind TkFileDialog <<ThemeChanged>> {\n\t\tif {$::tk::Priv(updirImage) in [image names]} {\n\t\t    $::tk::Priv(updirImage) configure \\\n\t\t\t    -data [::tk::dialog::file::UpdateUpdirImageData]\n\t\t}\n\t    }\n\t}\n    }\n    if {![info exists ::tk::Priv(folderImage)] ||\n\t    $::tk::Priv(folderImage) ni [image names]} {\n\tset ::tk::Priv(folderImage) [image create photo \\\n\t\t-format $::tk::svgFmt -data $folderImageData]\n    }\n    if {![info exists ::tk::Priv(fileImage)] ||\n\t    $::tk::Priv(fileImage) ni [image names]} {\n\tset ::tk::Priv(fileImage)   [image create photo \\\n\t\t-format $::tk::svgFmt -data $fileImageData]\n    }\n}\n\n# ::tk::dialog::file:: --\n#\n#\tImplements the TK file selection dialog.  This dialog is used when the\n#\ttk_strictMotif flag is set to false.  This procedure shouldn't be\n#\tcalled directly.  Call tk_getOpenFile or tk_getSaveFile instead.\n#\n# Arguments:\n#\ttype\t\t\"open\" or \"save\"\n#\targs\t\tOptions parsed by the procedure.\n#\n\nproc ::tk::dialog::file:: {type args} {\n    variable ::tk::Priv\n    variable showHiddenBtn\n    set dataName __tk_filedialog\n    upvar ::tk::dialog::file::$dataName data\n\n    Config $dataName $type $args\n\n    if {$data(-parent) eq \".\"} {\n\tset w .$dataName\n    } else {\n\tset w $data(-parent).$dataName\n    }\n\n    # (re)create the dialog box if necessary\n    #\n    if {![winfo exists $w]} {\n\tCreate $w TkFDialog\n    } elseif {[winfo class $w] ne \"TkFDialog\"} {\n\tdestroy $w\n\tCreate $w TkFDialog\n    } else {\n\tset data(dirMenuBtn) $w.contents.f1.menu\n\tset data(dirMenu) $w.contents.f1.menu.menu\n\tset data(upBtn) $w.contents.f1.up\n\tset data(icons) $w.contents.icons\n\tset data(ent) $w.contents.f2.ent\n\tset data(typeMenuLab) $w.contents.f2.lab2\n\tset data(typeMenuBtn) $w.contents.f2.menu\n\tset data(typeMenu) $data(typeMenuBtn).m\n\tset data(okBtn) $w.contents.f2.ok\n\tset data(cancelBtn) $w.contents.f2.cancel\n\tset data(hiddenBtn) $w.contents.f2.hidden\n\tSetSelectMode $w $data(-multiple)\n    }\n    if {$showHiddenBtn} {\n\t$data(hiddenBtn) configure -state normal\n\tgrid $data(hiddenBtn)\n    } else {\n\t$data(hiddenBtn) configure -state disabled\n\tgrid remove $data(hiddenBtn)\n    }\n\n    # Make sure subseqent uses of this dialog are independent [Bug 845189]\n    unset -nocomplain data(extUsed)\n\n    # Dialog boxes should be transient with respect to their parent, so that\n    # they will always stay on top of their parent window.  However, some\n    # window managers will create the window as withdrawn if the parent window\n    # is withdrawn or iconified.  Combined with the grab we put on the window,\n    # this can hang the entire application.  Therefore we only make the dialog\n    # transient if the parent is viewable.\n\n    if {[winfo viewable [winfo toplevel $data(-parent)]]} {\n\twm transient $w $data(-parent)\n    }\n\n    # Add traces on the selectPath variable\n    #\n\n    trace add variable data(selectPath) write \\\n\t    [list ::tk::dialog::file::SetPath $w]\n    $data(dirMenuBtn) configure \\\n\t    -textvariable ::tk::dialog::file::${dataName}(selectPath)\n\n    # Cleanup previous menu\n    #\n    $data(typeMenu) delete 0 end\n    $data(typeMenuBtn) configure -state normal -text \"\"\n\n    # Initialize the file types menu\n    #\n    if {[llength $data(-filetypes)]} {\n\t# Default type and name to first entry\n\tset initialtype     [lindex $data(-filetypes) 0]\n\tset initialTypeName [lindex $initialtype 0]\n\tif {$data(-typevariable) ne \"\"} {\n\t    upvar #0 $data(-typevariable) typeVariable\n\t    if {[info exists typeVariable]} {\n\t\tset initialTypeName $typeVariable\n\t    }\n\t}\n\tforeach type $data(-filetypes) {\n\t    set title  [lindex $type 0]\n\t    set filter [lindex $type 1]\n\t    $data(typeMenu) add command -label $title \\\n\t\t-command [list ::tk::dialog::file::SetFilter $w $type]\n\t    # [string first] avoids glob-pattern char issues\n\t    if {[string first ${initialTypeName} $title] == 0} {\n\t\tset initialtype $type\n\t    }\n\t}\n\tSetFilter $w $initialtype\n\t$data(typeMenuBtn) configure -state normal\n\t$data(typeMenuLab) configure -state normal\n    } else {\n\tset data(filter) \"*\"\n\t$data(typeMenuBtn) configure -state disabled -takefocus 0\n\t$data(typeMenuLab) configure -state disabled\n    }\n    UpdateWhenIdle $w\n\n    # Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w widget $data(-parent)\n    wm title $w $data(-title)\n\n    # Set a grab and claim the focus too.\n\n    ::tk::SetFocusGrab $w $data(ent)\n    $data(ent) delete 0 end\n    $data(ent) insert 0 $data(selectFile)\n    $data(ent) selection range 0 end\n    $data(ent) icursor end\n\n    # Wait for the user to respond, then restore the focus and return the\n    # index of the selected button.  Restore the focus before deleting the\n    # window, since otherwise the window manager may take the focus away so we\n    # can't redirect it.  Finally, restore any grab that was in effect.\n\n    vwait ::tk::Priv(selectFilePath)\n\n    ::tk::RestoreFocusGrab $w $data(ent) withdraw\n\n    # Cleanup traces on selectPath variable\n    #\n\n    foreach trace [trace info variable data(selectPath)] {\n\ttrace remove variable data(selectPath) {*}$trace\n    }\n    if {[winfo exists $data(dirMenuBtn)]} {\n\t$data(dirMenuBtn) configure -textvariable {}\n    }\n\n    return $Priv(selectFilePath)\n}\n\n# ::tk::dialog::file::Config --\n#\n#\tConfigures the TK filedialog according to the argument list\n#\nproc ::tk::dialog::file::Config {dataName type argList} {\n    upvar ::tk::dialog::file::$dataName data\n\n    set data(type) $type\n\n    # 0: Delete all variable that were set on data(selectPath) the\n    # last time the file dialog is used. The traces may cause troubles\n    # if the dialog is now used with a different -parent option.\n\n    foreach trace [trace info variable data(selectPath)] {\n\ttrace remove variable data(selectPath) {*}$trace\n    }\n\n    # 1: the configuration specs\n    #\n    set specs {\n\t{-defaultextension \"\" \"\" \"\"}\n\t{-filetypes \"\" \"\" \"\"}\n\t{-initialdir \"\" \"\" \"\"}\n\t{-initialfile \"\" \"\" \"\"}\n\t{-parent \"\" \"\" \".\"}\n\t{-title \"\" \"\" \"\"}\n\t{-typevariable \"\" \"\" \"\"}\n    }\n\n    # The \"-multiple\" option is only available for the \"open\" file dialog.\n    #\n    if {$type eq \"open\"} {\n\tlappend specs {-multiple \"\" \"\" \"0\"}\n    }\n\n    # The \"-confirmoverwrite\" option is only for the \"save\" file dialog.\n    #\n    if {$type eq \"save\"} {\n\tlappend specs {-confirmoverwrite \"\" \"\" \"1\"}\n    }\n\n    # 2: default values depending on the type of the dialog\n    #\n    if {![info exists data(selectPath)]} {\n\t# first time the dialog has been popped up\n\tset data(selectPath) [pwd]\n\tset data(selectFile) \"\"\n    }\n\n    # 3: parse the arguments\n    #\n    tclParseConfigSpec ::tk::dialog::file::$dataName $specs \"\" $argList\n\n    if {$data(-title) eq \"\"} {\n\tif {$type eq \"open\"} {\n\t    set data(-title) [mc \"Open\"]\n\t} else {\n\t    set data(-title) [mc \"Save As\"]\n\t}\n    }\n\n    # 4: set the default directory and selection according to the -initial\n    #    settings\n    #\n    if {$data(-initialdir) ne \"\"} {\n\t# Ensure that initialdir is an absolute path name.\n\tif {[file isdirectory $data(-initialdir)]} {\n\t    set old [pwd]\n\t    cd $data(-initialdir)\n\t    set data(selectPath) [pwd]\n\t    cd $old\n\t} else {\n\t    set data(selectPath) [pwd]\n\t}\n    }\n    set data(selectFile) $data(-initialfile)\n\n    # 5. Parse the -filetypes option\n    #\n    set data(origfiletypes) $data(-filetypes)\n    set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]\n\n    if {![winfo exists $data(-parent)]} {\n\treturn -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \\\n\t    \"bad window path name \\\"$data(-parent)\\\"\"\n    }\n\n    # Set -multiple to a one or zero value (not other boolean types like\n    # \"yes\") so we can use it in tests more easily.\n    if {$type eq \"save\"} {\n\tset data(-multiple) 0\n    } elseif {$data(-multiple)} {\n\tset data(-multiple) 1\n    } else {\n\tset data(-multiple) 0\n    }\n}\n\nproc ::tk::dialog::file::Create {w class} {\n    set dataName [lindex [split $w .] end]\n    upvar ::tk::dialog::file::$dataName data\n    variable ::tk::Priv\n    global tk_library\n\n    toplevel $w -class $class\n    if {[tk windowingsystem] eq \"x11\"} {wm attributes $w -type dialog}\n    pack [ttk::frame $w.contents] -expand 1 -fill both\n    #set w $w.contents\n\n    # f1: the frame with the directory option menu\n    #\n    set f1 [ttk::frame $w.contents.f1]\n    bind [::tk::AmpWidget ttk::label $f1.lab -text [mc \"&Directory:\"]] \\\n\t    <<AltUnderlined>> [list focus $f1.menu]\n\n    set data(dirMenuBtn) $f1.menu\n    if {![info exists data(selectPath)]} {\n\tset data(selectPath) \"\"\n    }\n    set data(dirMenu) $f1.menu.menu\n    ttk::menubutton $f1.menu -menu $data(dirMenu) -direction flush \\\n\t    -textvariable [format %s(selectPath) ::tk::dialog::file::$dataName]\n    menu $data(dirMenu) -tearoff 0\n    $data(dirMenu) add radiobutton -label \"\" -variable \\\n\t    [format %s(selectPath) ::tk::dialog::file::$dataName]\n    set data(upBtn) [ttk::button $f1.up]\n    $data(upBtn) configure -image $Priv(updirImage)\n\n    $f1.menu configure -takefocus 1;# -highlightthickness 2\n\n    pack $data(upBtn) -side right -padx 3p -fill both\n    pack $f1.lab -side left -padx 3p -fill both\n    pack $f1.menu -expand yes -fill both -padx 3p\n\n    # data(icons): the IconList that list the files and directories.\n    #\n    if {$class eq \"TkFDialog\"} {\n\tif { $data(-multiple) } {\n\t    set fNameCaption [mc \"File &names:\"]\n\t} else {\n\t    set fNameCaption [mc \"File &name:\"]\n\t}\n\tset fTypeCaption [mc \"Files of &type:\"]\n\tset iconListCommand [list ::tk::dialog::file::OkCmd $w]\n    } else {\n\tset fNameCaption [mc \"&Selection:\"]\n\tset iconListCommand [list ::tk::dialog::file::chooseDir::DblClick $w]\n    }\n    set data(icons) [::tk::IconList $w.contents.icons \\\n\t    -command $iconListCommand -multiple $data(-multiple)]\n    bind $data(icons) <<ListboxSelect>> \\\n\t    [list ::tk::dialog::file::ListBrowse $w]\n\n    # f2: the frame with the OK button, cancel button, \"file name\" field\n    #     and file types field.\n    #\n    set f2 [ttk::frame $w.contents.f2]\n    bind [::tk::AmpWidget ttk::label $f2.lab -text $fNameCaption -anchor e]\\\n\t    <<AltUnderlined>> [list focus $f2.ent]\n    # -pady 0\n    set data(ent) [ttk::entry $f2.ent]\n\n    # The font to use for the icons. The default Canvas font on Unix is just\n    # deviant.\n    set ::tk::$w.contents.icons(font) [$data(ent) cget -font]\n\n    # Make the file types bits only if this is a File Dialog\n    if {$class eq \"TkFDialog\"} {\n\tset data(typeMenuLab) [::tk::AmpWidget ttk::label $f2.lab2 \\\n\t\t-text $fTypeCaption -anchor e]\n\t# -pady [$f2.lab cget -pady]\n\tset data(typeMenuBtn) [ttk::menubutton $f2.menu \\\n\t\t-menu $f2.menu.m]\n\t# -indicatoron 1\n\tset data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]\n\t# $data(typeMenuBtn) configure -takefocus 1 -relief raised -anchor w\n\tbind $data(typeMenuLab) <<AltUnderlined>> [list \\\n\t\tfocus $data(typeMenuBtn)]\n    }\n\n    # The hidden button is displayed when ::tk::dialog::file::showHiddenBtn is\n    # true.  Create it disabled so the binding doesn't trigger if it isn't\n    # shown.\n    if {$class eq \"TkFDialog\"} {\n\tset text [mc \"Show &Hidden Files and Directories\"]\n    } else {\n\tset text [mc \"Show &Hidden Directories\"]\n    }\n    set data(hiddenBtn) [::tk::AmpWidget ttk::checkbutton $f2.hidden \\\n\t    -text $text -state disabled \\\n\t    -variable ::tk::dialog::file::showHiddenVar \\\n\t    -command [list ::tk::dialog::file::UpdateWhenIdle $w]]\n# -anchor w -padx 2p\n\n    # the okBtn is created after the typeMenu so that the keyboard traversal\n    # is in the right order, and add binding so that we find out when the\n    # dialog is destroyed by the user (added here instead of to the overall\n    # window so no confusion about how much <Destroy> gets called; exactly\n    # once will do). [Bug 987169]\n\n    set data(okBtn)     [::tk::AmpWidget ttk::button $f2.ok \\\n\t    -text [mc \"&OK\"]     -default active];# -pady 2p]\n    bind $data(okBtn) <Destroy> [list ::tk::dialog::file::Destroyed $w]\n    set data(cancelBtn) [::tk::AmpWidget ttk::button $f2.cancel \\\n\t    -text [mc \"&Cancel\"] -default normal];# -pady 2p]\n\n    # grid the widgets in f2\n    #\n    grid $f2.lab $f2.ent $data(okBtn) -padx 3p -pady 2p -sticky ew\n    grid configure $f2.ent -padx 1.5p\n    if {$class eq \"TkFDialog\"} {\n\tgrid $data(typeMenuLab) $data(typeMenuBtn) $data(cancelBtn) \\\n\t\t-padx 3p -sticky ew\n\tgrid configure $data(typeMenuBtn) -padx 0\n\tgrid $data(hiddenBtn) -columnspan 2 -padx 3p -sticky ew\n    } else {\n\tgrid $data(hiddenBtn) - $data(cancelBtn) -padx 3p -sticky ew\n    }\n    grid columnconfigure $f2 1 -weight 1\n\n    # Pack all the frames together. We are done with widget construction.\n    #\n    pack $f1 -side top -fill x -pady 3p\n    pack $f2 -side bottom -pady 3p -fill x\n    pack $data(icons) -expand yes -fill both -padx 3p -pady 1p\n\n    # Set up the event handlers that are common to Directory and File Dialogs\n    #\n\n    wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]\n    $data(upBtn)     configure -command [list ::tk::dialog::file::UpDirCmd $w]\n    $data(cancelBtn) configure -command [list ::tk::dialog::file::CancelCmd $w]\n    bind $w <Escape> [list $data(cancelBtn) invoke]\n    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]\n\n    # Set up event handlers specific to File or Directory Dialogs\n    #\n    if {$class eq \"TkFDialog\"} {\n\tbind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]\n\t$data(okBtn)     configure -command [list ::tk::dialog::file::OkCmd $w]\n\tbind $w <Alt-t> [format {\n\t    if {[%s cget -state] eq \"normal\"} {\n\t\tfocus %s\n\t    }\n\t} $data(typeMenuBtn) $data(typeMenuBtn)]\n    } else {\n\tset okCmd [list ::tk::dialog::file::chooseDir::OkCmd $w]\n\tbind $data(ent) <Return> $okCmd\n\t$data(okBtn) configure -command $okCmd\n\tbind $w <Alt-s> [list focus $data(ent)]\n\tbind $w <Alt-o> [list $data(okBtn) invoke]\n    }\n    bind $w <Alt-h> [list $data(hiddenBtn) invoke]\n    bind $data(ent) <Tab> [list ::tk::dialog::file::CompleteEnt $w]\n\n    # Build the focus group for all the entries\n    #\n    ::tk::FocusGroup_Create $w\n    ::tk::FocusGroup_BindIn $w  $data(ent) [list \\\n\t    ::tk::dialog::file::EntFocusIn $w]\n    ::tk::FocusGroup_BindOut $w $data(ent) [list \\\n\t    ::tk::dialog::file::EntFocusOut $w]\n}\n\n# ::tk::dialog::file::SetSelectMode --\n#\n#\tSet the select mode of the dialog to single select or multi-select.\n#\n# Arguments:\n#\tw\t\tThe dialog path.\n#\tmulti\t\t1 if the dialog is multi-select; 0 otherwise.\n#\n# Results:\n#\tNone.\n\nproc ::tk::dialog::file::SetSelectMode {w multi} {\n    set dataName __tk_filedialog\n    upvar ::tk::dialog::file::$dataName data\n    if { $multi } {\n\tset fNameCaption [mc \"File &names:\"]\n    } else {\n\tset fNameCaption [mc \"File &name:\"]\n    }\n    set iconListCommand [list ::tk::dialog::file::OkCmd $w]\n    ::tk::SetAmpText $w.contents.f2.lab $fNameCaption\n    $data(icons) configure -multiple $multi -command $iconListCommand\n    return\n}\n\n# ::tk::dialog::file::UpdateWhenIdle --\n#\n#\tCreates an idle event handler which updates the dialog in idle time.\n#\tThis is important because loading the directory may take a long time\n#\tand we don't want to load the same directory for multiple times due to\n#\tmultiple concurrent events.\n#\nproc ::tk::dialog::file::UpdateWhenIdle {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[info exists data(updateId)]} {\n\treturn\n    }\n    set data(updateId) [after idle [list ::tk::dialog::file::Update $w]]\n}\n\n# ::tk::dialog::file::Update --\n#\n#\tLoads the files and directories into the IconList widget. Also sets up\n#\tthe directory option menu for quick access to parent directories.\n#\nproc ::tk::dialog::file::Update {w} {\n    # This proc may be called within an idle handler. Make sure that the\n    # window has not been destroyed before this proc is called\n    if {![winfo exists $w]} {\n\treturn\n    }\n    set class [winfo class $w]\n    if {($class ne \"TkFDialog\") && ($class ne \"TkChooseDir\")} {\n\treturn\n    }\n\n    set dataName [winfo name $w]\n    upvar ::tk::dialog::file::$dataName data\n    variable ::tk::Priv\n    variable showHiddenVar\n    global tk_library\n    unset -nocomplain data(updateId)\n\n    set folder $Priv(folderImage)\n    set file   $Priv(fileImage)\n\n    set appPWD [pwd]\n    if {[catch {\n\tcd $data(selectPath)\n    }]} then {\n\t# We cannot change directory to $data(selectPath). $data(selectPath)\n\t# should have been checked before ::tk::dialog::file::Update is\n\t# called, so we normally won't come to here. Anyways, give an error\n\t# and abort action.\n\ttk_messageBox -type ok -parent $w -icon warning -message [mc \\\n\t       \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\"\\\n\t\t$data(selectPath)]\n\tcd $appPWD\n\treturn\n    }\n\n    # Turn on the busy cursor. BUG?? We haven't disabled X events, though,\n    # so the user may still click and cause havoc ...\n    #\n    set entCursor [$data(ent) cget -cursor]\n    set dlgCursor [$w cget -cursor]\n    $data(ent) configure -cursor watch\n    $w configure -cursor watch\n    update idletasks\n\n    $data(icons) deleteall\n\n    set showHidden $showHiddenVar\n\n    # Make the dir list. Note that using an explicit [pwd] (instead of '.') is\n    # better in some VFS cases.\n    $data(icons) add $folder [GlobFiltered [pwd] d 1]\n\n    if {$class eq \"TkFDialog\"} {\n\t# Make the file list if this is a File Dialog, selecting all but\n\t# 'd'irectory type files.\n\t#\n\t$data(icons) add $file [GlobFiltered [pwd] {f b c l p s}]\n    }\n\n    # Update the Directory: option menu\n    #\n    set list \"\"\n    set dir \"\"\n    foreach subdir [file split $data(selectPath)] {\n\tset dir [file join $dir $subdir]\n\tlappend list $dir\n    }\n\n    $data(dirMenu) delete 0 end\n    set var [format %s(selectPath) ::tk::dialog::file::$dataName]\n    foreach path $list {\n\t$data(dirMenu) add command -label $path -command [list set $var $path]\n    }\n\n    # Restore the PWD to the application's PWD\n    #\n    cd $appPWD\n\n    if {$class eq \"TkFDialog\"} {\n\t# Restore the Open/Save Button if this is a File Dialog\n\t#\n\tif {$data(type) eq \"open\"} {\n\t    ::tk::SetAmpText $data(okBtn) [mc \"&Open\"]\n\t} else {\n\t    ::tk::SetAmpText $data(okBtn) [mc \"&Save\"]\n\t}\n    }\n\n    # turn off the busy cursor.\n    #\n    $data(ent) configure -cursor $entCursor\n    $w configure -cursor $dlgCursor\n}\n\n# ::tk::dialog::file::SetPathSilently --\n#\n#\tSets data(selectPath) without invoking the trace procedure\n#\nproc ::tk::dialog::file::SetPathSilently {w path} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set cb [list ::tk::dialog::file::SetPath $w]\n    trace remove variable data(selectPath) write $cb\n    set data(selectPath) $path\n    trace add variable data(selectPath) write $cb\n}\n\n\n# This proc gets called whenever data(selectPath) is set\n#\nproc ::tk::dialog::file::SetPath {w name1 name2 op} {\n    if {[winfo exists $w]} {\n\tupvar ::tk::dialog::file::[winfo name $w] data\n\tUpdateWhenIdle $w\n\t# On directory dialogs, we keep the entry in sync with the currentdir.\n\tif {[winfo class $w] eq \"TkChooseDir\"} {\n\t    $data(ent) delete 0 end\n\t    $data(ent) insert end $data(selectPath)\n\t}\n    }\n}\n\n# This proc gets called whenever data(filter) is set\n#\nproc ::tk::dialog::file::SetFilter {w type} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set data(filterType) $type\n    set data(filter) [lindex $type 1]\n    $data(typeMenuBtn) configure -text [lindex $type 0] ;#-indicatoron 1\n\n    # If we aren't using a default extension, use the one suppled by the\n    # filter.\n    if {![info exists data(extUsed)]} {\n\tif {[string length $data(-defaultextension)]} {\n\t    set data(extUsed) 1\n\t} else {\n\t    set data(extUsed) 0\n\t}\n    }\n\n    if {!$data(extUsed)} {\n\t# Get the first extension in the list that matches {^\\*\\.\\w+$} and\n\t# remove all * from the filter.\n\tset index [lsearch -regexp $data(filter) {^\\*\\.\\w+$}]\n\tif {$index >= 0} {\n\t    set data(-defaultextension) \\\n\t\t    [string trimleft [lindex $data(filter) $index] \"*\"]\n\t} else {\n\t    # Couldn't find anything!  Reset to a safe default...\n\t    set data(-defaultextension) \"\"\n\t}\n    }\n\n    $data(icons) see 0\n\n    UpdateWhenIdle $w\n}\n\n# tk::dialog::file::ResolveFile --\n#\n#\tInterpret the user's text input in a file selection dialog.  Performs:\n#\n#\t(1) ~ substitution\n#\t(2) resolve all instances of . and ..\n#\t(3) check for non-existent files/directories\n#\t(4) check for chdir permissions\n#\t(5) conversion of environment variable references to their\n#\t    contents (once only)\n#\n# Arguments:\n#\tcontext:  the current directory you are in\n#\ttext:\t  the text entered by the user\n#\tdefaultext: the default extension to add to files with no extension\n#\texpandEnv: whether to expand environment variables (yes by default)\n#\n# Return vaue:\n#\t[list $flag $directory $file]\n#\n#\t flag = OK\t: valid input\n#\t      = PATTERN\t: valid directory/pattern\n#\t      = PATH\t: the directory does not exist\n#\t      = FILE\t: the directory exists by the file doesn't exist\n#\t      = CHDIR\t: Cannot change to the directory\n#\t      = ERROR\t: Invalid entry\n#\n#\t directory      : valid only if flag = OK or PATTERN or FILE\n#\t file           : valid only if flag = OK or PATTERN\n#\n#\tdirectory may not be the same as context, because text may contain a\n#\tsubdirectory name\n#\nproc ::tk::dialog::file::ResolveFile {context text defaultext {expandEnv 1}} {\n    set appPWD [pwd]\n\n    set path [JoinFile $context $text]\n\n    # If the file has no extension, append the default.  Be careful not to do\n    # this for directories, otherwise typing a dirname in the box will give\n    # back \"dirname.extension\" instead of trying to change dir.\n    if {\n\t![file isdirectory $path] && ([file ext $path] eq \"\") &&\n\t![string match {$*} [file tail $path]]\n    } then {\n\tset path \"$path$defaultext\"\n    }\n\n    if {[catch {file exists $path}]} {\n\t# This \"if\" block can be safely removed if the following code stop\n\t# generating errors.\n\t#\n\t#\tfile exists ~nonsuchuser\n\t#\n\treturn [list ERROR $path \"\"]\n    }\n\n    if {[file exists $path]} {\n\tif {[file isdirectory $path]} {\n\t    if {[catch {cd $path}]} {\n\t\treturn [list CHDIR $path \"\"]\n\t    }\n\t    set directory [pwd]\n\t    set file \"\"\n\t    set flag OK\n\t    cd $appPWD\n\t} else {\n\t    if {[catch {cd [file dirname $path]}]} {\n\t\treturn [list CHDIR [file dirname $path] \"\"]\n\t    }\n\t    set directory [pwd]\n\t    set file [file tail $path]\n\t    set flag OK\n\t    cd $appPWD\n\t}\n    } else {\n\tset dirname [file dirname $path]\n\tif {[file exists $dirname]} {\n\t    if {[catch {cd $dirname}]} {\n\t\treturn [list CHDIR $dirname \"\"]\n\t    }\n\t    set directory [pwd]\n\t    cd $appPWD\n\t    set file [file tail $path]\n\t    # It's nothing else, so check to see if it is an env-reference\n\t    if {$expandEnv && [string match {$*} $file]} {\n\t\tset var [string range $file 1 end]\n\t\tif {[info exist ::env($var)]} {\n\t\t    return [ResolveFile $context $::env($var) $defaultext 0]\n\t\t}\n\t    }\n\t    if {[regexp {[*?]} $file]} {\n\t\tset flag PATTERN\n\t    } else {\n\t\tset flag FILE\n\t    }\n\t} else {\n\t    set directory $dirname\n\t    set file [file tail $path]\n\t    set flag PATH\n\t    # It's nothing else, so check to see if it is an env-reference\n\t    if {$expandEnv && [string match {$*} $file]} {\n\t\tset var [string range $file 1 end]\n\t\tif {[info exist ::env($var)]} {\n\t\t    return [ResolveFile $context $::env($var) $defaultext 0]\n\t\t}\n\t    }\n\t}\n    }\n\n    return [list $flag $directory $file]\n}\n\n\n# Gets called when the entry box gets keyboard focus. We clear the selection\n# from the icon list . This way the user can be certain that the input in the\n# entry box is the selection.\n#\nproc ::tk::dialog::file::EntFocusIn {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[$data(ent) get] ne \"\"} {\n\t$data(ent) selection range 0 end\n\t$data(ent) icursor end\n    } else {\n\t$data(ent) selection clear\n    }\n\n    if {[winfo class $w] eq \"TkFDialog\"} {\n\t# If this is a File Dialog, make sure the buttons are labeled right.\n\tif {$data(type) eq \"open\"} {\n\t    ::tk::SetAmpText $data(okBtn) [mc \"&Open\"]\n\t} else {\n\t    ::tk::SetAmpText $data(okBtn) [mc \"&Save\"]\n\t}\n    }\n}\n\nproc ::tk::dialog::file::EntFocusOut {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    $data(ent) selection clear\n}\n\n\n# Gets called when user presses Return in the \"File name\" entry.\n#\nproc ::tk::dialog::file::ActivateEnt {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set text [$data(ent) get]\n    if {$data(-multiple)} {\n\tforeach t $text {\n\t    VerifyFileName $w $t\n\t}\n    } else {\n\tVerifyFileName $w $text\n    }\n}\n\n# Verification procedure\n#\nproc ::tk::dialog::file::VerifyFileName {w filename} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set list [ResolveFile $data(selectPath) $filename $data(-defaultextension)]\n    foreach {flag path file} $list {\n\tbreak\n    }\n\n    switch -- $flag {\n\tOK {\n\t    if {$file eq \"\"} {\n\t\t# user has entered an existing (sub)directory\n\t\tset data(selectPath) $path\n\t\t$data(ent) delete 0 end\n\t    } else {\n\t\tSetPathSilently $w $path\n\t\tif {$data(-multiple)} {\n\t\t    lappend data(selectFile) $file\n\t\t} else {\n\t\t    set data(selectFile) $file\n\t\t}\n\t\tDone $w\n\t    }\n\t}\n\tPATTERN {\n\t    set data(selectPath) $path\n\t    set data(filter) $file\n\t}\n\tFILE {\n\t    if {$data(type) eq \"open\"} {\n\t\ttk_messageBox -icon warning -type ok -parent $w \\\n\t\t\t-message [mc \"File \\\"%1\\$s\\\"  does not exist.\" \\\n\t\t\t[file join $path $file]]\n\t\t$data(ent) selection range 0 end\n\t\t$data(ent) icursor end\n\t    } else {\n\t\tSetPathSilently $w $path\n\t\tif {$data(-multiple)} {\n\t\t    lappend data(selectFile) $file\n\t\t} else {\n\t\t    set data(selectFile) $file\n\t\t}\n\t\tDone $w\n\t    }\n\t}\n\tPATH {\n\t    tk_messageBox -icon warning -type ok -parent $w -message \\\n\t\t    [mc \"Directory \\\"%1\\$s\\\" does not exist.\" $path]\n\t    $data(ent) selection range 0 end\n\t    $data(ent) icursor end\n\t}\n\tCHDIR {\n\t    tk_messageBox -type ok -parent $w -icon warning -message  \\\n\t\t    [mc \"Cannot change to the directory\\\n\t\t\t\\\"%1\\$s\\\".\\nPermission denied.\" $path]\n\t    $data(ent) selection range 0 end\n\t    $data(ent) icursor end\n\t}\n\tERROR {\n\t    tk_messageBox -type ok -parent $w -icon warning -message \\\n\t\t    [mc \"Invalid file name \\\"%1\\$s\\\".\" $path]\n\t    $data(ent) selection range 0 end\n\t    $data(ent) icursor end\n\t}\n    }\n}\n\n# Gets called when user presses the Alt-s or Alt-o keys.\n#\nproc ::tk::dialog::file::InvokeBtn {w key} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[$data(okBtn) cget -text] eq $key} {\n\t$data(okBtn) invoke\n    }\n}\n\n# Gets called when user presses the \"parent directory\" button\n#\nproc ::tk::dialog::file::UpDirCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {$data(selectPath) ne \"/\"} {\n\tset data(selectPath) [file dirname $data(selectPath)]\n    }\n}\n\n# Join a file name to a path name. The \"file join\" command will break if the\n# filename begins with ~\n#\nproc ::tk::dialog::file::JoinFile {path file} {\n    if {[string match {~*} $file] && [file exists $path/$file]} {\n\treturn [file join $path ./$file]\n    } else {\n\treturn [file join $path $file]\n    }\n}\n\n# Gets called when user presses the \"OK\" button\n#\nproc ::tk::dialog::file::OkCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set filenames {}\n    foreach item [$data(icons) selection get] {\n\tlappend filenames [$data(icons) get $item]\n    }\n\n    if {\n\t([llength $filenames] && !$data(-multiple)) ||\n\t($data(-multiple) && ([llength $filenames] == 1))\n    } then {\n\tset filename [lindex $filenames 0]\n\tset file [JoinFile $data(selectPath) $filename]\n\tif {[file isdirectory $file]} {\n\t    ListInvoke $w [list $filename]\n\t    return\n\t}\n    }\n\n    ActivateEnt $w\n}\n\n# Gets called when user presses the \"Cancel\" button\n#\nproc ::tk::dialog::file::CancelCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    variable ::tk::Priv\n\n    bind $data(okBtn) <Destroy> {}\n    set Priv(selectFilePath) \"\"\n}\n\n# Gets called when user destroys the dialog directly [Bug 987169]\n#\nproc ::tk::dialog::file::Destroyed {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    variable ::tk::Priv\n\n    set Priv(selectFilePath) \"\"\n}\n\n# Gets called when user browses the IconList widget (dragging mouse, arrow\n# keys, etc)\n#\nproc ::tk::dialog::file::ListBrowse {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set text {}\n    foreach item [$data(icons) selection get] {\n\tlappend text [$data(icons) get $item]\n    }\n    if {[llength $text] == 0} {\n\treturn\n    }\n    if {$data(-multiple)} {\n\tset newtext {}\n\tforeach file $text {\n\t    set fullfile [JoinFile $data(selectPath) $file]\n\t    if { ![file isdirectory $fullfile] } {\n\t\tlappend newtext $file\n\t    }\n\t}\n\tset text $newtext\n\tset isDir 0\n    } else {\n\tset text [lindex $text 0]\n\tset file [JoinFile $data(selectPath) $text]\n\tset isDir [file isdirectory $file]\n    }\n    if {!$isDir} {\n\t$data(ent) delete 0 end\n\t$data(ent) insert 0 $text\n\n\tif {[winfo class $w] eq \"TkFDialog\"} {\n\t    if {$data(type) eq \"open\"} {\n\t\t::tk::SetAmpText $data(okBtn) [mc \"&Open\"]\n\t    } else {\n\t\t::tk::SetAmpText $data(okBtn) [mc \"&Save\"]\n\t    }\n\t}\n    } elseif {[winfo class $w] eq \"TkFDialog\"} {\n\t::tk::SetAmpText $data(okBtn) [mc \"&Open\"]\n    }\n}\n\n# Gets called when user invokes the IconList widget (double-click, Return key,\n# etc)\n#\nproc ::tk::dialog::file::ListInvoke {w filenames} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[llength $filenames] == 0} {\n\treturn\n    }\n\n    set file [JoinFile $data(selectPath) [lindex $filenames 0]]\n\n    set class [winfo class $w]\n    if {$class eq \"TkChooseDir\" || [file isdirectory $file]} {\n\tset appPWD [pwd]\n\tif {[catch {cd $file}]} {\n\t    tk_messageBox -type ok -parent $w -icon warning -message \\\n\t\t    [mc \"Cannot change to the directory \\\"%1\\$s\\\".\\nPermission denied.\" $file]\n\t} else {\n\t    cd $appPWD\n\t    set data(selectPath) $file\n\t}\n    } else {\n\tif {$data(-multiple)} {\n\t    set data(selectFile) $filenames\n\t} else {\n\t    set data(selectFile) $file\n\t}\n\tDone $w\n    }\n}\n\n# ::tk::dialog::file::Done --\n#\n#\tGets called when user has input a valid filename.  Pops up a dialog\n#\tbox to confirm selection when necessary.  Sets the\n#\ttk::Priv(selectFilePath) variable, which will break the \"vwait\" loop\n#\tin ::tk::dialog::file:: and return the selected filename to the script\n#\tthat calls tk_getOpenFile or tk_getSaveFile\n#\nproc ::tk::dialog::file::Done {w {selectFilePath \"\"}} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    variable ::tk::Priv\n\n    if {$selectFilePath eq \"\"} {\n\tif {$data(-multiple)} {\n\t    set selectFilePath {}\n\t    foreach f $data(selectFile) {\n\t\tlappend selectFilePath [JoinFile $data(selectPath) $f]\n\t    }\n\t} else {\n\t    set selectFilePath [JoinFile $data(selectPath) $data(selectFile)]\n\t}\n\n\tset Priv(selectFile) $data(selectFile)\n\tset Priv(selectPath) $data(selectPath)\n\n\tif {($data(type) eq \"save\") && $data(-confirmoverwrite) && [file exists $selectFilePath]} {\n\t    set reply [tk_messageBox -icon warning -type yesno -parent $w \\\n\t\t    -message [mc \"File \\\"%1\\$s\\\" already exists.\\nDo you want\\\n\t\t    to overwrite it?\" $selectFilePath]]\n\t    if {$reply eq \"no\"} {\n\t\treturn\n\t    }\n\t}\n\tif {\n\t    [info exists data(-typevariable)] && $data(-typevariable) ne \"\"\n\t    && [info exists data(-filetypes)] && [llength $data(-filetypes)]\n\t    && [info exists data(filterType)] && $data(filterType) ne \"\"\n\t} then {\n\t    upvar #0 $data(-typevariable) typeVariable\n\t    set typeVariable [lindex $data(origfiletypes) \\\n\t\t    [lsearch -exact $data(-filetypes) $data(filterType)] 0]\n\t}\n    }\n    bind $data(okBtn) <Destroy> {}\n    set Priv(selectFilePath) $selectFilePath\n}\n\n# ::tk::dialog::file::GlobFiltered --\n#\n#\tGets called to do globbing, returning the results and filtering them\n#\taccording to the current filter (and removing the entries for '.' and\n#\t'..' which are never shown). Deals with evil cases such as where the\n#\tuser is supplying a filter which is an invalid list or where it has an\n#\tunbalanced brace. The resulting list will be dictionary sorted.\n#\n#\tArguments:\n#\t  dir\t\t Which directory to search\n#\t  type\t\t List of filetypes to look for ('d' or 'f b c l p s')\n#\t  overrideFilter Whether to ignore the filter for this search.\n#\n#\tNB: Assumes that the caller has mapped the state variable to 'data'.\n#\nproc ::tk::dialog::file::GlobFiltered {dir type {overrideFilter 0}} {\n    variable showHiddenVar\n    upvar 1 data(filter) filter\n\n    if {$filter eq \"*\" || $overrideFilter} {\n\tset patterns [list *]\n\tif {$showHiddenVar} {\n\t    lappend patterns .*\n\t}\n    } elseif {[string is list $filter]} {\n\tset patterns $filter\n    } else {\n\t# Invalid list; assume we can use non-whitespace sequences as words\n\tset patterns [regexp -inline -all {\\S+} $filter]\n    }\n\n    set opts [list -tails -directory $dir -type $type -nocomplain]\n\n    set result {}\n    catch {\n\t# We have a catch because we might have a really bad pattern (e.g.,\n\t# with an unbalanced brace); even [glob -nocomplain] doesn't like it.\n\t# Using a catch ensures that it just means we match nothing instead of\n\t# throwing a nasty error at the user...\n\tforeach f [glob {*}$opts -- {*}$patterns] {\n\t    if {$f eq \".\" || $f eq \"..\"} {\n\t\tcontinue\n\t    }\n\t    # See ticket [1641721], $f might be a link pointing to a dir\n\t    if {$type != \"d\" && [file isdir [file join $dir $f]]} {\n\t\tcontinue\n\t    }\n\t    lappend result $f\n\t}\n    }\n    return [lsort -dictionary -unique $result]\n}\n\nproc ::tk::dialog::file::CompleteEnt {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    set f [$data(ent) get]\n    if {$data(-multiple)} {\n\tif {![string is list $f] || [llength $f] != 1} {\n\t    return -code break\n\t}\n\tset f [lindex $f 0]\n    }\n\n    # Get list of matching filenames and dirnames\n    set files [if {[winfo class $w] eq \"TkFDialog\"} {\n\tGlobFiltered $data(selectPath) {f b c l p s}\n    }]\n    set dirs2 {}\n    foreach d [GlobFiltered $data(selectPath) d] {lappend dirs2 $d/}\n\n    set targets [concat \\\n\t    [lsearch -glob -all -inline $files $f*] \\\n\t    [lsearch -glob -all -inline $dirs2 $f*]]\n\n    if {[llength $targets] == 1} {\n\t# We have a winner!\n\tset f [lindex $targets 0]\n    } elseif {$f in $targets || [llength $targets] == 0} {\n\tif {[string length $f] > 0} {\n\t    bell\n\t}\n\treturn\n    } elseif {[llength $targets] > 1} {\n\t# Multiple possibles\n\tif {[string length $f] == 0} {\n\t    return\n\t}\n\tset t0 [lindex $targets 0]\n\tfor {set len [string length $t0]} {$len>0} {} {\n\t    set allmatch 1\n\t    foreach s $targets {\n\t\tif {![string equal -length $len $s $t0]} {\n\t\t    set allmatch 0\n\t\t    break\n\t\t}\n\t    }\n\t    incr len -1\n\t    if {$allmatch} break\n\t}\n\tset f [string range $t0 0 $len]\n    }\n\n    if {$data(-multiple)} {\n\tset f [list $f]\n    }\n    $data(ent) delete 0 end\n    $data(ent) insert 0 $f\n    return -code break\n}\n"
  },
  {
    "path": "library/ttk/altTheme.tcl",
    "content": "#\n# Ttk widget set: Alternate theme\n#\n\nnamespace eval ttk::theme::alt {\n\n    variable colors\n    array set colors {\n\t-frame\t\t\"#d9d9d9\"\n\t-window\t\t\"#ffffff\"\n\t-alternate\t\"#f0f0f0\"\n\t-darker\t\t\"#c3c3c3\"\n\t-border\t\t\"#414141\"\n\t-activebg\t\"#ececec\"\n\t-disabledfg\t\"#a3a3a3\"\n\t-selectbg\t\"#4a6984\"\n\t-selectfg\t\"#ffffff\"\n\t-altindicator\t\"#aaaaaa\"\n    }\n\n    ttk::style theme settings alt {\n\n\tttk::style configure \".\" \\\n\t    -background\t\t$colors(-frame) \\\n\t    -foreground\t\tblack \\\n\t    -troughcolor\t$colors(-darker) \\\n\t    -bordercolor\t$colors(-border) \\\n\t    -selectbackground\t$colors(-selectbg) \\\n\t    -selectforeground\t$colors(-selectfg) \\\n\t    -font\t\tTkDefaultFont\n\n\tttk::style map \".\" -background \\\n\t    [list disabled $colors(-frame)  active $colors(-activebg)]\n\tttk::style map \".\" -foreground [list disabled $colors(-disabledfg)]\n\tttk::style map \".\" -embossed [list disabled 1]\n\n\tttk::style configure TButton \\\n\t    -anchor center -width -11 -padding 0.75p \\\n\t    -relief raised -shiftrelief 1 \\\n\t    -highlightthickness 1 -highlightcolor $colors(-frame)\n\tttk::style map TButton -relief {\n\t    {pressed !disabled}\tsunken\n\t    {active !disabled}\traised\n\t} -highlightcolor {alternate black}\n\n\tttk::style configure TCheckbutton -indicatorcolor \"#ffffff\" \\\n\t    -indicatormargin {0 1.5p 3p 1.5p} -padding 1.5p\n\tttk::style configure TRadiobutton -indicatorcolor \"#ffffff\" \\\n\t    -indicatormargin {0 1.5p 3p 1.5p} -padding 1.5p\n\tttk::style map TCheckbutton -indicatorcolor \\\n\t    [list  pressed $colors(-frame) \\\n\t\t   alternate $colors(-altindicator) \\\n\t\t   disabled $colors(-frame)]\n\tttk::style map TRadiobutton -indicatorcolor \\\n\t    [list  pressed $colors(-frame) \\\n\t\t   alternate $colors(-altindicator) \\\n\t\t   disabled $colors(-frame)]\n\n\tttk::style configure TMenubutton \\\n\t    -width -11 -padding 2.25p -arrowsize 3.75p -relief raised\n\n\tttk::style configure TEntry -padding 1 \\\n\t    -focuswidth 2 -focuscolor $colors(-selectbg)\n\tttk::style map TEntry -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)]\n\n\tttk::style configure TCombobox -padding 1 -arrowsize 10.5p \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::style map TCombobox -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\tttk::style configure ComboboxPopdownFrame -relief solid -borderwidth 1\n\n\tttk::style configure TSpinbox -arrowsize 7.5p -padding {1.5p 0 7.5p 0} \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::style map TSpinbox -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\n\tttk::style configure Toolbutton -relief flat -padding 1.5p\n\tttk::style map Toolbutton -relief \\\n\t    {disabled flat selected sunken pressed sunken active raised}\n\tttk::style map Toolbutton -background \\\n\t    [list pressed $colors(-darker)  active $colors(-activebg)]\n\n\tttk::style configure TScrollbar -relief raised \\\n\t    -arrowsize 10.5p -width 10.5p\n\n\tttk::style configure TLabelframe -relief groove -borderwidth 2\n\n\tttk::style configure TNotebook -tabmargins {1.5p 1.5p 0.75p 0}\n\tttk::style configure TNotebook.Tab -background $colors(-darker) \\\n\t    -padding {3p 1.5p}\n\tttk::style map TNotebook.Tab \\\n\t    -background [list selected $colors(-frame)] \\\n\t    -expand {selected {1.5p 1.5p 0.75p 0}}\n\n\t# Treeview:\n\tttk::style configure Heading -font TkHeadingFont -relief raised\n\tttk::style configure Item \\\n\t    -indicatormargins {1.5p 1.5p 3p 1.5p}\n\tttk::style configure Treeview -background $colors(-window) \\\n\t    -stripedbackground $colors(-alternate) -indent 15p \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::setTreeviewRowHeight\n\tttk::style configure Treeview.Separator \\\n\t    -background $colors(-alternate)\n\tttk::style map Treeview \\\n\t    -background [list disabled $colors(-frame)\\\n\t\t\t\tselected $colors(-selectbg)] \\\n\t    -foreground [list disabled $colors(-disabledfg) \\\n\t\t\t\tselected $colors(-selectfg)]\n\n\tttk::style configure TScale \\\n\t    -groovewidth 3p -troughrelief sunken \\\n\t    -sliderthickness 11.25p -borderwidth 2\n\n\tttk::style configure TProgressbar \\\n\t    -background $colors(-selectbg) -borderwidth 0 \\\n\t    -barsize 22.5p -thickness 11.25p\n    }\n}\n\n# ttk::theme::alt::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook style $style and the\n# style $style.Tab.  Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::alt::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn {\n\t    ttk::style configure $style -tabmargins     {1.5p 1.5p 0.75p 0}\n\t    ttk::style configure $style.Tab -padding {3p 1.5p}\n\t    ttk::style map $style.Tab -expand {selected {1.5p 1.5p 0.75p 0}}\n\t}\n\ts {\n\t    ttk::style configure $style -tabmargins     {1.5p 0 0.75p 1.5p}\n\t    ttk::style configure $style.Tab -padding {3p 1.5p}\n\t    ttk::style map $style.Tab -expand {selected {1.5p 0 0.75p 1.5p}}\n\t}\n\tw {\n\t    ttk::style configure $style -tabmargins     {1.5p 1.5p 0 0.75p}\n\t    ttk::style configure $style.Tab -padding {1.5p 3p}\n\t    ttk::style map $style.Tab -expand {selected {1.5p 1.5p 0 0.75p}}\n\t}\n\te {\n\t    ttk::style configure $style -tabmargins     {0 1.5p 1.5p 0.75p}\n\t    ttk::style configure $style.Tab -padding {1.5p 3p}\n\t    ttk::style map $style.Tab -expand {selected {0 1.5p 1.5p 0.75p}}\n\t}\n\tdefault {\n\t    ttk::style configure $style -tabmargins     {1.5p 1.5p 0.75p 0}\n\t    ttk::style configure $style.Tab -padding {3p 1.5p}\n\t    ttk::style map $style.Tab -expand {selected {1.5p 1.5p 0.75p 0}}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/aquaTheme.tcl",
    "content": "#\n# Aqua theme (OSX native look and feel)\n#\n\nnamespace eval ttk::theme::aqua {\n\n    # ttk::theme::aqua::setInactiveSelectBgColor --\n    #\n    # Sets the default selection background color for the widget styles\n    # TEntry, TCombobox, and TSpinbox in the \"!focus\" state.\n\n    proc setInactiveSelectBgColor {} {\n\tlassign [winfo rgb . systemUnemphasizedSelectedTextBackgroundColor] \\\n\t    r g b\n\tif {$r != 32767} {\n\t    # macOS 10.14+\n\t    set inactiveSelBg systemUnemphasizedSelectedTextBackgroundColor\n\t} else {\n\t    # macOS 10.13\n\t    set inactiveSelBg systemWindowBackgroundColor2\n\t}\n\n\t# For Entry, Combobox and Spinbox widgets the selected text background\n\t# is the \"Highlight color\" selected in preferences when the widget has\n\t# focus.  It is a light gray color when the widget does not have focus\n\t# or is in background state.  (The background state implies !focus so\n\t# we only need to specify !focus.)\n\t#\n\tforeach style {TEntry TCombobox TSpinbox} {\n\t    ttk::style map $style -selectbackground [list !focus $inactiveSelBg]\n\t}\n\n\t# Override the dark gray color produced on macOS 10.13 by the\n\t# default value systemUnemphasizedSelectedTextBackgroundColor\n\t# of the text widget's -inactiveselectbackground option\n\t#\n\toption add *Text.inactiveSelectBackground \\\n\t    $inactiveSelBg widgetDefault\n    }\n\n    # ttk::theme::aqua::setTreeviewAndListboxSelectColors --\n    #\n    # Sets the default selection background and foreground colors for\n    # ttk::treeview and listbox widgets.\n\n    proc setTreeviewAndListboxSelectColors {} {\n\tif {[catch {winfo rgb . systemSelectedContentBackgroundColor}] == 0} {\n\t    # macOS 10.14+\n\t    set selectedBg\tsystemSelectedContentBackgroundColor\n\t    set inactiveSelBg\tsystemUnemphasizedSelectedContentBackgroundColor\n\t} else {\n\t    # macOS 10.13\n\t    set selectedBg\tsystemHighlightAlternate\n\t    set inactiveSelBg\tsystemWindowBackgroundColor2\n\t}\n\tset selectedFg\t\tsystemAlternateSelectedControlTextColor\n\tset inactiveSelFg\tsystemSelectedControlTextColor\n\n\t# The treeview uses the \"background\" state for selected\n\t# items when the widget has lost the focus.  Hence the\n\t# following code sets different default selection colors\n\t# depending on whether the widget has the focus or not.\n\t#\n\tttk::style map Treeview \\\n\t    -background [list background $inactiveSelBg selected $selectedBg] \\\n\t    -foreground [list background $inactiveSelFg selected $selectedFg]\n\n\toption add *Listbox.selectBackground\t$selectedBg widgetDefault\n\toption add *Listbox.selectForeground\t$selectedFg widgetDefault\n\toption add *Listbox.inactiveSelectBackground \\\n\t    $inactiveSelBg widgetDefault\n\toption add *Listbox.inactiveSelectForeground \\\n\t    $inactiveSelFg widgetDefault\n    }\n\n    ttk::style theme settings aqua {\n\n\tttk::style configure . \\\n\t    -font TkDefaultFont \\\n\t    -background systemWindowBackgroundColor \\\n\t    -foreground systemLabelColor \\\n\t    -selectbackground systemSelectedTextBackgroundColor \\\n\t    -selectforeground systemSelectedTextColor \\\n\t    -insertwidth 1\n\n\tttk::style map . \\\n\t    -foreground {\n\t\tdisabled systemDisabledControlTextColor\n\t\tbackground systemLabelColor} \\\n\t    -selectbackground {\n\t\tbackground systemSelectedTextBackgroundColor\n\t\t!focus systemSelectedTextBackgroundColor} \\\n\t    -selectforeground {\n\t\tbackground systemSelectedTextColor\n\t\t!focus systemSelectedTextColor}\n\n\t# Button\n\tttk::style configure TButton -anchor center \\\n\t    -foreground systemControlTextColor\n\tttk::style map TButton \\\n\t    -foreground {\n\t\tpressed white\n\t\t{alternate !pressed !background} white\n\t\tdisabled systemDisabledControlTextColor}\n\n\t# Menubutton\n\tttk::style configure TMenubutton -anchor center -padding {2 0 0 2}\n\n\t# Toolbutton\n\tttk::style configure Toolbutton -anchor center\n\n\t# Inline Button\n\tttk::style configure InlineButton -anchor center -font TkHeadingFont \\\n\t    -foreground systemTextBackgroundColor\n\tttk::style map InlineButton \\\n\t    -foreground {\n\t\tdisabled systemWindowBackgroundColor\n\t    }\n\n\t# Image Button\n\tttk::style configure ImageButton -anchor center -width 1 \\\n\t    -compound top\n\tttk::style map ImageButton \\\n\t    -foreground {\n\t\tpressed systemLabelColor\n\t\t!pressed systemSecondaryLabelColor\n\t    }\n\n\t# Recessed (radio) button\n\tfont create RecessedFont -family EmphasizedSystem -size 11 -weight bold\n\tttk::style configure RecessedButton \\\n\t    -foreground systemControlTextColor\n\tttk::style map RecessedButton \\\n\t    -foreground {\n\t\t{disabled selected} systemWindowBackgroundColor3\n\t\t{disabled !selected} systemDisabledControlTextColor\n\t\tselected systemTextBackgroundColor\n\t\tactive white\n\t\tpressed white\n\t    } \\\n\t    -font {\n\t\tselected RecessedFont\n\t\tactive RecessedFont\n\t\tpressed RecessedFont\n\t    }\n\n\t# Sidebar (radio) button\n\tfont create SidebarFont -family .AppleSystemUIFont -size 11 \\\n\t    -weight normal\n\tttk::style configure SidebarButton \\\n\t    -foreground systemControlTextColor \\\n\t    -font SidebarFont\n\tttk::style map SidebarButton \\\n\t    -foreground {\n\t\t{disabled selected} systemWindowBackgroundColor3\n\t\t{disabled !selected} systemDisabledControlTextColor\n\t\tselected systemTextColor\n\t\tactive systemTextColor\n\t\tpressed systemTextColor\n\t    }\n\n\t# Entry\n\tttk::style configure TEntry \\\n\t    -foreground systemTextColor \\\n\t    -background systemTextBackgroundColor\n\tttk::style map TEntry \\\n\t    -foreground {disabled systemDisabledControlTextColor}\n\n\t# Combobox\n\tttk::style map TCombobox \\\n\t    -foreground {disabled systemDisabledControlTextColor}\n\n\t# Spinbox\n\tttk::style configure TSpinbox \\\n\t    -foreground systemTextColor \\\n\t    -background systemTextBackgroundColor\n\tttk::style map TSpinbox \\\n\t    -foreground {disabled systemDisabledControlTextColor}\n\n\tsetInactiveSelectBgColor\t;# for TEntry, TCombobox, and TSpinbox\n\n\t# Workaround for #1100117:\n\t# Actually, on Aqua we probably shouldn't stipple images in\n\t# disabled buttons even if it did work...\n\tttk::style configure . -stipple {}\n\n\t# Notebook\n\tttk::style configure TNotebook -tabmargins {10 0} -tabposition n\n\tttk::style configure TNotebook -padding {18 8 18 17}\n\tttk::style configure TNotebook.Tab -padding {12 3 12 2}\n\tttk::style configure TNotebook.Tab -foreground systemControlTextColor\n\tttk::style map TNotebook.Tab \\\n\t    -foreground {\n\t\t{background !selected} systemControlTextColor\n\t\t{background selected} black\n\t\t{!background selected} systemSelectedTabTextColor\n\t\tdisabled systemDisabledControlTextColor}\n\n\t# Treeview\n\tttk::style configure Heading \\\n\t    -font TkHeadingFont \\\n\t    -foreground systemTextColor \\\n\t    -background systemWindowBackgroundColor\n\tttk::style configure Treeview -rowheight 18 \\\n\t    -background systemControlBackgroundColor \\\n\t    -stripedbackground systemControlAlternatingRowColor \\\n\t    -foreground systemTextColor \\\n\t    -fieldbackground systemTextBackgroundColor\n\tsetTreeviewAndListboxSelectColors\n\n\t# Enable animation for ttk::progressbar widget:\n\tttk::style configure TProgressbar -period 100 -maxphase 120\n\n\t# For Aqua, labelframe labels should appear outside the border,\n\t# with a 14 pixel inset and 4 pixels spacing between border and label\n\t# (ref: Apple Human Interface Guidelines / Controls / Grouping Controls)\n\t#\n\tttk::style configure TLabelframe \\\n\t    -labeloutside true \\\n\t    -labelmargins {14 0 14 2}\n\n\tttk::style configure TLabelframe.Label \\\n\t    -font TkSmallCaptionFont\n\n\t# TODO: panedwindow sashes should be 9 pixels (HIG:Controls:Split Views)\n    }\n}\n\n# ttk::theme::aqua::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook style $style and the\n# style $style.Tab.  Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::aqua::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn {\n\t    ttk::style configure $style -tabmargins {10 0}\n\t    ttk::style configure $style.Tab -padding {12 3 12 2}\n\t}\n\ts {\n\t    ttk::style configure $style -tabmargins {10 0}\n\t    ttk::style configure $style.Tab -padding {12 2 12 3}\n\t}\n\tw {\n\t    ttk::style configure $style -tabmargins {0 10}\n\t    ttk::style configure $style.Tab -padding {3 12 2 12}\n\t}\n\te {\n\t    ttk::style configure $style -tabmargins {0 10}\n\t    ttk::style configure $style.Tab -padding {2 12 3 12}\n\t}\n\tdefault {\n\t    ttk::style configure $style -tabmargins {10 0}\n\t    ttk::style configure $style.Tab -padding {12 3 12 2}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/button.tcl",
    "content": "#\n# Bindings for Buttons, Checkbuttons, and Radiobuttons.\n#\n# Notes: <Button1-Leave>, <Button1-Enter> only control the \"pressed\"\n# state; widgets remain \"active\" if the pointer is dragged out.\n# This doesn't seem to be conventional, but it's a nice way\n# to provide extra feedback while the grab is active.\n# (If the button is released off the widget, the grab deactivates and\n# we get a <Leave> event then, which turns off the \"active\" state)\n#\n# Normally, <ButtonRelease> and <ButtonN-Enter/Leave> events are\n# delivered to the widget which received the initial <Button>\n# event.  However, Tk [grab]s (#1223103) and menu interactions\n# (#1222605) can interfere with this.  To guard against spurious\n# <Button1-Enter> events, the <Button1-Enter> binding only sets\n# the pressed state if the button is currently active.\n#\n\nnamespace eval ttk::button {}\n\nbind TButton <Enter>\t\t{ %W instate !disabled {%W state active} }\nbind TButton <Leave>\t\t{ %W state !active }\nbind TButton <space>\t\t{ ttk::button::activate %W }\nbind TButton <<Invoke>>\t\t{ ttk::button::activate %W }\n\nbind TButton <Button-1> \\\n    { %W instate !disabled { ttk::clickToFocus %W; %W state pressed } }\nbind TButton <ButtonRelease-1> \\\n    { %W instate pressed { %W state !pressed; %W instate !disabled { %W invoke } } }\nbind TButton <Button1-Leave> \\\n    { %W state !pressed }\nbind TButton <Button1-Enter> \\\n    { %W instate {active !disabled} { %W state pressed } }\n\n# Checkbuttons and Radiobuttons have the same bindings as Buttons:\n#\nttk::copyBindings TButton TCheckbutton\nttk::copyBindings TButton TRadiobutton\n\n# ...plus a few more:\n\nbind TRadiobutton <Up>\t\t\t{ ttk::button::RadioTraverse %W -1 }\nbind TRadiobutton <Down>\t\t{ ttk::button::RadioTraverse %W +1 }\n\n# bind TCheckbutton <+> { %W select }\n# bind TCheckbutton <minus> { %W deselect }\n\n# activate --\n#\tSimulate a button press: temporarily set the state to 'pressed',\n#\tthen invoke the button.\n#\nproc ttk::button::activate {w} {\n    $w instate disabled { return }\n    set oldState [$w state pressed]\n    update idletasks; after 100\t;# block event loop to avoid reentrancy\n    $w state $oldState\n    $w invoke\n}\n\n# RadioTraverse -- up/down keyboard traversal for radiobutton groups.\n#\tSet focus to previous/next radiobutton in a group.\n#\tA radiobutton group consists of all the radiobuttons with\n#\tthe same parent and -variable; this is a pretty good heuristic\n#\tthat works most of the time.\n#\nproc ttk::button::RadioTraverse {w dir} {\n    set group [list]\n    foreach sibling [winfo children [winfo parent $w]] {\n\tif {   [winfo class $sibling] eq \"TRadiobutton\"\n\t    && [$sibling cget -variable] eq [$w cget -variable]\n\t    && ![$sibling instate disabled]\n\t} {\n\t   lappend group $sibling\n\t}\n    }\n\n    if {![llength $group]} {\t # Shouldn't happen, but can.\n\treturn\n    }\n\n    set pos [expr {([lsearch -exact $group $w] + $dir) % [llength $group]}]\n    tk::TabToWindow [lindex $group $pos]\n}\n"
  },
  {
    "path": "library/ttk/clamTheme.tcl",
    "content": "#\n# \"Clam\" theme.\n#\n# Inspired by the XFCE family of Gnome themes.\n#\n\nnamespace eval ttk::theme::clam {\n\n    variable colors\n    array set colors {\n\t-disabledfg\t\t\"#999999\"\n\t-frame\t\t\t\"#dcdad5\"\n\t-window\t\t\t\"#ffffff\"\n\t-dark\t\t\t\"#cfcdc8\"\n\t-darker\t\t\t\"#bab5ab\"\n\t-darkest\t\t\"#9e9a91\"\n\t-lighter\t\t\"#eeebe7\"\n\t-lightest\t\t\"#ffffff\"\n\t-selectbg\t\t\"#4a6984\"\n\t-selectfg\t\t\"#ffffff\"\n\t-altindicator\t\t\"#5895bc\"\n\t-disabledaltindicator\t\"#a0a0a0\"\n    }\n\n    ttk::style theme settings clam {\n\n\tttk::style configure \".\" \\\n\t    -background $colors(-frame) \\\n\t    -foreground black \\\n\t    -bordercolor $colors(-darkest) \\\n\t    -darkcolor $colors(-dark) \\\n\t    -lightcolor $colors(-lighter) \\\n\t    -troughcolor $colors(-darker) \\\n\t    -selectbackground $colors(-selectbg) \\\n\t    -selectforeground $colors(-selectfg) \\\n\t    -font TkDefaultFont\n\n\tttk::style map \".\" \\\n\t    -background [list disabled $colors(-frame) \\\n\t\t\t     active $colors(-lighter)] \\\n\t    -foreground [list disabled $colors(-disabledfg)] \\\n\t    -selectbackground [list !focus $colors(-darkest)] \\\n\t    -selectforeground [list !focus white]\n\n\t# -selectbackground [list  !focus \"#847d73\"]\n\n\tttk::style configure TButton \\\n\t    -anchor center -width -11 -padding 3.75p -relief raised\n\tttk::style map TButton \\\n\t    -background [list \\\n\t\t\t     disabled $colors(-frame) \\\n\t\t\t     pressed $colors(-darker) \\\n\t\t\t     active $colors(-lighter)] \\\n\t    -lightcolor [list pressed $colors(-darker)] \\\n\t    -darkcolor [list pressed $colors(-darker)] \\\n\t    -bordercolor {alternate #000000}\n\n\tttk::style configure Toolbutton \\\n\t    -anchor center -padding 1.5p -relief flat\n\tttk::style map Toolbutton \\\n\t    -relief [list \\\n\t\t    disabled flat \\\n\t\t    selected sunken \\\n\t\t    pressed sunken \\\n\t\t    active raised] \\\n\t    -background [list \\\n\t\t    disabled $colors(-frame) \\\n\t\t    pressed $colors(-darker) \\\n\t\t    active $colors(-lighter)] \\\n\t    -lightcolor [list pressed $colors(-darker)] \\\n\t    -darkcolor [list pressed $colors(-darker)]\n\n\tttk::style configure TCheckbutton \\\n\t    -indicatorbackground \"#ffffff\" \\\n\t    -indicatorforeground \"#000000\" \\\n\t    -indicatormargin {0.75p 0.75p 3p 0.75p} \\\n\t    -padding 1.5p\n\tttk::style configure TRadiobutton \\\n\t    -indicatorbackground \"#ffffff\" \\\n\t    -indicatorforeground \"#000000\" \\\n\t    -indicatormargin {0.75p 0.75p 3p 0.75p} \\\n\t    -padding 1.5p\n\tttk::style map TCheckbutton \\\n\t    -indicatorbackground [list \\\n\t\t    pressed\t\t  $colors(-frame) \\\n\t\t    {alternate disabled}  $colors(-disabledaltindicator) \\\n\t\t    alternate\t\t  $colors(-altindicator) \\\n\t\t    disabled\t\t  $colors(-frame)] \\\n\t    -indicatorforeground [list disabled $colors(-disabledfg)]\n\tttk::style map TRadiobutton \\\n\t    -indicatorbackground [list \\\n\t\t    pressed\t\t  $colors(-frame) \\\n\t\t    {alternate disabled}  $colors(-disabledaltindicator) \\\n\t\t    alternate\t\t  $colors(-altindicator) \\\n\t\t    disabled\t\t  $colors(-frame)] \\\n\t    -indicatorforeground [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TMenubutton \\\n\t    -width -11 -arrowsize 3.75p -arrowpadding 2.25p -padding 3.75p \\\n\t    -relief raised\n\n\tttk::style configure TEntry -padding 1 -insertwidth 1\n\tttk::style map TEntry \\\n\t    -background [list readonly $colors(-frame)] \\\n\t    -bordercolor [list focus $colors(-selectbg)] \\\n\t    -lightcolor [list focus #6f9dc6]\n\n\tttk::style configure TCombobox -padding 1 -insertwidth 1 \\\n\t    -arrowsize 10.5p\n\tttk::style map TCombobox \\\n\t    -background [list active $colors(-lighter) \\\n\t\t\t     pressed $colors(-lighter)] \\\n\t    -fieldbackground [list {readonly focus} $colors(-selectbg) \\\n\t\t\t\t  readonly $colors(-frame)] \\\n\t    -foreground [list {readonly focus} $colors(-selectfg)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)] \\\n\t    -bordercolor [list focus $colors(-selectbg)]\n\tttk::style configure ComboboxPopdownFrame \\\n\t    -relief solid -borderwidth 1\n\n\tttk::style configure TSpinbox -arrowsize 7.5p -padding {1.5p 0 7.5p 0}\n\tttk::style map TSpinbox \\\n\t    -background [list readonly $colors(-frame)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)] \\\n\t    -bordercolor [list focus $colors(-selectbg)]\n\n\tttk::style configure TNotebook.Tab -padding {4.5p 1.5p 4.5p 1.5p}\n\tttk::style map TNotebook.Tab \\\n\t    -padding {selected {4.5p 3p 4.5p 1.5p}} \\\n\t    -background [list selected $colors(-frame) {} $colors(-darker)] \\\n\t    -lightcolor [list selected $colors(-lighter) {} $colors(-dark)]\n\n\t# Treeview\n\tttk::style configure Heading \\\n\t    -font TkHeadingFont -relief raised -padding 2.25p\n\tttk::style configure Item -indicatorsize 9p \\\n\t    -indicatormargins {1.5p 1.5p 3p 1.5p}\n\tttk::style configure Treeview -background $colors(-window) \\\n\t    -stripedbackground $colors(-lighter) -indent 15p\n\tttk::setTreeviewRowHeight\n\tttk::style configure Treeview.Separator \\\n\t    -background $colors(-lighter)\n\t# The treeview uses the \"background\" state for\n\t# selected items when the widget has lost the focus.\n\tttk::style map Treeview \\\n\t    -background [list\tdisabled $colors(-frame) \\\n\t\t\t\tbackground $colors(-darkest) \\\n\t\t\t\tselected $colors(-selectbg)] \\\n\t    -foreground [list\tdisabled $colors(-disabledfg) \\\n\t\t\t\tbackground $colors(-selectfg) \\\n\t\t\t\tselected $colors(-selectfg)] \\\n\t    -bordercolor [list focus $colors(-selectbg)]\n\n\tttk::style configure TLabelframe \\\n\t    -labeloutside true -labelmargins {0 0 0 3p} \\\n\t    -borderwidth 2 -relief raised\n\n\tttk::style configure TScrollbar -gripsize 7.5p \\\n\t    -arrowsize 10.5p -width 10.5p\n\n\tttk::style configure TScale -gripsize 7.5p \\\n\t    -arrowsize 10.5p -sliderlength 22.5p\n\n\tttk::style configure TProgressbar -background $colors(-frame) \\\n\t    -arrowsize 10.5p -sliderlength 22.5p\n\n\tttk::style configure Sash -sashthickness 4.5p -gripsize 15p\n    }\n}\n\n# ttk::theme::clam::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook tab style $style.Tab.\n# Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::clam::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn {\n\t    ttk::style configure $style.Tab -padding     {4.5p 1.5p 4.5p 1.5p}\n\t    ttk::style map $style.Tab -padding {selected {4.5p 3p   4.5p 1.5p}}\n\t}\n\ts {\n\t    ttk::style configure $style.Tab -padding     {4.5p 1.5p 4.5p 1.5p}\n\t    ttk::style map $style.Tab -padding {selected {4.5p 1.5p 4.5p 3p  }}\n\t}\n\tw {\n\t    ttk::style configure $style.Tab -padding     {1.5p 4.5p 1.5p 4.5p}\n\t    ttk::style map $style.Tab -padding {selected {3p   4.5p 1.5p 4.5p}}\n\t}\n\te {\n\t    ttk::style configure $style.Tab -padding     {1.5p 4.5p 1.5p 4.5p}\n\t    ttk::style map $style.Tab -padding {selected {1.5p 4.5p 3p   4.5p}}\n\t}\n\tdefault {\n\t    ttk::style configure $style.Tab -padding     {4.5p 1.5p 4.5p 1.5p}\n\t    ttk::style map $style.Tab -padding {selected {4.5p 3p   4.5p 1.5p}}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/classicTheme.tcl",
    "content": "#\n# \"classic\" Tk theme.\n#\n# Implements Tk's traditional Motif-like look and feel.\n#\n\nnamespace eval ttk::theme::classic {\n\n    variable colors\n    array set colors {\n\t-frame\t\t\"#d9d9d9\"\n\t-window\t\t\"#ffffff\"\n\t-alternate\t\"#f0f0f0\"\n\t-activebg\t\"#ececec\"\n\t-troughbg\t\"#b3b3b3\"\n\t-selectbg\t\"#c3c3c3\"\n\t-selectfg\t\"#000000\"\n\t-disabledfg\t\"#a3a3a3\"\n\t-indicator\t\"#b03060\"\n\t-altindicator\t\"#b05e5e\"\n    }\n\n    ttk::style theme settings classic {\n\tttk::style configure \".\" \\\n\t    -font\t\tTkDefaultFont \\\n\t    -background\t\t$colors(-frame) \\\n\t    -foreground\t\tblack \\\n\t    -selectbackground\t$colors(-selectbg) \\\n\t    -selectforeground\t$colors(-selectfg) \\\n\t    -troughcolor\t$colors(-troughbg) \\\n\t    -indicatorcolor\t$colors(-frame) \\\n\t    -highlightcolor\t$colors(-frame) \\\n\t    -highlightthickness\t1 \\\n\t    -borderwidth\t1 \\\n\t    -insertwidth\t2 \\\n\t    -focuswidth\t\t0\n\n\t# To match pre-Xft X11 appearance, use:\n\t#\tttk::style configure . -font {Helvetica 12 bold}\n\n\tttk::style map \".\" -background \\\n\t    [list disabled $colors(-frame) active $colors(-activebg)]\n\tttk::style map \".\" -foreground \\\n\t    [list disabled $colors(-disabledfg)]\n\n\tttk::style map \".\" -highlightcolor {focus black}\n\n\tttk::style configure TButton \\\n\t    -anchor center -padding \"3m 1m\" -relief raised -shiftrelief 1\n\tttk::style map TButton -relief {{!disabled pressed} sunken}\n\n\tttk::style configure TCheckbutton -indicatorrelief raised \\\n\t    -indicatormargin {0 1.5p 3p 1.5p}\n\tttk::style map TCheckbutton \\\n\t    -indicatorcolor [list \\\n\t\t    pressed $colors(-frame) \\\n\t\t    alternate $colors(-altindicator) \\\n\t\t    selected $colors(-indicator)] \\\n\t    -indicatorrelief {alternate raised  selected sunken  pressed sunken}\n\n\tttk::style configure TRadiobutton -indicatorrelief raised \\\n\t    -indicatormargin {0 1.5p 3p 1.5p}\n\tttk::style map TRadiobutton \\\n\t    -indicatorcolor [list \\\n\t\t    pressed $colors(-frame) \\\n\t\t    alternate $colors(-altindicator) \\\n\t\t    selected $colors(-indicator)] \\\n\t    -indicatorrelief {alternate raised  selected sunken  pressed sunken}\n\n\tttk::style configure TMenubutton -relief raised \\\n\t    -indicatormargin {3.75p 0} -padding {3m 1m}\n\n\tttk::style configure TEntry -padding 1 -font TkTextFont\n\tttk::style map TEntry -fieldbackground \\\n\t\t[list readonly $colors(-frame) disabled $colors(-frame)]\n\n\tttk::style element create Combobox.downarrow from default\n\tttk::style configure TCombobox -padding 1 -arrowsize 9p\n\tttk::style map TCombobox -fieldbackground \\\n\t\t[list readonly $colors(-frame) disabled $colors(-frame)]\n\tttk::style configure ComboboxPopdownFrame \\\n\t    -relief solid -borderwidth 1\n\n\tttk::style element create Spinbox.uparrow from default\n\tttk::style element create Spinbox.downarrow from default\n\tttk::style configure TSpinbox -arrowsize 7.5p -padding {1.5p 0 7.5p 0}\n\tttk::style map TSpinbox -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)]\n\n\tttk::style configure TLabelframe -borderwidth 2 -relief groove\n\n\tttk::style configure TScrollbar -relief raised -arrowsize 9p -width 9p\n\tttk::style map TScrollbar -relief {{pressed !disabled} sunken}\n\n\tttk::style configure TScale -sliderrelief raised \\\n\t    -sliderlength 22.5p -sliderthickness 11.25p\n\tttk::style map TScale -sliderrelief {{pressed !disabled} sunken}\n\n\tttk::style configure TProgressbar -background SteelBlue \\\n\t    -barsize 22.5p -thickness 11.25p\n\n\tttk::style configure TNotebook.Tab \\\n\t    -padding {3m 1m} \\\n\t    -background $colors(-troughbg) \\\n\t    -focussolid 1\n\tttk::style map TNotebook.Tab -background [list selected $colors(-frame)]\n\n\t# Treeview:\n\tttk::style configure Heading -font TkHeadingFont -relief raised\n\tttk::style configure Item -indicatorsize 9p \\\n\t    -indicatormargins {1.5p 1.5p 3p 1.5p}\n\tttk::style configure Treeview -background $colors(-window) \\\n\t    -stripedbackground $colors(-alternate) -indent 15p\n\tttk::setTreeviewRowHeight\n\tttk::style configure Treeview.Separator \\\n\t    -background $colors(-alternate)\n\tttk::style map Treeview \\\n\t    -background [list disabled $colors(-frame)\\\n\t\t\t\tselected $colors(-selectbg)] \\\n\t    -foreground [list disabled $colors(-disabledfg) \\\n\t\t\t\tselected $colors(-selectfg)]\n\n\t#\n\t# Toolbar buttons:\n\t#\n\tttk::style layout Toolbutton {\n\t    Toolbutton.focus -children {\n\t\tToolbutton.border -children {\n\t\t    Toolbutton.padding -children {\n\t\t\tToolbutton.label\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tttk::style configure Toolbutton -padding 1.5p -relief flat \\\n\t    -shiftrelief 2 -focussolid 1\n\tttk::style map Toolbutton -relief \\\n\t    {disabled flat selected sunken pressed sunken active raised}\n\tttk::style map Toolbutton -background \\\n\t    [list pressed $colors(-troughbg)  active $colors(-activebg)]\n\n\tttk::style configure Sash \\\n\t    -sashthickness 4.5p -sashpad 1.5 -handlesize 6p -handlepad 6p\n    }\n}\n\n# ttk::theme::classic::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook tab style $style.Tab.\n# Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::classic::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn - s {\n\t    ttk::style configure $style.Tab -padding {3m 1m}\n\t}\n\tw - e {\n\t    ttk::style configure $style.Tab -padding {1m 3m}\n\t}\n\tdefault {\n\t    ttk::style configure $style.Tab -padding {3m 1m}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/combobox.tcl",
    "content": "#\n# Combobox bindings.\n#\n# <<NOTE-WM-TRANSIENT>>:\n#\n#\tNeed to set [wm transient] just before mapping the popdown\n#\tinstead of when it's created, in case a containing frame\n#\thas been reparented [#1818441].\n#\n#\tOn Windows: setting [wm transient] prevents the parent\n#\ttoplevel from becoming inactive when the popdown is posted\n#\t(Tk 8.4.8+)\n#\n#\tOn X11: WM_TRANSIENT_FOR on override-redirect windows\n#\tmay be used by compositing managers and by EWMH-aware\n#\twindow managers (even though the older ICCCM spec says\n#\tit's meaningless).\n#\n#       On OSX: The native combobox uses a popup menu to display the\n#       combobox choices.  So this implementation does that as well,\n#       rather than construc a Tk listbox.  Since the window manager\n#       takes care of scrolling and making sure that the menu can be\n#       displayed even when the button is close to the bottom of the\n#       screen, this actually simplifies the implementation.  The Post\n#       and PopupWindow procs have separate implementations for Aqua\n#       and other systems.  The configuration of the menu is handled\n#       by a different proc than the one which configures the listbox\n#       on other platforms -- ConfigureAquaMenu instead of\n#       ConfigureListbox.\n#\n\nnamespace eval ttk::combobox {\n    variable Values\t;# Values($cb) is -listvariable of listbox widget\n    variable State\n    set State(entryPress) 0\n}\n\n### Combobox bindings.\n#\n# Duplicate the Entry bindings, override if needed:\n#\n\nttk::copyBindings TEntry TCombobox\n\nbind TCombobox <Down>\t\t\t{ ttk::combobox::Post %W }\nbind TCombobox <Escape>\t\t\t{ ttk::combobox::Unpost %W }\n\nbind TCombobox <Button-1>\t\t{ ttk::combobox::Press \"\" %W %x %y }\nbind TCombobox <Shift-Button-1>\t\t{ ttk::combobox::Press \"s\" %W %x %y }\nbind TCombobox <Double-Button-1>\t{ ttk::combobox::Press \"2\" %W %x %y }\nbind TCombobox <Triple-Button-1>\t{ ttk::combobox::Press \"3\" %W %x %y }\nbind TCombobox <B1-Motion>\t\t{ ttk::combobox::Drag %W %x }\nbind TCombobox <Motion>\t\t\t{ ttk::combobox::Motion %W %x %y }\n\nttk::bindMouseWheel TCombobox\t\t{ ttk::combobox::Scroll %W }\nbind TCombobox <Shift-MouseWheel> {\n    # Ignore the event\n}\nbind TCombobox <Shift-Option-MouseWheel> {\n    # Ignore the event\n}\nbind TCombobox <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n    # TouchpadScroll events fire about 60 times per second.\n    if {$tk::Priv(deltaY) != 0 && %# %% 15 == 0} {\n\tttk::combobox::Scroll %W [expr {$tk::Priv(deltaY) > 0 ? -1 : 1}]\n    }\n}\nbind TCombobox <<TraverseIn>>\t\t{ ttk::combobox::TraverseIn %W }\n\n### Combobox listbox bindings.\n#\nbind ComboboxListbox <ButtonRelease-1>\t{ ttk::combobox::LBSelected %W }\nbind ComboboxListbox <Return>\t\t{ ttk::combobox::LBSelected %W }\nbind ComboboxListbox <Escape>\t\t{ ttk::combobox::LBCancel %W }\nbind ComboboxListbox <Tab>\t\t{ ttk::combobox::LBTab %W next }\nbind ComboboxListbox <<PrevWindow>>\t{ ttk::combobox::LBTab %W prev }\nbind ComboboxListbox <Destroy>\t\t{ ttk::combobox::LBCleanup %W }\nbind ComboboxListbox <Motion>\t\t{ ttk::combobox::LBHover %W %x %y }\nbind ComboboxListbox <Map>\t\t{ focus -force %W }\n\nswitch -- [tk windowingsystem] {\n    win32 {\n\t# Dismiss listbox when user switches to a different application.\n\t# NB: *only* do this on Windows (see #1814778)\n\tbind ComboboxListbox <FocusOut>\t\t{ ttk::combobox::LBCancel %W }\n    }\n    aqua {\n\tbind TCombobox <Destroy>\t\t{ ttk::combobox::AquaCleanup %W }\n    }\n}\n\n### Combobox popdown window bindings.\n#\nbind ComboboxPopdown\t<Map>\t\t{ ttk::combobox::MapPopdown %W }\nbind ComboboxPopdown\t<Unmap>\t\t{ ttk::combobox::UnmapPopdown %W }\nbind ComboboxPopdown\t<Button> \\\n\t\t\t{ ttk::combobox::Unpost [winfo parent %W] }\n\n### Option database settings.\n#\n\noption add *TCombobox*Listbox.font TkTextFont widgetDefault\noption add *TCombobox*Listbox.relief flat widgetDefault\noption add *TCombobox*Listbox.highlightThickness 0 widgetDefault\n\n## Platform-specific settings.\n#\nswitch -- [tk windowingsystem] {\n    x11 {\n\toption add *TCombobox*Listbox.background white widgetDefault\n    }\n}\n\n### Binding procedures.\n#\n\n## Press $mode $x $y -- Button binding for comboboxes.\n#\tEither post/unpost the listbox, or perform Entry widget binding,\n#\tdepending on widget state and location of button press.\n#\nproc ttk::combobox::Press {mode w x y} {\n    variable State\n\n    $w instate disabled { return }\n\n    set State(entryPress) [expr {\n\t   [$w instate !readonly]\n\t&& [string match *textarea [$w identify element $x $y]]\n    }]\n\n    focus $w\n    if {$State(entryPress)} {\n\tswitch -- $mode {\n\t    s\t{ ttk::entry::Shift-Press $w $x\t; # Shift }\n\t    2\t{ ttk::entry::Select $w $x word\t; # Double click}\n\t    3\t{ ttk::entry::Select $w $x line\t; # Triple click }\n\t    \"\"\t-\n\t    default { ttk::entry::Press $w $x }\n\t}\n    } else {\n\tPost $w\n    }\n}\n\n## Drag -- B1-Motion binding for comboboxes.\n#\tIf the initial Button event was handled by Entry binding,\n#\tperform Entry widget drag binding; otherwise nothing.\n#\nproc ttk::combobox::Drag {w x}  {\n    variable State\n    if {$State(entryPress)} {\n\tttk::entry::Drag $w $x\n    }\n}\n\n## Motion --\n#\tSet cursor.\n#\nproc ttk::combobox::Motion {w x y} {\n    variable State\n    ttk::saveCursor $w State(userConfCursor) [ttk::cursor text]\n    if {   [$w identify $x $y] eq \"textarea\"\n\t&& [$w instate {!readonly !disabled}]\n    } {\n\tttk::setCursor $w text\n    } else {\n\tttk::setCursor $w $State(userConfCursor)\n    }\n}\n\n## TraverseIn -- receive focus due to keyboard navigation\n#\tFor editable comboboxes, set the selection and insert cursor.\n#\nproc ttk::combobox::TraverseIn {w} {\n    $w instate {!readonly !disabled} {\n\t$w selection range 0 end\n\t$w icursor end\n    }\n}\n\n## SelectEntry $cb $index --\n#\tSet the combobox selection in response to a user action.\n#\nproc ttk::combobox::SelectEntry {cb index} {\n    $cb current $index\n    $cb selection range 0 end\n    $cb icursor end\n    event generate $cb <<ComboboxSelected>> -when mark\n}\n\n## Scroll -- Mousewheel binding\n#\nproc ttk::combobox::Scroll {cb dir {factor 1.0}} {\n    $cb instate disabled { return }\n    set max [llength [$cb cget -values]]\n    set current [$cb current]\n    if {$current < 0} {\n\tset index 0\n    } else {\n\tset d [expr {$dir/$factor}]\n\tset index [expr {$current + int($d > 0 ? ceil($d) : floor($d))}]\n\tif {$index >= $max} {set index [expr {$max - 1}]}\n\tif {$index < 0} {set index 0}\n    }\n    if {$max != 0 && $index != $current} {\n\tSelectEntry $cb $index\n    }\n}\n\n## LBSelected $lb -- Activation binding for listbox\n#\tSet the combobox value to the currently-selected listbox value\n#\tand unpost the listbox.\n#\nproc ttk::combobox::LBSelected {lb} {\n    set cb [LBMain $lb]\n    LBSelect $lb\n    Unpost $cb\n    focus $cb\n}\n\n## LBCancel --\n#\tUnpost the listbox.\n#\nproc ttk::combobox::LBCancel {lb} {\n    Unpost [LBMain $lb]\n}\n\n## LBTab -- Tab key binding for combobox listbox.\n#\tSet the selection, and navigate to next/prev widget.\n#\nproc ttk::combobox::LBTab {lb dir} {\n    set cb [LBMain $lb]\n    switch -- $dir {\n\tnext\t{ set newFocus [tk_focusNext $cb] }\n\tprev\t{ set newFocus [tk_focusPrev $cb] }\n    }\n\n    if {$newFocus ne \"\"} {\n\tLBSelect $lb\n\tUnpost $cb\n\t# The [grab release] call in [Unpost] queues events that later\n\t# re-set the focus (@@@ NOTE: this might not be true anymore).\n\t# Set new focus later:\n\tafter 0 [list ttk::traverseTo $newFocus]\n    }\n}\n\n## LBHover -- <Motion> binding for combobox listbox.\n#\tFollow selection on mouseover.\n#\nproc ttk::combobox::LBHover {w x y} {\n    $w selection clear 0 end\n    $w activate @$x,$y\n    $w selection set @$x,$y\n}\n\n## MapPopdown -- <Map> binding for ComboboxPopdown\n#\nproc ttk::combobox::MapPopdown {w} {\n    [winfo parent $w] state pressed\n    ttk::globalGrab $w\n}\n\n## UnmapPopdown -- <Unmap> binding for ComboboxPopdown\n#\nproc ttk::combobox::UnmapPopdown {w} {\n    [winfo parent $w] state !pressed\n    ttk::releaseGrab $w\n}\n\n## PopdownWindow --\n#\tReturns the popdown widget associated with a combobox,\n#\tcreating it if necessary.\n#\n\nif {[tk windowingsystem] ne \"aqua\"} {\n    proc ttk::combobox::PopdownWindow {cb} {\n\tif {![winfo exists $cb.popdown]} {\n\t    set poplevel [PopdownToplevel $cb.popdown]\n\t    set popdown [ttk::frame $poplevel.f -style ComboboxPopdownFrame]\n\n\t    ttk::scrollbar $popdown.sb \\\n\t\t-orient vertical -command [list $popdown.l yview]\n\t    listbox $popdown.l \\\n\t\t-listvariable ttk::combobox::Values($cb) \\\n\t\t-yscrollcommand [list $popdown.sb set] \\\n\t\t-exportselection false \\\n\t\t-selectmode browse \\\n\t\t-activestyle none \\\n\t\t;\n\n\t    bindtags $popdown.l \\\n\t\t[list $popdown.l ComboboxListbox Listbox $popdown all]\n\n\t    grid $popdown.l -row 0 -column 0 -padx {1 0} -pady 1 -sticky nsew\n\t    grid $popdown.sb -row 0 -column 1 -padx {0 1} -pady 1 -sticky ns\n\t    grid columnconfigure $popdown 0 -weight 1\n\t    grid rowconfigure $popdown 0 -weight 1\n\n\t    grid $popdown -sticky news -padx 0 -pady 0\n\t    grid rowconfigure $poplevel 0 -weight 1\n\t    grid columnconfigure $poplevel 0 -weight 1\n\t}\n\treturn $cb.popdown\n    }\n} else {\n    proc ttk::combobox::PopdownWindow {cb} {\n\tif {![winfo exists $cb.popdown]} {\n\t    set poplevel [PopdownToplevel $cb.popdown]\n\t    # The menu should be (at least) the same length as the button.\n\t    # Since there is no direct way to control the width of a menu\n\t    # in Tk, we fake it by using an invisible image in a disabled\n\t    # menu item, adjusting the image size to make the menu be the\n\t    # correct width.\n\t    image create nsimage $cb.spacer -source NSStatusNone -as name \\\n\t\t-alpha 0\n\t    set menu [menu $cb.popdown.menu -tearoff 0]\n\t}\n\treturn $cb.popdown\n    }\n}\n\n## PopdownToplevel -- Create toplevel window for the combobox popdown\n#\n#\tSee also <<NOTE-WM-TRANSIENT>>\n#\nproc ttk::combobox::PopdownToplevel {w} {\n    toplevel $w -class ComboboxPopdown\n    wm withdraw $w\n    switch -- [tk windowingsystem] {\n\tdefault -\n\tx11 {\n\t    $w configure -relief flat -borderwidth 0\n\t    wm attributes $w -type combo\n\t    wm overrideredirect $w true\n\t}\n\twin32 {\n\t    $w configure -relief flat -borderwidth 0\n\t    wm overrideredirect $w true\n\t    wm attributes $w -topmost 1\n\t}\n\taqua {\n\t    wm overrideredirect $w true\n\t    wm attributes $w -alpha 0\n\t}\n    }\n    return $w\n}\n\n## ConfigureListbox --\n#\tSet listbox values, selection, height, and scrollbar visibility\n#\tfrom current combobox values.\n#\nproc ttk::combobox::ConfigureListbox {cb} {\n    variable Values\n\n    set popdown [PopdownWindow $cb].f\n    set values [$cb cget -values]\n    set current [$cb current]\n    if {$current < 0} {\n\tset current 0\t\t;# no current entry, highlight first one\n    }\n    set Values($cb) $values\n    $popdown.l selection clear 0 end\n    $popdown.l selection set $current\n    $popdown.l activate $current\n    $popdown.l see $current\n    set height [llength $values]\n    if {$height > [$cb cget -height]} {\n\tset height [$cb cget -height]\n\tgrid $popdown.sb\n\tgrid configure $popdown.l -padx {1 0}\n    } else {\n\tgrid remove $popdown.sb\n\tgrid configure $popdown.l -padx 1\n    }\n    $popdown.l configure -height $height\n}\n\nproc ttk::combobox::ConfigureAquaMenu {cb width} {\n    set popdown [PopdownWindow $cb]\n    set values [$cb cget -values]\n    set current [$cb current]\n    if {$current < 0} {\n\tset current 0\t\t;# no current entry, highlight first one\n    }\n    $cb.popdown.menu delete 0 end\n    $cb.spacer configure -width [expr {$width - 40}] -height 1\n    set i 0\n    foreach item $values {\n\tif {$i == 0} {\n\t    # Add spaces to the first item to make the menu as long as cb\n\t    set menufont [$cb cget -font]\n\t    set stretch $item\n\t    while {[font measure $menufont $stretch] < [expr {$width - 32}]} {\n\t\tset stretch \"$stretch \"\n\t    }\n\t    $cb.popdown.menu add command -label \"$stretch\" \\\n\t\t-command \"ttk::combobox::SelectEntry $cb $i\"\n\t} else {\n\t    $cb.popdown.menu add command -label \"$item\" \\\n\t\t-command \"ttk::combobox::SelectEntry $cb $i\"\n\t}\n\tincr i\n    }\n    if { $i == 0 } {\n\t# There are no items.  To make an empty menu appear add a dummy item\n\t# containing a transparent image of the right width.\n\t$cb.popdown.menu add command -label {} -image $cb.spacer -state disabled\n    }\n}\n\n## PlacePopdown --\n#\tSet popdown window geometry.\n#\n# @@@TODO: factor with menubutton::PostPosition\n#\nproc ttk::combobox::PlacePopdown {cb popdown} {\n    set x [winfo rootx $cb]\n    set y [winfo rooty $cb]\n    set w [winfo width $cb]\n    set h [winfo height $cb]\n    set style [$cb cget -style]\n    if { $style eq {} } {\n      set style TCombobox\n    }\n    set postoffset [ttk::style lookup $style -postoffset {} {0 0 0 0}]\n    foreach var {x y w h} delta $postoffset {\n\tincr $var $delta\n    }\n\n    set H [winfo reqheight $popdown]\n    if {$y + $h + $H > [winfo screenheight $popdown]} {\n\tset Y [expr {$y - $H}]\n    } else {\n\tset Y [expr {$y + $h}]\n    }\n    wm geometry $popdown ${w}x${H}+${x}+${Y}\n}\n\nproc ttk::combobox::AquaPlacePopdown {cb popdown} {\n    set x [winfo rootx $cb]\n    set y [winfo rooty $cb]\n    set w [winfo width $cb]\n    set h [winfo height $cb]\n    set style [$cb cget -style]\n    set postoffset [ttk::style lookup $style -postoffset {} {0 0 0 0}]\n    foreach var {x y w h} delta $postoffset {\n\tincr $var $delta\n    }\n    wm geometry $popdown ${w}x${h}+${x}+${y}\n    return [list $x $y $w $h]\n}\n\n## Post $cb --\n#\tPop down the associated listbox or menu.\n#\nif {[tk windowingsystem] ne \"aqua\"} {\n    proc ttk::combobox::Post {cb} {\n\t# Don't do anything if disabled:\n\t#\n\t$cb instate disabled { return }\n\n\t# ASSERT: ![$cb instate pressed]\n\n\t# Run -postcommand callback:\n\t#\n\tuplevel #0 [$cb cget -postcommand]\n\n\tset popdown [PopdownWindow $cb]\n\tConfigureListbox $cb\n\tupdate idletasks\t;# needed for geometry propagation.\n\tPlacePopdown $cb $popdown\n\t# See <<NOTE-WM-TRANSIENT>>\n\tswitch -- [tk windowingsystem] {\n\t    x11 - win32 { wm transient $popdown [winfo toplevel $cb] }\n\t}\n\n\t# Post the listbox:\n\t#\n\twm attribute $popdown -topmost 1\n\twm deiconify $popdown\n\traise $popdown\n    }\n} else {\n    proc ttk::combobox::Post {cb} {\n\t# Don't do anything if disabled:\n\t#\n\t$cb instate disabled { return }\n\n\t# ASSERT: ![$cb instate pressed]\n\n\t# Run -postcommand callback:\n\t#\n\tuplevel #0 [$cb cget -postcommand]\n\n\tset popdown [PopdownWindow $cb]\n\n\t# Configure the menu\n\n\tforeach {x y width height} [AquaPlacePopdown $cb $popdown] { break }\n\tConfigureAquaMenu $cb [winfo width $cb]\n\n\t# Post the menu.  It will have a disclosure indicator if it is too\n\t# close to the bottom of the screen, and it may be posted above the\n\t# button if necessary to be visible.\n\n\t$popdown.menu post [expr {$x + 2}] [expr {$y + $height + 2}]\n    }\n}\n\n## Unpost $cb --\n#\tUnpost the listbox.\n#\nproc ttk::combobox::Unpost {cb} {\n    if {[winfo exists $cb.popdown]} {\n\twm withdraw $cb.popdown\n    }\n    grab release $cb.popdown ;# in case of stuck or unexpected grab [#1239190]\n}\n\n## LBMain $lb --\n#\tReturn the combobox main widget that owns the listbox.\n#\nproc ttk::combobox::LBMain {lb} {\n    winfo parent [winfo parent [winfo parent $lb]]\n}\n\n## LBSelect $lb --\n#\tTransfer listbox selection to combobox value.\n#\nproc ttk::combobox::LBSelect {lb} {\n    set cb [LBMain $lb]\n    set selection [$lb curselection]\n    if {[llength $selection] == 1} {\n\tSelectEntry $cb [lindex $selection 0]\n    }\n}\n\n## LBCleanup $lb --\n#\t<Destroy> binding for combobox listboxes.\n#\tCleans up by unsetting the linked textvariable.\n#\n#\tNote: we can't just use { unset [%W cget -listvariable] }\n#\tbecause the widget command is already gone when this binding fires).\n#\t[winfo parent] still works, fortunately.\n#\nproc ttk::combobox::LBCleanup {lb} {\n    variable Values\n    unset Values([LBMain $lb])\n}\n\nproc ttk::combobox::AquaCleanup {cb} {\n    catch {image delete $cb.spacer}\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/cursors.tcl",
    "content": "#\n# Map symbolic cursor names to platform-appropriate cursors.\n#\n# The following cursors are defined:\n#\n#\tstandard\t-- default cursor for most controls\n#\t\"\"\t\t-- inherit cursor from parent window\n#\tnone\t\t-- no cursor\n#\n#\ttext\t\t-- editable widgets (entry, text)\n#\tlink\t\t-- hyperlinks within text\n#\tcrosshair\t-- graphic selection, fine control\n#\tbusy\t\t-- operation in progress\n#\tforbidden\t-- action not allowed\n#\n#\thresize\t\t-- horizontal resizing\n#\tvresize\t\t-- vertical resizing\n#\n# Also resize cursors for each of the compass points,\n# {nw,n,ne,w,e,sw,s,se}resize.\n#\n# Platform notes:\n#\n# Windows doesn't distinguish resizing at the 8 compass points,\n# only horizontal, vertical, and the two diagonals.\n#\n# OSX doesn't have resize cursors for nw, ne, sw, or se corners.\n# We use the Tk-defined X11 fallbacks for these.\n#\n# X11 doesn't have a \"forbidden\" cursor (usually a slashed circle);\n# \"pirate\" seems to be the conventional cursor for this purpose.\n#\n# Windows has an IDC_HELP cursor, but it's not available from Tk.\n#\n# Tk does not support \"none\" on Windows.\n#\n\nnamespace eval ttk {\n\n    variable Cursors\n\n    # Use X11 cursor names as defaults, since Tk supplies these\n    # on all platforms.\n    #\n    array set Cursors {\n\t\"\"\t\t\"\"\n\tnone\t\tnone\n\n\tstandard\tleft_ptr\n\ttext\t\txterm\n\tlink\t\thand2\n\tcrosshair\tcrosshair\n\tbusy\t\twatch\n\tforbidden\tpirate\n\n\thresize\t\tsb_h_double_arrow\n\tvresize\t\tsb_v_double_arrow\n\n\tnresize\t\ttop_side\n\tsresize\t\tbottom_side\n\twresize\t\tleft_side\n\teresize\t\tright_side\n\tnwresize\ttop_left_corner\n\tneresize\ttop_right_corner\n\tswresize\tbottom_left_corner\n\tseresize\tbottom_right_corner\n\tmove\t\tfleur\n\n    }\n\n    # Platform-specific overrides for Windows and OSX.\n    #\n    switch [tk windowingsystem] {\n\t\"win32\" {\n\t    array set Cursors {\n\t\tnone\t\t{}\n\n\t\tstandard\tarrow\n\t\ttext\t\tibeam\n\t\tlink\t\thand2\n\t\tcrosshair\tcrosshair\n\t\tbusy\t\twait\n\t\tforbidden\tno\n\n\t\tvresize\t\tsize_ns\n\t\tnresize\t\tsize_ns\n\t\tsresize\t\tsize_ns\n\n\t\twresize\t\tsize_we\n\t\teresize\t\tsize_we\n\t\thresize\t\tsize_we\n\n\t\tnwresize\tsize_nw_se\n\t\tswresize\tsize_ne_sw\n\n\t\tneresize\tsize_ne_sw\n\t\tseresize\tsize_nw_se\n\t    }\n\t}\n\n\t\"aqua\" {\n\t    array set Cursors {\n\t\tstandard\tarrow\n\t\ttext\t\tibeam\n\t\tlink\t\tpointinghand\n\t\tcrosshair\tcrosshair\n\t\tbusy\t\twatch\n\t\tforbidden\tnotallowed\n\n\t\thresize\t\tresizeleftright\n\t\tvresize\t\tresizeupdown\n\t\tnresize\t\tresizeup\n\t\tsresize\t\tresizedown\n\t\twresize\t\tresizeleft\n\t\teresize\t\tresizeright\n\t    }\n\t}\n    }\n}\n\n## ttk::cursor $cursor --\n#\tReturn platform-specific cursor for specified symbolic cursor.\n#\nproc ttk::cursor {name} {\n    variable Cursors\n    return $Cursors($name)\n}\n\n## ttk::setCursor $w $cursor --\n#\tSet the cursor for specified window.\n#\n# [ttk::setCursor] should be used in <Motion> bindings\n# instead of directly calling [$w configure -cursor ...],\n# as the latter always incurs a server round-trip and\n# can lead to high CPU load (see [#1184746])\n#\n\nproc ttk::setCursor {w name} {\n    variable Cursors\n    if {[info exists Cursors($name)]} {\n\tset cursorname $Cursors($name)\n    }  else {\n\tset cursorname $name\n    }\n    if {[$w cget -cursor] ne $cursorname} {\n\t$w configure -cursor $cursorname\n    }\n}\n\n## ttk::saveCursor $w $saveVar $excludeList --\n#       Set variable $saveVar to the -cursor value from widget $w,\n#       if either:\n#       a. $saveVar does not yet exist\n#       b. the currently user-specified cursor for $w is not in\n#          $excludeList\n\nproc ttk::saveCursor {w saveVar excludeList} {\n    upvar $saveVar sv\n    if {![info exists sv]} {\n\tset sv [$w cget -cursor]\n    }\n    if {[$w cget -cursor] ni $excludeList} {\n\tset sv [$w cget -cursor]\n    }\n}\n\n## Interactive test harness:\n#\nproc ttk::CursorSampler {f} {\n    ttk::frame $f\n\n    set r 0\n    foreach row {\n\t{nwresize nresize   neresize}\n\t{ wresize move       eresize}\n\t{swresize sresize   seresize}\n\t{text link crosshair}\n\t{hresize vresize \"\"}\n\t{busy forbidden \"\"}\n\t{none standard \"\"}\n    } {\n\tset c 0\n\tforeach cursor $row {\n\t    set w $f.${r}${c}\n\t    ttk::label $w -text $cursor -cursor [ttk::cursor $cursor] \\\n\t\t-relief solid -borderwidth 1 -padding 3\n\t    grid $w -row $r -column $c -sticky nswe\n\t    grid columnconfigure $f $c -uniform cols -weight 1\n\t    incr c\n\t}\n\tgrid rowconfigure $f $r -uniform rows -weight 1\n\tincr r\n    }\n\n    return $f\n}\n\nif {[info exists argv0] && $argv0 eq [info script]} {\n    wm title . \"[array size ::ttk::Cursors] cursors\"\n    pack [ttk::CursorSampler .f] -expand true -fill both\n    bind . <Escape> [list destroy .]\n    focus .f\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/defaults.tcl",
    "content": "#\n# Settings for default theme.\n#\n\nnamespace eval ttk::theme::default {\n\n    variable colors\n    array set colors {\n\t-frame\t\t\t\"#d9d9d9\"\n\t-foreground\t\t\"#000000\"\n\t-window\t\t\t\"#ffffff\"\n\t-alternate\t\t\"#e8e8e8\"\n\t-text\t\t\t\"#000000\"\n\t-activebg\t\t\"#ececec\"\n\t-selectbg\t\t\"#4a6984\"\n\t-selectfg\t\t\"#ffffff\"\n\t-darker\t\t\t\"#c3c3c3\"\n\t-disabledfg\t\t\"#a3a3a3\"\n\t-indicator\t\t\"#4a6984\"\n\t-disabledindicator\t\"#a3a3a3\"\n\t-pressedindicator\t\"#5895bc\"\n    }\n\n    # On X11, if the user specifies their own choice of colour scheme via\n    # X resources, then set the colour palette based on the user's choice.\n    if {[tk windowingsystem] eq \"x11\"} {\n\tforeach \\\n\t\txResourceName {\n\t\t    {\tbackground\t\tBackground\t\t}\n\t\t    {\tforeground\t\tForeground\t\t}\n\t\t    {\tbackground\t\tBackground\t\t}\n\t\t    {\tbackground\t\tBackground\t\t}\n\t\t    {\tforeground\t\tForeground\t\t}\n\t\t    {\tactiveBackground\tActiveBackground\t}\n\t\t    {\tselectBackground\tSelectBackground\t}\n\t\t    {\tselectForeground\tSelectForeground\t}\n\t\t    {\ttroughColor\t\tTroughColor\t\t}\n\t\t    {\tdisabledForeground\tDisabledForeground\t}\n\t\t    {\tselectBackground\tSelectBackground\t}\n\t\t    {\tdisabledForeground\tDisabledForeground\t}\n\t\t    {\tselectBackground\tSelectBackground\t}\n\t\t    {\twindowColor\t\tBackground\t\t} } \\\n\t\tcolorName {\n\t\t    -frame -foreground -window -alternate -text\n\t\t    -activebg -selectbg -selectfg\n\t\t    -darker -disabledfg -indicator\n\t\t    -disabledindicator -pressedindicator -window } {\n\t    set color [eval option get . $xResourceName]\n\t    if {$color ne \"\"} {\n\t\tset colors($colorName) $color\n\t    }\n\t}\n    }\n\n    # This array is used to match up the tk widget options with\n    # the corresponding values in the 'colors' array.\n    # This is used by tk_setPalette to apply the new palette\n    # to the ttk widgets.\n    variable colorOptionLookup\n    array set colorOptionLookup {\n\tbackground\t\t{-frame -window -alternate}\n\tforeground\t\t{-foreground -text}\n\tactiveBackground\t-activebg\n\tselectBackground\t{-selectbg -indicator -pressedindicator}\n\tselectForeground\t-selectfg\n\ttroughColor\t\t-darker\n\tdisabledForeground\t{-disabledfg -disabledindicator}\n    }\n}\n\n# ttk::theme::default::reconfigureDefaultTheme --\n#\n# This procedure contains the definition of the 'default' theme itself.\n# The theme definition is in a procedure, so it can be re-called when\n# required, enabling tk_setPalette to set the colours of the ttk widgets.\n#\n# Arguments:\n# None.\n\nproc ttk::theme::default::reconfigureDefaultTheme {} {\n    upvar ttk::theme::default::colors colors\n\n    # The definition of the 'default' theme.\n\n    ttk::style theme settings default {\n\n\tttk::style configure \".\" \\\n\t    -borderwidth\t1 \\\n\t    -background\t\t$colors(-frame) \\\n\t    -foreground\t\t$colors(-foreground) \\\n\t    -troughcolor\t$colors(-darker) \\\n\t    -font\t\tTkDefaultFont \\\n\t    -selectbackground\t$colors(-selectbg) \\\n\t    -selectforeground\t$colors(-selectfg) \\\n\t    -insertwidth\t1 \\\n\t    -insertcolor\t$colors(-foreground) \\\n\t    -focuscolor\t\t$colors(-text)\n\n\tttk::style map \".\" -background \\\n\t    [list disabled $colors(-frame)  active $colors(-activebg)]\n\tttk::style map \".\" -foreground \\\n\t    [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TButton \\\n\t    -anchor center -padding 2.25p -width -9 \\\n\t    -relief raised -shiftrelief 1\n\tttk::style map TButton -relief [list {!disabled pressed} sunken]\n\n\tforeach style {TCheckbutton TRadiobutton} {\n\t    ttk::style configure $style \\\n\t\t-indicatorbackground $colors(-window) \\\n\t\t-indicatorforeground $colors(-selectfg) \\\n\t\t-indicatormargin {0 1.5p 3p 1.5p} -padding 0.75p\n\t    ttk::style map $style -indicatorbackground \\\n\t\t[list {alternate disabled}\t$colors(-disabledindicator) \\\n\t\t      {alternate pressed}\t$colors(-pressedindicator) \\\n\t\t      alternate\t\t\t$colors(-indicator) \\\n\t\t      {selected disabled}\t$colors(-disabledindicator) \\\n\t\t      {selected pressed}\t$colors(-pressedindicator) \\\n\t\t      selected\t\t\t$colors(-indicator) \\\n\t\t      disabled\t\t\t$colors(-frame) \\\n\t\t      pressed\t\t\t$colors(-darker)]\n\t}\n\n\tttk::style configure TMenubutton \\\n\t    -relief raised -arrowsize 3.75p -arrowpadding 2.25p \\\n\t    -arrowcolor $colors(-text) -padding {7.5p 2.25p}\n\tttk::style map TMenubutton \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TEntry \\\n\t    -fieldbackground $colors(-window) -padding 1 \\\n\t    -focuswidth 2 -focuscolor $colors(-selectbg)\n\tttk::style map TEntry -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)]\n\n\tttk::style configure TCombobox \\\n\t    -arrowsize 9p -arrowcolor $colors(-text) \\\n\t    -fieldbackground $colors(-window) -padding 1 \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::style map TCombobox -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TSpinbox \\\n\t    -arrowsize 7.5p -arrowcolor $colors(-text) \\\n\t    -fieldbackground $colors(-window) -padding {1.5p 0 7.5p 0} \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::style map TSpinbox -fieldbackground \\\n\t    [list readonly $colors(-frame) disabled $colors(-frame)] \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TLabelframe \\\n\t    -relief groove -borderwidth 2\n\n\tttk::style configure TScrollbar \\\n\t    -width 9p -arrowsize 9p -arrowcolor $colors(-text)\n\tttk::style map TScrollbar \\\n\t    -arrowcolor [list disabled $colors(-disabledfg)]\n\n\tttk::style configure TScale \\\n\t    -innercolor $colors(-selectbg) \\\n\t    -outercolor $colors(-window) \\\n\t    -bordercolor $colors(-darker) \\\n\t    -groovewidth 3p\n\tttk::style map TScale \\\n\t    -outercolor [list active $colors(-activebg)]\n\n\tttk::style configure TProgressbar \\\n\t    -background $colors(-selectbg) \\\n\t    -borderwidth 0 \\\n\t    -barsize 22.5p \\\n\t    -thickness 3p\n\n\tttk::style configure TNotebook.Tab \\\n\t    -padding {3p 1.5p} -background $colors(-darker)\n\tttk::style map TNotebook.Tab \\\n\t    -background [list selected $colors(-frame)] \\\n\t    -highlight [list selected 1] \\\n\t    -highlightcolor [list selected $colors(-selectbg)]\n\n\t# Treeview\n\tttk::style configure Heading -font TkHeadingFont -relief raised\n\tttk::style configure Item -indicatorsize 9p \\\n\t    -indicatormargins {1.5p 1.5p 3p 1.5p}\n\tttk::style configure Treeview \\\n\t    -background $colors(-window) \\\n\t    -stripedbackground $colors(-alternate) \\\n\t    -fieldbackground $colors(-window) \\\n\t    -foreground $colors(-text) \\\n\t    -indent 15p \\\n\t    -focuswidth 1 -focuscolor $colors(-selectbg)\n\tttk::setTreeviewRowHeight\n\tttk::style configure Treeview.Separator \\\n\t    -background $colors(-alternate)\n\tttk::style map Treeview \\\n\t    -background [list disabled $colors(-frame)\\\n\t\t\t\tselected $colors(-selectbg)] \\\n\t    -foreground [list disabled $colors(-disabledfg) \\\n\t\t\t\tselected $colors(-selectfg)]\n\n\t# Combobox popdown frame\n\tttk::style layout ComboboxPopdownFrame {\n\t    ComboboxPopdownFrame.border -sticky nswe\n\t}\n\tttk::style configure ComboboxPopdownFrame \\\n\t    -borderwidth 1 -relief solid\n\n\t#\n\t# Toolbar buttons:\n\t#\n\tttk::style layout Toolbutton {\n\t    Toolbutton.border -children {\n\t\tToolbutton.focus -children {\n\t\t    Toolbutton.padding -children {\n\t\t\tToolbutton.label\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tttk::style configure Toolbutton \\\n\t    -padding 1.5p -relief flat\n\tttk::style map Toolbutton -relief \\\n\t    [list disabled flat selected sunken pressed sunken active raised]\n\tttk::style map Toolbutton -background \\\n\t    [list pressed $colors(-darker)  active $colors(-activebg)]\n    }\n}\n\nttk::theme::default::reconfigureDefaultTheme\n\n# ttk::theme::default::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook tab style $style.Tab.\n# Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::default::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn - s {\n\t    ttk::style configure $style.Tab -padding {3p 1.5p}\n\t}\n\tw - e {\n\t    ttk::style configure $style.Tab -padding {1.5p 3p}\n\t}\n\tdefault {\n\t    ttk::style configure $style.Tab -padding {3p 1.5p}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/elements.tcl",
    "content": "#==============================================================================\n# elements.tcl - Copyright © 2025 Csaba Nemethi <csaba.nemethi@t-online.de>\n#\n# Contains procedures that create the Tglswitch*.trough and Tglswitch*.slider\n# elements for the Toggleswitch* styles.\n#\n# Structure of the module:\n#   - Private helper procedures and data\n#   - Generic private procedures creating the elements for arbitrary themes\n#   - Private procedures creating the elements for a few built-in themes\n#   - Public procedures\n#==============================================================================\n\n# Private helper procedures and data\n# ==================================\n\nnamespace eval ttk::toggleswitch {}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::Rgb2Hsv\n#\n# Converts the specified RGB value to HSV.  The argument is assumed to be of\n# the form \"#RRGGBB\".  The return value is a list of the form {h s v}, where h\n# in [0.0, 360.0) and s, v in [0.0, 100.0].\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::Rgb2Hsv rgb {\n    scan $rgb \"#%02x%02x%02x\" r g b\n    set r [expr {$r / 255.0}]\n    set g [expr {$g / 255.0}]\n    set b [expr {$b / 255.0}]\n\n    set min [expr {min($r, $g, $b)}]\n    set max [expr {max($r, $g, $b)}]\n    set d [expr {$max - $min}]\n\n    # Compute the saturation and value\n    set s [expr {$max == 0 ? 0 : 100 * $d / $max}]\n    set v [expr {100 * $max}]\n\n    # Compute the hue\n    if {$d == 0} {\n\tset h 0.0\n    } elseif {$max == $r} {\n\tset frac [expr {fmod(($g - $b) / $d, 6)}]\n\tif {$frac < 0} { set frac [expr {$frac + 6}] }\n\tset h [expr {60 * $frac}]\n    } elseif {$max == $g} {\n\tset h [expr {60 * (($b - $r) / $d + 2)}]\n    } else {\n\tset h [expr {60 * (($r - $g) / $d + 4)}]\n    }\n\n    return [list $h $s $v]\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::Hsv2Rgb\n#\n# Converts the specified HSV value to RGB.  The arguments are assumed to fulfil\n# the conditions: h in [0.0, 360.0) and s, v in [0.0, 100.0].  The return value\n# is a color specification of the form \"#RRGGBB\".\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::Hsv2Rgb {h s v} {\n    set s [expr {$s / 100.0}]; set v [expr {$v / 100.0}]\n    set c [expr {$s * $v}]\t\t\t\t;# chroma\n    set h [expr {$h / 60.0}]\t\t\t\t;# in [0.0, 6.0)\n    set x [expr {$c * (1 - abs(fmod($h, 2) - 1))}]\t;# intermediate value\n\n    switch [expr {int($h)}] {\n\t0 { set r $c;  set g $x;  set b  0 }\n\t1 { set r $x;  set g $c;  set b  0 }\n\t2 { set r  0;  set g $c;  set b $x }\n\t3 { set r  0;  set g $x;  set b $c }\n\t4 { set r $x;  set g  0;  set b $c }\n\t5 { set r $c;  set g  0;  set b $x }\n    }\n\n    set m [expr {$v - $c}]\t\t\t\t;# lightness adjustment\n    set r [expr {round(255 * ($r + $m))}]\n    set g [expr {round(255 * ($g + $m))}]\n    set b [expr {round(255 * ($b + $m))}]\n\n    return [format \"#%02x%02x%02x\" $r $g $b]\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::NormalizeColor\n#\n# Returns the representation of a given color in the form \"#RRGGBB\".\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::NormalizeColor color {\n    lassign [winfo rgb . $color] r g b\n    return [format \"#%02x%02x%02x\" \\\n\t    [expr {$r >> 8}] [expr {$g >> 8}] [expr {$b >> 8}]]\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::IsColorLight\n#\n# Checks whether a given color can be classified as light.\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::IsColorLight color {\n    lassign [winfo rgb . $color] r g b\n    return [expr {5 * ($g >> 8) + 2 * ($r >> 8) + ($b >> 8) > 8 * 192}]\n}\n\ninterp alias {} ttk::toggleswitch::CreateElem {} ttk::style element create\n\nnamespace eval ttk::toggleswitch {\n    variable troughData\n    set troughData(1) {\n<svg width=\"32\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"32\" height=\"16\" rx=\"8\" }\n    set troughData(2) {\n<svg width=\"40\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"40\" height=\"20\" rx=\"10\" }\n    set troughData(3) {\n<svg width=\"48\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"48\" height=\"24\" rx=\"12\" }\n\n    variable sliderData\n    set sliderData(1) {\n<svg width=\"16\" height=\"12\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"8\" cy=\"6\" r=\"6\" }\n    set sliderData(2) {\n<svg width=\"20\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"8\" r=\"8\" }\n    set sliderData(3) {\n<svg width=\"24\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"10\" r=\"10\" }\n\n    variable onAndroid\t  [expr {[info exists ::tk::android] && $::tk::android}]\n    variable madeElements 0\n}\n\n# Generic private procedures creating the elements for arbitrary themes\n# =====================================================================\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_genericLight\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_genericLight {} {\n    variable troughData\n    variable sliderData\n    variable onAndroid\n\n    set bg [ttk::style lookup . -background {} #d9d9d9]\n    scan [NormalizeColor $bg] \"#%02x%02x%02x\" r g b\n    set hasDarkerBg [expr {$r <= 0xd9 && $g <= 0xd9 && $b <= 0xd9}]\n\n    set selBg [ttk::style lookup . -selectbackground {} #000000]\n    if {[IsColorLight $selBg]} { set selBg #4a6984 }\n    set selBg [NormalizeColor $selBg]\n\n    foreach n {1 2 3} {\n\t# troughOffImg\n\tset imgData $troughData($n)\n\tset fill [expr {$hasDarkerBg ? \"#c3c3c3\" : \"#d3d3d3\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffImg [CreateImg -data $imgData]\n\n\t# troughOffActiveImg\n\tset imgData $troughData($n)\n\tset fill2 [expr {$hasDarkerBg ? \"#b3b3b3\" : \"#c3c3c3\"}]\n\tset fill [expr {$onAndroid ? $fill : $fill2}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffActiveImg [CreateImg -data $imgData]\n\n\t# troughOffPressedImg\n\tset imgData $troughData($n)\n\tset fill [expr {$hasDarkerBg ? \"#a3a3a3\" : \"#b3b3b3\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffPressedImg [CreateImg -data $imgData]\n\n\t# troughOffDisabledImg\n\tset imgData $troughData($n)\n\tset fill [expr {$hasDarkerBg ? \"#d1d1d1\" : \"#e1e1e1\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffDisabledImg [CreateImg -data $imgData]\n\n\t# troughOnImg\n\tset imgData $troughData($n)\n\tset fill $selBg\n\tlassign [Rgb2Hsv $fill] h s v\n\tset dv [expr {$v < 80 ? 10 : -10}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnImg [CreateImg -data $imgData]\n\n\t# troughOnActiveImg\n\tset imgData $troughData($n)\n\tset v [expr {$v + $dv}]\n\tset fill [expr {$onAndroid ? $fill : [Hsv2Rgb $h $s $v]}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnActiveImg [CreateImg -data $imgData]\n\n\t# troughOnPressedImg\n\tset imgData $troughData($n)\n\tset v [expr {$v + $dv}]\n\tappend imgData \"fill='[Hsv2Rgb $h $s $v]'/>\\n</svg>\"\n\tset troughOnPressedImg [CreateImg -data $imgData]\n\n\t# troughOnDisabledImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='[Hsv2Rgb $h 33.3 100]'/>\\n</svg>\"\n\tset troughOnDisabledImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.trough image [list $troughOffImg \\\n\t    {selected disabled}\t$troughOnDisabledImg \\\n\t    {selected pressed}\t$troughOnPressedImg \\\n\t    {selected active}\t$troughOnActiveImg \\\n\t    selected\t\t$troughOnImg \\\n\t    disabled\t\t$troughOffDisabledImg \\\n\t    pressed\t\t$troughOffPressedImg \\\n\t    active\t\t$troughOffActiveImg \\\n\t]\n\n\t# sliderImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.slider image $sliderImg\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_genericDark\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_genericDark {} {\n    variable troughData\n    variable sliderData\n    variable onAndroid\n\n    set selBg [ttk::style lookup . -selectbackground {} #000000]\n    if {[IsColorLight $selBg]} { set selBg #4a6984 }\n    set selBg [NormalizeColor $selBg]\n\n    foreach n {1 2 3} {\n\t# troughOffImg\n\tset imgData $troughData($n)\n\tset fill \"#585858\"\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffImg [CreateImg -data $imgData]\n\n\t# troughOffActiveImg\n\tset imgData $troughData($n)\n\tset fill [expr {$onAndroid ? $fill : \"#676767\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffActiveImg [CreateImg -data $imgData]\n\n\t# troughOffPressedImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='#787878'/>\\n</svg>\"\n\tset troughOffPressedImg [CreateImg -data $imgData]\n\n\t# troughOffDisabledImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='#4a4a4a'/>\\n</svg>\"\n\tset troughOffDisabledImg [CreateImg -data $imgData]\n\n\t# troughOnImg\n\tset imgData $troughData($n)\n\tset fill $selBg\n\tlassign [Rgb2Hsv $fill] h s v\n\tset vOrig $v\n\tset dv [expr {$v < 80 ? 10 : -10}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnImg [CreateImg -data $imgData]\n\n\t# troughOnActiveImg\n\tset imgData $troughData($n)\n\tset v [expr {$v + $dv}]\n\tset fill [expr {$onAndroid ? $fill : [Hsv2Rgb $h $s $v]}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnActiveImg [CreateImg -data $imgData]\n\n\t# troughOnPressedImg\n\tset imgData $troughData($n)\n\tset v [expr {$v + $dv}]\n\tappend imgData \"fill='[Hsv2Rgb $h $s $v]'/>\\n</svg>\"\n\tset troughOnPressedImg [CreateImg -data $imgData]\n\n\t# troughOnDisabledImg\n\tset imgData $troughData($n)\n\tset v [expr {$vOrig - 10}]\n\tif {$v < 0} { set v 0 }\n\tappend imgData \"fill='[Hsv2Rgb $h $s $v]'/>\\n</svg>\"\n\tset troughOnDisabledImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.trough image [list $troughOffImg \\\n\t    {selected disabled}\t$troughOnDisabledImg \\\n\t    {selected pressed}\t$troughOnPressedImg \\\n\t    {selected active}\t$troughOnActiveImg \\\n\t    selected\t\t$troughOnImg \\\n\t    disabled\t\t$troughOffDisabledImg \\\n\t    pressed\t\t$troughOffPressedImg \\\n\t    active\t\t$troughOffActiveImg \\\n\t]\n\n\t# sliderOffImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#d3d3d3'/>\\n</svg>\"\n\tset sliderOffImg [CreateImg -data $imgData]\n\n\t# sliderOffDisabledImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#888888'/>\\n</svg>\"\n\tset sliderOffDisabledImg [CreateImg -data $imgData]\n\n\t# sliderOnDisabledImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#9f9f9f'/>\\n</svg>\"\n\tset sliderOnDisabledImg [CreateImg -data $imgData]\n\n\t# sliderImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.slider image [list $sliderOffImg \\\n\t    {selected disabled}\t$sliderOnDisabledImg \\\n\t    selected\t\t$sliderImg \\\n\t    disabled\t\t$sliderOffDisabledImg \\\n\t    pressed\t\t$sliderImg \\\n\t    active\t\t$sliderImg \\\n\t]\n    }\n}\n\n# Private procedures creating the elements for a few built-in themes\n# ==================================================================\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_clam\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_clam {} {\n    variable troughData\n    variable sliderData\n    variable onAndroid\n\n    foreach n {1 2 3} {\n\t# troughOffImg\n\tset imgData $troughData($n)\n\tset fill \"#bab5ab\"\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffImg [CreateImg -data $imgData]\n\n\t# troughOffActiveImg\n\tset imgData $troughData($n)\n\tset fill [expr {$onAndroid ? $fill : \"#aca79e\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOffActiveImg [CreateImg -data $imgData]\n\n\t# troughOffPressedImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='#9e9a91'/>\\n</svg>\"\n\tset troughOffPressedImg [CreateImg -data $imgData]\n\n\t# troughOffDisabledImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='#cfc9be'/>\\n</svg>\"\n\tset troughOffDisabledImg [CreateImg -data $imgData]\n\n\t# troughOnImg\n\tset imgData $troughData($n)\n\tset fill [Hsv2Rgb 208 43.9 51.8]\t\t\t;# #4a6984\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnImg [CreateImg -data $imgData]\n\n\t# troughOnActiveImg\n\tset imgData $troughData($n)\n\tset fill [expr {$onAndroid ? $fill : [Hsv2Rgb 208 43.9 61.8]}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\tset troughOnActiveImg [CreateImg -data $imgData]\n\n\t# troughOnPressedImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='[Hsv2Rgb 208 43.9 71.8]'/>\\n</svg>\"\n\tset troughOnPressedImg [CreateImg -data $imgData]\n\n\t# troughOnDisabledImg\n\tset imgData $troughData($n)\n\tappend imgData \"fill='[Hsv2Rgb 208 33.9 100]'/>\\n</svg>\"\n\tset troughOnDisabledImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.trough image [list $troughOffImg \\\n\t    {selected disabled}\t$troughOnDisabledImg \\\n\t    {selected pressed}\t$troughOnPressedImg \\\n\t    {selected active}\t$troughOnActiveImg \\\n\t    selected\t\t$troughOnImg \\\n\t    disabled\t\t$troughOffDisabledImg \\\n\t    pressed\t\t$troughOffPressedImg \\\n\t    active\t\t$troughOffActiveImg \\\n\t]\n\n\t# sliderImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.slider image $sliderImg\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_vista\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_vista {} {\n    variable elemInfoArr\n    if {[info exists elemInfoArr(vista)]} {\n\treturn \"\"\n    }\n\n    if {$::tcl_platform(osVersion) >= 11.0} {\t\t\t;# Win 11+\n\tCreateElements_win11\n    } else {\t\t\t\t\t\t\t;# Win 10-\n\tCreateElements_win10\n    }\n\n    foreach n {1 2 3} {\n\tttk::style layout Toggleswitch$n [list \\\n\t    Tglswitch.focus -sticky nswe -children [list \\\n\t\tTglswitch.padding -sticky nswe -children [list \\\n\t\t    Tglswitch$n.trough -sticky {} -children [list \\\n\t\t\tTglswitch$n.slider -side left -sticky {}\n\t\t    ]\n\t\t]\n\t    ]\n\t]\n    }\n\n    set elemInfoArr(vista) 1\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_win11\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_win11 {} {\n    set troughOffData(1) {\n<svg width=\"32\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"15\" rx=\"7.5\" }\n    set troughOffData(2) {\n<svg width=\"40\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"39\" height=\"19\" rx=\"9.5\" }\n    set troughOffData(3) {\n<svg width=\"48\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"47\" height=\"23\" rx=\"11.5\" }\n\n    set troughOnData(1) {\n<svg width=\"32\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"32\" height=\"16\" rx=\"8\" }\n    set troughOnData(2) {\n<svg width=\"40\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"40\" height=\"20\" rx=\"10\" }\n    set troughOnData(3) {\n<svg width=\"48\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"48\" height=\"24\" rx=\"12\" }\n\n    set sliderOffData(1) {\n<svg width=\"16\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"7\" cy=\"5\" r=\"4\" }\t\t\t\t;# margins L, R: 3, 5\n    set sliderOffData(2) {\n<svg width=\"20\" height=\"14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"9\" cy=\"7\" r=\"6\" }\t\t\t\t;# margins L, R: 3, 5\n    set sliderOffData(3) {\n<svg width=\"24\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"11\" cy=\"9\" r=\"8\" }\t\t\t\t;# margins L, R: 3, 5\n\n    set sliderOnData(1) {\n<svg width=\"16\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"9\" cy=\"5\" r=\"4\" }\t\t\t\t;# margins L, R: 5, 3\n    set sliderOnData(2) {\n<svg width=\"20\" height=\"14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"11\" cy=\"7\" r=\"6\" }\t\t\t\t;# margins L, R: 5, 3\n    set sliderOnData(3) {\n<svg width=\"24\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"13\" cy=\"9\" r=\"8\" }\t\t\t\t;# margins L, R: 5, 3\n\n    set sliderActiveData(1) {\n<svg width=\"16\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"8\" cy=\"5\" r=\"5\" }\t\t\t\t;# margins L, R: 3, 3\n    set sliderActiveData(2) {\n<svg width=\"20\" height=\"14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"7\" r=\"7\" }\t\t\t\t;# margins L, R: 3, 3\n    set sliderActiveData(3) {\n<svg width=\"24\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"9\" r=\"9\" }\t\t\t\t;# margins L, R: 3, 3\n\n    set sliderOffPressedData(1) {\n<svg width=\"16\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"0\" width=\"13\" height=\"10\" rx=\"5\" }\t;# margins L, R: 3, 0\n    set sliderOffPressedData(2) {\n<svg width=\"20\" height=\"14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"0\" width=\"17\" height=\"14\" rx=\"7\" }\t;# margins L, R: 3, 0\n    set sliderOffPressedData(3) {\n<svg width=\"24\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"0\" width=\"21\" height=\"18\" rx=\"9\" }\t;# margins L, R: 3, 0\n\n    set sliderOnPressedData(1) {\n<svg width=\"16\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"13\" height=\"10\" rx=\"5\" }\t;# margins L, R: 0, 3\n    set sliderOnPressedData(2) {\n<svg width=\"20\" height=\"14\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"17\" height=\"14\" rx=\"7\" }\t;# margins L, R: 0, 3\n    set sliderOnPressedData(3) {\n<svg width=\"24\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"21\" height=\"18\" rx=\"9\" }\t;# margins L, R: 0, 3\n\n    foreach n {1 2 3} {\n\t# troughOffImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#f6f6f6' stroke='#8a8a8a'/>\\n</svg>\"\n\tset troughOffImg [CreateImg -data $imgData]\n\n\t# troughOffActiveImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#ededed' stroke='#878787'/>\\n</svg>\"\n\tset troughOffActiveImg [CreateImg -data $imgData]\n\n\t# troughOffPressedImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#e4e4e4' stroke='#858585'/>\\n</svg>\"\n\tset troughOffPressedImg [CreateImg -data $imgData]\n\n\t# troughOffDisabledImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#fbfbfb' stroke='#c5c5c5'/>\\n</svg>\"\n\tset troughOffDisabledImg [CreateImg -data $imgData]\n\n\t# troughOnImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#005fb8'/>\\n</svg>\"\n\tset troughOnImg [CreateImg -data $imgData]\n\n\t# troughOnActiveImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#196ebf'/>\\n</svg>\"\n\tset troughOnActiveImg [CreateImg -data $imgData]\n\n\t# troughOnPressedImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#327ec5'/>\\n</svg>\"\n\tset troughOnPressedImg [CreateImg -data $imgData]\n\n\t# troughOnDisabledImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#c5c5c5'/>\\n</svg>\"\n\tset troughOnDisabledImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.trough image [list $troughOffImg \\\n\t    {selected disabled}\t$troughOnDisabledImg \\\n\t    {selected pressed}\t$troughOnPressedImg \\\n\t    {selected active}\t$troughOnActiveImg \\\n\t    selected\t\t$troughOnImg \\\n\t    disabled\t\t$troughOffDisabledImg \\\n\t    pressed\t\t$troughOffPressedImg \\\n\t    active\t\t$troughOffActiveImg \\\n\t]\n\n\t# sliderOffImg\n\tset imgData $sliderOffData($n)\n\tappend imgData \"fill='#5d5d5d'/>\\n</svg>\"\n\tset sliderOffImg [CreateImg -data $imgData]\n\n\t# sliderOffActiveImg\n\tset imgData $sliderActiveData($n)\n\tappend imgData \"fill='#5a5a5a'/>\\n</svg>\"\n\tset sliderOffActiveImg [CreateImg -data $imgData]\n\n\t# sliderOffPressedImg\n\tset imgData $sliderOffPressedData($n)\n\tappend imgData \"fill='#575757'/>\\n</svg>\"\n\tset sliderOffPressedImg [CreateImg -data $imgData]\n\n\t# sliderOffDisabledImg\n\tset imgData $sliderOffData($n)\n\tappend imgData \"fill='#a1a1a1'/>\\n</svg>\"\n\tset sliderOffDisabledImg [CreateImg -data $imgData]\n\n\t# sliderOnImg\n\tset imgData $sliderOnData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderOnImg [CreateImg -data $imgData]\n\n\t# sliderOnActiveImg\n\tset imgData $sliderActiveData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderOnActiveImg [CreateImg -data $imgData]\n\n\t# sliderOnPressedImg\n\tset imgData $sliderOnPressedData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderOnPressedImg [CreateImg -data $imgData]\n\n\t# sliderOnDisabledImg\n\tset imgData $sliderOnData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderOnDisabledImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.slider image [list $sliderOffImg \\\n\t    {selected disabled}\t$sliderOnDisabledImg \\\n\t    {selected pressed}\t$sliderOnPressedImg \\\n\t    {selected active}\t$sliderOnActiveImg \\\n\t    selected\t\t$sliderOnImg \\\n\t    disabled\t\t$sliderOffDisabledImg \\\n\t    pressed\t\t$sliderOffPressedImg \\\n\t    active\t\t$sliderOffActiveImg \\\n\t]\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_win10\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_win10 {} {\n    set troughOffData(1) {\n<svg width=\"35\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"33\" height=\"14\" rx=\"7\" stroke-width=\"2\" }\n    set troughOffData(2) {\n<svg width=\"44\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"42\" height=\"18\" rx=\"9\" stroke-width=\"2\" }\n    set troughOffData(3) {\n<svg width=\"53\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"51\" height=\"22\" rx=\"11\" stroke-width=\"2\" }\n\n    set troughOnData(1) {\n<svg width=\"35\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"35\" height=\"16\" rx=\"8\" }\n    set troughOnData(2) {\n<svg width=\"44\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"44\" height=\"20\" rx=\"10\" }\n    set troughOnData(3) {\n<svg width=\"53\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"53\" height=\"24\" rx=\"12\" }\n\n    set troughPressedData(1) {\n<svg width=\"35\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"35\" height=\"16\" rx=\"8\" fill=\"#666666\"/>\n</svg>}\n    set troughPressedData(2) {\n<svg width=\"44\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"44\" height=\"20\" rx=\"10\" fill=\"#666666\"/>\n</svg>}\n    set troughPressedData(3) {\n<svg width=\"53\" height=\"24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"53\" height=\"24\" rx=\"12\" fill=\"#666666\"/>\n</svg>}\n\n    set sliderData(1) {\n<svg width=\"16\" height=\"8\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"8\" cy=\"4\" r=\"4\" }\n    set sliderData(2) {\n<svg width=\"20\" height=\"10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"5\" r=\"5\" }\n    set sliderData(3) {\n<svg width=\"24\" height=\"12\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"6\" r=\"6\" }\n\n    foreach n {1 2 3} {\n\t# troughOffImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#ffffff' stroke='#333333'/>\\n</svg>\"\n\tset troughOffImg [CreateImg -data $imgData]\n\n\t# troughOffDisabledImg\n\tset imgData $troughOffData($n)\n\tappend imgData \"fill='#ffffff' stroke='#999999'/>\\n</svg>\"\n\tset troughOffDisabledImg [CreateImg -data $imgData]\n\n\t# troughOnImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#0078d7'/>\\n</svg>\"\n\tset troughOnImg [CreateImg -data $imgData]\n\n\t# troughOnActiveImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#4da1e3'/>\\n</svg>\"\n\tset troughOnActiveImg [CreateImg -data $imgData]\n\n\t# troughOnDisabledImg\n\tset imgData $troughOnData($n)\n\tappend imgData \"fill='#cccccc'/>\\n</svg>\"\n\tset troughOnDisabledImg [CreateImg -data $imgData]\n\n\t# troughPressedImg\n\tset troughPressedImg [CreateImg -data $troughPressedData($n)]\n\n\tCreateElem Tglswitch$n.trough image [list $troughOffImg \\\n\t    {selected disabled}\t$troughOnDisabledImg \\\n\t    {selected pressed}\t$troughPressedImg \\\n\t    {selected active}\t$troughOnActiveImg \\\n\t    selected\t\t$troughOnImg \\\n\t    disabled\t\t$troughOffDisabledImg \\\n\t    pressed\t\t$troughPressedImg \\\n\t]\n\n\t# sliderOffImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#333333'/>\\n</svg>\"\n\tset sliderOffImg [CreateImg -data $imgData]\n\n\t# sliderOffDisabledImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#999999'/>\\n</svg>\"\n\tset sliderOffDisabledImg [CreateImg -data $imgData]\n\n\t# sliderOnImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderOnImg [CreateImg -data $imgData]\n\n\t# sliderOnDisabledImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#a3a3a3'/>\\n</svg>\"\n\tset sliderOnDisabledImg [CreateImg -data $imgData]\n\n\t# sliderPressedImg\n\tset imgData $sliderData($n)\n\tappend imgData \"fill='#ffffff'/>\\n</svg>\"\n\tset sliderPressedImg [CreateImg -data $imgData]\n\n\tCreateElem Tglswitch$n.slider image [list $sliderOffImg \\\n\t    {selected disabled}\t$sliderOnDisabledImg \\\n\t    selected\t\t$sliderOnImg \\\n\t    disabled\t\t$sliderOffDisabledImg \\\n\t    pressed\t\t$sliderPressedImg \\\n\t]\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements_aqua\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements_aqua {} {\n    variable troughImgArr\n    variable sliderImgArr\n\n    foreach n {1 2 3} {\n\tforeach state {off offPressed offDisabled\n\t\t       on onPressed onDisabled onBg onDisabledBg} {\n\t    set troughImgArr(${state}$n) [CreateImg]\n\t}\n\n\tCreateElem Tglswitch$n.trough image [list $troughImgArr(off$n) \\\n\t    {selected disabled background}\t$troughImgArr(onDisabledBg$n) \\\n\t    {selected disabled}\t\t\t$troughImgArr(onDisabled$n) \\\n\t    {selected background}\t\t$troughImgArr(onBg$n) \\\n\t    {selected pressed}\t\t\t$troughImgArr(onPressed$n) \\\n\t    selected\t\t\t\t$troughImgArr(on$n) \\\n\t    disabled\t\t\t\t$troughImgArr(offDisabled$n) \\\n\t    pressed\t\t\t\t$troughImgArr(offPressed$n) \\\n\t]\n\n\tforeach state {off offPressed offDisabled\n\t\t       on onPressed onDisabled} {\n\t    set sliderImgArr(${state}$n) [CreateImg]\n\t}\n\n\tCreateElem Tglswitch$n.slider image [list $sliderImgArr(off$n) \\\n\t    {selected disabled}\t\t$sliderImgArr(onDisabled$n) \\\n\t    {selected pressed}\t\t$sliderImgArr(onPressed$n) \\\n\t    selected\t\t\t$sliderImgArr(on$n) \\\n\t    disabled\t\t\t$sliderImgArr(offDisabled$n) \\\n\t    pressed\t\t\t$sliderImgArr(offPressed$n) \\\n\t]\n    }\n\n    UpdateElements_aqua\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::UpdateElements_aqua\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::UpdateElements_aqua {} {\n    scan $::tcl_platform(osVersion) \"%d\" majorOSVersion\n    if {$majorOSVersion >= 25} {\t\t\t;# macOS 26 or later\n\tUpdateElements_aqua_macos26\n    } else {\t\t\t\t\t\t;# macOS 15 or earlier\n\tUpdateElements_aqua_macos15\n    }\n\n    foreach n {1 2 3} {\n\tttk::style layout Toggleswitch$n [list \\\n\t    Tglswitch.padding -sticky nswe -children [list \\\n\t\tTglswitch$n.trough -sticky {} -children [list \\\n\t\t    Tglswitch$n.slider -side left -sticky {} \\\n\t\t]\n\t    ]\n\t]\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::UpdateElements_aqua_macos26\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::UpdateElements_aqua_macos26 {} {\n    variable troughImgArr\n    variable sliderImgArr\n\n    set troughOffData(1) {\n<svg width=\"29\" height=\"13\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"29\" height=\"13\" rx=\"6.5\" }\n    set troughOffData(2) {\n<svg width=\"36\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"36\" height=\"16\" rx=\"8\" }\n    set troughOffData(3) {\n<svg width=\"44\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"44\" height=\"20\" rx=\"10\" }\n\n    set troughOnData(1) $troughOffData(1)\n    set troughOnData(2) $troughOffData(2)\n    set troughOnData(3) $troughOffData(3)\n\n    set sliderOffData(1) {\n<svg width=\"19\" height=\"13\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"18\" height=\"12\" rx=\"6\" }\n    set sliderOffData(2) {\n<svg width=\"23\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"22\" height=\"15\" rx=\"7.5\" }\n    set sliderOffData(3) {\n<svg width=\"30\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"28\" height=\"18\" rx=\"9\" stroke-width=\"2\" }\n\n    set sliderOnData(1) {\n<svg width=\"19\" height=\"13\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"17\" height=\"11\" rx=\"5.5\" }\n    set sliderOnData(2) {\n<svg width=\"23\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1\" y=\"1\" width=\"21\" height=\"14\" rx=\"7\" }\n    set sliderOnData(3) {\n<svg width=\"30\" height=\"20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"2\" y=\"2\" width=\"26\" height=\"16\" rx=\"8\" }\n\n    set darkMode    [tk::unsupported::MacWindowStyle isdark .]\n    set selectBg    [NormalizeColor systemSelectedContentBackgroundColor]\n    set accentColor [NormalizeColor systemControlAccentColor]\n\n    foreach n {1 2 3} {\n\t# troughImgArr(off$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#3e4345\" : \"#dddddd\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(off$n) configure -data $imgData\n\n\t# troughImgArr(offPressed$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#525759\" : \"#c5c6c7\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(offPressed$n) configure -data $imgData\n\n\t# troughImgArr(offDisabled$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#343938\" : \"#e9e9e9\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(offDisabled$n) configure -data $imgData\n\n\t# troughImgArr(on$n)\n\tset imgData $troughOnData($n)\n\tset fill $accentColor\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(on$n) configure -data $imgData\n\n\t# troughImgArr(onPressed$n)\n\tset imgData $troughOnData($n)\n\tset fill $selectBg\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onPressed$n) configure -data $imgData\n\n\t# troughImgArr(onDisabled$n)\n\tset imgData $troughOnData($n)\n\tset fill [NormalizeColor systemSelectedControlColor]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onDisabled$n) configure -data $imgData\n\n\t# troughImgArr(onBg$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? \"#4b4c4d\" : \"#d2d2d2\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onBg$n) configure -data $imgData\n\n\t# troughImgArr(onDisabledBg$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? \"#393e3f\" : \"#e3e3e3\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onDisabledBg$n) configure -data $imgData\n\n\t# sliderImgArr(off$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#e2e3e3\" : \"#ffffff\"}]\n\tset strk [expr {$darkMode ? \"#3c4041\" : \"#d4d4d4\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(off$n) configure -data $imgData\n\n\t# sliderImgArr(offPressed$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#c2c3c3\" : \"#efefef\"}]\n\tset strk [expr {$darkMode ? \"#1c2021\" : \"#c4c4c4\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(offPressed$n) configure -data $imgData\n\n\t# sliderImgArr(offDisabled$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#e1e2e2\" : \"#ffffff\"}]\n\tset strk [expr {$darkMode ? \"#323739\" : \"#e0e0e0\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(offDisabled$n) configure -data $imgData\n\n\t# sliderImgArr(on$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#d9ecff\" : \"#ffffff\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(on$n) configure -data $imgData\n\n\t# sliderImgArr(onPressed$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#c2c3c3\" : \"#efefef\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(onPressed$n) configure -data $imgData\n\n\t# sliderImgArr(onDisabled$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#dde5ee\" : \"#ffffff\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(onDisabled$n) configure -data $imgData\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::UpdateElements_aqua_macos15\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::UpdateElements_aqua_macos15 {} {\n    variable troughImgArr\n    variable sliderImgArr\n\n    set troughOffData(1) {\n<svg width=\"26\" height=\"15\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"25\" height=\"14\" rx=\"7\" }\n    set troughOffData(2) {\n<svg width=\"32\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"17\" rx=\"8.5\" }\n    set troughOffData(3) {\n<svg width=\"38\" height=\"22\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0.5\" y=\"0.5\" width=\"37\" height=\"21\" rx=\"10.5\" }\n\n    set troughOnData(1) {\n<svg width=\"26\" height=\"15\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"26\" height=\"15\" rx=\"7.5\" }\n    set troughOnData(2) {\n<svg width=\"32\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"32\" height=\"18\" rx=\"9\" }\n    set troughOnData(3) {\n<svg width=\"38\" height=\"22\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"0\" y=\"0\" width=\"38\" height=\"22\" rx=\"11\" }\n\n    set sliderOffData(1) {\n<svg width=\"15\" height=\"15\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"7.5\" cy=\"7.5\" r=\"7\" }\n    set sliderOffData(2) {\n<svg width=\"18\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"9\" cy=\"9\" r=\"8.5\" }\n    set sliderOffData(3) {\n<svg width=\"22\" height=\"22\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"11\" cy=\"11\" r=\"10.5\" }\n\n    set sliderOnData(1) {\n<svg width=\"15\" height=\"15\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"7.5\" cy=\"7.5\" r=\"6.5\" }\n    set sliderOnData(2) {\n<svg width=\"18\" height=\"18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"9\" cy=\"9\" r=\"8\" }\n    set sliderOnData(3) {\n<svg width=\"22\" height=\"22\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"11\" cy=\"11\" r=\"10\" }\n\n    set darkMode [tk::unsupported::MacWindowStyle isdark .]\n    scan $::tcl_platform(osVersion) \"%d\" majorOSVersion\n    if {$majorOSVersion >= 18} {\t\t\t;# OS X 10.14 or later\n\tset selectBg    systemSelectedContentBackgroundColor\n\tset accentColor systemControlAccentColor\n    } else {\n\tset selectBg    systemHighlightAlternate\n\tset accentColor systemHighlightAlternate\n    }\n    set selectBg    [NormalizeColor $selectBg]\n    set accentColor [NormalizeColor $accentColor]\n\n    foreach n {1 2 3} {\n\t# troughImgArr(off$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#414141\" : \"#d9d9d9\"}]\n\tset strk [expr {$darkMode ? \"#606060\" : \"#cdcdcd\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$troughImgArr(off$n) configure -data $imgData\n\n\t# troughImgArr(offPressed$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#4d4d4d\" : \"#cbcbcb\"}]\n\tset strk [expr {$darkMode ? \"#6a6a6a\" : \"#c0c0c0\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$troughImgArr(offPressed$n) configure -data $imgData\n\n\t# troughImgArr(offDisabled$n)\n\tset imgData $troughOffData($n)\n\tset fill [expr {$darkMode ? \"#282828\" : \"#f4f4f4\"}]\n\tset strk [expr {$darkMode ? \"#393939\" : \"#ededed\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$troughImgArr(offDisabled$n) configure -data $imgData\n\n\t# troughImgArr(on$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? $selectBg : $accentColor}]\n\tif {$darkMode} {\n\t    # For the colors blue, purple, pink, red, orange, yellow, green,\n\t    # and graphite replace $fill with its counterpart for LightAqua\n\t    array set tmpArr {\n\t\t#0059d1 #0064e1  #803482 #7d2a7e  #c93379 #d93b86\n\t\t#d13539 #c4262b  #c96003 #d96b0a  #d19e00 #e1ac15\n\t\t#43932a #4da033  #696969 #808080\n\n\t\t#0058d0 #007aff  #7f3280 #953d96  #c83179 #f74f9e\n\t\t#d03439 #e0383e  #c86003 #f7821b  #cd8f0e #fcb827\n\t\t#42912a #62ba46  #686868 #989898\n\t    }\n\t    if {[info exists tmpArr($fill)]} { set fill $tmpArr($fill) }\n\t    array unset tmpArr\n\t}\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(on$n) configure -data $imgData\n\n\t# troughImgArr(onPressed$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? $accentColor : $selectBg}]\n\tif {$darkMode} {\n\t    # For the colors purple, red, yellow, and graphite\n\t    # replace $fill with its counterpart for LightAqua\n\t    array set tmpArr {\n\t\t#a550a7 #953d96  #ff5257 #e0383e\n\t\t#ffc600 #ffc726  #8c8c8c #989898\n\n\t\t#a550a7 #7d2a7e  #f74f9e #d93b85\n\t\t#fcb827 #de9e15  #8c8c8c #808080\n\t    }\n\t    if {[info exists tmpArr($fill)]} { set fill $tmpArr($fill) }\n\t    array unset tmpArr\n\t}\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onPressed$n) configure -data $imgData\n\n\t# troughImgArr(onDisabled$n)\n\tset imgData $troughOnData($n)\n\tset fill [NormalizeColor systemSelectedControlColor]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onDisabled$n) configure -data $imgData\n\n\t# troughImgArr(onBg$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? \"#676665\" : \"#b0b0b0\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onBg$n) configure -data $imgData\n\n\t# troughImgArr(onDisabledBg$n)\n\tset imgData $troughOnData($n)\n\tset fill [expr {$darkMode ? \"#282828\" : \"#f4f4f4\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$troughImgArr(onDisabledBg$n) configure -data $imgData\n\n\t# sliderImgArr(off$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#cacaca\" : \"#ffffff\"}]\n\tset strk [expr {$darkMode ? \"#606060\" : \"#cdcdcd\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(off$n) configure -data $imgData\n\n\t# sliderImgArr(offPressed$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#e4e4e4\" : \"#f0f0f0\"}]\n\tset strk [expr {$darkMode ? \"#6a6a6a\" : \"#c0c0c0\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(offPressed$n) configure -data $imgData\n\n\t# sliderImgArr(offDisabled$n)\n\tset imgData $sliderOffData($n)\n\tset fill [expr {$darkMode ? \"#595959\" : \"#fdfdfd\"}]\n\tset strk [expr {$darkMode ? \"#393939\" : \"#ededed\"}]\n\tappend imgData \"fill='$fill' stroke='$strk'/>\\n</svg>\"\n\t$sliderImgArr(offDisabled$n) configure -data $imgData\n\n\t# sliderImgArr(on$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#cacaca\" : \"#ffffff\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(on$n) configure -data $imgData\n\n\t# sliderImgArr(onPressed$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#e4e4e4\" : \"#f0f0f0\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(onPressed$n) configure -data $imgData\n\n\t# sliderImgArr(onDisabled$n)\n\tset imgData $sliderOnData($n)\n\tset fill [expr {$darkMode ? \"#595959\" : \"#fdfdfd\"}]\n\tappend imgData \"fill='$fill'/>\\n</svg>\"\n\t$sliderImgArr(onDisabled$n) configure -data $imgData\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CreateElements\n#\n# Creates the Tglswitch*.trough and Tglswitch*.slider elements for the\n# Toggleswitch* styles if they don't yet exist.  Invoked by the procedures\n# ttk::toggleswitch::CondMakeElements and ttk::toggleswitch::CondUpdateElements\n# below.\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CreateElements {} {\n    set theme [ttk::style theme use]\n\n    variable elemInfoArr\n    if {[info exists elemInfoArr($theme)]} {\n\tif {$theme eq \"aqua\"} {\n\t    UpdateElements_$theme\n\t}\n\n\treturn \"\"\n    }\n\n    switch $theme {\n\tclam - vista - aqua {\n\t    CreateElements_$theme\n\t}\n\twinnative {\n\t    ttk::style theme settings vista { CreateElements_vista }\n\t    foreach n {1 2 3} {\n\t\tCreateElem Tglswitch$n.trough from vista\n\t\tCreateElem Tglswitch$n.slider from vista\n\t    }\n\t}\n\tdefault {\n\t    if {[llength [info commands CreateElements_$theme]] == 1} {\n\t\t# The application can provide its own\n\t\t# ttk::toggleswitch::CreateElements_$theme command.\n\t\t#\n\t\tCreateElements_$theme\n\t    } else {\n\t\tset fg [ttk::style lookup . -foreground {} #000000]\n\t\tif {[IsColorLight $fg]} {\n\t\t    CreateElements_genericDark\n\t\t} else {\n\t\t    CreateElements_genericLight\n\t\t}\n\t    }\n\t}\n    }\n    set elemInfoArr($theme) 1\n\n    if {$theme eq \"aqua\"} {\n\tforeach n {1 2 3} {\n\t    ttk::style layout Toggleswitch$n [list \\\n\t\tTglswitch.padding -sticky nswe -children [list \\\n\t\t    Tglswitch$n.trough -sticky {} -children [list \\\n\t\t\tTglswitch$n.slider -side left -sticky {} \\\n\t\t    ]\n\t\t]\n\t    ]\n\n\t    if {[ttk::style lookup Toggleswitch$n -padding] eq \"\"} {\n\t\tttk::style configure Toggleswitch$n -padding 1.5p\n\t    }\n\t}\n    } else {\n\tforeach n {1 2 3} {\n\t    ttk::style layout Toggleswitch$n [list \\\n\t\tTglswitch.focus -sticky nswe -children [list \\\n\t\t    Tglswitch.padding -sticky nswe -children [list \\\n\t\t\tTglswitch$n.trough -sticky {} -children [list \\\n\t\t\t    Tglswitch$n.slider -side left -sticky {}\n\t\t\t]\n\t\t    ]\n\t\t]\n\t    ]\n\n\t    if {[ttk::style lookup Toggleswitch$n -padding] eq \"\"} {\n\t\tttk::style configure Toggleswitch$n -padding 0.75p\n\t    }\n\t    if {$theme eq \"classic\" &&\n\t\t    [ttk::style lookup Toggleswitch$n -focussolid] eq \"\"} {\n\t\tttk::style configure Toggleswitch$n -focussolid 1\n\t    }\n\t}\n    }\n}\n\n# Public procedures\n# =================\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CondMakeElements\n#\n# Creates the Tglswitch*.trough and Tglswitch*.slider elements for the\n# Toggleswitch* styles if necessary.  Invoked from within the C code, by the\n# widget initialization hook.\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CondMakeElements {} {\n    variable madeElements\n    if {!$madeElements} {\n\t# If Tk's scaling factor was changed via \"tk scaling\"\n\t# then $::tk::svgFmt now has the updated value.\n\n\tinterp alias {} ::ttk::toggleswitch::CreateImg \\\n\t\t     {} image create photo -format $::tk::svgFmt\n\n\tCreateElements\n\tset madeElements 1\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::toggleswitch::CondUpdateElements\n#\n# Updates the Tglswitch*.trough and Tglswitch*.slider elements for the\n# Toggleswitch* styles if necessary.  Invoked from within the procedures\n# ttk::ThemeChanged and ttk::AppearanceChanged (see ttk.tcl).\n#------------------------------------------------------------------------------\nproc ttk::toggleswitch::CondUpdateElements {} {\n    variable madeElements\n    if {$madeElements} {\t\t;# for some theme and appearance\n\tCreateElements\t\t\t;# for the new theme or appearance\n    }\n}\n"
  },
  {
    "path": "library/ttk/entry.tcl",
    "content": "#\n# DERIVED FROM: tk/library/entry.tcl r1.22\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 2004, Joe English\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\nnamespace eval ttk {\n    namespace eval entry {\n\tvariable State\n\n\tset State(x) 0\n\tset State(selectMode) none\n\tset State(anchor) 0\n\tset State(scanX) 0\n\tset State(scanIndex) 0\n\tset State(scanMoved) 0\n\n\t# Button-2 scan speed is (scanNum/scanDen) characters\n\t# per pixel of mouse movement.\n\t# The standard Tk entry widget uses the equivalent of\n\t# scanNum = 10, scanDen = average character width.\n\t# I don't know why that was chosen.\n\t#\n\tset State(scanNum) 1\n\tset State(scanDen) 1\n\tset State(deadband) 3\t;# #pixels for mouse-moved deadband.\n    }\n}\n\n### Option database settings.\n#\noption add *TEntry.cursor [ttk::cursor text] widgetDefault\n\n### Bindings.\n#\n# Removed the following standard Tk bindings:\n#\n# <Control-space>, <Control-Shift-space>,\n# <Select>,  <Shift-Select>:\n#\tTtk entry widget doesn't use selection anchor.\n# <Insert>:\n#\tInserts PRIMARY selection (on non-Windows platforms).\n#\tThis is inconsistent with typical platform bindings.\n# <Double-Shift-Button-1>, <Triple-Shift-Button-1>:\n#\tThese don't do the right thing to start with.\n# <Meta-b>, <Meta-d>, <Meta-f>,\n# <Meta-BackSpace>, <Meta-Delete>:\n#\tJudgment call.  If <Meta> happens to be assigned to the Alt key,\n#\tthese could conflict with application accelerators.\n#\t(Plus, who has a Meta key these days?)\n# <Control-t>:\n#\tAnother judgment call.  If anyone misses this, let me know\n#\tand I'll put it back.\n#\n\n## Clipboard events:\n#\nbind TEntry <<Cut>>\t\t\t{ ttk::entry::Cut %W }\nbind TEntry <<Copy>>\t\t\t{ ttk::entry::Copy %W }\nbind TEntry <<Paste>>\t\t\t{ ttk::entry::Paste %W }\nbind TEntry <<Clear>>\t\t\t{ ttk::entry::Clear %W }\n\n## Button1 bindings:\n#\tUsed for selection and navigation.\n#\nbind TEntry <Button-1>\t\t\t{ ttk::entry::Press %W %x }\nbind TEntry <Shift-Button-1>\t\t{ ttk::entry::Shift-Press %W %x }\nbind TEntry <Double-Button-1>\t\t{ ttk::entry::Select %W %x word }\nbind TEntry <Triple-Button-1>\t\t{ ttk::entry::Select %W %x line }\nbind TEntry <B1-Motion>\t\t\t{ ttk::entry::Drag %W %x }\n\nbind TEntry <B1-Leave>\t\t\t{ ttk::entry::DragOut %W %m }\nbind TEntry <B1-Enter>\t\t\t{ ttk::entry::DragIn %W }\nbind TEntry <ButtonRelease-1>\t\t{ ttk::entry::Release %W }\n\nbind TEntry <<ToggleSelection>> {\n    %W instate {!readonly !disabled} { %W icursor @%x ; focus %W }\n}\n\n## Button2 bindings:\n#\tUsed for scanning and primary transfer.\n#\tNote: ButtonRelease-2\n#\tis mapped to <<PasteSelection>> in tk.tcl.\n#\nbind TEntry <Button-2>\t\t\t{ ttk::entry::ScanMark %W %x }\nbind TEntry <B2-Motion>\t\t\t{ ttk::entry::ScanDrag %W %x }\nbind TEntry <ButtonRelease-2>\t\t{ ttk::entry::ScanRelease %W %x }\nbind TEntry <<PasteSelection>>\t\t{ ttk::entry::ScanRelease %W %x }\n\n## Keyboard navigation bindings:\n#\nbind TEntry <<PrevChar>>\t\t{ ttk::entry::Move %W prevchar }\nbind TEntry <<NextChar>>\t\t{ ttk::entry::Move %W nextchar }\nbind TEntry <<PrevWord>>\t\t{ ttk::entry::Move %W prevword }\nbind TEntry <<NextWord>>\t\t{ ttk::entry::Move %W nextword }\nbind TEntry <<LineStart>>\t\t{ ttk::entry::Move %W home }\nbind TEntry <<LineEnd>>\t\t\t{ ttk::entry::Move %W end }\n\nbind TEntry <<SelectPrevChar>>\t\t{ ttk::entry::Extend %W prevchar }\nbind TEntry <<SelectNextChar>>\t\t{ ttk::entry::Extend %W nextchar }\nbind TEntry <<SelectPrevWord>>\t\t{ ttk::entry::Extend %W prevword }\nbind TEntry <<SelectNextWord>>\t\t{ ttk::entry::Extend %W selectnextword }\nbind TEntry <<SelectLineStart>>\t\t{ ttk::entry::Extend %W home }\nbind TEntry <<SelectLineEnd>>\t\t{ ttk::entry::Extend %W end }\n\nbind TEntry <<SelectAll>>\t\t{ %W selection range 0 end }\nbind TEntry <<SelectNone>>\t\t{ %W selection clear }\n\nbind TEntry <<TraverseIn>>\t{ %W selection range 0 end; %W icursor end }\n\n## Edit bindings:\n#\nbind TEntry <Key>\t\t\t{ ttk::entry::Insert %W %A }\nbind TEntry <Delete>\t\t\t{ ttk::entry::Delete %W }\nbind TEntry <BackSpace>\t\t\t{ ttk::entry::Backspace %W }\n\n# Ignore all Alt, Meta, Control, Command, and Fn keypresses unless explicitly bound.\n# Otherwise, the <Key> class binding will fire and insert the character.\n# Ditto for Escape, Return, and Tab.\n#\nbind TEntry <Alt-Key>\t\t\t{# nothing}\nbind TEntry <Meta-Key>\t\t\t{# nothing}\nbind TEntry <Control-Key>\t\t{# nothing}\nbind TEntry <Escape>\t\t\t{# nothing}\nbind TEntry <Return>\t\t\t{# nothing}\nbind TEntry <KP_Enter>\t\t\t{# nothing}\nbind TEntry <Tab>\t\t\t{# nothing}\nbind TEntry <Command-Key>\t\t{# nothing}\nbind TEntry <Fn-Key>\t\t\t{# nothing}\n\n# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]\nbind TEntry <<PrevLine>>\t\t{# nothing}\nbind TEntry <<NextLine>>\t\t{# nothing}\n\n## Additional emacs-like bindings:\n#\nbind TEntry <Control-d>\t\t\t{ ttk::entry::Delete %W }\nbind TEntry <Control-h>\t\t\t{ ttk::entry::Backspace %W }\nbind TEntry <Control-k>\t\t\t{ %W delete insert end }\n\n# Bindings for IME text input.\n\nbind TEntry <<TkStartIMEMarkedText>> {\n    dict set ::tk::Priv(IMETextMark) \"%W\" [%W index insert]\n}\nbind TEntry <<TkEndIMEMarkedText>> {\n    if { [catch {dict get $::tk::Priv(IMETextMark) \"%W\"} mark] } {\n\tbell\n    } else {\n\t%W selection range $mark insert\n    }\n}\nbind TEntry <<TkClearIMEMarkedText>> {\n    %W delete [dict get $::tk::Priv(IMETextMark) \"%W\"] [%W index insert]\n}\nbind TEntry <<TkAccentBackspace>> {\n    ttk::entry::Backspace %W\n}\n\n# Copy the mouse wheel event bindings from Entry to TEntry\n#\nbind TEntry <Enter> {+\n    set tk::Priv(xWheelEvents) 0; set tk::Priv(yWheelEvents) 0\n}\nforeach event {<MouseWheel> <Option-MouseWheel>\n\t       <Shift-MouseWheel> <Shift-Option-MouseWheel>\n\t       <TouchpadScroll>} {\n    bind TEntry $event [bind Entry $event]\n}\nunset event\n\n## EndIMEMarkedText -- Handle the end of input method selection.\n#\nproc ::ttk::entry::EndIMEMarkedText {w} {\n    variable ::tk::Priv\n    if {[catch {\n\tset mark [dict get $Priv(IMETextMark) $w]\n    }]} {\n\tbell\n\treturn\n    }\n    $w selection range $mark insert\n}\n\n### Clipboard procedures.\n#\n\n## EntrySelection -- Return the selected text of the entry.\n#\tRaises an error if there is no selection.\n#\nproc ttk::entry::EntrySelection {w} {\n    set entryString [string range [$w get] [$w index sel.first] \\\n\t    [$w index sel.last]-1]\n    if {[$w cget -show] ne \"\"} {\n\treturn [string repeat [string index [$w cget -show] 0] \\\n\t\t[string length $entryString]]\n    }\n    return $entryString\n}\n\n## Paste -- Insert clipboard contents at current insert point.\n#\nproc ttk::entry::Paste {w} {\n    catch {\n\tset clipboard [::tk::GetSelection $w CLIPBOARD]\n\tPendingDelete $w\n\t$w insert insert $clipboard\n\tSee $w insert\n    }\n}\n\n## Copy -- Copy selection to clipboard.\n#\nproc ttk::entry::Copy {w} {\n    if {![catch {EntrySelection $w} selection]} {\n\tclipboard clear -displayof $w\n\tclipboard append -displayof $w $selection\n    }\n}\n\n## Clear -- Delete the selection.\n#\nproc ttk::entry::Clear {w} {\n    catch { $w delete sel.first sel.last }\n}\n\n## Cut -- Copy selection to clipboard then delete it.\n#\nproc ttk::entry::Cut {w} {\n    Copy $w; Clear $w\n}\n\n### Navigation procedures.\n#\n\n## ClosestGap -- Find closest boundary between characters.\n#\tReturns the index of the character just after the boundary.\n#\nproc ttk::entry::ClosestGap {w x} {\n    set pos [$w index @$x]\n    set bbox [$w bbox $pos]\n    if {$x - [lindex $bbox 0] > [lindex $bbox 2]/2} {\n\tincr pos\n    }\n    return $pos\n}\n\n## See $index -- Make sure that the character at $index is visible.\n#\nproc ttk::entry::See {w {index insert}} {\n    set c [$w index $index]\n    # @@@ OR: check [$w index left] / [$w index right]\n    if {$c < [$w index @0] || $c >= [$w index @[winfo width $w]]} {\n\t$w xview $c\n    }\n}\n\n## NextWord --\n# Returns the index of the next start-of-word position after the next\n# end-of-word position after a given position in the text.\n#\nproc ttk::entry::NextWord {w start} {\n    # the check on [winfo class] is because the spinbox and combobox also use this proc\n    if {[winfo class $w] eq \"TEntry\" && [$w cget -show] ne \"\"} {\n\treturn end\n    }\n    set pos [tk::endOfWord [$w get] [$w index $start]]\n    if {$pos >= 0} {\n\tset pos [tk::startOfNextWord [$w get] $pos]\n    }\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\n## SelectNextWord --\n# Returns the index of the next end-of-word position after a given\n# position in the text.\n#\nproc ttk::entry::SelectNextWord {w start} {\n    # the check on [winfo class] is because the spinbox and combobox also use this proc\n    if {[winfo class $w] eq \"TEntry\" && [$w cget -show] ne \"\"} {\n\treturn end\n    }\n    set pos [tk::endOfWord [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\n## PrevWord -- Find the previous word position.\n#\nproc ttk::entry::PrevWord {w start} {\n    # the check on [winfo class] is because the spinbox and combobox also use this proc\n    if {[winfo class $w] eq \"TEntry\" && [$w cget -show] ne \"\"} {\n\treturn 0\n    }\n    set pos [tk::startOfPreviousWord [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn 0\n    }\n    return $pos\n}\n\n## NextChar -- Find the next char position.\n#\nproc ttk::entry::NextChar {w start} {\n    variable State\n    set pos [tk::endOfCluster [$w get] [$w index $start]]\n    if {$pos < 0} {\n\treturn end\n    }\n    return $pos\n}\n\n## PrevChar -- Find the previous char position.\n#\nproc ttk::entry::PrevChar {w start} {\n    set pos [tk::startOfCluster [$w get] [expr {[$w index $start]-1}]]\n    if {$pos < 0} {\n\treturn 0\n    }\n    return $pos\n}\n\n## RelIndex -- Compute character/word/line-relative index.\n#\nproc ttk::entry::RelIndex {w where {index insert}} {\n    switch -- $where {\n\tprevchar\t{ PrevChar $w $index }\n\tnextchar\t{ NextChar $w $index }\n\tprevword\t{ PrevWord $w $index }\n\tnextword\t{ NextWord $w $index }\n\tselectnextword\t{ SelectNextWord $w $index }\n\thome\t\t{ return 0 }\n\tend\t\t{ $w index end }\n\tdefault\t\t{ error \"Bad relative index $index\" }\n    }\n}\n\n## Move -- Move insert cursor to relative location.\n#\tAlso clears the selection, if any, and makes sure\n#\tthat the insert cursor is visible.\n#\nproc ttk::entry::Move {w where} {\n    $w icursor [RelIndex $w $where]\n    $w selection clear\n    See $w insert\n}\n\n### Selection procedures.\n#\n\n## ExtendTo -- Extend the selection to the specified index.\n#\n# The other end of the selection (the anchor) is determined as follows:\n#\n# (1) if there is no selection, the anchor is the insert cursor;\n# (2) if the index is outside the selection, grow the selection;\n# (3) if the insert cursor is at one end of the selection, anchor the other end\n# (4) otherwise anchor the start of the selection\n#\n# The insert cursor is placed at the new end of the selection.\n#\n# Returns: selection anchor.\n#\nproc ttk::entry::ExtendTo {w index} {\n    set index [$w index $index]\n    set insert [$w index insert]\n\n    # Figure out selection anchor:\n    if {![$w selection present]} {\n\tset anchor $insert\n    } else {\n\tset selfirst [$w index sel.first]\n\tset sellast  [$w index sel.last]\n\n\tif {   ($index < $selfirst)\n\t    || ($insert == $selfirst && $index <= $sellast)\n\t} {\n\t    set anchor $sellast\n\t} else {\n\t    set anchor $selfirst\n\t}\n    }\n\n    # Extend selection:\n    if {$anchor < $index} {\n\t$w selection range $anchor $index\n    } else {\n\t$w selection range $index $anchor\n    }\n\n    $w icursor $index\n    return $anchor\n}\n\n## Extend -- Extend the selection to a relative position, show insert cursor\n#\nproc ttk::entry::Extend {w where} {\n    ExtendTo $w [RelIndex $w $where]\n    See $w\n}\n\n### Button 1 binding procedures.\n#\n# Double-clicking followed by a drag enters \"word-select\" mode.\n# Triple-clicking enters \"line-select\" mode.\n#\n\n## Press -- Button-1 binding.\n#\tSet the insertion cursor, claim the input focus, set up for\n#\tfuture drag operations.\n#\nproc ttk::entry::Press {w x} {\n    variable State\n\n    $w icursor [ClosestGap $w $x]\n    $w selection clear\n    $w instate !disabled { focus $w }\n\n    # Set up for future drag, double-click, or triple-click.\n    set State(x) $x\n    set State(selectMode) char\n    set State(anchor) [$w index insert]\n}\n\n## Shift-Press -- Shift-Button-1 binding.\n#\tExtends the selection, sets anchor for future drag operations.\n#\nproc ttk::entry::Shift-Press {w x} {\n    variable State\n\n    focus $w\n    set anchor [ExtendTo $w @$x]\n\n    set State(x) $x\n    set State(selectMode) char\n    set State(anchor) $anchor\n}\n\n## Select $w $x $mode -- Binding for double- and triple- clicks.\n#\tSelects a word or line (according to mode),\n#\tand sets the selection mode for subsequent drag operations.\n#\nproc ttk::entry::Select {w x mode} {\n    variable State\n    set cur [ClosestGap $w $x]\n\n    switch -- $mode {\n\tword\t{ WordSelect $w $cur $cur }\n\tline\t{ LineSelect $w $cur $cur }\n\tchar\t{ # no-op }\n    }\n\n    set State(anchor) $cur\n    set State(selectMode) $mode\n}\n\n## Drag -- Button1 motion binding.\n#\nproc ttk::entry::Drag {w x} {\n    variable State\n    set State(x) $x\n    DragTo $w $x\n}\n\n## DragTo $w $x -- Extend selection to $x based on current selection mode.\n#\nproc ttk::entry::DragTo {w x} {\n    variable State\n\n    set cur [ClosestGap $w $x]\n    switch $State(selectMode) {\n\tchar { CharSelect $w $State(anchor) $cur }\n\tword { WordSelect $w $State(anchor) $cur }\n\tline { LineSelect $w $State(anchor) $cur }\n\tnone { # no-op }\n    }\n}\n\n## <B1-Leave> binding:\n#\tBegin autoscroll.\n#\nproc ttk::entry::DragOut {w mode} {\n    variable State\n    if {$State(selectMode) ne \"none\" && $mode eq \"NotifyNormal\"} {\n\tttk::Repeatedly ttk::entry::AutoScroll $w\n    }\n}\n\n## <B1-Enter> binding\n#\tSuspend autoscroll.\n#\nproc ttk::entry::DragIn {w} {\n    ttk::CancelRepeat\n}\n\n## <ButtonRelease-1> binding\n#\nproc ttk::entry::Release {w} {\n    variable State\n    set State(selectMode) none\n    ttk::CancelRepeat\t;# suspend autoscroll\n}\n\n## AutoScroll\n#\tCalled repeatedly when the mouse is outside an entry window\n#\twith Button 1 down.  Scroll the window left or right,\n#\tdepending on where the mouse left the window, and extend\n#\tthe selection according to the current selection mode.\n#\n# TODO: AutoScroll should repeat faster (50ms) than normal autorepeat.\n# TODO: Need a way for Repeat scripts to cancel themselves.\n#\nproc ttk::entry::AutoScroll {w} {\n    variable State\n    if {![winfo exists $w]} return\n    set x $State(x)\n    if {$x > [winfo width $w]} {\n\t$w xview scroll 2 units\n\tDragTo $w $x\n    } elseif {$x < 0} {\n\t$w xview scroll -2 units\n\tDragTo $w $x\n    }\n}\n\n## CharSelect -- select characters between index $from and $to\n#\nproc ttk::entry::CharSelect {w from to} {\n    if {$to <= $from} {\n\t$w selection range $to $from\n    } else {\n\t$w selection range $from $to\n    }\n    $w icursor $to\n}\n\n## WordSelect -- Select whole words between index $from and $to\n#\nproc ttk::entry::WordSelect {w from to} {\n    if {$to < $from} {\n\tset first [WordBack [$w get] $to]\n\tset last [WordForward [$w get] $from]\n\t$w icursor $first\n    } else {\n\tset first [WordBack [$w get] $from]\n\tset last [WordForward [$w get] $to]\n\t$w icursor $last\n    }\n    $w selection range $first $last\n}\n\n## WordBack, WordForward -- helper routines for WordSelect.\n#\nproc ttk::entry::WordBack {text index {locale {}}} {\n    if {[set pos [tk::wordBreakBefore $text $index $locale]] < 0} { return 0 }\n    return $pos\n}\nproc ttk::entry::WordForward {text index {locale {}}} {\n    if {[set pos [tk::wordBreakAfter $text $index $locale]] < 0} { return end }\n    return $pos\n}\n\n## LineSelect -- Select the entire line.\n#\nproc ttk::entry::LineSelect {w _ _} {\n    variable State\n    $w selection range 0 end\n    $w icursor end\n}\n\n### Button 2 binding procedures.\n#\n\n## ScanMark -- Button-2 binding.\n#\tMarks the start of a scan or primary transfer operation.\n#\nproc ttk::entry::ScanMark {w x} {\n    variable State\n    set State(scanX) $x\n    set State(scanIndex) [$w index @0]\n    set State(scanMoved) 0\n}\n\n## ScanDrag -- Button2 motion binding.\n#\nproc ttk::entry::ScanDrag {w x} {\n    variable State\n\n    set dx [expr {$State(scanX) - $x}]\n    if {abs($dx) > $State(deadband)} {\n\tset State(scanMoved) 1\n    }\n    set left [expr {$State(scanIndex) + ($dx*$State(scanNum))/$State(scanDen)}]\n    $w xview $left\n\n    if {$left != [set newLeft [$w index @0]]} {\n\t# We've scanned past one end of the entry;\n\t# reset the mark so that the text will start dragging again\n\t# as soon as the mouse reverses direction.\n\t#\n\tset State(scanX) $x\n\tset State(scanIndex) $newLeft\n    }\n}\n\n## ScanRelease -- Button2 release binding.\n#\tDo a primary transfer if the mouse has not moved since the button press.\n#\nproc ttk::entry::ScanRelease {w x} {\n    variable State\n    if {!$State(scanMoved)} {\n\t$w instate {!disabled !readonly} {\n\t    $w icursor [ClosestGap $w $x]\n\t    catch {$w insert insert [::tk::GetSelection $w PRIMARY]}\n\t}\n    }\n}\n\n### Insertion and deletion procedures.\n#\n\n## PendingDelete -- Delete selection prior to insert.\n#\tIf the entry currently has a selection, delete it and\n#\tset the insert position to where the selection was.\n#\tReturns: 1 if pending delete occurred, 0 if nothing was selected.\n#\nproc ttk::entry::PendingDelete {w} {\n    if {[$w selection present]} {\n\t$w icursor sel.first\n\t$w delete sel.first sel.last\n\treturn 1\n    }\n    return 0\n}\n\n## Insert -- Insert text into the entry widget.\n#\tIf a selection is present, the new text replaces it.\n#\tOtherwise, the new text is inserted at the insert cursor.\n#\nproc ttk::entry::Insert {w s} {\n    if {$s eq \"\"} { return }\n    PendingDelete $w\n    $w insert insert $s\n    See $w insert\n}\n\n## Backspace -- Backspace over the character just before the insert cursor.\n#\tIf there is a selection, delete that instead.\n#\tIf the new insert position is offscreen to the left,\n#\tscroll to place the cursor at about the middle of the window.\n#\nproc ttk::entry::Backspace {w} {\n    if {[PendingDelete $w]} {\n\tSee $w\n\treturn\n    }\n    set x [expr {[$w index insert] - 1}]\n    if {$x < 0} { return }\n\n    $w delete [tk::startOfCluster [$w get] $x] [tk::endOfCluster [$w get] $x]\n\n    if {[$w index @0] >= [$w index insert]} {\n\tset range [$w xview]\n\tset left [lindex $range 0]\n\tset right [lindex $range 1]\n\t$w xview moveto [expr {$left - ($right - $left)/2.0}]\n    }\n}\n\n## Delete -- Delete the character after the insert cursor.\n#\tIf there is a selection, delete that instead.\n#\nproc ttk::entry::Delete {w} {\n    if {![PendingDelete $w]} {\n\t$w delete [tk::startOfCluster [$w get] [$w index insert]] \\\n\t\t[tk::endOfCluster [$w get] [$w index insert]]\n    }\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/fonts.tcl",
    "content": "#\n# Font specifications.\n#\n# This file, [source]d at initialization time, sets up the following\n# symbolic fonts based on the current platform:\n#\n# TkDefaultFont\t-- default for GUI items not otherwise specified\n# TkTextFont\t-- font for user text (entry, listbox, others)\n# TkFixedFont\t-- standard fixed width font\n# TkHeadingFont\t-- headings (column headings, etc)\n# TkCaptionFont -- dialog captions (primary text in alert dialogs, etc.)\n# TkTooltipFont\t-- font to use for tooltip windows\n# TkIconFont\t-- font to use for icon captions\n# TkMenuFont\t-- used to use for menu items\n#\n# In Tk 8.5, some of these fonts may be provided by the TIP#145 implementation\n# (On Windows and Mac OS X as of Oct 2007).\n#\n# +++ Platform notes:\n#\n# Windows:\n#\tThe default system font changed from \"MS Sans Serif\" to \"Tahoma\"\n#\tin Windows XP/Windows 2000.\n#\n#\tMS documentation says to use \"Tahoma 8\" in Windows 2000/XP,\n#\talthough many MS programs still use \"MS Sans Serif 8\"\n#\n#\tShould use SystemParametersInfo() instead.\n#\n# Mac OSX / Aqua:\n#\tQuoth the Apple HIG:\n#\tThe _system font_ (Lucida Grande Regular 13 pt) is used for text\n#\tin menus, dialogs, and full-size controls.\n#\t[...] Use the _view font_ (Lucida Grande Regular 12pt) as the default\n#\tfont of text in lists and tables.\n#\t[...] Use the _emphasized system font_ (Lucida Grande Bold 13 pt)\n#\tsparingly. It is used for the message text in alerts.\n#\t[...] The _small system font_ (Lucida Grande Regular 11 pt) [...]\n#\tis also the default font for column headings in lists, for help tags,\n#\tand for small controls.\n#\n#\tNote that the font for column headings (TkHeadingFont) is\n#\t_smaller_ than the default font.\n#\n#\tThere does not appear to be any recommendations for fixed-width fonts.\n#\n# X11:\n#\t\"Classic\" look used Helvetica bold for everything except\n#\tfor entry widgets, which use Helvetica medium.\n#\tMost other toolkits use medium weight for all UI elements,\n#\twhich is what we do now.\n#\n\nnamespace eval ttk {\n\nvariable tip145 [catch {font create TkDefaultFont}]\ncatch {font create TkTextFont}\ncatch {font create TkHeadingFont}\ncatch {font create TkCaptionFont}\ncatch {font create TkTooltipFont}\ncatch {font create TkFixedFont}\ncatch {font create TkIconFont}\ncatch {font create TkMenuFont}\ncatch {font create TkSmallCaptionFont}\n\nif {!$tip145} {apply {{} {\nglobal tcl_platform\nswitch -- [tk windowingsystem] {\n    win32 {\n\t# In safe interps there is no osVersion element.\n\tif {[info exists tcl_platform(osVersion)]} {\n\t    if {$tcl_platform(osVersion) >= 5.0} {\n\t\tset family \"Tahoma\"\n\t    } else {\n\t\tset family \"MS Sans Serif\"\n\t    }\n\t} else {\n\t    if {[lsearch -exact [font families] Tahoma] >= 0} {\n\t\tset family \"Tahoma\"\n\t    } else {\n\t\tset family \"MS Sans Serif\"\n\t    }\n\t}\n\tset size 8\n\n\tfont configure TkDefaultFont -family $family -size $size\n\tfont configure TkTextFont    -family $family -size $size\n\tfont configure TkHeadingFont -family $family -size $size\n\tfont configure TkCaptionFont -family $family -size $size -weight bold\n\tfont configure TkTooltipFont -family $family -size $size\n\tfont configure TkFixedFont   -family Courier -size 10\n\tfont configure TkIconFont    -family $family -size $size\n\tfont configure TkMenuFont    -family $family -size $size\n\tfont configure TkSmallCaptionFont -family $family -size $size\n    }\n    aqua {\n\tset family \"Lucida Grande\"\n\tset fixed \"Monaco\"\n\tset menusize 14\n\tset size 13\n\tset viewsize 12\n\tset smallsize 11\n\tset labelsize 10\n\tset fixedsize 11\n\n\tfont configure TkDefaultFont -family $family -size $size\n\tfont configure TkTextFont    -family $family -size $size\n\tfont configure TkHeadingFont -family $family -size $smallsize\n\tfont configure TkCaptionFont -family $family -size $size -weight bold\n\tfont configure TkTooltipFont -family $family -size $smallsize\n\tfont configure TkFixedFont   -family $fixed  -size $fixedsize\n\tfont configure TkIconFont    -family $family -size $size\n\tfont configure TkMenuFont    -family $family -size $menusize\n\tfont configure TkSmallCaptionFont -family $family -size $labelsize\n    }\n    default -\n    x11 {\n\tif {![catch {tk::pkgconfig get fontsystem} fs] && $fs eq \"xft\"} {\n\t    set family \"sans-serif\"\n\t    set fixed  \"monospace\"\n\t} else {\n\t    set family \"Helvetica\"\n\t    set fixed  \"courier\"\n\t}\n\tif {[::tk::FontScalingFactor] == 1} {\n\t    set size 10\n\t    set ttsize 9\n\t    set capsize 12\n\t    set fixedsize 10\n\t} else {\n\t    set size 20\n\t    set ttsize 18\n\t    set capsize 24\n\t    set fixedsize 20\n\t}\n\n\tfont configure TkDefaultFont -family $family -size $size\n\tfont configure TkTextFont    -family $family -size $size\n\tfont configure TkHeadingFont -family $family -size $size    -weight bold\n\tfont configure TkCaptionFont -family $family -size $capsize -weight bold\n\tfont configure TkTooltipFont -family $family -size $ttsize\n\tfont configure TkFixedFont   -family $fixed  -size $fixedsize\n\tfont configure TkIconFont    -family $family -size $size\n\tfont configure TkMenuFont    -family $family -size $size\n\tfont configure TkSmallCaptionFont -family $family -size $ttsize\n    }\n}\n} ::ttk}}\n\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/menubutton.tcl",
    "content": "#\n# Bindings for Menubuttons.\n#\n# Menubuttons have three interaction modes:\n#\n# Pulldown: Press menubutton, drag over menu, release to activate menu entry\n# Popdown: Click menubutton to post menu\n# Keyboard: <space> or accelerator key to post menu\n#\n# (In addition, when menu system is active, \"dropdown\" -- menu posts\n# on mouse-over.  Ttk menubuttons don't implement this).\n#\n# For keyboard and popdown mode, we hand off to tk_popup and let\n# the built-in Tk bindings handle the rest of the interaction.\n#\n# ON X11:\n#\n# Standard Tk menubuttons use a global grab on the menubutton.\n# This won't work for Ttk menubuttons in pulldown mode,\n# since we need to process the final <ButtonRelease> event,\n# and this might be delivered to the menu.  So instead we\n# rely on the passive grab that occurs on <Button> events,\n# and transition to popdown mode when the mouse is released\n# or dragged outside the menubutton.\n#\n# ON WINDOWS:\n#\n# I'm not sure what the hell is going on here.  [$menu post] apparently\n# sets up some kind of internal grab for native menus.\n# On this platform, just use [tk_popup] for all menu actions.\n#\n# ON MACOS:\n#\n# Same probably applies here.\n#\n\nnamespace eval ttk {\n    namespace eval menubutton {\n\tvariable State\n\tarray set State {\n\t    pulldown\t0\n\t    oldcursor\t{}\n\t}\n    }\n}\n\nbind TMenubutton <Enter>\t{ %W instate !disabled {%W state active } }\nbind TMenubutton <Leave>\t{ %W state !active }\nbind TMenubutton <space>\t{ ttk::menubutton::Popdown %W }\nbind TMenubutton <<Invoke>>\t{ ttk::menubutton::Popdown %W }\n\nif {[tk windowingsystem] eq \"x11\"} {\n    bind TMenubutton <Button-1>\t\t{ ttk::menubutton::Pulldown %W }\n    bind TMenubutton <ButtonRelease-1>\t{ ttk::menubutton::TransferGrab %W }\n    bind TMenubutton <B1-Leave>\t\t{ ttk::menubutton::TransferGrab %W }\n} else {\n    bind TMenubutton <Button-1>  \\\n\t{ %W state pressed ; ttk::menubutton::Popdown %W }\n    bind TMenubutton <ButtonRelease-1>  \\\n\t{ if {[winfo exists %W]} { %W state {!pressed}} }\n}\n\n# PostPosition --\n#\tReturns x and y coordinates and a menu item index.\n#       If the index is not an empty string the menu should\n#       be posted so that the upper left corner of the indexed\n#       menu item is located at the point (x, y).  Otherwise\n#       the top left corner of the menu itself should be located\n#       at that point.\n#\n# TODO: adjust menu width to be at least as wide as the button\n#\tfor -direction above, below.\n#\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    proc ::ttk::menubutton::PostPosition {mb menu} {\n\tset menuPad 5\n\tset buttonPad 1\n\tset bevelPad 4\n\tset flushPad 4\n\tset mh [winfo reqheight $menu]\n\tset bh [expr {[winfo height $mb]} + $buttonPad]\n\tset bbh [expr {[winfo height $mb]} + $bevelPad]\n\tset mw [winfo reqwidth $menu]\n\tset bw [winfo width $mb]\n\tset entry [::tk::MenuFindName $menu [$mb cget -text]]\n\tif {$entry < 0} {\n\t    set entry 0\n\t}\n\tset x [winfo rootx $mb]\n\tset y [winfo rooty $mb]\n\tswitch [$mb cget -direction] {\n\t    above {\n\t\tset entry \"\"\n\t\tincr y [expr {-$mh + 2 * $menuPad}]\n\t    }\n\t    below {\n\t\tset entry \"\"\n\t\tincr y $bh\n\t    }\n\t    left {\n\t\tincr y $menuPad\n\t\tincr x -$mw\n\t    }\n\t    right {\n\t\tincr y $menuPad\n\t\tincr x $bw\n\t    }\n\t    flush {\n\t\tincr y $flushPad\n\t\tincr x -$flushPad\n\t    }\n\t    default {\n\t    }\n\t}\n\treturn [list $x $y $entry]\n    }\n} else {\n    proc ::ttk::menubutton::PostPosition {mb menu} {\n\tset mh [expr {[winfo reqheight $menu]}]\n\tset bh [expr {[winfo height $mb]}]\n\tset mw [expr {[winfo reqwidth $menu]}]\n\tset bw [expr {[winfo width $mb]}]\n\tif {[tk windowingsystem] eq \"win32\"} {\n\t    incr mh 6\n\t    incr mw 16\n\t}\n\tset entry [::tk::MenuFindName $menu [$mb cget -text]]\n\tif {$entry < 0} {\n\t    set entry 0\n\t}\n\tset x [winfo rootx $mb]\n\tset y [winfo rooty $mb]\n\tswitch [$mb cget -direction] {\n\t    above {\n\t\tset entry \"\"\n\t\tincr y -$mh\n\t\t# if we go offscreen to the top, show as 'below'\n\t\tif {$y < [winfo vrooty $mb]} {\n\t\t    set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\\\n\t\t\t   + [winfo reqheight $mb]}]\n\t\t}\n\t    }\n\t    below {\n\t\tset entry \"\"\n\t\tincr y $bh\n\t\t# if we go offscreen to the bottom, show as 'above'\n\t\tif {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} {\n\t\t    set y [expr {[winfo vrooty $mb] + [winfo rooty $mb] - $mh}]\n\t\t}\n\t    }\n\t    left {\n\t\tincr x -$mw\n\t    }\n\t    right {\n\t\tincr x $bw\n\t    }\n\t    default {  # flush\n\t\tincr x [expr {([winfo width $mb] - [winfo reqwidth $menu])/ 2}]\n\t    }\n\t}\n\treturn [list $x $y $entry]\n    }\n}\n\n# Popdown --\n#\tPost the menu and set a grab on the menu.\n#\nproc ttk::menubutton::Popdown {mb} {\n    if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq \"\"} {\n\treturn\n    }\n    foreach {x y entry} [PostPosition $mb $menu] { break }\n    tk_popup $menu $x $y $entry\n}\n\n# Pulldown (X11 only) --\n#\tCalled when Button1 is pressed on a menubutton.\n#\tPosts the menu; a subsequent ButtonRelease\n#\tor Leave event will set a grab on the menu.\n#\nproc ttk::menubutton::Pulldown {mb} {\n    variable State\n    if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq \"\"} {\n\treturn\n    }\n    set State(pulldown) 1\n    set State(oldcursor) [$mb cget -cursor]\n\n    $mb state pressed\n    $mb configure -cursor [$menu cget -cursor]\n    foreach {x y entry} [PostPosition $mb $menu] { break }\n    if {$entry >= 0} {\n\t$menu post $x $y $entry\n    } else {\n\t$menu post $x $y\n    }\n    tk_menuSetFocus $menu\n}\n\n# TransferGrab (X11 only) --\n#\tSwitch from pulldown mode (menubutton has an implicit grab)\n#\tto popdown mode (menu has an explicit grab).\n#\nproc ttk::menubutton::TransferGrab {mb} {\n    variable State\n    if {$State(pulldown)} {\n\t$mb configure -cursor $State(oldcursor)\n\t$mb state {!pressed !active}\n\tset State(pulldown) 0\n\n\tset menu [$mb cget -menu]\n\tforeach {x y entry} [PostPosition $mb $menu] { break }\n\ttk_popup $menu [winfo rootx $menu] [winfo rooty $menu]\n    }\n}\n\n# FindMenuEntry --\n#\tHack to support tk_optionMenus.\n#\tReturns the index of the menu entry with a matching -label,\n#\t\"\" if not found.\n#\nproc ttk::menubutton::FindMenuEntry {menu s} {\n    set last [$menu index last]\n    if {$last < 0} {\n\treturn \"\"\n    }\n    for {set i 0} {$i <= $last} {incr i} {\n\tif {![catch {$menu entrycget $i -label} label]\n\t    && ($label eq $s)} {\n\t    return $i\n\t}\n    }\n    return \"\"\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/notebook.tcl",
    "content": "#\n# Bindings for TNotebook widget\n#\n\nnamespace eval ttk::notebook {\n    variable TLNotebooks ;# See enableTraversal\n}\n\nbind TNotebook <Button-1>\t\t{ ttk::notebook::Press %W %x %y }\nbind TNotebook <Right>\t\t\t{ ttk::notebook::CycleTab %W  1; break }\nbind TNotebook <Left>\t\t\t{ ttk::notebook::CycleTab %W -1; break }\nbind TNotebook <Control-Tab>\t\t{ ttk::notebook::CycleTab %W  1; break }\nbind TNotebook <Control-Shift-Tab>\t{ ttk::notebook::CycleTab %W -1; break }\ncatch {\nbind TNotebook <Control-ISO_Left_Tab>\t{ ttk::notebook::CycleTab %W -1; break }\n}\nbind TNotebook <Destroy>\t\t{ ttk::notebook::Cleanup %W }\n\nbind TNotebook <Enter> {\n    set tk::Priv(xEvents) 0; set tk::Priv(yEvents) 0\n}\nbind TNotebook <MouseWheel> {\n    ttk::notebook::CondCycleTab1 %W y %D -120.0\n}\nbind TNotebook <Option-MouseWheel> {\n    ttk::notebook::CondCycleTab1 %W y %D -12.0\n}\nbind TNotebook <Shift-MouseWheel> {\n    ttk::notebook::CondCycleTab1 %W x %D -120.0\n}\nbind TNotebook <Shift-Option-MouseWheel> {\n    ttk::notebook::CondCycleTab1 %W x %D -12.0\n}\nbind TNotebook <TouchpadScroll> {\n    # TouchpadScroll events fire about 60 times per second.\n    if {%# %% 15 == 0} {\n\tttk::notebook::CondCycleTab2 %W %D\n    }\n}\n\n# ActivateTab $nb $tab --\n#\tSelect the specified tab and set focus.\n#\n#  Desired behavior:\n#\t+ take focus when reselecting the currently-selected tab;\n#\t+ keep focus if the notebook already has it;\n#\t+ otherwise set focus to the first traversable widget\n#\t  in the newly-selected tab;\n#\t+ do not leave the focus in a deselected tab.\n#\nproc ttk::notebook::ActivateTab {w tab} {\n    set oldtab [$w select]\n    $w select $tab\n    set newtab [$w select] ;# NOTE: might not be $tab, if $tab is disabled\n\n    if {[focus] eq $w} { return }\n    if {$newtab eq $oldtab} { focus $w ; return }\n\n    update idletasks ;# needed so focus logic sees correct mapped states\n    if {[set f [ttk::focusFirst $newtab]] ne \"\"} {\n\tttk::traverseTo $f\n    } else {\n\tfocus $w\n    }\n}\n\n# Press $nb $x $y --\n#\tButton-1 binding for notebook widgets.\n#\tActivate the tab under the mouse cursor, if any.\n#\nproc ttk::notebook::Press {w x y} {\n    set index [$w index @$x,$y]\n    if {$index ne \"\"} {\n\tActivateTab $w $index\n    }\n}\n\n# CycleTab --\n#\tSelect the next/previous tab in the list.\n#\nproc ttk::notebook::CycleTab {w dir {factor 1.0}} {\n    set current [$w index current]\n    if {$current >= 0} {\n\tset tabCount [$w index end]\n\tset d [expr {$dir/$factor}]\n\tset d [expr {int($d > 0 ? ceil($d) : floor($d))}]\n\tset select [expr {($current + $d) % $tabCount}]\n\tset step [expr {$d > 0 ? 1 : -1}]\n\twhile {[$w tab $select -state] ne \"normal\" && ($select != $current)} {\n\t    set select [expr {($select + $step) % $tabCount}]\n\t}\n\tif {$select != $current} {\n\t    ActivateTab $w $select\n\t}\n    }\n}\n\n# CondCycleTab1 --\n#\tConditionally invoke the ttk::notebook::CycleTab proc.\n#\nproc ttk::notebook::CondCycleTab1 {w axis dir {factor 1.0}} {\n    # Count both the <MouseWheel> and <Shift-MouseWheel>\n    # events, and ignore the non-dominant ones\n\n    variable ::tk::Priv\n    incr Priv(${axis}Events)\n    if {($Priv(xEvents) + $Priv(yEvents) > 10) &&\n\t    ($axis eq \"x\" && $Priv(xEvents) < $Priv(yEvents) ||\n\t     $axis eq \"y\" && $Priv(yEvents) < $Priv(xEvents))} {\n\treturn\n    }\n\n    CycleTab $w $dir $factor\n}\n\n# CondCycleTab2 --\n#\tConditionally invoke the ttk::notebook::CycleTab proc.\n#\nproc ttk::notebook::CondCycleTab2 {w dxdy} {\n    if {[set style [$w cget -style]] eq \"\"} {\n\tset style TNotebook\n    }\n    set tabSide [string index [ttk::style lookup $style -tabposition {} nw] 0]\n\n    lassign [tk::PreciseScrollDeltas $dxdy] deltaX deltaY\n    if {$tabSide in {n s} && $deltaX != 0} {\n\tCycleTab $w [expr {$deltaX < 0 ? -1 : 1}]\n    } elseif {$tabSide in {w e} && $deltaY != 0} {\n\tCycleTab $w [expr {$deltaY < 0 ? -1 : 1}]\n    }\n}\n\n# MnemonicTab $nb $key --\n#\tScan all tabs in the specified notebook for one with the\n#\tspecified mnemonic. If found, returns path name of tab;\n#\totherwise returns \"\"\n#\nproc ttk::notebook::MnemonicTab {nb key} {\n    set key [string toupper $key]\n    foreach tab [$nb tabs] {\n\tset label [$nb tab $tab -text]\n\tset underline [$nb tab $tab -underline]\n\tif {$underline >= 0} {\n\t    set mnemonic [string toupper [string index $label $underline]]\n\t    if {$mnemonic ne \"\" && $mnemonic eq $key} {\n\t\treturn $tab\n\t    }\n\t}\n    }\n    return \"\"\n}\n\n# +++ Toplevel keyboard traversal.\n#\n\n# enableTraversal --\n#\tEnable keyboard traversal for a notebook widget\n#\tby adding bindings to the containing toplevel window.\n#\n#\tTLNotebooks($top) keeps track of the list of all traversal-enabled\n#\tnotebooks contained in the toplevel\n#\nproc ttk::notebook::enableTraversal {nb} {\n    variable TLNotebooks\n\n    set top [winfo toplevel $nb]\n\n    if {![info exists TLNotebooks($top)]} {\n\t# Augment $top bindings:\n\t#\n\tbind $top <Control-Next>             {+ttk::notebook::TLCycleTab %W  1}\n\tbind $top <Control-Prior>            {+ttk::notebook::TLCycleTab %W -1}\n\tbind $top <Control-Tab>              {+ttk::notebook::TLCycleTab %W  1}\n\tbind $top <Control-Shift-Tab>        {+ttk::notebook::TLCycleTab %W -1}\n\tcatch {\n\tbind $top <Control-ISO_Left_Tab>     {+ttk::notebook::TLCycleTab %W -1}\n\t}\n\tbind $top <Option-Key> \\\n\t    +[list ttk::notebook::MnemonicActivation $top %K]\n\tbind $top <Destroy> {+ttk::notebook::TLCleanup %W}\n    }\n\n    lappend TLNotebooks($top) $nb\n}\n\n# TLCleanup -- <Destroy> binding for traversal-enabled toplevels\n#\nproc ttk::notebook::TLCleanup {w} {\n    variable TLNotebooks\n    if {$w eq [winfo toplevel $w]} {\n\tunset -nocomplain -please TLNotebooks($w)\n    }\n}\n\n# Cleanup -- <Destroy> binding for notebooks\n#\nproc ttk::notebook::Cleanup {nb} {\n    variable TLNotebooks\n    set top [winfo toplevel $nb]\n    if {[info exists TLNotebooks($top)]} {\n\tset index [lsearch -exact $TLNotebooks($top) $nb]\n\tset TLNotebooks($top) [lreplace $TLNotebooks($top) $index $index]\n    }\n}\n\n# EnclosingNotebook $w --\n#\tReturn the nearest traversal-enabled notebook widget\n#\tthat contains $w.\n#\n# BUGS: this only works properly for tabs that are direct children\n#\tof the notebook widget.  This routine should follow the\n#\tgeometry manager hierarchy, not window ancestry, but that\n#\tinformation is not available in Tk.\n#\nproc ttk::notebook::EnclosingNotebook {w} {\n    variable TLNotebooks\n\n    set top [winfo toplevel $w]\n    if {![info exists TLNotebooks($top)]} { return }\n\n    while {$w ne $top  && $w ne \"\"} {\n\tif {[lsearch -exact $TLNotebooks($top) $w] >= 0} {\n\t    return $w\n\t}\n\tset w [winfo parent $w]\n    }\n    return \"\"\n}\n\n# TLCycleTab --\n#\ttoplevel binding procedure for Control-Tab / Control-Shift-Tab\n#\tSelect the next/previous tab in the nearest ancestor notebook.\n#\nproc ttk::notebook::TLCycleTab {w dir} {\n    set nb [EnclosingNotebook $w]\n    if {$nb ne \"\"} {\n\tCycleTab $nb $dir\n\treturn -code break\n    }\n}\n\n# MnemonicActivation $nb $key --\n#\tAlt-Key binding procedure for mnemonic activation.\n#\tScan all notebooks in specified toplevel for a tab with the\n#\tthe specified mnemonic.  If found, activate it and return TCL_BREAK.\n#\nproc ttk::notebook::MnemonicActivation {top key} {\n    variable TLNotebooks\n    foreach nb $TLNotebooks($top) {\n\tif {[set tab [MnemonicTab $nb $key]] ne \"\"} {\n\t    ActivateTab $nb [$nb index $tab]\n\t    return -code break\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/panedwindow.tcl",
    "content": "#\n# Bindings for ttk::panedwindow widget.\n#\n\nnamespace eval ttk::panedwindow {\n    variable State\n    array set State {\n\tpressed 0\n\tpressX\t-\n\tpressY\t-\n\tsash\t-\n\tsashPos -\n    }\n}\n\n## Bindings:\n#\nbind TPanedwindow <Button-1>\t\t{ ttk::panedwindow::Press %W %x %y }\nbind TPanedwindow <B1-Motion>\t\t{ ttk::panedwindow::Drag %W %x %y }\nbind TPanedwindow <ButtonRelease-1>\t{ ttk::panedwindow::Release %W %x %y }\n\nbind TPanedwindow <Motion>\t\t{ ttk::panedwindow::SetCursor %W %x %y }\nbind TPanedwindow <Enter>\t\t{ ttk::panedwindow::SetCursor %W %x %y }\nbind TPanedwindow <Leave>\t\t{ ttk::panedwindow::ResetCursor %W }\n\n## Sash movement:\n#\nproc ttk::panedwindow::Press {w x y} {\n    variable State\n\n    set sash [$w identify $x $y]\n    if {$sash eq \"\"} {\n\tset State(pressed) 0\n\treturn\n    }\n    set State(pressed)\t1\n    set State(pressX)\t$x\n    set State(pressY)\t$y\n    set State(sash)\t$sash\n    set State(sashPos)\t[$w sashpos $sash]\n}\n\nproc ttk::panedwindow::Drag {w x y} {\n    variable State\n    if {!$State(pressed)} { return }\n    switch -glob -- [$w cget -orient] {\n\th*  { set delta [expr {$x - $State(pressX)}] }\n\tv*  { set delta [expr {$y - $State(pressY)}] }\n    }\n    $w sashpos $State(sash) [expr {$State(sashPos) + $delta}]\n}\n\nproc ttk::panedwindow::Release {w x y} {\n    variable State\n    set State(pressed) 0\n    SetCursor $w $x $y\n}\n\n## Cursor management:\n#\nproc ttk::panedwindow::ResetCursor {w} {\n    variable State\n\n    ttk::saveCursor $w State(userConfCursor) \\\n\t    [list [ttk::cursor hresize] [ttk::cursor vresize]]\n\n    if {!$State(pressed)} {\n\tttk::setCursor $w $State(userConfCursor)\n    }\n}\n\nproc ttk::panedwindow::SetCursor {w x y} {\n    variable State\n\n    ttk::saveCursor $w State(userConfCursor) \\\n\t    [list [ttk::cursor hresize] [ttk::cursor vresize]]\n\n    set cursor $State(userConfCursor)\n    if {[llength [$w identify $x $y]]} {\n\t# Assume we're over a sash.\n\tswitch -glob -- [$w cget -orient] {\n\t    h*  { set cursor hresize }\n\t    v*  { set cursor vresize }\n\t}\n    }\n    ttk::setCursor $w $cursor\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/progress.tcl",
    "content": "#\n# Ttk widget set: progress bar utilities.\n#\n\nnamespace eval ttk::progressbar {\n    variable Timers\t;# Map: widget name -> after ID\n}\n\n# Autoincrement --\n#\tPeriodic callback procedure for autoincrement mode\n#\nproc ttk::progressbar::Autoincrement {pb steptime stepsize} {\n    variable Timers\n\n    if {![winfo exists $pb]} {\n\t# widget has been destroyed -- cancel timer\n\tunset -nocomplain Timers($pb)\n\treturn\n    }\n\n    set Timers($pb) [after $steptime \\\n\t[list ttk::progressbar::Autoincrement $pb $steptime $stepsize] ]\n\n    $pb step $stepsize\n}\n\n# ttk::progressbar::start --\n#\tStart autoincrement mode.  Invoked by [$pb start] widget code.\n#\nproc ttk::progressbar::start {pb {steptime 50} {stepsize 1}} {\n    variable Timers\n    if {![info exists Timers($pb)]} {\n\tAutoincrement $pb $steptime $stepsize\n    }\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t$pb state selected\n    }\n}\n\n# ttk::progressbar::stop --\n#\tCancel autoincrement mode. Invoked by [$pb stop] widget code.\n#\nproc ttk::progressbar::stop {pb} {\n    variable Timers\n    if {[info exists Timers($pb)]} {\n\tafter cancel $Timers($pb)\n\tunset Timers($pb)\n    }\n    $pb configure -value 0\n    if {[tk windowingsystem] eq \"aqua\"} {\n\t$pb state !selected\n    }\n}\n\n\n"
  },
  {
    "path": "library/ttk/scale.tcl",
    "content": "# scale.tcl - Copyright © 2004 Pat Thoyts <patthoyts@users.sourceforge.net>\n#\n# Bindings for the TScale widget\n\nnamespace eval ttk::scale {\n    variable State\n    array set State  {\n\tdragging 0\n    }\n}\n\nbind TScale <Button-1>        { ttk::scale::Press %W %x %y }\nbind TScale <B1-Motion>       { ttk::scale::Drag %W %x %y }\nbind TScale <ButtonRelease-1> { ttk::scale::Release %W %x %y }\n\nbind TScale <Button-2>        { ttk::scale::Jump %W %x %y }\nbind TScale <B2-Motion>       { ttk::scale::Drag %W %x %y }\nbind TScale <ButtonRelease-2> { ttk::scale::Release %W %x %y }\n\nbind TScale <Button-3>        { ttk::scale::Jump %W %x %y }\nbind TScale <B3-Motion>       { ttk::scale::Drag %W %x %y }\nbind TScale <ButtonRelease-3> { ttk::scale::Release %W %x %y }\n\n## Keyboard navigation bindings:\n#\nbind TScale <<LineStart>>     { %W set [%W cget -from] }\nbind TScale <<LineEnd>>       { %W set [%W cget -to] }\n\nbind TScale <<PrevChar>>      { ttk::scale::Increment %W -1 }\nbind TScale <<PrevLine>>      { ttk::scale::Increment %W -1 }\nbind TScale <<NextChar>>      { ttk::scale::Increment %W 1 }\nbind TScale <<NextLine>>      { ttk::scale::Increment %W 1 }\nbind TScale <<PrevWord>>      { ttk::scale::Increment %W -10 }\nbind TScale <<PrevPara>>      { ttk::scale::Increment %W -10 }\nbind TScale <<NextWord>>      { ttk::scale::Increment %W 10 }\nbind TScale <<NextPara>>      { ttk::scale::Increment %W 10 }\n\nproc ttk::scale::Press {w x y} {\n    variable State\n    set State(dragging) 0\n\n    switch -glob -- [$w identify $x $y] {\n\t*track -\n\t*trough {\n\t    set inc [expr {([$w get $x $y] <= [$w get]) ^ ([$w cget -from] > [$w cget -to]) ? -1 : 1}]\n\t    ttk::Repeatedly Increment $w $inc\n\t}\n\t*slider {\n\t    set State(dragging) 1\n\t    set State(initial) [$w get]\n\t}\n    }\n}\n\n# scale::Jump -- Button-2/3 binding for scale acts like\n#\tPress except that clicking in the trough jumps to the\n#\tclicked position.\nproc ttk::scale::Jump {w x y} {\n    variable State\n    set State(dragging) 0\n\n    switch -glob -- [$w identify $x $y] {\n\t*track -\n\t*trough {\n\t    $w set [$w get $x $y]\n\t    set State(dragging) 1\n\t    set State(initial) [$w get]\n\t}\n\t*slider {\n\t    Press $w $x $y\n\t}\n    }\n}\n\nproc ttk::scale::Drag {w x y} {\n    variable State\n    if {$State(dragging)} {\n\t$w set [$w get $x $y]\n    }\n}\n\nproc ttk::scale::Release {w x y} {\n    variable State\n    set State(dragging) 0\n    ttk::CancelRepeat\n}\n\nproc ttk::scale::Increment {w delta} {\n    if {![winfo exists $w]} return\n    if {([$w cget -from] > [$w cget -to])} {\n\tset delta [expr {-$delta}]\n    }\n    $w set [expr {[$w get] + $delta}]\n}\n"
  },
  {
    "path": "library/ttk/scrollbar.tcl",
    "content": "#\n# Bindings for TScrollbar widget\n#\n\nnamespace eval ttk::scrollbar {\n    variable State\n    # State(xPress)\t--\n    # State(yPress)\t-- initial position of mouse at start of drag.\n    # State(first)\t-- value of -first at start of drag.\n}\n\nbind TScrollbar <Button-1>\t\t{ ttk::scrollbar::Press %W %x %y }\nbind TScrollbar <B1-Motion>\t\t{ ttk::scrollbar::Drag %W %x %y }\nbind TScrollbar <ButtonRelease-1>\t{ ttk::scrollbar::Release %W %x %y }\n\nbind TScrollbar <Button-2>\t\t{ ttk::scrollbar::Jump %W %x %y }\nbind TScrollbar <B2-Motion>\t\t{ ttk::scrollbar::Drag %W %x %y }\nbind TScrollbar <ButtonRelease-2>\t{ ttk::scrollbar::Release %W %x %y }\n\n# Copy the mouse wheel event bindings from Scrollbar to TScrollbar\n#\nbind TScrollbar <Enter> {\n    set tk::Priv(xEvents) 0; set tk::Priv(yEvents) 0\n}\nforeach event {<MouseWheel> <Option-MouseWheel>\n\t       <Shift-MouseWheel> <Shift-Option-MouseWheel>\n\t       <TouchpadScroll>} {\n    bind TScrollbar $event [bind Scrollbar $event]\n}\nunset event\n\nproc ttk::scrollbar::Scroll {w n units} {\n    set cmd [$w cget -command]\n    if {$cmd ne \"\"} {\n\tuplevel #0 $cmd scroll $n $units\n    }\n}\n\nproc ttk::scrollbar::Moveto {w fraction} {\n    set cmd [$w cget -command]\n    if {$cmd ne \"\"} {\n\tuplevel #0 $cmd moveto $fraction\n    }\n}\n\nproc ttk::scrollbar::Press {w x y} {\n    variable State\n\n    set State(xPress) $x\n    set State(yPress) $y\n\n    switch -glob -- [$w identify $x $y] {\n\t*uparrow -\n\t*leftarrow {\n\t    ttk::Repeatedly Scroll $w -1 units\n\t}\n\t*downarrow -\n\t*rightarrow {\n\t    ttk::Repeatedly Scroll $w  1 units\n\t}\n\t*grip -\n\t*thumb {\n\t    set State(first) [lindex [$w get] 0]\n\t}\n\t*trough {\n\t    set f [$w fraction $x $y]\n\t    if {$f < [lindex [$w get] 0]} {\n\t\t# Clicked in upper/left trough\n\t\tttk::Repeatedly Scroll $w -1 pages\n\t    } elseif {$f > [lindex [$w get] 1]} {\n\t\t# Clicked in lower/right trough\n\t\tttk::Repeatedly Scroll $w 1 pages\n\t    } else {\n\t\t# Clicked on thumb (???)\n\t\tset State(first) [lindex [$w get] 0]\n\t    }\n\t}\n    }\n}\n\nproc ttk::scrollbar::Drag {w x y} {\n    variable State\n    if {![info exists State(first)]} {\n\t# Initial buttonpress was not on the thumb,\n\t# or something screwy has happened.  In either case, ignore:\n\treturn;\n    }\n    set xDelta [expr {$x - $State(xPress)}]\n    set yDelta [expr {$y - $State(yPress)}]\n    Moveto $w [expr {$State(first) + [$w delta $xDelta $yDelta]}]\n}\n\nproc ttk::scrollbar::Release {w x y} {\n    variable State\n    unset -nocomplain State(xPress) State(yPress) State(first)\n    ttk::CancelRepeat\n}\n\n# scrollbar::Jump -- Button-2 binding for scrollbars.\n#\tBehaves exactly like scrollbar::Press, except that\n#\tclicking in the trough jumps to the the selected position.\n#\nproc ttk::scrollbar::Jump {w x y} {\n    variable State\n\n    switch -glob -- [$w identify $x $y] {\n\t*grip -\n\t*thumb -\n\t*trough {\n\t    set State(first) [$w fraction $x $y]\n\t    Moveto $w $State(first)\n\t    set State(xPress) $x\n\t    set State(yPress) $y\n\t}\n\tdefault {\n\t    Press $w $x $y\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/sizegrip.tcl",
    "content": "#\n# Sizegrip widget bindings.\n#\n# Dragging a sizegrip widget resizes the containing toplevel.\n#\n# NOTE: the sizegrip widget must be in the lower right hand corner.\n#\n\nswitch -- [tk windowingsystem] {\n    x11 -\n    win32 {\n\toption add *TSizegrip.cursor [ttk::cursor seresize] widgetDefault\n    }\n    aqua {\n\t# Aqua sizegrips use default Arrow cursor.\n    }\n}\n\nnamespace eval ttk::sizegrip {\n    variable State\n    array set State {\n\tpressed\t\t0\n\tpressX\t\t0\n\tpressY\t\t0\n\twidth\t\t0\n\theight\t\t0\n\twidthInc\t1\n\theightInc\t1\n\tresizeX         1\n\tresizeY         1\n\ttoplevel\t{}\n    }\n}\n\nbind TSizegrip <Button-1>\t\t{ ttk::sizegrip::Press\t%W %X %Y }\nbind TSizegrip <B1-Motion>\t\t{ ttk::sizegrip::Drag\t%W %X %Y }\nbind TSizegrip <ButtonRelease-1>\t{ ttk::sizegrip::Release %W %X %Y }\n\nproc ttk::sizegrip::Press {W X Y} {\n    variable State\n\n    if {[$W instate disabled]} { return }\n\n    set top [winfo toplevel $W]\n\n    # If the toplevel is not resizable then bail\n    foreach {State(resizeX) State(resizeY)} [wm resizable $top] break\n    if {!$State(resizeX) && !$State(resizeY)} {\n\treturn\n    }\n\n    # Sanity-checks:\n    #\tIf a negative X or Y position was specified for [wm geometry],\n    #   just bail out -- there's no way to handle this cleanly.\n    #\n    if {[scan [wm geometry $top] \"%dx%d+%d+%d\" width height x y] != 4} {\n\treturn;\n    }\n\n    # Account for gridded geometry:\n    #\n    set grid [wm grid $top]\n    if {[llength $grid]} {\n\tset State(widthInc) [lindex $grid 2]\n\tset State(heightInc) [lindex $grid 3]\n    } else {\n\tset State(widthInc) [set State(heightInc) 1]\n    }\n\n    set State(toplevel) $top\n    set State(pressX) $X\n    set State(pressY) $Y\n    set State(width)  $width\n    set State(height) $height\n    set State(x)      $x\n    set State(y)      $y\n    set State(pressed) 1\n}\n\nproc ttk::sizegrip::Drag {W X Y} {\n    variable State\n    if {!$State(pressed)} { return }\n    set w $State(width)\n    set h $State(height)\n    if {$State(resizeX)} {\n\tset w [expr {$w + ($X - $State(pressX))/$State(widthInc)}]\n    }\n    if {$State(resizeY)} {\n\tset h [expr {$h + ($Y - $State(pressY))/$State(heightInc)}]\n    }\n    if {$w <= 0} { set w 1 }\n    if {$h <= 0} { set h 1 }\n    set x $State(x) ; set y $State(y)\n    wm geometry $State(toplevel) ${w}x${h}+${x}+${y}\n}\n\nproc ttk::sizegrip::Release {W X Y} {\n    variable State\n    set State(pressed) 0\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/spinbox.tcl",
    "content": "#\n# ttk::spinbox bindings\n#\n\nnamespace eval ttk::spinbox { }\n\n### Spinbox bindings.\n#\n# Duplicate the Entry bindings, override if needed:\n#\n\nttk::copyBindings TEntry TSpinbox\n\nbind TSpinbox <Motion>\t\t\t{ ttk::spinbox::Motion %W %x %y }\nbind TSpinbox <Button-1>\t\t{ ttk::spinbox::Press %W %x %y }\nbind TSpinbox <ButtonRelease-1>\t\t{ ttk::spinbox::Release %W }\nbind TSpinbox <Double-Button-1>\t\t{ ttk::spinbox::DoubleClick %W %x %y }\nbind TSpinbox <Triple-Button-1>\t\t{} ;# disable TEntry triple-click\n\nbind TSpinbox <Up>\t\t\t{ event generate %W <<Increment>> }\nbind TSpinbox <Down>\t\t\t{ event generate %W <<Decrement>> }\n\nbind TSpinbox <<Increment>>\t\t{ ttk::spinbox::Spin %W +1 }\nbind TSpinbox <<Decrement>>\t\t{ ttk::spinbox::Spin %W -1 }\n\nttk::bindMouseWheel TSpinbox\t\t{ ttk::spinbox::Spin %W }\nbind TSpinbox <Shift-MouseWheel> {\n    # Ignore the event\n}\nbind TSpinbox <Shift-Option-MouseWheel> {\n    # Ignore the event\n}\nbind TSpinbox <TouchpadScroll> {\n    lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n    # TouchpadScroll events fire about 60 times per second.\n    if {$tk::Priv(deltaY) != 0 && %# %% 12 == 0} {\n\tttk::spinbox::Spin %W [expr {$tk::Priv(deltaY) > 0 ? -1 : 1}]\n    }\n}\n\n## Motion --\n#\tSets cursor.\n#\nproc ttk::spinbox::Motion {w x y} {\n    variable State\n    ttk::saveCursor $w State(userConfCursor) [ttk::cursor text]\n    if {   [$w identify $x $y] eq \"textarea\"\n\t&& [$w instate {!readonly !disabled}]\n    } {\n\tttk::setCursor $w text\n    } else {\n\tttk::setCursor $w $State(userConfCursor)\n    }\n}\n\n## Press --\n#\nproc ttk::spinbox::Press {w x y} {\n    if {[$w instate disabled]} { return }\n    focus $w\n    switch -glob -- [$w identify $x $y] {\n\t*textarea\t{ ttk::entry::Press $w $x }\n\t*rightarrow\t-\n\t*uparrow\t{ ttk::Repeatedly event generate $w <<Increment>> }\n\t*leftarrow\t-\n\t*downarrow\t{ ttk::Repeatedly event generate $w <<Decrement>> }\n\t*spinbutton {\n\t    if {$y * 2 >= [winfo height $w]} {\n\t\tset event <<Decrement>>\n\t    } else {\n\t\tset event <<Increment>>\n\t    }\n\t    ttk::Repeatedly event generate $w $event\n\t}\n    }\n}\n\n## DoubleClick --\n#\tSelect all if over the text area; otherwise same as Press.\n#\nproc ttk::spinbox::DoubleClick {w x y} {\n    if {[$w instate disabled]} { return }\n\n    switch -glob -- [$w identify $x $y] {\n\t*textarea\t{ SelectAll $w }\n\t*\t\t{ Press $w $x $y }\n    }\n}\n\nproc ttk::spinbox::Release {w} {\n    ttk::CancelRepeat\n}\n\n## MouseWheel --\n#\tMousewheel callback.  Turn these into <<Increment>> (-1, up)\n#\tor <<Decrement> (+1, down) events. Not used any more.\n#\nproc ttk::spinbox::MouseWheel {w dir {factor 1.0}} {\n    if {[$w instate disabled]} { return }\n    if {($dir < 0) ^ ($factor < 0)} {\n\tevent generate $w <<Increment>>\n    } elseif {$dir != 0} {\n\tevent generate $w <<Decrement>>\n    }\n}\n\n## SelectAll --\n#\tSelect widget contents.\n#\nproc ttk::spinbox::SelectAll {w} {\n    $w selection range 0 end\n    $w icursor end\n}\n\n## Limit --\n#\tLimit $v to lie between $min and $max\n#\nproc ttk::spinbox::Limit {v min max} {\n    if {$v < $min} { return $min }\n    if {$v > $max} { return $max }\n    return $v\n}\n\n## Wrap --\n#\tAdjust $v to lie between $min and $max, wrapping if out of bounds.\n#\nproc ttk::spinbox::Wrap {v min max} {\n    if {$v < $min} { return $max }\n    if {$v > $max} { return $min }\n    return $v\n}\n\n## Adjust --\n#\tLimit or wrap spinbox value depending on -wrap.\n#\nproc ttk::spinbox::Adjust {w v min max} {\n    if {[$w cget -wrap]} {\n\treturn [Wrap $v $min $max]\n    } else  {\n\treturn [Limit $v $min $max]\n    }\n}\n\n## Spin --\n#\tHandle <<Increment>> and <<Decrement>> events.\n#\tIf -values is specified, cycle through the list.\n#\tOtherwise cycle through numeric range based on\n#\t-from, -to, and -increment.\n#\nproc ttk::spinbox::Spin {w dir {factor -1.0}} {\n    variable State\n\n    if {[$w instate disabled]} { return }\n\n    if {![info exists State($w,values.length)]} {\n\tset State($w,values.index) -1\n\tset State($w,values.last) {}\n    }\n    set State($w,values) [$w cget -values]\n    set State($w,values.length) [llength $State($w,values)]\n\n    set d [expr {-($dir/$factor)}]\n    set d [expr {int($d > 0 ? ceil($d) : floor($d))}]\n    if {$State($w,values.length) > 0} {\n\tset value [$w get]\n\tset current $State($w,values.index)\n\tif {$value ne $State($w,values.last)} {\n\t    set current [lsearch -exact $State($w,values) $value]\n\t    if {$current < 0} {set current -1}\n\t}\n\tset State($w,values.index) [Adjust $w [expr {$current + $d}] 0 \\\n\t\t[expr {$State($w,values.length) - 1}]]\n\tset State($w,values.last) [lindex $State($w,values) $State($w,values.index)]\n\t$w set $State($w,values.last)\n    } else {\n\tif {[catch {\n\t    set v [expr {[scan [$w get] %f] + $d * [$w cget -increment]}]\n\t}]} {\n\t    set v [$w cget -from]\n\t}\n\t$w set [FormatValue $w [Adjust $w $v [$w cget -from] [$w cget -to]]]\n    }\n    SelectAll $w\n    uplevel #0 [$w cget -command]\n}\n\n## FormatValue --\n#\tReformat numeric value based on -format.\n#\nproc ttk::spinbox::FormatValue {w val} {\n    set fmt [$w cget -format]\n    if {$fmt eq \"\"} {\n\t# Try to guess a suitable -format based on -increment.\n\tset delta [expr {abs([$w cget -increment])}]\n\tif {0 < $delta && $delta < 1} {\n\t    # NB: This guesses wrong if -increment has more than 1\n\t    # significant digit itself, e.g., -increment 0.25\n\t    set nsd [expr {int(ceil(-log10($delta)))}]\n\t    set fmt \"%.${nsd}f\"\n\t} else {\n\t    set fmt \"%.0f\"\n\t}\n    }\n    return [format $fmt $val]\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/toggleswitch.tcl",
    "content": "# toggleswitch.tcl - Copyright © 2025 Csaba Nemethi <csaba.nemethi@t-online.de>\n#\n# Bindings for the ttk::toggleswitch widget.\n\nnamespace eval ttk::toggleswitch {\n    variable State\n    set State(dragging)  0\n    set State(moveState) idle\t\t\t;# other values: moving, moved\n}\n\nbind Toggleswitch <<ThemeChanged>>\t{ ttk::toggleswitch::ThemeChanged %W }\n\nif {![info exists tk::android] || !$tk::android} {\n    bind Toggleswitch <Enter>\t{ %W instate !disabled {%W state active} }\n    bind Toggleswitch <Leave>\t{ %W state !active }\n}\nbind Toggleswitch <B1-Leave>\t\t{ # Preserves the active state. }\nbind Toggleswitch <Button-1>\t\t{ ttk::toggleswitch::Press   %W %x %y }\nbind Toggleswitch <B1-Motion>\t\t{ ttk::toggleswitch::Drag    %W %x %y }\nbind Toggleswitch <ButtonRelease-1>\t{ ttk::toggleswitch::Release       %W }\nbind Toggleswitch <space>\t\t{ ttk::toggleswitch::ToggleDelayed %W }\n\nproc ttk::toggleswitch::ThemeChanged w {\n    if {[info cmdtype $w] ne \"native\"} {\n\treturn \"\"    ;# the widget was not created by the ttk::toggleswitch cmd\n    }\n\n    set stateSpec [$w state !disabled]\t\t\t;# needed for $w set\n    $w set [expr {[$w switchstate] ? [$w get max] : [$w get min]}]\n    $w state $stateSpec\t\t\t\t\t;# restores the state\n}\n\nproc ttk::toggleswitch::Press {w x y} {\n     $w instate disabled {\n\treturn \"\"\n    }\n\n    $w state pressed\n\n    variable State\n    array set State [list  dragging 0  moveState idle  startX $x  prevX $x \\\n\t    prevElem [$w identify element $x $y]]\n}\n\nproc ttk::toggleswitch::Drag {w x y} {\n    if {[$w instate disabled] || [$w instate !pressed]} {\n\treturn \"\"\n    }\n\n    variable State\n\n    if {[ttk::style theme use] eq \"aqua\"} {\n\tif {$State(moveState) eq \"moving\"} {\n\t    return \"\"\n\t}\n\n\tset curElem [$w identify element $x $y]\n\tif {[string match \"*.slider\" $State(prevElem)] &&\n\t\t[string match \"*.trough\" $curElem]} {\n\t    StartToggling $w\n\t} elseif {$x < 0} {\n\t    StartMovingLeft $w\n\t} elseif {$x >= [winfo width $w]} {\n\t    StartMovingRight $w\n\t}\n\n\tset State(prevElem) $curElem\n    } else {\n\tif {!$State(dragging) && abs($x - $State(startX)) > [tk::ScaleNum 4]} {\n\t    set State(dragging) 1\n\t}\n\tif {!$State(dragging)} {\n\t    return \"\"\n\t}\n\n\tset curX [$w xcoord]\n\tset newX [expr {$curX + $x - $State(prevX)}]\n\t$w set [$w get $newX]\n\n\tset State(prevX) $x\n    }\n}\n\nproc ttk::toggleswitch::Release w {\n    if {[$w instate disabled] || [$w instate !pressed]} {\n\treturn \"\"\n    }\n\n    variable State\n\n    if {$State(dragging)} {\n\t$w switchstate [expr {[$w get] > [$w get max]/2}]\n    } elseif {[$w instate hover]} {\n\tif {[ttk::style theme use] eq \"aqua\"} {\n\t    if {$State(moveState) eq \"idle\"} {\n\t\tStartToggling $w\n\t    }\n\t} else {\n\t    $w toggle\n\t}\n    }\n\n    $w state !pressed\n    set State(dragging) 0\n}\n\nproc ttk::toggleswitch::ToggleDelayed w {\n    if {[$w instate disabled] || [$w instate pressed]} {\n\treturn \"\"\n    }\n\n    $w state pressed\n    after 200 [list ttk::toggleswitch::ToggleSwitchState $w]\n}\n\nproc ttk::toggleswitch::StartToggling w {\n    if {[$w get] == [$w get max]} {\n\tStartMovingLeft $w\n    } else {\n\tStartMovingRight $w\n    }\n}\n\nproc ttk::toggleswitch::StartMovingLeft w {\n    if {[$w get] == [$w get min]} {\n\treturn \"\"\n    }\n\n    variable State\n    set State(moveState) moving\n    $w state !selected\t\t;# will be undone before invoking switchstate\n    MoveLeft $w [$w get max]\n}\n\nproc ttk::toggleswitch::MoveLeft {w val} {\n    if {![winfo exists $w] || [winfo class $w] ne \"Toggleswitch\"} {\n\treturn \"\"\n    }\n\n    set val [expr {$val - 1}]\n    $w set $val\n\n    if {$val > [$w get min]} {\n\tafter 10 [list ttk::toggleswitch::MoveLeft $w $val]\n    } else {\n\t$w state selected\t;# restores the original selected state\n\t$w switchstate 0\n\n\tvariable State\n\tset State(moveState) moved\n    }\n}\n\nproc ttk::toggleswitch::StartMovingRight w {\n    if {[$w get] == [$w get max]} {\n\treturn \"\"\n    }\n\n    variable State\n    set State(moveState) moving\n    $w state selected\t\t;# will be undone before invoking switchstate\n    MoveRight $w [$w get min]\n}\n\nproc ttk::toggleswitch::MoveRight {w val} {\n    if {![winfo exists $w] || [winfo class $w] ne \"Toggleswitch\"} {\n\treturn \"\"\n    }\n\n    set val [expr {$val + 1}]\n    $w set $val\n\n    if {$val < [$w get max]} {\n\tafter 10 [list ttk::toggleswitch::MoveRight $w $val]\n    } else {\n\t$w state !selected\t;# restores the original !selected state\n\t$w switchstate 1\n\n\tvariable State\n\tset State(moveState) moved\n    }\n}\n\nproc ttk::toggleswitch::ToggleSwitchState w {\n    if {![winfo exists $w] || [winfo class $w] ne \"Toggleswitch\"} {\n\treturn \"\"\n    }\n\n    $w toggle\n    $w state !pressed\n}\n"
  },
  {
    "path": "library/ttk/treeview.tcl",
    "content": "#\n# ttk::treeview widget bindings and utilities.\n#\n\nnamespace eval ttk::treeview {\n    variable State\n\n    # Enter/Leave/Motion\n    #\n    set State(activeWidget)\t{}\n    set State(activeHeading)\t{}\n\n    # Press/drag/release:\n    #\n    set State(pressMode)\tnone\n    set State(pressX)\t\t0\n\n    # For pressMode == \"resize\"\n    set State(resizeColumn)\t#0\n\n    # For pressmode == \"heading\"\n    set State(heading)\t\t{}\n\n    set State(cellAnchor)\t{}\n    set State(cellAnchorOp)\t\"set\"\n}\n\n### Widget bindings.\n#\n\nbind Treeview\t<Motion>\t\t{ ttk::treeview::Motion %W %x %y }\nbind Treeview\t<B1-Leave>\t\t{ #nothing }\nbind Treeview\t<Leave>\t\t\t{ ttk::treeview::ActivateHeading {} {}}\nbind Treeview\t<Button-1>\t\t{ ttk::treeview::Press %W %x %y }\nbind Treeview\t<Double-Button-1>\t{ ttk::treeview::DoubleClick %W %x %y }\nbind Treeview\t<ButtonRelease-1>\t{ ttk::treeview::Release %W %x %y }\nbind Treeview\t<B1-Motion>\t\t{ ttk::treeview::Drag %W %x %y }\nbind Treeview\t<Up>\t\t\t{ ttk::treeview::Keynav %W up }\nbind Treeview\t<Down>\t\t\t{ ttk::treeview::Keynav %W down }\nbind Treeview\t<Right>\t\t\t{ ttk::treeview::Keynav %W right }\nbind Treeview\t<Left>\t\t\t{ ttk::treeview::Keynav %W left }\nbind Treeview\t<Prior>\t\t\t{ %W yview scroll -1 pages }\nbind Treeview\t<Next>\t\t\t{ %W yview scroll  1 pages }\nbind Treeview\t<Return>\t\t{ ttk::treeview::ToggleFocus %W }\nbind Treeview\t<space>\t\t\t{ ttk::treeview::ToggleFocus %W }\n\nbind Treeview\t<Shift-Button-1> \\\n\t\t{ ttk::treeview::Select %W %x %y extend }\nbind Treeview\t<<ToggleSelection>> \\\n\t\t{ ttk::treeview::Select %W %x %y toggle }\n\nttk::copyBindings TtkScrollable Treeview\n\n### Binding procedures.\n#\n\n## Keynav -- Keyboard navigation\n#\n# @@@ TODO: verify/rewrite up and down code.\n#\nproc ttk::treeview::Keynav {w dir} {\n    variable State\n    set focus [$w focus]\n    if {$focus eq \"\"} { return }\n\n    set cells [expr {[$w cget -selecttype] eq \"cell\"}]\n\n    if {$cells} {\n\tlassign $State(cellAnchor) _ colAnchor\n\t# Just in case, give it a valid value\n\tif {$colAnchor eq \"\"} {\n\t    set colAnchor \"#1\"\n\t}\n    }\n\n    switch -- $dir {\n\tup {\n\t    if {[set up [$w prev $focus]] eq \"\"} {\n\t\tset focus [$w parent $focus]\n\t    } else {\n\t\twhile {[$w item $up -open] && [llength [$w children $up]]} {\n\t\t    set up [lindex [$w children $up] end]\n\t\t}\n\t\tset focus $up\n\t    }\n\t}\n\tdown {\n\t    if {[$w item $focus -open] && [llength [$w children $focus]]} {\n\t\tset focus [lindex [$w children $focus] 0]\n\t    } else {\n\t\tset up $focus\n\t\twhile {$up ne \"\" && [set down [$w next $up]] eq \"\"} {\n\t\t    set up [$w parent $up]\n\t\t}\n\t\tset focus $down\n\t    }\n\t}\n\tleft {\n\t    if {$cells} {\n\t\t# This assumes that colAnchor is of the \"#N\" format.\n\t\tset colNo [string range $colAnchor 1 end]\n\t\tset firstCol [expr {\"tree\" ni [$w cget -show]}]\n\t\tif {$colNo >  $firstCol} {\n\t\t    incr colNo -1\n\t\t    set colAnchor \"#$colNo\"\n\t\t}\n\t    } elseif {[$w item $focus -open] && [llength [$w children $focus]]} {\n\t\tCloseItem $w $focus\n\t    } else {\n\t\tset focus [$w parent $focus]\n\t    }\n\t}\n\tright {\n\t    if {$cells} {\n\t\tset colNo [string range $colAnchor 1 end]\n\t\tset dispCol [$w cget -displaycolumns]\n\t\tif {$dispCol eq \"#all\"} {\n\t\t    set lastCol [llength [$w cget -columns]]\n\t\t} else {\n\t\t    set lastCol [llength $dispCol]\n\t\t}\n\t\tif {$colNo < ($lastCol - 1)} {\n\t\t    incr colNo\n\t\t    set colAnchor \"#$colNo\"\n\t\t}\n\t    } else {\n\t\tOpenItem $w $focus\n\t    }\n\t}\n    }\n\n    if {$focus != {}} {\n\tif {$cells} {\n\t    set cell [list $focus $colAnchor]\n\t    SelectOp $w $focus $cell choose\n\t} else {\n\t    SelectOp $w $focus \"\" choose\n\t}\n    }\n}\n\n## Motion -- pointer motion binding.\n#\tSets cursor, active element ...\n#\nproc ttk::treeview::Motion {w x y} {\n    variable State\n\n    ttk::saveCursor $w State(userConfCursor) [ttk::cursor hresize]\n\n    set cursor $State(userConfCursor)\n    set activeHeading {}\n\n    switch -- [$w identify region $x $y] {\n\tseparator { set cursor hresize }\n\theading { set activeHeading [$w identify column $x $y] }\n    }\n\n    ttk::setCursor $w $cursor\n    ActivateHeading $w $activeHeading\n}\n\n## ActivateHeading -- track active heading element\n#\nproc ttk::treeview::ActivateHeading {w heading} {\n    variable State\n\n    if {$w != $State(activeWidget) || $heading != $State(activeHeading)} {\n\tif {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {\n\t    # It may happen that $State(activeHeading) no longer corresponds\n\t    # to an existing display column. This happens for instance when\n\t    # changing -displaycolumns in a bound script when this change\n\t    # triggers a <Leave> event. A proc checking if the display column\n\t    # $State(activeHeading) is really still present or not could be\n\t    # written but it would need to check several special cases:\n\t    #   a. -displaycolumns \"#all\" or being an explicit columns list\n\t    #   b. column #0 display is not governed by the -displaycolumn\n\t    #      list but by the value of the -show option\n\t    # --> Let's rather catch the following line.\n\t    catch {$State(activeWidget) heading $State(activeHeading) state !active}\n\t}\n\tif {$heading != {}} {\n\t    $w heading $heading state active\n\t}\n\tset State(activeHeading) $heading\n\tset State(activeWidget) $w\n    }\n}\n\n## IndentifyCell -- Locate the cell at coordinate\n#\tOnly active when -selecttype is \"cell\", and leaves cell empty otherwise.\n#       Down the call chain it is enough to check cell to know the selecttype.\nproc ttk::treeview::IdentifyCell {w x y} {\n    set cell {}\n    if {[$w cget -selecttype] eq \"cell\"} {\n\t# Later handling assumes that the column in the cell ID is of the\n\t# format #N, which is always the case from \"identify cell\"\n\tset cell [$w identify cell $x $y]\n    }\n    return $cell\n}\n\n## Select $w $x $y $selectop\n#\tBinding procedure for selection operations.\n#\tSee \"Selection modes\", below.\n#\nproc ttk::treeview::Select {w x y op} {\n    if {[set item [$w identify row $x $y]] ne \"\" } {\n\tset cell [IdentifyCell $w $x $y]\n\tSelectOp $w $item $cell $op\n    }\n}\n\n## DoubleClick -- Double-Button-1 binding.\n#\nproc ttk::treeview::DoubleClick {w x y} {\n    if {[set row [$w identify row $x $y]] ne \"\"} {\n\tToggle $w $row\n    } else {\n\tPress $w $x $y ;# perform single-click action\n    }\n}\n\n## Press -- Button binding.\n#\nproc ttk::treeview::Press {w x y} {\n    focus $w\n    switch -- [$w identify region $x $y] {\n\tnothing { }\n\theading { heading.press $w $x $y }\n\tseparator { resize.press $w $x $y }\n\ttree -\n\tcell {\n\t    set item [$w identify item $x $y]\n\t    set cell [IdentifyCell $w $x $y]\n\n\t    SelectOp $w $item $cell choose\n\t    switch -glob -- [$w identify element $x $y] {\n\t\t*indicator -\n\t\t*disclosure { Toggle $w $item }\n\t    }\n\t}\n    }\n}\n\n## Drag -- B1-Motion binding\n#\nproc ttk::treeview::Drag {w x y} {\n    variable State\n    switch $State(pressMode) {\n\tresize\t{ resize.drag $w $x }\n\theading\t{ heading.drag $w $x $y }\n    }\n}\n\nproc ttk::treeview::Release {w x y} {\n    variable State\n    switch $State(pressMode) {\n\tresize\t{ resize.release $w $x }\n\theading\t{ heading.release $w }\n    }\n    set State(pressMode) none\n    Motion $w $x $y\n}\n\n### Interactive column resizing.\n#\nproc ttk::treeview::resize.press {w x y} {\n    variable State\n    set State(pressMode) \"resize\"\n    set State(resizeColumn) [$w identify column $x $y]\n}\n\nproc ttk::treeview::resize.drag {w x} {\n    variable State\n    $w drag $State(resizeColumn) $x\n}\n\nproc ttk::treeview::resize.release {w x} {\n    $w drop\n}\n\n### Heading activation.\n#\n\nproc ttk::treeview::heading.press {w x y} {\n    variable State\n    set column [$w identify column $x $y]\n    set State(pressMode) \"heading\"\n    set State(heading) $column\n    $w heading $column state pressed\n}\n\nproc ttk::treeview::heading.drag {w x y} {\n    variable State\n    if {   [$w identify region $x $y] eq \"heading\"\n\t&& [$w identify column $x $y] eq $State(heading)\n    } {\n\t$w heading $State(heading) state pressed\n    } else {\n\t$w heading $State(heading) state !pressed\n    }\n}\n\nproc ttk::treeview::heading.release {w} {\n    variable State\n    if {[lsearch -exact [$w heading $State(heading) state] pressed] >= 0} {\n\tafter 0 [$w heading $State(heading) -command]\n    }\n    $w heading $State(heading) state !pressed\n}\n\n### Selection modes.\n#\n\n## SelectOp $w $item [ choose | extend | toggle ] --\n#\tDispatch to appropriate selection operation\n#\tdepending on current value of -selectmode.\n#\nproc ttk::treeview::SelectOp {w item cell op} {\n    select.$op.[$w cget -selectmode] $w $item $cell\n}\n\n## -selectmode none:\n#\nproc ttk::treeview::select.choose.none {w item cell} { $w focus $item; $w see $item }\nproc ttk::treeview::select.toggle.none {w item cell} { $w focus $item; $w see $item }\nproc ttk::treeview::select.extend.none {w item cell} { $w focus $item; $w see $item }\n\n## -selectmode browse:\n#\nproc ttk::treeview::select.choose.browse {w item cell} { BrowseTo $w $item $cell }\nproc ttk::treeview::select.toggle.browse {w item cell} { BrowseTo $w $item $cell }\nproc ttk::treeview::select.extend.browse {w item cell} { BrowseTo $w $item $cell }\n\n## -selectmode multiple:\n#\nproc ttk::treeview::select.choose.extended {w item cell} {\n    BrowseTo $w $item $cell\n}\nproc ttk::treeview::select.toggle.extended {w item cell} {\n    variable State\n    if {$cell ne \"\"} {\n\t$w cellselection toggle [list $cell]\n\tset State(cellAnchor) $cell\n\tset State(cellAnchorOp) add\n    } else {\n\t$w selection toggle [list $item]\n    }\n}\nproc ttk::treeview::select.extend.extended {w item cell} {\n    variable State\n    if {$cell ne \"\"} {\n\tif {$State(cellAnchor) ne \"\"} {\n\t    $w cellselection $State(cellAnchorOp) $State(cellAnchor) $cell\n\t} else {\n\t    BrowseTo $w $item $cell\n\t}\n    } else {\n\tif {[set anchor [$w focus]] ne \"\"} {\n\t    $w selection set [between $w $anchor $item]\n\t} else {\n\t    BrowseTo $w $item $cell\n\t}\n    }\n}\n\n### Tree structure utilities.\n#\n\n## between $tv $item1 $item2 --\n#\tReturns a list of all items between $item1 and $item2,\n#\tin preorder traversal order.  $item1 and $item2 may be\n#\tin either order.\n#\n# NOTES:\n#\tThis routine is O(N) in the size of the tree.\n#\tThere's probably a way to do this that's O(N) in the number\n#\tof items returned, but I'm not clever enough to figure it out.\n#\nproc ttk::treeview::between {tv item1 item2} {\n    variable between [list]\n    variable selectingBetween 0\n    ScanBetween $tv $item1 $item2 {}\n    return $between\n}\n\n## ScanBetween --\n#\tRecursive worker routine for ttk::treeview::between\n#\nproc ttk::treeview::ScanBetween {tv item1 item2 item} {\n    variable between\n    variable selectingBetween\n\n    if {$item eq $item1 || $item eq $item2} {\n\tlappend between $item\n\tset selectingBetween [expr {!$selectingBetween}]\n    } elseif {$selectingBetween} {\n\tlappend between $item\n    }\n    foreach child [$tv children $item] {\n\tScanBetween $tv $item1 $item2 $child\n    }\n}\n\n### User interaction utilities.\n#\n\n## OpenItem, CloseItem -- Set the open state of an item, generate event\n#\n\nproc ttk::treeview::OpenItem {w item} {\n    $w focus $item\n    event generate $w <<TreeviewOpen>>\n    $w item $item -open true\n}\n\nproc ttk::treeview::CloseItem {w item} {\n    $w item $item -open false\n    $w focus $item\n    event generate $w <<TreeviewClose>>\n}\n\n## Toggle -- toggle opened/closed state of item\n#\nproc ttk::treeview::Toggle {w item} {\n    # don't allow toggling on indicators that\n    # are not present in front of leaf items\n    if {[$w children $item] == {}} {\n\treturn\n    }\n    # not a leaf, toggle!\n    if {[$w item $item -open]} {\n\tCloseItem $w $item\n    } else {\n\tOpenItem $w $item\n    }\n}\n\n## ToggleFocus -- toggle opened/closed state of focus item\n#\nproc ttk::treeview::ToggleFocus {w} {\n    set item [$w focus]\n    if {$item ne \"\"} {\n\tToggle $w $item\n    }\n}\n\n## BrowseTo -- navigate to specified item; set focus and selection\n#\nproc ttk::treeview::BrowseTo {w item cell} {\n    variable State\n\n    $w see $item\n    $w focus $item\n    set State(cellAnchor) $cell\n    set State(cellAnchorOp) set\n    if {$cell ne \"\"} {\n\t$w cellselection set [list $cell]\n    } else {\n\t$w selection set [list $item]\n    }\n}\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/ttk.tcl",
    "content": "#\n# Ttk widget set initialization script.\n#\n\n### Source library scripts.\n#\n\nnamespace eval ::ttk {\n    variable library\n    if {![info exists library]} {\n\tset library [file dirname [info script]]\n    }\n}\n\nsource [file join $::ttk::library fonts.tcl]\nsource [file join $::ttk::library cursors.tcl]\nsource [file join $::ttk::library utils.tcl]\nsource [file join $::ttk::library elements.tcl]\nsource [file join $::ttk::library wideSpinbox.tcl]\n\n## ttk::deprecated $old $new --\n#\tDefine $old command as a deprecated alias for $new command\n#\t$old and $new must be fully namespace-qualified.\n#\nproc ttk::deprecated {old new} {\n    interp alias {} $old {} ttk::do'deprecate $old $new\n}\n## do'deprecate --\n#\tImplementation procedure for deprecated commands --\n#\tissue a warning (once), then re-alias old to new.\n#\nproc ttk::do'deprecate {old new args} {\n    deprecated'warning $old $new\n    interp alias {} $old {} $new\n    uplevel 1 [linsert $args 0 $new]\n}\n\n## deprecated'warning --\n#\tGripe about use of deprecated commands.\n#\nproc ttk::deprecated'warning {old new} {\n    puts stderr \"$old deprecated -- use $new instead\"\n}\n\n### Backward-compatibility.\n#\n#\n# Make [package require tile] an effective no-op;\n# see SF#3016598 for discussion.\n#\npackage ifneeded tile 0.8.6 { package provide tile 0.8.6 }\n\n# ttk::panedwindow used to be named ttk::paned.  Keep the alias for now.\n#\n::ttk::deprecated ::ttk::paned ::ttk::panedwindow\n\n### ::ttk::ThemeChanged --\n#\tCalled from [::ttk::style theme use].\n#\tUpdates the elements of the Toggleswitch* and Wide.TSpinbox styles,\n#\tand sends a <<ThemeChanged>> virtual event to all widgets.\n#\nproc ::ttk::ThemeChanged {} {\n    toggleswitch::CondUpdateElements\t\t\t;# see elements.tcl\n    wideSpinbox::MakeOrUpdateElements\t\t\t;# see wideSpinbox.tcl\n\n    set Q .\n    while {[llength $Q]} {\n\tset QN [list]\n\tforeach w $Q {\n\t    event generate $w <<ThemeChanged>>\n\t    foreach child [winfo children $w] {\n\t\tlappend QN $child\n\t    }\n\t}\n\tset Q $QN\n    }\n}\n\n### ::ttk::AppearanceChanged --\n#\tCalled from the C code for macOSX, after sending the virtual events\n#\t<<LightAqua>>/<<DarkAqua>> and <<AppearanceChanged>> to \".\" and the\n#\ttoplevel windows.\n#\tUpdates the elements of the Toggleswitch* and Wide.TSpinbox styles.\n#\nproc ::ttk::AppearanceChanged {} {\n    toggleswitch::CondUpdateElements\t\t\t;# see elements.tcl\n    wideSpinbox::MakeOrUpdateElements\t\t\t;# see wideSpinbox.tcl\n}\n\n### Public API.\n#\n\nproc ::ttk::themes {{ptn *}} {\n    set themes [list]\n\n    foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] {\n\tlappend themes [namespace tail $pkg]\n    }\n\n    return $themes\n}\n\n## ttk::setTheme $theme --\n#\tSet the current theme to $theme, loading it if necessary.\n#\nproc ::ttk::setTheme {theme} {\n    variable currentTheme ;# @@@ Temp -- [::ttk::style theme use] doesn't work\n    if {$theme ni [::ttk::style theme names]} {\n\tpackage require ttk::theme::$theme\n    }\n    ::ttk::style theme use $theme\n    set currentTheme $theme\n}\n\n## ttk::configureNotebookStyle $style --\n#\tSets theme-specific option values for the ttk::notebook style $style\n#\tand/or the style $style.Tab.  To be invoked if the -tabposition option\n#\tof $style has a non-default value (like \"sw\", \"wn\", or \"en\").\n#\nproc ::ttk::configureNotebookStyle {style} {\n    set theme [ttk::style theme use]\n    if {[llength [info procs theme::${theme}::configureNotebookStyle]] > 0} {\n\ttheme::${theme}::configureNotebookStyle $style\n\treturn 1\n    } else {\n\treturn 0\n    }\n}\n\n## ttk::setTreeviewRowHeight --\n#\tSets the default height of the ttk::treeview rows for the current theme.\n#\tTo be invoked from within the library files for the built-in themes.\n#\nproc ::ttk::setTreeviewRowHeight {} {\n    set font [::ttk::style lookup Treeview -font {} TkDefaultFont]\n\n    ::ttk::style configure Treeview -rowheight \\\n\t    [expr {[font metrics $font -linespace] + 2}]\n}\n\n# Applications should make sure that the ttk::setTreeviewRowHeight\n# procedure will be invoked whenever the virtual event <<ThemeChanged>>\n# is received (e.g., because the value of the Treeview style's -font\n# option has changed), or the virtual event <<TkWorldChanged>> with\n# the user_data field (%d) set to \"FontChanged\" is received.  Example:\n#\n# bindtags . [linsert [bindtags .] 1 MyMainWin]\n# bind MyMainWin <<ThemeChanged>> ttk::setTreeviewRowHeight\n# bind MyMainWin <<TkWorldChanged>> {\n#     if {\"%d\" eq \"FontChanged\"} {\n#         ttk::setTreeviewRowHeight\n#     }\n# }\n\n### Load widget bindings.\n#\nsource [file join $::ttk::library button.tcl]\nsource [file join $::ttk::library menubutton.tcl]\nsource [file join $::ttk::library toggleswitch.tcl]\nsource [file join $::ttk::library scrollbar.tcl]\nsource [file join $::ttk::library scale.tcl]\nsource [file join $::ttk::library progress.tcl]\nsource [file join $::ttk::library notebook.tcl]\nsource [file join $::ttk::library panedwindow.tcl]\nsource [file join $::ttk::library entry.tcl]\nsource [file join $::ttk::library combobox.tcl]\t;# dependency: entry.tcl\nsource [file join $::ttk::library spinbox.tcl]  ;# dependency: entry.tcl\nsource [file join $::ttk::library treeview.tcl]\nsource [file join $::ttk::library sizegrip.tcl]\n\n## Label and Labelframe bindings:\n#  (not enough to justify their own file...)\n#\nbind TLabelframe <<Invoke>>\t{ tk::TabToWindow [tk_focusNext %W] }\nbind TLabel <<Invoke>>\t\t{ tk::TabToWindow [tk_focusNext %W] }\n\n### Load settings for built-in themes:\n#\nproc ttk::LoadThemes {} {\n    variable library\n\n    # \"default\" always present:\n    uplevel #0 [list source [file join $library defaults.tcl]]\n\n    set builtinThemes [style theme names]\n    foreach {theme scripts} {\n\tclassic\t\tclassicTheme.tcl\n\talt\t\taltTheme.tcl\n\tclam\t\tclamTheme.tcl\n\twinnative\twinTheme.tcl\n\tvista\t\tvistaTheme.tcl\n\taqua\t\taquaTheme.tcl\n    } {\n\tif {[lsearch -exact $builtinThemes $theme] >= 0} {\n\t    foreach script $scripts {\n\t\tuplevel #0 [list source [file join $library $script]]\n\t    }\n\t}\n    }\n}\n\nttk::LoadThemes; rename ::ttk::LoadThemes {}\n\n### Select platform-specific default theme:\n#\n# Notes:\n#\t+ On OSX, aqua theme is the default\n#\t+ On Windows, vista takes precedence over winnative if available.\n#\t+ On X11, users can use the X resource database to\n#\t  specify a preferred theme (*TkTheme: themeName);\n#\t  otherwise \"default\" is used.\n#\n\nproc ttk::DefaultTheme {} {\n    set preferred [list aqua vista winnative]\n\n    set userTheme [option get . tkTheme TkTheme]\n    if {$userTheme ne {} && ![catch {\n\tuplevel #0 [list package require ttk::theme::$userTheme]\n    }]} {\n\treturn $userTheme\n    }\n\n    foreach theme $preferred {\n\tif {[package provide ttk::theme::$theme] ne \"\"} {\n\t    return $theme\n\t}\n    }\n    return \"default\"\n}\n\nttk::setTheme [ttk::DefaultTheme] ; rename ttk::DefaultTheme {}\n\n# Scale the default ttk::scale and ttk::progressbar length\noption add *TScale.length\t75p widgetDefault\noption add *TProgressbar.length\t75p widgetDefault\n\n#*EOF*\n"
  },
  {
    "path": "library/ttk/utils.tcl",
    "content": "#\n# Utilities for widget implementations.\n#\n\n### Focus management.\n#\n# See also: #1516479\n#\n\n## ttk::takefocus --\n#\tThis is the default value of the \"-takefocus\" option\n#\tfor ttk::* widgets that participate in keyboard navigation.\n#\n# NOTES:\n#\ttk::FocusOK (called by tk_focusNext) tests [winfo viewable]\n#\tif -takefocus is 1, empty, or missing; but not if it's a\n#\tscript prefix, so we have to check that here as well.\n#\n#\nproc ttk::takefocus {w} {\n    expr {[$w instate !disabled] && [winfo viewable $w]}\n}\n\n## ttk::GuessTakeFocus --\n#\tThis routine is called as a fallback for widgets\n#\twith a missing or empty -takefocus option.\n#\n#\tIt implements the same heuristics as tk::FocusOK.\n#\nproc ttk::GuessTakeFocus {w} {\n    # Don't traverse to widgets with '-state disabled':\n    #\n    if {![catch {$w cget -state} state] && $state eq \"disabled\"} {\n\treturn 0\n    }\n\n    # Allow traversal to widgets with explicit key or focus bindings:\n    #\n    if {[regexp {Key|Focus} [concat [bind $w] [bind [winfo class $w]]]]} {\n\treturn 1;\n    }\n\n    # Default is nontraversable:\n    #\n    return 0;\n}\n\n## ttk::traverseTo $w --\n#\tSet the keyboard focus to the specified window.\n#\nproc ttk::traverseTo {w} {\n    set focus [focus]\n    if {$focus ne \"\"} {\n\tevent generate $focus <<TraverseOut>>\n    }\n    focus $w\n    event generate $w <<TraverseIn>>\n}\n\n## ttk::clickToFocus $w --\n#\tUtility routine, used in <Button-1> bindings --\n#\tAssign keyboard focus to the specified widget if -takefocus is enabled.\n#\nproc ttk::clickToFocus {w} {\n    if {[ttk::takesFocus $w]} { focus $w }\n}\n\n## ttk::takesFocus w --\n#\tTest if the widget can take keyboard focus.\n#\n#\tSee the description of the -takefocus option in options(n)\n#\tfor details.\n#\nproc ttk::takesFocus {w} {\n    if {![winfo viewable $w]} {\n\treturn 0\n    } elseif {[catch {$w cget -takefocus} takefocus]} {\n\treturn [GuessTakeFocus $w]\n    } else {\n\tswitch -- $takefocus {\n\t    \"\" { return [GuessTakeFocus $w] }\n\t    0  { return 0 }\n\t    1  { return 1 }\n\t    default {\n\t\treturn [expr {[uplevel #0 $takefocus [list $w]] == 1}]\n\t    }\n\t}\n    }\n}\n\n## ttk::focusFirst $w --\n#\tReturn the first descendant of $w, in preorder traversal order,\n#\tthat can take keyboard focus, \"\" if none do.\n#\n# See also: tk_focusNext\n#\n\nproc ttk::focusFirst {w} {\n    if {[ttk::takesFocus $w]} {\n\treturn $w\n    }\n    foreach child [winfo children $w] {\n\tif {[set c [ttk::focusFirst $child]] ne \"\"} {\n\t    return $c\n\t}\n    }\n    return \"\"\n}\n\n### Grabs.\n#\n# Rules:\n#\tEach call to [grabWindow $w] or [globalGrab $w] must be\n#\tmatched with a call to [releaseGrab $w] in LIFO order.\n#\n#\tDo not call [grabWindow $w] for a window that currently\n#\tappears on the grab stack.\n#\n#\tSee #1239190 and #1411983 for more discussion.\n#\nnamespace eval ttk {\n    variable Grab\t\t;# map: window name -> grab token\n\n    # grab token details:\n    #\tTwo-element list containing:\n    #\t1) a script to evaluate to restore the previous grab (if any);\n    #\t2) a script to evaluate to restore the focus (if any)\n}\n\n## SaveGrab --\n#\tRecord current grab and focus windows.\n#\nproc ttk::SaveGrab {w} {\n    variable Grab\n\n    if {[info exists Grab($w)]} {\n\t# $w is already on the grab stack.\n\t# This should not happen, but bail out in case it does anyway:\n\t#\n\treturn\n    }\n\n    set restoreGrab [set restoreFocus \"\"]\n\n    set grabbed [grab current $w]\n    if {[winfo exists $grabbed]} {\n\tswitch [grab status $grabbed] {\n\t    global { set restoreGrab [list grab -global $grabbed] }\n\t    local  { set restoreGrab [list grab $grabbed] }\n\t    none   { ;# grab window is really in a different interp }\n\t}\n    }\n\n    set focus [focus]\n    if {$focus ne \"\"} {\n\tset restoreFocus [list focus -force $focus]\n    }\n\n    set Grab($w) [list $restoreGrab $restoreFocus]\n}\n\n## RestoreGrab --\n#\tRestore previous grab and focus windows.\n#\tIf called more than once without an intervening [SaveGrab $w],\n#\tdoes nothing.\n#\nproc ttk::RestoreGrab {w} {\n    variable Grab\n\n    if {![info exists Grab($w)]} {\t# Ignore\n\treturn;\n    }\n\n    # The previous grab/focus window may have been destroyed,\n    # unmapped, or some other abnormal condition; ignore any errors.\n    #\n    foreach script $Grab($w) {\n\tcatch $script\n    }\n\n    unset Grab($w)\n}\n\n## ttk::grabWindow $w --\n#\tRecords the current focus and grab windows, sets an application-modal\n#\tgrab on window $w.\n#\nproc ttk::grabWindow {w} {\n    SaveGrab $w\n    grab $w\n}\n\n## ttk::globalGrab $w --\n#\tSame as grabWindow, but sets a global grab on $w.\n#\nproc ttk::globalGrab {w} {\n    SaveGrab $w\n    grab -global $w\n}\n\n## ttk::releaseGrab --\n#\tRelease the grab previously set by [ttk::grabWindow]\n#\tor [ttk::globalGrab].\n#\nproc ttk::releaseGrab {w} {\n    grab release $w\n    RestoreGrab $w\n}\n\n### Auto-repeat.\n#\n# NOTE: repeating widgets do not have -repeatdelay\n# or -repeatinterval resources as in standard Tk;\n# instead a single set of settings is applied application-wide.\n# (TODO: make this user-configurable)\n#\n# (@@@ Windows seems to use something like 500/50 milliseconds\n#  @@@ for -repeatdelay/-repeatinterval)\n#\n\nnamespace eval ttk {\n    variable Repeat\n    array set Repeat {\n\tdelay\t\t300\n\tinterval\t100\n\ttimer\t\t{}\n\tscript\t\t{}\n    }\n}\n\n## ttk::Repeatedly --\n#\tBegin auto-repeat.\n#\nproc ttk::Repeatedly {args} {\n    variable Repeat\n    after cancel $Repeat(timer)\n    set script [uplevel 1 [list namespace code $args]]\n    set Repeat(script) $script\n    set Repeat(timer) [after $Repeat(delay) ttk::Repeat]\n    uplevel #0 $script\n}\n\n## Repeat --\n#\tContinue auto-repeat\n#\nproc ttk::Repeat {} {\n    variable Repeat\n    set Repeat(timer) [after $Repeat(interval) ttk::Repeat]\n    uplevel #0 $Repeat(script)\n}\n\n## ttk::CancelRepeat --\n#\tHalt auto-repeat.\n#\nproc ttk::CancelRepeat {} {\n    variable Repeat\n    after cancel $Repeat(timer)\n}\n\n### Bindings.\n#\n\n## ttk::copyBindings $from $to --\n#\tUtility routine; copies bindings from one bindtag onto another.\n#\nproc ttk::copyBindings {from to} {\n    foreach event [bind $from] {\n\tbind $to $event [bind $from $event]\n    }\n}\n\n### Mousewheel bindings.\n#\n# Platform inconsistencies:\n#\n# MouseWheel scrolling is accelerated on X11, which is conventional\n# for Tk and appears to be conventional for other toolkits (although\n# Gtk+ and Qt do not appear to use as large a factor).\n#\n\n## ttk::bindMouseWheel $bindtag $command...\n#\tAdds basic mousewheel support to $bindtag.\n#\t$command will be passed two additional arguments\n#\tspecifying the mousewheel change and a factor.\n#\n\nproc ttk::bindMouseWheel {bindtag callback} {\n    bind $bindtag <MouseWheel> \"$callback %D -120.0\"\n    bind $bindtag <Option-MouseWheel> \"$callback %D -12.0\"\n}\n\n## Mousewheel bindings for standard scrollable widgets.\n#\n\nbind TtkScrollable <MouseWheel> \\\n\t{ tk::MouseWheel %W y %D -40.0 }\nbind TtkScrollable <Option-MouseWheel> \\\n\t{ tk::MouseWheel %W y %D -12.0 }\nbind TtkScrollable <Shift-MouseWheel> \\\n\t{ tk::MouseWheel %W x %D -40.0 }\nbind TtkScrollable <Shift-Option-MouseWheel> \\\n\t{ tk::MouseWheel %W x %D -12.0 }\n\n## Touchpad scrolling\n#\nbind TtkScrollable <TouchpadScroll> {\n    if {%# %% 5 == 0} {\n\tlassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)\n\tif {$tk::Priv(deltaX) != 0} {\n\t    %W xview scroll [expr {-$tk::Priv(deltaX)}] units\n\t}\n\tif {$tk::Priv(deltaY) != 0} {\n\t    %W yview scroll [expr {-$tk::Priv(deltaY)}] units\n\t}\n    }\n}\n#*EOF*\n"
  },
  {
    "path": "library/ttk/vistaTheme.tcl",
    "content": "#\n# Settings for Microsoft Windows Vista and Server 2008\n#\n\nnamespace eval ttk::theme::vista {\n\n    ttk::style theme settings vista {\n\n\tttk::style configure . \\\n\t    -background SystemButtonFace \\\n\t    -foreground SystemWindowText \\\n\t    -selectforeground SystemHighlightText \\\n\t    -selectbackground SystemHighlight \\\n\t    -insertcolor SystemWindowText \\\n\t    -font TkDefaultFont\n\n\tttk::style map \".\" -foreground {disabled SystemGrayText}\n\n\tttk::style configure TButton -anchor center -padding 0.75p -width -11\n\tttk::style configure TRadiobutton -padding 1.5p\n\tttk::style configure TCheckbutton -padding 1.5p\n\tttk::style configure TMenubutton -padding {6p 3p}\n\n\tttk::style element create Menubutton.dropdown vsapi \\\n\t    TOOLBAR 4 {{selected active} 6 {selected !active} 5\n\t\tdisabled 4 pressed 3 active 2 {} 1} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\n\t# Label and Toolbutton\n\tttk::style configure TLabelframe.Label -foreground SystemButtonText\n\n\tttk::style configure Toolbutton -padding 3p\n\n\t# Combobox\n\tttk::style configure TCombobox -padding 1.5p\n\tttk::style element create Combobox.border vsapi \\\n\t    COMBOBOX 4 {disabled 4 focus 3 active 2 hover 2 {} 1}\n\tttk::style element create Combobox.background vsapi \\\n\t    EDIT 3 {disabled 3 readonly 5 focus 4 hover 2 {} 1}\n\tttk::style element create Combobox.rightdownarrow vsapi \\\n\t    COMBOBOX 6 {disabled 4 pressed 3 active 2 {} 1} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\tttk::style layout TCombobox {\n\t    Combobox.border -sticky nswe -border 0 -children {\n\t\tCombobox.rightdownarrow -side right -sticky ns\n\t\tCombobox.padding -sticky nswe -children {\n\t\t    Combobox.background -sticky nswe -children {\n\t\t\tCombobox.focus -sticky nswe -children {\n\t\t\t    Combobox.textarea -sticky nswe\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n\t# Vista.Combobox droplist frame\n\tttk::style element create ComboboxPopdownFrame.background vsapi\\\n\t    LISTBOX 3 {disabled 4 active 3 focus 2 {} 1}\n\tttk::style layout ComboboxPopdownFrame {\n\t    ComboboxPopdownFrame.background -sticky news -border 1 -children {\n\t\tComboboxPopdownFrame.padding -sticky news\n\t    }\n\t}\n\tttk::style map TCombobox \\\n\t    -selectbackground [list !focus SystemWindow] \\\n\t    -selectforeground [list !focus SystemWindowText] \\\n\t    -foreground\t[list \\\n\t\tdisabled\t\tSystemGrayText \\\n\t\t{readonly focus}\tSystemHighlightText \\\n\t    ] \\\n\t    -focusfill\t[list {readonly focus} SystemHighlight]\n\n\t# Entry\n\tttk::style configure TEntry -padding {1 1 1 1} ;# Needs lookup\n\tttk::style element create Entry.field vsapi \\\n\t    EDIT 6 {disabled 4 focus 3 hover 2 {} 1} -padding {2 2 2 2}\n\tttk::style element create Entry.background vsapi \\\n\t    EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}\n\tttk::style layout TEntry {\n\t    Entry.field -sticky news -border 0 -children {\n\t\tEntry.background -sticky news -children {\n\t\t    Entry.padding -sticky news -children {\n\t\t\tEntry.textarea -sticky news\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tttk::style map TEntry \\\n\t    -selectbackground [list !focus SystemWindow] \\\n\t    -selectforeground [list !focus SystemWindowText]\n\n\t# Spinbox\n\tttk::style configure TSpinbox -padding 0\n\tttk::style element create Spinbox.field vsapi \\\n\t    EDIT 9 {disabled 4 focus 3 hover 2 {} 1} -padding {1 1 1 2}\n\tttk::style element create Spinbox.background vsapi \\\n\t    EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}\n\tttk::style element create Spinbox.innerbg vsapi \\\n\t    EDIT 3 {disabled 3 readonly 3 focus 4 hover 2 {} 1}\\\n\t    -padding {2 0 15 2}\n\tttk::style element create Spinbox.uparrow vsapi \\\n\t    SPIN 1 {disabled 4 pressed 3 active 2 {} 1} \\\n\t    -padding 1 -halfheight 1 \\\n\t    -syssize { SM_CXVSCROLL SM_CYVSCROLL }\n\tttk::style element create Spinbox.downarrow vsapi \\\n\t    SPIN 2 {disabled 4 pressed 3 active 2 {} 1} \\\n\t    -padding 1 -halfheight 1 \\\n\t    -syssize { SM_CXVSCROLL SM_CYVSCROLL }\n\tttk::style layout TSpinbox {\n\t    Spinbox.field -sticky nswe -children {\n\t\tSpinbox.background -sticky news -children {\n\t\t    Spinbox.padding -sticky news -children {\n\t\t\tSpinbox.innerbg -sticky news -children {\n\t\t\t    Spinbox.textarea\n\t\t\t}\n\t\t    }\n\t\t    Spinbox.uparrow -side top -sticky ens\n\t\t    Spinbox.downarrow -side bottom -sticky ens\n\t\t}\n\t    }\n\t}\n\tttk::style map TSpinbox \\\n\t    -selectbackground [list !focus SystemWindow] \\\n\t    -selectforeground [list !focus SystemWindowText]\n\n\t# Scrollbar elements (Vista includes a state for 'hover')\n\tttk::style element create Vertical.Scrollbar.uparrow vsapi \\\n\t    SCROLLBAR 1 {disabled 4 pressed 3 active 2 hover 17 {} 1} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\tttk::style element create Vertical.Scrollbar.downarrow vsapi \\\n\t    SCROLLBAR 1 {disabled 8 pressed 7 active 6 hover 18 {} 5} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\tttk::style element create Vertical.Scrollbar.trough vsapi \\\n\t    SCROLLBAR 7 {disabled 4 pressed 3 active 2 hover 5 {} 1}\n\tttk::style element create Vertical.Scrollbar.thumb vsapi \\\n\t    SCROLLBAR 3 {disabled 4 pressed 3 active 2 hover 5 {} 1} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\tttk::style element create Vertical.Scrollbar.grip vsapi \\\n\t    SCROLLBAR 9 {disabled 4 pressed 3 active 2 hover 5 {} 1} \\\n\t    -syssize {SM_CXVSCROLL SM_CYVSCROLL}\n\tttk::style element create Horizontal.Scrollbar.leftarrow vsapi \\\n\t    SCROLLBAR 1 {disabled 12 pressed 11 active 10 hover 19 {} 9} \\\n\t    -syssize {SM_CXHSCROLL SM_CYHSCROLL}\n\tttk::style element create Horizontal.Scrollbar.rightarrow vsapi \\\n\t    SCROLLBAR 1 {disabled 16 pressed 15 active 14 hover 20 {} 13} \\\n\t    -syssize {SM_CXHSCROLL SM_CYHSCROLL}\n\tttk::style element create Horizontal.Scrollbar.trough vsapi \\\n\t    SCROLLBAR 5 {disabled 4 pressed 3 active 2 hover 5 {} 1}\n\tttk::style element create Horizontal.Scrollbar.thumb vsapi \\\n\t    SCROLLBAR 2 {disabled 4 pressed 3 active 2 hover 5 {} 1} \\\n\t    -syssize {SM_CXHSCROLL SM_CYHSCROLL}\n\tttk::style element create Horizontal.Scrollbar.grip vsapi \\\n\t    SCROLLBAR 8 {disabled 4 pressed 3 active 2 hover 5 {} 1}\n\n\t# Notebook\n\tttk::style configure TNotebook -tabmargins {2 2 2 0}\n\tttk::style map TNotebook.Tab -expand {selected {2 2 2 2}}\n\n\t# Progressbar\n\tttk::style element create Horizontal.Progressbar.pbar vsapi \\\n\t    PROGRESS 3 {{} 1} -padding 8\n\tttk::style layout Horizontal.TProgressbar {\n\t    Horizontal.Progressbar.trough -sticky nswe -children {\n\t\tHorizontal.Progressbar.pbar -side left -sticky ns\n\t\tHorizontal.Progressbar.ctext -sticky nesw\n\t    }\n\t}\n\tttk::style element create Vertical.Progressbar.pbar vsapi \\\n\t    PROGRESS 3 {{} 1} -padding 8\n\tttk::style layout Vertical.TProgressbar {\n\t    Vertical.Progressbar.trough -sticky nswe -children {\n\t\tVertical.Progressbar.pbar -side bottom -sticky we\n\t    }\n\t}\n\n\t# Scale\n\tttk::style element create Horizontal.Scale.slider vsapi \\\n\t    TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \\\n\t    -width 6 -height 12\n\tttk::style layout Horizontal.TScale {\n\t    Scale.focus -sticky nswe -children {\n\t\tHorizontal.Scale.trough -sticky nswe -children {\n\t\t    Horizontal.Scale.track -sticky we\n\t\t    Horizontal.Scale.slider -side left -sticky {}\n\t\t}\n\t    }\n\t}\n\tttk::style element create Vertical.Scale.slider vsapi \\\n\t    TRACKBAR 6 {disabled 5 focus 4 pressed 3 active 2 {} 1} \\\n\t    -width 12 -height 6\n\tttk::style layout Vertical.TScale {\n\t    Scale.focus -sticky nswe -children {\n\t\tVertical.Scale.trough -sticky nswe -children {\n\t\t    Vertical.Scale.track -sticky ns\n\t\t    Vertical.Scale.slider -side top -sticky {}\n\t\t}\n\t    }\n\t}\n\n\t# Treeview\n\tttk::style configure Heading -font TkHeadingFont\n\tttk::style configure Item -padding {3p 0 0 0}\n\tttk::style configure Treeview -background SystemWindow \\\n\t    -stripedbackground System3dLight -indent 15p\n\tttk::setTreeviewRowHeight\n\tttk::style configure Treeview.Separator \\\n\t    -background System3dLight\n\t# The treeview uses the \"background\" state for\n\t# selected items when the widget has lost the focus.\n\tttk::style map Treeview \\\n\t    -background [list   disabled SystemButtonFace \\\n\t\t\t\tbackground #d9d9d9 \\\n\t\t\t\tselected SystemHighlight] \\\n\t    -foreground [list   disabled SystemGrayText \\\n\t\t\t\tbackground SystemWindowText \\\n\t\t\t\tselected SystemHighlightText]\n    }\n}\n\n# ttk::theme::vista::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook style $style and the\n# style $style.Tab.  Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::vista::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn {\n\t    ttk::style configure $style -tabmargins     {2 2 2 0}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 2}}\n\t}\n\ts {\n\t    ttk::style configure $style -tabmargins     {2 0 2 2}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 2}}\n\t}\n\tw {\n\t    ttk::style configure $style -tabmargins     {2 2 0 2}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 2}}\n\t}\n\te {\n\t    ttk::style configure $style -tabmargins     {0 2 2 2}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 2}}\n\t}\n\tdefault {\n\t    ttk::style configure $style -tabmargins     {2 2 2 0}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 2}}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/ttk/wideSpinbox.tcl",
    "content": "#==============================================================================\n# wideSpinbox.tcl - Copyright © 2025 Csaba Nemethi <csaba.nemethi@t-online.de>\n#\n# Contains the implementation of the Wide.TSpinbox layout, and arranges for it\n# to be created automatically for the current theme when needed.\n#\n# Usage:\n#   ttk::spinbox <pathName> -style Wide.TSpinbox ...\n#\n# Structure of the module:\n#   - Private procedures and data\n#   - Public procedures\n#==============================================================================\n\n# Private procedures and data\n# ===========================\n\ninterp alias {} ttk::wideSpinbox::CreateElem {} ttk::style element create\n\nnamespace eval ttk::wideSpinbox {\n    variable uparrowImgData {\n<svg width=\"20\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"8\" r=\"8\" fill=\"bg\"/>\n <path d=\"m6 10 4-4 4 4\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\" }\n    variable downarrowImgData {\n<svg width=\"20\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"8\" r=\"8\" fill=\"bg\"/>\n <path d=\"m6 6 4 4 4-4\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\" }\n\n    variable onAndroid\t  [expr {[info exists ::tk::android] && $::tk::android}]\n    variable madeElements 0\n}\n\n#------------------------------------------------------------------------------\n# ttk::wideSpinbox::NormalizeColor\n#\n# Returns the representation of a given color in the form \"#RRGGBB\".\n#------------------------------------------------------------------------------\nproc ttk::wideSpinbox::NormalizeColor color {\n    lassign [winfo rgb . $color] r g b\n    return [format \"#%02x%02x%02x\" \\\n\t    [expr {$r >> 8}] [expr {$g >> 8}] [expr {$b >> 8}]]\n}\n\n#------------------------------------------------------------------------------\n# ttk::wideSpinbox::CreateElements\n#\n# Creates the elements WideSpinbox.uparrow, WideSpinbox.downarrow, and\n# WideSpinbox.gap of the Wide.TSpinbox layout for a given theme.\n#------------------------------------------------------------------------------\nproc ttk::wideSpinbox::CreateElements theme {\n    # Create the WideSpinbox.uparrow element\n\n    variable uparrowImgsArr\n    set img  [CreateImg]\n    set dImg [CreateImg]\n    set pImg [CreateImg]\n    set aImg [CreateImg]\n    set uparrowImgsArr($theme) [list $img $dImg $pImg $aImg]\n    CreateElem WideSpinbox.uparrow image [list $img \\\n\t    disabled $dImg  pressed $pImg  active $aImg]\n\n    # Create the WideSpinbox.downarrow element\n\n    variable downarrowImgsArr\n    set img  [CreateImg]\n    set dImg [CreateImg]\n    set pImg [CreateImg]\n    set aImg [CreateImg]\n    set downarrowImgsArr($theme) [list $img $dImg $pImg $aImg]\n    CreateElem WideSpinbox.downarrow image [list $img \\\n\t    disabled $dImg  pressed $pImg  active $aImg]\n\n    # Create the WideSpinbox.gap element\n\n    variable gapImg\n    CreateElem WideSpinbox.gap image $gapImg\n\n    # Create the Wide.TSpinbox layout\n\n    if {$theme eq \"classic\"} {\n\tttk::style layout Wide.TSpinbox {\n\t    Entry.highlight -sticky nswe -children {\n\t\tEntry.field -sticky nswe -children {\n\t\t    WideSpinbox.uparrow -side right -sticky e\n\t\t    WideSpinbox.gap -side right -sticky e\n\t\t    WideSpinbox.downarrow -side right -sticky e\n\t\t    Entry.padding -sticky nswe -children {\n\t\t\tEntry.textarea -sticky nsew\n\t\t    }\n\t\t}\n\t    }\n\t}\n    } else {\n\tttk::style layout Wide.TSpinbox {\n\t    Entry.field -sticky nswe -children {\n\t\tWideSpinbox.uparrow -side right -sticky e\n\t\tWideSpinbox.gap -side right -sticky e\n\t\tWideSpinbox.downarrow -side right -sticky e\n\t\tEntry.padding -sticky nswe -children {\n\t\t    Entry.textarea -sticky nsew\n\t\t}\n\t    }\n\t}\n    }\n\n    set padding [ttk::style lookup TEntry -padding]\n    ttk::style configure Wide.TSpinbox -padding $padding\n}\n\n#------------------------------------------------------------------------------\n# ttk::wideSpinbox::UpdateElements\n#\n# Updates the elements WideSpinbox.uparrow and WideSpinbox.downarrow of the\n# Wide.TSpinbox layout for a given theme.\n#------------------------------------------------------------------------------\nproc ttk::wideSpinbox::UpdateElements theme {\n    set bg  [NormalizeColor [ttk::style lookup . -background {} #d9d9d9]]\n    variable onAndroid\n    set aBg [expr {$onAndroid ? $bg :\n\t    [NormalizeColor [ttk::style lookup . -background active #ececec]]}]\n    set fg  [NormalizeColor [ttk::style lookup . -foreground {} #000000]]\n    set dFg [NormalizeColor [ttk::style lookup . -foreground disabled #a3a3a3]]\n\n    if {$theme eq \"aqua\"} {\n\tscan $::tcl_platform(osVersion) \"%d\" majorOSVersion\n\tif {$majorOSVersion >= 18} {\t\t\t;# OS X 10.14 or later\n\t    set pBg [NormalizeColor systemControlAccentColor]\n\t} else {\n\t    set pBg [NormalizeColor systemHighlightAlternate]\n\t}\n\tset pFg #ffffff\n    } else {\n\tset pBg [ttk::style lookup . -selectbackground focus #000000]\n\tset pBg [NormalizeColor $pBg]\n\tset pFg [ttk::style lookup . -selectforeground focus #ffffff]\n\tset pFg [NormalizeColor $pFg]\n    }\n\n    set imgList [image names]\n\n    # Update the WideSpinbox.uparrow element\n\n    variable uparrowImgsArr\n    foreach img $uparrowImgsArr($theme) {\n\tif {$img ni $imgList} {\n\t    return \"\"\n\t}\n    }\n\n    lassign $uparrowImgsArr($theme) img dImg pImg aImg\n    variable uparrowImgData\n\n    set imgData $uparrowImgData\n    set idx [string first \"bg\" $imgData]\n    set imgData [string replace $imgData $idx $idx+1 $bg]\n    append imgData \"stroke='$fg'/>\\n</svg>\"\n    $img configure -data $imgData\n\n    set imgData $uparrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $bg]\n    append imgData \"stroke='$dFg'/>\\n</svg>\"\n    $dImg configure -data $imgData\n\n    set imgData $uparrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $pBg]\n    append imgData \"stroke='$pFg'/>\\n</svg>\"\n    $pImg configure -data $imgData\n\n    set imgData $uparrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $aBg]\n    append imgData \"stroke='$fg'/>\\n</svg>\"\n    $aImg configure -data $imgData\n\n    # Update the WideSpinbox.downarrow element\n\n    variable downarrowImgsArr\n    foreach img $downarrowImgsArr($theme) {\n\tif {$img ni $imgList} {\n\t    return \"\"\n\t}\n    }\n\n    lassign $downarrowImgsArr($theme) img dImg pImg aImg\n    variable downarrowImgData\n\n    set imgData $downarrowImgData\n    set idx [string first \"bg\" $imgData]\n    set imgData [string replace $imgData $idx $idx+1 $bg]\n    append imgData \"stroke='$fg'/>\\n</svg>\"\n    $img configure -data $imgData\n\n    set imgData $downarrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $bg]\n    append imgData \"stroke='$dFg'/>\\n</svg>\"\n    $dImg configure -data $imgData\n\n    set imgData $downarrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $pBg]\n    append imgData \"stroke='$pFg'/>\\n</svg>\"\n    $pImg configure -data $imgData\n\n    set imgData $downarrowImgData\n    set imgData [string replace $imgData $idx $idx+1 $aBg]\n    append imgData \"stroke='$fg'/>\\n</svg>\"\n    $aImg configure -data $imgData\n}\n\n# Public procedures\n# =================\n\n#------------------------------------------------------------------------------\n# ttk::wideSpinbox::CondMakeElements\n#\n# Creates the elements WideSpinbox.uparrow and WideSpinbox.downarrow of the\n# Wide.TSpinbox layout if necessary.  Invoked from within the C code, by the\n# ttk::spinbox widget initialization hook.\n#------------------------------------------------------------------------------\nproc ttk::wideSpinbox::CondMakeElements {} {\n    variable madeElements\n    if {!$madeElements} {\n\t# If Tk's scaling factor was changed via \"tk scaling\"\n\t# then $::tk::svgFmt now has the updated value.\n\n\tinterp alias {} ::ttk::wideSpinbox::CreateImg \\\n\t\t     {} image create photo -format $::tk::svgFmt\n\tvariable gapImg [CreateImg -data {\n<svg width=\"4\" height=\"16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"/>}]\n\n\tset theme [ttk::style theme use]\n\tCreateElements $theme\n\tUpdateElements $theme\n\n\tvariable elemInfoArr\n\tset elemInfoArr($theme) 1\n\n\tset madeElements 1\n    }\n}\n\n#------------------------------------------------------------------------------\n# ttk::wideSpinbox::MakeOrUpdateElements\n#\n# Creates and/or updates the elements WideSpinbox.uparrow and\n# WideSpinbox.downarrow of the Wide.TSpinbox layout for the current theme if\n# necessary.  Invoked from within the procedures ttk::ThemeChanged and\n# ttk::AppearanceChanged (see ttk.tcl).\n#------------------------------------------------------------------------------\nproc ttk::wideSpinbox::MakeOrUpdateElements {} {\n    variable madeElements\n    if {!$madeElements} {\n\treturn \"\"\n    }\n\n    variable elemInfoArr\n    set theme [ttk::style theme use]\n\n    if {![info exists elemInfoArr($theme)]} {\n\tCreateElements $theme\n\tUpdateElements $theme\n\tset elemInfoArr($theme) 1\n    } elseif {$theme eq \"aqua\"} {\n\tUpdateElements $theme\n    }\n}\n"
  },
  {
    "path": "library/ttk/winTheme.tcl",
    "content": "#\n# Settings for 'winnative' theme.\n#\n\nnamespace eval ttk::theme::winnative {\n\n    ttk::style theme settings winnative {\n\n\tttk::style configure \".\" \\\n\t    -background SystemButtonFace \\\n\t    -foreground SystemWindowText \\\n\t    -selectforeground SystemHighlightText \\\n\t    -selectbackground SystemHighlight \\\n\t    -fieldbackground SystemWindow \\\n\t    -insertcolor SystemWindowText \\\n\t    -troughcolor SystemScrollbar \\\n\t    -font TkDefaultFont\n\n\tttk::style map \".\" -foreground {disabled SystemGrayText}\n\tttk::style map \".\" -embossed {disabled 1}\n\n\tttk::style configure TButton \\\n\t    -anchor center -width -11 -relief raised -shiftrelief 1\n\tttk::style map TButton -relief {{!disabled pressed} sunken}\n\n\tttk::style configure TCheckbutton -padding {1.5p 3p}\n\tttk::style configure TRadiobutton -padding {1.5p 3p}\n\n\tttk::style configure TMenubutton \\\n\t    -padding {6p 3p} -arrowsize 2.25p -relief raised\n\n\tttk::style configure TEntry \\\n\t    -padding 2 -insertwidth 1\n\tttk::style map TEntry \\\n\t    -fieldbackground \\\n\t\t{readonly SystemButtonFace disabled SystemButtonFace} \\\n\t    -selectbackground {!focus SystemWindow} \\\n\t    -selectforeground {!focus SystemWindowText}\n\n\tttk::style configure TCombobox -padding 1.5p\n\tttk::style map TCombobox \\\n\t    -selectbackground [list !focus SystemWindow] \\\n\t    -selectforeground [list !focus SystemWindowText] \\\n\t    -fieldbackground [list \\\n\t\treadonly SystemButtonFace \\\n\t\tdisabled SystemButtonFace] \\\n\t    -foreground\t[list \\\n\t\tdisabled\t\tSystemGrayText \\\n\t\t{readonly focus}\tSystemHighlightText \\\n\t    ] \\\n\t    -focusfill {{readonly focus} SystemHighlight}\n\n\tttk::style element create ComboboxPopdownFrame.border from default\n\tttk::style configure ComboboxPopdownFrame \\\n\t    -borderwidth 1 -relief solid\n\n\tttk::style configure TSpinbox -padding {1.5p 0 12p 0}\n\n\tttk::style configure TLabelframe -borderwidth 2 -relief groove\n\n\tttk::style configure Toolbutton -relief flat -padding {6p 3p}\n\tttk::style map Toolbutton -relief \\\n\t    {disabled flat  selected sunken  pressed sunken  active raised}\n\n\tttk::style configure TScale -groovewidth 3p\n\n\tttk::style configure TNotebook -tabmargins {2 2 2 0}\n\tttk::style configure TNotebook.Tab -padding {2.25p 0.75p} -borderwidth 1\n\tttk::style map TNotebook.Tab -expand {selected {2 2 2 0}}\n\n\t# Treeview\n\tttk::style configure Heading -font TkHeadingFont -relief raised\n\tttk::style configure Item \\\n\t    -indicatormargins {1.5p 1.5p 3p 1.5p}\n\tttk::style configure Treeview -background SystemWindow \\\n\t    -stripedbackground System3dLight -indent 15p\n\tttk::setTreeviewRowHeight\n\t# The treeview uses the \"background\" state for\n\t# selected items when the widget has lost the focus.\n\tttk::style map Treeview \\\n\t    -background [list   disabled SystemButtonFace \\\n\t\t\t\tbackground #d9d9d9 \\\n\t\t\t\tselected SystemHighlight] \\\n\t    -foreground [list   disabled SystemGrayText \\\n\t\t\t\tbackground SystemWindowText \\\n\t\t\t\tselected SystemHighlightText]\n\n\tttk::style configure TProgressbar \\\n\t    -background SystemHighlight -borderwidth 0 \\\n\t    -barsize 22.5p -thickness 11.25p\n    }\n}\n\n# ttk::theme::winnative::configureNotebookStyle --\n#\n# Sets theme-specific option values for the ttk::notebook style $style and the\n# style $style.Tab.  Invoked by ::ttk::configureNotebookStyle.\n\nproc ttk::theme::winnative::configureNotebookStyle {style} {\n    set tabPos [ttk::style lookup $style -tabposition {} nw]\n    switch -- [string index $tabPos 0] {\n\tn {\n\t    ttk::style configure $style -tabmargins     {2 2 2 0}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 0}}\n\t}\n\ts {\n\t    ttk::style configure $style -tabmargins     {2 0 2 2}\n\t    ttk::style map $style.Tab -expand {selected {2 0 2 2}}\n\t}\n\tw {\n\t    ttk::style configure $style -tabmargins     {2 2 0 2}\n\t    ttk::style map $style.Tab -expand {selected {2 2 0 2}}\n\t}\n\te {\n\t    ttk::style configure $style -tabmargins     {0 2 2 2}\n\t    ttk::style map $style.Tab -expand {selected {0 2 2 2}}\n\t}\n\tdefault {\n\t    ttk::style configure $style -tabmargins     {2 2 2 0}\n\t    ttk::style map $style.Tab -expand {selected {2 2 2 0}}\n\t}\n    }\n}\n"
  },
  {
    "path": "library/xmfbox.tcl",
    "content": "# xmfbox.tcl --\n#\n#\tImplements the \"Motif\" style file selection dialog for the\n#\tUnix platform. This implementation is used only if the\n#\t\"::tk_strictMotif\" flag is set.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Scriptics Corporation\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nnamespace eval ::tk::dialog {}\nnamespace eval ::tk::dialog::file {}\n\n\n# ::tk::MotifFDialog --\n#\n#\tImplements a file dialog similar to the standard Motif file\n#\tselection box.\n#\n# Arguments:\n#\ttype\t\t\"open\" or \"save\"\n#\targs\t\tOptions parsed by the procedure.\n#\n# Results:\n#\tWhen -multiple is set to 0, this returns the absolute pathname\n#\tof the selected file. (NOTE: This is not the same as a single\n#\telement list.)\n#\n#\tWhen -multiple is set to > 0, this returns a Tcl list of absolute\n#       pathnames. The argument for -multiple is ignored, but for consistency\n#       with Windows it defines the maximum amount of memory to allocate for\n#       the returned filenames.\n\nproc ::tk::MotifFDialog {type args} {\n    variable ::tk::Priv\n    set dataName __tk_filedialog\n    upvar ::tk::dialog::file::$dataName data\n\n    set w [MotifFDialog_Create $dataName $type $args]\n\n    # Set a grab and claim the focus too.\n\n    ::tk::SetFocusGrab $w $data(sEnt)\n    $data(sEnt) selection range 0 end\n\n    # Wait for the user to respond, then restore the focus and\n    # return the index of the selected button.  Restore the focus\n    # before deleting the window, since otherwise the window manager\n    # may take the focus away so we can't redirect it.  Finally,\n    # restore any grab that was in effect.\n\n    vwait ::tk::Priv(selectFilePath)\n    set result $Priv(selectFilePath)\n    ::tk::RestoreFocusGrab $w $data(sEnt) withdraw\n\n    return $result\n}\n\n# ::tk::MotifFDialog_Create --\n#\n#\tCreates the Motif file dialog (if it doesn't exist yet) and\n#\tinitialize the internal data structure associated with the\n#\tdialog.\n#\n#\tThis procedure is used by ::tk::MotifFDialog to create the\n#\tdialog. It's also used by the test suite to test the Motif\n#\tfile dialog implementation. User code shouldn't call this\n#\tprocedure directly.\n#\n# Arguments:\n#\tdataName\tName of the global \"data\" array for the file dialog.\n#\ttype\t\t\"Save\" or \"Open\"\n#\targList\t\tOptions parsed by the procedure.\n#\n# Results:\n#\tPathname of the file dialog.\n\nproc ::tk::MotifFDialog_Create {dataName type argList} {\n    upvar ::tk::dialog::file::$dataName data\n\n    MotifFDialog_Config $dataName $type $argList\n\n    if {$data(-parent) eq \".\"} {\n\tset w .$dataName\n    } else {\n\tset w $data(-parent).$dataName\n    }\n\n    # (re)create the dialog box if necessary\n    #\n    if {![winfo exists $w]} {\n\tMotifFDialog_BuildUI $w\n    } elseif {[winfo class $w] ne \"TkMotifFDialog\"} {\n\tdestroy $w\n\tMotifFDialog_BuildUI $w\n    } else {\n\tset data(fEnt) $w.top.f1.ent\n\tset data(dList) $w.top.f2.a.l\n\tset data(fList) $w.top.f2.b.l\n\tset data(sEnt) $w.top.f3.ent\n\tset data(okBtn) $w.bot.ok\n\tset data(filterBtn) $w.bot.filter\n\tset data(cancelBtn) $w.bot.cancel\n    }\n    MotifFDialog_SetListMode $w\n\n    # Dialog boxes should be transient with respect to their parent,\n    # so that they will always stay on top of their parent window.  However,\n    # some window managers will create the window as withdrawn if the parent\n    # window is withdrawn or iconified.  Combined with the grab we put on the\n    # window, this can hang the entire application.  Therefore we only make\n    # the dialog transient if the parent is viewable.\n\n    if {[winfo viewable [winfo toplevel $data(-parent)]] } {\n\twm transient $w $data(-parent)\n    }\n\n    MotifFDialog_FileTypes $w\n    MotifFDialog_Update $w\n\n    # Withdraw the window, then update all the geometry information\n    # so we know how big it wants to be, then center the window in the\n    # display (Motif style) and de-iconify it.\n\n    ::tk::PlaceWindow $w\n    wm title $w $data(-title)\n\n    return $w\n}\n\n# ::tk::MotifFDialog_FileTypes --\n#\n#\tChecks the -filetypes option. If present this adds a list of radio-\n#\tbuttons to pick the file types from.\n#\n# Arguments:\n#\tw\t\tPathname of the tk_get*File dialogue.\n#\n# Results:\n#\tnone\n\nproc ::tk::MotifFDialog_FileTypes {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set f $w.top.f3.types\n    destroy $f\n\n    # No file types: use \"*\" as the filter and display no radio-buttons\n    if {$data(-filetypes) eq \"\"} {\n\tset data(filter) *\n\treturn\n    }\n\n    # The filetypes radiobuttons\n    # set data(fileType) $data(-defaulttype)\n    # Default type to first entry\n    set initialTypeName [lindex $data(origfiletypes) 0 0]\n    if {$data(-typevariable) ne \"\"} {\n\tupvar #0 $data(-typevariable) typeVariable\n\tif {[info exists typeVariable]} {\n\t    set initialTypeName $typeVariable\n\t}\n    }\n    set ix 0\n    set data(fileType) 0\n    foreach fltr $data(origfiletypes) {\n\tset fname [lindex $fltr 0]\n\tif {[string first $initialTypeName $fname] == 0} {\n\t    set data(fileType) $ix\n\t    break\n\t}\n\tincr ix\n    }\n\n    MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]\n\n    #don't produce radiobuttons for only one filetype\n    if {[llength $data(-filetypes)] == 1} {\n\treturn\n    }\n\n    frame $f\n    set cnt 0\n    if {$data(-filetypes) ne {}} {\n\tforeach type $data(-filetypes) {\n\t    set title  [lindex $type 0]\n\t    set filter [lindex $type 1]\n\t    radiobutton $f.b$cnt \\\n\t\t-text $title \\\n\t\t-variable ::tk::dialog::file::[winfo name $w](fileType) \\\n\t\t-value $cnt \\\n\t\t-command [list tk::MotifFDialog_SetFilter $w $type]\n\t    pack $f.b$cnt -side left\n\t    incr cnt\n\t}\n    }\n    $f.b$data(fileType) invoke\n\n    pack $f -side bottom -fill both\n\n    return\n}\n\n# This proc gets called whenever data(filter) is set\n#\nproc ::tk::MotifFDialog_SetFilter {w type} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n    variable ::tk::Priv\n\n    set data(filter) [lindex $type 1]\n\n    MotifFDialog_Update $w\n}\n\n# ::tk::MotifFDialog_Config --\n#\n#\tIterates over the optional arguments to determine the option\n#\tvalues for the Motif file dialog; gives default values to\n#\tunspecified options.\n#\n# Arguments:\n#\tdataName\tThe name of the global variable in which\n#\t\t\tdata for the file dialog is stored.\n#\ttype\t\t\"Save\" or \"Open\"\n#\targList\t\tOptions parsed by the procedure.\n\nproc ::tk::MotifFDialog_Config {dataName type argList} {\n    upvar ::tk::dialog::file::$dataName data\n\n    set data(type) $type\n\n    # 1: the configuration specs\n    #\n    set specs {\n\t{-defaultextension \"\" \"\" \"\"}\n\t{-filetypes \"\" \"\" \"\"}\n\t{-initialdir \"\" \"\" \"\"}\n\t{-initialfile \"\" \"\" \"\"}\n\t{-parent \"\" \"\" \".\"}\n\t{-title \"\" \"\" \"\"}\n\t{-typevariable \"\" \"\" \"\"}\n    }\n    if {$type eq \"open\"} {\n\tlappend specs {-multiple \"\" \"\" \"0\"}\n    }\n    if {$type eq \"save\"} {\n\tlappend specs {-confirmoverwrite \"\" \"\" \"1\"}\n    }\n\n    set data(-multiple) 0\n    set data(-confirmoverwrite) 1\n    # 2: default values depending on the type of the dialog\n    #\n    if {![info exists data(selectPath)]} {\n\t# first time the dialog has been popped up\n\tset data(selectPath) [pwd]\n\tset data(selectFile) \"\"\n    }\n\n    # 3: parse the arguments\n    #\n    tclParseConfigSpec ::tk::dialog::file::$dataName $specs \"\" $argList\n\n    if {$data(-title) eq \"\"} {\n\tif {$type eq \"open\"} {\n\t    if {$data(-multiple) != 0} {\n\t\tset data(-title) \"[mc {Open Multiple Files}]\"\n\t    } else {\n\t\tset data(-title) [mc \"Open\"]\n\t    }\n\t} else {\n\t    set data(-title) [mc \"Save As\"]\n\t}\n    }\n\n    # 4: set the default directory and selection according to the -initial\n    #    settings\n    #\n    if {$data(-initialdir) ne \"\"} {\n\tif {[file isdirectory $data(-initialdir)]} {\n\t    set data(selectPath) [lindex [glob $data(-initialdir)] 0]\n\t} else {\n\t    set data(selectPath) [pwd]\n\t}\n\n\t# Convert the initialdir to an absolute path name.\n\n\tset old [pwd]\n\tcd $data(selectPath)\n\tset data(selectPath) [pwd]\n\tcd $old\n    }\n    set data(selectFile) $data(-initialfile)\n\n    # 5. Parse the -filetypes option. It is not used by the motif\n    #    file dialog, but we check for validity of the value to make sure\n    #    the application code also runs fine with the TK file dialog.\n    #\n    set data(origfiletypes) $data(-filetypes)\n    set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]\n\n    if {![info exists data(filter)]} {\n\tset data(filter) *\n    }\n    if {![winfo exists $data(-parent)]} {\n\treturn -code error -errorcode [list TK LOOKUP WINDOW $data(-parent)] \\\n\t    \"bad window path name \\\"$data(-parent)\\\"\"\n    }\n}\n\n# ::tk::MotifFDialog_BuildUI --\n#\n#\tBuilds the UI components of the Motif file dialog.\n#\n# Arguments:\n#\tw\t\tPathname of the dialog to build.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_BuildUI {w} {\n    set dataName [lindex [split $w .] end]\n    upvar ::tk::dialog::file::$dataName data\n\n    # Create the dialog toplevel and internal frames.\n    #\n    toplevel $w -class TkMotifFDialog\n    set top [frame $w.top -relief raised -bd 1]\n    set bot [frame $w.bot -relief raised -bd 1]\n\n    pack $w.bot -side bottom -fill x\n    pack $w.top -side top -expand yes -fill both\n\n    set f1 [frame $top.f1]\n    set f2 [frame $top.f2]\n    set f3 [frame $top.f3]\n\n    pack $f1 -side top    -fill x\n    pack $f3 -side bottom -fill x\n    pack $f2 -expand yes -fill both\n\n    set f2a [frame $f2.a]\n    set f2b [frame $f2.b]\n\n    grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 3p -pady 3p \\\n\t-sticky news\n    grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 3p -pady 3p \\\n\t-sticky news\n    grid rowconfigure $f2 0    -minsize 0   -weight 1\n    grid columnconfigure $f2 0 -minsize 0   -weight 1\n    grid columnconfigure $f2 1 -minsize 150 -weight 2\n\n    # The Filter box\n    #\n    bind [::tk::AmpWidget label $f1.lab -text [mc \"Fil&ter:\"] -anchor w] \\\n\t<<AltUnderlined>> [list focus $f1.ent]\n    entry $f1.ent\n    pack $f1.lab -side top -fill x -padx 4.5p -pady 3p\n    pack $f1.ent -side top -fill x -padx 3p -pady 0\n    set data(fEnt) $f1.ent\n\n    # The file and directory lists\n    #\n    set data(dList) [MotifFDialog_MakeSList $w $f2a \\\n\t    [mc \"&Directory:\"] DList]\n    set data(fList) [MotifFDialog_MakeSList $w $f2b \\\n\t    [mc \"Fi&les:\"]     FList]\n\n    # The Selection box\n    #\n    bind [::tk::AmpWidget label $f3.lab -text [mc \"&Selection:\"] -anchor w] \\\n\t<<AltUnderlined>> [list focus $f3.ent]\n    entry $f3.ent\n    pack $f3.lab -side top -fill x -padx 4.5p -pady 0\n    pack $f3.ent -side top -fill x -padx 3p -pady 3p\n    set data(sEnt) $f3.ent\n\n    # The buttons\n    #\n    set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]\n    set maxWidth [expr {$maxWidth<6?6:$maxWidth}]\n    set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc \"&OK\"] \\\n\t    -width $maxWidth \\\n\t    -command [list tk::MotifFDialog_OkCmd $w]]\n    set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc \"&Filter\"] \\\n\t    -width $maxWidth \\\n\t    -command [list tk::MotifFDialog_FilterCmd $w]]\n    set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc \"&Cancel\"] \\\n\t    -width $maxWidth \\\n\t    -command [list tk::MotifFDialog_CancelCmd $w]]\n\n    pack $bot.ok $bot.filter $bot.cancel -padx 7.5p -pady 7.5p -expand yes \\\n\t-side left\n\n    # Create the bindings:\n    #\n    bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]\n\n    bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]\n    bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]\n    bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]\n    bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}\n\n    wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]\n}\n\nproc ::tk::MotifFDialog_SetListMode {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {$data(-multiple) != 0} {\n\tset selectmode extended\n    } else {\n\tset selectmode browse\n    }\n    set f $w.top.f2.b\n    $f.l configure -selectmode $selectmode\n}\n\n# ::tk::MotifFDialog_MakeSList --\n#\n#\tCreate a scrolled-listbox and set the keyboard accelerator\n#\tbindings so that the list selection follows what the user\n#\ttypes.\n#\n# Arguments:\n#\tw\t\tPathname of the dialog box.\n#\tf\t\tFrame widget inside which to create the scrolled\n#\t\t\tlistbox. This frame widget already exists.\n#\tlabel\t\tThe string to display on top of the listbox.\n#\tunder\t\tSets the -under option of the label.\n#\tcmdPrefix\tSpecifies procedures to call when the listbox is\n#\t\t\tbrowsed or activated.\n\nproc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {\n    bind [::tk::AmpWidget label $f.lab -text $label -anchor w] \\\n\t<<AltUnderlined>> [list focus $f.l]\n    listbox $f.l -width 12 -height 5 -exportselection 0\\\n\t-xscrollcommand [list $f.h set]\t-yscrollcommand [list $f.v set]\n    scrollbar $f.v -orient vertical   -takefocus 0 -command [list $f.l yview]\n    scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]\n    grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 \\\n\t-padx 1.5p -pady 1.5p\n    grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news\n    grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news\n    grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news\n\n    grid rowconfigure    $f 0 -weight 0 -minsize 0\n    grid rowconfigure    $f 1 -weight 1 -minsize 0\n    grid columnconfigure $f 0 -weight 1 -minsize 0\n\n    # bindings for the listboxes\n    #\n    set list $f.l\n    bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]\n    bind $list <Double-ButtonRelease-1> \\\n\t    [list tk::MotifFDialog_Activate$cmdPrefix $w]\n    bind $list <Return>\t\"tk::MotifFDialog_Browse$cmdPrefix [list $w]; \\\n\t    tk::MotifFDialog_Activate$cmdPrefix [list $w]\"\n\n    bindtags $list [list Listbox $list [winfo toplevel $list] all]\n    ListBoxKeyAccel_Set $list\n\n    return $f.l\n}\n\n# ::tk::MotifFDialog_InterpFilter --\n#\n#\tInterpret the string in the filter entry into two components:\n#\tthe directory and the pattern. If the string is a relative\n#\tpathname, give a warning to the user and restore the pattern\n#\tto original.\n#\n# Arguments:\n#\tw\t\tpathname of the dialog box.\n#\n# Results:\n#\tA list of two elements. The first element is the directory\n#\tspecified # by the filter. The second element is the filter\n#\tpattern itself.\n\nproc ::tk::MotifFDialog_InterpFilter {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set text [string trim [$data(fEnt) get]]\n\n    # Perform tilde substitution\n    #\n    set badTilde 0\n    if {[string index $text 0] eq \"~\"} {\n\tset list [file split $text]\n\tset tilde [lindex $list 0]\n\tif {[catch {set tilde [glob $tilde]}]} {\n\t    set badTilde 1\n\t} else {\n\t    set text [eval file join [concat $tilde [lrange $list 1 end]]]\n\t}\n    }\n\n    # If the string is a relative pathname, combine it\n    # with the current selectPath.\n\n    set relative 0\n    if {[file pathtype $text] eq \"relative\"} {\n\tset relative 1\n    } elseif {$badTilde} {\n\tset relative 1\n    }\n\n    if {$relative} {\n\ttk_messageBox -icon warning -type ok \\\n\t\t-message \"\\\"$text\\\" must be an absolute pathname\"\n\n\t$data(fEnt) delete 0 end\n\t$data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \\\n\t\t$data(filter)]\n\n\treturn [list $data(selectPath) $data(filter)]\n    }\n\n    set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]\n\n    if {[file isdirectory $resolved]} {\n\tset dir $resolved\n\tset fil $data(filter)\n    } else {\n\tset dir [file dirname $resolved]\n\tset fil [file tail    $resolved]\n    }\n\n    return [list $dir $fil]\n}\n\n# ::tk::MotifFDialog_Update\n#\n#\tLoad the files and synchronize the \"filter\" and \"selection\" fields\n#\tboxes.\n#\n# Arguments:\n#\tw\t\tpathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_Update {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    $data(fEnt) delete 0 end\n    $data(fEnt) insert 0 \\\n\t    [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]\n    $data(sEnt) delete 0 end\n    $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \\\n\t    $data(selectFile)]\n\n    MotifFDialog_LoadFiles $w\n}\n\n# ::tk::MotifFDialog_LoadFiles --\n#\n#\tLoads the files and directories into the two listboxes according\n#\tto the filter setting.\n#\n# Arguments:\n#\tw\t\tpathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_LoadFiles {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    $data(dList) delete 0 end\n    $data(fList) delete 0 end\n\n    set appPWD [pwd]\n    if {[catch {cd $data(selectPath)}]} {\n\tcd $appPWD\n\n\t$data(dList) insert end \"..\"\n\treturn\n    }\n\n    # Make the dir and file lists\n    #\n    # For speed we only have one glob, which reduces the file system\n    # calls (good for slow NFS networks).\n    #\n    # We also do two smaller sorts (files + dirs) instead of one large sort,\n    # which gives a small speed increase.\n    #\n    set top 0\n    set dlist \"\"\n    set flist \"\"\n    foreach f [glob -nocomplain .* *] {\n\tif {[file isdir ./$f]} {\n\t    lappend dlist $f\n\t} else {\n\t    foreach pat $data(filter) {\n\t\tif {[string match $pat $f]} {\n\t\t    if {[string match .* $f]} {\n\t\t\tincr top\n\t\t    }\n\t\t    lappend flist $f\n\t\t    break\n\t\t}\n\t    }\n\t}\n    }\n    eval [list $data(dList) insert end] [lsort -dictionary $dlist]\n    eval [list $data(fList) insert end] [lsort -dictionary $flist]\n\n    # The user probably doesn't want to see the . files. We adjust the view\n    # so that the listbox displays all the non-dot files\n    $data(fList) yview $top\n\n    cd $appPWD\n}\n\n# ::tk::MotifFDialog_BrowseDList --\n#\n#\tThis procedure is called when the directory list is browsed\n#\t(clicked-over) by the user.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_BrowseDList {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    focus $data(dList)\n    if {[$data(dList) curselection] eq \"\"} {\n\treturn\n    }\n    set subdir [$data(dList) get [$data(dList) curselection]]\n    if {$subdir eq \"\"} {\n\treturn\n    }\n\n    $data(fList) selection clear 0 end\n\n    set list [MotifFDialog_InterpFilter $w]\n    set data(filter) [lindex $list 1]\n\n    switch -- $subdir {\n\t. {\n\t    set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]\n\t}\n\t.. {\n\t    set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] \\\n\t\t$data(filter)]\n\t}\n\tdefault {\n\t    set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile \\\n\t\t    $data(selectPath) $subdir] $data(filter)]\n\t}\n    }\n\n    $data(fEnt) delete 0 end\n    $data(fEnt) insert 0 $newSpec\n}\n\n# ::tk::MotifFDialog_ActivateDList --\n#\n#\tThis procedure is called when the directory list is activated\n#\t(double-clicked) by the user.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_ActivateDList {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[$data(dList) curselection] eq \"\"} {\n\treturn\n    }\n    set subdir [$data(dList) get [$data(dList) curselection]]\n    if {$subdir eq \"\"} {\n\treturn\n    }\n\n    $data(fList) selection clear 0 end\n\n    switch -- $subdir {\n\t. {\n\t    set newDir $data(selectPath)\n\t}\n\t.. {\n\t    set newDir [file dirname $data(selectPath)]\n\t}\n\tdefault {\n\t    set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]\n\t}\n    }\n\n    set data(selectPath) $newDir\n    MotifFDialog_Update $w\n\n    if {$subdir ne \"..\"} {\n\t$data(dList) selection set 0\n\t$data(dList) activate 0\n    } else {\n\t$data(dList) selection set 1\n\t$data(dList) activate 1\n    }\n}\n\n# ::tk::MotifFDialog_BrowseFList --\n#\n#\tThis procedure is called when the file list is browsed\n#\t(clicked-over) by the user.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_BrowseFList {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    focus $data(fList)\n    set data(selectFile) \"\"\n    foreach item [$data(fList) curselection] {\n\tlappend data(selectFile) [$data(fList) get $item]\n    }\n    if {[llength $data(selectFile)] == 0} {\n\treturn\n    }\n\n    $data(dList) selection clear 0 end\n\n    $data(fEnt) delete 0 end\n    $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \\\n\t    $data(filter)]\n    $data(fEnt) xview end\n\n    # if it's a multiple selection box, just put in the filenames\n    # otherwise put in the full path as usual\n    $data(sEnt) delete 0 end\n    if {$data(-multiple) != 0} {\n\t$data(sEnt) insert 0 $data(selectFile)\n    } else {\n\t$data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \\\n\t\t[lindex $data(selectFile) 0]]\n    }\n    $data(sEnt) xview end\n}\n\n# ::tk::MotifFDialog_ActivateFList --\n#\n#\tThis procedure is called when the file list is activated\n#\t(double-clicked) by the user.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_ActivateFList {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    if {[$data(fList) curselection] eq \"\"} {\n\treturn\n    }\n    set data(selectFile) [$data(fList) get [$data(fList) curselection]]\n    if {$data(selectFile) eq \"\"} {\n\treturn\n    } else {\n\tMotifFDialog_ActivateSEnt $w\n    }\n}\n\n# ::tk::MotifFDialog_ActivateFEnt --\n#\n#\tThis procedure is called when the user presses Return inside\n#\tthe \"filter\" entry. It updates the dialog according to the\n#\ttext inside the filter entry.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_ActivateFEnt {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set list [MotifFDialog_InterpFilter $w]\n    set data(selectPath) [lindex $list 0]\n    set data(filter)    [lindex $list 1]\n\n    MotifFDialog_Update $w\n}\n\n# ::tk::MotifFDialog_ActivateSEnt --\n#\n#\tThis procedure is called when the user presses Return inside\n#\tthe \"selection\" entry. It sets the ::tk::Priv(selectFilePath)\n#\tvariable so that the vwait loop in tk::MotifFDialog will be\n#\tterminated.\n#\n# Arguments:\n#\tw\t\tThe pathname of the dialog box.\n#\n# Results:\n#\tNone.\n\nproc ::tk::MotifFDialog_ActivateSEnt {w} {\n    variable ::tk::Priv\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    set selectFilePath [string trim [$data(sEnt) get]]\n\n    if {$selectFilePath eq \"\"} {\n\tMotifFDialog_FilterCmd $w\n\treturn\n    }\n\n    if {$data(-multiple) == 0} {\n\tset selectFilePath [list $selectFilePath]\n    }\n\n    if {[file isdirectory [lindex $selectFilePath 0]]} {\n\tset data(selectPath) [lindex [glob $selectFilePath] 0]\n\tset data(selectFile) \"\"\n\tMotifFDialog_Update $w\n\treturn\n    }\n\n    set newFileList \"\"\n    foreach item $selectFilePath {\n\tif {[file pathtype $item] ne \"absolute\"} {\n\t    set item [file join $data(selectPath) $item]\n\t} elseif {![file exists [file dirname $item]]} {\n\t    tk_messageBox -icon warning -type ok \\\n\t\t    -message [mc {Directory \"%1$s\" does not exist.} \\\n\t\t    [file dirname $item]]\n\t    return\n\t}\n\n\tif {![file exists $item]} {\n\t    if {$data(type) eq \"open\"} {\n\t\ttk_messageBox -icon warning -type ok \\\n\t\t\t-message [mc {File \"%1$s\" does not exist.} $item]\n\t\treturn\n\t    }\n\t} elseif {$data(type) eq \"save\" && $data(-confirmoverwrite)} {\n\t    set message [format %s%s \\\n\t\t    [mc \"File \\\"%1\\$s\\\" already exists.\\n\\n\" $selectFilePath] \\\n\t\t    [mc {Replace existing file?}]]\n\t    set answer [tk_messageBox -icon warning -type yesno \\\n\t\t    -message $message]\n\t    if {$answer eq \"no\"} {\n\t\treturn\n\t    }\n\t}\n\n\tlappend newFileList $item\n    }\n\n    # Return selected filter\n    if {[info exists data(-typevariable)] && $data(-typevariable) ne \"\"\n\t    && [info exists data(-filetypes)] && $data(-filetypes) ne \"\"} {\n\tupvar #0 $data(-typevariable) typeVariable\n\tset typeVariable [lindex $data(origfiletypes) $data(fileType) 0]\n    }\n\n    if {$data(-multiple) != 0} {\n\tset Priv(selectFilePath) $newFileList\n    } else {\n\tset Priv(selectFilePath) [lindex $newFileList 0]\n    }\n\n    # Set selectFile and selectPath to first item in list\n    set Priv(selectFile)     [file tail    [lindex $newFileList 0]]\n    set Priv(selectPath)     [file dirname [lindex $newFileList 0]]\n}\n\n\nproc ::tk::MotifFDialog_OkCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    MotifFDialog_ActivateSEnt $w\n}\n\nproc ::tk::MotifFDialog_FilterCmd {w} {\n    upvar ::tk::dialog::file::[winfo name $w] data\n\n    MotifFDialog_ActivateFEnt $w\n}\n\nproc ::tk::MotifFDialog_CancelCmd {w} {\n    variable ::tk::Priv\n\n    set Priv(selectFilePath) \"\"\n    set Priv(selectFile)     \"\"\n    set Priv(selectPath)     \"\"\n}\n\nproc ::tk::ListBoxKeyAccel_Set {w} {\n    bind Listbox <Key> \"\"\n    bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]\n    bind $w <Key> [list tk::ListBoxKeyAccel_Key $w %A]\n}\n\nproc ::tk::ListBoxKeyAccel_Unset {w} {\n    variable ::tk::Priv\n\n    catch {after cancel $Priv(lbAccel,$w,afterId)}\n    unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)\n}\n\n# ::tk::ListBoxKeyAccel_Key--\n#\n#\tThis procedure maintains a list of recently entered keystrokes\n#\tover a listbox widget. It arranges an idle event to move the\n#\tselection of the listbox to the entry that begins with the\n#\tkeystrokes.\n#\n# Arguments:\n#\tw\t\tThe pathname of the listbox.\n#\tkey\t\tThe key which the user just pressed.\n#\n# Results:\n#\tNone.\n\nproc ::tk::ListBoxKeyAccel_Key {w key} {\n    variable ::tk::Priv\n\n    if { $key eq \"\" } {\n\treturn\n    }\n    append Priv(lbAccel,$w) $key\n    ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)\n    catch {\n\tafter cancel $Priv(lbAccel,$w,afterId)\n    }\n    set Priv(lbAccel,$w,afterId) [after 500 \\\n\t    [list tk::ListBoxKeyAccel_Reset $w]]\n}\n\nproc ::tk::ListBoxKeyAccel_Goto {w string} {\n    variable ::tk::Priv\n\n    set string [string tolower $string]\n    set end [$w index end]\n    set theIndex -1\n\n    for {set i 0} {$i < $end} {incr i} {\n\tset item [string tolower [$w get $i]]\n\tif {[string compare $string $item] >= 0} {\n\t    set theIndex $i\n\t}\n\tif {[string compare $string $item] <= 0} {\n\t    set theIndex $i\n\t    break\n\t}\n    }\n\n    if {$theIndex >= 0} {\n\t$w selection clear 0 end\n\t$w selection set $theIndex $theIndex\n\t$w activate $theIndex\n\t$w see $theIndex\n\tevent generate $w <<ListboxSelect>>\n    }\n}\n\nproc ::tk::ListBoxKeyAccel_Reset {w} {\n    variable ::tk::Priv\n\n    unset -nocomplain Priv(lbAccel,$w)\n}\n\n"
  },
  {
    "path": "license.terms",
    "content": "This software is copyrighted by the Regents of the University of\nCalifornia, Sun Microsystems, Inc., Scriptics Corporation, ActiveState\nCorporation, Apple Inc. and other parties.  The following terms apply to\nall files associated with the software unless explicitly disclaimed in\nindividual files.\n\nThe authors hereby grant permission to use, copy, modify, distribute,\nand license this software and its documentation for any purpose, provided\nthat existing copyright notices are retained in all copies and that this\nnotice is included verbatim in any distributions. No written agreement,\nlicense, or royalty fee is required for any of the authorized uses.\nModifications to this software may be copyrighted by their authors\nand need not follow the licensing terms described here, provided that\nthe new terms are clearly indicated on the first page of each file where\nthey apply.\n\nIN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY\nFOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\nARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY\nDERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\nTHE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE\nIS PROVIDED ON AN \"AS IS\" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE\nNO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR\nMODIFICATIONS.\n\nGOVERNMENT USE: If you are acquiring this software on behalf of the\nU.S. government, the Government shall have only \"Restricted Rights\"\nin the software and related documentation as defined in the Federal\nAcquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you\nare acquiring the software on behalf of the Department of Defense, the\nsoftware shall be classified as \"Commercial Computer Software\" and the\nGovernment shall have only \"Restricted Rights\" as defined in Clause\n252.227-7013 (b) (3) of DFARs.  Notwithstanding the foregoing, the\nauthors grant the U.S. Government and others acting in its behalf\npermission to use and distribute the software in accordance with the\nterms specified in this license.\n"
  },
  {
    "path": "macosx/Credits.html.in",
    "content": "<!doctype htmL>\n<html>\n<head>\n</head>\n<body style=\"font-size:120%;font-family:Arial,sans-serif;\">\n<p>\nTcl and Tk are distributed under a modified BSD license:<br>\n<a href=\"https://www.tcl-lang.org/software/tcltk/license.html\">\n  https://www.tcl-lang.org/software/tcltk/license.html\n</a>\n</p>\n<ul style=\"list-style-type:none;\">\n<li>&copy; 1987-@TK_YEAR@ Tcl Core Team and Contributers.</li>\n<li>&copy; 2011-@TK_YEAR@ Kevin Walzer.</li>\n<li>&copy; 2014-@TK_YEAR@ Marc Culler.</li>\n<li>&copy; 2002-2012 Daniel A. Steffen.</li>\n<li>&copy; 2001-2009 Apple Inc.</li>\n<li>&copy; 2001-2002 Jim Ingham &amp; Ian Reid.</li>\n<li>&copy; 1998-2000 Jim Ingham &amp; Ray Johnson.</li>\n<li>&copy; 1998-2000 Scriptics Inc.</li>\n<li>&copy; 1996-1997 Sun Microsystems Inc.</li>\n</ul>\n</body>\n</html>\n"
  },
  {
    "path": "macosx/GNUmakefile",
    "content": "########################################################################################################\n#\n# Makefile wrapper to build tk on Mac OS X in a way compatible with the tk/macosx Xcode buildsystem\n#\tuses the standard unix build system in tk/unix (which can be used directly instead of this\n#\tif you are not using the tk/macosx projects).\n#\n# Copyright © 2002-2008 Daniel A. Steffen <das@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution of\n# this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n########################################################################################################\n\n#-------------------------------------------------------------------------------------------------------\n# customizable settings\n\nDESTDIR\t\t\t?=\nINSTALL_ROOT\t\t?= ${DESTDIR}\n\nBUILD_DIR\t\t?= ${CURDIR}/../../build\nSYMROOT\t\t\t?= ${BUILD_DIR}/${PROJECT}\nOBJROOT\t\t\t?= ${SYMROOT}\n\nEXTRA_CONFIGURE_ARGS\t?=\nEXTRA_MAKE_ARGS\t\t?=\n\nINSTALL_PATH\t\t?= /Library/Frameworks\nTCL_INSTALL_PATH\t?= ${INSTALL_PATH}/Tcl.framework\nAPPLICATION_INSTALL_PATH ?= /Applications/Utilities\nPREFIX\t\t\t?= /usr/local\nBINDIR\t\t\t?= ${PREFIX}/bin\nLIBDIR\t\t\t?= ${INSTALL_PATH}\nMANDIR\t\t\t?= ${PREFIX}/man\n\n# tcl build directory (containing tclConfig.sh and Makefile)\nTCL_BUILD_DIR\t\t?= ${BUILD_DIR}/tcl/${BUILD_STYLE}\n# location of installed tcl, only used if tcl in TCL_BUILD_DIR can't be found\nTCL_FRAMEWORK_DIR\t?= /Library/Frameworks\nTCLSH_DIR\t\t?= ${PREFIX}/bin\n\n# set to non-empty value to install manpages in addition to html help:\nINSTALL_MANPAGES\t?=\n\n# set to non-empty value to build TkX11 instead of TkAqua:\nTK_X11\t\t\t?=\n\n# Checks and overrides for subframework builds\nifeq (${SUBFRAMEWORK}_${TK_X11},1_)\noverride BUILD_DIR = ${DESTDIR}/build\noverride INSTALL_PATH = /Frameworks\nendif\n\n#-------------------------------------------------------------------------------------------------------\n# meta targets\n\nmeta\t\t\t:= all install embedded install-embedded clean distclean test\n\nstyles\t\t\t:= develop deploy\n\nall\t\t\t:= ${styles}\nall\t\t\t: ${all}\n\ninstall\t\t\t:= ${styles:%=install-%}\ninstall\t\t\t: ${install}\ninstall-%:\t\taction := install-\n\nembedded\t\t:= ${styles:%=embedded-%}\nembedded\t\t: embedded-deploy\ninstall-embedded\t:= ${embedded:%=install-%}\ninstall-embedded\t: install-embedded-deploy\n\nclean\t\t\t:= ${styles:%=clean-%}\nclean\t\t\t: ${clean}\nclean-%:\t\taction := clean-\ndistclean\t\t:= ${styles:%=distclean-%}\ndistclean\t\t: ${distclean}\ndistclean-%:\t\taction := distclean-\n\ntest\t\t\t:= ${styles:%=test-%}\ntest\t\t\t: ${test}\ntest-%:\t\t\taction := test-\n\ntargets\t\t\t:= $(foreach v,${meta},${$v})\n\n#-------------------------------------------------------------------------------------------------------\n# build styles\n\nBUILD_STYLE\t\t=\nCONFIGURE_ARGS\t\t=\nOBJ_DIR\t\t\t= ${OBJROOT}/${BUILD_STYLE}\n\nempty\t\t\t:=\nspace\t\t\t:= ${empty} ${empty}\nobjdir\t\t\t= $(subst ${space},\\ ,${OBJ_DIR})\n\ndevelop_make_args\t:= BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols\ndeploy_make_args\t:= BUILD_STYLE=Deployment INSTALL_TARGET=install-strip\nembedded_make_args\t:= EMBEDDED_BUILD=1\ninstall_make_args\t:= INSTALL_BUILD=1\n\n${targets}:\n\t${MAKE} ${action}${PROJECT} \\\n\t$(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))\n\n#-------------------------------------------------------------------------------------------------------\n# project specific settings\n\nPROJECT\t\t\t:= tk\nPRODUCT_NAME\t\t:= Tk\n\nUNIX_DIR\t\t:= ${CURDIR}/../unix\nVERSION\t\t\t:= $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.ac)\nTCL_VERSION\t\t:= ${VERSION}\nwish\t\t\t:= wish\nWISH\t\t\t= wish${VERSION}\n\nBUILD_TARGET\t\t:= binaries libraries tktest\nINSTALL_TARGET\t\t:= install\n\nifneq ($(wildcard $(subst ${space},\\ ,${TCL_BUILD_DIR})/tclConfig.sh),)\nTCL_DIR\t\t\t:= ${TCL_BUILD_DIR}\nTCL_FRAMEWORK_DIR\t:= ${TCL_BUILD_DIR}/..\nMAKE_VARS\t\t:=\nelse\nTCL_DIR\t\t\t:= ${TCL_INSTALL_PATH}\nTCL_EXE\t\t\t:= ${TCLSH_DIR}/tclsh${TCL_VERSION}\nMAKE_VARS\t\t:= TCL_EXE\nexport DYLD_FRAMEWORK_PATH := ${TCL_FRAMEWORK_DIR}\nendif\n\nexport CPPROG\t\t:= cp -p\n\nifeq (${TK_X11},)\noverride CONFIGURE_ARGS := ${CONFIGURE_ARGS} --enable-aqua\nelse\noverride CONFIGURE_ARGS := ${CONFIGURE_ARGS} --enable-xft\nVERSION\t\t\t:= ${VERSION}-X11\nwish\t\t\t:= ${wish}-X11\noverride EMBEDDED_BUILD :=\nendif\n\nINSTALL_TARGETS\t\t= install-binaries install-libraries install-headers\nifeq (${EMBEDDED_BUILD},)\nINSTALL_TARGETS\t\t+= install-private-headers install-demos\nendif\nifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment)\nINSTALL_TARGETS\t\t+= html-tk\nifneq (${INSTALL_MANPAGES},)\nINSTALL_TARGETS\t\t+= install-doc\nendif\nendif\n\nMAKE_VARS\t\t+= INSTALL_ROOT INSTALL_TARGETS VERSION\nMAKE_ARGS_V\t\t= $(foreach v,${MAKE_VARS},$v='${$v}')\n\nbuild-${PROJECT}:\ttarget = ${BUILD_TARGET}\ninstall-${PROJECT}:\ttarget = ${INSTALL_TARGET}\nclean-${PROJECT} distclean-${PROJECT} test-${PROJECT}: \\\n\t\t\ttarget = $*\n\nDO_MAKE\t\t\t= +${MAKE} -C \"${OBJ_DIR}\" ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}\n\n#-------------------------------------------------------------------------------------------------------\n# locations for custom tk install actions\n\nifeq (${INSTALL_BUILD},1)\nTOP_DIR\t\t\t:= ${INSTALL_ROOT}/\nAPP_DIR\t\t\t:= ${APPLICATION_INSTALL_PATH}\nFMWK_DIR\t\t:= ${LIBDIR}\nelse\nTOP_DIR\t\t\t:= ${SYMROOT}\nAPP_DIR\t\t\t:= .\nFMWK_DIR\t\t:= .\nendif\n\nTCL_FMWK_DIR\t\t:= ${FMWK_DIR}/Tcl.framework/Versions/${TCL_VERSION}\nTK_FMWK_DIR\t\t:= ${FMWK_DIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}\n\n#-------------------------------------------------------------------------------------------------------\n# build rules\n\n${PROJECT}:\n\t${MAKE} install-${PROJECT} INSTALL_ROOT=\"${OBJ_DIR}/\"\n\n${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \\\n\t\t     ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in\n\tmkdir -p \"${OBJ_DIR}\" && cd \"${OBJ_DIR}\" && \\\n\tif [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \\\n\t--prefix=\"${PREFIX}\" --bindir=\"${BINDIR}\" --libdir=\"${LIBDIR}\" \\\n\t--mandir=\"${MANDIR}\" --enable-framework --disable-zipfs \\\n\t--with-tcl=\"${TCL_DIR}\" \\\n\t${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi\nifneq (${VERSION},${TCL_VERSION})\n\t@cd \"${OBJ_DIR}\" && sed -e 's#/Versions/${TCL_VERSION}#/Versions/${VERSION}#' \\\n\ttkConfig.sh > tkConfig.sh.1 && mv -f tkConfig.sh.1 tkConfig.sh\nendif\n\nbuild-${PROJECT}: ${objdir}/Makefile\n\t${DO_MAKE}\nifeq (${INSTALL_BUILD},)\n# symolic link hackery to trick\n# 'make install INSTALL_ROOT=${OBJ_DIR}'\n# into building Tk.framework and wish in ${SYMROOT}\n\t@cd \"${OBJ_DIR}\" && mkdir -p $(dir $(subst ${space},\\ ,./${LIBDIR})) $(dir $(subst ${space},\\ ,./${BINDIR})) \"${SYMROOT}\" && \\\n\trm -rf \"./${LIBDIR}\" \"./${BINDIR}\" && ln -fs \"${SYMROOT}\" \"./${LIBDIR}\" && \\\n\tln -fs \"${SYMROOT}\" \"./${BINDIR}\" && ln -fs \"${OBJ_DIR}/tktest\" \"${SYMROOT}\"\nifeq (${TK_X11},)\n\t@rm -f \"${OBJ_DIR}/${BINDIR}\" && \\\n\tln -fs Wish.app/Contents/MacOS/Wish \"${SYMROOT}/${WISH}\"\nendif\n# Create symbolic link to Tcl.framework in ${SYMROOT}if necessary\n\t@cd \"${SYMROOT}\" && if [ ! -e Tcl.framework -o -L Tcl.framework ]; then \\\n\trm -f Tcl.framework && ln -s \"${TCL_FRAMEWORK_DIR}/Tcl.framework\" . ; fi\nendif\n\ninstall-${PROJECT}: build-${PROJECT}\nifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_)\n\t@echo \"Cannot install-embedded with empty INSTALL_ROOT !\" && false\nendif\nifeq (${SUBFRAMEWORK}_${DYLIB_INSTALL_DIR},1_)\n\t@echo \"Cannot install subframework with empty DYLIB_INSTALL_DIR !\" && false\nendif\nifeq (${EMBEDDED_BUILD},1)\n\t@rm -rf \"${INSTALL_ROOT}/${LIBDIR}/Tk.framework\"\nendif\nifeq (${SUBFRAMEWORK},1)\n\t@rm -rf \"${INSTALL_ROOT}/Frameworks/Tk.framework\"\nendif\n\t${DO_MAKE}\nifeq (${EMBEDDED_BUILD}_${TK_X11},1_)\n# workaround bug with 'cp -pRH' on Darwin 6 and earlier\n\t@if [ \"`uname -r | awk -F. '{print $$1}'`\" -lt 7 ]; then \\\n\tmkdir -p \"${TOP_DIR}\"/{\"${TCL_FMWK_DIR}\",\"${TK_FMWK_DIR}\"}/PrivateHeaders; fi\nendif\nifeq (${INSTALL_BUILD},1)\nifeq (${EMBEDDED_BUILD},1)\n# if we are embedding frameworks, don't install wish\n\t@rm -f \"${INSTALL_ROOT}${BINDIR}/${WISH}\" && \\\n\trmdir -p \"${INSTALL_ROOT}${BINDIR}\" 2>&- || true\nelse\n# install wish symbolic link\n\t@ln -fs ${WISH} \"${INSTALL_ROOT}${BINDIR}/${wish}\"\nendif # embedded\nendif # install\nifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)\n# keep copy of debug library around, so that\n# Deployment build can be installed on top\n# of Development build without overwriting\n# the debug library\n\t@cd \"${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}\" && \\\n\tln -f \"${PRODUCT_NAME}\" \"${PRODUCT_NAME}_debug\"\nendif # Development, not embedded\nifeq (${TK_X11},)\nifeq (${SUBFRAMEWORK},)\nifeq (${EMBEDDED_BUILD},)\n# install Wish.app link in APPLICATION_INSTALL_PATH and setup 'Wish Shell' compatibility links\n\t@cd \"${TOP_DIR}\" && if [ -n \"${APP_DIR}\" ]; then mkdir -p \"./${APP_DIR}\" && rm -rf \"./${APP_DIR}/Wish.app\" && \\\n\tln -fsh \"./$$(echo \"${APP_DIR}\" | sed -e 's#/[^/][^/]*#/..#g')/${FMWK_DIR}/${PRODUCT_NAME}.framework/Resources/Wish.app\" \"./${APP_DIR}\" && \\\n\tln -fsh Wish.app \"./${APP_DIR}/Wish Shell.app\"; fi && \\\n\tln -fsh Wish.app \"./${TK_FMWK_DIR}/Resources/Wish Shell.app\" && \\\n\tln -fsh Wish \"./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish Shell\"\nelse\n# if we are embedding frameworks, move them into the app and fix their install names\n\t@cd \"${TOP_DIR}\" && \\\n\trm -rf \"./${APP_DIR}/Wish.app\" && mkdir -p \"./${APP_DIR}\" && \\\n\tmv -f \"./${TK_FMWK_DIR}/Resources/Wish.app\" \"./${APP_DIR}\" && \\\n\tln -fsh Wish.app \"./${APP_DIR}/Wish Shell.app\" && \\\n\trm -rf \"./${APP_DIR}/Wish.app/Contents/Frameworks\" && \\\n\tmkdir -p \"./${APP_DIR}/Wish.app/Contents/Frameworks\" && \\\n\t${CPPROG} -RH \"./${FMWK_DIR}\"/T{cl,k}.framework \"./${APP_DIR}/Wish.app/Contents/Frameworks\" && \\\n\tcd \"./${APP_DIR}/Wish.app/Contents\" && \\\n\trm -rf Frameworks/Tcl.framework/{,/Versions/${TCL_VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \\\n\trm -rf Frameworks/Tk.framework/{,/Versions/${VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \\\n\tfix_install_id ( ) { \\\n\t\tchmod -RH a+w \"$$1\"; \\\n\t\tOLD=$$(otool -L \"$$1\" | awk \"/$$2\\\\.framework.*[^:]\\$$/ {print \\$$1}\"); \\\n\t\tNEW=$$(echo \"$$OLD\" | sed \"s|^.*/Frameworks|@executable_path/../Frameworks|\"); \\\n\t\tinstall_name_tool -id \"$$NEW\" \"$$1\"; \\\n\t\tchmod -RH a-w \"$$1\"; \\\n\t} && \\\n\tfix_install_name ( ) { \\\n\t\tchmod -RH a+w \"$$1\"; \\\n\t\tOLD=$$(otool -L \"$$1\" | awk \"/$$2\\\\.framework.*[^:]\\$$/ {print \\$$1}\"); \\\n\t\tNEW=$$(echo \"$$OLD\" | sed \"s|^.*/Frameworks|@executable_path/../Frameworks|\"); \\\n\t\tinstall_name_tool -change \"$$OLD\" \"$$NEW\" \"$$1\"; \\\n\t\tchmod -RH a-w \"$$1\"; \\\n\t} && \\\n\tfix_install_id Frameworks/Tcl.framework/Tcl Tcl && fix_install_id Frameworks/Tk.framework/Tk Tk && \\\n\tfix_install_name MacOS/Wish Tcl && fix_install_name MacOS/Wish Tk\nifeq (${INSTALL_BUILD},1)\n\t@cd \"${TOP_DIR}\" && rm -rf \"./${FMWK_DIR}\"/T{cl,k}.framework && rmdir -p \"./${FMWK_DIR}\" 2>&- || true\nendif # install not subframework\nendif # embedded\nendif # not subframework\nendif # not X11\n\nclean-${PROJECT}: %-${PROJECT}:\n\t${DO_MAKE}\n\trm -rf \"${SYMROOT}\"/{${PRODUCT_NAME}.framework,${WISH},tktest}\n\trm -f \"${OBJ_DIR}\"{\"${LIBDIR}\",\"${BINDIR}\"} && \\\n\trmdir -p \"${OBJ_DIR}\"$(dir $(subst ${space},\\ ,${LIBDIR})) 2>&- || true && \\\n\trmdir -p \"${OBJ_DIR}\"$(dir $(subst ${space},\\ ,${BINDIR})) 2>&- || true\n\ndistclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT}\n\t${DO_MAKE}\n\trm -rf \"${OBJ_DIR}\"\n\ntest-${PROJECT}: %-${PROJECT}: build-${PROJECT}\n\t${DO_MAKE}\n\n#-------------------------------------------------------------------------------------------------------\n\n.PHONY: ${meta} ${targets} ${PROJECT} build-${PROJECT} install-${PROJECT} \\\n\tclean-${PROJECT} distclean-${PROJECT}\n\n.NOTPARALLEL:\n\n#-------------------------------------------------------------------------------------------------------\n"
  },
  {
    "path": "macosx/README",
    "content": "Tcl/Tk macOS README\n----------------------\n\nThis is the README file for the macOS/Darwin version of Tcl/Tk.\n\n1. Where to go for support\n--------------------------\n\n- The tcl-mac mailing list on sourceforge is the best place to ask questions\nspecific to Tcl & Tk on macOS:\n\thttp://lists.sourceforge.net/lists/listinfo/tcl-mac\n(this page also has a link to searchable archives of the list, please check them\nbefore asking on the list, many questions have already been answered).\n\n- For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet:\n\thttp://groups.google.com/group/comp.lang.tcl/\n\n- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see\n\thttps://wiki.tcl-lang.org/page/MacOS\n\n- Please report bugs with Tk on macOS to the tracker:\n\thttps://core.tcl-lang.org/tk/reportlist\n\n2. Using Tcl/Tk on macOS\n---------------------------\n\n- There are two versions of Tk available on macOS: TkAqua using the native\naqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets.\nTkX11 requires an X11 server to be installed, such as XQuartz (available from www.xquartz.org).\nTkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].\n\n- At a minimum, macOS 10.3 is required to run Tcl and TkX11.\nTkAqua requires macOS 10.6 or later.\n\n- Unless weak-linking is used, Tcl/Tk built on macOS 10.x will not run on\n10.y with y < x; on the other hand Tcl/Tk built on 10.y will always run on 10.x\nwith y <= x (but without any of the fixes and optimizations that would be\navailable in a binary built on 10.x).\nWeak-linking is available on OS X 10.2 or later, it additionally allows Tcl/Tk\nbuilt on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2).\n\n- Wish checks the Resources/Scripts directory in its application bundle for a\nfile called AppMain.tcl, if found it is used as the startup script and the\nScripts folder is added to the auto_path. This can be used to emulate the old\nOS9 TclTk droplets.\n\n- If standard input is a special file of zero length (e.g. /dev/null), Wish\nbrings up the Tk console window at startup. This is the case when double\nclicking Wish in the Finder (or using 'open Wish.app' from the Terminal).\n\n- Tcl extensions can be installed in any of:\n\t$HOME/Library/Tcl /Library/Tcl\n\t$HOME/Library/Frameworks /Library/Frameworks\n\t(searched in that order).\nGiven a potential package directory $pkg, Tcl on OSX checks for the file\n$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.\nThis allows building extensions as frameworks with all script files contained in\nthe Resources/Scripts directory of the framework.\n\n- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the\nstandard documentation location in the Tcl/Tk frameworks:\n\tTcl.framework/Resources/Documentation/Reference/Tcl\n\tTk.framework/Resources/Documentation/Reference/Tk\nNo nroff manpages are installed by default by the GNUmakefile.\n\n- The Tcl and Tk frameworks can be installed in any of the system's standard\nframework directories:\n\t$HOME/Library/Frameworks /Library/Frameworks\n\n- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in\n\tTk.framework/Resources\n\n- if 'Wish' is started from the Finder or via 'open', $argv may contain a\n\"-psn_XXXX\" argument. This is the process serial number, you may need to filter\nit out for cross platform compatibility of your scripts.\n\n- the env array is different when Wish is started from the Finder (i.e. via\nLaunchServices) than when it (or tclsh) is invoked from the Terminal, in\nparticular PATH may not be what you expect. (Wish started by LaunchServices\ninherits loginwindow's environment variables, which are essentially those set in\n$HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell).\n\n- TkAqua provides access to native OS X images via the Tk native bitmap facility\n(including any image file readable by NSImage). A native bitmap name is\ninterpreted as follows (in order):\n    - predefined builtin 32x32 icon name (stop, caution, document, etc)\n    - name defined by [tk::mac::iconBitmap]\n    - NSImage named image name\n    - NSImage url string\n    - 4-char OSType of IconServices icon\nthe syntax of [tk::mac::iconBitmap] is as follows:\n\ttk::mac::iconBitmap name width height -kind value\nwhere -kind is one of\n    -file\t    icon of file at given path\n    -fileType\t    icon of given file type\n    -osType\t    icon of given 4-char OSType file type\n    -systemType\t    icon for given IconServices 4-char OSType\n    -namedImage\t    named NSImage for given name\n    -imageFile\t    image at given path\nThis support was added with the Cocoa-based Tk 8.5.7.\n\n- TkAqua cursor names are interpred as follows (in order):\n    - standard or platform-specific Tk cursor name (c.f. cursors.n)\n    - @path to any image file readable by NSImage\n    - NSImage named image name\nSupport for the latter two was added with the Cocoa-based Tk 8.5.7.\n\n- The standard Tk dialog commands [tk_getOpenFile], [tk_chooseDirectory],\n[tk_getSaveFile] and [tk_messageBox] all take an additional optional -command\nparameter on TkAqua. If it is present, the given command prefix is evaluated at\nthe global level when the dialog closes, with the dialog command's result\nappended (the dialog command itself returning an emtpy result). If the -parent\noption is also present, the dialog is configured as a modeless (window-modal)\nsheet attached to the parent window and the dialog command returns immediately.\nSupport for -command was added with the Cocoa-based Tk 8.5.7.\n\n- The TkAqua-specific [tk::mac::standardAboutPanel] command brings the standard\nCocoa about panel to the front, with all its information filled in from your\napplication bundle files (i.e. standard about panel with no options specified).\nSee Apple Technote TN2179 and the AppKit documentation for -[NSApplication\norderFrontStandardAboutPanelWithOptions:] for details on the Info.plist keys and\napp bundle files used by the about panel.\nThis support was added with the Cocoa-based Tk 8.5.7.\n\n- TkAqua has three special menu names that give access to the standard\nApplication, Window and Help menus, see menu.n for details.  By default, the\nplatform-specific standard Help menu item \"YourApp Help\" performs the default\nCocoa action of showing the Help Book configured in the application's\nInfo.plist (or displaying an alert if no Help Book is set). This action can be\ncustomized by defining a procedure named [tk::mac::ShowHelp]. If present, this\nprocedure is invoked instead by the standard Help menu item.  Support for the\nWindow menu and [tk::mac::ShowHelp] was added with the Cocoa-based Tk 8.5.7.\n\n- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to\nget and set macOS-specific toplevel window class and attributes. Note that\nthe window class and many attributes have to be set before the window is first\nmapped for the change to have any effect.\nThe command has the following syntax:\n\ttk::unsupported::MacWindowStyle style window ?class? ?attributes?\nThe 2 argument form returns a list of the current class and attributes for the\ngiven window. The 3 argument form sets the class for the given window using the\ndefault attributes for that class. The 4 argument form sets the class and the\nlist of attributes for the given window.\nWindow class names:\n    document, modal, floating, utility, toolbar, simple, help, overlay\nWindow attribute names:\n    standardDocument, standardFloating, resizable, fullZoom, horizontalZoom,\n    verticalZoom, closeBox, collapseBox, toolbarButton, sideTitlebar,\n    noTitleBar, unifiedTitleAndToolbar, metal, hud, noShadow, doesNotCycle,\n    noActivates, hideOnSuspend, inWindowMenu, ignoreClicks, doesNotHide,\n    canJoinAllSpaces, moveToActiveSpace, nonActivating\n\nNote that not all attributes are valid for all window classes.  Support for the\n3 argument form was added with the Cocoa-based Tk 8.5.7, at the same time\nsupport for some legacy Carbon-specific classes and attributes was removed\n(they are still accepted by the command but no longer have any effect).\n\n- Another command available in the tk::unsupported::MacWindowStyle namespace is:\n  tk::unsupported::MacWindowStyle tabbingid window ?newId?\nwhich can be used to get or set the tabbingIdentifier for the NSWindow\nassociated with a Tk Window.  See section 3 for details.\n\n- The command:\n  tk::unsupported::MacWindowStyle appearance window ?newAppearance?\nis available when Tk is built and run on macOS 10.14 (Mojave) or later.  In\nthat case the Ttk widgets all support the \"Dark Mode\" appearance which was\nintroduced in 10.14. The command accepts the following values for the optional\nnewAppearance option: \"aqua\", \"darkaqua\", or \"auto\".  If the appearance is set\nto aqua or darkaqua then the window will be displayed with the corresponding\nappearance independent of any preferences settings.  If it is set to \"auto\"\nthe appearance will be determined by the preferences.  This command can be\nused to opt out of Dark Mode on a per-window basis.  It may be best to run the \"update\" command before setting the appearance property, to allow the event loop to run.\n\n\n- To determine the current appearance of a window in macOS 10.14 (Mojave) and\nhigher, one can use the command:\n  tk::unsupported::MacWindowStyle isdark\nThe boolean return value is true if the window is currently displayed with the\ndark appearance.\n\n- If you want to use Remote Debugging with Xcode, you need to set the\nenvironment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will\ncause us to force closing stdin & stdout.  Otherwise, given how Xcode launches\nWish remotely, they will be left open and then Wish & gdb will fight for stdin.\n\n- The Aqua port also supports the environment variable TK_NO_STDERR which, if set\nto a non-empty value, causes stderr to be redirected to /dev/null.  This is\nconvenient because Apple sometimes releases a new OS without removing all of\ntheir commands which log debugging information.  Log messages are written to\nstderr, and hence printed in the terminal, when wish or tclsh is started from\nthe terminal, or when running the tests. The messages are not only annoying,\nthey can also cause tests to fail if a debugging message is written to stderr\nwhile a test is running tktest as a subprocess with exec or open.\n\n3. FullScreen, Split View and Tabbed Windows\n--------------------------------------------\n\nSince the release of OSX 10.6 (Snow Leopard) a steadily expanding sequence of\nhigh level window operations have been added to Apple's window manager.  These\noperations are launched by user actions which are handled directly by the\nwindow manager; they are not initiated by the application.  In some, but not\nall cases, the application is notified before and after the operations are\ncarried out.\n\nIn OSX releases up to and including 10.6 there were three buttons with\nstoplight colors located on the left side of a window's title bar.  The\nfunction of the green button was to \"zoom\" or \"maximize\" the window, i.e. to\nexpand the window so that it fills the entire screen, while preserving the\nappearance of the window including its title bar.  The release of OSX 10.7\n(Lion) introduced the \"FullScreen\" window which not only filled the screen but\nalso hid the window's title bar and the menu bar which normally appears at the\ntop of the screen. These hidden objects would only become visible when the\nmouse hovered near the top of the screen.  FullScreen mode was initiated by\npressing a button showing two outward pointing arrows located on the right side\nof the title bar; it was terminated by pressing a similar button with inward\npointing arrows on the right hand side of the menu bar.  In OSX 10.10\n(Yosemite) the FullScreen button was removed. The green button was repurposed\nto cause a window to become a FullScreen window. To zoom a window the user had\nto hold down the option key while pressing the green button.  The release of\nOSX 10.11 added a third function to the green button: to create two half-screen\nwindows with hidden title bars and a hidden menu bar, called Split View\nwindows.  If the green button is held down for one second its window expands to\nfill half of the screen.  It can be moved to one side or the other with the\nmouse.  The opposite side shows thumbnail images of other windows.  Selecting\none of the thumbnails expands its window to fill that half of the screen.  The\ndivider between the two windows can be moved to adjust the percentage of the\nscreen occupied by each of the two tiles.  In OSX 10.12 (Sierra) Tabbed windows\nwere introduced.  These allow an application with multiple windows to display\nits windows as tabs within a single window frame.  Clicking on a tab brings its\nwindow into view.  Tabs can be rearranged by dragging.  Dragging a tab to the\ndesktop turns it into a separate window.  Items in the Window menu can be used\nto cycle through the tabs, move tabbed windows to separate windows, or merge a\nset of separate windows as tabs in the same window frame.\n\nTk now fully supports all of these high level window operations on any system\nwhere the operation exists.  The FullScreen and Split View windows are handled\nautomatically with no action required on the part of the programmer.  Tabbed\nwindows, on the other hand, require some attention from the programmer.\nBecause many of the operations with tabs are handled through the application's\nWindow menu, it is essential that an application provide a Windows menu to\navoid presenting a confusing interface to the user. This cannot be ignored, in\npart because the systemwide Dock Preferences offers an option to always attempt\nto open application windows as tabs. An application which does not provide a\nWindow menu will necessarily present a confusing interface to any user who has\nselected this option.\n\nA further complication is that it is not neccessarily appropriate for all of an\napplication's windows to be grouped together as tabs in the same frame.  In\nfact, the Apple guidelines insist that windows which are grouped together as\ntabs should be similar to each other.  The mechanism provided for arranging\nthis was to assign to each NSwindow a tabbingIdentifier, and to require that\nall windows grouped together as tabs in the same window frame must have the\nsame tabbingIdentifier.  A tabbingIdentifier is implemented as an arbitrary\nstring, and a system-generated default tabbingIdentifier is provided to all new\nwindows.\n\nTk provides a means for getting and setting the tabbingIdentifier of\nthe NSWindow underlying a Tk Window. This is handled by the command\n\ntk::unsupported::MacWindowStyle tabbingid window ?newId?\n\n(This command generates an error if used on OSX 10.11 or earlier, since the\ntabbingIdentifier does not exist on those systems.)  The command returns the\ntabbingIdentifier which had been assigned to the window prior to execution of\nthe command.  If the optional newId argument is omitted, the window's\ntabbingIdentifier is not changed.  Otherwise it is set to the string specified\nby the argument.\n\nSince NSWindows can only be grouped together as tabs if they all have the same\ntabbingIdentifier, one can prevent a window from becoming a tab by giving it a\nunique tabbingIdentifier. This is independent of any preferences setting. To\nensure that we maintain consistency, changing the tabbingIdentifier of a window\nwhich is already displayed as a tab will also cause it to become a separate\nwindow.\n\n4. Ttk, Dark Mode and semantic colors\n---------------------------------------\n\nWith the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua\nappearance.  Part of the implementation of the Dark Mode was to make\nsome of the named NSColors have dynamic values.  Apple calls these\n\"semantic colors\" because the name does not specify a specific color,\nbut rather refers to the context in which the color should be used.\nIn particular, when a user selects Dark Mode in the system preferences\nthese colors change appearance.  For example systemTextColor is dark in\nAqua and light in DarkAqua.\n\nTk now provides colors corresponding to all of the NSColors in Apple's System\nColorList.  The convention for naming these colors is that the Tk name is\ngenerated by capitalizing the macOS name and adding the prefix \"system\". The\nSystem ColorList differs between releases of macOS and some colors, such as\nsystemLinkColor and systemControlAccentColor, are simulated on older systems\nwhich did not provide them.  The following colors are available on all\nsupported macOS releases, although newer systems will support additional\ncolors: systemControlAccentColor, systemControlTextColor,\nsystemDisabledControlTextColor, systemLabelColor, systemLinkColor,\nsystemPlaceholderTextColor, systemSelectedTextBackgroundColor,\nsystemSelectedTextColor, systemSeparatorColor, systemTextBackgroundColor, and\nsystemTextColor.  One additional color, systemSelectedTabTextColor, does not\nexist in macOS but is used by Tk to match the different colors used for\nNotebook tab titles in different OS versions.\n\nThe default background and foreground colors of most of the Tk widgets\nhave been set to semantic colors, which means that the widgets will change\nappearance, and remain usable, when Dark Mode is selected in the system\npreferences.  However, to get a close match to the native Dark Mode style it\nis recommended to use Ttk widgets when possible.\n\nApple's tab view and GroupBox objects delimit their content by\ndisplaying it within a rounded rectangle with a background color that\ncontrasts with the background of the containing object.  This means\nthat the background color of a Ttk widget depends on how deeply it is\nnested inside of other widgets that use contrasting backgrounds.  To\nsupport this, there are 8 contrasting system colors named\nsystemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7.\nThe systemWindowBackgroundColor is the standard background for a\ndialog window and the others match the contrasting background colors\nused in ttk::notebooks and ttk::labelframes which are nested to the\ncorresponding depth.\n\n5. Building Tcl/Tk on macOS\n------------------------------\n\n- macOS 10.6 is required to build TkAqua and TkX11.  The XCode application provides everything needed to build Tk, but it is not necessary to install the full XCode.\nIt suffices to install the Command Line Tools package, which can be done\nby running the command:\nxcode-select --install\n\n- Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in\ntcl/macosx and tk/macosx (see below for details), but can also be built with the\nstandard unix configure and make buildsystem in tcl/unix resp. tk/unix as on any\nother unix platform (indeed, the GNUmakefiles are just wrappers around the unix\nbuildsystem).\nThe macOS specific configure flags are --enable-aqua, --enable-framework and\n--disable-corefoundation (which disables CF and notably reverts to the standard\nselect based notifier). Note that --enable-aqua is incompatible with\n--disable-corefoundation (for both Tcl and Tk configure).\n\n- It was once possible to build with the Xcode IDE via the project in\ntk/macosx, but this has not been tested recently. Take care to use the\nproject matching your DevTools and OS version:\n\tTk.xcodeproj:\t\t    for Xcode 3.2 on 10.6\nThese have the following targets:\n\tTk:\t\t\t    calls through to tk/macosx/GNUMakefile,\n\t\t\t\t    requires a corresponding build of the Tcl\n\t\t\t\t    target of tcl/macosx/Tcl.xcode.\n\ttktest:\t\t\t    static build of TkAqua tktest for debugging.\n\ttktest-X11:\t\t    static build of TkX11 tktest for debugging.\nThe following build configurations are available:\n\tDebug:\t\t\t    debug build for the active architecture,\n\t\t\t\t    with Fix & Continue enabled.\n\tDebug clang:\t\t    use clang compiler.\n\tDebug llvm-gcc:\t\t    use llvm-gcc compiler.\n\tDebug gcc40:\t\t    use gcc 4.0 compiler.\n\tDebugNoGC:\t\t    disable Objective-C garbage collection.\n\tDebugNoFixAndContinue:      disable Fix & Continue.\n\tDebugNoCF:\t\t    disable corefoundation (X11 only).\n\tDebugMemCompile:\t    enable memory and bytecode debugging.\n\tDebugLeaks:\t\t    define PURIFY.\n\tDebugGCov:\t\t    enable generation of gcov data files.\n\tRelease:\t\t    release build for the active architecture.\n\tReleaseUniversal:\t    32/64-bit universal build.\n\tReleaseUniversal clang:\t    use clang compiler.\n\tReleaseUniversal llvm-gcc:  use llvm-gcc compiler.\n\tReleaseUniversal gcc40:\t    use gcc 4.0 compiler.\n\tReleaseUniversal10.5SDK:    build against the 10.5 SDK (with 10.5\n\t\t\t\t    deployment target).\n\tNote that the non-SDK configurations have their deployment target set to\n\t10.6 (Tk.xcodeproj).\nThe Xcode projects refer to the toplevel tcl and tk source directories via the\nthe TCL_SRCROOT and TK_SRCROOT user build settings, by default these are set to\nthe project-relative paths '../../tcl' and '../../tk', if your source\ndirectories are named differently, e.g. '../../tcl9.1' and '../../tk9.1', you\nneed to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your\n${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a\ntext editor.\n\nDetailed Instructions for building with macosx/GNUmakefile\n----------------------------------------------------------\n\n- Unpack the Tcl and Tk source release archives and place the tcl and tk source\ntrees in a common parent directory.\n[ If you don't want have the two source trees in one directory, you'll need to ]\n[ create the following symbolic link for the build to work as setup by default ]\n[      ln -fs /path_to_tcl/build /path_to_tk/build\t\t\t       ]\n[ (where /path_to_{tcl,tk} is the directory containing the tcl resp. tk tree)  ]\n[ or you can pass an argument of BUILD_DIR=/somewhere to the tcl and tk make.  ]\n\n- The following instructions assume the Tcl and Tk source trees are named\n\"tcl${ver}\" and \"tk${ver}\" (where ${ver} is a shell variable containing the\nTcl/Tk version number, e.g. '9.0').\nSetup this shell variable as follows:\n\tver=\"9.0\"\n\n- Setup environment variables as desired, e.g. for a universal build on 10.9:\n\tCFLAGS=\"-arch x86_64 -arch arm64 -mmacosx-version-min=10.9\"\n\texport CFLAGS\n\n- Change to the directory containing the Tcl and Tk source trees and build:\n\tmake -C tcl${ver}/macosx\n\tmake -C tk${ver}/macosx\n\n- Install Tcl and Tk onto the root volume (admin password required):\n\tsudo make -C tcl${ver}/macosx install\n\tsudo make -C tk${ver}/macosx  install\nif you don't have an admin password, you can install into your home directory\ninstead by passing an INSTALL_ROOT argument to make:\n\tmake -C tcl${ver}/macosx install INSTALL_ROOT=\"${HOME}/\"\n\tmake -C tk${ver}/macosx  install INSTALL_ROOT=\"${HOME}/\"\n\n- The default GNUmakefile targets will build _both_ debug and optimized versions\nof the Tcl and Tk frameworks with the standard convention of naming the debug\nlibrary Tcl.framework/Tcl_debug resp. Tk.framework/Tk_debug.\nThis allows switching to the debug libraries at runtime by setting\n\texport DYLD_IMAGE_SUFFIX=_debug\n(c.f. man dyld for more details)\n\nIf you only want to build and install the debug or optimized build, use the\n'develop' or 'deploy' target variants of the GNUmakefile, respectively.\nFor example, to build and install only the optimized versions:\n\tmake -C tcl${ver}/macosx deploy\n\tmake -C tk${ver}/macosx deploy\n\tsudo make -C tcl${ver}/macosx install-deploy\n\tsudo make -C tk${ver}/macosx  install-deploy\n\n- The GNUmakefile can also build a version of Wish.app that has the Tcl and Tk\nframeworks embedded in its application package. This allows for standalone\ndeployment of the application with no installation required, e.g. from read-only\nmedia. To build & install in this manner, use the 'embedded' variants of\nthe GNUmakefile targets.\nFor example, to build a standalone 'Wish.app' in ./emb/Applications/Utilities:\n\tmake -C tcl${ver}/macosx embedded\n\tmake -C tk${ver}/macosx embedded\n\tsudo make -C tcl${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/emb/\n\tsudo make -C tk${ver}/macosx  install-embedded INSTALL_ROOT=`pwd`/emb/\nNotes:\n  * if you've already built standard TclTkAqua, building embedded does not\n  require any new compiling or linking, so you can skip the first two makes.\n  (making relinking unnecessary was added with 8.4.2)\n  * the embedded frameworks include only optimized builds and no documentation.\n  * the standalone Wish has the directory Wish.app/Contents/lib in its\n  auto_path. Thus you can place tcl extensions in this directory (i.e. embed\n  them in the app package) and load them with [package require].\n\n- It is possible to build Tk against an installed Tcl.framework; but you will\nstill need a tcl sourcetree in the location specified in TCL_SRC_DIR in\nTcl.framework/tclConfig.sh. Also, linking with Tcl.framework has to work exactly\nas indicated in TCL_LIB_SPEC in Tcl.framework/tclConfig.sh.\nIf you used non-default install locations for Tcl.framework, specify them as\nmake overrides to the tk/macosx GNUmakefile, e.g.\n\tmake -C tk${ver}/macosx \\\n\t    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin\n\tsudo make -C tk${ver}/macosx install \\\n\t    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin\nThe Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.\n\n- To build a Tcl.framework and Tk.framework for use as subframeworks in another\nframework, use the install-embedded target and set SUBFRAMEWORK=1.  Set the\nDYLIB_INSTALL_DIR variable to the path which should be the install_name path of\nthe shared library and set the DESTDIR variable to the pathname of a staging\ndirectory where the frameworks will be written.  The Tcl framework must be\nbuilt first.\nFor example, running the commands:\n\tmake -C ../tcl9.0/macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \\\n\tDYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tcl.framework\n\tmake -C macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \\\n\tDYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tk.framework\nwill produce a Tcl.framework and a Tk.framework usable as subframeworks of\nSome.framework.  The frameworks will be found in /tmp/tcltk/Frameworks/\n\n5. Details regarding the macOS port of Tk.\n-------------------------------------------\n\n5.1 About the event loop\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe main program in a typical OSX application looks like this (see\nhttps://developer.apple.com/library/mac/documentation/Cocoa/\\\nReference/ApplicationKit/Classes/NSApplication_Class)\n\n    void NSApplicationMain(int argc, char *argv[]) {\n\t[NSApplication sharedApplication];\n\t[NSBundle loadNibNamed:@\"myMain\" owner:NSApp];\n\t[NSApp run];\n    }\nHere NSApp is a standard global variable, initialized by the OS, which\npoints to an object in a subclass of NSApplication (called\nTKApplication in the case of the macOS port of Tk).\n\nThe [NSApp run] method implements the event loop for a typical Mac\napplication.  There are three key steps in the run method.  First it\ncalls [NSApp finishLaunching], which creates the bouncing application\nicon and does other mysterious things. Second it creates an\nNSAutoreleasePool.  Third, it starts an event loop which drains the\nNSAutoreleasePool every time the queue is empty, and replaces the\ndrained pool with a new one.  This third step is essential to\npreventing memory leaks, since the internal methods of Appkit objects\nall assume that an autorelease pool is in scope and will be drained\nwhen the event processing cycle ends.\n\nThe macOS Tk application does not call the [NSApp run] method at\nall.  Instead it uses the event loop built in to Tk.  So the\napplication must take care to replicate the important features of the\nmethod ourselves.  The way that autorelease pools are handled is\ndiscussed in 5.2 below.  Here we discuss the event handling itself.\n\nThe Tcl event loop simply consists of repeated calls to TclDoOneEvent.\nEach call to TclDoOneEvent begins by collecting all pending events from\nan \"event source\", converting them to Tcl events and adding them\nto the Tcl event queue. For macOS, the event source is the NSApp\nobject, which maintains an event queue even though its run method\nwill never be called to process them.  The NSApp provides methods for\ninspecting the queue and removing events from it as well as the\n[NSApp sendevent] which sends an event to all of the application's\nNSWindows which can then send it to subwindows, etc.\n\nThe event collection process consists of first calling a platform\nspecific SetupProc and then a platform specific CheckProc.  In\nthe macOS port, these are named TkMacOSXEventsSetupProc and\nTkMacOSXEventsCheckProc.\n\n5.2 Autorelease pools\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIn order to carry out the job of managing autorelease pools, which\nwould normally be handled by the [NSApp run] method, a private\nNSAutoreleasePool* property is added to the TkApplication subclass of\nNSApplication. The TkpInit function calls [NSApp _setup] which\ninitializes this property by creating an NSAutoreleasePool prior to\ncalling [NSApp finishLaunching].  This mimics the behavior of the\n[NSApp run] method, which calls [NSApp finishLaunching] just before\nstarting the event loop.\n\nSince the CheckProc function gets called for every Tk event, it is an\nappropriate place to drain the main NSAutoreleasePool and replace it\nwith a new pool.  This is done by calling the method [NSApp\n_resetAutoreleasePool], where _resetAutoreleasePool is a method which\nwe define for the subclass.  Unfortunately, by itself this is not\nsufficient for safe memory management because, as was made painfully\nevident with the release of OS X 10.13, it is possible for calls to\nTclDoOneEvent, and hence to CheckProc, to be nested.  Draining the\nautorelease pool in a nested call leads to crashes as objects in use\nby the outer call can get freed by the inner call and then reused later.\nOne particular situation where this happens is when a modal dialogue\ngets posted by a Tk Application.  To address this, the NSApp object\nalso implements a semaphore to prevent draining the autorelease pool\nin nested calls to CheckProc.\n\nOne additional minor caveat for developers is that there are several\nsteps of the Tk initialization which precede the call to TkpInit.\nNotably, the font package is initialized first.  Since there is no\nNSAutoreleasePool in scope prior to calling TkpInit, the functions\ncalled in these preliminary stages need to create and drain their own\nNSAutoreleasePools whenever they call methods of Appkit objects\n(e.g. NSFont).\n\n5.3 Clipping regions and \"ghost windows\"\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAnother unusual aspect of the macOS port is its use of clipping\nregions.  It was part of Daniel Steffen's original design that the\nTkWindowPrivate struct maintains three HIShapeRef regions, named\nvisRgn, aboveVisRgn and drawRgn.  These regions are used as clipping\nmasks whenever drawing into an NSView.  The visRgn is the bounding box\nof the window with a rectangle removed for each subwindow and for each\nsibling window at a higher stacking level.  The drawRgn is the\nintersection of the visRgn with the clipping rectangle of the\nwindow. (Normally, the clipping rectangle is the same as the bounding\nrectangle, but drawing can be clipped to a smaller rectangle by\ncalling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of\nthe window's bounding rectangle with the bounding rectangle of the\nparent window.  Much of the code in tkMacOSXSubwindows.c is devoted to\nrebuilding these clipping regions whenever something changes in the\nlayout of the windows.  This turns out to be a tricky thing to do and\nit is extremely prone to errors which can be difficult to trace.\n\nIt is not entirely clear what the original reason for using these\nclipping regions was.  But one benefit is that if they are correctly\nmaintained then it allows windows to be drawn in any order.  You do\nnot have to draw them in the order of the window hierarchy.  Each\nwindow can draw its entire rectangle through its own mask and never\nhave to worry about drawing in the wrong place.  It is likely that\nthe need for using clipping regions arose because, as Apple explicitly\nstates in the documentation for [NSView subviews],\n\n    \"The order of the subviews may be considered as being\n    back-to-front, but this does not imply invalidation and drawing\n    behavior.\"\n\nIn the early versions of the macOS port, buttons were implemented as\nsubviews of class TkButton.  This probably exacerbated the likelihood\nthat Tk windows would need to be drawn in arbitrary order.\n\nThe most obvious side effect caused by not maintaining the clipping\nregions is the appearance of so-called \"ghost windows\".  A common\nsituation where these may arise is when a window containing buttons\nis being scrolled.  A user may see two images of the same button on\nthe screen, one in the pre-scroll location and one in the post-scroll\nlocation.\n\nTo see how these 'ghost windows' can arise, think about what happens if\nthe clipping regions are not maintained correctly.  A window might\nhave a rectangle missing from its clipping region because that\nrectangle is the bounding rectangle for a subwindow, say a button.\nThe parent should not draw in the missing rectangle since doing so\nwould trash the button.  The button is responsible for drawing\nthere. Now imagine that the button gets moved, say by a scroll, but\nthe missing rectangle in the parent's clipping region does not get\nmoved correctly, or it gets moved later on, after the parent has\nredrawn itself.  The parent would still not be allowed to draw in the\nold rectangle, so the user would continue to see the image of the\nbutton in its old location, as well as another image in the new\nlocation.  This is a prototypical example of a \"ghost window\".\nAnytime you see a \"ghost window\", you should suspect problems with the\nupdates to the clipping region visRgn.  It is natural to look for\ntiming issues, race conditions, or other \"event loop problems\".  But\nin fact, the whole design of the code is to make those timing issues\nirrelevant.  As long as the clipping regions are correctly maintained\nthe timing does not matter.  And if they are not correctly maintained\nthen you will see \"ghost windows\".\n\nIt is worth including a detailed description of one specific place\nwhere the failure to correctly maintain clipping regions caused \"ghost\nwindow\" artifacts that plagued the macOS port for years.  These\noccurred when scrolling a Text widget which contained embedded\nsubwindows.  It involved some specific differences between the\nlow-level behavior of Apple's window manager versus those of the other\nplatforms, and the fix ultimately required changes in the generic Tk\nimplementation (documented in the comments in the DisplayText\nfunction).\n\nThe Text widget attempts to improve performance when scrolling by\nminimizing the number of text lines which need to be redisplayed.  It\ndoes this by calling the platform-specific TkScrollWindow function\nwhich uses a low-level routine to map one rectangle of the window to\nanother.  The TkScrollWindow function returns a damage region which is\nthen used by the Text widget's DisplayText function to determine which\ntext lines need to be redrawn.  On the unix and win platforms, this\ndamage region includes bounding rectangles for all embedded windows\ninside the Text widget.  The way that this works is system dependent.\nOn unix, the low level scrolling is done by XCopyArea, which\ngenerates a GraphicsExpose event for each embedded window.  These\nGraphicsExposed events are processsed within TkScrollWindow, using a\nspecial handler which adds the bounding rectangle of each subwindow to\nthe damage region.  On the win platform the damage region is built by\nthe low level function ScrollWindowEx, and it also includes bounding\nrectangles for all embedded windows.  This is possible because on X11\nand Windows every Tk widget is also known to the window manager as a\nwindow.  The situation is different on macOS.  The underlying object\nfor a top level window on macOS is the NSView.  However, Apple\nexplicitly warns in its documentation that performance degradation\noccurs when an NSView has more than about 100 subviews.  A Text widget\nwith thousands of lines of text could easily contain more than 100\nembedded windows.  In fact, while the original Cocoa port of Tk did\nuse the NSButton object, which is derived from NSView, as the basis\nfor its Tk Buttons, that was changed in order to improve performance.\nMoreover, the low level routine used for scrolling on macOS, namely\n[NSView scrollrect:by], does not provide any damage information.  So\nTkScrollWindow needs to work differently on macOS.  Since it would be\ninefficient to iterate through all embedded windows in a Text widget,\nlooking for those which meet the scrolling area, the damage region\nconstructed by TkScrollWindow contains only the difference between the\nsource and destination rectangles for the scrolling.  The embedded\nwindows are redrawn within the DisplayText function by some\nconditional code which is only used for macOS.\n\n6.0 Virtual events on macOS 10.14 and later\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe 10.14 release added support for system appearance changes,\nincluding a \"Dark Mode\" that renders all window frames and menus in\ndark colors. Tk 9.0 provides three virtual events <<LightAqua>>,\n<<DarkAqua>> and <<AppearanceChanged>>, to allow you to update your Tk\napp's appearance when the system appearance changes.  These events are\ngenerated in [NSView effectiveAppearanceChanged], which is called by\nthe Apple window manager when the General Preferences is changed\neither by switching between Light Mode and Dark Mode or by changing\nthe Accent Color or Highlight Color.\n\nThe <<AppearanceChanged>> virtual event has a data string which can be\naccessed with the %d substitution.  The format of the data string is\nthat it consists of 6 words:\n  \"Appearance XXXX Accent YYYY Highlight ZZZZ\"\nFor example, the following code will print the current appearance\nname, accent color and highlight color when the <<AppearanceChanged>>\nvirtual event fires:\n\nbind . <<AppearanceChanged>> {\n    array set data [split %d]\n    puts \"  Appearance: $data(Appearance)\"\n    puts \"  Accent: $data(Accent)\"\n    puts \"  Highlight: $data(Highlight)\\n\"\n}\n\n\n\n7.0 Mac Services\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWith 8.6.10, Tk supports the Mac's NSServices API, documented at\nhttps://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1\nand in TIP 536 and Tk's man page. Tk presents a simple,\nstraightforward API to implement the Services functionality.\n\nThe Tk implementation of the NSServices API is intended for standalone\napplications, such as one wrapped by the standalone version of Wish\nand re-named into a different application.  In particular such an\napplication would specify its own unique CFBundleIdentifier in its\nInfo.plist file.  During development, however, if Wish itself is being\nused as the receiver, it may be necessary to take some care to ensure\nthat the correct version of Wish.app is available as a receiver of\nNSServices data.\n\nWhen one macOS app uses NSServices to send data to another app that is\nnot running, LaunchServices will launch the receiver.  LaunchServices\nassumes that the CFBundleIdentifier uniquely identifies an app among\nall of the apps installed on a system.  But this may not be the case\nfor Wish.app if, for example, you have compiled Tk from source at some\ntime in the past.  In that case the Tk build directory will contain\nits own copy of Wish.app that will be visible to LaunchServices.  It\nmay be necessary when testing your app to take some steps to ensure\nthat LaunchServices is launching the correct Wish.app.  Instructions\nfor doing this are provided below.\n\nThe command line tool which manages the LaunchServices database has\nan amazingly unwieldy path name.  So, first, run this command:\n\nalias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'\n\nThen you can reset the LaunchServices database like this:\n\n$ lsregister -kill\n$ lsregister -seed\n\nTo find out which versions of Wish.app have been located by\nLaunchServices, run:\n\n$ lsregister -dump | grep path | grep Wish\n\nIf more than one version of Wish is showing up in this list, eliminate\nall of the unintended targets by running\n\nlsregister -u /path/to/bad/Wish.app\n\nContinue this until only the correct version of Wish shows up in the\nlist.\n"
  },
  {
    "path": "macosx/Tk-Info.plist.in",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<!--\n\tCopyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n\tCopyright © 2008-2009 Apple Inc.\n\n\tSee the file \"license.terms\" for information on usage and redistribution of\n\tthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n-->\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>@TK_LIB_FILE@</string>\n\t<key>CFBundleGetInfoString</key>\n\t<string>Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@@TK_PATCH_LEVEL@,\nCopyright © 1989-@TK_YEAR@ Tcl Core Team,\nCopyright © 2002-@TK_YEAR@ Daniel A. Steffen,\n\tCopyright © 1989-@TK_YEAR@ Contributors,\n\tCopyright © 2011-@TK_YEAR@ Kevin Walzer,\n\tCopyright © 2014-@TK_YEAR@ Marc Culler,\nCopyright © 2001-2009 Apple Inc.,\nCopyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.tcltk.tklibrary</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>\n\t<key>CFBundleSignature</key>\n\t<string>Tk  </string>\n\t<key>CFBundleVersion</key>\n\t<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "macosx/Wish-Info.plist.in",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<!--\n\tCopyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n\tCopyright © 2008-2009 Apple Inc.\n\n\tSee the file \"license.terms\" for information on usage and redistribution of\n\tthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n-->\n<plist version=\"1.0\">\n  <dict>\n    <key>CFBundleDevelopmentRegion</key>\n    <string>English</string>\n    <key>CFBundleDocumentTypes</key>\n    <array>\n      <dict>\n\t<key>CFBundleTypeExtensions</key>\n\t<array>\n\t  <string>tcl</string>\n\t  <string>TCL</string>\n\t  <string>*</string>\n\t</array>\n\t<key>CFBundleTypeMIMETypes</key>\n\t<array>\n\t  <string>application/x-tcl</string>\n\t  <string>text/plain</string>\n\t</array>\n\t<key>CFBundleTypeName</key>\n\t<string>NSStringPboardType</string>\n\t<key>CFBundleTypeOSTypes</key>\n\t<array>\n\t  <string>TEXT</string>\n\t  <string>****</string>\n\t</array>\n\t<key>CFBundleTypeRole</key>\n\t<string>Viewer</string>\n      </dict>\n    </array>\n    <key>CFBundleURLTypes</key>\n    <array>\n      <dict>\n\t<key>CFBundleTypeRole</key>\n\t<string>Viewer</string>\n\t<key>CFBundleURLSchemes</key>\n\t<array>\n\t  <string>foo</string>\n\t</array>\n\t<key>CFBundleURLName</key>\n\t<string>Get Foo</string>\n      </dict>\n    </array>\n    <key>CFBundleExecutable</key>\n    <string>Wish</string>\n    <key>CFBundleGetInfoString</key>\n    <string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,\n    Copyright © 1989-@TK_YEAR@ Tcl Core Team,\n    Copyright © 1989-@TK_YEAR@ Contributors,\n    Copyright © 2011-@TK_YEAR@ Kevin Walzer,\n    Copyright © 2014-@TK_YEAR@ Marc Culler,\n    Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,\n    Copyright © 2001-2009 Apple Inc.,\n    Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>\n    <key>CFBundleIconFile</key>\n    <string>Wish.icns</string>\n    <key>CFBundleIdentifier</key>\n    <string>com.tcltk.wish</string>\n    <key>CFBundleInfoDictionaryVersion</key>\n    <string>6.0</string>\n    <key>CFBundleLocalizations</key>\n    <array>\n      @CFBUNDLELOCALIZATIONS@\n    </array>\n    <key>CFBundleName</key>\n    <string>Wish</string>\n    <key>CFBundlePackageType</key>\n    <string>APPL</string>\n    <key>CFBundleShortVersionString</key>\n    <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>\n    <key>CFBundleSignature</key>\n    <string>WiSH</string>\n    <key>CFBundleVersion</key>\n    <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>\n    <key>LSMinimumSystemVersion</key>\n    <string>10.6.0</string>\n    <key>LSRequiresCarbon</key>\n    <true/>\n    <key>NSAppleScriptEnabled</key>\n    <true/>\n    <key>OSAScriptingDefinition</key>\n    <string>Wish.sdef</string>\n    <key>NSHighResolutionCapable</key>\n    <true/>\n    <key>NSServices</key>\n    <array>\n      <dict>\n\t<key>NSMessage</key>\n\t<string>provideService</string>\n\t<key>NSPortName</key>\n\t<string>Wish</string>\n\t<key>NSSendTypes</key>\n\t<array>\n\t  <string>NSStringPboardType</string>\n\t  <string>NSPasteboardTypeString</string>\n\t</array>\n      </dict>\n    </array>\n  </dict>\n</plist>\n"
  },
  {
    "path": "macosx/Wish.sdef",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE dictionary SYSTEM \"file://localhost/System/Library/DTDs/sdef.dtd\">\n<!--\n\tCopyright © 1997 Sun Microsystems, Inc.\n\tCopyright © 2009 Kevin Walzer\n\tCopyright © 2009 Daniel A. Steffen <das@users.sourceforge.net>\n\n\tSee the file \"license.terms\" for information on usage and redistribution of\n\tthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n-->\n<dictionary title=\"Wish Terminology\">\n\t<suite name=\"Standard Suite\" code=\"reqd\" description=\"Common commands for all applications.\">\n\t\t<command name=\"open\" code=\"aevtodoc\" description=\"Open a document.\">\n\t\t\t<direct-parameter description=\"The file(s) to be opened.\">\n\t\t\t\t<type type=\"file\"/>\n\t\t\t\t<type type=\"file\" list=\"yes\"/>\n\t\t\t</direct-parameter>\n\t\t</command>\n\t\t<command name=\"print\" code=\"aevtpdoc\" description=\"Print a document.\">\n\t\t\t<direct-parameter description=\"The file(s) to be printed.\">\n\t\t\t\t<type type=\"file\" list=\"yes\"/>\n\t\t\t\t<type type=\"specifier\"/>\n\t\t\t</direct-parameter>\n\t\t</command>\n\t\t<command name=\"quit\" code=\"aevtquit\" description=\"Quit the application.\"/>\n\t</suite>\n\t<suite name=\"Wish Suite\" code=\"WIsH\" description=\"Commands for the Wish application.\">\n\t\t<command name=\"do script\" code=\"miscdosc\" description=\"Execute a Tcl script.\">\n\t\t\t<direct-parameter description=\"Script to execute\" type=\"text\">\n\t\t\t\t<type type=\"text\"/>\n\t\t\t</direct-parameter>\n\t\t\t<result description=\"Result\">\n\t\t\t\t<type type=\"text\"/>\n\t\t\t</result>\n\t\t</command>\n\t\t\t<command name=\"open location\" code=\"GURLGURL\"\n\t\t\t\t description=\"Open a URL.\">\n\t\t\t<direct-parameter description=\"URL\" type=\"text\">\n\t\t\t\t<type type=\"text\"/>\n\t\t\t</direct-parameter>\n\t\t\t<result description=\"Result\">\n\t\t\t\t<type type=\"text\"/>\n\t\t\t</result>\n\t\t</command>\n\t</suite>\n</dictionary>\n"
  },
  {
    "path": "macosx/configure.ac",
    "content": "#! /bin/bash -norc\ndnl\tThis file is an input file used by the GNU \"autoconf\" program to\ndnl\tgenerate the file \"configure\", which is run during Tk installation\ndnl\tto configure the system for the local environment.\n\ndnl\tEnsure that the config (auto)headers support is used, then just\ndnl\tinclude the configure sources from ../unix:\n\nm4_include(../unix/aclocal.m4)\nm4_define(SC_USE_CONFIG_HEADERS)\nm4_include(../unix/configure.ac)\n"
  },
  {
    "path": "macosx/tkMacOSX.h",
    "content": "/*\n * tkMacOSX.h --\n *\n *\tDeclarations of Macintosh specific exported variables and procedures.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMAC\n#define _TKMAC\n\n#ifndef _TK\n#include \"tk.h\"\n#endif\n\n/*\n * Structures and function types for handling Netscape-type in process\n * embedding where Tk does not control the top-level\n */\n\ntypedef int (Tk_MacOSXEmbedRegisterWinProc) (long winID, Tk_Window window);\ntypedef void* (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window);\ntypedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window);\ntypedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, void *rgn);\ntypedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, void *ulCorner);\n\n#include \"tkPlatDecls.h\"  /* IWYU pragma: export */\n\n#endif /* _TKMAC */\n"
  },
  {
    "path": "macosx/tkMacOSXAccessibility.c",
    "content": "/*\n * tkMacOSXAccessibility.c --\n *\n *  This file implements the platform-native NSAccessibility API\n *  for Tk on macOS.\n *\n * Copyright © 2023 Apple Inc.\n * Copyright © 2024-2025 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n */\n\n\n#include <unistd.h>\n#include <CoreFoundation/CoreFoundation.h>\n#include <ApplicationServices/ApplicationServices.h>\n#include <Cocoa/Cocoa.h>\n#include <tkInt.h>\n#include <tkMacOSXInt.h>\n#include \"tkMacOSXImage.h\"\n#include \"tkMacOSXPrivate.h\"\n#include <AppKit/NSAccessibility.h>\n\n\n/* Data declarations and protoypes of functions used in this file. */\nextern Tcl_HashTable *TkAccessibilityObject;\nstatic NSPoint FlipY(NSPoint screenpoint, NSWindow *window);\nvoid PostAccessibilityAnnouncement(NSString *message);\nstatic void InitAccessibilityHashTables(void);\nvoid TkAccessibility_LinkWindowToElement(Tk_Window tkwin, TkAccessibilityElement *element);\nTkAccessibilityElement *TkAccessibility_GetElementForWindow(Tk_Window tkwin);\nTk_Window TkAccessibility_GetWindowForElement(TkAccessibilityElement *element);\nvoid TkAccessibility_UnlinkWindowAndElement(Tk_Window tkwin, TkAccessibilityElement *element);\nvoid TkAccessibility_CleanupHashTables(void);\nstatic int TkMacOSXAccessibleObjCmd(void *clientData,Tcl_Interp *ip, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void TkMacOSXAccessibility_DestroyHandler(void *clientData, XEvent *eventPtr);\nvoid TkMacOSXAccessibility_RegisterForCleanup(Tk_Window tkwin, void *accessibilityElement);\nint IsVoiceOverRunning(void *clientData, Tcl_Interp *ip, Tcl_Size objc, Tcl_Obj *const objv[]);\nint TkMacOSXAccessibility_Init(Tcl_Interp * interp);\nstatic int EmitSelectionChanged(void *clientData,Tcl_Interp *ip, Tcl_Size objc, Tcl_Obj *const objv[]);\nint TkMacOSXAccessibility_Init(Tcl_Interp * interp);\nstatic int ActionEventProc(Tcl_Event *ev, int flags);\n\nchar *callback_command;\nstatic Tcl_HashTable *TkWindowToElementTable = NULL;\nstatic Tcl_HashTable *ElementToTkWindowTable = NULL;\nstatic bool accessibilityTablesInitialized = false;\n\n/*\n * Map script-level roles to CoreFoundation role constants, which are bridged\n * to the NSAccessibilityRole constants. Using these offers better compatibility\n * in C code.\n */\n\n\n#ifndef kAXSwitchRole\n#define kAXSwitchRole CFSTR(\"AXSwitch\")\n#endif\n\nstruct MacRoleMap {\n    const char *tkrole;           /* Tk role string. */\n    CFStringRef macrole;          /* CF role constant (CFStringRef). */\n};\n\nconst struct MacRoleMap roleMap[] = {\n    {\"Button\",        kAXButtonRole},\n    {\"Canvas\",        kAXScrollAreaRole},\n    {\"Checkbutton\",   kAXCheckBoxRole},\n    {\"Combobox\",      kAXComboBoxRole},\n    {\"Entry\",         kAXTextFieldRole},\n    {\"Label\",         kAXStaticTextRole},\n    {\"Listbox\",       kAXGroupRole},\n    {\"Notebook\",      kAXTabGroupRole},\n    {\"Progressbar\",   kAXProgressIndicatorRole},\n    {\"Radiobutton\",   kAXRadioButtonRole},\n    {\"Scale\",         kAXSliderRole},\n    {\"Scrollbar\",     kAXScrollBarRole},\n    {\"Spinbox\",       kAXIncrementorRole},\n    {\"Table\",         kAXGroupRole},\n    {\"Text\",          kAXTextAreaRole},\n    {\"Tree\",          kAXGroupRole},\n    {\"Toggleswitch\",  kAXSwitchRole},\n    {NULL,            NULL}\n};\n\n\n/*\n *----------------------------------------------------------------------\n *\n * FlipY --\n *\n *  Flips the y-coordinate for an NSRect in an NSWindow.\n *\n * Results:\n *\tY-coordinate is oriented to upper left-hand corner of screen.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSPoint FlipY(NSPoint screenpoint, NSWindow *window)\n{\n\n    /* Convert screen coordinates to window base coordinates. */\n    NSPoint windowpoint= [window convertRectFromScreen:NSMakeRect(screenpoint.x, screenpoint.y, 0, 0)].origin;\n\n    /* Flip the y-axis to make it top-left origin. */\n    CGFloat flipped = window.contentView.frame.size.height - windowpoint.y;\n\n    return NSMakePoint(windowpoint.x, flipped);\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * PostAccessibilityAnnouncement --\n *\n *  Customized accessibility message.\n *\n * Results:\n *      Accessibilty API posts customized message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n\nvoid PostAccessibilityAnnouncement(NSString *message)\n{\n    if (!message || [message length] == 0) {\n\treturn; /* Avoid posting empty announcements. */\n    }\n\n    NSDictionary *userInfo = @{\n\tNSAccessibilityAnnouncementKey: message,\n\tNSAccessibilityPriorityKey: @(NSAccessibilityPriorityHigh)\n    };\n\n    /* Post to the main window or the focused accessibility element. */\n    id target = [NSApp mainWindow] ?: [NSApp keyWindow];\n    if (target) {\n\tNSAccessibilityPostNotificationWithUserInfo(\n\t    target,\n\t    NSAccessibilityAnnouncementRequestedNotification,\n\t    userInfo\n\t);\n    }\n}\n\n\n/*\n *\n * TkAccessibilityElement --\n *\n *  Primary interaction between Tk and NSAccessibility API. Accessibility is\n *  linked to a specific Tk_Window, and traits are set and retrieved from hash\n *  tables.\n *\n */\n\n@implementation TkAccessibilityElement : NSAccessibilityElement\n\n- (id) init\n{\n    self = [super init];\n    return self;\n}\n\n/* Foundational method. All actions derive from the role returned here. */\n- (NSString *) accessibilityRole\n{\n    Tk_Window win = self.tk_win;\n    if (!win) {\n\treturn nil;\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn nil;\n    }\n\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n    if (!hPtr2) {\n\treturn nil;\n    }\n\n    Tcl_Obj *roleObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr2);\n    if (!roleObj) {\n\treturn nil;\n    }\n\n    const char *result = Tcl_GetString(roleObj);\n    if (!result) {\n\treturn nil;\n    }\n\n    for (NSUInteger i = 0; roleMap[i].tkrole != NULL; i++) {\n\tif (strcmp(roleMap[i].tkrole, result) == 0) {\n\t    return (__bridge NSString *)roleMap[i].macrole;\n\t}\n    }\n\n    return nil;\n}\n\n\n- (NSString *) accessibilityLabel\n{\n    Tk_Window win = self.tk_win;\n    if (!win) {\n\treturn @\"\";\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn @\"\";\n    }\n\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\n    /* Special handling for group roles (tables, listboxes, trees). */\n    CFStringRef role = (__bridge CFStringRef)self.accessibilityRole;\n    if (role && CFStringCompare(role, kAXGroupRole, 0) == kCFCompareEqualTo) {\n\tNSInteger rowCount = [self accessibilityRowCount];\n\tNSString *count = [NSString stringWithFormat:@\"Table with %ld items. \", (long)rowCount];\n\tNSString *interact = self.accessibilityHint ?: @\"\";\n\tNSString *groupLabel = [NSString stringWithFormat:@\"%@%@\", count, interact];\n\treturn groupLabel;\n    }\n\n    /* Get the description for all other widget roles. */\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"description\");\n    if (!hPtr2) {\n\treturn @\"\";\n    }\n\n    Tcl_Obj *descObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr2);\n    if (!descObj) {\n\treturn @\"\";\n    }\n\n    const char *result = Tcl_GetString(descObj);\n    if (!result) {\n\treturn @\"\";\n    }\n\n    NSString *macdescription = [NSString stringWithUTF8String:result];\n    return macdescription ?: @\"\";\n}\n\n- (id)accessibilityValue\n{\n    CFStringRef role = (__bridge CFStringRef) self.accessibilityRole;\n    Tk_Window win = self.tk_win;\n    Tcl_HashEntry *hPtr, *hPtr2;\n    Tcl_HashTable *AccessibleAttributes;\n\n    if (!win) {\n\treturn nil;\n    }\n\n    hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn nil;\n    }\n\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\n    /*\n     * Special handling for checkbuttons, radio buttons and toggle switches.\n     */\n    if ((role && CFStringCompare(role, kAXCheckBoxRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXRadioButtonRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXSwitchRole, 0) == kCFCompareEqualTo)) {\n\n\tint stateValue = 0; /* Default off. */\n\tTcl_Interp *interp = Tk_Interp(win);\n\n\tif (interp) {\n\t    const char *path = Tk_PathName(win);\n\n\t    /* Get the variable name bound to this widget. */\n\t    Tcl_Obj *varCmd = Tcl_ObjPrintf(\"%s cget -variable\", path);\n\t    Tcl_IncrRefCount(varCmd);\n\t    const char *varName = NULL;\n\n\t    if (Tcl_EvalObjEx(interp, varCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t\tvarName = Tcl_GetStringResult(interp);\n\t    }\n\t    Tcl_DecrRefCount(varCmd);\n\n\t    if (varName && *varName) {\n\t\tconst char *varVal = Tcl_GetVar(interp, varName, TCL_GLOBAL_ONLY);\n\n\t\tif ((role && CFStringCompare(role, kAXCheckBoxRole, 0) == kCFCompareEqualTo) ||\n\t\t    (role && CFStringCompare(role, kAXSwitchRole, 0) == kCFCompareEqualTo)) {\n\t\t    if (varVal && strcmp(varVal, \"1\") == 0) {\n\t\t\tstateValue = 1;\n\t\t    }\n\t\t} else {\n\t\t    /* Radiobutton: need to compare with -value. */\n\t\t    Tcl_Obj *valueCmd = Tcl_ObjPrintf(\"%s cget -value\", path);\n\t\t    Tcl_IncrRefCount(valueCmd);\n\t\t    if (Tcl_EvalObjEx(interp, valueCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t\t\tconst char *rbValue = Tcl_GetStringResult(interp);\n\t\t\tif (varVal && rbValue && strcmp(varVal, rbValue) == 0) {\n\t\t\t    stateValue = 1;\n\t\t\t}\n\t\t    }\n\t\t    Tcl_DecrRefCount(valueCmd);\n\t\t}\n\t    }\n\t}\n\n\t/* Update the Tcl hash table for caching. */\n\tchar buf[2];\n\tsnprintf(buf, sizeof(buf), \"%d\", stateValue);\n\tint newEntry;\n\thPtr2 = Tcl_CreateHashEntry(AccessibleAttributes, \"value\", &newEntry);\n\tTcl_Obj *valObj = Tcl_NewStringObj(buf, -1);\n\tTcl_IncrRefCount(valObj);\n\tTcl_SetHashValue(hPtr2, valObj);\n\n\t/* Return NSNumber for VoiceOver. */\n\tNSControlStateValue cocoaValue =\n\t    (stateValue == 1) ? NSControlStateValueOn : NSControlStateValueOff;\n\n\t/* Notify VoiceOver that value changed. */\n\tNSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification);\n\treturn [NSNumber numberWithInteger:cocoaValue];\n    }\n\n\n    /* Fallback: return cached string value for other widget types. */\n    hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"value\");\n    if (!hPtr2) {\n\treturn nil;\n    }\n\n    Tcl_Obj *valObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr2);\n    const char *result = Tcl_GetString(valObj);\n    return [NSString stringWithUTF8String:result];\n}\n\n\n- (NSString*) accessibilityTitle\n{\n    CFStringRef role = (__bridge CFStringRef)self.accessibilityRole;\n\n    /* Return value for labels and text widgets. */\n    if ((role && CFStringCompare(role, kAXStaticTextRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXTextAreaRole, 0) == kCFCompareEqualTo)) {\n\tNSString *value = self.accessibilityValue;\n\treturn value;\n    }\n\n    Tk_Window win = self.tk_win;\n    if (!win) {\n\treturn @\"\";\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn @\"\";\n    }\n\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"name\");\n    if (!hPtr2) {\n\treturn @\"\";\n    }\n\n    Tcl_Obj *nameObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr2);\n    if (!nameObj) {\n\treturn @\"\";\n    }\n\n    const char *result = Tcl_GetString(nameObj);\n    if (!result) {\n\treturn @\"\";\n    }\n\n    NSString *mactitle = [NSString stringWithUTF8String:result];\n    return mactitle ?: @\"\";\n}\n\n\n- (NSString*) accessibilityHint\n{\n\n    Tk_Window win = self.tk_win;\n    Tcl_HashEntry *hPtr, *hPtr2;\n    Tcl_HashTable *AccessibleAttributes;\n\n    hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn nil;\n    }\n\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"help\");\n    if (!hPtr2) {\n\treturn nil;\n    }\n\n    char *result = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n    NSString *machelp = [NSString stringWithUTF8String:result];\n    return machelp;\n}\n\n\n- (NSRect) accessibilityFrame\n{\n\n    Tk_Window path;\n    path = self.tk_win;\n    TkWindow *winPtr = (TkWindow *)path;\n    CGRect bounds, screenrect, windowframe;\n    NSPoint flippedorigin;\n    CGFloat adjustedx;\n    NSWindow *w;\n\n    CFStringRef role = (__bridge CFStringRef) self.accessibilityRole;\n\n    /* Check to see if Tk_Window exists. */\n    if (!winPtr || winPtr->flags & TK_ALREADY_DEAD) {\n\treturn CGRectZero;\n    }\n\n    /* Get CGRect points for Tk widget.*/\n     TkMacOSXWinCGBounds(winPtr, &bounds);\n\n    /*\n     *  Convert CGRect coordinates to screen coordinates as required\n     *  by NSAccessibility API.\n     *\n     */\n\n    w  = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    screenrect = [w convertRectToScreen:bounds];\n\n    /*\n     * Convert to window coordinates and flip coordinates to\n     * Y-down orientation.\n     */\n\n    flippedorigin = FlipY(screenrect.origin, w);\n\n    /* Calculate the desired x-offset for the accessibility frame.*/\n    windowframe = w.frame;\n    adjustedx = screenrect.origin.x - windowframe.origin.x;\n\n    screenrect = CGRectMake(adjustedx, flippedorigin.y - screenrect.size.height,screenrect.size.width, screenrect.size.height);\n\n    /* Finally,convert back to screen coordinates. */\n    screenrect = [w convertRectToScreen:screenrect];\n\n    /*\n     *  Force focus on Tk widget to align with VoiceOver cursor/focus\n     *  if standard keyboard navigation of non-accessible widget elements\n     *  is required.\n     */\n\n    if ((role && CFStringCompare(role, kAXSliderRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXIncrementorRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXListRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXTableRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXGroupRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXProgressIndicatorRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXTextFieldRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXTextAreaRole, 0) == kCFCompareEqualTo)) {\n\t[self forceFocus];\n    }\n\n    return screenrect;\n}\n\n- (NSString*) accessibilityIdentifier\n{\n\n    int x = arc4random_uniform(1000);\n    NSNumber *id = [NSNumber numberWithInt: x];\n    NSString *identifier = [id stringValue];\n    return identifier;\n}\n\n- (NSString *) accessibilityLanguage\n{\n    /* Use the first system-preferred language. */\n    NSArray<NSString *> *languages = [NSLocale preferredLanguages];\n    if (languages.count > 0) {\n\treturn languages[0];  /* Example: @\"en-US\", @\"ja-JP\" .*/\n    }\n    return nil;\n}\n\n- (id) accessibilityParent\n{\n\n    Tk_Window win = self.tk_win;\n    TkWindow *winPtr = (TkWindow *)win;\n\n\n    /* Ensure Tk window exists. */\n    if (!winPtr) {\n\t[self invalidateAndRelease];\n\treturn nil;\n    }\n\n    if (!winPtr->window) {\n\treturn nil;\n    }\n\n    /*\n     * Tk window exists. Set the TKContentView as the\n     * accessibility parent.\n     */\n    if (winPtr->window) {\n\tTKContentView *view = (TKContentView *)TkMacOSXGetRootControl(winPtr->window);\n\tif (!view || ![view isKindOfClass:[TKContentView class]]) {\n\t    return nil;\n\t}\n\tself.parentView = view;\n\treturn self.parentView;\n    }\n    return nil;\n}\n\n- (BOOL) accessibilityIsFocused\n{\n    return [self.accessibilityParent window] == [NSApp keyWindow];\n}\n\n- (BOOL)becomeFirstResponder\n{\n    return TRUE;\n}\n\n\n- (BOOL)isAccessibilityElement\n{\n    return YES;\n}\n\n- (BOOL)accessibilityIsIgnored\n{\n\n    /* Check if Tk state is disabled. If so, ignore accessible atribute. */\n    Tk_Window win = self.tk_win;\n    Tcl_HashEntry *hPtr, *hPtr2;\n    Tcl_HashTable *AccessibleAttributes;\n\n    hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn NO;\n    }\n\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    hPtr2=Tcl_FindHashEntry(AccessibleAttributes, \"state\");\n    if (!hPtr2) {\n\treturn NO;\n    }\n\n    char *result = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n    if (strcmp(result, \"disabled\") == 0) {\n\treturn YES;\n    }\n\n\n    /* If state is NOT disabled, leave accessibility on. */\n    return NO;\n}\n\n/* Various actions for buttons. */\n- (void) accessibilityPerformAction: (NSAccessibilityActionName)action\n{\n    if (CFStringCompare((CFStringRef)action, kAXPressAction, 0) == kCFCompareEqualTo) {\n\tBOOL success = [self accessibilityPerformPress];\n\n\tif (success) {\n\t    /* Post notification AFTER the action completes. */\n\t    CFStringRef role = (__bridge CFStringRef) self.accessibilityRole;\n\t    if ((role && CFStringCompare(role, kAXCheckBoxRole, 0) == kCFCompareEqualTo) ||\n\t\t(role && CFStringCompare(role, kAXRadioButtonRole, 0) == kCFCompareEqualTo) ||\n\t\t(role && CFStringCompare(role, kAXSwitchRole, 0) == kCFCompareEqualTo)) {\n\t\t/* Delay the notification to ensure the value has actually changed. */\n\t\tdispatch_async(dispatch_get_main_queue(), ^{\n\t\t\tNSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification);\n\t\t    });\n\t    }\n\t}\n    }\n}\n\n\n/* Action for button roles. */\n- (BOOL) accessibilityPerformPress\n{\n    Tk_Window win = self.tk_win;\n    Tcl_HashEntry *hPtr, *hPtr2;\n    Tcl_HashTable *AccessibleAttributes;\n    Tcl_Event *event;\n\n    /* Standard button press. */\n    hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn FALSE;\n    }\n\n    AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"action\");\n    if (!hPtr2) {\n\treturn FALSE;\n    }\n    char *action = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n\n\n    callback_command = action;\n    event = (Tcl_Event *)Tcl_Alloc(sizeof(Tcl_Event));\n    event->proc = ActionEventProc;\n    Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);\n\n    return TRUE;\n}\n\n- (NSInteger)accessibilityRowCount\n{\n    Tk_Window win = self.tk_win;\n    if (!win) return 0;\n\n    Tcl_Interp *interp = Tk_Interp(win);\n    if (!interp) return 0;\n\n    const char *widgetPath = Tk_PathName(win);\n    if (!widgetPath) return 0;\n\n    NSString *widgetName = [NSString stringWithUTF8String:widgetPath];\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn 0;\n    }\n\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n    if (!hPtr2) {\n\treturn 0;\n    }\n\n    const char *result = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(hPtr2));\n    if (!result) {\n\treturn 0;\n    }\n\n    NSString *commandString = nil;\n\n    if (result && strcmp(result, \"Listbox\") == 0) {\n\tcommandString = [NSString stringWithFormat:@\"%@ size\", widgetName];\n    } else if (result &&\n\t       (strcmp(result, \"Table\") == 0 || strcmp(result, \"Tree\") == 0)) {\n\t/* For ttk::treeview, use llength [tree children {}]. */\n\tcommandString = [NSString stringWithFormat:@\"llength [%@ children {}]\", widgetName];\n    } else {\n\treturn 0;\n    }\n\n    Tcl_Obj *commandObj = Tcl_NewStringObj([commandString UTF8String], -1);\n    if (Tcl_EvalObjEx(interp, commandObj, TCL_EVAL_GLOBAL) != TCL_OK) return 0;\n\n    Tcl_Obj *resultObj = Tcl_GetObjResult(interp);\n    int rowCount = 0;\n    Tcl_GetIntFromObj(interp, resultObj, &rowCount);\n\n    return rowCount;\n}\n\n\n- (void) forceFocus\n{\n\n    TkMainInfo *info = TkGetMainInfoList();\n    NSString *widgetName = [NSString stringWithUTF8String:Tk_PathName(self.tk_win)];\n    NSString *commandString = [NSString stringWithFormat:@\"::tk::accessible::_forceTkFocus %@\", widgetName];\n    Tcl_Obj *commandObj = Tcl_NewStringObj([commandString UTF8String], -1);\n\n    if (Tcl_EvalObjEx(info->interp, commandObj, TCL_EVAL_GLOBAL) == TCL_OK) {\n\tTcl_GetObjResult(info->interp);\n    }\n}\n\n- (id)invalidateAndRelease\n{\n\n    if (!self.tk_win) {\n\treturn nil;\n    }\n\n    /* Notify macOS that this element is being destroyed. */\n    NSAccessibilityPostNotification(self, NSAccessibilityUIElementDestroyedNotification);\n\n    /* Break any strong references to avoid accessing stale memory. */\n    self.tk_win = NULL;\n    self.accessibilityParent = nil;\n\n    /* Finally, release the object.*/\n    [self release];\n    self = nil;\n\n    return TCL_OK;\n}\n\n- (void)dealloc {\n    [super dealloc];\n}\n\n@end\n\n\n/*\n * Event proc which calls the ActionEventProc procedure.\n */\n\nstatic int ActionEventProc(\n    TCL_UNUSED(Tcl_Event *), /* ev */\n    TCL_UNUSED(int)) /* flags */\n{\n    TkMainInfo *info = TkGetMainInfoList();\n    Tcl_GlobalEval(info->interp, callback_command);\n    return 1;\n}\n\n/*\n * Hash table functions to link Tk windows with their associated\n * NSAccessibilityElement objects.\n */\n\nstatic void InitAccessibilityHashTables(void)\n{\n    if (!accessibilityTablesInitialized) {\n\tTkWindowToElementTable = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tElementToTkWindowTable = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\n\tTcl_InitHashTable(TkWindowToElementTable, TCL_ONE_WORD_KEYS);\n\tTcl_InitHashTable(ElementToTkWindowTable, TCL_ONE_WORD_KEYS);\n\n\taccessibilityTablesInitialized = true;\n    }\n}\n\nvoid TkAccessibility_LinkWindowToElement(Tk_Window tkwin, TkAccessibilityElement *element)\n{\n    if (!tkwin || !element) {\n\treturn;\n    }\n\n    InitAccessibilityHashTables();\n\n    Tcl_HashEntry *hPtr;\n    int isNew;\n\n    /* Link Tk_Window -> TkAccessibilityElement. */\n    hPtr = Tcl_CreateHashEntry(TkWindowToElementTable, (char *)tkwin, &isNew);\n    if (hPtr) {\n\t/* Retain the element to ensure it stays alive. */\n\t[element retain];\n\tTcl_SetHashValue(hPtr, element);\n    }\n\n    /* Link TkAccessibilityElement -> Tk_Window. */\n    hPtr = Tcl_CreateHashEntry(ElementToTkWindowTable, (char *)element, &isNew);\n    if (hPtr) {\n\tTcl_SetHashValue(hPtr, tkwin);\n    }\n}\n\nTkAccessibilityElement *TkAccessibility_GetElementForWindow(Tk_Window tkwin)\n{\n    if (!tkwin || !accessibilityTablesInitialized) {\n\treturn nil;\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkWindowToElementTable, (char *)tkwin);\n    if (hPtr) {\n\treturn (TkAccessibilityElement *)Tcl_GetHashValue(hPtr);\n    }\n\n    return nil;\n}\n\nTk_Window TkAccessibility_GetWindowForElement(TkAccessibilityElement *element)\n{\n    if (!element || !accessibilityTablesInitialized) {\n\treturn NULL;\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(ElementToTkWindowTable, (char *)element);\n    if (hPtr) {\n\treturn (Tk_Window)Tcl_GetHashValue(hPtr);\n    }\n\n    return NULL;\n}\n\nvoid TkAccessibility_UnlinkWindowAndElement(Tk_Window tkwin, TkAccessibilityElement *element)\n{\n    if (!accessibilityTablesInitialized) {\n\treturn;\n    }\n\n    Tcl_HashEntry *hPtr;\n\n    /* Remove Tk_Window -> TkAccessibilityElement mapping. */\n    if (tkwin) {\n\thPtr = Tcl_FindHashEntry(TkWindowToElementTable, (char *)tkwin);\n\tif (hPtr) {\n\t    TkAccessibilityElement *storedElement = (TkAccessibilityElement *)Tcl_GetHashValue(hPtr);\n\t    [storedElement release]; /* Release the retained element. */\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n    }\n\n    /* Remove TkAccessibilityElement -> Tk_Window mapping. */\n    if (element) {\n\thPtr = Tcl_FindHashEntry(ElementToTkWindowTable, (char *)element);\n\tif (hPtr) {\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n    }\n}\n\nvoid TkAccessibility_CleanupHashTables(void)\n{\n    if (!accessibilityTablesInitialized) {\n\treturn;\n    }\n\n    /* Clean up TkWindowToElementTable and release all elements. */\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(TkWindowToElementTable, &search);\n    while (hPtr) {\n\tTkAccessibilityElement *element = (TkAccessibilityElement *)Tcl_GetHashValue(hPtr);\n\t[element release];\n\thPtr = Tcl_NextHashEntry(&search);\n    }\n\n    Tcl_DeleteHashTable(TkWindowToElementTable);\n    Tcl_DeleteHashTable(ElementToTkWindowTable);\n\n    Tcl_Free(TkWindowToElementTable);\n    Tcl_Free(ElementToTkWindowTable);\n\n    TkWindowToElementTable = NULL;\n    ElementToTkWindowTable = NULL;\n    accessibilityTablesInitialized = false;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * IsVoiceOverRunning --\n *\n * Runtime check to see if screen reader is running.\n *\n * Results:\n *\tReturns if screen reader is active or not.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint IsVoiceOverRunning(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *ip,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    TCL_UNUSED(Tcl_Obj *const *)) /* objv */\n{\n    int result = 0;\n    FILE *fp = popen(\"pgrep -x VoiceOver\", \"r\");\n    if (fp == NULL) {\n\tresult = 0;\n    }\n\n    char buffer[16];\n    /* If output exists, VoiceOver is running. */\n    int running = (fgets(buffer, sizeof(buffer), fp) != NULL);\n\n    pclose(fp);\n    if (running) {\n\tresult = 1;\n    }\n    Tcl_SetObjResult(ip, Tcl_NewIntObj(result));\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * EmitSelectionChanged --\n *\n * Accessibility system notification when selection changed.\n *\n * Results:\n *\tAccessibility system is made aware when a selection is changed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int EmitSelectionChanged(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *ip,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(ip, 1, objv, \"window?\");\n\treturn TCL_ERROR;\n    }\n    Tk_Window path;\n\n    path = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n    if (path == NULL) {\n\tTk_MakeWindowExist(path);\n    }\n\n    TkAccessibilityElement *widget = TkAccessibility_GetElementForWindow(path);\n    if (!widget) {\n\tTcl_SetResult(ip, \"no accessibility element for window\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    widget.tk_win = path;\n\n    CFStringRef role = (__bridge CFStringRef) widget.accessibilityRole;\n\n    if ((role && CFStringCompare(role, kAXTextFieldRole, 0) == kCFCompareEqualTo) ||\n\t(role && CFStringCompare(role, kAXTextAreaRole, 0) == kCFCompareEqualTo)) {\n\n\tNSString *announcement = widget.accessibilityValue;\n\tif (announcement && [announcement length] > 0) {\n\t    /* Delay slightly to ensure the value is fully updated. */\n\t    dispatch_async(dispatch_get_main_queue(), ^{\n\t\t    PostAccessibilityAnnouncement(announcement);\n\t\t});\n\t}\n    } else {\n\t/* Existing behavior for other widgets */\n\tNSAccessibilityPostNotification(widget, NSAccessibilityValueChangedNotification);\n\tNSAccessibilityPostNotification(widget, NSAccessibilitySelectedChildrenChangedNotification);\n\n\tNSString *announcement = widget.accessibilityValue;\n\tif (announcement && [announcement length] > 0) {\n\t    dispatch_async(dispatch_get_main_queue(), ^{\n\t\t    PostAccessibilityAnnouncement(announcement);\n\t\t});\n\t}\n    }\n\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXAccessibility_RegisterForCleanup --\n *\n * Register event handler for destroying accessibility element.\n *\n * Results:\n *      Event handler is registered.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid TkMacOSXAccessibility_RegisterForCleanup(Tk_Window tkwin, void *accessibilityElement)\n{\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, TkMacOSXAccessibility_DestroyHandler, accessibilityElement);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXAccessibility_DestroyHandler --\n *\n * Clean up accessibility element structures when window is destroyed.\n *\n * Results:\n *\tAccessibility element is deallocated.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void TkMacOSXAccessibility_DestroyHandler(void *clientData, XEvent *eventPtr)\n{\n      if (eventPtr->type == DestroyNotify) {\n\tTkAccessibilityElement *element = (TkAccessibilityElement *)clientData;\n\tif (element) {\n\t    Tk_Window tkwin = TkAccessibility_GetWindowForElement(element);\n\n\t    /* Remove from hash tables before invalidating */\n\t    TkAccessibility_UnlinkWindowAndElement(tkwin, element);\n\n\t    [element invalidateAndRelease];\n\t}\n    }\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacAccessibleObjCmd --\n *\n *\tMain command for adding and managing accessibility objects to Tk\n *      widgets on macOS using the NSAccessibilty API.\n *\n * Results:\n *\n *      A standard Tcl result.\n *\n * Side effects:\n *\n *\tTk widgets are now accessible to screen readers.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int TkMacOSXAccessibleObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *ip,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(ip, 1, objv, \"window?\");\n\treturn TCL_ERROR;\n    }\n\n    Tk_Window path = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n    if (path == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /* Check if element already exists for this window. */\n    TkAccessibilityElement *existingElement = TkAccessibility_GetElementForWindow(path);\n    if (existingElement) {\n\t/* Element already exists, no need to create a new one. */\n\treturn TCL_OK;\n    }\n\n    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\n    TkAccessibilityElement *widget = [[TkAccessibilityElement alloc] init];\n    widget.tk_win = path;\n\n    /* Create the bidirectional link. */\n    TkAccessibility_LinkWindowToElement(path, widget);\n\n    [widget.accessibilityParent accessibilityAddChildElement:widget];\n    TkMacOSXAccessibility_RegisterForCleanup(widget.tk_win, widget);\n    NSAccessibilityPostNotification(widget.parentView, NSAccessibilityLayoutChangedNotification);\n\n    [pool drain];\n    return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXAccessibility_Init --\n *\n *\tInitializes the accessibility module.\n *\n * Results:\n *\n *      A standard Tcl result.\n *\n * Side effects:\n *\n *\tAccessibility module is now activated.\n *\n *----------------------------------------------------------------------\n */\n\nint TkMacOSXAccessibility_Init(Tcl_Interp * interp)\n{\n\n    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::add_acc_object\", TkMacOSXAccessibleObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_selection_change\", EmitSelectionChanged, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::check_screenreader\", IsVoiceOverRunning, NULL, NULL);\n    [pool release];\n    return TCL_OK;\n}\n\n\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXBitmap.c",
    "content": "/*\n * tkMacOSXBitmap.c --\n *\n *\tThis file handles the implementation of native bitmaps.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n\n/*\n * This structure holds information about native bitmaps.\n */\n\ntypedef struct {\n    const char *name;\t\t/* Name of icon. */\n    OSType iconType;\t\t/* OSType of icon. */\n} BuiltInIcon;\n\n/*\n * This array maps a string name to the supported builtin icons\n * on the Macintosh.\n */\n\nstatic BuiltInIcon builtInIcons[] = {\n    {\"document\",\tkGenericDocumentIcon},\n    {\"stationery\",\tkGenericStationeryIcon},\n    {\"edition\",\t\tkGenericEditionFileIcon},\n    {\"application\",\tkGenericApplicationIcon},\n    {\"accessory\",\tkGenericDeskAccessoryIcon},\n    {\"folder\",\t\tkGenericFolderIcon},\n    {\"pfolder\",\t\tkPrivateFolderIcon},\n    {\"trash\",\t\tkTrashIcon},\n    {\"floppy\",\t\tkGenericFloppyIcon},\n    {\"ramdisk\",\t\tkGenericRAMDiskIcon},\n    {\"cdrom\",\t\tkGenericCDROMIcon},\n    {\"preferences\",\tkGenericPreferencesIcon},\n    {\"querydoc\",\tkGenericQueryDocumentIcon},\n    {\"stop\",\t\tkAlertStopIcon},\n    {\"note\",\t\tkAlertNoteIcon},\n    {\"caution\",\t\tkAlertCautionIcon},\n    {NULL,\t\t\t0}\n};\n\n#define builtInIconSize 32\n\nstatic Tcl_HashTable iconBitmapTable = {};\ntypedef struct {\n    int kind, width, height;\n    char *value;\n} IconBitmap;\n\nstatic const char *const iconBitmapOptionStrings[] = {\n    \"-file\", \"-fileType\", \"-imageFile\", \"-namedImage\", \"-osType\",\n    \"-systemType\", NULL\n};\nenum iconBitmapOptions {\n    ICON_FILE, ICON_FILETYPE, ICON_IMAGEFILE, ICON_NAMEDIMAGE, ICON_OSTYPE,\n    ICON_SYSTEMTYPE\n};\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDefineNativeBitmaps --\n *\n *\tAdd native bitmaps.\n *\n * Results:\n *\tA standard Tcl result. If an error occurs then TCL_ERROR is\n *\treturned and a message is left in the interp's result.\n *\n * Side effects:\n *\t\"Name\" is entered into the bitmap table and may be used from\n *\there on to refer to the given bitmap.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDefineNativeBitmaps(void)\n{\n    Tcl_HashTable *tablePtr = TkGetBitmapPredefTable();\n    BuiltInIcon *builtInPtr;\n\n    for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {\n\tTcl_HashEntry *predefHashPtr;\n\tTk_Uid name;\n\tint isNew;\n\n\tname = Tk_GetUid(builtInPtr->name);\n\tpredefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);\n\tif (isNew) {\n\t    TkPredefBitmap *predefPtr = (TkPredefBitmap *)Tcl_Alloc(sizeof(TkPredefBitmap));\n\n\t    predefPtr->source = UINT2PTR(builtInPtr->iconType);\n\t    predefPtr->width = builtInIconSize;\n\t    predefPtr->height = builtInIconSize;\n\t    predefPtr->native = 1;\n\t    Tcl_SetHashValue(predefHashPtr, predefPtr);\n\t}\n    }\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PixmapFromImage --\n *\n * Results:\n *\tReturns a Pixmap with an NSImage drawn into it.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Pixmap\nPixmapFromImage(\n    Display *display,\n    NSImage* image,\n    CGSize size)\n{\n    TkMacOSXDrawingContext dc;\n    Pixmap pixmap;\n\n    pixmap = Tk_GetPixmap(display, None, (int)size.width, (int)size.height, 0);\n    if (TkMacOSXSetupDrawingContext(pixmap, NULL, &dc)) {\n\tif (dc.context) {\n\t    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,\n\t\t\t\t    .tx = 0, .ty = size.height};\n\t    CGContextConcatCTM(dc.context, t);\n\t    [NSGraphicsContext saveGraphicsState];\n\t    [NSGraphicsContext setCurrentContext:GET_NSCONTEXT(dc.context, NO)];\n\t    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect\n\t\toperation:NSCompositeCopy fraction:1.0];\n\t    [NSGraphicsContext restoreGraphicsState];\n\t}\n\tTkMacOSXRestoreDrawingContext(&dc);\n    }\n    return pixmap;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateNativeBitmap --\n *\n *\tCreate native bitmap.\n *\n * Results:\n *\tNative bitmap.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTkpCreateNativeBitmap(\n    Display *display,\n    const void *source)\t\t/* Info about the icon to build. */\n{\n    NSString *filetype = TkMacOSXOSTypeToUTI(PTR2UINT(source));\n    NSImage *iconImage = TkMacOSXIconForFileType(filetype);\n    CGSize size = CGSizeMake(builtInIconSize, builtInIconSize);\n    Pixmap pixmap = PixmapFromImage(display, iconImage, size);\n    return pixmap;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * OSTypeFromString --\n *\n *\tHelper to convert string to OSType.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tt is set to OSType if conversion successful.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nOSTypeFromString(const char *s, OSType *t) {\n    int result = TCL_ERROR;\n    Tcl_DString ds;\n    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, \"macRoman\");\n\n    (void)Tcl_UtfToExternalDString(encoding, s, TCL_INDEX_NONE, &ds);\n    if (Tcl_DStringLength(&ds) <= 4) {\n\tchar string[4] = {};\n\tmemcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n\t*t = (OSType) string[0] << 24 | (OSType) string[1] << 16 |\n\t     (OSType) string[2] <<  8 | (OSType) string[3];\n\tresult = TCL_OK;\n    }\n    Tcl_DStringFree(&ds);\n    Tcl_FreeEncoding(encoding);\n    return result;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetNativeAppBitmap --\n *\n *\tGet a named native bitmap.\n *\n *\tAttemps to interpret the given name in order as:\n *\t    - name defined by ::tk::mac::iconBitmap\n *\t    - NSImage named image name\n *\t    - NSImage url string\n *\t    - 4-char OSType of IconServices icon\n *\n * Results:\n *\tNative bitmap or None.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTkpGetNativeAppBitmap(\n    Display *display,\t\t/* The display. */\n    const char *name,\t\t/* The name of the bitmap. */\n    int *width,\t\t\t/* The width & height of the bitmap. */\n    int *height)\n{\n    Tcl_HashEntry *hPtr;\n    Pixmap pixmap = None;\n    NSString *string;\n    NSImage *image = nil;\n    NSSize size = { .width = builtInIconSize, .height = builtInIconSize };\n    if (iconBitmapTable.buckets &&\n\t    (hPtr = Tcl_FindHashEntry(&iconBitmapTable, name))) {\n\tOSType type;\n\tIconBitmap *iconBitmap = (IconBitmap *)Tcl_GetHashValue(hPtr);\n\tname = NULL;\n\tsize = NSMakeSize(iconBitmap->width, iconBitmap->height);\n\tswitch (iconBitmap->kind) {\n\tcase ICON_FILE:\n\t    string = [[NSString stringWithUTF8String:iconBitmap->value]\n\t\t    stringByExpandingTildeInPath];\n\t    image = [[NSWorkspace sharedWorkspace] iconForFile:string];\n\t    break;\n\tcase ICON_FILETYPE:\n\t    string = [NSString stringWithUTF8String:iconBitmap->value];\n\t    image = TkMacOSXIconForFileType(string);\n\t    break;\n\tcase ICON_OSTYPE:\n\t    if (OSTypeFromString(iconBitmap->value, &type) == TCL_OK) {\n\t\tstring = [NSString stringWithUTF8String:iconBitmap->value];\n\t\timage = TkMacOSXIconForFileType(string);\n\t    }\n\t    break;\n\tcase ICON_SYSTEMTYPE:\n\t    name = iconBitmap->value;\n\t    break;\n\tcase ICON_NAMEDIMAGE:\n\t    string = [NSString stringWithUTF8String:iconBitmap->value];\n\t    image = [NSImage imageNamed:string];\n\t    break;\n\tcase ICON_IMAGEFILE:\n\t    string = [[NSString stringWithUTF8String:iconBitmap->value]\n\t\t    stringByExpandingTildeInPath];\n\t    image = [[[NSImage alloc] initWithContentsOfFile:string]\n\t\t    autorelease];\n\t    break;\n\t}\n\tif (image) {\n\t    [image setSize:size];\n\t}\n    } else {\n\tstring = [NSString stringWithUTF8String:name];\n\timage = [NSImage imageNamed:string];\n\tif (!image) {\n\t    NSURL *url = [NSURL fileURLWithPath:string];\n\t    if (url) {\n\t\timage = [[[NSImage alloc] initWithContentsOfURL:url]\n\t\t\tautorelease];\n\t    }\n\t}\n\tif (image) {\n\t    size = [image size];\n\t}\n    }\n    if (image) {\n\tpixmap = PixmapFromImage(display, image, NSSizeToCGSize(size));\n    } else if (name) {\n\t/*\n\t * As a last resort, try to interpret the name as an OSType.\n\t * It would probably be better to just return None at this\n\t * point.\n\t */\n\tOSType iconType;\n\tif (OSTypeFromString(name, &iconType) == TCL_OK) {\n\t    NSString *iconUTI = TkMacOSXOSTypeToUTI(iconType);\n\t    NSImage *iconImage = TkMacOSXIconForFileType(iconUTI);\n\t    pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));\n\t}\n    }\n    *width = (int)size.width;\n    *height = (int)size.height;\n    return pixmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXIconBitmapObjCmd --\n *\n *\tImplements the ::tk::mac::iconBitmap command.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tnone\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMacOSXIconBitmapObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tcl_HashEntry *hPtr;\n    int isNew, result = TCL_ERROR;\n    Tcl_Size i = 1, len;\n    const char *name, *value;\n    IconBitmap ib, *iconBitmap;\n\n    if (objc != 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"name width height \"\n\t\t\"-file|-fileType|-osType|-systemType|-namedImage|-imageFile \"\n\t\t\"value\");\n\tgoto end;\n    }\n    name = Tcl_GetStringFromObj(objv[i++], &len);\n    if (!len) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"empty bitmap name\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"MACBITMAP\", \"BAD\", (char *)NULL);\n\tgoto end;\n    }\n    if (Tcl_GetIntFromObj(interp, objv[i++], &ib.width) != TCL_OK) {\n\tgoto end;\n    }\n    if (Tcl_GetIntFromObj(interp, objv[i++], &ib.height) != TCL_OK) {\n\tgoto end;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[i++], iconBitmapOptionStrings,\n\t    sizeof(char *), \"kind\", TCL_EXACT, &ib.kind) != TCL_OK) {\n\tgoto end;\n    }\n    value = Tcl_GetStringFromObj(objv[i++], &len);\n    if (!len) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"empty bitmap value\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"MACBITMAP\", \"EMPTY\", (char *)NULL);\n\tgoto end;\n    }\n#if 0\n    if ((kind == ICON_TYPE || kind == ICON_SYSTEM)) {\n\tTcl_DString ds;\n\tTcl_Encoding encoding = Tcl_GetEncoding(NULL, \"macRoman\");\n\n\t(void)Tcl_UtfToExternalDString(encoding, value, TCL_INDEX_NONE, &ds);\n\tlen = Tcl_DStringLength(&ds);\n\tTcl_DStringFree(&ds);\n\tTcl_FreeEncoding(encoding);\n\tif (len > 4) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"invalid bitmap value\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MACBITMAP\", \"INVALID\", (char *)NULL);\n\t    goto end;\n\t}\n    }\n#endif\n    ib.value = (char *)Tcl_Alloc(len + 1);\n    strcpy(ib.value, value);\n    if (!iconBitmapTable.buckets) {\n\tTcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS);\n    }\n    hPtr = Tcl_CreateHashEntry(&iconBitmapTable, name, &isNew);\n    if (!isNew) {\n\ticonBitmap = (IconBitmap *)Tcl_GetHashValue(hPtr);\n\tTcl_Free(iconBitmap->value);\n    } else {\n\ticonBitmap = (IconBitmap *)Tcl_Alloc(sizeof(IconBitmap));\n\tTcl_SetHashValue(hPtr, iconBitmap);\n    }\n    *iconBitmap = ib;\n    result = TCL_OK;\n  end:\n    return result;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXButton.c",
    "content": "/*\n * tkMacOSXButton.c --\n *\n *\tThis file implements the Macintosh specific portion of the button\n *\twidgets.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n * Copyright © 2001 Apple Computer, Inc.\n * Copyright © 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2007 Revar Desmera\n * Copyright © 2015 Kevin Walzer\n * Copyright © 2015 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkButton.h\"\n#include \"tkMacOSXFont.h\"\n#include \"tkMacOSXDebug.h\"\n\n#define FIRST_DRAW\t    2\n#define ACTIVE\t\t    4\n\n/*\n * Extra padding used for computing the content size that should\n * be allowed when drawing the HITheme button.\n */\n\n#define HI_PADX 14\n#define HI_PADY 1\n\n/*\n * The delay in milliseconds between pulsing default button redraws.\n */\n#define PULSE_TIMER_MSECS 62   /* Largest value that didn't look stuttery */\n\n/*\n * Declaration of Mac specific button structure.\n */\n\n\ntypedef struct {\n    Tk_3DBorder border;\n    int relief;\n    int offset;\t\t\t/* 0 means this is a normal widget. 1 means\n\t\t\t\t * it is an image button, so we offset the\n\t\t\t\t * image to make the button appear to move\n\t\t\t\t * up and down as the relief changes. */\n    GC gc;\n    int hasImageOrBitmap;\n} DrawParams;\n\ntypedef struct {\n    TkButton info;\t\t/* Generic button info */\n    int id;\n    int usingControl;\n    int useTkText;\n    int flags;\t\t\t/* Initialisation status */\n    ThemeButtonKind btnkind;\n    HIThemeButtonDrawInfo drawinfo;\n    HIThemeButtonDrawInfo lastdrawinfo;\n    DrawParams drawParams;\n    Tcl_TimerToken defaultPulseHandler;\n} MacButton;\n\n/*\n * Forward declarations for procedures defined later in this file:\n */\n\nstatic void\tButtonBackgroundDrawCB(const HIRect *btnbounds,\n\t\t    MacButton *ptr, SInt16 depth, Boolean isColorDev);\nstatic void\tButtonContentDrawCB(const HIRect *bounds,\n\t\t    ThemeButtonKind kind,\n\t\t    const HIThemeButtonDrawInfo *info, MacButton *ptr,\n\t\t    SInt16 depth, Boolean isColorDev);\nstatic void\tButtonEventProc(void *clientData,\n\t\t    XEvent *eventPtr);\nstatic void\tTkMacOSXComputeButtonParams(TkButton *butPtr,\n\t\t    ThemeButtonKind *btnkind,\n\t\t    HIThemeButtonDrawInfo *drawinfo);\nstatic int\tTkMacOSXComputeButtonDrawParams(TkButton *butPtr,\n\t\t    DrawParams * dpPtr);\nstatic void\tTkMacOSXDrawButton(MacButton *butPtr, GC gc,\n\t\t    Pixmap pixmap);\nstatic void\tDrawButtonImageAndText(TkButton *butPtr);\nstatic void\tPulseDefaultButtonProc(void *clientData);\n\n/*\n * The class procedure table for the button widgets.\n */\n\nconst Tk_ClassProcs tkpButtonProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TkButtonWorldChanged,\t/* worldChangedProc */\n    NULL,\n\tNULL\n};\n\nstatic int bCount;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpButtonSetDefaults --\n *\n *\tThis procedure is invoked before option tables are created for buttons.\n *\tIt modifies some of the default values to match the current values\n *\tdefined for this platform.\n *\n * Results:\n *\tSome of the default values in *specPtr are modified.\n *\n * Side effects:\n *\tUpdates some of.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpButtonSetDefaults()\n{\n    /*No-op.*/\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateButton --\n *\n *\tAllocate a new TkButton structure.\n *\n * Results:\n *\tReturns a newly allocated TkButton structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkButton *\nTkpCreateButton(\n    Tk_Window tkwin)\n{\n    MacButton *macButtonPtr = (MacButton *)Tcl_Alloc(sizeof(MacButton));\n\n    Tk_CreateEventHandler(tkwin, ActivateMask,\n\t    ButtonEventProc, macButtonPtr);\n    macButtonPtr->id = bCount++;\n    macButtonPtr->flags = FIRST_DRAW;\n    macButtonPtr->btnkind = kThemePushButton;\n    macButtonPtr->defaultPulseHandler = NULL;\n    bzero(&macButtonPtr->drawinfo, sizeof(macButtonPtr->drawinfo));\n    bzero(&macButtonPtr->lastdrawinfo, sizeof(macButtonPtr->lastdrawinfo));\n\n    return (TkButton *) macButtonPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayButton --\n *\n *\tThis procedure is invoked to display a button widget. It is normally\n *\tinvoked as an idle handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the button in its current mode. The\n *\tREDRAW_PENDING flag is cleared.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayButton(\n    void *clientData)\t/* Information about widget. */\n{\n    MacButton *macButtonPtr = (MacButton *)clientData;\n    TkButton *butPtr = (TkButton *)clientData;\n    Tk_Window tkwin = butPtr->tkwin;\n    Pixmap pixmap;\n    DrawParams* dpPtr = &macButtonPtr->drawParams;\n    int needhighlight = 0;\n    int highlightWidth;\n\n    butPtr->flags &= ~REDRAW_PENDING;\n    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\n    if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) {\n\tmacButtonPtr->useTkText = 0;\n    } else {\n\tmacButtonPtr->useTkText = 1;\n    }\n    if (macButtonPtr->useTkText) {\n\tif (butPtr->type == TYPE_BUTTON) {\n\t    Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0,\n\t\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\t} else {\n\t    Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,\n\t\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\t}\n\n\t/*\n\t * Display image or bitmap or text for labels or custom controls.\n\t */\n\n\tDrawButtonImageAndText(butPtr);\n\tneedhighlight = 1;\n    } else {\n\t/*\n\t * Draw the native portion of the buttons.\n\t */\n\n\tTkMacOSXDrawButton(macButtonPtr, dpPtr->gc, pixmap);\n\n\t/*\n\t * Ask for the highlight border, if needed.\n\t */\n\n\tif (highlightWidth < 3) {\n\t    needhighlight = 1;\n\t}\n    }\n\n    /*\n     * Draw highlight border, if needed.\n     */\n\n    if (needhighlight) {\n\tGC gc = NULL;\n\tif ((butPtr->flags & GOT_FOCUS) && butPtr->highlightColorPtr) {\n\t    gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);\n\t} else if (butPtr->type == TYPE_LABEL) {\n\t    gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap);\n\t}\n\tif (gc) {\n\t    TkMacOSXDrawSolidBorder(tkwin, gc, 0, highlightWidth);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeButtonGeometry --\n *\n *\tAfter changes in a button's text or bitmap, this procedure recomputes\n *\tthe button's geometry and passes this information along to the geometry\n *\tmanager for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe button's window may change size.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeButtonGeometry(\n    TkButton *butPtr)\t\t/* Button whose geometry may have changed. */\n{\n    int width = 0, height = 0, charWidth = 1, haveImage = 0, haveText = 0;\n    int txtWidth = 0, txtHeight = 0;\n    MacButton *mbPtr = (MacButton *) butPtr;\n    Tk_FontMetrics fm;\n    char *text = Tcl_GetString(butPtr->textPtr);\n    int padX, padY, wrapLength;\n    int butPtrWidth, butPtrHeight;\n    int borderWidth, highlightWidth;\n\n    TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);\n\n    /*\n     * If the indicator is on, get its size.\n     */\n\n    if (butPtr->indicatorOn) {\n\tswitch (butPtr->type) {\n\tcase TYPE_RADIO_BUTTON:\n\t    GetThemeMetric(kThemeMetricRadioButtonWidth,\n\t\t    (SInt32 *) &butPtr->indicatorDiameter);\n\t    break;\n\tcase TYPE_CHECK_BUTTON:\n\t    GetThemeMetric(kThemeMetricCheckBoxWidth,\n\t\t    (SInt32 *) &butPtr->indicatorDiameter);\n\t    break;\n\tdefault:\n\t    break;\n\t}\n\n\t/*\n\t * Allow 2px extra space next to the indicator.\n\t */\n\n\tbutPtr->indicatorSpace = butPtr->indicatorDiameter + 2;\n    } else {\n\tbutPtr->indicatorSpace = 0;\n\tbutPtr->indicatorDiameter = 0;\n    }\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->widthObj, &butPtrWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->heightObj, &butPtrHeight);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->wrapLengthObj, &wrapLength);\n    if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {\n\tTk_FreeTextLayout(butPtr->textLayout);\n\tbutPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,\n\t\ttext, TCL_INDEX_NONE, wrapLength, butPtr->justify, 0,\n\t\t&butPtr->textWidth, &butPtr->textHeight);\n\n\ttxtWidth = butPtr->textWidth + 2 * padX;\n\ttxtHeight = butPtr->textHeight + 2 * padY;\n\thaveText = 1;\n    }\n\n    if (haveImage) {\n\tif (haveText) { /* Image and Text */\n\t    switch ((enum compound) butPtr->compound) {\n\t    case COMPOUND_TOP:\n\t    case COMPOUND_BOTTOM:\n\t\t/*\n\t\t* Image is above or below text.\n\t\t*/\n\n\t\theight += txtHeight + padY;\n\t\twidth = (width > txtWidth ? width : txtWidth);\n\t\tbreak;\n\t    case COMPOUND_LEFT:\n\t    case COMPOUND_RIGHT:\n\t\t/*\n\t\t* Image is left or right of text.\n\t\t*/\n\n\t\twidth += txtWidth + 2 * padX;\n\t\theight = (height > txtHeight ? height : txtHeight);\n\t\tbreak;\n\t    case COMPOUND_CENTER:\n\t\t/*\n\t\t* Image and text are superimposed.\n\t\t*/\n\n\t\twidth = (width > txtWidth ? width : txtWidth);\n\t\theight = (height > txtHeight ? height : txtHeight);\n\t\tbreak;\n\t    default:\n\t\tbreak;\n\t    }\n\t}\n\t/* Image with or without text */\n\twidth = butPtrWidth > 0 ? butPtrWidth : width + butPtr->indicatorSpace;\n\theight = butPtrHeight > 0 ? butPtrHeight : height;\n\tif (butPtr->type == TYPE_BUTTON) {\n\t    /*\n\t     * Allow room to shift the image.\n\t     */\n\t    width += 2;\n\t    height += 2;\n\t}\n    } else { /* Text only */\n\twidth = txtWidth + butPtr->indicatorSpace;\n\theight = txtHeight;\n\tif (butPtrWidth > 0) {\n\t    charWidth = Tk_TextWidth(butPtr->tkfont, \"0\", 1);\n\t    width = butPtrWidth * charWidth + 2 * padX;\n\t}\n\tif (butPtrHeight > 0) {\n\t    Tk_GetFontMetrics(butPtr->tkfont, &fm);\n\t    height = butPtrHeight * fm.linespace + 2 * padY;\n\t}\n    }\n\n    /*\n     * Now figure out the size of the border decorations for the button.\n     */\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\n    butPtr->inset = borderWidth + highlightWidth;\n\n    width += butPtr->inset * 2;\n    height += butPtr->inset * 2;\n    if ([NSApp macOSVersion] == 100600) {\n\twidth += 12;\n    }\n    if (mbPtr->btnkind == kThemePushButton) {\n\tHIRect tmpRect;\n\tHIRect contBounds;\n\n\t/*\n\t * A PushButton has a minimum size.  We make sure that we are not\n\t * underestimating the size by requesting the content size of a\n\t * Pushbutton whose overall size is our content size expanded by the\n\t * standard padding.\n\t */\n\n\ttmpRect = CGRectMake(0, 0, width + 2 * HI_PADX, height + 2 * HI_PADY);\n\tHIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);\n\tif (height < contBounds.size.height) {\n\t    height = (int)contBounds.size.height;\n\t}\n\tif (width < contBounds.size.width) {\n\t    width = (int)contBounds.size.width;\n\t}\n\theight += 2 * HI_PADY;\n\twidth += 2 * HI_PADX;\n    }\n    Tk_GeometryRequest(butPtr->tkwin, width, height);\n    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawButtonImageAndText --\n *\n *\tDraws the image and text associated with a button or label.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image and text are drawn.\n *\n *----------------------------------------------------------------------\n */\nstatic void\nDrawButtonImageAndText(\n    TkButton *butPtr)\n{\n\n    MacButton *mbPtr = (MacButton *) butPtr;\n    Tk_Window tkwin = butPtr->tkwin;\n    Pixmap pixmap;\n    int haveImage = 0, haveText = 0, pressed = 0;\n    int imageWidth = 0, imageHeight = 0;\n    int imageXOffset = 0, imageYOffset = 0;\n    int textXOffset = 0, textYOffset = 0;\n    int width = 0, height = 0;\n    int fullWidth = 0, fullHeight = 0;\n    int padX, padY, borderWidth, highlightWidth;\n    DrawParams *dpPtr = &mbPtr->drawParams;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    imageWidth = width;\n    imageHeight = height;\n\n    if (mbPtr->drawinfo.state == kThemeStatePressed) {\n\tpressed = 1;\n    }\n\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\n    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { /* Image and Text */\n\tint x, y;\n\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /* Image is above or below text */\n\t    if (butPtr->compound == COMPOUND_TOP) {\n\t\ttextYOffset = height + padY;\n\t    } else {\n\t\timageYOffset = butPtr->textHeight + padY;\n\t    }\n\t    fullHeight = height + butPtr->textHeight + padY;\n\t    fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_LEFT) {\n\t\ttextXOffset = width + padX;\n\t    } else {\n\t\timageXOffset = butPtr->textWidth + padX;\n\t    }\n\t    fullWidth = butPtr->textWidth + padX + width;\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed\n\t     */\n\n\t    fullWidth = (width > butPtr->textWidth ? width :\n\t\t    butPtr->textWidth);\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tdefault:\n\t    break;\n\t}\n\n\tTkComputeAnchor(butPtr->anchor, tkwin,\n\t\tpadX + borderWidth, padY + borderWidth,\n\t\tfullWidth + butPtr->indicatorSpace, fullHeight, &x, &y);\n\tx += butPtr->indicatorSpace;\n\n\tif (dpPtr->relief == TK_RELIEF_SUNKEN) {\n\t    x += dpPtr->offset;\n\t    y += dpPtr->offset;\n\t} else if (dpPtr->relief == TK_RELIEF_RAISED) {\n\t    x -= dpPtr->offset;\n\t    y -= dpPtr->offset;\n\t}\n\tif (pressed) {\n\t    x += dpPtr->offset;\n\t    y += dpPtr->offset;\n\t}\n\timageXOffset += x;\n\timageYOffset += y;\n\n\tif (butPtr->image != NULL) {\n\t    if ((butPtr->selectImage != NULL) &&\n\t\t    (butPtr->flags & SELECTED)) {\n\t\tTk_RedrawImage(butPtr->selectImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else if ((butPtr->tristateImage != NULL) &&\n\t\t    (butPtr->flags & TRISTATED)) {\n\t\tTk_RedrawImage(butPtr->tristateImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else {\n\t\tTk_RedrawImage(butPtr->image, 0, 0, width,\n\t\t\theight, pixmap, imageXOffset, imageYOffset);\n\t    }\n\t} else {\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc,\n\t\t    imageXOffset, imageYOffset);\n\t    XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,\n\t\t    0, 0, (unsigned int) width, (unsigned int) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);\n\t}\n\ty += 1; /* Tweak to match native buttons. */\n\tTk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,\n\t\t\t  x + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,\n\t\tbutPtr->textLayout,\n\t\tx + textXOffset, y + textYOffset,\n\t\tbutPtr->underline);\n    } else if (haveImage) { /* Image only */\n\tint x = 0, y;\n\n\tTkComputeAnchor(butPtr->anchor, tkwin,\n\t\tpadX + borderWidth, padY + borderWidth,\n\t\twidth + butPtr->indicatorSpace, height, &x, &y);\n\tx += butPtr->indicatorSpace;\n\tif (pressed) {\n\t    x += dpPtr->offset;\n\t    y += dpPtr->offset;\n\t}\n\timageXOffset += x;\n\timageYOffset += y;\n\n\tif (butPtr->image != NULL) {\n\t    if ((butPtr->selectImage != NULL) &&\n\t\t    (butPtr->flags & SELECTED)) {\n\t\tTk_RedrawImage(butPtr->selectImage, 0, 0, width,\n\t\t\theight, pixmap, imageXOffset, imageYOffset);\n\t    } else if ((butPtr->tristateImage != NULL) &&\n\t\t    (butPtr->flags & TRISTATED)) {\n\t\tTk_RedrawImage(butPtr->tristateImage, 0, 0, width,\n\t\t\theight, pixmap, imageXOffset, imageYOffset);\n\t    } else {\n\t\tTk_RedrawImage(butPtr->image, 0, 0, width, height,\n\t\t\tpixmap, imageXOffset, imageYOffset);\n\t    }\n\t} else {\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);\n\t    XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,\n\t\t    0, 0, (unsigned int) width, (unsigned int) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);\n\t}\n    } else { /* Text only */\n\tint x, y;\n\n\tTkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\tbutPtr->textWidth + butPtr->indicatorSpace,\n\t\tbutPtr->textHeight, &x, &y);\n\tx += butPtr->indicatorSpace;\n\ty += 1; /* Tweak to match native buttons */\n\tTk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,\n\t\t\t  x, y, 0, -1);\n    }\n\n    /*\n     * If the button is disabled with a stipple rather than a special\n     * foreground color, generate the stippled effect.  If the widget is\n     * selected and we use a different background color when selected, must\n     * temporarily modify the GC so the stippling is the right color.\n     */\n\n    if (mbPtr->useTkText) {\n\tif ((butPtr->state == STATE_DISABLED)\n\t\t&& ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {\n\t    if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t    && (butPtr->selectBorder != NULL)) {\n\t\tXSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t\tTk_3DBorderColor(butPtr->selectBorder)->pixel);\n\t    }\n\t    /*\n\t     * Stipple the whole button if no disabledFg was specified,\n\t     * otherwise restrict stippling only to displayed image\n\t     */\n\t    if (butPtr->disabledFg == NULL) {\n\t\tXFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,\n\t\t\t0, 0, (unsigned) Tk_Width(tkwin),\n\t\t\t(unsigned) Tk_Height(tkwin));\n\t    } else {\n\t\tXFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,\n\t\t\timageXOffset, imageYOffset,\n\t\t\t(unsigned) imageWidth, (unsigned) imageHeight);\n\t    }\n\t    if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t&& (butPtr->selectBorder != NULL)\n\t    ) {\n\t\tXSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t\tTk_3DBorderColor(butPtr->normalBorder)->pixel);\n\t    }\n\t}\n\n\t/*\n\t * Draw the border and traversal highlight last.  This way, if the\n\t * button's contents overflow they'll be covered up by the border.\n\t */\n\n\tif (dpPtr->relief != TK_RELIEF_FLAT) {\n\t    int inset = highlightWidth;\n\n\t    Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset,\n\t\t    Tk_Width(tkwin) - 2 * inset, Tk_Height(tkwin) - 2 * inset,\n\t\t    borderWidth, dpPtr->relief);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyButton --\n *\n *\tFree data structures associated with the button control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the default control state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyButton(\n    TkButton *butPtr)\n{\n    MacButton *mbPtr = (MacButton *) butPtr; /* Mac button. */\n\n    if (mbPtr->defaultPulseHandler) {\n\tTcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMacOSXDrawButton --\n *\n *\tThis function draws the tk button using Mac controls. In addition,\n *\tthis code may apply custom colors passed in the TkButton.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *      The control is created, or reinitialised as needed\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXDrawButton(\n    MacButton *mbPtr,    /* Mac button. */\n    TCL_UNUSED(GC),      /* The GC we are drawing into - needed for\n\t\t\t  * the bevel button */\n    Pixmap pixmap)       /* The pixmap we are drawing into - needed\n\t\t\t  * for the bevel button */\n{\n    TkButton *butPtr = (TkButton *) mbPtr;\n    TkWindow *winPtr = (TkWindow *) butPtr->tkwin;\n    HIRect cntrRect;\n    TkMacOSXDrawingContext dc;\n    DrawParams *dpPtr = &mbPtr->drawParams;\n    int useNewerHITools = 1;\n\n    TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);\n\n    cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,\n\t    Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));\n\n    cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);\n\n    if (useNewerHITools == 1) {\n\tHIRect contHIRec;\n\tstatic HIThemeButtonDrawInfo hiinfo;\n\n\tButtonBackgroundDrawCB(&cntrRect, mbPtr, 32, true);\n\n\tif (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {\n\t    return;\n\t}\n\n\thiinfo.version = 0;\n\thiinfo.state = mbPtr->drawinfo.state;\n\thiinfo.kind = mbPtr->btnkind;\n\thiinfo.value = mbPtr->drawinfo.value;\n\thiinfo.adornment = mbPtr->drawinfo.adornment;\n\thiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();\n\tif (hiinfo.animation.time.start == 0) {\n\t    hiinfo.animation.time.start = hiinfo.animation.time.current;\n\t}\n\n\t/*\n\t * To avoid buttons with white text on a white background, we set the\n\t * state to inactive in Dark Mode unless the button is pressed or is a\n\t * -default active button.  This isn't perfect but it is mostly usable.\n\t * Using a ttk::button would be a much better choice, however.\n\t */\n\n\tif ([NSApp macOSVersion] < 101500) {\n\t    if (TkMacOSXInDarkMode(butPtr->tkwin) &&\n\t\tmbPtr->drawinfo.state != kThemeStatePressed &&\n\t\t!(mbPtr->drawinfo.adornment & kThemeAdornmentDefault)) {\n\t\thiinfo.state = kThemeStateInactive;\n\t    }\n\t}\n\tHIThemeDrawButton(&cntrRect, &hiinfo, dc.context,\n\t\tkHIThemeOrientationNormal, &contHIRec);\n\n\tTkMacOSXRestoreDrawingContext(&dc);\n\tButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,\n\t\t(MacButton *) mbPtr, 32, true);\n    } else {\n\tif (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {\n\t    return;\n\t}\n\n\tTkMacOSXRestoreDrawingContext(&dc);\n    }\n    mbPtr->lastdrawinfo = mbPtr->drawinfo;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonBackgroundDrawCB --\n *\n *\tThis function draws the background that lies under checkboxes and\n *\tradiobuttons.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe background gets updated to the current color.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nButtonBackgroundDrawCB(\n    TCL_UNUSED(const HIRect *),\n    MacButton *ptr,\n    TCL_UNUSED(SInt16),\n    TCL_UNUSED(Boolean))\n{\n    MacButton *mbPtr = (MacButton *) ptr;\n    TkButton *butPtr = (TkButton *) mbPtr;\n    Tk_Window tkwin = butPtr->tkwin;\n    Pixmap pixmap;\n    int usehlborder = 0;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n\n    if (butPtr->type != TYPE_LABEL) {\n\tswitch (mbPtr->btnkind) {\n\tcase kThemeSmallBevelButton:\n\tcase kThemeBevelButton:\n\tcase kThemeRoundedBevelButton:\n\tcase kThemePushButton:\n\t    usehlborder = 1;\n\t    break;\n\t}\n    }\n    if (usehlborder) {\n\tTk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0,\n\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n    } else {\n\tTk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,\n\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonContentDrawCB --\n *\n *\tThis function draws the label and image for the button.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe content of the button gets updated.\n *\n *--------------------------------------------------------------\n */\nstatic void\nButtonContentDrawCB (\n    TCL_UNUSED(const HIRect *),\n    TCL_UNUSED(ThemeButtonKind),\n    TCL_UNUSED(const HIThemeButtonDrawInfo *),\n    MacButton *ptr,\n    TCL_UNUSED(SInt16),\n    TCL_UNUSED(Boolean))\n{\n    TkButton *butPtr = (TkButton *) ptr;\n    Tk_Window tkwin = butPtr->tkwin;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    /*\n     * Overlay Tk elements over button native region: drawing elements within\n     * button boundaries/native region causes unpredictable metrics.\n     */\n\n    DrawButtonImageAndText( butPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ButtonEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tbuttons.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nButtonEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkButton *buttonPtr = (TkButton *)clientData;\n    MacButton *mbPtr = (MacButton *)clientData;\n\n    if (eventPtr->type == ActivateNotify\n\t    || eventPtr->type == DeactivateNotify) {\n\tif ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) {\n\t    return;\n\t}\n\tif (eventPtr->type == ActivateNotify) {\n\t    mbPtr->flags |= ACTIVE;\n\t} else {\n\t    mbPtr->flags &= ~ACTIVE;\n\t}\n\tif ((buttonPtr->flags & REDRAW_PENDING) == 0) {\n\t    Tcl_DoWhenIdle(TkpDisplayButton, buttonPtr);\n\t    buttonPtr->flags |= REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXComputeButtonParams --\n *\n *      This procedure computes the various parameters used when creating a\n *      Carbon Appearance control.  These are determined by the various tk\n *      button parameters\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the btnkind and drawinfo parameters\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXComputeButtonParams(\n    TkButton *butPtr,\n    ThemeButtonKind *btnkind,\n    HIThemeButtonDrawInfo *drawinfo)\n{\n    MacButton *mbPtr = (MacButton *) butPtr;\n    int borderWidth, highlightWidth;\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\n    if (borderWidth <= 2) {\n\t*btnkind = kThemeSmallBevelButton;\n    } else if (borderWidth == 3) {\n\t*btnkind = kThemeBevelButton;\n    } else if (borderWidth == 4) {\n\t*btnkind = kThemeRoundedBevelButton;\n    } else {\n\t*btnkind = kThemePushButton;\n    }\n\n    if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {\n\tswitch (butPtr->type) {\n\tcase TYPE_BUTTON:\n\t    *btnkind = kThemePushButton;\n\t    break;\n\tcase TYPE_RADIO_BUTTON:\n\t    if (borderWidth <= 1) {\n\t\t*btnkind = kThemeSmallRadioButton;\n\t    } else {\n\t\t*btnkind = kThemeRadioButton;\n\t    }\n\t    break;\n\tcase TYPE_CHECK_BUTTON:\n\t    if (borderWidth <= 1) {\n\t\t*btnkind = kThemeSmallCheckBox;\n\t    } else {\n\t\t*btnkind = kThemeCheckBox;\n\t    }\n\t    break;\n\t}\n    }\n\n    if (butPtr->indicatorOn) {\n\tswitch (butPtr->type) {\n\tcase TYPE_RADIO_BUTTON:\n\t    if (borderWidth <= 1) {\n\t\t*btnkind = kThemeSmallRadioButton;\n\t    } else {\n\t\t*btnkind = kThemeRadioButton;\n\t    }\n\t    break;\n\tcase TYPE_CHECK_BUTTON:\n\t    if (borderWidth <= 1) {\n\t\t*btnkind = kThemeSmallCheckBox;\n\t    } else {\n\t\t*btnkind = kThemeCheckBox;\n\t    }\n\t    break;\n\t}\n    } else {\n\tif (butPtr->type == TYPE_RADIO_BUTTON ||\n\t\tbutPtr->type == TYPE_CHECK_BUTTON) {\n\t    if (*btnkind == kThemePushButton) {\n\t\t*btnkind = kThemeBevelButton;\n\t    }\n\t}\n    }\n\n    if (butPtr->flags & SELECTED) {\n\tdrawinfo->value = kThemeButtonOn;\n    } else if (butPtr->flags & TRISTATED) {\n\tdrawinfo->value = kThemeButtonMixed;\n    } else {\n\tdrawinfo->value = kThemeButtonOff;\n    }\n\n    if ((mbPtr->flags & FIRST_DRAW) != 0) {\n\tmbPtr->flags &= ~FIRST_DRAW;\n\tif (Tk_MacOSXIsAppInFront()) {\n\t    mbPtr->flags |= ACTIVE;\n\t}\n    }\n\n    drawinfo->state = kThemeStateInactive;\n    if ((mbPtr->flags & ACTIVE) == 0) {\n\tif (butPtr->state == STATE_DISABLED) {\n\t    drawinfo->state = kThemeStateUnavailableInactive;\n\t} else {\n\t    drawinfo->state = kThemeStateInactive;\n\t}\n    } else if (butPtr->state == STATE_DISABLED) {\n\tdrawinfo->state = kThemeStateUnavailable;\n    } else if (butPtr->state == STATE_ACTIVE) {\n\tdrawinfo->state = kThemeStatePressed;\n    } else {\n\tdrawinfo->state = kThemeStateActive;\n    }\n\n    drawinfo->adornment = kThemeAdornmentNone;\n    if (butPtr->defaultState == DEFAULT_ACTIVE) {\n\tif (drawinfo->state != kThemeStatePressed) {\n\t    drawinfo->adornment |= kThemeAdornmentDefault;\n\t}\n\n\t/*\n\t * Older macOS systems (10.9 and earlier) use an animation to\n\t * indicate the active button.  This is simulated by redrawing\n\t * the button periodically.\n\t */\n\n\tif (!mbPtr->defaultPulseHandler && ([NSApp macOSVersion] < 101000)) {\n\t    mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(\n\t\t    PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);\n\t}\n    } else if (mbPtr->defaultPulseHandler) {\n\tTcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);\n    }\n    if (highlightWidth >= 3) {\n\tif ((butPtr->flags & GOT_FOCUS)) {\n\t    drawinfo->adornment |= kThemeAdornmentFocus;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXComputeButtonDrawParams --\n *\n *\tThis procedure computes the various parameters used when drawing a\n *\tbutton. These are determined by the various tk button parameters\n *\n * Results:\n *\t1 if control will be used, 0 otherwise.\n *\n * Side effects:\n *\tSets the button draw parameters\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXComputeButtonDrawParams(\n    TkButton *butPtr,\n    DrawParams *dpPtr)\n{\n    MacButton *mbPtr = (MacButton *) butPtr;\n\n    dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)\n\t    || (butPtr->bitmap != None));\n\n    if (butPtr->type != TYPE_LABEL) {\n\tdpPtr->offset = 0;\n\tif (dpPtr->hasImageOrBitmap) {\n\t    switch (mbPtr->btnkind) {\n\t    case kThemeSmallBevelButton:\n\t    case kThemeBevelButton:\n\t    case kThemeRoundedBevelButton:\n\t    case kThemePushButton:\n\t\tdpPtr->offset = 1;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    dpPtr->border = butPtr->normalBorder;\n    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {\n\tdpPtr->gc = butPtr->disabledGC;\n    } else if (butPtr->type == TYPE_BUTTON && butPtr->state == STATE_ACTIVE) {\n\tdpPtr->gc = butPtr->activeTextGC;\n\tdpPtr->border = butPtr->activeBorder;\n    } else if ((mbPtr->drawinfo.adornment & kThemeAdornmentDefault) &&\n\t       mbPtr->drawinfo.state == kThemeStateActive) {\n\t/*\n\t * This is a \"-default active\" button in the front window.\n\t */\n\n\tdpPtr->gc = butPtr->activeTextGC;\n    } else {\n\tdpPtr->gc = butPtr->normalTextGC;\n    }\n\n    if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)\n\t    && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {\n\tdpPtr->border = butPtr->selectBorder;\n    }\n\n    /*\n     * Override the relief specified for the button if this is a checkbutton or\n     * radiobutton and there's no indicator.\n     */\n\n    dpPtr->relief = butPtr->relief;\n\n    if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {\n\tif (!dpPtr->hasImageOrBitmap) {\n\t    dpPtr->relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN\n\t\t    : TK_RELIEF_RAISED;\n\t}\n    }\n\n    if (butPtr->type != TYPE_LABEL && (butPtr->type == TYPE_BUTTON ||\n\t    butPtr->indicatorOn || dpPtr->hasImageOrBitmap)) {\n\t/*\n\t * Draw this widget as a native control.\n\t */\n\n\treturn 1;\n    } else {\n\t/*\n\t * Draw this widget from scratch.\n\t */\n\n\treturn 0;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * PulseDefaultButtonProc --\n *\n *     This function redraws the button on a timer, to pulse\n *     default buttons.\n *\n * Results:\n *     None.\n *\n * Side effects:\n *     Sets a timer to run itself again.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nPulseDefaultButtonProc(void *clientData)\n{\n    MacButton *mbPtr = (MacButton *)clientData;\n\n    TkpDisplayButton(clientData);\n    /*\n     * Fix 40ada90762: any idle calls to TkpDisplayButton need to be canceled\n     * in case the button is destroyed and has its data freed before the idle\n     * event is handled (DestroyButton only cancels calls when REDRAW_PENDING\n     * is set, which is not the case after calling TkpDisplayButton directly).\n     */\n    Tcl_CancelIdleCall(TkpDisplayButton, clientData);\n    mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(\n\t    PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXClipboard.c",
    "content": "/*\n * tkMacOSXClipboard.c --\n *\n *\tThis file manages the clipboard for the Tk toolkit.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkSelect.h\"\n\nstatic NSInteger changeCount = -1;\nstatic Tk_Window tkClipboardOwner = NULL;\n\n#pragma mark TKApplication(TKClipboard)\n\n@implementation TKApplication(TKClipboard)\n- (void) tkProvidePasteboard: (TkDisplay *) dispPtr\n\tpasteboard: (NSPasteboard *) sender\n\tprovideDataForType: (NSString *) type\n{\n    NSMutableString *string = [NSMutableString new];\n    if (dispPtr && dispPtr->clipboardActive &&\n\t    [type isEqualToString:NSStringPboardType]) {\n\tfor (TkClipboardTarget *targetPtr = dispPtr->clipTargetPtr; targetPtr;\n\t\ttargetPtr = targetPtr->nextPtr) {\n\t    if (targetPtr->type == XA_STRING ||\n\t\t    targetPtr->type == dispPtr->utf8Atom) {\n\t\tfor (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;\n\t\t\tcbPtr; cbPtr = cbPtr->nextPtr) {\n\t\t    NSString *s = [[TKNSString alloc]\n\t\t\tinitWithTclUtfBytes:cbPtr->buffer\n\t\t\t\t     length:(NSUInteger)cbPtr->length];\n\t\t    [string appendString:s];\n\t\t    [s release];\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    }\n    [sender setString:string forType:type];\n    changeCount = [sender changeCount];\n    [string release];\n}\n\n- (void) tkProvidePasteboard: (TkDisplay *) dispPtr\n{\n    if (dispPtr && dispPtr->clipboardActive) {\n\t[self tkProvidePasteboard:dispPtr\n\t\tpasteboard:[NSPasteboard generalPasteboard]\n\t\tprovideDataForType:NSStringPboardType];\n    }\n}\n\n- (void) pasteboard: (NSPasteboard *) sender\n\tprovideDataForType: (NSString *) type\n{\n    TkDisplay *dispPtr = TkGetDisplayList();\n    [self tkProvidePasteboard:dispPtr\n\t\t   pasteboard:[NSPasteboard generalPasteboard]\n\t   provideDataForType:NSStringPboardType];\n}\n\n- (void) tkCheckPasteboard\n{\n    if (tkClipboardOwner && [[NSPasteboard generalPasteboard] changeCount] !=\n\t    changeCount) {\n\tTkDisplay *dispPtr = TkGetDisplayList();\n\tif (dispPtr) {\n\t    XEvent event;\n\t    event.xany.type = SelectionClear;\n\t    event.xany.serial = NextRequest(Tk_Display(tkClipboardOwner));\n\t    event.xany.send_event = False;\n\t    event.xany.window = Tk_WindowId(tkClipboardOwner);\n\t    event.xany.display = Tk_Display(tkClipboardOwner);\n\t    event.xselectionclear.selection = dispPtr->clipboardAtom;\n\t    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t}\n\ttkClipboardOwner = NULL;\n    }\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelGetSelection --\n *\n *\tRetrieve the specified selection from another process. For now, only\n *\tfetching XA_STRING from CLIPBOARD is supported. Eventually other types\n *\tshould be allowed.\n *\n * Results:\n *\tThe return value is a standard Tcl return value. If an error occurs\n *\t(such as no selection exists) then an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkSelGetSelection(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tk_Window tkwin,\t\t/* Window on whose behalf to retrieve the\n\t\t\t\t * selection (determines display from which to\n\t\t\t\t * retrieve). */\n    Atom selection,\t\t/* Selection to retrieve. */\n    Atom target,\t\t/* Desired form in which selection is to be\n\t\t\t\t * returned. */\n    Tk_GetSelProc *proc,\t/* Procedure to call to process the selection,\n\t\t\t\t * once it has been retrieved. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    int result = TCL_ERROR;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    int haveExternalClip =\n\t    ([[NSPasteboard generalPasteboard] changeCount] != changeCount);\n\n    if (dispPtr && (haveExternalClip || dispPtr->clipboardActive)\n\t    && selection == dispPtr->clipboardAtom\n\t    && (target == XA_STRING || target == dispPtr->utf8Atom)) {\n\tNSString *string = nil;\n\tNSPasteboard *pb = [NSPasteboard generalPasteboard];\n\tNSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:\n\t\tNSStringPboardType]];\n\n\tif (type) {\n\t    string = [pb stringForType:type];\n\t}\n\tif (string) {\n\t    result = proc(clientData, interp, string.UTF8String);\n\t}\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t     \"%s selection doesn't exist or form \\\"%s\\\" not defined\",\n\t     Tk_GetAtomName(tkwin, selection),\n\t     Tk_GetAtomName(tkwin, target)));\n\tTcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"EXISTS\", (char *)NULL);\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSetSelectionOwner --\n *\n *\tThis function claims ownership of the specified selection. If the\n *\tselection is CLIPBOARD, then we empty the system clipboard.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetSelectionOwner(\n    Display *display,\t\t/* X Display. */\n    Atom selection,\t\t/* What selection to own. */\n    Window owner,\t\t/* Window to be the owner. */\n    TCL_UNUSED(Time))\t\t\t/* The current time? */\n{\n    TkDisplay *dispPtr = TkGetDisplayList();\n\n    if (dispPtr && selection == dispPtr->clipboardAtom) {\n\ttkClipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;\n\tif (!dispPtr->clipboardActive) {\n\t    NSPasteboard *pb = [NSPasteboard generalPasteboard];\n\t    changeCount = [pb declareTypes:[NSArray array] owner:NSApp];\n\t}\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSelDeadWindow --\n *\n *\tThis function is invoked just before a TkWindow is deleted. It performs\n *\tselection-related cleanup.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\ttkClipboardOwner is cleared.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXSelDeadWindow(\n    TkWindow *winPtr)\n{\n    if (winPtr && winPtr == (TkWindow *)tkClipboardOwner) {\n\ttkClipboardOwner = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelUpdateClipboard --\n *\n *\tThis function is called to force the clipboard to be updated after new\n *\tdata is added or the clipboard has been cleared.\n *\n *      The nil Object is declared to be the owner.  This is done in a way\n *      which triggers an incremeent of the pasteboard's changeCount property,\n *      notifying clipboard managers that the value has changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOwnership contents and attributes of the general NSPasteboard\n *      may change.\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * Apple says that the changeCount is incremented whenever the ownership\n * of a pasteboard type changes.  They actually mean that the changeCount\n * is incremented when declareTypes is called, but is left unchanged when\n * addTypes is called.  (Both methods can change ownership in some sense\n * and both return the new changeCount.)\n *\n * Apple also says that addTypes \"promises\" that the owner object (if not nil)\n * will provide data of the specified type, while declareTypes \"prepares\" the\n * pasteboard.  Maybe that explains something.\n */\n\nvoid\nTkSelUpdateClipboard(\n    TCL_UNUSED(TkWindow*),\t\t/* Window associated with clipboard. */\n    clipboardOption option)\t/* option passed to clipboard command */\n{\n    NSPasteboard *pb = [NSPasteboard generalPasteboard];\n    switch (option) {\n    case CLIPBOARD_APPEND:\n\t/*\n\t * This increments the changeCount so that clipboard managers will be\n\t * able to see and manage the clip.\n\t */\n\n\tchangeCount = [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType]\n\t\t\t\t owner:nil];\n\t[NSApp tkProvidePasteboard: TkGetDisplayList()\n\t\t\tpasteboard: (NSPasteboard *) pb\n\t\tprovideDataForType: (NSString *) NSStringPboardType];\n\tbreak;\n    case CLIPBOARD_CLEAR:\n\tchangeCount = [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType]\n\t\t\t\t owner:nil];\n\t[NSApp tkProvidePasteboard: TkGetDisplayList()\n\t\t\tpasteboard: (NSPasteboard *) pb\n\t\tprovideDataForType: (NSString *) NSStringPboardType];\n\tbreak;\n    default:\n\tbreak;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkSelEventProc --\n *\n *\tThis procedure is invoked whenever a selection-related event occurs.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLots: depends on the type of event.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkSelEventProc(\n    Tk_Window tkwin,\t\t/* Window for which event was targeted. */\n    XEvent *eventPtr)\t/* X event: either SelectionClear,\n\t\t\t\t * SelectionRequest, or SelectionNotify. */\n{\n    if (eventPtr->type == SelectionClear) {\n\ttkClipboardOwner = NULL;\n\tTkSelClearSelection(tkwin, eventPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelPropProc --\n *\n *\tThis procedure is invoked when property-change events occur on windows\n *\tnot known to the toolkit. This is a stub function under Windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelPropProc(\n    TCL_UNUSED(XEvent *))\t/* X PropertyChange event. */\n{\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXColor.c",
    "content": "/*\n * TkMacOSXColor.c --\n *\n *\tThis file maintains a database of color values for the Tk\n *\ttoolkit, in order to avoid round-trips to the server to\n *\tmap color names to pixel values.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2020 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkColor.h\"\n#include \"tkMacOSXColor.h\"\n\nstatic Tcl_HashTable systemColors;\nstatic size_t numSystemColors;\nstatic size_t rgbColorIndex;\nstatic size_t controlAccentIndex;\nstatic size_t controlAlternatingRowIndex;\nstatic size_t selectedTabTextIndex;\nstatic size_t pressedButtonTextIndex;\nstatic Bool useFakeAccentColor = NO;\nstatic SystemColorDatum **systemColorIndex;\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\nstatic NSAppearance *lightAqua = nil;\nstatic NSAppearance *darkAqua = nil;\n#endif\n\n#pragma mark TKApplication(TKColor)\n\n/*\n * Method in which to perform any appearance-dependent code.\n *\n * On macOS 11 and later, this simply wraps\n * NSAppearance performAsCurrentDrawingAppearance:.\n *\n * On macOS 10.14 and 10.15, this uses the workaround\n * of saving, temporarily setting, and then restoring\n * the deprecated NSAppearance.currentAppearance property.\n *\n * On earlier macOS versions this simply performs block().\n */\n@implementation TKApplication(TKColor)\n- (void) performAsCurrentDrawingAppearance:(void (^)(void))block\n\t\t       usingDarkAppearance:(BOOL)useDarkAppearance\n{\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n    NSAppearance *appearance = useDarkAppearance ? darkAqua : lightAqua;\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000\n    if(@available(macOS 11.0, *)) {\n\t[appearance performAsCurrentDrawingAppearance:block];\n\treturn;\n    }\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000\n    if(@available(macOS 10.14, *)) {\n\tNSAppearance *savedAppearance = NSAppearance.currentAppearance;\n\tNSAppearance.currentAppearance = appearance;\n\tblock();\n\tNSAppearance.currentAppearance = savedAppearance;\n\treturn;\n    }\n#endif\n\n#endif\n\n    block();\n}\n@end\n#pragma mark -\n\nMODULE_SCOPE\nCGColorRef\nTkMacOSXGetCGColorFromNSColorUsingAppearance(\n    NSColor *color,\n    BOOL useDarkAppearance)\n{\n    __block CGColorRef result = NULL;\n    [NSApp performAsCurrentDrawingAppearance:^{\n\t    result = color.CGColor;\n\t}\n\tusingDarkAppearance:useDarkAppearance\n    ];\n    return result;\n}\n\nMODULE_SCOPE\nNSColor *\nTkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n    NSColor *color,\n    NSColorSpace *colorSpace,\n    BOOL useDarkAppearance)\n{\n    __block NSColor *result = nil;\n    [NSApp performAsCurrentDrawingAppearance:^{\n\t    result = [color colorUsingColorSpace:colorSpace];\n\t}\n\tusingDarkAppearance:useDarkAppearance\n    ];\n    return result;\n}\n\nstatic NSColorSpace* sRGB = NULL;\nstatic const CGFloat WINDOWBACKGROUND[4] =\n    {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};\n\nstatic void initColorTable()\n{\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n    Tcl_InitHashTable(&systemColors, TCL_STRING_KEYS);\n    SystemColorDatum *entry, *oldEntry;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *hPtr;\n    int newPtr;\n    size_t index = 0;\n    NSColorList *systemColorList = [NSColorList colorListNamed:@\"System\"];\n    NSString *key;\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n    if (@available(macOS 10.14, *)) {\n\tdarkAqua = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];\n\tlightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua];\n\n\t/*\n\t * These retains prevent a crash on some macOS versions.\n\t * See bug [3a4310ee].\n\t */\n\t[darkAqua retain];\n\t[lightAqua retain];\n    }\n#endif\n\n    /*\n     * Build a hash table for looking up a color by its name.\n     * First add all of the static entries from tkMacOSXColor.h\n     */\n\n    for (entry = systemColorData; entry->name != NULL; entry++) {\n\thPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);\n\tif (entry->type == semantic) {\n\t    NSString *colorName = [[NSString alloc]\n\t\t\t\t   initWithCString:entry->macName\n\t\t\t\t\t  encoding:NSUTF8StringEncoding];\n\t    SEL colorSelector = NSSelectorFromString(colorName);\n\t    if (![NSColor respondsToSelector:colorSelector]) {\n\t\tif ([colorName isEqualToString:@\"controlAccentColor\"]) {\n\t\t    useFakeAccentColor = YES;\n\t\t} else if (   ![colorName isEqualToString:@\"selectedTabTextColor\"]\n\t\t\t   && ![colorName isEqualToString:@\"controlAlternatingRowColor\"]\n\t\t\t   && ![colorName isEqualToString:@\"pressedButtonTextColor\"]) {\n\t\t    /* Uncomment to print all unsupported colors:              */\n\t\t    /* printf(\"Unsupported color %s\\n\", colorName.UTF8String); */\n\t\t    continue;\n\t\t}\n\t    }\n\t    entry->selector = [colorName retain];\n\t}\n\tif (newPtr == 0) {\n\t    oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n\t    entry->index = oldEntry->index;\n\t    [oldEntry->selector release];\n\t} else {\n\t    entry->index = index++;\n\t}\n\tTcl_SetHashValue(hPtr, entry);\n    }\n\n    /*\n     * Add all of the colors in the System ColorList.\n     */\n\n    for (key in [systemColorList allKeys]) {\n\tNSUInteger length = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];\n\tchar *name;\n\tentry = (SystemColorDatum *)Tcl_Alloc(sizeof(SystemColorDatum));\n\tbzero(entry, sizeof(SystemColorDatum));\n\tname = (char *)Tcl_Alloc(length + 1);\n\tstrcpy(name, key.UTF8String);\n\tname[0] = (char)toupper(UCHAR(name[0]));\n\tif (!strcmp(name, \"WindowBackgroundColor\")) {\n\n\t    /*\n\t     * Avoid black windows on old systems.\n\t     */\n\n\t    continue;\n\t}\n\tentry->type=semantic;\n\tentry->name = name;\n\tentry->selector = [key retain];\n\thPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);\n\tif (newPtr == 0) {\n\t    oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n\t    entry->index = oldEntry->index;\n\t    [oldEntry->selector release];\n\t} else {\n\t    entry->index = index++;\n\t}\n\tTcl_SetHashValue(hPtr, entry);\n    }\n\n    /*\n     * Build an array for looking up a color by its index.\n     */\n\n    numSystemColors = index;\n    systemColorIndex = (SystemColorDatum **)Tcl_Alloc(numSystemColors * sizeof(SystemColorDatum *));\n    for (hPtr = Tcl_FirstHashEntry(&systemColors, &search); hPtr != NULL;\n\t hPtr = Tcl_NextHashEntry(&search)) {\n\tentry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n\tif (entry == NULL) {\n\t    Tcl_Panic(\"Unsupported semantic color with no supported backup!\");\n\t}\n\tsystemColorIndex[entry->index] = entry;\n    }\n\n    /*\n     * Remember the indexes of some special entries.\n     */\n\n    hPtr = Tcl_FindHashEntry(&systemColors, \"Pixel\");\n    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n    rgbColorIndex = entry->index;\n    hPtr = Tcl_FindHashEntry(&systemColors, \"ControlAccentColor\");\n    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n    controlAccentIndex = entry->index;\n    hPtr = Tcl_FindHashEntry(&systemColors, \"ControlAlternatingRowColor\");\n    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n    controlAlternatingRowIndex = entry->index;\n    hPtr = Tcl_FindHashEntry(&systemColors, \"SelectedTabTextColor\");\n    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n    selectedTabTextIndex = entry->index;\n    hPtr = Tcl_FindHashEntry(&systemColors, \"PressedButtonTextColor\");\n    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);\n    pressedButtonTextIndex = entry->index;\n    [pool drain];\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXRGBPixel --\n *\n *\tReturn an unsigned long value suitable for use in the pixel\n *\tfield of an XColor with the specified red, green and blue\n *\tintensities.  The inputs are cast as unsigned longs but are\n *      expected to have values representable by an unsigned char.\n *\n *      This is called in the TkpGetPixel macro, used in xcolor.c,\n *      and in ImageGetPixel.\n *\n * Results:\n *\tAn unsigned long that can be used as the pixel field of an XColor.\n *\n * Side effects:\n *\tNone.\n *----------------------------------------------------------------------\n */\nMODULE_SCOPE\nunsigned long\nTkMacOSXRGBPixel(\n    unsigned long red,\n    unsigned long green,\n    unsigned long blue)\n{\n    MacPixel p = {0};\n    p.pixel.colortype = rgbColor;\n    p.pixel.value = (unsigned int)(((red & 0xff) << 16)  |\n\t\t    ((green & 0xff) << 8) |\n\t\t    (blue & 0xff));\n    return p.ulong;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXClearPixel --\n *\n *\tReturn the unsigned long value that appears in the pixel\n *\tfield of the XColor for systemTransparentColor.\n *\n *      This is used in tkMacOSXImage.c.\n *\n * Results:\n *\tThe unsigned long that appears in the pixel field of the XColor\n *      for systemTransparentPixel.\n *\n * Side effects:\n *\tNone.\n *----------------------------------------------------------------------\n */\nMODULE_SCOPE\nunsigned long TkMacOSXClearPixel(\n    void)\n{\n    MacPixel p = {0};\n    p.pixel.value = 0;\n    p.pixel.colortype = clearColor;\n    return p.ulong;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetEntryFromPixel --\n *\n *\tLook up a SystemColorDatum which describes the XColor with\n *      the specified value as its pixel field.\n *\n * Results:\n *\tA pointer to a SystemColorDatum, or NULL if the pixel value is\n *\tinvalid.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nstatic SystemColorDatum*\nGetEntryFromPixel(\n    unsigned long pixel)\n{\n    MacPixel p = {0};\n    size_t index = rgbColorIndex;\n\n    p.ulong = pixel;\n    if (p.pixel.colortype != rgbColor) {\n\tindex = p.pixel.value;\n    }\n    if (index < numSystemColors) {\n\treturn systemColorIndex[index];\n    } else {\n\treturn NULL;\n    }\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * GetRGBA --\n *\n *\tGiven a SystemColorDatum and a pointer to an array of 4 CGFloats, store\n *      the associated RGBA color values in the array.  In the case of the\n *      RGBColor datum, the unsigned long pixel value containing the RGB values\n *      must also be provided as the pixel parameter.  Otherwise the pixel\n *      parameter is ignored.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe array rgba is filled in.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetRGBA(\n    SystemColorDatum *entry,\n    unsigned long pixel,\n    CGFloat *rgba,\n    BOOL useDarkAppearance)\n{\n    NSColor *bgColor, *color = nil;\n    int OSVersion = [NSApp macOSVersion];\n\n    if (!sRGB) {\n\tsRGB = [NSColorSpace sRGBColorSpace];\n    }\n\n    switch (entry->type) {\n    case rgbColor:\n\trgba[0] = ((pixel >> 16) & 0xff) / 255.0;\n\trgba[1] = ((pixel >>  8) & 0xff) / 255.0;\n\trgba[2] = ((pixel      ) & 0xff) / 255.0;\n\tbreak;\n    case ttkBackground:\n\n\t/*\n\t * Prior to OSX 10.14, getComponents returns black when applied to\n\t * windowBackgroundColor.\n\t */\n\n\tif ([NSApp macOSVersion] < 101400) {\n\t    for (int i = 0; i < 3; i++) {\n\t\trgba[i] = WINDOWBACKGROUND[i];\n\t    }\n\t} else {\n\t    bgColor = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t    [NSColor windowBackgroundColor], sRGB, useDarkAppearance);\n\t    [bgColor getComponents: rgba];\n\t}\n\tif (rgba[0] + rgba[1] + rgba[2] < 1.5) {\n\t    for (int i=0; i<3; i++) {\n\t\trgba[i] += entry->value*8.0 / 255.0;\n\t    }\n\t} else {\n\t    for (int i=0; i<3; i++) {\n\t\trgba[i] -= entry->value*8.0 / 255.0;\n\t    }\n\t}\n\tbreak;\n    case clearColor:\n\trgba[0] = rgba[1] = rgba[2] = 1.0;\n\trgba[3] = 0;\n\tbreak;\n    case semantic:\n\tif (entry->index == controlAccentIndex && useFakeAccentColor) {\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400\n\t    color = [[NSColor colorForControlTint: [NSColor currentControlTint]]\n\t\t\t      colorUsingColorSpace:sRGB];\n#endif\n\t} else if (entry->index == controlAlternatingRowIndex) {\n\t    /*\n\t     * Color which is now called alternatingContentBackgroundColor on 10.14.\n\t     * Taken from NSColor.controlAlternatingRowBackgroundColors (which was\n\t     * replaced by NSColor.alternatingContentBackgroundColors on 10.14).\n\t     */\n\t    color = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t    [NSColor colorWithCatalogName:@\"System\"\n\t\t\t\t\tcolorName:@\"controlAlternatingRowColor\"],\n\t\t    sRGB, useDarkAppearance);\n\t} else if (entry->index == selectedTabTextIndex) {\n\t    if (OSVersion > 100600 && OSVersion < 110000) {\n\t\tcolor = [[NSColor whiteColor] colorUsingColorSpace:sRGB];\n\t    } else {\n\t\tcolor = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t\t[NSColor textColor], sRGB, useDarkAppearance);\n\t    }\n\t} else if (entry->index == pressedButtonTextIndex) {\n\t    if (OSVersion < 120000) {\n\t\tcolor = [[NSColor whiteColor] colorUsingColorSpace:sRGB];\n\t    } else {\n\t\tcolor = [[NSColor blackColor] colorUsingColorSpace:sRGB];\n\t    }\n\t} else {\n\t    color = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t    [NSColor valueForKey:entry->selector], sRGB, useDarkAppearance);\n\t}\n\t[color getComponents: rgba];\n\tbreak;\n    default:\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetCGColorComponents --\n *\n *\tSet the components of a CGColorRef from an XColor pixel value and a\n *      SystemColorDatum.  The pixel value is only used in the case where\n *      the color is of type rgbColor.  In that case the normalized XColor RGB\n *      values are copied into the CGColorRef.  Otherwise the components are\n *      computed from the SystemColorDatum.\n *\n * Results:\n *\tTrue if the function succeeds, false otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nSetCGColorComponents(\n    SystemColorDatum *entry,\n    unsigned long pixel,\n    CGColorRef *c,\n    BOOL useDarkAppearance)\n{\n    CGFloat rgba[4] = {0, 0, 0, 1};\n\n    if (entry->type == HIBrush) {\n\tOSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c);\n\treturn err == noErr;\n    }\n\n    /*\n     * This function is called before our autorelease pool is set up,\n     * so it needs its own pool.\n     */\n\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n\n    GetRGBA(entry, pixel, rgba, useDarkAppearance);\n    *c = CGColorCreate(sRGB.CGColorSpace, rgba);\n    [pool drain];\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInDarkMode --\n *\n *      Tests whether the given window's NSView has a DarkAqua Appearance.\n *\n * Results:\n *      Returns true if the NSView is in DarkMode, false if not.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE bool\nTkMacOSXInDarkMode(Tk_Window tkwin)\n{\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n    if (@available(macOS 10.14, *)) {\n\tTkWindow *winPtr = (TkWindow*) tkwin;\n\tNSAppearanceName name;\n\tNSView *view = nil;\n\tif (winPtr && winPtr->privatePtr) {\n\t    view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr);\n\t}\n\tif (view) {\n\t    name = [[view effectiveAppearance] name];\n\t} else {\n\t    name = [[NSApp effectiveAppearance] name];\n\t}\n\treturn (name == NSAppearanceNameDarkAqua);\n    }\n#else\n    (void) tkwin;\n#endif\n    return false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetMacColor --\n *\n *\tSets the components of a CGColorRef from an XColor pixel value.  The\n *      pixel value is used to look up the color in the system color table, and\n *      then SetCGColorComponents is called with the table entry and the pixel\n *      value.  The parameter macColor should be a pointer to a CGColorRef.\n *\n * Results:\n *      Returns false if the color is not found, true otherwise.\n *\n * Side effects:\n *\tThe CGColorRef referenced by the variable macColor may be modified.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkSetMacColor(\n    unsigned long pixel,\t/* Pixel value to convert. */\n    void *macColor)\t\t/* CGColorRef to modify. */\n{\n    // Arbitrary; existing usage of TkSetMacColor() does not\n    // seem to depend on appearance\n    BOOL useDarkAppearance = NO;\n\n    return TkSetMacColor2(pixel, (CGColorRef *)macColor, useDarkAppearance);\n}\nbool\nTkSetMacColor2(\n    unsigned long pixel,\t/* Pixel value to convert. */\n    CGColorRef *color,\t\t/* CGColorRef to modify. */\n    BOOL useDarkAppearance)\n{\n    SystemColorDatum *entry = GetEntryFromPixel(pixel);\n\n    if (entry) {\n\treturn SetCGColorComponents(entry, pixel, color, useDarkAppearance);\n    } else {\n\treturn false;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNSColor --\n *\n *\tCreates an autoreleased NSColor from a X style pixel value.\n *      The return value is nil if the pixel value is invalid.\n *\n * Results:\n *\tA possibly nil pointer to an NSColor.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nNSColor*\nTkMacOSXGetNSColor(\n    TCL_UNUSED(GC),\n    unsigned long pixel)\t\t/* Pixel value to convert. */\n{\n    CGColorRef cgColor = NULL;\n    NSColor *nsColor = nil;\n\n    TkSetMacColor(pixel, &cgColor);\n    if (cgColor) {\n\tnsColor = [NSColor colorWithColorSpace:sRGB\n\t\t\tcomponents:CGColorGetComponents(cgColor)\n\t\t\tcount:(NSInteger)CGColorGetNumberOfComponents(cgColor)];\n\tCGColorRelease(cgColor);\n    }\n    return nsColor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSetColorInContext --\n *\n *\tSets the fill and stroke colors in the given CGContext to the CGColor\n *\twhich corresponds to the XColor having the specified value for its pixel\n *\tfield.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXSetColorInContext(\n    TCL_UNUSED(GC),\n    unsigned long pixel,\n    CGContextRef context,\n    BOOL useDarkAppearance)\n{\n    OSStatus err = noErr;\n    CGColorRef cgColor = NULL;\n    SystemColorDatum *entry = GetEntryFromPixel(pixel);\n\n    if (entry) {\n\tswitch (entry->type) {\n\tcase HIBrush:\n\t    err = ChkErr(HIThemeSetFill, entry->value, NULL, context,\n\t\t    kHIThemeOrientationNormal);\n\t    if (err == noErr) {\n\t\terr = ChkErr(HIThemeSetStroke, entry->value, NULL, context,\n\t\t\tkHIThemeOrientationNormal);\n\t    }\n\t    break;\n\tdefault:\n\t    SetCGColorComponents(entry, pixel, &cgColor, useDarkAppearance);\n\t    break;\n\t}\n    }\n    if (cgColor) {\n\tCGContextSetFillColorWithColor(context, cgColor);\n\tCGContextSetStrokeColorWithColor(context, cgColor);\n\tCGColorRelease(cgColor);\n    }\n    if (err != noErr) {\n\tTkMacOSXDbgMsg(\"Ignored unknown pixel value 0x%lx\", pixel);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColor --\n *\n *\tCreate a new TkColor for the color with the given name, for use in the\n *      specified window.\n *\n *      This function is called by Tk_GetColor.\n *\n * Results:\n *\tReturns a newly allocated TkColor, or NULL on failure.\n *\n * Side effects:\n *\n *\tAllocates memory for the TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColor(\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    const char *name)\t\t/* Name of color to be allocated (in form\n\t\t\t\t * suitable for passing to XParseColor). */\n{\n    Display *display = NULL;\n    TkColor *tkColPtr;\n    XColor color;\n    Colormap colormap = TK_DYNAMIC_COLORMAP;\n    bool haveValidXColor = false;\n    static bool initialized = false;\n\n    if (!initialized) {\n\tinitialized = true;\n\tinitColorTable();\n    }\n    if (tkwin) {\n\tdisplay = Tk_Display(tkwin);\n    }\n\n    /*\n     * Check to see if this is a system color. If not, just call XParseColor.\n     */\n\n    if (strncasecmp(name, \"system\", 6) == 0) {\n\tTcl_HashEntry *hPtr = Tcl_FindHashEntry(&systemColors, name + 6);\n\tMacPixel p = {0};\n\n\tif (hPtr != NULL) {\n\t    SystemColorDatum *entry = (SystemColorDatum *)Tcl_GetHashValue(hPtr);\n\t    CGColorRef c = NULL;\n\t    BOOL windowAppearanceIsDark = TkMacOSXInDarkMode(tkwin);\n\n\t    p.pixel.colortype = entry->type;\n\t    p.pixel.value = (unsigned int)entry->index;\n\t    color.pixel = p.ulong;\n\t    if (entry->type == semantic) {\n\t\tCGFloat rgba[4];\n\t\tGetRGBA(entry, p.ulong, rgba, windowAppearanceIsDark);\n\t\tcolor.red   = (unsigned short)(rgba[0] * 65535.0);\n\t\tcolor.green = (unsigned short)(rgba[1] * 65535.0);\n\t\tcolor.blue  = (unsigned short)(rgba[2] * 65535.0);\n\t\thaveValidXColor = True;\n\t    } else if (SetCGColorComponents(entry, 0, &c, windowAppearanceIsDark)) {\n\t\tconst size_t n = CGColorGetNumberOfComponents(c);\n\t\tconst CGFloat *rgba = CGColorGetComponents(c);\n\n\t\tswitch (n) {\n\t\tcase 4:\n\t\t    color.red   = (unsigned short)(rgba[0] * 65535.0);\n\t\t    color.green = (unsigned short)(rgba[1] * 65535.0);\n\t\t    color.blue  = (unsigned short)(rgba[2] * 65535.0);\n\t\t    break;\n\t\tcase 2:\n\t\t    color.red = color.green = color.blue = (unsigned short)(rgba[0] * 65535.0);\n\t\t    break;\n\t\tdefault:\n\t\t    Tcl_Panic(\"CGColor with %d components\", (int) n);\n\t\t}\n\t\tCGColorRelease(c);\n\t\thaveValidXColor = true;\n\t    }\n\t}\n    }\n    if (!haveValidXColor && TkParseColor(display, colormap, name, &color) == 0) {\n\treturn NULL;\n    }\n\n    tkColPtr = (TkColor *)Tcl_Alloc(sizeof(TkColor));\n    tkColPtr->colormap = colormap;\n    tkColPtr->color = color;\n    return tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColorByValue --\n *\n *\tGiven an pointer to an XColor, construct a TkColor whose red, green and\n *\tblue intensities match those of the XColor as closely as possible.  For\n *\tthe Macintosh, this means that the colortype bitfield of the pixel\n *\tvalue will be RGBColor and that the color intensities stored in its\n *\t24-bit value bitfield are computed from the 16-bit red green and blue\n *\tvalues in the XColor by dividing by 256.\n *\n * Results:\n *\tA pointer to a newly allocated TkColor structure.\n *\n * Side effects:\n *\tMay invalidate the colormap cache for the specified window.\n *\tAllocates memory for a TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColorByValue(\n    TCL_UNUSED(Tk_Window),\t\t/* Window in which color will be used. */\n    XColor *colorPtr)\t\t/* Red, green, and blue fields indicate\n\t\t\t\t * desired color. */\n{\n    TkColor *tkColPtr = (TkColor *)Tcl_Alloc(sizeof(TkColor));\n\n    tkColPtr->color.red = colorPtr->red;\n    tkColPtr->color.green = colorPtr->green;\n    tkColPtr->color.blue = colorPtr->blue;\n    tkColPtr->color.pixel = TkpGetPixel(colorPtr);\n    return tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Stub functions --\n *\n *\tThese functions are just stubs for functions that either\n *\tdon't make sense on the Mac or have yet to be implemented.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThese calls do nothing - which may not be expected.\n *\n *----------------------------------------------------------------------\n */\n\nStatus\nXAllocColor(\n    Display *display,\t\t/* Display. */\n    TCL_UNUSED(Colormap),\t\t/* Not used. */\n    XColor *colorPtr)\t\t/* XColor struct to modify. */\n{\n    LastKnownRequestProcessed(display)++;\n    colorPtr->pixel = TkpGetPixel(colorPtr);\n    return 1;\n}\n\nColormap\nXCreateColormap(\n    TCL_UNUSED(Display *),\t\t/* Display. */\n    TCL_UNUSED(Window),\t\t/* X window. */\n    TCL_UNUSED(Visual *),\t\t/* Not used. */\n    TCL_UNUSED(int))\t\t\t/* Not used. */\n{\n    static Colormap index = 16;\n\n    /*\n     * Just return a new value each time, large enough that it will not\n     * conflict with any value of the macColormap enum.\n     */\n    return index++;\n}\n\nint\nXFreeColormap(\n    TCL_UNUSED(Display *),\t\t/* Display. */\n    TCL_UNUSED(Colormap))\t\t/* Colormap. */\n{\n    return Success;\n}\n\nint\nXFreeColors(\n    TCL_UNUSED(Display *),\t\t/* Display. */\n    TCL_UNUSED(Colormap),\t\t/* Colormap. */\n    TCL_UNUSED(unsigned long *),\t/* Array of pixels. */\n    TCL_UNUSED(int),\t\t/* Number of pixels. */\n    TCL_UNUSED(unsigned long))\t/* Number of pixel planes. */\n{\n    /*\n     * Nothing needs to be done to release colors as there really is no\n     * colormap in the Tk sense.\n     */\n    return Success;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXColor.h",
    "content": "#ifndef MACOSXCOLOR_H\n#define MACOSXCOLOR_H\n/*\n * The generic Tk code uses the X11 GC type to describe a graphics context.\n * (A GC is a pointer to a struct XGCValues).  The foreground and background\n * colors in a GC are unsigned longs.  These are meant to be used as indexes\n * into a table of XColors, where an XColor is declared in Xlib.h as:\n * typedef struct {\n *       unsigned long pixel;\n *       unsigned short red, green, blue;\n *       char flags;\n *       char pad;\n * } XColor;\n *\n * The xlib function XParseColor creates XColors from strings.  It recognizes\n * literal hexadecimal color specifications such as \"#RRGGBB\" as well as the\n * standard X11 color names.  When XParseColor creates an XColor it fills in\n * all of the fields except for the pixel field, and then passes the XColor\n * to TkpGetPixel to get a value to use for the pixel field. Since TkpGetPixel\n * is platform specific, each platform is free to choose a value which can\n * be used to set the foreground or background color in the platform's graphics\n * context.\n *\n * Tk represents a color by a struct TkColor, which extends the XColor struct.\n * Tk provides a mapping from color names to TkColors which extends the mapping\n * provided by XParseColor but also allows for platform specific color names.\n * By convention, these platform specific color names begin with the string\n * \"system\".  The mapping from names to TkColors is implemented by the function\n * TkpGetColor defined for the Macintosh in this file.  The pixel field in the\n * XColor contained in a TkColor will be stored in the X11 graphics context.\n * In X11 the pixel field is used as an index into a colormap.  On the Mac\n * the high order byte of the pixel is used to indicate a color type and\n * the low 24 bits are either used as an rgb value (if the type is rgbColor)\n * or as an index into a table of color descriptions.\n */\n\nenum colorType {\n    rgbColor,      /* The 24 bit value is an rgb color. */\n    clearColor,    /* The unique rgba color with all channels 0. */\n    HIBrush,       /* A HITheme brush color.*/\n    ttkBackground, /* A background color which indicates nesting level.*/\n    semantic,      /* A semantic NSColor.*/\n};\n\ntypedef struct xpixel_t {\n    unsigned value: 24;     /* Either RGB or an index into systemColorData. */\n    unsigned colortype: 8;\n} xpixel;\n\ntypedef union MacPixel_t {\n    unsigned long ulong;\n    xpixel pixel;\n} MacPixel;\n\n/*\n * In TkMacOSXColor.c a Tk hash table is constructed from the static data\n * below to map system color names to CGColors.\n */\n\ntypedef struct {\n    const char *name;\n    enum colorType type;\n    ThemeBrush value;\n    const char *macName;\n    /* Fields below are filled in after or during construction of the hash table. */\n    size_t index;\n    NSString *selector;\n} SystemColorDatum;\n\n/*\n * WARNING: Semantic colors which are not supported on all systems must be\n * preceded by a backup color with the same name which *is* supported.  Systems\n * which do support the color will replace the backup value when the table is\n * constructed.  Failing to ensure this will result in a Tcl_Panic abort.\n */\n\nstatic SystemColorDatum systemColorData[] = {\n{\"Pixel\",\t\t\t\trgbColor, 0, NULL, 0, NULL },\n{\"Transparent\",\t\t\t\t\tclearColor,   0, NULL, 0, NULL },\n\n{\"Highlight\",\t\t\t\tHIBrush,  kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },\n{\"HighlightSecondary\",\t\t\tHIBrush,  kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },\n{\"HighlightText\",\t\t\tHIBrush,  kThemeBrushBlack, NULL, 0, NULL },\n{\"HighlightAlternate\",\t\t\tHIBrush,  kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },\n{\"PrimaryHighlightColor\",\t\tHIBrush,  kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },\n{\"ButtonFace\",\t\t\t\tHIBrush,  kThemeBrushButtonFaceActive, NULL, 0, NULL },\n{\"SecondaryHighlightColor\",\t\tHIBrush,  kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },\n{\"ButtonFrame\",\t\t\t\tHIBrush,  kThemeBrushButtonFrameActive, NULL, 0, NULL },\n{\"AlternatePrimaryHighlightColor\",      HIBrush,  kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },\n{\"WindowBody\",\t\t\t\tHIBrush,  kThemeBrushDocumentWindowBackground, NULL, 0, NULL },\n{\"SheetBackground\",\t\t\tHIBrush,  kThemeBrushSheetBackground, NULL, 0, NULL },\n{\"MenuActive\",\t\t\t\tHIBrush,  kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },\n{\"Menu\",\t\t\t\tHIBrush,  kThemeBrushMenuBackground, NULL, 0, NULL },\n{\"DialogBackgroundInactive\",\t\tHIBrush,  kThemeBrushDialogBackgroundInactive, NULL, 0, NULL },\n{\"DialogBackgroundActive\",\t\tHIBrush,  kThemeBrushDialogBackgroundActive, NULL, 0, NULL },\n{\"AlertBackgroundActive\",\t\tHIBrush,  kThemeBrushAlertBackgroundActive, NULL, 0, NULL },\n{\"AlertBackgroundInactive\",\t\tHIBrush,  kThemeBrushAlertBackgroundInactive, NULL, 0, NULL },\n{\"ModelessDialogBackgroundActive\",\tHIBrush,  kThemeBrushModelessDialogBackgroundActive, NULL, 0, NULL },\n{\"ModelessDialogBackgroundInactive\",\tHIBrush,  kThemeBrushModelessDialogBackgroundInactive, NULL, 0, NULL },\n{\"UtilityWindowBackgroundActive\",\tHIBrush,  kThemeBrushUtilityWindowBackgroundActive, NULL, 0, NULL },\n{\"UtilityWindowBackgroundInactive\",\tHIBrush,  kThemeBrushUtilityWindowBackgroundInactive, NULL, 0, NULL },\n{\"ListViewSortColumnBackground\",\tHIBrush,  kThemeBrushListViewSortColumnBackground, NULL, 0, NULL },\n{\"ListViewBackground\",\t\t\tHIBrush,  kThemeBrushListViewBackground, NULL, 0, NULL },\n{\"IconLabelBackground\",\t\t\tHIBrush,  kThemeBrushIconLabelBackground, NULL, 0, NULL },\n{\"ListViewSeparator\",\t\t\tHIBrush,  kThemeBrushListViewSeparator, NULL, 0, NULL },\n{\"ChasingArrows\",\t\t\tHIBrush,  kThemeBrushChasingArrows, NULL, 0, NULL },\n{\"DragHilite\",\t\t\t\tHIBrush,  kThemeBrushDragHilite, NULL, 0, NULL },\n{\"DocumentWindowBackground\",\t\tHIBrush,  kThemeBrushDocumentWindowBackground, NULL, 0, NULL },\n{\"FinderWindowBackground\",\t\tHIBrush,  kThemeBrushFinderWindowBackground, NULL, 0, NULL },\n{\"ScrollBarDelimiterActive\",\t\tHIBrush,  kThemeBrushScrollBarDelimiterActive, NULL, 0, NULL },\n{\"ScrollBarDelimiterInactive\",\t\tHIBrush,  kThemeBrushScrollBarDelimiterInactive, NULL, 0, NULL },\n{\"FocusHighlight\",\t\t\tHIBrush,  kThemeBrushFocusHighlight, NULL, 0, NULL },\n{\"PopupArrowActive\",\t\t\tHIBrush,  kThemeBrushPopupArrowActive, NULL, 0, NULL },\n{\"PopupArrowPressed\",\t\t\tHIBrush,  kThemeBrushPopupArrowPressed, NULL, 0, NULL },\n{\"PopupArrowInactive\",\t\t\tHIBrush,  kThemeBrushPopupArrowInactive, NULL, 0, NULL },\n{\"AppleGuideCoachmark\",\t\t\tHIBrush,  kThemeBrushAppleGuideCoachmark, NULL, 0, NULL },\n{\"IconLabelBackgroundSelected\",\t\tHIBrush,  kThemeBrushIconLabelBackgroundSelected, NULL, 0, NULL },\n{\"StaticAreaFill\",\t\t\tHIBrush,  kThemeBrushStaticAreaFill, NULL, 0, NULL },\n{\"ActiveAreaFill\",\t\t\tHIBrush,  kThemeBrushActiveAreaFill, NULL, 0, NULL },\n{\"ButtonFrameActive\",\t\t\tHIBrush,  kThemeBrushButtonFrameActive, NULL, 0, NULL },\n{\"ButtonFrameInactive\",\t\t\tHIBrush,  kThemeBrushButtonFrameInactive, NULL, 0, NULL },\n{\"ButtonFaceActive\",\t\t\tHIBrush,  kThemeBrushButtonFaceActive, NULL, 0, NULL },\n{\"ButtonFaceInactive\",\t\t\tHIBrush,  kThemeBrushButtonFaceInactive, NULL, 0, NULL },\n{\"ButtonFacePressed\",\t\t\tHIBrush,  kThemeBrushButtonFacePressed, NULL, 0, NULL },\n{\"ButtonActiveDarkShadow\",\t\tHIBrush,  kThemeBrushButtonActiveDarkShadow, NULL, 0, NULL },\n{\"ButtonActiveDarkHighlight\",\t\tHIBrush,  kThemeBrushButtonActiveDarkHighlight, NULL, 0, NULL },\n{\"ButtonActiveLightShadow\",\t\tHIBrush,  kThemeBrushButtonActiveLightShadow, NULL, 0, NULL },\n{\"ButtonActiveLightHighlight\",\t\tHIBrush,  kThemeBrushButtonActiveLightHighlight, NULL, 0, NULL },\n{\"ButtonInactiveDarkShadow\",\t\tHIBrush,  kThemeBrushButtonInactiveDarkShadow, NULL, 0, NULL },\n{\"ButtonInactiveDarkHighlight\",\t\tHIBrush,  kThemeBrushButtonInactiveDarkHighlight, NULL, 0, NULL },\n{\"ButtonInactiveLightShadow\",\t\tHIBrush,  kThemeBrushButtonInactiveLightShadow, NULL, 0, NULL },\n{\"ButtonInactiveLightHighlight\",\tHIBrush,  kThemeBrushButtonInactiveLightHighlight, NULL, 0, NULL },\n{\"ButtonPressedDarkShadow\",\t\tHIBrush,  kThemeBrushButtonPressedDarkShadow, NULL, 0, NULL },\n{\"ButtonPressedDarkHighlight\",\t\tHIBrush,  kThemeBrushButtonPressedDarkHighlight, NULL, 0, NULL },\n{\"ButtonPressedLightShadow\",\t\tHIBrush,  kThemeBrushButtonPressedLightShadow, NULL, 0, NULL },\n{\"ButtonPressedLightHighlight\",\t\tHIBrush,  kThemeBrushButtonPressedLightHighlight, NULL, 0, NULL },\n{\"BevelActiveLight\",\t\t\tHIBrush,  kThemeBrushBevelActiveLight, NULL, 0, NULL },\n{\"BevelActiveDark\",\t\t\tHIBrush,  kThemeBrushBevelActiveDark, NULL, 0, NULL },\n{\"BevelInactiveLight\",\t\t\tHIBrush,  kThemeBrushBevelInactiveLight, NULL, 0, NULL },\n{\"BevelInactiveDark\",\t\t\tHIBrush,  kThemeBrushBevelInactiveDark, NULL, 0, NULL },\n{\"NotificationWindowBackground\",\tHIBrush,  kThemeBrushNotificationWindowBackground, NULL, 0, NULL },\n{\"MovableModalBackground\",\t\tHIBrush,  kThemeBrushMovableModalBackground, NULL, 0, NULL },\n{\"SheetBackgroundOpaque\",\t\tHIBrush,  kThemeBrushSheetBackgroundOpaque, NULL, 0, NULL },\n{\"DrawerBackground\",\t\t\tHIBrush,  kThemeBrushDrawerBackground, NULL, 0, NULL },\n{\"ToolbarBackground\",\t\t\tHIBrush,  kThemeBrushToolbarBackground, NULL, 0, NULL },\n{\"SheetBackgroundTransparent\",\t\tHIBrush,  kThemeBrushSheetBackgroundTransparent, NULL, 0, NULL },\n{\"MenuBackground\",\t\t\tHIBrush,  kThemeBrushMenuBackground, NULL, 0, NULL },\n{\"MenuBackgroundSelected\",\t\tHIBrush,  kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },\n{\"ListViewOddRowBackground\",\t\tHIBrush,  kThemeBrushListViewOddRowBackground, NULL, 0, NULL },\n{\"ListViewEvenRowBackground\",\t\tHIBrush,  kThemeBrushListViewEvenRowBackground, NULL, 0, NULL },\n{\"ListViewColumnDivider\",\t\tHIBrush,  kThemeBrushListViewColumnDivider, NULL, 0, NULL },\n\n    /*\n     * Dynamic Colors\n     */\n\n{\"WindowBackgroundColor\",\t    ttkBackground, 0, NULL, 0, NULL },\n{\"WindowBackgroundColor1\",\t    ttkBackground, 1, NULL, 0, NULL },\n{\"WindowBackgroundColor2\",\t    ttkBackground, 2, NULL, 0, NULL },\n{\"WindowBackgroundColor3\",\t    ttkBackground, 3, NULL, 0, NULL },\n{\"WindowBackgroundColor4\",\t    ttkBackground, 4, NULL, 0, NULL },\n{\"WindowBackgroundColor5\",\t    ttkBackground, 5, NULL, 0, NULL },\n{\"WindowBackgroundColor6\",\t    ttkBackground, 6, NULL, 0, NULL },\n{\"WindowBackgroundColor7\",\t    ttkBackground, 7, NULL, 0, NULL },\n/* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */\n{\"SecondaryLabelColor\",\t\t    ttkBackground, 14, NULL, 0, NULL },\n/* Color to use for notebook tab label text -- depends on OS version. */\n{\"SelectedTabTextColor\",\t    semantic, 0, \"textColor\", 0, NULL },\n/* Color to use for selected button labels -- depends on OS version. */\n{\"PressedButtonTextColor\",\t    semantic, 0, \"textColor\", 0, NULL },\n/* Semantic colors that we simulate on older systems which don't supoort them. */\n{\"SelectedMenuItemTextColor\",       semantic, 0, \"selectedMenuItemTextColor\", 0, NULL },\n{\"ControlAccentColor\",\t\t    semantic, 0, \"controlAccentColor\", 0, NULL },\n{\"LabelColor\",                      semantic, 0, \"blackColor\", 0, NULL },\n{\"LinkColor\",\t\t\t    semantic, 0, \"blueColor\", 0, NULL },\n{\"PlaceholderTextColor\",\t    semantic, 0, \"grayColor\", 0, NULL },\n{\"SeparatorColor\",\t\t    semantic, 0, \"grayColor\", 0, NULL },\n{\"UnemphasizedSelectedTextBackgroundColor\", semantic, 0, \"grayColor\", 0, NULL },\n/* This color is available since 10.3, so the fallback is unused */\n{\"ControlAlternatingRowColor\",\t    semantic, 0, \"grayColor\" , 0, NULL },\n{NULL,\t\t\t\t    rgbColor, 0, NULL, 0, NULL }\n};\n\n#endif\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXConfig.c",
    "content": "/*\n * tkMacOSXConfig.c --\n *\n *\tThis module implements the Macintosh system defaults for\n *\tthe configuration package.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n * Copyright © 2001 Apple Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetSystemDefault --\n *\n *\tGiven a dbName and className for a configuration option,\n *\treturn a string representation of the option.\n *\n * Results:\n *\tReturns a Tcl_Obj* with the string identifier that identifies\n *\tthis option. Returns NULL if there are no system defaults\n *\tthat match this pair.\n *\n * Side effects:\n *\tNone, once the package is initialized.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_GetSystemDefault(\n    TCL_UNUSED(Tk_Window),\t\t\t/* A window to use. */\n    TCL_UNUSED(const char *),\t\t\t/* The option database name. */\n    TCL_UNUSED(const char *))\t\t/* The name of the option class. */\n{\n    return NULL;\n}\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXConstants.h",
    "content": "/*\n * tkMacOSXConstants.h --\n *\n *\tMacros which map the names of NS constants used in the Tk code to\n *      the new name that Apple came up with for subsequent versions of the\n *      operating system.  (Each new OS release seems to come with a new\n *      naming convention for the same old constants.)\n *\n * Copyright © 2017 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACCONSTANTS\n#define _TKMACCONSTANTS\n\n/*\n * Let's raise a glass for the project manager who improves our lives by\n * generating deprecation warnings about pointless changes of the names\n * of constants.\n */\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000\n#define NSOKButton NSModalResponseOK\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101100\n#define kCTFontUserFixedPitchFontType kCTFontUIFontUserFixedPitch\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200\n#define NSAppKitDefined NSEventTypeAppKitDefined\n#define NSApplicationDefined NSEventTypeApplicationDefined\n#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated\n#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated\n#define NSWindowExposedEventType NSEventSubtypeWindowExposed\n#define NSScreenChangedEventType NSEventSubtypeScreenChanged\n#define NSWindowMovedEventType NSEventSubtypeWindowMoved\n#define NSKeyUp NSEventTypeKeyUp\n#define NSKeyDown NSEventTypeKeyDown\n#define NSFlagsChanged NSEventTypeFlagsChanged\n#define NSLeftMouseDown NSEventTypeLeftMouseDown\n#define NSLeftMouseUp NSEventTypeLeftMouseUp\n#define NSRightMouseDown NSEventTypeRightMouseDown\n#define NSRightMouseUp NSEventTypeRightMouseUp\n#define NSLeftMouseDragged NSEventTypeLeftMouseDragged\n#define NSRightMouseDragged NSEventTypeRightMouseDragged\n#define NSMouseMoved NSEventTypeMouseMoved\n#define NSMouseEntered NSEventTypeMouseEntered\n#define NSMouseExited NSEventTypeMouseExited\n#define NSScrollWheel NSEventTypeScrollWheel\n#define NSOtherMouseDown NSEventTypeOtherMouseDown\n#define NSOtherMouseUp NSEventTypeOtherMouseUp\n#define NSOtherMouseDragged NSEventTypeOtherMouseDragged\n#define NSTabletPoint NSEventTypeTabletPoint\n#define NSTabletProximity NSEventTypeTabletProximity\n#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask\n#define NSCommandKeyMask NSEventModifierFlagCommand\n#define NSShiftKeyMask NSEventModifierFlagShift\n#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock\n#define NSAlternateKeyMask NSEventModifierFlagOption\n#define NSControlKeyMask NSEventModifierFlagControl\n#define NSNumericPadKeyMask NSEventModifierFlagNumericPad\n#define NSFunctionKeyMask NSEventModifierFlagFunction\n#define NSCursorUpdate NSEventTypeCursorUpdate\n#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground\n#define NSCompositeCopy NSCompositingOperationCopy\n#define NSCompositeSourceOver NSCompositingOperationSourceOver\n#define NSCompositeSourceAtop NSCompositingOperationSourceAtop\n#define NSCompositeDestinationIn NSCompositingOperationDestinationIn\n#define NSWarningAlertStyle NSAlertStyleWarning\n#define NSInformationalAlertStyle NSAlertStyleInformational\n#define NSCriticalAlertStyle NSAlertStyleCritical\n#define NSCenterTextAlignment NSTextAlignmentCenter\n#define NSApplicationDefinedMask NSEventMaskApplicationDefined\n#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow\n#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel\n#define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow\n#define NSHUDWindowMask NSWindowStyleMaskHUDWindow\n#define NSTitledWindowMask NSWindowStyleMaskTitled\n#define NSClosableWindowMask NSWindowStyleMaskClosable\n#define NSResizableWindowMask NSWindowStyleMaskResizable\n#define NSUnifiedTitleAndToolbarWindowMask NSWindowStyleMaskUnifiedTitleAndToolbar\n#define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable\n#define NSBorderlessWindowMask NSWindowStyleMaskBorderless\n#define NSFullScreenWindowMask NSWindowStyleMaskFullScreen\n#define NSAlphaFirstBitmapFormat NSBitmapFormatAlphaFirst\n#define NSAnyEventMask NSEventMaskAny\n#define NSLeftMouseDownMask NSEventMaskLeftMouseDown\n#define NSMouseMovedMask NSEventMaskMouseMoved\n#define NSLeftMouseDraggedMask NSEventMaskLeftMouseDragged\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400\n#define NSStringPboardType NSPasteboardTypeString\n#define NSOnState NSControlStateValueOn\n#define NSOffState NSControlStateValueOff\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000\n#define NSWindowStyleMaskTexturedBackground 0\n#endif\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000\n#define GET_NSCONTEXT(context, flip) [NSGraphicsContext\t\t\\\n\t    graphicsContextWithGraphicsPort:context flipped:flip]\n#else\n#define GET_NSCONTEXT(context, flip) [NSGraphicsContext\t\t\\\n\t    graphicsContextWithCGContext:context flipped:NO]\n#endif\n\n#endif\n"
  },
  {
    "path": "macosx/tkMacOSXCursor.c",
    "content": "/*\n * tkMacOSXCursor.c --\n *\n *\tThis file contains Macintosh specific cursor related routines.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXCursors.h\"\n#include \"tkMacOSXXCursors.h\"\n\n/*\n * Mac Cursor Types.\n */\n\n#define NONE\t\t-1\t/* Hidden cursor */\n#define SELECTOR\t1\t/* NSCursor class method */\n#define IMAGENAMED\t2\t/* Named NSImage */\n#define IMAGEPATH\t3\t/* Path to NSImage */\n#define IMAGEBITMAP\t4\t/* Pointer to 16x16 cursor bitmap data */\n\n#define pix\t\t16\t/* Pixel width & height of cursor bitmap data */\n\n/*\n * The following data structure contains the system specific data necessary to\n * control Windows cursors.\n */\n\ntypedef struct {\n    TkCursor info;\t\t/* Generic cursor info used by tkCursor.c */\n    NSCursor *macCursor;\t/* Macintosh cursor */\n    int type;\t\t\t/* Type of Mac cursor */\n} TkMacOSXCursor;\n\n/*\n * The table below is used to map from the name of a predefined cursor\n * to a NSCursor.\n */\n\nstruct CursorName {\n    const char *name;\n    const int kind;\n    id id1, id2;\n    NSPoint hotspot;\n};\n\n#define MacCursorData(n)\t((id)tkMacOSXCursors[TK_MAC_CURSOR_##n])\n#define MacXCursorData(n)\t((id)tkMacOSXXCursors[TK_MAC_XCURSOR_##n])\n\nstatic const struct CursorName cursorNames[] = {\n    {\"none\",\t\t\tNONE,\t    nil, nil, {0, 0}},\n    {\"arrow\",\t\t\tSELECTOR,    @\"arrowCursor\", nil, {0, 0}},\n    {\"top_left_arrow\",\t\tSELECTOR,    @\"arrowCursor\", nil, {0, 0}},\n    {\"left_ptr\",\t\tSELECTOR,    @\"arrowCursor\", nil, {0, 0}},\n    {\"copyarrow\",\t\tSELECTOR,    @\"dragCopyCursor\", @\"_copyDragCursor\", {0, 0}},\n    {\"aliasarrow\",\t\tSELECTOR,    @\"dragLinkCursor\", @\"_linkDragCursor\", {0, 0}},\n    {\"contextualmenuarrow\",\tSELECTOR,    @\"contextualMenuCursor\", nil, {0, 0}},\n    {\"movearrow\",\t\tSELECTOR,    @\"_moveCursor\", nil, {0, 0}},\n    {\"ibeam\",\t\t\tSELECTOR,    @\"IBeamCursor\", nil, {0, 0}},\n    {\"text\",\t\t\tSELECTOR,    @\"IBeamCursor\", nil, {0, 0}},\n    {\"xterm\",\t\t\tSELECTOR,    @\"IBeamCursor\", nil, {0, 0}},\n    {\"cross\",\t\t\tSELECTOR,    @\"crosshairCursor\", nil, {0, 0}},\n    {\"crosshair\",\t\tSELECTOR,    @\"crosshairCursor\", nil, {0, 0}},\n    {\"cross-hair\",\t\tSELECTOR,    @\"crosshairCursor\", nil, {0, 0}},\n    {\"tcross\",\t\t\tSELECTOR,    @\"crosshairCursor\", nil, {0, 0}},\n    {\"hand\",\t\t\tSELECTOR,    @\"openHandCursor\", nil, {0, 0}},\n    {\"openhand\",\t\tSELECTOR,    @\"openHandCursor\", nil, {0, 0}},\n    {\"closedhand\",\t\tSELECTOR,    @\"closedHandCursor\", nil, {0, 0}},\n    {\"fist\",\t\t\tSELECTOR,    @\"closedHandCursor\", nil, {0, 0}},\n    {\"pointinghand\",\t\tSELECTOR,    @\"pointingHandCursor\", nil, {0, 0}},\n    {\"resize\",\t\t\tSELECTOR,    @\"arrowCursor\", nil, {0, 0}},\n    {\"resizeleft\",\t\tSELECTOR,    @\"resizeLeftCursor\", nil, {0, 0}},\n    {\"resizeright\",\t\tSELECTOR,    @\"resizeRightCursor\", nil, {0, 0}},\n    {\"resizeleftright\",\t\tSELECTOR,    @\"resizeLeftRightCursor\", nil, {0, 0}},\n    {\"resizeup\",\t\tSELECTOR,    @\"resizeUpCursor\", nil, {0, 0}},\n    {\"resizedown\",\t\tSELECTOR,    @\"resizeDownCursor\", nil, {0, 0}},\n    {\"resizeupdown\",\t\tSELECTOR,    @\"resizeUpDownCursor\", nil, {0, 0}},\n    {\"resizebottomleft\",\tSELECTOR,    @\"_bottomLeftResizeCursor\", nil, {0, 0}},\n    {\"resizetopleft\",\t\tSELECTOR,    @\"_topLeftResizeCursor\", nil, {0, 0}},\n    {\"resizebottomright\",\tSELECTOR,    @\"_bottomRightResizeCursor\", nil, {0, 0}},\n    {\"resizetopright\",\t\tSELECTOR,    @\"_topRightResizeCursor\", nil, {0, 0}},\n    {\"notallowed\",\t\tSELECTOR,    @\"operationNotAllowedCursor\", nil, {0, 0}},\n    {\"poof\",\t\t\tSELECTOR,    @\"disappearingItemCursor\", nil, {0, 0}},\n    {\"wait\",\t\t\tSELECTOR,    @\"busyButClickableCursor\", nil, {0, 0}},\n    {\"spinning\",\t\tSELECTOR,    @\"busyButClickableCursor\", nil, {0, 0}},\n    {\"countinguphand\",\t\tSELECTOR,    @\"busyButClickableCursor\", nil, {0, 0}},\n    {\"countingdownhand\",\tSELECTOR,    @\"busyButClickableCursor\", nil, {0, 0}},\n    {\"countingupanddownhand\",\tSELECTOR,    @\"busyButClickableCursor\", nil, {0, 0}},\n    {\"help\",\t\t\tIMAGENAMED,  @\"NSHelpCursor\", nil, {8, 8}},\n//  {\"hand\",\t\t\tIMAGEBITMAP, MacCursorData(hand), nil, {0, 0}},\n    {\"bucket\",\t\t\tIMAGEBITMAP, MacCursorData(bucket), nil, {0, 0}},\n    {\"cancel\",\t\t\tIMAGEBITMAP, MacCursorData(cancel), nil, {0, 0}},\n//  {\"resize\",\t\t\tIMAGEBITMAP, MacCursorData(resize), nil, {0, 0}},\n    {\"eyedrop\",\t\t\tIMAGEBITMAP, MacCursorData(eyedrop), nil, {0, 0}},\n    {\"eyedrop-full\",\t\tIMAGEBITMAP, MacCursorData(eyedrop_full), nil, {0, 0}},\n    {\"zoom-in\",\t\t\tIMAGEBITMAP, MacCursorData(zoom_in), nil, {0, 0}},\n    {\"zoom-out\",\t\tIMAGEBITMAP, MacCursorData(zoom_out), nil, {0, 0}},\n    {\"X_cursor\",\t\tIMAGEBITMAP, MacXCursorData(X_cursor), nil, {0, 0}},\n//  {\"arrow\",\t\t\tIMAGEBITMAP, MacXCursorData(arrow), nil, {0, 0}},\n    {\"based_arrow_down\",\tIMAGEBITMAP, MacXCursorData(based_arrow_down), nil, {0, 0}},\n    {\"based_arrow_up\",\t\tIMAGEBITMAP, MacXCursorData(based_arrow_up), nil, {0, 0}},\n    {\"boat\",\t\t\tIMAGEBITMAP, MacXCursorData(boat), nil, {0, 0}},\n    {\"bogosity\",\t\tIMAGEBITMAP, MacXCursorData(bogosity), nil, {0, 0}},\n    {\"bottom_left_corner\",\tIMAGEBITMAP, MacXCursorData(bottom_left_corner), nil, {0, 0}},\n    {\"bottom_right_corner\",\tIMAGEBITMAP, MacXCursorData(bottom_right_corner), nil, {0, 0}},\n    {\"bottom_side\",\t\tIMAGEBITMAP, MacXCursorData(bottom_side), nil, {0, 0}},\n    {\"bottom_tee\",\t\tIMAGEBITMAP, MacXCursorData(bottom_tee), nil, {0, 0}},\n    {\"box_spiral\",\t\tIMAGEBITMAP, MacXCursorData(box_spiral), nil, {0, 0}},\n    {\"center_ptr\",\t\tIMAGEBITMAP, MacXCursorData(center_ptr), nil, {0, 0}},\n    {\"circle\",\t\t\tIMAGEBITMAP, MacXCursorData(circle), nil, {0, 0}},\n    {\"clock\",\t\t\tIMAGEBITMAP, MacXCursorData(clock), nil, {0, 0}},\n    {\"coffee_mug\",\t\tIMAGEBITMAP, MacXCursorData(coffee_mug), nil, {0, 0}},\n//  {\"cross\",\t\t\tIMAGEBITMAP, MacXCursorData(cross), nil, {0, 0}},\n    {\"cross_reverse\",\t\tIMAGEBITMAP, MacXCursorData(cross_reverse), nil, {0, 0}},\n//  {\"crosshair\",\t\tIMAGEBITMAP, MacXCursorData(crosshair), nil, {0, 0}},\n    {\"diamond_cross\",\t\tIMAGEBITMAP, MacXCursorData(diamond_cross), nil, {0, 0}},\n    {\"dot\",\t\t\tIMAGEBITMAP, MacXCursorData(dot), nil, {0, 0}},\n    {\"dotbox\",\t\t\tIMAGEBITMAP, MacXCursorData(dotbox), nil, {0, 0}},\n    {\"double_arrow\",\t\tIMAGEBITMAP, MacXCursorData(double_arrow), nil, {0, 0}},\n    {\"draft_large\",\t\tIMAGEBITMAP, MacXCursorData(draft_large), nil, {0, 0}},\n    {\"draft_small\",\t\tIMAGEBITMAP, MacXCursorData(draft_small), nil, {0, 0}},\n    {\"draped_box\",\t\tIMAGEBITMAP, MacXCursorData(draped_box), nil, {0, 0}},\n    {\"exchange\",\t\tIMAGEBITMAP, MacXCursorData(exchange), nil, {0, 0}},\n    {\"fleur\",\t\t\tIMAGEBITMAP, MacXCursorData(fleur), nil, {0, 0}},\n    {\"gobbler\",\t\t\tIMAGEBITMAP, MacXCursorData(gobbler), nil, {0, 0}},\n    {\"gumby\",\t\t\tIMAGEBITMAP, MacXCursorData(gumby), nil, {0, 0}},\n    {\"hand1\",\t\t\tIMAGEBITMAP, MacXCursorData(hand1), nil, {0, 0}},\n    {\"hand2\",\t\t\tIMAGEBITMAP, MacXCursorData(hand2), nil, {0, 0}},\n    {\"heart\",\t\t\tIMAGEBITMAP, MacXCursorData(heart), nil, {0, 0}},\n    {\"icon\",\t\t\tIMAGEBITMAP, MacXCursorData(icon), nil, {0, 0}},\n    {\"iron_cross\",\t\tIMAGEBITMAP, MacXCursorData(iron_cross), nil, {0, 0}},\n//  {\"left_ptr\",\t\tIMAGEBITMAP, MacXCursorData(left_ptr), nil, {0, 0}},\n    {\"left_side\",\t\tIMAGEBITMAP, MacXCursorData(left_side), nil, {0, 0}},\n    {\"left_tee\",\t\tIMAGEBITMAP, MacXCursorData(left_tee), nil, {0, 0}},\n    {\"leftbutton\",\t\tIMAGEBITMAP, MacXCursorData(leftbutton), nil, {0, 0}},\n    {\"ll_angle\",\t\tIMAGEBITMAP, MacXCursorData(ll_angle), nil, {0, 0}},\n    {\"lr_angle\",\t\tIMAGEBITMAP, MacXCursorData(lr_angle), nil, {0, 0}},\n    {\"man\",\t\t\tIMAGEBITMAP, MacXCursorData(man), nil, {0, 0}},\n    {\"middlebutton\",\t\tIMAGEBITMAP, MacXCursorData(middlebutton), nil, {0, 0}},\n    {\"mouse\",\t\t\tIMAGEBITMAP, MacXCursorData(mouse), nil, {0, 0}},\n    {\"pencil\",\t\t\tIMAGEBITMAP, MacXCursorData(pencil), nil, {0, 0}},\n    {\"pirate\",\t\t\tIMAGEBITMAP, MacXCursorData(pirate), nil, {0, 0}},\n    {\"plus\",\t\t\tIMAGEBITMAP, MacXCursorData(plus), nil, {0, 0}},\n    {\"question_arrow\",\t\tIMAGEBITMAP, MacXCursorData(question_arrow), nil, {0, 0}},\n    {\"right_ptr\",\t\tIMAGEBITMAP, MacXCursorData(right_ptr), nil, {0, 0}},\n    {\"right_side\",\t\tIMAGEBITMAP, MacXCursorData(right_side), nil, {0, 0}},\n    {\"right_tee\",\t\tIMAGEBITMAP, MacXCursorData(right_tee), nil, {0, 0}},\n    {\"rightbutton\",\t\tIMAGEBITMAP, MacXCursorData(rightbutton), nil, {0, 0}},\n    {\"rtl_logo\",\t\tIMAGEBITMAP, MacXCursorData(rtl_logo), nil, {0, 0}},\n    {\"sailboat\",\t\tIMAGEBITMAP, MacXCursorData(sailboat), nil, {0, 0}},\n    {\"sb_down_arrow\",\t\tIMAGEBITMAP, MacXCursorData(sb_down_arrow), nil, {0, 0}},\n    {\"sb_h_double_arrow\",\tIMAGEBITMAP, MacXCursorData(sb_h_double_arrow), nil, {0, 0}},\n    {\"sb_left_arrow\",\t\tIMAGEBITMAP, MacXCursorData(sb_left_arrow), nil, {0, 0}},\n    {\"sb_right_arrow\",\t\tIMAGEBITMAP, MacXCursorData(sb_right_arrow), nil, {0, 0}},\n    {\"sb_up_arrow\",\t\tIMAGEBITMAP, MacXCursorData(sb_up_arrow), nil, {0, 0}},\n    {\"sb_v_double_arrow\",\tIMAGEBITMAP, MacXCursorData(sb_v_double_arrow), nil, {0, 0}},\n    {\"shuttle\",\t\t\tIMAGEBITMAP, MacXCursorData(shuttle), nil, {0, 0}},\n    {\"sizing\",\t\t\tIMAGEBITMAP, MacXCursorData(sizing), nil, {0, 0}},\n    {\"spider\",\t\t\tIMAGEBITMAP, MacXCursorData(spider), nil, {0, 0}},\n    {\"spraycan\",\t\tIMAGEBITMAP, MacXCursorData(spraycan), nil, {0, 0}},\n    {\"star\",\t\t\tIMAGEBITMAP, MacXCursorData(star), nil, {0, 0}},\n    {\"target\",\t\t\tIMAGEBITMAP, MacXCursorData(target), nil, {0, 0}},\n//  {\"tcross\",\t\t\tIMAGEBITMAP, MacXCursorData(tcross), nil, {0, 0}},\n//  {\"top_left_arrow\",\t\tIMAGEBITMAP, MacXCursorData(top_left_arrow), nil, {0, 0}},\n    {\"top_left_corner\",\t\tIMAGEBITMAP, MacXCursorData(top_left_corner), nil, {0, 0}},\n    {\"top_right_corner\",\tIMAGEBITMAP, MacXCursorData(top_right_corner), nil, {0, 0}},\n    {\"top_side\",\t\tIMAGEBITMAP, MacXCursorData(top_side), nil, {0, 0}},\n    {\"top_tee\",\t\t\tIMAGEBITMAP, MacXCursorData(top_tee), nil, {0, 0}},\n    {\"trek\",\t\t\tIMAGEBITMAP, MacXCursorData(trek), nil, {0, 0}},\n    {\"ul_angle\",\t\tIMAGEBITMAP, MacXCursorData(ul_angle), nil, {0, 0}},\n    {\"umbrella\",\t\tIMAGEBITMAP, MacXCursorData(umbrella), nil, {0, 0}},\n    {\"ur_angle\",\t\tIMAGEBITMAP, MacXCursorData(ur_angle), nil, {0, 0}},\n    {\"watch\",\t\t\tIMAGEBITMAP, MacXCursorData(watch), nil, {0, 0}},\n//  {\"xterm\",\t\t\tIMAGEBITMAP, MacXCursorData(xterm), nil, {0, 0}},\n    {NULL, 0, nil, nil, {0, 0}}\n};\n\n/*\n * Declarations of static variables used in this file.\n */\n\nstatic TkMacOSXCursor *gCurrentCursor = NULL;\n\t\t\t\t/* A pointer to the current cursor. */\n\n/*\n * Declarations of procedures local to this file\n */\n\nstatic void FindCursorByName(TkMacOSXCursor *macCursorPtr, const char *string);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindCursorByName --\n *\n *\tRetrieve a system cursor by name, and fill the macCursorPtr\n *\tstructure. If the cursor cannot be found, the macCursor field\n *\twill be nil.\n *\n * Results:\n *\tFills the macCursorPtr record.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nFindCursorByName(\n    TkMacOSXCursor *macCursorPtr,\n    const char *name)\n{\n    NSString *path = nil;\n    NSImage *image = nil;\n    NSPoint hotSpot = NSZeroPoint;\n    int haveHotSpot = 0, result = TCL_ERROR;\n    NSCursor *macCursor = nil;\n\n    if (name[0] == '@') {\n\t/*\n\t * System cursor of type @filename\n\t */\n\n\tmacCursorPtr->type = IMAGEPATH;\n\tpath = [NSString stringWithUTF8String:&name[1]];\n    } else {\n\tTcl_Obj *strPtr = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n\tint idx;\n\n\tresult = Tcl_GetIndexFromObjStruct(NULL, strPtr, cursorNames,\n\t\t    sizeof(struct CursorName), NULL, TCL_EXACT, &idx);\n\tTcl_DecrRefCount(strPtr);\n\tif (result == TCL_OK) {\n\t    macCursorPtr->type = cursorNames[idx].kind;\n\t    switch (cursorNames[idx].kind) {\n\t    case SELECTOR: {\n\t\tSEL selector = NSSelectorFromString(cursorNames[idx].id1);\n\t\tif ([NSCursor respondsToSelector:selector]) {\n\t\t    macCursor = [[NSCursor performSelector:selector] retain];\n\t\t} else if (cursorNames[idx].id2) {\n\t\t    selector = NSSelectorFromString(cursorNames[idx].id2);\n\t\t    if ([NSCursor respondsToSelector:selector]) {\n\t\t\tmacCursor = [[NSCursor performSelector:selector] retain];\n\t\t    }\n\t\t}\n\t\tbreak;\n\t    }\n\t    case IMAGENAMED:\n\t\timage = [[NSImage imageNamed:cursorNames[idx].id1] retain];\n\t\thotSpot = cursorNames[idx].hotspot;\n\t\thaveHotSpot = 1;\n\t\tbreak;\n\t    case IMAGEPATH:\n\t\tpath = [NSApp tkFrameworkImagePath:cursorNames[idx].id1];\n\t\tbreak;\n\t    case IMAGEBITMAP: {\n\t\tunsigned char *bitmap = (unsigned char *)(cursorNames[idx].id1);\n\t\tNSBitmapImageRep *bitmapImageRep = nil;\n\t\tCGImageRef img = NULL, mask = NULL, maskedImg = NULL;\n\t\tstatic const CGFloat decodeWB[] = {1, 0};\n\t\tCGColorSpaceRef colorspace = CGColorSpaceCreateWithName(\n\t\t\tkCGColorSpaceGenericGray);\n\t\tCGDataProviderRef provider = CGDataProviderCreateWithData(NULL,\n\t\t\tbitmap, pix*pix/8, NULL);\n\n\t\tif (provider) {\n\t\t    img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace,\n\t\t\t    kCGBitmapByteOrderDefault, provider, decodeWB, 0,\n\t\t\t    kCGRenderingIntentDefault);\n\t\t    CFRelease(provider);\n\t\t}\n\t\tprovider = CGDataProviderCreateWithData(NULL, bitmap +\n\t\t\tpix*pix/8, pix*pix/8, NULL);\n\t\tif (provider) {\n\t\t    mask = CGImageMaskCreate(pix, pix, 1, 1, pix/8, provider,\n\t\t\t    decodeWB, 0);\n\t\t    CFRelease(provider);\n\t\t}\n\t\tif (img && mask) {\n\t\t    maskedImg = CGImageCreateWithMask(img, mask);\n\t\t}\n\t\tif (maskedImg) {\n\t\t    bitmapImageRep = [[NSBitmapImageRep alloc]\n\t\t\t    initWithCGImage:maskedImg];\n\t\t    CFRelease(maskedImg);\n\t\t}\n\t\tif (mask) {\n\t\t    CFRelease(mask);\n\t\t}\n\t\tif (img) {\n\t\t    CFRelease(img);\n\t\t}\n\t\tif (colorspace) {\n\t\t    CFRelease(colorspace);\n\t\t}\n\t\tif (bitmapImageRep) {\n\t\t    image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)];\n\t\t    [image addRepresentation:bitmapImageRep];\n\t\t    [image setTemplate:YES];\n\t\t    [bitmapImageRep release];\n\t\t}\n\n\t\tuint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8);\n\t\thotSpot.y = CFSwapInt16BigToHost(*hotSpotData++);\n\t\thotSpot.x = CFSwapInt16BigToHost(*hotSpotData);\n\t\thaveHotSpot = 1;\n\t\tbreak;\n\t    }\n\t    }\n\t}\n    }\n    if (path) {\n\timage = [[NSImage alloc] initWithContentsOfFile:path];\n    }\n    if (!image && !macCursor && result != TCL_OK) {\n\tmacCursorPtr->type = IMAGENAMED;\n\timage = [[NSImage imageNamed:[NSString stringWithUTF8String:name]]\n\t\tretain];\n\thaveHotSpot = 0;\n    }\n    if (image) {\n\tif (!haveHotSpot && [[path pathExtension] isEqualToString:@\"cur\"]) {\n\t    NSData *data = [NSData dataWithContentsOfFile:path];\n\t    if ([data length] > 14) {\n\t\tuint16_t *hotSpotData = (uint16_t*)((char*) [data bytes] + 10);\n\t\thotSpot.x = CFSwapInt16LittleToHost(*hotSpotData++);\n\t\thotSpot.y = CFSwapInt16LittleToHost(*hotSpotData);\n\t\thaveHotSpot = 1;\n\t    }\n\t}\n\tif (!haveHotSpot) {\n\t    NSSize size = [image size];\n\t    hotSpot.x = size.width * 0.5;\n\t    hotSpot.y = size.height * 0.5;\n\t}\n\thotSpot.y = -hotSpot.y;\n\tmacCursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot];\n\t[image release];\n    }\n    macCursorPtr->macCursor = macCursor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetCursorByName --\n *\n *\tRetrieve a system cursor by name.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkGetCursorByName(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    TCL_UNUSED(Tk_Window),\t\t/* Window in which cursor will be used. */\n    const char *string)\t\t/* Description of cursor. See manual entry\n\t\t\t\t * for details on legal syntax. */\n{\n    TkMacOSXCursor *macCursorPtr = NULL;\n    const char **argv = NULL;\n    Tcl_Size argc;\n\n    /*\n     * All cursor names are valid lists of one element (for\n     * TkX11-compatibility), even unadorned system cursor names.\n     */\n\n    if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK) {\n\tif (argc) {\n\t    macCursorPtr = (TkMacOSXCursor *)Tcl_Alloc(sizeof(TkMacOSXCursor));\n\t    macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;\n\t    macCursorPtr->macCursor = nil;\n\t    macCursorPtr->type = 0;\n\t    FindCursorByName(macCursorPtr, argv[0]);\n\t}\n\tTcl_Free(argv);\n    }\n    if (!macCursorPtr || (!macCursorPtr->macCursor &&\n\t    macCursorPtr->type != NONE)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad cursor spec \\\"%s\\\"\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CURSOR\", (char *)NULL);\n\tif (macCursorPtr) {\n\t    Tcl_Free(macCursorPtr);\n\t    macCursorPtr = NULL;\n\t}\n    }\n    return (TkCursor *) macCursorPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateCursorFromData --\n *\n *\tCreates a cursor from the source and mask bits.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkCreateCursorFromData(\n    TCL_UNUSED(Tk_Window),\t\t/* Window in which cursor will be used. */\n    TCL_UNUSED(const char *),\t\t/* Bitmap data for cursor shape. */\n    TCL_UNUSED(const char *),\t\t/* Bitmap data for cursor mask. */\n    TCL_UNUSED(int),\t/* Dimensions of cursor. */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\t\t/* Location of hot-spot in cursor. */\n    TCL_UNUSED(int),\n    TCL_UNUSED(XColor),\t\t/* Foreground color for cursor. */\n    TCL_UNUSED(XColor))\t\t/* Background color for cursor. */\n{\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeCursor --\n *\n *\tThis procedure is called to release a cursor allocated by\n *\tTkGetCursorByName.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor data structure is deallocated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeCursor(\n    TkCursor *cursorPtr)\n{\n    TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr;\n\n    [macCursorPtr->macCursor release];\n    macCursorPtr->macCursor = nil;\n    if (macCursorPtr == gCurrentCursor) {\n\tgCurrentCursor = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInstallCursor --\n *\n *\tInstalls either the current cursor as defined by TkpSetCursor or a\n *\tresize cursor as the cursor the Macintosh should currently display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the Macintosh mouse cursor.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXInstallCursor(\n    void)\n{\n    TkMacOSXCursor *macCursorPtr = gCurrentCursor;\n    static int cursorHidden = 0;\n    int cursorNone = 0;\n\n    if (!macCursorPtr) {\n\t[[NSCursor arrowCursor] set];\n    } else {\n\tswitch (macCursorPtr->type) {\n\tcase NONE:\n\t    if (!cursorHidden) {\n\t\tcursorHidden = 1;\n\t\t[NSCursor hide];\n\t    }\n\t    cursorNone = 1;\n\t    break;\n\tcase SELECTOR:\n\tcase IMAGENAMED:\n\tcase IMAGEPATH:\n\tcase IMAGEBITMAP:\n\tdefault:\n\t    [macCursorPtr->macCursor set];\n\t    break;\n\t}\n    }\n    if (cursorHidden && !cursorNone) {\n\tcursorHidden = 0;\n\t[NSCursor unhide];\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetCursor --\n *\n *\tSet the current cursor and install it.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the current cursor.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetCursor(\n    Cursor cursor)\n{\n    bool cursorChanged = true;\n\n    if (cursor == None) {\n\t/*\n\t * This is a little tricky. We can't really tell whether\n\t * gCurrentCursor is NULL because it was NULL last time around or\n\t * because we just freed the current cursor. So if the input cursor is\n\t * NULL, we always need to reset it, we can't trust the cursorChanged\n\t * logic.\n\t */\n\n\tgCurrentCursor = NULL;\n    } else {\n\tif (gCurrentCursor == (TkMacOSXCursor *) cursor) {\n\t    cursorChanged = false;\n\t}\n\tgCurrentCursor = (TkMacOSXCursor *) cursor;\n    }\n\n    if (Tk_MacOSXIsAppInFront() && cursorChanged) {\n\tTkMacOSXInstallCursor();\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXCursors.h",
    "content": "/*\n * tkMacOSXCursors.h --\n *\n *\tThis file defines a set of Macintosh cursor resources that\n *\tare only available on the Macintosh platform.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 2008-2009 Apple Inc.\n * Copyright © 2008-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\nstatic const unsigned char tkMacOSXCursors[][68] = {\n\n#define TK_MAC_CURSOR_hand 0\n[TK_MAC_CURSOR_hand] = {\n\t0x01, 0x80, 0x1A, 0x70, 0x26, 0x48, 0x26, 0x4A, 0x12, 0x4D, 0x12, 0x49, 0x68, 0x09, 0x98, 0x01,\n\t0x88, 0x02, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04, 0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,\n\t0x01, 0x80, 0x1B, 0xF0, 0x3F, 0xF8, 0x3F, 0xFA, 0x1F, 0xFF, 0x1F, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF,\n\t0xFF, 0xFE, 0x7F, 0xFE, 0x3F, 0xFE, 0x3F, 0xFC, 0x1F, 0xFC, 0x0F, 0xF8, 0x07, 0xF8, 0x07, 0xF8,\n\t0x00, 0x09, 0x00, 0x08,\n},\n\n#define TK_MAC_CURSOR_bucket 2\n[TK_MAC_CURSOR_bucket] = {\n\t0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x80, 0x09, 0x40, 0x0B, 0x30, 0x0D, 0x18, 0x09, 0x0C,\n\t0x12, 0x9C, 0x21, 0x2C, 0x10, 0x4C, 0x08, 0x8C, 0x05, 0x0C, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x80, 0x09, 0xC0, 0x0B, 0xF0, 0x0F, 0xF8, 0x0F, 0xFC,\n\t0x1F, 0xFC, 0x3F, 0xEC, 0x1F, 0xCC, 0x0F, 0x8C, 0x07, 0x0C, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0D, 0x00, 0x0C,\n},\n\n#define TK_MAC_CURSOR_cancel 3\n[TK_MAC_CURSOR_cancel] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x4A, 0x40, 0x4A, 0x40, 0x3F, 0x80,\n\t0x0A, 0x00, 0x3F, 0x80, 0x4A, 0x40, 0x4A, 0x46, 0x31, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x7B, 0xC0, 0xFF, 0xE0, 0xFF, 0xE0, 0x7F, 0xC0,\n\t0x3F, 0x80, 0x7F, 0xC0, 0xFF, 0xE6, 0xFF, 0xEF, 0x7B, 0xCF, 0x31, 0x86, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x08, 0x00, 0x05,\n},\n\n#define TK_MAC_CURSOR_resize 4\n[TK_MAC_CURSOR_resize] = {\n\t0xFF, 0xFF, 0x80, 0x01, 0xBF, 0x01, 0xA1, 0x81, 0xA1, 0xF9, 0xA1, 0x8D, 0xA1, 0x8D, 0xBF, 0x8D,\n\t0x9F, 0x8D, 0x88, 0x0D, 0x88, 0x0D, 0x88, 0x0D, 0x8F, 0xFD, 0x87, 0xFD, 0x80, 0x01, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x08, 0x00, 0x08,\n},\n\n#define TK_MAC_CURSOR_eyedrop 5\n[TK_MAC_CURSOR_eyedrop] = {\n\t0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xB8, 0x01, 0x18, 0x02, 0x28,\n\t0x04, 0x40, 0x08, 0x80, 0x11, 0x00, 0x22, 0x00, 0x44, 0x00, 0x48, 0x00, 0xB0, 0x00, 0x40, 0x00,\n\t0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xE8,\n\t0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,\n\t0x00, 0x0F, 0x00, 0x00,\n},\n\n#define TK_MAC_CURSOR_eyedrop_full 6\n[TK_MAC_CURSOR_eyedrop_full] = {\n\t0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xB8, 0x01, 0x18, 0x03, 0x28,\n\t0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,\n\t0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0x00, 0x7E, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xE8,\n\t0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x40, 0x00,\n\t0x00, 0x0F, 0x00, 0x00,\n},\n\n#define TK_MAC_CURSOR_zoom_in 7\n[TK_MAC_CURSOR_zoom_in] = {\n\t0x07, 0x80, 0x18, 0x60, 0x27, 0x90, 0x58, 0x68, 0x53, 0x28, 0xA3, 0x14, 0xAF, 0xD4, 0xAF, 0xD4,\n\t0xA3, 0x14, 0x53, 0x28, 0x58, 0x68, 0x27, 0x98, 0x18, 0x7C, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,\n\t0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x78, 0x78, 0x73, 0x38, 0xE3, 0x1C, 0xEF, 0xDC, 0xEF, 0xDC,\n\t0xE3, 0x1C, 0x73, 0x38, 0x78, 0x78, 0x3F, 0xF8, 0x1F, 0xFC, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_CURSOR_zoom_out 8\n[TK_MAC_CURSOR_zoom_out] = {\n\t0x07, 0x80, 0x18, 0x60, 0x27, 0x90, 0x58, 0x68, 0x50, 0x28, 0xA0, 0x14, 0xAF, 0xD4, 0xAF, 0xD4,\n\t0xA0, 0x14, 0x50, 0x28, 0x58, 0x68, 0x27, 0x98, 0x18, 0x7C, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,\n\t0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x78, 0x78, 0x70, 0x38, 0xE0, 0x1C, 0xEF, 0xDC, 0xEF, 0xDC,\n\t0xE0, 0x1C, 0x70, 0x38, 0x78, 0x78, 0x3F, 0xF8, 0x1F, 0xFC, 0x07, 0x8E, 0x00, 0x07, 0x00, 0x03,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n};\n"
  },
  {
    "path": "macosx/tkMacOSXDebug.c",
    "content": "/*\n * tkMacOSXDebug.c --\n *\n *\tImplementation of Macintosh specific functions for debugging MacOS\n *\tevents, regions, etc...\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXDebug.h\"\n\n#ifdef TK_MAC_DEBUG\n\n#include <mach-o/dyld.h>\n#include <mach-o/nlist.h>\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNamedDebugSymbol --\n *\n *\tDynamically acquire address of a named symbol from a loaded dynamic\n *\tlibrary, so that we can use API that may not be available on all OS\n *\tversions. For debugging purposes, if we cannot find the symbol with\n *\tthe usual dynamic library APIs, we manually walk the symbol table of\n *\tthe loaded library. This allows access to unexported symbols such as\n *\tprivate_extern internal debugging functions. If module is NULL or the\n *\tempty string, search all loaded libraries (could be very expensive and\n *\tshould be avoided).\n *\n *\tTHIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY BREAK\n *\tUNEXPECTEDLY IN THE FUTURE!\n *\n * Results:\n *\tAddress of given symbol or NULL if unavailable.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE void *\nTkMacOSXGetNamedDebugSymbol(\n    const char *module,\n    const char *symbol)\n{\n    void *addr = TkMacOSXGetNamedSymbol(module, symbol);\n\n#ifndef __LP64__\n    if (!addr) {\n\tconst struct mach_header *mh = NULL;\n\tuint32_t i, n = _dyld_image_count();\n\tsize_t module_len = 0;\n\n\tif (module && *module) {\n\t    module_len = strlen(module);\n\t}\n\tfor (i = 0; i < n; i++) {\n\t    if (module && *module) {\n\t\t/* Find image with given module name */\n\t\tconst char *name;\n\t\tconst char *path = _dyld_get_image_name(i);\n\n\t\tif (!path) {\n\t\t    continue;\n\t\t}\n\t\tname = strrchr(path, '/') + 1;\n\t\tif (strncmp(name, module, module_len) != 0) {\n\t\t    continue;\n\t\t}\n\t    }\n\t    mh = _dyld_get_image_header(i);\n\t    if (mh) {\n\t\tstruct load_command *lc;\n\t\tstruct symtab_command *st = NULL;\n\t\tstruct segment_command *sg = NULL;\n\t\tuint32_t j, m, nsect = 0, txtsectx = 0;\n\n\t\tlc = (struct load_command*)((const char*) mh +\n\t\t\tsizeof(struct mach_header));\n\t\tm = mh->ncmds;\n\t\tfor (j = 0; j < m; j++) {\n\t\t    /* Find symbol table and index of __text section */\n\t\t    if (lc->cmd == LC_SEGMENT) {\n\t\t\t/* Find last segment before symbol table */\n\t\t\tsg = (struct segment_command*) lc;\n\t\t\tif (!txtsectx) {\n\t\t\t    /* Count total sections until (__TEXT, __text) */\n\t\t\t    uint32_t k, ns = sg->nsects;\n\n\t\t\t    if (strcmp(sg->segname, SEG_TEXT) == 0) {\n\t\t\t\tstruct section *s = (struct section *)(\n\t\t\t\t\t(char *)sg +\n\t\t\t\t\tsizeof(struct segment_command));\n\n\t\t\t\tfor(k = 0; k < ns; k++) {\n\t\t\t\t    if (strcmp(s->sectname, SECT_TEXT) == 0) {\n\t\t\t\t\ttxtsectx = nsect+k+1;\n\t\t\t\t\tbreak;\n\t\t\t\t    }\n\t\t\t\t    s++;\n\t\t\t\t}\n\t\t\t    }\n\t\t\t    nsect += ns;\n\t\t\t}\n\t\t    } else if (!st && lc->cmd == LC_SYMTAB) {\n\t\t\tst = (struct symtab_command *) lc;\n\t\t\tbreak;\n\t\t    }\n\t\t    lc = (struct load_command *)((char *) lc + lc->cmdsize);\n\t\t}\n\t\tif (st && sg && txtsectx) {\n\t\t    intptr_t base, slide = _dyld_get_image_vmaddr_slide(i);\n\t\t    char *strings;\n\t\t    struct nlist *sym;\n\t\t    uint32_t strsize = st->strsize;\n\t\t    int32_t strx;\n\n\t\t    /*\n\t\t     * Offset file positions by difference to actual position\n\t\t     * in memory of last segment before symbol table:\n\t\t     */\n\n\t\t    base = (intptr_t) sg->vmaddr + slide - sg->fileoff;\n\t\t    strings = (char *) (base + st->stroff);\n\t\t    sym = (struct nlist *) (base + st->symoff);\n\t\t    m = st->nsyms;\n\t\t    for (j = 0; j < m; j++) {\n\t\t\t/* Find symbol with given name in __text section */\n\t\t\tstrx = sym->n_un.n_strx;\n\t\t\tif ((sym->n_type & N_TYPE) == N_SECT &&\n\t\t\t\tsym->n_sect == txtsectx &&\n\t\t\t\tstrx > 0 && (uint32_t) strx < strsize &&\n\t\t\t\tstrcmp(strings + strx, symbol) == 0) {\n\t\t\t    addr = (char*) sym->n_value + slide;\n\t\t\t    break;\n\t\t\t}\n\t\t\tsym++;\n\t\t    }\n\t\t}\n\t    }\n\t    if (module && *module) {\n\t\t/* If given a module name, only search corresponding image */\n\t\tbreak;\n\t    }\n\t}\n    }\n#endif /* __LP64__ */\n    return addr;\n}\n#endif /* TK_MAC_DEBUG */\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXDebug.h",
    "content": "/*\n * tkMacOSXDebug.h --\n *\n *\tDeclarations of Macintosh specific functions for debugging MacOS events,\n *\tregions, etc...\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACDEBUG\n#define _TKMACDEBUG\n\n#ifndef _TKMACINT\n#include \"tkMacOSXInt.h\"\n#endif\n\n#ifdef TK_MAC_DEBUG\n\nMODULE_SCOPE void* TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol);\n\n/* Macro to abstract common use of TkMacOSXGetNamedDebugSymbol to initialize named symbols */\n#define TkMacOSXInitNamedDebugSymbol(module, ret, symbol, ...) \\\n    static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \\\n    if (symbol == (void*)(-1L)) { \\\n\tsymbol = TkMacOSXGetNamedDebugSymbol(STRINGIFY(module), STRINGIFY(_##symbol));\\\n    }\n\n#endif /* TK_MAC_DEBUG */\n\n#endif\n"
  },
  {
    "path": "macosx/tkMacOSXDefault.h",
    "content": "/*\n * tkMacOSXDefault.h --\n *\n *\tThis file defines the defaults for all options for all of\n *\tthe Tk widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACDEFAULT\n#define _TKMACDEFAULT\n\n//#ifndef TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS\n//#define TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS 1\n//#endif\n\n/*\n * The definitions below provide symbolic names for the default colors.\n * NORMAL_BG -\t\tNormal background color.\n * NORMAL_FG -\t\tNormal foreground color.\n * ACTIVE_BG -\t\tBackground color when widget is active.\n * ACTIVE_FG -\t\tForeground color when widget is active.\n * SELECT_BG -\t\tBackground color for selected text.\n * SELECT_FG -\t\tForeground color for selected text.\n * TROUGH -\t\tBackground color for troughs in scales and scrollbars.\n * INDICATOR -\t\tColor for indicator when button is selected.\n * DISABLED -\t\tForeground color when widget is disabled.\n */\n\n#define BLACK\t\t\t\"Black\"\n#define WHITE\t\t\t\"White\"\n#define NORMAL_BG\t\t\"systemWindowBackgroundColor\"\n#define TEXT_BG                 \"systemTextBackgroundColor\"\n#define NORMAL_FG\t\t\"systemTextColor\"\n#define ACTIVE_BG\t\t\"systemWindowBackgroundColor\"\n#define ACTIVE_FG\t\t\"systemTextColor\"\n#define SELECT_BG\t\t\"systemSelectedTextBackgroundColor\"\n#define SELECT_FG\t\t\"systemSelectedTextColor\"\n#define INACTIVE_SELECT_BG\t\"systemUnemphasizedSelectedTextBackgroundColor\"\n#define INACTIVE_SELECT_FG\t\"systemSelectedControlTextColor\"\n#define TROUGH\t\t\t\"#c3c3c3\"\n#define INDICATOR\t\t\"#b03060\"\n#define DISABLED\t\t\"systemDisabledControlTextColor\"\n#define IGNORED                 \"#abcdef\"\n\n/*\n * Defaults for labels, buttons, checkbuttons, and radiobuttons:\n */\n\n#define DEF_BUTTON_ANCHOR\t\t\"center\"\n#define DEF_BUTTON_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_BUTTON_ACTIVE_BG_MONO\tBLACK\n#define DEF_BUTTON_ACTIVE_FG_COLOR\t\"systemPressedButtonTextColor\"\n#define DEF_CHKRAD_ACTIVE_FG_COLOR\tACTIVE_FG\n#define DEF_BUTTON_ACTIVE_FG_MONO\tWHITE\n#define DEF_BUTTON_BG_COLOR\t\tNORMAL_BG\n#define DEF_BUTTON_BG_MONO\t\tWHITE\n#define DEF_BUTTON_BITMAP\t\t\"\"\n#define DEF_BUTTON_BORDER_WIDTH\t\t\"2\"\n#define DEF_BUTTON_CURSOR\t\t\"\"\n#define DEF_BUTTON_COMMAND\t\t\"\"\n#define DEF_BUTTON_COMPOUND\t\t\"none\"\n#define DEF_BUTTON_DEFAULT\t\t\"disabled\"\n#define DEF_BUTTON_DISABLED_FG_COLOR\tDISABLED\n#define DEF_BUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_BUTTON_FG\t\t\tBLACK\n#define DEF_LABEL_FG\t\t\tNORMAL_FG\n#define DEF_CHKRAD_FG\t\t\tDEF_LABEL_FG\n#define DEF_BUTTON_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_BUTTON_HEIGHT\t\t\"0\"\n#define DEF_BUTTON_HIGHLIGHT_BG_COLOR\tDEF_BUTTON_BG_COLOR\n#define DEF_BUTTON_HIGHLIGHT_BG_MONO\tDEF_BUTTON_BG_MONO\n#define DEF_BUTTON_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_LABEL_HIGHLIGHT_WIDTH\t\"0\"\n//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS\n//#define DEF_BUTTON_HIGHLIGHT_WIDTH\t\"4\"\n//#define DEF_BUTTON_HIGHLIGHT_WIDTH_NOCM\t\"1\"\n//#else\n#define DEF_BUTTON_HIGHLIGHT_WIDTH\t\"1\"\n//#endif\n#define DEF_BUTTON_IMAGE\t\tNULL\n#define DEF_BUTTON_INDICATOR\t\t\"1\"\n#define DEF_BUTTON_JUSTIFY\t\t\"center\"\n#define DEF_BUTTON_OFF_VALUE\t\t\"0\"\n#define DEF_BUTTON_ON_VALUE\t\t\"1\"\n#define DEF_BUTTON_TRISTATE_VALUE\t\"\"\n#define DEF_BUTTON_OVER_RELIEF\t\t\"\"\n#define DEF_BUTTON_PADX\t\t\t\"1\"\n#define DEF_LABCHKRAD_PADX\t\t\"1\"\n#define DEF_BUTTON_PADY\t\t\t\"1\"\n#define DEF_LABCHKRAD_PADY\t\t\"1\"\n#define DEF_BUTTON_RELIEF\t\t\"flat\"\n#define DEF_LABCHKRAD_RELIEF\t\t\"flat\"\n#define DEF_BUTTON_REPEAT_DELAY\t\t\"0\"\n#define DEF_BUTTON_REPEAT_INTERVAL\t\"0\"\n#define DEF_BUTTON_SELECT_COLOR\t\tINDICATOR\n#define DEF_BUTTON_SELECT_MONO\t\tBLACK\n#define DEF_BUTTON_SELECT_IMAGE\t\tNULL\n#define DEF_BUTTON_STATE\t\t\"normal\"\n#define DEF_LABEL_TAKE_FOCUS\t\t\"0\"\n#define DEF_BUTTON_TAKE_FOCUS\t\tNULL\n#define DEF_BUTTON_TEXT\t\t\t\"\"\n#define DEF_BUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_BUTTON_VALUE\t\t\"\"\n#define DEF_BUTTON_WIDTH\t\t\"0\"\n#define DEF_BUTTON_WRAP_LENGTH\t\t\"0\"\n#define DEF_RADIOBUTTON_VARIABLE\t\"selectedButton\"\n#define DEF_CHECKBUTTON_VARIABLE\t\"\"\n\n/*\n * Defaults for canvases:\n */\n\n#define DEF_CANVAS_BG_COLOR\t\tNORMAL_BG\n#define DEF_CANVAS_BG_MONO\t\tWHITE\n#define DEF_CANVAS_BORDER_WIDTH\t\t\"0\"\n#define DEF_CANVAS_CLOSE_ENOUGH\t\t\"1\"\n#define DEF_CANVAS_CONFINE\t\t\"1\"\n#define DEF_CANVAS_CURSOR\t\t\"\"\n#define DEF_CANVAS_HEIGHT\t\t\"7c\"\n#define DEF_CANVAS_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_CANVAS_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_CANVAS_HIGHLIGHT_WIDTH\t\"3\"\n#define DEF_CANVAS_INSERT_BG\t\tBLACK\n#define DEF_CANVAS_INSERT_BD_COLOR\t\"0\"\n#define DEF_CANVAS_INSERT_BD_MONO\t\"0\"\n#define DEF_CANVAS_INSERT_OFF_TIME\t\"300\"\n#define DEF_CANVAS_INSERT_ON_TIME\t\"600\"\n#define DEF_CANVAS_INSERT_WIDTH\t\t\"2\"\n#define DEF_CANVAS_RELIEF\t\t\"flat\"\n#define DEF_CANVAS_SCROLL_REGION\t\"\"\n#define DEF_CANVAS_SELECT_COLOR\t\tSELECT_BG\n#define DEF_CANVAS_SELECT_MONO\t\tBLACK\n#define DEF_CANVAS_SELECT_BD_COLOR\t\"1\"\n#define DEF_CANVAS_SELECT_BD_MONO\t\"0\"\n#define DEF_CANVAS_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_CANVAS_SELECT_FG_MONO\tWHITE\n#define DEF_CANVAS_TAKE_FOCUS\t\tNULL\n#define DEF_CANVAS_WIDTH\t\t\"10c\"\n#define DEF_CANVAS_X_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_X_SCROLL_INCREMENT\t\"0\"\n#define DEF_CANVAS_Y_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_Y_SCROLL_INCREMENT\t\"0\"\n\n/*\n * Defaults for entries:\n */\n\n/*\n * I test the following two values in TkpDrawEntryBorderAndFocus\n * to determine whether to use the native entry widget. So if\n * you change the defaults to be different from these, then you\n * won't get the native widget by default.\n */\n\n#define MAC_OSX_FOCUS_WIDTH\t\t3\n#define MAC_OSX_ENTRY_BORDER\t\t2\n#define MAC_OSX_ENTRY_RELIEF\t\tTK_RELIEF_SUNKEN\n#define MAC_OSX_ENTRY_SELECT_RELIEF\tTK_RELIEF_FLAT\n\n#define DEF_ENTRY_BG_COLOR\t\tTEXT_BG\n#define DEF_ENTRY_BG_MONO\t\tWHITE\n#define DEF_ENTRY_BORDER_WIDTH\t\t\"2\"\n#define DEF_ENTRY_CURSOR\t\t\"xterm\"\n#define DEF_ENTRY_DISABLED_BG_COLOR\tNORMAL_BG\n#define DEF_ENTRY_DISABLED_BG_MONO\tWHITE\n#define DEF_ENTRY_DISABLED_FG\t\tDISABLED\n#define DEF_ENTRY_EXPORT_SELECTION\t\"1\"\n#define DEF_ENTRY_FONT\t\t\t\"TkTextFont\"\n#define DEF_ENTRY_FG\t\t\tNORMAL_FG\n#define DEF_ENTRY_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_ENTRY_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_ENTRY_HIGHLIGHT_WIDTH\t\"3\"\n#define DEF_ENTRY_INSERT_BG\t\tNORMAL_FG\n#define DEF_ENTRY_INSERT_BD_COLOR\t\"0\"\n#define DEF_ENTRY_INSERT_BD_MONO\t\"0\"\n#define DEF_ENTRY_INSERT_OFF_TIME\t\"300\"\n#define DEF_ENTRY_INSERT_ON_TIME\t\"600\"\n#define DEF_ENTRY_INSERT_WIDTH\t\t\"1\"\n#define DEF_ENTRY_JUSTIFY\t\t\"left\"\n#define DEF_ENTRY_PLACEHOLDER\t\t\"\"\n#define DEF_ENTRY_PLACEHOLDERFG\t\t\"systemPlaceholderTextColor\"\n#define DEF_ENTRY_READONLY_BG_COLOR\tNORMAL_BG\n#define DEF_ENTRY_READONLY_BG_MONO\tWHITE\n#define DEF_ENTRY_RELIEF\t\t\"sunken\"\n#define DEF_ENTRY_SCROLL_COMMAND\t\"\"\n#define DEF_ENTRY_SELECT_COLOR\t\tSELECT_BG\n#define DEF_ENTRY_SELECT_MONO\t\tBLACK\n#define DEF_ENTRY_SELECT_BD_COLOR\t\"1\"\n#define DEF_ENTRY_SELECT_BD_MONO\t\"0\"\n#define DEF_ENTRY_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_ENTRY_SELECT_FG_MONO\tWHITE\n#define DEF_ENTRY_SHOW\t\t\tNULL\n#define DEF_ENTRY_STATE\t\t\t\"normal\"\n#define DEF_ENTRY_TAKE_FOCUS\t\tNULL\n#define DEF_ENTRY_TEXT_VARIABLE\t\t\"\"\n#define DEF_ENTRY_WIDTH\t\t\t\"20\"\n\n/*\n * Defaults for frames:\n */\n\n#define DEF_FRAME_BG_COLOR\t\tNORMAL_BG\n#define DEF_FRAME_BG_IMAGE\t\tNULL\n#define DEF_FRAME_BG_MONO\t\tWHITE\n#define DEF_FRAME_BG_TILE\t\t\"0\"\n#define DEF_FRAME_BORDER_WIDTH\t\t\"0\"\n#define DEF_FRAME_CLASS\t\t\t\"Frame\"\n#define DEF_FRAME_COLORMAP\t\t\"\"\n#define DEF_FRAME_CONTAINER\t\t\"0\"\n#define DEF_FRAME_CURSOR\t\t\"\"\n#define DEF_FRAME_HEIGHT\t\t\"0\"\n#define DEF_FRAME_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_FRAME_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_FRAME_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_FRAME_PADX\t\t\t\"0\"\n#define DEF_FRAME_PADY\t\t\t\"0\"\n#define DEF_FRAME_RELIEF\t\t\"flat\"\n#define DEF_FRAME_TAKE_FOCUS\t\t\"0\"\n#define DEF_FRAME_VISUAL\t\t\"\"\n#define DEF_FRAME_WIDTH\t\t\t\"0\"\n\n/*\n * Defaults for labelframes:\n */\n\n#define DEF_LABELFRAME_BORDER_WIDTH\t\"2\"\n#define DEF_LABELFRAME_CLASS\t\t\"Labelframe\"\n#define DEF_LABELFRAME_RELIEF\t\t\"groove\"\n#define DEF_LABELFRAME_FG\t\tNORMAL_FG\n#define DEF_LABELFRAME_FONT\t\t\"TkDefaultFont\"\n#define DEF_LABELFRAME_TEXT\t\t\"\"\n#define DEF_LABELFRAME_LABELANCHOR\t\"nw\"\n\n/*\n * Defaults for listboxes:\n */\n\n#define DEF_LISTBOX_ACTIVE_STYLE\t\"dotbox\"\n#define DEF_LISTBOX_BG_COLOR\t\tTEXT_BG\n#define DEF_LISTBOX_BG_MONO\t\tWHITE\n#define DEF_LISTBOX_BORDER_WIDTH\t\"1\"\n#define DEF_LISTBOX_CURSOR\t\t\"\"\n#define DEF_LISTBOX_DISABLED_FG\t\tDISABLED\n#define DEF_LISTBOX_EXPORT_SELECTION\t\"1\"\n#define DEF_LISTBOX_FONT\t\t\"TkTextFont\"\n#define DEF_LISTBOX_FG\t\t\tNORMAL_FG\n#define DEF_LISTBOX_HEIGHT\t\t\"10\"\n#define DEF_LISTBOX_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_LISTBOX_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_LISTBOX_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_LISTBOX_JUSTIFY\t\t\"left\"\n#define DEF_LISTBOX_RELIEF\t\t\"solid\"\n#define DEF_LISTBOX_SCROLL_COMMAND\t\"\"\n#define DEF_LISTBOX_LIST_VARIABLE\t\"\"\n#define DEF_LISTBOX_INACTIVE_SELECT_COLOR\tINACTIVE_SELECT_BG\n#define DEF_LISTBOX_SELECT_COLOR\tSELECT_BG\n#define DEF_LISTBOX_SELECT_MONO\t\tBLACK\n#define DEF_LISTBOX_SELECT_BD\t\t\"0\"\n#define DEF_LISTBOX_INACTIVE_SELECT_FG_COLOR\tINACTIVE_SELECT_FG\n#define DEF_LISTBOX_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_LISTBOX_SELECT_FG_MONO\tWHITE\n#define DEF_LISTBOX_SELECT_MODE\t\t\"browse\"\n#define DEF_LISTBOX_SET_GRID\t\t\"0\"\n#define DEF_LISTBOX_STATE\t\t\"normal\"\n#define DEF_LISTBOX_TAKE_FOCUS\t\tNULL\n#define DEF_LISTBOX_WIDTH\t\t\"20\"\n\n/*\n * Defaults for individual entries of menus:\n */\n\n#define DEF_MENU_ENTRY_ACTIVE_BG\tNULL\n#define DEF_MENU_ENTRY_ACTIVE_FG\tNULL\n#define DEF_MENU_ENTRY_ACCELERATOR\tNULL\n#define DEF_MENU_ENTRY_BG\t\tNULL\n#define DEF_MENU_ENTRY_BITMAP\t\tNULL\n#define DEF_MENU_ENTRY_COLUMN_BREAK\t\"0\"\n#define DEF_MENU_ENTRY_COMMAND\t\tNULL\n#define DEF_MENU_ENTRY_COMPOUND\t\t\"none\"\n#define DEF_MENU_ENTRY_FG\t\tNULL\n#define DEF_MENU_ENTRY_FONT\t\tNULL\n#define DEF_MENU_ENTRY_HIDE_MARGIN\t\"0\"\n#define DEF_MENU_ENTRY_IMAGE\t\tNULL\n#define DEF_MENU_ENTRY_INDICATOR\t\"1\"\n#define DEF_MENU_ENTRY_LABEL\t\tNULL\n#define DEF_MENU_ENTRY_MENU\t\tNULL\n#define DEF_MENU_ENTRY_OFF_VALUE\t\"0\"\n#define DEF_MENU_ENTRY_ON_VALUE\t\t\"1\"\n#define DEF_MENU_ENTRY_SELECT_IMAGE\tNULL\n#define DEF_MENU_ENTRY_STATE\t\t\"normal\"\n#define DEF_MENU_ENTRY_VALUE\t\tNULL\n#define DEF_MENU_ENTRY_CHECK_VARIABLE\tNULL\n#define DEF_MENU_ENTRY_RADIO_VARIABLE\t\"selectedButton\"\n#define DEF_MENU_ENTRY_SELECT\t\tNULL\n\n/*\n * Defaults for menus overall:\n */\n\n#define DEF_MENU_ACTIVE_BG_COLOR\tIGNORED\n#define DEF_MENU_ACTIVE_BG_MONO\t\tIGNORED\n#define DEF_MENU_ACTIVE_BORDER_WIDTH\t\"0\"\n#define DEF_MENU_ACTIVE_FG_COLOR\tIGNORED\n#define DEF_MENU_ACTIVE_FG_MONO\t\tIGNORED\n#define DEF_MENU_ACTIVE_RELIEF\t\t\"flat\"\n#define DEF_MENU_BG_COLOR\t\t\"#000001\" /* Detects custom bg. */\n#define DEF_MENU_BG_MONO\t\tIGNORED\n#define DEF_MENU_BORDER_WIDTH\t\t\"0\"\n#define DEF_MENU_CURSOR\t\t\t\"arrow\"\n#define DEF_MENU_DISABLED_FG_COLOR\tIGNORED\n#define DEF_MENU_DISABLED_FG_MONO\t\"\"\n#define DEF_MENU_FONT\t\t\t\"menu\" /* special: see tkMacOSXMenu.c */\n#define DEF_MENU_FG\t\t\t\"#010000\"  /* Detects custom fg. */\n#define DEF_MENU_POST_COMMAND\t\t\"\"\n#define DEF_MENU_RELIEF\t\t\t\"flat\"\n#define DEF_MENU_SELECT_COLOR\t\tIGNORED\n#define DEF_MENU_SELECT_MONO\t\tIGNORED\n#define DEF_MENU_TAKE_FOCUS\t\t\"0\"\n#define DEF_MENU_TEAROFF\t\t\"0\"\n#define DEF_MENU_TEAROFF_CMD\t\tNULL\n#define DEF_MENU_TITLE\t\t\t\"\"\n#define DEF_MENU_TYPE\t\t\t\"normal\"\n\n/*\n * Defaults for menubuttons:\n */\n\n#define DEF_MENUBUTTON_ANCHOR\t\t\"w\"\n#define DEF_MENUBUTTON_ACTIVE_BG_COLOR\tNORMAL_BG /*ignored*/\n#define DEF_MENUBUTTON_ACTIVE_BG_MONO\tNORMAL_BG /*ignored*/\n#define DEF_MENUBUTTON_ACTIVE_FG_COLOR\t\"systemTextColor\"\n#define DEF_MENUBUTTON_ACTIVE_FG_MONO\t\"systemTextColor\"\n#define DEF_MENUBUTTON_BG_COLOR\t\tNORMAL_BG /*ignored*/\n#define DEF_MENUBUTTON_BG_MONO\t\tNORMAL_BG /*ignored*/\n#define DEF_MENUBUTTON_BITMAP\t\t\"\"\n#define DEF_MENUBUTTON_BORDER_WIDTH\t\"0\"\n#define DEF_MENUBUTTON_CURSOR\t\t\"\"\n#define DEF_MENUBUTTON_DIRECTION\t\"below\"\n#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED\n#define DEF_MENUBUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_MENUBUTTON_FONT\t\t\"TkDefaultFont\"\n#define DEF_MENUBUTTON_FG\t\tNORMAL_FG\n#define DEF_MENUBUTTON_HEIGHT\t\t\"0\"\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO  DEF_MENUBUTTON_BG_MONO\n#define DEF_MENUBUTTON_HIGHLIGHT\tNORMAL_FG\n#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MENUBUTTON_IMAGE\t\tNULL\n#define DEF_MENUBUTTON_INDICATOR\t\"1\"\n#define DEF_MENUBUTTON_JUSTIFY\t\t\"left\"\n#define DEF_MENUBUTTON_MENU\t\t\"\"\n#define DEF_MENUBUTTON_PADX\t\t\"0\"\n#define DEF_MENUBUTTON_PADY\t\t\"0\"\n#define DEF_MENUBUTTON_RELIEF\t\t\"flat\"\n#define DEF_MENUBUTTON_STATE\t\t\"normal\"\n#define DEF_MENUBUTTON_TAKE_FOCUS\t\"0\"\n#define DEF_MENUBUTTON_TEXT\t\t\"\"\n#define DEF_MENUBUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_MENUBUTTON_WIDTH\t\t\"0\"\n#define DEF_MENUBUTTON_WRAP_LENGTH\t\"0\"\n\n/*\n * Defaults for messages:\n */\n\n#define DEF_MESSAGE_ANCHOR\t\t\"center\"\n#define DEF_MESSAGE_ASPECT\t\t\"150\"\n#define DEF_MESSAGE_BG_COLOR\t\tNORMAL_BG\n#define DEF_MESSAGE_BG_MONO\t\tWHITE\n#define DEF_MESSAGE_BORDER_WIDTH\t\"1\"\n#define DEF_MESSAGE_CURSOR\t\t\"\"\n#define DEF_MESSAGE_FG\t\t\tNORMAL_FG\n#define DEF_MESSAGE_FONT\t\t\"TkDefaultFont\"\n#define DEF_MESSAGE_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_MESSAGE_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_MESSAGE_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MESSAGE_JUSTIFY\t\t\"left\"\n#define DEF_MESSAGE_PADX\t\tNULL\n#define DEF_MESSAGE_PADY\t\tNULL\n#define DEF_MESSAGE_RELIEF\t\t\"flat\"\n#define DEF_MESSAGE_TAKE_FOCUS\t\t\"0\"\n#define DEF_MESSAGE_TEXT\t\t\"\"\n#define DEF_MESSAGE_TEXT_VARIABLE\t\"\"\n#define DEF_MESSAGE_WIDTH\t\t\"0\"\n/*\n * Defaults for panedwindows\n */\n\n#define DEF_PANEDWINDOW_BG_COLOR\tNORMAL_BG\n#define DEF_PANEDWINDOW_BG_MONO\t\tWHITE\n#define DEF_PANEDWINDOW_BORDERWIDTH\t\"1\"\n#define DEF_PANEDWINDOW_CURSOR\t\t\"\"\n#define DEF_PANEDWINDOW_HANDLEPAD\t\"8\"\n#define DEF_PANEDWINDOW_HANDLESIZE\t\"8\"\n#define DEF_PANEDWINDOW_HEIGHT\t\t\"\"\n#define DEF_PANEDWINDOW_OPAQUERESIZE\t\"1\"\n#define DEF_PANEDWINDOW_ORIENT\t\t\"horizontal\"\n#define DEF_PANEDWINDOW_PROXYBORDER\t\"2\"\n#define DEF_PANEDWINDOW_RELIEF\t\t\"flat\"\n#define DEF_PANEDWINDOW_SASHCURSOR\t\"\"\n#define DEF_PANEDWINDOW_SASHPAD\t\t\"0\"\n#define DEF_PANEDWINDOW_SASHRELIEF\t\"flat\"\n#define DEF_PANEDWINDOW_SASHWIDTH\t\"3\"\n#define DEF_PANEDWINDOW_SHOWHANDLE\t\"0\"\n#define DEF_PANEDWINDOW_WIDTH\t\t\"\"\n\n/*\n * Defaults for panedwindow panes\n */\n\n#define DEF_PANEDWINDOW_PANE_AFTER\t\"\"\n#define DEF_PANEDWINDOW_PANE_BEFORE\t\"\"\n#define DEF_PANEDWINDOW_PANE_HEIGHT\t\"\"\n#define DEF_PANEDWINDOW_PANE_MINSIZE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADX\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADY\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STICKY\t\"nsew\"\n#define DEF_PANEDWINDOW_PANE_WIDTH\t\"\"\n#define DEF_PANEDWINDOW_PANE_HIDE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STRETCH\t\"last\"\n\n/*\n * Defaults for scales:\n */\n\n#define DEF_SCALE_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCALE_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCALE_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCALE_BG_MONO\t\tWHITE\n#define DEF_SCALE_BIG_INCREMENT\t\t\"0.0\"\n#define DEF_SCALE_BORDER_WIDTH\t\t\"1\"\n#define DEF_SCALE_COMMAND\t\t\"\"\n#define DEF_SCALE_CURSOR\t\t\"\"\n#define DEF_SCALE_DIGITS\t\t\"0\"\n#define DEF_SCALE_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_SCALE_FG_COLOR\t\tNORMAL_FG\n#define DEF_SCALE_FG_MONO\t\tBLACK\n#define DEF_SCALE_FROM\t\t\t\"0.0\"\n#define DEF_SCALE_HIGHLIGHT_BG_COLOR\tDEF_SCALE_BG_COLOR\n#define DEF_SCALE_HIGHLIGHT_BG_MONO\tDEF_SCALE_BG_MONO\n#define DEF_SCALE_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_SCALE_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_SCALE_LABEL\t\t\t\"\"\n#define DEF_SCALE_LENGTH\t\t\"100\"\n#define DEF_SCALE_ORIENT\t\t\"vertical\"\n#define DEF_SCALE_RELIEF\t\t\"flat\"\n#define DEF_SCALE_REPEAT_DELAY\t\"300\"\n#define DEF_SCALE_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCALE_RESOLUTION\t\t\"1.0\"\n#define DEF_SCALE_TROUGH_COLOR\t\tTROUGH\n#define DEF_SCALE_TROUGH_MONO\t\tWHITE\n#define DEF_SCALE_SHOW_VALUE\t\t\"1\"\n#define DEF_SCALE_SLIDER_LENGTH\t\t\"30\"\n#define DEF_SCALE_SLIDER_RELIEF\t\t\"raised\"\n#define DEF_SCALE_STATE\t\t\t\"normal\"\n#define DEF_SCALE_TAKE_FOCUS\t\tNULL\n#define DEF_SCALE_TICK_INTERVAL\t\t\"0.0\"\n#define DEF_SCALE_TO\t\t\t\"100.0\"\n#define DEF_SCALE_VARIABLE\t\t\"\"\n#define DEF_SCALE_WIDTH\t\t\t\"15\"\n\n/*\n * Defaults for scrollbars:\n */\n\n#define DEF_SCROLLBAR_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCROLLBAR_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCROLLBAR_ACTIVE_RELIEF\t\"raised\"\n#define DEF_SCROLLBAR_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCROLLBAR_BG_MONO\t\tWHITE\n#define DEF_SCROLLBAR_BORDER_WIDTH\t\"0\"\n#define DEF_SCROLLBAR_COMMAND\t\t\"\"\n#define DEF_SCROLLBAR_CURSOR\t\t\"\"\n#define DEF_SCROLLBAR_EL_BORDER_WIDTH\tNULL\n#define DEF_SCROLLBAR_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_SCROLLBAR_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_SCROLLBAR_JUMP\t\t\"0\"\n#define DEF_SCROLLBAR_ORIENT\t\t\"vertical\"\n#define DEF_SCROLLBAR_RELIEF\t\t\"flat\"\n#define DEF_SCROLLBAR_REPEAT_DELAY\t\"300\"\n#define DEF_SCROLLBAR_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCROLLBAR_TAKE_FOCUS\tNULL\n#define DEF_SCROLLBAR_TROUGH_COLOR\tTROUGH\n#define DEF_SCROLLBAR_TROUGH_MONO\tWHITE\n#define DEF_SCROLLBAR_WIDTH\t\t\"15\"\n\n/*\n * Defaults for texts:\n */\n\n#define DEF_TEXT_AUTO_SEPARATORS\t\"1\"\n#define DEF_TEXT_BG_COLOR\t\tTEXT_BG\n#define DEF_TEXT_BG_MONO\t\tWHITE\n#define DEF_TEXT_BLOCK_CURSOR\t\t\"0\"\n#define DEF_TEXT_BORDER_WIDTH\t\t\"0\"\n#define DEF_TEXT_CURSOR\t\t\t\"xterm\"\n#define DEF_TEXT_FG\t\t\tNORMAL_FG\n#define DEF_TEXT_EXPORT_SELECTION\t\"1\"\n#define DEF_TEXT_FONT\t\t\t\"TkFixedFont\"\n#define DEF_TEXT_HEIGHT\t\t\t\"24\"\n#define DEF_TEXT_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_TEXT_HIGHLIGHT\t\tNORMAL_FG\n#define DEF_TEXT_HIGHLIGHT_WIDTH\t\"3\"\n#define DEF_TEXT_INSERT_BG\t\tNORMAL_FG\n#define DEF_TEXT_INSERT_BD_COLOR\t\"0\"\n#define DEF_TEXT_INSERT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_INSERT_OFF_TIME\t\"300\"\n#define DEF_TEXT_INSERT_ON_TIME\t\t\"600\"\n#define DEF_TEXT_INSERT_UNFOCUSSED\t\"none\"\n#define DEF_TEXT_INSERT_WIDTH\t\t\"1\"\n#define DEF_TEXT_MAX_UNDO\t\t\"0\"\n#define DEF_TEXT_PADX\t\t\t\"1\"\n#define DEF_TEXT_PADY\t\t\t\"1\"\n#define DEF_TEXT_RELIEF\t\t\t\"flat\"\n#define DEF_TEXT_INACTIVE_SELECT_BG_COLOR\tINACTIVE_SELECT_BG\n#define DEF_TEXT_SELECT_COLOR\t\tSELECT_BG\n#define DEF_TEXT_SELECT_MONO\t\tBLACK\n#define DEF_TEXT_SELECT_BD_COLOR\t\"1\"\n#define DEF_TEXT_SELECT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_TEXT_SELECT_FG_MONO\t\tWHITE\n#define DEF_TEXT_SELECT_RELIEF\t\t\"flat\"\n#define DEF_TEXT_SET_GRID\t\t\"0\"\n#define DEF_TEXT_SPACING1\t\t\"0\"\n#define DEF_TEXT_SPACING2\t\t\"0\"\n#define DEF_TEXT_SPACING3\t\t\"0\"\n#define DEF_TEXT_STATE\t\t\t\"normal\"\n#define DEF_TEXT_TABS\t\t\t\"\"\n#define DEF_TEXT_TABSTYLE\t\t\"tabular\"\n#define DEF_TEXT_TAKE_FOCUS\t\tNULL\n#define DEF_TEXT_UNDO\t\t\t\"0\"\n#define DEF_TEXT_WIDTH\t\t\t\"80\"\n#define DEF_TEXT_WRAP\t\t\t\"char\"\n#define DEF_TEXT_XSCROLL_COMMAND\t\"\"\n#define DEF_TEXT_YSCROLL_COMMAND\t\"\"\n\n/*\n * Defaults for canvas text:\n */\n\n#define DEF_CANVTEXT_FONT\t\t\"TkDefaultFont\"\n\n/*\n * Defaults for canvas items\n * (arcs, bitmaps, lines, polygons, rectangles, and ovals):\n */\n\n#define DEF_CANVBMAP_FG\t\t\tNORMAL_FG\n#define DEF_CANVITEM_OUTLINE\t\tNORMAL_FG\n\n/*\n * Defaults for toplevels (most of the defaults for frames also apply\n * to toplevels):\n */\n\n#define DEF_TOPLEVEL_CLASS\t\t\"Toplevel\"\n#define DEF_TOPLEVEL_MENU\t\t\"\"\n#define DEF_TOPLEVEL_SCREEN\t\t\"\"\n#define DEF_TOPLEVEL_USE\t\t\"\"\n\n/*\n * Defaults for busy windows (not really used yet):\n */\n\n#define DEF_BUSY_CURSOR\t\t\t\"watch\"\n\n#endif /* _TKMACDEFAULT */\n"
  },
  {
    "path": "macosx/tkMacOSXDialog.c",
    "content": "/*\n * tkMacOSXDialog.c --\n *\n *\tContains the Mac implementation of the common dialog boxes.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2017 Christian Gollwitzer\n * Copyright © 2022 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkFileFilter.h\"\n#include \"tkMacOSXConstants.h\"\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090\n#define modalOK     NSOKButton\n#define modalCancel NSCancelButton\n#else\n#define modalOK     NSModalResponseOK\n#define modalCancel NSModalResponseCancel\n#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090\n#define modalOther  -1 // indicates that the -command option was used.\n#define modalError  -2\n\nstatic void setAllowedFileTypes(\n    NSSavePanel *panel,\n    NSMutableArray *extensions)\n{\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000\n/* UTType exists in the SDK */\n    if (@available(macOS 11.0, *)) {\n\tNSMutableArray<UTType *> *allowedTypes = [NSMutableArray array];\n\tfor (NSString *ext in extensions) {\n\t    UTType *uttype = [UTType typeWithFilenameExtension: ext];\n\t    if (uttype) {\n\t\t[allowedTypes addObject:uttype];\n\t    }\n\t}\n\t[panel setAllowedContentTypes:allowedTypes];\n    } else {\n# if MAC_OS_X_VERSION_MIN_REQUIRED < 110000\n/* setAllowedFileTypes is not deprecated */\n\t[panel setAllowedFileTypes:extensions];\n#endif\n    }\n#else\n    [panel setAllowedFileTypes:extensions];\n#endif\n}\n\n/*\n * Vars for filtering in \"open file\" and \"save file\" dialogs.\n */\n\ntypedef struct {\n    bool doFileTypes;\t\t\t/* Show the accessory view which\n\t\t\t\t\t * displays the filter menu */\n    bool preselectFilter;\t\t/* A filter was selected by the\n\t\t\t\t\t * typevariable. */\n    bool userHasSelectedFilter;\t\t/* The user has changed the filter in\n\t\t\t\t\t * the accessory view. */\n    NSMutableArray *fileTypeNames;\t/* Array of names, e.g. \"Text\n\t\t\t\t\t * document\". */\n    NSMutableArray *fileTypeExtensions;\t/* Array of allowed extensions per\n\t\t\t\t\t * name, e.g. \"txt\", \"doc\". */\n    NSMutableArray *fileTypeLabels;\t/* Displayed string, e.g. \"Text\n\t\t\t\t\t * document (.txt, .doc)\". */\n    NSMutableArray *fileTypeAllowsAll;\t/* Boolean if the all pattern (*.*) is\n\t\t\t\t\t * included. */\n    NSMutableArray *allowedExtensions;\t/* Set of all allowed extensions. */\n    bool allowedExtensionsAllowAll;\t/* Set of all allowed extensions\n\t\t\t\t\t * includes *.* */\n    NSUInteger fileTypeIndex;\t\t/* Index of currently selected\n\t\t\t\t\t * filter. */\n} filepanelFilterInfo;\n\n/*\n * Only one of these is needed for the application, so they can be static.\n */\n\nstatic filepanelFilterInfo filterInfo;\nstatic NSOpenPanel *openpanel;\nstatic NSSavePanel *savepanel;\n\n/*\n * A thread which closes the currently running modal dialog after a timeout.\n */\n\n@interface TKPanelMonitor: NSThread {\n@private\n    NSTimeInterval _timeout;\n}\n\n- (id) initWithTimeout: (NSTimeInterval) timeout;\n\n@end\n\n@implementation TKPanelMonitor: NSThread\n\n- (id) initWithTimeout: (NSTimeInterval) timeout {\n    self = [super init];\n    if (self) {\n\t_timeout = timeout;\n\treturn self;\n    }\n    return self;\n}\n\n- (void) main\n{\n    [NSThread sleepForTimeInterval:_timeout];\n    if ([self isCancelled]) {\n\t[NSThread exit];\n    }\n    [NSApp stopModalWithCode:modalCancel];\n}\n@end\n\n\nstatic const char *const colorOptionStrings[] = {\n    \"-initialcolor\", \"-parent\", \"-title\", NULL\n};\nenum colorOptions {\n    COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE\n};\n\nstatic const char *const openOptionStrings[] = {\n    \"-command\", \"-defaultextension\", \"-filetypes\", \"-initialdir\",\n    \"-initialfile\", \"-message\", \"-multiple\", \"-parent\", \"-title\",\n    \"-typevariable\", NULL\n};\nenum openOptions {\n    OPEN_COMMAND, OPEN_DEFAULT, OPEN_FILETYPES, OPEN_INITDIR,\n    OPEN_INITFILE, OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE,\n    OPEN_TYPEVARIABLE\n};\nstatic const char *const saveOptionStrings[] = {\n    \"-command\", \"-confirmoverwrite\", \"-defaultextension\", \"-filetypes\",\n    \"-initialdir\", \"-initialfile\", \"-message\", \"-parent\", \"-title\",\n    \"-typevariable\", NULL\n};\nenum saveOptions {\n    SAVE_COMMAND, SAVE_CONFIRMOW, SAVE_DEFAULT, SAVE_FILETYPES,\n    SAVE_INITDIR, SAVE_INITFILE, SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE,\n    SAVE_TYPEVARIABLE\n};\nstatic const char *const chooseOptionStrings[] = {\n    \"-command\", \"-initialdir\", \"-message\", \"-mustexist\", \"-parent\", \"-title\",\n    NULL\n};\nenum chooseOptions {\n    CHOOSE_COMMAND, CHOOSE_INITDIR, CHOOSE_MESSAGE, CHOOSE_MUSTEXIST,\n    CHOOSE_PARENT, CHOOSE_TITLE\n};\ntypedef struct {\n    Tcl_Interp *interp;\n    Tcl_Obj *cmdObj;\n    int multiple;\n} FilePanelCallbackInfo;\n\nstatic const char *const alertOptionStrings[] = {\n    \"-default\", \"-detail\", \"-icon\", \"-message\", \"-parent\", \"-title\",\n    \"-type\", \"-command\", NULL\n};\nenum alertOptions {\n    ALERT_DEFAULT, ALERT_DETAIL, ALERT_ICON, ALERT_MESSAGE, ALERT_PARENT,\n    ALERT_TITLE, ALERT_TYPE, ALERT_COMMAND\n};\ntypedef struct {\n    Tcl_Interp *interp;\n    Tcl_Obj *cmdObj;\n    int typeIndex;\n} AlertCallbackInfo;\nstatic const char *const alertTypeStrings[] = {\n    \"abortretryignore\", \"ok\", \"okcancel\", \"retrycancel\", \"yesno\",\n    \"yesnocancel\", NULL\n};\nenum alertTypeOptions {\n    TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL,\n    TYPE_YESNO, TYPE_YESNOCANCEL\n};\nstatic const char *const alertIconStrings[] = {\n    \"error\", \"info\", \"question\", \"warning\", NULL\n};\nenum alertIconOptions {\n    ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING\n};\nstatic const char *const alertButtonStrings[] = {\n    \"abort\", \"retry\", \"ignore\", \"ok\", \"cancel\", \"no\", \"yes\", NULL\n};\n\nstatic const NSString *const alertButtonNames[][3] = {\n    [TYPE_ABORTRETRYIGNORE] =   {@\"Abort\", @\"Retry\", @\"Ignore\"},\n    [TYPE_OK] =\t\t\t{@\"OK\"},\n    [TYPE_OKCANCEL] =\t\t{@\"OK\", @\"Cancel\"},\n    [TYPE_RETRYCANCEL] =\t{@\"Retry\", @\"Cancel\"},\n    [TYPE_YESNO] =\t\t{@\"Yes\", @\"No\"},\n    [TYPE_YESNOCANCEL] =\t{@\"Yes\", @\"No\", @\"Cancel\"},\n};\nstatic const NSAlertStyle alertStyles[] = {\n    [ICON_ERROR] =\t\tNSWarningAlertStyle,\n    [ICON_INFO] =\t\tNSInformationalAlertStyle,\n    [ICON_QUESTION] =\t\tNSWarningAlertStyle,\n    [ICON_WARNING] =\t\tNSCriticalAlertStyle,\n};\n\n/*\n * Need to map from 'alertButtonStrings' and its corresponding integer, index\n * to the native button index, which is 1, 2, 3, from right to left. This is\n * necessary to do for each separate '-type' of button sets.\n */\n\nstatic const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = {\n\t\t\t    /*  abort retry ignore ok   cancel yes   no */\n    [TYPE_ABORTRETRYIGNORE] =   {1,    2,    3,    0,    0,    0,    0},\n    [TYPE_OK] =\t\t\t{0,    0,    0,    1,    0,    0,    0},\n    [TYPE_OKCANCEL] =\t\t{0,    0,    0,    1,    2,    0,    0},\n    [TYPE_RETRYCANCEL] =\t{0,    1,    0,    0,    2,    0,    0},\n    [TYPE_YESNO] =\t\t{0,    0,    0,    0,    0,    2,    1},\n    [TYPE_YESNOCANCEL] =\t{0,    0,    0,    0,    3,    2,    1},\n};\n\n/*\n * Need also the inverse mapping, from NSAlertFirstButtonReturn etc to the\n * descriptive button text string index.\n */\n\nstatic const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {\n    [TYPE_ABORTRETRYIGNORE] =   {0, 1, 2},\n    [TYPE_OK] =\t\t\t{3, 0, 0},\n    [TYPE_OKCANCEL] =\t\t{3, 4, 0},\n    [TYPE_RETRYCANCEL] =\t{1, 4, 0},\n    [TYPE_YESNO] =\t\t{6, 5, 0},\n    [TYPE_YESNOCANCEL] =\t{6, 5, 4},\n};\n\n/*\n * Construct a file URL from directory and filename. Either may be nil. If both\n * are nil, returns nil.\n */\n\nstatic NSURL *\ngetFileURL(\n    NSString *directory,\n    NSString *filename)\n{\n    NSURL *url = nil;\n    if (directory) {\n\turl = [NSURL fileURLWithPath:directory isDirectory:YES];\n    }\n    if (filename) {\n\turl = [NSURL URLWithString:filename relativeToURL:url];\n    }\n    return url;\n}\n\f\n#pragma mark TKApplication(TKDialog)\n\n@implementation TKApplication(TKDialog)\n\n- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {\n\t(void)sender;\n\t(void)url;\n    return YES;\n}\n\n- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url {\n    (void)sender;\n    (void)url;\n}\n\n- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError {\n    (void)sender;\n    (void)url;\n    *outError = nil;\n    return YES;\n}\n\n- (void) tkFilePanelDidEnd: (NSSavePanel *) panel\n\t\treturnCode: (NSModalResponse) returnCode\n\t       contextInfo: (const void *) contextInfo\n{\n    const FilePanelCallbackInfo *callbackInfo = (const FilePanelCallbackInfo *)contextInfo;\n\n    if (returnCode == modalOK) {\n\tTcl_Obj *resultObj;\n\n\tif (callbackInfo->multiple) {\n\t    resultObj = Tcl_NewListObj(0, NULL);\n\t    for (NSURL *url in [(NSOpenPanel*)panel URLs]) {\n\t\tTcl_ListObjAppendElement(callbackInfo->interp, resultObj,\n\t\t\tTcl_NewStringObj([[url path] UTF8String], TCL_INDEX_NONE));\n\t    }\n\t} else {\n\t    resultObj = Tcl_NewStringObj([[[panel URL]path] UTF8String], TCL_INDEX_NONE);\n\t}\n\tif (callbackInfo->cmdObj) {\n\t    Tcl_Obj **objv, **tmpv;\n\t    Tcl_Size objc;\n\t    int result = Tcl_ListObjGetElements(callbackInfo->interp,\n\t\t    callbackInfo->cmdObj, &objc, &objv);\n\n\t    if (result == TCL_OK && objc) {\n\t\ttmpv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * (objc + 2));\n\t\tmemcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);\n\t\ttmpv[objc] = resultObj;\n\t\tTkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,\n\t\t\tTCL_EVAL_GLOBAL);\n\t\tTcl_Free(tmpv);\n\t    }\n\t} else {\n\t    Tcl_SetObjResult(callbackInfo->interp, resultObj);\n\t}\n    } else if (returnCode == modalCancel) {\n\tTcl_ResetResult(callbackInfo->interp);\n    }\n    [NSApp stopModalWithCode:returnCode];\n}\n\n- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode\n\tcontextInfo: (const void *) contextInfo\n{\n    AlertCallbackInfo *callbackInfo = (AlertCallbackInfo *)contextInfo;\n\n    if (returnCode >= NSAlertFirstButtonReturn) {\n\tTcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[\n\t\talertNativeButtonIndexAndTypeToButtonIndex[callbackInfo->\n\t\ttypeIndex][returnCode - NSAlertFirstButtonReturn]], TCL_INDEX_NONE);\n\n\tif (callbackInfo->cmdObj) {\n\t    Tcl_Obj **objv, **tmpv;\n\t    Tcl_Size objc;\n\t    int result = Tcl_ListObjGetElements(callbackInfo->interp,\n\t\t    callbackInfo->cmdObj, &objc, &objv);\n\n\t    if (result == TCL_OK && objc) {\n\t\ttmpv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * (objc + 2));\n\t\tmemcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);\n\t\ttmpv[objc] = resultObj;\n\t\tTkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,\n\t\t\tTCL_EVAL_GLOBAL);\n\t\tTcl_Free(tmpv);\n\t    }\n\t} else {\n\t    Tcl_SetObjResult(callbackInfo->interp, resultObj);\n\t}\n    }\n    if ([alert window] == [NSApp modalWindow]) {\n\t[NSApp stopModalWithCode:returnCode];\n    }\n}\n\n- (void)selectFormat:(id)sender  {\n    NSPopUpButton *button      = (NSPopUpButton *)sender;\n    filterInfo.fileTypeIndex   = (NSUInteger)[button indexOfSelectedItem];\n    if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {\n\t[openpanel setAllowsOtherFileTypes:YES];\n\n\t/*\n\t * setAllowsOtherFileTypes might have no effect; it's inherited from\n\t * the NSSavePanel, where it has the effect that it does not append an\n\t * extension. Setting the allowed file types to nil allows selecting\n\t * any file.\n\t */\n\n\tsetAllowedFileTypes(openpanel, nil);\n    } else {\n\tNSMutableArray *allowedtypes =\n\t\t[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];\n\tsetAllowedFileTypes(openpanel, allowedtypes);\n\t[openpanel setAllowsOtherFileTypes:NO];\n    }\n\n    filterInfo.userHasSelectedFilter = true;\n}\n\n- (void)saveFormat:(id)sender  {\n    NSPopUpButton *button     = (NSPopUpButton *)sender;\n    filterInfo.fileTypeIndex  = (NSUInteger)[button indexOfSelectedItem];\n\n    if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {\n\t[savepanel setAllowsOtherFileTypes:YES];\n\tsetAllowedFileTypes(savepanel, nil);\n    } else {\n\tNSMutableArray *allowedtypes =\n\t\t[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];\n\tsetAllowedFileTypes(savepanel, allowedtypes);\n\t[savepanel setAllowsOtherFileTypes:NO];\n    }\n\n    filterInfo.userHasSelectedFilter = true;\n}\n\n@end\n\n#pragma mark -\n\f\nstatic NSInteger showOpenSavePanel(\n    NSSavePanel *panel,\n    NSWindow *parent,\n    Tcl_Interp *interp,\n    Tcl_Obj *cmdObj,\n    int multiple)\n{\n    NSInteger modalReturnCode;\n    int OSVersion = [NSApp macOSVersion];\n    const FilePanelCallbackInfo callbackInfo = {interp, cmdObj, multiple};\n\n    /*\n     * Use a sheet if -parent is specified (unless there is already a sheet).\n     */\n\n    if (parent && ![parent attachedSheet]) {\n\tif (OSVersion < 101500) {\n\t    [panel beginSheetModalForWindow:parent\n\t\t\t  completionHandler:^(NSModalResponse returnCode) {\n\t\t    [NSApp tkFilePanelDidEnd:panel\n\t\t\t\t  returnCode:returnCode\n\t\t\t\t contextInfo:&callbackInfo ];\n\t\t}];\n\t    modalReturnCode = [NSApp runModalForWindow:panel];\n\t} else if (OSVersion < 110000) {\n\t    [panel beginSheetModalForWindow:parent\n\t\t\t  completionHandler:^(NSModalResponse returnCode) {\n\t\t    [NSApp tkFilePanelDidEnd:panel\n\t\t\t\t  returnCode:returnCode\n\t\t\t\t contextInfo:&callbackInfo ];\n\t\t}];\n\t    modalReturnCode = [panel runModal];\n\t} else {\n\t    [parent beginSheet: panel completionHandler:nil];\n\t    modalReturnCode = [panel runModal];\n\t    [NSApp tkFilePanelDidEnd:panel\n\t\t\t  returnCode:modalReturnCode\n\t\t\t contextInfo:&callbackInfo ];\n\t    [parent endSheet:panel];\n\t}\n    } else {\n\tmodalReturnCode = [panel runModal];\n\t[NSApp tkFilePanelDidEnd:panel\n\t\t      returnCode:modalReturnCode\n\t\t     contextInfo:&callbackInfo ];\n    }\n    return cmdObj ? modalOther : modalReturnCode;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ChooseColorObjCmd --\n *\n *\tThis procedure implements the color dialog box for the Mac platform.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ChooseColorObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int result = TCL_ERROR;\n    Tk_Window parent, tkwin = (Tk_Window)clientData;\n    const char *title = NULL;\n    Tcl_Size i;\n    NSColor *color = nil, *initialColor = nil;\n    NSColorPanel *colorPanel;\n    NSInteger returnCode, numberOfComponents = 0;\n\n    for (i = 1; i < objc; i += 2) {\n\tint index;\n\tconst char *value;\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], colorOptionStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"COLORDIALOG\", \"VALUE\", (char *)NULL);\n\t    goto end;\n\t}\n\tvalue = Tcl_GetString(objv[i + 1]);\n\n\tswitch (index) {\n\tcase COLOR_INITIAL: {\n\t    XColor *colorPtr;\n\n\t    colorPtr = Tk_AllocColorFromObj(interp, tkwin, objv[i + 1]);\n\t    if (colorPtr == NULL) {\n\t\tgoto end;\n\t    }\n\t    initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);\n\t    Tk_FreeColor(colorPtr);\n\t    break;\n\t}\n\tcase COLOR_PARENT:\n\t    parent = Tk_NameToWindow(interp, value, tkwin);\n\t    if (parent == NULL) {\n\t\tgoto end;\n\t    }\n\t    break;\n\tcase COLOR_TITLE:\n\t    title = value;\n\t    break;\n\t}\n    }\n    colorPanel = [NSColorPanel sharedColorPanel];\n    [colorPanel orderOut:NSApp];\n    [colorPanel setContinuous:NO];\n    [colorPanel setBecomesKeyOnlyIfNeeded:NO];\n    [colorPanel setShowsAlpha: NO];\n    [colorPanel _setUseModalAppearance:YES];\n    if (title) {\n\tNSString *s = [[TKNSString alloc] initWithTclUtfBytes:title length:TCL_INDEX_NONE];\n\n\t[colorPanel setTitle:s];\n\t[s release];\n    }\n    if (initialColor) {\n\t[colorPanel setColor:initialColor];\n    }\n    returnCode = [NSApp runModalForWindow:colorPanel];\n    if (returnCode == modalOK) {\n\tcolor = [[colorPanel color] colorUsingColorSpace:\n\t\t[NSColorSpace deviceRGBColorSpace]];\n\tnumberOfComponents = [color numberOfComponents];\n    }\n    if (color && numberOfComponents >= 3 && numberOfComponents <= 4) {\n\tCGFloat components[4];\n\tchar colorstr[8];\n\n\t[color getComponents:components];\n\tsnprintf(colorstr, 8, \"#%02x%02x%02x\",\n\t\t(short)(components[0] * 255),\n\t\t(short)(components[1] * 255),\n\t\t(short)(components[2] * 255));\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(colorstr, 7));\n    } else {\n\tTcl_ResetResult(interp);\n    }\n    result = TCL_OK;\n\nend:\n    return result;\n}\n\n/*\n * Dissect the -filetype nested lists and store the information in the\n * filterInfo structure.\n */\n\nstatic int\nparseFileFilters(\n    Tcl_Interp *interp,\n    Tcl_Obj *fileTypesPtr,\n    Tcl_Obj *typeVariablePtr)\n{\n\n    if (!fileTypesPtr) {\n\tfilterInfo.doFileTypes = false;\n\treturn TCL_OK;\n    }\n\n    FileFilterList fl;\n\n    TkInitFileFilters(&fl);\n    if (TkGetFileFilters(interp, &fl, fileTypesPtr, false) != TCL_OK) {\n\tTkFreeFileFilters(&fl);\n\treturn TCL_ERROR;\n    }\n\n    filterInfo.doFileTypes = (fl.filters != NULL);\n\n    filterInfo.fileTypeIndex = 0;\n    filterInfo.fileTypeExtensions = [NSMutableArray array];\n    filterInfo.fileTypeNames = [NSMutableArray array];\n    filterInfo.fileTypeLabels = [NSMutableArray array];\n    filterInfo.fileTypeAllowsAll = [NSMutableArray array];\n\n    filterInfo.allowedExtensions = [NSMutableArray array];\n    filterInfo.allowedExtensionsAllowAll = NO;\n\n    if (filterInfo.doFileTypes) {\n\tfor (FileFilter *filterPtr = fl.filters; filterPtr;\n\t\tfilterPtr = filterPtr->next) {\n\t    NSString *name = [[TKNSString alloc] initWithTclUtfBytes: filterPtr->name length:TCL_INDEX_NONE];\n\n\t    [filterInfo.fileTypeNames addObject:name];\n\t    [name release];\n\t    NSMutableArray *clauseextensions = [NSMutableArray array];\n\t    NSMutableArray *displayextensions = [NSMutableArray array];\n\t    bool allowsAll = NO;\n\n\t    for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr;\n\t\t    clausePtr = clausePtr->next) {\n\n\t\tfor (GlobPattern *globPtr = clausePtr->patterns; globPtr;\n\t\t\tglobPtr = globPtr->next) {\n\t\t    const char *str = globPtr->pattern;\n\t\t    while (*str && (*str == '*' || *str == '.')) {\n\t\t\tstr++;\n\t\t    }\n\t\t    if (*str) {\n\t\t\tNSString *extension = [[TKNSString alloc] initWithTclUtfBytes:str length:TCL_INDEX_NONE];\n\t\t\tif (![filterInfo.allowedExtensions containsObject:extension]) {\n\t\t\t    [filterInfo.allowedExtensions addObject:extension];\n\t\t\t}\n\n\t\t\t[clauseextensions addObject:extension];\n\t\t\t[displayextensions addObject:[@\".\" stringByAppendingString:extension]];\n\n\t\t\t[extension release];\n\t\t    } else {\n\t\t\t/*\n\t\t\t * It is the all pattern (*, .* or *.*)\n\t\t\t */\n\n\t\t\tallowsAll = YES;\n\t\t\tfilterInfo.allowedExtensionsAllowAll = YES;\n\t\t\t[displayextensions addObject:@\"*\"];\n\t\t    }\n\t\t}\n\t    }\n\t    [filterInfo.fileTypeExtensions addObject:clauseextensions];\n\t    [filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]];\n\n\t    NSMutableString *label = [[NSMutableString alloc] initWithString:name];\n\t    [label appendString:@\" (\"];\n\t    [label appendString:[displayextensions componentsJoinedByString:@\", \"]];\n\t    [label appendString:@\")\"];\n\t    [filterInfo.fileTypeLabels addObject:label];\n\t    [label release];\n\t}\n\n\t/*\n\t * Check if the typevariable exists and matches one of the names.\n\t */\n\n\tfilterInfo.preselectFilter = false;\n\tfilterInfo.userHasSelectedFilter = false;\n\tif (typeVariablePtr) {\n\t    /*\n\t     * Extract the variable content as a NSString.\n\t     */\n\n\t    Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp,\n\t\t    typeVariablePtr, NULL, TCL_GLOBAL_ONLY);\n\n\t    /*\n\t     * Check that the typevariable exists.\n\t     */\n\n\t    if (selectedFileTypeObj != NULL) {\n\t\tconst char *selectedFileType =\n\t\t\tTcl_GetString(selectedFileTypeObj);\n\t\tNSString *selectedFileTypeStr =\n\t\t\t[[TKNSString alloc] initWithTclUtfBytes:selectedFileType length:TCL_INDEX_NONE];\n\t\tNSUInteger index =\n\t\t\t[filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];\n\n\t\tif (index != NSNotFound) {\n\t\t    filterInfo.fileTypeIndex = index;\n\t\t    filterInfo.preselectFilter = true;\n\t\t}\n\t    }\n\t}\n\n    }\n\n    TkFreeFileFilters(&fl);\n    return TCL_OK;\n}\n\nstatic bool\nfilterCompatible(\n    NSString *extension,\n\tNSUInteger filterIndex)\n{\n    NSMutableArray *allowedExtensions =\n\t    [filterInfo.fileTypeExtensions objectAtIndex: filterIndex];\n\n    /*\n     * If this contains the all pattern, accept any extension.\n     */\n\n    if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) {\n\treturn true;\n    }\n\n    return [allowedExtensions containsObject: extension];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOpenFileObjCmd --\n *\n *\tThis procedure implements the \"open file\" dialog box for the Mac\n *\tplatform. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee user documentation.\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetOpenFileObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    char *str;\n    Tcl_Size i;\n    int result = TCL_ERROR, haveParentOption = 0;\n    int index, multiple = 0;\n    Tcl_Size len;\n    Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL;\n    NSString *directory = nil, *filename = nil;\n    NSString *message = nil, *title = nil;\n    NSWindow *parent;\n    openpanel =  [NSOpenPanel openPanel];\n    NSInteger modalReturnCode = modalError;\n    BOOL parentIsKey = NO;\n\n    for (i = 1; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FILEDIALOG\", \"VALUE\", (char *)NULL);\n\t    goto end;\n\t}\n\tswitch (index) {\n\tcase OPEN_DEFAULT:\n\t    break;\n\tcase OPEN_FILETYPES:\n\t    fileTypesPtr = objv[i + 1];\n\t    break;\n\tcase OPEN_INITDIR:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    if (len) {\n\t\tdirectory = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\tautorelease];\n\t    }\n\t    break;\n\tcase OPEN_INITFILE:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    if (len) {\n\t\tfilename = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\tautorelease];\n\t    }\n\t    break;\n\tcase OPEN_MESSAGE:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    message = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:len];\n\t    break;\n\tcase OPEN_MULTIPLE:\n\t    if (Tcl_GetBooleanFromObj(interp, objv[i + 1],\n\t\t    &multiple) != TCL_OK) {\n\t\tgoto end;\n\t    }\n\t    break;\n\tcase OPEN_PARENT:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    tkwin = Tk_NameToWindow(interp, str, tkwin);\n\t    if (!tkwin) {\n\t\tgoto end;\n\t    }\n\t    haveParentOption = 1;\n\t    break;\n\tcase OPEN_TITLE:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    title = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:len];\n\t    break;\n\tcase OPEN_TYPEVARIABLE:\n\t    typeVariablePtr = objv[i + 1];\n\t    break;\n\tcase OPEN_COMMAND:\n\t    cmdObj = objv[i+1];\n\t    break;\n\t}\n    }\n    if (title) {\n\t[openpanel setTitle:title];\n\n\t/*\n\t * From OSX 10.11, the title string is silently ignored in the open\n\t * panel.  Prepend the title to the message in this case.\n\t */\n\n\tif ([NSApp macOSVersion] >= 101100) {\n\t    if (message) {\n\t\tNSString *fullmessage =\n\t\t    [[NSString alloc] initWithFormat:@\"%@\\n%@\", title, message];\n\t\t[message release];\n\t\t[title release];\n\t\tmessage = fullmessage;\n\t    } else {\n\t\tmessage = title;\n\t    }\n\t}\n    }\n\n    if (message) {\n\t[openpanel setMessage:message];\n\t[message release];\n    }\n\n    [openpanel setAllowsMultipleSelection:multiple != 0];\n\n    if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) {\n\tgoto end;\n    }\n\n    if (filterInfo.doFileTypes) {\n\tNSTextField *label = [[NSTextField alloc]\n\t\tinitWithFrame:NSMakeRect(0, 0, 60, 22)];\n\tNSPopUpButton *popupButton = [[NSPopUpButton alloc]\n\t\tinitWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];\n\tNSView *accessoryView = [[NSView alloc]\n\t\tinitWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];\n\n\t[label setEditable:NO];\n\t[label setStringValue:@\"Filter:\"];\n\t[label setBordered:NO];\n\t[label setBezeled:NO];\n\t[label setDrawsBackground:NO];\n\t[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];\n\t[popupButton setTarget:NSApp];\n\t[popupButton setAction:@selector(selectFormat:)];\n\t[accessoryView addSubview:label];\n\t[accessoryView addSubview:popupButton];\n\tif (filterInfo.preselectFilter) {\n\n\t    /*\n\t     * A specific filter was selected from the typevariable. Select it\n\t     * and open the accessory view.\n\t     */\n\n\t    [popupButton selectItemAtIndex:(NSInteger)filterInfo.fileTypeIndex];\n\n\t    /*\n\t     * On OSX > 10.11, the options are not visible by default. Ergo\n\t     * allow all file types\n\t    [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];\n\t    */\n\n\t    setAllowedFileTypes(openpanel, filterInfo.allowedExtensions);\n\t} else {\n\t    setAllowedFileTypes(openpanel, filterInfo.allowedExtensions);\n\t}\n\tif (filterInfo.allowedExtensionsAllowAll) {\n\t    [openpanel setAllowsOtherFileTypes:YES];\n\t} else {\n\t    [openpanel setAllowsOtherFileTypes:NO];\n\t}\n\t[openpanel setAccessoryView:accessoryView];\n    } else {\n\t/*\n\t * No filters are given. Allow picking all files.\n\t */\n\n\t[openpanel setAllowsOtherFileTypes:YES];\n    }\n    if (cmdObj) {\n\tif (Tcl_IsShared(cmdObj)) {\n\t    cmdObj = Tcl_DuplicateObj(cmdObj);\n\t}\n\tTcl_IncrRefCount(cmdObj);\n    }\n    if (directory || filename) {\n\tNSURL *fileURL = getFileURL(directory, filename);\n\n\t[openpanel setDirectoryURL:fileURL];\n    }\n    if (haveParentOption) {\n\tparent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);\n\tparentIsKey = parent && [parent isKeyWindow];\n    } else {\n\tparent = nil;\n\tparentIsKey = False;\n    }\n    TKPanelMonitor *monitor;\n    if (testsAreRunning) {\n\t/*\n\t * We need the panel to close by itself when running tests.\n\t */\n\n\tmonitor = [[TKPanelMonitor alloc] initWithTimeout: 1.0];\n\t[monitor start];\n    }\n    modalReturnCode = showOpenSavePanel(openpanel, parent, interp, cmdObj,\n\t\t\t\t\tmultiple);\n    if (testsAreRunning) {\n\t[monitor cancel];\n    }\n    if (cmdObj) {\n\tTcl_DecrRefCount(cmdObj);\n    }\n    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;\n    if (parentIsKey) {\n\t[parent makeKeyWindow];\n    }\n    if ((typeVariablePtr && (modalReturnCode == NSOKButton))\n\t    && filterInfo.doFileTypes) {\n\t/*\n\t * The -typevariable must be set to the selected file type, if the\n\t * dialog was not cancelled.\n\t */\n\n\tNSUInteger selectedFilterIndex = filterInfo.fileTypeIndex;\n\tNSString *selectedFilter = NULL;\n\n\tif (filterInfo.userHasSelectedFilter) {\n\t    selectedFilterIndex = filterInfo.fileTypeIndex;\n\t    selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];\n\t} else {\n\t    /*\n\t     * Difficult case: the user has not touched the filter settings,\n\t     * but we must return something in the typevariable. First check if\n\t     * the preselected type is compatible with the selected file,\n\t     * otherwise choose the first compatible type from the list,\n\t     * finally fall back to the empty string.\n\t     */\n\n\t    NSURL *selectedFile;\n\t    NSString *extension;\n\t    if (multiple) {\n\t\t/*\n\t\t * Use the first file in the case of multiple selection.\n\t\t * Anyway it is not overly useful here.\n\t\t */\n\t\tselectedFile = [[openpanel URLs] objectAtIndex:0];\n\t    } else {\n\t\tselectedFile = [openpanel URL];\n\t    }\n\n\t    extension = [selectedFile pathExtension];\n\n\t    if (filterInfo.preselectFilter &&\n\t\t    filterCompatible(extension, filterInfo.fileTypeIndex)) {\n\t\tselectedFilterIndex = filterInfo.fileTypeIndex;  // The preselection from the typevariable\n\t\tselectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];\n\t    } else {\n\t\tNSUInteger j;\n\n\t\tfor (j = 0; j < [filterInfo.fileTypeNames count]; j++) {\n\t\t    if (filterCompatible(extension, j)) {\n\t\t\tselectedFilterIndex = j;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tif (j == selectedFilterIndex) {\n\t\t    selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];\n\t\t} else {\n\t\t    selectedFilter = @\"\";\n\t\t}\n\t    }\n\t}\n\tTcl_ObjSetVar2(interp, typeVariablePtr, NULL,\n\t\tTcl_NewStringObj([selectedFilter UTF8String], TCL_INDEX_NONE),\n\t\tTCL_GLOBAL_ONLY);\n    }\n end:\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetSaveFileObjCmd --\n *\n *\tThis procedure implements the \"save file\" dialog box for the Mac\n *\tplatform. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetSaveFileObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    char *str;\n    Tcl_Size i;\n    int result = TCL_ERROR, haveParentOption = 0;\n    int confirmOverwrite = 1;\n    int index;\n    Tcl_Size len;\n    Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL;\n    NSString *directory = nil, *filename = nil, *defaultType = nil;\n    NSString *message = nil, *title = nil;\n    NSWindow *parent;\n    savepanel = [NSSavePanel savePanel];\n    NSInteger modalReturnCode = modalError;\n    BOOL parentIsKey = NO;\n\n    for (i = 1; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FILEDIALOG\", \"VALUE\", (char *)NULL);\n\t    goto end;\n\t}\n\tswitch (index) {\n\t    case SAVE_DEFAULT:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\twhile (*str && (*str == '*' || *str == '.')) {\n\t\t    str++; len--;\n\t\t}\n\t\tif (*str) {\n\t\t    defaultType = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\t    autorelease];\n\t\t}\n\t\tbreak;\n\t    case SAVE_FILETYPES:\n\t\tfileTypesPtr = objv[i + 1];\n\t\tbreak;\n\t    case SAVE_INITDIR:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\tif (len) {\n\t\t    directory = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\t    autorelease];\n\t\t}\n\t\tbreak;\n\t    case SAVE_INITFILE:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\tif (len) {\n\t\t    filename = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\t    autorelease];\n\t\t    [savepanel setNameFieldStringValue:filename];\n\t\t}\n\t\tbreak;\n\t    case SAVE_MESSAGE:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\tmessage = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t\tstr length:len];\n\t\tbreak;\n\t    case SAVE_PARENT:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\ttkwin = Tk_NameToWindow(interp, str, tkwin);\n\t\tif (!tkwin) {\n\t\t    goto end;\n\t\t}\n\t\thaveParentOption = 1;\n\t\tbreak;\n\t    case SAVE_TITLE:\n\t\tstr = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t\ttitle = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t\tstr length:len];\n\t\tbreak;\n\t    case SAVE_TYPEVARIABLE:\n\t\ttypeVariablePtr = objv[i + 1];\n\t\tbreak;\n\t    case SAVE_COMMAND:\n\t\tcmdObj = objv[i+1];\n\t\tbreak;\n\t    case SAVE_CONFIRMOW:\n\t\tif (Tcl_GetBooleanFromObj(interp, objv[i + 1],\n\t\t\t&confirmOverwrite) != TCL_OK) {\n\t\t    goto end;\n\t\t}\n\t\tbreak;\n\t}\n    }\n\n    if (title) {\n\t[savepanel setTitle:title];\n\n\t/*\n\t * From OSX 10.11, the title string is silently ignored, if the save\n\t * panel is a sheet.  Prepend the title to the message in this case.\n\t * NOTE: should be conditional on OSX version, but -mmacosx-version-min\n\t * does not revert this behaviour.\n\t */\n\n\tif (haveParentOption) {\n\t    if (message) {\n\t\tNSString *fullmessage =\n\t\t    [[NSString alloc] initWithFormat:@\"%@\\n%@\",title,message];\n\t\t[message release];\n\t\t[title release];\n\t\tmessage = fullmessage;\n\t    } else {\n\t\tmessage = title;\n\t    }\n\t}\n    }\n\n    if (message) {\n\t[savepanel setMessage:message];\n\t[message release];\n    }\n\n    if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) {\n\tgoto end;\n    }\n\n    if (filterInfo.doFileTypes) {\n\tNSView *accessoryView = [[NSView alloc]\n\t\tinitWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];\n\tNSTextField *label = [[NSTextField alloc]\n\t\tinitWithFrame:NSMakeRect(0, 0, 60, 22)];\n\n\t[label setEditable:NO];\n\t[label setStringValue:NSLocalizedString(@\"Format:\", nil)];\n\t[label setBordered:NO];\n\t[label setBezeled:NO];\n\t[label setDrawsBackground:NO];\n\n\tNSPopUpButton *popupButton = [[NSPopUpButton alloc]\n\t\tinitWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];\n\n\t[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];\n\t[popupButton selectItemAtIndex:(NSInteger)filterInfo.fileTypeIndex];\n\t[popupButton setTarget:NSApp];\n\t[popupButton setAction:@selector(saveFormat:)];\n\t[accessoryView addSubview:label];\n\t[accessoryView addSubview:popupButton];\n\n\t[savepanel setAccessoryView:accessoryView];\n\n\tsetAllowedFileTypes(savepanel,\n\t    [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]);\n\t[savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll];\n    } else if (defaultType) {\n\t/*\n\t * If no filetypes are given, defaultextension is an alternative way to\n\t * specify the attached extension. Just propose this extension, but\n\t * don't display an accessory view.\n\t */\n\n\tNSMutableArray *AllowedFileTypes = [NSMutableArray array];\n\n\t[AllowedFileTypes addObject:defaultType];\n\tsetAllowedFileTypes(savepanel, AllowedFileTypes);\n\t[savepanel setAllowsOtherFileTypes:YES];\n    }\n\n    [savepanel setCanSelectHiddenExtension:YES];\n    [savepanel setExtensionHidden:NO];\n\n    if (cmdObj) {\n\tif (Tcl_IsShared(cmdObj)) {\n\t    cmdObj = Tcl_DuplicateObj(cmdObj);\n\t}\n\tTcl_IncrRefCount(cmdObj);\n    }\n\n    if (directory) {\n\t[savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];\n    }\n\n    /*\n     * Check for file name and set to the empty string if nil. This prevents a crash\n     * with an uncaught exception.\n     */\n\n    if (filename) {\n\t[savepanel setNameFieldStringValue:filename];\n    } else {\n\t[savepanel setNameFieldStringValue:@\"\"];\n    }\n    if (haveParentOption) {\n\tparent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);\n\tparentIsKey = parent && [parent isKeyWindow];\n    } else {\n\tparent = nil;\n\tparentIsKey = False;\n    }\n    modalReturnCode = showOpenSavePanel(savepanel, parent, interp, cmdObj, 0);\n    if (cmdObj) {\n\tTcl_DecrRefCount(cmdObj);\n    }\n    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;\n    if (parentIsKey) {\n\t[parent makeKeyWindow];\n    }\n\n    if (typeVariablePtr && (modalReturnCode == NSOKButton)\n\t    && filterInfo.doFileTypes) {\n\t/*\n\t * The -typevariable must be set to the selected file type, if the\n\t * dialog was not cancelled.\n\t */\n\n\tNSString *selectedFilter =\n\t    [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];\n\tTcl_ObjSetVar2(interp, typeVariablePtr, NULL,\n\t\tTcl_NewStringObj([selectedFilter UTF8String], TCL_INDEX_NONE),\n\t\tTCL_GLOBAL_ONLY);\n    }\n\n  end:\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ChooseDirectoryObjCmd --\n *\n *\tThis procedure implements the \"tk_chooseDirectory\" dialog box for the\n *\tMacOS X platform. See the user documentation for details on what it\n *\tdoes.\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tA modal dialog window is created.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ChooseDirectoryObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    char *str;\n    int result = TCL_ERROR, haveParentOption = 0;\n    int index, mustexist = 0;\n    Tcl_Size len;\n    Tcl_Size i;\n    Tcl_Obj *cmdObj = NULL;\n    NSString *directory = nil;\n    NSString *message, *title;\n    NSWindow *parent;\n    NSOpenPanel *panel = [NSOpenPanel openPanel];\n    NSInteger modalReturnCode = modalError;\n    BOOL parentIsKey = NO;\n\n    for (i = 1; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"DIRDIALOG\", \"VALUE\", (char *)NULL);\n\t    goto end;\n\t}\n\tswitch (index) {\n\tcase CHOOSE_INITDIR:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    if (len) {\n\t\tdirectory = [[[TKNSString alloc] initWithTclUtfBytes:str length:len]\n\t\t\tautorelease];\n\t    }\n\t    break;\n\tcase CHOOSE_MESSAGE:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    message = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:len];\n\t    [panel setMessage:message];\n\t    [message release];\n\t    break;\n\tcase CHOOSE_MUSTEXIST:\n\t    if (Tcl_GetBooleanFromObj(interp, objv[i + 1],\n\t\t    &mustexist) != TCL_OK) {\n\t\tgoto end;\n\t    }\n\t    break;\n\tcase CHOOSE_PARENT:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    tkwin = Tk_NameToWindow(interp, str, tkwin);\n\t    if (!tkwin) {\n\t\tgoto end;\n\t    }\n\t    haveParentOption = 1;\n\t    break;\n\tcase CHOOSE_TITLE:\n\t    str = Tcl_GetStringFromObj(objv[i + 1], &len);\n\t    title = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:len];\n\t    [panel setTitle:title];\n\t    [title release];\n\t    break;\n\tcase CHOOSE_COMMAND:\n\t    cmdObj = objv[i+1];\n\t    break;\n\t}\n    }\n    [panel setPrompt:@\"Choose\"];\n    [panel setCanChooseFiles:NO];\n    [panel setCanChooseDirectories:YES];\n    [panel setCanCreateDirectories:!mustexist];\n    if (cmdObj) {\n\tif (Tcl_IsShared(cmdObj)) {\n\t    cmdObj = Tcl_DuplicateObj(cmdObj);\n\t}\n\tTcl_IncrRefCount(cmdObj);\n    }\n\n    /*\n     * Check for directory value, set to root if not specified; otherwise\n     * crashes with exception because of nil string parameter.\n     */\n\n    if (!directory) {\n\tdirectory = @\"/\";\n    }\n    parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);\n    [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];\n    if (haveParentOption) {\n\tparent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);\n\tparentIsKey = parent && [parent isKeyWindow];\n    } else {\n\tparent = nil;\n\tparentIsKey = False;\n    }\n    modalReturnCode = showOpenSavePanel(panel, parent, interp, cmdObj, 0);\n    if (cmdObj) {\n\tTcl_DecrRefCount(cmdObj);\n    }\n    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;\n    if (parentIsKey) {\n\t[parent makeKeyWindow];\n    }\n  end:\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkAboutDlg --\n *\n *\tDisplays the default Tk About box.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkAboutDlg(void)\n{\n    [NSApp orderFrontStandardAboutPanel:NSApp];\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXStandardAboutPanelObjCmd --\n *\n *\tImplements the ::tk::mac::standardAboutPanel command.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tnone\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMacOSXStandardAboutPanelObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    if (objc > 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    [NSApp orderFrontStandardAboutPanel:NSApp];\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MessageBoxObjCmd --\n *\n *\tImplements the tk_messageBox in native Mac OS X style.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tnone\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_MessageBoxObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    char *str;\n    Tcl_Size i;\n    int result = TCL_ERROR, haveParentOption = 0;\n    int index, typeIndex, iconIndex, indexDefaultOption = 0;\n    int defaultNativeButtonIndex = 1; /* 1, 2, 3: right to left */\n    Tcl_Obj *cmdObj = NULL;\n    AlertCallbackInfo callbackInfo;\n    NSString *message, *title;\n    NSWindow *parent;\n    NSArray *buttons;\n    NSAlert *alert = [NSAlert new];\n    NSInteger modalReturnCode = 1;\n    BOOL parentIsKey = NO;\n\n    iconIndex = ICON_INFO;\n    typeIndex = TYPE_OK;\n    for (i = 1; i < objc; i += 2) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], alertOptionStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MSGBOX\", \"VALUE\", (char *)NULL);\n\t    goto end;\n\t}\n\tswitch (index) {\n\tcase ALERT_DEFAULT:\n\t    /*\n\t     * Need to postpone processing of this option until we are sure to\n\t     * know the '-type' as well.\n\t     */\n\n\t    indexDefaultOption = i;\n\t    break;\n\n\tcase ALERT_DETAIL:\n\t    str = Tcl_GetString(objv[i + 1]);\n\t    message = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:TCL_INDEX_NONE];\n\t    [alert setInformativeText:message];\n\t    [message release];\n\t    break;\n\n\tcase ALERT_ICON:\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings,\n\t\t    sizeof(char *), \"-icon value\", TCL_EXACT, &iconIndex) != TCL_OK) {\n\t\tgoto end;\n\t    }\n\t    break;\n\n\tcase ALERT_MESSAGE:\n\t    str = Tcl_GetString(objv[i + 1]);\n\t    message = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:TCL_INDEX_NONE];\n\t    [alert setMessageText:message];\n\t    [message release];\n\t    break;\n\n\tcase ALERT_PARENT:\n\t    str = Tcl_GetString(objv[i + 1]);\n\t    tkwin = Tk_NameToWindow(interp, str, tkwin);\n\t    if (!tkwin) {\n\t\tgoto end;\n\t    }\n\t    haveParentOption = 1;\n\t    break;\n\n\tcase ALERT_TITLE:\n\t    str = Tcl_GetString(objv[i + 1]);\n\t    title = [[TKNSString alloc] initWithTclUtfBytes:\n\t\t    str length:TCL_INDEX_NONE];\n\t    [[alert window] setTitle:title];\n\t    [title release];\n\t    break;\n\n\tcase ALERT_TYPE:\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings,\n\t\t    sizeof(char *), \"-type value\", TCL_EXACT, &typeIndex) != TCL_OK) {\n\t\tgoto end;\n\t    }\n\t    break;\n\tcase ALERT_COMMAND:\n\t    cmdObj = objv[i+1];\n\t    break;\n\t}\n    }\n    if (indexDefaultOption) {\n\t/*\n\t * Any '-default' option needs to know the '-type' option, which is\n\t * why we do this here.\n\t */\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],\n\t\talertButtonStrings, sizeof(char *), \"-default value\",\n\t\tTCL_EXACT, &index) != TCL_OK) {\n\t    goto end;\n\t}\n\n\t/*\n\t * Need to map from \"ok\" etc. to 1, 2, 3, right to left.\n\t */\n\n\tdefaultNativeButtonIndex =\n\t\talertButtonIndexAndTypeToNativeButtonIndex[typeIndex][index];\n\tif (!defaultNativeButtonIndex) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(\"Illegal default option\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MSGBOX\", \"DEFAULT\", (char *)NULL);\n\t    goto end;\n\t}\n    }\n    [alert setIcon:[NSApp applicationIconImage]];\n    [alert setAlertStyle:alertStyles[iconIndex]];\n    i = 0;\n    while (i < 3 && alertButtonNames[typeIndex][i]) {\n\t[alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]];\n    }\n    buttons = [alert buttons];\n    for (NSButton *b in buttons) {\n\tNSString *ke = [b keyEquivalent];\n\n\tif (([ke isEqualToString:@\"\\r\"] || [ke isEqualToString:@\"\\033\"]) &&\n\t\t![b keyEquivalentModifierMask]) {\n\t    [b setKeyEquivalent:@\"\"];\n\t}\n    }\n    [[buttons objectAtIndex: [buttons count]-1] setKeyEquivalent: @\"\\033\"];\n    [[buttons objectAtIndex: (NSUInteger)(defaultNativeButtonIndex-1)]\n\t    setKeyEquivalent: @\"\\r\"];\n    if (cmdObj) {\n\tif (Tcl_IsShared(cmdObj)) {\n\t    cmdObj = Tcl_DuplicateObj(cmdObj);\n\t}\n\tTcl_IncrRefCount(cmdObj);\n    }\n    callbackInfo.cmdObj = cmdObj;\n    callbackInfo.interp = interp;\n    callbackInfo.typeIndex = typeIndex;\n    parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);\n    if (haveParentOption && parent && ![parent attachedSheet]) {\n\tparentIsKey = [parent isKeyWindow];\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090\n\t[alert beginSheetModalForWindow:parent\n\t       completionHandler:^(NSModalResponse returnCode) {\n\t    [NSApp tkAlertDidEnd:alert\n\t\t    returnCode:returnCode\n\t\t    contextInfo:&callbackInfo];\n\t}];\n#else\n\t[alert beginSheetModalForWindow:parent\n\t       modalDelegate:NSApp\n\t       didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)\n\t       contextInfo:&callbackInfo];\n#endif\n\tmodalReturnCode = cmdObj ? 0 :\n\t    [alert runModal];\n    } else {\n\tmodalReturnCode = [alert runModal];\n\t[NSApp tkAlertDidEnd:alert returnCode:modalReturnCode\n\t\tcontextInfo:&callbackInfo];\n    }\n    if (cmdObj) {\n\tTcl_DecrRefCount(cmdObj);\n    }\n    result = (modalReturnCode >= NSAlertFirstButtonReturn) ? TCL_OK : TCL_ERROR;\n  end:\n    [alert release];\n    if (parentIsKey) {\n\t[parent makeKeyWindow];\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n */\n#pragma mark [tk fontchooser] implementation (TIP 324)\n/*\n *----------------------------------------------------------------------\n */\n\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXFont.h\"\n\ntypedef struct FontchooserData {\n    Tcl_Obj *titleObj;\n    Tcl_Obj *cmdObj;\n    Tk_Window parent;\n} FontchooserData;\n\nenum FontchooserEvent {\n    FontchooserClosed,\n    FontchooserSelection\n};\n\nstatic void\t\tFontchooserEvent(int kind);\nstatic Tcl_Obj *\tFontchooserCget(FontchooserData *fcdPtr,\n\t\t\t    int optionIndex);\nstatic Tcl_ObjCmdProc2 FontchooserConfigureCmd;\nstatic Tcl_ObjCmdProc2 FontchooserShowCmd;\nstatic Tcl_ObjCmdProc2 FontchooserHideCmd;\nstatic void\t\tFontchooserParentEventHandler(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tDeleteFontchooserData(void *clientData,\n\t\t\t    Tcl_Interp *interp);\n\nMODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[];\nconst TkEnsemble tkFontchooserEnsemble[] = {\n    { \"configure\", FontchooserConfigureCmd, NULL },\n    { \"show\", FontchooserShowCmd, NULL },\n    { \"hide\", FontchooserHideCmd, NULL },\n    { NULL, NULL, NULL }\n};\n\nstatic Tcl_Interp *fontchooserInterp = NULL;\nstatic NSFont *fontPanelFont = nil;\nstatic NSMutableDictionary *fontPanelFontAttributes = nil;\n\nstatic const char *const fontchooserOptionStrings[] = {\n    \"-command\", \"-font\", \"-parent\", \"-title\",\n    \"-visible\", NULL\n};\nenum FontchooserOption {\n    FontchooserCmd, FontchooserFont, FontchooserParent, FontchooserTitle,\n    FontchooserVisible\n};\n\n@implementation TKApplication(TKFontPanel)\n\n- (void) changeFont: (id) sender\n{\n    NSFontManager *fm = [NSFontManager sharedFontManager];\n    (void)sender;\n\n    if ([fm currentFontAction] == NSViaPanelFontAction) {\n\tNSFont *font = [fm convertFont:fontPanelFont];\n\n\tif (![fontPanelFont isEqual:font]) {\n\t    [fontPanelFont release];\n\t    fontPanelFont = [font retain];\n\t    FontchooserEvent(FontchooserSelection);\n\t}\n    }\n}\n\n- (void) changeAttributes: (id) sender\n{\n    NSDictionary *attributes = [sender convertAttributes:\n\t    fontPanelFontAttributes];\n\n    if (![fontPanelFontAttributes isEqual:attributes]) {\n\t[fontPanelFontAttributes setDictionary:attributes];\n\tFontchooserEvent(FontchooserSelection);\n    }\n}\n\n- (NSUInteger) validModesForFontPanel: (NSFontPanel *)fontPanel\n{\n    (void)fontPanel;\n\n    return (NSFontPanelStandardModesMask & ~NSFontPanelAllEffectsModeMask) |\n\t    NSFontPanelUnderlineEffectModeMask |\n\t    NSFontPanelStrikethroughEffectModeMask;\n}\n\n- (void) windowDidOrderOffScreen: (NSNotification *)notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if ([[notification object] isEqual:[[NSFontManager sharedFontManager]\n\t    fontPanel:NO]]) {\n\tFontchooserEvent(FontchooserClosed);\n    }\n}\n@end\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FontchooserEvent --\n *\n *\tThis processes events generated by user interaction with the font\n *\tpanel.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAdditional events may be placed on the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFontchooserEvent(\n    int kind)\n{\n    FontchooserData *fcdPtr;\n    Tcl_Obj *fontObj;\n\n    if (!fontchooserInterp) {\n\treturn;\n    }\n    fcdPtr = (FontchooserData *)Tcl_GetAssocData(fontchooserInterp, \"::tk::fontchooser\", NULL);\n    switch (kind) {\n    case FontchooserClosed:\n\tif (fcdPtr->parent != NULL) {\n\t    Tk_SendVirtualEvent(fcdPtr->parent, \"TkFontchooserVisibility\", NULL);\n\t    fontchooserInterp = NULL;\n\t}\n\tbreak;\n    case FontchooserSelection:\n\tfontObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(\n\t\tfontPanelFont, fontPanelFontAttributes);\n\tif (fontObj) {\n\t    if (fcdPtr->cmdObj) {\n\t\tTcl_Size objc;\n\t\tint result;\n\t\tTcl_Obj **objv, **tmpv;\n\n\t\tresult = Tcl_ListObjGetElements(fontchooserInterp,\n\t\t\tfcdPtr->cmdObj, &objc, &objv);\n\t\tif (result == TCL_OK) {\n\t\t    tmpv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * (objc + 2));\n\t\t    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);\n\t\t    tmpv[objc] = fontObj;\n\t\t    TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,\n\t\t\t    TCL_EVAL_GLOBAL);\n\t\t    Tcl_Free(tmpv);\n\t\t}\n\t    }\n\t    Tk_SendVirtualEvent(fcdPtr->parent, \"TkFontchooserFontChanged\", NULL);\n\t}\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FontchooserCget --\n *\n *\tHelper for the FontchooserConfigure command to return the current value\n *\tof any of the options (which may be NULL in the structure).\n *\n * Results:\n *\tTcl object of option value.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nFontchooserCget(\n    FontchooserData *fcdPtr,\n    int optionIndex)\n{\n    Tcl_Obj *resObj = NULL;\n\n    switch(optionIndex) {\n    case FontchooserParent:\n\tif (fcdPtr->parent != NULL) {\n\t    resObj = Tcl_NewStringObj(\n\t\t    ((TkWindow *)fcdPtr->parent)->pathName, TCL_INDEX_NONE);\n\t} else {\n\t    resObj = Tcl_NewStringObj(\".\", 1);\n\t}\n\tbreak;\n    case FontchooserTitle:\n\tif (fcdPtr->titleObj) {\n\t    resObj = fcdPtr->titleObj;\n\t} else {\n\t    resObj = Tcl_NewObj();\n\t}\n\tbreak;\n    case FontchooserFont:\n\tresObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(\n\t\tfontPanelFont, fontPanelFontAttributes);\n\tif (!resObj) {\n\t    resObj = Tcl_NewObj();\n\t}\n\tbreak;\n    case FontchooserCmd:\n\tif (fcdPtr->cmdObj) {\n\t    resObj = fcdPtr->cmdObj;\n\t} else {\n\t    resObj = Tcl_NewObj();\n\t}\n\tbreak;\n    case FontchooserVisible:\n\tresObj = Tcl_NewBooleanObj([[[NSFontManager sharedFontManager]\n\t\tfontPanel:NO] isVisible]);\n\tbreak;\n    default:\n\tresObj = Tcl_NewObj();\n    }\n    return resObj;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserConfigureCmd --\n *\n *\tImplementation of the 'tk fontchooser configure' ensemble command.  See\n *\tthe user documentation for what it does.\n *\n * Results:\n *\tSee the user documentation.\n *\n * Side effects:\n *\tPer-interp data structure may be modified\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserConfigureCmd(\n    void *clientData,\t/* Main window */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, \"::tk::fontchooser\",\n\t    NULL);\n    Tcl_Size i;\n    int r = TCL_OK;\n\n    /*\n     * With no arguments we return all the options in a dict\n     */\n\n    if (objc == 1) {\n\tTcl_Obj *keyObj, *valueObj;\n\tTcl_Obj *dictObj = Tcl_NewDictObj();\n\n\tfor (i = 0; r == TCL_OK && fontchooserOptionStrings[i] != NULL; ++i) {\n\t    keyObj = Tcl_NewStringObj(fontchooserOptionStrings[i], TCL_INDEX_NONE);\n\t    valueObj = FontchooserCget(fcdPtr, (int)i);\n\t    r = Tcl_DictObjPut(interp, dictObj, keyObj, valueObj);\n\t}\n\tif (r == TCL_OK) {\n\t    Tcl_SetObjResult(interp, dictObj);\n\t}\n\treturn r;\n    }\n\n    for (i = 1; i < objc; i += 2) {\n\tint optionIndex;\n\tTcl_Size len;\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], fontchooserOptionStrings,\n\t\tsizeof(char *), \"option\", 0, &optionIndex) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 2) {\n\t    /*\n\t     * With one option and no arg, return the current value.\n\t     */\n\n\t    Tcl_SetObjResult(interp, FontchooserCget(fcdPtr, optionIndex));\n\t    return TCL_OK;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FONTDIALOG\", \"VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tswitch (optionIndex) {\n\tcase FontchooserVisible: {\n\t    const char *msg = \"cannot change read-only option \"\n\t\t    \"\\\"-visible\\\": use the show or hide command\";\n\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FONTDIALOG\", \"READONLY\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tcase FontchooserParent: {\n\t    Tk_Window parent = Tk_NameToWindow(interp,\n\t\t    Tcl_GetString(objv[i+1]), tkwin);\n\n\t    if (parent == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (fcdPtr->parent) {\n\t\tTk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,\n\t\t\tFontchooserParentEventHandler, fcdPtr);\n\t    }\n\t    fcdPtr->parent = parent;\n\t    Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,\n\t\t    FontchooserParentEventHandler, fcdPtr);\n\t    break;\n\t}\n\tcase FontchooserTitle:\n\t    if (fcdPtr->titleObj) {\n\t\tTcl_DecrRefCount(fcdPtr->titleObj);\n\t    }\n\t    Tcl_GetStringFromObj(objv[i+1], &len);\n\t    if (len) {\n\t\tfcdPtr->titleObj = objv[i+1];\n\t\tif (Tcl_IsShared(fcdPtr->titleObj)) {\n\t\t    fcdPtr->titleObj = Tcl_DuplicateObj(fcdPtr->titleObj);\n\t\t}\n\t\tTcl_IncrRefCount(fcdPtr->titleObj);\n\t    } else {\n\t\tfcdPtr->titleObj = NULL;\n\t    }\n\t    break;\n\tcase FontchooserFont: {\n\t    Tcl_GetStringFromObj(objv[i+1], &len);\n\t    if (len) {\n\t\tTk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]);\n\n\t\tif (!f) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\t[fontPanelFont autorelease];\n\t\tfontPanelFont = [TkMacOSXNSFontForFont(f) retain];\n\t\t[fontPanelFontAttributes setDictionary:\n\t\t\tTkMacOSXNSFontAttributesForFont(f)];\n\t\t[fontPanelFontAttributes removeObjectsForKeys:[NSArray\n\t\t\tarrayWithObjects:NSFontAttributeName,\n\t\t\tNSLigatureAttributeName, NSKernAttributeName, nil]];\n\t\tTk_FreeFont(f);\n\t    } else {\n\t\t[fontPanelFont release];\n\t\tfontPanelFont = nil;\n\t\t[fontPanelFontAttributes removeAllObjects];\n\t    }\n\n\t    NSFontManager *fm = [NSFontManager sharedFontManager];\n\t    NSFontPanel *fp = [fm fontPanel:NO];\n\n\t    [fp setPanelFont:fontPanelFont isMultiple:NO];\n\t    [fm setSelectedFont:fontPanelFont isMultiple:NO];\n\t    [fm setSelectedAttributes:fontPanelFontAttributes\n\t\t    isMultiple:NO];\n\t    if ([fp isVisible]) {\n\t\tTk_SendVirtualEvent(fcdPtr->parent,\n\t\t\t\"TkFontchooserFontChanged\", NULL);\n\t    }\n\t    break;\n\t}\n\tcase FontchooserCmd:\n\t    if (fcdPtr->cmdObj) {\n\t\tTcl_DecrRefCount(fcdPtr->cmdObj);\n\t    }\n\t    Tcl_GetStringFromObj(objv[i+1], &len);\n\t    if (len) {\n\t\tfcdPtr->cmdObj = objv[i+1];\n\t\tif (Tcl_IsShared(fcdPtr->cmdObj)) {\n\t\t    fcdPtr->cmdObj = Tcl_DuplicateObj(fcdPtr->cmdObj);\n\t\t}\n\t\tTcl_IncrRefCount(fcdPtr->cmdObj);\n\t    } else {\n\t\tfcdPtr->cmdObj = NULL;\n\t    }\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserShowCmd --\n *\n *\tImplements the 'tk fontchooser show' ensemble command. The per-interp\n *\tconfiguration data for the dialog is held in an interp associated\n *\tstructure.\n *\n * Results:\n *\tSee the user documentation.\n *\n * Side effects:\n *\tFont Panel may be shown.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserShowCmd(\n    void *clientData,\t/* Main window */\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, \"::tk::fontchooser\",\n\t    NULL);\n\n    if (fcdPtr->parent == NULL) {\n\tfcdPtr->parent = (Tk_Window)clientData;\n\tTk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,\n\t\tFontchooserParentEventHandler, fcdPtr);\n    }\n\n    NSFontManager *fm = [NSFontManager sharedFontManager];\n    NSFontPanel *fp = [fm fontPanel:YES];\n\n    if ([fp delegate] != NSApp) {\n\t[fp setDelegate:NSApp];\n    }\n    if (![fp isVisible]) {\n\t[fm orderFrontFontPanel:NSApp];\n\tTk_SendVirtualEvent(fcdPtr->parent, \"TkFontchooserVisibility\", NULL);\n    }\n    fontchooserInterp = interp;\n\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserHideCmd --\n *\n *\tImplementation of the 'tk fontchooser hide' ensemble. See the user\n *\tdocumentation for details.\n *\n * Results:\n *\tSee the user documentation.\n *\n * Side effects:\n *\tFont Panel may be hidden.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserHideCmd(\n    TCL_UNUSED(void *),\t/* Main window */\n    TCL_UNUSED(Tcl_Interp *),\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];\n\n    if ([fp isVisible]) {\n\t[fp orderOut:NSApp];\n    }\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserParentEventHandler --\n *\n *\tEvent handler for StructureNotify events on the font chooser's parent\n *\twindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFont chooser parent info is cleared and font panel is hidden.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\nFontchooserParentEventHandler(\n    void *clientData,\n    XEvent *eventPtr)\n{\n    FontchooserData *fcdPtr = (FontchooserData *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tTk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,\n\t\tFontchooserParentEventHandler, fcdPtr);\n\tfcdPtr->parent = NULL;\n\tFontchooserHideCmd(NULL, NULL, 0, NULL);\n    }\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * DeleteFontchooserData --\n *\n *\tClean up the font chooser configuration data when the interp is\n *\tdestroyed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tper-interp configuration data is destroyed.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\nDeleteFontchooserData(\n    void *clientData,\n    Tcl_Interp *interp)\n{\n    FontchooserData *fcdPtr = (FontchooserData *)clientData;\n\n    if (fcdPtr->titleObj) {\n\tTcl_DecrRefCount(fcdPtr->titleObj);\n    }\n    if (fcdPtr->cmdObj) {\n\tTcl_DecrRefCount(fcdPtr->cmdObj);\n    }\n    Tcl_Free(fcdPtr);\n\n    if (fontchooserInterp == interp) {\n\tfontchooserInterp = NULL;\n    }\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkInitFontchooser --\n *\n *\tAssociate the font chooser configuration data with the Tcl interpreter.\n *\tThere is one font chooser per interp.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tper-interp configuration data is destroyed.\n *\n * ----------------------------------------------------------------------\n */\n\nMODULE_SCOPE int\nTkInitFontchooser(\n    Tcl_Interp *interp,\n    TCL_UNUSED(void *))\n{\n    FontchooserData *fcdPtr = (FontchooserData *)Tcl_Alloc(sizeof(FontchooserData));\n\n    bzero(fcdPtr, sizeof(FontchooserData));\n    Tcl_SetAssocData(interp, \"::tk::fontchooser\", DeleteFontchooserData,\n\t    fcdPtr);\n    if (!fontPanelFontAttributes) {\n\tfontPanelFontAttributes = [NSMutableDictionary new];\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXDraw.c",
    "content": "/*\n * tkMacOSXDraw.c --\n *\n *\tThis file contains functions that draw to windows. Many of these\n *\tfunctions emulate Xlib functions.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2014-2020 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkButton.h\"\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000\n#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext]\n#else\n#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort]\n#endif\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_DRAWING\n#define TK_MAC_DEBUG_IMAGE_DRAWING\n#define TK_MAC_DEBUG_CG\n#endif\n*/\n\n#define radians(d)\t((d) * (M_PI/180.0))\n\n/*\n * Non-antialiased CG drawing looks better and more like X11 drawing when using\n * very fine lines, so decrease all linewidths by the following constant.\n */\n#define NON_AA_CG_OFFSET .999\n\nstatic int cgAntiAliasLimit = 0;\n#define notAA(w)\t((w) < cgAntiAliasLimit)\n\nstatic int useThemedToplevel = 0;\nstatic int useThemedFrame = 0;\nstatic unsigned long transparentColor;\n\n/*\n * Prototypes for functions used only in this file.\n */\n\nstatic void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);\nstatic NSImage *CreateNSImageFromPixmap(Pixmap pixmap, int width, int height);\nstatic HIShapeRef GetClipRgn(Drawable drawable);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInitCGDrawing --\n *\n *\tInitializes link vars that control CG drawing.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE int\nTkMacOSXInitCGDrawing(\n    Tcl_Interp *interp,\n    TCL_UNUSED(int),\n    int limit)\n{\n    static bool initialized = false;\n\n    if (!initialized) {\n\tinitialized = true;\n\n\tif (Tcl_CreateNamespace(interp, \"::tk::mac\", NULL, NULL) == NULL) {\n\t    Tcl_ResetResult(interp);\n\t}\n\n\tif (Tcl_LinkVar(interp, \"::tk::mac::CGAntialiasLimit\",\n\t\t&cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {\n\t    Tcl_ResetResult(interp);\n\t}\n\tcgAntiAliasLimit = limit;\n\n\t/*\n\t * Piggy-back the themed drawing var init here.\n\t */\n\n\tif (Tcl_LinkVar(interp, \"::tk::mac::useThemedToplevel\",\n\t\t&useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {\n\t    Tcl_ResetResult(interp);\n\t}\n\tif (Tcl_LinkVar(interp, \"::tk::mac::useThemedFrame\",\n\t\t&useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {\n\t    Tcl_ResetResult(interp);\n\t}\n\ttransparentColor = TkMacOSXClearPixel();\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNSImageFromTkImage --\n *\n *\tGet autoreleased NSImage for Tk_Image.\n *\n * Results:\n *\tNSImage.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nNSImage *\nTkMacOSXGetNSImageFromTkImage(\n    Display *display,\n    Tk_Image image,\n    int width,\n    int height)\n{\n    Pixmap pixmap;\n    NSImage *nsImage;\n    if (width <= 0 || height <= 0) {\n\treturn nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];\n    }\n    pixmap = Tk_GetPixmap(display, None, width, height, 0);\n    Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);\n    nsImage = CreateNSImageFromPixmap(pixmap, width, height);\n    Tk_FreePixmap(display, pixmap);\n\n    return [nsImage autorelease];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNSImageFromBitmap --\n *\n *\tGet autoreleased NSImage for Bitmap.\n *\n * Results:\n *\tNSImage.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nNSImage *\nTkMacOSXGetNSImageFromBitmap(\n    Display *display,\n    Pixmap bitmap,\n    GC gc,\n    int width,\n    int height)\n{\n    Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);\n    NSImage *nsImage;\n\n    unsigned long origBackground = gc->background;\n\n    gc->background = transparentColor;\n    XSetClipOrigin(display, gc, 0, 0);\n    XCopyPlane(display, bitmap, pixmap, gc, 0, 0, (unsigned)width, (unsigned)height, 0, 0, 1);\n    gc->background = origBackground;\n    nsImage = CreateNSImageFromPixmap(pixmap, width, height);\n    Tk_FreePixmap(display, pixmap);\n\n    return [nsImage autorelease];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateNSImageFromPixmap --\n *\n *\tCreate NSImage for Pixmap.\n *\n * Results:\n *\tNSImage.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSImage *\nCreateNSImageFromPixmap(\n    Pixmap pixmap,\n    int width,\n    int height)\n{\n    CGImageRef cgImage;\n    NSImage *nsImage;\n    NSBitmapImageRep *bitmapImageRep;\n    CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);\n\n    if (context) {\n\tcgImage = CGBitmapContextCreateImage(context);\n    } else {\n\treturn NULL;\n    }\n    nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];\n    bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];\n    [nsImage addRepresentation:bitmapImageRep];\n    [bitmapImageRep release];\n    CFRelease(cgImage);\n\n    return nsImage;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MacOSXGetCGContextForDrawable --\n *\n *\tGet CGContext for given Drawable, creating one if necessary.\n *\n * Results:\n *\tCGContext.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid *\nTk_MacOSXGetCGContextForDrawable(\n    Drawable drawable)\n{\n    MacDrawable *macDraw = (MacDrawable *)drawable;\n\n    if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {\n\tconst size_t bitsPerComponent = 8;\n\tCGColorSpaceRef colorspace = NULL;\n\tCGBitmapInfo bitmapInfo =\n#ifdef __LITTLE_ENDIAN__\n\t\tkCGBitmapByteOrder32Host;\n#else\n\t\tkCGBitmapByteOrderDefault;\n#endif\n\tCGRect bounds = CGRectMake(0, 0,\n\t\tmacDraw->size.width, macDraw->size.height);\n\n\tif (macDraw->flags & TK_IS_BW_PIXMAP) {\n\t    bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;\n\t} else {\n\t    colorspace = CGColorSpaceCreateDeviceRGB();\n\t    bitmapInfo |= kCGImageAlphaPremultipliedFirst;\n\t}\n\tmacDraw->context = CGBitmapContextCreate(NULL, (unsigned)macDraw->size.width,\n\t\t(unsigned)macDraw->size.height, bitsPerComponent, 0,\n\t\tcolorspace, bitmapInfo);\n\tif (macDraw->context) {\n\t    CGContextClearRect(macDraw->context, bounds);\n\t}\n\tif (colorspace) {\n\t    CFRelease(colorspace);\n\t}\n    }\n\n    return (macDraw ? macDraw->context : NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXDrawCGImage --\n *\n *\tDraw CG image into drawable. The entire image is used, and will\n *\tbe rescaled if its dimensions do not equal dstBounds.size.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXDrawCGImage(\n    Drawable d,\n    GC gc,\n    CGContextRef context,\n    CGImageRef image,\n    unsigned long imageForeground,\n    unsigned long imageBackground,\n    CGRect dstBounds)\n{\n    MacDrawable *macDraw = (MacDrawable *)d;\n\n    if (macDraw && context && image) {\n\tdstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);\n\tif (CGImageIsMask(image)) {\n\t    if (macDraw->flags & TK_IS_BW_PIXMAP) {\n\n\t\t/*\n\t\t * Set fill color to black; background comes from the context,\n\t\t * or is transparent.\n\t\t */\n\n\t\tif (imageBackground != transparentColor) {\n\t\t    CGContextClearRect(context, dstBounds);\n\t\t}\n\t\tCGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);\n\t    } else {\n\t\tif (imageBackground != transparentColor) {\n\t\t    TkMacOSXSetColorInContext(gc, imageBackground, context,\n\t\t\t    TkMacOSXInDarkMode((Tk_Window)macDraw->winPtr));\n\t\t    CGContextFillRect(context, dstBounds);\n\t\t}\n\t\tTkMacOSXSetColorInContext(gc, imageForeground, context,\n\t\t\tTkMacOSXInDarkMode((Tk_Window)macDraw->winPtr));\n\t    }\n\t}\n\n#ifdef TK_MAC_DEBUG_IMAGE_DRAWING\n\tCGContextSaveGState(context);\n\tCGContextSetLineWidth(context, 1.0);\n\tCGContextSetRGBStrokeColor(context, 0, 0, 0, 0.1);\n\tCGContextSetRGBFillColor(context, 0, 1, 0, 0.1);\n\tCGContextFillRect(context, dstBounds);\n\tCGContextStrokeRect(context, dstBounds);\n\n\tCGPoint p[4] = {dstBounds.origin,\n\t    CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMaxY(dstBounds)),\n\t    CGPointMake(CGRectGetMinX(dstBounds), CGRectGetMaxY(dstBounds)),\n\t    CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMinY(dstBounds))\n\t};\n\n\tCGContextStrokeLineSegments(context, p, 4);\n\tCGContextRestoreGState(context);\n\tTkMacOSXDbgMsg(\"Drawing CGImage at (x=%f, y=%f), (w=%f, h=%f)\",\n\t\tdstBounds.origin.x, dstBounds.origin.y,\n\t\tdstBounds.size.width, dstBounds.size.height);\n#else /* TK_MAC_DEBUG_IMAGE_DRAWING */\n\tCGContextSaveGState(context);\n\tCGContextTranslateCTM(context, 0, dstBounds.origin.y + CGRectGetMaxY(dstBounds));\n\tCGContextScaleCTM(context, 1, -1);\n\tCGContextDrawImage(context, dstBounds, image);\n\tCGContextRestoreGState(context);\n#endif /* TK_MAC_DEBUG_IMAGE_DRAWING */\n    } else {\n\tTkMacOSXDbgMsg(\"Drawing of empty CGImage requested\");\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawLines --\n *\n *\tDraw connected lines.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRenders a series of connected lines.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawLines(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    XPoint *points,\t\t/* Array of points. */\n    int npoints,\t\t/* Number of points. */\n    int mode)\t\t\t/* Line drawing mode. */\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int i, lw = gc->line_width;\n\n    if (npoints < 2) {\n\treturn BadValue;\n    }\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tdouble prevx, prevy;\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\tCGContextBeginPath(dc.context);\n\tprevx = macWin->xOff + points[0].x + o;\n\tprevy = macWin->yOff + points[0].y + o;\n\tCGContextMoveToPoint(dc.context, prevx, prevy);\n\tfor (i = 1; i < npoints; i++) {\n\t    if (mode == CoordModeOrigin) {\n\t\tCGContextAddLineToPoint(dc.context,\n\t\t\tmacWin->xOff + points[i].x + o,\n\t\t\tmacWin->yOff + points[i].y + o);\n\t    } else {\n\t\tprevx += points[i].x;\n\t\tprevy += points[i].y;\n\t\tCGContextAddLineToPoint(dc.context, prevx, prevy);\n\t    }\n\t}\n\n\t/*\n\t * In the case of closed polylines, the first and last points are the\n\t * same. We want miter or bevel join be rendered also at this point,\n\t * this needs telling CoreGraphics that the path is closed.\n\t */\n\n\tif ((points[0].x == points[npoints-1].x) &&\n\t\t(points[0].y == points[npoints-1].y)) {\n\t    CGContextClosePath(dc.context);\n\t}\n\tCGContextStrokePath(dc.context);\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawSegments --\n *\n *\tDraw unconnected lines.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRenders a series of unconnected lines.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawSegments(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XSegment *segments,\n    int nsegments)\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int i, lw = gc->line_width;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\tfor (i = 0; i < nsegments; i++) {\n\t    CGContextBeginPath(dc.context);\n\t    CGContextMoveToPoint(dc.context,\n\t\t    macWin->xOff + segments[i].x1 + o,\n\t\t    macWin->yOff + segments[i].y1 + o);\n\t    CGContextAddLineToPoint(dc.context,\n\t\t    macWin->xOff + segments[i].x2 + o,\n\t\t    macWin->yOff + segments[i].y2 + o);\n\t    CGContextStrokePath(dc.context);\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillPolygon --\n *\n *\tDraws a filled polygon.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a filled polygon on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillPolygon(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    XPoint *points,\t\t/* Array of points. */\n    int npoints,\t\t/* Number of points. */\n    TCL_UNUSED(int),\t\t/* Shape to draw. */\n    int mode)\t\t\t/* Drawing mode. */\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int i;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tdouble prevx, prevy;\n\tdouble o = (gc->line_width % 2) ? .5 : 0;\n\n\tCGContextBeginPath(dc.context);\n\tprevx = macWin->xOff + points[0].x + o;\n\tprevy = macWin->yOff + points[0].y + o;\n\tCGContextMoveToPoint(dc.context, prevx, prevy);\n\tfor (i = 1; i < npoints; i++) {\n\t    if (mode == CoordModeOrigin) {\n\t\tCGContextAddLineToPoint(dc.context,\n\t\t\tmacWin->xOff + points[i].x + o,\n\t\t\tmacWin->yOff + points[i].y + o);\n\t    } else {\n\t\tprevx += points[i].x;\n\t\tprevy += points[i].y;\n\t\tCGContextAddLineToPoint(dc.context, prevx, prevy);\n\t    }\n\t}\n\t(gc->fill_rule == EvenOddRule)\n\t\t? CGContextEOFillPath(dc.context)\n\t\t: CGContextFillPath(dc.context);\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawRectangle --\n *\n *\tDraws a rectangle.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a rectangle on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawRectangle(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    int x, int y,\t\t/* Upper left corner. */\n    unsigned int width,\t\t/* Width & height of rect. */\n    unsigned int height)\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int lw = gc->line_width;\n\n    if (width == 0 || height == 0) {\n\treturn BadDrawable;\n    }\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\trect = CGRectMake(\n\t\tmacWin->xOff + x + o, macWin->yOff + y + o,\n\t\twidth, height);\n\tCGContextStrokeRect(dc.context, rect);\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawRectangles --\n *\n *\tDraws the outlines of the specified rectangles as if a five-point\n *\tPolyLine protocol request were specified for each rectangle:\n *\n *\t    [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y]\n *\n *\tFor the specified rectangles, these functions do not draw a pixel more\n *\tthan once. XDrawRectangles draws the rectangles in the order listed in\n *\tthe array. If rectangles intersect, the intersecting pixels are drawn\n *\tmultiple times. Draws a rectangle.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws rectangles on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawRectangles(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XRectangle *rectArr,\n    int nRects)\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    XRectangle * rectPtr;\n    int i, lw = gc->line_width;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\tfor (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) {\n\t    if (rectPtr->width == 0 || rectPtr->height == 0) {\n\t\tcontinue;\n\t    }\n\t    rect = CGRectMake(\n\t\t    macWin->xOff + rectPtr->x + o,\n\t\t    macWin->yOff + rectPtr->y + o,\n\t\t    rectPtr->width, rectPtr->height);\n\t    CGContextStrokeRect(dc.context, rect);\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillRectangles --\n *\n *\tFill multiple rectangular areas in the given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws onto the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillRectangles(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    XRectangle *rectangles,\t/* Rectangle array. */\n    int n_rectangles)\t\t/* Number of rectangles. */\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    XRectangle * rectPtr;\n    int i;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\n\tfor (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) {\n\t    if (rectPtr->width == 0 || rectPtr->height == 0) {\n\t\tcontinue;\n\t    }\n\t    rect = CGRectMake(\n\t\t    macWin->xOff + rectPtr->x,\n\t\t    macWin->yOff + rectPtr->y,\n\t\t    rectPtr->width, rectPtr->height);\n\t    CGContextFillRect(dc.context, rect);\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXDrawSolidBorder --\n *\n *\tDraws a border rectangle of specified thickness inside the bounding\n *      rectangle of a Tk Window.  The border rectangle can be inset within the\n *      bounding rectangle.  For a highlight border the inset should be 0, but\n *      for a solid border around the actual window the inset should equal the\n *      thickness of the highlight border.  The color of the border rectangle\n *      is the foreground color of the graphics context passed to the function.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a rectangular border inside the bounding rectangle of a window.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE void\nTkMacOSXDrawSolidBorder(\n    Tk_Window tkwin,\n    GC gc,\n    int inset,\n    int thickness)\n{\n    Drawable d = Tk_WindowId(tkwin);\n    TkMacOSXDrawingContext dc;\n    CGRect outerRect, innerRect;\n\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn;\n    }\n    if (dc.context) {\n\touterRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin),\n\t\t\t       Tk_Width(tkwin), Tk_Height(tkwin));\n\touterRect = CGRectInset(outerRect, inset, inset);\n\tinnerRect = CGRectInset(outerRect, thickness, thickness);\n\tCGContextBeginPath(dc.context);\n\tCGContextAddRect(dc.context, outerRect);\n\tCGContextAddRect(dc.context, innerRect);\n\tCGContextEOFillPath(dc.context);\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawArc --\n *\n *\tDraw an arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws an arc on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawArc(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    int x, int y,\t\t/* Upper left of bounding rect. */\n    unsigned int width,\t\t/* Width & height. */\n    unsigned int height,\n    int angle1,\t\t\t/* Staring angle of arc. */\n    int angle2)\t\t\t/* Extent of arc. */\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int lw = gc->line_width;\n\n    if (width == 0 || height == 0 || angle2 == 0) {\n\treturn BadDrawable;\n    }\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\trect = CGRectMake(\n\t\tmacWin->xOff + x + o,\n\t\tmacWin->yOff + y + o,\n\t\twidth, height);\n\tif (angle1 == 0 && angle2 == 23040) {\n\t    CGContextStrokeEllipseInRect(dc.context, rect);\n\t} else {\n\t    CGMutablePathRef p = CGPathCreateMutable();\n\t    CGAffineTransform t = CGAffineTransformIdentity;\n\t    CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));\n\t    double w = CGRectGetWidth(rect);\n\n\t    if (width != height) {\n\t\tt = CGAffineTransformMakeScale(1.0, CGRectGetHeight(rect)/w);\n\t\tc = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));\n\t    }\n\t    CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),\n\t\t    radians(-(angle1 + angle2)/64.0), angle2 > 0);\n\t    CGContextAddPath(dc.context, p);\n\t    CGPathRelease(p);\n\t    CGContextStrokePath(dc.context);\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawArcs --\n *\n *\tDraws multiple circular or elliptical arcs. Each arc is specified by a\n *\trectangle and two angles. The center of the circle or ellipse is the\n *\tcenter of the rect- angle, and the major and minor axes are specified\n *\tby the width and height.  Positive angles indicate counterclock- wise\n *\tmotion, and negative angles indicate clockwise motion. If the magnitude\n *\tof angle2 is greater than 360 degrees, XDrawArcs truncates it to 360\n *\tdegrees.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws an arc for each array element on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawArcs(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XArc *arcArr,\n    int nArcs)\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    XArc *arcPtr;\n    int i, lw = gc->line_width;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0;\n\n\tfor (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {\n\t    if (arcPtr->width == 0 || arcPtr->height == 0\n\t\t    || arcPtr->angle2 == 0) {\n\t\tcontinue;\n\t    }\n\t    rect = CGRectMake(\n\t\t    macWin->xOff + arcPtr->x + o,\n\t\t    macWin->yOff + arcPtr->y + o,\n\t\t    arcPtr->width, arcPtr->height);\n\n\t    if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040) {\n\t\tCGContextStrokeEllipseInRect(dc.context, rect);\n\t    } else {\n\t\tCGMutablePathRef p = CGPathCreateMutable();\n\t\tCGAffineTransform t = CGAffineTransformIdentity;\n\t\tCGPoint c = CGPointMake(CGRectGetMidX(rect),\n\t\t\tCGRectGetMidY(rect));\n\t\tdouble w = CGRectGetWidth(rect);\n\n\t\tif (arcPtr->width != arcPtr->height) {\n\t\t    t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);\n\t\t    c = CGPointApplyAffineTransform(c,\n\t\t\t    CGAffineTransformInvert(t));\n\t\t}\n\t\tCGPathAddArc(p, &t, c.x, c.y, w/2,\n\t\t\tradians(-arcPtr->angle1/64.0),\n\t\t\tradians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),\n\t\t\tarcPtr->angle2 > 0);\n\t\tCGContextAddPath(dc.context, p);\n\t\tCGPathRelease(p);\n\t\tCGContextStrokePath(dc.context);\n\t    }\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillArc --\n *\n *\tDraw a filled arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a filled arc on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillArc(\n    Display *display,\t\t/* Display. */\n    Drawable d,\t\t\t/* Draw on this. */\n    GC gc,\t\t\t/* Use this GC. */\n    int x, int y,\t\t/* Upper left of bounding rect. */\n    unsigned int width,\t\t/* Width & height. */\n    unsigned int height,\n    int angle1,\t\t\t/* Staring angle of arc. */\n    int angle2)\t\t\t/* Extent of arc. */\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    int lw = gc->line_width;\n\n    if (width == 0 || height == 0 || angle2 == 0) {\n\treturn BadDrawable;\n    }\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0, u = 0;\n\n\tif (notAA(lw)) {\n\t    o += NON_AA_CG_OFFSET/2;\n\t    u += NON_AA_CG_OFFSET;\n\t}\n\trect = CGRectMake(\n\t\tmacWin->xOff + x + o,\n\t\tmacWin->yOff + y + o,\n\t\twidth - u, height - u);\n\n\tif (angle1 == 0 && angle2 == 23040) {\n\t    CGContextFillEllipseInRect(dc.context, rect);\n\t} else {\n\t    CGMutablePathRef p = CGPathCreateMutable();\n\t    CGAffineTransform t = CGAffineTransformIdentity;\n\t    CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));\n\t    double w = CGRectGetWidth(rect);\n\n\t    if (width != height) {\n\t\tt = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);\n\t\tc = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));\n\t    }\n\t    if (gc->arc_mode == ArcPieSlice) {\n\t\tCGPathMoveToPoint(p, &t, c.x, c.y);\n\t    }\n\t    CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),\n\t\t    radians(-(angle1 + angle2)/64.0), angle2 > 0);\n\t    CGPathCloseSubpath(p);\n\t    CGContextAddPath(dc.context, p);\n\t    CGPathRelease(p);\n\t    CGContextFillPath(dc.context);\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillArcs --\n *\n *\tDraw a filled arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a filled arc for each array element on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillArcs(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XArc *arcArr,\n    int nArcs)\n{\n    MacDrawable *macWin = (MacDrawable *)d;\n    TkMacOSXDrawingContext dc;\n    XArc * arcPtr;\n    int i, lw = gc->line_width;\n\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect rect;\n\tdouble o = (lw % 2) ? .5 : 0, u = 0;\n\n\tif (notAA(lw)) {\n\t    o += NON_AA_CG_OFFSET/2;\n\t    u += NON_AA_CG_OFFSET;\n\t}\n\tfor (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {\n\t    if (arcPtr->width == 0 || arcPtr->height == 0\n\t\t    || arcPtr->angle2 == 0) {\n\t\tcontinue;\n\t    }\n\t    rect = CGRectMake(\n\t\t    macWin->xOff + arcPtr->x + o,\n\t\t    macWin->yOff + arcPtr->y + o,\n\t\t    arcPtr->width - u, arcPtr->height - u);\n\t    if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040) {\n\t\tCGContextFillEllipseInRect(dc.context, rect);\n\t    } else {\n\t\tCGMutablePathRef p = CGPathCreateMutable();\n\t\tCGAffineTransform t = CGAffineTransformIdentity;\n\t\tCGPoint c = CGPointMake(CGRectGetMidX(rect),\n\t\t\tCGRectGetMidY(rect));\n\t\tdouble w = CGRectGetWidth(rect);\n\n\t\tif (arcPtr->width != arcPtr->height) {\n\t\t    t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);\n\t\t    c = CGPointApplyAffineTransform(c,\n\t\t\t    CGAffineTransformInvert(t));\n\t\t}\n\t\tif (gc->arc_mode == ArcPieSlice) {\n\t\t    CGPathMoveToPoint(p, &t, c.x, c.y);\n\t\t}\n\t\tCGPathAddArc(p, &t, c.x, c.y, w/2,\n\t\t\tradians(-arcPtr->angle1/64.0),\n\t\t\tradians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),\n\t\t\tarcPtr->angle2 > 0);\n\t\tCGPathCloseSubpath(p);\n\t\tCGContextAddPath(dc.context, p);\n\t\tCGPathRelease(p);\n\t\tCGContextFillPath(dc.context);\n\t    }\n\t}\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSetUpDrawingContext --\n *\n *\tSet up a drawing context for the given drawable from an X GC.\n *\n * Results:\n *\tBoolean indicating whether it is ok to draw; if false, the drawing\n *\tcontext was not setup, so do not attempt to draw and do not call\n *\tTkMacOSXRestoreDrawingContext().\n *\n * Side effects:\n *\tMay modify or create the drawable's graphics context.  May expand the\n *      drawable's dirty rectangle.  When the result is true The dcPtr\n *      parameter is set to reference the new or updated drawing context.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkMacOSXSetupDrawingContext(\n    Drawable d,\n    GC gc,\n    TkMacOSXDrawingContext *dcPtr)\n{\n    MacDrawable *macDraw = (MacDrawable *)d;\n    bool canDraw = true;\n    TKContentView *view = nil;\n    TkMacOSXDrawingContext dc = {};\n    CGFloat drawingHeight;\n\n#ifdef TK_MAC_DEBUG_CG\n    fprintf(stderr, \"TkMacOSXSetupDrawingContext: %s\\n\",\n\t    macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : \"None\");\n#endif\n\n    /*\n     * If the drawable is not a pixmap, get the associated NSView.\n     */\n\n    if (!(macDraw->flags & TK_IS_PIXMAP)) {\n\tview = (TKContentView *)TkMacOSXGetNSViewForDrawable(d);\n\tif (!view) {\n\t    Tcl_Panic(\"TkMacOSXSetupDrawingContext(): \"\n\t\t    \"no NSView to draw into !\");\n\t}\n    }\n\n    /*\n     * Intersect the drawable's clipping region with the region stored in the\n     * X GC.  If the resulting region is empty, don't do any drawing.\n     */\n//#if 0 // disable clipping (almost works, but windows can open up blank)\n    dc.clipRgn = GetClipRgn(d);\n    ClipToGC(d, gc, &dc.clipRgn);\n    if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {\n\t/*\n\t * Things are probably not set up for drawing yet.  Request a call to\n\t * updateLayer and return failure.\n\t */\n\tcanDraw = false;\n\tgoto end;\n    }\n//#endif //disable clipping\n    /*\n     * If the drawable already has a CGContext, use it.  Otherwise, we must be\n     * drawing to a window and we use the current context of its ContentView.\n     */\n\n    dc.context = TkMacOSXGetCGContextForDrawable(d);\n    if (!dc.context) {\n\tdc.view = view;\n\tdc.context = view.tkLayerBitmapContext;\n\tif (dc.clipRgn) {\n\t    CGRect clipBounds;\n\t    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,\n\t\t\t\t    .ty = [view bounds].size.height};\n\t    HIShapeGetBounds(dc.clipRgn, &clipBounds);\n\t    clipBounds = CGRectApplyAffineTransform(clipBounds, t);\n\t}\n    }\n\n    /*\n     * Finish configuring the drawing context.\n     */\n\n#ifdef TK_MAC_DEBUG_CG\n    fprintf(stderr, \"TkMacOSXSetupDrawingContext: pushing GState for %s\\n\",\n\t    macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : \"None\");\n#endif\n\n    CGContextSaveGState(dc.context);\n    CGContextSetTextDrawingMode(dc.context, kCGTextFill);\n    { /* Restricted scope for t needed for C++ */\n\tdrawingHeight = view ? [view bounds].size.height :\n\t    CGContextGetClipBoundingBox(dc.context).size.height;\n\tCGAffineTransform t = {\n\t    .a = 1, .b = 0,\n\t    .c = 0, .d = -1,\n\t    .tx = 0,\n\t    .ty = drawingHeight\n\t};\n\tCGContextConcatCTM(dc.context, t);\n    }\n//#if 0    // disable clipping\n    if (dc.clipRgn) {\n\n#ifdef TK_MAC_DEBUG_DRAWING\n\tCGContextSaveGState(dc.context);\n\tChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);\n\tCGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);\n\tCGContextEOFillPath(dc.context);\n\tCGContextRestoreGState(dc.context);\n#endif /* TK_MAC_DEBUG_DRAWING */\n\n\tif (!HIShapeIsRectangular(dc.clipRgn)) {\n\n\t    /*\n\t     * We expect the clipping path dc.clipRgn to consist of the\n\t     * bounding rectangle of the drawable window, together with\n\t     * disjoint smaller rectangles inside of it which bound its\n\t     * geometric children.  In that case the even-odd rule will\n\t     * clip to the region inside the large rectangle and outside\n\t     * of the smaller rectangles.\n\t     */\n\n\t    ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);\n\n#ifdef TK_MAC_DEBUG_CG\n\t    fprintf(stderr, \"Setting complex clip for %s to:\\n\",\n\t\t    macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : \"None\");\n\t    TkMacOSXPrintRectsInRegion(dc.clipRgn);\n#endif\n\n\t    CGContextEOClip(dc.context);\n\t} else {\n\t    CGRect r;\n\t    HIShapeGetBounds(dc.clipRgn, &r);\n\n#ifdef TK_MAC_DEBUG_CG\n\t    fprintf(stderr, \"Current clip BBox is %s\\n\",\n\t\t    NSStringFromRect(CGContextGetClipBoundingBox(GET_CGCONTEXT)).UTF8String);\n\t    fprintf(stderr, \"Setting clip for %s to rect %s:\\n\",\n\t\t    macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : \"None\",\n\t\t    NSStringFromRect(r).UTF8String);\n#endif\n\n\t    CGContextClipToRect(dc.context, r);\n\t}\n    }\n//#endif //disable clipping\n\n    if (gc) {\n\tstatic const CGLineCap cgCap[] = {\n\t    [CapNotLast] = kCGLineCapButt,\n\t    [CapButt] = kCGLineCapButt,\n\t    [CapRound] = kCGLineCapRound,\n\t    [CapProjecting] = kCGLineCapSquare,\n\t};\n\tstatic const CGLineJoin cgJoin[] = {\n\t    [JoinMiter] = kCGLineJoinMiter,\n\t    [JoinRound] = kCGLineJoinRound,\n\t    [JoinBevel] = kCGLineJoinBevel,\n\t};\n\tbool shouldAntialias = !notAA(gc->line_width);\n\tdouble w = gc->line_width;\n\n\tTkMacOSXSetColorInContext(gc, gc->foreground, dc.context,\n\t\tTkMacOSXInDarkMode((Tk_Window)macDraw->winPtr));\n\tif (view) {\n\t    CGSize size = NSSizeToCGSize([view bounds].size);\n\t    CGContextSetPatternPhase(dc.context, size);\n\t}\n\tif (gc->function != GXcopy) {\n\t    TkMacOSXDbgMsg(\"Logical functions other than GXcopy are \"\n\t\t\t   \"not supported for CG drawing!\");\n\t}\n\tif (!shouldAntialias) {\n\n\t    /*\n\t     * Make non-antialiased CG drawing look more like X11.\n\t     */\n\n\t    w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);\n\t}\n\tCGContextSetShouldAntialias(dc.context, shouldAntialias);\n\tCGContextSetLineWidth(dc.context, w);\n\tif (gc->line_style != LineSolid) {\n\t    size_t num = 0;\n\t    char *p = &gc->dashes;\n\t    CGFloat dashOffset = gc->dash_offset;\n\t    dashOffset -= (gc->line_width % 2) ? 0.5 : 0.0;\n\t    CGFloat lengths[10];\n\n\t    while (p[num] != '\\0' && num < 10) {\n\t\tlengths[num] = p[num];\n\t\tnum++;\n\t    }\n\t    CGContextSetLineDash(dc.context, dashOffset, lengths, num);\n\t}\n\tif ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {\n\t    CGContextSetLineCap(dc.context, cgCap[(unsigned) gc->cap_style]);\n\t}\n\tif ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {\n\t    CGContextSetLineJoin(dc.context, cgJoin[(unsigned) gc->join_style]);\n\t}\n    }\n\nend:\n\n#ifdef TK_MAC_DEBUG_DRAWING\n    if (!canDraw && (macDraw->winPtr != NULL)) {\n\tfprintf(stderr, \"Cannot draw in %s - postponing.\\n\",\n\t\tTk_PathName(macDraw->winPtr));\n    }\n#endif\n\n    if (!canDraw && dc.clipRgn) {\n\tCFRelease(dc.clipRgn);\n\tdc.clipRgn = NULL;\n    }\n    *dcPtr = dc;\n    return canDraw;\n}\n\f\n/*\n * Idle task to schedule a call to updateLayer so the results of drawing\n * operations become visible. The call to nextEventMatchingMask has no effect,\n * but it provides an opportunity for the window manager to call updateLayer.\n */\n\nMODULE_SCOPE void\nTkMacOSXUpdateViewIdleTask(void *clientData) {\n    NSView *view = (NSView *) clientData;\n    [view setNeedsDisplay:YES];\n    [NSApp nextEventMatchingMask:NSAnyEventMask\n\t\t       untilDate:[NSDate distantPast]\n\t\t\t  inMode:NSDefaultRunLoopMode\n\t\t\t dequeue:NO];\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXRestoreDrawingContext --\n *\n *\tRestore drawing context.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXRestoreDrawingContext(\n    TkMacOSXDrawingContext *dcPtr)\n{\n    if (dcPtr->context) {\n\tCGContextSynchronize(dcPtr->context);\n\tCGContextRestoreGState(dcPtr->context);\n\n#ifdef TK_MAC_DEBUG_CG\n\tfprintf(stderr, \"TkMacOSXRestoreDrawingContext: popped GState\\n\");\n#endif\n\n    }\n    if (dcPtr->clipRgn) {\n\tCFRelease(dcPtr->clipRgn);\n\tdcPtr->clipRgn = NULL;\n    }\n\n    /*\n     * Schedule a call to updateLayer, since we have drawn on the view's\n     * backing layer.\n     */\n\n    Tcl_CancelIdleCall(TkMacOSXUpdateViewIdleTask, (void *) dcPtr->view);\n    Tcl_DoWhenIdle(TkMacOSXUpdateViewIdleTask, (void *) dcPtr->view);\n\n#ifdef TK_MAC_DEBUG\n    bzero(dcPtr, sizeof(TkMacOSXDrawingContext));\n#endif\n\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetClipRgn --\n *\n *\tGet the clipping region needed to restrict drawing to the given\n *\tdrawable.\n *\n * Results:\n *\tClipping region. If non-NULL, CFRelease it when done.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHIShapeRef\nGetClipRgn(\n    Drawable drawable)\t\t/* Drawable. */\n{\n    MacDrawable *macDraw = (MacDrawable *)drawable;\n    HIShapeRef clipRgn = NULL;\n\n    if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {\n\tTkMacOSXUpdateClipRgn(macDraw->winPtr);\n#ifdef TK_MAC_DEBUG_DRAWING\n\tTkMacOSXDbgMsg(\"%s\", macDraw->winPtr->pathName);\n\n\tNSView *view = TkMacOSXGetNSViewForDrawable(macDraw);\n\tCGContextRef context = GET_CGCONTEXT;\n\n\tCGContextSaveGState(context);\n\tCGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,\n\t      -1.0, 0.0, [view bounds].size.height));\n\tChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);\n\tCGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);\n\tCGContextEOFillPath(context);\n\tCGContextRestoreGState(context);\n#endif /* TK_MAC_DEBUG_DRAWING */\n    }\n\n    if (macDraw->drawRgn) {\n\t// The drawRgn is the visRgn intersected with a rectangle which\n\t// may be smaller than the widget bounds.\n\tclipRgn = HIShapeCreateCopy(macDraw->drawRgn);\n    } else if (macDraw->visRgn) {\n\tclipRgn = HIShapeCreateCopy(macDraw->visRgn);\n    }\n    // A NULL clipRgn does not allow any drawing at all.\n    return clipRgn;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ClipDrawableToRect --\n *\n *\tClip all drawing into the drawable d to the given rectangle. If width\n *\tor height are negative, reset to no clipping. This is called by the\n *\tText widget to display each DLine, and by the Canvas widget when it\n *\tis updating a sub rectangle in the canvas.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSubsequent drawing into d is offset and clipped as specified.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ClipDrawableToRect(\n    TCL_UNUSED(Display *),\n    Drawable d,\n    int x, int y,\n    int width, int height)\n{\n    MacDrawable *macDraw = (MacDrawable *)d;\n\n    if (macDraw->drawRgn) {\n\tCFRelease(macDraw->drawRgn);\n\tmacDraw->drawRgn = NULL;\n    }\n    if (width >= 0 && height >= 0) {\n\tCGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,\n\t\twidth, height);\n\tHIShapeRef drawRgn = HIShapeCreateWithRect(&clipRect);\n\n\t// When drawing a Text widget we can reuse the\n\t// clipping region for different DLines, so we don't want to\n\t// update unless necessary.\n\tif (macDraw->winPtr && (macDraw->flags & TK_CLIP_INVALID)) {\n\t    TkMacOSXUpdateClipRgn(macDraw->winPtr);\n\t}\n\tif (macDraw->visRgn) {\n\t    macDraw->drawRgn = HIShapeCreateIntersection(macDraw->visRgn,\n\t\t    drawRgn);\n\t    CFRelease(drawRgn);\n\t} else {\n\t    macDraw->drawRgn = drawRgn;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClipToGC --\n *\n *\tHelper function to intersect given region with gc clip region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nClipToGC(\n    Drawable d,\n    GC gc,\n    HIShapeRef *clipRgnPtr) /* must point to initialized variable */\n{\n    if (gc && gc->clip_mask &&\n\t    ((TkpClipMask *)gc->clip_mask)->type == TKP_CLIP_REGION) {\n\tRegion gcClip = ((TkpClipMask *)gc->clip_mask)->value.region;\n\tint xOffset = ((MacDrawable *)d)->xOff + gc->clip_x_origin;\n\tint yOffset = ((MacDrawable *)d)->yOff + gc->clip_y_origin;\n\tHIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;\n\n\tXOffsetRegion(gcClip, xOffset, yOffset);\n\tgcClipRgn = TkMacOSXGetNativeRegion(gcClip);\n\tif (clipRgn) {\n\t    *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn);\n\t    CFRelease(clipRgn);\n\t} else {\n\t    *clipRgnPtr = HIShapeCreateCopy(gcClipRgn);\n\t}\n\tCFRelease(gcClipRgn);\n\tXOffsetRegion(gcClip, -xOffset, -yOffset);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DrawHighlightBorder --\n *\n *\tThis procedure draws a rectangular ring around the outside of a widget\n *\tto indicate that it has received the input focus.\n *\n *\tOn the Macintosh, this puts a 1 pixel border in the bgGC color between\n *\tthe widget and the focus ring, except in the case where highlightWidth\n *\tis 0 or 1, in which case the border is left out.\n *\n *\tFor proper Mac L&F, use highlightWidth of 3.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA rectangle \"width\" pixels wide is drawn in \"drawable\", corresponding\n *\tto the outer area of \"tkwin\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DrawHighlightBorder(\n    Tk_Window tkwin,\n    GC fgGC,\n    GC bgGC,\n    int highlightWidth,\n    Drawable drawable)\n{\n    if (highlightWidth <= 1) {\n\tTkDrawInsetFocusHighlight(tkwin, fgGC, 1, drawable, 0);\n    } else {\n\tTkDrawInsetFocusHighlight(tkwin, bgGC, highlightWidth, drawable, 0);\n\tif (fgGC != bgGC) {\n\t    TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth - 1,\n\t\t    drawable, 0);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawFrameEx --\n *\n *\tThis procedure draws the rectangular frame area. If the user has\n *\trequested themeing, it draws with the background theme.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws inside the tkwin area.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawFrameEx(\n    Tk_Window tkwin,\n    Drawable drawable,\n    Tk_3DBorder border,\n    int highlightWidth,\n    int borderWidth,\n    int relief)\n{\n    if (useThemedToplevel && Tk_IsTopLevel(tkwin)) {\n\tstatic Tk_3DBorder themedBorder = NULL;\n\n\tif (!themedBorder) {\n\t    themedBorder = Tk_Get3DBorder(NULL, tkwin,\n\t\t    \"systemWindowHeaderBackground\");\n\t}\n\tif (themedBorder) {\n\t    border = themedBorder;\n\t}\n    }\n\n    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,\n\t    highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth,\n\t    Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief);\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXEmbed.c",
    "content": "/*\n * tkMacOSXEmbed.c --\n *\n *\tThis file contains platform-specific procedures for theMac to provide\n *\tbasic operations needed for application embedding (where one\n *\tapplication can use as its main window an internal window from some\n *\tother application). Currently only Toplevel embedding within the same\n *\tTk application is allowed on the Macintosh.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkBusy.h\"\n\n/*\n * One of the following structures exists for each container in this\n * application. It keeps track of the container window and its associated\n * embedded window.\n */\n\ntypedef struct Container {\n    Window parent;\t\t/* The Mac Drawable for the parent of the pair\n\t\t\t\t * (the container). */\n    TkWindow *parentPtr;\t/* Tk's information about the container, or\n\t\t\t\t * NULL if the container isn't in this\n\t\t\t\t * process. */\n    Window embedded;\t\t/* The MacDrawable for the embedded window.\n\t\t\t\t * Starts off as None, but gets filled in when\n\t\t\t\t * the window is eventually created. */\n    TkWindow *embeddedPtr;\t/* Tk's information about the embedded window,\n\t\t\t\t * or NULL if the embedded application isn't\n\t\t\t\t * in this process. */\n    struct Container *nextPtr;\t/* Next in list of all containers in this\n\t\t\t\t * process. */\n} Container;\n\nstatic Container *firstContainerPtr = NULL;\n\t\t\t\t/* First in list of all containers managed by\n\t\t\t\t * this process. */\n\n/*\n * Prototypes for static procedures defined in this file:\n */\n\nstatic void\tContainerEventProc(void *clientData, XEvent *eventPtr);\nstatic void\tEmbeddedEventProc(void *clientData, XEvent *eventPtr);\nstatic void\tEmbedActivateProc(void *clientData, XEvent *eventPtr);\nstatic void\tEmbedFocusProc(void *clientData, XEvent *eventPtr);\nstatic void\tEmbedGeometryRequest(Container *containerPtr, int width,\n\t\t    int height);\nstatic void\tEmbedSendConfigure(Container *containerPtr);\nstatic void\tEmbedStructureProc(void *clientData, XEvent *eventPtr);\nstatic void\tEmbedWindowDeleted(TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeWindow --\n *\n *\tCreates an X Window (Mac subwindow).\n *\n * Results:\n *\tThe window id is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTk_MakeWindow(\n    Tk_Window tkwin,\n    TCL_UNUSED(Window))\n{\n    MacDrawable *macWin;\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    /*\n     * If this window is marked as embedded then the window structure should\n     * have already been created in the Tk_UseWindow function.\n     */\n\n    if (Tk_IsEmbedded(winPtr)) {\n\tmacWin = winPtr->privatePtr;\n    } else {\n\t/*\n\t * Allocate sub window\n\t */\n\n\tmacWin = (MacDrawable *)Tcl_Alloc(sizeof(MacDrawable));\n\tif (macWin == NULL) {\n\t    winPtr->privatePtr = NULL;\n\t    return None;\n\t}\n\tmacWin->winPtr = winPtr;\n\twinPtr->privatePtr = macWin;\n\tmacWin->visRgn = NULL;\n\tmacWin->aboveVisRgn = NULL;\n\tmacWin->drawRgn = NULL;\n\tmacWin->referenceCount = 0;\n\tmacWin->flags = TK_CLIP_INVALID;\n\tmacWin->view = nil;\n\tmacWin->context = NULL;\n\tmacWin->size = CGSizeZero;\n\tif (Tk_IsTopLevel(macWin->winPtr)) {\n\t    /*\n\t     * This will be set when we are mapped.\n\t     */\n\n\t    macWin->xOff = 0;\n\t    macWin->yOff = 0;\n\t    macWin->toplevel = macWin;\n\t} else if (winPtr->parentPtr) {\n\t    macWin->xOff = winPtr->parentPtr->privatePtr->xOff +\n\t\t    winPtr->parentPtr->changes.border_width +\n\t\t    winPtr->changes.x;\n\t    macWin->yOff = winPtr->parentPtr->privatePtr->yOff +\n\t\t    winPtr->parentPtr->changes.border_width +\n\t\t    winPtr->changes.y;\n\t    macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;\n\t}\n\tmacWin->toplevel->referenceCount++;\n    }\n    return (Window) macWin;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpScanWindowId --\n *\n *\tGiven a string, produce the corresponding Window Id.\n *\n * Results:\n *      The return value is normally TCL_OK; in this case *idPtr will be set\n *      to the Window value equivalent to string. If string is improperly\n *      formed then TCL_ERROR is returned and an error message will be left in\n *      the interp's result.\n *\n * Side effects:\n *      None.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpScanWindowId(\n    Tcl_Interp *interp,\n    const char * string,\n    Window *idPtr)\n{\n    int code;\n    Tcl_Obj obj;\n\n    obj.refCount = 1;\n    obj.bytes = (char *) string;\t/* DANGER?! */\n    obj.length = strlen(string);\n    obj.typePtr = NULL;\n\n    code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr);\n\n    if (obj.refCount > 1) {\n\tTcl_Panic(\"invalid sharing of Tcl_Obj on C stack\");\n    }\n    if (obj.typePtr && obj.typePtr->freeIntRepProc) {\n\tobj.typePtr->freeIntRepProc(&obj);\n    }\n    return code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UseWindow --\n *\n *\tThis procedure causes a Tk window to use a given X window as its\n *\tparent window, rather than the root window for the screen. It is\n *\tinvoked by an embedded application to specify the window in which it\n *\tis embedded.\n *\n * Results:\n *\tThe return value is normally TCL_OK. If an error occurs (such as\n *\tstring not being a valid window spec), then the return value is\n *\tTCL_ERROR and an error message is left in the interp's result if\n *\tinterp is non-NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_UseWindow(\n    Tcl_Interp *interp,\t\t/* If not NULL, used for error reporting if\n\t\t\t\t * string is bogus. */\n    Tk_Window tkwin,\t\t/* Tk window that does not yet have an\n\t\t\t\t * associated X window. */\n    const char *string)\t\t/* String identifying an X window to use for\n\t\t\t\t * tkwin; must be an integer value. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *usePtr;\n    MacDrawable *parent, *macWin;\n    Container *containerPtr;\n\n    if (winPtr->window != None) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't modify container after widget is created\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"POST_CREATE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Decode the container window ID, and look for it among the list of\n     * available containers.\n     *\n     * N.B. For now, we are limiting the containers to be in the same Tk\n     * application as tkwin, since otherwise they would not be in our list of\n     * containers.\n     */\n\n    if (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);\n    if (usePtr == NULL) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"couldn't create child of window \\\"%s\\\"\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"NO_TARGET\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    } else if (!(usePtr->flags & TK_CONTAINER)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" doesn't have -container option set\",\n\t\tusePtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"CONTAINER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Since we do not allow embedding into windows belonging to a different\n     * process, we know that a container will exist showing the parent window\n     * as the parent.  This loop finds that container.\n     */\n\n    for (containerPtr = firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->parent == (Window) parent) {\n\t    winPtr->flags |= TK_BOTH_HALVES;\n\t    containerPtr->parentPtr->flags |= TK_BOTH_HALVES;\n\t    break;\n\t}\n    }\n\n    /*\n     * Make the embedded window.\n     */\n\n    macWin = (MacDrawable *)Tcl_Alloc(sizeof(MacDrawable));\n    if (macWin == NULL) {\n\twinPtr->privatePtr = NULL;\n\treturn TCL_ERROR;\n    }\n\n    macWin->winPtr = winPtr;\n    macWin->view = nil;\n    macWin->context = NULL;\n    macWin->size = CGSizeZero;\n    macWin->visRgn = NULL;\n    macWin->aboveVisRgn = NULL;\n    macWin->drawRgn = NULL;\n    macWin->referenceCount = 0;\n    macWin->flags = TK_CLIP_INVALID;\n    macWin->toplevel = macWin;\n    macWin->toplevel->referenceCount++;\n\n    winPtr->privatePtr = macWin;\n    winPtr->flags |= TK_EMBEDDED;\n\n    /*\n     * Make a copy of the TK_EMBEDDED flag, since sometimes we need this to\n     * get the port after the TkWindow structure has been freed.\n     */\n\n    macWin->flags |= TK_EMBEDDED;\n    macWin->xOff = parent->winPtr->privatePtr->xOff +\n\t    parent->winPtr->changes.border_width +\n\t    winPtr->changes.x;\n    macWin->yOff = parent->winPtr->privatePtr->yOff +\n\t    parent->winPtr->changes.border_width +\n\t    winPtr->changes.y;\n\n    /*\n     * Finish filling up the container structure with the embedded window's\n     * information.\n     */\n\n    containerPtr->embedded = (Window) macWin;\n    containerPtr->embeddedPtr = macWin->winPtr;\n\n    /*\n     * Create an event handler to clean up the Container structure when\n     * tkwin is eventually deleted.\n     */\n\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t    EmbeddedEventProc, winPtr);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeContainer --\n *\n *\tThis procedure is called to indicate that a particular window will be\n *\ta container for an embedded application. This changes certain aspects\n *\tof the window's behavior, such as whether it will receive events\n *\tanymore.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MakeContainer(\n    Tk_Window tkwin)\t\t/* Token for a window that is about to become\n\t\t\t\t * a container. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    Container *containerPtr;\n\n    /*\n     * Register the window as a container so that, for example, we can make\n     * sure the argument to -use is valid.\n     */\n\n    Tk_MakeWindowExist(tkwin);\n    containerPtr = (Container *)Tcl_Alloc(sizeof(Container));\n    containerPtr->parent = Tk_WindowId(tkwin);\n    containerPtr->parentPtr = winPtr;\n    containerPtr->embedded = None;\n    containerPtr->embeddedPtr = NULL;\n    containerPtr->nextPtr = firstContainerPtr;\n    firstContainerPtr = containerPtr;\n    winPtr->flags |= TK_CONTAINER;\n\n    /*\n     * Request SubstructureNotify events so that we can find out when the\n     * embedded application creates its window or attempts to resize it. Also\n     * watch Configure events on the container so that we can resize the child\n     * to match. Also, pass activate events from the container down to the\n     * embedded toplevel.\n     */\n\n    Tk_CreateEventHandler(tkwin,\n\t    SubstructureNotifyMask|SubstructureRedirectMask,\n\t    ContainerEventProc, winPtr);\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc,\n\t    containerPtr);\n    Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc,\n\t    containerPtr);\n    Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc,\n\t    containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXContainerId --\n *\n *\tGiven an embedded window, this procedure returns the MacDrawable\n *\tidentifier for the associated container window.\n *\n * Results:\n *\tThe return value is the MacDrawable for winPtr's container window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMacDrawable *\nTkMacOSXContainerId(\n    TkWindow *winPtr)\t\t/* Tk's structure for an embedded window. */\n{\n    Container *containerPtr;\n\n    for (containerPtr = firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->embeddedPtr == winPtr) {\n\t    return (MacDrawable *)containerPtr->parent;\n\t}\n    }\n    Tcl_Panic(\"TkMacOSXContainerId couldn't find window\");\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetHostToplevel --\n *\n *\tGiven the TkWindow, return the MacDrawable for the outermost toplevel\n *\tcontaining it. This will be a real Macintosh window.\n *\n * Results:\n *\tReturns a MacDrawable corresponding to a Macintosh Toplevel\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMacDrawable *\nTkMacOSXGetHostToplevel(\n    TkWindow *winPtr)\t\t/* Tk's structure for a window. */\n{\n    TkWindow *contWinPtr, *topWinPtr;\n\n    if (!(winPtr && winPtr->privatePtr)) {\n\treturn NULL;\n    }\n\n    topWinPtr = winPtr->privatePtr->toplevel->winPtr;\n    if (!Tk_IsEmbedded(topWinPtr)) {\n\treturn winPtr->privatePtr->toplevel;\n    }\n    contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)topWinPtr);\n\n    /*\n     * TODO: Here we should handle out of process embedding.\n     */\n\n    return TkMacOSXGetHostToplevel(contWinPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpClaimFocus --\n *\n *\tThis procedure is invoked when someone asks for the input focus to be\n *\tput on a window in an embedded application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe input focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpClaimFocus(\n    TkWindow *topLevelPtr,\t/* Top-level window containing desired focus\n\t\t\t\t * window; should be embedded. */\n    int force)\t\t\t/* One means that the container should claim\n\t\t\t\t * the focus if it doesn't currently have\n\t\t\t\t * it. */\n{\n    XEvent event;\n    Container *containerPtr;\n\n    if (!(topLevelPtr->flags & TK_EMBEDDED)) {\n\treturn;\n    }\n\n    for (containerPtr = firstContainerPtr;\n\t    containerPtr->embeddedPtr != topLevelPtr;\n\t    containerPtr = containerPtr->nextPtr) {\n\t/* Empty loop body. */\n    }\n\n    event.xfocus.type = FocusIn;\n    event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);\n    event.xfocus.send_event = 1;\n    event.xfocus.display = topLevelPtr->display;\n    event.xfocus.window = containerPtr->parent;\n    event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;\n    event.xfocus.detail = force;\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTestembedCmd --\n *\n *\tThis procedure implements the \"testembed\" command. It returns some or\n *\tall of the information in the list pointed to by firstContainerPtr.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpTestembedCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    int all;\n    Container *containerPtr;\n    Tcl_DString dString;\n    char buffer[50];\n    Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;\n\n    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), \"all\") == 0)) {\n\tall = 1;\n    } else {\n\tall = 0;\n    }\n    Tcl_DStringInit(&dString);\n    for (containerPtr = firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->embeddedPtr != NULL) {\n\t    embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;\n\t}\n\tif (containerPtr->parentPtr != NULL) {\n\t    parentInterp = containerPtr->parentPtr->mainPtr->interp;\n\t}\n\tif (embeddedInterp != interp && parentInterp != interp) {\n\t    continue;\n\t}\n\tTcl_DStringStartSublist(&dString);\n\n\t/*\n\t * Parent id\n\t */\n\n\tif (containerPtr->parent == None) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else if (all) {\n\t    snprintf(buffer, sizeof(buffer), \"0x%\" TCL_Z_MODIFIER \"x\",\n\t\t    (size_t) containerPtr->parent);\n\t    Tcl_DStringAppendElement(&dString, buffer);\n\t} else {\n\t    Tcl_DStringAppendElement(&dString, \"XXX\");\n\t}\n\n\t/*\n\t * Parent pathName\n\t */\n\n\tif (containerPtr->parentPtr == NULL ||\n\t    parentInterp != interp) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else {\n\t    Tcl_DStringAppendElement(&dString,\n\t\t    containerPtr->parentPtr->pathName);\n\t}\n\n\t/*\n\t * On X11 embedded is a wrapper, which does not exist on macOS.\n\t */\n\n\tTcl_DStringAppendElement(&dString, \"\");\n\n\t/*\n\t * Embedded window pathName\n\t */\n\n\tif (containerPtr->embeddedPtr == NULL ||\n\t    embeddedInterp != interp) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else {\n\t    Tcl_DStringAppendElement(&dString,\n\t\t    containerPtr->embeddedPtr->pathName);\n\t}\n\tTcl_DStringEndSublist(&dString);\n    }\n    Tcl_DStringResult(interp, &dString);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpRedirectKeyEvent --\n *\n *\tThis procedure is invoked when a key press or release event arrives\n *\tfor an application that does not believe it owns the input focus. This\n *\tcan happen because of embedding; for example, X can send an event to\n *\tan embedded application when the real focus window is in the container\n *\tapplication and is an ancestor of the container. This procedure's job\n *\tis to forward the event back to the application where it really\n *\tbelongs.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe event may get sent to a different application.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpRedirectKeyEvent(\n    TCL_UNUSED(TkWindow *),\t\t/* Window to which the event was originally\n\t\t\t\t * reported. */\n    TCL_UNUSED(XEvent *))\t\t/* X event to redirect (should be KeyPress or\n\t\t\t\t * KeyRelease). */\n{\n    /* TODO: Implement this or decide it definitely needs no implementation */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOtherWindow --\n *\n *\tIf both the container and embedded window are in the same process,\n *\tthis procedure will return either one, given the other.\n *\n * Results:\n *\tIf tkwin is a container, the return value is the token for the\n *\tembedded window, and vice versa. If the \"other\" window isn't in this\n *\tprocess, NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_GetOtherWindow(\n    Tk_Window tkwin)\t\t/* Tk's structure for a container or embedded\n\t\t\t\t * window. */\n{\n    Container *containerPtr;\n\n    /*\n     * Tk_GetOtherWindow returns NULL if both windows are not in the same\n     * process...\n     */\n\n    if (!(tkwin && (((TkWindow*)tkwin)->flags & TK_BOTH_HALVES))) {\n\treturn NULL;\n    }\n\n    for (containerPtr = firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif ((Tk_Window)containerPtr->embeddedPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->parentPtr;\n\t} else if ((Tk_Window)containerPtr->parentPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->embeddedPtr;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbeddedEventProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when various\n *\tuseful events are received for a window that is embedded in\n *\tanother application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOur internal state gets cleaned up when an embedded window is\n *\tdestroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbeddedEventProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tEmbedWindowDeleted(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ContainerEventProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when various\n *\tuseful events are received for the children of a container window. It\n *\tforwards relevant information, such as geometry requests, from the\n *\tevents into the container's application.\n *\n *\tNOTE: on the Mac, only the DestroyNotify branch is ever taken. We\n *\tdon't synthesize the other events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the event. For example, when ConfigureRequest events occur,\n *\tgeometry information gets set for the container window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nContainerEventProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    Container *containerPtr;\n    Tk_ErrorHandler errHandler;\n\n    if (!firstContainerPtr) {\n\t/*\n\t * When the interpreter is being dismantled this can be nil.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * Ignore any X protocol errors that happen in this procedure (almost any\n     * operation could fail, for example, if the embedded application has\n     * deleted its window).\n     */\n\n    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,\n\t    -1, -1, NULL, NULL);\n\n    /*\n     * Find the Container structure associated with the parent window.\n     */\n\n    for (containerPtr = firstContainerPtr;\n\t    containerPtr->parent != eventPtr->xmaprequest.parent;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr == NULL) {\n\t    Tcl_Panic(\"ContainerEventProc couldn't find Container record\");\n\t}\n    }\n\n    if (eventPtr->type == CreateNotify) {\n\t/*\n\t * A new child window has been created in the container. Record its id\n\t * in the Container structure (if more than one child is created, just\n\t * remember the last one and ignore the earlier ones).\n\t */\n\n\tcontainerPtr->embedded = eventPtr->xcreatewindow.window;\n    } else if (eventPtr->type == ConfigureRequest) {\n\tif ((eventPtr->xconfigurerequest.x != 0)\n\t\t|| (eventPtr->xconfigurerequest.y != 0)) {\n\t    /*\n\t     * The embedded application is trying to move itself, which isn't\n\t     * legal. At this point, the window hasn't actually moved, but we\n\t     * need to send it a ConfigureNotify event to let it know that its\n\t     * request has been denied. If the embedded application was also\n\t     * trying to resize itself, a ConfigureNotify will be sent by the\n\t     * geometry management code below, so we don't need to do\n\t     * anything. Otherwise, generate a synthetic event.\n\t     */\n\n\t    if ((eventPtr->xconfigurerequest.width == winPtr->changes.width)\n\t\t    && (eventPtr->xconfigurerequest.height\n\t\t    == winPtr->changes.height)) {\n\t\tEmbedSendConfigure(containerPtr);\n\t    }\n\t}\n\tEmbedGeometryRequest(containerPtr,\n\t\teventPtr->xconfigurerequest.width,\n\t\teventPtr->xconfigurerequest.height);\n    } else if (eventPtr->type == MapRequest) {\n\t/*\n\t * The embedded application's map request was ignored and simply\n\t * passed on to us, so we have to map the window for it to appear on\n\t * the screen.\n\t */\n\n\tXMapWindow(eventPtr->xmaprequest.display,\n\t\teventPtr->xmaprequest.window);\n    } else if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * It is not clear whether the container should be destroyed\n\t * when an embedded window is destroyed.  See ticket [67384bce7d].\n\t * Here we are following unix, by destroying the container.\n\t */\n\n\tTk_DestroyWindow((Tk_Window)winPtr);\n    }\n    Tk_DeleteErrorHandler(errHandler);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedStructureProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when a container\n *\twindow owned by this application gets resized (and also at several\n *\tother times that we don't care about). This procedure reflects the\n *\tsize change in the embedded window that corresponds to the container.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe embedded window gets resized to match the container.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedStructureProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Tk_ErrorHandler errHandler;\n\n    if (eventPtr->type == ConfigureNotify) {\n\n\t/*\n\t * Send a ConfigureNotify  to the embedded application.\n\t */\n\n\tif (containerPtr->embeddedPtr != NULL) {\n\t    TkDoConfigureNotify(containerPtr->embeddedPtr);\n\t}\n\tif (containerPtr->embedded != None) {\n\t    /*\n\t     * Ignore errors, since the embedded application could have\n\t     * deleted its window.\n\t     */\n\n\t    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,\n\t\t    -1, -1, NULL, NULL);\n\t    Tk_MoveResizeWindow((Tk_Window)containerPtr->embeddedPtr, 0, 0,\n\t\t    Tk_Width((Tk_Window)containerPtr->parentPtr),\n\t\t    Tk_Height((Tk_Window)containerPtr->parentPtr));\n\t    Tk_DeleteErrorHandler(errHandler);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tEmbedWindowDeleted(containerPtr->parentPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedActivateProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when Activate and\n *\tDeactivate events occur for a container window owned by this\n *\tapplication. It is responsible for forwarding an activate event down\n *\tinto the embedded toplevel.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe X focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedActivateProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n\n    if (containerPtr->embeddedPtr != NULL) {\n\tif (eventPtr->type == ActivateNotify) {\n\t    TkGenerateActivateEvents(containerPtr->embeddedPtr,1);\n\t} else if (eventPtr->type == DeactivateNotify) {\n\t    TkGenerateActivateEvents(containerPtr->embeddedPtr,0);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedFocusProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when FocusIn and\n *\tFocusOut events occur for a container window owned by this\n *\tapplication. It is responsible for moving the focus back and forth\n *\tbetween a container application and an embedded application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe X focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedFocusProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Display *display;\n    XEvent event;\n\n    if (containerPtr->embeddedPtr != NULL) {\n\tdisplay = Tk_Display(containerPtr->parentPtr);\n\tevent.xfocus.serial = LastKnownRequestProcessed(display);\n\tevent.xfocus.send_event = false;\n\tevent.xfocus.display = display;\n\tevent.xfocus.mode = NotifyNormal;\n\tevent.xfocus.window = containerPtr->embedded;\n\n\tif (eventPtr->type == FocusIn) {\n\t    /*\n\t     * The focus just arrived at the container. Change the X focus to\n\t     * move it to the embedded application, if there is one. Ignore X\n\t     * errors that occur during this operation (it's possible that the\n\t     * new focus window isn't mapped).\n\t     */\n\n\t    event.xfocus.detail = NotifyNonlinear;\n\t    event.xfocus.type = FocusIn;\n\t} else if (eventPtr->type == FocusOut) {\n\t    /*\n\t     * When the container gets a FocusOut event, it has to tell the\n\t     * embedded app that it has lost the focus.\n\t     */\n\n\t    event.xfocus.type = FocusOut;\n\t    event.xfocus.detail = NotifyNonlinear;\n\t}\n\n\tTk_QueueWindowEvent(&event, TCL_QUEUE_MARK);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedGeometryRequest --\n *\n *\tThis procedure is invoked when an embedded application requests a\n *\tparticular size. It processes the request (which may or may not\n *\tactually honor the request) and reflects the results back to the\n *\tembedded application.\n *\n *\tNOTE: On the Mac, this is a stub, since we don't synthesize\n *\tConfigureRequest events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf we deny the child's size change request, a Configure event is\n *\tsynthesized to let the child know how big it ought to be. Events get\n *\tprocessed while we're waiting for the geometry managers to do their\n *\tthing.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedGeometryRequest(\n    Container *containerPtr,\t/* Information about the embedding. */\n    int width, int height)\t/* Size that the child has requested. */\n{\n    TkWindow *winPtr = containerPtr->parentPtr;\n\n    /*\n     * Forward the requested size into our geometry management hierarchy via\n     * the container window. We need to send a Configure event back to the\n     * embedded application if we decide not to honor its request; to make this\n     * happen, process all idle event handlers synchronously here (so that the\n     * geometry managers have had a chance to do whatever they want to do), and\n     * if the window's size didn't change then generate a configure event.\n     */\n\n    Tk_GeometryRequest((Tk_Window)winPtr, width, height);\n    if ((winPtr->changes.width != width)\n\t|| (winPtr->changes.height != height)) {\n\tEmbedSendConfigure(containerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedSendConfigure --\n *\n *\tThis is currently a stub. It is called to notify an embedded\n *\tapplication of its current size and location. This procedure is called\n *\twhen the embedded application made a geometry request that we did not\n *\tgrant, so that the embedded application knows that its geometry didn't\n *\tchange after all. It is a response to ConfigureRequest events, which we\n *\tdo not currently synthesize on the Mac\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedSendConfigure(\n    TCL_UNUSED(Container *))\t/* Information about the embedding. */\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedWindowDeleted --\n *\n *\tThis procedure is invoked when a window involved in embedding (as\n *\teither the container or the embedded application) is destroyed. It\n *\tcleans up the Container structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Container structure may be freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedWindowDeleted(\n    TkWindow *winPtr)\t\t/* Tk's information about window that\n\t\t\t\t * was deleted. */\n{\n    Container *containerPtr, *prevPtr;\n\n    /*\n     * Find the Container structure for this window. Delete the information\n     * about the embedded application and free the container's record.\n     */\n\n    prevPtr = NULL;\n    containerPtr = firstContainerPtr;\n    while (1) {\n\tif (containerPtr == NULL) {\n\t    return;\n\t}\n\tif (containerPtr->embeddedPtr == winPtr) {\n\t    /*\n\t     * We also have to destroy our parent, to clean up the container.\n\t     * Fabricate an event to do this.\n\t     */\n\n\t    if (containerPtr->parentPtr != NULL &&\n\t\t    containerPtr->parentPtr->flags & TK_BOTH_HALVES) {\n\t\tXEvent event;\n\n\t\tevent.xany.serial = LastKnownRequestProcessed(\n\t\t\tTk_Display(containerPtr->parentPtr));\n\t\tevent.xany.send_event = False;\n\t\tevent.xany.display = Tk_Display(containerPtr->parentPtr);\n\n\t\tevent.xany.type = DestroyNotify;\n\t\tevent.xany.window = containerPtr->parent;\n\t\tevent.xdestroywindow.event = containerPtr->parent;\n\t\tTk_QueueWindowEvent(&event, TCL_QUEUE_HEAD);\n\t    }\n\n\t    containerPtr->embedded = None;\n\t    containerPtr->embeddedPtr = NULL;\n\t    break;\n\t}\n\tif (containerPtr->parentPtr == winPtr) {\n\t    containerPtr->parentPtr = NULL;\n\t    break;\n\t}\n\tprevPtr = containerPtr;\n\tcontainerPtr = containerPtr->nextPtr;\n    }\n    if ((containerPtr->embeddedPtr == NULL)\n\t    && (containerPtr->parentPtr == NULL)) {\n\tif (prevPtr == NULL) {\n\t    firstContainerPtr = containerPtr->nextPtr;\n\t} else {\n\t    prevPtr->nextPtr = containerPtr->nextPtr;\n\t}\n\tTcl_Free(containerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpShowBusyWindow, TkpHideBusyWindow, TkpMakeTransparentWindowExist,\n * TkpCreateBusy --\n *\n *\tPortability layer for busy windows. Holds platform-specific gunk for\n *\tthe [tk busy] command, which is currently a dummy implementation for\n *\tOSX/Aqua. The individual functions are supposed to do the following:\n *\n * TkpShowBusyWindow --\n *\tMake the busy window appear.\n *\n * TkpHideBusyWindow --\n *\tMake the busy window go away.\n *\n * TkpMakeTransparentWindowExist --\n *\tActually make a transparent window.\n *\n * TkpCreateBusy --\n *\tCreates the platform-specific part of a busy window structure.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpShowBusyWindow(\n    TCL_UNUSED(TkBusy))\n{\n}\n\nvoid\nTkpHideBusyWindow(\n    TCL_UNUSED(TkBusy))\n{\n}\n\nvoid\nTkpMakeTransparentWindowExist(\n    TCL_UNUSED(Tk_Window),\t\t/* Token for window. */\n    TCL_UNUSED(Window))\t\t/* Parent window. */\n{\n}\n\nvoid\nTkpCreateBusy(\n    TCL_UNUSED(Tk_FakeWin *),\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(TkBusy))\n{\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXEntry.c",
    "content": "/*\n * tkMacOSXEntry.c --\n *\n *\tThis file implements the native aqua entry widget.\n *\n * Copyright © 2001 Apple Computer, Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2008-2009 Apple Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkEntry.h\"\n\nstatic ThemeButtonKind\tComputeIncDecParameters(int height, int *width);\n\n#define HIOrientation kHIThemeOrientationNormal\n\f\n/*\n *--------------------------------------------------------------\n *\n * ComputeIncDecParameters --\n *\n *\tThis procedure figures out which of the kThemeIncDec buttons to use.\n *\tIt also sets width to the width of the IncDec button.\n *\n * Results:\n *\tThe ThemeButtonKind of the button we should use.\n *\n * Side effects:\n *\tMay draw the entry border into pixmap.\n *\n *--------------------------------------------------------------\n */\n\nstatic ThemeButtonKind\nComputeIncDecParameters(\n    int height,\n    int *width)\n{\n    ThemeButtonKind kind;\n\n    if (height < 11 || height > 28) {\n\t*width = 0;\n\tkind = (ThemeButtonKind) 0;\n    } else {\n\tif (height >= 21) {\n\t    *width = 13;\n\t    kind = kThemeIncDecButton;\n\t} else if (height >= 18) {\n\t    *width = 12;\n\t    kind = kThemeIncDecButtonSmall;\n\t} else {\n\t    *width = 11;\n\t    kind = kThemeIncDecButtonMini;\n\t}\n    }\n\n    return kind;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDrawEntryBorderAndFocus --\n *\n *\tThis procedure redraws the border of an entry window. It overrides the\n *\tgeneric border drawing code if the entry widget parameters are such\n *\tthat the native widget drawing is a good fit. This version just\n *\treturns 1, so platforms that don't do special native drawing don't\n *\thave to implement it.\n *\n * Results:\n *\ttrue if it has drawn the border, false if not.\n *\n * Side effects:\n *\tMay draw the entry border into pixmap.\n *\n *--------------------------------------------------------------\n */\n\nbool\nTkpDrawEntryBorderAndFocus(\n    Entry *entryPtr,\n    Drawable d,\n    bool isSpinbox)\n{\n    CGRect bounds;\n    TkMacOSXDrawingContext dc;\n    GC bgGC;\n    Tk_Window tkwin = entryPtr->tkwin;\n    int oldWidth = 0;\n    MacDrawable *macDraw = (MacDrawable *)d;\n    const HIThemeFrameDrawInfo info = {\n\t.version = 0,\n\t.kind = kHIThemeFrameTextFieldSquare,\n\t.state = (entryPtr->state == STATE_DISABLED ? kThemeStateInactive :\n\t\tkThemeStateActive),\n\t.isFocused = (entryPtr->flags & GOT_FOCUS ? 1 : 0),\n    };\n    int borderWidth, highlightWidth;\n\n    /*\n     * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the 3\n     * are because the Mac OS Entry widgets leave more space around the Text\n     * than Tk does on X11.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, entryPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, entryPtr->highlightWidthObj, &highlightWidth);\n    if (borderWidth != MAC_OSX_ENTRY_BORDER\n\t    || highlightWidth != MAC_OSX_FOCUS_WIDTH\n\t    || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) {\n\treturn false;\n    }\n\n    /*\n     * For the spinbox, we have to make the entry part smaller by the size of\n     * the buttons. We also leave 2 pixels to the left (as per the HIG) and\n     * space for one pixel to the right, 'cause it makes the buttons look\n     * nicer.\n     */\n\n    if (isSpinbox) {\n\tint incDecWidth;\n\n\t/*\n\t * If native spinbox buttons are going to be drawn, then temporarily\n\t * change the width of the widget so that the same code can be used\n\t * for drawing the Entry portion of the Spinbox as is used to draw\n\t * an ordinary Entry.  The width must be restored before returning.\n\t */\n\n\toldWidth = Tk_Width(tkwin);\n\tif (ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,\n\t\t&incDecWidth) != 0) {\n\t    Tk_Width(tkwin) -= incDecWidth + 1;\n\t}\n    }\n\n   /*\n    * The focus ring is drawn with an Alpha at the outside part of the ring,\n    * so we have to draw over the edges of the ring before drawing the focus\n    * or the text will peep through.\n    */\n\n    bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, d);\n    TkDrawInsetFocusHighlight(entryPtr->tkwin, bgGC, MAC_OSX_FOCUS_WIDTH, d, 0);\n\n    /*\n     * Inset the entry Frame by the maximum width of the focus rect, which is\n     * 3 according to the Carbon docs.\n     */\n\n    bounds.origin.x = macDraw->xOff + MAC_OSX_FOCUS_WIDTH;\n    bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;\n    bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;\n    bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;\n    if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {\n\n\t/*\n\t * No graphics context is available.  If the widget is a Spinbox, we\n\t * must restore its width before returning 0. (Ticket [273b6a4996].)\n\t */\n\n\tif (isSpinbox) {\n\t    Tk_Width(tkwin) = oldWidth;\n\t}\n\treturn false;\n    }\n    ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);\n    TkMacOSXRestoreDrawingContext(&dc);\n    if (isSpinbox) {\n\tTk_Width(tkwin) = oldWidth;\n    }\n    return true;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDrawSpinboxButtons --\n *\n *\tThis procedure redraws the buttons of an spinbox widget. It overrides\n *\tthe generic button drawing code if the spinbox widget parameters are\n *\tsuch that the native widget drawing is a good fit. This version just\n *\treturns 0, so platforms that don't do special native drawing don't\n *\thave to implement it.\n *\n * Results:\n *\t1 if it has drawn the buttons, 0 if not.\n *\n * Side effects:\n *\tMay draw the buttons into pixmap.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkpDrawSpinboxButtons(\n    Spinbox *sbPtr,\n    Drawable d)\n{\n    CGRect bounds;\n    Tk_Window tkwin = sbPtr->entry.tkwin;\n    int height = Tk_Height(tkwin);\n    int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH;\n    int incDecWidth;\n    TkMacOSXDrawingContext dc;\n    XRectangle rects[1];\n    GC bgGC;\n    MacDrawable *macDraw = (MacDrawable *)d;\n    HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.adornment = kThemeAdornmentNone,\n    };\n\n    /*\n     * FIXME: RAISED really makes more sense\n     */\n\n    if (sbPtr->buRelief != TK_RELIEF_FLAT) {\n\treturn 0;\n    }\n\n    /*\n     * The actual sizes of the IncDec button are 21 for the normal, 18 for the\n     * small and 15 for the mini. But the spinbox still looks okay if the\n     * entry is a little bigger than this, so we give it a little slop.\n     */\n\n    info.kind = ComputeIncDecParameters(buttonHeight, &incDecWidth);\n    if (info.kind == (ThemeButtonKind) 0) {\n\treturn 0;\n    }\n\n    if (sbPtr->entry.state == STATE_DISABLED) {\n\tinfo.state = kThemeStateInactive;\n\tinfo.value = kThemeButtonOff;\n    } else if (sbPtr->selElement == SEL_BUTTONUP) {\n\tinfo.state = kThemeStatePressedUp;\n\tinfo.value = kThemeButtonOn;\n    } else if (sbPtr->selElement == SEL_BUTTONDOWN) {\n\tinfo.state = kThemeStatePressedDown;\n\tinfo.value = kThemeButtonOn;\n    } else {\n\tinfo.state = kThemeStateActive;\n\tinfo.value = kThemeButtonOff;\n    }\n\n    bounds.origin.x = macDraw->xOff + Tk_Width(tkwin) - incDecWidth - 1;\n    bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;\n    bounds.size.width = incDecWidth;\n    bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;\n\n    /*\n     * We had to make the entry part of the window smaller so that we wouldn't\n     * overdraw the spin buttons with the focus highlight. So now we have to\n     * draw the highlightbackground.\n     */\n\n    bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);\n    rects[0].x = (short)(Tk_Width(tkwin) - incDecWidth - 1);\n    rects[0].y = 0;\n    rects[0].width = (unsigned short)(incDecWidth + 1);\n    rects[0].height = (unsigned short)Tk_Height(tkwin);\n    XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);\n\n    if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {\n\treturn 0;\n    }\n    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);\n    TkMacOSXRestoreDrawingContext(&dc);\n    return 1;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXEvent.c",
    "content": "/*\n * tkMacOSXEvent.c --\n *\n *\tThis file contains the basic Mac OS X Event handling routines.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXConstants.h\"\n\n#pragma mark TKApplication(TKEvent)\n\nenum {\n    NSWindowWillMoveEventType = 20\n};\n\n@implementation TKApplication(TKEvent)\n/* TODO: replace by +[addLocalMonitorForEventsMatchingMask ? */\n- (NSEvent *) tkProcessEvent: (NSEvent *) theEvent\n{\n#ifdef TK_MAC_DEBUG_EVENTS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), theEvent);\n#endif\n    NSEvent\t    *processedEvent = theEvent;\n    NSEventType\t    type = [theEvent type];\n    NSInteger\t    subtype;\n\n    switch ((NSInteger)type) {\n    case NSAppKitDefined:\n\tsubtype = [theEvent subtype];\n\n\tswitch (subtype) {\n\t    /* Ignored at the moment. */\n\tcase NSApplicationActivatedEventType:\n\t    break;\n\tcase NSApplicationDeactivatedEventType:\n\t    break;\n\tcase NSWindowExposedEventType:\n\t    break;\n\tcase NSScreenChangedEventType:\n\t    break;\n\tcase NSWindowMovedEventType:\n\t    break;\n\tcase NSWindowWillMoveEventType:\n\t    break;\n\n\tdefault:\n\t    break;\n\t}\n\tbreak; /* AppkitEvent. Return theEvent */\n    case NSKeyUp:\n    case NSKeyDown:\n    case NSFlagsChanged:\n\tprocessedEvent = [self tkProcessKeyEvent:theEvent];\n\tbreak; /* Key event.  Return the processed event. */\n    case NSLeftMouseDown:\n    case NSLeftMouseUp:\n    case NSRightMouseDown:\n    case NSRightMouseUp:\n    case NSLeftMouseDragged:\n    case NSRightMouseDragged:\n    case NSMouseMoved:\n    case NSMouseEntered:\n    case NSMouseExited:\n    case NSScrollWheel:\n    case NSOtherMouseDown:\n    case NSOtherMouseUp:\n    case NSOtherMouseDragged:\n    case NSTabletPoint:\n    case NSTabletProximity:\n\tprocessedEvent = [self tkProcessMouseEvent:theEvent];\n\tbreak; /* Mouse event.  Return the processed event. */\n#if 0\n    case NSSystemDefined:\n\tsubtype = [theEvent subtype];\n\tbreak;\n    case NSApplicationDefined: {\n\tid win;\n\twin = [theEvent window];\n\tbreak;\n\t}\n    case NSCursorUpdate:\n\tbreak;\n    case NSEventTypeGesture:\n    case NSEventTypeMagnify:\n    case NSEventTypeRotate:\n    case NSEventTypeSwipe:\n    case NSEventTypeBeginGesture:\n    case NSEventTypeEndGesture:\n\tbreak;\n#endif\n\n    default:\n\tbreak; /* return theEvent */\n    }\n    return processedEvent;\n}\n@end\n#pragma mark -\n\nint\nXSync(\n    Display *display,\n    TCL_UNUSED(Bool))\n{\n    /*\n     *  The main use of XSync is by the update command, which alternates\n     *  between running an event loop to process all events without waiting and\n     *  calling XSync on all displays until no events are left.  On X11 the\n     *  call to XSync might cause the window manager to generate more events\n     *  which would then get processed. Apparently this process stabilizes on\n     *  X11, leaving the window manager in a state where all events have been\n     *  generated and no additional events can be genereated by updating widgets.\n     *\n     *  It is not clear what the Aqua port should do when XSync is called, but\n     *  currently the best option seems to be to do nothing.  (See ticket\n     *  [da5f2266df].)\n     */\n\n    LastKnownRequestProcessed(display)++;\n    return 0;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXFileTypes.c",
    "content": "/*\nThere are situations where a graphical user interface needs to know the file\ntype (i.e. data format) of a file.  The two main ones are when generating an\nicon to represent a file, and when filtering the choice of files in a file\nopen or save dialog.\n\nEarly Macintosh systems used OSTypes as identifiers for file types.  An OSType\nis a FourCC datatype - four bytes which can be packed into a 32 bit integer.  In\nthe HFS filesystem they were included in the file metadata.  The metadata also\nincluded another OSType (the Creator Code) which identified the application\nwhich created the file.\n\nIn OSX 10.4 the Uniform Type Identifier was introduced as an alternative way to\ndescribe file types.  These are strings (NSStrings, actually) in a reverse DNS\nformat, such as \"com.apple.application-bundle\".  Apple provided a tool for\nconverting OSType codes to Uniform Type Identifiers, which they deprecated in\nmacOS 12.0 after introducing the UTType class in macOS 11.0.  An instance of the\nUTType class has properties which give the Uniform Type Identifier as well as\nthe preferred file name extension for a given file type.\n\nThis module provides tools for working with file types which are meant to abstract\nthe many variants that Apple has used over the years, and which can be used\nwithout generating deprecation warnings.\n*/\n\n#include \"tkMacOSXPrivate.h\"\n\n#define CHARS_TO_OSTYPE(string) (OSType) string[0] << 24 | \\\n\t\t\t\t(OSType) string[1] << 16 | \\\n\t\t\t\t(OSType) string[2] <<  8 | \\\n\t\t\t\t(OSType) string[3]\n\nMODULE_SCOPE NSString *TkMacOSXOSTypeToUTI(OSType ostype) {\n    char string[5];\n    string[4] = '\\0';\n    string[3] = ostype;\n    string[2] = ostype >> 8;\n    string[1] = ostype >> 16;\n    string[0] = ostype >> 24;\n    NSString *tag = [NSString stringWithCString:string encoding:NSMacOSRomanStringEncoding];\n    if (tag == nil) {\n\treturn nil;\n    }\n    NSString *result = nil;\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000\n    if (@available(macOS 11.0, *)) {\n\treturn [UTType typeWithTag:tag tagClass:@\"com.apple.ostype\" conformingToType:nil].identifier;\n    }\n#endif\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000\n    result = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, (CFStringRef)tag, NULL);\n#endif\n    return result;\n}\n\n/*\n * The NSWorkspace method iconForFileType, which was deprecated in macOS 12.0, would\n * accept an NSString which could be an encoding of an OSType, or a file extension,\n * or a Uniform Type Idenfier.  This function can serve as a replacement.\n */\nMODULE_SCOPE NSImage *TkMacOSXIconForFileType(NSString *filetype) {\n#if MAC_OS_X_VERSION_MAX_ALLOWED < 110000\n// We don't have UTType but iconForFileType is not deprecated, so use it.\n    return [[NSWorkspace sharedWorkspace] iconForFileType:filetype];\n#else\n// We might have UTType but iconForFileType might be deprecated.\n    if (@available(macOS 11.0, *)) {\n\t/* Yes, we do have UTType */\n\tif (filetype == nil) {\n\t    /*\n\t     * Bug 9be830f61b: match the behavior of\n\t     * [NSWorkspace.sharedWorkspace iconForFileType:nil]\n\t     */\n\t     filetype = @\"public.data\";\n\t}\n\tUTType *uttype = [UTType typeWithIdentifier: filetype];\n\tif (uttype == nil || !uttype.isDeclared) {\n\t    uttype = [UTType typeWithFilenameExtension: filetype];\n\t}\n\tif (uttype == nil || (!uttype.isDeclared && filetype.length == 4)) {\n\t    OSType ostype = CHARS_TO_OSTYPE(filetype.UTF8String);\n\t    NSString *UTI = TkMacOSXOSTypeToUTI(ostype);\n\t    if (UTI) {\n\t\tuttype = [UTType typeWithIdentifier:UTI];\n\t    }\n\t}\n\tif (uttype == nil || !uttype.isDeclared) {\n\t    return nil;\n\t}\n\treturn [[NSWorkspace sharedWorkspace] iconForContentType:uttype];\n    } else {\n\t/* No, we don't have UTType. */\n #if MAC_OS_X_VERSION_MIN_REQUIRED < 110000\n\t/* but iconForFileType is not deprecated, so we can use it. */\n    return [[NSWorkspace sharedWorkspace] iconForFileType:filetype];\n #else\n    /*\n     * Cannot be reached: MIN_REQUIRED >= 110000 yet 11.0 is not available.\n     * But the compiler can't figure that out, so it will warn about an\n     * execution path with no return value unless we put a return here.\n     */\n    return nil;\n #endif\n    }\n#endif\n}\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXFont.c",
    "content": "/*\n * tkMacOSXFont.c --\n *\n *\tContains the Macintosh implementation of the platform-independent font\n *\tpackage interface.\n *\n * Copyright © 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2008-2009 Apple Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXFont.h\"\n#include \"tkMacOSXConstants.h\"\n\n#define fixedPitch kCTFontUserFixedPitchFontType\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_FONTS\n#endif\n*/\n\n/*\n * The following structure represents our Macintosh-specific implementation\n * of a font object.\n */\n\ntypedef struct {\n    TkFont font;\t\t/* Stuff used by generic font package. Must be\n\t\t\t\t * first in structure. */\n    NSFont *nsFont;\n    NSDictionary *nsAttributes;\n} MacFont;\n\n/*\n * The names for our \"native\" fonts.\n */\n\n#define SYSTEMFONT_NAME\t\t\"system\"\n#define APPLFONT_NAME\t\t\"application\"\n#define MENUITEMFONT_NAME\t\"menu\"\n\nstruct SystemFontMapEntry {\n    ThemeFontID id;\n    const char *systemName;\n    const char *tkName;\n    const char *tkName1;\n};\n\n#define ThemeFont(n, ...) { kTheme##n##Font, \"system\" #n \"Font\", ##__VA_ARGS__ }\nstatic const struct SystemFontMapEntry systemFontMap[] = {\n    ThemeFont(System,\t\t\t\"TkDefaultFont\", \"TkIconFont\"),\n    ThemeFont(EmphasizedSystem,\t\t\"TkCaptionFont\", NULL),\n    ThemeFont(SmallSystem,\t\t\"TkHeadingFont\", \"TkTooltipFont\"),\n    ThemeFont(SmallEmphasizedSystem, NULL, NULL),\n    ThemeFont(Application,\t\t\"TkTextFont\", NULL),\n    ThemeFont(Label,\t\t\t\"TkSmallCaptionFont\", NULL),\n    ThemeFont(Views, NULL, NULL),\n    ThemeFont(MenuTitle, NULL, NULL),\n    ThemeFont(MenuItem,\t\t\t\"TkMenuFont\", NULL),\n    ThemeFont(MenuItemMark, NULL, NULL),\n    ThemeFont(MenuItemCmdKey, NULL, NULL),\n    ThemeFont(WindowTitle, NULL, NULL),\n    ThemeFont(PushButton, NULL, NULL),\n    ThemeFont(UtilityWindowTitle, NULL, NULL),\n    ThemeFont(AlertHeader, NULL, NULL),\n    ThemeFont(Toolbar, NULL, NULL),\n    ThemeFont(MiniSystem, NULL, NULL),\n    { kThemeSystemFontDetail,\t\t\"systemDetailSystemFont\", NULL, NULL },\n    { kThemeSystemFontDetailEmphasized,\t\"systemDetailEmphasizedSystemFont\", NULL, NULL },\n    { (ThemeFontID)-1, NULL, NULL, NULL }\n};\n#undef ThemeFont\n\nstatic int antialiasedTextEnabled = -1;\nstatic NSCharacterSet *whitespaceCharacterSet = nil;\nstatic NSCharacterSet *lineendingCharacterSet = nil;\n\nstatic void\t\tGetTkFontAttributesForNSFont(NSFont *nsFont,\n\t\t\t    TkFontAttributes *faPtr);\nstatic NSFont *\t\tFindNSFont(const char *familyName,\n\t\t\t    NSFontTraitMask traits, NSInteger weight,\n\t\t\t    CGFloat size, int fallbackToDefault);\nstatic void\t\tInitFont(NSFont *nsFont,\n\t\t\t    const TkFontAttributes *reqFaPtr,\n\t\t\t    MacFont *fontPtr);\nstatic int\t\tCreateNamedSystemFont(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, const char *name,\n\t\t\t    TkFontAttributes *faPtr);\n\n#pragma mark -\n#pragma mark Font Helpers:\n\n/*\n * To avoid an extra copy, a TKNSString object wraps a Tcl_DString with an\n * NSString that uses the DString's buffer as its character buffer.  It can be\n * constructed from a Tcl_DString and it has a DString property that handles\n * converting from an NSString to a Tcl_DString.\n */\n\n@implementation TKNSString\n\n- (instancetype)initWithTclUtfBytes:(const void *)bytes\n\t\t       length:(NSUInteger)len\n{\n    self = [self init];\n    if (self) {\n\tTcl_DStringInit(&_ds);\n\tTcl_UtfToChar16DString((const char *)bytes, len, &_ds);\n\t_string = [[NSString alloc]\n\t     initWithCharactersNoCopy:(unichar *)Tcl_DStringValue(&_ds)\n\t\t\t       length:Tcl_DStringLength(&_ds)>>1\n\t\t\t freeWhenDone:NO];\n\tself.UTF8String = _string.UTF8String;\n    }\n    return self;\n}\n\n- (instancetype)initWithString:(NSString *)aString\n{\n    self = [self init];\n    if (self) {\n\t_string = [[NSString alloc] initWithString:aString];\n\t_UTF8String = _string.UTF8String;\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    Tcl_DStringFree(&_ds);\n    [_string release];\n    [super dealloc];\n}\n\n- (NSUInteger)length\n{\n    return _string.length;\n}\n\n- (unichar)characterAtIndex:(NSUInteger)index\n{\n    return [_string characterAtIndex:index];\n}\n\n- (Tcl_DString)DString\n{\n    if ( _ds.string == NULL) {\n\n\t/*\n\t * The DString has not been initialized. Construct it from\n\t * our string's unicode characters.\n\t */\n\tchar *p;\n\tNSUInteger index;\n\n\tTcl_DStringInit(&_ds);\n\tTcl_DStringSetLength(&_ds, 3 * [_string length]);\n\tp = Tcl_DStringValue(&_ds);\n\tfor (index = 0; index < [_string length]; index++) {\n\t    p += Tcl_UniCharToUtf([_string characterAtIndex: index]|TCL_COMBINE, p);\n\t}\n\tTcl_DStringSetLength(&_ds, (Tcl_Size)(p - Tcl_DStringValue(&_ds)));\n    }\n    return _ds;\n}\n\n@synthesize UTF8String = _UTF8String;\n@synthesize DString = _ds;\n@end\n\f\n#define GetNSFontTraitsFromTkFontAttributes(faPtr) \\\n\t((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \\\n\t((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask)\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetTkFontAttributesForNSFont --\n *\n *\tFill in TkFontAttributes for given NSFont.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nGetTkFontAttributesForNSFont(\n    NSFont *nsFont,\n    TkFontAttributes *faPtr)\n{\n    NSFontTraitMask traits = [[NSFontManager sharedFontManager]\n\t    traitsOfFont:nsFont];\n    faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);\n#define FACTOR 0.75\n    faPtr->size = [nsFont pointSize] * FACTOR;\n    faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);\n    faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);\n\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * FindNSFont --\n *\n *\tFind NSFont for given attributes. Use default values for missing\n *\tattributes, and do a case-insensitive search for font family names\n *\tif necessary. If fallbackToDefault flag is set, use the system font\n *\tas a last resort.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic NSFont *\nFindNSFont(\n    const char *familyName,\n    NSFontTraitMask traits,\n    NSInteger weight,\n    CGFloat size,\n    int fallbackToDefault)\n{\n    NSFontManager *fm = [NSFontManager sharedFontManager];\n    NSFont *nsFont, *dflt = nil;\n    #define defaultFont (dflt ? dflt : (dflt = [NSFont systemFontOfSize:0]))\n    NSString *family;\n\n    if (familyName) {\n\tfamily = [[[TKNSString alloc] initWithTclUtfBytes:familyName length:TCL_INDEX_NONE] autorelease];\n    } else {\n\tfamily = [defaultFont familyName];\n    }\n    if (size == 0.0) {\n\tsize = [defaultFont pointSize] * FACTOR;\n    }\n    nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];\n\n    /*\n     * A second bug in NSFontManager that Apple created for the Catalina OS\n     * causes requests as above to sometimes return fonts with additional\n     * traits that were not requested, even though fonts without those unwanted\n     * traits exist on the system.  See bug [90d555e088].  As a workaround\n     * we ask the font manager to remove any unrequested traits.\n     */\n\n    if (nsFont) {\n\tnsFont = [fm convertFont:nsFont toNotHaveTrait:~traits];\n    }\n    if (!nsFont) {\n\tNSArray *availableFamilies = [fm availableFontFamilies];\n\tNSString *caseFamily = nil;\n\n\tfor (NSString *f in availableFamilies) {\n\t    if ([family caseInsensitiveCompare:f] == NSOrderedSame) {\n\t\tcaseFamily = f;\n\t\tbreak;\n\t    }\n\t}\n\tif (caseFamily) {\n\t    nsFont = [fm fontWithFamily:caseFamily traits:traits weight:weight\n\t\t    size:size];\n\t}\n    }\n    if (!nsFont) {\n\tnsFont = [NSFont fontWithName:family size:size];\n    }\n    if (!nsFont && fallbackToDefault) {\n\tnsFont = [fm convertFont:defaultFont toFamily:family];\n\tnsFont = [fm convertFont:nsFont toSize:size];\n\tnsFont = [fm convertFont:nsFont toHaveTrait:traits];\n    }\n    [nsFont retain];\n    #undef defaultFont\n    return nsFont;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitFont --\n *\n *\tHelper for TkpGetNativeFont() and TkpGetFontFromAttributes().\n *\n * Results:\n *\tFills the MacFont structure.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitFont(\n    NSFont *nsFont,\n    const TkFontAttributes *reqFaPtr,\t/* Can be NULL */\n    MacFont *fontPtr)\n{\n    TkFontAttributes *faPtr;\n    TkFontMetrics *fmPtr;\n    NSDictionary *nsAttributes;\n    NSRect bounds;\n    CGFloat kern = 0.0;\n    NSFontRenderingMode renderingMode = NSFontDefaultRenderingMode;\n    int ascent, descent/*, dontAA*/;\n    static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7};\n\t\t\t/* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */\n#define nCh\t(sizeof(ch) / sizeof(UniChar))\n    CGGlyph glyphs[nCh];\n    CGRect boundingRects[nCh];\n\n    fontPtr->font.fid = (Font) fontPtr;\n    faPtr = &fontPtr->font.fa;\n    if (reqFaPtr) {\n\t*faPtr = *reqFaPtr;\n    } else {\n\tTkInitFontAttributes(faPtr);\n    }\n    fontPtr->nsFont = nsFont;\n\n    /*\n     * Some don't like antialiasing on fixed-width even if bigger than limit\n     */\n\n    // dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;\n    if (antialiasedTextEnabled >= 0/* || dontAA*/) {\n\trenderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ?\n\t\tNSFontIntegerAdvancementsRenderingMode :\n\t\tNSFontAntialiasedRenderingMode;\n    }\n    nsFont = [nsFont screenFontWithRenderingMode:renderingMode];\n    GetTkFontAttributesForNSFont(nsFont, faPtr);\n    fmPtr = &fontPtr->font.fm;\n    fmPtr->ascent = (int)floor([nsFont ascender] + [nsFont leading] + 0.5);\n    fmPtr->descent = (int)floor(-[nsFont descender] + 0.5);\n    fmPtr->maxWidth = (int)[nsFont maximumAdvancement].width;\n    fmPtr->fixed = [nsFont isFixedPitch];   /* Does not work for all fonts */\n\n    /*\n     * The ascent, descent and fixed fields are not correct for all fonts, as\n     * a workaround deduce that info from the metrics of some typical glyphs,\n     * along with screenfont kerning (space advance difference to printer font)\n     */\n\n    bounds = [nsFont boundingRectForFont];\n    if (CTFontGetGlyphsForCharacters((CTFontRef) nsFont, ch, glyphs, nCh)) {\n\tfmPtr->fixed = [nsFont advancementForGlyph:glyphs[0]].width ==\n\t\t[nsFont advancementForGlyph:glyphs[1]].width;\n\tbounds = NSRectFromCGRect(CTFontGetBoundingRectsForGlyphs((CTFontRef)\n\t\tnsFont, kCTFontOrientationDefault, ch, boundingRects, nCh));\n\tkern = [nsFont advancementForGlyph:glyphs[2]].width -\n\t\t[fontPtr->nsFont advancementForGlyph:glyphs[2]].width;\n    }\n    descent = (int)floor(-bounds.origin.y + 0.5);\n    ascent = (int)floor(bounds.size.height + bounds.origin.y + 0.5);\n    if (ascent > fmPtr->ascent) {\n\tfmPtr->ascent = ascent;\n    }\n    if (descent > fmPtr->descent) {\n\tfmPtr->descent = descent;\n    }\n    nsAttributes = [NSDictionary dictionaryWithObjectsAndKeys:\n\t    nsFont, NSFontAttributeName,\n\t    [NSNumber numberWithInt:faPtr->underline ?\n\t\tNSUnderlineStyleSingle|NSUnderlinePatternSolid :\n\t\tNSUnderlineStyleNone], NSUnderlineStyleAttributeName,\n\t    [NSNumber numberWithInt:faPtr->overstrike ?\n\t\tNSUnderlineStyleSingle|NSUnderlinePatternSolid :\n\t\tNSUnderlineStyleNone], NSStrikethroughStyleAttributeName,\n\t    [NSNumber numberWithInt:fmPtr->fixed ? 0 : 1],\n\t\tNSLigatureAttributeName,\n\t    [NSNumber numberWithDouble:kern], NSKernAttributeName, nil];\n    fontPtr->nsAttributes = [nsAttributes retain];\n#undef nCh\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * CreateNamedSystemFont --\n *\n *\tRegister a system font with the Tk named font mechanism.\n *\n * Results:\n *\n *\tResult from TkCreateNamedFont().\n *\n * Side effects:\n *\n *\tA new named font is added to the Tk font registry.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nCreateNamedSystemFont(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    const char* name,\n    TkFontAttributes *faPtr)\n{\n    TkDeleteNamedFont(NULL, tkwin, name);\n    return TkCreateNamedFont(interp, tkwin, name, faPtr);\n}\n\n#pragma mark -\n\n#pragma mark Grapheme Cluster indexing\n\n/*\n *----------------------------------------------------------------------\n *\n * startOfClusterObjCmd --\n *\n *      This function is invoked to process the startOfCluster command.\n *\n * Results:\n *      A standard Tcl result.\n *\n * Side effects:\n *      None\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nstartOfClusterObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,         /* Current interpreter. */\n    Tcl_Size objc,              /* Number of arguments. */\n    Tcl_Obj *const objv[])      /* Argument objects. */\n{\n    TKNSString *S;\n    const char *stringArg;\n    Tcl_Size len, idx;\n    if ((size_t)(objc - 3) > 1) {\n\tTcl_WrongNumArgs(interp, 1 , objv, \"str start ?locale?\");\n\treturn TCL_ERROR;\n    }\n    stringArg = Tcl_GetStringFromObj(objv[1], &len);\n    if (stringArg == NULL) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Size ulen = Tcl_GetCharLength(objv[1]);\n    S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len];\n    len = [S length];\n    if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad index \\\"%s\\\": must be integer?[+-]integer?, end?[+-]integer?, or \\\"\\\"\",\n\t\tTcl_GetString(objv[2])));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INDEX\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (idx >= ulen) {\n\tidx = len;\n    } else if (idx > 0 && len != ulen) {\n\t/* The string contains codepoints > \\uFFFF. Determine UTF-16 index */\n\tTcl_Size newIdx = 0;\n\tfor (Tcl_Size i = 0; i < idx; i++) {\n\t    newIdx += 1 + (((newIdx < len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00));\n\t}\n\tidx = newIdx;\n    }\n    if (idx >= 0) {\n\tif (idx >= len) {\n\t    idx = len;\n\t} else {\n\t    NSRange range = [S rangeOfComposedCharacterSequenceAtIndex:idx];\n\t    idx = range.location;\n\t}\n\tif (idx > 0 && len != ulen) {\n\t    /* The string contains codepoints > \\uFFFF. Determine UTF-32 index */\n\t    Tcl_Size newIdx = 1;\n\t    for (Tcl_Size i = 1; i < idx; i++) {\n\t\tif ((([S characterAtIndex:i-1]&0xFC00) != 0xD800) || (([S characterAtIndex:i]&0xFC00) != 0xDC00)) newIdx++;\n\t    }\n\t    idx = newIdx;\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(idx));\n    }\n    return TCL_OK;\n}\n\nstatic int\nendOfClusterObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,         /* Current interpreter. */\n    Tcl_Size objc,              /* Number of arguments. */\n    Tcl_Obj *const objv[])      /* Argument objects. */\n{\n    TKNSString *S;\n    char *stringArg;\n    Tcl_Size idx, len;\n\n    if ((size_t)(objc - 3) > 1) {\n\tTcl_WrongNumArgs(interp, 1 , objv, \"str start ?locale?\");\n\treturn TCL_ERROR;\n    }\n    stringArg = Tcl_GetStringFromObj(objv[1], &len);\n    if (stringArg == NULL) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Size ulen = Tcl_GetCharLength(objv[1]);\n    S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len];\n    len = [S length];\n    if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad index \\\"%s\\\": must be integer?[+-]integer?, end?[+-]integer?, or \\\"\\\"\",\n\t\tTcl_GetString(objv[2])));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"INDEX\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (idx >= ulen) {\n\tidx = len;\n    } else if (idx > 0 && len != ulen) {\n\t/* The string contains codepoints > \\uFFFF. Determine UTF-16 index */\n\tTcl_Size newIdx = 0;\n\tfor (Tcl_Size i = 0; i < idx; i++) {\n\t    newIdx += 1 + (((newIdx < len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00));\n\t}\n\tidx = newIdx;\n    }\n    if (idx + 1 <= len) {\n\tif (idx < 0) {\n\t    idx = 0;\n\t} else {\n\t    NSRange range = [S rangeOfComposedCharacterSequenceAtIndex:idx];\n\t    idx = range.location + range.length;\n\t    if (idx > 0 && len != ulen) {\n\t\t/* The string contains codepoints > \\uFFFF. Determine UTF-32 index */\n\t\tTcl_Size newIdx = 1;\n\t\tfor (Tcl_Size i = 1; i < idx; i++) {\n\t\tif ((([S characterAtIndex:i-1]&0xFC00) != 0xD800) || (([S characterAtIndex:i]&0xFC00) != 0xDC00)) newIdx++;\n\t\t}\n\t\tidx = newIdx;\n\t    }\n\t}\n\tTcl_SetObjResult(interp, TkNewIndexObj(idx));\n    }\n    return TCL_OK;\n}\n\n#pragma mark -\n#pragma mark Font handling:\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpFontPkgInit --\n *\n *\tThis procedure is called when an application is created. It\n *\tinitializes all the structures that are used by the\n *\tplatform-dependent code on a per application basis.\n *\tNote that this is called before TkpInit() !\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInitialize named system fonts.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpFontPkgInit(\n    TkMainInfo *mainPtr)\t/* The application being created. */\n{\n    Tcl_Interp *interp = mainPtr->interp;\n    Tk_Window tkwin = (Tk_Window)mainPtr->winPtr;\n    const struct SystemFontMapEntry *systemFont = systemFontMap;\n    NSFont *nsFont;\n    TkFontAttributes fa;\n    NSMutableCharacterSet *cs;\n    /*\n     * Since we called before TkpInit, we need our own autorelease pool.\n     */\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n\n    /*\n     * Force this for now.\n     */\n    if (!mainPtr->winPtr->mainPtr) {\n\tmainPtr->winPtr->mainPtr = mainPtr;\n    }\n    while (systemFont->systemName) {\n\tnsFont = (NSFont*) CTFontCreateUIFontForLanguage(\n\t\tHIThemeGetUIFontType(systemFont->id), 0, NULL);\n\tif (nsFont) {\n\t    TkInitFontAttributes(&fa);\n\t    GetTkFontAttributesForNSFont(nsFont, &fa);\n\t    CreateNamedSystemFont(interp, tkwin, systemFont->systemName, &fa);\n\t    if (systemFont->tkName) {\n\t\tCreateNamedSystemFont(interp, tkwin, systemFont->tkName, &fa);\n\t    }\n\t    if (systemFont->tkName1) {\n\t\tCreateNamedSystemFont(interp, tkwin, systemFont->tkName1, &fa);\n\t    }\n\t    CFRelease(nsFont);\n\t}\n\tsystemFont++;\n    }\n    TkInitFontAttributes(&fa);\n#if 0\n\n    /*\n     * In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused\n     * it to not recognize the familyName \".SF NSMono\" which is the familyName\n     * of the default fixed pitch system fault on that system.  See bug [855049e799].\n     * As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead.\n     * This returns a user font in the \"Menlo\" family.\n     */\n\n    nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);\n#else\n    nsFont = [NSFont userFixedPitchFontOfSize:11];\n#endif\n    if (nsFont) {\n\tGetTkFontAttributesForNSFont(nsFont, &fa);\n#if 0\n\tCFRelease(nsFont);\n#endif\n    } else {\n\tfa.family = Tk_GetUid(\"Monaco\");\n\tfa.size = 11;\n\tfa.weight = TK_FW_NORMAL;\n\tfa.slant = TK_FS_ROMAN;\n    }\n    CreateNamedSystemFont(interp, tkwin, \"TkFixedFont\", &fa);\n    if (!whitespaceCharacterSet) {\n\twhitespaceCharacterSet = [[NSCharacterSet\n\t\twhitespaceAndNewlineCharacterSet] retain];\n\tcs = [whitespaceCharacterSet mutableCopy];\n\t[cs removeCharactersInString:@\" \"];\n\tlineendingCharacterSet = [cs copy];\n\t[cs release];\n    }\n    [pool drain];\n    Tcl_CreateObjCommand2(interp, \"::tk::startOfCluster\", startOfClusterObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::endOfCluster\", endOfClusterObjCmd, NULL, NULL);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetNativeFont --\n *\n *\tMap a platform-specific native font name to a TkFont.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the native\n *\tfont. If a native font by the given name could not be found, the return\n *\tvalue is NULL.\n *\n *\tEvery call to this procedure returns a new TkFont structure, even if\n *\tthe name has already been seen before. The caller should call\n *\tTkpDeleteFont() when the font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generics TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetNativeFont(\n    TCL_UNUSED(Tk_Window),\t\t/* For display where font will be used. */\n    const char *name)\t\t/* Platform-specific font name. */\n{\n    MacFont *fontPtr = NULL;\n    ThemeFontID themeFontId;\n    CTFontRef ctFont;\n\n    if (strcmp(name, SYSTEMFONT_NAME) == 0) {\n\tthemeFontId = kThemeSystemFont;\n    } else if (strcmp(name, APPLFONT_NAME) == 0) {\n\tthemeFontId = kThemeApplicationFont;\n    } else if (strcmp(name, MENUITEMFONT_NAME) == 0) {\n\tthemeFontId = kThemeMenuItemFont;\n    } else {\n\treturn NULL;\n    }\n    ctFont = CTFontCreateUIFontForLanguage(\n\t    HIThemeGetUIFontType(themeFontId), 0, NULL);\n    if (ctFont) {\n\tfontPtr = (MacFont *)Tcl_Alloc(sizeof(MacFont));\n\tInitFont((NSFont*) ctFont, NULL, fontPtr);\n    }\n\n    return (TkFont *) fontPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFromAttributes --\n *\n *\tGiven a desired set of attributes for a font, find a font with the\n *\tclosest matching attributes.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the font with\n *\tthe desired attributes. If a font with the desired attributes could not\n *\tbe constructed, some other font will be substituted automatically.\n *\n *\tEvery call to this procedure returns a new TkFont structure, even if\n *\tthe specified attributes have already been seen before. The caller\n *\tshould call TkpDeleteFont() to free the platform- specific data when\n *\tthe font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generic TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetFontFromAttributes(\n    TkFont *tkFontPtr,\t\t/* If non-NULL, store the information in this\n\t\t\t\t * existing TkFont structure, rather than\n\t\t\t\t * allocating a new structure to hold the font;\n\t\t\t\t * the existing contents of the font will be\n\t\t\t\t * released. If NULL, a new TkFont structure is\n\t\t\t\t * allocated. */\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const TkFontAttributes *faPtr)\n\t\t\t\t/* Set of attributes to match. */\n{\n    MacFont *fontPtr;\n    CGFloat points = floor(TkFontGetPoints(tkwin, faPtr->size / FACTOR) + 0.5);\n    NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr);\n    NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5);\n    NSFont *nsFont;\n\n    nsFont = FindNSFont(faPtr->family, traits, weight, points, 0);\n    if (!nsFont) {\n\tconst char *const *aliases = TkFontGetAliasList(faPtr->family);\n\n\twhile (aliases && !nsFont) {\n\t    nsFont = FindNSFont(*aliases++, traits, weight, points, 0);\n\t}\n    }\n    if (!nsFont) {\n\tnsFont = FindNSFont(faPtr->family, traits, weight, points, 1);\n    }\n    if (!nsFont) {\n\tTcl_Panic(\"Could not determine NSFont from TkFontAttributes\");\n    }\n    if (tkFontPtr == NULL) {\n\tfontPtr = (MacFont *)Tcl_Alloc(sizeof(MacFont));\n    } else {\n\tfontPtr = (MacFont *)tkFontPtr;\n\tTkpDeleteFont(tkFontPtr);\n    }\n    CFRetain(nsFont); /* Always needed to allow unconditional CFRelease below */\n    InitFont(nsFont, faPtr, fontPtr);\n\n    return (TkFont *) fontPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpDeleteFont --\n *\n *\tCalled to release a font allocated by TkpGetNativeFont() or\n *\tTkpGetFontFromAttributes(). The caller should have already released the\n *\tfields of the TkFont that are used exclusively by the generic TkFont\n *\tcode.\n *\n * Results:\n *\tTkFont is deallocated.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpDeleteFont(\n    TkFont *tkFontPtr)\t\t/* Token of font to be deleted. */\n{\n    MacFont *fontPtr = (MacFont *) tkFontPtr;\n\n    [fontPtr->nsAttributes release];\n    fontPtr->nsAttributes = NULL;\n    CFRelease(fontPtr->nsFont); /* Either a CTFontRef or a CFRetained NSFont */\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFamilies --\n *\n *\tReturn information about the font families that are available on the\n *\tdisplay of the given window.\n *\n * Results:\n *\tModifies interp's result object to hold a list of all the available\n *\tfont families.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontFamilies(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    TCL_UNUSED(Tk_Window))\t\t/* For display to query. */\n{\n    Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);\n    NSArray *list = [[NSFontManager sharedFontManager] availableFontFamilies];\n\n    for (NSString *family in list) {\n\tTcl_ListObjAppendElement(NULL, resultPtr,\n\t\tTcl_NewStringObj([family UTF8String], TCL_INDEX_NONE));\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpGetSubFonts --\n *\n *\tA function used by the testing package for querying the actual screen\n *\tfonts that make up a font object.\n *\n * Results:\n *\tModifies interp's result object to hold a list containing the names of\n *\tthe screen fonts that make up the given font object.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpGetSubFonts(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Font tkfont)\t\t/* Font object to query. */\n{\n    MacFont *fontPtr = (MacFont *) tkfont;\n    Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);\n\n    if (fontPtr->nsFont) {\n\tNSArray *list = [[fontPtr->nsFont fontDescriptor]\n\t\tobjectForKey:NSFontCascadeListAttribute];\n\n\tfor (NSFontDescriptor *subFontDesc in list) {\n\t    NSString *family = [subFontDesc objectForKey:NSFontFamilyAttribute];\n\n\t    if (family) {\n\t\tTcl_ListObjAppendElement(NULL, resultPtr,\n\t\t\tTcl_NewStringObj([family UTF8String], TCL_INDEX_NONE));\n\t    }\n\t}\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetFontAttrsForChar --\n *\n *\tRetrieve the font attributes of the actual font used to render a given\n *\tcharacter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe font attributes are stored in *faPtr.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontAttrsForChar(\n    TCL_UNUSED(Tk_Window),\t\t/* Window on the font's display */\n    Tk_Font tkfont,\t\t/* Font to query */\n    int c,\t\t\t/* Character of interest */\n    TkFontAttributes* faPtr)\t/* Output: Font attributes */\n{\n    MacFont *fontPtr = (MacFont *) tkfont;\n    NSFont *nsFont = fontPtr->nsFont;\n    *faPtr = fontPtr->font.fa;\n    if (nsFont && ![[nsFont coveredCharacterSet] characterIsMember:c]) {\n\tUTF16Char ch = (UTF16Char) c;\n\n\tnsFont = [nsFont bestMatchingFontForCharacters:&ch\n\t\tlength:1 attributes:nil actualCoveredLength:NULL];\n\tif (nsFont) {\n\t    GetTkFontAttributesForNSFont(nsFont, faPtr);\n\t}\n    }\n}\n\n#pragma mark -\n#pragma mark Measuring and drawing:\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureChars --\n *\n *\tDetermine the number of characters from the string that will fit in\n *\tthe given horizontal span. The measurement is done under the\n *\tassumption that Tk_DrawChars() will be used to actually display the\n *\tcharacters.\n *\n *\tWith ATSUI we need the line context to do this right, so we have the\n *\tactual implementation in Tk_MeasureCharsInContext().\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n * Todo:\n *\tEffects of the \"flags\" parameter are untested.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureChars(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    Tcl_Size numBytes,\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length; don't consider any\n\t\t\t\t * character that would cross this x-position.\n\t\t\t\t * If < 0, then line length is unbounded and\n\t\t\t\t * the flags argument is ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fit on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character even if\n\t\t\t\t * no characters fit. */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    return Tk_MeasureCharsInContext(tkfont, source, numBytes, 0, numBytes,\n\t    maxLength, flags, lengthPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureCharsInContext --\n *\n *\tDetermine the number of bytes from the string that will fit in the\n *\tgiven horizontal span. The measurement is done under the assumption\n *\tthat Tk_DrawCharsInContext() will be used to actually display the\n *\tcharacters.\n *\n *\tThis one is almost the same as Tk_MeasureChars(), but with access to\n *\tall the characters on the line for context.\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureCharsInContext(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    Tcl_Size numBytes,\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string in all. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to measure. */\n    Tcl_Size rangeLength,\t\t/* Length of range to measure in bytes. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length; don't consider any\n\t\t\t\t * character that would cross this x-position.\n\t\t\t\t * If < 0, then line length is unbounded and\n\t\t\t\t * the flags argument is ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fits on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE means\n\t\t\t\t * return at least one character even if no\n\t\t\t\t * characters fit.  If TK_WHOLE_WORDS and\n\t\t\t\t * TK_AT_LEAST_ONE are set and the first word\n\t\t\t\t * doesn't fit, we return at least one\n\t\t\t\t * character or whatever characters fit into\n\t\t\t\t * maxLength.  TK_ISOLATE_END means that the\n\t\t\t\t * last character should not be considered in\n\t\t\t\t * context with the rest of the string (used\n\t\t\t\t * for breaking lines). */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    const MacFont *fontPtr = (const MacFont *) tkfont;\n    NSString *string;\n    NSAttributedString *attributedString;\n    CTTypesetterRef typesetter;\n    CFIndex start, len;\n    CFRange range = {0, 0};\n    CTLineRef line;\n    CGFloat offset = 0;\n    CFIndex index;\n    double width;\n    int length, fit;\n\n    if (rangeStart < 0 || rangeLength <= 0 ||\n\t    rangeStart + rangeLength > numBytes ||\n\t    (maxLength == 0 && !(flags & TK_AT_LEAST_ONE))) {\n\t*lengthPtr = 0;\n\treturn 0;\n    }\n    if (maxLength > 32767) {\n\tmaxLength = 32767;\n    }\n    string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];\n    if (!string) {\n\tlength = 0;\n\tfit = rangeLength;\n\tgoto done;\n    }\n    attributedString = [[NSAttributedString alloc] initWithString:string\n\t    attributes:fontPtr->nsAttributes];\n    typesetter = CTTypesetterCreateWithAttributedString(\n\t    (CFAttributedStringRef)attributedString);\n    start = TclNumUtfChars(source, rangeStart);\n    len = TclNumUtfChars(source + rangeStart, rangeLength);\n    if (start > 0) {\n\trange.length = start;\n\tline = CTTypesetterCreateLine(typesetter, range);\n\toffset = CTLineGetTypographicBounds(line, NULL, NULL, NULL);\n\tCFRelease(line);\n    }\n    if (maxLength < 0) {\n\tindex = len;\n\trange.length = len;\n\tline = CTTypesetterCreateLine(typesetter, range);\n\twidth = CTLineGetTypographicBounds(line, NULL, NULL, NULL);\n\tCFRelease(line);\n    } else {\n\tdouble maxWidth = maxLength + offset;\n\tNSCharacterSet *cs;\n\n\t/*\n\t * Get a line breakpoint in the source string.\n\t */\n\n\tindex = start;\n\tif (flags & TK_WHOLE_WORDS) {\n\t    index = CTTypesetterSuggestLineBreak(typesetter, start, maxWidth);\n\t    if (index <= start && (flags & TK_AT_LEAST_ONE)) {\n\t\tflags &= ~TK_WHOLE_WORDS;\n\t    }\n\t}\n\tif (index <= start && !(flags & TK_WHOLE_WORDS)) {\n\t    index = CTTypesetterSuggestClusterBreak(typesetter, start, maxWidth);\n\t}\n\n\t/*\n\t * Trim right whitespace/lineending characters.\n\t */\n\n\tcs = (index <= len && (flags & TK_WHOLE_WORDS)) ?\n\t\twhitespaceCharacterSet : lineendingCharacterSet;\n\twhile (index > start &&\n\t\t[cs characterIsMember:[string characterAtIndex:(index - 1)]]) {\n\t    index--;\n\t}\n\n\t/*\n\t * If there is no line breakpoint in the source string between its\n\t * start and the index position that fits in maxWidth, then\n\t * CTTypesetterSuggestLineBreak() returns that very last index.\n\t * However if the TK_WHOLE_WORDS flag is set, we want to break at a\n\t * word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we\n\t * must report that zero chars actually fit (in other words the\n\t * smallest word of the source string is still larger than maxWidth).\n\t */\n\n\tif ((index >= start) && (index < len) &&\n\t\t(flags & TK_WHOLE_WORDS) && !(flags & TK_AT_LEAST_ONE) &&\n\t\t![cs characterIsMember:[string characterAtIndex:index]]) {\n\t    index = start;\n\t}\n\n\tif (index <= start && (flags & TK_AT_LEAST_ONE)) {\n\t    index = start + 1;\n\t}\n\n\t/*\n\t * Now measure the string width in pixels.\n\t */\n\n\tif (index > 0) {\n\t    range.length = index;\n\t    line = CTTypesetterCreateLine(typesetter, range);\n\t    width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);\n\t    CFRelease(line);\n\t} else {\n\t    width = 0;\n\t}\n\tif (width < maxWidth && (flags & TK_PARTIAL_OK) && index < len) {\n\t    range.length = ++index;\n\t    line = CTTypesetterCreateLine(typesetter, range);\n\t    width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);\n\t    CFRelease(line);\n\t}\n\n\t/*\n\t * The call to CTTypesetterSuggestClusterBreak above will always return\n\t * at least one character regardless of whether it exceeded it or not.\n\t * Clean that up now.\n\t */\n\n\twhile (width > maxWidth && !(flags & TK_PARTIAL_OK)\n\t\t&& index > start+(flags & TK_AT_LEAST_ONE)) {\n\t    range.length = --index;\n\t    line = CTTypesetterCreateLine(typesetter, range);\n\t    width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);\n\t    CFRelease(line);\n\t}\n\n    }\n    CFRelease(typesetter);\n    [attributedString release];\n    [string release];\n    length = ceil(width - offset);\n    fit = (TclUtfAtIndex(source, index) - source) - rangeStart;\ndone:\n#ifdef TK_MAC_DEBUG_FONTS\n    TkMacOSXDbgMsg(\"measure: source=\\\"%s\\\" range=\\\"%.*s\\\" maxLength=%d \"\n\t    \"flags='%s%s%s%s' -> width=%d bytesFit=%d\\n\", source, rangeLength,\n\t    source+rangeStart, maxLength,\n\t    flags & TK_PARTIAL_OK   ? \"partialOk \"  : \"\",\n\t    flags & TK_WHOLE_WORDS  ? \"wholeWords \" : \"\",\n\t    flags & TK_AT_LEAST_ONE ? \"atLeastOne \" : \"\",\n\t    flags & TK_ISOLATE_END  ? \"isolateEnd \" : \"\",\n\t    length, fit);\n#endif\n    *lengthPtr = length;\n    return fit;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawChars --\n *\n *\tDraw a string of characters on the screen.\n *\n *\tWith ATSUI we need the line context to do this right, so we have the\n *\tactual implementation in TkpDrawAngledCharsInContext().\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int x, int y)\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * string when drawing. */\n{\n    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,\n\t    0, numBytes, x, y, 0.0);\n}\n\f\nvoid\nTkDrawAngledChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    double x, double y,\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,\n\t    0, numBytes, x, y, angle);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawCharsInContext --\n *\n *\tDraw a string of characters on the screen like Tk_DrawChars(), with\n *\taccess to all the characters on the line for context.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n * Todo:\n *\tStippled text drawing.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    int x, int y)\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n{\n    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,\n\t    rangeStart, rangeLength, x, y, 0.0);\n}\n\f\nvoid\nTkpDrawAngledCharsInContext(\n    TCL_UNUSED(Display *),\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    double x, double y,\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    const MacFont *fontPtr = (const MacFont *) tkfont;\n    NSString *string;\n    NSMutableDictionary *attributes;\n    NSAttributedString *attributedString;\n    CTTypesetterRef typesetter;\n    CFIndex start, length;\n    CTLineRef line, full=nil;\n    MacDrawable *macWin = (MacDrawable *)drawable;\n    TkMacOSXDrawingContext drawingContext;\n    CGContextRef context;\n    CGColorRef fg = NULL;\n    NSFont *nsFont;\n    CGAffineTransform t;\n    CGFloat width, height, textX = (CGFloat) x, textY = (CGFloat) y;\n\n    if (rangeStart < 0 || rangeLength <= 0\n\t    || rangeStart + rangeLength > numBytes\n\t    || !TkMacOSXSetupDrawingContext(drawable, gc, &drawingContext)) {\n\treturn;\n    }\n    string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];\n    if (!string) {\n\treturn;\n    }\n\n    context = drawingContext.context;\n    TkSetMacColor2(gc->foreground, &fg, TkMacOSXInDarkMode((Tk_Window)macWin->winPtr));\n    attributes = [fontPtr->nsAttributes mutableCopy];\n    if (fg) {\n\t[attributes setObject:(id)fg forKey:(id)kCTForegroundColorAttributeName];\n\tCGColorRelease(fg);\n    }\n    nsFont = [attributes objectForKey:NSFontAttributeName];\n    [nsFont setInContext:GET_NSCONTEXT(context, NO)];\n    CGContextSetTextMatrix(context, CGAffineTransformIdentity);\n    attributedString = [[NSAttributedString alloc] initWithString:string\n\t    attributes:attributes];\n    [string release];\n    typesetter = CTTypesetterCreateWithAttributedString(\n\t    (CFAttributedStringRef)attributedString);\n    textX += (CGFloat) macWin->xOff;\n    textY += (CGFloat) macWin->yOff;\n    height = [drawingContext.view bounds].size.height;\n    textY = height - textY;\n    t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height);\n    if (angle != 0.0) {\n\tt = CGAffineTransformTranslate(\n\t     CGAffineTransformRotate(\n\t\t CGAffineTransformTranslate(t, textX, textY), angle*PI/180.0),\n\t     -textX, -textY);\n    }\n    CGContextConcatCTM(context, t);\n    start = TclNumUtfChars(source, rangeStart);\n    length = TclNumUtfChars(source, rangeStart + rangeLength) - start;\n    line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, length));\n    if (start > 0) {\n\n\t/*\n\t * We are only drawing part of the string.  To compute the x coordinate\n\t * of the part we are drawing we subtract its typographical length from\n\t * the typographical length of the full string.  This accounts for the\n\t * kerning after the initial part of the string.\n\t */\n\n\tfull = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start + length));\n\twidth = CTLineGetTypographicBounds(full, NULL, NULL, NULL);\n\tCFRelease(full);\n\ttextX += (width - CTLineGetTypographicBounds(line, NULL, NULL, NULL));\n    }\n    CGContextSetTextPosition(context, textX, textY);\n    CTLineDraw(line, context);\n    CFRelease(line);\n    CFRelease(typesetter);\n    [attributedString release];\n    [attributes release];\n    TkMacOSXRestoreDrawingContext(&drawingContext);\n}\n\n#pragma mark -\n#pragma mark Accessors:\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkMacOSXNSFontForFont --\n *\n *\tReturn an NSFont for the given Tk_Font.\n *\n * Results:\n *\tNSFont*.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nMODULE_SCOPE NSFont*\nTkMacOSXNSFontForFont(\n    Tk_Font tkfont)\n{\n    return tkfont ? ((MacFont *)tkfont)->nsFont : nil;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkMacOSXNSFontAttributesForFont --\n *\n *\tReturn an NSDictionary of font attributes for the given Tk_Font.\n *\n * Results:\n *\tNSFont*.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nMODULE_SCOPE NSDictionary*\nTkMacOSXNSFontAttributesForFont(\n    Tk_Font tkfont)\n{\n    return tkfont ? ((MacFont *)tkfont)->nsAttributes : nil;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXFontDescriptionForNSFontAndNSFontAttributes --\n *\n *\tGet text description of a font specified by NSFont and attributes.\n *\n * Results:\n *\tList object or NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE Tcl_Obj *\nTkMacOSXFontDescriptionForNSFontAndNSFontAttributes(\n    NSFont *nsFont,\n    NSDictionary *nsAttributes)\n{\n    Tcl_Obj *objv[6];\n    int i = 0;\n    const char *familyName = [[nsFont familyName] UTF8String];\n\n    if (nsFont && familyName) {\n\tNSFontTraitMask traits = [[NSFontManager sharedFontManager]\n\t\ttraitsOfFont:nsFont];\n\tid underline = [nsAttributes objectForKey:\n\t\tNSUnderlineStyleAttributeName];\n\tid strikethrough = [nsAttributes objectForKey:\n\t\tNSStrikethroughStyleAttributeName];\n\n\tobjv[i++] = Tcl_NewStringObj(familyName, TCL_INDEX_NONE);\n\tobjv[i++] = Tcl_NewWideIntObj((Tcl_WideInt)floor([nsFont pointSize] * FACTOR + 0.5));\n#define S(s)    Tcl_NewStringObj(STRINGIFY(s), (sizeof(STRINGIFY(s))-1))\n\tobjv[i++] = (traits & NSBoldFontMask)\t? S(bold)   : S(normal);\n\tobjv[i++] = (traits & NSItalicFontMask)\t? S(italic) : S(roman);\n\tif ([underline respondsToSelector:@selector(intValue)] &&\n\t\t([underline intValue] & (NSUnderlineStyleSingle |\n\t\tNSUnderlineStyleThick | NSUnderlineStyleDouble))) {\n\t    objv[i++] = S(underline);\n\t}\n\tif ([strikethrough respondsToSelector:@selector(intValue)] &&\n\t\t([strikethrough intValue] & (NSUnderlineStyleSingle |\n\t\tNSUnderlineStyleThick | NSUnderlineStyleDouble))) {\n\t    objv[i++] = S(overstrike);\n\t}\n#undef S\n    }\n    return i ? Tcl_NewListObj(i, objv) : NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXUseAntialiasedText --\n *\n *\tEnables or disables application-wide use of antialiased text (where\n *\tavailable). Sets up a linked Tcl global variable to allow disabling of\n *\tantialiased text from Tcl.\n *\n *\tThe possible values for this variable are:\n *\n *\t-1 - Use system default as configurable in \"System Prefs\" -> \"General\".\n *\t 0 - Unconditionally disable antialiasing.\n *\t 1 - Unconditionally enable antialiasing.\n *\n * Results:\n *\n *\tTCL_OK.\n *\n * Side effects:\n *\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE int\nTkMacOSXUseAntialiasedText(\n    Tcl_Interp * interp,\t/* The Tcl interpreter to receive the\n\t\t\t\t * variable.*/\n    int enable)\t\t\t/* Initial value. */\n{\n    static bool initialized = false;\n\n    if (!initialized) {\n\tinitialized = true;\n\n\tif (Tcl_CreateNamespace(interp, \"::tk::mac\", NULL, NULL) == NULL) {\n\t    Tcl_ResetResult(interp);\n\t}\n\tif (Tcl_LinkVar(interp, \"::tk::mac::antialiasedtext\",\n\t\t&antialiasedTextEnabled,\n\t\tTCL_LINK_INT) != TCL_OK) {\n\t    Tcl_ResetResult(interp);\n\t}\n    }\n    antialiasedTextEnabled = enable;\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXFont.h",
    "content": "/*\n * tkMacOSXFont.h --\n *\n *\tContains the Macintosh implementation of the platform-independent\n *\tfont package interface.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef TKMACOSXFONT_H\n#define TKMACOSXFONT_H 1\n\n#include \"tkFont.h\"\n\n#ifndef _TKMACINT\n#include \"tkMacOSXInt.h\"\n#endif\n\n/*\n * Function prototypes\n */\n\nMODULE_SCOPE Tcl_Obj * TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(\n\tNSFont *nsFont, NSDictionary *nsAttributes);\n\n#endif /*TKMACOSXFONT_H*/\n"
  },
  {
    "path": "macosx/tkMacOSXHLEvents.c",
    "content": "/*\n * tkMacOSXHLEvents.c --\n *\n *\tImplements high level event support for the Macintosh.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2015-2019 Marc Culler\n * Copyright © 2019 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include <sys/param.h>\n#define URL_MAX_LENGTH (17 + MAXPATHLEN)\n\n/*\n * This is a Tcl_Event structure that the Quit AppleEvent handler uses to\n * schedule the ReallyKillMe function.\n */\n\ntypedef struct KillEvent {\n    Tcl_Event header;\t\t/* Information that is standard for all\n\t\t\t\t * events. */\n    Tcl_Interp *interp;\t\t/* Interp that was passed to the Quit\n\t\t\t\t * AppleEvent */\n} KillEvent;\n\n/*\n * When processing an AppleEvent as an idle task, a pointer to one\n * of these structs is passed as the clientData.\n */\n\ntypedef struct AppleEventInfo {\n    Tcl_Interp *interp;\n    const char *procedure;\n    Tcl_DString command;\n    NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */\n    int retryCount;\n} AppleEventInfo;\n\n/*\n * Static functions used only in this file.\n */\n\nstatic int  MissedAnyParameters(const AppleEvent *theEvent);\nstatic int  ReallyKillMe(Tcl_Event *eventPtr, int flags);\nstatic void ProcessAppleEvent(void *clientData);\n\n/*\n * Names of the procedures which can be used to process AppleEvents.\n */\n\nstatic const char openDocumentProc[] = \"::tk::mac::OpenDocument\";\nstatic const char launchURLProc[] = \"::tk::mac::LaunchURL\";\nstatic const char printDocProc[] = \"::tk::mac::PrintDocument\";\nstatic const char scriptFileProc[] = \"::tk::mac::DoScriptFile\";\nstatic const char scriptTextProc[] = \"::tk::mac::DoScriptText\";\nstatic const char getSdefProc[] = \"::tk::mac::GetDynamicSdef\";\n\n#pragma mark TKApplication(TKHLEvents)\n\n@implementation TKApplication(TKHLEvents)\n- (void) terminate: (id) sender\n{\n    (void)sender;\n    [self handleQuitApplicationEvent:Nil withReplyEvent:Nil];\n}\n\n- (void) superTerminate: (id) sender\n{\n    (void) sender;\n    [super terminate:nil];\n}\n\n- (void) preferences: (id) sender\n{\n    (void)sender;\n    [self handleShowPreferencesEvent:Nil withReplyEvent:Nil];\n}\n\n- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event\n    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    KillEvent *eventPtr;\n    (void)event;\n    (void)replyEvent;\n\n    if (_eventInterp) {\n\t/*\n\t * Call the exit command from the event loop, since you are not\n\t * supposed to call ExitToShell in an Apple Event Handler. We put this\n\t * at the head of Tcl's event queue because this message usually comes\n\t * when the Mac is shutting down, and we want to kill the shell as\n\t * quickly as possible.\n\t */\n\n\teventPtr = (KillEvent *)Tcl_Alloc(sizeof(KillEvent));\n\teventPtr->header.proc = ReallyKillMe;\n\teventPtr->interp = _eventInterp;\n\n\tTcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);\n    }\n}\n\n- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event\n    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    (void)event;\n    (void)replyEvent;\n\n    if (_eventInterp &&\n\tTcl_FindCommand(_eventInterp, \"::tk::mac::OpenApplication\", NULL, 0)){\n\tint code = Tcl_EvalEx(_eventInterp, \"::tk::mac::OpenApplication\",\n\t\t\t      TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n    }\n}\n\n- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event\n    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    (void)event;\n    (void)replyEvent;\n\n    [NSApp activateIgnoringOtherApps: YES];\n    if (_eventInterp && Tcl_FindCommand(_eventInterp,\n\t    \"::tk::mac::ReopenApplication\", NULL, 0)) {\n\tint code = Tcl_EvalEx(_eventInterp, \"::tk::mac::ReopenApplication\",\n\t\t\t      TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tif (code != TCL_OK){\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n    }\n}\n\n- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event\n    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    (void)event;\n    (void)replyEvent;\n\n    if (_eventInterp &&\n\t    Tcl_FindCommand(_eventInterp, \"::tk::mac::ShowPreferences\", NULL, 0)){\n\tint code = Tcl_EvalEx(_eventInterp, \"::tk::mac::ShowPreferences\",\n\t\t\t      TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n    }\n}\n\n- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event\n    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    Tcl_Encoding utf8;\n    const AEDesc *fileSpecDesc = nil;\n    AEDesc contents;\n    char URLString[1 + URL_MAX_LENGTH];\n    NSURL *fileURL;\n    DescType type;\n    Size actual;\n    long count, index;\n    AEKeyword keyword;\n    Tcl_DString pathName;\n    (void)replyEvent;\n\n    /*\n     * Do nothing if we don't have an interpreter.\n     */\n\n    if (!_eventInterp) {\n\treturn;\n    }\n\n    fileSpecDesc = [event aeDesc];\n    if (fileSpecDesc == nil ) {\n\treturn;\n    }\n\n    /*\n     * The AppleEvent's descriptor should either contain a value of\n     * typeObjectSpecifier or typeAEList.  In the first case, the descriptor\n     * can be treated as a list of size 1 containing a value which can be\n     * coerced into a fileURL. In the second case we want to work with the list\n     * itself.  Values in the list will be coerced into fileURL's if possible;\n     * otherwise they will be ignored.\n     */\n\n    /* Get a copy of the AppleEvent's descriptor. */\n    AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents);\n    if (contents.descriptorType == typeAEList) {\n\tfileSpecDesc = &contents;\n    }\n\n    if (AECountItems(fileSpecDesc, &count) != noErr) {\n\tAEDisposeDesc(&contents);\n\treturn;\n    }\n\n    /*\n     * Construct a Tcl expression which calls the ::tk::mac::OpenDocument\n     * procedure, passing the paths contained in the AppleEvent as arguments.\n     */\n\n    AppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n    Tcl_DString *openCommand = &AEInfo->command;\n    Tcl_DStringInit(openCommand);\n    Tcl_DStringAppend(openCommand, openDocumentProc, TCL_INDEX_NONE);\n    utf8 = Tcl_GetEncoding(NULL, \"utf-8\");\n\n    for (index = 1; index <= count; index++) {\n\tif (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,\n\t\t\t\t &type, (Ptr) URLString, URL_MAX_LENGTH, &actual)) {\n\t    continue;\n\t}\n\tif (type != typeFileURL) {\n\t    continue;\n\t}\n\tURLString[actual] = '\\0';\n\tfileURL = [NSURL URLWithString:[NSString stringWithUTF8String:(char*)URLString]];\n\tif (fileURL == nil) {\n\t    continue;\n\t}\n\t(void)Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], TCL_INDEX_NONE,\n\t\t&pathName);\n\tTcl_DStringAppendElement(openCommand, Tcl_DStringValue(&pathName));\n\tTcl_DStringFree(&pathName);\n    }\n\n    Tcl_FreeEncoding(utf8);\n    AEDisposeDesc(&contents);\n    AEInfo->interp = _eventInterp;\n    AEInfo->procedure = openDocumentProc;\n    AEInfo->replyEvent = nil;\n    AEInfo->retryCount = 0;\n    if (Tcl_FindCommand(_eventInterp, \"::tk::mac::OpenDocuments\", NULL, 0)){\n\tProcessAppleEvent((void *)AEInfo);\n    } else {\n\tTcl_CreateTimerHandler(500, ProcessAppleEvent, (void *)AEInfo);\n    }\n}\n\n- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event\n\t\t    withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    NSString* file = [[event paramDescriptorForKeyword:keyDirectObject]\n\t\t\t stringValue];\n    const char *printFile = [file UTF8String];\n    AppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n    Tcl_DString *printCommand = &AEInfo->command;\n    (void)replyEvent;\n\n    Tcl_DStringInit(printCommand);\n    Tcl_DStringAppend(printCommand, printDocProc, TCL_INDEX_NONE);\n    Tcl_DStringAppendElement(printCommand, printFile);\n    AEInfo->interp = _eventInterp;\n    AEInfo->procedure = printDocProc;\n    AEInfo->replyEvent = nil;\n    AEInfo->retryCount = 0;\n    ProcessAppleEvent((void *)AEInfo);\n}\n\n- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event\n\t      withReplyEvent: (NSAppleEventDescriptor *)replyEvent\n{\n    OSStatus err;\n    const AEDesc *theDesc = nil;\n    DescType type = 0, initialType = 0;\n    Size actual;\n    char URLBuffer[1 + URL_MAX_LENGTH];\n    char errString[128];\n\n    /*\n     * The DoScript event receives one parameter that should be text data or a\n     * fileURL.\n     */\n\n    theDesc = [event aeDesc];\n    if (theDesc == nil) {\n\treturn;\n    }\n\n    err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,\n\t\t\tNULL, 0, NULL);\n    if (err != noErr) {\n\tsnprintf(errString, sizeof(errString), \"AEDoScriptHandler: GetParamDesc error %d\", (int)err);\n\tAEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,\n\t\t      typeChar, errString, strlen(errString));\n\treturn;\n    }\n\n    if (MissedAnyParameters((AppleEvent*)theDesc)) {\n\tsnprintf(errString, sizeof(errString), \"AEDoScriptHandler: extra parameters\");\n\tAEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,\n\t\t      typeChar,errString, strlen(errString));\n\treturn;\n    }\n\n    if (initialType == typeFileURL || initialType == typeAlias) {\n\n\t/*\n\t * This descriptor can be coerced to a file url.  Construct a Tcl\n\t * expression which passes the file path as a string argument to\n\t * ::tk::mac::DoScriptFile.\n\t */\n\n\tif (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,\n\t\t\t\t  (Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) {\n\t    if (actual > 0) {\n\t\tURLBuffer[actual] = '\\0';\n\t\tNSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];\n\t\tNSURL *fileURL = [NSURL URLWithString:urlString];\n\t\tAppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n\t\tTcl_DString *scriptFileCommand = &AEInfo->command;\n\t\tTcl_DStringInit(scriptFileCommand);\n\t\tTcl_DStringAppend(scriptFileCommand, scriptFileProc, TCL_INDEX_NONE);\n\t\tTcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]);\n\t\tAEInfo->interp = _eventInterp;\n\t\tAEInfo->procedure = scriptFileProc;\n\t\tAEInfo->replyEvent = nil;\n\t\tAEInfo->retryCount = 0;\n\t\tProcessAppleEvent((void *)AEInfo);\n\t    }\n\t}\n    } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,\n\t\t\t       NULL, 0, &actual)) {\n\t/*\n\t * The descriptor cannot be coerced to a file URL but can be coerced to\n\t * text.  Construct a Tcl expression which passes the text as a string\n\t * argument to ::tk::mac::DoScriptText.\n\t */\n\n\tif (actual > 0) {\n\t    char *data = (char *)Tcl_Alloc(actual + 1);\n\t    if (noErr == AEGetParamPtr(theDesc, keyDirectObject,\n\t\t\t\t       typeUTF8Text, &type,\n\t\t\t\t       data, actual, NULL)) {\n\t\tdata[actual] = '\\0';\n\t\tAppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n\t\tTcl_DString *scriptTextCommand = &AEInfo->command;\n\t\tTcl_DStringInit(scriptTextCommand);\n\t\tTcl_DStringAppend(scriptTextCommand, scriptTextProc, TCL_INDEX_NONE);\n\t\tTcl_DStringAppendElement(scriptTextCommand, data);\n\t\tAEInfo->interp = _eventInterp;\n\t\tAEInfo->procedure = scriptTextProc;\n\t\tAEInfo->retryCount = 0;\n\t\tif (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {\n\t\t    AEInfo->replyEvent = replyEvent;\n\t\t    ProcessAppleEvent(AEInfo);\n\t\t} else {\n\t\t    AEInfo->replyEvent = nil;\n\t\t    ProcessAppleEvent(AEInfo);\n\t\t}\n\t    }\n\t}\n    }\n}\n\n- (void)handleURLEvent:(NSAppleEventDescriptor*)event\n\twithReplyEvent:(NSAppleEventDescriptor*)replyEvent\n{\n    NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]\n\t\t\tstringValue];\n    const char *cURL=[url UTF8String];\n    AppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n    Tcl_DString *launchCommand = &AEInfo->command;\n    (void)replyEvent;\n\n    Tcl_DStringInit(launchCommand);\n    Tcl_DStringAppend(launchCommand, launchURLProc, TCL_INDEX_NONE);\n    Tcl_DStringAppendElement(launchCommand, cURL);\n    AEInfo->interp = _eventInterp;\n    AEInfo->procedure = launchURLProc;\n    AEInfo->replyEvent = nil;\n    AEInfo->retryCount = 0;\n    ProcessAppleEvent((void *)AEInfo);\n}\n\n- (void)handleGetSDEFEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {\n     AppleEventInfo *AEInfo = (AppleEventInfo *)Tcl_Alloc(sizeof(AppleEventInfo));\n    Tcl_DString *sdefCommand = &AEInfo->command;\n    (void)event;\n    (void)replyEvent;\n\n    Tcl_DStringInit(sdefCommand);\n    Tcl_DStringAppend(sdefCommand, getSdefProc, TCL_INDEX_NONE);\n    AEInfo->interp = _eventInterp;\n    AEInfo->procedure =  getSdefProc;\n    AEInfo->replyEvent = nil;\n    AEInfo->retryCount = 0;\n    ProcessAppleEvent((void *)AEInfo);\n\n}\n\n@end\n\n#pragma mark -\n\n/*\n *----------------------------------------------------------------------\n *\n * ProcessAppleEvent --\n *\n *      Usually used as an idle task which evaluates a Tcl expression generated\n *      from an AppleEvent.  If the AppleEventInfo passed as the client data\n *      has a non-null replyEvent, the result of evaluating the expression will\n *      be added to the reply.  This must not be done when this function is\n *      called as an idle task, but is done when handling DoScriptText events\n *      when this function is called directly.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe expression will be evaluated and the clientData will be freed.\n *      The replyEvent may be modified to contain the result of evaluating\n *      a Tcl expression.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void ProcessAppleEvent(\n    void *clientData)\n{\n    int code;\n    AppleEventInfo *AEInfo = (AppleEventInfo*) clientData;\n\n    if (!AEInfo->interp) {\n\treturn;\n    }\n\n    /*\n     * Apple events that are delivered during the app startup can arrive\n     * before the Tcl procedure for handling the events has been defined.\n     * If the command is not found we create a timer handler to process\n     * the event later, hopefully after the command has been created.\n     * We retry up to 2 times before giving up.\n     */\n\n    if (!Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {\n\tif (AEInfo->retryCount < 2) {\n\t    AEInfo->retryCount++;\n\t    Tcl_CreateTimerHandler(200, ProcessAppleEvent, clientData);\n\t} else {\n\t    Tcl_Free(clientData);\n\t}\n\treturn;\n    }\n    code = Tcl_EvalEx(AEInfo->interp, Tcl_DStringValue(&AEInfo->command),\n\t    Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL);\n\n    if (AEInfo->replyEvent && code >= 0) {\n\tTcl_Size reslen;\n\tconst char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp),\n\t\t\t\t\t\t  &reslen);\n\tif (code == TCL_OK) {\n\t    AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],\n\t\t\t  keyErrorNumber, typeSInt32, &code, 4);\n\t    AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],\n\t\t\t  keyDirectObject, typeChar, result, reslen);\n\t} else {\n\t    AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],\n\t\t\t  keyErrorNumber, typeSInt32, &code, 4);\n\t    AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],\n\t\t\t  keyErrorString, typeUTF8Text, result, reslen);\n\t}\n    } else if (code != TCL_OK) {\n\tTcl_BackgroundException(AEInfo->interp, code);\n    }\n\n    Tcl_DStringFree(&AEInfo->command);\n    Tcl_Free(clientData);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInitAppleEvents --\n *\n *\tRegister AppleEvent handlers with the NSAppleEventManager for\n *      this NSApplication.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXInitAppleEvents(\n    TCL_UNUSED(Tcl_Interp *))\n{\n    NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];\n    static bool initialized = false;\n\n    if (!initialized) {\n\tinitialized = true;\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleQuitApplicationEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEQuitApplication];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleOpenApplicationEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEOpenApplication];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleReopenApplicationEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEReopenApplication];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleShowPreferencesEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEShowPreferences];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handlePrintDocumentsEvent:withReplyEvent:)\n\t    forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleDoScriptEvent:withReplyEvent:)\n\t    forEventClass:kAEMiscStandards andEventID:kAEDoScript];\n\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleURLEvent:withReplyEvent:)\n\t    forEventClass:kInternetEventClass andEventID:kAEGetURL];\n\n\t/*\n\t * We do not load our sdef dynamically but this event handler\n\t * is required to silence error messages from inline execution\n\t * of AppleScript at the Objective-C level.\n\t */\n\t[aeManager setEventHandler:NSApp\n\t    andSelector:@selector(handleGetSDEFEvent:withReplyEvent:)\n\t    forEventClass:'ascr' andEventID:'gsdf'];\n\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXDoHLEvent --\n *\n *\tDispatch an AppleEvent.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepend on the AppleEvent.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMacOSXDoHLEvent(\n    void *theEvent)\n{\n    /* According to the NSAppleEventManager reference:\n     *   \"The theReply parameter always specifies a reply Apple event, never\n     *   nil.  However, the handler should not fill out the reply if the\n     *   descriptor type for the reply event is typeNull, indicating the sender\n     *   does not want a reply.\"\n     * The specified way to build such a non-nil descriptor is used here.  But\n     * on OSX 10.11, the compiler nonetheless generates a warning.  I am\n     * supressing the warning here -- maybe the warnings will stop in a future\n     * compiler release.\n     */\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wnonnull\"\n#endif\n\n    NSAppleEventDescriptor* theReply = [NSAppleEventDescriptor nullDescriptor];\n    NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];\n\n    return [aeManager dispatchRawAppleEvent:(const AppleEvent*)theEvent\n\t\t      withRawReply: (AppleEvent *)theReply\n\t\t      handlerRefCon: (SRefCon)0];\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReallyKillMe --\n *\n *\tThis procedure tries to kill the shell by running exit, called from\n *      an event scheduled by the \"Quit\" AppleEvent handler.\n *\n * Results:\n *\tRuns the \"exit\" command which might kill the shell.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReallyKillMe(\n    Tcl_Event *eventPtr,\n    TCL_UNUSED(int))\n{\n    Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;\n    int quit = Tcl_FindCommand(interp, \"::tk::mac::Quit\", NULL, 0)!=NULL;\n\n    if (!quit) {\n\tTcl_Exit(0);\n    }\n\n    int code = Tcl_EvalEx(interp, \"::tk::mac::Quit\", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\n\t/*\n\t * Should be never reached...\n\t */\n\n\tTcl_BackgroundException(interp, code);\n    }\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MissedAnyParameters --\n *\n *\tChecks to see if parameters are still left in the event.\n *\n * Results:\n *\tTrue or false.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMissedAnyParameters(\n    const AppleEvent *theEvent)\n{\n   DescType returnedType;\n   Size actualSize;\n   OSStatus err;\n\n   err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr,\n\t    typeWildCard, &returnedType, NULL, 0, &actualSize);\n\n   return (err != errAEDescNotFound);\n}\f\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXImage.c",
    "content": "/*\n * tkMacOSXImage.c --\n *\n *\tThe code in this file provides an interface for XImages, and\n *      implements the nsimage image type.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2017-2021 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXImage.h\"\n#include \"tkColor.h\"\n#include \"xbytes.h\"\n\nstatic CGImageRef CreateCGImageFromPixmap(Drawable pixmap);\nstatic CGImageRef CreateCGImageFromDrawableRect( Drawable drawable, int force_1x_scale,\n     int x, int y, unsigned int width, unsigned int height, CGFloat *scale);\nstatic inline CGRect ClipCopyRects(CGRect srcBounds, CGRect dstBounds,\n     int src_x, int src_y, unsigned int width,  unsigned int height);\n\n/* Pixel formats\n *\n * Tk uses the XImage structure defined in Xlib.h for storing images.  The\n * image data in an XImage is a 32-bit aligned array of bytes.  Interpretation\n * of that data is not specified, but the structure includes parameters which\n * provide interpretation hints so that an application can use a family of\n * different data structures.\n *\n * The possible values for the XImage format field are XYBitmap, XYPixmap and\n * ZPixmap.  The macOS port does not support the XYPixmap format.  This means\n * that bitmap images are stored as a single bit plane (XYBitmap) and that\n * color images are stored as a sequence of pixel values (ZPixmap).\n *\n * For a ZPixmap, the number of bits allocated to each pixel is specified by\n * the bits_per_pixel field of the XImage structure.  The functions in this\n * module which convert between XImage and native CGImage or NSImage structures\n * only support XImages with 32 bits per pixel.  The ImageGetPixel and PutPixel\n * implementations in this file allow 1, 4, 8, 16 or 32 bits per pixel, however.\n *\n * In tkImgPhInstance.c the layout used for pixels is determined by the values\n * of the red_mask, blue_mask and green_mask fields in the XImage structure.\n * The Aqua port always sets red_mask = 0xFF0000, green_mask = 0xFF00, and\n * blue_mask = 0xFF. This means that a 32bpp ZPixmap XImage uses ARGB32 pixels,\n * with small-endian byte order BGRA. The data array for such an XImage can be\n * passed directly to construct a CGBitmapImageRep if one specifies the\n * bitmapInfo as kCGBitmapByteOrder32Big | kCGImageAlphaLast.\n *\n * The structures below describe the bitfields in two common 32 bpp pixel\n * layouts.  Note that bit field layouts are compiler dependent. The layouts\n * shown in the comments are those produced by clang and gcc.  Also note\n * that kCGBitmapByteOrder32Big is consistently set when creating CGImages or\n * CGImageBitmapReps.\n */\n\n/* RGBA32 0xRRGGBBAA (Byte order is RGBA on big-endian systems.)\n * This is used by NSBitmapImageRep when the bitmapFormat property is 0,\n * the default value.\n */\n\ntypedef struct RGBA32pixel_t {\n    unsigned red: 8;\n    unsigned green: 8;\n    unsigned blue: 8;\n    unsigned alpha: 8;\n} RGBA32pixel;\n\n/*\n * ARGB32 0xAARRGGBB (Byte order is ARGB on big-endian systems.)\n * This is used by Aqua Tk for XImages and by NSBitmapImageReps whose\n * bitmapFormat property is NSAlphaFirstBitmapFormat.\n */\n\ntypedef struct ARGB32pixel_t {\n    unsigned blue: 8;\n    unsigned green: 8;\n    unsigned red: 8;\n    unsigned alpha: 8;\n} ARGB32pixel;\n\ntypedef union pixel32_t {\n    unsigned int uint;\n    RGBA32pixel rgba;\n    ARGB32pixel argb;\n} pixel32;\n\n#pragma mark XImage handling\n\nint\n_XInitImageFuncPtrs(\n    TCL_UNUSED(XImage *)) /* image */\n{\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXCreateCGImageWithXImage --\n *\n *\tCreate CGImage from XImage, copying the image data.  Called\n *      in Tk_PutImage and (currently) nowhere else.\n *\n * Results:\n *\tCGImage, release after use.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void ReleaseData(\n    void *info,\n    TCL_UNUSED(const void *), /* data */\n    TCL_UNUSED(size_t))        /* size */\n{\n    Tcl_Free(info);\n}\n\nstatic CGImageRef\nTkMacOSXCreateCGImageWithXImage(\n    XImage *image,\n    uint32_t bitmapInfo)\n{\n    CGImageRef img = NULL;\n    size_t bitsPerComponent, bitsPerPixel;\n    size_t len = image->bytes_per_line * image->height;\n    const CGFloat *decode = NULL;\n    CGDataProviderRef provider = NULL;\n    char *data = NULL;\n    CGDataProviderReleaseDataCallback releaseData = ReleaseData;\n\n    if (image->bits_per_pixel == 1) {\n\t/*\n\t * BW image\n\t */\n\n\t/* Reverses the sense of the bits */\n\tstatic const CGFloat decodeWB[2] = {1, 0};\n\tdecode = decodeWB;\n\n\tbitsPerComponent = 1;\n\tbitsPerPixel = 1;\n\tdata = (char *)Tcl_Alloc(len);\n\tif (data) {\n\t    if (image->bitmap_bit_order != MSBFirst) {\n\t\tchar *srcPtr = image->data + image->xoffset;\n\t\tchar *endPtr = srcPtr + len;\n\t\tchar *destPtr = data;\n\n\t\twhile (srcPtr < endPtr) {\n\t\t    *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];\n\t\t}\n\t    } else {\n\t\tmemcpy(data, image->data + image->xoffset, len);\n\t    }\n\t    provider = CGDataProviderCreateWithData(data, data, len,\n\t\t    releaseData);\n\t    if (!provider) {\n\t\tTcl_Free(data);\n\t    }\n\t    img = CGImageMaskCreate(image->width, image->height,\n\t\t    bitsPerComponent, bitsPerPixel, image->bytes_per_line,\n\t\t    provider, decode, 0);\n\t    CGDataProviderRelease(provider);\n\t}\n    } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) {\n\n\t/*\n\t * Color image\n\t */\n\n\tif (image->width == 0 && image->height == 0) {\n\n\t    /*\n\t     * CGCreateImage complains on early macOS releases.\n\t     */\n\n\t    return NULL;\n\t}\n\tCGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();\n\tbitsPerComponent = 8;\n\tbitsPerPixel = 32;\n\tdata = (char *)Tcl_Alloc(len);\n\tif (data) {\n\t    memcpy(data, image->data + image->xoffset, len);\n\t    provider = CGDataProviderCreateWithData(data, data, len,\n\t\t    releaseData);\n\t    if (!provider) {\n\t\tTcl_Free(data);\n\t    }\n\t    img = CGImageCreate(image->width, image->height, bitsPerComponent,\n\t\t    bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,\n\t\t    provider, decode, 0, kCGRenderingIntentDefault);\n\t    CGDataProviderRelease(provider);\n\t}\n\tif (colorspace) {\n\t    CFRelease(colorspace);\n\t}\n    } else {\n\tTkMacOSXDbgMsg(\"Unsupported image type\");\n    }\n    return img;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyImage --\n *\n *\tDestroys storage associated with an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeallocates the image.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDestroyImage(\n    XImage *image)\n{\n    if (image) {\n\tif (image->data) {\n\t    Tcl_Free(image->data);\n\t}\n\tTcl_Free(image);\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageGetPixel --\n *\n *\tGet a single pixel from an image.\n *\n * Results:\n *      The XColor structure contains an unsigned long field named pixel which\n *      identifies the color.  This function returns the unsigned long that\n *      would be used as the pixel value of an XColor that has the same red\n *      green and blue components as the XImage pixel at the specified\n *      location.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic unsigned long\nImageGetPixel(\n    XImage *image,\n    int x,\n    int y)\n{\n    unsigned char r = 0, g = 0, b = 0;\n\n    /*\n     * Compute 8 bit red green and blue values, which are passed as inputs to\n     * TkMacOSXRGBPixel to produce the pixel value.\n     */\n\n    if (image && image->data) {\n\tunsigned char *srcPtr = ((unsigned char*) image->data)\n\t\t+ (y * image->bytes_per_line)\n\t\t+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);\n\n\tswitch (image->bits_per_pixel) {\n\tcase 32: /* 8 bits per channel */\n\t    {\n\t\tARGB32pixel *pixel = (ARGB32pixel *)srcPtr;\n\t\tr = pixel->red;\n\t\tg = pixel->green;\n\t\tb = pixel->blue;\n\t    }\n\t    break;\n\tcase 16: /* 5 bits per channel */\n\t    r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;\n\t    g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;\n\t    b = (*((unsigned short*) srcPtr) << 3) & 0xf8;\n\t    break;\n\tcase 8: /* 2 bits per channel */\n\t    r = (*srcPtr << 2) & 0xc0;\n\t    g = (*srcPtr << 4) & 0xc0;\n\t    b = (*srcPtr << 6) & 0xc0;\n\t    r |= r >> 2 | r >> 4 | r >> 6;\n\t    g |= g >> 2 | g >> 4 | g >> 6;\n\t    b |= b >> 2 | b >> 4 | b >> 6;\n\t    break;\n\tcase 4: { /* 1 bit per channel */\n\t    unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);\n\n\t    r = (c & 0x04) ? 0xff : 0;\n\t    g = (c & 0x02) ? 0xff : 0;\n\t    b = (c & 0x01) ? 0xff : 0;\n\t    break;\n\t}\n\tcase 1: /* Black-white bitmap. */\n\t    r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;\n\t    break;\n\t}\n    }\n\n    return TkMacOSXRGBPixel(r, g, b);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImagePutPixel --\n *\n *\tSet a single pixel in an image.  The pixel is provided as an unsigned\n *      32-bit integer.  The value of that integer is interpreted by assuming\n *      that its low-order N bits have the format specified by the XImage,\n *      where N is equal to the bits_per_pixel field of the XImage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nImagePutPixel(\n    XImage *image,\n    int x,\n    int y,\n    unsigned long pixel)\n{\n    if (image && image->data) {\n\tunsigned char *dstPtr = ((unsigned char*) image->data)\n\t\t+ (y * image->bytes_per_line)\n\t\t+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);\n\n\tif (image->bits_per_pixel == 32) {\n\t    *((unsigned int*) dstPtr) = pixel;\n\t} else {\n\t    switch (image->bits_per_pixel) {\n\t    case 16:\n\t\t*((unsigned short*) dstPtr) = pixel & 0xffff;\n\t\tbreak;\n\t    case 8:\n\t\t*dstPtr = pixel & 0xff;\n\t\tbreak;\n\t    case 4: {\n\t\t*dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (pixel & 0x0f)) :\n\t\t\t((*dstPtr & 0x0f) | ((pixel << 4) & 0xf0));\n\t\tbreak;\n\t\t}\n\t    case 1:\n\t\t*dstPtr = pixel ? (*dstPtr | (0x80 >> (x % 8))) :\n\t\t\t(*dstPtr & ~(0x80 >> (x % 8)));\n\t\tbreak;\n\t    }\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateImage --\n *\n *\tAllocates storage for a new XImage.\n *\n * Results:\n *\tReturns a newly allocated XImage.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nXImage *\nXCreateImage(\n    Display* display,\n    TCL_UNUSED(Visual*), /* visual */\n    unsigned int depth,\n    int format,\n    int offset,\n    char* data,\n    unsigned int width,\n    unsigned int height,\n    int bitmap_pad,\n    int bytes_per_line)\n{\n    XImage *ximage;\n\n    LastKnownRequestProcessed(display)++;\n    ximage = (XImage *)Tcl_Alloc(sizeof(XImage));\n\n    ximage->height = height;\n    ximage->width = width;\n    ximage->depth = depth;\n    ximage->xoffset = offset;\n    ximage->format = format;\n    ximage->data = data;\n    ximage->obdata = NULL;\n\n    if (format == ZPixmap) {\n\tximage->bits_per_pixel = 32;\n\tximage->bitmap_unit = 32;\n    } else {\n\tximage->bits_per_pixel = 1;\n\tximage->bitmap_unit = 8;\n    }\n    if (bitmap_pad) {\n\tximage->bitmap_pad = bitmap_pad;\n    } else {\n\t/*\n\t * Use 16 byte alignment for best Quartz performance.\n\t */\n\n\tximage->bitmap_pad = 128;\n    }\n    if (bytes_per_line) {\n\tximage->bytes_per_line = bytes_per_line;\n    } else {\n\tximage->bytes_per_line = ((width * ximage->bits_per_pixel +\n\t\t(ximage->bitmap_pad - 1)) >> 3) &\n\t\t~((ximage->bitmap_pad >> 3) - 1);\n    }\n#ifdef WORDS_BIGENDIAN\n    ximage->byte_order = MSBFirst;\n    ximage->bitmap_bit_order = MSBFirst;\n#else\n    ximage->byte_order = LSBFirst;\n    ximage->bitmap_bit_order = LSBFirst;\n#endif\n    ximage->red_mask = 0x00FF0000;\n    ximage->green_mask = 0x0000FF00;\n    ximage->blue_mask = 0x000000FF;\n    ximage->f.create_image = NULL;\n    ximage->f.destroy_image = DestroyImage;\n    ximage->f.get_pixel = ImageGetPixel;\n    ximage->f.put_pixel = ImagePutPixel;\n    ximage->f.sub_image = NULL;\n    ximage->f.add_pixel = NULL;\n\n    return ximage;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPutImage, XPutImage, TkpPutRGBAImage --\n *\n *\tThese functions, which all have the same signature, copy a rectangular\n *      subimage of an XImage into a drawable.  TkPutImage is an alias for\n *      XPutImage, which assumes that the XImage data has the structure of a\n *      32bpp ZPixmap in which the image data is an array of 32bit integers\n *      packed with 8 bit values for the Red Green and Blue channels.  The\n *      fourth byte is ignored.  The function TkpPutRGBAImage assumes that the\n *      XImage data has been extended by using the fourth byte to store an\n *      8-bit Alpha value.  (The Alpha data is assumed not to pre-multiplied).\n *      The image is then drawn into the drawable using standard Porter-Duff\n *      Source Atop Composition (kCGBlendModeSourceAtop in Apple's Core\n *      Graphics).\n *\n *      The TkpPutRGBAImage function is used by TkImgPhotoDisplay to render photo\n *      images if the compile-time variable TK_CAN_RENDER_RGBA is defined in\n *      a platform's tkXXXXPort.h header, as is the case for the macOS Aqua port.\n *\n * Results:\n *\tThese functions return either BadDrawable or Success.\n *\n * Side effects:\n *\tDraws the image on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\n#define USE_ALPHA (kCGImageAlphaLast | kCGBitmapByteOrder32Big)\n#define IGNORE_ALPHA (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little)\n\nstatic int\nTkMacOSXPutImage(\n    uint32_t pixelFormat,\n    Display* display,\t\t/* Display. */\n    Drawable drawable,\t\t/* Drawable to place image on. */\n    GC gc,\t\t\t/* GC to use. */\n    XImage* image,\t\t/* Image to place. */\n    int src_x,\t\t\t/* Source X & Y. */\n    int src_y,\n    int dest_x,\t\t\t/* Destination X & Y. */\n    int dest_y,\n    unsigned int width,\t        /* Same width & height for both */\n    unsigned int height)\t/* destination and source. */\n{\n    TkMacOSXDrawingContext dc;\n    MacDrawable *macDraw = (MacDrawable *)drawable;\n    int result = Success;\n\n    if (width <= 0 || height <= 0) {\n\treturn Success; /* Is OK. Nothing to see here, literally. */\n    }\n    LastKnownRequestProcessed(display)++;\n    if (!TkMacOSXSetupDrawingContext(drawable, gc, &dc)) {\n\treturn BadDrawable;\n    }\n    if (dc.context) {\n\tCGRect dstRect, srcRect = CGRectMake(src_x, src_y, width, height);\n\t/*\n\t * Whole image is copied before cropping. For performance,\n\t * consider revising TkMacOSXCreateCGImageWithXImage() to accept\n\t * source x/y/w/h and copy only the needed portion instead.\n\t */\n\tCGImageRef img = TkMacOSXCreateCGImageWithXImage(image, pixelFormat);\n\tCGImageRef cropped = CGImageCreateWithImageInRect(img, srcRect);\n\tCGImageRelease(img);\n\timg = cropped;\n\n\t/*\n\t * The CGContext for a pixmap is RGB only, with A = 0.\n\t */\n\n\tif (!(macDraw->flags & TK_IS_PIXMAP)) {\n\t    CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop);\n\t}\n\tif (img) {\n\t    dstRect = CGRectMake(dest_x, dest_y, width, height);\n\t    TkMacOSXDrawCGImage(drawable, gc, dc.context, img,\n\t\t\t\tgc->foreground, gc->background, dstRect);\n\t    CFRelease(img);\n\t} else {\n\t    TkMacOSXDbgMsg(\"Invalid source drawable\");\n\t    result = BadDrawable;\n\t}\n    } else {\n\tTkMacOSXDbgMsg(\"Invalid destination drawable\");\n\tresult = BadDrawable;\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    return result;\n}\n\nint XPutImage(\n    Display* display,\n    Drawable drawable,\n    GC gc,\n    XImage* image,\n    int src_x,\n    int src_y,\n    int dest_x,\n    int dest_y,\n    unsigned int width,\n    unsigned int height) {\n    return TkMacOSXPutImage(IGNORE_ALPHA, display, drawable, gc, image,\n\t\t\t    src_x, src_y, dest_x, dest_y, width, height);\n}\n\nint TkpPutRGBAImage(\n    Display* display,\n    Drawable drawable,\n    GC gc,\n    XImage* image,\n    int src_x,\n    int src_y,\n    int dest_x,\n    int dest_y,\n    unsigned int width,\n    unsigned int height) {\n    return TkMacOSXPutImage(USE_ALPHA, display, drawable, gc, image,\n\t\t     src_x, src_y, dest_x, dest_y, width, height);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateCGImageFromDrawableRect\n *\n *\tExtract image data from a MacOSX drawable as a CGImage.  The drawable\n *      may be either a pixmap or a window, but there issues in the case of\n *      a window.\n *\n *      CreateCGImageFromDrawableRect is called by XGetImage and XCopyArea.\n *      The Tk core uses these two functions on some platforms in order to\n *      implement explicit double-buffered drawing -- a pixmap is copied from a\n *      window, modified using CPU-based graphics composition, and then copied\n *      back to the window.  Platforms, such as macOS, on which the system\n *      provides double-buffered drawing and GPU-based composition operations\n *      can avoid calls to XGetImage and XCopyArea from the core by defining\n *      the compile-time variable TK_NO_DOUBLE_BUFFERING.  Nonetheless, these\n *      two functions are in the stubs table and therefore could be used by\n *      extensions.\n *\n *      The implementation here does not always work correctly when the source\n *      is a window.  The original version of this function relied on\n *      [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was\n *      deprecated by Apple in OSX 10.14 and also required the use of other\n *      deprecated functions such as [NSView lockFocus]. Apple's suggested\n *      replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that\n *      is being used here.  However, cacheDisplayInRect works by calling\n *      [NSView drawRect] after setting the current graphics context to be one\n *      which draws to a bitmap.  There are situations in which this can be\n *      used, e.g. when taking a screenshot of a window.  But it cannot be used\n *      as part of a normal display procedure, using the copy-modify-paste\n *      paradigm that is the basis of the explicit double-buffering.  Since the\n *      copy operation will call the same display procedure that is calling\n *      this function via XGetImage or XCopyArea, this would create an infinite\n *      recursion.\n *\n *      An alternative to the copy-modify-paste paradigm is to use GPU-based\n *      graphics composition, clipping to the specified rectangle.  That is\n *      the approach that must be followed by display procedures on macOS.\n *\n * Results:\n *\tReturns an NSBitmapRep representing the image of the given rectangle of\n *      the given drawable. This object is retained. The caller is responsible\n *      for releasing it.\n *\n *      NOTE: The x,y coordinates should be relative to a coordinate system\n *      with origin at the top left, as used by XImage and CGImage, not bottom\n *      left as used by NSView.\n *\n *      If force_1x_scale is true, then the returned CGImage will be downscaled\n *      if necessary to have the requested width and height. Othewise, for\n *      windows on Retina displays, the width and height of the returned CGImage\n *      will be twice the requested width and height.\n *\n * Side effects:\n *     None\n *\n *----------------------------------------------------------------------\n */\n\nstatic CGImageRef\nCreateCGImageFromDrawableRect(\n    Drawable drawable,\n    int force_1x_scale,\n    int x,\n    int y,\n    unsigned int width,\n    unsigned int height,\n    CGFloat *scalePtr)\n{\n    MacDrawable *mac_drawable = (MacDrawable *)drawable;\n    CGContextRef cg_context = NULL;\n    CGImageRef cg_image = NULL, result = NULL;\n    CGFloat scaleFactor = 1.0;\n    if (mac_drawable->flags & TK_IS_PIXMAP) {\n\tcg_context = TkMacOSXGetCGContextForDrawable(drawable);\n\tCGContextRetain(cg_context);\n    } else {\n\tNSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable);\n\tif (view == nil) {\n\t    TkMacOSXDbgMsg(\"Invalid source drawable\");\n\t    return NULL;\n\t}\n\tscaleFactor = view.layer.contentsScale;\n\tcg_context = ((TKContentView *)view).tkLayerBitmapContext;\n\tCGContextRetain(cg_context);\n    }\n    if (scalePtr != nil) {\n\t*scalePtr = scaleFactor;\n    }\n    if (cg_context) {\n\tcg_image = CGBitmapContextCreateImage(cg_context);\n\tCGContextRelease(cg_context);\n    }\n    if (cg_image) {\n\tCGRect rect = CGRectMake(x + mac_drawable->xOff, y + mac_drawable->yOff,\n\t\t\t\t width, height);\n\trect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(scaleFactor, scaleFactor));\n\tif (force_1x_scale && (scaleFactor != 1.0)) {\n\t    // See https://web.archive.org/web/20200219030756/http://blog.foundry376.com/2008/07/scaling-a-cgimage/#comment-200\n\t    // create context, keeping original image properties\n\t    CGColorSpaceRef colorspace = CGImageGetColorSpace(cg_image);\n\t    cg_context = CGBitmapContextCreate(NULL, width, height,\n\t\t    CGImageGetBitsPerComponent(cg_image),\n\t\t    //CGImageGetBytesPerRow(cg_image), // wastes space?\n\t\t    CGImageGetBitsPerPixel(cg_image) * width / 8,\n\t\t    colorspace,\n\t\t    CGImageGetBitmapInfo(cg_image));\n\t    CGColorSpaceRelease(colorspace);\n\t    if (cg_context) {\n\t\t// Extract the subimage in the specified rectangle.\n\t\tCGImageRef subimage = CGImageCreateWithImageInRect(cg_image, rect);\n\t\t// Draw the subimage in our context (resizing it to fit).\n\t\tCGContextDrawImage(cg_context, CGRectMake(0, 0, width, height),\n\t\t\tsubimage);\n\t\t// We will return the image we just drew.\n\t\tresult = CGBitmapContextCreateImage(cg_context);\n\t\tCGContextRelease(cg_context);\n\t\tCGImageRelease(subimage);\n\t    }\n\t} else {\n\t    // No resizing is needed.  Just return the subimage\n\t    result = CGImageCreateWithImageInRect(cg_image, rect);\n\t}\n\tCGImageRelease(cg_image);\n    }\n    return result;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * CreatePDFFromDrawableRect\n *\n *\tExtract PDF data from a MacOSX drawable.\n *\n * Results:\n *\tReturns a CFDataRef that can be written to a file.\n *\n *      NOTE: The x,y coordinates should be relative to a coordinate system\n *      with origin at the bottom left as used by NSView,  not top left\n *      as used by XImage and CGImage.\n *\n * Side effects:\n *     None\n *\n *----------------------------------------------------------------------\n */\n\nCFDataRef\nCreatePDFFromDrawableRect(\n\t\t\t  Drawable drawable,\n\t\t\t  int x,\n\t\t\t  int y,\n\t\t\t  unsigned int width,\n\t\t\t  unsigned int height)\n{\n    MacDrawable *mac_drawable = (MacDrawable *) drawable;\n    NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable);\n    if (view == nil) {\n\tTkMacOSXDbgMsg(\"Invalid source drawable\");\n\treturn NULL;\n    }\n\n    NSRect bounds;\n    CGRect viewSrcRect;\n\n    /*\n     * Get the child window area in NSView coordinates\n     * (origin at bottom left).\n     */\n\n    bounds = [view bounds];\n    viewSrcRect = CGRectMake(mac_drawable->xOff + x,\n\t\t\t     bounds.size.height - height - (mac_drawable->yOff + y),\n\t\t\t     width, height);\n\n    NSMutableData *pdfData = [NSMutableData data];\n\n    CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((__bridge CFMutableDataRef) pdfData);\n\n    CGRect pdfBounds = CGRectMake(0, 0, width, height);\n\n    CGContextRef ctx = CGPDFContextCreate(consumer, &pdfBounds, NULL);\n\n    CGPDFContextBeginPage(ctx, NULL);\n\n    CGContextSaveGState(ctx);\n\n    /*\n     * Translate so the requested rect maps to (0,0).\n     */\n\n    CGContextTranslateCTM(ctx, -viewSrcRect.origin.x,\n\t\t\t  -viewSrcRect.origin.y);\n\n    /*\n     * Render CALayer tree.\n     */\n\n    [view.layer renderInContext:ctx];\n\n    CGContextRestoreGState(ctx);\n\n    CGPDFContextEndPage(ctx);\n\n    CGContextRelease(ctx);\n    CGDataConsumerRelease(consumer);\n\n    /*\n     * Caller owns returned CFDataRef.\n     */\n\n    return (CFDataRef)CFBridgingRetain(pdfData);\n}\n\n\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateCGImageFromPixmap --\n *\n *\tCreate a CGImage from an X Pixmap.\n *\n * Results:\n *\tCGImage, release after use.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic CGImageRef\nCreateCGImageFromPixmap(\n    Drawable pixmap)\n{\n    CGImageRef img = NULL;\n    CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);\n\n    if (context) {\n\timg = CGBitmapContextCreateImage(context);\n    }\n    return img;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetImage --\n *\n *\tThis function copies data from a pixmap or window into an XImage.  It\n *      is essentially never used. At one time it was called by\n *      pTkImgPhotoDisplay, but that is no longer the case. Currently it is\n *      called two places, one of which is requesting an XY image which we do\n *      not support.  It probably does not work correctly -- see the comments\n *      for CGImageFromDrawableRect.\n *\n * Results:\n *\tReturns a newly allocated XImage containing the data from the given\n *\trectangle of the given drawable, or NULL if the XImage could not be\n *\tconstructed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nXImage *\nXGetImage(\n    Display *display,\n    Drawable drawable,\n    int x,\n    int y,\n    unsigned int width,\n    unsigned int height,\n    TCL_UNUSED(unsigned long),  /* plane_mask */\n    int format)\n{\n    XImage* imagePtr = NULL;\n    NSBitmapImageRep* bitmapRep = nil;\n    NSBitmapFormat bitmap_fmt = 0;\n    char *bitmap = NULL;\n    int depth = 32, offset = 0, bitmap_pad = 0;\n    NSInteger bytes_per_row, samples_per_pixel, size;\n    unsigned int row, n, m;\n\n    if (format == ZPixmap) {\n\tCGImageRef cgImage;\n\tif (width == 0 || height == 0) {\n\t    return NULL;\n\t}\n\n\t// Request 1x-scale image for compatibility\n\tcgImage = CreateCGImageFromDrawableRect(drawable, 1, x, y, width, height, nil);\n\tif (cgImage) {\n\t    bitmapRep = [NSBitmapImageRep alloc];\n\t    [bitmapRep initWithCGImage:cgImage];\n\t    CFRelease(cgImage);\n\t} else {\n\t    TkMacOSXDbgMsg(\"XGetImage: Failed to construct CGImage\");\n\t    return NULL;\n\t}\n\tbitmap_fmt = [bitmapRep bitmapFormat];\n\tsize = [bitmapRep bytesPerPlane];\n\tbytes_per_row = [bitmapRep bytesPerRow];\n\tsamples_per_pixel = [bitmapRep samplesPerPixel];\n#if 0\n\tfprintf(stderr, \"XGetImage:\\n\"\n\t\t\"  bitmsp_fmt = %ld\\n\"\n\t\t\"  samples_per_pixel = %ld\\n\"\n\t\t\"  width = %u\\n\"\n\t\t\"  height = %u\\n\"\n\t\t\"  bytes_per_row = %ld\\n\"\n\t\t\"  size = %ld\\n\",\n\t\tbitmap_fmt, samples_per_pixel, width, height, bytes_per_row, size);\n#endif\n\t/*\n\t * Image data with all pixels having alpha value 255 may be reported\n\t * as 3 samples per pixel, even though each row has 4*width pixels and\n\t * the pixels are stored in the default ARGB32 format.\n\t */\n\n\tif ((bitmap_fmt != 0 && bitmap_fmt != NSAlphaFirstBitmapFormat)\n\t    || samples_per_pixel < 3\n\t    || samples_per_pixel > 4\n\t    || [bitmapRep isPlanar] != 0\n\t    || size != bytes_per_row * height) {\n\t    TkMacOSXDbgMsg(\"XGetImage: Unrecognized bitmap format\");\n\t    [bitmapRep release];\n\t    return NULL;\n\t}\n\tbitmap = (char *)Tcl_Alloc(size);\n\tmemcpy(bitmap, (char *)[bitmapRep bitmapData], size);\n\t[bitmapRep release];\n\n\tfor (row = 0, n = 0; row < height; row++, n += bytes_per_row) {\n\t    for (m = n; m < n + 4*width; m += 4) {\n\t\tpixel32 pixel = *((pixel32 *)(bitmap + m));\n\t\tif (bitmap_fmt == 0) { // default format\n\n\t\t    /*\n\t\t     * This pixel is in ARGB32 format.  We need RGBA32.\n\t\t     */\n\n\t\t    pixel32 flipped;\n\t\t    flipped.rgba.red = pixel.argb.red;\n\t\t    flipped.rgba.green = pixel.argb.green;\n\t\t    flipped.rgba.blue = pixel.argb.blue;\n\t\t    flipped.rgba.alpha = pixel.argb.alpha;\n\t\t    *((pixel32 *)(bitmap + m)) = flipped;\n\t\t} else { // bitmap_fmt = NSAlphaFirstBitmapFormat\n\t\t    *((pixel32 *)(bitmap + m)) = pixel;\n\t\t}\n\t    }\n\t}\n\n\timagePtr = XCreateImage(display, NULL, depth, format, offset,\n\t\t(char*) bitmap, width, height,\n\t\tbitmap_pad, bytes_per_row);\n    } else {\n\n\t/*\n\t * There are some calls to XGetImage in the generic Tk code which pass\n\t * an XYPixmap rather than a ZPixmap.  XYPixmaps should be handled\n\t * here.\n\t */\n\n\tTkMacOSXDbgMsg(\"XGetImage does not handle XYPixmaps at the moment.\");\n    }\n    return imagePtr;\n}\n\f\nstatic inline CGRect\nClipCopyRects(\n    CGRect srcBounds,\n    CGRect dstBounds,\n    int src_x,\n    int src_y,\n    unsigned int width,\n    unsigned int height)\n{\n    CGRect srcRect = CGRectMake(src_x, src_y, width, height);\n    CGRect bounds1 = CGRectIntersection(srcRect, srcBounds);\n    return CGRectIntersection(bounds1, dstBounds);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScrollWindow --\n *\n *\tScroll a rectangle of the specified window and accumulate a damage\n *\tregion.\n *\n * Results:\n *\tReturns false if the scroll generated no additional damage. Otherwise, sets\n *\tthe region that needs to be repainted after scrolling and returns true.\n *      When drawRect was in use, this function used the now deprecated\n *      scrollRect method of NSView.  With the current updateLayer\n *      implementation, using a CGImage as the view's backing layer, we are\n *      able to use XCopyArea.  But both implementations are incomplete.\n *      They return a damage area which is just the source rectangle minus\n *      destination rectangle.  Other platforms, e.g. Windows, where\n *      this function is essentially provided by the windowing system,\n *      are able to add to the damage region the bounding rectangles of\n *      all subwindows which meet the source rectangle, even if they are\n *      contained in the destination rectangle.  The information needed\n *      to do that is not available in this module, as far as I know.\n *\n *      In fact, the Text widget is the only one which calls this\n *      function, and  textDisp.c compensates for this defect by using\n *      macOS-specific code.  This is possible because access to the\n *      list of all embedded windows in a Text widget is available in\n *      that module.\n *\n * Side effects:\n *\tScrolls the bits in the window.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkScrollWindow(\n    Tk_Window tkwin,\t\t/* The window to be scrolled. */\n    GC gc,\t\t\t/* GC for window to be scrolled. */\n    int x, int y,\t\t/* Position rectangle to be scrolled. */\n    int width, int height,\n    int dx, int dy,\t\t/* Distance rectangle should be moved. */\n    Region damageRgn)\t\t/* Region to accumulate damage in. */\n{\n    Drawable drawable = Tk_WindowId(tkwin);\n    HIShapeRef srcRgn, dstRgn;\n    HIMutableShapeRef dmgRgn = HIShapeCreateMutable();\n    NSRect srcRect, dstRect;\n    bool result = false;\n    NSView *view = TkMacOSXGetNSViewForDrawable(drawable);\n    CGRect viewBounds = [view bounds];\n\n    /*\n     * To compute the damage region correctly we need to clip the source and\n     * destination rectangles to the NSView bounds in the same way that\n     * XCopyArea does.\n     */\n\n    CGRect bounds = ClipCopyRects(viewBounds, viewBounds, x, y, width, height);\n    unsigned int w = bounds.size.width;\n    unsigned int h = bounds.size.height;\n\n    if (XCopyArea(Tk_Display(tkwin), drawable, drawable, gc, x, y,\n\t     w, h, x + dx, y + dy) == Success) {\n\n\t/*\n\t * Compute the damage region, using Tk coordinates (origin at top left).\n\t */\n\n\tsrcRect = CGRectMake(x, y, width, height);\n\tdstRect = CGRectOffset(bounds, dx, dy);\n\t//dstRect = CGRectOffset(srcRect, dx, dy);\n\tsrcRgn = HIShapeCreateWithRect(&srcRect);\n\tdstRgn = HIShapeCreateWithRect(&dstRect);\n\tChkErr(HIShapeDifference, srcRgn, dstRgn, dmgRgn);\n\tCFRelease(dstRgn);\n\tCFRelease(srcRgn);\n\tresult = !HIShapeIsEmpty(dmgRgn);\n\n    }\n\n    /*\n     * Convert the HIShape dmgRgn into a Region and store it.\n     */\n\n    TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);\n\n    CFRelease(dmgRgn);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCopyArea --\n *\n *\tCopies image data from one drawable to another.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tImage data is moved from a window or bitmap to a second window or bitmap.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXCopyArea(\n    Display *display,\t\t/* Display. */\n    Drawable src,\t\t/* Source drawable. */\n    Drawable dst,\t\t/* Destination drawable. */\n    GC gc,\t\t\t/* GC to use. */\n    int src_x,\t\t\t/* X & Y, width & height */\n    int src_y,\t\t\t/* define the source rectangle */\n    unsigned int width,\t\t/* that will be copied. */\n    unsigned int height,\n    int dst_x,\t\t\t/* Dest X & Y on dest rect. */\n    int dst_y)\n{\n    TkMacOSXDrawingContext dc;\n    CGImageRef img = NULL;\n    CGRect dstRect;\n\n    // XXXX Need to deal with pixmaps!\n\n    NSView *srcView = TkMacOSXGetNSViewForDrawable(src);\n    NSView *dstView = TkMacOSXGetNSViewForDrawable(dst);\n    CGRect srcBounds = [srcView bounds];\n    CGRect dstBounds = [dstView bounds];\n\n    // To avoid distorting the image when it is drawn we must ensure that\n    // the source and destination rectangles have the same size.  This is\n    // tricky because each of those rectangles will be clipped to the\n    // bounds of its containing NSView.  If the source gets clipped and\n    // the destination does not, for example, then the shapes will differ.\n    // We deal with this by reducing their common size  enough so that both\n    // rectangles are  contained in their respective views.\n\n    CGRect bounds = ClipCopyRects(srcBounds, dstBounds, src_x, src_y, width, height);\n    width = (int) bounds.size.width;\n    height = (int) bounds.size.height;\n    CGFloat scaleFactor;\n\n    LastKnownRequestProcessed(display)++;\n    if (!width || !height) {\n\treturn BadDrawable;\n    }\n\n    if (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {\n\tTkMacOSXDbgMsg(\"Failed to setup drawing context.\");\n\treturn BadDrawable;\n    }\n\n    if (!dc.context) {\n\tTkMacOSXDbgMsg(\"Invalid destination drawable - no context.\");\n\treturn BadDrawable;\n    }\n\n    img = CreateCGImageFromDrawableRect(src, 0, src_x, src_y, width, height, &scaleFactor);\n\n    if (img) {\n\tunsigned int w = (unsigned int) (CGImageGetWidth(img) / scaleFactor);\n\tunsigned int h = (unsigned int) (CGImageGetHeight(img) / scaleFactor);\n\tdstRect = CGRectMake(dst_x, dst_y, w, h);\n\tTkMacOSXDrawCGImage(dst, gc, dc.context, img,\n\t\tgc->foreground, gc->background, dstRect);\n\tCFRelease(img);\n    } else {\n\tTkMacOSXDbgMsg(\"Failed to construct CGImage.\");\n    }\n\n    TkMacOSXRestoreDrawingContext(&dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCopyPlane --\n *\n *\tCopies a bitmap from a source drawable to a destination drawable. The\n *\tplane argument specifies which bit plane of the source contains the\n *\tbitmap. Note that this implementation ignores the gc->function.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the destination drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXCopyPlane(\n    Display *display,\t\t/* Display. */\n    Drawable src,\t\t/* Source drawable. */\n    Drawable dst,\t\t/* Destination drawable. */\n    GC gc,\t\t\t\t/* GC to use. */\n    int src_x,\t\t\t/* X & Y, width & height */\n    int src_y,\t\t\t/* define the source rectangle */\n    unsigned int width,\t/* that will be copied. */\n    unsigned int height,\n    int dest_x,\t\t\t/* Dest X & Y on dest rect. */\n    int dest_y,\n    unsigned long plane)\t/* Which plane to copy. */\n{\n    TkMacOSXDrawingContext dc;\n    MacDrawable *srcDraw = (MacDrawable *)src;\n    MacDrawable *dstDraw = (MacDrawable *)dst;\n    CGRect srcRect, dstRect;\n    LastKnownRequestProcessed(display)++;\n    if (!width || !height) {\n\t/* TkMacOSXDbgMsg(\"Drawing of empty area requested\"); */\n\treturn BadDrawable;\n    }\n    if (plane != 1) {\n\tTcl_Panic(\"Unexpected plane specified for XCopyPlane\");\n    }\n    if (srcDraw->flags & TK_IS_PIXMAP) {\n\tif (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {\n\t    return BadDrawable;\n\t}\n\n\tCGContextRef context = dc.context;\n\n\tif (context) {\n\t    CGImageRef img = CreateCGImageFromPixmap(src);\n\n\t    if (img) {\n\t\tTkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;\n\t\tunsigned long imageBackground  = gc->background;\n\n\t\tif (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {\n\t\t    srcRect = CGRectMake(src_x, src_y, width, height);\n\t\t    CGImageRef mask = CreateCGImageFromPixmap(\n\t\t\t    clipPtr->value.pixmap);\n\t\t    CGImageRef submask = CGImageCreateWithImageInRect(\n\t\t\t    img, srcRect);\n\t\t    CGRect rect = CGRectMake(dest_x, dest_y, width, height);\n\n\t\t    rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);\n\t\t    CGContextSaveGState(context);\n\n\t\t    /*\n\t\t     * Move the origin of the destination to top left.\n\t\t     */\n\n\t\t    CGContextTranslateCTM(context,\n\t\t\t    0, rect.origin.y + CGRectGetMaxY(rect));\n\t\t    CGContextScaleCTM(context, 1, -1);\n\n\t\t    /*\n\t\t     * Fill with the background color, clipping to the mask.\n\t\t     */\n\n\t\t    CGContextClipToMask(context, rect, submask);\n\t\t    TkMacOSXSetColorInContext(gc, gc->background, dc.context,\n\t\t\t    TkMacOSXInDarkMode((Tk_Window)dstDraw->winPtr));\n\t\t    CGContextFillRect(context, rect);\n\n\t\t    /*\n\t\t     * Fill with the foreground color, clipping to the\n\t\t     * intersection of img and mask.\n\t\t     */\n\n\t\t    CGImageRef subimage = CGImageCreateWithImageInRect(\n\t\t\t    img, srcRect);\n\t\t    CGContextClipToMask(context, rect, subimage);\n\t\t    TkMacOSXSetColorInContext(gc, gc->foreground, context,\n\t\t\t    TkMacOSXInDarkMode((Tk_Window)dstDraw->winPtr));\n\t\t    CGContextFillRect(context, rect);\n\t\t    CGContextRestoreGState(context);\n\t\t    CGImageRelease(img);\n\t\t    CGImageRelease(mask);\n\t\t    CGImageRelease(submask);\n\t\t    CGImageRelease(subimage);\n\t\t} else {\n\t\t    dstRect = CGRectMake(dest_x, dest_y, width, height);\n\t\t    TkMacOSXDrawCGImage(dst, gc, dc.context, img,\n\t\t\t    gc->foreground, imageBackground, dstRect);\n\t\t    CGImageRelease(img);\n\t\t}\n\t    } else {\n\t\t/* no image */\n\t\tTkMacOSXDbgMsg(\"Invalid source drawable\");\n\t    }\n\t} else {\n\t    TkMacOSXDbgMsg(\"Invalid destination drawable - \"\n\t\t    \"could not get a bitmap context.\");\n\t}\n\tTkMacOSXRestoreDrawingContext(&dc);\n\treturn Success;\n    } else {\n\t/*\n\t * Source drawable is a Window, not a Pixmap.\n\t */\n\n\treturn XCopyArea(display, src, dst, gc, src_x, src_y, width, height,\n\t\tdest_x, dest_y);\n    }\n}\n\f\n/* ---------------------------------------------------------------------------*/\n\n/*\n * Implementation of a Tk image type which provide access to NSImages\n * for use in buttons etc.\n */\n\n/*\n * Forward declarations.\n */\n\ntypedef struct TkMacOSXNSImageInstance TkMacOSXNSImageInstance;\ntypedef struct TkMacOSXNSImageModel TkMacOSXNSImageModel;\n\n/*\n * The following data structure represents a particular use of an nsimage\n * in a widget.\n */\n\nstruct TkMacOSXNSImageInstance {\n    TkMacOSXNSImageModel *modelPtr;   /* Pointer to the model for the image. */\n    NSImage *image;\t\t  /* Pointer to an NSImage.*/\n    TkMacOSXNSImageInstance *nextPtr;   /* First in the list of instances associated\n\t\t\t\t   * with this model. */\n};\n\n/*\n * The following data structure represents the model for an nsimage:\n */\n\nstruct TkMacOSXNSImageModel {\n    Tk_ImageModel tkModel;\t      /* Tk's token for image model. */\n    Tcl_Interp *interp;\t\t      /* Interpreter for application. */\n    int width, height;\t\t      /* Dimensions of the image. */\n    int radius;                       /* Radius for rounded corners. */\n    int ring;                         /* Thickness of the focus ring. */\n    double alpha;                     /* Transparency, between 0.0 and 1.0*/\n    char *imageName;                  /* Malloc'ed image name. */\n    Tcl_Obj *sourceObj;               /* Describing the image. */\n    Tcl_Obj *asObj;                   /* Interpretation of source */\n    int\tflags;\t                      /* Sundry flags, defined below. */\n    bool pressed;                     /* Image is for use in a pressed button.*/\n    bool templ;                       /* Image is for use as a template.*/\n    TkMacOSXNSImageInstance *instancePtr;   /* Start of list of instances associated\n\t\t\t\t       * with this model. */\n    NSImage *image;                   /* The underlying NSImage object. */\n    NSImage *darkModeImage;           /* A modified image to use in Dark Mode. */\n};\n\n/*\n * Bit definitions for the flags field of a TkMacOSXNSImageModel.\n * IMAGE_CHANGED:\t\t1 means that the instances of this image need\n *\t\t\t\tto be redisplayed.\n */\n\n#define IMAGE_CHANGED\t\t1\n\n/*\n * The type record for nsimage images:\n */\n\nstatic int\t\tTkMacOSXNSImageCreate(Tcl_Interp *interp,\n\t\t\t    const char *name, Tcl_Size objc, Tcl_Obj *const objv[],\n\t\t\t    const Tk_ImageType *typePtr, Tk_ImageModel model,\n\t\t\t    void **clientDataPtr);\nstatic void *TkMacOSXNSImageGet(Tk_Window tkwin, void *clientData);\nstatic void\t\tTkMacOSXNSImageDisplay(void *clientData,\n\t\t\t    Display *display, Drawable drawable,\n\t\t\t    int imageX, int imageY, int width,\n\t\t\t    int height, int drawableX,\n\t\t\t    int drawableY);\nstatic void\t\tTkMacOSXNSImageFree(void *clientData, Display *display);\nstatic void\t\tTkMacOSXNSImageDelete(void *clientData);\n\nstatic Tk_ImageType TkMacOSXNSImageType = {\n    \"nsimage\",\t\t\t/* name of image type */\n    TkMacOSXNSImageCreate,\t\t/* createProc */\n    TkMacOSXNSImageGet,\t\t/* getProc */\n    TkMacOSXNSImageDisplay,\t\t/* displayProc */\n    TkMacOSXNSImageFree,\t\t/* freeProc */\n    TkMacOSXNSImageDelete,\t\t/* deleteProc */\n    NULL,\t\t\t/* postscriptPtr */\n    NULL,\t\t\t/* nextPtr */\n    NULL\n};\n\n/*\n * Default values used for parsing configuration specifications:\n */\n#define DEF_SOURCE   \"\"\n#define DEF_AS       \"name\"\n#define DEF_HEIGHT   \"0\"\n#define DEF_WIDTH    \"0\"\n#define DEF_RADIUS   \"0\"\n#define DEF_RING     \"0\"\n#define DEF_ALPHA    \"1.0\"\n#define DEF_PRESSED  \"0\"\n#define DEF_TEMPLATE \"0\"\n\nstatic const Tk_OptionSpec systemImageOptions[] = {\n    {TK_OPTION_STRING, \"-source\", NULL, NULL, DEF_SOURCE,\n     offsetof(TkMacOSXNSImageModel, sourceObj), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_STRING, \"-as\", NULL, NULL, DEF_AS,\n     offsetof(TkMacOSXNSImageModel, asObj), TCL_INDEX_NONE, 0, NULL, 0},\n    {TK_OPTION_INT, \"-width\", NULL, NULL, DEF_WIDTH,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, width), 0, NULL, 0},\n    {TK_OPTION_INT, \"-height\", NULL, NULL, DEF_HEIGHT,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, height), 0, NULL, 0},\n    {TK_OPTION_INT, \"-radius\", NULL, NULL, DEF_RADIUS,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, radius), 0, NULL, 0},\n    {TK_OPTION_INT, \"-ring\", NULL, NULL, DEF_RING,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, ring), 0, NULL, 0},\n    {TK_OPTION_DOUBLE, \"-alpha\", NULL, NULL, DEF_ALPHA,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, alpha), 0, NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-pressed\", NULL, NULL, DEF_PRESSED,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, pressed), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_BOOLEAN, \"-template\", NULL, NULL, DEF_TEMPLATE,\n     TCL_INDEX_NONE, offsetof(TkMacOSXNSImageModel, templ), TK_OPTION_VAR(bool), NULL, 0},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, TCL_INDEX_NONE, TCL_INDEX_NONE, 0, NULL, 0}\n};\n\n/*\n * The -as option specifies how the string provided in the -source\n * option should be interpreted as a description of an NSImage.\n * Below are the possible values and their meanings.  (The last two\n * provide the macOS icon for a particular file type.)\n */\n\nstatic const char *sourceInterpretations[] = {\n    \"name\",       /* A name for a named NSImage. */\n    \"file\",       /* A path to an image file. */\n    \"path\",       /* A path to a file whose type should be examined. */\n    \"filetype\",   /* A file extension or 4-byte OSCode. */\n};\n\nenum {NAME_SOURCE, FILE_SOURCE, PATH_SOURCE, FILETYPE_SOURCE};\n\n\n/*\n *----------------------------------------------------------------------\n *\n * TintImage --\n *\n *      Modify an NSImage by blending it with a color.  The transparent part of\n *      the image remains transparent.  The opaque part of the image is painted\n *      with the color, using the specified alpha value for the transparency of\n *      the color.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe appearance of the NSImage changes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void TintImage(\n    NSImage *image,\n    NSColor *color,\n    double alpha)\n{\n    NSSize size = [image size];\n    NSRect rect = {NSZeroPoint, size};\n    NSImage *mask = [[[NSImage alloc] initWithSize:size] retain];\n    [mask lockFocus];\n    [color set];\n    NSRectFillUsingOperation(rect, NSCompositeCopy);\n    [image drawInRect:rect\n\t     fromRect:rect\n\t    operation:NSCompositeDestinationIn\n\t     fraction:1.0];\n    [mask unlockFocus];\n    [image lockFocus];\n    [mask drawInRect:rect\n\t    fromRect:rect\n\t   operation:NSCompositeSourceOver\n\t    fraction:alpha];\n    [image unlockFocus];\n    [mask release];\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageConfigureModel --\n *\n *\tThis function is called when an nsimage image is created or\n *\treconfigured.  It processes configuration options and resets any\n *\tinstances of the image.\n *\n * Results:\n *\tA standard Tcl return value. If TCL_ERROR is returned then an error\n *\tmessage is left in the modelPtr->interp's result.\n *\n * Side effects:\n *\tExisting instances of the image will be redisplayed to match the new\n *\tconfiguration options.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXNSImageConfigureModel(\n    Tcl_Interp *interp,\t\t   /* Interpreter to use for reporting errors. */\n    TkMacOSXNSImageModel *modelPtr,    /* Pointer to data structure describing\n\t\t\t\t    * overall photo image to (re)configure. */\n    Tcl_Size objc,\t\t\t   /* Number of entries in objv. */\n    Tcl_Obj *const objv[])\t   /* Pairs of configuration options for image. */\n{\n    Tk_OptionTable optionTable = Tk_CreateOptionTable(interp, systemImageOptions);\n    NSImage *newImage;\n    Tcl_Obj *objPtr;\n    static Tcl_Obj *asOption = NULL;\n    int sourceInterpretation;\n    NSString *source;\n    int oldWidth = modelPtr->width, oldHeight = modelPtr->height;\n\n    if (asOption == NULL) {\n\tasOption = Tcl_NewStringObj(\"-as\", TCL_INDEX_NONE);\n\tTcl_IncrRefCount(asOption);\n    }\n\n    modelPtr->width = 0;\n    modelPtr->height = 0;\n    if (Tk_SetOptions(interp, modelPtr, optionTable, objc, objv,\n\t\t      NULL, NULL, NULL) != TCL_OK){\n\tgoto errorExit;\n    }\n    if (modelPtr->width == 0 && modelPtr->height == 0) {\n\tmodelPtr->width = oldWidth;\n\tmodelPtr->height = oldHeight;\n    }\n\n    if (modelPtr->sourceObj == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"-source is required.\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SYSTEM\", \"BAD_VALUE\", (char *)NULL);\n\tgoto errorExit;\n    }\n\n    objPtr = Tk_GetOptionValue(interp, (char *) modelPtr, optionTable,\n\t\t\t\tasOption, NULL);\n    if (Tcl_GetIndexFromObj(interp, objPtr, sourceInterpretations, \"option\",\n\t\t\t    0, &sourceInterpretation) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    \"Unknown interpretation for source in -as option.  \"\n\t    \"Should be name, file, path, or filetype.\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SYSTEM\", \"BAD_VALUE\", (char *)NULL);\n\tgoto errorExit;\n    }\n\n    source = [[NSString alloc] initWithUTF8String: Tcl_GetString(modelPtr->sourceObj)];\n    switch (sourceInterpretation) {\n    case NAME_SOURCE:\n\tnewImage = [[NSImage imageNamed:source] copy];\n\tbreak;\n    case FILE_SOURCE:\n\tnewImage = [[NSImage alloc] initWithContentsOfFile:source];\n\tbreak;\n    case PATH_SOURCE:\n\tnewImage = [[NSWorkspace sharedWorkspace] iconForFile:source];\n\tbreak;\n    case FILETYPE_SOURCE:\n\tnewImage = TkMacOSXIconForFileType(source);\n\tbreak;\n    default:\n\tnewImage = NULL;\n\tbreak;\n    }\n    [source release];\n    if (newImage) {\n\tNSSize size = NSMakeSize(modelPtr->width - 2*modelPtr->ring,\n\t\t\t\t modelPtr->height - 2*modelPtr->ring);\n\t[modelPtr->image release];\n\t[modelPtr->darkModeImage release];\n\tnewImage.size = size;\n\tmodelPtr->image = [newImage retain];\n\tif (modelPtr->templ) {\n\t    newImage.template = YES;\n\t}\n\tmodelPtr->darkModeImage = [[newImage copy] retain];\n\tif ([modelPtr->darkModeImage isTemplate]) {\n\n\t    /*\n\t     * For a template image the Dark Mode version should be white.\n\t     */\n\n\t    NSRect rect = {NSZeroPoint, size};\n\t    [modelPtr->darkModeImage lockFocus];\n\t    [[NSColor whiteColor] set];\n\t    NSRectFillUsingOperation(rect, NSCompositeSourceAtop);\n\t    [modelPtr->darkModeImage unlockFocus];\n\t} else if (modelPtr->pressed) {\n\n\t    /*\n\t     * Non-template pressed images are darker in Light Mode and lighter\n\t     * in Dark Mode.\n\t     */\n\n\t    TintImage(modelPtr->image, [NSColor blackColor], 0.2);\n\t    TintImage(modelPtr->darkModeImage, [NSColor whiteColor], 0.5);\n\t}\n    } else {\n\tswitch(sourceInterpretation) {\n\tcase NAME_SOURCE:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"Unknown named NSImage.\\n\"\n\t\t\"Try omitting ImageName, \"\n\t\t\"e.g. use NSCaution for NSImageNameCaution.\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SYSTEM\", \"BAD_VALUE\", (char *)NULL);\n\t    goto errorExit;\n\tcase FILE_SOURCE:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Failed to load image file.\\n\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SYSTEM\", \"BAD_VALUE\", (char *)NULL);\n\t    goto errorExit;\n\tdefault:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"Unrecognized file type.\\n\"\n\t\t\"If using a filename extension, do not include the dot.\\n\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"IMAGE\", \"SYSTEM\", \"BAD_VALUE\", (char *)NULL);\n\t    goto errorExit;\n\t}\n    }\n\n    /*\n     * Set the width and height.  If only one is specified, set the other one\n     * so as to preserve the aspect ratio.  If neither is specified, match the\n     * size of the image.\n     */\n\n    if (modelPtr->width == 0 && modelPtr->height == 0) {\n\tCGSize size = [modelPtr->image size];\n\tmodelPtr->width = (int) size.width;\n\tmodelPtr->height = (int) size.height;\n    } else {\n\tCGSize size = [modelPtr->image size], newsize;\n\tCGFloat aspect = size.width && size.height ?\n\t     size.height / size.width : 1;\n\tif (modelPtr->width == 0) {\n\t    modelPtr->width = (int) ((CGFloat)(modelPtr->height) / aspect);\n\t} else if (modelPtr->height == 0) {\n\t    modelPtr->height = (int) ((CGFloat)(modelPtr->width) * aspect);\n\t}\n\tnewsize = NSMakeSize(modelPtr->width, modelPtr->height);\n\tmodelPtr->image.size = newsize;\n\tmodelPtr->darkModeImage.size = newsize;\n    }\n\n    /*\n     * Inform the generic image code that the image has (potentially) changed.\n     */\n\n    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,\n\t    modelPtr->height, modelPtr->width, modelPtr->height);\n    modelPtr->flags &= ~IMAGE_CHANGED;\n\n    return TCL_OK;\n\n  errorExit:\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageObjCmd --\n *\n *\tThis function implements the configure and cget commands for an\n *\tnsimage instance.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe image may be reconfigured.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMacOSXNSImageObjCmd(\n    void *clientData,\t/* Information about the image model. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkMacOSXNSImageModel *modelPtr = (TkMacOSXNSImageModel *)clientData;\n    Tk_OptionTable optionTable = Tk_CreateOptionTable(interp, systemImageOptions);\n    static const char *const options[] = {\"cget\", \"configure\", NULL};\n    enum {CGET, CONFIGURE};\n    Tcl_Obj *objPtr;\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    Tcl_Preserve(modelPtr);\n    switch (index) {\n    case CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"option\");\n\t    return TCL_ERROR;\n\t}\n\tobjPtr = Tk_GetOptionValue(interp, (char *)modelPtr, optionTable,\n\t\tobjv[2], NULL);\n\tif (objPtr == NULL) {\n\t    goto error;\n\t}\n\tTcl_SetObjResult(interp, objPtr);\n\tbreak;\n    case CONFIGURE:\n\tif (objc == 2) {\n\t    objPtr = Tk_GetOptionInfo(interp, (char *)modelPtr, optionTable,\n\t\t\t\t     NULL, NULL);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    break;\n\t} else if (objc == 3) {\n\t    objPtr = Tk_GetOptionInfo(interp, (char *)modelPtr, optionTable,\n\t\t\t\t     objv[2], NULL);\n\t    if (objPtr == NULL) {\n\t\tgoto error;\n\t    }\n\t    Tcl_SetObjResult(interp, objPtr);\n\t    break;\n\t} else {\n\t    TkMacOSXNSImageConfigureModel(interp, modelPtr, objc - 2, objv + 2);\n\t    break;\n\t}\n    default:\n\tbreak;\n    }\n\n    Tcl_Release(modelPtr);\n    return TCL_OK;\n\n error:\n    Tcl_Release(modelPtr);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageCreate --\n *\n *\tAllocate and initialize an nsimage model.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tThe data structure for a new image is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXNSImageCreate(\n    Tcl_Interp *interp,\t\t /* Interpreter for application using image. */\n    const char *name,\t\t /* Name to use for image. */\n    Tcl_Size objc,\t\t\t /* Number of arguments. */\n    Tcl_Obj *const objv[],\t /* Argument strings for options (not\n\t\t\t\t  * including image name or type). */\n    TCL_UNUSED(const Tk_ImageType *), /* typePtr */\n    Tk_ImageModel model,\t /* Token for image, to be used in callbacks. */\n    void **clientDataPtr)\t /* Store manager's token for image here; it\n\t\t\t\t  * will be returned in later callbacks. */\n{\n    TkMacOSXNSImageModel *modelPtr;\n    Tk_OptionTable optionTable = Tk_CreateOptionTable(interp, systemImageOptions);\n\n    modelPtr = (TkMacOSXNSImageModel *)Tcl_Alloc(sizeof(TkMacOSXNSImageModel));\n    modelPtr->tkModel = model;\n    modelPtr->interp = interp;\n    modelPtr->imageName = (char *)Tcl_Alloc(strlen(name) + 1);\n    strcpy(modelPtr->imageName, name);\n    modelPtr->flags = 0;\n    modelPtr->instancePtr = NULL;\n    modelPtr->image = NULL;\n    modelPtr->darkModeImage = NULL;\n    modelPtr->sourceObj = NULL;\n    modelPtr->asObj = NULL;\n\n    /*\n     * Process configuration options given in the image create command.\n     */\n\n    if (Tk_InitOptions(interp, (char *) modelPtr, optionTable, NULL) != TCL_OK\n\t|| TkMacOSXNSImageConfigureModel(interp, modelPtr, objc, objv) != TCL_OK) {\n\tTkMacOSXNSImageDelete(modelPtr);\n\treturn TCL_ERROR;\n    }\n    Tcl_CreateObjCommand2(interp, name, TkMacOSXNSImageObjCmd, modelPtr, NULL);\n    *clientDataPtr = modelPtr;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageGet --\n *\n *\tAllocate and initialize an nsimage instance.\n *\n * Results:\n *\tThe return value is a token for the image instance, which is used in\n *\tfuture callbacks to ImageDisplay and ImageFree.\n *\n * Side effects:\n *\tA new new nsimage instance is created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void *\nTkMacOSXNSImageGet(\n    TCL_UNUSED(Tk_Window),      /* tkwin */\n    void *clientData)\t/* Pointer to TkMacOSXNSImageModel for image. */\n{\n    TkMacOSXNSImageModel *modelPtr = (TkMacOSXNSImageModel *) clientData;\n    TkMacOSXNSImageInstance *instPtr;\n\n    instPtr = (TkMacOSXNSImageInstance *)Tcl_Alloc(sizeof(TkMacOSXNSImageInstance));\n    instPtr->modelPtr = modelPtr;\n    return instPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageDisplay --\n *\n *\tDisplay or redisplay an nsimage in the given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe image gets drawn.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXNSImageDisplay(\n    void *clientData,\t/* Pointer to TkMacOSXNSImageInstance for image. */\n    TCL_UNUSED(Display *),      /* display */\n    Drawable drawable,\t\t/* Where to draw or redraw image. */\n    int imageX, int imageY,\t/* Origin of area to redraw, relative to\n\t\t\t\t * origin of image. */\n    int width, int height,\t/* Dimensions of area to redraw. */\n    int drawableX, int drawableY)\n\t\t\t\t/* Coordinates in drawable corresponding to\n\t\t\t\t * imageX and imageY. */\n{\n    MacDrawable *macWin = (MacDrawable *) drawable;\n    Tk_Window tkwin = (Tk_Window) macWin->winPtr;\n    TkMacOSXNSImageInstance *instPtr = (TkMacOSXNSImageInstance *) clientData;\n    TkMacOSXNSImageModel *modelPtr = instPtr->modelPtr;\n    TkMacOSXDrawingContext dc;\n    NSRect dstRect = NSMakeRect(macWin->xOff + drawableX,\n\t\t\t\t macWin->yOff + drawableY, width, height);\n    NSRect srcRect = NSMakeRect(imageX, imageY, width, height);\n    NSImage *image = TkMacOSXInDarkMode(tkwin) ? modelPtr->darkModeImage :\n\tmodelPtr->image;\n    int ring = modelPtr->ring;\n    int radius = modelPtr->radius;\n\n    if (TkMacOSXSetupDrawingContext(drawable, NULL, &dc)) {\n\tif (dc.context) {\n\t    CGRect clipRect = CGRectMake(\n\t\tdstRect.origin.x - srcRect.origin.x + ring,\n\t\tdstRect.origin.y - srcRect.origin.y + ring,\n\t\tmodelPtr->width - 2*ring,\n\t\tmodelPtr->height - 2*ring);\n\t    CGPathRef path = CGPathCreateWithRoundedRect(clipRect, radius, radius, NULL);\n\t    CGContextSaveGState(dc.context);\n\t    CGContextBeginPath(dc.context);\n\t    CGContextAddPath(dc.context, path);\n\t    CGContextClip(dc.context);\n\t    NSGraphicsContext *savedContext = NSGraphicsContext.currentContext;\n\t    NSGraphicsContext.currentContext = [NSGraphicsContext\n\t\tgraphicsContextWithCGContext:dc.context flipped:YES];\n\t    [image drawInRect:clipRect\n\t\t     fromRect:srcRect\n\t\t    operation:NSCompositeSourceOver\n\t\t     fraction:modelPtr->alpha\n\t       respectFlipped:YES\n\t\t\thints:nil];\n\t    CGContextRestoreGState(dc.context);\n\n\t    /*\n\t     * Draw the focus ring.\n\t     */\n\n\t    if (ring) {\n\t\tCGRect ringRect = CGRectInset(clipRect, -ring, -ring);\n\t\tCGPathRef ringPath = CGPathCreateWithRoundedRect(ringRect,\n\t\t    radius + ring, radius + ring, NULL);\n\t\tCGContextSaveGState(dc.context);\n\t\tCGContextAddPath(dc.context, path);\n\t\tCGContextAddPath(dc.context, ringPath);\n\t\tCGContextSetFillColorWithColor(dc.context,\n\t\t\t\t\t       controlAccentColor().CGColor);\n\t\tCGContextEOFillPath(dc.context);\n\t\tCGContextRestoreGState(dc.context);\n\t\tCFRelease(ringPath);\n\t    }\n\t    CFRelease(path);\n\t    NSGraphicsContext.currentContext = savedContext;\n\t}\n\tTkMacOSXRestoreDrawingContext(&dc);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageFree --\n *\n *\tDeallocate an instance of an nsimage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation related to the instance is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXNSImageFree(\n    void *clientData,\t/* Pointer to TkMacOSXNSImageInstance for instance. */\n    TCL_UNUSED(Display *))\t/* display */\n{\n    TkMacOSXNSImageInstance *instPtr = (TkMacOSXNSImageInstance *) clientData;\n    Tcl_Free(instPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImageDelete --\n *\n *\tDeallocate an nsimage model.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\t NSImages are released and memory is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXNSImageDelete(\n    void *clientData)\t/* Pointer to TkMacOSXNSImageModel for image. When\n\t\t\t\t * this function is called, no more instances\n\t\t\t\t * exist. */\n{\n    TkMacOSXNSImageModel *modelPtr = (TkMacOSXNSImageModel *) clientData;\n\n    Tcl_DeleteCommand(modelPtr->interp, modelPtr->imageName);\n    Tcl_Free(modelPtr->imageName);\n    Tcl_DecrRefCount(modelPtr->sourceObj);\n    Tcl_DecrRefCount(modelPtr->asObj);\n    [modelPtr->image release];\n    [modelPtr->darkModeImage release];\n    Tcl_Free(modelPtr);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNSImage_Init --\n *\n *\tAdds the TkMacOSXNSImage type to Tk.\n *\n * Results:\n *\tReturns a standard Tcl completion code, and leaves an error message in\n *\tthe interp's result if an error occurs.\n *\n * Side effects:\n *\tCreates the image create nsrect ...  command.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkMacOSXNSImage_Init(\n    TCL_UNUSED(Tcl_Interp *))\t /* interp */\n{\n    Tk_CreateImageType(&TkMacOSXNSImageType);\n    return 1;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXImage.h",
    "content": "/*\n *  tkMacOSXImage.h --\n *\n *\n *\tThe code in this file provides an interface for XImages, and\n *      implements the nsimage image type.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2017-2021 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Function prototypes\n */\n\nMODULE_SCOPE CFDataRef CreatePDFFromDrawableRect( Drawable drawable,\n\t   int x, int y, unsigned int width, unsigned int height);\n"
  },
  {
    "path": "macosx/tkMacOSXInit.c",
    "content": "/*\n * tkMacOSXInit.c --\n *\n *\tThis file contains Mac OS X -specific interpreter initialization\n *\tfunctions.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2017 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXWm.h\"\n#include <dlfcn.h>\n#include <objc/objc-auto.h>\n#include <sys/stat.h>\n#include <sys/utsname.h>\n\n/*\n * This flag is set if tests are being run.\n */\n\nbool testsAreRunning = false;\n\nstatic char tkLibPath[PATH_MAX + 1] = \"\";\n\n/*\n * If the App is in an App package, then we want to add the Scripts directory\n * to the auto_path.\n */\n\nstatic char scriptPath[PATH_MAX + 1] = \"\";\n\n/*\n * Forward declarations...\n */\n\nstatic Tcl_ObjCmdProc2 TkMacOSXGetAppPathObjCmd;\nstatic Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;\nint TkMacOSXAccessibility_Init(Tcl_Interp *interp);\nstatic Tcl_ObjCmdProc2 TkMacOSXGetInfoAsJSONObjCmd;\n\n#pragma mark TKApplication(TKInit)\n\n@implementation TKApplication\n@synthesize poolLock = _poolLock;\n@synthesize macOSVersion = _macOSVersion;\n@synthesize tkLiveResizeEnded = _tkLiveResizeEnded;\n@synthesize tkWillExit = _tkWillExit;\n@synthesize tkPointerWindow = _tkPointerWindow;\n\n- (void) setTkPointerWindow: (TkWindow *)winPtr\n{\n    if (winPtr) {\n\tTcl_Preserve(winPtr);\n    }\n    if (_tkPointerWindow) {\n\tTcl_Release(_tkPointerWindow);\n    }\n    _tkPointerWindow = winPtr;\n    return;\n}\n@synthesize tkEventTarget = _tkEventTarget;\n- (void) setTkEventTarget: (TkWindow *)winPtr\n{\n    if (winPtr) {\n\tTcl_Preserve(winPtr);\n    }\n    if (_tkEventTarget) {\n\tTcl_Release(_tkEventTarget);\n    }\n    _tkEventTarget = winPtr;\n    return;\n}\n@synthesize tkDragTarget = _tkDragTarget;\n- (void) setTkDragTarget: (TkWindow *)winPtr\n{\n    if (winPtr) {\n\tTcl_Preserve(winPtr);\n    }\n    if (_tkDragTarget) {\n\tTcl_Release(_tkDragTarget);\n    }\n    _tkDragTarget = winPtr;\n    return;\n}\n@synthesize tkButtonState = _tkButtonState;\n@end\n\n/*\n * #define this to see a message on stderr whenever _resetAutoreleasePool is\n * called while the pool is locked.\n */\n#undef DEBUG_LOCK\n\n@implementation TKApplication(TKInit)\n- (void) _resetAutoreleasePool\n{\n    if ([self poolLock] == 0) {\n\t[_mainPool drain];\n\t_mainPool = [NSAutoreleasePool new];\n    } else {\n#ifdef DEBUG_LOCK\n\tfprintf(stderr, \"Pool is locked with count %d!!!!\\n\", [self poolLock]);\n#endif\n    }\n}\n- (void) _lockAutoreleasePool\n{\n    [self setPoolLock:[self poolLock] + 1];\n}\n- (void) _unlockAutoreleasePool\n{\n    [self setPoolLock:[self poolLock] - 1];\n}\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n- (void) _postedNotification: (NSNotification *) notification\n{\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n}\n#endif\n\n- (void) _setupApplicationNotifications\n{\n    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];\n#define observe(n, s) \\\n\t[nc addObserver:self selector:@selector(s) name:(n) object:nil]\n    observe(NSApplicationDidBecomeActiveNotification, applicationActivate:);\n    observe(NSApplicationWillResignActiveNotification, applicationDeactivate:);\n    observe(NSApplicationDidUnhideNotification, applicationShowHide:);\n    observe(NSApplicationDidHideNotification, applicationShowHide:);\n    observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:);\n    observe(NSTextInputContextKeyboardSelectionDidChangeNotification, keyboardChanged:);\n#undef observe\n}\n\n\n/*\n * Fix for 10b38a7a7c.\n */\n\n- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app\n{\n    (void) app;\n    return YES;\n}\n\n-(void)applicationWillFinishLaunching:(NSNotification *)aNotification\n{\n    (void)aNotification;\n\n    /*\n     * Initialize notifications.\n     */\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    [[NSNotificationCenter defaultCenter] addObserver:self\n\t    selector:@selector(_postedNotification:) name:nil object:nil];\n#endif\n    [self _setupWindowNotifications];\n    [self _setupApplicationNotifications];\n\n    if ([NSApp macOSVersion] >= 110000) {\n\n   /*\n    * Initialize Apple Event processing. Apple's docs (see\n    * https://developer.apple.com/documentation/appkit/nsapplication)\n    * recommend doing this here, although historically we have\n    * done this in applicationWillFinishLaunching. In response to\n    * bug 7bb246b072.\n    */\n\n    TkMacOSXInitAppleEvents(_eventInterp);\n\n    }\n}\n\n-(void)applicationDidFinishLaunching:(NSNotification *)notification\n{\n    (void)notification;\n\n   if ([NSApp macOSVersion] < 110000) {\n\n   /*\n    * Initialize Apple Event processing on macOS versions\n    * older than Big Sur (11).\n    */\n\n    TkMacOSXInitAppleEvents(_eventInterp);\n    }\n\n\n    /*\n     * Initialize the graphics context.\n     */\n\n    TkMacOSXUseAntialiasedText(_eventInterp, -1);\n    TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);\n\n    /*\n     * Construct the menu bar.\n     */\n\n    _defaultMainMenu = nil;\n    [self _setupMenus];\n\n    /*\n     * Run initialization routines that depend on the OS version.\n     */\n\n    Ttk_MacOSXInit();\n    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];\n\n    /*\n     * Add an event monitor so we continue to receive NSMouseMoved and\n     * NSMouseDragged events when the mouse moves outside of the key\n     * window. The handler simply returns the events it receives, so\n     * they can be processed in the same way as for other events.\n     */\n\n    [NSEvent addLocalMonitorForEventsMatchingMask:(NSMouseMovedMask |\n\t\t\t\t\t\t   NSLeftMouseDraggedMask)\n\t handler:^NSEvent *(NSEvent *event)\n\t {\n\t     return event;\n\t }];\n}\n\n- (void) _setup: (Tcl_Interp *) interp\n{\n    /*\n     * Remember our interpreter.\n     */\n    _eventInterp = interp;\n\n    /*\n     * Install the global autoreleasePool.\n     */\n    _mainPool = [NSAutoreleasePool new];\n    [NSApp setPoolLock:0];\n\n    /*\n     * Record the OS version we are running on.\n     */\n\n    int minorVersion, majorVersion;\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000\n    Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);\n    majorVersion = 10;\n#else\n    NSOperatingSystemVersion systemVersion;\n    systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];\n    majorVersion = (int)systemVersion.majorVersion;\n    minorVersion = (int)systemVersion.minorVersion;\n#endif\n\n    if (majorVersion == 10 && minorVersion == 16) {\n\n\t/*\n\t * If a program compiled with a macOS 10.XX SDK is run on macOS 11.0 or\n\t * later then it will report majorVersion 10 and minorVersion 16, no\n\t * matter what the actual OS version of the host may be. And of course\n\t * Apple never released macOS 10.16. To work around this we guess the\n\t * OS version from the kernel release number, as reported by uname.\n\t */\n\n\tstruct utsname name;\n\tchar *endptr;\n\tif (uname(&name) == 0) {\n\t    majorVersion = (int)strtol(name.release, &endptr, 10) + 1;\n\t    if (majorVersion < 26) {\n\t\tmajorVersion -= 10;\n\t    }\n\t    minorVersion = 0;\n\t}\n    }\n    [NSApp setMacOSVersion: 10000*majorVersion + 100*minorVersion];\n\n    /*\n     * Be our own delegate.\n     */\n\n    [self setDelegate:self];\n\n    /*\n     * If no icon has been set from an Info.plist file, use the Wish icon from\n     * the Tk framework.\n     */\n\n    NSString *iconFile = [[NSBundle mainBundle] objectForInfoDictionaryKey:\n\t\t\t\t\t\t    @\"CFBundleIconFile\"];\n    if (!iconFile) {\n\tNSString *path = [NSApp tkFrameworkImagePath:@\"Tk.icns\"];\n\tif (path) {\n\t    NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];\n\t    if (image) {\n\t\t[image setName:@\"NSApplicationIcon\"];\n\t\t[NSApp setApplicationIconImage:image];\n\t\t[image release];\n\t    }\n\t}\n    }\n}\n\n- (NSString *) tkFrameworkImagePath: (NSString *) image\n{\n    NSString *path = nil;\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n    if (tkLibPath[0] != '\\0') {\n\tpath = [[NSBundle bundleWithPath:[[NSString stringWithUTF8String:\n\t\ttkLibPath] stringByAppendingString:@\"/../..\"]]\n\t\tpathForImageResource:image];\n    }\n    if (!path) {\n\tconst char *tk_library = Tcl_GetVar2(_eventInterp, \"tk_library\", NULL,\n\t\tTCL_GLOBAL_ONLY);\n\n\tif (tk_library) {\n\t    NSFileManager *fm = [NSFileManager defaultManager];\n\n\t    path = [[NSString stringWithUTF8String:tk_library]\n\t\t    stringByAppendingFormat:@\"/%@\", image];\n\t    if (![fm isReadableFileAtPath:path]) {\n\t\tpath = [[NSString stringWithUTF8String:tk_library]\n\t\t\tstringByAppendingFormat:@\"/../macosx/%@\", image];\n\t\tif (![fm isReadableFileAtPath:path]) {\n\t\t    path = nil;\n\t\t}\n\t    }\n\t}\n    }\n#ifdef TK_MAC_DEBUG\n    if (!path && getenv(\"TK_SRCROOT\")) {\n\tpath = [[NSString stringWithUTF8String:getenv(\"TK_SRCROOT\")]\n\t\tstringByAppendingFormat:@\"/macosx/%@\", image];\n\tif (![[NSFileManager defaultManager] isReadableFileAtPath:path]) {\n\t    path = nil;\n\t}\n    }\n#endif\n    [path retain];\n    [pool drain];\n    return path;\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpInit --\n *\n *\tPerforms Mac-specific interpreter initialization related to the\n *\ttk_library variable.\n *\n * Results:\n *\tReturns a standard Tcl result. Leaves an error message or result in\n *\tthe interp's result.\n *\n * Side effects:\n *\tSets \"tk_library\" Tcl variable, runs \"tk.tcl\" script.\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * Helper function which closes the shared NSFontPanel and NSColorPanel.\n */\n\nstatic void closePanels(\n    void)\n{\n    if ([NSFontPanel sharedFontPanelExists]) {\n\t[[NSFontPanel sharedFontPanel] orderOut:nil];\n    }\n    if ([NSColorPanel sharedColorPanelExists]) {\n\t[[NSColorPanel sharedColorPanel] orderOut:nil];\n    }\n}\n\n/*\n * This custom exit procedure is called by Tcl_Exit in place of the exit\n * function from the C runtime.  It calls the terminate method of the\n * NSApplication class (superTerminate for a TKApplication).  The purpose of\n * doing this is to ensure that the NSFontPanel and the NSColorPanel are closed\n * before the process exits, and that the application state is recorded\n * correctly for all termination scenarios.\n *\n * TkpWantsExitProc tells Tcl_AppInit whether to install our custom exit proc,\n * which terminates the process by calling [NSApplication terminate].  This\n * does not work correctly if the process is part of an exec pipeline, so it is\n * only done if the process was launched by the launcher or if both stdin and\n * stdout are ttys.  To disable using the custom exit proc altogether, undefine\n * USE_CUSTOM_EXIT_PROC.\n */\n\n#if defined(USE_CUSTOM_EXIT_PROC)\nstatic bool doCleanupFromExit = false;\n\nint TkpWantsExitProc(void) {\n    return doCleanupFromExit;\n}\n\nTCL_NORETURN void TkpExitProc(\n    void *clientdata)\n{\n    bool doCleanup = doCleanupFromExit;\n    if (doCleanupFromExit) {\n\tdoCleanupFromExit = false; /* prevent possible recursive call. */\n\tclosePanels();\n    }\n\n    /*\n     * At this point it is too late to be looking up the Tk window associated\n     * to any NSWindows, but it can happen.  This makes sure the answer is None\n     * if such a query is attempted.  It is also too late to be running any\n     * event loops, as happens in updateLayer.  Set the tkWillExit flag to\n     * prevent this.\n     */\n\n    [NSApp setTkWillExit:YES];\n    for (TKWindow *w in [NSApp orderedWindows]) {\n\tif ([w respondsToSelector: @selector (tkWindow)]) {\n\t    [w setTkWindow: None];\n\t}\n    }\n\n    /*\n     * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.\n     */\n\n    Tcl_Finalize();\n    if (doCleanup == YES) {\n\t[(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */\n    }\n    exit((int)PTR2INT(clientdata)); /* Convince the compiler that we don't return. */\n}\n#endif\n\n/*\n * This signal handler is installed for the SIGINT, SIGHUP and SIGTERM signals\n * so that normal finalization occurs when a Tk app is killed by one of these\n * signals (e.g when ^C is pressed while running Wish in the shell).  It calls\n * Tcl_Exit instead of the C runtime exit function called by the default handler.\n * This is consistent with the Tcl_Exit manual page, which says that Tcl_Exit\n * should always be called instead of exit.  When Tk is killed by a signal we\n * return exit status 1.\n */\n\nstatic void TkMacOSXSignalHandler(TCL_UNUSED(int)) {\n\n    Tcl_Exit(1);\n}\n\n/*\n * This static function is run as an idle task to order the root window front.\n * This is only done if the window is in the normal state.  This avoids\n * flashing the root window on the screen if it was withdrawn immediately after\n * loading Tk.\n */\n\nstatic void showRootWindow(void *clientData) {\n    NSWindow *root = (NSWindow *) clientData;\n    if ([NSApp tkWillExit]) {\n\treturn;\n    }\n    TkWindow *winPtr = TkMacOSXGetTkWindow(root);\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr->hints.initial_state == NormalState) {\n\t[root makeKeyAndOrderFront:NSApp];\n    }\n    [NSApp activateIgnoringOtherApps: YES];\n}\n\nint\nTkpInit(\n    Tcl_Interp *interp)\n{\n    static bool initialized = false;\n\n    /*\n     * TkpInit can be called multiple times with different interpreters. But\n     * The application initialization should only be done once.\n     */\n\n    if (!initialized) {\n\tstruct stat st;\n\tbool shouldOpenConsole = false;\n\tbool stdinIsNullish = (!isatty(0) &&\n\t    (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)));\n\n\t/*\n\t * Initialize/check OS version variable for runtime checks.\n\t */\n\n#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090\n#   error Mac OS X 10.9 required\n#endif\n\n\tinitialized = true;\n\n#ifdef TK_FRAMEWORK\n\n\t/*\n\t * When Tk is in a framework, force tcl_findLibrary to look in the\n\t * framework scripts directory.\n\t * FIXME: Should we come up with a more generic way of doing this?\n\t */\n\n\tif (Tcl_MacOSXOpenVersionedBundleResources(interp,\n\t\t\"com.tcltk.tklibrary\", TK_FRAMEWORK_VERSION, 0, PATH_MAX,\n\t\ttkLibPath) != TCL_OK) {\n\t    # if 0 /* This is not really an error.  Wish still runs fine. */\n\t    TkMacOSXDbgMsg(\"Tcl_MacOSXOpenVersionedBundleResources failed\");\n\t    # endif\n\t}\n#endif\n\n\t/*\n\t * Instantiate our NSApplication object. This needs to be done before\n\t * we check whether to open a console window.\n\t */\n\n\tNSAutoreleasePool *pool = [NSAutoreleasePool new];\n\t[[NSUserDefaults standardUserDefaults] registerDefaults:\n\t\t[NSDictionary dictionaryWithObjectsAndKeys:\n\t\t\t\t  [NSNumber numberWithBool:YES],\n\t\t\t      @\"_NSCanWrapButtonTitles\",\n\t\t\t\t   [NSNumber numberWithInt:-1],\n\t\t\t      @\"NSStringDrawingTypesetterBehavior\",\n\t\t\t      nil]];\n\t[TKApplication sharedApplication];\n\t[pool drain];\n\n\t/*\n\t * WARNING: The finishLaunching method runs asynchronously. This\n\t * creates a race between the initialization of the NSApplication and\n\t * the initialization of Tk.  If Tk wins the race bad things happen\n\t * with the root window (see below).  If the NSApplication wins then an\n\t * AppleEvent created during launch, e.g. by dropping a file icon on\n\t * the application icon, will be delivered before the procedure meant\n\t * to to handle the AppleEvent has been defined.  This is handled in\n\t * tkMacOSXHLEvents.c by scheduling a timer event to handle the\n\t * AppleEvent later, after the required procedure has been defined.\n\t */\n\n\t[NSApp _setup:interp];\n\t[NSApp finishLaunching];\n\n\t/*\n\t * Create a Tk event source based on the Appkit event queue.\n\t */\n\n\tTk_MacOSXSetupTkNotifier();\n\n\t/*\n\t * If Tk initialization wins the race, the root window is mapped before\n\t * the NSApplication is initialized.  This can cause bad things to\n\t * happen.  The root window can open off screen with no way to make it\n\t * appear on screen until the app icon is clicked.  This will happen if\n\t * a Tk application opens a modal window in its startup script (see\n\t * ticket 56a1823c73).  In other cases, an empty root window can open\n\t * on screen and remain visible for a noticeable amount of time while\n\t * the Tk initialization finishes (see ticket d1989fb7cf).  The call\n\t * below forces Tk to block until the Appkit event queue has been\n\t * created.  This seems to be sufficient to ensure that the\n\t * NSApplication initialization wins the race, avoiding these bad\n\t * window behaviors.\n\t */\n\n\tTcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);\n\n\t/*\n\t * Decide whether to open a console window.  If the TK_CONSOLE\n\t * environment variable is not defined we only show the console if\n\t * stdin is not a tty and there is no startup script.\n\t */\n\n\tif (getenv(\"TK_CONSOLE\")) {\n\t    shouldOpenConsole = true;\n\t} else if (stdinIsNullish && Tcl_GetStartupScript(NULL) == NULL) {\n\t    const char *intvar = Tcl_GetVar2(interp, \"tcl_interactive\",\n\t\t\t\t\t     NULL, TCL_GLOBAL_ONLY);\n\t    if (intvar == NULL) {\n\t\tTcl_SetVar2(interp, \"tcl_interactive\", NULL, \"1\",\n\t\t\t    TCL_GLOBAL_ONLY);\n\t    }\n\n#if defined(USE_CUSTOM_EXIT_PROC)\n\t    doCleanupFromExit = true;\n#endif\n\n\t    shouldOpenConsole = true;\n\t}\n\tif (shouldOpenConsole) {\n\t    Tk_InitConsoleChannels(interp);\n\t    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));\n\t    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));\n\t    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));\n\t    if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {\n\t\treturn TCL_ERROR;\n\t    }\n\t} else if (stdinIsNullish) {\n\n\t    /*\n\t     * When launched as a macOS application with no console,\n\t     * redirect stderr and stdout to /dev/null. This avoids waiting\n\t     * forever for those files to become writable if the underlying\n\t     * Tcl program tries to write to them with a puts command.\n\t     */\n\n\t    FILE *null = fopen(\"/dev/null\", \"w\");\n\t    dup2(fileno(null), STDOUT_FILENO);\n\t    dup2(fileno(null), STDERR_FILENO);\n#if defined(USE_CUSTOM_EXIT_PROC)\n\t    doCleanupFromExit = true;\n#endif\n\t} else if (getenv(\"TK_NO_STDERR\") != NULL) {\n\t    FILE *null = fopen(\"/dev/null\", \"w\");\n\t    dup2(fileno(null), STDERR_FILENO);\n\t}\n\n\t/*\n\t * FIXME: Close stdin & stdout for remote debugging if XCNOSTDIN is\n\t * set.  Otherwise we will fight with gdb for stdin & stdout\n\t */\n\n\tif (getenv(\"XCNOSTDIN\") != NULL) {\n\t    close(0);\n\t    close(1);\n\t}\n\n\t/*\n\t * Now we can run initialization routines which require that both the\n\t * NSApplication and the Tcl interpreter have been created and\n\t * initialized.\n\t */\n\n\tTkMacOSXServices_Init(interp);\n\tTkMacOSXNSImage_Init(interp);\n\tTkMacOSXAccessibility_Init(interp);\n\n\t/*\n\t * The root window has been created and mapped, but XMapWindow deferred its\n\t * call to makeKeyAndOrderFront because the first call to XMapWindow\n\t * occurs too early in the initialization process for that.  Process idle\n\t * tasks now, so the root window is configured.\n\t */\n\n\twhile(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {};\n\n\tfor (NSWindow *window in [NSApp windows]) {\n\t    TkWindow *winPtr = TkMacOSXGetTkWindow(window);\n\t    if (winPtr && Tk_IsMapped(winPtr)) {\n\n\t\t/*\n\t\t * Ordering the root window front in an idle task allows\n\t\t * checking whether it was immediately withdrawn, and\n\t\t * therefore does not need to be placed on the screen.\n\t\t */\n\n\t\tTcl_DoWhenIdle(showRootWindow, window);\n\t\tbreak;\n\t    }\n\t}\n\n# if defined(USE_CUSTOM_EXIT_PROC)\n\n\tif ((isatty(0) && isatty(1))) {\n\t    doCleanupFromExit = true;\n\t}\n\n# endif\n\n\t/*\n\t * Install a signal handler for SIGINT, SIGHUP and SIGTERM which uses\n\t * Tcl_Exit instead of exit so that normal cleanup takes place if a TK\n\t * application is killed with one of these signals.\n\t */\n\n\tsignal(SIGINT, TkMacOSXSignalHandler);\n\tsignal(SIGHUP, TkMacOSXSignalHandler);\n\tsignal(SIGTERM, TkMacOSXSignalHandler);\n    }\n    /*\n     * Initialization steps that are needed for all interpreters.\n     */\n\n    if (tkLibPath[0] != '\\0') {\n\tTcl_SetVar2(interp, \"tk_library\", NULL, tkLibPath, TCL_GLOBAL_ONLY);\n    }\n    if (scriptPath[0] != '\\0') {\n\tTcl_SetVar2(interp, \"auto_path\", NULL, scriptPath,\n\t\tTCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE);\n    }\n    Tcl_CreateObjCommand2(interp, \"nsimage\",\n\t    TkMacOSXNSImageObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::mac::standardAboutPanel\",\n\t    TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::mac::iconBitmap\",\n\t    TkMacOSXIconBitmapObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::mac::GetAppPath\",\n\t    TkMacOSXGetAppPathObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::mac::GetInfoAsJSON\",\n\t    TkMacOSXGetInfoAsJSONObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::mac::macOSVersion\",\n\t    TkMacOSVersionObjCmd, NULL, NULL);\n    MacSystrayInit(interp);\n    MacPrint_Init(interp);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetAppPathObjCmd --\n *\n *\tReturns the path of the Wish application bundle.\n *\n * Results:\n *\tReturns the application path.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXGetAppPathObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Get the application path URL and convert it to a string path reference.\n     */\n\n    CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());\n    CFStringRef appPath =\n\t    CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);\n\n    /*\n     * Convert (and copy) the string reference into a Tcl result.\n     */\n\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    CFStringGetCStringPtr(appPath, CFStringGetSystemEncoding()), TCL_INDEX_NONE));\n\n    CFRelease(mainBundleURL);\n    CFRelease(appPath);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetAppName --\n *\n *\tRetrieves the name of the current application from a platform specific\n *\tlocation. For Unix, the application name is the tail of the path\n *\tcontained in the tcl variable argv0.\n *\n * Results:\n *\tReturns the application name in the given Tcl_DString.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetAppName(\n    Tcl_Interp *interp,\n    Tcl_DString *namePtr)\t/* A previously initialized Tcl_DString. */\n{\n    const char *p, *name;\n\n    name = Tcl_GetVar2(interp, \"argv0\", NULL, TCL_GLOBAL_ONLY);\n    if ((name == NULL) || (*name == 0)) {\n\tname = \"tk\";\n    } else {\n\tp = strrchr(name, '/');\n\tif (p != NULL) {\n\t    name = p+1;\n\t}\n    }\n    Tcl_DStringAppend(namePtr, name, TCL_INDEX_NONE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSVersionObjCmd --\n *\n *\tTcl command which returns an integer encoding the major and minor\n *\tversion numbers of the currently running operating system in the\n *\tform 10000*majorVersion + 100*minorVersion.\n *\n * Results:\n *\tReturns the OS version.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\f\nstatic int\nTkMacOSVersionObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    static char version[16] = \"\";\n    if (objc > 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    if (version[0] == '\\0') {\n\tsnprintf(version, 16, \"%d\", [NSApp macOSVersion]);\n    }\n    Tcl_SetResult(interp, version, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetInfoAsJSONObjCmd --\n *\n *\tReturns the contents of the Info.plist file in the application\n *      bundle as a JSON-encoded Tcl string.\n *\n * Results:\n *\tReturns the JSON encoding of the Info.plist file..\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXGetInfoAsJSONObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    static char *bytes = NULL;\n\n    if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (bytes == NULL) {\n\tNSJSONWritingOptions opt = NSJSONWritingPrettyPrinted;\n\tNSDictionary<NSString *, id> *infoDict = [[NSBundle mainBundle]\n\t\t\t\t\t\t     infoDictionary];\n\tNSData *infoAsJSON = [NSJSONSerialization\n\t\t\t\t dataWithJSONObject: infoDict\n\t\t\t\t\t    options:opt\n\t\t\t\t\t      error:nil];\n\tif (infoAsJSON.length) {\n\t    int buffer_size = (int) infoAsJSON.length + 1;\n\t    bytes = (char *)malloc(buffer_size);\n\t    strlcpy(bytes, (char *)infoAsJSON.bytes, buffer_size);\n\t}\n    }\n    if (bytes) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(bytes, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayWarning --\n *\n *\tThis routines is called from Tk_Main to display warning messages that\n *\toccur during startup.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates messages on stdout.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayWarning(\n    const char *msg,\t\t/* Message to be displayed. */\n    const char *title)\t\t/* Title of warning. */\n{\n    Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);\n\n    if (errChannel) {\n\tTcl_WriteChars(errChannel, title, TCL_INDEX_NONE);\n\tTcl_WriteChars(errChannel, \": \", 2);\n\tTcl_WriteChars(errChannel, msg, TCL_INDEX_NONE);\n\tTcl_WriteChars(errChannel, \"\\n\", 1);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXDefaultStartupScript --\n *\n *\tOn MacOS X, we look for a file in the Resources/Scripts directory\n *\tcalled AppMain.tcl and if found, we set argv[1] to that, so that the\n *\trest of the code will find it, and add the Scripts folder to the\n *\tauto_path. If we don't find the startup script, we just bag it,\n *\tassuming the user is starting up some other way.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTcl_SetStartupScript() called when AppMain.tcl found.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE void\nTkMacOSXDefaultStartupScript(void)\n{\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n    CFBundleRef bundleRef = CFBundleGetMainBundle();\n\n    if (bundleRef != NULL) {\n\tCFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,\n\t\tCFSTR(\"AppMain\"), CFSTR(\"tcl\"), CFSTR(\"Scripts\"));\n\n\tif (appMainURL != NULL) {\n\t    CFURLRef scriptFldrURL;\n\t    char startupScript[PATH_MAX + 1];\n\n\t    if (CFURLGetFileSystemRepresentation(appMainURL, true,\n\t\t    (unsigned char *) startupScript, PATH_MAX)) {\n\t\tTcl_SetStartupScript(Tcl_NewStringObj(startupScript, TCL_INDEX_NONE), NULL);\n\t\tscriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL,\n\t\t\tappMainURL);\n\t\tif (scriptFldrURL != NULL) {\n\t\t    CFURLGetFileSystemRepresentation(scriptFldrURL, true,\n\t\t\t    (unsigned char *) scriptPath, PATH_MAX);\n\t\t    CFRelease(scriptFldrURL);\n\t\t}\n\t    }\n\t    CFRelease(appMainURL);\n\t}\n    }\n    [pool drain];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNamedSymbol --\n *\n *\tDynamically acquire address of a named symbol from a loaded dynamic\n *\tlibrary, so that we can use API that may not be available on all OS\n *\tversions.\n *\n * Results:\n *\tAddress of given symbol or NULL if unavailable.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE void*\nTkMacOSXGetNamedSymbol(\n    TCL_UNUSED(const char *),\n    const char *symbol)\n{\n    void *addr = dlsym(RTLD_NEXT, symbol);\n\n    if (!addr) {\n\t(void) dlerror(); /* Clear dlfcn error state */\n    }\n    return addr;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXInt.h",
    "content": "/*\n * tkMacOSXInt.h --\n *\n *\tDeclarations of Macintosh specific shared variables and procedures.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACINT\n#define _TKMACINT\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Include platform specific public interfaces.\n */\n\n#ifndef _TKMAC\n#include \"tkMacOSX.h\"\n#define Cursor QDCursor\n#import <Cocoa/Cocoa.h>\n#undef Cursor\n#endif\n\n/*\n * Define compatibility platform types used in the structures below so that\n * this header can be included without pulling in the platform headers.\n */\n\n#ifndef _TKMACPRIV\n#   ifndef CGGEOMETRY_H_\n#\tifndef CGFLOAT_DEFINED\n#\t    if __LP64__\n#\t\tdefine CGFloat double\n#\t    else\n#\t\tdefine CGFloat float\n#\t    endif\n#\tendif\n#\tdefine CGSize struct {CGFloat width; CGFloat height;}\n#   endif\n#   ifndef CGCONTEXT_H_\n#\tdefine CGContextRef void *\n#   endif\n#   ifndef CGCOLOR_H_\n#\tdefine CGColorRef void *\n#   endif\n#   ifndef __HISHAPE__\n#\tdefine HIShapeRef void *\n#   endif\n#   ifndef _APPKITDEFINES_H\n#\tdefine NSView void *\n#   endif\n#endif\n\nstruct TkWindowPrivate {\n    TkWindow *winPtr;\t\t/* Ptr to tk window or NULL if Pixmap */\n    NSView *view;\n    CGContextRef context;\n    int xOff;\t\t\t/* X offset from toplevel window */\n    int yOff;\t\t\t/* Y offset from toplevel window */\n    CGSize size;\n    HIShapeRef visRgn;\t\t/* Visible region of window */\n    HIShapeRef aboveVisRgn;\t/* Visible region of window & its children */\n    HIShapeRef drawRgn;\t\t/* Clipped drawing region */\n    int referenceCount;\t\t/* Don't delete toplevel until children are\n\t\t\t\t * gone. */\n    struct TkWindowPrivate *toplevel;\n\t\t\t\t/* Pointer to the toplevel datastruct. */\n    CGFloat fillRGBA[4];        /* Background used by the ttk FillElement */\n    int flags;\t\t\t/* Various state see defines below. */\n};\ntypedef struct TkWindowPrivate MacDrawable;\n\n/*\n * Defines use for the flags field of the MacDrawable data structure.\n */\n\n#define TK_SCROLLBAR_GROW\t0x01\n#define TK_CLIP_INVALID\t\t0x02\n#define TK_HOST_EXISTS\t\t0x04\n#define TK_DRAWN_UNDER_MENU\t0x08\n#define TK_IS_PIXMAP\t\t0x10\n#define TK_IS_BW_PIXMAP\t\t0x20\n#define TTK_HAS_CONTRASTING_BG  0x80\n\n/*\n * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags\n * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the\n * TkWindow structure for the window, but in the MacWin. This way we can\n * still tell what the correct port is after the TKWindow structure has been\n * freed. This actually happens when you bind destroy of a toplevel to\n * Destroy of a child.\n */\n\n/*\n * Undef compatibility platform types defined above.\n */\n\n#ifndef _TKMACPRIV\n#   ifndef CGGEOMETRY_H_\n#\tifndef CGFLOAT_DEFINED\n#\t    undef CGFloat\n#\tendif\n#\tundef CGSize\n#   endif\n#   ifndef CGCONTEXT_H_\n#\tundef CGContextRef\n#   endif\n#   ifndef CGCOLOR_H_\n#\tundef CGColorRef\n#   endif\n#   ifndef __HISHAPE__\n#\tundef HIShapeRef\n#   endif\n#   ifndef _APPKITDEFINES_H\n#\tundef NSView\n#   endif\n#endif\n\n/*\n * Defines used for TkMacOSXInvalidateWindow\n */\n\n#define TK_WINDOW_ONLY 0\n#define TK_PARENT_WINDOW 1\n\n/*\n * Accessor for the privatePtr flags field for the TK_HOST_EXISTS field\n */\n\n#define TkMacOSXHostToplevelExists(tkwin) \\\n    (((TkWindow *) (tkwin))->privatePtr->toplevel->flags & TK_HOST_EXISTS)\n\n/*\n * Defines used for the flags argument to TkGenWMConfigureEvent.\n */\n\n#define TK_LOCATION_CHANGED\t1\n#define TK_SIZE_CHANGED\t\t2\n#define TK_BOTH_CHANGED\t\t3\n#define TK_MACOSX_HANDLE_EVENT_IMMEDIATELY 1024\n\n/*\n * Defines for tkTextDisp.c and tkFont.c\n */\n\n#define TK_LAYOUT_WITH_BASE_CHUNKS\t1\n#define TK_DRAW_IN_CONTEXT\t\t1\n\n/*\n * Prototypes of internal procs not in the stubs table.\n */\n\nMODULE_SCOPE void TkMacOSXDefaultStartupScript(void);\nMODULE_SCOPE Bool TkTestLogDisplay(Drawable drawable);\nMODULE_SCOPE void TkMacOSXInvalidateWindow(MacDrawable *macWin, int flag);\nMODULE_SCOPE void TkMacOSXMakeRealWindowExist(TkWindow *winPtr);\nMODULE_SCOPE void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag);\n\n/*\n * Include the stubbed internal platform-specific API.\n */\n\n#include \"tkIntPlatDecls.h\"  /* IWYU pragma: export */\n\n#endif /* _TKMACINT */\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXKeyEvent.c",
    "content": "/*\n * tkMacOSXKeyEvent.c --\n *\n *\tThis file implements functions that decode & handle keyboard events on\n *\tMacOS X.\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2012 Adrian Robert.\n * Copyright © 2015-2020 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXWm.h\"\n\n/*\n * See tkMacOSXPrivate.h for macros related to key event processing.\n */\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_KEYBOARD\n#endif\n*/\n\n#define NS_KEYLOG 0\n#define XEVENT_MOD_MASK (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask)\nstatic Tk_Window keyboardGrabWinPtr = NULL; /* Current keyboard grab window. */\nstatic NSWindow *keyboardGrabNSWindow = nil; /* Its underlying NSWindow.*/\nstatic NSModalSession modalSession = nil;\nstatic BOOL processingCompose = NO;\nstatic Tk_Window composeWin = NULL;\nstatic int caret_x = 0, caret_y = 0, caret_height = 0;\nstatic void setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers);\nstatic void setXEventPoint(XEvent *xEvent, Tk_Window tkwin, NSWindow *w);\nstatic NSUInteger textInputModifiers;\n\n#pragma mark TKApplication(TKKeyEvent)\n\n@implementation TKApplication(TKKeyEvent)\n\n- (NSEvent *) tkProcessKeyEvent: (NSEvent *) theEvent\n{\n#ifdef TK_MAC_DEBUG_EVENTS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), theEvent);\n#endif\n    NSWindow *w = [theEvent window];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w), *grabWinPtr, *focusWinPtr;\n    Tk_Window tkwin = (Tk_Window)winPtr;\n    NSEventType type = [theEvent type];\n    NSUInteger virt = [theEvent keyCode];\n    NSUInteger modifiers = ([theEvent modifierFlags] &\n\t\t\t    NSDeviceIndependentModifierFlagsMask);\n    XEvent xEvent;\n    MacKeycode macKC;\n    UniChar keychar = 0;\n    Bool can_input_text, has_modifiers = NO, use_text_input = NO;\n    static NSUInteger savedModifiers = 0;\n    static NSMutableArray *nsEvArray = nil;\n\n    if (nsEvArray == nil) {\n\tnsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];\n\tprocessingCompose = NO;\n    }\n    if (!winPtr) {\n\treturn theEvent;\n    }\n\n    /*\n     * Discard repeating KeyDown events if the repeat speed has been set to\n     * \"off\" in System Preferences.  It is unclear why we get these, but we do.\n     * See ticket [2ecb09d118].\n     */\n\n    if ([theEvent type] ==  NSKeyDown &&\n\t[theEvent isARepeat] &&\n\t[NSEvent keyRepeatDelay] < 0) {\n\t    return theEvent;\n\t}\n\n    /*\n     * If a local grab is in effect, key events for windows in the\n     * grabber's application are redirected to the grabber.  Key events\n     * for other applications are delivered normally.  If a global\n     * grab is in effect all key events are redirected to the grabber.\n     */\n\n    grabWinPtr = winPtr->dispPtr->grabWinPtr;\n    if (grabWinPtr) {\n\tif (winPtr->dispPtr->grabFlags ||  /* global grab */\n\t    grabWinPtr->mainPtr == winPtr->mainPtr){ /* same application */\n\t    winPtr = winPtr->dispPtr->focusPtr;\n\t    if (!winPtr) {\n\t\treturn theEvent;\n\t    }\n\t    tkwin = (Tk_Window)winPtr;\n\t}\n    }\n\n    /*\n     * Extract the unicode character from KeyUp and KeyDown events.\n     */\n\n    if (type == NSKeyUp || type == NSKeyDown) {\n\tNSString *characters = [theEvent characters];\n\tif (characters.length > 0) {\n\t    keychar = [characters characterAtIndex:0];\n\n\t    /*\n\t     * Currently, real keys always send BMP characters, but who knows?\n\t     */\n\n\t    if (CFStringIsSurrogateHighCharacter(keychar)) {\n\t\tUniChar lowChar = [characters characterAtIndex:1];\n\t\tkeychar = CFStringGetLongCharacterForSurrogatePair(\n\t\t    keychar, lowChar);\n\t    }\n\t} else {\n\n\t    /*\n\t     * This is a dead key, such as Option-e, so it usually should get\n\t     * passed to the TextInputClient.  But if it has a Command modifier\n\t     * then it is not functioning as a dead key and should not be\n\t     * handled by the TextInputClient.  See ticket [1626ed65b8] and the\n\t     * method performKeyEquivalent which is implemented in\n\t     * tkMacOSXMenu.c.\n\t     */\n\n\t    if (!(modifiers & NSCommandKeyMask)) {\n\t\tuse_text_input = YES;\n\t    }\n\t}\n\n\t/*\n\t * Apple uses 0x10 for unrecognized keys.\n\t */\n\n\tif (keychar == 0x10) {\n\t    keychar = UNKNOWN_KEYCHAR;\n\t}\n\n#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1\n\tTKLog(@\"-[%@(%p) %s] repeat=%d mods=%x char=%x code=%lu c=%d type=%d\",\n\t      [self class], self, sel_getName(_cmd),\n\t      (type == NSKeyDown) && [theEvent isARepeat], modifiers, keychar,\n\t      virt, w, type);\n#endif\n\n    }\n\n    /*\n     * Build a skeleton XEvent.  We need to build it here, even if we will not\n     * send it, so we can pass it to TkFocusKeyEvent to determine whether the\n     * target widget can input text.\n     */\n\n    setupXEvent(&xEvent, tkwin, modifiers);\n    has_modifiers = xEvent.xkey.state & XEVENT_MOD_MASK;\n    focusWinPtr = TkFocusKeyEvent(winPtr, &xEvent);\n    if (focusWinPtr == NULL) {\n\tTKContentView *contentView = [w contentView];\n\n\t/*\n\t * This NSEvent is being sent to a window which does not have focus.\n\t * This could mean, for example, that the user deactivated the Tk app\n\t * while the NSTextInputClient's popup character selection window was\n\t * still open.  We attempt to abandon any ongoing composition operation\n\t * and discard the event.\n\t */\n\n\t[contentView cancelComposingText];\n\treturn theEvent;\n    }\n    can_input_text = ((focusWinPtr->flags & TK_CAN_INPUT_TEXT) != 0);\n\n#if (NS_KEYLOG)\n    TKLog(@\"keyDown: %s compose sequence.\\n\",\n\t  processingCompose == YES ? \"Continue\" : \"Begin\");\n#endif\n\n    /*\n     * Decide whether this event should be processed with the NSTextInputClient\n     * protocol.\n     */\n\n    if (processingCompose ||\n\t(type == NSKeyDown && can_input_text && !has_modifiers &&\n\t IS_PRINTABLE(keychar))\n\t) {\n\tuse_text_input = YES;\n    }\n\n    /*\n     * If we are processing this KeyDown event as an NSTextInputClient we do\n     * not queue an XEvent.  We pass the NSEvent to our interpretKeyEvents\n     * method.  When the composition sequence is complete, the callback method\n     * insertText: replacementRange will be called.  That method generates a\n     * keyPress XEvent with the selected character.\n     */\n\n    if (use_text_input) {\n\ttextInputModifiers = modifiers;\n\n\t/*\n\t * In IME the Enter key is used to terminate a composition sequence.\n\t * When there are multiple choices of input text available, and the\n\t * user's selected choice is not the default, it may be necessary to\n\t * hit the Enter key multiple times before the text is accepted and\n\t * rendered (See ticket 39de9677aa]). So when sending an Enter key\n\t * during composition, we continue sending Enter keys until the\n\t * inputText method has cleared the processingCompose flag.\n\t */\n\n\tif (processingCompose && [theEvent keyCode] == 36) {\n\t    [nsEvArray addObject: theEvent];\n\t    while(processingCompose) {\n\t\t[[w contentView] interpretKeyEvents: nsEvArray];\n\t    }\n\t    [nsEvArray removeObject: theEvent];\n\t} else {\n\t    [nsEvArray addObject: theEvent];\n\t    [[w contentView] interpretKeyEvents: nsEvArray];\n\t    [nsEvArray removeObject: theEvent];\n\t}\n\treturn theEvent;\n    }\n\n    /*\n     * We are not handling this event as an NSTextInputClient, so we need to\n     * finish constructing the XEvent and queue it.\n     */\n\n    macKC.v.o_s =  ((modifiers & NSShiftKeyMask ? INDEX_SHIFT : 0) |\n\t\t    (modifiers & NSAlternateKeyMask ? INDEX_OPTION : 0));\n    macKC.v.virt = virt;\n    switch (type) {\n    case NSFlagsChanged:\n\n\t/*\n\t * This XEvent is a simulated KeyPress or KeyRelease event for a\n\t * modifier key.  To determine the type, note that the highest bit\n\t * where the flags differ is 1 if and only if it is a KeyPress. The\n\t * modifiers are saved so we can detect the next flag change.\n\t */\n\n\txEvent.xany.type = modifiers > savedModifiers ? KeyPress : KeyRelease;\n\tsavedModifiers = modifiers;\n\n\t/*\n\t * Set the keychar to MOD_KEYCHAR as a signal to TkpGetKeySym (see\n\t * tkMacOSXKeyboard.c) that this is a modifier key event.\n\t */\n\n\tkeychar = MOD_KEYCHAR;\n\tbreak;\n    case NSKeyUp:\n\txEvent.xany.type = KeyRelease;\n\tbreak;\n    case NSKeyDown:\n\txEvent.xany.type = KeyPress;\n\tbreak;\n    default:\n\treturn theEvent; /* Unrecognized key event. */\n    }\n    macKC.v.keychar = keychar;\n    xEvent.xkey.keycode = macKC.uint;\n    setXEventPoint(&xEvent, tkwin, w);\n\n    /*\n     * Finally we can queue the XEvent, inserting a KeyRelease before a\n     * repeated KeyPress.\n     */\n\n    if (type == NSKeyDown && [theEvent isARepeat]) {\n\txEvent.xany.type = KeyRelease;\n\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\txEvent.xany.type = KeyPress;\n    }\n    Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n    return theEvent;\n}\n@end\n\f\n\n@implementation TKContentView\n\n@synthesize onScreen = _onScreen;\n\n/*\n * Implementation of the NSTextInputClient protocol.\n */\n\n/* [NSTextInputClient inputText: replacementRange:] is called by\n * interpretKeyEvents when a composition sequence is complete.  It is also\n * called when we delete working text.  In that case the call is followed\n * immediately by doCommandBySelector: deleteBackward:\n */\n- (void)insertText: (id)aString\n  replacementRange: (NSRange)repRange\n{\n    int i, len, state;\n    XEvent xEvent;\n    NSString *str, *keystr, *lower;\n    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);\n    Tk_Window tkwin = (Tk_Window)winPtr;\n    Bool sendingIMEText = NO;\n\n    str = ([aString isKindOfClass: [NSAttributedString class]]) ?\n\t[aString string] : aString;\n    len = [str length];\n\n    if (NS_KEYLOG) {\n\tTKLog(@\"insertText '%@'\\tlen = %d\", aString, len);\n    }\n\n    /*\n     * Clear any working text.\n     */\n\n    if (privateWorkingText != nil) {\n\tsendingIMEText = YES;\n\t[self deleteWorkingText];\n    }\n\n    /*\n     * Insert the string as a sequence of keystrokes.\n     */\n\n    setupXEvent(&xEvent, tkwin, textInputModifiers);\n    setXEventPoint(&xEvent, tkwin, [self window]);\n    xEvent.xany.type = KeyPress;\n\n    /*\n     * Apple evidently sets location to 0 to signal that an accented letter has\n     * been selected from the accent menu.  An unaccented letter has already\n     * been displayed and we need to erase it before displaying the accented\n     * letter.\n     */\n\n    if (repRange.location == 0) {\n\tTk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;\n\tTk_SendVirtualEvent(focusWin, \"TkAccentBackspace\", NULL);\n    }\n\n    /*\n     * Next we generate an XEvent for each unicode character in our string.\n     * This string could contain non-BMP characters, for example if the\n     * emoji palette was used.\n     *\n     * NSString uses UTF-16 internally, which means that a non-BMP character is\n     * represented by a sequence of two 16-bit \"surrogates\".  We record this in\n     * the XEvent by setting the low order 21-bits of the keycode to the UCS-32\n     * value value of the character and the virtual keycode in the high order\n     * byte to the special value NON_BMP.\n     */\n\n    state = xEvent.xkey.state;\n    for (i = 0; i < len; i++) {\n\tUniChar keychar;\n\tMacKeycode macKC = {0};\n\n\tkeychar = [str characterAtIndex:i];\n\tmacKC.v.keychar = keychar;\n\tif (CFStringIsSurrogateHighCharacter(keychar)) {\n\t    UniChar lowChar = [str characterAtIndex:++i];\n\t    macKC.v.keychar = CFStringGetLongCharacterForSurrogatePair(\n\t\t\t\t  (UniChar)keychar, lowChar);\n\t    macKC.v.virt = NON_BMP_VIRTUAL;\n\t} else if (repRange.location == 0 || sendingIMEText) {\n\t    macKC.v.virt = REPLACEMENT_VIRTUAL;\n\t} else {\n\t    macKC.uint = TkMacOSXAddVirtual(macKC.uint);\n\t    xEvent.xkey.state |= INDEX2STATE(macKC.x.xvirtual);\n\t}\n\tkeystr = [[NSString alloc] initWithCharacters:&keychar length:1];\n\tlower = [keystr lowercaseString];\n\tif (![keystr isEqual: lower]) {\n\t    macKC.v.o_s |= INDEX_SHIFT;\n\t    xEvent.xkey.state |= ShiftMask;\n\t}\n\tif (xEvent.xkey.state & Mod2Mask) {\n\t    macKC.v.o_s |= INDEX_OPTION;\n\t}\n\txEvent.xkey.keycode = macKC.uint;\n\txEvent.xany.type = KeyPress;\n\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\txEvent.xkey.state = state;\n    }\n}\n\n/*\n * This required method is allowed to return nil.\n */\n\n- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange\n      actualRange:(NSRangePointer)thePointer\n{\n    (void)theRange;\n    (void)thePointer;\n\n    return nil;\n}\n\n/*\n * This method is supposed to insert (or replace selected text with) the string\n * argument. If the argument is an NSString, it should be displayed with a\n * distinguishing appearance, e.g underlined.\n */\n\n- (void)setMarkedText: (id)aString\n\tselectedRange: (NSRange)selRange\n     replacementRange: (NSRange)repRange\n{\n    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);\n    if (!winPtr) {\n\treturn;\n    }\n    Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;\n    NSString *temp;\n    NSString *str;\n    (void)selRange;\n\n    str = ([aString isKindOfClass: [NSAttributedString class]]) ?\n\t[aString string] : aString;\n    if (focusWin) {\n\n\t/*\n\t * Remember the widget where the composition is happening, in case it\n\t * gets defocussed during the composition.\n\t */\n\n\tcomposeWin = focusWin;\n    } else {\n\treturn;\n    }\n    if (NS_KEYLOG) {\n\tTKLog(@\"setMarkedText '%@' len =%lu range %lu from %lu\", str,\n\t      (unsigned long) [str length], (unsigned long) selRange.length,\n\t      (unsigned long) selRange.location);\n    }\n\n    if (privateWorkingText != nil) {\n\t[self deleteWorkingText];\n    }\n\n    if ([str length] == 0) {\n\treturn;\n    }\n\n    /*\n     * Use our insertText method to display the marked text.\n     */\n\n    Tk_SendVirtualEvent(focusWin, \"TkStartIMEMarkedText\", NULL);\n    processingCompose = YES;\n    temp = [str copy];\n    [self insertText: temp replacementRange:repRange];\n    privateWorkingText = temp;\n    Tk_SendVirtualEvent(focusWin, \"TkEndIMEMarkedText\", NULL);\n}\n\n- (BOOL)hasMarkedText\n{\n    return privateWorkingText != nil;\n}\n\n- (NSRange)markedRange\n{\n    NSRange rng = privateWorkingText != nil\n\t? NSMakeRange(0, [privateWorkingText length])\n\t: NSMakeRange(NSNotFound, 0);\n\n    if (NS_KEYLOG) {\n\tTKLog(@\"markedRange request\");\n    }\n    return rng;\n}\n\n- (void)unmarkText\n{\n    if (NS_KEYLOG) {\n\tTKLog(@\"unmarkText\");\n    }\n    [self deleteWorkingText];\n    processingCompose = NO;\n}\n\n/*\n * Called by the system to get a position for popup character selection windows\n * such as a Character Palette, or a selection menu for IME.\n */\n\n- (NSRect)firstRectForCharacterRange: (NSRange)theRange\n\t\t\t actualRange: (NSRangePointer)thePointer\n{\n    NSRect rect;\n    NSPoint pt;\n    (void)theRange;\n    (void)thePointer;\n\n    pt.x = caret_x;\n    pt.y = caret_y;\n\n    pt = [self convertPoint: pt toView: nil];\n    pt = [[self window] tkConvertPointToScreen: pt];\n    pt.y -= caret_height;\n\n    rect.origin = pt;\n    rect.size.width = 0;\n    rect.size.height = caret_height;\n    return rect;\n}\n\n- (NSInteger)conversationIdentifier\n{\n    return (NSInteger) self;\n}\n\n- (void)doCommandBySelector: (SEL)aSelector\n{\n    if (NS_KEYLOG) {\n\tTKLog(@\"doCommandBySelector: %@\", NSStringFromSelector(aSelector));\n    }\n    processingCompose = NO;\n    if (aSelector == @selector (deleteBackward:)) {\n\tTkWindow *winPtr = TkMacOSXGetTkWindow([self window]);\n\tTk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;\n\tTk_SendVirtualEvent(focusWin, \"TkAccentBackspace\", NULL);\n    }\n}\n\n- (NSArray *)validAttributesForMarkedText\n{\n    static NSArray *arr = nil;\n    if (arr == nil) {\n\tarr = [[NSArray alloc] initWithObjects:\n\t    NSUnderlineStyleAttributeName,\n\t    NSUnderlineColorAttributeName,\n\t    nil];\n\t[arr retain];\n    }\n    return arr;\n}\n\n- (NSRange)selectedRange\n{\n    if (NS_KEYLOG) {\n\tTKLog(@\"selectedRange request\");\n    }\n    return NSMakeRange(0, 0);\n}\n\n- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint\n{\n    (void)thePoint;\n    if (NS_KEYLOG) {\n\tTKLog(@\"characterIndexForPoint request\");\n    }\n    return NSNotFound;\n}\n\n- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange\n{\n    static NSAttributedString *str = nil;\n    (void)theRange;\n\n    if (str == nil) {\n\tstr = [NSAttributedString new];\n    }\n    if (NS_KEYLOG) {\n\tTKLog(@\"attributedSubstringFromRange request\");\n    }\n    return str;\n}\n/* End of NSTextInputClient implementation. */\n\n@end\n\f\n\n@implementation TKContentView(TKKeyEvent)\n\n/*\n * Tell the widget to erase the displayed composing characters.  This\n * is not part of the NSTextInputClient protocol.\n */\n\n- (void)deleteWorkingText\n{\n    if (privateWorkingText == nil) {\n\treturn;\n    } else {\n\n\tif (NS_KEYLOG) {\n\t    TKLog(@\"deleteWorkingText len = %lu\\n\",\n\t\t  (unsigned long)[privateWorkingText length]);\n\t}\n\n\t[privateWorkingText release];\n\tprivateWorkingText = nil;\n\tprocessingCompose = NO;\n\tif (composeWin) {\n\t    Tk_SendVirtualEvent(composeWin, \"TkClearIMEMarkedText\", NULL);\n\t}\n    }\n}\n\n- (void)cancelComposingText\n{\n    if (NS_KEYLOG) {\n\tTKLog(@\"cancelComposingText\");\n    }\n    [self deleteWorkingText];\n    processingCompose = NO;\n}\n\n@end\n\n/*\n * Set up basic fields in xevent for keyboard input.\n */\n\nstatic void\nsetupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers)\n{\n    unsigned int state = 0;\n    Display *display;\n\n    if (tkwin == NULL) {\n\treturn;\n    }\n    display = Tk_Display(tkwin);\n    if (modifiers) {\n\tstate = (modifiers & NSAlphaShiftKeyMask ? LockMask    : 0) |\n\t\t(modifiers & NSShiftKeyMask      ? ShiftMask   : 0) |\n\t\t(modifiers & NSControlKeyMask    ? ControlMask : 0) |\n\t\t(modifiers & NSCommandKeyMask    ? Mod1Mask    : 0) |\n\t\t(modifiers & NSAlternateKeyMask  ? Mod2Mask    : 0) |\n\t\t(modifiers & NSNumericPadKeyMask ? Mod3Mask    : 0) |\n\t\t(modifiers & NSFunctionKeyMask   ? Mod4Mask    : 0) ;\n    }\n    memset(xEvent, 0, sizeof(XEvent));\n    xEvent->xany.serial = LastKnownRequestProcessed(display);\n    xEvent->xany.display = Tk_Display(tkwin);\n    xEvent->xany.window = Tk_WindowId(tkwin);\n\n    xEvent->xkey.root = XRootWindow(display, 0);\n    xEvent->xkey.time = TkpGetMS();\n    xEvent->xkey.state = state;\n    xEvent->xkey.same_screen = true;\n    /* No need to initialize other fields implicitly here,\n     * because of the memset() above. */\n}\n\nstatic void\nsetXEventPoint(\n    XEvent *xEvent,\n    Tk_Window tkwin,\n    NSWindow *w)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    NSPoint local = [w  mouseLocationOutsideOfEventStream];\n    NSPoint global = [w tkConvertPointToScreen: local];\n    int win_x, win_y;\n\n    if (Tk_IsEmbedded(winPtr)) {\n\tTkWindow *contPtr = (TkWindow *)Tk_GetOtherWindow(tkwin);\n\tif (Tk_IsTopLevel(contPtr)) {\n\t    local.x -= contPtr->wmInfoPtr->xInParent;\n\t    local.y -= contPtr->wmInfoPtr->yInParent;\n\t} else {\n\t    MacDrawable *topMacWin = TkMacOSXGetHostToplevel(winPtr);\n\t    if (topMacWin) {\n\t\tTkWindow *topPtr = topMacWin->winPtr;\n\t\tlocal.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);\n\t\tlocal.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);\n\t    }\n\t}\n    } else if (winPtr->wmInfoPtr != NULL) {\n\tlocal.x -= winPtr->wmInfoPtr->xInParent;\n\tlocal.y -= winPtr->wmInfoPtr->yInParent;\n    }\n    tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);\n    local.x = win_x;\n    local.y = win_y;\n    global.y = TkMacOSXZeroScreenHeight() - global.y;\n    xEvent->xbutton.x = local.x;\n    xEvent->xbutton.y = local.y;\n    xEvent->xbutton.x_root = global.x;\n    xEvent->xbutton.y_root = global.y;\n}\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGrabKeyboard --\n *\n *\tSimulates a keyboard grab by setting the focus.\n *\n * Results:\n *\tAlways returns GrabSuccess.\n *\n * Side effects:\n *\tSets the keyboard focus to the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXGrabKeyboard(\n    Display* display,\n    Window grab_window,\n    TCL_UNUSED(Bool),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(Time))\n{\n    keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);\n    TkWindow *captureWinPtr = (TkWindow *) TkpGetCapture();\n\n    if (keyboardGrabWinPtr && captureWinPtr) {\n\tNSWindow *w = TkMacOSXGetNSWindowForDrawable(grab_window);\n\tMacDrawable *macWin = (MacDrawable *)grab_window;\n\n\tif (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) {\n\t    if (modalSession ) {\n\t\tif (keyboardGrabNSWindow == w) {\n\t\t    return GrabSuccess;\n\t\t} else {\n\t\t    Tcl_Panic(\"XGrabKeyboard: already grabbed\");\n\t\t}\n\t    }\n\t    keyboardGrabNSWindow = w;\n\t    [w retain];\n\t    modalSession = [NSApp beginModalSessionForWindow:w];\n\t}\n    }\n    return GrabSuccess;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUngrabKeyboard --\n *\n *\tReleases the simulated keyboard grab.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the keyboard focus back to the value before the grab.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUngrabKeyboard(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Time))\n{\n    if (modalSession) {\n\t[NSApp endModalSession:modalSession];\n\tmodalSession = nil;\n    }\n    if (keyboardGrabNSWindow) {\n\t[keyboardGrabNSWindow release];\n\tkeyboardGrabNSWindow = nil;\n    }\n    keyboardGrabWinPtr = NULL;\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetModalSession --\n *\n * Results:\n *\tReturns the current modal session\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE NSModalSession\nTkMacOSXGetModalSession(void)\n{\n    return modalSession;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetCaretPos --\n *\n *\tThis enables correct placement of the popups used for character\n *      selection by the NSTextInputClient.  It gets called by text entry\n *      widgets whenever the cursor is drawn.  It does nothing if the widget's\n *      NSWindow is not the current KeyWindow.  Otherwise it updates the\n *      display's caret structure and records the caret geometry in static\n *      variables for use by the NSTextInputClient implementation.  Any\n *      widget passed to this function will be marked as being able to input\n *      text by setting the TK_CAN_INPUT_TEXT flag.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *      Sets the CAN_INPUT_TEXT flag on the widget passed as tkwin.  May update\n *      the display's caret structure as well as the static variables caret_x,\n *      caret_y and caret_height.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetCaretPos(\n    Tk_Window tkwin,\n    int x,\n    int y,\n    int height)\n {\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkCaret *caretPtr = &(winPtr->dispPtr->caret);\n    NSWindow *w = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));\n\n    /*\n     * Register this widget as being capable of text input, so we know we\n     * should process (appropriate) key events for this window with the\n     * NSTextInputClient protocol.\n     */\n\n    winPtr->flags |= TK_CAN_INPUT_TEXT;\n    if (w && ![w isKeyWindow]) {\n\treturn;\n    }\n    if ((caretPtr->winPtr == winPtr\n\t && caretPtr->x == x) && (caretPtr->y == y)) {\n\treturn;\n    }\n\n    /*\n     * Update the display's caret information.\n     */\n\n    caretPtr->winPtr = winPtr;\n    caretPtr->x = x;\n    caretPtr->y = y;\n    caretPtr->height = height;\n\n    /*\n     * Record the caret geometry in static variables for use when processing\n     * key events.  We use the TKContextView coordinate system for this.\n     */\n\n    caret_height = height;\n    while (!Tk_IsTopLevel(tkwin)) {\n\tx += Tk_X(tkwin);\n\ty += Tk_Y(tkwin);\n\ttkwin = Tk_Parent(tkwin);\n\tif (tkwin == NULL) {\n\t    return;\n\t}\n    }\n    caret_x = x;\n    caret_y = Tk_Height(tkwin) - y;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXKeyboard.c",
    "content": "/*\n * tkMacOSXKeyboard.c --\n *\n *\tRoutines to support keyboard events on the Macintosh.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2020 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXKeysyms.h\"\n\n/*\n * About keyboards\n * ---------------\n * Keyboards are complicated.  This long comment is an attempt to provide\n * enough information about them to make it possible to read and understand\n * the code in this file.\n *\n * Every key on a keyboard is identified by a number between 0 and 127.  In\n * macOS, pressing or releasing a key on the keyboard generates an NSEvent of\n * type KeyDown, KeyUp or FlagsChanged.  The 8-bit identifier of the key that\n * was involved in this event is provided in the attribute [NSEvent keyCode].\n * Apple also refers to this number as a \"Virtual KeyCode\".  In this file, to\n * avoid confusion with other uses of the word keycode, we will refer to this\n * key identifier as a \"virtual keycode\", usually the value of a variable named\n * \"virtual\".\n *\n * Some of the keys on a keyboard, such as the Shift, Option, Command or\n * Control keys, are \"modifier\" keys.  The effect of pressing or releasing a\n * key depends on three quantities:\n *     - which key is being pressed or released\n *     - which modifier keys are being held down at the moment\n *     - the current keyboard layout\n * If the key is a modifier key then the effect of pressing or releasing it is\n * only to change the list of which modifier keys are being held down.  Apple\n * reports this by sending an NSEvent of type FlagsChanged.  X11 reports this\n * as a KeyPress or KeyRelease event for the modifier key.  Note that there may\n * be combinations of modifier key states and key presses which have no effect.\n *\n * In X11 every meaningful effect from a key action is identified by a 16 bit\n * value known as a keysym.  Every keysym has an associated string name, also\n * known as a keysym.  The Tk bind command uses the X11 keysym string to\n * specify a key event which should invoke a certain action and it provides the\n * numeric and symbolic keysyms to the bound proc as %N and %K respectively.\n * An X11 XEvent which reports a KeyPress or KeyRelease does not include the\n * keysym.  Instead it includes a platform-specific numerical value called a\n * keycode which is available to the bound procedure as %k.  A platform port of\n * Tk must provide functions which convert between keycodes and numerical\n * keysyms.  Conversion between numerical and symbolic keysyms is provided by\n * the generic Tk code, although platforms are allowed to provide their own by\n * defining the XKeysymToString and XStringToKeysym functions and undefining\n * the macro REDO_KEYSYM_LOOKUP.  This macOS port uses the conversion provided\n * by the generic code.\n *\n * When the keyboard focus is on a Tk widget which provides text input, there\n * are some X11 KeyPress events which cause text to be inserted.  We will call\n * these \"printable\" events. The UCS-32 character stored in the keycode field\n * of an XKeyEvent depends on more than the three items above.  It may also\n * depend on the sequence of keypresses that preceded the one being reported by\n * the XKeyEvent.  For example, on macOS an <Alt-e> event does not cause text\n * to be inserted but a following <a> event causes an accented 'a' to be\n * inserted.  The events in such a composition sequence, other than the final\n * one, are known as \"dead-key\" events.\n *\n * MacOS packages the information described above in a different way.  Every\n * meaningful effect from a key action *other than changing the state of\n * modifier keys* is identified by a unicode string which is provided as the\n * [NSEvent characters] attribute of a KeyDown or KeyUp event.  FlagsChanged\n * events do not have characters.  In principle, the characters attribute could\n * be an arbitrary unicode string but in practice it is always a single UTF-16\n * character which we usually store in a variable named keychar.  While the\n * keychar is a legal unicode code point, it does not necessarily represent a\n * glyph. MacOS uses unicode code points in the private-use range 0xF700-0xF8FF\n * for non-printable events which have no associated ASCII code point.  For\n * example, pressing the F2 key generates an NSEvent with the character 0xF705,\n * the Backspace key produces 0x7F (ASCII del) and the Delete key produces\n * 0xF728.\n *\n * With the exception of modifier keys, it is possible to translate between\n * numerical X11 keysyms and macOS keychars; this file constructs Tcl hash\n * tables to do this job, using data defined in the file tkMacOSXKeysyms.h.\n * The code here adopts the convention that the keychar of any modifier key\n * is MOD_KEYCHAR.  Keys which do not appear on any Macintosh keyboard, such\n * as the Menu key on PC keyboards, are assigned UNKNOWN_KEYCHAR.\n *\n * The macosx platform-specific scheme for generating a keycode when mapping an\n * NSEvent of type KeyUp, KeyDown or FlagsChanged to an XEvent of type KeyPress\n * or KeyRelease is as follows:\n *     keycode = (virtual << 24) | index << 22 | keychar\n * where index is a 2-bit quantity whose bits indicate the state of the Option\n * and Shift keys.\n *\n * A few remarks are in order.  First, we are using 32 bits for the keycode and\n * we are allowing room for up to 22 bits for the keychar.  This means that\n * there is enough room in the keycode to hold a UTF-32 character, which only\n * requires 21 bits.  Second, the KeyCode type for the keycode field in an\n * XEvent is currently defined as unsigned int, which was modified from the\n * unsigned short used in X11 in order to accomodate macOS. Finally, there is\n * no obstruction to generating KeyPress events for keys that represent letters\n * which do not exist on the current keyboard layout.  And different keyboard\n * layouts can assign a given letter to different keys.  So we need a\n * convention for what value to assign to \"virtual\" when computing the keycode\n * for a generated event.  The convention used here is as follows: If there is\n * a key on the current keyboard which produces the keychar, use the virtual\n * keycode of that key.  Otherwise set virtual = NO_VIRTUAL.\n */\n\n\n/*\n * See tkMacOSXPrivate.h for macros and structures related to key event processing.\n */\n\n/*\n * Hash tables and array used to translate between various key attributes.\n */\n\nstatic Tcl_HashTable special2keysym;\t/* Special virtual keycode to keysym */\nstatic Tcl_HashTable keysym2keycode;\t/* keysym to XEvent keycode */\nstatic Tcl_HashTable keysym2unichar;\t/* keysym to unichar */\nstatic Tcl_HashTable unichar2keysym;\t/* unichar to X11 keysym */\nstatic Tcl_HashTable unichar2xvirtual;\t/* unichar to virtual with index */\nstatic UniChar xvirtual2unichar[512];\t/* virtual with index to unichar */\n\n/*\n * Flags.\n */\n\nstatic bool initialized = false;\nstatic bool keyboardChanged = true;\n\n/*\n * Prototypes for static functions used in this file.\n */\n\nstatic void\tInitHashTables(void);\nstatic void     UpdateKeymaps(void);\nstatic int\tKeyDataToUnicode(UniChar *uniChars, int maxChars,\n\t\t\tUInt16 keyaction, UInt32 virt, UInt32 modifiers,\n\t\t\tUInt32 * deadKeyStatePtr);\n\n#pragma mark TKApplication(TKKeyboard)\n\n@implementation TKApplication(TKKeyboard)\n- (void) keyboardChanged: (NSNotification *) notification\n{\n    (void)notification;\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    keyboardChanged = true;\n    UpdateKeymaps();\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitHashTables --\n *\n *\tCreates hash tables used by some of the functions in this file.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAllocates memory & creates some hash tables.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitHashTables(void)\n{\n    Tcl_HashEntry *hPtr;\n    const KeyInfo *kPtr;\n    const KeysymInfo *ksPtr;\n    int dummy, index;\n\n    Tcl_InitHashTable(&special2keysym, TCL_ONE_WORD_KEYS);\n    Tcl_InitHashTable(&keysym2keycode, TCL_ONE_WORD_KEYS);\n    for (kPtr = keyArray; kPtr->virt != 0; kPtr++) {\n\tMacKeycode macKC;\n\tmacKC.v.o_s = 0;\n\thPtr = Tcl_CreateHashEntry(&special2keysym, INT2PTR(kPtr->virt),\n\t\t\t\t   &dummy);\n\tTcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));\n\thPtr = Tcl_CreateHashEntry(&keysym2keycode, INT2PTR(kPtr->keysym),\n\t\t\t\t   &dummy);\n\tmacKC.v.virt = kPtr->virt;\n\tmacKC.v.keychar = kPtr->keychar;\n\tTcl_SetHashValue(hPtr, INT2PTR(macKC.uint));\n\n\t/*\n\t * The Carbon framework does not work for finding the unicode character\n\t * of a special key.  But that does not depend on the keyboard layout,\n\t * so we can record the information here.\n\t */\n\n\tfor (index = 3; index >= 0; index--) {\n\t    macKC.v.o_s = index;\n\t    xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar;\n\t}\n    }\n    Tcl_InitHashTable(&keysym2unichar, TCL_ONE_WORD_KEYS);\n    Tcl_InitHashTable(&unichar2keysym, TCL_ONE_WORD_KEYS);\n    for (ksPtr = keysymTable; ksPtr->keysym != 0; ksPtr++) {\n\thPtr = Tcl_CreateHashEntry(&keysym2unichar, INT2PTR(ksPtr->keysym),\n\t\t\t\t   &dummy);\n\tTcl_SetHashValue(hPtr, INT2PTR(ksPtr->keycode));\n\thPtr = Tcl_CreateHashEntry(&unichar2keysym, INT2PTR(ksPtr->keycode),\n\t\t\t\t   &dummy);\n\tTcl_SetHashValue(hPtr, INT2PTR(ksPtr->keysym));\n    }\n    UpdateKeymaps();\n    initialized = true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateKeymaps --\n *\n *\tCalled when the keyboard changes to update the hash tables that provide\n *      maps between unicode characters and virtual keycodes with indexes.  In\n *      order for the map from characters to virtual keycodes to be\n *      well-defined we have to ignore virtual keycodes for keypad keys, since\n *      each keypad key has the same character as the corresponding key on the\n *      main keyboard.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInitializes, if necessary, and updates the unichar2xvirtual hash table\n *      and the xvirtual2unichar array.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateKeymaps()\n{\n    static Bool keymapInitialized = false;\n    Tcl_HashEntry *hPtr;\n    int virt, index, dummy;\n\n    if (!keymapInitialized) {\n\tTcl_InitHashTable(&unichar2xvirtual, TCL_ONE_WORD_KEYS);\n\tkeymapInitialized = true;\n    } else {\n\tTcl_DeleteHashTable(&unichar2xvirtual);\n\tTcl_InitHashTable(&unichar2xvirtual, TCL_ONE_WORD_KEYS);\n    }\n    /*\n     * This loop goes backwards so that a lookup by keychar will provide the\n     * minimal modifier mask.  Simpler combinations will overwrite more complex\n     * ones when constructing the table.\n     */\n\n    for (index = 3; index >= 0; index--) {\n\tfor (virt = 0; virt < 128; virt++) {\n\t    MacKeycode macKC;\n\t    macKC.v = (keycode_v) {.virt = virt, .o_s = index, .keychar = 0};\n\t    int modifiers = INDEX2CARBON(index);\n\t    UniChar keychar = 0;\n\t    KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virt,\n\t\t\t\t      modifiers, NULL);\n\t    if (keychar == 0x10) {\n\n\t\t/*\n\t\t * This is a special key, handled in InitHashTables.\n\t\t */\n\n\t\tcontinue;\n\t    }\n\t    macKC.v.keychar = keychar;\n\t    if (! ON_KEYPAD(virt)) {\n\t\thPtr = Tcl_CreateHashEntry(&unichar2xvirtual,\n\t\t\t\t\t   INT2PTR(macKC.x.keychar), &dummy);\n\t\tTcl_SetHashValue(hPtr, INT2PTR(macKC.x.xvirtual));\n\t    }\n\t    xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * KeyDataToUnicode --\n *\n *\tGiven MacOS key event data this function generates the keychar.  It\n *\tdoes this by using OS resources from the Carbon framework.  Note that\n *      the Carbon functions used here are not aware of the keychars in the\n *      private-use range which macOS now uses for special keys.  For those\n *      keys this function returns 0x10 (ASCII dle).\n *\n *\tThe parameter deadKeyStatePtr can be NULL, if no deadkey handling is\n *\tneeded (which is always the case here).\n *\n *\tThis function is called in XkbKeycodeToKeysym and UpdateKeymaps.\n *\n * Results:\n *\tThe number of characters generated if any, 0 if we are waiting for\n *\tanother byte of a dead-key sequence.\n *\n * Side Effects:\n *\t Fills in the uniChars array with a Unicode string.\n *\n *----------------------------------------------------------------------\n */\n\n\nstatic int\nKeyDataToUnicode(\n    UniChar *uniChars,\n    int maxChars,\n    UInt16 keyaction,\n    UInt32 virt,\n    UInt32 modifiers,\n    UInt32 *deadKeyStatePtr)\n{\n    static const void *layoutData = NULL;\n    static UInt32 keyboardType = 0;\n    UniCharCount actuallength = 0;\n\n    if (keyboardChanged) {\n\tTISInputSourceRef currentKeyboardLayout =\n\t\tTISCopyCurrentKeyboardLayoutInputSource();\n\n\tif (currentKeyboardLayout) {\n\t    CFDataRef keyLayoutData = (CFDataRef) TISGetInputSourceProperty(\n\t\t    currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData);\n\n\t    if (keyLayoutData) {\n\t\tlayoutData = CFDataGetBytePtr(keyLayoutData);\n\t\tkeyboardType = LMGetKbdType();\n\t    }\n\t    CFRelease(currentKeyboardLayout);\n\t}\n\tkeyboardChanged = false;\n    }\n    if (layoutData) {\n\tOptionBits options = 0;\n\tUInt32 dummyState;\n\tOSStatus err;\n\n\tvirt &= 0xFF;\n\tmodifiers = (modifiers >> 8) & 0xFF;\n\tif (!deadKeyStatePtr) {\n\t    options = kUCKeyTranslateNoDeadKeysMask;\n\t    dummyState = 0;\n\t    deadKeyStatePtr = &dummyState;\n\t}\n\terr = ChkErr(UCKeyTranslate, (const UCKeyboardLayout *)layoutData, virt, keyaction, modifiers,\n\t\tkeyboardType, options, deadKeyStatePtr, maxChars,\n\t\t&actuallength, uniChars);\n\tif (!actuallength && *deadKeyStatePtr) {\n\n\t    /*\n\t     * We are waiting for another key.\n\t     */\n\n\t    return 0;\n\t}\n\t*deadKeyStatePtr = 0;\n\tif (err != noErr) {\n\t    actuallength = 0;\n\t}\n    }\n    return actuallength;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XkbKeycodeToKeysym --\n *\n *\tThis is a stub function which translates from the keycode used in an\n *      XEvent to a numerical keysym.  On macOS, the display parameter is\n *      ignored and only the the virtual keycode stored in the .virtual bitfield\n *      of a MacKeycode.v.\n *\n * Results:\n *      Returns the corresponding numerical keysym, or NoSymbol if the keysym\n *      cannot be found.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nXkbKeycodeToKeysym(\n    TCL_UNUSED(Display *),\n    unsigned int keycode,\n    TCL_UNUSED(int),\n    int index)\n{\n    Tcl_HashEntry *hPtr;\n    MacKeycode macKC;\n    int modifiers, result;\n    UniChar keychar = 0;\n\n    if (!initialized) {\n\tInitHashTables();\n    }\n    macKC.uint = keycode;\n    macKC.v.o_s = index;\n\n    /*\n     * First check if the virtual keycode corresponds to a special key, such as\n     * an Fn function key or Tab, Backspace, Home, End, etc.\n     */\n\n    hPtr = Tcl_FindHashEntry(&special2keysym, INT2PTR(macKC.v.virt));\n    if (hPtr != NULL) {\n\treturn (KeySym) Tcl_GetHashValue(hPtr);\n    }\n\n    /*\n     * If the virtual value in this keycode does not correspond to an actual\n     * key in the current keyboard layout, try using its keychar to look up a\n     * keysym.\n     */\n\n    if (macKC.v.virt > 127) {\n\thPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(macKC.v.keychar));\n\tif (hPtr != NULL) {\n\t    return (KeySym) Tcl_GetHashValue(hPtr);\n\t}\n    }\n\n    /*\n     * If the virtual keycode does belong to a key, use the virtual and the\n     * Option-Shift from index to look up a keychar by using the Carbon\n     * Framework; then translate the keychar to a keysym using the\n     * unicode2keysym hash table.\n     */\n\n    modifiers = INDEX2CARBON(macKC.v.o_s);\n    result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, macKC.v.virt,\n\t\t\t      modifiers, NULL);\n    if (result) {\n\thPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(keychar));\n\tif (hPtr != NULL) {\n\t    return (KeySym) Tcl_GetHashValue(hPtr);\n\t}\n    }\n    return NoSymbol;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetString --\n *\n *\tThis is a stub function which retrieves the string stored in the\n *      transchars field of an XEvent and converts it to a Tcl_DString.\n *\n * Results:\n *\tReturns a pointer to the string value of the DString.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkpGetString(\n    TCL_UNUSED(TkWindow *),\t/* Window where event occurred: Needed to get\n\t\t\t\t * input context. */\n    XEvent *eventPtr,\t\t/* X keyboard event. */\n    Tcl_DString *dsPtr)\t\t/* Uninitialized or empty string to hold\n\t\t\t\t * result. */\n{\n    MacKeycode macKC;\n    char utfChars[8];\n    int length = 0;\n\n    macKC.uint = eventPtr->xkey.keycode;\n    if (IS_PRINTABLE(macKC.v.keychar)) {\n\tlength = Tcl_UniCharToUtf(macKC.v.keychar, utfChars);\n    }\n    utfChars[length] = 0;\n\n    Tcl_DStringInit(dsPtr);\n    return Tcl_DStringAppend(dsPtr, utfChars, length);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetModifierMapping --\n *\n *\tX11 stub function to get the keycodes used as modifiers.  This\n *      is never called by the macOS port.\n *\n * Results:\n *\tReturns a newly allocated modifier map.\n *\n * Side effects:\n *\tAllocates a new modifier map data structure.\n *\n *----------------------------------------------------------------------\n */\n\nXModifierKeymap *\nXGetModifierMapping(\n    TCL_UNUSED(Display *))\n{\n    XModifierKeymap *modmap;\n\n    modmap = (XModifierKeymap *)Tcl_Alloc(sizeof(XModifierKeymap));\n    modmap->max_keypermod = 0;\n    modmap->modifiermap = NULL;\n    return modmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFreeModifiermap --\n *\n *\tDeallocates a modifier map that was created by XGetModifierMapping.\n *      This is also never called by the macOS port.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees the datastructure referenced by modmap.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFreeModifiermap(\n    XModifierKeymap *modmap)\n{\n    if (modmap->modifiermap != NULL) {\n\tTcl_Free(modmap->modifiermap);\n    }\n    Tcl_Free(modmap);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XKeysymToString, XStringToKeysym --\n *\n *\tThese X11 stub functions map keysyms to strings & strings to keysyms.\n *      A platform can do its own conversion by defining these and undefining\n *      REDO_KEYSYM_LOOKUP.  The macOS port defines REDO_KEYSYM_LOOKUP so these\n *      are never called and Tk does the conversion for us.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nchar *\nXKeysymToString(\n    TCL_UNUSED(KeySym))\n{\n    return NULL;\n}\n\nKeySym\nXStringToKeysym(\n    TCL_UNUSED(const char *))\n{\n    return NoSymbol;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XKeysymToKeycode --\n *\n *\tThis is a stub function which converts a numerical keysym to the\n *      platform-specific keycode used in a KeyPress or KeyRelease XEvent.\n *      For macOS the keycode is an unsigned int with bitfields described\n *      in the definition of the MacKeycode type.\n *\n * Results:\n *\n *      A macOS KeyCode. See the description of keycodes at the top of this\n *\tfile and the definition of the MacKeycode type in tkMacOSXPrivate.h.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeyCode\nXKeysymToKeycode(\n    TCL_UNUSED(Display *),\n    KeySym keysym)\n{\n    Tcl_HashEntry *hPtr;\n    MacKeycode macKC;\n    if (!initialized) {\n\tInitHashTables();\n    }\n\n    /*\n     * First check for a special key.\n     */\n\n    hPtr = Tcl_FindHashEntry(&keysym2keycode, INT2PTR(keysym));\n    if (hPtr != NULL) {\n\treturn (KeyCode) PTR2INT(Tcl_GetHashValue(hPtr));\n    }\n\n    /*\n     * Initialize the keycode as if the keysym cannot be converted to anything\n     * else.\n     */\n\n    macKC.v.virt = NO_VIRTUAL;\n    macKC.v.o_s = 0;\n    macKC.v.keychar = 0;\n\n    /*\n     * If the keysym is recognized fill in the keychar.  Also fill in the\n     * xvirtual field if the key exists on the current keyboard.\n     */\n\n    hPtr = (Tcl_HashEntry *) Tcl_FindHashEntry(&keysym2unichar,\n\t\t\t\t\t       INT2PTR(keysym));\n    if (hPtr != NULL) {\n\tunsigned long data = (unsigned long) Tcl_GetHashValue(hPtr);\n\tmacKC.x.keychar = (unsigned int) data;\n\thPtr = Tcl_FindHashEntry(&unichar2xvirtual, INT2PTR(macKC.x.keychar));\n\tif (hPtr != NULL) {\n\t    data = (unsigned long) Tcl_GetHashValue(hPtr);\n\t    macKC.x.xvirtual = (unsigned int) data;\n\t}\n    }\n    return (KeyCode) macKC.uint;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetKeycodeAndState --\n *\n *\tThis function accepts a keysym and an XEvent and sets some fields of\n *\tthe XEvent.  It is used by the event generate command.\n *\n * Results:\n *      None\n *\n * Side effects:\n *\n *\tModifies the XEvent. Sets the xkey.keycode to a keycode value formatted\n *\tby XKeysymToKeycode and updates the shift and option flags in\n *\txkey.state if either of those modifiers is required to generate the\n *\tkeysym.\n *\n *----------------------------------------------------------------------\n */\nvoid\nTkpSetKeycodeAndState(\n    TCL_UNUSED(Tk_Window),\n    KeySym keysym,\n    XEvent *eventPtr)\n{\n    if (keysym == NoSymbol) {\n\teventPtr->xkey.keycode = 0;\n    } else {\n\tint eventIndex = STATE2INDEX(eventPtr->xkey.state);\n\tMacKeycode macKC;\n\tmacKC.uint = XKeysymToKeycode(NULL, keysym);\n\n\t/*\n\t * We have a virtual keycode and a minimal choice for Shift and Option\n\t * modifiers which generates the keychar that corresponds to the\n\t * specified keysym.  But we might not have the correct keychar yet,\n\t * because the xEvent may have specified modifiers beyond our minimal\n\t * set.  For example, the events described by <Oslash>, <Shift-oslash>,\n\t * <Shift-Option-O> and <Shift-Option-o> should all produce the same\n\t * uppercase Danish O.  So we may need to add the extra modifiers and\n\t * do another lookup for the keychar.  We don't want to do this for\n\t * special keys, however.\n\t */\n\n\tif (macKC.v.o_s != eventIndex) {\n\t    macKC.v.o_s |= eventIndex;\n\t}\n\tif (macKC.v.keychar < 0xF700) {\n\t    UniChar keychar = macKC.v.keychar;\n\t    NSString *str, *lower, *upper;\n\t    if (macKC.v.virt != NO_VIRTUAL) {\n\t\tmacKC.x.keychar = xvirtual2unichar[macKC.x.xvirtual];\n\t    } else {\n\t\tstr = [[NSString alloc] initWithCharacters:&keychar length:1];\n\t\tlower = [str lowercaseString];\n\t\tupper = [str uppercaseString];\n\t\tif (![str isEqual: lower]) {\n\t\t    macKC.v.o_s |= INDEX_SHIFT;\n\t\t}\n\t\tif (macKC.v.o_s & INDEX_SHIFT) {\n\t\t    macKC.v.keychar = [upper characterAtIndex:0];\n\t\t}\n\t    }\n\t}\n\teventPtr->xkey.keycode = macKC.uint;\n\teventPtr->xkey.state |= INDEX2STATE(macKC.v.o_s);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetKeySym --\n *\n *\tThis is a stub function called in tkBind.c.  Given a KeyPress or\n *\tKeyRelease XEvent, it maps the keycode in the event to a numerical\n *      keysym.\n *\n * Results:\n *\tThe return value is the keysym corresponding to eventPtr, or NoSymbol\n *\tif no matching keysym could be found.\n *\n * Side effects:\n *\tIn the first call for a given display, calls TkpInitKeymapInfo.\n *\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nTkpGetKeySym(\n    TkDisplay *dispPtr,\t\t/* Display in which to map keycode. */\n    XEvent *eventPtr)\t\t/* Description of X event. */\n{\n    KeySym sym;\n    int index;\n    MacKeycode macKC;\n    macKC.uint = eventPtr->xkey.keycode;\n\n    /*\n     * Refresh the mapping information if it's stale.\n     */\n\n    if (dispPtr->bindInfoStale) {\n\tTkpInitKeymapInfo(dispPtr);\n    }\n\n    /*\n     * Modifier key events have a special mac keycode (see tkProcessKeyEvent).\n     */\n\n    if (macKC.v.keychar == MOD_KEYCHAR) {\n\tswitch (macKC.v.virt) {\n\tcase 54:\n\t    return XK_Meta_R;\n\tcase 55:\n\t    return XK_Meta_L;\n\tcase 56:\n\t    return XK_Shift_L;\n\tcase 57:\n\t    return XK_Caps_Lock;\n\tcase 58:\n\t    return XK_Alt_L;\n\tcase 59:\n\t    return XK_Control_L;\n\tcase 60:\n\t    return XK_Shift_R;\n\tcase 61:\n\t    return XK_Alt_R;\n\tcase 62:\n\t    return XK_Control_R;\n\tcase 63:\n\t    return XK_Super_L;\n\tdefault:\n\t    return NoSymbol;\n\t}\n    }\n\n    /*\n     * Figure out which of the four slots in the keymap vector to use for this\n     * key. Refer to Xlib documentation for more info on how this computation\n     * works.\n     */\n\n    index = STATE2INDEX(eventPtr->xkey.state);\n    if (eventPtr->xkey.state & LockMask) {\n\tindex |= INDEX_SHIFT;\n    }\n\n    /*\n     * First do the straightforward lookup.\n     */\n\n    sym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0, index);\n\n    /*\n     * Special handling: If the key was shifted because of Lock, which is only\n     * caps lock on macOS, not shift lock, and if the shifted keysym isn't\n     * upper-case alphabetic, then switch back to the unshifted keysym.\n     */\n\n    if ((index & INDEX_SHIFT) && !(eventPtr->xkey.state & ShiftMask)) {\n\tif ((sym == NoSymbol) || !Tcl_UniCharIsUpper(sym)) {\n\t    sym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0,\n\t\t\t\t   index & ~INDEX_SHIFT);\n\t}\n    }\n\n    /*\n     * Another bit of special handling: If this is a shifted key and there is\n     * no keysym defined, then use the keysym for the unshifted key.\n     */\n\n    if ((index & INDEX_SHIFT) && (sym == NoSymbol)) {\n\tsym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0,\n\t\t\t       index & ~INDEX_SHIFT);\n    }\n    return sym;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitKeymapInfo --\n *\n *\tThis procedure initializes fields in the display that pertain\n *      to modifier keys.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tModifier key information in dispPtr is initialized.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitKeymapInfo(\n    TkDisplay *dispPtr)\t\t/* Display for which to recompute keymap\n\t\t\t\t * information. */\n{\n    dispPtr->bindInfoStale = 0;\n\n    /*\n     * On macOS the caps lock key is always interpreted to mean that alphabetic\n     * keys become uppercase but other keys do not get shifted.  (X11 allows\n     * a configuration option which makes the caps lock equivalent to holding\n     * down the shift key.)\n     * There is no offical \"Mode_switch\" key.\n     */\n\n    dispPtr->lockUsage = LU_CAPS;\n\n    /* This field is no longer used by tkBind.c */\n\n    dispPtr->modeModMask = 0;\n\n    /* The Alt and Meta keys are interchanged on Macintosh keyboards compared\n     * to PC keyboards.  These fields could be set to make the Alt key on a PC\n     * keyboard behave likd an Alt key. That would also require interchanging\n     * Mod1Mask and Mod2Mask in tkMacOSXKeyEvent.c.\n     */\n\n    dispPtr->altModMask = 0;\n    dispPtr->metaModMask = 0;\n\n    /*\n     * The modKeyCodes table lists the keycodes that appear in KeyPress or\n     * KeyRelease XEvents for modifier keys.  In tkBind.c this table is\n     * searched to determine whether an XEvent corresponds to a modifier key.\n     */\n\n    if (dispPtr->modKeyCodes != NULL) {\n\tTcl_Free(dispPtr->modKeyCodes);\n    }\n    dispPtr->numModKeyCodes = NUM_MOD_KEYCODES;\n    dispPtr->modKeyCodes = (KeyCode *)Tcl_Alloc(NUM_MOD_KEYCODES * sizeof(KeyCode));\n    for (int i = 0; i < NUM_MOD_KEYCODES; i++) {\n\tdispPtr->modKeyCodes[i] = XKeysymToKeycode(NULL, modKeyArray[i]);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMacOSXAddVirtual --\n *\n *\tThis procedure is an internal utility which accepts an unsigned int\n *      that has been partially filled as a MacKeycode, having the Option and\n *      Shift state set in the o_s field and the keychar field set but with the\n *      virtual keycode blank.  It looks up the virtual keycode for the keychar\n *      (possibly NO_VIRTUAL) and returns an unsigned int which is a complete\n *      MacKeycode with the looked up virtual keycode added.  This is used when\n *      creating XEvents for the unicode characters which are generated by the\n *      NSTextInputClient.\n *\n * Results:\n *      An unsigned int which is a complete MacKeycode, including a virtual\n *\tkeycode which matches the Option-Shift state and keychar.\n *\n * Side effects:\n *\tNone\n *\n *--------------------------------------------------------------\n */\nunsigned\nTkMacOSXAddVirtual(\n    unsigned int keycode)\n{\n    MacKeycode macKC;\n    Tcl_HashEntry *hPtr;\n    macKC.uint = keycode;\n\n    if (!initialized) {\n\tInitHashTables();\n    }\n\n    hPtr = (Tcl_HashEntry *) Tcl_FindHashEntry(&unichar2xvirtual,\n\t\t\t\t\t       INT2PTR(macKC.v.keychar));\n    if (hPtr != NULL) {\n\tunsigned long data = (unsigned long) Tcl_GetHashValue(hPtr);\n\tmacKC.x.xvirtual = (unsigned int) data;\n    } else {\n\tmacKC.v.virt = NO_VIRTUAL;\n    }\n    return macKC.uint;\n}\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXKeysyms.h",
    "content": "/*\n * tkMacOSXKeysyms.h --\n *\n *      Contains data used for processing key events, some of which was\n *      moved from tkMacOSXKeyboard.c.\n *\n * Copyright © 1990-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2020 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef TKMACOSXKEYSYMS_H\n#define TKMACOSXKEYSYMS_H 1\n\n/*\n * This table enumerates the keys on Mac keyboards which do not represent\n * letters.  This is static data -- these keys do not change when the keyboard\n * layout changes.  The unicode representation of a special key which is not a\n * modifier and does not have an ASCII code point lies in the reserved range\n * 0xF700 - 0xF8FF.\n *\n * The table includes every key listed in Apple's documentation of Function-Key\n * Unicodes which is not marked as \"Not on most Macintosh keyboards\", as well\n * as F20, which is reported to be usable in scripts even though it does not\n * appear on any Macintosh keyboard.\n */\n\ntypedef struct {\n    int virt;\t/* value of [NSEvent keyCode] */\n    KeySym keysym;\t/* X11 keysym */\n    KeyCode keychar;\t/* XEvent keycode & 0xFFFF */\n} KeyInfo;\n\nstatic const KeyInfo keyArray[] = {\n    {36,\tXK_Return,\tNSNewlineCharacter},\n    {48,\tXK_Tab,\t\tNSTabCharacter},\n    {51,\tXK_BackSpace,\tNSDeleteCharacter},\n    {52,\tXK_Return,\tNSNewlineCharacter},  /* Used on some Powerbooks */\n    {53,\tXK_Escape,\t0x1B},\n    {54,\tXK_Meta_R,      MOD_KEYCHAR},\n    {55,\tXK_Meta_L,\tMOD_KEYCHAR},\n    {56,\tXK_Shift_L,\tMOD_KEYCHAR},\n    {57,\tXK_Caps_Lock,   MOD_KEYCHAR},\n    {58,\tXK_Alt_L,\tMOD_KEYCHAR},\n    {59,\tXK_Control_L,\tMOD_KEYCHAR},\n    {60,\tXK_Shift_R,\tMOD_KEYCHAR},\n    {61,\tXK_Alt_R,\tMOD_KEYCHAR},\n    {62,\tXK_Control_R,\tMOD_KEYCHAR},\n    {63,\tXK_Super_L,\tMOD_KEYCHAR},\n    {64,\tXK_F17,\t\tNSF17FunctionKey},\n    {65,\tXK_KP_Decimal,\t'.'},\n    {67,\tXK_KP_Multiply, '*'},\n    {69,\tXK_KP_Add,\t'+'},\n    {71,\tXK_Clear,       NSClearLineFunctionKey}, /* Numlock on PC */\n    {75,\tXK_KP_Divide,   '/'},\n    {76,\tXK_KP_Enter,\tNSEnterCharacter},       /* Fn Return */\n    {78,\tXK_KP_Subtract, '-'},\n    {79,\tXK_F18,\t\tNSF18FunctionKey},\n    {80,\tXK_F19,\t\tNSF19FunctionKey},\n    {81,\tXK_KP_Equal,\t'='},\n    {82,\tXK_KP_0,\t'0'},\n    {83,\tXK_KP_1,\t'1'},\n    {84,\tXK_KP_2,\t'2'},\n    {85,\tXK_KP_3,\t'3'},\n    {86,\tXK_KP_4,\t'4'},\n    {87,\tXK_KP_5,\t'5'},\n    {88,\tXK_KP_6,\t'6'},\n    {89,\tXK_KP_7,\t'7'},\n    {90,\tXK_F20,\t\tNSF20FunctionKey}, /* For scripting only */\n    {91,\tXK_KP_8,\t'8'},\n    {92,\tXK_KP_9,\t'9'},\n    {96,\tXK_F5,\t\tNSF5FunctionKey},\n    {97,\tXK_F6,\t\tNSF6FunctionKey},\n    {98,\tXK_F7,\t\tNSF7FunctionKey},\n    {99,\tXK_F3,\t\tNSF3FunctionKey},\n    {100,\tXK_F8,\t\tNSF8FunctionKey},\n    {101,\tXK_F9,\t\tNSF9FunctionKey},\n    {103,\tXK_F11,\t\tNSF11FunctionKey},\n    {105,\tXK_F13,\t\tNSF13FunctionKey},\n    {106,\tXK_F16,\t\tNSF16FunctionKey},\n    {107,\tXK_F14,\t\tNSF14FunctionKey},\n    {109,\tXK_F10,\t\tNSF10FunctionKey},\n    {110,\tXK_Menu,\tUNKNOWN_KEYCHAR},\n    {111,\tXK_F12,\t\tNSF12FunctionKey},\n    {113,\tXK_F15,\t\tNSF15FunctionKey},\n    {114,\tXK_Help,\tNSHelpFunctionKey},\n    {115,\tXK_Home,\tNSHomeFunctionKey},     /* Fn Left */\n    {116,\tXK_Prior,\tNSPageUpFunctionKey},   /* Fn Up */\n    {117,\tXK_Delete,\tNSDeleteFunctionKey},   /* Fn Delete */\n    {118,\tXK_F4,\t\tNSF4FunctionKey},\n    {119,\tXK_End,\t\tNSEndFunctionKey},      /* Fn Right */\n    {120,\tXK_F2,\t\tNSF2FunctionKey},\n    {121,\tXK_Next,\tNSPageDownFunctionKey}, /* Fn Down */\n    {122,\tXK_F1,\t\tNSF1FunctionKey},\n    {123,\tXK_Left,\tNSLeftArrowFunctionKey},\n    {124,\tXK_Right,\tNSRightArrowFunctionKey},\n    {125,\tXK_Down,\tNSDownArrowFunctionKey},\n    {126,\tXK_Up,\t\tNSUpArrowFunctionKey},\n    {0, 0, 0}\n};\n\n/*\n * X11 keysyms for modifier keys, in order.  This list includes keys\n * which do not appear on Apple keyboards, such as Shift_Lock and\n * Super_R.  While most systems don't provide events for the \"fn\"\n * function key, Apple does.  We map it to Super_L when processing a\n * FlagsChanged NSEvent.\n */\n\n#define NUM_MOD_KEYCODES 14\nstatic const KeyCode modKeyArray[NUM_MOD_KEYCODES] = {\n    XK_Shift_L,\n    XK_Shift_R,\n    XK_Control_L,\n    XK_Control_R,\n    XK_Caps_Lock,\n    XK_Shift_Lock,\n    XK_Meta_L,\n    XK_Meta_R,\n    XK_Alt_L,\n    XK_Alt_R,\n    XK_Super_L,\n    XK_Super_R,\n    XK_Hyper_L,\n    XK_Hyper_R,\n};\n\n/*\n * This table pairs X11 Keysyms for alphanumeric characters with the\n * unicode code point for that letter.\n * The data comes from http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt\n */\n\ntypedef struct KeysymInfo {\n    KeySym keysym;\n    KeyCode keycode;\n} KeysymInfo;\n\nstatic const KeysymInfo keysymTable[] = {\n    {0x0020, 0x0020}, /* space */\n    {0x0021, 0x0021}, /* exclam */\n    {0x0022, 0x0022}, /* quotedbl */\n    {0x0023, 0x0023}, /* numbersign */\n    {0x0024, 0x0024}, /* dollar */\n    {0x0025, 0x0025}, /* percent */\n    {0x0026, 0x0026}, /* ampersand */\n    {0x0027, 0x0027}, /* apostrophe */\n    {0x0028, 0x0028}, /* parenleft */\n    {0x0029, 0x0029}, /* parenright */\n    {0x002a, 0x002a}, /* asterisk */\n    {0x002b, 0x002b}, /* plus */\n    {0x002c, 0x002c}, /* comma */\n    {0x002d, 0x002d}, /* minus */\n    {0x002e, 0x002e}, /* period */\n    {0x002f, 0x002f}, /* slash */\n    {0x0030, 0x0030}, /* 0 */\n    {0x0031, 0x0031}, /* 1 */\n    {0x0032, 0x0032}, /* 2 */\n    {0x0033, 0x0033}, /* 3 */\n    {0x0034, 0x0034}, /* 4 */\n    {0x0035, 0x0035}, /* 5 */\n    {0x0036, 0x0036}, /* 6 */\n    {0x0037, 0x0037}, /* 7 */\n    {0x0038, 0x0038}, /* 8 */\n    {0x0039, 0x0039}, /* 9 */\n    {0x003a, 0x003a}, /* colon */\n    {0x003b, 0x003b}, /* semicolon */\n    {0x003c, 0x003c}, /* less */\n    {0x003d, 0x003d}, /* equal */\n    {0x003e, 0x003e}, /* greater */\n    {0x003f, 0x003f}, /* question */\n    {0x0040, 0x0040}, /* at */\n    {0x0041, 0x0041}, /* A */\n    {0x0042, 0x0042}, /* B */\n    {0x0043, 0x0043}, /* C */\n    {0x0044, 0x0044}, /* D */\n    {0x0045, 0x0045}, /* E */\n    {0x0046, 0x0046}, /* F */\n    {0x0047, 0x0047}, /* G */\n    {0x0048, 0x0048}, /* H */\n    {0x0049, 0x0049}, /* I */\n    {0x004a, 0x004a}, /* J */\n    {0x004b, 0x004b}, /* K */\n    {0x004c, 0x004c}, /* L */\n    {0x004d, 0x004d}, /* M */\n    {0x004e, 0x004e}, /* N */\n    {0x004f, 0x004f}, /* O */\n    {0x0050, 0x0050}, /* P */\n    {0x0051, 0x0051}, /* Q */\n    {0x0052, 0x0052}, /* R */\n    {0x0053, 0x0053}, /* S */\n    {0x0054, 0x0054}, /* T */\n    {0x0055, 0x0055}, /* U */\n    {0x0056, 0x0056}, /* V */\n    {0x0057, 0x0057}, /* W */\n    {0x0058, 0x0058}, /* X */\n    {0x0059, 0x0059}, /* Y */\n    {0x005a, 0x005a}, /* Z */\n    {0x005b, 0x005b}, /* bracketleft */\n    {0x005c, 0x005c}, /* backslash */\n    {0x005d, 0x005d}, /* bracketright */\n    {0x005e, 0x005e}, /* asciicircum */\n    {0x005f, 0x005f}, /* underscore */\n    {0x0060, 0x0060}, /* grave */\n    {0x0061, 0x0061}, /* a */\n    {0x0062, 0x0062}, /* b */\n    {0x0063, 0x0063}, /* c */\n    {0x0064, 0x0064}, /* d */\n    {0x0065, 0x0065}, /* e */\n    {0x0066, 0x0066}, /* f */\n    {0x0067, 0x0067}, /* g */\n    {0x0068, 0x0068}, /* h */\n    {0x0069, 0x0069}, /* i */\n    {0x006a, 0x006a}, /* j */\n    {0x006b, 0x006b}, /* k */\n    {0x006c, 0x006c}, /* l */\n    {0x006d, 0x006d}, /* m */\n    {0x006e, 0x006e}, /* n */\n    {0x006f, 0x006f}, /* o */\n    {0x0070, 0x0070}, /* p */\n    {0x0071, 0x0071}, /* q */\n    {0x0072, 0x0072}, /* r */\n    {0x0073, 0x0073}, /* s */\n    {0x0074, 0x0074}, /* t */\n    {0x0075, 0x0075}, /* u */\n    {0x0076, 0x0076}, /* v */\n    {0x0077, 0x0077}, /* w */\n    {0x0078, 0x0078}, /* x */\n    {0x0079, 0x0079}, /* y */\n    {0x007a, 0x007a}, /* z */\n    {0x007b, 0x007b}, /* braceleft */\n    {0x007c, 0x007c}, /* bar */\n    {0x007d, 0x007d}, /* braceright */\n    {0x007e, 0x007e}, /* asciitilde */\n    {0x00a0, 0x00a0}, /* nobreakspace */\n    {0x00a1, 0x00a1}, /* exclamdown */\n    {0x00a2, 0x00a2}, /* cent */\n    {0x00a3, 0x00a3}, /* sterling */\n    {0x00a4, 0x00a4}, /* currency */\n    {0x00a5, 0x00a5}, /* yen */\n    {0x00a6, 0x00a6}, /* brokenbar */\n    {0x00a7, 0x00a7}, /* section */\n    {0x00a8, 0x00a8}, /* diaeresis */\n    {0x00a9, 0x00a9}, /* copyright */\n    {0x00aa, 0x00aa}, /* ordfeminine */\n    {0x00ab, 0x00ab}, /* guillemotleft */\n    {0x00ac, 0x00ac}, /* notsign */\n    {0x00ad, 0x00ad}, /* hyphen */\n    {0x00ae, 0x00ae}, /* registered */\n    {0x00af, 0x00af}, /* macron */\n    {0x00b0, 0x00b0}, /* degree */\n    {0x00b1, 0x00b1}, /* plusminus */\n    {0x00b2, 0x00b2}, /* twosuperior */\n    {0x00b3, 0x00b3}, /* threesuperior */\n    {0x00b4, 0x00b4}, /* acute */\n    {0x00b5, 0x00b5}, /* mu */\n    {0x00b6, 0x00b6}, /* paragraph */\n    {0x00b7, 0x00b7}, /* periodcentered */\n    {0x00b8, 0x00b8}, /* cedilla */\n    {0x00b9, 0x00b9}, /* onesuperior */\n    {0x00ba, 0x00ba}, /* masculine */\n    {0x00bb, 0x00bb}, /* guillemotright */\n    {0x00bc, 0x00bc}, /* onequarter */\n    {0x00bd, 0x00bd}, /* onehalf */\n    {0x00be, 0x00be}, /* threequarters */\n    {0x00bf, 0x00bf}, /* questiondown */\n    {0x00c0, 0x00c0}, /* Agrave */\n    {0x00c1, 0x00c1}, /* Aacute */\n    {0x00c2, 0x00c2}, /* Acircumflex */\n    {0x00c3, 0x00c3}, /* Atilde */\n    {0x00c4, 0x00c4}, /* Adiaeresis */\n    {0x00c5, 0x00c5}, /* Aring */\n    {0x00c6, 0x00c6}, /* AE */\n    {0x00c7, 0x00c7}, /* Ccedilla */\n    {0x00c8, 0x00c8}, /* Egrave */\n    {0x00c9, 0x00c9}, /* Eacute */\n    {0x00ca, 0x00ca}, /* Ecircumflex */\n    {0x00cb, 0x00cb}, /* Ediaeresis */\n    {0x00cc, 0x00cc}, /* Igrave */\n    {0x00cd, 0x00cd}, /* Iacute */\n    {0x00ce, 0x00ce}, /* Icircumflex */\n    {0x00cf, 0x00cf}, /* Idiaeresis */\n    {0x00d0, 0x00d0}, /* ETH */\n    {0x00d1, 0x00d1}, /* Ntilde */\n    {0x00d2, 0x00d2}, /* Ograve */\n    {0x00d3, 0x00d3}, /* Oacute */\n    {0x00d4, 0x00d4}, /* Ocircumflex */\n    {0x00d5, 0x00d5}, /* Otilde */\n    {0x00d6, 0x00d6}, /* Odiaeresis */\n    {0x00d7, 0x00d7}, /* multiply */\n    {0x00d8, 0x00d8}, /* Oslash */\n    {0x00d9, 0x00d9}, /* Ugrave */\n    {0x00da, 0x00da}, /* Uacute */\n    {0x00db, 0x00db}, /* Ucircumflex */\n    {0x00dc, 0x00dc}, /* Udiaeresis */\n    {0x00dd, 0x00dd}, /* Yacute */\n    {0x00de, 0x00de}, /* THORN */\n    {0x00df, 0x00df}, /* ssharp */\n    {0x00e0, 0x00e0}, /* agrave */\n    {0x00e1, 0x00e1}, /* aacute */\n    {0x00e2, 0x00e2}, /* acircumflex */\n    {0x00e3, 0x00e3}, /* atilde */\n    {0x00e4, 0x00e4}, /* adiaeresis */\n    {0x00e5, 0x00e5}, /* aring */\n    {0x00e6, 0x00e6}, /* ae */\n    {0x00e7, 0x00e7}, /* ccedilla */\n    {0x00e8, 0x00e8}, /* egrave */\n    {0x00e9, 0x00e9}, /* eacute */\n    {0x00ea, 0x00ea}, /* ecircumflex */\n    {0x00eb, 0x00eb}, /* ediaeresis */\n    {0x00ec, 0x00ec}, /* igrave */\n    {0x00ed, 0x00ed}, /* iacute */\n    {0x00ee, 0x00ee}, /* icircumflex */\n    {0x00ef, 0x00ef}, /* idiaeresis */\n    {0x00f0, 0x00f0}, /* eth */\n    {0x00f1, 0x00f1}, /* ntilde */\n    {0x00f2, 0x00f2}, /* ograve */\n    {0x00f3, 0x00f3}, /* oacute */\n    {0x00f4, 0x00f4}, /* ocircumflex */\n    {0x00f5, 0x00f5}, /* otilde */\n    {0x00f6, 0x00f6}, /* odiaeresis */\n    {0x00f7, 0x00f7}, /* division */\n    {0x00f8, 0x00f8}, /* oslash */\n    {0x00f9, 0x00f9}, /* ugrave */\n    {0x00fa, 0x00fa}, /* uacute */\n    {0x00fb, 0x00fb}, /* ucircumflex */\n    {0x00fc, 0x00fc}, /* udiaeresis */\n    {0x00fd, 0x00fd}, /* yacute */\n    {0x00fe, 0x00fe}, /* thorn */\n    {0x00ff, 0x00ff}, /* ydiaeresis */\n    {0x01a1, 0x0104}, /* Aogonek */\n    {0x01a2, 0x02d8}, /* breve */\n    {0x01a3, 0x0141}, /* Lstroke */\n    {0x01a5, 0x013d}, /* Lcaron */\n    {0x01a6, 0x015a}, /* Sacute */\n    {0x01a9, 0x0160}, /* Scaron */\n    {0x01aa, 0x015e}, /* Scedilla */\n    {0x01ab, 0x0164}, /* Tcaron */\n    {0x01ac, 0x0179}, /* Zacute */\n    {0x01ae, 0x017d}, /* Zcaron */\n    {0x01af, 0x017b}, /* Zabovedot */\n    {0x01b1, 0x0105}, /* aogonek */\n    {0x01b2, 0x02db}, /* ogonek */\n    {0x01b3, 0x0142}, /* lstroke */\n    {0x01b5, 0x013e}, /* lcaron */\n    {0x01b6, 0x015b}, /* sacute */\n    {0x01b7, 0x02c7}, /* caron */\n    {0x01b9, 0x0161}, /* scaron */\n    {0x01ba, 0x015f}, /* scedilla */\n    {0x01bb, 0x0165}, /* tcaron */\n    {0x01bc, 0x017a}, /* zacute */\n    {0x01bd, 0x02dd}, /* doubleacute */\n    {0x01be, 0x017e}, /* zcaron */\n    {0x01bf, 0x017c}, /* zabovedot */\n    {0x01c0, 0x0154}, /* Racute */\n    {0x01c3, 0x0102}, /* Abreve */\n    {0x01c5, 0x0139}, /* Lacute */\n    {0x01c6, 0x0106}, /* Cacute */\n    {0x01c8, 0x010c}, /* Ccaron */\n    {0x01ca, 0x0118}, /* Eogonek */\n    {0x01cc, 0x011a}, /* Ecaron */\n    {0x01cf, 0x010e}, /* Dcaron */\n    {0x01d0, 0x0110}, /* Dstroke */\n    {0x01d1, 0x0143}, /* Nacute */\n    {0x01d2, 0x0147}, /* Ncaron */\n    {0x01d5, 0x0150}, /* Odoubleacute */\n    {0x01d8, 0x0158}, /* Rcaron */\n    {0x01d9, 0x016e}, /* Uring */\n    {0x01db, 0x0170}, /* Udoubleacute */\n    {0x01de, 0x0162}, /* Tcedilla */\n    {0x01e0, 0x0155}, /* racute */\n    {0x01e3, 0x0103}, /* abreve */\n    {0x01e5, 0x013a}, /* lacute */\n    {0x01e6, 0x0107}, /* cacute */\n    {0x01e8, 0x010d}, /* ccaron */\n    {0x01ea, 0x0119}, /* eogonek */\n    {0x01ec, 0x011b}, /* ecaron */\n    {0x01ef, 0x010f}, /* dcaron */\n    {0x01f0, 0x0111}, /* dstroke */\n    {0x01f1, 0x0144}, /* nacute */\n    {0x01f2, 0x0148}, /* ncaron */\n    {0x01f5, 0x0151}, /* odoubleacute */\n    {0x01f8, 0x0159}, /* rcaron */\n    {0x01f9, 0x016f}, /* uring */\n    {0x01fb, 0x0171}, /* udoubleacute */\n    {0x01fe, 0x0163}, /* tcedilla */\n    {0x01ff, 0x02d9}, /* abovedot */\n    {0x02a1, 0x0126}, /* Hstroke */\n    {0x02a6, 0x0124}, /* Hcircumflex */\n    {0x02a9, 0x0130}, /* Iabovedot */\n    {0x02ab, 0x011e}, /* Gbreve */\n    {0x02ac, 0x0134}, /* Jcircumflex */\n    {0x02b1, 0x0127}, /* hstroke */\n    {0x02b6, 0x0125}, /* hcircumflex */\n    {0x02b9, 0x0131}, /* idotless */\n    {0x02bb, 0x011f}, /* gbreve */\n    {0x02bc, 0x0135}, /* jcircumflex */\n    {0x02c5, 0x010a}, /* Cabovedot */\n    {0x02c6, 0x0108}, /* Ccircumflex */\n    {0x02d5, 0x0120}, /* Gabovedot */\n    {0x02d8, 0x011c}, /* Gcircumflex */\n    {0x02dd, 0x016c}, /* Ubreve */\n    {0x02de, 0x015c}, /* Scircumflex */\n    {0x02e5, 0x010b}, /* cabovedot */\n    {0x02e6, 0x0109}, /* ccircumflex */\n    {0x02f5, 0x0121}, /* gabovedot */\n    {0x02f8, 0x011d}, /* gcircumflex */\n    {0x02fd, 0x016d}, /* ubreve */\n    {0x02fe, 0x015d}, /* scircumflex */\n    {0x03a2, 0x0138}, /* kra */\n    {0x03a3, 0x0156}, /* Rcedilla */\n    {0x03a5, 0x0128}, /* Itilde */\n    {0x03a6, 0x013b}, /* Lcedilla */\n    {0x03aa, 0x0112}, /* Emacron */\n    {0x03ab, 0x0122}, /* Gcedilla */\n    {0x03ac, 0x0166}, /* Tslash */\n    {0x03b3, 0x0157}, /* rcedilla */\n    {0x03b5, 0x0129}, /* itilde */\n    {0x03b6, 0x013c}, /* lcedilla */\n    {0x03ba, 0x0113}, /* emacron */\n    {0x03bb, 0x0123}, /* gcedilla */\n    {0x03bc, 0x0167}, /* tslash */\n    {0x03bd, 0x014a}, /* ENG */\n    {0x03bf, 0x014b}, /* eng */\n    {0x03c0, 0x0100}, /* Amacron */\n    {0x03c7, 0x012e}, /* Iogonek */\n    {0x03cc, 0x0116}, /* Eabovedot */\n    {0x03cf, 0x012a}, /* Imacron */\n    {0x03d1, 0x0145}, /* Ncedilla */\n    {0x03d2, 0x014c}, /* Omacron */\n    {0x03d3, 0x0136}, /* Kcedilla */\n    {0x03d9, 0x0172}, /* Uogonek */\n    {0x03dd, 0x0168}, /* Utilde */\n    {0x03de, 0x016a}, /* Umacron */\n    {0x03e0, 0x0101}, /* amacron */\n    {0x03e7, 0x012f}, /* iogonek */\n    {0x03ec, 0x0117}, /* eabovedot */\n    {0x03ef, 0x012b}, /* imacron */\n    {0x03f1, 0x0146}, /* ncedilla */\n    {0x03f2, 0x014d}, /* omacron */\n    {0x03f3, 0x0137}, /* kcedilla */\n    {0x03f9, 0x0173}, /* uogonek */\n    {0x03fd, 0x0169}, /* utilde */\n    {0x03fe, 0x016b}, /* umacron */\n    {0x047e, 0x203e}, /* overline */\n    {0x04a1, 0x3002}, /* kana_fullstop */\n    {0x04a2, 0x300c}, /* kana_openingbracket */\n    {0x04a3, 0x300d}, /* kana_closingbracket */\n    {0x04a4, 0x3001}, /* kana_comma */\n    {0x04a5, 0x30fb}, /* kana_conjunctive */\n    {0x04a6, 0x30f2}, /* kana_WO */\n    {0x04a7, 0x30a1}, /* kana_a */\n    {0x04a8, 0x30a3}, /* kana_i */\n    {0x04a9, 0x30a5}, /* kana_u */\n    {0x04aa, 0x30a7}, /* kana_e */\n    {0x04ab, 0x30a9}, /* kana_o */\n    {0x04ac, 0x30e3}, /* kana_ya */\n    {0x04ad, 0x30e5}, /* kana_yu */\n    {0x04ae, 0x30e7}, /* kana_yo */\n    {0x04af, 0x30c3}, /* kana_tsu */\n    {0x04b0, 0x30fc}, /* prolongedsound */\n    {0x04b1, 0x30a2}, /* kana_A */\n    {0x04b2, 0x30a4}, /* kana_I */\n    {0x04b3, 0x30a6}, /* kana_U */\n    {0x04b4, 0x30a8}, /* kana_E */\n    {0x04b5, 0x30aa}, /* kana_O */\n    {0x04b6, 0x30ab}, /* kana_KA */\n    {0x04b7, 0x30ad}, /* kana_KI */\n    {0x04b8, 0x30af}, /* kana_KU */\n    {0x04b9, 0x30b1}, /* kana_KE */\n    {0x04ba, 0x30b3}, /* kana_KO */\n    {0x04bb, 0x30b5}, /* kana_SA */\n    {0x04bc, 0x30b7}, /* kana_SHI */\n    {0x04bd, 0x30b9}, /* kana_SU */\n    {0x04be, 0x30bb}, /* kana_SE */\n    {0x04bf, 0x30bd}, /* kana_SO */\n    {0x04c0, 0x30bf}, /* kana_TA */\n    {0x04c1, 0x30c1}, /* kana_CHI */\n    {0x04c2, 0x30c4}, /* kana_TSU */\n    {0x04c3, 0x30c6}, /* kana_TE */\n    {0x04c4, 0x30c8}, /* kana_TO */\n    {0x04c5, 0x30ca}, /* kana_NA */\n    {0x04c6, 0x30cb}, /* kana_NI */\n    {0x04c7, 0x30cc}, /* kana_NU */\n    {0x04c8, 0x30cd}, /* kana_NE */\n    {0x04c9, 0x30ce}, /* kana_NO */\n    {0x04ca, 0x30cf}, /* kana_HA */\n    {0x04cb, 0x30d2}, /* kana_HI */\n    {0x04cc, 0x30d5}, /* kana_FU */\n    {0x04cd, 0x30d8}, /* kana_HE */\n    {0x04ce, 0x30db}, /* kana_HO */\n    {0x04cf, 0x30de}, /* kana_MA */\n    {0x04d0, 0x30df}, /* kana_MI */\n    {0x04d1, 0x30e0}, /* kana_MU */\n    {0x04d2, 0x30e1}, /* kana_ME */\n    {0x04d3, 0x30e2}, /* kana_MO */\n    {0x04d4, 0x30e4}, /* kana_YA */\n    {0x04d5, 0x30e6}, /* kana_YU */\n    {0x04d6, 0x30e8}, /* kana_YO */\n    {0x04d7, 0x30e9}, /* kana_RA */\n    {0x04d8, 0x30ea}, /* kana_RI */\n    {0x04d9, 0x30eb}, /* kana_RU */\n    {0x04da, 0x30ec}, /* kana_RE */\n    {0x04db, 0x30ed}, /* kana_RO */\n    {0x04dc, 0x30ef}, /* kana_WA */\n    {0x04dd, 0x30f3}, /* kana_N */\n    {0x04de, 0x309b}, /* voicedsound */\n    {0x04df, 0x309c}, /* semivoicedsound */\n    {0x05ac, 0x060c}, /* Arabic_comma */\n    {0x05bb, 0x061b}, /* Arabic_semicolon */\n    {0x05bf, 0x061f}, /* Arabic_question_mark */\n    {0x05c1, 0x0621}, /* Arabic_hamza */\n    {0x05c2, 0x0622}, /* Arabic_maddaonalef */\n    {0x05c3, 0x0623}, /* Arabic_hamzaonalef */\n    {0x05c4, 0x0624}, /* Arabic_hamzaonwaw */\n    {0x05c5, 0x0625}, /* Arabic_hamzaunderalef */\n    {0x05c6, 0x0626}, /* Arabic_hamzaonyeh */\n    {0x05c7, 0x0627}, /* Arabic_alef */\n    {0x05c8, 0x0628}, /* Arabic_beh */\n    {0x05c9, 0x0629}, /* Arabic_tehmarbuta */\n    {0x05ca, 0x062a}, /* Arabic_teh */\n    {0x05cb, 0x062b}, /* Arabic_theh */\n    {0x05cc, 0x062c}, /* Arabic_jeem */\n    {0x05cd, 0x062d}, /* Arabic_hah */\n    {0x05ce, 0x062e}, /* Arabic_khah */\n    {0x05cf, 0x062f}, /* Arabic_dal */\n    {0x05d0, 0x0630}, /* Arabic_thal */\n    {0x05d1, 0x0631}, /* Arabic_ra */\n    {0x05d2, 0x0632}, /* Arabic_zain */\n    {0x05d3, 0x0633}, /* Arabic_seen */\n    {0x05d4, 0x0634}, /* Arabic_sheen */\n    {0x05d5, 0x0635}, /* Arabic_sad */\n    {0x05d6, 0x0636}, /* Arabic_dad */\n    {0x05d7, 0x0637}, /* Arabic_tah */\n    {0x05d8, 0x0638}, /* Arabic_zah */\n    {0x05d9, 0x0639}, /* Arabic_ain */\n    {0x05da, 0x063a}, /* Arabic_ghain */\n    {0x05e0, 0x0640}, /* Arabic_tatweel */\n    {0x05e1, 0x0641}, /* Arabic_feh */\n    {0x05e2, 0x0642}, /* Arabic_qaf */\n    {0x05e3, 0x0643}, /* Arabic_kaf */\n    {0x05e4, 0x0644}, /* Arabic_lam */\n    {0x05e5, 0x0645}, /* Arabic_meem */\n    {0x05e6, 0x0646}, /* Arabic_noon */\n    {0x05e7, 0x0647}, /* Arabic_ha */\n    {0x05e8, 0x0648}, /* Arabic_waw */\n    {0x05e9, 0x0649}, /* Arabic_alefmaksura */\n    {0x05ea, 0x064a}, /* Arabic_yeh */\n    {0x05eb, 0x064b}, /* Arabic_fathatan */\n    {0x05ec, 0x064c}, /* Arabic_dammatan */\n    {0x05ed, 0x064d}, /* Arabic_kasratan */\n    {0x05ee, 0x064e}, /* Arabic_fatha */\n    {0x05ef, 0x064f}, /* Arabic_damma */\n    {0x05f0, 0x0650}, /* Arabic_kasra */\n    {0x05f1, 0x0651}, /* Arabic_shadda */\n    {0x05f2, 0x0652}, /* Arabic_sukun */\n    {0x06a1, 0x0452}, /* Serbian_dje */\n    {0x06a2, 0x0453}, /* Macedonia_gje */\n    {0x06a3, 0x0451}, /* Cyrillic_io */\n    {0x06a4, 0x0454}, /* Ukrainian_ie */\n    {0x06a5, 0x0455}, /* Macedonia_dse */\n    {0x06a6, 0x0456}, /* Ukrainian_i */\n    {0x06a7, 0x0457}, /* Ukrainian_yi */\n    {0x06a8, 0x0458}, /* Cyrillic_je */\n    {0x06a9, 0x0459}, /* Cyrillic_lje */\n    {0x06aa, 0x045a}, /* Cyrillic_nje */\n    {0x06ab, 0x045b}, /* Serbian_tshe */\n    {0x06ac, 0x045c}, /* Macedonia_kje */\n    {0x06ae, 0x045e}, /* Byelorussian_shortu */\n    {0x06af, 0x045f}, /* Cyrillic_dzhe */\n    {0x06b0, 0x2116}, /* numerosign */\n    {0x06b1, 0x0402}, /* Serbian_DJE */\n    {0x06b2, 0x0403}, /* Macedonia_GJE */\n    {0x06b3, 0x0401}, /* Cyrillic_IO */\n    {0x06b4, 0x0404}, /* Ukrainian_IE */\n    {0x06b5, 0x0405}, /* Macedonia_DSE */\n    {0x06b6, 0x0406}, /* Ukrainian_I */\n    {0x06b7, 0x0407}, /* Ukrainian_YI */\n    {0x06b8, 0x0408}, /* Cyrillic_JE */\n    {0x06b9, 0x0409}, /* Cyrillic_LJE */\n    {0x06ba, 0x040a}, /* Cyrillic_NJE */\n    {0x06bb, 0x040b}, /* Serbian_TSHE */\n    {0x06bc, 0x040c}, /* Macedonia_KJE */\n    {0x06be, 0x040e}, /* Byelorussian_SHORTU */\n    {0x06bf, 0x040f}, /* Cyrillic_DZHE */\n    {0x06c0, 0x044e}, /* Cyrillic_yu */\n    {0x06c1, 0x0430}, /* Cyrillic_a */\n    {0x06c2, 0x0431}, /* Cyrillic_be */\n    {0x06c3, 0x0446}, /* Cyrillic_tse */\n    {0x06c4, 0x0434}, /* Cyrillic_de */\n    {0x06c5, 0x0435}, /* Cyrillic_ie */\n    {0x06c6, 0x0444}, /* Cyrillic_ef */\n    {0x06c7, 0x0433}, /* Cyrillic_ghe */\n    {0x06c8, 0x0445}, /* Cyrillic_ha */\n    {0x06c9, 0x0438}, /* Cyrillic_i */\n    {0x06ca, 0x0439}, /* Cyrillic_shorti */\n    {0x06cb, 0x043a}, /* Cyrillic_ka */\n    {0x06cc, 0x043b}, /* Cyrillic_el */\n    {0x06cd, 0x043c}, /* Cyrillic_em */\n    {0x06ce, 0x043d}, /* Cyrillic_en */\n    {0x06cf, 0x043e}, /* Cyrillic_o */\n    {0x06d0, 0x043f}, /* Cyrillic_pe */\n    {0x06d1, 0x044f}, /* Cyrillic_ya */\n    {0x06d2, 0x0440}, /* Cyrillic_er */\n    {0x06d3, 0x0441}, /* Cyrillic_es */\n    {0x06d4, 0x0442}, /* Cyrillic_te */\n    {0x06d5, 0x0443}, /* Cyrillic_u */\n    {0x06d6, 0x0436}, /* Cyrillic_zhe */\n    {0x06d7, 0x0432}, /* Cyrillic_ve */\n    {0x06d8, 0x044c}, /* Cyrillic_softsign */\n    {0x06d9, 0x044b}, /* Cyrillic_yeru */\n    {0x06da, 0x0437}, /* Cyrillic_ze */\n    {0x06db, 0x0448}, /* Cyrillic_sha */\n    {0x06dc, 0x044d}, /* Cyrillic_e */\n    {0x06dd, 0x0449}, /* Cyrillic_shcha */\n    {0x06de, 0x0447}, /* Cyrillic_che */\n    {0x06df, 0x044a}, /* Cyrillic_hardsign */\n    {0x06e0, 0x042e}, /* Cyrillic_YU */\n    {0x06e1, 0x0410}, /* Cyrillic_A */\n    {0x06e2, 0x0411}, /* Cyrillic_BE */\n    {0x06e3, 0x0426}, /* Cyrillic_TSE */\n    {0x06e4, 0x0414}, /* Cyrillic_DE */\n    {0x06e5, 0x0415}, /* Cyrillic_IE */\n    {0x06e6, 0x0424}, /* Cyrillic_EF */\n    {0x06e7, 0x0413}, /* Cyrillic_GHE */\n    {0x06e8, 0x0425}, /* Cyrillic_HA */\n    {0x06e9, 0x0418}, /* Cyrillic_I */\n    {0x06ea, 0x0419}, /* Cyrillic_SHORTI */\n    {0x06eb, 0x041a}, /* Cyrillic_KA */\n    {0x06ec, 0x041b}, /* Cyrillic_EL */\n    {0x06ed, 0x041c}, /* Cyrillic_EM */\n    {0x06ee, 0x041d}, /* Cyrillic_EN */\n    {0x06ef, 0x041e}, /* Cyrillic_O */\n    {0x06f0, 0x041f}, /* Cyrillic_PE */\n    {0x06f1, 0x042f}, /* Cyrillic_YA */\n    {0x06f2, 0x0420}, /* Cyrillic_ER */\n    {0x06f3, 0x0421}, /* Cyrillic_ES */\n    {0x06f4, 0x0422}, /* Cyrillic_TE */\n    {0x06f5, 0x0423}, /* Cyrillic_U */\n    {0x06f6, 0x0416}, /* Cyrillic_ZHE */\n    {0x06f7, 0x0412}, /* Cyrillic_VE */\n    {0x06f8, 0x042c}, /* Cyrillic_SOFTSIGN */\n    {0x06f9, 0x042b}, /* Cyrillic_YERU */\n    {0x06fa, 0x0417}, /* Cyrillic_ZE */\n    {0x06fb, 0x0428}, /* Cyrillic_SHA */\n    {0x06fc, 0x042d}, /* Cyrillic_E */\n    {0x06fd, 0x0429}, /* Cyrillic_SHCHA */\n    {0x06fe, 0x0427}, /* Cyrillic_CHE */\n    {0x06ff, 0x042a}, /* Cyrillic_HARDSIGN */\n    {0x07a1, 0x0386}, /* Greek_ALPHAaccent */\n    {0x07a2, 0x0388}, /* Greek_EPSILONaccent */\n    {0x07a3, 0x0389}, /* Greek_ETAaccent */\n    {0x07a4, 0x038a}, /* Greek_IOTAaccent */\n    {0x07a5, 0x03aa}, /* Greek_IOTAdiaeresis */\n    {0x07a7, 0x038c}, /* Greek_OMICRONaccent */\n    {0x07a8, 0x038e}, /* Greek_UPSILONaccent */\n    {0x07a9, 0x03ab}, /* Greek_UPSILONdieresis */\n    {0x07ab, 0x038f}, /* Greek_OMEGAaccent */\n    {0x07ae, 0x0385}, /* Greek_accentdieresis */\n    {0x07af, 0x2015}, /* Greek_horizbar */\n    {0x07b1, 0x03ac}, /* Greek_alphaaccent */\n    {0x07b2, 0x03ad}, /* Greek_epsilonaccent */\n    {0x07b3, 0x03ae}, /* Greek_etaaccent */\n    {0x07b4, 0x03af}, /* Greek_iotaaccent */\n    {0x07b5, 0x03ca}, /* Greek_iotadieresis */\n    {0x07b6, 0x0390}, /* Greek_iotaaccentdieresis */\n    {0x07b7, 0x03cc}, /* Greek_omicronaccent */\n    {0x07b8, 0x03cd}, /* Greek_upsilonaccent */\n    {0x07b9, 0x03cb}, /* Greek_upsilondieresis */\n    {0x07ba, 0x03b0}, /* Greek_upsilonaccentdieresis */\n    {0x07bb, 0x03ce}, /* Greek_omegaaccent */\n    {0x07c1, 0x0391}, /* Greek_ALPHA */\n    {0x07c2, 0x0392}, /* Greek_BETA */\n    {0x07c3, 0x0393}, /* Greek_GAMMA */\n    {0x07c4, 0x0394}, /* Greek_DELTA */\n    {0x07c5, 0x0395}, /* Greek_EPSILON */\n    {0x07c6, 0x0396}, /* Greek_ZETA */\n    {0x07c7, 0x0397}, /* Greek_ETA */\n    {0x07c8, 0x0398}, /* Greek_THETA */\n    {0x07c9, 0x0399}, /* Greek_IOTA */\n    {0x07ca, 0x039a}, /* Greek_KAPPA */\n    {0x07cb, 0x039b}, /* Greek_LAMBDA */\n    {0x07cc, 0x039c}, /* Greek_MU */\n    {0x07cd, 0x039d}, /* Greek_NU */\n    {0x07ce, 0x039e}, /* Greek_XI */\n    {0x07cf, 0x039f}, /* Greek_OMICRON */\n    {0x07d0, 0x03a0}, /* Greek_PI */\n    {0x07d1, 0x03a1}, /* Greek_RHO */\n    {0x07d2, 0x03a3}, /* Greek_SIGMA */\n    {0x07d4, 0x03a4}, /* Greek_TAU */\n    {0x07d5, 0x03a5}, /* Greek_UPSILON */\n    {0x07d6, 0x03a6}, /* Greek_PHI */\n    {0x07d7, 0x03a7}, /* Greek_CHI */\n    {0x07d8, 0x03a8}, /* Greek_PSI */\n    {0x07d9, 0x03a9}, /* Greek_OMEGA */\n    {0x07e1, 0x03b1}, /* Greek_alpha */\n    {0x07e2, 0x03b2}, /* Greek_beta */\n    {0x07e3, 0x03b3}, /* Greek_gamma */\n    {0x07e4, 0x03b4}, /* Greek_delta */\n    {0x07e5, 0x03b5}, /* Greek_epsilon */\n    {0x07e6, 0x03b6}, /* Greek_zeta */\n    {0x07e7, 0x03b7}, /* Greek_eta */\n    {0x07e8, 0x03b8}, /* Greek_theta */\n    {0x07e9, 0x03b9}, /* Greek_iota */\n    {0x07ea, 0x03ba}, /* Greek_kappa */\n    {0x07eb, 0x03bb}, /* Greek_lambda */\n    {0x07ec, 0x03bc}, /* Greek_mu */\n    {0x07ed, 0x03bd}, /* Greek_nu */\n    {0x07ee, 0x03be}, /* Greek_xi */\n    {0x07ef, 0x03bf}, /* Greek_omicron */\n    {0x07f0, 0x03c0}, /* Greek_pi */\n    {0x07f1, 0x03c1}, /* Greek_rho */\n    {0x07f2, 0x03c3}, /* Greek_sigma */\n    {0x07f3, 0x03c2}, /* Greek_finalsmallsigma */\n    {0x07f4, 0x03c4}, /* Greek_tau */\n    {0x07f5, 0x03c5}, /* Greek_upsilon */\n    {0x07f6, 0x03c6}, /* Greek_phi */\n    {0x07f7, 0x03c7}, /* Greek_chi */\n    {0x07f8, 0x03c8}, /* Greek_psi */\n    {0x07f9, 0x03c9}, /* Greek_omega */\n    {0x08a1, 0x23b7}, /* leftradical */\n    {0x08a4, 0x2320}, /* topintegral */\n    {0x08a5, 0x2321}, /* botintegral */\n    {0x08a7, 0x23a1}, /* topleftsqbracket */\n    {0x08a8, 0x23a3}, /* botleftsqbracket */\n    {0x08a9, 0x23a4}, /* toprightsqbracket */\n    {0x08aa, 0x23a6}, /* botrightsqbracket */\n    {0x08ab, 0x239b}, /* topleftparens */\n    {0x08ac, 0x239d}, /* botleftparens */\n    {0x08ad, 0x239e}, /* toprightparens */\n    {0x08ae, 0x23a0}, /* botrightparens */\n    {0x08af, 0x23a8}, /* leftmiddlecurlybrace */\n    {0x08b0, 0x23ac}, /* rightmiddlecurlybrace */\n    {0x08bc, 0x2264}, /* lessthanequal */\n    {0x08bd, 0x2260}, /* notequal */\n    {0x08be, 0x2265}, /* greaterthanequal */\n    {0x08bf, 0x222b}, /* integral */\n    {0x08c0, 0x2234}, /* therefore */\n    {0x08c1, 0x221d}, /* variation */\n    {0x08c2, 0x221e}, /* infinity */\n    {0x08c5, 0x2207}, /* nabla */\n    {0x08c8, 0x223c}, /* approximate */\n    {0x08c9, 0x2243}, /* similarequal */\n    {0x08cd, 0x21d4}, /* ifonlyif */\n    {0x08ce, 0x21d2}, /* implies */\n    {0x08cf, 0x2261}, /* identical */\n    {0x08d6, 0x221a}, /* radical */\n    {0x08da, 0x2282}, /* includedin */\n    {0x08db, 0x2283}, /* includes */\n    {0x08dc, 0x2229}, /* intersection */\n    {0x08dd, 0x222a}, /* union */\n    {0x08de, 0x2227}, /* logicaland */\n    {0x08df, 0x2228}, /* logicalor */\n    {0x08ef, 0x2202}, /* partialderivative */\n    {0x08f6, 0x0192}, /* function */\n    {0x08fb, 0x2190}, /* leftarrow */\n    {0x08fc, 0x2191}, /* uparrow */\n    {0x08fd, 0x2192}, /* rightarrow */\n    {0x08fe, 0x2193}, /* downarrow */\n    {0x09e0, 0x25c6}, /* soliddiamond */\n    {0x09e1, 0x2592}, /* checkerboard */\n    {0x09e2, 0x2409}, /* ht */\n    {0x09e3, 0x240c}, /* ff */\n    {0x09e4, 0x240d}, /* cr */\n    {0x09e5, 0x240a}, /* lf */\n    {0x09e8, 0x2424}, /* nl */\n    {0x09e9, 0x240b}, /* vt */\n    {0x09ea, 0x2518}, /* lowrightcorner */\n    {0x09eb, 0x2510}, /* uprightcorner */\n    {0x09ec, 0x250c}, /* upleftcorner */\n    {0x09ed, 0x2514}, /* lowleftcorner */\n    {0x09ee, 0x253c}, /* crossinglines */\n    {0x09ef, 0x23ba}, /* horizlinescan1 */\n    {0x09f0, 0x23bb}, /* horizlinescan3 */\n    {0x09f1, 0x2500}, /* horizlinescan5 */\n    {0x09f2, 0x23bc}, /* horizlinescan7 */\n    {0x09f3, 0x23bd}, /* horizlinescan9 */\n    {0x09f4, 0x251c}, /* leftt */\n    {0x09f5, 0x2524}, /* rightt */\n    {0x09f6, 0x2534}, /* bott */\n    {0x09f7, 0x252c}, /* topt */\n    {0x09f8, 0x2502}, /* vertbar */\n    {0x0aa1, 0x2003}, /* emspace */\n    {0x0aa2, 0x2002}, /* enspace */\n    {0x0aa3, 0x2004}, /* em3space */\n    {0x0aa4, 0x2005}, /* em4space */\n    {0x0aa5, 0x2007}, /* digitspace */\n    {0x0aa6, 0x2008}, /* punctspace */\n    {0x0aa7, 0x2009}, /* thinspace */\n    {0x0aa8, 0x200a}, /* hairspace */\n    {0x0aa9, 0x2014}, /* emdash */\n    {0x0aaa, 0x2013}, /* endash */\n    {0x0aae, 0x2026}, /* ellipsis */\n    {0x0aaf, 0x2025}, /* doubbaselinedot */\n    {0x0ab0, 0x2153}, /* onethird */\n    {0x0ab1, 0x2154}, /* twothirds */\n    {0x0ab2, 0x2155}, /* onefifth */\n    {0x0ab3, 0x2156}, /* twofifths */\n    {0x0ab4, 0x2157}, /* threefifths */\n    {0x0ab5, 0x2158}, /* fourfifths */\n    {0x0ab6, 0x2159}, /* onesixth */\n    {0x0ab7, 0x215a}, /* fivesixths */\n    {0x0ab8, 0x2105}, /* careof */\n    {0x0abb, 0x2012}, /* figdash */\n    {0x0ac3, 0x215b}, /* oneeighth */\n    {0x0ac4, 0x215c}, /* threeeighths */\n    {0x0ac5, 0x215d}, /* fiveeighths */\n    {0x0ac6, 0x215e}, /* seveneighths */\n    {0x0ac9, 0x2122}, /* trademark */\n    {0x0ad0, 0x2018}, /* leftsinglequotemark */\n    {0x0ad1, 0x2019}, /* rightsinglequotemark */\n    {0x0ad2, 0x201c}, /* leftdoublequotemark */\n    {0x0ad3, 0x201d}, /* rightdoublequotemark */\n    {0x0ad4, 0x211e}, /* prescription */\n    {0x0ad6, 0x2032}, /* minutes */\n    {0x0ad7, 0x2033}, /* seconds */\n    {0x0ad9, 0x271d}, /* latincross */\n    {0x0aec, 0x2663}, /* club */\n    {0x0aed, 0x2666}, /* diamond */\n    {0x0aee, 0x2665}, /* heart */\n    {0x0af0, 0x2720}, /* maltesecross */\n    {0x0af1, 0x2020}, /* dagger */\n    {0x0af2, 0x2021}, /* doubledagger */\n    {0x0af3, 0x2713}, /* checkmark */\n    {0x0af4, 0x2717}, /* ballotcross */\n    {0x0af5, 0x266f}, /* musicalsharp */\n    {0x0af6, 0x266d}, /* musicalflat */\n    {0x0af7, 0x2642}, /* malesymbol */\n    {0x0af8, 0x2640}, /* femalesymbol */\n    {0x0af9, 0x260e}, /* telephone */\n    {0x0afa, 0x2315}, /* telephonerecorder */\n    {0x0afb, 0x2117}, /* phonographcopyright */\n    {0x0afc, 0x2038}, /* caret */\n    {0x0afd, 0x201a}, /* singlelowquotemark */\n    {0x0afe, 0x201e}, /* doublelowquotemark */\n    {0x0bc2, 0x22a5}, /* downtack */\n    {0x0bc4, 0x230a}, /* downstile */\n    {0x0bca, 0x2218}, /* jot */\n    {0x0bcc, 0x2395}, /* quad */\n    {0x0bce, 0x22a4}, /* uptack */\n    {0x0bcf, 0x25cb}, /* circle */\n    {0x0bd3, 0x2308}, /* upstile */\n    {0x0bdc, 0x22a2}, /* lefttack */\n    {0x0bfc, 0x22a3}, /* righttack */\n    {0x0cdf, 0x2017}, /* hebrew_doublelowline */\n    {0x0ce0, 0x05d0}, /* hebrew_aleph */\n    {0x0ce1, 0x05d1}, /* hebrew_bet */\n    {0x0ce2, 0x05d2}, /* hebrew_gimel */\n    {0x0ce3, 0x05d3}, /* hebrew_dalet */\n    {0x0ce4, 0x05d4}, /* hebrew_he */\n    {0x0ce5, 0x05d5}, /* hebrew_waw */\n    {0x0ce6, 0x05d6}, /* hebrew_zain */\n    {0x0ce7, 0x05d7}, /* hebrew_chet */\n    {0x0ce8, 0x05d8}, /* hebrew_tet */\n    {0x0ce9, 0x05d9}, /* hebrew_yod */\n    {0x0cea, 0x05da}, /* hebrew_finalkaph */\n    {0x0ceb, 0x05db}, /* hebrew_kaph */\n    {0x0cec, 0x05dc}, /* hebrew_lamed */\n    {0x0ced, 0x05dd}, /* hebrew_finalmem */\n    {0x0cee, 0x05de}, /* hebrew_mem */\n    {0x0cef, 0x05df}, /* hebrew_finalnun */\n    {0x0cf0, 0x05e0}, /* hebrew_nun */\n    {0x0cf1, 0x05e1}, /* hebrew_samech */\n    {0x0cf2, 0x05e2}, /* hebrew_ayin */\n    {0x0cf3, 0x05e3}, /* hebrew_finalpe */\n    {0x0cf4, 0x05e4}, /* hebrew_pe */\n    {0x0cf5, 0x05e5}, /* hebrew_finalzade */\n    {0x0cf6, 0x05e6}, /* hebrew_zade */\n    {0x0cf7, 0x05e7}, /* hebrew_qoph */\n    {0x0cf8, 0x05e8}, /* hebrew_resh */\n    {0x0cf9, 0x05e9}, /* hebrew_shin */\n    {0x0cfa, 0x05ea}, /* hebrew_taw */\n    {0x0da1, 0x0e01}, /* Thai_kokai */\n    {0x0da2, 0x0e02}, /* Thai_khokhai */\n    {0x0da3, 0x0e03}, /* Thai_khokhuat */\n    {0x0da4, 0x0e04}, /* Thai_khokhwai */\n    {0x0da5, 0x0e05}, /* Thai_khokhon */\n    {0x0da6, 0x0e06}, /* Thai_khorakhang */\n    {0x0da7, 0x0e07}, /* Thai_ngongu */\n    {0x0da8, 0x0e08}, /* Thai_chochan */\n    {0x0da9, 0x0e09}, /* Thai_choching */\n    {0x0daa, 0x0e0a}, /* Thai_chochang */\n    {0x0dab, 0x0e0b}, /* Thai_soso */\n    {0x0dac, 0x0e0c}, /* Thai_chochoe */\n    {0x0dad, 0x0e0d}, /* Thai_yoying */\n    {0x0dae, 0x0e0e}, /* Thai_dochada */\n    {0x0daf, 0x0e0f}, /* Thai_topatak */\n    {0x0db0, 0x0e10}, /* Thai_thothan */\n    {0x0db1, 0x0e11}, /* Thai_thonangmontho */\n    {0x0db2, 0x0e12}, /* Thai_thophuthao */\n    {0x0db3, 0x0e13}, /* Thai_nonen */\n    {0x0db4, 0x0e14}, /* Thai_dodek */\n    {0x0db5, 0x0e15}, /* Thai_totao */\n    {0x0db6, 0x0e16}, /* Thai_thothung */\n    {0x0db7, 0x0e17}, /* Thai_thothahan */\n    {0x0db8, 0x0e18}, /* Thai_thothong */\n    {0x0db9, 0x0e19}, /* Thai_nonu */\n    {0x0dba, 0x0e1a}, /* Thai_bobaimai */\n    {0x0dbb, 0x0e1b}, /* Thai_popla */\n    {0x0dbc, 0x0e1c}, /* Thai_phophung */\n    {0x0dbd, 0x0e1d}, /* Thai_fofa */\n    {0x0dbe, 0x0e1e}, /* Thai_phophan */\n    {0x0dbf, 0x0e1f}, /* Thai_fofan */\n    {0x0dc0, 0x0e20}, /* Thai_phosamphao */\n    {0x0dc1, 0x0e21}, /* Thai_moma */\n    {0x0dc2, 0x0e22}, /* Thai_yoyak */\n    {0x0dc3, 0x0e23}, /* Thai_rorua */\n    {0x0dc4, 0x0e24}, /* Thai_ru */\n    {0x0dc5, 0x0e25}, /* Thai_loling */\n    {0x0dc6, 0x0e26}, /* Thai_lu */\n    {0x0dc7, 0x0e27}, /* Thai_wowaen */\n    {0x0dc8, 0x0e28}, /* Thai_sosala */\n    {0x0dc9, 0x0e29}, /* Thai_sorusi */\n    {0x0dca, 0x0e2a}, /* Thai_sosua */\n    {0x0dcb, 0x0e2b}, /* Thai_hohip */\n    {0x0dcc, 0x0e2c}, /* Thai_lochula */\n    {0x0dcd, 0x0e2d}, /* Thai_oang */\n    {0x0dce, 0x0e2e}, /* Thai_honokhuk */\n    {0x0dcf, 0x0e2f}, /* Thai_paiyannoi */\n    {0x0dd0, 0x0e30}, /* Thai_saraa */\n    {0x0dd1, 0x0e31}, /* Thai_maihanakat */\n    {0x0dd2, 0x0e32}, /* Thai_saraaa */\n    {0x0dd3, 0x0e33}, /* Thai_saraam */\n    {0x0dd4, 0x0e34}, /* Thai_sarai */\n    {0x0dd5, 0x0e35}, /* Thai_saraii */\n    {0x0dd6, 0x0e36}, /* Thai_saraue */\n    {0x0dd7, 0x0e37}, /* Thai_sarauee */\n    {0x0dd8, 0x0e38}, /* Thai_sarau */\n    {0x0dd9, 0x0e39}, /* Thai_sarauu */\n    {0x0dda, 0x0e3a}, /* Thai_phinthu */\n    {0x0ddf, 0x0e3f}, /* Thai_baht */\n    {0x0de0, 0x0e40}, /* Thai_sarae */\n    {0x0de1, 0x0e41}, /* Thai_saraae */\n    {0x0de2, 0x0e42}, /* Thai_sarao */\n    {0x0de3, 0x0e43}, /* Thai_saraaimaimuan */\n    {0x0de4, 0x0e44}, /* Thai_saraaimaimalai */\n    {0x0de5, 0x0e45}, /* Thai_lakkhangyao */\n    {0x0de6, 0x0e46}, /* Thai_maiyamok */\n    {0x0de7, 0x0e47}, /* Thai_maitaikhu */\n    {0x0de8, 0x0e48}, /* Thai_maiek */\n    {0x0de9, 0x0e49}, /* Thai_maitho */\n    {0x0dea, 0x0e4a}, /* Thai_maitri */\n    {0x0deb, 0x0e4b}, /* Thai_maichattawa */\n    {0x0dec, 0x0e4c}, /* Thai_thanthakhat */\n    {0x0ded, 0x0e4d}, /* Thai_nikhahit */\n    {0x0df0, 0x0e50}, /* Thai_leksun */\n    {0x0df1, 0x0e51}, /* Thai_leknung */\n    {0x0df2, 0x0e52}, /* Thai_leksong */\n    {0x0df3, 0x0e53}, /* Thai_leksam */\n    {0x0df4, 0x0e54}, /* Thai_leksi */\n    {0x0df5, 0x0e55}, /* Thai_lekha */\n    {0x0df6, 0x0e56}, /* Thai_lekhok */\n    {0x0df7, 0x0e57}, /* Thai_lekchet */\n    {0x0df8, 0x0e58}, /* Thai_lekpaet */\n    {0x0df9, 0x0e59}, /* Thai_lekkao */\n    {0x13bc, 0x0152}, /* OE */\n    {0x13bd, 0x0153}, /* oe */\n    {0x13be, 0x0178}, /* Ydiaeresis */\n    {0x20a0, 0x20a0}, /* EcuSign */\n    {0x20a1, 0x20a1}, /* ColonSign */\n    {0x20a2, 0x20a2}, /* CruzeiroSign */\n    {0x20a3, 0x20a3}, /* FFrancSign */\n    {0x20a4, 0x20a4}, /* LiraSign */\n    {0x20a5, 0x20a5}, /* MillSign */\n    {0x20a6, 0x20a6}, /* NairaSign */\n    {0x20a7, 0x20a7}, /* PesetaSign */\n    {0x20a8, 0x20a8}, /* RupeeSign */\n    {0x20a9, 0x20a9}, /* WonSign */\n    {0x20aa, 0x20aa}, /* NewSheqelSign */\n    {0x20ab, 0x20ab}, /* DongSign */\n    {0x20ac, 0x20ac}, /* EuroSign */\n    {0x06ad, 0x0491}, /* Ukrainian_ghe_with_upturn */\n    {0x06bd, 0x0490}, /* Ukrainian_GHE_WITH_UPTURN */\n    {0x14a2, 0x0587}, /* Armenian_ligature_ew */\n    {0x14a3, 0x0589}, /* Armenian_verjaket */\n    {0x14aa, 0x055d}, /* Armenian_but */\n    {0x14ad, 0x058a}, /* Armenian_yentamna */\n    {0x14af, 0x055c}, /* Armenian_amanak */\n    {0x14b0, 0x055b}, /* Armenian_shesht */\n    {0x14b1, 0x055e}, /* Armenian_paruyk */\n    {0x14b2, 0x0531}, /* Armenian_AYB */\n    {0x14b3, 0x0561}, /* Armenian_ayb */\n    {0x14b4, 0x0532}, /* Armenian_BEN */\n    {0x14b5, 0x0562}, /* Armenian_ben */\n    {0x14b6, 0x0533}, /* Armenian_GIM */\n    {0x14b7, 0x0563}, /* Armenian_gim */\n    {0x14b8, 0x0534}, /* Armenian_DA */\n    {0x14b9, 0x0564}, /* Armenian_da */\n    {0x14ba, 0x0535}, /* Armenian_YECH */\n    {0x14bb, 0x0565}, /* Armenian_yech */\n    {0x14bc, 0x0536}, /* Armenian_ZA */\n    {0x14bd, 0x0566}, /* Armenian_za */\n    {0x14be, 0x0537}, /* Armenian_E */\n    {0x14bf, 0x0567}, /* Armenian_e */\n    {0x14c0, 0x0538}, /* Armenian_AT */\n    {0x14c1, 0x0568}, /* Armenian_at */\n    {0x14c2, 0x0539}, /* Armenian_TO */\n    {0x14c3, 0x0569}, /* Armenian_to */\n    {0x14c4, 0x053a}, /* Armenian_ZHE */\n    {0x14c5, 0x056a}, /* Armenian_zhe */\n    {0x14c6, 0x053b}, /* Armenian_INI */\n    {0x14c7, 0x056b}, /* Armenian_ini */\n    {0x14c8, 0x053c}, /* Armenian_LYUN */\n    {0x14c9, 0x056c}, /* Armenian_lyun */\n    {0x14ca, 0x053d}, /* Armenian_KHE */\n    {0x14cb, 0x056d}, /* Armenian_khe */\n    {0x14cc, 0x053e}, /* Armenian_TSA */\n    {0x14cd, 0x056e}, /* Armenian_tsa */\n    {0x14ce, 0x053f}, /* Armenian_KEN */\n    {0x14cf, 0x056f}, /* Armenian_ken */\n    {0x14d0, 0x0540}, /* Armenian_HO */\n    {0x14d1, 0x0570}, /* Armenian_ho */\n    {0x14d2, 0x0541}, /* Armenian_DZA */\n    {0x14d3, 0x0571}, /* Armenian_dza */\n    {0x14d4, 0x0542}, /* Armenian_GHAT */\n    {0x14d5, 0x0572}, /* Armenian_ghat */\n    {0x14d6, 0x0543}, /* Armenian_TCHE */\n    {0x14d7, 0x0573}, /* Armenian_tche */\n    {0x14d8, 0x0544}, /* Armenian_MEN */\n    {0x14d9, 0x0574}, /* Armenian_men */\n    {0x14da, 0x0545}, /* Armenian_HI */\n    {0x14db, 0x0575}, /* Armenian_hi */\n    {0x14dc, 0x0546}, /* Armenian_NU */\n    {0x14dd, 0x0576}, /* Armenian_nu */\n    {0x14de, 0x0547}, /* Armenian_SHA */\n    {0x14df, 0x0577}, /* Armenian_sha */\n    {0x14e0, 0x0548}, /* Armenian_VO */\n    {0x14e1, 0x0578}, /* Armenian_vo */\n    {0x14e2, 0x0549}, /* Armenian_CHA */\n    {0x14e3, 0x0579}, /* Armenian_cha */\n    {0x14e4, 0x054a}, /* Armenian_PE */\n    {0x14e5, 0x057a}, /* Armenian_pe */\n    {0x14e6, 0x054b}, /* Armenian_JE */\n    {0x14e7, 0x057b}, /* Armenian_je */\n    {0x14e8, 0x054c}, /* Armenian_RA */\n    {0x14e9, 0x057c}, /* Armenian_ra */\n    {0x14ea, 0x054d}, /* Armenian_SE */\n    {0x14eb, 0x057d}, /* Armenian_se */\n    {0x14ec, 0x054e}, /* Armenian_VEV */\n    {0x14ed, 0x057e}, /* Armenian_vev */\n    {0x14ee, 0x054f}, /* Armenian_TYUN */\n    {0x14ef, 0x057f}, /* Armenian_tyun */\n    {0x14f0, 0x0550}, /* Armenian_RE */\n    {0x14f1, 0x0580}, /* Armenian_re */\n    {0x14f2, 0x0551}, /* Armenian_TSO */\n    {0x14f3, 0x0581}, /* Armenian_tso */\n    {0x14f4, 0x0552}, /* Armenian_VYUN */\n    {0x14f5, 0x0582}, /* Armenian_vyun */\n    {0x14f6, 0x0553}, /* Armenian_PYUR */\n    {0x14f7, 0x0583}, /* Armenian_pyur */\n    {0x14f8, 0x0554}, /* Armenian_KE */\n    {0x14f9, 0x0584}, /* Armenian_ke */\n    {0x14fa, 0x0555}, /* Armenian_O */\n    {0x14fb, 0x0585}, /* Armenian_o */\n    {0x14fc, 0x0556}, /* Armenian_FE */\n    {0x14fd, 0x0586}, /* Armenian_fe */\n    {0x14fe, 0x055a}, /* Armenian_apostrophe */\n    {0x15d0, 0x10d0}, /* Georgian_an */\n    {0x15d1, 0x10d1}, /* Georgian_ban */\n    {0x15d2, 0x10d2}, /* Georgian_gan */\n    {0x15d3, 0x10d3}, /* Georgian_don */\n    {0x15d4, 0x10d4}, /* Georgian_en */\n    {0x15d5, 0x10d5}, /* Georgian_vin */\n    {0x15d6, 0x10d6}, /* Georgian_zen */\n    {0x15d7, 0x10d7}, /* Georgian_tan */\n    {0x15d8, 0x10d8}, /* Georgian_in */\n    {0x15d9, 0x10d9}, /* Georgian_kan */\n    {0x15da, 0x10da}, /* Georgian_las */\n    {0x15db, 0x10db}, /* Georgian_man */\n    {0x15dc, 0x10dc}, /* Georgian_nar */\n    {0x15dd, 0x10dd}, /* Georgian_on */\n    {0x15de, 0x10de}, /* Georgian_par */\n    {0x15df, 0x10df}, /* Georgian_zhar */\n    {0x15e0, 0x10e0}, /* Georgian_rae */\n    {0x15e1, 0x10e1}, /* Georgian_san */\n    {0x15e2, 0x10e2}, /* Georgian_tar */\n    {0x15e3, 0x10e3}, /* Georgian_un */\n    {0x15e4, 0x10e4}, /* Georgian_phar */\n    {0x15e5, 0x10e5}, /* Georgian_khar */\n    {0x15e6, 0x10e6}, /* Georgian_ghan */\n    {0x15e7, 0x10e7}, /* Georgian_qar */\n    {0x15e8, 0x10e8}, /* Georgian_shin */\n    {0x15e9, 0x10e9}, /* Georgian_chin */\n    {0x15ea, 0x10ea}, /* Georgian_can */\n    {0x15eb, 0x10eb}, /* Georgian_jil */\n    {0x15ec, 0x10ec}, /* Georgian_cil */\n    {0x15ed, 0x10ed}, /* Georgian_char */\n    {0x15ee, 0x10ee}, /* Georgian_xan */\n    {0x15ef, 0x10ef}, /* Georgian_jhan */\n    {0x15f0, 0x10f0}, /* Georgian_hae */\n    {0x15f1, 0x10f1}, /* Georgian_he */\n    {0x15f2, 0x10f2}, /* Georgian_hie */\n    {0x15f3, 0x10f3}, /* Georgian_we */\n    {0x15f4, 0x10f4}, /* Georgian_har */\n    {0x15f5, 0x10f5}, /* Georgian_hoe */\n    {0x15f6, 0x10f6}, /* Georgian_fi */\n    {0x12a1, 0x1e02}, /* Babovedot */\n    {0x12a2, 0x1e03}, /* babovedot */\n    {0x12a6, 0x1e0a}, /* Dabovedot */\n    {0x12a8, 0x1e80}, /* Wgrave */\n    {0x12aa, 0x1e82}, /* Wacute */\n    {0x12ab, 0x1e0b}, /* dabovedot */\n    {0x12ac, 0x1ef2}, /* Ygrave */\n    {0x12b0, 0x1e1e}, /* Fabovedot */\n    {0x12b1, 0x1e1f}, /* fabovedot */\n    {0x12b4, 0x1e40}, /* Mabovedot */\n    {0x12b5, 0x1e41}, /* mabovedot */\n    {0x12b7, 0x1e56}, /* Pabovedot */\n    {0x12b8, 0x1e81}, /* wgrave */\n    {0x12b9, 0x1e57}, /* pabovedot */\n    {0x12ba, 0x1e83}, /* wacute */\n    {0x12bb, 0x1e60}, /* Sabovedot */\n    {0x12bc, 0x1ef3}, /* ygrave */\n    {0x12bd, 0x1e84}, /* Wdiaeresis */\n    {0x12be, 0x1e85}, /* wdiaeresis */\n    {0x12bf, 0x1e61}, /* sabovedot */\n    {0x12d0, 0x0174}, /* Wcircumflex */\n    {0x12d7, 0x1e6a}, /* Tabovedot */\n    {0x12de, 0x0176}, /* Ycircumflex */\n    {0x12f0, 0x0175}, /* wcircumflex */\n    {0x12f7, 0x1e6b}, /* tabovedot */\n    {0x12fe, 0x0177}, /* ycircumflex */\n    {0x0590, 0x06f0}, /* Farsi_0 */\n    {0x0591, 0x06f1}, /* Farsi_1 */\n    {0x0592, 0x06f2}, /* Farsi_2 */\n    {0x0593, 0x06f3}, /* Farsi_3 */\n    {0x0594, 0x06f4}, /* Farsi_4 */\n    {0x0595, 0x06f5}, /* Farsi_5 */\n    {0x0596, 0x06f6}, /* Farsi_6 */\n    {0x0597, 0x06f7}, /* Farsi_7 */\n    {0x0598, 0x06f8}, /* Farsi_8 */\n    {0x0599, 0x06f9}, /* Farsi_9 */\n    {0x05a5, 0x066a}, /* Arabic_percent */\n    {0x05a6, 0x0670}, /* Arabic_superscript_alef */\n    {0x05a7, 0x0679}, /* Arabic_tteh */\n    {0x05a8, 0x067e}, /* Arabic_peh */\n    {0x05a9, 0x0686}, /* Arabic_tcheh */\n    {0x05aa, 0x0688}, /* Arabic_ddal */\n    {0x05ab, 0x0691}, /* Arabic_rreh */\n    {0x05ae, 0x06d4}, /* Arabic_fullstop */\n    {0x05b0, 0x0660}, /* Arabic_0 */\n    {0x05b1, 0x0661}, /* Arabic_1 */\n    {0x05b2, 0x0662}, /* Arabic_2 */\n    {0x05b3, 0x0663}, /* Arabic_3 */\n    {0x05b4, 0x0664}, /* Arabic_4 */\n    {0x05b5, 0x0665}, /* Arabic_5 */\n    {0x05b6, 0x0666}, /* Arabic_6 */\n    {0x05b7, 0x0667}, /* Arabic_7 */\n    {0x05b8, 0x0668}, /* Arabic_8 */\n    {0x05b9, 0x0669}, /* Arabic_9 */\n    {0x05f3, 0x0653}, /* Arabic_madda_above */\n    {0x05f4, 0x0654}, /* Arabic_hamza_above */\n    {0x05f5, 0x0655}, /* Arabic_hamza_below */\n    {0x05f6, 0x0698}, /* Arabic_jeh */\n    {0x05f7, 0x06a4}, /* Arabic_veh */\n    {0x05f8, 0x06a9}, /* Arabic_keheh */\n    {0x05f9, 0x06af}, /* Arabic_gaf */\n    {0x05fa, 0x06ba}, /* Arabic_noon_ghunna */\n    {0x05fb, 0x06be}, /* Arabic_heh_doachashmee */\n    {0x05fc, 0x06cc}, /* Farsi_yeh */\n    {0x05fd, 0x06d2}, /* Arabic_yeh_baree */\n    {0x05fe, 0x06c1}, /* Arabic_heh_goal */\n    {0x0680, 0x0492}, /* Cyrillic_GHE_bar */\n    {0x0681, 0x0496}, /* Cyrillic_ZHE_descender */\n    {0x0682, 0x049a}, /* Cyrillic_KA_descender */\n    {0x0683, 0x049c}, /* Cyrillic_KA_vertstroke */\n    {0x0684, 0x04a2}, /* Cyrillic_EN_descender */\n    {0x0685, 0x04ae}, /* Cyrillic_U_straight */\n    {0x0686, 0x04b0}, /* Cyrillic_U_straight_bar */\n    {0x0687, 0x04b2}, /* Cyrillic_HA_descender */\n    {0x0688, 0x04b6}, /* Cyrillic_CHE_descender */\n    {0x0689, 0x04b8}, /* Cyrillic_CHE_vertstroke */\n    {0x068a, 0x04ba}, /* Cyrillic_SHHA */\n    {0x068c, 0x04d8}, /* Cyrillic_SCHWA */\n    {0x068d, 0x04e2}, /* Cyrillic_I_macron */\n    {0x068e, 0x04e8}, /* Cyrillic_O_bar */\n    {0x068f, 0x04ee}, /* Cyrillic_U_macron */\n    {0x0690, 0x0493}, /* Cyrillic_ghe_bar */\n    {0x0691, 0x0497}, /* Cyrillic_zhe_descender */\n    {0x0692, 0x049b}, /* Cyrillic_ka_descender */\n    {0x0693, 0x049d}, /* Cyrillic_ka_vertstroke */\n    {0x0694, 0x04a3}, /* Cyrillic_en_descender */\n    {0x0695, 0x04af}, /* Cyrillic_u_straight */\n    {0x0696, 0x04b1}, /* Cyrillic_u_straight_bar */\n    {0x0697, 0x04b3}, /* Cyrillic_ha_descender */\n    {0x0698, 0x04b7}, /* Cyrillic_che_descender */\n    {0x0699, 0x04b9}, /* Cyrillic_che_vertstroke */\n    {0x069a, 0x04bb}, /* Cyrillic_shha */\n    {0x069c, 0x04d9}, /* Cyrillic_schwa */\n    {0x069d, 0x04e3}, /* Cyrillic_i_macron */\n    {0x069e, 0x04e9}, /* Cyrillic_o_bar */\n    {0x069f, 0x04ef}, /* Cyrillic_u_macron */\n    {0x16a3, 0x1e8a}, /* Xabovedot */\n    {0x16a6, 0x012c}, /* Ibreve */\n    {0x16a9, 0x01b5}, /* Zstroke */\n    {0x16aa, 0x01e6}, /* Gcaron */\n    {0x16af, 0x019f}, /* Obarred */\n    {0x16b3, 0x1e8b}, /* xabovedot */\n    {0x16b6, 0x012d}, /* ibreve */\n    {0x16b9, 0x01b6}, /* zstroke */\n    {0x16ba, 0x01e7}, /* gcaron */\n    {0x16bd, 0x01d2}, /* ocaron */\n    {0x16bf, 0x0275}, /* obarred */\n    {0x16c6, 0x018f}, /* SCHWA */\n    {0x16f6, 0x0259}, /* schwa */\n    {0x16d1, 0x1e36}, /* Lbelowdot */\n    {0x16e1, 0x1e37}, /* lbelowdot */\n    {0x1ea0, 0x1ea0}, /* Abelowdot */\n    {0x1ea1, 0x1ea1}, /* abelowdot */\n    {0x1ea2, 0x1ea2}, /* Ahook */\n    {0x1ea3, 0x1ea3}, /* ahook */\n    {0x1ea4, 0x1ea4}, /* Acircumflexacute */\n    {0x1ea5, 0x1ea5}, /* acircumflexacute */\n    {0x1ea6, 0x1ea6}, /* Acircumflexgrave */\n    {0x1ea7, 0x1ea7}, /* acircumflexgrave */\n    {0x1ea8, 0x1ea8}, /* Acircumflexhook */\n    {0x1ea9, 0x1ea9}, /* acircumflexhook */\n    {0x1eaa, 0x1eaa}, /* Acircumflextilde */\n    {0x1eab, 0x1eab}, /* acircumflextilde */\n    {0x1eac, 0x1eac}, /* Acircumflexbelowdot */\n    {0x1ead, 0x1ead}, /* acircumflexbelowdot */\n    {0x1eae, 0x1eae}, /* Abreveacute */\n    {0x1eaf, 0x1eaf}, /* abreveacute */\n    {0x1eb0, 0x1eb0}, /* Abrevegrave */\n    {0x1eb1, 0x1eb1}, /* abrevegrave */\n    {0x1eb2, 0x1eb2}, /* Abrevehook */\n    {0x1eb3, 0x1eb3}, /* abrevehook */\n    {0x1eb4, 0x1eb4}, /* Abrevetilde */\n    {0x1eb5, 0x1eb5}, /* abrevetilde */\n    {0x1eb6, 0x1eb6}, /* Abrevebelowdot */\n    {0x1eb7, 0x1eb7}, /* abrevebelowdot */\n    {0x1eb8, 0x1eb8}, /* Ebelowdot */\n    {0x1eb9, 0x1eb9}, /* ebelowdot */\n    {0x1eba, 0x1eba}, /* Ehook */\n    {0x1ebb, 0x1ebb}, /* ehook */\n    {0x1ebc, 0x1ebc}, /* Etilde */\n    {0x1ebd, 0x1ebd}, /* etilde */\n    {0x1ebe, 0x1ebe}, /* Ecircumflexacute */\n    {0x1ebf, 0x1ebf}, /* ecircumflexacute */\n    {0x1ec0, 0x1ec0}, /* Ecircumflexgrave */\n    {0x1ec1, 0x1ec1}, /* ecircumflexgrave */\n    {0x1ec2, 0x1ec2}, /* Ecircumflexhook */\n    {0x1ec3, 0x1ec3}, /* ecircumflexhook */\n    {0x1ec4, 0x1ec4}, /* Ecircumflextilde */\n    {0x1ec5, 0x1ec5}, /* ecircumflextilde */\n    {0x1ec6, 0x1ec6}, /* Ecircumflexbelowdot */\n    {0x1ec7, 0x1ec7}, /* ecircumflexbelowdot */\n    {0x1ec8, 0x1ec8}, /* Ihook */\n    {0x1ec9, 0x1ec9}, /* ihook */\n    {0x1eca, 0x1eca}, /* Ibelowdot */\n    {0x1ecb, 0x1ecb}, /* ibelowdot */\n    {0x1ecc, 0x1ecc}, /* Obelowdot */\n    {0x1ecd, 0x1ecd}, /* obelowdot */\n    {0x1ece, 0x1ece}, /* Ohook */\n    {0x1ecf, 0x1ecf}, /* ohook */\n    {0x1ed0, 0x1ed0}, /* Ocircumflexacute */\n    {0x1ed1, 0x1ed1}, /* ocircumflexacute */\n    {0x1ed2, 0x1ed2}, /* Ocircumflexgrave */\n    {0x1ed3, 0x1ed3}, /* ocircumflexgrave */\n    {0x1ed4, 0x1ed4}, /* Ocircumflexhook */\n    {0x1ed5, 0x1ed5}, /* ocircumflexhook */\n    {0x1ed6, 0x1ed6}, /* Ocircumflextilde */\n    {0x1ed7, 0x1ed7}, /* ocircumflextilde */\n    {0x1ed8, 0x1ed8}, /* Ocircumflexbelowdot */\n    {0x1ed9, 0x1ed9}, /* ocircumflexbelowdot */\n    {0x1eda, 0x1eda}, /* Ohornacute */\n    {0x1edb, 0x1edb}, /* ohornacute */\n    {0x1edc, 0x1edc}, /* Ohorngrave */\n    {0x1edd, 0x1edd}, /* ohorngrave */\n    {0x1ede, 0x1ede}, /* Ohornhook */\n    {0x1edf, 0x1edf}, /* ohornhook */\n    {0x1ee0, 0x1ee0}, /* Ohorntilde */\n    {0x1ee1, 0x1ee1}, /* ohorntilde */\n    {0x1ee2, 0x1ee2}, /* Ohornbelowdot */\n    {0x1ee3, 0x1ee3}, /* ohornbelowdot */\n    {0x1ee4, 0x1ee4}, /* Ubelowdot */\n    {0x1ee5, 0x1ee5}, /* ubelowdot */\n    {0x1ee6, 0x1ee6}, /* Uhook */\n    {0x1ee7, 0x1ee7}, /* uhook */\n    {0x1ee8, 0x1ee8}, /* Uhornacute */\n    {0x1ee9, 0x1ee9}, /* uhornacute */\n    {0x1eea, 0x1eea}, /* Uhorngrave */\n    {0x1eeb, 0x1eeb}, /* uhorngrave */\n    {0x1eec, 0x1eec}, /* Uhornhook */\n    {0x1eed, 0x1eed}, /* uhornhook */\n    {0x1eee, 0x1eee}, /* Uhorntilde */\n    {0x1eef, 0x1eef}, /* uhorntilde */\n    {0x1ef0, 0x1ef0}, /* Uhornbelowdot */\n    {0x1ef1, 0x1ef1}, /* uhornbelowdot */\n    {0x1ef4, 0x1ef4}, /* Ybelowdot */\n    {0x1ef5, 0x1ef5}, /* ybelowdot */\n    {0x1ef6, 0x1ef6}, /* Yhook */\n    {0x1ef7, 0x1ef7}, /* yhook */\n    {0x1ef8, 0x1ef8}, /* Ytilde */\n    {0x1ef9, 0x1ef9}, /* ytilde */\n    {0x1efa, 0x01a0}, /* Ohorn */\n    {0x1efb, 0x01a1}, /* ohorn */\n    {0x1efc, 0x01af}, /* Uhorn */\n    {0x1efd, 0x01b0}, /* uhorn */\n    {0, 0}\n};\n\n#endif\n"
  },
  {
    "path": "macosx/tkMacOSXMenu.c",
    "content": "/*\n * tkMacOSXMenu.c --\n *\n *\tThis module implements the Mac-platform specific features of menus.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2012 Adrian Robert.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMenubutton.h\"\n#include \"tkMenu.h\"\n#include \"tkColor.h\"\n#include \"tkFont.h\"\n#include \"tkMacOSXWm.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXConstants.h\"\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_MENUS\n#endif\n*/\n\n#define ENTRY_HELP_MENU\t\tENTRY_PLATFORM_FLAG1\n#define ENTRY_APPLE_MENU\tENTRY_PLATFORM_FLAG2\n#define ENTRY_WINDOWS_MENU\tENTRY_PLATFORM_FLAG3\n\n#define sl(s) ((int) (sizeof(s \"\") - 1))\n\n#define SPECIALMENU(n, f) {.name = \".\" #n, .len = sl(#n) + 1, \\\n\t.flag = ENTRY_##f##_MENU }\nstatic const struct {\n    const char *name; size_t len; int flag;\n} specialMenus[] = {\n    SPECIALMENU(help,\tHELP),\n    SPECIALMENU(apple,\tAPPLE),\n    SPECIALMENU(window,\tWINDOWS),\n    {NULL, 0, 0}\n};\n#undef SPECIALMENU\n\n#define MODIFIER(n, f) {.name = #n, .len = sl(#n), .mask = f }\nstatic const struct {\n    const char *name; size_t len; NSUInteger mask;\n} allModifiers[] = {\n    MODIFIER(Control,\tNSControlKeyMask),\n    MODIFIER(Ctrl,\tNSControlKeyMask),\n    MODIFIER(Option,\tNSAlternateKeyMask),\n    MODIFIER(Opt,\tNSAlternateKeyMask),\n    MODIFIER(Alt,\tNSAlternateKeyMask),\n    MODIFIER(Shift,\tNSShiftKeyMask),\n    MODIFIER(Command,\tNSCommandKeyMask),\n    MODIFIER(Cmd,\tNSCommandKeyMask),\n    MODIFIER(Meta,\tNSCommandKeyMask),\n    {NULL, 0, 0}\n};\n#undef MODIFIER\n\n#define ACCEL(n, c) {.name = #n, .len = sl(#n), .ch = c }\nstatic const struct {\n    const char *name; size_t len; UniChar ch;\n} specialAccelerators[] = {\n    ACCEL(PageUp,\tNSPageUpFunctionKey),\n    ACCEL(PageDown,\tNSPageDownFunctionKey),\n    ACCEL(Left,\t\tNSLeftArrowFunctionKey),\n    ACCEL(Right,\tNSRightArrowFunctionKey),\n    ACCEL(Up,\t\tNSUpArrowFunctionKey),\n    ACCEL(Down,\t\tNSDownArrowFunctionKey),\n    ACCEL(Escape,\t0x001b),\n    ACCEL(Clear,\tNSClearDisplayFunctionKey),\n    ACCEL(Enter,\tNSEnterCharacter),\n    ACCEL(Backspace,\tNSBackspaceCharacter),\n    ACCEL(Space,\t' '),\n    ACCEL(Tab,\t\tNSTabCharacter),\n    ACCEL(BackTab,\tNSBackTabCharacter),\n    ACCEL(Delete,\tNSDeleteCharacter),\n    ACCEL(Home,\t\tNSHomeFunctionKey),\n    ACCEL(End,\t\tNSEndFunctionKey),\n    ACCEL(Return,\tNSCarriageReturnCharacter),\n    ACCEL(Help,\t\tNSHelpFunctionKey),\n    ACCEL(Power,\t0x233d),\n    ACCEL(Eject,\t0xf804),\n    {NULL, 0, 0}\n};\n#undef ACCEL\n#undef sl\n\nstatic Bool   inPostMenu = false;\nstatic SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;\nstatic SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;\nstatic SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;\nstatic SInt16 menuSeparatorHeight = 0;\n\nstatic void\tCheckForSpecialMenu(TkMenu *menuPtr);\nstatic NSString *ParseAccelerator(const char *accel, NSUInteger *maskPtr);\nstatic int\tGenerateMenuSelectEvent(TKMenu *menu, NSMenuItem *menuItem);\nstatic void\tMenuSelectEvent(TkMenu *menuPtr);\nstatic void\tRecursivelyClearActiveMenu(TkMenu *menuPtr);\nstatic int\tModifierCharWidth(Tk_Font tkfont);\nstatic void ClearMenubarActive(void);\n\n\n#pragma mark TkBackgroundLoop\n\n/*\n * The function TkMacOSXEventsCheckProc (in tkMacOSXNotify.c) is the \"check\n * proc\" for the macOS event source.  Its job is to remove NSEvents from the\n * default event queue of the NSApplication.  It does this by calling the\n * method [NSApp nextEventMatchingMask: untilDate: inMode: dequeue:]. As a\n * rule, when the untilDate is set to the distant past this method returns\n * immediately.  An exception to that rule is when the next event is the button\n * press on a menu button.  In that case, the method starts running a nested\n * event loop in the mode NSEventTrackingRunLoopMode which does not return\n * until the menu has been dismissed.  In Tk 8.6.10 and earlier, this meant\n * that the Tk event loop would block in its call to the check proc as long as\n * the menu was posted.  For example, opening a menu during the Rube Goldberg\n * demo would cause the animation to stop.  This was also the case for\n * menubuttons.\n *\n * The TKBackgroundLoop object below works around this problem, and allows a Tk\n * event loop to run while a menu is open.  It is a subclass of NSThread which\n * inserts requests to call [NSApp _runBackgroundLoop] onto the queue\n * associated with the NSEventTrackingRunLoopMode.  One of these threads gets\n * started in the callback [NSApp menuBeginTracking] and cancelled in [NSApp\n * menuEndTracking].\n */\n\n@interface TKBackgroundLoop: NSThread\n@end\n\n@implementation TKBackgroundLoop\n- (void) main\n{\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n    NSArray *modeArray = [NSArray arrayWithObjects: NSEventTrackingRunLoopMode,\n\t\t\t\t  nil];\n    while(1) {\n\n\t/*\n\t * Queue a request to process Tk events during event tracking.\n\t */\n\n\t[NSApp performSelectorOnMainThread:@selector(_runBackgroundLoop)\n\t\t\t\twithObject:nil\n\t\t\t     waitUntilDone:true\n\t\t\t\t     modes:modeArray];\n\tif ([self isCancelled]) {\n\t    [NSThread exit];\n\t}\n\n\t/*\n\t * Allow the tracked events to be processed too.\n\t */\n\n\t[NSThread sleepForTimeInterval:0.001];\n    }\n    [pool drain];\n}\n@end\n\nTKBackgroundLoop *backgroundLoop = nil;\n\n#pragma mark TKMenu\n\n/*\n * This interface is not declared in tkMacOSXPrivate.h because it requires\n * tkMenu.h.\n */\n\n@interface TKMenu(TKMenuPrivate)\n- (id) initWithTkMenu: (TkMenu *) tkMenu;\n- (TkMenu *) tkMenu;\n- (Tcl_Size) tkIndexOfItem: (NSMenuItem *) menuItem;\n- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;\n@end\n\n@implementation TKMenu\n- (void) setSpecial: (NSUInteger) special\n{\n    NSAssert(!_tkSpecial, @\"Cannot change specialness of a special menu\");\n    _tkSpecial = special;\n}\n- (BOOL) isSpecial: (NSUInteger) special\n{\n    return (_tkSpecial == special);\n}\n\n/*\n * There are cases where a KeyEquivalent (aka menu accelerator) is defined for\n * a \"dead key\", i.e. a key which does not have an associated character but is\n * only meant to be the start of a composition sequence.  For example, on a\n * Spanish keyboard both the ' and the ` keys are dead keys used to place\n * accents over letters.  But ⌘` is a standard KeyEquivalent which cycles\n * through the open windows of an application, changing the focus to the next\n * window. This caused a bug reported in [1626ed65b8].  When a dead key that is\n * also as a KeyEquivalent is pressed, a KeyDown event with no characters would\n * be passed to performKeyEquivalent.  The default implementation provided by\n * Apple would cause that event to be routed to some private methods of NSMenu\n * which raise NSInvalidArgumentException, causing an abort. Returning NO in\n * such a case prevents the abort.  So the override below returns NO when the\n * event has no characters.\n *\n * In fact, however, we never want to handle accelerators because they are\n * handled by Tk.  Hence this method could always return NO.  But if we did\n * that then we would not see the menu flash when an accelerator is pressed.\n * The flash is a useful visual indicator. It turns out that the flash is an\n * undocumented side effect of calling the super method for\n * performKeyEquivalent.  The super method also calls the NSMenuItem's action\n * method - tkMenuItemInvoke in our case.  This is also not documented.\n *\n * To enable the flash we set up a flag that tells the action method to do\n * nothing, because it is being called by an accelerator. The override below\n * sets the flag and then calls super. See ticket [ead70921a9].\n */\n\nstatic Bool runMenuCommand = true;\n- (BOOL)performKeyEquivalent:(NSEvent *)event\n{\n    if ([[event characters] length] == 0) {\n\treturn NO;\n    }\n    runMenuCommand = false;\n    /* Make the menu flash and call tkMenuItemInvoke. */\n    return [super performKeyEquivalent: event];\n}\n@end\n\n@implementation TKMenu(TKMenuPrivate)\n\n- (id) initWithTitle: (NSString *) aTitle\n{\n    self = [super initWithTitle:aTitle];\n    if (self) {\n\t_tkMenu = NULL;\n\t_tkOffset = 0;\n\t_tkItemCount = 0;\n\t_tkSpecial = 0;\n\t[self setDelegate:self];\n    }\n    return self;\n}\n\n- (id) initWithTkMenu: (TkMenu *) tkMenu\n{\n    NSString *title = [[TKNSString alloc] initWithTclUtfBytes:\n\t    Tk_PathName(tkMenu->tkwin) length:TCL_INDEX_NONE];\n\n    self = [self initWithTitle:title];\n    [title release];\n    if (self) {\n\t_tkMenu = tkMenu;\n    }\n    return self;\n}\n\n- (id) copyWithZone: (NSZone *) zone\n{\n    TKMenu *copy = [super copyWithZone:zone];\n\n    NSAssert(_tkMenu == nil, @\"Cannot copy tkMenu\");\n    copy->_tkMenu = _tkMenu;\n    copy->_tkOffset = _tkOffset;\n    copy->_tkItemCount = _tkItemCount;\n    copy->_tkSpecial = _tkSpecial;\n    return copy;\n}\n\n- (TkMenu *) tkMenu\n{\n    return (TkMenu *)_tkMenu;\n}\n\n- (Tcl_Size) tkIndexOfItem: (NSMenuItem *) menuItem\n{\n    NSInteger index = [self indexOfItem:menuItem];\n    if (index < 0 || (NSUInteger) index < _tkOffset) {\n\treturn TCL_INDEX_NONE;\n    }\n    return ((Tcl_Size)index - (Tcl_Size)_tkOffset);\n}\n\n- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index\n{\n    [super insertItem:newItem atIndex:index + (NSInteger)_tkOffset];\n    _tkItemCount++;\n}\n\n- (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index\n{\n    if (_tkMenu && index >= 0) {\n\tif ((NSUInteger) index <= _tkOffset) {\n\t    _tkOffset++;\n\t} else {\n\t    NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset,\n\t\t    @\"Cannot insert in the middle of Tk menu\");\n\t}\n    }\n    [super insertItem:newItem atIndex:index];\n}\n\n- (void) removeItemAtIndex: (NSInteger) index\n{\n    if (_tkMenu && index >= 0) {\n\tif ((NSUInteger) index < _tkOffset) {\n\t    _tkOffset--;\n\t} else if ((NSUInteger) index < _tkItemCount + _tkOffset) {\n\t    _tkItemCount--;\n\t}\n    }\n    [super removeItemAtIndex:index];\n}\n\n- (NSMenuItem *) newTkMenuItem: (TkMenuEntry *) mePtr\n{\n    NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@\"\"\n\t    action:@selector(tkMenuItemInvoke:) keyEquivalent:@\"\"];\n\n    [menuItem setTarget:self];\n    [menuItem setTag:(NSInteger) mePtr];\n    return menuItem;\n}\n@end\n\n@implementation TKMenu(TKMenuActions)\n\n- (BOOL) validateMenuItem: (NSMenuItem *) menuItem\n{\n    return [menuItem isEnabled];\n}\n\n/*\n * Workaround for bug 3572016; leave menu items enabled during modal dialog.\n */\n\n- (BOOL)worksWhenModal\n{\n    return YES;\n}\n\n- (void) tkMenuItemInvoke: (id) sender\n{\n    if (!runMenuCommand) {\n\n\t/*\n\t * We are being called for a menu accelerator.  Tk will handle it.\n\t * Just update the runMenuCommand flag.\n\t */\n\n\trunMenuCommand = true;\n\treturn;\n    }\n\n    /*\n     * We are being called for an actual menu item selection; run the command.\n     */\n\n    if ([sender isKindOfClass:[NSMenuItem class]]) {\n\tNSMenuItem *menuItem = (NSMenuItem *) sender;\n\tTkMenu *menuPtr = (TkMenu *) _tkMenu;\n\tTkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag];\n\n\tif (menuPtr && mePtr) {\n\t    Tcl_Interp *interp = menuPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    Tcl_Preserve(menuPtr);\n\t    int result = TkInvokeMenu(interp, menuPtr, mePtr->index);\n\t    if (result != TCL_OK && result != TCL_CONTINUE &&\n\t\t    result != TCL_BREAK) {\n\t\tTcl_AddErrorInfo(interp, \"\\n    (menu invoke)\");\n\t\tTcl_BackgroundException(interp, result);\n\t    }\n\t    Tcl_Release(menuPtr);\n\t    Tcl_Release(interp);\n\t}\n    }\n}\n@end\n\n@implementation TKMenu(TKMenuDelegate)\n\n- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event\n\ttarget: (id *) target action: (SEL *) action\n{\n    (void)menu;\n\n    /*\n     * Use lowercaseString when comparing keyEquivalents since the notion of\n     * a shifted upper case letter does not make much sense.\n     */\n\n    NSString *key = [[event charactersIgnoringModifiers] lowercaseString];\n    NSUInteger modifiers = [event modifierFlags] &\n\t    NSDeviceIndependentModifierFlagsMask;\n\n    if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&\n\t    [key compare:@\"?\"] == NSOrderedSame) {\n\t/*\n\t * Command-Shift-? has not been allowed as a keyboard equivalent since\n\t * the first aqua port, for some mysterious reason.\n\t */\n\n\treturn NO;\n    } else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) &&\n\t    [event keyCode] == 48) {\n\t/*\n\t * Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used\n\t * to select window tabs.  But for some even more mysterious reason the\n\t * Control-Shift-Tab event has character 0x19 = NSBackTabCharacter\n\t * rather than 0x09 = NSTabCharacter.  At the same time, the\n\t * keyEquivalent must be \\0x09 in order for it to be displayed\n\t * correctly in the menu. This makes it impossible for the standard\n\t * \"Select Previous Tab\" to work correctly, unless we intervene.\n\t */\n\n\tkey = @\"\\t\";\n    } else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {\n\t/*\n\t * If the command modifier is set, use the full character string so\n\t * things like the dvorak / qwerty layout will work.\n\t */\n\n\tkey = [event characters];\n    }\n\n    NSArray *itemArray = [self itemArray];\n    for (NSMenuItem *item in itemArray) {\n\tif ([item isEnabled] &&\n\t    [[item keyEquivalent] compare:key] == NSOrderedSame) {\n\t    NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];\n\t    if (keyEquivModifiers == modifiers) {\n\t\t*target = [item target];\n\t\t*action = [item action];\n\t\treturn YES;\n\t    }\n\t}\n    }\n    return NO;\n}\n\n- (void) menuWillOpen: (NSMenu *) menu\n{\n    (void)menu;\n\n    if (_tkMenu) {\n\t//RecursivelyClearActiveMenu(_tkMenu);\n\tGenerateMenuSelectEvent((TKMenu *)[self supermenu],\n\t\t[self itemInSupermenu]);\n    }\n}\n\n- (void) menuDidClose: (NSMenu *) menu\n{\n    (void)menu;\n\n    if (_tkMenu) {\n\tRecursivelyClearActiveMenu((TkMenu *)_tkMenu);\n    }\n}\n\n- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item\n{\n    (void)menu;\n\n    if (_tkMenu) {\n\tGenerateMenuSelectEvent(self, item);\n    }\n}\n\n- (void) menuNeedsUpdate: (NSMenu *) menu\n{\n    TkMenu *menuPtr = (TkMenu *) _tkMenu;\n    (void)menu;\n\n    if (menuPtr) {\n\tTcl_Interp *interp = menuPtr->interp;\n\n\tTcl_Preserve(interp);\n\tTcl_Preserve(menuPtr);\n\n\tint result = TkPostCommand(menuPtr);\n\n\tif (result!=TCL_OK && result!=TCL_CONTINUE && result!=TCL_BREAK) {\n\t      Tcl_AddErrorInfo(interp, \"\\n    (menu preprocess)\");\n\t      Tcl_BackgroundException(interp, result);\n\t}\n\tTcl_Release(menuPtr);\n\tTcl_Release(interp);\n    }\n}\n@end\n\n#pragma mark TKApplication(TKMenu)\n\n@implementation TKApplication(TKMenu)\n\n- (void) menuBeginTracking: (NSNotification *) notification\n{\n    (void)notification;\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if (backgroundLoop) {\n\t[backgroundLoop cancel];\n\t[backgroundLoop release];\n    }\n    backgroundLoop = [[TKBackgroundLoop alloc] init];\n    [backgroundLoop start];\n\n    /*\n     * Make sure that we can run commands when actually using a menu.\n     * See [412b80fcaf].\n     */\n\n    runMenuCommand = true;\n}\n\n- (void) menuEndTracking: (NSNotification *) notification\n{\n    (void)notification;\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if (backgroundLoop) {\n\t[backgroundLoop cancel];\n\t[backgroundLoop release];\n\tbackgroundLoop = nil;\n    }\n    if (!inPostMenu) {\n\tClearMenubarActive();\n    }\n}\n\n- (void) tkSetMainMenu: (TKMenu *) menu\n{\n    TKMenu *applicationMenu = nil;\n\n    if (menu) {\n\tNSMenuItem *applicationMenuItem = [menu numberOfItems] ?\n\t\t[menu itemAtIndex:0] : nil;\n\n\tif (![menu isSpecial:tkMainMenu]) {\n\t    TkMenuEntry *mePtr = (TkMenuEntry *)[applicationMenuItem tag];\n\n\t    if (!mePtr || !(mePtr->entryFlags & ENTRY_APPLE_MENU)) {\n\t\tapplicationMenuItem = [NSMenuItem itemWithSubmenu:\n\t\t\t[_defaultApplicationMenu copy]];\n\t\t[menu insertItem:applicationMenuItem atIndex:0];\n\t    }\n\t    [menu setSpecial:tkMainMenu];\n\t}\n\tapplicationMenu = (TKMenu *)[applicationMenuItem submenu];\n\tif (![applicationMenu isSpecial:tkApplicationMenu]) {\n\t    for (NSMenuItem *item in _defaultApplicationMenuItems) {\n\t\t[applicationMenu addItem:[item copy]];\n\t    }\n\t    [applicationMenu setSpecial:tkApplicationMenu];\n\t}\n\n\tNSArray *itemArray = [menu itemArray];\n\n\tfor (NSMenuItem *item in itemArray) {\n\t    TkMenuEntry *mePtr = (TkMenuEntry *)[item tag];\n\t    TKMenu *submenu = (TKMenu *)[item submenu];\n\t    if (mePtr && submenu) {\n\t\tif ((mePtr->entryFlags & ENTRY_WINDOWS_MENU) &&\n\t\t\t![submenu isSpecial:tkWindowsMenu]) {\n\t\t    NSInteger index = 0;\n\n\t\t    for (NSMenuItem *i in _defaultWindowsMenuItems) {\n\t\t\t[submenu insertItem:[i copy] atIndex:index++];\n\t\t    }\n\t\t    [self setWindowsMenu:submenu];\n\t\t    [submenu setSpecial:tkWindowsMenu];\n\t\t} else if ((mePtr->entryFlags & ENTRY_HELP_MENU) &&\n\t\t\t![submenu isSpecial:tkHelpMenu]) {\n\t\t    NSInteger index = 0;\n\n\t\t    for (NSMenuItem *i in _defaultHelpMenuItems) {\n\t\t\t[submenu insertItem:[i copy] atIndex:index++];\n\t\t    }\n\t\t    [submenu setSpecial:tkHelpMenu];\n\t\t}\n\t    }\n\t}\n    } else {\n\tmenu = _defaultMainMenu;\n\tapplicationMenu = _defaultApplicationMenu;\n    }\n\n    NSMenuItem *servicesMenuItem =\n\t    [applicationMenu itemWithTitle:@\"Services\"];\n\n    if (servicesMenuItem && [servicesMenuItem submenu] != _servicesMenu) {\n\t[[_servicesMenu itemInSupermenu] setSubmenu:nil];\n\t[servicesMenuItem setSubmenu:_servicesMenu];\n    }\n    [self setAppleMenu:applicationMenu];\n    [self setMainMenu:menu];\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpNewMenu --\n *\n *\tGets a new blank menu. Only the platform specific options are filled\n *\tin.\n *\n * Results:\n *\tReturns a standard Tcl error.\n *\n * Side effects:\n *\tAllocates a NSMenu and puts it into the platformData field of the\n *\tmenuPtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpNewMenu(\n    TkMenu *menuPtr)\t\t/* The common structure we are making the\n\t\t\t\t * platform structure for. */\n{\n    TKMenu *menu = [[TKMenu alloc] initWithTkMenu:menuPtr];\n    menuPtr->platformData = (TkMenuPlatformData) menu;\n    CheckForSpecialMenu(menuPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenu --\n *\n *\tDestroys platform-specific menu structures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll platform-specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenu(\n    TkMenu *menuPtr)\t\t/* The common menu structure */\n{\n    NSMenu* nsmenu = (NSMenu*)(menuPtr->platformData);\n\n    [nsmenu release];\n    menuPtr->platformData = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNewEntry --\n *\n *\tAdds a pointer to a new menu entry structure with the platform-\n *\tspecific fields filled in. The Macintosh uses the platformEntryData\n *\tfield of the TkMenuEntry record.\n *\n * Results:\n *\tStandard TCL error.\n *\n * Side effects:\n *\tStorage gets allocated. New menu entry data is put into the\n *\tplatformEntryData field of the mePtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpMenuNewEntry(\n    TkMenuEntry *mePtr)\t\t/* The menu we are adding an entry to */\n{\n    TKMenu *menu = (TKMenu *) mePtr->menuPtr->platformData;\n    NSMenuItem *menuItem;\n    if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {\n\tmenuItem = [[NSMenuItem separatorItem] retain];\n    } else {\n\tmenuItem = [menu newTkMenuItem:mePtr];\n    }\n    mePtr->platformEntryData = (TkMenuPlatformEntryData) menuItem;\n\n    /*\n     * Caller TkMenuEntry() already did this same insertion into the generic\n     * TkMenu so we just match it for the platform menu.\n     */\n\n    [menu insertItem:menuItem atTkIndex:mePtr->index];\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureMenuEntry --\n *\n *\tProcesses configurations for menu entries.\n *\n * Results:\n *\tReturns standard TCL result. If TCL_ERROR is returned, then the\n *\tinterp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information get set for mePtr; old resources get freed,\n *\tif any need it.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpConfigureMenuEntry(\n    TkMenuEntry *mePtr)\t/* Information about menu entry; may or may\n\t\t\t\t * not already have values for some fields. */\n{\n    NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;\n    NSString *title = @\"\";\n    NSAttributedString *attributedTitle = nil;\n    NSImage *image = nil;\n    NSString *keyEquivalent = @\"\";\n    NSUInteger modifierMask = NSCommandKeyMask;\n    NSMenu *submenu = nil;\n    int imageWidth, imageHeight;\n    GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC);\n    Tcl_Obj *fontPtr = (mePtr->fontPtr ?\n\t\t\tmePtr->fontPtr : mePtr->menuPtr->fontPtr);\n    static bool initialized = 0;\n\n    if (!initialized) {\n\tTkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);\n\tTcl_Free(tkColPtr);\n\ttkColPtr = TkpGetColor(NULL, DEF_MENU_FG);\n\tTcl_Free(tkColPtr);\n    }\n\n    if (mePtr->image) {\n\tTk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);\n\timage = TkMacOSXGetNSImageFromTkImage(mePtr->menuPtr->display,\n\t\tmePtr->image, imageWidth, imageHeight);\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin,\n\t\tmePtr->bitmapPtr);\n\n\tTk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth,\n\t\t&imageHeight);\n\timage = TkMacOSXGetNSImageFromBitmap(mePtr->menuPtr->display, bitmap,\n\t\tgc, imageWidth, imageHeight);\n\t[image setTemplate:YES];\n    }\n    [menuItem setImage:image];\n    if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&\n\t    mePtr->labelLength) {\n\ttitle = [[[TKNSString alloc]\n\t\t    initWithTclUtfBytes:Tcl_GetString(mePtr->labelPtr)\n\t\t\t\tlength:mePtr->labelLength]\n\t\tautorelease];\n\tif ([title hasSuffix:@\"...\"]) {\n\t    title = [NSString stringWithFormat:@\"%@%C\",\n\t\t    [title substringToIndex:[title length] - 3], 0x2026];\n\t}\n    }\n    [menuItem setTitle:title];\n\n#if 0\n\n    /*\n     * The -background and -foreground options are now ignored in Aqua.\n     * See ticket [635167af14].\n     */\n\n    NSDictionary fontAttributes = TkMacOSXNSFontAttributesForFont(\n\tTk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr));\n    NSMutableDictionary *attributes = [fontAttributes mutableCopy];\n    static unsigned long defaultBg = 0, defaultFg = 0;\n    if (defaultBg == 0) {\n\ttkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);\n\tdefaultBg = tkColPtr->color.pixel;\n\tTcl_Free(tkColPtr);\n    }\n    if (defaultFg == 0) {\n\ttkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);\n\tdefaultFg = tkColPtr->color.pixel;\n\tTcl_Free(tkColPtr);\n    }\n    if (gc->foreground != defaultFg) {\n\tNSColor *fgcolor = TkMacOSXGetNSColor(gc, gc->foreground);\n\t[attributes setObject:fgcolor\n\t\t       forKey:NSForegroundColorAttributeName];\n    }\n    if (gc->background != defaultBg) {\n\tNSColor *bgcolor = TkMacOSXGetNSColor(gc, gc->background);\n\t[attributes setObject:bgcolor\n\t\t       forKey:NSBackgroundColorAttributeName];\n    }\n\n#else\n\n    NSDictionary *attributes = TkMacOSXNSFontAttributesForFont(\n\tTk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr));\n\n#endif\n\n    attributedTitle = [[NSAttributedString alloc] initWithString:title\n\tattributes:attributes];\n    [menuItem setAttributedTitle:attributedTitle];\n    [attributedTitle release];\n    [menuItem setEnabled:(mePtr->state != ENTRY_DISABLED)];\n    [menuItem setState:((mePtr->type == CHECK_BUTTON_ENTRY ||\n\t    mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn &&\n\t    (mePtr->entryFlags & ENTRY_SELECTED) ? NSOnState : NSOffState)];\n    if (mePtr->type != CASCADE_ENTRY && mePtr->accelPtr && mePtr->accelLength) {\n\tkeyEquivalent = ParseAccelerator(Tcl_GetString(mePtr->accelPtr),\n\t\t&modifierMask);\n    }\n    [menuItem setKeyEquivalent:keyEquivalent];\n    [menuItem setKeyEquivalentModifierMask:modifierMask];\n    if (mePtr->type == CASCADE_ENTRY && mePtr->namePtr) {\n\tTkMenuReferences *menuRefPtr;\n\n\tmenuRefPtr = TkFindMenuReferencesObj(mePtr->menuPtr->interp,\n\t\tmePtr->namePtr);\n\tif (menuRefPtr && menuRefPtr->menuPtr) {\n\t    CheckForSpecialMenu(menuRefPtr->menuPtr);\n\t    submenu = (TKMenu *) menuRefPtr->menuPtr->platformData;\n\t    if ([submenu supermenu] && [menuItem submenu] != submenu) {\n\t\t/*\n\t\t * This happens during a clone, where the parent menu is\n\t\t * cloned before its children, so just ignore this temporary\n\t\t * setting, it will be changed shortly (c.f. tkMenu.c\n\t\t * CloneMenu())\n\t\t */\n\n\t\tsubmenu = nil;\n\t    } else {\n\t\t[submenu setTitle:title];\n\n\t\tif ([menuItem isEnabled]) {\n\n\t\t    /*\n\t\t     * This menuItem might have been previously disabled which\n\t\t     * would have disabled all of its entries; we must re-enable the\n\t\t     * entries here.  It is important to iterate though the Tk\n\t\t     * entries, not the NSMenuItems, since some NSMenuItems may\n\t\t     * have been added by the system.  See [7185d26cf4].\n\t\t     */\n\n\t\t    for (Tcl_Size i = 0; i < menuRefPtr->menuPtr->numEntries; i++) {\n\t\t\tTkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];\n\t\t\tNSMenuItem *item = (NSMenuItem *) submePtr->platformEntryData;\n\t\t\t[item setEnabled:(submePtr->state != ENTRY_DISABLED)];\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n    [menuItem setSubmenu:submenu];\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenuEntry --\n *\n *\tCleans up platform-specific menu entry items.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tAll platform-specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenuEntry(\n    TkMenuEntry *mePtr)\n{\n    NSMenuItem *menuItem;\n    TKMenu *menu;\n    NSInteger index;\n\n    if (mePtr->platformEntryData) {\n\tmenuItem = (NSMenuItem *) mePtr->platformEntryData;\n\tif (mePtr->menuPtr->platformData) {\n\t    menu = (TKMenu *) mePtr->menuPtr->platformData;\n\t    index = [menu indexOfItem:menuItem];\n\n\t    if (index > -1) {\n\t\t[menu removeItemAtIndex:index];\n\t    }\n\t}\n\t[menuItem setTag:(NSInteger) NULL];\n\t[menuItem release];\n\tmePtr->platformEntryData = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostMenu --\n *\n *\tPosts a menu on the screen. If entry is < 0 then the menu is drawn so\n *      its top left corner is located at the point with screen coordinates\n *      (x,y).  Otherwise the top left corner of the specified entry is located\n *      at that point.\n *\n * Results:\n *\tReturns a standard Tcl result.\n *\n * Side effects:\n *\tThe menu is posted and handled.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostMenu(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* The interpreter this menu lives in */\n    TkMenu *menuPtr,\t\t/* The menu we are posting */\n    int x, int y,\t\t/* The screen coordinates where the top left\n\t\t\t\t * corner of the menu, or of the specified\n\t\t\t\t * entry, will be located. */\n    Tcl_Size index)\n{\n    int result;\n    Tk_Window realWin = menuPtr->tkwin;\n    TkWindow *realWinPtr;\n    NSView *realWinView;\n\n    while (1) {\n\tif (realWin == NULL) {\n\t    return TCL_ERROR;\n\t}\n\t/*\n\t * Fix for bug 07cfc9f03e: use the view for the parent real (non-menu)\n\t * toplevel window, rather than always using the root window.\n\t * This allows menus to appear on a separate monitor than the root\n\t * window, and to use the appearance of their parent real window\n\t * rather than the appearance of the root window.\n\t */\n\trealWinPtr = (TkWindow*) realWin;\n\trealWinView = TkMacOSXGetNSViewForDrawable(realWinPtr->privatePtr);\n\tif (realWinView != nil) {\n\t    break;\n\t}\n\trealWin = Tk_Parent(realWin);\n    }\n    NSMenu *menu = (NSMenu *) menuPtr->platformData;\n    NSInteger itemIndex = index;\n    NSInteger numItems = [menu numberOfItems];\n    NSMenuItem *item = nil;\n    NSPoint location = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);\n\n    inPostMenu = true;\n    result = TkPreprocessMenu(menuPtr);\n    if (result != TCL_OK) {\n\tinPostMenu = false;\n\treturn result;\n    }\n    if (itemIndex >= numItems) {\n\titemIndex = numItems - 1;\n    }\n    if (itemIndex >= 0) {\n\titem = [menu itemAtIndex:itemIndex];\n    }\n\n    /*\n     * The post commands could have deleted the menu, which means we are dead\n     * and should go away.\n     */\n\n    if (menuPtr->tkwin == NULL) {\n\treturn TCL_OK;\n    }\n\n    [menu popUpMenuPositioningItem:item\n\t\t\tatLocation:location\n\t\t\t    inView:nil\n\t\t\tappearance:realWinView.effectiveAppearance];\n    inPostMenu = false;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostTearoffMenu --\n *\n *\tTearoff menus are not supported on the Mac.  This placeholder function,\n *      which is simply a copy of the unix function, posts a completely useless\n *      window with a black background on the screen. If entry is < 0 then the\n *      window is positioned so that its top left corner is located at the\n *      point with screen coordinates (x, y).  Otherwise the window position is\n *      offset so that top left corner of the specified entry would be located\n *      at that point, if there actually were a menu.\n *\n *      Mac menus steal all mouse or keyboard input from the application until\n *      the menu is dismissed, with or without a selection, by a mouse or key\n *      event.  Posting a Mac menu in a regression test will cause the test to\n *      halt waiting for user input.  This is why the TkpPostMenu function is\n *      not being used as the placeholder.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA useless window is posted.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostTearoffMenu(\n    TCL_UNUSED(Tcl_Interp *),\t/* The interpreter this menu lives in */\n    TkMenu *menuPtr,\t\t/* The menu we are posting */\n    int x, int y, Tcl_Size index)\t/* The screen coordinates where the top left\n\t\t\t\t * corner of the menu, or of the specified\n\t\t\t\t * entry, will be located. */\n{\n    int vRootX, vRootY, vRootWidth, vRootHeight;\n    int result;\n\n    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n    TkRecomputeMenu(menuPtr);\n    result = TkPostCommand(menuPtr);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * The post commands could have deleted the menu, which means we are dead\n     * and should go away.\n     */\n\n    if (menuPtr->tkwin == NULL) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Adjust the menu y position so that the specified entry will be located\n     * at the given coordinates.\n     */\n\n    if (index < 0 || index >= menuPtr->numEntries) {\n\tindex = menuPtr->numEntries - 1;\n    }\n    if (index >= 0) {\n\ty -= menuPtr->entries[index]->y;\n    }\n\n    /*\n     * Adjust the position of the menu if necessary to keep it visible on the\n     * screen. There are two special tricks to make this work right:\n     *\n     * 1. If a virtual root window manager is being used then the coordinates\n     *    are in the virtual root window of menuPtr's parent; since the menu\n     *    uses override-redirect mode it will be in the *real* root window for\n     *    the screen, so we have to map the coordinates from the virtual root\n     *    (if any) to the real root. Can't get the virtual root from the menu\n     *    itself (it will never be seen by the wm) so use its parent instead\n     *    (it would be better to have an an option that names a window to use\n     *    for this...).\n     * 2. The menu may not have been mapped yet, so its current size might be\n     *    the default 1x1. To compute how much space it needs, use its\n     *    requested size, not its actual size.\n     */\n\n    Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,\n\t&vRootWidth, &vRootHeight);\n    vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);\n    if (x > vRootX + vRootWidth) {\n\tx = vRootX + vRootWidth;\n    }\n    if (x < vRootX) {\n\tx = vRootX;\n    }\n    vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);\n    if (y > vRootY + vRootHeight) {\n\ty = vRootY + vRootHeight;\n    }\n    if (y < vRootY) {\n\ty = vRootY;\n    }\n    Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);\n    if (!Tk_IsMapped(menuPtr->tkwin)) {\n\tTk_MapWindow(menuPtr->tkwin);\n    }\n    TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetWindowMenuBar --\n *\n *\tAssociates a given menu with a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOn Windows and UNIX, associates the platform menu with the platform\n *\twindow.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetWindowMenuBar(\n    Tk_Window tkwin,\t\t/* The window we are setting the menu in */\n    TkMenu *menuPtr)\t\t/* The menu we are setting */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (winPtr->wmInfoPtr) {\n\twinPtr->wmInfoPtr->menuPtr = menuPtr;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetMainMenubar --\n *\n *\tPuts the menu associated with a window into the menubar. Should only be\n *\tcalled when the window is in front.\n *\n *      This is a no-op on all other platforms.  On OS X it installs the\n *      menubar with the specified menuName, if possible.  If the name is NULL\n *      it installs the default menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menubar may be changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetMainMenubar(\n    Tcl_Interp *interp,\t\t/* The interpreter of the application */\n    Tk_Window tkwin,\t\t/* The frame we are setting up */\n    const char *menuName)\t/* The name of the menu to put in front. */\n{\n    TKMenu *menu = nil;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    /*\n     * We will be called when an embedded window receives an ActivationNotify\n     * event, but we should not change the menubar in that case.\n     */\n\n    if (Tk_IsEmbedded(winPtr)) {\n\treturn;\n    }\n\n    if (menuName) {\n\tTk_Window menubar = NULL;\n\n\tif (winPtr->wmInfoPtr &&\n\t\twinPtr->wmInfoPtr->menuPtr &&\n\t\twinPtr->wmInfoPtr->menuPtr->mainMenuPtr) {\n\t    menubar = winPtr->wmInfoPtr->menuPtr->mainMenuPtr->tkwin;\n\t}\n\n\t/*\n\t * Attempt to find the NSMenu directly.  If that fails, ask Tk to find\n\t * it.\n\t */\n\n\tif (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {\n\t    menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;\n\t} else {\n\t    TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,\n\t\t    menuName);\n\n\t    if (menuRefPtr && menuRefPtr->menuPtr &&\n\t\t    menuRefPtr->menuPtr->platformData) {\n\t\tmenu = (TKMenu *) menuRefPtr->menuPtr->platformData;\n\t    }\n\t}\n    }\n\n    /*\n     * If we couldn't find a menu this will install the default menubar.\n     */\n\n    [NSApp tkSetMainMenu:menu];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckForSpecialMenu --\n *\n *\tGiven a menu, check to see whether or not it is a cascade in a menubar\n *\twith one of the special names \".apple\", \".help\" or \".window\". If it is,\n *\tthe entry that points to this menu will be marked.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWill set entryFlags appropriately.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCheckForSpecialMenu(\n    TkMenu *menuPtr)\t\t/* The menu we are checking */\n{\n    if (!menuPtr->mainMenuPtr->tkwin) {\n\treturn;\n    }\n    for (TkMenuEntry *cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;\n\t    cascadeEntryPtr;\n\t    cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {\n\tif (cascadeEntryPtr->menuPtr->menuType == MENUBAR\n\t\t&& cascadeEntryPtr->menuPtr->mainMenuPtr->tkwin) {\n\t    TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->mainMenuPtr;\n\t    int i = 0;\n\t    Tcl_DString ds;\n\n\t    Tcl_DStringInit(&ds);\n\t    Tcl_DStringAppend(&ds, Tk_PathName(mainMenuPtr->tkwin), TCL_INDEX_NONE);\n\t    while (specialMenus[i].name) {\n\t\tTcl_DStringAppend(&ds, specialMenus[i].name,\n\t\t\tspecialMenus[i].len);\n\t\tif (strcmp(Tcl_DStringValue(&ds),\n\t\t\tTk_PathName(menuPtr->mainMenuPtr->tkwin)) == 0) {\n\t\t    cascadeEntryPtr->entryFlags |= specialMenus[i].flag;\n\t\t} else {\n\t\t    cascadeEntryPtr->entryFlags &= ~specialMenus[i].flag;\n\t\t}\n\t\tTcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) -\n\t\t\tspecialMenus[i].len);\n\t\ti++;\n\t    }\n\t    Tcl_DStringFree(&ds);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseAccelerator --\n *\n *\tParse accelerator string.\n *\n * Results:\n *\tAccelerator string & flags.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSString *\nParseAccelerator(\n    const char *accel,\n    NSUInteger *maskPtr)\n{\n    unichar ch = 0;\n    size_t len;\n    int i;\n\n    *maskPtr = 0;\n    while (1) {\n\ti = 0;\n\twhile (allModifiers[i].name) {\n\t    size_t l = allModifiers[i].len;\n\n\t    if (!strncasecmp(accel, allModifiers[i].name, l) &&\n\t\t    (accel[l] == '-' || accel[l] == '+')) {\n\t\t*maskPtr |= allModifiers[i].mask;\n\t\taccel += l+1;\n\t\tbreak;\n\t    }\n\t    i++;\n\t}\n\tif (!allModifiers[i].name || !*accel) {\n\t    break;\n\t}\n    }\n    len = strlen(accel);\n    if (len > 1) {\n\ti = 0;\n\tif (accel[0] == 'F' && len < 4 && accel[1] > '0' && accel[1] <= '9') {\n\t    int fkey = accel[1] - '0';\n\n\t    if (len == 3) {\n\t\tif (accel[2] >= '0' && accel[2] <= '9') {\n\t\t    fkey = 10 * fkey + (accel[2] - '0');\n\t\t} else {\n\t\t    fkey = 0;\n\t\t}\n\t    }\n\t    if (fkey >= 1 && fkey <= 15) {\n\t\tch = NSF1FunctionKey + fkey - 1;\n\t    }\n\t} else while (specialAccelerators[i].name) {\n\t    if (accel[0] == specialAccelerators[i].name[0] &&\n\t\t    len == specialAccelerators[i].len && !strncasecmp(accel,\n\t\t    specialAccelerators[i].name, specialAccelerators[i].len)) {\n\t\tch = specialAccelerators[i].ch;\n\t\tbreak;\n\t    }\n\t    i++;\n\t}\n    }\n    if (ch) {\n\treturn [[[NSString alloc] initWithCharacters:&ch length:1] autorelease];\n    } else {\n\treturn [[[[TKNSString alloc] initWithTclUtfBytes:accel length:TCL_INDEX_NONE] autorelease]\n\t\tlowercaseString];\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ModifierCharWidth --\n *\n *\tHelper measuring width of command char in given font.\n *\n * Results:\n *\tWidth of command char.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nModifierCharWidth(\n    Tk_Font tkfont)\n{\n    static NSString *cmdChar = nil;\n\n    if (!cmdChar) {\n\tunichar cmd = kCommandUnicode;\n\n\tcmdChar = [[NSString alloc] initWithCharacters:&cmd length:1];\n    }\n    return [cmdChar sizeWithAttributes:\n\t    TkMacOSXNSFontAttributesForFont(tkfont)].width;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeStandardMenuGeometry --\n *\n *\tThis procedure is invoked to recompute the size and layout of a menu\n *\tthat is not a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeStandardMenuGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    NSSize menuSize;\n    Tk_Font tkfont, menuFont;\n    Tk_FontMetrics menuMetrics, entryMetrics;\n    int modifierCharWidth, menuModifierCharWidth;\n    int x, y, modifierWidth, labelWidth, indicatorSpace;\n    int windowWidth, maxWidth, windowHeight, accelWidth;\n    Tcl_Size i;\n    int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;\n    TkMenuEntry *mePtr;\n    int haveAccel = 0;\n\n    /*\n     * Do nothing if this menu is a clone.\n     */\n\n    if (menuPtr->tkwin == NULL || menuPtr->mainMenuPtr != menuPtr) {\n\treturn;\n    }\n\n    menuSize = [(NSMenu *) menuPtr->platformData size];\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t    &borderWidth);\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,\n\t    &activeBorderWidth);\n    x = y = borderWidth;\n    windowHeight = maxWidth = 0;\n    maxIndicatorSpace = 0;\n\n    /*\n     * On the Mac especially, getting font metrics can be quite slow, so we\n     * want to do it intelligently. We are going to precalculate them and pass\n     * them down to all of the measuring and drawing routines. We will measure\n     * the font metrics of the menu once. If an entry does not have its own\n     * font set, then we give the geometry/drawing routines the menu's font and\n     * metrics. If an entry has its own font, we will measure that font and\n     * give all of the geometry/drawing the entry's font and metrics.\n     */\n\n    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n    Tk_GetFontMetrics(menuFont, &menuMetrics);\n    menuModifierCharWidth = ModifierCharWidth(menuFont);\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tmePtr = menuPtr->entries[i];\n\tif (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {\n\t    haveAccel = 1;\n\t    break;\n\t}\n    }\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tmePtr = menuPtr->entries[i];\n\tif (mePtr->type == TEAROFF_ENTRY) {\n\t    continue;\n\t}\n\tif (mePtr->fontPtr == NULL) {\n\t    tkfont = menuFont;\n\t    modifierCharWidth = menuModifierCharWidth;\n\t} else {\n\t    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);\n\t    Tk_GetFontMetrics(tkfont, &entryMetrics);\n\t    modifierCharWidth = ModifierCharWidth(tkfont);\n\t}\n\taccelWidth = modifierWidth = indicatorSpace = 0;\n\tif (mePtr->type == SEPARATOR_ENTRY) {\n\t    mePtr->height = menuSeparatorHeight;\n\t} else {\n\t    /*\n\t     * For each entry, compute the height required by that particular\n\t     * entry, plus three widths: the width of the label, the width to\n\t     * allow for an indicator to be displayed to the left of the label\n\t     * (if any), and the width of the accelerator to be displayed to\n\t     * the right of the label (if any). These sizes depend, of course,\n\t     * on the type of the entry.\n\t     */\n\n\t    NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;\n\t    int haveImage = 0, width = 0, height = 0;\n\n\t    if (mePtr->image) {\n\t\tTk_SizeOfImage(mePtr->image, &width, &height);\n\t\thaveImage = 1;\n\t\theight += 2; /* tweak */\n\t    } else if (mePtr->bitmapPtr) {\n\t\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,\n\t\t\tmePtr->bitmapPtr);\n\n\t\tTk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);\n\t\thaveImage = 1;\n\t\theight += 2; /* tweak */\n\t    }\n\t    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {\n\t\tNSAttributedString *attrTitle = [menuItem attributedTitle];\n\t\tNSSize size;\n\n\t\tif (attrTitle) {\n\t\t    size = [attrTitle size];\n\t\t} else {\n\t\t    size = [[menuItem title] sizeWithAttributes:\n\t\t\tTkMacOSXNSFontAttributesForFont(tkfont)];\n\t\t}\n\t\tsize.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;\n\t\tsize.height -= 1; /* tweak */\n\t\tif (haveImage && (mePtr->compound != COMPOUND_NONE)) {\n\t\t    int margin = width + menuIconTrailingEdgeMargin;\n\n\t\t    if (margin > menuTextLeadingEdgeMargin) {\n\t\t\tmargin = menuTextLeadingEdgeMargin;\n\t\t    }\n\t\t    width += size.width + menuIconTrailingEdgeMargin - margin;\n\t\t    if (size.height > height) {\n\t\t\theight = size.height;\n\t\t    }\n\t\t} else {\n\t\t    width = size.width;\n\t\t    height = size.height;\n\t\t}\n\t    }\n\t    else {\n\t\t/* image only. */\n\t    }\n\t    labelWidth = width + menuItemExtraWidth;\n\t    mePtr->height = height + menuItemExtraHeight;\n\t    if (mePtr->type == CASCADE_ENTRY) {\n\t\tmodifierWidth = modifierCharWidth;\n\t    } else if (mePtr->accelLength == 0) {\n\t\tif (haveAccel && !mePtr->hideMargin) {\n\t\t    modifierWidth = modifierCharWidth;\n\t\t}\n\t    } else {\n\t\tNSUInteger modifMask = [menuItem keyEquivalentModifierMask];\n\t\tint j = 0;\n\n\t\twhile (allModifiers[j].name) {\n\t\t    if (modifMask & allModifiers[j].mask) {\n\t\t\tmodifMask &= ~allModifiers[j].mask;\n\t\t\tmodifierWidth += modifierCharWidth;\n\t\t    }\n\t\t    j++;\n\t\t}\n\t\taccelWidth = [[menuItem keyEquivalent] sizeWithAttributes:\n\t\t\tTkMacOSXNSFontAttributesForFont(tkfont)].width;\n\t    }\n\t    if (!mePtr->hideMargin) {\n\t\tindicatorSpace = menuMarkColumnWidth;\n\t    }\n\t    if (indicatorSpace > maxIndicatorSpace) {\n\t\tmaxIndicatorSpace = indicatorSpace;\n\t    }\n\t    entryWidth = labelWidth + modifierWidth + accelWidth;\n\t    if (entryWidth > maxWidth) {\n\t\tmaxWidth = entryWidth;\n\t    }\n\t    menuPtr->entries[i]->width = entryWidth;\n\t    mePtr->height += 2 * activeBorderWidth;\n\t}\n\tmePtr->x = x;\n\tmePtr->y = y;\n\ty += menuPtr->entries[i]->height + borderWidth;\n    }\n    windowWidth = menuSize.width;\n    if (windowWidth <= 0) {\n\twindowWidth = 1;\n    }\n    windowHeight = menuSize.height;\n    if (windowHeight <= 0) {\n\twindowHeight = 1;\n    }\n    menuPtr->totalWidth = windowWidth;\n    menuPtr->totalHeight = windowHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateMenuSelectEvent --\n *\n *\tRespond to a menu item being selected.\n *\n * Results:\n *\tTrue if event(s) are generated - false otherwise.\n *\n * Side effects:\n *\tPlaces a virtual event on the event queue.\n *\n *----------------------------------------------------------------------\n */\n\nint\nGenerateMenuSelectEvent(\n    TKMenu *menu,\n    NSMenuItem *menuItem)\n{\n    TkMenu *menuPtr = [menu tkMenu];\n\n    if (menuPtr) {\n\tTcl_Size index = [menu tkIndexOfItem:menuItem];\n\n\tif (index < 0 || index >= menuPtr->numEntries ||\n\t\t(menuPtr->entries[index])->state == ENTRY_DISABLED) {\n\t    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n\t} else {\n\t    TkActivateMenuEntry(menuPtr, index);\n\t    MenuSelectEvent(menuPtr);\n\t    return true;\n\t}\n    }\n    return false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuSelectEvent --\n *\n *\tGenerates a \"MenuSelect\" virtual event. This can be used to do\n *\tcontext-sensitive menu help.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPlaces a virtual event on the event queue.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nMenuSelectEvent(\n    TkMenu *menuPtr)\t\t/* the menu we have selected. */\n{\n    union {XEvent general; XVirtualEvent virt;} event;\n\n    bzero(&event, sizeof(event));\n    event.virt.type = VirtualEvent;\n    event.virt.serial = LastKnownRequestProcessed(menuPtr->display);\n    event.virt.send_event = false;\n    event.virt.display = menuPtr->display;\n    event.virt.event = Tk_WindowId(menuPtr->tkwin);\n    event.virt.root = XRootWindow(menuPtr->display, 0);\n    event.virt.subwindow = None;\n    event.virt.time = TkpGetMS();\n    XQueryPointer(NULL, None, NULL, NULL, &event.virt.x_root, &event.virt.y_root, NULL,\n\t    NULL, &event.virt.state);\n    event.virt.same_screen = true;\n    event.virt.name = Tk_GetUid(\"MenuSelect\");\n    Tk_MakeWindowExist(menuPtr->tkwin);\n    if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {\n\tTk_HandleEvent(&event.general);\n    } else {\n\tTk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RecursivelyClearActiveMenu --\n *\n *\tRecursively clears the active entry in the menu's cascade hierarchy.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates <<MenuSelect>> virtual events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nRecursivelyClearActiveMenu(\n    TkMenu *menuPtr)\t\t/* The menu to reset. */\n{\n    Tcl_Size i;\n\n    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tTkMenuEntry *mePtr = menuPtr->entries[i];\n\n\tif (mePtr->type == CASCADE_ENTRY\n\t\t&& (mePtr->childMenuRefPtr != NULL)\n\t\t&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {\n\t    RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ClearMenubarActive --\n *\n *\tRecursively clears the active entry in the current menubar hierarchy.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates <<MenuSelect>> virtual events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nClearMenubarActive(void)\n{\n    NSMenu *mainMenu = [NSApp mainMenu];\n\n    if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {\n\tTkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];\n\n\tif (menuPtr &&\n\t    !(menuPtr->menuFlags & MENU_DELETION_PENDING) &&\n\t    menuPtr->numEntries > 0 &&\n\t    menuPtr->entries != NULL) {\n\t    RecursivelyClearActiveMenu(menuPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuInit --\n *\n *\tInitializes Mac-specific menu data.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAllocates a hash table.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuInit(void)\n{\n    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];\n\n#define observe(n, s) \\\n\t[nc addObserver:NSApp selector:@selector(s) name:(n) object:nil]\n    observe(NSMenuDidBeginTrackingNotification, menuBeginTracking:);\n    observe(NSMenuDidEndTrackingNotification, menuEndTracking:);\n#undef observe\n\n    [NSMenuItem setUsesUserKeyEquivalents:NO];\n    ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,\n\t    &menuMarkColumnWidth);\n    ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,\n\t    &menuTextLeadingEdgeMargin);\n    ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin,\n\t    &menuTextTrailingEdgeMargin);\n    ChkErr(GetThemeMetric, kThemeMetricMenuIconTrailingEdgeMargin,\n\t    &menuIconTrailingEdgeMargin);\n    ChkErr(GetThemeMenuItemExtra, kThemeMenuItemPlain, &menuItemExtraHeight,\n\t    &menuItemExtraWidth);\n    ChkErr(GetThemeMenuSeparatorHeight, &menuSeparatorHeight);\n}\n\n#pragma mark -\n#pragma mark NOPs\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuThreadInit --\n *\n *\tDoes platform-specific initialization of thread-specific menu state.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuThreadInit(void)\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNotifyToplevelCreate --\n *\n *\tThis routine reconfigures the menu and the clones indicated by\n *\tmenuName because a toplevel has been created and any system menus need\n *\tto be created. Only applicable to Windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn idle handler is set up to do the reconfiguration.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuNotifyToplevelCreate(\n    TCL_UNUSED(Tcl_Interp *),\t/* The interp the menu lives in. */\n    TCL_UNUSED(const char *))\t/* The name of the menu to reconfigure. */\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitializeMenuBindings --\n *\n *\tFor every interp, initializes the bindings for Windows menus. Does\n *\tnothing on Mac or XWindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tC-level bindings are setup for the interp which will handle Alt-key\n *\tsequences for menus without beeping or interfering with user-defined\n *\tAlt-key bindings.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitializeMenuBindings(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* The interpreter to set. */\n    TCL_UNUSED(Tk_BindingTable))\n\t\t\t\t/* The table to add to. */\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeMenubarGeometry --\n *\n *\tThis procedure is invoked to recompute the size and layout of a menu\n *\tthat is a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeMenubarGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    TkpComputeStandardMenuGeometry(menuPtr);\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawMenuEntry --\n *\n *\tDraws the given menu entry at the given coordinates with the given\n *\tattributes.  This is a no-op on macOS since the menus are drawn by\n *      the Apple window manager, which also handles all events related to\n *      selecting menu items.  This function is only called for tearoff\n *      menus, which are not supported on macOS but do get drawn as nearly\n *      invisible 1 pixel wide windows on macOS\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawMenuEntry(\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry to draw */\n    TCL_UNUSED(Drawable),\t\t\t/* What to draw into */\n    TCL_UNUSED(Tk_Font),\t\t/* Precalculated font for menu */\n    TCL_UNUSED(const Tk_FontMetrics *),\n\t\t\t\t/* Precalculated metrics for menu */\n    TCL_UNUSED(int),\t\t\t/* X-coordinate of topleft of entry */\n    TCL_UNUSED(int),\t\t\t/* Y-coordinate of topleft of entry */\n    TCL_UNUSED(int),\t\t\t/* Width of the entry rectangle */\n    TCL_UNUSED(int),\t\t\t/* Height of the current rectangle */\n    TCL_UNUSED(DrawMenuFlags))\t\t/* flags */\n{\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXMenubutton.c",
    "content": "/*\n * tkMacOSXMenubutton.c --\n *\n *\tThis file implements the Macintosh specific portion of the menubutton\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 2001 Apple Computer, Inc.\n * Copyright © 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2007 Revar Desmera\n * Copyright © 2015 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMenu.h\"\n#include \"tkMenubutton.h\"\n#include \"tkMacOSXFont.h\"\n#include \"tkMacOSXDebug.h\"\n\n#define FIRST_DRAW\t    2\n#define ACTIVE\t\t    4\n\n\ntypedef struct {\n    Tk_3DBorder border;\n    int relief;\n    GC gc;\n    int hasImageOrBitmap;\n} DrawParams;\n\n/*\n * Declaration of Mac specific button structure.\n */\n\ntypedef struct MacMenuButton {\n    TkMenuButton info;\t\t/* Generic button info. */\n    int flags;\n    ThemeButtonKind btnkind;\n    HIThemeButtonDrawInfo drawinfo;\n    HIThemeButtonDrawInfo lastdrawinfo;\n    DrawParams drawParams;\n} MacMenuButton;\n\n/*\n * Forward declarations for static functions defined later in this file:\n */\n\nstatic void\t\tMenuButtonEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tMenuButtonBackgroundDrawCB(MacMenuButton *ptr,\n\t\t\t    SInt16 depth, Boolean isColorDev);\nstatic void\t\tMenuButtonContentDrawCB(ThemeButtonKind kind,\n\t\t\t    const HIThemeButtonDrawInfo *info,\n\t\t\t    MacMenuButton *ptr, SInt16 depth,\n\t\t\t    Boolean isColorDev);\nstatic void\t\tMenuButtonEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tTkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr,\n\t\t\t    ThemeButtonKind *btnkind,\n\t\t\t    HIThemeButtonDrawInfo *drawinfo);\nstatic void\t\tTkMacOSXComputeMenuButtonDrawParams(\n\t\t\t    TkMenuButton *butPtr, DrawParams *dpPtr);\nstatic void\t\tTkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc,\n\t\t\t    Pixmap pixmap);\nstatic void\t\tDrawMenuButtonImageAndText(TkMenuButton *butPtr);\n\n/*\n * The structure below defines menubutton class behavior by means of\n * procedures that can be invoked from generic window code.\n */\n\nTk_ClassProcs tkpMenubuttonClass = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TkMenuButtonWorldChanged,\t/* worldChangedProc */\n\tNULL,\n\tNULL\n};\n\n/*\n * We use Apple's Pop-Up Button widget to represent the Tk Menubutton.\n * However, we do not use the NSPopUpButton class for this control.  Instead we\n * render the Pop-Up Button using the HITheme library.  This imposes some\n * constraints on what can be done.  The HITheme renderer allows only specific\n * dimensions for the button.\n *\n * The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds\n * rectangle.  However the button is always drawn as a rounded box which is 22\n * pixels high.  If the bounds rectangle is less than 22 pixels high, the\n * button is drawn at the top of the rectangle and the bottom of the button is\n * clipped away.  So we set a minimum height of 22 pixels for a Menubutton.  If\n * the bounds rectangle is more than 22 pixels high, then the button is drawn\n * centered vertically in the bounds rectangle.\n *\n * The content rectangle of the button is inset by 14 pixels on the left and 28\n * pixels on the right.  The rightmost part of the button contains the blue\n * double-arrow symbol which is 28 pixels wide.\n *\n * To maintain compatibility with code that runs on multiple operating systems,\n * the width and height of the content rectangle includes the borderWidth, the\n * highlightWidth and the padX and padY dimensions of the Menubutton.  However,\n * to be consistent with the standard Apple appearance, the content is always\n * be drawn at the left side of the content rectangle.  All of the excess space\n * appears on the right side of the content, and the anchor property is\n * ignored.  The easiest way to comply with Apple's Human Interface Guidelines\n * would be to set bd = highlightthickness = padx = 0 and to specify an\n * explicit width for the button.  Apple also recommends using the same width\n * for all Pop-Up Buttons in a given window.\n */\n\n#define LEFT_INSET 8\n#define RIGHT_INSET 28\n#define MIN_HEIGHT 22\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateMenuButton  --\n *\n *\tAllocate a new TkMenuButton structure.\n *\n * Results:\n *\tReturns a newly allocated TkMenuButton structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkMenuButton *\nTkpCreateMenuButton(\n    Tk_Window tkwin)\n{\n    MacMenuButton *mbPtr = (MacMenuButton *)Tcl_Alloc(sizeof(MacMenuButton));\n\n    Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);\n    mbPtr->flags = FIRST_DRAW;\n    mbPtr->btnkind = kThemePopupButton;\n    bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));\n    bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));\n    return (TkMenuButton *) mbPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayMenuButton --\n *\n *\tThis procedure is invoked to display a menubutton widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menubutton in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayMenuButton(\n    void *clientData)\t/* Information about widget. */\n{\n    MacMenuButton *mbPtr = (MacMenuButton *)clientData;\n    TkMenuButton *butPtr = (TkMenuButton *)clientData;\n    Tk_Window tkwin = butPtr->tkwin;\n    Pixmap pixmap;\n    DrawParams *dpPtr = &mbPtr->drawParams;\n    int highlightWidth;\n\n    butPtr->flags &= ~REDRAW_PENDING;\n    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n\n    TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr);\n\n    /*\n     * Draw the native portion of the buttons.\n     */\n\n    TkMacOSXDrawMenuButton(mbPtr,  dpPtr->gc, pixmap);\n\n    /*\n     * Draw highlight border, if needed.\n     */\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    if (highlightWidth < 3) {\n\tif (butPtr->flags & GOT_FOCUS) {\n\t    GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);\n\t    TkMacOSXDrawSolidBorder(tkwin, gc, 0, highlightWidth);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenuButton --\n *\n *\tFree data structures associated with the menubutton control. This is a\n *      no-op on the Mac.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenuButton(\n    TCL_UNUSED(TkMenuButton *))\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeMenuButtonGeometry --\n *\n *\tAfter changes in a menu button's text or bitmap, this procedure\n *\trecomputes the menu button's geometry and passes this information\n *\talong to the geometry manager for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu button's window may change size.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeMenuButtonGeometry(\n    TkMenuButton *butPtr)\t/* Widget record for menu button. */\n{\n    int width, height, avgWidth, haveImage = 0, haveText = 0;\n    int txtWidth, txtHeight;\n    Tk_FontMetrics fm;\n    int borderWidth, highlightWidth;\n    int padX, padY;\n\n    /*\n     * First compute the size of the contents of the button.\n     */\n\n    width = 0;\n    height = 0;\n    txtWidth = 0;\n    txtHeight = 0;\n    avgWidth = 0;\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    if (butPtr->textObj && Tcl_GetString(butPtr->textObj)[0]) {\n\tint wrapLength;\n\n\thaveText = 1;\n\tTk_FreeTextLayout(butPtr->textLayout);\n\tTk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->wrapLengthObj, &wrapLength);\n\tbutPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,\n\t\tTcl_GetString(butPtr->textObj), TCL_INDEX_NONE, wrapLength,\n\t\tbutPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);\n\ttxtWidth = butPtr->textWidth;\n\ttxtHeight = butPtr->textHeight;\n\tavgWidth = Tk_TextWidth(butPtr->tkfont, \"0\", 1);\n\tTk_GetFontMetrics(butPtr->tkfont, &fm);\n    }\n\n    /*\n     * If the button is compound (ie, it shows both an image and text), the new\n     * geometry is a combination of the image and text geometry. We only honor\n     * the compound bit if the button has both text and an image, because\n     * otherwise it is not really a compound button.\n     */\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->widthObj, &butPtr->width);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->heightObj, &butPtr->height);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padYObj, &padY);\n    if (haveImage && haveText) {\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text\n\t     */\n\n\t    height += txtHeight + padY;\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text\n\t     */\n\n\t    width += txtWidth + padX;\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed\n\t     */\n\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\n\tif (butPtr->width > 0) {\n\t    width = butPtr->width;\n\t}\n\tif (butPtr->height > 0) {\n\t    height = butPtr->height;\n\t}\n\n    } else {\n\tif (haveImage) { /* Image only */\n\t    if (butPtr->width > 0) {\n\t\twidth = butPtr->width;\n\t    }\n\t    if (butPtr->height > 0) {\n\t\theight = butPtr->height;\n\t    }\n\t} else { /* Text only */\n\t    width = txtWidth;\n\t    height = txtHeight;\n\t    if (butPtr->width > 0) {\n\t\twidth = butPtr->width * avgWidth + 2 * padX;\n\t    }\n\t    if (butPtr->height > 0) {\n\t\theight = butPtr->height * fm.linespace + 2 * padY;\n\t    }\n\t}\n    }\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    butPtr->inset = highlightWidth + borderWidth;\n    width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;\n    height += 2*butPtr->inset;\n    height = height < MIN_HEIGHT ? MIN_HEIGHT : height;\n    Tk_GeometryRequest(butPtr->tkwin, width, height);\n    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuButtonImageAndText --\n *\n *        Draws the image and text associated with a button or label.\n *\n * Results:\n *        None.\n *\n * Side effects:\n *        The image and text are drawn.\n *\n *----------------------------------------------------------------------\n */\nvoid\nDrawMenuButtonImageAndText(\n    TkMenuButton *butPtr)\n{\n    MacMenuButton *mbPtr = (MacMenuButton *) butPtr;\n    Tk_Window tkwin  = butPtr->tkwin;\n    Pixmap pixmap;\n    int haveImage = 0, haveText = 0;\n    int imageXOffset = 0, imageYOffset = 0;\n    int textXOffset = 0, textYOffset = 0;\n    int width = 0, height = 0;\n    int fullWidth = 0, fullHeight = 0;\n    int padX, padY;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    DrawParams *dpPtr = &mbPtr->drawParams;\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padYObj, &padY);\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tint x = 0, y = 0;\n\n\ttextXOffset = 0;\n\ttextYOffset = 0;\n\tfullWidth = 0;\n\tfullHeight = 0;\n\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_TOP) {\n\t\ttextYOffset = height + padY;\n\t    } else {\n\t\timageYOffset = butPtr->textHeight + padY;\n\t    }\n\t    fullHeight = height + butPtr->textHeight + padY;\n\t    fullWidth = (width > butPtr->textWidth ?\n\t\t     width : butPtr->textWidth);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_LEFT) {\n\t\ttextXOffset = width + padX - 2;\n\t    } else {\n\t\timageXOffset = butPtr->textWidth + padX;\n\t    }\n\t    fullWidth = butPtr->textWidth + padX + width;\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed\n\t     */\n\n\t    fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth);\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textXOffset = (fullWidth - butPtr->textWidth) / 2;\n\t    imageXOffset = (fullWidth - width) / 2;\n\t    textYOffset = (fullHeight - butPtr->textHeight) / 2;\n\t    imageYOffset = (fullHeight - height) / 2;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\n\tTkComputeAnchor(butPtr->anchor, tkwin,\n\t\tpadX + butPtr->inset, padY + butPtr->inset,\n\t\tfullWidth, fullHeight, &x, &y);\n\timageXOffset = LEFT_INSET;\n\timageYOffset += y;\n\ttextYOffset -= 1;\n\n\tif (butPtr->image != NULL) {\n\t    Tk_RedrawImage(butPtr->image, 0, 0, width,\n\t\t    height, pixmap, imageXOffset, imageYOffset);\n\t} else {\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc,\n\t\t    imageXOffset, imageYOffset);\n\t    XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,\n\t\t    0, 0, (unsigned int) width, (unsigned int) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);\n\t}\n\n\tTk_DrawTextLayout(butPtr->display, pixmap,\n\t\tdpPtr->gc, butPtr->textLayout,\n\t\tx + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,\n\t\tbutPtr->textLayout, x + textXOffset, y + textYOffset,\n\t\tbutPtr->underline);\n    } else {\n\tint x, y;\n\n\tif (haveImage) {\n\t    int borderWidth;\n\n\t    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n\t    TkComputeAnchor(butPtr->anchor, tkwin,\n\t\t    padX + borderWidth,\n\t\t    padY + borderWidth,\n\t\t    width, height, &x, &y);\n\t    imageXOffset = LEFT_INSET;\n\t    imageYOffset += y;\n\t    if (butPtr->image != NULL) {\n\t\tTk_RedrawImage(butPtr->image, 0, 0, width, height,\n\t\t\t       pixmap, imageXOffset, imageYOffset);\n\t    } else {\n\t\tXSetClipOrigin(butPtr->display, dpPtr->gc, x, y);\n\t\tXCopyPlane(butPtr->display, butPtr->bitmap,\n\t\t\t   pixmap, dpPtr->gc,\n\t\t\t   0, 0, (unsigned int) width,\n\t\t\t   (unsigned int) height,\n\t\t\t   imageXOffset, imageYOffset, 1);\n\t\tXSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);\n\t    }\n\t} else {\n\t    textXOffset = LEFT_INSET;\n\t    TkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\t    butPtr->textWidth, butPtr->textHeight, &x, &y);\n\t    Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,\n\t\t    butPtr->textLayout, textXOffset, y, 0, -1);\n\t    y += butPtr->textHeight/2;\n\t}\n   }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMacOSXDrawMenuButton --\n *\n *        This function draws the tk menubutton using Mac controls. In\n *        addition, this code may apply custom colors passed in the\n *        TkMenubutton.\n *\n * Results:\n *        None.\n *\n * Side effects:\n *        None.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXDrawMenuButton(\n    MacMenuButton *mbPtr, /* Mac menubutton. */\n    TCL_UNUSED(GC),       /* The GC we are drawing into - not used */\n    Pixmap pixmap)        /* The pixmap we are drawing into - needed for the\n\t\t\t   * bevel button */\n{\n    TkMenuButton *butPtr = (TkMenuButton *) mbPtr;\n    TkWindow *winPtr = (TkWindow *) butPtr->tkwin;\n    HIRect cntrRect;\n    TkMacOSXDrawingContext dc;\n    DrawParams *dpPtr = &mbPtr->drawParams;\n    int useNewerHITools = 1;\n\n    TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);\n\n    cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,\n\t    Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));\n\n    if (useNewerHITools == 1) {\n\tHIRect contHIRec;\n\tstatic HIThemeButtonDrawInfo hiinfo;\n\n\tMenuButtonBackgroundDrawCB(mbPtr, 32, true);\n\tif (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {\n\t    return;\n\t}\n\n\thiinfo.version = 0;\n\thiinfo.state = mbPtr->drawinfo.state;\n\thiinfo.kind = mbPtr->btnkind;\n\thiinfo.value = mbPtr->drawinfo.value;\n\thiinfo.adornment = mbPtr->drawinfo.adornment;\n\thiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();\n\tif (hiinfo.animation.time.start == 0) {\n\t    hiinfo.animation.time.start = hiinfo.animation.time.current;\n\t}\n\n\t/*\n\t * To avoid menubuttons with white text on a white background, we\n\t * always set the state to inactive in Dark Mode.  It isn't perfect but\n\t * it is usable.  Using a ttk::menubutton would be a better choice,\n\t * however.\n\t */\n\n\tif (TkMacOSXInDarkMode(butPtr->tkwin)) {\n\t    hiinfo.state = kThemeStateInactive;\n\t}\n\n\tHIThemeDrawButton(&cntrRect, &hiinfo, dc.context,\n\t\tkHIThemeOrientationNormal, &contHIRec);\n\tTkMacOSXRestoreDrawingContext(&dc);\n\tMenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,\n\t\tmbPtr, 32, true);\n    } else {\n\tif (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {\n\t    return;\n\t}\n\tTkMacOSXRestoreDrawingContext(&dc);\n    }\n    mbPtr->lastdrawinfo = mbPtr->drawinfo;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonBackgroundDrawCB --\n *\n *      This function draws the background that lies under checkboxes and\n *      radiobuttons.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      The background gets updated to the current color.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMenuButtonBackgroundDrawCB (\n    MacMenuButton *ptr,\n    TCL_UNUSED(SInt16),\n    TCL_UNUSED(Boolean))\n{\n    TkMenuButton* butPtr = (TkMenuButton *) ptr;\n    Tk_Window tkwin = butPtr->tkwin;\n    Pixmap pixmap;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n    pixmap = (Pixmap) Tk_WindowId(tkwin);\n    Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,\n\t    Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonContentDrawCB --\n *\n *      This function draws the label and image for the button.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      The content of the button gets updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMenuButtonContentDrawCB (\n    TCL_UNUSED(ThemeButtonKind),\n    TCL_UNUSED(const HIThemeButtonDrawInfo *),\n    MacMenuButton *ptr,\n    TCL_UNUSED(SInt16),\n    TCL_UNUSED(Boolean))\n{\n    TkMenuButton *butPtr = (TkMenuButton *) ptr;\n    Tk_Window tkwin = butPtr->tkwin;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n    DrawMenuButtonImageAndText(butPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * MenuButtonEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tbuttons.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen it gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nMenuButtonEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkMenuButton *buttonPtr = (TkMenuButton *)clientData;\n    MacMenuButton *mbPtr = (MacMenuButton *)clientData;\n\n    if (eventPtr->type == ActivateNotify\n\t    || eventPtr->type == DeactivateNotify) {\n\tif ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) {\n\t    return;\n\t}\n\tif (eventPtr->type == ActivateNotify) {\n\t    mbPtr->flags |= ACTIVE;\n\t} else {\n\t    mbPtr->flags &= ~ACTIVE;\n\t}\n\tif ((buttonPtr->flags & REDRAW_PENDING) == 0) {\n\t    Tcl_DoWhenIdle(TkpDisplayMenuButton, buttonPtr);\n\t    buttonPtr->flags |= REDRAW_PENDING;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXComputeMenuButtonParams --\n *\n *      This procedure computes the various parameters used when creating a\n *      Carbon Appearance control. These are determined by the various Tk\n *      button parameters\n *\n * Results:\n *        None.\n *\n * Side effects:\n *        Sets the btnkind and drawinfo parameters\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXComputeMenuButtonParams(\n    TkMenuButton *butPtr,\n    ThemeButtonKind *btnkind,\n    HIThemeButtonDrawInfo *drawinfo)\n{\n    MacMenuButton *mbPtr = (MacMenuButton *) butPtr;\n    int highlightWidth;\n\n    if (butPtr->image || butPtr->bitmap || butPtr->textObj) {\n\t/* TODO: allow for Small and Mini menubuttons. */\n\t*btnkind = kThemePopupButton;\n    } else { /* This should never happen. */\n\t*btnkind = kThemeArrowButton;\n    }\n\n    drawinfo->value = kThemeButtonOff;\n\n    if ((mbPtr->flags & FIRST_DRAW) != 0) {\n\tmbPtr->flags &= ~FIRST_DRAW;\n\tif (Tk_MacOSXIsAppInFront()) {\n\t    mbPtr->flags |= ACTIVE;\n\t}\n    }\n\n    drawinfo->state = kThemeStateInactive;\n    if ((mbPtr->flags & ACTIVE) == 0) {\n\tif (butPtr->state == STATE_DISABLED) {\n\t    drawinfo->state = kThemeStateUnavailableInactive;\n\t} else {\n\t    drawinfo->state = kThemeStateInactive;\n\t}\n    } else if (butPtr->state == STATE_DISABLED) {\n\tdrawinfo->state = kThemeStateUnavailable;\n    } else {\n\tdrawinfo->state = kThemeStateActive;\n    }\n\n    drawinfo->adornment = kThemeAdornmentNone;\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    if (highlightWidth >= 3) {\n\tif ((butPtr->flags & GOT_FOCUS)) {\n\t    drawinfo->adornment |= kThemeAdornmentFocus;\n\t}\n    }\n    drawinfo->adornment |= kThemeAdornmentArrowDoubleArrow;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXComputeMenuButtonDrawParams --\n *\n *      This procedure selects an appropriate drawing context for drawing a\n *      menubutton.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      Sets the button draw parameters.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXComputeMenuButtonDrawParams(\n    TkMenuButton *butPtr,\n    DrawParams *dpPtr)\n{\n    dpPtr->hasImageOrBitmap =\n\t    ((butPtr->image != NULL) || (butPtr->bitmap != None));\n    dpPtr->border = butPtr->normalBorder;\n    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {\n\tdpPtr->gc = butPtr->disabledGC;\n    } else if (butPtr->state == STATE_ACTIVE) {\n\tdpPtr->gc = butPtr->activeTextGC;\n\tdpPtr->border = butPtr->activeBorder;\n    } else {\n\tdpPtr->gc = butPtr->normalTextGC;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXMenus.c",
    "content": "/*\n * tkMacOSXMenus.c --\n *\n *\tThese calls set up the default menus for Tk.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMenu.h\"\n#include \"tkMacOSXConstants.h\"\n\nstatic void\t\tGenerateEditEvent(const char *name);\nstatic Tcl_Obj *\tGetWidgetDemoPath(Tcl_Interp *interp);\n\n\f\n#pragma mark TKApplication(TKMenus)\n\n@implementation TKApplication(TKMenus)\n- (void) _setupMenus\n{\n    if (_defaultMainMenu) {\n\treturn;\n    }\n    TkMenuInit();\n\n    NSString *applicationName = [[NSBundle mainBundle]\n\t    objectForInfoDictionaryKey:@\"CFBundleName\"];\n\n    if (!applicationName) {\n\tapplicationName = [[NSProcessInfo processInfo] processName];\n    }\n\n    NSString *aboutName = (applicationName &&\n\t    ![applicationName isEqualToString:@\"Wish\"] &&\n\t    ![applicationName hasPrefix:@\"tclsh\"]) ?\n\t    applicationName : @\"Tcl & Tk\";\n\n    _servicesMenu = [NSMenu menuWithTitle:@\"Services\"];\n    _defaultApplicationMenuItems = [[NSArray arrayWithObjects:\n\t    [NSMenuItem separatorItem],\n\t    [NSMenuItem itemWithTitle:\n\t\t   [NSString stringWithFormat:@\"Preferences%C\", 0x2026]\n\t\t   action:@selector(preferences:) keyEquivalent:@\",\"],\n\t    [NSMenuItem separatorItem],\n\t    [NSMenuItem itemWithTitle:@\"Services\" submenu:_servicesMenu],\n\t    [NSMenuItem separatorItem],\n\t    [NSMenuItem itemWithTitle:\n\t\t   [NSString stringWithFormat:@\"Hide %@\", applicationName]\n\t\t   action:@selector(hide:) keyEquivalent:@\"h\"],\n\t    [NSMenuItem itemWithTitle:@\"Hide Others\"\n\t\t   action:@selector(hideOtherApplications:) keyEquivalent:@\"h\"\n\t\t   keyEquivalentModifierMask:\n\t\t   NSCommandKeyMask|NSAlternateKeyMask],\n\t    [NSMenuItem itemWithTitle:@\"Show All\"\n\t\t   action:@selector(unhideAllApplications:)],\n\t    [NSMenuItem separatorItem],\n\t    [NSMenuItem itemWithTitle:\n\t\t   [NSString stringWithFormat:@\"Quit %@\", applicationName]\n\t\t   action: @selector(terminate:) keyEquivalent:@\"q\"],\n\t    nil] retain];\n    _defaultApplicationMenu = [TKMenu menuWithTitle:applicationName\n\t    menuItems:_defaultApplicationMenuItems];\n    [_defaultApplicationMenu insertItem:\n\t    [NSMenuItem itemWithTitle:\n\t\t    [NSString stringWithFormat:@\"About %@\", aboutName]\n\t\t    action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];\n    _defaultFileMenuItems =\n\t    [[NSArray arrayWithObjects:\n\t    [NSMenuItem itemWithTitle:\n\t\t   [NSString stringWithFormat:@\"Source%C\", 0x2026]\n\t\t   action:@selector(tkSource:)],\n\t    [NSMenuItem itemWithTitle:@\"Run Widget Demo\"\n\t\t   action:@selector(tkDemo:)],\n\t    [NSMenuItem itemWithTitle:@\"Close\" action:@selector(performClose:)\n\t\t   target:nil keyEquivalent:@\"w\"],\n\t    nil] retain];\n    _demoMenuItem = [_defaultFileMenuItems objectAtIndex:1];\n    TKMenu *fileMenu = [TKMenu menuWithTitle:@\"File\"\n\t    menuItems: _defaultFileMenuItems];\n    TKMenu *editMenu = [TKMenu menuWithTitle:@\"Edit\" menuItems:\n\t    [NSArray arrayWithObjects:\n\t    [NSMenuItem itemWithTitle:@\"Undo\" action:@selector(undo:)\n\t\t   target:nil keyEquivalent:@\"z\"],\n\t    [NSMenuItem itemWithTitle:@\"Redo\" action:@selector(redo:)\n\t\t   target:nil keyEquivalent:@\"y\"],\n\t    [NSMenuItem separatorItem],\n\t    [NSMenuItem itemWithTitle:@\"Cut\" action:@selector(cut:)\n\t\t   target:nil keyEquivalent:@\"x\"],\n\t    [NSMenuItem itemWithTitle:@\"Copy\" action:@selector(copy:)\n\t\t   target:nil keyEquivalent:@\"c\"],\n\t    [NSMenuItem itemWithTitle:@\"Paste\" action:@selector(paste:)\n\t\t   target:nil keyEquivalent:@\"v\"],\n\t    [NSMenuItem itemWithTitle:@\"Delete\" action:@selector(delete:)\n\t\t   target:nil],\n\t    nil]];\n\n    _defaultWindowsMenuItems = [NSArray arrayWithObjects:\n\t    [NSMenuItem itemWithTitle:@\"Minimize\"\n\t\t   action:@selector(performMiniaturize:) target:nil\n\t\t   keyEquivalent:@\"m\"],\n\t    [NSMenuItem itemWithTitle:@\"Zoom\" action:@selector(performZoom:)\n\t\t   target:nil],\n\t    nil];\n\n    /*\n     * On OS X 10.12 we get duplicate tab control items if we create them here.\n     */\n\n    if ([NSApp macOSVersion] >= 101300) {\n\t_defaultWindowsMenuItems = [_defaultWindowsMenuItems\n\t     arrayByAddingObjectsFromArray:\n\t     [NSArray arrayWithObjects:\n\t\t    [NSMenuItem separatorItem],\n\t\t    [NSMenuItem itemWithTitle:@\"Show Previous Tab\"\n\t\t\t   action:@selector(selectPreviousTab:)\n\t\t\t   target:nil\n\t\t\t   keyEquivalent:@\"\\t\"\n\t\t\t   keyEquivalentModifierMask:\n\t\t\t       NSControlKeyMask|NSShiftKeyMask],\n\t\t    [NSMenuItem itemWithTitle:@\"Show Next Tab\"\n\t\t\t   action:@selector(selectNextTab:)\n\t\t\t   target:nil\n\t\t\t   keyEquivalent:@\"\\t\"\n\t\t\t   keyEquivalentModifierMask:NSControlKeyMask],\n\t\t    [NSMenuItem itemWithTitle:@\"Move Tab To New Window\"\n\t\t\t   action:@selector(moveTabToNewWindow:)\n\t\t\t   target:nil],\n\t\t    [NSMenuItem itemWithTitle:@\"Merge All Windows\"\n\t\t\t   action:@selector(mergeAllWindows:)\n\t\t\t   target:nil],\n\t\t    [NSMenuItem separatorItem],\n\t\t    nil]];\n    }\n    _defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject:\n\t    [NSMenuItem itemWithTitle:@\"Bring All to Front\"\n\t\t   action:@selector(arrangeInFront:)]];\n    [_defaultWindowsMenuItems retain];\n    TKMenu *windowsMenu = [TKMenu menuWithTitle:@\"Window\" menuItems:\n\t\t\t\t      _defaultWindowsMenuItems];\n    _defaultHelpMenuItems = [[NSArray arrayWithObjects:\n\t    [NSMenuItem itemWithTitle:\n\t\t   [NSString stringWithFormat:@\"%@ Help\", applicationName]\n\t\t   action:@selector(showHelp:) keyEquivalent:@\"?\"],\n\t    nil] retain];\n    TKMenu *helpMenu = [TKMenu menuWithTitle:@\"Help\" menuItems:\n\t    _defaultHelpMenuItems];\n    [self setServicesMenu:_servicesMenu];\n    [self setWindowsMenu:windowsMenu];\n    _defaultMainMenu = [[TKMenu menuWithTitle:@\"\" submenus:[NSArray\n\t    arrayWithObjects:_defaultApplicationMenu, fileMenu, editMenu,\n\t    windowsMenu, helpMenu, nil]] retain];\n    [_defaultMainMenu setSpecial:tkMainMenu];\n    [_defaultApplicationMenu setSpecial:tkApplicationMenu];\n    [windowsMenu setSpecial:tkWindowsMenu];\n    [helpMenu setSpecial:tkHelpMenu];\n    [self tkSetMainMenu:nil];\n}\n\n- (void) dealloc\n{\n    [_defaultMainMenu release];\n    [_defaultHelpMenuItems release];\n    [_defaultWindowsMenuItems release];\n    [_defaultApplicationMenuItems release];\n    [_defaultFileMenuItems release];\n    [super dealloc];\n}\n\n- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem\n{\n    SEL action = [anItem action];\n\n    if (sel_isEqual(action, @selector(preferences:))) {\n\treturn (_eventInterp && Tcl_FindCommand(_eventInterp,\n\t\t\"::tk::mac::ShowPreferences\", NULL, 0));\n    } else if (sel_isEqual(action, @selector(tkDemo:))) {\n\tBOOL haveDemo = NO;\n\n\tif (_eventInterp) {\n\t    Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);\n\n\t    if (path) {\n\t\tTcl_IncrRefCount(path);\n\t\thaveDemo = (Tcl_FSAccess(path, R_OK) == 0);\n\t\tTcl_DecrRefCount(path);\n\t    }\n\t}\n\treturn haveDemo;\n    } else {\n\treturn [super validateUserInterfaceItem:anItem];\n    }\n}\n\n- (void) orderFrontStandardAboutPanel: (id) sender\n{\n    (void)sender;\n\n    if (!_eventInterp || !Tcl_FindCommand(_eventInterp, \"tkAboutDialog\",\n\t    NULL, 0) || (GetCurrentEventKeyModifiers() & optionKey)) {\n\t[super orderFrontStandardAboutPanel:NSApp];\n    } else {\n\tint code = Tcl_EvalEx(_eventInterp, \"tkAboutDialog\", TCL_INDEX_NONE,\n\t\tTCL_EVAL_GLOBAL);\n\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n\tTcl_ResetResult(_eventInterp);\n    }\n}\n\n- (void) showHelp: (id) sender\n{\n    if (!_eventInterp || !Tcl_FindCommand(_eventInterp,\n\t    \"::tk::mac::ShowHelp\", NULL, 0)) {\n\t[super showHelp:sender];\n    } else {\n\tint code = Tcl_EvalEx(_eventInterp, \"::tk::mac::ShowHelp\", TCL_INDEX_NONE,\n\t\tTCL_EVAL_GLOBAL);\n\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n\tTcl_ResetResult(_eventInterp);\n    }\n}\n\n- (void) tkSource: (id) sender\n{\n    (void)sender;\n\n    if (_eventInterp) {\n\tif (Tcl_EvalEx(_eventInterp, \"tk_getOpenFile -filetypes {\"\n\t\t\"{{TCL Scripts} {.tcl} TEXT} {{Text Files} {} TEXT}}\",\n\t\tTCL_INDEX_NONE, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t    Tcl_Obj *path = Tcl_GetObjResult(_eventInterp);\n\t    Tcl_Size len;\n\n\t    Tcl_GetStringFromObj(path, &len);\n\t    if (len) {\n\t\tTcl_IncrRefCount(path);\n\n\t\tint code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);\n\n\t\tif (code != TCL_OK) {\n\t\t    Tcl_BackgroundException(_eventInterp, code);\n\t\t}\n\t\tTcl_DecrRefCount(path);\n\t    }\n\t}\n\tTcl_ResetResult(_eventInterp);\n    }\n}\n\n- (void) tkDemo: (id) sender\n{\n\t(void)sender;\n\n    if (_eventInterp) {\n\tTcl_Obj *path = GetWidgetDemoPath(_eventInterp);\n\n\tif (path) {\n\t    Tcl_IncrRefCount(path);\n\n\t    [_demoMenuItem setHidden:YES];\n\t    int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);\n\n\t    if (code != TCL_OK) {\n\t\tTcl_BackgroundException(_eventInterp, code);\n\t    }\n\t    Tcl_DecrRefCount(path);\n\t    Tcl_ResetResult(_eventInterp);\n\t}\n    }\n}\n@end\n\f\n#pragma mark TKContentView(TKMenus)\n\n@implementation TKContentView(TKMenus)\n\n- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem\n{\n    (void)anItem;\n\n    return YES;\n}\n\n#define EDIT_ACTION(a, e) \\\n    - (void) a: (id) sender \\\n    { \\\n\tif ([sender isKindOfClass:[NSMenuItem class]]) { \\\n\t    GenerateEditEvent(#e); \\\n\t} \\\n    }\nEDIT_ACTION(cut, Cut)\nEDIT_ACTION(copy, Copy)\nEDIT_ACTION(paste, Paste)\nEDIT_ACTION(delete, Clear)\nEDIT_ACTION(undo, Undo)\nEDIT_ACTION(redo, Redo)\n#undef EDIT_ACTION\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetWidgetDemoPath --\n *\n *\tGet path to the widget demo.\n *\n * Results:\n *\tpathObj with ref count 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetWidgetDemoPath(\n    Tcl_Interp *interp)\n{\n    Tcl_Obj *result = NULL;\n\n    if (Tcl_EvalEx(interp, \"::tk::pkgconfig get demodir,runtime\",\n\t\t   TCL_INDEX_NONE, TCL_EVAL_GLOBAL) == TCL_OK) {\n\tTcl_Obj *libpath, *demo[1] = { Tcl_NewStringObj(\"widget\", 6) };\n\n\tlibpath = Tcl_GetObjResult(interp);\n\tTcl_IncrRefCount(libpath);\n\tTcl_IncrRefCount(demo[0]);\n\tresult = Tcl_FSJoinToPath(libpath, 1, demo);\n\tTcl_DecrRefCount(demo[0]);\n\tTcl_DecrRefCount(libpath);\n    }\n    Tcl_ResetResult(interp);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateEditEvent --\n *\n *\tTakes an edit menu item and posts the corasponding a virtual event to\n *\tTk's event queue.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay place events of queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateEditEvent(\n    const char *name)\n{\n    union {XEvent general; XVirtualEvent virt;} event;\n    int x, y;\n    TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);\n    Tk_Window tkwin;\n\n    if (!winPtr) {\n\treturn;\n    }\n    tkwin = (Tk_Window)winPtr->dispPtr->focusPtr;\n    if (!tkwin) {\n\treturn;\n    }\n    bzero(&event, sizeof(event));\n    event.virt.type = VirtualEvent;\n    event.virt.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n    event.virt.send_event = false;\n    event.virt.display = Tk_Display(tkwin);\n    event.virt.event = Tk_WindowId(tkwin);\n    event.virt.root = XRootWindow(Tk_Display(tkwin), 0);\n    event.virt.subwindow = None;\n    event.virt.time = TkpGetMS();\n    XQueryPointer(NULL, winPtr->window, NULL, NULL,\n\t    &event.virt.x_root, &event.virt.y_root, &x, &y, &event.virt.state);\n    Tk_TopCoordsToWindow(tkwin, x, y, &event.virt.x, &event.virt.y);\n    event.virt.same_screen = true;\n    event.virt.name = Tk_GetUid(name);\n    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);\n}\n\n#pragma mark -\n\f\n#pragma mark NSMenu & NSMenuItem Utilities\n\n@implementation NSMenu(TKUtils)\n\n+ (id) menuWithTitle: (NSString *) title\n{\n    NSMenu *m = [[self alloc] initWithTitle:title];\n\n    return [m autorelease];\n}\n\n+ (id) menuWithTitle: (NSString *) title menuItems: (NSArray *) items\n{\n    NSMenu *m = [[self alloc] initWithTitle:title];\n\n    for (NSMenuItem *i in items) {\n\t[m addItem:i];\n    }\n    return [m autorelease];\n}\n\n+ (id) menuWithTitle: (NSString *) title submenus: (NSArray *) submenus\n{\n    NSMenu *m = [[self alloc] initWithTitle:title];\n\n    for (NSMenu *i in submenus) {\n\t[m addItem:[NSMenuItem itemWithSubmenu:i]];\n    }\n    return [m autorelease];\n}\n\n- (NSMenuItem *) itemWithSubmenu: (NSMenu *) submenu\n{\n    return [self itemAtIndex:[self indexOfItemWithSubmenu:submenu]];\n}\n\n- (NSMenuItem *) itemInSupermenu\n{\n    NSMenu *supermenu = [self supermenu];\n\n    return (supermenu ? [supermenu itemWithSubmenu:self] : nil);\n}\n@end\n\n@implementation NSMenuItem(TKUtils)\n\n+ (id) itemWithSubmenu: (NSMenu *) submenu\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:[submenu title] action:NULL\n\t    keyEquivalent:@\"\"];\n\n    [i setSubmenu:submenu];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title submenu: (NSMenu *) submenu\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:NULL\n\t    keyEquivalent:@\"\"];\n\n    [i setSubmenu:submenu];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:@\"\"];\n\n    [i setTarget:NSApp];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n\ttarget: (id) target\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:@\"\"];\n\n    [i setTarget:target];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n\tkeyEquivalent: (NSString *) keyEquivalent\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:keyEquivalent];\n\n    [i setTarget:NSApp];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n\ttarget: (id) target keyEquivalent: (NSString *) keyEquivalent\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:keyEquivalent];\n\n    [i setTarget:target];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n\tkeyEquivalent: (NSString *) keyEquivalent\n\tkeyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:keyEquivalent];\n\n    [i setTarget:NSApp];\n    [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];\n    return [i autorelease];\n}\n\n+ (id) itemWithTitle: (NSString *) title action: (SEL) action\n\ttarget: (id) target keyEquivalent: (NSString *) keyEquivalent\n\tkeyEquivalentModifierMask: (NSUInteger) keyEquivalentModifierMask\n{\n    NSMenuItem *i = [[self alloc] initWithTitle:title action:action\n\t    keyEquivalent:keyEquivalent];\n\n    [i setTarget:target];\n    [i setKeyEquivalentModifierMask:keyEquivalentModifierMask];\n    return [i autorelease];\n}\n@end\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXMouseEvent.c",
    "content": "/*\n * tkMacOSXMouseEvent.c --\n *\n *\tThis file implements functions that decode & handle mouse events on\n *\tMacOS X.\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXWm.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXConstants.h\"\n\ntypedef struct {\n    unsigned int state;\n    long delta;\n    Window window;\n    Point global;\n    Point local;\n} MouseEventData;\n\nstatic Tk_Window captureWinPtr = NULL;\t/* Current capture window; may be\n\t\t\t\t\t * NULL. */\n\n#pragma mark TKApplication(TKMouseEvent)\n\nenum {\n    NSWindowWillMoveEventType = 20\n};\n\n/*\n * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil\n * window attribute pointing to the key window.  As of 10.8 this behavior had\n * changed.  The new behavior was that if the mouse were ever moved outside of\n * a window, all subsequent NSMouseMoved NSEvents would have a Nil window\n * attribute until the mouse returned to the window.  In 11.1 it changed again.\n * The window attribute can be non-nil, but referencing a window which does not\n * belong to the application.\n */\n\n/* The basic job of tkProcessMouseEvent is to generate a call to\n * Tk_UpdatePointer.  That function receives a Tk_Window which (ignoring cases\n * when a grab is in effect) should be the highest window within the focused\n * toplevel that contains the pointer, as well as the pointer location in\n * screen coordinates and the current button state.  Tk maintains a cache of\n * these three values.  A change in any of these values causes Tk_UpdatePointer\n * to generate, respectively, Enter/Leave events, or Motion events, or\n * button Press/Release events. The Tk_Window value is allowed to be NULL,\n * which indicates that the pointer is not in the focused toplevel.\n *\n * Enter or Leave events for toplevel windows are generated when the Tk_Window\n * value changes to or from NULL.  This is problematic on macOS due to the fact\n * that Tk_UpdatePointer does not generate Motion events when the Tk_Window\n * value is NULL.  A consequence of this is that Tk_UpdatePointer will either\n * fail to generate correct Enter/Leave events for toplevels or else be unable\n * to generate Motion events when the pointer is outside of the focus window.\n * It is important to be able to generate such events because otherwise a\n * scrollbar on the edge of a toplevel becomes unusable.  Any time that the\n * pointer wanders out of the window during a scroll, the scroll will stop.\n * That is an extremely annoying and unexpected behavior.  Much of the code in\n * this module, including the trickiest parts, is devoted to working around\n * this problem.  The other tricky parts are related to transcribing Apple's\n * NSMouseEntered, NSMouseExited, and NSLeftMouseDragged events into a form\n * that makes sense to Tk.\n */\n\n\n@implementation TKApplication(TKMouseEvent)\n\n- (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent\n{\n    NSWindow *eventWindow = [theEvent window];\n    NSEventType eventType = [theEvent type];\n    TKContentView *contentView = [eventWindow contentView];\n    NSPoint location = [theEvent locationInWindow];\n    //NSPoint viewLocation = [contentView convertPoint:location fromView:nil];\n    TkWindow *winPtr = NULL, *grabWinPtr, *scrollTarget = NULL;\n    Tk_Window tkwin = NULL, capture, target;\n    NSPoint local, global;\n    NSInteger button;\n    TkWindow *newFocus = NULL;\n    int win_x, win_y;\n    unsigned int buttonState = 0;\n    Bool isTestingEvent = NO;\n    Bool isMotionEvent = NO;\n    Bool isOutside = NO;\n    Bool firstDrag = NO;\n    static Bool ignoreDrags = NO;\n    static Bool ignoreUpDown = NO;\n    static NSTimeInterval timestamp = 0;\n\n#ifdef TK_MAC_DEBUG_EVENTS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), theEvent);\n#endif\n\n    /*\n     * If this event is not for a Tk toplevel, it should normally just be\n     * passed up the responder chain.  However, there is are two exceptions.\n     * One is for synthesized events, which are used in testing.  Those events\n     * are recognized by having their timestamp set to 0.  The other is for\n     * motion events sent by the local event monitor, which will have their\n     * window attribute set to nil.\n     */\n\n    if (![eventWindow isMemberOfClass:[TKWindow class]] &&\n\t![eventWindow isMemberOfClass:[TKPanel class]]) {\n\tif ([theEvent timestamp] == 0) {\n\t    isTestingEvent = YES;\n\t    eventWindow = [NSApp keyWindow];\n\t}\n\tif (eventType == NSLeftMouseDragged ||\n\t    eventType == NSMouseMoved) {\n\t    eventWindow = [NSApp keyWindow];\n\t    isMotionEvent = YES;\n\t}\n\tif (!isTestingEvent && !isMotionEvent) {\n\t    return theEvent;\n\t}\n    } else if (!NSPointInRect(location, [contentView bounds])) {\n\tisOutside = YES;\n    }\n    button = [theEvent buttonNumber] + Button1;\n    if ((button & -2) == Button2) {\n\tbutton ^= 1; /* Swap buttons 2/3 */\n    }\n    switch (eventType) {\n    case NSRightMouseUp:\n    case NSOtherMouseUp:\n\tbuttonState &= ~Tk_GetButtonMask(button);\n\tbreak;\n    case NSLeftMouseDragged:\n\tbuttonState |= Tk_GetButtonMask(button);\n\tif (![NSApp tkDragTarget]) {\n\t    if (isOutside) {\n\t\tignoreDrags = YES;\n\t    } else {\n\t\tfirstDrag = YES;\n\t    }\n\t}\n\tif (ignoreDrags) {\n\t    return theEvent;\n\t}\n\tif (![NSApp tkDragTarget]) {\n\t    [NSApp setTkDragTarget: [NSApp tkEventTarget]];\n\t}\n\tbreak;\n    case NSRightMouseDragged:\n    case NSOtherMouseDragged:\n\tisMotionEvent = YES;\n    case NSRightMouseDown:\n    case NSOtherMouseDown:\n\tbuttonState |= Tk_GetButtonMask(button);\n\tbreak;\n    case NSMouseEntered:\n\tif (![eventWindow isKeyWindow] || isOutside) {\n\t    return theEvent;\n\t}\n\t[NSApp setTkLiveResizeEnded:NO];\n\t[NSApp setTkPointerWindow:[NSApp tkEventTarget]];\n\tbreak;\n    case NSMouseExited:\n\tif (![eventWindow isKeyWindow] || !isOutside) {\n\t    return theEvent;\n\t}\n\t[NSApp setTkPointerWindow:nil];\n\tbreak;\n    case NSLeftMouseUp:\n\t[NSApp setTkDragTarget: nil];\n\tif ([theEvent clickCount] == 2) {\n\t    ignoreUpDown = NO;\n\t}\n\tif (ignoreUpDown) {\n\t    return theEvent;\n\t}\n\tif (ignoreDrags) {\n\t    ignoreDrags = NO;\n\t    return theEvent;\n\t}\n\tbuttonState &= ~Tk_GetButtonMask(Button1);\n\tbreak;\n    case NSLeftMouseDown:\n\n\t/*\n\t * There are situations where Apple does not send NSLeftMouseUp events\n\t * even though the mouse button has been released.  One of these is\n\t * whenever a menu is posted on the screen.  This causes Tk to have an\n\t * inaccurate idea of the current button state and to behave strangely.\n\t * (See ticket[a132b5507e].)  As a work-around we watch for NSButtonDown\n\t * events that arrive when Tk thinks the button is already down and\n\t * we attempt to correct Tk's cached button state by insering a call to\n\t * Tk_UpdatePointer showing the button as up.\n\t */\n\n\tif ([NSApp tkButtonState] & Tk_GetButtonMask(Button1)) {\n\t    int fakeState = [NSApp tkButtonState] & ~Tk_GetButtonMask(Button1);\n\t    int x = location.x;\n\t    int y = floor(TkMacOSXZeroScreenHeight() - location.y);\n\t    Tk_UpdatePointer((Tk_Window) [NSApp tkEventTarget], x, y, fakeState);\n\t}\n\n\t/*\n\t * Ignore left mouse button events which are in an NSWindow but outside\n\t * of its contentView (see tickets [d72abe6b54] and [39cbacb9e8]).\n\t * Ignore the first left button press after a live resize ends. (Apple\n\t * sends the button press event that started the resize after the\n\t * resize ends.  It should not be seen by Tk.  See tickets [d72abe6b54]\n\t * and [39cbacb9e8]).  Ignore button press events when ignoreUpDown is\n\t * set.  These are extraneous events which appear when double-clicking\n\t * in a window without focus, causing duplicate Double-1 events (see\n\t * ticket [7bda9882cb]).  When a LeftMouseDown event with clickCount 2\n\t * is received we set the ignoreUpDown flag and we clear it when the\n\t * matching LeftMouseUp with click count 2 is received.\n\t */\n\n\t/*\n\t * Make sure we don't ignore LeftMouseUp and LeftMouseDown forever.\n\t * Currently tkBind.c sets NEARBY_MS to 500 (the Windows default).\n\t */\n\n\tif ([theEvent timestamp] - timestamp > 1) {\n\t    ignoreUpDown = NO;\n\t}\n\tif ([theEvent clickCount] == 2) {\n\t    if (ignoreUpDown == YES) {\n\t\treturn theEvent;\n\t    } else {\n\t\ttimestamp = [theEvent timestamp];\n\t\tignoreUpDown = YES;\n\t    }\n\t}\n\tif (!isTestingEvent) {\n\t    NSRect bounds = [contentView bounds];\n\t    NSRect grip = NSMakeRect(bounds.size.width - 10, 0, 10, 10);\n\t    bounds = NSInsetRect(bounds, 2.0, 2.0);\n\t    if (!NSPointInRect(location, bounds)) {\n\t\treturn theEvent;\n\t    }\n\t    if (NSPointInRect(location, grip)) {\n\t\treturn theEvent;\n\t    }\n\t    if ([NSApp tkLiveResizeEnded]) {\n\t\t[NSApp setTkLiveResizeEnded:NO];\n\t\treturn theEvent;\n\t    }\n\t}\n\n\t/*\n\t * If this click will change the focus, the Tk event should\n\t * be sent to the toplevel which will be receiving focus rather than to\n\t * the current focus window.  So reset tkEventTarget.\n\t */\n\n\tif (eventWindow != [NSApp keyWindow]) {\n\t    NSWindow *w;\n\n\t    if (eventWindow && isOutside) {\n\t\treturn theEvent;\n\t    }\n\t    for (w in [NSApp orderedWindows]) {\n\t\tif (NSPointInRect([NSEvent mouseLocation], [w frame])) {\n\t\t    newFocus = TkMacOSXGetTkWindow(w);\n\t\t    break;\n\t\t}\n\t    }\n\t    if (newFocus) {\n\t\t[NSApp setTkEventTarget: newFocus];\n\t\t[NSApp setTkPointerWindow: newFocus];\n\t\ttarget = (Tk_Window) newFocus;\n\t    }\n\t}\n\tbuttonState |= Tk_GetButtonMask(Button1);\n\tbreak;\n    case NSMouseMoved:\n\tif (eventWindow && eventWindow != [NSApp keyWindow]) {\n\t    return theEvent;\n\t}\n\tisMotionEvent = YES;\n\tbreak;\n    case NSScrollWheel:\n\n\t/*\n\t * Scroll wheel events are sent to the window containing the pointer,\n\t * or ignored if no window contains the pointer.  See TIP #171.  Note,\n\t * however, that TIP #171 proposed sending scroll wheel events to the\n\t * focus window when no window contains the pointer.  That proposal was\n\t * ultimately rejected.\n\t */\n\n\tscrollTarget = TkMacOSXGetTkWindow(eventWindow);\n#if 0\n    case NSCursorUpdate:\n    case NSTabletPoint:\n    case NSTabletProximity:\n#endif\n\tbreak;\n    default: /* This type of event is ignored. */\n\treturn theEvent;\n    }\n\n    /*\n     * Find the toplevel window for the event.\n     */\n\n    if ([NSApp tkDragTarget]) {\n\tTkWindow *dragPtr = (TkWindow *) [NSApp tkDragTarget];\n\tTKWindow *dragWindow = nil;\n\tMacDrawable *topMacWin;\n\tif (dragPtr) {\n\t    dragWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable(\n\t\t\t    dragPtr->window);\n\t}\n\tif (!dragWindow) {\n\t    [NSApp setTkDragTarget: nil];\n\t    target = NULL;\n\t    return theEvent;\n\t}\n\ttopMacWin = TkMacOSXGetHostToplevel(dragPtr);\n\tif (topMacWin) {\n\t    winPtr = topMacWin->winPtr;\n\t}\n    } else if (eventType == NSScrollWheel) {\n\twinPtr = scrollTarget;\n    } else {\n\twinPtr = [NSApp tkEventTarget];\n    }\n    if (!winPtr) {\n\n\t/*\n\t * If we couldn't find a toplevel for this event we have to ignore it.\n\t * (But this should never happen.)\n\t */\n\n#ifdef TK_MAC_DEBUG_EVENTS\n\tTkMacOSXDbgMsg(\"Event received with no Tk window.\");\n#endif\n\n\treturn theEvent;\n    }\n    tkwin = (Tk_Window) winPtr;\n\n    /*\n     * Compute the mouse position in local (toplevel) and global (screen)\n     * coordinates.  These are Tk coordinates, meaning that the local origin is\n     * at the top left corner of the containing toplevel and the global origin\n     * is at top left corner of the primary screen.\n     */\n\n    global = [NSEvent mouseLocation];\n    local = [eventWindow tkConvertPointFromScreen: global];\n    global.x = floor(global.x);\n    global.y = floor(TkMacOSXZeroScreenHeight() - global.y);\n    local.x = floor(local.x);\n    local.y = floor(eventWindow.frame.size.height - local.y);\n    if (Tk_IsEmbedded(winPtr)) {\n\tTkWindow *contPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\tif (Tk_IsTopLevel(contPtr)) {\n\t    local.x -= contPtr->wmInfoPtr->xInParent;\n\t    local.y -= contPtr->wmInfoPtr->yInParent;\n\t} else {\n\t    MacDrawable *topMacWin = TkMacOSXGetHostToplevel(winPtr);\n\t    if (topMacWin) {\n\t\tTkWindow* topPtr = topMacWin->winPtr;\n\t\tlocal.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);\n\t\tlocal.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);\n\t    }\n\t}\n    }\n    else {\n\tif (winPtr && winPtr->wmInfoPtr) {\n\t    local.x -= winPtr->wmInfoPtr->xInParent;\n\t    local.y -= winPtr->wmInfoPtr->yInParent;\n\t} else {\n\t    return theEvent;\n\t}\n    }\n\n    /*\n     * Use the toplevel coordinates to decide which Tk window should receive\n     * this event.  Also convert the toplevel coordinates into the coordinate\n     * system of that window.  These converted coordinates are needed for\n     * XEvents that we generate, namely ScrollWheel events and Motion events\n     * when the mouse is outside of the focused toplevel.\n     */\n\n    if ([NSApp tkDragTarget]) {\n\tTk_Window dragTarget = (Tk_Window) [NSApp tkDragTarget];\n\tTk_Window dragWidget = NULL;\n\tint x, y;\n\tTk_GetRootCoords(dragTarget, &x, &y);\n\twin_x = global.x - x;\n\twin_y = global.y - y;\n\tif (firstDrag) {\n\t    dragWidget = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &x, &y);\n\t    if (dragWidget) {\n\t\t[NSApp setTkDragTarget: (TkWindow *) dragWidget];\n\t    }\n\t}\n\ttarget = (Tk_Window) [NSApp tkDragTarget];\n    } else {\n\ttarget = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);\n    }\n\n\n    grabWinPtr = winPtr->dispPtr->grabWinPtr;\n\n    /*\n     * Ignore the event if a local grab is in effect and the Tk window is\n     * not in the grabber's subtree.\n     */\n\n    if (grabWinPtr && /* There is a grab in effect ... */\n\t!winPtr->dispPtr->grabFlags && /* and it is a local grab ... */\n\tgrabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */\n\tTk_Window w;\n\tif (!target) {\n\t    return theEvent;\n\t}\n\tfor (w = target; !Tk_IsTopLevel(w); w = Tk_Parent(w)) {\n\t    if (w == (Tk_Window)grabWinPtr) {\n\t\tbreak;\n\t    }\n\t}\n\tif (w != (Tk_Window)grabWinPtr) {\n\t    return theEvent;\n\t}\n    }\n\n    /*\n     * Ignore the event if a global grab is in effect and the Tk window is\n     * not in the grabber's subtree.\n     */\n\n    if (grabWinPtr && /* There is a grab in effect ... */\n\twinPtr->dispPtr->grabFlags && /* and it is a global grab ... */\n\tgrabWinPtr->mainPtr == winPtr->mainPtr) { /* in the same application. */\n\tTk_Window w;\n\tif (!target) {\n\t    return theEvent;\n\t}\n\tfor (w = target; !Tk_IsTopLevel(w); w = Tk_Parent(w)) {\n\t    if (w == (Tk_Window)grabWinPtr) {\n\t\tbreak;\n\t    }\n\t}\n\tif (w != (Tk_Window)grabWinPtr) {\n\t    /* Force the focus back to the grab window. */\n\t    TkpChangeFocus(grabWinPtr, 1);\n\t}\n    }\n\n    /*\n     *  Translate the current button state into Tk's format.\n     */\n\n    unsigned int state = buttonState;\n    NSUInteger modifiers = [theEvent modifierFlags];\n    if (modifiers & NSAlphaShiftKeyMask) {\n\tstate |= LockMask;\n    }\n    if (modifiers & NSShiftKeyMask) {\n\tstate |= ShiftMask;\n    }\n    if (modifiers & NSControlKeyMask) {\n\tstate |= ControlMask;\n    }\n    if (modifiers & NSCommandKeyMask) {\n\tstate |= Mod1Mask;\t\t/* command key */\n    }\n    if (modifiers & NSAlternateKeyMask) {\n\tstate |= Mod2Mask;\t\t/* option key */\n    }\n    if (modifiers & NSNumericPadKeyMask) {\n\tstate |= Mod3Mask;\n    }\n    if (modifiers & NSFunctionKeyMask) {\n\tstate |= Mod4Mask;\n    }\n    [NSApp setTkButtonState:state];\n\n    /*\n     * Send XEvents.  We do this here for Motion events outside of the focused\n     * toplevel and for MouseWheel events.  In other cases the XEvents will be\n     * sent when we call Tk_UpdatePointer.\n     */\n\n    if (eventType != NSScrollWheel) {\n\tif ([NSApp tkDragTarget]) {\n\n\t    /*\n\t     * When dragging the mouse into the resize area Apple shows the\n\t     * left button to be up, which confuses Tk_UpdatePointer.  So\n\t     * we make sure that the button state appears the way that Tk\n\t     * expects.\n\t     */\n\n\t    state |= Tk_GetButtonMask(Button1);\n\t}\n\tif (eventType == NSMouseEntered) {\n\t    Tk_Window new_win = Tk_CoordsToWindow(global.x, global.y,\n\t\t (Tk_Window) [NSApp tkPointerWindow]);\n\t    Tk_UpdatePointer(new_win, global.x, global.y, state);\n\t} else if (eventType == NSMouseExited) {\n\t    if ([NSApp tkDragTarget]) {\n\t\tTk_UpdatePointer((Tk_Window) [NSApp tkDragTarget],\n\t\t\t\t global.x, global.y, state);\n\t    } else {\n\t    Tk_UpdatePointer(NULL, global.x, global.y, state);\n\t    }\n\t} else if (eventType == NSMouseMoved ||\n\t\t   eventType == NSLeftMouseDragged) {\n\t    if ([NSApp tkPointerWindow]) {\n\t\tTk_UpdatePointer(target, global.x, global.y, state);\n\t    } else {\n\t\tXEvent xEvent = {0};\n\n\t\txEvent.type = MotionNotify;\n\t\txEvent.xany.send_event = false;\n\t\txEvent.xany.display = Tk_Display(target);\n\t\txEvent.xany.window = Tk_WindowId(target);\n\t\txEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n\t\txEvent.xmotion.x = win_x;\n\t\txEvent.xmotion.y = win_y;\n\t\txEvent.xmotion.x_root = global.x;\n\t\txEvent.xmotion.y_root = global.y;\n\t\txEvent.xmotion.state = state;\n\t\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\n\t\t/*\n\t\t * Tk_UpdatePointer must not be called in this case.  Doing so\n\t\t * will break scrollbars; dragging will stop when the mouse\n\t\t * leaves the window.\n\t\t */\n\n\t    }\n\t} else {\n\t    Tk_UpdatePointer(target, global.x, global.y, state);\n\t}\n    } else {\n\tstatic unsigned long scrollCounter = 0;\n\tunsigned delta;\n\tCGFloat Delta;\n\tBool deltaIsPrecise = [theEvent hasPreciseScrollingDeltas];\n\tXEvent xEvent = {0};\n\txEvent.xbutton.x = win_x;\n\txEvent.xbutton.y = win_y;\n\txEvent.xbutton.x_root = global.x;\n\txEvent.xbutton.y_root = global.y;\n\txEvent.xany.send_event = false;\n\txEvent.xany.display = Tk_Display(target);\n\txEvent.xany.window = Tk_WindowId(target);\n\tif (deltaIsPrecise) {\n\t    unsigned deltaX = (unsigned)(int)[theEvent scrollingDeltaX];\n\t    unsigned deltaY = (unsigned)(int)[theEvent scrollingDeltaY];\n\t    delta = (deltaX << 16) | (deltaY & 0xffff);\n\t    if (delta != 0) {\n\t\txEvent.type = TouchpadScroll;\n\t\txEvent.xbutton.state = state;\n\t\txEvent.xkey.keycode = delta;\n\t\txEvent.xany.serial = scrollCounter++;\n\t\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\t    }\n\t} else {\n\t    /*\n\t     * A low precision scroll is 120 or -120 wheel units per click.\n\t     * Each click generates one event.\n\t     */\n\t    Delta = [theEvent scrollingDeltaY];\n\t    if (Delta != 0.0) {\n\t\txEvent.type = MouseWheelEvent;\n\t\txEvent.xbutton.state = state;\n\t\txEvent.xkey.keycode = Delta > 0.0 ? 120 : -120;\n\t\txEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n\t\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\t    }\n\t    Delta = [theEvent scrollingDeltaX];\n\t    if (Delta != 0.0) {\n\t\txEvent.type = MouseWheelEvent;\n\t\txEvent.xbutton.state = state | ShiftMask;\n\t\txEvent.xkey.keycode = Delta > 0 ? 120 : -120;\n\t\txEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n\t\tTk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);\n\t    }\n\t}\n    }\n\n    /*\n     * If button events are being captured, and the target is not in the\n     * subtree below the capturing window, then the NSEvent should not be sent\n     * up the responder chain.  This avoids, for example, beeps when clicking\n     * the mouse button outside of a posted combobox.  See ticket [eb26d4ec8e].\n     */\n\n    capture = TkpGetCapture();\n    if (capture && eventType == NSLeftMouseDown) {\n\tTk_Window w;\n\tfor (w = target; w != NULL;  w = Tk_Parent(w)) {\n\t    if (w == capture) {\n\t\tbreak;\n\t    }\n\t}\n\tif (w != capture) {\n\t    return nil;\n\t}\n    }\n    return theEvent;\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XQueryPointer --\n *\n *\tCheck the current state of the mouse. This is not a complete\n *\timplementation of this function. It only computes the root coordinates\n *\tand the current mask.\n *\n * Results:\n *\tSets root_x_return, root_y_return, and mask_return. Returns true on\n *\tsuccess.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nBool\nXQueryPointer(\n    TCL_UNUSED(Display *),\n    Window w,\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window *),\n    int *root_x_return,\n    int *root_y_return,\n    int *win_x_return,\n    int *win_y_return,\n    unsigned int *mask_return)\n{\n    int getGlobal = (root_x_return && root_y_return);\n    int getLocal = (win_x_return && win_y_return && w != None);\n\n    if (getGlobal || getLocal) {\n\tNSPoint global = [NSEvent mouseLocation];\n\n\tif (getLocal) {\n\t    MacDrawable *macWin = (MacDrawable *)w;\n\t    NSWindow *win = TkMacOSXGetNSWindowForDrawable(w);\n\n\t    if (win) {\n\t\tNSPoint local;\n\n\t\tlocal = [win tkConvertPointFromScreen:global];\n\t\tlocal.y = [win frame].size.height - local.y;\n\t\tif (macWin->winPtr && macWin->winPtr->wmInfoPtr) {\n\t\t    local.x -= macWin->winPtr->wmInfoPtr->xInParent;\n\t\t    local.y -= macWin->winPtr->wmInfoPtr->yInParent;\n\t\t}\n\t\t*win_x_return = local.x;\n\t\t*win_y_return = local.y;\n\t    }\n\t}\n\tif (getGlobal) {\n\t    *root_x_return = global.x;\n\t    *root_y_return = TkMacOSXZeroScreenHeight() - global.y;\n\t}\n    }\n    if (mask_return) {\n\t*mask_return = [NSApp tkButtonState];\n    }\n    return True;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWarpPointer --\n *\n *\tMove the mouse cursor to the screen location specified by the warpX and\n *\twarpY fields of a TkDisplay.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe mouse cursor is moved.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpWarpPointer(\n    TkDisplay *dispPtr)\n{\n    CGPoint pt;\n    Window window;\n    int rootx, rooty;\n    unsigned int modifierState;\n\n    if (dispPtr->warpWindow) {\n\tint x, y;\n\tTk_GetRootCoords(dispPtr->warpWindow, &x, &y);\n\tpt.x = x + dispPtr->warpX;\n\tpt.y = y + dispPtr->warpY;\n\twindow = Tk_WindowId(dispPtr->warpWindow);\n    } else {\n\tpt.x = dispPtr->warpX;\n\tpt.y = dispPtr->warpY;\n\twindow = None;\n    }\n    CGWarpMouseCursorPosition(pt);\n\n    XQueryPointer(NULL, window, NULL, NULL, &rootx, &rooty, NULL, NULL,\n\t    &modifierState);\n    Tk_Window newPointerWin = Tk_CoordsToWindow(rootx, rooty,\n\t    dispPtr->warpMainwin);\n    Tk_UpdatePointer(newPointerWin, rootx, rooty, modifierState);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetCapture --\n *\n *\tThis function captures the mouse so that all future events will be\n *\treported to this window, even if the mouse is outside the window. If\n *\tthe specified window is NULL, then the mouse is released.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the capture flag and captures the mouse.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetCapture(\n    TkWindow *winPtr)\t\t/* Capture window, or NULL. */\n{\n    while (winPtr && !Tk_IsTopLevel(winPtr)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    captureWinPtr = (Tk_Window)winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetCapture --\n *\n * Results:\n *\tReturns the current grab window\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTkpGetCapture(void)\n{\n    return captureWinPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXNotify.c",
    "content": "/*\n * tkMacOSXNotify.c --\n *\n *\tThis file contains the implementation of a tcl event source\n *\tfor the AppKit event loop.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2015 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXConstants.h\"\n#import <objc/objc-auto.h>\n\n/* This is not used for anything at the moment. */\ntypedef struct ThreadSpecificData {\n    bool initialized;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n#define TSD_INIT() ThreadSpecificData *tsdPtr = (ThreadSpecificData *) \\\n\tTcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData))\n\nstatic void TkMacOSXNotifyExitHandler(void *clientData);\nstatic void TkMacOSXEventsSetupProc(void *clientData, int flags);\nstatic void TkMacOSXEventsCheckProc(void *clientData, int flags);\n\n#ifdef TK_MAC_DEBUG_EVENTS\nstatic const char *Tk_EventName[39] = {\n    \"\",\n    \"\",\n    \"KeyPress\",\t\t/*2*/\n    \"KeyRelease\",\t/*3*/\n    \"ButtonPress\",\t/*4*/\n    \"ButtonRelease\",\t/*5*/\n    \"MotionNotify\",\t/*6*/\n    \"EnterNotify\",\t/*7*/\n    \"LeaveNotify\",\t/*8*/\n    \"FocusIn\",\t\t/*9*/\n    \"FocusOut\",\t\t/*10*/\n    \"KeymapNotify\",\t/*11*/\n    \"Expose\",\t\t/*12*/\n    \"GraphicsExpose\",\t/*13*/\n    \"NoExpose\",\t\t/*14*/\n    \"VisibilityNotify\",\t/*15*/\n    \"CreateNotify\",\t/*16*/\n    \"DestroyNotify\",\t/*17*/\n    \"UnmapNotify\",\t/*18*/\n    \"MapNotify\",\t/*19*/\n    \"MapRequest\",\t/*20*/\n    \"ReparentNotify\",\t/*21*/\n    \"ConfigureNotify\",\t/*22*/\n    \"ConfigureRequest\",\t/*23*/\n    \"GravityNotify\",\t/*24*/\n    \"ResizeRequest\",\t/*25*/\n    \"CirculateNotify\",\t/*26*/\n    \"CirculateRequest\",\t/*27*/\n    \"PropertyNotify\",\t/*28*/\n    \"SelectionClear\",\t/*29*/\n    \"SelectionRequest\",\t/*30*/\n    \"SelectionNotify\",\t/*31*/\n    \"ColormapNotify\",\t/*32*/\n    \"ClientMessage\",\t/*33*/\n    \"MappingNotify\",\t/*34*/\n    \"VirtualEvent\",\t/*35*/\n    \"ActivateNotify\",\t/*36*/\n    \"DeactivateNotify\",\t/*37*/\n    \"MouseWheelEvent\"\t/*38*/\n};\n\nstatic Tk_RestrictAction\nInspectQueueRestrictProc(\n     void *arg,\n     XEvent *eventPtr)\n{\n    XVirtualEvent* ve = (XVirtualEvent*) eventPtr;\n    const char *name;\n    long serial = ve->serial;\n    long time = eventPtr->xkey.time;\n\n    if (eventPtr->type == VirtualEvent) {\n\tname = ve->name;\n    } else {\n\tname = Tk_EventName[eventPtr->type];\n    }\n    fprintf(stderr, \"    > %s;serial = %lu; time=%lu)\\n\",\n\t    name, serial, time);\n    return TK_DEFER_EVENT;\n}\n\n/*\n * Debugging tool which prints the current Tcl queue.\n */\n\nvoid DebugPrintQueue(void)\n{\n    void *oldArg;\n    Tk_RestrictProc *oldProc;\n\n    oldProc = Tk_RestrictEvents(InspectQueueRestrictProc, NULL, &oldArg);\n    fprintf(stderr, \"Current queue:\\n\");\n    while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT)) {};\n    Tk_RestrictEvents(oldProc, oldArg, &oldArg);\n}\n# endif\n\n#pragma mark TKApplication(TKNotify)\n\n@implementation TKApplication(TKNotify)\n/*\n * Earlier versions of Tk would override nextEventMatchingMask here, adding a\n * call to displayIfNeeded on all windows after calling super. This would cause\n * windows to be redisplayed (if necessary) each time that an event was\n * received.  This was intended to replace Apple's default autoDisplay\n * mechanism, which the earlier versions of Tk would disable.  When autoDisplay\n * is set to the default value of YES, the Apple event loop will call\n * displayIfNeeded on all windows at the beginning of each iteration of their\n * event loop.  Since Tk does not call the Apple event loop, it was thought\n * that the autoDisplay behavior needed to be replicated.\n *\n * However, as of OSX 10.14 (Mojave) the autoDisplay property became\n * deprecated.  Luckily it turns out that, even though we don't ever start the\n * Apple event loop, the Apple window manager still calls displayIfNeeded on\n * all windows on a regular basis, perhaps each time the queue is empty.  So we\n * no longer, and perhaps never did need to set autoDisplay to NO, nor call\n * displayIfNeeded on our windows.  We can just leave all of that to the window\n * manager.\n */\n\n/*\n * Since the contentView is the first responder for a Tk Window, it is\n * responsible for sending events up the responder chain.  We also check the\n * pasteboard here.\n */\n- (void) sendEvent: (NSEvent *) theEvent\n{\n\n    /*\n     * Workaround for an Apple bug.  When an accented character is selected\n     * from an NSTextInputClient popup character viewer with the mouse, Apple\n     * sends an event of type NSAppKitDefined and subtype 21. If that event is\n     * sent up the responder chain it causes Apple to print a warning to the\n     * console log and, extremely obnoxiously, also to stderr, which says\n     * \"Window move completed without beginning.\"  Apparently they are sending\n     * the \"move completed\" event without having sent the \"move began\" event of\n     * subtype 20, and then announcing their error on our stderr.  Also, of\n     * course, no movement is occurring.  The popup is not movable and is just\n     * being closed.  The bug has been reported to Apple.  If they ever fix it,\n     * this block should be removed.\n     */\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500\n    if ([theEvent type] == NSAppKitDefined) {\n\tstatic Bool aWindowIsMoving = NO;\n\tswitch([theEvent subtype]) {\n\tcase 20:\n\t    aWindowIsMoving = YES;\n\t    break;\n\tcase 21:\n\t    if (aWindowIsMoving) {\n\t\taWindowIsMoving = NO;\n\t\tbreak;\n\t    } else {\n\t\t// printf(\"Bug!!!!\\n\");\n\t\treturn;\n\t    }\n\tdefault:\n\t    break;\n\t}\n    }\n#endif\n\n    [super sendEvent:theEvent];\n    [NSApp tkCheckPasteboard];\n\n#ifdef TK_MAC_DEBUG_EVENTS\n    fprintf(stderr, \"Sending event of type %d\\n\", (int)[theEvent type]);\n    DebugPrintQueue();\n#endif\n\n}\n\n- (void) _runBackgroundLoop\n{\n    while(Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)){\n    }\n}\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetRunLoopMode --\n *\n * Results:\n *\tRunLoop mode that should be passed to -nextEventMatchingMask:\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSString *\nGetRunLoopMode(NSModalSession modalSession)\n{\n    NSString *runLoopMode = nil;\n\n    if (modalSession) {\n\trunLoopMode = NSModalPanelRunLoopMode;\n    }\n    if (!runLoopMode) {\n\trunLoopMode = [[NSRunLoop currentRunLoop] currentMode];\n    }\n    if (!runLoopMode) {\n\trunLoopMode = NSDefaultRunLoopMode;\n    }\n    return runLoopMode;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MacOSXSetupTkNotifier --\n *\n *\tThis procedure is called during Tk initialization to create the event\n *\tsource for TkAqua events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new event source is created.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MacOSXSetupTkNotifier(void)\n{\n    TSD_INIT();\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\n\t/*\n\t * Install TkAqua event source in main event loop thread.\n\t */\n\n\tif (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {\n\t    if (![NSThread isMainThread]) {\n\t\t/*\n\t\t * Panic if main runloop is not on the main application thread.\n\t\t */\n\n\t\tTcl_Panic(\"Tk_MacOSXSetupTkNotifier: %s\",\n\t\t    \"first [load] of TkAqua has to occur in the main thread!\");\n\t    }\n\t    Tcl_CreateEventSource(TkMacOSXEventsSetupProc,\n\t\t    TkMacOSXEventsCheckProc, NULL);\n\t    TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);\n\t    Tcl_MacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);\n\t    Tcl_MacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXNotifyExitHandler --\n *\n *\tThis function is called during finalization to clean up the\n *\tTkMacOSXNotify module.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkMacOSXNotifyExitHandler(\n    TCL_UNUSED(void *))\t/* Not used. */\n{\n    TSD_INIT();\n\n    Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,\n\t    TkMacOSXEventsCheckProc, NULL);\n    tsdPtr->initialized = false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXEventsSetupProc --\n *\n *\tThis procedure implements the setup part of the MacOSX event source. It\n *\tis invoked by Tcl_DoOneEvent before calling TkMacOSXEventsCheckProc to\n *\tprocess all queued NSEvents.  In our case, all we need to do is to set\n *\tthe Tcl MaxBlockTime to 0 before starting the loop to process all\n *\tqueued NSEvents.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\n *\tIf NSEvents are queued, or if there is any drawing that needs to be\n *      done, then the maximum block time will be set to 0 to ensure that\n *      Tcl_WaitForEvent returns immediately.\n *\n *----------------------------------------------------------------------\n */\n\n#define TICK 200\nstatic Tcl_TimerToken ticker = NULL;\n\nstatic void\nHeartbeat(\n    TCL_UNUSED(void *))\n{\n\n    if (ticker) {\n\tticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);\n    }\n}\n\nstatic const Tcl_Time zeroBlockTime = { 0, 0 };\n\nstatic void\nTkMacOSXEventsSetupProc(\n    TCL_UNUSED(void *),\n    int flags)\n{\n    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];\n\n    /*\n     * runloopMode will be nil if we are in a Tcl event loop.\n     */\n\n    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {\n\n\t[NSApp _resetAutoreleasePool];\n\n\t/*\n\t * After calling this setup proc, Tcl_DoOneEvent will call\n\t * Tcl_WaitForEvent.  Then it will call check proc to collect the\n\t * events and translate them into XEvents.\n\t *\n\t * If we have any events waiting or if there is any drawing to be done\n\t * we want Tcl_WaitForEvent to return immediately.  So we set the block\n\t * time to 0 and stop the heartbeat.\n\t */\n\n\tNSEvent *currentEvent =\n\t\t[NSApp nextEventMatchingMask:NSAnyEventMask\n\t\t\tuntilDate:[NSDate distantPast]\n\t\t\tinMode:GetRunLoopMode(TkMacOSXGetModalSession())\n\t\t\tdequeue:NO];\n\tif ((currentEvent)) {\n\t    Tcl_SetMaxBlockTime(&zeroBlockTime);\n\t    Tcl_DeleteTimerHandler(ticker);\n\t    ticker = NULL;\n\t} else if (ticker == NULL) {\n\n\t    /*\n\t     * When the user is not generating events we schedule a \"heartbeat\"\n\t     * TimerHandler to fire every 200 milliseconds.  The handler does\n\t     * nothing, but when its timer fires it causes Tcl_WaitForEvent to\n\t     * return.  This helps avoid hangs when calling vwait during the\n\t     * non-regression tests.\n\t     */\n\n\t    ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXEventsCheckProc --\n *\n *\tThis procedure loops through all NSEvents waiting in the TKApplication\n *      event queue, generating X events from them.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNSevents are used to generate X events, which are added to the Tcl\n *      event queue.\n *\n *----------------------------------------------------------------------\n */\nstatic void\nTkMacOSXEventsCheckProc(\n    TCL_UNUSED(void *),\n    int flags)\n{\n    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];\n\n    /*\n     * runloopMode will be nil if we are in a Tcl event loop.\n     */\n\n    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {\n\tNSEvent *currentEvent = nil;\n\tNSEvent *testEvent = nil;\n\tNSModalSession modalSession;\n\n\t/*\n\t * It is possible for the SetupProc to be called before this function\n\t * returns.  This happens, for example, when we process an event which\n\t * opens a modal window.  To prevent premature release of our\n\t * application-wide autorelease pool by a nested call to the SetupProc,\n\t * we must lock it here.\n\t */\n\n\t[NSApp _lockAutoreleasePool];\n\tdo {\n\t    modalSession = TkMacOSXGetModalSession();\n\t    testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask\n\t\t    untilDate:[NSDate distantPast]\n\t\t    inMode:GetRunLoopMode(modalSession)\n\t\t    dequeue:NO];\n\n\t    /*\n\t     * We must not steal any events during LiveResize.\n\t     */\n\n\t    if (testEvent && [[testEvent window] inLiveResize]) {\n\t\tbreak;\n\t    }\n\t    currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask\n\t\t    untilDate:[NSDate distantPast]\n\t\t    inMode:GetRunLoopMode(modalSession)\n\t\t    dequeue:YES];\n\t    if (currentEvent) {\n\n\t\t/*\n\t\t * Generate Xevents.\n\t\t */\n\n\t\tNSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];\n\t\tif (processedEvent) {\n\n#ifdef TK_MAC_DEBUG_EVENTS\n\t\t    TKLog(@\"   event: %@\", currentEvent);\n#endif\n\n\t\t    if (modalSession) {\n\t\t\t[NSApp _modalSession:modalSession sendEvent:currentEvent];\n\t\t    } else {\n\t\t\t[NSApp sendEvent:currentEvent];\n\t\t    }\n\t\t}\n\t    } else {\n\t\tbreak;\n\t    }\n\t} while (1);\n\n\t/*\n\t * Now we can unlock the pool.\n\t */\n\n\t[NSApp _unlockAutoreleasePool];\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXPort.h",
    "content": "/*\n * tkMacOSXPort.h --\n *\n *\tThis file is included by all of the Tk C files.  It contains\n *\tinformation that may be configuration-dependent, such as\n *\t#includes for system include files and a few other things.\n *\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACPORT\n#define _TKMACPORT\n\n#include <stdio.h>\n#include <pwd.h>\n#include <assert.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <ctype.h>\n#include <math.h>\n#include <string.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <sys/file.h>\n#ifdef HAVE_SYS_SELECT_H\n#   include <sys/select.h>\n#endif\n#include <sys/stat.h>\n#ifndef _TCL\n#   include <tcl.h>\n#endif\n#ifdef HAVE_SYS_TIME_H\n#\tinclude <sys/time.h>\n#endif\n#include <time.h>\n#include <inttypes.h>\n#include <unistd.h>\n#if defined(__GNUC__) && !defined(__cplusplus)\n#   pragma GCC diagnostic ignored \"-Wc++-compat\"\n#endif\n\n/*\n * The following macro defines the type of the mask arguments to\n * select:\n */\n\n#ifndef NO_FD_SET\n#   define SELECT_MASK fd_set\n#else\n#   ifndef _AIX\n\ttypedef long fd_mask;\n#   endif\n#   if defined(_IBMR2)\n#\tdefine SELECT_MASK void\n#   else\n#\tdefine SELECT_MASK int\n#   endif\n#endif\n\n/*\n * Used to tag functions that are only to be visible within the module being\n * built and not outside it (where this is supported by the linker).\n */\n\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#\tdefine MODULE_SCOPE extern \"C\"\n#   else\n#\tdefine MODULE_SCOPE extern\n#   endif\n#endif\n\n/*\n * The following macro defines the number of fd_masks in an fd_set:\n */\n\n#ifndef FD_SETSIZE\n#   ifdef OPEN_MAX\n#\tdefine FD_SETSIZE OPEN_MAX\n#   else\n#\tdefine FD_SETSIZE 256\n#   endif\n#endif\n#if !defined(howmany)\n#   define howmany(x, y) (((x)+((y)-1))/(y))\n#endif\n#ifndef NFDBITS\n#   define NFDBITS NBBY*sizeof(fd_mask)\n#endif\n#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS)\n\n/*\n * Define \"NBBY\" (number of bits per byte) if it's not already defined.\n */\n\n#ifndef NBBY\n#   define NBBY 8\n#endif\n\n/*\n * The following define causes Tk to use its internal keysym hash table\n */\n\n#define REDO_KEYSYM_LOOKUP\n\n/*\n * The following functions are not used on the Mac, so we stub them out.\n */\n\n#define TkpCmapStressed(tkwin,colormap) (false)\n#define TkpFreeColor(tkColPtr)\n#define TkSetPixmapColormap(p,c) {}\n#define TkpSync(display)\n\n/*\n * This macro stores a representation of the window handle in a string.\n */\n\n#define TkpPrintWindowId(buf,w) \\\n\tsnprintf((buf), TCL_INTEGER_SPACE, \"0x%lx\", (unsigned long) (w))\n\n/*\n * Turn off Tk double-buffering as Aqua windows are already double-buffered.\n */\n\n#define TK_NO_DOUBLE_BUFFERING 1\n#define TK_HAS_DYNAMIC_COLORS 1\n#define TK_DYNAMIC_COLORMAP 0x0fffffff\n\n/*\n * Inform tkImgPhInstance.c that we implement TkpPutRGBAImage to render RGBA\n * images directly into a window.\n */\n\n#define TK_CAN_RENDER_RGBA\n\nMODULE_SCOPE int TkpPutRGBAImage(\n\t\t     Display* display, Drawable drawable, GC gc,XImage* image,\n\t\t     int src_x, int src_y, int dest_x, int dest_y,\n\t\t     unsigned int width, unsigned int height);\n\n/*\n * Inform tkCanvas.c that our XGetImage returns a 32pp pixmap packed as 0xAABBGGRR\n */\n\n#define TK_XGETIMAGE_USES_ABGR32\n\n/*\n * Used by xcolor.c\n */\n\nMODULE_SCOPE unsigned long TkMacOSXRGBPixel(unsigned long red, unsigned long green,\n\t\t\t\t\t    unsigned long blue);\n#define TkpGetPixel(p) (TkMacOSXRGBPixel(p->red >> 8, p->green >> 8, p->blue >> 8))\n\n/*\n * Used by tkAppInit\n */\n\n#define USE_CUSTOM_EXIT_PROC\nEXTERN int TkpWantsExitProc(void);\nEXTERN TCL_NORETURN void TkpExitProc(void *);\n\n#endif /* _TKMACPORT */\n"
  },
  {
    "path": "macosx/tkMacOSXPrint.c",
    "content": "/*\n * tkMacOSXPrint.c --\n *\n *      This module implements native printing dialogs for macOS.\n *\n * Copyright © 2006 Apple Inc.\n * Copyright © 2011-2021 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include <tcl.h>\n#include <tk.h>\n#include <tkInt.h>\n#include <Cocoa/Cocoa.h>\n#include <CoreFoundation/CoreFoundation.h>\n#include <CoreServices/CoreServices.h>\n#include <ApplicationServices/ApplicationServices.h>\n#include <tkMacOSXInt.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include \"tkMacOSXImage.h\"\n#include \"tkMacOSXPrivate.h\"\n\nNSString * fileName = nil;\nCFStringRef urlFile = NULL;\n\n/*Forward declaration of functions.*/\nstatic Tcl_ObjCmdProc2 StartPrint;\nstatic OSStatus\tFinishPrint(NSString *file, int buttonValue);\nstatic Tcl_ObjCmdProc2 MakePDF;\nint\t\t\tMacPrint_Init(Tcl_Interp * interp);\n\f\n/* Delegate class for print dialogs. */\n@interface PrintDelegate: NSObject\n    - (id) init;\n    - (void) printPanelDidEnd: (NSPrintPanel *) printPanel\n\t\t   returnCode: (int) returnCode\n\t\t  contextInfo: (void *) contextInfo;\n@end\n\n@implementation PrintDelegate\n- (id) init {\n    self = [super init];\n    return self;\n}\n\n- (void) printPanelDidEnd: (NSPrintPanel *) printPanel\n\t       returnCode: (int) returnCode\n\t      contextInfo: (void *) contextInfo {\n    (void) printPanel;\n    (void) contextInfo;\n\n    /*\n     * Pass returnCode to FinishPrint function to determine how to\n     * handle.\n     */\n\n    FinishPrint(fileName, returnCode);\n}\n@end\n\f\n/*\n *----------------------------------------------------------------------\n *\n * StartPrint --\n *\n *\tLaunch native print dialog.\n *\n * Results:\n *\tConfigures values and starts print process.\n *\n *----------------------------------------------------------------------\n */\n\nint\nStartPrint(\n    TCL_UNUSED(void *),\n    Tcl_Interp * interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    NSPrintInfo * printInfo = [NSPrintInfo sharedPrintInfo];\n    NSPrintPanel * printPanel = [NSPrintPanel printPanel];\n    int accepted;\n    PMPrintSession printSession;\n    PMPrintSettings printSettings;\n    OSStatus status = noErr;\n\n    /* Check for proper number of arguments. */\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"file\");\n\treturn TCL_ERROR;\n    }\n\n    fileName = [NSString stringWithUTF8String: Tcl_GetString(objv[1])];\n    urlFile = (CFStringRef) fileName;\n    CFRetain(urlFile);\n\n    /* Initialize the delegate for the callback from the page panel. */\n    PrintDelegate * printDelegate = [[PrintDelegate alloc] init];\n\n    status = PMCreateSession( & printSession);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating print session.\");\n\treturn TCL_ERROR;\n    }\n\n    status = PMCreatePrintSettings( & printSettings);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating print settings.\");\n\treturn TCL_ERROR;\n    }\n\n    status = PMSessionDefaultPrintSettings(printSession, printSettings);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating default print settings.\");\n\treturn TCL_ERROR;\n    }\n\n    printSession = (PMPrintSession)[printInfo PMPrintSession];\n    (void)(PMPageFormat)[printInfo PMPageFormat];\n    printSettings = (PMPrintSettings)[printInfo PMPrintSettings];\n\n    accepted = (int)[printPanel runModalWithPrintInfo: printInfo];\n    [printDelegate printPanelDidEnd: printPanel\n\t\t\t returnCode: accepted\n\t\t\tcontextInfo: printInfo];\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FinishPrint --\n *\n *\tHandles print process based on input from dialog.\n *\n * Results:\n *\tCompletes print process.\n *\n *----------------------------------------------------------------------\n */\n\nOSStatus\nFinishPrint(\n    NSString *file,\n    int buttonValue)\n{\n    NSPrintInfo * printInfo = [NSPrintInfo sharedPrintInfo];\n    PMPrintSession printSession;\n    PMPageFormat pageFormat;\n    PMPrintSettings printSettings;\n    OSStatus status = noErr;\n    CFStringRef mimeType = NULL;\n\n    /*\n     * If value passed here is NSCancelButton, return noErr;\n     * otherwise printing will occur regardless of value.\n     */\n    if (buttonValue == NSModalResponseCancel) {\n\treturn noErr;\n    }\n\n    status = PMCreateSession( & printSession);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating print session.\");\n\treturn status;\n    }\n\n    status = PMCreatePrintSettings( & printSettings);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating print settings.\");\n\treturn status;\n    }\n\n    status = PMSessionDefaultPrintSettings(printSession, printSettings);\n    if (status != noErr) {\n\tNSLog(@ \"Error creating default print settings.\");\n\treturn status;\n    }\n\n    printSession = (PMPrintSession)[printInfo PMPrintSession];\n    pageFormat = (PMPageFormat)[printInfo PMPageFormat];\n    printSettings = (PMPrintSettings)[printInfo PMPrintSettings];\n\n    /*Handle print operation.*/\n    if (buttonValue == NSModalResponseOK) {\n\n\tif (urlFile == NULL) {\n\t    NSLog(@ \"Could not get file to print.\");\n\t    return noErr;\n\t}\n\n\tfileName = file;\n\n\tCFURLRef printURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlFile, kCFURLPOSIXPathStyle, false);\n\n\tPMPrinter currentPrinter;\n\tPMDestinationType printDestination;\n\n\t/*Get the intended destination.*/\n\tstatus = PMSessionGetDestinationType(printSession, printSettings, & printDestination);\n\n\t/*Destination is printer. Send file to printer.*/\n\tif (status == noErr && printDestination == kPMDestinationPrinter) {\n\n\t    status = PMSessionGetCurrentPrinter(printSession, & currentPrinter);\n\t    if (status == noErr) {\n\t\tCFArrayRef mimeTypes;\n\t\tstatus = PMPrinterGetMimeTypes(currentPrinter, printSettings, & mimeTypes);\n\t\tif (status == noErr && mimeTypes != NULL) {\n\t\t    mimeType = CFSTR(\"application/pdf\");\n\t\t    if (CFArrayContainsValue(mimeTypes, CFRangeMake(0, CFArrayGetCount(mimeTypes)), mimeType)) {\n\t\t\tstatus = PMPrinterPrintWithFile(currentPrinter, printSettings, pageFormat, mimeType, printURL);\n\t\t\tCFRelease(urlFile);\n\t\t\treturn status;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t/* Destination is file. Determine how to handle. */\n\tif (status == noErr && printDestination == kPMDestinationFile) {\n\t    CFURLRef outputLocation = NULL;\n\n\t    status = PMSessionCopyDestinationLocation(printSession, printSettings, & outputLocation);\n\t    if (status == noErr) {\n\t\t/*Get the source file and target destination, convert to strings.*/\n\t\tCFStringRef sourceFile = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle);\n\t\tCFStringRef savePath = CFURLCopyFileSystemPath(outputLocation, kCFURLPOSIXPathStyle);\n\t\tNSString * sourcePath = (NSString * ) sourceFile;\n\t\tNSString * finalPath = (NSString * ) savePath;\n\t\tNSString * pathExtension = [finalPath pathExtension];\n\t\tNSFileManager * fileManager = [NSFileManager defaultManager];\n\t\tNSError * error = nil;\n\n\t/*\n\t\t * Is the target file a PDF? If so, copy print file\n\t\t * to output location.\n\t\t */\n\t\tif ([pathExtension isEqualToString: @ \"pdf\"]) {\n\n\t\t    /*Make sure no file conflict exists.*/\n\t\t    if ([fileManager fileExistsAtPath: finalPath]) {\n\t\t\t[fileManager removeItemAtPath: finalPath error: &error];\n\t\t    }\n\t\t    if ([fileManager fileExistsAtPath: sourcePath]) {\n\t\t\terror = nil;\n\t\t\t[fileManager copyItemAtPath: sourcePath toPath: finalPath error: & error];\n\t\t    }\n\t\t    return status;\n\t\t}\n\n\t\t/*\n\t\t * Is the target file PostScript? If so, run print file\n\t\t * through CUPS filter to convert back to PostScript.\n\t\t */\n\n\t      if ([pathExtension isEqualToString: @ \"ps\"]) {\n\t\t    char source[5012];\n\t\t    char target[5012];\n\t\t    [sourcePath getCString: source maxLength: (sizeof source) encoding: NSUTF8StringEncoding];\n\t\t    [finalPath getCString: target maxLength: (sizeof target) encoding: NSUTF8StringEncoding];\n\t\t    /*Make sure no file conflict exists.*/\n\t\t    if ([fileManager fileExistsAtPath: finalPath]) {\n\t\t\t[fileManager removeItemAtPath: finalPath error: &error];\n\t\t    }\n\n\t\t    /*\n\t\t     *  Fork and start new process with command string. Thanks to Peter da Silva\n\t\t     *  for assistance.\n\t\t     */\n\t\t    pid_t pid;\n\t\t    if ((pid = fork()) == -1) {\n\t\t      return -1;\n\t\t    } else if (pid == 0) {\n\t\t      /* Redirect output to file and silence debugging output.*/\n\t\t      dup2(open(target, O_RDWR | O_CREAT, 0777), 1);\n\t\t      dup2(open(\"/dev/null\", O_WRONLY), 2);\n\t\t      execl(\"/usr/sbin/cupsfilter\", \"/usr/sbin/cupsfilter\", \"-m\", \"application/postscript\", source, NULL);\n\t\t      exit(0);\n\t\t    }\n\t      return status;\n\t      }\n\t    }\n\t}\n\n\t/* Destination is preview. Open file in default application for PDF. */\n\tif ((status == noErr) && (printDestination == kPMDestinationPreview)) {\n\t    CFStringRef urlpath = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle);\n\t    NSString * path = (NSString * ) urlpath;\n\t    NSURL * url = [NSURL fileURLWithPath: path];\n\t    NSWorkspace * ws = [NSWorkspace sharedWorkspace];\n\t    [ws openURL: url];\n\t    status = noErr;\n\t    return status;\n\t}\n\n\t/*\n\t * If destination is not printer, file or preview,\n\t * we do not support it. Display alert.\n\t */\n\n\tif (((status == noErr) && (printDestination != kPMDestinationPreview)) || ((status == noErr) && (printDestination != kPMDestinationFile)) || ((status == noErr) &&  (printDestination != kPMDestinationPrinter))) {\n\n\t    NSAlert * alert = [[[NSAlert alloc] init] autorelease];\n\t    [alert addButtonWithTitle: @ \"OK\"];\n\n\t    [alert setMessageText: @ \"Unsupported Printing Operation\"];\n\t    [alert setInformativeText: @ \"This printing operation is not supported.\"];\n\t    [alert setAlertStyle: NSAlertStyleInformational];\n\t    [alert runModal];\n\t    return status;\n\t}\n    }\n\n    /* Return because cancel button was clicked. */\n    if (buttonValue == NSModalResponseCancel) {\n\tPMRelease(printSession);\n\treturn status;\n    }\n\n    return status;\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * MakePDF--\n *\n *\tConverts a Tk canvas to PDF data.\n *\n * Results:\n *\tOutputs PDF file.\n *\n *----------------------------------------------------------------------\n */\n\nint MakePDF(\n    TCL_UNUSED(void *),\n    Tcl_Interp *ip,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tk_Window path;\n    Drawable d;\n    unsigned int width, height;\n    CFDataRef pdfData;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(ip, 1, objv, \"path?\");\n\treturn TCL_ERROR;\n    }\n\n    /*Get window and render to PDF.*/\n\n    path = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n    if (path == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    Tk_MakeWindowExist(path);\n    Tk_MapWindow(path);\n    d = Tk_WindowId(path);\n    width = Tk_Width(path);\n    height = Tk_Height(path);\n\n    pdfData = CreatePDFFromDrawableRect(d, 0, 0, width, height);\n\n    NSData *viewData = (NSData*)pdfData;\n    [viewData writeToFile:@\"/tmp/tk_canvas.pdf\" atomically:YES];\n    return TCL_OK;\n\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * MacPrint_Init--\n *\n *\tInitializes the printing module.\n *\n * Results:\n *\tPrinting module initialized.\n *\n *----------------------------------------------------------------------\n */\n\nint MacPrint_Init(Tcl_Interp * interp) {\n    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_print\", StartPrint, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_printcanvas\", MakePDF, NULL, NULL);\n    [pool release];\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXPrivate.h",
    "content": "/*\n * tkMacOSXPrivate.h --\n *\n *\tMacros and declarations that are purely internal & private to TkAqua.\n *\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2008-2009 Apple Inc.\n * Copyright © 2020 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * RCS: @(#) $Id$\n */\n\n#ifndef _TKMACPRIV\n#define _TKMACPRIV\n\n#if !__OBJC__\n#error Objective-C compiler required\n#endif\n\n#ifndef __clang__\n#define instancetype id\n#endif\n\n#define TextStyle MacTextStyle\n#define Cursor QDCursor\n#import <ApplicationServices/ApplicationServices.h>\n#undef Cursor\n#import <Cocoa/Cocoa.h>\n#import <QuartzCore/QuartzCore.h>\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000\n#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>\n#endif\n#ifndef NO_CARBON_H\n#import <Carbon/Carbon.h>\n#endif\n#undef TextStyle\n#import <objc/runtime.h> /* for sel_isEqual() */\n\n#ifndef _TKMACINT\n#include \"tkMacOSXInt.h\"\n#endif\n#ifndef _TKMACDEFAULT\n#include \"tkMacOSXDefault.h\"\n#endif\n\n/* Macros for Mac OS X API availability checking */\n#define TK_IF_MAC_OS_X_API(vers, symbol, ...) \\\n\ttk_if_mac_os_x_10_##vers(symbol != NULL, 1, __VA_ARGS__)\n#define TK_ELSE_MAC_OS_X(vers, ...) \\\n\ttk_else_mac_os_x_10_##vers(__VA_ARGS__)\n#define TK_IF_MAC_OS_X_API_COND(vers, symbol, cond, ...) \\\n\ttk_if_mac_os_x_10_##vers(symbol != NULL, cond, __VA_ARGS__)\n#define TK_ELSE(...) \\\n\t} else { __VA_ARGS__\n#define TK_ENDIF \\\n\t}\n/* Private macros that implement the checking macros above */\n#define tk_if_mac_os_x_yes(chk, cond, ...) \\\n\tif (cond) { __VA_ARGS__\n#define tk_else_mac_os_x_yes(...) \\\n\t} else {\n#define tk_if_mac_os_x_chk(chk, cond, ...) \\\n\tif ((chk) && (cond)) { __VA_ARGS__\n#define tk_else_mac_os_x_chk(...) \\\n\t} else { __VA_ARGS__\n#define tk_if_mac_os_x_no(chk, cond, ...) \\\n\tif (0) {\n#define tk_else_mac_os_x_no(...) \\\n\t} else { __VA_ARGS__\n\n/*\n * Macros for DEBUG_ASSERT_MESSAGE et al from Debugging.h.\n */\n\n#undef kComponentSignatureString\n#undef COMPONENT_SIGNATURE\n#define kComponentSignatureString \"TkMacOSX\"\n#define COMPONENT_SIGNATURE 'Tk  '\n\n/*\n * Macros abstracting checks only active in a debug build.\n */\n\n#ifdef TK_MAC_DEBUG\n#define TKLog(f, ...) NSLog(f, ##__VA_ARGS__)\n\n/*\n * Macro to do debug message output.\n */\n#define TkMacOSXDbgMsg(m, ...) \\\n    do { \\\n\tTKLog(@\"%s:%d: %s(): \" m, strrchr(__FILE__, '/')+1, \\\n\t\t__LINE__, __func__, ##__VA_ARGS__); \\\n    } while (0)\n\n/*\n * Macro to do debug API failure message output.\n */\n#define TkMacOSXDbgOSErr(f, err) \\\n    do { \\\n\tTkMacOSXDbgMsg(\"%s failed: %d\", #f, (int)(err)); \\\n    } while (0)\n\n/*\n * Macro to do very common check for noErr return from given API and output\n * debug message in case of failure.\n */\n#define ChkErr(f, ...) ({ \\\n\tOSStatus err_ = f(__VA_ARGS__); \\\n\tif (err_ != noErr) { \\\n\t    TkMacOSXDbgOSErr(f, err_); \\\n\t} \\\n\terr_;})\n\n#else /* TK_MAC_DEBUG */\n#define TKLog(f, ...)\n#define TkMacOSXDbgMsg(m, ...)\n#define TkMacOSXDbgOSErr(f, err)\n#define ChkErr(f, ...) ({f(__VA_ARGS__);})\n#endif /* TK_MAC_DEBUG */\n\n/*\n * Macro abstracting use of TkMacOSXGetNamedSymbol to init named symbols.\n */\n\n#define UNINITIALISED_SYMBOL\t((void*)(-1L))\n#define TkMacOSXInitNamedSymbol(module, ret, symbol, ...) \\\n    static ret (* symbol)(__VA_ARGS__) = UNINITIALISED_SYMBOL; \\\n    if (symbol == UNINITIALISED_SYMBOL) { \\\n\tsymbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), \\\n\t\tSTRINGIFY(symbol)); \\\n    }\n\n/*\n *  This is set to 1 if tests are being run. Defined in tkMacOSXInit.c.\n */\n\nextern bool testsAreRunning;\n\n/*\n *  The structure of a 32-bit XEvent keycode on macOS. It may be viewed as\n *  an unsigned int or as having either two or three bitfields.\n */\n\ntypedef struct keycode_v_t {\n    unsigned keychar: 22;    /* UCS-32 character */\n    unsigned o_s: 2;         /* State of Option and Shift keys. */\n    unsigned virt: 8;     /* 8-bit virtual keycode - identifies a key. */\n} keycode_v;\n\ntypedef struct keycode_x_t {\n    unsigned keychar: 22;     /* UCS-32 character */\n    unsigned xvirtual: 10;    /* Combines o_s and virtual. This 10-bit integer\n\t\t\t       * is used as a key for looking up the character\n\t\t\t       * produced when pressing a key with a particular\n\t\t\t       * Shift and Option modifier state. */\n} keycode_x;\n\ntypedef union MacKeycode_t {\n  unsigned int uint;\n  keycode_v v;\n  keycode_x x;\n} MacKeycode;\n\n/*\n * Macros used in tkMacOSXKeyboard.c and tkMacOSXKeyEvent.c.\n * Note that 0x7f is del and 0xF8FF is the Apple Logo character.\n */\n\n#define ON_KEYPAD(virt) ((virt >= 0x41) && (virt <= 0x5C))\n#define IS_PRINTABLE(keychar) ((keychar >= 0x20) && (keychar != 0x7f) && \\\n\t\t\t       ((keychar < 0xF700) || keychar >= 0xF8FF))\n\n/*\n * An \"index\" is 2-bit bitfield showing the state of the Option and Shift\n * keys.  It is used as an index when building the keymaps and it\n * is the value of the o_s bitfield of a keycode_v.\n */\n\n#define INDEX_SHIFT 1\n#define INDEX_OPTION 2\n#define INDEX2STATE(index) ((index & INDEX_SHIFT ? ShiftMask : 0) |\t\\\n\t\t\t    (index & INDEX_OPTION ? Mod2Mask : 0))\n#define INDEX2CARBON(index) ((index & INDEX_SHIFT ? shiftKey : 0) |\t\\\n\t\t\t     (index & INDEX_OPTION ? optionKey : 0))\n#define STATE2INDEX(state) ((state & ShiftMask ? INDEX_SHIFT : 0) |\t\\\n\t\t\t    (state & Mod2Mask ? INDEX_OPTION : 0))\n\n/*\n * Special values for the virtual bitfield.  Actual virtual keycodes are < 128.\n */\n\n#define NO_VIRTUAL 0xFF /* Not generated by a key or the NSText\"InputClient. */\n#define REPLACEMENT_VIRTUAL 0x80 /* A BMP char sent by the NSTextInputClient. */\n#define NON_BMP_VIRTUAL 0x81 /* A non-BMP char sent by the NSTextInputClient. */\n\n/*\n * A special character is used in the keycode for simulated modifier KeyPress\n * or KeyRelease XEvents.  It is near the end of the private-use range but\n * different from the UniChar 0xF8FF which Apple uses for their logo character.\n * A different special character is used for keys, like the Menu key, which do\n * not appear on Macintosh keyboards.\n */\n\n#define MOD_KEYCHAR 0xF8FE\n#define UNKNOWN_KEYCHAR 0xF8FD\n\n/*\n * Structure encapsulating current drawing environment.\n */\n\ntypedef struct TkMacOSXDrawingContext {\n    CGContextRef context;\n    NSView *view;\n    HIShapeRef clipRgn;\n} TkMacOSXDrawingContext;\n\n/*\n * Prototypes for TkMacOSXRegion.c.\n */\n\nMODULE_SCOPE HIShapeRef\tTkMacOSXGetNativeRegion(Region r);\nMODULE_SCOPE void\tTkMacOSXSetWithNativeRegion(Region r,\n\t\t\t    HIShapeRef rgn);\nMODULE_SCOPE OSStatus\tTkMacOSHIShapeDifferenceWithRect(\n\t\t\t    HIMutableShapeRef inShape, const CGRect *inRect);\nMODULE_SCOPE int\tTkMacOSXCountRectsInRegion(HIShapeRef shape);\nMODULE_SCOPE void       TkMacOSXPrintRectsInRegion(HIShapeRef shape);\n/*\n * Prototypes of TkAqua internal procs.\n */\n\nMODULE_SCOPE void *\tTkMacOSXGetNamedSymbol(const char *module,\n\t\t\t    const char *symbol);\nMODULE_SCOPE void\tTkMacOSXDisplayChanged(Display *display);\nMODULE_SCOPE CGFloat\tTkMacOSXZeroScreenHeight();\nMODULE_SCOPE CGFloat\tTkMacOSXZeroScreenTop();\nMODULE_SCOPE int\tTkMacOSXUseAntialiasedText(Tcl_Interp *interp,\n\t\t\t    int enable);\nMODULE_SCOPE int\tTkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,\n\t\t\t    int antiAlias);\nMODULE_SCOPE int\tTkMacOSXIsWindowZoomed(TkWindow *winPtr);\nMODULE_SCOPE void       TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,\n\t\t\t    CGImageRef image, unsigned long imageForeground,\n\t\t\t    unsigned long imageBackground, CGRect dstBounds);\nMODULE_SCOPE bool\tTkMacOSXSetupDrawingContext(Drawable d, GC gc,\n\t\t\t    TkMacOSXDrawingContext *dcPtr);\nMODULE_SCOPE void\tTkMacOSXRestoreDrawingContext(\n\t\t\t    TkMacOSXDrawingContext *dcPtr);\nMODULE_SCOPE void\tTkMacOSXSetColorInContext(GC gc, unsigned long pixel,\n\t\t\t    CGContextRef context, BOOL useDarkAppearance);\nMODULE_SCOPE void       TkMacOSXRedrawViewIdleTask(void *clientData);\nMODULE_SCOPE void       TkMacOSXUpdateViewIdleTask(void *clientData);\n#define TkMacOSXGetTkWindow(window) ((TkWindow *)Tk_MacOSXGetTkWindow(window))\n#define TkMacOSXGetNSWindowForDrawable(drawable) ((NSWindow *)Tk_MacOSXGetNSWindowForDrawable(drawable))\n#define TkMacOSXGetNSViewForDrawable(macWin) ((NSView *)Tk_MacOSXGetNSViewForDrawable((Drawable)(macWin)))\n#define TkMacOSXGetCGContextForDrawable(drawable) ((CGContextRef)Tk_MacOSXGetCGContextForDrawable(drawable))\nMODULE_SCOPE void\tTkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);\nMODULE_SCOPE void\tTkMacOSXInvalidateViewRegion(NSView *view,\n\t\t\t    HIShapeRef rgn);\nMODULE_SCOPE NSImage*\tTkMacOSXGetNSImageFromTkImage(Display *display,\n\t\t\t    Tk_Image image, int width, int height);\nMODULE_SCOPE NSImage*\tTkMacOSXGetNSImageFromBitmap(Display *display,\n\t\t\t    Pixmap bitmap, GC gc, int width, int height);\nMODULE_SCOPE NSColor*\tTkMacOSXGetNSColor(GC gc, unsigned long pixel);\nMODULE_SCOPE NSFont*\tTkMacOSXNSFontForFont(Tk_Font tkfont);\nMODULE_SCOPE NSDictionary* TkMacOSXNSFontAttributesForFont(Tk_Font tkfont);\nMODULE_SCOPE NSModalSession TkMacOSXGetModalSession(void);\nMODULE_SCOPE void\tTkMacOSXSelDeadWindow(TkWindow *winPtr);\nMODULE_SCOPE void\tTkMacOSXApplyWindowAttributes(TkWindow *winPtr,\n\t\t\t    NSWindow *macWindow);\nMODULE_SCOPE Tcl_ObjCmdProc2 TkMacOSXStandardAboutPanelObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 TkMacOSXIconBitmapObjCmd;\nMODULE_SCOPE Tcl_ObjCmdProc2 TkMacOSXNSImageObjCmd;\nMODULE_SCOPE void       TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,\n\t\t\t    int inset, int thickness);\nMODULE_SCOPE int\tTkMacOSXServices_Init(Tcl_Interp *interp);\nMODULE_SCOPE unsigned   TkMacOSXAddVirtual(unsigned int keycode);\nMODULE_SCOPE int\tTkMacOSXNSImage_Init(Tcl_Interp *interp);\nMODULE_SCOPE bool       TkMacOSXInDarkMode(Tk_Window tkwin);\nMODULE_SCOPE void\tTkMacOSXDrawAllViews(void *clientData);\nMODULE_SCOPE NSColor*   controlAccentColor(void);\nMODULE_SCOPE void       Ttk_MacOSXInit(void);\nMODULE_SCOPE unsigned long TkMacOSXClearPixel(void);\nMODULE_SCOPE bool\tTkSetMacColor2(unsigned long pixel, CGColorRef *color,\n\t\t\t    BOOL useDarkAppearance);\nMODULE_SCOPE CGColorRef\tTkMacOSXGetCGColorFromNSColorUsingAppearance(\n\t\t\t    NSColor *color, BOOL useDarkAppearance);\nMODULE_SCOPE NSColor*\tTkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t\t    NSColor *color, NSColorSpace *colorSpace,\n\t\t\t    BOOL useDarkAppearance);\nMODULE_SCOPE int MacSystrayInit(Tcl_Interp *);\nMODULE_SCOPE int MacPrint_Init(Tcl_Interp *);\nMODULE_SCOPE NSString*  TkMacOSXOSTypeToUTI(OSType ostype);\nMODULE_SCOPE NSImage*   TkMacOSXIconForFileType(NSString *filetype);\nMODULE_SCOPE void TkMacOSXAssignNewKeyWindow(Tcl_Interp *interp,\n\t\t\t\t\t     NSWindow *ignore);\n\n#pragma mark Private Objective-C Classes\n\n#define VISIBILITY_HIDDEN __attribute__((visibility(\"hidden\")))\n\nenum { tkMainMenu = 1, tkApplicationMenu, tkWindowsMenu, tkHelpMenu};\n\nVISIBILITY_HIDDEN\n@interface TKMenu : NSMenu {\n@private\n    void *_tkMenu;\n    NSUInteger _tkOffset, _tkItemCount, _tkSpecial;\n}\n- (void)setSpecial:(NSUInteger)special;\n- (BOOL)isSpecial:(NSUInteger)special;\n@end\n\n@interface TKMenu(TKMenuDelegate) <NSMenuDelegate>\n@end\n\nVISIBILITY_HIDDEN\n@interface TKApplication : NSApplication {\n@private\n    Tcl_Interp *_eventInterp;\n    NSMenu *_servicesMenu;\n    TKMenu *_defaultMainMenu, *_defaultApplicationMenu;\n    NSMenuItem *_demoMenuItem;\n    NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;\n    NSArray *_defaultHelpMenuItems, *_defaultFileMenuItems;\n    NSAutoreleasePool *_mainPool;\n}\n@property int poolLock;\n@property int macOSVersion;\n@property Bool tkLiveResizeEnded;\n@property Bool tkWillExit;\n\n/*\n * Persistent state variables used by processMouseEvent.\n */\n\n@property(nonatomic) TkWindow *tkPointerWindow;\n@property(nonatomic) TkWindow *tkEventTarget;\n@property(nonatomic) TkWindow *tkDragTarget;\n@property unsigned int tkButtonState;\n\n@end\n@interface TKApplication(TKInit)\n- (NSString *)tkFrameworkImagePath:(NSString*)image;\n- (void)_resetAutoreleasePool;\n- (void)_lockAutoreleasePool;\n- (void)_unlockAutoreleasePool;\n@end\n@interface TKApplication(TKColor)\n- (void) performAsCurrentDrawingAppearance:(void (^)(void))block\n\t\t       usingDarkAppearance:(BOOL)useDarkAppearance;\n@end\n@interface TKApplication(TKKeyboard)\n- (void) keyboardChanged: (NSNotification *) notification;\n@end\n@interface TKApplication(TKWindowEvent) <NSApplicationDelegate>\n- (void) _setupWindowNotifications;\n@end\n@interface TKApplication(TKDialog) <NSOpenSavePanelDelegate>\n@end\n@interface TKApplication(TKMenu)\n- (void)tkSetMainMenu:(TKMenu *)menu;\n@end\n@interface TKApplication(TKMenus)\n- (void) _setupMenus;\n@end\n@interface NSApplication(TKNotify)\n/* We need to declare this hidden method. */\n- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;\n- (void) _runBackgroundLoop;\n@end\n@interface TKApplication(TKEvent)\n- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;\n@end\n@interface TKApplication(TKMouseEvent)\n- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent;\n@end\n@interface TKApplication(TKKeyEvent)\n- (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent;\n@end\n@interface TKApplication(TKClipboard)\n- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;\n- (void)tkCheckPasteboard;\n@end\n@interface TKApplication(TKHLEvents)\n- (void) terminate: (id) sender;\n- (void) superTerminate: (id) sender;\n- (void) preferences: (id) sender;\n- (void) handleQuitApplicationEvent:   (NSAppleEventDescriptor *)event\n\t\t     withReplyEvent:   (NSAppleEventDescriptor *)replyEvent;\n- (void) handleOpenApplicationEvent:   (NSAppleEventDescriptor *)event\n\t\t     withReplyEvent:   (NSAppleEventDescriptor *)replyEvent;\n- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event\n\t\t       withReplyEvent: (NSAppleEventDescriptor *)replyEvent;\n- (void) handleShowPreferencesEvent:   (NSAppleEventDescriptor *)event\n\t\t     withReplyEvent:   (NSAppleEventDescriptor *)replyEvent;\n- (void) handleOpenDocumentsEvent:     (NSAppleEventDescriptor *)event\n\t\t   withReplyEvent:     (NSAppleEventDescriptor *)replyEvent;\n- (void) handlePrintDocumentsEvent:    (NSAppleEventDescriptor *)event\n\t\t   withReplyEvent:     (NSAppleEventDescriptor *)replyEvent;\n- (void) handleDoScriptEvent:          (NSAppleEventDescriptor *)event\n\t\t   withReplyEvent:     (NSAppleEventDescriptor *)replyEvent;\n- (void)handleURLEvent:                (NSAppleEventDescriptor*)event\n\t\t   withReplyEvent:     (NSAppleEventDescriptor*)replyEvent;\n@end\n\nVISIBILITY_HIDDEN\n/*\n * Subclass TKContentView from NSTextInputClient to enable composition and\n * input from the Character Palette.\n */\n\n@interface TKContentView : NSView <NSTextInputClient>\n{\n@private\n    NSString *privateWorkingText;\n    NSTrackingArea *trackingArea;\n}\n@property CGContextRef tkLayerBitmapContext;\n@property Bool onScreen;\n@end\n\n@interface TKContentView(TKKeyEvent)\n- (void) deleteWorkingText;\n- (void) cancelComposingText;\n@end\n\n@interface TKContentView(TKWindowEvent)\n- (void) generateExposeEvents: (NSRect) rect;\n- (void) tkToolbarButton: (id) sender;\n- (void) resetTkLayerBitmapContext;\n@end\n\n@interface TkAccessibilityElement : NSAccessibilityElement\n@property (nonatomic, strong)  TKContentView  *parentView;\n@property Tk_Window tk_win;\n@end\n\n\n@interface NSWindow(TKWm)\n- (NSPoint) tkConvertPointToScreen:(NSPoint)point;\n- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;\n@end\n\nVISIBILITY_HIDDEN\n@interface TKWindow : NSWindow\n{\n}\n@property Window tkWindow;\n@end\n\n@interface TKWindow(TKWm)\n- (void)    tkLayoutChanged;\n@end\n\n@interface TKDrawerWindow : NSWindow\n{\n    id _i1, _i2;\n}\n@property Window tkWindow;\n@end\n\n@interface TKPanel : NSPanel\n{\n}\n@property Window tkWindow;\n@end\n\n@interface TKPanel(TKWm)\n- (void)    tkLayoutChanged;\n@end\n#pragma mark NSMenu & NSMenuItem Utilities\n\n@interface NSMenu(TKUtils)\n+ (id)menuWithTitle:(NSString *)title;\n+ (id)menuWithTitle:(NSString *)title menuItems:(NSArray *)items;\n+ (id)menuWithTitle:(NSString *)title submenus:(NSArray *)submenus;\n- (NSMenuItem *)itemWithSubmenu:(NSMenu *)submenu;\n- (NSMenuItem *)itemInSupermenu;\n@end\n\n// Need undocumented appearance: argument\n@interface NSMenu(TKMenu)\n- (BOOL)popUpMenuPositioningItem:(NSMenuItem *)item\n\t\t      atLocation:(NSPoint)location\n\t\t\t  inView:(NSView *)view\n\t\t      appearance:(NSAppearance *)appearance;\n@end\n\n@interface NSMenuItem(TKUtils)\n+ (id)itemWithSubmenu:(NSMenu *)submenu;\n+ (id)itemWithTitle:(NSString *)title submenu:(NSMenu *)submenu;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action\n\ttarget:(id)target;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action\n\tkeyEquivalent:(NSString *)keyEquivalent;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action\n\ttarget:(id)target keyEquivalent:(NSString *)keyEquivalent;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action\n\tkeyEquivalent:(NSString *)keyEquivalent\n\tkeyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;\n+ (id)itemWithTitle:(NSString *)title action:(SEL)action\n\ttarget:(id)target keyEquivalent:(NSString *)keyEquivalent\n\tkeyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;\n@end\n\n@interface NSColorPanel(TKDialog)\n- (void) _setUseModalAppearance: (BOOL) flag;\n@end\n\n@interface NSFont(TKFont)\n- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters\n\tlength: (NSUInteger) length attributes: (NSDictionary *) attributes\n\tactualCoveredLength: (NSUInteger *) coveredLength;\n@end\n\n/*\n * This method of NSApplication is not declared in NSApplication.h so we\n * declare it here to be a method of the TKMenu category.\n */\n\n@interface NSApplication(TKMenu)\n- (void) setAppleMenu: (NSMenu *) menu;\n@end\n\n/*\n * These methods are exposed because they are needed to prevent zombie windows\n * on systems with a TouchBar.  The TouchBar Key-Value observer holds a\n * reference to the key window, which prevents deallocation of the key window\n * when it is closed.\n */\n\n@interface NSApplication(TkWm)\n- (id) _setKeyWindow: (NSWindow *) window;\n- (id) _setMainWindow: (NSWindow *) window;\n@end\n\n\n/*\n *---------------------------------------------------------------------------\n *\n * TKNSString --\n *\n * Tcl uses modified UTF-8 as internal encoding.  Apple's NSString class\n * does not provide a constructor which accepts a modified UTF-8 encoded\n * byte sequence as initial data.  So we add a new class which does provide\n * such a constructor.  It also has a DString property which is a DString whose\n * string pointer is a byte sequence encoding the NSString with modified UTF-8.\n *\n *---------------------------------------------------------------------------\n */\n\n@interface TKNSString:NSString {\n@private\n    Tcl_DString _ds;\n    NSString *_string;\n    const char *_UTF8String;\n}\n@property const char *UTF8String;\n@property (readonly) Tcl_DString DString;\n- (instancetype)initWithTclUtfBytes:(const void *)bytes\n\t\t\t     length:(NSUInteger)len;\n@end\n\n#endif /* _TKMACPRIV */\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXRegion.c",
    "content": "/*\n * tkMacOSXRegion.c --\n *\n *\tImplements X window calls for manipulating regions\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\nstatic void ReleaseRegion(Region r);\n\n#ifdef DEBUG\nstatic int totalRegions = 0;\nstatic int totalRegionRetainCount = 0;\n#define DebugLog(msg, ...) fprintf(stderr, (msg), ##__VA_ARGS__)\n#else\n#define DebugLog(msg, ...)\n#endif\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateRegion --\n *\n *\tImplements the equivalent of the X window function XCreateRegion. See\n *\tXwindow documentation for more details.\n *\n * Results:\n *\tReturns an allocated region handle.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nRegion\nXCreateRegion(void)\n{\n    Region region = (Region) HIShapeCreateMutable();\n    DebugLog(\"Created region: total regions = %d, total count is %d\\n\",\n\t++totalRegions, ++totalRegionRetainCount);\n    return region;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDestroyRegion --\n *\n *\tImplements the equivalent of the X window function XDestroyRegion. See\n *\tXwindow documentation for more details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDestroyRegion(\n    Region r)\n{\n    if (r) {\n\tDebugLog(\"Destroyed region: total regions = %d\\n\", --totalRegions);\n\tReleaseRegion(r);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XIntersectRegion --\n *\n *\tImplements the equivalent of the X window function XIntersectRegion.\n *\tSee Xwindow documentation for more details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXIntersectRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,\n\t   (HIMutableShapeRef) dr_return);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSubtractRegion --\n *\n *\tImplements the equivalent of the X window function XSubtractRegion.\n *\tSee X window documentation for more details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSubtractRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,\n\t   (HIMutableShapeRef) dr_return);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUnionRectWithRegion --\n *\n *\tImplements the equivalent of the X window function\n *\tXUnionRectWithRegion. See Xwindow documentation for more details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUnionRectWithRegion(\n    XRectangle* rectangle,\n    Region src_region,\n    Region dest_region_return)\n{\n    const CGRect r = CGRectMake(rectangle->x, rectangle->y,\n\t    rectangle->width, rectangle->height);\n\n    if (src_region == dest_region_return) {\n\tChkErr(HIShapeUnionWithRect,\n\t\t(HIMutableShapeRef) dest_region_return, &r);\n    } else {\n\tHIShapeRef rectRgn = HIShapeCreateWithRect(&r);\n\n\tChkErr(HIShapeUnion, rectRgn, (HIShapeRef) src_region,\n\t\t(HIMutableShapeRef) dest_region_return);\n\tCFRelease(rectRgn);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXIsEmptyRegion --\n *\n *\tReturn native region for given tk region.\n *\n * Results:\n *\t1 if empty, 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXIsEmptyRegion(\n    Region r)\n{\n    return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XRectInRegion --\n *\n *\tImplements the equivalent of the X window function XRectInRegion. See\n *\tXwindow documentation for more details.\n *\n * Results:\n *\tReturns RectanglePart or RectangleOut. Note that this is not a complete\n *\timplementation since it doesn't test for RectangleIn.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXRectInRegion(\n    Region region,\n    int x,\n    int y,\n    unsigned int width,\n    unsigned int height)\n{\n    if (TkMacOSXIsEmptyRegion(region)) {\n\treturn RectangleOut;\n    } else {\n\tconst CGRect r = CGRectMake(x, y, width, height);\n\n\treturn HIShapeIntersectsRect((HIShapeRef) region, &r) ?\n\t\tRectanglePart : RectangleOut;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XClipBox --\n *\n *\tImplements the equivalent of the X window function XClipBox. See\n *\tXwindow documentation for more details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXClipBox(\n    Region r,\n    XRectangle *rect_return)\n{\n    CGRect rect;\n\n    HIShapeGetBounds((HIShapeRef) r, &rect);\n    rect_return->x = rect.origin.x;\n    rect_return->y = rect.origin.y;\n    rect_return->width = rect.size.width;\n    rect_return->height = rect.size.height;\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpBuildRegionFromAlphaData --\n *\n *\tSet up a rectangle of the given region based on the supplied alpha\n *\tdata.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe region is updated, with extra pixels added to it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpBuildRegionFromAlphaData(\n    Region region,\t\t\t/* Region to update. */\n    unsigned int x,\t\t\t/* Where in region to update. */\n    unsigned int y,\t\t\t/* Where in region to update. */\n    unsigned int width,\t\t\t/* Size of rectangle to update. */\n    unsigned int height,\t\t/* Size of rectangle to update. */\n    unsigned char *dataPtr,\t\t/* Data to read from. */\n    unsigned int pixelStride,\t\t/* num bytes from one piece of alpha\n\t\t\t\t\t * data to the next in the line. */\n    unsigned int lineStride)\t\t/* num bytes from one line of alpha\n\t\t\t\t\t * data to the next line. */\n{\n    unsigned char *lineDataPtr;\n    unsigned int x1, y1, end;\n    XRectangle rect;\n\n    for (y1 = 0; y1 < height; y1++) {\n\tlineDataPtr = dataPtr;\n\tfor (x1 = 0; x1 < width; x1 = end) {\n\t    /*\n\t     * Search for first non-transparent pixel.\n\t     */\n\n\t    while ((x1 < width) && !*lineDataPtr) {\n\t\tx1++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    end = x1;\n\n\t    /*\n\t     * Search for first transparent pixel.\n\t     */\n\n\t    while ((end < width) && *lineDataPtr) {\n\t\tend++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    if (end > x1) {\n\t\trect.x = x + x1;\n\t\trect.y = y + y1;\n\t\trect.width = end - x1;\n\t\trect.height = 1;\n\t\tXUnionRectWithRegion(&rect, region, region);\n\t    }\n\t}\n\tdataPtr += lineStride;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReleaseRegion --\n *\n *\tDecreases reference count of region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay free memory.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nReleaseRegion(\n    Region r)\n{\n    CFRelease(r);\n    DebugLog(\"Released region: total count is %d\\n\", --totalRegionRetainCount);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSetEmptyRegion --\n *\n *\tSet region to emtpy.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXSetEmptyRegion(\n    Region r)\n{\n    ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNativeRegion --\n *\n *\tReturn native region for given tk region.\n *\n * Results:\n *\tNative region, CFRelease when done.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHIShapeRef\nTkMacOSXGetNativeRegion(\n    Region r)\n{\n    return (HIShapeRef) CFRetain(r);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSetWithNativeRegion --\n *\n *\tSet region to the native region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXSetWithNativeRegion(\n    Region r,\n    HIShapeRef rgn)\n{\n    ChkErr(HIShapeSetWithShape, (HIMutableShapeRef) r, rgn);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XOffsetRegion --\n *\n *\tOffsets region by given distances.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXOffsetRegion(\n    Region r,\n    int dx,\n    int dy)\n{\n    ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCopyRegion --\n *\n *  Makes the destination region a copy of the source region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCopyRegion(\n    Region dst,\n    Region src)\n{\n    ChkErr(HIShapeSetWithShape, (HIMutableShapeRef)dst, (HIShapeRef)src);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSHIShapeDifferenceWithRect --\n *\n *\tWrapper functions for missing/buggy HIShape API\n *\n *----------------------------------------------------------------------\n */\n\nOSStatus\nTkMacOSHIShapeDifferenceWithRect(\n    HIMutableShapeRef inShape,\n    const CGRect *inRect)\n{\n    OSStatus result;\n    HIShapeRef rgn = HIShapeCreateWithRect(inRect);\n\n    result = HIShapeDifference(inShape, rgn, inShape);\n    CFRelease(rgn);\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XEqualRegion --\n *\n *\tAlthough the undocumented function\n *\n *\t    Boolean __attribute__((overloadable))\n *\t    __HIShapeEqual(void const *inShape1, void const *inShape2)\n *\n *\tis probably more optimal than the approach used here,\n *\tit is \"non-external\" and so not easily usable by Tk Aqua.\n *\n *----------------------------------------------------------------------\n */\nBool\nXEqualRegion(\n    Region r1,\n    Region r2)\n{\n    HIShapeRef hsa = (HIShapeRef)r1, hsb = (HIShapeRef)r2;\n    if (hsa == hsb) {\n\treturn True;\n    }\n    CGRect ba, bb;\n    HIShapeGetBounds(hsa, &ba);\n    HIShapeGetBounds(hsb, &bb);\n    if (!CGRectEqualToRect(ba, bb)) {\n\treturn False;\n    }\n    HIShapeRef hsx = HIShapeCreateXor(hsa, hsb);\n    Bool result = HIShapeIsEmpty(hsx);\n    CFRelease(hsx);\n    return result;\n}\n\nint\nXUnionRegion(\n    Region srca,\n    Region srcb,\n    Region dr_return)\n{\n    ChkErr(HIShapeUnion, (HIShapeRef)srca, (HIShapeRef)srcb,\n\t    (HIMutableShapeRef)dr_return);\n    return 1;\n}\n\nint\nXXorRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    ChkErr(HIShapeXor, (HIShapeRef)sra, (HIShapeRef)srb,\n\t    (HIMutableShapeRef)dr_return);\n    return 0;\n}\n\nBool\nXPointInRegion(\n    Region r,\n    int x,\n    int y)\n{\n    CGPoint p = CGPointMake(x, y);\n    return HIShapeContainsPoint((HIShapeRef)r, &p);\n}\n\nstatic OSStatus\nrectCounter(\n    TCL_UNUSED(int),\n    TCL_UNUSED(HIShapeRef),\n    TCL_UNUSED(const CGRect *),\n    void *ref)\n{\n    int *count = (int *)ref;\n    (*count)++;\n    return noErr;\n}\n\nstatic OSStatus\nrectPrinter(\n    TCL_UNUSED(int),\n    TCL_UNUSED(HIShapeRef),\n    const CGRect *rect,\n    TCL_UNUSED(void *))\n{\n    if (rect) {\n\tfprintf(stderr, \"    %s\\n\", NSStringFromRect(NSRectFromCGRect(*rect)).UTF8String);\n    }\n    return noErr;\n}\n\nint\nTkMacOSXCountRectsInRegion(\n    HIShapeRef shape)\n{\n    int rect_count = 0;\n    if (!HIShapeIsEmpty(shape)) {\n\tHIShapeEnumerate(shape,\n\t    kHIShapeParseFromBottom|kHIShapeParseFromLeft,\n\t    (HIShapeEnumerateProcPtr) rectCounter, (void *) &rect_count);\n    }\n    return rect_count;\n}\n\nvoid\nTkMacOSXPrintRectsInRegion(\n    HIShapeRef shape)\n{\n    if (!HIShapeIsEmpty(shape)) {\n\tHIShapeEnumerate( shape,\n\t    kHIShapeParseFromBottom|kHIShapeParseFromLeft,\n\t    (HIShapeEnumerateProcPtr) rectPrinter, NULL);\n    }\n}\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXScrlbr.c",
    "content": "/*\n * tkMacOSXScrollbar.c --\n *\n *\tThis file implements the Macintosh specific portion of the scrollbar\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2015 Kevin Walzer\n * Copyright © 2018-2019 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkScrollbar.h\"\n#include \"tkMacOSXPrivate.h\"\n\n/*\n * Minimum slider length, in pixels (designed to make sure that the slider is\n * always easy to grab with the mouse).\n */\n\n#define MIN_SLIDER_LENGTH\t18\n#define MIN_GAP\t\t\t4\n\n/*\n * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.\n */\n\n#ifdef __LP64__\n#define RangeToFactor(maximum)\t(((double) (INT_MAX >> 1)) / (maximum))\n#else\n#define RangeToFactor(maximum)\t(((double) (LONG_MAX >> 1)) / (maximum))\n#endif /* __LP64__ */\n\n/*\n * Apple reversed the scroll direction with the release of OSX 10.7 Lion.\n */\n\n#define SNOW_LEOPARD_STYLE\t(NSAppKitVersionNumber < 1138)\n\n/*\n * Declaration of an extended scrollbar structure with Mac specific additions.\n */\n\ntypedef struct MacScrollbar {\n    TkScrollbar information;\t/* Generic scrollbar info. */\n    GC troughGC;\t\t/* For drawing trough. */\n    GC copyGC;\t\t\t/* Used for copying from pixmap onto screen. */\n    Bool buttonDown;            /* Is the mouse button down? */\n    Bool mouseOver;             /* Is the pointer over the scrollbar. */\n    HIThemeTrackDrawInfo info;\t/* Controls how the scrollbar is drawn. */\n} MacScrollbar;\n\n/* Used to initialize a MacScrollbar's info field. */\nHIThemeTrackDrawInfo defaultInfo = {\n    .version = 0,\n    .min = 0.0,\n    .max = 100.0,\n    .attributes = kThemeTrackShowThumb,\n};\n\n/*\n * The class procedure table for the scrollbar widget. All fields except size\n * are left initialized to NULL, which should happen automatically since the\n * variable is declared at this scope.\n */\n\nconst Tk_ClassProcs tkpScrollbarProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    NULL,\t\t\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n/*\n * Information on scrollbar layout, metrics, and draw info.\n */\n\ntypedef struct ScrollbarMetrics {\n    SInt32 width, minThumbHeight;\n    int minHeight, topArrowHeight, bottomArrowHeight;\n    NSControlSize controlSize;\n} ScrollbarMetrics;\n\nstatic ScrollbarMetrics metrics = {\n    /* kThemeScrollBarMedium */\n    15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal\n};\n\n/*\n * Declarations of static functions defined later in this file:\n */\n\nstatic void\t\tScrollbarEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tScrollbarEvent(TkScrollbar *scrollPtr,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tUpdateControlValues(TkScrollbar *scrollPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateScrollbar --\n *\n *\tAllocate a new TkScrollbar structure.\n *\n * Results:\n *\tReturns a newly allocated TkScrollbar structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkScrollbar *\nTkpCreateScrollbar(\n    Tk_Window tkwin)\n{\n    MacScrollbar *scrollPtr = (MacScrollbar *)Tcl_Alloc(sizeof(MacScrollbar));\n\n    scrollPtr->troughGC = NULL;\n    scrollPtr->copyGC = NULL;\n    scrollPtr->info = defaultInfo;\n    scrollPtr->buttonDown = false;\n\n    Tk_CreateEventHandler(tkwin,\n\t    ExposureMask        |\n\t    StructureNotifyMask |\n\t    FocusChangeMask     |\n\t    ButtonPressMask     |\n\t    ButtonReleaseMask   |\n\t    EnterWindowMask     |\n\t    LeaveWindowMask     |\n\t    VisibilityChangeMask,\n\t    ScrollbarEventProc, scrollPtr);\n\n    return (TkScrollbar *) scrollPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDisplayScrollbar --\n *\n *\tThis procedure redraws the contents of a scrollbar window. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's nothing\n *\telse for the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a scrollbar on the screen.\n *\n *--------------------------------------------------------------\n */\n\n/*\n * This stand-alone drawing function is used because\n * the HIToolbox does not draw the scrollbar thumb at the expected size on\n * those systems.  The thumb is drawn too large, causing a mouse click on the\n * thumb to be interpreted as a mouse click in the trough.\n */\n\nstatic void drawMacScrollbar(\n    TkScrollbar *scrollPtr,\n    MacScrollbar *msPtr,\n    CGContextRef context)\n{\n    Drawable d = Tk_WindowId(scrollPtr->tkwin);\n    NSView *view = TkMacOSXGetNSViewForDrawable(d);\n    CGPathRef path;\n    CGPoint inner[2], outer[2], thumbOrigin;\n    CGSize thumbSize;\n    CGRect troughBounds = msPtr->info.bounds;\n    troughBounds.origin.y = [view bounds].size.height -\n\t(troughBounds.origin.y + troughBounds.size.height);\n    if (scrollPtr->vertical) {\n\tthumbOrigin.x = troughBounds.origin.x + MIN_GAP;\n\tthumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst;\n\tthumbSize.width = troughBounds.size.width - 2 * MIN_GAP + 1;\n\tthumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst;\n\tinner[0] = troughBounds.origin;\n\tinner[1] = CGPointMake(inner[0].x,\n\t\t\t       inner[0].y + troughBounds.size.height);\n\touter[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1,\n\t\t\t       inner[0].y);\n\touter[1] = CGPointMake(outer[0].x, inner[1].y);\n    } else {\n\tthumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst;\n\tthumbOrigin.y = troughBounds.origin.y + MIN_GAP;\n\tthumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst;\n\tthumbSize.height = troughBounds.size.height - 2 * MIN_GAP + 1;\n\tinner[0] = troughBounds.origin;\n\tinner[1] = CGPointMake(inner[0].x + troughBounds.size.width,\n\t\t\t       inner[0].y + 1);\n\touter[0] = CGPointMake(inner[0].x,\n\t\t\t       inner[0].y + troughBounds.size.height);\n\touter[1] = CGPointMake(inner[1].x, outer[0].y);\n    }\n    CGContextSetShouldAntialias(context, false);\n    CGContextSetGrayFillColor(context, 250.0 / 255, 1.0);\n    CGContextFillRect(context, troughBounds);\n    CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0);\n    CGContextStrokeLineSegments(context, inner, 2);\n    CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0);\n    CGContextStrokeLineSegments(context, outer, 2);\n\n    /*\n     * Do not display the thumb unless scrolling is possible, in accordance\n     * with macOS behavior.\n     *\n     * Native scrollbars and Ttk scrollbars are always 15 pixels wide, but we\n     * allow Tk scrollbars to have any width, even if it looks bad. To prevent\n     * sporadic assertion errors when drawing skinny thumbs we must make sure\n     * the radius is at most half the width.\n     */\n\n    if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {\n\tCGRect thumbBounds = {thumbOrigin, thumbSize};\n\tint width = scrollPtr->vertical ? thumbSize.width : thumbSize.height;\n\tint radius = width >= 8 ? 4 : width >> 1;\n\tpath = CGPathCreateWithRoundedRect(thumbBounds, radius, radius, NULL);\n\tCGContextBeginPath(context);\n\tCGContextAddPath(context, path);\n\tif (msPtr->info.trackInfo.scrollbar.pressState != 0) {\n\t    CGContextSetGrayFillColor(context, 133.0 / 255, 1.0);\n\t} else {\n\t    CGContextSetGrayFillColor(context, 200.0 / 255, 1.0);\n\t}\n\tCGContextSetShouldAntialias(context, true);\n\tCGContextFillPath(context);\n\tCFRelease(path);\n    }\n}\n\nvoid\nTkpDisplayScrollbar(\n    void *clientData)\t/* Information about window. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n    MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;\n    Tk_Window tkwin = scrollPtr->tkwin;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkMacOSXDrawingContext dc;\n    int borderWidth, highlightWidth;\n\n    scrollPtr->flags &= ~REDRAW_PENDING;\n\n    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    MacDrawable *macWin = (MacDrawable *)winPtr->window;\n    NSView *view = TkMacOSXGetNSViewForDrawable(macWin);\n\n    if ((view == NULL)\n\t    || !TkMacOSXSetupDrawingContext((Drawable)macWin, NULL, &dc)) {\n\treturn;\n    }\n\n    /*\n     * Transform NSView coordinates to CoreGraphics coordinates.\n     */\n\n    CGFloat viewHeight = [view bounds].size.height;\n    CGAffineTransform t = {\n\t.a = 1, .b = 0,\n\t.c = 0, .d = -1,\n\t.tx = 0, .ty = viewHeight\n    };\n\n    CGContextConcatCTM(dc.context, t);\n\n    /*\n     * Draw a 3D rectangle to provide a base for the native scrollbar.\n     */\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n    if (highlightWidth > 0) {\n\tGC fgGC, bgGC;\n\n\tbgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin);\n\tif (scrollPtr->flags & GOT_FOCUS) {\n\t    fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin);\n\t} else {\n\t    fgGC = bgGC;\n\t}\n\tTk_DrawHighlightBorder(tkwin, fgGC, bgGC, highlightWidth,\n\t\t(Pixmap) macWin);\n    }\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->borderWidthObj, &borderWidth);\n    Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,\n\t    highlightWidth, highlightWidth,\n\t    Tk_Width(tkwin) - 2 * highlightWidth,\n\t    Tk_Height(tkwin) - 2 * highlightWidth,\n\t    borderWidth, scrollPtr->relief);\n    Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,\n\t    scrollPtr->inset, scrollPtr->inset,\n\t    Tk_Width(tkwin) - 2 * scrollPtr->inset,\n\t    Tk_Height(tkwin) - 2 * scrollPtr->inset, 0, TK_RELIEF_FLAT);\n\n    /*\n     * Update values and then draw the native scrollbar over the rectangle.\n     */\n\n    UpdateControlValues(scrollPtr);\n\n    if (SNOW_LEOPARD_STYLE) {\n\tHIThemeDrawTrack(&msPtr->info, 0, dc.context,\n\t\t\t kHIThemeOrientationInverted);\n    } else {\n\n\t/*\n\t * Switch back to NSView coordinates and draw a modern scrollbar.\n\t */\n\n\tCGContextConcatCTM(dc.context, t);\n\tdrawMacScrollbar(scrollPtr, msPtr, dc.context);\n    }\n    TkMacOSXRestoreDrawingContext(&dc);\n    scrollPtr->flags &= ~REDRAW_PENDING;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeScrollbarGeometry --\n *\n *\tAfter changes in a scrollbar's size or configuration, this procedure\n *\trecomputes various geometry information used in displaying the\n *\tscrollbar.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe scrollbar will be displayed differently.\n *\n *----------------------------------------------------------------------\n */\n\nextern void\nTkpComputeScrollbarGeometry(\n    TkScrollbar *scrollPtr)\n\t\t\t\t/* Scrollbar whose geometry may have\n\t\t\t\t * changed. */\n{\n    /*\n     * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to\n     * account for some differences between macOS and X11. The Unix scrollbar\n     * has an arrow button on each end.  On macOS 10.6 (Snow Leopard) the\n     * scrollbars by default have both arrow buttons at the bottom or right.\n     * (There is a preferences setting to use the Unix layout, but we are not\n     * supporting that!)  On more recent versions of macOS there are no arrow\n     * buttons at all. The case of no arrow buttons can be handled as a special\n     * case of having both buttons at the end, but where scrollPtr->arrowLength\n     * happens to be zero.  To adjust for having both arrows at the same end we\n     * shift the scrollbar up by the arrowLength.\n     */\n\n    int fieldLength;\n    int width, borderWidth, highlightWidth;\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->widthObj, &width);\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n    scrollPtr->inset = highlightWidth + borderWidth;\n    if ([NSApp macOSVersion] == 100600) {\n\tscrollPtr->arrowLength = width;\n    } else {\n\tscrollPtr->arrowLength = 0;\n    }\n    fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)\n\t    : Tk_Width(scrollPtr->tkwin))\n\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n    if (fieldLength < 0) {\n\tfieldLength = 0;\n    }\n    scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;\n    scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;\n\n    /*\n     * Adjust the slider so that it has at least a minimal size and so there\n     * is a small gap on either end which can be used to scroll by one page.\n     */\n\n    if (scrollPtr->sliderFirst < MIN_GAP) {\n\tscrollPtr->sliderFirst = MIN_GAP;\n\tscrollPtr->sliderLast += MIN_GAP;\n    }\n    if (scrollPtr->sliderLast > fieldLength - MIN_GAP) {\n\tscrollPtr->sliderLast = fieldLength - MIN_GAP;\n\tscrollPtr->sliderFirst -= MIN_GAP;\n    }\n    if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {\n\tscrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;\n    }\n    if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {\n\tscrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;\n    }\n    scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset;\n    scrollPtr->sliderLast += scrollPtr->inset;\n\n    /*\n     * Register the desired geometry for the window. Leave enough space for the\n     * two arrows, if there are any arrows, plus a minimum-size slider, plus\n     * border around the whole window, if any. Then arrange for the window to\n     * be redisplayed.\n     */\n\n    if (scrollPtr->vertical) {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\twidth + 2 * scrollPtr->inset,\n\t\t2 * (scrollPtr->arrowLength + borderWidth\n\t\t+ scrollPtr->inset) + metrics.minThumbHeight);\n    } else {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\t2 * (scrollPtr->arrowLength + borderWidth\n\t\t+ scrollPtr->inset) + metrics.minThumbHeight,\n\t\twidth + 2 * scrollPtr->inset);\n    }\n    Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyScrollbar --\n *\n *\tFree data structures associated with the scrollbar control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees the GCs associated with the scrollbar.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyScrollbar(\n    TkScrollbar *scrollPtr)\n{\n    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;\n\n    if (macScrollPtr->troughGC != NULL) {\n\tTk_FreeGC(scrollPtr->display, macScrollPtr->troughGC);\n    }\n    if (macScrollPtr->copyGC != NULL) {\n\tTk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureScrollbar --\n *\n *\tThis procedure is called after the generic code has finished processing\n *\tconfiguration options, in order to configure platform specific options.\n *\tThere are no such option on the Mac, however.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCurrently, none.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpConfigureScrollbar(\n    TCL_UNUSED(TkScrollbar *))\n{\n    /* empty */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpScrollbarPosition --\n *\n *\tDetermine the scrollbar element corresponding to a given position.\n *\n * Results:\n *\tOne of TOP_ARROW, TOP_GAP, etc., indicating which element of the\n *\tscrollbar covers the position given by (x, y). If (x,y) is outside the\n *\tscrollbar entirely, then OUTSIDE is returned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkpScrollbarPosition(\n    TkScrollbar *scrollPtr,\n\t\t\t\t/* Scrollbar widget record. */\n    int x, int y)\t\t/* Coordinates within scrollPtr's window. */\n{\n    /*\n     * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment\n     * since it does not involve the arrow buttons.\n     */\n\n    int length, width, tmp;\n    const int inset = scrollPtr->inset;\n\n    if (scrollPtr->vertical) {\n\tlength = Tk_Height(scrollPtr->tkwin);\n\twidth = Tk_Width(scrollPtr->tkwin);\n    } else {\n\ttmp = x;\n\tx = y;\n\ty = tmp;\n\tlength = Tk_Width(scrollPtr->tkwin);\n\twidth = Tk_Height(scrollPtr->tkwin);\n    }\n\n    if (x < inset || x >= width - inset ||\n\t    y < inset || y >= length - inset) {\n\treturn OUTSIDE;\n    }\n\n    /*\n     * Here we assume that the scrollbar is layed out with both arrow buttons\n     * at the bottom (or right).  Except on 10.6, however, the arrows do not\n     * actually exist, i.e. the arrowLength is 0.  These are the same\n     * assumptions which are being made in TkpComputeScrollbarGeometry.\n     */\n\n    if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) {\n\treturn TOP_GAP;\n    }\n    if (y < scrollPtr->sliderLast) {\n\treturn SLIDER;\n    }\n    if (y < length - (2 * scrollPtr->arrowLength + inset)) {\n\treturn BOTTOM_GAP;\n    }\n\n    /*\n     * On systems newer than 10.6 we have already returned.\n     */\n\n    if (y < length - (scrollPtr->arrowLength + inset)) {\n\treturn TOP_ARROW;\n    }\n    return BOTTOM_ARROW;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * UpdateControlValues --\n *\n *\tThis procedure updates the Macintosh scrollbar control to display the\n *\tvalues defined by the Tk scrollbar. This is the key interface to the\n *\tMac-native scrollbar; the Unix bindings drive scrolling in the Tk\n *\twindow and all the Mac scrollbar has to do is redraw itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe Macintosh control is updated.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nUpdateControlValues(\n    TkScrollbar *scrollPtr)\t\t/* Scrollbar data struct. */\n{\n    MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;\n    Tk_Window tkwin = scrollPtr->tkwin;\n    MacDrawable *macWin = (MacDrawable *)Tk_WindowId(scrollPtr->tkwin);\n    double dViewSize;\n    HIRect contrlRect;\n    short height;\n\n    NSView *view = TkMacOSXGetNSViewForDrawable(macWin);\n    CGFloat viewHeight = [view bounds].size.height;\n    NSRect frame;\n\n    frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),\n\t    Tk_Height(tkwin));\n    frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);\n    frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);\n\n    contrlRect = NSRectToCGRect(frame);\n    msPtr->info.bounds = contrlRect;\n\n    height = contrlRect.size.height - scrollPtr->arrowLength;\n\n    /*\n     * Ensure we set scrollbar control bounds only once all size adjustments\n     * have been computed.\n     */\n\n    msPtr->info.bounds = contrlRect;\n    if (scrollPtr->vertical) {\n\tmsPtr->info.attributes &= ~kThemeTrackHorizontal;\n    } else {\n\tmsPtr->info.attributes |= kThemeTrackHorizontal;\n    }\n\n    /*\n     * Given the Tk parameters for the fractions of the start and end of the\n     * thumb, the following calculation determines the location for the\n     * Macintosh thumb. The Aqua scroll control works as follows. The\n     * scrollbar's value is the position of the left (or top) side of the view\n     * area in the content area being scrolled. The maximum value of the\n     * control is therefore the dimension of the content area less the size of\n     * the view area.\n     */\n\n    double factor = RangeToFactor(100.0);\n    dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor;\n    msPtr->info.max = factor - dViewSize;\n    msPtr->info.trackInfo.scrollbar.viewsize = dViewSize;\n    if (scrollPtr->vertical) {\n\tif (SNOW_LEOPARD_STYLE) {\n\t    msPtr->info.value = factor * scrollPtr->firstFraction;\n\t} else {\n\t    msPtr->info.value = msPtr->info.max -\n\t\t    factor * scrollPtr->firstFraction;\n\t}\n    } else {\n\tmsPtr->info.value = factor * scrollPtr->firstFraction;\n    }\n\n    if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)\n\t    || height <= metrics.minHeight) {\n\tmsPtr->info.enableState = kThemeTrackHideTrack;\n    } else {\n\tmsPtr->info.enableState = kThemeTrackActive;\n\tmsPtr->info.attributes =\n\t\tkThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScrollbarEvent --\n *\n *\tThis procedure is invoked in response to <Button>,\n *      <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events.  The\n *      Scrollbar appearance is modified for each event.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nScrollbarEvent(\n    TkScrollbar *scrollPtr,\n    XEvent *eventPtr)\n{\n    MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;\n\n    /*\n     * The pressState does not indicate whether the moused button was pressed\n     * at some location in the Scrollbar.  Rather, it indicates that the\n     * scrollbar should appear as if it were pressed in that location. The\n     * standard Mac behavior is that once the button is pressed inside the\n     * Scrollbar the appearance should not change until the button is released,\n     * even if the mouse moves outside of the scrollbar.  However, if the mouse\n     * lies over the scrollbar but the button is not pressed then the\n     * appearance should be the same as if the button had been pressed on the\n     * slider, i.e. kThemeThumbPressed.  See the file Appearance.r, or\n     * HIToolbox.bridgesupport on 10.14.\n     */\n\n    if (eventPtr->type == ButtonPress) {\n\tmsPtr->buttonDown = true;\n\tUpdateControlValues(scrollPtr);\n\n\tint where = TkpScrollbarPosition(scrollPtr,\n\t\teventPtr->xbutton.x, eventPtr->xbutton.y);\n\n\tswitch (where) {\n\tcase OUTSIDE:\n\t    msPtr->info.trackInfo.scrollbar.pressState = 0;\n\t    break;\n\tcase TOP_GAP:\n\t    msPtr->info.trackInfo.scrollbar.pressState = kThemeTopTrackPressed;\n\t    break;\n\tcase SLIDER:\n\t    msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;\n\t    break;\n\tcase BOTTOM_GAP:\n\t    msPtr->info.trackInfo.scrollbar.pressState =\n\t\t    kThemeBottomTrackPressed;\n\t    break;\n\tcase TOP_ARROW:\n\n\t    /*\n\t     * This looks wrong and the docs say it is wrong but it works.\n\t     */\n\n\t    msPtr->info.trackInfo.scrollbar.pressState =\n\t\t    kThemeTopInsideArrowPressed;\n\t    break;\n\tcase BOTTOM_ARROW:\n\t    msPtr->info.trackInfo.scrollbar.pressState =\n\t\t    kThemeBottomOutsideArrowPressed;\n\t    break;\n\t}\n    }\n    if (eventPtr->type == ButtonRelease) {\n\tmsPtr->buttonDown = false;\n\tif (!msPtr->mouseOver) {\n\t    msPtr->info.trackInfo.scrollbar.pressState = 0;\n\t}\n    }\n    if (eventPtr->type == EnterNotify) {\n\tmsPtr->mouseOver = true;\n\tif (!msPtr->buttonDown) {\n\t    msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;\n\t}\n    }\n    if (eventPtr->type == LeaveNotify) {\n\tmsPtr->mouseOver = false;\n\tif (!msPtr->buttonDown) {\n\t    msPtr->info.trackInfo.scrollbar.pressState = 0;\n\t}\n    }\n    TkScrollbarEventuallyRedraw(scrollPtr);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ScrollbarEventProc --\n *\n *\tThis procedure is invoked by the Tk dispatcher for various events on\n *\tscrollbars.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWhen the window gets deleted, internal structures get cleaned up. When\n *\tit gets exposed, it is redisplayed.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nScrollbarEventProc(\n    void *clientData,\t/* Information about window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n\n    switch (eventPtr->type) {\n    case UnmapNotify:\n\tTkMacOSXSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false);\n\tbreak;\n    case ActivateNotify:\n    case DeactivateNotify:\n\tTkScrollbarEventuallyRedraw(scrollPtr);\n\tbreak;\n    case ButtonPress:\n    case ButtonRelease:\n    case EnterNotify:\n    case LeaveNotify:\n\tScrollbarEvent(scrollPtr, eventPtr);\n\tbreak;\n    default:\n\tTkScrollbarEventProc(scrollPtr, eventPtr);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXSend.c",
    "content": "/*\n * tkMacOSXSend.c --\n *\n * This file implements the \"send\" command, which allows commands to be passed\n * from interpreter to interpreter.  This implementation uses Apple for\n * interprocess communication, in place of the XProperties in the original\n * unix implementation.\n *\n * Copyright © 1989-1994 The Regents of the University of California.\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n * Copyright © 2025 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXInt.h\"\n\n/*\n * The following structure is used to keep track of the interpreters\n * registered by this process.\n */\n\ntypedef struct RegisteredInterp {\n    char *name;                 /* Interpreter's name (malloc'ed).*/\n    Tcl_Interp *interp;\t\t/* Interpreter associated with name. NULL\n\t\t\t\t * means that the application was unregistered\n\t\t\t\t * or deleted while a send was in progress to\n\t\t\t\t * it. */\n    struct RegisteredInterp *nextPtr;\n\t\t\t\t/* Next in list of names associated with\n\t\t\t\t * interps in this process. NULL means end of\n\t\t\t\t * list. */\n} RegisteredInterp;\n\n/*\n * When running in an environment where user interaction is possible, i.e not\n * on a CI runner, a registry of all interpreters owned by the current user is\n * maintained in the file ~/Library/Caches/com.tcltk.appnames. The file\n * contains the string representation of a TclDictObj.  The dictionary keys\n * are appname strings and the value assigned to a key is a Tcl list\n * containing two Tcl_IntObj items whose integer values are, respectively, the\n * pid of the process which registered the interpreter and a currently unused\n * void *.\n *\n * The static variable below is set for the case of a CI runner, to avoid\n * panics when fopen fails.  When user interaction is available it will\n * be reassigned to the path in the user's Library/Caches directory.\n */\n\nstatic char *appNameRegistryPath = \"/tmp/TkAppnames\";\n\n/*\n * Information that we record about an application.\n * RegFindName returns a struct of this type.\n */\n\ntypedef struct AppInfo {\n    pid_t pid;\n    void *clientData;\n} AppInfo;\n\n/*\n * Construct an AppInfo from a ListObj value of the appNameDict.\n */\n\nstatic AppInfo\nObjToAppInfo(\n    Tcl_Obj *value)\n{\n    AppInfo result = {0, NULL};\n    Tcl_Size objc;\n    Tcl_Obj **objvPtr;\n    static const char *failure = \"AppName registry is corrupted.  Try deleting %s\";\n    if (TCL_OK != Tcl_ConvertToType(NULL, value, Tcl_GetObjType(\"list\"))) {\n\tTcl_Panic(failure, appNameRegistryPath);\n    } else if (Tcl_ListObjGetElements(NULL, value, &objc, &objvPtr) == TCL_OK) {\n\tif (objc != 2) {\n\t    Tcl_Panic(failure, appNameRegistryPath);\n\t}\n\tTcl_GetIntFromObj(NULL, objvPtr[0], &result.pid);\n\tTcl_GetLongFromObj(NULL, objvPtr[1], (long *) &result.clientData);\n    }\n    return result;\n}\n\n/*\n * Construct a ListObj value for the appNameDict from an AppInfo.\n */\n\nstatic Tcl_Obj*\nAppInfoToObj(\n    AppInfo info)\n{\n    Tcl_Obj *objv[2] = {Tcl_NewIntObj(info.pid),\n\t\t\tTcl_NewLongObj(info.clientData)};\n    return Tcl_NewListObj(2, objv);\n}\n\n/* When the AppName registry is being manipulated by an application (e.g. to\n * add or remove an entry), it is loaded into memory using a structure of the\n * following type:\n */\n\ntypedef struct NameRegistry {\n    int modified;\t\t/* Non-zero means that the property has been\n\t\t\t\t * modified, so it needs to be written out\n\t\t\t\t * when the NameRegistry is closed. */\n    Tcl_Obj *appNameDict;       /* Tcl dict mapping interpreter names to\n\t\t\t\t * a Tcl list {pid, clientData}\n\t\t\t\t */\n} NameRegistry;\n\n/*\n * When sending to a different process we use the AppleEvent DoScript handler\n * to evaluate the command in the target interpreter.  (Note: The AppleEvent\n * tools are part of the Carbon framework, so we need to deal with status\n * codes of type OSStatus.)\n */\n\n/* Translate some common OSStatus values to strings. */\nstatic const char *getError(OSStatus status) {\n    static char aeErrorString[30];\n    const char *errorName;\n    switch (status) {\n    case -50:\n      errorName = \"paramError\";\n      break;\n    case -600:\n      errorName = \"procNotFound\";\n      break;\n    case -609:\n      errorName = \"connectionInvalid\";\n    case -1700:\n      errorName = \"errAECoercionFail\";\n      break;\n    case -1701:\n      errorName = \"errAEDescNotFound\";\n      break;\n    case -1704:\n      errorName = \"errAENotAEDesc\";\n      break;\n    case -1708:\n      errorName = \"errAEEventNotHandled\";\n      break;\n    case -1712:\n      errorName = \"errAETimeout\";\n      break;\n    default:\n      errorName = aeErrorString;\n      snprintf(aeErrorString, 30, \"%d\", status);\n      break;\n    }\n    return errorName;\n}\n\n/* Macros for checking OSStatus values. */\n#define CHECK(func)\t\t\t\t\t\t\t\\\n    if (status != noErr) {\t\t\t\t\t\t\\\n\tchar msg[512];\t\t\t\t\t\t\t\\\n\tsnprintf(msg, 512, \"%s returned error %s\",\t\t\t\\\n\t\t   func, getError(status));\t\t\t\t\\\n\tTcl_AddErrorInfo(interp, msg);\t\t\t\t\t\\\n\tTcl_AppendResult(interp, msg, (char *)NULL);\t\t\t\\\n\treturn TCL_ERROR;\t\t\t\t\t\t\\\n    }\n\n#define CHECK2(func)\t\t\t\t\t\t\t\\\n    if (status != noErr && status != errAEDescNotFound) {\t\t\\\n\tchar msg[512];\t\t\t\t\t\t\t\\\n\tsnprintf(msg, 512, \"%s returned error %s\",\t\t\t\\\n\t\t   func, getError(status));\t\t\t\t\\\n\tTcl_AddErrorInfo(interp, msg);\t\t\t\t\t\\\n\tTcl_AppendResult(interp, msg, (char *)NULL);\t\t\t\\\n\treturn TCL_ERROR;\t\t\t\t\t\t\\\n    }\n\n/*\n * For the implementation of the synchronous send command we need to be able\n * to process incoming Apple Events while we are waiting for a reply to an\n * Apple Event sent earlier.  For example, if we have two Tk applications\n * Wish and Wish #2 running in different processes and we issue the command:\n * `send Wish {send {Wish #2} set a 5}` on Wish #2, then Wish #2 must wait for\n * a reply to the full send command, but Wish cannot issue that reply until\n * Wish $2 has run the command `set a 5` sent to it by Wish.  So Wish #2 needs\n * to respond to the message from Wish concurrently with waiting for a\n * reply from Wish.\n *\n * To deal with this we create a separate thread to send the command while\n * condurrently running the Tk event loop in the main thread.  The following\n * Objective C class implements the thread.\n */\n\n@interface AEReplyThread: NSThread\n{\n}\n@property AppleEvent *eventPtr;\n@property AppleEvent *replyPtr;\n@property int *statusPtr;\n@end\n\n@implementation AEReplyThread\n- (void) main\n{\n    /*\n     * The original unix implementation of the send command would wait\n     * arbitrarily long for the command to return, unless the target\n     * interpreter died.  So we request no timeout in our call to\n     * AESendMessage.  If the call returns a non-zero status we know that the\n     * target process has died.\n     */\n\n    *_statusPtr = AESendMessage(_eventPtr, _replyPtr, kAEWaitReply,\n\t\t\t\t    kNoTimeOut);\n    [NSThread exit];\n}\n@end\n\n\n/*\n * Sends an AppleEvent of type DoScript to a Tk app identified by its pid.\n */\n\nstatic int\nsendAEDoScript(\n    Tcl_Interp *interp,\n    const pid_t pid,\n    const char *command,\n    int async)\n{\n    AppleEvent event, reply;\n    OSStatus status;\n\n    // Build an AppleEvent targeting the provided pid.\n    status = AEBuildAppleEvent(kAEMiscStandards, // NOT kAECoreSuite!!!\n\t\t\t       kAEDoScript,\n\t\t\t       typeKernelProcessID, &pid, sizeof(pid_t),\n\t\t\t       kAutoGenerateReturnID,\n\t\t\t       kAnyTransactionID,\n\t\t\t       &event,\n\t\t\t       NULL,             // No error struct is needed.\n\t\t\t       \"'----':utf8(@)\", // direct parameter: utf8 bytes\n\t\t\t       strlen(command),\n\t\t\t       command);\n    CHECK(\"AEBuildAppleEvent\")\n\n    // Send the event.\n    if (async) {\n\n\t/*\n\t * If the async parameter is true then no result is produced and\n\t * errors are ignored.  So we do not need a reply to our AppleEvent.\n\t */\n\tstatus = AESendMessage(&event, nil, kAENoReply, 0);\n\tCHECK(\"AESendMessage\")\n    } else {\n\n\t/*\n\t * Otherwise we call AESendMessage from an NSThread and run\n\t * an event loop until the status changes.\n\t */\n\n\tstatus = 1;  /* impossible OSStatus */\n\tAEReplyThread *replyThread = [[AEReplyThread alloc] init];\n\treplyThread.eventPtr = &event;\n\treplyThread.replyPtr = &reply;\n\treplyThread.statusPtr = &status;\n\t[replyThread start];\n\twhile (status == 1) {\n\t    // check if the target interpreter is alive.\n\t    Tcl_DoOneEvent(TCL_ALL_EVENTS);\n\t}\n\tif (status) {\n\t    const char *msg = \"target application died\";\n\t    Tcl_AddErrorInfo(interp, msg);\n\t    Tcl_SetResult(interp, msg, NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n    int result = TCL_OK;\n    if (async == 0) {\n\t// Read the reply and extract relevant info.\n\tint code = 0;\n\tDescType actualType = 0;\n\tAEGetParamPtr(&reply, keyErrorNumber, typeSInt32, &actualType,\n\t\t      &code, 4, NULL);\n\tCHECK2(\"AEGetParamPtr\")\n\tif (code == TCL_OK) {\n\t    // Get the result string.\n\t    Size resultSize = 0;\n\t    status = AESizeOfParam(&reply, keyDirectObject, &actualType,\n\t\t\t\t   &resultSize);\n\t    CHECK2(\"AESizeOfParam\")\n\t    char *resultBuffer = (char *)Tcl_Alloc(resultSize + 1);\n\t    AEGetParamPtr(&reply, keyDirectObject, typeUTF8Text, &actualType,\n\t\t\t  resultBuffer, resultSize, NULL);\n\t    CHECK2(\"AEGetParamPtr\")\n\t    if (resultSize > 0) {\n\t\tresultBuffer[resultSize] = '\\0';\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(resultBuffer,\n\t\t\t\t\t\t\t  TCL_INDEX_NONE));\n\t    }\n\n\t    result = TCL_OK;\n\t    Tcl_Free(resultBuffer);\n\t    AEDisposeDesc(&reply);\n\t} else {\n\t    // Get the error string.\n\t    Size errorSize;\n\t    status = AESizeOfParam(&reply, keyErrorString,\n\t\t\t\t   &actualType, &errorSize);\n\t    CHECK2(\"AESizeOfParam\")\n\t    char *errorBuffer = (char *)Tcl_Alloc(errorSize + 1);\n\t    AEGetParamPtr(&reply, keyErrorString, typeUTF8Text, &actualType,\n\t\t\t  errorBuffer, errorSize, NULL);\n\t    CHECK2(\"AEGetParamPtr\")\n\t    if (errorSize > 0) {\n\t\terrorBuffer[errorSize] = '\\0';\n\t\tTcl_AddErrorInfo(interp, errorBuffer);\n\t    }\n\t    Tcl_SetObjErrorCode(interp, Tcl_NewStringObj(errorBuffer,\n\t\t\t\t\t\t      TCL_INDEX_NONE));\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorBuffer,\n\t\t\t\t\t\t      TCL_INDEX_NONE));\n\t    result = TCL_ERROR;\n\t    Tcl_Free(errorBuffer);\n\t}\n\tAEDisposeDesc(&reply);\n    }\n    AEDisposeDesc(&event);\n    return result;\n}\n\n/*\n * The following struct contains  per-process data:\n */\n\nstatic struct {\n    int sendSerial;\t\t      /* The serial number that was used * in\n\t\t\t\t       * the last \"send\" command. */\n    int sendDebug;\t\t      /* This can be set while debugging to\n\t\t\t\t       * add print statements, for example. */\n    int initialized;                  /* Set when SendInit is called. */\n    RegisteredInterp *interpListPtr;  /* List of all interpreters registered\n\t\t\t\t       * in this process. */\n\n} staticData = {0, 0, 0, 0};\n\n/*\n * Forward declarations for static functions defined later in this file:\n */\n\nstatic Tcl_CmdDeleteProc DeleteProc;\nstatic NameRegistry*\tRegOpen(Tcl_Interp *interp);\nstatic void\t\tRegClose(NameRegistry *regPtr);\nstatic void\t\tRegAddName(NameRegistry *regPtr, const char *name,\n\t\t\t\t    Window commWindow);\nstatic void\t\tRegDeleteName(NameRegistry *regPtr, const char *name);\nstatic AppInfo\t\tRegFindName(NameRegistry *regPtr, const char *name);\nstatic int\t\tSendInit();\n\nstatic void\nsaveAppNameRegistry(\n    Tcl_Obj *dict,\n    const char *path)\n{\n    if (path == NULL) {\n\t/* We are running in a CI runner */\n\treturn;\n    }\n    Tcl_Size length, bytesWritten;\n    /* Open the file ab+ to avoid truncating it before flocking it. */\n    FILE *appNameFile = fopen(path, \"ab+\");\n    char *bytes;\n    if (appNameFile == NULL) {\n\tTcl_Panic(\"fopen failed on %s\", path);\n\treturn;\n    }\n    if (flock(fileno(appNameFile), LOCK_EX)) {\n\tTcl_Panic(\"flock failed on %s\", path);\n    }\n    /* Now we can truncate the file. */\n    if (ftruncate(fileno(appNameFile), 0) != 0) {\n\tTcl_Panic(\"ftruncate failed on %s\", path);\n    }\n    bytes = Tcl_GetStringFromObj(dict, &length);\n    bytesWritten = (Tcl_Size) fwrite(bytes, 1, length, appNameFile);\n    flock(fileno(appNameFile), LOCK_UN);\n    fclose(appNameFile);\n    if (bytesWritten != length) {\n\tTcl_Panic(\"write failed on %s: length: %lu wrote: %lu\", path,\n\t\tlength, bytesWritten);\n\treturn;\n    }\n}\n\nstatic Tcl_Obj*\nloadAppNameRegistry(\n    const char *path)\n{\n    size_t length, bytesRead;\n    char *bytes = NULL;\n    Tcl_Obj *result;\n    if (path == NULL) {\n\t/* We are running in a CI runner. */\n\treturn NULL;\n    }\n\n    FILE *appNameFile = fopen(path, \"ab+\");\n    if (appNameFile == NULL) {\n\tTcl_Panic(\"fopen failed on %s\", path);\n    }\n    if (flock(fileno(appNameFile), LOCK_EX)) {\n\tTcl_Panic(\"flock failed on %s\", path);\n    }\n    /*\n     * In macOS, \"ab+\" sets read and write position at the end.\n     * But this is not a posix requirement and does not happen\n     * on linux.  So we seek to the end anyway.\n     */\n    fseek(appNameFile, 0, SEEK_END);\n    length = ftell(appNameFile);\n    if (length > 0) {\n\tbytes = (char *)Tcl_Alloc(length);\n\tif (bytes) {\n\t    fseek(appNameFile, 0, SEEK_SET);\n\t    bytesRead = fread(bytes, 1, length, appNameFile);\n\t} else {\n\t    Tcl_Panic(\"Out of memory\");\n\t}\n    }\n    flock(fileno(appNameFile), LOCK_UN);\n    fclose(appNameFile);\n    if (length == 0) {\n\treturn Tcl_NewDictObj();\n    }\n    if (bytesRead != length) {\n\tTcl_Panic(\"read failed on %s: length %lu; read %lu,\\n\", path,\n\t\tlength, bytesRead);\n    }\n    result = Tcl_NewStringObj(bytes, length);\n    Tcl_Free(bytes);\n    /*\n     * Convert the string object to a dict. If that fails the file\n     * must be corrupt, so all we can do is return an empty dict.\n     */\n    Tcl_Size size;\n    if (TCL_OK != Tcl_DictObjSize(NULL, result, &size)){\n\tresult = Tcl_NewDictObj();\n    }\n    return result;\n}\n\n\f\n/*\n *--------------------------------------------------------------\n *\n * SendInit --\n *\n *\tThis function is called to initialize the objects needed\n *\tfor sending commands and receiving results.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets up various data structures and windows.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSendInit()\n{\n    if (getenv(\"CI\")) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Intialize the path used for the appname registry.\n     */\n    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(\n\t\t NSCachesDirectory, NSUserDomainMask, YES);\n    NSString *cachesDirectory = [searchPaths objectAtIndex:0];\n    NSString *RegistryPath = [cachesDirectory\n\tstringByAppendingPathComponent:@\"com.tcltk.appnames\"];\n    size_t length = 1 + strlen(RegistryPath.UTF8String);\n    appNameRegistryPath = (char *)Tcl_Alloc(length);\n    strlcpy(appNameRegistryPath, (char *)RegistryPath.UTF8String, length);\n    return TCL_OK;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegOpen --\n *\n *\tThis function loads the name registry into memory so that it can be\n *\tmanipulated.  It reads a string representation of a Tcl dict from a\n *\tfile and constructs the dict.\n *\n * Results:\n *\tThe return value is a pointer to a NameRegistry structure.\n *\n *\n *\n *----------------------------------------------------------------------\n */\n\nstatic NameRegistry *\nRegOpen(\n    Tcl_Interp *interp)\t\t/* Interpreter to use for error reporting\n\t\t\t\t * (errors cause a panic so in fact no error\n\t\t\t\t * is ever returned, but the interpreter is\n\t\t\t\t * needed anyway). */\n{\n    NameRegistry *regPtr;\n    regPtr = (NameRegistry *)Tcl_Alloc(sizeof(NameRegistry));\n    regPtr->modified = 0;\n\n    /*\n     * Deserialize the registry file as a Tcl dict.\n     */\n\n    Tcl_Obj *dict = loadAppNameRegistry(appNameRegistryPath);\n    if (dict) {\n\tregPtr->appNameDict = dict;\n    } else {\n\tregPtr->appNameDict = Tcl_NewDictObj();\n    }\n\n    /*\n     * Find and remove any interpreter name for which the process is no longer\n     * running.  This cleans up after a crash of some other wish process.\n     */\n\n    Tcl_Size dictSize;\n    Tcl_DictObjSize(NULL, regPtr->appNameDict, &dictSize);\n    Tcl_Obj **deadinterps = (Tcl_Obj**) Tcl_Alloc(dictSize * sizeof(Tcl_Obj*));\n    int count = 0;\n    Tcl_DictSearch search;\n    Tcl_Obj *key, *value;\n    int done = 0, i;\n    for (Tcl_DictObjFirst(\n\t  interp, regPtr->appNameDict, &search, &key, &value, &done) ;\n\t     !done ;\n\t     Tcl_DictObjNext(&search, &key, &value, &done)) {\n\tAppInfo info = ObjToAppInfo(value);\n\tif (kill(info.pid, 0)) {\n\t    deadinterps[count++] = key;\n\t}\n    }\n    for (i = 0; i < count; i++) {\n\tTcl_DictObjRemove(NULL, regPtr->appNameDict, deadinterps[i]);\n    }\n    Tcl_Free(deadinterps);\n    return regPtr;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegClose --\n *\n *\tThis function is called to end a series of operations on a name\n *\tregistry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *      The registry is written back if it has been modified, Memory for the\n *\tregistry is freed, so the caller should never use regPtr again.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegClose(\n    NameRegistry *regPtr)\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n{\n    if (regPtr->modified) {\n\tsaveAppNameRegistry(regPtr->appNameDict, appNameRegistryPath);\n    }\n    Tcl_Free(regPtr);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegFindName --\n *\n *\tGiven an open name registry, this function finds an entry with a given\n *\tname, if there is one, and returns information about that entry.\n *\n * Results:\n *      The return value is an AppInfo struct containing the pid and the\n *\tclientData for the application named \"name\", or nil if there is no\n *\tsuch entry in the registry.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nAppInfo\nRegFindName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name)\t\t/* Name of an application. */\n{\n    Tcl_Obj *valuePtr = NULL, *keyPtr = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n    Tcl_DictObjGet(NULL, regPtr->appNameDict, keyPtr, &valuePtr);\n    // Maybe using pid 0 as the default is a bad idea?\n    AppInfo resultTcl = {0, NULL};\n    if (valuePtr) {\n\tresultTcl = ObjToAppInfo(valuePtr);\n    }\n    return resultTcl;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegDeleteName --\n *\n *\tThis function deletes the entry for a given name from an open\n *\tregistry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there used to be an entry named \"name\" in the registry, then it is\n *\tdeleted and the registry is marked as modified so it will be written\n *\tback when closed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegDeleteName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name)\t\t/* Name of an application. */\n{\n    Tcl_Obj *keyPtr = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n    Tcl_DictObjRemove(NULL, regPtr->appNameDict, keyPtr);\n    regPtr->modified = 1;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegAddName --\n *\n *\tAdd a new entry to an open registry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe open registry is expanded; it is marked as modified so that it\n *\twill be written back when closed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegAddName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name,\t\t/* Name of an application. The caller must\n\t\t\t\t * ensure that this name isn't already\n\t\t\t\t * registered. */\n    Window commWindow)\t\t/* X identifier for comm. window of\n\t\t\t\t * application. */\n{\n    (void) commWindow; /////\n    Tcl_Obj *keyPtr = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n    AppInfo valueTcl = {getpid(), 0};\n    Tcl_Obj *valuePtr = AppInfoToObj(valueTcl);\n    Tcl_DictObjPut(NULL, regPtr->appNameDict, keyPtr, valuePtr);\n    regPtr->modified = 1;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAppName --\n *\n *\tThis function is called to associate an ASCII name with a Tk\n *\tapplication. If the application has already been named, the name\n *\treplaces the old one.\n *\n * Results:\n *\tThe return value is the name actually given to the application. This\n *\twill normally be the same as name, but if name was already in use for\n *\tan application then a name of the form \"name #2\" will be chosen, with\n *\ta high enough number to make the name unique.\n *\n *      A crucial exception to the behavior described above arises when Tk is\n *      being run on a Continuous Integration runner.  The file-based App\n *      registry which is used to ensure uniqueness cannot be used on CI\n *      runners because macOS will post a system privacy dialog requesting\n *      permission to write files.  This causes Wish to hang, since it is not\n *      possible to dismiss the dialog without user interaction.  We use the\n *      environment variable CI to determine whether we are being run on a CI\n *      runner.  If so, this command always returns the name provided as an\n *      argument.  Note that this makes the command winfo interps ignore all\n *      other interpreteters.\n *\n * Side effects:\n *\tIn normal usage (i.e. when interaction is possible) the app name is\n *\tsaved in a registry file, thereby allowing the \"send\" command to be\n *\tused later to invoke commands in the application. In addition, the\n *\t\"send\" command is created in the application's interpreter. The\n *\tregistration will be removed automatically if the interpreter is\n *\tdeleted or the \"send\" command is removed.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTk_SetAppName(\n    Tk_Window tkwin,\t\t/* Token for any window in the application to\n\t\t\t\t * be named: it is just used to identify the\n\t\t\t\t * application. */\n    const char *name)\t\t/* The name that will be used to refer to the\n\t\t\t\t * interpreter in later \"send\" commands. Must\n\t\t\t\t * be globally unique. */\n{\n    if (getenv(\"CI\")) {\n\treturn name;\n    }\n    RegisteredInterp *riPtr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    NameRegistry *regPtr;\n    Tcl_Interp *interp;\n    const char *actualName;\n    Tcl_DString dString;\n    int offset, i;\n    interp = winPtr->mainPtr->interp;\n    if (!staticData.initialized) {\n\tSendInit();\n    }\n\n    /*\n     * See if the application is already registered; if so, remove its current\n     * name from the registry.\n     */\n\n    regPtr = RegOpen(interp);\n    for (riPtr = staticData.interpListPtr; ; riPtr = riPtr->nextPtr) {\n\tif (riPtr == NULL) {\n\t    /*\n\t     * This interpreter isn't currently registered; create the data\n\t     * structure that will be used to register it, plus add\n\t     * the \"send\" command to the interpreter.  The name gets added\n\t     * to the structure later.\n\t     */\n\n\t    riPtr = (RegisteredInterp *)Tcl_Alloc(sizeof(RegisteredInterp));\n\t    riPtr->interp = interp;\n\t    riPtr->nextPtr = staticData.interpListPtr;\n\t    staticData.interpListPtr = riPtr;\n\t    riPtr->name = NULL;\n\t    Tcl_CreateObjCommand2(interp, \"send\", Tk_SendObjCmd, riPtr,\n\t\t\t\t  DeleteProc);\n\t    if (Tcl_IsSafe(interp)) {\n\t\tTcl_HideCommand(interp, \"send\", \"send\");\n\t    }\n\t    break;\n\t}\n\tif (riPtr->interp == interp) {\n\t    /*\n\t     * The interpreter is currently registered; remove it from the\n\t     * name registry.\n\t     */\n\n\t    if (riPtr->name) {\n\t\tRegDeleteName(regPtr, riPtr->name);\n\t\tTcl_Free(riPtr->name);\n\t    }\n\t    break;\n\t}\n    }\n\n    /*\n     * Pick a name to use for the application. Use \"name\" if it's not already\n     * in use. Otherwise add a suffix such as \" #2\", trying larger and larger\n     * numbers until we eventually find one that is unique.\n     */\n\n    actualName = name;\n    offset = 0;\t\t\t\t/* Needed only to avoid \"used before\n\t\t\t\t\t * set\" compiler warnings. */\n    for (i = 1; ; i++) {\n\tif (i > 1) {\n\t    if (i == 2) {\n\t\tTcl_DStringInit(&dString);\n\t\tTcl_DStringAppend(&dString, name, TCL_INDEX_NONE);\n\t\tTcl_DStringAppend(&dString, \" #\", 2);\n\t\toffset = Tcl_DStringLength(&dString);\n\t\tTcl_DStringSetLength(&dString, offset+TCL_INTEGER_SPACE);\n\t\tactualName = Tcl_DStringValue(&dString);\n\t    }\n\t    snprintf(Tcl_DStringValue(&dString) + offset, TCL_INTEGER_SPACE,\n\t\t     \"%d\", i);\n\t}\n\tAppInfo info = RegFindName(regPtr, actualName);\n\tif (info.pid == 0) {\n\t    break;\n\t}\n    }\n\n    /*\n     * We've now got a name to use. Store it in the name registry and in the\n     * local entry for this application.\n     */\n\n    RegAddName(regPtr, actualName, None);\n    RegClose(regPtr);\n    riPtr->name = (char *)Tcl_Alloc(strlen(actualName) + 1);\n    strcpy(riPtr->name, actualName);\n    if (actualName != name) {\n\tTcl_DStringFree(&dString);\n    }\n    return riPtr->name;\n}\n\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SendObjCmd --\n *\n *\tThis function is invoked to process the \"send\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SendObjCmd(\n    TCL_UNUSED(void *),\t    /* Information about sender */\n    Tcl_Interp *interp,\t    /* Current interpreter. */\n    Tcl_Size objc,\t    /* Number of arguments. */\n    Tcl_Obj *const objv[])  /* Argument strings. */\n{\n    enum {\n\tSEND_ASYNC, SEND_DISPLAYOF, SEND_LAST\n    };\n    static const char *const sendOptions[] = {\n\t\"-async\",   \"-displayof\",   \"--\",  NULL\n    };\n    const char *stringRep, *destName;\n    TkWindow *winPtr;\n    //    Window commWindow;\n    RegisteredInterp *riPtr;\n    int result, async, i, firstArg, index;\n    NameRegistry *regPtr;\n    Tcl_DString request, request2;\n    Tcl_Interp *localInterp;\t/* Used when the interpreter to send the\n\t\t\t\t * command to is within the same process. */\n\n    /*\n     * Process options, if any.\n     */\n\n    async = 0;\n    winPtr = (TkWindow *) Tk_MainWindow(interp);\n    if (winPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Process the command options.\n     */\n\n    for (i = 1; i < (objc - 1); i++) {\n\tstringRep = Tcl_GetString(objv[i]);\n\tif (stringRep[0] == '-') {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions,\n\t\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (index == SEND_ASYNC) {\n\t\t++async;\n\t    } else if (index == SEND_DISPLAYOF) {\n\t\twinPtr = (TkWindow *) Tk_NameToWindow(interp,\n\t\t\t\t\t  Tcl_GetString(objv[++i]),\n\t\t\t(Tk_Window) winPtr);\n\t\tif (winPtr == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else /* if (index == SEND_LAST) */ {\n\t\ti++;\n\t\tbreak;\n\t    }\n\t} else {\n\t    break;\n\t}\n    }\n\n    if (objc < (i + 2)) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"?-option value ...? interpName arg ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    destName = Tcl_GetString(objv[i]);\n    firstArg = i+1;\n\n    /*\n     * See if the target interpreter is local. If so, execute the command\n     * directly without going through the X server. The only tricky thing is\n     * passing the result from the target interpreter to the invoking\n     * interpreter. Watch out: they could be the same!\n     */\n\n    for (riPtr = staticData.interpListPtr; riPtr != NULL;\n\t    riPtr = riPtr->nextPtr) {\n\tif (strcmp(riPtr->name, destName) != 0) {\n\t    continue;\n\t}\n\t/* We have found our target interpreter */\n\tTcl_Preserve(riPtr);\n\tlocalInterp = riPtr->interp;\n\tTcl_Preserve(localInterp);\n\tif (firstArg + 1 == objc) {\n\t    result = Tcl_EvalEx(localInterp, Tcl_GetString(objv[firstArg]),\n\t\t\t\tTCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t} else {\n\t    Tcl_DStringInit(&request);\n\t    Tcl_DStringAppend(&request, Tcl_GetString(objv[firstArg]),\n\t\t\t      TCL_INDEX_NONE);\n\t    for (i = firstArg+1; i < objc; i++) {\n\t\tTcl_DStringAppend(&request, \" \", 1);\n\t\tTcl_DStringAppend(&request, Tcl_GetString(objv[i]),\n\t\t\t\t  TCL_INDEX_NONE);\n\t    }\n\t    result = Tcl_EvalEx(localInterp, Tcl_DStringValue(&request),\n\t\t\t\tTCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    Tcl_DStringFree(&request);\n\n\t}\n\tif (interp != localInterp) {\n\t    if (result == TCL_ERROR) {\n\t\tTcl_Obj *errorObjPtr;\n\n\t\t/*\n\t\t * An error occurred, so transfer error information from the\n\t\t * destination interpreter back to our interpreter. Must clear\n\t\t * interp's result before calling Tcl_AddErrorInfo, since\n\t\t * Tcl_AddErrorInfo will store the interp's result in\n\t\t * errorInfo before appending riPtr's $errorInfo; we've\n\t\t * already got everything we need in riPtr's $errorInfo.\n\t\t */\n\n\t\tTcl_ResetResult(interp);\n\t\tTcl_AddErrorInfo(interp, Tcl_GetVar2(localInterp,\n\t\t\t\"errorInfo\", NULL, TCL_GLOBAL_ONLY));\n\t\terrorObjPtr = Tcl_GetVar2Ex(localInterp, \"errorCode\", NULL,\n\t\t\tTCL_GLOBAL_ONLY);\n\t\tTcl_SetObjErrorCode(interp, errorObjPtr);\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_GetObjResult(localInterp));\n\t    Tcl_ResetResult(localInterp);\n\t}\n\tTcl_Release(riPtr);\n\tTcl_Release(localInterp);\n\treturn result;\n    }\n\n    /*\n     * We are targetng an interpreter in another process.  First make sure the\n     * interpreter is registered.\n     */\n\n    regPtr = RegOpen(interp);\n    AppInfo info = RegFindName(regPtr, destName);\n    RegClose(regPtr);\n\n    if (info.pid == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"no application named \\\"%s\\\"\", destName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"APPLICATION\", destName,\n\t\tNULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Send the command with args to the target interpreter\n     */\n\n    Tcl_DStringInit(&request2);\n    Tcl_DStringAppend(&request2, Tcl_GetString(objv[firstArg]), TCL_INDEX_NONE);\n    if (firstArg < objc - 1) {\n\tfor (i = firstArg+1; i < objc; i++) {\n\t    Tcl_DStringAppend(&request2, \" \", 1);\n\t    Tcl_DStringAppend(&request2, Tcl_GetString(objv[i]), TCL_INDEX_NONE);\n\t}\n    }\n\n     // When async is 0, the call below blocks until a reply is received.\n     // Perhaps we should run a background thread to process timer events?\n\n    int code = sendAEDoScript(interp, info.pid, Tcl_DStringValue(&request2),\n\t\t\t      async);\n    staticData.sendSerial++;\n    return code;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetInterpNames --\n *\n *\tThis function is invoked to fetch a list of all the interpreter names\n *\tcurrently registered on this host.\n *\n * Results:\n *\tA standard Tcl return value. The interp's result will be set to hold a\n *\tlist of all the interpreter names defined on this host. If an\n *\terror occurs, then TCL_ERROR is returned and the interp's result will\n *\thold an error message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetInterpNames(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning a result. */\n    TCL_UNUSED(Tk_Window))\n{\n    NameRegistry *regPtr;\n    Tcl_Obj *resultObj = Tcl_NewObj();\n    regPtr = RegOpen(interp);\n    Tcl_DictSearch search;\n    Tcl_Obj *keyTcl, *value;\n    int done = 0;\n    for (Tcl_DictObjFirst(\n\t  interp, regPtr->appNameDict, &search, &keyTcl, &value, &done) ;\n\t     !done ;\n\t     Tcl_DictObjNext(&search, &keyTcl, &value, &done)) {\n\tTcl_ListObjAppendElement(NULL, resultObj, keyTcl);\n    }\n    RegClose(regPtr);\n    Tcl_SetObjResult(interp, resultObj);\n    return TCL_OK;\n}\n\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkSendCleanup --\n *\n *\tThis function is called to free resources used by the communication\n *\tchannels for sending commands and receiving results.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees various data structures and windows.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkSendCleanup(\n    TCL_UNUSED(TkDisplay *)) /* dispPtr */\n{\n\tTcl_Free((char *)appNameRegistryPath);\n}\n\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteProc --\n *\n *\tThis function is invoked by Tcl when the \"send\" command is deleted in\n *\tan interpreter. It unregisters the interpreter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe interpreter given by riPtr is unregistered.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteProc(\n    void *clientData)\t/* Info about registration */\n{\n    RegisteredInterp *riPtr = (RegisteredInterp *)clientData;\n    RegisteredInterp *riPtr2;\n    NameRegistry *regPtr;\n    regPtr = RegOpen(riPtr->interp);\n    RegDeleteName(regPtr, riPtr->name);\n    RegClose(regPtr);\n\n    if (staticData.interpListPtr == riPtr) {\n\tstaticData.interpListPtr = riPtr->nextPtr;\n    } else {\n\tfor (riPtr2 = staticData.interpListPtr; riPtr2 != NULL;\n\t\triPtr2 = riPtr2->nextPtr) {\n\t    if (riPtr2->nextPtr == riPtr) {\n\t\triPtr2->nextPtr = riPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    Tcl_Free(riPtr->name);\n    riPtr->interp = NULL;\n    Tcl_EventuallyFree(riPtr, TCL_DYNAMIC);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTestsendCmd --\n *\n *\tThis function implements the \"testsend\" command. It provides a set of\n *\tfunctions for testing the \"send\" command and support function in\n *\ttkSend.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tDepends on option; see below.\n *\n *----------------------------------------------------------------------\n */\n\n// We are not ready for the TestSendCmd yet.  The unix code is\n// below.  Much of it seems to involve inspecting X properties\n// which aren't being used here.\n#if 0\n\nint\nTkpTestsendCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    enum {\n\tTESTSEND_BOGUS, TESTSEND_PROP, TESTSEND_SERIAL\n    };\n    static const char *const testsendOptions[] = {\n\t\"bogus\",   \"prop\",   \"serial\",  NULL\n    };\n    TkWindow *winPtr = (TkWindow *)clientData;\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (index == TESTSEND_BOGUS) {\n\thandler = Tk_CreateErrorHandler(winPtr->dispPtr->display, -1, -1, -1,\n\t\tNULL, NULL);\n\tTk_DeleteErrorHandler(handler);\n    } else if (index == TESTSEND_PROP) {\n\tint result, actualFormat;\n\tunsigned long length, bytesAfter;\n\tAtom actualType, propName;\n\tchar *property, **propertyPtr = &property, *p, *end;\n\tWindow w;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\t\"prop window name ?value ?\");\n\t    return TCL_ERROR;\n\t}\n\tif (strcmp(Tcl_GetString(objv[2]), \"root\") == 0) {\n\t    w = RootWindow(winPtr->dispPtr->display, 0);\n\t} else if (strcmp(Tcl_GetString(objv[2]), \"comm\") == 0) {\n\t    w = Tk_WindowId(winPtr->dispPtr->commTkwin);\n\t} else {\n\t    w = strtoul(Tcl_GetString(objv[2]), &end, 0);\n\t}\n\tpropName = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));\n\tif (objc == 4) {\n\t    property = NULL;\n\t    result = GetWindowProperty(winPtr->dispPtr->display, w, propName,\n\t\t    0, 100000, False, XA_STRING, &actualType, &actualFormat,\n\t\t    &length, &bytesAfter, (unsigned char **) propertyPtr);\n\t    if ((result == Success) && (actualType != None)\n\t\t    && (actualFormat == 8) && (actualType == XA_STRING)) {\n\t\tfor (p = property; (unsigned long)(p-property) < length; p++) {\n\t\t    if (*p == 0) {\n\t\t\t*p = '\\n';\n\t\t    }\n\t\t}\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(property, TCL_INDEX_NONE));\n\t    }\n\t    if (property != NULL) {\n\t\tXFree(property);\n\t    }\n\t} else if (Tcl_GetString(objv[4])[0] == 0) {\n\t    handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,\n\t\t    -1, -1, -1, NULL, NULL);\n\t    DeleteProperty(winPtr->dispPtr->display, w, propName);\n\t    Tk_DeleteErrorHandler(handler);\n\t} else {\n\t    Tcl_DString tmp;\n\n\t    Tcl_DStringInit(&tmp);\n\t    for (p = Tcl_DStringAppend(&tmp, Tcl_GetString(objv[4]),\n\t\t    (int) strlen(Tcl_GetString(objv[4]))); *p != 0; p++) {\n\t\tif (*p == '\\n') {\n\t\t    *p = 0;\n\t\t}\n\t    }\n\t    handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,\n\t\t    -1, -1, -1, NULL, NULL);\n\t    ChangeProperty(winPtr->dispPtr->display, w, propName, XA_STRING,\n\t\t    8, PropModeReplace, (unsigned char*)Tcl_DStringValue(&tmp),\n\t\t    p-Tcl_DStringValue(&tmp));\n\t    Tk_DeleteErrorHandler(handler);\n\t    Tcl_DStringFree(&tmp);\n\t}\n    } else if (index == TESTSEND_SERIAL) {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(staticData.sendSerial+1));\n    }\n    return TCL_OK;\n}\n#endif\n\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-file-style: \"k&r\"\n * c-basic-offset: 4\n * c-file-offsets: ((arglist-cont . 0))\n * fill-column: 78\n * End:\n */\n\n"
  },
  {
    "path": "macosx/tkMacOSXServices.c",
    "content": "/*\n * tkMacOSXServices.c --\n *\\\n *\tThis file allows the integration of Tk and the Cocoa NSServices API.\n *\n * Copyright © 2010-2019 Kevin Walzer\n * Copyright © 2019 Marc Culler\n * Copyright © 2010 Adrian Robert\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include <tkInt.h>\n#include <tkMacOSXInt.h>\n\n/*\n * Event proc which calls the PerformService procedure.\n */\n\nstatic int\nServicesEventProc(\n    TCL_UNUSED(Tcl_Event *),\n    TCL_UNUSED(int))\n{\n    TkMainInfo *info = TkGetMainInfoList();\n\n    Tcl_GlobalEval(info->interp, \"::tk::mac::PerformService\");\n    return 1;\n}\n\f\n/*\n * The Wish application can send the current selection in the Tk clipboard\n * to other applications which accept messages of type NSString.  The TkService\n * object provides this service via its provideService method.  (The method\n * must be specified in the application's Info.plist file for this to work.)\n */\n\n@interface TkService : NSObject {\n\n}\n\n+ (void) initialize;\n- (void) provideService:(NSPasteboard *)pboard\n\t       userData:(NSString *)data\n\t\t  error:(NSString **)error;\n- (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard\n\t\t\t      types:(NSArray *)types;\n\n@end\n\f\n/*\n * Class methods.\n */\n\n@implementation TkService\n\n+ (void) initialize {\n    NSArray *sendTypes = [NSArray arrayWithObjects:@\"NSStringPboardType\",\n\t\t\t\t  @\"NSPasteboardTypeString\", nil];\n    [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes];\n    return;\n}\n\n/*\n * Get the current Tk selection and copy it to the system pasteboard.\n */\n\n- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard\n\t\t\t     types:(NSArray *)types\n{\n    NSArray *typesDeclared = nil;\n    NSString *pboardType = nil;\n    TkMainInfo *info = TkGetMainInfoList();\n\n    for (NSString *typeString in types) {\n\tif ([typeString isEqualToString:@\"NSStringPboardType\"] ||\n\t    [typeString isEqualToString:@\"NSPasteboardTypeString\"]) {\n\t    typesDeclared = [NSArray arrayWithObject:typeString];\n\t    pboardType = typeString;\n\t    break;\n\t}\n    }\n    if (!typesDeclared) {\n\treturn NO;\n    }\n    Tcl_Eval(info->interp, \"selection get\");\n\n    char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp));\n    NSString *writestring = [NSString stringWithUTF8String:copystring];\n\n    [pboard declareTypes:typesDeclared owner:nil];\n    return [pboard setString:writestring forType:pboardType];\n}\n\n/*\n * This is the method that actually calls the Tk service; it must be specified\n * in Info.plist.\n */\n\n- (void)provideService:(NSPasteboard *)pboard\n\t      userData:(NSString *)data\n\t\t error:(NSString **)error\n{\n    NSString *pboardString = nil, *pboardType = nil;\n    NSArray *types = [pboard types];\n    Tcl_Event *event;\n    (void)data;\n    (void)error;\n\n    /*\n     * Get a string from the private pasteboard and copy it to the general\n     * pasteboard to make it available to other applications.\n     */\n\n    for (NSString *typeString in types) {\n\tif ([typeString isEqualToString:@\"NSStringPboardType\"] ||\n\t    [typeString isEqualToString:@\"NSPasteboardTypeString\"]) {\n\t    pboardString = [pboard stringForType:typeString];\n\t    pboardType = typeString;\n\t    break;\n\t}\n    }\n    if (pboardString) {\n\tNSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard];\n\t[generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]\n\t\t\t\t  owner:nil];\n\t[generalpasteboard setString:pboardString forType:pboardType];\n\tevent = (Tcl_Event *)Tcl_Alloc(sizeof(Tcl_Event));\n\tevent->proc = ServicesEventProc;\n\tTcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);\n    }\n}\n@end\n\f\n/*\n\n * Instantiate a TkService object and register it with the NSApplication.\n * This is called exactly one time from TkpInit.\n */\n\nint\nTkMacOSXServices_Init(\n    TCL_UNUSED(Tcl_Interp *))\n{\n    /*\n     * Initialize an instance of TkService and register it with the NSApp.\n     */\n\n    TkService *service = [[TkService alloc] init];\n    [NSApp setServicesProvider:service];\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXSubwindows.c",
    "content": "/*\n * tkMacOSXSubwindows.c --\n *\n *\tImplements subwindows for the macintosh version of Tk.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXWm.h\"\n#include \"tkMacOSXConstants.h\"\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_CLIP_REGIONS\n#endif\n*/\n\n/*\n * Prototypes for functions used only in this file.\n */\n\nstatic void\t\tMoveResizeWindow(MacDrawable *macWin);\nstatic void\t\tGenerateConfigureNotify(TkWindow *winPtr,\n\t\t\t    int includeWin);\nstatic void\t\tUpdateOffsets(TkWindow *winPtr, int deltaX,\n\t\t\t    int deltaY);\nstatic void\t\tNotifyVisibility(TkWindow *winPtr, XEvent *eventPtr);\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDestroyWindow --\n *\n *\tDeallocates the given X Window.\n *\n * Results:\n *\tThe window id is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDestroyWindow(\n    TCL_UNUSED(Display *),\t\t/* Display. */\n    Window window)\t\t/* Window. */\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n    TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macWin);\n    //fprintf(stderr, \"XDestroyWindow: %s with parent %s\\n\",\n    //\t    Tk_PathName(macWin->winPtr),\n    //\t    Tk_PathName(macWin->winPtr->parentPtr));\n\n    /*\n     * Remove any dangling pointers that may exist if the window we are\n     * deleting is being tracked by the grab code.\n     */\n\n    TkMacOSXSelDeadWindow(macWin->winPtr);\n    TkPointerDeadWindow(macWin->winPtr);\n    macWin->toplevel->referenceCount--;\n\n    if (!Tk_IsTopLevel(macWin->winPtr)) {\n\tif (macWin->winPtr->parentPtr != NULL) {\n\t    TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr);\n\t    Tcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask, (void *) view);\n\t    Tcl_DoWhenIdle(TkMacOSXRedrawViewIdleTask, (void *) view);\n\t}\n\tif (macWin->visRgn) {\n\t    CFRelease(macWin->visRgn);\n\t    macWin->visRgn = NULL;\n\t}\n\tif (macWin->aboveVisRgn) {\n\t    CFRelease(macWin->aboveVisRgn);\n\t    macWin->aboveVisRgn = NULL;\n\t}\n\tif (macWin->drawRgn) {\n\t    CFRelease(macWin->drawRgn);\n\t    macWin->drawRgn = NULL;\n\t}\n\n\tif (macWin->toplevel->referenceCount == 0) {\n\t    Tcl_Free(macWin->toplevel);\n\t}\n\tmacWin->winPtr->privatePtr = NULL;\n\tTcl_Free(macWin);\n\treturn Success;\n    }\n    if (macWin->visRgn) {\n\tCFRelease(macWin->visRgn);\n\tmacWin->visRgn = NULL;\n    }\n    if (macWin->aboveVisRgn) {\n\tCFRelease(macWin->aboveVisRgn);\n\tmacWin->aboveVisRgn = NULL;\n    }\n    if (macWin->drawRgn) {\n\tCFRelease(macWin->drawRgn);\n\tmacWin->drawRgn = NULL;\n    }\n    macWin->view = nil;\n    macWin->winPtr->privatePtr = NULL;\n\n    /*\n     * Delay deletion of a toplevel data structure until all children have\n     * been deleted.\n     */\n\n    if (macWin->toplevel->referenceCount == 0) {\n\tTcl_Free(macWin->toplevel);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMapWindow --\n *\n *\tThis X11 stub maps the given X11 Window but does not update any of\n *      the Tk structures describing the window.  Tk applications should\n *\tnever call this directly, but it is called by Tk_MapWindow and\n *      Tk_WmMapWindow.\n *\n * Results:\n *\tAlways returns Success or BadWindow.\n *\n * Side effects:\n *\tThe subwindow or toplevel may appear on the screen.  VisibilityNotify\n *      events are generated.\n *\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMapWindow(\n    Display *display,\t\t/* Display. */\n    Window window)\t\t/* Window. */\n{\n    if (!window) {\n\treturn BadWindow;\n    }\n    MacDrawable *macWin = (MacDrawable *)window;\n    static bool initialized = false;\n    NSPoint mouse = [NSEvent mouseLocation];\n    int x = mouse.x, y = TkMacOSXZeroScreenHeight() - mouse.y;\n    //fprintf(stderr, \"XMapWindow: %s\\n\", Tk_PathName(macWin->winPtr));\n\n    /*\n     * Under certain situations it's possible for this function to be called\n     * before the toplevel window it's associated with has actually been\n     * mapped. In that case we need to create the real Macintosh window now as\n     * this function as well as other X functions assume that the portPtr is\n     * valid.\n     */\n\n    if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) {\n\tTkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr);\n    }\n\n    TkWindow *winPtr = macWin->winPtr;\n    NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);\n    TKContentView *view = [win contentView];\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(winPtr)) {\n\tif (!Tk_IsEmbedded(winPtr)) {\n\n\t    /*\n\t     * We want to activate Tk when a toplevel is mapped but we can't\n\t     * always specify activateIgnoringOtherApps to be YES.  This is\n\t     * because during Tk initialization the root window is mapped\n\t     * before applicationDidFinishLaunching returns. Forcing the app to\n\t     * activate too early can make the menu bar unresponsive.\n\t     */\n\n\t    TkMacOSXApplyWindowAttributes(winPtr, win);\n\t    [win setExcludedFromWindowsMenu:NO];\n\t    [NSApp activateIgnoringOtherApps:initialized];\n\t    if (initialized) {\n\t\tif ([win canBecomeKeyWindow]) {\n\t\t    [win makeKeyAndOrderFront:NSApp];\n\t\t    [NSApp setTkEventTarget:TkMacOSXGetTkWindow(win)];\n\t\t} else {\n\t\t    [win orderFrontRegardless];\n\t\t}\n\n\t\t/*\n\t\t * Delay for up to 20 milliseconds until the toplevel has\n\t\t * actually become the highest toplevel.  This is to ensure\n\t\t * that the Visibility event occurs after the toplevel is\n\t\t * visible.\n\t\t */\n\n\t\tfor (int count = 0; count < 20; count++) {\n\t\t    if ([[NSApp orderedWindows] firstObject] == win) {\n\t\t\tbreak;\n\t\t    }\n\t\t    [NSThread sleepForTimeInterval:.001];\n\t\t}\n\t    }\n\n\t    /*\n\t     * Call Tk_UpdatePointer to tell Tk whether the pointer is in the\n\t     * new window.\n\t     */\n\n\t    NSPoint viewLocation = [view convertPoint:mouse fromView:nil];\n\t    if (NSPointInRect(viewLocation, NSInsetRect([view bounds], 2, 2))) {\n\t\tTk_UpdatePointer((Tk_Window) winPtr, x, y, [NSApp tkButtonState]);\n\t    }\n\t} else {\n\t    Tk_Window contWinPtr = Tk_GetOtherWindow((Tk_Window)winPtr);\n\n\t    /*\n\t     * Rebuild the container's clipping region and display\n\t     * the window.\n\t     */\n\n\t    TkMacOSXInvalClipRgns(contWinPtr);\n\t}\n    } else {\n\n\t/*\n\t * For non-toplevel windows, rebuild the parent's clipping region\n\t * and redisplay the window.\n\t */\n\n\tTkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);\n    }\n\n    /*\n     * If a geometry manager is mapping hundreds of windows we\n     * don't want to redraw the view hundreds of times, so do\n     * it in an idle task.\n     */\n\n    Tcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask, view);\n    Tcl_DoWhenIdle(TkMacOSXRedrawViewIdleTask, view);\n\n    /*\n     * Generate VisibilityNotify events for window and all mapped children.\n     */\n\n    if (initialized) {\n\tXEvent event;\n\tevent.xany.send_event = False;\n\tevent.xany.display = display;\n\tevent.xvisibility.type = VisibilityNotify;\n\tevent.xvisibility.state = VisibilityUnobscured;\n\tNotifyVisibility(winPtr, &event);\n    } else {\n\tinitialized = true;\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NotifyVisibility --\n *\n *\tHelper for XMapWindow().  Generates VisibilityNotify events\n *      for the window and all of its descendants.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tVisibilityNotify events are queued.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nNotifyVisibility(\n    TkWindow *winPtr,\n    XEvent *eventPtr)\n{\n    if (winPtr->atts.event_mask & VisibilityChangeMask) {\n\teventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display);\n\teventPtr->xvisibility.window = winPtr->window;\n\tTk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);\n    }\n    for (winPtr = winPtr->childList; winPtr != NULL;\n\t    winPtr = winPtr->nextPtr) {\n\tif (winPtr->flags & TK_MAPPED) {\n\t    NotifyVisibility(winPtr, eventPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUnmapWindow --\n *\n *\tThis X11 stub maps the given X11 Window but does not update any of\n *\tThe Tk structures describing the window.  Tk applications should\n *\tnever call this directly, but it is called by Tk_UnmapWindow and\n *      Tk_WmUnmapWindow.\n *\n * Results:\n *\tAlways returns Success or BadWindow.\n *\n * Side effects:\n *\tThe subwindow or toplevel may be removed from the screen.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUnmapWindow(\n    Display *display,\t\t/* Display. */\n    Window window)\t\t/* Window. */\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n    TkWindow *winPtr = macWin->winPtr;\n    NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);\n\n    if (!window) {\n\treturn BadWindow;\n    }\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(winPtr)) {\n\tif (!Tk_IsEmbedded(winPtr) &&\n\t    winPtr->wmInfoPtr->hints.initial_state!=IconicState) {\n\t    [win setExcludedFromWindowsMenu:YES];\n\t    [win orderOut:NSApp];\n\t    [[win contentView] setOnScreen:NO];\n\t    if ([win isKeyWindow]) {\n\n\t\t/*\n\t\t * If we are unmapping the key window then we need to make sure\n\t\t * that a new key window is assigned, if possible.  This is\n\t\t * supposed to happen when a key window is ordered out, but as\n\t\t * noted in tkMacOSXWm.c this does not happen, in spite of\n\t\t * Apple's claims to the contrary.\n\t\t */\n\n\t\tfor (NSWindow *w in [NSApp orderedWindows]) {\n\t\t    TkWindow *winPtr2 = TkMacOSXGetTkWindow(w);\n\t\t    WmInfo *wmInfoPtr;\n\n\t\t    BOOL isOnScreen;\n\n\t\t    if (!winPtr2 || !winPtr2->wmInfoPtr) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    wmInfoPtr = winPtr2->wmInfoPtr;\n\t\t    isOnScreen = (wmInfoPtr->hints.initial_state != IconicState &&\n\t\t\t\t  wmInfoPtr->hints.initial_state != WithdrawnState);\n\t\t    if (w != win && isOnScreen && [w canBecomeKeyWindow]) {\n\t\t\t[w makeKeyAndOrderFront:NSApp];\n\t\t\t[NSApp setTkEventTarget:TkMacOSXGetTkWindow(win)];\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tTkMacOSXInvalClipRgns((Tk_Window)winPtr);\n    } else {\n\n\t/*\n\t * Rebuild the clip regions for the parent so it will be allowed\n\t * to draw in the space from which this subwindow was removed and then\n\t * redraw the window.\n\t */\n\n\tTkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XResizeWindow --\n *\n *\tResize a given X window. See X windows documentation for further\n *\tdetails.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXResizeWindow(\n    Display *display,\t\t/* Display. */\n    Window window,\t\t/* Window. */\n    unsigned int width,\n    unsigned int height)\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {\n\tTKWindow *w = (TKWindow *)macWin->winPtr->wmInfoPtr->window;\n\n\tif (w) {\n\t    if ([w styleMask] & NSFullScreenWindowMask) {\n\t\t[(TKWindow *)w tkLayoutChanged];\n\t    } else {\n\t\tNSRect r = [w contentRectForFrameRect:[w frame]];\n\t\tr.origin.y += r.size.height - height;\n\t\tr.size.width = width;\n\t\tr.size.height = height;\n\t\t[w setFrame:[w frameRectForContentRect:r] display:NO];\n\t    }\n\t}\n    } else {\n\tMoveResizeWindow(macWin);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMoveResizeWindow --\n *\n *\tMove or resize a given X window. See X windows documentation for\n *\tfurther details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMoveResizeWindow(\n    Display *display,\t\t/* Display. */\n    Window window,\t\t/* Window. */\n    int x, int y,\n    unsigned int width,\n    unsigned int height)\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {\n\tNSWindow *w = macWin->winPtr->wmInfoPtr->window;\n\n\tif (w) {\n\t    /*\n\t     * We explicitly convert everything to doubles so we don't get\n\t     * surprised (again) by what happens when you do arithmetic with\n\t     * unsigned ints.\n\t     */\n\n\t    CGFloat X = (CGFloat) x;\n\t    CGFloat Y = (CGFloat) y;\n\t    CGFloat Width = (CGFloat) width;\n\t    CGFloat Height = (CGFloat) height;\n\t    CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent;\n\t    CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent;\n\t    NSRect r = NSMakeRect(\n\t\t    X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height,\n\t\t    Width, Height);\n\n\t    [w setFrame:[w frameRectForContentRect:r] display:NO];\n\t}\n    } else {\n\tMoveResizeWindow(macWin);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMoveWindow --\n *\n *\tMove a given X window. See X windows documentation for further details.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMoveWindow(\n    Display *display,\t\t/* Display. */\n    Window window,\t\t/* Window. */\n    int x, int y)\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {\n\tNSWindow *w = macWin->winPtr->wmInfoPtr->window;\n\n\tif (w) {\n\t    [w setFrameTopLeftPoint: NSMakePoint(\n\t\t    x, TkMacOSXZeroScreenHeight() - y)];\n\t}\n    } else {\n\tMoveResizeWindow(macWin);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MoveResizeWindow --\n *\n *\tHelper proc for XResizeWindow, XMoveResizeWindow and XMoveWindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMoveResizeWindow(\n    MacDrawable *macWin)\n{\n    int deltaX = 0, deltaY = 0, parentBorderwidth = 0;\n    MacDrawable *macParent = NULL;\n    NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable((Drawable)macWin);\n\n    /*\n     * Find the Parent window, for an embedded window it will be its container.\n     */\n\n    if (Tk_IsEmbedded(macWin->winPtr)) {\n\tTkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)macWin->winPtr);\n\n\tif (contWinPtr) {\n\t    macParent = contWinPtr->privatePtr;\n\t} else {\n\t    /*\n\t     * Here we should handle out of process embedding. At this point,\n\t     * we are assuming that the changes.x,y is not maintained, if you\n\t     * need the info get it from Tk_GetRootCoords, and that the\n\t     * toplevel sits at 0,0 when it is drawn.\n\t     */\n\t}\n    } else {\n\t/*\n\t * TODO: update all xOff & yOffs\n\t */\n\n\tmacParent = macWin->winPtr->parentPtr->privatePtr;\n\tparentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;\n    }\n\n    if (macParent) {\n\tdeltaX = macParent->xOff + parentBorderwidth +\n\t\tmacWin->winPtr->changes.x - macWin->xOff;\n\tdeltaY = macParent->yOff + parentBorderwidth +\n\t\tmacWin->winPtr->changes.y - macWin->yOff;\n    }\n    if (macWindow) {\n\tTkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);\n\tif (macParent) {\n\t    TkMacOSXInvalClipRgns((Tk_Window)macParent->winPtr);\n\t}\n    }\n    UpdateOffsets(macWin->winPtr, deltaX, deltaY);\n    if (macWindow) {\n\tTkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);\n    }\n    GenerateConfigureNotify(macWin->winPtr, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateConfigureNotify --\n *\n *\tGenerates ConfigureNotify events for all the child widgets of the\n *\twidget passed in the winPtr parameter. If includeWin is true, also\n *\tgenerates ConfigureNotify event for the widget itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfigureNotify events will be posted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateConfigureNotify(\n    TkWindow *winPtr,\n    int includeWin)\n{\n    TkWindow *childPtr;\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tif (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {\n\t    continue;\n\t}\n\tGenerateConfigureNotify(childPtr, 1);\n    }\n    if (includeWin) {\n\tTkDoConfigureNotify(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XRaiseWindow --\n *\n *\tChange the stacking order of a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the stacking order of the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXRaiseWindow(\n    Display *display,\t\t/* Display. */\n    Window window)\t\t/* Window. */\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {\n\tTkWmRestackToplevel(macWin->winPtr, Above, NULL);\n    } else {\n\t/*\n\t * TODO: this should generate damage\n\t */\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XLowerWindow --\n *\n *\tChange the stacking order of a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the stacking order of the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXLowerWindow(\n    Display *display,\t\t/* Display. */\n    Window window)\t\t/* Window. */\n{\n    MacDrawable *macWin = (MacDrawable *)window;\n\n    LastKnownRequestProcessed(display)++;\n    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {\n\tTkWmRestackToplevel(macWin->winPtr, Below, NULL);\n    } else {\n\t/*\n\t * TODO: this should generate damage\n\t */\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XConfigureWindow --\n *\n *\tChange the size, position, stacking, or border of the specified window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the attributes of the specified window. Note that we ignore the\n *\tpassed in values and use the values stored in the TkWindow data\n *\tstructure.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXConfigureWindow(\n    Display *display,\t\t/* Display. */\n    Window w,\t\t\t/* Window. */\n    unsigned int value_mask,\n    TCL_UNUSED(XWindowChanges *))\n{\n    MacDrawable *macWin = (MacDrawable *)w;\n    TkWindow *winPtr = macWin->winPtr;\n\n    LastKnownRequestProcessed(display)++;\n\n    /*\n     * Change the shape and/or position of the window.\n     */\n\n    if (value_mask & (CWX|CWY|CWWidth|CWHeight)) {\n\tXMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y,\n\t\twinPtr->changes.width, winPtr->changes.height);\n    }\n\n    /*\n     * Change the stacking order of the window. Tk actually keeps all the\n     * information we need for stacking order. All we need to do is make sure\n     * the clipping regions get updated and generate damage that will ensure\n     * things get drawn correctly.\n     */\n\n    if (value_mask & CWStackMode) {\n\tNSView *view = TkMacOSXGetNSViewForDrawable(macWin);\n\n\tif (view) {\n\t    TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);\n\t}\n    }\n\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXUpdateClipRgn --\n *\n *\tThis function updates the clipping regions for a given window and all of\n *\tits children. Once updated the TK_CLIP_INVALID flag in the subwindow\n *\tdata structure is unset. The TK_CLIP_INVALID flag should always be\n *\tunset before any drawing is attempted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe clip regions for the window and its children are updated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXUpdateClipRgn(\n    TkWindow *winPtr)\n{\n    MacDrawable *macWin;\n\n    if (winPtr == NULL) {\n\treturn;\n    }\n    macWin = winPtr->privatePtr;\n    if (macWin && macWin->flags & TK_CLIP_INVALID) {\n\tTkWindow *win2Ptr;\n\n#ifdef TK_MAC_DEBUG_CLIP_REGIONS\n\tTkMacOSXDbgMsg(\"%s\", winPtr->pathName);\n#endif\n\tif (Tk_IsMapped(winPtr)) {\n\t    int rgnChanged = 0;\n\t    CGRect bounds;\n\t    HIMutableShapeRef rgn;\n\n\t    /*\n\t     * Start with a region defined by the window bounds.\n\t     */\n\n\t    TkMacOSXWinCGBounds(winPtr, &bounds);\n\t    rgn = HIShapeCreateMutableWithRect(&bounds);\n\n\t    /*\n\t     * Clip away the area of any windows that may obscure this window.\n\t     * For a non-toplevel window, first, clip to the parent's visible\n\t     * clip region. Second, clip away any siblings that are higher in\n\t     * the stacking order. For an embedded toplevel, just clip to the\n\t     * container's visible clip region. Remember, we only allow one\n\t     * contained window in a frame, and don't support any other widgets\n\t     * in the frame either. This is not currently enforced, however.\n\t     */\n\n\t    if (!Tk_IsTopLevel(winPtr)) {\n\t\tif (winPtr->parentPtr) {\n\t\t    TkMacOSXUpdateClipRgn(winPtr->parentPtr);\n\t\t    ChkErr(HIShapeIntersect,\n\t\t\t    winPtr->parentPtr->privatePtr->aboveVisRgn,\n\t\t\t    rgn, rgn);\n\t\t}\n\t\twin2Ptr = winPtr;\n\t\twhile ((win2Ptr = win2Ptr->nextPtr)) {\n\t\t    if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {\n\t\t\tcontinue;\n\t\t    }\n\t\t    TkMacOSXWinCGBounds(win2Ptr, &bounds);\n\t\t    ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);\n\t\t}\n\t    } else if (Tk_IsEmbedded(winPtr)) {\n\t\twin2Ptr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t\tif (win2Ptr) {\n\t\t    TkMacOSXUpdateClipRgn(win2Ptr);\n\t\t    ChkErr(HIShapeIntersect,\n\t\t\t    win2Ptr->privatePtr->aboveVisRgn, rgn, rgn);\n\t\t}\n\n\t\t/*\n\t\t * TODO: Here we should handle out of process embedding.\n\t\t */\n\t    }\n\t    macWin->aboveVisRgn = HIShapeCreateCopy(rgn);\n\n\t    /*\n\t     * The final clip region is the aboveVis region (or visible region)\n\t     * minus all the children of this window. If the window is a\n\t     * container, we must also subtract the region of the embedded\n\t     * window.\n\t     */\n\n\t    win2Ptr = winPtr->childList;\n\t    while (win2Ptr) {\n\t\tif (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {\n\t\t    win2Ptr = win2Ptr->nextPtr;\n\t\t    continue;\n\t\t}\n\t\tTkMacOSXWinCGBounds(win2Ptr, &bounds);\n\t\tChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);\n\t\trgnChanged = 1;\n\t\twin2Ptr = win2Ptr->nextPtr;\n\t    }\n\n\t    if (Tk_IsContainer(winPtr)) {\n\t\twin2Ptr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t\tif (win2Ptr) {\n\t\t    if (Tk_IsMapped(win2Ptr)) {\n\t\t\tTkMacOSXWinCGBounds(win2Ptr, &bounds);\n\t\t\tChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);\n\t\t\trgnChanged = 1;\n\t\t    }\n\t\t}\n\n\t\t/*\n\t\t * TODO: Here we should handle out of process embedding.\n\t\t */\n\t    }\n\n\t    if (rgnChanged) {\n\t\tHIShapeRef diffRgn = HIShapeCreateDifference(\n\t\t\tmacWin->aboveVisRgn, rgn);\n\n\t\tif (!HIShapeIsEmpty(diffRgn)) {\n\t\t    macWin->visRgn = HIShapeCreateCopy(rgn);\n\t\t}\n\t\tCFRelease(diffRgn);\n\t    }\n\t    CFRelease(rgn);\n\t} else {\n\t    /*\n\t     * An unmapped window has empty clip regions to prevent any\n\t     * (erroneous) drawing into it or its children from becoming\n\t     * visible. [Bug 940117]\n\t     */\n\n\t    if (!Tk_IsTopLevel(winPtr)) {\n\t\tTkMacOSXUpdateClipRgn(winPtr->parentPtr);\n\t    } else if (Tk_IsEmbedded(winPtr)) {\n\t\twin2Ptr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t\tif (win2Ptr) {\n\t\t    TkMacOSXUpdateClipRgn(win2Ptr);\n\t\t}\n\t    }\n\t    macWin->aboveVisRgn = HIShapeCreateEmpty();\n\t}\n\tif (!macWin->visRgn) {\n\t    macWin->visRgn = HIShapeCreateCopy(macWin->aboveVisRgn);\n\t}\n\tmacWin->flags &= ~TK_CLIP_INVALID;\n    }\n}\n\f\n// Unused and misspelled stub function\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXVisableClipRgn --\n *\n *\tThis function returns the Macintosh clipping region for the given\n *\twindow. The caller is responsible for disposing of the returned region\n *\tvia XDestroyRegion().\n *\n * Results:\n *\tThe region.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nRegion\nTkMacOSXVisableClipRgn(\n    TkWindow *winPtr)\n{\n    if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {\n\tTkMacOSXUpdateClipRgn(winPtr);\n    }\n    return (Region) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);\n}\n\f\n#if 0\n//This code is not currently used.  But it shows how to iterate over the\n//rectangles in a region described by an HIShape.\n\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInvalidateViewRegion --\n *\n *\tThis function invalidates the given region of a view.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDamage is created.\n *\n *----------------------------------------------------------------------\n */\n\nstatic OSStatus\nInvalViewRect(\n    int msg,\n    TCL_UNUSED(HIShapeRef),\n    const CGRect *rect,\n    void *ref)\n{\n    static CGAffineTransform t;\n    TKContentView *view = (TKContentView *)ref;\n    NSRect dirtyRect;\n\n    if (!view) {\n\treturn paramErr;\n    }\n    switch (msg) {\n    case kHIShapeEnumerateInit:\n\tt = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0,\n\t\tNSHeight([view bounds]));\n\tbreak;\n    case kHIShapeEnumerateRect:\n\tdirtyRect = NSRectFromCGRect(CGRectApplyAffineTransform(*rect, t));\n\tbreak;\n    }\n    [view generateExposeEvents:[view bounds]];\n    return noErr;\n}\n\nvoid\nTkMacOSXInvalidateViewRegion(\n    NSView *view,\n    HIShapeRef rgn)\n{\n    if (view && !HIShapeIsEmpty(rgn)) {\n\tChkErr(HIShapeEnumerate, rgn,\n\t\tkHIShapeParseFromBottom|kHIShapeParseFromLeft,\n\t\tInvalViewRect, view);\n    }\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInvalidateWindow --\n *\n *\tThis stub function redraws the part of the toplevel window\n *      covered by a given Tk window.  (Except currently it redraws\n *      the entire toplevel.)\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is redrawn.\n *\n *----------------------------------------------------------------------\n */\nvoid\nTkMacOSXRedrawViewIdleTask(\n    void *clientData)\n{\n    TKContentView *view = (TKContentView *) clientData;\n    //    fprintf(stderr, \"idle redraw for %p\\n\", view);\n    [view generateExposeEvents:[view bounds]];\n}\n\nvoid\nTkMacOSXInvalidateWindow(\n    MacDrawable *macWin,\t/* Window to be invalidated. */\n    int flag)\t\t\t/* Should be TK_WINDOW_ONLY or\n\t\t\t\t * TK_PARENT_WINDOW */\n{\n#ifdef TK_MAC_DEBUG_CLIP_REGIONS\n    TkMacOSXDbgMsg(\"%s\", macWin->winPtr->pathName);\n#endif\n    TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macWin);\n    TkWindow *winPtr = macWin->winPtr;\n    Tk_Window tkwin = (Tk_Window) winPtr;\n    Tk_Window parent = (Tk_Window) winPtr->parentPtr;\n    TkMacOSXInvalClipRgns(tkwin);\n    if ((flag == TK_PARENT_WINDOW) && parent){\n\tTkMacOSXInvalClipRgns(parent);\n    }\n    [view generateExposeEvents:[view bounds]];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNSWindowForDrawable --\n *\n *\tThis function returns the NSWindow for a given X drawable, if the\n *      drawable is a window.  If the drawable is a pixmap it returns nil.\n *\n * Results:\n *\tA NSWindow, or nil for off screen pixmaps.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid *\nTk_MacOSXGetNSWindowForDrawable(\n    Drawable drawable)\n{\n    MacDrawable *macWin = (MacDrawable *)drawable;\n    NSWindow *result = nil;\n\n    if (!macWin || macWin->flags & TK_IS_PIXMAP) {\n\tresult = nil;\n\n    } else if (macWin->toplevel && macWin->toplevel->winPtr &&\n\t    macWin->toplevel->winPtr->wmInfoPtr &&\n\t    macWin->toplevel->winPtr->wmInfoPtr->window) {\n\tresult = macWin->toplevel->winPtr->wmInfoPtr->window;\n\n    } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr &&\n\t    macWin->winPtr->wmInfoPtr->window) {\n\tresult = macWin->winPtr->wmInfoPtr->window;\n\n    } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) {\n\tTkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)macWin->toplevel->winPtr);\n\tif (contWinPtr && contWinPtr->privatePtr) {\n\t    result = TkMacOSXGetNSWindowForDrawable((Drawable)contWinPtr->privatePtr);\n\t}\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetNSViewForDrawable/TkMacOSXGetRootControl --\n *\n *\tThe function name TkMacOSXGetRootControl is being preserved only\n *      because it exists in a stubs table.  Nobody knows what it means to\n *      get a \"RootControl\".  The macro TkMacOSXGetNSViewForDrawable calls\n *      this function and should always be used rather than directly using\n *      the obscure official name of this function.\n *\n *      It returns the NSView for a given X drawable in the case that the\n *      drawable is a window.  If the drawable is a pixmap it returns nil.\n *\n * Results:\n *\tA NSView* or nil.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid *\nTkMacOSXGetRootControl(\n    Drawable drawable)\n{\n    void *result = NULL;\n    MacDrawable *macWin = (MacDrawable *)drawable;\n\n    if (!macWin) {\n\tresult = NULL;\n    } else if (!macWin->toplevel) {\n\tresult = macWin->view;\n    } else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {\n\tresult = macWin->toplevel->view;\n    } else {\n\tTkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)macWin->toplevel->winPtr);\n\n\tif (contWinPtr) {\n\t    result = TkMacOSXGetRootControl((Drawable)contWinPtr->privatePtr);\n\t}\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXInvalClipRgns --\n *\n *\tThis function invalidates the clipping regions for a given window and\n *\tall of its children. This function should be called whenever changes\n *\tare made to subwindows that would affect the size or position of\n *\twindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe clipping regions for the window and its children are marked invalid.\n *\t(Make sure they are valid before drawing.)\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXInvalClipRgns(\n    Tk_Window tkwin)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *childPtr;\n    MacDrawable *macWin = winPtr->privatePtr;\n\n    /*\n     * If already marked we can stop because all descendants will also already\n     * be marked.\n     */\n\n#ifdef TK_MAC_DEBUG_CLIP_REGIONS\n\tTkMacOSXDbgMsg(\"%s\", winPtr->pathName);\n#endif\n\n    if (!macWin || macWin->flags & TK_CLIP_INVALID) {\n\treturn;\n    }\n\n    macWin->flags |= TK_CLIP_INVALID;\n    if (macWin->visRgn) {\n\tCFRelease(macWin->visRgn);\n\tmacWin->visRgn = NULL;\n    }\n    if (macWin->aboveVisRgn) {\n\tCFRelease(macWin->aboveVisRgn);\n\tmacWin->aboveVisRgn = NULL;\n    }\n    if (macWin->drawRgn) {\n\tCFRelease(macWin->drawRgn);\n\tmacWin->drawRgn = NULL;\n    }\n\n    /*\n     * Invalidate clip regions for all children & their descendants, unless the\n     * child is a toplevel.\n     */\n\n    childPtr = winPtr->childList;\n    while (childPtr) {\n\tif (!Tk_IsTopLevel(childPtr)) {\n\t    TkMacOSXInvalClipRgns((Tk_Window)childPtr);\n\t}\n\tchildPtr = childPtr->nextPtr;\n    }\n\n    /*\n     * Also, if the window is a container, mark its embedded window.\n     */\n\n    if (Tk_IsContainer(winPtr)) {\n\tchildPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\n\tif (childPtr) {\n\t    TkMacOSXInvalClipRgns((Tk_Window)childPtr);\n\t}\n\n\t/*\n\t * TODO: Here we should handle out of process embedding.\n\t */\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXWinBounds --\n *\n *\tGiven a Tk window this function determines the window's bounds in\n *\trelation to the Macintosh window's coordinate system. This is also the\n *\tsame coordinate system as the Tk toplevel window in which this window\n *\tis contained.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFills in a Rect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXWinBounds(\n    TkWindow *winPtr,\n    void *bounds)\n{\n    Rect *b = (Rect *) bounds;\n\n    b->left = winPtr->privatePtr->xOff;\n    b->top = winPtr->privatePtr->yOff;\n    b->right = b->left + winPtr->changes.width;\n    b->bottom = b->top + winPtr->changes.height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXWinCGBounds --\n *\n *\tGiven a Tk window this function determines the window's bounds in\n *\tthe coordinate system of the Tk toplevel window in which this window\n *\tis contained.  This fills in a CGRect struct.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFill in a CGRect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXWinCGBounds(\n    TkWindow *winPtr,\n    CGRect *bounds)\n{\n    bounds->origin.x = winPtr->privatePtr->xOff;\n    bounds->origin.y = winPtr->privatePtr->yOff;\n    bounds->size.width = winPtr->changes.width;\n    bounds->size.height = winPtr->changes.height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateOffsets --\n *\n *\tUpdates the X & Y offsets of the given TkWindow from the TopLevel it is\n *\ta descendant of.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe xOff & yOff fields for the Mac window datastructure is updated to\n *\tthe proper offset.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateOffsets(\n    TkWindow *winPtr,\n    int deltaX,\n    int deltaY)\n{\n    TkWindow *childPtr;\n\n    if (winPtr->privatePtr == NULL) {\n\t/*\n\t * We haven't called Tk_MakeWindowExist for this window yet. The offset\n\t * information will be postponed and calulated at that time. (This will\n\t * usually only happen when a mapped parent is being moved but has\n\t * child windows that have yet to be mapped.)\n\t */\n\n\treturn;\n    }\n\n    winPtr->privatePtr->xOff += deltaX;\n    winPtr->privatePtr->yOff += deltaY;\n\n    childPtr = winPtr->childList;\n    while (childPtr != NULL) {\n\tif (!Tk_IsTopLevel(childPtr)) {\n\t    UpdateOffsets(childPtr, deltaX, deltaY);\n\t}\n\tchildPtr = childPtr->nextPtr;\n    }\n\n    if (Tk_IsContainer(winPtr)) {\n\tchildPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\tif (childPtr != NULL) {\n\t    UpdateOffsets(childPtr,deltaX,deltaY);\n\t}\n\n\t/*\n\t * TODO: Here we should handle out of process embedding.\n\t */\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetPixmap --\n *\n *\tCreates an in memory drawing surface.\n *\n * Results:\n *\tReturns a handle to a new pixmap.\n *\n * Side effects:\n *\tAllocates a new CGBitmapContext.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetPixmap(\n    Display *display,\t/* Display for new pixmap (can be null). */\n    TCL_UNUSED(Drawable),\t\t/* Drawable where pixmap will be used (ignored). */\n    int width,\t\t/* Dimensions of pixmap. */\n    int height,\n    int depth)\t\t/* Bits per pixel for pixmap. */\n{\n    MacDrawable *macPix;\n\n    if (display != NULL) {\n\tLastKnownRequestProcessed(display)++;\n    }\n    macPix = (MacDrawable *)Tcl_Alloc(sizeof(MacDrawable));\n    macPix->winPtr = NULL;\n    macPix->xOff = 0;\n    macPix->yOff = 0;\n    macPix->visRgn = NULL;\n    macPix->aboveVisRgn = NULL;\n    macPix->drawRgn = NULL;\n    macPix->referenceCount = 0;\n    macPix->toplevel = NULL;\n    macPix->flags = TK_IS_PIXMAP | (depth == 1 ? TK_IS_BW_PIXMAP : 0);\n    macPix->view = nil;\n    macPix->context = NULL;\n    macPix->size = CGSizeMake(width, height);\n\n    return (Pixmap) macPix;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreePixmap --\n *\n *\tRelease the resources associated with a pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeletes the CGBitmapContext created by Tk_GetPixmap.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreePixmap(\n    Display *display,\t\t/* Display. */\n    Pixmap pixmap)\t\t/* Pixmap to destroy */\n{\n    MacDrawable *macPix = (MacDrawable *)pixmap;\n\n    LastKnownRequestProcessed(display)++;\n    if (macPix->context) {\n\tCFRelease(macPix->context);\n    }\n    Tcl_Free(macPix);\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXSysTray.c",
    "content": "/*\n * tkMacOSXSysTray.c --\n *\n *\ttkMacOSXSysTray.c implements a \"systray\" Tcl command which allows\n *      one to change the system tray/taskbar icon of a Tk toplevel\n *      window and a \"sysnotify\" command to post system notifications.\n *      In macOS the icon appears on the right hand side of the menu bar.\n *\n * Copyright © 2020 Kevin Walzer\n * Copyright © 2020 Jan Nijtmans\n * Copyright © 2020 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include <tkInt.h>\n#include <tkMacOSXInt.h>\n#include \"tkMacOSXPrivate.h\"\n\n/*\n * Class declaration for TkStatusItem.\n */\n\n@interface TkStatusItem: NSObject {\n    NSStatusItem * statusItem;\n    NSStatusBar * statusBar;\n    NSImage * icon;\n    NSString * tooltip;\n    Tcl_Interp * interp;\n    Tcl_Obj * b1_callback;\n    Tcl_Obj * b3_callback;\n}\n\n- (id) init : (Tcl_Interp *) interp;\n- (void) setImagewithImage : (NSImage *) image;\n- (void) setTextwithString : (NSString *) string;\n- (void) setB1Callback : (Tcl_Obj *) callback;\n- (void) setB3Callback : (Tcl_Obj *) callback;\n- (void) clickOnStatusItem;\n- (void) dealloc;\n\n@end\n\n\n\n/*\n * Class declaration for TkStatusItem. A TkStatusItem represents an icon posted\n * on the status bar located on the right side of the MenuBar.  Each interpreter\n * may have at most one TkStatusItem.  A pointer to the TkStatusItem belonging\n * to an interpreter is stored as the clientData of the MacSystrayObjCmd instance\n * in that interpreter.  It will be NULL until the tk systray command is executed\n * by the interpreter.\n */\n\n@implementation TkStatusItem : NSObject\n\n- (id) init : (Tcl_Interp *) interpreter {\n    [super init];\n    statusBar = [NSStatusBar systemStatusBar];\n    statusItem = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain];\n    statusItem.button.target = self;\n    statusItem.button.action = @selector(clickOnStatusItem);\n    [statusItem.button sendActionOn : NSEventMaskLeftMouseUp | NSEventMaskRightMouseUp];\n    statusItem.visible = YES;\n    interp = interpreter;\n    b1_callback = NULL;\n    b3_callback = NULL;\n    return self;\n}\n\n- (void) setImagewithImage : (NSImage *) image\n{\n    icon = nil;\n    icon = image;\n    statusItem.button.image = icon;\n}\n\n- (void) setTextwithString : (NSString *) string\n{\n    tooltip = nil;\n    tooltip = string;\n    statusItem.button.toolTip = tooltip;\n}\n\n- (void) setB1Callback : (Tcl_Obj *) obj\n{\n    if (obj != NULL) {\n\tTcl_IncrRefCount(obj);\n    }\n    if (b1_callback != NULL) {\n\tTcl_DecrRefCount(b1_callback);\n    }\n    b1_callback = obj;\n}\n\n- (void) setB3Callback : (Tcl_Obj *) obj\n{\n    if (obj != NULL) {\n\tTcl_IncrRefCount(obj);\n    }\n    if (b3_callback != NULL) {\n\tTcl_DecrRefCount(b3_callback);\n    }\n    b3_callback = obj;\n}\n\n- (void) clickOnStatusItem\n{\n    NSEvent *event = [NSApp currentEvent];\n    if (([event type] == NSEventTypeLeftMouseUp) && (b1_callback != NULL)) {\n\tint result = Tcl_EvalObjEx(interp, b1_callback, TCL_EVAL_GLOBAL);\n\tif (result != TCL_OK) {\n\t    Tcl_BackgroundException(interp, result);\n\t}\n    } else {\n\tif (([event type] == NSEventTypeRightMouseUp) && (b3_callback != NULL)) {\n\t    int result = Tcl_EvalObjEx(interp, b3_callback, TCL_EVAL_GLOBAL);\n\t    if (result != TCL_OK) {\n\t\tTcl_BackgroundException(interp, result);\n\t    }\n\t}\n    }\n}\n- (void) dealloc\n{\n    [statusBar removeStatusItem: statusItem];\n    if (b1_callback != NULL) {\n\tTcl_DecrRefCount(b1_callback);\n    }\n    if (b3_callback != NULL) {\n\tTcl_DecrRefCount(b3_callback);\n    }\n    [super dealloc];\n}\n\n@end\n\n/*\n * Type used for the ClientData of a MacSystrayObjCmd instance.\n */\n\ntypedef TkStatusItem** StatusItemInfo;\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * MacSystrayDestroy --\n *\n *\tRemoves an intepreters icon from the status bar.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe icon is removed and memory is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMacSystrayDestroy(\n    void *clientData)\n{\n    StatusItemInfo info = (StatusItemInfo)clientData;\n    if (info) {\n\t[*info release];\n\tTcl_Free(info);\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * MacSystrayObjCmd --\n *\n *\tMain command for creating, displaying, and removing icons from the\n *\tstatus bar.\n *\n * Results:\n *\n *      A standard Tcl result.\n *\n * Side effects:\n *\n *\tManagement of icon display in the status bar.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nMacSystrayObjCmd(\n    void *clientData,\n    Tcl_Interp * interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    Tk_Image tk_image;\n    int result, idx;\n    static const char *options[] =\n\t{\"create\", \"modify\", \"destroy\", NULL};\n    typedef enum {TRAY_CREATE, TRAY_MODIFY, TRAY_DESTROY} optionsEnum;\n    static const char *modifyOptions[] =\n\t{\"image\", \"text\", \"b1_callback\", \"b3_callback\", NULL};\n    typedef enum {TRAY_IMAGE, TRAY_TEXT, TRAY_B1_CALLBACK, TRAY_B3_CALLBACK\n\t} modifyOptionsEnum;\n\n    if ([NSApp macOSVersion] < 101000) {\n\tTcl_AppendResult(interp,\n\t    \"StatusItem icons not supported on macOS versions lower than 10.10\",\n\t    NULL);\n\treturn TCL_OK;\n    }\n\n    StatusItemInfo info = (StatusItemInfo)clientData;\n    TkStatusItem *statusItem = *info;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"create | modify | destroy\");\n\treturn TCL_ERROR;\n    }\n\n    result = Tcl_GetIndexFromObjStruct(interp, objv[1], options,\n\t\t\t\t       sizeof(char *), \"command\", 0, &idx);\n\n    if (result != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch((optionsEnum)idx) {\n    case TRAY_CREATE: {\n\n\tif (objc < 3 ||  objc > 6) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"create -image -text -button1 -button3\");\n\t    return TCL_ERROR;\n\t}\n\n\tif (statusItem == NULL) {\n\t    statusItem = [[TkStatusItem alloc] init: interp];\n\t    *info = statusItem;\n\t} else {\n\t    Tcl_AppendResult(interp, \"Only one system tray icon supported per interpreter\", NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Create the icon.\n\t */\n\n\tint width, height;\n\tTk_Window tkwin = Tk_MainWindow(interp);\n\tTkWindow *winPtr = (TkWindow *)tkwin;\n\tDisplay *d = winPtr->display;\n\tNSImage *icon;\n\n\ttk_image = Tk_GetImage(interp, tkwin, Tcl_GetString(objv[2]), NULL, NULL);\n\tif (tk_image == NULL) {\n\t    return TCL_ERROR;\n\t}\n\n\tTk_SizeOfImage(tk_image, &width, &height);\n\tif (width != 0 && height != 0) {\n\t    icon = TkMacOSXGetNSImageFromTkImage(d, tk_image,\n\t\t\t\t\t\t width, height);\n\t    [statusItem setImagewithImage: icon];\n\t    Tk_FreeImage(tk_image);\n\t}\n\n\t/*\n\t * Set the text for the tooltip.\n\t */\n\n\tNSString *tooltip = [NSString stringWithUTF8String: Tcl_GetString(objv[3])];\n\tif (tooltip == nil) {\n\t    Tcl_AppendResult(interp, \" unable to set tooltip for systray icon\", NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t[statusItem setTextwithString: tooltip];\n\n\t/*\n\t * Set the proc for the callback.\n\t */\n\n\t[statusItem setB1Callback : (objc > 4) ? objv[4] : NULL];\n\t[statusItem setB3Callback : (objc > 5) ? objv[5] : NULL];\n\tbreak;\n\n    }\n    case TRAY_MODIFY: {\n\tif (objc != 4) {\n\t    Tcl_WrongNumArgs(interp, 1, objv, \"modify object item\");\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Modify the icon.\n\t */\n\n\tresult = Tcl_GetIndexFromObjStruct(interp, objv[2], modifyOptions,\n\t\t\t\t\t   sizeof(char *), \"option\", 0, &idx);\n\n\tif (result != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((modifyOptionsEnum)idx) {\n\tcase TRAY_IMAGE: {\n\t    Tk_Window tkwin = Tk_MainWindow(interp);\n\t    TkWindow *winPtr = (TkWindow *)tkwin;\n\t    Display *d = winPtr -> display;\n\t    NSImage *icon;\n\t    int width, height;\n\n\t    tk_image = Tk_GetImage(interp, tkwin, Tcl_GetString(objv[3]), NULL, NULL);\n\t    if (tk_image == NULL) {\n\t\tTcl_AppendResult(interp, \" unable to obtain image for systray icon\",\n\t\t\t\t NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    Tk_SizeOfImage(tk_image, &width, &height);\n\t    if (width != 0 && height != 0) {\n\t\ticon = TkMacOSXGetNSImageFromTkImage(d, tk_image,\n\t\t\t\t\t\t     width, height);\n\t\t[statusItem setImagewithImage: icon];\n\t    }\n\t    Tk_FreeImage(tk_image);\n\t    break;\n\t}\n\n\t/*\n\t * Modify the text for the tooltip.\n\t */\n\n\tcase TRAY_TEXT: {\n\t    NSString *tooltip = [NSString stringWithUTF8String:Tcl_GetString(objv[3])];\n\t    if (tooltip == nil) {\n\t\tTcl_AppendResult(interp, \"unable to set tooltip for systray icon\",\n\t\t\t\t NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    [statusItem setTextwithString: tooltip];\n\t    break;\n\t}\n\n\t/*\n\t * Modify the proc for the callback.\n\t */\n\n\tcase TRAY_B1_CALLBACK: {\n\t    [statusItem setB1Callback : objv[3]];\n\t    break;\n\t}\n\tcase TRAY_B3_CALLBACK: {\n\t    [statusItem setB3Callback : objv[3]];\n\t    break;\n\t}\n    }\n    break;\n    }\n\n    case TRAY_DESTROY: {\n\t/*\n\t * Set all properties to nil, and release statusItem.\n\t */\n\t[statusItem setImagewithImage: nil];\n\t[statusItem setTextwithString: nil];\n\t[statusItem setB1Callback : NULL];\n\t[statusItem setB3Callback : NULL];\n\t[statusItem release];\n\t*info = NULL;\n\tstatusItem = NULL;\n\tbreak;\n    }\n    }\n\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * SysNotifyObjCmd --\n *\n *      Create system notification.\n *\n * Results:\n *\n *      A standard Tcl result.\n *\n * Side effects:\n *\n *      System notifications are posted.\n *\n *-------------------------------z---------------------------------------\n */\n\nstatic int SysNotifyObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp * interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"title message\");\n\treturn TCL_ERROR;\n    }\n\n    if ([NSApp macOSVersion] < 101000) {\n\tTcl_AppendResult(interp,\n\t    \"Notifications not supported on macOS versions lower than 10.10\",\n\t     NULL);\n\treturn TCL_OK;\n    }\n\n    /*\n     * Using NSAppleScript API here allows us to use a single API rather\n     * than multiple, some deprecated, API's, and also allows notifications\n     * to work correctly without requiring Wish to be code-signed - an\n     * undocumented but apparently consistent requirement. And by calling\n     * NSAppleScript inline rather than shelling to out osascript,\n     * Wish shows correctly as the calling app rather than Script Editor.\n     */\n\n    NSString *title = [NSString stringWithUTF8String: Tcl_GetString(objv[1])];\n    NSString *message = [NSString stringWithUTF8String: Tcl_GetString(objv[2])];\n    NSMutableString *notify = [NSMutableString new];\n    [notify appendString: @\"display notification \"];\n    [notify appendString:@\"\\\"\"];\n    [notify appendString:message];\n    [notify appendString:@\"\\\"\"];\n    [notify appendString:@\" with title \\\"\"];\n    [notify appendString:title];\n    [notify appendString:@\"\\\"\"];\n    NSAppleScript *scpt = [[[NSAppleScript alloc] initWithSource:notify] autorelease];\n    NSDictionary *errorInfo;\n    NSAppleEventDescriptor *result = [scpt executeAndReturnError:&errorInfo];\n    NSString *info = [result stringValue];\n    const char* output = [info UTF8String];\n\n    Tcl_AppendResult(interp,\n\t\t     output,\n\t\t     NULL);\n\n    return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * MacSystrayInit --\n *\n *\tInitialize this package and create script-level commands.\n *      This is called from TkpInit for each interpreter.\n *\n * Results:\n *\n *      A standard Tcl result.\n *\n * Side effects:\n *\n *\tThe tk systray and tk sysnotify commands are installed in an\n *\tinterpreter\n *\n *----------------------------------------------------------------------\n */\n\nint\nMacSystrayInit(Tcl_Interp *interp)\n{\n\n    /*\n     * Initialize the TkStatusItem for this interpreter.\n     */\n\n    StatusItemInfo info = (StatusItemInfo)Tcl_Alloc(sizeof(StatusItemInfo));\n    *info = 0;\n\n    Tcl_CreateObjCommand2(interp, \"::tk::systray::_systray\", MacSystrayObjCmd, info,\n\t    MacSystrayDestroy);\n    Tcl_CreateObjCommand2(interp, \"::tk::sysnotify::_sysnotify\", SysNotifyObjCmd, NULL, NULL);\n    return TCL_OK;\n}\n\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXTest.c",
    "content": "/*\n * tkMacOSXTest.c --\n *\n *\tContains commands for platform specific tests for\n *\tthe Macintosh platform.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXConstants.h\"\n#include \"tkMacOSXWm.h\"\n\n/*\n * Forward declarations of procedures defined later in this file:\n */\n\nstatic Tcl_ObjCmdProc2 TestpressbuttonObjCmd;\nstatic Tcl_ObjCmdProc2 TestmovemouseObjCmd;\nstatic Tcl_ObjCmdProc2 TestinjectkeyeventObjCmd;\nstatic Tcl_ObjCmdProc2 TestmenubarheightObjCmd;\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkplatformtestInit --\n *\n *\tDefines commands that test platform specific functionality for\n *\tUnix platforms.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tDefines new commands.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkplatformtestInit(\n    Tcl_Interp *interp)\t\t/* Interpreter to add commands to. */\n{\n    /*\n     * Set a flag indicating that testing is in progress.\n     */\n\n    testsAreRunning = true;\n\n    /*\n     * Add commands for platform specific tests on MacOS here.\n     */\n\n    Tcl_CreateObjCommand2(interp, \"testpressbutton\", TestpressbuttonObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"testmovemouse\", TestmovemouseObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"testinjectkeyevent\", TestinjectkeyeventObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"testmenubarheight\", TestmenubarheightObjCmd, NULL, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestmenubarheightObjCmd --\n *\n *\tThis procedure calls [NSMenu menuBarHeight] and returns the result\n *      as an integer.  Windows can never be placed to overlap the MenuBar,\n *      so tests need to be aware of its size.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestmenubarheightObjCmd(\n    TCL_UNUSED(void *),\t\t/* Not used. */\n    Tcl_Interp *interp,\t\t\t/* Not used. */\n    TCL_UNUSED(Tcl_Size),\t\t\t\t/* Not used. */\n    TCL_UNUSED(Tcl_Obj *const *))\t\t/* Not used. */\n{\n    static int height = 0;\n    if (height == 0) {\n\theight = (int) [[NSApp mainMenu] menuBarHeight];\n    }\n    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(height));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTestLogDisplay --\n *\n *      The test image display procedure calls this to determine whether it\n *      should write a log message recording that it has being run.\n *\n * Results:\n *      Returns true if and only if the NSView of the drawable is the\n *      current focusView, which on 10.14 and newer systems can only be the\n *      case when within [NSView drawRect].\n *      NOTE: This is no longer needed when we use updateLayer instead\n *      of drawRect.  Now it always returns True.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE Bool\nTkTestLogDisplay(\n    Drawable drawable)\n{\n    (void) drawable;\n    return True;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestpressbuttonObjCmd --\n *\n *\tThis Tcl command simulates a button press at a specific screen\n *      location.  It injects NSEvents into the NSApplication event queue, as\n *      opposed to adding events to the Tcl queue as event generate would do.\n *      One application is for testing the grab command. These events have\n *      their timestamp property set to 0 as a signal indicating that they\n *      should not be ignored by [NSApp tkProcessMouseEvent].\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestpressbuttonObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    int x = 0, y = 0, value;\n    Tcl_Size i;\n    CGPoint pt;\n    NSPoint loc;\n    NSEvent *motion, *press, *release;\n    NSArray *screens = [NSScreen screens];\n    CGFloat ScreenHeight = 0;\n    enum {X=1, Y};\n\n    if (screens && [screens count]) {\n\tScreenHeight = [[screens objectAtIndex:0] frame].size.height;\n    }\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"x y\");\n\treturn TCL_ERROR;\n    }\n    for (i = 1; i < objc; i++) {\n\tif (Tcl_GetIntFromObj(interp,objv[i],&value) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch (i) {\n\tcase X:\n\t    x = value;\n\t    break;\n\tcase Y:\n\t    y = value;\n\t    break;\n\tdefault:\n\t    break;\n\t}\n    }\n    pt.x = loc.x = x;\n    pt.y = y;\n    loc.y = ScreenHeight - y;\n\n    /*\n     *  We set the timestamp to 0 as a signal to tkProcessMouseEvent.\n     */\n\n    CGWarpMouseCursorPosition(pt);\n    motion = [NSEvent mouseEventWithType:NSMouseMoved\n\tlocation:loc\n\tmodifierFlags:0\n\ttimestamp:0\n\twindowNumber:0\n\tcontext:nil\n\teventNumber:0\n\tclickCount:1\n\tpressure:0];\n    [NSApp postEvent:motion atStart:NO];\n    press = [NSEvent mouseEventWithType:NSLeftMouseDown\n\tlocation:loc\n\tmodifierFlags:0\n\ttimestamp:0\n\twindowNumber:0\n\tcontext:nil\n\teventNumber:0\n\tclickCount:1\n\tpressure:0];\n    [NSApp postEvent:press atStart:NO];\n    release = [NSEvent mouseEventWithType:NSLeftMouseUp\n\tlocation:loc\n\tmodifierFlags:0\n\ttimestamp:0\n\twindowNumber:0\n\tcontext:nil\n\teventNumber:0\n\tclickCount:1\n\tpressure:0];\n    [NSApp postEvent:release atStart:NO];\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestmovemouseObjCmd --\n *\n *\tThis Tcl command simulates a mouse motion to a specific screen\n *      location.  It injects an NSEvent into the NSApplication event queue,\n *      as opposed to adding events to the Tcl queue as event generate would\n *      do.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestmovemouseObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    int x = 0, y = 0, value;\n    Tcl_Size i;\n    CGPoint pt;\n    NSPoint loc;\n    NSEvent *motion;\n    NSArray *screens = [NSScreen screens];\n    CGFloat ScreenHeight = 0;\n    enum {X=1, Y};\n\n    if (screens && [screens count]) {\n\tScreenHeight = [[screens objectAtIndex:0] frame].size.height;\n    }\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"x y\");\n\treturn TCL_ERROR;\n    }\n    for (i = 1; i < objc; i++) {\n\tif (Tcl_GetIntFromObj(interp,objv[i],&value) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch (i) {\n\tcase X:\n\t    x = value;\n\t    break;\n\tcase Y:\n\t    y = value;\n\t    break;\n\tdefault:\n\t    break;\n\t}\n    }\n    pt.x = loc.x = x;\n    pt.y = y;\n    loc.y = ScreenHeight - y;\n\n    /*\n     *  We set the timestamp to 0 as a signal to tkProcessMouseEvent.\n     */\n\n    CGWarpMouseCursorPosition(pt);\n    motion = [NSEvent mouseEventWithType:NSMouseMoved\n\tlocation:loc\n\tmodifierFlags:0\n\ttimestamp:0\n\twindowNumber:0\n\tcontext:nil\n\teventNumber:0\n\tclickCount:1\n\tpressure:0];\n    [NSApp postEvent:motion atStart:NO];\n    return TCL_OK;\n}\n\f\nstatic int\nTestinjectkeyeventObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    static const char *const optionStrings[] = {\n\t\"flagschanged\", \"press\", \"release\", NULL};\n    NSUInteger types[3] = {NSFlagsChanged, NSKeyDown, NSKeyUp};\n    static const char *const argStrings[] = {\n\t\"-command\", \"-control\", \"-function\", \"-option\", \"-shift\", \"-x\", \"-y\", NULL};\n    enum args {KEYEVENT_COMMAND, KEYEVENT_CONTROL, KEYEVENT_FUNCTION, KEYEVENT_OPTION,\n\t       KEYEVENT_SHIFT, KEYEVENT_X, KEYEVENT_Y};\n    Tcl_Size i;\n    int index, keysym, mods = 0, x = 0, y = 0;\n    NSString *chars = nil, *unmod = nil, *upper, *lower;\n    NSEvent *keyEvent;\n    NSUInteger type;\n    MacKeycode macKC;\n\n    if (objc < 3) {\n    wrongArgs:\n\tTcl_WrongNumArgs(interp, 1, objv, \"option keysym ?arg?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    type = types[index];\n    if (Tcl_GetIntFromObj(interp, objv[2], &keysym) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t \"keysym must be an integer\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"TEST\", \"INJECT\", \"KEYSYM\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    macKC.uint = XKeysymToKeycode(NULL, keysym);\n    for (i = 3; i < objc; i++) {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], argStrings,\n\t\tsizeof(char *), \"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((enum args) index) {\n\tcase KEYEVENT_SHIFT:\n\t    mods |= NSShiftKeyMask;\n\t    break;\n\tcase KEYEVENT_CONTROL:\n\t    mods |= NSControlKeyMask;\n\t    break;\n\tcase KEYEVENT_OPTION:\n\t    mods |= NSAlternateKeyMask;\n\t    break;\n\tcase KEYEVENT_COMMAND:\n\t    mods |= NSCommandKeyMask;\n\t    break;\n\tcase KEYEVENT_FUNCTION:\n\t    mods |= NSFunctionKeyMask;\n\t    break;\n\tcase KEYEVENT_X:\n\t    if (++i >= objc) {\n\t\tgoto wrongArgs;\n\t    }\n\t    if (Tcl_GetIntFromObj(interp,objv[i], &x) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase KEYEVENT_Y:\n\t    if (++i >= objc) {\n\t\tgoto wrongArgs;\n\t    }\n\t    if (Tcl_GetIntFromObj(interp,objv[i], &y) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\t}\n    }\n    if (type != NSFlagsChanged) {\n\tUniChar keychar = macKC.v.keychar;\n\tchars = [[NSString alloc] initWithCharacters: &keychar length:1];\n\tupper = [chars uppercaseString];\n\tlower = [chars lowercaseString];\n\tif (![upper isEqual: lower] && [chars isEqual: upper]) {\n\t    mods |= NSShiftKeyMask;\n\t}\n\tif (mods & NSShiftKeyMask) {\n\t    chars = upper;\n\t    unmod = lower;\n\t    macKC.v.o_s |= INDEX_SHIFT;\n\t} else {\n\t    unmod = chars;\n\t}\n\tif (macKC.v.o_s & INDEX_OPTION) {\n\t    mods |= NSAlternateKeyMask;\n\t}\n    }\n    keyEvent = [NSEvent keyEventWithType:type\n\tlocation:NSMakePoint(x, y)\n\tmodifierFlags:mods\n\ttimestamp:GetCurrentEventTime()\n\twindowNumber:0\n\tcontext:nil\n\tcharacters:chars\n\tcharactersIgnoringModifiers:unmod\n\tisARepeat:NO\n\tkeyCode:macKC.v.virt];\n    [NSApp postEvent:keyEvent atStart:NO];\n    return TCL_OK;\n}\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXWindowEvent.c",
    "content": "/*\n * tkMacOSXWindowEvent.c --\n *\n *\tThis file defines the routines for both creating and handling Window\n *\tManager class events for Tk.\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2015 Kevin Walzer\n * Copyright © 2015 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXWm.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXConstants.h\"\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_EVENTS\n#define TK_MAC_DEBUG_DRAWING\n#endif\n*/\n\nextern NSMutableArray<TkAccessibilityElement*> *_tkAccessibleElements;\n/*\n * Declaration of functions used only in this file\n */\n\nstatic int\t\tGenerateUpdates(\n\t\t\t    CGRect *updateBounds, TkWindow *winPtr);\nstatic int\t\tGenerateActivateEvents(TkWindow *winPtr,\n\t\t\t    int activeFlag);\nstatic void\t\tGenerateWMDestroyEvent(Tk_Window tkwin);\n\n#pragma mark TKApplication(TKWindowEvent)\n\nextern NSString *NSWindowDidOrderOnScreenNotification;\nextern NSString *NSWindowWillOrderOnScreenNotification;\nextern NSString *NSWindowWillCloseNotification;\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\nextern NSString *NSWindowDidOrderOffScreenNotification;\n#endif\n\n@implementation TKApplication(TKWindowEvent)\n\n- (void) windowActivation: (NSNotification *) notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if ([NSApp tkWillExit]) {\n\treturn;\n    }\n    static NSWindow *systemDialog = NULL;\n    NSWindow *win = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(win);\n    NSString *name = [notification name];\n    if ([name isEqualToString:NSWindowDidResignKeyNotification]) {\n\tif (![NSApp keyWindow] && [NSApp isActive]) {\n\t    if (winPtr) {\n\t\t/*\n\t\t * A Tk window lost focus and no window has focus anymore.\n\t\t */\n\n\t\tTkMacOSXAssignNewKeyWindow(Tk_Interp((Tk_Window) winPtr), NULL);\n\t    } else {\n\t\t/*\n\t\t * A system dialog, such as a standard About dialog, lost focus.\n\t\t */\n\n\t\tTkMacOSXAssignNewKeyWindow(NULL, NULL);\n\t    }\n\t}\n\tif (winPtr && Tk_IsMapped(winPtr)) {\n\t    GenerateActivateEvents(winPtr, false);\n\t}\n    }\n    /*\n     * On older systems the system dialogs do not send DidResignKey\n     * but the do send WillClose.\n     */\n\n    if ([name isEqualToString:NSWindowWillCloseNotification]) {\n\tif (win == systemDialog) {\n\t    TkMacOSXAssignNewKeyWindow(NULL, NULL);\n\t}\n    }\n    if ([name isEqualToString:NSWindowDidBecomeKeyNotification]) {\n\tif (winPtr) {\n\t    NSPoint location = [NSEvent mouseLocation];\n\t    int x = location.x;\n\t    int y = floor(TkMacOSXZeroScreenHeight() - location.y);\n\t    /*\n\t     * The Tk event target persists when there is no key window but\n\t     * gets reset when a new window becomes the key window.\n\t     */\n\n\t    [NSApp setTkEventTarget: winPtr];\n\n\t    /*\n\t     * Call Tk_UpdatePointer if the pointer is in the window.\n\t     */\n\n\t    NSView *view = [win contentView];\n\t    NSPoint viewLocation = [view convertPoint:location fromView:nil];\n\t    if (NSPointInRect(viewLocation,\n\t\t\t      NSInsetRect([view bounds], 2, 2))) {\n\t\tTk_UpdatePointer((Tk_Window) winPtr, x, y,\n\t\t\t\t [NSApp tkButtonState]);\n\t    }\n\t} else {\n\t    systemDialog = win;\n\t}\n\tif (winPtr && Tk_IsMapped(winPtr)) {\n\t    GenerateActivateEvents(winPtr, true);\n\t}\n    }\n    /*\n     * Make sure that the updated keyWindow is associated with the\n     * current TkEventTarget.\n     */\n\n    NSWindow *keyWin = [NSApp keyWindow];\n    if (keyWin) {\n\tTkWindow *keyWinPtr = TkMacOSXGetTkWindow(keyWin);\n\tif (keyWinPtr) {\n\t    [NSApp setTkEventTarget:keyWinPtr];\n\t}\n    }\n}\n\n- (void) windowBoundsChanged: (NSNotification *) notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    BOOL movedOnly = [[notification name]\n\t    isEqualToString:NSWindowDidMoveNotification];\n    NSWindow *w = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n\n    if (winPtr) {\n\tWmInfo *wmPtr = winPtr->wmInfoPtr;\n\tNSRect bounds = [w frame];\n\tint x, y, width = -1, height = -1, flags = 0;\n\n\tx = bounds.origin.x;\n\ty = TkMacOSXZeroScreenHeight() - (bounds.origin.y + bounds.size.height);\n\tif (winPtr->changes.x != x || winPtr->changes.y != y) {\n\t    flags |= TK_LOCATION_CHANGED;\n\t} else {\n\t    x = y = -1;\n\t}\n\tif (!movedOnly && (winPtr->changes.width != bounds.size.width ||\n\t\twinPtr->changes.height !=  bounds.size.height)) {\n\t    width = bounds.size.width - wmPtr->xInParent;\n\t    height = bounds.size.height - wmPtr->yInParent;\n\t    flags |= TK_SIZE_CHANGED;\n\t}\n\t/*\n\t * Propagate geometry changes immediately.\n\t */\n\n\tflags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;\n\tTkGenWMConfigureEvent((Tk_Window)winPtr, x, y, width, height, flags);\n\n\t/*Resize accessibility frame if window is resized.*/\n\tTKContentView *view = [w contentView];\n\tif ([view isKindOfClass:[TKContentView class]]) {\n\t    for (TkAccessibilityElement *element in view.accessibilityChildren) {\n\t\tif  (movedOnly) {\n\t\t    NSAccessibilityPostNotification(element, NSAccessibilityMovedNotification);\n\t\t} else {\n\t\t    NSAccessibilityPostNotification(element, NSAccessibilityResizedNotification);\n\t\t}\n\t    }\n\t}\n    }\n}\n\n- (void) windowExpanded: (NSNotification *) notification\n{\n    // This method will be called when the asynchronous deminiaturization\n    // operation has completed.  If the window is iconified by clicking on its\n    // dock icon, as opposed to calling wm deiconify, then the Tk state of\n    // the window needs to be updated.  That is the purpose of this method.\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n\n    NSWindow *w = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n    if (winPtr && winPtr->wmInfoPtr->hints.initial_state == IconicState) {\n\twinPtr->wmInfoPtr->hints.initial_state =\n\t\tTkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;\n\tTkWmMapWindow(winPtr);\n\n\t/*\n\t * NSWindowDidDeminiaturizeNotification is received after\n\t * NSWindowDidBecomeKeyNotification, so activate manually\n\t */\n\n\tGenerateActivateEvents(winPtr, 1);\n    }\n}\n\n- (NSRect)windowWillUseStandardFrame:(NSWindow *)window\n\t\t\tdefaultFrame:(NSRect)newFrame\n{\n    (void)window;\n\n    /*\n     * This method needs to be implemented in order for [NSWindow isZoomed] to\n     * give the correct answer. But it suffices to always validate every\n     * request.\n     */\n\n    return newFrame;\n}\n\n- (NSSize)window:(NSWindow *)window\n  willUseFullScreenContentSize:(NSSize)proposedSize\n{\n    (void)window;\n\n    /*\n     * We don't need to change the proposed size, but we do need to implement\n     * this method.  Otherwise the full screen window will be sized to the\n     * screen's visibleFrame, leaving black bands at the top and bottom.\n     */\n\n    return proposedSize;\n}\n\n- (void) windowEnteredFullScreen: (NSNotification *) notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if (![[notification object] respondsToSelector: @selector (tkLayoutChanged)]) {\n\treturn;\n    }\n    [(TKWindow *)[notification object] tkLayoutChanged];\n}\n\n- (void) windowExitedFullScreen: (NSNotification *) notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    if (![[notification object] respondsToSelector: @selector (tkLayoutChanged)]) {\n\treturn;\n    }\n    [(TKWindow *)[notification object] tkLayoutChanged];\n}\n\n- (void) windowCollapsed: (NSNotification *) notification\n{\n    // This method will be called when the asynchronous miniaturization\n    // operation has completed.  If the window is iconified by clicking on its\n    // yellow button, as opposed to calling wm iconify, then the Tk state of\n    // the window needs to be updated.  That is the purpose of this method.\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    NSWindow *w = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n    NSString *name = [notification name];\n    if (!winPtr) {\n\treturn;\n    }\n    if ([name isEqualToString:NSWindowWillMiniaturizeNotification]) {\n\tif (winPtr && winPtr->wmInfoPtr->hints.initial_state != IconicState) {\n\t    winPtr->wmInfoPtr->hints.initial_state = IconicState;\n\t}\n    } else {\n\tTkWmUnmapWindow(winPtr);\n    }\n}\n\n- (BOOL) windowShouldClose: (NSWindow *) w\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), w);\n#endif\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n\n    if (winPtr) {\n\tGenerateWMDestroyEvent((Tk_Window)winPtr);\n    }\n\n    /*\n     * If necessary, GenerateWMDestroyEvent() handles [close]ing the window, so\n     * can always return NO from -windowShouldClose: for a Tk window.\n     */\n\n    return (winPtr ? NO : YES);\n}\n\n// Not used by default - may be enabled for debugging.\n- (void) windowBecameVisible: (NSNotification *) notification\n{\n    if ([NSApp tkWillExit]) {\n\treturn;\n    }\n    NSWindow *window = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(window);\n    if (winPtr) {\n\tfprintf(stderr, \"Window %s became visible.\\n\", Tk_PathName(winPtr));\n    }\n}\n\n// Not used by default - may be enabled for debugging.\n- (void) windowMapped: (NSNotification *) notification\n{\n    if ([NSApp tkWillExit]) {\n\treturn;\n    }\n    NSWindow *w = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n\n    if (winPtr) {\n\tfprintf(stderr, \"Window %s was ordered on screen.\\n\", Tk_PathName(winPtr));\n    }\n}\n\n- (void) windowLiveResize: (NSNotification *) notification\n{\n    NSString *name = [notification name];\n    if ([name isEqualToString:NSWindowWillStartLiveResizeNotification]) {\n\t// fprintf(stderr, \"Starting live resize.\\n\");\n    } else if ([name isEqualToString:NSWindowDidEndLiveResizeNotification]) {\n\t[self setTkLiveResizeEnded:YES];\n\t// fprintf(stderr, \"Ending live resize\\n\");\n    }\n}\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n\n- (void) windowDragStart: (NSNotification *) notification\n{\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n}\n\n- (void) windowUnmapped: (NSNotification *) notification\n{\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n    NSWindow *w = [notification object];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n}\n\n#endif /* TK_MAC_DEBUG_NOTIFICATIONS */\n\n- (void) _setupWindowNotifications\n{\n    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];\n\n#define observe(n, s) \\\n\t[nc addObserver:self selector:@selector(s) name:(n) object:nil]\n\n    observe(NSWindowDidBecomeKeyNotification, windowActivation:);\n    observe(NSWindowDidResignKeyNotification, windowActivation:);\n    observe(NSWindowWillCloseNotification, windowActivation:);\n    observe(NSWindowDidMoveNotification, windowBoundsChanged:);\n    observe(NSWindowDidResizeNotification, windowBoundsChanged:);\n    observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);\n    observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);\n    observe(NSWindowWillMiniaturizeNotification, windowCollapsed:);\n#if 0\n    // These can be useful for debugging.\n    observe(NSWindowWillOrderOnScreenNotification, windowMapped:);\n    observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);\n#endif\n    observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);\n    observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);\n    observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);\n    observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:);\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    observe(NSWindowWillMoveNotification, windowDragStart:);\n    observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);\n#endif\n#undef observe\n\n}\n@end\n\f\n\n/*\n * Idle task which forces focus to a particular window.\n */\n\nstatic void RefocusGrabWindow(void *data) {\n    TkWindow *winPtr = (TkWindow *) data;\n    TkpChangeFocus(winPtr, 1);\n    Tcl_Release(winPtr);\n}\n\n#pragma mark TKApplication(TKApplicationEvent)\n\n@implementation TKApplication(TKApplicationEvent)\n\n- (void) applicationActivate: (NSNotification *) notification\n{\n    NSWindow *iconifiedWindow = nil;\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#else\n    (void) notification;\n#endif\n    [NSApp tkCheckPasteboard];\n\n    /*\n     * When the application is activated with Command-Tab it will create a\n     * zombie window for every Tk window which has been withdrawn.  So iterate\n     * through the list of windows and order out any withdrawn window.\n     * If one of the windows is the grab window for its display we focus\n     * it.  This is done as at idle, in case the app was reactivated by\n     * clicking a different window.  In that case we need to wait until the\n     * mouse event has been processed before focusing the grab window.\n     */\n\n    for (NSWindow *win in [NSApp windows]) {\n\tif (! [win isKindOfClass:[TKWindow class]]) {\n\t    continue;\n\t}\n\tTkWindow *winPtr = TkMacOSXGetTkWindow(win);\n\tif (!winPtr || !winPtr->wmInfoPtr) {\n\t    continue;\n\t}\n\tif (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) {\n\t    [win orderOut:NSApp];\n\t    [[win contentView] setOnScreen:NO];\n\t}\n\tif (winPtr->dispPtr->grabWinPtr == winPtr) {\n\t    Tcl_Preserve(winPtr);\n\t    Tcl_DoWhenIdle(RefocusGrabWindow, winPtr);\n\t}\n\tif (iconifiedWindow == nil && [win isMiniaturized]) {\n\t    iconifiedWindow = win;\n\t}\n    }\n    if ([self keyWindow] == nil && iconifiedWindow != nil) {\n\t[iconifiedWindow makeKeyAndOrderFront:self];\n    } else {\n\t[[self keyWindow] orderFront:self];\n    }\n\n}\n\n- (void) applicationDeactivate: (NSNotification *) notification\n{\n    (void)notification;\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n\n    /*\n     * To prevent zombie windows on systems with a TouchBar, set the key window\n     * to nil if the current key window is not visible.  This allows a closed\n     * Help or About window to be deallocated so it will not reappear as a\n     * zombie when the app is reactivated.\n     */\n\n    NSWindow *keywindow = [NSApp keyWindow];\n    if (keywindow && ![keywindow isVisible]) {\n\t[NSApp _setKeyWindow:nil];\n\t[NSApp _setMainWindow:nil];\n    }\n\n}\n\n- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender\n\t\t    hasVisibleWindows:(BOOL)flag\n{\n    (void)sender;\n    (void)flag;\n\n    /*\n     * Allowing the default response means that withdrawn windows will get\n     * displayed on the screen with unresponsive title buttons.  We don't\n     * really want that.  Besides, we can write our own code to handle this\n     * with ::tk::mac::ReopenApplication.  So we just say NO.\n     */\n\n    return NO;\n}\n\n\n- (void) applicationShowHide: (NSNotification *) notification\n{\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    const char *cmd = ([[notification name] isEqualToString:\n\t    NSApplicationDidUnhideNotification] ?\n\t    \"::tk::mac::OnShow\" : \"::tk::mac::OnHide\");\n\n    if (_eventInterp && Tcl_FindCommand(_eventInterp, cmd, NULL, 0)) {\n\tint code = Tcl_EvalEx(_eventInterp, cmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(_eventInterp, code);\n\t}\n\tTcl_ResetResult(_eventInterp);\n    }\n}\n\n- (void) displayChanged: (NSNotification *) notification\n{\n    (void)notification;\n\n#ifdef TK_MAC_DEBUG_NOTIFICATIONS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), notification);\n#endif\n    TkDisplay *dispPtr = TkGetDisplayList();\n\n    if (dispPtr) {\n\tTkMacOSXDisplayChanged(dispPtr->display);\n    }\n}\n@end\n\n#pragma mark -\n\n/*\n *----------------------------------------------------------------------\n *\n * GenerateUpdates --\n *\n *\tGiven an update rectangle and a Tk window, this function generates\n *\tan X Expose event for the window if it meets the update region. The\n *\tfunction will then recursively have each damaged window generate Expose\n *\tevents for its child windows.\n *\n * Results:\n *\tTrue if event(s) are generated - false otherwise.\n *\n * Side effects:\n *\tAdditional events may be placed on the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGenerateUpdates(\n    CGRect *updateBounds,\n    TkWindow *winPtr)\n{\n    TkWindow *childPtr;\n    XEvent event;\n    CGRect bounds, damageBounds;\n    NSView *view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr);\n\n    TkMacOSXWinCGBounds(winPtr, &bounds);\n\n    /*\n     * Compute the bounding box of the area that the damage occurred in.\n     */\n\n    damageBounds = CGRectIntersection(bounds, *updateBounds);\n    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));\n    event.xany.send_event = false;\n    event.xany.window = Tk_WindowId(winPtr);\n    event.xany.display = Tk_Display(winPtr);\n    event.type = Expose;\n    event.xexpose.x = damageBounds.origin.x - bounds.origin.x;\n    event.xexpose.y = damageBounds.origin.y - bounds.origin.y;\n    event.xexpose.width = damageBounds.size.width;\n    event.xexpose.height = damageBounds.size.height;\n    event.xexpose.count = 0;\n    if ([view inLiveResize]) {\n\tTk_HandleEvent(&event);\n    } else {\n\tTk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n    }\n\n#ifdef TK_MAC_DEBUG_DRAWING\n    TKLog(@\"Exposed %p {{%d, %d}, {%d, %d}}\", event.xany.window, event.xexpose.x,\n\tevent.xexpose.y, event.xexpose.width, event.xexpose.height);\n#endif\n\n    /*\n     * Generate updates for the children of this window\n     */\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tif (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {\n\t    continue;\n\t}\n\tGenerateUpdates(updateBounds, childPtr);\n    }\n\n    /*\n     * Generate updates for any contained windows\n     */\n\n    if (Tk_IsContainer(winPtr)) {\n\tchildPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\tif (childPtr != NULL && Tk_IsMapped(childPtr)) {\n\t    GenerateUpdates(updateBounds, childPtr);\n\t}\n\n\t/*\n\t * TODO: Here we should handle out of process embedding.\n\t */\n    }\n\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGenerateFocusEvent --\n *\n *\tGiven a Macintosh window activate event this function generates all\n *\tthe X Focus events needed by Tk.\n *\n * Results:\n *\tTrue if event(s) are generated - false otherwise.\n *\n * Side effects:\n *\tAdditional events may be placed on the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTkMacOSXGenerateFocusEvent(\n    TkWindow *winPtr,\t\t/* Root X window for event. */\n    int activeFlag)\n{\n    XEvent event;\n\n    /*\n     * Don't send focus events to windows of class help or to windows with the\n     * kWindowNoActivatesAttribute.\n     */\n\n    if (winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||\n\t    winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)) {\n\treturn false;\n    }\n\n    /*\n     * Generate FocusIn and FocusOut events. This event is only sent to the\n     * toplevel window.\n     */\n\n    if (activeFlag) {\n\tevent.xany.type = FocusIn;\n    } else {\n\tevent.xany.type = FocusOut;\n    }\n\n    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));\n    event.xany.send_event = False;\n    event.xfocus.display = Tk_Display(winPtr);\n    event.xfocus.window = winPtr->window;\n    event.xfocus.mode = NotifyNormal;\n    event.xfocus.detail = NotifyDetailNone;\n\n    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateActivateEvents --\n *\n *\tGiven a Macintosh window activate event this function generates all the\n *\tX Activate events needed by Tk.\n *\n * Results:\n *\tTrue if event(s) are generated - false otherwise.\n *\n * Side effects:\n *\tAdditional events may be placed on the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nint\nGenerateActivateEvents(\n    TkWindow *winPtr,\n    int activeFlag)\n{\n    TkGenerateActivateEvents(winPtr, activeFlag);\n    if (activeFlag || ![NSApp isActive]) {\n\tTkMacOSXGenerateFocusEvent(winPtr, activeFlag);\n    }\n    return true;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkGenWMConfigureEvent --\n *\n *\tGenerate a ConfigureNotify event for Tk. Depending on the value of flag\n *\tthe values of width/height, x/y, or both may be changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA ConfigureNotify event is sent to Tk.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGenWMConfigureEvent(\n    Tk_Window tkwin,\n    int x, int y,\n    int width, int height,\n    int flags)\n{\n    XEvent event;\n    WmInfo *wmPtr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    if (tkwin == NULL) {\n\treturn;\n    }\n\n    event.type = ConfigureNotify;\n    event.xconfigure.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n    event.xconfigure.send_event = False;\n    event.xconfigure.display = Tk_Display(tkwin);\n    event.xconfigure.event = Tk_WindowId(tkwin);\n    event.xconfigure.window = Tk_WindowId(tkwin);\n    event.xconfigure.border_width = winPtr->changes.border_width;\n    event.xconfigure.override_redirect = winPtr->atts.override_redirect;\n    if (winPtr->changes.stack_mode == Above) {\n\tevent.xconfigure.above = winPtr->changes.sibling;\n    } else {\n\tevent.xconfigure.above = None;\n    }\n\n    if (!(flags & TK_LOCATION_CHANGED)) {\n\tx = Tk_X(tkwin);\n\ty = Tk_Y(tkwin);\n    }\n    if (!(flags & TK_SIZE_CHANGED)) {\n\twidth = Tk_Width(tkwin);\n\theight = Tk_Height(tkwin);\n    }\n    event.xconfigure.x = x;\n    event.xconfigure.y = y;\n    event.xconfigure.width = width;\n    event.xconfigure.height = height;\n\n    if (flags & TK_MACOSX_HANDLE_EVENT_IMMEDIATELY) {\n\tTk_HandleEvent(&event);\n    } else {\n\tTk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n    }\n\n    /*\n     * Update window manager information.\n     */\n\n    if (Tk_IsTopLevel(winPtr)) {\n\twmPtr = winPtr->wmInfoPtr;\n\tif (flags & TK_LOCATION_CHANGED) {\n\t    wmPtr->x = x;\n\t    wmPtr->y = y;\n\t}\n\tif ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&\n\t\t((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {\n\t    if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {\n\t\t/*\n\t\t * Don't set external width, since the user didn't change it\n\t\t * from what the widgets asked for.\n\t\t */\n\t    } else if (wmPtr->gridWin != NULL) {\n\t\twmPtr->width = wmPtr->reqGridWidth\n\t\t\t+ (width - winPtr->reqWidth)/wmPtr->widthInc;\n\t\tif (wmPtr->width < 0) {\n\t\t    wmPtr->width = 0;\n\t\t}\n\t    } else {\n\t\twmPtr->width = width;\n\t    }\n\n\t    if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {\n\t\t/*\n\t\t * Don't set external height, since the user didn't change it\n\t\t * from what the widgets asked for.\n\t\t */\n\t    } else if (wmPtr->gridWin != NULL) {\n\t\twmPtr->height = wmPtr->reqGridHeight\n\t\t\t+ (height - winPtr->reqHeight)/wmPtr->heightInc;\n\t\tif (wmPtr->height < 0) {\n\t\t    wmPtr->height = 0;\n\t\t}\n\t    } else {\n\t\twmPtr->height = height;\n\t    }\n\n\t    wmPtr->configWidth = width;\n\t    wmPtr->configHeight = height;\n\t}\n    }\n\n    /*\n     * Now set up the changes structure. Under X we wait for the\n     * ConfigureNotify to set these values. On the Mac we know immediately that\n     * this is what we want - so we just set them. However, we need to make\n     * sure the windows clipping region is marked invalid so the change is\n     * visible to the subwindow.\n     */\n\n    winPtr->changes.x = x;\n    winPtr->changes.y = y;\n    winPtr->changes.width = width;\n    winPtr->changes.height = height;\n    TkMacOSXInvalClipRgns(tkwin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateWMDestroyEvent --\n *\n *\tGenerate a WM Destroy event for Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA WM_PROTOCOL/WM_DELETE_WINDOW event is sent to Tk.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nGenerateWMDestroyEvent(\n    Tk_Window tkwin)\n{\n    XEvent event;\n\n    event.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n    event.xany.send_event = False;\n    event.xany.display = Tk_Display(tkwin);\n\n    event.xclient.window = Tk_WindowId(tkwin);\n    event.xclient.type = ClientMessage;\n    event.xclient.message_type = Tk_InternAtom(tkwin, \"WM_PROTOCOLS\");\n    event.xclient.format = 32;\n    event.xclient.data.l[0] = Tk_InternAtom(tkwin, \"WM_DELETE_WINDOW\");\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmProtocolEventProc --\n *\n *\tThis procedure is called by the Tk_HandleEvent whenever a ClientMessage\n *\tevent arrives whose type is \"WM_PROTOCOLS\". This procedure handles the\n *\tmessage from the window manager in an appropriate fashion.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what sort of handler, if any, was set up for the protocol.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmProtocolEventProc(\n    TkWindow *winPtr,\t\t/* Window to which the event was sent. */\n    XEvent *eventPtr)\t\t/* X event. */\n{\n    WmInfo *wmPtr;\n    ProtocolHandler *protPtr;\n    Tcl_Interp *interp;\n    Atom protocol;\n    int result;\n\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n    protocol = (Atom) eventPtr->xclient.data.l[0];\n    for (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t    protPtr = protPtr->nextPtr) {\n\tif (protocol == protPtr->protocol) {\n\t    Tcl_Preserve(protPtr);\n\t    interp = protPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    result = Tcl_EvalEx(interp, Tcl_GetString(protPtr->commandObj), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    if (result != TCL_OK) {\n\t\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\t\"\\n    (command for \\\"%s\\\" window manager protocol)\",\n\t\t\tTk_GetAtomName((Tk_Window)winPtr, protocol)));\n\t\tTcl_BackgroundException(interp, result);\n\t    }\n\t    Tcl_Release(interp);\n\t    Tcl_Release(protPtr);\n\t    return;\n\t}\n    }\n\n    /*\n     * No handler was present for this protocol. If this is a WM_DELETE_WINDOW\n     * message then just destroy the window.\n     */\n\n    if (protocol == Tk_InternAtom((Tk_Window)winPtr, \"WM_DELETE_WINDOW\")) {\n\tTk_DestroyWindow((Tk_Window)winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MacOSXIsAppInFront --\n *\n *\tReturns 1 if this app is the foreground app.\n *\n * Results:\n *\t1 if app is in front, 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_MacOSXIsAppInFront(void)\n{\n    return ([NSRunningApplication currentApplication].active == true);\n}\n\f\n#pragma mark TKContentView\n\n#import <ApplicationServices/ApplicationServices.h>\n\n/*\n * Custom content view for use in Tk NSWindows.\n *\n * Since Tk handles all drawing of widgets, we only use the AppKit event loop\n * as a source of input events.  To do this, we overload the NSView drawRect\n * method with a method which generates Expose events for Tk but does no\n * drawing.  The redrawing operations are then done when Tk processes these\n * events.\n *\n * Earlier versions of Mac Tk used subclasses of NSView, e.g. NSButton, as the\n * basis for Tk widgets.  These would then appear as subviews of the\n * TKContentView.  To prevent the AppKit from redrawing and corrupting the Tk\n * Widgets it was necessary to use Apple private API calls.  In order to avoid\n * using private API calls, the NSView-based widgets have been replaced with\n * normal Tk widgets which draw themselves as native widgets by using the\n * HITheme API.\n *\n */\n\n/*\n * Restrict event processing to Expose events.\n */\n\nstatic Tk_RestrictAction\nExposeRestrictProc(\n    void *arg,\n    XEvent *eventPtr)\n{\n    return (eventPtr->type==Expose && eventPtr->xany.serial==PTR2UINT(arg)\n\t    ? TK_PROCESS_EVENT : TK_DEFER_EVENT);\n}\n\n@implementation TKContentView(TKWindowEvent)\n\n- (id)initWithFrame:(NSRect)frame\n{\n    self = [super initWithFrame:frame];\n    if (self) {\n\tself.wantsLayer = YES;\n\tself.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;\n\tself.layer.contentsGravity = self.layer.contentsAreFlipped ?\n\t    kCAGravityTopLeft : kCAGravityBottomLeft;\n\ttrackingArea = [[NSTrackingArea alloc]\n\t\t\t   initWithRect:[self bounds]\n\t\t\t\toptions:(NSTrackingMouseEnteredAndExited |\n\t\t\t\t\t NSTrackingMouseMoved |\n\t\t\t\t\t NSTrackingEnabledDuringMouseDrag |\n\t\t\t\t\t NSTrackingInVisibleRect |\n\t\t\t\t\t NSTrackingActiveAlways)\n\t\t\t\t  owner:self\n\t\t\t       userInfo:nil];\n\t[self addTrackingArea:trackingArea];\n    }\n    return self;\n}\n\n- (BOOL) wantsUpdateLayer\n{\n    return YES;\n}\n- (void) updateLayer {\n    CGContextRef context = self.tkLayerBitmapContext;\n    if (context && ![NSApp tkWillExit]) {\n\t/*\n\t * If this ContentView is off screen, Run any pending widget\n\t * display procs before updating the layer.\n\t */\n\n\tif (! [self onScreen]) {\n\t    //printf(\"Running event loop.\\n\");\n\t    while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}\n\t    [self setOnScreen:YES];\n\t}\n\n\t/*\n\t * Create a CGImage by copying (probably using copy-on-write) the\n\t * bitmap data of the CGBitmapContext that we have been using for\n\t * drawing.  Then render that CGImage into the CALayer of this view by\n\t * assigning a reference to the CGImage to the contents property of the\n\t * layer. This will cause all drawing done since the last call to this\n\t * function to become visible.\n\t */\n\n\tCGImageRef newImg = CGBitmapContextCreateImage(context);\n\tself.layer.contents = (__bridge id) newImg;\n\tCGImageRelease(newImg); // will quickly leak memory if this is missing\n    }\n}\n\n- (void) viewDidChangeBackingProperties\n{\n\n    /*\n     * Make sure that the layer uses a contentScale that matches the\n     * backing scale factor of the screen.  This avoids blurry text when\n     * the view is on a Retina display, as well as incorrect size when\n     * the view is on a normal display.\n     */\n\n    self.layer.contentsScale = self.window.screen.backingScaleFactor;\n    [self resetTkLayerBitmapContext];\n    // need to redraw\n    [self generateExposeEvents: self.bounds];\n}\n\n-(void) setFrameSize: (NSSize)newsize\n{\n    NSSize oldsize = self.bounds.size;\n    [super setFrameSize: newsize];\n    if ((newsize.width == 1 && newsize.height == 1) ||\n\t(oldsize.width == 0 && oldsize.height == 0)) {\n\treturn;\n    }\n    NSWindow *w = [self window];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(w);\n    Tk_Window tkwin = (Tk_Window)winPtr;\n\n    if (winPtr) {\n\tunsigned int width = (unsigned int)newsize.width;\n\tunsigned int height= (unsigned int)newsize.height;\n\n\t/*\n\t * This function can be re-entered, so we need to make sure we don't\n\t * clobber any AutoreleasePool set up by the caller.\n\t */\n\n\t[NSApp _lockAutoreleasePool];\n\n\t /*\n\t  * Generate and handle a ConfigureNotify event for the new size.\n\t  */\n\n\tTkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,\n\t\tTK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);\n\n\t/*\n\t * Update Tk's window data for the new size.\n\t */\n\n\tif ([w respondsToSelector: @selector (tkLayoutChanged)]) {\n\t    [(TKWindow *)w tkLayoutChanged];\n\t}\n\n\t/*\n\t * Reset the cgimage layer and redraw the entire content view.\n\t */\n\n\t[self viewDidChangeBackingProperties];\n\n\t/*\n\t * In live resize we seem to need to draw a second time to\n\t * avoid artifacts.\n\t */\n\n\tif ([self inLiveResize]) {\n\t    [self generateExposeEvents:self.bounds];\n\t}\n\n\t/*\n\t * Finally, unlock the main autoreleasePool.\n\t */\n\n\t[NSApp _unlockAutoreleasePool];\n    }\n}\n\n/*\n * Core method of this class: generates expose events for redrawing.  The\n * expose events are immediately removed from the Tcl event loop and processed.\n * This causes drawing procedures to be scheduled as idle events.  Then all\n * pending idle events are processed so the drawing will actually take place.\n */\n\n- (void) generateExposeEvents: (NSRect) rect\n{\n    CGRect updateBounds;\n    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);\n    void *oldArg;\n    Tk_RestrictProc *oldProc;\n    static int reentered = 0;\n\n    if (!winPtr ||\n\t(winPtr->flags & (TK_ALREADY_DEAD)) ||\n\t!Tk_IsMapped(winPtr)) {\n\treturn;\n    }\n\n    if (reentered) {\n\t/*\n\t * When in liveResize an event loop gets run below to\n\t * immediately process displayProcs while the resize is being\n\t * done.  Those can cause calls to this function, leading to\n\t * crashes or very poor performance.  The reentered flag is\n\t * used to detect this.\n\t */\n\t// fprintf(stderr, \"Recursive call to generateExposeEvents\\n\");\n\treturn;\n    }\n    reentered = 1;\n\n    /*\n     * Generate Tk Expose events.  All of these events will share the same\n     * serial number.\n     */\n    if ([self inLiveResize]) {\n\tupdateBounds = [self bounds];\n    } else {\n\tupdateBounds = NSRectToCGRect(rect);\n    }\n    updateBounds.origin.y = ([self bounds].size.height - updateBounds.origin.y\n\t\t\t     - updateBounds.size.height);\n    if ( GenerateUpdates(&updateBounds, winPtr)) {\n\t/*\n\t * Use the ExposeRestrictProc to process the expose events we just\n\t * generated.  This will create idle drawing tasks, which we handle\n\t * before we return in the case of a live resize.\n\t */\n\tunsigned int serial = LastKnownRequestProcessed(Tk_Display(winPtr));\n\toldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);\n\twhile (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {};\n\tTk_RestrictEvents(oldProc, NULL, &oldArg);\n\n\t/*\n\t * During a LiveResize we process all idle tasks generated by the\n\t * expose events to redraw the window while it is being resized.\n\t */\n\tif ([self inLiveResize]) {\n\t    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}\n\t}\n    }\n    reentered = 0;\n}\n\n/*\n * In macOS 10.14 and later this method is called when a user changes between\n * light and dark mode or changes the accent color. The implementation\n * generates two virtual events.  The first is either <<LightAqua>> or\n * <<DarkAqua>>, depending on the view's current effective appearance.  The\n * second is <<AppearnceChanged>> and has a data string describing the\n * effective appearance of the view and the current accent and highlight\n * colors.\n */\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\nstatic const char *const accentNames[] = {\n    \"Graphite\",\n    \"Red\",\n    \"Orange\",\n    \"Yellow\",\n    \"Green\",\n    \"Blue\",\n    \"Purple\",\n    \"Pink\"\n};\n\n- (void) viewDidChangeEffectiveAppearance\n{\n    Tk_Window tkwin = (Tk_Window)TkMacOSXGetTkWindow([self window]);\n    if (!tkwin) {\n\treturn;\n    }\n    NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name];\n    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];\n    static const char *defaultColor = NULL;\n\n    if (effectiveAppearanceName == NSAppearanceNameAqua) {\n\tTk_SendVirtualEvent(tkwin, \"LightAqua\", NULL);\n    } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) {\n\tTk_SendVirtualEvent(tkwin, \"DarkAqua\", NULL);\n    }\n    if (!defaultColor) {\n\tdefaultColor = [NSApp macOSVersion] < 110000 ? \"Blue\" : \"Multicolor\";\n    }\n    NSString *accent = [preferences stringForKey:@\"AppleAccentColor\"];\n    NSArray *words = [[preferences stringForKey:@\"AppleHighlightColor\"]\n\t\t\t\tcomponentsSeparatedByString: @\" \"];\n    NSString *highlight = [words count] > 3 ? [words objectAtIndex:3] : nil;\n    const char *accentName = accent ? accentNames[1 + accent.intValue] : defaultColor;\n    const char *highlightName = highlight ? highlight.UTF8String: defaultColor;\n    char data[256];\n    snprintf(data, 256, \"Appearance %s Accent %s Highlight %s\",\n\t     effectiveAppearanceName.UTF8String, accentName,\n\t     highlightName);\n    Tk_SendVirtualEvent(tkwin, \"AppearanceChanged\", Tcl_NewStringObj(data, TCL_INDEX_NONE));\n    // Force a redraw of the view.\n    [self setFrameSize:self.frame.size];\n\n    /*\n     * Update some style elements\n     */\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    int code = Tcl_EvalEx(interp, \"after 0 ttk::AppearanceChanged\",\n\t    TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) {\n\tTcl_BackgroundException(interp, code);\n    }\n}\n\n- (void)observeValueForKeyPath:(NSString *)keyPath\n\t\t      ofObject:(id)object\n\t\t\tchange:(NSDictionary *)change\n\t\t       context:(void *)context\n{\n    (void) change;\n    (void) context;\n    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];\n    if (object == preferences && [keyPath isEqualToString:@\"AppleHighlightColor\"]) {\n\tif (@available(macOS 10.14, *)) {\n\t    [self viewDidChangeEffectiveAppearance];\n\t}\n    }\n}\n\n#endif\n\n/*\n * This is no-op on 10.7 and up because Apple has removed this widget, but we\n * are leaving it here for backwards compatibility.\n */\n\n- (void) tkToolbarButton: (id) sender\n{\n#ifdef TK_MAC_DEBUG_EVENTS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), sender);\n#endif\n    union {XEvent general; XVirtualEvent virt;} event;\n    int x, y;\n    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);\n    Tk_Window tkwin = (Tk_Window)winPtr;\n    (void)sender;\n\n    if (!winPtr){\n\treturn;\n    }\n    bzero(&event, sizeof(event));\n    event.virt.type = VirtualEvent;\n    event.virt.serial = LastKnownRequestProcessed(Tk_Display(tkwin));\n    event.virt.send_event = false;\n    event.virt.display = Tk_Display(tkwin);\n    event.virt.event = Tk_WindowId(tkwin);\n    event.virt.root = XRootWindow(Tk_Display(tkwin), 0);\n    event.virt.subwindow = None;\n    event.virt.time = TkpGetMS();\n    XQueryPointer(NULL, winPtr->window, NULL, NULL,\n\t    &event.virt.x_root, &event.virt.y_root, &x, &y, &event.virt.state);\n    Tk_TopCoordsToWindow(tkwin, x, y, &event.virt.x, &event.virt.y);\n    event.virt.same_screen = true;\n    event.virt.name = Tk_GetUid(\"ToolbarButton\");\n    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);\n}\n\n/*\n * On Catalina this is never called and drawRect clips to the rect that\n * is passed to it by AppKit.\n */\n\n- (BOOL) wantsDefaultClipping\n{\n    return NO;\n}\n\n- (BOOL) acceptsFirstResponder\n{\n    return YES;\n}\n\n/*\n * This keyDown method does nothing, which is a huge improvement over the\n * default keyDown method which beeps every time a key is pressed.\n */\n\n- (void) keyDown: (NSEvent *) theEvent\n{\n    (void)theEvent;\n\n#ifdef TK_MAC_DEBUG_EVENTS\n    TKLog(@\"-[%@(%p) %s] %@\", [self class], self, sel_getName(_cmd), theEvent);\n#endif\n}\n\n/*\n * When the services menu is opened this is called for each Responder in\n * the Responder chain until a service provider is found.  The TKContentView\n * should be the first (and generally only) Responder in the chain.  We\n * return the TkServices object that was created in TkpInit.\n */\n\n- (id)validRequestorForSendType:(NSString *)sendType\n\t\t     returnType:(NSString *)returnType\n{\n    if ([sendType isEqualToString:@\"NSStringPboardType\"] ||\n\t[sendType isEqualToString:@\"NSPasteboardTypeString\"]) {\n\treturn [NSApp servicesProvider];\n    }\n    return [super validRequestorForSendType:sendType returnType:returnType];\n}\n\n-(void) resetTkLayerBitmapContext {\n    NSScreen *screen = [[self window] screen];\n    NSNumber *screenNumber = [[screen deviceDescription]\n\t\t\t\t objectForKey:@\"NSScreenNumber\"];\n    CGDirectDisplayID displayID = [screenNumber unsignedIntValue];\n    CGColorSpaceRef colorspace = CGDisplayCopyColorSpace(displayID);\n    CGContextRef newCtx = CGBitmapContextCreate(\n\t    NULL, self.layer.contentsScale * self.frame.size.width,\n\t    self.layer.contentsScale * self.frame.size.height, 8, 0,\n\t    colorspace,\n\t    // will also need to specify this when capturing\n\t    kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast\n    );\n    // CGDisplayCopyColorSpace retains the colorspace.\n    CGColorSpaceRelease(colorspace);\n    CGContextScaleCTM(newCtx, self.layer.contentsScale,\n\t\t      self.layer.contentsScale);\n#if 0\n    fprintf(stderr, \"rTkLBC %.1f %s %p %p %ld\\n\",\n\t    (float)self.layer.contentsScale,\n\t    NSStringFromSize(self.frame.size).UTF8String, colorspace, newCtx,\n\t    self.tkLayerBitmapContext ?\n\t    (long)CFGetRetainCount(self.tkLayerBitmapContext) : INT_MIN);\n    fprintf(stderr, \"rTkLBC %p %ld\\n\", self.tkLayerBitmapContext,\n\t    (long)(self.tkLayerBitmapContext ?\n\t    CFGetRetainCount(self.tkLayerBitmapContext) : LONG_MIN));\n#endif\n    // The context is also released in TkWmDeadWindow.\n    CGContextRelease(self.tkLayerBitmapContext);\n    self.tkLayerBitmapContext = newCtx;\n}\n\n/*Add support for accessibility in TKContentView.*/\n\nNSMutableArray *_tkAccessibleElements;\n\n+ (BOOL)isAccessibilityElement {\n    return NO;\n}\n\n- (NSArray *)accessibilityChildren {\n    return [_tkAccessibleElements copy];\n}\n\n\n- (void)accessibilityChildrenChanged {\n    NSAccessibilityPostNotification(self, NSAccessibilityCreatedNotification);\n}\n\n- (BOOL)accessibilityIsIgnored {\n    return YES;\n}\n\n- (void)accessibilityAddChildElement:(NSAccessibilityElement *)element {\n\n    if (!_tkAccessibleElements) {\n\t_tkAccessibleElements = [[NSMutableArray alloc ] init];\n    }\n\n    if (element) {\n\t[_tkAccessibleElements addObject:element];\n\t[self accessibilityChildrenChanged];\n    }\n}\n\n- (void)setAccessibilityParentView:(NSView *)parentView {\n    [self setAccessibilityParent:self];\n}\n\n\n@end\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXWm.c",
    "content": "/*\n * tkMacOSXWm.c --\n *\n *\tThis module takes care of the interactions between a Tk-based\n *\tapplication and the window manager. Among other things, it implements\n *\tthe \"wm\" command and passes geometry information to the window manager.\n *\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2010 Kevin Walzer\n * Copyright © 2017-2019 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"tkScrollbar.h\"\n#include \"tkMacOSXWm.h\"\n#include \"tkMacOSXInt.h\"\n#include \"tkMacOSXDebug.h\"\n#include \"tkMacOSXConstants.h\"\n\n/*\n * Setting this to 1 prints when each window is freed, setting it to 2 adds\n * dumps of the autorelease pools, and setting it to 3 also shows each retain\n * and release.\n */\n\n#define DEBUG_ZOMBIES 0\n\n/*\n#ifdef TK_MAC_DEBUG\n#define TK_MAC_DEBUG_WINDOWS\n#endif\n*/\n\n/*\n * Carbon window attributes and classes.\n */\n\n#define WM_NSMASK_SHIFT 36\n#define tkWindowDoesNotHideAttribute \\\n\t((UInt64) 1 << kHIWindowBitDoesNotHide)\n#define tkCanJoinAllSpacesAttribute \\\n\t((UInt64) NSWindowCollectionBehaviorCanJoinAllSpaces << 34)\n#define tkMoveToActiveSpaceAttribute \\\n\t((UInt64) NSWindowCollectionBehaviorMoveToActiveSpace << 34)\n#define tkNonactivatingPanelAttribute \\\n\t((UInt64) NSNonactivatingPanelMask << WM_NSMASK_SHIFT)\n#define tkHUDWindowAttribute \\\n\t((UInt64) NSHUDWindowMask << WM_NSMASK_SHIFT)\n#define tkAlwaysValidAttributes (kWindowNoUpdatesAttribute \\\n\t| kWindowNoActivatesAttribute\t    | kWindowHideOnSuspendAttribute \\\n\t| kWindowHideOnFullScreenAttribute  | kWindowNoConstrainAttribute \\\n\t| kWindowNoShadowAttribute\t    | kWindowLiveResizeAttribute \\\n\t| kWindowOpaqueForEventsAttribute   | kWindowIgnoreClicksAttribute \\\n\t| kWindowDoesNotCycleAttribute\t    | tkWindowDoesNotHideAttribute \\\n\t| tkCanJoinAllSpacesAttribute\t    | tkMoveToActiveSpaceAttribute \\\n\t| tkNonactivatingPanelAttribute\t    | tkHUDWindowAttribute)\n\nstatic const struct {\n    const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs;\n    int flags; NSUInteger styleMask;\n} macClassAttrs[] = {\n    [kAlertWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute, },\n    [kMovableAlertWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute, },\n    [kModalWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute, },\n    [kMovableModalWindowClass] = {\n\t.validAttrs = kWindowCloseBoxAttribute | kWindowMetalAttribute |\n\t\tkWindowFullZoomAttribute | kWindowResizableAttribute,\n\t.defaultAttrs = kWindowDoesNotCycleAttribute, },\n    [kFloatingWindowClass] = {\n\t.validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |\n\t\tkWindowMetalAttribute | kWindowToolbarButtonAttribute |\n\t\tkWindowNoTitleBarAttribute | kWindowFullZoomAttribute |\n\t\tkWindowResizableAttribute | kWindowSideTitlebarAttribute,\n\t.defaultAttrs = kWindowStandardFloatingAttributes |\n\t\tkWindowHideOnSuspendAttribute | kWindowDoesNotCycleAttribute,\n\t.forceOnAttrs = kWindowResizableAttribute,\n\t.forceOffAttrs = kWindowCollapseBoxAttribute,\n\t.styleMask = NSUtilityWindowMask, },\n    [kDocumentWindowClass] = {\n\t.validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |\n\t\tkWindowMetalAttribute | kWindowToolbarButtonAttribute |\n\t\tkWindowNoTitleBarAttribute |\n\t\tkWindowUnifiedTitleAndToolbarAttribute |\n\t\tkWindowInWindowMenuAttribute | kWindowFullZoomAttribute |\n\t\tkWindowResizableAttribute,\n\t.forceOnAttrs = kWindowResizableAttribute,\n\t.defaultAttrs = kWindowStandardDocumentAttributes |\n\t\tkWindowLiveResizeAttribute | kWindowInWindowMenuAttribute, },\n    [kUtilityWindowClass] = {\n\t.validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute |\n\t\tkWindowMetalAttribute | kWindowToolbarButtonAttribute |\n\t\tkWindowNoTitleBarAttribute | kWindowFullZoomAttribute |\n\t\tkWindowResizableAttribute | kWindowSideTitlebarAttribute,\n\t.defaultAttrs = kWindowStandardFloatingAttributes |\n\t\tkWindowHideOnFullScreenAttribute |\n\t\ttkWindowDoesNotHideAttribute | tkNonactivatingPanelAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.forceOnAttrs = kWindowResizableAttribute,\n\t.forceOffAttrs = kWindowCollapseBoxAttribute,\n\t.flags = WM_TOPMOST,\n\t.styleMask = NSUtilityWindowMask, },\n    [kHelpWindowClass] = {\n\t.defaultAttrs = kWindowHideOnSuspendAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.flags = WM_TOPMOST,\n\t.styleMask = 0},\n    [kSheetWindowClass] = {\n\t.validAttrs = kWindowResizableAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.styleMask = NSDocModalWindowMask, },\n    [kToolbarWindowClass] = {\n\t.defaultAttrs = kWindowHideOnSuspendAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.styleMask = NSUtilityWindowMask, },\n    [kPlainWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute, },\n    [kOverlayWindowClass] = {\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.flags = WM_TOPMOST | WM_TRANSPARENT, },\n    [kSheetAlertWindowClass] = {\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute,\n\t.styleMask = NSDocModalWindowMask, },\n    [kAltPlainWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute, },\n    [kSimpleWindowClass] = {\n\t.defaultAttrs = kWindowDoesNotCycleAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute, },\n    [kDrawerWindowClass] = {\n\t.validAttrs = kWindowMetalAttribute | kWindowResizableAttribute,\n\t.forceOnAttrs = kWindowNoTitleBarAttribute |\n\t\tkWindowDoesNotCycleAttribute, },\n};\n\n#define ForceAttributes(attributes, class) \\\n\t((attributes) & (~macClassAttrs[(class)].forceOffAttrs | \\\n\t(macClassAttrs[(class)].forceOnAttrs & ~kWindowResizableAttribute)))\n\n/*\n * Structures and data for the wm attributes command (macOS 10.13 and later):\n */\n\n/* Hash tables for attributes which can be set before a window exists */\nstatic Tcl_HashTable pathnameToSubclass;\nstatic Tcl_HashTable pathnameToTabbingId;\nstatic Tcl_HashTable pathnameToTabbingMode;\n\nenum NSWindowSubclass {\n    subclassNSWindow = 0,\n    subclassNSPanel = 1\n};\n/* This array must be indexed by the enum above.*/\nstatic const char *subclassNames[] = {\"nswindow\", \"nspanel\", NULL};\n\ntypedef struct buttonField_t {\n    unsigned zoom: 1;\n    unsigned miniaturize: 1;\n    unsigned close: 1;\n} buttonField;\n\n/* The order of these names must match the order of the bits above! */\nstatic const char *buttonNames[] = {\"zoom\", \"miniaturize\", \"close\", NULL};\n\ntypedef union windowButtonState_t {\n    int intvalue;\n    buttonField bits;\n} windowButtonState;\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\nenum NSWindowClass {\n    NSWindowClass_any = 0,\n    NSWindowClass_window = 1,\n    NSWindowClass_panel = 2\n};\ntypedef struct styleMaskBit_t {\n    const char *bitname;\n    unsigned long bitvalue;\n    enum NSWindowClass allowed;\n} styleMaskBit;\n\nstatic const styleMaskBit styleMaskBits[] = {\n    /* Make the titlebar visible and use round corners. */\n    {\"titled\", NSWindowStyleMaskTitled, NSWindowClass_window},\n    /* Enable the close button. */\n    {\"closable\", NSWindowStyleMaskClosable, NSWindowClass_window},\n    /* Enable the miniaturize button. */\n    {\"miniaturizable\", NSWindowStyleMaskMiniaturizable, NSWindowClass_window},\n    /* Allow the user to resize the window. */\n    {\"resizable\", NSWindowStyleMaskResizable, NSWindowClass_window},\n    /*\n     * Make the content view extend under the titlebar.  We force\n     * titlebarAppearsTransparent when this bit is set.  Otherwise it is\n     * pretty useless.\n     */\n    {\"fullsizecontentview\", NSWindowStyleMaskFullSizeContentView, NSWindowClass_window},\n    /* Rounded corners, cannot have a titlebar (overrides titled bit). */\n    {\"docmodal\", NSWindowStyleMaskDocModalWindow, NSWindowClass_any},\n    /* ============================================\n     * The following bits are only valid for panels.\n     */\n    /* Make the title bar thinner. */\n    {\"utility\", NSWindowStyleMaskUtilityWindow, NSWindowClass_panel},\n    /* Do not activate the app when the window is activated. */\n    {\"nonactivatingpanel\", NSWindowStyleMaskNonactivatingPanel, NSWindowClass_panel},\n    /*\n     * Requires utility.  Cannot be resizable.  Close button is an X; no other buttons.\n     * Cannot be a docmodal.\n     */\n    {\"HUDwindow\", NSWindowStyleMaskHUDWindow, NSWindowClass_panel},\n    {NULL, 0, NSWindowClass_any}\n};\n\ntypedef struct tabbingMode_t {\n    const char *modeName;\n    long modeValue;\n} tabbingMode;\n\nstatic const tabbingMode tabbingModes[] = {\n    {\"auto\",  NSWindowTabbingModeAutomatic},\n    {\"disallowed\", NSWindowTabbingModeDisallowed},\n    {\"preferred\", NSWindowTabbingModePreferred},\n    {NULL, -1}\n};\n\nstatic const char *const appearanceStrings[] = {\n    \"aqua\", \"auto\", \"darkaqua\", NULL\n};\nenum appearances {\n    APPEARANCE_AQUA, APPEARANCE_AUTO, APPEARANCE_DARKAQUA\n};\n\nstatic Bool wantsToBeTab(NSWindow *macWindow) {\n    Bool result;\n    switch ([macWindow tabbingMode]) {\n    case NSWindowTabbingModeDisallowed:\n\tresult = False;\n\tbreak;\n    case NSWindowTabbingModePreferred:\n\tresult = True;\n\tbreak;\n    case NSWindowTabbingModeAutomatic:\n\tresult = ([NSWindow userTabbingPreference] ==\n\t\tNSWindowUserTabbingPreferenceAlways);\n\tbreak;\n    default:\n\tresult = False;\n\tbreak;\n    }\n    return result;\n}\n\n/*\n * Helper for the tkLayoutChanged methods.  Synchronizes Tk's understanding of\n * the bounds of a contentView with the window's.  It is needed because there\n * are situations when the window manager can change the layout of an NSWindow\n * without having been requested to do so by Tk.  Examples are when a window\n * goes FullScreen or shows a tab bar.  NSWindow methods which involve such\n * layout changes should be overridden or protected by methods which call this.\n */\n\nstatic void syncLayout(NSWindow *macWindow)\n{\n    TkWindow *winPtr = TkMacOSXGetTkWindow(macWindow);\n\n    if (winPtr) {\n\t// Using screen coordinates with origin at bottom left.\n\tNSRect frameRect = [macWindow frame];\n\t// This accounts for the tab bar, if there is one.\n\tNSRect contentRect = [macWindow contentRectForFrameRect: frameRect];\n\tWmInfo *wmPtr = winPtr->wmInfoPtr;\n\n\t// The parent includes the title bar, tab bar and window frame.\n\twmPtr->xInParent = frameRect.origin.x - contentRect.origin.x;\n\twmPtr->yInParent = (frameRect.origin.y + frameRect.size.height -\n\t    contentRect.origin.y - contentRect.size.height);\n\twmPtr->parentWidth = winPtr->changes.width + frameRect.size.width -\n\t    contentRect.size.width;\n\twmPtr->parentHeight = winPtr->changes.height + frameRect.size.height -\n\t    contentRect.size.height;\n\tTkMacOSXInvalClipRgns((Tk_Window)winPtr);\n    }\n}\n#endif\n\ntypedef enum {\n    WMATT_ALPHA, WMATT_APPEARANCE, WMATT_BUTTONS, WMATT_FULLSCREEN,\n    WMATT_ISDARK, WMATT_MODIFIED, WMATT_NOTIFY, WMATT_TITLEPATH, WMATT_TOPMOST,\n    WMATT_TRANSPARENT, WMATT_STYLEMASK, WMATT_CLASS, WMATT_TABBINGID,\n    WMATT_TABBINGMODE, WMATT_TYPE, _WMATT_LAST_ATTRIBUTE\n} WmAttribute;\n\nstatic const char *const WmAttributeNames[] = {\n    \"-alpha\", \"-appearance\", \"-buttons\", \"-fullscreen\", \"-isdark\", \"-modified\",\n    \"-notify\", \"-titlepath\", \"-topmost\", \"-transparent\", \"-stylemask\", \"-class\",\n    \"-tabbingid\", \"-tabbingmode\", \"-type\", NULL\n};\n\n/*\n * The variable below is used to enable or disable tracing in this module. If\n * tracing is enabled, then information is printed on standard output about\n * interesting interactions with the window manager.\n */\n\nstatic int wmTracing = 0;\n\n/*\n * The following structure is the official type record for geometry management\n * of top-level windows.\n */\n\nstatic void TopLevelReqProc(void *dummy, Tk_Window tkwin);\n\nstatic const Tk_GeomMgr wmMgrType = {\n    \"wm\",\t\t\t/* name */\n    TopLevelReqProc,\t\t/* requestProc */\n    NULL,\t\t\t/* lostContentProc */\n};\n\n/*\n * The following keeps state for Aqua dock icon bounce notification.\n */\n\nstatic int tkMacOSXWmAttrNotifyVal = 0;\n\n/*\n * Declarations of static functions defined in this file:\n */\n\nstatic NSRect\t\tInitialWindowBounds(TkWindow *winPtr,\n\t\t\t    NSWindow *macWindow);\nstatic int\t\tParseGeometry(Tcl_Interp *interp, char *string,\n\t\t\t    TkWindow *winPtr);\nstatic void\t\tTopLevelEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tWmStackorderToplevelWrapperMap(TkWindow *winPtr,\n\t\t\t    Display *display, Tcl_HashTable *table);\nstatic void\t\tUpdateGeometryInfo(void *clientData);\nstatic void\t\tUpdateSizeHints(TkWindow *winPtr);\nstatic void\t\tUpdateVRootGeometry(WmInfo *wmPtr);\nstatic int\t\tWmAspectCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmClientCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmColormapwindowsCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmCommandCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmForgetCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFrameCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGridCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGroupCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbadgeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmManageCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmOverrideredirectCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmResizableCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStateCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTitleCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTransientCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tWmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);\nstatic int\t\tWmWinStyle(Tcl_Interp *interp, TkWindow *winPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int\t\tWmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,\n\t\t\t    Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic void\t\tApplyWindowAttributeFlagChanges(TkWindow *winPtr,\n\t\t\t    NSWindow *macWindow, UInt64 oldAttributes,\n\t\t\t    int oldFlags, int create, int initial);\nstatic void\t\tApplyContainerOverrideChanges(TkWindow *winPtr,\n\t\t\t    NSWindow *macWindow);\nstatic void\t\tGetMinSize(TkWindow *winPtr, int *minWidthPtr,\n\t\t\t    int *minHeightPtr);\nstatic void\t\tGetMaxSize(TkWindow *winPtr, int *maxWidthPtr,\n\t\t\t    int *maxHeightPtr);\nstatic void\t\tRemapWindows(TkWindow *winPtr,\n\t\t\t    MacDrawable *parentWin);\nstatic void             RemoveTransient(TkWindow *winPtr);\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n\n/*\n * Add a window as a tab in the group specified by its tabbingid, or\n * make it a standalone window if it is the only window with that\n * tabbingid.  Adjust the window size if a tab bar appeared or\n * disappeared.\n */\n\nstatic void placeAsTab(TKWindow *macWindow) {\n    TkWindow *winPtr = NULL, *winPtr2 = NULL;\n    TKWindow *target = NULL, *sibling = NULL;\n    NSString *identifier = [macWindow tabbingIdentifier];\n    if (!wantsToBeTab(macWindow)) {\n\t[macWindow moveTabToNewWindow:NSApp];\n\t[(TKWindow *)target tkLayoutChanged];\n\treturn;\n    }\n    for (NSWindow *window in [NSApp windows]) {\n\tif (window == macWindow) {\n\t    continue;\n\t}\n\tif ([identifier isEqualTo: [window tabbingIdentifier]] &&\n\t    wantsToBeTab(window)) {\n\t    target = (TKWindow*) window;\n\t    syncLayout(target);\n\t    break;\n\t}\n    }\n    syncLayout(macWindow);\n    NSArray<NSWindow *> *tabs = [macWindow tabbedWindows];\n    if ([tabs count] == 2) {\n\tsibling = tabs[0] == macWindow ? (TKWindow *)tabs[1] : (TKWindow *)tabs[0];\n\tsyncLayout(sibling);\n\twinPtr2 = TkMacOSXGetTkWindow(sibling);\n    }\n    if (target) {\n\tCGFloat winHeight = [macWindow contentRectForFrameRect:\n\t\t\t\t[macWindow frame]].size.height;\n\tCGFloat winDelta = 0, targetHeight, targetDelta = 0;\n\ttargetHeight =  [target contentRectForFrameRect:\n\t\t\t    [target frame]].size.height;\n\t[target addTabbedWindow:macWindow ordered:NSWindowAbove];\n\ttargetDelta = targetHeight - [target contentRectForFrameRect:\n\t\t\t\t\t [target frame]].size.height;\n\twinDelta = winHeight - [target contentRectForFrameRect:\n\t\t\t\t   [target frame]].size.height;\n\tif (winDelta) {\n\t    winPtr = TkMacOSXGetTkWindow(macWindow);\n\t    XMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t      winPtr->changes.x, winPtr->changes.y,\n\t\t\t      winPtr->changes.width, winPtr->changes.height + winDelta );\n\t    if (sibling) {\n\t\twinPtr = TkMacOSXGetTkWindow(sibling);\n\t\tXMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t\t  winPtr->changes.x, winPtr->changes.y,\n\t\t\t\t  winPtr->changes.width, winPtr->changes.height - winDelta );\n\t    }\n\t}\n\tif (targetDelta) {\n\t    winPtr = TkMacOSXGetTkWindow(target);\n\t    XMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t      winPtr->changes.x, winPtr->changes.y,\n\t\t\t      winPtr->changes.width, winPtr->changes.height + targetDelta );\n\t}\n    } else {\n\tCGFloat height = [macWindow contentRectForFrameRect:\n\t\t\t     [macWindow frame]].size.height;\n\t[macWindow moveTabToNewWindow:NSApp];\n\tCGFloat delta = height - [macWindow contentRectForFrameRect:\n\t\t\t    [macWindow frame]].size.height;\n\twinPtr = TkMacOSXGetTkWindow(macWindow);\n\tXMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t  winPtr->changes.x, winPtr->changes.y,\n\t\t\t  winPtr->changes.width, winPtr->changes.height + delta);\n\tif (winPtr2) {\n\t    XMoveResizeWindow(winPtr2->display, winPtr2->window,\n\t\t\t      winPtr2->changes.x, winPtr2->changes.y,\n\t\t\t      winPtr2->changes.width, winPtr2->changes.height + delta );\n\t}\n    }\n}\n#endif\n\n#pragma mark NSWindow(TKWm)\n\n@implementation NSWindow(TKWm)\n\n- (NSPoint) tkConvertPointToScreen: (NSPoint) point\n{\n    NSRect pointrect = {point, {0,0}};\n    return [self convertRectToScreen:pointrect].origin;\n}\n\n- (NSPoint) tkConvertPointFromScreen: (NSPoint)point\n{\n    NSRect pointrect = {point, {0,0}};\n    return [self convertRectFromScreen:pointrect].origin;\n}\n@end\n\n#pragma mark -\n\n@implementation TKPanel: NSPanel\n@synthesize tkWindow = _tkWindow;\n\n- (void) tkLayoutChanged\n{\n    syncLayout(self);\n}\n\n@end\n\n@implementation TKDrawerWindow: NSWindow\n@synthesize tkWindow = _tkWindow;\n@end\n\n@implementation TKWindow: NSWindow\n@synthesize tkWindow = _tkWindow;\n@end\n\n#pragma mark TKWindow(TKWm)\n\n@implementation TKWindow(TKWm)\n\n- (void) tkLayoutChanged\n{\n    syncLayout(self);\n}\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n- (void)toggleTabBar:(id)sender\n{\n    TkWindow *winPtr = TkMacOSXGetTkWindow(self);\n    if (!winPtr) {\n\treturn;\n    }\n    [super toggleTabBar:sender];\n    [self tkLayoutChanged];\n}\n#endif\n\n- (NSSize)windowWillResize:(NSWindow *)sender\n\t\t    toSize:(NSSize)frameSize\n{\n    NSRect currentFrame = [sender frame];\n    TkWindow *winPtr = TkMacOSXGetTkWindow(sender);\n    if (winPtr) {\n\tif (winPtr->wmInfoPtr->flags & WM_WIDTH_NOT_RESIZABLE) {\n\t    frameSize.width = currentFrame.size.width;\n\t}\n\tif (winPtr->wmInfoPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {\n\t    frameSize.height = currentFrame.size.height;\n\t}\n    }\n    return frameSize;\n}\n\n- (BOOL) canBecomeKeyWindow\n{\n    if ([NSApp tkWillExit]) {\n\treturn NO;\n    }\n    TkWindow *winPtr = TkMacOSXGetTkWindow(self);\n\n    if (!winPtr || !winPtr->wmInfoPtr) {\n\treturn NO;\n    }\n    return (winPtr->wmInfoPtr &&\n\t    (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||\n\t     winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)\n\t    ) ? NO : YES;\n}\n\n#if DEBUG_ZOMBIES\n- (id) retain\n{\n    id result = [super retain];\n    const char *title = [[self title] UTF8String];\n    if (title == nil) {\n\ttitle = \"unnamed window\";\n    }\n    if (DEBUG_ZOMBIES > 2) {\n\tfprintf(stderr, \"Retained <%s>. Count is: %lu\\n\",\n\t\ttitle, [self retainCount]);\n    }\n    return result;\n}\n\n- (id) autorelease\n{\n    id result = [super autorelease];\n    const char *title = [[self title] UTF8String];\n    if (title == nil) {\n\ttitle = \"unnamed window\";\n    }\n    if (DEBUG_ZOMBIES > 2) {\n\tfprintf(stderr, \"Autoreleased <%s>. Count is %lu\\n\",\n\t\ttitle, [self retainCount]);\n    }\n    return result;\n}\n\n- (oneway void) release {\n    const char *title = [[self title] UTF8String];\n    if (title == nil) {\n\ttitle = \"unnamed window\";\n    }\n    if (DEBUG_ZOMBIES > 2) {\n\tfprintf(stderr, \"Releasing <%s>. Count is %lu\\n\",\n\t\ttitle, [self retainCount]);\n    }\n    [super release];\n}\n\n- (void) dealloc {\n    const char *title = [[self title] UTF8String];\n    if (title == nil) {\n\ttitle = \"unnamed window\";\n    }\n    if (DEBUG_ZOMBIES > 0) {\n\tfprintf(stderr, \">>>> Freeing <%s>. Count is %lu\\n\",\n\t\ttitle, [self retainCount]);\n    }\n    [super dealloc];\n}\n\n#endif\n@end\n\n#pragma mark -\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetWindowSizeLimits --\n *\n *\tSets NSWindow size limits\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSetWindowSizeLimits(\n    TkWindow *winPtr)\n{\n    NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int minWidth, minHeight, maxWidth, maxHeight, base;\n\n    if (!macWindow) {\n\treturn;\n    }\n    GetMinSize(winPtr, &minWidth, &minHeight);\n    GetMaxSize(winPtr, &maxWidth, &maxHeight);\n    if (wmPtr->gridWin) {\n\tbase = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tminWidth = base + (minWidth * wmPtr->widthInc);\n\tmaxWidth = base + (maxWidth * wmPtr->widthInc);\n\tbase = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tminHeight = base + (minHeight * wmPtr->heightInc);\n\tmaxHeight = base + (maxHeight * wmPtr->heightInc);\n    }\n    if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {\n\tminWidth = maxWidth = wmPtr->configWidth;\n    }\n    if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {\n\tminHeight = maxHeight = wmPtr->configHeight;\n    }\n    if (wmPtr->gridWin) {\n\t[macWindow setResizeIncrements:NSMakeSize(wmPtr->widthInc,\n\t\twmPtr->heightInc)];\n    } else if (wmPtr->sizeHintsFlags & PAspect && wmPtr->minAspect.x ==\n\t    wmPtr->maxAspect.x && wmPtr->minAspect.y == wmPtr->maxAspect.y) {\n\tNSSize aspect = NSMakeSize(wmPtr->minAspect.x, wmPtr->minAspect.y);\n\tCGFloat ratio = aspect.width/aspect.height;\n\n\t[macWindow setContentAspectRatio:aspect];\n\tif ((CGFloat)minWidth/(CGFloat)minHeight > ratio) {\n\t    minHeight = lround(minWidth / ratio);\n\t} else {\n\t    minWidth = lround(minHeight * ratio);\n\t}\n\tif ((CGFloat)maxWidth/(CGFloat)maxHeight > ratio) {\n\t    maxWidth = lround(maxHeight * ratio);\n\t} else {\n\t    maxHeight = lround(maxWidth / ratio);\n\t}\n\tif ((CGFloat)wmPtr->configWidth/(CGFloat)wmPtr->configHeight > ratio) {\n\t    wmPtr->configWidth = lround(wmPtr->configHeight * ratio);\n\t    if (wmPtr->configWidth < minWidth) {\n\t\twmPtr->configWidth = minWidth;\n\t\twmPtr->configHeight = minHeight;\n\t    }\n\t} else {\n\t    wmPtr->configHeight = lround(wmPtr->configWidth / ratio);\n\t    if (wmPtr->configHeight < minHeight) {\n\t\twmPtr->configWidth = minWidth;\n\t\twmPtr->configHeight = minHeight;\n\t    }\n\t}\n    } else {\n\t[macWindow setResizeIncrements:NSMakeSize(1.0, 1.0)];\n    }\n    [macWindow setContentMinSize:NSMakeSize(minWidth, minHeight)];\n    [macWindow setContentMaxSize:NSMakeSize(maxWidth, maxHeight)];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FrontMostToplevelAtPoint --\n *\n *  Determine the frontmost toplevel window on the screen at a given\n *  screen location. The location must be inside the toplevel's content\n *  frame, not inside the title bar.\n *\n * Results:\n *  A pointer to the TkWindow structure for the toplevel window, or NULL\n *  if the location isn't inside any toplevel.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkWindow*\nFrontMostToplevelAtPoint(\n    int x,\n    int y)\n{\n    NSPoint p = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);\n\n    for (NSWindow *w in [NSApp orderedWindows]) {\n\tTkWindow *winPtr = TkMacOSXGetTkWindow(w);\n\tif (winPtr && Tk_IsMapped(winPtr)) {\n\t    NSRect windowFrame = [w frame];\n\t    NSRect contentFrame = windowFrame;\n\n\t    /*\n\t     * For consistency with other platforms, points in the\n\t     * title bar are not considered to be contained in the\n\t     * window.\n\t     */\n\n\t    contentFrame.size.height = [[w contentView] frame].size.height;\n\t    if (NSMouseInRect(p, contentFrame, NO)) {\n\t\treturn winPtr;\n\t    } else if (NSMouseInRect(p, windowFrame, NO)) {\n\t\t/*\n\t\t * The pointer is in the title bar of the highest NSWindow\n\t\t * containing it, and therefore it should not be considered\n\t\t * to be contained in any Tk window.\n\t\t */\n\t\treturn NULL;\n\t    }\n\t}\n    }\n    return NULL;\n}\n\f\nvoid TkMacOSXAssignNewKeyWindow(\n    Tcl_Interp *interp,\n    NSWindow *ignore)\n{\n    TkWindow *winPtr;\n\n    /*\n     * Avoid bug 5692042764: set tkEventTarget to NULL if there is no window to\n     * send Tk events to.\n     */\n\n    [NSApp setTkEventTarget: NULL];\n    for (NSWindow *w in [NSApp orderedWindows]) {\n\tWmInfo *wmPtr;\n\tBOOL isOnScreen;\n\twinPtr = TkMacOSXGetTkWindow(w);\n\tif (!winPtr\n\t    || !winPtr->wmInfoPtr\n\t    || (winPtr->flags & TK_ALREADY_DEAD)) {\n\t    continue;\n\t}\n\tif (interp && interp != Tk_Interp((Tk_Window) winPtr)) {\n\t    continue;\n\t}\n\twmPtr = winPtr->wmInfoPtr;\n\tisOnScreen = (wmPtr->hints.initial_state != IconicState &&\n\t\t      wmPtr->hints.initial_state != WithdrawnState);\n\tif (w != ignore && isOnScreen && [w canBecomeKeyWindow]) {\n\t    TKMenu *menu;\n\t    [w makeKeyAndOrderFront:NSApp];\n\t    /* Set the menubar for the new front window. */\n\t    if (winPtr->wmInfoPtr &&\n\t\twinPtr->wmInfoPtr->menuPtr &&\n\t\twinPtr->wmInfoPtr->menuPtr->mainMenuPtr) {\n\t\tmenu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;\n\t\t[NSApp tkSetMainMenu:menu];\n\t\t[NSApp setTkEventTarget: winPtr];\n\t    }\n\t    break;\n\t}\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkWmNewWindow --\n *\n *\tThis procedure is invoked whenever a new top-level window is created.\n *\tIts job is to initialize the WmInfo structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA WmInfo structure gets allocated and initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmNewWindow(\n    TkWindow *winPtr)\t\t/* Newly-created top-level window. */\n{\n    WmInfo *wmPtr = (WmInfo *)Tcl_Alloc(sizeof(WmInfo));\n\n    wmPtr->winPtr = winPtr;\n    wmPtr->reparent = None;\n    wmPtr->titleUid = NULL;\n    wmPtr->iconName = NULL;\n    wmPtr->container = NULL;\n    wmPtr->hints.flags = InputHint | StateHint;\n    wmPtr->hints.input = True;\n    wmPtr->hints.initial_state = NormalState;\n    wmPtr->hints.icon_pixmap = None;\n    wmPtr->hints.icon_window = None;\n    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;\n    wmPtr->hints.icon_mask = None;\n    wmPtr->hints.window_group = None;\n    wmPtr->leaderName = NULL;\n    wmPtr->icon = NULL;\n    wmPtr->iconFor = NULL;\n    wmPtr->transientPtr = NULL;\n    wmPtr->sizeHintsFlags = 0;\n    wmPtr->minWidth = wmPtr->minHeight = 1;\n    wmPtr->maxWidth = 0;\n    wmPtr->maxHeight = 0;\n    wmPtr->gridWin = NULL;\n    wmPtr->widthInc = wmPtr->heightInc = 1;\n    wmPtr->minAspect.x = wmPtr->minAspect.y = 1;\n    wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;\n    wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;\n    wmPtr->gravity = NorthWestGravity;\n    wmPtr->width = -1;\n    wmPtr->height = -1;\n    wmPtr->x = winPtr->changes.x;\n    wmPtr->y = winPtr->changes.y;\n    wmPtr->parentWidth = winPtr->changes.width\n\t    + 2*winPtr->changes.border_width;\n    wmPtr->parentHeight = winPtr->changes.height\n\t    + 2*winPtr->changes.border_width;\n    wmPtr->xInParent = 0;\n    wmPtr->yInParent = 0;\n    wmPtr->cmapList = NULL;\n    wmPtr->cmapCount = 0;\n    wmPtr->configX = 0;\n    wmPtr->configY = 0;\n    wmPtr->configWidth = -1;\n    wmPtr->configHeight = -1;\n    wmPtr->vRoot = None;\n    wmPtr->protPtr = NULL;\n    wmPtr->commandObj = NULL;\n    wmPtr->clientMachine = NULL;\n    wmPtr->flags = WM_NEVER_MAPPED;\n    wmPtr->macClass = kDocumentWindowClass;\n    wmPtr->attributes = macClassAttrs[kDocumentWindowClass].defaultAttrs;\n    wmPtr->scrollWinPtr = NULL;\n    wmPtr->menuPtr = NULL;\n    wmPtr->window = nil;\n    winPtr->wmInfoPtr = wmPtr;\n\n    // initialize wmPtr->NSWindowSubclass here\n\n    UpdateVRootGeometry(wmPtr);\n\n    /*\n     * Tk must monitor structure events for top-level windows, in order to\n     * detect size and position changes caused by window managers.\n     */\n\n    Tk_CreateEventHandler((Tk_Window)winPtr, StructureNotifyMask,\n\t    TopLevelEventProc, winPtr);\n\n    /*\n     * Arrange for geometry requests to be reflected from the window to the\n     * window manager.\n     */\n\n    Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmMapWindow --\n *\n *\tThis procedure is invoked to map a top-level window. This module gets\n *\ta chance to update all window-manager-related information in\n *\tproperties before the window manager sees the map event and checks the\n *\tproperties. It also gets to decide whether or not to even map the\n *\twindow after all.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties of winPtr may get updated to provide up-to-date information\n *\tto the window manager. The window may also get mapped, but it may not\n *\tbe if this procedure decides that isn't appropriate (e.g. because the\n *\twindow is withdrawn).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmMapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * mapped. */\n{\n    if (Tk_IsMapped(winPtr)) {\n\treturn;\n    }\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    XEvent event;\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\t/*\n\t * Create the underlying Mac window for this Tk window.\n\t */\n\n\tif (!TkMacOSXHostToplevelExists(winPtr)) {\n\t    TkMacOSXMakeRealWindowExist(winPtr);\n\t}\n\n\twmPtr->flags &= ~WM_NEVER_MAPPED;\n\n\t/*\n\t * Generate configure event when we first map the window.\n\t */\n\n\tTkGenWMConfigureEvent((Tk_Window)winPtr, wmPtr->x, wmPtr->y, -1, -1,\n\t\tTK_LOCATION_CHANGED);\n\n\t/*\n\t * This is the first time this window has ever been mapped. Store all\n\t * the window-manager-related information for the window.\n\t */\n\n\tif (wmPtr->titleUid == NULL) {\n\t    wmPtr->titleUid = winPtr->nameUid;\n\t}\n\n\tif (!Tk_IsEmbedded(winPtr)) {\n\t    TkSetWMName(winPtr, wmPtr->titleUid);\n\t}\n\n\tTkWmSetClass(winPtr);\n\n\tif (wmPtr->iconName != NULL) {\n\t    XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);\n\t}\n\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    }\n    if (wmPtr->hints.initial_state == WithdrawnState) {\n\treturn;\n    }\n\n    /*\n     * TODO: we need to display a window if it's iconic on creation.\n     */\n\n    if (wmPtr->hints.initial_state == IconicState) {\n\treturn;\n    }\n\n    /*\n     * Update geometry information.\n     */\n\n    wmPtr->flags |= WM_ABOUT_TO_MAP;\n    if (wmPtr->flags & WM_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n    }\n    UpdateGeometryInfo(winPtr);\n    wmPtr->flags &= ~WM_ABOUT_TO_MAP;\n\n    /*\n     * Map the window and process a MapNotify event for it.\n     */\n\n    winPtr->flags |= TK_MAPPED;\n    XMapWindow(winPtr->display, winPtr->window);\n    event.xany.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xany.send_event = False;\n    event.xany.display = winPtr->display;\n    event.xmap.window = winPtr->window;\n    event.xmap.type = MapNotify;\n    event.xmap.event = winPtr->window;\n    event.xmap.override_redirect = winPtr->atts.override_redirect;\n    Tk_HandleEvent(&event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmUnmapWindow --\n *\n *\tThis procedure is invoked to unmap a top-level window. On the\n *\tMacintosh all we do is call XUnmapWindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUnmaps the window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmUnmapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * unmapped. */\n{\n    if (!Tk_IsMapped(winPtr)) {\n\treturn;\n    }\n    if ((winPtr->window != None)\n\t    && (XUnmapWindow(winPtr->display, winPtr->window) == Success)) {\n\twinPtr->flags &= ~TK_MAPPED;\n\tXEvent event;\n\tevent.xany.serial = LastKnownRequestProcessed(winPtr->display);\n\tevent.xany.send_event = False;\n\tevent.xany.display = winPtr->display;\n\tevent.xunmap.type = UnmapNotify;\n\tevent.xunmap.window = winPtr->window;\n\tevent.xunmap.event = winPtr->window;\n\tevent.xunmap.from_configure = false;\n\tTk_HandleEvent(&event);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmDeadWindow --\n *\n *\tThis procedure is invoked when a top-level window is about to be\n *\tdeleted. It cleans up the wm-related data structures for the window.\n *      If the dead window contains the pointer, TkUpdatePointer is called\n *      to tell Tk which window will be the new pointer window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe WmInfo structure for winPtr gets freed.  Tk's cached pointer\n *      window may change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmDeadWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's being deleted. */\n{\n    TkWindow *winPtr2;\n    NSWindow *w;\n    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;\n    TKWindow *deadNSWindow = NULL;\n    if (Tk_WindowId(winPtr) == None) {\n\tfprintf(stderr, \"TkWmDeadWindow: no window id\\n\");\n    } else {\n\tdeadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable(Tk_WindowId(winPtr));\n    }\n    /*\n     *If the dead window is a transient, remove it from the container's list.\n     */\n\n    RemoveTransient(winPtr);\n    Tk_ManageGeometry((Tk_Window)winPtr, NULL, NULL);\n    Tk_DeleteEventHandler((Tk_Window)winPtr, StructureNotifyMask,\n\t    TopLevelEventProc, winPtr);\n    if (wmPtr->hints.flags & IconPixmapHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n    }\n    if (wmPtr->hints.flags & IconMaskHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n    }\n    if (wmPtr->iconName != NULL) {\n\tTcl_Free(wmPtr->iconName);\n    }\n    if (wmPtr->leaderName != NULL) {\n\tTcl_Free(wmPtr->leaderName);\n    }\n    if (wmPtr->icon != NULL) {\n\twmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;\n\twmPtr2->iconFor = NULL;\n    }\n    if (wmPtr->iconFor != NULL) {\n\twmPtr2 = ((TkWindow *)wmPtr->iconFor)->wmInfoPtr;\n\twmPtr2->icon = NULL;\n\twmPtr2->hints.flags &= ~IconWindowHint;\n    }\n    while (wmPtr->protPtr != NULL) {\n\tProtocolHandler *protPtr = wmPtr->protPtr;\n\twmPtr->protPtr = protPtr->nextPtr;\n\tTcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n    }\n    if (wmPtr->commandObj != NULL) {\n\tTcl_DecrRefCount(wmPtr->commandObj);\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    if (wmPtr->flags & WM_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n    }\n\n    /*\n     * If the dead window has a transient, remove references to it from\n     * the transient.\n     */\n\n    for (Transient *transientPtr = wmPtr->transientPtr;\n\t    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {\n\tTkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(\n\t    transientPtr->winPtr);\n\tif (containerPtr == winPtr) {\n\t    wmPtr2 = transientPtr->winPtr->wmInfoPtr;\n\t    wmPtr2->container = NULL;\n\t}\n    }\n\n    while (wmPtr->transientPtr != NULL) {\n\tTransient *transientPtr = wmPtr->transientPtr;\n\n\twmPtr->transientPtr = transientPtr->nextPtr;\n\tTcl_Free(transientPtr);\n    }\n\n    /*\n     * Remove references to the Tk window from the mouse event processing\n     * state which is recorded in the NSApplication object and notify Tk\n     * of the new pointer window.\n     */\n\n    NSPoint mouse = [NSEvent mouseLocation];\n    [NSApp setTkPointerWindow:nil];\n    winPtr2 = NULL;\n\n    for (w in [NSApp orderedWindows]) {\n\tif (w == deadNSWindow || w == NULL) {\n\t    continue;\n\t}\n\twinPtr2 = TkMacOSXGetTkWindow(w);\n\tif (winPtr2 == NULL) {\n\t    continue;\n\t}\n\tif (NSPointInRect(mouse, [w frame])) {\n\t    [NSApp setTkPointerWindow: winPtr2];\n\t    break;\n\t}\n    }\n    if (winPtr2) {\n\t/*\n\t * We now know which toplevel will contain the pointer when the window\n\t * is destroyed.  We need to know which Tk window within the\n\t * toplevel will contain the pointer.\n\t */\n\tNSPoint local = [w tkConvertPointFromScreen: mouse];\n\tint top_x = floor(local.x),\n\t    top_y = floor(w.frame.size.height - local.y);\n\tint root_x = floor(mouse.x),\n\t    root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y);\n\tint win_x, win_y;\n\tTk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y);\n\t/*\n\t * A non-toplevel window can have a NULL parent while it is in the process of\n\t * being destroyed.  We should not call Tk_UpdatePointer in that case.\n\t */\n\tif (Tk_Parent(target) != NULL || Tk_IsTopLevel(target)) {\n\t    Tk_UpdatePointer(target, root_x, root_y, [NSApp tkButtonState]);\n\t}\n    }\n\n    /*\n     * Unregister the NSWindow and remove all references to it from the Tk\n     * data structures.  If the NSWindow is a child, disassociate it from\n     * the parent.  Then close and release the NSWindow.\n     */\n\n    if (deadNSWindow && !Tk_IsEmbedded(winPtr)) {\n\tNSWindow *parent = [deadNSWindow parentWindow];\n\t[deadNSWindow setTkWindow:None];\n\tif (winPtr->window) {\n\t    ((MacDrawable *)winPtr->window)->view = nil;\n\t}\n\twmPtr->window = NULL;\n\n\tif (parent) {\n\t    [parent removeChildWindow:deadNSWindow];\n\t}\n\n#if DEBUG_ZOMBIES > 1\n\t{\n\t    const char *title = [[deadNSWindow title] UTF8String];\n\t    if (title == nil) {\n\t\ttitle = \"unnamed window\";\n\t    }\n\t    fprintf(stderr, \">>>> Closing <%s>. Count is: %lu\\n\", title,\n\t\t    [deadNSWindow retainCount]);\n\t}\n#endif\n\n\t/*\n\t * When a window is closed we want to move the focus to the next\n\t * highest window.  Apple's documentation says that calling the\n\t * orderOut method of the key window will accomplish this.  But\n\t * experiment shows that this is not the case.  So we have to reset the\n\t * key window ourselves.  When the window is the last one on the screen\n\t * there is no choice for a new key window.  Moreover, if the host\n\t * computer has a TouchBar then the TouchBar holds a reference to the\n\t * key window which prevents it from being deallocated until it stops\n\t * being the key window.  On these systems the only option for\n\t * preventing zombies is to set the key window to nil.\n\t */\n\n\t/*\n\t * Prevent zombies on systems with a TouchBar.\n\t */\n\n\tif (deadNSWindow == [NSApp keyWindow]) {\n\t    [NSApp _setKeyWindow:nil];\n\t    [NSApp _setMainWindow:nil];\n\t}\n\n\t/*\n\t * Find a new keyWindow.  It will be assinged as the new\n\t * TkEventTarget when [NSApp WindowActivation] is called..\n\t */\n\n\tTkMacOSXAssignNewKeyWindow(Tk_Interp((Tk_Window) winPtr), deadNSWindow);\n\n\t/*\n\t * Avoid redrawing the view after it is released.\n\t */\n\n\tTKContentView *deadView = [deadNSWindow contentView];\n\tTcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask, (void *) deadView);\n\tTcl_CancelIdleCall(TkMacOSXUpdateViewIdleTask, (void *) deadView);\n\tCGContextRelease(deadView.tkLayerBitmapContext);\n\t[deadNSWindow close];\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\tNSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];\n\t[preferences removeObserver:deadNSWindow.contentView\n\t\t      forKeyPath:@\"AppleHighlightColor\"];\n#endif\n\t[deadNSWindow release];\n\n#if DEBUG_ZOMBIES > 1\n\tfprintf(stderr, \"================= Pool dump ===================\\n\");\n\t[NSAutoreleasePool showPools];\n#endif\n\n    }\n\n    /*\n     * Deallocate the wmInfo and clear the wmInfoPtr.\n     */\n\n    Tcl_Free(wmPtr);\n    winPtr->wmInfoPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmSetClass --\n *\n *\tThis procedure is invoked whenever a top-level window's class is\n *\tchanged. If the window has been mapped then this procedure updates the\n *\twindow manager property for the class. If the window hasn't been\n *\tmapped, the update is deferred until just before the first mapping.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA window property may get updated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmSetClass(\n    TCL_UNUSED(TkWindow *))\t\t/* Newly-created top-level window. */\n{\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_WmObjCmd --\n *\n *\tThis procedure is invoked to process the \"wm\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_WmObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    static const char *const optionStrings[] = {\n\t\"aspect\", \"attributes\", \"client\", \"colormapwindows\",\n\t\"command\", \"deiconify\", \"focusmodel\", \"forget\",\n\t\"frame\", \"geometry\", \"grid\", \"group\", \"iconbadge\",\n\t\"iconbitmap\", \"iconify\", \"iconmask\", \"iconname\",\n\t\"iconphoto\", \"iconposition\", \"iconwindow\",\n\t\"manage\", \"maxsize\", \"minsize\", \"overrideredirect\",\n\t\"positionfrom\", \"protocol\", \"resizable\", \"sizefrom\",\n\t\"stackorder\", \"state\", \"title\", \"transient\",\n\t\"withdraw\", NULL };\n    enum options {\n\tWMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,\n\tWMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET,\n\tWMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP,  WMOPT_ICONBADGE,\n\tWMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME,\n\tWMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW,\n\tWMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT,\n\tWMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM,\n\tWMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT,\n\tWMOPT_WITHDRAW };\n    int index;\n    Tcl_Size length;\n    char *argv1;\n    TkWindow *winPtr;\n\n    if (objc < 2) {\n    wrongNumArgs:\n\tTcl_WrongNumArgs(interp, 1, objv, \"option window ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    argv1 = Tcl_GetStringFromObj(objv[1], &length);\n    if ((argv1[0] == 't') && (strncmp(argv1, \"tracing\", length) == 0)\n\t    && (length >= 3)) {\n\tif ((objc != 2) && (objc != 3)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?boolean?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(wmTracing));\n\t    return TCL_OK;\n\t}\n\treturn Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing);\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (objc < 3) {\n\tgoto wrongNumArgs;\n    }\n    if (index == WMOPT_ATTRIBUTES && objc == 5 &&\n\tstrcmp(Tcl_GetString(objv[3]), \"-class\") == 0) {\n\tif (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr)\n\t    == TCL_OK) {\n\t    if (winPtr->wmInfoPtr->window != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Cannot change the class after the mac window is created.\",-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CLASS_CHANGE\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t\twinPtr = NULL;\n\t}\n    } else if (index == WMOPT_ATTRIBUTES && objc == 5 &&\n\t       strcmp(Tcl_GetString(objv[3]), \"-tabbingid\") == 0) {\n\t    if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr)\n\t\t!= TCL_OK) {\n\t\twinPtr = NULL;\n\t    }\n    } else if (index == WMOPT_ATTRIBUTES && objc == 5 &&\n\t       strcmp(Tcl_GetString(objv[3]), \"-tabbingmode\") == 0) {\n\t    if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr)\n\t\t!= TCL_OK) {\n\t\twinPtr = NULL;\n\t    }\n    } else if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr)\n\t       != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (winPtr && !Tk_IsTopLevel(winPtr)\n\t    && (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" isn't a top-level window\", winPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TOPLEVEL\", winPtr->pathName,\n\t\tNULL);\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case WMOPT_ASPECT:\n\treturn WmAspectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ATTRIBUTES:\n\treturn WmAttributesCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_CLIENT:\n\treturn WmClientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COLORMAPWINDOWS:\n\treturn WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COMMAND:\n\treturn WmCommandCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_DEICONIFY:\n\treturn WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FOCUSMODEL:\n\treturn WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FORGET:\n\treturn WmForgetCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FRAME:\n\treturn WmFrameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GEOMETRY:\n\treturn WmGeometryCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GRID:\n\treturn WmGridCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GROUP:\n\treturn WmGroupCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBADGE:\n\treturn WmIconbadgeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBITMAP:\n\treturn WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONIFY:\n\treturn WmIconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONMASK:\n\treturn WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONNAME:\n\treturn WmIconnameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPHOTO:\n\treturn WmIconphotoCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPOSITION:\n\treturn WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONWINDOW:\n\treturn WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MANAGE:\n\treturn WmManageCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MAXSIZE:\n\treturn WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MINSIZE:\n\treturn WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_OVERRIDEREDIRECT:\n\treturn WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_POSITIONFROM:\n\treturn WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_PROTOCOL:\n\treturn WmProtocolCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_RESIZABLE:\n\treturn WmResizableCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_SIZEFROM:\n\treturn WmSizefromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STACKORDER:\n\treturn WmStackorderCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STATE:\n\treturn WmStateCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TITLE:\n\treturn WmTitleCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TRANSIENT:\n\treturn WmTransientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_WITHDRAW:\n\treturn WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);\n    }\n\n    /* This should not happen */\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAspectCmd --\n *\n *\tThis procedure is invoked to process the \"wm aspect\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAspectCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int numer1, denom1, numer2, denom2;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?minNumer minDenom maxNumer maxDenom?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PAspect) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~PAspect;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||\n\t\t(denom2 <= 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"aspect number can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ASPECT\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr->minAspect.x = numer1;\n\twmPtr->minAspect.y = denom1;\n\twmPtr->maxAspect.x = numer2;\n\twmPtr->maxAspect.y = denom2;\n\twmPtr->sizeHintsFlags |= PAspect;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmSetAttribute --\n *\n *\tHelper routine for WmAttributesCmd. Sets the value of the specified\n *\tattribute.\n *\n * Returns:\n *\n *\tTCL_OK if successful, TCL_ERROR otherwise. In case of an error, leaves\n *\ta message in the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmSetAttribute(\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    NSWindow *macWindow,\n    Tcl_Interp *interp,\t\t/* Current interpreter */\n    WmAttribute attribute,\t/* Code of attribute to set */\n    Tcl_Obj *value)\t\t/* New value */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int boolValue;\n    NSString *identifier;\n\n    switch (attribute) {\n    case WMATT_ALPHA: {\n\tdouble dval;\n\n\tif (Tcl_GetDoubleFromObj(interp, value, &dval) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * The user should give (transparent) 0 .. 1.0 (opaque)\n\t */\n\n\tif (dval < 0.0) {\n\t    dval = 0.0;\n\t} else if (dval > 1.0) {\n\t    dval = 1.0;\n\t}\n\t[macWindow setAlphaValue:dval];\n\tbreak;\n    }\n    case WMATT_APPEARANCE: {\n\tint index;\n\tif (Tcl_GetIndexFromObjStruct(interp, value, appearanceStrings,\n\t    sizeof(char *), \"appearancename\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((enum appearances) index) {\n\tcase APPEARANCE_AQUA:\n\t    macWindow.appearance = [NSAppearance appearanceNamed:\n\t\tNSAppearanceNameAqua];\n\t    break;\n\tcase APPEARANCE_DARKAQUA:\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t    if (@available(macOS 10.14, *)) {\n\t\tmacWindow.appearance = [NSAppearance appearanceNamed:\n\t\t    NSAppearanceNameDarkAqua];\n\t    }\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t    break;\n\tdefault:\n\t    macWindow.appearance = nil;\n\t}\n\tbreak;\n    }\n    case WMATT_BUTTONS: {\n\twindowButtonState state = {0};\n\tTcl_Obj **elements;\n\tTcl_Size nElements, i;\n\tif (Tcl_ListObjGetElements(interp, value, &nElements, &elements) == TCL_OK) {\n\t    int index = 0;\n\t    for (i = 0; i < nElements; i++) {\n\t\tif (Tcl_GetIndexFromObjStruct(interp, elements[i], buttonNames,\n\t\t       sizeof(char *), \"window button name\", 0, &index) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t} else {\n\t\t    state.intvalue |= (1 << index);\n\t\t}\n\t    }\n\t} else if (Tcl_GetIntFromObj(interp, value, &state.intvalue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tNSButton *closer = [macWindow standardWindowButton:\n\t\t\t       NSWindowCloseButton];\n\tNSButton *miniaturizer = [macWindow standardWindowButton:\n\t\t\t\t     NSWindowMiniaturizeButton];\n\tNSButton *zoomer = [macWindow standardWindowButton:\n\t\t\t      NSWindowZoomButton];\n\tcloser.enabled = (state.bits.close != 0);\n\tminiaturizer.enabled = (state.bits.miniaturize != 0);\n\tzoomer.enabled = (state.bits.zoom != 0);\n\tbreak;\n    }\n    case WMATT_FULLSCREEN:\n\tif (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue != (([macWindow styleMask] & NSFullScreenWindowMask) != 0)) {\n\t    [macWindow toggleFullScreen:macWindow];\n\t}\n\tbreak;\n    case WMATT_MODIFIED:\n\tif (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue != [macWindow isDocumentEdited]) {\n\t    [macWindow setDocumentEdited:(BOOL)boolValue];\n\t}\n\tbreak;\n    case WMATT_NOTIFY:\n\tif (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue == !tkMacOSXWmAttrNotifyVal) {\n\t    static NSInteger request = -1;\n\n\t    if (request >= 0) {\n\t\t[NSApp cancelUserAttentionRequest:request];\n\t\trequest = -1;\n\t    }\n\t    if (boolValue) {\n\t\trequest = [NSApp requestUserAttention:NSCriticalRequest];\n\t    }\n\t    tkMacOSXWmAttrNotifyVal = boolValue;\n\t}\n\tbreak;\n    case WMATT_STYLEMASK: {\n\tunsigned long styleMaskValue = 0;\n\tTcl_Obj **elements;\n\tTcl_Size nElements, i;\n\tif (Tcl_ListObjGetElements(interp, value, &nElements, &elements) == TCL_OK) {\n\t    int index;\n\t    for (i = 0; i < nElements; i++) {\n\t\tif (Tcl_GetIndexFromObjStruct(interp, elements[i], styleMaskBits,\n\t\t       sizeof(styleMaskBit), \"styleMask bit\", 0, &index) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t} else if (![macWindow isKindOfClass: [NSPanel class]] &&\n\t\t\t   styleMaskBits[index].allowed == NSWindowClass_panel) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"styleMask bit \\\"%s\\\" can only be used with an NSPanel\",\n\t\t\tstyleMaskBits[index].bitname));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"INVALID_STYLEMASK_BIT\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t} else {\n\t\t    styleMaskValue |= styleMaskBits[index].bitvalue;\n\t\t}\n\t\t/*\n\t\t * Be sure not to change the fullscreen bit.\n\t\t */\n\t\tstyleMaskValue |= (NSWindowStyleMaskFullScreen & macWindow.styleMask);\n\t    }\n\t    /*\n\t     * A resizable docmodal NSWindow or NSPanel does not work\n\t     * correctly.  It cannot be resized from the top edge.  Other bits,\n\t     * such as titled are ignored for docmodals.  To be safe, we clear\n\t     * all other bits when the docmodal bit is set.\n\t     */\n\t    if (styleMaskValue & NSDocModalWindowMask) {\n\t\tstyleMaskValue &= ~NSWindowStyleMaskResizable;\n\t    }\n\t    if ([macWindow isKindOfClass: [NSPanel class]]) {\n\t\t/*\n\t\t * We always make NSPanels titled, nonactivating utility windows,\n\t\t * even if these bits are not requested in the command.\n\t\t */\n\t\tif (!(styleMaskValue & NSWindowStyleMaskTitled) ) {\n\t\t    styleMaskValue |= NSWindowStyleMaskTitled;\n\t\t    styleMaskValue |= NSWindowStyleMaskUtilityWindow;\n\t\t    styleMaskValue |= NSWindowStyleMaskNonactivatingPanel;\n\t\t}\n\t    }\n\t    if (styleMaskValue & NSWindowStyleMaskFullSizeContentView) {\n\t\tmacWindow.titlebarAppearsTransparent = YES;\n\t    } else {\n\t\tmacWindow.titlebarAppearsTransparent = NO;\n\t    }\n\t} else {\n\t    return TCL_ERROR;\n\t}\n\tNSRect oldFrame = [macWindow frame];\n#ifdef DEBUG\n\tfprintf(stderr, \"Current styleMask: %lx\\n\", [macWindow styleMask]);\n\tfprintf(stderr, \"Setting styleMask to %lx\\n\", styleMaskValue);\n#endif\n\tmacWindow.styleMask = (unsigned long) styleMaskValue;\n\tNSRect newFrame = [macWindow frame];\n\tint heightDiff = newFrame.size.height - oldFrame.size.height;\n\tint newHeight = heightDiff < 0 ? newFrame.size.height :\n\t    newFrame.size.height - heightDiff;\n\t[(TKWindow *)macWindow tkLayoutChanged];\n\tif (heightDiff) {\n\t    // Calling XMoveResizeWindow twice is a hack to force a relayout\n\t    // of the window.\n\t    XMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t  winPtr->changes.x, winPtr->changes.y,\n\t\t\t  newFrame.size.width, newHeight - 1);\n\t    XMoveResizeWindow(winPtr->display, winPtr->window,\n\t\t\t  winPtr->changes.x, winPtr->changes.y,\n\t\t\t  newFrame.size.width, newHeight);\n\t}\n\tbreak;\n    }\n    case WMATT_TABBINGID: {\n\tNSString *oldId = [macWindow tabbingIdentifier];\n\tchar *valueString;\n\tTcl_Size length;\n\tif ([NSApp macOSVersion] < 101300) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t  \"Tabbing identifiers require macOS 10.13\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TABBINGID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tvalueString = Tcl_GetStringFromObj(value, &length);\n\tidentifier = [NSString stringWithUTF8String:valueString];\n\t[macWindow setTabbingIdentifier: identifier];\n\n\t/*\n\t * If the tabbingIdentifier of a tab is changed we move it into\n\t * the tab group with that identifier.\n\t */\n\n\tif ([oldId compare:identifier] != NSOrderedSame) {\n\t    placeAsTab((TKWindow *)macWindow);\n\t}\n\tbreak;\n    }\n    case WMATT_TABBINGMODE: {\n\tint index;\n\ttabbingMode mode;\n\tif (Tcl_GetIndexFromObjStruct(interp, value, tabbingModes,\n\t   sizeof(tabbingMode), \"NSWindow Tabbing Mode\", 0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\tmode = tabbingModes[index];\n\t[macWindow setTabbingMode: mode.modeValue];\n\tplaceAsTab((TKWindow *)macWindow);\n\tbreak;\n    }\n    case WMATT_ISDARK: {\n\tbreak;\n    }\n    case WMATT_TITLEPATH: {\n\tconst char *path = (const char *)Tcl_FSGetNativePath(value);\n\tNSString *filename = @\"\";\n\n\tif (path && *path) {\n\t    filename = [NSString stringWithUTF8String:path];\n\t}\n\t[macWindow setRepresentedFilename:filename];\n\tbreak;\n    }\n    case WMATT_TOPMOST:\n\tif (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue != ((wmPtr->flags & WM_TOPMOST) != 0)) {\n\t    int oldFlags = wmPtr->flags;\n\n\t    if (boolValue) {\n\t\twmPtr->flags |= WM_TOPMOST;\n\t    } else {\n\t\twmPtr->flags &= ~WM_TOPMOST;\n\t    }\n\t    ApplyWindowAttributeFlagChanges(winPtr, macWindow,\n\t\t    wmPtr->attributes, oldFlags, 1, 0);\n\t}\n\tbreak;\n    case WMATT_TRANSPARENT:\n\tif (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (boolValue != ((wmPtr->flags & WM_TRANSPARENT) != 0)) {\n\t    UInt64 oldAttributes = wmPtr->attributes;\n\t    int oldFlags = wmPtr->flags;\n\n\t    if (boolValue) {\n\t\twmPtr->flags |= WM_TRANSPARENT;\n\t\twmPtr->attributes |= kWindowNoShadowAttribute;\n\t    } else {\n\t\twmPtr->flags &= ~WM_TRANSPARENT;\n\t\twmPtr->attributes &= ~kWindowNoShadowAttribute;\n\t    }\n\t    ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,\n\t\t    oldFlags, 1, 0);\n\t    [macWindow setBackgroundColor:boolValue ? [NSColor clearColor] : nil];\n\t    [macWindow setOpaque:!boolValue];\n\t    TkMacOSXInvalidateWindow((MacDrawable *)winPtr->window,\n\t\t    TK_PARENT_WINDOW);\n\t    }\n\tbreak;\n    case WMATT_CLASS:\n\tbreak;\n    case WMATT_TYPE:\n\tTKLog(@\"The type attribute is ignored on macOS.\");\n\tbreak;\n    case _WMATT_LAST_ATTRIBUTE:\n    default:\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGetAttribute --\n *\n *\tHelper routine for WmAttributesCmd. Returns the current value of the\n *\tspecified attribute.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nWmGetAttribute(\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    NSWindow *macWindow,\n    WmAttribute attribute)\t/* Code of attribute to get */\n{\n    Tcl_Obj *result = NULL;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    switch (attribute) {\n    case WMATT_ALPHA:\n\tresult = Tcl_NewDoubleObj([macWindow alphaValue]);\n\tbreak;\n    case WMATT_APPEARANCE: {\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n\tNSAppearanceName appearance;\n#else\n\tNSString *appearance;\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n\tconst char *resultString = \"unrecognized\";\n\tappearance = macWindow.appearance.name;\n\tif (appearance == nil) {\n\t    resultString = appearanceStrings[APPEARANCE_AUTO];\n\t} else if (appearance == NSAppearanceNameAqua) {\n\t    resultString = appearanceStrings[APPEARANCE_AQUA];\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t} else if (@available(macOS 10.14, *)) {\n\t    if (appearance == NSAppearanceNameDarkAqua) {\n\t\tresultString = appearanceStrings[APPEARANCE_DARKAQUA];\n\t    }\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t}\n\tresult = Tcl_NewStringObj(resultString, TCL_INDEX_NONE);\n\tbreak;\n    }\n    case WMATT_BUTTONS: {\n\tresult = Tcl_NewListObj(3, NULL);\n\tif ([macWindow standardWindowButton:NSWindowCloseButton].enabled) {\n\t    Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(\"close\", TCL_INDEX_NONE));\n\t}\n\tif ([macWindow standardWindowButton:NSWindowMiniaturizeButton].enabled) {\n\t    Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(\"miniaturize\", TCL_INDEX_NONE));\n\t}\n\tif ([macWindow standardWindowButton:NSWindowZoomButton].enabled) {\n\t    Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(\"zoom\", TCL_INDEX_NONE));\n\t}\n\tbreak;\n    }\n    case WMATT_CLASS:\n\tif ([macWindow isKindOfClass:[NSPanel class]]) {\n\t    result = Tcl_NewStringObj(subclassNames[subclassNSPanel], TCL_INDEX_NONE);\n\t} else {\n\t    result = Tcl_NewStringObj(subclassNames[subclassNSWindow], TCL_INDEX_NONE);\n\t}\n\tbreak;\n    case WMATT_FULLSCREEN:\n\tresult = Tcl_NewBooleanObj([macWindow styleMask] & NSFullScreenWindowMask);\n\tbreak;\n    case WMATT_ISDARK:\n\tresult = Tcl_NewBooleanObj(TkMacOSXInDarkMode((Tk_Window)winPtr));\n\tbreak;\n    case WMATT_MODIFIED:\n\tresult = Tcl_NewBooleanObj([macWindow isDocumentEdited]);\n\tbreak;\n    case WMATT_NOTIFY:\n\tresult = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal);\n\tbreak;\n    case WMATT_STYLEMASK: {\n\tunsigned long styleMaskValue = [macWindow styleMask];\n\tconst styleMaskBit *bit;\n\tresult = Tcl_NewListObj(9, NULL);\n\tfor (bit = styleMaskBits; bit->bitname != NULL; bit++) {\n\t    if (styleMaskValue & bit->bitvalue) {\n\t\tTcl_ListObjAppendElement(NULL, result,\n\t\t    Tcl_NewStringObj(bit->bitname, TCL_INDEX_NONE));\n\t    }\n\t}\n\tbreak;\n    }\n    case WMATT_TABBINGID:\n\tresult = Tcl_NewStringObj([[macWindow tabbingIdentifier] UTF8String],\n\t\t-1);\n\tbreak;\n    case WMATT_TABBINGMODE: {\n\tlong mode = [macWindow tabbingMode];\n\tconst char *name = \"unrecognized\";\n\tfor (const tabbingMode *m = tabbingModes; m->modeName != NULL; m++) {\n\t    if (m->modeValue == mode) {\n\t\tname = m->modeName;\n\t\tbreak;\n\t    }\n\t}\n\tresult = Tcl_NewStringObj(name, TCL_INDEX_NONE);\n\tbreak;\n    }\n    case WMATT_TITLEPATH:\n\tresult = Tcl_NewStringObj([[macWindow representedFilename] UTF8String],\n\t\tTCL_INDEX_NONE);\n\tbreak;\n    case WMATT_TOPMOST:\n\tresult = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST);\n\tbreak;\n    case WMATT_TRANSPARENT:\n\tresult = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT);\n\tbreak;\n    case WMATT_TYPE:\n\tresult = Tcl_NewStringObj(\"unsupported\", TCL_INDEX_NONE);\n\tbreak;\n    case _WMATT_LAST_ATTRIBUTE:\n    default:\n\tbreak;\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAttributesCmd --\n *\n *\tThis procedure is invoked to process the \"wm attributes\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAttributesCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int attribute = 0;\n    NSWindow *macWindow;\n    if (winPtr == NULL && objc == 5) {\n\tint index, isNew = 0;\n\tTcl_Size length;\n\n\t/*\n\t * If we are setting an atttribute of a future window, save the value\n\t * in a hash table so we can look it up when the window is actually\n\t * created.\n\t */\n\n\tif (strcmp(Tcl_GetString(objv[3]), \"-class\") == 0) {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[4], subclassNames,\n\t\t    sizeof(char *), \"NSWindow subclass\", 0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToSubclass,\n\t\tTcl_GetString(objv[2]), &isNew);\n\t    if (hPtr) {\n\t\tTcl_SetHashValue(hPtr, INT2PTR(index));\n\t\treturn TCL_OK;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[3]), \"-tabbingid\") == 0) {\n\t    char *identifier = Tcl_GetStringFromObj(objv[4], &length);\n\t    char *value = (char *)Tcl_Alloc(length + 1);\n\t    strncpy(value, identifier, length + 1);\n\t    Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToTabbingId,\n\t\t\t\t      Tcl_GetString(objv[2]), &isNew);\n\t    if (hPtr) {\n\t\tTcl_SetHashValue(hPtr, value);\n\t\treturn TCL_OK;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[3]), \"-tabbingmode\") == 0) {\n\t    long value = NSWindowTabbingModeAutomatic;\n\t    int modeIndex;\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[4], tabbingModes,\n\t       sizeof(tabbingMode), \"NSWindow Tabbing Mode\", 0, &modeIndex) == TCL_OK) {\n\t\tvalue = tabbingModes[modeIndex].modeValue;\n\t    }\n\t    Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToTabbingMode,\n\t\tTcl_GetString(objv[2]), &isNew);\n\t    if (hPtr) {\n\t\tTcl_SetHashValue(hPtr, value);\n\t\treturn TCL_OK;\n\t    }\n\t}\n    }\n    if (!winPtr) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t   \"Only -class, -tabbingid, or -tabbingmode can be set before the window exists.\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"NO_WINDOW\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (winPtr && winPtr->window == None) {\n\tTk_MakeWindowExist((Tk_Window)winPtr);\n    }\n    if (!TkMacOSXHostToplevelExists(winPtr)) {\n\tTkMacOSXMakeRealWindowExist(winPtr);\n    }\n    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n\n    if (objc == 3) {\t\t/* wm attributes $win */\n\tTcl_Obj *result = Tcl_NewObj();\n\n\tfor (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) {\n\t    Tcl_ListObjAppendElement(NULL, result,\n\t\t    Tcl_NewStringObj(WmAttributeNames[attribute], TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(NULL, result,\n\t\t    WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute));\n\t}\n\tTcl_SetObjResult(interp, result);\n    } else if (objc == 4) {\t/* wm attributes $win -attribute */\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames,\n\t\tsizeof(char *), \"attribute\", 0, &attribute) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute));\n    } else if ((objc - 3) % 2 == 0) {\t/* wm attributes $win -att value... */\n\tTcl_Size i;\n\n\tfor (i = 3; i < objc; i += 2) {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames,\n\t\t    sizeof(char *), \"attribute\", 0, &attribute) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (WmSetAttribute(winPtr, macWindow, interp, (WmAttribute)attribute, objv[i+1])\n\t\t    != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    } else {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?-attribute ?value ...??\");\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmClientCmd --\n *\n *\tThis procedure is invoked to process the \"wm client\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmClientCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    char *argv3;\n    Tcl_Size length;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(wmPtr->clientMachine, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    if (argv3[0] == 0) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_Free(wmPtr->clientMachine);\n\t    wmPtr->clientMachine = NULL;\n\t}\n\treturn TCL_OK;\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    wmPtr->clientMachine = (char *)Tcl_Alloc(length + 1);\n    strcpy(wmPtr->clientMachine, argv3);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmColormapwindowsCmd --\n *\n *\tThis procedure is invoked to process the \"wm colormapwindows\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmColormapwindowsCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    TkWindow **cmapList, *winPtr2;\n    Tcl_Size i, windowObjc;\n    int gotToplevel = 0;\n    Tcl_Obj **windowObjv, *resultObj;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?windowList?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTk_MakeWindowExist((Tk_Window)winPtr);\n\tresultObj = Tcl_NewObj();\n\tfor (i = 0; i < wmPtr->cmapCount; i++) {\n\t    if ((i == (wmPtr->cmapCount-1))\n\t\t    && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {\n\t\tbreak;\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, resultObj,\n\t\t    Tk_NewWindowObj((Tk_Window)wmPtr->cmapList[i]));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    cmapList = (TkWindow **)Tcl_Alloc((windowObjc+1) * sizeof(TkWindow*));\n    for (i = 0; i < windowObjc; i++) {\n\tif (TkGetWindowFromObj(interp, tkwin, windowObjv[i],\n\t\t(Tk_Window *) &winPtr2) != TCL_OK) {\n\t    Tcl_Free(cmapList);\n\t    return TCL_ERROR;\n\t}\n\tif (winPtr2 == winPtr) {\n\t    gotToplevel = 1;\n\t}\n\tif (winPtr2->window == None) {\n\t    Tk_MakeWindowExist((Tk_Window)winPtr2);\n\t}\n\tcmapList[i] = winPtr2;\n    }\n    if (!gotToplevel) {\n\twmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;\n\tcmapList[windowObjc] = winPtr;\n\twindowObjc++;\n    } else {\n\twmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;\n    }\n    wmPtr->flags |= WM_COLORMAPS_EXPLICIT;\n    if (wmPtr->cmapList != NULL) {\n\tTcl_Free(wmPtr->cmapList);\n    }\n    wmPtr->cmapList = cmapList;\n    wmPtr->cmapCount = windowObjc;\n\n    /*\n     * On the Macintosh all of this is just an excercise in compatibility as\n     * we don't support colormaps. If we did they would be installed here.\n     */\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmCommandCmd --\n *\n *\tThis procedure is invoked to process the \"wm command\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmCommandCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tcl_Size len;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?value?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->commandObj != NULL) {\n\t    Tcl_SetObjResult(interp, wmPtr->commandObj);\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\tif (wmPtr->commandObj != NULL) {\n\t    Tcl_DecrRefCount(wmPtr->commandObj);\n\t    wmPtr->commandObj = NULL;\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_ListObjLength(interp, objv[3], &len) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->commandObj != NULL) {\n\tTcl_DecrRefCount(wmPtr->commandObj);\n    }\n    wmPtr->commandObj = Tcl_DuplicateObj(objv[3]);\n    Tcl_IncrRefCount(wmPtr->commandObj);\n    Tcl_InvalidateStringRep(wmPtr->commandObj);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmDeiconifyCmd --\n *\n *\tThis procedure is invoked to process the \"wm deiconify\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmDeiconifyCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    NSWindow *win = nil;\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't deiconify %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"DEICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (winPtr->flags & TK_EMBEDDED) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't deiconify %s: it is an embedded window\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"DEICONIFY\", \"EMBEDDED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (winPtr->window) {\n\twin = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n    TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ?\n\t    ZoomState : NormalState);\n    if (win) {\n\t[win setExcludedFromWindowsMenu:NO];\n\tTkMacOSXApplyWindowAttributes(winPtr, win);\n\t[win orderFront:NSApp];\n    }\n    if (wmPtr->icon) {\n\tTk_UnmapWindow((Tk_Window)wmPtr->icon);\n    }\n\n    /*\n     * If this window has a transient, the transient must also be deiconified if\n     * it was withdrawn by the container.\n     */\n\n    for (Transient *transientPtr = wmPtr->transientPtr;\n\t    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {\n\tTkWindow *winPtr2 = transientPtr->winPtr;\n\tWmInfo *wmPtr2 = winPtr2->wmInfoPtr;\n\tTkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);\n\n\tif (containerPtr == winPtr) {\n\t    if ((wmPtr2->hints.initial_state == WithdrawnState) &&\n\t\t    ((transientPtr->flags & WITHDRAWN_BY_CONTAINER) != 0)) {\n\t\tTkpWmSetState(winPtr2, NormalState);\n\t\ttransientPtr->flags &= ~WITHDRAWN_BY_CONTAINER;\n\t    }\n\t}\n    }\n\n    //Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFocusmodelCmd --\n *\n *\tThis procedure is invoked to process the \"wm focusmodel\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFocusmodelCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"active\", \"passive\", NULL };\n    enum options {\n\tOPT_ACTIVE, OPT_PASSIVE };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?active|passive?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\twmPtr->hints.input ? \"passive\" : \"active\", TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t    sizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (index == OPT_ACTIVE) {\n\twmPtr->hints.input = False;\n    } else { /* OPT_PASSIVE */\n\twmPtr->hints.input = True;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmForgetCmd --\n *\n *\tThis procedure is invoked to process the \"wm forget\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmForgetCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t\t/* Toplevel or Frame to work with */\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t/* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window)winPtr;\n\n    /*\n     * Tk ticket c77b426d: avoid panic on usage after wm forget\n     */\n\n    if (Tk_IsTopLevel(frameWin) && Tk_IsManageable(frameWin)) {\n\tMacDrawable *macWin;\n\n\tTk_MakeWindowExist(frameWin);\n\tif (winPtr->parentPtr) {\n\t    Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);\n\t}\n\tmacWin = (MacDrawable *)winPtr->window;\n\n\tTkFocusJoin(winPtr);\n\tTk_UnmapWindow(frameWin);\n\n\tmacWin->toplevel->referenceCount--;\n\tmacWin->flags &= ~TK_HOST_EXISTS;\n\tif (winPtr->parentPtr) {\n\t    macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;\n\t    macWin->toplevel->referenceCount++;\n\t    RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window);\n\t}\n\t/*\n\t * Make sure wm no longer manages this window\n\t */\n\tTk_ManageGeometry(frameWin, NULL, NULL);\n\n\twinPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);\n\n\t/*\n\t * Flags (above) must be cleared before calling TkMapTopFrame (below).\n\t */\n\n\tTkMapTopFrame(frameWin);\n    } else {\n\t/*\n\t * Already not managed by wm - ignore it.\n\t */\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFrameCmd --\n *\n *\tThis procedure is invoked to process the \"wm frame\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFrameCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Window window;\n    char buf[TCL_INTEGER_SPACE];\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    window = wmPtr->reparent;\n    if (window == None) {\n\twindow = Tk_WindowId((Tk_Window)winPtr);\n    }\n    snprintf(buf, sizeof(buf), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)window);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGeometryCmd --\n *\n *\tThis procedure is invoked to process the \"wm geometry\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGeometryCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    NSWindow *win = nil;\n    char xSign = '+', ySign = '+';\n    int width, height, x = wmPtr->x, y= wmPtr->y;\n    char *argv3;\n    if (winPtr && winPtr->window) {\n\twin = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newGeometry?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->gridWin != NULL) {\n\t    width = wmPtr->reqGridWidth + (winPtr->changes.width\n\t\t    - winPtr->reqWidth)/wmPtr->widthInc;\n\t    height = wmPtr->reqGridHeight + (winPtr->changes.height\n\t\t    - winPtr->reqHeight)/wmPtr->heightInc;\n\t} else {\n\t    width = winPtr->changes.width;\n\t    height = winPtr->changes.height;\n\t}\n\tif (win) {\n\t    if (wmPtr->flags & WM_NEGATIVE_X) {\n\t\txSign = '-';\n\t\tx = wmPtr->vRootWidth - wmPtr->x\n\t\t    - (width + (wmPtr->parentWidth - winPtr->changes.width));\n\t    }\n\t    if (wmPtr->flags & WM_NEGATIVE_Y) {\n\t\tySign = '-';\n\t\ty = wmPtr->vRootHeight - wmPtr->y\n\t\t    - (height + (wmPtr->parentHeight - winPtr->changes.height));\n\t    }\n\t}\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%dx%d%c%d%c%d\",\n\t\twidth, height, xSign, x, ySign, y));\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n\tWmUpdateGeom(wmPtr, winPtr);\n\treturn TCL_OK;\n    }\n    return ParseGeometry(interp, argv3, winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGridCmd --\n *\n *\tThis procedure is invoked to process the \"wm grid\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGridCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int reqWidth, reqHeight, widthInc, heightInc;\n    const char *errorMsg;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?baseWidth baseHeight widthInc heightInc?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PBaseSize) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\t/*\n\t * Turn off gridding and reset the width and height to make sense as\n\t * ungridded numbers.\n\t */\n\n\twmPtr->sizeHintsFlags &= ~PBaseSize;\n\tif (wmPtr->width != -1) {\n\t    wmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t    - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t    wmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t    - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t}\n\twmPtr->widthInc = 1;\n\twmPtr->heightInc = 1;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &heightInc)!=TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif (reqWidth < 0) {\n\t    errorMsg = \"baseWidth can't be < 0\";\n\t    goto error;\n\t} else if (reqHeight < 0) {\n\t    errorMsg = \"baseHeight can't be < 0\";\n\t    goto error;\n\t} else if (widthInc <= 0) {\n\t    errorMsg = \"widthInc can't be <= 0\";\n\t    goto error;\n\t} else if (heightInc <= 0) {\n\t    errorMsg = \"heightInc can't be <= 0\";\n\t    goto error;\n\t}\n\tTk_SetGrid((Tk_Window)winPtr, reqWidth, reqHeight, widthInc,\n\t\theightInc);\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMsg, TCL_INDEX_NONE));\n    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"GRID\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGroupCmd --\n *\n *\tThis procedure is invoked to process the \"wm group\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGroupCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    char *argv3;\n    Tcl_Size length;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & WindowGroupHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    if (*argv3 == '\\0') {\n\twmPtr->hints.flags &= ~WindowGroupHint;\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->leaderName = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTk_MakeWindowExist(tkwin2);\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->hints.window_group = Tk_WindowId(tkwin2);\n\twmPtr->hints.flags |= WindowGroupHint;\n\twmPtr->leaderName = (char *)Tcl_Alloc(length + 1);\n\tstrcpy(wmPtr->leaderName, argv3);\n    }\n    return TCL_OK;\n}\n\f\n /*----------------------------------------------------------------------\n *\n * WmIconbadgeCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconbadge\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbadgeCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    (void) winPtr;\n    NSString *label;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv,\"window badge\");\n\treturn TCL_ERROR;\n    }\n\n    label = [NSString stringWithUTF8String:Tcl_GetString(objv[3])];\n\n    int number = [label intValue];\n    NSDockTile *dockicon = [NSApp dockTile];\n\n    /*\n     * First, check that the label is not a decimal. If it is,\n     * return an error.\n     */\n\n    if ([label containsString:@\".\"]) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use \\\"%s\\\" as icon badge\", Tcl_GetString(objv[3])));\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Next, check that label is an int, empty string, or exclamation\n     * point. If so, set the icon badge on the Dock icon. Otherwise,\n     * return an error.\n     */\n\n    NSArray *array = @[@\"\", @\"!\"];\n    if ([array containsObject: label]) {\n\t[dockicon setBadgeLabel:label];\n    } else if (number > 0) {\n\tNSString *str = [@(number) stringValue];\n\t[dockicon setBadgeLabel:str];\n    } else {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use \\\"%s\\\" as icon badge\", Tcl_GetString(objv[3])));\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconbitmapCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconbitmap\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbitmapCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Pixmap pixmap;\n    char *str;\n    Tcl_Size len;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?bitmap?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconPixmapHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display,wmPtr->hints.icon_pixmap),\n\t\t    -1));\n\t}\n\treturn TCL_OK;\n    }\n    str = Tcl_GetStringFromObj(objv[3], &len);\n    if (winPtr->window == None) {\n\tTk_MakeWindowExist((Tk_Window)winPtr);\n    }\n    if (!TkMacOSXHostToplevelExists(winPtr)) {\n\tTkMacOSXMakeRealWindowExist(winPtr);\n    }\n    if (WmSetAttribute(winPtr, TkMacOSXGetNSWindowForDrawable(winPtr->window), interp,\n\t    WMATT_TITLEPATH, objv[3]) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!len) {\n\tif (wmPtr->hints.icon_pixmap != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n\t    wmPtr->hints.icon_pixmap = None;\n\t}\n\twmPtr->hints.flags &= ~IconPixmapHint;\n    } else {\n\tpixmap = Tk_GetBitmap(interp, (Tk_Window)winPtr, str);\n\tif (pixmap == None) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_pixmap = pixmap;\n\twmPtr->hints.flags |= IconPixmapHint;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconifyCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconify\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconifyCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"OVERRIDE_REDIRECT\",\n\t\tNULL);\n\treturn TCL_ERROR;\n    } else if (wmPtr->container != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is a transient\", winPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"TRANSIENT\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is an icon for \\\"%s\\\"\",\n\t\twinPtr->pathName, Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else if (winPtr->flags & TK_EMBEDDED) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is an embedded window\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"EMBEDDED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    TkpWmSetState(winPtr, IconicState);\n    if (wmPtr->icon) {\n\tTk_MapWindow((Tk_Window)wmPtr->icon);\n    }\n\n    /*\n     * If this window has a transient the transient must be withdrawn when\n     * the container is iconified.\n     */\n\n    for (Transient *transientPtr = wmPtr->transientPtr;\n\t    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {\n\tTkWindow *winPtr2 = transientPtr->winPtr;\n\tTkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);\n\tif (containerPtr == winPtr &&\n\t\twinPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {\n\t    TkpWmSetState(winPtr2, WithdrawnState);\n\t    transientPtr->flags |= WITHDRAWN_BY_CONTAINER;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconmaskCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconmask\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconmaskCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Pixmap pixmap;\n    char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?bitmap?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconMaskHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),\n\t\t    -1));\n\t}\n\treturn TCL_OK;\n    }\n\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\tif (wmPtr->hints.icon_mask != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n\t}\n\twmPtr->hints.flags &= ~IconMaskHint;\n    } else {\n\tpixmap = Tk_GetBitmap(interp, tkwin, argv3);\n\tif (pixmap == None) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_mask = pixmap;\n\twmPtr->hints.flags |= IconMaskHint;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconnameCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconname\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconnameCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size length;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->iconName != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n\n    if (wmPtr->iconName != NULL) {\n\tTcl_Free(wmPtr->iconName);\n    }\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    wmPtr->iconName = (char *)Tcl_Alloc(length + 1);\n    strcpy(wmPtr->iconName, argv3);\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tXSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconphotoCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconphoto\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconphotoCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Image tk_icon;\n    int width, height;\n    NSImage *newIcon = NULL;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\t \"window ?-default? image1 ?image2 ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse args.\n     */\n\n    if (strcmp(Tcl_GetString(objv[3]), \"-default\") == 0) {\n\tif (objc == 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"window ?-default? image1 ?image2 ...?\");\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Get icon name. We only use the first icon name because macOS does not\n     * support multiple images in Tk photos.\n     */\n\n    char *icon;\n    if (strcmp(Tcl_GetString(objv[3]), \"-default\") == 0) {\n\ticon = Tcl_GetString(objv[4]);\n    } else {\n\ticon = Tcl_GetString(objv[3]);\n    }\n\n    /*\n     * Get image and convert to NSImage that can be displayed as icon.\n     */\n\n    tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL);\n    if (tk_icon == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t      \"can't use \\\"%s\\\" as iconphoto: not a photo image\",\n\t      icon));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"PHOTO\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    Tk_SizeOfImage(tk_icon, &width, &height);\n    if (width != 0 && height != 0) {\n\tnewIcon = TkMacOSXGetNSImageFromTkImage(winPtr->display, tk_icon,\n\t\t\t\t\t\twidth, height);\n    }\n    Tk_FreeImage(tk_icon);\n    if (newIcon == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"failed to create an iconphoto with image \\\"%s\\\"\", icon));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"IMAGE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    [NSApp setApplicationIconImage: newIcon];\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconpositionCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconposition\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconpositionCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?x y?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconPositionHint) {\n\t    Tcl_Obj *results[2];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\t}\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->hints.flags &= ~IconPositionHint;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_x = x;\n\twmPtr->hints.icon_y = y;\n\twmPtr->hints.flags |= IconPositionHint;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconwindowCmd --\n *\n *\tThis procedure is invoked to process the \"wm iconwindow\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconwindowCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    WmInfo *wmPtr2;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tif (wmPtr->icon != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));\n\t}\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->hints.flags &= ~IconWindowHint;\n\tif (wmPtr->icon != NULL) {\n\t    wmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;\n\t    wmPtr2->iconFor = NULL;\n\t    wmPtr2->hints.initial_state = WithdrawnState;\n\t}\n\twmPtr->icon = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (!Tk_IsTopLevel(tkwin2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't use %s as icon window: not at top level\",\n\t\t    Tk_PathName(tkwin2)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"TOPLEVEL\",\n\t\t    NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr2 = ((TkWindow *)tkwin2)->wmInfoPtr;\n\tif (wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s is already an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (wmPtr->icon != NULL) {\n\t    NSWindow *win = nil;\n\t    TkWindow *oldIcon = (TkWindow *)wmPtr->icon;\n\t    if (winPtr && winPtr->window) {\n\t\twin = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n\t    }\n\t    /*\n\t     * The old icon should be withdrawn.\n\t     */\n\t    if (oldIcon) {\n\t\tWmInfo *wmPtr3 = oldIcon->wmInfoPtr;\n\t\tTkpWmSetState(oldIcon, WithdrawnState);\n\t\tif (wmPtr3) {\n\t\t    wmPtr3->iconFor = NULL;\n\t\t}\n\t    }\n\t    [win orderOut:NSApp];\n\t    [[win contentView] setOnScreen: NO];\n\t    [win setExcludedFromWindowsMenu:YES];\n\t}\n\tTk_MakeWindowExist(tkwin2);\n\twmPtr->hints.icon_window = Tk_WindowId(tkwin2);\n\twmPtr->hints.flags |= IconWindowHint;\n\twmPtr->icon = tkwin2;\n\twmPtr2->iconFor = (Tk_Window)winPtr;\n\tif (!(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t    /*\n\t     * If the window is in normal or zoomed state, the icon should be\n\t     * unmapped.\n\t     */\n\n\t    if (wmPtr->hints.initial_state == NormalState ||\n\t\t    wmPtr->hints.initial_state == ZoomState) {\n\t\tTk_UnmapWindow(tkwin2);\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmManageCmd --\n *\n *\tThis procedure is invoked to process the \"wm manage\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmManageCmd(\n    TCL_UNUSED(Tk_Window),\t\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t\t/* Toplevel or Frame to work with */\n    Tcl_Interp *interp,\t\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t/* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window)winPtr;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!Tk_IsTopLevel(frameWin)) {\n\tMacDrawable *macWin = (MacDrawable *)winPtr->window;\n\n\tif (!Tk_IsManageable(frameWin)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" is not manageable: must be a\"\n\t\t    \" frame, labelframe or toplevel\",\n\t\t    Tk_PathName(frameWin)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"MANAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Draw the managed widget at the top left corner of its toplevel.\n\t * See [4a40c6cace].\n\t */\n\n\tif (macWin) {\n\t    winPtr->changes.x -= macWin->xOff;\n\t    winPtr->changes.y -= macWin->yOff;\n\t    XMoveWindow(winPtr->display, winPtr->window, 0, 0);\n\t}\n\n\tTkFocusSplit(winPtr);\n\tTk_UnmapWindow(frameWin);\n\tif (wmPtr == NULL) {\n\t    TkWmNewWindow(winPtr);\n\t    if (winPtr->window == None) {\n\t\tTk_MakeWindowExist((Tk_Window)winPtr);\n\t\tmacWin = (MacDrawable *)winPtr->window;\n\t    }\n\t}\n\twmPtr = winPtr->wmInfoPtr;\n\twinPtr->flags &= ~TK_MAPPED;\n\tmacWin->toplevel->referenceCount--;\n\tmacWin->toplevel = macWin;\n\tmacWin->toplevel->referenceCount++;\n\tRemapWindows(winPtr, macWin);\n\twinPtr->flags |=\n\t\t(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);\n\tTkMapTopFrame(frameWin);\n\tTkWmMapWindow(winPtr);\n    } else if (Tk_IsTopLevel(frameWin)) {\n\t/* Already managed by wm - ignore it */\n    }\n    Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMaxsizeCmd --\n *\n *\tThis procedure is invoked to process the \"wm maxsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMaxsizeCmd(\n    Tk_Window tkwin,\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tGetMaxSize(winPtr, &width, &height);\n\tresults[0] = Tcl_NewWideIntObj(width);\n\tresults[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->maxWidth = width;\n    wmPtr->maxHeight = height;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMinsizeCmd --\n *\n *\tThis procedure is invoked to process the \"wm minsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMinsizeCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tGetMinSize(winPtr, &width, &height);\n\tresults[0] = Tcl_NewWideIntObj(width);\n\tresults[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->minWidth = width;\n    wmPtr->minHeight = height;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmOverrideredirectCmd --\n *\n *\tThis procedure is invoked to process the \"wm overrideredirect\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmOverrideredirectCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Bool boolValue;\n    XSetWindowAttributes atts;\n    NSWindow *win = nil;\n    if (winPtr && winPtr->window) {\n\twin = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?boolean?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\tTk_Attributes((Tk_Window)winPtr)->override_redirect));\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    atts.override_redirect = boolValue;\n    Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);\n    if ([NSApp macOSVersion] >= 101300) {\n\tif (boolValue) {\n\t    win.styleMask |= NSWindowStyleMaskDocModalWindow;\n\t} else {\n\t    win.styleMask &= ~NSWindowStyleMaskDocModalWindow;\n\t}\n    } else {\n\tApplyContainerOverrideChanges(winPtr, win);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmPositionfromCmd --\n *\n *\tThis procedure is invoked to process the \"wm positionfrom\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmPositionfromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL };\n    enum options {\n\tOPT_PROGRAM, OPT_USER };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user/program?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & USPosition) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"user\", TCL_INDEX_NONE));\n\t} else if (wmPtr->sizeHintsFlags & PPosition) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"program\", TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USPosition|PPosition);\n    } else {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PPosition;\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t} else {\n\t    wmPtr->sizeHintsFlags &= ~USPosition;\n\t    wmPtr->sizeHintsFlags |= PPosition;\n\t}\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmProtocolCmd --\n *\n *\tThis procedure is invoked to process the \"wm protocol\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmProtocolCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    ProtocolHandler *protPtr, *prevPtr;\n    Atom protocol;\n    Tcl_Obj *resultObj;\n\n    if ((objc < 3) || (objc > 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name? ?command?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\t/*\n\t * Return a list of all defined protocols for the window.\n\t */\n\n\tresultObj = Tcl_NewObj();\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol),-1));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n\n    protocol = Tk_InternAtom((Tk_Window)winPtr, Tcl_GetString(objv[3]));\n    if (objc == 4) {\n\t/*\n\t * Return the command to handle a given protocol.\n\t */\n\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    if (protPtr->protocol == protocol) {\n\t\tTcl_SetObjResult(interp, protPtr->commandObj);\n\t\treturn TCL_OK;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n\n    /*\n     * Delete any current protocol handler, then create a new one with the\n     * specified command, unless the command is empty.\n     */\n\n    for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;\n\t    prevPtr = protPtr, protPtr = protPtr->nextPtr) {\n\tif (protPtr->protocol == protocol) {\n\t    if (prevPtr == NULL) {\n\t\twmPtr->protPtr = protPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = protPtr->nextPtr;\n\t    }\n\t    if (protPtr->commandObj)\n\t\tTcl_DecrRefCount(protPtr->commandObj);\n\t    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n\t    break;\n\t}\n    }\n    if (Tcl_GetString(objv[4])[0]) {\n\tprotPtr = (ProtocolHandler *)Tcl_Alloc(sizeof(ProtocolHandler));\n\tprotPtr->protocol = protocol;\n\tprotPtr->nextPtr = wmPtr->protPtr;\n\twmPtr->protPtr = protPtr;\n\tprotPtr->interp = interp;\n\tprotPtr->commandObj = objv[4];\n\tTcl_IncrRefCount(protPtr->commandObj);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmResizableCmd --\n *\n *\tThis procedure is invoked to process the \"wm resizable\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmResizableCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n    UInt64 oldAttributes = wmPtr->attributes;\n    int oldFlags = wmPtr->flags;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tresults[0] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE));\n\tresults[1] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE));\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n\n    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)\n\t    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (width) {\n\twmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;\n\twmPtr->attributes |= kWindowHorizontalZoomAttribute;\n    } else {\n\twmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;\n\twmPtr->attributes &= ~kWindowHorizontalZoomAttribute;\n    }\n    if (height) {\n\twmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;\n\twmPtr->attributes |= kWindowVerticalZoomAttribute;\n    } else {\n\twmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;\n\twmPtr->attributes &= ~kWindowVerticalZoomAttribute;\n    }\n    if (width || height) {\n\twmPtr->attributes |= kWindowResizableAttribute;\n    } else {\n\twmPtr->attributes &= ~kWindowResizableAttribute;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (wmPtr->scrollWinPtr != NULL) {\n\tTkScrollbarEventuallyRedraw((TkScrollbar *)\n\t\twmPtr->scrollWinPtr->instanceData);\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags, 1,0);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmSizefromCmd --\n *\n *\tThis procedure is invoked to process the \"wm sizefrom\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmSizefromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL };\n    enum options {\n\tOPT_PROGRAM, OPT_USER };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user|program?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & USSize) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"user\", TCL_INDEX_NONE));\n\t} else if (wmPtr->sizeHintsFlags & PSize) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"program\", TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USSize|PSize);\n    } else {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PSize;\n\t    wmPtr->sizeHintsFlags |= USSize;\n\t} else { /* OPT_PROGRAM */\n\t    wmPtr->sizeHintsFlags &= ~USSize;\n\t    wmPtr->sizeHintsFlags |= PSize;\n\t}\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStackorderCmd --\n *\n *\tThis procedure is invoked to process the \"wm stackorder\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStackorderCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkWindow **windows, **windowPtr;\n    static const char *const optionStrings[] = {\n\t\"isabove\", \"isbelow\", NULL\n    };\n    enum options {\n\tOPT_ISABOVE, OPT_ISBELOW\n    };\n    Tcl_Obj *resultObj;\n    int index;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?isabove|isbelow window?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\twindows = TkWmStackorderToplevel(winPtr);\n\tif (windows != NULL) {\n\t    resultObj = Tcl_NewObj();\n\t    for (windowPtr = windows; *windowPtr ; windowPtr++) {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTk_NewWindowObj((Tk_Window)*windowPtr));\n\t    }\n\t    Tcl_SetObjResult(interp, resultObj);\n\t    Tcl_Free(windows);\n\t    return TCL_OK;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tTkWindow *winPtr2;\n\tint index1 = -1, index2 = -1, result;\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsTopLevel(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't a top-level window\",\n\t\t    winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"TOPLEVEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsMapped(winPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t} else if (!Tk_IsMapped(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Lookup stacking order of all toplevels that are children of \".\" and\n\t * find the position of winPtr and winPtr2 in the stacking order.\n\t */\n\n\twindows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);\n\tif (windows == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"TkWmStackorderToplevel failed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"FAIL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (windowPtr = windows; *windowPtr ; windowPtr++) {\n\t    if (*windowPtr == winPtr) {\n\t\tindex1 = windowPtr - windows;\n\t    }\n\t    if (*windowPtr == winPtr2) {\n\t\tindex2 = windowPtr - windows;\n\t    }\n\t}\n\tif (index1 == -1) {\n\t    Tcl_Panic(\"winPtr window not found\");\n\t} else if (index2 == -1) {\n\t    Tcl_Panic(\"winPtr2 window not found\");\n\t}\n\n\tTcl_Free(windows);\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_ISABOVE) {\n\t    result = index1 > index2;\n\t} else { /* OPT_ISBELOW */\n\t    result = index1 < index2;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(result));\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStateCmd --\n *\n *\tThis procedure is invoked to process the \"wm state\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStateCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"iconic\", \"normal\", \"withdrawn\", \"zoomed\", NULL };\n    enum options {\n\tOPT_ICONIC, OPT_NORMAL, OPT_WITHDRAWN, OPT_ZOOMED };\n    int index;\n\n    if ((objc < 3) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?state?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 4) {\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't change state of \\\"%s\\\": it is an icon for \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (winPtr->flags & TK_EMBEDDED) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't change state of \\\"%s\\\": it is an embedded window\",\n\t\t    winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"EMBEDDED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tswitch (index) {\n\tcase OPT_NORMAL:\n\t    TkpWmSetState(winPtr, NormalState);\n\n\t    /*\n\t     * This varies from 'wm deiconify' because it does not force the\n\t     * window to be raised and receive focus\n\t     */\n\n\t    break;\n\tcase OPT_ICONIC:\n\t    if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\",\n\t\t\t\"OVERRIDE_REDIRECT\", NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (wmPtr->container != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": it is a transient\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"TRANSIENT\",\n\t\t\tNULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkpWmSetState(winPtr, IconicState);\n\t    break;\n\tcase OPT_WITHDRAWN:\n\t    TkpWmSetState(winPtr, WithdrawnState);\n\t    break;\n\tdefault: /* OPT_ZOOMED */\n\t    TkpWmSetState(winPtr, ZoomState);\n\t    break;\n\t}\n    } else if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"icon\", TCL_INDEX_NONE));\n    } else {\n\tif (wmPtr->hints.initial_state == NormalState ||\n\t\twmPtr->hints.initial_state == ZoomState) {\n\t    wmPtr->hints.initial_state = (TkMacOSXIsWindowZoomed(winPtr) ?\n\t\t    ZoomState : NormalState);\n\t}\n\tswitch (wmPtr->hints.initial_state) {\n\tcase NormalState:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"normal\", TCL_INDEX_NONE));\n\t    break;\n\tcase IconicState:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"iconic\", TCL_INDEX_NONE));\n\t    break;\n\tcase WithdrawnState:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"withdrawn\", TCL_INDEX_NONE));\n\t    break;\n\tcase ZoomState:\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"zoomed\", TCL_INDEX_NONE));\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTitleCmd --\n *\n *\tThis procedure is invoked to process the \"wm title\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTitleCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    char *argv3;\n    Tcl_Size length;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newTitle?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\twmPtr->titleUid ? wmPtr->titleUid : winPtr->nameUid, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    wmPtr->titleUid = Tk_GetUid(argv3);\n    if (!(wmPtr->flags & WM_NEVER_MAPPED) && !Tk_IsEmbedded(winPtr)) {\n\tTkSetWMName(winPtr, wmPtr->titleUid);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTransientCmd --\n *\n *\tThis procedure is invoked to process the \"wm transient\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTransientCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window container;\n    TkWindow *containerPtr, *w;\n    WmInfo *wmPtr2;\n    Transient *transient;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?window?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->container != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\tTcl_NewStringObj(Tk_PathName(wmPtr->container), TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\tRemoveTransient(winPtr);\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &container) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tRemoveTransient(winPtr);\n\tcontainerPtr = (TkWindow*) container;\n\twhile (!Tk_TopWinHierarchy(containerPtr)) {\n\t    /*\n\t     * Ensure that the container window is actually a Tk toplevel.\n\t     */\n\n\t    containerPtr = containerPtr->parentPtr;\n\t}\n\tTk_MakeWindowExist((Tk_Window)containerPtr);\n\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a transient: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\twmPtr2 = containerPtr->wmInfoPtr;\n\n\t/*\n\t * Under some circumstances, wmPtr2 is NULL here.\n\t */\n\n\tif (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a container: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;\n\t    w = (TkWindow *)w->wmInfoPtr->container) {\n\t    if (w == winPtr) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't set \\\"%s\\\" as container: would cause management loop\",\n\t\t    Tk_PathName(containerPtr)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"SELF\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\t/*\n\t * Add the transient to the container's list, if it not already there.\n\t */\n\n\tfor (transient = wmPtr2->transientPtr;\n\t     transient != NULL && transient->winPtr != winPtr;\n\t     transient = transient->nextPtr) {}\n\tif (transient == NULL) {\n\t    transient = (Transient *)Tcl_Alloc(sizeof(Transient));\n\t    transient->winPtr = winPtr;\n\t    transient->flags = 0;\n\t    transient->nextPtr = wmPtr2->transientPtr;\n\t    wmPtr2->transientPtr = transient;\n\t}\n\n\t/*\n\t * If the container is withdrawn or iconic then withdraw the transient.\n\t */\n\n\tif ((wmPtr2->hints.initial_state == WithdrawnState ||\n\t\twmPtr2->hints.initial_state == IconicState) &&\n\t\twmPtr->hints.initial_state != WithdrawnState) {\n\t    TkpWmSetState(winPtr, WithdrawnState);\n\t    transient->flags |= WITHDRAWN_BY_CONTAINER;\n\t}\n\n\twmPtr->container = (Tk_Window)containerPtr;\n    }\n    ApplyContainerOverrideChanges(winPtr, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemoveTransient --\n *\n *      Clears the transient's container record and removes the transient from the\n *      container's list.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *      References to a container are removed from the transient's wmInfo\n *\tstructure and references to the transient are removed from its container's\n *\twmInfo.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemoveTransient(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;\n    TkWindow *containerPtr;\n    Transient *transPtr, *temp;\n\n    if (wmPtr == NULL || wmPtr->container == NULL) {\n\treturn;\n    }\n    containerPtr = (TkWindow *)wmPtr->container;\n    wmPtr2 = containerPtr->wmInfoPtr;\n    if (wmPtr2 == NULL) {\n\treturn;\n    }\n    wmPtr->container= NULL;\n    transPtr = wmPtr2->transientPtr;\n    while (transPtr != NULL) {\n\tif (transPtr->winPtr != winPtr) {\n\t    break;\n\t}\n\ttemp = transPtr->nextPtr;\n\tTcl_Free(transPtr);\n\ttransPtr = temp;\n    }\n    wmPtr2->transientPtr = transPtr;\n    while (transPtr != NULL) {\n\tif (transPtr->nextPtr && transPtr->nextPtr->winPtr == winPtr) {\n\t    temp = transPtr->nextPtr;\n\t    transPtr->nextPtr = temp->nextPtr;\n\t    Tcl_Free(temp);\n\t} else {\n\t    transPtr = transPtr->nextPtr;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmWithdrawCmd --\n *\n *\tThis procedure is invoked to process the \"wm withdraw\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmWithdrawCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't withdraw %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"WITHDRAW\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    TkpWmSetState(winPtr, WithdrawnState);\n\n    /*\n     * If this window has a transient, the transient must also be withdrawn.\n     */\n\n    for (Transient *transientPtr = wmPtr->transientPtr;\n\t    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {\n\tTkWindow *winPtr2 = transientPtr->winPtr;\n\tTkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);\n\n\tif (containerPtr == winPtr &&\n\t\twinPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {\n\t    TkpWmSetState(winPtr2, WithdrawnState);\n\t    transientPtr->flags |= WITHDRAWN_BY_CONTAINER;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n * Invoked by those wm subcommands that affect geometry.  Schedules a geometry\n * update.\n */\n\nstatic void\nWmUpdateGeom(\n    WmInfo *wmPtr,\n    TkWindow *winPtr)\n{\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetGrid --\n *\n *\tThis procedure is invoked by a widget when it wishes to set a grid\n *\tcoordinate system that controls the size of a top-level window. It\n *\tprovides a C interface equivalent to the \"wm grid\" command and is\n *\tusually asscoiated with the -setgrid option.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGrid-related information will be passed to the window manager, so that\n *\tthe top-level window associated with tkwin will resize on even grid\n *\tunits. If some other window already controls gridding for the\n *\ttop-level window then this procedure call has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetGrid(\n    Tk_Window tkwin,\t\t/* Token for window. New window mgr info will\n\t\t\t\t * be posted for the top-level window\n\t\t\t\t * associated with this window. */\n    int reqWidth,\t\t/* Width (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int reqHeight,\t\t/* Height (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int widthInc, int heightInc)/* Pixel increments corresponding to a change\n\t\t\t\t * of one grid unit. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Ensure widthInc and heightInc are greater than 0\n     */\n\n    if (widthInc <= 0) {\n\twidthInc = 1;\n    }\n    if (heightInc <= 0) {\n\theightInc = 1;\n    }\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_LEVEL)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n\n    if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {\n\treturn;\n    }\n\n    if ((wmPtr->reqGridWidth == reqWidth)\n\t    && (wmPtr->reqGridHeight == reqHeight)\n\t    && (wmPtr->widthInc == widthInc)\n\t    && (wmPtr->heightInc == heightInc)\n\t    && ((wmPtr->sizeHintsFlags & PBaseSize) == PBaseSize)) {\n\treturn;\n    }\n\n    /*\n     * If gridding was previously off, then forget about any window size\n     * requests made by the user or via \"wm geometry\": these are in pixel units\n     * and there's no easy way to translate them to grid units since the new\n     * requested size of the top-level window in pixels may not yet have been\n     * registered yet (it may filter up the hierarchy in DoWhenIdle handlers).\n     * However, if the window has never been mapped yet then just leave the\n     * window size alone: assume that it is intended to be in grid units but\n     * just happened to have been specified before this procedure was called.\n     */\n\n    if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n    }\n\n    /*\n     * Set the new gridding information, and start the process of passing all\n     * of this information to the window manager.\n     */\n\n    wmPtr->gridWin = tkwin;\n    wmPtr->reqGridWidth = reqWidth;\n    wmPtr->reqGridHeight = reqHeight;\n    wmPtr->widthInc = widthInc;\n    wmPtr->heightInc = heightInc;\n    wmPtr->sizeHintsFlags |= PBaseSize;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UnsetGrid --\n *\n *\tThis procedure cancels the effect of a previous call to Tk_SetGrid.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf tkwin currently controls gridding for its top-level window,\n *\tgridding is cancelled for that top-level window; if some other window\n *\tcontrols gridding then this procedure has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UnsetGrid(\n    Tk_Window tkwin)\t\t/* Token for window that is currently\n\t\t\t\t * controlling gridding. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_LEVEL)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (tkwin != wmPtr->gridWin) {\n\treturn;\n    }\n\n    wmPtr->gridWin = NULL;\n    wmPtr->sizeHintsFlags &= ~PBaseSize;\n    if (wmPtr->width != -1) {\n\twmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t- wmPtr->reqGridWidth)*wmPtr->widthInc;\n\twmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t- wmPtr->reqGridHeight)*wmPtr->heightInc;\n    }\n    wmPtr->widthInc = 1;\n    wmPtr->heightInc = 1;\n\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelEventProc --\n *\n *\tThis procedure is invoked when a top-level (or other externally-\n *\tmanaged window) is restructured in any way.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTk's internal data structures for the window get modified to reflect\n *\tthe structural change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTopLevelEventProc(\n    void *clientData,\t/* Window for which event occurred. */\n    XEvent *eventPtr)\t\t/* Event that just happened. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n\n    winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE;\n    if (eventPtr->type == DestroyNotify) {\n\tif (!(winPtr->flags & TK_ALREADY_DEAD)) {\n\t    /*\n\t     * A top-level window was deleted externally (e.g., by the window\n\t     * manager). This is probably not a good thing, but cleanup as\n\t     * best we can. The error handler is needed because\n\t     * Tk_DestroyWindow will try to destroy the window, but of course\n\t     * it's already gone.\n\t     */\n\n\t    Tk_ErrorHandler handler = Tk_CreateErrorHandler(winPtr->display,\n\t\t    -1, -1, -1, NULL, NULL);\n\n\t    Tk_DestroyWindow((Tk_Window)winPtr);\n\t    Tk_DeleteErrorHandler(handler);\n\t}\n\tif (wmTracing) {\n\t    TkMacOSXDbgMsg(\"TopLevelEventProc: %s deleted\", winPtr->pathName);\n\t}\n    } else if (eventPtr->type == ReparentNotify) {\n\tTcl_Panic(\"received unwanted reparent event\");\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelReqProc --\n *\n *\tThis procedure is invoked by the geometry manager whenever the\n *\trequested size for a top-level window is changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArrange for the window to be resized to satisfy the request (this\n *\thappens as a when-idle action).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTopLevelReqProc(\n    TCL_UNUSED(void *),\t\t/* Not used. */\n    Tk_Window tkwin)\t\t/* Information about window. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    WmInfo *wmPtr;\n\n    wmPtr = winPtr->wmInfoPtr;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateGeometryInfo --\n *\n *\tThis procedure is invoked when a top-level window is first mapped, and\n *\talso as a when-idle procedure, to bring the geometry and/or position\n *\tof a top-level window back into line with what has been requested by\n *\tthe user and/or widgets. This procedure doesn't return until the\n *\twindow manager has responded to the geometry change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window's size and location may change, unless the WM prevents that\n *\tfrom happening.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateGeometryInfo(\n    void *clientData)\t/* Pointer to the window's record. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y, width, height, min, max;\n\n    wmPtr->flags &= ~WM_UPDATE_PENDING;\n\n    if (wmPtr->flags & WM_FULLSCREEN) {\n\treturn;\n    }\n\n    /*\n     * Compute the new size for the top-level window. See the user\n     * documentation for details on this, but the size requested depends on\n     * (a) the size requested internally by the window's widgets, (b) the size\n     * requested by the user in a \"wm geometry\" command or via wm-based\n     * interactive resizing (if any), and (c) whether or not the window is\n     * gridded. Don't permit sizes <= 0 because this upsets the X server.\n     */\n\n    if (wmPtr->width == -1) {\n\twidth = winPtr->reqWidth;\n    } else if (wmPtr->gridWin != NULL) {\n\twidth = winPtr->reqWidth\n\t\t+ (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc;\n    } else {\n\twidth = wmPtr->width;\n    }\n    if (width <= 0) {\n\twidth = 1;\n    }\n\n    /*\n     * Account for window max/min width\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqWidth\n\t\t+ (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\tif (wmPtr->maxWidth > 0) {\n\t    max = winPtr->reqWidth\n\t\t    + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minWidth;\n\tmax = wmPtr->maxWidth;\n    }\n    if (width < min) {\n\twidth = min;\n    } else if ((max > 0) && (width > max)) {\n\twidth = max;\n    }\n\n    if (wmPtr->height == -1) {\n\theight = winPtr->reqHeight;\n    } else if (wmPtr->gridWin != NULL) {\n\theight = winPtr->reqHeight\n\t\t+ (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc;\n    } else {\n\theight = wmPtr->height;\n    }\n    if (height <= 0) {\n\theight = 1;\n    }\n\n    /*\n     * Account for window max/min height\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqHeight\n\t\t+ (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\tif (wmPtr->maxHeight > 0) {\n\t    max = winPtr->reqHeight\n\t\t    + (wmPtr->maxHeight-wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minHeight;\n\tmax = wmPtr->maxHeight;\n    }\n    if (height < min) {\n\theight = min;\n    } else if ((max > 0) && (height > max)) {\n\theight = max;\n    }\n    x = wmPtr->x;\n    y = wmPtr->y;\n\n    /*\n     * If the window's size is going to change and the window is supposed to\n     * not be resizable by the user, then we have to update the size hints.\n     * There may also be a size-hint-update request pending from somewhere\n     * else, too.\n     */\n\n    if (((width != winPtr->changes.width)\n\t    || (height != winPtr->changes.height))\n\t    && (wmPtr->gridWin == NULL)\n\t    && !(wmPtr->sizeHintsFlags & (PMinSize|PMaxSize))) {\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    }\n    if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) {\n\tUpdateSizeHints(winPtr);\n    }\n\n    /*\n     * Reconfigure the window if it isn't already configured correctly. A few\n     * tricky points:\n     *\n     * 1. If the window is embedded and the container is also in this process,\n     *    don't actually reconfigure the window; just pass the desired size on\n     *    to the container. Also, zero out any position information, since\n     *    embedded windows are not allowed to move.\n     * 2. Sometimes the window manager will give us a different size than we\n     *    asked for (e.g. mwm has a minimum size for windows), so base the\n     *    size check on what we *asked for* last time, not what we got.\n     * 3. Don't move window unless a new position has been requested for it.\n     *    This is because of \"features\" in some window managers (e.g. twm, as\n     *    of 4/24/91) where they don't interpret coordinates according to\n     *    ICCCM. Moving a window to its current location may cause it to shift\n     *    position on the screen.\n     */\n\n    if (Tk_IsEmbedded(winPtr)) {\n\tTk_Window contWinPtr = Tk_GetOtherWindow((Tk_Window)winPtr);\n\n\t/*\n\t * TODO: Here we should handle out of process embedding.\n\t */\n\n\tif (contWinPtr != NULL) {\n\t    /*\n\t     * This window is embedded and the container is also in this\n\t     * process, so we don't need to do anything special about the\n\t     * geometry, except to make sure that the desired size is known by\n\t     * the container. Also, zero out any position information, since\n\t     * embedded windows are not allowed to move.\n\t     */\n\n\t    wmPtr->x = wmPtr->y = 0;\n\t    wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);\n\t    Tk_GeometryRequest(contWinPtr, width, height);\n\t}\n\treturn;\n    }\n    if (wmPtr->flags & WM_MOVE_PENDING) {\n\twmPtr->configWidth = width;\n\twmPtr->configHeight = height;\n\tif (wmTracing) {\n\t    TkMacOSXDbgMsg(\"Moving to %d %d, resizing to %d x %d\", x, y,\n\t\t    width, height);\n\t}\n\tSetWindowSizeLimits(winPtr);\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tXMoveResizeWindow(winPtr->display, winPtr->window, x, y,\n\t\twmPtr->configWidth, wmPtr->configHeight);\n\twmPtr->flags &= ~WM_SYNC_PENDING;\n    } else if ((width != wmPtr->configWidth)\n\t    || (height != wmPtr->configHeight)) {\n\twmPtr->configWidth = width;\n\twmPtr->configHeight = height;\n\tif (wmTracing) {\n\t    TkMacOSXDbgMsg(\"Resizing to %d x %d\\n\", width, height);\n\t}\n\tSetWindowSizeLimits(winPtr);\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tXResizeWindow(winPtr->display, winPtr->window, wmPtr->configWidth,\n\t\twmPtr->configHeight);\n\twmPtr->flags &= ~WM_SYNC_PENDING;\n    } else {\n\tSetWindowSizeLimits(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateSizeHints --\n *\n *\tThis procedure is called to update the window manager's size hints\n *\tinformation from the information in a WmInfo structure.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties get changed for winPtr.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateSizeHints(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseGeometry --\n *\n *\tThis procedure parses a geometry string and updates information used\n *\tto control the geometry of a top-level window.\n *\n * Results:\n *\tA standard Tcl return value, plus an error message in the interp's\n *\tresult if an error occurs.\n *\n * Side effects:\n *\tThe size and/or location of winPtr may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nParseGeometry(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    char *string,\t\t/* String containing new geometry. Has the\n\t\t\t\t * standard form \"=wxh+x+y\". */\n    TkWindow *winPtr)\t\t/* Pointer to top-level window whose geometry\n\t\t\t\t * is to be changed. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y, width, height, flags;\n    char *end;\n    char *p = string;\n\n    /*\n     * The leading \"=\" is optional.\n     */\n\n    if (*p == '=') {\n\tp++;\n    }\n\n    /*\n     * Parse the width and height, if they are present. Don't actually update\n     * any of the fields of wmPtr until we've successfully parsed the entire\n     * geometry string.\n     */\n\n    width = wmPtr->width;\n    height = wmPtr->height;\n    x = -1;\n    y = -1;\n    flags = wmPtr->flags;\n    if (isdigit(UCHAR(*p))) {\n\twidth = strtoul(p, &end, 10);\n\tp = end;\n\tif (*p != 'x') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p))) {\n\t    goto error;\n\t}\n\theight = strtoul(p, &end, 10);\n\tp = end;\n    }\n\n    /*\n     * Parse the X and Y coordinates, if they are present.\n     */\n\n    if (*p != '\\0') {\n\tflags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_X;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\tx = strtol(p, &end, 10);\n\tp = end;\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_Y;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\ty = strtol(p, &end, 10);\n\tif (*end != '\\0') {\n\t    goto error;\n\t}\n\n\t/*\n\t * Assume that the geometry information came from the user, unless an\n\t * explicit source has been specified. Otherwise most window managers\n\t * assume that the size hints were program-specified and they ignore\n\t * them.\n\t */\n\n\tif (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t    flags |= WM_UPDATE_SIZE_HINTS;\n\t}\n    }\n\n    /*\n     * Everything was parsed OK. Update the fields of *wmPtr and arrange for\n     * the appropriate information to be percolated out to the window manager\n     * at the next idle moment.\n     *\n     * Computing the new position for the upper-left pixel of the window's\n     * decorative frame is tricky because we need to include the border\n     * widths supplied by a reparented parent in the calculation, but we can't\n     * use the parent's current overall size since that may change as a result\n     * of this code.\n     */\n\n    wmPtr->width = width;\n    wmPtr->height = height;\n    if (flags & WM_NEGATIVE_X) {\n\tint borderwidth = wmPtr->parentWidth - winPtr->changes.width;\n\tint newWidth = width == -1 ? winPtr->changes.width : width;\n\n\tx = (x == -1) ?\n\t\twmPtr->x + winPtr->changes.width - newWidth :\n\t\twmPtr->vRootWidth - x - newWidth - borderwidth;\n    }\n    if (x == -1) {\n\tx = wmPtr->x;\n    }\n    if (flags & WM_NEGATIVE_Y) {\n\tint borderheight = wmPtr->parentHeight - winPtr->changes.height;\n\tint newHeight = height == -1 ? winPtr->changes.height : height;\n\n\ty = (y == -1) ?\n\t\twmPtr->y + winPtr->changes.height - newHeight :\n\t\twmPtr->vRootHeight - y - newHeight - borderheight;\n    }\n    if (y == -1) {\n\ty = wmPtr->y;\n    }\n    if (wmPtr->flags & WM_FULLSCREEN) {\n\twmPtr->configX = x;\n\twmPtr->configY = y;\n    } else {\n\twmPtr->x = x;\n\twmPtr->y = y;\n    }\n    flags |= WM_MOVE_PENDING;\n    wmPtr->flags = flags;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n    return TCL_OK;\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad geometry specifier \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GEOMETRY\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetRootCoords --\n *\n *\tGiven a token for a window, this procedure traces through the window's\n *\tlineage to find the (virtual) root-window coordinates corresponding to\n *\tpoint (0,0) in the window.\n *\n * Results:\n *\tThe locations pointed to by xPtr and yPtr are filled in with the root\n *\tcoordinates of the (0,0) point in tkwin. If a virtual root window is\n *\tin effect for the window, then the coordinates in the virtual root are\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetRootCoords(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    int *xPtr,\t\t\t/* Where to store x-displacement of (0,0). */\n    int *yPtr)\t\t\t/* Where to store y-displacement of (0,0). */\n{\n    int x, y;\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    /*\n     * Search back through this window's parents all the way to a top-level\n     * window, combining the offsets of each window within its parent.\n     */\n\n    x = y = 0;\n    while (1) {\n\tx += winPtr->changes.x + winPtr->changes.border_width;\n\ty += winPtr->changes.y + winPtr->changes.border_width;\n\tif (winPtr->flags & TK_TOP_LEVEL) {\n\t    TkWindow *otherPtr;\n\n\t    if (!(Tk_IsEmbedded(winPtr))) {\n\t\tx += winPtr->wmInfoPtr->xInParent;\n\t\ty += winPtr->wmInfoPtr->yInParent;\n\t\tbreak;\n\t    }\n\n\t    otherPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t    if (otherPtr == NULL) {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * The container window is in the same application. Query its\n\t     * coordinates.\n\t     */\n\n\t    winPtr = otherPtr;\n\t    continue;\n\t}\n\twinPtr = winPtr->parentPtr;\n    }\n    *xPtr = x;\n    *yPtr = y;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CoordsToWindow --\n *\n *\tThis is a Macintosh specific implementation of this function. Given\n *\tthe root coordinates of a point, this procedure returns the token for\n *\tthe top-most window covering that point, if there exists such a window\n *\tin this application.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\trootX and rootY, or else NULL to indicate that there is no such window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_CoordsToWindow(\n    int rootX, int rootY,\t/* Coordinates of point in root window. If a\n\t\t\t\t * virtual-root window manager is in use,\n\t\t\t\t * these coordinates refer to the virtual\n\t\t\t\t * root, not the real root. */\n    Tk_Window tkwin)\t\t/* Token for any window in application; used\n\t\t\t\t * to identify the display. */\n{\n    TkWindow *winPtr, *childPtr;\n    TkWindow *nextPtr;\t\t/* Coordinates of highest child found so far\n\t\t\t\t * that contains point. */\n    int x, y;\t\t\t/* Coordinates in winPtr. */\n    int tmpx, tmpy, bd;\n\n    /*\n     * Step 1: find the top-level window that contains the desired point.\n     */\n\n    winPtr = FrontMostToplevelAtPoint(rootX, rootY);\n    if (!winPtr) {\n\treturn NULL;\n    }\n\n    /*\n     * Step 2: work down through the hierarchy underneath this window. At each\n     * level, scan through all the children to find the highest one in the\n     * stacking order that contains the point. Then repeat the whole process\n     * on that child.\n     */\n\n    x = rootX - winPtr->wmInfoPtr->xInParent;\n    y = rootY - winPtr->wmInfoPtr->yInParent;\n    while (1) {\n\tx -= winPtr->changes.x;\n\ty -= winPtr->changes.y;\n\tnextPtr = NULL;\n\n\t/*\n\t * Container windows cannot have children. So if it is a container,\n\t * look there, otherwise inspect the children.\n\t */\n\n\tif (Tk_IsContainer(winPtr)) {\n\t    childPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t    if (childPtr != NULL) {\n\t\tif (Tk_IsMapped(childPtr)) {\n\t\t    tmpx = x - childPtr->changes.x;\n\t\t    tmpy = y - childPtr->changes.y;\n\t\t    bd = childPtr->changes.border_width;\n\n\t\t    if ((tmpx >= -bd) && (tmpy >= -bd)\n\t\t\t    && (tmpx < (childPtr->changes.width + bd))\n\t\t\t    && (tmpy < (childPtr->changes.height + bd))) {\n\t\t\tnextPtr = childPtr;\n\t\t    }\n\t\t}\n\t    }\n\n\t    /*\n\t     * TODO: Here we should handle out of process embedding.\n\t     */\n\t} else {\n\t    for (childPtr = winPtr->childList; childPtr != NULL;\n\t\t    childPtr = childPtr->nextPtr) {\n\t\tif (!Tk_IsMapped(childPtr) ||\n\t\t\t(childPtr->flags & TK_TOP_LEVEL)) {\n\t\t    continue;\n\t\t}\n\t\ttmpx = x - childPtr->changes.x;\n\t\ttmpy = y - childPtr->changes.y;\n\t\tbd = childPtr->changes.border_width;\n\t\tif ((tmpx >= -bd) && (tmpy >= -bd)\n\t\t\t&& (tmpx < (childPtr->changes.width + bd))\n\t\t\t&& (tmpy < (childPtr->changes.height + bd))) {\n\t\t    nextPtr = childPtr;\n\t\t}\n\t    }\n\t}\n\tif (nextPtr == NULL) {\n\t    break;\n\t}\n\twinPtr = nextPtr;\n    }\n    if (winPtr->mainPtr != ((TkWindow *)tkwin)->mainPtr) {\n\treturn NULL;\n    }\n    return (Tk_Window)winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_TopCoordsToWindow --\n *\n *\tGiven a Tk Window, and coordinates of a point relative to that window\n *\tthis procedure returns the top-most child of the window (excluding\n *\ttoplevels) covering that point, if there exists such a window in this\n *\tapplication. It also sets newX, and newY to the coords of the point\n *\trelative to the window returned.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\trootX and rootY, or else NULL to indicate that there is no such\n *\twindow. newX and newY are also set to the coords of the point relative\n *\tto the returned window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_TopCoordsToWindow(\n    Tk_Window tkwin,\t\t/* Token for a Tk Window which defines the\n\t\t\t\t * coordinates for rootX & rootY */\n    int rootX, int rootY,\t/* Coordinates of a point in tkWin. */\n    int *newX, int *newY)\t/* Coordinates of point in the upperMost child\n\t\t\t\t * of tkWin containing (rootX,rootY) */\n{\n    TkWindow *winPtr, *childPtr;\n    TkWindow *nextPtr;\t\t/* Coordinates of highest child found so far\n\t\t\t\t * that contains point. */\n    int x, y;\t\t\t/* Coordinates in winPtr. */\n\n    winPtr = (TkWindow *)tkwin;\n    x = rootX;\n    y = rootY;\n    while (1) {\n\tnextPtr = NULL;\n\n\t/*\n\t * Container windows cannot have children. So if it is a container,\n\t * look there, otherwise inspect the children.\n\t */\n\n\tif (Tk_IsContainer(winPtr)) {\n\t    childPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\t    if (childPtr != NULL) {\n\t\tif (Tk_IsMapped(childPtr) &&\n\t\t\tx > childPtr->changes.x &&\n\t\t\tx < childPtr->changes.x + childPtr->changes.width &&\n\t\t\ty > childPtr->changes.y &&\n\t\t\ty < childPtr->changes.y + childPtr->changes.height) {\n\t\t    nextPtr = childPtr;\n\t\t}\n\t    }\n\n\t    /*\n\t     * TODO: Here we should handle out of process embedding.\n\t     */\n\t} else {\n\t    for (childPtr = winPtr->childList; childPtr != NULL;\n\t\t    childPtr = childPtr->nextPtr) {\n\t\tif (!Tk_IsMapped(childPtr) ||\n\t\t\t(childPtr->flags & TK_TOP_LEVEL)) {\n\t\t    continue;\n\t\t}\n\t\tif (x < childPtr->changes.x || y < childPtr->changes.y) {\n\t\t    continue;\n\t\t}\n\t\tif (x > childPtr->changes.x + childPtr->changes.width ||\n\t\t\ty > childPtr->changes.y + childPtr->changes.height) {\n\t\t    continue;\n\t\t}\n\t\tnextPtr = childPtr;\n\t    }\n\t}\n\tif (nextPtr == NULL) {\n\t    break;\n\t}\n\twinPtr = nextPtr;\n\tx -= winPtr->changes.x;\n\ty -= winPtr->changes.y;\n    }\n    *newX = x;\n    *newY = y;\n    return (Tk_Window)winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateVRootGeometry --\n *\n *\tThis procedure is called to update all the virtual root geometry\n *\tinformation in wmPtr.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe vRootX, vRootY, vRootWidth, and vRootHeight fields in wmPtr are\n *\tfilled with the most up-to-date information.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateVRootGeometry(\n    WmInfo *wmPtr)\t\t/* Window manager information to be updated.\n\t\t\t\t * The wmPtr->vRoot field must be valid. */\n{\n    TkWindow *winPtr = wmPtr->winPtr;\n    unsigned int bd, dummy;\n    Window dummy2;\n    Status status;\n    Tk_ErrorHandler handler;\n\n    /*\n     * If this isn't a virtual-root window manager, just return information\n     * about the screen.\n     */\n\n    wmPtr->flags &= ~WM_VROOT_OFFSET_STALE;\n    if (wmPtr->vRoot == None) {\n    noVRoot:\n\twmPtr->vRootX = wmPtr->vRootY = 0;\n\twmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum);\n\twmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum);\n\treturn;\n    }\n\n    /*\n     * Refresh the virtual root information if it's out of date.\n     */\n\n    handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL);\n    status = XGetGeometry(winPtr->display, wmPtr->vRoot,\n\t    &dummy2, &wmPtr->vRootX, &wmPtr->vRootY,\n\t    &wmPtr->vRootWidth, &wmPtr->vRootHeight, &bd, &dummy);\n    if (wmTracing) {\n\tTkMacOSXDbgMsg(\"x = %d, y = %d, width = %d, height = %d, status = %d\",\n\t\twmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth,\n\t\twmPtr->vRootHeight, status);\n    }\n    Tk_DeleteErrorHandler(handler);\n    if (status == 0) {\n\t/*\n\t * The virtual root is gone! Pretend that it never existed.\n\t */\n\n\twmPtr->vRoot = None;\n\tgoto noVRoot;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetVRootGeometry --\n *\n *\tThis procedure returns information about the virtual root window\n *\tcorresponding to a particular Tk window.\n *\n * Results:\n *\tThe values at xPtr, yPtr, widthPtr, and heightPtr are set with the\n *\toffset and dimensions of the root window corresponding to tkwin. If\n *\ttkwin is being managed by a virtual root window manager these values\n *\tcorrespond to the virtual root window being used for tkwin; otherwise\n *\tthe offsets will be 0 and the dimensions will be those of the screen.\n *\n * Side effects:\n *\tVroot window information is refreshed if it is out of date.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetVRootGeometry(\n    Tk_Window tkwin,\t\t/* Window whose virtual root is to be\n\t\t\t\t * queried. */\n    int *xPtr, int *yPtr,\t/* Store x and y offsets of virtual root\n\t\t\t\t * here. */\n    int *widthPtr,\t\t/* Store dimensions of virtual root here. */\n    int *heightPtr)\n{\n    WmInfo *wmPtr;\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    /*\n     * Find the top-level window for tkwin, and locate the window manager\n     * information for that window.\n     */\n\n    while (!(winPtr->flags & TK_TOP_LEVEL)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n\n    /*\n     * Make sure that the geometry information is up-to-date, then copy it out\n     * to the caller.\n     */\n\n    if (wmPtr->flags & WM_VROOT_OFFSET_STALE) {\n\tUpdateVRootGeometry(wmPtr);\n    }\n    *xPtr = wmPtr->vRootX;\n    *yPtr = wmPtr->vRootY;\n    *widthPtr = wmPtr->vRootWidth;\n    *heightPtr = wmPtr->vRootHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MoveToplevelWindow --\n *\n *\tThis procedure is called instead of Tk_MoveWindow to adjust the x-y\n *\tlocation of a top-level window. It delays the actual move to a later\n *\ttime and keeps window-manager information up-to-date with the move.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is eventually moved so that its upper-left corner\n *\t(actually, the upper-left corner of the window's decorative frame, if\n *\tthere is one) is at (x,y).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MoveToplevelWindow(\n    Tk_Window tkwin,\t\t/* Window to move. */\n    int x, int y)\t\t/* New location for window (within parent). */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\tTcl_Panic(\"Tk_MoveToplevelWindow called with non-toplevel window\");\n    }\n    wmPtr->x = x;\n    wmPtr->y = y;\n    wmPtr->flags |= WM_MOVE_PENDING;\n    if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\twmPtr->sizeHintsFlags |= USPosition;\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    }\n\n    /*\n     * If the window has already been mapped, must bring its geometry\n     * up-to-date immediately, otherwise an event might arrive from the server\n     * that would overwrite wmPtr->x and wmPtr->y and lose the new position.\n     */\n\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tif (wmPtr->flags & WM_UPDATE_PENDING) {\n\t    Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n\t}\n\tUpdateGeometryInfo(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRestackToplevel --\n *\n *\tThis procedure restacks a top-level window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr gets restacked as specified by aboveBelow and otherPtr. This\n *\tprocedure doesn't return until the restack has taken effect and the\n *\tConfigureNotify event for it has been received.\n *\n *----------------------------------------------------------------------\n */\n#define PRINT_STACK\t\t\t\t\t\\\n    for (NSWindow *w in [NSApp orderedWindows]) {\t\t\\\n    TkWindow *winPtr2 = TkMacOSXGetTkWindow(w);\t\t\t\\\n\tif (winPtr2) {\t\t\t\t\t\t\\\n\t    fprintf(stderr, \"%s \", Tk_PathName(winPtr2));\t\\\n\t}\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\n    fprintf(stderr, \"\\n\");\t\t\t\t\t\\\n    fflush(stderr)\n\nvoid\nTkWmRestackToplevel(\n    TkWindow *winPtr,\t\t/* Window to restack. */\n    int aboveBelow,\t\t/* Gives relative position for restacking;\n\t\t\t\t * must be Above or Below. */\n    TkWindow *otherPtr)\t\t/* Window relative to which to restack; if\n\t\t\t\t * NULL, then winPtr gets restacked above or\n\t\t\t\t * below *all* siblings. */\n{\n    NSWindow *macWindow;\n    NSWindow *otherMacWindow;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int macAboveBelow = (aboveBelow == Above ? NSWindowAbove : NSWindowBelow);\n    int otherNumber = 0; /* 0 will be used when otherPtr is NULL. */\n\n    /*\n     * If the Tk windows has no drawable, or is withdrawn do nothing.\n     */\n\n    if (winPtr->window == None ||\n\t    wmPtr == NULL      ||\n\t    wmPtr->hints.initial_state == WithdrawnState) {\n\treturn;\n    }\n    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    if (macWindow == nil) {\n\treturn;\n    }\n    if (otherPtr) {\n\t/*\n\t * When otherPtr is non-NULL, if the other window has no drawable or is\n\t * withdrawn, do nothing.\n\t */\n\n\tWmInfo *otherWmPtr = otherPtr->wmInfoPtr;\n\tif (winPtr->window == None ||\n\t\totherWmPtr == NULL ||\n\t\totherWmPtr->hints.initial_state == WithdrawnState) {\n\t    return;\n\t}\n\totherMacWindow = TkMacOSXGetNSWindowForDrawable(otherPtr->window);\n\tif (otherMacWindow == nil) {\n\t    return;\n\t}\n\n\t/*\n\t * If the other window is OK, get its number.\n\t */\n\n\totherNumber = [otherMacWindow windowNumber];\n    }\n\n    /*\n     * Just let the Mac window manager deal with all the subtleties of keeping\n     * track of off-screen windows, etc.\n     */\n#if 0\n    fprintf(stderr, \"window order: \"); PRINT_STACK;\n#endif\n    [macWindow orderWindow:macAboveBelow relativeTo:otherNumber];\n#if 0\n    fprintf(stderr, \"new window order: \"); PRINT_STACK;\n#endif\n#undef PRINT_STACK\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmAddToColormapWindows --\n *\n *\tThis procedure is called to add a given window to the\n *\tWM_COLORMAP_WINDOWS property for its top-level, if it isn't already\n *\tthere. It is invoked by the Tk code that creates a new colormap, in\n *\torder to make sure that colormap information is propagated to the\n *\twindow manager by default.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets added to the WM_COLORMAP_WINDOWS property of its\n *\tnearest top-level ancestor, unless the colormaps have been set\n *\texplicitly with the \"wm colormapwindows\" command.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmAddToColormapWindows(\n    TkWindow *winPtr)\t\t/* Window with a non-default colormap. Should\n\t\t\t\t * not be a top-level window. */\n{\n    TkWindow *topPtr;\n    TkWindow **oldPtr, **newPtr;\n    int count, i;\n\n    if (winPtr->window == None) {\n\treturn;\n    }\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Window is being deleted. Skip the whole operation.\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_LEVEL) {\n\t    break;\n\t}\n    }\n    if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {\n\treturn;\n    }\n\n    /*\n     * Make sure that the window isn't already in the list.\n     */\n\n    count = topPtr->wmInfoPtr->cmapCount;\n    oldPtr = topPtr->wmInfoPtr->cmapList;\n\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr) {\n\t    return;\n\t}\n    }\n\n    /*\n     * Make a new bigger array and use it to reset the property. Automatically\n     * add the toplevel itself as the last element of the list.\n     */\n\n    newPtr = (TkWindow **)Tcl_Alloc((count+2) * sizeof(TkWindow *));\n    if (count > 0) {\n\tmemcpy(newPtr, oldPtr, count * sizeof(TkWindow *));\n    }\n    if (count == 0) {\n\tcount++;\n    }\n    newPtr[count-1] = winPtr;\n    newPtr[count] = topPtr;\n    if (oldPtr != NULL) {\n\tTcl_Free(oldPtr);\n    }\n\n    topPtr->wmInfoPtr->cmapList = newPtr;\n    topPtr->wmInfoPtr->cmapCount = count+1;\n\n    /*\n     * On the Macintosh all of this is just an excercise in compatibility as\n     * we don't support colormaps. If we did they would be installed here.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRemoveFromColormapWindows --\n *\n *\tThis procedure is called to remove a given window from the\n *\tWM_COLORMAP_WINDOWS property for its top-level. It is invoked when\n *\twindows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets removed from the WM_COLORMAP_WINDOWS property of\n *\tits nearest top-level ancestor, unless the top-level itself is being\n *\tdeleted too.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmRemoveFromColormapWindows(\n    TkWindow *winPtr)\t\t/* Window that may be present in\n\t\t\t\t * WM_COLORMAP_WINDOWS property for its\n\t\t\t\t * top-level. Should not be a top-level\n\t\t\t\t * window. */\n{\n    TkWindow *topPtr, **oldPtr;\n    int count, i, j;\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Ancestors have been deleted, so skip the whole operation. Seems\n\t     * like this can't ever happen?\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_LEVEL) {\n\t    break;\n\t}\n    }\n    if (topPtr->flags & TK_ALREADY_DEAD) {\n\t/*\n\t * Top-level is being deleted, so there's no need to cleanup the\n\t * WM_COLORMAP_WINDOWS property.\n\t */\n\n\treturn;\n    }\n\n    /*\n     * Find the window and slide the following ones down to cover it up.\n     */\n\n    count = topPtr->wmInfoPtr->cmapCount;\n    oldPtr = topPtr->wmInfoPtr->cmapList;\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr) {\n\t    for (j = i ; j < count-1; j++) {\n\t\toldPtr[j] = oldPtr[j+1];\n\t    }\n\t    topPtr->wmInfoPtr->cmapCount = count - 1;\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetPointerCoords --\n *\n *\tFetch the position of the mouse pointer.\n *\n * Results:\n *\t*xPtr and *yPtr are filled in with the (virtual) root coordinates of\n *\tthe mouse pointer for tkwin's display. If the pointer isn't on tkwin's\n *\tscreen, then -1 values are returned for both coordinates. The argument\n *\ttkwin must be a toplevel window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetPointerCoords(\n    TCL_UNUSED(Tk_Window),\t/* Toplevel window that identifies screen on\n\t\t\t\t * which lookup is to be done. */\n    int *xPtr, int *yPtr)\t/* Store pointer coordinates here. */\n{\n    XQueryPointer(NULL, None, NULL, NULL, xPtr, yPtr, NULL, NULL, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitialWindowBounds --\n *\n *\tThis function calculates the initial bounds for a new Mac toplevel\n *\twindow. Unless the geometry is specified by the user this code will\n *\tauto place the windows in a cascade diagonially across the main monitor\n *\tof the Mac.\n *\n * Results:\n *\tWindow bounds.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NSRect\nInitialWindowBounds(\n    TkWindow *winPtr,\t\t/* Window to get initial bounds for. */\n    NSWindow *macWindow)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))) {\n\tstatic NSPoint cascadePoint = { .x = 0, .y = 0 };\n\tNSRect frame;\n\n\tcascadePoint = [macWindow cascadeTopLeftFromPoint:cascadePoint];\n\tframe = [macWindow frame];\n\twmPtr->x = frame.origin.x;\n\twmPtr->y = TkMacOSXZeroScreenHeight() - (frame.origin.y +\n\t\tframe.size.height);\n    }\n    return NSMakeRect(wmPtr->x, wmPtr->y, winPtr->changes.width,\n\t    winPtr->changes.height);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetWMName --\n *\n *\tSet the title for a toplevel window. If the window is embedded, do not\n *\tchange the window title.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe title of the window is changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSetWMName(\n    TkWindow *winPtr,\n    const char *title)\n{\n    if (Tk_IsEmbedded(winPtr)) {\n\treturn;\n    }\n\n    NSString *nstitle = [[TKNSString alloc] initWithTclUtfBytes:title length:TCL_INDEX_NONE];\n    [TkMacOSXGetNSWindowForDrawable(winPtr->window) setTitle:nstitle];\n    [nstitle release];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetContainer --\n *\n *\tIf the passed window has the TRANSIENT_FOR property set this will\n *\treturn the container window. Otherwise it will return None.\n *\n * Results:\n *\tThe container window or None.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTkMacOSXGetContainer(\n    TkWindow *winPtr)\n{\n    if (Tk_PathName(winPtr)) {\n\treturn (Tk_Window)winPtr->wmInfoPtr->container;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXGetXWindow --\n *\n *\tStub function that returns the X window Id associated with the\n *      given NSWindow*.\n *\n * Results:\n *\tThe window id is returned. None is returned if not a Tk window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTkMacOSXGetXWindow(\n    void *macWinPtr)\n{\n    Window window = None;\n    TKWindow *w = (TKWindow *)macWinPtr;\n    if ([w respondsToSelector: @selector (tkWindow)]) {\n\twindow = [w tkWindow];\n    }\n    return window ? window : None;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MacOSXGetTkWindow --\n *\n *\tReturns the Tk_Window associated with the given NSWindow*.  This\n *      function is a stub, so the NSWindow* parameter must be declared as\n *      void*.\n *\n * Results:\n *\tA Tk_Window, or None if the NSWindow is not associated with\n *      any Tk window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_MacOSXGetTkWindow(\n    void *w)\n{\n    Window window = None;\n    if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) {\n\twindow = [(TKWindow *)w tkWindow];\n\tTkDisplay *dispPtr = TkGetDisplayList();\n\tif (window && dispPtr && dispPtr->display) {\n\t    return Tk_IdToWindow(dispPtr->display, window);\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXIsWindowZoomed --\n *\n *\tAsk Cocoa if the given window is in the zoomed out state. Because\n *\tdragging & growing a window can change the Cocoa zoom state, we\n *\tcannot rely on wmInfoPtr->hints.initial_state for this information.\n *\n * Results:\n *\tTrue if window is zoomed out, false otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nMODULE_SCOPE int\nTkMacOSXIsWindowZoomed(\n    TkWindow *winPtr)\n{\n    NSWindow *macWindow = nil;\n    if (winPtr && winPtr->window) {\n\tmacWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n    return [macWindow isZoomed];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXZoomToplevel --\n *\n *\tThe function is invoked when the user clicks in the zoom region of a\n *\tTk window or when the window state is set/unset to \"zoomed\" manually.\n *\tIf the window is to be zoomed (in or out), the window size is changed\n *\tand events are generated to let Tk know what happened.\n *\n * Results:\n *\tTrue if events were placed on event queue, false otherwise.\n *\n * Side effects:\n *\tThe window may be resized & events placed on Tk's queue.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkMacOSXZoomToplevel(\n    void *whichWindow,\t\t/* The Macintosh window to zoom. */\n    short zoomPart)\t\t/* Either inZoomIn or inZoomOut */\n{\n    NSWindow *window = (NSWindow *)whichWindow;\n    TkWindow *winPtr = (TkWindow *)TkMacOSXGetTkWindow(window);\n    WmInfo *wmPtr;\n\n    if (!winPtr || !winPtr->wmInfoPtr) {\n\treturn false;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&\n\t    (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {\n\treturn false;\n    }\n\n    /*\n     * Do nothing if already in desired zoom state.\n     */\n\n    if (([window isZoomed] == (zoomPart == inZoomOut))) {\n\treturn false;\n    }\n    [window zoom:NSApp];\n\n    wmPtr->hints.initial_state =\n\t(zoomPart == inZoomIn ? NormalState : ZoomState);\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUnsupported1ObjCmd --\n *\n *\tThis procedure is invoked to process the\n *\t\"::tk::unsupported::MacWindowStyle\" Tcl command. This command allows\n *\tyou to set the style of decoration for a Macintosh window.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tChanges the style of a new Mac window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkUnsupported1ObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    static const char *const subcmds[] = {\n\t\"appearance\", \"isdark\", \"style\", NULL\n    };\n    enum SubCmds {\n\tTKMWS_APPEARANCE, TKMWS_ISDARK, TKMWS_STYLE\n    };\n    Tk_Window tkwin = (Tk_Window)clientData;\n    TkWindow *winPtr;\n    int index;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"option window ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    winPtr = (TkWindow *)\n\t    Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);\n    if (winPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" isn't a top-level window\", winPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WINDOWSTYLE\", \"TOPLEVEL\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], subcmds,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    switch((enum SubCmds) index) {\n    case TKMWS_STYLE:\n\tif ((objc < 3) || (objc > 5)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?class attributes?\");\n\t    return TCL_ERROR;\n\t}\n\treturn WmWinStyle(interp, winPtr, objc, objv);\n    case TKMWS_APPEARANCE:\n\tif ((objc < 3) || (objc > 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window ?appearancename?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 4 && [NSApp macOSVersion] < 101400) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Window appearances cannot be changed before OSX 10.14.\",\n\t\t    -1));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WINDOWSTYLE\", \"APPEARANCE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\treturn WmWinAppearance(interp, winPtr, objc, objv);\n    case TKMWS_ISDARK:\n\tif ((objc != 3)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"window\");\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\tTkMacOSXInDarkMode((Tk_Window)winPtr)));\n\treturn TCL_OK;\n    default:\n\treturn TCL_ERROR;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmWinStyle --\n *\n *\tThis procedure is invoked to process the\n *\t\"::tk::unsupported::MacWindowStyle style\" subcommand. This command\n *\tallows you to set the style of decoration for a Macintosh window.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tChanges the style of a new Mac window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmWinStyle(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TkWindow *winPtr,\t\t/* Window to be manipulated. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj * const objv[])\t/* Argument objects. */\n{\n    struct StrIntMap {\n\tconst char *strValue;\n\tUInt64 intValue;\n    };\n    static const struct StrIntMap classMap[] = {\n\t{ \"alert\",\t\tkAlertWindowClass\t\t\t     },\n\t{ \"moveableAlert\",\tkMovableAlertWindowClass\t\t     },\n\t{ \"modal\",\t\tkModalWindowClass\t\t\t     },\n\t{ \"moveableModal\",\tkMovableModalWindowClass\t\t     },\n\t{ \"floating\",\t\tkFloatingWindowClass\t\t\t     },\n\t{ \"document\",\t\tkDocumentWindowClass\t\t\t     },\n\t{ \"utility\",\t\tkUtilityWindowClass\t\t\t     },\n\t{ \"help\",\t\tkHelpWindowClass\t\t\t     },\n\t{ \"sheet\",\t\tkSheetWindowClass\t\t\t     },\n\t{ \"toolbar\",\t\tkToolbarWindowClass\t\t\t     },\n\t{ \"plain\",\t\tkPlainWindowClass\t\t\t     },\n\t{ \"overlay\",\t\tkOverlayWindowClass\t\t\t     },\n\t{ \"sheetAlert\",\t\tkSheetAlertWindowClass\t\t\t     },\n\t{ \"altPlain\",\t\tkAltPlainWindowClass\t\t\t     },\n\t{ \"simple\",\t\tkSimpleWindowClass\t\t\t     },\n\t{ \"drawer\",\t\tkDrawerWindowClass\t\t\t     },\n\t{ NULL, 0 }\n    };\n    static const struct StrIntMap compositeAttrMap[] = {\n\t{ \"none\",\t\tkWindowNoAttributes\t\t\t     },\n\t{ \"standardDocument\",\tkWindowStandardDocumentAttributes\t     },\n\t{ \"standardFloating\",\tkWindowStandardFloatingAttributes\t     },\n\t{ \"fullZoom\",\t\tkWindowFullZoomAttribute\t\t     },\n\t{ NULL, 0 }\n    };\n\n    /*\n     * Map window attributes. Color and opacity are mapped to NULL; these are\n     * parsed from the objv in TkUnsupported1ObjCmd.\n     */\n\n    static const struct StrIntMap attrMap[] = {\n\t{ \"closeBox\",\t\tkWindowCloseBoxAttribute\t\t     },\n\t{ \"horizontalZoom\",\tkWindowHorizontalZoomAttribute\t\t     },\n\t{ \"verticalZoom\",\tkWindowVerticalZoomAttribute\t\t     },\n\t{ \"collapseBox\",\tkWindowCollapseBoxAttribute\t\t     },\n\t{ \"resizable\",\t\tkWindowResizableAttribute\t\t     },\n\t{ \"sideTitlebar\",\tkWindowSideTitlebarAttribute\t\t     },\n\t{ \"toolbarButton\",\tkWindowToolbarButtonAttribute\t\t     },\n\t{ \"unifiedTitleAndToolbar\", kWindowUnifiedTitleAndToolbarAttribute   },\n\t{ \"metal\",\t\tkWindowMetalAttribute\t\t\t     },\n\t{ \"noTitleBar\",\t\tkWindowNoTitleBarAttribute\t\t     },\n\t{ \"texturedSquareCorners\", kWindowTexturedSquareCornersAttribute     },\n\t{ \"metalNoContentSeparator\", kWindowMetalNoContentSeparatorAttribute },\n\t{ \"doesNotCycle\",\tkWindowDoesNotCycleAttribute\t\t     },\n\t{ \"noUpdates\",\t\tkWindowNoUpdatesAttribute\t\t     },\n\t{ \"noActivates\",\tkWindowNoActivatesAttribute\t\t     },\n\t{ \"opaqueForEvents\",\tkWindowOpaqueForEventsAttribute\t\t     },\n\t{ \"noShadow\",\t\tkWindowNoShadowAttribute\t\t     },\n\t{ \"hideOnSuspend\",\tkWindowHideOnSuspendAttribute\t\t     },\n\t{ \"hideOnFullScreen\",\tkWindowHideOnFullScreenAttribute\t     },\n\t{ \"inWindowMenu\",\tkWindowInWindowMenuAttribute\t\t     },\n\t{ \"liveResize\",\t\tkWindowLiveResizeAttribute\t\t     },\n\t{ \"ignoreClicks\",\tkWindowIgnoreClicksAttribute\t\t     },\n\t{ \"noConstrain\",\tkWindowNoConstrainAttribute\t\t     },\n\t{ \"doesNotHide\",\ttkWindowDoesNotHideAttribute\t\t     },\n\t{ \"canJoinAllSpaces\",\ttkCanJoinAllSpacesAttribute\t\t     },\n\t{ \"moveToActiveSpace\",\ttkMoveToActiveSpaceAttribute\t\t     },\n\t{ \"nonActivating\",\ttkNonactivatingPanelAttribute\t\t     },\n\t{ \"hud\",\t\ttkHUDWindowAttribute\t\t\t     },\n\t{ NULL, 0 }\n    };\n\n    int index;\n    Tcl_Size i;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc == 3) {\n\tTcl_Obj *attributeList, *newResult = NULL;\n\tUInt64 attributes;\n\n\tfor (i = 0; classMap[i].strValue != NULL; i++) {\n\t    if (wmPtr->macClass == classMap[i].intValue) {\n\t\tnewResult = Tcl_NewStringObj(classMap[i].strValue, TCL_INDEX_NONE);\n\t\tbreak;\n\t    }\n\t}\n\tif (newResult == NULL) {\n\t    Tcl_Panic(\"invalid class\");\n\t}\n\n\tattributeList = Tcl_NewListObj(0, NULL);\n\tattributes = wmPtr->attributes;\n\n\tfor (i = 0; compositeAttrMap[i].strValue != NULL; i++) {\n\t    UInt64 intValue = compositeAttrMap[i].intValue;\n\n\t    if (intValue && (attributes & intValue) == intValue) {\n\t\tTcl_ListObjAppendElement(NULL, attributeList,\n\t\t\tTcl_NewStringObj(compositeAttrMap[i].strValue,\n\t\t\t-1));\n\t\tattributes &= ~intValue;\n\t\tbreak;\n\t    }\n\t}\n\tfor (i = 0; attrMap[i].strValue != NULL; i++) {\n\t    if (attributes & attrMap[i].intValue) {\n\t\tTcl_ListObjAppendElement(NULL, attributeList,\n\t\t\tTcl_NewStringObj(attrMap[i].strValue, TCL_INDEX_NONE));\n\t    }\n\t}\n\tTcl_ListObjAppendElement(NULL, newResult, attributeList);\n\tTcl_SetObjResult(interp, newResult);\n    } else {\n\tTcl_Size attrObjc;\n\tTcl_Obj **attrObjv = NULL;\n\tWindowClass macClass;\n\tUInt64 oldAttributes = wmPtr->attributes;\n\tint oldFlags = wmPtr->flags;\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], classMap,\n\t\tsizeof(struct StrIntMap), \"class\", 0, &index) != TCL_OK) {\n\t    goto badClassAttrs;\n\t}\n\tmacClass = classMap[index].intValue;\n\tif (objc == 5) {\n\t    if (Tcl_ListObjGetElements(interp, objv[4], &attrObjc, &attrObjv)\n\t\t    != TCL_OK) {\n\t\tgoto badClassAttrs;\n\t    }\n\t    wmPtr->attributes = kWindowNoAttributes;\n\t    for (i = 0; i < attrObjc; i++) {\n\t\tif (Tcl_GetIndexFromObjStruct(interp, attrObjv[i],\n\t\t\tcompositeAttrMap, sizeof(struct StrIntMap),\n\t\t\t\"attribute\", 0, &index) == TCL_OK) {\n\t\t    wmPtr->attributes |= compositeAttrMap[index].intValue;\n\t\t} else if (Tcl_GetIndexFromObjStruct(interp, attrObjv[i],\n\t\t\tattrMap, sizeof(struct StrIntMap),\n\t\t\t\"attribute\", 0, &index) == TCL_OK) {\n\t\t    Tcl_ResetResult(interp);\n\t\t    wmPtr->attributes |= attrMap[index].intValue;\n\t\t} else {\n\t\t    goto badClassAttrs;\n\t\t}\n\t    }\n\t} else {\n\t    wmPtr->attributes = macClassAttrs[macClass].defaultAttrs;\n\t}\n\twmPtr->attributes &= (tkAlwaysValidAttributes |\n\t\tmacClassAttrs[macClass].validAttrs);\n\twmPtr->flags |= macClassAttrs[macClass].flags;\n\twmPtr->macClass = macClass;\n\tApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags,\n\t\t0, 1);\n\treturn TCL_OK;\n\n    badClassAttrs:\n\twmPtr->attributes = oldAttributes;\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmWinAppearance --\n *\n *\tThis procedure is invoked to process the\n *\t\"::tk::unsupported::MacWindowStyle appearance\" subcommand. The command\n *\tallows you to get or set the appearance for the NSWindow associated\n *\twith a Tk Window.  The syntax is:\n *\n *\t    tk::unsupported::MacWindowStyle appearance window ?newAppearance?\n *\n *      Allowed appearance names are \"aqua\", \"darkaqua\", and \"auto\".\n *\n * Results:\n *      Returns the appearance setting of the window prior to calling this\n *\tfunction.\n *\n * Side effects:\n *      The underlying NSWindow's appearance property is set to the specified\n *      value if the optional newAppearance argument is supplied. Otherwise the\n *      window's appearance property is not changed.  If the appearance is set\n *      to aqua or darkaqua then the window will use the associated\n *      NSAppearance even if the user has selected a different appearance with\n *      the system preferences.  If it is set to auto then the appearance\n *      property is set to nil, meaning that the preferences will determine the\n *      appearance.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmWinAppearance(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TkWindow *winPtr,\t\t/* Window to be manipulated. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj * const objv[])\t/* Argument objects. */\n{\n#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000\n    (void) interp;\n    (void) winPtr;\n    (void) objc;\n    (void) objv;\n    return TCL_OK;\n#else\n    Tcl_Obj *result = NULL;\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n    NSAppearanceName appearance;\n#else\n    NSString *appearance;\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n\n    const char *resultString = \"unrecognized\";\n    NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    if (win) {\n\tappearance = win.appearance.name;\n\tif (appearance == nil) {\n\t    resultString = appearanceStrings[APPEARANCE_AUTO];\n\t} else if (appearance == NSAppearanceNameAqua) {\n\t    resultString = appearanceStrings[APPEARANCE_AQUA];\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t} else if (@available(macOS 10.14, *)) {\n\t    if (appearance == NSAppearanceNameDarkAqua) {\n\t\tresultString = appearanceStrings[APPEARANCE_DARKAQUA];\n\t    }\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t}\n\tresult = Tcl_NewStringObj(resultString, strlen(resultString));\n    }\n    if (result == NULL) {\n\tNSLog(@\"Failed to read appearance name; try calling update idletasks before getting/setting the appearance of the window.\");\n\treturn TCL_OK;\n    }\n    if (objc == 4) {\n\tint index;\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings,\n\t\tsizeof(char *), \"appearancename\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tswitch ((enum appearances) index) {\n\tcase APPEARANCE_AQUA:\n\t    win.appearance = [NSAppearance appearanceNamed:\n\t\tNSAppearanceNameAqua];\n\t    break;\n\tcase APPEARANCE_DARKAQUA:\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t    if (@available(macOS 10.14, *)) {\n\t\twin.appearance = [NSAppearance appearanceNamed:\n\t\t    NSAppearanceNameDarkAqua];\n\t    }\n#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n\t    break;\n\tdefault:\n\t    win.appearance = nil;\n\t}\n    }\n    Tcl_SetObjResult(interp, result);\n    return TCL_OK;\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMakeMenuWindow --\n *\n *\tConfigure the window to be either a undecorated pull-down (or pop-up)\n *\tmenu, or as a toplevel floating menu (palette).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the style bit used to create a new Mac toplevel.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMakeMenuWindow(\n    Tk_Window tkwin,\t\t/* New window. */\n    int transient)\t\t/* 1 means menu is only posted briefly as a\n\t\t\t\t * popup or pulldown or cascade. 0 means menu\n\t\t\t\t * is always visible, e.g. as a floating\n\t\t\t\t * menu. */\n{\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    if (transient) {\n\twinPtr->wmInfoPtr->macClass = kSimpleWindowClass;\n\twinPtr->wmInfoPtr->attributes = kWindowNoActivatesAttribute;\n    } else {\n\twinPtr->wmInfoPtr->macClass = kFloatingWindowClass;\n\twinPtr->wmInfoPtr->attributes = kWindowStandardFloatingAttributes;\n\twinPtr->wmInfoPtr->flags |= WM_WIDTH_NOT_RESIZABLE;\n\twinPtr->wmInfoPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXMakeRealWindowExist --\n *\n *\tThis function finally creates the real Macintosh window that the Mac\n *\tactually understands.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new Macintosh toplevel is created.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXMakeRealWindowExist(\n    TkWindow *winPtr)\t\t/* Tk window. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    MacDrawable *macWin;\n    WindowClass macClass;\n    Class winClass = nil;\n    Bool overrideRedirect = Tk_Attributes((Tk_Window)winPtr)->override_redirect;\n    Tcl_HashEntry *hPtr = NULL;\n    NSUInteger styleMask;\n    NSString *identifier;\n    char *tabbingId = NULL;\n    long tabbingMode = NSWindowTabbingModeAutomatic;\n    static bool initialized = false;\n\n    if (TkMacOSXHostToplevelExists(winPtr)) {\n\treturn;\n    }\n\n    macWin = (MacDrawable *)winPtr->window;\n\n    /*\n     * If this is embedded, make sure its container's toplevel exists, then\n     * return...\n     */\n\n    if (Tk_IsEmbedded(winPtr)) {\n\tTkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr);\n\n\tif (contWinPtr != NULL) {\n\t    TkMacOSXMakeRealWindowExist(\n\t\t    contWinPtr->privatePtr->toplevel->winPtr);\n\t    macWin->flags |= TK_HOST_EXISTS;\n\t    return;\n\t}\n\n\tTcl_Panic(\"TkMacOSXMakeRealWindowExist could not find container\");\n\treturn;\n\n\t/*\n\t * TODO: Here we should handle out of process embedding.\n\t */\n    }\n\n    if ([NSApp macOSVersion] >= 101300) {\n\t/*\n\t * Prior to macOS 10.12 the styleMask was readonly.  From macOS 10.12\n\t * onward, the styleMask can replace the Carbon window classes and\n\t * attributes.\n\t */\n\tint index;\n\tif (!initialized) {\n\t    Tcl_InitHashTable(&pathnameToSubclass, TCL_STRING_KEYS);\n\t    Tcl_InitHashTable(&pathnameToTabbingId, TCL_STRING_KEYS);\n\t    Tcl_InitHashTable(&pathnameToTabbingMode, TCL_STRING_KEYS);\n\t    initialized = true;\n\t}\n\thPtr = Tcl_FindHashEntry(&pathnameToSubclass, Tk_PathName(winPtr));\n\tindex = hPtr ? PTR2INT(Tcl_GetHashValue(hPtr)) : subclassNSWindow;\n\tswitch(index) {\n\tcase subclassNSPanel:\n\t    winClass = [TKPanel class];\n\t    styleMask =  (NSWindowStyleMaskTitled        |\n\t\t\t  NSWindowStyleMaskClosable      |\n\t\t\t  NSWindowStyleMaskResizable     |\n\t\t\t  NSWindowStyleMaskUtilityWindow |\n\t\t\t  NSWindowStyleMaskNonactivatingPanel );\n\t\tbreak;\n\tdefault:\n\t    winClass = [TKWindow class];\n\t    styleMask =  (NSWindowStyleMaskTitled         |\n\t\t\t  NSWindowStyleMaskClosable       |\n\t\t\t  NSWindowStyleMaskMiniaturizable |\n\t\t\t  NSWindowStyleMaskResizable );\n\t\tbreak;\n\t}\n\tif (overrideRedirect) {\n\t    styleMask |= NSWindowStyleMaskDocModalWindow;\n\t}\n\t/* Help windows (used for tooltips) should have stylemask 0. */\n\tif (wmPtr->macClass == kHelpWindowClass) {\n\t    styleMask = 0;\n\t}\n\tif (hPtr) {\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n\thPtr = Tcl_FindHashEntry(&pathnameToTabbingId, Tk_PathName(winPtr));\n\tif (hPtr) {\n\t    tabbingId = (char *)Tcl_GetHashValue(hPtr);\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n\thPtr = Tcl_FindHashEntry(&pathnameToTabbingMode, Tk_PathName(winPtr));\n\tif (hPtr) {\n\t    tabbingMode = PTR2INT(Tcl_GetHashValue(hPtr));\n\t    Tcl_DeleteHashEntry(hPtr);\n\t}\n    } else {\n\n\t/*\n\t * If this is an override-redirect window, the NSWindow is created first as\n\t * a document window then converted to a simple window.\n\t */\n\n\tif (overrideRedirect) {\n\t    wmPtr->macClass = kDocumentWindowClass;\n\t}\n\tmacClass = wmPtr->macClass;\n\twmPtr->attributes &= (tkAlwaysValidAttributes |\n\t\t\t      macClassAttrs[macClass].validAttrs);\n\twmPtr->flags |= macClassAttrs[macClass].flags |\n\t    ((wmPtr->attributes & kWindowResizableAttribute) ? 0 :\n\t     WM_WIDTH_NOT_RESIZABLE|WM_HEIGHT_NOT_RESIZABLE);\n\tUInt64 attributes = (wmPtr->attributes &\n\t\t\t     ~macClassAttrs[macClass].forceOffAttrs) |\n\t    macClassAttrs[macClass].forceOnAttrs;\n\tstyleMask = macClassAttrs[macClass].styleMask |\n\t    ((attributes & kWindowNoTitleBarAttribute) ? 0 : NSTitledWindowMask) |\n\t    ((attributes & kWindowCloseBoxAttribute) ? NSClosableWindowMask : 0) |\n\t    ((attributes & kWindowCollapseBoxAttribute) ?\n\t     NSMiniaturizableWindowMask : 0) |\n\t    ((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) |\n\t    ((attributes & kWindowMetalAttribute) ?\n\t     NSTexturedBackgroundWindowMask : 0) |\n\t    ((attributes & kWindowUnifiedTitleAndToolbarAttribute) ?\n\t     NSUnifiedTitleAndToolbarWindowMask : 0) |\n\t    ((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) |\n\t    (attributes >> WM_NSMASK_SHIFT);\n\twinClass = (macClass == kDrawerWindowClass ? [TKDrawerWindow class] :\n\t\t    (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask|\n\t\t\t\t  NSNonactivatingPanelMask|NSHUDWindowMask)) ?\n\t\t    [TKPanel class] : [TKWindow class]);\n    }\n    NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect\n\t    styleMask:styleMask];\n    NSRect contentRect = NSMakeRect(5 - structureRect.origin.x,\n\t    TkMacOSXZeroScreenHeight() - (TkMacOSXZeroScreenTop() + 5 +\n\t    structureRect.origin.y + structureRect.size.height + 200), 200, 200);\n    if (wmPtr->hints.initial_state == WithdrawnState) {\n\t//// ???????\n    }\n    TKWindow *window = [[winClass alloc] initWithContentRect:contentRect\n\t    styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];\n    if (!window) {\n\tTcl_Panic(\"couldn't allocate new Mac window\");\n    }\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300\n    if (tabbingId) {\n\tidentifier = [NSString stringWithUTF8String:tabbingId];\n    } else {\n\tidentifier = [NSString stringWithUTF8String:Tk_PathName(winPtr)];\n    }\n    [window setTabbingIdentifier: identifier];\n    [window setTabbingMode: tabbingMode];\n#endif\n    if (tabbingId) {\n\tTcl_Free(tabbingId);\n    }\n    TKContentView *contentView = [[TKContentView alloc]\n\t\t\t\t     initWithFrame:NSZeroRect];\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400\n    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];\n\n    /*\n     * AppKit calls the viewDidChangeEffectiveAppearance method when the\n     * user changes the Accent Color but not when the user changes the\n     * Highlight Color.  So we register to receive KVO notifications for\n     * Highlight Color as well.\n     */\n\n    [preferences addObserver:contentView\n\t\t  forKeyPath:@\"AppleHighlightColor\"\n\t\t     options:NSKeyValueObservingOptionNew\n\t\t     context:NULL];\n#endif\n    [window setContentView:contentView];\n    [contentView release];\n    [window setDelegate:NSApp];\n    [window setAcceptsMouseMovedEvents:NO];\n    [window setReleasedWhenClosed:NO];\n    if (styleMask & NSUtilityWindowMask) {\n\t[(TKPanel*)window setFloatingPanel:YES];\n    }\n    if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&\n\t    !(styleMask & NSDocModalWindowMask)) {\n\t/*\n\t * Workaround for [Bug 2824538]: Textured windows are draggable from\n\t *                               opaque content.\n\t */\n\t[window setMovableByWindowBackground:NO];\n    }\n    [window setDocumentEdited:NO];\n    wmPtr->window = window;\n    macWin->view = window.contentView;\n    TkMacOSXApplyWindowAttributes(winPtr, window);\n    NSRect geometry = InitialWindowBounds(winPtr, window);\n    geometry.size.width += structureRect.size.width;\n    geometry.size.height += structureRect.size.height;\n    geometry.origin.y = TkMacOSXZeroScreenHeight() - (geometry.origin.y +\n\t    geometry.size.height);\n    [window setFrame:geometry display:YES];\n    [window setTkWindow: (Window) macWin];\n\n    macWin->flags |= TK_HOST_EXISTS;\n    if (overrideRedirect) {\n\tXSetWindowAttributes atts;\n\n\tatts.override_redirect = True;\n\tTk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);\n\tif ([NSApp macOSVersion] >= 101300) {\n\t    window.styleMask |= NSWindowStyleMaskDocModalWindow;\n\t} else {\n\t    ApplyContainerOverrideChanges(winPtr, NULL);\n\t}\n    }\n    [window display];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXSetScrollbarGrow --\n *\n *\tSets a flag for a toplevel window indicating that the passed Tk\n *\tscrollbar window will display the grow region for the toplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA flag is set int windows toplevel parent.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXSetScrollbarGrow(\n    TkWindow *winPtr,\t\t/* Tk scrollbar window. */\n    int flag)\t\t\t/* Boolean value true or false. */\n{\n    if (flag) {\n\twinPtr->privatePtr->toplevel->flags |= TK_SCROLLBAR_GROW;\n\twinPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = winPtr;\n    } else if (winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr\n\t    == winPtr) {\n\twinPtr->privatePtr->toplevel->flags &= ~TK_SCROLLBAR_GROW;\n\twinPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmFocusToplevel --\n *\n *\tThis is a utility procedure invoked by focus-management code. It\n *\texists because of the extra wrapper windows that exist under Unix; its\n *\tjob is to map from wrapper windows to the corresponding toplevel\n *\twindows. On PCs and Macs there are no wrapper windows so no mapping is\n *\tnecessary; this procedure just determines whether a window is a\n *\ttoplevel or not.\n *\n * Results:\n *\tIf winPtr is a toplevel window, returns the pointer to the window;\n *\totherwise returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkWmFocusToplevel(\n    TkWindow *winPtr)\t\t/* Window that received a focus-related\n\t\t\t\t * event. */\n{\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\treturn NULL;\n    }\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetWrapperWindow --\n *\n *\tThis is a utility procedure invoked by focus-management code. It maps\n *\tto the wrapper for a top-level, which is just the same as the\n *\ttop-level on Macs and PCs.\n *\n * Results:\n *\tIf winPtr is a toplevel window, returns the pointer to the window;\n *\totherwise returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkpGetWrapperWindow(\n    TkWindow *winPtr)\t\t/* Window that received a focus-related\n\t\t\t\t * event. */\n{\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\treturn NULL;\n    }\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWmSetState --\n *\n *\tSets the window manager state for the wrapper window of a given\n *\ttoplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay maximize, minimize, restore, or withdraw a window.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkpWmSetState(\n    TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n    int state)\t\t\t/* One of IconicState, ZoomState, NormalState,\n\t\t\t\t * or WithdrawnState. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    NSWindow *macWin = nil;\n\n    wmPtr->hints.initial_state = state;\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\tgoto setStateEnd;\n    }\n    if (winPtr && winPtr->window) {\n\tmacWin = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n\n    /*\n     * Make sure windows are updated before the state change.  As an exception,\n     * do not process idle tasks before withdrawing a window.  The purpose of\n     * this is to support the common paradigm of immediately withdrawing the\n     * root window.  Processing idle tasks before changing the state causes the\n     * root to briefly flash on the screen, which users of this paradigm find\n     * annoying.  Not processing the events does not guarantee that the window\n     * will not appear but makes it more likely.\n     */\n\n    if (state != WithdrawnState) {\n\twhile (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {};\n    }\n    if (state == WithdrawnState) {\n\tTkWmUnmapWindow(winPtr);\n    } else if (state == IconicState) {\n\n\t/*\n\t * The window always gets unmapped. If we can show the icon version of\n\t * the window we also collapse it.\n\t */\n\n\tif (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&\n\t\t![macWin isMiniaturized]) {\n\t    [macWin miniaturize:NSApp];\n\t}\n\tTkWmUnmapWindow(winPtr);\n    } else if (state == NormalState || state == ZoomState) {\n\tTkWmMapWindow(winPtr);\n\t[macWin deminiaturize:NSApp];\n\t[macWin orderFront:NSApp];\n\tTkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : inZoomOut);\n    }\n\n    /*\n     * Make sure windows are updated after the state change too.  This is needed\n     * in order for the event-9.11-20 tests to pass.\n     */\n\n    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}\nsetStateEnd:\n    return true;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkMacOSXWindowOffset --\n *\n *\tDetermines the x and y offset from the orgin of the toplevel window\n *\tdressing (the structure region, i.e. title bar) and the orgin of the\n *\tcontent area.\n *\n * Results:\n *\tThe x & y offset in pixels.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXWindowOffset(\n    void *wRef,\n    int *xOffset,\n    int *yOffset)\n{\n    TkWindow *winPtr = TkMacOSXGetTkWindow(wRef);\n\n    if (winPtr && winPtr->wmInfoPtr) {\n\t*xOffset = winPtr->wmInfoPtr->xInParent;\n\t*yOffset = winPtr->wmInfoPtr->yInParent;\n    } else {\n\t*xOffset = 0;\n\t*yOffset = 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetMS --\n *\n *\tReturn a relative time in milliseconds. It doesn't matter when the\n *\tepoch was.\n *\n * Results:\n *\tNumber of milliseconds.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nunsigned long\nTkpGetMS(void)\n{\n    Tcl_Time now;\n\n    Tcl_GetTime(&now);\n    return (long) now.sec * 1000 + now.usec / 1000;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSetInputFocus --\n *\n *\tChange the focus window for the application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetInputFocus(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(Time))\n{\n    /*\n     * Don't need to do a thing. Tk manages the focus for us.\n     */\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpChangeFocus --\n *\n *\tThis function is called when Tk moves focus from one window to another.\n *      It should be passed a non-embedded TopLevel. That toplevel gets raised\n *      to the top of the Tk stacking order and the associated NSWindow is\n *      ordered Front.\n *\n * Results:\n *\tThe return value is the serial number of the command that changed the\n *\tfocus. It may be needed by the caller to filter out focus change\n *\tevents that were queued before the command. If the procedure doesn't\n *\tactually change the focus then it returns 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nsize_t\nTkpChangeFocus(\n    TkWindow *winPtr,\t\t/* Window that is to receive the X focus. */\n    int force)\t\t\t/* Non-zero means claim the focus even if it\n\t\t\t\t * didn't originally belong to topLevelPtr's\n\t\t\t\t * application. */\n{\n    if (!winPtr || (winPtr->flags & TK_ALREADY_DEAD)\n\t    || !Tk_IsMapped(winPtr) ||\n\t    winPtr->atts.override_redirect) {\n\treturn 0;\n    }\n    if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) {\n\tNSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n\n\tTkWmRestackToplevel(winPtr, Above, NULL);\n\tif (force) {\n\t    [NSApp activateIgnoringOtherApps:YES];\n\t}\n\tif (win && [win canBecomeKeyWindow]) {\n\t    [win makeKeyAndOrderFront:NSApp];\n\t    [NSApp setTkEventTarget:TkMacOSXGetTkWindow(win)];\n\t}\n    }\n\n    /*\n     * Remember the current serial number for the X server and issue a dummy\n     * server request. This marks the position at which we changed the focus,\n     * so we can distinguish FocusIn and FocusOut events on either side of the\n     * mark.\n     */\n\n    return NextRequest(winPtr->display);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStackorderToplevelWrapperMap --\n *\n *\tThis procedure will create a table that maps the reparent wrapper X id\n *\tfor a toplevel to the TkWindow structure that it wraps. Tk keeps track\n *\tof a mapping from the window X id to the TkWindow structure but that\n *\tdoes us no good here since we only get the X id of the wrapper window.\n *\tOnly those toplevel windows that are mapped have a position in the\n *\tstacking order.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAdds entries to the passed hashtable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nWmStackorderToplevelWrapperMap(\n    TkWindow *winPtr,\t\t/* TkWindow to recurse on */\n    Display *display,\t\t/* X display of parent window */\n    Tcl_HashTable *table)\t/* Maps mac window to TkWindow */\n{\n    TkWindow *childPtr;\n    Tcl_HashEntry *hPtr;\n    int newEntry;\n\n    if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)\n\t    && (winPtr->display == display)) {\n\thPtr = Tcl_CreateHashEntry(table,\n\t\t(void *)TkMacOSXGetNSWindowForDrawable(winPtr->window), &newEntry);\n\tTcl_SetHashValue(hPtr, winPtr);\n    }\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tWmStackorderToplevelWrapperMap(childPtr, display, table);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevel --\n *\n *\tThis procedure returns the stack order of toplevel windows.\n *\n * Results:\n *\tA NULL terminated array of pointers to tk window objects in stacking\n *\torder or else NULL if there was an error.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow **\nTkWmStackorderToplevel(\n    TkWindow *parentPtr)\t/* Parent toplevel window. */\n{\n    TkWindow *childWinPtr, **windows, **windowPtr;\n    Tcl_HashTable table;\n    Tcl_HashEntry *hPtr;\n    NSArray *macWindows = [NSApp orderedWindows];\n    NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects];\n    NSInteger windowCount = [macWindows count];\n\n    windows = windowPtr = (TkWindow **)Tcl_Alloc((windowCount + 1) * sizeof(TkWindow *));\n    if (windows != NULL) {\n\tTcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);\n\tWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);\n\tfor (NSWindow *w in backToFront) {\n\t    hPtr = Tcl_FindHashEntry(&table, (char*) w);\n\t    if (hPtr != NULL) {\n\t\tchildWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);\n\t\t*windowPtr++ = childWinPtr;\n\t    }\n\t}\n\t*windowPtr = NULL;\n\tTcl_DeleteHashTable(&table);\n    }\n    return windows;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXApplyWindowAttributes --\n *\n *\tThis procedure applies all window attributes to the NSWindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXApplyWindowAttributes(\n    TkWindow *winPtr,\n    NSWindow *macWindow)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);\n    if (wmPtr->container != NULL || winPtr->atts.override_redirect) {\n\tApplyContainerOverrideChanges(winPtr, macWindow);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ApplyWindowAttributeFlagChanges --\n *\n *\tThis procedure applies window attribute and flag changes.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nApplyWindowAttributeFlagChanges(\n    TkWindow *winPtr,\n    NSWindow *macWindow,\n    UInt64 oldAttributes,\n    int oldFlags,\n    int create,\n    int initial)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    UInt64 newAttributes = ForceAttributes(wmPtr->attributes, wmPtr->macClass);\n    UInt64 changedAttributes = newAttributes ^ ForceAttributes(oldAttributes,\n\t    wmPtr->macClass);\n\n    if (changedAttributes || wmPtr->flags != oldFlags || initial) {\n\tif (!macWindow) {\n\t    if (winPtr->window == None) {\n\t\tif (!create) {\n\t\t    return;\n\t\t}\n\t\tTk_MakeWindowExist((Tk_Window)winPtr);\n\t    }\n\t    if (!TkMacOSXHostToplevelExists(winPtr)) {\n\t\tif (!create) {\n\t\t    return;\n\t\t}\n\t\tTkMacOSXMakeRealWindowExist(winPtr);\n\t    }\n\t    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n\t}\n\tif ((changedAttributes & kWindowCloseBoxAttribute) || initial) {\n\t    [[macWindow standardWindowButton:NSWindowCloseButton]\n\t\t    setEnabled:!!(newAttributes & kWindowCloseBoxAttribute)];\n\t}\n\tif ((changedAttributes & kWindowCollapseBoxAttribute) || initial) {\n\t    [[macWindow standardWindowButton:NSWindowMiniaturizeButton]\n\t\t    setEnabled:!!(newAttributes & kWindowCollapseBoxAttribute)];\n\t}\n\tif ((changedAttributes & (kWindowResizableAttribute |\n\t\tkWindowFullZoomAttribute)) || initial) {\n\t    [[macWindow standardWindowButton:NSWindowZoomButton]\n\t\t    setEnabled:(newAttributes & kWindowResizableAttribute) &&\n\t\t    (newAttributes & kWindowFullZoomAttribute)];\n\t    if (newAttributes & kWindowHorizontalZoomAttribute) {\n\t\twmPtr->flags &= ~(WM_WIDTH_NOT_RESIZABLE);\n\t    } else {\n\t\twmPtr->flags |= (WM_WIDTH_NOT_RESIZABLE);\n\t    }\n\t    if (newAttributes & kWindowVerticalZoomAttribute) {\n\t\twmPtr->flags &= ~(WM_HEIGHT_NOT_RESIZABLE);\n\t    } else {\n\t\twmPtr->flags |= (WM_HEIGHT_NOT_RESIZABLE);\n\t    }\n\t    WmUpdateGeom(wmPtr, winPtr);\n\t}\n\tif ((changedAttributes & kWindowToolbarButtonAttribute) || initial) {\n\t    [macWindow setShowsToolbarButton:\n\t\t    !!(newAttributes & kWindowToolbarButtonAttribute)];\n\t    if ((newAttributes & kWindowToolbarButtonAttribute) &&\n\t\t    ![macWindow toolbar]) {\n\t\tNSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@\"\"];\n\n\t\t[toolbar setVisible:NO];\n\t\t[macWindow setToolbar:toolbar];\n\t\t[toolbar release];\n\t\tNSCell *toolbarButtonCell = [[macWindow standardWindowButton:\n\t\t\tNSWindowToolbarButton] cell];\n\t\t[toolbarButtonCell setTarget:[macWindow contentView]];\n\t\t[toolbarButtonCell setAction:@selector(tkToolbarButton:)];\n\t    }\n\t}\n\tif ((changedAttributes & kWindowNoShadowAttribute) || initial) {\n\t    [macWindow setHasShadow:\n\t\t    !(newAttributes & kWindowNoShadowAttribute)];\n\t}\n\tif ((changedAttributes & kWindowHideOnSuspendAttribute) || initial) {\n\t    [macWindow setHidesOnDeactivate:\n\t\t    !!(newAttributes & kWindowHideOnSuspendAttribute)];\n\t}\n\tif ((changedAttributes & kWindowInWindowMenuAttribute) || initial) {\n\t    [macWindow setExcludedFromWindowsMenu:\n\t\t    !(newAttributes & kWindowInWindowMenuAttribute)];\n\t}\n\tif ((changedAttributes & kWindowIgnoreClicksAttribute) || initial) {\n\t    [macWindow setIgnoresMouseEvents:\n\t\t    !!(newAttributes & kWindowIgnoreClicksAttribute)];\n\t}\n\tif ((changedAttributes & tkWindowDoesNotHideAttribute) || initial) {\n\t    [macWindow setCanHide:\n\t\t    !(newAttributes & tkWindowDoesNotHideAttribute)];\n\t}\n\tif ((changedAttributes & (kWindowDoesNotCycleAttribute |\n\t\ttkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute)) ||\n\t\tinitial) {\n\t    NSWindowCollectionBehavior b = NSWindowCollectionBehaviorDefault;\n\n\t    /*\n\t     * This behavior, which makes the green button expand a window to\n\t     * full screen, was included in the default as of OSX 10.13.  For\n\t     * uniformity we use the new default in all versions of the OS\n\t     * after 10.10.\n\t     */\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100\n\t    if (!(macWindow.styleMask & NSUtilityWindowMask)) {\n\t\t/*\n\t\t * Exclude overrideredirect, transient, and \"help\"-styled\n\t\t * windows from moving into their own fullscreen space.\n\t\t */\n\n\t\tif ((winPtr->atts.override_redirect) ||\n\t\t\t(wmPtr->container != NULL) ||\n\t\t\t(winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {\n\t\t    b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |\n\t\t\t    NSWindowCollectionBehaviorFullScreenAuxiliary);\n\t\t} else {\n\t\t    b |= NSWindowCollectionBehaviorFullScreenPrimary;\n\n\t\t    /*\n\t\t     * The default max size has height less than the screen\n\t\t     * height. This causes the window manager to refuse to\n\t\t     * allow the window to be resized when it is a split\n\t\t     * window. To work around this we make the max size equal\n\t\t     * to the screen size.  (For 10.11 and up, only)\n\t\t     */\n\n\t\t    if ([NSApp macOSVersion] >= 101100) {\n\t\t\tNSSize screenSize = [[macWindow screen] frame].size;\n\t\t\t[macWindow setMaxFullScreenContentSize:screenSize];\n\t\t    }\n\t\t}\n\t    }\n#endif\n\n\t    if (newAttributes & tkCanJoinAllSpacesAttribute) {\n\t\tb |= NSWindowCollectionBehaviorCanJoinAllSpaces;\n\t    } else if (newAttributes & tkMoveToActiveSpaceAttribute) {\n\t\tb |= NSWindowCollectionBehaviorMoveToActiveSpace;\n\t    }\n\t    if (newAttributes & kWindowDoesNotCycleAttribute) {\n\t\tb |= NSWindowCollectionBehaviorIgnoresCycle;\n\t    } else {\n\t\tb |= NSWindowCollectionBehaviorParticipatesInCycle;\n\t    }\n\t    [macWindow setCollectionBehavior:b];\n\t}\n\tif ((wmPtr->flags & WM_TOPMOST) != (oldFlags & WM_TOPMOST)) {\n\t    [macWindow setLevel:(wmPtr->flags & WM_TOPMOST) ?\n\t\t    kCGUtilityWindowLevel : ([macWindow isKindOfClass:\n\t\t    [TKPanel class]] && [macWindow isFloatingPanel] ?\n\t\t    kCGFloatingWindowLevel : kCGNormalWindowLevel)];\n\t}\n\n\t/*\n\t * The change of window class/attributes might have changed the window\n\t * frame geometry:\n\t */\n\n\tNSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect];\n\n\twmPtr->xInParent = -structureRect.origin.x;\n\twmPtr->yInParent = structureRect.origin.y + structureRect.size.height;\n\twmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;\n\twmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ApplyContainerOverrideChanges --\n *\n *\tThis procedure applies changes to override_redirect or container.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nApplyContainerOverrideChanges(\n    TkWindow *winPtr,\n    NSWindow *macWindow)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    UInt64 oldAttributes = wmPtr->attributes;\n    int oldFlags = wmPtr->flags;\n    unsigned long styleMask;\n    NSRect structureRect;\n    NSWindow *parentWindow;\n\n    if (!macWindow && winPtr->window != None &&\n\t    TkMacOSXHostToplevelExists(winPtr)) {\n\tmacWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);\n    }\n    styleMask = [macWindow styleMask];\n\n    /*\n     * FIX: We need an UpdateWrapper equivalent to make this 100% correct\n     */\n\n    if (winPtr->atts.override_redirect) {\n\tif (wmPtr->macClass == kDocumentWindowClass) {\n\t    wmPtr->macClass = kSimpleWindowClass;\n\t    wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;\n\t}\n\twmPtr->attributes |= kWindowNoActivatesAttribute;\n\tif ([NSApp macOSVersion] == 100600) {\n\t    styleMask = 0;\n\t} else {\n\t    styleMask &= ~NSTitledWindowMask;\n\t}\n    } else {\n\tif (wmPtr->macClass == kSimpleWindowClass &&\n\t    (oldAttributes & kWindowNoActivatesAttribute)) {\n\t    wmPtr->macClass = kDocumentWindowClass;\n\t    wmPtr->attributes =\n\t\t    macClassAttrs[kDocumentWindowClass].defaultAttrs;\n\t}\n\twmPtr->attributes &= ~kWindowNoActivatesAttribute;\n\tif ([NSApp macOSVersion] == 100600) {\n\t    styleMask = NSTitledWindowMask         |\n\t\t\tNSClosableWindowMask       |\n\t\t\tNSMiniaturizableWindowMask |\n\t\t\tNSResizableWindowMask;\n\t} else {\n\t    styleMask |= NSTitledWindowMask;\n\t}\n    }\n    if (macWindow) {\n\tstructureRect = [NSWindow frameRectForContentRect:NSZeroRect\n\t\tstyleMask:styleMask];\n\n\t/*\n\t * Synchronize the wmInfoPtr to match the new window configuration\n\t * so windowBoundsChanged won't corrupt the window manager info.\n\t */\n\n\twmPtr->xInParent = -structureRect.origin.x;\n\twmPtr->yInParent = structureRect.origin.y + structureRect.size.height;\n\twmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;\n\twmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;\n\tif (winPtr->atts.override_redirect) {\n\t    [macWindow setExcludedFromWindowsMenu:YES];\n\t    [macWindow setStyleMask:styleMask];\n\t    if (wmPtr->hints.initial_state == NormalState) {\n\t\t[macWindow orderFront:NSApp];\n\t    }\n\t    if (wmPtr->container != NULL) {\n\t\twmPtr->flags |= WM_TOPMOST;\n\t    } else {\n\t\twmPtr->flags &= ~WM_TOPMOST;\n\t    }\n\t} else {\n\t    const char *title = winPtr->wmInfoPtr->titleUid;\n\n\t    if (!title) {\n\t\ttitle = winPtr->nameUid;\n\t    }\n\t    [macWindow setStyleMask:styleMask];\n\t    [macWindow setTitle:[NSString stringWithUTF8String:title]];\n\t    [macWindow setExcludedFromWindowsMenu:NO];\n\t    wmPtr->flags &= ~WM_TOPMOST;\n\t}\n\tif (wmPtr->container != NULL) {\n\t    TkWindow *containerWinPtr = (TkWindow *)wmPtr->container;\n\n\t    if (containerWinPtr && (containerWinPtr->window != None)\n\t\t    && TkMacOSXHostToplevelExists(containerWinPtr)) {\n\t\tNSWindow *containerMacWin = TkMacOSXGetNSWindowForDrawable(\n\t\t\tcontainerWinPtr->window);\n\n\t\t/*\n\t\t * Try to add the transient window as a child window of the\n\t\t * container. A child NSWindow retains its relative position\n\t\t * with respect to the parent when the parent is moved.  This\n\t\t * is pointless if the parent is offscreen, and adding a child\n\t\t * to an offscreen window causes the parent to be displayed as\n\t\t * a zombie.  So we only do this if the parent is visible.\n\t\t */\n\n\t\tif (containerMacWin && [containerMacWin isVisible]\n\t\t\t&& (winPtr->flags & TK_MAPPED)) {\n\t\t    /*\n\t\t     * If the transient is already a child of some other window,\n\t\t     * remove it.\n\t\t     */\n\n\t\t    parentWindow = [macWindow parentWindow];\n\t\t    if (parentWindow && parentWindow != containerMacWin) {\n\t\t\t[parentWindow removeChildWindow:macWindow];\n\t\t    }\n\t\t    [macWindow orderFront:NSApp];\n\t\t    [containerMacWin addChildWindow:macWindow\n\t\t\t\t\t    ordered:NSWindowAbove];\n\t\t}\n\t    }\n\t} else {\n\t    parentWindow = [macWindow parentWindow];\n\t    if (parentWindow) {\n\t\t[parentWindow removeChildWindow:macWindow];\n\t    }\n\t}\n\tif (wmPtr->flags & WM_TOPMOST) {\n\t    [macWindow setLevel:kCGUtilityWindowLevel];\n\t}\n\tApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,\n\t\toldFlags, 0, 0);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMinSize --\n *\n *\tThis function computes the current minWidth and minHeight values for a\n *\twindow, taking into account the possibility that they may be\n *\tdefaulted.\n *\n * Results:\n *\tThe values at *minWidthPtr and *minHeightPtr are filled in with the\n *\tminimum allowable dimensions of wmPtr's window, in grid units. If the\n *\trequested minimum is smaller than the system required minimum, then\n *\tthis function computes the smallest size that will satisfy both the\n *\tsystem and the grid constraints.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMinSize(\n    TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n    int *minWidthPtr,\t\t/* Where to store the current minimum width of\n\t\t\t\t * the window. */\n    int *minHeightPtr)\t\t/* Where to store the current minimum height\n\t\t\t\t * of the window. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int minWidth = 1, minHeight = 1;\n\n    /*\n     * Compute the minimum width & height by taking the default client size and\n     * rounding it up to the nearest grid unit. Return the greater of the\n     * default minimum and the specified minimum.\n     */\n\n    switch (wmPtr->macClass) {\n    case kDocumentWindowClass:\n    case kMovableAlertWindowClass:\n    case kMovableModalWindowClass:\n\tminWidth = 72;\n\tif (wmPtr->attributes & kWindowResizableAttribute) {\n\t    minHeight = 15;\n\t}\n\tif (wmPtr->attributes & kWindowToolbarButtonAttribute) {\n\t    minWidth += 29;\n\t}\n\tbreak;\n    case kFloatingWindowClass:\n    case kUtilityWindowClass:\n\tminWidth = 59;\n\tif (wmPtr->attributes & kWindowResizableAttribute) {\n\t    minHeight = 11;\n\t}\n\tif (wmPtr->attributes & kWindowSideTitlebarAttribute) {\n\t    int tmp = minWidth;\n\n\t    minWidth = minHeight;\n\t    minHeight = tmp;\n\t} else if (wmPtr->attributes & kWindowToolbarButtonAttribute) {\n\t    minWidth += 29;\n\t}\n\tbreak;\n    default:\n\tif (wmPtr->attributes & kWindowResizableAttribute) {\n\t    minWidth = 15;\n\t    minHeight = 15;\n\t}\n\tbreak;\n    }\n\n    if (wmPtr->gridWin != NULL) {\n\tint base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);\n\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tminWidth = ((minWidth - base) + wmPtr->widthInc-1)/wmPtr->widthInc;\n\tbase = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tminHeight = ((minHeight - base) + wmPtr->heightInc-1)/wmPtr->heightInc;\n    }\n    if (minWidth < wmPtr->minWidth) {\n\tminWidth = wmPtr->minWidth;\n    }\n    if (minHeight < wmPtr->minHeight) {\n\tminHeight = wmPtr->minHeight;\n    }\n    *minWidthPtr = minWidth;\n    *minHeightPtr = minHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMaxSize --\n *\n *\tThis function computes the current maxWidth and maxHeight values for a\n *\twindow, taking into account the possibility that they may be\n *\tdefaulted.\n *\n * Results:\n *\tThe values at *maxWidthPtr and *maxHeightPtr are filled in with the\n *\tmaximum allowable dimensions of wmPtr's window, in grid units. If no\n *\tmaximum has been specified for the window, then this function computes\n *\tthe largest sizes that will fit on the screen.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMaxSize(\n    TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n    int *maxWidthPtr,\t\t/* Where to store the current maximum width of\n\t\t\t\t * the window. */\n    int *maxHeightPtr)\t\t/* Where to store the current maximum height\n\t\t\t\t * of the window. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    NSRect *maxBounds = (NSRect*)(ScreenOfDisplay(winPtr->display, 0)->ext_data);\n\n    if (wmPtr->maxWidth > 0) {\n\t*maxWidthPtr = wmPtr->maxWidth;\n    } else {\n\tint maxWidth = maxBounds->size.width - wmPtr->xInParent;\n\n\tif (wmPtr->gridWin != NULL) {\n\t    maxWidth = wmPtr->reqGridWidth\n\t\t    + (maxWidth - winPtr->reqWidth)/wmPtr->widthInc;\n\t}\n\t*maxWidthPtr = maxWidth;\n    }\n    if (wmPtr->maxHeight > 0) {\n\t*maxHeightPtr = wmPtr->maxHeight;\n    } else {\n\tint maxHeight = maxBounds->size.height - wmPtr->yInParent;\n\n\tif (wmPtr->gridWin != NULL) {\n\t    maxHeight = wmPtr->reqGridHeight\n\t\t    + (maxHeight - winPtr->reqHeight)/wmPtr->heightInc;\n\t}\n\t*maxHeightPtr = maxHeight;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemapWindows\n *\n *\tAdjust parent/child relation ships of the given window hierarchy.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tkeeps windowing system (X11) happy\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemapWindows(\n    TkWindow *winPtr,\n    MacDrawable *parentWin)\n{\n    TkWindow *childPtr;\n\n    /*\n     * Remove the OS specific window. It will get rebuilt when the window gets\n     * Mapped.\n     */\n\n    if (winPtr->window != None) {\n\tMacDrawable *macWin = (MacDrawable *)winPtr->window;\n\n\tmacWin->toplevel->referenceCount--;\n\tmacWin->toplevel = parentWin->toplevel;\n\tmacWin->toplevel->referenceCount++;\n\twinPtr->flags &= ~TK_MAPPED;\n#ifdef TK_REBUILD_TOPLEVEL\n\twinPtr->flags |= TK_REBUILD_TOPLEVEL;\n#endif\n    }\n\n    /*\n     * Repeat for all the children.\n     */\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tRemapWindows(childPtr, (MacDrawable *)winPtr->window);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXWm.h",
    "content": "/*\n * tkMacOSXWm.h --\n *\n *\tDeclarations of Macintosh specific window manager structures.\n *\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKMACWM\n#define _TKMACWM\n\n#include \"tkMacOSXInt.h\"\n#include \"tkMenu.h\"\n\n/*\n * A data structure of the following type holds information for each window\n * manager protocol (such as WM_DELETE_WINDOW) for which a handler (i.e. a Tcl\n * command) has been defined for a particular top-level window.\n */\n\ntypedef struct ProtocolHandler {\n    Atom protocol;\t\t/* Identifies the protocol. */\n    struct ProtocolHandler *nextPtr;\n\t\t\t\t/* Next in list of protocol handlers for the\n\t\t\t\t * same top-level window, or NULL for end of\n\t\t\t\t * list. */\n    Tcl_Interp *interp;\t\t/* Interpreter in which to invoke command. */\n    Tcl_Obj* commandObj;\t\t/* Tcl command to invoke when a client message\n\t\t\t\t * for this protocol arrives. The actual size\n\t\t\t\t * of the structure varies to accommodate the\n\t\t\t\t * needs of the actual command. THIS MUST BE\n\t\t\t\t * THE LAST FIELD OF THE STRUCTURE. */\n} ProtocolHandler;\n\n/* The following data structure is used in the TkWmInfo to maintain a list of all of the\n * transient windows belonging to a given container.\n */\n\ntypedef struct Transient {\n    TkWindow *winPtr;\n    int flags;\n    struct Transient *nextPtr;\n} Transient;\n\n#define WITHDRAWN_BY_CONTAINER 0x1\n\n/*\n * A data structure of the following type holds window-manager-related\n * information for each top-level window in an application.\n */\n\ntypedef struct TkWmInfo {\n    TkWindow *winPtr;\t\t/* Pointer to main Tk information for this\n\t\t\t\t * window. */\n    Window reparent;\t\t/* If the window has been reparented, this\n\t\t\t\t * gives the ID of the ancestor of the window\n\t\t\t\t * that is a child of the root window (may not\n\t\t\t\t * be window's immediate parent). If the window\n\t\t\t\t * isn't reparented, this has the value\n\t\t\t\t * None. */\n    Tk_Uid titleUid;\t\t/* Title to display in window caption. If NULL,\n\t\t\t\t * use name of widget. */\n    char *iconName;\t\t/* Name to display in icon. */\n    Tk_Window container;\t\t/* Container window for TRANSIENT_FOR property,\n\t\t\t\t * or None. */\n    XWMHints hints;\t\t/* Various pieces of information for window\n\t\t\t\t * manager. */\n    char *leaderName;\t\t/* Path name of leader of window group\n\t\t\t\t * (corresponds to hints.window_group).\n\t\t\t\t * Malloc-ed. Note: this field doesn't get\n\t\t\t\t * updated if leader is destroyed. */\n    Tk_Window icon;\t\t/* Window to use as icon for this window, or\n\t\t\t\t * NULL. */\n    Tk_Window iconFor;\t\t/* Window for which this window is icon, or\n\t\t\t\t * NULL if this isn't an icon for anyone. */\n    Transient *transientPtr;    /* First item in a list of all transient windows\n\t\t\t\t * belonging to this window, or NULL if there\n\t\t\t\t * are no transients. */\n\n    /*\n     * Information used to construct an XSizeHints structure for the window\n     * manager:\n     */\n\n    int sizeHintsFlags;\t\t/* Flags word for XSizeHints structure. If the\n\t\t\t\t * PBaseSize flag is set then the window is\n\t\t\t\t * gridded; otherwise it isn't gridded. */\n    int minWidth, minHeight;\t/* Minimum dimensions of window, in grid units,\n\t\t\t\t * not pixels. */\n    int maxWidth, maxHeight;\t/* Maximum dimensions of window, in grid units,\n\t\t\t\t * not pixels. */\n    Tk_Window gridWin;\t\t/* Identifies the window that controls gridding\n\t\t\t\t * for this top-level, or NULL if the top-level\n\t\t\t\t * isn't currently gridded. */\n    int widthInc, heightInc;\t/* Increments for size changes (# pixels per\n\t\t\t\t * step). */\n    struct {\n\tint x;\t\t\t/* numerator */\n\tint y;\t\t\t/* denominator */\n    } minAspect, maxAspect;\t/* Min/max aspect ratios for window. */\n    int reqGridWidth, reqGridHeight;\n\t\t\t\t/* The dimensions of the window (in grid units)\n\t\t\t\t * requested through the geometry manager. */\n    int gravity;\t\t/* Desired window gravity. */\n\n    /*\n     * Information used to manage the size and location of a window.\n     */\n\n    int width, height;\t\t/* Desired dimensions of window, specified in\n\t\t\t\t * grid units. These values are set by the \"wm\n\t\t\t\t * geometry\" command and by ConfigureNotify\n\t\t\t\t * events (for when wm resizes window). -1\n\t\t\t\t * means user hasn't requested dimensions. */\n    int x, y;\t\t\t/* Desired X and Y coordinates for window.\n\t\t\t\t * These values are set by \"wm geometry\", plus\n\t\t\t\t * by ConfigureNotify events (when wm moves\n\t\t\t\t * window). These numbers are different than\n\t\t\t\t * the numbers stored in winPtr->changes\n\t\t\t\t * because (a) they could be measured from the\n\t\t\t\t * right or bottom edge of the screen (see\n\t\t\t\t * WM_NEGATIVE_X and WM_NEGATIVE_Y flags) and\n\t\t\t\t * (b) if the window has been reparented then\n\t\t\t\t * they refer to the parent rather than the\n\t\t\t\t * window itself. */\n    int parentWidth, parentHeight;\n\t\t\t\t/* Width and height of reparent, in pixels\n\t\t\t\t * *including border*. If window hasn't been\n\t\t\t\t * reparented then these will be the outer\n\t\t\t\t * dimensions of the window, including\n\t\t\t\t * border. */\n    int xInParent, yInParent;\t/* Offset of window within reparent, measured\n\t\t\t\t * from upper-left outer corner of parent's\n\t\t\t\t * border to upper-left outer corner of child's\n\t\t\t\t * border. If not reparented then these are\n\t\t\t\t * zero. */\n    int configX, configY;\t/* x,y position of toplevel when window is\n\t\t\t\t * switched into fullscreen state, */\n    int configWidth, configHeight;\n\t\t\t\t/* Dimensions passed to last request that we\n\t\t\t\t * issued to change geometry of window. Used to\n\t\t\t\t * eliminate redundant resize operations. */\n\n    /*\n     * Information about the virtual root window for this top-level, if there\n     * is one.\n     */\n\n    Window vRoot;\t\t/* Virtual root window for this top-level, or\n\t\t\t\t * None if there is no virtual root window\n\t\t\t\t * (i.e. just use the screen's root). */\n    int vRootX, vRootY;\t\t/* Position of the virtual root inside the root\n\t\t\t\t * window. If the WM_VROOT_OFFSET_STALE flag is\n\t\t\t\t * set then this information may be incorrect\n\t\t\t\t * and needs to be refreshed from the OS. If\n\t\t\t\t * vRoot is None then these values are both\n\t\t\t\t * 0. */\n    unsigned int vRootWidth, vRootHeight;\n\t\t\t\t/* Dimensions of the virtual root window. If\n\t\t\t\t * vRoot is None, gives the dimensions of the\n\t\t\t\t * containing screen. This information is never\n\t\t\t\t * stale, even though vRootX and vRootY can\n\t\t\t\t * be. */\n\n    /*\n     * List of children of the toplevel which have private colormaps.\n     */\n\n    TkWindow **cmapList;\t/* Array of window with private colormaps. */\n    Tcl_Size cmapCount;\t\t/* Number of windows in array. */\n\n    /*\n     * Miscellaneous information.\n     */\n\n    ProtocolHandler *protPtr;\t/* First in list of protocol handlers for this\n\t\t\t\t * window (NULL means none). */\n    Tcl_Obj *commandObj;\t/* The command (guaranteed to be a list) for\n\t\t\t\t * the WM_COMMAND property. NULL means nothing\n\t\t\t\t * available. */\n    char *clientMachine;\t/* String to store in WM_CLIENT_MACHINE\n\t\t\t\t * property, or NULL. */\n    int flags;\t\t\t/* Miscellaneous flags, defined below. */\n\n    /*\n     * Macintosh information.\n     */\n\n    WindowClass macClass;\n    UInt64 attributes, configAttributes;\n    TkWindow *scrollWinPtr;\t/* Ptr to scrollbar handling grow widget. */\n    TkMenu *menuPtr;\n    NSWindow *window;\n\n    /*\n     * Space to cache current window state when window becomes Fullscreen.\n     */\n\n    unsigned long cachedStyle;\n    unsigned long cachedPresentation;\n    NSRect cachedBounds;\n\n} WmInfo;\n\n/*\n * Flag values for WmInfo structures:\n *\n * WM_NEVER_MAPPED -\t\tnon-zero means window has never been mapped;\n *\t\t\t\tneed to update all info when window is first\n *\t\t\t\tmapped.\n * WM_UPDATE_PENDING -\t\tnon-zero means a call to UpdateGeometryInfo\n *\t\t\t\thas already been scheduled for this window; no\n *\t\t\t\tneed to schedule another one.\n * WM_NEGATIVE_X -\t\tnon-zero means x-coordinate is measured in\n *\t\t\t\tpixels from right edge of screen, rather than\n *\t\t\t\tfrom left edge.\n * WM_NEGATIVE_Y -\t\tnon-zero means y-coordinate is measured in\n *\t\t\t\tpixels up from bottom of screen, rather than\n *\t\t\t\tdown from top.\n * WM_UPDATE_SIZE_HINTS -\tnon-zero means that new size hints need to be\n *\t\t\t\tpropagated to window manager.\n * WM_SYNC_PENDING -\t\tset to non-zero while waiting for the window\n *\t\t\t\tmanager to respond to some state change.\n * WM_VROOT_OFFSET_STALE -\tnon-zero means that (x,y) offset information\n *\t\t\t\tabout the virtual root window is stale and\n *\t\t\t\tneeds to be fetched fresh from the X server.\n * WM_ABOUT_TO_MAP -\t\tnon-zero means that the window is about to be\n *\t\t\t\tmapped by TkWmMapWindow. This is used by\n *\t\t\t\tUpdateGeometryInfo to modify its behavior.\n * WM_MOVE_PENDING -\t\tnon-zero means the application has requested a\n *\t\t\t\tnew position for the window, but it hasn't\n *\t\t\t\tbeen reflected through the window manager yet.\n * WM_COLORMAPS_EXPLICIT -\tnon-zero means the colormap windows were set\n *\t\t\t\texplicitly via \"wm colormapwindows\".\n * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when \"wm colormapwindows\"\n *\t\t\t\twas called the top-level itself wasn't\n *\t\t\t\tspecified, so we added it implicitly at the\n *\t\t\t\tend of the list.\n * WM_WIDTH_NOT_RESIZABLE -\tnon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the width of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n * WM_HEIGHT_NOT_RESIZABLE -\tnon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the height of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n */\n\n#define WM_NEVER_MAPPED\t\t\t0x0001\n#define WM_UPDATE_PENDING\t\t0x0002\n#define WM_NEGATIVE_X\t\t\t0x0004\n#define WM_NEGATIVE_Y\t\t\t0x0008\n#define WM_UPDATE_SIZE_HINTS\t\t0x0010\n#define WM_SYNC_PENDING\t\t\t0x0020\n#define WM_VROOT_OFFSET_STALE\t\t0x0040\n#define WM_ABOUT_TO_MAP\t\t\t0x0080\n#define WM_MOVE_PENDING\t\t\t0x0100\n#define WM_COLORMAPS_EXPLICIT\t\t0x0200\n#define WM_ADDED_TOPLEVEL_COLORMAP\t0x0400\n#define WM_WIDTH_NOT_RESIZABLE\t\t0x0800\n#define WM_HEIGHT_NOT_RESIZABLE\t\t0x1000\n#define WM_TOPMOST\t\t\t0x2000\n#define WM_FULLSCREEN\t\t\t0x4000\n#define WM_TRANSPARENT\t\t\t0x8000\n\n#endif /* _TKMACWM */\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/tkMacOSXXCursors.h",
    "content": "/*\n * tkMacOSXXCursors.h --\n *\n *\tThis file defines a set of Macintosh cursors that\n *\temulate the X cursor set. All of these cursors were\n *\tconstructed and donated by Grant Neufeld. (gneufeld@ccs.carleton.ca)\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 2008-2009 Apple Inc.\n * Copyright © 2008-2009 Daniel A. Steffen <das@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\nstatic const unsigned char tkMacOSXXCursors[][68] = {\n\n#define TK_MAC_XCURSOR_X_cursor 0\n[TK_MAC_XCURSOR_X_cursor] = {\n\t0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0x7C, 0x3E, 0x3E, 0x7C, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0,\n\t0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3E, 0x7C, 0x7C, 0x3E, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07,\n\t0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0x7C, 0x3E, 0x3E, 0x7C, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0,\n\t0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3E, 0x7C, 0x7C, 0x3E, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_arrow 1\n[TK_MAC_XCURSOR_arrow] = {\n\t0x00, 0x00, 0x00, 0x06, 0x00, 0x1E, 0x00, 0x7C, 0x01, 0xFC, 0x07, 0xF8, 0x00, 0xF8, 0x01, 0xF0,\n\t0x03, 0xB0, 0x07, 0x20, 0x0E, 0x20, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x1F, 0x00, 0x7F, 0x01, 0xFE, 0x07, 0xFE, 0x1F, 0xFC, 0x7F, 0xFC, 0x03, 0xF8,\n\t0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0x70, 0x3E, 0x60, 0x7C, 0x60, 0xF8, 0x40, 0x70, 0x40, 0x20, 0x00,\n\t0x00, 0x01, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_based_arrow_down 2\n[TK_MAC_XCURSOR_based_arrow_down] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x03, 0x00, 0x03, 0x00,\n\t0x03, 0x00, 0x0B, 0x40, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x07, 0x80, 0x07, 0x80,\n\t0x3F, 0xF0, 0x1F, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0B, 0x00, 0x06,\n},\n\n#define TK_MAC_XCURSOR_based_arrow_up 3\n[TK_MAC_XCURSOR_based_arrow_up] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0B, 0x40, 0x03, 0x00,\n\t0x03, 0x00, 0x03, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1F, 0xE0, 0x3F, 0xF0,\n\t0x07, 0x80, 0x07, 0x80, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x04, 0x00, 0x06,\n},\n\n#define TK_MAC_XCURSOR_boat 4\n[TK_MAC_XCURSOR_boat] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xC0, 0x84, 0x60, 0xFF, 0xFF,\n\t0x00, 0x18, 0x00, 0x20, 0x00, 0x40, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xC0, 0x87, 0xE0, 0xFF, 0xFF,\n\t0xFF, 0xF8, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x0F,\n},\n\n#define TK_MAC_XCURSOR_bogosity 5\n[TK_MAC_XCURSOR_bogosity] = {\n\t0x00, 0x00, 0x71, 0x1C, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x7F, 0xFC, 0x51, 0x14, 0x51, 0x14,\n\t0x51, 0x14, 0x51, 0x14, 0x7F, 0xFC, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x71, 0x1C, 0x00, 0x00,\n\t0x00, 0x00, 0x71, 0x1C, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC,\n\t0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x71, 0x1C, 0x00, 0x00,\n\t0x00, 0x01, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_bottom_left_corner 6\n[TK_MAC_XCURSOR_bottom_left_corner] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x20, 0xC8, 0x40, 0xC8, 0x80,\n\t0xC9, 0x00, 0xCA, 0x00, 0xCC, 0x00, 0xCF, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xF0, 0xFF, 0xF0,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x20, 0xC8, 0x40, 0xC8, 0x80,\n\t0xC9, 0x00, 0xCA, 0x00, 0xCC, 0x00, 0xCF, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xF0, 0xFF, 0xF0,\n\t0x00, 0x0F, 0x00, 0x00,\n},\n\n#define TK_MAC_XCURSOR_bottom_right_corner 7\n[TK_MAC_XCURSOR_bottom_right_corner] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x02, 0x13, 0x01, 0x13,\n\t0x00, 0x93, 0x00, 0x53, 0x00, 0x33, 0x03, 0xF3, 0x00, 0x03, 0x00, 0x03, 0x0F, 0xFF, 0x0F, 0xFF,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x02, 0x13, 0x01, 0x13,\n\t0x00, 0x93, 0x00, 0x53, 0x00, 0x33, 0x03, 0xF3, 0x00, 0x03, 0x00, 0x03, 0x0F, 0xFF, 0x0F, 0xFF,\n\t0x00, 0x0F, 0x00, 0x0F,\n},\n\n#define TK_MAC_XCURSOR_bottom_side 8\n[TK_MAC_XCURSOR_bottom_side] = {\n\t0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10,\n\t0x09, 0x20, 0x05, 0x40, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10,\n\t0x09, 0x20, 0x05, 0x40, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00,\n\t0x00, 0x0B, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_bottom_tee 9\n[TK_MAC_XCURSOR_bottom_tee] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,\n\t0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,\n\t0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0B, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_box_spiral 10\n[TK_MAC_XCURSOR_box_spiral] = {\n\t0xFF, 0xFE, 0x80, 0x00, 0xBF, 0xFE, 0xA0, 0x02, 0xAF, 0xFA, 0xA8, 0x0A, 0xAB, 0xEA, 0xAA, 0x2A,\n\t0xAA, 0xAA, 0xAB, 0xAA, 0xA8, 0x2A, 0xAF, 0xEA, 0xA0, 0x0A, 0xBF, 0xFA, 0x80, 0x02, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0x80, 0x00, 0xBF, 0xFE, 0xA0, 0x02, 0xAF, 0xFA, 0xA8, 0x0A, 0xAB, 0xEA, 0xAA, 0x2A,\n\t0xAA, 0xAA, 0xAB, 0xAA, 0xA8, 0x2A, 0xAF, 0xEA, 0xA0, 0x0A, 0xBF, 0xFA, 0x80, 0x02, 0xFF, 0xFE,\n\t0x00, 0x08, 0x00, 0x08,\n},\n\n#define TK_MAC_XCURSOR_center_ptr 11\n[TK_MAC_XCURSOR_center_ptr] = {\n\t0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0,\n\t0x1F, 0xE0, 0x33, 0x30, 0x23, 0x10, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,\n\t0x03, 0x00, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0, 0x1F, 0xE0, 0x3F, 0xF0,\n\t0x3F, 0xF0, 0x7F, 0xF8, 0x77, 0xB8, 0x67, 0x98, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80,\n\t0x00, 0x01, 0x00, 0x06,\n},\n\n#define TK_MAC_XCURSOR_circle 12\n[TK_MAC_XCURSOR_circle] = {\n\t0x00, 0x00, 0x03, 0xC0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3C, 0x3C, 0x38, 0x1C, 0x70, 0x0E, 0x70, 0x0E,\n\t0x70, 0x0E, 0x70, 0x0E, 0x38, 0x1C, 0x3C, 0x3C, 0x1F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0, 0x00, 0x00,\n\t0x03, 0xC0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0x7C, 0x3E, 0xF8, 0x1F, 0xF8, 0x1F,\n\t0xF8, 0x1F, 0xF8, 0x1F, 0x7C, 0x3E, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_clock 13\n[TK_MAC_XCURSOR_clock] = {\n\t0x1F, 0xF8, 0x33, 0xCC, 0x64, 0x66, 0x49, 0x92, 0x4F, 0x12, 0x44, 0x22, 0x63, 0xC6, 0x3F, 0xFC,\n\t0x29, 0x94, 0x29, 0x94, 0x29, 0x94, 0x2B, 0xD4, 0x69, 0x96, 0x78, 0x1E, 0x7F, 0xFE, 0x7F, 0xFE,\n\t0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x3F, 0xFC,\n\t0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,\n\t0x00, 0x04, 0x00, 0x08,\n},\n\n#define TK_MAC_XCURSOR_coffee_mug 14\n[TK_MAC_XCURSOR_coffee_mug] = {\n\t0x03, 0xF8, 0x0C, 0x06, 0x10, 0x01, 0x1C, 0x07, 0x33, 0xF9, 0x70, 0x01, 0xD0, 0x01, 0x90, 0x01,\n\t0x96, 0x0D, 0xDA, 0x55, 0x7A, 0x55, 0x36, 0xED, 0x10, 0xA1, 0x10, 0x01, 0x08, 0x02, 0x07, 0xFC,\n\t0x03, 0xF8, 0x0F, 0xFE, 0x1F, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF, 0x1F, 0xFF, 0x0F, 0xFE, 0x07, 0xFC,\n\t0x00, 0x04, 0x00, 0x03,\n},\n\n#define TK_MAC_XCURSOR_cross 15\n[TK_MAC_XCURSOR_cross] = {\n\t0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0xFE, 0xFE, 0x00, 0x00,\n\t0xFE, 0xFE, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x00, 0x00,\n\t0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_cross_reverse 16\n[TK_MAC_XCURSOR_cross_reverse] = {\n\t0x42, 0x84, 0xA2, 0x8A, 0x52, 0x94, 0x2A, 0xA8, 0x16, 0xD0, 0x0A, 0xA0, 0xFD, 0x7E, 0x02, 0x80,\n\t0xFD, 0x7E, 0x0A, 0xA0, 0x16, 0xD0, 0x2A, 0xA8, 0x52, 0x94, 0xA2, 0x8A, 0x42, 0x84, 0x00, 0x00,\n\t0x43, 0x84, 0xE3, 0x8E, 0x73, 0x9C, 0x3B, 0xB8, 0x1F, 0xF0, 0x0F, 0xE0, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0x0F, 0xE0, 0x1F, 0xF0, 0x3B, 0xB8, 0x73, 0x9C, 0xE3, 0x8E, 0x43, 0x84, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_crosshair 17\n[TK_MAC_XCURSOR_crosshair] = {\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFE, 0xFE,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFE, 0xFE,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_diamond_cross 18\n[TK_MAC_XCURSOR_diamond_cross] = {\n\t0x02, 0x80, 0x06, 0xC0, 0x0A, 0xA0, 0x12, 0x90, 0x22, 0x88, 0x42, 0x84, 0xFE, 0xFE, 0x00, 0x00,\n\t0xFE, 0xFE, 0x42, 0x84, 0x22, 0x88, 0x12, 0x90, 0x0A, 0xA0, 0x06, 0xC0, 0x02, 0x80, 0x00, 0x00,\n\t0x02, 0x80, 0x06, 0xC0, 0x0E, 0xE0, 0x1E, 0xF0, 0x3E, 0xF8, 0x7E, 0xFC, 0xFE, 0xFE, 0x00, 0x00,\n\t0xFE, 0xFE, 0x7E, 0xFC, 0x3E, 0xF8, 0x1E, 0xF0, 0x0E, 0xE0, 0x06, 0xC0, 0x02, 0x80, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_dot 19\n[TK_MAC_XCURSOR_dot] = {\n\t0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x1F, 0xE0, 0x1F, 0xE0, 0x3F, 0xF0, 0x3F, 0xF0, 0x3F, 0xF0,\n\t0x3F, 0xF0, 0x1F, 0xE0, 0x1F, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x07, 0x80, 0x1F, 0xE0, 0x3F, 0xF0, 0x3F, 0xF0, 0x7F, 0xF8, 0x7F, 0xF8, 0x7F, 0xF8,\n\t0x7F, 0xF8, 0x3F, 0xF0, 0x3F, 0xF0, 0x1F, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x06, 0x00, 0x06,\n},\n\n#define TK_MAC_XCURSOR_dotbox 20\n[TK_MAC_XCURSOR_dotbox] = {\n\t0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x21, 0x84,\n\t0x21, 0x84, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x31, 0x8C, 0x33, 0xCC,\n\t0x33, 0xCC, 0x31, 0x8C, 0x30, 0x0C, 0x30, 0x0C, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_double_arrow 21\n[TK_MAC_XCURSOR_double_arrow] = {\n\t0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0D, 0xB0, 0x19, 0x98, 0x01, 0x80, 0x01, 0x80,\n\t0x01, 0x80, 0x01, 0x80, 0x19, 0x98, 0x0D, 0xB0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00,\n\t0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3B, 0xDC, 0x03, 0xC0,\n\t0x03, 0xC0, 0x3B, 0xDC, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_draft_large 22\n[TK_MAC_XCURSOR_draft_large] = {\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF8, 0x03, 0xF8, 0x0F, 0xF0, 0x00, 0xF0,\n\t0x01, 0x60, 0x02, 0x60, 0x04, 0x40, 0x08, 0x40, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00,\n\t0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xFE, 0x03, 0xFC, 0x0F, 0xFC, 0x3F, 0xF8, 0xFF, 0xF8,\n\t0x03, 0xF0, 0x07, 0xF0, 0x0E, 0xE0, 0x1C, 0xE0, 0x38, 0xC0, 0x70, 0xC0, 0xE0, 0x80, 0x40, 0x80,\n\t0x00, 0x01, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_draft_small 23\n[TK_MAC_XCURSOR_draft_small] = {\n\t0x00, 0x00, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF8, 0x03, 0xF8, 0x00, 0x70, 0x00, 0xB0,\n\t0x01, 0x20, 0x02, 0x20, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00,\n\t0x00, 0x03, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xFE, 0x03, 0xFC, 0x0F, 0xFC, 0x3F, 0xF8, 0x01, 0xF8,\n\t0x03, 0xF0, 0x07, 0x70, 0x0E, 0x60, 0x1C, 0x60, 0x38, 0x40, 0x70, 0x40, 0xE0, 0x00, 0x40, 0x00,\n\t0x00, 0x01, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_draped_box 24\n[TK_MAC_XCURSOR_draped_box] = {\n\t0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x22, 0x44, 0x26, 0x64, 0x2C, 0x34, 0x38, 0x1C, 0x21, 0x84,\n\t0x21, 0x84, 0x38, 0x1C, 0x2C, 0x34, 0x26, 0x64, 0x22, 0x44, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3E, 0x7C, 0x3E, 0x7C, 0x3C, 0x3C, 0x39, 0x9C, 0x23, 0xC4,\n\t0x23, 0xC4, 0x39, 0x9C, 0x3C, 0x3C, 0x3E, 0x7C, 0x3E, 0x7C, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_exchange 25\n[TK_MAC_XCURSOR_exchange] = {\n\t0x00, 0x00, 0x47, 0xC0, 0x6F, 0xE0, 0x7C, 0x30, 0x48, 0x10, 0x4C, 0x00, 0x7E, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0xFC, 0x00, 0x64, 0x10, 0x24, 0x18, 0x7C, 0x0F, 0xEC, 0x07, 0xC4, 0x00, 0x00,\n\t0xC7, 0xC0, 0xEF, 0xE0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFC, 0x38, 0xFE, 0x10, 0xFF, 0x00, 0xFF, 0x80,\n\t0x03, 0xFE, 0x01, 0xFE, 0x10, 0xFE, 0x38, 0x7E, 0x3F, 0xFE, 0x1F, 0xFE, 0x0F, 0xEE, 0x07, 0xC6,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_fleur 26\n[TK_MAC_XCURSOR_fleur] = {\n\t0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x01, 0x80, 0x11, 0x88, 0x31, 0x8C, 0x7F, 0xFE,\n\t0x7F, 0xFE, 0x31, 0x8C, 0x11, 0x88, 0x01, 0x80, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00,\n\t0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x17, 0xE8, 0x3B, 0xDC, 0x7F, 0xFE, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0x7F, 0xFE, 0x3B, 0xDC, 0x17, 0xE8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_gobbler 27\n[TK_MAC_XCURSOR_gobbler] = {\n\t0x00, 0x00, 0x00, 0x78, 0x00, 0x70, 0x40, 0x36, 0x4F, 0xB0, 0x7F, 0xF0, 0x7E, 0x30, 0x7C, 0x30,\n\t0x30, 0x38, 0x00, 0xF0, 0x0F, 0xE0, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,\n\t0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8,\n\t0xFF, 0xFC, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F, 0xF0, 0x0E, 0x00, 0x1F, 0x80, 0x1F, 0x80, 0x1F, 0x80,\n\t0x00, 0x03, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_gumby 28\n[TK_MAC_XCURSOR_gumby] = {\n\t0x3F, 0x00, 0x10, 0xC0, 0xC8, 0x20, 0xEA, 0xA0, 0xC8, 0x20, 0xCB, 0xA0, 0xF8, 0x38, 0x38, 0x3E,\n\t0x08, 0x26, 0x08, 0x26, 0x09, 0x2E, 0x09, 0x26, 0x09, 0x20, 0x11, 0x10, 0x21, 0x08, 0x3E, 0xF8,\n\t0x3F, 0x00, 0x1F, 0xC0, 0xCF, 0xE0, 0xEF, 0xE0, 0xCF, 0xE0, 0xCF, 0xE0, 0xFF, 0xF8, 0x3F, 0xFE,\n\t0x0F, 0xE6, 0x0F, 0xE6, 0x0F, 0xEE, 0x0F, 0xE6, 0x0F, 0xE0, 0x1F, 0xF0, 0x3F, 0xF8, 0x3E, 0xF8,\n\t0x00, 0x00, 0x00, 0x02,\n},\n\n#define TK_MAC_XCURSOR_hand1 29\n[TK_MAC_XCURSOR_hand1] = {\n\t0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x2F, 0xE0,\n\t0x7F, 0xF0, 0x5F, 0xF0, 0x07, 0xE0, 0x07, 0xC0, 0x4A, 0x00, 0x62, 0x00, 0x34, 0x00, 0x18, 0x00,\n\t0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x2F, 0xE0,\n\t0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0xE0, 0x7F, 0xC0, 0x7E, 0x00, 0x7E, 0x00, 0x3C, 0x00, 0x18, 0x00,\n\t0x00, 0x00, 0x00, 0x0D,\n},\n\n#define TK_MAC_XCURSOR_hand2 30\n[TK_MAC_XCURSOR_hand2] = {\n\t0x00, 0x00, 0x3F, 0xC0, 0x40, 0x20, 0x3F, 0x10, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x07, 0x14,\n\t0x08, 0x22, 0x06, 0x41, 0x01, 0x82, 0x01, 0x24, 0x00, 0x88, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00,\n\t0x00, 0x00, 0x3F, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x0F, 0xF8, 0x07, 0xF8, 0x0F, 0xF8, 0x07, 0xFC,\n\t0x0F, 0xFE, 0x07, 0xFF, 0x01, 0xFE, 0x01, 0xFC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00,\n\t0x00, 0x02, 0x00, 0x01,\n},\n\n#define TK_MAC_XCURSOR_heart 31\n[TK_MAC_XCURSOR_heart] = {\n\t0x00, 0x00, 0x3E, 0xF8, 0x63, 0x8C, 0xC1, 0x06, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02,\n\t0xC0, 0x06, 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x0C, 0x60, 0x06, 0xC0, 0x03, 0x80, 0x00, 0x00,\n\t0x00, 0x00, 0x3E, 0xF8, 0x7F, 0xFC, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00,\n\t0x00, 0x03, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_icon 32\n[TK_MAC_XCURSOR_icon] = {\n\t0xFF, 0xFF, 0xD5, 0x55, 0xAA, 0xAB, 0xD5, 0x55, 0xA0, 0x0B, 0xD0, 0x05, 0xA0, 0x0B, 0xD0, 0x05,\n\t0xA0, 0x0B, 0xD0, 0x05, 0xA0, 0x0B, 0xD0, 0x05, 0xAA, 0xAB, 0xD5, 0x55, 0xAA, 0xAB, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,\n\t0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_iron_cross 33\n[TK_MAC_XCURSOR_iron_cross] = {\n\t0x00, 0x00, 0x3F, 0xFC, 0x1F, 0xF8, 0x4F, 0xF2, 0x67, 0xE6, 0x73, 0xCE, 0x79, 0x9E, 0x7F, 0xFE,\n\t0x7F, 0xFE, 0x79, 0x9E, 0x73, 0xCE, 0x67, 0xE6, 0x4F, 0xF2, 0x1F, 0xF8, 0x3F, 0xFC, 0x00, 0x00,\n\t0x7F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE,\n\t0x00, 0x07, 0x00, 0x06,\n},\n\n#define TK_MAC_XCURSOR_left_ptr 34\n[TK_MAC_XCURSOR_left_ptr] = {\n\t0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x0F, 0xC0, 0x0F, 0xE0,\n\t0x0F, 0xF0, 0x0F, 0x80, 0x0D, 0x80, 0x08, 0xC0, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00,\n\t0x18, 0x00, 0x1C, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x1F, 0x80, 0x1F, 0xC0, 0x1F, 0xE0, 0x1F, 0xF0,\n\t0x1F, 0xF8, 0x1F, 0xFC, 0x1F, 0xC0, 0x1D, 0xE0, 0x19, 0xE0, 0x10, 0xF0, 0x00, 0xF0, 0x00, 0x70,\n\t0x00, 0x01, 0x00, 0x04,\n},\n\n#define TK_MAC_XCURSOR_left_side 35\n[TK_MAC_XCURSOR_left_side] = {\n\t0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x80, 0x61, 0x00, 0x62, 0x00, 0x64, 0x00, 0x6F, 0xFC,\n\t0x64, 0x00, 0x62, 0x00, 0x61, 0x00, 0x60, 0x80, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x80, 0x61, 0x00, 0x62, 0x00, 0x64, 0x00, 0x6F, 0xFC,\n\t0x64, 0x00, 0x62, 0x00, 0x61, 0x00, 0x60, 0x80, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x04,\n},\n\n#define TK_MAC_XCURSOR_left_tee 36\n[TK_MAC_XCURSOR_left_tee] = {\n\t0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8,\n\t0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8,\n\t0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x04,\n},\n\n#define TK_MAC_XCURSOR_leftbutton 37\n[TK_MAC_XCURSOR_leftbutton] = {\n\t0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x45, 0x54, 0x45, 0x54, 0x45, 0x54, 0x45, 0x54,\n\t0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0x00, 0x04, 0x00, 0x03,\n},\n\n#define TK_MAC_XCURSOR_ll_angle 38\n[TK_MAC_XCURSOR_ll_angle] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,\n\t0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,\n\t0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0B, 0x00, 0x04,\n},\n\n#define TK_MAC_XCURSOR_lr_angle 39\n[TK_MAC_XCURSOR_lr_angle] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,\n\t0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,\n\t0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x0B, 0x00, 0x0B,\n},\n\n#define TK_MAC_XCURSOR_man 40\n[TK_MAC_XCURSOR_man] = {\n\t0x03, 0x80, 0x1E, 0xF0, 0x02, 0x80, 0x81, 0x00, 0x43, 0x87, 0x24, 0x4B, 0x1D, 0x70, 0x05, 0x40,\n\t0x04, 0x40, 0x02, 0x80, 0x04, 0x40, 0x09, 0x20, 0x12, 0x90, 0x14, 0x50, 0x78, 0x3C, 0xF8, 0x3F,\n\t0x03, 0x80, 0x1F, 0xF0, 0x03, 0x80, 0x81, 0x00, 0x43, 0x87, 0x27, 0xCB, 0x1F, 0xF0, 0x07, 0xC0,\n\t0x07, 0xC0, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1E, 0xF0, 0x1C, 0x70, 0x78, 0x3C, 0xF8, 0x3F,\n\t0x00, 0x01, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_middlebutton 41\n[TK_MAC_XCURSOR_middlebutton] = {\n\t0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,\n\t0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0x00, 0x04, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_mouse 42\n[TK_MAC_XCURSOR_mouse] = {\n\t0x06, 0x00, 0x01, 0x00, 0x01, 0x80, 0x0F, 0xF0, 0x10, 0x08, 0x17, 0xE8, 0x14, 0x28, 0x14, 0x28,\n\t0x17, 0xE8, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x0F, 0xF0,\n\t0x06, 0x00, 0x01, 0x00, 0x01, 0x80, 0x0F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,\n\t0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x0F, 0xF0,\n\t0x00, 0x00, 0x00, 0x00,\n},\n\n#define TK_MAC_XCURSOR_pencil 43\n[TK_MAC_XCURSOR_pencil] = {\n\t0x00, 0x00, 0x00, 0xF0, 0x00, 0x88, 0x01, 0x08, 0x01, 0x90, 0x02, 0x70, 0x02, 0x20, 0x04, 0x40,\n\t0x04, 0x40, 0x08, 0x80, 0x08, 0x80, 0x11, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00,\n\t0x00, 0x00, 0x00, 0xF0, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0xF0, 0x03, 0xF0, 0x03, 0xE0, 0x07, 0xC0,\n\t0x07, 0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x1F, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00,\n\t0x00, 0x0F, 0x00, 0x03,\n},\n\n#define TK_MAC_XCURSOR_pirate 44\n[TK_MAC_XCURSOR_pirate] = {\n\t0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x19, 0x98, 0x19, 0x98, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0,\n\t0x43, 0xC2, 0x43, 0xC3, 0x21, 0x84, 0x1C, 0x38, 0x03, 0xC0, 0x0F, 0xF1, 0x78, 0x1F, 0x40, 0x02,\n\t0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xF0, 0x47, 0xE2,\n\t0xE7, 0xE7, 0xE7, 0xE7, 0x7F, 0xFF, 0x3F, 0xFC, 0x1F, 0xF9, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F,\n\t0x00, 0x0A, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_plus 45\n[TK_MAC_XCURSOR_plus] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8,\n\t0x1F, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8,\n\t0x1F, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_question_arrow 46\n[TK_MAC_XCURSOR_question_arrow] = {\n\t0x07, 0xC0, 0x0F, 0xE0, 0x1C, 0x70, 0x18, 0x30, 0x1C, 0x30, 0x0C, 0x70, 0x00, 0xE0, 0x03, 0xC0,\n\t0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0E, 0xE0, 0x06, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,\n\t0x07, 0xC0, 0x0F, 0xE0, 0x1C, 0x70, 0x18, 0x30, 0x1C, 0x30, 0x0C, 0x70, 0x00, 0xE0, 0x03, 0xC0,\n\t0x03, 0x80, 0x02, 0x80, 0x3F, 0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,\n\t0x00, 0x0E, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_right_ptr 47\n[TK_MAC_XCURSOR_right_ptr] = {\n\t0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xF0, 0x01, 0xF0, 0x03, 0xF0, 0x07, 0xF0,\n\t0x0F, 0xF0, 0x01, 0xF0, 0x01, 0xB0, 0x03, 0x10, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xF8, 0x07, 0xF8, 0x0F, 0xF8,\n\t0x1F, 0xF8, 0x3F, 0xF8, 0x03, 0xF8, 0x07, 0xB8, 0x07, 0x98, 0x0F, 0x08, 0x0F, 0x00, 0x0E, 0x00,\n\t0x00, 0x01, 0x00, 0x0B,\n},\n\n#define TK_MAC_XCURSOR_right_side 48\n[TK_MAC_XCURSOR_right_side] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x01, 0x06, 0x00, 0x86, 0x00, 0x46, 0x00, 0x26,\n\t0x3F, 0xF6, 0x00, 0x26, 0x00, 0x46, 0x00, 0x86, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x01, 0x06, 0x00, 0x86, 0x00, 0x46, 0x00, 0x26,\n\t0x3F, 0xF6, 0x00, 0x26, 0x00, 0x46, 0x00, 0x86, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,\n\t0x00, 0x08, 0x00, 0x0B,\n},\n\n#define TK_MAC_XCURSOR_right_tee 49\n[TK_MAC_XCURSOR_right_tee] = {\n\t0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0,\n\t0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x1F, 0xF0,\n\t0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x0A,\n},\n\n#define TK_MAC_XCURSOR_rightbutton 50\n[TK_MAC_XCURSOR_rightbutton] = {\n\t0x80, 0x02, 0x7F, 0xFC, 0x7F, 0xFC, 0x44, 0x44, 0x55, 0x44, 0x55, 0x44, 0x55, 0x44, 0x55, 0x44,\n\t0x44, 0x44, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x7F, 0xFC, 0x80, 0x02,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,\n\t0x00, 0x04, 0x00, 0x03,\n},\n\n#define TK_MAC_XCURSOR_rtl_logo 51\n[TK_MAC_XCURSOR_rtl_logo] = {\n\t0x00, 0x00, 0x7F, 0xFE, 0x40, 0x22, 0x40, 0x22, 0x40, 0x22, 0x7F, 0xE2, 0x44, 0x22, 0x44, 0x22,\n\t0x44, 0x22, 0x44, 0x22, 0x47, 0xFE, 0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x7F, 0xFE, 0x00, 0x00,\n\t0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x60, 0x76, 0x7F, 0xF6, 0x7F, 0xF6, 0x7C, 0x36, 0x6C, 0x36,\n\t0x6C, 0x36, 0x6C, 0x3E, 0x6F, 0xFE, 0x6F, 0xFE, 0x6E, 0x06, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_sailboat 52\n[TK_MAC_XCURSOR_sailboat] = {\n\t0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0x60, 0x01, 0x60, 0x03, 0x60, 0x03, 0x70, 0x07, 0x70,\n\t0x07, 0x70, 0x0F, 0x78, 0x0F, 0x78, 0x1F, 0x78, 0x1F, 0x7C, 0x3E, 0x38, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x40, 0x00, 0xE0, 0x01, 0xE0, 0x03, 0xF0, 0x03, 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x0F, 0xF8,\n\t0x0F, 0xF8, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFE, 0x7F, 0x7C, 0x7E, 0x38, 0x00, 0x00,\n\t0x00, 0x0C, 0x00, 0x08,\n},\n\n#define TK_MAC_XCURSOR_sb_down_arrow 53\n[TK_MAC_XCURSOR_sb_down_arrow] = {\n\t0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80,\n\t0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,\n\t0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,\n\t0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,\n\t0x00, 0x0E, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_sb_h_double_arrow 54\n[TK_MAC_XCURSOR_sb_h_double_arrow] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x3F, 0xFC, 0x78, 0x1E,\n\t0x3F, 0xFC, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x38, 0x1C, 0x7F, 0xFE, 0xFF, 0xFF,\n\t0x7F, 0xFE, 0x38, 0x1C, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_sb_left_arrow 55\n[TK_MAC_XCURSOR_sb_left_arrow] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x3F, 0xFF, 0x78, 0x00,\n\t0x3F, 0xFF, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,\n\t0x7F, 0xFF, 0x38, 0x00, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x01,\n},\n\n#define TK_MAC_XCURSOR_sb_right_arrow 56\n[TK_MAC_XCURSOR_sb_right_arrow] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0xFF, 0xFC,\n\t0x00, 0x1E, 0xFF, 0xFC, 0x00, 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x1C, 0xFF, 0xFE,\n\t0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x08, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_sb_up_arrow 57\n[TK_MAC_XCURSOR_sb_up_arrow] = {\n\t0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,\n\t0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,\n\t0x00, 0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0,\n\t0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0,\n\t0x00, 0x01, 0x00, 0x08,\n},\n\n#define TK_MAC_XCURSOR_sb_v_double_arrow 58\n[TK_MAC_XCURSOR_sb_v_double_arrow] = {\n\t0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80,\n\t0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00,\n\t0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1F, 0xF0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,\n\t0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_shuttle 59\n[TK_MAC_XCURSOR_shuttle] = {\n\t0x00, 0x20, 0x00, 0x70, 0x00, 0xF8, 0x01, 0xDE, 0x05, 0xDE, 0x09, 0xDE, 0x11, 0xDE, 0x11, 0xDE,\n\t0x11, 0xDE, 0x11, 0xDE, 0x31, 0xDE, 0x71, 0xDE, 0xFD, 0xDE, 0x18, 0x88, 0x00, 0x78, 0x00, 0x30,\n\t0x00, 0x20, 0x00, 0x70, 0x00, 0xF8, 0x01, 0xFE, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE,\n\t0x1F, 0xFE, 0x1F, 0xFE, 0x3F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFE, 0x18, 0xF8, 0x00, 0x78, 0x00, 0x30,\n\t0x00, 0x00, 0x00, 0x0A,\n},\n\n#define TK_MAC_XCURSOR_sizing 60\n[TK_MAC_XCURSOR_sizing] = {\n\t0x00, 0x00, 0x7F, 0x80, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x47, 0xE0, 0x44, 0x20, 0x44, 0x22,\n\t0x44, 0x22, 0x04, 0x22, 0x07, 0xE2, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x06, 0x01, 0xFE, 0x00, 0x00,\n\t0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xE0, 0x00, 0xEF, 0xF0, 0xEF, 0xF0, 0xEC, 0x37, 0xEC, 0x37,\n\t0xEC, 0x37, 0xEC, 0x37, 0x0F, 0xF7, 0x0F, 0xFF, 0x00, 0x1F, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF,\n\t0x00, 0x0E, 0x00, 0x0E,\n},\n\n#define TK_MAC_XCURSOR_spider 61\n[TK_MAC_XCURSOR_spider] = {\n\t0x20, 0x10, 0x10, 0x20, 0x10, 0x20, 0x08, 0x40, 0x08, 0x40, 0x87, 0x87, 0x67, 0x98, 0x1F, 0xE0,\n\t0x1F, 0xE0, 0x67, 0x98, 0x87, 0x87, 0x08, 0x40, 0x08, 0x40, 0x10, 0x20, 0x10, 0x20, 0x20, 0x10,\n\t0x70, 0x38, 0x38, 0x70, 0x38, 0x70, 0x1C, 0xE0, 0x9F, 0xE7, 0xEF, 0xDF, 0xFF, 0xFF, 0x7F, 0xF8,\n\t0x7F, 0xF8, 0xFF, 0xFF, 0xEF, 0xDF, 0x9F, 0xE7, 0x1C, 0xE0, 0x38, 0x70, 0x38, 0x70, 0x70, 0x38,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_spraycan 62\n[TK_MAC_XCURSOR_spraycan] = {\n\t0x00, 0x18, 0x00, 0x40, 0x0D, 0x18, 0x1E, 0x40, 0x1A, 0x18, 0x3F, 0x00, 0x21, 0x00, 0x39, 0x00,\n\t0x29, 0x00, 0x39, 0x00, 0x29, 0x00, 0x39, 0x00, 0x39, 0x00, 0x21, 0x00, 0x21, 0x00, 0x3F, 0x00,\n\t0x00, 0x18, 0x00, 0x40, 0x0D, 0x18, 0x1E, 0x40, 0x1E, 0x18, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00,\n\t0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00,\n\t0x00, 0x02, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_star 63\n[TK_MAC_XCURSOR_star] = {\n\t0x01, 0x00, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x39, 0x38,\n\t0xC0, 0x06, 0x38, 0x38, 0x09, 0x20, 0x12, 0x90, 0x24, 0x48, 0x28, 0x28, 0x30, 0x18, 0x20, 0x08,\n\t0x01, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0xC0, 0x07, 0xC0, 0x07, 0xC0, 0x3F, 0xF8,\n\t0xFF, 0xFE, 0x3F, 0xF8, 0x0F, 0xE0, 0x1E, 0xF0, 0x3C, 0x78, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_target 64\n[TK_MAC_XCURSOR_target] = {\n\t0x00, 0x00, 0x03, 0x80, 0x0F, 0xE0, 0x1C, 0x70, 0x30, 0x18, 0x60, 0x0C, 0xC1, 0x06, 0xC2, 0x86,\n\t0xC1, 0x06, 0x60, 0x0C, 0x30, 0x18, 0x1C, 0x70, 0x0F, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x03, 0x80, 0x0F, 0xE0, 0x1F, 0xF0, 0x3C, 0x78, 0x70, 0x1C, 0xE3, 0x8E, 0xE3, 0x8E,\n\t0xE3, 0x8E, 0x70, 0x1C, 0x3C, 0x78, 0x1F, 0xF0, 0x0F, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_tcross 65\n[TK_MAC_XCURSOR_tcross] = {\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFE,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFE,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,\n\t0x00, 0x07, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_top_left_arrow 66\n[TK_MAC_XCURSOR_top_left_arrow] = {\n\t0x00, 0x00, 0x60, 0x00, 0x78, 0x00, 0x3E, 0x00, 0x3F, 0x80, 0x1F, 0xE0, 0x1E, 0x00, 0x0D, 0x00,\n\t0x0C, 0x80, 0x04, 0x40, 0x04, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,\n\t0xE0, 0x00, 0xF8, 0x00, 0xFE, 0x00, 0x7F, 0x80, 0x7F, 0xE0, 0x3F, 0xF8, 0x3F, 0xFE, 0x1F, 0x80,\n\t0x1F, 0xC0, 0x0E, 0xE0, 0x0E, 0x70, 0x06, 0x38, 0x06, 0x1C, 0x02, 0x0E, 0x02, 0x04, 0x00, 0x00,\n\t0x00, 0x01, 0x00, 0x01,\n},\n\n#define TK_MAC_XCURSOR_top_left_corner 67\n[TK_MAC_XCURSOR_top_left_corner] = {\n\t0xFF, 0xF0, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00, 0xCF, 0xC0, 0xCC, 0x00, 0xCA, 0x00, 0xC9, 0x00,\n\t0xC8, 0x80, 0xC8, 0x40, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0xFF, 0xF0, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00, 0xCF, 0xC0, 0xCC, 0x00, 0xCA, 0x00, 0xC9, 0x00,\n\t0xC8, 0x80, 0xC8, 0x40, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00,\n},\n\n#define TK_MAC_XCURSOR_top_right_corner 68\n[TK_MAC_XCURSOR_top_right_corner] = {\n\t0x0F, 0xFF, 0x0F, 0xFF, 0x00, 0x03, 0x00, 0x03, 0x03, 0xF3, 0x00, 0x33, 0x00, 0x53, 0x00, 0x93,\n\t0x01, 0x13, 0x02, 0x13, 0x04, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x0F, 0xFF, 0x0F, 0xFF, 0x00, 0x03, 0x00, 0x03, 0x03, 0xF3, 0x00, 0x33, 0x00, 0x53, 0x00, 0x93,\n\t0x01, 0x13, 0x02, 0x13, 0x04, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x0F,\n},\n\n#define TK_MAC_XCURSOR_top_side 69\n[TK_MAC_XCURSOR_top_side] = {\n\t0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x05, 0x40, 0x09, 0x20,\n\t0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x7F, 0xFC, 0x7F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x05, 0x40, 0x09, 0x20,\n\t0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x04, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_top_tee 70\n[TK_MAC_XCURSOR_top_tee] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80,\n\t0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80,\n\t0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x04, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_trek 71\n[TK_MAC_XCURSOR_trek] = {\n\t0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x0E, 0xE0, 0x0F, 0xE0, 0x07, 0xC0,\n\t0x03, 0x80, 0x01, 0x00, 0x0B, 0xA0, 0x0D, 0x60, 0x09, 0x20, 0x08, 0x20, 0x08, 0x20, 0x00, 0x00,\n\t0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF0, 0x0F, 0xE0,\n\t0x07, 0xC0, 0x0B, 0xA0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF0, 0x1D, 0x70, 0x1C, 0x70, 0x08, 0x20,\n\t0x00, 0x00, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_ul_angle 72\n[TK_MAC_XCURSOR_ul_angle] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,\n\t0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x0F, 0xF8, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00,\n\t0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x03, 0x00, 0x04,\n},\n\n#define TK_MAC_XCURSOR_umbrella 73\n[TK_MAC_XCURSOR_umbrella] = {\n\t0x00, 0x00, 0x08, 0x90, 0x02, 0x28, 0x49, 0xA6, 0x27, 0xC8, 0x19, 0x30, 0x61, 0x0C, 0x01, 0x00,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 0x01, 0x40, 0x00, 0x80, 0x00, 0x00,\n\t0x00, 0x00, 0x0F, 0xF0, 0x1F, 0xF8, 0x7F, 0xFE, 0x7F, 0xFC, 0xFF, 0xFE, 0xFB, 0xBE, 0xE3, 0x8E,\n\t0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xE0, 0x03, 0xE0, 0x01, 0xC0, 0x00, 0x80,\n\t0x00, 0x04, 0x00, 0x07,\n},\n\n#define TK_MAC_XCURSOR_ur_angle 74\n[TK_MAC_XCURSOR_ur_angle] = {\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30,\n\t0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x00, 0x30, 0x00, 0x30,\n\t0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x04, 0x00, 0x0B,\n},\n\n#define TK_MAC_XCURSOR_watch 75\n[TK_MAC_XCURSOR_watch] = {\n\t0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x08, 0x10, 0x10, 0x88, 0x10, 0x88, 0x10, 0x8C,\n\t0x13, 0x8C, 0x10, 0x08, 0x10, 0x08, 0x08, 0x10, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,\n\t0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFC,\n\t0x1F, 0xFC, 0x1F, 0xF8, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,\n\t0x00, 0x08, 0x00, 0x0D,\n},\n\n#define TK_MAC_XCURSOR_xterm 76\n[TK_MAC_XCURSOR_xterm] = {\n\t0x0C, 0x60, 0x02, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x0C, 0x60,\n\t0x0C, 0x60, 0x02, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,\n\t0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x0C, 0x60,\n\t0x00, 0x0B, 0x00, 0x07,\n},\n\n};\n"
  },
  {
    "path": "macosx/tkMacOSXXStubs.c",
    "content": "/*\n * tkMacOSXXStubs.c --\n *\n *\tThis file contains most of the X calls called by Tk. Many of these\n *\tcalls are just stubs and either don't make sense on the Macintosh or\n *\ttheir implementation just doesn't do anything. Other calls will\n *\teventually be moved into other files.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 2001-2009 Apple Inc.\n * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2014 Marc Culler.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#define XLIB_ILLEGAL_ACCESS\n#include \"tkMacOSXPrivate.h\"\n#include \"tkMacOSXInt.h\"\n\n#include <IOKit/IOKitLib.h>\n#include <IOKit/hidsystem/IOHIDShared.h>\n\n/*\n * Because this file is still under major development Debugger statements are\n * used through out this file. The define TCL_DEBUG will decide whether the\n * debugger statements actually call the debugger or not.\n */\n\n#ifndef TCL_DEBUG\n#   define Debugger()\n#endif\n\n#define ROOT_ID 10\n\n/*\n * Declarations of static variables used in this file.\n */\n\n/* The unique Macintosh display. */\nstatic TkDisplay *gMacDisplay = NULL;\n/* The default name of the Macintosh display. */\nstatic const char *macScreenName = \":0\";\n/* Timestamp showing the last reset of the inactivity timer. */\nstatic Time lastInactivityReset = 0;\n\n\n/*\n * Forward declarations of procedures used in this file.\n */\n\nstatic XID\t\tMacXIdAlloc(Display *display);\nstatic int\t\tDefaultErrorHandler(Display *display,\n\t\t\t    XErrorEvent *err_evt);\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXDisplayChanged --\n *\n *\tCalled to set up initial screen info or when an event indicated\n *\tdisplay (screen) change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay change info regarding the screen.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkMacOSXDisplayChanged(\n    Display *display)\n{\n    Screen *screen;\n    NSArray *nsScreens;\n\n\n    if (display == NULL || (((_XPrivDisplay)(display))->screens) == NULL) {\n\treturn;\n    }\n    screen = (((_XPrivDisplay)(display))->screens);\n\n    nsScreens = [NSScreen screens];\n    if (nsScreens && [nsScreens count]) {\n\tNSScreen *s = [nsScreens objectAtIndex:0];\n\tNSRect bounds = [s frame];\n\tNSRect maxBounds = NSZeroRect;\n\n\tDefaultDepthOfScreen(screen) = NSBitsPerPixelFromDepth([s depth]);\n\tWidthOfScreen(screen) = bounds.size.width;\n\tHeightOfScreen(screen) = bounds.size.height;\n\tWidthMMOfScreen(screen) = (bounds.size.width * 381 + 720) / 1440; /* = 3/4 * 254/720 */\n\tHeightMMOfScreen(screen) = (bounds.size.height * 381 + 720) / 1440; /* = 3/4 * 254/720 */\n\n\tfor (s in nsScreens) {\n\t    maxBounds = NSUnionRect(maxBounds, [s visibleFrame]);\n\t}\n\t*((NSRect *)screen->ext_data) = maxBounds;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXZeroScreenHeight --\n *\n *\tReplacement for the tkMacOSXZeroScreenHeight variable to avoid\n *\tcaching values from NSScreen (fixes bug aea00be199).\n *\n * Results:\n *\tReturns the height of screen 0 (the screen assigned the menu bar\n *\tin System Preferences), or 0.0 if getting [NSScreen screens] fails.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nCGFloat\nTkMacOSXZeroScreenHeight()\n{\n    NSArray *nsScreens = [NSScreen screens];\n    if (nsScreens && [nsScreens count]) {\n\tNSScreen *s = [nsScreens objectAtIndex:0];\n\tNSRect bounds = [s frame];\n\treturn bounds.size.height;\n    }\n    return 0.0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkMacOSXZeroScreenTop --\n *\n *\tReplacement for the tkMacOSXZeroScreenTop variable to avoid\n *\tcaching values from visibleFrame.\n *\n * Results:\n *\tReturns how far below the top of screen 0 to draw\n *\t(i.e. the height of the menu bar if it is always shown),\n *\tor 0.0 if getting [NSScreen screens] fails.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nCGFloat\nTkMacOSXZeroScreenTop()\n{\n    NSArray *nsScreens = [NSScreen screens];\n    if (nsScreens && [nsScreens count]) {\n\tNSScreen *s = [nsScreens objectAtIndex:0];\n\tNSRect bounds = [s frame], visible = [s visibleFrame];\n\treturn bounds.size.height - (visible.origin.y + visible.size.height);\n    }\n    return 0.0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpOpenDisplay/XkbOpenDisplay --\n *\n *\tCreate the Display structure and fill it with device specific\n *\tinformation.\n *\n * Results:\n *\tReturns a Display structure on success or NULL on failure.\n *\n * Side effects:\n *\tAllocates a new Display structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkDisplay *\nTkpOpenDisplay(\n    const char *display_name)\n{\n    Display *display;\n\n    if (gMacDisplay != NULL) {\n\tif (strcmp(DisplayString(gMacDisplay->display), display_name) == 0) {\n\t    return gMacDisplay;\n\t} else {\n\t    return NULL;\n\t}\n    }\n\n    NSAutoreleasePool *pool = [NSAutoreleasePool new];\n\n    display = XkbOpenDisplay(display_name, NULL, NULL, NULL, NULL, NULL);\n\n    /*\n     * Initialize screen bits that may change\n     */\n\n    TkMacOSXDisplayChanged(display);\n\n    gMacDisplay = (TkDisplay *)Tcl_Alloc(sizeof(TkDisplay));\n\n    /*\n     * This is the quickest way to make sure that all the *Init flags get\n     * properly initialized\n     */\n\n    bzero(gMacDisplay, sizeof(TkDisplay));\n    gMacDisplay->display = display;\n    [pool drain];\n\n    /*\n     * Key map info must be available immediately, because of \"send event\".\n     */\n    TkpInitKeymapInfo(gMacDisplay);\n\n    return gMacDisplay;\n}\n\nDisplay *\nXkbOpenDisplay(\n    TCL_UNUSED(const char *),\n\tint *ev_rtrn,\n\tint *err_rtrn,\n\tint *major_rtrn,\n\tint *minor_rtrn,\n\tint *reason)\n{\n    _XPrivDisplay display = (_XPrivDisplay)Tcl_Alloc(sizeof(Display));\n    Screen *screen = (Screen *)Tcl_Alloc(sizeof(Screen));\n    int fd = 0;\n    NSArray *cgVers;\n    static char vendor[25] = \"\";\n    static NSRect maxBounds = {{0, 0}, {0, 0}};\n\n    bzero(display, sizeof(Display));\n    bzero(screen, sizeof(Screen));\n\n    display->resource_alloc = MacXIdAlloc;\n    LastKnownRequestProcessed(display) = 1;\n    display->qlen\t    = 0;\n    display->fd\t\t    = fd;\n    display->screens\t    = screen;\n    display->nscreens\t    = 1;\n    display->default_screen = 0;\n    display->display_name   = (char *) macScreenName;\n\n    /*\n     * These screen bits never change\n     */\n    screen->root\t= ROOT_ID;\n    screen->display\t= display;\n    screen->black_pixel = 0x00000000;\n    screen->white_pixel = 0x00FFFFFF;\n    screen->ext_data\t= (XExtData *) &maxBounds;\n\n    screen->root_visual = (Visual *)Tcl_Alloc(sizeof(Visual));\n    screen->root_visual->visualid     = 0;\n    screen->root_visual->c_class      = TrueColor;\n    screen->root_visual->red_mask     = 0x00FF0000;\n    screen->root_visual->green_mask   = 0x0000FF00;\n    screen->root_visual->blue_mask    = 0x000000FF;\n    screen->root_visual->bits_per_rgb = 24;\n    screen->root_visual->map_entries  = 256;\n\n    cgVers = [[[NSBundle bundleWithIdentifier:@\"com.apple.CoreGraphics\"]\n\t    objectForInfoDictionaryKey:@\"CFBundleShortVersionString\"]\n\t    componentsSeparatedByString:@\".\"];\n    if ([cgVers count] >= 2) {\n\tdisplay->proto_major_version = [[cgVers objectAtIndex:1] integerValue];\n    }\n    if ([cgVers count] >= 3) {\n\tdisplay->proto_minor_version = [[cgVers objectAtIndex:2] integerValue];\n    }\n    if (!vendor[0]) {\n\tsnprintf(vendor, sizeof(vendor), \"Apple AppKit %g\",\n\t\tNSAppKitVersionNumber);\n    }\n    display->vendor = vendor;\n    {\n\tint major, minor, patch;\n\n#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000\n\tGestalt(gestaltSystemVersionMajor, (SInt32*)&major);\n\tGestalt(gestaltSystemVersionMinor, (SInt32*)&minor);\n\tGestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);\n#else\n\tNSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];\n\tmajor = (int)systemVersion.majorVersion;\n\tminor = (int)systemVersion.minorVersion;\n\tpatch = (int)systemVersion.patchVersion;\n#endif\n\tdisplay->release = major << 16 | minor << 8 | patch;\n    }\n\n\n    if (ev_rtrn) *ev_rtrn = 0;\n    if (err_rtrn) *err_rtrn = 0;\n    if (major_rtrn) *major_rtrn = 0;\n    if (minor_rtrn) *minor_rtrn = 0;\n    if (reason) *reason = 0;\n\n    return display;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCloseDisplay --\n *\n *\tDeallocates a display structure created by TkpOpenDisplay.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees memory.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCloseDisplay(\n    TkDisplay *displayPtr)\n{\n    _XPrivDisplay display = (_XPrivDisplay)displayPtr->display;\n\n    if (gMacDisplay != displayPtr) {\n\tTcl_Panic(\"TkpCloseDisplay: tried to call TkpCloseDisplay on bad display\");\n    }\n\n    gMacDisplay = NULL;\n    if (display->screens != NULL) {\n\tif (DefaultVisualOfScreen(ScreenOfDisplay(display, 0)) != NULL) {\n\t    Tcl_Free(DefaultVisualOfScreen(ScreenOfDisplay(display, 0)));\n\t}\n\tTcl_Free(display->screens);\n    }\n    Tcl_Free(display);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkClipCleanup --\n *\n *\tThis procedure is called to cleanup resources associated with claiming\n *\tclipboard ownership and for receiving selection get results. This\n *\tfunction is called in tkWindow.c. This has to be called by the display\n *\tcleanup function because we still need the access display elements.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources are freed - the clipboard may no longer be used.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkClipCleanup(\n    TkDisplay *dispPtr)\t\t/* display associated with clipboard */\n{\n    /*\n     * Make sure that the local scrap is transfered to the global scrap if\n     * needed.\n     */\n\n    [NSApp tkProvidePasteboard:dispPtr];\n\n    if (dispPtr->clipWindow != NULL) {\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->applicationAtom);\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->windowAtom);\n\n\tTk_DestroyWindow(dispPtr->clipWindow);\n\tTcl_Release(dispPtr->clipWindow);\n\tdispPtr->clipWindow = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MacXIdAlloc --\n *\n *\tThis procedure is invoked by Xlib as the resource allocator for a\n *\tdisplay.\n *\n * Results:\n *\tThe return value is an X resource identifier that isn't currently in\n *\tuse.\n *\n * Side effects:\n *\tThe identifier is removed from the stack of free identifiers, if it\n *\twas previously on the stack.\n *\n *----------------------------------------------------------------------\n */\n\nstatic XID\nMacXIdAlloc(\n    TCL_UNUSED(Display *))\t\t/* Display for which to allocate. */\n{\n    static long int cur_id = 100;\n    /*\n     * Some special XIds are reserved\n     *   - this is why we start at 100\n     */\n\n    return ++cur_id;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DefaultErrorHandler --\n *\n *\tThis procedure is the default X error handler. Tk uses it's own error\n *\thandler so this call should never be called.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThis function will call panic and exit.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDefaultErrorHandler(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XErrorEvent *))\n{\n    /*\n     * This call should never be called. Tk replaces it with its own error\n     * handler.\n     */\n\n    Tcl_Panic(\"Warning hit bogus error handler!\");\n    return 0;\n}\n\f\nchar *\nXGetAtomName(\n    Display *display,\n    TCL_UNUSED(Atom))\n{\n    LastKnownRequestProcessed(display)++;\n    return NULL;\n}\n\f\nXErrorHandler\nXSetErrorHandler(\n    TCL_UNUSED(XErrorHandler))\n{\n    return DefaultErrorHandler;\n}\n\nWindow\nXRootWindow(\n    Display *display,\n    TCL_UNUSED(int))\n{\n    LastKnownRequestProcessed(display)++;\n    return ROOT_ID;\n}\n\nint\nXGetGeometry(\n    Display *display,\n    Drawable d,\n    Window *root_return,\n    int *x_return,\n    int *y_return,\n    unsigned int *width_return,\n    unsigned int *height_return,\n    unsigned int *border_width_return,\n    unsigned int *depth_return)\n{\n    TkWindow *winPtr = ((MacDrawable *)d)->winPtr;\n\n    LastKnownRequestProcessed(display)++;\n    *root_return = ROOT_ID;\n    if (winPtr) {\n\t*x_return = Tk_X(winPtr);\n\t*y_return = Tk_Y(winPtr);\n\t*width_return = Tk_Width(winPtr);\n\t*height_return = Tk_Height(winPtr);\n\t*border_width_return = winPtr->changes.border_width;\n\t*depth_return = Tk_Depth(winPtr);\n    } else {\n\tCGSize size = ((MacDrawable *)d)->size;\n\t*x_return = 0;\n\t*y_return =  0;\n\t*width_return = size.width;\n\t*height_return = size.height;\n\t*border_width_return = 0;\n\t*depth_return = 32;\n    }\n    return 1;\n}\n\nint\nXChangeProperty(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(const unsigned char *),\n    TCL_UNUSED(int))\n{\n    Debugger();\n    return Success;\n}\n\nint\nXSelectInput(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(long))\n{\n    Debugger();\n    return Success;\n}\n\nint\nXBell(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int))\n{\n    NSBeep();\n    return Success;\n}\n\n#if 0\nvoid\nXSetWMNormalHints(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(XSizeHints *))\n{\n    /*\n     * Do nothing. Shouldn't even be called.\n     */\n}\n\nXSizeHints *\nXAllocSizeHints(void)\n{\n    /*\n     * Always return NULL. Tk code checks to see if NULL is returned & does\n     * nothing if it is.\n     */\n\n    return NULL;\n}\n#endif\n\nGContext\nXGContextFromGC(\n    TCL_UNUSED(GC))\n{\n    /*\n     * TODO: currently a no-op\n     */\n\n    return 0;\n}\n\nStatus\nXSendEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Bool),\n    TCL_UNUSED(long),\n    TCL_UNUSED(XEvent *))\n{\n    Debugger();\n    return 0;\n}\n\nint\nXClearWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window))\n{\n    return Success;\n}\n\n/*\nint\nXDrawPoint(\n    Display* display,\n    Drawable d,\n    GC gc,\n    int x,\n    int y)\n{\n    return Success;\n}\n\nint\nXDrawPoints(\n    Display* display,\n    Drawable d,\n    GC gc,\n    XPoint* points,\n    int npoints,\n    int mode)\n{\n    return Success;\n}\n*/\n\nint\nXWarpPointer(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXQueryColor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    XColor* def_in_out)\n{\n    unsigned long p;\n    unsigned char r, g, b;\n    XColor *d = def_in_out;\n\n    p\t\t= d->pixel;\n    r\t\t= (p & 0x00FF0000) >> 16;\n    g\t\t= (p & 0x0000FF00) >> 8;\n    b\t\t= (p & 0x000000FF);\n    d->red\t= (r << 8) | r;\n    d->green\t= (g << 8) | g;\n    d->blue\t= (b << 8) | b;\n    d->flags\t= DoRed|DoGreen|DoBlue;\n    d->pad\t= 0;\n    return Success;\n}\n\nBool\nXTranslateCoordinates(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(Window *))\n{\n    return 0;\n}\n\nint\nXSetCommand(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(char **),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXGetWindowAttributes(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(XWindowAttributes *))\n{\n    return Success;\n}\n\nStatus\nXGetWMColormapWindows(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window **),\n    TCL_UNUSED(int *))\n{\n    return Success;\n}\n\nint\nXIconifyWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nXHostAddress *\nXListHosts(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(Bool *))\n{\n    return NULL;\n}\n\nint\nXLookupColor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(XColor *),\n    TCL_UNUSED(XColor *))\n{\n    return Success;\n}\n\nint\nXNextEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXPutBackEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXQueryColors(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    XColor* defs_in_out,\n    int ncolors)\n{\n    int i;\n    unsigned long p;\n    unsigned char r, g, b;\n    XColor *d = defs_in_out;\n\n    for (i = 0; i < ncolors; i++, d++) {\n\tp\t\t= d->pixel;\n\tr\t\t= (p & 0x00FF0000) >> 16;\n\tg\t\t= (p & 0x0000FF00) >> 8;\n\tb\t\t= (p & 0x000000FF);\n\td->red\t\t= (r << 8) | r;\n\td->green\t= (g << 8) | g;\n\td->blue\t\t= (b << 8) | b;\n\td->flags\t= DoRed|DoGreen|DoBlue;\n\td->pad\t\t= 0;\n    }\n    return Success;\n}\n\nint\nXQueryTree(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window **),\n    TCL_UNUSED(unsigned int *))\n{\n    return 0;\n}\n\n\nint\nXGetWindowProperty(\n    Display *display,\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(long),\n    TCL_UNUSED(long),\n    TCL_UNUSED(Bool),\n    TCL_UNUSED(Atom),\n    Atom *actual_type_return,\n    int *actual_format_return,\n    unsigned long *nitems_return,\n    unsigned long *bytes_after_return,\n    TCL_UNUSED(unsigned char **))\n{\n    LastKnownRequestProcessed(display)++;\n    *actual_type_return = None;\n    *actual_format_return = *bytes_after_return = 0;\n    *nitems_return = 0;\n    return 0;\n}\n\nint\nXWindowEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(long),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXWithdrawWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXmbLookupString(\n    TCL_UNUSED(XIC),\n    TCL_UNUSED(XKeyPressedEvent *),\n    TCL_UNUSED(char *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(KeySym *),\n    TCL_UNUSED(Status *))\n{\n    return Success;\n}\n\nint\nXRefreshKeyboardMapping(\n    TCL_UNUSED(XMappingEvent *))\n{\n    /* used by tkXEvent.c */\n    Debugger();\n    return Success;\n}\n\nint\nXSetIconName(\n    Display* display,\n    TCL_UNUSED(Window),\n    TCL_UNUSED(const char *))\n{\n    /*\n     * This is a no-op, no icon name for Macs.\n     */\n    LastKnownRequestProcessed(display)++;\n    return Success;\n}\n\nBool\nXFilterEvent(\n    TCL_UNUSED(XEvent *),\n    TCL_UNUSED(Window))\n{\n    return 0;\n}\n\nint\nXForceScreenSaver(\n    Display* display,\n    TCL_UNUSED(int))\n{\n    /*\n     * This function is just a no-op. It is defined to reset the screen saver.\n     * However, there is no real way to do this on a Mac. Let me know if there\n     * is!\n     */\n\n    LastKnownRequestProcessed(display)++;\n    return Success;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkGetServerInfo --\n *\n *\tGiven a window, this procedure returns information about the window\n *\tserver for that window. This procedure provides the guts of the \"winfo\n *\tserver\" command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetServerInfo(\n    Tcl_Interp *interp,\t\t/* The server information is returned in this\n\t\t\t\t * interpreter's result. */\n    Tk_Window tkwin)\t\t/* Token for window; this selects a particular\n\t\t\t\t * display and server. */\n{\n    char buffer[5 + TCL_INTEGER_SPACE * 2];\n    char buffer2[11 + TCL_INTEGER_SPACE];\n\n    snprintf(buffer, sizeof(buffer), \"CG%d.%d \",\n\t    ProtocolVersion(Tk_Display(tkwin)),\n\t    ProtocolRevision(Tk_Display(tkwin)));\n    snprintf(buffer2, sizeof(buffer2), \" Mac OS X %x\",\n\t    VendorRelease(Tk_Display(tkwin)));\n    Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),\n\t    buffer2, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XChangeWindowAttributes, XSetWindowBackground,\n * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,\n * XSetWindowBorderWidth, XSetWindowColormap\n *\n *\tThese functions are all no-ops. They all have equivalent Tk calls that\n *\tshould always be used instead.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXChangeWindowAttributes(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned long),\n    TCL_UNUSED(XSetWindowAttributes *))\n{\n    return Success;\n}\n\nint\nXSetWindowBackground(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned long))\n{\n    return Success;\n}\n\nint\nXSetWindowBackgroundPixmap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Pixmap))\n{\n    return Success;\n}\n\nint\nXSetWindowBorder(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned long))\n{\n    return Success;\n}\n\nint\nXSetWindowBorderPixmap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Pixmap))\n{\n    return Success;\n}\n\nint\nXSetWindowBorderWidth(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned int))\n{\n    return Success;\n}\n\nint\nXSetWindowColormap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Colormap))\n{\n    Debugger();\n    return Success;\n}\n\f\nStatus\nXStringListToTextProperty(\n    TCL_UNUSED(char **),\n    TCL_UNUSED(int),\n    TCL_UNUSED(XTextProperty *))\n{\n    Debugger();\n    return Success;\n}\n\nvoid\nXSetWMClientMachine(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(XTextProperty *))\n{\n    Debugger();\n}\n\nXIC\nXCreateIC(TCL_UNUSED(XIM), ...)\n{\n    Debugger();\n    return (XIC) 0;\n}\n\f\nint\nXDeleteProperty(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom))\n{\n    return Success;\n}\n\nint\nXGetInputFocus(\n    Display *display,\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(int *))\n{\n    LastKnownRequestProcessed(display)++;\n    return Success;\n}\n\nVisualID\nXVisualIDFromVisual(\n    Visual *visual)\n{\n    return visual->visualid;\n}\n\nXAfterFunction\nXSynchronize(\n    Display *display,\n    TCL_UNUSED(Bool))\n{\n    LastKnownRequestProcessed(display)++;\n    return NULL;\n}\n\nint\nXUngrabServer(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\nint\nXFreeCursor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Cursor))\n{\n    return Success;\n}\n\nint\nXNoOp(\n    Display *display)\n{\n    LastKnownRequestProcessed(display)++;\n    return 0;\n}\n\nint\nXGrabServer(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\nint\nXFree(\n    void *data)\n{\n\tif ((data) != NULL) {\n\t\tTcl_Free(data);\n\t}\n    return 0;\n}\n\nint\nXFlush(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkGetDefaultScreenName --\n *\n *\tReturns the name of the screen that Tk should use during\n *\tinitialization.\n *\n * Results:\n *\tReturns a statically allocated string.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkGetDefaultScreenName(\n    TCL_UNUSED(Tcl_Interp *),\n    const char *screenName)\t\t/* If NULL, use default string. */\n{\n    if ((screenName == NULL) || (screenName[0] == '\\0')) {\n\tscreenName = macScreenName;\n    }\n    return screenName;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetUserInactiveTime --\n *\n *\tReturn the number of milliseconds the user was inactive.\n *\n * Results:\n *\tThe number of milliseconds the user has been inactive, or -1 if\n *\tquerying the inactive time is not supported.\n *\n * Side effects:\n *\tNone.\n *----------------------------------------------------------------------\n */\n\nlong\nTk_GetUserInactiveTime(\n    TCL_UNUSED(Display *))\n{\n    io_registry_entry_t regEntry;\n    CFMutableDictionaryRef props = NULL;\n    CFTypeRef timeObj;\n    long ret = -1l;\n    uint64_t time;\n    IOReturn result;\n\n    regEntry = IOServiceGetMatchingService(0,\n\t    IOServiceMatching(\"IOHIDSystem\"));\n\n    if (regEntry == 0) {\n\treturn -1l;\n    }\n\n    result = IORegistryEntryCreateCFProperties(regEntry, &props,\n\t    kCFAllocatorDefault, 0);\n    IOObjectRelease(regEntry);\n\n    if (result != KERN_SUCCESS || props == NULL) {\n\treturn -1l;\n    }\n\n    timeObj = CFDictionaryGetValue(props, CFSTR(\"HIDIdleTime\"));\n\n    if (timeObj) {\n\t    CFNumberGetValue((CFNumberRef)timeObj,\n\t\t    kCFNumberSInt64Type, &time);\n\t    /* Convert nanoseconds to milliseconds. */\n\t    ret = (long) (time/kMillisecondScale);\n    }\n    /* Cleanup */\n    CFRelease(props);\n\n    /*\n     * If the idle time reported by the system is larger than the elapsed\n     * time since the last reset, return the elapsed time.\n     */\n    long elapsed = (long)(TkpGetMS() - lastInactivityReset);\n    if (ret > elapsed) {\n\tret = elapsed;\n    }\n\n    return ret;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ResetUserInactiveTime --\n *\n *\tReset the user inactivity timer\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tThe user inactivity timer of the underlaying windowing system is reset\n *\tto zero.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ResetUserInactiveTime(\n    TCL_UNUSED(Display *))\n{\n    lastInactivityReset = TkpGetMS();\n}\n\f\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/ttkMacOSXTheme.c",
    "content": "/*\n * ttkMacOSXTheme.c --\n *\n *      Tk theme engine for Mac OSX, using the Appearance Manager API.\n *\n * Copyright © 2004 Joe English\n * Copyright © 2005 Neil Madden\n * Copyright © 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2008-2009 Apple Inc.\n * Copyright © 2009 Kevin Walzer\n * Copyright © 2019 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * See also:\n *\n * <URL: http://developer.apple.com/documentation/Carbon/Reference/\n *      Appearance_Manager/appearance_manager/APIIndex.html >\n *\n * Notes:\n *      \"Active\" means different things in Mac and Tk terminology --\n *      On Aqua, widgets are \"Active\" if they belong to the foreground window,\n *      \"Inactive\" if they are in a background window.  Tk uses the term\n *      \"active\" to mean that the mouse cursor is over a widget; aka \"hover\",\n *      \"prelight\", or \"hot-tracked\".  Aqua doesn't use this kind of feedback.\n *\n *      The QuickDraw/Carbon coordinate system is relative to the top-level\n *      window, not to the Tk_Window.  BoxToRect() accounts for this.\n */\n\n#include \"tkMacOSXPrivate.h\"\n#include \"ttk/ttkThemeInt.h\"\n#include \"ttkMacOSXTheme.h\"\n#include \"tkColor.h\"\n\nMODULE_SCOPE NSColor *controlAccentColor(void) {\n    static int accentPixel = -1;\n    if (accentPixel == -1) {\n\tTkColor *temp = TkpGetColor(NULL, \"systemControlAccentColor\");\n\taccentPixel = temp->color.pixel;\n\tTcl_Free(temp);\n    }\n    return TkMacOSXGetNSColor(NULL, accentPixel);\n}\n\n/*\n * Values which depend on the OS version.  These are initialized\n * in Ttk_MacOSXInit.\n */\n\nstatic Ttk_Padding entryElementPadding;\nstatic CGFloat Ttk_ContrastDelta;\n\n/*----------------------------------------------------------------------\n * +++ ComputeButtonDrawInfo --\n *\n *      Fill in an appearance manager HIThemeButtonDrawInfo record\n *      from a Ttk state and the ThemeButtonParams used as the\n *      clientData.\n */\n\nstatic inline HIThemeButtonDrawInfo ComputeButtonDrawInfo(\n    ThemeButtonParams *params,\n    Ttk_State state,\n    TCL_UNUSED(Tk_Window))\n{\n    /*\n     * See ButtonElementDraw for the explanation of why we always draw\n     * some buttons in the active state.\n     */\n\n    SInt32 HIThemeState;\n    int adornment = 0;\n\n    HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state);\n\n    /*\n     * HITheme uses the adornment to decide the direction of the\n     * arrow on a Disclosure Button.  Also HITheme draws inactive\n     * (TTK_STATE_BACKGROUND) buttons in a gray color but macOS\n     * no longer does that.  So we adjust the HIThemeState.\n     */\n\n    switch (params->kind) {\n    case kThemeArrowButton:\n\tadornment = kThemeAdornmentDrawIndicatorOnly;\n\tif (state & TTK_STATE_SELECTED) {\n\t    adornment |= kThemeAdornmentArrowUpArrow;\n\t}\n\t/* Fall through. */\n    case kThemeRadioButton:\n\t/*\n\t * The gray color is better than the blue color for a\n\t * background selected Radio Button.\n\t */\n\n\tif (state & TTK_STATE_SELECTED) {\n\t    break;\n\t}\n    default:\n\tif (state & TTK_STATE_BACKGROUND) {\n\t    HIThemeState |= kThemeStateActive;\n\t}\n\tbreak;\n    }\n\n    const HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.state = HIThemeState,\n\t.kind = params ? params->kind : 0,\n\t.value = Ttk_StateTableLookup(ButtonValueTable, state),\n\t.adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state) | adornment,\n    };\n    return info;\n}\n\n/*\n * When we draw simulated Apple widgets we use the Core Graphics framework.\n * Core Graphics uses CGColorRefs, not NSColors.  A CGColorRef must be retained\n * and released explicitly while an NSColor is autoreleased.  In version 10.8\n * of macOS Apple introduced a CGColor property of an NSColor which is guaranteed\n * to be a valid CGColorRef for (approximately) the same color and is released\n * when the NSColor is autoreleased.\n *\n * When building on systems earlier than 10.8 there is no painless way to\n * convert an NSColor to a CGColor. On the other hand, on those systems we use\n * the HIToolbox to draw all widgets, so we never need to call Core Graphics\n * drawing routines directly.  This means that the functions and macros below\n * which construct CGColorRefs can be defined to return nil on systems before\n * 10.8.\n *\n * Similarly, those older systems did not have CGPathCreateWithRoundedRect, but\n * since we never need to draw rounded rectangles on those systems we can just\n * define it to return nil.\n */\n\nstatic CGColorRef\nCGColorFromRGBA(\n    CGFloat *rgba)\n{\n    NSColorSpace *colorSpace = [NSColorSpace sRGBColorSpace];\n    NSColor *nscolor = [NSColor colorWithColorSpace: colorSpace\n\t\t\t\t\t components: rgba\n\t\t\t\t\t      count: 4];\n    return nscolor.CGColor;\n}\n\nstatic CGColorRef\nCGColorFromGray(\n    GrayColor g)\n{\n    CGFloat rgba[4] = {g.grayscale, g.grayscale, g.grayscale, g.alpha};\n    NSColorSpace *colorSpace = [NSColorSpace sRGBColorSpace];\n    NSColor *nscolor = [NSColor colorWithColorSpace: colorSpace\n\t\t\t\t\t components: rgba\n\t\t\t\t\t      count: 4];\n    return nscolor.CGColor;\n}\n\n#define CGCOLOR(nscolor) (nscolor).CGColor\n\n/*----------------------------------------------------------------------\n * +++ Utilities.\n */\n\n/*----------------------------------------------------------------------\n * BoxToRect --\n *\n *    Convert a Ttk_Box in Tk coordinates relative to the given Drawable to a\n *    native CGRect relative to the containing NSView.  (The coordinate system\n *    is the one used by CGContextRef, which has origin at the upper left\n *    corner, and y increasing downward.)\n */\n\nstatic inline CGRect BoxToRect(\n    Drawable d,\n    Ttk_Box b)\n{\n    MacDrawable *md = (MacDrawable *)d;\n    CGRect rect;\n\n    rect.origin.y       = b.y + md->yOff;\n    rect.origin.x       = b.x + md->xOff;\n    rect.size.height    = b.height;\n    rect.size.width     = b.width;\n\n    return rect;\n}\n\n/*----------------------------------------------------------------------\n * LookupGrayPalette\n *\n * Retrieves the palette of grayscale colors needed to draw a particular\n * type of button, in a particular state, in light or dark mode.\n *\n */\n\nstatic GrayPalette LookupGrayPalette(\n    const ButtonDesign *design,\n    Ttk_State state,\n    bool isDark)\n{\n    const PaletteStateTable *entry = design->palettes;\n    while ((state & entry->onBits) != entry->onBits ||\n\t   (~state & entry->offBits) != entry->offBits)\n    {\n\t++entry;\n    }\n    return isDark ? entry->dark : entry->light;\n}\n\n/*----------------------------------------------------------------------\n * NormalizeButtonBounds --\n *\n *      This function returns the actual bounding rectangle that will be used\n *      in drawing the button.\n *\n *      Apple only allows three specific heights for most buttons: regular,\n *      small and mini. We always use the regular size.  However, Ttk may\n *      provide a bounding rectangle with arbitrary height.  We draw the Mac\n *      button centered vertically in the Ttk rectangle, with the same width as\n *      the rectangle.  (But we take care to produce an integer y coordinate,\n *      to avoid unexpected anti-aliasing.)\n *\n *      In addition, the button types which are not known to HIToolbox need some\n *      adjustments to their bounds.\n *\n */\n\nstatic CGRect NormalizeButtonBounds(\n    ThemeButtonParams *params,\n    CGRect bounds,\n    bool isDark)\n{\n    SInt32 height;\n\n    if (params->heightMetric != NoThemeMetric) {\n\tChkErr(GetThemeMetric, params->heightMetric, &height);\n\theight += 2;\n\tbounds.origin.y += round(1 + (bounds.size.height - height) / 2);\n\tbounds.size.height = height;\n    }\n    switch (params->kind) {\n    case TkRoundedRectButton:\n\tbounds.size.height -= 1;\n\tbreak;\n    case TkInlineButton:\n\tbounds.size.height -= 4;\n\tbounds.origin.y += 1;\n\tbreak;\n    case TkRecessedButton:\n\tbounds.size.height -= 2;\n\tbreak;\n    case TkSidebarButton:\n\tbounds.size.height += 8;\n\tbreak;\n    case kThemeRoundButtonHelp:\n\tif (isDark) {\n\t    bounds.size.height = bounds.size.width = 22;\n\t} else {\n\t    bounds.size.height = bounds.size.width = 22;\n\t}\n\tbreak;\n    default:\n\tbreak;\n    }\n    return bounds;\n}\n\n/*----------------------------------------------------------------------\n * +++ Background Colors\n *\n * Support for contrasting background colors when GroupBoxes or Tabbed\n * panes are nested inside each other.  Early versions of macOS used ridged\n * borders, so do not need contrasting backgrounds.\n */\n\n/*\n * For systems older than 10.14, [NSColor windowBackgroundColor] generates\n * garbage when called from this function.  In 10.14 it works correctly, and\n * must be used in order to have a background color which responds to Dark\n * Mode.  So we use this hard-wired RGBA color on the older systems which don't\n * support Dark Mode anyway.\n */\n\nRGBACOLOR windowBackground[4] = RGBA256(235.0, 235.0, 235.0, 1.0);\n\n/*----------------------------------------------------------------------\n * GetBackgroundColor --\n *\n *      Fills the array rgba with the color coordinates for a background color.\n *      Start with the background color of a window's container, or the\n *      standard ttk window background if there is no container. If the\n *      contrast parameter is nonzero, modify this color to be darker, for the\n *      aqua appearance, or lighter for the DarkAqua appearance.  This is\n *      primarily used by the Fill and Background elements.  The save parameter\n *      is normally YES, so the contrasting color is saved in the private\n *      data of the widget.  This behavior can be disabled in special cases,\n *      such as when drawing notebook tabs in macOS 11.\n */\n\nstatic void GetBackgroundColorRGBA(\n    TCL_UNUSED(CGContextRef),\n    Tk_Window tkwin,\n    int contrast,\n    Bool save,\n    CGFloat *rgba)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *containerPtr = (TkWindow *) TkGetContainer(tkwin);\n\n    while (containerPtr && containerPtr->privatePtr) {\n\tif (containerPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {\n\t    break;\n\t}\n\tcontainerPtr = (TkWindow *)TkGetContainer(containerPtr);\n    }\n    if (containerPtr && containerPtr->privatePtr) {\n\tfor (int i = 0; i < 4; i++) {\n\t    rgba[i] = containerPtr->privatePtr->fillRGBA[i];\n\t}\n    } else {\n\tif ([NSApp macOSVersion] >= 101400) {\n\t    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];\n\t    bool isDark = TkMacOSXInDarkMode(tkwin);\n\t    NSColor *windowColor = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\t    [NSColor windowBackgroundColor], deviceRGB, isDark);\n\t    [windowColor getComponents: rgba];\n\t} else {\n\t    for (int i = 0; i < 4; i++) {\n\t\trgba[i] = windowBackground[i];\n\t    }\n\t}\n    }\n\n    if (contrast) {\n\tbool isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5);\n\n\tif (isDark) {\n\t    for (int i = 0; i < 3; i++) {\n\t\trgba[i] += Ttk_ContrastDelta*contrast / 255.0;\n\t    }\n\t} else {\n\t    for (int i = 0; i < 3; i++) {\n\t\trgba[i] -= Ttk_ContrastDelta*contrast / 255.0;\n\t    }\n\t}\n\tif (save && winPtr->privatePtr) {\n\t    winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG;\n\t    for (int i = 0; i < 4; i++) {\n\t\twinPtr->privatePtr->fillRGBA[i] = rgba[i];\n\t    }\n\t}\n    }\n}\n\nstatic CGColorRef GetBackgroundCGColor(\n    CGContextRef context,\n    Tk_Window tkwin,\n    int contrast,\n    Bool save)\n{\n    CGFloat rgba[4];\n    GetBackgroundColorRGBA(context, tkwin, contrast, save, rgba);\n    return CGColorFromRGBA(rgba);\n}\n\n/*----------------------------------------------------------------------\n * +++ Buttons\n */\n\n/*----------------------------------------------------------------------\n * FillRoundedRectangle --\n *\n *      Fill a rounded rectangle with a specified solid color.\n */\n\nstatic void FillRoundedRectangle(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat radius,\n    CGColorRef color)\n{\n    CGPathRef path;\n    CHECK_RADIUS(radius, bounds)\n\n    path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);\n    if (!path) {\n\treturn;\n    }\n    CGContextSetFillColorWithColor(context, color);\n    CGContextBeginPath(context);\n    CGContextAddPath(context, path);\n    CGContextFillPath(context);\n    CFRelease(path);\n}\n\n/*----------------------------------------------------------------------\n * FillBorder --\n *\n *      Draw a 1-pixel border around a rounded rectangle using a 3-step\n *      gradient of shades of gray.\n */\n\nstatic void FillBorder(\n    CGContextRef context,\n    CGRect bounds,\n    GrayPalette palette,\n    CGFloat radius)\n{\n    if (bounds.size.width < 2) {\n\treturn;\n    }\n    CHECK_RADIUS(radius, bounds);\n    NSColorSpace *sRGB = [NSColorSpace sRGBColorSpace];\n    CGPoint end = CGPointMake(bounds.origin.x, bounds.origin.y + bounds.size.height);\n    CGFloat corner = (radius > 0 ? radius : 2.0) / bounds.size.height;\n    CGFloat locations[4] = {0.0, corner, 1.0 - corner, 1.0};\n    CGPathRef path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);\n    CGFloat colors[16];\n    colors[0] = colors[1] = colors[2] = palette.top / 255.0;\n    colors[4] = colors[5] = colors[6] = palette.side / 255.0;\n    colors[8] = colors[9] = colors[10] = palette.side / 255.0;\n    colors[12] = colors[13] = colors[14] = palette.bottom / 255.0;\n    colors[3] = colors[7] = colors[11] = colors[15] = 1.0;\n    CGGradientRef gradient = CGGradientCreateWithColorComponents(\n\t sRGB.CGColorSpace, colors, locations, 4);\n    if (!gradient) {\n\treturn;\n    }\n    CGContextSaveGState(context);\n    CGContextBeginPath(context);\n    CGContextAddPath(context, path);\n    CGContextClip(context);\n    CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0.0);\n    CGContextRestoreGState(context);\n    CFRelease(path);\n    CFRelease(gradient);\n}\n\n/*----------------------------------------------------------------------\n * DrawFocusRing --\n *\n *      Draw a 4-pixel wide rounded focus ring enclosing a rounded\n *      rectangle, using the current system accent color.\n */\n\nstatic void DrawFocusRing(\n    CGContextRef context,\n    CGRect bounds,\n    const ButtonDesign *design)\n{\n    CGColorRef highlightColor;\n    CGFloat highlight[4] = {1.0, 1.0, 1.0, 0.2};\n    CGColorRef focusColor;\n\n    focusColor = CGCOLOR([controlAccentColor() colorWithAlphaComponent:0.6]);\n    FillRoundedRectangle(context, bounds, design->radius, focusColor);\n    bounds = CGRectInset(bounds, 3, 3);\n    highlightColor = CGColorFromRGBA(highlight);\n    CGContextSetFillColorWithColor(context, highlightColor);\n    CGContextFillRect(context, bounds);\n}\n\n/*----------------------------------------------------------------------\n * DrawGrayButton --\n *\n *      Draw a button in normal gray colors.\n *\n *      Aqua buttons are normally drawn in a grayscale color.  The buttons,\n *      which are shaped as rounded rectangles have a 1-pixel border which is\n *      drawn in a 3-step gradient and a solid gray face.\n *\n *      Note that this will produce a round button if length = width =\n *      2 * radius.\n */\n\nstatic void DrawGrayButton(\n    CGContextRef context,\n    CGRect bounds,\n    const ButtonDesign *design,\n    Ttk_State state,\n    Tk_Window tkwin)\n{\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n    GrayPalette palette = LookupGrayPalette(design, state, isDark);\n    GrayColor faceGray = {.grayscale = 0.0, .alpha = 1.0};\n    if (palette.top <= 255.0) {\n\tFillBorder(context, bounds, palette, design->radius);\n    }\n    if (palette.face <= 255.0) {\n\tfaceGray.grayscale = palette.face / 255.0;\n    } else {\n\n\t/*\n\t * Color values > 255 are \"transparent\" which really means that we\n\t * fill with the background color.\n\t */\n\n\tCGFloat rgba[4], gray;\n\tGetBackgroundColorRGBA(context, tkwin, 0, NO, rgba);\n\tgray = (rgba[0] + rgba[1] + rgba[2]) / 3.0;\n\tfaceGray.grayscale = gray;\n    }\n    FillRoundedRectangle(context, CGRectInset(bounds, 1, 1),\n\t\t\t design->radius - 1,\n\t\t\t CGColorFromGray(faceGray));\n}\n\n/*----------------------------------------------------------------------\n * DrawAccentedButton --\n *\n *      The accent color is only used when drawing buttons in the active\n *      window.  Push Buttons and segmented Arrow Buttons are drawn in color\n *      when in the pressed state.  Selected Check Buttons, Radio Buttons and\n *      notebook Tabs are also drawn in color.  The color is based on the\n *      user's current choice for the controlAccentColor, but is actually a\n *      linear gradient with a 1-pixel darker line at the top and otherwise\n *      changing from lighter at the top to darker at the bottom.  This\n *      function draws a colored rounded rectangular button.\n */\n\nstatic void DrawAccentedButton(\n    CGContextRef context,\n    CGRect bounds,\n    const ButtonDesign *design,\n    int state,\n    bool isDark)\n{\n    NSColorSpace *sRGB = [NSColorSpace sRGBColorSpace];\n    CGColorRef faceColor = CGCOLOR(controlAccentColor());\n    CGFloat radius = design->radius;\n    CHECK_RADIUS(radius, bounds);\n    CGPathRef path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);\n    // This gradient should only be used for PushButtons and Tabs, and it needs\n    // to be lighter at the top.\n    static CGFloat components[12] = {1.0, 1.0, 1.0, 0.05,\n\t\t\t\t     1.0, 1.0, 1.0, 0.2,\n\t\t\t\t     1.0, 1.0, 1.0, 0.0};\n    CGFloat locations[3] = {0.0, 0.05, 1.0};\n    CGGradientRef gradient = CGGradientCreateWithColorComponents(\n\t\t\t\t sRGB.CGColorSpace, components, locations, 3);\n    CGPoint end;\n    if (bounds.size.height > 2*radius) {\n\tbounds.size.height -= 1;\n    }\n    end = CGPointMake(bounds.origin.x, bounds.origin.y + bounds.size.height);\n    CGContextSaveGState(context);\n    CGContextBeginPath(context);\n    CGContextAddPath(context, path);\n    CGContextClip(context);\n    FillRoundedRectangle(context, bounds, radius, faceColor);\n    CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0.0);\n    if (state & TTK_STATE_PRESSED &&\n\tstate & TTK_STATE_ALTERNATE) {\n\tCGColorRef color = isDark ?\n\t    CGColorFromGray(darkPressedDefaultButton) :\n\t    CGColorFromGray(pressedDefaultButton);\n\tFillRoundedRectangle(context, bounds, radius, color);\n    }\n    CGContextRestoreGState(context);\n    CFRelease(path);\n    CFRelease(gradient);\n}\n\n/*----------------------------------------------------------------------\n * DrawAccentedSegment --\n *\n *      Draw the colored ends of widgets like popup buttons and combo buttons.\n */\n\nstatic void DrawAccentedSegment(\n    CGContextRef context,\n    CGRect bounds,\n    const ButtonDesign *design,\n    Ttk_State state,\n    Tk_Window tkwin)\n{\n    /*\n     * Clip to the bounds and then draw an accented button which is extended so\n     * that the rounded corners on the left will be clipped off.  This assumes\n     * that the bounds include room for the focus ring.\n     */\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n    GrayColor sepGray = isDark ? darkComboSeparator : lightComboSeparator;\n    CGColorRef sepColor = CGColorFromGray(sepGray);\n    CGRect clip = bounds;\n    clip.size.height += 10;\n    bounds.origin.x -= 10;\n    bounds.size.width += 10;\n    CGPoint separator[2] = {\n\tCGPointMake(clip.origin.x - 1, bounds.origin.y + 5),\n\tCGPointMake(clip.origin.x - 1,\n\t\t    bounds.origin.y + bounds.size.height - 3)};\n    CGContextSaveGState(context);\n    CGContextSetStrokeColorWithColor(context, sepColor);\n    CGContextSetShouldAntialias(context, false);\n    CGContextSetLineWidth(context, 0.5);\n    CGContextAddLines(context, separator, 2);\n    CGContextStrokePath(context);\n    CGContextSetShouldAntialias(context, true);\n    if (state & TTK_STATE_FOCUS) {\n\tCGRect focusClip = clip;\n\tclip.size.width += 4;\n\tCGContextClipToRect(context, focusClip);\n\tbounds = CGRectInset(bounds, 0, 1);\n\tDrawFocusRing(context, bounds, design);\n    }\n    bounds = CGRectInset(bounds, 4, 4);\n    if (state & TTK_STATE_BACKGROUND) {\n\tbounds.size.height += 2;\n    } else {\n\tbounds.size.height += 1;\n    }\n    CGContextClipToRect(context, clip);\n    if ((state & TTK_STATE_BACKGROUND) || (state & TTK_STATE_DISABLED)) {\n\tDrawGrayButton(context, bounds, design, state, tkwin);\n    } else {\n\tDrawAccentedButton(context, bounds, design, state | TTK_STATE_ALTERNATE,\n\t\t\t   isDark);\n    }\n    CGContextRestoreGState(context);\n}\n\n/*----------------------------------------------------------------------\n * +++ Entry boxes\n */\n\nstatic void DrawEntry(\n    CGContextRef context,\n    CGRect bounds,\n    const ButtonDesign *design,\n    int state,\n    Tk_Window tkwin)\n{\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n    GrayPalette palette = LookupGrayPalette(design, state, isDark);\n    CGColorRef backgroundColor;\n    CGFloat bgRGBA[4];\n    if (isDark) {\n\tGetBackgroundColorRGBA(context, tkwin, 0, NO, bgRGBA);\n\n\t/*\n\t * Lighten the entry background to provide contrast.\n\t */\n\n\tfor (int i = 0; i < 3; i++) {\n\t\tbgRGBA[i] += 8.0 / 255.0;\n\t    }\n\tbackgroundColor = CGColorFromRGBA(bgRGBA);\n    } else {\n\tbackgroundColor = CG_WHITE;\n    }\n    if (state & TTK_STATE_FOCUS) {\n\tDrawFocusRing(context, bounds, design);\n    } else {\n\tFillBorder(context, CGRectInset(bounds,3,3), palette, design->radius);\n    }\n    bounds = CGRectInset(bounds, 4, 4);\n    FillRoundedRectangle(context, bounds, design->radius, backgroundColor);\n}\n\n/*----------------------------------------------------------------------\n * +++ Chevrons, CheckMarks, etc. --\n */\n\nstatic void DrawDownArrow(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat inset,\n    CGFloat size,\n    int state,\n    bool isDark)\n{\n    CGColorRef strokeColor;\n    CGFloat x, y;\n\n\n    if (state & TTK_STATE_DISABLED) {\n\tstrokeColor = TkMacOSXGetCGColorFromNSColorUsingAppearance(\n\t\t[NSColor disabledControlTextColor], isDark);\n    } else if (state & TTK_STATE_IS_ACCENTED) {\n\tstrokeColor = CG_WHITE;\n    } else {\n\tstrokeColor = TkMacOSXGetCGColorFromNSColorUsingAppearance(\n\t\t[NSColor controlTextColor], isDark);\n    }\n    CGContextSetStrokeColorWithColor(context, strokeColor);\n    CGContextSetLineWidth(context, 1.5);\n    x = bounds.origin.x + inset;\n    y = bounds.origin.y + trunc(bounds.size.height / 2) + 1;\n    CGContextBeginPath(context);\n    CGPoint arrow[3] = {\n\t{x, y - size / 4}, {x + size / 2, y + size / 4},\n\t{x + size, y - size / 4}\n    };\n    CGContextAddLines(context, arrow, 3);\n    CGContextStrokePath(context);\n}\n\n/*----------------------------------------------------------------------\n * DrawUpArrow --\n *\n * Draws a single upward pointing arrow for ListHeaders and Disclosure Buttons.\n */\n\nstatic void DrawUpArrow(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat inset,\n    CGFloat size,\n    int state,\n    bool isDark)\n{\n    NSColor *strokeColor;\n    CGFloat x, y;\n\n    if (state & TTK_STATE_DISABLED) {\n\tstrokeColor = [NSColor disabledControlTextColor];\n    } else {\n\tstrokeColor = [NSColor controlTextColor];\n    }\n    CGContextSetStrokeColorWithColor(context, TkMacOSXGetCGColorFromNSColorUsingAppearance(strokeColor, isDark));\n    CGContextSetLineWidth(context, 1.5);\n    x = bounds.origin.x + inset;\n    y = bounds.origin.y + trunc(bounds.size.height / 2);\n    CGContextBeginPath(context);\n    CGPoint arrow[3] = {\n\t{x, y + size / 4}, {x + size / 2, y - size / 4},\n\t{x + size, y + size / 4}\n    };\n    CGContextAddLines(context, arrow, 3);\n    CGContextStrokePath(context);\n}\n\n/*----------------------------------------------------------------------\n * DrawUpDownArrows --\n *\n * Draws the double arrows used in menu buttons and spin buttons.\n */\n\nstatic void DrawUpDownArrows(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat inset,\n    CGFloat size,\n    CGFloat gap,\n    int state,\n    ThemeDrawState drawState,\n    bool isDark)\n{\n    CGFloat x, y;\n    NSColor *topStrokeColor, *bottomStrokeColor;\n    if (drawState == BOTH_ARROWS && !(state & TTK_STATE_BACKGROUND)) {\n\ttopStrokeColor = bottomStrokeColor = [NSColor whiteColor];\n    } else if (drawState == kThemeStatePressedDown) {\n\ttopStrokeColor = [NSColor controlTextColor];\n\tbottomStrokeColor = [NSColor whiteColor];\n    } else if (drawState == kThemeStatePressedUp) {\n\ttopStrokeColor = [NSColor whiteColor];\n\tbottomStrokeColor = [NSColor controlTextColor];\n    } else if (state & TTK_STATE_DISABLED) {\n\ttopStrokeColor = bottomStrokeColor = [NSColor disabledControlTextColor];\n    } else {\n\ttopStrokeColor = bottomStrokeColor = [NSColor controlTextColor];\n    }\n    CGContextSetLineWidth(context, 1.5);\n    x = bounds.origin.x + inset;\n    y = bounds.origin.y + trunc(bounds.size.height / 2);\n    CGContextBeginPath(context);\n    CGPoint bottomArrow[3] =\n\t{{x, y + gap}, {x + size / 2, y + gap + size / 2}, {x + size, y + gap}};\n    CGContextAddLines(context, bottomArrow, 3);\n    CGContextSetStrokeColorWithColor(context, TkMacOSXGetCGColorFromNSColorUsingAppearance(bottomStrokeColor, isDark));\n    CGContextStrokePath(context);\n    CGContextBeginPath(context);\n    CGPoint topArrow[3] =\n\t{{x, y - gap}, {x + size / 2, y - gap - size / 2}, {x + size, y - gap}};\n    CGContextAddLines(context, topArrow, 3);\n    CGContextSetStrokeColorWithColor(context, TkMacOSXGetCGColorFromNSColorUsingAppearance(topStrokeColor, isDark));\n    CGContextStrokePath(context);\n}\n\n/*----------------------------------------------------------------------\n * DrawClosedDisclosure --\n *\n * Draws a closed disclosure chevron or filled triangle for Treeviews.\n */\n\nstatic void DrawClosedDisclosure(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat inset,\n    CGFloat size,\n    CGFloat *rgba)\n{\n    int OSVersion = [NSApp macOSVersion];\n    CGFloat x = bounds.origin.x + inset;\n    CGFloat y = bounds.origin.y + trunc(bounds.size.height / 2) + 1;\n\n    if (OSVersion >= 110000) {\n\tCGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);\n\tCGContextSetLineWidth(context, 1.5);\n    } else {\n\tCGContextSetRGBFillColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);\n    }\n\n    CGContextBeginPath(context);\n    CGPoint arrow[3] = {\n\t{x, y - size / 4 - 1}, {x + size / 2, y}, {x, y + size / 4 + 1}\n    };\n    if (OSVersion < 110000) {\n\tarrow[1].x += 1;\n    }\n    CGContextAddLines(context, arrow, 3);\n\n    if (OSVersion >= 110000) {\n\tCGContextStrokePath(context);\n    } else {\n\tCGContextFillPath(context);\n    }\n}\n\n/*----------------------------------------------------------------------\n * DrawOpenDisclosure --\n *\n * Draws an open disclosure chevron or filled triangle for Treeviews.\n */\n\nstatic void DrawOpenDisclosure(\n    CGContextRef context,\n    CGRect bounds,\n    CGFloat inset,\n    CGFloat size,\n    CGFloat *rgba)\n{\n    int OSVersion = [NSApp macOSVersion];\n    CGFloat x = bounds.origin.x + inset;\n    CGFloat y = bounds.origin.y + trunc(bounds.size.height / 2);\n\n    if (OSVersion >= 110000) {\n\tCGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);\n\tCGContextSetLineWidth(context, 1.5);\n    } else {\n\tCGContextSetRGBFillColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);\n    }\n\n    CGContextBeginPath(context);\n    CGPoint arrow[3] = {\n\t{x, y - size / 4}, {x + size / 2, y + size / 2}, {x + size, y - size / 4}\n    };\n    if (OSVersion < 110000) {\n\tarrow[0].y -= 1; arrow[2].y -= 1;\n    }\n    CGContextAddLines(context, arrow, 3);\n\n    if (OSVersion >= 110000) {\n\tCGContextStrokePath(context);\n    } else {\n\tCGContextFillPath(context);\n    }\n}\n\n/*----------------------------------------------------------------------\n * IndicatorColor --\n *\n * Returns a CGColorRef of the appropriate shade for a check button or\n * radio button in a given state.\n */\n\nstatic CGColorRef IndicatorColor(\n   int state,\n   bool isDark)\n{\n    if (state & TTK_STATE_DISABLED) {\n\treturn isDark ?\n\t    CGColorFromGray(darkDisabledIndicator) :\n\t    CGColorFromGray(lightDisabledIndicator);\n    } else if ((state & TTK_STATE_SELECTED || state & TTK_STATE_ALTERNATE) &&\n\t       !(state & TTK_STATE_BACKGROUND)) {\n\treturn CG_WHITE;\n    } else {\n\t// Q: how to reach this?\n\treturn TkMacOSXGetCGColorFromNSColorUsingAppearance([NSColor controlTextColor], isDark);\n    }\n}\n\n/*----------------------------------------------------------------------\n * DrawCheckIndicator --\n *\n * Draws the checkmark or horizontal bar in a check box.\n */\n\nstatic void DrawCheckIndicator(\n    CGContextRef context,\n    CGRect bounds,\n    int state,\n    bool isDark)\n{\n    CGFloat x = bounds.origin.x, y = bounds.origin.y;\n    CGColorRef strokeColor = IndicatorColor(state, isDark);\n\n    CGContextSetStrokeColorWithColor(context, strokeColor);\n    if (state & TTK_STATE_SELECTED) {\n\tCGContextSetLineWidth(context, 1.5);\n\tCGContextBeginPath(context);\n\tCGPoint check[3] = {{x + 3, y + 7}, {x + 6, y + 10}, {x + 10, y + 3}};\n\tCGContextAddLines(context, check, 3);\n\tCGContextStrokePath(context);\n    } else if (state & TTK_STATE_ALTERNATE) {\n\tCGContextSetLineWidth(context, 2.0);\n\tCGContextBeginPath(context);\n\tCGPoint bar[2] = {{x + 3, y + 7}, {x + 11, y + 7}};\n\tCGContextAddLines(context, bar, 2);\n\tCGContextStrokePath(context);\n    }\n}\n\n/*----------------------------------------------------------------------\n * DrawRadioIndicator --\n *\n * Draws the dot in the middle of a selected radio button.\n */\n\nstatic void DrawRadioIndicator(\n    CGContextRef context,\n    CGRect bounds,\n    int state,\n    bool isDark)\n{\n    CGFloat x = bounds.origin.x, y = bounds.origin.y;\n    CGColorRef fillColor = IndicatorColor(state, isDark);\n\n    CGContextSetFillColorWithColor(context, fillColor);\n    if (state & TTK_STATE_SELECTED) {\n\tCGContextBeginPath(context);\n\tCGRect dot = {{x + 5, y + 5}, {6, 6}};\n\tCGContextAddEllipseInRect(context, dot);\n\tCGContextFillPath(context);\n    } else if (state & TTK_STATE_ALTERNATE) {\n\tCGRect bar = {{x + 4, y + 7}, {8, 2}};\n\tCGContextFillRect(context, bar);\n    }\n}\n\nstatic void\nDrawHelpSymbol(\n    CGContextRef context,\n    CGRect bounds,\n    int state,\n    bool isDark)\n{\n    NSFont *font = [NSFont controlContentFontOfSize:15];\n    NSColor *foreground = state & TTK_STATE_DISABLED ?\n\t[NSColor disabledControlTextColor] : [NSColor controlTextColor];\n    NSDictionary *attrs = @{\n\tNSForegroundColorAttributeName : TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(foreground, [NSColorSpace deviceRGBColorSpace], isDark),\n\tNSFontAttributeName : font\n    };\n    NSAttributedString *attributedString = [[NSAttributedString alloc]\n\t\t\t\t\t\t      initWithString:@\"?\"\n\t\t\t\t\t\t\t  attributes:attrs];\n    CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(\n\t       (CFAttributedStringRef)attributedString);\n    CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, 1));\n    CGAffineTransform t = CGAffineTransformMake(\n\t\t\t      1.0, 0.0, 0.0, -1.0, 0.0, bounds.size.height);\n    CGContextSaveGState(context);\n    CGContextSetTextMatrix(context, t);\n    CGContextSetTextPosition(context,\n\t\t\t     bounds.origin.x + 6.5,\n\t\t\t     bounds.origin.y + bounds.size.height - 5);\n    CTLineDraw(line, context);\n    CGContextRestoreGState(context);\n    CFRelease(line);\n    CFRelease(typesetter);\n    [attributedString release];\n}\n\n\n\f\n/*----------------------------------------------------------------------\n * +++ Progress bars.\n */\n\n/*----------------------------------------------------------------------\n * DrawProgressBar --\n *\n * Draws a progress bar, with parameters supplied by a HIThemeTrackDrawInfo\n * struct.  Draws a rounded rectangular track overlayed by a colored\n * rounded rectangular indicator.  An indeterminate progress bar is\n * animated.\n */\n\nstatic void DrawProgressBar(\n    CGContextRef context,\n    CGRect bounds,\n    HIThemeTrackDrawInfo info,\n    int state,\n    Tk_Window tkwin)\n{\n    CGRect colorBounds;\n    CGFloat rgba[4];\n    CGColorRef trackColor, highlightColor, fillColor;\n    NSColor *accent;\n    CGFloat ratio = (CGFloat) info.value / (CGFloat) (info.max - info.min);\n\n    GetBackgroundColorRGBA(context, tkwin, 0, NO, rgba);\n\n    /*\n     * Compute the bounds for the track and indicator.  The track is 6 pixels\n     * wide in the center of the widget bounds.\n     */\n\n    if (info.attributes & kThemeTrackHorizontal) {\n\tbounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3);\n\tcolorBounds = bounds;\n\tif (info.kind == kThemeIndeterminateBar) {\n\t    CGFloat width = 0.25*bounds.size.width;\n\t    CGFloat travel = 0.75*bounds.size.width;\n\t    CGFloat center = bounds.origin.x + (width / 2) + ratio*travel;\n\t    colorBounds.origin.x = center - width / 2;\n\t    colorBounds.size.width = width;\n\t} else {\n\t    colorBounds.size.width = ratio*bounds.size.width;\n\t}\n\tif (colorBounds.size.width > 0 && colorBounds.size.width < 6) {\n\t    colorBounds.size.width = 6;\n\t}\n    } else {\n\tbounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 1);\n\tcolorBounds = bounds;\n\tif (info.kind == kThemeIndeterminateBar) {\n\t    CGFloat height = 0.25*bounds.size.height;\n\t    CGFloat travel = 0.75*bounds.size.height;\n\t    CGFloat center = bounds.origin.y + (height / 2) + ratio*travel;\n\t    colorBounds.origin.y = center - height / 2;\n\t    colorBounds.size.height = height;\n\t} else {\n\t    colorBounds.size.height = ratio*(bounds.size.height);\n\t}\n\tif (colorBounds.size.height > 0 && colorBounds.size.height < 6) {\n\t    colorBounds.size.height = 6;\n\t}\n\tcolorBounds.origin.y += bounds.size.height - colorBounds.size.height;\n    }\n\n    /*\n     * Compute the colors for the track and indicator.\n     */\n\n    if (TkMacOSXInDarkMode(tkwin)) {\n\tfor(int i=0; i < 3; i++) {\n\t    rgba[i] += 30.0 / 255.0;\n\t}\n\ttrackColor = CGColorFromRGBA(rgba);\n\tfor(int i=0; i < 3; i++) {\n\t    rgba[i] -= 5.0 / 255.0;\n\t}\n\thighlightColor = CGColorFromRGBA(rgba);\n\tFillRoundedRectangle(context, bounds, 3, trackColor);\n    } else {\n\tfor(int i=0; i < 3; i++) {\n\t    rgba[i] -= 14.0 / 255.0;\n\t}\n\ttrackColor = CGColorFromRGBA(rgba);\n\tfor(int i=0; i < 3; i++) {\n\t    rgba[i] += 3.0 / 255.0;\n\t}\n\thighlightColor = CGColorFromRGBA(rgba);\n\tbounds.size.height -= 1;\n\tbounds = CGRectInset(bounds, 0, -1);\n    }\n    if (state & TTK_STATE_BACKGROUND) {\n\taccent = [NSColor colorWithRed:0.72 green:0.72 blue:0.72 alpha:0.72];\n    } else {\n\taccent = controlAccentColor();\n    }\n\n    /*\n     * Draw the track, with highlighting around the edge.\n     */\n\n    FillRoundedRectangle(context, bounds, 3, trackColor);\n    bounds = CGRectInset(bounds, 0, 0.5);\n    FillRoundedRectangle(context, bounds, 2.5, highlightColor);\n    bounds = CGRectInset(bounds, 0.5, 0.5);\n    FillRoundedRectangle(context, bounds, 2, trackColor);\n    bounds = CGRectInset(bounds, -0.5, -1);\n\n    /*\n     * Draw the indicator.  Make it slightly transparent around the\n     * edge so the highlightng shows through.\n     */\n\n    if (info.kind == kThemeIndeterminateBar &&\n\t(state & TTK_STATE_SELECTED) == 0) {\n\treturn;\n    }\n\n    fillColor = CGCOLOR([accent colorWithAlphaComponent:0.9]);\n    FillRoundedRectangle(context, colorBounds, 3, fillColor);\n    colorBounds = CGRectInset(colorBounds, 1, 1);\n    fillColor = CGCOLOR([accent colorWithAlphaComponent:1.0]);\n    FillRoundedRectangle(context, colorBounds, 2.5, fillColor);\n}\n\f\n/*----------------------------------------------------------------------\n * +++ Sliders.\n */\n\n/*----------------------------------------------------------------------\n * DrawSlider --\n *\n * Draws a slider track and round thumb for a Ttk scale widget.  The accent\n * color is used on the left or top part of the track, so the fraction of\n * the track which is colored is equal to (value - from) / (to - from).\n *\n */\n\nstatic void DrawSlider(\n    CGContextRef context,\n    CGRect bounds,\n    HIThemeTrackDrawInfo info,\n    int state,\n    Tk_Window tkwin)\n{\n    CGColorRef trackColor;\n    CGRect clipBounds, trackBounds, thumbBounds;\n    CGPoint thumbPoint;\n    CGFloat position;\n    CGColorRef accentColor;\n    Bool fromIsSmaller = info.reserved;\n    double from = info.min, to = fabs((double) info.max), value = info.value;\n\n    /*\n     * info.min, info.max and info.value are integers.  When this is called\n     * we will have arranged that min = 0 and max is a large positive integer.\n     */\n\n    double fraction = (from < to) ? (value - from) / (to - from) : 0.5;\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n\n    if (info.attributes & kThemeTrackHorizontal) {\n\ttrackBounds = CGRectInset(bounds, 0, bounds.size.height / 2 - 3);\n\ttrackBounds.size.height = 3;\n\tposition = 8 + fraction * (trackBounds.size.width - 16);\n\tclipBounds = trackBounds;\n\tif (fromIsSmaller) {\n\t    clipBounds.size.width = position;\n\t} else {\n\t    clipBounds.origin.x += position;\n\t    clipBounds.size.width -= position;\n\t}\n\tthumbPoint = CGPointMake(trackBounds.origin.x + position,\n\t\t\t\t trackBounds.origin.y + 1);\n    } else {\n\ttrackBounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 0);\n\ttrackBounds.size.width = 3;\n\tposition = 8 + fraction * (trackBounds.size.height - 16);\n\tclipBounds = trackBounds;\n\tif (fromIsSmaller) {\n\t    clipBounds.size.height = position;\n\t} else {\n\t    clipBounds.origin.y += position;\n\t    clipBounds.size.height -= position;\n\t}\n\tthumbPoint = CGPointMake(trackBounds.origin.x + 1,\n\t\t\t\t trackBounds.origin.y + position);\n    }\n    trackColor = isDark ? CGColorFromGray(darkTrack):\n\tCGColorFromGray(lightTrack);\n    thumbBounds = CGRectMake(thumbPoint.x - 8, thumbPoint.y - 8, 17, 17);\n    CGContextSaveGState(context);\n    FillRoundedRectangle(context, trackBounds, 1.5, trackColor);\n    CGContextClipToRect(context, clipBounds);\n    if (state & (TTK_STATE_BACKGROUND | TTK_STATE_DISABLED)) {\n\taccentColor = isDark ? CGColorFromGray(darkInactiveTrack) :\n\t    CGColorFromGray(lightInactiveTrack);\n    } else {\n\taccentColor = CGCOLOR(controlAccentColor());\n    }\n    FillRoundedRectangle(context, trackBounds, 1.5, accentColor);\n    CGContextRestoreGState(context);\n    DrawGrayButton(context, thumbBounds, &sliderDesign, state, tkwin);\n}\n\n/*----------------------------------------------------------------------\n * +++ Drawing procedures for native widgets.\n *\n *      The HIToolbox does not support Dark Mode, and apparently never will.\n *      It also draws some widgets in discontinued older styles even when used\n *      on new OS releases.  So to make widgets look \"native\" we have to provide\n *      analogues of the HIToolbox drawing functions to be used on newer systems.\n *      We continue to use NIToolbox for older versions of the OS.\n *\n *      Drawing the dark widgets requires NSColors that were introduced in OSX\n *      10.14, so we make some of these functions be no-ops when building on\n *      systems older than 10.14.\n */\n\n/*----------------------------------------------------------------------\n * DrawButton --\n *\n * This is a standalone drawing procedure which draws most types of macOS\n * buttons for newer OS releases.  The button style is specified in the\n * \"kind\" field of a HIThemeButtonDrawInfo struct, although some of the\n * identifiers are not recognized by HIToolbox.\n */\n\nstatic void DrawButton(\n    CGRect bounds,\n    HIThemeButtonDrawInfo info,\n    Ttk_State state,\n    CGContextRef context,\n    Tk_Window tkwin)\n{\n    ThemeButtonKind kind = info.kind;\n    ThemeDrawState drawState = info.state;\n    CGRect arrowBounds = bounds = CGRectInset(bounds, 1, 1);\n    bool hasIndicator, isDark = TkMacOSXInDarkMode(tkwin);\n\n    switch (kind) {\n    case TkRoundedRectButton:\n\tDrawGrayButton(context, bounds, &roundedrectDesign, state, tkwin);\n\tbreak;\n    case TkInlineButton:\n\tDrawGrayButton(context, bounds, &inlineDesign, state, tkwin);\n\tbreak;\n    case TkRecessedButton:\n\tDrawGrayButton(context, bounds, &recessedDesign, state, tkwin);\n\tbreak;\n    case TkSidebarButton:\n\tDrawGrayButton(context, bounds, &sidebarDesign, state, tkwin);\n\tbreak;\n    case kThemeRoundedBevelButton:\n\tDrawGrayButton(context, bounds, &bevelDesign, state, tkwin);\n\tbreak;\n    case kThemePushButton:\n\n\t/*\n\t * The TTK_STATE_ALTERNATE bit means -default active.  Apple only\n\t * indicates the default state (which means that the key equivalent is\n\t * \"\\n\") for Push Buttons.\n\t */\n\n\tif ((state & TTK_STATE_PRESSED || state & TTK_STATE_ALTERNATE) &&\n\t    !(state & TTK_STATE_BACKGROUND)) {\n\t    DrawAccentedButton(context, bounds, &pushbuttonDesign, state, isDark);\n\t} else {\n\t    DrawGrayButton(context, bounds, &pushbuttonDesign, state, tkwin);\n\t}\n\tbreak;\n    case kThemeRoundButtonHelp:\n\tDrawGrayButton(context, bounds, &helpDesign, state, tkwin);\n\tDrawHelpSymbol(context, bounds, state, isDark);\n\tbreak;\n    case kThemePopupButton:\n\tdrawState = 0;\n\tDrawGrayButton(context, bounds, &popupDesign, state, tkwin);\n\tarrowBounds.size.width = 17;\n\tarrowBounds.origin.x += bounds.size.width - 17;\n\tif (!(state & TTK_STATE_BACKGROUND) &&\n\t    !(state & TTK_STATE_DISABLED)) {\n\t    CGRect popupBounds = arrowBounds;\n\n\t    /*\n\t     * Allow room for nonexistent focus ring.\n\t     */\n\n\t    popupBounds.size.width += 4;\n\t    popupBounds.origin.y -= 4;\n\t    popupBounds.size.height += 8;\n\t    DrawAccentedSegment(context, popupBounds, &popupDesign, state, tkwin);\n\t    drawState = BOTH_ARROWS;\n\t}\n\tarrowBounds.origin.x += 2;\n\tDrawUpDownArrows(context, arrowBounds, 3, 7, 2, state, drawState, isDark);\n\tbreak;\n    case kThemeComboBox:\n\tif (state & TTK_STATE_DISABLED) {\n\t    // Need to add the disabled case to entryDesign.\n\t    DrawEntry(context, bounds, &entryDesign, state, tkwin);\n\t} else {\n\t    DrawEntry(context, bounds, &entryDesign, state, tkwin);\n\t}\n\tarrowBounds.size.width = 17;\n\tif (state & TTK_STATE_BACKGROUND) {\n\t    arrowBounds.origin.x += bounds.size.width - 20;\n\t    arrowBounds.size.width += 4;\n\t    arrowBounds.origin.y -= 1;\n\t} else {\n\t    arrowBounds.origin.y -= 1;\n\t    arrowBounds.origin.x += bounds.size.width - 20;\n\t    arrowBounds.size.width += 4;\n\t    arrowBounds.size.height += 2;\n\t}\n\tDrawAccentedSegment(context, arrowBounds, &comboDesign, state, tkwin);\n\tif (!(state & TTK_STATE_BACKGROUND)) {\n\t    state |= TTK_STATE_IS_ACCENTED;\n\t}\n\tDrawDownArrow(context, arrowBounds, 6, 6, state, isDark);\n\tbreak;\n    case kThemeCheckBox:\n\tbounds = CGRectOffset(CGRectMake(0, bounds.size.height / 2 - 8, 16, 16),\n\t\t\t      bounds.origin.x, bounds.origin.y);\n\tbounds = CGRectInset(bounds, 1, 1);\n\thasIndicator = state & TTK_STATE_SELECTED || state & TTK_STATE_ALTERNATE;\n\tif (hasIndicator &&\n\t    !(state & TTK_STATE_BACKGROUND) &&\n\t    !(state & TTK_STATE_DISABLED)) {\n\t    DrawAccentedButton(context, bounds, &checkDesign, 0, isDark);\n\t} else {\n\t    DrawGrayButton(context, bounds, &checkDesign, state, tkwin);\n\t}\n\tif (hasIndicator) {\n\t    DrawCheckIndicator(context, bounds, state, isDark);\n\t}\n\tbreak;\n    case kThemeRadioButton:\n\tbounds = CGRectOffset(CGRectMake(0, bounds.size.height / 2 - 9, 18, 18),\n\t\t\t\t\t bounds.origin.x, bounds.origin.y);\n\tbounds = CGRectInset(bounds, 1, 1);\n\thasIndicator = state & TTK_STATE_SELECTED || state & TTK_STATE_ALTERNATE;\n\tif (hasIndicator &&\n\t    !(state & TTK_STATE_BACKGROUND) &&\n\t    !(state & TTK_STATE_DISABLED)) {\n\t    DrawAccentedButton(context, bounds, &radioDesign, 0, isDark);\n\t} else {\n\t    DrawGrayButton(context, bounds, &radioDesign, state, tkwin);\n\t}\n\tif (hasIndicator) {\n\t    DrawRadioIndicator(context, bounds, state, isDark);\n\t}\n\tbreak;\n    case kThemeArrowButton:\n\tDrawGrayButton(context, bounds, &pushbuttonDesign, state, tkwin);\n\tarrowBounds.origin.x = bounds.origin.x + bounds.size.width - 17;\n\tarrowBounds.size.width = 16;\n\tarrowBounds.origin.y -= 1;\n\tif (state & TTK_STATE_SELECTED) {\n\t    DrawUpArrow(context, arrowBounds, 5, 6, state, isDark);\n\t} else {\n\t    DrawDownArrow(context, arrowBounds, 5, 6, state, isDark);\n\t}\n\tbreak;\n    case kThemeIncDecButton:\n\tDrawGrayButton(context, bounds, &incdecDesign, state, tkwin);\n\tif (state & TTK_STATE_PRESSED) {\n\t    CGRect clip;\n\t    if (drawState == kThemeStatePressedDown) {\n\t\tclip = bounds;\n\t\tclip.size.height /= 2;\n\t\tclip.origin.y += clip.size.height;\n\t\tbounds.size.height += 1;\n\t\tclip.size.height += 1;\n\t    } else {\n\t\tclip = bounds;\n\t\tclip.size.height /= 2;\n\t    }\n\t    CGContextSaveGState(context);\n\t    CGContextClipToRect(context, clip);\n\t    DrawAccentedButton(context, bounds, &incdecDesign, 0, isDark);\n\t    CGContextRestoreGState(context);\n\t}\n\t{\n\t    CGFloat inset = (bounds.size.width - 5) / 2;\n\t    DrawUpDownArrows(context, bounds, inset, 5, 3, state, drawState, isDark);\n\t}\n\tbreak;\n    default:\n\tbreak;\n    }\n}\n\f\n/*----------------------------------------------------------------------\n * DrawGroupBox --\n *\n * This is a standalone drawing procedure which draws the contrasting rounded\n * rectangular box for LabelFrames and Notebook panes used in more recent\n * versions of macOS.  Normally the contrast is set to one, since the nesting\n * level of the Group Box is higher by 1 compared to its container.  But we\n * allow higher contrast for special cases, notably notebook tabs in macOS 11.\n * The save parameter is passed to GetBackgroundColor and should probably be\n * NO in such special cases.\n */\n\nstatic void DrawGroupBox(\n    CGRect bounds,\n    CGContextRef context,\n    Tk_Window tkwin,\n    int contrast,\n    Bool save)\n{\n    CGFloat radius = 5;\n    CHECK_RADIUS(radius, bounds)\n\n    CGPathRef path;\n    CGColorRef backgroundColor, borderColor;\n\n    backgroundColor = GetBackgroundCGColor(context, tkwin, contrast, save);\n    borderColor = CGColorFromGray(boxBorder);\n    CGContextSetFillColorWithColor(context, backgroundColor);\n    path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);\n    CGContextClipToRect(context, bounds);\n    CGContextBeginPath(context);\n    CGContextAddPath(context, path);\n    CGContextFillPath(context);\n    CGContextSetFillColorWithColor(context, borderColor);\n    CGContextBeginPath(context);\n    CGContextAddPath(context, path);\n    CGContextReplacePathWithStrokedPath(context);\n    CGContextFillPath(context);\n    CFRelease(path);\n}\n\f\n/*----------------------------------------------------------------------\n * DrawListHeader --\n *\n * This is a standalone drawing procedure which draws column headers for a\n * Treeview in the Aqua appearance.  (The HIToolbox headers have not matched the\n * native ones since OSX 10.8)  Note that the header image is ignored, but we\n * draw arrows according to the state.\n */\n\nstatic void DrawListHeader(\n    CGRect bounds,\n    CGContextRef context,\n    Tk_Window tkwin,\n    int state)\n{\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n    CGFloat x = bounds.origin.x, y = bounds.origin.y;\n    CGFloat w = bounds.size.width, h = bounds.size.height;\n    CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};\n    CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};\n    CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};\n    CGColorRef strokeColor, backgroundColor;\n\n    /*\n     * Apple changes the background color of a list header when the window is\n     * not active.  But Ttk does not indicate that in the state of a\n     * TreeHeader.  So we have to query the Apple window manager.\n     */\n\n    NSWindow *win = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));\n    if (!isDark) {\n\tGrayColor bgGray = [win isKeyWindow] ?\n\t    listheaderActiveBG : listheaderInactiveBG;\n\tbackgroundColor = CGColorFromGray(bgGray);\n    }\n\n    CGContextSaveGState(context);\n    CGContextSetShouldAntialias(context, false);\n    if (!isDark) {\n\tCGContextBeginPath(context);\n\tCGContextSetFillColorWithColor(context, backgroundColor);\n\tCGContextAddRect(context, bounds);\n\tCGContextFillPath(context);\n    }\n    strokeColor = isDark ?\n\tCGColorFromGray(darkListheaderBorder) :\n\tCGColorFromGray(listheaderSeparator);\n    CGContextSetStrokeColorWithColor(context, strokeColor);\n    CGContextAddLines(context, separator, 2);\n    CGContextStrokePath(context);\n    strokeColor = isDark ?\n\tCGColorFromGray(darkListheaderBorder) :\n\tCGColorFromGray(lightListheaderBorder);\n    CGContextSetStrokeColorWithColor(context, strokeColor);\n    CGContextAddLines(context, top, 2);\n    CGContextStrokePath(context);\n    CGContextAddLines(context, bottom, 2);\n    CGContextStrokePath(context);\n    CGContextRestoreGState(context);\n\n    if (state & TTK_TREEVIEW_STATE_SORTARROW) {\n\tCGRect arrowBounds = bounds;\n\tarrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;\n\tarrowBounds.size.width = 16;\n\tif (state & TTK_STATE_ALTERNATE) {\n\t    DrawUpArrow(context, arrowBounds, 3, 8, state, isDark);\n\t} else if (state & TTK_STATE_SELECTED) {\n\t    DrawDownArrow(context, arrowBounds, 3, 8, state, isDark);\n\t}\n    }\n}\n\f\n/*----------------------------------------------------------------------\n * DrawTab --\n *\n * This is a standalone drawing procedure which draws Tabbed Pane Tabs for the\n * notebook widget.\n */\n\nstatic void\nDrawTab(\n    CGRect bounds,\n    Ttk_State state,\n    CGContextRef context,\n    Tk_Window tkwin)\n{\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    bool horizontal = true;\n    CGRect originalBounds = bounds;\n    CGColorRef strokeColor;\n    int OSVersion = [NSApp macOSVersion];\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n\thorizontal =\n\t    nbTabPlcStickBit == TTK_STICK_S || nbTabPlcStickBit == TTK_STICK_N;\n    }\n\n    /*\n     * Extend the bounds to one or both sides so the rounded part will be\n     * clipped off in the right of the left tab, the left of the right tab,\n     * and both sides of the middle tabs.  Similarly for vertical tab rows.\n     */\n\n    CGContextClipToRect(context, bounds);\n    if (OSVersion < 110000 || !(state & TTK_STATE_SELECTED)) {\n\tif (!(state & TTK_STATE_FIRST)) {\n\t    if (horizontal) {\n\t\tbounds.origin.x -= 10;\n\t\tbounds.size.width += 10;\n\t    } else {\n\t\tbounds.origin.y -= 10;\n\t\tbounds.size.height += 10;\n\t    }\n\t}\n\tif (!(state & TTK_STATE_LAST)) {\n\t    if (horizontal) {\n\t\tbounds.size.width += 10;\n\t    } else {\n\t\tbounds.size.height += 10;\n\t    }\n\t}\n    }\n\n    /*\n     * Fill the tab face with the appropriate color or gradient.  Use a solid\n     * color if the tab is not selected, otherwise use the accent color with\n     * highlights\n     */\n\n    if (!(state & TTK_STATE_SELECTED)) {\n\tDrawGrayButton(context, bounds, &tabDesign, state, tkwin);\n\n\t/*\n\t * Draw a separator line on the left/top side of the tab if it is\n\t * not first.\n\t */\n\n\tif (!(state & TTK_STATE_FIRST)) {\n\t    CGContextSaveGState(context);\n\t    strokeColor = CGColorFromGray(darkTabSeparator);\n\t    CGContextSetStrokeColorWithColor(context, strokeColor);\n\t    CGContextBeginPath(context);\n\t    if (horizontal) {\n\t\tCGContextMoveToPoint(context, originalBounds.origin.x,\n\t\t    originalBounds.origin.y + 1);\n\t\tCGContextAddLineToPoint(context, originalBounds.origin.x,\n\t\t    originalBounds.origin.y + originalBounds.size.height - 1);\n\t    } else {\n\t\tCGContextMoveToPoint(context, originalBounds.origin.x + 1,\n\t\t    originalBounds.origin.y);\n\t\tCGContextAddLineToPoint(context,\n\t\t    originalBounds.origin.x + originalBounds.size.width - 1,\n\t\t    originalBounds.origin.y);\n\t    }\n\t    CGContextStrokePath(context);\n\t    CGContextRestoreGState(context);\n\t}\n    } else {\n\t/*\n\t * This is the selected tab; paint it with the current accent color.\n\t * If it is first, cover up the separator line drawn by the second one.\n\t * (The selected tab is always drawn last.)\n\t */\n\n\tif ((state & TTK_STATE_FIRST) && !(state & TTK_STATE_LAST)) {\n\t    if (horizontal) {\n\t\tbounds.size.width += 1;\n\t    } else {\n\t\tbounds.size.height += 1;\n\t    }\n\t}\n\tif (!(state & TTK_STATE_BACKGROUND)) {\n\t    DrawAccentedButton(context, bounds, &tabDesign, 0, 0);\n\t} else {\n\t    DrawGrayButton(context, bounds, &tabDesign, state, tkwin);\n\t}\n    }\n}\n\nstatic void\nDrawTab11(\n    CGRect bounds,\n    Ttk_State state,\n    CGContextRef context,\n    Tk_Window tkwin)\n{\n    if (state & TTK_STATE_SELECTED) {\n\tDrawGrayButton(context, bounds, &pushbuttonDesign, state, tkwin);\n    } else {\n\tTtk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n\tTkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\tCGRect clipRect = bounds;\n\n\tif (mainInfoPtr != NULL) {\n\t    nbTabPlcStickBit =\n\t\t(Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n\t}\n\n\t/*\n\t * Draw a segment of a Group Box as a background for non-selected tabs.\n\t * Clip the Group Box so that the segments fit together to form a long\n\t * rounded rectangle behind the entire tab bar.\n\t */\n\n\tif (!(state & TTK_STATE_FIRST)) {\n\t    if (nbTabPlcStickBit == TTK_STICK_S ||\n\t\t    nbTabPlcStickBit == TTK_STICK_N) {\n\t\tclipRect.origin.x -= 5;\n\t\tbounds.origin.x -= 5;\n\t\tclipRect.size.width += 5;\n\t\tbounds.size.width += 5;\n\t    } else {\n\t\tclipRect.origin.y -= 5;\n\t\tbounds.origin.y -= 5;\n\t\tclipRect.size.height += 5;\n\t\tbounds.size.height += 5;\n\t    }\n\t}\n\n\tif (!(state & TTK_STATE_LAST)) {\n\t    if (nbTabPlcStickBit == TTK_STICK_S ||\n\t\t    nbTabPlcStickBit == TTK_STICK_N) {\n\t\tclipRect.size.width += 5;\n\t\tbounds.size.width += 5;\n\t    } else {\n\t\tclipRect.size.height += 5;\n\t\tbounds.size.height += 5;\n\t    }\n\t}\n\n\tCGContextSaveGState(context);\n\tCGContextClipToRect(context, clipRect);\n\tDrawGroupBox(bounds, context, tkwin, 3, NO);\n\tCGContextRestoreGState(context);\n    }\n}\n\n/*----------------------------------------------------------------------\n * DrawDarkSeparator --\n *\n * This is a standalone drawing procedure which draws a separator widget\n * in Dark Mode.  HIToolbox is used in light mode.\n */\n\nstatic void DrawDarkSeparator(\n    CGRect bounds,\n    CGContextRef context,\n    TCL_UNUSED(Tk_Window))\n{\n    CGColorRef sepColor = CGColorFromGray(darkSeparator);\n\n    CGContextSetFillColorWithColor(context, sepColor);\n    CGContextFillRect(context, bounds);\n}\n\n/*----------------------------------------------------------------------\n * +++ DrawGradientButton --\n *\n *      This is a standalone drawing procedure which draws a\n *      a Gradient Button.\n */\n\nstatic void DrawGradientBorder(\n    CGRect bounds,\n    CGContextRef context,\n    Tk_Window tkwin,\n    Ttk_State state)\n{\n    CGColorRef faceColor, borderColor;\n    GrayColor faceGray, borderGray;\n    CGRect inside = CGRectInset(bounds, 1, 1);\n\n    if (TkMacOSXInDarkMode(tkwin)) {\n\tif (state & TTK_STATE_DISABLED) {\n\t    faceGray = darkGradientDisabled;\n\t    borderGray = darkGradientBorderDisabled;\n\t} else {\n\t    faceGray = state & TTK_STATE_PRESSED ?\n\t\tdarkGradientPressed : darkGradientNormal;\n\t    borderGray = darkGradientBorder;\n\t}\n    } else {\n\tif (state & TTK_STATE_DISABLED) {\n\t    faceGray = lightGradientDisabled;\n\t    borderGray = lightGradientBorderDisabled;\n\t} else {\n\t    faceGray = state & TTK_STATE_PRESSED ?\n\t\tlightGradientPressed : lightGradientNormal;\n\t    borderGray = lightGradientBorder;\n\t}\n    }\n    faceColor = CGColorFromGray(faceGray);\n    borderColor = CGColorFromGray(borderGray);\n    CGContextSetFillColorWithColor(context, faceColor);\n    CGContextFillRect(context, inside);\n    CGContextSetFillColorWithColor(context, borderColor);\n    CGContextAddRect(context, bounds);\n    CGContextAddRect(context, inside);\n    CGContextEOFillPath(context);\n}\n\n/*----------------------------------------------------------------------\n * +++ Button elements.\n */\n\nstatic void ButtonElementMinSize(\n    void *clientData,\n    int *minWidth,\n    int *minHeight)\n{\n    ThemeButtonParams *params = (ThemeButtonParams *)clientData;\n\n    if (params->heightMetric != NoThemeMetric) {\n\tChkErr(GetThemeMetric, params->heightMetric, minHeight);\n\n\t/*\n\t * The theme height does not include the 1-pixel border around\n\t * the button, although it does include the 1-pixel shadow at\n\t * the bottom.\n\t */\n\n\t*minHeight += 2;\n\n\t/*\n\t * For buttons with labels the minwidth must be 0 to force the\n\t * correct text layout.  For example, a non-zero value will cause the\n\t * text to be left justified, no matter what -anchor setting is used in\n\t * the style.\n\t */\n\n\tif (params->widthMetric != NoThemeMetric) {\n\t    ChkErr(GetThemeMetric, params->widthMetric, minWidth);\n\t    *minWidth += 2;\n\t    *minHeight += 2;\n\t} else {\n\t    *minWidth = 0;\n\t}\n    }\n}\n\nstatic void ButtonElementSize(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    int *minWidth,\n    int *minHeight,\n    Ttk_Padding *paddingPtr)\n{\n    ThemeButtonParams *params = (ThemeButtonParams *)clientData;\n    HIThemeButtonDrawInfo info =\n\tComputeButtonDrawInfo(params, 0, tkwin);\n    static const CGRect scratchBounds = {{0, 0}, {100, 100}};\n    CGRect contentBounds, backgroundBounds;\n    int verticalPad;\n\n    ButtonElementMinSize(clientData, minWidth, minHeight);\n    switch (info.kind) {\n    case TkSidebarButton:\n\t*paddingPtr = Ttk_MakePadding(30, 10, 30, 10);\n\treturn;\n    case TkGradientButton:\n\t*paddingPtr = Ttk_MakePadding(1, 1, 1, 1);\n\t/* Fall through. */\n    case kThemeArrowButton:\n    case kThemeRoundButtonHelp:\n\treturn;\n\t/* Buttons which are sized like PushButtons but unknown to HITheme. */\n    case TkRoundedRectButton:\n    case TkRecessedButton:\n    case TkInlineButton:\n\tinfo.kind = kThemePushButton;\n\tbreak;\n    default:\n\tbreak;\n    }\n\n    /*\n     * Given a hypothetical bounding rectangle for a button, HIToolbox will\n     * compute a bounding rectangle for the button contents and a bounding\n     * rectangle for the button background.  The background bounds are large\n     * enough to contain the image of the button in any state, which might\n     * include highlight borders, shadows, etc.  The content rectangle is not\n     * centered vertically within the background rectangle, presumably because\n     * shadows only appear on the bottom.  Nonetheless, when HIToolbox is asked\n     * to draw a button with a certain bounding rectangle it draws the button\n     * centered within the rectangle.\n     *\n     * To compute the effective padding around a button we request the\n     * content and bounding rectangles for a 100x100 button and use the\n     * padding between those.  However, we symmetrize the padding on the\n     * top and bottom, because that is how the button will be drawn.\n     */\n\n    ChkErr(HIThemeGetButtonContentBounds,\n\t&scratchBounds, &info, &contentBounds);\n    ChkErr(HIThemeGetButtonBackgroundBounds,\n\t&scratchBounds, &info, &backgroundBounds);\n    paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x;\n    paddingPtr->right =\n\tCGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds);\n    verticalPad = backgroundBounds.size.height - contentBounds.size.height;\n    paddingPtr->top = paddingPtr->bottom = verticalPad / 2;\n    if (info.kind == kThemePopupButton) {\n\tpaddingPtr->top += 1;\n\tpaddingPtr->bottom -= 1;\n    }\n}\n\nstatic void ButtonElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ThemeButtonParams *params = (ThemeButtonParams *)clientData;\n    CGRect bounds = BoxToRect(d, b);\n    HIThemeButtonDrawInfo info = ComputeButtonDrawInfo(params, state, tkwin);\n    bool isDark = TkMacOSXInDarkMode(tkwin);\n\n    switch (info.kind) {\n\n    /*\n     * A Gradient Button should have an image and no text.  The size is set to\n     * that of the image.  All we need to do is draw a 1-pixel border.\n     */\n\n    case TkGradientButton:\n\tBEGIN_DRAWING(d)\n\t    DrawGradientBorder(bounds, dc.context, tkwin, state);\n\tEND_DRAWING\n\treturn;\n    /*\n     * Buttons with no height restrictions are ready to draw.\n     */\n\n    case kThemeArrowButton:\n    case kThemeCheckBox:\n    case kThemeRadioButton:\n    case TkSidebarButton:\n\tbreak;\n\n    /*\n     * Other buttons have a maximum height.   We have to deal with that.\n     */\n\n    default:\n\tbounds = NormalizeButtonBounds(params, bounds, isDark);\n\tbreak;\n    }\n\n    /* We do our own drawing on new systems.*/\n\n    if ([NSApp macOSVersion] > 100800) {\n\tBEGIN_DRAWING(d)\n\tDrawButton(bounds, info, state, dc.context, tkwin);\n\tEND_DRAWING\n\treturn;\n    }\n\n    /*\n     * If execution reaches here it means we should use HIToolbox to draw the\n     * button.  Buttons that HIToolbox doesn't know are rendered as\n     * PushButtons.\n     */\n\n    switch (info.kind) {\n    case TkRoundedRectButton:\n    case TkRecessedButton:\n\tinfo.kind = kThemePushButton;\n\tbreak;\n    default:\n\tbreak;\n    }\n\n    /*\n     * Apple's PushButton and PopupButton do not change their fill color\n     * when the window is inactive.  However, except in 10.7 (Lion), the\n     * color of the arrow button on a PopupButton does change.  For some\n     * reason HITheme fills inactive buttons with a transparent color that\n     * allows the window background to show through, leading to\n     * inconsistent behavior.  We work around this by filling behind an\n     * inactive PopupButton with a text background color before asking\n     * HIToolbox to draw it. For PushButtons, we simply draw them in the\n     * active state.\n     */\n\n    BEGIN_DRAWING(d)\n    if (info.kind == kThemePopupButton  &&\n\t(state & TTK_STATE_BACKGROUND)) {\n\tCGRect innerBounds = CGRectInset(bounds, 1, 1);\n\tFillRoundedRectangle(dc.context, innerBounds, 4, CG_WHITE);\n    }\n\n    /*\n     * A BevelButton with mixed value is drawn borderless, which does make\n     * much sense for us.\n     */\n\n    if (info.kind == kThemeRoundedBevelButton &&\n\tinfo.value == kThemeButtonMixed) {\n\tinfo.value = kThemeButtonOff;\n\tinfo.state = kThemeStateInactive;\n    }\n    if (info.kind == kThemePushButton) {\n\tbounds.origin.y -= 2;\n    }\n    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,\n\t   NULL);\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec ButtonElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    ButtonElementSize,\n    ButtonElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Notebook elements.\n */\n\n/* Tab position logic, c.f. ttkNotebook.c TabState() */\nstatic const Ttk_StateTable TabStyleTable[] = {\n    {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND, 0},\n    {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND, 0},\n    {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED, 0},\n    {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED, 0},\n    {kThemeTabFront, TTK_STATE_SELECTED, 0},\n    {kThemeTabNonFrontPressed, TTK_STATE_PRESSED, 0},\n    {kThemeTabNonFront, 0, 0}\n};\nstatic const Ttk_StateTable TabAdornmentTable[] = {\n    {kHIThemeTabAdornmentNone, TTK_STATE_FIRST | TTK_STATE_LAST, 0},\n    {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST, 0},\n    {kHIThemeTabAdornmentNone, TTK_STATE_LAST, 0},\n    {kHIThemeTabAdornmentTrailingSeparator, 0, 0},\n};\nstatic const Ttk_StateTable TabPositionTable[] = {\n    {kHIThemeTabPositionOnly, TTK_STATE_FIRST | TTK_STATE_LAST, 0},\n    {kHIThemeTabPositionFirst, TTK_STATE_FIRST, 0},\n    {kHIThemeTabPositionLast, TTK_STATE_LAST, 0},\n    {kHIThemeTabPositionMiddle, 0, 0},\n};\n\n/*\n * Apple XHIG Tab View Specifications:\n *\n * Control sizes: Tab views are available in regular, small, and mini sizes.\n * The tab height is fixed for each size, but you control the size of the pane\n * area. The tab heights for each size are listed below:\n *  - Regular size: 20 pixels.\n *  - Small: 17 pixels.\n *  - Mini: 15 pixels.\n *\n * Label spacing and fonts: The tab labels should be in a font that’s\n * proportional to the size of the tab view control. In addition, the label\n * should be placed so that there are equal margins of space before and after\n * it. The guidelines below provide the specifications you should use for tab\n * labels:\n *  - Regular size: System font. Center in tab, leaving 12 pixels on each\n *side.\n *  - Small: Small system font. Center in tab, leaving 10 pixels on each side.\n *  - Mini: Mini system font. Center in tab, leaving 8 pixels on each side.\n *\n * Control spacing: Whether you decide to inset a tab view in a window or\n * extend its edges to the window sides and bottom, you should place the top\n * edge of the tab view 12 or 14 pixels below the bottom edge of the title bar\n * (or toolbar, if there is one). If you choose to inset a tab view in a\n * window, you should leave a margin of 20 pixels between the sides and bottom\n * of the tab view and the sides and bottom of the window (although 16 pixels\n * is also an acceptable margin-width). If you need to provide controls below\n * the tab view, leave enough space below the tab view so the controls are 20\n * pixels above the bottom edge of the window and 12 pixels between the tab\n * view and the controls.\n *\n * If you choose to extend the tab view sides and bottom so that they meet the\n * window sides and bottom, you should leave a margin of at least 20 pixels\n * between the content in the tab view and the tab-view edges.\n *\n * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/\n *       AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/\n *       TP30000359-TPXREF116>\n */\n\nstatic void TabElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    TCL_UNUSED(int *),     /* minWidth */\n    TCL_UNUSED(int *),     /* minHeight */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_MakePadding(0, -2, 0, 1);\n}\n\nstatic void TabElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] >= 110000) {\n\tDrawTab11(bounds, state, dc.context, tkwin);\n    } else if ([NSApp macOSVersion] > 100800) {\n\tDrawTab(bounds, state, dc.context, tkwin);\n    } else {\n\tHIThemeTabDrawInfo info = {\n\t    .version = 1,\n\t    .style = Ttk_StateTableLookup(TabStyleTable, state),\n\t    .direction = kThemeTabNorth,\n\t    .size = kHIThemeTabSizeNormal,\n\t    .adornment = Ttk_StateTableLookup(TabAdornmentTable, state),\n\t    .kind = kHIThemeTabKindNormal,\n\t    .position = Ttk_StateTableLookup(TabPositionTable, state),\n\t};\n\tChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation,\n\t    NULL);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec TabElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TabElementSize,\n    TabElementDraw\n};\n\n/*\n * Notebook panes:\n */\n\nstatic void PaneElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    TCL_UNUSED(int *),     /* minWidth */\n    TCL_UNUSED(int *),     /* minHeight */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_MakePadding(9, 5, 9, 9);\n}\n\nstatic void PaneElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n\n    bounds.origin.y -= kThemeMetricTabFrameOverlap;\n    bounds.size.height += kThemeMetricTabFrameOverlap;\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tDrawGroupBox(bounds, dc.context, tkwin, 1, YES);\n    } else {\n\tHIThemeTabPaneDrawInfo info = {\n\t    .version = 1,\n\t    .state = Ttk_StateTableLookup(ThemeStateTable, state),\n\t    .direction = kThemeTabNorth,\n\t    .size = kHIThemeTabSizeNormal,\n\t    .kind = kHIThemeTabKindNormal,\n\t    .adornment = kHIThemeTabPaneAdornmentNormal,\n\t    };\n\tbounds.origin.y -= kThemeMetricTabFrameOverlap;\n\tbounds.size.height += kThemeMetricTabFrameOverlap;\n\tChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec PaneElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    PaneElementSize,\n    PaneElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Labelframe elements --\n *\n * Labelframe borders: Use \"primary group box ...\"  Quoth\n * DrawThemePrimaryGroup reference: \"The primary group box frame is drawn\n * inside the specified rectangle and is a maximum of 2 pixels thick.\"\n *\n */\n\nstatic void GroupElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    TCL_UNUSED(int *),     /* minWidth */\n    TCL_UNUSED(int *),     /* minHeight */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_MakePadding(0, 0, 0, 0);\n}\n\nstatic void GroupElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tDrawGroupBox(bounds, dc.context, tkwin, 1, YES);\n    } else {\n\tconst HIThemeGroupBoxDrawInfo info = {\n\t    .version = 0,\n\t    .state = Ttk_StateTableLookup(ThemeStateTable, state),\n\t    .kind = kHIThemeGroupBoxKindPrimaryOpaque,\n\t    };\n\tChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec GroupElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    GroupElementSize,\n    GroupElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Entry elements --\n *\n *    3 pixels padding for focus rectangle\n *    2 pixels padding for EditTextFrame\n */\n\ntypedef struct {\n    Tcl_Obj     *backgroundObj;\n    Tcl_Obj     *fieldbackgroundObj;\n} EntryElement;\n\n#define ENTRY_DEFAULT_BACKGROUND \"systemTextBackgroundColor\"\n\nstatic Ttk_ElementOptionSpec EntryElementOptions[] = {\n    {\"-background\", TK_OPTION_BORDER,\n     offsetof(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},\n    {\"-fieldbackground\", TK_OPTION_BORDER,\n     offsetof(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\n\nstatic void EntryElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    TCL_UNUSED(int *),     /* minWidth */\n    TCL_UNUSED(int *),     /* minHeight */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = entryElementPadding;\n}\n\nstatic void EntryElementDraw(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    EntryElement *e = (EntryElement *)elementRecord;\n    ThemeFrameParams *params = (ThemeFrameParams *)clientData;\n    HIThemeFrameKind kind = params ? params->kind :\n\tkHIThemeFrameTextFieldSquare;\n    CGRect bounds = BoxToRect(d, b);\n    CGColorRef background;\n    Tk_3DBorder backgroundPtr = NULL;\n    static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND;\n\n    if ([NSApp macOSVersion] > 100800) {\n\tBEGIN_DRAWING(d)\n\t    switch(kind) {\n\t    case kHIThemeFrameTextFieldRound:\n\t\tDrawEntry(dc.context, bounds, &searchDesign, state, tkwin);\n\t\tbreak;\n\t    case kHIThemeFrameTextFieldSquare:\n\t\tDrawEntry(dc.context, bounds, &entryDesign, state, tkwin);\n\t\tbreak;\n\t    default:\n\t\treturn;\n\t    }\n\tEND_DRAWING\n    } else {\n\tconst HIThemeFrameDrawInfo info = {\n\t    .version = 0,\n\t    .kind = params->kind,\n\t    .state = Ttk_StateTableLookup(ThemeStateTable, state),\n\t    .isFocused = state & TTK_STATE_FOCUS,\n\t};\n\n\t/*\n\t * Earlier versions of the Aqua theme ignored the -fieldbackground\n\t * option and used the -background as if it were -fieldbackground.\n\t * Here we are enabling -fieldbackground.  For backwards\n\t * compatibility, if -fieldbackground is set to the default color and\n\t * -background is set to a different color then we use -background as\n\t * -fieldbackground.\n\t */\n\n\tif (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) {\n\t    backgroundPtr =\n\t\tTk_Get3DBorderFromObj(tkwin, e->fieldbackgroundObj);\n\t} else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) {\n\t    backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);\n\t}\n\tif (backgroundPtr != NULL) {\n\t    XFillRectangle(Tk_Display(tkwin), d,\n\t\tTk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),\n\t\tb.x, b.y, b.width, b.height);\n\t}\n\tBEGIN_DRAWING(d)\n\tif (backgroundPtr == NULL) {\n\t    if ([NSApp macOSVersion] > 100800) { // unreachable?\n\t\tbackground = TkMacOSXGetCGColorFromNSColorUsingAppearance([NSColor textBackgroundColor], TkMacOSXInDarkMode(tkwin));\n\t\tCGContextSetFillColorWithColor(dc.context, background);\n\t    } else {\n\t\tCGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0);\n\t    }\n\t    CGContextFillRect(dc.context, bounds);\n\t}\n\tChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);\n\tEND_DRAWING\n    }\n}\n\nstatic Ttk_ElementSpec EntryElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(EntryElement),\n    EntryElementOptions,\n    EntryElementSize,\n    EntryElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Combobox elements --\n *\n * NOTES:\n *      The HIToolbox has incomplete and inconsistent support for ComboBoxes.\n *      There is no constant available to get the height of a ComboBox with\n *      GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as\n *      PopupButtons and PushButtons, but they have no shadow at the bottom.\n *      As a result, they are drawn 1 pixel above the center of the bounds\n *      rectangle rather than being centered like the other buttons.  One can\n *      request background bounds for a ComboBox, and it is reported with\n *      height 23, while the actual button face, including its 1-pixel border\n *      has height 21. Attempting to request the content bounds returns a 0x0\n *      rectangle.  Measurement indicates that the arrow button has width 18.\n *\n *      With no help available from HIToolbox, we have to use hard-wired\n *      constants for the padding. We shift the bounding rectangle downward by\n *      1 pixel to account for the fact that the button is not centered.\n */\n\n// OS dependent ???\nstatic Ttk_Padding ComboboxPadding = {7, 5, 24, 5};\n\nstatic void ComboboxElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    Ttk_Padding *paddingPtr)\n{\n    *minWidth = 24;\n    *minHeight = 0;\n    *paddingPtr = ComboboxPadding;\n}\n\nstatic void ComboboxElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n    const HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.state = Ttk_StateTableLookup(ThemeStateTable, state),\n\t.kind = kThemeComboBox,\n\t.value = Ttk_StateTableLookup(ButtonValueTable, state),\n\t.adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state),\n    };\n\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tbounds = CGRectInset(bounds, -1, -1);\n\tDrawButton(bounds, info, state, dc.context, tkwin);\n    } else {\n\tbounds.origin.y += 1;\n\tChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,\n\t       NULL);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec ComboboxElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    ComboboxElementSize,\n    ComboboxElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Spinbutton elements --\n *\n *      From Apple HIG, part III, section \"Controls\", \"The Stepper Control\":\n *      there should be 2 pixels of space between the stepper control (AKA\n *      IncDecButton, AKA \"little arrows\") and the text field it modifies.\n *\n *      Ttk expects the up and down arrows to be distinct elements but\n *      HIToolbox draws them as one widget with two different pressed states.\n *      We work around this by defining them as separate elements in the\n *      layout, but making each one have a drawing method which also draws the\n *      other one.  The down button does no drawing when not pressed, and when\n *      pressed draws the entire IncDecButton in its \"pressed down\" state.\n *      The up button draws the entire IncDecButton when not pressed and when\n *      pressed draws the IncDecButton in its \"pressed up\" state.  NOTE: This\n *      means that when the down button is pressed the IncDecButton will be\n *      drawn twice, first in unpressed state by the up arrow and then in\n *      \"pressed down\" state by the down button.  The drawing must be done in\n *      that order.  So the up button must be listed first in the layout.\n */\n\nstatic Ttk_Padding SpinbuttonMargins = {2, 0, 0, 0};\n\nstatic void SpinButtonReBounds(\n    Tk_Window tkwin,\n    CGRect *bounds)\n{\n    if (TkMacOSXInDarkMode(tkwin)) {\n\tbounds->origin.x -= 2;\n\tbounds->origin.y += 1;\n\tbounds->size.height -= 0.5;\n    } else {\n\tbounds->origin.x -= 3;\n\tbounds->origin.y += 1;\n\tbounds->size.width += 1;\n    }\n}\n\nstatic void SpinButtonElementSize(\n    TCL_UNUSED(void *),       /* clientdata */\n    TCL_UNUSED(void *),       /* elementRecord */\n    TCL_UNUSED(Tk_Window),    /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* PaddingPtr */\n{\n    SInt32 s;\n\n    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);\n    *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);\n    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);\n    *minHeight = 2 + (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;\n}\n\nstatic void SpinButtonUpElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));\n    int infoState;\n\n    SpinButtonReBounds(tkwin, &bounds);\n    bounds.size.height *= 2;\n    if (state & TTK_STATE_PRESSED) {\n\tinfoState = kThemeStatePressedUp;\n    } else {\n\tinfoState = Ttk_StateTableLookup(ThemeStateTable, state);\n    }\n    const HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.state = infoState,\n\t.kind = kThemeIncDecButton,\n\t.value = Ttk_StateTableLookup(ButtonValueTable, state),\n\t.adornment = kThemeAdornmentNone,\n    };\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tDrawButton(bounds, info, state, dc.context, tkwin);\n    } else {\n\tChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,\n\t       NULL);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec SpinButtonUpElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SpinButtonElementSize,\n    SpinButtonUpElementDraw\n};\n\nstatic void SpinButtonDownElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));\n    int infoState = 0;\n\n    SpinButtonReBounds(tkwin, &bounds);\n    bounds.origin.y -= bounds.size.height;\n    bounds.size.height += bounds.size.height;\n    if (state & TTK_STATE_PRESSED) {\n\tinfoState = kThemeStatePressedDown;\n    } else {\n\treturn;\n    }\n    const HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.state = infoState,\n\t.kind = kThemeIncDecButton,\n\t.value = Ttk_StateTableLookup(ButtonValueTable, state),\n\t.adornment = kThemeAdornmentNone,\n    };\n\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tDrawButton(bounds, info, state, dc.context, tkwin);\n    } else {\n\tChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,\n\t       NULL);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec SpinButtonDownElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SpinButtonElementSize,\n    SpinButtonDownElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ DrawThemeTrack-based elements --\n *\n *    Progress bars and scales. (See also: <<NOTE-TRACKS>>)\n */\n\n/*\n * Apple does not change the appearance of a slider when the window becomes\n * inactive.  So we shouldn't either.\n */\n\nstatic const Ttk_StateTable ThemeTrackEnableTable[] = {\n    {kThemeTrackDisabled, TTK_STATE_DISABLED, 0},\n    {kThemeTrackActive, TTK_STATE_BACKGROUND, 0},\n    {kThemeTrackActive, 0, 0}\n    /* { kThemeTrackNothingToScroll, ?, ? }, */\n};\n\ntypedef struct {        /* TrackElement client data */\n    ThemeTrackKind kind;\n    SInt32 thicknessMetric;\n} TrackElementData;\n\nstatic TrackElementData ScaleData = {\n    kThemeSlider, kThemeMetricHSliderHeight\n};\n\ntypedef struct {\n    Tcl_Obj *fromObj;           /* minimum value */\n    Tcl_Obj *toObj;             /* maximum value */\n    Tcl_Obj *valueObj;          /* current value */\n    Tcl_Obj *orientObj;         /* horizontal / vertical */\n} TrackElement;\n\nstatic Ttk_ElementOptionSpec TrackElementOptions[] = {\n    {\"-from\", TK_OPTION_DOUBLE, offsetof(TrackElement, fromObj), NULL},\n    {\"-to\", TK_OPTION_DOUBLE, offsetof(TrackElement, toObj), NULL},\n    {\"-value\", TK_OPTION_DOUBLE, offsetof(TrackElement, valueObj), NULL},\n    {\"-orient\", TK_OPTION_STRING, offsetof(TrackElement, orientObj), NULL},\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\nstatic void TrackElementSize(\n    void *clientData,\n    TCL_UNUSED(void *),       /* elementRecord */\n    TCL_UNUSED(Tk_Window),    /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    TrackElementData *data = (TrackElementData *)clientData;\n    SInt32 size = 24;   /* reasonable default ... */\n\n    ChkErr(GetThemeMetric, data->thicknessMetric, &size);\n    *minWidth = *minHeight = size;\n}\n\nstatic void TrackElementDraw(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    TrackElementData *data = (TrackElementData *)clientData;\n    TrackElement *elem = (TrackElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n    double from = 0, to = 100, value = 0, fraction, max;\n    CGRect bounds = BoxToRect(d, b);\n\n    Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation);\n    Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);\n    Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);\n    Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);\n\n    fraction = (value - from) / (to - from);\n    max = RangeToFactor(fabs(to - from));\n    HIThemeTrackDrawInfo info = {\n\t.version = 0,\n\t.kind = data->kind,\n\t.bounds = bounds,\n\t.min = 0,\n\t.max = max,\n\t.value = fraction * max,\n\t.attributes = kThemeTrackShowThumb |\n\t    (orientation == TTK_ORIENT_HORIZONTAL ?\n\t    kThemeTrackHorizontal : 0),\n\t.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),\n\t.trackInfo.progress.phase = 0\n    };\n\n    if (info.kind == kThemeSlider) {\n\tinfo.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ?\n\t    kThemeThumbPressed : 0;\n\tif (state & TTK_STATE_ALTERNATE) {\n\t    info.trackInfo.slider.thumbDir = kThemeThumbDownward;\n\t} else {\n\t    info.trackInfo.slider.thumbDir = kThemeThumbPlain;\n\t}\n    }\n    BEGIN_DRAWING(d)\n    if (([NSApp macOSVersion] > 100800) && !(state & TTK_STATE_ALTERNATE)) {\n\n\t/*\n\t * We use the reserved field to indicate whether \"from\" is less than\n\t * \"to\".  It should be 0 if passing the info to HIThemeDrawInfo, but\n\t * we aren't doing that.\n\t */\n\n\tinfo.reserved = (from < to);\n\tDrawSlider(dc.context, bounds, info, state, tkwin);\n    } else {\n\tChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec TrackElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TrackElement),\n    TrackElementOptions,\n    TrackElementSize,\n    TrackElementDraw\n};\n\n/*----------------------------------------------------------------------\n * Slider elements -- <<NOTE-TRACKS>>\n *\n * Has geometry only. The Scale widget adjusts the position of this element,\n * and uses it for hit detection. In the Aqua theme, the slider is actually\n * drawn as part of the trough element.\n *\n */\n\nstatic void SliderElementSize(\n    TCL_UNUSED(void *),        /* clientData */\n    TCL_UNUSED(void *),        /* elementRecord */\n    TCL_UNUSED(Tk_Window),     /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    *minWidth = *minHeight = 24;\n}\n\nstatic Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SliderElementSize,\n    TtkNullElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Progress bar elements --\n *\n * @@@ NOTE: According to an older revision of the Aqua reference docs,\n * @@@ the 'phase' field is between 0 and 4. Newer revisions say\n * @@@ that it can be any UInt8 value.\n */\n\ntypedef struct {\n    Tcl_Obj *orientObj;         /* horizontal / vertical */\n    Tcl_Obj *valueObj;          /* current value */\n    Tcl_Obj *maximumObj;        /* maximum value */\n    Tcl_Obj *phaseObj;          /* animation phase */\n    Tcl_Obj *modeObj;           /* progress bar mode */\n} PbarElement;\n\nstatic Ttk_ElementOptionSpec PbarElementOptions[] = {\n    {\"-orient\", TK_OPTION_STRING,\n     offsetof(PbarElement, orientObj), \"horizontal\"},\n    {\"-value\", TK_OPTION_DOUBLE,\n     offsetof(PbarElement, valueObj), \"0.0\"},\n    {\"-maximum\", TK_OPTION_DOUBLE,\n     offsetof(PbarElement, maximumObj), \"100.0\"},\n    {\"-phase\", TK_OPTION_INT,\n     offsetof(PbarElement, phaseObj), \"0\"},\n    {\"-mode\", TK_OPTION_STRING,\n     offsetof(PbarElement, modeObj), \"determinate\"},\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\nstatic void PbarElementSize(\n    TCL_UNUSED(void *),        /* clientData */\n    TCL_UNUSED(void *),        /* elementRecord */\n    TCL_UNUSED(Tk_Window),     /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    SInt32 size = 24;           /* @@@ Check HIG for correct default */\n\n    ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size);\n    *minWidth = *minHeight = size;\n}\n\nstatic void PbarElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    PbarElement *pbar = (PbarElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n    int phase;\n    double value = 0, maximum = 100, factor;\n    CGRect bounds = BoxToRect(d, b);\n    bool isIndeterminate = !strcmp(\"indeterminate\",\n\t\t\t\t  Tcl_GetString(pbar->modeObj));\n\n    Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation);\n    Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value);\n    Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum);\n    Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase);\n\n    if (isIndeterminate) {\n\n\t/*\n\t * When an indeterminate progress bar is animated the phase is\n\t * (currently) always 0 and the value increases from min to max\n\t * and then decreases back to min.  We scale the value by 3 to\n\t * speed the animation up a bit.\n\t */\n\n\tdouble remainder = fmod(3*value, 2*maximum);\n\tvalue = remainder > maximum ? 2*maximum - remainder : remainder;\n    }\n    factor = RangeToFactor(maximum);\n    HIThemeTrackDrawInfo info = {\n\t.version = 0,\n\t.kind = isIndeterminate? kThemeIndeterminateBar : kThemeProgressBar,\n\t.bounds = bounds,\n\t.min = 0,\n\t.max = maximum * factor,\n\t.value = value * factor,\n\t.attributes = kThemeTrackShowThumb |\n\t    (orientation == TTK_ORIENT_HORIZONTAL ?\n\t    kThemeTrackHorizontal : 0),\n\t.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),\n\t.trackInfo.progress.phase = phase,\n    };\n\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tDrawProgressBar(dc.context, bounds, info, state, tkwin);\n    } else {\n\tChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec PbarElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(PbarElement),\n    PbarElementOptions,\n    PbarElementSize,\n    PbarElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Scrollbar elements\n */\n\ntypedef struct\n{\n    Tcl_Obj *orientObj;\n} ScrollbarElement;\n\nstatic Ttk_ElementOptionSpec ScrollbarElementOptions[] = {\n    {\"-orient\", TK_OPTION_STRING,\n     offsetof(ScrollbarElement, orientObj), \"horizontal\"},\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\nstatic void TroughElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    void *elementRecord,\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    Ttk_Padding *paddingPtr)\n{\n    ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n    SInt32 thickness = 15;\n\n    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);\n    ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness);\n    if (orientation == TTK_ORIENT_HORIZONTAL) {\n\t*minHeight = thickness;\n\tif ([NSApp macOSVersion] > 100700) {\n\t    *paddingPtr = Ttk_MakePadding(4, 4, 4, 3);\n\t}\n    } else {\n\t*minWidth = thickness;\n\tif ([NSApp macOSVersion] > 100700) {\n\t    *paddingPtr = Ttk_MakePadding(4, 4, 3, 4);\n\t}\n    }\n}\n\nstatic void TroughElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State)) /* state */\n{\n    ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n    CGRect bounds = BoxToRect(d, b);\n    GrayColor bgGray;\n\n    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);\n    if (orientation == TTK_ORIENT_HORIZONTAL) {\n\tbounds = CGRectInset(bounds, 0, 1);\n    } else {\n\tbounds = CGRectInset(bounds, 1, 0);\n    }\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\tbgGray = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough;\n\tCGContextSetFillColorWithColor(dc.context, CGColorFromGray(bgGray));\n    } else {\n\tChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL,\n\t    dc.context, HIOrientation);\n    }\n    CGContextFillRect(dc.context, bounds);\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec TroughElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    TroughElementSize,\n    TroughElementDraw\n};\nstatic void ThumbElementSize(\n    TCL_UNUSED(void *),        /* clientData */\n    void *elementRecord,\n    TCL_UNUSED(Tk_Window),     /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n\n    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);\n    if (orientation == TTK_ORIENT_VERTICAL) {\n\t*minHeight = 18;\n\t*minWidth = 8;\n    } else {\n\t*minHeight = 8;\n\t*minWidth = 18;\n    }\n}\n\nstatic void ThumbElementDraw(\n    TCL_UNUSED(void *),        /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord;\n    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;\n\n    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);\n\n    /*\n     * In order to make ttk scrollbars work correctly it is necessary to be\n     * able to display the thumb element at the size and location which the ttk\n     * scrollbar widget requests.  The algorithm that HIToolbox uses to\n     * determine the thumb geometry from the input values of min, max, value\n     * and viewSize is undocumented.  A seemingly natural algorithm is\n     * implemented below.  This code uses that algorithm for older OS versions,\n     * because using HIToolbox also handles drawing the buttons and 3D thumb used\n     * on those systems.  For newer systems the cleanest approach is to just\n     * draw the thumb directly.\n     */\n\n    if ([NSApp macOSVersion] > 100800) {\n\tCGRect thumbBounds = BoxToRect(d, b);\n\tCGColorRef thumbColor;\n\tGrayColor bgGray;\n\n\t/*\n\t * Apple does not draw the thumb when scrolling is not possible.\n\t */\n\n\tif ((orientation == TTK_ORIENT_HORIZONTAL &&\n\t    thumbBounds.size.width >= Tk_Width(tkwin) - 8) ||\n\t    (orientation == TTK_ORIENT_VERTICAL &&\n\t    thumbBounds.size.height >= Tk_Height(tkwin) - 8)) {\n\t    return;\n\t}\n\tbool isDark = TkMacOSXInDarkMode(tkwin);\n\tif ((state & TTK_STATE_PRESSED) ||\n\t    (state & TTK_STATE_HOVER)) {\n\t    bgGray = isDark ? darkActiveThumb : lightActiveThumb;\n\t} else {\n\t    bgGray = isDark ? darkInactiveThumb : lightInactiveThumb;\n\t}\n\tthumbColor = CGColorFromGray(bgGray);\n\tBEGIN_DRAWING(d)\n\tFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor);\n\tEND_DRAWING\n    } else {\n\tdouble thumbSize, trackSize, visibleSize, factor, fraction;\n\tMacDrawable *macWin = (MacDrawable *)Tk_WindowId(tkwin);\n\tCGRect troughBounds = {{macWin->xOff, macWin->yOff},\n\t\t\t       {Tk_Width(tkwin), Tk_Height(tkwin)}};\n\n\t/*\n\t * The info struct has integer fields, which will be converted to\n\t * floats in the drawing routine.  All of values provided in the info\n\t * struct, namely min, max, value, and viewSize are only defined up to\n\t * an arbitrary scale factor.  To avoid roundoff error we scale so\n\t * that the viewSize is a large float which is smaller than the\n\t * largest int.\n\t */\n\n\tHIThemeTrackDrawInfo info = {\n\t    .version = 0,\n\t    .bounds = troughBounds,\n\t    .min = 0,\n\t    .attributes = kThemeTrackShowThumb |\n\t\tkThemeTrackThumbRgnIsNotGhost,\n\t    .enableState = kThemeTrackActive\n\t};\n\tfactor = RangeToFactor(100.0);\n\tif (orientation == TTK_ORIENT_HORIZONTAL) {\n\t    trackSize = troughBounds.size.width;\n\t    thumbSize = b.width;\n\t    fraction = b.x / trackSize;\n\t} else {\n\t    trackSize = troughBounds.size.height;\n\t    thumbSize = b.height;\n\t    fraction = b.y / trackSize;\n\t}\n\tvisibleSize = (thumbSize / trackSize) * factor;\n\tinfo.max = factor - visibleSize;\n\tinfo.trackInfo.scrollbar.viewsize = visibleSize;\n\tif ([NSApp macOSVersion] < 100800 ||\n\t    orientation == TTK_ORIENT_HORIZONTAL) {\n\t    info.value = factor * fraction;\n\t} else {\n\t    info.value = info.max - factor * fraction;\n\t}\n\tif ((state & TTK_STATE_PRESSED) ||\n\t    (state & TTK_STATE_HOVER)) {\n\t    info.trackInfo.scrollbar.pressState = kThemeThumbPressed;\n\t} else {\n\t    info.trackInfo.scrollbar.pressState = 0;\n\t}\n\tif (orientation == TTK_ORIENT_HORIZONTAL) {\n\t    info.attributes |= kThemeTrackHorizontal;\n\t} else {\n\t    info.attributes &= ~kThemeTrackHorizontal;\n\t}\n\tBEGIN_DRAWING(d)\n\tHIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal);\n\tEND_DRAWING\n    }\n}\n\nstatic Ttk_ElementSpec ThumbElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    ThumbElementSize,\n    ThumbElementDraw\n};\nstatic void ArrowElementSize(\n    TCL_UNUSED(void *),        /* clientData */\n    TCL_UNUSED(void *),        /* elementRecord */\n    TCL_UNUSED(Tk_Window),     /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    if ([NSApp macOSVersion] < 100800) {\n\t*minHeight = *minWidth = 14;\n    } else {\n\t*minHeight = *minWidth = -1;\n    }\n}\n\nstatic Ttk_ElementSpec ArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ScrollbarElement),\n    ScrollbarElementOptions,\n    ArrowElementSize,\n    TtkNullElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Separator element.\n *\n *    DrawThemeSeparator() guesses the orientation of the line from the width\n *    and height of the rectangle, so the same element can can be used for\n *    horizontal, vertical, and general separators.\n */\n\nstatic void SeparatorElementSize(\n    TCL_UNUSED(void *),       /* clientData */\n    TCL_UNUSED(void *),       /* elementRecord */\n    TCL_UNUSED(Tk_Window),    /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    *minWidth = *minHeight = 1;\n}\n\nstatic void SeparatorElementDraw(\n    TCL_UNUSED(void *),       /* clientData */\n    TCL_UNUSED(void *),       /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n    const HIThemeSeparatorDrawInfo info = {\n\t.version = 0,\n\t/* Separator only supports kThemeStateActive, kThemeStateInactive */\n\t.state = Ttk_StateTableLookup(ThemeStateTable,\n\t    state & TTK_STATE_BACKGROUND),\n    };\n\n    BEGIN_DRAWING(d)\n    if (TkMacOSXInDarkMode(tkwin)) {\n\tDrawDarkSeparator(bounds, dc.context, tkwin);\n    } else {\n\tChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context,\n\t    HIOrientation);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec SeparatorElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SeparatorElementSize,\n    SeparatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Size grip elements -- (obsolete)\n */\n\nstatic const ThemeGrowDirection sizegripGrowDirection\n    = kThemeGrowRight | kThemeGrowDown;\n\nstatic void SizegripElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    HIThemeGrowBoxDrawInfo info = {\n\t.version = 0,\n\t.state = kThemeStateActive,\n\t.kind = kHIThemeGrowBoxKindNormal,\n\t.direction = sizegripGrowDirection,\n\t.size = kHIThemeGrowBoxSizeNormal,\n    };\n    CGRect bounds = CGRectZero;\n\n    ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds);\n    *minWidth = bounds.size.width;\n    *minHeight = bounds.size.height;\n}\n\nstatic void SizegripElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n    HIThemeGrowBoxDrawInfo info = {\n\t.version = 0,\n\t/* Grow box only supports kThemeStateActive, kThemeStateInactive */\n\t.state = Ttk_StateTableLookup(ThemeStateTable,\n\t    state & TTK_STATE_BACKGROUND),\n\t.kind = kHIThemeGrowBoxKindNormal,\n\t.direction = sizegripGrowDirection,\n\t.size = kHIThemeGrowBoxSizeNormal,\n    };\n\n    BEGIN_DRAWING(d)\n    ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context,\n\tHIOrientation);\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec SizegripElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SizegripElementSize,\n    SizegripElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Background and fill elements --\n *\n *      Before drawing any ttk widget, its bounding rectangle is filled with a\n *      background color.  This color must match the background color of the\n *      containing widget to avoid looking ugly. The need for care when doing\n *      this is exacerbated by the fact that ttk enforces its \"native look\" by\n *      not allowing user control of the background or highlight colors of ttk\n *      widgets.\n *\n *      This job is made more complicated in recent versions of macOS by the\n *      fact that the Appkit GroupBox (used for ttk LabelFrames) and\n *      TabbedPane (used for the Notebook widget) both place their content\n *      inside a rectangle with rounded corners that has a color which\n *      contrasts with the dialog background color.  Moreover, although the\n *      Apple human interface guidelines recommend against doing so, there are\n *      times when one wants to nest these widgets, for example placing a\n *      GroupBox inside of a TabbedPane.  To have the right contrast, each\n *      level of nesting requires a different color.\n *\n *      Previous Tk releases used the HIThemeDrawGroupBox routine to draw\n *      GroupBoxes and TabbedPanes. This meant that the best that could be\n *      done was to set the GroupBox to be of kind\n *      kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the\n *      system background color.  If widgets inside the box were drawn with\n *      the system background color the backgrounds would match.  But this\n *      produces a GroupBox with no contrast, the only visual clue being a\n *      faint highlighting around the top of the GroupBox.  Moreover, the\n *      TabbedPane does not have an Opaque version, so while it is drawn\n *      inside a contrasting rounded rectangle, the widgets inside the pane\n *      needed to be enclosed in a frame with the system background\n *      color. This added a visual artifact since the frame's background color\n *      does not match the Pane's background color.  That code has now been\n *      replaced with the standalone drawing procedure macOSXDrawGroupBox,\n *      which draws a rounded rectangle with an appropriate contrasting\n *      background color.\n *\n *      Patterned backgrounds, which are now obsolete, should be aligned with\n *      the coordinate system of the top-level window.  Apparently failing to\n *      do this used to cause graphics anomalies when drawing into an\n *      off-screen graphics port.  The code for handling this is currently\n *      commented out.\n */\n\nstatic void FillElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    CGRect bounds = BoxToRect(d, b);\n\n    if ([NSApp macOSVersion] > 100800) {\n\tCGColorRef bgColor;\n\tBEGIN_DRAWING(d)\n\tbgColor = GetBackgroundCGColor(dc.context, tkwin, NO, 0);\n\tCGContextSetFillColorWithColor(dc.context, bgColor);\n\tCGContextFillRect(dc.context, bounds);\n\tEND_DRAWING\n    } else {\n\tThemeBrush brush = (state & TTK_STATE_BACKGROUND)\n\t    ? kThemeBrushModelessDialogBackgroundInactive\n\t    : kThemeBrushModelessDialogBackgroundActive;\n\tBEGIN_DRAWING(d)\n\tChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);\n\tCGContextFillRect(dc.context, bounds);\n\tEND_DRAWING\n    }\n}\n\nstatic void BackgroundElementDraw(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    TCL_UNUSED(Ttk_Box),\n    Ttk_State state)\n{\n    FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin),\n\tstate);\n}\n\nstatic Ttk_ElementSpec FillElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TtkNullElementSize,\n    FillElementDraw\n};\nstatic Ttk_ElementSpec BackgroundElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TtkNullElementSize,\n    BackgroundElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ ToolbarBackground element -- toolbar style for frames.\n *\n *    This is very similar to the normal background element, but uses a\n *    different ThemeBrush in order to get the lighter pinstripe effect\n *    used in toolbars. We use SetThemeBackground() rather than\n *    ApplyThemeBackground() in order to get the right style.\n *\n *    <URL: http://developer.apple.com/documentation/Carbon/Reference/\n *    Appearance_Manager/appearance_manager/constant_7.html#/\n *    /apple_ref/doc/uid/TP30000243/C005321>\n *\n */\n\nstatic void ToolbarBackgroundElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    TCL_UNUSED(Ttk_Box),\n    TCL_UNUSED(Ttk_State))\n{\n    ThemeBrush brush = kThemeBrushToolbarBackground;\n    CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin));\n\n    BEGIN_DRAWING(d)\n    ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);\n    //QDSetPatternOrigin(PatternOrigin(tkwin, d));\n    CGContextFillRect(dc.context, bounds);\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec ToolbarBackgroundElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TtkNullElementSize,\n    ToolbarBackgroundElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Field elements --\n *\n *      Used for the Treeview widget. This is like the BackgroundElement\n *      except that the fieldbackground color is configurable.\n */\n\ntypedef struct {\n    Tcl_Obj     *backgroundObj;\n} FieldElement;\n\nstatic Ttk_ElementOptionSpec FieldElementOptions[] = {\n    {\"-fieldbackground\", TK_OPTION_BORDER,\n     offsetof(FieldElement, backgroundObj), \"white\"},\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\n\nstatic void FieldElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    FieldElement *e = (FieldElement *)elementRecord;\n    Tk_3DBorder backgroundPtr =\n\tTk_Get3DBorderFromObj(tkwin, e->backgroundObj);\n\n    XFillRectangle(Tk_Display(tkwin), d,\n\tTk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),\n\tb.x, b.y, b.width, b.height);\n}\n\nstatic Ttk_ElementSpec FieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    TtkNullElementSize,\n    FieldElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Treeview headers --\n *\n *    On systems older than 10.9 the header is a kThemeListHeaderButton drawn\n *    by HIToolbox.  On newer systems those buttons do not match the Apple\n *    buttons, so we draw them from scratch.\n */\n\nstatic const Ttk_StateTable TreeHeaderValueTable[] = {\n    {kThemeButtonOn, TTK_STATE_ALTERNATE, 0},\n    {kThemeButtonOn, TTK_STATE_SELECTED, 0},\n    {kThemeButtonOff, 0, 0}\n};\n\nstatic const Ttk_StateTable TreeHeaderAdornmentTable[] = {\n    {kThemeAdornmentHeaderButtonSortUp,\n     TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW, 0},\n    {kThemeAdornmentDefault,\n     TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW, 0},\n    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE, 0},\n    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED, 0},\n    {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0},\n    {kThemeAdornmentNone, 0, 0}\n};\n\nstatic void TreeAreaElementSize (\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    TCL_UNUSED(int *),     /* minWidth */\n    TCL_UNUSED(int *),     /* minHeight */\n    Ttk_Padding *paddingPtr)\n{\n\n    /*\n     * Padding is needed to get the heading text to align correctly, since the\n     * widget expects the heading to be the same height as a row.\n     */\n\n    if ([NSApp macOSVersion] > 100800) {\n\t*paddingPtr = Ttk_MakePadding(0, 4, 0, 0);\n    }\n}\n\nstatic Ttk_ElementSpec TreeAreaElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TreeAreaElementSize,\n    TtkNullElementDraw\n};\nstatic void TreeHeaderElementSize(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *minWidth,\n    int *minHeight,\n    Ttk_Padding *paddingPtr)\n{\n    if ([NSApp macOSVersion] > 100800) {\n\t*minHeight = 24;\n    } else {\n\tButtonElementSize(clientData, elementRecord, tkwin, minWidth,\n\t    minHeight, paddingPtr);\n    }\n}\n\nstatic void TreeHeaderElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ThemeButtonParams *params = (ThemeButtonParams *)clientData;\n    CGRect bounds = BoxToRect(d, b);\n    const HIThemeButtonDrawInfo info = {\n\t.version = 0,\n\t.state = Ttk_StateTableLookup(ThemeStateTable, state),\n\t.kind = params->kind,\n\t.value = Ttk_StateTableLookup(TreeHeaderValueTable, state),\n\t.adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state),\n    };\n\n    BEGIN_DRAWING(d)\n    if ([NSApp macOSVersion] > 100800) {\n\n\t/*\n\t * Compensate for the padding added in TreeHeaderElementSize, so\n\t * the larger heading will be drawn at the top of the widget.\n\t */\n\n\tbounds.origin.y -= 4;\n\tDrawListHeader(bounds, dc.context, tkwin, state);\n    } else {\n\tChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,\n\t    NULL);\n    }\n    END_DRAWING\n}\n\nstatic Ttk_ElementSpec TreeHeaderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TreeHeaderElementSize,\n    TreeHeaderElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Disclosure element --\n */\n\nstatic void DisclosureElementSize(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    TCL_UNUSED(Tk_Window), /* tkwin */\n    int *minWidth,\n    int *minHeight,\n    TCL_UNUSED(Ttk_Padding *)) /* paddingPtr */\n{\n    SInt32 s;\n\n    ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s);\n    *minWidth = s;\n    ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s);\n    *minHeight = s;\n}\n\nstatic void DisclosureElementDraw(\n    TCL_UNUSED(void *),    /* clientData */\n    TCL_UNUSED(void *),    /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    if (!(state & TTK_STATE_LEAF)) {\n\t/*\n\t * The treeview uses the TTK_STATE_BACKGROUND state for\n\t * selected items when the widget has lost the focus.\n\t */\n\n\tCGRect bounds = BoxToRect(d, b);\n\tbool isSelected = (state & TTK_STATE_SELECTED) != 0;\n\tbool isActive = (state & TTK_STATE_BACKGROUND) == 0;\n\tNSColor *color = isSelected && isActive ?\n\t    [NSColor whiteColor] : [NSColor textColor];\n\tNSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];\n\tbool isDark = TkMacOSXInDarkMode(tkwin);\n\tcolor = TkMacOSXGetNSColorFromNSColorUsingColorSpaceAndAppearance(\n\t\tcolor, deviceRGB, isDark);\n\tCGFloat rgba[4];\n\n\t[color getComponents: rgba];\n\tif (rgba[0] == 0) {\n\t    rgba[0] = rgba[1] = rgba[2] = 0.5;\n\t} else if (isSelected && isActive) {\n\t    if (isDark) {\n\t\trgba[0] = rgba[1] = rgba[2] = 0.9;\n\t    }\n\t} else {\n\t    rgba[0] = rgba[1] = rgba[2] = 0.6;\n\t}\n\n\tBEGIN_DRAWING(d)\n\tif (state & TTK_STATE_OPEN) {\n\t    DrawOpenDisclosure(dc.context, bounds, 2, 8, rgba);\n\t} else {\n\t    DrawClosedDisclosure(dc.context, bounds, 3, 12, rgba);\n\t}\n\tEND_DRAWING\n    }\n}\n\nstatic Ttk_ElementSpec DisclosureElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    DisclosureElementSize,\n    DisclosureElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Widget layouts --\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"Toolbar\",\n    TTK_NODE(\"Toolbar.background\", TTK_FILL_BOTH))\n\nTTK_LAYOUT(\"TButton\",\n    TTK_GROUP(\"Button.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\nTTK_LAYOUT(\"TRadiobutton\",\n    TTK_GROUP(\"Radiobutton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Radiobutton.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Radiobutton.label\", TTK_PACK_LEFT))))\n\nTTK_LAYOUT(\"TCheckbutton\",\n    TTK_GROUP(\"Checkbutton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Checkbutton.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Checkbutton.label\", TTK_PACK_LEFT))))\n\nTTK_LAYOUT(\"TMenubutton\",\n    TTK_GROUP(\"Menubutton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Menubutton.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Menubutton.label\", TTK_PACK_LEFT))))\n\nTTK_LAYOUT(\"TCombobox\",\n    TTK_GROUP(\"Combobox.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Combobox.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Combobox.textarea\", TTK_FILL_BOTH))))\n\n/* Image Button - no button */\nTTK_LAYOUT(\"ImageButton\",\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH)))\n\n/* Inline Button */\nTTK_LAYOUT(\"InlineButton\",\n    TTK_GROUP(\"InlineButton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\n/* Rounded Rect Button -- transparent face */\nTTK_LAYOUT(\"RoundedRectButton\",\n    TTK_GROUP(\"RoundedRectButton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\n/* Gradient Button */\nTTK_LAYOUT(\"GradientButton\",\n    TTK_GROUP(\"GradientButton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\n/* Recessed Button - text only radio button */\n\nTTK_LAYOUT(\"RecessedButton\",\n    TTK_GROUP(\"RecessedButton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\n/* Sidebar Button - text only radio button for sidebars */\n\nTTK_LAYOUT(\"SidebarButton\",\n    TTK_GROUP(\"SidebarButton.button\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\n/* DisclosureButton (not a triangle) -- No label, no border*/\nTTK_LAYOUT(\"DisclosureButton\",\n    TTK_NODE(\"DisclosureButton.button\", TTK_FILL_BOTH))\n\n/* HelpButton -- No label, no border*/\nTTK_LAYOUT(\"HelpButton\",\n    TTK_NODE(\"HelpButton.button\", TTK_FILL_BOTH))\n\n/* Notebook tabs -- no focus ring */\nTTK_LAYOUT(\"Tab\",\n    TTK_GROUP(\"Notebook.tab\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Notebook.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Notebook.label\", TTK_FILL_BOTH))))\n\n/* Spinbox -- buttons 2px to the right of the field. */\nTTK_LAYOUT(\"TSpinbox\",\n    TTK_GROUP(\"Spinbox.buttons\", TTK_PACK_RIGHT,\n    TTK_NODE(\"Spinbox.uparrow\", TTK_PACK_TOP | TTK_STICK_E)\n    TTK_NODE(\"Spinbox.downarrow\", TTK_PACK_BOTTOM | TTK_STICK_E))\n    TTK_GROUP(\"Spinbox.field\", TTK_FILL_X,\n    TTK_NODE(\"Spinbox.textarea\", TTK_FILL_X)))\n\nTTK_LAYOUT(\"TEntry\",\n    TTK_GROUP(\"Entry.field\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Entry.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Entry.textarea\", TTK_FILL_BOTH))))\n\n/* Searchbox */\nTTK_LAYOUT(\"Searchbox\",\n    TTK_GROUP(\"Searchbox.field\", TTK_FILL_BOTH|TTK_BORDER,\n\tTTK_GROUP(\"Entry.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Entry.textarea\", TTK_FILL_BOTH))))\n\n/* Progress bars -- track only */\nTTK_LAYOUT(\"TProgressbar\",\n    TTK_NODE(\"Progressbar.track\", TTK_FILL_BOTH))\n\n/* Treeview -- no border. */\nTTK_LAYOUT(\"Treeview\",\n    TTK_GROUP(\"Treeview.field\", TTK_FILL_BOTH,\n    TTK_GROUP(\"Treeview.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Treeview.treearea\", TTK_FILL_BOTH))))\n\n/* Tree heading -- no border, fixed height */\nTTK_LAYOUT(\"Heading\",\n    TTK_NODE(\"Treeheading.cell\", TTK_FILL_BOTH)\n    TTK_NODE(\"Treeheading.image\", TTK_PACK_RIGHT)\n    TTK_NODE(\"Treeheading.text\", TTK_PACK_TOP))\n\n/* Tree items -- omit focus ring */\nTTK_LAYOUT(\"Item\",\n    TTK_GROUP(\"Treeitem.padding\", TTK_FILL_BOTH,\n    TTK_NODE(\"Treeitem.indicator\", TTK_PACK_LEFT)\n    TTK_NODE(\"Treeitem.image\", TTK_PACK_LEFT)\n    TTK_NODE(\"Treeitem.text\", TTK_PACK_LEFT)))\n\n/* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */\n\nTTK_LAYOUT(\"Vertical.TScrollbar\",\n    TTK_GROUP(\"Vertical.Scrollbar.trough\", TTK_FILL_Y,\n    TTK_NODE(\"Vertical.Scrollbar.thumb\", TTK_FILL_BOTH)\n    TTK_NODE(\"Vertical.Scrollbar.downarrow\", TTK_PACK_BOTTOM)\n    TTK_NODE(\"Vertical.Scrollbar.uparrow\", TTK_PACK_BOTTOM)))\n\nTTK_LAYOUT(\"Horizontal.TScrollbar\",\n    TTK_GROUP(\"Horizontal.Scrollbar.trough\", TTK_FILL_X,\n    TTK_NODE(\"Horizontal.Scrollbar.thumb\", TTK_FILL_BOTH)\n    TTK_NODE(\"Horizontal.Scrollbar.rightarrow\", TTK_PACK_RIGHT)\n    TTK_NODE(\"Horizontal.Scrollbar.leftarrow\", TTK_PACK_RIGHT)))\n\nTTK_END_LAYOUT_TABLE\n\n/*----------------------------------------------------------------------\n * +++ Initialization --\n */\n\n/*----------------------------------------------------------------------\n * +++ Ttk_MacOSXInit --\n *\n *    Initialize variables which depend on [NSApp macOSVersion].  Called from\n *    [NSApp applicationDidFinishLaunching].\n */\n\nMODULE_SCOPE void\nTtk_MacOSXInit(void)\n{\n    if ([NSApp macOSVersion] < 101400) {\n\tentryElementPadding = Ttk_MakePadding(7, 6, 7, 5);\n    } else {\n\tentryElementPadding = Ttk_MakePadding(7, 5, 7, 6);\n    }\n    if ([NSApp macOSVersion] < 110000) {\n\tTtk_ContrastDelta = 8.0;\n    } else {\n\n\t/*\n\t * The subtle contrast became event more subtle in 11.0.\n\t */\n\n\tTtk_ContrastDelta = 5.0;\n    }\n}\n\nstatic int AquaTheme_Init(\n    Tcl_Interp *interp)\n{\n    Ttk_Theme themePtr = Ttk_CreateTheme(interp, \"aqua\", NULL);\n\n    if (!themePtr) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Elements:\n     */\n\n    Ttk_RegisterElement(NULL, themePtr, \"background\", &BackgroundElementSpec,\n\t0);\n    Ttk_RegisterElement(NULL, themePtr, \"fill\", &FillElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"field\", &FieldElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Toolbar.background\",\n\t&ToolbarBackgroundElementSpec, 0);\n\n    Ttk_RegisterElement(NULL, themePtr, \"Button.button\",\n\t&ButtonElementSpec, &PushButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"InlineButton.button\",\n\t&ButtonElementSpec, &InlineButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"RoundedRectButton.button\",\n\t&ButtonElementSpec, &RoundedRectButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Checkbutton.button\",\n\t&ButtonElementSpec, &CheckBoxParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Radiobutton.button\",\n\t&ButtonElementSpec, &RadioButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"RecessedButton.button\",\n\t&ButtonElementSpec, &RecessedButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"SidebarButton.button\",\n\t&ButtonElementSpec, &SidebarButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Toolbutton.border\",\n\t&ButtonElementSpec, &BevelButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Menubutton.button\",\n\t&ButtonElementSpec, &PopupButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"DisclosureButton.button\",\n\t&ButtonElementSpec, &DisclosureButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"HelpButton.button\",\n\t&ButtonElementSpec, &HelpButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"GradientButton.button\",\n\t&ButtonElementSpec, &GradientButtonParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Spinbox.uparrow\",\n\t&SpinButtonUpElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Spinbox.downarrow\",\n\t&SpinButtonDownElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Combobox.button\",\n\t&ComboboxElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Treeitem.indicator\",\n\t&DisclosureElementSpec, &DisclosureParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Treeheading.cell\",\n\t&TreeHeaderElementSpec, &ListHeaderParams);\n\n    Ttk_RegisterElement(NULL, themePtr, \"Treeview.treearea\",\n\t&TreeAreaElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Notebook.tab\", &TabElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Notebook.client\", &PaneElementSpec, 0);\n\n    Ttk_RegisterElement(NULL, themePtr, \"Labelframe.border\", &GroupElementSpec,\n\t0);\n    Ttk_RegisterElement(NULL, themePtr, \"Entry.field\", &EntryElementSpec,\n\t\t\t    &EntryFieldParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Searchbox.field\", &EntryElementSpec,\n\t\t\t    &SearchboxFieldParams);\n    Ttk_RegisterElement(NULL, themePtr, \"Spinbox.field\", &EntryElementSpec,\n\t\t\t    &EntryFieldParams);\n\n    Ttk_RegisterElement(NULL, themePtr, \"separator\", &SeparatorElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"hseparator\", &SeparatorElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"vseparator\", &SeparatorElementSpec, 0);\n\n    Ttk_RegisterElement(NULL, themePtr, \"sizegrip\", &SizegripElementSpec, 0);\n\n    /*\n     * <<NOTE-TRACKS>>\n     * In some themes the Layouts for a progress bar has a trough element and a\n     * pbar element.  But in our case the appearance manager draws both parts\n     * of the progress bar, so we just have a single element called \".track\".\n     */\n\n    Ttk_RegisterElement(NULL, themePtr, \"Progressbar.track\", &PbarElementSpec,\n\t0);\n\n    Ttk_RegisterElement(NULL, themePtr, \"Scale.trough\", &TrackElementSpec,\n\t&ScaleData);\n    Ttk_RegisterElement(NULL, themePtr, \"Scale.slider\", &SliderElementSpec, 0);\n\n    Ttk_RegisterElement(NULL, themePtr, \"Vertical.Scrollbar.trough\",\n\t&TroughElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Vertical.Scrollbar.thumb\",\n\t&ThumbElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Horizontal.Scrollbar.trough\",\n\t&TroughElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Horizontal.Scrollbar.thumb\",\n\t&ThumbElementSpec, 0);\n\n    /*\n     * If we are not in Snow Leopard or Lion the arrows won't actually be\n     * displayed.\n     */\n\n    Ttk_RegisterElement(NULL, themePtr, \"Vertical.Scrollbar.uparrow\",\n\t&ArrowElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Vertical.Scrollbar.downarrow\",\n\t&ArrowElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Horizontal.Scrollbar.leftarrow\",\n\t&ArrowElementSpec, 0);\n    Ttk_RegisterElement(NULL, themePtr, \"Horizontal.Scrollbar.rightarrow\",\n\t&ArrowElementSpec, 0);\n\n    /*\n     * Layouts:\n     */\n\n    Ttk_RegisterLayouts(themePtr, LayoutTable);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::aqua\", TTK_VERSION);\n    return TCL_OK;\n}\n\nMODULE_SCOPE int\nTtk_MacOSXPlatformInit(\n    Tcl_Interp *interp)\n{\n    return AquaTheme_Init(interp);\n}\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "macosx/ttkMacOSXTheme.h",
    "content": "/*\n * ttkMacOSXTheme.h --\n *\n *      Static data and macros used in ttkMacOSXTheme.c\n *\n * Copyright 2019 Marc Culler\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Macros for handling drawing contexts.\n */\n\n#define BEGIN_DRAWING(d) {\t\t\t\t    \\\n    TkMacOSXDrawingContext dc;\t\t\t\t    \\\n    if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) {\t    \\\n\treturn;\t\t\t\t\t\t    \\\n    }\t\t\t\t\t\t\t    \\\n\n#define END_DRAWING\t\t\t\t\\\n    TkMacOSXRestoreDrawingContext(&dc);}\n\n\n#define HIOrientation kHIThemeOrientationNormal\n#define NoThemeMetric 0xFFFFFFFF\n\n/*\n *  A scale factor used to map a range of non-negative doubles into a large\n *  range of non-negative 32-bit integers without losing too much information.\n *  (Use 1073741824 == 2^30 so we don't get surprised by roundoff.)\n */\n\n#define RangeToFactor(max) ((double) (1073741824.0) / (max < 1.0 ? 1.0 : max))\n\n/*\n * Meanings of Ttk states represented by User1 and User2.\n */\n\n#define TTK_STATE_IS_ACCENTED   TTK_STATE_USER2\n#define TTK_TREEVIEW_STATE_SORTARROW    TTK_STATE_USER1\n\n/*\n * Colors and gradients used when drawing buttons.\n */\n\ntypedef struct GrayColor {\n    CGFloat grayscale;\n    CGFloat alpha;\n} GrayColor;\n\n#define RGBACOLOR static CGFloat\n#define RGBA256(r, g, b, a) {r / 255.0, g / 255.0, b / 255.0, a}\n#define GRAYCOLOR static GrayColor\n#define GRAY256(grayscale) {grayscale / 255.0, 1.0}\n\n/*\n * Opaque Grays used for Gradient Buttons, Scrollbars and List Headers\n */\n\nGRAYCOLOR darkDisabledIndicator = GRAY256(122.0);\nGRAYCOLOR lightDisabledIndicator = GRAY256(152.0);\n\nGRAYCOLOR darkGradientNormal = GRAY256(95.0);\nGRAYCOLOR darkGradientPressed = GRAY256(118.0);\nGRAYCOLOR darkGradientDisabled = GRAY256(82.0);\nGRAYCOLOR darkGradientBorder = GRAY256(118.0);\nGRAYCOLOR darkGradientBorderDisabled = GRAY256(94.0);\nGRAYCOLOR lightGradientNormal = GRAY256(244.0);\nGRAYCOLOR lightGradientPressed = GRAY256(175.0);\nGRAYCOLOR lightGradientDisabled = GRAY256(235.0);\nGRAYCOLOR lightGradientBorder = GRAY256(165.0);\nGRAYCOLOR lightGradientBorderDisabled = GRAY256(204.0);\n\nGRAYCOLOR lightTrough = GRAY256(250.0);\nGRAYCOLOR darkTrough = GRAY256(47.0);\nGRAYCOLOR lightInactiveThumb = GRAY256(200.0);\nGRAYCOLOR lightActiveThumb = GRAY256(133.0);\nGRAYCOLOR darkInactiveThumb = GRAY256(117.0);\nGRAYCOLOR darkActiveThumb = GRAY256(158.0);\n\nGRAYCOLOR lightListheaderBorder = GRAY256(200.0);\nGRAYCOLOR listheaderSeparator = GRAY256(220.0);\nGRAYCOLOR listheaderActiveBG = GRAY256(238.0);\nGRAYCOLOR listheaderInactiveBG = GRAY256(246.0);\n\nGRAYCOLOR lightComboSeparator = GRAY256(236.0);\nGRAYCOLOR darkComboSeparator = GRAY256(66.0);\n\nGRAYCOLOR darkTrack = GRAY256(84.0);\nGRAYCOLOR darkInactiveTrack = GRAY256(107.0);\nGRAYCOLOR lightTrack = GRAY256(177.0);\nGRAYCOLOR lightInactiveTrack = GRAY256(139.0);\n\n/*\n * Transparent Grays\n */\n\nGRAYCOLOR boxBorder = {1.0, 0.20};\nGRAYCOLOR darkSeparator = {1.0, 0.3};\nGRAYCOLOR darkTabSeparator = {0.0, 0.25};\nGRAYCOLOR darkListheaderBorder = {1.0, 0.125};\nGRAYCOLOR pressedDefaultButton = {0.0, 0.1};\nGRAYCOLOR darkPressedDefaultButton = {1.0, 0.1};\n\n#define CG_WHITE CGColorGetConstantColor(kCGColorWhite)\n\n\n/*\n * Structures which comprise a database of corner radii and state-dependent\n * colors used when drawing various types of buttons or entry widgets.\n */\n\ntypedef struct GrayPalette {\n    CGFloat face;\n    CGFloat top;\n    CGFloat side;\n    CGFloat bottom;\n} GrayPalette;\n\ntypedef struct PaletteStateTable {\n    GrayPalette light;          /* Light palette to use if this entry matches */\n    GrayPalette dark;           /* dark palette to use if this entry matches */\n    unsigned int onBits;        /* Bits which must be set */\n    unsigned int offBits;       /* Bits which must be cleared */\n} PaletteStateTable;\n\ntypedef struct ButtonDesign {\n    CGFloat radius;\n    PaletteStateTable palettes[];\n} ButtonDesign;\n\n/*\n * The data.\n */\n\nstatic const ButtonDesign pushbuttonDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 213.0, .side = 210.0, .bottom = 200.0},\n      .dark =  {.face = 94.0,  .top = 98.0,  .side = 94.0,  .bottom = 58.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0},\n    {\n      .light = {.face = 205.0, .top = 215.0, .side = 211.0, .bottom = 173.0},\n      .dark =  {.face = 140.0, .top = 150.0, .side = 140.0, .bottom = 42.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 198.0, .side = 192.0, .bottom = 173.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign helpDesign = {\n  .radius = 11.0,\n  .palettes = {\n    {\n      .light = {.face = 241.0, .top = 218.0, .side = 217.0, .bottom = 206.0},\n      .dark =  {.face = 83.0,  .top = 89.0,  .side = 82.0,  .bottom = 82.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0},\n    {\n      .light = {.face = 240.0, .top = 208.0, .side = 205.0, .bottom = 188.0},\n      .dark =  {.face = 129.0, .top = 121.0, .side = 106.0, .bottom = 106.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 208.0, .side = 205.0, .bottom = 188.0},\n      .dark =  {.face = 107.0, .top = 121.0, .side = 106.0, .bottom = 106.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign inlineDesign = {\n  .radius = 8.0,\n  .palettes = {\n    {\n      .light = {.face = 170.0, .top = 170.0, .side = 170.0, .bottom = 170.0},\n      .dark =  {.face = 106.0,  .top = 106.0,  .side = 106.0,  .bottom = 106.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0},\n    {\n      .light = {.face = 34.0, .top = 34.0, .side = 34.0, .bottom = 34.0},\n      .dark =  {.face = 225.0, .top = 225.0, .side = 225.0, .bottom = 225.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 113.0, .top = 113.0, .side = 113.0, .bottom = 113.0},\n      .dark =  {.face = 165.0, .top = 165.0, .side = 165.0, .bottom = 165.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign roundedrectDesign = {\n  .radius = 3.0,\n  .palettes = {\n    {\n      .light = {.face = 256.0, .top = 192.0, .side = 192.0, .bottom = 192.0},\n      .dark =  {.face = 256.0, .top = 165.0, .side = 163.0, .bottom = 42.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 204.0, .top = 158.0, .side = 158.0, .bottom = 158.0},\n      .dark =  {.face = 85.0,  .top = 115.0, .side = 115.0, .bottom = 115.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 205.0, .top = 215.0, .side = 211.0, .bottom = 173.0},\n      .dark =  {.face = 140.0, .top = 150.0, .side = 140.0, .bottom = 42.0},\n      .onBits = TTK_STATE_ALTERNATE, .offBits = TTK_STATE_BACKGROUND\n    },\n\n    /*\n     * Gray values > 255 are replaced by the background color.\n     */\n\n    {\n      .light = {.face = 256.0, .top = 158.0, .side = 158.0, .bottom = 158.0},\n      .dark =  {.face = 256.0, .top = 115.0, .side = 115.0, .bottom = 115.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign popupDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 213.0, .side = 210.0, .bottom = 200.0},\n      .dark =  {.face = 94.0,  .top = 98.0,  .side = 94.0,  .bottom = 58.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 198.0, .side = 192.0, .bottom = 173.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign checkDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 192.0, .side = 199.0, .bottom = 199.0},\n      .dark =  {.face = 80.0,  .top = 90.0,  .side = 80.0,  .bottom = 49.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 165.0, .side = 184.0, .bottom = 184.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign radioDesign = {\n  .radius = 8.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 189.0, .side = 198.0, .bottom = 199.0},\n      .dark =  {.face = 80.0,  .top = 84.0,  .side = 88.0,  .bottom = 60.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 165.0, .side = 184.0, .bottom = 184.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign recessedDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 117.0, .top = 117.0, .side = 117.0, .bottom = 117.0},\n      .dark =  {.face = 129.0, .top = 129.0, .side = 129.0, .bottom = 129.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 182.0, .top = 182.0, .side = 182.0, .bottom = 182.0},\n      .dark =  {.face = 105.0,  .top = 105.0, .side = 105.0, .bottom = 105.0},\n      .onBits = TTK_STATE_ACTIVE, .offBits = TTK_STATE_SELECTED\n    },\n    {\n      .light = {.face = 145.0, .top = 145.0, .side = 145.0, .bottom = 145.0},\n      .dark =  {.face = 166.0, .top = 166.0, .side = 166.0, .bottom = 166.0},\n      .onBits = TTK_STATE_SELECTED, .offBits = 0\n    },\n    {\n      .light = {.face = 256.0, .top = 256.0, .side = 256.0, .bottom = 256.0},\n      .dark =  {.face = 256.0, .top = 256.0, .side = 256.0, .bottom = 256.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign sidebarDesign = {\n  .radius = 8.0,\n  .palettes = {\n    {\n      .light = {.face = 210.0, .top = 210.0, .side = 210.0, .bottom = 210.0},\n      .dark =  {.face = 129.0, .top = 129.0, .side = 129.0, .bottom = 129.0},\n      .onBits = TTK_STATE_SELECTED, .offBits = 0\n    },\n    {\n      .light = {.face = 210.0, .top = 210.0, .side = 210.0, .bottom = 210.0},\n      .dark =  {.face = 129.0, .top = 129.0, .side = 129.0, .bottom = 129.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 256.0, .top = 256.0, .side = 256.0, .bottom = 256.0},\n      .dark =  {.face = 256.0, .top = 256.0, .side = 256.0, .bottom = 256.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign incdecDesign = {\n  .radius = 5.0,\n  .palettes = {\n    {\n      .light = {.face = 246.0, .top = 236.0, .side = 227.0, .bottom = 213.0},\n      .dark =  {.face = 80.0,  .top = 90.0,  .side = 80.0,  .bottom = 49.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 198.0, .side = 192.0, .bottom = 173.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign bevelDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 213.0, .side = 210.0, .bottom = 200.0},\n      .dark =  {.face = 94.0,  .top = 98.0,  .side = 94.0,  .bottom = 58.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 205.0, .top = 215.0, .side = 211.0, .bottom = 173.0},\n      .dark =  {.face = 140.0, .top = 150.0, .side = 140.0, .bottom = 42.0},\n      .onBits = TTK_STATE_PRESSED, .offBits = 0\n    },\n    {\n      .light = {.face = 228.0, .top = 215.0, .side = 211.0, .bottom = 173.0},\n      .dark =  {.face = 163.0, .top = 150.0, .side = 140.0, .bottom = 42.0},\n      .onBits = TTK_STATE_SELECTED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 198.0, .side = 192.0, .bottom = 173.0},\n      .dark =  {.face = 118.0, .top = 132.0, .side = 118.0, .bottom = 48.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign tabDesign = {\n  .radius = 4.0,\n  .palettes = {\n\n    /*\n     * Apple does not have such a thing as a disabled tab.  If it is\n     * disabled, it should be removed.  But we provide one based on the\n     * disabled button.\n     */\n\n    {\n      .light = {.face = 229.0, .top = 213.0, .side = 242.0, .bottom = 200.0},\n      .dark =  {.face = 163.0,  .top = 90.0,  .side = 80.0,  .bottom = 49.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 229.0, .top = 205.0, .side = 211.0, .bottom = 183.0},\n      .dark =  {.face = 163.0, .top = 165.0, .side = 163.0, .bottom = 42.0},\n      .onBits = TTK_STATE_SELECTED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 215.0, .side = 211.0, .bottom = 183.0},\n      .dark =  {.face = 108.0, .top = 129.0, .side = 108.0, .bottom = 47.0},\n      .onBits = 0, .offBits = 0\n    },\n  }\n};\n\nstatic const ButtonDesign entryDesign = {\n  .radius = 0.0,\n  .palettes = {\n    {\n      .light = {.face = 256.0, .top = 198.0, .side = 198.0, .bottom = 198.0},\n      .dark =  {.face = 256.0,  .top = 66.0,  .side = 66.0,  .bottom = 84.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign searchDesign = {\n  .radius = 3.5,\n  .palettes = {\n    {\n      .light = {.face = 256.0, .top = 198.0, .side = 198.0, .bottom = 198.0},\n      .dark =  {.face = 256.0,  .top = 66.0,  .side = 66.0,  .bottom = 84.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign comboDesign = {\n  .radius = 4.0,\n  .palettes = {\n    {\n      .light = {.face = 256.0, .top = 190.0, .side = 190.0, .bottom = 190.0},\n      .dark =  {.face = 256.0,  .top = 66.0,  .side = 66.0,  .bottom = 90.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\nstatic const ButtonDesign sliderDesign = {\n  .radius = 8.0,\n  .palettes = {\n    {\n      .light = {.face = 242.0, .top = 189.0, .side = 198.0, .bottom = 199.0},\n      .dark =  {.face = 80.0,  .top = 84.0,  .side = 88.0,  .bottom = 60.0},\n      .onBits = TTK_STATE_DISABLED, .offBits = 0\n    },\n    {\n      .light = {.face = 255.0, .top = 165.0, .side = 184.0, .bottom = 184.0},\n      .dark =  {.face = 205.0, .top = 205.0, .side = 205.0, .bottom = 198.0},\n      .onBits = 0, .offBits = 0\n    }\n  }\n};\n\n\n/*\n * Table mapping Tk states to Appearance manager ThemeStates\n */\n\nstatic const Ttk_StateTable ThemeStateTable[] = {\n    {kThemeStateActive, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},\n    {kThemeStateUnavailable, TTK_STATE_DISABLED, 0},\n    {kThemeStatePressed, TTK_STATE_PRESSED, 0},\n    {kThemeStateInactive, TTK_STATE_BACKGROUND, 0},\n    {kThemeStateUnavailableInactive, TTK_STATE_DISABLED | TTK_STATE_BACKGROUND, 0},\n    {kThemeStateActive, 0, 0}\n\n    /* Others:\n     * The kThemeStatePressedUp and kThemeStatePressedDown bits indicate\n     * which of the two segments of an IncDec button is being pressed.\n     * We don't use these. kThemeStateRollover roughly corresponds to\n     * TTK_STATE_ACTIVE, but does not do what we want with the help button.\n     *\n     * {kThemeStatePressedUp, 0, 0},\n     * {kThemeStatePressedDown, 0, 0}\n     * {kThemeStateRollover, TTK_STATE_ACTIVE, 0},\n     */\n};\n\n/*\n * Translation between Ttk and HIToolbox.\n */\n\nstatic const Ttk_StateTable ButtonValueTable[] = {\n    {kThemeButtonOff, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},\n    {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0},\n    {kThemeButtonOn, TTK_STATE_SELECTED, 0},\n    {kThemeButtonOff, 0, 0}\n};\n\nstatic const Ttk_StateTable ButtonAdornmentTable[] = {\n    {kThemeAdornmentNone, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},\n    {kThemeAdornmentDefault | kThemeAdornmentFocus,\n     TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0},\n    {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0},\n    {kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0},\n    {kThemeAdornmentNone, 0, 0}\n};\n\n/*\n * Our enums for button styles not known to HIToolbox.\n */\n\n#define TkGradientButton    0x8001\n#define TkRoundedRectButton 0x8002\n#define TkRecessedButton    0x8003\n#define TkInlineButton      0x8004\n#define TkSidebarButton     0x8005\n/*\n * The struct passed as clientData when drawing Ttk buttons.\n */\n\ntypedef struct {\n    ThemeButtonKind kind;\n    ThemeMetric heightMetric;\n    ThemeMetric widthMetric;\n} ThemeButtonParams;\n\nstatic ThemeButtonParams\n    PushButtonParams =  {kThemePushButton, kThemeMetricPushButtonHeight,\n\t\t\t NoThemeMetric},\n    CheckBoxParams =    {kThemeCheckBox, kThemeMetricCheckBoxHeight,\n\t\t\t NoThemeMetric},\n    RadioButtonParams = {kThemeRadioButton, kThemeMetricRadioButtonHeight,\n\t\t\t NoThemeMetric},\n    BevelButtonParams = {kThemeRoundedBevelButton, NoThemeMetric, NoThemeMetric},\n    PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight,\n\t\t\t NoThemeMetric},\n    DisclosureParams =  {kThemeDisclosureButton,\n\t\t\t kThemeMetricDisclosureTriangleHeight,\n\t\t\t kThemeMetricDisclosureTriangleWidth},\n    DisclosureButtonParams = {kThemeArrowButton,\n\t\t\t      kThemeMetricSmallDisclosureButtonHeight,\n\t\t\t      kThemeMetricSmallDisclosureButtonWidth},\n    HelpButtonParams = {kThemeRoundButtonHelp, kThemeMetricRoundButtonSize,\n\t\t\tkThemeMetricRoundButtonSize},\n    ListHeaderParams = {kThemeListHeaderButton, kThemeMetricListHeaderHeight,\n\t\t\tNoThemeMetric},\n    GradientButtonParams = {TkGradientButton, NoThemeMetric, NoThemeMetric},\n    RoundedRectButtonParams = {TkRoundedRectButton, kThemeMetricPushButtonHeight,\n\t\t\t       NoThemeMetric},\n    RecessedButtonParams = {TkRecessedButton, kThemeMetricPushButtonHeight,\n\t\t\t    NoThemeMetric},\n    SidebarButtonParams = {TkSidebarButton, NoThemeMetric, NoThemeMetric},\n    InlineButtonParams = {TkInlineButton,  kThemeMetricPushButtonHeight, NoThemeMetric};\n\n    /*\n     * Others: kThemeDisclosureRight, kThemeDisclosureDown,\n     * kThemeDisclosureLeft\n     */\n\n/*\n *  The struct passed as clientData when drawing Ttk Entry widgets.\n */\n\ntypedef struct {\n    HIThemeFrameKind kind;\n    ThemeMetric heightMetric;\n    ThemeMetric widthMetric;\n} ThemeFrameParams;\n\nstatic ThemeFrameParams\n    EntryFieldParams = {kHIThemeFrameTextFieldSquare, NoThemeMetric, NoThemeMetric},\n    SearchboxFieldParams = {kHIThemeFrameTextFieldRound, NoThemeMetric, NoThemeMetric};\n\n/*\n * If we try to draw a rounded rectangle with too large of a radius, the Core\n * Graphics library will sometimes raise a fatal exception.  This macro\n * protects against this by setting the radius to 0 if the width or height is\n * less than twice the radius.  Presumably this mainly happens when a widget\n * has not yet been configured and hence has size 1x1, so there is nothing\n * to draw anyway.\n */\n\n#define CHECK_RADIUS(radius, bounds)            \\\n    if (radius < 0.0                            \\\n\t|| 2 * radius > bounds.size.width       \\\n\t|| 2 * radius > bounds.size.height) {   \\\n\tradius = 0.0;                           \\\n    }\n\n/*\n * The spinbox widget needs to draw the two arrows in different colors when\n * one half or the other is being pressed, but the menubutton always draws\n * them in the same color.  This constant is used to distinguish those two\n * situations.\n */\n\n#define BOTH_ARROWS 1 << 30\n\n/*\n * Local Variables:\n * mode: objc\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "tests/README",
    "content": "README -- Tk test suite design document.\n\nThis directory contains a set of validation tests for the Tk commands.\nPlease see the tests/README file in the Tcl source distribution for\ninformation about the test suite.\n"
  },
  {
    "path": "tests/all.tcl",
    "content": "# all.tcl --\n#\n# This file contains a top-level script to run all of the Tk\n# tests. Execute it by invoking \"source all.tcl\" when running tktest\n# in this directory.\n#\n# Copyright © 1998-1999 Scriptics Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n#\n# REQUIREMENTS\n#\npackage require tk ;# This is the Tk test suite; fail early if no Tk!\npackage require tcltest 2.2\n\n#\n# TCLTEST CONFIGURATION\n#\n\n# Set defaults for the Tk test suite\ntcltest::configure -singleproc 1\n\n# Handle command line parameters\nif {[llength $argv] & 1} {\n    puts stderr \"error: the number of command line parameters must be even (name - value pairs).\"\n    exit 1\n}\nset ignoredOptions [list -testdir]\nset ignoredIndices [list ]\nset index 0\nforeach {key value} $argv {\n    if {$key in $ignoredOptions} {\n\tlappend ignoredIndices $index\n\tputs stderr \"warning: the Tk test suite ignores the option \\\"$key\\\" on the command line.\"\n    }\n    incr index 2\n}\nset tcltestOptions $argv\nforeach index [lreverse $ignoredIndices] {\n    set tcltestOptions [lreplace $tcltestOptions $index [expr {$index + 1}]]\n}\ntcltest::configure {*}$tcltestOptions\nunset ignoredIndices ignoredOptions index tcltestOptions\n\n# Set tcltest options that are not user-configurable for the Tk test suite\ntcltest::configure -testdir [file normalize [file dirname [info script]]]\n\n# Determine test files to skip\nset skipFiles [tcltest::configure -notfile]\nforeach {constraint definition fileList} {\n    testutils\t{}\t\t    testutils.test\n    unix\tTCLTEST_BUILT_IN    {unixButton.test unixEmbed.test unixFont.test unixMenu.test \\\n\t\t\t\t\t    unixSelect.test unixWm.test}\n    win\t\tTCLTEST_BUILT_IN    {winButton.test winClipboard.test winDialog.test winFont.test \\\n\t\t\t\t\t    winMenu.test winMsgbox.test winSend.test winWm.test}\n} {\n    set toSkip 0\n    if {$definition eq \"TCLTEST_BUILT_IN\"} {\n\tif {! [tcltest::testConstraint $constraint]} {\n\t    set toSkip 1\n\t}\n    } elseif {$definition eq \"\"} {\n\tif {$constraint ni [tcltest::configure -constraints]} {\n\t    set toSkip 1\n\t}\n    }\n    if {$toSkip} {\n\tset skipFiles [concat $skipFiles $fileList]\n    }\n}\ntcltest::configure -notfile [lsort -unique $skipFiles]\nunset constraint definition fileList skipFiles toSkip\n\n#\n# RUN ALL TESTS\n#\n\n# Note: the environment variable ERROR_ON_FAILURES is set by Github CI\nif {[tcltest::runAllTests] && [info exists env(ERROR_ON_FAILURES)]} {\n    exit 1\n}\n"
  },
  {
    "path": "tests/arc.tcl",
    "content": "# This file creates a visual test for arcs.  It is part of the Tk\n# visual test suite, which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Visual Tests for Canvas Arcs\"\nwm iconname .t \"Arcs\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\ncanvas .t.c -width 650 -height 600 -relief raised\npack .t.c -expand yes -fill both\nbutton .t.quit -text Quit -command {destroy .t}\npack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2\n\nputs \"depth is [winfo depth .t]\"\nif {[winfo depth .t] > 1} {\n    set fill1 aquamarine3\n    set fill2 aquamarine3\n    set fill3 IndianRed1\n    set outline2 IndianRed3\n} else {\n    set fill1 black\n    set fill2 white\n    set fill3 Black\n    set outline2 white\n}\nset outline black\n\n.t.c create arc 20 20 220 120 -start 30 -extent 270 -outline $fill1 -width 14 \\\n\t-style arc\n.t.c create arc 260 20 460 120 -start 30 -extent 270 -fill $fill2 -width 14 \\\n\t-style chord -outline $outline\n.t.c create arc 500 20 620 160 -start 30 -extent 270 -fill {} -width 14 \\\n\t-style chord -outline $outline -outlinestipple gray50\n.t.c create arc 20 260 140 460 -start 45 -extent 90 -fill $fill2 -width 14 \\\n\t-style pieslice -outline $outline\n.t.c create arc 180 260 300 460 -start 45 -extent 90 -fill {} -width 14 \\\n\t-style pieslice -outline $outline\n.t.c create arc 340 260 460 460 -start 30 -extent 150 -fill $fill2 -width 14 \\\n\t-style chord -outline $outline -stipple gray50 -outlinestipple gray25\n.t.c create arc 500 260 620 460 -start 30 -extent 150 -fill {} -width 14 \\\n\t-style chord -outline $outline\n.t.c create arc 20 450 140 570 -start 135 -extent 270 -fill $fill1 -width 14 \\\n\t-style pieslice -outline {}\n.t.c create arc 180 450 300 570 -start 30 -extent -90 -fill $fill1 -width 14 \\\n\t-style pieslice -outline {}\n.t.c create arc 340 450 460 570 -start 320 -extent 270 -fill $fill1 -width 14 \\\n\t-style chord -outline {}\n.t.c create arc 500 450 620 570 -start 350 -extent -110 -fill $fill1 -width 14 \\\n\t-style chord -outline {}\n.t.c addtag arc withtag all\n.t.c addtag circle withtag [.t.c create oval 320 200 340 220 -fill MistyRose3]\n\n.t.c bind arc <Enter> {\n    set prevFill [lindex [.t.c itemconf current -fill] 4]\n    set prevOutline [lindex [.t.c itemconf current -outline] 4]\n    if {($prevFill ne \"\") || ($prevOutline eq \"\")} {\n\t.t.c itemconf current -fill $fill3\n    }\n    if {$prevOutline ne \"\"} {\n\t.t.c itemconf current -outline $outline2\n    }\n}\n.t.c bind arc <Leave> {.t.c itemconf current -fill $prevFill -outline $prevOutline}\n\nbind .t.c <Button-1> {markarea %x %y}\nbind .t.c <B1-Motion> {strokearea %x %y}\n\nproc markarea {x y} {\n    global areaX1 areaY1\n    set areaX1 $x\n    set areaY1 $y\n}\n\nproc strokearea {x y} {\n    global areaX1 areaY1 areaX2 areaY2\n    if {($areaX1 != $x) && ($areaY1 != $y)} {\n\t.t.c delete area\n\t.t.c addtag area withtag [.t.c create rect $areaX1 $areaY1 $x $y \\\n\t\t-outline black]\n\tset areaX2 $x\n\tset areaY2 $y\n    }\n}\n\nbind .t.c <Control-f> {\n    puts stdout \"Enclosed: [.t.c find enclosed $areaX1 $areaY1 $areaX2 $areaY2]\"\n    puts stdout \"Overlapping: [.t.c find overl $areaX1 $areaY1 $areaX2 $areaY2]\"\n}\n\nbind .t.c <Button-3> {puts stdout \"%x %y\"}\n\n# The code below allows the circle to be move by shift-dragging.\n\nbind .t.c <Shift-Button-1> {\n    set curx %x\n    set cury %y\n}\n\nbind .t.c <Shift-B1-Motion> {\n    .t.c move circle [expr {%x-$curx}] [expr {%y-$cury}]\n    set curx %x\n    set cury %y\n}\n\n# The binding below flashes the closest item to the mouse.\n\nbind .t.c <Control-c> {\n    set closest [.t.c find closest %x %y]\n    set oldfill [lindex [.t.c itemconf $closest -fill] 4]\n    .t.c itemconf $closest -fill IndianRed1\n    after 200 [list .t.c itemconfig $closest -fill $oldfill]\n}\n\nproc c {option value} {.t.c itemconf 2 $option $value}\n\nbind .t.c a {\n    set go 1\n    set i 1\n    while {$go} {\n\tif {$i >= 50} {\n\t    set delta -5\n\t}\n\tif {$i <= 5} {\n\t    set delta 5\n\t}\n\tincr i $delta\n\tc -start $i\n\tc -extent [expr {360-2*$i}]\n\tafter 20\n\tupdate\n    }\n}\n\nbind .t.c b {set go 0}\n\nbind .t.c <Control-x> {.t.c delete current}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/attribtable.test",
    "content": "#\n# tk attribtable command tests\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed for \"-singleproc 0\"\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest tk_attribtable-1.1 \"tableName set\" -body {\n    tk attribtable table\n    pack [button .btn -text Button]\n    set prevText [.btn cget -text]\n    .btn configure -text \"NewText\"\n    table set .btn prevText $prevText\n} -result {}\n\ntest tk_attribtable-1.2 \"tableName get\" -body {\n    list [table get .btn prevText] [table get .btn curText]\n} -result [list Button {}]\n\ntest tk_attribtable-1.3 \"tableName get - all\" -body {\n    table get .btn\n} -result [list prevText Button]\n\ntest tk_attribtable-1.4 \"tableName exists\" -body {\n    list [table exists .btn prevText] [table exists .btn curText]\n} -result [list 1 0]\n\ntest tk_attribtable-1.5 \"tableName names\" -body {\n    table names .btn\n} -result [list prevText]\n\ntest tk_attribtable-1.6 \"tableName pathnames\" -body {\n    table pathnames\n} -result [list .btn]\n\ntest tk_attribtable-1.7 \"tableName unset\" -body {\n    table unset .btn prevText\n} -result {}\n\ntest tk_attribtable-1.8 \"tableName get - after unset\" -body {\n    table get .btn prevText \"Default Text\"\n} -result \"Default Text\"\n\ntest tk_attribtable-1.9 \"tableName exists - after unset\" -body {\n    table exists .btn prevText\n} -result 0\n\ntest tk_attribtable-1.10 \"tableName names - after unset\" -body {\n    table names .btn\n} -result [list]\n\ntest tk_attribtable-1.1 \"tableName pathnames - after unset\" -body {\n    table pathnames\n} -result [list]\n\n\ntest tk_attribtable-2.1 \"tableName bad op\" -body {\n    catch {table badOp .btn}\n} -result 1\n\ntest tk_attribtable-2.2 \"tableName bad window\" -body {\n    catch {table get .bad.window.path.name prevText}\n} -result 1\n\ntest tk_attribtable-2.3 \"tableName set - wrong # args\" -body {\n    list [catch {table set .btn}] [catch {table set .btn prevText}]\n} -result [list 1 1]\n\ntest tk_attribtable-2.4 \"tableName get - wrong # args\" -body {\n    catch {table get .btn oldText prevText curText}\n} -result 1\n\ntest tk_attribtable-2.5 \"tableName exists - wrong # args\" -body {\n    list [catch {table exists .btn prevText curText}] \\\n\t [catch {table exists .btn oldText prevText curText}]\n} -cleanup {\n    destroy .btn\n} -result [list 1 1]\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/bell.test",
    "content": "# This file is a Tcl script to test out Tk's \"bell\" command.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1998-2000 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest bell-1.1 {bell command} -body {\n    bell a\n} -returnCodes error -result {bad option \"a\": must be -displayof or -nice}\n\ntest bell-1.2 {bell command} -body {\n    bell a b\n} -returnCodes error -result {bad option \"a\": must be -displayof or -nice}\n\ntest bell-1.3 {bell command} -body {\n    bell -displayof gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\n\ntest bell-1.4 {bell command} -body {\n    bell -nice -displayof\n} -returnCodes error -result {wrong # args: should be \"bell ?-displayof window? ?-nice?\"}\n\ntest bell-1.5 {bell command} -body {\n    bell -nice -nice -nice\n} -returnCodes {ok} -result {}  ;#keep -result {} and -returnCodes {ok} for clarity?\n\ntest bell-1.6 {bell command} -body {\n    bell -displayof . -nice\n} -returnCodes {ok} -result {}\n\ntest bell-1.7 {bell command} -body {\n    bell -nice -displayof . -nice\n} -returnCodes error -result {wrong # args: should be \"bell ?-displayof window? ?-nice?\"}\n\ntest bell-1.8 {bell command} -body {\n    puts \"Bell should ring now ...\"\n    flush stdout\n    after 200\n    bell -displayof .\n    after 200\n    bell -nice\n    after 200\n    bell\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/bevel.tcl",
    "content": "# This file creates a visual test for bevels drawn around text in text\n# widgets.  It is part of the Tk visual test suite, which is invoked\n# via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Visual Tests for Borders in Text Widgets\"\nwm iconname .t \"Text Borders\"\nwm geom .t +0+0\n\ntext .t.t -width 60 -height 30 -setgrid true -xscrollcommand {.t.h set} \\\n\t-font {Courier 12} \\\n\t-yscrollcommand {.t.v set} -wrap none -relief raised -bd 2\nscrollbar .t.v -orient vertical -command \".t.t yview\"\nscrollbar .t.h -orient horizontal -command \".t.t xview\"\nbutton .t.quit -text Quit -command {destroy .t}\npack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2\npack .t.h -side bottom -fill x\npack .t.v -side right -fill y\npack .t.t -expand yes -fill both\nwm minsize .t 1 1\n\nif {[winfo depth .t] > 1} {\n    .t.t tag configure r1 -relief raised -borderwidth 2 -background #b2dfee\n    .t.t tag configure r2 -relief raised -borderwidth 2 -background #b2dfee \\\n\t    -offset 2\n    .t.t tag configure s1 -relief sunken -borderwidth 2 -background #b2dfee\n} else {\n    .t.t tag configure r1 -relief raised -borderwidth 2 -background white\n    .t.t tag configure r2 -relief raised -borderwidth 2 -background white \\\n\t    -offset 2\n    .t.t tag configure s1 -relief sunken -borderwidth 2 -background white\n}\n.t.t tag configure indent1 -lmargin1 100\n.t.t tag configure indent2 -lmargin1 200\n\n.t.t insert end {This display contains a bunch of raised and sunken\nregions to exercise the bevel-drawing facilities of\nDisplayLineBackground.  The letters have the following\nsignificance:\n\nr - should appear raised\nu - should appear raised and also slightly offset vertically\ns - should appear sunken\nS - should appear solid\nn - preceding relief should extend right to end of line.\n* - should appear \"normal\"\nx - extra long lines to allow horizontal scrolling.\n\nTry scrolling the text both vertically and horizontally to\nbe sure that the bevels are still drawn correctly.\n\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nPass 1 (side bevels):\n\n}\n.t.t insert end ****\n.t.t insert end rrrrrrr r1\n.t.t insert end uuuu r2\n.t.t insert end ************\n.t.t insert end ssssssssssssssssss s1\n.t.t insert end \\n\\n****************\n.t.t insert end rrrrrrrrrrrrrrn\\n r1\n\n.t.t insert end \"\\nPass 2 (top bevels):\\n\\n\"\n.t.t insert end rrrrrrrrrrrrrr r1\n.t.t insert end rrrrr {r1 dummy}\n.t.t insert end rrrrrrrrrrrrrrrrrrr r1\n.t.t insert end \\n************\n.t.t insert end rrrrrrrrrrrrrrrrr r1\n.t.t insert end ***********\\n\n.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr r1\n.t.t insert end \\n\\n***\n.t.t insert end rrrrrrrrrrrrrrrrrrr r1\n.t.t insert end ***********\\n*\n.t.t insert end rrrrrrrrr r1\n.t.t insert end ********\n.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1\n.t.t insert end \\n\\n*\n.t.t insert end *** dummy\n.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1\n.t.t insert end n\\nrrrrrrrrrrrrrrr {r1 indent1}\n.t.t insert end \\n\\n***\n.t.t insert end rrr r1\n.t.t insert end \\n\n.t.t insert end rrrr {r1 indent1}\n\n.t.t insert end \\n\\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\\n\n.t.t insert end \"Pass 3 (bottom bevels):\\n\\n\"\n.t.t insert end *******\n.t.t insert end ********** dummy\n.t.t insert end rrrrrrrrrrrrrrrr r1\n.t.t insert end **********\\n\n.t.t insert end rrrrrrrrr r1\n.t.t insert end uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu r2\n.t.t insert end \\n********************\n.t.t insert end rrrrrrrrrrrrrrr r1\n.t.t insert end ************\\n\\n*\n.t.t insert end rrrrrrrrrrrr r1\n.t.t insert end ********\n.t.t insert end rrrrrrrrrrrrrrrrrrrrrrrrr r1\n.t.t insert end \\n*****\n.t.t insert end rrrrrrrrrrrrrrrrrrrr r1\n.t.t insert end **********\\n\\n\n.t.t insert end rrrrrrrrrrrrrrr {r1 indent1}\n.t.t insert end \\n** dummy\n.t.t insert end **\n.t.t insert end rrrrrrrrrrrrrrrrrrrrn\\n r1\n.t.t insert end \\n\n.t.t insert end rrrr {r1 indent1}\n.t.t insert end \\n***\n.t.t insert end rrr r1\n\n.t.t insert end \\n\\nMiscellaneous:\\n\\n\n.t.t insert end rrr r1\n.t.t insert end *****\n.t.t insert end rrr r1\nforeach i {1 2 3} {\n    .t.t insert end \\n\n    .t.t insert end ***\n    .t.t insert end rrrrr r1\n}\n.t.t insert end \\n\n.t.t insert end rrr r1\n.t.t insert end *****\n.t.t insert end rrr r1\n\nfont configure TkFixedFont -size 20\n.t.t tag configure sol100 -relief solid -borderwidth 100 \\\n\t\t\t  -foreground red -font TkFixedFont\n.t.t tag configure sol12 -relief solid -borderwidth 12 \\\n\t\t\t  -foreground red -font TkFixedFont\n.t.t tag configure big -font TkFixedFont\nset ind [.t.t index end]\n\n.t.t insert end \"\\n\\nBorders do not leak on the neighbour chars\"\n.t.t insert end \"\\nOnly \\\"S\\\" is on dark background\"\n.t.t insert end {\n xxx\n x} {} S sol100 {x\n xxx}\n\n.t.t insert end \"\\n\\nA very thick border grows toward the inside of the tagged area only\"\n.t.t insert end \"\\nOnly \\\"S\\\" is on dark background\"\n.t.t insert end {\n xxxx} {} SSSSS sol100 {xxxx\n x} {} SSSSSSSSSSSSSSSSSS sol100 {x\n xxx} {} SSSSSSSSS sol100 xxxx {}\n\n.t.t insert end \"\\n\\nA thinner border is continuous\"\n.t.t insert end {\n xxxx} {} SSSSS sol12 {xxxx\n x} {} SSSSSSSSSSSSSSSSSS sol12 {x\n xxx} {} SSSSSSSSS sol12 xxxx {}\n\n.t.t tag add big $ind end\n\n"
  },
  {
    "path": "tests/bgerror.test",
    "content": "# This file is a Tcl script to test the bgerror command.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# Some testing of the default error dialog would be needed too, but that's\n# not easy at all to emulate.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest bgerror-1.1 {bgerror / tkerror compat} -setup {\n    set errRes {}\n    proc tkerror {err} {\n\tglobal errRes;\n\tset errRes $err;\n    }\n} -body {\n    after 0 {error err1}\n    vwait errRes;\n    return $errRes;\n} -cleanup {\n    catch {rename tkerror {}}\n} -result {err1}\n\ntest bgerror-1.2 {bgerror / tkerror compat / accumulation} -setup {\n    set errRes {}\n    proc tkerror {err} {\n\tglobal errRes;\n\tlappend errRes $err;\n    }\n} -body {\n    after 0 {error err1}\n    after 0 {error err2}\n    after 0 {error err3}\n    update\n    return $errRes;\n} -cleanup {\n    catch {rename tkerror {}}\n} -result {err1 err2 err3}\n\ntest bgerror-1.3 {bgerror / tkerror compat / accumulation / break} -setup {\n    set errRes {}\n    proc tkerror {err} {\n\tglobal errRes;\n\tlappend errRes $err;\n\treturn -code break \"skip!\";\n    }\n} -body {\n    after 0 {error err1}\n    after 0 {error err2}\n    after 0 {error err3}\n    update\n    return $errRes;\n} -cleanup {\n    catch {rename tkerror {}}\n} -result {err1}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/bind.test",
    "content": "# This file is a Tcl script to test out Tk's \"bind\" and \"bindtags\"\n# commands plus the procedures in tkBind.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\ntk useinputmethods 0\n\ntoplevel .t -width 100 -height 50\nwm geom .t +0+0\nupdate idletasks\n\nforeach p [event info] {event delete $p}\nforeach event [bind Test] {\n    bind Test $event {}\n}\nforeach event [bind all] {\n    bind all $event {}\n}\n\n# move the mouse pointer away of the testing area\n# otherwise some spurious events may pollute the tests\ntoplevel .top\nwm geometry .top 50x50-50-50\nupdate\nevent generate .top <Button-1> -warp 1\ncontrolPointerWarpTiming\ndestroy .top\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc testKey {window event type mods} {\n    global keyInfo numericKeysym\n    set keyInfo {}\n    set numericKeysym {}\n    bind $window <Key> {\n\tset keyInfo [format \"%K,0x%%X,0x%%X,%A\" %N %k]\n\tset numericKeysym %N\n    }\n    focus -force $window\n    update\n    event generate $window $event\n    if {$keyInfo eq {}} {\n\tvwait keyInfo\n    }\n    set save $keyInfo\n    set keyInfo {}\n    set injectcmd [list testinjectkeyevent $type $numericKeysym]\n    foreach {option} $mods {\n\tlappend injectcmd $option\n    }\n    eval $injectcmd\n    if {$keyInfo eq {}} {\n\tvwait keyInfo\n    }\n    if {$save ne $keyInfo} {\n\treturn \"[format \"0x%x\" $numericKeysym] ($mods): $save != $keyInfo\"\n    }\n    return pass\n}\n\nproc testKeyWithMods {window keysym type} {\n    set result [testKey $window \"<$keysym>\" $type {}]\n    if {$result ne \"pass\"} {\n\treturn $result\n    }\n    set result [testKey $window \"<Shift-$keysym>\" $type {-shift}]\n    if {$result ne \"pass\"} {\n\treturn $result\n    }\n    set result [testKey $window \"<Option-$keysym>\" $type {-option}]\n    if {$result ne \"pass\"} {\n\treturn $result\n    }\n    set result [testKey $window \"<Shift-Option-$keysym>\" $type {-shift -option}]\n    if {$result ne \"pass\"} {\n\treturn $result\n    }\n    return pass\n}\n\nproc unsetBindings {} {\n    bind all <Enter> {}\n    bind Test <Enter> {}\n    bind Toplevel <Enter> {}\n    bind xyz <Enter> {}\n    bind {a b} <Enter> {}\n    bind .t <Enter> {}\n}\n\n#\n# TESTS\n#\n\ntest bind-1.1 {bind command} -body {\n    bind\n} -returnCodes error -result {wrong # args: should be \"bind window ?pattern? ?command?\"}\ntest bind-1.2 {bind command} -body {\n    bind a b c d\n} -returnCodes error -result {wrong # args: should be \"bind window ?pattern? ?command?\"}\ntest bind-1.3 {bind command} -body {\n    bind .gorp\n} -returnCodes error -result {bad window path name \".gorp\"}\ntest bind-1.4 {bind command} -body {\n    bind foo\n} -returnCodes ok -result {}\ntest bind-1.5 {bind command} -body {\n    bind .t <gorp-> {}\n} -returnCodes ok -result {}\ntest bind-1.6 {bind command} -body {\n    frame .t.f\n    bind .t.f <Enter> {test script}\n    set result [bind .t.f <Enter>]\n    bind .t.f <Enter> {}\n    list $result [bind .t.f <Enter>]\n} -cleanup {\n    destroy .t.f\n} -result {{test script} {}}\ntest bind-1.7 {bind command} -body {\n    frame .t.f\n    bind .t.f <Enter> {test script}\n    bind .t.f <Enter> {+more text}\n    bind .t.f <Enter>\n} -cleanup {\n    destroy .t.f\n} -result {test script\nmore text}\ntest bind-1.8 {bind command} -body {\n    bind .t <gorp-> {test script}\n} -returnCodes error -result {bad event type or keysym \"gorp\"}\ntest bind-1.9 {bind command} -body {\n    catch {bind .t <gorp-> {test script}}\n    bind .t\n} -result {}\ntest bind-1.10 {bind command} -body {\n    bind .t <gorp->\n} -returnCodes ok -result {}\ntest bind-1.11 {bind command} -body {\n    frame .t.f\n    bind .t.f <Enter> {script 1}\n    bind .t.f <Leave> {script 2}\n    bind .t.f a {script for a}\n    bind .t.f b {script for b}\n    lsort [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {<Enter> <Leave> a b}\n\ntest bind-2.1 {bindtags command} -body {\n    bindtags\n} -returnCodes error -result {wrong # args: should be \"bindtags window ?taglist?\"}\ntest bind-2.2 {bindtags command} -body {\n    bindtags a b c\n} -returnCodes error -result {wrong # args: should be \"bindtags window ?taglist?\"}\ntest bind-2.3 {bindtags command} -body {\n    bindtags .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest bind-2.4 {bindtags command} -body {\n    bindtags .t\n} -result {.t Toplevel all}\ntest bind-2.5 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {.t.f Frame .t all}\ntest bind-2.6 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {{x y z} b c d}\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {{x y z} b c d}\ntest bind-2.7 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {x y z}\n    bindtags .t.f {}\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {.t.f Frame .t all}\ntest bind-2.8 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {x y z}\n    bindtags .t.f {a b c d}\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {a b c d}\ntest bind-2.9 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {a b c}\n    bindtags .t.f \"\\{\"\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {unmatched open brace in list}\ntest bind-2.10 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {a b c}\n    catch {bindtags .t.f \"\\{\"}\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {.t.f Frame .t all}\ntest bind-2.11 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {a b c}\n    bindtags .t.f \"a .gorp b\"\n} -cleanup {\n    destroy .t.f\n} -returnCodes ok\ntest bind-2.12 {bindtags command} -body {\n    frame .t.f\n    bindtags .t.f {a b c}\n    catch {bindtags .t.f \"a .gorp b\"}\n    bindtags .t.f\n} -cleanup {\n    destroy .t.f\n} -result {a .gorp b}\n\n\ntest bind-3.1 {TkFreeBindingTags procedure} -body {\n    frame .t.f\n    bindtags .t.f \"a b c d\"\n    destroy .t.f\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-3.2 {TkFreeBindingTags procedure} -body {\n    frame .t.f\n    catch {bindtags .t.f \"a .gorp b .t.f\"}\n    destroy .t.f\n} -cleanup {\n    destroy .t.f\n} -result {}\n\n\ntest bind-4.1 {TkBindEventProc procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update\n    set x {}\n} -body {\n    bind all <Enter> {lappend x \"%W enter all\"}\n    bind Test <Enter> {lappend x \"%W enter frame\"}\n    bind Toplevel <Enter> {lappend x \"%W enter toplevel\"}\n    bind xyz <Enter> {lappend x \"%W enter xyz\"}\n    bind {a b} <Enter> {lappend x \"%W enter {a b}\"}\n    bind .t <Enter>  {lappend x \"%W enter .t\"}\n    bind .t.f <Enter> {lappend x \"%W enter .t.f\"}\n\n    event generate .t.f <Enter>\n    return $x\n} -cleanup {\n    destroy .t.f\n    unsetBindings\n} -result {{.t.f enter .t.f} {.t.f enter frame} {.t.f enter .t} {.t.f enter all}}\ntest bind-4.2 {TkBindEventProc procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update\n    set x {}\n} -body {\n    bind all <Enter> {lappend x \"%W enter all\"}\n    bind Test <Enter> {lappend x \"%W enter frame\"}\n    bind Toplevel <Enter> {lappend x \"%W enter toplevel\"}\n    bind xyz <Enter> {lappend x \"%W enter xyz\"}\n    bind {a b} <Enter> {lappend x \"%W enter {a b}\"}\n    bind .t <Enter>  {lappend x \"%W enter .t\"}\n    bind .t.f <Enter> {lappend x \"%W enter .t.f\"}\n\n    bindtags .t.f {.t.f {a b} xyz}\n    event generate .t.f <Enter>\n    return $x\n} -cleanup {\n    destroy .t.f\n    unsetBindings\n} -result {{.t.f enter .t.f} {.t.f enter {a b}} {.t.f enter xyz}}\ntest bind-4.3 {TkBindEventProc procedure} -body {\n    set x {}\n    bind all <Enter> {lappend x \"%W enter all\"}\n    bind Test <Enter> {lappend x \"%W enter frame\"}\n    bind Toplevel <Enter> {lappend x \"%W enter toplevel\"}\n    bind xyz <Enter> {lappend x \"%W enter xyz\"}\n    bind {a b} <Enter> {lappend x \"%W enter {a b}\"}\n    bind .t <Enter>  {lappend x \"%W enter .t\"}\n\n    event generate .t <Enter>\n    return $x\n} -cleanup {\n    unsetBindings\n}  -result {{.t enter .t} {.t enter toplevel} {.t enter all}}\ntest bind-4.4 {TkBindEventProc procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    frame .t.f3 -width 50 -height 50\n    pack .t.f3\n    update\n    set x {}\n} -body {\n    bind all <Enter> {lappend x \"%W enter all\"}\n    bind Test <Enter> {lappend x \"%W enter frame\"}\n    bind Toplevel <Enter> {lappend x \"%W enter toplevel\"}\n    bind xyz <Enter> {lappend x \"%W enter xyz\"}\n    bind {a b} <Enter> {lappend x \"%W enter {a b}\"}\n    bind .t <Enter>  {lappend x \"%W enter .t\"}\n\n    bindtags .t.f {.t.f .t.f2 .t.f3}\n    bind .t.f <Enter> {lappend x \"%W enter .t.f\"}\n    bind .t.f3 <Enter> {lappend x \"%W enter .t.f3\"}\n    event generate .t.f <Enter>\n    return $x\n} -cleanup {\n    destroy .t.f .t.f3\n    unsetBindings\n} -result {{.t.f enter .t.f} {.t.f enter .t.f3}}\ntest bind-4.5 {TkBindEventProc procedure} -setup {\n    # This tests memory allocation for objPtr;  it won't serve any useful\n    # purpose unless run with some sort of allocation checker turned on.\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update\n} -body {\n    bind all <Enter> {lappend x \"%W enter all\"}\n    bind Test <Enter> {lappend x \"%W enter frame\"}\n    bind Toplevel <Enter> {lappend x \"%W enter toplevel\"}\n    bind xyz <Enter> {lappend x \"%W enter xyz\"}\n    bind {a b} <Enter> {lappend x \"%W enter {a b}\"}\n    bind .t <Enter>  {lappend x \"%W enter .t\"}\n    bindtags .t.f {a b c d e f g h i j k l m n o p q r s t u v w x y z}\n\n    event generate .t.f <Enter>\n} -cleanup {\n    destroy .t.f\n    unsetBindings\n} -result {}\n\n\ntest bind-5.1 {Tk_CreateBindingTable procedure} -body {\n    canvas .t.c\n    .t.c bind foo\n} -cleanup {\n    destroy .t.c\n} -result {}\n\n\ntest bind-6.1 {Tk_DeleteBindTable procedure} -body {\n    canvas .t.c\n    .t.c bind foo <Button-1> {string 1}\n    .t.c create rectangle 0 0 100 100\n    .t.c bind 1 <Button-2> {string 2}\n    destroy .t.c\n} -cleanup {\n    destroy .t.c\n} -result {}\ntest bind-7.1 {Tk_CreateBinding procedure: bad binding} -body {\n    canvas .t.c\n    .t.c bind foo <\n} -cleanup {\n    destroy .t.c\n} -returnCodes error -result {no event type or button # or keysym}\ntest bind-7.3 {Tk_CreateBinding procedure: append} -body {\n    canvas .t.c\n    .t.c bind foo <Button-1> \"button 1\"\n    .t.c bind foo <Button-1> \"+more button 1\"\n    .t.c bind foo <Button-1>\n} -cleanup {\n    destroy .t.c\n} -result {button 1\nmore button 1}\ntest bind-7.4 {Tk_CreateBinding procedure: append to non-existing} -body {\n    canvas .t.c\n    .t.c bind foo <Button-1> \"+button 1\"\n    .t.c bind foo <Button-1>\n} -cleanup {\n    destroy .t.c\n} -result {button 1}\n\ntest bind-8.1 {Tk_CreateBinding: error} -body {\n    bind . <xyz> \"xyz\"\n} -returnCodes error -result {bad event type or keysym \"xyz\"}\n\ntest bind-9.1 {Tk_DeleteBinding procedure} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <\n} -cleanup {\n    destroy .t.f\n} -returnCodes ok\ntest bind-9.2 {Tk_DeleteBinding procedure} -setup {\n    set result {}\n} -body {\n    frame .t.f -class Test -width 150 -height 100\n    foreach i {a b c d} {\n\tbind .t.f $i \"binding for $i\"\n    }\n    foreach i {b d a c} {\n\tbind .t.f $i {}\n\tlappend result [lsort [bind .t.f]]\n    }\n    return $result\n} -cleanup {\n    destroy .t.f\n} -result {{a c d} {a c} c {}}\ntest bind-9.3 {Tk_DeleteBinding procedure} -setup {\n    set result {}\n} -body {\n    frame .t.f -class Test -width 150 -height 100\n    foreach i {<Button-1> <Meta-Button-1> <Control-Button-1> <Double-Alt-Button-1>} {\n\tbind .t.f $i \"binding for $i\"\n    }\n    foreach i {<Control-Button-1> <Double-Alt-Button-1> <Button-1> <Meta-Button-1>} {\n\tbind .t.f $i {}\n\tlappend result [lsort [bind .t.f]]\n    }\n    return $result\n} -cleanup {\n    destroy .t.f\n} -result {{<Button-1> <Double-Alt-Button-1> <Meta-Button-1>} {<Button-1> <Meta-Button-1>} <Meta-Button-1> {}}\n\ntest bind-10.1 {Tk_GetBinding procedure} -body {\n    canvas .t.c\n    .t.c bind foo <\n} -cleanup {\n    destroy .t.c\n} -returnCodes error -result {no event type or button # or keysym}\ntest bind-10.2 {Tk_GetBinding procedure} -body {\n    canvas .t.c\n    .t.c bind foo a Test\n    .t.c bind foo a\n} -cleanup {\n    destroy .t.c\n} -result {Test}\n\ntest bind-11.1 {Tk_GetAllBindings procedure} -body {\n    frame .t.f\n    foreach i \"! a \\\\\\{ ~ <Delete> <space> <<Paste>> <Tab> <Linefeed> <Key-<> <Meta-a> <Â>\" {\n\tbind .t.f $i Test\n    }\n    lsort [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result \"! <<Paste>> <Key-<> <Key-Delete> <Key-Linefeed> <Key-Tab> <Key-space> <Key-Â> <Meta-Key-a> a \\\\\\{ ~\"\ntest bind-11.2 {Tk_GetAllBindings procedure} -body {\n    frame .t.f\n    foreach i \"<Double-Button-1> <Triple-Button-1> <Meta-Control-a> <Double-Alt-Enter> <Button-1>\" {\n\tbind .t.f $i Test\n    }\n    lsort [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {<Button-1> <Control-Meta-Key-a> <Double-Alt-Enter> <Double-Button-1> <Triple-Button-1>}\ntest bind-11.3 {Tk_GetAllBindings procedure} -body {\n    frame .t.f\n    foreach i \"<Double-Triple-Button-1> abcd a<Leave>b\" {\n\tbind .t.f $i Test\n    }\n    lsort [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {<Triple-Button-1> a<Leave>b abcd}\n\n\ntest bind-12.1 {Tk_DeleteAllBindings procedure} -body {\n    frame .t.f -class Test -width 150 -height 100\n    destroy .t.f\n} -result {}\ntest bind-12.2 {Tk_DeleteAllBindings procedure} -body {\n    frame .t.f -class Test -width 150 -height 100\n    foreach i \"a b c <Meta-Button-1> <Alt-a> <Control-a>\" {\n\tbind .t.f $i x\n    }\n    destroy .t.f\n} -result {}\n\ntest bind-13.1 {Tk_BindEvent procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind Test <Key> {lappend x \"%W %K Test Key\"}\n    bind all <Key> {lappend x \"%W %K all Key\"}\n    bind Test : {lappend x \"%W %K Test :\"}\n    bind all  _ {lappend x \"%W %K all _\"}\n    bind .t.f : {lappend x \"%W %K .t.f :\"}\n\n    event generate .t.f <:>\n    event generate .t.f <+>\n    event generate .t.f <_>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind all <Key> {}\n    bind Test <Key> {}\n    bind all _ {}\n    bind Test : {}\n} -result {{.t.f : .t.f :} {.t.f : Test :} {.t.f : all Key} {.t.f + Test Key} {.t.f + all Key} {.t.f _ Test Key} {.t.f _ all _}}\n\ntest bind-13.2 {Tk_BindEvent procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind Test <Key> {lappend x \"%W %K Test press any\"; break}\n    bind all <Key> {continue; lappend x \"%W %K all press any\"}\n    bind .t.f : {lappend x \"%W %K .t.f pressed colon\"}\n\n    event generate .t.f <:>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind all <Key> {}\n    bind Test <Key> {}\n} -result {{.t.f : .t.f pressed colon} {.t.f : Test press any}}\n\ntest bind-13.3 {Tk_BindEvent procedure} -setup {\n    proc bgerror args {}\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind Test <Key> {lappend x \"%W %K Test press any\"; error Test}\n    bind .t.f : {lappend x \"%W %K .t.f pressed colon\"}\n    event generate .t.f <:>\n    update\n    list $x $errorInfo\n} -cleanup {\n    destroy .t.f\n    bind Test <Key> {}\n    rename bgerror {}\n}  -result {{{.t.f : .t.f pressed colon} {.t.f : Test press any}} {Test\n    while executing\n\"error Test\"\n    (command bound to event)}}\ntest bind-13.4 {Tk_BindEvent procedure} -setup {\n    proc foo {} {\n\tset x 44\n\tevent generate .t.f <:>\n    }\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind Test : {lappend x \"%W %K Test\"}\n    bind .t.f : {lappend x \"%W %K .t.f\"}\n    foo\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test : {}\n} -result {{.t.f : .t.f} {.t.f : Test}}\n\ntest bind-13.5 {Tk_BindEvent procedure} -body {\n    bind all <Destroy> {lappend x \"%W destroyed\"}\n    set x {}\n    frame .t.g -gorp foo\n} -cleanup {\n    bind all <Destroy> {}\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest bind-13.6 {Tk_BindEvent procedure} -body {\n    bind all <Destroy> {lappend x \"%W destroyed\"}\n    set x {}\n    catch {frame .t.g -gorp foo}\n    return $x\n} -cleanup {\n    bind all <Destroy> {}\n} -result {{.t.g destroyed}}\n\ntest bind-13.7 {Tk_BindEvent procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f : {lappend x \"%W (.t.f binding)\"}\n    bind Test : {lappend x \"%W (Test binding)\"}\n    bind all : {bind .t.f : {}; lappend x \"%W (all binding)\"}\n    event generate .t.f <:>\n    return $x\n} -cleanup {\n    bind Test : {}\n    bind all : {}\n    destroy .t.f\n} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}\ntest bind-13.8 {Tk_BindEvent procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f : {lappend x \"%W (.t.f binding)\"}\n    bind Test : {lappend x \"%W (Test binding)\"}\n    bind all : {destroy .t.f; lappend x \"%W (all binding)\"}\n    event generate .t.f <:>\n    return $x\n} -cleanup {\n    bind Test : {}\n    bind all : {}\n    destroy .t.f\n} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}\n\ntest bind-13.9 {Tk_BindEvent procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> {lappend x \"%W z (.t.f <Button-1> binding)\"}\n    bind .t.f <Button> {lappend x \"%W z (.t.f <Button> binding)\"}\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {{.t.f z (.t.f <Button-1> binding)} {.t.f z (.t.f <Button> binding)}}\ntest bind-13.10 {Tk_BindEvent procedure: don't ignore NotifyInferior - bug 47d4f29159} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x Enter%#\"\n    bind .t.f <Leave> \"lappend x Leave%#\"\n    event generate .t.f <Enter> -serial 100 -detail NotifyAncestor\n    event generate .t.f <Enter> -serial 101 -detail NotifyInferior\n    event generate .t.f <Leave> -serial 102 -detail NotifyAncestor\n    event generate .t.f <Leave> -serial 103 -detail NotifyInferior\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Enter100 Enter101 Leave102 Leave103}\ntest bind-13.11 {Tk_BindEvent procedure: collapse Motions} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x Motion%#(%x,%y)\"\n    event generate .t.f <Motion> -serial 100 -x 100 -y 200 -when tail\n    update\n    event generate .t.f <Motion> -serial 101 -x 200 -y 300 -when tail\n    event generate .t.f <Motion> -serial 102 -x 300 -y 400 -when tail\n    update\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Motion100(100,200) Motion102(300,400)}\ntest bind-13.12 {Tk_BindEvent procedure: collapse repeating modifiers} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> \"lappend x %K%#\"\n    bind .t.f <KeyRelease> \"lappend x %K%#\"\n    event generate .t.f <Shift_L> -serial 100 -when tail\n    event generate .t.f <KeyRelease-Shift_L> -serial 101 -when tail\n    event generate .t.f <Shift_L> -serial 102 -when tail\n    event generate .t.f <KeyRelease-Shift_L> -serial 103 -when tail\n    update\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-13.13 {Tk_BindEvent procedure: valid key detail} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x Key%K\"\n    bind .t.f <KeyRelease> \"lappend x Release%K\"\n    event generate .t.f <Key> -keysym :\n    event generate .t.f <KeyRelease> -keysym :\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Key: Release:}\ntest bind-13.14 {Tk_BindEvent procedure: invalid key detail} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x Key%K\"\n    bind .t.f <KeyRelease> \"lappend x Release%K\"\n    event generate .t.f <Key> -keycode -1\n    event generate .t.f <KeyRelease> -keycode -1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Key?? Release??}\ntest bind-13.15 {Tk_BindEvent procedure: button detail} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x Button%b\"\n    bind .t.f <ButtonRelease> \"lappend x Release%b\"\n    event generate .t.f <Button> -button 1\n    event generate .t.f <ButtonRelease> -button 3\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Button1 Release3}\ntest bind-13.16 {Tk_BindEvent procedure: virtual detail} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <<Paste>>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Paste}\ntest bind-13.17 {Tk_BindEvent procedure: virtual event in event stream} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <<Paste>>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Paste}\ntest bind-13.18 {Tk_BindEvent procedure: match detail physical} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {set x Button-2}\n    event add <<Paste>> <Button-2>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n} -result {Button-2}\n\ntest bind-13.19 {Tk_BindEvent procedure: no match detail physical} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-2>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n} -result {Paste}\ntest bind-13.20 {Tk_BindEvent procedure: match detail virtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-2>\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n} -result {Paste}\ntest bind-13.21 {Tk_BindEvent procedure: no match detail virtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-2>\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <Button>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n} -result {}\ntest bind-13.22 {Tk_BindEvent procedure: match no-detail physical} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {set x Button}\n    event add <<Paste>> <Button>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button>\n} -result {Button}\ntest bind-13.23 {Tk_BindEvent procedure: no match no-detail physical} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button>\n} -result {Paste}\ntest bind-13.24 {Tk_BindEvent procedure: match no-detail virtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button>\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button>\n} -result {Paste}\ntest bind-13.25 {Tk_BindEvent procedure: no match no-detail virtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Key>\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    event generate .t.f <Button>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Key>\n} -result {}\ntest bind-13.26 {Tk_BindEvent procedure: precedence} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-2>\n    event add <<Copy>> <Button>\n    bind .t.f <Button-2> \"lappend x Button-2\"\n    bind .t.f <<Paste>> \"lappend x Paste\"\n    bind .t.f <Button> \"lappend x Button\"\n    bind .t.f <<Copy>> \"lappend x Copy\"\n\n    event generate .t.f <Button-2>\n    bind .t.f <Button-2> {}\n    event generate .t.f <Button-2>\n    bind .t.f <<Paste>> {}\n    event generate .t.f <Button-2>\n    bind .t.f <Button> {}\n    event generate .t.f <Button-2>\n    bind .t.f <<Copy>> {}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n    event delete <<Copy>> <Button>\n} -result {Button-2 Paste Button Copy}\ntest bind-13.27 {Tk_BindEvent procedure: no detail virtual pattern list} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {set x Button-2}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Button-2}\ntest bind-13.28 {Tk_BindEvent procedure: detail virtual pattern list} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-2>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-2>\n} -result {Paste}\ntest bind-13.29 {Tk_BindEvent procedure: no no-detail virtual pattern list} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {set x Button}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Button}\ntest bind-13.30 {Tk_BindEvent procedure: no-detail virtual pattern list} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button>\n    bind .t.f <<Paste>> {set x Paste}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button>\n} -result {Paste}\ntest bind-13.31 {Tk_BindEvent procedure: no match} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    event generate .t.f <Button-2>\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-13.32 {Tk_BindEvent procedure: match} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {set x Button-2}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {Button-2}\ntest bind-13.33 {Tk_BindEvent procedure: many C bindings cause realloc} -setup {\n    # this test might not be useful anymore [#3009998]\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bindtags .t.f {a b c d e f g h i j k l m n o p}\n    foreach p [bindtags .t.f] {\n\tbind $p <Button-1> \"lappend x $p\"\n    }\n    event generate .t.f <Button-1>\n    return $x\n} -cleanup {\n    foreach p [bindtags .t.f] {bind $p <Button-1> {}}\n    destroy .t.f\n} -result {a b c d e f g h i j k l m n o p}\ntest bind-13.34 {Tk_BindEvent procedure: multiple tags} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {lappend x .t.f}\n    bind Test <Button-2> {lappend x Button}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-2> {}\n} -result {.t.f Button}\ntest bind-13.35 {Tk_BindEvent procedure: execute binding} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> {lappend x 1}\n    event generate .t.f <Button-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-13.38 {Tk_BindEvent procedure: binding gets to run} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind Test <Button-1> {lappend x Test}\n    bind .t.f <Button-1> {lappend x .t.f}\n    event generate .t.f <Button-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-1> {}\n} -result {.t.f Test}\ntest bind-13.41 {Tk_BindEvent procedure: continue in script} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {lappend x b1; continue; lappend x b2}\n    bind Test <Button-2> {lappend x B1; continue; lappend x B2}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-2> {}\n} -result {b1 B1}\ntest bind-13.43 {Tk_BindEvent procedure: break in script} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {lappend x b1; break; lappend x b2}\n    bind Test <Button-2> {lappend x B1; break; lappend x B2}\n    event generate .t.f <Button-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-2> {}\n} -result  {b1}\ntest bind-13.45 {Tk_BindEvent procedure: error in script} -setup {\n    proc bgerror msg {\n\tglobal x\n\tlappend x $msg\n    }\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2> {lappend x b1; blap}\n    bind Test <Button-2> {lappend x B1}\n    event generate .t.f <Button-2>\n    update\n    return $x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-2> {}\n    proc bgerror args {}\n} -result {b1 {invalid command name \"blap\"}}\n\ntest bind-15.1 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update idletasks\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f 12 {set x 1}\n    set x 0\n    event generate .t.f <Key-1>\n    event generate .t.f <KeyRelease-1>\n    event generate .t.f <Key-2>\n    event generate .t.f <KeyRelease-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.2 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update idletasks\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f 12 {set x 1}\n    set x 0\n    event generate .t.f <Key-1>\n    event generate .t.f <Enter>\n    event generate .t.f <KeyRelease-1>\n    event generate .t.f <Leave>\n    event generate .t.f <Key-2>\n    event generate .t.f <KeyRelease-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.3 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f 12 {set x 1}\n    set x 0\n    event generate .t.f <Key-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Key-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.4 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.5 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-ButtonRelease> {set x 1}\n    set x 0\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.6 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.7 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-1>\n    event generate .t.f <Shift_L>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.8 {MatchPatterns procedure, ignoring type mismatches} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f ab {set x 1}\n    set x 0\n    event generate .t.f <a>\n    event generate .t.f <c>\n    event generate .t.f <b>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.9 {MatchPatterns procedure, modifier checks} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <M1-M2-Key> {set x 1}\n    set x 0\n    event generate .t.f <a> -state 0x18\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.10 {MatchPatterns procedure, modifier checks} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <M1-M2-Key> {set x 1}\n    set x 0\n    event generate .t.f <a> -state 0xfc\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.11 {MatchPatterns procedure, modifier checks} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <M1-M2-Key> {set x 1}\n    set x 0\n    event generate .t.f <a> -state 0x8\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.12 {MatchPatterns procedure, ignore modifier presses and releases} -constraints {\n    nonPortable\n} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    # This test is non-portable because the Shift_L keysym may behave\n    # differently on some platforms.\n    bind .t.f aB {set x 1}\n    set x 0\n    event generate .t.f <a>\n    event generate .t.f <Shift_L>\n    event generate .t.f <b> -state 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.13 {MatchPatterns procedure, checking detail} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f ab {set x 1}\n    set x 0\n    event generate .t.f <a>\n    event generate .t.f <c>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.14 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 31 -y 39\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.15 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 29 -y 41\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.16 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 40 -y 40\n    event generate .t.f <ButtonRelease-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.17 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 20 -y 40\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.18 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 30 -y 30\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.19 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -x 30 -y 40\n    event generate .t.f <Button-1> -x 30 -y 50\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.20 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -time 300\n    event generate .t.f <Button-1> -time 700\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.21 {MatchPatterns procedure, checking \"nearby\"} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1> -time 300\n    event generate .t.f <Button-1> -time 900\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.22 {MatchPatterns procedure, time wrap-around} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-1> -time -100\n    event generate .t.f <Button-1> -time 200\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.23 {MatchPatterns procedure, time wrap-around} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Double-Button-1> {set x 1}\n    set x 0\n    event generate .t.f <Button-1> -time -100\n    event generate .t.f <Button-1> -time 500\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.24 {MatchPatterns procedure, virtual event} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Button-1>\n    bind .t.f <<Paste>> {lappend x paste}\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Button-1>\n} -result {paste}\ntest bind-15.25 {MatchPatterns procedure, reject a  virtual event} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<Paste>> <Shift-Button-1>\n    bind .t.f <<Paste>> {lappend x paste}\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    event delete <<Paste>> <Shift-Button-1>\n} -result {}\ntest bind-15.26 {MatchPatterns procedure, reject a virtual event} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<V1>> <Button>\n    event add <<V2>> <Button-1>\n    event add <<V3>> <Shift-Button-1>\n    bind .t.f <<V2>> \"lappend x V2%#\"\n    event generate .t.f <Button> -serial 101\n    event generate .t.f <Button-1> -serial 102\n    event generate .t.f <Shift-Button-1> -serial 103\n    event generate .t.f <ButtonRelease-1>\n    bind .t.f <Shift-Button-1> \"lappend x Shift-Button-1\"\n    event generate .t.f <Button> -serial 104\n    event generate .t.f <Button-1> -serial 105\n    event generate .t.f <Shift-Button-1> -serial 106\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    event delete <<V1>> <Button>\n    event delete <<V2>> <Button-1>\n    event delete <<V3>> <Shift-Button-1>\n} -result {V2102 V2103 V2105 Shift-Button-1}\ntest bind-15.27 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update idletasks\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x 0}\n    bind .t.f 1 {set x 1}\n    set x none\n    event generate .t.f <Key-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.28 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update idletasks\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x 0}\n    bind .t.f 1 {set x 1}\n    set x none\n    event generate .t.f <Key-2>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 0\ntest bind-15.29 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    update idletasks\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {lappend x 0}\n    bind .t.f 1 {lappend x 1}\n    bind .t.f 21 {lappend x 2}\n    set x none\n    event generate .t.f <Key-2>\n    event generate .t.f <KeyRelease-2>\n    event generate .t.f <Key-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {none 0 2}\ntest bind-15.30 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {set x 0}\n    bind .t.f <Button-1> {set x 1}\n    set x none\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.31 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <M1-Key> {set x 0}\n    bind .t.f <M2-Key> {set x 1}\n    event generate .t.f <a> -state 0x18\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.32 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <M2-Key> {set x 0}\n    bind .t.f <M1-Key> {set x 1}\n    set x none\n    event generate .t.f <a> -state 0x18\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-15.33 {MatchPatterns procedure, conflict resolution} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> {lappend x single}\n    bind Test <Button-1> {lappend x single(Test)}\n    bind Test <Double-Button-1> {lappend x double(Test)}\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    bind Test <Button-1> {}\n    bind Test <Double-Button-1> {}\n} -result {single single(Test) single double(Test) single double(Test)}\n\n\ntest bind-16.1 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x abcd}\n    set x none\n    event generate .t.f <Enter>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {abcd}\ntest bind-16.2 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %#}\n    set x none\n    event generate .t.f <Enter> -serial 1234\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1234\ntest bind-16.3 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Configure> {set x %a}\n    set x none\n    event generate .t.f <Configure> -above .t -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result [winfo id .t]\ntest bind-16.4 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {set x %b}\n    set x none\n    event generate .t.f <Button-3>\n    event generate .t.f <ButtonRelease-3>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 3\ntest bind-16.5 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Expose> {set x %c}\n    set x none\n    event generate .t.f <Expose> -count 47\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 47\ntest bind-16.6 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyAncestor\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyAncestor}\ntest bind-16.7 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyVirtual\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyVirtual}\ntest bind-16.8 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyNonlinear\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyNonlinear}\ntest bind-16.9 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyNonlinearVirtual\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyNonlinearVirtual}\ntest bind-16.10 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyPointer\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyPointer}\ntest bind-16.11 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyPointerRoot\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyPointerRoot}\ntest bind-16.12 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %d}\n    set x none\n    event generate .t.f <Enter> -detail NotifyDetailNone\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyDetailNone}\ntest bind-16.13 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x %f}\n    set x none\n    event generate .t.f <Enter> -focus 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-16.14 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Expose> {set x \"%x %y %w %h\"}\n    set x none\n    event generate .t.f <Expose> -x 24 -y 18 -width 147 -height 61\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {24 18 147 61}\ntest bind-16.15 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Configure> {set x \"%x %y %w %h\"}\n    set x none\n    event generate .t.f <Configure> -x 24 -y 18 -width 147 -height 61 -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {24 18 147 61}\ntest bind-16.16 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x \"%k\"}\n    set x none\n    event generate .t.f <Key> -keycode 146\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 146\ntest bind-16.17 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%m\"}\n    set x none\n    event generate .t.f <Enter> -mode NotifyNormal\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyNormal}\ntest bind-16.18 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%m\"}\n    set x none\n    event generate .t.f <Enter> -mode NotifyGrab\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyGrab}\ntest bind-16.19 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%m\"}\n    set x none\n    event generate .t.f <Enter> -mode NotifyUngrab\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyUngrab}\ntest bind-16.20 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> {set x \"%m\"}\n    set x none\n    event generate .t.f <Enter> -mode NotifyWhileGrabbed\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyWhileGrabbed}\ntest bind-16.21 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Map> {set x \"%o\"}\n    set x none\n    event generate .t.f <Map> -override 1 -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-16.22 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Reparent> {set x \"%o\"}\n    set x none\n    event generate .t.f <Reparent> -override true -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-16.23 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Configure> {set x \"%o\"}\n    set x none\n    event generate .t.f <Configure> -override 1 -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-16.24 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Circulate> {set x \"%p\"}\n    set x none\n    event generate .t.f <Circulate> -place PlaceOnTop -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {PlaceOnTop}\ntest bind-16.25 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Circulate> {set x \"%p\"}\n    set x none\n    event generate .t.f <Circulate> -place PlaceOnBottom -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {PlaceOnBottom}\ntest bind-16.26 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-1> {set x \"%s\"}\n    set x none\n    event generate .t.f <Button-1> -state 1402\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1402\ntest bind-16.27 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%s\"}\n    set x none\n    event generate .t.f <Enter> -state 0x3ff\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1023\ntest bind-16.28 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Visibility> {set x \"%s\"}\n    set x none\n    event generate .t.f <Visibility> -state VisibilityPartiallyObscured\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {VisibilityPartiallyObscured}\ntest bind-16.29 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Visibility> {set x \"%s\"}\n    set x none\n    event generate .t.f <Visibility> -state VisibilityUnobscured\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {VisibilityUnobscured}\ntest bind-16.30 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Visibility> {set x \"%s\"}\n    set x none\n    event generate .t.f <Visibility> -state VisibilityFullyObscured\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {VisibilityFullyObscured}\ntest bind-16.31 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {set x \"%t\"}\n    set x none\n    event generate .t.f <Button> -time 4294\n    event generate .t.f <ButtonRelease>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 4294\ntest bind-16.32 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {set x \"%x %y\"}\n    set x none\n    event generate .t.f <Button> -x 881 -y 432\n    event generate .t.f <ButtonRelease>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {881 432}\ntest bind-16.33 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Reparent> {set x \"%x %y\"}\n    set x none\n    event generate .t.f <Reparent> -x 882 -y 431 -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {882 431}\ntest bind-16.34 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%x %y\"}\n    set x none\n    event generate .t.f <Enter> -x 781 -y 632\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {781 632}\ntest bind-16.35 {ExpandPercents procedure} -constraints {\n    nonPortable\n} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> {lappend x \"%A\"}\n    event generate .t.f <a>\n    event generate .t.f <A> -state 1\n    event generate .t.f <Tab>\n    event generate .t.f <Return>\n    event generate .t.f <F1>\n    event generate .t.f <Shift_L>\n    event generate .t.f <space>\n    event generate .t.f <dollar> -state 1\n    event generate .t.f <braceleft> -state 1\n    event generate .t.f <Multi_key>\n    event generate .t.f <e>\n    event generate .t.f <apostrophe>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {a A {\t} {\\r} {{}} {{}} { } {\\$} \\\\\\{ {{}} {{}} é}\ntest bind-16.36 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Configure> {set x \"%B\"}\n    set x none\n    event generate .t.f <Configure> -borderwidth 24 -window .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 24\ntest bind-16.37 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> {set x \"%E\"}\n    set x none\n    event generate .t.f <Enter> -sendevent 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-16.38 {ExpandPercents procedure} -constraints {\n    nonPortable\n} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> {lappend x %K}\n    event generate .t.f <a>\n    event generate .t.f <A> -state 1\n    event generate .t.f <Tab>\n    event generate .t.f <F1>\n    event generate .t.f <Shift_L>\n    event generate .t.f <space>\n    event generate .t.f <dollar> -state 1\n    event generate .t.f <braceleft> -state 1\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {a A Tab F1 Shift_L space dollar braceleft}\ntest bind-16.39 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x \"%N\"}\n    set x none\n    event generate .t.f <space>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 32\ntest bind-16.40 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x \"%S\"}\n    set x none\n    event generate .t.f <space> -subwindow .t\n    set x\n} -cleanup {\n    destroy .t.f\n} -result [winfo id .t]\ntest bind-16.41 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x \"%T\"}\n    set x none\n    event generate .t.f <Key>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 2\ntest bind-16.42 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> {set x \"%W\"}\n    set x none\n    event generate .t.f <Key>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\ntest bind-16.43 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {set x \"%X %Y\"}\n    set x none\n    event generate .t.f <Button> -rootx 422 -rooty 13\n    event generate .t.f <ButtonRelease>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {422 13}\ntest bind-16.44 {ExpandPercents procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Gravity> {set x \"%R %S\"}\n    set x none\n    event generate .t.f <Gravity>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {?? ??}\n\ntest bind-16.45 {ExpandPercents procedure} -setup {\n    set savedBind(Entry) [bind Entry <Key>]\n    set savedBind(All) [bind all <Key>]\n    entry .t.e\n    pack .t.e\n    focus -force .t.e\n    foreach p [event info] {event delete $p}\n    update\n} -body {\n    bind .t.e <Key> {set x \"%M\"}\n    bind Entry <Key> {set y \"%M\"}\n    bind all <Key> {set z \"%M\"}\n    set x none; set y none; set z none\n    event gen .t.e <a>\n    list $x $y $z\n} -cleanup {\n    destroy .t.e\n    bind all <Key> $savedBind(All)\n    bind Entry <Key> $savedBind(Entry)\n    unset savedBind\n} -result {0 1 2}\ntest bind-16.46 {ExpandPercents procedure} -setup {\n    set savedBind(All) [bind all <Key>]\n    set savedBind(Entry) [bind Entry <Key>]\n    entry .t.e\n    pack .t.e\n    focus -force .t.e\n    foreach p [event info] {event delete $p}\n    update\n} -body {\n    bind all <Key> {set z \"%M\"}\n    bind Entry <Key> {set y \"%M\"}\n    bind .t.e <Key> {set x \"%M\"}\n    set x none; set y none; set z none\n    event gen .t.e <a>\n    list $x $y $z\n} -cleanup {\n    destroy .t.e\n    bind Entry <Key> $savedBind(Entry)\n    bind all <Key> $savedBind(All)\n    unset savedBind\n} -result {0 1 2}\ntest bind-16.47 {ExpandPercents procedure} -constraints aquaOrWin32 -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> {set x \"%K\"}\n    set x none\n    event generate .t.f <Key> -keysym :\n    set x\n} -cleanup {\n    destroy .t.f\n} -result :\n\ntest bind-17.1 {event command} -body {\n    event\n} -returnCodes error -result {wrong # args: should be \"event option ?arg?\"}\ntest bind-17.2 {event command} -body {\n    event xyz\n} -returnCodes error -result {bad option \"xyz\": must be add, delete, generate, or info}\ntest bind-17.3 {event command: add} -body {\n    event add\n} -returnCodes error -result {wrong # args: should be \"event add virtual sequence ?sequence ...?\"}\ntest bind-17.4 {event command: add 1} -body {\n    event delete <<Paste>>\n    event add <<Paste>> <Control-v>\n    event info <<Paste>>\n} -cleanup {\n    event delete <<Paste>> <Control-v>\n} -result <Control-Key-v>\ntest bind-17.5 {event command: add 2} -body {\n    event delete <<Paste>>\n    event add <<Paste>> <Control-v> <Button-2>\n    lsort [event info <<Paste>>]\n} -cleanup {\n    event delete <<Paste>> <Control-v> <Button-2>\n} -result {<Button-2> <Control-Key-v>}\n\ntest bind-17.6 {event command: add with error} -body {\n    event add <<Paste>> <Control-v> <Button-2> abc <xyz> <Button-1>\n} -cleanup {\n    event delete <<Paste>>\n} -returnCodes error -result {bad event type or keysym \"xyz\"}\ntest bind-17.7 {event command: add with error} -body {\n    event delete <<Paste>>\n    catch {event add <<Paste>> <Control-v> <Button-2> abc <xyz> <Button-1>}\n    lsort [event info <<Paste>>]\n} -cleanup {\n    event delete <<Paste>>\n} -result {<Button-2> <Control-Key-v> abc}\n\ntest bind-17.8 {event command: delete} -body {\n    event delete\n} -returnCodes error -result {wrong # args: should be \"event delete virtual ?sequence ...?\"}\ntest bind-17.9 {event command: delete many} -body {\n    event delete <<Paste>>\n    event add <<Paste>> <Button-3> <Button-1> <Button-2> t\n    event delete <<Paste>> <Button-1> <Button-2>\n    lsort [event info <<Paste>>]\n} -cleanup {\n    event delete <<Paste>>\n    event delete <<Paste>> <Button-3> t\n} -result {<Button-3> t}\ntest bind-17.10 {event command: delete all} -body {\n    event add <<Paste>> a b\n    event delete <<Paste>>\n    event info <<Paste>>\n} -cleanup {\n    event delete <<Paste>> a b\n} -result {}\ntest bind-17.11 {event command: delete 1} -body {\n    event delete <<Paste>>\n    event add <<Paste>> a b c\n    event delete <<Paste>> b\n    lsort [event info <<Paste>>]\n} -cleanup {\n    event delete <<Paste>>\n} -result {a c}\ntest bind-17.12 {event command: info name} -body {\n    event delete <<Paste>>\n    event add <<Paste>> a b c\n    lsort [event info <<Paste>>]\n} -cleanup {\n    event delete <<Paste>>\n} -result {a b c}\ntest bind-17.13 {event command: info all} -body {\n    foreach p [event info] {event delete $p}\n    event add <<Paste>> a\n    event add <<Alive>> b\n    lsort [event info]\n} -cleanup {\n    event delete <<Paste>>\n    event delete <<Alive>>\n} -result {<<Alive>> <<Paste>>}\n\ntest bind-17.14 {event command: info error} -body {\n    event info <<Paste>> <Control-v>\n} -returnCodes error -result {wrong # args: should be \"event info ?virtual?\"}\ntest bind-17.15 {event command: generate} -body {\n    event generate\n} -returnCodes error -result {wrong # args: should be \"event generate window event ?-option value ...?\"}\n\ntest bind-17.16 {event command: generate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> \"lappend x 1\"\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-17.17 {event command: generate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    event generate .t.f <xyz>\n} -cleanup {\n    destroy .t.f\n}  -returnCodes error -result {bad event type or keysym \"xyz\"}\ntest bind-17.18 {event command} -body {\n    event foo\n} -returnCodes error -result {bad option \"foo\": must be add, delete, generate, or info}\n\n\ntest bind-18.1 {CreateVirtualEvent procedure: GetVirtualEventUid} -body {\n    event add asd <Ctrl-v>\n} -returnCodes error -result {virtual event \"asd\" is badly formed}\ntest bind-18.2 {CreateVirtualEvent procedure: FindSequence} -body {\n    event add <<asd>> <Ctrl-v>\n} -returnCodes error -result {bad event type or keysym \"Ctrl\"}\ntest bind-18.3 {CreateVirtualEvent procedure: new physical} -body {\n    event delete <<xyz>>\n    event add <<xyz>> <Control-v>\n    event info <<xyz>>\n} -cleanup {\n    event delete <<xyz>>\n} -result <Control-Key-v>\ntest bind-18.4 {CreateVirtualEvent procedure: duplicate physical} -body {\n    event delete <<xyz>>\n    event add <<xyz>> <Control-v>\n    event add <<xyz>> <Control-v>\n    event info <<xyz>>\n} -cleanup {\n    event delete <<xyz>>\n} -result <Control-Key-v>\ntest bind-18.5 {CreateVirtualEvent procedure: existing physical} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event add <<abc>> <Control-v>\n    list [lsort [event info]] [event info <<xyz>>] [event info <<abc>>]\n} -cleanup {\n    event delete <<xyz>>\n    event delete <<abc>>\n} -result {{<<abc>> <<xyz>>} <Control-Key-v> <Control-Key-v>}\ntest bind-18.6 {CreateVirtualEvent procedure: new virtual} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    list [event info] [event info <<xyz>>]\n} -cleanup {\n    event delete <<abc>>\n} -result {<<xyz>> <Control-Key-v>}\ntest bind-18.7 {CreateVirtualEvent procedure: existing virtual} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event add <<xyz>> <Button-2>\n    list [event info] [lsort [event info <<xyz>>]]\n} -cleanup {\n    event delete <<xyz>>\n} -result {<<xyz>> {<Button-2> <Control-Key-v>}}\n\n\ntest bind-19.1 {DeleteVirtualEvent procedure: GetVirtualEventUid} -body {\n    event add xyz {}\n} -returnCodes error -result {virtual event \"xyz\" is badly formed}\ntest bind-19.2 {DeleteVirtualEvent procedure: non-existent virtual} -setup {\n    foreach p [event info] {event delete $p}\n} -body {\n    event delete <<xyz>>\n    event info\n} -result {}\ntest bind-19.3 {DeleteVirtualEvent procedure: delete 1} -setup {\n    event delete <<xyz>>\n} -body {\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>> <Control-v>\n    event info <<xyz>>\n} -result {}\ntest bind-19.4 {DeleteVirtualEvent procedure: delete 1, not owned} -setup {\n    event delete <<xyz>>\n} -body {\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>> <Button-1>\n    event info <<xyz>>\n} -result <Control-Key-v>\ntest bind-19.5 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>> <xyz>\n} -cleanup {\n    event delete <<xyz>>\n} -returnCodes error -result {bad event type or keysym \"xyz\"}\ntest bind-19.6 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>> <<Paste>>\n} -cleanup {\n    event delete <<xyz>>\n} -returnCodes error -result {virtual event not allowed in definition of another virtual event}\ntest bind-19.7 {DeleteVirtualEvent procedure: owns 1, delete all} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>>\n    event info\n} -result {}\ntest bind-19.8 {DeleteVirtualEvent procedure: owns 1, delete 1} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event delete <<xyz>> <Control-v>\n    event info\n} -result {}\ntest bind-19.9 {DeleteVirtualEvent procedure: owns many, delete all} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v> <Control-w> <Control-x>\n    event delete <<xyz>>\n    event info\n} -result {}\ntest bind-19.10 {DeleteVirtualEvent procedure: owns many, delete 1} -body {\n    event delete <<xyz>>\n    event add <<xyz>> <Control-v> <Control-w> <Control-x>\n    event delete <<xyz>> <Control-w>\n    lsort [event info <<xyz>>]\n} -cleanup {\n    event delete <<xyz>>\n} -result {<Control-Key-v> <Control-Key-x>}\ntest bind-19.11 {DeleteVirtualEvent procedure: owned by 1, only} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<xyz>>\n} -body {\n    event add <<xyz>> <Button-2>\n    bind .t.f <<xyz>> {lappend x %#}\n    event generate .t.f <Button-2> -serial 101\n    event generate .t.f <ButtonRelease-2>\n    event delete <<xyz>>\n    event generate .t.f <Button-2> -serial 102\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 101\ntest bind-19.12 {DeleteVirtualEvent procedure: owned by 1, first in chain} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<abc>> <Control-Button-2>\n    event add <<xyz>> <Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.f <<abc>> {lappend x abc}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    event delete <<xyz>>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    list $x [event info <<abc>>]\n} -cleanup {\n    destroy .t.f\n    event delete <<abc>>\n} -result {{xyz abc abc} <Control-Button-2>}\ntest bind-19.13 {DeleteVirtualEvent procedure: owned by 1, second in chain} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<def>>\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<def>> <Shift-Button-2>\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Control-Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.f <<abc>> {lappend x abc}\n    bind .t.f <<def>> {lappend x def}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    event generate .t.f <Shift-Button-2>\n    event generate .t.f <Shift-ButtonRelease-2>\n    event delete <<xyz>>\n    event generate .t.f <Button-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Shift-Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    event generate .t.f <Shift-ButtonRelease-2>\n    list $x [event info <<def>>] [event info <<xyz>>] [event info <<abc>>]\n} -cleanup {\n    destroy .t.f\n    event delete <<abc>>\n    event delete <<def>>\n} -result {{xyz abc def abc def} <Shift-Button-2> {} <Control-Button-2>}\ntest bind-19.14 {DeleteVirtualEvent procedure: owned by 1, last in chain} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<def>>\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Control-Button-2>\n    event add <<def>> <Shift-Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.f <<abc>> {lappend x abc}\n    bind .t.f <<def>> {lappend x def}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    event generate .t.f <Shift-Button-2>\n    event generate .t.f <Shift-ButtonRelease-2>\n    event delete <<xyz>>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Control-Button-2>\n    event generate .t.f <Control-ButtonRelease-2>\n    event generate .t.f <Shift-Button-2>\n    event generate .t.f <Shift-ButtonRelease-2>\n    list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]\n} -cleanup {\n    destroy .t.f\n    event delete <<def>>\n    event delete <<abc>>\n} -result {{xyz abc def abc def} {} <Control-Button-2> <Shift-Button-2>}\ntest bind-19.15 {DeleteVirtualEvent procedure: owned by many, first} -setup {\n    pack [frame .t.f -class Test -width 150 -height 100]\n    pack [frame .t.g -class Test -width 150 -height 100]\n    pack [frame .t.h -class Test -width 150 -height 100]\n    after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<def>>\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Button-2>\n    event add <<def>> <Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.g <<abc>> {lappend x abc}\n    bind .t.h <<def>> {lappend x def}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    event delete <<xyz>>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]\n} -cleanup {\n    destroy .t.f .t.g .t.h\n    event delete <<def>>\n    event delete <<abc>>\n} -result {{xyz abc def abc def} {} <Button-2> <Button-2>}\ntest bind-19.16 {DeleteVirtualEvent procedure: owned by many, middle} -setup {\n    pack [frame .t.f -class Test -width 150 -height 100]\n    pack [frame .t.g -class Test -width 150 -height 100]\n    pack [frame .t.h -class Test -width 150 -height 100]\n    after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<def>>\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Button-2>\n    event add <<def>> <Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.g <<abc>> {lappend x abc}\n    bind .t.h <<def>> {lappend x def}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    event delete <<abc>>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]\n} -cleanup {\n    destroy .t.f .t.g .t.h\n    event delete <<def>>\n    event delete <<xyz>>\n} -result {{xyz abc def xyz def} <Button-2> {} <Button-2>}\ntest bind-19.17 {DeleteVirtualEvent procedure: owned by many, last} -setup {\n    pack [frame .t.f -class Test -width 150 -height 100]\n    pack [frame .t.g -class Test -width 150 -height 100]\n    pack [frame .t.h -class Test -width 150 -height 100]\n    after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)\n    focus -force .t.f\n    update\n    set x {}\n    event delete <<def>>\n    event delete <<xyz>>\n    event delete <<abc>>\n} -body {\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Button-2>\n    event add <<def>> <Button-2>\n    bind .t.f <<xyz>> {lappend x xyz}\n    bind .t.g <<abc>> {lappend x abc}\n    bind .t.h <<def>> {lappend x def}\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    event delete <<def>>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.g <Button-2>\n    event generate .t.g <ButtonRelease-2>\n    event generate .t.h <Button-2>\n    event generate .t.h <ButtonRelease-2>\n    list $x [event info <<xyz>>] [event info <<abc>>] [event info <<def>>]\n} -cleanup {\n    destroy .t.f .t.g .t.h\n    event delete <<xyz>>\n    event delete <<abc>>\n} -result {{xyz abc def xyz abc} <Button-2> <Button-2> {}}\n\n\ntest bind-20.1 {GetVirtualEvent procedure: GetVirtualEventUid} -body {\n    event info asd\n} -returnCodes error -result {virtual event \"asd\" is badly formed}\ntest bind-20.2 {GetVirtualEvent procedure: non-existent event} -body {\n    event delete <<asd>>\n    event info <<asd>>\n} -result {}\ntest bind-20.3 {GetVirtualEvent procedure: owns 1} -setup {\n    event delete <<xyz>>\n} -body {\n    event add <<xyz>> <Control-v>\n    event info <<xyz>>\n} -cleanup {\n    event delete <<xyz>>\n} -result <Control-Key-v>\ntest bind-20.4 {GetVirtualEvent procedure: owns many} -setup {\n    event delete <<xyz>>\n} -body {\n    event add <<xyz>> <Control-v> <Button-2> spack\n    event info <<xyz>>\n} -cleanup {\n    event delete <<xyz>>\n} -result {<Control-Key-v> <Button-2> spack}\n\n\ntest bind-21.1 {GetAllVirtualEvents procedure: no events} -body {\n    foreach p [event info] {event delete $p}\n    event info\n} -result {}\ntest bind-21.2 {GetAllVirtualEvents procedure: 1 event} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event info\n} -cleanup {\n    event delete <<xyz>>\n} -result <<xyz>>\ntest bind-21.3 {GetAllVirtualEvents procedure: many events} -body {\n    foreach p [event info] {event delete $p}\n    event add <<xyz>> <Control-v>\n    event add <<xyz>> <Button-2>\n    event add <<abc>> <Control-v>\n    event add <<def>> <F6>\n    lsort [event info]\n} -cleanup {\n    event delete <<xyz>>\n    event delete <<abc>>\n    event delete <<def>>\n} -result {<<abc>> <<def>> <<xyz>>}\n\ntest bind-22.1 {HandleEventGenerate} -setup {\n    destroy .xyz\n} -body {\n    event generate .xyz <Control-v>\n} -returnCodes error -result {bad window path name \".xyz\"}\ntest bind-22.2 {HandleEventGenerate} -body {\n    event generate zzz <Control-v>\n} -returnCodes error -result {bad window name/identifier \"zzz\"}\ntest bind-22.3 {HandleEventGenerate} -body {\n    event generate 47 <Control-v>\n} -returnCodes error -result {bad window name/identifier \"47\"}\ntest bind-22.4 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {set x \"%s %b\"}\n    event generate [winfo id .t.f] <Control-Button-1> -state 260\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {260 1}\ntest bind-22.5 {HandleEventGenerate} -body {\n    event generate . <xyz>\n} -returnCodes error -result {bad event type or keysym \"xyz\"}\ntest bind-22.6 {HandleEventGenerate} -body {\n    event generate . <Double-Button-1>\n} -returnCodes error -result {Double, Triple, or Quadruple modifier not allowed}\ntest bind-22.7 {HandleEventGenerate} -body {\n    event generate . xyz\n} -returnCodes error -result {only one event specification allowed}\ntest bind-22.8 {HandleEventGenerate} -body {\n    event generate . <Button> -button\n} -returnCodes error -result {value for \"-button\" missing}\ntest bind-22.9 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {set x \"%s %b\"}\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <ButtonRelease-3>\n    event generate .t.f <Control-Button-1>\n    event generate .t.f <Control-ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {4 1}\ntest bind-22.10 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> {set x \"%s %K\"}\n    event generate .t.f <Control-space>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {4 space}\ntest bind-22.11 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> {set x \"%s\"}\n    event generate .t.f <<Paste>> -state 1\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-22.12 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> {set x \"%s\"}\n    event generate .t.f <Control-Motion>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 4\ntest bind-22.13 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {lappend x %#}\n    event generate .t.f <Button> -when now -serial 100\n    event generate .t.f <ButtonRelease> -when now\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 100\ntest bind-22.14 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {lappend x %#}\n    event generate .t.f <Button> -when head -serial 100\n    event generate .t.f <Button> -when head -serial 101\n    event generate .t.f <Button> -when head -serial 102\n    event generate .t.f <ButtonRelease> -when tail\n    lappend x foo\n    update\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {foo 102 101 100}\ntest bind-22.15 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {lappend x %#}\n    event generate .t.f <Button> -when head -serial 99\n    event generate .t.f <Button> -when mark -serial 100\n    event generate .t.f <Button> -when mark -serial 101\n    event generate .t.f <Button> -when mark -serial 102\n    event generate .t.f <ButtonRelease> -when tail\n    lappend x foo\n    update\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {foo 100 101 102 99}\ntest bind-22.16 {HandleEventGenerate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> {lappend x %#}\n    event generate .t.f <Button> -when head -serial 99\n    event generate .t.f <Button> -when tail -serial 100\n    event generate .t.f <Button> -when tail -serial 101\n    event generate .t.f <Button> -when tail -serial 102\n    event generate .t.f <ButtonRelease> -when tail\n    lappend x foo\n    update\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {foo 99 100 101 102}\ntest bind-22.17 {HandleEventGenerate} -body {\n    event generate . <Button> -when xyz\n} -returnCodes error -result {bad -when value \"xyz\": must be now, head, mark, or tail}\ntest bind-22.18 {HandleEventGenerate} -body {\n    # Bug 411307\n    event generate . <a> -root 98765\n} -returnCodes error -result {bad window name/identifier \"98765\"}\n\ntest bind-22.19 {HandleEventGenerate: options <Configure> -above .xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %a\"\n    event generate .t.f <Configure> -above .xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window path name \".xyz\"}\ntest bind-22.20 {HandleEventGenerate: options <Configure> -above .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %a\"\n    event generate .t.f <Configure> -above .t\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result [winfo id .t]\ntest bind-22.21 {HandleEventGenerate: options <Configure> -above xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %a\"\n    event generate .t.f <Configure> -above xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window name/identifier \"xyz\"}\ntest bind-22.22 {HandleEventGenerate: options <Configure> -above [winfo id .t]} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %a\"\n    event generate .t.f <Configure> -above [winfo id .t]\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result [winfo id .t]\n\ntest bind-22.23 {HandleEventGenerate: options <Key> -above .} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %b\"\n    event generate .t.f <Key> -above .\n    return $x\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-above\" option}\n\ntest bind-22.24 {HandleEventGenerate: options <Configure> -borderwidth xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %B\"\n    event generate .t.f <Configure> -borderwidth xyz\n    return $x\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.25 {HandleEventGenerate: options <Configure> -borderwidth 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %B\"\n    event generate .t.f <Configure> -borderwidth 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.26 {HandleEventGenerate: options <Key> -borderwidth 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -borderwidth 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-borderwidth\" option}\n\ntest bind-22.27 {HandleEventGenerate: options <Button> -button xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %b\"\n    event generate .t.f <Button> -button xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.28 {HandleEventGenerate: options <Button> -button 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %b\"\n    event generate .t.f <Button> -button 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.29 {HandleEventGenerate: options <ButtonRelease> -button 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %b\"\n    event generate .t.f <ButtonRelease> -button 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.30 {HandleEventGenerate: options <Key> -button 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -button 1\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-button\" option}\n\ntest bind-22.31 {HandleEventGenerate: options <Expose> -count xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %c\"\n    event generate .t.f <Expose> -count xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.32 {HandleEventGenerate: options <Expose> -count 20} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %c\"\n    event generate .t.f <Expose> -count 20\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 20\n\ntest bind-22.33 {HandleEventGenerate: options <Key> -count 20} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %b\"\n    event generate .t.f <Key> -count 20\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-count\" option}\n\ntest bind-22.34 {HandleEventGenerate: options <Enter> -detail xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %d\"\n    event generate .t.f <Enter> -detail xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad -detail value \"xyz\": must be NotifyAncestor, NotifyVirtual, NotifyInferior, NotifyNonlinear, NotifyNonlinearVirtual, NotifyPointer, NotifyPointerRoot, or NotifyDetailNone}\n\ntest bind-22.35 {HandleEventGenerate: options <FocusIn> -detail NotifyVirtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <FocusIn> \"lappend x FocusIn %d\"\n    event generate .t.f <FocusIn> -detail NotifyVirtual\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {FocusIn NotifyVirtual}\n\ntest bind-22.35.1 {HandleEventGenerate: options <FocusOut> -detail NotifyVirtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <FocusOut> \"lappend x FocusOut %d\"\n    event generate .t.f <FocusOut> -detail NotifyVirtual\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {FocusOut NotifyVirtual}\n\ntest bind-22.36 {HandleEventGenerate: options <Enter> -detail NotifyVirtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %d\"\n    event generate .t.f <Enter> -detail NotifyVirtual\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyVirtual}\n\ntest bind-22.37 {HandleEventGenerate: options <Key> -detail NotifyVirtual} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -detail NotifyVirtual\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-detail\" option}\n\ntest bind-22.38 {HandleEventGenerate: options <Enter> -focus xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %f\"\n    event generate .t.f <Enter> -focus xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\n\ntest bind-22.39 {HandleEventGenerate: options <Enter> -focus 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %f\"\n    event generate .t.f <Enter> -focus 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.40 {HandleEventGenerate: options <Key> -focus 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -focus 1\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-focus\" option}\n\ntest bind-22.41 {HandleEventGenerate: options <Expose> -height xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %h\"\n    event generate .t.f <Expose> -height xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.42 {HandleEventGenerate: options <Expose> -height 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %h\"\n    event generate .t.f <Expose> -height 2i\n    expr {$x eq [winfo pixels .t.f 2i]}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.43 {HandleEventGenerate: options <Configure> -height 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %h\"\n    event generate .t.f <Configure> -height 2i\n    expr {$x eq [winfo pixels .t.f 2i]}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.44 {HandleEventGenerate: options <Key> -height 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -height 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-height\" option}\n\ntest bind-22.45 {HandleEventGenerate: options <Key> -keycode xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -keycode xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.46 {HandleEventGenerate: options <Key> -keycode 20} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -keycode 20\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 20\n\ntest bind-22.47 {HandleEventGenerate: options <Button> -keycode 20} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %b\"\n    event generate .t.f <Button> -keycode 20\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Button> event doesn't accept \"-keycode\" option}\n\ntest bind-22.48 {HandleEventGenerate: options <Key> -keysym xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %K\"\n    event generate .t.f <Key> -keysym xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {unknown keysym \"xyz\"}\n\ntest bind-22.49 {HandleEventGenerate: options <Key> -keysym space} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %K\"\n    event generate .t.f <Key> -keysym space\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {space}\n\ntest bind-22.50 {HandleEventGenerate: options <Button> -keysym space} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %b\"\n    event generate .t.f <Button> -keysym space\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Button> event doesn't accept \"-keysym\" option}\n\ntest bind-22.51 {HandleEventGenerate: options <Enter> -mode xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %m\"\n    event generate .t.f <Enter> -mode xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad -mode value \"xyz\": must be NotifyNormal, NotifyGrab, NotifyUngrab, or NotifyWhileGrabbed}\n\ntest bind-22.52 {HandleEventGenerate: options <Enter> -mode NotifyNormal} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %m\"\n    event generate .t.f <Enter> -mode NotifyNormal\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyNormal}\n\ntest bind-22.53 {HandleEventGenerate: options <FocusIn> -mode NotifyNormal} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <FocusIn> \"lappend x %m\"\n    event generate .t.f <FocusIn> -mode NotifyNormal\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {NotifyNormal}\n\ntest bind-22.54 {HandleEventGenerate: options <Key> -mode NotifyNormal} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -mode NotifyNormal\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-mode\" option}\ntest bind-22.55 {HandleEventGenerate: options <Map> -override xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Map> \"lappend x %o\"\n    event generate .t.f <Map> -override xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\n\ntest bind-22.56 {HandleEventGenerate: options <Map> -override 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Map> \"lappend x %o\"\n    event generate .t.f <Map> -override 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.57 {HandleEventGenerate: options <Reparent> -override 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Reparent> \"lappend x %o\"\n    event generate .t.f <Reparent> -override 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.58 {HandleEventGenerate: options <Configure> -override 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %o\"\n    event generate .t.f <Configure> -override 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.59 {HandleEventGenerate: options <Key> -override 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -override 1\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-override\" option}\n\ntest bind-22.60 {HandleEventGenerate: options <Circulate> -place xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Circulate> \"lappend x %p\"\n    event generate .t.f <Circulate> -place xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad -place value \"xyz\": must be PlaceOnTop, or PlaceOnBottom}\n\ntest bind-22.61 {HandleEventGenerate: options <Circulate> -place PlaceOnTop} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Circulate> \"lappend x %p\"\n    event generate .t.f <Circulate> -place PlaceOnTop\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {PlaceOnTop}\n\ntest bind-22.62 {HandleEventGenerate: options <Key> -place PlaceOnTop} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -place PlaceOnTop\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-place\" option}\n\ntest bind-22.63 {HandleEventGenerate: options <Key> -root .xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %R\"\n    event generate .t.f <Key> -root .xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window path name \".xyz\"}\n\ntest bind-22.64 {HandleEventGenerate: options <Key> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %R\"\n    event generate .t.f <Key> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.65 {HandleEventGenerate: options <Key> -root xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %R\"\n    event generate .t.f <Key> -root xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window name/identifier \"xyz\"}\n\ntest bind-22.66 {HandleEventGenerate: options <Key> -root [winfo id .t]} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %R\"\n    event generate .t.f <Key> -root [winfo id .t]\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.67 {HandleEventGenerate: options <Button> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %R\"\n    event generate .t.f <Button> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.68 {HandleEventGenerate: options <ButtonRelease> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %R\"\n    event generate .t.f <ButtonRelease> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.69 {HandleEventGenerate: options <Motion> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %R\"\n    event generate .t.f <Motion> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.70 {HandleEventGenerate: options <<Paste>> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %R\"\n    event generate .t.f <<Paste>> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.71 {HandleEventGenerate: options <Enter> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %R\"\n    event generate .t.f <Enter> -root .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.72 {HandleEventGenerate: options <Configure> -root .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %R\"\n    event generate .t.f <Configure> -root .t\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-root\" option}\n\ntest bind-22.73 {HandleEventGenerate: options <Key> -rootx xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %X\"\n    event generate .t.f <Key> -rootx xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.74 {HandleEventGenerate: options <Key> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %X\"\n    event generate .t.f <Key> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.75 {HandleEventGenerate: options <Button> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %X\"\n    event generate .t.f <Button> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.76 {HandleEventGenerate: options <ButtonRelease> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %X\"\n    event generate .t.f <ButtonRelease> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.77 {HandleEventGenerate: options <Motion> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %X\"\n    event generate .t.f <Motion> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.78 {HandleEventGenerate: options <<Paste>> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %X\"\n    event generate .t.f <<Paste>> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.79 {HandleEventGenerate: options <Enter> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %X\"\n    event generate .t.f <Enter> -rootx 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.80 {HandleEventGenerate: options <Configure> -rootx 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %X\"\n    event generate .t.f <Configure> -rootx 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-rootx\" option}\n\ntest bind-22.81 {HandleEventGenerate: options <Key> -rooty xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %Y\"\n    event generate .t.f <Key> -rooty xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.82 {HandleEventGenerate: options <Key> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %Y\"\n    event generate .t.f <Key> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.83 {HandleEventGenerate: options <Button> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %Y\"\n    event generate .t.f <Button> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.84 {HandleEventGenerate: options <ButtonRelease> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %Y\"\n    event generate .t.f <ButtonRelease> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.85 {HandleEventGenerate: options <Motion> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %Y\"\n    event generate .t.f <Motion> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.86 {HandleEventGenerate: options <<Paste>> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %Y\"\n    event generate .t.f <<Paste>> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.87 {HandleEventGenerate: options <Enter> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %Y\"\n    event generate .t.f <Enter> -rooty 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.88 {HandleEventGenerate: options <Configure> -rooty 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %Y\"\n    event generate .t.f <Configure> -rooty 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-rooty\" option}\n\ntest bind-22.89 {HandleEventGenerate: options <Key> -sendevent xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %E\"\n    event generate .t.f <Key> -sendevent xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\n\ntest bind-22.90 {HandleEventGenerate: options <Key> -sendevent 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %E\"\n    event generate .t.f <Key> -sendevent 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.91 {HandleEventGenerate: options <Key> -sendevent yes} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %E\"\n    event generate .t.f <Key> -sendevent yes\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.92 {HandleEventGenerate: options <Key> -sendevent 43} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %E\"\n    event generate .t.f <Key> -sendevent 43\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.93 {HandleEventGenerate: options <Key> -serial xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %#\"\n    event generate .t.f <Key> -serial xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.94 {HandleEventGenerate: options <Key> -serial 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %#\"\n    event generate .t.f <Key> -serial 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.95 {HandleEventGenerate: options <Key> -state xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %s\"\n    event generate .t.f <Key> -state xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.96 {HandleEventGenerate: options <Key> -state 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %s\"\n    event generate .t.f <Key> -state 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.97 {HandleEventGenerate: options <Button> -state 1025} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %s\"\n    event generate .t.f <Button> -state 1025\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1025\n\ntest bind-22.98 {HandleEventGenerate: options <ButtonRelease> -state 1025} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %s\"\n    event generate .t.f <ButtonRelease> -state 1025\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1025\n\ntest bind-22.99 {HandleEventGenerate: options <Motion> -state 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %s\"\n    event generate .t.f <Motion> -state 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.100 {HandleEventGenerate: options <<Paste>> -state 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %s\"\n    event generate .t.f <<Paste>> -state 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.101 {HandleEventGenerate: options <Enter> -state 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %s\"\n    event generate .t.f <Enter> -state 1\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.102 {HandleEventGenerate: options <Visibility> -state xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Visibility> \"lappend x %s\"\n    event generate .t.f <Visibility> -state xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad -state value \"xyz\": must be VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured}\n\ntest bind-22.103 {HandleEventGenerate: options <Visibility> -state VisibilityUnobscured} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Visibility> \"lappend x %s\"\n    event generate .t.f <Visibility> -state VisibilityUnobscured\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {VisibilityUnobscured}\n\ntest bind-22.104 {HandleEventGenerate: options <Configure> -state xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %s\"\n    event generate .t.f <Configure> -state xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-state\" option}\n\ntest bind-22.105 {HandleEventGenerate: options <Key> -subwindow .xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %S\"\n    event generate .t.f <Key> -subwindow .xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window path name \".xyz\"}\n\ntest bind-22.106 {HandleEventGenerate: options <Key> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %S\"\n    event generate .t.f <Key> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.107 {HandleEventGenerate: options <Key> -subwindow xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %S\"\n    event generate .t.f <Key> -subwindow xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window name/identifier \"xyz\"}\n\ntest bind-22.108 {HandleEventGenerate: options <Key> -subwindow [winfo id .t]} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %S\"\n    event generate .t.f <Key> -subwindow [winfo id .t]\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.109 {HandleEventGenerate: options <Button> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %S\"\n    event generate .t.f <Button> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.110 {HandleEventGenerate: options <ButtonRelease> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %S\"\n    event generate .t.f <ButtonRelease> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.111 {HandleEventGenerate: options <Motion> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %S\"\n    event generate .t.f <Motion> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.112 {HandleEventGenerate: options <<Paste>> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %S\"\n    event generate .t.f <<Paste>> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.113 {HandleEventGenerate: options <Enter> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %S\"\n    event generate .t.f <Enter> -subwindow .t\n    expr {[winfo id .t] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.114 {HandleEventGenerate: options <Configure> -subwindow .t} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %S\"\n    event generate .t.f <Configure> -subwindow .t\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-subwindow\" option}\n\ntest bind-22.115 {HandleEventGenerate: options <Key> -time xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %t\"\n    event generate .t.f <Key> -time xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest bind-22.116 {HandleEventGenerate: options <Key> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %t\"\n    event generate .t.f <Key> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.117 {HandleEventGenerate: options <Button> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %t\"\n    event generate .t.f <Button> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.118 {HandleEventGenerate: options <ButtonRelease> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %t\"\n    event generate .t.f <ButtonRelease> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.119 {HandleEventGenerate: options <Motion> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %t\"\n    event generate .t.f <Motion> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.120 {HandleEventGenerate: options <<Paste>> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %t\"\n    event generate .t.f <<Paste>> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.121 {HandleEventGenerate: options <Enter> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %t\"\n    event generate .t.f <Enter> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.122 {HandleEventGenerate: options <Property> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Property> \"lappend x %t\"\n    event generate .t.f <Property> -time 100\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result 100\n\ntest bind-22.123 {HandleEventGenerate: options <Configure> -time 100} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %t\"\n    event generate .t.f <Configure> -time 100\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Configure> event doesn't accept \"-time\" option}\n\ntest bind-22.124 {HandleEventGenerate: options <Expose> -width xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %w\"\n    event generate .t.f <Expose> -width xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.125 {HandleEventGenerate: options <Expose> -width 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %w\"\n    event generate .t.f <Expose> -width 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.126 {HandleEventGenerate: options <Configure> -width 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %w\"\n    event generate .t.f <Configure> -width 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.127 {HandleEventGenerate: options <Key> -width 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -width 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-width\" option}\n\ntest bind-22.128 {HandleEventGenerate: options <Unmap> -window .xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Unmap> \"lappend x %W\"\n    event generate .t.f <Unmap> -window .xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window path name \".xyz\"}\n\ntest bind-22.129 {HandleEventGenerate: options <Unmap> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Unmap> \"lappend x %W\"\n    event generate .t.f <Unmap> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.130 {HandleEventGenerate: options <Unmap> -window xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Unmap> \"lappend x %W\"\n    event generate .t.f <Unmap> -window xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad window name/identifier \"xyz\"}\n\ntest bind-22.131 {HandleEventGenerate: options <Unmap> -window [winfo id .t.f]} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Unmap> \"lappend x %W\"\n    event generate .t.f <Unmap> -window [winfo id .t.f]\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.132 {HandleEventGenerate: options <Unmap> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Unmap> \"lappend x %W\"\n    event generate .t.f <Unmap> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.133 {HandleEventGenerate: options <Map> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Map> \"lappend x %W\"\n    event generate .t.f <Map> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.134 {HandleEventGenerate: options <Reparent> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Reparent> \"lappend x %W\"\n    event generate .t.f <Reparent> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.135 {HandleEventGenerate: options <Configure> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %W\"\n    event generate .t.f <Configure> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.136 {HandleEventGenerate: options <Gravity> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Gravity> \"lappend x %W\"\n    event generate .t.f <Gravity> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.137 {HandleEventGenerate: options <Circulate> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Circulate> \"lappend x %W\"\n    event generate .t.f <Circulate> -window .t.f\n    return $x\n} -cleanup {\n    destroy .t.f\n} -result {.t.f}\n\ntest bind-22.138 {HandleEventGenerate: options <Key> -window .t.f} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %W\"\n    event generate .t.f <Key> -window .t.f\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Key> event doesn't accept \"-window\" option}\n\ntest bind-22.139 {HandleEventGenerate: options <Key> -x xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %x\"\n    event generate .t.f <Key> -x xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.140 {HandleEventGenerate: options <Key> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %x\"\n    event generate .t.f <Key> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.141 {HandleEventGenerate: options <Button> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %x\"\n    event generate .t.f <Button> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.142 {HandleEventGenerate: options <ButtonRelease> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %x\"\n    event generate .t.f <ButtonRelease> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.143 {HandleEventGenerate: options <Motion> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %x\"\n    event generate .t.f <Motion> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.144 {HandleEventGenerate: options <<Paste>> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %x\"\n    event generate .t.f <<Paste>> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.145 {HandleEventGenerate: options <Enter> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %x\"\n    event generate .t.f <Enter> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.146 {HandleEventGenerate: options <Expose> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %x\"\n    event generate .t.f <Expose> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.147 {HandleEventGenerate: options <Configure> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %x\"\n    event generate .t.f <Configure> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.148 {HandleEventGenerate: options <Gravity> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Gravity> \"lappend x %x\"\n    event generate .t.f <Gravity> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.149 {HandleEventGenerate: options <Reparent> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Reparent> \"lappend x %x\"\n    event generate .t.f <Reparent> -x 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.150 {HandleEventGenerate: options <Map> -x 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Map> \"lappend x %x\"\n    event generate .t.f <Map> -x 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Map> event doesn't accept \"-x\" option}\n\ntest bind-22.151 {HandleEventGenerate: options <Key> -y xyz} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %y\"\n    event generate .t.f <Key> -y xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\n\ntest bind-22.152 {HandleEventGenerate: options <Key> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %y\"\n    event generate .t.f <Key> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.153 {HandleEventGenerate: options <Button> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button> \"lappend x %y\"\n    event generate .t.f <Button> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.154 {HandleEventGenerate: options <ButtonRelease> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <ButtonRelease> \"lappend x %y\"\n    event generate .t.f <ButtonRelease> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.155 {HandleEventGenerate: options <Motion> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Motion> \"lappend x %y\"\n    event generate .t.f <Motion> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.156 {HandleEventGenerate: options <<Paste>> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> \"lappend x %y\"\n    event generate .t.f <<Paste>> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.157 {HandleEventGenerate: options <Enter> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Enter> \"lappend x %y\"\n    event generate .t.f <Enter> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.158 {HandleEventGenerate: options <Expose> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Expose> \"lappend x %y\"\n    event generate .t.f <Expose> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.159 {HandleEventGenerate: options <Configure> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Configure> \"lappend x %y\"\n    event generate .t.f <Configure> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.160 {HandleEventGenerate: options <Gravity> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Gravity> \"lappend x %y\"\n    event generate .t.f <Gravity> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.161 {HandleEventGenerate: options <Reparent> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Reparent> \"lappend x %y\"\n    event generate .t.f <Reparent> -y 2i\n    expr {[winfo pixels .t.f 2i] eq $x}\n} -cleanup {\n    destroy .t.f\n} -result 1\n\ntest bind-22.162 {HandleEventGenerate: options <Map> -y 2i} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Map> \"lappend x %y\"\n    event generate .t.f <Map> -y 2i\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<Map> event doesn't accept \"-y\" option}\n\ntest bind-22.163 {HandleEventGenerate: options <Key> -xyz 1} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> \"lappend x %k\"\n    event generate .t.f <Key> -xyz 1\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad option \"-xyz\": must be -when, -above, -borderwidth, -button, -count, -data, -delta, -detail, -focus, -height, -keycode, -keysym, -mode, -override, -place, -root, -rootx, -rooty, -sendevent, -serial, -state, -subwindow, -time, -warp, -width, -window, -x, or -y}\n# Note that the -data option is tested in bind-32.* because it has\n# more demanding requirements in memory handling\n\n\ntest bind-23.1 {GetVirtualEventUid procedure} -body {\n    event info <<asd\n} -returnCodes error -result {virtual event \"<<asd\" is badly formed}\ntest bind-23.2 {GetVirtualEventUid procedure} -body {\n    event info <<>>\n} -returnCodes error -result {virtual event \"<<>>\" is badly formed}\ntest bind-23.3 {GetVirtualEventUid procedure} -body {\n    event info <<asd>\n} -returnCodes error -result {virtual event \"<<asd>\" is badly formed}\ntest bind-23.4 {GetVirtualEventUid procedure} -setup {\n    event delete <<asd>>\n} -body {\n    event info <<asd>>\n} -result {}\n\n\ntest bind-24.1 {FindSequence procedure: no event} -body {\n    bind .t {} test\n} -returnCodes error -result {no events specified in binding}\ntest bind-24.2 {FindSequence procedure: bad event} -body {\n    bind .t <xyz> test\n} -returnCodes error -result {bad event type or keysym \"xyz\"}\ntest bind-24.3 {FindSequence procedure: virtual allowed} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<Paste>> test\n} -cleanup {\n    destroy .t.f\n} -result  {}\ntest bind-24.4 {FindSequence procedure: virtual not allowed} -body {\n    event add <<Paste>> <<Alive>>\n} -returnCodes error -result {virtual event not allowed in definition of another virtual event}\ntest bind-24.5 {FindSequence procedure, multiple bindings} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-1> {lappend x single}\n    bind .t.f <Double-Button-1> {lappend x double}\n    bind .t.f <Triple-Button-1> {lappend x triple}\n    bind .t.f <Quadruple-Button-1> {lappend x quadruple}\n    set x press\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    lappend x press\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    lappend x press\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    lappend x press\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    lappend x press\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {press single press double press triple press quadruple press quadruple}\ntest bind-24.6 {FindSequence procedure: virtual composed} -body {\n    bind .t <Control-b><<Paste>> \"puts hi\"\n} -returnCodes error -result {virtual events may not be composed}\ntest bind-24.7 {FindSequence procedure: new pattern sequence} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-2> {lappend x 1-2}\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {1-2}\ntest bind-24.8 {FindSequence procedure: similar pattern sequence} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-2> {lappend x 1-2}\n    bind .t.f <Button-2> {lappend x 2}\n    event generate .t.f <Button-3>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {2 1-2}\ntest bind-24.9 {FindSequence procedure: similar pattern sequence} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-2> {lappend x 1-2}\n    bind .t.f <Button-2><Button-2> {lappend x 2-2}\n    event generate .t.f <Button-3>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {2-2 1-2}\ntest bind-24.10 {FindSequence procedure: similar pattern sequence} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2><Button-2> {lappend x 2-2}\n    bind .t.f <Double-Button-2> {lappend x d-2}\n    event generate .t.f <Button-3>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    event generate .t.f <Button-2> -x 100\n    event generate .t.f <ButtonRelease-2>\n    event generate .t.f <Button-2> -x 200\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {d-2 2-2}\ntest bind-24.11 {FindSequence procedure: new sequence, don't create} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-2>\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-24.12 {FindSequence procedure: not new sequence, don't create} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Control-Button-2> \"foo\"\n    bind .t.f <Button-2>\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-24.13 {FindSequence procedure: no binding} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <a>\n} -cleanup {\n    destroy .t.f\n} -returnCodes ok\ntest bind-24.14 {FindSequence procedure: no binding} -body {\n    canvas .t.c\n    set i [.t.c create rect 10 10 100 100]\n    .t.c bind $i <a>\n} -cleanup {\n    destroy .t.c\n} -returnCodes ok\n\ntest bind-25.1 {ParseEventDescription procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f a test\n    bind .t.f a\n} -cleanup {\n    destroy .t.f\n} -result test\ntest bind-25.2 {ParseEventDescription procedure: misinterpreted modifier} -setup {\n    button .b\n} -body {\n    bind .b <Control-M> a\n    bind .b <Meta-M> b\n    lsort [bind .b]\n} -cleanup {\n    destroy .b\n} -result {<Control-Key-M> <Meta-Key-M>}\ntest bind-25.3 {ParseEventDescription procedure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <a---> {nothing}\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result a\ntest bind-25.4 {ParseEventDescription} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <<Shift-Paste>> {puts hi}\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <<Shift-Paste>>\n\n# Assorted error cases in event sequence parsing\ntest bind-25.5 {ParseEventDescription procedure error cases} -body {\n    bind .t \\x7 {puts hi}\n} -returnCodes error -result {bad ASCII character 0x7}\ntest bind-25.6 {ParseEventDescription procedure error cases} -body {\n    bind .t \\x7f {puts hi}\n} -returnCodes error -result {bad ASCII character 0x7f}\ntest bind-25.7 {ParseEventDescription procedure error cases} -body {\n    bind .t \\x4 {puts hi}\n} -returnCodes error -result {bad ASCII character 0x4}\ntest bind-25.8 {ParseEventDescription procedure error cases} -body {\n    bind .t <<>>  {puts hi}\n} -returnCodes error -result {virtual event \"<<>>\" is badly formed}\ntest bind-25.9 {ParseEventDescription procedure error cases} -body {\n    bind .t <<Paste  {puts hi}\n} -returnCodes error -result {missing \">\" in virtual binding}\ntest bind-25.10 {ParseEventDescription procedure error cases} -body {\n    bind .t <<Paste>  {puts hi}\n} -returnCodes error -result {missing \">\" in virtual binding}\ntest bind-25.11 {ParseEventDescription procedure error cases} -body {\n    bind .t <<Paste>>h  {puts hi}\n} -returnCodes error -result {virtual events may not be composed}\ntest bind-25.12 {ParseEventDescription procedure error cases} -body {\n    bind .t <>  {puts hi}\n} -returnCodes error -result {no event type or button # or keysym}\ntest bind-25.13 {ParseEventDescription procedure error cases} -body {\n    bind .t <a--  {puts hi}\n} -returnCodes error -result {missing \">\" in binding}\ntest bind-25.14 {ParseEventDescription procedure error cases} -body {\n    bind .t <a-b> {puts hi}\n} -returnCodes error -result {extra characters after detail in binding}\ntest bind-25.15 {ParseEventDescription procedure error cases} -body {\n    bind .t <<abc   {puts hi}\n} -returnCodes error -result {missing \">\" in virtual binding}\ntest bind-25.16 {ParseEventDescription procedure error cases} -body {\n    bind .t <<abc>  {puts hi}\n} -returnCodes error -result {missing \">\" in virtual binding}\ntest bind-25.17 {ParseEventDescription} -body {\n    event add <<xyz>> <<abc>>\n} -returnCodes error -result {virtual event not allowed in definition of another virtual event}\n\n# Modifier canonicalization tests\n\ntest bind-25.18 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f {<Control- a>} foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Control-Key-a>\n\ntest bind-25.19 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Shift-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Shift-Key-a>\n\ntest bind-25.20 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Lock-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Lock-Key-a>\n\ntest bind-25.21 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Meta---a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Meta-Key-a>\n\ntest bind-25.22 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Meta-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Meta-Key-a>\n\ntest bind-25.23 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Alt-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Alt-Key-a>\n\ntest bind-25.24 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <B1-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B1-Key-a>\n\ntest bind-25.25 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <B2-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B2-Key-a>\n\ntest bind-25.26 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <B3-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B3-Key-a>\n\ntest bind-25.27 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <B4-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B4-Key-a>\n\ntest bind-25.28 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <B5-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B5-Key-a>\n\ntest bind-25.29 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button1-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B1-Key-a>\n\ntest bind-25.30 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button2-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B2-Key-a>\n\ntest bind-25.31 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button3-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B3-Key-a>\n\ntest bind-25.32 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button4-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B4-Key-a>\n\ntest bind-25.33 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button5-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B5-Key-a>\n\ntest bind-25.34 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <M1-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod1-Key-a>\n\ntest bind-25.35 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <M2-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod2-Key-a>\n\ntest bind-25.36 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <M3-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod3-Key-a>\n\ntest bind-25.37 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <M4-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod4-Key-a>\n\ntest bind-25.38 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <M5-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod5-Key-a>\n\ntest bind-25.39 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Mod1-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod1-Key-a>\n\ntest bind-25.40 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Mod2-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod2-Key-a>\n\ntest bind-25.41 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Mod3-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod3-Key-a>\n\ntest bind-25.42 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Mod4-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod4-Key-a>\n\ntest bind-25.43 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Mod5-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod5-Key-a>\n\ntest bind-25.44 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Double-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Double-Key-a>\n\ntest bind-25.45 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Triple-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Triple-Key-a>\n\ntest bind-25.46 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f {<Double 1>} foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Double-Button-1>\n\ntest bind-25.47 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Triple-1> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Triple-Button-1>\n\ntest bind-25.48 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f {<M1-M2 M3-M4 B1-Control-a>} foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Control-B1-Mod1-Mod2-Mod3-Mod4-Key-a>\n\ntest bind-25.49 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Extended-Return> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Extended-Key-Return>\n\ntest bind-25.50 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button6-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B6-Key-a>\n\ntest bind-25.51 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button7-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B7-Key-a>\n\ntest bind-25.52 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button8-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B8-Key-a>\n\ntest bind-25.53 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Button9-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <B9-Key-a>\n\ntest bind-25.54 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Num-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod3-Key-a>\n\ntest bind-25.55 {modifier names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <Fn-a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Mod4-Key-a>\n\n\ntest bind-26.1 {event names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <FocusIn> {nothing}\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <FocusIn>\ntest bind-26.2 {event names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n} -body {\n    bind .t.f <FocusOut> {nothing}\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <FocusOut>\ntest bind-26.3 {event names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Destroy> {lappend x \"destroyed\"}\n    set x [bind .t.f]\n    destroy .t.f\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Destroy> destroyed}\n\ntest bind-26.4 {event names: Motion} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Motion> \"set x {event Motion}\"\n    set x xyzzy\n    event generate .t.f <Motion>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Motion} <Motion>}\n\ntest bind-26.5 {event names: Button} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> \"set x {event Button}\"\n    set x xyzzy\n    event generate .t.f <Button>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Button} <Button>}\n\ntest bind-26.7 {event names: ButtonRelease} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <ButtonRelease> \"set x {event ButtonRelease}\"\n    set x xyzzy\n    event generate .t.f <ButtonRelease>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event ButtonRelease} <ButtonRelease>}\n\ntest bind-26.8 {event names: Colormap} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Colormap> \"set x {event Colormap}\"\n    set x xyzzy\n    event generate .t.f <Colormap>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Colormap} <Colormap>}\n\ntest bind-26.9 {event names: Enter} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Enter> \"set x {event Enter}\"\n    set x xyzzy\n    event generate .t.f <Enter>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Enter} <Enter>}\n\ntest bind-26.10 {event names: Leave} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Leave> \"set x {event Leave}\"\n    set x xyzzy\n    event generate .t.f <Leave>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Leave} <Leave>}\n\ntest bind-26.11 {event names: Expose} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Expose> \"set x {event Expose}\"\n    set x xyzzy\n    event generate .t.f <Expose>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Expose} <Expose>}\n\ntest bind-26.12 {event names: Key} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Key> \"set x {event Key}\"\n    set x xyzzy\n    event generate .t.f <Key>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Key} <Key>}\n\ntest bind-26.14 {event names: KeyRelease} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <KeyRelease> \"set x {event KeyRelease}\"\n    set x xyzzy\n    event generate .t.f <KeyRelease>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event KeyRelease} <KeyRelease>}\n\ntest bind-26.15 {event names: Property} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Property> \"set x {event Property}\"\n    set x xyzzy\n    event generate .t.f <Property>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Property} <Property>}\n\ntest bind-26.16 {event names: Visibility} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Visibility> \"set x {event Visibility}\"\n    set x xyzzy\n    event generate .t.f <Visibility>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Visibility} <Visibility>}\n\ntest bind-26.17 {event names: Activate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Activate> \"set x {event Activate}\"\n    set x xyzzy\n    event generate .t.f <Activate>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Activate} <Activate>}\n\ntest bind-26.18 {event names: Deactivate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Deactivate> \"set x {event Deactivate}\"\n    set x xyzzy\n    event generate .t.f <Deactivate>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Deactivate} <Deactivate>}\n\n\n# These events require an extra argument to [event generate]\ntest bind-26.19 {event names: Circulate} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Circulate> \"set x {event Circulate}\"\n    set x xyzzy\n    event generate .t.f <Circulate>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Circulate} <Circulate>}\n\ntest bind-26.20 {event names: Configure} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Configure> \"set x {event Configure}\"\n    set x xyzzy\n    event generate .t.f <Configure>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Configure} <Configure>}\n\ntest bind-26.21 {event names: Gravity} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Gravity> \"set x {event Gravity}\"\n    set x xyzzy\n    event generate .t.f <Gravity>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Gravity} <Gravity>}\n\ntest bind-26.22 {event names: Map} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Map> \"set x {event Map}\"\n    set x xyzzy\n    event generate .t.f <Map>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Map} <Map>}\n\ntest bind-26.23 {event names: Reparent} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Reparent> \"set x {event Reparent}\"\n    set x xyzzy\n    event generate .t.f <Reparent>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Reparent} <Reparent>}\n\ntest bind-26.24 {event names: Unmap} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Unmap> \"set x {event Unmap}\"\n    set x xyzzy\n    event generate .t.f <Unmap>\n    list $x [bind .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {{event Unmap} <Unmap>}\n\n\ntest bind-27.1 {button names} -body {\n    bind .t <Expose-1> foo\n} -returnCodes error -result {specified button \"1\" for non-button event}\ntest bind-27.2 {button names} -body {\n    bind .t <Button-10> foo\n} -returnCodes error -result {bad button number \"10\"}\ntest bind-27.3 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-1> {lappend x \"button 1\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-1> {button 1}}\ntest bind-27.4 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-2> {lappend x \"button 2\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-2>\n    event generate .t.f <ButtonRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-2> {button 2}}\ntest bind-27.5 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-3> {lappend x \"button 3\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-3>\n    event generate .t.f <ButtonRelease-3>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-3> {button 3}}\ntest bind-27.6 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-4> {lappend x \"button 4\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-4>\n    event generate .t.f <ButtonRelease-4>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-4> {button 4}}\ntest bind-27.7 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-5> {lappend x \"button 5\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-5>\n    event generate .t.f <ButtonRelease-5>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-5> {button 5}}\ntest bind-27.8 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-6> {lappend x \"button 6\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-6>\n    event generate .t.f <ButtonRelease-6>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-6> {button 6}}\ntest bind-27.9 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-7> {lappend x \"button 7\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-7>\n    event generate .t.f <ButtonRelease-7>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-7> {button 7}}\ntest bind-27.10 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-8> {lappend x \"button 8\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-8>\n    event generate .t.f <ButtonRelease-8>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-8> {button 8}}\ntest bind-27.11 {button names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button-9> {lappend x \"button 9\"}\n    set x [bind .t.f]\n    event generate .t.f <Button-9>\n    event generate .t.f <ButtonRelease-9>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Button-9> {button 9}}\n\ntest bind-28.1 {keysym names} -body {\n    bind .t <Expose-a> foo\n} -returnCodes error -result {specified keysym \"a\" for non-key event}\ntest bind-28.2 {keysym names} -body {\n    bind .t <Gorp> foo\n} -returnCodes error -result {bad event type or keysym \"Gorp\"}\ntest bind-28.3 {keysym names} -body {\n    bind .t <Stupid> foo\n} -returnCodes error -result {bad event type or keysym \"Stupid\"}\ntest bind-28.4 {keysym names} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <a> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result {a}\n\ntest bind-28.5 {keysym names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <:> \"lappend x \\\"keysym received\\\"\"\n    bind .t.f <_> \"lappend x {bad binding match}\"\n    set x [lsort [bind .t.f]]\n    event generate .t.f <:> ;# -state 0\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {: _ {keysym received}}\ntest bind-28.6 {keysym names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Return> \"lappend x \\\"keysym Return\\\"\"\n    bind .t.f <x> \"lappend x {bad binding match}\"\n    set x [lsort [bind .t.f]]\n    event generate .t.f <Return> -state 0\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {<Key-Return> x {keysym Return}}\ntest bind-28.7 {keysym names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <X> \"lappend x \\\"keysym X\\\"\"\n    bind .t.f <x> \"lappend x {bad binding match}\"\n    set x [lsort [bind .t.f]]\n    event generate .t.f <X> -state 1\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {X x {keysym X}}\ntest bind-28.8 {keysym names} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <X> \"lappend x \\\"keysym X\\\"\"\n    bind .t.f <x> \"lappend x {bad binding match}\"\n    set x [lsort [bind .t.f]]\n    event generate .t.f <X> -state 1\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {X x {keysym X}}\ntest bind-28.9 {keysym names, Ð} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <Ð> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Key-Ð>\ntest bind-28.10 {keysym names, Ø} -constraints deprecated -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <Ø> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Key-Ø>\ntest bind-28.11 {keysym names, gcedilla} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <gcedilla> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Key-gcedilla>\ntest bind-28.12 {keysym names, Greek_IOTAdiaeresis -> Greek_IOTAdieresis} -constraints deprecated -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <Greek_IOTAdiaeresis> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result <Key-Greek_IOTAdieresis>\ntest bind-28.13 {keysym names, Unicode} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <€> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result \"<Key-€>\"\ntest bind-28.14 {keysym names, Emoji} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <\\U1F44D> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result \"<Key-\\U1F44D>\"\ntest bind-28.15 {keysym names, Emoji} -body {\n    frame .t.f -class Test -width 150 -height 100\n    bind .t.f <👍> foo\n    bind .t.f\n} -cleanup {\n    destroy .t.f\n} -result \"<Key-👍>\"\n\n\ntest bind-29.1 {Tcl_BackgroundError procedure} -setup {\n    proc bgerror msg {\n\tglobal x errorInfo\n\tset x [list $msg $errorInfo]\n    }\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {error \"This is a test\"}\n    set x none\n    event generate .t.f <Button>\n    event generate .t.f <ButtonRelease>\n    update\n    set x\n} -cleanup {\n    destroy .t.f\n    rename bgerror {}\n} -result {{This is a test} {This is a test\n    while executing\n\"error \"This is a test\"\"\n    (command bound to event)}}\n\ntest bind-29.2 {Tcl_BackgroundError procedure} -setup {\n    proc do {} {\n\tevent generate .t.f <Button>\n\tevent generate .t.f <ButtonRelease>\n    }\n    proc bgerror msg {\n\tglobal x errorInfo\n\tset x [list $msg $errorInfo]\n    }\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    bind .t.f <Button> {error Message2}\n    set x none\n    do\n    update\n    set x\n} -cleanup {\n    destroy .t.f\n    rename bgerror {}\n    rename do {}\n} -result {Message2 {Message2\n    while executing\n\"error Message2\"\n    (command bound to event)}}\n\n\ntest bind-30.1 {MouseWheel events} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <MouseWheel> {set x Wheel}\n    event generate .t.f <MouseWheel>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Wheel}\ntest bind-30.2 {MouseWheel events} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <MouseWheel> {set x %D}\n    event generate .t.f <MouseWheel> -delta 120\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 120\ntest bind-30.3 {MouseWheel events} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <MouseWheel> {set x \"%D %x %y\"}\n    event generate .t.f <MouseWheel> -delta 240 -x 10 -y 30\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {240 10 30}\n\n\ntest bind-31.1 {virtual event user_data field - bad generation} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n# Check no confusion, since Focus events use %d for something else\n    event generate .t.f <FocusIn> -data foo\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {<FocusIn> event doesn't accept \"-data\" option}\ntest bind-31.2 {virtual event user_data field - NULL, synch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {TestUserData >{}<}\ntest bind-31.3 {virtual event user_data field - shared, synch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>> -data \"foo bar\"\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {TestUserData >foo bar<}\ntest bind-31.4 {virtual event user_data field - unshared, synch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>> -data [string index abc 1]\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {TestUserData >b<}\n# Note that asynch event handling can only really catch any potential\n# extra errors when used in combination with a tool like Purify or\n# Valgrind. Such testing is rarely done, but at least any problem with\n# reference handling will eventually show up with these tests...\ntest bind-31.5 {virtual event user_data field - NULL, asynch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>> -when head\n    list $x [update] $x\n} -cleanup {\n    destroy .t.f\n} -result {{} {} {TestUserData >{}<}}\ntest bind-31.6 {virtual event user_data field - shared, asynch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>> -data \"foo bar\" -when head\n    list $x [update] $x\n} -cleanup {\n    destroy .t.f\n} -result {{} {} {TestUserData >foo bar<}}\ntest bind-31.7 {virtual event user_data field - unshared, asynch} -setup {\n    frame .t.f -class Test -width 150 -height 100\n    pack .t.f\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <<TestUserData>> {set x \"TestUserData >%d<\"}\n    event generate .t.f <<TestUserData>> -data [string index abc 1] -when head\n    list $x [update] $x\n} -cleanup {\n    destroy .t.f\n} -result {{} {} {TestUserData >b<}}\n\ntest bind-32.1 {-warp, window was destroyed before the idle callback DoWarp} -setup {\n    # note: this test is now essentially useless\n    #       since DoWarp no longer exist, not even as an idle callback\n    frame .t.f\n    pack .t.f\n    focus -force .t.f\n    update\n} -body {\n    event generate .t.f <Button-1> -warp 1\n    controlPointerWarpTiming\n    event generate .t.f <ButtonRelease-1>\n    destroy .t.f\n    update  ;  # shall simply not crash\n} -cleanup {\n} -result {}\ntest bind-32.2 {detection of double click should not fail} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    bind .t.f <Double-Button-1> { set x \"Double\" }\n    update\n    set x {}\n} -body {\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    # Simulate a lot of intervening exposure events. The old implementation\n    # that used an event ring overflowed, and the double click was not detected.\n    # But new implementation should work properly.\n    for {set i 0} {$i < 1000} {incr i} {\n\tevent generate .t.f <Expose>\n    }\n    event generate .t.f <Button-1>\n    event generate .t.f <ButtonRelease-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Double}\ntest bind-32.3 {should trigger best match of modifier states} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Alt-Control-A> { lappend x \"Alt-Control\" }\n    bind .t.f <Shift-Control-A> { lappend x \"Shift-Control\" }\n    bind .t.f <Shift-A> { lappend x \"Shift\" }\n    event generate .t.f <Alt-Control-A>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Shift-Control}\ntest bind-32.4 {should not trigger Double-1} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Double-Button-1> { set x \"Double\" }\n    event generate .t.f <Button-1> -time current\n    after 1000\n    event generate .t.f <Button-1> -time current\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest bind-32.5 {should trigger Quadruple-1} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Quadruple-Button-1> { set x \"Quadruple\" }\n    bind .t.f <Triple-Button-1> { set x \"Triple\" }\n    bind .t.f <Double-Button-1> { set x \"Double\" }\n    bind .t.f <Button-1> { set x \"Single\" }\n    # Old implementation triggered \"Double\", but new implementation\n    # triggers \"Quadruple\", the latter behavior conforms to other toolkits.\n    event generate .t.f <Button-1> -time 0\n    event generate .t.f <Button-1> -time 400\n    event generate .t.f <Button-1> -time 800\n    event generate .t.f <Button-1> -time 1200\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Quadruple}\ntest bind-32.6 {problem with sendevent} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    # Old implementation was losing sendevent value\n    bind .t.f <FocusIn> { set x \"sendevent=%E\" }\n    event generate .t.f <FocusIn> -sendevent 1\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {sendevent=1}\ntest bind-32.7 {test sequences} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Double-Button-1> { lappend x \"Double\" }\n    bind .t.f <Button-1><Button-1><a> { lappend x \"11\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Double 11}\ntest bind-32.8 {test sequences} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <a><Button-1><Double-Button-1><Button-1><a> { lappend x \"Double\" }\n    event generate .t.f <a>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Double}\ntest bind-32.9 {trigger events for modifier keys} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key> { set x \"Key\" }\n    event generate .t.f <Key> -keysym Caps_Lock\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Key}\ntest bind-32.10 {reset key state when destroying window} -setup {\n    set x {}\n} -body {\n    pack [frame .t.f]; update; focus -force .t.f\n    bind .t.f <A> { set x \"A\" }\n    event generate .t.f <A>\n    event generate .t.f <A>\n    destroy .t.f; update\n    pack [frame .t.f]; update; focus -force .t.f\n    bind .t.f <A> { set x \"A\" }\n    bind .t.f <Double-A> { set x \"AA\" }\n    event generate .t.f <A>\n    destroy .t.f\n    set x\n} -result {A}\ntest bind-32.11 {match detailed virtual} -setup {\n    pack [frame .t.f -class Test]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    event add <<TestControlButton1>> <Control-Button-1>\n    bind Test <<TestControlButton1>> { set x \"Control-Button-1\" }\n    bind Test <Button-1> { set x \"Button-1\" }\n    bind .t.f <Button-1> { set x \"Button-1\" }\n    event generate .t.f <Control-Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    event delete <<TestControlButton1>>\n    bind Test <Button-1> {#}\n} -result {Control-Button-1}\ntest bind-32.12 {don't detect repetition when window has changed} -setup {\n    pack [frame .t.f]\n    pack [frame .t.g]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> { set x \"1\" }\n    bind .t.f <Double-Button-1> { set x \"11\" }\n    event generate .t.f <Button-1>\n    event generate .t.g <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    destroy .t.g\n} -result 1\ntest bind-32.13 {don't detect repetition when window has changed} -setup {\n    pack [frame .t.f]\n    pack [frame .t.g]\n    update\n    set x {}\n} -body {\n    bind .t.f <A> { set x \"A\" }\n    bind .t.f <Double-A> { set x \"AA\" }\n    focus -force .t.f; event generate .t.f <A>\n    focus -force .t.g; event generate .t.g <A>\n    focus -force .t.f; event generate .t.f <A>\n    set x\n} -cleanup {\n    destroy .t.f\n    destroy .t.g\n} -result {A}\ntest bind-32.14 {don't detect repetition when window has changed} -setup {\n    pack [frame .t.f]\n    pack [frame .t.g]\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1> { set x \"1\" }\n    bind .t.f <Double-Button-1> { set x \"11\" }\n    focus -force .t.f; event generate .t.f <Button-1>\n    focus -force .t.g; event generate .t.g <Button-1>\n    focus -force .t.f; event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    destroy .t.g\n} -result 1\ntest bind-32.15 {reset button state when destroying window} -setup {\n    set x {}\n} -body {\n    pack [frame .t.f]; update; focus -force .t.f\n    bind .t.f <Button-1> { set x \"1\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    destroy .t.f; update\n    pack [frame .t.f]; update; focus -force .t.f\n    bind .t.f <Button-1> { set x \"1\" }\n    bind .t.f <Double-Button-1> { set x \"11\" }\n    event generate .t.f <Button-1>\n    destroy .t.f\n    set x\n} -result 1\n\ntest bind-33.1 {prefer longest match} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <a><Button-1><Button-1> { lappend x \"a11\" }\n    bind .t.f <Double-Button-1> { lappend x \"Double\" }\n    event generate .t.f <a>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {a11}\ntest bind-33.2 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Double-Button-1> { lappend x \"Double\" }\n    bind .t.f <Button-1><Button-1> { lappend x \"11\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result Double\ntest bind-33.3 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <a><Double-Button-1><a> { lappend x \"Double\" }\n    bind .t.f <a><Button-1><Button-1><a> { lappend x \"11\" }\n    event generate .t.f <a>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result Double\ntest bind-33.4 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-1> { lappend x \"11\" }\n    bind .t.f <Double-Button-1> { lappend x \"Double\" }\n    event generate .t.f <Button-1> -time 0\n    event generate .t.f <Button-1> -time 1000\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 11\ntest bind-33.5 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-1> { lappend x \"11\" }\n    bind .t.f <Double-Button> { lappend x \"Double\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 11\ntest bind-33.6 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <a><Button-1><Button-1><Button-1><Button-1><a> { lappend x \"1111\" }\n    bind .t.f <a><Button><Double-Button><Button><a> { lappend x \"Any-Double-Any\" }\n    event generate .t.f <a>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1111\ntest bind-33.7 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><a> { lappend x \"1\" }\n    bind .t.f <Button><a> { lappend x \"Any\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-33.8 {prefer most specific event} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Double-Button-1><a> { lappend x \"1\" }\n    bind .t.f <Button><Button><a> { lappend x \"Any\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <a>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result 1\ntest bind-33.9 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button-2><Button-2><Double-Button-1> { lappend x \"first\" }\n    bind .t.f <Button-1><Double-Button-2><Button-1><Button-1> { lappend x \"last\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result last\ntest bind-33.10 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Double-Button-2><Button-1><Button-1> { lappend x \"first\" }\n    bind .t.f <Button-1><Button-2><Button-2><Double-Button-1> { lappend x \"last\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result last\ntest bind-33.11 {should prefer most specific} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-2><Double-Button-1><Double-Button-2><Double-Button-1><Button-2><Button-2> { lappend x \"first\" }\n    bind .t.f <Button-2><Button-1><Button-1><Button-2><Button-2><Double-Button-1><Double-Button-2> { lappend x \"last\" }\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-2>\n    event generate .t.f <Button-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result first\ntest bind-33.12 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Control-Button-1><Button-1> { lappend x \"first\" }\n    bind .t.f <Button-1><Control-Button-1> { lappend x \"last\" }\n    event generate .t.f <Control-Button-1>\n    event generate .t.f <Control-Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result last\ntest bind-33.13 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Control-Button-1> { lappend x \"first\" }\n    bind .t.f <Control-Button-1><Button-1> { lappend x \"last\" }\n    event generate .t.f <Control-Button-1>\n    event generate .t.f <Control-Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    # Old implementation failed, and returned \"first\", but this was wrong,\n    # because both bindings are homogeneous equal, so the most recently defined\n    # must be preferred.\n} -result last\ntest bind-33.14 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button-1><Button><Button-1><Button> { lappend x \"first\" }\n    bind .t.f <Button><Button-1><Button><Button-1> { lappend x \"last\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result last\ntest bind-33.15 {prefer last in case of homogeneous equal patterns} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Button><Button-1><Button><Button-1> { lappend x \"first\" }\n    bind .t.f <Button-1><Button><Button-1><Button> { lappend x \"last\" }\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n    # Old implementation failed, and returned \"first\", but this was wrong,\n    # because both bindings are homogeneous equal, so the most recently defined\n    # must be preferred.\n} -result last\ntest bind-33.16 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Escape><Control-c> { lappend x \"Esc_Control-c\" }\n    event generate .t.f <Escape>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control-c>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Esc_Control-c}\ntest bind-33.17 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Escape><Control-c> { lappend x \"Esc_Control-c\" }\n    bind .t.f <Escape><Control_L><Control-c> { lappend x \"Esc_Ctrl_L_Control-c\" }\n    event generate .t.f <Escape>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control-c>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Esc_Ctrl_L_Control-c}\ntest bind-33.18 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Escape><Control-c> { lappend x \"Esc_Control-c\" }\n    bind .t.f <Escape><Control_L><Control-c> { lappend x \"Esc_Ctrl_L_Control-c\" }\n    bind .t.f <Escape><Control_L><Control_L><Control-c> { lappend x \"Esc_Ctrl_L(2)_Control-c\" }\n    event generate .t.f <Escape>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control-c>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Esc_Ctrl_L(2)_Control-c}\ntest bind-33.19 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Escape><Control-c> { lappend x \"Esc_Control-c\" }\n    bind .t.f <Escape><Key><Key><Control-c> { lappend x \"Esc_Key(2)_Control-c\" }\n    event generate .t.f <Escape>\n    event generate .t.f <Alt_L>\n    event generate .t.f <Control_L>\n    event generate .t.f <Control-c>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {Esc_Key(2)_Control-c}\ntest bind-33.20 {simulate use of the keyboard to trigger a pattern sequence with mixed Key and Button types - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key-1><Button-1> { lappend x \"1_Button1\" }\n    event generate .t.f <Key-1>\n    event generate .t.f <KeyRelease-1>\n    event generate .t.f <Button-1>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {1_Button1}\ntest bind-33.21 {simulate use of the keyboard to trigger a pattern sequence with mixed Key and Button types - bug [16ef161925]} -setup {\n    pack [frame .t.f]\n    focus -force .t.f\n    update\n    set x {}\n} -body {\n    bind .t.f <Key-1><Button-1> { lappend x \"1_Button1\" }\n    bind .t.f <Key-1><Button-1><Key-2> { lappend x \"1_Button1_2\" }\n    event generate .t.f <Key-1>\n    event generate .t.f <KeyRelease-1>\n    event generate .t.f <Button-1>\n    event generate .t.f <Key-2>\n    event generate .t.f <KeyRelease-2>\n    set x\n} -cleanup {\n    destroy .t.f\n} -result {1_Button1 1_Button1_2}\n\ntest bind-34.1 {-warp works relatively to a window} -setup {\n    toplevel .top\n    wm geometry .top +100+100\n    after 10 ; update\n} -body {\n    # In order to avoid platform-dependent coordinate results due to\n    # decorations and borders, this test warps the pointer twice\n    # relatively to a window that moved in the meantime, and checks\n    # how much the pointer moved\n    wm geometry .top +200+200\n    after 10 ; update\n    event generate .top <Motion> -x 20 -y 20 -warp 1\n    controlPointerWarpTiming\n    set pointerPos1 [winfo pointerxy .top]\n    wm geometry .top +600+600\n    after 10 ; update\n    event generate .top <Motion> -x 20 -y 20 -warp 1\n    controlPointerWarpTiming\n    set pointerPos2 [winfo pointerxy .top]\n    # from the first warped position to the second one, the mouse\n    # pointer should have moved the same amount as the window moved\n    set res 1\n    foreach pos1 $pointerPos1 pos2 $pointerPos2 {\n\tif {$pos1 != ($pos2 - 400)} {\n\t    set res [list $pointerPos1 $pointerPos2]\n\t}\n    }\n    set res\n} -cleanup {\n    destroy .top\n} -result 1\ntest bind-34.2 {-warp works relatively to the screen} -setup {\n} -body {\n    # Contrary to bind-34.1, we're directly checking screen coordinates\n    event generate {} <Motion> -x 20 -y 20 -warp 1\n    controlPointerWarpTiming\n    set res [winfo pointerxy .]\n    event generate {} <Motion> -x 200 -y 200 -warp 1\n    controlPointerWarpTiming\n    lappend res {*}[winfo pointerxy .]\n} -cleanup {\n} -result {20 20 200 200}\ntest bind-34.3 {-warp works with null or negative coordinates} -setup {\n    # On some OS/WM, at least Linux with KDE, the \"Screen edges\" feature\n    # provides hot spots that can be associated with some action.\n    # When activated, the WM will not allow warping to happen on top of\n    # a hot spot (which would trigger the corresponding action as an\n    # unwanted effect) but will warp the pointer to the hot spot limit only.\n    if {[tk windowingsystem] eq \"x11\"} {\n\tset halo 1\n    } else {\n\tset halo 0\n    }\n    set res {}\n} -body {\n    event generate {} <Motion> -x 0 -y 0 -warp 1\n    controlPointerWarpTiming\n    foreach dim [winfo pointerxy .] {\n\tif {$dim <= $halo} {\n\t    lappend res ok\n\t} else {\n\t    lappend res $dim\n\t}\n    }\n    event generate {} <Motion> -x 100 -y 100 -warp 1\n    controlPointerWarpTiming\n    event generate {} <Motion> -x -1 -y -1 -warp 1\n    controlPointerWarpTiming\n    foreach dim [winfo pointerxy .] {\n\tif {$dim <= $halo} {\n\t    lappend res ok\n\t} else {\n\t    lappend res $dim\n\t}\n    }\n    set res\n} -cleanup {\n} -result {ok ok ok ok}\ntest bind-34.4 {Pointer warp relative to the root window of the screen when the Tk root window is unmapped. (Ticket e2418ce5fe)} -setup {\n    deleteWindows\n    if {! [winfo ismapped .]} {\n\twm deiconify .\n\twm geometry . 200x200+100+100\n\tafter 10; update\n    }\n    event generate {} <Motion> -warp 1 -x 350 -y 200\n    controlPointerWarpTiming\n    wm withdraw .\n    assert {([winfo ismapped .] == 0) && ([winfo pointerx .] == 350) && ([winfo pointery .] == 200)}\n} -body {\n    event generate {} <Motion> -warp 1 -x 360 -y 250\n    controlPointerWarpTiming\n    winfo pointerxy .\n} -cleanup {\n    wm deiconify .\n} -result {360 250}\ntest bind-34.5 {Pointer warp relative to an arbitrary toplevel when the Tk root window is unmapped. (Ticket e2418ce5fe)} -setup {\n    deleteWindows\n    if {! [winfo ismapped .]} {\n\twm deiconify .\n\twm geometry . 200x200+100+100\n\tafter 10; update\n    }\n    event generate {} <Motion> -warp 1 -x 350 -y 200\n    controlPointerWarpTiming\n    toplevel .one\n    wm geometry .one 200x200+100+350\n    after 10; update\n    wm withdraw .\n    assert {([winfo ismapped .] == 0) && ([winfo pointerx .] == 350) && ([winfo pointery .] == 200)}\n} -body {\n    event generate .one <Motion> -warp 1 -x 250 -y 100\n    after 10; update\n    list [expr {[winfo pointerx .one] - [winfo rootx .one]}] [expr {[winfo pointery .one] - [winfo rooty .one]}]\n} -cleanup {\n    wm deiconify .\n} -result {250 100}\n\ntest bind-35.0 {Generated and real key events agree} -constraints {aqua} -body {\n    foreach k {o O F2 Home Right Greek_sigma Greek_ALPHA} {\n\tset result [testKeyWithMods . $k press]\n\tif {$result ne \"pass\"} {\n\t    return $result\n\t}\n    }\n    return pass\n} -cleanup {\n} -result pass\n\ntest bind-35.1 {Key events agree for entry widgets} -constraints {aqua} -setup {\n    toplevel .new\n    entry .new.e\n    pack .new.e\n} -body {\n    foreach k {o O F2 Home Right Greek_sigma Greek_ALPHA Menu} {\n\tset result [testKeyWithMods .new.e $k press]\n\tif {$result ne \"pass\"} {\n\t    return $result\n\t}\n    }\n    return pass\n} -cleanup {\n    destroy .new.e\n    destroy .new\n} -result pass\n\ntest bind-35.2 {Can bind to function keys} -constraints {aqua} -body {\n    global keyInfo numericKeysym\n    bind . <Key> {}\n    bind . <Key> {\n\tlappend keyInfo %K\n\tset numericKeysym %N\n    }\n    set keyInfo {}\n    set numericKeysym {}\n    focus -force .\n    event generate . <F2>\n    testinjectkeyevent press $numericKeysym -function\n    vwait keyInfo\n    return $keyInfo\n} -cleanup {\n} -result {F2 F2}\n\ntest bind-35.3 {Events agree for modifier keys} -constraints {aqua} -setup {\n} -body {\n    global keyInfo numericalKeysym\n    set result {}\n    bind . <Key> {\n\tset keyInfo [format \"%K,0x%%X,0x%%X,%A\" %N %k]\n\tset numericalKeysym [format \"0x%x\" %N]\n    }\n    foreach event {\n\t{<Control_L> -control}\n\t{<Control_R> -control}\n\t{<Alt_L> -option}\n\t{<Alt_R> -option}\n\t{<Meta_L> -command}\n\t{<Meta_R> -command}\n\t{<Shift_L> -shift}\n\t{<Shift_R> -shift}\n    } {\n\tset keyInfo {}\n\tevent generate . [lindex $event 0]\n\tif {$keyInfo eq {}} {\n\t    vwait keyInfo\n\t}\n\tset save $keyInfo\n\ttestinjectkeyevent flagschanged $numericKeysym [lindex $event 1]\n\tif {$keyInfo eq {}} {\n\t    vwait keyInfo\n\t}\n\tif {$save ne $keyInfo} {\n\t    return \"$save ne $keyInfo\"\n\t}\n    }\n    return pass\n} -cleanup {\n} -result pass\n\ntest bind-36.1 {pointer warp with grab on toplevel, bug [e3888d5820]} -setup {\n    event generate {} <Motion> -warp 1 -x 50 -y 50\n    controlPointerWarpTiming\n    toplevel .top\n    grab release .top\n    wm geometry .top 200x200+300+300\n    label .top.l -height 5 -width 20 -highlightthickness 2 \\\n\t    -highlightbackground black -bg yellow -text \"My label\"\n    pack .top.l -side bottom\n    update\n    # On KDE/Plasma _with_the_Aurorae_theme_ (at least), setting up the toplevel\n    # and the label will not be finished after the above 'update'. The WM still\n    # needs some time before the window is fully ready. For me 50 ms is enough,\n    # but let's wait more (it depends on computer performance).\n    after 100 ; update\n} -body {\n    grab .top\n    event generate .top.l <Motion> -warp 1 -x 10 -y 10\n    controlPointerWarpTiming\n    foreach {x1 y1} [winfo pointerxy .top.l] {}\n    event generate {} <Motion> -warp 1 -x 50 -y 50\n    controlPointerWarpTiming\n    grab release .top\n    event generate .top.l <Motion> -warp 1 -x 10 -y 10\n    controlPointerWarpTiming\n    foreach {x2 y2} [winfo pointerxy .top.l] {}\n    # success if the coords are the same with or without the grab, and if they\n    # are at (10,10) inside the label widget as requested by the warping\n    expr {$x1==$x2 && $y1==$y2 && $x1==[winfo rootx .top.l]+10 \\\n\t\t\t       && $y1==[winfo rooty .top.l]+10}\n} -cleanup {\n    destroy .top\n    unset x1 y1 x2 y2\n} -result 1\n\ntest bind-37.1 {Promotion tables do not contain duplicate sequences, bug [43573999ca]} -body {\n    proc A {} {\n       bind .c <B1-Motion><Enter> {}\n       set myv(a) 1\n       set b [array get myv]\n       bind .c <B1-Motion><Enter> \"puts Trigger\"\n    }\n    pack [canvas .c]\n    bind .c <ButtonRelease-1>  \"A\"\n    A\n    update\n    event generate .c <Button-1>\n    event generate .c <B1-Motion>\n    event generate .c <B1-Motion>\n    event generate .c <B1-Motion>\n    event generate .c <ButtonRelease-1>\n    event generate .c <B1-Motion>\n} -cleanup {\n    destroy .c\n} -returnCodes ok -result {}  ; # shall not crash (assertion failed)\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# vi:set ts=4 sw=4 et:\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/bitmap.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkBitmap.c.\n#\n# Copyright © 1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest bitmap-1.1 {Tk_AllocBitmapFromObj - converting internal reps} -constraints {\n    testbitmap\n} -body {\n    set x gray25\n    lindex $x 0\n    button .b -bitmap $x\n    lindex $x 0\n    testbitmap gray25\n} -cleanup {\n    destroy .b\n} -result {{1 0}}\ntest bitmap-1.2 {Tk_AllocBitmapFromObj - discard stale bitmap} -constraints {\n    testbitmap\n} -setup {\n    set result {}\n} -body {\n    set x gray25\n    button .b1 -bitmap $x\n    destroy .b1\n    lappend result [testbitmap gray25]\n    button .b2 -bitmap $x\n    lappend result [testbitmap gray25]\n} -cleanup {\n    destroy .b1 .b2\n} -result {{} {{1 1}}}\ntest bitmap-1.3 {Tk_AllocBitmapFromObj - reuse existing bitmap} -constraints {\n    testbitmap\n} -setup {\n    set result {}\n} -body {\n    set x gray25\n    button .b1 -bitmap $x\n    lappend result [testbitmap gray25]\n    button .b2 -bitmap $x\n    pack .b1 .b2 -side top\n    lappend result [testbitmap gray25]\n} -cleanup {\n    destroy .b1 .b2\n} -result {{{1 1}} {{2 1}}}\n\ntest bitmap-2.1 {Tk_GetBitmap procedure} -body {\n    button .b1 -bitmap bad_name\n} -cleanup {\n    destroy .b1\n} -returnCodes error -result {bitmap \"bad_name\" not defined}\ntest bitmap-2.2 {Tk_GetBitmap procedure} -body {\n    button .b1 -bitmap @xyzzy\n} -cleanup {\n    destroy .b1\n} -returnCodes error -result {error reading bitmap file \"xyzzy\"}\n\ntest bitmap-3.1 {Tk_FreeBitmapFromObj - reference counts} -constraints {\n    testbitmap\n} -setup {\n    set result {}\n} -body {\n    set x questhead\n    button .b1 -bitmap $x\n    button .b3 -bitmap $x\n    button .b2 -bitmap $x\n    lappend result [testbitmap questhead]\n    destroy .b1\n    lappend result [testbitmap questhead]\n    destroy .b2\n    lappend result [testbitmap questhead]\n    destroy .b3\n    lappend result [testbitmap questhead]\n} -cleanup {\n    destroy .b1 .b2 .b3     ;# destroying just in case\n} -result {{{3 1}} {{2 1}} {{1 1}} {}}\n\ntest bitmap-4.1 {FreeBitmapObjProc} -constraints {\n    testbitmap\n} -setup {\n    proc copy {s} {return [string index $s 0][string range $s 1 end]}\n} -body {\n    set x [copy questhead]\n    button .b -bitmap $x\n    set y [copy questhead]\n    .b configure -bitmap $y\n    set z [copy questhead]\n    .b configure -bitmap $z\n    set result {}\n    lappend result [testbitmap questhead]\n    set x red\n    lappend result [testbitmap questhead]\n    set z 32\n    lappend result [testbitmap questhead]\n    destroy .b\n    lappend result [testbitmap questhead]\n    set y bogus\n    return $result\n} -cleanup {\n    rename copy {}\n    destroy .b\n} -result {{{1 3}} {{1 2}} {{1 1}} {}}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/border.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkBorder.c.\n#\n# Copyright © 1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest border-1.1 {Tk_AllocBorderFromObj - converting internal reps} -constraints {\n    testborder\n} -body {\n    set x orange\n    lindex $x 0\n    button .b1 -bg $x -text .b1\n    lindex $x 0\n    testborder orange\n} -cleanup {\n    destroy .b1\n} -result {{1 0}}\ntest border-1.2 {Tk_AllocBorderFromObj - discard stale border} -constraints {\n    testborder\n} -setup {\n    set result {}\n} -body {\n    set x orange\n    button .b1 -bg $x -text First\n    destroy .b1\n    lappend result [testborder orange]\n    button .b2 -bg $x -text Second\n    lappend result [testborder orange]\n} -cleanup {\n    destroy .b1 .b2\n} -result {{} {{1 1}}}\ntest border-1.3 {Tk_AllocBorderFromObj - reuse existing border} -constraints {\n    testborder\n} -setup {\n    set result {}\n} -body {\n    set x orange\n    button .b1 -bg $x -text First\n    lappend result [testborder orange]\n    button .b2 -bg $x -text Second\n    pack .b1 .b2 -side top\n    lappend result [testborder orange]\n} -cleanup {\n    destroy .b1 .b2\n} -result {{{1 1}} {{2 1}}}\ntest border-1.4 {Tk_AllocBorderFromObj - try other borders in list} -constraints {\n    testborder pseudocolor8\n} -setup {\n    toplevel .t -visual {pseudocolor 8} -colormap new\n    wm geom .t +0+0\n    set result {}\n} -body {\n    set x purple\n    button .b1 -bg $x -text First\n    pack .b1 -side top\n    lappend result [testborder purple]\n    button .t.b -bg $x -text Second\n    pack .t.b -side top\n    lappend result [testborder purple]\n    button .b2 -bg $x -text Third\n    pack .b2 -side top\n    lappend result [testborder purple]\n} -cleanup {\n    destroy .b1 .b2 .t\n} -result {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}\n\ntest border-2.1 {Tk_Free3DBorder - reference counts} -constraints {\n    testborder pseudocolor8\n} -setup {\n    toplevel .t -visual {pseudocolor 8} -colormap new\n    wm geom .t +0+0\n    set result {}\n} -body {\n    set x purple\n    button .b1 -bg $x -text First\n    pack .b1 -side top\n    button .t.b -bg $x -text Second\n    pack .t.b -side top\n    button .b2 -bg $x -text Third\n    pack .b2 -side top\n    lappend result [testborder purple]\n    destroy .b1\n    lappend result [testborder purple]\n    destroy .b2\n    lappend result [testborder purple]\n    destroy .t.b\n    lappend result [testborder purple]\n} -cleanup {\n    destroy .b1 .b2 .t\n} -result {{{1 0} {2 1}} {{1 0} {1 1}} {{1 0}} {}}\ntest border-2.2 {Tk_Free3DBorder - unlinking from list} -constraints {\n    testborder pseudocolor8\n} -setup {\n    toplevel .t -visual {pseudocolor 8} -colormap new\n    wm geom .t +0+0\n    toplevel .t2 -visual {pseudocolor 8} -colormap new\n    toplevel .t3 -visual {pseudocolor 8} -colormap new\n    set result {}\n} -body {\n    set x purple\n    button .b -bg $x -text .b1\n    button .t.b1 -bg $x -text .t.b1\n    button .t.b2 -bg $x -text .t.b2\n    button .t2.b1 -bg $x -text .t2.b1\n    button .t2.b2 -bg $x -text .t2.b2\n    button .t2.b3 -bg $x -text .t2.b3\n    button .t3.b1 -bg $x -text .t3.b1\n    button .t3.b2 -bg $x -text .t3.b2\n    button .t3.b3 -bg $x -text .t3.b3\n    button .t3.b4 -bg $x -text .t3.b4\n    lappend result [testborder purple]\n    destroy .t2\n    lappend result [testborder purple]\n    destroy .b\n    lappend result [testborder purple]\n    destroy .t3\n    lappend result [testborder purple]\n    destroy .t\n    lappend result [testborder purple]\n} -cleanup {\n    destroy .b .t2 .t3 .t\n} -result {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}}\n\n\ntest border-3.1 {FreeBorderObjProc} -constraints {\n    testborder\n} -setup {\n    set result {}\n    proc copy {s} {return [string index $s 0][string range $s 1 end]}\n} -body {\n    set x [copy purple]\n    button .b -bg $x -text .b1\n    set y [copy purple]\n    .b configure -bg $y\n    set z [copy purple]\n    .b configure -bg $z\n    lappend result [testborder purple]\n    set x red\n    lappend result [testborder purple]\n    set z 32\n    lappend result [testborder purple]\n    destroy .b\n    lappend result [testborder purple]\n    set y bogus\n    return $result\n} -cleanup {\n    rename copy {}\n    destroy .b\n} -result {{{1 3}} {{1 2}} {{1 1}} {}}\n\ntest border-4.1 {Tk_GetReliefFromObj} -body {\n    button .b -relief flat\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {flat}\ntest border-4.2 {Tk_GetReliefFromObj} -body {\n    button .b -relief groove\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {groove}\ntest border-4.3 {Tk_GetReliefFromObj} -body {\n    button .b -relief raised\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {raised}\ntest border-4.4 {Tk_GetReliefFromObj} -body {\n    button .b -relief ridge\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {ridge}\ntest border-4.5 {Tk_GetReliefFromObj} -body {\n    button .b -relief solid\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {solid}\ntest border-4.6 {Tk_GetReliefFromObj} -body {\n    button .b -relief sunken\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {sunken}\ntest border-4.7 {Tk_GetReliefFromObj - error} -body {\n    button .b -relief upanddown\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad relief \"upanddown\": must be flat, groove, raised, ridge, solid, or sunken}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/busy.test",
    "content": "# This file is a Tcl script to test out the tk busy command.\n#\n# Copyright © 1998-2000 Jos Decoster. All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest busy-1.1 {Tk_BusyObjCmd} -returnCodes error -body {\n    tk busy\n} -result {wrong # args: should be \"tk busy options ?arg ...?\"}\n\ntest busy-2.1 {tk busy hold} -returnCodes error -body {\n    tk busy hold\n} -result {wrong # args: should be \"tk busy hold window ?-option value ...?\"}\ntest busy-2.2 {tk busy hold root window} -body {\n    set res [tk busy hold .]\n    update\n    set res\n} -cleanup {\n    tk busy forget .\n} -result {._Busy}\ntest busy-2.3 {tk busy hold root window with shortcut} -body {\n    set res [tk busy .]\n    update\n    set res\n} -cleanup {\n    tk busy forget .\n} -result {._Busy}\ntest busy-2.4 {tk busy hold nested window} -setup {\n    pack [frame .f]\n} -body {\n    set res [tk busy hold .f]\n    update\n    set res\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f_Busy}\ntest busy-2.5 {tk busy hold nested window with shortcut} -setup {\n    pack [frame .f]\n} -body {\n    set res [tk busy .f]\n    update\n    set res\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f_Busy}\ntest busy-2.6 {tk busy hold toplevel window} -setup {\n    toplevel .f\n} -body {\n    set res [tk busy hold .f]\n    update\n    set res\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f._Busy}\ntest busy-2.7 {tk busy hold toplevel window with shortcut} -setup {\n    toplevel .f\n} -body {\n    set res [tk busy .f]\n    update\n    set res\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f._Busy}\ntest busy-2.8 {tk busy hold non existing window} -body {\n    tk busy hold .f\n    update\n} -returnCodes error -result {bad window path name \".f\"}\ntest busy-2.9 {tk busy hold (shortcut) non existing window} -body {\n    tk busy .f\n    update\n} -returnCodes error -result {bad window path name \".f\"}\ntest busy-2.10 {tk busy hold root window with cursor} -body {\n    set res [tk busy hold . -cursor arrow]\n    update\n    set res\n} -cleanup {\n    tk busy forget .\n} -result {._Busy}\ntest busy-2.11 {tk busy hold (shortcut) root window, cursor} -body {\n    set res [tk busy . -cursor arrow]\n    update\n    set res\n} -cleanup {\n    tk busy forget .\n} -result {._Busy}\ntest busy-2.12 {tk busy hold root window, invalid cursor} -body {\n    tk busy hold . -cursor nonExistingCursor\n    update\n} -returnCodes error -cleanup {\n    tk busy forget .\n} -result {bad cursor spec \"nonExistingCursor\"}\ntest busy-2.13 {tk busy hold (shortcut) root window, invalid cursor} -body {\n    tk busy . -cursor nonExistingCursor\n    update\n} -returnCodes error -cleanup {\n    tk busy forget .\n} -result {bad cursor spec \"nonExistingCursor\"}\ntest busy-2.14 {tk busy hold root window, invalid option} -body {\n    tk busy hold . -invalidOption 1\n    update\n} -returnCodes error -cleanup {\n    tk busy forget .\n} -result {unknown option \"-invalidOption\"}\ntest busy-2.15 {tk busy hold (shortcut) root window, invalid option} -body {\n    tk busy . -invalidOption 1\n    update\n} -returnCodes error -cleanup {\n    tk busy forget .\n} -result {unknown option \"-invalidOption\"}\n\ntest busy-3.1 {tk busy cget no window} -returnCodes error -body {\n    tk busy cget\n} -result {wrong # args: should be \"tk busy cget window option\"}\ntest busy-3.2 {tk busy cget no option} -returnCodes error -body {\n    tk busy cget\n} -result {wrong # args: should be \"tk busy cget window option\"}\ntest busy-3.3 {tk busy cget invalid window} -returnCodes error -body {\n    tk busy cget .f -cursor\n} -result {bad window path name \".f\"}\ntest busy-3.4 {tk busy cget non-busy window} -setup {\n    pack [frame .f]\n} -body {\n    tk busy cget .f -cursor\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {cannot find busy window \".f\"}\ntest busy-3.5 {tk busy cget invalid option} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy cget .f -invalidOption\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -returnCodes error -result {unknown option \"-invalidOption\"}\ntest busy-3.6unix {tk busy cget unix} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy cget .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {watch} -constraints unix\ntest busy-3.6win {tk busy cget win} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy cget .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {wait} -constraints win\ntest busy-3.7 {tk busy cget unix} -setup {\n    pack [frame .f]\n    tk busy hold .f -cursor hand1\n    update\n} -body {\n    tk busy cget .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {hand1}\n\ntest busy-4.1 {tk busy configure no window} -returnCodes error -body {\n    tk busy configure\n} -result {wrong # args: should be \"tk busy configure window ?-option value ...?\"}\n\ntest busy-4.2 {tk busy configure invalid window} -body {\n    tk busy configure .f\n} -returnCodes error -result {bad window path name \".f\"}\n\ntest busy-4.3 {tk busy configure non-busy window} -setup {\n    pack [frame .f]\n} -body {\n    tk busy configure .f\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {cannot find busy window \".f\"}\n\ntest busy-4.4 {tk busy configure} -constraints macOrUnix -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {{-cursor cursor Cursor watch watch}}\n\ntest busy-4.4-win {tk busy configure} -constraints {win} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {{-cursor cursor Cursor wait wait}}\n\ntest busy-4.5 {tk busy configure} -constraints macOrUnix -setup {\n    pack [frame .f]\n    tk busy hold .f -cursor hand2\n    update\n} -body {\n    tk busy configure .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {{-cursor cursor Cursor watch hand2}}\n\ntest busy-4.5-win {tk busy configure} -constraints win -setup {\n    pack [frame .f]\n    tk busy hold .f -cursor hand2\n    update\n} -body {\n    tk busy configure .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {{-cursor cursor Cursor wait hand2}}\n\ntest busy-4.6 {tk busy configure invalid option} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f -invalidOption\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -returnCodes error -result {unknown option \"-invalidOption\"}\n\ntest busy-4.7 {tk busy configure valid option} -constraints macOrUnix -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {-cursor cursor Cursor watch watch}\n\ntest busy-4.7-win {tk busy configure valid option} -constraints {win} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {-cursor cursor Cursor wait wait}\n\ntest busy-4.8 {tk busy configure valid option} -constraints {\n    macOrUnix\n} -setup {\n    pack [frame .f]\n    tk busy hold .f -cursor circle\n    update\n} -body {\n    tk busy configure .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {-cursor cursor Cursor watch circle}\n\ntest busy-4.8-win {tk busy configure valid option} -constraints win -setup {\n    pack [frame .f]\n    tk busy hold .f -cursor circle\n    update\n} -body {\n    tk busy configure .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {-cursor cursor Cursor wait circle}\n\ntest busy-4.9 {tk busy configure valid option with value} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f -cursor pencil\n    tk busy cget .f -cursor\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {pencil}\n\ntest busy-4.10 {tk busy configure valid option with invalid value} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy configure .f -cursor nonExistingCursor\n} -returnCodes error -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {bad cursor spec \"nonExistingCursor\"}\n\ntest busy-5.1 {tk busy forget} -returnCodes error -body {\n    tk busy forget\n} -result {wrong # args: should be \"tk busy forget window\"}\ntest busy-5.2 {tk busy forget non existing window} -body {\n    tk busy forget .f\n} -returnCodes error -result {bad window path name \".f\"}\ntest busy-5.3 {tk busy forget non busy window} -setup {\n    pack [frame .f]\n} -body {\n    tk busy forget .f\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {cannot find busy window \".f\"}\ntest busy-5.4 {tk busy forget window} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    set r [tk busy status .f]\n    tk busy forget .f\n    lappend r [tk busy status .f]\n} -cleanup {\n    destroy .f\n} -result {1 0}\n\ntest busy-6.1 {tk busy status} -returnCodes error -body {\n    tk busy status\n} -result {wrong # args: should be \"tk busy status window\"}\ntest busy-6.2 {tk busy status non existing window} -body {\n    tk busy status .f\n} -result 0\ntest busy-6.3 {tk busy status non busy window} -setup {\n    pack [frame .f]\n} -body {\n    tk busy status .f\n} -cleanup {\n    destroy .f\n} -result 0\ntest busy-6.4 {tk busy status busy window} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy status .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result 1\ntest busy-6.5 {tk busy status forgotten busy window} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n    tk busy forget .f\n} -body {\n    tk busy status .f\n} -cleanup {\n    destroy .f\n} -result 0\n\ntest busy-7.1 {tk busy current no busy} -body {\n    tk busy current\n} -result {}\ntest busy-7.2 {tk busy current 1 busy} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n} -body {\n    tk busy current\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f}\ntest busy-7.3 {tk busy current 2 busy} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n} -body {\n    lsort [tk busy current]\n} -cleanup {\n    tk busy forget .f1\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {.f1 .f2}\ntest busy-7.4 {tk busy current 2 busy with matching filter} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n} -body {\n    lsort [tk busy current *2*]\n} -cleanup {\n    tk busy forget .f1\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {.f2}\ntest busy-7.5 {tk busy current 2 busy with non matching filter} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n} -body {\n    lsort [tk busy current *3*]\n} -cleanup {\n    tk busy forget .f1\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {}\ntest busy-7.6 {tk busy current 1 busy after forget} -setup {\n    pack [frame .f]\n    tk busy hold .f\n    update\n    tk busy forget .f\n} -body {\n    tk busy current\n} -cleanup {\n    destroy .f\n} -result {}\ntest busy-7.7 {tk busy current 2 busy after forget} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n    tk busy forget .f1\n} -body {\n    lsort [tk busy current]\n} -cleanup {\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {.f2}\ntest busy-7.8 {tk busy current 2 busy with matching filter after forget} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n    tk busy forget .f1\n} -body {\n    lsort [tk busy current *2*]\n} -cleanup {\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {.f2}\ntest busy-7.9 {tk busy current 2 busy with non matching filter after forget} -setup {\n    pack [frame .f1]\n    pack [frame .f2]\n    tk busy hold .f1\n    tk busy hold .f2\n    update\n    tk busy forget .f1\n} -body {\n    lsort [tk busy current *3*]\n} -cleanup {\n    tk busy forget .f2\n    destroy .f1 .f2\n} -result {}\n\ntest busy-8.1 {tk busy busywindow with a busy toplevel} -body {\n    toplevel .top\n    tk busy .top\n    tk busy busywindow .top\n} -cleanup {\n    tk busy forget .top\n    destroy .top\n} -result {.top._Busy}\ntest busy-8.2 {tk busy busywindow with a busy widget} -body {\n    pack [frame .f]\n    tk busy .f\n    tk busy busywindow .f\n} -cleanup {\n    tk busy forget .f\n    destroy .f\n} -result {.f_Busy}\ntest busy-8.3 {tk busy busywindow with a nonexisting widget} -body {\n    tk busy .\n    tk busy busywindow .nonExistingWidget\n} -cleanup {\n    tk busy forget .\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\n::tcltest::cleanupTests\n"
  },
  {
    "path": "tests/butGeom.tcl",
    "content": "# This file creates a visual test for button layout.  It is part of\n# the Tk visual test suite, which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Visual Tests for Button Geometry\"\nwm iconname .t \"Button Geometry\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nlabel .t.l -text {This screen exercises the layout mechanisms for various flavors of buttons.  Select display options below, and they will be applied to all of the button widgets.  In order to see the effects of different anchor positions, expand the window so that there is extra space in the buttons.  The letter \"o\" in \"automatically\" should be underlined in the right column of widgets.} -wraplength 5i\npack .t.l -side top -fill both\n\nbutton .t.quit -text Quit -command {destroy .t}\npack .t.quit -side bottom -pady 2m\n\nset sepId 1\nproc sep {} {\n    global sepId\n    frame .t.sep$sepId -height 2 -bd 1 -relief sunken\n    pack .t.sep$sepId -side top -padx 2m -pady 2m -fill x\n    incr sepId\n}\n\n# Create buttons that control configuration options.\n\nframe .t.control\npack .t.control -side top -fill x -pady 3m\nframe .t.control.left\nframe .t.control.right\npack .t.control.left .t.control.right -side left -expand 1 -fill x\nlabel .t.anchorLabel -text \"Anchor:\"\nframe .t.control.left.f -width 6c -height 3c\npack .t.anchorLabel .t.control.left.f -in .t.control.left -side top\nforeach anchor {nw n ne w center e sw s se} {\n    button .t.anchor-$anchor -text $anchor -command \"config -anchor $anchor\"\n}\nplace .t.anchor-nw -in .t.control.left.f -relx 0 -relwidth 0.333 \\\n\t-rely 0 -relheight 0.333\nplace .t.anchor-n -in .t.control.left.f -relx 0.333 -relwidth 0.333 \\\n\t-rely 0 -relheight 0.333\nplace .t.anchor-ne -in .t.control.left.f -relx 0.666 -relwidth 0.333 \\\n\t-rely 0 -relheight 0.333\nplace .t.anchor-w -in .t.control.left.f -relx 0 -relwidth 0.333 \\\n\t-rely 0.333 -relheight 0.333\nplace .t.anchor-center -in .t.control.left.f -relx 0.333 -relwidth 0.333 \\\n\t-rely 0.333 -relheight 0.333\nplace .t.anchor-e -in .t.control.left.f -relx 0.666 -relwidth 0.333 \\\n\t-rely 0.333 -relheight 0.333\nplace .t.anchor-sw -in .t.control.left.f -relx 0 -relwidth 0.333 \\\n\t-rely 0.666 -relheight 0.333\nplace .t.anchor-s -in .t.control.left.f -relx 0.333 -relwidth 0.333 \\\n\t-rely 0.666 -relheight 0.333\nplace .t.anchor-se -in .t.control.left.f -relx 0.666 -relwidth 0.333 \\\n\t-rely 0.666 -relheight 0.333\n\nset justify center\nradiobutton .t.justify-left -text \"Justify Left\" -relief flat \\\n\t-command \"config -justify left\" -variable justify \\\n\t-value left\nradiobutton .t.justify-center -text \"Justify Center\" -relief flat \\\n\t-command \"config -justify center\" -variable justify \\\n\t-value center\nradiobutton .t.justify-right -text \"Justify Right\" -relief flat \\\n\t-command \"config -justify right\" -variable justify \\\n\t-value right\npack .t.justify-left .t.justify-center .t.justify-right \\\n\t-in .t.control.right -anchor w\n\nsep\nframe .t.f1\npack .t.f1 -side top -expand 1 -fill both\nsep\nframe .t.f2\npack .t.f2 -side top -expand 1 -fill both\nsep\nframe .t.f3\npack .t.f3 -side top -expand 1 -fill both\nsep\nframe .t.f4\npack .t.f4 -side top -expand 1 -fill both\nsep\n\nlabel .t.l1 -text Label -bd 2 -relief sunken\nlabel .t.l2 -text \"Explicit\\nnewlines\\n\\nin the text\" -bd 2 -relief sunken\nlabel .t.l3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -bd 2 -relief sunken -underline 50\npack .t.l1 .t.l2 .t.l3 -in .t.f1 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nbutton .t.b1 -text Button\nbutton .t.b2 -text \"Explicit\\nnewlines\\n\\nin the text\"\nbutton .t.b3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -underline 50\npack .t.b1 .t.b2 .t.b3 -in .t.f2 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\ncheckbutton .t.c1 -text Checkbutton -variable a\ncheckbutton .t.c2 -text \"Explicit\\nnewlines\\n\\nin the text\" -variable b\ncheckbutton .t.c3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -variable c -underline 50\npack .t.c1 .t.c2 .t.c3 -in .t.f3 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nradiobutton .t.r1 -text Radiobutton -value a\nradiobutton .t.r2 -text \"Explicit\\nnewlines\\n\\nin the text\" -value b\nradiobutton .t.r3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -value c -underline 50\npack .t.r1 .t.r2 .t.r3 -in .t.f4 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nproc config {option value} {\n    foreach w {.t.l1 .t.l2 .t.l3 .t.b1 .t.b2 .t.b3 .t.c1 .t.c2 .t.c3\n\t    .t.r1 .t.r2 .t.r3} {\n\t$w configure $option $value\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/butGeom2.tcl",
    "content": "# This file creates a visual test for button layout.  It is part of\n# the Tk visual test suite, which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Visual Tests for Button Geometry\"\nwm iconname .t \"Button Geometry\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nlabel .t.l -text {This screen exercises the color options for various flavors of buttons.  Select display options below, and they will be applied to the appropriate button widgets.} -wraplength 5i\npack .t.l -side top -fill both\n\nbutton .t.quit -text Quit -command {destroy .t}\npack .t.quit -side bottom -pady 2m\n\nset sepId 1\nproc sep {} {\n    global sepId\n    frame .t.sep$sepId -height 2 -bd 1 -relief sunken\n    pack .t.sep$sepId -side top -padx 2m -pady 2m -fill x\n    incr sepId\n}\n\n# Create buttons that control configuration options.\n\nframe .t.control\npack .t.control -side top -fill x -pady 3m\nframe .t.control.left\nframe .t.control.right\npack .t.control.left .t.control.right -side left -expand 1 -fill x\nlabel .t.anchorLabel -text \"Color:\"\nframe .t.control.left.f -width 6c -height 3c\npack .t.anchorLabel .t.control.left.f -in .t.control.left -side top -anchor w\nforeach opt {activebackground activeforeground background disabledforeground foreground highlightbackground highlightcolor } {\n    #button .t.color-$opt -text $opt -command \"config -$opt \\[tk_chooseColor]\"\n    menubutton .t.color-$opt -text $opt -menu .t.color-$opt.m -indicatoron 1 \\\n\t    -relief raised -bd 2\n    menu .t.color-$opt.m -tearoff 0\n    .t.color-$opt.m add command -label Red -command \"config -$opt red\"\n    .t.color-$opt.m add command -label Green -command \"config -$opt green\"\n    .t.color-$opt.m add command -label Blue -command \"config -$opt blue\"\n    .t.color-$opt.m add command -label Other... \\\n\t    -command \"config -$opt \\[tk_chooseColor]\"\n    pack .t.color-$opt -in .t.control.left.f -fill x\n}\n\nset default disabled\nlabel .t.default -text Default:\nradiobutton .t.default-normal -text \"Default normal\" -relief flat \\\n\t-command \"config-but -default normal\" -variable default \\\n\t-value normal\nradiobutton .t.default-active -text \"Default active\" -relief flat \\\n\t-command \"config-but -default active\" -variable default \\\n\t-value active\nradiobutton .t.default-disabled -text \"Default disabled\" -relief flat \\\n\t-command \"config-but -default disabled\" -variable default \\\n\t-value disabled\npack .t.default .t.default-normal .t.default-active .t.default-disabled \\\n\t-in .t.control.right -anchor w\n\nsep\nframe .t.f1\npack .t.f1 -side top -expand 1 -fill both\nsep\nframe .t.f2\npack .t.f2 -side top -expand 1 -fill both\nsep\nframe .t.f3\npack .t.f3 -side top -expand 1 -fill both\nsep\nframe .t.f4\npack .t.f4 -side top -expand 1 -fill both\nsep\n\nlabel .t.l1 -text Label -bd 2 -relief sunken\nlabel .t.l2 -text \"Explicit\\nnewlines\\n\\nin the text\" -bd 2 -relief sunken\nlabel .t.l3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -bd 2 -relief sunken -underline 50\npack .t.l1 .t.l2 .t.l3 -in .t.f1 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nbutton .t.b1 -text Button\nbutton .t.b2 -text \"Explicit\\nnewlines\\n\\nin the text\"\nbutton .t.b3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -underline 50\npack .t.b1 .t.b2 .t.b3 -in .t.f2 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\ncheckbutton .t.c1 -text Checkbutton -variable a\ncheckbutton .t.c2 -text \"Explicit\\nnewlines\\n\\nin the text\" -variable b\ncheckbutton .t.c3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -variable c -underline 50\npack .t.c1 .t.c2 .t.c3 -in .t.f3 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nradiobutton .t.r1 -text Radiobutton -value a\nradiobutton .t.r2 -text \"Explicit\\nnewlines\\n\\nin the text\" -value b\nradiobutton .t.r3 -text \"This text is quite long, so it must be wrapped automatically by Tk\" -wraplength 2i -value c -underline 50\npack .t.r1 .t.r2 .t.r3 -in .t.f4 -side left -padx 5m -pady 3m \\\n\t-expand y -fill both\n\nproc config {option value} {\n    foreach w {.t.l1 .t.l2 .t.l3 .t.b1 .t.b2 .t.b3 .t.c1 .t.c2 .t.c3\n\t    .t.r1 .t.r2 .t.r3} {\n\tcatch {$w configure $option $value}\n    }\n}\n\nproc config-but {option value} {\n    foreach w {.t.b1 .t.b2 .t.b3} {\n\t$w configure $option $value\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/button.test",
    "content": "# This file is a Tcl script to test labels, buttons, checkbuttons, and\n# radiobuttons in Tk (i.e., all the widgets defined in tkButton.c).\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding these widgets that\n# are specific to the unix platform (this includes macOS) go into the test file\n# unixButton.test. Tests regarding these widgets that are specific to the windows\n# platform go into the test file winButton.test.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import button image\n\nimageInit\n\n#\n# TESTS\n#\n\ntest button-1.1 {configuration option: \"activebackground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -activebackground #012345\n    .l cget -activebackground\n} -cleanup {\n    destroy .l\n} -result {#012345}\ntest button-1.2 {configuration option: \"activebackground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -activebackground non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.3 {configuration option: \"activebackground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -activebackground #012345\n    .b cget -activebackground\n} -cleanup {\n    destroy .b\n} -result {#012345}\ntest button-1.4 {configuration option: \"activebackground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -activebackground non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.5 {configuration option: \"activebackground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -activebackground #012345\n    .c cget -activebackground\n} -cleanup {\n    destroy .c\n} -result {#012345}\ntest button-1.6 {configuration option: \"activebackground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -activebackground non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.7 {configuration option: \"activebackground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -activebackground #012345\n    .r cget -activebackground\n} -cleanup {\n    destroy .r\n} -result {#012345}\ntest button-1.8 {configuration option: \"activebackground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -activebackground non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.9 {configuration option: \"activeforeground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -activeforeground #ff0000\n    .l cget -activeforeground\n} -cleanup {\n    destroy .l\n} -result {#ff0000}\ntest button-1.10 {configuration option: \"activeforeground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -activeforeground non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.11 {configuration option: \"activeforeground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -activeforeground #ff0000\n    .b cget -activeforeground\n} -cleanup {\n    destroy .b\n} -result {#ff0000}\ntest button-1.12 {configuration option: \"activeforeground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -activeforeground non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.13 {configuration option: \"activeforeground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -activeforeground #ff0000\n    .c cget -activeforeground\n} -cleanup {\n    destroy .c\n} -result {#ff0000}\ntest button-1.14 {configuration option: \"activeforeground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -activeforeground non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.15 {configuration option: \"activeforeground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -activeforeground #ff0000\n    .r cget -activeforeground\n} -cleanup {\n    destroy .r\n} -result {#ff0000}\ntest button-1.16 {configuration option: \"activeforeground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -activeforeground non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.17 {configuration option: \"anchor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -anchor nw\n    .l cget -anchor\n} -cleanup {\n    destroy .l\n} -result {nw}\ntest button-1.18 {configuration option: \"anchor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -anchor bogus\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest button-1.19 {configuration option: \"anchor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -anchor nw\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {nw}\ntest button-1.20 {configuration option: \"anchor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -anchor bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest button-1.21 {configuration option: \"anchor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -anchor nw\n    .c cget -anchor\n} -cleanup {\n    destroy .c\n} -result {nw}\ntest button-1.22 {configuration option: \"anchor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -anchor bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest button-1.23 {configuration option: \"anchor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -anchor nw\n    .r cget -anchor\n} -cleanup {\n    destroy .r\n} -result {nw}\ntest button-1.24 {configuration option: \"anchor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -anchor bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\n\ntest button-1.25 {configuration option: \"background\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -background #ff0000\n    .l cget -background\n} -cleanup {\n    destroy .l\n} -result {#ff0000}\ntest button-1.26 {configuration option: \"background\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -background non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.27 {configuration option: \"background\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -background #ff0000\n    .b cget -background\n} -cleanup {\n    destroy .b\n} -result {#ff0000}\ntest button-1.28 {configuration option: \"background\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -background non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.29 {configuration option: \"background\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -background #ff0000\n    .c cget -background\n} -cleanup {\n    destroy .c\n} -result {#ff0000}\ntest button-1.30 {configuration option: \"background\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -background non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.31 {configuration option: \"background\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -background #ff0000\n    .r cget -background\n} -cleanup {\n    destroy .r\n} -result {#ff0000}\ntest button-1.32 {configuration option: \"background\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -background non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.33 {configuration option: \"bd\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bd 4\n    .l cget -bd\n} -cleanup {\n    destroy .l\n} -result 4\ntest button-1.34 {configuration option: \"bd\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bd badValue\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.35 {configuration option: \"bd\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bd 4\n    .b cget -bd\n} -cleanup {\n    destroy .b\n} -result 4\ntest button-1.36 {configuration option: \"bd\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bd badValue\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.37 {configuration option: \"bd\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bd 4\n    .c cget -bd\n} -cleanup {\n    destroy .c\n} -result 4\ntest button-1.38 {configuration option: \"bd\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bd badValue\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.39 {configuration option: \"bd\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bd 4\n    .r cget -bd\n} -cleanup {\n    destroy .r\n} -result 4\ntest button-1.40 {configuration option: \"bd\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bd badValue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest button-1.41 {configuration option: \"bg\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bg #ff0000\n    .l cget -bg\n} -cleanup {\n    destroy .l\n} -result {#ff0000}\ntest button-1.42 {configuration option: \"bg\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bg non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.43 {configuration option: \"bg\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bg #ff0000\n    .b cget -bg\n} -cleanup {\n    destroy .b\n} -result {#ff0000}\ntest button-1.44 {configuration option: \"bg\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bg non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.45 {configuration option: \"bg\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bg #ff0000\n    .c cget -bg\n} -cleanup {\n    destroy .c\n} -result {#ff0000}\ntest button-1.46 {configuration option: \"bg\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bg non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.47 {configuration option: \"bg\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bg #ff0000\n    .r cget -bg\n} -cleanup {\n    destroy .r\n} -result {#ff0000}\ntest button-1.48 {configuration option: \"bg\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bg non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.49 {configuration option: \"bitmap\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bitmap questhead\n    .l cget -bitmap\n} -cleanup {\n    destroy .l\n} -result {questhead}\ntest button-1.50 {configuration option: \"bitmap\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -bitmap badValue\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bitmap \"badValue\" not defined}\ntest button-1.51 {configuration option: \"bitmap\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bitmap questhead\n    .b cget -bitmap\n} -cleanup {\n    destroy .b\n} -result {questhead}\ntest button-1.52 {configuration option: \"bitmap\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -bitmap badValue\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bitmap \"badValue\" not defined}\ntest button-1.53 {configuration option: \"bitmap\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bitmap questhead\n    .c cget -bitmap\n} -cleanup {\n    destroy .c\n} -result {questhead}\ntest button-1.54 {configuration option: \"bitmap\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -bitmap badValue\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bitmap \"badValue\" not defined}\ntest button-1.55 {configuration option: \"bitmap\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bitmap questhead\n    .r cget -bitmap\n} -cleanup {\n    destroy .r\n} -result {questhead}\ntest button-1.56 {configuration option: \"bitmap\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -bitmap badValue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bitmap \"badValue\" not defined}\n\ntest button-1.57 {configuration option: \"borderwidth\" for label} -setup {\n    label .l -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -borderwidth 1.3\n    .l cget -borderwidth\n} -cleanup {\n    destroy .l\n} -result {1.3}\ntest button-1.58 {configuration option: \"borderwidth\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -borderwidth badValue\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.59 {configuration option: \"borderwidth\" for button} -setup {\n    button .b -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -borderwidth 1.3\n    .b cget -borderwidth\n} -cleanup {\n    destroy .b\n} -result {1.3}\ntest button-1.60 {configuration option: \"borderwidth\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -borderwidth badValue\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.61 {configuration option: \"borderwidth\" for checkbutton} -setup {\n    checkbutton .c -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -borderwidth 1.3\n    .c cget -borderwidth\n} -cleanup {\n    destroy .c\n} -result {1.3}\ntest button-1.62 {configuration option: \"borderwidth\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -borderwidth badValue\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.63 {configuration option: \"borderwidth\" for radiobutton} -setup {\n    radiobutton .r -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -borderwidth 1.3\n    .r cget -borderwidth\n} -cleanup {\n    destroy .r\n} -result {1.3}\ntest button-1.64 {configuration option: \"borderwidth\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -borderwidth badValue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest button-1.65 {configuration option: \"command\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -command {set x}\n    .b cget -command\n} -cleanup {\n    destroy .b\n} -result {set x}\ntest button-1.66 {configuration option: \"command\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -command {set x}\n    .b cget -command\n} -cleanup {\n    destroy .b\n} -result {set x}\ntest button-1.67 {configuration option: \"command\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -command {set x}\n    .c cget -command\n} -cleanup {\n    destroy .c\n} -result {set x}\ntest button-1.68 {configuration option: \"command\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -command {set x}\n    .r cget -command\n} -cleanup {\n    destroy .r\n} -result {set x}\n\ntest button-1.69 {configuration option: \"compound\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -compound left\n    .l cget -compound\n} -cleanup {\n    destroy .l\n} -result {left}\ntest button-1.70 {configuration option: \"compound\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -compound bogus\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad compound \"bogus\": must be bottom, center, left, none, right, or top}\ntest button-1.71 {configuration option: \"compound\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -compound left\n    .b cget -compound\n} -cleanup {\n    destroy .b\n} -result {left}\ntest button-1.72 {configuration option: \"compound\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -compound bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad compound \"bogus\": must be bottom, center, left, none, right, or top}\ntest button-1.73 {configuration option: \"compound\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -compound left\n    .c cget -compound\n} -cleanup {\n    destroy .c\n} -result {left}\ntest button-1.74 {configuration option: \"compound\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -compound bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad compound \"bogus\": must be bottom, center, left, none, right, or top}\ntest button-1.75 {configuration option: \"compound\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -compound left\n    .r cget -compound\n} -cleanup {\n    destroy .r\n} -result {left}\ntest button-1.76 {configuration option: \"compound\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -compound bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad compound \"bogus\": must be bottom, center, left, none, right, or top}\n\ntest button-1.77 {configuration option: \"cursor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -cursor arrow\n    .l cget -cursor\n} -cleanup {\n    destroy .l\n} -result {arrow}\ntest button-1.78 {configuration option: \"cursor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -cursor badValue\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest button-1.79 {configuration option: \"cursor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -cursor arrow\n    .b cget -cursor\n} -cleanup {\n    destroy .b\n} -result {arrow}\ntest button-1.80 {configuration option: \"cursor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -cursor badValue\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest button-1.81 {configuration option: \"cursor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -cursor arrow\n    .c cget -cursor\n} -cleanup {\n    destroy .c\n} -result {arrow}\ntest button-1.82 {configuration option: \"cursor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -cursor badValue\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest button-1.83 {configuration option: \"cursor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -cursor arrow\n    .r cget -cursor\n} -cleanup {\n    destroy .r\n} -result {arrow}\ntest button-1.84 {configuration option: \"cursor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -cursor badValue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest button-1.85 {configuration option: \"default\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -default active\n    .b cget -default\n} -cleanup {\n    destroy .b\n} -result {active}\ntest button-1.86 {configuration option: \"default\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -default huh?\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad default \"huh?\": must be active, disabled, or normal}\n\ntest button-1.87 {configuration option: \"disabledforeground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -disabledforeground #00ff00\n    .l cget -disabledforeground\n} -cleanup {\n    destroy .l\n} -result {#00ff00}\ntest button-1.88 {configuration option: \"disabledforeground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -disabledforeground non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.89 {configuration option: \"disabledforeground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -disabledforeground #00ff00\n    .b cget -disabledforeground\n} -cleanup {\n    destroy .b\n} -result {#00ff00}\ntest button-1.90 {configuration option: \"disabledforeground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -disabledforeground non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.91 {configuration option: \"disabledforeground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -disabledforeground #00ff00\n    .c cget -disabledforeground\n} -cleanup {\n    destroy .c\n} -result {#00ff00}\ntest button-1.92 {configuration option: \"disabledforeground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -disabledforeground non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.93 {configuration option: \"disabledforeground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -disabledforeground #00ff00\n    .r cget -disabledforeground\n} -cleanup {\n    destroy .r\n} -result {#00ff00}\ntest button-1.94 {configuration option: \"disabledforeground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -disabledforeground non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.95 {configuration option: \"fg\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -fg #110022\n    .l cget -fg\n} -cleanup {\n    destroy .l\n} -result {#110022}\ntest button-1.96 {configuration option: \"fg\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -fg non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.97 {configuration option: \"fg\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -fg #110022\n    .b cget -fg\n} -cleanup {\n    destroy .b\n} -result {#110022}\ntest button-1.98 {configuration option: \"fg\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -fg non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.99 {configuration option: \"fg\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -fg #110022\n    .c cget -fg\n} -cleanup {\n    destroy .c\n} -result {#110022}\ntest button-1.100 {configuration option: \"fg\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -fg non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.101 {configuration option: \"fg\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -fg #110022\n    .r cget -fg\n} -cleanup {\n    destroy .r\n} -result {#110022}\ntest button-1.102 {configuration option: \"fg\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -fg non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.103 {configuration option: \"font\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2\n    pack .l\n    update\n} -body {\n    .l configure -font {Helvetica -12}\n    .l cget -font\n} -cleanup {\n    destroy .l\n} -result {Helvetica -12}\ntest button-1.104 {configuration option: \"activebackground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2\n    pack .l\n    update\n} -body {\n    .l configure -font {}\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {font \"\" does not exist}\ntest button-1.105 {configuration option: \"font\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2\n    pack .b\n    update\n} -body {\n    .b configure -font {Helvetica -12}\n    .b cget -font\n} -cleanup {\n    destroy .b\n} -result {Helvetica -12}\ntest button-1.106 {configuration option: \"activebackground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2\n    pack .b\n    update\n} -body {\n    .b configure -font {}\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {font \"\" does not exist}\ntest button-1.107 {configuration option: \"font\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2\n    pack .c\n    update\n} -body {\n    .c configure -font {Helvetica -12}\n    .c cget -font\n} -cleanup {\n    destroy .c\n} -result {Helvetica -12}\ntest button-1.108 {configuration option: \"activebackground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2\n    pack .c\n    update\n} -body {\n    .c configure -font {}\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {font \"\" does not exist}\ntest button-1.109 {configuration option: \"font\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2\n    pack .r\n    update\n} -body {\n    .r configure -font {Helvetica -12}\n    .r cget -font\n} -cleanup {\n    destroy .r\n} -result {Helvetica -12}\ntest button-1.110 {configuration option: \"activebackground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2\n    pack .r\n    update\n} -body {\n    .r configure -font {}\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {font \"\" does not exist}\n\ntest button-1.111 {configuration option: \"foreground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -foreground #110022\n    .l cget -foreground\n} -cleanup {\n    destroy .l\n} -result {#110022}\ntest button-1.112 {configuration option: \"foreground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -foreground non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.113 {configuration option: \"foreground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -foreground #110022\n    .b cget -foreground\n} -cleanup {\n    destroy .b\n} -result {#110022}\ntest button-1.114 {configuration option: \"foreground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -foreground non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.115 {configuration option: \"foreground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -foreground #110022\n    .c cget -foreground\n} -cleanup {\n    destroy .c\n} -result {#110022}\ntest button-1.116 {configuration option: \"foreground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -foreground non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.117 {configuration option: \"foreground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -foreground #110022\n    .r cget -foreground\n} -cleanup {\n    destroy .r\n} -result {#110022}\ntest button-1.118 {configuration option: \"foreground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -foreground non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.119 {configuration option: \"height\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -height 18\n    .l cget -height\n} -cleanup {\n    destroy .l\n} -result 18\ntest button-1.120 {configuration option: \"height\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -height 20.0\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected integer but got \"20.0\"}\ntest button-1.121 {configuration option: \"height\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -height 18\n    .b cget -height\n} -cleanup {\n    destroy .b\n} -result 18\ntest button-1.122 {configuration option: \"height\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -height 20.0\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"20.0\"}\ntest button-1.123 {configuration option: \"height\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -height 18\n    .c cget -height\n} -cleanup {\n    destroy .c\n} -result 18\ntest button-1.124 {configuration option: \"height\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -height 20.0\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected integer but got \"20.0\"}\ntest button-1.125 {configuration option: \"height\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -height 18\n    .r cget -height\n} -cleanup {\n    destroy .r\n} -result 18\ntest button-1.126 {configuration option: \"height\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -height 20.0\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected integer but got \"20.0\"}\n\ntest button-1.127 {configuration option: \"highlightbackground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightbackground #110022\n    .l cget -highlightbackground\n} -cleanup {\n    destroy .l\n} -result {#110022}\ntest button-1.128 {configuration option: \"highlightbackground\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightbackground non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.129 {configuration option: \"highlightbackground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightbackground #110022\n    .b cget -highlightbackground\n} -cleanup {\n    destroy .b\n} -result {#110022}\ntest button-1.130 {configuration option: \"highlightbackground\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightbackground non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.131 {configuration option: \"highlightbackground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightbackground #110022\n    .c cget -highlightbackground\n} -cleanup {\n    destroy .c\n} -result {#110022}\ntest button-1.132 {configuration option: \"highlightbackground\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightbackground non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.133 {configuration option: \"highlightbackground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightbackground #110022\n    .r cget -highlightbackground\n} -cleanup {\n    destroy .r\n} -result {#110022}\ntest button-1.134 {configuration option: \"highlightbackground\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightbackground non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.135 {configuration option: \"highlightcolor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightcolor #110022\n    .l cget -highlightcolor\n} -cleanup {\n    destroy .l\n} -result {#110022}\ntest button-1.136 {configuration option: \"highlightcolor\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightcolor non-existent\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.137 {configuration option: \"highlightcolor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightcolor #110022\n    .b cget -highlightcolor\n} -cleanup {\n    destroy .b\n} -result {#110022}\ntest button-1.138 {configuration option: \"highlightcolor\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightcolor non-existent\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.139 {configuration option: \"highlightcolor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightcolor #110022\n    .c cget -highlightcolor\n} -cleanup {\n    destroy .c\n} -result {#110022}\ntest button-1.140 {configuration option: \"highlightcolor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightcolor non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.141 {configuration option: \"highlightcolor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightcolor #110022\n    .r cget -highlightcolor\n} -cleanup {\n    destroy .r\n} -result {#110022}\ntest button-1.142 {configuration option: \"highlightcolor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightcolor non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.143 {configuration option: \"highlightthickness\" for label} -setup {\n    label .l -borderwidth 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightthickness 6m\n    .l cget -highlightthickness\n} -cleanup {\n    destroy .l\n} -result {6m}\ntest button-1.144 {configuration option: \"highlightthickness\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -highlightthickness badValue\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.145 {configuration option: \"highlightthickness\" for button} -setup {\n    button .b -borderwidth 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightthickness 6m\n    .b cget -highlightthickness\n} -cleanup {\n    destroy .b\n} -result {6m}\ntest button-1.146 {configuration option: \"highlightthickness\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -highlightthickness badValue\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.147 {configuration option: \"highlightthickness\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightthickness 6m\n    .c cget -highlightthickness\n} -cleanup {\n    destroy .c\n} -result {6m}\ntest button-1.148 {configuration option: \"highlightthickness\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -highlightthickness badValue\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest button-1.149 {configuration option: \"highlightthickness\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightthickness 6m\n    .r cget -highlightthickness\n} -cleanup {\n    destroy .r\n} -result {6m}\ntest button-1.150 {configuration option: \"highlightthickness\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -highlightthickness badValue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest button-1.151 {configuration option: \"image\" for label} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -image image1\n    .l cget -image\n} -cleanup {\n    destroy .l\n    image delete image1\n} -result {image1}\ntest button-1.152 {configuration option: \"image\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -image bogus\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest button-1.153 {configuration option: \"image\" for button} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -image image1\n    .b cget -image\n} -cleanup {\n    destroy .b\n    image delete image1\n} -result {image1}\ntest button-1.154 {configuration option: \"image\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -image bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest button-1.155 {configuration option: \"image\" for checkbutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -image image1\n    .c cget -image\n} -cleanup {\n    destroy .c\n    image delete image1\n} -result {image1}\ntest button-1.156 {configuration option: \"image\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -image bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest button-1.157 {configuration option: \"image\" for radiobutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -image image1\n    .r cget -image\n} -cleanup {\n    destroy .r\n    image delete image1\n} -result {image1}\ntest button-1.158 {configuration option: \"image\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -image bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest button-1.159 {configuration option: \"indicatoron\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -indicatoron yes\n    .c cget -indicatoron\n} -cleanup {\n    destroy .c\n} -result 1\ntest button-1.160 {configuration option: \"indicatoron\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -indicatoron no_way\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected boolean value but got \"no_way\"}\ntest button-1.161 {configuration option: \"indicatoron\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -indicatoron yes\n    .r cget -indicatoron\n} -cleanup {\n    destroy .r\n} -result 1\ntest button-1.162 {configuration option: \"indicatoron\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -indicatoron no_way\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected boolean value but got \"no_way\"}\n\ntest button-1.163 {configuration option: \"justify\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -justify right\n    .l cget -justify\n} -cleanup {\n    destroy .l\n} -result {right}\ntest button-1.164 {configuration option: \"justify\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -justify bogus\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\ntest button-1.165 {configuration option: \"justify\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -justify right\n    .b cget -justify\n} -cleanup {\n    destroy .b\n} -result {right}\ntest button-1.166 {configuration option: \"justify\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -justify bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\ntest button-1.167 {configuration option: \"justify\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -justify right\n    .c cget -justify\n} -cleanup {\n    destroy .c\n} -result {right}\ntest button-1.168 {configuration option: \"justify\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -justify bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\ntest button-1.169 {configuration option: \"justify\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -justify right\n    .r cget -justify\n} -cleanup {\n    destroy .r\n} -result {right}\ntest button-1.170 {configuration option: \"justify\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -justify bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\n\ntest button-1.171 {configuration option: \"offrelief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -offrelief flat\n    .c cget -offrelief\n} -cleanup {\n    destroy .c\n} -result {flat}\ntest button-1.172 {configuration option: \"offrelief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -offrelief 1.5\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest button-1.173 {configuration option: \"offrelief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -offrelief flat\n    .r cget -offrelief\n} -cleanup {\n    destroy .r\n} -result {flat}\ntest button-1.174 {configuration option: \"offrelief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -offrelief 1.5\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest button-1.175 {configuration option: \"offvalue\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -offvalue lousy\n    .c cget -offvalue\n} -cleanup {\n    destroy .c\n} -result {lousy}\n\ntest button-1.176 {configuration option: \"onvalue\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -onvalue fantastic\n    .c cget -onvalue\n} -cleanup {\n    destroy .c\n} -result {fantastic}\n\ntest button-1.177 {configuration option: \"overrelief\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -overrelief \"\"\n    .b cget -overrelief\n} -cleanup {\n    destroy .b\n} -result {}\ntest button-1.178 {configuration option: \"overrelief\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -overrelief 1.5\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\ntest button-1.179 {configuration option: \"overrelief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -overrelief \"\"\n    .c cget -overrelief\n} -cleanup {\n    destroy .c\n} -result {}\ntest button-1.180 {configuration option: \"overrelief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -overrelief 1.5\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\ntest button-1.181 {configuration option: \"overrelief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -overrelief \"\"\n    .r cget -overrelief\n} -cleanup {\n    destroy .r\n} -result {}\ntest button-1.182 {configuration option: \"overrelief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -overrelief 1.5\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\n\ntest button-1.183 {configuration option: \"padx\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -padx 12m\n    .l cget -padx\n} -cleanup {\n    destroy .l\n} -result {12m}\ntest button-1.184 {configuration option: \"padx\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -padx 420x\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.185 {configuration option: \"padx\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -padx 12m\n    .b cget -padx\n} -cleanup {\n    destroy .b\n} -result {12m}\ntest button-1.186 {configuration option: \"padx\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -padx 420x\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.187 {configuration option: \"padx\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -padx 12m\n    .c cget -padx\n} -cleanup {\n    destroy .c\n} -result {12m}\ntest button-1.188 {configuration option: \"padx\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -padx 420x\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.189 {configuration option: \"padx\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -padx 12m\n    .r cget -padx\n} -cleanup {\n    destroy .r\n} -result {12m}\ntest button-1.190 {configuration option: \"padx\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -padx 420x\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"420x\"}\n\ntest button-1.191 {configuration option: \"pady\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -pady 12m\n    .l cget -pady\n} -cleanup {\n    destroy .l\n} -result {12m}\ntest button-1.192 {configuration option: \"pady\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -pady 420x\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.193 {configuration option: \"pady\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -pady 12m\n    .b cget -pady\n} -cleanup {\n    destroy .b\n} -result {12m}\ntest button-1.194 {configuration option: \"pady\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -pady 420x\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.195 {configuration option: \"pady\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -pady 12m\n    .c cget -pady\n} -cleanup {\n    destroy .c\n} -result {12m}\ntest button-1.196 {configuration option: \"pady\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -pady 420x\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest button-1.197 {configuration option: \"pady\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -pady 12m\n    .r cget -pady\n} -cleanup {\n    destroy .r\n} -result {12m}\ntest button-1.198 {configuration option: \"pady\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -pady 420x\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"420x\"}\n\ntest button-1.199 {configuration option: \"repeatdelay\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -repeatdelay 100\n    .b cget -repeatdelay\n} -cleanup {\n    destroy .b\n} -result 100\ntest button-1.200 {configuration option: \"repeatdelay\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -repeatdelay foo\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"foo\"}\n\ntest button-1.201 {configuration option: \"repeatinterval\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -repeatinterval 100\n    .b cget -repeatinterval\n} -cleanup {\n    destroy .b\n} -result 100\ntest button-1.202 {configuration option: \"repeatinterval\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -repeatinterval foo\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"foo\"}\n\ntest button-1.203 {configuration option: \"relief\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -relief flat\n    .l cget -relief\n} -cleanup {\n    destroy .l\n} -result {flat}\ntest button-1.204 {configuration option: \"relief\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -relief 1.5\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest button-1.205 {configuration option: \"relief\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -relief flat\n    .b cget -relief\n} -cleanup {\n    destroy .b\n} -result {flat}\ntest button-1.206 {configuration option: \"relief\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -relief 1.5\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest button-1.207 {configuration option: \"relief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -relief flat\n    .c cget -relief\n} -cleanup {\n    destroy .c\n} -result {flat}\ntest button-1.208 {configuration option: \"relief\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -relief 1.5\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest button-1.209 {configuration option: \"relief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -relief flat\n    .r cget -relief\n} -cleanup {\n    destroy .r\n} -result {flat}\ntest button-1.210 {configuration option: \"relief\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -relief 1.5\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest button-1.211 {configuration option: \"selectcolor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -selectcolor #110022\n    .c cget -selectcolor\n} -cleanup {\n    destroy .c\n} -result {#110022}\ntest button-1.212 {configuration option: \"selectcolor\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -selectcolor non-existent\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest button-1.213 {configuration option: \"selectcolor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -selectcolor #110022\n    .r cget -selectcolor\n} -cleanup {\n    destroy .r\n} -result {#110022}\ntest button-1.214 {configuration option: \"selectcolor\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -selectcolor non-existent\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest button-1.215 {configuration option: \"selectimage\" for checkbutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -selectimage image1\n    .c cget -selectimage\n} -cleanup {\n    destroy .c\n    image delete image1\n} -result {image1}\ntest button-1.216 {configuration option: \"selectimage\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -selectimage bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest button-1.217 {configuration option: \"selectimage\" for radiobutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -selectimage image1\n    .r cget -selectimage\n} -cleanup {\n    destroy .r\n    image delete image1\n} -result {image1}\ntest button-1.218 {configuration option: \"selectimage\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -selectimage bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest button-1.219 {configuration option: \"state\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -state normal\n    .l cget -state\n} -cleanup {\n    destroy .l\n} -result {normal}\ntest button-1.220 {configuration option: \"state\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -state bogus\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\ntest button-1.221 {configuration option: \"state\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -state normal\n    .b cget -state\n} -cleanup {\n    destroy .b\n} -result {normal}\ntest button-1.222 {configuration option: \"state\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -state bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\ntest button-1.223 {configuration option: \"state\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -state normal\n    .c cget -state\n} -cleanup {\n    destroy .c\n} -result {normal}\ntest button-1.224 {configuration option: \"state\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -state bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\ntest button-1.225 {configuration option: \"state\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -state normal\n    .r cget -state\n} -cleanup {\n    destroy .r\n} -result {normal}\ntest button-1.226 {configuration option: \"state\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -state bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\n\ntest button-1.227 {configuration option: \"takefocus\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -takefocus \"any string\"\n    .l cget -takefocus\n} -cleanup {\n    destroy .l\n} -result {any string}\ntest button-1.228 {configuration option: \"takefocus\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -takefocus \"any string\"\n    .b cget -takefocus\n} -cleanup {\n    destroy .b\n} -result {any string}\ntest button-1.229 {configuration option: \"takefocus\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -takefocus \"any string\"\n    .c cget -takefocus\n} -cleanup {\n    destroy .c\n} -result {any string}\ntest button-1.230 {configuration option: \"takefocus\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -takefocus \"any string\"\n    .r cget -takefocus\n} -cleanup {\n    destroy .r\n} -result {any string}\n\ntest button-1.231 {configuration option: \"text\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -text \"Sample text\"\n    .l cget -text\n} -cleanup {\n    destroy .l\n} -result {Sample text}\ntest button-1.232 {configuration option: \"text\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -text \"Sample text\"\n    .b cget -text\n} -cleanup {\n    destroy .b\n} -result {Sample text}\ntest button-1.233 {configuration option: \"text\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -text \"Sample text\"\n    .c cget -text\n} -cleanup {\n    destroy .c\n} -result {Sample text}\ntest button-1.234 {configuration option: \"text\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -text \"Sample text\"\n    .r cget -text\n} -cleanup {\n    destroy .r\n} -result {Sample text}\n\ntest button-1.235 {configuration option: \"textvariable\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -textvariable i\n    .l cget -textvariable\n} -cleanup {\n    destroy .l\n} -result {i}\ntest button-1.236 {configuration option: \"textvariable\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -textvariable i\n    .b cget -textvariable\n} -cleanup {\n    destroy .b\n} -result {i}\ntest button-1.237 {configuration option: \"textvariable\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -textvariable i\n    .c cget -textvariable\n} -cleanup {\n    destroy .c\n} -result {i}\ntest button-1.238 {configuration option: \"textvariable\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -textvariable i\n    .r cget -textvariable\n} -cleanup {\n    destroy .r\n} -result {i}\n\ntest button-1.239 {configuration option: \"tristateimage\" for checkbutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -tristateimage image1\n    .c cget -tristateimage\n} -cleanup {\n    destroy .c\n    image delete image1\n} -result {image1}\ntest button-1.240 {configuration option: \"tristateimage\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -tristateimage bogus\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest button-1.241 {configuration option: \"tristateimage\" for radiobutton} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -tristateimage image1\n    .r cget -tristateimage\n} -cleanup {\n    destroy .r\n    image delete image1\n} -result {image1}\ntest button-1.242 {configuration option: \"tristateimage\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -tristateimage bogus\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest button-1.243 {configuration option: \"underline\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -underline 5\n    .l cget -underline\n} -cleanup {\n    destroy .l\n} -result 5\ntest button-1.244 {configuration option: \"underline\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -underline 3p\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\ntest button-1.245 {configuration option: \"underline\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -underline 5\n    .b cget -underline\n} -cleanup {\n    destroy .b\n} -result 5\ntest button-1.246 {configuration option: \"underline\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -underline 3p\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\ntest button-1.247 {configuration option: \"underline\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -underline 5\n    .c cget -underline\n} -cleanup {\n    destroy .c\n} -result 5\ntest button-1.248 {configuration option: \"underline\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -underline 3p\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\ntest button-1.249 {configuration option: \"underline\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -underline 5\n    .r cget -underline\n} -cleanup {\n    destroy .r\n} -result 5\ntest button-1.250 {configuration option: \"underline\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -underline 3p\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\n\ntest button-1.251 {configuration option: \"tristatevalue\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -tristatevalue unknowable\n    .c cget -tristatevalue\n} -cleanup {\n    destroy .c\n} -result {unknowable}\ntest button-1.252 {configuration option: \"tristatevalue\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -tristatevalue unknowable\n    .r cget -tristatevalue\n} -cleanup {\n    destroy .r\n} -result {unknowable}\n\ntest button-1.253 {configuration option: \"value\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -value anyString\n    .r cget -value\n} -cleanup {\n    destroy .r\n} -result {anyString}\n\ntest button-1.254 {configuration option: \"width\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -width 402\n    .l cget -width\n} -cleanup {\n    destroy .l\n} -result 402\ntest button-1.255 {configuration option: \"width\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -width 3p\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected integer but got \"3p\"}\ntest button-1.256 {configuration option: \"width\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -width 402\n    .b cget -width\n} -cleanup {\n    destroy .b\n} -result 402\ntest button-1.257 {configuration option: \"width\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -width 3p\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"3p\"}\ntest button-1.258 {configuration option: \"width\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -width 402\n    .c cget -width\n} -cleanup {\n    destroy .c\n} -result 402\ntest button-1.259 {configuration option: \"width\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -width 3p\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected integer but got \"3p\"}\ntest button-1.260 {configuration option: \"width\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -width 402\n    .r cget -width\n} -cleanup {\n    destroy .r\n} -result 402\ntest button-1.261 {configuration option: \"width\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -width 3p\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected integer but got \"3p\"}\n\ntest button-1.262 {configuration option: \"wraplength\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -wraplength 100\n    .l cget -wraplength\n} -cleanup {\n    destroy .l\n} -result 100\ntest button-1.263 {configuration option: \"wraplength\" for label} -setup {\n    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .l\n    update\n} -body {\n    .l configure -wraplength 6x\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {expected screen distance but got \"6x\"}\ntest button-1.264 {configuration option: \"wraplength\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -wraplength 100\n    .b cget -wraplength\n} -cleanup {\n    destroy .b\n} -result 100\ntest button-1.265 {configuration option: \"wraplength\" for button} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .b\n    update\n} -body {\n    .b configure -wraplength 6x\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected screen distance but got \"6x\"}\ntest button-1.266 {configuration option: \"wraplength\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -wraplength 100\n    .c cget -wraplength\n} -cleanup {\n    destroy .c\n} -result 100\ntest button-1.267 {configuration option: \"wraplength\" for checkbutton} -setup {\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -wraplength 6x\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"6x\"}\ntest button-1.268 {configuration option: \"wraplength\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -wraplength 100\n    .r cget -wraplength\n} -cleanup {\n    destroy .r\n} -result 100\ntest button-1.269 {configuration option: \"wraplength\" for radiobutton} -setup {\n    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .r\n    update\n} -body {\n    .r configure -wraplength 6x\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {expected screen distance but got \"6x\"}\n\ntest button-1.270 {configuration options} -body {\n# Additional check to make sure that -selectcolor may be empty in\n# checkbox widgets\n    checkbutton .c\n    .c configure -selectcolor {}\n} -cleanup {\n    destroy .c\n} -result {}\n\ntest button-1.271 {configuration options: fallback to default} -setup {\n    checkbutton .c -borderwidth 0 -highlightthickness 0 -font {Helvetica -12 bold}\n    pack .c\n    update\n} -body {\n    .c configure -padx 0 -pady 0 -wraplength 0\n    list [.c cget -padx] [.c cget -pady] [.c cget -borderwidth] [.c cget -highlightthickness] [.c cget -wraplength]\n} -cleanup {\n    destroy .c\n} -result {0 0 0 0 0}\n\ntest button-2.1 {ButtonCreate - not enough arguments} -body {\n    button\n} -returnCodes error -result {wrong # args: should be \"button pathName ?-option value ...?\"}\n\ntest button-2.2 {ButtonCreate procedure - setting label class} -body {\n    label .x\n    winfo class .x\n} -cleanup {\n    destroy .x\n} -result {Label}\ntest button-2.3 {ButtonCreate - setting button class} -body {\n    button .x\n    winfo class .x\n} -cleanup {\n    destroy .x\n} -result {Button}\ntest button-2.4 {ButtonCreate - setting checkbutton class} -body {\n    checkbutton .x\n    winfo class .x\n} -cleanup {\n    destroy .x\n} -result {Checkbutton}\ntest button-2.5 {ButtonCreate - setting radiobutton class} -body {\n    radiobutton .x\n    winfo class .x\n} -cleanup {\n    destroy .x\n} -result {Radiobutton}\ntest button-2.6 {ButtonCreate - setting class} -body {\n    rename button gorp\n    gorp .x\n    winfo class .x\n} -cleanup {\n    destroy .x\n    rename gorp button\n} -result {Button}\n\ntest button-2.7 {ButtonCreate - bad window name} -body {\n    button foo\n} -cleanup {\n    destroy foo\n} -returnCodes error -result {bad window path name \"foo\"}\n\ntest button-2.8 {ButtonCreate procedure - error in default option value} -body {\n    option add *funny.background bogus\n    button .funny\n} -cleanup {\n    option clear\n    destroy .funny\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest button-2.9 {ButtonCreate procedure - error in default option value} -body {\n   option add *funny.background bogus\n    catch {button .funny}\n    return $errorInfo\n} -cleanup {\n    option clear\n    destroy .funny\n} -result {unknown color name \"bogus\"\n    (database entry for \"-background\" in widget \".funny\")\n    invoked from within\n\"button .funny\"}\n\ntest button-2.10 {ButtonCreate procedure - option error} -body {\n    button .x -gorp foo\n}  -cleanup {\n    destroy .x\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest button-2.11 {ButtonCreate procedure - option error} -body {\n    catch {button .x -gorp foo}\n    winfo exists .x\n}  -cleanup {\n    destroy .x\n} -result 0\ntest button-2.12 {ButtonCreate procedure - return value} -body {\n    set x [button .abcd]\n    return $x\n} -cleanup {\n    destroy .abcd\n} -result {.abcd}\n\ntest button-3.1 {ButtonWidgetCmd - too few arguments} -body {\n    button .b\n    .b\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {wrong # args: should be \".b option ?arg ...?\"}\ntest button-3.2 {ButtonWidgetCmd - bad option name} -body {\n    button .b\n    .b c\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {ambiguous option \"c\": must be cget, configure, flash, or invoke}\ntest button-3.3 {ButtonWidgetCmd - bad option name} -body {\n    button .b\n    .b bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad option \"bogus\": must be cget, configure, flash, or invoke}\ntest button-3.4 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    button .b\n    .b cget a b\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {wrong # args: should be \".b cget option\"}\ntest button-3.5 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    button .b\n    .b cget -gorp\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown option \"-gorp\"}\n\n#ex 4.7\ntest button-3.6 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    label .l\n    .l cget -disabledforeground\n} -cleanup {\n    destroy .l\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.7 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    button .b\n    .b cget -disabledforeground\n} -cleanup {\n    destroy .b\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.8 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    button .b\n    .b cget -variable\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown option \"-variable\"}\n\ntest button-3.9 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    checkbutton .c\n    .c cget -variable\n} -cleanup {\n    destroy .c\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.10 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    checkbutton .c\n    .c cget -value\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest button-3.11 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    radiobutton .r\n    .r cget -value\n} -cleanup {\n    destroy .r\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.12 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    radiobutton .r\n    .r cget -onvalue\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest button-3.13 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    button .b -highlightthickness 3\n    lindex [.b configure -highlightthickness] 4\n} -cleanup {\n    destroy .b\n}  -result 3\ntest button-3.14 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    checkbutton .c\n    llength [.c configure]\n} -cleanup {\n    destroy .c\n} -result 41\ntest button-3.15 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    button .b\n    .b configure -gorp\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest button-3.16 {ButtonWidgetCmd procedure, \"configure\" option} -setup {\n    button .b\n} -body {\n    .b co -bg #ffffff -fg\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {value for \"-fg\" missing}\ntest button-3.17 {ButtonWidgetCmd procedure, \"configure\" option} -setup {\n    button .b\n} -body {\n    .b configure -fg #123456\n    .b configure -bg #654321\n    lindex [.b configure -fg] 4\n} -cleanup {\n    destroy .b\n} -result {#123456}\ntest button-3.18 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    checkbutton .c\n    .c deselect foo\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {wrong # args: should be \".c deselect\"}\ntest button-3.19 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    label .l\n    .l deselect\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad option \"deselect\": must be cget or configure}\ntest button-3.20 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    button .b\n    .b deselect\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad option \"deselect\": must be cget, configure, flash, or invoke}\n\ntest button-3.21 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0\n    set checkvar 1\n    .c d\n    return $checkvar\n} -cleanup {\n    destroy .c\n} -result 0\ntest button-3.22 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar green\n    .r deselect\n    return $radiovar\n} -cleanup {\n    destroy .r\n} -result {green}\ntest button-3.23 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar red\n    .r deselect\n    return $radiovar\n} -cleanup {\n    destroy .r\n} -result {}\n\ntest button-3.24 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0\n    set checkvar 1\n    trace add variable checkvar write bogusTrace\n    .c deselect\n} -cleanup {\n    destroy .c\n    trace remove variable checkvar write bogusTrace\n} -returnCodes error -result {can't set \"checkvar\": trace aborted}\ntest button-3.25 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0\n    set checkvar 1\n    trace add variable checkvar write bogusTrace\n    catch {.c deselect}\n    list $errorInfo $checkvar\n} -cleanup {\n    trace remove variable checkvar write bogusTrace\n    destroy .c\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".c deselect\"} 0}\ntest button-3.26 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar red\n    trace add variable radiovar write bogusTrace\n    .r deselect\n} -cleanup {\n    destroy .r\n    trace remove variable radiovar write bogusTrace\n} -match glob -returnCodes error -result {can't set \"radiovar\": trace aborted}\ntest button-3.27 {ButtonWidgetCmd procedure, \"deselect\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar red\n    trace add variable radiovar write bogusTrace\n    catch {.r deselect}\n    list $errorInfo $radiovar\n} -cleanup {\n    destroy .r\n    trace remove variable radiovar write bogusTrace\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".r deselect\"} {}}\n\ntest button-3.28 {ButtonWidgetCmd procedure, \"flash\" option} -body {\n    button .b\n    .b flash foo\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {wrong # args: should be \".b flash\"}\ntest button-3.29 {ButtonWidgetCmd procedure, \"flash\" option} -body {\n    label .l\n    .l flash\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad option \"flash\": must be cget or configure}\ntest button-3.30 {ButtonWidgetCmd procedure, \"flash\" option} -body {\n    button .b\n    catch {.b flash}\n} -cleanup {\n    destroy .b\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.31 {ButtonWidgetCmd procedure, \"flash\" option} -body {\n    checkbutton .c\n    catch {.c flash}\n} -cleanup {\n    destroy .c\n} -returnCodes {ok} -match glob -result {*}\ntest button-3.32 {ButtonWidgetCmd procedure, \"flash\" option} -body {\n    radiobutton .r\n    catch {.r f}\n} -cleanup {\n    destroy .r\n} -returnCodes {ok} -match glob -result {*}\n\ntest button-3.33 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    label .l\n    .l invoke\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad option \"invoke\": must be cget or configure}\ntest button-3.34 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    button .b\n    .b invoke foo\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {wrong # args: should be \".b invoke\"}\ntest button-3.35 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    button .b\n    .b configure -command {set x invoked}\n    set x \"not invoked\"\n    .b invoke\n    return $x\n} -cleanup {\n    destroy .b\n} -result {invoked}\ntest button-3.36 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    button .b\n    .b configure -command {set x invoked} -state disabled\n    set x \"not invoked\"\n    .b invoke\n    return $x\n} -cleanup {\n    destroy .b\n} -result {not invoked}\ntest button-3.37 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0 \\\n\t-command {set x invoked}\n    set checkvar bogus\n    set x \"not invoked\"\n    .c invoke\n    list $x $checkvar\n} -cleanup {\n    destroy .c\n} -result  {invoked 1}\ntest button-3.38 {ButtonWidgetCmd procedure, \"invoke\" option} -body {\n    radiobutton .r -command {set x invoked} -variable radiovar -value red\n    set radiovar green\n    set x \"not invoked\"\n    .r i\n    list $x $radiovar\n} -cleanup {\n    destroy .r\n} -result {invoked red}\n\ntest button-3.39 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    label .l\n    .l select\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad option \"select\": must be cget or configure}\ntest button-3.40 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    button .b\n    .b select\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad option \"select\": must be cget, configure, flash, or invoke}\ntest button-3.41 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    checkbutton .c\n    .c select foo\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {wrong # args: should be \".c select\"}\ntest button-3.42 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    checkbutton .c -variable checkvar -onvalue lovely -offvalue 0\n    set checkvar bogus\n    .c s\n    return $checkvar\n} -cleanup {\n    destroy .c\n} -result  {lovely}\ntest button-3.43 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar green\n    .r select\n    return $radiovar\n} -cleanup {\n    destroy .r\n} -result  {red}\ntest button-3.44 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar yellow\n    trace add variable radiovar write bogusTrace\n    .r select\n} -cleanup {\n    destroy .r\n    trace remove variable radiovar write bogusTrace\n} -returnCodes error -result {can't set \"radiovar\": trace aborted}\ntest button-3.45 {ButtonWidgetCmd procedure, \"select\" option} -body {\n    radiobutton .r -variable radiovar -value red\n    set radiovar yellow\n    trace add variable radiovar write bogusTrace\n    catch {.r select}\n    list $errorInfo $radiovar\n} -cleanup {\n    destroy .r\n    trace remove variable radiovar write bogusTrace\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".r select\"} red}\n\ntest button-3.46 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    label .l\n    .l toggle\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad option \"toggle\": must be cget or configure}\ntest button-3.47 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    button .b\n    .b toggle\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad option \"toggle\": must be cget, configure, flash, or invoke}\ntest button-3.48 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    radiobutton .r\n    .r toggle\n} -cleanup {\n    destroy .r\n} -returnCodes error -result {bad option \"toggle\": must be cget, configure, deselect, flash, invoke, or select}\ntest button-3.49 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    checkbutton .c\n    .c toggle foo\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {wrong # args: should be \".c toggle\"}\ntest button-3.50 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    set checkvar bogus\n    checkbutton .c -variable checkvar -onvalue sunshine -offvalue rain\n    .c toggle\n    set result $checkvar\n    .c toggle\n    lappend result $checkvar\n    .c toggle\n    lappend result $checkvar\n    return $result\n} -cleanup {\n    destroy .c\n} -result {sunshine rain sunshine}\ntest button-3.51 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    set checkvar xyz\n    trace add variable checkvar write bogusTrace\n    .c toggle\n} -cleanup {\n    destroy .c\n    trace remove variable checkvar write bogusTrace\n} -returnCodes error -result {can't set \"checkvar\": trace aborted}\ntest button-3.52 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    set checkvar xyz\n    trace add variable checkvar write bogusTrace\n    catch {.c toggle}\n    list $errorInfo $checkvar\n} -cleanup {\n    trace remove variable checkvar write bogusTrace\n    destroy .c\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".c toggle\"} abc}\ntest button-3.53 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    set checkvar abc\n    trace add variable checkvar write bogusTrace\n    .c toggle\n} -cleanup {\n    trace remove variable checkvar write bogusTrace\n    destroy .c\n} -returnCodes error -result {can't set \"checkvar\": trace aborted}\ntest button-3.54 {ButtonWidgetCmd procedure, \"toggle\" option} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    set checkvar abc\n    trace add variable checkvar write bogusTrace\n    catch {.c toggle}\n    list $errorInfo $checkvar\n} -cleanup {\n    trace remove variable checkvar write bogusTrace\n    destroy .c\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".c toggle\"} xyz}\ntest button-3.55 {ButtonWidgetCmd procedure, \"toggle\" option} -setup {\n    unset -nocomplain checkvar\n} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    unset checkvar\n    set checkvar(1) 1\n    .c toggle\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {can't set \"checkvar\": variable is array}\ntest button-3.56 {ButtonWidgetCmd procedure, \"toggle\" option} -setup {\n    unset -nocomplain checkvar\n} -body {\n    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc\n    unset checkvar\n    set checkvar(1) 1\n    catch {.c toggle}\n    return $errorInfo\n} -cleanup {\n    destroy .c\n} -match glob -result {can't set \"checkvar\": variable is array\n    while executing\n\".c toggle\"}\n\ntest button-4.1 {DestroyButton procedure} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n    unset -nocomplain x\n} -body {\n    button .b1 -image image1\n    button .b2 -fg #ff0000 -text \"Button 2\"\n    button .b3 -state active -text \"Button 3\"\n    button .b4 -disabledforeground #0000ff -state disabled -text \"Button 4\"\n    checkbutton .b5 -variable x -text \"Checkbutton 5\"\n    set x 1\n    pack .b1 .b2 .b3 .b4 .b5\n    update\n    deleteWindows\n} -cleanup {\n    destroy .b1 .b2 .b3 .b4 .b5\n    image delete image1\n} -result {}\n\ntest button-5.1 {ConfigureButton - textvariable trace} -body {\n    button .b -bd 4 -bg green\n    .b configure -bd 7 -bg red -fg bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest button-5.2 {ConfigureButton - textvariable trace} -body {\n    button .b -bd 4 -bg green\n    catch {.b configure -bd 7 -bg red -fg bogus}\n    list [.b cget -bd] [.b cget -bg]\n} -cleanup {\n    destroy .b\n} -result {4 green}\ntest button-5.3 {ConfigureButton - textvariable trace} -body {\n    button .b -textvariable x\n    set x From-x\n    set y From-y\n    .b configure -textvariable y\n    set x New\n    lindex [.b configure -text] 4\n} -cleanup {\n    destroy .b\n} -result {From-y}\ntest button-5.4 {ConfigureButton - variable trace} -body {\n    checkbutton .c -variable x\n    set x 1\n    set y 1\n    .c configure -textvariable y\n    set x 0\n    .c toggle\n    return $y\n} -cleanup {\n    destroy .c\n} -result 1\n\ntest button-5.5 {ConfigureButton - image handling} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n    image create test image1\n    image create test image2\n} -body {\n    button .b -image image1\n    image delete image1\n    .b configure -image image2\n    imageNames\n} -cleanup {\n    destroy .b\n    imageCleanup\n} -result {image2}\n\ntest button-5.6 {ConfigureButton - default value for variable} -body {\n    checkbutton .c\n    .c cget -variable\n} -cleanup {\n    destroy .c\n} -result {c}\ntest button-5.7 {ConfigureButton - setting selected state from variable} -body {\n    set x 0\n    set y Shiny\n    checkbutton .c -variable x\n    .c configure -variable y -onvalue Shiny\n    .c toggle\n    return $y\n} -cleanup {\n    destroy .c\n} -result 0\ntest button-5.8 {ConfigureButton - setting selected state from variable} -setup {\n    unset -nocomplain x\n} -body {\n    checkbutton .c -variable x -offvalue Bogus\n    return $x\n} -cleanup {\n    destroy .c\n} -result {Bogus}\n\ntest button-5.9 {ConfigureButton - setting selected state from variable} -setup {\n    unset -nocomplain x\n} -body {\n    radiobutton .r -variable x\n    return $x\n} -cleanup {\n    destroy .r\n} -result {}\n\ntest button-5.10 {ConfigureButton - error in setting variable} -setup {\n    unset -nocomplain x\n} -body {\n    trace add variable x write bogusTrace\n    radiobutton .r -variable x\n} -cleanup {\n    destroy .r\n    trace remove variable x write bogusTrace\n} -returnCodes error -result {can't set \"x\": trace aborted}\n\ntest button-5.11 {ConfigureButton - bad image name} -body {\n    button .b -image bogus\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest button-5.12 {ConfigureButton - setting variable from current text value} -setup {\n    unset -nocomplain x\n} -body {\n    button .b -textvariable x -text \"Button 1\"\n    return $x\n} -cleanup {\n    destroy .b\n} -result {Button 1}\n\ntest button-5.13 {ConfigureButton - using current value of variable} -body {\n    set x Override\n    button .b -textvariable x -text \"Button 1\"\n    return $x\n} -cleanup {\n    destroy .b\n} -result {Override}\n\ntest button-5.14 {ConfigureButton - variable handling} -setup {\n    unset -nocomplain x\n} -body {\n    trace add variable x write bogusTrace\n    radiobutton .r -text foo -textvariable x\n} -cleanup {\n    trace remove variable x write bogusTrace\n    destroy .r\n} -returnCodes error -result {can't set \"x\": trace aborted}\ntest button-5.15 {ConfigureButton - variable handling} -setup {\n    unset -nocomplain x\n} -body {\n    trace add variable x write bogusTrace\n    catch {radiobutton .r -text foo -textvariable x}\n\treturn $x\n} -cleanup {\n    trace remove variable x write bogusTrace\n    destroy .r\n} -result {foo}\n\n#ex 6.14\ntest button-5.16 {ConfigureButton - -width option} -body {\n    button .b -text \"Button 1\"\n    .b configure -width 1i\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"1i\"}\ntest button-5.17 {ConfigureButton - -width option} -body {\n    button .b -text \"Button 1\"\n    catch {.b configure -width 1i}\n    return $errorInfo\n} -cleanup {\n    destroy .b\n} -result  {expected integer but got \"1i\"\n    (processing \"-width\" option)\n    invoked from within\n\".b configure -width 1i\"}\ntest button-5.18 {ConfigureButton - -height option} -body {\n    button .b -text \"Button 1\"\n    .b configure -height 0.5c\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {expected integer but got \"0.5c\"}\ntest button-5.19 {ConfigureButton - -height option} -body {\n    button .b -text \"Button 1\"\n    catch {.b configure -height 0.5c}\n    return $errorInfo\n} -cleanup {\n    destroy .b\n} -result {expected integer but got \"0.5c\"\n    (processing \"-height\" option)\n    invoked from within\n\".b configure -height 0.5c\"}\n#ex 6.16\ntest button-5.20 {ConfigureButton - -width option} -body {\n    button .b -bitmap questhead\n    .b configure -width abc\n} -cleanup {\n    destroy .b\n} -returnCodes error -result  {expected screen distance but got \"abc\"}\ntest button-5.21 {ConfigureButton - -width option} -body {\n    button .b -bitmap questhead\n    catch {.b configure -width abc}\n    return $errorInfo\n} -cleanup {\n    destroy .b\n} -result {expected screen distance but got \"abc\"\n    (processing \"-width\" option)\n    invoked from within\n\".b configure -width abc\"}\ntest button-5.22 {ConfigureButton - -height option} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n} -body {\n    button .b -image image1\n    .b configure -height 0.5x\n} -cleanup {\n    destroy .b\n    image delete image1\n} -returnCodes error -result {expected screen distance but got \"0.5x\"}\ntest button-5.23 {ConfigureButton - -height option} -constraints {\n    testImageType\n} -setup {\n    image create test image1\n} -body {\n#ztestImageType\n    button .b -image image1\n    catch {.b configure -height 0.5x}\n    return $errorInfo\n} -cleanup {\n    destroy .b\n    image delete image1\n} -result  {expected screen distance but got \"0.5x\"\n    (processing \"-height\" option)\n    invoked from within\n\".b configure -height 0.5x\"}\n#ex 6.18\ntest button-5.24 {ConfigureButton - computing geometry} -constraints {\n    fonts\n} -body {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t\t-padx 30 -pady 20\n    # 1. button with text\n    .b configure -text \"Sample text\"\n    pack .b\n    set textwidth [font measure [.b cget -font] -displayof .b [.b cget -text]]\n    set expectedwidth [expr {$textwidth + 2*[.b cget -borderwidth] \\\n\t    + 2*[.b cget -highlightthickness] + 2*[.b cget -padx]}]\n    incr expectedwidth 2   ; # added (hardcoded) in tkUnixButton.c\n    set result [expr {$expectedwidth == [winfo reqwidth .b]}]\n    set linespace [lindex [font metrics [.b cget -font] -displayof .b] 5]\n    set expectedheight [expr {$linespace + 2*[.b cget -borderwidth] \\\n\t    + 2*[.b cget -highlightthickness] + 2*[.b cget -pady]}]\n    incr expectedheight 2   ; # added (hardcoded) in tkUnixButton.c\n    lappend result [expr {$expectedheight == [winfo reqheight .b]}]\n    # 2. button with a bitmap image\n    # there is no access to characteristics the predefined bitmaps,\n    # so define one as an image (copied from questhead.xbm)\n    set myquesthead [image create bitmap -data {\n\t#define myquesthead_width 20\n\t#define myquesthead_height 22\n\tstatic unsigned char myquesthead_bits[] = {\n\t   0xf8, 0x1f, 0x00, 0xac, 0x2a, 0x00, 0x56, 0x55, 0x00, 0xeb, 0xaf, 0x00,\n\t   0xf5, 0x5f, 0x01, 0xfb, 0xbf, 0x00, 0x75, 0x5d, 0x01, 0xfb, 0xbe, 0x02,\n\t   0x75, 0x5d, 0x05, 0xab, 0xbe, 0x0a, 0x55, 0x5f, 0x07, 0xab, 0xaf, 0x00,\n\t   0xd6, 0x57, 0x01, 0xac, 0xab, 0x00, 0xd8, 0x57, 0x00, 0xb0, 0xaa, 0x00,\n\t   0x50, 0x55, 0x00, 0xb0, 0x0b, 0x00, 0xd0, 0x17, 0x00, 0xb0, 0x0b, 0x00,\n\t   0x58, 0x15, 0x00, 0xa8, 0x2a, 0x00};\n    }]\n    .b configure -image $myquesthead\n    set expectedwidth [expr {[image width $myquesthead] + 2*[.b cget -borderwidth] \\\n\t    + 2*[.b cget -highlightthickness]}]\n    incr expectedwidth 2   ; # added (hardcoded) in tkUnixButton.c\n    lappend result [expr {$expectedwidth == [winfo reqwidth .b]}]\n    set expectedheight [expr {[image height $myquesthead] + 2*[.b cget -borderwidth] \\\n\t    + 2*[.b cget -highlightthickness]}]\n    incr expectedheight 2   ; # added (hardcoded) in tkUnixButton.c\n    lappend result [expr {$expectedheight == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .b\n} -result {1 1 1 1}\n\ntest button-5.25 {ConfigureButton - computing geometry} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n} -body {\n    .b configure -text \"Button 1\"\n    set old [winfo reqwidth .b]\n    .b configure -text \"Much longer text\"\n    set new [winfo reqwidth .b]\n    expr {$old == $new}\n} -cleanup {\n    destroy .b\n} -result 0\n\ntest button-6.1 {ButtonEventProc procedure} -body {\n    button .b -text \"Test Button\" -command {\n\t   destroy .b\n\t   set x [list [winfo exists .b] [info commands .b]]\n}\n    .b invoke\n    return $x\n} -cleanup {\n    destroy .b\n} -result {0 {}}\n\ntest button-6.2 {ButtonEventProc procedure} -setup {\n    set x {}\n} -body {\n    button .b1 -bg #543210\n    rename .b1 .b2\n    lappend x [winfo children .]\n    lappend x [.b2 cget -bg]\n    destroy .b1\n    lappend x [info command .b*] [winfo children .]\n} -cleanup {\n    destroy .b1\n} -result {.b1 #543210 {} {}}\n\ntest button-7.1 {ButtonCmdDeletedProc procedure} -body {\n    button .b\n    rename .b {}\n    list [info command .b*] [winfo children .]\n} -cleanup {\n    destroy .b\n} -result {{} {}}\n\ntest button-8.1 {TkInvokeButton procedure} -setup {\n    set x 0\n} -body {\n    checkbutton .c -variable x\n    set result $x\n    .c invoke\n    lappend result $x\n    .c invoke\n    lappend result $x\n} -cleanup {\n    destroy .c\n} -result {0 1 0}\n\ntest button-8.2 {TkInvokeButton procedure} -setup {\n    set x 0\n} -body {\n    checkbutton .c -variable x\n    trace add variable x write bogusTrace\n    .c invoke\n} -cleanup {\n    destroy .c\n    trace remove variable x write bogusTrace\n} -returnCodes error -result {can't set \"x\": trace aborted}\ntest button-8.3 {TkInvokeButton procedure} -setup {\n    set x 0\n} -body {\n    checkbutton .c -variable x\n    trace add variable x write bogusTrace\n    catch {.c invoke}\n    return $x\n} -cleanup {\n    destroy .c\n    trace remove variable x write bogusTrace\n} -result 1\ntest button-8.4 {TkInvokeButton procedure} -setup {\n    set x 1\n} -body {\n    checkbutton .c -variable x\n    trace add variable x write bogusTrace\n    .c invoke\n} -cleanup {\n    destroy .c\n    trace remove variable x write bogusTrace\n} -returnCodes error -result {can't set \"x\": trace aborted}\ntest button-8.5 {TkInvokeButton procedure} -setup {\n    set x 1\n} -body {\n    checkbutton .c -variable x\n    trace add variable x write bogusTrace\n    catch {.c invoke}\n    return $x\n} -cleanup {\n    destroy .c\n    trace remove variable x write bogusTrace\n} -result 0\n\ntest button-8.6 {TkInvokeButton procedure} -setup {\n    set x 0\n} -body {\n    radiobutton .r -variable x -value red\n    set result $x\n    .r invoke\n    lappend result $x\n    .r invoke\n    lappend result $x\n} -cleanup {\n    destroy .r\n} -result {0 red red}\n\ntest button-8.7 {TkInvokeButton procedure} -body {\n    radiobutton .r -variable x -value red\n    set x green\n    trace add variable x write bogusTrace\n    .r invoke\n} -cleanup {\n    destroy .r\n    trace remove variable x write bogusTrace\n} -returnCodes error -result {can't set \"x\": trace aborted}\ntest button-8.8 {TkInvokeButton procedure} -body {\n    radiobutton .r -variable x -value red\n    set x green\n    trace add variable x write bogusTrace\n    catch {.r invoke}\n    list $errorInfo $x\n} -cleanup {\n    destroy .r\n    trace remove variable x write bogusTrace\n} -match glob -result {{*trace aborted\n    while executing\n*\n\".r invoke\"} red}\n\n#ex 9.6\ntest button-8.9 {TkInvokeButton procedure} -setup {\n    set result untouched\n} -body {\n    button .b -command {set result invoked}\n    set msg [.b invoke]\n    list $msg $result\n} -cleanup {\n    destroy .b\n} -result {invoked invoked}\ntest button-8.10 {TkInvokeButton procedure} -setup {\n    set result untouched\n    set x 0\n} -body {\n    checkbutton .c -variable x -command {set result \"invoked $x\"}\n    set msg [.c invoke]\n    list $msg $result\n} -cleanup {\n    destroy .c\n} -result {{invoked 1} {invoked 1}}\ntest button-8.11 {TkInvokeButton procedure} -setup {\n    set result untouched\n    set x 0\n} -body {\n    radiobutton .r -variable x -value red -command {set result \"invoked $x\"}\n    set msg [.r invoke]\n    list $msg $result\n} -cleanup {\n    destroy .r\n} -result {{invoked red} {invoked red}}\n\ntest button-9.1 {ButtonVarProc procedure} -body {\n    set x 1\n    checkbutton .c -variable x\n    unset x\n    set result [info exists x]\n    .c toggle\n    lappend result $x\n    set x 0\n    .c toggle\n    lappend result $x\n} -cleanup {\n    destroy .c\n} -result {0 1 1}\ntest button-9.2 {ButtonVarProc procedure} -body {\n    set x 0\n    checkbutton .c -variable x\n    set x 44\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 1\ntest button-9.3 {ButtonVarProc procedure} -setup {\n    set x 1\n} -body {\n    checkbutton .c -variable x\n    set x 44\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 1\ntest button-9.4 {ButtonVarProc procedure} -setup {\n    set x 0\n} -body {\n    checkbutton .c -variable x\n    set x 1\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 0\ntest button-9.5 {ButtonVarProc procedure} -setup {\n    set x 1\n} -body {\n    checkbutton .c -variable x\n    set x 1\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 0\ntest button-9.6 {ButtonVarProc procedure} -setup {\n    set x 0\n} -body {\n    checkbutton .c -variable x\n    set x 0\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 1\ntest button-9.7 {ButtonVarProc procedure} -setup {\n    set x 1\n} -body {\n    checkbutton .c -variable x\n    set x 0\n    .c toggle\n    return $x\n} -cleanup {\n    destroy .c\n} -result 1\ntest button-9.8 {ButtonVarProc procedure, can't read variable} -setup {\n# This test does nothing but produce a core dump if there's a prbblem.\n    unset -nocomplain a\n} -body {\n    checkbutton .c -variable a\n    unset a\n    set a(32) 0\n    unset a\n} -cleanup {\n    destroy .c\n} -result {}\n\ntest button-10.1 {ButtonTextVarProc procedure} -body {\n    set x Label\n    button .b -textvariable x\n    unset x\n    set result [list $x [.b cget -text]]\n    set x New\n    lappend result [.b cget -text]\n} -cleanup {\n    destroy .b\n} -result {Label Label New}\ntest button-10.2 {ButtonTextVarProc procedure} -setup {\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n} -body {\n# Windows buttons have a default min width, so we have to\n# set this to be longer to force the wider button.\n    set x ExtraLongLabel\n    .b configure -textvariable x\n    set old [winfo reqwidth .b]\n    set x New\n    set new [winfo reqwidth .b]\n    expr {$old == $new}\n} -cleanup {\n    destroy .b\n} -result 0\n\ntest button-11.1 {ButtonImageProc procedure} -constraints {\n    testImageType\n} -setup {\n    label .l -highlightthickness 0 -font {Helvetica -12 bold}\n    image create test image1\n} -body {\n    .l configure -image image1 -padx 0 -pady 0 -bd 0\n    pack .l\n    set result \"[winfo reqwidth .l] [winfo reqheight .l]\"\n    image1 changed 0 0 0 0 80 100\n    lappend result [winfo reqwidth .l] [winfo reqheight .l]\n} -cleanup {\n    destroy .l\n    image delete image1\n} -result {30 15 80 100}\n\ntest button-12.1 {button widget vs hidden commands} -body {\n    button .b -text hello\n    set l [interp hidden]\n    interp hide {} .b\n    destroy .b\n\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 == $res2}\n} -cleanup {\n    destroy .b\n} -result 1\n\ntest button-13.1 {size behavior: label} -setup {\n    label .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    label .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    label .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\ntest button-13.2 {size behavior: label} -setup {\n    label .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    label .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    label .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-13.3 {size behavior: button} -setup {\n    button .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    button .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\ntest button-13.4 {size behavior: button} -setup {\n    button .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    button .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    button .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-13.5 {size behavior: radiobutton} -setup {\n    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-13.6 {size behavior: radiobutton} -setup {\n    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-13.7 {size behavior: checkbutton} -setup {\n    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-13.8 {size behavior: checkbutton} -setup {\n    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}\n    set result {}\n} -body {\n\t.a configure -text Hej\n\t.b configure -text Hej -width 10 -height 1\n\t.c configure -text \"\" -width 10 -height 1\n\n# With -width, width should not be affected by text change\n\tlappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]\n# With -height, height should not be affected by text change\n\tlappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]\n# A one line text should be as high as -height 1\n\tlappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]\n} -cleanup {\n    destroy .a .b .c\n} -result {1 1 1}\n\ntest button-14.1 {bug fix: [011706ec42] tk::ButtonInvoke unsafe wrt widget destruction} -body {\n    proc destroy_button {} {\n\tif {[winfo exists .top.b]} {\n\t    destroy .top.b\n\t}\n    }\n    toplevel .top\n    button .top.b -text Foo -command destroy_button\n    bind .top.b <space> destroy_button\n    pack .top.b\n    focus -force .top.b\n    update\n    event generate .top.b <space>\n    update  ; # shall not trigger error  invalid command name \".top.b\"\n} -cleanup {\n    destroy .top.b .top\n} -result {}\n\ntest button-15.1 {Bug [5d991b822e]} {\n    # Want this not to segfault\n    set var INIT\n    button .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n} {}\ntest button-15.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    button .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\ntest button-15.3 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    checkbutton .b -variable var\n    trace add variable var unset {apply {args {\n\t.b configure -variable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n} {}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ntestutils forget button image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/canvImg.test",
    "content": "# This file is a Tcl script to test out the procedures in tkCanvImg.c,\n# which implement canvas \"image\" items.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n# For every test case of the whole file\n#\ncanvas .c\npack .c\nupdate\n\n#\n# TESTS\n#\n\ntest canvImg-1.1 {options for image items} -body {\n    .c create image 50 50 -anchor nw -tags i1\n    .c itemconfigure i1 -anchor\n} -cleanup {\n    .c delete all\n} -result {-anchor {} {} center nw}\ntest canvImg-1.2 {options for image items} -body {\n    .c create image 50 50 -anchor gorp -tags i1\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {bad anchor \"gorp\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest canvImg-1.3 {options for image items} -constraints testImageType -setup {\n    image create test foo\n\t.c delete all\n} -body {\n    .c create image 50 50 -image foo -tags i1\n    .c itemconfigure i1 -image\n} -cleanup {\n    .c delete all\n\timage delete foo\n} -result {-image {} {} {} foo}\ntest canvImg-1.4 {options for image items} -body {\n    .c create image 50 50 -image unknown -tags i1\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {image \"unknown\" does not exist}\ntest canvImg-1.5 {options for image items} -constraints testImageType -setup {\n    image create test foo\n\t.c delete all\n} -body {\n    .c create image 50 50 -image foo -tags {i1 foo}\n    .c itemconfigure i1 -tags\n} -cleanup {\n    .c delete all\n\timage delete foo\n} -result {-tags {} {} {} {i1 foo}}\n\ntest canvImg-2.1 {CreateImage procedure} -body {\n    .c create image 40\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {wrong # coordinates: expected 2, got 1}\ntest canvImg-2.2 {CreateImage procedure} -body {\n    .c create image 40 50 60\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {unknown option \"60\"}\ntest canvImg-2.3 {CreateImage procedure} -body {\n    .c delete all\n    set i [.c create image 50 50]\n    list [lindex [.c itemconf $i -anchor] 4] \\\n\t    [lindex [.c itemconf $i -image] 4] \\\n\t    [lindex [.c itemconf $i -tags] 4]\n} -cleanup {\n    .c delete all\n} -result {center {} {}}\ntest canvImg-2.4 {CreateImage procedure} -body {\n    .c create image xyz 40\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvImg-2.5 {CreateImage procedure} -body {\n    .c create image 50 qrs\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {expected screen distance but got \"qrs\"}\ntest canvImg-2.6 {CreateImage procedure} -constraints testImageType -body {\n    .c create image 50 50 -gorp foo\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {unknown option \"-gorp\"}\n\n\ntest canvImg-3.1 {ImageCoords procedure} -constraints testImageType -setup {\n\timage create test foo\n} -body {\n    .c create image 50 100 -image foo -tags i1\n    format {%.6g %.6g} {*}[.c coords i1]\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -result {50 100}\ntest canvImg-3.2 {ImageCoords procedure} -constraints testImageType -setup {\n\timage create test foo\n} -body {\n    .c create image 50 100 -image foo -tags i1\n    .c coords i1 dumb 100\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -returnCodes error -result {expected screen distance but got \"dumb\"}\ntest canvImg-3.3 {ImageCoords procedure} -constraints testImageType -setup {\n\timage create test foo\n} -body {\n    .c delete all\n    .c create image 50 100 -image foo -tags i1\n    .c coords i1 250 dumb0\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -returnCodes error -result {expected screen distance but got \"dumb0\"}\ntest canvImg-3.4 {ImageCoords procedure} -constraints testImageType -setup {\n\timage create test foo\n} -body {\n    .c delete all\n    .c create image 50 100 -image foo -tags i1\n    .c coords i1 250\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -returnCodes error -result {wrong # coordinates: expected 2, got 1}\ntest canvImg-3.5 {ImageCoords procedure} -constraints testImageType -setup {\n\timage create test foo\n} -body {\n    .c delete all\n    .c create image 50 100 -image foo -tags i1\n    .c coords i1 250 300 400\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -returnCodes error -result {wrong # coordinates: expected 0 or 2, got 3}\n\n\ntest canvImg-4.1 {ConfiugreImage procedure} -constraints testImageType -setup {\n    .c delete all\n} -body {\n\timage create test foo -variable x\n    .c create image 50 100 -image foo -tags i1\n    update\n    set x {}\n    .c itemconfigure i1 -image {}\n    update\n    list $x [.c bbox i1]\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -result {{{foo free}} {}}\ntest canvImg-4.2 {ConfigureImage procedure} -constraints testImageType -setup {\n    .c delete all\n} -body {\n    image create test foo -variable x\n    image create test foo2 -variable y\n    foo2 changed 0 0 0 0 80 60\n    .c create image 50 100 -image foo -tags i1 -anchor nw\n    update\n    set x {}\n    set y {}\n    set timer [after 500 {lappend y \"timed out\"}]\n    .c itemconfigure i1 -image foo2\n    update idletasks\n    update\n    # On MacOS we need to wait for the test image display procedure to run.\n    while {\"timed out\" ni $y && [lindex $y end 1] ne \"display\"} {\n\tvwait y\n    }\n    after cancel $timer\n    list $x $y [.c bbox i1]\n} -cleanup {\n    .c delete all\n    image delete foo\n    image delete foo2\n} -result {{{foo free}} {{foo2 get} {foo2 display 0 0 80 60}} {50 100 130 160}}\ntest canvImg-4.3 {ConfiugreImage procedure} -constraints testImageType -setup {\n    .c delete all\n} -body {\n\timage create test foo -variable x\n    image create test foo2 -variable y\n    foo2 changed 0 0 0 0 80 60\n    .c create image 50 100 -image foo -tags i1 -anchor nw\n    update\n    set x {}\n    set y {}\n    .c itemconfigure i1 -image lousy\n} -cleanup {\n\t.c delete all\n\timage delete foo foo2\n} -returnCodes error -result {image \"lousy\" does not exist}\n\n\ntest canvImg-5.1 {DeleteImage procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    image create test foo2 -variable y\n    image create test xyzzy -variable z\n    .c create image 50 100 -image xyzzy -tags i1\n    update\n    set names [lsort [imageNames]]\n    image delete xyzzy\n    set z {}\n    set names2 [lsort [imageNames]]\n    .c delete i1\n    update\n    list $names $names2 $z [lsort [imageNames]]\n} -cleanup {\n    imageCleanup\n    .c delete all\n} -result {{foo foo2 xyzzy} {foo foo2} {} {foo foo2}}\ntest canvImg-5.2 {DeleteImage procedure (don't delete non-existent image)} -body {\n    .c delete all\n    .c create image 50 100 -tags i1\n    update\n    .c delete i1\n    update\n} -result {}\n\n\ntest canvImg-6.1 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c create image 15.51 17.51 -image foo -tags i1 -anchor nw\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {16 18 46 33}\ntest canvImg-6.2 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c create image 15.49 17.49 -image foo -tags i1 -anchor nw\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {15 17 45 32}\ntest canvImg-6.3 {ComputeImageBbox procedure} -setup {\n    .c delete all\n} -body {\n    .c create image 20 30 -tags i1 -anchor nw\n    .c bbox i1\n} -cleanup {\n    .c delete all\n} -result {}\ntest canvImg-6.4 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor nw\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {20 30 50 45}\ntest canvImg-6.5 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor n\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {5 30 35 45}\ntest canvImg-6.6 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor ne\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {-10 30 20 45}\ntest canvImg-6.7 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor e\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {-10 23 20 38}\ntest canvImg-6.8 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor se\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {-10 15 20 30}\ntest canvImg-6.9 {ComputeImageBbox procedure} -constraints testImageType -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor s\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {5 15 35 30}\ntest canvImg-6.10 {ComputeImageBbox procedure} -constraints {\n    testImageType\n} -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor sw\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    image delete foo\n} -result {20 15 50 30}\ntest canvImg-6.11 {ComputeImageBbox procedure} -constraints {\n    testImageType\n} -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor w\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    image delete foo\n} -result {20 23 50 38}\ntest canvImg-6.12 {ComputeImageBbox procedure} -constraints {\n\ttestImageType\n} -setup {\n    image create test foo\n    .c delete all\n} -body {\n    .c delete all\n    .c create image 20 30 -image foo -tags i1 -anchor center\n    .c bbox i1\n} -cleanup {\n    .c delete all\n    image delete foo\n} -result {5 23 35 38}\n\ntest canvImg-7.1 {DisplayImage procedure} -constraints {\n    testImageType\n} -setup {\n    .c delete all\n} -body {\n    image create test foo -variable x\n    .c create image 50 100 -image foo -tags i1 -anchor nw\n    update\n    set x {}\n    .c create rect 55 110 65 115 -width 1 -outline black -fill white\n    update\n    set x\n} -result {{foo display 4 9 12 6}}\ntest canvImg-7.2 {DisplayImage procedure, no image} -body {\n    .c delete all\n    .c create image 50 100 -tags i1\n    update\n    .c create rect 55 110 65 115 -width 1 -outline black -fill white\n    update\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvImg-8.*\n#\nif {[testConstraint testImageType]} {\n    image create test foo\n}\n\ntest canvImg-8.1 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect 50 70 80 81\n\t.c gettags [.c find closest 70 90]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.2 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{50 70 80 79}\n\t.c gettags [.c find closest {*}{70 90}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.3 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{99 70 110 81}\n\t.c gettags [.c find closest {*}{90 90}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.4 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{101 70 110 79}\n\t.c gettags [.c find closest {*}{90 90}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.5 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{99 100 110 115}\n\t.c gettags [.c find closest {*}{90 110}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.6 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{101 100 110 115}\n\t.c gettags [.c find closest {*}{90 110}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.7 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{99 134 110 145}\n\t.c gettags [.c find closest {*}{90 125}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.8 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{101 136 110 145}\n\t.c gettags [.c find closest {*}{90 125}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.9 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{50 134 80 145}\n\t.c gettags [.c find closest {*}{70 125}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.10 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{50 136 80 145}\n\t.c gettags [.c find closest {*}{70 125}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.11 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 134 31 145}\n\t.c gettags [.c find closest {*}{40 125}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.12 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 136 29 145}\n\t.c gettags [.c find closest {*}{40 125}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.13 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 100 31 115}\n\t.c gettags [.c find closest {*}{40 110}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.14 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 100 29 115}\n\t.c gettags [.c find closest {*}{40 110}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.15 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 70 31 80}\n\t.c gettags [.c find closest {*}{40 90}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\ntest canvImg-8.16 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{20 70 29 79}\n\t.c gettags [.c find closest {*}{40 90}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.17 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{60 70 69 109}\n\t.c gettags [.c find closest {*}{70 110}]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.18 {ImageToArea procedure} -constraints testImageType -setup {\n\t.c create image 50 100 -image foo -tags image -anchor nw\n\t.c create rect 10 10 20 20 -tags rect -fill black -width 0 -outline {}\n} -body {\n\t.c coords rect {*}{60 70 71 111}\n\t.c gettags [.c find closest {*}{70 110}]\n} -cleanup {\n\t.c delete all\n} -result {rect}\n\n#\n# COMMON TEST CLEANUP\n#\n.c delete all\n\ntest canvImg-8.19 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 0 70 99]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.20 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 0 70 99.999]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.21 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 0 70 101]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.22 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 81 105 120 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.23 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 80.001 105 120 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.24 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 79 105 120 115]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.25 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 116 70 150]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.26 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 115.001 70 150]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.27 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 60 114 70 150]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.28 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 105 49 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.29 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 105 50 114.999]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.30 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 105 51 115]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.31 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 0 49.999 99.999]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.32 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 0 51 101]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.33 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 80 0 150 100]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.34 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 79 0 150 101]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.35 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 80.001 115.001 150 180]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.36 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 79 114 150 180]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.37 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 115 50 180]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.38 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find overlapping 0 114 51 180]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.39 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 0 0 200 200]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.40 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 49.999 99.999 80.001 115.001]\n} -cleanup {\n\t.c delete all\n} -result {image}\ntest canvImg-8.41 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 51 100 80 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.42 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 50 101 80 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.43 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 50 100 79 115]\n} -cleanup {\n\t.c delete all\n} -result {}\ntest canvImg-8.44 {ImageToArea procedure} -constraints testImageType -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c gettags [.c find enclosed 50 100 80 114]\n} -cleanup {\n\t.c delete all\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\nif {[testConstraint testImageType]} {\n\timage delete foo\n}\n\ntest canvImg-9.1 {DisplayImage procedure} -constraints testImageType -setup {\n    .c delete all\n\timage create test foo\n} -body {\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c scale image 25 0 2.0 1.5\n    .c bbox image\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -result {75 150 105 165}\n\ntest canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup {\n    .c delete all\n    update\n} -body {\n    image create test foo -variable x\n    .c create image 50 100 -image foo -tags image -anchor nw\n    update\n    set x {}\n    set timer [after 500 {lappend x \"timed out\"}]\n    foo changed 2 4 6 8 30 15\n    vwait x\n    after cancel $timer\n    return $x\n} -cleanup {\n    .c delete all\n    image delete foo\n} -result {{foo display 2 4 6 8}}\n\ntest canvImg-11.1 {TranslateImage procedure} -constraints testImageType -setup {\n    .c delete all\n    update\n} -body {\n    image create test foo -variable x\n    .c create image 50 100 -image foo -tags image -anchor nw\n    update\n    set x {}\n    set timer [after 500 {lappend x \"timed out\"}]\n    foo changed 2 4 6 8 40 50\n    vwait x\n    after cancel $timer\n    update\n    return $x\n} -cleanup {\n    .c delete all\n    image delete foo\n} -result {{foo display 0 0 40 50}}\ntest canvImg-11.2 {ImageChangedProc procedure} -constraints {\n\ttestImageType\n} -setup {\n    .c delete all\n} -body {\n    image create test foo -variable x\n    .c create image 50 100 -image foo -tags image -anchor center\n    update\n    set x {}\n    foo changed 0 0 0 0 40 50\n    .c bbox image\n} -cleanup {\n\t.c delete all\n\timage delete foo\n} -result {30 75 70 125}\n\ntest canvImg-11.3 {ImageChangedProc procedure} -constraints {\n\ttestImageType\n} -setup {\n    .c delete all\n    update idletasks\n} -body {\n    image create test foo -variable x\n    image create test foo2 -variable z\n    foo changed 0 0 0 0 40 50\n    foo2 changed 0 0 0 0 80 60\n    .c create image 50 100 -image foo -tags image -anchor nw\n    .c create image 70 110 -image foo2 -anchor nw\n    set z {}\n    set timer [after 500 {lappend z \"timed out\"}]\n    image delete foo\n    vwait z\n    after cancel $timer\n    return $z\n} -cleanup {\n    .c delete all\n    image delete foo2\n} -result {{foo2 display 0 0 80 60}}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/canvMoveto.test",
    "content": "# This file is a Tcl script to test out the canvas \"moveto\" command. It is\n# derived from canvRect.test.\n#\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2004 Neil McKay.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\ncanvas .c -width 400 -height 300 -bd 2 -relief sunken\n.c create rectangle 20 20 80 80 -tag {test rect1}\n.c create rectangle 40 40 90 100 -tag {test rect2}\n\n#\n# TESTS\n#\n\ntest canvMoveto-1.1 {Bad args handling for \"moveto\" command} -body {\n    .c moveto test\n} -returnCodes error -result {wrong # args: should be \".c moveto tagOrId x y\"}\ntest canvMoveto-1.2 {Bad args handling for \"moveto\" command} -body {\n    .c moveto rect\n} -returnCodes error -result {wrong # args: should be \".c moveto tagOrId x y\"}\ntest canvMoveto-1.3 {Bad args handling for \"moveto\" command} -body {\n    .c moveto test 12\n} -returnCodes error -result {wrong # args: should be \".c moveto tagOrId x y\"}\ntest canvMoveto-1.4 {Bad args handling for \"moveto\" command} -body {\n    .c moveto test 12 y\n} -returnCodes error -result {expected screen distance but got \"y\"}\ntest canvMoveto-1.5 {Bad args handling for \"moveto\" command} -body {\n    .c moveto test 12 20 -anchor\n} -returnCodes error -result {wrong # args: should be \".c moveto tagOrId x y\"}\n\ntest canvMoveto-2.1 {Canvas \"moveto\" command coordinates} {\n    .c moveto test 200 150\n    .c bbox test\n} {200 150 272 232}\ntest canvMoveto-2.2 {Canvas \"moveto\" command, blank y coordinate} {\n    .c moveto test 200 150\n    .c moveto test 150 {}\n    .c bbox test\n} {150 150 222 232}\ntest canvMoveto-2.3 {Canvas \"moveto\" command, blank x coordinate} {\n    .c moveto test 200 150\n    .c moveto test {} 200\n    .c bbox test\n} {200 200 272 282}\n\n#\n# TESTFILE CLEANUP\n#\n\n.c delete withtag all\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/canvPs.test",
    "content": "# This file is a Tcl script to test out procedures to write postscript\n# for canvases to files and channels. It exercises the procedure\n# TkCanvPostscriptCmd in generic/tkCanvPs.c\n#\n# Copyright © 1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# TESTS\n#\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-1.* and canvas-2.*\n#\ncanvas .c -width 400 -height 300 -bd 2 -relief sunken\n.c create rectangle 20 20 80 80 -fill red\npack .c\nupdate\n\ntest canvPs-1.1 {test writing to a file} -constraints {\n    unixOrWin\n} -setup {\n    set foo [makeFile {} foo.ps]\n} -body {\n    set res [.c postscript -file $foo]\n    lappend res [file exists $foo]\n} -cleanup {\n    removeFile foo.ps\n} -result 1\ntest canvPs-1.2 {test writing to a file, idempotency} -constraints {\n    unixOrWin\n} -setup {\n    set foo [makeFile {} foo.ps]\n    set bar [makeFile {} bar.ps]\n} -body {\n    .c postscript -file $foo\n    .c postscript -file $bar\n    set status ok\n    if {[file size $bar] != [file size $foo]} {\n\tset status broken\n    }\n    set status\n} -cleanup {\n    removeFile foo.ps\n    removeFile bar.ps\n} -result ok\n\n\ntest canvPs-2.1 {test writing to a channel} -constraints {\n    unixOrWin\n} -setup {\n    set foo [makeFile {} foo.ps]\n    file delete $foo\n} -body {\n    set chan [open $foo w]\n    fconfigure $chan -translation lf\n    set res [.c postscript -channel $chan]\n    close $chan\n    lappend res [file exists $foo]\n} -cleanup {\n    removeFile foo.ps\n} -result 1\ntest canvPs-2.2 {test writing to channel, idempotency} -constraints {\n    unixOrWin\n} -setup {\n    set foo [makeFile {} foo.ps]\n    set bar [makeFile {} bar.ps]\n    file delete $foo\n    file delete $bar\n} -body {\n    set c1 [open $foo w]\n    set c2 [open $bar w]\n    fconfigure $c1 -translation lf\n    fconfigure $c2 -translation lf\n    .c postscript -channel $c1\n    .c postscript -channel $c2\n    close $c1\n    close $c2\n    set status ok\n    if {[file size $bar] != [file size $foo]} {\n\t    set status broken\n    }\n    set status\n} -cleanup {\n    removeFile foo.ps\n    removeFile bar.ps\n} -result ok\ntest canvPs-2.3 {test writing to channel and file, same output} -constraints {\n    unix\n} -setup {\n    set foo [makeFile {} foo.ps]\n    set bar [makeFile {} bar.ps]\n    file delete $foo\n    file delete $bar\n} -body {\n    set c1 [open $foo w]\n    fconfigure $c1 -translation lf\n    .c postscript -channel $c1\n    close $c1\n    .c postscript -file $bar\n    set status ok\n    if {[file size $foo] != [file size $bar]} {\n\t    set status broken\n    }\n    set status\n} -cleanup {\n    removeFile foo.ps\n    removeFile bar.ps\n} -result ok\ntest canvPs-2.4 {test writing to channel and file, same output} -constraints {\n    win\n} -setup  {\n    set foo [makeFile {} foo.ps]\n    set bar [makeFile {} bar.ps]\n    file delete $foo\n    file delete $bar\n} -body {\n    set c1 [open $foo w]\n    fconfigure $c1 -translation crlf\n    .c postscript -channel $c1\n    close $c1\n    .c postscript -file $bar\n    set status ok\n    if {[file size $foo] != [file size $bar]} {\n\t    set status broken\n    }\n    set status\n} -cleanup {\n    removeFile foo.ps\n    removeFile bar.ps\n} -result ok\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .c\n\ntest canvPs-3.1 {test ps generation with an embedded window} -setup {\n    set bar [makeFile {} bar.ps]\n    file delete $bar\n} -body {\n    pack [canvas .c -width 200 -height 200 -background white]\n    .c create rect 20 20 150 150 -tags rect0 -dash . -width 2\n    .c create arc 0 50 200 200 -tags arc0 \\\n\t    -dash {4 4} -stipple question -outline red -fill green\n\n    image create photo logo \\\n\t-file [file join [file dirname [info script]] pwrdLogo150.gif]\n    .c create image 200 50 -image logo -anchor nw\n\n    entry .c.e -background pink -foreground blue -width 14\n    .c.e insert 0 \"we gonna be postscripted\"\n    .c create window 50 180 -anchor nw -window .c.e\n\n    # Strong realization fixes for embedded window (XGetImage BadMatch)\n    wm geometry . 800x600+100+100\n    update\n    update idletasks\n    wm deiconify .\n    raise .\n    focus .c.e\n\n    # Extra time for X server\n    after 150 {update}\n    after 300 {update idletasks}\n    after 450 {update}\n\n    .c postscript -file $bar\n    file exists $bar\n} -cleanup {\n    destroy .c\n    imageCleanup\n    removeFile bar.ps\n} -result 1\n\n\ntest canvPs-3.2 {test ps generation with an embedded window not mapped} -setup {\n    set bar [makeFile {} bar.ps]\n    file delete $bar\n} -body {\n    pack [canvas .c -width 200 -height 200 -background white]\n    entry .c.e -background pink -foreground blue -width 14\n    .c.e insert 0 \"we gonna be postscripted\"\n    .c create window 50 180 -anchor nw -window .c.e\n\n    # Same strong realization fixes\n    wm geometry . 800x600+100+100\n    update\n    update idletasks\n    wm deiconify .\n    raise .\n    focus .c.e\n\n    after 150 {update}\n    after 300 {update idletasks}\n    after 450 {update}\n\n    .c postscript -file $bar\n    file exists $bar\n} -cleanup {\n    destroy .c\n    removeFile bar.ps\n} -result 1\n\ntest canvPs-4.1 {test ps generation with single-point uncolored poly, bug 734498} -body {\n    pack [canvas .c]\n    .c create poly 10 20 10 20\n    .c postscript\n} -cleanup {\n    destroy .c\n} -returnCodes ok -match glob -result *\n\n\ntest canvPs-5.1 {test ps generation with bitmap, bug 424773a00c} -body {\n    pack [canvas .c]\n    update\n    .c create bitmap 50 50 -bitmap questhead\n    .c postscript  ; # was crashing on macOS\n} -cleanup {\n    destroy .c\n} -returnCodes ok -match glob -result *\ntest canvPs-5.2 {test ps generation with image} -body {\n    pack [canvas .c]\n    update\n    .c create image 50 50 -image ::tk::icons::information\n    .c postscript\n} -cleanup {\n    destroy .c\n} -returnCodes ok -match glob -result *\n\n#\n# TESTFILE CLEANUP\n#\n\nunset -nocomplain foo bar\nimageFinish\ntestutils forget image\ndeleteWindows\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/canvPsArc.tcl",
    "content": "# This file creates a screen to exercise Postscript generation\n# for bitmaps in canvases.  It is part of the Tk visual test suite,\n# which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Postscript Tests for Canvases\"\nwm iconname .t \"Postscript\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nset c .t.c\n\nmessage .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for arcs.  Click on \"Print\" to print the canvas to your default printer.  You can click on items in the canvas to delete them.} -width 6i\npack .t.m -side top -fill both\n\nframe .t.bot\npack .t.bot -side bottom -fill both\nbutton .t.bot.quit -text Quit -command {destroy .t}\nbutton .t.bot.print -text Print -command \"lpr $c\"\npack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1\n\ncanvas $c -width 6i -height 6i -bd 2 -relief sunken\npack $c -expand yes -fill both -padx 2m -pady 2m\n\n$c create arc .5i .5i 2i 2i -style pieslice -start 20 -extent 90 \\\n    -fill black -outline {}\n$c create arc 2.5i 0 4.5i 1i -style pieslice -start -45 -extent -135 \\\n    -fill {} -outline black -outlinestipple gray50 -width 3m\n$c create arc 5.0i .5i 6.5i 2i -style pieslice -start 45 -extent 315 \\\n    -fill black -stipple gray25 -outline black -width 1m\n\n$c create arc -.5i 2.5i 2.0i 3.5i -style chord -start 90 -extent 270 \\\n    -fill black -outline {}\n$c create arc 2.5i 2i 4i 6i -style chord -start 20 -extent 140 \\\n    -fill black -stipple gray50 -outline black -width 2m\n$c create arc 4i 2.5i 8i 4.5i -style chord -start 60 -extent 60 \\\n    -fill {} -outline black\n\n$c create arc .5i 4.5i 2i 6i -style arc -start 135 -extent 315 -width 3m \\\n    -outline black -outlinestipple gray25\n$c create arc 3.5i 4.5i 5.5i 5.5i -style arc -start 45 -extent -90 -width 1m \\\n    -outline black\n"
  },
  {
    "path": "tests/canvPsBmap.tcl",
    "content": "# This file creates a screen to exercise Postscript generation\n# for bitmaps in canvases.  It is part of the Tk visual test suite,\n# which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Postscript Tests for Canvases\"\nwm iconname .t \"Postscript\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nset c .t.c\n\nmessage .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for bitmaps.  Click on \"Print\" to print the canvas to your default printer.  You can click on items in the canvas to delete them.} -width 6i\npack .t.m -side top -fill both\n\nframe .t.bot\npack .t.bot -side bottom -fill both\nbutton .t.bot.quit -text Quit -command {destroy .t}\nbutton .t.bot.print -text Print -command \"lpr $c\"\npack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1\n\ncanvas $c -width 6i -height 6i -bd 2 -relief sunken\npack $c -expand yes -fill both -padx 2m -pady 2m\n\nset canvPsBmapImageDir [file join [file dirname [info script]] images]\n\n$c create bitmap 0.5i 0.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \\\n    -background {} -foreground black -anchor nw\n$c create rect 0.47i 0.47i 0.53i 0.53i -fill {} -outline black\n\n$c create bitmap 3.0i 0.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \\\n    -background {} -foreground black -anchor n\n$c create rect 2.97i 0.47i 3.03i 0.53i -fill {} -outline black\n\n$c create bitmap 5.5i 0.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagdown.xbm] \\\n    -background black -foreground white -anchor ne\n$c create rect 5.47i 0.47i 5.53i 0.53i -fill {} -outline black\n\n$c create bitmap 0.5i 3.0i \\\n    -bitmap @[file join $canvPsBmapImageDir face.xbm] \\\n    -background {} -foreground black -anchor w\n$c create rect 0.47i 2.97i 0.53i 3.03i -fill {} -outline black\n\n$c create bitmap 3.0i 3.0i \\\n    -bitmap @[file join $canvPsBmapImageDir face.xbm] \\\n    -background {} -foreground black -anchor center\n$c create rect 2.97i 2.97i 3.03i 3.03i -fill {} -outline black\n\n$c create bitmap 5.5i 3.0i \\\n    -bitmap @[file join $canvPsBmapImageDir face.xbm] \\\n    -background blue -foreground black -anchor e\n$c create rect 5.47i 2.97i 5.53i 3.03i -fill {} -outline black\n\n$c create bitmap 0.5i 5.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \\\n    -background black -foreground white -anchor sw\n$c create rect 0.47i 5.47i 0.53i 5.53i -fill {} -outline black\n\n$c create bitmap 3.0i 5.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \\\n    -background green -foreground white -anchor s\n$c create rect 2.97i 5.47i 3.03i 5.53i -fill {} -outline black\n\n$c create bitmap 5.5i 5.5i \\\n    -bitmap @[file join $canvPsBmapImageDir flagup.xbm] \\\n    -background {} -foreground black -anchor se\n$c create rect 5.47i 5.47i 5.53i 5.53i -fill {} -outline black\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/canvPsGrph.tcl",
    "content": "# This file creates a screen to exercise Postscript generation\n# for some of the graphical objects in canvases.  It is part of the Tk\n# visual test suite, which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Postscript Tests for Canvases\"\nwm iconname .t \"Postscript\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nset c .t.mid.c\n\nmessage .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets.  Select what you want to display with the buttons below, then click on \"Print\" to print it to your default printer.  You can click on items in the canvas to delete them.} -width 4i\npack .t.m -side top -fill both\n\nframe .t.top\npack .t.top -side top -fill both\nset what rect\nradiobutton .t.top.rect -text Rectangles -variable what -value rect \\\n\t-command \"mkObjs $c\" -relief flat\nradiobutton .t.top.oval -text Ovals -variable what -value oval \\\n\t-command \"mkObjs $c\" -relief flat\nradiobutton .t.top.poly -text Polygons -variable what -value poly \\\n\t-command \"mkObjs $c\" -relief flat\nradiobutton .t.top.line -text Lines -variable what -value line \\\n\t-command \"mkObjs $c\" -relief flat\npack .t.top.rect .t.top.oval .t.top.poly .t.top.line \\\n\t-side left -pady 2m -ipadx 2m -ipady 1m -expand 1\n\nframe .t.bot\npack .t.bot -side bottom -fill both\nbutton .t.bot.quit -text Quit -command {destroy .t}\nbutton .t.bot.print -text Print -command \"lpr $c\"\npack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1\n\nframe .t.mid -relief sunken -bd 2\npack .t.mid -side top -expand yes -fill both -padx 2m -pady 2m\ncanvas $c -width 400 -height 350 -bd 0 -relief sunken\npack $c -expand yes -fill both -padx 1 -pady 1\n\nproc mkObjs c {\n    global what\n    $c delete all\n    if {$what eq \"rect\"} {\n\t$c create rect 0 0 400 350 -outline black\n\t$c create rect 2 2 100 50 -fill black -stipple gray25\n\t$c create rect -20 180 80 320 -fill black -stipple gray50 -width .5c\n\t$c create rect 200 -20 240 20 -fill black\n\t$c create rect 380 200 420 240 -fill black\n\t$c create rect 200 330 240 370 -fill black\n    }\n\n    if {$what eq \"oval\"} {\n\t$c create oval 50 10 150 80 -fill black -stipple gray25 -outline {}\n\t$c create oval 100 100 200 150 -outline {} -fill black -stipple gray50\n\t$c create oval 250 100 400 300 -width .5c\n    }\n\n    if {$what eq \"poly\"} {\n\t$c create poly 100 200 200 50 300 200 -smooth yes -stipple gray25 \\\n\t\t-outline black -width 4\n\t$c create poly 100 300 100 250 350 250 350 300 350 300 100 300 100 300 \\\n\t\t-fill red -smooth yes\n\t$c create poly 20 10 40 10 40 60 80 60 80 25 30 25 30 \\\n\t\t35 50 35 50 45 20 45\n\t$c create poly 300 20 300 120 380 80 320 100 -fill blue -outline black\n\t$c create poly 20 200 100 220 90 100 40 250 \\\n\t\t-fill {} -outline brown -width 3\n    }\n\n    if {$what eq \"line\"} {\n\t$c create line 20 20 120 20 -arrow both -width 5\n\t$c create line 20 80 150 80 20 200 150 200 -smooth yes\n\t$c create line 150 20 150 150 250 150 -width .5c -smooth yes \\\n\t\t-arrow both -arrowshape {.75c 1.0c .5c} -stipple gray25\n\t$c create line 50 340 100 250 150 340 -join round -cap round -width 10\n\t$c create line 200 340 250 250 300 340 -join bevel -cap project \\\n\t\t-width 10\n\t$c create line 300 20 380 20 300 150 380 150 -join miter -cap butt \\\n\t\t-width 10 -stipple gray25\n    }\n}\n\nmkObjs $c\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/canvPsImg.tcl",
    "content": "# This file creates a screen to exercise Postscript generation\n# for images in canvases.  It is part of the Tk visual test suite,\n# which is invoked via the \"visual\" script.\n\n# Build a test image in a canvas\nproc BuildTestImage {} {\n    global BitmapImage PhotoImage visual level\n    catch {destroy .t.f}\n    frame .t.f -visual $visual -colormap new\n    pack .t.f -side top -after .t.top\n    bind .t.f <Enter> {wm colormapwindows .t {.t.f .t}}\n    bind .t.f <Leave> {wm colormapwindows .t {.t .t.f}}\n    canvas .t.f.c -width 550 -height 350 -borderwidth 2 -relief raised\n    pack .t.f.c\n    .t.f.c create rectangle 25 25 525 325 -fill {} -outline black\n    .t.f.c create image 50 50 -anchor nw -image $BitmapImage\n    .t.f.c create image 250 50 -anchor nw -image $PhotoImage\n}\n\n# Put postscript in a file\nproc FilePostscript { canvas } {\n    global level\n    $canvas postscript -file /tmp/test.ps -colormode $level\n}\n\n# Send postscript output to printer\nproc PrintPostcript { canvas } {\n    global level\n    $canvas postscript -file tmp.ps -colormode $level\n    exec lpr tmp.ps\n}\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Postscript Tests for Canvases: Images\"\nwm iconname .t \"Postscript\"\n\nmessage .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for images.  Click the buttons below to select a Visual type for the canvas and colormode for the Postscript output.  Then click \"Print\" to send the results to the default printer, or \"Print to file\" to put the Postscript output in a file called \"/tmp/test.ps\".  You can also click on items in the canvas to delete them.\nNOTE: Some Postscript printers may not be able to handle Postscript generated in color mode.} -width 6i\npack .t.m -side top -fill both\n\nframe .t.top\npack .t.top -side top\nframe .t.top.l -relief raised -borderwidth 2\nframe .t.top.r -relief raised -borderwidth 2\npack .t.top.l .t.top.r -side left -fill both -expand 1\n\nlabel .t.visuals -text \"Visuals\"\npack .t.visuals -in .t.top.l\n\nset visual [lindex [winfo visualsavailable .] 0]\nforeach v [winfo visualsavailable .] {\n    # The hack below is necessary for some systems, which have more than one\n    # visual of the same type...\n    if {![winfo exists .t.$v]} {\n\tradiobutton .t.$v -text $v -variable visual -value $v \\\n\t\t-command BuildTestImage\n\tpack .t.$v -in .t.top.l -anchor w\n    }\n}\n\nlabel .t.levels -text \"Color Levels\"\npack .t.levels -in .t.top.r\nset level monochrome\nforeach l { monochrome gray color } {\n    radiobutton .t.$l -text $l -variable level -value $l\n    pack .t.$l -in .t.top.r -anchor w\n}\n\nset BitmapImage [image create bitmap \\\n\t-file [file join [file dirname [info script]] face.xbm] \\\n\t-background white -foreground black]\nset PhotoImage [image create photo \\\n\t-file [file join [file dirname [info script]] teapot.ppm]]\n\nBuildTestImage\n\nframe .t.bot\npack .t.bot -side top -fill x -expand 1\n\nbutton .t.file -text \"Print to File\" -command { FilePostscript .t.f.c }\nbutton .t.print -text \"Print\" -command { PrintPostscript .t.f.c }\nbutton .t.quit -text \"Quit\" -command { destroy .t }\npack .t.file .t.print .t.quit -in .t.bot -side left -fill x -expand 1\n"
  },
  {
    "path": "tests/canvPsText.tcl",
    "content": "# This file creates a screen to exercise Postscript generation\n# for text in canvases.  It is part of the Tk visual test suite,\n# which is invoked via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t\nwm title .t \"Postscript Tests for Canvases\"\nwm iconname .t \"Postscript\"\nwm geom .t +0+0\nwm minsize .t 1 1\n\nset c .t.c\n\nmessage .t.m -text {This screen exercises the Postscript-generation abilities of Tk canvas widgets for text.  Click on \"Print\" to print the canvas to your default printer.  The \"Stipple\" button can be used to turn stippling on and off for the text, but beware:  many Postscript printers cannot handle stippled text.  You can click on items in the canvas to delete them.} -width 6i\npack .t.m -side top -fill both\n\nset stipple {}\ncheckbutton .t.stipple -text Stippling -variable stipple -onvalue gray50 \\\n\t-offvalue {} -command \"setStipple $c\" -relief flat\npack .t.stipple -side top -pady 2m -expand 1 -anchor w\n\nframe .t.bot\npack .t.bot -side bottom -fill both\nbutton .t.bot.quit -text Quit -command {destroy .t}\nbutton .t.bot.print -text Print -command \"lpr $c\"\npack .t.bot.print .t.bot.quit -side left -pady 1m -expand 1\n\ncanvas $c -width 6i -height 7i -bd 2 -relief sunken\npack $c -expand yes -fill both -padx 2m -pady 2m\n\n$c create rect 2.95i 0.45i 3.05i 0.55i -fill {} -outline black\n$c create text 3.0i 0.5i -text \"Center Courier Oblique 24\" \\\n\t-anchor center -tags text -font {Courier 24 italic} -stipple $stipple\n$c create rect 2.95i 0.95i 3.05i 1.05i -fill {} -outline black\n$c create text 3.0i 1.0i -text \"Northwest Helvetica 24\" \\\n\t-anchor nw -tags text -font {Helvetica 24} -stipple $stipple\n$c create rect 2.95i 1.45i 3.05i 1.55i -fill {} -outline black\n$c create text 3.0i 1.5i -text \"North Helvetica Oblique 12 \" \\\n\t-anchor n -tags text -font {Helvetica 12 italic} -stipple $stipple\n$c create rect 2.95i 1.95i 3.05i 2.05i -fill {} -outline blue\n$c create text 3.0i 2.0i -text \"Northeast Helvetica Bold 24\" \\\n\t-anchor ne -tags text -font {Helvetica 24 bold} -stipple $stipple\n$c create rect 2.95i 2.45i 3.05i 2.55i -fill {} -outline black\n$c create text 3.0i 2.5i -text \"East Helvetica Bold Oblique 18\" \\\n\t-anchor e -tags text -font {Helvetica 18 {bold italic}} -stipple $stipple\n$c create rect 2.95i 2.95i 3.05i 3.05i -fill {} -outline black\n$c create text 3.0i 3.0i -text \"Southeast Times 10\" \\\n\t-anchor se -tags text -font {Times 10} -stipple $stipple\n$c create rect 2.95i 3.45i 3.05i 3.55i -fill {} -outline black\n$c create text 3.0i 3.5i -text \"South Times Italic 24\" \\\n\t-anchor s -tags text -font {Times 24 italic} -stipple $stipple\n$c create rect 2.95i 3.95i 3.05i 4.05i -fill {} -outline black\n$c create text 3.0i 4.0i -text \"Southwest Times Bold 18\" \\\n\t-anchor sw -tags text -font {Times 18 bold} -stipple $stipple\n$c create rect 2.95i 4.45i 3.05i 4.55i -fill {} -outline black\n$c create text 3.0i 4.5i -text \"West Times Bold Italic 24\"\\\n\t-anchor w -tags text -font {Times 24 {bold italic}} -stipple $stipple\n\n$c create rect 0.95i 5.20i 1.05i 5.30i -fill {} -outline black\n$c create text 1.0i 5.25i -width 1.9i -anchor c -justify left -tags text \\\n\t-font {Times 18 bold} -stipple $stipple \\\n\t-text \"This is a sample text item to see how left justification works\"\n$c create rect 2.95i 5.20i 3.05i 5.30i -fill {} -outline black\n$c create text 3.0i 5.25i -width 1.8i -anchor c -justify center -tags text \\\n\t-font {Times 18 bold} -stipple $stipple \\\n\t-text \"This is a sample text item to see how center justification works\"\n$c create rect 4.95i 5.20i 5.05i 5.30i -fill {} -outline black\n$c create text 5.0i 5.25i -width 1.8i -anchor c -justify right -tags text \\\n\t-font {Times 18 bold} -stipple $stipple \\\n\t-text \"This is a sample text item to see how right justification works\"\n\n$c create text 3.0i 6.0i -width 5.0i -anchor n -justify right -tags text \\\n\t-text \"This text is\\nright justified\\nwith a line length equal to\\n\\\n\tthe size of the enclosing rectangle.\\nMake sure it prints right\\\n\tjustified as well.\"\n$c create rect 0.5i 6.0i 5.5i 6.9i -fill {} -outline black\n\nproc setStipple c {\n    global stipple\n    $c itemconfigure text -stipple $stipple\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/canvRect.test",
    "content": "# This file is a Tcl script to test out the procedures in tkRectOval.c,\n# which implement canvas \"rectangle\" and \"oval\" items.\n#\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n# For every test case of the whole file\n#\ncanvas .c -width 400 -height 300 -bd 2 -relief sunken\npack .c\nupdate\n\n#\n# TESTS\n#\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvRect-1.*\n#\n.c create rectangle 20 20 80 80 -tag test\n\ntest canvRect-1.1 {configuration options: good value for -fill} -body {\n    .c itemconfigure test -fill #ff0000\n    list [.c itemcget test -fill] [lindex [.c itemconfigure test -fill] 4]\n} -result {{#ff0000} #ff0000}\ntest canvRect-1.2 {configuration options: bad value for -fill} -body {\n    .c itemconfigure test -fill non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest canvRect-1.3 {configuration options: good value for -outline} -body {\n    .c itemconfigure test -outline #123456\n    list [.c itemcget test -outline] [lindex [.c itemconfigure test -outline] 4]\n} -result {{#123456} #123456}\ntest canvRect-1.4 {configuration options: bad value for -outline} -body {\n    .c itemconfigure test -outline non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest canvRect-1.5 {configuration options: good value for -stipple } -body {\n    .c itemconfigure test -stipple  gray50\n    list [.c itemcget test -stipple ] [lindex [.c itemconfigure test -stipple ] 4]\n} -result {gray50 gray50}\ntest canvRect-1.6 {configuration options: bad value for -stipple } -body {\n    .c itemconfigure test -stipple  bogus\n} -returnCodes error -result {bitmap \"bogus\" not defined}\ntest canvRect-1.7 {configuration options: good value for -tags} -body {\n    .c itemconfigure test -tags {test a b c}\n    list [.c itemcget test -tags] [lindex [.c itemconfigure test -tags] 4]\n} -result {{test a b c} {test a b c}}\ntest canvRect-1.8 {configuration options} -body {\n    .c itemconfigure test -tags {test xyz}\n    .c itemcget xyz -tags\n} -result {test xyz}\ntest canvRect-1.9 {configuration options: good value for -width} -body {\n    .c itemconfigure test -width 6.0\n    list [.c itemcget test -width] [lindex [.c itemconfigure test -width] 4]\n} -result {6.0 6.0}\ntest canvRect-1.10 {configuration options: bad value for -width} -body {\n    .c itemconfigure test -width abc\n} -returnCodes error -result {expected screen distance but got \"abc\"}\n\n#\n# COMMON TEST CLEANUP\n#\n.c delete withtag all\n\ntest canvRect-2.1 {CreateRectOval procedure} -body {\n    .c create rect\n} -returnCodes error -result {wrong # args: should be \".c create rect coords ?arg ...?\"}\ntest canvRect-2.2 {CreateRectOval procedure} -body {\n    .c create oval x y z\n} -returnCodes error -result {wrong # coordinates: expected 0 or 4, got 3}\ntest canvRect-2.3 {CreateRectOval procedure} -body {\n    .c create rectangle x 2 3 4\n} -returnCodes error -result {expected screen distance but got \"x\"}\ntest canvRect-2.4 {CreateRectOval procedure} -body {\n    .c create rectangle 1 y 3 4\n} -returnCodes error -result {expected screen distance but got \"y\"}\ntest canvRect-2.5 {CreateRectOval procedure} -body {\n    .c create rectangle 1 2 z 4\n} -returnCodes error -result {expected screen distance but got \"z\"}\ntest canvRect-2.6 {CreateRectOval procedure} -body {\n    .c create rectangle 1 2 3 q\n} -returnCodes error -result {expected screen distance but got \"q\"}\ntest canvRect-2.7 {CreateRectOval procedure} -body {\n    .c create rectangle 1 2 3 4 -tags x\n    set result {}\n    foreach element [.c coords x] {\n\t    lappend result [format %.1f $element]\n    }\n    set result\n} -result {1.0 2.0 3.0 4.0}\ntest canvRect-2.8 {CreateRectOval procedure} -body {\n    .c create rectangle 1 2 3 4 -gorp foo\n} -returnCodes error -result {unknown option \"-gorp\"}\n\n#\n# COMMON TEST CLEANUP\n#\n.c delete withtag all\n\ntest canvRect-3.1 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    set result {}\n    foreach element [.c coords x] {\n\t    lappend result [format %.1f $element]\n    }\n    return $result\n} -cleanup {\n    .c delete withtag all\n} -result {10.0 20.0 30.0 40.0}\ntest canvRect-3.2 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x a 2 3 4\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"a\"}\ntest canvRect-3.3 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x 1 b 3 4\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"b\"}\ntest canvRect-3.4 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x 1 2 c 4\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"c\"}\ntest canvRect-3.5 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x 1 2 3 d\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"d\"}\ntest canvRect-3.6 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x 10 25 15 40\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {9 24 16 41}\ntest canvRect-3.7 {RectOvalCoords procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x\n    .c coords x 1 2 3 4 5\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {wrong # coordinates: expected 0 or 4, got 5}\n\n\ntest canvRect-4.1 {ConfigureRectOval procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1\n    .c itemconfigure x -width abc\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"abc\"}\ntest canvRect-4.2 {ConfigureRectOval procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1\n    catch {.c itemconfigure x -width abc}\n\t.c itemcget x -width\n} -cleanup {\n    .c delete withtag all\n} -result {1.0}\ntest canvRect-4.3 {ConfigureRectOval procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1\n    .c itemconfigure x -width -5\n} -cleanup {\n    .c delete withtag all\n} -returnCodes error -result {expected screen distance but got \"-5\"}\ntest canvRect-4.4 {ConfigureRectOval procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1\n    .c itemconfigure x -width 10\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {5 15 35 45}\n\n# I can't come up with any good tests for DeleteRectOval.\n\ntest canvRect-5.1.1 {ComputeRectOvalBbox procedure} -constraints macOrUnix -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}\n    .c coords x 20 15 10 5\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {10 5 20 15}\n# On Windows the bbox of rectangle items is 1 pixel larger at each border due\n# to the \"bloat\" implemented in ComputeRectOvalBbox() in case -outline is {}\ntest canvRect-5.1.2 {ComputeRectOvalBbox procedure} -constraints win32 -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}\n    .c coords x 20 15 10 5\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {9 4 21 16}\ntest canvRect-5.2 {ComputeRectOvalBbox procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}\n    .c coords x 10 20 30 10\n    .c itemconfigure x -width 1 -outline red\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {9 9 31 21}\ntest canvRect-5.3 {ComputeRectOvalBbox procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}\n    .c coords x 10 20 30 10\n    .c itemconfigure x -width 2 -outline red\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {9 9 31 21}\ntest canvRect-5.4 {ComputeRectOvalBbox procedure} -body {\n    .c create rectangle 10 20 30 40 -tags x -width 1 -outline {}\n    .c coords x 10 20 30 10\n    .c itemconfigure x -width 3 -outline red\n    .c bbox x\n} -cleanup {\n    .c delete withtag all\n} -result {8 8 32 22}\n\n# I can't come up with any good tests for DisplayRectOval.\n\ntest canvRect-6.1 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n    .c itemconfigure y -outline {}\n    list [expr {[.c find closest 14.9 28] eq $xId}] \\\n\t\t[expr {[.c find closest 15.1 28] eq $yId}] \\\n\t\t[expr {[.c find closest 24.9 28] eq $yId}] \\\n\t\t[expr {[.c find closest 25.1 28] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\ntest canvRect-6.2 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n    .c itemconfigure y -outline {}\n    list [expr {[.c find closest 20 24.9] eq $xId}] \\\n\t\t [expr {[.c find closest 20 25.1] eq $yId}] \\\n\t    [expr {[.c find closest 20 29.9] eq $yId}] \\\n\t\t [expr {[.c find closest 20 30.1] eq $xId}]\n\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\ntest canvRect-6.3 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n    .c itemconfigure y -width 1 -outline black\n    list [expr {[.c find closest 14.4 28] eq $xId}] \\\n\t\t [expr {[.c find closest 14.6 28] eq $yId}] \\\n\t    [expr {[.c find closest 25.4 28] eq $yId}] \\\n\t\t [expr {[.c find closest 25.6 28] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\ntest canvRect-6.4 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n    .c itemconfigure  y -width 1 -outline black\n    list [expr {[.c find closest 20 24.4] eq $xId}] \\\n\t\t [expr {[.c find closest 20 24.6] eq $yId}] \\\n\t    [expr {[.c find closest 20 30.4] eq $yId}] \\\n\t\t [expr {[.c find closest 20 30.6] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\n\ntest canvRect-6.5 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n\t.c itemconfigure x -fill {} -outline black -width 3\n\t.c itemconfigure y -outline {}\n    list [expr {[.c find closest 13.2 28] eq $xId}] \\\n\t\t [expr {[.c find closest 13.3 28] eq $yId}] \\\n\t    [expr {[.c find closest 26.7 28] eq $yId}] \\\n\t\t [expr {[.c find closest 26.8 28] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\ntest canvRect-6.6 {RectToPoint procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -tags x -fill green]\n\tset yId [.c create rectangle 15 25 25 30  -tags y -fill red]\n\t.c itemconfigure x -fill {} -outline black -width 3\n\t.c itemconfigure y -outline {}\n    list [expr {[.c find closest 20 23.2] eq $xId}] \\\n\t\t [expr {[.c find closest 20 23.3] eq $yId}] \\\n\t    [expr {[.c find closest 20 31.7] eq $yId}] \\\n\t\t [expr {[.c find closest 20 31.8] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\n\ntest canvRect-6.7 {RectToPoint procedure} -body {\n\tset xId [.c create rectangle 10 20 30 40 -outline {} -fill black]\n\tset yId [.c create rectangle 40 40 50 50 -outline {} -fill black]\n    list [expr {[.c find closest 35 35] eq $xId}] \\\n\t\t [expr {[.c find closest 36 36] eq $yId}] \\\n\t    [expr {[.c find closest 37 37] eq $yId}] \\\n\t\t [expr {[.c find closest 38 38] eq $yId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1}\n\n\ntest canvRect-7.1 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 20 50 38 60] eq {}}] \\\n\t    [expr {[.c find overlapping 20 50 39 60] eq $yId}] \\\n\t    [expr {[.c find overlapping 20 50 70 60] eq $yId}] \\\n\t    [expr {[.c find overlapping 61 50 70 60] eq $yId}] \\\n\t    [expr {[.c find overlapping 62 50 70 60] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1}\ntest canvRect-7.2 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 45 20 55 43] eq {}}] \\\n\t    [expr {[.c find overlapping 45 20 55 44] eq $yId}] \\\n\t    [expr {[.c find overlapping 45 20 55 80] eq $yId}] \\\n\t    [expr {[.c find overlapping 45 71 55 80] eq $yId}] \\\n\t    [expr {[.c find overlapping 45 72 55 80] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1}\ntest canvRect-7.3 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 5 25 9.9 30] eq {}}] \\\n\t\t[expr {[.c find overlapping 5 25 10.1 30] eq $xId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1}\ntest canvRect-7.4 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 102 152 118 168]  eq {}}]\\\n\t    [expr {[.c find overlapping 101 152 118 168] eq $zId}] \\\n\t    [expr {[.c find overlapping 102 151 118 168] eq $zId}] \\\n\t    [expr {[.c find overlapping 102 152 119 168] eq $zId}] \\\n\t    [expr {[.c find overlapping 102 152 118 169] eq $zId}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1}\ntest canvRect-7.5 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find enclosed 20 40 38 80] eq {}}] \\\n\t    [expr {[.c find enclosed 20 40 39 80] eq {}}] \\\n\t    [expr {[.c find enclosed 20 40 70 80] eq $yId}] \\\n\t    [expr {[.c find enclosed 61 40 70 80] eq {}}] \\\n\t    [expr {[.c find enclosed 62 40 70 80] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1}\ntest canvRect-7.6 {RectToArea procedure} -body {\n\tset xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]\n\tset yId [.c create rectangle 40 45 60 70 -fill red -outline black -width 3]\n\tset zId [.c create rectangle 100 150 120 170 -fill {} -outline black -width 3]\n    list [expr {[.c find enclosed 20 20 65 43] eq {}}] \\\n\t    [expr {[.c find enclosed 20 20 65 44] eq {}}] \\\n\t    [expr {[.c find enclosed 20 20 65 80] eq $yId}] \\\n\t    [expr {[.c find enclosed 20 71 65 80] eq {}}] \\\n\t    [expr {[.c find enclosed 20 72 65 80] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1}\n\n\ntest canvRect-8.1 {OvalToArea procedure} -body {\n\tset xId  [.c create oval 50 100 200 150 -fill green -outline {}]\n\tset yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]\n\tset zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 20 120 48 130] eq {}}] \\\n\t    [expr {[.c find overlapping 20 120 49 130] eq \"$yId $zId\"}] \\\n\t    [expr {[.c find overlapping 20 120 50.2 130] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 20 120 300 130] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 60 120 190 130] eq \"$xId $yId\"}] \\\n\t    [expr {[.c find overlapping 199.9 120 300 130] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 201 120 300 130] eq \"$yId $zId\"}] \\\n\t    [expr {[.c find overlapping 202 120 300 130] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1 1 1 1}\ntest canvRect-8.2 {OvalToArea procedure} -body {\n\tset xId  [.c create oval 50 100 200 150 -fill green -outline {}]\n\tset yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]\n\tset zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 100 50 150 98] eq {}}] \\\n\t    [expr {[.c find overlapping 100 50 150 99] eq \"$yId $zId\"}] \\\n\t    [expr {[.c find overlapping 100 50 150 100.1] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 100 50 150 200] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 100 110 150 140] eq \"$xId $yId\"}] \\\n\t    [expr {[.c find overlapping 100 149.9 150 200] eq \"$xId $yId $zId\"}] \\\n\t    [expr {[.c find overlapping 100 151 150 200] eq \"$yId $zId\"}] \\\n\t    [expr {[.c find overlapping 100 152 150 200] eq {}}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1 1 1 1}\ntest canvRect-8.3 {OvalToArea procedure} -body {\n\tset xId  [.c create oval 50 100 200 150 -fill green -outline {}]\n\tset yId [.c create oval 50 100 200 150 -fill red -outline black -width 3]\n\tset zId [.c create oval 50 100 200 150 -fill {} -outline black -width 3]\n    list [expr {[.c find overlapping 176 104 177 105] eq {}}] \\\n\t    [expr {[.c find overlapping 187 116 188 117] eq \"$xId $yId\"}] \\\n\t    [expr {[.c find overlapping 192 142 193 143] eq {}}] \\\n\t    [expr {[.c find overlapping 180 138 181 139] eq \"$xId $yId\"}] \\\n\t    [expr {[.c find overlapping 61 142 62 143] eq {}}] \\\n\t    [expr {[.c find overlapping 65 137 66 136] eq \"$xId $yId\"}] \\\n\t    [expr {[.c find overlapping 62 108 63 109] eq {}}] \\\n\t    [expr {[.c find overlapping 68 115 69 116] eq \"$xId $yId\"}]\n} -cleanup {\n\t.c delete all\n} -result {1 1 1 1 1 1 1 1}\n\n\ntest canvRect-9.1 {ScaleRectOval procedure} -setup {\n    .c delete withtag all\n} -body {\n    .c create rect 100 300 200 350 -tags x\n    .c scale x 50 100 2 4\n    format {%.6g %.6g %.6g %.6g} {*}[.c coords x]\n} -result {150 900 350 1100}\n\ntest canvRect-10.1 {TranslateRectOval procedure} -setup {\n    .c delete withtag all\n} -body {\n    .c create rect 100 300 200 350 -tags x\n    .c move x 100 -10\n    format {%.6g %.6g %.6g %.6g} {*}[.c coords x]\n} -result {200 290 300 340}\n\n\ntest canvRect-11.1 {RectOvalToPostscript procedure} -constraints {\n    nonPortable\n} -setup {\n    .c delete withtag all\n} -body {\n    # This test is non-portable because different color information\n    # will get generated on different displays (e.g. mono displays\n    # vs. color).\n    .c configure -bd 0 -highlightthickness 0\n    .c create rect 50 60 90 80 -fill black -stipple gray50 -outline {}\n    .c create oval 100 150 200 200 -fill {} -outline #ff0000 -width 5\n    update\n    set x [.c postscript]\n    string range $x [string first \"-200 -150 translate\" $x] end\n} -result {-200 -150 translate\n0 300 moveto 400 300 lineto 400 0 lineto 0 0 lineto closepath clip newpath\ngsave\n50 240 moveto 40 0 rlineto 0 -20 rlineto -40 0 rlineto closepath\n0.000 0.000 0.000 setrgbcolor AdjustColor\nclip 16 16 <5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555aaaa5555\naaaa> StippleFill\ngrestore\ngsave\nmatrix currentmatrix\n150 125 translate 50 25 scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n5 setlinewidth 0 setlinejoin 2 setlinecap\n1.000 0.000 0.000 setrgbcolor AdjustColor\nstroke\ngrestore\nrestore showpage\n\n%%Trailer\nend\n%%EOF\n}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/canvText.test",
    "content": "# This file is a Tcl script to test out the procedures in tkCanvText.c,\n# which implement canvas \"text\" items.\n#\n# Copyright © 1996-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-1.* - 17.*\n#\ncanvas .c -width 400 -height 300 -bd 2 -relief sunken\npack .c\nupdate\n.c create text 20 20 -tag test\n\ntest canvText-1.1 {configuration options: good value for \"anchor\"} -body {\n    .c itemconfigure test -anchor nw\n    list [lindex [.c itemconfigure test -anchor] 4] [.c itemcget test -anchor]\n} -result {nw nw}\ntest canvasText-1.2 {configuration options: bad value for \"anchor\"} -body {\n    .c itemconfigure test -anchor xyz\n} -returnCodes error -result {bad anchor \"xyz\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest canvText-1.3 {configuration options: good value for \"fill\"} -body {\n    .c itemconfigure test -fill #ff0000\n    list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]\n} -result {{#ff0000} #ff0000}\ntest canvasText-1.4 {configuration options: bad value for \"fill\"} -body {\n    .c itemconfigure test -fill xyz\n} -returnCodes error -result {unknown color name \"xyz\"}\ntest canvText-1.5 {configuration options: good value for \"fill\"} -body {\n    .c itemconfigure test -fill {}\n    list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]\n} -result {{} {}}\ntest canvText-1.6 {configuration options: good value for \"font\"} -body {\n    .c itemconfigure test -font {Times 40}\n    list [lindex [.c itemconfigure test -font] 4] [.c itemcget test -font]\n} -result {{Times 40} {Times 40}}\ntest canvasText-1.7 {configuration options: bad value for \"font\"} -body {\n    .c itemconfigure test -font {}\n} -returnCodes error -result {font \"\" does not exist}\ntest canvText-1.8 {configuration options: good value for \"justify\"} -body {\n    .c itemconfigure test -justify left\n    list [lindex [.c itemconfigure test -justify] 4] [.c itemcget test -justify]\n} -result {left left}\ntest canvasText-1.9 {configuration options: bad value for \"justify\"} -body {\n    .c itemconfigure test -justify xyz\n} -returnCodes error -result {bad justification \"xyz\": must be left, right, or center}\ntest canvText-1.10 {configuration options: good value for \"stipple\"} -body {\n    .c itemconfigure test -stipple gray50\n    list [lindex [.c itemconfigure test -stipple] 4] [.c itemcget test -stipple]\n} -result {gray50 gray50}\ntest canvasText-1.11 {configuration options: bad value for \"stipple\"} -body {\n    .c itemconfigure test -stipple abcxyz\n} -returnCodes error -result {bitmap \"abcxyz\" not defined}\ntest canvText-1.12 {configuration options: good value for \"underline\"} -body {\n    .c itemconfigure test -underline 0\n    list [lindex [.c itemconfigure test -underline] 4] [.c itemcget test -underline]\n} -result {0 0}\ntest canvasText-1.13 {configuration options: bad value for \"underline\"} -body {\n    .c itemconfigure test -underline xyz\n} -returnCodes error -result {bad index \"xyz\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\ntest canvText-1.14 {configuration options: good value for \"width\"} -body {\n    .c itemconfigure test -width 6\n    list [lindex [.c itemconfigure test -width] 4] [.c itemcget test -width]\n} -result {6 6}\ntest canvasText-1.15 {configuration options: bad value for \"width\"} -body {\n    .c itemconfigure test -width xyz\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvText-1.16 {configuration options: good value for \"tags\"} -body {\n    .c itemconfigure test -tags {test a b c}\n    list [lindex [.c itemconfigure test -tags] 4] [.c itemcget test -tags]\n} -result {{test a b c} {test a b c}}\ntest canvasText-1.17 {configuration options: bad value for \"angle\"} -body {\n    .c itemconfigure test -angle xyz\n} -returnCodes error -result {expected floating-point number but got \"xyz\"}\ntest canvasText-1.18 {configuration options: good value for \"angle\"} -body {\n    .c itemconfigure test -angle 32.5\n    list [lindex [.c itemconfigure test -angle] 4] [.c itemcget test -angle]\n} -result {32.5 32.5}\ntest canvasText-1.19 {configuration options: bounding of \"angle\"} -body {\n    .c itemconfigure test -angle 390\n    set result [.c itemcget test -angle]\n    .c itemconfigure test -angle -30\n    lappend result [.c itemcget test -angle]\n    .c itemconfigure test -angle -360\n    lappend result [.c itemcget test -angle]\n} -result {30.0 330.0 0.0}\n\n#\n# COMMON TEST CLEANUP\n#\n.c delete test\n\ntest canvText-2.1 {CreateText procedure: args} -body {\n    .c create text\n} -returnCodes error -result {wrong # args: should be \".c create text coords ?arg ...?\"}\ntest canvText-2.2 {CreateText procedure: args} -body {\n    .c create text xyz 0\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvText-2.3 {CreateText procedure: args} -body {\n    .c create text 0 xyz\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvText-2.4 {CreateText procedure: args} -body {\n    .c create text 0 0 -xyz xyz\n} -cleanup {\n    .c delete all\n} -returnCodes error -result {unknown option \"-xyz\"}\ntest canvText-2.5 {CreateText procedure} -body {\n    .c create text 0 0 -tags x\n    .c coords x\n} -cleanup {\n    .c delete x\n} -result {0.0 0.0}\n\n\ntest canvText-3.1 {TextCoords procedure} -body {\n    .c create text 20 20 -tag test\n    .c coords test 0 0\n    update\n    .c coords test\n} -cleanup {\n    .c delete test\n} -result {0.0 0.0}\ntest canvText-3.2 {TextCoords procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c coords test xyz 0\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvText-3.3 {TextCoords procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c coords test 0 xyz\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvText-3.4 {TextCoords procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c coords test 10 10\n    set result {}\n    foreach element [.c coords test] {\n\tlappend result [format %.1f $element]\n    }\n    return $result\n} -cleanup {\n    .c delete test\n} -result {10.0 10.0}\ntest canvText-3.5 {TextCoords procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c coords test 10\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {wrong # coordinates: expected 2, got 1}\ntest canvText-3.6 {TextCoords procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c coords test 10 10 10\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {wrong # coordinates: expected 0 or 2, got 3}\n\n\ntest canvText-4.1 {ConfigureText procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c itemconfig test -fill xyz\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {unknown color name \"xyz\"}\ntest canvText-4.2 {ConfigureText procedure} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c itemconfig test -fill blue\n    .c itemcget test -fill\n} -cleanup {\n    .c delete test\n} -result {blue}\ntest canvText-4.3 {ConfigureText procedure: construct font gcs} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c itemconfig test -font \"times 20\" -fill black -stipple gray50\n    list [.c itemcget test -font] [.c itemcget test -fill] [.c itemcget test -stipple]\n} -cleanup {\n    .c delete test\n} -result {{times 20} black gray50}\ntest canvText-4.4 {ConfigureText procedure: construct cursor gc} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c icursor test 3\n    # Both black -> cursor becomes white.\n    .c config -insertbackground black\n    .c config -selectbackground black\n    .c itemconfig test -just left\n    update\n    # Both same color (and not black) -> cursor becomes black.\n    .c config -insertbackground red\n    .c config -selectbackground red\n    .c itemconfig test -just left\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-4.5 {ConfigureText procedure: adjust selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n    set x {}\n} -body {\n    .c itemconfig test -text \"abcdefghi\"\n    .c select from test 2\n    .c select to test 6\n    lappend x [selection get]\n    .c dchars test 1 end\n    lappend x [catch {selection get}]\n    .c insert test end \"bcdefghi\"\n    .c select from test 2\n    .c select to test 6\n    lappend x [selection get]\n    .c dchars test 4 end\n    lappend x [selection get]\n    .c insert test end \"efghi\"\n    .c select from test 6\n    .c select to test 2\n    lappend x [selection get]\n    .c dchars test 4 end\n    lappend x [selection get]\n} -cleanup {\n    .c delete test\n} -result {cdefg 1 cdefg cd cdef cd}\ntest canvText-4.6 {ConfigureText procedure: adjust cursor} -setup {\n    .c create text 20 20 -tag test\n} -body {\n    .c itemconfig test -text \"abcdefghi\"\n    .c icursor test 6\n    .c dchars test 4 end\n    .c index test insert\n} -cleanup {\n\t.c delete test\n} -result 4\n\n\ntest canvText-5.1 {ConfigureText procedure: adjust cursor} -body {\n    .c create text 10 10 -tag x -fill blue -font \"times 40\" -stipple gray50 \\\n\t-text \"xyz\"\n    .c delete x\n} -result {}\n\n\ntest canvText-6.1 {ComputeTextBbox procedure} -constraints {fonts failsOnXQuartz} -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor n; .c bbox test] \\\n\t      eq \"[expr {-$ax/2-1}] 0 [expr {$ax/2+1}] $ay\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.2 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor nw; .c bbox test] \\\n\t      eq \"-1 0 [expr {$ax+1}] $ay\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.3 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor w; .c bbox test] \\\n\t      eq \"-1 [expr {-$ay/2}] [expr {$ax+1}] [expr {$ay/2}]\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.4 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor sw; .c bbox test] \\\n\t      eq \"-1 -$ay [expr {$ax+1}] 0\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.5 {ComputeTextBbox procedure} -constraints {fonts failsOnXQuartz} -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor s; .c bbox test] \\\n\t      eq \"[expr {-$ax/2-1}] -$ay [expr {$ax/2+1}] 0\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.6 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor se; .c bbox test] \\\n\t      eq \"[expr {-$ax-1}] -$ay 1 0\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.7 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor e; .c bbox test]\\\n\t      eq \"[expr {-$ax-1}] [expr {-$ay/2}] 1 [expr {$ay/2}]\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.8 {ComputeTextBbox procedure} -constraints fonts -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor ne; .c bbox test] \\\n\t      eq \"[expr {-$ax-1}] 0 1 $ay\"}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-6.9 {ComputeTextBbox procedure} -constraints {fonts failsOnXQuartz} -setup {\n    .c delete test\n} -body {\n    set font \"-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*\"\n    set ay [font metrics $font -linespace]\n    set ax [font measure $font 0]\n    .c create text 0 0 -tag test\n    .c itemconfig test -font $font -text 0\n    expr {[.c itemconfig test -anchor center; .c bbox test] \\\n\t      eq \"[expr {-$ax/2-1}] [expr {-$ay/2}] [expr {$ax/2+1}] [expr {$ay/2}]\"}\n} -cleanup {\n    .c delete test\n} -result 1\n\n#\n# COMMON TEST SETUP\n#\nfocus .c\n.c focus test\n.c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n\ntest canvText-7.1 {DisplayText procedure: stippling} -body {\n    .c create text 20 20 -tag test\n    .c itemconfig test -stipple gray50\n    update\n    .c itemconfig test -stipple {}\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.2 {DisplayText procedure: draw selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    .c select from test 0\n    .c select to test end\n    update\n    selection get\n} -cleanup {\n    .c delete test\n} -result \"abcd\\nefghi\\njklmnopq\"\ntest canvText-7.3 {DisplayText procedure: selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    .c select from test 0\n    .c select to test end\n    update\n    selection get\n} -cleanup {\n    .c delete test\n} -result \"abcd\\nefghi\\njklmnopq\"\ntest canvText-7.4 {DisplayText procedure: one line selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    .c select from test 2\n    .c select to test 3\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.5 {DisplayText procedure: multi-line selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    .c select from test 2\n    .c select to test 12\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.6 {DisplayText procedure: draw cursor} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    .c icursor test 3\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.7 {DisplayText procedure: selected text different color} -setup {\n    .c create text 20 20 -tag test\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    focus .c\n    .c focus test\n} -body {\n    .c config -selectforeground blue\n    .c itemconfig test -anchor n\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.8 {DisplayText procedure: not selected} -setup {\n    .c create text 20 20 -tag test\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    focus .c\n    .c focus test\n} -body {\n    .c select clear\n    update\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-7.9 {DisplayText procedure: select end} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t +0+0\n    canvas .t.c\n    pack .t.c\n    set id [.t.c create text 0 0 -text Dummy -anchor nw]\n    update\n    .t.c select from $id 0\n    .t.c select to $id end\n    update\n    #catch {destroy .t}\n    update\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest canvText-8.1 {TextInsert procedure: 0 length insert} -setup {\n    .c create text 20 20 -tag test\n    .c itemconfig test -text \"abcd\\nefghi\\njklmnopq\"\n    focus .c\n    .c focus test\n} -body {\n    .c insert test end {}\n} -cleanup {\n    .c delete test\n} -result {}\ntest canvText-8.2 {TextInsert procedure: before beginning/after end} -body {\n    # Can't test this because GetTextIndex filters out those numbers.\n} -result {}\ntest canvText-8.3 {TextInsert procedure: inserting in a selected item} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c insert test 1 \"xyz\"\n    .c itemcget test -text\n} -result {axyzbcdefg}\ntest canvText-8.4 {TextInsert procedure: inserting before selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c insert test 1 \"xyz\"\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {5 7}\ntest canvText-8.5 {TextInsert procedure: inserting in selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c insert test 3 \"xyz\"\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {2 7}\ntest canvText-8.6 {TextInsert procedure: inserting after selection} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c insert test 5 \"xyz\"\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {2 4}\ntest canvText-8.7 {TextInsert procedure: inserting in unselected item} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select clear\n    .c insert test 5 \"xyz\"\n    .c itemcget test -text\n} -result {abcdexyzfg}\ntest canvText-8.8 {TextInsert procedure: inserting before cursor} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c icursor test 3\n    .c insert test 2 \"xyz\"\n    .c index test insert\n} -result 6\ntest canvText-8.9 {TextInsert procedure: inserting after cursor} -setup {\n    .c create text 20 20 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c icursor test 3\n    .c insert test 4 \"xyz\"\n    .c index test insert\n} -result 3\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvasText-9.*\n#\n.c create text 20 20 -tag test\n\ntest canvText-9.1 {TextInsert procedure: before beginning/after end} -body {\n    # Can't test this because GetTextIndex filters out those numbers.\n} -result {}\ntest canvText-9.2 {TextInsert procedure: start > end} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c dchars test 4 2\n    .c itemcget test -text\n} -result {abcdefg}\ntest canvText-9.3 {TextInsert procedure: deleting from a selected item} -body {\n    .c itemconfig test -text \"abcdefg\"\n    .c select from test 2\n    .c select to test 4\n    .c dchars test 3 5\n    .c itemcget test -text\n} -result {abcg}\ntest canvText-9.4 {TextInsert procedure: deleting before start} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 1 1\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {3 7}\ntest canvText-9.5 {TextInsert procedure: keep start > first char deleted} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 2 6\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {2 3}\ntest canvText-9.6 {TextInsert procedure: deleting inside selection} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 6 6\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {4 7}\ntest canvText-9.7 {TextInsert procedure: keep end > first char deleted} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 6 10\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {4 5}\ntest canvText-9.8 {TextInsert procedure: selectFirst > selectLast: deselect} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 3 10\n    .c index test sel.first\n} -returnCodes error -result {selection isn't in item}\ntest canvText-9.9 {TextInsert procedure: selectFirst <= selectLast} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 4\n    .c select to test 8\n    .c dchars test 4 7\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {4 4}\ntest canvText-9.10 {TextInsert procedure: move anchor} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 6\n    .c select to test 8\n    .c dchars test 2 4\n    .c select to test 1\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {1 2}\ntest canvText-9.11 {TextInsert procedure: keep anchor >= first} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 6\n    .c select to test 8\n    .c dchars test 5 7\n    .c select to test 1\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {1 4}\ntest canvText-9.12 {TextInsert procedure: anchor doesn't move} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c select from test 2\n    .c select to test 5\n    .c dchars test 6 8\n    .c select to test 8\n    list [.c index test sel.first] [.c index test sel.last]\n} -result {2 8}\ntest canvText-9.13 {TextInsert procedure: move cursor} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c icursor test 6\n    .c dchars test 2 4\n    .c index test insert\n} -result 3\ntest canvText-9.14 {TextInsert procedure: keep cursor >= first} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c icursor test 6\n    .c dchars test 2 10\n    .c index test insert\n} -result 2\ntest canvText-9.15 {TextInsert procedure: cursor doesn't move} -body {\n    .c itemconfig test -text \"abcdefghijk\"\n    .c icursor test 5\n    .c dchars test 7 9\n    .c index test insert\n} -result 5\n\n#\n# COMMON TEST CLEANUP\n#\n.c delete test\n\ntest canvText-10.1 {TextToPoint procedure} -body {\n    .c create text 0 0 -tag test\n    .c itemconfig test -text 0 -anchor center\n    .c index test @0,0\n} -cleanup {\n\t.c delete test\n} -result 0\n\n\ntest canvText-11.1 {TextToArea procedure} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text 0 -anchor center\n    set res1 [.c find overlapping 0 0 1 1]\n    set res2 [.c find withtag test]\n    expr {$res1 eq $res2}\n} -cleanup {\n    .c delete test\n} -result 1\ntest canvText-11.2 {TextToArea procedure} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text 0 -anchor center\n    .c find overlapping 1000 1000 1001 1001\n} -cleanup {\n\t.c delete test\n} -result {}\n\n\ntest canvText-12.1 {ScaleText procedure} -body {\n    .c create text 100 100 -tag test\n    .c scale all 50 50 2 2\n    format {%.6g %.6g} {*}[.c coords test]\n} -cleanup {\n\t.c delete test\n} -result {150 150}\n\n\ntest canvText-13.1 {TranslateText procedure} -body {\n\t.c create text 100 100 -tag test\n    .c move all 10 10\n    format {%.6g %.6g} {*}[.c coords test]\n} -cleanup {\n\t.c delete test\n} -result {110 110}\n\n\ntest canvText-14.1 {GetTextIndex procedure} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefghijklmno\" -anchor nw\n    .c select from test 5\n    .c select to test 8\n    .c icursor test 12\n    .c coords test 0 0\n    list [.c index test end] [.c index test insert] \\\n\t[.c index test sel.first] [.c index test sel.last] \\\n\t[.c index test @0,0] \\\n\t[.c index test {}] [.c index test 10] [.c index test 100]\n} -cleanup {\n    .c delete test\n} -result {15 12 5 8 0 0 10 15}\ntest canvText-14.2 {GetTextIndex procedure: select error} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c select clear\n    .c index test sel.first\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {selection isn't in item}\ntest canvText-14.3 {GetTextIndex procedure: select error} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c select clear\n    .c index test sel.last\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {selection isn't in item}\ntest canvText-14.4 {GetTextIndex procedure: select error} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c select clear\n    .c index test sel.\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {bad index \"sel.\"}\ntest canvText-14.5 {GetTextIndex procedure: bad int or unknown index} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c index test xyz\n} -cleanup {\n    .c delete test\n} -returnCodes error -result {bad index \"xyz\"}\ntest canvText-14.6 {select clear errors} -setup {\n    .c create text 0 0 -tag test\n} -body {\n    .c select clear test\n} -cleanup {\n    .c delete test\n} -returnCodes error -result \"wrong \\# args: should be \\\".c select clear\\\"\"\ntest canvText-14.7 {GetTextIndex procedure: pixel index with non-default scrollregion} -setup {\n    canvas .cc\n    .cc create text 50 80 -tag test -text Hello -anchor nw -font \"Arial 30\"\n    foreach {xmin ymin xmax ymax} [.cc bbox test] {}\n} -body {\n    # default -scrollregion\n    set res [.cc index test @$xmin,$ymin]\n    lappend res [.cc index test @$xmax,$ymax]\n    # -scrollregion with positive upper left corner\n    .cc configure -scrollregion {50 50 700 900}\n    lappend res [.cc index test @$xmin,$ymin]\n    lappend res [.cc index test @$xmax,$ymax]\n    # -scrollregion with negative upper left corner\n    .cc configure -scrollregion {-100 -100 700 900}\n    lappend res [.cc index test @$xmin,$ymin]\n    lappend res [.cc index test @$xmax,$ymax]\n} -cleanup {\n    destroy .cc\n} -result {0 5 0 5 0 5}\n\ntest canvText-15.1 {SetTextCursor procedure} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefghijklmno\" -anchor nw\n    .c itemconfig -text \"abcdefg\"\n    .c icursor test 3\n    .c index test insert\n} -cleanup {\n    .c delete test\n} -result 3\n\ntest canvText-16.1 {GetSelText procedure} -setup {\n    .c create text 0 0 -tag test\n    focus .c\n    .c focus test\n} -body {\n    .c itemconfig test -text \"abcdefghijklmno\" -anchor nw\n    .c select from test 5\n    .c select to test 8\n    selection get\n} -cleanup {\n    .c delete test\n} -result {fghi}\n\ntest canvText-17.1 {TextToPostscript procedure} -setup {\n    .c delete all\n    set result {findfont [font actual $font -size] scalefont ISOEncode setfont\n0.000 0.000 0.000 setrgbcolor AdjustColor\n0 100 200 \\[\n\\[(000)\\]\n\\[(000)\\]\n\\[(00)\\]\n\\] $ay -0.5 0 0 false DrawText\ngrestore\nrestore showpage\n\n%%Trailer\nend\n%%EOF\n}\n} -body {\n    set font {Courier 12 italic}\n    set ax [font measure $font 0]\n    set ay [font metrics $font -linespace]\n    .c config -height 300 -highlightthickness 0 -bd 0\n    update\n    .c create text 100 100 -tags test\n    .c itemconfig test -font $font -text \"00000000\" -width [expr {3*$ax}]\n    .c itemconfig test -anchor n -fill black\n    set x [.c postscript]\n    set x [string range $x [string first \"findfont \" $x] end]\n    expr {$x eq [subst $result] ? \"ok\" : $x}\n} -result ok\n\ntest canvText-18.1 {bug fix 2525, find enclosed on text with newlines} -setup {\n    destroy .c\n} -body {\n    pack [canvas .c]\n    .c create text 100 100 -text Hello\\n -anchor nw\n    set bbox [.c bbox 1]\n    set x2 [lindex $bbox 2]\n    set y2 [lindex $bbox 3]\n    incr y2\n    update\n    .c find enclosed 99 99 [expr {$x2 + 1}] [expr {$y2 + 1}]\n} -cleanup {\n    destroy .c\n    unset -nocomplain bbox x2 y2\n} -result 1\n\ntest canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -constraints !withXft -setup {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    destroy .c\n    set c [canvas .c -bg black -width 964]\n    pack $c\n    $c delete all\n    after 100 \"set done 1\"; vwait done\n} -body {\n    set f {Arial 28 bold}\n    set s1 {    Yeah-ah-ah-ah-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-Yow}\n    set s2 {    Yeah ah ah ah oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh Yow}\n    $c create text 21 18 \\\n\t-font $f \\\n\t-text $s1 \\\n\t-fill white \\\n\t-width 922 \\\n\t-anchor nw \\\n\t-tags tbox1\n    $c create rect {*}[$c bbox tbox1] -outline red\n    $c create text 21 160 \\\n\t-font $f \\\n\t-text $s2 \\\n\t-fill white \\\n\t-width 922 \\\n\t-anchor nw \\\n\t-tags tbox2\n    $c create rect {*}[$c bbox tbox2] -outline red\n    after 500 \"set done 1\" ; vwait done\n    set results [list]\n    $c select from tbox2 4\n    $c select to tbox2 8\n    lappend results [selection get]\n    $c select from tbox1 4\n    $c select to tbox1 8\n    lappend results [selection get]\n    array set metrics [font metrics $f]\n    set x [expr {21 + [font measure $f \"    \"] \\\n\t+ ([font measure {Arial 28 bold} \"Y\"] / 2)}]\n    set y1 [expr {18 + ($metrics(-linespace) / 2)}]\n    set y2 [expr {160 + ($metrics(-linespace) / 2)}]\n    lappend results [$c index tbox1 @$x,$y1]\n    lappend results [$c index tbox2 @$x,$y2]\n} -cleanup {\n    destroy .c\n} -result {{Yeah } Yeah- 4 4}\n\ntest canvText-20.1 {angled text bounding box} -setup {\n    destroy .c\n    canvas .c\n    proc transpose {bbox} {\n\tlassign $bbox a b c d\n\tlist $b $a $d $c\n    }\n    proc almosteq {b1 b2} {\n\t# check whether the two boxes are equal, with 1 unit tolerance on each x y w h\n\tlassign $b1 a b c d\n\tlassign $b2 e f g h\n\texpr {($e-$a)<=1 && ($f-$b)<=1 && ($g-$c)<=1 && ($h-$d)<=1}\n    }\n} -body {\n    .c create text 2 2 -tag t -anchor center -text 0 -font {TkDefaultFont 24}\n    set bb0 [.c bbox t]\n    .c itemconf t -angle 90\n    set bb1 [.c bbox t]\n    .c itemconf t -angle 180\n    set bb2 [.c bbox t]\n    .c itemconf t -angle 270\n    set bb3 [.c bbox t]\n    # bboxes should be the same, possibly with a small (platform-specific) rounding difference\n    list [expr {[almosteq $bb0 $bb2] ? \"ok\" : \"$bb0,$bb2\"}] \\\n\t[expr {[almosteq $bb1 $bb3] ? \"ok\" : \"$bb1,$bb3\"}] \\\n\t[expr {[almosteq $bb0 [transpose $bb1]] ? \"ok\" : \"$bb0,$bb1\"}]\n} -cleanup {\n    destroy .c\n    rename transpose {}\n} -result {ok ok ok}\n\ntest canvText-20.2 {crash on angled text selection (X11, without xft) - bug 2712f43f6e} -setup {\n    destroy .c\n    canvas .c -background bisque -selectforeground green2\n    grid .c\n    set id [.c create text 50 150 -anchor w -text \"Angled text\" \\\n\t    -angle 30 -font {Helvetica 32} -fill darkblue]\n} -body {\n    .c select clear\n    .c select from $id 0\n    .c select to $id 8 ; update    ;  # used to crash on X11 (--disable-xft build only)\n} -cleanup {\n    destroy .c\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/canvWind.test",
    "content": "# This file is a Tcl script to test out the procedures in tkCanvWind.c,\n# which implement canvas \"window\" items.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest canvWind-1.1 {DisplayWinItem, windows off-screen vertically} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \\\n\t    -relief sunken -xscrollincrement 1 -yscrollincrement 1 \\\n\t    -highlightthickness 1\n    pack .t.c -fill both -expand 1 -padx 20 -pady 20\n    wm geometry .t +0+0\n    set f .t.f\n    frame $f -width 80 -height 50 -bg red\n    .t.c create window 300 400 -window $f -anchor nw\n    .t.c xview moveto .3\n    .t.c yview moveto .50\n    update\n    set x [list [list [winfo ismapped $f] [winfo y $f]]]\n    .t.c yview scroll 52 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll 1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll -255 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll -1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n} -cleanup {\n    destroy .t\n} -result {{1 23} {1 -29} {0 -29} {1 225} {0 225}}\n\ntest canvWind-1.2 {DisplayWinItem, windows off-screen vertically} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \\\n\t    -relief sunken -xscrollincrement 1 -yscrollincrement 1 \\\n\t    -highlightthickness 1\n    pack .t.c -fill both -expand 1 -padx 20 -pady 20\n    wm geometry .t +0+0\n    set f .t.c.f\n    frame $f -width 80 -height 50 -bg red\n    .t.c create window 300 400 -window $f -anchor nw\n    .t.c xview moveto .3\n    .t.c yview moveto .50\n    update\n    set x [list [list [winfo ismapped $f] [winfo y $f]]]\n    .t.c yview scroll 52 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll 1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll -255 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n    .t.c yview scroll -1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo y $f]]\n} -cleanup {\n    destroy .t\n} -result {{1 3} {1 -49} {0 -49} {1 205} {0 205}}\n\ntest canvWind-1.3 {DisplayWinItem, windows off-screen horizontally} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \\\n\t    -relief sunken -xscrollincrement 1 -yscrollincrement 1 \\\n\t    -highlightthickness 1\n    pack .t.c -fill both -expand 1 -padx 20 -pady 20\n    wm geometry .t +0+0\n    set f .t.f\n    frame $f -width 80 -height 50 -bg red\n    .t.c create window 300 400 -window $f -anchor nw\n    .t.c xview moveto .3\n    .t.c yview moveto .50\n    update\n    set x [list [list [winfo ismapped $f] [winfo x $f]]]\n    .t.c xview scroll 82 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll 1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll -335 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll -1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n} -cleanup {\n    destroy .t\n} -result {{1 23} {1 -59} {0 -59} {1 275} {0 275}}\n\ntest canvWind-1.4 {DisplayWinItem, windows off-screen horizontally} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    canvas .t.c -scrollregion {0 0 1000 800} -width 250 -height 200 -bd 2 \\\n\t    -relief sunken -xscrollincrement 1 -yscrollincrement 1 \\\n\t    -highlightthickness 1\n    pack .t.c -fill both -expand 1 -padx 20 -pady 20\n    wm geometry .t +0+0\n    set f .t.c.f\n    frame $f -width 80 -height 50 -bg red\n    .t.c create window 300 400 -window $f -anchor nw\n    .t.c xview moveto .3\n    .t.c yview moveto .50\n    update\n    set x [list [list [winfo ismapped $f] [winfo x $f]]]\n    .t.c xview scroll 82 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll 1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll -335 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n    .t.c xview scroll -1 units\n    update\n    lappend x [list [winfo ismapped $f] [winfo x $f]]\n} -cleanup {\n    destroy .t\n} -result {{1 3} {1 -79} {0 -79} {1 255} {0 255}}\n\ntest canvWind-2.1 {DisplayWinItem, window gets destroyed during <Configure>} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    canvas .t.c\n    pack .t.c\n    frame .t.c.f -width 50 -height 50 -background red\n    set id [.t.c create window 50 50 -window .t.c.f]\n    update\n    bind .t.c.f <Configure> {destroy .t.c.f}\n    .t.c coords $id 60 60 ;  # was crashing\n    update\n} -cleanup {\n    destroy .t\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/canvas.test",
    "content": "# This file is a Tcl script to test out the procedures in tkCanvas.c, which\n# implements generic code for canvases.\n#\n# Copyright © 1995-1996 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Ajuba Solutions.\n# Copyright © 2008 Donal K. Fellows\n# All rights reserved.\n\n# NOTE\n#\n# This test file is woefully incomplete. At present, only a few of the\n# features are tested.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc kill_canvas {w} {\n    destroy $w\n    pack [canvas $w -height 200 -width 200] -fill both -expand yes\n    update idle\n    $w create rectangle 80 80 120 120 -fill blue -tags blue\n    # bind a button press to re-build the canvas\n    $w bind blue <ButtonRelease-1> [subst {\n\t[lindex [info level 0] 0] $w\n\tappend ::x ok\n    }]\n}\n\nproc matchPixels {pixels expected} {\n    set matched 1\n    foreach pline $pixels eline $expected {\n\tforeach ppixel $pline epixel $eline {\n\t    if {$ppixel != $epixel} {\n\t\tset matched 0\n\t\tbreak\n\t    }\n\t}\n    }\n    return $matched\n}\n\n#\n# TESTS\n#\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-1.*\n#\ncanvas .c\npack .c\nupdate\n\ntest canvas-1.1 {configuration options: good value for \"background\"} -body {\n    .c configure -background #ff0000\n    .c cget -background\n} -result {#ff0000}\ntest canvas-1.2 {configuration options: bad value for \"background\"} -body {\n    .c configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest canvas-1.3 {configuration options: good value for \"bg\"} -body {\n    .c configure -bg #ff0000\n    .c cget -bg\n} -result {#ff0000}\ntest canvas-1.4 {configuration options: bad value for \"bg\"} -body {\n    .c configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest canvas-1.5 {configuration options: good value for \"bd\"} -body {\n    .c configure -bd 4\n    .c cget -bd\n} -result 4\ntest canvas-1.6 {configuration options: bad value for \"bd\"} -body {\n    .c configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest canvas-1.7 {configuration options: good value for \"borderwidth\"} -body {\n    .c configure -borderwidth 1.3\n    .c cget -borderwidth\n} -result 1.3\ntest canvas-1.8 {configuration options: bad value for \"borderwidth\"} -body {\n    .c configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest canvas-1.9 {configuration options: good value for \"closeenough\"} -body {\n    .c configure -closeenough 24\n    .c cget -closeenough\n} -result {24.0}\ntest canvas-1.10 {configuration options: bad value for \"closeenough\"} -body {\n    .c configure -closeenough bogus\n} -returnCodes error -result {expected floating-point number but got \"bogus\"}\ntest canvas-1.11 {configuration options: good value for \"confine\"} -body {\n    .c configure -confine true\n    .c cget -confine\n} -result 1\ntest canvas-1.12 {configuration options: bad value for \"confine\"} -body {\n    .c configure -confine silly\n} -returnCodes error -result {expected boolean value but got \"silly\"}\ntest canvas-1.13 {configuration options: good value for \"cursor\"} -body {\n    .c configure -cursor arrow\n    .c cget -cursor\n} -result {arrow}\ntest canvas-1.14 {configuration options: bad value for \"cursor\"} -body {\n    .c configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest canvas-1.15 {configuration options: good value for \"height\"} -body {\n    .c configure -height 2.1\n    .c cget -height\n} -result 2.1\ntest canvas-1.16 {configuration options: bad value for \"height\"} -body {\n    .c configure -height x42\n} -returnCodes error -result {expected screen distance but got \"x42\"}\ntest canvas-1.17 {configuration options: good value for \"highlightbackground\"} -body {\n    .c configure -highlightbackground #112233\n    .c cget -highlightbackground\n} -result {#112233}\ntest canvas-1.18 {configuration options: bad value for \"highlightbackground\"} -body {\n    .c configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest canvas-1.19 {configuration options: good value for \"highlightcolor\"} -body {\n    .c configure -highlightcolor #110022\n    .c cget -highlightcolor\n} -result {#110022}\ntest canvas-1.20 {configuration options: bad value for \"highlightcolor\"} -body {\n    .c configure -highlightcolor bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest canvas-1.21 {configuration options: good value for \"highlightthickness\"} -body {\n    .c configure -highlightthickness 18\n    .c cget -highlightthickness\n} -result 18\ntest canvas-1.22 {configuration options: bad value for \"highlightthickness\"} -body {\n    .c configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest canvas-1.23 {configuration options: good value for \"insertbackground\"} -body {\n    .c configure -insertbackground #110022\n    .c cget -insertbackground\n} -result {#110022}\ntest canvas-1.24 {configuration options: bad value for \"insertbackground\"} -body {\n    .c configure -insertbackground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest canvas-1.25 {configuration options: good value for \"insertborderwidth\"} -body {\n    .c configure -insertborderwidth 1.3\n    .c cget -insertborderwidth\n} -result 1.3\ntest canvas-1.26 {configuration options: bad value for \"insertborderwidth\"} -body {\n    .c configure -insertborderwidth 2.6x\n} -returnCodes error -result {expected screen distance but got \"2.6x\"}\ntest canvas-1.27 {configuration options: good value for \"insertofftime\"} -body {\n    .c configure -insertofftime 100\n    .c cget -insertofftime\n} -result 100\ntest canvas-1.28 {configuration options: bad value for \"insertofftime\"} -body {\n    .c configure -insertofftime 3.2\n} -returnCodes error -result {expected integer but got \"3.2\"}\ntest canvas-1.29 {configuration options: good value for \"insertontime\"} -body {\n    .c configure -insertontime 100\n    .c cget -insertontime\n} -result 100\ntest canvas-1.30 {configuration options: bad value for \"insertontime\"} -body {\n    .c configure -insertontime 3.2\n} -returnCodes error -result {expected integer but got \"3.2\"}\ntest canvas-1.31 {configuration options: good value for \"insertwidth\"} -body {\n    .c configure -insertwidth 1.3\n    .c cget -insertwidth\n} -result 1.3\ntest canvas-1.32 {configuration options: bad value for \"insertwidth\"} -body {\n    .c configure -insertwidth 6x\n} -returnCodes error -result {expected screen distance but got \"6x\"}\ntest canvas-1.33 {configuration options: good value for \"relief\"} -body {\n    .c configure -relief g\n    .c cget -relief\n} -result {groove}\ntest canvas-1.34 {configuration options: bad value for \"relief\"} -body {\n    .c configure -relief r\n} -returnCodes error -result {ambiguous relief \"r\": must be flat, groove, raised, ridge, solid, or sunken}\ntest canvas-1.35 {configuration options: good value for \"selectbackground\"} -body {\n    .c configure -selectbackground #110022\n    .c cget -selectbackground\n} -result {#110022}\ntest canvas-1.36 {configuration options: bad value for \"selectbackground\"} -body {\n    .c configure -selectbackground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest canvas-1.37 {configuration options: good value for \"selectborderwidth\"} -body {\n    .c configure -selectborderwidth 1.3\n    .c cget -selectborderwidth\n} -result 1.3\ntest canvas-1.38 {configuration options: bad value for \"selectborderwidth\"} -body {\n    .c configure -selectborderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest canvas-1.39 {configuration options: good value for \"selectforeground\"} -body {\n    .c configure -selectforeground #654321\n    .c cget -selectforeground\n} -result {#654321}\ntest canvas-1.40 {configuration options: bad value for \"selectforeground\"} -body {\n    .c configure -selectforeground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest canvas-1.41 {configuration options: good value for \"takefocus\"} -body {\n    .c configure -takefocus \"any string\"\n    .c cget -takefocus\n} -result {any string}\ntest canvas-1.42 {configuration options: good value for \"width\"} -body {\n    .c configure -width 402\n    .c cget -width\n} -result 402\ntest canvas-1.43 {configuration options: bad value for \"width\"} -body {\n    .c configure -width xyz\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest canvas-1.44 {configuration options: good value for \"xscrollcommand\"} -body {\n    .c configure -xscrollcommand {Some command}\n    .c cget -xscrollcommand\n} -result {Some command}\ntest canvas-1.45 {configuration options: good value for \"yscrollcommand\"} -body {\n    .c configure -yscrollcommand {Another command}\n    .c cget -yscrollcommand\n} -result {Another command}\ntest canvas-1.46 {configure throws error on bad option} -body {\n    .c configure -gorp foo\n} -returnCodes error -match glob -result {*}\ntest canvas-1.47 {configure throws error on bad option} -body {\n    catch {.c configure -gorp foo}\n    .c create rect 10 10 100 100\n    .c configure -gorp foo\n} -returnCodes error -match glob -result {*}\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-2.*\n#\ndestroy .c\ncanvas .c -width 60 -height 40 -scrollregion {0 0 200 150} -bd 0 \\\n\t-highlightthickness 0\npack .c\nupdate\n\ntest canvas-2.1 {CanvasWidgetCmd, bind option} -body {\n    set i [.c create rect 10 10 100 100]\n    .c bind $i <a>\n} -cleanup {\n    .c delete $i\n} -returnCodes ok\ntest canvas-2.2 {CanvasWidgetCmd, bind option} -body {\n    set i [.c create rect 10 10 100 100]\n    .c bind $i <\n} -cleanup {\n    .c delete $i\n} -returnCodes error -result {no event type or button # or keysym}\ntest canvas-2.3 {CanvasWidgetCmd, xview option} -body {\n    .c configure -xscrollincrement 40 -yscrollincrement 5\n    .c xview moveto 0\n    update\n    set x [list [.c xview]]\n    .c xview scroll 2 units\n    update\n    lappend x [.c xview]\n} -result {{0.0 0.3} {0.4 0.7}}\ntest canvas-2.4 {CanvasWidgetCmd, xview option} -body {\n    .c configure -xscrollincrement 0 -yscrollincrement 5\n    .c xview moveto 0.6\n    update\n    set x [list [.c xview]]\n    .c xview scroll 2 units\n    update\n    lappend x [.c xview]\n} -result {{0.6 0.9} {0.66 0.96}}\ntest canvas-2.5 {CanvasWidgetCmd, raise/lower option, no error on non-existing tags} -setup {\n    .c create line 0 0 10 10 -tags aline\n} -body {\n    .c raise aline noline\n    .c raise bline aline\n    .c lower aline noline\n    .c lower bline aline\n} -cleanup {\n    .c delete aline\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-3.*\n#\ncatch {destroy .c}\ncanvas .c -width 60 -height 40 -scrollregion {0 0 200 80} \\\n\t-borderwidth 0 -highlightthickness 0\npack .c\nupdate\n\ntest canvas-3.1 {CanvasWidgetCmd, yview option} -body {\n    .c configure -xscrollincrement 40 -yscrollincrement 5\n    .c yview moveto 0\n    update\n    set x [list [.c yview]]\n    .c yview scroll 3 units\n    update\n    lappend x [.c yview]\n} -result {{0.0 0.5} {0.1875 0.6875}}\ntest canvas-3.2 {CanvasWidgetCmd, yview option} -body {\n    .c configure -xscrollincrement 40 -yscrollincrement 0\n    .c yview moveto 0\n    update\n    set x [list [.c yview]]\n    .c yview scroll 2 units\n    update\n    lappend x [.c yview]\n} -result {{0.0 0.5} {0.1 0.6}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .c\n\ntest canvas-4.1 {ButtonEventProc procedure} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    canvas .c1 -bg #543210\n    rename .c1 .c2\n    lappend x [winfo children .]\n    lappend x [.c2 cget -bg]\n    destroy .c1\n    lappend x [info command .c*] [winfo children .]\n} -result {.c1 #543210 {} {}}\n\ntest canvas-5.1 {ButtonCmdDeletedProc procedure} -body {\n    canvas .c1\n    rename .c1 {}\n    list [info command .c*] [winfo children .]\n} -cleanup {\n    destroy .c1\n} -result {{} {}}\n\n#\n# COMMON TEST SETUP\n#\n# For tests canvas-6.*\n#\ncanvas .c -width 100 -height 50 -scrollregion {-200 -100 305 102} \\\n\t-borderwidth 2 -highlightthickness 3\npack .c\nupdate\n\ntest canvas-6.1 {CanvasSetOrigin procedure} -body {\n    .c configure -xscrollincrement 0 -yscrollincrement 0\n    .c xview moveto 0\n    .c yview moveto 0\n    update\n    list [.c canvasx 0] [.c canvasy 0]\n} -result {-205.0 -105.0}\ntest canvas-6.2 {CanvasSetOrigin procedure} -body {\n    .c configure -xscrollincrement 20 -yscrollincrement 10\n    set x \"\"\n    foreach i {.08 .10 .48 .50} {\n\t.c xview moveto $i\n\tupdate\n\tlappend x [.c canvasx 0]\n    }\n    return $x\n} -result {-165.0 -145.0 35.0 55.0}\ntest canvas-6.3 {CanvasSetOrigin procedure} -body {\n    .c configure -xscrollincrement 20 -yscrollincrement 10\n    set x \"\"\n    foreach i {.06 .08 .70 .72} {\n\t.c yview moveto $i\n\tupdate\n\tlappend x [.c canvasy 0]\n    }\n    return $x\n} -result {-95.0 -85.0 35.0 45.0}\ntest canvas-6.4 {CanvasSetOrigin procedure} -body {\n    .c configure -xscrollincrement 20 -yscrollincrement 10\n    .c xview moveto 1.0\n    .c canvasx 0\n} -result {215.0}\ntest canvas-6.5 {CanvasSetOrigin procedure} -body {\n    .c configure -xscrollincrement 20 -yscrollincrement 10\n    .c yview moveto 1.0\n    .c canvasy 0\n} -result {55.0}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest canvas-7.1 {canvas widget vs hidden commands} -setup {\n    canvas .c\n} -body {\n    interp hide {} .c\n    destroy .c\n    list [winfo children .] [lsort [interp hidden]]\n} -cleanup {\n    destroy .c\n} -result [list {} [lsort [interp hidden]]]\n\ntest canvas-8.1 {canvas arc bbox} -setup {\n    catch {destroy .c}\n    canvas .c\n} -body {\n    .c create arc -100 10 100 210 -start 10 -extent 50 -style arc -tags arc1\n    set arcBox [.c bbox arc1]\n    .c create arc 100 10 300 210 -start 10 -extent 50 -style chord -tags arc2\n    set coordBox [.c bbox arc2]\n    .c create arc 300 10 500 210 -start 10 -extent 50 -style pieslice -tags arc3\n    set pieBox [.c bbox arc3]\n    .c create arc 100 200 300 200 -height [expr {(1-0.5*sqrt(3))*200}] -style arc -tags arc4\n    set arcSegBox [.c bbox arc4]\n    list $arcBox $coordBox $pieBox $arcSegBox\n} -result {{48 21 100 94} {248 21 300 94} {398 21 500 112} {98 171 302 202}}\ntest canvas-8.2 {canvas very small arc} -setup {\n    catch {destroy .c}\n    canvas .c\n} -body {\n    # no Inf or NaN must be generated even for very small arcs\n    .c create arc 0 100 0 100 -height 100 -style arc -outline \"\" -tags arc1\n    set arcBox [.c bbox arc1]\n    .c create arc 0 100 0 100 -height 100 -style arc -outline blue -tags arc2\n    set outlinedArcBox [.c bbox arc2]\n    set coords [.c coords arc1]\n    set start [.c itemcget arc1 -start]\n    set extent [.c itemcget arc1 -extent]\n    set width [.c itemcget arc1 -width]\n    set height [.c itemcget arc1 -height]\n    list $arcBox $outlinedArcBox $coords $start $extent $width $height\n} -cleanup {\n    unset -nocomplain arcBox coords extent height outlinedArcBox start width\n} -result {{-1 99 1 101} {-2 98 2 102} {0.0 100.0 0.0 100.0} 0.0 0.0 1.0 0.0}\n\ntest canvas-9.1 {canvas id creation and deletion} -setup {\n    catch {destroy .c}\n    canvas .c\n} -body {\n    # With Tk 8.0.4 the ids are now stored in a hash table. You can use this\n    # test as a performance test with older versions by changing the value of\n    # size.\n    set size 15\n    for {set i 0} {$i < $size} {incr i} {\n\tset x [expr {-10 + 3*$i}]\n\tfor {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {\n\t    .c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \\\n\t\t    -outline black -fill blue -tags rect\n\t    .c create text [expr {$x+1}]c [expr {$y+1}]c -text \"$i,$j\" \\\n\t\t    -anchor center -tags text\n\t}\n    }\n    # The actual bench mark - this code also exercises all the hash table\n    # changes.\n    set time [lindex [time {\n\tforeach id [.c find withtag all] {\n\t    .c lower $id\n\t    .c raise $id\n\t    .c find withtag $id\n\t    .c bind <Return> $id {}\n\t    .c delete $id\n\t}\n    }] 0]\n    set x \"\"\n} -result {}\n\ntest canvas-10.1 {find items using tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    set res {}\n} -body {\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 60 40 80 -fill yellow -tag [list b a]\n    .c create oval 20 100 40 120 -fill green -tag [list c b]\n    .c create oval 20 140 40 160 -fill blue -tag [list b]\n    .c create oval 20 180 40 200 -fill bisque -tag [list a d e]\n    .c create oval 20 220 40 240 -fill bisque -tag b\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n    lappend res [.c find withtag {!a}]\n    lappend res [.c find withtag {b&&c}]\n    lappend res [.c find withtag {b||c}]\n    lappend res [.c find withtag {a&&!b}]\n    lappend res [.c find withtag {!b&&!c}]\n    lappend res [.c find withtag {d&&a&&c&&b}]\n    lappend res [.c find withtag {b^a}]\n    lappend res [.c find withtag {(a&&!b)||(!a&&b)}]\n    lappend res [.c find withtag { ( a && ! b ) || ( ! a && b ) }]\n    lappend res [.c find withtag {a&&!(c||d)}]\n    lappend res [.c find withtag {d&&\"tag with spaces\"}]\n    lappend res [.c find withtag \"tag with spaces\"]\n} -result {{3 4 6 7} {1 3} {1 2 3 4 6} 5 {5 7} 1 {3 4 5 6} {3 4 5 6} {3 4 5 6} 2 7 7}\ntest canvas-10.2 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {&&c}\n} -returnCodes error -result {unexpected operator in tag search expression}\ntest canvas-10.3 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {!!c}\n} -returnCodes error -result {too many '!' in tag search expression}\ntest canvas-10.4 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {b||}\n} -returnCodes error -result {missing tag in tag search expression}\ntest canvas-10.5 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {b&&(c||)}\n} -returnCodes error -result {unexpected operator in tag search expression}\ntest canvas-10.6 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {d&&\"\"}\n} -returnCodes error -result {null quoted tag string in tag search expression}\ntest canvas-10.7 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag \"d&&\\\"tag with spaces\"\n} -returnCodes error -result {missing endquote in tag search expression}\ntest canvas-10.8 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -returnCodes error -body {\n    .c find withtag {a&&\"tag with spaces\"z}\n} -result {invalid boolean operator in tag search expression}\ntest canvas-10.9 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {a&&b&c}\n} -returnCodes error -result {singleton '&' in tag search expression}\ntest canvas-10.10 {check errors from tag expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red -tag [list a b c d]\n    .c create oval 20 260 40 280 -fill bisque -tag [list d \"tag with spaces\"]\n} -body {\n    .c find withtag {a||b|c}\n} -returnCodes error -result {singleton '|' in tag search expression}\ntest canvas-10.11 {backward compatility - strange tags that are not expressions} -setup {\n    catch {destroy .c}\n    canvas .c\n    .c create oval 20 20 40 40 -fill red \\\n\t-tag [list { strange tag(xxx&yyy|zzz) \" && \\\" || ! ^ \" }]\n} -body {\n    .c find withtag { strange tag(xxx&yyy|zzz) \" && \\\" || ! ^ \" }\n} -result 1\ntest canvas-10.12 {multple events bound to same tag expr} -setup {\n    catch {destroy .c}\n    canvas .c\n} -body {\n    .c bind {a && b} <Enter> {puts Enter}\n    .c bind {a && b} <Leave> {puts Leave}\n} -result {}\ntest canvas-10.13 {more long tag searches; Bug 2931374} -setup {\n    catch {destroy .c}\n    canvas .c\n} -body {\n    .c find withtag {(A&&B&&C&&D)&&area&&!text}\n    # memory errors on failure\n} -cleanup {\n    destroy .c\n} -result {}\n\ntest canvas-11.1 {canvas poly fill check, bug 5783} -setup {\n    destroy .c\n    pack [canvas .c]\n} -body {\n    # This would crash in 8.3.0 and 8.3.1\n    .c create polygon 0 0 100 100 200 50 \\\n\t    -fill {} -stipple gray50 -outline black\n} -result 1\ntest canvas-11.2 {canvas poly overlap fill check, bug 226357} -setup {\n    destroy .c\n    pack [canvas .c]\n    set result {}\n} -body {\n    .c create poly 30 30 90 90 30 90 90 30\n    lappend result [.c find over 40 40 45 45];\t# rect region inc. edge\n    lappend result [.c find over 60 40 60 40];\t# top-center point\n    lappend result [.c find over 0 0 0 0];\t# not on poly\n    lappend result [.c find over 60 60 60 60];\t# center-point\n    lappend result [.c find over 45 50 45 50];\t# outside poly\n    .c itemconfig 1 -fill \"\" -outline black\n    lappend result [.c find over 40 40 45 45];\t# rect region inc. edge\n    lappend result [.c find over 60 40 60 40];\t# top-center point\n    lappend result [.c find over 0 0 0 0];\t# not on poly\n    lappend result [.c find over 60 60 60 60];\t# center-point\n    lappend result [.c find over 45 50 45 50];\t# outside poly\n    .c itemconfig 1 -width 8\n    lappend result [.c find over 45 50 45 50];\t# outside poly\n} -result {1 1 {} 1 {} 1 1 {} 1 {} 1}\ntest canvas-11.3 {canvas poly dchars, bug 3291543} {\n    # This would crash\n    destroy .c\n    pack [canvas .c]\n    .c create polygon 0 0 0 10 10 0\n    .c dchars 1 2 end\n    .c coords 1\n} {}\ntest canvas-11.4 {canvas line dchars crash with -arrows, bug 51ece3786f} {\n    # This would crash\n    destroy .c\n    canvas .c\n    .c create line 10 10 100 100 -arrow last\n    .c dchars 1 0 1\n} {}\n\ntest canvas-12.1 {canvas mm obj, patch SF-403327, 102471} -setup {\n    destroy .c\n    pack [canvas .c]\n} -body {\n    set qx [expr {1.+1.}]\n    # qx has type double and no string representation\n    .c scale all $qx 0 1. 1.\n    # qx has now type MMRep and no string representation\n    list $qx [string length $qx]\n} -result {2.0 3}\ntest canvas-12.2 {canvas mm obj, patch SF-403327, 102471} -setup {\n    destroy .c\n    pack [canvas .c]\n} -body {\n    set val 10\n    incr val\n    # qx has type double and no string representation\n    .c scale all $val 0 1 1\n    # qx has now type MMRep and no string representation\n    incr val\n} -result 12\n\ntest canvas-13.1 {canvas delete during event, SF bug-228024} -body {\n    kill_canvas .c\n    set ::x {}\n    # do this many times to improve chances of triggering the crash\n    for {set i 0} {$i < 30} {incr i} {\n\tevent generate .c <Button-1> -x 100 -y 100\n\tevent generate .c <ButtonRelease-1> -x 100 -y 100\n    }\n    return $::x\n} -result {okokokokokokokokokokokokokokokokokokokokokokokokokokokokokok}\n\ntest canvas-14.1 {canvas scan SF bug 581560} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c scan\n} -result {wrong # args: should be \".c scan mark|dragto x y ?dragGain?\"}\ntest canvas-14.2 {canvas scan} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c scan bogus\n} -result {wrong # args: should be \".c scan mark|dragto x y ?dragGain?\"}\ntest canvas-14.3 {canvas scan} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c scan mark\n} -result {wrong # args: should be \".c scan mark|dragto x y ?dragGain?\"}\ntest canvas-14.4 {canvas scan} -setup {\n    destroy .c\n    canvas .c\n} -body {\n    .c scan mark 10 10\n} -result {}\ntest canvas-14.5 {canvas scan} -setup {\n    destroy .c\n    canvas .c\n} -body {\n    .c scan mark 10 10 5\n} -returnCodes error -result {wrong # args: should be \".c scan mark x y\"}\ntest canvas-14.6 {canvas scan} -setup {\n    destroy .c\n    canvas .c\n} -body {\n    .c scan dragto 10 10 5\n} -result {}\n\ntest canvas-15.1 {basic types check: arc requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create arc\n} -result {wrong # args: should be \".c create arc coords ?arg ...?\"}\ntest canvas-15.2 \"basic coords check: arc coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -body {\n    .c create arc 0\n} -returnCodes error -result {wrong # coordinates: expected 4, got 1}\ntest canvas-15.3 {basic types check: bitmap requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create bitmap\n} -result {wrong # args: should be \".c create bitmap coords ?arg ...?\"}\ntest canvas-15.4 \"basic coords check: bitmap coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -body {\n    .c create bitmap 0\n} -returnCodes error -result {wrong # coordinates: expected 2, got 1}\ntest canvas-15.5 {basic types check: image requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create image\n} -result {wrong # args: should be \".c create image coords ?arg ...?\"}\ntest canvas-15.6 \"basic coords check: image coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create image 0\n} -result {wrong # coordinates: expected 2, got 1}\ntest canvas-15.7 {basic types check: line requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create line\n} -result {wrong # args: should be \".c create line coords ?arg ...?\"}\ntest canvas-15.8 \"basic coords check: line coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create line 0\n} -result {wrong # coordinates: expected an even number, got 1}\ntest canvas-15.9 {basic types check: oval requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create oval\n} -result {wrong # args: should be \".c create oval coords ?arg ...?\"}\ntest canvas-15.10 \"basic coords check: oval coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create oval 0\n} -result {wrong # coordinates: expected 0 or 4, got 1}\ntest canvas-15.11 {basic types check: polygon requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create polygon\n} -result {wrong # args: should be \".c create polygon coords ?arg ...?\"}\ntest canvas-15.12 \"basic coords check: polygon coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create polygon 0\n} -result {wrong # coordinates: expected an even number, got 1}\ntest canvas-15.13 {basic types check: rect requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create rect\n} -result {wrong # args: should be \".c create rect coords ?arg ...?\"}\ntest canvas-15.14 \"basic coords check: rect coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create rect 0\n} -result {wrong # coordinates: expected 0 or 4, got 1}\ntest canvas-15.15 {basic types check: text requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create text\n} -result {wrong # args: should be \".c create text coords ?arg ...?\"}\ntest canvas-15.16 \"basic coords check: text coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create text 0\n} -result {wrong # coordinates: expected 2, got 1}\ntest canvas-15.17 {basic types check: window requires coords} -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create window\n} -result {wrong # args: should be \".c create window coords ?arg ...?\"}\ntest canvas-15.18 \"basic coords check: window coords are paired\" -setup {\n    destroy .c\n    canvas .c\n} -returnCodes error -body {\n    .c create window 0\n} -result {wrong # coordinates: expected 2, got 1}\ntest canvas-15.19 \"basic coords check: centimeters are larger than pixels\" -setup {\n    destroy .c\n    canvas .c\n} -body {\n    set id [.c create rect 0 0 1c 1c]\n    expr {[lindex [.c coords $id] 2]>1}\n} -result 1\ntest canvas-15.20 {bug [237971ce]} -setup {\n    destroy .c\n    canvas .c\n} -body {\n    set id [.c create line {0 0 50 50 100 50}]\n    .c insert $id end {200 200}\n    .c coords $id\n} -result {0.0 0.0 50.0 50.0 100.0 50.0 200.0 200.0}\ntest canvas-15.21 {bug [237971ce]} -setup {\n    destroy .c\n    canvas .c\n} -body {\n    set id [.c create poly {0 0 50 50 100 50}]\n    .c insert $id end {200 200}\n    .c coords $id\n} -result {0.0 0.0 50.0 50.0 100.0 50.0 200.0 200.0}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .c\n\ntest canvas-16.1 {arc coords check} -setup {\n    canvas .c\n} -body {\n    set id [.c create arc {0 10 20 30} -start 33]\n    .c itemcget $id -start\n} -cleanup {\n    destroy .c\n} -result {33.0}\n\ntest canvas-17.1 {default smooth method handling} -setup {\n    canvas .c\n} -body {\n    set id [.c create line {0 0 1 1 2 2 3 3 4 4 5 5 6 6}]\n    set result [.c itemcget $id -smooth]\n    foreach smoother {yes 1 bezier raw r b} {\n\t.c itemconfigure $id -smooth $smoother\n\tlappend result [.c itemcget $id -smooth]\n    }\n    return $result\n} -cleanup {\n    destroy .c\n} -result {0 true true true raw raw true}\n\ntest canvas-18.1 {imove method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id 0 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {4.0 4.0 1.0 1.0 2.0 2.0 3.0 3.0}\ntest canvas-18.2 {imove method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1]\n    .c imove $id 0 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {4.0 4.0 1.0 1.0}\ntest canvas-18.3 {imove method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id @1,1 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 4.0 4.0 2.0 2.0 3.0 3.0}\ntest canvas-18.4 {imove method - lines} -constraints knownBug -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id end 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 1.0 1.0 2.0 2.0 4.0 4.0}\ntest canvas-18.5 {imove method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c imove $id 0 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {4.0 4.0 1.0 1.0 2.0 2.0 3.0 3.0}\ntest canvas-18.6 {imove method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1]\n    .c imove $id 0 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {4.0 4.0 1.0 1.0}\ntest canvas-18.7 {imove method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c imove $id @1,1 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 4.0 4.0 2.0 2.0 3.0 3.0}\ntest canvas-18.8 {imove method - polygon} -constraints knownBug -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c imove $id end 4 4\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 1.0 1.0 2.0 2.0 4.0 4.0}\ntest canvas-18.9 {imove method - errors} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id foobar 4 4\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad index \"foobar\"}\ntest canvas-18.10 {imove method - errors} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id 0 foobar 4\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"foobar\"}\ntest canvas-18.11 {imove method - errors} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c imove $id 0 4 foobar\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {expected screen distance but got \"foobar\"}\n\ntest canvas-19.1 {rchars method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {4 4}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 4.0 4.0 3.0 3.0}\ntest canvas-19.2 {rchars method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 3.0 3.0}\ntest canvas-19.3 {rchars method - lines} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {10 11 12 13 14 15}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 10.0 11.0 12.0 13.0 14.0 15.0 3.0 3.0}\ntest canvas-19.4 {rchars method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {4 4}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 4.0 4.0 3.0 3.0}\ntest canvas-19.5 {rchars method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 3.0 3.0}\ntest canvas-19.6 {rchars method - polygon} -setup {\n    canvas .c\n} -body {\n    set id [.c create polygon 0 0 1 1 2 2 3 3]\n    .c rchars $id 2 4 {10 11 12 13 14 15}\n    .c coords $id\n} -cleanup {\n    destroy .c\n} -result {0.0 0.0 10.0 11.0 12.0 13.0 14.0 15.0 3.0 3.0}\ntest canvas-19.7 {rchars method - text} -setup {\n    canvas .c\n} -body {\n    set id [.c create text 0 0 -text abcde]\n    .c rchars $id 1 3 XYZ\n    .c itemcget $id -text\n} -cleanup {\n    destroy .c\n} -result aXYZe\ntest canvas-19.8 {rchars method - text} -setup {\n    canvas .c\n} -body {\n    set id [.c create text 0 0 -text abcde]\n    .c rchars $id 1 3 {}\n    .c itemcget $id -text\n} -cleanup {\n    destroy .c\n} -result ae\ntest canvas-19.9 {rchars method - text} -setup {\n    canvas .c\n} -body {\n    set id [.c create text 0 0 -text abcde]\n    .c rchars $id 1 3 FOOBAR\n    .c itemcget $id -text\n} -cleanup {\n    destroy .c\n} -result aFOOBARe\ntest canvas-19.10 {rchars method - errors} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1]\n    .c rchars $id foo 1 {2 2}\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad index \"foo\"}\ntest canvas-19.11 {rchars method - errors} -setup {\n    canvas .c\n} -body {\n    set id [.c create line 0 0 1 1]\n    .c rchars $id 1 foo {2 2}\n} -cleanup {\n    destroy .c\n} -returnCodes error -result {bad index \"foo\"}\n\ntest canvas-20.1 {addtag/dtag - no shuffling of tag sequence} -setup {\n    canvas .c\n    .c create text 100 100 -text Hello\n} -body {\n    for {set i 1} {$i < 5} {incr i} {\n\t.c addtag tag$i all\n    }\n    # [.c addtags] only adds tags that are not already present\n    .c addtag tag1 all   ; # no effect\n    set res [list [.c gettags 1]]\n    .c dtag 1 tag2\n    lappend res [.c gettags 1]\n} -cleanup {\n    destroy .c\n} -result {{tag1 tag2 tag3 tag4} {tag1 tag3 tag4}}\ntest canvas-20.2 {tag deletion - multiple tags with same name, no shuffling} -setup {\n    canvas .c\n    .c create text 100 100 -text Hello\n} -body {\n    # [.c itemconfigure -tags] lets the user add duplicate tags\n    # this is not a problem although inconsistent with [.c addtags]\n    .c itemconfigure 1 -tags {tagA tagB tagA tagA tagC tagA}\n    set res [list [.c gettags 1]]\n    .c dtag 1 tagA\n    lappend res [.c gettags 1]\n} -cleanup {\n    destroy .c\n} -result {{tagA tagB tagA tagA tagC tagA} {tagB tagC}}\ntest canvas-20.3 {tag deletion - all tags match} -setup {\n    canvas .c\n    .c create text 100 100 -text Hello\n} -body {\n    # [.c itemconfigure -tags] lets the user add duplicate tags\n    # this is not a problem although inconsistent with [.c addtags]\n    .c itemconfigure 1 -tags {tagA tagA tagA tagA tagA tagA}\n    set res [list [.c gettags 1]]\n    .c dtag 1 tagA\n    lappend res [.c gettags 1]\n} -cleanup {\n    destroy .c\n} -result {{tagA tagA tagA tagA tagA tagA} {}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .c\n\ntest canvas-21.1 {canvas rotate} -setup {\n    pack [canvas .c]\n} -body {\n    .c create line 50 50 50 100 100 100\n    .c rotate all 75 75 90\n    lmap c [.c coords all] {format %.2f $c}\n} -cleanup {\n    destroy .c\n} -result {50.00 100.00 100.00 100.00 100.00 50.00}\ntest canvas-21.2 {canvas rotate} -setup {\n    pack [canvas .c]\n} -body {\n    .c create line 50 50 50 100 100 100\n    .c rotate all 75 75 -10\n    lmap c [.c coords all] {format %.2f $c}\n} -cleanup {\n    destroy .c\n} -result {54.72 46.04 46.04 95.28 95.28 103.96}\ntest canvas-21.3 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all 75 75\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {wrong # args: should be \".c rotate tagOrId x y angle\"}\ntest canvas-21.4 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all 75 75 123 123\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {wrong # args: should be \".c rotate tagOrId x y angle\"}\ntest canvas-21.5 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate {!} 1 1 1\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {missing tag in tag search expression}\ntest canvas-21.6 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all x 1 1\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {expected screen distance but got \"x\"}\ntest canvas-21.7 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all 1 x 1\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {expected screen distance but got \"x\"}\ntest canvas-21.8 {canvas rotate: syntax} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all 1 1 x\n} -returnCodes error -cleanup {\n    destroy .c\n} -result {expected floating-point number but got \"x\"}\ntest canvas-21.9 {canvas rotate: nothing to rotate} -setup {\n    pack [canvas .c]\n} -body {\n    .c rotate all 75 75 10\n} -cleanup {\n    destroy .c\n} -result {}\ntest canvas-21.10 {canvas rotate: multiple things to rotate} -setup {\n    pack [canvas .c]\n} -body {\n    .c create line 50 50 50 100 -tag a\n    .c create line 50 50 100 50 -tag b\n    .c rotate all 75 75 45\n    list [lmap c [.c coords a] {format %.2f $c}] [lmap c [.c coords b] {format %.2f $c}]\n} -cleanup {\n    destroy .c\n} -result {{39.64 75.00 75.00 110.36} {39.64 75.00 75.00 39.64}}\n\ntest canvas-22.1 {canvas rotate: arc item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create arc 50 50 75 75 -start 45 -extent 90\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {-start -extent} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 125.00 75.00 150.00} {45.0 90.0} {52 123 73 140}}\ntest canvas-22.2 {canvas rotate: bitmap item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create bitmap 50 50 -bitmap info -anchor se\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {-bitmap -anchor} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 150.00} {info se} {42 129 50 150}}\ntest canvas-22.3 {canvas rotate: image item rotation behaviour} -setup {\n    pack [canvas .c]\n    image create photo dummy -width 50 -height 50\n} -body {\n    .c create image 50 50 -image dummy -anchor se\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {-image -anchor} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n    image delete dummy\n} -result {{50.00 150.00} {dummy se} {0 100 50 150}}\ntest canvas-22.4 {canvas rotate: line item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create line 50 50 75 50 50 75 75 75\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 150.00 50.00 125.00 75.00 150.00 75.00 125.00} {} {48 123 77 152}}\ntest canvas-22.5 {canvas rotate: oval item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create oval 50 50 65 85\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{60.00 125.00 75.00 160.00} {} {59 124 76 161}}\ntest canvas-22.6 {canvas rotate: polygon item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create polygon 50 50 75 50 50 75 75 75\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 150.00 50.00 125.00 75.00 150.00 75.00 125.00} {} {48 123 77 152}}\ntest canvas-22.7 {canvas rotate: rectangle item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create rectangle 50 50 75 75\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 125.00 75.00 150.00} {} {49 124 76 151}}\ntest canvas-22.8 {canvas rotate: text item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create text 50 50 -text foo -angle 45\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {-text -angle} {.c itemcget all $o}]\n    # [.c bbox all]\n    # No testing of text bounding box; fonts too variable!\n} -cleanup {\n    destroy .c\n} -result {{50.00 150.00} {foo 45.0}}\ntest canvas-22.9 {canvas rotate: window item rotation behaviour} -setup {\n    pack [canvas .c]\n} -body {\n    .c create window 50 50 -window [frame .c.f -width 25 -height 25] \\\n\t-anchor se\n    .c rotate all 100 100 90\n    list [lmap c [.c coords all] {format %.2f $c}] \\\n\t[lmap o {} {.c itemcget all $o}] \\\n\t[.c bbox all]\n} -cleanup {\n    destroy .c\n} -result {{50.00 150.00} {} {25 125 50 150}}\n\ntest canvas-23.1 {canvas image} -setup {\n    canvas .c\n    image create photo testimage\n} -body  {\n    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}\n    .c create rectangle 0 0 0 9 -fill #000080 -outline #000080\n    .c image testimage\n    matchPixels [testimage data] { \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t    {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}\n} -cleanup {\n    destroy .c\n    image delete testimage\n} -result 1\n\ntest canvas-23.2 {canvas image with subsample} -setup {\n    canvas .c\n    image create photo testimage\n} -body  {\n    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}\n    .c create rectangle 0 0 1 9 -fill #008000 -outline #008000\n    .c image testimage 2\n    matchPixels [testimage data] { \\\n\t{#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}\n} -cleanup {\n    destroy .c\n    image delete testimage\n} -result 1\n\ntest canvas-23.3 {canvas image with subsample and zoom} -setup {\n    canvas .c\n    image create photo testimage\n} -body  {\n    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}\n    .c create rectangle 0 0 9 0 -fill #800000 -outline #800000\n    .c image testimage 1 2\n    matchPixels [testimage data] { \\\n\t{#800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000} \\\n\t{#800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \\\n\t{#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}\n} -cleanup {\n    destroy .c\n    image delete testimage\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\nimageCleanup\ntestutils forget image\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/choosedir.test",
    "content": "# This file is a Tcl script to test out Tk's \"tk_chooseDir\".\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc EnterDirsByKey {parent dirs} {\n    if {$parent eq \".\"} {\n\tset w .__tk_choosedir\n    } else {\n\tset w $parent.__tk_choosedir\n    }\n    upvar ::tk::dialog::file::__tk_choosedir data\n\n    foreach dir $dirs {\n\t$data(ent) delete 0 end\n\t$data(ent) insert 0 $dir\n\tupdate\n\tSendButtonPress $parent ok mouse\n\tafter 50\n    }\n}\n\nproc ToEnterDirsByKey {parent dirs} {\n    after 100 [list EnterDirsByKey $parent $dirs]\n}\n\n#\n# COMMON TEST SETUP\n#\nset parent .\n\n# Make a dir for us to rely on for tests\nset real [makeDirectory choosedirTest]\nset fake [file join [file dirname $real] non-existant]\n\n#\n# TESTS\n#\n\ntest choosedir-1.1 {tk_chooseDirectory command} -body {\n    tk_chooseDirectory -initialdir\n} -returnCodes error -result {value for \"-initialdir\" missing}\ntest choosedir-1.2 {tk_chooseDirectory command} -body {\n    tk_chooseDirectory -mustexist\n} -returnCodes error -result {value for \"-mustexist\" missing}\ntest choosedir-1.3 {tk_chooseDirectory command} -body {\n    tk_chooseDirectory -parent\n} -returnCodes error -result {value for \"-parent\" missing}\ntest choosedir-1.4 {tk_chooseDirectory command} -body {\n    tk_chooseDirectory -title\n} -returnCodes error -result {value for \"-title\" missing}\ntest choosedir-1.5.1 {tk_chooseDirectory command} -constraints notAqua -body {\n    tk_chooseDirectory -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -initialdir, -mustexist, -parent, or -title}\ntest choosedir-1.5.2 {tk_chooseDirectory command} -constraints aqua -body {\n    tk_chooseDirectory -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -command, -initialdir, -message, -mustexist, -parent, or -title}\ntest choosedir-1.6 {tk_chooseDirectory command} -body {\n    tk_chooseDirectory -parent foo.bar\n} -returnCodes error -result {bad window path name \"foo.bar\"}\n\n\ntest choosedir-2.1 {tk_chooseDirectory command, cancel gives null} -constraints {\n\tunix notAqua\n} -body {\n    ToPressButton $parent cancel\n    tk_chooseDirectory -title \"Press Cancel\" -parent $parent\n} -result {}\n\n\ntest choosedir-3.1 {tk_chooseDirectory -mustexist 1} -constraints {\n\tunix notAqua\n} -body {\n    # first enter a bogus dirname, then enter a real one.\n    ToEnterDirsByKey $parent [list $fake $real $real]\n    set result [tk_chooseDirectory \\\n\t    -title \"Enter \\\"$fake\\\", press OK, enter \\\"$real\\\", press OK\" \\\n\t    -parent $parent -mustexist 1]\n    set result\n} -result $real\ntest choosedir-3.2 {tk_chooseDirectory -mustexist 0} -constraints {\n\tunix notAqua\n} -body {\n    ToEnterDirsByKey $parent [list $fake $fake]\n    tk_chooseDirectory -title \"Enter \\\"$fake\\\", press OK\" \\\n\t    -parent $parent -mustexist 0\n} -result $fake\n\n\ntest choosedir-4.1 {tk_chooseDirectory command, initialdir} -constraints {\n\tunix notAqua\n} -body {\n    ToPressButton $parent ok\n    tk_chooseDirectory -title \"Press Ok\" -parent $parent -initialdir $real\n} -result $real\ntest choosedir-4.2 {tk_chooseDirectory command, initialdir} -constraints {\n\tunix notAqua\n} -body {\n    ToEnterDirsByKey $parent [list $fake $fake]\n    tk_chooseDirectory \\\n\t    -title \"Enter \\\"$fake\\\" and press Ok\" \\\n\t    -parent $parent -initialdir $real\n} -result $fake\ntest choosedir-4.3 {tk_chooseDirectory command, {} initialdir} -constraints {\n\tunix notAqua\n} -body {\n    catch {unset ::tk::dialog::file::__tk_choosedir}\n    ToPressButton $parent ok\n    tk_chooseDirectory \\\n\t    -title \"Press OK\" \\\n\t    -parent $parent -initialdir \"\"\n} -result [pwd]\n\n\ntest choosedir-5.1 {tk_chooseDirectory, handles {} entry text} -constraints {\n\tunix notAqua\n} -body {\n    ToEnterDirsByKey $parent [list \"\" $real $real]\n    tk_chooseDirectory -title \"Clear entry, Press OK; Enter $real, press OK\" \\\n\t    -parent $parent\n} -result $real\n\n#\n# TESTFILE CLEANUP\n#\n\nunset fake parent real\nremoveDirectory choosedirTest\ntestutils forget dialog\ncleanupTests\n"
  },
  {
    "path": "tests/clipboard.test",
    "content": "# This file is a Tcl script to test out Tk's clipboard management code,\n# especially the \"clipboard\" command.\n#\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is platform-indifferent. Tests regarding the clipboard that\n#   are specific to the windows platform go into the test file winClipboard.test.\n# * Multiple display clipboard handling will only be tested if the environment\n#   variable TK_ALT_DISPLAY is set to an alternate display.\n# * Some of these tests may fail if another application is grabbing the\n#   clipboard (e.g. an X server, or a VNC viewer)\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# COMMON TEST SETUP\n#\n\n# set up a very large buffer to test INCR retrievals\nset longValue \"\"\nforeach i {a b c d e f g j h i j k l m o p q r s t u v w x y z} {\n    set j $i.1$i.2$i.3$i.4$i.5$i.6$i.7$i.8$i.9$i.10$i.11$i.12$i.13$i.14\n    append longValue A$j B$j C$j D$j E$j F$j G$j H$j I$j K$j L$j M$j N$j\n}\n\n#\n# TESTS\n#\n\ntest clipboard-1.1 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"test\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result {test}\ntest clipboard-1.2 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"test\"\n    clipboard append \"ing\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result {testing}\ntest clipboard-1.3 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"t\"\n    clipboard append \"e\"\n    clipboard append \"s\"\n    clipboard append \"t\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result {test}\ntest clipboard-1.4 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append $longValue\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result \"$longValue\"\ntest clipboard-1.5 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append $longValue\n    clipboard append \"test\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result \"${longValue}test\"\ntest clipboard-1.6 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -t TEST $longValue\n    clipboard append -t STRING \"test\"\n    list [clipboard get -t STRING] [clipboard get -t TEST]\n} -cleanup {\n    clipboard clear\n} -result [list test $longValue]\ntest clipboard-1.7 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -t TEST [string range $longValue 1 4000]\n    clipboard append -t STRING \"test\"\n    list [clipboard get -t STRING] [clipboard get -t TEST]\n} -cleanup {\n    clipboard clear\n} -result [list test [string range $longValue 1 4000]]\ntest clipboard-1.8 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result {}\ntest clipboard-1.9 {ClipboardHandler procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"\"\n    clipboard append \"Test\"\n    clipboard get\n} -cleanup {\n    clipboard clear\n} -result {Test}\n\n##############################################################################\n\ntest clipboard-2.1 {ClipboardAppHandler procedure} -setup {\n    set oldAppName [tk appname]\n    clipboard clear\n} -body {\n    tk appname UnexpectedName\n    clipboard append -type NEW_TYPE Data\n    selection get -selection CLIPBOARD -type TK_APPLICATION\n} -cleanup {\n    tk appname $oldAppName\n    clipboard clear\n} -result {UnexpectedName}\n\n##############################################################################\n\ntest clipboard-3.1 {ClipboardWindowHandler procedure} -setup {\n    set oldAppName [tk appname]\n    clipboard clear\n} -body {\n    tk appname UnexpectedName\n    clipboard append -type NEW_TYPE Data\n    selection get -selection CLIPBOARD -type TK_WINDOW\n} -cleanup {\n    tk appname $oldAppName\n    clipboard clear\n} -result {.}\n\n##############################################################################\n\ntest clipboard-4.1 {ClipboardLostSel procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"Test\"\n    selection clear -s CLIPBOARD\n    clipboard get\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"STRING\" not defined}\ntest clipboard-4.2 {ClipboardLostSel procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"Test\"\n    clipboard append -t TEST \"Test2\"\n    selection clear -s CLIPBOARD\n    clipboard get\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"STRING\" not defined}\ntest clipboard-4.3 {ClipboardLostSel procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"Test\"\n    clipboard append -t TEST \"Test2\"\n    selection clear -s CLIPBOARD\n    clipboard get -t TEST\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"TEST\" not defined}\ntest clipboard-4.4 {ClipboardLostSel procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"Test\"\n    clipboard append -t TEST \"Test2\"\n    clipboard append \"Test3\"\n    selection clear -s CLIPBOARD\n    clipboard get\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"STRING\" not defined}\ntest clipboard-4.5 {ClipboardLostSel procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"Test\"\n    clipboard append -t TEST \"Test2\"\n    clipboard append \"Test3\"\n    selection clear -s CLIPBOARD\n    clipboard get -t TEST\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"TEST\" not defined}\n\n\n\n##############################################################################\n\ntest clipboard-5.1 {Tk_ClipboardClear procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -t TEST \"test\"\n    set result [lsort [clipboard get TARGETS]]\n    clipboard clear\n    list $result [lsort [clipboard get TARGETS]]\n} -cleanup {\n    clipboard clear\n}  -result {{MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest clipboard-5.2 {Tk_ClipboardClear procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -t TEST \"test\"\n    set result [lsort [clipboard get TARGETS]]\n    selection own -s CLIPBOARD .\n    lappend result [lsort [clipboard get TARGETS]]\n    clipboard clear\n    clipboard append -t TEST \"test\"\n    lappend result [lsort [clipboard get TARGETS]]\n} -cleanup {\n    clipboard clear\n}  -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\n\n##############################################################################\n\ntest clipboard-6.1 {Tk_ClipboardAppend procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"first chunk\"\n    selection own -s CLIPBOARD .\n\tclipboard append \" second chunk\"\n\tclipboard get\n} -cleanup {\n    clipboard clear\n}  -returnCodes ok -result {first chunk second chunk}\ntest clipboard-6.2 {Tk_ClipboardAppend procedure} -constraints x11 -setup {\n    clipboard clear\n} -body {\n    childTkProcess create\n    clipboard append -f INTEGER -t TEST \"16\"\n    set result [childTkProcess eval {clipboard get TEST}]\n    return $result\n} -cleanup {\n    clipboard clear\n    childTkProcess exit\n}  -result {0x10 }\ntest clipboard-6.3 {Tk_ClipboardAppend procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -f INTEGER -t TEST \"16\"\n    clipboard append -t TEST \"test\"\n} -cleanup {\n    clipboard clear\n}  -returnCodes error -result {format \"STRING\" does not match current format \"INTEGER\" for TEST}\n\n##############################################################################\n\ntest clipboard-7.1 {Tk_ClipboardCmd procedure} -body {\n    clipboard\n} -returnCodes error -result {wrong # args: should be \"clipboard option ?arg ...?\"}\ntest clipboard-7.2 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append --\n} -cleanup {\n    clipboard clear\n} -returnCodes ok -result {}\ntest clipboard-7.3 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append --\n\tselection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -result {--}\ntest clipboard-7.4 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -- information\n\tselection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -result {information}\ntest clipboard-7.5 {Tk_ClipboardCmd procedure} -body {\n    clipboard append --x a b\n} -returnCodes error -result {bad option \"--x\": must be -displayof, -format, or -type}\ntest clipboard-7.6 {Tk_ClipboardCmd procedure} -body {\n    clipboard append -- a b\n} -returnCodes error -result {wrong # args: should be \"clipboard append ?-option value ...? data\"}\ntest clipboard-7.7 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -format\n} -returnCodes ok -result {}\ntest clipboard-7.8 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -format\n\tselection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -result {-format}\ntest clipboard-7.9 {Tk_ClipboardCmd procedure} -body {\n    clipboard append -displayofoo f\n} -returnCodes error -result {bad option \"-displayofoo\": must be -displayof, -format, or -type}\ntest clipboard-7.10 {Tk_ClipboardCmd procedure} -body {\n    clipboard append -type TEST\n} -returnCodes error -result {wrong # args: should be \"clipboard append ?-option value ...? data\"}\ntest clipboard-7.11 {Tk_ClipboardCmd procedure} -body {\n    clipboard append -displayof foo \"test\"\n} -returnCodes error -result {bad window path name \"foo\"}\ntest clipboard-7.12 {Tk_ClipboardCmd procedure} -body {\n    clipboard clear -displayof\n} -returnCodes error -result {wrong # args: should be \"clipboard clear ?-displayof window?\"}\ntest clipboard-7.13 {Tk_ClipboardCmd procedure} -body {\n    clipboard clear -displayofoo f\n} -returnCodes error -result {bad option \"-displayofoo\": must be -displayof}\ntest clipboard-7.14 {Tk_ClipboardCmd procedure} -body {\n    clipboard clear foo\n} -returnCodes error -result {wrong # args: should be \"clipboard clear ?-displayof window?\"}\ntest clipboard-7.15 {Tk_ClipboardCmd procedure} -body {\n    clipboard clear -displayof foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest clipboard-7.16 {Tk_ClipboardCmd procedure} -body {\n    clipboard error\n} -returnCodes error -result {bad option \"error\": must be append, clear, or get}\ntest clipboard-7.17 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -displayof\n} -cleanup {\n    clipboard clear\n} -returnCodes ok -result {}\ntest clipboard-7.18 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -displayof\n\tselection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -result {-displayof}\ntest clipboard-7.19 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -type\n} -cleanup {\n    clipboard clear\n} -returnCodes ok -result {}\ntest clipboard-7.20 {Tk_ClipboardCmd procedure} -setup {\n    clipboard clear\n} -body {\n    clipboard append -type\n\tselection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -result {-type}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget child\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/clrpick.test",
    "content": "# This file is a Tcl script to test out Tk's \"tk_chooseColor\" command.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\nif {[testConstraint defaultPseudocolor8]} {\n    # let's soak up a bunch of colors...so that\n    # machines with small color palettes still fail.\n    # some tests will be skipped if there are no more colors\n    set numcolors 32\n    testConstraint colorsLeftover 1\n    set i 0\n    canvas .c\n    pack .c -expand 1 -fill both\n    while {$i<$numcolors} {\n\tset color \\#[format \"%02x%02x%02x\" $i [expr {$i+1}] [expr {$i+3}]]\n\t.c create rectangle [expr {10+$i}] [expr {10+$i}] [expr {50+$i}] [expr {50+$i}] -fill $color -outline $color\n\tincr i\n    }\n    set i 0\n    while {$i<$numcolors} {\n\tset color [.c itemcget $i -fill]\n\tif {$color ne \"\"} {\n\t    foreach {r g b} [winfo rgb . $color] {}\n\t    set r [expr {$r/256}]\n\t    set g [expr {$g/256}]\n\t    set b [expr {$b/256}]\n\t    if {\"$color\" ne \"#[format %02x%02x%02x $r $g $b]\"} {\n\t\ttestConstraint colorsLeftover 0\n\t    }\n\t}\n\t.c delete $i\n\tincr i\n    }\n    destroy .c\n} else {\n    testConstraint colorsLeftover 1\n}\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc ChooseColorByKey {parent r g b} {\n    set w .__tk__color\n    upvar ::tk::dialog::color::[winfo name $w] data\n\n    update\n    $data(red,entry)   delete 0 end\n    $data(green,entry) delete 0 end\n    $data(blue,entry)  delete 0 end\n\n    $data(red,entry)   insert 0 $r\n    $data(green,entry) insert 0 $g\n    $data(blue,entry)  insert 0 $b\n\n    # Manually force the refresh of the color values instead\n    # of counting on the timing of the event stream to change\n    # the values for us.\n    tk::dialog::color::HandleRGBEntry $w\n\n    SendButtonPress . ok mouse\n}\n\nproc ToChooseColorByKey {parent r g b} {\n    if {! $::dialogIsNative} {\n\tafter 200 ChooseColorByKey . $r $g $b\n    }\n}\n\n#\n# TESTS\n#\n\ntest clrpick-1.1 {tk_chooseColor command} -body {\n    tk_chooseColor -foo\n} -returnCodes error -result {bad option \"-foo\": must be -initialcolor, -parent, or -title}\n\ntest clrpick-1.2 {tk_chooseColor command } -body {\n    tk_chooseColor -initialcolor\n} -returnCodes error -result {value for \"-initialcolor\" missing}\ntest clrpick-1.2.1 {tk_chooseColor command } -body {\n    tk_chooseColor -parent\n} -returnCodes error -result {value for \"-parent\" missing}\ntest clrpick-1.2.2 {tk_chooseColor command } -body {\n    tk_chooseColor -title\n} -returnCodes error -result {value for \"-title\" missing}\n\ntest clrpick-1.3 {tk_chooseColor command} -body {\n    tk_chooseColor -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -initialcolor, -parent, or -title}\ntest clrpick-1.4 {tk_chooseColor command} -body {\n    tk_chooseColor -initialcolor\n} -returnCodes error -result {value for \"-initialcolor\" missing}\ntest clrpick-1.5 {tk_chooseColor command} -body {\n    tk_chooseColor -parent foo.bar\n} -returnCodes error -result {bad window path name \"foo.bar\"}\ntest clrpick-1.6 {tk_chooseColor command} -body {\n    tk_chooseColor -initialcolor badbadbaadcolor\n} -returnCodes error -result {unknown color name \"badbadbaadcolor\"}\ntest clrpick-1.7 {tk_chooseColor command} -body {\n    tk_chooseColor -initialcolor ##badbadbaadcolor\n} -returnCodes error -result {invalid color name \"##badbadbaadcolor\"}\n\ntest clrpick-2.1 {tk_chooseColor command} -constraints {\n    nonUnixUserInteraction colorsLeftover\n} -setup {\n    set verylongstring [string repeat longstring: 100]\n} -body {\n    ToPressButton . ok\n    tk_chooseColor -title \"Press Ok $verylongstring\" -initialcolor #404040 \\\n\t    -parent .\n} -result {#404040}\ntest clrpick-2.2 {tk_chooseColor command} -constraints {\n    nonUnixUserInteraction colorsLeftover\n} -body {\n    set colors \"128 128 64\"\n    ToChooseColorByKey . 128 128 64\n    tk_chooseColor -parent . -title \"choose #808040\"\n} -result {#808040}\ntest clrpick-2.3 {tk_chooseColor command} -constraints {\n    nonUnixUserInteraction colorsLeftover\n} -body {\n    ToPressButton . ok\n    tk_chooseColor -parent . -title \"Press OK\"\n} -result {#808040}\ntest clrpick-2.4 {tk_chooseColor command} -constraints {\n    nonUnixUserInteraction colorsLeftover\n} -body {\n    ToPressButton . cancel\n    tk_chooseColor -parent . -title \"Press Cancel\"\n} -result {}\n\n\ntest clrpick-3.1 {tk_chooseColor: background events} -constraints {\n\tnonUnixUserInteraction\n} -body {\n    after 1 {set x 53}\n    ToPressButton . ok\n    tk_chooseColor -parent . -title \"Press OK\" -initialcolor #000000\n} -result {#000000}\ntest clrpick-3.2 {tk_chooseColor: background events} -constraints {\n\tnonUnixUserInteraction\n} -body {\n    after 1 {set x 53}\n    ToPressButton . cancel\n    tk_chooseColor -parent . -title \"Press Cancel\"\n} -result {}\n\n\ntest clrpick-4.1 {tk_chooseColor: screen is inherited from parent} -constraints {\n\tunix notAqua\n} -body {\n    after 50 {set ::scr [winfo screen .__tk__color]}\n    ToPressButton . cancel\n    tk_chooseColor -parent .\n    set ::scr\n} -result [winfo screen .]\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget dialog\ncleanupTests\n"
  },
  {
    "path": "tests/cluster.test",
    "content": "# This file is a Tcl script to test the [::tk::startOf|endOf]* functions in\n# tk.tcl and tkIcu.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\ntestConstraint needsICU [expr {[catch {info body ::tk::startOfCluster}]}]\n\n#\n# TESTS\n#\n\ntest cluster-1.0 {::tk::startOfCluster} -body {\n    ::tk::startOfCluster é -1\n} -result {}\ntest cluster-1.1 {::tk::startOfCluster} -body {\n    ::tk::startOfCluster é 0\n} -result 0\ntest cluster-1.2 {::tk::startOfCluster} -constraints needsICU -body {\n    ::tk::startOfCluster é 1\n} -result 0\ntest cluster-1.3 {::tk::startOfCluster} -constraints needsICU -body {\n    ::tk::startOfCluster é 2\n} -result 2\ntest cluster-1.4 {::tk::startOfCluster} -constraints needsICU -body {\n    ::tk::startOfCluster é 3\n} -result 2\ntest cluster-1.5 {::tk::startOfCluster} -constraints needsICU -body {\n    ::tk::startOfCluster é end\n} -result 0\ntest cluster-1.6 {::tk::startOfCluster} -body {\n    ::tk::startOfCluster é {}\n} -result {}\ntest cluster-1.7 {::tk::startOfCluster} -constraints needsICU -body {\n    ::tk::startOfCluster é end-1\n} -result 0\n\ntest cluster-2.0 {::tk::endOfCluster} -body {\n    ::tk::endOfCluster é -1\n} -result 0\ntest cluster-2.1 {::tk::endOfCluster} -constraints needsICU -body {\n    ::tk::endOfCluster é 0\n} -result 2\ntest cluster-2.2 {::tk::endOfCluster} -constraints needsICU -body {\n    ::tk::endOfCluster é 1\n} -result 2\ntest cluster-2.3 {::tk::endOfCluster} -body {\n    ::tk::endOfCluster é 2\n} -result {}\ntest cluster-2.4 {::tk::endOfCluster} -body {\n    ::tk::endOfCluster é 3\n} -result {}\ntest cluster-2.5 {::tk::endOfCluster} -constraints needsICU -body {\n    ::tk::endOfCluster é end\n} -result 2\ntest cluster-2.6 {::tk::endOfCluster} -body {\n    ::tk::endOfCluster é {}\n} -result 0\ntest cluster-2.7 {::tk::endOfCluster} -constraints needsICU -body {\n    ::tk::endOfCluster é end-1\n} -result 2\n\ntest cluster-3.0 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" -1\n} -result 2\ntest cluster-3.1 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 0\n} -result 2\ntest cluster-3.2 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 1\n} -result 2\ntest cluster-3.3 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 2\n} -result {}\ntest cluster-3.4 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 3\n} -result {}\ntest cluster-3.5 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 4\n} -result {}\ntest cluster-3.6 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" 5\n} -result {}\ntest cluster-3.7 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" end\n} -result {}\ntest cluster-3.8 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" {}\n} -result 2\ntest cluster-3.9 {::tk::endOfWord} -body {\n    ::tk::endOfWord \"ab cd\" end-1\n} -result {}\n\ntest cluster-4.0 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" -1\n} -result {}\ntest cluster-4.1 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 0\n} -result {}\ntest cluster-4.2 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 1\n} -result 0\ntest cluster-4.3 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 2\n} -result 0\ntest cluster-4.4 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 3\n} -result 0\ntest cluster-4.5 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 4\n} -result 3\ntest cluster-4.6 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" 5\n} -result 3\ntest cluster-4.7 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" end\n} -result 3\ntest cluster-4.8 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" {}\n} -result {}\ntest cluster-4.9 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord \"ab cd\" end-1\n} -result 0\n\ntest cluster-5.0 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" -1\n} -result 3\ntest cluster-5.1 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 0\n} -result 3\ntest cluster-5.2 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 1\n} -result 3\ntest cluster-5.3 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 2\n} -result 3\ntest cluster-5.4 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 3\n} -result {}\ntest cluster-5.5 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 4\n} -result {}\ntest cluster-5.6 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" 5\n} -result {}\ntest cluster-5.7 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" end\n} -result {}\ntest cluster-5.8 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" {}\n} -result 3\ntest cluster-5.9 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord \"ab cd\" end-1\n} -result {}\n\ntest cluster-6.0 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" -1\n} -result {}\ntest cluster-6.1 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 0\n} -result {}\ntest cluster-6.2 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 1\n} -result {}\ntest cluster-6.3 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 2\n} -result 2\ntest cluster-6.4 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 3\n} -result 3\ntest cluster-6.5 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 4\n} -result 3\ntest cluster-6.6 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" 5\n} -result 3\ntest cluster-6.7 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" end\n} -result 3\ntest cluster-6.8 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore \"ab cd\" {}\n} -result {}\ntest cluster-6.9 {::tk::wordBreakBefore} -body {\n    ::tk::startOfNextWord \"ab cd\" end-1\n} -result {}\n\ntest cluster-7.0 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" -1\n} -result 2\ntest cluster-7.1 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 0\n} -result 2\ntest cluster-7.2 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 1\n} -result 2\ntest cluster-7.3 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 2\n} -result 3\ntest cluster-7.4 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 3\n} -result {}\ntest cluster-7.5 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 4\n} -result {}\ntest cluster-7.6 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" 5\n} -result {}\ntest cluster-7.7 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" end\n} -result {}\ntest cluster-7.8 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" {}\n} -result 2\ntest cluster-7.9 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter \"ab cd\" end-1\n} -result {}\n\n\ntest cluster-8.0 {::tk::startOfCluster} -body {\n    ::tk::startOfCluster a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::startOfCluster str start ?locale?\"}\ntest cluster-8.1 {::tk::endOfCluster} -body {\n    ::tk::endOfCluster a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::endOfCluster str start ?locale?\"}\ntest cluster-8.2 {::tk::startOfPreviousWord} -body {\n    ::tk::startOfPreviousWord a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::startOfPreviousWord str start ?locale?\"}\ntest cluster-8.3 {::tk::startOfNextWord} -body {\n    ::tk::startOfNextWord a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::startOfNextWord str start ?locale?\"}\ntest cluster-8.4 {::tk::endOfWord} -body {\n    ::tk::endOfWord a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::endOfWord str start ?locale?\"}\ntest cluster-8.5 {::tk::wordBreakBefore} -body {\n    ::tk::wordBreakBefore a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::wordBreakBefore str start ?locale?\"}\ntest cluster-8.6 {::tk::wordBreakAfter} -body {\n    ::tk::wordBreakAfter a b c d\n} -returnCodes 1 -result {wrong # args: should be \"::tk::wordBreakAfter str start ?locale?\"}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/cmap.tcl",
    "content": "# This file creates a visual test for colormaps and the WM_COLORMAP_WINDOWS\n# property.  It is part of the Tk visual test suite, which is invoked\n# via the \"visual\" script.\n\ncatch {destroy .t}\ntoplevel .t -colormap new\nwm title .t \"Visual Test for Colormaps\"\nwm iconname .t \"Colormaps\"\nwm geom .t +0+0\n\n# The following procedure creates a whole bunch of frames within a\n# window, in order to eat up all the colors in a colormap.\n\nproc colors {w redInc greenInc blueInc} {\n    set red 0\n    set green 0\n    set blue 0\n    for {set y 0} {$y < 8} {incr y} {\n\tfor {set x 0} {$x < 8} {incr x} {\n\t    frame $w.f$x,$y -width 40 -height 40 -bd 2 -relief raised \\\n\t\t    -bg [format #%02x%02x%02x $red $green $blue]\n\t    place $w.f$x,$y -x [expr {40*$x}] -y [expr {40*$y}]\n\t    incr red $redInc\n\t    incr green $greenInc\n\t    incr blue $blueInc\n\t}\n    }\n}\n\nmessage .t.m -width 6i -text {This window displays two nested frames, each with a whole bunch of subwindows that eat up a lot of colors.  The toplevel window has its own colormap, which is inherited by the outer frame.  The inner frame has its own colormap.  As you move the mouse around, the colors in the frames should change back and forth.}\npack .t.m -side top -fill x\n\nbutton .t.quit -text Quit -command {destroy .t}\npack .t.quit -side bottom -pady 3 -ipadx 4 -ipady 2\n\nframe .t.f -width 700 -height 450 -relief raised -bd 2\npack .t.f -side top -padx 1c -pady 1c\ncolors .t.f 4 0 0\nframe .t.f.f -width 350 -height 350 -colormap new -bd 2 -relief raised\nplace .t.f.f -relx 1.0 -rely 0 -anchor ne\ncolors .t.f.f 0 4 0\nbind .t.f.f <Enter> {wm colormapwindows .t {.t.f.f .t}}\nbind .t.f.f <Leave> {wm colormapwindows .t {.t .t.f.f}}\n\ncatch {destroy .t2}\ntoplevel .t2\nwm title .t2 \"Visual Test for Colormaps\"\nwm iconname .t2 \"Colormaps\"\nwm geom .t2 +0-0\n\nmessage .t2.m -width 6i -text {This window just eats up most of the colors in the default colormap.}\npack .t2.m -side top -fill x\n\nbutton .t2.quit -text Quit -command {destroy .t2}\npack .t2.quit -side bottom -pady 3 -ipadx 4 -ipady 2\n\nframe .t2.f -height 320 -width 320\npack .t2.f -side bottom\ncolors .t2.f 0 0 4\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/cmds.test",
    "content": "# This file is a Tcl script to test the procedures in the file\n# tkCmds.c.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\nupdate\n\n#\n# TESTS\n#\n\ntest cmds-1.1 {tkwait visibility, argument errors} -body {\n    tkwait visibility\n} -returnCodes error -result {wrong # args: should be \"tkwait variable|visibility|window name\"}\ntest cmds-1.2 {tkwait visibility, argument errors} -body {\n    tkwait visibility foo bar\n} -returnCodes error -result {wrong # args: should be \"tkwait variable|visibility|window name\"}\ntest cmds-1.3 {tkwait visibility, argument errors} -body {\n    tkwait visibility bad_window\n} -returnCodes error -result {bad window path name \"bad_window\"}\ntest cmds-1.4 {tkwait visibility, waiting for window to be mapped} -setup {\n    button .b -text \"Test\"\n    set x init\n} -body {\n    after 100 {set x delay; place .b -x 0 -y 0}\n    tkwait visibility .b\n    return $x\n} -cleanup {\n    destroy .b\n} -result {delay}\ntest cmds-1.5 {tkwait visibility, window gets deleted} -setup {\n    frame .f\n    button .f.b -text \"Test\"\n    pack .f.b\n    set x init\n} -body {\n    after 100 {set x deleted; destroy .f}\n    tkwait visibility .f.b\n} -returnCodes error -result {window \".f.b\" was deleted before its visibility changed}\ntest cmds-1.6 {tkwait visibility, window gets deleted} -setup {\n    frame .f\n    button .f.b -text \"Test\"\n    pack .f.b\n    set x init\n} -body {\n    after 100 {set x deleted; destroy .f}\n    catch {tkwait visibility .f.b}\n    return $x\n} -cleanup {\n    destroy .f\n} -result {deleted}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/color.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkColor.c.\n#\n# Copyright © 1995-1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import colors\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# c255  -\n# Given a list of red, green, and blue intensities, scale them\n# down to a 0-255 range.\n#\n# Arguments:\n# vals -\tList of intensities.\n\nproc c255 {vals} {\n    list [expr {[lindex $vals 0]/256}] [expr {[lindex $vals 1]/256}] \\\n\t    [expr {[lindex $vals 2]/256}]\n}\n\n# closest -\n# Given intensities between 0 and 255, return the closest intensities\n# that the server can provide.\n#\n# Arguments:\n# w -\t\tWindow in which to lookup color\n# r, g, b -\tDesired intensities, between 0 and 255.\n\nproc closest {w r g b} {\n    set vals [winfo rgb $w [cname $r $g $b]]\n    list [expr {[lindex $vals 0]/256}] [expr {[lindex $vals 1]/256}] \\\n\t    [expr {[lindex $vals 2]/256}]\n}\n\n# cname --\n# Returns a proper name for a color, given its intensities.\n#\n# Arguments:\n# r, g, b -\tIntensities on a 0-255 scale.\nproc cname {r g b} {\n    format #%02x%02x%02x $r $g $b\n}\nproc cname4 {r g b} {\n    format #%04x%04x%04x $r $g $b\n}\n\n# mkColors --\n# Creates a canvas and fills it with a 2-D array of squares, each of a\n# different color.\n#\n# Arguments:\n# c -\t\tName of canvas window to create.\n# width -\tNumber of squares in each row.\n# height -\tNumber of squares in each column.\n# r, g, b -\tInitial value for red, green, and blue intensities.\n# rx, gx, bx -\tChange in intensities between adjacent elements in row.\n# ry, gy, by -\tChange in intensities between adjacent elements in column.\n\nproc mkColors {c width height r g b rx gx bx ry gy by} {\n    catch {destroy $c}\n    canvas $c -width 400 -height 200 -bd 0\n    for {set y 0} {$y < $height} {incr y} {\n\tfor {set x 0} {$x < $width} {incr x} {\n\t    set color [format #%02x%02x%02x [expr {$r + $y*$ry + $x*$rx}] \\\n\t\t    [expr {$g + $y*$gy + $x*$gx}] [expr {$b + $y*$by + $x*$bx}]]\n\t    $c create rectangle [expr {10*$x}] [expr {20*$y}] \\\n\t\t    [expr {10*$x + 10}] [expr {20*$y + 20}] -outline {} \\\n\t\t    -fill $color\n\t}\n    }\n}\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\n# -- WARNING (SB, 6.4.2017) --\n#\n# The if block below looks _very_ outdated. It didn't get any\n# substantial changes as far back as the fossil history goes. It might\n# be from a time, when 256 color was the best you could get! :-o.\n#\n# The problem is, on machines with a fancy 24 truecolor display, the\n# 'colorsFree' constraint doesn't get set, turning off pretty much every test\n# in this file.\n#\nif {[testConstraint pseudocolor8]} {\n    toplevel .t -visual {pseudocolor 8} -colormap new\n    wm geom .t +0+0\n    mkColors .t.c 40 6 0 0 0 0 6 0 0 0 40\n    pack .t.c\n    update\n\n    testConstraint colorsFree [colorsFree .t.c 101 233 17]\n\n    if {[testConstraint colorsFree]} {\n\tmkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0\n\tpack .t.c2\n\ttestConstraint colorsFree [expr {![colorsFree .t.c]}]\n    }\n    destroy .t.c .t.c2\n}\n\n#\n# TESTS\n#\n\ntest color-1.1 {Tk_AllocColorFromObj - converting internal reps} colorsFree {\n    set x green\n    lindex $x 0\n    destroy .b1\n    button .b1 -foreground $x -text .b1\n    lindex $x 0\n    testcolor green\n} {{1 0}}\ntest color-1.2 {Tk_AllocColorFromObj - discard stale color} colorsFree {\n    set x green\n    destroy .b1 .b2\n    button .b1 -foreground $x -text First\n    destroy .b1\n    set result {}\n    lappend result [testcolor green]\n    button .b2 -foreground $x -text Second\n    lappend result [testcolor green]\n} {{} {{1 1}}}\ntest color-1.3 {Tk_AllocColorFromObj - reuse existing color} colorsFree {\n    set x green\n    destroy .b1 .b2\n    button .b1 -foreground $x -text First\n    set result {}\n    lappend result [testcolor green]\n    button .b2 -foreground $x -text Second\n    pack .b1 .b2 -side top\n    lappend result [testcolor green]\n} {{{1 1}} {{2 1}}}\ntest color-1.4 {Tk_AllocColorFromObj - try other colors in list} colorsFree {\n    set x purple\n    destroy .b1 .b2 .t.b\n    button .b1 -foreground $x -text First\n    pack .b1 -side top\n    set result {}\n    lappend result [testcolor purple]\n    button .t.b -foreground $x -text Second\n    pack .t.b -side top\n    lappend result [testcolor purple]\n    button .b2 -foreground $x -text Third\n    pack .b2 -side top\n    lappend result [testcolor purple]\n} {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}\ntest color-1.5 {Color table} nonPortable {\n    set fd [open ../xlib/rgb.txt]\n    set result {}\n    while {[gets $fd line] >= 0} {\n\tif {[string index $line 0] eq \"!\"} continue\n\tset rgb [c255 [winfo rgb . [lrange $line 3 end]]]\n\tif {$rgb ne [lrange $line 0 2] } {\n\t\tappend result $line\\n\n\t}\n\n    }\n    return $result\n} {}\n\ntest color-2.1 {Tk_GetColor procedure} colorsFree {\n    c255 [winfo rgb .t #FF0000]\n} {255 0 0}\ntest color-2.2 {Tk_GetColor procedure} colorsFree {\n    list [catch {winfo rgb .t noname} msg] $msg\n} {1 {unknown color name \"noname\"}}\ntest color-2.3 {Tk_GetColor procedure} colorsFree {\n    c255 [winfo rgb .t #123456]\n} {18 52 86}\ntest color-2.4 {Tk_GetColor procedure} colorsFree {\n    list [catch {winfo rgb .t #xyz} msg] $msg\n} {1 {invalid color name \"#xyz\"}}\ntest color-2.5 {Tk_GetColor procedure} colorsFree {\n    winfo rgb .t #00FF00\n} {0 65535 0}\ntest color-2.6 {Tk_GetColor procedure} {colorsFree nonPortable} {\n    # Red doesn't always map to *pure* red\n    winfo rgb .t red\n} {65535 0 0}\ntest color-2.7 {Tk_GetColor procedure} colorsFree {\n    winfo rgb .t #ff0000\n} {65535 0 0}\ntest color-2.8 {Tk_GetColor, invalid char after 3 valid hex digits} -body {\n    winfo rgb . #abcg\n} -returnCodes error -result {invalid color name \"#abcg\"}\ntest color-2.9 {Tk_GetColor, invalid char after 6 vaild hex digits} -body {\n    winfo rgb . #aabbccz\n} -returnCodes error -result {invalid color name \"#aabbccz\"}\ntest color-2.10 {Tk_GetColor, 3 hex digits, last one invalid} -body {\n    winfo rgb . #abz\n} -returnCodes error -result {invalid color name \"#abz\"}\ntest color-2.11 {Tk_GetColor, 6 hex digits, last one invalid} -body {\n    winfo rgb . #12345g\n} -returnCodes error -result {invalid color name \"#12345g\"}\n\ntest color-3.1 {Tk_FreeColor procedure, reference counting} colorsFree {\n    destroy {*}[winfo children .t]\n    mkColors .t.c 40 6 0 240 240 0 -6 0 0 0 -40\n    pack .t.c\n    mkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0\n    pack .t.c2\n    update\n    set last [.t.c2 create rectangle 50 50 70 60 -outline {} \\\n\t    -fill [cname 0 240 240]]\n    .t.c delete 1\n    set result [colorsFree .t]\n    .t.c2 delete $last\n    lappend result [colorsFree .t]\n} {0 1}\ntest color-3.2 {Tk_FreeColor procedure, flushing stressed cmap information} colorsFree {\n    destroy {*}[winfo children .t]\n    mkColors .t.c 40 6 0 240 240 0 -6 0 0 0 -40\n    pack .t.c\n    mkColors .t.c2 20 1 250 0 0 -10 0 0 0 0 0\n    mkColors .t.c2 20 1 250 250 0 -10 -10 0 0 0 0\n    pack .t.c2\n    update\n    closest .t 241 241 1\n} {240 240 0}\ntest color-3.3 {Tk_FreeColorFromObj - reference counts} colorsFree {\n    set x purple\n    destroy .b1 .b2 .t.b\n    button .b1 -foreground $x -text First\n    pack .b1 -side top\n    button .t.b -foreground $x -text Second\n    pack .t.b -side top\n    button .b2 -foreground $x -text Third\n    pack .b2 -side top\n    set result {}\n    lappend result [testcolor purple]\n    destroy .b1\n    lappend result [testcolor purple]\n    destroy .b2\n    lappend result [testcolor purple]\n    destroy .t.b\n    lappend result [testcolor purple]\n} {{{1 0} {2 1}} {{1 0} {1 1}} {{1 0}} {}}\ntest color-3.4 {Tk_FreeColorFromObj - unlinking from list} colorsFree {\n    destroy .b .t.b .t2 .t3\n    toplevel .t2 -visual {pseudocolor 8} -colormap new\n    toplevel .t3 -visual {pseudocolor 8} -colormap new\n    set x purple\n    button .b -foreground $x -text .b1\n    button .t.b1 -foreground $x -text .t.b1\n    button .t.b2 -foreground $x -text .t.b2\n    button .t2.b1 -foreground $x -text .t2.b1\n    button .t2.b2 -foreground $x -text .t2.b2\n    button .t2.b3 -foreground $x -text .t2.b3\n    button .t3.b1 -foreground $x -text .t3.b1\n    button .t3.b2 -foreground $x -text .t3.b2\n    button .t3.b3 -foreground $x -text .t3.b3\n    button .t3.b4 -foreground $x -text .t3.b4\n    set result {}\n    lappend result [testcolor purple]\n    destroy .t2\n    lappend result [testcolor purple]\n    destroy .b\n    lappend result [testcolor purple]\n    destroy .t3\n    lappend result [testcolor purple]\n    destroy .t\n    lappend result [testcolor purple]\n} {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}}\n\ntest color-4.1 {FreeColorObjProc} -constraints {\n    colorsFree\n} -setup {\n    proc copy {s} {return [string index $s 0][string range $s 1 end]}\n} -body {\n    destroy .b\n    set x [copy purple]\n    button .b -foreground $x -text .b1\n    set y [copy purple]\n    .b configure -foreground $y\n    set z [copy purple]\n    .b configure -foreground $z\n    set result {}\n    lappend result [testcolor purple]\n    set x red\n    lappend result [testcolor purple]\n    set z 32\n    lappend result [testcolor purple]\n    destroy .b\n    lappend result [testcolor purple]\n    set y bogus\n    set result\n} -cleanup {\n    rename copy {}\n} -result {{{1 3}} {{1 2}} {{1 1}} {}}\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .t\ntestutils forget colors\ncleanupTests\n"
  },
  {
    "path": "tests/config.test",
    "content": "# This file is a Tcl script to test the procedures in tkConfig.c,\n# which comprise the new new option configuration system.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc killTables {} {\n    # Note: it's important to delete chain2 before chain1, because\n    # chain2 depends on chain1.  If chain1 is deleted first, the\n    # delete of chain2 will crash.\n    deleteWindows\n    foreach t {alltypes chain3 chain2 chain1 configerror internal\n\t    new notenoughparams twowindows} {\n\t    while {[testobjconfig info $t] ne \"\"} {\n\t\ttestobjconfig delete $t\n\t    }\n    }\n}\n\n#\n# TESTS\n#\n\n#\n# COMMON TEST SETUP\n#\noption clear\ndeleteWindows\nif {[testConstraint testobjconfig]} {\n    killTables\n}\n\ntest config-1.1 {Tk_CreateOptionTable - reference counts} -constraints {\n\ttestobjconfig\n} -body {\n    set x {}\n    testobjconfig alltypes .a\n    lappend x [testobjconfig info alltypes]\n    testobjconfig alltypes .b\n    lappend x [testobjconfig info alltypes]\n    set x\n} -cleanup {\n    killTables\n} -result {{1 17 -boolean} {2 17 -boolean}}\ntest config-1.2 {Tk_CreateOptionTable - synonym initialization} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a -synonym green\n    .a cget -color\n} -cleanup {\n    killTables\n} -result green\ntest config-1.3 {Tk_CreateOptionTable - option database initialization} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    option add *b.string different\n    testobjconfig alltypes .b\n    list [.a cget -string] [.b cget -string]\n} -cleanup {\n    killTables\n    option clear\n} -result {foo different}\ntest config-1.4 {Tk_CreateOptionTable - option database initialization} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    option add *b.String bar\n    testobjconfig alltypes .b\n    list [.a cget -string] [.b cget -string]\n} -cleanup {\n    killTables\n    option clear\n} -result {foo bar}\ntest config-1.5 {Tk_CreateOptionTable - default initialization} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    .a cget -anchor\n} -cleanup {\n    killTables\n} -result center\ntest config-1.6 {Tk_CreateOptionTable - chained tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain1 .a\n    testobjconfig chain2 .b\n    testobjconfig info chain2\n} -cleanup {\n    killTables\n} -result {1 4 -three 2 2 -one}\ntest config-1.7 {Tk_CreateOptionTable - chained tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .b\n    testobjconfig chain1 .a\n    testobjconfig info chain2\n} -cleanup {\n    killTables\n} -result {1 4 -three 2 2 -one}\ntest config-1.8 {Tk_CreateOptionTable - chained tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain1 .a\n    testobjconfig chain2 .b\n    .a cget -four\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown option \"-four\"}\ntest config-1.9 {Tk_CreateOptionTable - chained tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain1 .a\n    testobjconfig chain2 .b\n    catch {.a cget -four}\n    list [.a cget -one] [.b cget -four] [.b cget -one]\n} -cleanup {\n    killTables\n} -result {one four one}\n\n\ntest config-2.1 {Tk_DeleteOptionTable - reference counts} -constraints {\n    testobjconfig\n} -body {\n    set x {}\n    testobjconfig chain1 .a\n    testobjconfig chain2 .b\n    testobjconfig chain3 .c\n    deleteWindows\n    testobjconfig delete chain3\n    lappend x [testobjconfig info chain2] [testobjconfig info chain1]\n    testobjconfig delete chain2\n    lappend x [testobjconfig info chain2] [testobjconfig info chain1]\n} -cleanup {\n    killTables\n} -result {{3 4 -three 2 2 -one} {2 2 -one} {} {2 2 -one}}\n\ntest config-3.1 {Tk_InitOptions - priority of chained tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain1 .a\n    testobjconfig chain2 .b\n    list [.a cget -two] [.b cget -two]\n} -cleanup {\n    killTables\n} -result {two {two and a half}}\ntest config-3.2 {Tk_InitOptions - initialize from database} -constraints {\n    testobjconfig\n} -body {\n    option add *a.color blue\n    testobjconfig alltypes .a\n    list [.a cget -color]\n} -cleanup {\n    killTables\n    option clear\n} -result blue\ntest config-3.3 {Tk_InitOptions - initialize from database} -constraints {\n    testobjconfig\n} -body {\n    option add *a.justify bogus\n    testobjconfig alltypes .a\n    list [.a cget -justify]\n} -cleanup {\n    killTables\n    option clear\n} -result left\ntest config-3.4 {Tk_InitOptions - initialize from widget class} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    list [.a cget -color]\n} -cleanup {\n    killTables\n} -result red\ntest config-3.5 {Tk_InitOptions - no initial value} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    .a cget -relief\n} -cleanup {\n    killTables\n} -result {}\ntest config-3.6 {Tk_InitOptions - bad initial value} -constraints {\n    testobjconfig\n} -body {\n    option add *a.color non-existent\n    testobjconfig alltypes .a\n} -cleanup {\n    killTables\n    option clear\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest config-3.7 {Tk_InitOptions - bad initial value} -constraints {\n    testobjconfig\n} -body {\n    option add *a.color non-existent\n    catch {testobjconfig alltypes .a}\n    return $errorInfo\n} -cleanup {\n    killTables\n    option clear\n} -result {unknown color name \"non-existent\"\n    (database entry for \"-color\" in widget \".a\")\n    invoked from within\n\"testobjconfig alltypes .a\"}\n\ntest config-3.8 {Tk_InitOptions - bad initial value} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig configerror\n} -returnCodes error -result {expected integer or \"\" but got \"bogus\"}\ntest config-3.9 {Tk_InitOptions - bad initial value} -constraints {\n    testobjconfig\n} -body {\n    catch {testobjconfig configerror}\n    return $errorInfo\n} -result {expected integer or \"\" but got \"bogus\"\n    (default value for \"-int\")\n    invoked from within\n\"testobjconfig configerror\"}\n\ntest config-4.1 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 0\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.2 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 0\n    .foo cget -boolean\n} -cleanup {\n    killTables\n} -returnCodes ok -result 0\ntest config-4.3 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 0\n    .foo cget -boolean\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.4 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 1\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.5 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 1\n    .foo cget -boolean\n} -cleanup {\n    killTables\n} -returnCodes ok -result 1\ntest config-4.6 {DoObjConfig - boolean} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean 1\n    .foo cget -boolean\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.7 {DoObjConfig - invalid boolean} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -boolean foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {expected boolean value or \"\" but got \"foo\"}\ntest config-4.8 {DoObjConfig - boolean internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -boolean 0\n    .foo cget -boolean\n} -cleanup {\n    killTables\n} -result 0\n\ntest config-4.9 {DoObjConfig - integer} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -integer 3\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.10 {DoObjConfig - integer} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -integer 3\n    .foo cget -integer\n} -cleanup {\n    killTables\n} -returnCodes ok -result 3\ntest config-4.11 {DoObjConfig - integer} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -integer 3\n    .foo cget -integer\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.12 {DoObjConfig - invalid integer} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -integer bar\n} -cleanup {\n    killTables\n} -cleanup {\n    killTables\n} -returnCodes error -result {expected integer but got \"bar\"}\ntest config-4.13 {DoObjConfig - integer internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -integer 421\n    .foo cget -integer\n} -cleanup {\n    killTables\n} -result 421\n\ntest config-4.14 {DoObjConfig - double} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -double 3.14\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.15 {DoObjConfig - double} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -double 3.14\n    .foo cget -double\n} -cleanup {\n    killTables\n} -returnCodes ok -result 3.14\ntest config-4.16 {DoObjConfig - double} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -double 3.14\n    .foo cget -double\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.17 {DoObjConfig - invalid double} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -double bar\n} -cleanup {\n    killTables\n} -returnCodes error -result {expected floating-point number but got \"bar\"}\ntest config-4.18 {DoObjConfig - double internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -double 62.75\n    .foo cget -double\n} -cleanup {\n    killTables\n} -result 62.75\n\ntest config-4.19 {DoObjConfig - string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string test\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.20 {DoObjConfig - string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string test\n    .foo cget -string\n} -cleanup {\n    killTables\n} -returnCodes ok -result test\ntest config-4.21 {DoObjConfig - string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string test\n    .foo cget -string\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.22 {DoObjConfig - null string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.23 {DoObjConfig - null string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string {}\n    .foo cget -string\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.24 {DoObjConfig - null string} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -string {}\n    .foo cget -string\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\n\ntest config-4.25 {DoObjConfig - string internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -string \"this is a test\"\n    .foo cget -string\n} -cleanup {\n    killTables\n} -result {this is a test}\n\ntest config-4.26 {DoObjConfig - string table} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -stringtable two\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.27 {DoObjConfig - string table} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -stringtable two\n    .foo cget -stringtable\n} -cleanup {\n    killTables\n} -returnCodes ok -result two\ntest config-4.28 {DoObjConfig - string table} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -stringtable two\n    .foo cget -stringtable\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.29 {DoObjConfig - invalid string table} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -stringtable foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad stringtable \"foo\": must be one, two, three, four, or \"\"}\ntest config-4.29a {DoObjConfig - invalid string table} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -stringtable2 foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad stringtable2 \"foo\": must be one, two, or \"\"}\ntest config-4.30 {DoObjConfig - new string table} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -stringtable two\n    .foo configure -stringtable three\n} -cleanup {\n    killTables\n} -returnCodes ok -result 16\ntest config-4.31 {DoObjConfig - new string table} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -stringtable two\n    .foo configure -stringtable three\n    .foo cget -stringtable\n} -cleanup {\n    killTables\n} -returnCodes ok -result three\ntest config-4.32 {DoObjConfig - new string table} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -stringtable two\n    .foo configure -stringtable three\n    .foo cget -stringtable\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.33 {DoObjConfig - stringtable internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -stringtable \"four\"\n    .foo cget -stringtable\n} -cleanup {\n    killTables\n} -result four\n\ntest config-4.34 {DoObjConfig - color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color blue\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.35 {DoObjConfig - color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color blue\n    .foo cget -color\n} -cleanup {\n    killTables\n} -returnCodes ok -result blue\ntest config-4.36 {DoObjConfig - color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color blue\n    .foo cget -color\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.37 {DoObjConfig - invalid color} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color xxx\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown color name \"xxx\"}\ntest config-4.38 {DoObjConfig - color internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -color purple\n    .foo cget -color\n} -cleanup {\n    killTables\n} -result purple\n\ntest config-4.39 {DoObjConfig - null color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.40 {DoObjConfig - null color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color {}\n    .foo cget -color\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.41 {DoObjConfig - null color} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -color {}\n    .foo cget -color\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\ntest config-4.42 {DoObjConfig - getting rid of old color} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color #333333\n    .foo configure -color #444444\n} -cleanup {\n    killTables\n} -returnCodes ok -result 32\ntest config-4.43 {DoObjConfig - getting rid of old color} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color #333333\n    .foo configure -color #444444\n    .foo cget -color\n} -cleanup {\n    killTables\n} -returnCodes ok -result {#444444}\ntest config-4.44 {DoObjConfig - getting rid of old color} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color #333333\n    .foo configure -color #444444\n    .foo cget -color\n    rename .foo {}\n} -cleanup {\n    killTables\n} -returnCodes ok\n\ntest config-4.45 {DoObjConfig - font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {Helvetica 72}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.46 {DoObjConfig - font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {Helvetica 72}\n    .foo cget -font\n} -cleanup {\n    killTables\n} -returnCodes ok -result {Helvetica 72}\ntest config-4.47 {DoObjConfig - new font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {Courier 12}\n    .foo configure -font {Helvetica 72}\n} -cleanup {\n    killTables\n} -returnCodes ok -result 64\ntest config-4.48 {DoObjConfig - new font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {Courier 12}\n    .foo configure -font {Helvetica 72}\n    .foo cget -font\n} -cleanup {\n    killTables\n} -returnCodes ok -result {Helvetica 72}\ntest config-4.49 {DoObjConfig - invalid font} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {Helvetica 12 foo}\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown font style \"foo\"}\ntest config-4.50 {DoObjConfig - null font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.51 {DoObjConfig - null font} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -font {}\n    .foo cget -font\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.52 {DoObjConfig - font internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -font {Times 16}\n    .foo cget -font\n} -cleanup {\n    killTables\n} -result {Times 16}\n\ntest config-4.53 {DoObjConfig - bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap gray75\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.54 {DoObjConfig - bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap gray75\n    .foo cget -bitmap\n} -cleanup {\n    killTables\n} -returnCodes ok -result gray75\ntest config-4.55 {DoObjConfig - new bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap gray75\n    .foo configure -bitmap gray50\n} -cleanup {\n    killTables\n} -returnCodes ok -result 128\ntest config-4.56 {DoObjConfig - new bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap gray75\n    .foo configure -bitmap gray50\n    .foo cget -bitmap\n} -cleanup {\n    killTables\n} -returnCodes ok -result gray50\ntest config-4.57 {DoObjConfig - invalid bitmap} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -bitmap foobar\n} -cleanup {\n    killTables\n} -returnCodes error -result {bitmap \"foobar\" not defined}\ntest config-4.58 {DoObjConfig - null bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.59 {DoObjConfig - null bitmap} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -bitmap {}\n    .foo cget -bitmap\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.60 {DoObjConfig - bitmap internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -bitmap gray25\n    .foo cget -bitmap\n} -cleanup {\n    killTables\n} -result gray25\n\ntest config-4.61 {DoObjConfig - border} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -border green\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.62 {DoObjConfig - border} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -border green\n    .foo cget -border\n} -cleanup {\n    killTables\n} -returnCodes ok -result green\ntest config-4.63 {DoObjConfig - invalid border} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -border xxx\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown color name \"xxx\"}\ntest config-4.64 {DoObjConfig - null border} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -border {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.65 {DoObjConfig - null border} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -border {}\n    .foo cget -border\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.66 {DoObjConfig - border internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -border #123456\n    .foo cget -border\n} -cleanup {\n    killTables\n} -result {#123456}\ntest config-4.67 {DoObjConfig - getting rid of old border} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -border #333333\n    .foo configure -border #444444\n} -cleanup {\n    killTables\n} -returnCodes ok -result 256\ntest config-4.68 {DoObjConfig - getting rid of old border} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -border #333333\n    .foo configure -border #444444\n    .foo cget -border\n} -cleanup {\n    killTables\n} -returnCodes ok -result {#444444}\n\ntest config-4.69 {DoObjConfig - relief} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -relief flat\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.70 {DoObjConfig - relief} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -relief flat\n    .foo cget -relief\n} -cleanup {\n    killTables\n} -returnCodes ok -result flat\ntest config-4.71 {DoObjConfig - invalid relief} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -relief foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad relief \"foo\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\ntest config-4.72 {DoObjConfig - relief internal value} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -relief ridge\n    .foo cget -relief\n} -cleanup {\n    killTables\n} -result ridge\ntest config-4.73 {DoObjConfig - new relief} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -relief raised\n    .foo configure -relief flat\n} -cleanup {\n    killTables\n} -returnCodes ok -result 512\ntest config-4.74 {DoObjConfig - new relief} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -relief raised\n    .foo configure -relief flat\n    .foo cget -relief\n} -cleanup {\n    killTables\n} -returnCodes ok -result flat\n\ntest config-4.75 {DoObjConfig - cursor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -cursor arrow\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.76 {DoObjConfig - cursor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -cursor arrow\n    .foo cget -cursor\n} -cleanup {\n    killTables\n} -returnCodes ok -result arrow\ntest config-4.77 {DoObjConfig - invalid cursor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -cursor foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad cursor spec \"foo\"}\ntest config-4.78 {DoObjConfig - null cursor} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -cursor {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.79 {DoObjConfig - null cursor} -constraints testobjconfig -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig alltypes .foo -cursor {}\n    .foo cget -cursor\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.80 {DoObjConfig - new cursor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -cursor xterm\n    .foo configure -cursor arrow\n} -cleanup {\n    killTables\n} -returnCodes ok -result 1024\ntest config-4.81 {DoObjConfig - new cursor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -cursor xterm\n    .foo configure -cursor arrow\n    .foo cget -cursor\n} -cleanup {\n    killTables\n} -returnCodes ok -result arrow\ntest config-4.82 {DoObjConfig - cursor internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -cursor watch\n    .foo cget -cursor\n} -cleanup {\n    killTables\n} -result watch\n\ntest config-4.83 {DoObjConfig - justify} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -justify center\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.84 {DoObjConfig - justify} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -justify center\n    .foo cget -justify\n} -cleanup {\n    killTables\n} -returnCodes ok -result center\ntest config-4.85 {DoObjConfig - invalid justify} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -justify foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad justification \"foo\": must be left, right, center, or \"\"}\ntest config-4.86 {DoObjConfig - new justify} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -justify left\n    .foo configure -justify right\n} -cleanup {\n    killTables\n} -returnCodes ok -result 2048\ntest config-4.87 {DoObjConfig - new justify} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -justify left\n    .foo configure -justify right\n    .foo cget -justify\n} -cleanup {\n    killTables\n} -returnCodes ok -result right\ntest config-4.88 {DoObjConfig - justify internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -justify center\n    .foo cget -justify\n} -cleanup {\n    killTables\n} -result center\n\ntest config-4.89 {DoObjConfig - anchor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -anchor center\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.90 {DoObjConfig - anchor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -anchor center\n    .foo cget -anchor\n} -cleanup {\n    killTables\n} -returnCodes ok -result center\ntest config-4.91 {DoObjConfig - invalid anchor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -anchor foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad anchor \"foo\": must be n, ne, e, se, s, sw, w, nw, center, or \"\"}\ntest config-4.92 {DoObjConfig - new anchor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -anchor e\n    .foo configure -anchor n\n} -cleanup {\n    killTables\n} -returnCodes ok -result 4096\ntest config-4.93 {DoObjConfig - new anchor} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -anchor e\n    .foo configure -anchor n\n    .foo cget -anchor\n} -cleanup {\n    killTables\n} -returnCodes ok -result n\ntest config-4.94 {DoObjConfig - anchor internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -anchor sw\n    .foo cget -anchor\n} -cleanup {\n    killTables\n} -result sw\ntest config-4.95 {DoObjConfig - pixel} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -pixel 42\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.96 {DoObjConfig - pixel} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -pixel 42\n    .foo cget -pixel\n} -cleanup {\n    killTables\n} -returnCodes ok -result 42\ntest config-4.97 {DoObjConfig - invalid pixel} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -pixel foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {expected screen distance or \"\" but got \"foo\"}\ntest config-4.98 {DoObjConfig - new pixel} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -pixel 42m\n    .foo configure -pixel 3c\n} -cleanup {\n    killTables\n} -returnCodes ok -result 8192\ntest config-4.99 {DoObjConfig - new pixel} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -pixel 42m\n    .foo configure -pixel 3c\n    .foo cget -pixel\n} -cleanup {\n    killTables\n} -returnCodes ok -result 3c\ntest config-4.100 {DoObjConfig - pixel internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -pixel [winfo screenmmwidth .]m\n    set screenW [winfo screenwidth .]\n    set result [.foo cget -pixel]\n    expr {$screenW eq $result}\n} -cleanup {\n    killTables\n} -result 1\n\ntest config-4.101 {DoObjConfig - window} -constraints testobjconfig -body {\n    toplevel .bar\n    testobjconfig twowindows .foo -window .bar\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.102 {DoObjConfig - window} -constraints testobjconfig -body {\n    toplevel .bar\n    testobjconfig twowindows .foo -window .bar\n    .foo cget -window\n} -cleanup {\n    killTables\n} -returnCodes ok -result .bar\ntest config-4.103 {DoObjConfig - invalid window} -constraints testobjconfig -body {\n    toplevel .bar\n    testobjconfig twowindows .foo -window foo\n} -cleanup {\n    killTables\n} -returnCodes error -result {bad window path name \"foo\"}\ntest config-4.104 {DoObjConfig - null window} -constraints testobjconfig -body {\n    toplevel .bar\n    testobjconfig twowindows .foo -window {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.105 {DoObjConfig - null window} -constraints testobjconfig -body {\n    toplevel .bar\n    testobjconfig twowindows .foo -window {}\n    .foo cget -window\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.106 {DoObjConfig - new window} -constraints testobjconfig -body {\n    toplevel .bar\n    toplevel .blamph\n    testobjconfig twowindows .foo -window .bar\n    .foo configure -window .blamph\n} -cleanup {\n    killTables\n} -returnCodes ok -result 0\ntest config-4.107 {DoObjConfig - new window} -constraints testobjconfig -body {\n    toplevel .bar\n    toplevel .blamph\n    testobjconfig twowindows .foo -window .bar\n    .foo configure -window .blamph\n    .foo cget -window\n} -cleanup {\n    killTables\n} -returnCodes ok -result .blamph\ntest config-4.108 {DoObjConfig - window internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -window .\n    .foo cget -window\n} -cleanup {\n    killTables\n} -result .\n\ntest config-4.109 {DoObjConfig - releasing old values} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    # This test doesn't generate a useful value to check; if an\n    # error occurs, it will be detected only by memory checking software\n    # such as Purify or Tcl's built-in checker.\n\n    testobjconfig alltypes .foo -string {Test string} -color yellow \\\n\t    -font {Courier 18} -bitmap questhead -border green -cursor cross \\\n\t    -custom foobar\n    .foo configure -string {new string} -color brown \\\n\t    -font {Times 8} -bitmap gray75 -border pink -cursor watch \\\n\t    -custom barbaz\n    concat {}\n} -cleanup {\n    killTables\n} -result {}\ntest config-4.110 {DoObjConfig - releasing old values} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    # This test doesn't generate a useful value to check; if an\n    # error occurs, it will be detected only by memory checking software\n    # such as Purify or Tcl's built-in checker.\n\n    testobjconfig internal .foo -string {Test string} -color yellow \\\n\t    -font {Courier 18} -bitmap questhead -border green -cursor cross \\\n\t    -custom foobar\n    .foo configure -string {new string} -color brown \\\n\t    -font {Times 8} -bitmap gray75 -border pink -cursor watch \\\n\t    -custom barbaz\n    concat {}\n} -cleanup {\n    killTables\n} -result {}\n\ntest config-4.111 {DoObjConfig - custom} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -custom test\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.112 {DoObjConfig - custom} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -custom test\n    .foo cget -custom\n} -cleanup {\n    killTables\n} -returnCodes ok -result TEST\ntest config-4.113 {DoObjConfig - null custom} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -custom {}\n} -cleanup {\n    killTables\n} -returnCodes ok -result .foo\ntest config-4.114 {DoObjConfig - null custom} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo -custom {}\n    .foo cget -custom\n} -cleanup {\n    killTables\n} -returnCodes ok -result {}\ntest config-4.115 {DoObjConfig - custom internal value} -constraints {\n    testobjconfig\n} -setup {\n    catch {rename .foo {}}\n} -body {\n    testobjconfig internal .foo -custom \"this is a test\"\n    .foo cget -custom\n} -cleanup {\n    killTables\n}  -result {THIS IS A TEST}\n\n\ntest config-5.1 {TkObjIsEmpty - object is already string} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color [format \"\"]\n    .foo cget -color\n} -cleanup {\n    killTables\n}  -result {}\ntest config-5.2 {TkObjIsEmpty - object is already string} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color [format \" \"]\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown color name \" \"}\ntest config-5.3 {TkObjIsEmpty - must convert back to string} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -color [list]\n    .foo cget -color\n} -cleanup {\n    killTables\n} -result {}\n\n\ntest config-6.1 {GetOptionFromObj - cached answer} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .a\n    list [.a cget -three] [.a cget -three]\n} -cleanup {\n    killTables\n} -result {three three}\ntest config-6.2 {GetOptionFromObj - exact match} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .a\n    .a cget -one\n} -cleanup {\n    killTables\n} -result one\ntest config-6.3 {GetOptionFromObj - abbreviation} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .a\n    .a cget -fo\n} -cleanup {\n    killTables\n} -result four\ntest config-6.4 {GetOptionFromObj - ambiguous abbreviation} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .a\n    .a cget -on\n} -cleanup {\n    killTables\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown option \"-on\"}\ntest config-6.5 {GetOptionFromObj - duplicate options in different tables} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig chain2 .a\n    .a cget -tw\n} -cleanup {\n    killTables\n} -result {two and a half}\ntest config-6.6 {GetOptionFromObj - synonym} -constraints testobjconfig -body {\n    testobjconfig alltypes .b\n    .b cget -synonym\n} -cleanup {\n    killTables\n} -result red\n\n#\n# COMMON TEST SETUP\n#\nif {[testConstraint testobjconfig]} {\n    testobjconfig alltypes .a\n}\n\ntest config-7.1 {Tk_SetOptions - basics} -constraints testobjconfig -body {\n    .a configure -color green -rel sunken\n     list [.a cget -color] [.a cget -relief]\n} -result {green sunken}\ntest config-7.2 {Tk_SetOptions - bogus option name} -constraints {\n    testobjconfig\n} -body {\n    .a configure -bogus\n} -returnCodes error -result {unknown option \"-bogus\"}\ntest config-7.3 {Tk_SetOptions - synonym} -constraints testobjconfig -body {\n    .a configure -synonym blue\n    .a cget -color\n} -result blue\ntest config-7.4 {Tk_SetOptions - missing value} -constraints {\n    testobjconfig\n} -body {\n    .a configure -color green -relief\n} -returnCodes error -result {value for \"-relief\" missing}\ntest config-7.5 {Tk_SetOptions - missing value} -constraints {\n    testobjconfig\n} -body {\n    catch {.a configure -color green -relief}\n    .a cget -color\n} -result green\ntest config-7.6 {Tk_SetOptions - saving old values} -constraints {\n    testobjconfig\n} -body {\n    .a configure -color red -int 7 -relief raised -double 3.14159\n    .a csave -color green -int 432 -relief sunken -double 2.0 -color bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest config-7.7 {Tk_SetOptions - saving old values} -constraints {\n    testobjconfig\n} -body {\n    .a configure -color red -int 7 -relief raised -double 3.14159\n    catch {.a csave -color green -int 432 -relief sunken -double 2.0 -color bogus}\n    list [.a cget -color] [.a cget -int] [.a cget -relief] [.a cget -double]\n} -result {red 7 raised 3.14159}\n\ntest config-7.8 {Tk_SetOptions - error in DoObjConfig call} -constraints {\n    testobjconfig\n} -body {\n    .a configure -color bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest config-7.9 {Tk_SetOptions - error in DoObjConfig call} -constraints {\n    testobjconfig\n} -body {\n    catch {.a configure -color bogus}\n    return $errorInfo\n} -result {unknown color name \"bogus\"\n    (processing \"-color\" option)\n    invoked from within\n\".a configure -color bogus\"}\n\ntest config-7.10 {Tk_SetOptions - synonym name in error message} -constraints {\n    testobjconfig\n} -body {\n    .a configure -synonym bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest config-7.11 {Tk_SetOptions - synonym name in error message} -constraints {\n    testobjconfig\n} -body {\n    catch {.a configure -synonym bogus}\n    return $errorInfo\n} -result {unknown color name \"bogus\"\n    (processing \"-synonym\" option)\n    invoked from within\n\".a configure -synonym bogus\"}\ntest config-7.12 {Tk_SetOptions - returning mask} -constraints testobjconfig -body {\n    format %x [.a configure -color red -int 7 -relief raised -double 3.14159]\n} -result 226\ntest config-7.13 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {\n    testobjconfig\n} -body {\n    .a configure -custom bad\n} -returnCodes error -result {expected good value, got \"BAD\"}\ntest config-7.14 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {\n    testobjconfig\n} -body {\n    catch {.a configure -custom bad}\n    return $errorInfo\n} -result {expected good value, got \"BAD\"\n    (processing \"-custom\" option)\n    invoked from within\n\".a configure -custom bad\"}\n\n#\n# COMMON TEST CLEANUP\n#\nif {[testConstraint testobjconfig]} {\n    killTables\n}\n\ntest config-8.1 {Tk_RestoreSavedOptions - restore in proper order} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    .a csave -color green -color black -color blue \\\n\t-color #ffff00 -color #ff00ff -color bogus \\\n} -cleanup {\n    killTables\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest config-8.2 {Tk_RestoreSavedOptions - restore in proper order} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    catch {.a csave -color green -color black -color blue \\\n\t    -color #ffff00 -color #ff00ff -color bogus}\n\t.a cget -color\n} -cleanup {\n    killTables\n} -result red\ntest config-8.3 {Tk_RestoreSavedOptions - freeing object memory} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .a\n    .a csave -color green -color black -color blue -color #ffff00 -color #ff00ff\n} -cleanup {\n    killTables\n} -result 32\ntest config-8.4 {Tk_RestoreSavedOptions - boolean internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    .a csave -boolean 0 -color bogus\n} -cleanup {\n    killTables\n} -returnCodes error -match glob -result *\ntest config-8.5 {Tk_RestoreSavedOptions - boolean internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -boolean 0 -color bogus}\n    .a cget -boolean\n} -cleanup {\n    killTables\n} -result 1\ntest config-8.6 {Tk_RestoreSavedOptions - integer internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    .a csave -integer 24 -color bogus\n} -cleanup {\n    killTables\n} -returnCodes error -match glob -result *\ntest config-8.7 {Tk_RestoreSavedOptions - integer internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -integer 24 -color bogus}\n    .a cget -integer\n} -cleanup {\n    killTables\n} -result 148962237\ntest config-8.8 {Tk_RestoreSavedOptions - double internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -double 62.4 -color bogus}\n    .a cget -double\n} -cleanup {\n    killTables\n} -result 3.14159\ntest config-8.9 {Tk_RestoreSavedOptions - string internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -string \"A long string\" -color bogus}\n\t.a cget -string\n} -cleanup {\n    killTables\n} -result foo\ntest config-8.10 {Tk_RestoreSavedOptions - string table internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -stringtable three -color bogus}\n\t.a cget -stringtable\n} -cleanup {\n    killTables\n} -result one\ntest config-8.11 {Tk_RestoreSavedOptions - color internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -color green -color bogus}\n    .a cget -color\n} -cleanup {\n    killTables\n} -result red\ntest config-8.12 {Tk_RestoreSavedOptions - font internal form} -constraints {\n    testobjconfig nonPortable\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -font {Times 12} -color bogus}\n    .a cget -font\n} -cleanup {\n    killTables\n} -result {Helvetica 12}\ntest config-8.13 {Tk_RestoreSavedOptions - bitmap internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -bitmap questhead -color bogus}\n    .a cget -bitmap\n} -cleanup {\n    killTables\n} -result gray50\ntest config-8.14 {Tk_RestoreSavedOptions - border internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -border brown -color bogus}\n    .a cget -border\n} -cleanup {\n    killTables\n} -result blue\ntest config-8.15 {Tk_RestoreSavedOptions - anchor internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -anchor e -color bogus}\n    .a cget -anchor\n} -cleanup {\n    killTables\n} -result center\ntest config-8.16 {Tk_RestoreSavedOptions - cursor internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -cursor watch -color bogus}\n    .a cget -cursor\n} -cleanup {\n    killTables\n} -result xterm\ntest config-8.17 {Tk_RestoreSavedOptions - justify internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -justify right -color bogus}\n    .a cget -justify\n} -cleanup {\n    killTables\n} -result left\ntest config-8.18 {Tk_RestoreSavedOptions - anchor internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a\n    catch {.a csave -anchor n -color bogus}\n    .a cget -anchor\n} -cleanup {\n    killTables\n} -result center\ntest config-8.19 {Tk_RestoreSavedOptions - window internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a -window .a\n    catch {.a csave -window .a -color bogus}\n    .a cget -window\n} -cleanup {\n    killTables\n} -result .a\ntest config-8.20 {Tk_RestoreSavedOptions - custom internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .a -custom \"foobar\"\n    catch {.a csave -custom \"barbaz\" -color bogus}\n    .a cget -custom\n} -cleanup {\n    killTables\n} -result FOOBAR\n\n# Most of the tests below will cause memory leakage if there is a\n# problem.  This may not be evident unless the tests are run in\n# conjunction with a memory usage analyzer such as Purify.\n\ntest config-9.1 {Tk_FreeConfigOptions/FreeResources - string internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -string \"two words\"\n    destroy .foo\n} -result {}\ntest config-9.2 {Tk_FreeConfigOptions/FreeResources - color internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -color yellow\n    destroy .foo\n} -result {}\ntest config-9.3 {Tk_FreeConfigOptions/FreeResources - color} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -color [format blue]\n    destroy .foo\n} -result {}\ntest config-9.4 {Tk_FreeConfigOptions/FreeResources - font internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -font {Courier 20}\n    destroy .foo\n} -result {}\ntest config-9.5 {Tk_FreeConfigOptions/FreeResources - font} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -font [format {Courier 24}]\n    destroy .foo\n} -result {}\ntest config-9.6 {Tk_FreeConfigOptions/FreeResources - bitmap internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -bitmap gray75\n    destroy .foo\n} -result {}\ntest config-9.7 {Tk_FreeConfigOptions/FreeResources - bitmap} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -bitmap [format gray75]\n    destroy .foo\n} -result {}\ntest config-9.8 {Tk_FreeConfigOptions/FreeResources - border internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -border orange\n    destroy .foo\n} -result {}\ntest config-9.9 {Tk_FreeConfigOptions/FreeResources - border} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -border [format blue]\n    destroy .foo\n} -result {}\ntest config-9.10 {Tk_FreeConfigOptions/FreeResources - cursor internal form} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig internal .foo\n    .foo configure -cursor cross\n    destroy .foo\n} -result {}\ntest config-9.11 {Tk_FreeConfigOptions/FreeResources - cursor} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -cursor [format watch]\n    destroy .foo\n} -result {}\ntest config-9.12 {Tk_FreeConfigOptions/FreeResources - not special} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -integer [format 27]\n    destroy .foo\n} -result {}\ntest config-9.13 {Tk_FreeConfigOptions/FreeResources - custom internal form} -constraints {\n    testobjconfig\n} -body {\n    catch {destroy .fpp}\n    testobjconfig internal .foo\n    .foo configure -custom \"foobar\"\n    destroy .foo\n} -result {}\n\n#\n# COMMON TEST CLEANUP\n#\nif {[testConstraint testobjconfig]} {\n    killTables\n}\n\ntest config-10.1 {Tk_GetOptionInfo - one item} -constraints testobjconfig -body {\n    testobjconfig alltypes .foo\n    .foo configure -anchor e\n    .foo configure -anchor\n} -cleanup {\n    destroy .foo\n} -result {-anchor anchor Anchor center e}\ntest config-10.2 {Tk_GetOptionInfo - one item, synonym} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo\n    .foo configure -color black\n    .foo configure -synonym\n} -cleanup {\n    destroy .foo\n} -result {-color color Color red black}\ntest config-10.3 {Tk_GetOptionInfo - all items} -constraints {\n    testobjconfig\n} -body {\n    testobjconfig alltypes .foo -font {Helvetica 18} -integer 13563\n    .foo configure\n} -cleanup {\n    destroy .foo\n} -result {{-boolean boolean Boolean {} {}} {-integer integer Integer 7 13563} {-double double Double 3.14159 3.14159} {-string string String foo foo} {-stringtable StringTable stringTable one one} {-stringtable2 StringTable2 stringTable2 two two} {-color color Color red red} {-font font Font {Helvetica 12} {Helvetica 18}} {-bitmap bitmap Bitmap gray50 gray50} {-border border Border blue blue} {-relief relief Relief {} {}} {-cursor cursor Cursor xterm xterm} {-justify {} {} left left} {-anchor anchor Anchor center center} {-pixel pixel Pixel 1 1} {-custom {} {} {} {}} {-synonym -color}}\ntest config-10.4 {Tk_GetOptionInfo - chaining through tables} -constraints testobjconfig -body {\n    testobjconfig chain2 .foo -one asdf -three xyzzy\n    .foo configure\n} -cleanup {\n    destroy .foo\n} -result {{-three three Three three xyzzy} {-four four Four four four} {-two two Two {two and a half} {two and a half}} {-oneAgain oneAgain OneAgain {one again} {one again}} {-one one One one asdf} {-two two Two two {two and a half}}}\n\n#\n# COMMON TEST SETUP\n#\nif {[testConstraint testobjconfig]} {\n    killTables\n    testobjconfig alltypes .a\n}\n\ntest config-11.1 {GetConfigList - synonym} -constraints testobjconfig -body {\n    lindex [.a configure] end\n} -result {-synonym -color}\ntest config-11.2 {GetConfigList - null database names} -constraints {\n    testobjconfig\n} -body {\n    .a configure -justify\n} -result {-justify {} {} left left}\ntest config-11.3 {GetConfigList - null default and current value} -constraints {\n    testobjconfig\n} -body {\n    .a configure -relief\n} -result {-relief relief Relief {} {}}\n\n#\n# COMMON TEST SETUP\n#\nif {[testConstraint testobjconfig]} {\n    killTables\n    testobjconfig internal .a\n}\n\ntest config-12.1 {GetObjectForOption - boolean} -constraints testobjconfig -body {\n    .a configure -boolean 0\n    .a cget -boolean\n} -result 0\ntest config-12.2 {GetObjectForOption - integer} -constraints testobjconfig -body {\n    .a configure -integer 1247\n    .a cget -integer\n} -result 1247\ntest config-12.3 {GetObjectForOption - double} -constraints testobjconfig -body {\n    .a configure -double -88.82\n    .a cget -double\n} -result {-88.82}\ntest config-12.4 {GetObjectForOption - string} -constraints testobjconfig -body {\n    .a configure -string \"test value\"\n    .a cget -string\n} -result {test value}\ntest config-12.5 {GetObjectForOption - stringTable} -constraints {\n    testobjconfig\n} -body {\n    .a configure -stringtable \"two\"\n    .a cget -stringtable\n} -result two\ntest config-12.6 {GetObjectForOption - color} -constraints testobjconfig -body {\n    .a configure -color \"green\"\n    .a cget -color\n} -result green\ntest config-12.7 {GetObjectForOption - font} -constraints testobjconfig -body {\n    .a configure -font {Times 36}\n    .a cget -font\n} -result {Times 36}\ntest config-12.8 {GetObjectForOption - bitmap} -constraints testobjconfig -body {\n    .a configure -bitmap \"questhead\"\n    .a cget -bitmap\n} -result questhead\ntest config-12.9 {GetObjectForOption - border} -constraints testobjconfig -body {\n    .a configure -border #33217c\n    .a cget -border\n} -result {#33217c}\ntest config-12.10 {GetObjectForOption - relief} -constraints {\n    testobjconfig\n} -body {\n    .a configure -relief groove\n    .a cget -relief\n} -result groove\ntest config-12.11 {GetObjectForOption - cursor} -constraints {\n    testobjconfig\n} -body {\n    .a configure -cursor watch\n    .a cget -cursor\n} -result watch\ntest config-12.12 {GetObjectForOption - justify} -constraints {\n    testobjconfig\n} -body {\n    .a configure -justify right\n    .a cget -justify\n} -result right\ntest config-12.13 {GetObjectForOption - anchor} -constraints testobjconfig -body {\n    .a configure -anchor e\n    .a cget -anchor\n} -result e\ntest config-12.14 {GetObjectForOption - pixels} -constraints testobjconfig -body {\n    .a configure -pixel 193.2\n    .a cget -pixel\n} -result 193\ntest config-12.15 {GetObjectForOption - window} -constraints testobjconfig -body {\n    .a configure -window .a\n    .a cget -window\n} -result .a\ntest config-12.16 {GetObjectForOption -custom} -constraints testobjconfig -body {\n    .a configure -custom foobar\n    .a cget -custom\n} -result FOOBAR\ntest config-12.17 {GetObjectForOption - null values} -constraints {\n    testobjconfig\n} -body {\n    .a configure -string {} -color {} -font {} -bitmap {} -border {} \\\n\t    -cursor {} -window {} -custom {}\n    list [.a cget -string] [.a cget -color] [.a cget -font] \\\n\t    [.a cget -bitmap] [.a cget -border] [.a cget -cursor] \\\n\t    [.a cget -window] [.a cget -custom]\n} -result {{} {} {} {} {} {} {} {}}\n\n#\n# COMMON TEST CLEANUP\n#\nif {[testConstraint testobjconfig]} {\n    killTables\n}\n\ntest config-13.1 {proper cleanup of options with widget destroy} -body {\n    button .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.2 {proper cleanup of options with widget destroy} -body {\n    canvas .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.3 {proper cleanup of options with widget destroy} -body {\n    entry .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.4 {proper cleanup of options with widget destroy} -body {\n    frame .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.5 {proper cleanup of options with widget destroy} -body {\n    listbox .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.6 {proper cleanup of options with widget destroy} -body {\n    menu .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.7 {proper cleanup of options with widget destroy} -body {\n    menubutton .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.8 {proper cleanup of options with widget destroy} -body {\n    message .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.9 {proper cleanup of options with widget destroy} -body {\n    scale .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.10 {proper cleanup of options with widget destroy} -body {\n    scrollbar .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.11 {proper cleanup of options with widget destroy} -body {\n    text .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.12 {proper cleanup of options with widget destroy} -body {\n    radiobutton .w -cursor crosshair\n    destroy .w\n} -result {}\ntest config-13.13 {proper cleanup of options with widget destroy} -body {\n    checkbutton .w -cursor crosshair\n    destroy .w\n} -result {}\n\ntest config-14.1 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::button\n\t::foo::button .a\n\t::foo::button .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.2 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::canvas\n\t::foo::canvas .a\n\t::foo::canvas .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.3 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::entry\n\t::foo::entry .a\n\t::foo::entry .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.4 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::frame\n\t::foo::frame .a\n\t::foo::frame .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.5 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::listbox\n\t::foo::listbox .a\n\t::foo::listbox .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.6 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::menu\n\t::foo::menu .a\n\t::foo::menu .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.7 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::menubutton\n\t::foo::menubutton .a\n\t::foo::menubutton .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.8 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::message\n\t::foo::message .a\n\t::foo::message .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.9 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::scale\n\t::foo::scale .a\n\t::foo::scale .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.10 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::scrollbar\n\t::foo::scrollbar .a\n\t::foo::scrollbar .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.11 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::spinbox\n\t::foo::spinbox .a\n\t::foo::spinbox .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.12 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::text\n\t::foo::text .a\n\t::foo::text .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.13 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::radiobutton\n\t::foo::radiobutton .a\n\t::foo::radiobutton .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\ntest config-14.14 {Tk_CreateOptionTable - use with namespace import} -setup {\n    namespace export -clear *\n} -body {\n    namespace eval ::foo [subst {\n\tnamespace import -force ::checkbutton\n\t::foo::checkbutton .a\n\t::foo::checkbutton .b\n\t}\n    ]\n    destroy .a .b\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\nif {[testConstraint testobjconfig]} {\n    killTables\n}\ncleanupTests\n"
  },
  {
    "path": "tests/constraints.tcl",
    "content": "# constraints.tcl --\n#\n# This file is sourced into each test file by \"main.tcl\". It defines test\n# constraints that are used by several test files in the Tk test suite.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nnamespace import -force tcltest::testConstraint\n\n#\n# OPERATING SYSTEM\n#\ntestConstraint failsOnCILinux [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]\nif {$tcl_platform(os) eq \"Darwin\"} {\n    scan $tcl_platform(osVersion) \"%d\" macosVersion\n}\ntestConstraint notMacosSequoiaOrOlder [expr {($tcl_platform(os) ne \"Darwin\") || ($macosVersion > 24)}]\nunset -nocomplain macosVersion\n\n#\n# WINDOWING SYSTEM AND DISPLAY\n#\ntestConstraint notAqua [expr {[tk windowingsystem] ne \"aqua\"}]\ntestConstraint aqua [expr {[tk windowingsystem] eq \"aqua\"}]\ntestConstraint x11 [expr {[tk windowingsystem] eq \"x11\"}]\ntestConstraint win32 [expr {[tk windowingsystem] eq \"win32\"}]\ntestConstraint aquaOrWin32 [expr {\n    ([tk windowingsystem] eq \"win32\") || [testConstraint aqua]\n}]\ntestConstraint haveDISPLAY [expr {[info exists env(DISPLAY)] && [testConstraint x11]}]\ntestConstraint altDisplay  [info exists env(TK_ALT_DISPLAY)]\n\n# constraint for running a test on all windowing system except aqua\n# where the test fails due to a known bug\ntestConstraint aquaKnownBug [expr {[testConstraint notAqua] || [testConstraint knownBug]}]\n\n# This constraint is for running an aqua test only when user interaction is\n# possible, not on a CI runner.  Some actions, such as writing to the\n# filesystem, require that the user review and dismiss a system dialog, which\n# cannot be done on a CI runner.\ntestConstraint notMacCI [expr {[testConstraint notAqua] || ![info exists ::env(CI)]}]\n\n# constraint based on whether our display is secure\ntestutils import child\nchildTkProcess create\nset app [childTkProcess eval {tk appname}]\ntestConstraint secureserver 0\nif {[llength [info commands send]]} {\n    testConstraint secureserver 1\n    if {[catch {send $app set a 0} msg] == 1} {\n\tif {[string match \"X server insecure *\" $msg]} {\n\t    testConstraint secureserver 0\n\t}\n    }\n}\nchildTkProcess exit\ntestutils forget child\n\ntestConstraint failsOnXQuartz [expr {$tcl_platform(os) ne \"Darwin\" || [tk windowingsystem] ne \"x11\" }]\n\n#\n# FONTS\n#\ntestConstraint fonts 1\ndestroy .e\nentry .e -width 0 -font {Helvetica -12} -bd 1 -highlightthickness 1\n.e insert end a.bcd\nif {([winfo reqwidth .e] != 37) || ([winfo reqheight .e] != 20)} {\n    testConstraint fonts 0\n}\ndestroy .e\ndestroy .t\ntext .t -width 80 -height 20 -font {Times -14} -bd 1\npack .t\n.t insert end \"This is\\na dot.\"\nupdate\nset x [list [.t bbox 1.3] [.t bbox 2.5]]\ndestroy .t\nif {![string match {{22 3 6 15} {31 18 [34] 15}} $x]} {\n    testConstraint fonts 0\n}\n\ntestConstraint withXft [expr {![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq \"xft\")}]\nunset fs\n\n# Expected results of some tests on Linux rely on availability of the \"times\"\n# font. This font is generally provided when Tk uses the old X font system,\n# but not when using Xft on top of fontconfig. Specifically (old system):\n#    xlsfonts | grep times\n# may return quite some output while (new system):\n#    fc-list | grep times\n# return value is empty. That's not surprising since the two font systems are\n# separate (availability of a font in one of them does not mean it's available\n# in the other one). The following constraints are useful in this kind of\n# situation.\ntestConstraint haveTimesFamilyFont [expr {\n    [string tolower [font actual {-family times} -family]] eq \"times\"\n}]\ntestConstraint haveFixedFamilyFont [expr {\n    [string tolower [font actual {-family fixed} -family]] eq \"fixed\"\n}]\n\n# Although unexpected, some systems may have a very limited set of fonts available.\n# The following constraints happen to evaluate to false at least on one system: the\n# Github CI runner for Linux with --disable-xft, which has exactly ONE single font\n# ([font families] returns a single element: \"fixed\"), for which [font actual]\n# returns:\n#    -family fixed -size 9 -weight normal -slant roman -underline 0\n# and [font metrics] returns:\n#    -ascent 11 -descent 2 -linespace 13 -fixed 1\n# The following constraints are hence tailored to check exactly what is needed in the\n# tests they constrain (that is: availability of any font having the given font\n# attributes), so that these constrained tests will in fact run on all systems having\n# reasonable font dotation.\ntestConstraint havePointsize37Font [expr {\n    [font actual {-family courier -size 37} -size] == 37\n}]\ntestConstraint havePointsize14BoldFont [expr {\n    ([font actual {times 14 bold} -size] == 14) &&\n    ([font actual {times 14 bold} -weight] eq \"bold\")\n}]\ntestConstraint haveBoldItalicUnderlineOverstrikeFont [expr {\n    ([font actual {times 12 bold italic overstrike underline} -weight] eq \"bold\") &&\n    ([font actual {times 12 bold italic overstrike underline} -slant] eq \"italic\") &&\n    ([font actual {times 12 bold italic overstrike underline} -underline] eq \"1\") &&\n    ([font actual {times 12 bold italic overstrike underline} -overstrike] eq \"1\")\n}]\nset fixedFont {Courier 12}   ; # warning: must be consistent with the files using the constraint below!\nset bigFont   {Helvetica 24} ; # ditto\ntestConstraint haveBigFontTwiceLargerThanTextFont [expr {\n    [font actual $fixedFont -size] * 2 <= [font actual $bigFont -size]\n}]\nunset fixedFont bigFont\n\n#\n# VISUALS\n#\ntestConstraint pseudocolor8 [expr {\n    ([catch {\n\ttoplevel .t -visual {pseudocolor 8} -colormap new\n    }] == 0) && ([winfo depth .t] == 8)\n}]\ndestroy .t\ntestConstraint haveTruecolor24 [expr {\n    {truecolor 24} in [winfo visualsavailable .]\n}]\ntestConstraint haveGrayscale8 [expr {\n    {grayscale 8} in [winfo visualsavailable .]\n}]\ntestConstraint defaultPseudocolor8 [expr {\n    ([winfo visual .] eq \"pseudocolor\") && ([winfo depth .] == 8)\n}]\n\n\n#\n# VARIOUS\n#\ntestConstraint nonUnixUserInteraction [expr {\n    [testConstraint userInteraction] ||\n    ([testConstraint unix] && [testConstraint notAqua])\n}]\n\ntestConstraint deprecated [expr {![::tk::build-info no-deprecate]}]\n\n# constraints for testing facilities defined in the tktest executable\ntestConstraint testbitmap      [llength [info commands testbitmap]]\ntestConstraint testborder      [llength [info commands testborder]]\ntestConstraint testcbind       [llength [info commands testcbind]]\ntestConstraint testclipboard   [llength [info commands testclipboard]]\ntestConstraint testcolor       [llength [info commands testcolor]]\ntestConstraint testcursor      [llength [info commands testcursor]]\ntestConstraint testembed       [llength [info commands testembed]]\ntestConstraint testfont        [llength [info commands testfont]]\ntestConstraint testImageType   [expr {\"test\" in [image types]}]\ntestConstraint testmakeexist   [llength [info commands testmakeexist]]\ntestConstraint testmenubar     [llength [info commands testmenubar]]\ntestConstraint testmetrics     [llength [info commands testmetrics]]\ntestConstraint testmovemouse   [llength [info commands testmovemouse]]\ntestConstraint testobjconfig   [llength [info commands testobjconfig]]\ntestConstraint testpressbutton [llength [info commands testpressbutton]]\ntestConstraint testsend        [llength [info commands testsend]]\ntestConstraint testtext        [llength [info commands testtext]]\ntestConstraint testwinevent    [llength [info commands testwinevent]]\ntestConstraint testwrapper     [llength [info commands testwrapper]]\n\n# EOF\n"
  },
  {
    "path": "tests/cursor.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkCursor.c.\n#\n# Copyright © 1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# Tests 2.3 and 2.4 need a helper file with a very specific name and\n# controlled format.\nproc setWincur {wincurName} {\n\tupvar $wincurName wincur\n\tset wincur(data_octal) {\n\t    000 000 002 000 001 000 040 040 000 000 007 000 007 000 060 001\n\t    000 000 026 000 000 000 050 000 000 000 040 000 000 000 100 000\n\t    000 000 001 000 001 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 377 377 377 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000\n\t    000 000 000 000 000 000 000 000 000 000 160 016 000 000 170 036\n\t    000 000 174 076 000 000 076 174 000 000 037 370 000 000 017 360\n\t    000 000 007 340 000 000 007 340 000 000 017 360 000 000 037 370\n\t    000 000 076 174 000 000 174 076 000 000 170 036 000 000 160 016\n\t    000 000 000 000 000 000 377 377 377 377 377 377 377 377 377 377\n\t    377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377\n\t    377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377\n\t    377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377\n\t    377 377 377 377 377 377 017 360 377 377 007 340 377 377 003 300\n\t    377 377 001 200 377 377 200 001 377 377 300 003 377 377 340 007\n\t    377 377 360 017 377 377 360 017 377 377 340 007 377 377 300 003\n\t    377 377 200 001 377 377 001 200 377 377 003 300 377 377 007 340\n\t    377 377 017 360 377 377\n\t}\n\tset wincur(data_binary) {}\n\tforeach wincur(num) $wincur(data_octal) {\n\t    append wincur(data_binary) [binary format c [scan $wincur(num) %o]]\n\t}\n\tset wincur(dir) [makeDirectory {dir with spaces}]\n\tset wincur(file) [makeFile $wincur(data_binary) \"test file.cur\" $wincur(dir)]\n}\n\n#\n# TESTS\n#\n\ntest cursor-1.1 {Tk_AllocCursorFromObj - converting internal reps} -constraints {\n    testcursor\n} -body {\n    set x watch\n    lindex $x 0\n    button .b -cursor $x\n    lindex $x 0\n    testcursor watch\n} -cleanup {\n    destroy .b\n} -result {{1 0}}\ntest cursor-1.2 {Tk_AllocCursorFromObj - discard stale cursor} -constraints {\n    testcursor\n} -body {\n    set x watch\n    set result {}\n    button .b1 -cursor $x\n    destroy .b1\n    lappend result [testcursor watch]\n    button .b2 -cursor $x\n    lappend result [testcursor watch]\n} -cleanup {\n    destroy .b2\n} -result {{} {{1 1}}}\ntest cursor-1.3 {Tk_AllocCursorFromObj - reuse existing cursor} -constraints {\n    testcursor\n} -body {\n    set x watch\n    set result {}\n    button .b1 -cursor $x\n    lappend result [testcursor watch]\n    button .b2 -cursor $x\n    pack .b1 .b2 -side top\n    lappend result [testcursor watch]\n} -cleanup {\n    destroy .b1 .b2\n} -result {{{1 1}} {{2 1}}}\n\ntest cursor-2.1 {Tk_GetCursor procedure} -body {\n    button .b -cursor bad_name\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad cursor spec \"bad_name\"}\ntest cursor-2.2 {Tk_GetCursor procedure} -body {\n    button .b -cursor @xyzzy\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad cursor spec \"@xyzzy\"}\n\ntest cursor-2.3 {Tk_GetCursor procedure: cursor specs are lists} -constraints {\n    win\n} -setup {\n\tunset -nocomplain wincur\n\tset wincur(file) \"\"\n} -body {\n\tsetWincur wincur\n    button .b -cursor [list @$wincur(file)]\n} -cleanup {\n    destroy .b\n\tremoveDirectory $wincur(dir)\n\tunset wincur\n} -result {.b}\ntest cursor-2.4 {Tk_GetCursor procedure: cursor specs are lists} -constraints {\n    win\n} -setup {\n\tunset -nocomplain wincur\n\tset wincur(file) \"\"\n} -body {\n\tsetWincur wincur\n    button .b -cursor @[regsub -all {[][ \\\\{}\"\"$#]} $wincur(file) {\\\\&}]\n} -cleanup {\n    destroy .b\n\tremoveDirectory $wincur(dir)\n\tunset wincur\n} -result {.b}\n\ntest cursor-3.1 {Tk_FreeCursorFromObj - reference counts} -constraints {\n    testcursor\n} -setup {\n    set x heart\n    set result {}\n} -body {\n    button .b1 -cursor $x\n    button .b3 -cursor $x\n    button .b2 -cursor $x\n    lappend result [testcursor heart]\n    destroy .b1\n    lappend result [testcursor heart]\n    destroy .b2\n    lappend result [testcursor heart]\n    destroy .b3\n    lappend result [testcursor heart]\n} -result {{{3 1}} {{2 1}} {{1 1}} {}}\n\ntest cursor-4.1 {FreeCursorObjProc} -constraints {\n    testcursor\n} -setup {\n    proc copy {s} {return [string index $s 0][string range $s 1 end]}\n} -body {\n    set x [copy heart]\n    button .b -cursor $x\n    set y [copy heart]\n    .b configure -cursor $y\n    set z [copy heart]\n    .b configure -cursor $z\n    set result {}\n    lappend result [testcursor heart]\n    set x red\n    lappend result [testcursor heart]\n    set z 32\n    lappend result [testcursor heart]\n    destroy .b\n    lappend result [testcursor heart]\n    set y bogus\n    set result\n} -cleanup {\n    rename copy {}\n    destroy .b\n} -result {{{1 3}} {{1 2}} {{1 1}} {}}\n\n# -------------------------------------------------------------------------\ntest cursor-5.1 {assert consistent cursor configuration command} -setup {\n    button .b\n} -body {\n    .b configure -cursor {watch red black}\n} -cleanup {\n    destroy .b\n} -result {}\n\n# -------------------------------------------------------------------------\n# Check for the standard set of cursors.\ntest cursor-6.1 {check cursor-font cursor X_cursor} -setup {\n\tbutton .b -text X_cursor\n} -body {\n\t.b configure -cursor X_cursor\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.2 {check cursor-font cursor arrow} -setup {\n\tbutton .b -text arrow\n} -body {\n\t.b configure -cursor arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.3 {check cursor-font cursor based_arrow_down} -setup {\n\tbutton .b -text based_arrow_down\n} -body {\n\t.b configure -cursor based_arrow_down\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.4 {check cursor-font cursor based_arrow_up} -setup {\n\tbutton .b -text based_arrow_up\n} -body {\n\t.b configure -cursor based_arrow_up\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.5 {check cursor-font cursor boat} -setup {\n\tbutton .b -text boat\n} -body {\n\t.b configure -cursor boat\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.6 {check cursor-font cursor bogosity} -setup {\n\tbutton .b -text bogosity\n} -body {\n\t.b configure -cursor bogosity\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.7 {check cursor-font cursor bottom_left_corner} -setup {\n\tbutton .b -text bottom_left_corner\n} -body {\n\t.b configure -cursor bottom_left_corner\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.8 {check cursor-font cursor bottom_right_corner} -setup {\n\tbutton .b -text bottom_right_corner\n} -body {\n\t.b configure -cursor bottom_right_corner\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.9 {check cursor-font cursor bottom_side} -setup {\n\tbutton .b -text bottom_side\n} -body {\n\t.b configure -cursor bottom_side\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.10 {check cursor-font cursor bottom_tee} -setup {\n\tbutton .b -text bottom_tee\n} -body {\n\t.b configure -cursor bottom_tee\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.11 {check cursor-font cursor box_spiral} -setup {\n\tbutton .b -text box_spiral\n} -body {\n\t.b configure -cursor box_spiral\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.12 {check cursor-font cursor center_ptr} -setup {\n\tbutton .b -text center_ptr\n} -body {\n\t.b configure -cursor center_ptr\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.13 {check cursor-font cursor circle} -setup {\n\tbutton .b -text circle\n} -body {\n\t.b configure -cursor circle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.14 {check cursor-font cursor clock} -setup {\n\tbutton .b -text clock\n} -body {\n\t.b configure -cursor clock\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.15 {check cursor-font cursor coffee_mug} -setup {\n\tbutton .b -text coffee_mug\n} -body {\n\t.b configure -cursor coffee_mug\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.16 {check cursor-font cursor cross} -setup {\n\tbutton .b -text cross\n} -body {\n\t.b configure -cursor cross\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.17 {check cursor-font cursor cross_reverse} -setup {\n\tbutton .b -text cross_reverse\n} -body {\n\t.b configure -cursor cross_reverse\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.18 {check cursor-font cursor crosshair} -setup {\n\tbutton .b -text crosshair\n} -body {\n\t.b configure -cursor crosshair\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.19 {check cursor-font cursor diamond_cross} -setup {\n\tbutton .b -text diamond_cross\n} -body {\n\t.b configure -cursor diamond_cross\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.20 {check cursor-font cursor dot} -setup {\n\tbutton .b -text dot\n} -body {\n\t.b configure -cursor dot\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.21 {check cursor-font cursor dotbox} -setup {\n\tbutton .b -text dotbox\n} -body {\n\t.b configure -cursor dotbox\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.22 {check cursor-font cursor double_arrow} -setup {\n\tbutton .b -text double_arrow\n} -body {\n\t.b configure -cursor double_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.23 {check cursor-font cursor draft_large} -setup {\n\tbutton .b -text draft_large\n} -body {\n\t.b configure -cursor draft_large\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.24 {check cursor-font cursor draft_small} -setup {\n\tbutton .b -text draft_small\n} -body {\n\t.b configure -cursor draft_small\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.25 {check cursor-font cursor draped_box} -setup {\n\tbutton .b -text draped_box\n} -body {\n\t.b configure -cursor draped_box\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.26 {check cursor-font cursor exchange} -setup {\n\tbutton .b -text exchange\n} -body {\n\t.b configure -cursor exchange\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.27 {check cursor-font cursor fleur} -setup {\n\tbutton .b -text fleur\n} -body {\n\t.b configure -cursor fleur\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.28 {check cursor-font cursor gobbler} -setup {\n\tbutton .b -text gobbler\n} -body {\n\t.b configure -cursor gobbler\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.29 {check cursor-font cursor gumby} -setup {\n\tbutton .b -text gumby\n} -body {\n\t.b configure -cursor gumby\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.30 {check cursor-font cursor hand1} -setup {\n\tbutton .b -text hand1\n} -body {\n\t.b configure -cursor hand1\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.31 {check cursor-font cursor hand2} -setup {\n\tbutton .b -text hand2\n} -body {\n\t.b configure -cursor hand2\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.32 {check cursor-font cursor heart} -setup {\n\tbutton .b -text heart\n} -body {\n\t.b configure -cursor heart\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.33 {check cursor-font cursor icon} -setup {\n\tbutton .b -text icon\n} -body {\n\t.b configure -cursor icon\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.34 {check cursor-font cursor iron_cross} -setup {\n\tbutton .b -text iron_cross\n} -body {\n\t.b configure -cursor iron_cross\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.35 {check cursor-font cursor left_ptr} -setup {\n\tbutton .b -text left_ptr\n} -body {\n\t.b configure -cursor left_ptr\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.36 {check cursor-font cursor left_side} -setup {\n\tbutton .b -text left_side\n} -body {\n\t.b configure -cursor left_side\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.37 {check cursor-font cursor left_tee} -setup {\n\tbutton .b -text left_tee\n} -body {\n\t.b configure -cursor left_tee\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.38 {check cursor-font cursor leftbutton} -setup {\n\tbutton .b -text leftbutton\n} -body {\n\t.b configure -cursor leftbutton\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.39 {check cursor-font cursor ll_angle} -setup {\n\tbutton .b -text ll_angle\n} -body {\n\t.b configure -cursor ll_angle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.40 {check cursor-font cursor lr_angle} -setup {\n\tbutton .b -text lr_angle\n} -body {\n\t.b configure -cursor lr_angle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.41 {check cursor-font cursor man} -setup {\n\tbutton .b -text man\n} -body {\n\t.b configure -cursor man\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.42 {check cursor-font cursor middlebutton} -setup {\n\tbutton .b -text middlebutton\n} -body {\n\t.b configure -cursor middlebutton\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.43 {check cursor-font cursor mouse} -setup {\n\tbutton .b -text mouse\n} -body {\n\t.b configure -cursor mouse\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.44 {check cursor-font cursor pencil} -setup {\n\tbutton .b -text pencil\n} -body {\n\t.b configure -cursor pencil\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.45 {check cursor-font cursor pirate} -setup {\n\tbutton .b -text pirate\n} -body {\n\t.b configure -cursor pirate\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.46 {check cursor-font cursor plus} -setup {\n\tbutton .b -text plus\n} -body {\n\t.b configure -cursor plus\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.47 {check cursor-font cursor question_arrow} -setup {\n\tbutton .b -text question_arrow\n} -body {\n\t.b configure -cursor question_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.48 {check cursor-font cursor right_ptr} -setup {\n\tbutton .b -text right_ptr\n} -body {\n\t.b configure -cursor right_ptr\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.49 {check cursor-font cursor right_side} -setup {\n\tbutton .b -text right_side\n} -body {\n\t.b configure -cursor right_side\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.50 {check cursor-font cursor right_tee} -setup {\n\tbutton .b -text right_tee\n} -body {\n\t.b configure -cursor right_tee\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.51 {check cursor-font cursor rightbutton} -setup {\n\tbutton .b -text rightbutton\n} -body {\n\t.b configure -cursor rightbutton\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.52 {check cursor-font cursor rtl_logo} -setup {\n\tbutton .b -text rtl_logo\n} -body {\n\t.b configure -cursor rtl_logo\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.53 {check cursor-font cursor sailboat} -setup {\n\tbutton .b -text sailboat\n} -body {\n\t.b configure -cursor sailboat\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.54 {check cursor-font cursor sb_down_arrow} -setup {\n\tbutton .b -text sb_down_arrow\n} -body {\n\t.b configure -cursor sb_down_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.55 {check cursor-font cursor sb_h_double_arrow} -setup {\n\tbutton .b -text sb_h_double_arrow\n} -body {\n\t.b configure -cursor sb_h_double_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.56 {check cursor-font cursor sb_left_arrow} -setup {\n\tbutton .b -text sb_left_arrow\n} -body {\n\t.b configure -cursor sb_left_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.57 {check cursor-font cursor sb_right_arrow} -setup {\n\tbutton .b -text sb_right_arrow\n} -body {\n\t.b configure -cursor sb_right_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.58 {check cursor-font cursor sb_up_arrow} -setup {\n\tbutton .b -text sb_up_arrow\n} -body {\n\t.b configure -cursor sb_up_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.59 {check cursor-font cursor sb_v_double_arrow} -setup {\n\tbutton .b -text sb_v_double_arrow\n} -body {\n\t.b configure -cursor sb_v_double_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.60 {check cursor-font cursor shuttle} -setup {\n\tbutton .b -text shuttle\n} -body {\n\t.b configure -cursor shuttle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.61 {check cursor-font cursor sizing} -setup {\n\tbutton .b -text sizing\n} -body {\n\t.b configure -cursor sizing\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.62 {check cursor-font cursor spider} -setup {\n\tbutton .b -text spider\n} -body {\n\t.b configure -cursor spider\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.63 {check cursor-font cursor spraycan} -setup {\n\tbutton .b -text spraycan\n} -body {\n\t.b configure -cursor spraycan\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.64 {check cursor-font cursor star} -setup {\n\tbutton .b -text star\n} -body {\n\t.b configure -cursor star\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.65 {check cursor-font cursor target} -setup {\n\tbutton .b -text target\n} -body {\n\t.b configure -cursor target\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.66 {check cursor-font cursor tcross} -setup {\n\tbutton .b -text tcross\n} -body {\n\t.b configure -cursor tcross\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.67 {check cursor-font cursor top_left_arrow} -setup {\n\tbutton .b -text top_left_arrow\n} -body {\n\t.b configure -cursor top_left_arrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.68 {check cursor-font cursor top_left_corner} -setup {\n\tbutton .b -text top_left_corner\n} -body {\n\t.b configure -cursor top_left_corner\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.69 {check cursor-font cursor top_right_corner} -setup {\n\tbutton .b -text top_right_corner\n} -body {\n\t.b configure -cursor top_right_corner\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.70 {check cursor-font cursor top_side} -setup {\n\tbutton .b -text top_side\n} -body {\n\t.b configure -cursor top_side\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.71 {check cursor-font cursor top_tee} -setup {\n\tbutton .b -text top_tee\n} -body {\n\t.b configure -cursor top_tee\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.72 {check cursor-font cursor trek} -setup {\n\tbutton .b -text trek\n} -body {\n\t.b configure -cursor trek\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.73 {check cursor-font cursor ul_angle} -setup {\n\tbutton .b -text ul_angle\n} -body {\n\t.b configure -cursor ul_angle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.74 {check cursor-font cursor umbrella} -setup {\n\tbutton .b -text umbrella\n} -body {\n\t.b configure -cursor umbrella\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.75 {check cursor-font cursor ur_angle} -setup {\n\tbutton .b -text ur_angle\n} -body {\n\t.b configure -cursor ur_angle\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.76 {check cursor-font cursor watch} -setup {\n\tbutton .b -text watch\n} -body {\n\t.b configure -cursor watch\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-6.77 {check cursor-font cursor xterm} -setup {\n\tbutton .b -text xterm\n} -body {\n\t.b configure -cursor xterm\n} -cleanup {\n\tdestroy .b\n} -result {}\n\n# Test cursor named \"none\", it is not defined in\n# the X cursor table. It is defined in a Tk specific\n# table of named cursors and should be available on\n# all platforms.\ntest cursor-6.78 {test cursor named \"none\"} -setup {\n    button .b -text CButton\n} -body {\n    .b configure -cursor none\n    .b cget -cursor\n} -cleanup {\n    destroy .b\n} -result none\n\ntest cursor-6.79 {test cursor named \"none\"} -setup {\n    button .b -text CButton\n} -body {\n    .b configure -cursor none\n    .b configure -cursor {}\n    .b cget -cursor\n} -cleanup {\n    destroy .b\n} -result {}\n\ntest cursor-6.80 {test cursor named \"none\"} -setup {\n    button .b -text CButton\n} -body {\n    .b configure -cursor none\n    .b configure -cursor {}\n    .b configure -cursor none\n    .b cget -cursor\n} -cleanup {\n    destroy .b\n} -result none\n\ntest cursor-6.81 {test cursor named \"none\"} -setup {\n    button .b -text CButton\n} -body {\n    # Setting fg and bg does nothing for the none cursor\n    # because it displays no fg or bg pixels.\n    set results [list]\n    .b configure -cursor none\n    lappend results [.b cget -cursor]\n    .b configure -cursor {none blue}\n    lappend results [.b cget -cursor]\n    .b configure -cursor {none blue green}\n    lappend results [.b cget -cursor]\n    .b configure -cursor {}\n    lappend results [.b cget -cursor]\n    set results\n} -cleanup {\n    destroy .b\n    unset results\n} -result {none {none blue} {none blue green} {}}\n\n# -------------------------------------------------------------------------\n# Check the Windows specific cursors\ntest cursor-7.1 {check Windows cursor no} -constraints win -setup {\n\tbutton .b -text no\n} -body {\n\t.b configure -cursor no\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.2 {check Windows cursor starting} -constraints win -setup {\n\tbutton .b -text starting\n} -body {\n\t.b configure -cursor starting\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.3 {check Windows cursor size} -constraints win -setup {\n\tbutton .b -text size\n} -body {\n\t.b configure -cursor size\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.4 {check Windows cursor size_ne_sw} -constraints win -setup {\n\tbutton .b -text size_ne_sw\n} -body {\n\t.b configure -cursor size_ne_sw\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.5 {check Windows cursor size_ns} -constraints win -setup {\n\tbutton .b -text size_ns\n} -body {\n\t.b configure -cursor size_ns\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.6 {check Windows cursor size_nw_se} -constraints win -setup {\n\tbutton .b -text size_nw_se\n} -body {\n\t.b configure -cursor size_nw_se\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.7 {check Windows cursor size_we} -constraints win -setup {\n\tbutton .b -text size_we\n} -body {\n\t.b configure -cursor size_we\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.8 {check Windows cursor uparrow} -constraints win -setup {\n\tbutton .b -text uparrow\n} -body {\n\t.b configure -cursor uparrow\n} -cleanup {\n\tdestroy .b\n} -result {}\ntest cursor-7.9 {check Windows cursor wait} -constraints win -setup {\n\tbutton .b -text wait\n} -body {\n\t.b configure -cursor wait\n} -cleanup {\n\tdestroy .b\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/dialog.test",
    "content": "# This file is a Tcl script to test out Tk's \"tk_dialog\" command.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding the dialogs that\n# are specific to the windows platform go into the test file winDialog.test.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\n#\n# TESTS\n#\n\ntest dialog-1.1 {tk_dialog command} -body {\n    tk_dialog\n} -match glob -returnCodes error -result {wrong # args: should be \"tk_dialog w title text bitmap default *\"}\ntest dialog-1.2 {tk_dialog command} -body {\n    tk_dialog foo foo foo foo foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest dialog-1.3 {tk_dialog command} -body {\n    tk_dialog .d foo foo fooBitmap foo\n} -cleanup {\n    destroy .d\n} -returnCodes error -result {bitmap \"fooBitmap\" not defined}\n\ntest dialog-2.1 {tk_dialog operation} -body {\n    set x [after 5000 [list set tk::Priv(button) \"no response\"]]\n    after 100 {\n\tif {![winfo ismapped .d.button0]} {\n\t    update\n\t}\n\tPressButton .d.button0\n    }\n    set res [tk_dialog .d foo foo info 0 click]\n    after cancel $x\n    return $res\n} -cleanup {\n    destroy .d\n} -result 0\ntest dialog-2.2 {tk_dialog operation} -setup {\n    proc HitReturn {w} {\n\tevent generate $w <Enter>\n\tfocus -force $w\n\tevent generate $w <Key> -keysym Return\n    }\n} -body {\n    set x [after 5000 [list set tk::Priv(button) \"no response\"]]\n    after 100 HitReturn .d\n    set res [tk_dialog .d foo foo info 1 click default]\n    after cancel $x\n    return $res\n} -cleanup {\n    destroy .d\n} -result 1\ntest dialog-2.3 {tk_dialog operation} -body {\n    set x [after 5000 [list set tk::Priv(button) \"no response\"]]\n    after 100 destroy .d\n    set res [tk_dialog .d foo foo info 0 click]\n    after cancel $x\n    return $res\n} -cleanup {\n    destroy .b\n} -result -1\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget dialog\ncleanupTests\n"
  },
  {
    "path": "tests/embed.test",
    "content": "# This file is a Tcl script to test out embedded Windows.\n#\n# Copyright © 1996-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding embedded windows that\n# are specific to the unix platform (this includes macOS) go into the test file\n# unixEmbed.test.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest embed-1.1 {Tk_UseWindow procedure, bad window identifier} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -use xyz\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"xyz\"}\n\ntest embed-1.2 {CreateFrame procedure, bad window identifier} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -container xyz\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\n\ntest embed-1.3 {CreateFrame procedure, both -use and -container is invalid} -setup {\n    deleteWindows\n} -body {\n    toplevel .container -container 1\n    toplevel .t -use [winfo id .container] -container 1\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {windows cannot have both the -use and the -container option set}\n\n# testing window embedding for win platforms\ntest embed-1.4.win {Tk_UseWindow procedure, -container must be set} -constraints {\n\twin\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .container\n    toplevel .embd -use [winfo id .container]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {the window to use is not a Tk container}\n# testing window embedding for win platforms\ntest embed-1.5.win {Tk_UseWindow procedure, -container must be set} -constraints {\n\twin\n} -setup {\n    deleteWindows\n} -body {\n    frame .container\n    toplevel .embd -use [winfo id .container]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {the window to use is not a Tk container}\n\n# testing window embedding for other than win platforms\ntest embed-1.4.macOrUnix {Tk_UseWindow procedure, -container must be set} -constraints {\n\tmacOrUnix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .container\n    toplevel .embd -use [winfo id .container]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {window \".container\" doesn't have -container option set}\n# testing window embedding for other than win platforms\ntest embed-1.5.macOrUnix {Tk_UseWindow procedure, -container must be set} -constraints {\n\tmacOrUnix\n} -setup {\n    deleteWindows\n} -body {\n    frame .container\n    toplevel .embd -use [winfo id .container]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {window \".container\" doesn't have -container option set}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/entry.test",
    "content": "# This file is a Tcl script to test entry widgets in Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# Gathered comments about lacks\n# Still need to write tests for EntryBlinkProc, EntryFocusProc,\n# EntryTextVarProc, EntryScanTo and EntrySelectTo, DisplayEntry, EventuallyRedraw.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script \"main.tcl\", which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import entry scroll\n\n#\n# COMMON TEST SETUP\n#\n\nforeach i {1 2 3} {\n    set validateCmd$i [list validateCommand$i %W %d %i %P %s %S %v %V]\n}\nset cy [font metrics {Courier -12} -linespace]\n\n#\n# TESTS\n#\n\ntest entry-1.1 {configuration option: \"background\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -background #ff0000\n    .e cget -background\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest entry-1.2 {configuration option: \"background\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -background non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.3 {configuration option: \"bd\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -bd 4\n    .e cget -bd\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-1.4 {configuration option: \"bd\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -bd badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest entry-1.5 {configuration option: \"bg\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -bg #ff0000\n    .e cget -bg\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest entry-1.6 {configuration option: \"bg\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -bg non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.7 {configuration option: \"borderwidth\" for entry} -setup {\n    entry .e -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -borderwidth 1.3\n    .e cget -borderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest entry-1.8 {configuration option: \"borderwidth\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -borderwidth badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest entry-1.9 {configuration option: \"cursor\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -cursor arrow\n    .e cget -cursor\n} -cleanup {\n    destroy .e\n} -result {arrow}\ntest entry-1.10 {configuration option: \"cursor\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -cursor badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest entry-1.11 {configuration option: \"disabledbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -disabledbackground green\n    .e cget -disabledbackground\n} -cleanup {\n    destroy .e\n} -result {green}\ntest entry-1.12 {configuration option: \"disabledbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -disabledbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.13 {configuration option: \"disabledforeground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -disabledforeground blue\n    .e cget -disabledforeground\n} -cleanup {\n    destroy .e\n} -result {blue}\ntest entry-1.14 {configuration option: \"disabledforeground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -disabledforeground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.15 {configuration option: \"exportselection\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -exportselection yes\n    .e cget -exportselection\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-1.16 {configuration option: \"exportselection\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -exportselection xyzzy\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected boolean value but got \"xyzzy\"}\n\ntest entry-1.17 {configuration option: \"fg\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -fg #110022\n    .e cget -fg\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.18 {configuration option: \"fg\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -fg non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.19 {configuration option: \"font\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -font {Helvetica -12}\n    .e cget -font\n} -cleanup {\n    destroy .e\n} -result {Helvetica -12}\ntest entry-1.20 {configuration option: \"font\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -font {}\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {font \"\" does not exist}\n\ntest entry-1.21 {configuration option: \"foreground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -foreground #110022\n    .e cget -foreground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.22 {configuration option: \"foreground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -foreground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.23 {configuration option: \"highlightbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightbackground #110022\n    .e cget -highlightbackground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.24 {configuration option: \"highlightbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.25 {configuration option: \"highlightcolor\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightcolor #110022\n    .e cget -highlightcolor\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.26 {configuration option: \"highlightcolor\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightcolor non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.27 {configuration option: \"highlightthickness\" for entry} -setup {\n    entry .e -borderwidth 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightthickness 6\n    .e cget -highlightthickness\n} -cleanup {\n    destroy .e\n} -result 6\ntest entry-1.28 {configuration option: \"highlightthickness\" for entry} -setup {\n    entry .e -borderwidth 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightthickness -2\n    .e cget -highlightthickness\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"-2\"}\ntest entry-1.29 {configuration option: \"highlightthickness\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -highlightthickness badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest entry-1.30 {configuration option: \"insertbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertbackground #110022\n    .e cget -insertbackground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.31 {configuration option: \"insertbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.32 {configuration option: \"insertborderwidth\" for entry} -setup {\n    entry .e -borderwidth 2 -insertwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertborderwidth 1.3\n    .e cget -insertborderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest entry-1.33 {configuration option: \"insertborderwidth\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertborderwidth 2.6x\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"2.6x\"}\n\ntest entry-1.34 {configuration option: \"insertofftime\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertofftime 100\n    .e cget -insertofftime\n} -cleanup {\n    destroy .e\n} -result 100\ntest entry-1.35 {configuration option: \"insertofftime\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertofftime 3.2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3.2\"}\n\ntest entry-1.36 {configuration option: \"insertontime\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertontime 100\n    .e cget -insertontime\n} -cleanup {\n    destroy .e\n} -result 100\ntest entry-1.37 {configuration option: \"insertontime\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -insertontime 3.2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3.2\"}\n\ntest entry-1.38 {configuration option: \"invalidcommand\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -invalidcommand \"any string\"\n    .e cget -invalidcommand\n} -cleanup {\n    destroy .e\n} -result {any string}\n\ntest entry-1.39 {configuration option: \"invcmd\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -invcmd \"any string\"\n    .e cget -invcmd\n} -cleanup {\n    destroy .e\n} -result {any string}\n\ntest entry-1.40 {configuration option: \"justify\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -justify right\n    .e cget -justify\n} -cleanup {\n    destroy .e\n} -result {right}\ntest entry-1.41 {configuration option: \"justify\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -justify bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\n\ntest entry-1.42 {configuration option: \"readonlybackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -readonlybackground green\n    .e cget -readonlybackground\n} -cleanup {\n    destroy .e\n} -result {green}\ntest entry-1.43 {configuration option: \"readonlybackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -readonlybackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.44 {configuration option: \"relief\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -relief flat\n    .e cget -relief\n} -cleanup {\n    destroy .e\n} -result {flat}\n\ntest entry-1.45 {configuration option: \"selectbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectbackground #110022\n    .e cget -selectbackground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.46 {configuration option: \"selectbackground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.47 {configuration option: \"selectborderwidth\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectborderwidth 1.3\n    .e cget -selectborderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest entry-1.48 {configuration option: \"selectborderwidth\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectborderwidth badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest entry-1.49 {configuration option: \"selectforeground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectforeground #110022\n    .e cget -selectforeground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest entry-1.50 {configuration option: \"selectforeground\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -selectforeground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest entry-1.51 {configuration option: \"show\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -show *\n    .e cget -show\n} -cleanup {\n    destroy .e\n} -result {*}\n\ntest entry-1.52 {configuration option: \"state\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -state n\n    .e cget -state\n} -cleanup {\n    destroy .e\n} -result {normal}\ntest entry-1.53 {configuration option: \"state\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -state bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad state \"bogus\": must be disabled, normal, or readonly}\n\ntest entry-1.54 {configuration option: \"takefocus\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -takefocus \"any string\"\n    .e cget -takefocus\n} -cleanup {\n    destroy .e\n} -result {any string}\n\ntest entry-1.55 {configuration option: \"textvariable\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -textvariable i\n    .e cget -textvariable\n} -cleanup {\n    destroy .e\n} -result {i}\n\ntest entry-1.56 {configuration option: \"width\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -width 402\n    .e cget -width\n} -cleanup {\n    destroy .e\n} -result 402\ntest entry-1.57 {configuration option: \"width\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -width 3p\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3p\"}\n\ntest entry-1.58 {configuration option: \"xscrollcommand\" for entry} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -xscrollcommand {Some command}\n    .e cget -xscrollcommand\n} -cleanup {\n    destroy .e\n} -result {Some command}\n\ntest entry-1.59 {configuration option: \"-placeholder\"} -setup {\n    pack [entry .e]\n} -body {\n    .e configure -placeholder {Some text}\n    .e cget -placeholder\n} -cleanup {\n    destroy .e\n} -result {Some text}\n\ntest entry-1.60 {configuration option: \"-placeholderforeground\"} -setup {\n    pack [entry .e]\n} -body {\n    .e configure -placeholder {Some text} -placeholderforeground red\n    .e cget -placeholderforeground\n} -cleanup {\n    destroy .e\n} -result {red}\n\n\ntest entry-2.1 {Tk_EntryCmd procedure} -body {\n    entry\n} -returnCodes error -result {wrong # args: should be \"entry pathName ?-option value ...?\"}\ntest entry-2.2 {Tk_EntryCmd procedure} -body {\n    entry gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest entry-2.3 {Tk_EntryCmd procedure} -body {\n    entry .e\n    pack .e ; update idletasks\n    update\n    list [winfo exists .e] [winfo class .e] [info commands .e]\n} -cleanup {\n    destroy .e\n} -result {1 Entry .e}\ntest entry-2.4 {Tk_EntryCmd procedure} -body {\n    entry .e -gorp foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest entry-2.4.1 {Tk_EntryCmd procedure} -body {\n    catch {entry .e -gorp foo}\n    list [winfo exists .e] [info commands .e]\n} -cleanup {\n    destroy .e\n} -result {0 {}}\ntest entry-2.5 {Tk_EntryCmd procedure} -body {\n    entry .e\n} -cleanup {\n    destroy .e\n} -result {.e}\n\n\ntest entry-3.1 {EntryWidgetCmd procedure} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e option ?arg ...?\"}\ntest entry-3.2 {EntryWidgetCmd procedure, \"bbox\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e bbox\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e bbox index\"}\ntest entry-3.3 {EntryWidgetCmd procedure, \"bbox\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e bbox a b\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e bbox index\"}\ntest entry-3.4 {EntryWidgetCmd procedure, \"bbox\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e bbox bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"bogus\"}\ntest entry-3.5 {EntryWidgetCmd procedure, \"bbox\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n   .e bbox 0\n} -cleanup {\n    destroy .e\n} -result [list 5 5 0 $cy]\n\n# Previously the result was count using previousli counted font measurements\n# and metrics. It was changed to less verbose solution - the result is the one\n# that passes fonts constraint (this concerns tests 3.6, 3.7, 3.8, 3.10)\ntest entry-3.6 {EntryWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n# Tcl_UtfAtIndex(): no utf chars\n    .e insert 0 \"abc\"\n    list [.e bbox 3] [.e bbox end]\n} -cleanup {\n    destroy .e\n} -result {{19 5 7 13} {19 5 7 13}}\ntest entry-3.7 {EntryWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n# Tcl_UtfAtIndex(): utf at end\n    .e insert 0 \"ab乎\"\n    .e bbox end\n} -cleanup {\n    destroy .e\n} -result {19 5 12 13}\ntest entry-3.8 {EntryWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n# Tcl_UtfAtIndex(): utf before index\n    .e insert 0 \"ab乎c\"\n    .e bbox 3\n} -cleanup {\n    destroy .e\n} -result {31 5 7 13}\ntest entry-3.9 {EntryWidgetCmd procedure, \"bbox\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n# Tcl_UtfAtIndex(): no chars\n    .e bbox end\n} -cleanup {\n    destroy .e\n} -result \"5 5 0 $cy\"\ntest entry-3.10 {EntryWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert 0 \"abcdefghij乎klmnop\"\n    list [.e bbox 0] [.e bbox 1] [.e bbox 10] [.e bbox end]\n} -cleanup {\n    destroy .e\n} -result {{5 5 7 13} {12 5 7 13} {75 5 12 13} {122 5 7 13}}\ntest entry-3.11 {EntryWidgetCmd procedure, \"cget\" widget command} -setup {\n    entry .e\n} -body {\n    .e cget\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e cget option\"}\ntest entry-3.12 {EntryWidgetCmd procedure, \"cget\" widget command} -setup {\n    entry .e\n} -body {\n    .e cget a b\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e cget option\"}\ntest entry-3.13 {EntryWidgetCmd procedure, \"cget\" widget command} -setup {\n    entry .e\n} -body {\n    .e cget -gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest entry-3.14 {EntryWidgetCmd procedure, \"cget\" widget command} -setup {\n    entry .e\n} -body {\n    .e configure -bd 4\n    .e cget -bd\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-3.15 {EntryWidgetCmd procedure, \"configure\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    llength [.e configure]\n} -cleanup {\n    destroy .e\n} -result 38\ntest entry-3.16 {EntryWidgetCmd procedure, \"configure\" widget command} -setup {\n    entry .e\n} -body {\n    .e configure -foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-foo\"}\ntest entry-3.17 {EntryWidgetCmd procedure, \"configure\" widget command} -setup {\n    entry .e\n} -body {\n    .e configure -bd 4\n    .e configure -bg #ffffff\n    lindex [.e configure -bd] 4\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-3.18 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n} -body {\n    .e delete\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e delete firstIndex ?lastIndex?\"}\ntest entry-3.19 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n} -body {\n    .e delete a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e delete firstIndex ?lastIndex?\"}\ntest entry-3.20 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n} -body {\n    .e delete foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"foo\"}\ntest entry-3.21 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n} -body {\n    .e delete 0 bar\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"bar\"}\ntest entry-3.22 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 2 4\n    .e get\n} -cleanup {\n    destroy .e\n} -result 014567890\ntest entry-3.23 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 6\n    .e get\n} -cleanup {\n    destroy .e\n} -result 0123457890\ntest entry-3.24 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n    set result {}\n} -body {\n# UTF\n    .e insert end \"01234乎67890\"\n    .e delete 6\n    lappend result [.e get]\n    .e delete 0 end\n    .e insert end \"012345乎7890\"\n    .e delete 6\n    lappend result [.e get]\n    .e delete 0 end\n    .e insert end \"0123456乎890\"\n    .e delete 6\n    lappend result [.e get]\n} -cleanup {\n    destroy .e\n} -result [list \"01234乎7890\" \"0123457890\" \"012345乎890\"]\ntest entry-3.25 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 6 5\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest entry-3.26 {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state disabled\n    .e delete 2 8\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest entry-3.26a {EntryWidgetCmd procedure, \"delete\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state readonly\n    .e delete 2 8\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest entry-3.27 {EntryWidgetCmd procedure, \"get\" widget command} -setup {\n    entry .e\n} -body {\n    .e get foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e get\"}\ntest entry-3.28 {EntryWidgetCmd procedure, \"icursor\" widget command} -setup {\n    entry .e\n} -body {\n    .e icursor\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e icursor pos\"}\ntest entry-3.29 {EntryWidgetCmd procedure, \"icursor\" widget command} -setup {\n    entry .e\n} -body {\n    .e icursor foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"foo\"}\ntest entry-3.30 {EntryWidgetCmd procedure, \"icursor\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert end \"01234567890\"\n    .e icursor 4\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-3.31 {EntryWidgetCmd procedure, \"index\" widget command} -setup {\n    entry .e\n} -body {\n    .e in\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {ambiguous option \"in\": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}\ntest entry-3.32 {EntryWidgetCmd procedure, \"index\" widget command} -setup {\n    entry .e\n} -body {\n    .e index\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e index string\"}\ntest entry-3.33 {EntryWidgetCmd procedure, \"index\" widget command} -setup {\n    entry .e\n} -body {\n    .e index foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"foo\"}\ntest entry-3.34 {EntryWidgetCmd procedure, \"index\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e index 0\n} -cleanup {\n    destroy .e\n} -returnCodes {ok} -match glob -result {*}\ntest entry-3.35 {EntryWidgetCmd procedure, \"index\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n# UTF\n    .e insert 0 abc乎œdef\n    list [.e index 3] [.e index 4] [.e index end]\n} -cleanup {\n    destroy .e\n} -result {3 4 8}\ntest entry-3.36 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert a\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest entry-3.37 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest entry-3.38 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert foo Text\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"foo\"}\ntest entry-3.39 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e insert 3 xxx\n    .e get\n} -cleanup {\n    destroy .e\n} -result {012xxx34567890}\ntest entry-3.40 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state disabled\n    .e insert 3 xxx\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest entry-3.40a {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state readonly\n    .e insert 3 xxx\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest entry-3.41 {EntryWidgetCmd procedure, \"insert\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest entry-3.42 {EntryWidgetCmd procedure, \"scan\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e scan a\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e scan mark|dragto x\"}\ntest entry-3.43 {EntryWidgetCmd procedure, \"scan\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e scan a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e scan mark|dragto x\"}\ntest entry-3.44 {EntryWidgetCmd procedure, \"scan\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e scan foobar 20\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad scan option \"foobar\": must be dragto or mark}\ntest entry-3.45 {EntryWidgetCmd procedure, \"scan\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e scan mark 20.1\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"20.1\"}\n\n# This test is non-portable because character sizes vary.\ntest entry-3.46 {EntryWidgetCmd procedure, \"scan\" widget command} -constraints {\n    fonts\n} -setup {\n    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long string, in fact a \"\n    .e insert end \"very very long string\"\n    .e scan mark 30\n    .e scan dragto 28\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 2\ntest entry-3.47 {EntryWidgetCmd procedure, \"select\" widget command} -setup {\n    entry .e\n} -body {\n    .e select\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection option ?index?\"}\ntest entry-3.48 {EntryWidgetCmd procedure, \"select\" widget command} -setup {\n    entry .e\n} -body {\n    .e select foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad selection option \"foo\": must be adjust, clear, from, present, range, or to}\n\ntest entry-3.49 {EntryWidgetCmd procedure, \"select clear\" widget command} -setup {\n    entry .e\n} -body {\n    .e select clear gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection clear\"}\ntest entry-3.50 {EntryWidgetCmd procedure, \"select clear\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 4\n    update\n    .e select clear\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest entry-3.50.1 {EntryWidgetCmd procedure, \"select clear\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 4\n    update\n    .e select clear\n    catch {selection get}\n    selection own\n} -cleanup {\n    destroy .e\n} -result {.e}\n\ntest entry-3.51 {EntryWidgetCmd procedure, \"selection present\" widget command} -setup {\n    entry .e\n} -body {\n    .e selection present foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection present\"}\ntest entry-3.52 {EntryWidgetCmd procedure, \"selection present\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-3.53 {EntryWidgetCmd procedure, \"selection present\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e configure -exportselection false\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-3.54 {EntryWidgetCmd procedure, \"selection present\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e delete 0 end\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 0\ntest entry-3.55 {EntryWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    entry .e\n} -body {\n    .e select adjust x\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"x\"}\ntest entry-3.56 {EntryWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    entry .e\n} -body {\n    .e select adjust 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection adjust index\"}\ntest entry-3.57 {EntryWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    update\n    .e select adjust 4\n    selection get\n} -cleanup {\n    destroy .e\n} -result 123\ntest entry-3.58 {EntryWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    update\n    .e select adjust 2\n    selection get\n} -cleanup {\n    destroy .e\n} -result 234\ntest entry-3.59 {EntryWidgetCmd procedure, \"selection from\" widget command} -setup {\n    entry .e\n} -body {\n    .e select from 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection from index\"}\n\ntest entry-3.60 {EntryWidgetCmd procedure, \"selection range\" widget command} -setup {\n    entry .e\n} -body {\n    .e select range 2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection range start end\"}\ntest entry-3.61 {EntryWidgetCmd procedure, \"selection range\" widget command} -setup {\n    entry .e\n} -body {\n    .e selection range 2 3 4\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection range start end\"}\ntest entry-3.62 {EntryWidgetCmd procedure, \"selection range\" widget command} -setup {\n    entry .e\n} -body {\n    .e insert end 0123456789\n    .e select from 1\n    .e select to 5\n    .e select range 4 4\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest entry-3.63 {EntryWidgetCmd procedure, \"selection range\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 7\n    .e select range 2 9\n    list [.e index sel.first] [.e index sel.last] [.e index anchor]\n} -cleanup {\n    destroy .e\n} -result {2 9 3}\ntest entry-3.64 {EntryWidgetCmd procedure, \"selection\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state disabled\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {0 10}\ntest entry-3.64a {EntryWidgetCmd procedure, \"selection\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state readonly\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 4}\ntest entry-3.64b {EntryWidgetCmd procedure, \"selection to\" widget command} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n} -body {\n    .e select to 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection to index\"}\n\ntest entry-3.65 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 5\n    format {%.7f %.7f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.0537634 0.2688172}\ntest entry-3.66 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e xview gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"gorp\"}\ntest entry-3.67 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 0\n    .e icursor 10\n    .e xview insert\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.107527 0.322581}\ntest entry-3.68 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e xview moveto foo bar\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e xview moveto fraction\"}\ntest entry-3.69 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e xview moveto foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"foo\"}\ntest entry-3.70 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview moveto 0.5\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.505376 0.720430}\ntest entry-3.71 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview scroll 24\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e xview scroll number pages|units\"}\ntest entry-3.72 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview scroll gorp units\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"gorp\"}\ntest entry-3.73 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview moveto 0\n    .e xview scroll 1 pages\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.193548 0.408602}\ntest entry-3.74 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview moveto .9\n    update\n    .e xview scroll -2 p\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.397849 0.612903}\ntest entry-3.75 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 30\n    update\n    .e xview scroll 2 units\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 32\ntest entry-3.76 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 30\n    update\n    .e xview scroll -1 units\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 29\ntest entry-3.77 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview scroll 23 foobars\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad argument \"foobars\": must be pages or units}\ntest entry-3.78 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview eat 23 hamburgers\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"eat\": must be moveto or scroll}\ntest entry-3.79 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 0\n    update\n    .e xview {}\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 0\ntest entry-3.80 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 300\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 73\ntest entry-3.86 {EntryWidgetCmd procedure, \"xview\" widget command} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e insert 10 乎\n    update\n# UTF\n# If Tcl_NumUtfChars wasn't used, wrong answer would be:\n# 0.106383 0.117021 0.117021\n    set result {}\n    .e xview moveto .1\n    lappend result [format {%.6f} [lindex [.e xview] 0]]\n    .e xview moveto .11\n    lappend result [format {%.6f} [lindex [.e xview] 0]]\n    .e xview moveto .12\n    lappend result [format {%.6f} [lindex [.e xview] 0]]\n} -cleanup {\n    destroy .e\n} -result {0.095745 0.106383 0.117021}\n\ntest entry-3.82 {EntryWidgetCmd procedure} -setup {\n    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad option \"gorp\": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}\n\n# The test below doesn't actually check anything directly, but if run\n# with Purify or some other memory-allocation-checking program it will\n# ensure that resources get properly freed.\n\ntest entry-4.1 {DestroyEntry procedure} -body {\n    entry .e -textvariable textVar -show *\n    pack .e ; update idletasks\n    .e insert end \"Sample text\"\n    update\n    destroy .e\n} -result {}\n\ntest entry-5.1 {ConfigureEntry procedure, -textvariable} -body {\n    set textVar 12345\n    entry .e -textvariable textVar\n    .e get\n} -cleanup {\n    destroy .e\n} -result 12345\ntest entry-5.2 {ConfigureEntry procedure, -textvariable} -body {\n    set textVar 12345\n    entry .e -textvariable textVar\n    set y abcde\n    .e configure -textvariable y\n    set textVar 54321\n    .e get\n} -cleanup {\n    destroy .e\n} -result {abcde}\ntest entry-5.3 {ConfigureEntry procedure, -textvariable} -setup {\n    unset -nocomplain textVar\n    entry .e\n} -body {\n    .e insert 0 \"Some text\"\n    .e configure -textvariable textVar\n    set textVar\n} -cleanup {\n    destroy .e\n} -result {Some text}\ntest entry-5.4 {ConfigureEntry procedure, -textvariable} -setup {\n    unset -nocomplain textVar\n    entry .e\n} -body {\n    trace add variable textVar write override\n    .e insert 0 \"Some text\"\n    .e configure -textvariable textVar\n    list $textVar [.e get]\n} -cleanup {\n    destroy .e\n    trace remove variable textVar write override\n    unset textVar\n} -result {12345 12345}\n\ntest entry-5.5 {ConfigureEntry procedure} -setup {\n    set result {}\n    entry .e1\n    entry .e2\n} -body {\n    .e2 insert end \"This is some sample text\"\n    .e1 configure -exportselection false\n    .e1 insert end \"0123456789\"\n    pack .e1 .e2 ; update idletasks\n    .e2 select from 0\n    .e2 select to 10\n    lappend result [selection get]\n    .e1 select from 1\n    .e1 select to 5\n    lappend result [selection get]\n    .e1 configure -exportselection 1\n    lappend result [selection get]\n    set result\n} -cleanup {\n    destroy .e1 .e2\n} -result {{This is so} {This is so} 1234}\ntest entry-5.6 {ConfigureEntry procedure} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    .e configure -exportselection 0\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest entry-5.6.1 {ConfigureEntry procedure} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    .e configure -exportselection 0\n    catch {selection get}\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 5}\n\ntest entry-5.7 {ConfigureEntry procedure} -setup {\n    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -width 4 -xscrollcommand setScrollInfo\n    .e insert end \"01234567890\"\n    update\n    set scrollInfo wrong\n    .e configure -width 5\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.454545}\n\n\ntest entry-5.8 {ConfigureEntry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -width 0 -font {Helvetica -12}\n    .e insert end \"0123\"\n    update\n    .e configure -font {Helvetica -24}\n    update\n    winfo geom .e\n} -cleanup {\n    destroy .e\n} -result {62x37+0+0}\ntest entry-5.9 {ConfigureEntry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised\n    .e insert end \"0123\"\n    update\n    list [.e index @10] [.e index @11] [.e index @12] [.e index @13]\n} -cleanup {\n    destroy .e\n} -result {0 0 1 1}\ntest entry-5.10 {ConfigureEntry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief flat\n    .e insert end \"0123\"\n    update\n    list [.e index @10] [.e index @11] [.e index @12] [.e index @13]\n} -cleanup {\n    destroy .e\n} -result {0 0 1 1}\ntest entry-5.11 {ConfigureEntry procedure} -setup {\n    entry .e -borderwidth 2 -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n# If \"0\" in selected font had 0 width, caused divide-by-zero error.\n    .e configure -font {{open look glyph}}\n    .e scan dragto 30\n    update\n} -cleanup {\n    destroy .e\n} -result {}\n\n# No tests for DisplayEntry.\n\ntest entry-6.1 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \\\n\t-highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @61] [.e index @62]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest entry-6.2 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \\\n\t-justify center -highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @96] [.e index @97]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest entry-6.3 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \\\n\t-justify right -highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @131] [.e index @132]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest entry-6.4 {EntryComputeGeometry procedure} -setup {\n    entry .e\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 5\n    .e insert end \"01234567890\"\n    update\n    .e xview 6\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 6\ntest entry-6.5 {EntryComputeGeometry procedure} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 5\n    .e insert end \"01234567890\"\n    update\n    .e xview 7\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 6\ntest entry-6.6 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 10\n    .e insert end \"01234\\t67890\"\n    update\n    .e xview 3\n    list [.e index @39] [.e index @40]\n} -cleanup {\n    destroy .e\n} -result {5 6}\ntest entry-6.7 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 5\n    .e insert end \"01234567\"\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {77 39}\ntest entry-6.8 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0\n    .e insert end \"01234567\"\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {116 39}\ntest entry-6.9 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {25 39}\ntest entry-6.10 {EntryComputeGeometry procedure} -constraints {\n    unix fonts\n} -setup {\n    entry .e -highlightthickness 2 -font {Helvetica -12}\n    pack .e ; update idletasks\n} -body {\n    .e configure -bd 1 -relief raised -width 0 -show .\n    .e insert 0 12345\n    update\n    set result [winfo reqwidth .e]\n    .e configure -show X\n    lappend result [winfo reqwidth .e]\n    .e configure -show \"\"\n    lappend result [winfo reqwidth .e]\n} -cleanup {\n    destroy .e\n} -result {23 53 43}\ntest entry-6.11 {EntryComputeGeometry procedure} -constraints {\n    win\n} -setup {\n    entry .e -highlightthickness 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -bd 1 -relief raised -width 0 -show . -font {helvetica 12}\n    .e insert 0 12345\n    update\n    set x1 [winfo reqwidth .e]\n\tset x2 [expr {8+5*[font measure {helvetica 12} .]}]\n\tset result [expr {$x1 eq $x2}]\n    .e configure -show X\n\tset x1 [winfo reqwidth .e]\n\tset x2 [expr {8+5*[font measure {helvetica 12} X]}]\n    lappend result [expr {$x1 eq $x2}]\n    .e configure -show \"\"\n\tset x1 [winfo reqwidth .e]\n\tset x2 [expr {8+[font measure {helvetica 12} 12345]}]\n    lappend result [expr {$x1 eq $x2}]\n} -cleanup {\n    destroy .e\n} -result {1 1 1}\ntest entry-6.12 {EntryComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    catch {destroy .e}\n    entry .e -font {Courier -12} -bd 2 -relief raised -width 20\n    pack .e ; update idletasks\n} -body {\n    .e insert end \"012\\t456\\t\"\n    update\n    list [.e index @80] [.e index @81] [.e index @115] [.e index @116]\n} -cleanup {\n    destroy .e\n} -result {6 7 7 8}\n\n\ntest entry-7.1 {InsertChars procedure} -setup {\n    unset -nocomplain contents\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    update\n    set scrollInfo wrong\n    .e insert 0 abcde\n    .e insert 2 XXX\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abXXXcde abXXXcde {0.000000 1.000000}}\n\ntest entry-7.2 {InsertChars procedure} -setup {\n    unset -nocomplain contents\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    update\n    set scrollInfo wrong\n    .e insert 0 abcde\n    .e insert 500 XXX\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abcdeXXX abcdeXXX {0.000000 1.000000}}\ntest entry-7.3 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 2 XXX\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {5 9 5 8}\ntest entry-7.4 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 3 XXX\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 9 2 8}\ntest entry-7.5 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 5 XXX\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 9 2 8}\ntest entry-7.6 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 6 XXX\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 6 2 5}\ntest entry-7.7 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -xscrollcommand setScrollInfo\n    .e insert 0 0123456789\n    .e icursor 4\n    .e insert 4 XXX\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 7\ntest entry-7.8 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789\n    .e icursor 4\n    .e insert 5 XXX\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-7.9 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 \"This is a very long string\"\n    update\n    .e xview 4\n    .e insert 3 XXX\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 7\ntest entry-7.10 {InsertChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 \"This is a very long string\"\n    update\n    .e xview 4\n    .e insert 4 XXX\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 4\n\ntest entry-7.11 {InsertChars procedure} -constraints {\n    fonts\n} -setup {\n    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 \"xyzzy\"\n    update\n    .e insert 2 00\n    winfo reqwidth .e\n} -cleanup {\n    destroy .e\n} -result 59\n\ntest entry-8.1 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    update\n    set scrollInfo wrong\n    .e insert 0 abcde\n    .e delete 2 4\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abe abe {0.000000 1.000000}}\ntest entry-8.2 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    update\n    set scrollInfo wrong\n    .e insert 0 abcde\n    .e delete {} 2\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {cde cde {0.000000 1.000000}}\ntest entry-8.3 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    update\n    set scrollInfo wrong\n    .e insert 0 abcde\n    .e delete 3 1000\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abc abc {0.000000 1.000000}}\ntest entry-8.4 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 3\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 6 1 5}\ntest entry-8.5 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 4\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 4\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 5 1 4}\ntest entry-8.6 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 7\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 2 1 5}\ntest entry-8.7 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 8\n    update\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest entry-8.8 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 3 7\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 4 3 8}\ntest entry-8.9 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 3 8\n    update\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest entry-8.10 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 8\n    .e select to 3\n    .e delete 5 8\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 5 5 8}\ntest entry-8.11 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 8\n    .e select to 3\n    .e delete 8 10\n    update\n    set result \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 4\n    lappend result [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 8 4 8}\ntest entry-8.12 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 1 4\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-8.13 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 1 5\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-8.14 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 4 6\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-8.15 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 1 4\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-8.16 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 1 5\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-8.17 {DeleteChars procedure} -setup {\n    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 4 6\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-8.18 {DeleteChars procedure} -setup {\n    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    focus .e\n} -body {\n    .e insert 0 \"xyzzy\"\n    update\n    .e delete 2 4\n    # To check that deletion actually happened we measure the new width\n    # of the widget, based on the measuring width of the remaining text (\"xyy\")\n    # in the widget. For that purpose we have to mirror the code in tkEntry.c\n    # for computation of the reqwidth\n    # note: XPAD corresponds to the hardcoded    #define XPAD 1\n    set XPAD 1\n    set expected [expr { [font measure [.e cget -font] \"xyy\"] \\\n\t\t\t  + 2 * ( [.e cget -borderwidth] + \\\n\t\t\t\t[.e cget -highlightthickness] + $XPAD ) } ]\n    expr {[winfo reqwidth .e] == $expected}\n} -cleanup {\n    destroy .e\n    unset XPAD expected\n} -result {1}\n\ntest entry-9.1 {EntryValueChanged procedure} -setup {\n    unset -nocomplain textVar\n} -body {\n    trace add variable textVar write override\n    entry .e -textvariable textVar -width 0\n    .e insert 0 foo\n    list $textVar [.e get]\n} -cleanup {\n    destroy .e\n    trace remove variable textVar write override\n    unset textVar\n} -result {12345 12345}\n\n\ntest entry-10.1 {EntrySetValue procedure} -constraints fonts -body {\n    set textVar abcde\n    set y ab\n    entry .e  -font {Helvetica -12} -highlightthickness 2 -bd 2  -width 0\n    pack .e ; update idletasks\n    .e configure -textvariable textVar\n    .e configure -textvariable y\n    update\n    list [.e get] [winfo reqwidth .e]\n} -cleanup {\n    destroy .e\n} -result {ab 24}\ntest entry-10.2 {EntrySetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"a\"\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest entry-10.3 {EntrySetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"abcdefg\"\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {4 7}\ntest entry-10.4 {EntrySetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"abcdefghijklmn\"\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {4 10}\ntest entry-10.5 {EntrySetValue procedure, updating display position} -setup {\n    unset -nocomplain textVar\n    entry .e -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e xview 10\n    update\n    set textVar \"abcdefg\"\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 0\ntest entry-10.6 {EntrySetValue procedure, updating display position} -setup {\n    unset -nocomplain textVar\n    entry .e -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e ; update idletasks\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e xview 10\n    update\n    set textVar \"1234567890123456789012\"\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 10\ntest entry-10.7 {EntrySetValue procedure, updating insertion cursor} -setup {\n    unset -nocomplain textVar\n    entry .e -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n    update\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e ; update idletasks\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e icursor 5\n    set textVar \"123\"\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 3\ntest entry-10.8 {EntrySetValue procedure, updating insertion cursor} -setup {\n    unset -nocomplain textVar\n    entry .e -highlightthickness 2 -bd 2\n    pack .e ; update idletasks\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e ; update idletasks\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e icursor 5\n    set textVar \"123456\"\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 5\n\ntest entry-11.1 {EntryEventProc procedure} -setup {\n    entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 abcdefg\n    destroy .e\n    update\n} -cleanup {\n    destroy .e\n} -result {}\ntest entry-11.2 {EntryEventProc procedure} -setup {\n    set result {}\n} -body {\n    entry .e1 -fg #112233\n    rename .e1 .e2\n    lappend result [winfo children .]\n    lappend result [.e2 cget -fg]\n    destroy .e1\n    lappend result [info command .e*] [winfo children .]\n} -cleanup {\n    destroy .e1\n} -result {.e1 #112233 {} {}}\n\ntest entry-12.1 {EntryCmdDeletedProc procedure} -body {\n    button .b -text \"xyz_123\"\n    rename .b {}\n    list [info command .b*] [winfo children .]\n} -cleanup {\n    destroy .b\n} -result {{} {}}\n\n\ntest entry-13.1 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index end\n} -cleanup {\n    destroy .e\n} -result 21\ntest entry-13.2 {GetEntryIndex procedure} -body {\n    entry .e\n    .e index abogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"abogus\"}\ntest entry-13.3 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 1\ntest entry-13.4 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 4\n    .e select to 1\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-13.5 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 3\n    .e select to 15\n    .e select adjust 4\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 15\ntest entry-13.6 {GetEntryIndex procedure} -setup {\n    entry .e\n} -body {\n    .e index ebogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"ebogus\"}\ntest entry-13.7 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e icursor 2\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 2\ntest entry-13.8 {GetEntryIndex procedure} -setup {\n    entry .e\n} -body {\n    .e index ibogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"ibogus\"}\ntest entry-13.9 {GetEntryIndex procedure} -setup {\n    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e ; update idletasks\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 6}\n\n\n\n\n\n\ntest entry-13.10 {GetEntryIndex procedure} -constraints x11 -body {\n# On unix, when selection is cleared, entry widget's internal\n# selection range is reset.\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\n\ntest entry-13.11 {GetEntryIndex procedure} -constraints aquaOrWin32 -body {\n# On mac and pc, when selection is cleared, entry widget remembers\n# last selected range.  When selection ownership is restored to\n# entry, the old range will be rehighlighted.\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    catch {selection get}\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -result 1\n\ntest entry-13.12 {GetEntryIndex procedure} -constraints x11 -body {\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\n\n# why when string in .e index changed to not beginning with s,\n# it behaves differently?\ntest entry-13.12.1 {GetEntryIndex procedure} -constraints unix -body {\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"bogus\"}\n\ntest entry-13.13 {GetEntryIndex procedure} -constraints win -body {\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"sbogus\"}\n\ntest entry-13.14 {GetEntryIndex procedure} -constraints win -body {\n# On mac and pc, when selection is cleared, entry widget remembers\n# last selected range.  When selection ownership is restored to\n# entry, the old range will be rehighlighted.\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -match glob -result {*}\n\ntest entry-13.14.1 {GetEntryIndex procedure} -constraints win -body {\n# On mac and pc, when selection is cleared, entry widget remembers\n# last selected range.  When selection ownership is restored to\n# entry, the old range will be rehighlighted.\n# Previous settings:\n\tentry .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e ; update idletasks\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    catch {selection get}\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -match glob -result {*}\n\ntest entry-13.15 {GetEntryIndex procedure} -body {\n    entry .e\n    selection clear .e\n    .e index @xyz\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"@xyz\"}\n\ntest entry-13.16 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @4\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-13.17 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @11\n} -cleanup {\n    destroy .e\n} -result 4\ntest entry-13.18 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @12\n} -cleanup {\n    destroy .e\n} -result 5\ntest entry-13.19 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @[expr {[winfo width .e] - 6}]\n} -cleanup {\n    destroy .e\n} -result 8\ntest entry-13.20 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @[expr {[winfo width .e] - 5}]\n} -cleanup {\n    destroy .e\n} -result 9\ntest entry-13.21 {GetEntryIndex procedure} -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @1000\n} -cleanup {\n    destroy .e\n} -result 9\ntest entry-13.22 {GetEntryIndex procedure} -setup {\n    entry .e\n    pack .e ; update idletasks\n    update\n} -body {\n    .e index 1xyz\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad entry index \"1xyz\"}\ntest entry-13.23 {GetEntryIndex procedure} -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index {}\n} -cleanup {\n    destroy .e\n} -result 0\ntest entry-13.24 {GetEntryIndex procedure} -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index 12\n} -cleanup {\n    destroy .e\n} -result 12\ntest entry-13.25 {GetEntryIndex procedure} -body {\n    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\\\n\t-font {Courier -12}\n    pack .e ; update idletasks\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index 49\n} -cleanup {\n    destroy .e\n} -result 21\ntest entry-13.26 {GetEntryIndex procedure} -constraints fonts -body {\n    entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}\n    selection clear .e\n    .e configure -show .\n    .e insert 0 XXXYZZY\n    pack .e ; update idletasks\n    update\n    list [.e index @7] [.e index @8]\n} -cleanup {\n    destroy .e\n} -result {0 1}\n\n# Still need to write tests for EntryScanTo and EntrySelectTo.\n\n\ntest entry-14.1 {EntryFetchSelection procedure} -body {\n    entry .e\n    .e insert end \"This is a test string\"\n    .e select from 1\n    .e select to 18\n    selection get\n} -cleanup {\n    destroy .e\n} -result {his is a test str}\ntest entry-14.2 {EntryFetchSelection procedure} -body {\n    entry .e -show *\n    .e insert end \"This is a test string\"\n    .e select from 1\n    .e select to 18\n    selection get\n} -cleanup {\n    destroy .e\n} -result {*****************}\ntest entry-14.3 {EntryFetchSelection procedure} -setup {\n    set textVar {}\n    for {set i 1} {$i <= 500} {incr i} {\n\tappend textVar \"This is line $i, out of 500\\n\"\n}\n} -body {\n    entry .e\n    .e insert end $textVar\n    .e select from 0\n    .e select to end\n    string compare [selection get] $textVar\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-15.1 {EntryLostSelection} -body {\n    entry .e\n    .e insert 0 \"Text\"\n    .e select from 0\n    .e select to 4\n    set result [selection get]\n    selection clear\n    .e select from 0\n    .e select to 4\n    lappend result [selection get]\n} -cleanup {\n    destroy .e\n} -result {Text Text}\n\n# is scrollcommand needed here??\ntest entry-16.1 {EntryVisibleRange procedure} -constraints fonts  -body {\n    entry .e -width 10 -font {Helvetica -12}\n    pack .e ; update idletasks\n    update\n    .e insert 0 \".............................\"\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.827586}\ntest entry-16.2 {EntryVisibleRange procedure} -constraints {\n    unix fonts\n} -body {\n    entry .e -show X -width 10  -font {Helvetica -12}\n    pack .e ; update idletasks\n    update\n    .e insert 0 \".............................\"\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.275862}\ntest entry-16.3 {EntryVisibleRange procedure} -constraints {\n    win\n} -body {\n    entry .e -show . -width 10  -font {Helvetica -12}\n\tpack .e ; update idletasks\n    update\n    .e insert 0 XXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.827586}\ntest entry-16.4 {EntryVisibleRange procedure} -body {\n    entry .e -show \"\"\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 1.000000}\n\n\ntest entry-17.1 {EntryUpdateScrollbar procedure} -body {\n    entry .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    update\n    set scrollInfo wrong\n    .e delete 0 end\n    .e insert 0 123\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.000000 1.000000}\ntest entry-17.2 {EntryUpdateScrollbar procedure} -body {\n    entry .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    update\n    set scrollInfo wrong\n    .e insert 0 0123456789abcdef\n    .e xview 3\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.187500 0.812500}\ntest entry-17.3 {EntryUpdateScrollbar procedure} -body {\n    entry .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    update\n    set scrollInfo wrong\n    .e insert 0 abcdefghijklmnopqrs\n    .e xview 6\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.315789 0.842105}\ntest entry-17.4 {EntryUpdateScrollbar procedure} -setup {\n    proc bgerror msg {\n\tglobal textVar\n\tset textVar $msg\n}\n} -body {\n    entry .e -width 5\n    pack .e\n    update\n    set scrollInfo wrong\n    .e configure -xscrollcommand thisisnotacommand\n    update\n    list $textVar $errorInfo\n} -cleanup {\n    destroy .e\n    rename bgerror {}\n} -result {{invalid command name \"thisisnotacommand\"} {invalid command name \"thisisnotacommand\"\n    while executing\n\"thisisnotacommand 0.0 1.0\"\n    (horizontal scrolling command executed by .e)}}\n\n\ntest entry-18.1 {Entry widget vs hiding} -setup {\n    entry .e\n} -body {\n    set l [interp hidden]\n    interp hide {} .e\n    destroy .e\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 eq $res2}\n} -result 1\n\n##\n## Entry widget VALIDATION tests\n##\n# The validation tests build each one upon the previous, so cascading\n# failures aren't good\n#\n\n# 19.* test cases in previous version highly depended on the previous\n# test cases. This was replaced by inserting recently set configurations\n# that matters for the test case\ntest entry-19.1 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 a\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 0 a {} a all key}\n\ntest entry-19.2 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 a   ;# previous settings\n    .e insert 1 b\n    return $validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 1 ab a b all key}\n\ntest entry-19.3 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 ab   ;# previous settings\n    .e insert end c\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 2 abc ab c all key}\n\ntest entry-19.4 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 abc   ;# previous settings\n    .e insert 1 123\n    list $validationData $textVar\n} -cleanup {\n    destroy .e\n} -result {{.e 1 1 a123bc abc 123 all key} a123bc}\n\ntest entry-19.5 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 a123bc   ;# previous settings\n    .e delete 2\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 0 2 a13bc a123bc 2 all key}\n\ntest entry-19.6 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 a13bc   ;# previous settings\n    .e configure -validate key\n    .e delete 1 3\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 0 1 abc a13bc 13 key key}\n\ntest entry-19.7 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focus \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abc                 ;# previous settings\n    set validationData {}\n    .e insert end d\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest entry-19.8 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e configure -validate focus    ;# previous settings\n    .e insert end abcd              ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focus focusin}\n\ntest entry-19.9 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focus \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd      ;# previous settings\n    focus -force .e         ;# previous settings\n    update                  ;# previous settings\n# update necessary to process FocusIn event\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focus focusout}\n\ntest entry-19.10 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd          ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} all focusin}\n\ntest entry-19.11 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd          ;# previous settings\n    focus -force .e             ;# previous settings\n# update necessary to process FocusIn event\n    update                      ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} all focusout}\n\ntest entry-19.12 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focusin \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert 0 abcd              ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focusin focusin}\n\ntest entry-19.13 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focusin \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd              ;# previous settings\n    set validationData {}\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest entry-19.14 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd              ;# previous settings\n    set validationData {}                  ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest entry-19.15 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd              ;# previous settings\n    set validationData {}                  ;# previous settings\n    focus -force .e                 ;# previous settings\n# update necessary to process FocusIn event\n    update                          ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focusout focusout}\n\n# the same as 19.16 but added [.e validate] to returned list\ntest entry-19.16 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd              ;# previous settings\n    set validationData {}                  ;# previous settings\n    focus -force .e                 ;# previous settings\n# update necessary to process FocusIn event\n    update                          ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    list [.e validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {1 {.e -1 -1 abcd abcd {} all forced}}\n\n\ntest entry-19.17 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    .e insert end abcd              ;# previous settings\n    set textVar newdata\n    list [.e cget -validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {focusout {.e -1 -1 newdata abcd {} focusout forced}}\n\n\n# Using validateCmd3, which returns 0\ntest entry-19.18 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd3 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    set textVar newdata                 ;# previous settings\n    .e configure -validate all\n    set textVar nextdata\n    list [.e cget -validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {none {.e -1 -1 nextdata newdata {} all forced}}\n\n## This sets validate to none because it shows that we prevent a possible\n## loop condition in the validation, when the entry textvar is also set\n# Using validateCmd2\ntest entry-19.19 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd3 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    set textVar nextdata                 ;# previous settings\n\n    .e configure -validatecommand $validateCmd2\n    .e validate\n    list [.e cget -validate] [.e get] $validationData\n} -cleanup {\n    destroy .e\n} -result {none nextdata {.e -1 -1 nextdata nextdata {} all forced}}\n\n## This leaves validate alone because we trigger validation through the\n## textvar (a write trace), and the write during validation triggers\n## nothing (by definition of avoiding loops on var traces).  This is\n## one of those \"dangerous\" conditions where the user will have a\n## different value in the entry widget shown as is in the textvar.\ntest entry-19.20 {entry widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e ; update idletasks\n    set textVar nextdata                 ;# previous settings\n    .e configure -validatecommand $validateCmd2 ;# prev\n    .e validate                     ;# previous settings\n\n    .e configure -validate all\n    set textVar testdata\n    list [.e cget -validate] [.e get] $textVar $validationData\n} -cleanup {\n    destroy .e\n} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}\n\n## This leaves validate alone because we trigger validation through the\n## textvar (a write trace), and the write during validation triggers\n## nothing (by definition of avoiding loops on var traces).  This is\n## one of those \"dangerous\" conditions where the user will have a\n## different value in the entry widget shown as is in the textvar.\ntest entry-19.21 {entry widget validation - bug 40e4bf6198} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    entry .e -validate key \\\n\t-validatecommand $validateCmd2 \\\n\t-textvariable textVar\n    pack .e ; update idletasks\n    set textVar origdata\n    .e insert 0 A\n    list [.e cget -validate] [.e get] $textVar $validationData\n} -cleanup {\n    destroy .e\n} -result {none origdata mydata {.e 1 0 Aorigdata origdata A key key}}\n\n##\n## End validation tests\n##\n\ntest entry-20.1 {widget deletion while active} -body {\n    entry .e -validate all \\\n\t    -validatecommand { destroy %W ; return 1 } \\\n\t    -invalidcommand bell\n    update\n    .e insert 0 abc\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.2 {widget deletion while active} -body {\n    entry .e -validate all \\\n\t    -validatecommand { return 0 } \\\n\t    -invalidcommand { destroy %W }\n    .e insert 0 abc\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.3 {widget deletion while active} -body {\n    entry .e -validate all \\\n\t    -validatecommand { rename .e {} ; return 1 }\n    .e insert 0 abc\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.4 {widget deletion while active} -body {\n    entry .e -validate all \\\n\t    -validatecommand { return 0 } \\\n\t    -invalidcommand { rename .e {} }\n    .e insert 0 abc\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.5 {widget deletion while active} -body {\n    entry .e -validatecommand { destroy .e ; return 0 }\n    .e validate\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.6 {widget deletion while active} -body {\n    pack [entry .e]\n    update\n    .e config -xscrollcommand { destroy .e }\n    update idle\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest entry-20.7 {widget deletion with textvariable active} -body {\n# SF bugs 607390 and 617446\n    set FOO init\n    entry .e -textvariable FOO -validate all \\\n\t    -validatecommand {%W configure -bg white; format 1}\n    bind .e <Destroy> { set FOO hello }\n    destroy .e\n    winfo exists .e\n} -cleanup {\n    destroy .e\n} -result 0\n\n\ntest entry-21.1 {selection present while disabled, bug 637828} -body {\n    entry .e\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    set out [.e selection present]\n    .e configure -state disabled\n# still return 1 when disabled, because 'selection get' will work,\n# but selection cannot be changed (new behavior since 8.4)\n    .e select to 9\n    lappend out [.e selection present] [selection get]\n} -cleanup {\n    destroy .e\n} -result {1 1 345}\n\ntest entry-22.1 {lost namespaced textvar} -body {\n    namespace eval test { variable foo {a b} }\n    entry .e -textvariable ::test::foo\n    namespace delete test\n    set ::test::foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {can't read \"::test::foo\": no such variable}\ntest entry-22.2 {lost namespaced textvar} -body {\n    namespace eval test { variable foo {a b} }\n    entry .e -textvariable ::test::foo\n    namespace delete test\n    catch {.e insert end \"more stuff\"} result1\n    catch {.e delete 5 end } result2\n    catch {set ::test::foo} result3\n    list [.e get] [.e cget -textvar] $result1 $result2 $result3\n} -cleanup {\n    destroy .e\n} -result [list \"a bmo\" ::test::foo \\\n\t{can't set \"::test::foo\": parent namespace doesn't exist} \\\n\t{can't set \"::test::foo\": parent namespace doesn't exist} \\\n\t{can't read \"::test::foo\": no such variable}]\n\ntest entry-23.1 {error in trace proc attached to the textvariable} -setup {\n    destroy .e\n} -body {\n    trace add variable myvar write traceit\n    proc traceit args {error \"Intentional error here!\"}\n    entry .e -textvariable myvar\n    catch {.e insert end mystring} result1\n    catch {.e delete 0} result2\n    list $result1 $result2\n} -cleanup {\n    destroy .e\n} -result [list {can't set \"myvar\": Intentional error here!} \\\n    {can't set \"myvar\": Intentional error here!}]\n\ntest entry-24.1 {textvariable lives in a non-existing namespace} -setup {\n    destroy .e\n} -body {\n    catch {entry .e -textvariable thisnsdoesntexist::myvar} result1\n    set result1\n} -cleanup {\n  destroy .e\n} -result {can't trace \"thisnsdoesntexist::myvar\": parent namespace doesn't exist}\n\ntest entry-25.1 {Bug [5d991b822e]} {\n    # Want this not to segfault, or write to variable with empty name\n    set var INIT\n    entry .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n    info exists {}\n} 0\ntest entry-25.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    entry .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\ntest entry-25.3 {Bug [2a32225cd1] - Navigation in a password made of several words} -setup {\n    destroy .e\n    pack [entry .e -show *]\n    update\n    set res {}\n} -body {\n    .e insert end \"A sample password made of several words\"\n    .e icursor end\n    event generate .e <<PrevWord>>  ; # shall move insert to index 0\n    .e delete insert end\n    lappend res [.e get]\n    .e insert end \"A sample password made of several words\"\n    .e icursor 2\n    event generate .e <<NextWord>>  ; # shall move insert to index end\n    .e delete 0 insert\n    lappend res [.e get]\n} -cleanup {\n    destroy .e\n} -result {{} {}}\n\n#\n# TESTFILE CLEANUP\n#\n\n# option clear\nforeach i {1 2 3} {\n    unset validateCmd$i\n}\nunset i\ntestutils forget entry scroll\ncleanupTests\n\n"
  },
  {
    "path": "tests/event.test",
    "content": "# This file is a Tcl script to test the code in tkEvent.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is woefully incomplete.  Right now it only tests\n# a few of the procedures in tkEvent.c.  Please add more tests whenever\n# possible.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# _get_selection --\n#\n#    Return selection only if owned by the given widget\n#\nproc _get_selection {widget} {\n    if {[string compare $widget [selection own]] != 0} {\n\treturn \"\"\n    }\n    if {[catch {selection get} sel]} {\n\treturn \"\"\n    }\n    return $sel\n}\n\n# _init_keypress_lookup --\n#\n#    Setup table used to query key events.\n#\nproc _init_keypress_lookup {} {\n    global keypress_lookup\n\n    # Characters with meaning to Tcl...\n    array set keypress_lookup [list \\\n\t    -    minus \\\n\t    >    greater \\\n\t    \\\"   quotedbl \\\n\t    \\#   numbersign \\\n\t    \\$   dollar \\\n\t    \\;   semicolon \\\n\t    \\[   bracketleft \\\n\t    \\\\   backslash \\\n\t    \\]   bracketright \\\n\t    \\{   braceleft \\\n\t    \\}   braceright \\\n\t    \" \"  space \\\n\t    \\xA0 nobreakspace \\\n\t    \"\\n\" Return \\\n\t    \"\\t\" Tab]\n}\n\n# _keypress --\n#\n#    Lookup and generate a pair of Key and KeyRelease events\n#\nproc _keypress {win key} {\n    set keysym [_keypress_lookup $key]\n\n    # Force focus to the window before delivering\n    # each event so that a window manager using\n    # a focus follows mouse will not steal away\n    # the focus if the mouse is moved around.\n\n    if {[focus] ne $win} {\n\tfocus -force $win\n    }\n    event generate $win <Key-$keysym>\n    pause 50\n    if {[focus] ne $win} {\n\tfocus -force $win\n    }\n    event generate $win <KeyRelease-$keysym>\n    pause 50\n}\n\n# _keypress_lookup --\n#\n#    Lookup an event in the keypress table.\n#\n#    For example:\n#\t Q -> Q\n#\t ; -> semicolon\n#\t > -> greater\n#\t Delete -> Delete\n#\t Escape -> Escape\n#\nproc _keypress_lookup {char} {\n    global keypress_lookup\n\n    if {! [info exists keypress_lookup]} {\n\t_init_keypress_lookup\n    }\n\n    if {$char eq \"\"} {\n\terror \"empty char\"\n    }\n\n    if {[info exists keypress_lookup($char)]} {\n\treturn $keypress_lookup($char)\n    } else {\n\treturn $char\n    }\n}\n\n# _keypress_string --\n#\n#    Call _keypress for each character in the given string\n#\nproc _keypress_string {win string} {\n    foreach letter [split $string \"\"] {\n\t_keypress $win $letter\n    }\n}\n\n# _text_ind_to_x_y --\n#\n#    Helper proc to convert index to x y position\n#\nproc _text_ind_to_x_y {text ind} {\n    set bbox [$text bbox $ind]\n    if {[llength $bbox] != 4} {\n\terror \"got bbox \\{$bbox\\} from $text, index $ind\"\n    }\n    foreach {x1 y1 width height} $bbox break\n    set middle_y [expr {$y1 + ($height / 2)}]\n    return [list $x1 $middle_y]\n}\n\nproc create_and_pack_frames {{w {}}} {\n    frame $w.f1 -bg blue -width 200 -height 200\n    pack propagate $w.f1 0\n    frame $w.f1.f2 -bg yellow -width 100 -height 100\n    pack $w.f1.f2 $w.f1 -side bottom -anchor se\n    update idletasks\n}\n\n# setup_win_mousepointer --\n#\n#    Position the window and the mouse pointer as an initial state for some tests.\n#    The so-called \"pointer window\" is the $w window that will now contain the mouse pointer.\n#\nproc setup_win_mousepointer {w} {\n    wm geometry . +700+400; # root window out of our way - must not cover windows from event-9.1*\n    toplevel $w\n    pack propagate $w 0\n    wm geometry $w 300x300+100+100\n    tkwait visibility $w\n    update; # service remaining screen drawing events (e.g. <Expose>)\n    set pointerWin [winfo containing [winfo pointerx $w] [winfo pointery $w]]\n    event generate $w <Motion> -warp 1 -x 250 -y 250\n    if {($pointerWin ne $w) && ([tk windowingsystem] ne \"aqua\")} {\n\twaitForWindowEvent $w <Enter>\n    } else {\n\tcontrolPointerWarpTiming\n    }\n}\n\n# waitForWindowEvent --\n#\n#    This proc is intended to overcome latency of windowing system\n#    notifications when toplevel windows are involved. These latencies vary\n#    considerably with the window manager in use, with the system load,\n#    with configured scheduling priorities for processes, etc ...\n#    Waiting for the corresponding window events evades the trouble that is\n#    associated with the alternative: waiting or halting the Tk process for a\n#    fixed amount of time (using \"after ms\"). With the latter strategy it's\n#    always a gamble how much waiting time is enough on an end user's system.\n#    It also leads to long fixed waiting times in order to be on the safe side.\n#\nproc waitForWindowEvent {w event {timeout 1000}} {\n\n    variable _windowEvent\n\n    # Use counter as a unique ID to prevent subsequent waits\n    # from interfering with each other.\n    set counter [incr _windowEvent(counter)]\n    set _windowEvent($counter) 1\n    set savedBinding [bind $w $event]\n    bind $w $event [list +waitForWindowEvent.signal $counter]\n    set afterID [after $timeout [list set _windowEvent($counter) -1]]\n    vwait _windowEvent($counter)\n    set late [expr {$_windowEvent($counter) == -1}]\n    bind $w $event $savedBinding\n    unset _windowEvent($counter)\n    if {$late} {\n\tputs stderr \"wait for $event event on $w timed out (> $timeout ms)\"\n    } else {\n\tafter cancel $afterID\n    }\n}\n\n# waitForWindowEvent.signal--\n#\n#    Helper proc that records the triggering of a window event.\n#\nproc waitForWindowEvent.signal {counter} {\n    incr ::_windowEvent($counter)\n}\n\n#\n# TESTS\n#\n\ntest event-1.1 {Tk_HandleEvent procedure, filter events for dead windows} -setup {\n\tdeleteWindows\n    set x {}\n} -body {\n    button .b -text Test\n    pack .b\n    bindtags .b .b\n    update\n    bind .b <Destroy> {\n\t    lappend x destroy\n\t    event generate .b <Button-1>\n\t    event generate .b <ButtonRelease-1>\n    }\n    bind .b <Button-1> {\n\t    lappend x button\n    }\n\n    destroy .b\n    return $x\n} -cleanup {\n    deleteWindows\n} -result {destroy}\ntest event-1.2 {event generate <Alt-z>} -setup {\n\tdeleteWindows\n    catch {unset ::event12result}\n} -body {\n\tset ::event12result 0\n\tpack [entry .e]\n\tupdate\n\tbind .e <Alt-z> {set ::event12result \"1\"}\n\n\tfocus -force .e\n     event generate .e <Alt-z>\n\tdestroy .e\n\tset ::event12result\n} -cleanup {\n    deleteWindows\n} -result 1\n\n\ntest event-2.1(keypress) {type into entry widget and hit Return} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    set return_binding 0\n    bind $e <Return> {set return_binding 1}\n    tkwait visibility $e\n    _keypress_string $e HELLO\\n\n    list [$e get] $return_binding\n} -cleanup {\n    deleteWindows\n} -result {HELLO 1}\ntest event-2.2(keypress) {type into entry widget and then delete some text} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    # Avoid a hang when macOS puts the mouse pointer on the green button\n    wm geometry .t +200+100\n    _keypress_string $e MELLO\n    _keypress $e BackSpace\n    _keypress $e BackSpace\n    $e get\n} -cleanup {\n    deleteWindows\n} -result {MEL}\ntest event-2.3(keypress) {type into entry widget, triple click, hit Delete key,\n\tand then type some more} -setup {\n    deleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e JUMP\n\n    set result [$e get]\n\n    event generate $e <Enter>\n    for {set i 0} {$i < 3} {incr i} {\n\tpause 100\n\tevent generate $e <Button-1>\n\tpause 100\n\tevent generate $e <ButtonRelease-1>\n    }\n\n    _keypress $e Delete\n    _keypress_string $e UP\n    lappend result [$e get]\n} -cleanup {\n    deleteWindows\n} -result {JUMP UP}\ntest event-2.4(keypress) {type into text widget and hit Return} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    set return_binding 0\n    bind $e <Return> {set return_binding 1}\n    tkwait visibility $e\n    _keypress_string $e HELLO\\n\n    list [$e get 1.0 end] $return_binding\n} -cleanup {\n    deleteWindows\n} -result [list \"HELLO\\n\\n\" 1]\ntest event-2.5(keypress) {type into text widget and then delete some text} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e MELLO\n    _keypress $e BackSpace\n    _keypress $e BackSpace\n    $e get 1.0 1.end\n} -cleanup {\n    deleteWindows\n} -result {MEL}\ntest event-2.6(keypress) {type into text widget, triple click,\n    hit Delete key, and then type some more} -setup {\n\tdeleteWindows\n\tupdate idletasks\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e JUMP\n\n    set result [$e get 1.0 1.end]\n\n    event generate $e <Enter>\n    for {set i 0} {$i < 3} {incr i} {\n\tpause 100\n\tevent generate $e <Button-1>\n\tpause 100\n\tevent generate $e <ButtonRelease-1>\n    }\n\n    _keypress $e Delete\n    _keypress_string $e UP\n    lappend result [$e get 1.0 1.end]\n} -cleanup {\n    deleteWindows\n} -result {JUMP UP}\n\ntest event-3.1(click-drag) {click and drag in a text widget, this tests\n    tkTextSelectTo in text.tcl} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e \"A Tcl/Tk selection test!\"\n    set anchor 1.6\n    set selend 1.18\n\n    set result [list]\n    lappend result [$e get 1.0 1.end]\n\n    # Get the x,y coords of the second T in \"Tcl/Tk\"\n    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break\n\n    # Click down to set the insert cursor position\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Now drag until selend is highlighted, then click up\n\n    set current $anchor\n    while {[$e compare $current <= $selend]} {\n\tforeach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\tevent generate $e <B1-Motion> -x $current_x -y $current_y\n\tset current [$e index [list $current + 1 char]]\n\tpause 50\n    }\n\n    event generate $e <ButtonRelease-1> -x $current_x -y $current_y\n    pause 200\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Save the highlighted text\n    lappend result [_get_selection $e]\n\n    # Now click and click and drag to the left, over \"Tcl/Tk selection\"\n\n    event generate $e <Button-1> -x $current_x -y $current_y\n\n    while {[$e compare $current >= [list $anchor - 4 char]]} {\n\tforeach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\tevent generate $e <B1-Motion> -x $current_x -y $current_y\n\tset current [$e index [list $current - 1 char]]\n\tpause 50\n    }\n\n    event generate $e <ButtonRelease-1> -x $current_x -y $current_y\n    pause 200\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Save the highlighted text\n    lappend result [_get_selection $e]\n\n} -cleanup {\n    deleteWindows\n} -result {{A Tcl/Tk selection test!} 1.6 1.18 {Tk selection} 1.2 {Tcl/Tk selection}}\n test event-3.2(click-drag) {click and drag in an entry widget, this\n    tests tkEntryMouseSelect in entry.tcl} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e \"A Tcl/Tk selection!\"\n    set anchor 6\n    set selend 18\n\n    set result [list]\n    lappend result [$e get]\n\n    # Get the x,y coords of the second T in \"Tcl/Tk\"\n    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break\n\n    # Click down to set the insert cursor position\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Now drag until selend is highlighted, then click up\n\n    set current $anchor\n    while {$current <= $selend} {\n\tforeach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\tevent generate $e <B1-Motion> -x $current_x -y $current_y\n\tincr current\n\tpause 50\n    }\n\n    event generate $e <ButtonRelease-1> -x $current_x -y $current_y\n    pause 200\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Save the highlighted text\n    lappend result [_get_selection $e]\n\n    # Now click and click and drag to the left, over \"Tcl/Tk selection\"\n\n    event generate $e <Button-1> -x $current_x -y $current_y\n\n    while {$current >= ($anchor - 4)} {\n\tforeach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\tevent generate $e <B1-Motion> -x $current_x -y $current_y\n\tincr current -1\n\tpause 50\n    }\n\n    event generate $e <ButtonRelease-1> -x $current_x -y $current_y\n    pause 200\n\n    # Save the position of the insert cursor\n    lappend result [$e index insert]\n\n    # Save the highlighted text\n    lappend result [_get_selection $e]\n\n} -cleanup {\n    deleteWindows\n} -result {{A Tcl/Tk selection!} 6 18 {Tk selection} 2 {Tcl/Tk selection}}\n\n\ntest event-4.1(double-click-drag) {click down, click up, click down again,\n    then drag in a text widget} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e \"Word select test\"\n    set anchor 1.8\n\n    # Get the x,y coords of the second e in \"select\"\n    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break\n\n    # Click down, release, then click down again\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n\n    # Save the highlighted text\n    set result [list]\n    lappend result [_get_selection $e]\n\n    # Insert cursor should be at beginning of \"select\"\n    lappend result [$e index insert]\n\n    # Move mouse one character to the left\n    set current [$e index [list $anchor - 1 char]]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    # Insert cursor should be before the l in \"select\"\n    lappend result [$e index insert]\n\n    # Selection should still be the word \"select\"\n    lappend result [_get_selection $e]\n\n    # Move mouse to the space before the word \"select\"\n    set current [$e index [list $current - 3 char]]\n\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 200\n\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    # Move mouse to the r in \"Word\"\n    set current 1.2\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    # Selection should now be \"Word select\"\n    lappend result [_get_selection $e]\n\n    # Insert cursor should be before the r in \"Word\"\n    lappend result [$e index insert]\n\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {select 1.5 1.7 select 1.4 { select} {Word select} 1.2}\ntest event-4.2(double-click-drag) {click down, click up, click down again,\n    then drag in an entry widget} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e \"Word select test\"\n\n    set anchor 8\n\n    # Get the x,y coords of the second e in \"select\"\n    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break\n\n    # Click down, release, then click down again\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n\n    set result [list]\n    lappend result [_get_selection $e]\n\n    # Insert cursor should be at the end of \"select\"\n    lappend result [$e index insert]\n\n    # Move mouse one character to the left\n    set current [expr {$anchor - 1}]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    # Insert cursor should be before the l in \"select\"\n    lappend result [$e index insert]\n\n    # Selection should still be the word \"select\"\n    lappend result [_get_selection $e]\n\n    # Move mouse to the space before the word \"select\"\n    set current [expr {$current - 3}]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    # Move mouse to the r in \"Word\"\n    set current [expr {$current - 2}]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    # Selection should now be \"Word select\"\n    lappend result [_get_selection $e]\n\n    # Insert cursor should be before the r in \"Word\"\n    lappend result [$e index insert]\n\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {select 11 7 select 4 { select} {Word select} 2}\n\ntest event-5.1(triple-click-drag) {Triple click and drag across lines in a\n\ttext widget, this should extend the selection to the new line} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    _keypress_string $e \"LINE ONE\\nLINE TWO\\nLINE THREE\"\n\n    set anchor 3.2\n\n    # Triple click one third line leaving mouse down\n\n    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break\n\n    event generate $e <Enter>\n\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y\n    pause 50\n\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y\n    pause 50\n\n    event generate $e <Button-1> -x $anchor_x -y $anchor_y\n    pause 50\n\n    set result [list]\n    lappend result [_get_selection $e]\n\n    # Drag up to second line\n\n    set current [$e index [list $anchor - 1 line]]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    lappend result [_get_selection $e]\n\n    # Drag up to first line\n\n    set current [$e index [list $current - 1 line]]\n    foreach {current_x current_y} [_text_ind_to_x_y $e $current] break\n\n    event generate $e <B1-Motion> -x $current_x -y $current_y\n    pause 50\n\n    lappend result [_get_selection $e]\n\n    return $result\n} -cleanup {\n    deleteWindows\n} -result [list \"LINE THREE\\n\" \"LINE TWO\\nLINE THREE\\n\" \\\n\t\"LINE ONE\\nLINE TWO\\nLINE THREE\\n\"]\n\ntest event-6.1(button-state) {button press in a window that is then\n\tdestroyed, when the mouse is moved into another window it\n\tshould not generate a <B1-motion> event since the mouse\n\twas not pressed down in that window} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n\n    event generate $t <Button-1>\n    destroy $t\n    set t [toplevel .t]\n    set motion nomotion\n    bind $t <B1-Motion> {set motion inmotion}\n    event generate $t <Motion>\n    return $motion\n} -cleanup {\n    deleteWindows\n} -result {nomotion}\n\ntest event-7.1(double-click) {A double click on a lone character\n    in a text widget should select that character} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [text $t.e]\n    pack $e\n    tkwait visibility $e\n    focus -force $e\n    _keypress_string $e \"On A letter\"\n\n    set anchor 1.3\n\n    # Get x,y coords just inside the left\n    # and right hand side of the letter A\n    foreach {x1 y1 width height} [$e bbox $anchor] break\n\n    set middle_y [expr {$y1 + ($height / 2)}]\n\n    set left_x [expr {$x1 + 2}]\n    set left_y $middle_y\n\n    set right_x [expr {($x1 + $width) - 2}]\n    set right_y $middle_y\n\n    # Double click near left hand egde of the letter A\n\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <Button-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $left_x -y $left_y\n    pause 50\n\n    set result [list]\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    # Clear selection by clicking at 0,0\n\n    event generate $e <Button-1> -x 0 -y 0\n    pause 50\n    event generate $e <ButtonRelease-1> -x 0 -y 0\n    pause 50\n\n    # Double click near right hand edge of the letter A\n\n    event generate $e <Button-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <Button-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $right_x -y $right_y\n    pause 50\n\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    return $result\n} -cleanup {\n    deleteWindows\n    unset x1 y1 width height middle_y left_x left_y right_x right_y\n} -result {1.3 A 1.3 A}\ntest event-7.2(double-click) {A double click on a lone character\n    in an entry widget should select that character} -setup {\n\tdeleteWindows\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    focus -force $e\n    _keypress_string $e \"On A letter\"\n\n    set anchor 3\n\n    # Get x,y coords just inside the left\n    # and right hand side of the letter A\n    foreach {x1 y1 width height} [$e bbox $anchor] break\n\n    set middle_y [expr {$y1 + ($height / 2)}]\n\n    set left_x [expr {$x1 + 2}]\n    set left_y $middle_y\n\n    set right_x [expr {($x1 + $width) - 2}]\n    set right_y $middle_y\n\n    # Double click near left hand egde of the letter A\n\n    event generate $e <Enter>\n    event generate $e <Button-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <Button-1> -x $left_x -y $left_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $left_x -y $left_y\n    pause 50\n\n    set result [list]\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    # Clear selection by clicking at 0,0\n\n    event generate $e <Button-1> -x 0 -y 0\n    pause 50\n    event generate $e <ButtonRelease-1> -x 0 -y 0\n    pause 50\n\n    # Double click near right hand edge of the letter A\n\n    event generate $e <Button-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <Button-1> -x $right_x -y $right_y\n    pause 50\n    event generate $e <ButtonRelease-1> -x $right_x -y $right_y\n    pause 50\n\n    lappend result [$e index insert]\n    lappend result [_get_selection $e]\n\n    return $result\n} -cleanup {\n    deleteWindows\n    unset x1 y1 width height middle_y left_x left_y right_x right_y\n} -result {4 A 4 A}\n\ntest event-8 {event generate with keysyms corresponding to\n\t      multi-byte virtual keycodes - bug\n\t      e36963bfe8df9f5e528134707a91b9c0051de723} -constraints nonPortable -setup {\n    deleteWindows\n    set res [list ]\n} -body {\n    set t [toplevel .t]\n    set e [entry $t.e]\n    pack $e\n    tkwait visibility $e\n    bind $e <Key> {lappend res keycode: %k keysym: %K}\n    focus -force $e\n    update\n    event generate $e <diaeresis>\n    # The value now contained in $res depends on the actual\n    # physical keyboard layout and keycode generated, from\n    # the hardware on which the test suite happens to run.\n    # We don't need (and we can't really) check correctness\n    # of the (system-dependent) keycode received, however\n    # Tk should be able to associate this keycode to a\n    # (system-independent) known keysym, unless the system\n    # running the test does not have a keyboard with a\n    # diaeresis key.\n    if {[lindex $res 3] ne \"??\"} {\n\t# keyboard has a physical diaeresis key and bug is fixed\n\treturn \"OK\"\n    } else  {\n\treturn \"Test failed, unless the keyboard tied to the system \\\n\t\ton which this test is run does NOT have a diaeresis \\\n\t\tphysical key - in this case, test is actually void.\"\n    }\n} -cleanup {\n    deleteWindows\n} -result {OK}\n\ntest event-9.1 {enter . window by destroying a toplevel - bug b1d115fa60} -setup {\n    set EnterBind [bind . <Enter>]\n} -body {\n    wm geometry . 200x200+300+300\n    wm deiconify .\n    pause 200\n    toplevel .top2 -width 200 -height 200\n    wm geometry .top2 +[expr {[winfo rootx .]+50}]+[expr {[winfo rooty .]+50}]\n    update idletasks\n    wm deiconify .top2\n    update idletasks\n    raise .top2\n    pause 400\n    event generate .top2 <Motion> -warp 1 -x 50 -y 50\n    pause 100\n    bind . <Enter> {lappend res %W}\n    set res [list ]\n    destroy .top2\n    update idletasks\n    pause 200\n    set res\n} -cleanup {\n    deleteWindows\n    bind . <Enter> $EnterBind\n} -result {.}\n\n# This test fails sporadically when run on the macOS CI runner. It does\n# not seem to fail on real computers.  It is not needed since the same\n# thing is tested by 9.13.  So it is simpler to constrain it as notAqua.\ntest event-9.2 {enter toplevel window by destroying a toplevel - bug b1d115fa60} \\\n-constraints { notAqua} \\\n-setup {\n    set iconified false\n    if {[winfo ismapped .]} {\n\twm iconify .\n\tupdate\n\tset iconified true\n    }\n} -body {\n    toplevel .top1\n    wm geometry .top1 200x200+300+300\n    wm deiconify .top1\n    pause 200\n    toplevel .top2 -width 200 -height 200\n    wm geometry .top2 +[expr {[winfo rootx .top1]+50}]+[expr {[winfo rooty .top1]+50}]\n    pause 200\n    wm deiconify .top2\n    update idletasks\n    raise .top2\n    pause 400\n    event generate .top2 <Motion> -warp 1 -x 50 -y 50\n    pause 100\n    bind .top1 <Enter> {lappend res %W}\n    set res [list ]\n    destroy .top2\n    pause 200\n    set res\n} -cleanup {\n    deleteWindows ; # destroy all children of \".\", this already includes .top1\n    if {$iconified} {\n\twm deiconify .\n\tupdate\n    }\n} -result {.top1}\n\ntest event-9.11 {pointer window container = parent} -setup {\n    setup_win_mousepointer .one\n    wm withdraw .one\n    create_and_pack_frames .one\n    wm deiconify .one\n    tkwait visibility .one.f1.f2\n    pause 200; # needed for Windows\n    update idletasks; # finish display of window\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .one.f1.f2\n    update\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyInferior .one.f1|}\n\ntest event-9.12 {pointer window container != parent} -setup {\n    setup_win_mousepointer .one\n    wm withdraw .one\n    create_and_pack_frames .one\n    pack propagate .one.f1.f2 0\n    pack [frame .one.g -bg orange -width 80 -height 80] -anchor se -side bottom -in .one.f1.f2\n    wm deiconify .one\n    tkwait visibility .one.g\n    event generate .one <Motion> -warp 1 -x 250 -y 250\n    pause 200; # needed for Windows\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .one.g\n    update\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyNonlinearVirtual .one.f1|<Enter> NotifyNonlinear .one.f1.f2|}\n\ntest event-9.13 {pointer window is a toplevel, toplevel destination} -setup {\n    setup_win_mousepointer .one\n    toplevel .two\n    wm geometry .two 300x300+150+150\n    wm withdraw .two\n    wm deiconify .two\n    waitForWindowEvent .two <Enter>\n    update idletasks; # finish displaying windows\n    set result |\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .two\n    waitForWindowEvent .one <Enter>\n    update\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyNonlinear .one|}\n\ntest event-9.14 {pointer window is a toplevel, tk internal destination} -setup {\n    setup_win_mousepointer .one\n    wm withdraw .one\n    create_and_pack_frames .one\n    toplevel .two\n    wm geometry .two 300x300+150+150\n    wm withdraw .two\n    wm deiconify .one\n    wm deiconify .two\n    waitForWindowEvent .two <Enter>\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .two\n    waitForWindowEvent .one.f1.f2 <Enter>\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyNonlinearVirtual .one|<Enter> NotifyNonlinearVirtual .one.f1|<Enter> NotifyNonlinear .one.f1.f2|}\n\ntest event-9.15 {pointer window is a toplevel, destination is screen root.\n    Due to a malfunction on macOS Sequoia and older (see bug #c494cc25c4), this test is skipped on those OS versions.  It also fails sporadically on the macOS CI runner.\n} -constraints {notMacosSequoiaOrOlder notMacCI} -setup {\n    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)\n#    destroy .one\n    toplevel .two\n    wm geometry .two 300x300+150+150\n    wm deiconify .two\n    waitForWindowEvent .two <Enter>\n    update idletasks; # finish displaying .two\n    event generate .two <Motion> -warp 1 -x 275 -y 275\n    controlPointerWarpTiming\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .two\n    update; # Ensure that crossing events get processed.\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|}\n\ntest event-9.16 {Successive destructions (pointer window + parent), single generation of crossing events} -setup {\n    # Tests correctness of overwriting the dead window struct in\n    # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave().\n    setup_win_mousepointer .one\n    wm withdraw .one\n    create_and_pack_frames .one\n    wm deiconify .one\n    tkwait visibility .one.f1.f2\n    update idletasks; # finish displaying window\n    pause 200; # needed for Windows\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .one.f1\n    update\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyInferior .one|}\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    after 1000; # Give Apple's _windowserver some time to catch up.\n    update\n}\n\ntest event-9.17 {Successive destructions (pointer window + parent), separate crossing events} -setup {\n    # Tests correctness of overwriting the dead window struct in\n    # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave().\n    setup_win_mousepointer .one\n    wm withdraw .one\n    create_and_pack_frames .one\n    wm deiconify .one\n    tkwait visibility .one.f1.f2\n    update idletasks; # finish displaying window\n    pause 200; # needed for Windows\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .one.f1.f2\n    update; # make sure window is gone\n    destroy .one.f1\n    update; # make sure window is gone\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyInferior .one.f1|<Enter> NotifyInferior .one|}\n\ntest event-9.18 {Successive destructions (pointer window + ancestors including its toplevel), destination is non-root toplevel} -setup {\n    setup_win_mousepointer .one\n    toplevel .two\n    pack propagate .two 0\n    wm geometry .two 300x300+100+100\n    create_and_pack_frames .two\n    wm deiconify .two\n    waitForWindowEvent .two.f1.f2 <Enter>\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .two\n    waitForWindowEvent .one <Enter>\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    unset result\n} -result {|<Enter> NotifyNonlinear .one|}\n\ntest event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup {\n    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)\n    wm geometry . +500+500; # avoid an extraneous <Leave> event\n    update idletasks\n    destroy .one\n    toplevel .two\n    pack propagate .two 0\n    wm geometry .two 300x300+100+100\n    create_and_pack_frames .two\n    wm deiconify .two\n    update idletasks; # make sure two is there\n    toplevel .three\n    pack propagate .three 0\n    wm geometry .three 300x300+110+110\n    create_and_pack_frames .three\n    wm deiconify .three\n    waitForWindowEvent .three.f1.f2 <Enter>\n    update idletasks; # finish displaying windows\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .three\n    waitForWindowEvent .two.f1.f2 <Enter>\n    update idletasks; #finish destroying .two\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .one\n    destroy .two\n    unset result\n} -result {|<Enter> NotifyNonlinearVirtual .two|<Enter> NotifyNonlinearVirtual .two.f1|<Enter> NotifyNonlinear .two.f1.f2|}\n\ntest event-9.20 {Successive destructions (pointer window + ancestors including its toplevel), destination is screen root.\n    Due to a malfunction on macOS Sequoia and older (see bug #c494cc25c4), this test is skipped on those OS versions.  It also fails sporadically on macOS CI runners.\n} -constraints {notMacosSequoiaOrOlder notMacCI} -setup {\n    setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test)\n    destroy .one\n    toplevel .two\n    pack propagate .two 0\n    wm geometry .two 300x300+100+100\n    create_and_pack_frames .two\n    wm deiconify .two\n    waitForWindowEvent .two.f1.f2 <Enter>\n    set result \"|\"\n} -body {\n    bind all <Leave> {append result \"<Leave> %d %W|\"}\n    bind all <Enter> {append result \"<Enter> %d %W|\"}\n    destroy .two\n    update; # Ensure that crossing events get processed.\n    set result\n} -cleanup {\n    bind all <Leave> {}\n    bind all <Enter> {}\n    unset result\n} -result {|}\n\ntest event-86299fe7ce {Generate window crossing events immediately upon pointer warp. See ticket #86299fe7ce} -setup {\n    deleteWindows\n    wm geometry . 200x200+100+100\n    wm deiconify .\n    after 10; update\n    # On MS Windows with bug present:\n    # Ensure that the test body starts immediately after a MOUSE_TIMER_INTERVAL\n    set pointerWin [winfo containing [winfo pointerx .] [winfo pointery .]]\n    if {$pointerWin eq \".\"} {\n\tevent generate . <Motion> -warp 1 -x -50 -y 50\n    }\n    event generate . <Motion> -warp 1 -x 50 -y 50\n    waitForWindowEvent . <Enter>; # ensures that a MOUSE_TIMER_INTERVAL just ended\n    bind all <Leave> {append result \"<Leave> %W\"}\n    bind all <Enter> {append result \"<Enter> %W\"}\n    set result \"|\"\n} -body {\n    # Let the screen pointer perform a back and forth warp in quick succession,\n    # while immediatly providing opportunity for the event loop to service any\n    # crossing events.\n    event generate . <Motion> -warp 1 -x -50 -y 50\n    update\n    append result \"|\"\n    event generate . <Motion> -warp 1 -x 50 -y 50\n    update\n    append result \"|\"\n    # On MS Windows with bug present:\n    # The TkWinPointerEvent mechanism doesn't detect the previous changes to\n    # the position of the screen pointer because the back and forth motion\n    # happens entirely within one MOUSE_TIMER_INTERVAL. The value for the\n    # result variable in this case is: \"|||\"\n    set result\n} -cleanup {\n    unset result\n    bind all <Leave> {}\n    bind all <Enter> {}\n} -result \"|<Leave> .|<Enter> .|\"\n\ntest event-c3f5c85322 {Aqua: incorrect crossing events upon pointer warp. See ticket #c3f5c85322} -setup {\n    wm geometry . 200x200+100+100\n    pack [frame .f -width 100 -height 200 -bg blue] -side right\n    after 10; update\n    event generate {} <Motion> -warp 1 -x 50 -y 100\n    after 10; update; # opportunity to service crossing events\n\n    set windowList [list \"{}\" . .f]\n    array set coords {\n        \"A,{}\" 150\n        \"B,{}\" 250\n        \"A,.\" 50\n        \"B,.\" 150\n        \"A,.f\" 50\n        \"B,.f\" 150\n        \"x,{},{}\" 50\n        \"x,{},.\" -50\n        \"x,{},.f\" -150\n        \"x,.,{}\" 150\n        \"x,.,.\" 50\n        \"x,.,.f\" -50\n        \"x,.f,{}\" 250\n        \"x,.f,.\" 150\n        \"x,.f,.f\" 50\n    }\n    set i 0\n    set yPos X\n\n    bind all <Leave> {append result \"<Leave> %W|\"}\n    bind all <Enter> {append result \"<Enter> %W|\"}\n    set result \"|\"\n} -body {\n    # The cases below exercise a pointer warp with source window, destination\n    # window and warp window varying over the fixed set of windows in windowList,\n    # utilizing the destination of a previous warp as the source for the next one.\n    foreach destWin $windowList {\n        foreach warpWin $windowList {\n            set srcWin $destWin\n            set yPos [expr {$yPos ne \"A\"?\"A\":\"B\"}]\n            set caseID {}\n            foreach w [list $srcWin $destWin $warpWin] {\n                append caseID [lsearch $windowList $w]\n            }\n            append result \"[incr i]($caseID)|\"\n            event generate [expr {$warpWin eq \"{}\"?\"\":$warpWin}] <Motion> -warp 1 \\\n                    -x $coords(x,$destWin,$warpWin) -y $coords($yPos,$warpWin)\n            after 10; update; # opportunity to service crossing events\n        }\n        if {$destWin eq [lindex $windowList end]} {\n            set nextDestWin \"{}\"\n        } else {\n            set nextDestWin [lindex $windowList [expr {[lsearch $windowList $destWin]+1}]]\n        }\n        set prevDestWin $destWin\n        foreach warpWin $windowList {\n            # don't swap yPos, but srcWin and destWin2\n            set destWin2 [expr {$prevDestWin eq $nextDestWin?$srcWin:$nextDestWin}]\n            set srcWin $prevDestWin\n            set prevDestWin $destWin2\n            set caseID {}\n            foreach w [list $srcWin $destWin2 $warpWin] {\n                append caseID [lsearch $windowList $w]\n            }\n            append result \"[incr i]($caseID)|\"\n            event generate [expr {$warpWin eq \"{}\"?\"\":$warpWin}] <Motion> -warp 1 \\\n                    -x $coords(x,$destWin2,$warpWin) -y $coords($yPos,$warpWin)\n            after 10; update; # opportunity to service crossing events\n        }\n    }\n    set result\n} -cleanup {\n    unset -nocomplain caseID coords i destWin destWin2 nextDestWin prevDestWin \\\n            result srcWin yPos warpWin windowList\n    bind all <Leave> {}\n    bind all <Enter> {}\n    destroy .f\n} -result {|1(000)|2(001)|3(002)|4(010)|<Enter> .|5(101)|<Leave> .|6(012)|<Enter> .|7(110)|8(111)|9(112)|10(120)|<Leave> .|<Enter> .f|11(211)|<Leave> .f|<Enter> .|12(122)|<Leave> .|<Enter> .f|13(220)|14(221)|15(222)|16(200)|<Leave> .f|<Leave> .|17(021)|<Enter> .|<Enter> .f|18(202)|<Leave> .f|<Leave> .|}\n\n#\n# TESTFILE CLEANUP\n#\n\n# macOS sometimes has trouble deleting the test window,\n# causing a failure in focus.test.\npause 200;\ndeleteWindows\nupdate\nunset -nocomplain keypress_lookup\nrename _init_keypress_lookup {}\nrename _keypress_lookup {}\nrename _keypress {}\nrename _text_ind_to_x_y {}\nrename _get_selection {}\nrename create_and_pack_frames {}\nrename setup_win_mousepointer {}\n\ncleanupTests\n"
  },
  {
    "path": "tests/face.xbm",
    "content": "#define face_width 108\n#define face_height 144\n#define face_x_hot 48\n#define face_y_hot 80\nstatic char face_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09,\n   0x20, 0x80, 0x24, 0x05, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x88,\n   0x24, 0x20, 0x80, 0x24, 0x00, 0x00, 0x00, 0x10, 0x80, 0x04, 0x00, 0x01,\n   0x00, 0x01, 0x40, 0x0a, 0x09, 0x00, 0x92, 0x04, 0x80, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x10, 0x40, 0x12, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x84,\n   0x24, 0x40, 0x22, 0xa8, 0x02, 0x14, 0x84, 0x92, 0x40, 0x42, 0x12, 0x04,\n   0x10, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x52, 0x11, 0x00, 0x12, 0x00,\n   0x40, 0x02, 0x00, 0x20, 0x00, 0x08, 0x00, 0xaa, 0x02, 0x54, 0x85, 0x24,\n   0x00, 0x10, 0x12, 0x00, 0x00, 0x81, 0x44, 0x00, 0x90, 0x5a, 0x00, 0xea,\n   0x1b, 0x00, 0x80, 0x40, 0x40, 0x02, 0x00, 0x08, 0x00, 0x20, 0xa2, 0x05,\n   0x8a, 0xb4, 0x6e, 0x45, 0x12, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10, 0x02,\n   0xa8, 0x92, 0x00, 0xda, 0x5f, 0x10, 0x00, 0x10, 0xa1, 0x04, 0x20, 0x41,\n   0x02, 0x00, 0x5a, 0x25, 0xa0, 0xff, 0xfb, 0x05, 0x41, 0x02, 0x04, 0x00,\n   0x00, 0x08, 0x40, 0x80, 0xec, 0x9b, 0xec, 0xfe, 0x7f, 0x01, 0x04, 0x20,\n   0x90, 0x02, 0x04, 0x00, 0x08, 0x20, 0xfb, 0x2e, 0xf5, 0xff, 0xff, 0x57,\n   0x00, 0x04, 0x02, 0x00, 0x00, 0x20, 0x01, 0xc1, 0x6e, 0xab, 0xfa, 0xff,\n   0xff, 0x05, 0x90, 0x20, 0x48, 0x02, 0x00, 0x04, 0x20, 0xa8, 0xdf, 0xb5,\n   0xfe, 0xff, 0xff, 0x0b, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x04, 0xe0,\n   0xbb, 0xef, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x04, 0x48, 0x02, 0x00, 0x20,\n   0x80, 0xf4, 0x6f, 0xfb, 0xff, 0xff, 0xff, 0x20, 0x90, 0x40, 0x02, 0x00,\n   0x00, 0x04, 0x08, 0xb8, 0xf6, 0xff, 0xff, 0xdf, 0xbe, 0x12, 0x45, 0x10,\n   0x90, 0x04, 0x90, 0x00, 0x22, 0xfa, 0xff, 0xff, 0xff, 0xbb, 0xd7, 0xe9,\n   0x3a, 0x02, 0x02, 0x00, 0x04, 0x90, 0x80, 0xfe, 0xdf, 0xf6, 0xb7, 0xef,\n   0xbe, 0x56, 0x57, 0x40, 0x48, 0x09, 0x00, 0x04, 0x00, 0xfa, 0xf5, 0xdf,\n   0xed, 0x5a, 0xd5, 0xea, 0xbd, 0x09, 0x00, 0x00, 0x40, 0x00, 0x92, 0xfe,\n   0xbf, 0x7d, 0xb7, 0x6a, 0x55, 0xbf, 0xf7, 0x02, 0x11, 0x01, 0x00, 0x91,\n   0x00, 0xff, 0xff, 0xaf, 0x55, 0x55, 0x5b, 0xeb, 0xef, 0x22, 0x04, 0x04,\n   0x04, 0x00, 0xa4, 0xff, 0xf7, 0xad, 0xaa, 0xaa, 0xaa, 0xbe, 0xfe, 0x03,\n   0x20, 0x00, 0x10, 0x44, 0x80, 0xff, 0x7f, 0x55, 0x12, 0x91, 0x2a, 0xeb,\n   0xbf, 0x0b, 0x82, 0x02, 0x00, 0x00, 0xd1, 0x7f, 0xdf, 0xa2, 0xa4, 0x54,\n   0x55, 0xfd, 0xfd, 0x47, 0x08, 0x08, 0x00, 0x21, 0xe4, 0xff, 0x37, 0x11,\n   0x09, 0xa5, 0xaa, 0xb6, 0xff, 0x0d, 0x80, 0x00, 0x00, 0x04, 0xd0, 0xff,\n   0x4f, 0x44, 0x20, 0x48, 0x55, 0xfb, 0xff, 0x27, 0x11, 0x02, 0x40, 0x40,\n   0xe2, 0xfb, 0x15, 0x11, 0x4a, 0x55, 0x4a, 0x7d, 0xf7, 0x0f, 0x00, 0x00,\n   0x04, 0x08, 0xf8, 0xdf, 0x52, 0x44, 0x01, 0x52, 0xb5, 0xfa, 0xff, 0x0f,\n   0x49, 0x02, 0x00, 0x02, 0xe9, 0xf6, 0x0a, 0x11, 0xa4, 0x88, 0x4a, 0x6d,\n   0xff, 0x5f, 0x00, 0x00, 0x10, 0x20, 0xf0, 0x2f, 0x21, 0x44, 0x10, 0x52,\n   0xb5, 0xfa, 0xff, 0x0f, 0x44, 0x04, 0x80, 0x08, 0xf8, 0xab, 0x8a, 0x00,\n   0x81, 0xa4, 0xd4, 0xd6, 0xfe, 0x2f, 0x00, 0x00, 0x04, 0x40, 0xb5, 0x2d,\n   0x21, 0x08, 0x04, 0x90, 0xaa, 0xfa, 0xff, 0x1f, 0x11, 0x01, 0x00, 0x04,\n   0xf0, 0x57, 0x0a, 0x22, 0x40, 0x4a, 0xda, 0x5e, 0xfb, 0x1f, 0x40, 0x00,\n   0x40, 0x20, 0xba, 0x95, 0x90, 0x00, 0x01, 0xa0, 0xaa, 0xea, 0xff, 0x5f,\n   0x02, 0x02, 0x00, 0x01, 0xe8, 0x57, 0x05, 0x00, 0x00, 0x12, 0xd5, 0xfe,\n   0xfd, 0x1f, 0x48, 0x00, 0x04, 0x48, 0x7a, 0x95, 0x08, 0x02, 0x10, 0x40,\n   0xaa, 0x55, 0xf7, 0x1f, 0x00, 0x09, 0x20, 0x00, 0xf8, 0x57, 0x22, 0x10,\n   0x00, 0x28, 0xa9, 0xfa, 0xff, 0x5f, 0x02, 0x00, 0x00, 0x49, 0xdd, 0x29,\n   0x01, 0x00, 0x80, 0x80, 0xaa, 0xd7, 0xff, 0x0f, 0x10, 0x00, 0x08, 0x00,\n   0xf8, 0x96, 0x08, 0x00, 0x00, 0x20, 0x54, 0xfa, 0xee, 0x3f, 0x81, 0x04,\n   0x40, 0x24, 0xfe, 0x55, 0x82, 0x00, 0x00, 0x82, 0xd2, 0xad, 0xff, 0x0f,\n   0x08, 0x00, 0x04, 0x80, 0x6c, 0x97, 0x00, 0x00, 0x02, 0x20, 0xa9, 0xf6,\n   0xdf, 0x5f, 0x00, 0x02, 0x20, 0x09, 0xfa, 0x49, 0x12, 0x00, 0x20, 0x84,\n   0x54, 0xdb, 0xfe, 0x1f, 0x91, 0x00, 0x00, 0x00, 0xf8, 0x2b, 0x00, 0x20,\n   0x00, 0x40, 0xa4, 0xf6, 0xbb, 0x1f, 0x04, 0x00, 0x44, 0x92, 0x7e, 0x95,\n   0x02, 0x00, 0x00, 0x89, 0xaa, 0xdd, 0xff, 0x1f, 0x20, 0x09, 0x10, 0x00,\n   0xf4, 0x57, 0x20, 0x01, 0x08, 0x20, 0xa9, 0x76, 0xff, 0x5f, 0x02, 0x00,\n   0x00, 0x21, 0xfc, 0x4a, 0x05, 0x00, 0x01, 0x80, 0x54, 0xdb, 0xff, 0x1e,\n   0x08, 0x02, 0x04, 0x08, 0xf9, 0x2b, 0x00, 0x00, 0x40, 0x28, 0xd2, 0xf6,\n   0xff, 0xbf, 0x80, 0x00, 0x90, 0x00, 0xbc, 0x92, 0x08, 0x10, 0x00, 0x82,\n   0x54, 0xdb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x44, 0xf9, 0x55, 0x02, 0x01,\n   0x00, 0x20, 0xaa, 0xbd, 0xfd, 0x3f, 0x08, 0x04, 0x04, 0x10, 0xf4, 0x2a,\n   0x01, 0x00, 0x22, 0x80, 0xd4, 0xf6, 0xff, 0x5f, 0x82, 0x00, 0x40, 0x02,\n   0xf8, 0x55, 0x20, 0x00, 0x00, 0x50, 0x6a, 0xdf, 0xfe, 0x3f, 0x00, 0x00,\n   0x00, 0x48, 0xe9, 0x4a, 0x05, 0x08, 0x00, 0xa5, 0xd5, 0xf5, 0xff, 0x3f,\n   0x10, 0x01, 0x10, 0x01, 0xb0, 0xab, 0x92, 0x02, 0x40, 0xf8, 0xbf, 0xde,\n   0xfe, 0x5f, 0x02, 0x04, 0x04, 0x48, 0xfa, 0xd4, 0x6f, 0x20, 0x84, 0xef,\n   0xff, 0xfb, 0xff, 0x1f, 0x20, 0x00, 0x00, 0x00, 0xe0, 0xed, 0xbf, 0x0b,\n   0xa1, 0x7e, 0xff, 0xbf, 0xfd, 0x5f, 0x04, 0x01, 0x20, 0x49, 0xd2, 0xfb,\n   0xfe, 0x55, 0xd4, 0xff, 0xff, 0xf6, 0xff, 0x07, 0x00, 0x04, 0x00, 0x00,\n   0xc0, 0xaa, 0xfb, 0x2b, 0xa2, 0xfe, 0xff, 0xdf, 0xee, 0x1f, 0x91, 0x00,\n   0x82, 0xa4, 0xa4, 0xf5, 0xff, 0x57, 0xd5, 0xff, 0xbf, 0xfd, 0xff, 0x4d,\n   0x00, 0x00, 0x20, 0x00, 0x88, 0x5b, 0xff, 0x2f, 0x69, 0xff, 0xff, 0xdb,\n   0xfe, 0x1f, 0x24, 0x02, 0x00, 0x49, 0xa2, 0xd6, 0xff, 0x5f, 0xea, 0xff,\n   0x7f, 0x7f, 0x7f, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x40, 0xab, 0xf7, 0xbb,\n   0xf0, 0xdf, 0xff, 0xd5, 0xff, 0xbf, 0x82, 0x04, 0x42, 0x24, 0x91, 0xd5,\n   0xaa, 0xae, 0xd4, 0xaa, 0x52, 0x7b, 0xff, 0x15, 0x08, 0x00, 0x00, 0x01,\n   0x04, 0x55, 0xd5, 0x55, 0x70, 0x5b, 0x75, 0xdd, 0xdf, 0x1f, 0x40, 0x00,\n   0x08, 0x48, 0xa0, 0x4a, 0xa9, 0x56, 0xea, 0x56, 0xad, 0x6a, 0x7d, 0x9b,\n   0x04, 0x01, 0x00, 0x02, 0x42, 0x2a, 0xd5, 0xaa, 0xa8, 0xaa, 0xaa, 0xfa,\n   0xdf, 0x2f, 0x10, 0x04, 0x22, 0x48, 0x08, 0x45, 0x2a, 0x15, 0x68, 0x55,\n   0x55, 0xd7, 0x76, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x40, 0x2a, 0x80, 0xa0,\n   0xb2, 0x09, 0x48, 0xb9, 0xdf, 0x17, 0x22, 0x01, 0x00, 0x24, 0x45, 0x8a,\n   0x24, 0x4a, 0x54, 0x51, 0x91, 0xf6, 0x6e, 0x4b, 0x00, 0x04, 0x90, 0x00,\n   0x80, 0x52, 0x00, 0x20, 0x69, 0x05, 0xa4, 0xaa, 0xff, 0x1e, 0x48, 0x00,\n   0x02, 0x92, 0x08, 0x05, 0x81, 0x94, 0xd4, 0x92, 0x40, 0xfd, 0xb6, 0x8b,\n   0x00, 0x01, 0x40, 0x00, 0x82, 0x54, 0x00, 0x48, 0x68, 0x05, 0x90, 0xa4,\n   0xef, 0x06, 0x24, 0x00, 0x08, 0x12, 0x10, 0x05, 0x00, 0x10, 0xb5, 0x01,\n   0x42, 0xfb, 0xbf, 0x43, 0x00, 0x09, 0x00, 0x40, 0x81, 0xa8, 0x08, 0x4a,\n   0xaa, 0x96, 0x90, 0xac, 0x6d, 0x15, 0x22, 0x00, 0x20, 0x09, 0x04, 0x15,\n   0x80, 0x28, 0xdc, 0x01, 0x24, 0xfb, 0xbf, 0x01, 0x80, 0x04, 0x09, 0x00,\n   0x40, 0x48, 0x02, 0x45, 0xb2, 0x2e, 0x41, 0x6d, 0xef, 0x05, 0x11, 0x00,\n   0x40, 0x52, 0x02, 0x15, 0x29, 0x2a, 0xac, 0x42, 0x54, 0xfb, 0x3b, 0x51,\n   0x84, 0x00, 0x08, 0x00, 0x20, 0x54, 0x80, 0x05, 0xb5, 0x3d, 0xa2, 0xb6,\n   0xdf, 0x00, 0x20, 0x04, 0x20, 0x49, 0x89, 0xa8, 0x6a, 0x29, 0xac, 0xd6,\n   0x54, 0xff, 0x3f, 0x84, 0x00, 0x01, 0x04, 0x10, 0x00, 0x94, 0xa8, 0x56,\n   0xda, 0x5f, 0xab, 0xd5, 0x1e, 0x10, 0x48, 0x00, 0x90, 0x82, 0x48, 0xa8,\n   0xb2, 0xac, 0xfd, 0x55, 0xd5, 0xfe, 0x9f, 0x80, 0x00, 0x0a, 0x02, 0x08,\n   0x02, 0x55, 0x5a, 0x75, 0xff, 0xaf, 0xb6, 0xf7, 0x2d, 0x12, 0x92, 0x00,\n   0x10, 0x20, 0x10, 0xa8, 0x54, 0xd5, 0xbf, 0x5d, 0xad, 0xdd, 0x0f, 0x00,\n   0x00, 0x04, 0x40, 0x09, 0x84, 0xa8, 0xaa, 0x5a, 0xed, 0xeb, 0x6a, 0xff,\n   0x9f, 0xa4, 0x24, 0x01, 0x02, 0xa0, 0x20, 0x50, 0x55, 0xd5, 0xbe, 0xae,\n   0xad, 0xfd, 0x16, 0x00, 0x10, 0x04, 0x20, 0x0a, 0x08, 0xb4, 0xaa, 0x95,\n   0xaa, 0x7b, 0xb7, 0xdb, 0x5f, 0x92, 0x04, 0x01, 0x84, 0x20, 0x21, 0x51,\n   0xd5, 0x2a, 0xa9, 0xee, 0xd5, 0xfe, 0x0d, 0x00, 0x20, 0x04, 0x10, 0x00,\n   0x08, 0x50, 0xe9, 0xd7, 0xd4, 0xfb, 0xb5, 0xff, 0x9f, 0x24, 0x09, 0x01,\n   0x42, 0x4a, 0xa2, 0x64, 0xd5, 0x55, 0x7b, 0x7f, 0xda, 0x7d, 0x4f, 0x00,\n   0x20, 0x04, 0x00, 0x80, 0x00, 0xa0, 0x2a, 0x13, 0x84, 0x6a, 0x55, 0xff,\n   0x1d, 0x48, 0x8a, 0x00, 0x94, 0x24, 0x8a, 0xc8, 0xaa, 0x42, 0x20, 0x5d,\n   0xf5, 0xff, 0x5f, 0x01, 0x00, 0x02, 0x01, 0x00, 0x20, 0xa2, 0x4a, 0x1a,\n   0x82, 0x56, 0xda, 0xbd, 0x3f, 0x92, 0x92, 0x00, 0x90, 0x92, 0x00, 0x40,\n   0x95, 0x6a, 0xf4, 0x55, 0x6d, 0xff, 0xd6, 0x00, 0x00, 0x0a, 0x04, 0x20,\n   0x14, 0x49, 0x4b, 0xaa, 0xaa, 0x56, 0xf5, 0xff, 0xbf, 0xab, 0xa4, 0x00,\n   0x20, 0x89, 0x40, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xde, 0xbf, 0xeb, 0x03,\n   0x00, 0x02, 0x04, 0x02, 0x0a, 0x10, 0x2b, 0x2a, 0x55, 0x5b, 0xf5, 0xff,\n   0xd7, 0x2f, 0x92, 0x00, 0x10, 0x28, 0x21, 0x01, 0x56, 0x95, 0xa0, 0x56,\n   0xdf, 0xef, 0xea, 0x87, 0x40, 0x0a, 0x42, 0x41, 0x00, 0x90, 0xaa, 0x52,\n   0xb6, 0xad, 0xfa, 0xff, 0xd5, 0x2f, 0x14, 0x00, 0x00, 0x04, 0x95, 0x04,\n   0xaa, 0xac, 0x55, 0x6b, 0xff, 0xb7, 0xea, 0x9f, 0x40, 0x02, 0x28, 0x51,\n   0x00, 0x40, 0x58, 0xd5, 0xda, 0xd6, 0x6e, 0x7f, 0xf9, 0x3f, 0x12, 0x04,\n   0x02, 0x04, 0x49, 0x25, 0x55, 0xaa, 0x77, 0xab, 0xff, 0x2b, 0xfd, 0x3f,\n   0x48, 0x01, 0x20, 0x41, 0x00, 0x00, 0x58, 0xa9, 0xda, 0xea, 0xfd, 0xaf,\n   0xfa, 0xff, 0x02, 0x04, 0x08, 0x14, 0x29, 0x49, 0x52, 0x55, 0x55, 0x55,\n   0xff, 0x8d, 0xfe, 0x3f, 0xa8, 0x00, 0x02, 0x41, 0x00, 0x02, 0xa0, 0xa2,\n   0xaa, 0xea, 0xff, 0x53, 0xfd, 0xff, 0x02, 0x04, 0x50, 0x04, 0x25, 0xa8,\n   0x54, 0x49, 0x52, 0xb5, 0xbf, 0x8a, 0xfe, 0xff, 0xa9, 0x08, 0x04, 0x50,\n   0x80, 0x02, 0xa1, 0x2a, 0x95, 0xea, 0xff, 0xa1, 0xff, 0xff, 0x03, 0x02,\n   0x90, 0x02, 0x09, 0x08, 0x44, 0x49, 0x52, 0xbd, 0x7f, 0xca, 0xff, 0xff,\n   0x2b, 0x09, 0x04, 0x48, 0x40, 0x82, 0x90, 0x56, 0xa9, 0xf6, 0xbf, 0xd0,\n   0xff, 0xff, 0x47, 0x00, 0x50, 0x02, 0x15, 0x11, 0x40, 0x95, 0xaa, 0xfd,\n   0x2f, 0xe9, 0xff, 0xff, 0x8f, 0x0a, 0x84, 0x50, 0x40, 0x84, 0x14, 0xaa,\n   0x6a, 0xff, 0x5f, 0xf2, 0xff, 0xff, 0x7f, 0x00, 0x10, 0x02, 0x09, 0x10,\n   0x40, 0x7d, 0xf7, 0xff, 0x0b, 0xfc, 0xff, 0xff, 0xaf, 0x02, 0x84, 0x50,\n   0x42, 0x85, 0x12, 0xd0, 0xdd, 0xff, 0xa7, 0xf2, 0xff, 0xff, 0xff, 0x04,\n   0x00, 0x0a, 0x08, 0x10, 0x48, 0xf8, 0xff, 0xff, 0x0a, 0xfe, 0xff, 0xff,\n   0x7f, 0x03, 0xa4, 0x80, 0xa2, 0x8a, 0x02, 0x68, 0xff, 0xff, 0x52, 0xfd,\n   0xff, 0xff, 0xff, 0x07, 0x00, 0x2a, 0x08, 0x20, 0x28, 0xdc, 0xff, 0x5f,\n   0x05, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x92, 0x40, 0x22, 0x09, 0x02, 0xea,\n   0xfb, 0xaf, 0x48, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x12, 0x81, 0xa0,\n   0x48, 0x9c, 0x6e, 0x93, 0xa2, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa8, 0x40,\n   0x28, 0x0a, 0x02, 0x74, 0xb5, 0x45, 0x81, 0xff, 0xff, 0xff, 0xff, 0x0f,\n   0x02, 0x0a, 0x81, 0x20, 0x08, 0xae, 0xaa, 0x90, 0xe8, 0xff, 0xff, 0xff,\n   0xff, 0x0f, 0x90, 0x40, 0x28, 0x88, 0x12, 0x58, 0x15, 0x50, 0xd0, 0xff,\n   0xff, 0xff, 0xff, 0x0f, 0x44, 0x0a, 0x41, 0x21, 0x08, 0xae, 0x04, 0x14,\n   0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40, 0x14, 0x88, 0x04, 0xba,\n   0x02, 0x28, 0xe8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x42, 0x15, 0x41, 0x21,\n   0x05, 0xad, 0x00, 0x05, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x40,\n   0x24, 0x8a, 0x0e, 0x36, 0x00, 0x0a, 0xf4, 0xff, 0xff, 0xff, 0xff, 0x0f,\n   0x42, 0x25, 0x90, 0xd0, 0x8b, 0xc2, 0x41, 0x05, 0xfc, 0xff, 0xff, 0xff,\n   0xff, 0x0f, 0x10, 0x08, 0x05, 0xe8, 0x8e, 0x58, 0x80, 0x02, 0xfa, 0xff,\n   0xff, 0xff, 0xff, 0x0f, 0x4a, 0x20, 0xa8, 0xba, 0x0b, 0x2b, 0x51, 0x01,\n   0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x8a, 0x02, 0xe8, 0xaf, 0x84,\n   0x90, 0x04, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x52, 0x21, 0x54, 0xbf,\n   0x1f, 0x15, 0xa5, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x08,\n   0x01, 0xfa, 0xb6, 0xa4, 0x52, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,\n   0x4a, 0xa2, 0x54, 0xef, 0x5f, 0x4b, 0xa4, 0x80, 0xff, 0xff, 0xff, 0xff,\n   0xff, 0x0f, 0x80, 0x10, 0x82, 0xfe, 0xbf, 0x92, 0x52, 0x42, 0xff, 0xff,\n   0xff, 0xff, 0xff, 0x0f, 0x12, 0x42, 0xa8, 0xbf, 0x1f, 0x24, 0x80, 0xa0,\n   0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28, 0x8a, 0xf7, 0x37, 0x80,\n   0x52, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x82, 0xe0, 0xff,\n   0x1f, 0x00, 0x20, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x84, 0x28,\n   0xca, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,\n   0x10, 0x42, 0xf0, 0xfd, 0x1b, 0x00, 0x50, 0xf0, 0xff, 0xff, 0xff, 0xff,\n   0xff, 0x0f, 0xa4, 0x10, 0xc5, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff,\n   0xff, 0xff, 0xff, 0x0f, 0x00, 0x22, 0xf8, 0xff, 0x0e, 0x00, 0x00, 0xf0,\n   0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xaa, 0x88, 0xe2, 0xff, 0x0f, 0x10,\n   0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x25, 0xfa, 0xff,\n   0x0f, 0x01, 0x11, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfb,\n   0xfb, 0xff, 0x7f, 0x5d, 0xd5, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f};\n"
  },
  {
    "path": "tests/filebox.test",
    "content": "# This file is a Tcl script to test out Tk's \"tk_getOpenFile\" and\n# \"tk_getSaveFile\" commands.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\nset tk_strictMotif_old $tk_strictMotif\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc EnterFileByKey {parent fileName fileDir} {\n    global tk_strictMotif\n    if {$parent eq \".\"} {\n\tset w .__tk_filedialog\n    } else {\n\tset w $parent.__tk_filedialog\n    }\n    upvar ::tk::dialog::file::__tk_filedialog data\n\n    if {$tk_strictMotif} {\n\t$data(sEnt) delete 0 end\n\t$data(sEnt) insert 0 [file join $fileDir $fileName]\n    } else {\n\t$data(ent) delete 0 end\n\t$data(ent) insert 0 $fileName\n    }\n\n    update\n    SendButtonPress $parent ok mouse\n}\n\nproc ToEnterFileByKey {parent fileName fileDir} {\n    if {! $::dialogIsNative} {\n\tafter 100 EnterFileByKey $parent [list $fileName] [list $fileDir]\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset unknownOptionsMsg(tk_getOpenFile,notAqua) {bad option \"-foo\": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}\nset unknownOptionsMsg(tk_getOpenFile,aqua) {bad option \"-foo\": must be -command, -defaultextension, -filetypes, -initialdir, -initialfile, -message, -multiple, -parent, -title, or -typevariable}\nset unknownOptionsMsg(tk_getSaveFile,notAqua) {bad option \"-foo\": must be -confirmoverwrite, -defaultextension, -filetypes, -initialdir, -initialfile, -parent, -title, or -typevariable}\nset unknownOptionsMsg(tk_getSaveFile,aqua) {bad option \"-foo\": must be -command, -confirmoverwrite, -defaultextension, -filetypes, -initialdir, -initialfile, -message, -parent, -title, or -typevariable}\n\nset tmpFile \"filebox.tmp\"\nmakeFile {\n    # this file can be empty!\n} $tmpFile\n\narray set filters {\n    1 {}\n    2 {\n\t{\"Text files\"\t\t{.txt .doc}\t}\n\t{\"Text files\"\t\t{}\t\tTEXT}\n\t{\"Tcl Scripts\"\t\t{.tcl}\t\tTEXT}\n\t{\"C Source Files\"\t{.c .h}\t\t}\n\t{\"All Source Files\"\t{.tcl .c .h}\t}\n\t{\"Image Files\"\t\t{.gif}\t\t}\n\t{\"Image Files\"\t\t{.jpeg .jpg}\t}\n\t{\"Image Files\"\t\t\"\"\t\t{GIFF JPEG}}\n\t{\"All files\"\t\t*}\n    }\n    3 {\n\t{\"Text files\"\t\t{.txt .doc}\tTEXT}\n\t{\"Foo\"\t\t\t{\"\"}\t\tTEXT}\n    }\n}\n\nset parent .\nset verylongstring [string repeat longstring: 16]\n\n#\n# TESTS\n#\n\ntest fileDialog-0.1 {GetFileName: file types: MakeFilter() fails} {\n    # MacOS type that is too long\n\n    set res [list [catch {tk_getSaveFile -filetypes {{\"foo\" .foo {\\0\\0\\0\\0\\0}}}} msg] $msg]\n    regsub -all \"\\0\" $res {\\\\0}\n} {1 {bad Macintosh file type \"\\0\\0\\0\\0\\0\"}}\ntest fileDialog-0.2 {GetFileName: file types: MakeFilter() fails} {\n    # MacOS type that is too short, but looks ok in utf (4 bytes).\n\n    set x [catch {tk_getSaveFile -filetypes {{\"foo\" .foo {\\0\\0}}}} msg]\n    regsub -all \"\\0\" $msg {\\\\0} msg\n    list $x $msg\n} {1 {bad Macintosh file type \"\\0\\0\"}}\n# The next test must actually open a file dialog window, but it does\n# not require human interaction to close the dialog because the Aqua\n# port of tktest automatically closes every file dialog after a short\n# timeout when tests are being run.\ntest fileDialog-0.3 {GetFileName: file types: bad filetype} \\\n-constraints aqua \\\n-body {\n    # Checks for the Aqua crash reported in ticket 080a28104.\n    set filename [tk_getOpenFile -filetypes {\n\t{\"Invalid extension\" {x.y}}\n\t{\"All files\" {*}}\n    }]\n} \\\n-result {}\n\n# Test both the motif version and the \"tk\" version of the file dialog\n# box on Unix.\n#\n# Note that this means that test names are unusually complex.\n#\nif {$tcl_platform(platform) eq \"unix\"} {\n    set modes \"0 1\"\n} else {\n    set modes 1\n}\nforeach mode $modes {\n\n    #\n    # COMMON TEST SETUP\n    #\n    set addedExtensions {}\n    if {$tcl_platform(platform) eq \"unix\"} {\n\tset tk_strictMotif $mode\n\t# Extension adding is only done when using the non-motif file\n\t# box with an extension-less filename\n\tif {!$mode} {\n\t    set addedExtensions {NONE {} .txt .txt}\n\t}\n    }\n\n    test filebox-1.1.1-$mode \"tk_getOpenFile command\" -constraints notAqua -body {\n\ttk_getOpenFile -foo\n    } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,notAqua)\n    test filebox-1.1.2-$mode \"tk_getOpenFile command\" -constraints aqua -body {\n\ttk_getOpenFile -foo\n    } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,aqua)\n\n    catch {tk_getOpenFile -foo 1} msg\n    regsub -all ,      $msg \"\" options\n    regsub \\\"-foo\\\" $options \"\" options\n\n    foreach option $options {\n\tif {[string index $option 0] eq \"-\"} {\n\t    test filebox-1.2-$mode$option \"tk_getOpenFile command\" -body {\n\t\ttk_getOpenFile $option\n\t    } -returnCodes error -result \"value for \\\"$option\\\" missing\"\n\t}\n    }\n\n    test filebox-1.3.1-$mode \"tk_getOpenFile command\" -constraints notAqua -body {\n\ttk_getOpenFile -foo bar\n    } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,notAqua)\n    test filebox-1.3.2-$mode \"tk_getOpenFile command\" -constraints aqua -body {\n\ttk_getOpenFile -foo bar\n    } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,aqua)\n    test filebox-1.4-$mode \"tk_getOpenFile command\" -body {\n\ttk_getOpenFile -initialdir\n    } -returnCodes error -result {value for \"-initialdir\" missing}\n    test filebox-1.5-$mode \"tk_getOpenFile command\" -body {\n\ttk_getOpenFile -parent foo.bar\n    } -returnCodes error -result {bad window path name \"foo.bar\"}\n    test filebox-1.6-$mode \"tk_getOpenFile command\" -body {\n\ttk_getOpenFile -filetypes {Foo}\n    } -returnCodes error -result {bad file type \"Foo\", should be \"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\"}\n\n    test filebox-2.1-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\tToPressButton $parent cancel\n\ttk_getOpenFile -title \"Press Cancel ($verylongstring)\" -parent $parent\n    } \"\"\n\n    #\n    # COMMON TEST SETUP\n    #\n    set fileName $tmpFile\n    set fileDir [tcltest::temporaryDirectory]\n    set pathName [file join $fileDir $fileName]\n\n    test filebox-2.2-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\tToPressButton $parent ok\n\tset choice [tk_getOpenFile -title \"Press Ok\" \\\n\t\t-parent $parent -initialfile $fileName -initialdir $fileDir]\n    } $pathName\n    test filebox-2.3-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\tToEnterFileByKey $parent $fileName $fileDir\n\tset choice [tk_getOpenFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir $fileDir]\n    } $pathName\n    test filebox-2.4-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\tcd $fileDir\n\tToPressButton $parent ok\n\tset choice [tk_getOpenFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir . -initialfile $fileName]\n    } $pathName\n    test filebox-2.5-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\tToPressButton $parent ok\n\tset choice [tk_getOpenFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir /badpath -initialfile $fileName]\n    } $pathName\n    test filebox-2.6-$mode \"tk_getOpenFile command\" -setup {\n\ttoplevel .t1; toplevel .t2\n\twm geometry .t1 +0+0\n\twm geometry .t2 +0+0\n    } -constraints nonUnixUserInteraction -body {\n\tset choice {}\n\tToPressButton .t1 ok\n\tlappend choice [tk_getOpenFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t1 -initialdir $fileDir \\\n\t\t-initialfile $fileName]\n\tToPressButton .t2 ok\n\tlappend choice [tk_getOpenFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t2 -initialdir $fileDir \\\n\t\t-initialfile $fileName]\n\tToPressButton .t1 ok\n\tlappend choice [tk_getOpenFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t1 -initialdir $fileDir \\\n\t\t-initialfile $fileName]\n    } -result [list $pathName $pathName $pathName] -cleanup {\n\tdestroy .t1\n\tdestroy .t2\n    }\n\n    test fileDialog-2.7-$mode {\"tk_getOpenFile: bad extension\" -body {\n\t#ToPressButton $parent cancel\n\tset filename [tk_getOpenFile -filetypes {\n\t    {\"Invalid extension\" {x.y}}\n\t    {\"All files\" {*}}\n\t}]\n\t} -result {}\n    }\n\n    foreach x [lsort -integer [array names filters]] {\n\ttest filebox-3.$x-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\t    ToPressButton $parent ok\n\t    set choice [tk_getOpenFile -title \"Press Ok\" \\\n\t\t    -filetypes $filters($x) -parent $parent \\\n\t\t    -initialfile $fileName -initialdir $fileDir]\n\t} $pathName\n    }\n    foreach {x res} [list 1 \"-unset-\" 2 \"Text files\"] {\n\tset t [expr {$x + [llength [array names filters]]}]\n\ttest filebox-3.$t-$mode \"tk_getOpenFile command\" nonUnixUserInteraction {\n\t    catch {unset tv}\n\t    catch {unset typeName}\n\t    ToPressButton $parent ok\n\t    set choice [tk_getOpenFile -title \"Press Ok\" \\\n\t\t    -filetypes $filters($x) -parent $parent \\\n\t\t    -initialfile $fileName -initialdir $fileDir \\\n\t\t    -typevariable tv]\n\t    if {[info exists tv]} {\n\t\tset typeName $tv\n\t    } else {\n\t\tset typeName \"-unset-\"\n\t    }\n\t    set typeName\n\t} $res\n    }\n\n    test filebox-4.1.1-$mode \"tk_getSaveFile command\" -constraints notAqua -body {\n\ttk_getSaveFile -foo\n    } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,notAqua)\n    test filebox-4.1.2-$mode \"tk_getSaveFile command\" -constraints aqua -body {\n\ttk_getSaveFile -foo\n    } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,aqua)\n\n    catch {tk_getSaveFile -foo 1} msg\n    regsub -all ,      $msg \"\" options\n    regsub \\\"-foo\\\" $options \"\" options\n    foreach option $options {\n\tif {[string index $option 0] eq \"-\"} {\n\t    test filebox-4.2-$mode$option \"tk_getSaveFile command\" -body {\n\t\ttk_getSaveFile $option\n\t    } -returnCodes error -result \"value for \\\"$option\\\" missing\"\n\t}\n    }\n\n    test filebox-4.3.1-$mode \"tk_getSaveFile command\" -constraints notAqua -body {\n\ttk_getSaveFile -foo bar\n    } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,notAqua)\n    test filebox-4.3.2-$mode \"tk_getSaveFile command\" -constraints aqua -body {\n\ttk_getSaveFile -foo bar\n    } -returnCodes error -result $unknownOptionsMsg(tk_getSaveFile,aqua)\n    test filebox-4.4-$mode \"tk_getSaveFile command\" -body {\n\ttk_getSaveFile -initialdir\n    } -returnCodes error -result {value for \"-initialdir\" missing}\n    test filebox-4.5-$mode \"tk_getSaveFile command\" -body {\n\ttk_getSaveFile -parent foo.bar\n    } -returnCodes error -result {bad window path name \"foo.bar\"}\n    test filebox-4.6-$mode \"tk_getSaveFile command\" -body {\n\ttk_getSaveFile -filetypes {Foo}\n    } -returnCodes error -result {bad file type \"Foo\", should be \"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\"}\n\n    test filebox-5.1-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\tToPressButton $parent cancel\n\ttk_getSaveFile -title \"Press Cancel ($verylongstring)\" -parent $parent\n    } \"\"\n\n    #\n    # COMMON TEST SETUP\n    #\n    set fileName \"12x 455\"\n    set fileDir [pwd]\n    set pathName [file join [pwd] $fileName]\n\n    test filebox-5.2-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\tToPressButton $parent ok\n\tset choice [tk_getSaveFile -title \"Press Ok\" \\\n\t\t-parent $parent -initialfile $fileName -initialdir $fileDir]\n    } $pathName\n    test filebox-5.3-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\tToEnterFileByKey $parent $fileName $fileDir\n\tset choice [tk_getSaveFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir $fileDir]\n    } $pathName\n    test filebox-5.4-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\tToPressButton $parent ok\n\tset choice [tk_getSaveFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir . -initialfile $fileName]\n    } $pathName\n    test filebox-5.5-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\tToPressButton $parent ok\n\tset choice [tk_getSaveFile -title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent $parent -initialdir /badpath -initialfile $fileName]\n    } $pathName\n\n    test filebox-5.6-$mode \"tk_getSaveFile command\" -setup {\n\ttoplevel .t1; toplevel .t2\n\twm geometry .t1 +0+0\n\twm geometry .t2 +0+0\n    } -constraints nonUnixUserInteraction -body {\n\tset choice {}\n\tToPressButton .t1 ok\n\tlappend choice [tk_getSaveFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t1 -initialdir $fileDir -initialfile $fileName]\n\tToPressButton .t2 ok\n\tlappend choice [tk_getSaveFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t2 -initialdir $fileDir -initialfile $fileName]\n\tToPressButton .t1 ok\n\tlappend choice [tk_getSaveFile \\\n\t\t-title \"Enter \\\"$fileName\\\" and press Ok\" \\\n\t\t-parent .t1 -initialdir $fileDir -initialfile $fileName]\n    } -result [list $pathName $pathName $pathName] -cleanup {\n\tdestroy .t1\n\tdestroy .t2\n    }\n\n    foreach x [lsort -integer [array names filters]] {\n\ttest filebox-6.$x-$mode \"tk_getSaveFile command\" nonUnixUserInteraction {\n\t    ToPressButton $parent ok\n\t    set choice [tk_getSaveFile -title \"Press Ok\" \\\n\t\t    -filetypes $filters($x) -parent $parent \\\n\t\t    -initialfile $fileName -initialdir $fileDir]\n\t} $pathName[lindex $addedExtensions $x]\n    }\n\n    if {!$mode} {\n\n\ttest filebox-7.1-$mode \"tk_getOpenFile - directory not readable\" \\\n\t    -constraints nonUnixUserInteraction \\\n\t    -setup {\n\t\trename ::tk_messageBox ::saved_messageBox\n\t\tset ::gotmessage {}\n\t\tproc tk_messageBox args {\n\t\t    set ::gotmessage $args\n\t\t}\n\t\ttoplevel .t1\n\t\tfile mkdir [file join $fileDir NOTREADABLE]\n\t\tfile attributes [file join $fileDir NOTREADABLE] \\\n\t\t    -permissions 300\n\t    } \\\n\t    -cleanup {\n\t\trename ::tk_messageBox {}\n\t\trename ::saved_messageBox ::tk_messageBox\n\t\tunset ::gotmessage\n\t\tdestroy .t1\n\t\tfile delete -force [file join $fileDir NOTREADABLE]\n\t    } \\\n\t    -body {\n\t\tToEnterFileByKey .t1 NOTREADABLE $fileDir\n\t\tToPressButton .t1 ok\n\t\tToPressButton .t1 cancel\n\t\ttk_getOpenFile -parent .t1 \\\n\t\t    -title \"Please select the NOTREADABLE directory\" \\\n\t\t    -initialdir $fileDir\n\t\tset gotmessage\n\t    } \\\n\t    -match glob \\\n\t    -result \"*NOTREADABLE*\"\n\n\ttest filebox-7.2-$mode \"tk_getOpenFile - bad file name\" \\\n\t    -constraints nonUnixUserInteraction \\\n\t    -setup {\n\t\trename ::tk_messageBox ::saved_messageBox\n\t\tset ::gotmessage {}\n\t\tproc tk_messageBox args {\n\t\t    set ::gotmessage $args\n\t\t}\n\t\ttoplevel .t1\n\t    } \\\n\t    -cleanup {\n\t\trename ::tk_messageBox {}\n\t\trename ::saved_messageBox ::tk_messageBox\n\t\tunset ::gotmessage\n\t\tdestroy .t1\n\t    } \\\n\t    -body {\n\t\tToEnterFileByKey .t1 RUBBISH $fileDir\n\t\tToPressButton .t1 ok\n\t\tToPressButton .t1 cancel\n\t\ttk_getOpenFile -parent .t1 \\\n\t\t    -title \"Please enter RUBBISH as a file name\" \\\n\t\t    -initialdir $fileDir\n\t\tset gotmessage\n\t    } \\\n\t    -match glob \\\n\t    -result \"*RUBBISH*\"\n    }\n\n    # The rest of the tests need to be executed on Unix only.\n    # They test whether the dialog box widgets were implemented correctly.\n    # These tests are not\n    # needed on the other platforms because they use native file dialogs.\n}\n\n#\n# TESTFILE CLEANUP\n#\n\nset tk_strictMotif $tk_strictMotif_old\nremoveFile filebox.tmp\ntestutils forget dialog\ncleanupTests\n"
  },
  {
    "path": "tests/flagdown.xbm",
    "content": "#define flagdown_width 48\n#define flagdown_height 48\nstatic char flagdown_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,\n   0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe1, 0x00, 0x00,\n   0x00, 0x00, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00,\n   0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04,\n   0x00, 0x00, 0x03, 0x00, 0x06, 0x06, 0x00, 0x80, 0x01, 0x00, 0x06, 0x07,\n   0x00, 0xc0, 0x1f, 0x00, 0x87, 0x07, 0x00, 0xe0, 0x7f, 0x80, 0xc7, 0x07,\n   0x00, 0x70, 0xe0, 0xc0, 0xe5, 0x07, 0x00, 0x38, 0x80, 0xe1, 0x74, 0x07,\n   0x00, 0x18, 0x80, 0x71, 0x3c, 0x07, 0x00, 0x0c, 0x00, 0x3b, 0x1e, 0x03,\n   0x00, 0x0c, 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x86, 0x1f, 0x8e, 0x07, 0x00,\n   0x00, 0x06, 0x06, 0xc6, 0x05, 0x00, 0x00, 0x06, 0x00, 0xc6, 0x05, 0x00,\n   0x00, 0x06, 0x00, 0xc6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,\n   0x7f, 0x06, 0x00, 0x06, 0xe4, 0xff, 0x00, 0x06, 0x00, 0x06, 0x04, 0x00,\n   0x00, 0x06, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x00,\n   0x00, 0x06, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,\n   0x00, 0x06, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00,\n   0x00, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3e, 0x00, 0x00,\n   0x00, 0xfe, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x27, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00,\n   0xf7, 0xbf, 0x8e, 0xfc, 0xdf, 0xf8, 0x9d, 0xeb, 0x9b, 0x76, 0xd2, 0x7a,\n   0x46, 0x30, 0xe2, 0x0f, 0xe1, 0x47, 0x55, 0x84, 0x48, 0x11, 0x84, 0x19};\n"
  },
  {
    "path": "tests/flagup.xbm",
    "content": "#define flagup_width 48\n#define flagup_height 48\nstatic char flagup_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00,\n   0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xef, 0x6a, 0x00,\n   0x00, 0x00, 0xc0, 0x7b, 0x75, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x6a, 0x00,\n   0x00, 0x00, 0x30, 0x60, 0x75, 0x00, 0x00, 0x00, 0x18, 0xe0, 0x7f, 0x00,\n   0x00, 0x00, 0x0c, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x04, 0x00,\n   0x00, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00,\n   0x00, 0xc0, 0x1f, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0xe0, 0x07, 0x00,\n   0x00, 0x70, 0xe0, 0xe0, 0x05, 0x00, 0x00, 0x38, 0x80, 0xe1, 0x04, 0x00,\n   0x00, 0x18, 0x80, 0xf1, 0x04, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x04, 0x00,\n   0x00, 0x0c, 0x00, 0xff, 0x04, 0x00, 0x00, 0x86, 0x1f, 0xee, 0x04, 0x00,\n   0x00, 0x06, 0x06, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0xe6, 0x04, 0x00,\n   0x00, 0x06, 0x00, 0xe6, 0x04, 0x00, 0x00, 0x06, 0x00, 0x66, 0x04, 0x00,\n   0x7f, 0x56, 0x52, 0x06, 0xe4, 0xff, 0x00, 0x76, 0x55, 0x06, 0x04, 0x00,\n   0x00, 0x56, 0x57, 0x06, 0x04, 0x00, 0x00, 0x56, 0x55, 0x06, 0x06, 0x00,\n   0x00, 0x56, 0xd5, 0x06, 0x03, 0x00, 0x00, 0x06, 0x00, 0x86, 0x01, 0x00,\n   0x54, 0x06, 0x00, 0xc6, 0x54, 0x55, 0xaa, 0x06, 0x00, 0x66, 0xaa, 0x2a,\n   0x54, 0x06, 0x00, 0x36, 0x55, 0x55, 0xaa, 0x06, 0x00, 0xbe, 0xaa, 0x2a,\n   0x54, 0xfe, 0xff, 0x6f, 0x55, 0x55, 0xaa, 0xfc, 0xff, 0xa7, 0xaa, 0x2a,\n   0x54, 0x01, 0x88, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x60, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa0, 0xaa, 0x2a,\n   0x54, 0x55, 0x8d, 0x50, 0x55, 0x55, 0xaa, 0xaa, 0x8a, 0xa8, 0xaa, 0x2a,\n   0x54, 0x55, 0x95, 0x54, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,\n   0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\n"
  },
  {
    "path": "tests/focus.test",
    "content": "# This file is a Tcl script to test out the \"focus\" command and the\n# other procedures in the file tkFocus.c.\n#\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# focusClear --\n#\n#    Ensures that there is no input focus in this application.  It does it by\n#    arranging for another application to grab the focus.  The \"after\" and\n#    \"update\" stuff is needed to wait long enough for pending actions to get\n#    through the X server and possibly also the window manager.\n#\nif {[tk windowingsystem] eq \"aqua\"} {\n    proc focusClear {} {\n\tchildInterp eval {\n\t    focus -force .\n\t    set i 0\n\t    while {[focus] ne \".\"} {\n\t\tafter 100\n\t\tincr i\n\t\tif {$i > 10} {\n\t\t    break\n\t\t}\n\t    }\n\t}\n    }\n} else {\n    proc focusClear {} {\n\tchildTkProcess eval {after 200; focus -force .; update}\n\tafter 400\n\tupdate\n    }\n}\n\nproc focusSetup {} {\n    destroy .t\n    toplevel .t\n    wm geom .t +0+0\n    foreach i {b1 b2 b3 b4} {\n\tbutton .t.$i -text .t.$i -relief raised -bd 2\n\tpack .t.$i\n    }\n    tkwait visibility .t.b4\n}\n\nproc focusSetupAlt {} {\n    global env\n    destroy .alt\n    toplevel .alt -screen $env(TK_ALT_DISPLAY)\n    foreach i {a b c d} {\n\tbutton .alt.$i -text .alt.$i -relief raised -bd 2\n\tpack .alt.$i\n    }\n    tkwait visibility .alt.d\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# childTkProcess exit will be after 4.3 test\nchildTkProcess create\nupdate\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    childTkInterp childInterp\n}\n\nfocusSetup\nif {[testConstraint altDisplay]} {\n    focusSetupAlt\n}\n\n# Button used in some tests in the whole test file\nbutton .b -text .b -relief raised -bd 2\npack .b\n\nbind all <FocusIn> {\n    append focusInfo \"in %W %d\\n\"\n}\nbind all <FocusOut> {\n    append focusInfo \"out %W %d\\n\"\n}\nbind all <Key> {\n    append focusInfo \"press %W %K\"\n}\n\n# Make sure the window manager knows who has focus\ncatch {fixfocus}\n\n#\n# TESTS\n#\n\ntest focus-1.1 {Tk_FocusCmd procedure} -constraints unix -body {\n    focusClear\n    after 100\n    focus\n} -result {}\ntest focus-1.2 {Tk_FocusCmd procedure} -constraints {\n    unix altDisplay\n} -body {\n    focus .alt.b\n    focus\n} -result {}\ntest focus-1.3 {Tk_FocusCmd procedure} -constraints unix -body {\n    focusClear\n    focus .t.b3\n    focus\n} -result {}\ntest focus-1.4 {Tk_FocusCmd procedure} -constraints unix -body {\n    focus \"\"\n} -returnCodes ok -result {}\ntest focus-1.5 {Tk_FocusCmd procedure} -constraints unix -body {\n    focusClear\n    focus -force .t\n    focus .t.b3\n    focus\n}  -result {.t.b3}\ntest focus-1.6 {Tk_FocusCmd procedure} -constraints unix -body {\n    focus .gorp\n} -returnCodes error -result {bad window path name \".gorp\"}\ntest focus-1.7 {Tk_FocusCmd procedure} -constraints unix -body {\n    focus .gorp a\n} -returnCodes error -result {bad option \".gorp\": must be -displayof, -force, or -lastfor}\ntest focus-1.8 {Tk_FocusCmd procedure, focussing on dead window} -constraints {\n    unix\n} -setup {\n    destroy .t2\n} -body {\n    focusClear\n    toplevel .t2\n    wm geom .t2 +10+10\n    frame .t2.f -width 200 -height 100 -bd 2 -relief raised\n    frame .t2.f2 -width 200 -height 100 -bd 2 -relief raised\n    pack .t2.f .t2.f2\n    bind .t2.f <Destroy> {focus .t2.f}\n    bind .t2.f2 <Destroy> {focus .t2}\n    focus -force .t2.f2\n    tkwait visibility .t2.f2\n    update\n    set x [focus]\n    destroy .t2.f2\n    lappend x [focus]\n    destroy .t2.f\n    lappend x [focus]\n    destroy .t2\n    return $x\n} -cleanup {\n    destroy .t2\n} -result {.t2.f2 .t2 .t2}\ntest focus-1.9 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix\n} -body {\n    focus -displayof\n} -returnCodes error -result {wrong # args: should be \"focus -displayof window\"}\ntest focus-1.10 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix\n} -body {\n    focus -displayof a b\n} -returnCodes error -result {wrong # args: should be \"focus -displayof window\"}\ntest focus-1.11 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix\n} -body {\n    focus -displayof .lousy\n} -returnCodes error -result {bad window path name \".lousy\"}\ntest focus-1.12 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix\n} -body {\n    # Move focus to the root window in the child process/interpreter.\n    focusClear\n    # The main application does not have focus, so this has no effect now.\n    focus .t\n    focus -displayof .t.b3\n}  -result {}\ntest focus-1.13 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix\n} -body {\n    focusClear\n    focus -force .t\n    focus -displayof .t.b3\n} -result {.t}\ntest focus-1.14 {Tk_FocusCmd procedure, -displayof option} -constraints {\n    unix altDisplay\n} -body {\n    focusClear\n    focus -force .alt.c\n    focus -displayof .alt\n} -result {.alt.c}\ntest focus-1.15 {Tk_FocusCmd procedure, -force option} -constraints unix -body {\n    focus -force\n} -returnCodes error -result {wrong # args: should be \"focus -force window\"}\ntest focus-1.16 {Tk_FocusCmd procedure, -force option} -constraints unix -body {\n    focus -force a b\n} -returnCodes error -result {wrong # args: should be \"focus -force window\"}\ntest focus-1.17 {Tk_FocusCmd procedure, -force option} -constraints unix -body {\n    focus -force foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest focus-1.18 {Tk_FocusCmd procedure, -force option} -constraints unix -body {\n    focus -force \"\"\n} -returnCodes ok -result {}\ntest focus-1.19 {Tk_FocusCmd procedure, -force option} -constraints unix -body {\n    focusClear\n    focus .t.b1\n    set x  [list [focus]]\n    focus -force .t.b1\n    lappend x [focus]\n} -result {{} .t.b1}\ntest focus-1.20 {Tk_FocusCmd procedure, -lastfor option} -constraints {\n    unix\n} -body {\n    focus -lastfor\n} -returnCodes error -result {wrong # args: should be \"focus -lastfor window\"}\ntest focus-1.21 {Tk_FocusCmd procedure, -lastfor option} -constraints {\n    unix\n} -body {\n    focus -lastfor 1 2\n} -returnCodes error -result {wrong # args: should be \"focus -lastfor window\"}\ntest focus-1.22 {Tk_FocusCmd procedure, -lastfor option} -constraints {\n    unix\n} -body {\n    focus -lastfor who_knows?\n} -returnCodes error -result {bad window path name \"who_knows?\"}\ntest focus-1.23 {Tk_FocusCmd procedure, -lastfor option} -constraints {\n    unix\n} -body {\n    focusClear\n    focusSetup\n    focus .b\n    focus .t.b1\n    list [focus -lastfor .] [focus -lastfor .t.b3]\n} -result {.b .t.b1}\ntest focus-1.24 {Tk_FocusCmd procedure, -lastfor option} -constraints {\n    unix\n} -body {\n    focusClear\n    focusSetup\n    update\n    focus -lastfor .t.b2\n} -result {.t}\ntest focus-1.25 {Tk_FocusCmd procedure} -constraints unix -body {\n    focus -unknown\n} -returnCodes error -result {bad option \"-unknown\": must be -displayof, -force, or -lastfor}\n\n#\n# COMMON TEST SETUP\n#\nfocusSetup\n\ntest focus-2.1 {TkFocusFilterEvent procedure} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusClear\n    focus -force .b\n    focusSetup\n    update\n    set focusInfo {}\n    event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor \\\n\t    -sendevent 0x54217567\n    return $focusInfo\n} -result {}\ntest focus-2.2 {TkFocusFilterEvent procedure} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusClear\n    focus -force .b\n    focusSetup\n    update\n    set focusInfo {}\n    event gen .t <FocusIn> -detail NotifyAncestor -sendevent 0x547321ac\n    list $focusInfo [focus]\n} -result {{in .t NotifyAncestor\n} .b}\ntest focus-2.3 {TkFocusFilterEvent procedure} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusClear\n    focus -force .b\n    focusSetup\n    update\n    set focusInfo {}\n    event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor\n    update\n    list $focusInfo [focus -lastfor .t]\n} -result {{out .b NotifyNonlinear\nout . NotifyNonlinearVirtual\nin .t NotifyNonlinear\n} .t}\ntest focus-2.4 {TkFocusFilterEvent procedure, FocusIn events} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusClear\n    set result {}\n    focus .t.b1\n    # Important to end with NotifyAncestor, which is an\n    # event that is processed normally. This has a side\n    # effect on text 2.5\n    foreach detail {NotifyAncestor NotifyNonlinear\n\t    NotifyNonlinearVirtual NotifyPointer NotifyPointerRoot\n\t    NotifyVirtual NotifyAncestor} {\n\tfocus -force .\n\tupdate\n\tevent gen [testwrapper .t] <FocusIn> -detail $detail\n\tset focusInfo {}\n\tupdate\n\tlappend result $focusInfo\n    }\n    return $result\n} -result {{out . NotifyNonlinear\nin .t NotifyNonlinearVirtual\nin .t.b1 NotifyNonlinear\n} {out . NotifyNonlinear\nin .t NotifyNonlinearVirtual\nin .t.b1 NotifyNonlinear\n} {} {out . NotifyNonlinear\nin .t NotifyNonlinearVirtual\nin .t.b1 NotifyNonlinear\n} {} {} {out . NotifyNonlinear\nin .t NotifyNonlinearVirtual\nin .t.b1 NotifyNonlinear\n}}\ntest focus-2.5 {TkFocusFilterEvent procedure, creating FocusInfo struct} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusSetup\n    focus .t.b1\n    update\n    event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor\n    list $focusInfo [focus]\n} -result {{out . NotifyNonlinear\nin .t NotifyNonlinearVirtual\nin .t.b1 NotifyNonlinear\n} .t.b1}\n\ntest focus-2.6 {TkFocusFilterEvent procedure, FocusIn events} -constraints {\n    unix  testwrapper failsOnCILinux failsOnXQuartz\n} -body {\n    focus .t.b1\n    focus .\n    update\n    event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor\n    set focusInfo {}\n    set x [focus]\n    event gen . <x>\n    list $x $focusInfo\n} -result {.t.b1 {press .t.b1 x}}\ntest focus-2.7 {TkFocusFilterEvent procedure, FocusOut events} -constraints {\n    unix  testwrapper failsOnCILinux failsOnXQuartz\n} -body {\n    set result {}\n    foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear\n\t    NotifyNonlinearVirtual NotifyPointer NotifyPointerRoot\n\t    NotifyVirtual} {\n\tfocus -force .t.b1\n\tevent gen [testwrapper .t] <FocusOut> -detail $detail\n\tupdate\n\tlappend result [focus]\n    }\n    return $result\n} -result {{} .t.b1 {} {} .t.b1 .t.b1 {}}\ntest focus-2.8 {TkFocusFilterEvent procedure, FocusOut events} -constraints {\n    unix  testwrapper\n} -body {\n    focus -force .t.b1\n    event gen .t.b1 <FocusOut> -detail NotifyAncestor\n    focus\n} -result {.t.b1}\ntest focus-2.9 {TkFocusFilterEvent procedure, FocusOut events} -constraints {\n    unix  testwrapper failsOnCILinux failsOnXQuartz\n} -body {\n    focus .t.b1\n    event gen [testwrapper .] <FocusOut> -detail NotifyAncestor\n    focus\n} -result {}\ntest focus-2.10 {TkFocusFilterEvent procedure, Enter events} -constraints {\n    unix  testwrapper\n} -body {\n    set result {}\n    focus .t.b1\n    focusClear\n    foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear\n\t    NotifyNonlinearVirtual NotifyVirtual} {\n\tevent gen [testwrapper .t] <Enter> -detail $detail -focus 1\n\tupdate\n\tlappend result [focus]\n\tevent gen [testwrapper .t] <Leave> -detail NotifyAncestor\n\tupdate\n    }\n    return $result\n} -result {.t.b1 {} .t.b1 .t.b1 .t.b1}\ntest focus-2.11 {TkFocusFilterEvent procedure, Enter events} -constraints {\n    unix  testwrapper\n} -body {\n    focusClear\n    set focusInfo {}\n    event gen [testwrapper .t] <Enter> -detail NotifyAncestor\n    update\n    return $focusInfo\n} -result {}\ntest focus-2.12 {TkFocusFilterEvent procedure, Enter events} -constraints {\n    unix  testwrapper\n} -body {\n    focus -force .b\n    update\n    set focusInfo {}\n    event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1\n    update\n    return $focusInfo\n} -result {}\ntest focus-2.13 {TkFocusFilterEvent procedure, Enter events} -constraints {\n    unix  testwrapper\n} -body {\n    focus .t.b1\n    focusClear\n    event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1\n    set focusInfo {}\n    update\n    return $focusInfo\n} -result {in .t NotifyVirtual\nin .t.b1 NotifyAncestor\n}\ntest focus-2.14 {TkFocusFilterEvent procedure, Enter events, ignore errors when setting focus due to implicit focus} -constraints {\n    unix testwrapper\n} -setup {\n    destroy .t2\n    set focusInfo {}\n} -body {\n    focusClear\n    toplevel .t2\n    wm withdraw .t2\n    update\n    event gen [testwrapper .t2] <Enter> -detail NotifyAncestor -focus 1\n    update\n} -cleanup {\n    destroy .t2\n} -result {}\ntest focus-2.15 {TkFocusFilterEvent procedure, Leave events} -constraints {\n    unix  testwrapper\n} -body {\n    set result {}\n    focus .t.b1\n    foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear\n\t    NotifyNonlinearVirtual NotifyVirtual} {\n\tfocusClear\n\tevent gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1\n\tupdate\n\tevent gen [testwrapper .t] <Leave> -detail $detail\n\tupdate\n\tlappend result [focus]\n    }\n    return $result\n} -result {{} .t.b1 {} {} {}}\ntest focus-2.16 {TkFocusFilterEvent procedure, Leave events} -constraints {\n    unix  testwrapper\n} -body {\n    focusClear\n    focus .t.b1\n    event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1\n    update\n    set focusInfo {}\n    event gen [testwrapper .t] <Leave> -detail NotifyAncestor\n    update\n    return $focusInfo\n} -result {out .t.b1 NotifyAncestor\nout .t NotifyVirtual\n}\ntest focus-2.17 {TkFocusFilterEvent procedure, Leave events} -constraints {\n    unix  testwrapper\n} -body {\n    focusClear\n    focus .t.b1\n    event gen [testwrapper .t] <Enter> -detail NotifyAncestor -focus 1\n    update\n    set focusInfo {}\n    event gen .t.b1 <Leave> -detail NotifyAncestor\n    event gen [testwrapper .] <Leave> -detail NotifyAncestor\n    update\n    list $focusInfo [focus]\n} -result {{out .t.b1 NotifyAncestor\nout .t NotifyVirtual\n} {}}\n\n\ntest focus-3.1 {SetFocus procedure, create record on focus} -constraints {\n    unix  testwrapper\n} -body {\n    toplevel .t2 -width 250 -height 100\n    wm geometry .t2 +0+0\n    update\n    focus -force .t2\n    update\n    focus\n} -cleanup {\n    destroy .t2\n} -result {.t2}\n# This test produces no result, but it will generate a protocol\n# error if Tk forgets to make the window exist before focussing\n# on it.\ntest focus-3.2 {SetFocus procedure, making window exist} -constraints {\n    unix testwrapper\n} -body {\n    update\n    button .b2 -text \"Another button\"\n    focus .b2\n    update\n} -cleanup {\n    destroy .b2\n    update\n} -result {}\n# The following test doesn't produce a check-able result, but if\n# there are bugs it may generate an X protocol error.\ntest focus-3.3 {SetFocus procedure, delaying claim of X focus} -constraints {\n    unix  testwrapper\n} -body {\n    focusSetup\n    focus -force .t.b2\n    update\n} -result {}\ntest focus-3.4 {SetFocus procedure, delaying claim of X focus} -constraints {\n    unix  testwrapper\n} -body {\n    focusSetup\n    wm withdraw .t\n    focus -force .t.b2\n    toplevel .t2 -width 250 -height 100\n    wm geometry .t2 +10+10\n    focus -force .t2\n    wm withdraw .t2\n    update\n    wm deiconify .t2\n    wm deiconify .t\n} -cleanup {\n    destroy .t2\n} -result {}\ntest focus-3.5 {SetFocus procedure, generating events} -constraints {\n    unix testwrapper\n} -body {\n    focusSetup\n    focusClear\n    set focusInfo {}\n    focus -force .t.b2\n    update\n    return $focusInfo\n} -result {in .t NotifyVirtual\nin .t.b2 NotifyAncestor\n}\ntest focus-3.6 {SetFocus procedure, generating events} -constraints {\n    unix testwrapper\n} -body {\n    focusSetup\n    focus -force .b\n    update\n    set focusInfo {}\n    focus .t.b2\n    update\n    return $focusInfo\n} -result {out .b NotifyNonlinear\nout . NotifyNonlinearVirtual\nin .t NotifyNonlinearVirtual\nin .t.b2 NotifyNonlinear\n}\ntest focus-3.7 {SetFocus procedure, generating events} -constraints {\nunix nonPortable testwrapper\n} -body {\n    # Non-portable because some platforms generate extra events.\n    focusSetup\n    focusClear\n    set focusInfo {}\n    focus .t.b2\n    update\n    return $focusInfo\n} -result {}\n\n\ntest focus-4.1 {TkFocusDeadWindow procedure} -constraints {\n    unix testwrapper\n} -body {\n    focusSetup\n    update\n    focus -force .b\n    update\n    destroy .t\n    focus\n} -result {.b}\ntest focus-4.2 {TkFocusDeadWindow procedure} -constraints {\n    unix testwrapper\n} -body {\n    focusSetup\n    update\n    focus -force .t.b2\n    focus .b\n    update\n    destroy .t.b2\n    update\n    focus\n} -result {.b}\n# Non-portable due to wm-specific redirection of input focus when\n# windows are deleted:\ntest focus-4.3 {TkFocusDeadWindow procedure} -constraints {\n    unix nonPortable testwrapper\n} -body {\n    focusSetup\n    update\n    focus .t\n    update\n    destroy .t\n    update\n    focus\n} -result {}\ntest focus-4.4 {TkFocusDeadWindow procedure} -constraints {\n    unix testwrapper\n} -body {\n    focusSetup\n    focus -force .t.b2\n    update\n    destroy .t.b2\n    focus\n} -result {.t}\n\n#\n# COMMON TEST CLEANUP\n#\nchildTkProcess exit\n\n\n# I don't know how to test most of the remaining procedures of this file\n# explicitly;  they've already been exercised by the preceding tests.\n\n# Test 5.1 fails (before and after update)\ntest focus-5.1 {ChangeXFocus procedure, don't take focus unless have it} -constraints {\n    unix testwrapper secureserver failsOnCILinux failsOnXQuartz\n} -body {\n    childTkProcess create\n    focusSetup\n    focus -force .t\n    update\n    set result [focus]\n    send [childTkProcess eval {tk appname}] {focus -force .; update}\n    lappend result [focus]\n    focus .t.b2\n    update\n    lappend result [focus]\n} -cleanup {\n    childTkProcess exit\n} -result {.t {} {}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\nbind all <FocusIn> {}\nbind all <FocusOut> {}\nbind all <Key> {}\nfixfocus\n\ntest focus-6.1 {miscellaneous - embedded application in same process} -constraints {\n    unix  testwrapper\n} -setup {\n    eval interp delete [interp children]\n} -body {\n    toplevel .t\n    wm geometry .t +0+0\n    frame .t.f1 -container 1\n    frame .t.f2\n    pack .t.f1 .t.f2\n    entry .t.f2.e1 -bg red\n    pack .t.f2.e1\n    bind all <FocusIn> {lappend x \"focus in %W %d\"}\n    bind all <FocusOut> {lappend x \"focus out %W %d\"}\n    interp create child\n    child eval \"set argv {-use [winfo id .t.f1]}\"\n    load {} Tk child\n    child eval {\n\tentry .e1 -bg lightBlue\n\tpack .e1\n\tbind all <FocusIn> {lappend x \"focus in %W %d\"}\n\tbind all <FocusOut> {lappend x \"focus out %W %d\"}\n\tset x {}\n    }\n\n    # Claim the focus and wait long enough for it to really arrive.\n\n    focus -force .t.f2.e1\n    after 300 {set timer 1}\n    vwait timer\n    set x {}\n    lappend x [focus] [child eval focus]\n\n    # See if a \"focus\" command will move the focus to the embedded\n    # application.\n\n    child eval {focus .e1}\n    after 300 {set timer 1}\n    vwait timer\n    lappend x |\n    child eval {lappend x |}\n\n    # Bring the focus back to the main application.\n\n    focus .t.f2.e1\n    after 300 {set timer 1}\n    vwait timer\n    set result [list $x [child eval {set x}]]\n    return $result\n} -cleanup {\n    interp delete child\n    destroy .t\n    bind all <FocusIn> {}\n    bind all <FocusOut> {}\n} -result {{.t.f2.e1 {} {focus out .t.f2.e1 NotifyNonlinear} {focus out .t.f2 NotifyNonlinearVirtual} {focus in .t.f1 NotifyNonlinear} | {focus out .t.f1 NotifyNonlinear} {focus in .t.f2 NotifyNonlinearVirtual} {focus in .t.f2.e1 NotifyNonlinear}} {{focus in . NotifyVirtual} {focus in .e1 NotifyAncestor} | {focus out .e1 NotifyAncestor} {focus out . NotifyVirtual}}}\n\ntest focus-6.2 {miscellaneous - embedded application in different process} -constraints {\n    unix  testwrapper\n} -body {\n    childTkProcess create\n    toplevel .t\n    wm geometry .t +0+0\n    frame .t.f1 -container 1\n    frame .t.f2\n    pack .t.f1 .t.f2\n    entry .t.f2.e1 -bg red\n    pack .t.f2.e1\n    bind all <FocusIn> {lappend x \"focus in %W %d\"}\n    bind all <FocusOut> {lappend x \"focus out %W %d\"}\n    childTkProcess create -use [winfo id .t.f1]\n    childTkProcess eval {\n\tentry .e1 -bg lightBlue\n\tpack .e1\n\tbind all <FocusIn> {lappend x \"focus in %W %d\"}\n\tbind all <FocusOut> {lappend x \"focus out %W %d\"}\n\tset x {}\n    }\n\n    # Claim the focus and wait long enough for it to really arrive.\n\n    focus -force .t.f2.e1\n    after 300 {set timer 1}\n    vwait timer\n    set x {}\n    lappend x [focus] [childTkProcess eval focus]\n\n    # See if a \"focus\" command will move the focus to the embedded\n    # application.\n\n    childTkProcess eval {focus .e1}\n    after 300 {set timer 1}\n    vwait timer\n    lappend x |\n    childTkProcess eval {lappend x |}\n\n    # Bring the focus back to the main application.\n\n    focus .t.f2.e1\n    after 300 {set timer 1}\n    vwait timer\n    set result [list $x [childTkProcess eval {set x}]]\n    return $result\n} -cleanup {\n    destroy .t\n    childTkProcess exit\n    bind all <FocusIn> {}\n    bind all <FocusOut> {}\n} -result {{.t.f2.e1 {} {focus out .t.f2.e1 NotifyNonlinear} {focus out .t.f2 NotifyNonlinearVirtual} {focus in .t.f1 NotifyNonlinear} | {focus out .t.f1 NotifyNonlinear} {focus in .t.f2 NotifyNonlinearVirtual} {focus in .t.f2.e1 NotifyNonlinear}} {{focus in . NotifyVirtual} {focus in .e1 NotifyAncestor} | {focus out .e1 NotifyAncestor} {focus out . NotifyVirtual}}}\n\ntest focus-7.1 {TkSetFocusWin procedure, unmapped windows} -setup {\n    # TkSetFocusWin handles the case of not yet mapped windows\n    # by not setting the focus on them right at the time it is\n    # requested, but by scheduling an event handler that will\n    # set the focus later once it gets mapped. The purpose of\n    # this test is to check that event scheduling and deletion\n    # work as expected (bug [08e2f8e6f0]).\n    toplevel .top\n    spinbox .top.s1\n    spinbox .top.s2\n    spinbox .top.s3\n    grid .top.s1 .top.s2 .top.s3\n} -body {\n    focus -force .top.s2\n    focus -force .top.s3\n    update\n    focus\n} -cleanup {\n    destroy .top\n} -result {.top.s3}\n\ntest focus-8.1 {fdc0ed342d - segfault on focus -force} -body {\n    pack [button .b0]\n    toplevel .one\n    update\n    event generate .one <Motion> -warp 1 -x 175 -y 175\n    update idletasks\n    destroy {*}[winfo children .]\n    toplevel .t\n    pack [canvas .t.c]\n    update\n    destroy .t.c\n    pack [label .t.l]\n    update\n    destroy .t.l\n    destroy {*}[winfo children .]\n    proc crashit {} {\n\tpack [listbox .l]\n\tupdate\n\tfocus -force .l;  # This line segfaulted *with xvfb*\n\tset res Reached\n    }\n    crashit\n} -result {Reached}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ntestutils forget child\ncleanupTests\nif {[tk windowingsystem] eq \"aqua\"} {\n    interp delete childInterp\n}\n"
  },
  {
    "path": "tests/focusTcl.test",
    "content": "# This file is a Tcl script to test out the features of the script\n# file focus.tcl, which includes the procedures tk_focusNext and\n# tk_focusPrev, among other things.\n#\n# Copyright © 1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc setup1 w {\n    if {$w eq \".\"} {\n\tset w \"\"\n    }\n    foreach i {a b c d} {\n\tdestroy $w.$i\n\tframe  $w.$i -width 200 -height 50 -bd 2 -relief raised\n\tpack $w.$i\n    }\n    .b configure -width 0 -height 0\n    foreach i {x y z} {\n\tdestroy $w.b.$i\n\tbutton $w.b.$i -text \"Button $w.b.$i\"\n\tpack $w.b.$i -side left\n    }\n    if {![winfo ismapped $w.b.z]} {\n\ttkwait visibility $w.b.z\n    }\n}\n\nproc cleanup1 w {\n    if {$w eq \".\"} {\n\tset w \"\"\n    }\n    foreach i {a b c d} {\n\tdestroy $w.$i\n    }\n    foreach i {x y z} {\n\tdestroy $w.b.$i\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\noption add *takeFocus 1\noption add *highlightThickness 2\n. configure -takefocus 1 -highlightthickness 2\n\n#\n# TESTS\n#\n\ntest focusTcl-1.1 {tk_focusNext procedure, no children} -body {\n    tk_focusNext .\n} -result {.}\n\ntest focusTcl-1.2 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .\n} -cleanup {\n    cleanup1 .\n} -result {.a}\ntest focusTcl-1.3 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .a\n} -cleanup {\n    cleanup1 .\n} -result {.b}\ntest focusTcl-1.4 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.b.x}\ntest focusTcl-1.5 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .b.x\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-1.6 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .b.y\n} -cleanup {\n    cleanup1 .\n} -result {.b.z}\ntest focusTcl-1.7 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .b.z\n} -cleanup {\n    cleanup1 .\n} -result {.c}\ntest focusTcl-1.8 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .c\n} -cleanup {\n    cleanup1 .\n} -result {.d}\ntest focusTcl-1.9 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusNext .d\n} -cleanup {\n    cleanup1 .\n} -result {.}\n\ntest focusTcl-1.10 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    foreach w {.b .b.x .b.y .c .d} {\n\t$w configure -takefocus 0\n    }\n    tk_focusNext .a\n} -cleanup {\n    cleanup1 .\n} -result {.b.z}\ntest focusTcl-1.11 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    foreach w {.b .b.x .b.y .c .d} {\n\t$w configure -takefocus 0\n    }\n    tk_focusNext .b.z\n} -cleanup {\n    cleanup1 .\n} -result {.}\n\ntest focusTcl-1.12 {tk_focusNext procedure, basic tree traversal} -body {\n    setup1 .\n    deleteWindows\n    setup1 .\n    update\n    . configure -takefocus 0\n    tk_focusNext .d\n} -cleanup {\n    . configure -takefocus 1\n    cleanup1 .\n} -result {.a}\n\n\ntest focusTcl-2.1 {tk_focusNext procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusNext .a\n} -cleanup {\n    deleteWindows\n} -result {.b}\ntest focusTcl-2.2 {tk_focusNext procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusNext .d\n} -cleanup {\n    deleteWindows\n} -result {.}\ntest focusTcl-2.3 {tk_focusNext procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusNext .t\n} -cleanup {\n    deleteWindows\n} -result {.t}\ntest focusTcl-2.4 {tk_focusNext procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n    setup1 .t\n    raise .t.b\n\n    tk_focusNext .t\n} -cleanup {\n    deleteWindows\n} -result {.t.a}\ntest focusTcl-2.5 {tk_focusNext procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n    setup1 .t\n    raise .t.b\n\n    tk_focusNext .t.b.z\n} -cleanup {\n    deleteWindows\n} -result {.t}\n\n\ntest focusTcl-3.1 {tk_focusPrev procedure, no children} -body {\n    tk_focusPrev .\n} -result {.}\n\ntest focusTcl-3.2 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .\n} -cleanup {\n    cleanup1 .\n} -result {.d}\ntest focusTcl-3.3 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .d\n} -cleanup {\n    cleanup1 .\n} -result {.c}\ntest focusTcl-3.4 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .c\n} -cleanup {\n    cleanup1 .\n} -result {.b.z}\ntest focusTcl-3.5 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .b.z\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-3.6 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .b.y\n} -cleanup {\n    cleanup1 .\n} -result {.b.x}\ntest focusTcl-3.7 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .b.x\n} -cleanup {\n    cleanup1 .\n} -result {.b}\ntest focusTcl-3.8 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .b\n} -cleanup {\n    cleanup1 .\n} -result {.a}\ntest focusTcl-3.9 {tk_focusPrev procedure, basic tree traversal} -body {\n    setup1 .\n    tk_focusPrev .a\n} -cleanup {\n    cleanup1 .\n} -result {.}\n\n#\n# COMMON TEST SETUP\n#\n\ndeleteWindows\nsetup1 .\ntoplevel .t\nwm geom .t +0+0\ntoplevel .t2\nwm geom .t2 -0+0\nraise .t .a\n\ntest focusTcl-4.1 {tk_focusPrev procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusPrev .\n} -cleanup {\n    deleteWindows\n} -result {.d}\ntest focusTcl-4.2 {tk_focusPrev procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusPrev .b\n} -cleanup {\n    deleteWindows\n} -result {.a}\ntest focusTcl-4.3 {tk_focusPrev procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n\n    tk_focusPrev .t\n} -cleanup {\n    deleteWindows\n} -result {.t}\n\ntest focusTcl-4.4 {tk_focusPrev procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n    setup1 .t\n    update\n    .t configure -takefocus 0\n    raise .t.b\n\n    tk_focusPrev .t\n} -cleanup {\n    deleteWindows\n} -result {.t.b.z}\ntest focusTcl-4.5 {tk_focusPrev procedure, toplevels} -setup {\n    deleteWindows\n} -body {\n    setup1 .\n    toplevel .t\n    wm geom .t +0+0\n    toplevel .t2\n    wm geom .t2 -0+0\n    raise .t .a\n    setup1 .t\n    update\n    .t configure -takefocus 0\n    raise .t.b\n\n    tk_focusPrev .t.a\n} -cleanup {\n    deleteWindows\n} -result {.t.b.z}\n\n\ntest focusTcl-5.1 {tkFocusOK procedure, -takefocus 0} -body {\n    setup1 .\n    .b.x configure -takefocus 0\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-5.2 {tkFocusOK procedure, -takefocus 1} -body {\n    setup1 .\n    pack forget .b\n    update\n    .b configure -takefocus \"\"\n    .b.y configure -takefocus \"\"\n    .b.z configure -takefocus \"\"\n    list [tk_focusNext .a] [tk_focusNext .b.x]\n} -cleanup {\n    cleanup1 .\n} -result {.c .c}\ntest focusTcl-5.3 {tkFocusOK procedure, -takefocus procedure} -body {\n    proc t w {\n    if {$w eq \".b.x\"} {\n\treturn 1\n    } elseif {$w eq \".b.y\"} {\n\treturn \"\"\n    }\n    return 0\n    }\n\n    setup1 .\n    pack forget .b.y\n    update\n    .b configure -takefocus \"\"\n    foreach w {.b.x .b.y .b.z .c} {\n\t$w configure -takefocus t\n    }\n    list [tk_focusNext .a] [tk_focusNext .b.x]\n} -cleanup {\n    cleanup1 .\n} -result {.b.x .d}\ntest focusTcl-5.4 {tkFocusOK procedure, -takefocus \"\"} -body {\n    setup1 .\n    .b.x configure -takefocus \"\"\n    update\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.b.x}\ntest focusTcl-5.5 {tkFocusOK procedure, -takefocus \"\", not mapped} -body {\n    setup1 .\n    .b.x configure -takefocus \"\"\n    pack forget .b.x\n    update\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-5.6 {tkFocusOK procedure, -takefocus \"\", not mapped} -body {\n    setup1 .\n    foreach w {.b.x .b.y .b.z} {\n\t$w configure -takefocus \"\"\n    }\n    pack forget .b\n    update\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.c}\ntest focusTcl-5.7 {tkFocusOK procedure, -takefocus \"\", not mapped} -body {\n    setup1 .\n    .b.y configure -takefocus 1\n    pack forget .b.y\n    update\n    tk_focusNext .b.x\n} -cleanup {\n    cleanup1 .\n} -result {.b.z}\ntest focusTcl-5.8 {tkFocusOK procedure, -takefocus \"\", not mapped} -body {\n    proc always args {return 1}\n    setup1 .\n    .b.y configure -takefocus always\n    pack forget .b.y\n    update\n    tk_focusNext .b.x\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-5.9 {tkFocusOK procedure, -takefocus \"\", window disabled} -body {\n    setup1 .\n    foreach w {.b.x .b.y .b.z} {\n\t$w configure -takefocus \"\"\n    }\n    update\n    .b.x configure -state disabled\n    tk_focusNext .b\n} -cleanup {\n    cleanup1 .\n} -result {.b.y}\ntest focusTcl-5.10 {tkFocusOK procedure, -takefocus \"\", check for bindings} -body {\n    setup1 .\n    foreach w {.a .b .c .d} {\n\t$w configure -takefocus \"\"\n    }\n    update\n    bind .a <Key> {foo}\n    list [tk_focusNext .] [tk_focusNext .a]\n} -cleanup {\n    cleanup1 .\n} -result {.a .b.x}\ntest focusTcl-5.11 {tkFocusOK procedure, -takefocus \"\", check for bindings} -body {\n    setup1 .\n    foreach w {.a .b .c .d} {\n\t$w configure -takefocus \"\"\n    }\n    update\n    bind Frame <Key> {foo}\n    list [tk_focusNext .] [tk_focusNext .a]\n} -cleanup {\n    cleanup1 .\n    bind Frame <Key> {}\n} -result {.a .b}\n\n#\n# TESTFILE CLEANUP\n#\n\n. configure -takefocus 0 -highlightthickness 0\noption clear\ncleanupTests\n"
  },
  {
    "path": "tests/font.test",
    "content": "# This file is a Tcl script to test out Tk's \"font\" command\n# plus the procedures in tkFont.c.\n#\n# Copyright © 1996-1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding the font system that\n# are specific to the unix platform (this includes macOS), or to the windows\n# platform go into the test files unixFont.test or winFont.test respectively.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc clearnondefaultfonts {} {\n    foreach afont [getnondefaultfonts] {\n\tfont delete $afont\n    }\n}\n\nproc csetup {{str \"\"}} {\n    focus -force .t.c\n    .t.c dchars text 0 end\n    .t.c insert text 0 $str\n    .t.c focus text\n}\n\nproc getnondefaultfonts {} {\n    global defaultfontlist\n    set nondeffonts [list ]\n    foreach afont [font names] {\n\tif {$afont ni $defaultfontlist} {\n\t    lappend nondeffonts $afont\n\t}\n    }\n    set nondeffonts\n}\n\nproc psfontname {name} {\n\tdestroy .t.c\n\tcanvas .t.c -closeenough 0\n\t.t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\n\tpack .t.c\n\tupdate\n    set a [.t.c itemcget text -font]\n    .t.c itemconfig text -text \"We need text\" -font $name\n    set post [.t.c postscript]\n    .t.c itemconfig text -font $a\n    set end [string first \"findfont\" $post]\n    incr end -2\n    set post [string range $post [expr {$end-70}] $end]\n    set start [string first \"gsave\" $post]\n\tdestroy .t.c\n    return [string range $post [expr {$start+7}] end]\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset defaultfontlist [font names]\n\nswitch [tk windowingsystem] {\n    x11\t\t{set fixed \"TkFixedFont\"}\n    win32\t{set fixed \"courier 12\"}\n    aqua\t{set fixed \"monaco 9\"}\n}\n\ndeleteWindows\n# Toplevel used (in some tests) of the whole file\ntoplevel .t\nwm geom .t +0+0\nupdate idletasks\n\n#\n# TESTS\n#\n\ntest font-1.1 {TkFontPkgInit} -setup {\n    catch {interp delete foo}\n} -body {\n    interp create foo\n    foo eval {\n\tload {} Tk\n\twm geometry . +0+0\n\tupdate\n    }\n    interp delete foo\n} -result {}\n\n\ntest font-2.1 {TkFontPkgFree} -setup {\n    catch {interp delete foo}\n    set x {}\n} -body {\n    interp create foo\n\n    # Makes sure that named font was visible only to child interp.\n    foo eval {\n\tload {} Tk\n\twm geometry . +0+0\n\tbutton .b -font {times 16} -text \"hi\"\n\tpack .b\n\tfont create wiggles -family courier -underline 1\n\tupdate\n    }\n    lappend x [catch {font configure wiggles} msg; set msg]\n\n    # Tests cancelling the idle handler for TheWorldHasChanged,\n    # because app goes away before idle serviced.\n    foo eval {\n\t.b config -font wiggles\n\tfont config wiggles -size 24\n\tdestroy .\n    }\n    lappend x [foo eval {catch {font families} msg; set msg}]\n} -cleanup {\n    interp delete foo\n} -result {{named font \"wiggles\" does not exist} {cannot invoke \"font\" command: application has been destroyed}}\n\n\ntest font-3.1 {font command: general} -body {\n    font\n} -returnCodes error -result {wrong # args: should be \"font option ?arg?\"}\ntest font-3.2 {font command: general} -body {\n    font xyz\n} -returnCodes error -result {bad option \"xyz\": must be actual, configure, create, delete, families, measure, metrics, or names}\n\n\ntest font-4.1 {font command: actual: arguments} -body {\n    # (skip < 0)\n    font actual xyz -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest font-4.2 {font command: actual: arguments} -body {\n    # (objc < 3)\n    font actual\n} -returnCodes error -result {wrong # args: should be \"font actual font ?-displayof window? ?-option? ?--? ?char?\"}\ntest font-4.3 {font command: actual: arguments} -body {\n    # (objc - skip > 4) when skip == 0\n    font actual xyz abc def\n} -returnCodes error -result {wrong # args: should be \"font actual font ?-displayof window? ?-option? ?--? ?char?\"}\ntest font-4.4 {font command: actual: displayof specified, so skip to next} -body {\n    catch {font actual xyz -displayof . -size}\n} -result 0\ntest font-4.5 {font command: actual: displayof specified, so skip to next} -body {\n    lindex [font actual xyz -displayof .] 0\n} -result {-family}\ntest font-4.6 {font command: actual: arguments} -body {\n    # (objc - skip > 4) when skip == 2\n    font actual xyz -displayof . abc def\n} -returnCodes error -result {wrong # args: should be \"font actual font ?-displayof window? ?-option? ?--? ?char?\"}\ntest font-4.7 {font command: actual: arguments} -body {\n    # (tkfont == NULL)\n    font actual \"\\{xyz\"\n} -returnCodes error -result \"font \\\"{xyz\\\" does not exist\"\ntest font-4.8 {font command: actual: all attributes} -body {\n    # not (objc > 3) so objPtr = NULL\n    lindex [font actual {-family times}] 0\n} -result {-family}\ntest font-4.9 {font command: actual} -constraints {haveTimesFamilyFont} -body {\n    # (objc > 3) so objPtr = objv[3 + skip]\n    string tolower [font actual {-family times} -family]\n} -result {times}\ntest font-4.10 {font command: actual} -constraints win -body {\n    # (objc > 3) so objPtr = objv[3 + skip]\n    font actual {-family times} -family\n} -result {times}\ntest font-4.11 {font command: bad option} -body {\n    font actual xyz -style\n} -returnCodes error -result {bad option \"-style\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\ntest font-4.12 {font command: actual} -body {\n    font actual {-family times} -- \\uD800\n} -match glob -result {*}\ntest font-4.13 {font command: actual} -body {\n    font actual {-family times} -- \\uDC00\n} -match glob -result {*}\ntest font-4.14 {font command: actual} -body {\n    font actual {-family times} -- \\uD800\\uDC00\n} -returnCodes 1 -match glob -result {expected a single character but got \"*\"}\ntest font-4.15 {font command: actual} -body {\n    font actual {-family times} -- \\uDC00\\uD800\n} -returnCodes 1 -match glob -result {expected a single character but got \"*\"}\ntest font-4.16 {font command: actual} -constraints {win knownBug} -body {\n    font actual {-family times} -family -- \\U10000\n} -result {times}\n\n\ntest font-5.1 {font command: configure} -body {\n    # (objc < 3)\n    font configure\n} -returnCodes error -result {wrong # args: should be \"font configure fontname ?-option value ...?\"}\ntest font-5.2 {font command: configure: non-existent font} -body {\n    # (namedHashPtr == NULL)\n    font configure xyz\n} -returnCodes error -result {named font \"xyz\" does not exist}\ntest font-5.3 {font command: configure: \"deleted\" font} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # (nfPtr->deletePending != 0)\n    font create xyz\n    .t.f configure -font xyz\n    font delete xyz\n    font configure xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {named font \"xyz\" does not exist}\ntest font-5.4 {font command: configure: get all options} -setup {\n    catch {font delete xyz}\n} -body {\n    # (objc == 3) so objPtr = NULL\n    font create xyz -family xyz\n    lindex [font configure xyz] 1\n} -cleanup {\n    font delete xyz\n} -result xyz\ntest font-5.5 {font command: configure: get one option} -setup {\n    clearnondefaultfonts\n} -body {\n    # (objc == 4) so objPtr = objv[3]\n    font create xyz -family xyz\n    font configure xyz -family\n    getnondefaultfonts\n} -cleanup {\n    font delete xyz\n} -result xyz\ntest font-5.6 {font command: configure: update existing font} -setup {\n    catch {font delete xyz}\n} -body {\n    # else result = ConfigAttributesObj()\n    font create xyz\n    font configure xyz -family xyz\n    update\n    font configure xyz -family\n} -cleanup {\n    font delete xyz\n} -result xyz\ntest font-5.7 {font command: configure: bad option} -setup {\n    catch {font delete xyz}\n} -body {\n    font create xyz\n    font configure xyz -style\n} -cleanup {\n    font delete xyz\n} -returnCodes error -result {bad option \"-style\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\n\n\ntest font-6.1 {font command: create: make up name} -setup {\n    clearnondefaultfonts\n} -body {\n    # (objc < 3) so name = NULL\n    font create\n    getnondefaultfonts\n} -cleanup {\n    font delete font1\n} -result {font1}\ntest font-6.2 {font command: create: name specified} -setup {\n    clearnondefaultfonts\n} -body {\n    # not (objc < 3)\n    font create xyz\n    getnondefaultfonts\n} -cleanup {\n    font delete xyz\n} -result {xyz}\ntest font-6.3 {font command: create: name not really specified} -setup {\n    clearnondefaultfonts\n} -body {\n    # (name[0] == '-') so name = NULL\n    font create -family xyz\n    getnondefaultfonts\n} -cleanup {\n    font delete font1\n} -result {font1}\ntest font-6.4 {font command: create: generate name} -setup {\n} -body {\n    # (name == NULL)\n    font create -family one\n    font create -family two\n    font create -family three\n    font delete font2\n    font create -family four\n    font configure font2 -family\n} -cleanup {\n    font delete font1 font2 font3\n} -result {four}\ntest font-6.5 {font command: create: bad option creating new font} -setup {\n    catch {font delete xyz}\n} -body {\n    # name was specified so skip = 3\n    font create xyz -xyz times\n} -returnCodes error -result {bad option \"-xyz\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\ntest font-6.6 {font command: create: bad option creating new font} -setup {\n    clearnondefaultfonts\n} -body {\n    # name was not specified so skip = 2\n    font create -xyz times\n} -returnCodes error -result {bad option \"-xyz\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\ntest font-6.7 {font command: create: already exists} -setup {\n    catch {font delete xyz}\n} -body {\n    # (CreateNamedFont() != TCL_OK)\n    font create xyz\n    font create xyz\n} -cleanup {\n    font delete xyz\n} -returnCodes error -result {named font \"xyz\" already exists}\n\ntest font-7.1 {font command: delete: arguments} -body {\n    # (objc < 3)\n    font delete\n} -returnCodes error -result {wrong # args: should be \"font delete fontname ?fontname ...?\"}\ntest font-7.2 {font command: delete: loop test} -setup {\n    clearnondefaultfonts\n    set x {}\n} -body {\n    # for (i = 2; i < objc; i++)\n    font create a -underline 1\n    font create b -underline 1\n    font create c -underline 1\n    font create d -underline 1\n    font create e -underline 1\n    lappend x [lsort [getnondefaultfonts]]\n    font delete a e c b\n    lappend x [lsort [getnondefaultfonts]]\n} -cleanup {\n    getnondefaultfonts\n} -result {{a b c d e} d}\ntest font-7.3 {font command: delete: loop test} -setup {\n    clearnondefaultfonts\n    set x {}\n} -body {\n    # (namedHashPtr == NULL) in middle of loop\n    font create a -underline 1\n    font create b -underline 1\n    font create c -underline 1\n    font create d -underline 1\n    font create e -underline 1\n    lappend x [lsort [getnondefaultfonts]]\n    catch {font delete a d q c e b}\n    lappend x [lsort [getnondefaultfonts]]\n} -cleanup {\n    clearnondefaultfonts\n} -result {{a b c d e} {b c e}}\ntest font-7.4 {font command: delete: non-existent} -setup {\n    catch {font delete xyz}\n} -body {\n    # (namedHashPtr == NULL)\n    font delete xyz\n} -returnCodes error -result {named font \"xyz\" does not exist}\ntest font-7.5 {font command: delete: mark for later deletion} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # (nfPtr->refCount != 0)\n    font create xyz\n    .t.f configure -font xyz\n    font delete xyz\n    font actual xyz\n    font configure xyz\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {named font \"xyz\" does not exist}\ntest font-7.6 {font command: delete: mark for later deletion} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # (nfPtr->refCount != 0)\n    font create xyz\n    .t.f configure -font xyz\n    font delete xyz\n    font actual xyz\n    catch {font configure xyz}\n    .t.f cget -font\n} -cleanup {\n\tdestroy .t.f\n} -result xyz\ntest font-7.7 {font command: delete: actually delete} -setup {\n    catch {font delete xyz}\n} -body {\n    # not (nfPtr->refCount != 0)\n    font create xyz -underline 1\n    font delete xyz\n    font config xyz\n} -returnCodes error -match glob -result {*}\n\n\ntest font-8.1 {font command: families: arguments} -body {\n    # (skip < 0)\n    font families -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest font-8.2 {font command: families: arguments} -body {\n    # (objc - skip != 2) when skip == 0\n    font families xyz\n} -returnCodes error -result {wrong # args: should be \"font families ?-displayof window?\"}\ntest font-8.3 {font command: families: arguments} -body {\n    # (objc - skip != 2) when skip == 2\n    font families -displayof . xyz\n} -returnCodes error -result {wrong # args: should be \"font families ?-displayof window?\"}\ntest font-8.4 {font command: families} -constraints haveTimesFamilyFont -body {\n    # TkpGetFontFamilies()\n    regexp -nocase times [font families]\n} -result 1\n\n\ntest font-9.1 {font command: measure: arguments} -body {\n    # (skip < 0)\n    expr {[font measure xyz -displayof] > 0}\n} -returnCodes ok -result 1\ntest font-9.2 {font command: measure: arguments} -body {\n    # (objc - skip != 4)\n    font measure\n} -returnCodes error -result {wrong # args: should be \"font measure font ?-displayof window? text\"}\ntest font-9.3 {font command: measure: arguments} -body {\n    # (objc - skip != 4)\n    font measure xyz abc def\n} -returnCodes error -result {wrong # args: should be \"font measure font ?-displayof window? text\"}\ntest font-9.4 {font command: measure: arguments} -body {\n    # (tkfont == NULL)\n    font measure \"\\{xyz\" abc\n} -returnCodes error -result \"font \\\"{xyz\\\" does not exist\"\ntest font-9.5 {font command: measure} -body {\n    # Tk_TextWidth()\n    expr {[font measure $fixed \"abcdefg\"] == [font measure $fixed \"a\"]*7 }\n} -result 1\ntest font-9.6 {font command: measure -d} -body {\n     expr {[font measure $fixed -d] > 0}\n} -returnCodes ok -result 1\ntest font-9.7 {font command: measure -d with -displayof} -body {\n     expr {[font measure $fixed -displayof . -d] > 0}\n} -returnCodes ok -result 1\ntest font-9.8 {font command: measure: arguments} -body {\n    font measure $fixed -displayof .\n} -returnCodes error -result {wrong # args: should be \"font measure font ?-displayof window? text\"}\n\n\ntest font-10.1 {font command: metrics: arguments} -body {\n    font metrics xyz -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest font-10.2 {font command: metrics: arguments} -body {\n    # (skip < 0)\n    font metrics xyz -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest font-10.3 {font command: metrics: arguments} -body {\n    # (objc < 3)\n    font metrics\n} -returnCodes error -result {wrong # args: should be \"font metrics font ?-displayof window? ?-option?\"}\ntest font-10.4 {font command: metrics: arguments} -body {\n    # (objc - skip) > 4) when skip == 0\n    font metrics xyz abc def\n} -returnCodes error -result {wrong # args: should be \"font metrics font ?-displayof window? ?-option?\"}\ntest font-10.5 {font command: metrics: arguments} -body {\n    # (objc - skip) > 4) when skip == 2\n    font metrics xyz -displayof . abc\n} -returnCodes error -result {bad metric \"abc\": must be -ascent, -descent, -fixed, or -linespace}\ntest font-10.6 {font command: metrics: bad font} -body {\n    # (tkfont == NULL)\n    font metrics \"\\{xyz\"\n} -returnCodes error -result \"font \\\"{xyz\\\" does not exist\"\ntest font-10.7 {font command: metrics: get all metrics} -setup {\n    catch {unset a}\n} -body {\n    # (objc == 3)\n    array set a [font metrics {-family xyz}]\n    lsort [array names a]\n} -cleanup {\n    unset a\n} -result {-ascent -descent -fixed -linespace}\ntest font-10.8 {font command: metrics: bad metric} -body {\n    # (Tcl_GetIndexFromObj() != TCL_OK)\n    font metrics $fixed -xyz\n} -returnCodes error -result {bad metric \"-xyz\": must be -ascent, -descent, -fixed, or -linespace}\ntest font-10.9 {font command: metrics: get individual metrics} -body {\n    font metrics $fixed -ascent\n    font metrics $fixed -descent\n    font metrics $fixed -linespace\n    font metrics $fixed -fixed\n} -result 1\n\n\ntest font-11.1 {font command: names: arguments} -body {\n    # (objc != 2)\n    font names xyz\n} -returnCodes error -result {wrong # args: should be \"font names\"}\ntest font-11.2 {font command: names: loop test: no passes} -setup {\n    clearnondefaultfonts\n} -body {\n    getnondefaultfonts\n} -result {}\ntest font-11.3 {font command: names: loop test: one pass} -setup {\n    clearnondefaultfonts\n} -body {\n    font create\n    getnondefaultfonts\n} -result {font1}\ntest font-11.4 {font command: names: loop test: multiple passes} -setup {\n    clearnondefaultfonts\n} -body {\n    font create xyz\n    font create abc\n    font create def\n    lsort [getnondefaultfonts]\n} -cleanup {\n    clearnondefaultfonts\n} -result {abc def xyz}\ntest font-11.5 {font command: names: skip deletePending fonts} -setup {\n    destroy .t.f\n    clearnondefaultfonts\n    pack [label .t.f]\n    update\n    set x {}\n} -body {\n    # (nfPtr->deletePending == 0)\n    font create xyz\n    font create abc\n    lappend x [lsort [getnondefaultfonts]]\n    .t.f config -font xyz\n    font delete xyz\n    lappend x [getnondefaultfonts]\n} -cleanup {\n    clearnondefaultfonts\n} -result {{abc xyz} abc}\n\n\ntest font-12.1 {UpdateDependantFonts procedure: no users} -setup {\n    catch {font delete xyz}\n} -body {\n    # (nfPtr->refCount == 0)\n    font create xyz\n    font configure xyz -family times\n} -cleanup {\n    font delete xyz\n} -result {}\ntest font-12.2 {UpdateDependantFonts procedure: pings the widgets} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update idletasks\n} -body {\n    font create xyz -family times -size 20\n    .t.f config -font xyz -text \"abcd\" -padx 0 -bd 0 -highlightthickness 0\n    set a1 [font measure xyz \"abcd\"]\n    update idletasks\n    set b1 [winfo reqwidth .t.f]\n    font configure xyz -family helvetica -size 20\n    set a2 [font measure xyz \"abcd\"]\n    update idletasks\n    set b2 [winfo reqwidth .t.f]\n    expr {$a1==$b1 && $a2==$b2}\n} -cleanup {\n    destroy .t.f\n    font delete xyz\n} -result 1\n\n\ntest font-13.1 {CreateNamedFont: new named font} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    # not (new == 0)\n    lappend x [getnondefaultfonts]\n    font create xyz\n    lappend x [getnondefaultfonts]\n} -cleanup {\n    font delete xyz\n} -result {{} xyz}\ntest font-13.2 {CreateNamedFont: named font already exists} -setup {\n    catch {font delete xyz}\n} -body {\n    # (new == 0)\n    font create xyz\n    font create xyz\n} -cleanup {\n    font delete xyz\n} -returnCodes error -result {named font \"xyz\" already exists}\ntest font-13.3 {CreateNamedFont: named font already exists} -setup {\n    catch {font delete xyz}\n} -body {\n    # (nfPtr->deletePending == 0)\n    font create xyz\n    font create xyz\n} -cleanup {\n    font delete xyz\n} -returnCodes error -result {named font \"xyz\" already exists}\ntest font-13.4 {CreateNamedFont: recreate \"deleted\" font} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # not (nfPtr->deletePending == 0)\n    font create xyz -family times\n    .t.f configure -font xyz\n    font delete xyz\n    font create xyz -family courier\n    font configure xyz -family\n} -cleanup {\n    font delete xyz\n    destroy .t.f\n} -result {courier}\n\n\ntest font-14.1 {Tk_GetFont procedure} -body {\n} -result {}\n\n\ntest font-15.1 {Tk_AllocFontFromObj - converting internal reps} -constraints {\n    testfont\n} -setup {\n    destroy .b1 .b2\n} -body {\n    set x [font create font-15.1_font -family Times -size 16]\n    lindex $x 0\n    button .b1 -font $x\n    lindex $x 0\n    testfont counts $x\n} -cleanup {\n    font delete font-15.1_font\n    destroy .b1 .b2\n} -result {{1 0}}\ntest font-15.2 {Tk_AllocFontFromObj - discard stale font} -constraints {\n    testfont\n} -setup {\n    destroy .b1 .b2\n    set result {}\n} -body {\n    set x [font create font-15.2_font -family Times -size 16]\n    button .b1 -font $x\n    destroy .b1\n    lappend result [testfont counts $x]\n    button .b2 -font $x\n    lappend result [testfont counts $x]\n} -cleanup {\n    font delete font-15.2_font\n    destroy .b2\n} -result {{} {{1 1}}}\ntest font-15.3 {Tk_AllocFontFromObj - reuse existing font} -constraints {\n    testfont\n} -setup {\n    destroy .b1 .b2\n    set result {}\n} -body {\n    set x [font create font-15.3_font -family Times -size 16]\n    button .b1 -font $x\n    lappend result [testfont counts $x]\n    button .b2 -font $x\n    pack .b1 .b2 -side top\n    lappend result [testfont counts $x]\n} -cleanup {\n    font delete font-15.3_font\n    destroy .b1 .b2\n} -result {{{1 1}} {{2 1}}}\ntest font-15.4 {Tk_AllocFontFromObj procedure: bump ref count} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # (new == 0)\n    .t.f config -font {-family fixed}\n    lindex [font actual {-family fixed}] 0\n} -cleanup {\n    destroy .t.f\n} -result {-family}\ntest font-15.5 {Tk_AllocFontFromObj procedure: get named font} -setup {\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # (namedHashPtr != NULL)\n    font create xyz\n    .t.f config -font xyz\n} -cleanup {\n    destroy .t.f\n    font delete xyz\n} -result {}\ntest font-15.6 {Tk_AllocFontFromObj procedure: not a named font} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # not (namedHashPtr != NULL)\n    .t.f config -font {times 20}\n} -cleanup {\n    destroy .t.f\n} -result {-family} -result {}\ntest font-15.7 {Tk_AllocFontFromObj procedure: get native font} -constraints {\n\tunix\n} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # not (fontPtr == NULL)\n    .t.f config -font fixed\n} -result {}\ntest font-15.8 {Tk_AllocFontFromObj procedure: get native font} -constraints {\n\twin\n} -setup {\n    destroy .t.f\n    clearnondefaultfonts\n    pack [label .t.f]\n    update\n} -body {\n    # not (fontPtr == NULL)\n    .t.f config -font oemfixed\n} -cleanup {\n\tdestroy .t.f\n} -result {}\ntest font-15.9 {Tk_AllocFontFromObj procedure: get attribute font} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # (fontPtr == NULL)\n    .t.f config -font {xxx yyy zzz}\n} -cleanup {\n\tdestroy .t.f\n} -returnCodes error -result {expected integer but got \"yyy\"}\ntest font-15.10 {Tk_AllocFontFromObj procedure: no match} -body {\n    # (ParseFontNameObj() != TCL_OK)\n    font actual \"\\{xyz\"\n} -returnCodes error -result \"font \\\"{xyz\\\" does not exist\"\ntest font-15.11 {Tk_AllocFontFromObj procedure: get attribute font} -body {\n    # not (ParseFontNameObj() != TCL_OK)\n    lindex [font actual {plan 9}] 0\n} -result {-family}\ntest font-15.12 {Tk_AllocFontFromObj procedure: setup tab width} -setup {\n    destroy .l\n} -body {\n    # Tk_MeasureChars(fontPtr, \"0\", ...)\n    label .l -bd 0 -padx 0  -highlightthickness 0 -font $fixed -text \"a\\tb\"\n    update\n    set res1 [winfo reqwidth .l]\n\tset res2 [expr {[font measure $fixed \"0\"]*9}]\n\texpr {$res1 eq $res2}\n} -cleanup {\n    destroy .l\n} -result 1\ntest font-15.13 {Tk_AllocFontFromObj procedure: underline position} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # (fontPtr->underlineHeight == 0) because size was < 10\n    .t.f config -text \"underline\" -font \"times -8 underline\"\n    update\n} -cleanup {\n    destroy .t.f\n} -result {}\n\n\ntest font-16.1 {Tk_NameOfFont procedure} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    .t.f config -font -family\\ fixed\n    .t.f cget -font\n} -cleanup {\n    destroy .t.f\n} -result {-family fixed}\n\n\ntest font-17.1 {Tk_FreeFontFromObj - reference counts} -constraints {\n    testfont\n} -setup {\n    destroy .b1 .b2 .b3\n    set result {}\n} -body {\n    set x [font create font-17.1_font -family Courier -size 12]\n    button .b1 -font $x\n    button .b3 -font $x\n    button .b2 -font $x\n    lappend result [testfont counts $x]\n    destroy .b1\n    lappend result [testfont counts $x]\n    destroy .b2\n    lappend result [testfont counts $x]\n    destroy .b3\n    lappend result [testfont counts $x]\n} -cleanup {\n    font delete font-17.1_font\n} -result {{{3 1}} {{2 1}} {{1 1}} {}}\ntest font-17.2 {Tk_FreeFont procedure: one ref} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    # (fontPtr->refCount == 0)\n    .t.f config -font {-family fixed}\n    destroy .t.f\n} -result {}\ntest font-17.3 {Tk_FreeFont procedure: multiple ref} -setup {\n    destroy .t.f .t.b\n    pack [label .t.f]\n    update\n} -body {\n    # not (fontPtr->refCount == 0)\n    .t.f config -font {-family fixed}\n    button .t.b -font {-family fixed}\n    destroy .t.f\n    .t.b cget -font\n} -cleanup {\n    destroy .t.b\n} -result {-family fixed}\ntest font-17.4 {Tk_FreeFont procedure: named font} -setup {\n    destroy .t.f\n    clearnondefaultfonts\n    pack [label .t.f]\n    update\n} -body {\n    # (fontPtr->namedHashPtr != NULL)\n    font create xyz\n    .t.f config -font xyz\n    destroy .t.f\n    getnondefaultfonts\n} -result {xyz}\ntest font-17.5 {Tk_FreeFont procedure: named font} -constraints !withXft -setup {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    destroy .t.f\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    # not (fontPtr->refCount == 0)\n    font create xyz -underline 1\n    .t.f config -font xyz\n    font delete xyz\n    set x [font actual xyz -underline]\n    destroy .t.f\n    list [font actual xyz -underline] $x\n} -result {0 1}\ntest font-17.6 {Tk_FreeFont procedure: named font not deleted yet} -setup {\n    destroy .t.f .t.b\n    catch {font delete xyz}\n    pack [label .t.f]\n    update\n} -body {\n    font create xyz\n    .t.f config -font xyz\n    button .t.b -font xyz\n    font delete xyz\n    set x [font actual xyz]\n    destroy .t.b\n    list [lindex [font actual xyz] 0] [lindex $x 0]\n} -cleanup {\n    destroy .t.f\n} -result {-family -family}\n\n\ntest font-18.1 {FreeFontObjProc} -constraints testfont -setup {\n    destroy .b1\n    set result {}\n} -body {\n    set f [font create font-18.1_font -family Courier -size 12]\n    set x [join [list $f 50] { }]\n    button .b1 -font $x\n    set y [join [list $f 50] { }]\n    .b1 configure -font $y\n    set z [join [list $f 50] { }]\n    .b1 configure -font $z\n    lappend result [testfont counts [list $f 50]]\n    set x red\n    lappend result [testfont counts [list $f 50]]\n    set z 32\n    lappend result [testfont counts [list $f 50]]\n    destroy .b1\n    lappend result [testfont counts [list $f 50]]\n    set y bogus\n    return $result\n} -cleanup {\n    font delete font-18.1_font\n} -result {{{1 3}} {{1 2}} {{1 1}} {}}\n\n\ntest font-19.1 {Tk_FontId} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    .t.f config -font \"times 20\"\n    update\n} -cleanup {\n\tdestroy .t.f\n} -result {}\n\n\ntest font-20.1 {Tk_GetFontMetrics procedure} -setup {\n\tdestroy .t.w1 .t.w2\n} -body {\n    button .t.w1 -text abc\n    entry .t.w2 -text abcd\n    update\n    destroy .t.w1 .t.w2\n} -result {}\n\ntest font-21.1 {Tk_PostscriptFontName procedure: native} -constraints {\n\tunix\n} -body {\n    set x [font actual {{itc avant garde} 10} -family]\n    if {[string match *avant*garde $x]} {\n\t\tpsfontname \"{itc avant garde} 10\"\n    } else {\n\t\tset x {AvantGarde-Book}\n    }\n} -result {AvantGarde-Book}\ntest font-21.2 {Tk_PostscriptFontName procedure: native} -constraints {\n\twin\n} -body {\n    psfontname \"arial 10\"\n} -result {Helvetica}\ntest font-21.3 {Tk_PostscriptFontName procedure: native} -constraints {\n\twin\n} -body {\n    psfontname \"{times new roman} 10\"\n} -result {Times-Roman}\ntest font-21.4 {Tk_PostscriptFontName procedure: native} -constraints {\n\twin\n} -body {\n    psfontname \"{courier new} 10\"\n} -result {Courier}\ntest font-21.5 {Tk_PostscriptFontName procedure: spaces} -constraints {\n\tunix\n} -body {\n    set x [font actual {{lucida bright} 10} -family]\n    if {[string match lucida*bright $x]} {\n\t\tpsfontname \"{lucida bright} 10\"\n    } else {\n\t\tset x {LucidaBright}\n    }\n} -result {LucidaBright}\ntest font-21.6 {Tk_PostscriptFontName procedure: spaces} -constraints {\n    x11\n} -body {\n    set name {{new century schoolbook} 10}\n    if {[font actual {{new century schoolbook} 10} -family] eq \"new century schoolbook\"} {\n\tset x [psfontname \"{new century schoolbook} 10\"]\n    } else {\n\tset x NewCenturySchlbk-Roman\n    }\n} -result {NewCenturySchlbk-Roman}\ntest font-21.7 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {avantgarde 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"avantgarde\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x AvantGarde-Book\n    }\n} -result {AvantGarde-Book}\ntest font-21.8 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {avantgarde 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"avantgarde\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x AvantGarde-Demi\n    }\n} -result {AvantGarde-Demi}\ntest font-21.9 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {avantgarde 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"avantgarde\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x AvantGarde-BookOblique\n    }\n} -result {AvantGarde-BookOblique}\ntest font-21.10 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {avantgarde 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"avantgarde\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x AvantGarde-DemiOblique\n    }\n} -result {AvantGarde-DemiOblique}\n\ntest font-21.11 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {bookman 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"bookman\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Bookman-Light\n    }\n} -result {Bookman-Light}\ntest font-21.12 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {bookman 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"bookman\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Bookman-Demi\n    }\n} -result {Bookman-Demi}\ntest font-21.13 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {bookman 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"bookman\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Bookman-LightItalic\n    }\n} -result {Bookman-LightItalic}\ntest font-21.14 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {bookman 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"bookman\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Bookman-DemiItalic\n    }\n} -result {Bookman-DemiItalic}\n\ntest font-21.15 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {courier 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"courier\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Courier\n    }\n} -result {Courier}\ntest font-21.16 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {courier 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"courier\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Courier-Bold\n    }\n} -result {Courier-Bold}\ntest font-21.17 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {courier 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"courier\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Courier-Oblique\n    }\n} -result {Courier-Oblique}\ntest font-21.18 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {courier 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"courier\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Courier-BoldOblique\n    }\n} -result {Courier-BoldOblique}\n\ntest font-21.19 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {helvetica 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"helvetica\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Helvetica\n    }\n} -result {Helvetica}\ntest font-21.20 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {helvetica 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"helvetica\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Helvetica-Bold\n    }\n} -result {Helvetica-Bold}\ntest font-21.21 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {helvetica 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"helvetica\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Helvetica-Oblique\n    }\n} -result {Helvetica-Oblique}\ntest font-21.22 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {helvetica 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"helvetica\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Helvetica-BoldOblique\n    }\n} -result {Helvetica-BoldOblique}\n\ntest font-21.23 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {{new century schoolbook} 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"new century schoolbook\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x NewCenturySchlbk-Roman\n    }\n} -result {NewCenturySchlbk-Roman}\ntest font-21.24 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {{new century schoolbook} 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"new century schoolbook\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x NewCenturySchlbk-Bold\n    }\n} -result {NewCenturySchlbk-Bold}\ntest font-21.25 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {{new century schoolbook} 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"new century schoolbook\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x NewCenturySchlbk-Italic\n    }\n} -result {NewCenturySchlbk-Italic}\ntest font-21.26 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {{new century schoolbook} 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"new century schoolbook\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x NewCenturySchlbk-BoldItalic\n    }\n} -result {NewCenturySchlbk-BoldItalic}\n\ntest font-21.27 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {palatino 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"palatino\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Palatino-Roman\n    }\n} -result {Palatino-Roman}\ntest font-21.28 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {palatino 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"palatino\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Palatino-Bold\n    }\n} -result {Palatino-Bold}\ntest font-21.29 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {palatino 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"palatino\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Palatino-Italic\n    }\n} -result {Palatino-Italic}\ntest font-21.30 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {palatino 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"palatino\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Palatino-BoldItalic\n    }\n} -result {Palatino-BoldItalic}\n\ntest font-21.31 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {symbol 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"symbol\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Symbol\n    }\n} -result {Symbol}\ntest font-21.32 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {symbol 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"symbol\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Symbol\n    }\n} -result {Symbol}\ntest font-21.33 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {symbol 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"symbol\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Symbol\n    }\n} -result {Symbol}\ntest font-21.34 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {symbol 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"symbol\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Symbol\n    }\n} -result {Symbol}\n\ntest font-21.35 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {times 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"times\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Times-Roman\n    }\n} -result {Times-Roman}\ntest font-21.36 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {times 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"times\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Times-Bold\n    }\n} -result {Times-Bold}\ntest font-21.37 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {times 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"times\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Times-Italic\n    }\n} -result {Times-Italic}\ntest font-21.38 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {times 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"times\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x Times-BoldItalic\n    }\n} -result {Times-BoldItalic}\n\ntest font-21.39 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfchancery 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfchancery\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfChancery-MediumItalic\n    }\n} -result {ZapfChancery-MediumItalic}\ntest font-21.40 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfchancery 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfchancery\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfChancery-MediumItalic\n    }\n} -result {ZapfChancery-MediumItalic}\ntest font-21.41 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfchancery 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfchancery\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfChancery-MediumItalic\n    }\n} -result {ZapfChancery-MediumItalic}\ntest font-21.42 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfchancery 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfchancery\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfChancery-MediumItalic\n    }\n} -result {ZapfChancery-MediumItalic}\n\ntest font-21.43 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfdingbats 12 roman normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfdingbats\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfDingbats\n    }\n} -result {ZapfDingbats}\ntest font-21.44 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfdingbats 12 roman bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfdingbats\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfDingbats\n    }\n} -result {ZapfDingbats}\ntest font-21.45 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfdingbats 12 italic normal}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfdingbats\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfDingbats\n    }\n} -result {ZapfDingbats}\ntest font-21.46 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    unix\n} -body {\n    set name {zapfdingbats 12 italic bold}\n    if {[font actual {avantgarde 12 roman normal} -family] eq \"zapfdingbats\"} {\n\tset x [psfontname avantgarde 12 roman normal]\n    } else {\n\tset x ZapfDingbats\n    }\n} -result {ZapfDingbats}\n\ntest font-21.47 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {arial 12 roman normal}]\n} -result {Helvetica}\ntest font-21.48 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {arial 12 roman bold}]\n} -result {Helvetica-Bold}\ntest font-21.49 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {arial 12 italic normal}]\n} -result {Helvetica-Oblique}\ntest font-21.50 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {arial 12 italic bold}]\n} -result {Helvetica-BoldOblique}\n\ntest font-21.51 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{courier new} 12 roman normal}]\n} -result {Courier}\ntest font-21.52 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{courier new} 12 roman bold}]\n} -result {Courier-Bold}\ntest font-21.53 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{courier new} 12 italic normal}]\n} -result {Courier-Oblique}\ntest font-21.54 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{courier new} 12 italic bold}]\n} -result {Courier-BoldOblique}\n\ntest font-21.55 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {helvetica 12 roman normal}]\n} -result {Helvetica}\ntest font-21.56 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {helvetica 12 roman bold}]\n} -result {Helvetica-Bold}\ntest font-21.57 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {helvetica 12 italic normal}]\n} -result {Helvetica-Oblique}\ntest font-21.58 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {helvetica 12 italic bold}]\n} -result {Helvetica-BoldOblique}\n\ntest font-21.59 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {symbol 12 roman normal}]\n} -result {Symbol}\ntest font-21.60 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {symbol 12 roman bold}]\n} -result {Symbol-Bold}\ntest font-21.61 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {symbol 12 italic normal}]\n} -result {Symbol-Italic}\ntest font-21.62 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {symbol 12 italic bold}]\n} -result {Symbol-BoldItalic}\n\ntest font-21.63 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{times new roman} 12 roman normal}]\n} -result {Times-Roman}\ntest font-21.64 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{times new roman} 12 roman bold}]\n} -result {Times-Bold}\ntest font-21.65 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{times new roman} 12 italic normal}]\n} -result {Times-Italic}\ntest font-21.66 {Tk_PostscriptFontName procedure: exhaustive} -constraints {\n    win\n} -body {\n    set x [psfontname {{times new roman} 12 italic bold}]\n} -result {Times-BoldItalic}\n\n\ntest font-22.1 {Tk_TextWidth procedure} -setup {\n    destroy .t.l\n} -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t    -text \"0\" -font \"Courier -12\"\n    pack .t.l\n    set ax [winfo reqwidth .t.l]\n    expr {[font measure [.t.l cget -font] \"000\"] eq $ax*3}\n} -cleanup {\n    destroy .t.l\n} -result 1\n\n\ntest font-23.1 {Tk_UnderlineChars procedure} -setup {\n    destroy .t.t\n} -body {\n    text .t.t\n    .t.t insert 1.0 abc\\tdefg\n    .t.t tag config sel -underline 1\n    .t.t tag add sel 1.0 end\n    update\n} -cleanup {\n    destroy .t.t\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-24.*\n#\n\ndestroy .t.l\nlabel .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font \"Courier -12\"\npack .t.l\nupdate\nset ax [winfo reqwidth .t.l]\nset ay [winfo reqheight .t.l]\n\ntest font-24.1 {Tk_ComputeTextLayout: empty string} -body {\n    .t.l config -text \"\"\n} -result {}\ntest font-24.2 {Tk_ComputeTextLayout: simple string} -body {\n    .t.l config -text \"000\"\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq $ay}]\n} -result {1 1}\ntest font-24.3 {Tk_ComputeTextLayout: find special chars} -body {\n    .t.l config -text \"000\\n000\"\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n} -result {1 1}\ntest font-24.4 {Tk_ComputeTextLayout: calls Tk_MeasureChars} -body {\n    .t.l config -text \"000\\n000\"\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n} -result {1 1}\ntest font-24.5 {Tk_ComputeTextLayout: break line} -constraints !withXft -body {\n     # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n     # skip test if compiled with Xft.\n    .t.l config -text \"000\\t00000\" -wrap [expr {9 * $ax}]\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n} -cleanup {\n    .t.l config -wrap 0\n} -result {1 1}\ntest font-24.6 {Tk_ComputeTextLayout: normal ended on special char} -body {\n    .t.l config -text \"000\\n000\"\n} -result {}\ntest font-24.7 {Tk_ComputeTextLayout: special char was \\n} -body {\n    .t.l config -text \"000\\n0000\"\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n} -result {1 1}\ntest font-24.8 {Tk_ComputeTextLayout: special char was \\t} -body {\n    .t.l config -text \"000\\t00\"\n    update\n    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}] \\\n\t    [expr {[winfo reqheight .t.l] eq $ay}]\n} -result {1 1}\ntest font-24.9 {Tk_ComputeTextLayout: tab didn't cause break} -body {\n    set x {}\n    .t.l config -text \"000\\t000\"\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq $ay}]\n    .t.l config -text \"000\\t000\" -wrap [expr {100 * $ax}]\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq $ay}]\n    return $x\n} -cleanup {\n    .t.l config -wrap 0\n} -result {1 1 1 1}\ntest font-24.10 {Tk_ComputeTextLayout: tab caused break} -body {\n    set x {}\n    .t.l config -text \"000\\t\"\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq $ay}]\n    .t.l config -text \"000\\t00\" -wrap [expr {$ax * 6}]\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n    return $x\n} -cleanup {\n    .t.l config -wrap 0\n} -result {1 1 1 1}\ntest font-24.11 {Tk_ComputeTextLayout: absorb spaces at eol} -constraints !withXft -body {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    set x {}\n    .t.l config -text \"000            000\" -wrap [expr {$ax * 5}]\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n    .t.l config -text \"000            \"\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq $ay}]\n    return $x\n} -cleanup {\n    .t.l config -wrap 0\n} -result {1 1 1 1}\ntest font-24.12 {Tk_ComputeTextLayout: append non-printing spaces to chunk} -constraints !withXft -body {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    set x {}\n    .t.l config -text \"000            0000\" -wrap [expr {$ax * 5}]\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n    .t.l config -text \"000\\t00            0000\" -wrap [expr {$ax * 12}]\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n    return $x\n} -cleanup {\n    .t.l config -wrap 0\n} -result {1 1 1 1}\ntest font-24.13 {Tk_ComputeTextLayout: many lines -> realloc line array} -body {\n    .t.l config -text \"\\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\\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\\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\\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\\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    update\n    list [expr {[winfo reqwidth .t.l] eq 1}] \\\n\t    [expr {[winfo reqheight .t.l] eq [expr {$ay * 129}]}]\n} -result {1 1}\ntest font-24.14 {Tk_ComputeTextLayout: text ended with \\n} -body {\n    set x {}\n    .t.l config -text \"0000\"\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq $ay}]\n    .t.l config -text \"0000\\n\"\n    update\n    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]\n    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]\n    set x\n} -result {1 1 1 1}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t.l\n\ntest font-24.15 {Tk_ComputeTextLayout: justification} -setup {\n    set x {}\n    destroy .t.c\n    canvas .t.c -closeenough 0\n    .t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\n    pack .t.c\n    update\n} -body {\n    csetup \"000\\n00000\"\n    .t.c itemconfig text -just left\n    lappend x [.t.c index text @[expr {$ax*2}],0]\n    .t.c itemconfig text -just center\n    lappend x [.t.c index text @[expr {$ax*2}],0]\n    .t.c itemconfig text -just right\n    lappend x [.t.c index text @[expr {$ax*2}],0]\n    .t.c itemconfig text -just left\n    return $x\n} -cleanup {\n    destroy .t.c\n} -result {2 1 0}\n\n\ntest font-25.1 {Tk_FreeTextLayout procedure} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    .t.f config -text foo\n    .t.f config -text boo\n} -cleanup {\n    destroy .t.f\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-26.*\n#\ndestroy .t.c\ncanvas .t.c -closeenough 0\n.t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\npack .t.c\nupdate\n\ntest font-26.1 {Tk_DrawTextLayout procedure: auto-detect last char} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    .t.f config -text foo\n} -cleanup {\n    destroy .t.f\n} -result {}\ntest font-26.2 {Tk_DrawTextLayout procedure: multiple chunks} -body {\n    csetup \"000\\t00\\n000\"\n} -result {}\ntest font-26.3 {Tk_DrawTextLayout: draw subset of chunk: numDisplay <= 0} -body {\n    csetup \"000\\t00\"\n    .t.c select from text 3\n    .t.c select to text 5\n} -result {}\ntest font-26.4 {Tk_DrawTextLayout: draw subset of chunk: firstChar <= 0} -body {\n    csetup \"000\\t00\"\n    .t.c select from text 3\n    .t.c select to text 5\n} -result {}\ntest font-26.5 {Tk_DrawTextLayout: draw subset of chunk: firstChar > 0} -body {\n    csetup \"000\\t00\"\n    .t.c select from text 2\n    .t.c select to text 2\n} -result {}\ntest font-26.6 {Tk_DrawTextLayout: draw subset of chunk: lastChar < numChars} -body {\n    csetup \"000\\t00\"\n    .t.c select from text 4\n    .t.c select to text 4\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-27.*\n#\n\ndestroy .t.c\ndestroy .t.f\npack [label .t.f]\nupdate\n\ntest font-27.1 {Tk_UnderlineTextLayout procedure: no underline chosen} -body {\n    .t.f config -text \"foo\" -underline {}\n} -result {}\ntest font-27.2 {Tk_UnderlineTextLayout procedure: underline not visible} -body {\n    .t.f config -text \"000          00000\" -wrap [expr {$ax*7}] -under 10\n} -result {}\ntest font-27.3 {Tk_UnderlineTextLayout procedure: underline is visible} -body {\n    .t.f config -text \"000          00000\" -wrap [expr {$ax*7}] -under 5\n    .t.f config -wrap 0 -underline {}\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-28.*\n#\n\ndestroy .t.f\ndestroy .t.c\ncanvas .t.c -closeenough 0\n.t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\npack .t.c\nupdate\n\ntest font-28.1 {Tk_PointToChar procedure: above all lines} -body {\n    csetup \"000\"\n    .t.c index text @-1,0\n} -result 0\ntest font-28.2 {Tk_PointToChar procedure: no chars} -body {\n    # After fixing the following bug:\n    #\n    # In canvas text item, it was impossible to click to position the\n    # insertion point just after the last character.\n    #\n    # introduced another bug that Tk_PointToChar() would return a character\n    # index of 1 if TextLayout contained 0 characters.\n\n    csetup \"\"\n    .t.c index text @100,100\n} -result 0\ntest font-28.3 {Tk_PointToChar procedure: loop test} -body {\n    csetup \"000\\n000\\n000\\n000\"\n    .t.c index text @10000,0\n} -result 3\ntest font-28.4 {Tk_PointToChar procedure: intersect line} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c index text @0,$ay\n} -result 4\ntest font-28.5 {Tk_PointToChar procedure: to the left of all chunks} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c index text @-100,$ay\n} -result 4\ntest font-28.6 {Tk_PointToChar procedure: past any possible chunk} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c index text @100000,$ay\n} -result 7\ntest font-28.7 {Tk_PointToChar procedure: which chunk on this line} -body {\n    csetup \"000\\n000\\t000\\t000\\n000\"\n    .t.c index text @[expr {$ax*2}],$ay\n} -result 6\ntest font-28.8 {Tk_PointToChar procedure: which chunk on this line} -body {\n    csetup \"000\\n000\\t000\\t000\\n000\"\n    .t.c index text @[expr {$ax*10}],$ay\n} -result 10\ntest font-28.9 {Tk_PointToChar procedure: in special chunk} -body {\n    csetup \"000\\n000\\t000\\t000\\n000\"\n    .t.c index text @[expr {$ax*6}],$ay\n} -result 7\ntest font-28.10 {Tk_PointToChar procedure: past all chars in chunk} -body {\n    csetup \"000 0000000\"\n    .t.c itemconfig text -width [expr {$ax*5}]\n    set x [.t.c index text @[expr {$ax*5}],0]\n    .t.c itemconfig text -width 0\n    return $x\n} -result 3\ntest font-28.11 {Tk_PointToChar procedure: below all chunks} -body {\n    csetup \"000 0000000\"\n    .t.c index text @0,1000000\n} -result 11\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-29.*\n#\n\ndestroy .t.c\ndestroy .t.f\npack [label .t.f]\nupdate\n\ntest font-29.1 {Tk_CharBBox procedure: index < 0} -body {\n    .t.f config -text \"000\" -underline {}\n} -result {}\ntest font-29.2 {Tk_CharBBox procedure: loop} -body {\n    .t.f config -text \"000\\t000\\t000\\t000\" -underline 9\n} -result {}\ntest font-29.3 {Tk_CharBBox procedure: special char} -body {\n    .t.f config -text \"000\\t000\\t000\" -underline 7\n} -result {}\ntest font-29.4 {Tk_CharBBox procedure: normal char} -body {\n    .t.f config -text \"000\" -underline 1\n} -result {}\ntest font-29.5 {Tk_CharBBox procedure: right edge of bbox truncated} -body {\n    .t.f config -text \"0    0000\" -wrap [expr {$ax*4}] -under 2\n    .t.f config -wrap 0\n} -result {}\ntest font-29.6 {Tk_CharBBox procedure: bbox pegged to right edge} -body {\n    .t.f config -text \"0    0000\" -wrap [expr {$ax*4}] -under 3\n    .t.f config -wrap 0\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-30.*\n#\n\ndestroy .t.f\ndestroy .t.c\ncanvas .t.c -closeenough 0\n.t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\npack .t.c\nupdate\n\ntest font-30.1 {Tk_DistanceToTextLayout procedure: loop once} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x 0 -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result 0\ntest font-30.2 {Tk_DistanceToTextLayout procedure: loop multiple} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x $ax -y $ay\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result 5\ntest font-30.3 {Tk_DistanceToTextLayout procedure: loop to end} -body {\n    csetup \"000\\n0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x [expr {$ax*2}] -y $ay\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\ntest font-30.4 {Tk_DistanceToTextLayout procedure: hit a special char (tab)} -body {\n    csetup \"000\\t000\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x [expr {$ax*6}] -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result 3\ntest font-30.5 {Tk_DistanceToTextLayout procedure: ignore newline} -body {\n    csetup \"000\\n0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x [expr {$ax*2}] -y $ay\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\ntest font-30.6 {Tk_DistanceToTextLayout procedure: ignore spaces at eol} -constraints !withXft -body {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    csetup \"000\\n000      000000000\"\n    .t.c itemconfig text -width [expr {$ax*10}]\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x [expr {$ax*5}] -y $ay\n    .t.c itemconfig text -width 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n.t.c itemconfig text -justify center\n\ntest font-30.7 {Tk_DistanceToTextLayout procedure: on left side} -body {\n    csetup \"0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x 0 -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\ntest font-30.8 {Tk_DistanceToTextLayout procedure: on right side} -body {\n    csetup \"0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x [expr {$ax*2}] -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\ntest font-30.9 {Tk_DistanceToTextLayout procedure: inside line} -body {\n    csetup \"0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x $ax -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result 0\ntest font-30.10 {Tk_DistanceToTextLayout procedure: above line} -body {\n    csetup \"0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x 0 -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result {}\ntest font-30.11 {Tk_DistanceToTextLayout procedure: below line} -body {\n    csetup \"000\\n0\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x 0 -y $ay\n    return $x\n} -cleanup {\n\tbind all <Enter> {}\n} -result {}\ntest font-30.12 {Tk_DistanceToTextLayout procedure: in line} -body {\n    csetup \"0\\n000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x $ax -y $ay\n    return $x\n} -cleanup {\n\tbind all <Enter> {}\n} -result 3\n\n#\n# COMMON TEST SETUP\n#\n.t.c itemconfig text -justify left\n\ntest font-30.13 {Tk_DistanceToTextLayout procedure: exact hit} -body {\n    csetup \"000\"\n    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}\n    set x {}\n    event generate .t.c <Leave>\n    event generate .t.c <Enter> -x $ax -y 0\n    return $x\n} -cleanup {\n    bind all <Enter> {}\n} -result 1\n\n#\n# COMMON TEST SETUP\n#\n# For tests font-31.*\n#\ndestroy .t.c\ncanvas .t.c -closeenough 0\n.t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\npack .t.c\nupdate\n\ntest font-31.1 {Tk_IntersectTextLayout procedure: loop once} -body {\n    csetup \"000\\n000\\n000\"\n    .t.c find overlapping 0 0 0 0\n} -result [.t.c find withtag text]\ntest font-31.2 {Tk_IntersectTextLayout procedure: loop multiple} -body {\n    csetup \"000\\t000\\t000\"\n    .t.c find overlapping [expr {$ax*10}] 0 [expr {$ax*10}] 0\n} -result [.t.c find withtag text]\ntest font-31.3 {Tk_IntersectTextLayout procedure: loop to end} -body {\n    csetup \"0\\n000\"\n    .t.c find overlapping [expr {$ax*2}] 0 [expr {$ax*2}] 0\n} -result {}\ntest font-31.4 {Tk_IntersectTextLayout procedure: hit a special char (tab)} -body {\n    csetup \"000\\t000\"\n    .t.c find overlapping [expr {$ax*6}] 0 [expr {$ax*6}] 0\n} -result [.t.c find withtag text]\ntest font-31.5 {Tk_IntersectTextLayout procedure: ignore newlines} -body {\n    csetup \"000\\n0\\n000\"\n    .t.c find overlapping $ax $ay $ax $ay\n} -result {}\ntest font-31.6 {Tk_IntersectTextLayout procedure: ignore spaces at eol} -constraints !withXft -body {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    csetup \"000\\n000      000000000\"\n    .t.c itemconfig text -width [expr {$ax*10}]\n    set x [.t.c find overlapping [expr {$ax*5}] $ay [expr {$ax*5}] $ay]\n    .t.c itemconfig text -width 0\n    return $x\n} -result {}\ntest font-31.7 {TkIntersectAngledTextLayout procedure: bug [514ff64dd0]} -body {\n    csetup \"This is line one\\nand line two\\nand line three here\"\n    .t.c itemconfigure text -angle 90\n    # Coordinates of the rectangle to check can be hardcoded:\n    # The goal of this test is to check whether the overlap detection algorithm\n    # works when the rectangle is entirely included in a chunk of the text layout.\n    # The text has been rotated 90 degrees around it's upper left corner,\n    # so it's enough to check with a small rectangle with small negative y coords.\n    .t.c find overlapping 5 -7 7 -5\n} -result 1\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t.c\n\ntest font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {\n    destroy .t.c\n    canvas .t.c -closeenough 0\n    .t.c create text 0 0 -tags text -anchor nw -just left -font \"Courier -12\"\n    pack .t.c\n    update\n} -body {\n    # If there were a whole bunch of returns or tabs in a row, then the\n    # temporary buffer could overflow and write on the stack.\n    csetup \"qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\\n\"\n    .t.c itemconfig text -width 800\n    .t.c insert text end \"qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\\n\"\n    .t.c insert text end \"\\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\\n\\n\\n\\n\"\n    .t.c insert text end \"end\"\n    set x [.t.c postscript]\n    set i [string first \"(qwerty\" $x]\n    string range $x $i [expr {$i + 278}]\n} -cleanup {\n    destroy .t.c\n} -result {(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]\n[(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]\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[()]\n[()]\n[()]\n[()]\n[()]\n[(end)]\n}\n\n\ntest font-33.1 {Tk_TextWidth procedure} -body {\n} -result {}\n\n\ntest font-34.1 {ConfigAttributesObj procedure: arguments} -setup {\n    catch {font delete xyz}\n} -body {\n    # (Tcl_GetIndexFromObj() != TCL_OK)\n    font create xyz -xyz\n} -returnCodes {\n    error\n} -result {bad option \"-xyz\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\ntest font-34.2 {ConfigAttributesObj procedure: arguments} -setup {\n    catch {font delete xyz}\n} -body {\n    # (objc & 1)\n    font create xyz -family\n} -returnCodes error -result {value for \"-family\" option missing}\n\ntest font-34.3 {ConfigAttributesObj procedure: family} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -family xyz\n    lappend x [font config xyz -family]\n    font config xyz -family times\n    lappend x [font config xyz -family]\n} -cleanup {\n\tfont delete xyz\n} -result {xyz times}\ntest font-34.4 {ConfigAttributesObj procedure: size} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -size 20\n    lappend x [font config xyz -size]\n    font config xyz -size 40\n    lappend x [font config xyz -size]\n} -cleanup {\n    font delete xyz\n} -result {20 40}\ntest font-34.5 {ConfigAttributesObj procedure: weight} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -weight normal\n    lappend x [font config xyz -weight]\n    font config xyz -weight bold\n    lappend x [font config xyz -weight]\n} -cleanup {\n    font delete xyz\n} -result {normal bold}\ntest font-34.6 {ConfigAttributesObj procedure: slant} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -slant roman\n    lappend x [font config xyz -slant]\n    font config xyz -slant italic\n    lappend x [font config xyz -slant]\n} -cleanup {\n    font delete xyz\n} -result {roman italic}\ntest font-34.7 {ConfigAttributesObj procedure: underline} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -underline 0\n    lappend x [font config xyz -underline]\n    font config xyz -underline 1\n    lappend x [font config xyz -underline]\n} -cleanup {\n    font delete xyz\n} -result {0 1}\ntest font-34.8 {ConfigAttributesObj procedure: overstrike} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -overstrike 0\n    lappend x [font config xyz -overstrike]\n    font config xyz -overstrike 1\n    lappend x [font config xyz -overstrike]\n} -cleanup {\n    font delete xyz\n} -result {0 1}\n\ntest font-34.9 {ConfigAttributesObj procedure: size} -body {\n    font create xyz -size xyz\n} -returnCodes error -result {expected integer but got \"xyz\"}\ntest font-34.10 {ConfigAttributesObj procedure: weight} -body {\n    font create xyz -weight xyz\n} -returnCodes error -result {bad -weight value \"xyz\": must be normal, or bold}\ntest font-34.11 {ConfigAttributesObj procedure: slant} -body {\n    font create xyz -slant xyz\n} -returnCodes error -result {bad -slant value \"xyz\": must be roman, or italic}\ntest font-34.12 {ConfigAttributesObj procedure: underline} -body {\n    font create xyz -underline xyz\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\ntest font-34.13 {ConfigAttributesObj procedure: overstrike} -body {\n    font create xyz -overstrike xyz\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\n\n\ntest font-35.1 {GetAttributeInfoObj procedure: one attribute} -setup {\n    catch {font delete xyz}\n} -body {\n    # (objPtr != NULL)\n    font create xyz -family xyz\n    font config xyz -family\n} -cleanup {\n    font delete xyz\n} -result {xyz}\n\n\ntest font-36.1 {GetAttributeInfoObj procedure: unknown attribute} -setup {\n    catch {font delete xyz}\n} -body {\n    # (Tcl_GetIndexFromObj() != TCL_OK)\n    font create xyz\n    font config xyz -xyz\n} -cleanup {\n    font delete xyz\n} -returnCodes {\n    error\n} -result {bad option \"-xyz\": must be -family, -size, -weight, -slant, -underline, or -overstrike}\n\n\ntest font-37.1 {GetAttributeInfoObj procedure: all attributes} -setup {\n    catch {font delete xyz}\n} -body {\n    # not (objPtr != NULL)\n    font create xyz -family xyz\n    font config xyz\n} -cleanup {\n    font delete xyz\n} -result {-family xyz -size 0 -weight normal -slant roman -underline 0 -overstrike 0}\ntest font-37.2 {GetAttributeInfo procedure: family} -setup {\n    catch {font delete xyz}\n} -body {\n    font create xyz -family xyz\n    font config xyz -family\n} -cleanup {\n    font delete xyz\n} -result {xyz}\ntest font-37.3 {GetAttributeInfo procedure: size} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -size 20\n    font config xyz -size\n} -cleanup {\n    font delete xyz\n} -result 20\ntest font-37.4 {GetAttributeInfo procedure: weight} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -weight normal\n    font config xyz -weight\n} -cleanup {\n    font delete xyz\n} -result {normal}\ntest font-37.5 {GetAttributeInfo procedure: slant} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -slant italic\n    font config xyz -slant\n} -cleanup {\n    font delete xyz\n} -result {italic}\ntest font-37.6 {GetAttributeInfo procedure: underline} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -underline yes\n    font config xyz -underline\n} -cleanup {\n    font delete xyz\n} -result 1\ntest font-37.7 {GetAttributeInfo procedure: overstrike} -setup {\n    catch {font delete xyz}\n    set x {}\n} -body {\n    font create xyz -overstrike no\n    font config xyz -overstrike\n} -cleanup {\n    font delete xyz\n} -result 0\n\n\n# In tests below, one field is set to \"xyz\" so that font name doesn't\n# look like a native X font, so that ParseFontNameObj or TkParseXLFD will\n# be called.\n\ntest font-38.1 {ParseFontNameObj procedure: begins with -} -body {\n    lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1\n} -result [font actual {times 0} -family]\ntest font-38.2 {ParseFontNameObj procedure: begins with -*} -body {\n    lindex [font actual -*-times-xyz-*-*-*-*-*-*-*-*-*-*-*] 1\n} -result [font actual {times 0} -family]\ntest font-38.3 {ParseFontNameObj procedure: begins with -, doesn't look like list} -body {\n    lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1\n} -result [font actual {times 0} -family]\ntest font-38.4 {ParseFontNameObj procedure: begins with -, looks like list} -body {\n    lindex [font actual {-family times}] 1\n} -result [font actual {times 0} -family]\ntest font-38.5 {ParseFontNameObj procedure: begins with *} -body {\n    lindex [font actual *-times-xyz-*-*-*-*-*-*-*-*-*-*-*] 1\n} -result [font actual {times 0} -family]\ntest font-38.6 {ParseFontNameObj procedure: begins with *} -body {\n    font actual *-times-xyz -family\n} -result [font actual {times 0} -family]\ntest font-38.7 {ParseFontNameObj procedure: arguments} -body {\n    font actual \"\\{xyz\"\n} -returnCodes error -result \"font \\\"{xyz\\\" does not exist\"\ntest font-38.8 {ParseFontNameObj procedure: arguments} -body {\n    font actual \"\"\n} -returnCodes error -result {font \"\" does not exist}\ntest font-38.9 {ParseFontNameObj procedure: arguments} -body {\n    font actual {times 20 xyz xyz}\n} -returnCodes error -result {unknown font style \"xyz\"}\ntest font-38.10 {ParseFontNameObj procedure: arguments} -body {\n    font actual {times xyz xyz}\n} -returnCodes error -result {expected integer but got \"xyz\"}\ntest font-38.11 {ParseFontNameObj procedure: stylelist loop} -constraints {\n    unixOrWin haveBoldItalicUnderlineOverstrikeFont\n} -body {\n    lrange [font actual {times 12 bold italic overstrike underline}] 4 end\n} -result {-weight bold -slant italic -underline 1 -overstrike 1}\ntest font-38.12 {ParseFontNameObj procedure: stylelist error} -body {\n    font actual {times 12 bold xyz}\n} -returnCodes error -result {unknown font style \"xyz\"}\ntest font-38.13 \"ParseFontNameObj: options with hyphenated family: bug #2791352\" -body {\n    font actual {-family sans-serif -size 12 -weight bold -slant roman -underline 0 -overstrike 0}\n} -returnCodes ok -result [font actual {sans-serif 12 bold}]\ntest font-38.14 \"ParseFontNameObj: bug #2791352\" -body {\n    font actual {-invalidfont 8 bold}\n} -returnCodes error -match glob -result {bad option \"-invalidfont\": *}\n\n\ntest font-39.1 {NewChunk procedure: test realloc} -setup {\n    destroy .t.f\n    pack [label .t.f]\n    update\n} -body {\n    .t.f config -text \"xxx\\nxxx\\txxx\\nxxx\\t\\t\\t\"\n} -cleanup {\n\tdestroy .t.f\n} -result {}\n\n\ntest font-40.1 {TkFontParseXLFD procedure: initial dash} -body {\n    font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-* -family\n} -result [font actual {times 0} -family]\ntest font-40.2 {TkFontParseXLFD procedure: no initial dash} -body {\n    font actual *-times-*-*-*-*-*-*-*-*-*-*-*-xyz -family\n} -result [font actual {times 0} -family]\ntest font-40.3 {TkFontParseXLFD procedure: not enough fields} -body {\n    font actual -xyz-times-*-*-* -family\n} -result [font actual {times 0} -family]\ntest font-40.4 {TkFontParseXLFD procedure: all fields unspecified} -body {\n    lindex [font actual -xyz-*-*-*-*-*-*-*-*-*-*-*-*-*] 0\n} -result {-family}\ntest font-40.5 {TkFontParseXLFD procedure: all fields specified} -body {\n    lindex [font actual \\\n\t-foundry-times-weight-slant-setwidth-addstyle-10-10-10-10-spacing-avgwidth-registry-encoding] 1\n} -result [font actual {times 0} -family]\n\n\ntest font-41.1 {TkParseXLFD procedure: arguments} -body {\n    # XLFD with bad pointsize: fallback to some system font.\n    font actual -*-*-*-*-*-*-xyz-*-*-*-*-*-*-*\n    set x {}\n} -result {}\n\n\ntest font-42.1 {TkFontParseXLFD procedure: arguments} -body {\n    # XLFD with bad pixelsize: fallback to some system font.\n    font actual -*-*-*-*-*-*-*-xyz-*-*-*-*-*-*\n    set x {}\n} -result {}\ntest font-42.2 {TkFontParseXLFD procedure: pixelsize specified} -body {\n    font metrics -xyz-times-*-*-*-*-12-*-*-*-*-*-*-* -linespace\n    set x {}\n} -result {}\ntest font-42.3 {TkFontParseXLFD procedure: weird pixelsize specified} -body {\n    font metrics {-xyz-times-*-*-*-*-[ 12.0 0 12.0 0]-*-*-*-*-*-*-*} -linespace\n    set x {}\n} -result {}\ntest font-42.4 {TkFontParseXLFD procedure: pointsize specified} -body {\n    font metrics -xyz-times-*-*-*-*-*-120-*-*-*-*-*-* -linespace\n    set x {}\n} -result {}\ntest font-42.5 {TkFontParseXLFD procedure: weird pointsize specified} -body {\n    font metrics {-xyz-times-*-*-*-*-*-[ 12.0 0 12.0 0]-*-*-*-*-*-*} -linespace\n    set x {}\n} -result {}\n\n\ntest font-43.1 {FieldSpecified procedure: specified vs. non-specified} -body {\n    font actual -xyz--*-*-*-*-*-*-*-*-*-*-*-*\n    font actual -xyz-*-*-*-*-*-*-*-*-*-*-*-*-*\n    font actual -xyz-?-*-*-*-*-*-*-*-*-*-*-*-*\n    lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1\n} -result [font actual {times 0} -family]\n\n\ntest font-44.1 {TkFontGetPixels: size < 0}  -setup {\n    set oldscale [tk scaling]\n} -body {\n    # if this test failed, start the investigations by reading ticket [8162e9b7a9]\n    tk scaling 0.5\n    font actual {times -13} -size\n} -cleanup {\n    tk scaling $oldscale\n} -result 26\ntest font-44.2 {TkFontGetPoints: size >= 0} -setup {\n    set oldscale [tk scaling]\n} -body {\n    set oldSize [font actual {times 12} -size]\n    tk scaling 0.5\n    expr {[font actual {times 12} -size] == $oldSize}\n} -cleanup {\n    tk scaling $oldscale\n} -result 1\ntest font-44.3 {font create with display scaling not 100% - bug 8162e9b7a9} -body {\n    set font1 TkDefaultFont\n    set font2 [font create Font2 {*}[font actual $font1]]\n    expr {[font actual $font1 -size] == [font actual $font2 -size]}\n} -cleanup {\n    font delete $font2\n} -result 1\n\n\ntest font-45.1 {TkFontGetAliasList: no match} -body {\n    font actual {snarky 10} -family\n} -result [font actual {-size 10} -family]\ntest font-45.2 {TkFontGetAliasList: match} -constraints win -body {\n    font actual {times 10} -family\n} -result {times}\ntest font-45.3 {TkFontGetAliasList: match} -constraints haveTimesFamilyFont -body {\n    if {[font actual {{times new roman} 10} -family] eq \"Times New Roman\"} {\n\t# avoid test failure on systems that have a real \"times new roman\" font\n\tset res 1\n    } else {\n\tset res [expr {[font actual {{times new roman} 10} -family] eq \\\n\t\t       [font actual {times 10} -family]} ]\n    }\n} -result 1\n\n\ntest font-46.1 {font actual, with character, no option, no --} -body {\n    font actual {times 10} a\n} -match glob -result [list -family [font actual {times 10} -family] -size *\\\n\t\t -slant roman -underline 0 -overstrike 0]\n\ntest font-46.2 {font actual, with character introduced by --} -body {\n    font actual {times 10} -- -\n} -match glob -result [list -family [font actual {times 10} -family] -size *\\\n\t\t -slant roman -underline 0 -overstrike 0]\n\ntest font-46.3 {font actual, with character and option} -body {\n    font actual {times 10} -family a\n} -result [font actual {times 10} -family]\n\ntest font-46.4 {font actual, with character, option and --} -body {\n    font actual {times 10} -family -- -\n} -result [font actual {times 10} -family]\n\ntest font-46.5 {font actual, too many chars} -body {\n    font actual {times 10} 123456789012345678901234567890123456789012345678901\n} -returnCodes error -result {expected a single character but got \"1234567890123456789012345678901234567...\"}\n\ntest font-47.1 {Bug f214b8ad5b} -body {\n    interp create one\n    interp create two\n    load {} Tk one\n    load {} Tk two\n    one eval menu .menubar\n    two eval menu .menubar\n    interp delete one\n    interp delete two\n} -result {}\n\ntest font-47.2 {Bug 3049518 - Canvas} -body {\n    if {\"MyFont\" ni [font names]} {\n\tfont create MyFont -family \"Liberation Sans\" -size 13\n    }\n    set text Hello!\n    destroy .t.c\n    set c [canvas .t.c]\n    set textid [$c create text 20 20 -font MyFont -text $text -anchor nw]\n    set twidth [font measure MyFont $text]\n    set theight [font metrics MyFont -linespace]\n    set circid [$c create polygon \\\n\t15                    15 \\\n\t[expr {15 + $twidth}] 15 \\\n\t[expr {15 + $twidth}] [expr {15 + $theight}] \\\n\t15                    [expr {15 + $theight}] \\\n\t    -width 1 -joinstyle round -smooth true -fill {} -outline blue]\n    pack $c -fill both -expand 1 -side top\n    update\n\n    # Lambda test functions\n    set circle_text {{w user_data text circ} {\n\tif {[winfo class $w] ne \"Canvas\"} {\n\t    puts \"Wrong widget type: $w\"\n\t    return\n\t}\n\tif {$user_data ne \"FontChanged\"} {\n\t    return\n\t}\n\tlappend ::results called-$w\n\tlassign [$w bbox $text] x0 y0 x1 y1\n\tset offset 5\n\tset coord [lmap expr {\n\t\t\t      $x0-$offset $y0-$offset $x1+$offset $y0-$offset\n\t\t\t      $x1+$offset $y1+$offset $x0-$offset $y1+$offset\n\t\t\t  } {expr $expr}]\n\tif {[catch {$w coord $circ $coord} err]} {\n\t    puts Error:$err\n\t}\n    }}\n    set enclosed {{can id} {$can find enclosed {*}[$can bbox $id]}}\n\n    set results {}\n    apply $circle_text $c FontChanged $textid $circid\n    update\n    bind $c <<TkWorldChanged>> [list apply $circle_text %W %d $textid $circid]\n    update idletasks\n\n    # Begin test:\n    set results {}\n    lappend results [apply $enclosed $c $circid]\n    font configure MyFont -size 26\n    update  ; # services the \"TheWorldHasChanged\" event, queues \"TkWorldChanged\" events\n    update  ; # services the queued \"TkWorldChanged\" events\n    lappend results [apply $enclosed $c $circid]\n    font configure MyFont -size 9\n    update idletasks\n    update\n    lappend results [apply $enclosed $c $circid]\n    font configure MyFont -size 12\n    update idletasks\n    update\n    lappend results [apply $enclosed $c $circid]\n} -cleanup {\n    destroy $c\n    unset -nocomplain ::results\n} -result {{1 2} called-.t.c {1 2} called-.t.c {1 2} called-.t.c {1 2}}\n\ntest font-47.3 {Bug 3049518 - Label} -body {\n    if {\"MyFont\" ni [font names]} {\n\tfont create MyFont -family \"Liberation Sans\" -size 13\n    }\n    set text \"Label Test\"\n    destroy .t.l\n\n    set make-img {{size} {\n\tset img [image create photo -width $size -height $size]\n\t$img blank\n\tset max [expr {$size - 1}]\n\tfor {set x 0} {$x < $size} {incr x} {\n\t    $img put red -to $x $x\n\t    $img put black -to 0 $x\n\t    $img put black -to $x 0\n\t    $img put black -to $max $x\n\t    $img put black -to $x $max\n\t}\n\treturn $img\n    }}\n\n    set testWorldChanged {{w user_data} {\n\tglobal make-img\n\tif {$user_data ne \"FontChanged\"} {\n\t    return\n\t}\n\tif {![winfo exists $w] || [winfo class $w] ne \"Label\"} {\n\t    return\n\t}\n\tif {[$w cget -image] ne \"\"} {\n\t    image delete [$w cget -image]\n\t}\n\tset size [font metrics [$w cget -font] -linespace]\n\tset img [apply ${make-img} $size]\n\t$w configure -image $img\n    }}\n\n    set check {{w} {\n\tglobal results\n\tset f [$w cget -font]\n\tset i [$w cget -image]\n\tset fs [font metrics $f -linespace]\n\tset ish [image height $i]\n\tset isw [image width $i]\n\tlappend results [list [expr {$fs == $ish ? 1 : [list $fs $ish]}] [expr {$fs == $isw ? 1 : [list $fs $isw]}]]\n    }}\n\n    set size [font metrics MyFont -linespace]\n    set img [apply ${make-img} $size]\n    set l [label .t.l -compound left -image $img -text $text -font MyFont]\n    pack $l -side top -fill both -expand 1\n    update\n    bind $l <<TkWorldChanged>> [list apply $testWorldChanged %W %d]\n    set ::results {}\n\n    apply $check $l\n    font configure MyFont -size 26\n    update  ; # services the \"TheWorldHasChanged\" event, queues \"TkWorldChanged\" events\n    update  ; # services the queued \"TkWorldChanged\" events\n    apply $check $l\n    font configure MyFont -size 9\n    update idletasks\n    update\n    apply $check $l\n    font configure MyFont -size 13\n    update idletasks\n    update\n    apply $check $l\n    set results\n} -cleanup {\n    destroy $l\n    unset -nocomplain ::results\n} -result {{1 1} {1 1} {1 1} {1 1}}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/fontchooser.test",
    "content": "# Test the \"tk::fontchooser\" command\n#\n# Copyright © 2008 Pat Thoyts\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\nset applyFontCmd [list set testDialogFont]\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\n# The tk fontchooser call below autoloads fontchooser.tcl on platforms\n# that don't provide a native implementation of the font selection dialog.\n# This will make ::tk::fontchooser::Configure exist, and scriptImpl become true,\n# indicating use of the scripted implementation of the dialog. Platforms using\n# the native dialog do not define a ::tk::fontchooser::Configure proc.\ncatch {tk fontchooser}\ntestConstraint scriptImpl [llength [info proc ::tk::fontchooser::Configure]]\n\n#\n# TESTS\n#\n\ntest fontchooser-1.1 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser -z\n} -result {unknown or ambiguous subcommand \"-z\": must be configure, hide, or show}\n\ntest fontchooser-1.2 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -z\n} -match glob -result {bad option \"-z\":*}\n\ntest fontchooser-1.3 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -parent . -font\n} -result {value for \"-font\" missing}\n\ntest fontchooser-1.4 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -parent . -title\n} -result {value for \"-title\" missing}\n\ntest fontchooser-1.5 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -parent . -command\n} -result {value for \"-command\" missing}\n\ntest fontchooser-1.6 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -title . -parent\n} -result {value for \"-parent\" missing}\n\ntest fontchooser-1.7 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -parent abc\n} -result {bad window path name \"abc\"}\n\ntest fontchooser-1.8 {tk fontchooser: usage} -returnCodes ok -body {\n    tk fontchooser configure -visible\n} -result 0\n\ntest fontchooser-1.9 {tk fontchooser: usage} -returnCodes error -body {\n    tk fontchooser configure -visible 1\n} -match glob -result {*}\n\n#\n# The remaining tests in this file are only relevant for the script\n# implementation. They can be tested by sourcing the script file but\n# the Tk tests are run with -singleproc 1 and doing this affects the\n# result of later attempts to test the native implementations.\n#\n\ntest fontchooser-2.0 {fontchooser -title} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -title \"Hello\"\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tset x [wm title $testDialog]\n\tClick cancel\n    }\n    set x\n} -result {Hello}\n\ntest fontchooser-2.1 {fontchooser -title (cyrillic)} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure \\\n\t    -title \"Привет\"\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tset x [wm title $testDialog]\n\tClick cancel\n    }\n    set x\n} -result \"Привет\"\n\ntest fontchooser-3.0 {fontchooser -parent} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -parent .\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tset x [winfo parent $testDialog]\n\tClick cancel\n    }\n    set x\n} -result {.}\n\ntest fontchooser-3.1 {fontchooser -parent (invalid)} -constraints scriptImpl -body {\n    tk::fontchooser::Configure -parent junk\n} -returnCodes error -match glob -result {bad window path *}\n\ntest fontchooser-4.0 {fontchooser -font} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -command $applyFontCmd -font courier\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tClick cancel\n    }\n    set testDialogFont\n} -result {}\n\ntest fontchooser-4.1 {fontchooser -font} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -command $applyFontCmd -font courier\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tClick ok\n    }\n    expr {$testDialogFont ne {}}\n} -result 1\n\ntest fontchooser-4.2 {fontchooser -font} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -command $applyFontCmd -font TkDefaultFont\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tClick ok\n    }\n    expr {$testDialogFont ne {}}\n} -result 1\n\ntest fontchooser-4.3 {fontchooser -font} -constraints scriptImpl -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -command $applyFontCmd -font {times 14 bold}\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tClick ok\n    }\n    expr {$testDialogFont ne {}}\n} -result 1\n\ntest fontchooser-4.4 {fontchooser -font} -constraints {scriptImpl havePointsize14BoldFont} -body {\n    testDialog launch {\n\ttk::fontchooser::Configure -command $applyFontCmd -font {times 14 bold}\n\ttk::fontchooser::Show\n    }\n    testDialog onDisplay {\n\tClick ok\n    }\n    lrange $testDialogFont 1 end\n} -result {14 bold}\n\ntest fontchooser-5.1 {fontchooser multiple configure} -constraints {scriptImpl} -body {\n    tk fontchooser configure -title TestTitle -command foo\n    tk fontchooser configure -command bar\n    tk fontchooser configure -title\n} -result {TestTitle}\n\n#\n# TESTFILE CLEANUP\n#\n\nunset applyFontCmd\ntestutils forget dialog\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# indent-tabs-mode: nil\n# End:\n"
  },
  {
    "path": "tests/frame.test",
    "content": "# This file is a Tcl script to test out the \"frame\", \"labelframe\" and\n# \"toplevel\" commands of Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import colors\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# optnames --\n#\n# Returns the option names out of a list of option details.\n#\n# Arguments:\n# options -\t\tThe option detail list.\nproc optnames {options} {\n    lsort [lmap desc $options {lindex $desc 0}]\n}\n\n# uniq --\n#\n# Returns the unique items of a list in the order they first appear.\n#\n# Arguments:\n# list -\t\tThe list to uniq-ify.\nproc uniq {list} {\n    set d {}\n    foreach item $list {\n\tdict set d $item {}\n    }\n    return [dict keys $d]\n}\n\n#\n# TESTS\n#\n\ntest frame-1.1 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -class NewFrame\n    .f configure -class\n} -cleanup {\n    deleteWindows\n} -result {-class class Class Frame NewFrame}\ntest frame-1.2 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -class NewFrame\n    .f configure -class Different\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -class option after widget is created}\ntest frame-1.3 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -colormap new\n    .f configure -colormap\n} -cleanup {\n    deleteWindows\n} -result {-colormap colormap Colormap {} new}\ntest frame-1.4 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -colormap new\n    .f configure -colormap .\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -colormap option after widget is created}\ntest frame-1.5 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -visual default\n    .f configure -visual\n} -cleanup {\n    deleteWindows\n} -result {-visual visual Visual {} default}\ntest frame-1.6 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -visual default\n    .f configure -visual best\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -visual option after widget is created}\ntest frame-1.7 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -screen bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-screen\"}\ntest frame-1.8 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -container true\n} -cleanup {\n    deleteWindows\n} -result {.f}\ntest frame-1.9 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -container true\n    .f configure -container\n} -cleanup {\n    deleteWindows\n} -result {-container container Container 0 1}\ntest frame-1.10 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f -container bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected boolean value but got \"bogus\"}\ntest frame-1.11 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    frame .f\n    .f configure -container 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -container option after widget is created}\ntest frame-1.12 {frame configuration options} -setup {\n    deleteWindows\n} -body {\n    # Make sure all options can be set to the default value\n    frame .f\n    set opts {}\n    foreach opt [.f configure] {\n\tif {[llength $opt] == 5} {\n\t    lappend opts [lindex $opt 0] [lindex $opt 4]\n\t}\n    }\n    frame .g {*}$opts\n} -cleanup {\n    destroy .f .g\n    deleteWindows\n} -result .g\n\n#\n# COMMON TEST SETUP\n#\ndestroy .f\nframe .f\n\ntest frame-1.13 {frame configuration options} -body {\n    .f configure -background #ff0000\n    lindex [.f configure -background] 4\n} -cleanup {\n    .f configure -background [lindex [.f configure -background] 3]\n} -result \"#ff0000\"\ntest frame-1.14 {frame configuration options} -body {\n    .f configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-1.15 {frame configuration options} -body {\n    .f configure -bd 4\n    lindex [.f configure -bd] 4\n} -cleanup {\n    .f configure -bd [lindex [.f configure -bd] 3]\n} -result 4\ntest frame-1.16 {frame configuration options} -body {\n    .f configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-1.17 {frame configuration options} -body {\n    .f configure -bg #00ff00\n    lindex [.f configure -bg] 4\n} -cleanup {\n    .f configure -bg [lindex [.f configure -bg] 3]\n} -result \"#00ff00\"\ntest frame-1.18 {frame configuration options} -body {\n    .f configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-1.19 {frame configuration options} -body {\n    .f configure -borderwidth 1.3\n    lindex [.f configure -borderwidth] 4\n} -cleanup {\n    .f configure -borderwidth [lindex [.f configure -borderwidth] 3]\n} -result 1.3\ntest frame-1.20 {frame configuration options} -body {\n    .f configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-1.21 {frame configuration options} -body {\n    .f configure -cursor arrow\n    lindex [.f configure -cursor] 4\n} -cleanup {\n    .f configure -cursor [lindex [.f configure -cursor] 3]\n} -result {arrow}\ntest frame-1.22 {frame configuration options} -body {\n    .f configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest frame-1.23 {frame configuration options} -body {\n    .f configure -height 100\n    lindex [.f configure -height] 4\n} -cleanup {\n    .f configure -height [lindex [.f configure -height] 3]\n} -result 100\ntest frame-1.24 {frame configuration options} -body {\n    .f configure -height not_a_number\n} -returnCodes error -result {expected screen distance but got \"not_a_number\"}\ntest frame-1.25 {frame configuration options} -body {\n    .f configure -highlightbackground #112233\n    lindex [.f configure -highlightbackground] 4\n} -cleanup {\n    .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]\n} -result \"#112233\"\ntest frame-1.26 {frame configuration options} -body {\n    .f configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest frame-1.27 {frame configuration options} -body {\n    .f configure -highlightcolor #123456\n    lindex [.f configure -highlightcolor] 4\n} -cleanup {\n    .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]\n} -result \"#123456\"\ntest frame-1.28 {frame configuration options} -body {\n    .f configure -highlightcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-1.29 {frame configuration options} -body {\n    .f configure -highlightthickness 6\n    lindex [.f configure -highlightthickness] 4\n} -cleanup {\n    .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]\n} -result 6\ntest frame-1.30 {frame configuration options} -body {\n    .f configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-1.31 {frame configuration options} -body {\n    .f configure -padx 3\n    lindex [.f configure -padx] 4\n} -cleanup {\n    .f configure -padx [lindex [.f configure -padx] 3]\n} -result 3\ntest frame-1.32 {frame configuration options} -body {\n    .f configure -padx badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-1.33 {frame configuration options} -body {\n    .f configure -pady 4\n    lindex [.f configure -pady] 4\n} -cleanup {\n    .f configure -pady [lindex [.f configure -pady] 3]\n} -result 4\ntest frame-1.34 {frame configuration options} -body {\n    .f configure -pady badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-1.35 {frame configuration options} -body {\n    .f configure -relief ridge\n    lindex [.f configure -relief] 4\n} -cleanup {\n    .f configure -relief [lindex [.f configure -relief] 3]\n} -result {ridge}\ntest frame-1.36 {frame configuration options} -returnCodes error -body {\n    .f configure -relief badValue\n} -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\ntest frame-1.37 {frame configuration options} -body {\n    .f configure -takefocus {any string}\n    lindex [.f configure -takefocus] 4\n} -cleanup {\n    .f configure -takefocus [lindex [.f configure -takefocus] 3]\n} -result {any string}\ntest frame-1.38 {frame configuration options} -body {\n    .f configure -width 32\n    lindex [.f configure -width] 4\n} -cleanup {\n    .f configure -width [lindex [.f configure -width] 3]\n} -result 32\ntest frame-1.39 {frame configuration options} -body {\n    .f configure -width badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .f\n\ntest frame-2.1 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -class NewClass\n    wm geometry .t +0+0\n    .t configure -class\n} -cleanup {\n    deleteWindows\n} -result {-class class Class Toplevel NewClass}\ntest frame-2.2 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -class NewClass\n    wm geometry .t +0+0\n    .t configure -class Another\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -class option after widget is created}\ntest frame-2.3 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -colormap new\n    wm geometry .t +0+0\n    .t configure -colormap\n} -cleanup {\n    deleteWindows\n} -result {-colormap colormap Colormap {} new}\ntest frame-2.4 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -colormap new\n    wm geometry .t +0+0\n    .t configure -colormap .\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -colormap option after widget is created}\ntest frame-2.5 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    .t configure -container 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -container option after widget is created}\ntest frame-2.6 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    catch {.t configure -container 1}\n    .t configure -container\n} -cleanup {\n    deleteWindows\n} -result {-container container Container 0 0}\ntest frame-2.7 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -colormap bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad window path name \"bogus\"}\ntest frame-2.8 {toplevel configuration options} -constraints win -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    .t configure -use 0x44022\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {window \"0x44022\" does not exist}\ntest frame-2.9 {toplevel configuration options} -constraints win -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    catch {.t configure -use 0x44022}\n    .t configure -use\n} -cleanup {\n    deleteWindows\n} -result {-use use Use {} {}}\ntest frame-2.10 {toplevel configuration options} -constraints macOrUnix -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    .t configure -use 0x44022\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {can't modify -use option after widget is created}\ntest frame-2.11 {toplevel configuration options} -constraints macOrUnix -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100\n    wm geometry .t +0+0\n    catch {.t configure -use 0x44022}\n    .t configure -use\n} -cleanup {\n    deleteWindows\n} -result {-use use Use {} {}}\ntest frame-2.12 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -visual default\n    wm geometry .t +0+0\n    .t configure -visual\n} -cleanup {\n    deleteWindows\n} -result {-visual visual Visual {} default}\ntest frame-2.13 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -visual default\n    wm geometry .t +0+0\n    .t configure -visual best\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -visual option after widget is created}\ntest frame-2.14 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -visual who_knows?\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {unknown or ambiguous visual name \"who_knows?\": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}\ntest frame-2.15 {toplevel configuration options} -constraints haveDISPLAY -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -screen $env(DISPLAY)\n    wm geometry .t +0+0\n    .t configure -screen\n} -cleanup {\n    deleteWindows\n} -result [expr {[tcltest::testConstraint haveDISPLAY]?[list -screen screen Screen {} $env(DISPLAY)]:\"\"}]\ntest frame-2.16 {toplevel configuration options} -constraints haveDISPLAY -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -screen $env(DISPLAY)\n    wm geometry .t +0+0\n    .t configure -screen another\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -screen option after widget is created}\ntest frame-2.17 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 200 -height 100 -screen bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {couldn't connect to display \"bogus\"}\ntest frame-2.18 {toplevel configuration options} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -container 1 -width 300 -height 120\n    wm geometry .t +0+0\n    toplevel .x -container 1 -use [winfo id .t]\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {windows cannot have both the -use and the -container option set}\ntest frame-2.19 {toplevel configuration options} -setup {\n    deleteWindows\n    set opts {}\n} -body {\n    # Make sure all options can be set to the default value\n    toplevel .f\n    foreach opt [.f configure] {\n\tif {[llength $opt] == 5} {\n\t    lappend opts [lindex $opt 0] [lindex $opt 4]\n\t}\n    }\n    toplevel .g {*}$opts\n} -cleanup {\n    destroy .f .g\n    deleteWindows\n} -result .g\n\n#\n# COMMON TEST SETUP\n#\ndestroy .t\ntoplevel .t -width 300 -height 150\nwm geometry .t +0+0\nupdate\n\ntest frame-2.20 {toplevel configuration options} -body {\n    .t configure -background #ff0000\n    lindex [.t configure -background] 4\n} -result \"#ff0000\"\ntest frame-2.21 {toplevel configuration options} -body {\n    .t configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-2.22 {toplevel configuration options} -body {\n    .t configure -bd 4\n    lindex [.t configure -bd] 4\n} -result 4\ntest frame-2.23 {toplevel configuration options} -body {\n    .t configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-2.24 {toplevel configuration options} -body {\n    .t configure -bg #00ff00\n    lindex [.t configure -bg] 4\n} -result \"#00ff00\"\ntest frame-2.25 {toplevel configuration options} -body {\n    .t configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-2.26 {toplevel configuration options} -body {\n    .t configure -borderwidth 1.3\n    lindex [.t configure -borderwidth] 4\n} -result 1.3\ntest frame-2.27 {toplevel configuration options} -body {\n    .t configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-2.28 {toplevel configuration options} -body {\n    .t configure -cursor arrow\n    lindex [.t configure -cursor] 4\n} -result {arrow}\ntest frame-2.29 {toplevel configuration options} -body {\n    .t configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest frame-2.30 {toplevel configuration options} -body {\n    .t configure -height 100\n    lindex [.t configure -height] 4\n} -result 100\ntest frame-2.31 {toplevel configuration options} -body {\n    .t configure -height not_a_number\n} -returnCodes error -result {expected screen distance but got \"not_a_number\"}\ntest frame-2.32 {toplevel configuration options} -body {\n    .t configure -highlightcolor #123456\n    lindex [.t configure -highlightcolor] 4\n} -result \"#123456\"\ntest frame-2.33 {toplevel configuration options} -body {\n    .t configure -highlightcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-2.34 {toplevel configuration options} -body {\n    .t configure -highlightthickness 3\n    lindex [.t configure -highlightthickness] 4\n} -result 3\ntest frame-2.35 {toplevel configuration options} -body {\n    .t configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-2.36 {toplevel configuration options} -body {\n    .t configure -padx 3\n    lindex [.t configure -padx] 4\n} -result 3\ntest frame-2.37 {toplevel configuration options} -body {\n    .t configure -padx badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-2.38 {toplevel configuration options} -body {\n    .t configure -pady 4\n    lindex [.t configure -pady] 4\n} -result 4\ntest frame-2.39 {toplevel configuration options} -body {\n    .t configure -pady badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-2.40 {toplevel configuration options} -body {\n    .t configure -relief ridge\n    lindex [.t configure -relief] 4\n} -result {ridge}\ntest frame-2.41 {toplevel configuration options} -returnCodes error -body {\n    .t configure -relief badValue\n} -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\ntest frame-2.42 {toplevel configuration options} -body {\n    .t configure -width 32\n    lindex [.t configure -width] 4\n} -result 32\ntest frame-2.43 {toplevel configuration options} -body {\n    .t configure -width badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\ntest frame-3.1 {TkCreateFrame procedure} -returnCodes error -body {\n    frame\n} -result {wrong # args: should be \"frame pathName ?-option value ...?\"}\ntest frame-3.2 {TkCreateFrame procedure} -setup {\n    deleteWindows\n    frame .f\n} -body {\n    .f configure -class\n} -cleanup {\n    deleteWindows\n} -result {-class class Class Frame Frame}\ntest frame-3.3 {TkCreateFrame procedure} -setup {\n    deleteWindows\n    toplevel .t\n    wm geometry .t +0+0\n} -body {\n    .t configure -class\n} -cleanup {\n    deleteWindows\n} -result {-class class Class Toplevel Toplevel}\ntest frame-3.4 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 350 -class NewClass -bg black -visual default -height 90\n    wm geometry .t +0+0\n    update\n    list [lindex [.t configure -width] 4] \\\n\t    [lindex [.t configure -background] 4] \\\n\t    [lindex [.t configure -height] 4]\n} -cleanup {\n    deleteWindows\n} -result {350 black 90}\n# Be sure that the -class, -colormap, and -visual options are processed\n# before configuring the widget.\ntest frame-3.5 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    option add *NewFrame.background #123456\n    frame .f -class NewFrame\n    lindex [.f configure -background] 4\n} -cleanup {\n    deleteWindows\n    option clear\n} -result {#123456}\ntest frame-3.7 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    option add *NewFrame.background #332211\n    option add *f.class NewFrame\n    frame .f\n    list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]\n} -cleanup {\n    deleteWindows\n    option clear\n} -result {NewFrame #332211}\ntest frame-3.8 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    option add *Silly.background #122334\n    option add *f.Class Silly\n    frame .f\n    list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]\n} -cleanup {\n    deleteWindows\n    option clear\n} -result {Silly #122334}\ntest frame-3.9 {TkCreateFrame procedure, -use option} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -container 1 -width 300 -height 120\n    wm geometry .t +0+0\n    toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green\n    tkwait visibility .x\n    list [expr {[winfo rootx .x] - [winfo rootx .t]}] \\\n\t    [expr {[winfo rooty .x] - [winfo rooty .t]}] \\\n\t    [winfo width .t] [winfo height .t]\n} -cleanup {\n    deleteWindows\n} -result {0 0 140 300}\ntest frame-3.10 {TkCreateFrame procedure, -use option} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -container 1 -width 300 -height 120\n    wm geometry .t +0+0\n    update\n    option add *x.use [winfo id .t]\n    toplevel .x -width 140 -height 300 -bg green\n    tkwait visibility .x\n    update\n    list [expr {[winfo rootx .x] - [winfo rootx .t]}] \\\n\t    [expr {[winfo rooty .x] - [winfo rooty .t]}] \\\n\t    [winfo width .t] [winfo height .t]\n} -cleanup {\n    destroy .t\n    option clear\n} -result {0 0 140 300}\n\n#\n# COMMON TEST SETUP\n#\n\n# The tests below require specific display characteristics (i.e. that they are\n# run on a pseudocolor display of depth 8).  Even so, they are non-portable:\n# some machines don't seem to ever run out of colors.\nif {[testConstraint defaultPseudocolor8]} {\n    eatColors .t1\n}\n\ntest frame-3.11 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200 -bg #475601\n    wm geometry .t +0+0\n    update\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 0\ntest frame-3.12 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200 -bg #475601 -colormap new\n    wm geometry .t +0+0\n    update\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest frame-3.13 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    option add *t.class Toplevel2\n    option add *Toplevel2.colormap new\n    toplevel .t -width 300 -height 200 -bg #475601\n    wm geometry .t +0+0\n    update\n    option clear\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest frame-3.14 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    option add *t.class Toplevel3\n    option add *Toplevel3.Colormap new\n    toplevel .t -width 300 -height 200 -bg #475601 -colormap new\n    wm geometry .t +0+0\n    update\n    option clear\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest frame-3.15 {TkCreateFrame procedure, -use and -colormap} -constraints {\n    defaultPseudocolor8 unix nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -container 1 -width 300 -height 120\n    wm geometry .t +0+0\n    toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green -colormap new\n    tkwait visibility .x\n    list [colorsFree .t] [colorsFree .x]\n} -cleanup {\n    destroy .t\n} -result {0 1}\ntest frame-3.16 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200 -bg #475601 -visual default\n    wm geometry .t +0+0\n    update\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 0\ntest frame-3.17 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200 -bg #475601 -visual default \\\n\t    -colormap new\n    wm geometry .t +0+0\n    update\n    colorsFree .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest frame-3.18 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 haveGrayscale8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343\n    wm geometry .t +0+0\n    update\n    colorsFree .t 131 131 131\n} -cleanup {\n    destroy .t\n} -result 1\ntest frame-3.19 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 haveGrayscale8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    option add *t.class T4\n    option add *T4.visual {grayscale 8}\n    toplevel .t -width 300 -height 200 -bg #434343\n    wm geometry .t +0+0\n    update\n    option clear\n    list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]\n} -cleanup {\n    destroy .t\n} -result {1 {grayscale 8}}\ntest frame-3.20 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 haveGrayscale8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    option add *t.class T5\n    option add *T5.Visual {grayscale 8}\n    toplevel .t -width 300 -height 200 -bg #434343\n    wm geometry .t +0+0\n    update\n    option clear\n    list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]\n} -cleanup {\n    destroy .t\n} -result {1 {grayscale 8}}\ntest frame-3.21 {TkCreateFrame procedure} -constraints {\n    defaultPseudocolor8 haveGrayscale8 nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343\n    wm geometry .t +0+0\n    update\n    colorsFree .t 131 131 131\n} -cleanup {\n    destroy .t\n} -result 1\n\n#\n# COMMON TEST CLEANUP\n#\nif {[testConstraint defaultPseudocolor8]} {\n    destroy .t1\n}\n\ntest frame-3.22 {TkCreateFrame procedure, default dimensions} -setup {\n    deleteWindows\n} -body {\n    toplevel .t\n    wm geometry .t +0+0\n    update\n    set result \"[winfo reqwidth .t] [winfo reqheight .t]\"\n    frame .t.f -bg red\n    pack .t.f\n    update\n    lappend result [winfo reqwidth .t.f] [winfo reqheight .t.f]\n} -cleanup {\n    deleteWindows\n} -result {200 200 1 1}\ntest frame-3.23 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    frame .f -gorp glob\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest frame-3.24 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 300 -height 200 -colormap new -bogus option\n    wm geometry .t +0+0\n} -returnCodes error -result {unknown option \"-bogus\"}\n\ntest frame-4.1 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    catch {frame .f -gorp glob}\n    winfo exists .f\n} -result 0\ntest frame-4.2 {TkCreateFrame procedure} -setup {\n    deleteWindows\n} -body {\n    list [frame .f -width 200 -height 100] [winfo exists .f]\n} -cleanup {\n    deleteWindows\n} -result {.f 1}\n\n#\n# COMMON TEST SETUP\n#\nframe .f -highlightcolor black\n\ntest frame-5.1 {FrameWidgetCommand procedure} -body {\n    .f\n} -returnCodes error -result {wrong # args: should be \".f option ?arg ...?\"}\ntest frame-5.2 {FrameWidgetCommand procedure, cget option} -body {\n    .f cget\n} -returnCodes error -result {wrong # args: should be \".f cget option\"}\ntest frame-5.3 {FrameWidgetCommand procedure, cget option} -body {\n    .f cget a b\n} -returnCodes error -result {wrong # args: should be \".f cget option\"}\ntest frame-5.4 {FrameWidgetCommand procedure, cget option} -body {\n    .f cget -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest frame-5.5 {FrameWidgetCommand procedure, cget option} -body {\n    .f cget -highlightcolor\n} -result {black}\ntest frame-5.6 {FrameWidgetCommand procedure, cget option} -body {\n    .f cget -screen\n} -returnCodes error -result {unknown option \"-screen\"}\ntest frame-5.7 {FrameWidgetCommand procedure, cget option} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    .t cget -screen\n} -cleanup {\n    destroy .t\n} -returnCodes ok -match glob -result *\ntest frame-5.8 {FrameWidgetCommand procedure, configure option} -body {\n    optnames [.f configure]\n} -result {-background -backgroundimage -bd -bg -bgimg -borderwidth -class -colormap -container -cursor -height -highlightbackground -highlightcolor -highlightthickness -padx -pady -relief -takefocus -tile -visual -width}\ntest frame-5.9 {FrameWidgetCommand procedure, configure option} -body {\n    .f configure -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest frame-5.10 {FrameWidgetCommand procedure, configure option} -body {\n    .f configure -gorp bogus\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest frame-5.11 {FrameWidgetCommand procedure, configure option} -body {\n    .f configure -width 200 -height\n} -returnCodes error -result {value for \"-height\" missing}\ntest frame-5.12 {FrameWidgetCommand procedure} -body {\n    .f swizzle\n} -returnCodes error -result {bad option \"swizzle\": must be cget or configure}\ntest frame-5.13 {FrameWidgetCommand procedure, configure option} -body {\n    optnames [. configure]\n} -result {-background -backgroundimage -bd -bg -bgimg -borderwidth -class -colormap -container -cursor -height -highlightbackground -highlightcolor -highlightthickness -menu -padx -pady -relief -screen -takefocus -tile -use -visual -width}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .f\n\ntest frame-6.1 {ConfigureFrame procedure} -setup {\n    deleteWindows\n} -body {\n    frame .f -width 150\n    list [winfo reqwidth .f] [winfo reqheight .f]\n} -cleanup {\n    deleteWindows\n} -result {150 1}\ntest frame-6.2 {ConfigureFrame procedure} -setup {\n    deleteWindows\n} -body {\n    frame .f -height 97\n    list [winfo reqwidth .f] [winfo reqheight .f]\n} -cleanup {\n    deleteWindows\n} -result {1 97}\ntest frame-6.3 {ConfigureFrame procedure} -setup {\n    deleteWindows\n} -body {\n    frame .f\n    set result {}\n    lappend result [winfo reqwidth .f] [winfo reqheight .f]\n    .f configure -width 100 -height 180\n    lappend result [winfo reqwidth .f] [winfo reqheight .f]\n    .f configure -width 0 -height 0\n    lappend result [winfo reqwidth .f] [winfo reqheight .f]\n} -cleanup {\n    deleteWindows\n} -result {1 1 100 180 100 180}\n\ntest frame-7.1 {FrameEventProc procedure} -setup {\n    deleteWindows\n} -body {\n    frame .frame2\n    set result [info commands .frame2]\n    destroy .frame2\n    lappend result [info commands .frame2]\n} -result {.frame2 {}}\ntest frame-7.2 {FrameEventProc procedure} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    frame .f1 -bg #543210\n    rename .f1 .f2\n    lappend x [winfo children .]\n    lappend x [.f2 cget -bg]\n    destroy .f1\n    lappend x [info command .f*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {.f1 #543210 {} {}}\n\ntest frame-8.1 {FrameCmdDeletedProc procedure} -setup {\n    deleteWindows\n} -body {\n    frame .f1\n    rename .f1 {}\n    list [info command .f*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest frame-8.2 {FrameCmdDeletedProc procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .f1 -menu .m\n    wm geometry .f1 +0+0\n    update\n    rename .f1 {}\n    update\n    list [info command .f*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n#\n# This one fails with the dash-patch!!!! Still don't know why  :-(\n#\n#test frame-8.3 {FrameCmdDeletedProc procedure} -setup {\n#    deleteWindows\n#} -body {\n#    toplevel .f1 -menu .m\n#    wm geometry .f1 +0+0\n#    menu .m\n#    update\n#    rename .f1 {}\n#    update\n#    list [info command .f*] [winfo children .]\n#} -cleanup {\n#    deleteWindows\n#} -result {{} .m}\n\ntest frame-9.1 {MapFrame procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 100 -height 400\n    wm geometry .t +0+0\n    set result [winfo ismapped .t]\n    update\n    lappend result [winfo ismapped .t]\n} -cleanup {\n    deleteWindows\n} -result {0 1}\ntest frame-9.2 {MapFrame procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -width 100 -height 400\n    wm geometry .t +0+0\n    destroy .t\n    update\n    winfo exists .t\n} -result 0\ntest frame-9.3 {MapFrame procedure, window deleted while mapping} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -width 200 -height 200\n    wm geometry .t2 +0+0\n    tkwait visibility .t2\n    toplevel .t -width 100 -height 400\n    wm geometry .t +0+0\n    frame .t2.f -width 50 -height 50\n    bind .t2.f <Configure> {destroy .t}\n    pack .t2.f -side top\n    update\n    winfo exists .t\n} -cleanup {\n    deleteWindows\n} -result 0\n\ntest frame-10.1 {frame widget vs hidden commands} -setup {\n    deleteWindows\n} -body {\n    frame .t\n    interp hide {} .t\n    destroy .t\n    list [winfo children .] [lsort [interp hidden]]\n} -result [list {} [lsort [interp hidden]]]\n\ntest frame-11.1 {TkInstallFrameMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m1.system\n    menu .m1.system -tearoff 0\n    .m1.system add command -label foo\n    toplevel .t -menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.t}\ntest frame-11.2 {TkInstallFrameMenu - frame renamed} -setup {\n    deleteWindows\n    catch {rename foo {}}\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m1.system\n    menu .m1.system -tearoff 0\n    .m1.system add command -label foo\n    toplevel .t\n    rename .t foo\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest frame-12.1 {FrameWorldChanged procedure} -setup {\n    deleteWindows\n} -body {\n    # Test -bd -padx and -pady\n    frame .f -borderwidth 2 -padx 3 -pady 4\n    place .f -x 0 -y 0 -width 40 -height 40\n    pack [frame .f.f] -fill both -expand 1\n    update\n    list [winfo x .f.f] [winfo y .f.f] [winfo width .f.f] [winfo height .f.f]\n} -cleanup {\n    deleteWindows\n} -result {5 6 30 28}\ntest frame-12.2 {FrameWorldChanged procedure} -setup {\n    deleteWindows\n} -body {\n    # Test all -labelanchor positions\n    set font {helvetica 12}\n    labelframe .f -highlightthickness 1 -bd 3 -padx 1 -pady 2 -font $font \\\n\t    -text \"Mupp\"\n    set fh [expr {max([font metrics $font -linespace] + 2 - 3, 0)}]\n    set fw [expr {max([font measure $font \"Mupp\"] + 2 - 3, 0)}]\n    place .f -x 0 -y 0 -width 100 -height 100\n    pack [frame .f.f] -fill both -expand 1\n    set result {}\n    foreach lp {nw n ne en e es se s sw ws w wn} {\n\t.f configure -labelanchor $lp\n\tupdate\n\tset expx 5\n\tset expy 6\n\tset expw 90\n\tset exph 88\n\tswitch -glob $lp {\n\t    n* {incr expy $fh ; incr exph -$fh}\n\t    s* {incr exph -$fh}\n\t    w* {incr expx $fw ; incr expw -$fw}\n\t    e* {incr expw -$fw}\n\t}\n\tlappend result [expr {\n\t    [winfo x .f.f] == $expx && [winfo y .f.f] == $expy &&\n\t    [winfo width .f.f] == $expw && [winfo height .f.f] == $exph\n\t}]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {1 1 1 1 1 1 1 1 1 1 1 1}\ntest frame-12.3 {FrameWorldChanged procedure} -setup {\n    deleteWindows\n} -body {\n    # Check reaction on font change\n    font create myfont -family courier -size 10\n    labelframe .f -font myfont -text Mupp\n    place .f -x 0 -y 0 -width 40 -height 40\n    pack [frame .f.f] -fill both -expand 1\n    update\n    set h1 [font metrics myfont -linespace]\n    set y1 [winfo y .f.f]\n    font configure myfont -size 20\n    update  ; # services the \"TheWorldHasChanged\" event, queues \"TkWorldChanged\" events\n    update  ; # services the queued \"TkWorldChanged\" events\n    set h2 [font metrics myfont -linespace]\n    set y2 [winfo y .f.f]\n    expr {($h2 - $h1) - ($y2 - $y1)}\n} -cleanup {\n    deleteWindows\n    font delete myfont\n} -result 0\n\ntest frame-13.1 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -class NewFrame\n    .f configure -class\n} -cleanup {\n    deleteWindows\n} -result {-class class Class Labelframe NewFrame}\ntest frame-13.2 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -class NewFrame\n    .f configure -class Different\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -class option after widget is created}\ntest frame-13.3 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -colormap new\n} -cleanup {\n    deleteWindows\n} -result {.f}\ntest frame-13.4 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -visual default\n} -cleanup {\n    deleteWindows\n} -result {.f}\ntest frame-13.5 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -screen bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-screen\"}\ntest frame-13.6 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -container true\n} -cleanup {\n    deleteWindows\n} -result {.f}\ntest frame-13.7 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f -container true\n    .f configure -container\n} -cleanup {\n    deleteWindows\n} -result {-container container Container 0 1}\ntest frame-13.8 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n     labelframe .f -container bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected boolean value but got \"bogus\"}\ntest frame-13.9 {labelframe configuration options} -setup {\n    deleteWindows\n} -body {\n    labelframe .f\n    .f configure -container 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't modify -container option after widget is created}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .f\nlabelframe .f\n\ntest frame-13.10 {labelframe configuration options} -body {\n    .f configure -background #ff0000\n    lindex [.f configure -background] 4\n} -cleanup {\n    .f configure -background [lindex [.f configure -background] 3]\n} -result \"#ff0000\"\ntest frame-13.11 {labelframe configuration options} -body {\n    .f configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-13.12 {labelframe configuration options} -body {\n    .f configure -bd 4\n    lindex [.f configure -bd] 4\n} -cleanup {\n    .f configure -bd [lindex [.f configure -bd] 3]\n} -result 4\ntest frame-13.13 {labelframe configuration options} -body {\n    .f configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-13.14 {labelframe configuration options} -body {\n    .f configure -bg #00ff00\n    lindex [.f configure -bg] 4\n} -cleanup {\n    .f configure -bg [lindex [.f configure -bg] 3]\n} -result \"#00ff00\"\ntest frame-13.15 {labelframe configuration options} -body {\n    .f configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-13.16 {labelframe configuration options} -body {\n    .f configure -borderwidth 1.3\n    lindex [.f configure -borderwidth] 4\n} -cleanup {\n    .f configure -borderwidth [lindex [.f configure -borderwidth] 3]\n} -result 1.3\ntest frame-13.17 {labelframe configuration options} -body {\n    .f configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-13.18 {labelframe configuration options} -body {\n    .f configure -cursor arrow\n    lindex [.f configure -cursor] 4\n} -cleanup {\n    .f configure -cursor [lindex [.f configure -cursor] 3]\n} -result {arrow}\ntest frame-13.19 {labelframe configuration options} -body {\n    .f configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest frame-13.20 {labelframe configuration options} -body {\n    .f configure -fg #0000ff\n    lindex [.f configure -fg] 4\n} -cleanup {\n    .f configure -fg [lindex [.f configure -fg] 3]\n} -result \"#0000ff\"\ntest frame-13.21 {labelframe configuration options} -body {\n    .f configure -fg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-13.22 {labelframe configuration options} -body {\n    .f configure -font {courier 8}\n    lindex [.f configure -font] 4\n} -cleanup {\n    .f configure -font [lindex [.f configure -font] 3]\n} -result {courier 8}\ntest frame-13.23 {labelframe configuration options} -body {\n    .f configure -foreground #ff0000\n    lindex [.f configure -foreground] 4\n} -cleanup {\n    .f configure -foreground [lindex [.f configure -foreground] 3]\n} -result \"#ff0000\"\ntest frame-13.24 {labelframe configuration options} -body {\n    .f configure -foreground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-13.25 {labelframe configuration options} -body {\n    .f configure -height 100\n    lindex [.f configure -height] 4\n} -cleanup {\n    .f configure -height [lindex [.f configure -height] 3]\n} -result 100\ntest frame-13.26 {labelframe configuration options} -body {\n    .f configure -height not_a_number\n} -returnCodes error -result {expected screen distance but got \"not_a_number\"}\ntest frame-13.27 {labelframe configuration options} -body {\n    .f configure -highlightbackground #112233\n    lindex [.f configure -highlightbackground] 4\n} -cleanup {\n    .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]\n} -result \"#112233\"\ntest frame-13.28 {labelframe configuration options} -body {\n    .f configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest frame-13.29 {labelframe configuration options} -body {\n    .f configure -highlightcolor #123456\n    lindex [.f configure -highlightcolor] 4\n} -cleanup {\n    .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]\n} -result \"#123456\"\ntest frame-13.30 {labelframe configuration options} -body {\n    .f configure -highlightcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest frame-13.31 {labelframe configuration options} -body {\n    .f configure -highlightthickness 6\n    lindex [.f configure -highlightthickness] 4\n} -cleanup {\n    .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]\n} -result 6\ntest frame-13.32 {labelframe configuration options} -body {\n    .f configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-13.33 {labelframe configuration options} -body {\n    .f configure -labelanchor se\n    lindex [.f configure -labelanchor] 4\n} -cleanup {\n    .f configure -labelanchor [lindex [.f configure -labelanchor] 3]\n} -result {se}\ntest frame-13.34 {labelframe configuration options} -returnCodes error -body {\n    .f configure -labelanchor badValue\n} -result {bad labelanchor \"badValue\": must be e, en, es, n, ne, nw, s, se, sw, w, wn, or ws}\ntest frame-13.35 {labelframe configuration options} -body {\n    .f configure -padx 3\n    lindex [.f configure -padx] 4\n} -cleanup {\n    .f configure -padx [lindex [.f configure -padx] 3]\n} -result 3\ntest frame-13.36 {labelframe configuration options} -body {\n    .f configure -padx badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-13.37 {labelframe configuration options} -body {\n    .f configure -pady 4\n    lindex [.f configure -pady] 4\n} -cleanup {\n    .f configure -pady [lindex [.f configure -pady] 3]\n} -result 4\ntest frame-13.38 {labelframe configuration options} -body {\n    .f configure -pady badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest frame-13.39 {labelframe configuration options} -body {\n    .f configure -relief ridge\n    lindex [.f configure -relief] 4\n} -cleanup {\n    .f configure -relief [lindex [.f configure -relief] 3]\n} -result {ridge}\ntest frame-13.40 {labelframe configuration options} -returnCodes error -body {\n    .f configure -relief badValue\n} -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\ntest frame-13.41 {labelframe configuration options} -body {\n    .f configure -takefocus {any string}\n    lindex [.f configure -takefocus] 4\n} -cleanup {\n    .f configure -takefocus [lindex [.f configure -takefocus] 3]\n} -result {any string}\ntest frame-13.42 {labelframe configuration options} -body {\n    .f configure -text {any string}\n    lindex [.f configure -text] 4\n} -cleanup {\n    .f configure -text [lindex [.f configure -text] 3]\n} -result {any string}\ntest frame-13.43 {labelframe configuration options} -body {\n    .f configure -width 32\n    lindex [.f configure -width] 4\n} -cleanup {\n    .f configure -width [lindex [.f configure -width] 3]\n} -result 32\ntest frame-13.44 {labelframe configuration options} -body {\n    .f configure -width badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .f\n\ntest frame-14.1 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Test that label is moved in stacking order\n    label .l -text Mupp -font {helvetica 8}\n    labelframe .f -labelwidget .l\n    pack .f\n    frame .f.f -width 50 -height 50\n    pack .f.f\n    update\n    list [winfo children .] [winfo width .f] \\\n\t[expr {[winfo height .f] - [winfo height .l]}]\n} -cleanup {\n    deleteWindows\n} -result {{.f .l} 54 52}\ntest frame-14.2 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Test the labelframe's reaction if the label is destroyed\n    label .l -text Aratherlonglabel\n    labelframe .f -labelwidget .l\n    pack .f\n    label .f.l -text Mupp\n    pack .f.l\n    update\n    set res [list [.f cget -labelwidget]]\n    lappend res [expr {[winfo width .f] - [winfo width .l]}]\n    destroy .l\n    lappend res [.f cget -labelwidget]\n    update\n    lappend res [expr {[winfo width .f] - [winfo width .f.l]}]\n} -cleanup {\n    deleteWindows\n} -result {.l 12 {} 4}\ntest frame-14.3 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Test the labelframe's reaction if the label is stolen\n    label .l -text Aratherlonglabel\n    labelframe .f -labelwidget .l\n    pack .f\n    label .f.l -text Mupp\n    pack .f.l\n    update\n    set res [list [.f cget -labelwidget]]\n    lappend res [expr {[winfo width .f] - [winfo width .l]}]\n    pack .l\n    lappend res [.f cget -labelwidget]\n    update\n    lappend res [expr {[winfo width .f] - [winfo width .f.l]}]\n} -cleanup {\n    deleteWindows\n} -result {.l 12 {} 4}\ntest frame-14.4 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Test the label's reaction if the labelframe is destroyed\n    label .l -text Mupp\n    labelframe .f -labelwidget .l\n    pack .f\n    update\n    set res [list [winfo manager .l]]\n    destroy .f\n    lappend res [winfo manager .l]\n} -cleanup {\n    deleteWindows\n} -result {labelframe {}}\ntest frame-14.5 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Test that the labelframe reacts on changes in label\n    label .l -text Aratherlonglabel\n    labelframe .f -labelwidget .l\n    pack .f\n    label .f.l -text Mupp\n    pack .f.l\n    update\n    set first [winfo width .f]\n    set res [expr {[winfo width .f] - [winfo width .l]}]\n    .l configure -text Shorter\n    update\n    lappend res [expr {[winfo width .f] - [winfo width .l]}]\n    lappend res [expr {[winfo width .f] < $first}]\n    .l configure -text Alotlongerthananytimebefore\n    update\n    lappend res [expr {[winfo width .f] - [winfo width .l]}]\n    lappend res [expr {[winfo width .f] > $first}]\n} -cleanup {\n    deleteWindows\n} -result {12 12 1 12 1}\ntest frame-14.6 {labelframe labelwidget option} -setup {\n    deleteWindows\n} -body {\n    # Destroying a labelframe with a child label caused a crash when not\n    # handling mapping of the label correctly.\n    # This test does not test anything directly, it's just ment to catch if\n    # the same mistake is made again.\n    labelframe .f\n    pack .f\n    label .f.l -text Mupp\n    .f configure -labelwidget .f.l\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest frame-15.1 {TIP 262: frame background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    frame .f -width 100 -height 100\n    pack .f\n    list [image inuse gorp] [.f configure -backgroundimage gorp;update] \\\n\t[image inuse gorp] [winfo width .f] [winfo height .f]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {0 {} 1 100 100}\ntest frame-15.2 {TIP 262: frame background images} -setup {\n    deleteWindows\n    catch {rename gorp \"\"}\n} -body {\n    frame .f -width 100 -height 100\n    pack .f\n    update\n    .f configure -backgroundimage gorp\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {image \"gorp\" does not exist}\ntest frame-15.3 {TIP 262: frame background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    frame .f -width 100 -height 100 -backgroundimage gorp\n    pack .f\n    .f configure -tile yes\n    update\n    list [.f cget -bgimg] [.f cget -tile]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {gorp 1}\ntest frame-15.4 {TIP 262: frame background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    frame .f -width 100 -height 100 -backgroundimage gorp\n    pack .f\n    .f configure -tile yes\n    update\n    gorp put red -to 15 15 20 20\n    update\n    list [.f cget -bgimg] [.f cget -tile]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {gorp 1}\ntest frame-15.5 {TIP 262: frame background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n    set result {}\n} -body {\n    frame .f -width 100 -height 100 -backgroundimage gorp\n    pack .f\n    .f configure -tile yes\n    update\n    image delete gorp\n    update\n    set result [list [.f cget -bgimg] [.f cget -tile]]\n    image create photo gorp -width 250 -height 250\n    update\n    lappend result [.f cget -backgroundimage]\n} -cleanup {\n    catch {image delete gorp}\n    deleteWindows\n} -result {gorp 1 gorp}\ntest frame-15.6 {TIP 262: frame background images} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 100 -height 100 -bgimg gorp]\n    update idletasks; update\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15}}\ntest frame-15.6a {TIP 262: frame background images (offsets)} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 10 -height 10 -bgimg gorp]\n    update idletasks; update\n    # On MacOS must wait for the test image display procedure to run.\n    set timer [after 300 {lappend result \"timedout\"}]\n    while {\"timedout\" ni $result &&\n\t   \"gorp display 10 2 10 10\" ni $result} {\n       vwait result\n    }\n    after cancel $timer\n    update idletasks; update\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 10 2 10 10}}\ntest frame-15.7 {TIP 262: frame background images} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1]\n    update idletasks; update\n    # On MacOS must wait for the test image display procedure to run.\n    set timer [after 300 {lappend result \"timedout\"}]\n    while {\"timedout\" ni $result &&\n\t   \"gorp display 0 0 20 10\" ni $result} {\n\tvwait result\n    }\n    after cancel $timer\n    if {[lindex $result end] eq \"timedout\"} {\n\treturn [lreplace $result end end]\n    }\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 10} {gorp display 0 0 20 15} {gorp display 0 0 20 10}}\ntest frame-15.7a {TIP 262: frame background images (offsets)} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -highlightthick 1]\n    update idletasks; update\n    # On MacOS must wait for the test image display procedure to run.\n    set timer [after 300 {lappend result \"timedout\"}]\n    while {\"timedout\" ni $result &&\n\t   \"gorp display 0 0 18 8\" ni $result} {\n\tvwait result\n   }\n    after cancel $timer\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 8} {gorp display 0 0 18 15} {gorp display 0 0 18 8}}\ntest frame-15.7b {TIP 262: frame background images (offsets)} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -bd 2]\n    update idletasks; update\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 6} {gorp display 0 0 16 15} {gorp display 0 0 16 6}}\ntest frame-15.7c {TIP 262: frame background images (offsets)} -setup {\n    deleteWindows\n    set result {}\n    . configure -width 200 -height 200\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -bd 2 -highlightthick 1]\n    update idletasks; update\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 4} {gorp display 0 0 14 15} {gorp display 0 0 14 4}}\ntest frame-15.8 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    toplevel .t -width 100 -height 100\n    update\n    # Used to verify that setting a background image doesn't change the widget size\n    set w [winfo width .t]\n    set h [winfo height .t]\n    list [image inuse gorp] [.t configure -backgroundimage gorp;update] \\\n\t[image inuse gorp] \\\n\t[expr {$w-[winfo width .t]}] [expr {$h-[winfo height .t]}]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {0 {} 1 0 0}\ntest frame-15.9 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    catch {rename gorp \"\"}\n} -body {\n    toplevel .t -width 100 -height 100\n    update\n    .t configure -backgroundimage gorp\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {image \"gorp\" does not exist}\ntest frame-15.10 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes\n    update\n    list [.t cget -bgimg] [.t cget -tile]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {gorp 1}\ntest frame-15.11 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n} -body {\n    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes\n    update\n    gorp put red -to 15 15 20 20\n    update\n    list [.t cget -bgimg] [.t cget -tile]\n} -cleanup {\n    image delete gorp\n    deleteWindows\n} -result {gorp 1}\ntest frame-15.12 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    image create photo gorp -width 10 -height 10\n    gorp put black -to 2 2 7 7\n    set result {}\n} -body {\n    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes\n    update\n    image delete gorp\n    update\n    set result [list [.t cget -bgimg] [.t cget -tile]]\n    image create photo gorp -width 250 -height 250\n    update\n    lappend result [.t cget -backgroundimage]\n} -cleanup {\n    catch {image delete gorp}\n    deleteWindows\n} -result {gorp 1 gorp}\ntest frame-15.13 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    set result {}\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    toplevel .t -width 100 -height 100 -bgimg gorp\n    wm overrideredirect .t 1;\t# Reduce trouble from window managers\n    update idletasks; update\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15}}\ntest frame-15.14 {TIP 262: toplevel background images} -setup {\n    deleteWindows\n    set result {}\n} -constraints testImageType -body {\n    image create test gorp -variable result\n    toplevel .t -width 50 -height 25 -bgimg gorp -tile 1\n    wm overrideredirect .t 1;\t# Reduce trouble from window managers\n    update idletasks; update\n    # On MacOS must wait for the test image display procedure to run.\n    set timer [after 300 {lappend result \"timedout\"}]\n    while {\"timedout\" ni $result &&\n\t   \"gorp display 0 0 20 10\" ni $result} {\n\tvwait result\n   }\n    after cancel $timer\n    return [uniq $result]\n} -cleanup {\n    deleteWindows\n    catch {image delete gorp}\n} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 10} {gorp display 0 0 20 15} {gorp display 0 0 20 10}}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\napply {cmds {foreach cmd $cmds {rename $cmd {}}}} {\n    uniq optnames\n}\ntestutils forget colors\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/geometry.test",
    "content": "# This file is a Tcl script to test the procedures in the file\n# tkGeometry.c (generic support for geometry managers).\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n\n#\n# COMMON TEST SETUP\n#\n\nwm geometry . 300x300\nraise .\nupdate\n\nframe .f -bd 2 -relief raised\nframe .f.f -bd 2 -relief sunken\nframe .f.f.f -bd 2 -relief raised\nbutton .b1 -text .b1\nbutton .b2 -text .b2\nbutton .b3 -text .b3\nbutton .f.f.b4 -text .b4\n\n#\n# TESTS\n#\n\ntest geometry-1.1 {Tk_ManageGeometry procedure} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .b1 -x 120 -y 80\n    update\n    list [winfo x .b1] [winfo y .b1]\n} -result {120 80}\ntest geometry-1.2 {Tk_ManageGeometry procedure} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .b1 -in .f -x 40 -y 30\n    update\n    pack .b1 -side top -anchor w\n    place .f -x 30 -y 40\n    update\n    list [winfo x .b1] [winfo y .b1]\n} -result {0 0}\n\n\ntest geometry-2.1 {Tk_GeometryRequest procedure} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n    destroy .f2\n} -body {\n    frame .f2\n    set result [list [winfo reqwidth .f2] [winfo reqheight .f2]]\n    .f2 configure -width 150 -height 300\n    update\n    lappend result [winfo reqwidth .f2] [winfo reqheight .f2] \\\n\t[winfo geom .f2]\n    place .f2 -x 10 -y 20\n    update\n    lappend result [winfo geom .f2]\n    .f2 configure -width 100 -height 80\n    update\n    lappend result [winfo geom .f2]\n} -cleanup {\n    destroy .f2\n} -result {1 1 150 300 1x1+0+0 150x300+10+20 100x80+10+20}\n\n\ntest geometry-3.1 {Tk_SetInternalBorder procedure} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .b1 -in .f -x 50 -y 5\n    update\n    set x [list [winfo x .b1] [winfo y .b1]]\n    .f configure -bd 5\n    update\n    lappend x [winfo x .b1] [winfo y .b1]\n} -cleanup {\n    .f configure -bd 2\n} -result {72 37 75 40}\n\n\ntest geometry-4.1 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    update\n    list [winfo x .b1] [winfo y .b1]\n} -result {91 46}\ntest geometry-4.2 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    place .b3 -in .f.f.f -x 50 -y 25\n    update\n    place .f -x 30 -y 25\n    update\n    list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \\\n\t[winfo x .b3] [winfo y .b3]\n} -result {101 41 61 61 101 61}\ntest geometry-4.3 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    place .b3 -in .f.f.f -x 50 -y 25\n    update\n    destroy .b1\n    button .b1 -text .b1\n    place .f.f -x 10 -y 25\n    update\n    list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \\\n\t[winfo x .b3] [winfo y .b3]\n} -result {0 0 46 86 86 86}\ntest geometry-4.4 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    place .b3 -in .f.f.f -x 50 -y 25\n    update\n    destroy .b2\n    button .b2 -text .b2\n    place .f.f.f -x 2 -y 3\n    update\n    list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \\\n\t[winfo x .b3] [winfo y .b3]\n} -result {93 49 0 0 93 69}\ntest geometry-4.5 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    place .b3 -in .f.f.f -x 50 -y 25\n    update\n    destroy .b3\n    button .b3 -text .b3\n    place .f.f.f -x 2 -y 3\n    update\n    list [winfo x .b1] [winfo y .b1] [winfo x .b2] [winfo y .b2] \\\n\t[winfo x .b3] [winfo y .b3]\n} -result {93 49 53 69 0 0}\ntest geometry-4.6 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    foreach w {.f .f.f .f.f.f .b1 .b2 .b3 .f.f.b4} {\n    place forget $w\n    }\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .f.f.b4 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    update\n    place .f -x 25 -y 35\n    update\n    list [winfo x .f.f.b4] [winfo y .f.f.b4] [winfo x .b2] [winfo y .b2]\n} -result {54 9 56 71}\ntest geometry-4.7 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    bind .b1 <Configure> {lappend x configure}\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .f.f.b4 -in .f.f.f -x 50 -y 5\n    place .b1 -in .f.f.f -x 10 -y 25\n    update\n    set x init\n    place .f -x 25 -y 35\n    update\n    lappend x |\n    place .f -x 30 -y 40\n    place .f.f -x 10 -y 0\n    update\n    return $x\n} -cleanup {\n    bind .b1 <Configure> {}\n} -result {init configure |}\ntest geometry-4.8 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    place .b2 -in .f.f.f -x 10 -y 25\n    place .b3 -in .f.f.f -x 50 -y 25\n    update\n    destroy .f.f\n    frame .f.f -bd 2 -relief raised\n    frame .f.f.f -bd 2 -relief raised\n    place .f -x 30 -y 25\n    update\n    list [winfo x .b1] [winfo y .b1] [winfo ismapped .b1] \\\n\t[winfo x .b2] [winfo y .b2] [winfo ismapped .b2] \\\n\t[winfo x .b3] [winfo y .b3] [winfo ismapped .b3]\n} -result {91 46 0 51 66 0 91 66 0}\ntest geometry-4.9 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n} -body {\n    place .f -x 20 -y 30 -width 200 -height 200\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    place .f.f.f -width 100 -height 80\n    place .b1 -in .f.f.f -x 50 -y 5\n    update\n    set result [winfo ismapped .b1]\n    place forget .f.f\n    update\n    lappend result [winfo ismapped .b1]\n    place .f.f -x 15 -y 5 -width 150 -height 120\n    update\n    lappend result [winfo ismapped .b1]\n} -result {1 0 1}\ntest geometry-4.10 {Tk_MaintainGeometry and Tk_UnmaintainGeometry} -setup {\n\tforeach w {.f .f.f .f.f.f .b1 .b2 .b3} {\n\tplace forget $w\n    }\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t +0+0\n    tkwait visibility .t\n    update\n    pack [frame .t.f]\n    button .t.quit -text Quit -command exit\n    pack .t.quit -in .t.f\n    wm iconify .t\n    set x 0\n    after 500 {set x 1}\n    tkwait variable x\n    wm deiconify .t\n    update\n    winfo ismapped .t.quit\n} -cleanup {\n    destroy .t\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/get.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkGet.c.\n#\n# Copyright © 1998 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest get-1.1 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor n\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {n}\ntest get-1.2 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor ne\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {ne}\ntest get-1.3 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor e\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {e}\ntest get-1.4 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor se\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {se}\ntest get-1.5 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor s\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {s}\ntest get-1.6 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor sw\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {sw}\ntest get-1.7 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor w\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {w}\ntest get-1.8 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor nw\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {nw}\ntest get-1.9 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor n\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {n}\ntest get-1.10 {Tk_GetAnchorFromObj} -setup {\n    button .b\n} -body {\n    .b configure -anchor center\n    .b cget -anchor\n} -cleanup {\n    destroy .b\n} -result {center}\ntest get-1.11 {Tk_GetAnchorFromObj - error} -setup {\n    button .b\n} -body {\n    .b configure -anchor unknown\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad anchor \"unknown\": must be n, ne, e, se, s, sw, w, nw, or center}\n\n\ntest get-2.1 {Tk_GetJustifyFromObj} -setup {\n    button .b\n} -body {\n    .b configure -justify left\n    .b cget -justify\n} -cleanup {\n    destroy .b\n} -result {left}\ntest get-2.2 {Tk_GetJustifyFromObj} -setup {\n    button .b\n} -body {\n    .b configure -justify right\n    .b cget -justify\n} -cleanup {\n    destroy .b\n} -result {right}\ntest get-2.3 {Tk_GetJustifyFromObj} -setup {\n    button .b\n} -body {\n    .b configure -justify center\n    .b cget -justify\n} -cleanup {\n    destroy .b\n} -result {center}\ntest get-2.4 {Tk_GetJustifyFromObj - error} -setup {\n    button .b\n} -body {\n    .b configure -justify stupid\n} -cleanup {\n    destroy .b\n} -returnCodes error -result {bad justification \"stupid\": must be left, right, or center}\n\n#\n# TESTFILE CLEANUP\n#\n\n# cleanup\ncleanupTests\n"
  },
  {
    "path": "tests/grab.test",
    "content": "# Tests for the grab command.\n#\n# Copyright © 1998-2000 Ajuba Solutions.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# The macOS test module includes the testpressbutton command to simulate a\n# mouse button press event by injecting events into the NSApplication\n# event queue.  On other platforms there is currently no way to test\n# the actual grab effect, per se, in an automated test.  Therefore,\n# this test suite only covers the interface to the grab command (ie,\n# error messages, etc.) on platforms other than macOS.\n\n#\n# TESTS\n#\n\ntest grab-1.1 {Tk_GrabObjCmd} -body {\n    grab\n} -returnCodes error -result {wrong # args: should be \"grab ?-global? window\" or \"grab option ?arg ...?\"}\ntest grab-1.2 {Tk_GrabObjCmd} -body {\n    rename grab grabTest1.2\n    grabTest1.2\n} -cleanup {\n    rename grabTest1.2 grab\n} -returnCodes error -result {wrong # args: should be \"grabTest1.2 ?-global? window\" or \"grabTest1.2 option ?arg ...?\"}\n\ntest grab-1.3 {Tk_GrabObjCmd, \"grab ?-global? window\"} -body {\n    grab .foo bar baz\n} -returnCodes error -result {wrong # args: should be \"grab ?-global? window\"}\ntest grab-1.4 {Tk_GrabObjCmd, \"grab ?-global? window\"} -body {\n    destroy .foo\n    grab .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest grab-1.5 {Tk_GrabObjCmd, \"grab ?-global? window\"} -body {\n    grab -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -global}\ntest grab-1.6 {Tk_GrabObjCmd, \"grab ?-global? window\"} -body {\n    destroy .foo\n    grab -global .foo\n} -returnCodes error -result {bad window path name \".foo\"}\n\ntest grab-1.7 {Tk_GrabObjCmd} -body {\n    grab foo\n} -returnCodes error -result {bad option \"foo\": must be current, release, set, or status}\n\ntest grab-1.8 {Tk_GrabObjCmd, \"grab current ?window?\"} -body {\n    grab current foo bar\n} -returnCodes error -result {wrong # args: should be \"grab current ?window?\"}\ntest grab-1.9 {Tk_GrabObjCmd, \"grab current ?window?\"} -body {\n    destroy .foo\n    grab current .foo\n} -returnCodes error -result {bad window path name \".foo\"}\n\ntest grab-1.10 {Tk_GrabObjCmd, \"grab release window\"} -body {\n    grab release\n} -returnCodes error -result {wrong # args: should be \"grab release window\"}\ntest grab-1.11 {Tk_GrabObjCmd, \"grab release window\"} -body {\n    destroy .foo\n    grab release .foo\n} -returnCodes ok -result {}\ntest grab-1.12 {Tk_GrabObjCmd, \"grab release window\"} -body {\n    grab release foo\n} -returnCodes ok -result {}\n\ntest grab-1.13 {Tk_GrabObjCmd, \"grab set ?-global? window\"} -body {\n    grab set\n} -returnCodes error -result {wrong # args: should be \"grab set ?-global? window\"}\ntest grab-1.14 {Tk_GrabObjCmd, \"grab set ?-global? window\"} -body {\n    grab set foo bar baz\n} -returnCodes error -result {wrong # args: should be \"grab set ?-global? window\"}\ntest grab-1.15 {Tk_GrabObjCmd, \"grab set ?-global? window\"} -body {\n    destroy .foo\n    grab set .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest grab-1.16 {Tk_GrabObjCmd, \"grab set ?-global? window\"} -body {\n    grab set -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -global}\ntest grab-1.17 {Tk_GrabObjCmd, \"grab set ?-global? window\"} -body {\n    destroy .foo\n    grab set -global .foo\n} -returnCodes error -result {bad window path name \".foo\"}\n\ntest grab-1.18 {Tk_GrabObjCmd, \"grab status window\"} -body {\n    grab status\n} -returnCodes error -result {wrong # args: should be \"grab status window\"}\ntest grab-1.19 {Tk_GrabObjCmd, \"grab status window\"} -body {\n    grab status foo bar\n} -returnCodes error -result {wrong # args: should be \"grab status window\"}\ntest grab-1.20 {Tk_GrabObjCmd, \"grab status window\"} -body {\n    destroy .foo\n    grab status .foo\n} -returnCodes error -result {bad window path name \".foo\"}\n\n\ntest grab-2.1 {Tk_GrabObjCmd, grab status gives correct status} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab status .\n} -cleanup {\n    grab release .\n} -result none\ntest grab-2.2 {Tk_GrabObjCmd, grab status gives correct status} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab .\n    grab status .\n} -cleanup {\n    grab release .\n} -result {local}\ntest grab-2.3 {Tk_GrabObjCmd, grab status gives correct status} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab -global .\n    grab status .\n} -cleanup {\n    grab release .\n} -result {global}\n\n\ntest grab-3.1 {Tk_GrabObjCmd, grab current gives correct information} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    return $curr\n} -result {}\ntest grab-3.2 {Tk_GrabObjCmd, grab current gives correct information} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab .\n    grab current\n} -cleanup {\n    grab release .\n} -result {.}\n\n\ntest grab-4.1 {Tk_GrabObjCmd, grab release releases grab} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab .\n    set result [grab status .]\n    grab release .\n    lappend result [grab status .]\n    grab -global .\n    lappend result [grab status .]\n    grab release .\n    lappend result [grab status .]\n} -result {local none global none}\n\n\ntest grab-5.1 {Tk_GrabObjCmd, grab set} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab set .\n    list [grab current .] [grab status .]\n} -cleanup {\n    grab release .\n} -result {. local}\ntest grab-5.2 {Tk_GrabObjCmd, grab set} -body {\n    set curr [grab current .]\n    if { [string length $curr] > 0 } {\n\tgrab release $curr\n    }\n    grab set -global .\n    list [grab current .] [grab status .]\n} -cleanup {\n    grab release .\n} -result {. global}\n\ntest grab-6.1 {local grab on child window} -constraints {\n    testpressbutton\n} -body {\n    wm geometry . 100x200+200+100\n    set result {}\n    frame .f -background red -padx 10 -pady 10 -height 100 -width 80\n    bind . <Button-1> {lappend result \"outside\"}\n    bind .f <Button-1> {lappend result \"inside\"}\n    pack .f\n    update idletasks\n    testpressbutton 250 150\n    update\n    lappend result \":\"\n    testpressbutton 250 250\n    update\n    lappend result \":\"\n    grab set .f\n    testpressbutton 250 150\n    update\n    lappend result \":\"\n    testpressbutton 250 250\n    update\n    return $result\n} -cleanup {\n    grab release .f\n} -result {inside outside : outside : inside outside :}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/grid.test",
    "content": "# This file is a Tcl script to test out the *NEW* \"grid\" command of Tk.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# grid_reset --\n#\n#    Helper routine to return \".\" to a sane state after a test.\n#    The variable GRID_VERBOSE can be used to \"look\" at the result of one or all\n#    of the tests\n#\nproc grid_reset {{test ?} {top .}} {\n    global GRID_VERBOSE\n    if {[info exists GRID_VERBOSE]} {\n\tif {$GRID_VERBOSE eq \"\" || $GRID_VERBOSE eq $test} {\n\t    puts -nonewline \"grid test $test: \"\n\t    flush stdout\n\t    gets stdin\n\t}\n    }\n    destroy {*}[winfo children $top]\n    update\n    foreach {cols rows} [grid size .] {}\n    for {set i 0} {$i <= $cols} {incr i} {\n\tgrid columnconfigure . $i -weight 0 -minsize 0 -pad 0 -uniform \"\"\n    }\n    for {set i 0} {$i <= $rows} {incr i} {\n\tgrid rowconfigure . $i -weight 0 -minsize 0 -pad 0 -uniform \"\"\n    }\n    grid propagate . 1\n    grid anchor . nw\n    update\n}\n\n#\n# COMMON TEST SETUP\n#\n\ngrid_reset 0.0\nwm geometry . {}\n\n#\n# TESTS\n#\n\ntest grid-1.1 {basic argument checking} -body {\n    grid\n} -returnCodes error -result {wrong # args: should be \"grid option arg ?arg ...?\"}\ntest grid-1.2 {basic argument checking} -body {\n    grid foo bar\n} -returnCodes error -result {bad option \"foo\": must be anchor, bbox, columnconfigure, configure, content, forget, info, location, propagate, remove, rowconfigure, or size}\ntest grid-1.3 {basic argument checking} -body {\n    button .b\n    grid .b -row 0 -column\n} -cleanup {\n    grid_reset 1.3\n} -returnCodes error -result {extra option or option with no value}\ntest grid-1.4 {basic argument checking} -body {\n    button .b\n    grid configure .b - foo\n} -cleanup {\n    grid_reset 1.4\n} -returnCodes error -result {unexpected parameter \"foo\" in configure list: should be window name or option}\ntest grid-1.5 {basic argument checking} -body {\n    grid .\n} -returnCodes error -result {can't manage \".\": it's a top-level window}\ntest grid-1.6 {basic argument checking} -body {\n    grid x\n} -returnCodes error -result {can't determine container window}\ntest grid-1.7 {basic argument checking} -body {\n    grid configure x\n} -returnCodes error -result {can't determine container window}\ntest grid-1.8 {basic argument checking} -body {\n    button .b\n    grid x .b\n} -cleanup {\n    grid_reset 1.8\n} -returnCodes ok -result {}\ntest grid-1.9 {basic argument checking} -body {\n    button .b\n    grid configure x .b\n} -cleanup {\n    grid_reset 1.9\n} -returnCodes ok -result {}\n\n\ntest grid-2.1 {bbox} -body {\n    grid bbox .\n} -result {0 0 0 0}\ntest grid-2.2 {bbox} -body {\n    button .b\n    grid .b\n    destroy .b\n    update\n    grid bbox .\n} -result {0 0 0 0}\ntest grid-2.3 {bbox: argument checking} -body {\n    grid bbox . 0 0 5\n} -returnCodes error -result {wrong # args: should be \"grid bbox window ?column row ?column row??\"}\ntest grid-2.4 {bbox} -body {\n    grid bbox .bad 0 0\n} -returnCodes error -result {bad window path name \".bad\"}\ntest grid-2.5 {bbox} -body {\n    grid bbox . x 0\n} -returnCodes error -result {expected integer but got \"x\"}\ntest grid-2.6 {bbox} -body {\n    grid bbox . 0 x\n} -returnCodes error -result {expected integer but got \"x\"}\ntest grid-2.7 {bbox} -body {\n    grid bbox . 0 0 x 0\n} -returnCodes error -result {expected integer but got \"x\"}\ntest grid-2.8 {bbox} -body {\n    grid bbox . 0 0 0 x\n} -returnCodes error -result {expected integer but got \"x\"}\ntest grid-2.9 {bbox} -body {\n    frame .1 -width 75 -height 75 -bg red\n    frame .2 -width 90 -height 90 -bg red\n    grid .1 -row 0 -column 0\n    grid .2 -row 1 -column 1\n    update\n    set a \"\"\n    lappend a [grid bbox .]\n    lappend a [grid bbox . 0 0]\n    lappend a [grid bbox . 0 0 1 1]\n    lappend a [grid bbox . 1 1]\n    return $a\n} -cleanup {\n    grid_reset 2.9\n} -result {{0 0 165 165} {0 0 75 75} {0 0 165 165} {75 75 90 90}}\ntest grid-2.10 {bbox} -body {\n    frame .1 -width 75 -height 75 -bg red\n    frame .2 -width 90 -height 90 -bg red\n    grid .1 -row 0 -column 0\n    grid .2 -row 1 -column 1\n    update\n    set a \"\"\n    lappend a [grid bbox . 10 10 0 0]\n    lappend a [grid bbox . -2 -2 -1 -1]\n    lappend a [grid bbox . 10 10 12 12]\n    return $a\n} -cleanup {\n    grid_reset 2.10\n} -result {{0 0 165 165} {0 0 0 0} {165 165 0 0}}\n\ntest grid-3.1 {configure: basic argument checking} -body {\n    grid configure foo\n} -returnCodes error -result {bad argument \"foo\": must be name of window}\ntest grid-3.2 {configure: basic argument checking} -body {\n    button .b\n    grid configure .b\n    grid content .\n} -cleanup {\n    grid_reset 3.2\n} -result {.b}\ntest grid-3.3 {configure: basic argument checking} -body {\n    button .b\n    grid .b -row -1\n} -cleanup {\n    grid_reset 3.3\n} -returnCodes error -result {bad row value \"-1\": must be a non-negative integer}\ntest grid-3.4 {configure: basic argument checking} -body {\n    button .b\n    grid .b -column -1\n} -cleanup {\n    grid_reset 3.4\n} -returnCodes error -result {bad column value \"-1\": must be a non-negative integer}\ntest grid-3.5 {configure: basic argument checking} -body {\n    button .b\n    grid .b -rowspan 0\n} -cleanup {\n    grid_reset 3.5\n} -returnCodes error -result {bad rowspan value \"0\": must be a positive integer}\ntest grid-3.6 {configure: basic argument checking} -body {\n    button .b\n    grid .b -columnspan 0\n} -cleanup {\n    grid_reset 3.6\n} -returnCodes error -result {bad columnspan value \"0\": must be a positive integer}\ntest grid-3.7 {configure: basic argument checking} -body {\n    frame .f\n    button .f.b\n    grid .f .f.b\n} -cleanup {\n    grid_reset 3.7\n} -returnCodes error -result {can't put \".f.b\" inside \".\"}\ntest grid-3.8 {configure: basic argument checking} -body {\n    button .b\n    grid configure x .b\n    grid content .\n} -cleanup {\n    grid_reset 3.8\n} -result {.b}\ntest grid-3.9 {configure: basic argument checking} -body {\n    button .b\n    grid configure y .b\n} -cleanup {\n    grid_reset 3.9\n} -returnCodes error -result {invalid window shortcut, \"y\" should be '-', 'x', or '^'}\ntest grid-3.10 {ConfigureContent procedure, bad -in option} -body {\n    frame .f\n    grid .f -in .f\n} -cleanup {\n    grid_reset 3.10\n} -returnCodes error -result {window can't be managed in itself}\ntest grid-3.11 {prevent management loops} -body {\n    frame .f1\n    frame .f2\n    grid .f1 -in .f2\n    grid .f2 -in .f1\n} -cleanup {\n    grid_reset 3.11\n} -returnCodes error -result {can't put \".f2\" inside \".f1\": would cause management loop}\ntest grid-3.12 {prevent management loops} -body {\n    frame .f1\n    frame .f2\n    frame .f3\n    grid .f1 -in .f2\n    grid .f2 -in .f3\n    grid .f3 -in .f1\n} -cleanup {\n    grid_reset 3.12\n} -returnCodes error -result {can't put \".f3\" inside \".f1\": would cause management loop}\n\ntest grid-4.1 {forget: basic argument checking} -body {\n    grid forget foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest grid-4.2 {forget} -body {\n    button .c\n    grid [button .b]\n    set a [grid content .]\n    grid forget .b .c\n    lappend a [grid content .]\n    return $a\n} -cleanup {\n    grid_reset 4.2\n} -result {.b {}}\ntest grid-4.3 {forget} -body {\n    button .c\n    grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns\n    grid forget .c\n    grid .c -row 0 -column 0\n    grid info .c\n} -cleanup {\n    grid_reset 4.3\n} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}\ntest grid-4.4 {forget} -body {\n    button .c\n    grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns\n    grid forget .c\n    grid .c -row 0 -column 0\n    grid info .c\n} -cleanup {\n    grid_reset 4.4\n} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}\ntest grid-4.5 {forget, calling Tk_UnmaintainGeometry} -body {\n    frame .f -bd 2 -relief raised\n    place .f -x 10 -y 20 -width 200 -height 100\n    frame .f2 -width 50 -height 30 -bg red\n    grid .f2 -in .f\n    update\n    set x [winfo ismapped .f2]\n    grid forget .f2\n    place .f -x 30\n    update\n    lappend x [winfo ismapped .f2]\n} -cleanup {\n    grid_reset 4.5\n} -result {1 0}\n\ntest grid-5.1 {info: basic argument checking} -body {\n    grid info a b\n} -returnCodes error -result {wrong # args: should be \"grid info window\"}\ntest grid-5.2 {info} -body {\n    frame .1 -width 75 -height 75 -bg red\n    grid .1 -row 0 -column 0\n    update\n    grid info .x\n} -cleanup {\n    grid_reset 5.2\n} -returnCodes error -result {bad window path name \".x\"}\ntest grid-5.3 {info} -body {\n    frame .1 -width 75 -height 75 -bg red\n    grid .1 -row 0 -column 0\n    update\n    grid info .1\n} -cleanup {\n    grid_reset 5.3\n} -result {-in . -column 0 -row 0 -columnspan 1 -rowspan 1 -ipadx 0 -ipady 0 -padx 0 -pady 0 -sticky {}}\ntest grid-5.4 {info} -body {\n    frame .1 -width 75 -height 75 -bg red\n    update\n    grid info .1\n} -cleanup {\n    grid_reset 5.4\n} -returnCodes ok -result {}\n\ntest grid-6.1 {location: basic argument checking} -body {\n    grid location .\n} -returnCodes error -result {wrong # args: should be \"grid location window x y\"}\ntest grid-6.2 {location: basic argument checking} -body {\n    grid location .bad 0 0\n} -returnCodes error -result {bad window path name \".bad\"}\ntest grid-6.3 {location: basic argument checking} -body {\n    grid location . x y\n} -returnCodes error -result {expected screen distance but got \"x\"}\ntest grid-6.4 {location: basic argument checking} -body {\n    grid location . 1c y\n} -returnCodes error -result {expected screen distance but got \"y\"}\ntest grid-6.5 {location: basic argument checking} -body {\n    frame .f\n    grid location .f 10 10\n} -cleanup {\n    grid_reset 6.5\n} -result {-1 -1}\ntest grid-6.6 {location (x)} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set got \"\"\n    set result \"\"\n    for {set x -10} { $x < 220} { incr x} {\n\tset a [grid location . $x 0]\n\tif {$a ne $got} {\n\t    lappend result $x->$a\n\t    set got $a\n\t}\n    }\n    return $result\n} -cleanup {\n    grid_reset 6.6\n} -result {{-10->-1 0} {0->0 0} {201->1 0}}\ntest grid-6.7 {location (y)} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set got \"\"\n    set result \"\"\n    for {set y -10} { $y < 110} { incr y} {\n\tset a [grid location . 0 $y]\n\tif {$a ne $got} {\n\t    lappend result $y->$a\n\t    set got $a\n\t}\n    }\n    return $result\n} -cleanup {\n    grid_reset 6.7\n} -result {{-10->0 -1} {0->0 0} {101->0 1}}\ntest grid-6.8 {location (weights)} -body {\n    frame .f -width 300 -height 100 -highlightthickness 0 -bg red\n    frame .a\n    grid .a\n    grid .f -in .a\n    grid rowconfigure .f 0 -weight 1\n    grid columnconfigure .f 0 -weight 1\n    grid propagate .a 0\n    .a configure -width 200 -height 15\n    update\n    set got \"\"\n    set result \"\"\n    for {set y -10} { $y < 210} { incr y} {\n\tset a [grid location . $y $y]\n\tif {$a ne $got} {\n\t    lappend result $y->$a\n\t    set got $a\n\t}\n    }\n    return $result\n} -cleanup {\n    grid_reset 6.8\n} -result {{-10->-1 -1} {0->0 0} {16->0 1} {201->1 1}}\ntest grid-6.9 {location: check updates pending} -body {\n    set a \"\"\n    foreach i {0 1 2} {\n\tframe .$i -width 120 -height 75 -bg red\n\tlappend a [grid location . 150 90]\n\tgrid .$i -row $i -column $i\n    }\n    return $a\n} -cleanup {\n    grid_reset 6.9\n} -result {{0 0} {1 1} {1 1}}\n\ntest grid-7.1 {propagate} -body {\n    grid propagate . 1 xxx\n} -cleanup {\n    grid_reset 7.1\n} -returnCodes error -result {wrong # args: should be \"grid propagate window ?boolean?\"}\ntest grid-7.2 {propagate} -body {\n    grid propagate .\n} -cleanup {\n    grid_reset 7.2\n} -result 1\ntest grid-7.3 {propagate} -body {\n    grid propagate . 0;grid propagate .\n} -cleanup {\n    grid_reset 7.3\n} -result 0\ntest grid-7.4 {propagate} -body {\n    grid propagate .x\n} -cleanup {\n    grid_reset 7.4\n} -returnCodes error -result {bad window path name \".x\"}\ntest grid-7.5 {propagate} -body {\n    grid propagate . x\n} -cleanup {\n    grid_reset 7.5\n} -returnCodes error -result {expected boolean value but got \"x\"}\ntest grid-7.6 {propagate} -body {\n    frame .f -width 100 -height 100 -bg red\n    grid .f -row 0 -column 0\n    update\n    set a [winfo width .f]x[winfo height .f]\n    grid propagate .f 0\n    frame .g -width 75 -height 85 -bg green\n    grid .g -in .f -row 0 -column 0\n    update\n    lappend a [winfo width .f]x[winfo height .f]\n    grid propagate .f 1\n    update\n    lappend a [winfo width .f]x[winfo height .f]\n    return $a\n} -cleanup {\n    grid_reset 7.6\n} -result {100x100 100x100 75x85}\ntest grid-7.7 {propagate} -body {\n    grid propagate . 1\n    set res [list [grid propagate .]]\n    grid propagate . 0\n    lappend res [grid propagate .]\n    grid propagate . 0\n    lappend res [grid propagate .]\n    return $res\n} -cleanup {\n    grid_reset 7.7\n} -result [list 1 0 0]\n\ntest grid-8.1 {size} -body {\n    grid size . foo\n} -cleanup {\n    grid_reset 8.1\n} -returnCodes error -result {wrong # args: should be \"grid size window\"}\ntest grid-8.2 {size} -body {\n    grid size .x\n} -cleanup {\n    grid_reset 8.2\n} -returnCodes error -result {bad window path name \".x\"}\ntest grid-8.3 {size} -body {\n    frame .f\n    grid size .f\n} -cleanup {\n    grid_reset 8.3\n} -result {0 0}\ntest grid-8.4 {size} -body {\n    catch {unset a}\n    scale .f\n    grid .f -row 0 -column 0\n    update\n    lappend a [grid size .]\n    grid .f -row 4 -column 5\n    update\n    lappend a [grid size .]\n    grid .f -row 947 -column 663\n    update\n    lappend a [grid size .]\n    grid .f -row 0 -column 0\n    update\n    lappend a [grid size .]\n    return $a\n} -cleanup {\n    grid_reset 8.4\n} -result {{1 1} {6 5} {664 948} {1 1}}\ntest grid-8.5 {size} -body {\n    catch {unset a}\n    scale .f\n    grid .f -row 0 -column 0\n    update\n    lappend a [grid size .]\n    grid rowconfigure . 17 -weight 1\n    update\n    lappend a [grid size .]\n    grid columnconfigure . 63 -weight 1\n    update\n    lappend a [grid size .]\n    grid columnconfigure . 63 -weight 0\n    grid rowconfigure . 17 -weight 0\n    update\n    lappend a [grid size .]\n    return $a\n} -cleanup {\n    grid_reset 8.5\n} -result {{1 1} {1 18} {64 18} {1 1}}\ntest grid-8.6 {size} -body {\n    catch {unset a}\n    scale .f\n    grid .f -row 10 -column 50\n    update\n    lappend a [grid size .]\n    grid columnconfigure . 15 -weight 1\n    grid columnconfigure . 30 -weight 1\n    update\n    lappend a [grid size .]\n    grid .f -row 10 -column 20\n    update\n    lappend a [grid size .]\n    grid columnconfigure . 30 -weight 0\n    update\n    lappend a [grid size .]\n    grid .f -row 0 -column 0\n    update\n    lappend a [grid size .]\n    grid columnconfigure . 15 -weight 0\n    update\n    lappend a [grid size .]\n    return $a\n} -cleanup {\n    grid_reset 8.6\n} -result {{51 11} {51 11} {31 11} {21 11} {16 1} {1 1}}\n\ntest grid-9.1 {content} -body {\n    grid content .\n} -returnCodes ok -result {}\ntest grid-9.2 {content} -body {\n    grid content .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest grid-9.3 {content} -body {\n    grid content a b\n} -returnCodes error -result {wrong # args: should be \"grid content window ?-option value ...?\"}\ntest grid-9.4 {content} -body {\n    grid content . a b\n} -returnCodes error -result {bad option \"a\": must be -column or -row}\ntest grid-9.5 {content} -body {\n    grid content . -column x\n} -returnCodes error -result {expected integer but got \"x\"}\ntest grid-9.6 {content} -body {\n    grid content . -row -3\n} -returnCodes error -result {-3 is an invalid value: should NOT be < 0}\ntest grid-9.7 {content} -body {\n    grid content . -foo 3\n} -returnCodes error -result {bad option \"-foo\": must be -column or -row}\ntest grid-9.8 {content} -body {\n    grid content .x -row 3\n} -returnCodes error -result {bad window path name \".x\"}\ntest grid-9.9 {content} -body {\n    grid content . -row 3\n} -returnCodes ok -result {}\ntest grid-9.10 {content} -body {\n    foreach i {0 1 2} {\n\tlabel .$i -text $i\n\tgrid .$i -row $i -column $i\n    }\n    grid content .\n} -cleanup {\n    grid_reset 9.10\n} -result {.2 .1 .0}\ntest grid-9.11 {content} -body {\n    catch {unset a}\n    foreach i {0 1 2} {\n\tlabel .$i -text $i\n\tlabel .$i-x -text $i-x\n\tgrid .$i -row $i -column $i\n\tgrid .$i-x -row $i -column [incr i]\n    }\n    foreach row {0 1 2 3} {\n\tlappend a $row{[grid content . -row $row]}\n    }\n    foreach col {0 1 2 3} {\n\tlappend a $col{[grid content . -column $col]}\n    }\n    return $a\n} -cleanup {\n    grid_reset 9.11\n} -result {{0{.0-x .0}} {1{.1-x .1}} {2{.2-x .2}} 3{} 0{.0} {1{.1 .0-x}} {2{.2 .1-x}} 3{.2-x}}\n\n# column/row configure\ntest grid-10.1 {column/row configure} -body {\n    grid columnconfigure .\n} -cleanup {\n    grid_reset 10.1\n} -returnCodes error -result {wrong # args: should be \"grid columnconfigure window index ?-option value ...?\"}\ntest grid-10.2 {column/row configure} -body {\n    grid columnconfigure . 0 -weight 0 -pad\n} -cleanup {\n    grid_reset 10.2\n} -returnCodes error -result {wrong # args: should be \"grid columnconfigure window index ?-option value ...?\"}\ntest grid-10.3 {column/row configure} -body {\n    grid columnconfigure .f 0 -weight\n} -cleanup {\n    grid_reset 10.3\n} -returnCodes error -result {bad window path name \".f\"}\ntest grid-10.4 {column/row configure} -body {\n    grid columnconfigure . nine -weight\n} -cleanup {\n    grid_reset 10.4\n} -returnCodes error -result {expected integer but got \"nine\" (when retrieving options only integer indices are allowed)}\ntest grid-10.5 {column/row configure} -body {\n    grid columnconfigure . 265 -weight\n} -cleanup {\n    grid_reset 10.5\n} -result 0\ntest grid-10.6 {column/row configure} -body {\n    grid columnconfigure . 0\n} -cleanup {\n    grid_reset 10.6\n} -result {-minsize 0 -pad 0 -uniform {} -weight 0}\ntest grid-10.7 {column/row configure} -body {\n    grid columnconfigure . 0 -foo\n} -cleanup {\n    grid_reset 10.7\n} -returnCodes error -result {bad option \"-foo\": must be -minsize, -pad, -uniform, or -weight}\ntest grid-10.8 {column/row configure} -body {\n    grid columnconfigure . 0 -minsize foo\n} -cleanup {\n    grid_reset 10.8\n} -returnCodes error -result {expected screen distance but got \"foo\"}\ntest grid-10.9 {column/row configure} -body {\n    grid columnconfigure . 0 -minsize foo\n} -cleanup {\n    grid_reset 10.9\n} -returnCodes error -result {expected screen distance but got \"foo\"}\ntest grid-10.10 {column/row configure} -body {\n    grid columnconfigure . 0 -minsize 10\n    grid columnconfigure . 0 -minsize\n} -cleanup {\n    grid_reset 10.10\n} -result 10\ntest grid-10.11 {column/row configure} -body {\n    grid columnconfigure . 0 -weight bad\n} -cleanup {\n    grid_reset 10.11\n} -returnCodes error -result {expected integer but got \"bad\"}\ntest grid-10.12 {column/row configure} -body {\n    grid columnconfigure . 0 -weight -3\n} -cleanup {\n    grid_reset 10.12\n} -returnCodes error -result {invalid arg \"-weight\": should be non-negative}\ntest grid-10.13 {column/row configure} -body {\n    grid columnconfigure . 0 -weight 3\n    grid columnconfigure . 0 -weight\n} -cleanup {\n    grid_reset 10.13\n} -result 3\ntest grid-10.14 {column/row configure} -body {\n    grid columnconfigure . 0 -pad foo\n} -cleanup {\n    grid_reset 10.14\n} -returnCodes error -result {expected screen distance but got \"foo\"}\ntest grid-10.15 {column/row configure} -body {\n    grid columnconfigure . 0 -pad -3\n} -cleanup {\n    grid_reset 10.15\n} -returnCodes error -result {invalid arg \"-pad\": should be non-negative}\ntest grid-10.16 {column/row configure} -body {\n    grid columnconfigure . 0 -pad 3\n    grid columnconfigure . 0 -pad\n} -cleanup {\n    grid_reset 10.16\n} -result 3\ntest grid-10.17 {column/row configure} -body {\n    frame .f\n    set a \"\"\n    grid columnconfigure .f 0 -weight 0\n    lappend a [grid columnconfigure .f 0 -weight]\n    grid columnconfigure .f 0 -weight 1\n    lappend a [grid columnconfigure .f 0 -weight]\n    grid rowconfigure .f 0 -weight 0\n    lappend a [grid rowconfigure .f 0 -weight]\n    grid rowconfigure .f 0 -weight 1\n    lappend a [grid columnconfigure .f 0 -weight]\n    grid columnconfigure .f 0 -weight 0\n    return $a\n} -cleanup {\n    grid_reset 10.17\n} -result {0 1 0 1}\ntest grid-10.18 {column/row configure} -body {\n    frame .f\n    grid columnconfigure .f {0 2} -minsize 10 -weight 1\n    list [grid columnconfigure .f 0 -minsize] \\\n\t[grid columnconfigure .f 1 -minsize] \\\n\t[grid columnconfigure .f 2 -minsize] \\\n\t[grid columnconfigure .f 0 -weight] \\\n\t[grid columnconfigure .f 1 -weight] \\\n\t[grid columnconfigure .f 2 -weight]\n} -cleanup {\n    grid_reset 10.18\n} -result {10 0 10 1 0 1}\ntest grid-10.19 {column/row configure} -body {\n    grid columnconfigure . {0 -1 2} -weight 1\n} -cleanup {\n    grid_reset 10.19\n} -returnCodes error -result {\"-1\" is out of range}\ntest grid-10.20 {column/row configure} -body {\n    grid columnconfigure . 0 -uniform foo\n    grid columnconfigure . 0 -uniform\n} -cleanup {\n    grid_reset 10.20\n} -result {foo}\ntest grid-10.21 {column/row configure} -body {\n    grid columnconfigure . .b -weight 1\n} -cleanup {\n    grid_reset 10.21\n} -returnCodes error -result {illegal index \".b\"}\ntest grid-10.22 {column/row configure} -body {\n    button .b\n    grid columnconfigure . .b -weight 1\n} -cleanup {\n    grid_reset 10.22\n} -returnCodes error -result {the window \".b\" is not managed by \".\"}\ntest grid-10.23 {column/row configure} -body {\n    button .b\n    grid .b -column 1 -columnspan 2\n    grid columnconfigure . .b -weight 1\n    set res {}\n    foreach i {0 1 2 3} {\n\tlappend res [grid columnconfigure . $i -weight]\n    }\n    return $res\n} -cleanup {\n    grid_reset 10.23\n} -result {0 1 1 0}\ntest grid-10.24 {column/row configure} -body {\n    button .b\n    button .c\n    button .d\n    grid .b -column 1 -columnspan 2\n    grid .c -column 2 -columnspan 3\n    grid .d -column 4 -columnspan 2\n    grid columnconfigure . {.b .d} -weight 1\n    grid columnconfigure . .c -weight 2\n    set res {}\n    foreach i {0 1 2 3 4 5 6} {\n\tlappend res [grid columnconfigure . $i -weight]\n    }\n    return $res\n} -cleanup {\n    grid_reset 10.24\n} -result {0 1 2 2 2 1 0}\ntest grid-10.25 {column/row configure} -body {\n    button .b\n    button .c\n    button .d\n    grid .b -row 1 -rowspan 2\n    grid .c -row 2 -rowspan 3\n    grid .d -row 4 -rowspan 2\n    grid rowconfigure . {7 all} -weight 1\n    grid rowconfigure . {1 .d} -weight 2\n    set res {}\n    foreach i {0 1 2 3 4 5 6 7} {\n\tlappend res [grid rowconfigure . $i -weight]\n    }\n    return $res\n} -cleanup {\n    grid_reset 10.25\n} -result {0 2 1 1 2 2 0 1}\ntest grid-10.26 {column/row configure} -body {\n    button .b\n    grid columnconfigure .b 0\n} -cleanup {\n    grid_reset 10.26\n} -result {-minsize 0 -pad 0 -uniform {} -weight 0}\ntest grid-10.27 {column/row configure - no indices} -body {\n    # Bug 1422430\n    set t [toplevel .test]\n    grid columnconfigure $t \"\" -weight 1\n} -cleanup {\n    destroy $t\n} -returnCodes error -result {no column indices specified}\ntest grid-10.28 {column/row configure - no indices} -body {\n    set t [toplevel .test]\n    grid rowconfigure $t \"\" -weight 1\n} -cleanup {\n    destroy $t\n} -returnCodes error -result {no row indices specified}\ntest grid-10.29 {column/row configure - invalid indices} -body {\n    grid columnconfigure . {0 1 2} -weight\n} -returnCodes error -result {must specify a single element on retrieval}\ntest grid-10.30 {column/row configure - invalid indices} -body {\n    grid rowconfigure . {0 1 2} -weight\n} -returnCodes error -result {must specify a single element on retrieval}\ntest grid-10.31 {column/row configure - empty 'all' configure} -body {\n    # Bug 1422430\n    set t [toplevel .test]\n    grid rowconfigure $t all -weight 1\n    destroy $t\n} -result {}\ntest grid-10.32 {column/row configure} -body {\n    # Test that no lingering message is there\n    frame .f\n    set res    [grid columnconfigure .f all -weight 1]\n    append res [grid columnconfigure .f {0 all} -weight 1]\n    frame .f.f\n    grid .f.f\n    append res [grid columnconfigure .f {.f.f} -weight 1]\n    append res [grid columnconfigure .f {.f.f 1} -weight 1]\n    append res [grid columnconfigure .f {2 .f.f} -weight 1]\n    destroy .f\n    return $res\n} -cleanup {\n    grid_reset 10.32\n} -result {}\ntest grid-10.33 {column/row configure} -body {\n    grid columnconfigure . all\n} -cleanup {\n    grid_reset 10.33\n} -returnCodes error -result {expected integer but got \"all\" (when retrieving options only integer indices are allowed)}\ntest grid-10.34 {column/row configure} -body {\n    grid columnconfigure . 100000\n} -cleanup {\n    grid_reset 10.34\n} -result {-minsize 0 -pad 0 -uniform {} -weight 0}\ntest grid-10.35 {column/row configure} -body {\n    # This is a test for bug 1423666 where a column >= 10000 caused\n    # a crash in layout.  The update is needed to reach the layout stage.\n    # Test different combinations of row/column overflow\n    frame .f\n    set res {}\n    lappend res [catch {grid .f -row 10 -column 9999} msg] $msg ; update\n    lappend res [catch {grid .f -row 9999 -column 10} msg] $msg ; update\n    lappend res [catch {grid .f -columnspan 2 -column 9998} msg] $msg ; update\n    lappend res [catch {grid .f -rowspan 2 -row 9998} msg] $msg ; update\n    lappend res [catch {grid .f -column 9998 -columnspan 2} msg] $msg ; update\n    lappend res [catch {grid .f -row 9998 -rowspan 2} msg] $msg ; update\n    return $res\n} -cleanup {\n    destroy .f\n    grid_reset 10.35\n} -result [lrange {\n    1 {column out of bounds}\n    1 {row out of bounds}\n    1 {column out of bounds}\n    1 {row out of bounds}\n    1 {column out of bounds}\n    1 {row out of bounds}\n} 0 end]\ntest grid-10.36 {column/row configure} -body {\n    # Additional tests for row/column overflow\n    frame .f\n    frame .g\n    set res {}\n    grid .f -row 9998 -column 0\n    lappend res [catch {grid ^ -in .} msg] $msg  ; update\n    lappend res [catch {grid .g} msg] $msg  ; update\n    grid forget .f .g\n    lappend res [catch {grid .f - -column 9998} msg] $msg ; update\n    grid forget .f .g\n    lappend res [catch {eval grid [string repeat \" x \" 9999] .f} msg] $msg\n    update\n    return $res\n} -cleanup {\n    destroy .f .g\n    grid_reset 10.36\n} -result [lrange {\n    1 {row out of bounds}\n    1 {row out of bounds}\n    1 {column out of bounds}\n    1 {column out of bounds}\n} 0 end]\n\n# auto-placement tests\ntest grid-11.1 {default widget placement} -body {\n    grid ^\n} -cleanup {\n    grid_reset 11.1\n} -returnCodes error -result {can't use '^', can't find container window}\ntest grid-11.2 {default widget placement} -body {\n    button .b\n    grid .b ^\n} -cleanup {\n    grid_reset 11.2\n} -returnCodes error -result {can't find content to extend with \"^\"}\ntest grid-11.3 {default widget placement} -body {\n    button .b\n    grid .b - - .c\n} -cleanup {\n    grid_reset 11.3\n} -returnCodes error -result {bad window path name \".c\"}\ntest grid-11.4 {default widget placement} -body {\n    button .b\n    grid .b - - = -\n} -cleanup {\n    grid_reset 11.4\n} -returnCodes error -result {invalid window shortcut, \"=\" should be '-', 'x', or '^'}\ntest grid-11.5 {default widget placement} -body {\n    button .b\n    grid .b - x -\n} -cleanup {\n    grid_reset 11.5\n} -returnCodes error -result {must specify window before shortcut '-'}\ntest grid-11.6 {default widget placement} -body {\n    foreach i {1 2 3 4 5 6} {\n\tframe .f$i -width 50 -height 50 -highlightthickness 0 -bg red\n    }\n    grid .f1 .f2 .f3 .f4\n    grid .f5   -  x  .f6 -sticky nsew\n    update\n    set a \"\"\n    foreach i {5 6} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.6\n} -result {{0,50  100,50} {150,50  50,50}}\ntest grid-11.7 {default widget placement} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -row 5 -column 5\n    grid .f x -\n} -cleanup {\n    grid_reset 11.7\n} -returnCodes error -result {must specify window before shortcut '-'}\ntest grid-11.8 {default widget placement} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -row 5 -column 5\n    grid .f ^ -\n} -cleanup {\n    grid_reset 11.8\n} -returnCodes error -result {must specify window before shortcut '-'}\ntest grid-11.9 {default widget placement} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -row 5 -column 5\n    grid .f x ^\n} -cleanup {\n    grid_reset 11.9\n} -returnCodes error -result {can't find content to extend with \"^\"}\ntest grid-11.10 {default widget placement} -body {\n    foreach i {1 2 3} {\n\tframe .f$i -width 100 -height 50 -highlightthickness 0 -bg red\n    }\n    grid .f1 .f2  -sticky nsew\n    grid .f3   ^  -sticky nsew\n    update\n    set a \"\"\n    foreach i {1 2 3} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.10\n} -result {{0,0  100,50} {100,0  100,100} {0,50  100,50}}\ntest grid-11.11 {default widget placement} -body {\n    foreach i {1 2 3 4 5 6 7 8 9 10 11 12} {\n\tframe .f$i -width 50 -height 50 -highlightthickness 1 -highlightbackground black\n    }\n    grid .f1  .f2  .f3 .f4  -sticky nsew\n    grid .f5  .f6   -  .f7  -sticky nsew\n    grid .f8    ^   ^  .f9  -sticky nsew\n    grid .f10   ^   ^  .f11 -sticky nsew\n    grid .f12   -   -   -   -sticky nsew\n    update\n    set a \"\"\n    foreach i {5 6 7 8 9 10 11 12 } {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.11\n} -result {{0,50  50,50} {50,50  100,150} {150,50  50,50} {0,100  50,50} {150,100  50,50} {0,150  50,50} {150,150  50,50} {0,200  200,50}}\ntest grid-11.12 {default widget placement} -body {\n    foreach i {1 2 3 4} {\n\tframe .f$i -width 75 -height 50 -highlightthickness 1 -highlightbackground black\n    }\n    grid .f1  .f2   .f3     -sticky nsew\n    grid .f4    ^           -sticky nsew\n    update\n    set a \"\"\n    foreach i {1 2 3 4} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    grid .f4    ^   -column 1\n    update\n    foreach i {1 2 3 4} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.12\n} -result {{0,0  75,50} {75,0  75,100} {150,0  75,50} {0,50  75,50} {0,0  75,50} {75,0  75,100} {150,0  75,100} {75,50  75,50}}\ntest grid-11.13 {default widget placement} -body {\n    foreach i {1 2 3 4 5 6 7} {\n\tframe .f$i -width 40 -height 50 -highlightthickness 1 -highlightbackground black\n    }\n    grid .f1  .f2  .f3 .f4 .f5 -sticky nsew\n    grid .f6    -  .f7         -sticky nsew -columnspan 2\n    update\n    set a \"\"\n    foreach i {6 7} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.13\n} -result {{0,50  120,50} {120,50  80,50}}\ntest grid-11.14 {default widget placement} -body {\n    foreach i {1 2 3} {\n\tframe .f$i -width 60 -height 60 -highlightthickness 0 -bg red\n    }\n    grid .f1 .f2\n    grid  ^  .f3\n    update\n    set a \"\"\n    foreach i {1 2 3} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i] \\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.14\n} -result {{0,30  60,60} {60,0  60,60} {60,60  60,60}}\ntest grid-11.15 {^ ^ test with multiple windows} -body {\n    foreach i {1 2 3 4} {\n\tframe .f$i -width 50 -height 50 -bd 1 -relief solid\n    }\n    grid .f1 .f2 .f3 -sticky ns\n    grid .f4 ^ ^\n    update\n    set a \"\"\n    foreach i {1 2 3 4} {\n\tlappend a \"[winfo x .f$i],[winfo y .f$i]\\\n\t\t[winfo width .f$i],[winfo height .f$i]\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 11.15\n} -result {{0,0 50,50} {50,0 50,100} {100,0 50,100} {0,50 50,50}}\ntest grid-11.16 {default widget placement} -body {\n    foreach l {a b c d e} {\n\tframe .$l -width 50 -height 50\n    }\n    grid .a .b .c .d -sticky news\n    grid  x  ^  x .e -sticky news\n    update\n    set res \"\"\n    lappend res [winfo height .a]\n    lappend res [winfo height .b]\n    lappend res [winfo height .c]\n} -cleanup {\n    grid_reset 11.16\n} -result {50 100 50}\ntest grid-11.17 {default widget placement} -body {\n    foreach l {a b c d e} {\n\tframe .$l -width 50 -height 50\n    }\n    grid .a .b .c .d -sticky news\n    grid  ^  x  ^ .e -sticky news\n    update\n    set res \"\"\n    lappend res [winfo height .a]\n    lappend res [winfo height .b]\n    lappend res [winfo height .c]\n} -cleanup {\n    grid_reset 11.17\n} -result {100 50 100}\ntest grid-11.18 {default widget placement} -body {\n    foreach l {a b c d e} {\n\tframe .$l -width 50 -height 50\n    }\n    grid .a .b .c .d -sticky news\n    grid  ^  ^  ^  x -in .           ;# ^ and no child should work with -in.\n    grid rowconfigure . {0 1} -uniform a\n    update\n    set res \"\"\n    lappend res [winfo height .a]\n    lappend res [winfo height .b]\n    lappend res [winfo height .c]\n    lappend res [winfo height .d]\n} -cleanup {\n    grid_reset 11.18\n} -result {100 100 100 50}\ntest grid-11.19 {default widget placement} -body {\n    foreach l {a b c d e} {\n\tframe .$l -width 50 -height 50\n    }\n    grid .a .b -sticky news\n    grid .c .d -sticky news\n    grid ^     -in . -row 2\n    grid x  ^  -in . -row 1\n    grid rowconfigure . {0 1 2} -uniform a\n    update\n    set res \"\"\n    lappend res [winfo height .a]\n    lappend res [winfo height .b]\n    lappend res [winfo height .c]\n    lappend res [winfo height .d]\n} -cleanup {\n    grid_reset 11.19\n} -result {50 100 100 50}\n\ntest grid-12.1 {-sticky} -body {\n    catch {unset data}\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    set a \"\"\n    grid .f\n    grid rowconfigure . 0 -weight 1\n    grid columnconfigure . 0 -weight 1\n    grid propagate . 0\n    . configure -width 250 -height 150\n    foreach i { {} n s e w ns ew nw ne se sw nse nsw sew new nsew} {\n\tgrid .f -sticky $i\n\tupdate\n\tarray set data [grid info .f]\n\tappend a \"($data(-sticky)) [winfo x .f] [winfo y .f] [winfo width .f] [winfo height .f]\\n\"\n    }\n    return $a\n} -cleanup {\n    grid_reset 12.1\n} -result {() 25 25 200 100\n(n) 25 0 200 100\n(s) 25 50 200 100\n(e) 50 25 200 100\n(w) 0 25 200 100\n(ns) 25 0 200 150\n(ew) 0 25 250 100\n(nw) 0 0 200 100\n(ne) 50 0 200 100\n(es) 50 50 200 100\n(sw) 0 50 200 100\n(nes) 50 0 200 150\n(nsw) 0 0 200 150\n(esw) 0 50 250 100\n(new) 0 0 250 100\n(nesw) 0 0 250 150\n}\ntest grid-12.2 {-sticky} -body {\n    frame .f -bg red\n    grid .f -sticky glue\n} -cleanup {\n    grid_reset 12.2\n} -returnCodes error -result {bad stickyness value \"glue\": must be a string containing n, e, s, and/or w}\ntest grid-12.3 {-sticky} -body {\n    frame .f -bg red\n    grid .f -sticky {n,s,e,w}\n    array set A [grid info .f]\n    set A(-sticky)\n} -cleanup {\n    grid_reset 12.3\n} -result {nesw}\n\ntest grid-13.1 {-in} -body {\n    frame .f -bg red\n    grid .f -in .f\n} -cleanup {\n    grid_reset 13.1\n} -returnCodes error -result {window can't be managed in itself}\ntest grid-13.2 {-in} -body {\n    frame .f -bg red\n    list [winfo manager .f] \\\n\t [catch {grid .f -in .f} err] $err \\\n\t [winfo manager .f]\n} -cleanup {\n    grid_reset 13.2\n} -result {{} 1 {window can't be managed in itself} {}}\ntest grid-13.3 {-in} -body {\n    frame .f -bg red\n    grid .f -in .bad\n} -cleanup {\n    grid_reset 13.3\n} -returnCodes error -result {bad window path name \".bad\"}\ntest grid-13.4 {-in} -body {\n    frame .f -bg red\n    toplevel .top\n    grid .f -in .top\n} -cleanup {\n    grid_reset 13.4\n    destroy .top\n} -returnCodes error -result {can't put \".f\" inside \".top\"}\ntest grid-13.5 {-ipadx} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -ipadx x\n} -cleanup {\n    grid_reset 13.5\n} -returnCodes error -result {bad ipadx value \"x\": must be positive screen distance}\ntest grid-13.6 {-ipadx} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -ipadx {5 5}\n} -cleanup {\n    grid_reset 13.6\n} -returnCodes error -result {bad ipadx value \"5 5\": must be positive screen distance}\ntest grid-13.7 {-ipadx} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a [winfo width .f]\n    grid .f -ipadx 1\n    update\n    list $a [winfo width .f]\n} -cleanup {\n    grid_reset 13.7\n} -result {200 202}\ntest grid-13.8 {-ipady} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -ipady x\n} -cleanup {\n    grid_reset 13.8\n} -returnCodes error -result {bad ipady value \"x\": must be positive screen distance}\ntest grid-13.9 {-ipady} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -ipady {5 5}\n} -cleanup {\n    grid_reset 13.9\n} -returnCodes error -result {bad ipady value \"5 5\": must be positive screen distance}\ntest grid-13.10 {-ipady} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a [winfo height .f]\n    grid .f -ipady 1\n    update\n    list $a [winfo height .f]\n} -cleanup {\n    grid_reset 13.10\n} -result {100 102}\ntest grid-13.11 {-padx} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -padx x\n} -cleanup {\n    grid_reset 13.11\n} -returnCodes error -result {bad pad value \"x\": must be positive screen distance}\ntest grid-13.12 {-padx} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -padx {10 x}\n} -cleanup {\n    grid_reset 13.12\n} -returnCodes error -result {bad 2nd pad value \"x\": must be positive screen distance}\ntest grid-13.13 {-padx} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a \"[winfo width .f] [winfo width .]\"\n    grid .f -padx 1\n    update\n    list $a \"[winfo width .f] [winfo width .] [winfo x .f]\"\n} -cleanup {\n    grid_reset 13.13\n} -result {{200 200} {200 202 1}}\ntest grid-13.14 {-padx} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a \"[winfo width .f] [winfo width .]\"\n    grid .f -padx {10 5}\n    update\n    list $a \"[winfo width .f] [winfo width .] [winfo x .f]\"\n} -cleanup {\n    grid_reset 13.14\n} -result {{200 200} {200 215 10}}\ntest grid-13.15 {-pady} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -pady x\n} -cleanup {\n    grid_reset 13.15\n} -returnCodes error -result {bad pad value \"x\": must be positive screen distance}\ntest grid-13.16 {-pady} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid .f -pady {10 x}\n} -cleanup {\n    grid_reset 13.16\n} -returnCodes error -result {bad 2nd pad value \"x\": must be positive screen distance}\ntest grid-13.17 {-pady} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a \"[winfo height .f] [winfo height .]\"\n    grid .f -pady 1\n    update\n    list $a \"[winfo height .f] [winfo height .] [winfo y .f]\"\n} -cleanup {\n    grid_reset 13.17\n} -result {{100 100} {100 102 1}}\ntest grid-13.18 {-pady} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    update\n    set a \"[winfo height .f] [winfo height .]\"\n    grid .f -pady {4 16}\n    update\n    list $a \"[winfo height .f] [winfo height .] [winfo y .f]\"\n} -cleanup {\n    grid_reset 13.18\n} -result {{100 100} {100 120 4}}\ntest grid-13.19 {-ipad x and y} -body {\n    frame .f -width 20 -height 20 -highlightthickness 0 -bg red\n    grid columnconfigure . 0 -minsize 150\n    grid rowconfigure . 0 -minsize 100\n    set a \"\"\n    foreach x {0 5} {\n\tforeach y {0 5} {\n\t    grid .f -ipadx $x -ipady $y\n\t    update\n\t    append a \" $x,$y:\"\n\t    foreach prop {x y width height} {\n\t\tappend a ,[winfo $prop .f]\n\t    }\n\t}\n    }\n    return $a\n} -cleanup {\n    grid_reset 13.19\n} -result { 0,0:,65,40,20,20 0,5:,65,35,20,30 5,0:,60,40,30,20 5,5:,60,35,30,30}\ntest grid-13.20 {reparenting} -body {\n    frame .1\n    frame .2\n    button .b\n    grid .1 .2\n    grid .b -in .1\n    set a \"\"\n    catch {unset info}; array set info [grid info .b]\n    lappend a [grid content .1],[grid content .2],$info(-in)\n    grid .b -in .2\n    catch {unset info}; array set info [grid info .b]\n    lappend a [grid content .1],[grid content .2],$info(-in)\n    unset info\n    return $a\n} -cleanup {\n    grid_reset 13.20\n} -result {.b,,.1 ,.b,.2}\n\ntest grid-14.1 {structure notify} -body {\n    frame .f -width 200 -height 100 -highlightthickness 0 -bg red\n    frame .g -width 200 -height 100 -highlightthickness 0 -bg red\n    grid .f\n    grid .g -in .f\n    update\n    set a \"\"\n    lappend a \"[winfo x .g],[winfo y .g] \\\n\t[winfo width .g],[winfo height .g]\"\n    .f configure -bd 5 -relief raised\n    update\n    lappend a \"[winfo x .g],[winfo y .g] \\\n\t[winfo width .g],[winfo height .g]\"\n    return $a\n} -cleanup {\n    grid_reset 14.1\n} -result {{0,0  200,100} {5,5  200,100}}\ntest grid-14.2 {structure notify} -body {\n    frame .f -width 200 -height 100\n    frame .f.g -width 200 -height 100\n    grid .f\n    grid .f.g\n    update\n    set a \"\"\n    lappend a [grid bbox .],[grid bbox .f]\n    .f config -bd 20\n    update\n    lappend a [grid bbox .],[grid bbox .f]\n} -cleanup {\n    grid_reset 14.2\n} -result {{0 0 200 100,0 0 200 100} {0 0 240 140,20 20 200 100}}\ntest grid-14.3 {map notify: bug 1648} -constraints {nonPortable} -body {\n    # This test is nonPortable because the number of times\n    # A(.) will be incremented is unspecified--the behavior\n    # is different accross window managers.\n    global A\n    catch {unset A}\n    bind . <Configure> {incr A(%W)}\n    set A(.) 0\n    foreach i {0 1 2} {\n\tframe .$i -width 100 -height 75\n\tset A(.$i) 0\n    }\n    grid .0 .1 .2\n    update\n    bind <Configure> .1 {destroy .0}\n    .2 configure -bd 10\n    update\n    bind . <Configure> {}\n    array get A\n} -cleanup {\n    grid_reset 14.3\n} -result {.2 2 .0 1 . 2 .1 1}\n\ntest grid-15.1 {lost content} -body {\n    button .b\n    grid .b\n    set a [grid content .]\n    pack .b\n    lappend a [grid content .]\n    grid .b\n    lappend a [grid content .]\n} -cleanup {\n    grid_reset 15.1\n} -result {.b {} .b}\ntest grid-15.2 {lost content} -body {\n    frame .f\n    grid .f\n    button .b\n    grid .b -in .f\n    set a [grid content .f]\n    pack .b -in .f\n    lappend a [grid content .f]\n    grid .b -in .f\n    lappend a [grid content .f]\n} -cleanup {\n    grid_reset 15.2\n} -result {.b {} .b}\n\ntest grid-16.1 {layout centering} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 75 -height 50 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n    }\n    grid propagate . 0\n    grid anchor . center\n    . configure -width 300 -height 250\n    update\n    grid bbox .\n} -cleanup {\n    grid_reset 16.1\n} -result {37 50 225 150}\ntest grid-16.2 {layout weights (expanding)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 75 -height 50 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n\tgrid rowconfigure . $i -weight [expr {$i + 1}]\n\tgrid columnconfigure . $i -weight [expr {$i + 1}]\n    }\n    grid propagate . 0\n    . configure -width 500 -height 300\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.2\n} -result {120-75 167-100 213-125}\ntest grid-16.3 {layout weights (shrinking)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n\tgrid rowconfigure . $i -weight [expr {$i + 1}]\n\tgrid columnconfigure . $i -weight [expr {$i + 1}]\n    }\n    grid propagate . 0\n    . configure -width 200 -height 150\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.3\n} -result {84-63 66-50 50-37}\ntest grid-16.4 {layout weights (shrinking with minsize)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n\tgrid rowconfigure . $i -weight [expr {$i + 1}] -minsize 45\n\tgrid columnconfigure . $i -weight [expr {$i + 1}] -minsize 65\n    }\n    grid propagate . 0\n    . configure -width 200 -height 150\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.4\n} -result {70-60 65-45 65-45}\ntest grid-16.5 {layout weights (shrinking at minsize)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n\tgrid rowconfigure . $i -weight 0 -minsize 70\n\tgrid columnconfigure . $i -weight 0 -minsize 90\n    }\n    grid propagate . 0\n    . configure -width 100 -height 75\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.5\n} -result {100-75 100-75 100-75}\ntest grid-16.6 {layout weights (shrinking at minsize)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n\tgrid rowconfigure . $i -weight [expr {$i + 1}] -minsize 52\n\tgrid columnconfigure . $i -weight [expr {$i + 1}] -minsize 69\n    }\n    grid propagate . 0\n    . configure -width 200 -height 150\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.6\n} -result {69-52 69-52 69-52}\n# test fails when run alone\n# reason (I think): -minsize 0 causes both:\n# [winfo ismapped .$i] => 0 and\n# not responding for width ang height settings, so that\n# [winfo width .$i] [winfo height .$i] take different values\n# That doesn't happen if previous tests run\ntest grid-16.7 {layout weights (shrinking at minsize)} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n    }\n    grid propagate . 0\n    grid columnconfigure . 1 -weight 1 -minsize 0\n    grid rowconfigure . 1 -weight 1 -minsize 0\n    . configure -width 100 -height 1\n    set a \"\"\n    update\n    foreach i {0 1 2} {\n\tlappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.7\n} -result {100-75-1 1-1-0 100-75-1}\ntest grid-16.8 {layout internal constraints} -body {\n    foreach i {0 1 2 3 4} {\n\tframe .$i -bg gray  -width 30 -height 25 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n    }\n    frame .f -bg red -width 250 -height 200\n    frame .g -bg green -width 200 -height 180\n    lower .f\n    raise .g .f\n    grid .f -row 1 -column 1 -rowspan 3 -columnspan 3 -sticky nswe\n    grid .g -row 1 -column 1 -rowspan 2 -columnspan 2 -sticky nswe\n    update\n    set a \"\"\n    foreach i {0 1 2 3 4} {\n\tappend a \"[winfo x .$i] \"\n    }\n    append a \", \"\n    grid remove .f\n    update\n    foreach i {0 1 2 3 4} {\n\tappend a \"[winfo x .$i] \"\n    }\n    append a \", \"\n    grid remove .g\n    grid .f\n    update\n    foreach i {0 1 2 3 4} {\n\tappend a \"[winfo x .$i] \"\n    }\n    append a \", \"\n    grid remove .f\n    update\n    foreach i {0 1 2 3 4} {\n\tappend a \"[winfo x .$i] \"\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.8\n} -result {0 30 130 230 280 , 0 30 130 230 260 , 0 30 113 196 280 , 0 30 60 90 120 }\ntest grid-16.9 {layout uniform} -body {\n    frame .f1 -width 75 -height 50\n    frame .f2 -width 60 -height 25\n    frame .f3 -width 95 -height 75\n    frame .f4 -width 135 -height 100\n    frame .f5 -width 80 -height 40\n    for {set t 1} {$t <= 5} {incr t} {\n\tgrid .f$t\n    }\n    grid rowconfigure . {0 2} -uniform a\n    grid rowconfigure . {1 3} -uniform b\n    update\n    list [grid bbox . 0 0] [grid bbox . 0 1] [grid bbox . 0 2] \\\n\t    [grid bbox . 0 3] [grid bbox . 0 4]\n} -cleanup {\n    grid_reset 16.9\n} -result {{0 0 135 75} {0 75 135 100} {0 175 135 75} {0 250 135 100} {0 350 135 40}}\ntest grid-16.10 {layout uniform} -body {\n    grid [frame .f1 -width  75 -height  50] -row 0 -column 0\n    grid [frame .f2 -width  60 -height  30] -row 1 -column 2\n    grid [frame .f3 -width  95 -height  90] -row 2 -column 1\n    grid [frame .f4 -width  60 -height 100] -row 3 -column 4\n    grid [frame .f5 -width  60 -height  40] -row 4 -column 3\n    grid rowconfigure . {0 1} -uniform a\n    grid rowconfigure . {2 4} -uniform b\n    grid rowconfigure . {0 2} -weight 2\n    grid columnconfigure . {0 2} -uniform a\n    grid columnconfigure . {3 4} -uniform b\n    grid columnconfigure . {2 4} -weight 2\n    grid columnconfigure . 3 -minsize 70\n    grid columnconfigure . 4 -minsize 130\n    update\n    list [grid bbox . 0 0] [grid bbox . 2 1] [grid bbox . 1 2] \\\n\t    [grid bbox . 4 3] [grid bbox . 3 4]\n} -cleanup {\n    grid_reset 16.10\n} -result {{0 0 75 60} {170 60 150 30} {75 90 95 90} {390 180 140 100} {320 280 70 45}}\ntest grid-16.11 {layout uniform (shrink)} -body {\n    frame .f1 -width 75 -height 50\n    frame .f2 -width 100 -height 95\n    grid .f1 .f2 -sticky news\n    grid columnconfigure . {0 1} -uniform a\n    grid columnconfigure . 0 -weight 1\n    update\n    set res {}\n    lappend res [grid bbox . 0 0] [grid bbox . 1 0]\n    grid propagate . 0\n    . configure -width 150 -height 95\n    update\n    lappend res [grid bbox . 0 0] [grid bbox . 1 0]\n} -cleanup {\n    grid_reset 16.11\n} -result {{0 0 100 95} {100 0 100 95} {0 0 50 95} {50 0 100 95}}\ntest grid-16.12 {layout uniform (grow)} -body {\n    frame .f1 -width 40 -height 50\n    frame .f2 -width 50 -height 95\n    frame .f3 -width 60 -height 50\n    frame .f4 -width 70 -height 95\n    grid .f1 .f2 .f3 .f4 -sticky news\n    grid columnconfigure . {0 1 2} -uniform a\n    # Put weight 2 on the biggest in the group to see that the groups\n    # adapt to one of the smaller.\n    grid columnconfigure . 2 -weight 2\n    grid columnconfigure . {0 3} -weight 1\n    update\n    set res {}\n    lappend res [grid bbox . 0 0] [grid bbox . 1 0]\n    lappend res [grid bbox . 2 0] [grid bbox . 3 0]\n    grid propagate . 0\n    . configure -width 350 -height 95\n    update\n    lappend res [grid bbox . 0 0] [grid bbox . 1 0]\n    lappend res [grid bbox . 2 0] [grid bbox . 3 0]\n} -cleanup {\n    grid_reset 16.12\n} -result [list {0 0 50 95} {50 0 50 95} {100 0 100 95} {200 0 70 95} \\\n\t{0 0 70 95} {70 0 50 95} {120 0 140 95} {260 0 90 95}]\ntest grid-16.13 {layout span} -body {\n    frame .f1 -width 24 -height 20\n    frame .f2 -width 38 -height 20\n    frame .f3 -width 150 -height 20\n    grid .f1 - - .f2\n    grid .f3 - - -\n    set res {}\n    foreach w {{0 1 0 0} {0 0 1 0} {1 3 4 0} {1 2 1 2} {1 1 1 12}} {\n\tfor {set c 0} {$c < 4} {incr c} {\n\t    grid columnconfigure . $c -weight [lindex $w $c]\n\t}\n\tupdate\n\tset res2 {}\n\tfor {set c 0} {$c <= 4} {incr c} {\n\t    lappend res2 [lindex [grid bbox . $c 0] 2]\n\t}\n\tlappend res $res2\n    }\n    return $res\n    # The last result below should ideally be 8 8 8 126 but the current\n    # implementation is not exact enough.\n} -cleanup {\n    grid_reset 16.13\n} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 14 42 56 38 0] \\\n\t   [list 18 38 18 76 0] [list 7 8 9 126 0]]\ntest grid-16.14 {layout span} -body {\n    frame .f1 -width 110 -height 20\n    frame .f2 -width 38 -height 20\n    frame .f3 -width 150 -height 20\n    grid .f1 - - .f2\n    grid .f3 - - -\n    set res {}\n    foreach w {{0 1 0 0} {0 0 1 0} {1 3 4 0} {1 2 1 3} {1 1 1 12}} {\n\tfor {set c 0} {$c < 4} {incr c} {\n\t    grid columnconfigure . $c -weight [lindex $w $c]\n\t}\n\tupdate\n\tset res2 {}\n\tfor {set c 0} {$c <= 4} {incr c} {\n\t    lappend res2 [lindex [grid bbox . $c 0] 2]\n\t}\n\tlappend res $res2\n    }\n    return $res\n} -cleanup {\n    grid_reset 16.14\n} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 14 42 56 38 0] \\\n\t   [list 27 55 28 40 0] [list 36 37 37 40 0]]\ntest grid-16.15 {layout span} -body {\n    frame .f1 -width 24 -height 20\n    frame .f2 -width 38 -height 20\n    frame .f3 -width 150 -height 20\n    grid .f1 - - .f2\n    grid x .f3 - -\n    set res {}\n    foreach w {{0 1 0 0} {0 0 1 0} {1 0 1 0} {0 0 0 0} {1 0 0 6}} {\n\tfor {set c 0} {$c < 4} {incr c} {\n\t    grid columnconfigure . $c -weight [lindex $w $c]\n\t}\n\tupdate\n\tset res2 {}\n\tfor {set c 0} {$c <= 4} {incr c} {\n\t    lappend res2 [lindex [grid bbox . $c 0] 2]\n\t}\n\tlappend res $res2\n    }\n    return $res\n} -cleanup {\n    grid_reset 16.15\n} -result [list [list 0 112 0 38 0] [list 0 0 112 38 0] [list 0 0 112 38 0] \\\n\t   [list 0 37 37 76 0] [list 0 12 12 126 0]]\ntest grid-16.16 {layout span} -body {\n    frame .f1 -width 64 -height 20\n    frame .f2 -width 38 -height 20\n    frame .f3 -width 150 -height 20\n    frame .f4 -width 15 -height 20\n    frame .f5 -width 18 -height 20\n    frame .f6 -width 20 -height 20\n    grid .f1 - x .f2\n    grid .f3 - - -\n    grid .f4 .f5 .f6\n    set res {}\n    foreach w {{1 1 5 1} {0 0 1 0} {1 3 4 0} {1 2 1 2} {1 1 1 12}} {\n\tfor {set c 0} {$c < 4} {incr c} {\n\t    grid columnconfigure . $c -weight [lindex $w $c]\n\t}\n\tupdate\n\tset res2 {}\n\tfor {set c 0} {$c <= 4} {incr c} {\n\t    lappend res2 [lindex [grid bbox . $c 0] 2]\n\t}\n\tlappend res $res2\n    }\n    return $res\n} -cleanup {\n    grid_reset 16.16\n} -result [list [list 30 34 43 43 0] [list 30 34 48 38 0] [list 22 42 48 38 0] \\\n\t   [list 25 39 29 57 0] [list 30 34 22 64 0]]\ntest grid-16.17 {layout weights (shrinking at minsize)} -body {\n    foreach i {0 1 2 3} {\n\tframe .$i -bg gray  -width 100 -height 75 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n    }\n    grid propagate . 0\n    grid columnconfigure . {0 1} -weight 1 -minsize 0\n    grid rowconfigure . {0 1} -weight 1 -minsize 0\n    set a \"\"\n    . configure -width 250 -height 200\n    update\n    foreach i {0 1 2 3} {\n\tlappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]\n    }\n    . configure -width 150 -height 100\n    update\n    foreach i {0 1 2 3} {\n\tlappend a [winfo width .$i]-[winfo height .$i]-[winfo ismapped .$i]\n    }\n    return $a\n} -cleanup {\n    grid_reset 16.17\n} -result {25-25-1 25-25-1 100-75-1 100-75-1 25-25-0 25-25-0 100-75-1 100-75-1}\ntest grid-16.18 {layout span} -body {\n    frame .f1 -width 30  -height 20\n    frame .f2 -width 166 -height 20\n    frame .f3 -width 39  -height 20\n    frame .f4 -width 10  -height 20\n    grid .f1 .f3 -\n    grid .f2 -   .f4\n    grid columnconfigure . 0 -weight 1\n    set res {}\n    foreach w {{1 0 0} {0 1 0} {0 0 1}} {\n\tfor {set c 0} {$c < 3} {incr c} {\n\t    grid columnconfigure . $c -weight [lindex $w $c]\n\t}\n\tupdate\n\tset res2 {}\n\tfor {set c 0} {$c <= 2} {incr c} {\n\t    lappend res2 [lindex [grid bbox . $c 0] 2]\n\t}\n\tlappend res $res2\n    }\n    return $res\n} -cleanup {\n    grid_reset 16.18\n} -result [list [list 137 29 10] [list 30 136 10] [list 98 68 10]]\ntest grid-16.19 {layout span} -constraints { knownBug } -body {\n    # This test shows the problem in Bug 2075285\n    # Several overlapping multi-span widgets is a weak spot\n    # in the current implementation.\n    # Test present as a reminder in case a future algorithm update is made.\n    frame .f1 -width 100 -height 20\n    frame .f2 -width 20  -height 20\n    frame .f3 -width 10  -height 20\n    frame .f4 -width 20  -height 20\n    grid .f1 - -   - -   - -sticky we\n    grid .f2 - .f3 - .f4 - -sticky we\n    grid columnconfigure . {1 5} -weight 1\n    set res {}\n    update\n    for {set c 0} {$c <= 5} {incr c} {\n\tlappend res [lindex [grid bbox . $c 0] 2]\n    }\n    return $res\n} -cleanup {\n    grid_reset 16.19\n} -result [list 0 45 5 5 0 45]\n\ntest grid-17.1 {forget and pending idle handlers} -body {\n    # This test is intended to detect a crash caused by a failure to remove\n    # pending idle handlers when grid forget is invoked.\n    toplevel .t\n    wm geometry .t +0+0\n    frame .t.f\n    label .t.f.l -text foobar\n    grid .t.f.l\n    grid .t.f\n    update\n    grid forget .t.f.l\n    grid forget .t.f\n    destroy .t\n    toplevel .t\n    frame .t.f\n    label .t.f.l -text foobar\n    grid .t.f.l\n    destroy .t\n    set result ok\n} -result ok\n\ntest grid-18.1 {test respect for internalborder} -body {\n    toplevel .pack\n    wm geometry .pack 200x200\n    frame .pack.l -width 15 -height 10\n    labelframe .pack.lf -labelwidget .pack.l\n    pack .pack.lf -fill both -expand 1\n    frame .pack.lf.f\n    grid .pack.lf.f -sticky news\n    grid columnconfigure .pack.lf 0 -weight 1\n    grid rowconfigure .pack.lf 0 -weight 1\n    update\n    set res [list [winfo geometry .pack.lf.f]]\n    .pack.lf configure -labelanchor e -padx 3 -pady 5\n    update\n    lappend res [winfo geometry .pack.lf.f]\n    destroy .pack\n    return $res\n} -result {196x188+2+10 177x186+5+7}\ntest grid-18.2 {test support for minreqsize} -body {\n    toplevel .pack\n    wm geometry .pack {}\n    frame .pack.l -width 150 -height 100\n    labelframe .pack.lf -labelwidget .pack.l\n    pack .pack.lf -fill both -expand 1\n    frame .pack.lf.f -width 20 -height 25\n    grid .pack.lf.f\n    update\n    set res [list [winfo geometry .pack.lf]]\n    .pack.lf configure -labelanchor ws\n    update\n    lappend res [winfo geometry .pack.lf]\n    destroy .pack\n    return $res\n} -result {162x127+0+0 172x112+0+0}\n\ntest grid-19.1 {uniform realloc} -body {\n    # Use a lot of uniform groups to test the reallocation mechanism\n    for {set t 0} {$t < 100} {incr t 2} {\n\tframe .fa$t -width 5 -height 20\n\tframe .fb$t -width 6 -height 20\n\tgrid .fa$t .fb$t -row 0 -column $t -sticky news\n\tgrid columnconfigure . [list $t [expr {$t + 1}]] -uniform a$t\n    }\n    update\n    grid bbox .\n} -cleanup {\n    grid_reset 19.1\n} -result {0 0 600 20}\n\ntest grid-20.1 {recalculate size after removal (destroy)} -body {\n    label .l1 -text l1\n    grid .l1 -row 2 -column 2\n    destroy .l1\n    label .l2 -text l2\n    grid .l2\n    grid size .\n} -cleanup {\n    grid_reset 20.1\n} -result {1 1}\ntest grid-20.2 {recalculate size after removal (forget)} -body {\n    label .l1 -text l1\n    grid .l1 -row 2 -column 2\n    grid forget .l1\n    label .l2 -text l2\n    grid .l2\n    grid size .\n} -cleanup {\n    grid_reset 20.2\n} -result {1 1}\n\ntest grid-21.1 {anchor} -body {\n    grid anchor . 1 xxx\n} -cleanup {\n    grid_reset 21.1\n} -returnCodes error -result {wrong # args: should be \"grid anchor window ?anchor?\"}\ntest grid-21.2 {anchor} -body {\n    grid anchor .\n} -cleanup {\n    grid_reset 21.2\n} -result {nw}\ntest grid-21.3 {anchor} -body {\n    grid anchor . se;grid anchor .\n} -cleanup {\n    grid_reset 21.3\n} -result {se}\ntest grid-21.4 {anchor} -body {\n    grid anchor .x\n} -cleanup {\n    grid_reset 21.4\n} -returnCodes error -result {bad window path name \".x\"}\ntest grid-21.5 {anchor} -body {\n    grid anchor . x\n} -cleanup {\n    grid_reset 21.5\n} -returnCodes error -result {bad anchor \"x\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest grid-21.6 {anchor} -body {\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 75 -height 50 -bd 2 -relief ridge\n\tgrid .$i -row $i -column $i -sticky nswe\n    }\n    grid propagate . 0\n    . configure -width 300 -height 250\n    set res {}\n    foreach a {n ne e se s sw w nw center} {\n\tgrid anchor . $a\n\tupdate\n\tlappend res [grid bbox .]\n    }\n    return $res\n} -cleanup {\n    grid_reset 21.6\n} -result [list {37 0 225 150} {75 0 225 150} {75 50 225 150} {75 100 225 150} \\\n\t   {37 100 225 150} {0 100 225 150} {0 50 225 150} {0 0 225 150} \\\n\t   {37 50 225 150}]\ntest grid-21.7 {anchor} -body {\n    # Test with a non-symmetric internal border.\n    # This only tests vertically, there is currently no way to get\n    # it assymetric horizontally.\n    labelframe .f -bd 0\n    frame .f.x -width 20 -height 20\n    .f configure -labelwidget .f.x\n    pack .f -fill both -expand 1\n    foreach i {0 1 2} {\n\tframe .$i -bg gray  -width 75 -height 50 -bd 2 -relief ridge\n\tgrid .$i -in .f -row $i -column $i -sticky nswe\n    }\n    pack propagate . 0\n    grid propagate .f 0\n    . configure -width 300 -height 250\n    set res {}\n    foreach a {n ne e se s sw w nw center} {\n\tgrid anchor .f $a\n\tupdate\n\tlappend res [grid bbox .f]\n    }\n    pack propagate . 1 ; wm geometry . {}\n    return $res\n} -cleanup {\n    grid_reset 21.7\n} -result [list {37 20 225 150} {75 20 225 150} {75 60 225 150} {75 100 225 150} \\\n\t   {37 100 225 150} {0 100 225 150} {0 60 225 150} {0 20 225 150} \\\n\t   {37 60 225 150}]\n\ntest grid-22.1 {remove: basic argument checking} {\n    list [catch {grid remove foo} msg] $msg\n} {1 {bad window path name \"foo\"}}\ntest grid-22.2 {remove} -body {\n    button .c\n    grid [button .b]\n    set a [grid content .]\n    grid remove .b .c\n    lappend a [grid content .]\n    return $a\n} -cleanup {\n    grid_reset 22.2\n} -result {.b {}}\ntest grid-22.3 {remove} -body {\n    button .c\n    grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns\n    grid remove .c\n    grid .c -row 0 -column 0\n    grid info .c\n} -cleanup {\n    grid_reset 22.3\n} -result {-in . -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx 3 -pady 4 -sticky ns}\ntest grid-22.3.1 {remove} -body {\n    frame .a\n    button .c\n    grid .c -in .a -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns\n    grid remove .c\n    grid .c -row 0 -column 0\n    grid info .c\n} -cleanup {\n    grid_reset 22.3.1\n} -result {-in .a -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx {3 5} -pady {4 7} -sticky ns}\ntest grid-22.4 {remove, calling Tk_UnmaintainGeometry} -body {\n    frame .f -bd 2 -relief raised\n    place .f -x 10 -y 20 -width 200 -height 100\n    frame .f2 -width 50 -height 30 -bg red\n    grid .f2 -in .f\n    update\n    set x [winfo ismapped .f2]\n    grid remove .f2\n    place .f -x 30\n    update\n    lappend x [winfo ismapped .f2]\n} -cleanup {\n    grid_reset 22.4\n} -result {1 0}\ntest grid-22.5 {remove} -body {\n    frame .a\n    button .c\n    grid .c -in .a -row 2 -column 2 -rowspan 2 -columnspan 2 -padx {3 5} -pady {4 7} -sticky ns\n    grid remove .c\n    # If .a was destroyed while remembered by the removed .c, make sure it\n    # is ignored.\n    destroy .a\n    grid .c -row 0 -column 0\n    grid info .c\n} -cleanup {\n    grid_reset 22.5\n} -result {-in . -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx {3 5} -pady {4 7} -sticky ns}\n\ntest grid-23 {grid configure -in leaked from previous container window - bug\n\t      6aea69fccbb266b7f0437686379fbe5b55442958} -body {\n    frame .f\n    frame .g\n    pack .f .g\n    text .t\n    grid .t -in .f\n    pack forget .f\n    update\n    grid .t -in .g\n    # .t is now managed by .g; following lines must have no effect on .t\n    pack .f\n    update\n    pack forget .f\n    update\n    winfo ismapped .t ; # must return 1\n} -cleanup {\n    grid_reset 23\n} -result 1\n\ntest grid-24.1 {<<NoManagedChild>> fires on last grid forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    grid forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.1\n} -result 1\ntest grid-24.2 {<<NoManagedChild>> fires on last grid remove} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    grid remove .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.2\n} -result 1\ntest grid-24.3 {<<NoManagedChild>> fires on last gridded child destruction} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    update\n    bind . <<NoManagedChild>> {incr A}\n    destroy .1\n    update\n    set A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.3\n} -result 1\ntest grid-24.4 {<Configure> does not fire on last grid forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    update\n    bind . <Configure> {set A 1}\n    grid forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <Configure> {}\n    grid_reset 24.4\n} -result 0\ntest grid-24.5 {<Configure> fires on forelast grid forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    grid [frame .2]\n    update\n    bind . <Configure> {set A 1}\n    grid forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <Configure> {}\n    grid_reset 24.5\n} -result 1\ntest grid-24.6 {<<NoManagedChild>> does not fire on forelast grid forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    grid [frame .2]\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    grid forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.6\n} -result 0\ntest grid-24.7 {<<NoManagedChild>> does not fire on grid anchor} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    bind . <<NoManagedChild>> {set A 1}\n    grid anchor . w\n    update\n    info exists A\n} -cleanup {\n    grid anchor . nw\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.7\n} -result 0\ntest grid-24.8 {<<NoManagedChild>> does not fire on last grid forget if propagation is off} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    grid [frame .1]\n    grid propagate . 0\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    grid forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    grid_reset 24.8\n} -result 0\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/image.test",
    "content": "# This file is a Tcl script to test out the \"image\" command and the\n# other procedures in the file tkImage.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n\n# Canvas used in some tests in the whole file\ncanvas .c -highlightthickness 2\npack .c\nupdate\n\n#\n# TESTS\n#\n\ntest image-1.1 {Tk_ImageCmd procedure, \"create\" option} -body {\n    image\n} -returnCodes error -result {wrong # args: should be \"image option ?args?\"}\ntest image-1.2 {Tk_ImageCmd procedure, \"create\" option} -body {\n    image gorp\n} -returnCodes error -result {bad option \"gorp\": must be create, delete, height, inuse, names, type, types, or width}\ntest image-1.3 {Tk_ImageCmd procedure, \"create\" option} -body {\n    image create\n} -returnCodes error -result {wrong # args: should be \"image create type ?name? ?-option value ...?\"}\ntest image-1.4 {Tk_ImageCmd procedure, \"create\" option} -body {\n    image c bad_type\n} -returnCodes error -result {image type \"bad_type\" does not exist}\ntest image-1.5 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n    testImageType\n} -body {\n    list [image create test myimage] [imageNames]\n} -cleanup {\n    imageCleanup\n} -result {myimage myimage}\ntest image-1.6 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    scan [image create test] image%d first\n    image create test myimage\n    scan [image create test -variable x] image%d second\n    expr {$second-$first}\n} -cleanup {\n    imageCleanup\n} -result 1\n\ntest image-1.7 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage -variable x\n    .c create image 100 50 -image myimage\n    .c create image 100 150 -image myimage\n    update\n    set x {}\n    set timer [after 500 {lappend x \"timed out\"}]\n    image create test myimage -variable x\n    update idletasks\n    update\n    # On MacOS we need to wait for the test image display procedure to run.\n    while {\"timed out\" ni $x && [lindex $x end 1] ne \"display\"} {\n\tvwait x\n    }\n    after cancel timer\n    if {[lindex $x end] eq \"timed out\"} {\n       return [lreplace $x end end]\n    }\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{myimage free} {myimage free} {myimage delete} {myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}\ntest image-1.8 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n\ttestImageType\n} -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create test myimage -variable x\n    .c create image 100 50 -image myimage\n    .c create image 100 150 -image myimage\n    image delete myimage\n    update\n    set x {}\n    set timer [after 500 {lappend x \"timed out\"}]\n    image create test myimage -variable x\n    vwait x\n    after cancel $timer\n    return $x\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {{myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}\ntest image-1.9 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n\ttestImageType\n} -body {\n    image create test -badName foo\n} -returnCodes error -result {bad option name \"-badName\"}\ntest image-1.10 {Tk_ImageCmd procedure, \"create\" option} -constraints {\n    testImageType\n} -body {\n    catch {image create test -badName foo}\n    imageNames\n} -result {}\ntest image-1.11 {Tk_ImageCmd procedure, \"create\" option with same name as main window} -body {\n    set code [loadTkCommand]\n    append code {\n\t    update\n\t    puts [list [catch {image create photo .} msg] $msg]\n\t    exit\n    }\n    set script [makeFile $code script]\n    exec [interpreter] <$script\n} -cleanup {\n    removeFile script\n} -result {1 {images may not be named the same as the main window}}\ntest image-1.12 {Tk_ImageCmd procedure, \"create\" option with same name as main window after renaming} -body {\n    set code [loadTkCommand]\n    append code {\n\t    update\n\t    puts [list [catch {rename . foo;image create photo foo} msg] $msg]\n\t    exit\n    }\n    set script [makeFile $code script]\n    exec [interpreter] <$script\n} -cleanup {\n    removeFile script\n} -result {1 {images may not be named the same as the main window}}\ntest image-1.13 {Tk_ImageCmd, \"create\" option: do not generated command name in use} -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    set i [image create bitmap]\n    regexp {^image(\\d+)$} $i -> serial\n    incr serial\n    proc image$serial {} {return works}\n    set j [image create bitmap]\n\n    image$serial\n} -cleanup {\n    rename image$serial {}\n    image delete $i $j\n} -result works\n\ntest image-2.1 {Tk_ImageCmd procedure, \"delete\" option} -body {\n    image delete\n} -result {}\ntest image-2.2 {Tk_ImageCmd procedure, \"delete\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n    set result {}\n} -body {\n    image create test myimage\n    image create test img2\n    lappend result [lsort [imageNames]]\n    image d myimage img2\n    lappend result [imageNames]\n} -cleanup {\n    imageCleanup\n} -result {{img2 myimage} {}}\ntest image-2.3 {Tk_ImageCmd procedure, \"delete\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    image create test img2\n    image delete myimage gorp img2\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image \"gorp\" does not exist}\ntest image-2.4 {Tk_ImageCmd procedure, \"delete\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    image create test img2\n    catch {image delete myimage gorp img2}\n    imageNames\n} -cleanup {\n    imageCleanup\n} -result {img2}\n\n\ntest image-3.1 {Tk_ImageCmd procedure, \"height\" option} -body {\n    image height\n} -returnCodes error -result {wrong # args: should be \"image height name\"}\ntest image-3.2 {Tk_ImageCmd procedure, \"height\" option} -body {\n    image height a b\n} -returnCodes error -result {wrong # args: should be \"image height name\"}\ntest image-3.3 {Tk_ImageCmd procedure, \"height\" option} -body {\n    image height foo\n} -returnCodes error -result {image \"foo\" does not exist}\ntest image-3.4 {Tk_ImageCmd procedure, \"height\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    set x [image h myimage]\n    myimage changed 0 0 0 0 60 50\n    list $x [image height myimage]\n} -cleanup {\n    imageCleanup\n} -result {15 50}\n\n\ntest image-4.1 {Tk_ImageCmd procedure, \"names\" option} -body {\n    image names x\n} -returnCodes error -result {wrong # args: should be \"image names\"}\ntest image-4.2 {Tk_ImageCmd procedure, \"names\" option} -constraints {\n    testImageType\n} -setup {\n    catch {interp delete testinterp}\n} -body {\n    interp create testinterp\n    load {} Tk testinterp\n    interp eval testinterp {\n\timage delete {*}[image names]\n\timage create test myimage\n\timage create test img2\n\timage create test 24613\n\tlsort [image names]\n    }\n} -cleanup {\n    interp delete testinterp\n} -result {24613 img2 myimage}\ntest image-4.3 {Tk_ImageCmd procedure, \"names\" option} -setup {\n    catch {interp delete testinterp}\n} -body {\n    interp create testinterp\n    load {} Tk testinterp\n    interp eval testinterp {\n\timage delete {*}[image names]\n\teval image delete [image names] [image names]\n\tlsort [image names]\n    }\n} -cleanup {\n    interp delete testinterp\n} -result {}\n\n\ntest image-5.1 {Tk_ImageCmd procedure, \"type\" option} -body {\n    image type\n} -returnCodes error -result {wrong # args: should be \"image type name\"}\ntest image-5.2 {Tk_ImageCmd procedure, \"type\" option} -body {\n    image type a b\n} -returnCodes error -result {wrong # args: should be \"image type name\"}\ntest image-5.3 {Tk_ImageCmd procedure, \"type\" option} -body {\n    image type foo\n} -returnCodes error -result {image \"foo\" does not exist}\n\ntest image-5.4 {Tk_ImageCmd procedure, \"type\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    image type myimage\n} -cleanup {\n    imageCleanup\n} -result {test}\ntest image-5.5 {Tk_ImageCmd procedure, \"type\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    .c create image 50 50 -image myimage\n    image delete myimage\n    image type myimage\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image \"myimage\" does not exist}\n\n\ntest image-6.1 {Tk_ImageCmd procedure, \"types\" option} -constraints {\n    testImageType\n} -body {\n    image types x\n} -returnCodes error -result {wrong # args: should be \"image types\"}\ntest image-6.2 {Tk_ImageCmd procedure, \"types\" option} -body {\n    lsort [image types]\n} -match glob -result {bitmap*photo test}\n\n\ntest image-7.1 {Tk_ImageCmd procedure, \"width\" option} -body {\n    image width\n} -returnCodes error -result {wrong # args: should be \"image width name\"}\ntest image-7.2 {Tk_ImageCmd procedure, \"width\" option} -body {\n    image width a b\n} -returnCodes error -result {wrong # args: should be \"image width name\"}\ntest image-7.3 {Tk_ImageCmd procedure, \"width\" option} -body {\n    image width foo\n} -returnCodes error -result {image \"foo\" does not exist}\ntest image-7.4 {Tk_ImageCmd procedure, \"width\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n} -body {\n    image create test myimage\n    set x [image w myimage]\n    myimage changed 0 0 0 0 60 50\n    list $x [image width myimage]\n} -cleanup {\n    imageCleanup\n} -result {30 60}\n\n\ntest image-8.1 {Tk_ImageCmd procedure, \"inuse\" option} -constraints {\n    testImageType\n} -setup {\n    imageCleanup\n    set res {}\n    destroy .b\n} -body {\n    image create test myimage2\n    lappend res [image inuse myimage2]\n    button .b -image myimage2\n    lappend res [image inuse myimage2]\n} -cleanup {\n    imageCleanup\n    catch {destroy .b}\n} -result [list 0 1]\n\ntest image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n    update\n} -body {\n    image create test foo -variable x\n    .c create image 50 50 -image foo\n    update\n    set x {}\n    set timer [after 500 {lappend x \"timed out\"}]\n    foo changed 5 6 7 8 30 15\n    update idletasks\n    update\n    after cancel $timer\n    return $x\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {{foo display 5 6 7 8}}\n\ntest image-9.2 {Tk_ImageChanged procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n    update\n} -body {\n    image create test foo -variable x\n    .c create image 50 50 -image foo\n    .c create image 90 100 -image foo\n    update\n    set x {}\n    foo changed 5 6 7 8 30 15\n    set timer [after 500 {lappend x \"timed out\"}]\n    image create test myimage -variable x\n    vwait x\n    after cancel $timer\n    return $x\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {{foo display 5 6 25 9} {foo display 0 0 12 14}}\n\ntest image-10.1 {Tk_GetImage procedure} -setup {\n    imageCleanup\n} -body {\n    .c create image 100 10 -image bad_name\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image \"bad_name\" does not exist}\ntest image-10.2 {Tk_GetImage procedure} -constraints testImageType -setup {\n    destroy .l\n    imageCleanup\n} -body {\n    image create test mytest\n    label .l -image mytest\n    image delete  mytest\n    label .l2 -image mytest\n} -cleanup {\n    destroy .l\n    imageCleanup\n} -returnCodes error -result {image \"mytest\" does not exist}\n\n\ntest image-11.1 {Tk_FreeImage procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 50 -image foo -tags i1\n    .c create image 90 100 -image foo -tags i2\n    pack forget .c\n    update\n    set x {}\n    .c delete i1\n    set timer [after 500 {lappend x \"timed out\"}]\n    pack .c\n    vwait x\n    after cancel $timer\n    list [imageNames] $x\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {foo {{foo free} {foo display 0 0 30 15}}}\ntest image-11.2 {Tk_FreeImage procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 50 -image foo -tags i1\n    set names [imageNames]\n    image delete foo\n    update\n    set names2 [imageNames]\n    set x {}\n    .c delete i1\n    pack forget .c\n    pack .c\n    update\n    list $names $names2 [imageNames] $x\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {foo {} {} {}}\n\n\n# Non-portable, apparently due to differences in rounding:\ntest image-12.1 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 30 40 55 65 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 0 0 5 5 50 50}}\ntest image-12.2 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 60 40 100 65 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 10 0 20 5 30 50}}\ntest image-12.3 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 60 70 100 200 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 10 10 20 5 30 30}}\ntest image-12.4 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 30 70 55 200 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 0 10 5 5 50 30}}\ntest image-12.5 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 10 20 120 130 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 0 0 30 15 70 70}}\ntest image-12.6 {Tk_RedrawImage procedure, redisplay area clipping} -constraints {\n    testImageType nonPortable\n} -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 60 -image foo -tags i1 -anchor nw\n    update\n    .c create rectangle 55 65 75 70 -width 0 -fill black -outline {}\n    set x {}\n    update\n    return $x\n} -cleanup {\n    imageCleanup\n} -result {{foo display 5 5 20 5 30 30}}\n\n\ntest image-13.1 {Tk_SizeOfImage procedure} -constraints testImageType -setup {\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    set result [list [image width foo] [image height foo]]\n    foo changed 0 0 0 0 85 60\n    lappend result [image width foo] [image height foo]\n} -cleanup {\n    imageCleanup\n} -result {30 15 85 60}\n\ntest image-13.2 {DeleteImage procedure} -constraints testImageType -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create test foo -variable x\n    .c create image 50 50 -image foo -tags i1\n    .c create image 90 100 -image foo -tags i2\n    set x {}\n    image delete foo\n    lappend x | [imageNames] | [catch {image delete foo} msg] | $msg | [imageNames] |\n} -cleanup {\n    imageCleanup\n} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image \"foo\" does not exist} | {} |}\n\ntest image-14.1 {image command vs hidden commands} -body {\n    catch {image delete hidden}\n    set l [imageNames]\n    set h [interp hidden]\n    image create photo hidden\n    interp hide {} hidden\n    image delete hidden\n    set res1 [list [imageNames] [interp hidden]]\n    set res2 [list $l $h]\n    expr {$res1 eq $res2}\n} -result 1\n\ntest image-15.1 {deleting image does not make widgets forget about it} -setup {\n    .c delete all\n    imageCleanup\n} -body {\n    image create photo foo -width 10 -height 10\n    .c create image 10 10 -image foo -tags i1 -anchor nw\n    update\n    set x [.c bbox i1]\n    lappend x [imageNames]\n    image delete foo\n    lappend x [imageNames]\n    image create photo foo -width 20 -height 20\n    lappend x [.c bbox i1] [imageNames]\n} -cleanup {\n    .c delete all\n    imageCleanup\n} -result {10 10 20 20 foo {} {10 10 30 30} foo}\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .c\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/imgBmap.test",
    "content": "# This file is a Tcl script to test out images of type \"bitmap\" (i.e.,\n# the procedures in the file tkImgBmap.c).\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc bgerror msg {\n    global errMsg\n    set errMsg $msg\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset data1 {#define foo_width 16\n#define foo_height 16\n#define foo_x_hot 3\n#define foo_y_hot 3\nstatic unsigned char foo_bits[] = {\n   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n   0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0xff};\n}\nset data2 {\n    #define foo2_width 16\n    #define foo2_height 16\n    static char foo2_bits[] = {\n       0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n       0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n       0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0xff};\n}\nmakeFile $data1 foo.bm\nmakeFile $data2 foo2.bm\n\nimageCleanup\n\n#\n# TESTS\n#\n\ntest imageBmap-1.1 {options for bitmap images} -body {\n    image create bitmap i1 -background #123456\n    lindex [i1 configure -background] 4\n} -cleanup {\n\timage delete i1\n} -result {#123456}\ntest imageBmap-1.2 {options for bitmap images} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    set errMsg {}\n    image create bitmap i1 -background lousy\n    .c create image 200 100 -image i1\n    update\n    list $errMsg $errorInfo\n} -cleanup {\n\timage delete i1\n    destroy .c\n} -result {{unknown color name \"lousy\"} {unknown color name \"lousy\"\n    (while configuring image \"i1\")}}\ntest imageBmap-1.3 {options for bitmap images} -body {\n    image create bitmap i1 -data $data1\n    lindex [i1 configure -data] 4\n} -result $data1\ntest imageBmap-1.4 {options for bitmap images} -body {\n    image create bitmap i1 -data bogus\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-1.5 {options for bitmap images} -body {\n    image create bitmap i1 -file foo.bm\n    lindex [i1 configure -file] 4\n} -result foo.bm\ntest imageBmap-1.6 {options for bitmap images} -body {\n    list [catch {image create bitmap i1 -file bogus} msg] [string tolower $msg]\n} -result {1 {couldn't read bitmap file \"bogus\": no such file or directory}}\ntest imageBmap-1.7 {options for bitmap images} -body {\n    image create bitmap i1 -foreground #00ff00\n    lindex [i1 configure -foreground] 4\n} -cleanup {\n\timage delete i1\n} -result {#00ff00}\ntest imageBmap-1.8 {options for bitmap images} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    set errMsg {}\n    image create bitmap i1 -foreground bad_color\n    .c create image 200 100 -image i1\n    update\n    list $errMsg $errorInfo\n} -cleanup {\n    destroy .c\n\timage delete i1\n} -result {{unknown color name \"bad_color\"} {unknown color name \"bad_color\"\n    (while configuring image \"i1\")}}\ntest imageBmap-1.9 {options for bitmap images} -body {\n    image create bitmap i1 -data $data1 -maskdata $data2\n    lindex [i1 configure -maskdata] 4\n} -result $data2\ntest imageBmap-1.10 {options for bitmap images} -body {\n    image create bitmap i1 -data $data1 -maskdata bogus\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-1.11 {options for bitmap images} -body {\n    image create bitmap i1 -file foo.bm -maskfile foo2.bm\n    lindex [i1 configure -maskfile] 4\n} -result foo2.bm\ntest imageBmap-1.12 {options for bitmap images} -body {\n    list [catch {image create bitmap i1 -data $data1 -maskfile bogus} msg] \\\n\t    [string tolower $msg]\n} -result {1 {couldn't read bitmap file \"bogus\": no such file or directory}}\n\n#\n# COMMON TEST CLEANUP\n#\nrename bgerror {}\n\ntest imageBmap-2.1 {ImgBmapCreate procedure} -setup {\n    imageCleanup\n} -body {\n    list [catch {image create bitmap -gorp dum} msg] $msg [imageNames]\n} -result {1 {unknown option \"-gorp\"} {}}\ntest imageBmap-2.2 {ImgBmapCreate procedure} -setup {\n    imageCleanup\n} -body {\n    image create bitmap image1\n    list [info commands image1] [imageNames] \\\n\t    [image width image1] [image height image1] \\\n\t    [lindex [image1 configure -foreground] 4] \\\n\t    [lindex [image1 configure -background] 4]\n} -cleanup {\n    image delete image1\n} -result {image1 image1 0 0 #000000 {}}\n\n\ntest imageBmap-3.1 {ImgBmapConfigureModel procedure, memory de-allocation} -body {\n    image create bitmap i1 -data $data1\n    i1 configure -data $data1\n} -cleanup {\n\timage delete i1\n} -result {}\ntest imageBmap-3.2 {ImgBmapConfigureModel procedure} -body {\n    image create bitmap i1 -data $data1\n    list [catch {i1 configure -data bogus} msg] $msg [image width i1] \\\n\t    [image height i1]\n} -result {1 {format error in bitmap data} 16 16}\ntest imageBmap-3.3 {ImgBmapConfigureModel procedure, memory de-allocation} -body {\n    image create bitmap i1 -data $data1 -maskdata $data2\n    i1 configure -maskdata $data2\n} -cleanup {\n\timage delete i1\n} -result {}\ntest imageBmap-3.4 {ImgBmapConfigureModel procedure} -body {\n    image create bitmap i1\n    i1 configure -maskdata $data2\n} -returnCodes error -result {cannot have a mask without a bitmap}\ntest imageBmap-3.5 {ImgBmapConfigureModel procedure} -body {\n    image create bitmap i1 -data $data1 -maskdata {\n\t#define foo_width 8\n\t#define foo_height 16\n\tstatic char foo_bits[] = {\n\t   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};\n\t}\n} -returnCodes error -result {bitmap and mask have different sizes}\ntest imageBmap-3.6 {ImgBmapConfigureModel procedure} -body {\n    image create bitmap i1 -data $data1 -maskdata {\n\t#define foo_width 16\n\t#define foo_height 8\n\tstatic char foo_bits[] = {\n\t   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};\n\t}\n} -returnCodes error -result {bitmap and mask have different sizes}\ntest imageBmap-3.7 {ImgBmapConfigureModel procedure} -setup {\n    destroy .c\n    pack [canvas .c]\n} -body {\n    image create bitmap i1 -data $data1\n    .c create image 100 100 -image i1 -tags i1.1 -anchor nw\n    .c create image 200 100 -image i1 -tags i1.2 -anchor nw\n    update\n    i1 configure -data {\n\t#define foo2_height 14\n\t#define foo2_width 15\n\tstatic char foo2_bits[] = {\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0xff};\n    }\n    update\n    list [image width i1] [image height i1] [.c bbox i1.1] [.c bbox i1.2]\n} -cleanup {\n\timage delete i1\n    destroy .c\n} -result {15 14 {100 100 115 114} {200 100 215 114}}\n\n\ntest imageBmap-4.1 {ImgBmapConfigureInstance procedure: check error handling} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    proc bgerror args {}\n    image create bitmap i1 -file foo.bm\n    .c create image 100 100 -image i1\n    update\n    i1 configure -foreground bogus\n    update\n} -cleanup {\n\timage delete i1\n    destroy .c\n} -result {}\n\n\ntest imageBmap-5.1 {GetBitmapData procedure} -body {\n    list [catch {image create bitmap -file ~bad_user/a/b} msg] \\\n\t    [string tolower $msg]\n} -result {1 {couldn't read bitmap file \"~bad_user/a/b\": no such file or directory}}\ntest imageBmap-5.2 {GetBitmapData procedure} -body {\n    list [catch {image create bitmap -file bad_name} msg] [string tolower $msg]\n} -result {1 {couldn't read bitmap file \"bad_name\": no such file or directory}}\ntest imageBmap-5.3 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data { }\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.4 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_width\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.5 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_width gorp\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.6 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_width 1.4\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.7 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_height\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.8 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_height gorp\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.9 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap -data \"#define foo2_height 1.4\"\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.10 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_height 14\n\t#define foo2_width 15 xx _widtg 18 xwidth 18 _heighz 18 xheight 18\n\tstatic char foo2_bits[] = {\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0xff};\n    }\n    list [image width i1] [image height i1]\n} -cleanup {\n    image delete i1\n} -result {15 14}\ntest imageBmap-5.11 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t_height 14 _width 15\n\tchar {\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0xff}\n    }\n    list [image width i1] [image height i1]\n} -cleanup {\n    image delete i1\n} -result {15 14}\ntest imageBmap-5.12 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_height 14\n\t#define foo2_width 15\n\tstatic short foo2_bits[] = {\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0xff};\n    }\n} -returnCodes error -result {format error in bitmap data; looks like it's an obsolete X10 bitmap file}\ntest imageBmap-5.13 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_height 16\n\t#define foo2_width 16\n\tstatic char foo2_bits[] =\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0xff;\n    }\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.14 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_width 16\n\tstatic char foo2_bits[] = {\n\t   0xff, 0xff, 0xff, }}\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.15 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_height 16\n\tstatic char foo2_bits[] = {\n\t   0xff, 0xff, 0xff, }}\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.16 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {\n\t#define foo2_height 16\n\t#define foo2_width 16\n\tstatic char foo2_bits[] = {\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, foo};\n    }\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-5.17 {GetBitmapData procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data \"\n\t#define foo2_height 16\n\t#define foo2_width 16\n\tstatic char foo2_bits[] = \\{\n\t   0xff, 0xff, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81,\n\t   0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff, 0x81,\n\t   0xff\n    \"\n} -returnCodes error -result {format error in bitmap data}\n\n\ntest imageBmap-6.1 {NextBitmapWord procedure} -setup {imageCleanup} -body {\n    image create bitmap i1 -data {1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890}\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-6.2 {NextBitmapWord procedure} -setup {imageCleanup} -body {\n    makeFile {1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890} foo3.bm\n    image create bitmap i1 -file foo3.bm\n} -cleanup {\n    removeFile foo3.bm\n} -returnCodes error -result {format error in bitmap data}\ntest imageBmap-6.3 {NextBitmapWord procedure} -setup {imageCleanup} -body {\n    makeFile {   } foo3.bm\n    image create bitmap i1 -file foo3.bm\n} -cleanup {\n    removeFile foo3.bm\n} -returnCodes error -result {format error in bitmap data}\n\n#\n# COMMON TEST SETUP\n#\n# For tests imageBmap-7.*\n#\nimageCleanup\nimage create bitmap i1\n\ntest imageBmap-7.1 {ImgBmapCmd procedure} -body {\n    i1\n} -returnCodes error -result {wrong # args: should be \"i1 option ?arg ...?\"}\ntest imageBmap-7.2 {ImgBmapCmd procedure, \"cget\" option} -body {\n    i1 cget\n} -returnCodes error -result {wrong # args: should be \"i1 cget option\"}\ntest imageBmap-7.3 {ImgBmapCmd procedure, \"cget\" option} -body {\n    i1 cget a b\n} -returnCodes error -result {wrong # args: should be \"i1 cget option\"}\ntest imageBmap-7.4 {ImgBmapCmd procedure, \"cget\" option} -body {\n    i1 co -foreground #123456\n    i1 cget -foreground\n} -result {#123456}\ntest imageBmap-7.5 {ImgBmapCmd procedure, \"cget\" option} -body {\n    i1 cget -stupid\n} -returnCodes error -result {unknown option \"-stupid\"}\ntest imageBmap-7.6 {ImgBmapCmd procedure} -body {\n    llength [i1 configure]\n} -result 6\ntest imageBmap-7.7 {ImgBmapCmd procedure} -body {\n    i1 co -foreground #001122\n    i1 configure -foreground\n} -result {-foreground {} {} #000000 #001122}\ntest imageBmap-7.8 {ImgBmapCmd procedure} -body {\n    i1 configure -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest imageBmap-7.9 {ImgBmapCmd procedure} -body {\n    i1 configure -foreground #221100 -background\n} -returnCodes error -result {value for \"-background\" missing}\ntest imageBmap-7.10 {ImgBmapCmd procedure} -body {\n    i1 gorp\n} -returnCodes error -result {bad option \"gorp\": must be cget or configure}\n\n#\n# COMMON TEST CLEANUP\n#\nimageCleanup\n\ntest imageBmap-8.1 {ImgBmapGet/Free procedures, shared instances} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    image create bitmap i1 -data $data1\n    .c create image 50 100 -image i1 -tags i1.1\n    .c create image 150 100 -image i1 -tags i1.2\n    .c create image 250 100 -image i1 -tags i1.3\n    update\n    .c delete i1.1\n    i1 configure -background black\n    update\n    .c delete i1.2\n    i1 configure -background white\n    update\n    .c delete i1.3\n    i1 configure -background black\n    update\n    image delete i1\n} -cleanup {\n    destroy .c\n} -result {}\n\n\ntest imageBmap-9.1 {ImgBmapDisplay procedure, nothing to display} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    proc bgerror args {}\n    imageCleanup\n    image create bitmap i1 -data $data1\n    .c create image 50 100 -image i1 -tags i1.1\n    i1 configure -data {}\n    update\n} -cleanup {\n    image delete i1\n    destroy .c\n} -result {}\ntest imageBmap-9.2 {ImgBmapDisplay procedure, nothing to display} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    proc bgerror args {}\n    imageCleanup\n    .c delete all\n    image create bitmap i1 -data $data1\n    .c create image 50 100 -image i1 -tags i1.1\n    i1 configure -foreground bogus\n    update\n} -cleanup {\n    image delete i1\n    destroy .c\n} -result {}\n\n#\n# COMMON TEST CLEANUP\n#\nif {[info exists bgerror]} {\n    rename bgerror {}\n}\n\ntest imageBmap-10.1 {ImgBmapFree procedure, resource freeing} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    imageCleanup\n    image create bitmap i1 -data $data1 -maskdata $data2 -foreground #112233 \\\n\t    -background #445566\n    .c create image 100 100 -image i1\n    update\n    .c delete all\n    image delete i1\n} -cleanup {\n    destroy .c\n} -result {}\ntest imageBmap-10.2 {ImgBmapFree procedures, unlinking} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    imageCleanup\n    image create bitmap i1 -data $data1 -maskdata $data2 -foreground #112233 \\\n\t    -background #445566\n    .c create image 100 100 -image i1\n    button .b1 -image i1\n    button .b2 -image i1\n    button .b3 -image i1\n    pack .b1 .b2 .b3\n    update\n    destroy .b2\n    update\n    destroy .b3\n    update\n    destroy .b1\n    update\n    .c delete all\n} -cleanup {\n\timage delete i1\n    deleteWindows\n} -result {}\n\n\ntest imageBmap-11.1 {ImgBmapDelete procedure} -body {\n    image create bitmap i2 -file foo.bm -maskfile foo2.bm\n    image delete i2\n    info command i2\n} -result {}\ntest imageBmap-11.2 {ImgBmapDelete procedure} -body {\n    image create bitmap i2 -file foo.bm -maskfile foo2.bm\n    rename i2 newi2\n    set x [list [info command i2] [info command new*] [newi2 cget -file]]\n    image delete i2\n    lappend x [info command new*]\n} -result {{} newi2 foo.bm {}}\n\n\ntest imageBmap-12.1 {ImgBmapCmdDeletedProc procedure} -body {\n    image create bitmap i2 -file foo.bm -maskfile foo2.bm\n    rename i2 {}\n    list [expr {\"i2\" in [imageNames]}] [catch {i2 foo} msg] $msg\n} -result {0 1 {invalid command name \"i2\"}}\n\n#\n# TESTFILE CLEANUP\n#\n\nremoveFile foo.bm\nremoveFile foo2.bm\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "tests/imgListFormat.test",
    "content": "# This file is a Tcl script to test out the default image data format\n# (\"list format\") implementend in the file tkImgListFormat.c.\n#\n# Copyright © 2017 Simon Bachmann\n# All rights reserved.\n#\n# Author: Simon Bachmann (simonbachmann@bluewin.ch)\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# TEST INITIALIZATION\n#\n\nset teapotPhotoFile [file join [file dirname [info script]] teapot.ppm]\nset transpTeapotPhotoFile [file join [file dirname [info script]] teapotTransparent.png]\n\n#\n# TESTS\n#\n\ntest imgListFormat-1.1 {ParseFormatOptions: default values} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{red green} {blue black}}\n    lindex [photo1 data] 1 1\n} -cleanup {\n    imageCleanup\n} -result {#000000}\ntest imgListFormat-1.2 {ParseFormatOptions: format name as first arg} -setup {\n    image create photo photo1\n} -body {\n    photo1 put #1256ef -format {default} -to 0 0 10 10\n} -cleanup {\n    imageCleanup\n} -result {}\ntest imgListFormat-1.3 {ParseFormatOptions: unknown option} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -bogus}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {bad format option \"-bogus\": must be -colorformat}\ntest imgListFormat-1.4 {ParseFormatOptions: option not allowed} -setup {\n    image create photo photo1\n} -body {\n    photo1 put yellow -format {default -colorformat rgb}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {bad format option \"-colorformat\": no options allowed}\ntest imgListFormat-1.5 {ParseFormatOptions: no -colorformat value} -setup {\n    image create photo photo1 -data black\n} -body {\n    photo1 data -format {default -colorformat}\n} -returnCodes error -result {the \"-colorformat\" option requires a value}\ntest imgListFormat-1.6 {ParseFormatOptions: bad -colorformat val #1} -setup {\n    image create photo photo1\n} -body {\n    photo1 put yellow\n    photo1 data -format {default -colorformat bogus}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {bad color format \"bogus\": must be rgb, rgba, or list}\ntest imgListFormat-1.7 {ParseFormatOptions: bad -colorformat val #2} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat tkcolor}\n} -returnCodes error -result \\\n    {bad color format \"tkcolor\": must be rgb, rgba, or list}\ntest imgListFormat-1.8 {ParseFormatOptions: bad -colorformat #3} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat emptystring}\n} -returnCodes error -result \\\n    {bad color format \"emptystring\": must be rgb, rgba, or list}\ntest imgListFormat-1.9 {ParseFormatOptions: bad -colorformat #4} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat rgb-short}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {bad color format \"rgb-short\": must be rgb, rgba, or list}\ntest imgListFormat-1.10 {ParseFormatOptions: bad -colorformat #5} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat rgba-short}\n} -returnCodes error -result \\\n    {bad color format \"rgba-short\": must be rgb, rgba, or list}\ntest imgListFormat-1.11 {valid colorformats} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white#78\n    set result {}\n    lappend result [photo1 data -format {default -colorformat rgb}]\n    lappend result [photo1 data -format {default -colorformat rgba}]\n    lappend result [photo1 data -format {default -colorformat list}]\n    set result\n} -cleanup {\n    imageCleanup\n    unset result\n} -result {{{#ffffff}} {{#ffffff78}} {{{255 255 255 120}}}}\n\n# GetBadOptMsg: only use case already tested with imgListFormat-1.4\n\ntest imgListFormat-3.1 {StringMatchDef: data is not a list} -body {\n    testphotostringmatch {not a \" proper list}\n    # \" (this comment is here only for editor highlighting)\n} -returnCodes error -result {unmatched open quote in list}\n# empty data case tested with imgPhoto-4.95 (imgPhoto.test)\ntest imgListFormat-3.2 {StringMatchDef: \\\n\tlist element not a proper list} -body {\n    testphotostringmatch {{red white} {not \"} {blue green}}\n    # \"\n} -returnCodes error -result {unmatched open quote in list}\ntest imgListFormat-3.3 {StringMatchDef: \\\n\tsublists with differen lengths} -body {\n    testphotostringmatch {{#001122 #334455 #667788}\n\t\t{#99AABB #CCDDEE}\n\t\t{#FF0011 #223344 #556677}}\n} -returnCodes error -result \\\n    {invalid row # 1: all rows must have the same number of elements}\ntest imgListFormat-3.4 {StringMatchDef: base64 data is not parsed as valid \\\n} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {\n\tiVBORw0KGgoAAAANSUhEUgAAAAIAAAACCA\n\tYAAAEFsT2yAAAABGdBTUEAAYagMeiWXwAA\n\tABdJREFUCJkFwQEBAAAAgiD6P9pACRoqDk\n\tfUBvt1wUFKAAAAAElFTkSuQmCC\n    } -format default\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCA\"}\ntest imgListFormat-3.5 {StringMatchDef: valid data} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{blue green}\n\t\t{yellow magenta}\n\t\t{#000000 #FFFFFFFF}}\n    list [image width photo1] [image height photo1] \\\n\t[photo1 get 0 2 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {2 3 {0 0 0 255}}\n\n# ImgStringRead: most of the error cases cannot be tested with current code,\n# as the errors are detected by StringMatchDef\ntest imgListFormat-4.1 {StringReadDef: use with -format opt} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -format \"default\"\n    photo1 get 0 0\n} -cleanup {\n    imageCleanup\n} -result {255 255 255}\ntest imgListFormat-4.2 {StringReadDef: suboptions to format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -format {default -bogus}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {bad format option \"-bogus\": no options allowed}\ntest imgListFormat-4.3 {StringReadDef: erroneous non-option argument} -setup {\n    image create photo photo1\n} -body {\n    photo1 put orange -format {default bogus}\n} -returnCodes error -result {bad format option \"bogus\": no options allowed}\ntest imgListFormat-4.4 {StringReadDef: normal use case} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    set imgData [photo1 data]\n    photo2 put $imgData\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    imageCleanup\n    unset imgData\n} -result 1\ntest imgListFormat-4.5 {StringReadDef: correct compositing rule} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n    image create photo photo2\n} -body {\n    photo2 put #FF0000 -to 0 0 50 50\n    photo2 put [photo1 data -format {default -colorformat rgba}] -to 10 10 40 40\n    list [photo2 get 0 0 -withalpha] [photo2 get 20 25 -withalpha] \\\n\t[photo2 get 49 49 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {{255 0 0 255} {0 78 185 225} {255 0 0 255}}\n\ntest imgListFormat-5.1 {StringWriteDef: format options not a list} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default \" bogus}\n    # \"\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {unmatched open quote in list}\ntest imgListFormat-5.2 {StringWriteDef: invalid format option} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -bogus}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {bad format option \"-bogus\": must be -colorformat}\ntest imgListFormat-5.3 {StringWriteDef: non-option arg in format} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat list bogus}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {bad format option \"bogus\": must be -colorformat}\ntest imgListFormat-5.4 {StringWriteDef: empty image} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format {default -colorformat rgba}\n} -cleanup {\n    imageCleanup\n} -result {}\ntest imgListFormat-5.5 {StirngWriteDef: size of data} -setup {\n    image create photo photo1\n} -body {\n    photo1 put blue -to 0 0 35 64\n    set imgData [photo1 data]\n    list [llength [lindex $imgData 0]] [llength $imgData]\n} -cleanup {\n    unset imgData\n    imageCleanup\n} -result {35 64}\ntest imgListFormat-5.6 {StringWriteDef: test some pixels #1} -setup {\n    set result {}\n    image create photo photo1 -file $teapotPhotoFile\n} -body {\n    set imgData [photo1 data]\n    # note: with [lindex], the coords are inverted (y x)\n    lappend result [lindex $imgData 0 0]\n    lappend result [lindex $imgData 3 2]\n    lappend result [lindex $imgData 107 53]\n    lappend result [lindex $imgData 203 157]\n    lappend result [lindex $imgData 255 255]\n    set result\n} -cleanup {\n    unset result\n    unset imgData\n    imageCleanup\n} -result {{#135cc0} #135cc0 #a06d52 #e1c8ba #135cc0}\ntest imgListFormat-5.7 {StringWriteDef: test some pixels #2} -setup {\n    set result {}\n    image create photo photo1 -file $teapotPhotoFile\n} -body {\n    set imgData [photo1 data -format {default -colorformat rgba}]\n    # note: with [lindex], the coords are inverted (y x)\n    lappend result [lindex $imgData 0 0]\n    lappend result [lindex $imgData 3 2]\n    lappend result [lindex $imgData 107 53]\n    lappend result [lindex $imgData 203 157]\n    lappend result [lindex $imgData 255 255]\n    set result\n} -cleanup {\n    unset result\n    unset imgData\n    imageCleanup\n} -result {{#135cc0ff} #135cc0ff #a06d52ff #e1c8baff #135cc0ff}\ntest imgListFormat-5.8 {StringWriteDef: test some pixels #3} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n} -body {\n    set imgData [photo1 data -format {default -colorformat rgb}]\n    set result {}\n    lappend result [lindex $imgData 3 2]\n    lappend result [lindex $imgData 107 53]\n    lappend result [lindex $imgData 203 157]\n    set result\n} -cleanup {\n    unset result\n    unset imgData\n    imageCleanup\n} -result {{#004eb9} #a14100 #ffca9f}\ntest imgListFormat-5.9 {StringWriteDef: test some pixels #4} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n} -body {\n    set imgData [photo1 data -format {default -colorformat rgba}]\n    set result [lindex $imgData 3 2]\n    lappend result [lindex $imgData 107 53]\n    lappend result [lindex $imgData 203 157]\n    set result\n} -cleanup {\n    unset result\n    unset imgData\n    imageCleanup\n} -result {{#004eb9e1} #a14100aa #ffca9faf}\ntest imgListFormat-5.10 {StringWriteDef: test some pixels #5} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n} -body {\n    set imgData [photo1 data -format {default -colorformat list}]\n    set result {}\n    lappend result [lindex $imgData 3 2]\n    lappend result [lindex $imgData 107 53]\n    lappend result [lindex $imgData 203 157]\n    set result\n} -cleanup {\n    unset imgData\n    unset result\n    imageCleanup\n} -result {{0 78 185 225} {161 65 0 170} {255 202 159 175}}\n\ntest imgListFormat-6.1 {ParseColor: empty string} -setup {\n    image create photo photo1\n    set result {}\n} -body {\n    photo1 put {{\"\" \"\"} {\"\" \"\"}}\n    lappend result [image width photo1]\n    lappend result [image height photo1]\n    lappend result [photo1 get 1 1 -withalpha]\n    set result\n} -cleanup {\n    unset result\n    imageCleanup\n} -result {2 2 {0 0 0 0}}\ntest imgListFormat-6.2 {ParseColor: empty string, mixed} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{black white} {{} white}}\n    list [photo1 get 0 0 -withalpha] [photo1 get 0 1 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {{0 0 0 255} {0 0 0 0}}\ntest imgListFormat-6.3 {ParseColor: color name too long} -setup {\n    image create photo photo1\n    set longstr {}\n    for {set i 1} {$i <= 100} {incr i} {\n\tappend longstr \"z\"\n    }\n} -body {\n    photo1 put [list [list blue] [list $longstr]]\n} -cleanup {\n    imageCleanup\n    unset longstr\n} -returnCodes error -result {invalid color}\ntest imgListFormat-6.4 {ParseColor: #XXX color, different forms} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#A123 #334455} {#012 #fffefd#00}}\n    photo1 data -format {default -colorformat rgba}\n} -cleanup {\n    imageCleanup\n} -result {{#aa112233 #334455ff} {#001122ff #fffefd00}}\ntest imgListFormat-6.5 {ParseColor: list format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put [list [list [list 255 255 255]]]\n    photo1 get 0 0 -withalpha\n} -cleanup {\n    imageCleanup\n} -result {255 255 255 255}\ntest imgListFormat-6.6 {ParseColor: string format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put [list [list [list white]]]\n    photo1 get 0 0 -withalpha\n} -cleanup {\n    imageCleanup\n} -result {255 255 255 255}\ntest imgListFormat-6.7 {ParseColor: invalid color} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{blue red} {green bogus}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"bogus\"}\ntest imgListFormat-6.8 {ParseColor: overall test} -setup {\n    image create photo photo1\n    set result {}\n} -body {\n    photo1 put {\n\t\t{snow@0.5 snow#80 snow#8 #fffffafafafa@0.5 #fffffabbfacc#8}\n\t\t{#fffffafffaff#80 #ffffaafaa@.5 #ffffaafaa#8 #ffffaafaa#80 #fee#8}\n\t\t{#fee#80 #fee@0.5 #fffafa@0.5 #fffafa#8 #fffafa#80}\n\t\t{{0xff 250 0xfa 128} {255 250 250} #fee8 #fffafa80 snow}}\n    for {set y 0} {$y < 4} {incr y} {\n\t\tfor {set x 0} {$x < 5} {incr x} {\n\t\t\tlappend result [photo1 get $x $y -withalpha]\n\t\t}\n    }\n    set result\n} -cleanup {\n    imageCleanup\n    unset result\n} -result \\\n{{255 250 250 128} {255 250 250 128} {255 250 250 136} {255 250 250 128}\\\n{255 250 250 136} {255 250 250 128} {255 250 250 128} {255 250 250 136}\\\n{255 250 250 128} {255 238 238 136} {255 238 238 128} {255 238 238 128}\\\n{255 250 250 128} {255 250 250 136} {255 250 250 128} {255 250 250 128}\\\n{255 250 250 255} {255 238 238 136} {255 250 250 128} {255 250 250 255}}\n\n# Note: these tests were written for an earlier implementation of\n# ParseColorAsList. For this reason, their order and layout do not follow the\n# current code very well. Test coverage is pretty good, nevertheless.\ntest imgListFormat-7.1 {ParseColorAsList: invalid list} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{123 45 67 89} {123 45 \" 67}}}\n\t#\"\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"123 45 \" 67\"}\n#\"\ntest imgListFormat-7.2 {ParseColorAsList: too few elements in list} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{0 255 0 255} {0 255}}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"0 255\"}\ntest imgListFormat-7.3 {ParseColorAsList: too many elements in list} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{0 100 200 255} {0 100 200 255 0}}}\n} -returnCodes error -result {invalid color name \"0 100 200 255 0\"}\ntest imgListFormat-7.4 {ParseColorAsList: not an integer value} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{9 0xf3 87 65} {43 21 10 1.0}}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"43 21 10 1.0\"}\ntest imgListFormat-7.5 {ParseColorAsList: negative value in list} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{121 121 121} {121 121 -1}}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"121 121 -1\"}\ntest imgListFormat-7.6 {ParseColorAsList: value in list too large} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{0 1 2 3} {254 255 256}}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"254 255 256\"}\ntest imgListFormat-7.7 {ParseColorAsList: suffix not allowed} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{100 100 100} {100 100 100#FE}}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"100 100 100#FE\"}\ntest imgListFormat-7.8 {ParseColorAsList: valid list form} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{{0x0 0x10 0xfe 0xff} {0 100 254}}\n\t\t{{30 30 30 0} {1 1 254 1}}}\n    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha] \\\n\t[photo1 get 0 1 -withalpha] [photo1 get 1 1 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {{0 16 254 255} {0 100 254 255} {30 30 30 0} {1 1 254 1}}\ntest imgListFormat-7.9 {ParseColorAsList: additional spaces in list} -setup {\n    image create photo photo1\n} -body {\n    photo1 put { { { 1 2 3} {1  2\t 3} } { {1 2 3  } {  1  2  3   4  }  } }\n    photo1 data -format {default -colorformat rgba}\n} -cleanup {\n    imageCleanup\n} -result {{#010203ff #010203ff} {#010203ff #01020304}}\ntest imgListFormat-7.10 {ParseColorAsList: list format, string rep} -setup {\n\timage create photo photo1\n} -body {\n\tphoto1 put {{\"111 222 33 44\"}}\n\tphoto1 get 0 0 -withalpha\n} -cleanup {\n\timageCleanup\n} -result {111 222 33 44}\n\ntest imgListFormat-8.1 {ParseColorAsHex: RGB format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#010 #001100}}\n    photo1 data\n} -cleanup {\n    imageCleanup\n} -result {{#001100 #001100}}\ntest imgListFormat-8.2 {ParseColorAsHex: invalid hex digit} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#ABCD #ABCZ}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"#ABCZ\"}\ntest imgListFormat-8.3 {ParseColorAsHex: RGB with suffix, 8 chars} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#FFfFFf #AbCdef#0}}\n    photo1 data\n} -cleanup {\n    imageCleanup\n} -result {{#ffffff #abcdef}}\ntest imgListFormat-8.4 {ParseColor: valid #RGBA color} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#9bd5020d #7acF}}\n    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {{155 213 2 13} {119 170 204 255}}\n\ntest imgListFormat-9.1 {ParseColorAsStandard:\n\tTk color, valid suffixes} -setup {\n    image create photo photo1\n    set result {}\n} -body {\n    photo1 put {{blue@0.711 #114433#C} {#8D4#1A magenta}}\n    lappend result [photo1 get 0 0 -withalpha]\n    lappend result [photo1 get 1 0 -withalpha]\n    lappend result [photo1 get 0 1 -withalpha]\n    lappend result [photo1 get 1 1 -withalpha]\n    set result\n} -cleanup {\n    unset result\n    imageCleanup\n} -result {{0 0 255 181} {17 68 51 204} {136 221 68 26} {255 0 255 255}}\ntest imgListFormat-9.2 {ParseColorAsStandard:\n\tTk color with and w/o suffixes} -setup {\n    image create photo photo1\n    set result {}\n} -body {\n    photo1 put {{#52D8a0 #2B5} {#E47@0.01 maroon#4}}\n    lappend result [photo1 get 0 0 -withalpha]\n    lappend result [photo1 get 1 0 -withalpha]\n    lappend result [photo1 get 0 1 -withalpha]\n    lappend result [photo1 get 1 1 -withalpha]\n    set result\n} -cleanup {\n    unset result\n    imageCleanup\n} -result {{82 216 160 255} {34 187 85 255} {238 68 119 3} {128 0 0 68}}\ntest imgListFormat-9.3 {ParseColorAsStandard: wrong digit count} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#000 #00}}\n} -returnCodes error -result {invalid color name \"#00\"}\ntest imgListFormat-9.4 {ParseColorAsStandard: @A suffix, not a float} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{blue@0.5 blue@bogus}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {invalid alpha suffix \"@bogus\": expected floating-point value}\ntest imgListFormat-9.5 {ParseColorAsStandard: @A, value too low} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {green@.1 green@-0.1}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {invalid alpha suffix \"@-0.1\": value must be in the range from 0 to 1}\ntest imgListFormat-9.6 {ParseColorAsStandard: @A, value too high} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#000000@0 #000000@1.0001}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {invalid alpha suffix \"@1.0001\": value must be in the range from 0 to 1}\ntest imgListFormat-9.7 {ParseColorAsStandard: @A suffix, edge values} -setup {\n    imageCleanup\n    image create photo photo1\n} -body {\n    photo1 put {{yellow@1e-22 yellow@0.12352941 yellow@0.12352942 \\\n\t\t yellow@0.9999999}}\n    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha] \\\n\t[photo1 get 2 0 -withalpha] [photo1 get 3 0 -withalpha]\n} -cleanup {\n    imageCleanup\n} -result {{255 255 0 0} {255 255 0 31} {255 255 0 32} {255 255 0 255}}\ntest imgListFormat-9.8 {ParseColorAsStandard: # suffix, no hex digits} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{black#f} {black#}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid alpha suffix \"#\"}\ntest imgListFormat-9.9 {ParseColorAsStandard:\n\t'#' suffix, too many digits} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#ABC#12 #ABC#123}}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid alpha suffix \"#123\"}\ntest imgListFormat-9.10 {ParseColorAsStandard:\n\tinvalid digit in #X suffix} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#000#a #000#g}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid alpha suffix \"#g\": expected hex digit}\ntest imgListFormat-9.11 {ParseColorAsStandard:\n\tinvalid digit in #XX suffix} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {green#2 green#2W}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid alpha suffix \"#2W\": expected hex digit}\ntest imgListFormat-9.12 {ParseColorAsStandard:\n\tinvalid color: not a hex digit} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#ABCDEF@.99 #ABCDEG@.99}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"#ABCDEG@.99\"}\ntest imgListFormat-9.13 {ParseColorAsStandard: suffix not allowed #1} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#ABC@.5 #ABCD@0.5}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"#ABCD@0.5\"}\ntest imgListFormat-9.14 {ParseColorAsStandard: suffix not allowed #2} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {#1111 #1111#1}\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"#1111#1\"}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ntestutils forget image\ncleanupTests\n"
  },
  {
    "path": "tests/imgPNG.test",
    "content": "# This file is a Tcl script to test out the code in tkImgFmtPNG.c, which reads\n# and write PNG-format image files for photo widgets.\n#\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 1998 Willem van Schaik (images only)\n# Copyright © 2008 Donal K. Fellows\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n\nnamespace eval png {\n    variable encoded\n    # Key names are from the names of the source images, which come from\n    #    http://www.schaik.com/pngsuite/pngsuite.html\n    # The exception is \"BadX\", which is used to test handling badly compressed\n    # images.\n    array set encoded {\n\tbasn0g08 \"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAAAAABWESUoAAAABGdBTUEAAYag\nMeiWXwAAAEFJREFUeJxjZGAkABQIyLMMBQWMDwgp+PcfP2B5MBwUMMoRkGdkonlcDAYFjI/wyv7/z/\niH5nExGBQwyuCVZWQEAFDl/nE14thZAAAAAElFTkSuQmCC\"\n\tbasn2c08 \"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAAYag\nMeiWXwAAAEhJREFUeJzt1cEJADAMAkCF7JH9t3ITO0Qr9KH4zuErtA0EO4AKFPgcoO3kfUx4QIECD0\nqHH8KEBxQo8KB0OCOpQIG7cHejwAGCsfleD0DPSwAAAABJRU5ErkJggg==\"\n\tbasn3p08 \"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAAYag\nMeiWXwAAAwBQTFRFIkQA9f/td/93y///EQoAOncAIiL//xH/EQAAIiIA/6xVZv9m/2Zm/wH/IhIA3P\n//zP+ZRET/AFVVIgAAy8v/REQAVf9Vy8sAMxoA/+zc7f//5P/L/9zcRP9EZmb/MwAARCIA7e3/ZmYA\n/6RE//+q7e0AAMvL/v///f/+//8BM/8zVSoAAQH/iIj/AKqqAQEARAAAiIgA/+TLulsAIv8iZjIA//\n+Zqqr/VQAAqqoAy2MAEf8R1P+qdzoA/0RE3GsAZgAAAf8BiEIA7P/ca9wA/9y6ADMzAO0A7XMA//+I\nmUoAEf//dwAA/4MB/7q6/nsA//7/AMsA/5mZIv//iAAA//93AIiI/9z/GjMAAACqM///AJkAmQAAAA\nABMmYA/7r/RP///6r/AHcAAP7+qgAASpkA//9m/yIiAACZi/8RVf///wEB/4j/AFUAABER///+//3+\npP9EZv///2b/ADMA//9V/3d3AACI/0T/ABEAd///AGZm///tAAEA//XtERH///9E/yL//+3tEREAiP\n//AAB3k/8iANzcMzP//gD+urr/mf//MzMAY8sAuroArP9V///c//8ze/4A7QDtVVX/qv//3Nz/VVUA\nAABm3NwA3ADcg/8Bd3f//v7////L/1VVd3cA/v4AywDLAAD+AQIAAQAAEiIA//8iAEREm/8z/9SqAA\nBVmZn/mZkAugC6KlUA/8vLtP9m/5sz//+6qgCqQogAU6oA/6qqAADtALq6//8RAP4AAABEAJmZmQCZ\n/8yZugAAiACIANwA/5MiAADc/v/+qlMAdwB3AgEAywAAAAAz/+3/ALoA/zMz7f/t/8SIvP93AKoAZg\nBmACIi3AAA/8v/3P/c/4sRAADLAAEBVQBVAIgAAAAiAf//y//L7QAA/4iIRABEW7oA/7x3/5n/AGYA\nuv+6AHd3c+0A/gAAMwAzAAC6/3f/AEQAqv+q//7+AAARIgAixP+IAO3tmf+Z/1X/ACIA/7RmEQARCh\nEA/xER3P+6uv//iP+IAQAB/zP/uY7TYgAAAbFJREFUeJwNwQcACAQQAMBHqIxIZCs7Mwlla1hlZ+8V\nitCw9yoqNGiYDatsyt6jjIadlVkysve+u5jC9xTmV/qyl6bcJR7kAQZzg568xXmuE2lIyUNM5So7OM\nAFIhvp+YgGvEtFNnOKeJonSEvwP9NZzhHiOfLzBXPoxKP8yD6iPMXITjP+oTdfsp14lTJMJjGtOMFQ\nfiFe4wWK8BP7qUd31hBNqMos2tKYFbRnJdGGjTzPz2yjEA1ZSKymKCM5ylaWcJrZxCZK8jgfU4vc/M\nW3xE7K8RUvsZb3Wc/XxCEqk4v/qMQlFvMZcZIafMOnLKM13zGceJNqPMU4KnCQAqQgbrKHpXSgFK/Q\nn6REO9YxjWE8Sx2SMJD4jfl8wgzy0YgPuEeUJQcD6EoWWpCaHsQkHuY9RpGON/icK0RyrvE680jG22\nTlHaIbx6jLnySkF+M5QxzmD6pwkTsMoSAdidqsojipuMyHzOQ4sYgfyElpzjKGErQkqvMyC7jFv9xm\nBM2JuTzDRDLxN4l4jF1EZjIwmhfZzSOMpT4xiH70IQG/k5En2UKcowudycsG8jCBmtwHgRv+EIeWyO\nAAAAAASUVORK5CYII=\"\n\tbasn6a08 \"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAYag\nMeiWXwAAAG9JREFUeJzt1jEKgDAMRuEnZGhPofc/VQSPIcTdxUV4HVLoUCj8H00o2YoBMF57fpz/uj\nODHXUFRwPKBqj5DVigB041HiJ9gFyCVOMbsEIPXNwuAHkgiJL/4qABNqB7QAeUPBAE2QAZUDZAfwEb\n8ABSIBqcFg+4TAAAAABJRU5ErkJggg==\"\n\n\tBadX \"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhk\niAAAABN0RVh0U29mdHdhcmUAVGsgOC42YjEuMcrtT1oAAAAcSURBVHicYmBgYPjPgAr+ozP+o0uj68\nBUiWEmAAAA//8SozfjAAAAAElFTkSuQmCC\"\n\tMultiIDAT \"iVBORw0KGgoAAAANSUhEUgAAAN8AAADUCAYAAAAcPvbvAAAAAXNSR0IArs4\nc6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oEGQQKMpLRO\nuoAACAASURBVHja7L158GbZWd/3ec45977bb+2e7p7pnu7ZNzFaRhJCwggjsHqUCgUhiWMSJymwUoV\nUlkumJChCHFWBywQQNqhYpFDB2Ljs2EWqiAmphMQVO2ATQMJCQsuMZrp7lt5++7ve9957lid/3Ptbu\ntWjGRAgZvo9XW//3vXe973nfM/zPN9nE1VlMf58RwHkgFMgJhDAQg0EAJQ+FuYekgVrCBope5YK6F3\n8Vw9UCdbvOnuBwbH2aDnBKy7rtkcA357PYHC0B0/t2xfjaz7M4hJ8jS+6fPnriqKqxLqG1IDTGINpP\n9vtds8bY85j5ABoYBAxX3ly5dbnW4wF+G7PoTcDpvnnYyDEeACYJOlgsozN3xMS71Fx7RQaFIOIbY6\nn5iaMpQX4/gIOt7gEf/7jyzFgQMFIAxODQSShmYXcgICmRr5F9dlwPH3XaFJw3LgMjFcsgiDtcZAG1\nHIEsArIAnwLybcA30urnQcPjSHr5GBNK7kSgpLq6h0XLz63fP36xjKYd4AlYUgYdF/t1MPJlVtJv8V\nYgO92vujmFmJQblAUFbWmfXPCZQaH4mezJ5/+wtM8//yLBJ+ePFQ7pQGdtjhTGkl49LiSFuBbgG8h+\nV5OJU0CAQVJJBQxIBqY7uw8+fyFS2xcvkooqycPxBzSqJU3MjcHE5yOAnAxFjbf7bzjyVG06Y07YWy\nghEps3AUaMJpB7U8Ue8MnptvbpKSkyj9BTCewbMm+TccR6WdvBLoutM6F5FtIvpvuHFE7DaAaMRiCJ\nhKxnSUlFMW7r1+8ZIrNberhmPHWhsHIu20r16K2yE2HgL55khd+3QX4FuMWNh8KouDUoijG2saWA9B\nEPR6f37t8Fb+zTbW1wdVnn0GHu+eJFYaAMa0uc8MxzWKiF2rnYtys/+nNkjA1Dw4kIAaIiCYAmW3vv\nPv6xUuc7uY4Z5ltXENC9W6siKKaNEEAK6ZVZxVEDjRbARC7uP4LybcY6WYNsbXVGuDpwStiFIJ//Wh\nr+/Tw6nXcdEI2m7B96Vn8aPc0qX49VIjEBls36pmAaX2A5gZ1dDEW4LvtheCNd1ppqPsATc39afHke\nGsLijlrKXDMKDoZUY92INZPQiASUEmo6OEBAJI2t1ucZzEW4Lttgbcv/W54UsEeqIsREWE2Gp7fvbZ\nBR4S7Bl1ODnosWaXY2wZfnBcCSiRoA8B9cuWQYJEF8BbgW4yviMZDbbMJsEYRUm+8s/fOzWtX6RmHK\nUt0NiVMp1x5/iJpMn4n0LMI1jQ2nR7x56nqIfAWbr4F+BbjKxuDgrR2HwDvms7GnclwhBXDXXcc5/j\nqEsu9LnVRoMF3IL1LSXitSC3CVF5Kx12MBfhu0xGlSa2LBKDCUIH4AxdBSFABdcrpsgTT4jxXL3C3v\n8bXZZsMj09YX4k8sLfLGy9sYj//AuxMzqc4oxTLmEQtYKRJMxIR1OjNwZ6LsQDf7TteCge29QZYAxC\nZ7e6cH+/tYpLSzRyDwQDnGi9RWZawuwfz+Xln7a1z+F7JSRdjAb7b5aLv+/LM/hTI4ZNiGxUxA/D1u\nd3rVx/b29zAxJqBc2TWISJ0Oh2cs1DMoJw/ZpKegxpzk355g/q5AN8CfLe7xDMcDURpH7VPqECMYAH\nq8vxo8zrz4R5dha4xTQRM5ED61eMRTKcQ03nRwIGr70gcm+4ffzEW4Luth+4D0HBDzvlB1nozMY5Em\nk+fjJMxnbqmbw0dlH7Ww4khxkgxn7K7s0Xc3QEfnlyRDHcTpalH/y4AuADf7Q6+fQA2twaKKg0Zo4C\nzQArWj4bfJtMZfWDZGnoiZGJxJsN1crLMYjWRiikUs2+DZDNNByFl+ypnkhuBuBgL8C2YliM1WBJNU\nkIEnCSopm8rtjfXw2iPzNd0ETpJMcmRuR5Z3qXb79HJLTIvYTRap6ze5lLCHg1wOfJ34eZbgG8x4KD\nY0X7mwWEiekSIUM7P+71dwniErSqcD1iUvhuQGUeISlGW1MWMajyC8QSinicq0sIs3ax7LsYCfLf3a\nGWQ3giK/SBrQUE9Ops+GcZj0nRGR5WOs0iM+DJRFDVBlYQS64o4HsHuLoTwZBNMLU1qX2qSbJsSobr\nA4AJ8t7vamb7M/jsqnCwKKa2HWfE2PxqSh0DXGHKxZFlGbvt08iUkyxFrsMYQZwVxcwf2Rm+j9uu0M\nZ37Np+9UQ4uxgJ8ty/f8mUA5KbEdu+/rdjdttPtHZxP9GyGMYYsy8ntgKwzQIxDrSOzllTMKba3YDS\nyhPBtaGyO1TKn5sDODIsJWIDv9h3xqPK3z3weAaABKOsnp7tDyuEIGyNWDClBQDBqMZIRsCQBay3UN\nWk8g2IOSZ9EBYNytGqEFV0Yfwvw3e7gS4dB00cyGQ4iXxRiMTtfjsdQB3JjceIa+w4BzYjJUadETBB\njRLwnFQVMphDj+abOpxwCW0FIB0TMYizAd9uqnfHmJ/SGx4/NJ9Nz1bRo7Lw2nAzjSEZAHT4mklpqj\nYS6JtWeOJ/D1jaU1TlCfOzgcAnQ2E72AnwL8N3Wki+2ki/emMPXOt6T9+dHe0PqYk4mBougqhjnMFm\nOkYwUmyBQwRBCgBShDky3d2E6AV+dv6FIRVKU2HoTF2MBvttY8qVbsjDN8N6fn02mVPOySQdKiZRS0\n6nIZs3bVZvHzrb2nGBIzGeTxu6r6/OKNhKzJXgWZQP/Yo1F9bI/T9C1iz/Spw9NQz4FejAlUlOzCp1\nsd/td/UtXcFtzenPBxBx1UKSaEC1djWQmI9VgnWsKdkahmxx6bQR/+Hm489S7TLXbKaypCrcK5Aw0x\n4XFrC8k3+180aWtLn1TcmvTaUjfWRVFz1c1GiOookkQNc0tQUqJGCMpNLcYAr6uqeYlVTEnDIcwnvS\nI+k5n7H7vzS8vJ78YC/DdbkP21U5p9M0YIwI4BI3x/GS3sfdSiKR0o7qoKRFCQFOCmNCgaB1IPhCqm\nnI+Z+vaBmzvQEznu8YtBN0CfIuxPxKHlfxAG3uulU5pXj052xsR5h4TFQJoBFFBkqBBCSkRQ0JTQkL\nCREGiIjGhdWCyNyRt7UDpn2wmObah24uxAN9C8jXgsxyEnhgEB6fDdP76+d4YrTwOi2jjXNckEA2xB\nu89IQRSSGhImKRYFSQKEiCVNeONbZjOX0/ktNOI1bb+52LGF+C77S/6fkiLE0S0aXEZw7vr4Uj8aIq\nUHptAVIkxIckiScAnfB3RoCSfSJUn1REJNFLRe0IZ2L56Hba2BR/f7ZKQyyKTfQG+xbhRBLZ/LKDz6\nvx8e0iazJEqYqOgEVLQJjtBHRrb/D9tX/OJWEeiT3gfqavAbDrl6vMvMrx6HWbz88S238OiR9hfqLG\nwxb9GmFONIK5pfpkClszovH63H02xRY2tIyYKISopAmohKkYdYiwiilElJYtGJSbFR8XHyHQ2Z4Qy2\ntpjbVa+m17f4DQhsWFOv+peKYs9eyH5/oKOl3Jmi0jr9G4c5sH7ZhIUqMMTroontp+/Qr03oRMgzit\niHRFxzOcVVeUbuy8m6ipSzCrms5JyXlNUNUVVMatqyhjx3vO5T3+GsL17gpSeIDVBnokvZ1CPfu/91\n24sNX8TYXTkPTd/fuHIX0i+vzDgk1s41ywGS8LmFjRhswxierIajTCzCqkjztOQJ6ntdxkVrRMEJXR\nNWwLekKIwrz0xRqqYmMbAqC7Y8yXF5hbj3T2ORX0STX+AGoy1reRtgHZ0U9i/LQC0kHyvOsAd3fmP/\nr35BhFNjQM91XWDsKp6cu/aJmkypxPABcUkwbSFADUJMYKvE7WPhAAhQFlFJvOaYVGyPZuyM59RG2F\nrOOTChQtcfPYCeP8kIpRlgVd/ADhjDMaYryitF0BcSL5XpYr50he9bWiibYSnmGVieke5N6YTIasTJ\niQ0RKIoUSAmg8QGp943sZ6+qqnnJfO6Yh49Y18zToFpmdiaTCh9xYULl3jrpHgHa6vLeZ5PklhU9Yb\nvt39/X53cB+TR3yiL8JiF5HtVECrtQr1ZnTskXJSjmeaQ3uWHw2y0tUU1miCVR+cBX3qqsmZeeXxM+\nAAxKAlH8IlyXjOrAkVITENi5Gt25gWX93YpgqesPBcuXOC5S5cy6vpdMTbnjDEeqJxHpbOINIm5Cwm\n4AN+rSeodVStvBtuXfS4F9jl/cRnU/j17W9vMRmPK0QSqQKw9ofZ4HwkpNfl7SQkRYoI6wLyqmc5Lp\nmXFuCzZLefszAtmGilCYFRMufDsRa5duwZJ35PlOYmm0vVR6bYfK3qzyvxSqvViLMD3qrL/jt72e+g\nRA8TIfDw+v7O13YSKKahP0AZNp5RIsZFWPgbqumY2K5jNCiazOZNpwd5kyt5sxrAoGFZzJlXF3mzGX\njHl0vPP8cUvfpFrl198/7ycU6Wasizx3h+omfsbxa1s1sVY2HyvKgl4VPW81YKeT6agynhv7wlV/Ya\n969f/zQvPPTfU0fj1/WKe+yph6pqQwoHNl2IilR5becblDF/VFMWcopgz9XOmEijUU2lgHEpCo9zyw\nniHX//1X+daXXDPGx+v1s/c9Uf3nzr7h4PB4FMrKyu/NxgMPu2cwzl3S9fBwtb7MzRPbscdzlPSRFO\naI38P1QCNbRl3A02nythkipvGZhqSYxBsW+jdtoX5AjAPje/cojjGOPbohhKmNWyPHg07o/Ofuv573\n7o3nn7zZ75waf36iyNOd0/zsDvDyT3D8V3F7pXEqqSQinIgTLPIuJ4xns+oqhK7u0WZAsN6zrYv2CO\nwZwK7WrMdPMMI0UEQRx2UGJU867O+ssbS0hIPn+rz0GOPcuaBezlx7vTeg48/9ltn7z/3/ywtLf1fn\naz7FFHJbQeNhgiI7Ta/jcbtkamSidzQ7OWw6xJH7NkbukQcGenI1ZYjStjLKWLpNaWw3Zbgq6jbhXM\nIQMNhuOWhbdZEoohpc89Nk3M3ItEhawsSgfcRUUfHWaxAVU2QuEcoNvCTjbcVm1e/a+u5y99++UuXH\nr/+4iYvzq+zNRrzhWcuU0yFJ+59gneefTPn/CprY5CdKZoC01QwEc/c1BSpYjgaMRmPSeWYOkUmqWY\nnzNlNnqEJ7BLYS0oBeAvBCDEJITaL3ZGRGYtJBYOOpb/SY+3EKg8/+iCPPPoADz14P/efPfu5+++5/\nzeOrR3/Nddf+X1sBlmHGou3FiHD4m6AzAHAUkA14lrSRm6IZTsKmHgL4L0cqNJrzlq6TcHnj8i8tk+\nQHpnQtp7KfqMRNTe2NDcpYo0AHsE3z6YAsznMZ8StF+4bbVz861svPvXXtq9deny4vcHu9h67uyOKW\nc0w9bi6tculywUuc7zjsb/EW8+9kfWxhetTBkGwBiZhxrCcUlASY2Syt8vuzg4TG6lJzJJnV0tGePb\nwTEiMUGY0SfLxoAeZgaStImpY7TqCr0kR+haODWCtC2dO9Xjg7N08cP+9PPzIYzz2xjd97tT9D/4LT\np75p7jOJRBULOgpVJu+7yL7x20u3H5VNmk3twOJdnSZSbgFkF6p1HvtgO82tfluVnnayT2KMGsQOSx\nBFI/clpNAqoESZAr1FN3dZHb58neEjSt/Y/vZz3+n33qR6d5lUjFC5gXMSsxc6aqBaYbfKuiUcO7Yn\nZxbu4s128ekmipFJnUAo5QamMaaedWoodW0REjsGcUnmAFjDEOUCcIMocYQ24bT+z9HJGEyg2gTvbJ\nX1ViFdQd3rcCprjBQZX06x12/wAubz+CvfJ7RC59+/OzDjz1+92Ov+7vH7773X9r1E/9Qlld+nbSMq\nB5tMAjGHdm72n6AB1scN25scjOAbk/ez92e0DMI6aVblB9ZC0nbGs/7QFTAz0Dn4PeIwxcZXr34vtE\nLF95fXn3hDW64Q9q6gp2PWKkndDVA9IwrD7PGRTAZlexsNsdblyVWgiXtzWAcyZNlWhZ4qSnwFMkzr\nucUkwmhKhCUXQNVikzVM6RmTGRKokLwCMFkHJZpSqhCjG0omQHpOGyK9HJhJXesW+VkFjnWSwxSYm0\n1o6NTphvPcLHeZDp6jjvP3fudJ+8+951rJ05+llP242SdT5D3GgMXA9GRxCKmAxgS9gB+B3gT/hj23\nQJ8r02W6dDK+/IXbnYZxIATwVjXqqEK0yvocIPR1qXvn2xc+v5y44WzYesyDHeQ2YQVEwlaMI0zijI\nyKyF4MGLIxDH2iQgcy7ucXT/NcVlC9mrCzpxU1oToKaiYSs1Ua4ahZuQLEjUWx9B6ilgzoaYgMkWpM\nFTtlhL2u6NYB/ijafONHZsCSZuKZxmGnhGOLy9xetWRuznS9ayudxkc72P74OIOxcacYbmB7Ky/QWL\n28cHy2g/btVM/TW/tp2EA0sPQBTVoS0Dtb1iHXXJTWyb/FstO+YpzcWuyZgG+V92wuh9QbA/L+N2kg\nRpRNNU49U2ty5iI8wnFeEJ1+ffft7dx5YcmVy/eY4Zb9OsJy7MZqS4Ifs60mlJrzRSYOYPv9pDkSHN\nlOvW8MJxQAnf2V1npr9IjR7ynqiLldM48VhQ2sMuMnThjr55RSMCTSMzZTCVlrCgIrdUp1AgRQY1tf\n1DznTGmTZtoMtnFgBihK8rqYIn15S494zHGoM4QMsfa8SX6x3p0VnJsR+h3PaudwHo+Z9V1uT7890h\nYP7vM3f+AcOcH6Zz4cczxT+COgeSI2ltgK+z3TfryZfeytEO6hd23AN+rlGVKLdjsQUNKPaIeGQOWi\nEgNWkAsYLrH9Nrz37Fx5fJH0uan36LFBDcZ0asn5NMZZlpAVWI1kfX6zNVQzBOjOlImQ6kZ89ozmwa\nqXh8NJaY/oPbKbFzSKZt4zTIFtmdjZnlgK824Vo8Yqyc4YZ4ikzhjO84plZbqab51gAZ8GhBnm7DRl\nA515f3OtAoaFTHQdZa15WVWTc3yQFm/Y0BvOTK4w+JWLLan5B1YXepyrJuz5BLEGb1sE9KUqpjjdHy\nPqacfl+78v4Hwo7j06yI9mgbW2WsSNAvwfTUjNRJBUZLIAQD3BWAiYuIMW4+h3Ibh1fuKjed/bHbtu\ne/WvW1s8RzG13RTSV8rnHiSDXgjRHGUoaJMileDOiEGZV6VVHVNSoGRF3LJGKwdww6W2B3P6UWBHK7\nMR2zHgpRnjHxkbGGKMEmBUgIlllFqgCcCLoOyVoxNaFSyrI+v64boNwZSQjGINmqvoOSZspxZus7Qz\nZTVnqWbFVhJrK320Kyg03EsrfUYDPr084yutdi8C3kXK2NyF8nzHIwlxkis5m+xMvuXRsb/XNz6Dwv\nLlwyDFoCNA1/bPhN64Ae0yH4ZRb1xeg6y/EURMUfUzbQA36tb9DWz29DkcgMJZ1BsKrA6g2obf/2pD\n46e//xPVpvP5VIOOUbAxjEpVKR6TvB1E6isieQcRjIk1oSipJ6XWGdY63aRgbC7MWW4B0Nfs2oyKjX\n43DHLEluTMbP5jE07Z8fOSNFyfb7HOFbQ7zGtE8NQNYm1rcljLYS2sW2336GqPDE0Va7RdGDrNUlJr\ni1HL9RVhSeBRnKTWOrC8Z5yYiVyx3LN8vGM0A3YvMJZQ+YsttODTg42I3OGzAIyBzGIqREzJ8kUTXv\nfLXr8P0bWf1BY/5hhHRgg0kWTQxRS62o4dMLfWF9GzCthqhfge5WCzzZkgAZUTLs0E4aIY474PardF\nx6eXnnqY9X1Z99jhpfpVtvkYYyJFbaqqOuKOpTU0RNRojT0ukk16gPLWYbVxMx7dveG7OzCuICQQd9\n06Ls+UWCzmOKLis3xFrNQE9YMS3ece6q/tvTUkvpn8l7/uc7S8uU/evrpjd/77L//3Vrrg3CSKBAjd\nJY6fPO3fMuJc2fuXo0+3THaG5+ajEZ3b23u3Luzs/fQbDZ7tKrqR0MIxBhxNgOBmBI2h7X1LneuCHc\nszRnIlCUyEgmkQ6fTpbvSxXT6YHLAkuUDxLomKkHmiKkwpkB1SEo7aNjJxdzxM87e+R4IHwT5EmRNf\nbZWrVf0IKVK1dyU4vSKmJcF+F6dvgaDpoSmiDEBZxJCDWEGfkSx+dx7Z9ee/bnx5ae7rthg3VYsDyJ\npVlHNh2SlI0aPpAhWiQplnYihRjxIEqRWxCsSG4d5tMokwmYJ8+Dp9hMboxEu2904duyO3zr3yFt+5\n/RD937y9EP3ffrYqfXi+PHjdJ2lm/eoysg//p//GV+4fIW92QzyDnjfBGarcseps3zHd/4n2+e/9V3\nbBrkgQDGZsru9x+bmNpevXOPixUv9C89eemJjY+Prr2xe+cZquPHNV7bGpy5kJWeWTnLfqRWOHV9ib\nbkGU2CyRNYdQLcPuYPctO1tFekstd6CACYh1mNsRZI56BzROaqepOY9Iu4zQvYBcL/UuCVsa52apn/\nEgU1oX0aqvbZUztsWfIojSUBMwJg2arHcJY2u4UdXPjG6/PT32XKXVbYxZoKppsx9Ab5ADaTUVBNTb\ncu4ix7s1knbiM9sQDIdirJmo665XldMctDj8ODxR/+/1z382P/+5te98TcffvCxT9197330T6xjVwf\nkq31cblnpdluvvqEeTukeW8esLLF+Yp2uXaGazyhGOzAe0ukf5/S5+7nn3gcwGknRI0mRRwUxOSkoe\n+NJsbmx9e92h6N/90dPf+5nXrzwFNe++Om3msnVJ6cu/YdX5913dAtLbTJO33kS20vQyyBzIBaVCHl\nAugZxDjWpkX42gDGISVgCQoVSoalAdEiQvCti/ycj+vXG1O9D+kB2xIbTWwDLvOZVztsWfHPAiWlqW\nVJBtQd7zz1aXnv6l8vtS2/PptfpMselOeiUyk/xddXszXkHnxlCisRQQ1JcVLrR4MURbM64ipTGsVV\nHLk2Va2VOOvXIH77hG5/453edffh/eewvv/PCmROnOLZ8nMzmuF4fBpZKGrwFLfExkAXAC5Um8rVV7\nnrsIY7dcxab7mVvZ4MvffGP2KmewWTLiPRIgPeBbu7Q1BRRIkXE5Kyur7C8tsq5mPj6b3or0/GI7Su\nXPrV3+eKnys0X/l7Yu/rAeLr1nxbl9nfX4+xNK0lZ7hq6YsAl6CSkGyBXou01G45regY2RWEExGI0A\n+2ACEkr0DFJLMmF77OM3yh0vxfufWq/M4U0RRPZDwpQFUQSt4MT/jUJvpeLV40iCIaUPKYcwfDFb68\n2nv0Vv/XsOpMXWLMVUo9JZUEIjVoaOzlRwUdIVommsfFcFKQ22EqoS6FMQpUN2IqWra4je+TRf/ime\n9/8j85+3Tf/9j0Pv50Tp45R5nss5V26ptfEkDZNhvCAp6YvOU4S2MYeTbZElvpkp44zOHsX9698E9e\nvPM/m9RE717fodI/h8iUUyPIOPswRgayTN61XmpK8GCBzlmExpjvocu9jb+Khx95ELArKve0L843LP\n1EPr/3E6NqX3jk1o++Jcfw3+n5GT2qyvIasBOMJrkNmsobxwYI6iFlbCrELKQOTY6xBxZNkiEpFJH8\n7uN+RdOa/NuJ+A5Ebgq8PokTV3kB/vlbTmm5Lybcfr+m9J4333ldtXft42r2GLXcZaImLM0hzjFYkj\nfgEPik+WRKCTwmDkIklw2A1EatELAJTn9A7jg3veuihn/26173548cee+u1/pk3YPp3NKU3gdwsE1E\nCYAViVDxNFGSHHEtTidq6DggY5+gsD+jfsU7v5B1kaRmbL4Prg+nT7awgJqMO4AQ6rnPg0E5AUI/Sq\nI8isNJfImGoGrlP3u/T651j6fg5mIw48+Djv11vf+m397Y/83cm1XPvD8Xsbw365VreqxDjUeNJhiY\nbXg0kBykH6YDpgGaNamkMxiTU1CQ8ikGRdav6vyXC+61kn3jpzVNf08B79YJvvwqD9e3yAchQ7SAJJ\nArYCLZsJzEj0iGmhqdYtQEtrzLa/cxH6tFnf8RMn6ZXX6cfZ0gSfJ0obZ9pp0dpA9YnlufC2qhGxhU\nlV1HXpzJ9rqaMzbpDOThJ/4GHx71TD/3kfW96x0/nayeLwYk7sUsDkgMvTZKgQ8lxbZ/0ANpMglODi\nrRqZ02n1yrIyeJiYnloeHh4kjPXTrF5WgkZdPo5xIKODUg9o2MgaSK0PWj3SQyR5p7d5w6DHDpXjq7\ntDDi2SvI9smOnOH7u8WvzyfWPlNPNH9+bTr4/K/wPZo6V3ul/g8O0Lc48SAVmBq4HdkCswMgAMdrcp\nImmbTx9guN3ENP9OKyfhGM/CisoPSIdVBwqTXaEIbZpW9I0isEiWJLsZ078yYApC/B9te6C/f/slxv\nj+2GbakEjSZp+JAo4Azq9wGx67aeqyZUP6XwHG0qESJSEswnNlTpUpKT0nMUqkDxBlV43Y7V3jp3xn\nJ1xzYQeq2fu4aGH3vrROx/9hh+zZx4eki9DtgydHvsmTRZBTERECAJW0k0exsNhxZJISPIYDMEp3kQ\nK8RR4MitkxmBMw8tHX0NsAsWN2T9iOrg2+6CT/dOZfXLDHqRN7Wt5AuAskvdxA8Pyas7yfLmoJtt/b\nz7d+fl5Wfywq9Z+IDlwRKyNDetJajYTX2Ftv81yaG8KaERN2w5bPRoFMdMfQbIVcB9uokw7RBXMfgG\nq1haUtsOuIK8gFG0h+f5sh6V1lBug0+oqDXOmZr9ymG1CqVTa8KoKp03C53Dvkz/rp1sfCNMX6NSbd\nMIEazyaRbxJBOtxNtANHkJC50qswbgOMe+wOYRa+3ROrnLs9P3/6/GH3vjfZw++/nOcvB/cEtAjkLX\n2C809kWaVByXkiUQi22dJ9cbNoyEhEl4jmc0JTihsZCaeWRbpSEKMtv3VI1U9b8kfMPaw6bS0f00b4\nbKPdTWpfbW5hnqTOBDTgN9gIetBZuj0u8jy8tCWxQ/aNPsVpfi73k/+o8gYxwxjQTUQqXFm0Pye1Ep\neEsZEwKMSkDRHqUjJIzZ9SIx0IP9bhlZl1X1Hu6EtGdyUtDiQ1LIA39eMUJF547DVjJuFh0pE2x0ds\nRhjMeIhjonVNn4+J3sJbgAAIABJREFU/NlUfOYDzIfk5R7dMKUrFUYitVWCicTocSZh1aNlRNWQXId\n5EPZmJTtylpN3n9u4/9HHf0Duf/SfcOpuyFaBjEnlMZ0ugYjRSKd16DdxlglEiSQEPSKb2kWv+w5m0\n6Y9WRQhWqU2kXmm1B2l20qPFGvQSDkbU/s5KQasNBn3rtmBjli5h6RiPKD19QCeHKE4BAiqaFSMCJn\nt4lxOvrKCWwmYSfY50vi76nj9vwrp6keTyCljSqwJGDJiDIh4DB6MYIySSFiNDfDjtJG2Mm/iZ0U/A\nA6kBWBsxbc1bXpuBGl8s41/cAG+ryFh0qhjIhxGRQtgpM1gO3zKCkANYZs4e+an5uPLH3DheVwqcDq\nlpw1IkiYSihdFxaC+Iq+bWibRdBipY6w5dZ5z7Bu+/Z8eP3P2b8vZe7dZPtYSDTlITt/mBG1URyMGQ\n0JpJFUjftJB5rfZ93UdyaK3R1RqJ225Bm0kurTEIqmGUKOxAgJlNaepyZluTS+puQXlZI58hxslbyO\nVs0b9pAsonsi+NdntPAQ6Jo8r/4TY+z986v5MiLt/3eoca1oVX6vGpEw1ooLR/VqlCU1jjLUtW1pBi\nIB8ANOpMJ0Po71Gapo2/pNmbjD7W9YipehrNmK7Z7tDjvpAcqiYg8zzxtyKiB+ixYsf8ZMvfShNnqe\nfxmgscVpiUmx6HqREVEXFNZ2AEjgMErvsjj1b04yVux/jode9+f2Tx5/8RKe/3BAMCKlOmJSD67R9G\nA4MLwJKTSTRqJj7nq3GDjOHdSqO/pbUSC2TBJzgIvRsRs/aRnUOnhjqJspGhBBC6+iX/RZINyauSqu\nWS2Pv2S9LZk1HFDnTxp3LQV5e0ERKbeNq0za1dl3IeuSpv23Cyn9Zh+v/Noatj4c4otcFk+qmxIaax\nvYODqKgSUhujN23CdVCjCQVjMs+hMgYWf1RzKBlgATIDtzxr6Vws1en2vlSmdCt8RKOTJEPu6TJc+9\njfPFHtHge569hIxAFm1rbMQWSCjZZjOSot5jYJ3rLtHSUrsvKubOfPfvGd75Xvu6tn6q7ZxDyFkSCZ\nIlcHfhIrCtsp7VDTaNm7meTpta+6rYK5Q3kkd78O2zj/EuJgeQcz/usZl160RKDPyiqiyg+xTYKxbS\nM4iGQ9i1D3Y/AwbTf/Oj5jtRY0YTRhtiQNpLHqGCMO/CnRwtGOohkYLs4WQGz/gnPyqdSuvpLyvANa\niqgQJI2dnnqQuo0THQ+B8kgGdCMpAG0CfcTnf8I9uQm3PEJdBW0ByYjteqnvobaW79K2c7OgdUkN/U\nVkNausQYsM2J9/dt98cLHmT6HrTfpM8FUHVJSotQEqcFEUhKcZOTapyoFX+UMx0rJEicefOJXV5/4l\nu/hjvsKasF0+wcY8YBR25wvd1h3ZGGL4MQcQC0QGtuHnMOaMY1E0v2sb23ivg90Z4XMZKznfdZsn34\nURi3wQghoagKkkzSbUkwRZ83BJpUOKIvDQ+b70360sp+mG8GvjQFqjuLUt691laAGSQ5DjrErOFlG6\nHwqRvuOmMI/Smb2V50qIv5Q8pomtlNMTdKExPyAmVWzAzIlMsTK9ONodRmV34CcGDKikYbDIZG/1sB\n3tLDrrRybL9f26o/jEH25CJSXjVAxDqsJlYi0/jNSE6lvAavg8IhuPTqdXviVevw0Hb9BHqeIn4NfJ\nUSP63ZJpmY+HZNj6CRHmM4JswHDMcSl05x93dv+fufhN3+YpbtAl6HfZ0X3yZ1WmphmXdZteUHVgJN\nG/TSAbdVKpzn4gHZa8kAEpKmNWbU5bM6AltB1NDaRb36fVpHZ7hBnB9SDQdNUM0aoSmK0iHUETZgYM\nGIx4g7jTTks/qRAaIkd00pc2S9Sqgl8aM7bBLG2z9/o4gkkjEgjuBKkYBBdRWwgz1JRFJP/zMTqp3y\nqPiQpkhEwWjUbjQkELTHSO5BgST2aiqaqmdlkVmzR78VfEbvyjcSVp6CLNU1MbqBC94k2ubWvT1/OH\n6GvbH3eqpnMV7O+bz6GO/rCX5QKxS/3HSQJxtiWSq9bQ1zaSAvIUkLDFuX04i+H0TPrprqG9buYUKK\n1hyAkLFNfoXlJNrD0Uo5MHTY5ikli9eR9LD/wlh/iwdf/BMfOkOwSUfqoQB4OzSkVmqrSbU55Aqy4w\n2jFqNgUW58jkFwjicy+2zkREWJLFhmg26XJWKjnzTMB6nJO9IGUEpkzDLo9+v1uQzKlRF2XWIROp9t\n8NsXGxhJFbNt3r2mNSSA/IPGlrYZtDDhjkI5raf023We/h98NpE2jQps2takJSHGIDIBj9HoPkEL3w\n7HubqFbP56kwEhoik6RwDbBAJKkFbgBbIExU8SCsVO8H6xnaf2Xxa6+w2oPHzKS9dibuiztO+5fMfD\n+hOvvZuHzUs1Fb/X5l1rP7uY3vZI6ni91kldaA/Tl3vdy4LOpZTFl/2InEgHBYlSwcUQ5fv4Txe4X3\nh6nF+nGLWycoqEE39gW2IBPJZo8Wcfii0Q9KYhTh1s+zfI9r/ubPPaGX2DtLtT0KVu/nblpBxVpiB9\n7YJHs49K2722/6JEAfm0dx1E9QSMYiyUjxzblKzSBLyDMweYwnzOa7jGtZlCMkXyV2XREVZUQPcZ28\nVWJL+d0yKGqGollLc4KzjTpO40rXKlCxDmLaVVdrNnfxg4k+kFFQLtPc8QDTtSQHS73NhNdm8A5lFV\nEcqzrIaH/E1H6E5Gdn4ddMGPQEpXG79g0+GxYUCMek0rU1DjxBH8FwvG3590Tn8D03mdjF0mCtY2mc\nHQN3gy4l11fXyVpc6v2AEcfH+1S9cey+f44nUn/pJLyZSXby33pVhtCLJGGZDBGMaaCWMP88nvj+NL\n3yeh5OmGbrpnhYgU+NiUK4ghjPZkoSS2pFHb2avykS69zgpNf943fx+lHf5GlY2Ac03bh2YazBBdvs\no9AVHF6hI61rSonN15lVZAUcAYy0UNLLHn8tKAeTxDvcbEexNnsLWUVX//czviR55979r4gHula+ks\nZOzs1KZTgIDeJK5cuvPj7//Zfby0hV06vrV9a6fafXhks/RHdzh/QdTP6GS6zoIG8dxxIhNRE/9AWk\nlKagsLuyBc2R5z1+56drC2QpHJoUR4GrPWBHmgXMX2s7f4C2gkq+j8iHpGIamgiXlqXkW0rCxAbkid\nTj4YRKV0hsf59puM+aczJXzLSBbIb1sefhbZ2Kwy8Ekwc7U71Sr7TV0243OrH/1mrrkY4Qih0G3cCC\nSgg7T48Hz3zc2lygbzaoisVOYEUEj427B1phI1CRyHFLlUtlJMe3eX7OXnfN/5NHnvHL5Ktg+lRqCB\nisEdyA8qWUbStH1H22Yx4pPx5MgcZ59q+FFoZ3Q+xKfHgmwrXlCVhOGTvyvUnh1evvHu6ufmXs1S/d\nXt7m0sbm3zu2i6f3Z4RTtxD7+RJlk2grqfU9RSKERvPX+VX/9k/vvu3fi2/u1f5J+4/eSf3nDjJfWf\nOcufpuzh5+tSn7rr37v83O3Pq/2Z58JvIDKzBSeuwbsPUQsuGtl3jOdobQY644yW2Es82AFL2k2JzI\njkSwNJBshyxFoL+Yki1A//zog7STlPZU2qMaTYEUgahf3DBslBR+WuUlaU/kJ9jIL+NnPwSVUI63a9\nq836lNt8fR7rdvCG8kk3B/XFVwj9NCfgn35oOJU5DrxsSFXUcYYvnPlbsPdXNi8t0w5CcAgioT8QQC\nAh9U0MEVxl8mROrHl13huN3v/2HePibfoHeGdTk1NZisY2/jyYoWtQQJR7MYcQ0sfpiGpZyH22tmpm\nSIpaDpiqIgaKCvR2Kay8yvX71yXo0/Gv17u53za5vrs23tqEsMAaK7Q02r1zhwuVNNjTn1PG7yHOwL\ntEfZJw8tcbOtSXqnRFXLj7DKFQci5Bdu4ZdP4k+/yKbS0ssrQzeevyuE289fueJD/VW+sO1Bx75tWM\nnT/2L7Mzp32RlDYwF63DG4Iw9KPLHkQYy0jrkD2NEE6i2Vb1N6wDIGvZVW/85A8juAJ0hqfgFH+Ny0\nv6PO7fX2HmprasdXbMz+W5zXwIiAak3CbGkVNPtuqWPkS//B8T8K649Qf5U7L6vBg+vlKR0f5onOto\nW66vZmV7281oB3QM1LkkTMjWfbnwwbT/7nlC8QF5vYutJo4a2XiJVIRIQmWNqgxQd/NjQc6dYvvdtf\n597/tJP0HuAQrt4m2GBjERGQmJqYxWhk9mWRVQSBm8EPbKhxnbBWtXGPk2KpECal1RlSe+ZC4ONF59\n//+aFp98737j6qJsWZPM5bjpjuZiT+Rok0h9uszyZ0pmUKCVaFxSzEWa0RVVPIFWkOMeIkpnIshVWj\nGBnE2zWxboMZjPme5a94TbF1Rewzq25Zy587513n/3eex58+KnVc/f8EsdPfJyllRm9JXAGZ8CKaWy\n/g4Brc0TNrg9tWFw7n47U0r/Slg5tNJQMslWsnqIO+hPR908489SHNNaEUGJjxHiL+D7UDfhSmhFkQ\nqljqrhLVUbUr7ynt3L8g3TXPnYrhv6l7L8/TcB9JSLmK61ZERE9fENPmgMVr9jV8Oe1W7yikWqQHFV\nDbON3vff3TabDn6z3rrAUx0icIqGEOrZrRA4CSUJdYKocKTNc1aEzOP2rnH3zh1l/CFgi5IelBM1Bn\nficI+Kuec3YFvjtxn1EUcuATJqQMMqaajRmtLGxMtkd/kD1yT/44Gjj6nKxcY1+PWcZGJQVrvBk85o\nuiUkxwQ3HdMuKbmqOlwOZgLWCMeB9RZgMkQRdJ3TEYuaBPIMlY1jPM1Z6A/KOJe900JiIoaS4fp1r4\nzGTzZ1Hj794+aMnH3jkI8fuf/BjnHAfpefGGHNY0u9A05BDt4Np07hkP5nWNoqpHrg3CandfCwgPch\nWcd7ja/fhFPRcivVfTfUEao+pM1xtMFUO0VCUFTUTStnCG4iaKKcnOBUe/Mn8xH2/Dlz6arrkyks3C\nUhH1m9HRPbz1dZEZNZO8TERWQMuA7mqPqSqQVU3gHuBu4wxW+3xHgeSqu4A94vIOeAZ4F8BTzXcfDB\n9iaIk5tLk3giaFCeNgh9KxMQmUxPYMeGgO52haRuV7cdNaLsDxcP5kXaBHmiLDcF3JLjpkF1LNz2+l\nbY5dT2WrCEHuuUYW41h5+kf8xc/mevms6juMPVzbL/LbDRkdWUZrSMSPC4lOuEBtvdKtuou6w9+w2f\nv/Pr3fA8n7yfhCVlFB0enVaYEiEZucHd5tP3VYFKiiyG0wcwekKgsKZi6hs3r8NyzuMvPfdhcufTfh\nSsvrg2KbU7UEHYnyLiiqxmxKvGxxvU6bO/uIcYy3J1TxUYF7HYGhAxkxeHSEK3HGFUGa2cotrcYT3M\nGuaUT5tRqCHUkD4HV6OnOazq1xznX9Fxfyumh2Osj4m5BcfH6sr3/0t9ZfeSRD3Dv6b/HXad+in6Xm\nTFEDF3pNo5t38xKMA3pYWj7zRMRIN/v856aKAfV1IRtsgRmmdQ9g5qa8rnf+p6Ujj8ymY3fsLm9waD\nXJTeGrRcvMBCHqQJhpiR/Apd3yQZLXJt+hs215/O3nH/+x6aD7/7PnTEYYzoGU7VOmxzVgaruNQSuv\nSdBGVLYxshZhzsJbHpiqsget41M34B4nyBnLGwJ0aZUvz4zRGLcc3C/GLmLFDeoqi4hfh1QlfnWrkl\n6j/PhjPH+ReY+ow4PoBIxnU0/nJ6oxA0KsbO57SRZXV9eO3MWZOkLFenasShBRHBN3TbuxfJXCOmhe\nlK8kCRdNJbjucNA/Bz4RMedoI7XmIyfO35icAqs06TPpCC1VXc3JgzB7aImQ+yAyLDhoLUDVC7UjY5\noxGCzdFCcsa15KSJou9Ua85Uj153N0JiQELC2C+Od77hy4ep3b17axPmKoIlMG1KyLjsMQ6AsC7Lco\nGJIwTMsEv0Td3HnPQ+/l8FagVpM1m0Dec0BvX60n9GhVLOkFKk1YK29octcjtK1ApMZYeM64y899eT\nu5z/7P8Rrl5/ozEbEYooNNeoTqYqkOpJiatVnS/IROl08Qr6ySpzMmAOTqqCbIikFOp2MTsciLhHFo\n5LwyVPWkb4Gsu4ynW63KSPhGqlknSXLWqYwyxCbgRFCiISiwF/bZmazNR2OPnpHFf+L/K6T/+1gde0\n3yZoolBgb+87YW/Wbb6+SafuqmUZsitjW4dIGutqmH3zgdPH5L372vdvb258cj4eUxRT1gfloSCoq4\nrTCNoQoSQXJOkyqimMnT5Fl93z3I39lXnT6/UhmniPEjKRvwNqalPaoyvuAu3HuslFyF/zjpDTHmG1\nSOi11fVdP9Wq79k7XdUUK9V4KfjWG2sTgVVVDDHUmMYCGqD5YXzZpW6rKXrhOMZ3h56WapMdS5ZmOZ\n0wmU3zg3sIntouSwuSDux5+HW/8xm8ql1ZO/EZ/dfmjFvf7+6qTCz7hjA0YlqpUfevGePN1v//7v0t\nZTCYrvdycOrYyyJOfGV9tHVvqn7xjbd3ygr9gjPFG3FkVc0Vs53nT6R0jH3Sw7vMELcGcwtprOHcRY\n9ZRtaj+ESIRl5/AmCtgLqHplAHBuc+Jyw1GTjIbb2Lci1hzByJdMM+3qFzHmFnecTVFaBLs5tPq4qe\n++JHf/de/zXTzixwbVOQyoyORfidnHxp1rDl2bA0xifFsgnTXeOz0o+/n3td/iv7xJv7QdJA2/lKOE\nA2N3RMPOtCikLB4E4kHCZ+JTBM2CTocM3rxMnuXLv703jNP/e3Js1+iu7vNegwMFOaxRH0T+WJtjg8\nBtRlJEsO6IACzsmQkym5o+ujWAqbTZHGrlKjU+FDgfYlYxWWCNYY86xCtEl3TOdCnSMdYTJaTd7qIQ\nrSdRiUxGc5ajOsgAdJuga+Umek/Yefyf7q77c+wsvL90usgInjTBGwfePn0JjNlP33qSHaFtBRNg8n\n/n7k3DbYsLet8f++whj2decw5a8ya54GiKCiGy9iIeJ3AFrBDxBuBjY3YHd1BBNGhtqKCVyIE2w4pR\nem4tnJF7QtGKyiFRQ1Q85BT5XTy5Dl55n32tNZ6p/thrX3yZIFfbDvo+lJVmZVZO9dez/s+z//5D4p\nIBhozr6L/7c1vP/rYsZ89eeLYZ7vbbYIpML1A5EtuQVTtc60tDdSsg5HxjKz7LMI98lOjo6M00hrOF\nigPSRQHEZzI+wNsnoVYRzcqITCmwBlLCOGg9x7rClpZb48QAZzH2BxnzLjzecnxtVZ4m0WuyEtjZGe\nUNwVFUewUHyLHGUev1xVb3R6Z92Qe1rt9lre7FHHKzOGr2XfkCq49fM3Rq/dd+btj6dgfEcQagK+el\nw5BeCfCcSnFr5iIv3Gp/Nhm1n7Hdx5/uLVw7CVaEiYT3WgF0ZhIE8YbDeZ1uD5NU5K0HmSkJ5SObkr\nqDRrNEeKkdkdpAy6dkpGK45hIxUYIpaWUQkrpXXOiLaUcr76iC0Jp4ijdoyK9JIS6gFRTUquaUPHzC\nFUg2AfqPEqdRspxW1OxQj0rVN30Fxd/+cRjL7H4/CL9rS3W2Mb0V1EyoIQkjlOEVOhYMz4lsd7QTR2\n33HnrH4/uv+VzNOdBjoBPL6PsDmPExM4iePi2lTsDGZdyl4KCgCfBorICujnrz710++rpU7+7dX7hT\ntobNK2hiaRlPEme47XG5AZvJcZKusbjRSAjsNrLaI6NsrzdZ90Flo0hB0KiQQaMzUvwxQ/Iiw4u2wQ\nPA2vZdgHhAgfmZhG1BNFMkTouS0BHFD7graMWSlqAlBod19H1BrLWRKkU52LUagfHKmrgPiJm8/vZM\n/MzshU/GYSgAJLqEBqCGyUN9PIkJMTuG7JESX0IZVczdgOHr8swf/vS55567rH77aB4r3BQBKhzyfJ\niSJ9vRnV0UOQXJC88sQorf8xIs0WjlqKlItWKZpwKFTy+yBlrNEWqVZmQaw3B2WpPWyJIPlsr52YR8\nN4SfKmDFMKhgkW6HOEtwReltX1wRK40HPbekm4VZM5AYbBFRmYsfR8wSpEkCQeuvY4H3/mDxc33Pfj\nfmZz+JLXRRxEaslDupnQ5muko0riKmyhT/fjo7MTPvvEdb/qHgwenf+bbf//1I8ce/Rar58+i4xpFr\ncb68hL1rI1vtQjNhpC63ABlSYxptEjqtdLXMihFkEgZoYSOyn9WKBVJ35gcF1WYYgjsCUIhVQTIeR/\nEvPG+5CYq/XqPJARCQN4ohEBKGfKJpnCFfzdW011rs/jyacIGuC3F+nqXZnMECBTGImSMFQERSc4ub\nZKZnMl7r7w4de29H5EHbgBXA1GHSFO4EiIXQ3uTcGmlcRmI5i79u8WW2y1vsReX6J84+xObzx/7/GB\nxUdPeoOYtaZ6T5gW6nyH7A/JIk2cOKSKciihSTRFFdDCsqR5nN7dYaW/TMZaztmANGODoFQOCy8t5W\nwyItNsR8jdHWjQD0O5ybnOdVDgSKSjqDaaSOjJOGEnqJErRiJt4qRAiBhUjiBBOIgpB7ANprFBtgwv\nbBC/u1JF+DDX+AVHXf6SE+se2r5ev0XaSoAShCuUU1crGOMWBa2/njle/iaeePfGR488//0YT8lkP9\nBDEOi5vcRWhnYS4UTF3HFknsH5umbZcpZ7GjNabjKQ1CiVJpCAm0FFtrJLESiC9QwZf3fCqnHllmyB\nFSQn0BQSLV6VjOcGQ5Z2y6ERFIJCOEALO5BhnmcwU/U4Hgiet1ZAqkDlDfW6ewzfczL1vffvTh2+/9\nz8zOfeHWNHbATiUqDSK5cGkh7YYttJXp1FtTc9M/tb0/a969PqDe3/xxcMH3/7M178ed86dI/WBuk6\np56vUQ04jSKQD7y2R0NRUThISIh1jfSB4RRAaQlxaqcsYJSP6WwOElAhRra2FREiN9RLrPEJEOCHxT\nuACWI+wLuB9IIQgtluaYhDAxQiriLswJiap1SStmREGRRfjyodWBEXfFJjc0+5vMT41w76bH/jYnhv\nuW6M1j80kUuoStQwVMUVUKGfYDfVcGl3QQ1JvICIQY2Frg/bJY/9+7Ylnf9ktrZBsbJEUBZG3+O42R\na9P6ktl+GDgsSjQMSaKWA+WC9ttzm6us7i5wUp/q1Qf1Jv0k5ioFtMaqaG1pNlImRyt0WsnjDajSnY\nOQQaS5gjWONCKdec5enGJJRkxGafsG5/k4Px+picmGScpleEyAZXiZYStDhgZFErFEJVkNz8wmI22R\nokvqMnWgbhV/5VhV7mDGsrvxRCRVcBJRT8rY5OQUtLXnlpS574HH+Dc2dNri+fOfuziRv6HzTSlk2U\nMQo4WEc0oKm+ioo8WnoZQ1KVkc6MDwVFPUtyIxSR9YgENJWhEGpWm5Q2HRxGIZCjzFSMNkSSvuTIqM\nBh8MCjp0TgEFu8zorreIS2GapfssFgFRW5YMV36iWfLedZsh2xsgsNHjnDo3vv8/I23f3nP7Xd+kqj\n5eGa99zoi0RWKUIVjiZ22cxch1VftQUyKSMKje/bu/5fzb3nLT16/7+AHTzzx+K3nXzjG5vIyjZkx4\njghisseXgtNLZLUIkkiA/3+JsILPBohI7xISmsHYUBHNAa2/IKkqiDsCCk11guMBYSlsJA7CM6DlwQ\nfsMZgrGN7JUfJFFdEmEJS5I5+v0fhCmScsr3ZpT3IcTomE9DJAoVw5D7mrlvv//M7HnzbFxpzh0HW8\nVEJBLwyoy9Q5thdgl7lkMS4o/FUeOI8I1tdYvvYS7+x+fSzHzWnz9Bs99HdjMg5grPkvT7O5uRa4YU\nk0zUGzrHZ67JuLBezgjOdLdbyHJOm7D1yN5PTU4xOTy7oVv3RIo2evlh0jy52239W1xJfdAi2TxpBs\nyYIkeZNb3nzHW978I2H6qgj3cWlW+3m5r356tr+fGWVfL3NxSzHdtps6YjECXRaI1UpkYiRKiFEETK\npIdMaQSlEpCFKStex3BM6GUrrXxYqniDSv7CL6LlzKA278/LlEpdZQ4UQSo1HKMkIBsPcgTne+JY38\nOzTT3zhq1/563fnPnuXoVxTBGtAeyIHkbUEGYhI0DbDGEUaJ8Q6KWdY5xFSILRESolUIIJDCI+S1d5\nSuYqSKPBBE4IjeIFElmEwFXBmiSgGHZywWG+w3uBF6bmTmYIsy7gQOXwck8cJjE9w4IabueaBB5/Yd\n8sdnxNTc1+0spkNkLgoIqZW6ksDeOOJlKRSfJVLdgUkaCy2rHBvSaVG1kZ6RPXf3Xfn2FN7Zvf94qk\nDz/7A0Wefl/n5fyh9J4MnDo7WUOLvLN4UNKMIHASh8SrCCYVBlR9CBlpxWXTOhfKGDKakJTuBM5X63\nAaC8eAFIiiEC4TC4KwhjQ1xlLDZ6dJez0DEOAKdXkbP9vCJpp05Qk2QIdiyYLSkMT7FHQ++/uNX3XQ\nbVicQJHJXhJz6Hq1UEENx6qXK7HiIBSTBItvbrL700m8vPvrYh83p00z0C2r9gribo205RQovGKiIL\nRzbRYctH7Pe73FqbZWVIseNjhIfPsid1x7h2ltufvi6W27+8+nZ2a/Wm/UX09E6XTPgO0ef5Utf+Qt\nst0NzrlHKdFxB0S/9XGZnZ5981WsffHJ+fIoUgW1vUWy2r+8sr7xl8cTJd507euI13fUt+kJy5uVNa\ni3DRJrScqArNb0TEqEjBiIQi4ASAa80SqqSydC3EHofZWY0RvBzO7jK7uy/nZtuF/F6SLnaxQ91BJI\no5qZbb+Ud73gnR1889vGjZ868S2jQGrIccuOIiEijmKaskRZAL0fZhGYSM5Y0SQTEzpNqTUPHpBKiA\nFEoV0WR8MRaVvYWrvxgeUzwgeBceSPHlO+B92ALalGK9wWFFxgv8KqMW5PaoKKE9cMNNvoDRuf2cc+\nb3uyveNVr/oqpuU8SNx51suUMcUVEjMpLLQhSASKSVcb4TvGVT0xVaJSvAPbSc8OXfg210Uflodp7r\nmpNvmf6yE0fWnwqvuvCmTNsLS8zJkEnMSFclcyBAAAgAElEQVTLsL0+0gZM3qdZaxAlKbkXFMZhRAC\nVlL22KZBSo2QJa1hX0rAioYgSTadr0FJTjyIy68kLj7UWUxQUucGYrDQosim1KKaXOTJbYELACMHFr\nXVcFBO0ZBA8F/0WI40Jbnngnl+/6f67nk/qjYoU5odr9J3TCMA6uyNIdVTzZygTgbQqldwaT1jZYOm\nxp39j8fFHP+wvnGckK9D9Ab3VDUaiJqGXM8hy9GiTrrCc7G3S1YEzFxZZbm/QlZLpI1dz0wMPdG589\nX2fO3Dt9Q+Nzcy8mDSaCCUr4qgh8QkTUxOM1uvEiUb7jEYsqxcFigzStE69OUrcGsEai05T9NTsi/X\nDV744e/Mtn7pldeP6pbML71+/uPKhTfdY69zSRZYvXmB/HDEmFKmIUPWy+SJK6HqHDh4pBdp54qKag\nYKhaHc/HCdJQRL9wk7xKS6pJLh0Iw6LUEu98wNWSFLKApDUec39b+Q7jz/3/KmHfv/XpdIfa2d9lNB\noH1OTCZFPCIUiISEmpk5M2veksWeknqJxJLmgJgOJD0R4arEm1WXBae/RIpRWi9ZTeEG9lmC9RcvAe\nKOOsz16nQFRBKY3KLkDwWOtY+B9+d4KSQgxq/UJrr/nJnfLPa9+bOzKI7/D2NQfE9eBhKIIECuScgt\ncaktDxf99hSxGD+OCGQYoBlWuz+UwRSZCqABRPSOp/0FzbOrYdRNv+8XaiePvOP/iC9KtrjHIcoTto\n5IYKS2pLpEll5fCTSUjUp1gpMQNeUcyVK0u2ODYmenKFMeKKlQJVqUoX0atEM4TnMd7S5Zn9AeBTmY\nZeEPH9en6LlEzpe8K2v1NehI26XBw39Xb9735Nb8yd/Veimo1IIYeyhVdYJiYIxW74qKjHacFKirbw\nHeJs4L+saP/fvU7T39UnlqikXXR+QDyjGa9xvb6Nk2RktZHOLvd4RR9ToQBR5dXaK+nXHPzDbz29a/\ntXH//q351/w03/Nb4/n19kTbKT1Be+JW7Q0A4i9aaWEMqBc2aJlGgnEFVB0KsYhCKzCt0VHYZKqpSe\nNM6amz8xX1zc7840+l+ws7v/8j5k6f/3eLL51rrW336W1tMeolIGihlGBlPCHGMiyK8kGUQSoCosJB\nbQipBqI8SRRvAr+y0nvry9WwQl9Y1lxGaK2ArVgJRi9k7fwWvuvd1PPf8sV958fixnwkuHXHWoq1Ai\n5iEGk2Z0hApTRXTKhyicCR9y0gtRgqHNAVaOVIRkXhB7MqbO9YSrQRxJAjBYYVHxR6hS82jMTndgUE\nFg0wEUZqgRESn36FvHCaKsUAePGmzxfjEOG94948yv2fvX7b2H/oUrfFHEUnJPxIJtUgRnLwkLduxC\nAmXuHpVBZZYZZCXhh5BOShXg6YVpf+WlgJU5Ega/yDGrv+Bw+N73zsxc/j/Wj1+9J7OyVOqXywhVEQ\nkIA5lgQgf0D6UPpBClR6a3uOjMo65TPvxGFdasgt0RU0yeCkonMdYT+HBBI/Fl6RmKTAOCmPoG0dmD\nT1XMGDAIOTkHtqmz4Yt8HGM1hFH7rz+k69+06u3ZCuqhuuww2AZvhFDAEEisZVbyHC5LocKoQCxGTB\nYvPATq8+98MvF8ZcZ2dqm5gryojwxe6aMZu52MgwFy8Hz3OYqz9otsskmDzzwDu5+8LWfufuNr/1E4\n9D+DZIYh8IBxcCSpro8lHxVfKJ0ftaA8oY4glhZlLQlCQmIVUmKhhKy95XaQgZBrASRkjA+Rjw21o8\nnx3/lmmsOf6750sufWHz22Ic3Tl+gv7aKCZJ9I1dgjcdpXybOWtBG4rWqZjGHGOR4IZFS/TJJdA4p/\nqiyGi0d1v4xMnz1fOtyV0F6UKnmjjvu4DUvPbC1cPb8J8n5JYGn5iUTKmUkJNRDTCOuMZo2GJEGYww\n1nVKPEmSwWGfBC5SQKCkJwVZc3kp1HwTOB4x1GJmjQ4SKSx1oVhSlhSGObOBRaUxPeXpBkEkwKqI+O\ncGBI9ebuWuPPMLdD36GevPPiNLKHEpWORWVT6m8dPiEnUWx37WOkbuI1eEVJ1P1tg2Nd1xlShQA7z1\nNX0eON/5ktDZ1brQ18282GnPv2mqeIDt/ns2NDQpnGU01dR2TBo8xhtxYNIFIKbyUeAc2WGwozWFLj\n01QWmMHBdYV5CaQm0BmPcYHcmvJTY7XksJb+tYxcJ5BMGTSkGMx0tHOe3R8To7DC8HeK/Zv3XbvHZ+\nePTDPoOgRx+muE9nvMqy87Ecr0VKl7fKgREA4T7yxdvu5p57+fOelo0xkBeNFwPZ6ZH6ASWNWum1at\nQl6ec7KZo9zZsDLuSW96mrueevrn/uJd/yrj8wd2v81OTeBVYGezdE6IUJSS0rGX6hWil6UWsWyQzE\nIFzDBIGTJ4dSq7AZV8ERCElVroyFGVCUPwrC1doGiIUnSqY35RuPnJmZm//z8M8d/6+UnX7hpNeszZ\nsqViNIS6SKcDdjc4JQijkvGjM4KnChRarz9PLX4RSL95BB0eSU3MFQD4fDdU0LgnccF0EJAJLjimkO\n85jWv4qknHv30M99+8hdSGY2NpTXGRY16EVC5QQZLFElCocsxKYkujVBKIOME4qgiwEqc9DtKe+Md3\nnu8EMTelI4GMiBDgfWDkoMqAwNTYHNLoSOyWDHQmtbefVx9y+3M3H7HV9i3/zdpzT2KrjaRjtImvAo\ncDVXtuF2+POEVUpx0p+3cbQ8gLqFWvvryA1wW4iSlwPo6cZCGuPYwe656eGJ05ocm9h/68Mpzz9538\ndjRqNfZIgSPEYLUlbptCUhX0sh6Rcn7FxXxWHqFcyWB1psCpUTZngaH8wYfwHmHcxbvCzo5dAcF2wN\nHpwgMgicXhlwYCixWOTwO6z3G5Ry58chnbr3j1r4Qcif55zIj2WFfOUQLRDXzivJze2dLNXjw2H6X9\nlPP/u7y49/WyZkF6gMHm1vYvAuxYLXYpi0lq2bAQAleLnqc2t5m9u7beN37fvT3rnvg3g/tmbnekyq\n8khg8Wqc7i+UhP3Z403qhEGiiSBGpsrgKv4mMLGlNksSQZUCRI60lGn53cpe6YvjHLOcKnIzJVSCdi\nEibI1+7amru1nR0/HOnXzrx0+fbm4zIQCPWNBp1IhlhAtjcErxAxxGJc5Dn5cEgUk2sfxe4i8qx0Iv\nwXQqPIRpTjoeGgEUqXa48coeoaw4d3suRa6/qXzh+4jNy4D5ed566dCS+XIYZk5ObjCIzJEmEEYHtr\nI93BbVU04g1XitCVD5bpQJBeIpQgHMopVBRTNPn5PkAby2I8rvVWuJLoxiKADaqU5uYYHb/oezALbd\n8s3HT7Z9hcuovEIJyviv/TEHLnRHJDf1x5OWrYf/dLQBDPchug/+y7dTDX+SrGVGidnk7ep1UDzUgE\nglx9Jek6epUEn1Uz068c+3kSQbrF+lurJMUBU0FKaXnii0yrBXlg5AKrUuU1BmPMRneFyRpnWA9prJ\nEF2HYJjokju2BKYsv92ROYISgCI6cghzDwGYYAkJJWqOj3HXXPZ+94vA1BASxqjGM4RBhF0S3CzuXF\nYtfVYZMerg07ndZO3f605uPP3WnWrhA2uliO33c5lZF/VJs9npsNxssZT1eOr/CSi/nyL2v5p0/9VM\nfvfOtb/hUfXYajMKJco4IojSgsN6g8gJFBDJCiPJWs0N9mhRILdBSIBOPrgmiNBApyAVIb5DOgC1n2\nFAFyVo8zjtE5Q0hdqhzGqtduejdO+73xbd90I42j144cfY3V7e7DLoKF2laYhQda6zz+OBA6PImDhY\nbAkoIVKTvJIk/jeTnv+vWC+VkP+w6Q/XeREpirUXqmCIYkiCZ37uH++66h1Pffv6z3cW1j7utLkJ4E\nhUTSY1UEVYIamlCVIsRkabwFm8NkRdVEI5ByUCkS/K7FKG8jV35AZRSYCTClN6sURwhYkXhDZ1+Tl8\nqXKNOc89B9t12O5O33/kVDh7+NPXWY2UvL3Gu7IZKFUcJxiBFNaeHXQYiofIdF99TKqB34Jfhzwu/Q\n+AIuMrc1SJDQFYWc0bWKuMgURJ0nStULf6GPLD3GxNzY++Mplof3j5z6v7Nl0+lZn2VojBl22AcPli\nULjmXIZSkYudc6RcpBFIFgrcI5/G2wJoM5xzBBbyxOFvQyx29PGdgAhaFkYo8WAahoOf69MkpkFgvO\nTS/9/evufrIktYxphgGOsqSElWZ+Ow8mF1tJ/7SjFdadDnaS4tvfv7bT3xk/OQZJnJHnBe47S6xD7j\nCsJF36eE4s7nBmcJyMu9z+PbbeOfPfvC9973pLV9U9WY5I8iKSSOGiKsnFpIo1mDkzm5ReHDK4LF4X\n4as6DiiPpqwvd0F4fABIgX1pARhcIY4jncZB5cvRrTL8kIZj44CQSr60oIP1OZazEZHPhWNjy6fee7\n4H2edPpsbW4ggaDabJejlAKGxwZQng1dY4VDKk+jwERq1r5LovxY7raffMQpmt++JVwgpKUwfqSTIF\nGOAEDE9MUci60uW2u8bb3+qplISUUNpiJKUen2M0bT8vSOp0FLiCKV8y/kK8fEEawlWoqPSXMuZQLA\nWZ6AXwAuNI+CERuuY7QIGkSKZnmLq6qsHk9de+3D9jrs+zd4DXyVOGSDpywiJZrxCAkP16vjd7bW4t\nJiSiFewpORlKlp9mUF/lZFty3sDWUZIVhbml2aj4a55KP9RKsYjiLVEJOKrrRuObDYb8c8nmh/Mzml\nYWydstQkGIjTaxWUmXV5QFAZrLCpExHFEpFO2tvsUhSUfZBRZjnEe4z3WOIwpyEwgN5aCgKXcFRYYM\nnIysp2Tp4+lXm9+IU1rdLa2GZ+eKjV41aPyQZWOmsN2c7cL1hCccq5k95qMtQsX/tNLzz3Nvett6kp\nhsgxX5CRpwtLWOgtbK/SmRljudTi+bZm/7Tp++EM//UN3v/ENX9Kt0UtpQOHybCKNJBaU7GF3yftly\nC0NovTlFFoRx5q4FiNUILcDnC/3YrUkRkVx5e1XHjKqaj3V8H/sPThPolKwDqcVSmuGQWvxbJ1xsfe\nLzvhs7eTCn/UurjPo9kikRkW63I0pRW4zdBpXyU4KIwIukiSR+k8qkn8t1NB24pK4tZQeVc/WCIgkU\nqQYK9nu9Dl/6hwLR0/x2Fe+Nr292fs//cD/VEKdWNXASaxzyDQhrY8SD3rkgz4+BKJ6Sk3rcp8nNQ2\ntkMGhnCSSksiXgiMTFCE3YApMM8F5QzfLwDkSrTA6pjU3w6HbbqTxqvu/wp49n2Zs8nFURBtJLmsMg\nAwYt0NEvjrMhC9HJkLl0you8cu9vDT4+Uuo8PB7v2ypLIBkSBj8R+h7tpLaaGS5wwiyMrJN8LJZWGE\nf5oqZh5uzN75FLV38+Y1jJ1+zeezlmlvZQFnLjc+9TKgn9Gopg7SgW7Nli+kFsTF4Z1CFoDaIKPrQR\n9KNIja0YxtHMThJYQu8gjxWbHjDVihoY2hbT88DkSLoJt88efJvLvzHT37lvte+5aH7X/PGvzp0+Kp\n8vtVlz8wkcSoIhUV4Vy5dhMLLCEO1yxMgXcn9C+dO/cLZR/72ttb6ecZWF2jUWyxsroGucS5zbMcTL\nDTrHF/vcizXTF5zAz/y0z/33vvf8q4vqZExXCX2UwGyaGvHvzoiQdIsB/WozJgsDXAtEo0mRRpPLUh\nqaZ+QrNLoDEh7OSNyjCLvEEdj9PQMfRGTJgEhsqExYKW6jKpTNxqGV5QAVxWmOYTDPZBMpMzcePWXO\niq8d00Uf2ysw8cFdRlKoKJf0GKblhwtV0kOokaDYiNHNPPbOHzgF5D8hiJAQ4Hw9Is+cT3FESjI6Xe\natDsZy+sXWVg8x8mTJ/Y8//RTP3r06ed+cv302VvrxnPt9F4iI8m2+sQqoqU0jWCo5X0W4i5JBKMom\njhaARpB0rSCNJLk3hBisMrhKBDOoPBEKhBLyfb2RWwcYeoRvVYTuX+e5jVX9mq33Pz3+vqbPuXHx/7\nWqKhSbSpqQtCoDhGFKPMy2C06lyXK+r3qRf4vMFDa6VLFrnt3F7qjdETUbH0t3au641H68716892Lz\nx9j6cwZzMwoubAYEZAioHND0R1grCcScRkSqSV5bOnnnn5e0CsyBtaSFzmFMRgcJihyZxmYnH7IyHA\n4IIkkPevwto/JnHrumWfesd3z71i+uMGhw1f9j/Hx+KGD++a+fOXB/b0D81PMTo6iRelPGyqvWudKe\nRpIWNsYefnFF//D+sJ5+hubbNqCXtZjzfTxhSFHs4Vkqb3Kqhuga01e++YHP3rXfXd+sTGSoqLyFho\niH4KkojL4Sox8qW+RogJMqmyHshFO0aqGVnW0Aik3gT4+DEpARTmCLzA2J/aq8k8Rl+CWoC/np6piV\n2P03byeNIWrrrrqiyNxMrf88unf3G63CTpCpTUIhl6vQKkC4wP9Isd3+6XaIW+xZ6z5Hxhp/Gdq8fa\nQvSDjBlvdAaub6ywuLXHieMHyysWD5y8svGd9a/0nep3t6zeWl1lv9+j0DY2ojgoRtaRGXIuoW0Ejx\nDRkgio0iS/1mlJ6nHRkyNLzpdreogQhlLxMjUTrGOkNWEtuDIyM0LcFPQSN6Wmuvvte5m6/9a+Yn/t\ntRka/7aXaSdQQQlUd4P+85eA/S/Hp6mOo4QS9y/lYiHLnEfB4pQtZq32TvfPfbDQbbzicpv9GjzZfe\n/7JbzUGnQF+UFCTklrQKKvKwBEV2BoMMGi60tKWBd1gyK2HrJwdCxlwXhC0xIlAESwZbgd2zm354IW\nU6KRGXKvTrNeQItDe2HjT8RX1piePr1DXz39j79TIQ1cfPvClwwfm2wcO7GPPngamKjypyiX70umzH\n3vsG98cW3jpGHZ7i0VnYFDQVeC8xUURG3nBBdel0Jrr7rrx9970L/6PTx268RqsKOU2oZp7yvarhqx\nsisSQWLor7EUKv0OGEL7S/YUU6RsoL4hTQ5wURFFGnEJaEyhtCcEipdgxtRVVyAjD2WPn5MyGE8nO6\nR6ErhJgS5g8GZHM7pn+lOm1j6yY/k9ngwzXGyB8YIYWg1xQGMtmv8fWoMfmYJuQRiy018bueu39H5M\ny+fjK6hZbvYyVrU1OnllgYWn56jPnzr63Z/a+N7f5VYiI2vh+0pEcHxLWVzp4sYV1EYVVJHGd0Vqdt\nO9peEVLJtSKiHEUUkoSytnRKUmmAjJSeFmyFIQrXQucKhOelCj3N0EIVqRk7MBBZg7u783fcN3fNW6\n/7dfZv/fv0XGJhleO38Ojr5Ix7hAIwvez+Ia2eWJ3XJO4JMUJDHeDpd1eIj2Mth6OrrtmcMWe2c7Ku\nP/RlTMLbJ04i11t0xhYdAaiACMKullOHjm2hWdbFPQpysAOa4itwWqBEVCIQIEnrzxUdtmrVCOcwAw\nGeBIatYTZiQlGxiZoNG8g67Zpry0/cGqh88D62qnfP3ps6bHx8RN/MDU9/t8OHZhbG2ulzI/UaYZB4\n4knX/jX33z8SczqBZQ15L5yP9MxwQvyvMfi5hbLwJ6r9j/31h/7oQ9dcdMRgixDtSQO43IiNEpopCj\nDkeXueLBdaLMSnhBM1S4ObQk1wkUEG5PGhiQ2aF2QJFCvS5IIlHAVxStUFILSRPiyutu13S7/G7cjB\ng4IvBDoWIGFuBWz79DeDwlv7l04fuamTq9PGicsbbYRGx16eY/17gar3XWWtlbp+Iz0+Cgn2yv/ujU\n986tnL6z22n17w3Zm/+X6eu/HVVI/UJgR6hP7acjS38X5jPXVRVa3umxs9xg4S4ak188IqaKW1onzD\nJV7oqDRSjMWRdX2WiGjCBJJUIJcljtQiox6JEmiMhOjbzJcsIhIoiKNP7CHvXfewewdd36Z/Xs/Q6v\nxHYQEF7BSlmLNIeGimv3F7iFdfB+Lb+hfuds0dvcH8jtlGRG0xOOQRVFQTx4hnXlk5g33f7Z2auFjS\nXP0dZtPH20Mzq2QVC+OwxOkJJeBgXP0Q0HXZaXhrTHYYMgU9KyhXxT0RCDDVlkJ5YLZhdLuQMcxuSm\nt17c3N9jaWKeWJAzyjEbSojVVQ9oBSgac7d+ztNS559z51d959PGnnhodrf3heE3/Pw1RvPelxx9tP\nXdqCd3v4vMes2mEzQtGR0fBCzpZn5XMMLVnmrvf9taPvPrtb/PJ1Dg9a9C6thPWqVS0wzIqCfbye/T\nyHsiro6sA4urULW/NcoYboJRBi6LM5o1A6aFr9CvM/sTlXqdlJTZ3LZJ8dXQNvU9D5b8dEFFEPFb3j\ndGxj3gd/e1WzyB7jni9YHvQYWVzhdXeKhuDLdYGm3RdhktiXri42Jrad7C72S2WonR8fmRkDp1OMju\nzD9Bs2IQ8H9DpbLK5scy5c8c5f+YUnc4WUsB2aLM90BRhCpHUEap0IsidIE4EDSJcGHrrSNAR6IBxh\npAbkgBaxeg4wYaCbihwUUx9coT65Hj30Nvf8HezV13xa+w/8E3SuFy1VWwuVBXeMgyX8t+DhKK+j8W\n3U/yvFJuKS21pDpgqe7VAIGOBkIZISKxoPdI4fMUv7Ze1drM2+p6t5gn6Z5cYrKzR6/UYCInxUBSGL\nDfkpsA7h8XgsPSFpBMK+nj6oQwo2Z3EQ+U5Yge9yrouZmnxHNZ4Zmb2MDmT4MfGaTVToliSpglWxRi\nZYAK0B93b2oPt207b/qdD1qHbCfjpq+i2N+isr9KxA7quoNUuVzCZtwShefX9D37mwR/8sa+N7jlAo\ncvtaJlcDtFw82ov6QEvfWK96/AqsccgKsRZlsigji1RYlGJQyJIdFQaIklLEmuSeOguuptZcinJ1Q+\nPAOHB65KzuSNZlEBR2dh7HA6PR3uHiGvM7N/7tX7PfGZpZfPDLzz7EubiKpvtTTb7m+TC4FIQTU1ja\nhLVbFAfn6Q2MY5qRfON5gyNxgzOxOSZZ21thbX2NlvtDdbWl9jcWmZtbQGzdgGybXyw1HTM+HyT+nR\nCcI4iLlCRwQoFqSh9aaTYSRKVPiBdifIGF0jjlBAEnTxnIC22VWfk4BwHbr6G+cMH/zS+587foTXyF\nFqXaySlsKoE2iSXi6hF+F+XCPhPKr5hVK8YBi76sLN/kG4YKlruV4oqxDIiQmpVtYdNI0cbj6ZXjz4\n6Pzb72dG5/f924cnnX7f6zPPNjYXzmFDuzYrc43JbriUEmEgw8NDH0cfRw5GhyAjlMlqU/J7Z+Wmmp\nma+luXm9ReX1xlkjvbmKu2NDc6efpnxkQ5jI03Gx8eZnZ1lZn6OWrNBiGNarRbpSJPcW/J8QNZtMzq\n1h/1X3sz6hUV67S3WF49iLq6w5gy2yHFopqenOodvv+8TM1deR89FeClLVkxF89A7ySRcXmhi11ch2\nGmgQ3XzhaEZr+4TdB90j0jFNGp10jhBS0sUlfYFWqvv8V0NjW5LHqPE4UPzslM0EHHJe82WDasOl1y\njmoL6RPSJQnXff271ROv0C89TeEfaqtGaHqMxOUJrZoKxuRnikRGCroFISVyMtbC+tkKv41ld2uT8+\nUWK7jprG6usbyxBvlUC+DXB7IEx5qcmeM2tt27ftO+K/3cklw8tPXPi79r99rJ2zA7jybJQtsZKCax\nz+J5BKkEsA4oIGSS5s7hEE81NM3vtoe78bdd+ffbGa36N+Zl/IB2BuHzeXmg8ijx4nCvpj1oMxyouy\n6T436L4dkaUncK7/Ea0hSOOy+bUIHDBVQi3onCGhqpRmAKlJGrf3kfrU1P/cWZsdK072nx/fOocRx9\n7EhEGBDK8E1gvKKSgB/S1p+ctfSwZkOPISk/qHSLrvgP7/9t7fuzHf+Tw4StrR186+S+OHT/9/nNnl\n968cH5ZdvsZ7c4ZNhdzTp+D1tg4k1Oz1OojpCPjjE5PMTY9h0wSarUacdKildRIhMDbGlNTMHNoP4s\nLZ9lYW6O3vYG1GeP7Z3916vDVGzZOMdUtF1fPKSkRd0zXEzVk1eyZCnSRpXJiZzCLKwv24T7SIvFYB\ntjQQdJDSkkUxWitKUUHsiS+7xC69I7RbbjMkLFSk1f/qRue7jvDYIwkJs8z4qj0R+22l1i6cI7jx17\nceHnp8V/rydO/NH/jDHEtZXJ2htHpKYyUFEJAHJMHgR0UbHc7FLlgdWmT5cU18oFje6PL+vomorOMk\nI6JkRozh+bZe2CaK686sH7zLdf92ZGrDj90xdz8tw7vu4LNl07z1e1ttpeWvyGK8MMiSKy0ZMZQRxA\nFhcsNIc9K4XMSQSzpmRw/EtPYO83+O2+0h+679b9G1x3+HKO1p0vLCE0QEuMcQVc5vUIi9K6iC7u44\nGL3QfXPh7jof2rTGYZxwzJclmwqBNQjtQN+yF18NUnZi3vjUaqBkx6LtKKePDF2+60fODI7/18G55b\n+7WbhH1x8+oVmZ6tLxwuM1Kxsr+EixcBZOi6jR2VgFMr1glQRloAQnkMHr3jkne/6ASbGJgevfeDBP\n+l2sz85dux0dPr0ubedOHnq/U8ce+btx4+fiBbPLrHR6bDRuQjGQ22E1vgUoxMztFqjjI9PMDM1C3G\nd7cJS03UipQlxwTWTY1xcvoB3BUoYrMkOfv2Rb9x2eunUUzfeeB1HrrmKvXvmqKsEbwzBOKJmCs4Tc\nJgwQAWPFgkylETzAMgoYmAlKI0SUVkMpoOQEuMKmmkEQmHMAKUkWkOcSGr1qPRWHapFUHgPWpdB1LJ\nKRaJ66XYsDytrA1kRkK0JBOdpdzdZWDzOiy8+rk+eePat65vn3+9s/917r4EknmNkbIxac4yB8XQ6A\nwqnybqWzfYaKxc3ubC4ysZam/Zmu7QkGBSopIbLB0zXNVdecxW33HLD8m133vQnt9554x8evmr/d5o\njdSIt0dUYOj45xp5985xLjj4SJ+6H6yHFDzxWBApnsXlGZD31OCGSgqCgiBWmmbLntmt7+++8/m/nb\n7vuVzly+FtEYIUlyARdcUu0luyW2Yldxk2XuSMKf8lWAtBCfz+LT0OZsBwAACAASURBVO4C6OR3X8k\nVy0eLS9KKy0pXVU7TSPLq98tljJyb+VYtTj/xwI//yPIL84984JmH/0Ff+PZ36Pc6yKRGUJCZHoUKZ\nUiq8NhwSQ3lQ+nVUavVnoiiiFotIY5rjI6NMT42YW699dYvb21tf/l1qyfEyydPv/npp154/wsvHH3\nnyRPnaqvLq9Bfp2N7dJZPQdqg0RhhrDVGo9ZgtD7C9OQMzVqTYiynNdJgZn6MRiPFu5yLFxc+uLm98\nsH8+MbaqZef+dMn5qb/4ODeuUdvue56rjl8iInREZAZOEvh4lICJFRJYneXoGxvIdEjFH6AcwKtU6Q\nMxFGLOB1FiII0rSNVjoo0JbuvVHsMD0Yty1iXIcteCHBWY51ExhBH2U6RImUVVhLobm+y3d7g1Omj6\ncLiyXecWzj2gazYeHNaD+rA5BhC1ksdpWtQmIIts06/71la22Zpqc3S8hbrGz02ltfRSQOfG+j10El\nC1AwcuXqe+bm5hfvvvvu/XnPN1V+45rorn5+fn2Z0cgQdicpzRV6SBkQNmvVxmvHIE9guFBKdg0sCk\nVQI4bG2oGMLRCTQtQQ50eSmN93P3juv+0Lj0PxnmRp5lnjIolQ77BO5SyrmX7ETF2E3HdrvYMPhu0j\nS36dVw3fZSO/OFReXO36JV0C0QVyea7BjixIlPp6dfrIxOf3B21utz4/tm/93anz0nc889i3a5xdLG\n7gKXDGVM/LQor1UYghirZnfu+epVqtFHMc7XLE4UdSbMSOjNSbm6uGuG2/56psfeP1XT718nmeff+n\nBZ5958f3PPPfsu86cOTOy3RlAb5teb4neWrn3iZMmzeYIWseM7m0wOTnJ2HiLOJqjXo+ZnEgBSz2RU\n4TiQ93txQ+9uH6qvXr++S+9MD350L75mW9cd/XVzMzMYNIDpPX6DkkhVEz44QtgHChZYyj+Fq5OsC0\na0Tyx6BPEFkJb0toE9foqOkqRsgyNNDsuARWNbXgQStCilL04u47SCikdLu+ytrXC8vK55vnFUz+wt\nr70gU5n6w29bItaU7N/dpLmSIPBYMDqxjqD7ja9osfLp86yeH6N7e2C9dWM9Y2MPJMEp6BnsEWAIie\ntxdx5+w0vH7n6ii/ed++df3TjTTccn5o7zOzMVBnuWSVeWG8qdU5StpBCQZQwPbqXqdbsU73gifqO2\nGhMVAJDSil8GmGFIY8CphbwNcc9Nx2mcfdNn2a0dtxgCaJE5/WuOOxKo11BguzkMu20mrtjsnc17+H\n7XXy73S3DK6/of6QAd/9V+HKBLQQkHpy85MNTAF4GWlfs/9at81Mfj0brt6/3t/adv7hE3s/QaBxmJ\n+bYV6o77yAIQZrUj05MTPWVkJVdXUnKds6XangEYyKFNGJyb4srpvdy1/W3fX3xgaWvv/jSS5w8ffy\n+xx9/5H3PvPD0BxeXzmNMBh4Ku83G5jIIRS+vsbVcZ2SsxfbqNKNjLWq1mPGJBs36CM36CIn2mKw76\noreB86eu/CBhQXbu7D0/F/MTE19ft+1b/ofY2MjjLeaxLpGpMZRjO1wu6X3BEcVTVbmkrh+naLXoL2\n+jXAdlhZ7LC4atrZAKEGeS3xQpFGCD+Hy5z/EzN2AYDJULZB1lllcOjW2sPDSD62tnXp/P1u93/suQ\nlqmZmtMyZg4aaCUZqvdZXFxk6XlLfqDghdefpGzZ5dYXytv6iIHBiXpWuk6KkkYa7U4dPB6Xv/gA2u\nve/C+qw7u38P8/DSjo02sGi3hpgB5btBaInVSuh8gLr2UacTY2Axjo9N9o7eOCt87EoVSHeO9x0ooE\nuhJWHV9VrbX6YQVbgldZurymiA5bquSqg13qu5SjyleEYR2ufHoP3bdhO/zzRfkZWyl3Q57Qrxi9fA\n9UCJZ/fIYiHfxTi1gfcmxyhWkrfTZycP7fj2ZGvm/iygwoKBGhA/msotWUjLbhZDU6/WjY2Nj5e0aP\nEKVLIgkKsvbq5I9P0w3kQHGR2PGxw9y7aGD9Af3PnL3rdc883v/5Xc++HebC2wYhxXVHR2AOCZb79B\nfg/5GnfbKMkktpjnaYHZ6nK2pcQ7sn2ZyrEE9UaSNFm5E0h+0G2tbF378/PLJH3/66GI+PTP+36++8\ntDnrzx09Vdnpw5aFfcp7QgCWmsICmvqmFxRdGFrpWD9fM75hSWeV4ssnF3h9Ol1Tp2FsdU2Dz/83Pv\nm5q//g9vvugPnHPVGRc4OWVV8A5xbY9Dbmt5eXfvhxYVT7zt16vm7tzrnSZOc0TFNrS6QKqI/6OGCo\nb9tWN/YZPFCxulTm7x8ZoWVi1t0Bz0626Wdu1YQm7KbSVSCkopmrcnYSJMH7r2Hn/5X75u64urDDXz\nRQ4nyMCuFHThf2l8oLXa+/1C9R7p6O3WrTjrSgISjVtojTnu8lmTK03OG9aLNUrbF6d4qS7ZLv6l5V\n96lr/wVEo+uIt7kUB1+WZHJaq96qcFUwxMwfPeF879F23k5ZeLy61hcsur/7gV89fdoqKOrwiSrC6k\n0862gOOMNuXf0XX5gc7DNZtEruZvSs5u5WAbUKowrJTfNZvPE3Mxs+QIPBY/Bl0bTrtzkxPjSrirVl\nz6jgyiF0doYN191xR2TiSYtchpF1Rqb8uVI8AgfkWOwnQFbnRyLI04jVhcuMjZWZ3VxhumpJiMjmun\nJJhNTNUbHRhmbaJQyKhuSbLD87hPHTr373KlH3MTI7Ffn5654aP+Bq/5ydn5PHpxCqEl0JBlsxZw7u\nf6+Yy+8+InzL69z8WKPMxcdFy4Etjuj+HyEtYuCL/3pNx5aXOp+4i1vPfWJt7ztwT+opSCUJ7BJ0W3\nvLfLVH93YPPuT2+2Lt1y4eA5vc0bHDXv2TVNLFcFl9Lpdup0+vU5gfX2b4ycv8sKLy5xbyNnahn4Gh\namCeT3UY0FCSpABrWLiuNRopxq6G+t0NjcIzmOy4o4gwzdiFaMjTSgMMopKBLwM5qms7cMO8dsIqEV\ngmwI/IrBNfyKvDcBAB4P1sFJsc3Z7hVOdiyzQZgDEssF6dxN8OCC8Q8uojKCuXjkpL38fPfKy1zl8r\n/ui2qSpf+aNwz+t+Pylt19cdiL4S9zd6id38+GGp4by5pJLkKgwJlFZaAuB84ZUlgLefNDbu97eoJA\nOp6BT6XEqDyakkAQpwXmEkNRqjTPNZhMlSoUxIlSaMkmky3jHPvmO7AjKYEYtS8UB3rG6sHDT4OI6z\naK0LweQKiV3noYcxU02Wd/cQKYpmTVsFz18rtjM+mytdVk4tcT4WDkH7t0/xtyeUabnxzh81X4mJkd\nI9AqtCVcJiQfKmrNvP39h6e0Xlr4DSv3Nddff9tDE+OEvx/qK7qmj+W8//a1zH37hmaOcO32WfrfN4\noVxCFOMt2qMjyiMz1nfXOSr/9/Dh86eO/VQWnd33HTT4U/t2TPynnyw8hPd7YXrev8/e28eZFl213d\n+zna3t+XLvaqylt6rW71Uq1d1awGEBwxjjywghmHMIDuMgcByGBs8eBx2yGMTMTM2HhxjkOzANjMsM\nRgBZgsQGgNSIwn13tXd1VXVtee+v/fyrffec878ce/LzKpuCUd4PN0KkREvKpeot9x7fuf8lu8yWKL\nbXWTQ32VqtpSKFwEuy2ltt1hd3GJ9tUOv63j55cv0hpJW27K5k7HdglEOKjBMNCocCef+OE3T9wdGE\n5mALB0yGgwZjQaMRiPae216bsTlSxdZW17h6InjD0Rx5fPjMsHIHGx+SD2ghCOoAmMzAtCOWEhs3eG\naYCfsteFOn7yfsdTrs5cPWOu3WU53WKdLD8g1BFqxurQMg/SYiRQm8IxGGSqMsLqENLiDscHbnWbqM\nIjkluRTinfLyecPg+VvPr4p0RWHc+rxB1V5IYJUtENLJUc7jqjCghmpIE3Za7fmBqM+1WaNkRG0W32\nw5aknCx0RJwrOthCCIAiWwjBESllAj3A4Z0u2uEdqTZe05FJ5BJ5QF0aYWPC7exgv7mlGFU5OzpLuD\nRn2U4QvEBAVl7CRS7Q3NKqTv6LC8H8cefs9Toq/vNtpnR72O0hl6e7t0dpJ2d7pcOkaRBU4crxOc6r\nBfSeGLCxMc+zoJNVKiJYBAkGajuin+TdfvvLcN19XN8gHF7l6znLp9T1uXFpjdWmJne01dtNTzM0cp\nRrXccozOVNlPj3O5evPcf3aDf7X/+1/+fif+3OPfvz9T72HxoRDqxZJPGB6VhKGEwzyFbrtAZubfTZ\nX+yxe3uXSG1tcuQQ7m5Bn0NqDYQZBBWanZ5icnfuPR46f+Ln5o0f+wx3Jfd2rVy//++Wlxe/a3d6i3\nRthhynSe2Kj6Q9HVGSITUfs7e1hrb/HAcMyTd0PPJsVR5E0Bal2DJaAEhdbKPlTBVdjKYtysnzE6uo\n2W3mbFbbZJScTGieL589bHXa3ttGOuUiWGFDn9/VUUqB2iAT7pzZRbmkminca24l565Por0JcuhV3M\nQhLzRLvUGMjEqVASJwQ5ELhbYFXbLf3pqYDhYwcw05BXbniCkJ4Xzr6mcPbLg0KNbOqyNddGLBrYoL\nCewiZF7o6Vhe7amwDjBKFjK/N8dLhhGIoc3zg2N1Zv23OpcwkhnDQxgQZg1GfAZJBugdpyAX6zB+7/\neX7v+cjVzdC9RO91P7E6sVrxzbPX/3u/vrm965vrD60trfJVs+BNYgduL6UEqs2F051OHHMc9eddU4\nen2J2JmKmCRNVmG5W6bfg9bNXWFpc5Nqi4/zlHa5vbrLSWgfbh6CBVnWkrDNXn6GuYDKZZP7Ox9ncW\neXcyy/xu5tfpOL2+IvfcTuzM22E7ZD3HNuX21zdqXJ9cYerVzdYXGlzY7HP4ir0BmCMIXOG6YVj9vT\nxE585fnzh3915x22/ffr03cOTp47RbNQRnYw/+n3xssr4rqgXY7KQCd8kiCzejNgx2+QRjPp7LC/dQ\nOX5bcpBRQBZjg+H44ofV64cAcTOEXtLb9CnUp0oHKNVHTVznFbl3PpVUtY3r/J74TJeAVagbIzwAmE\n1FZmBcOSjIRutralKs1kIZgRh4RBcME6h9AlRXw2mKfgvhyv7z0W4/Jf8kqJUf7IZWTZq2jxFSAhDi\nKpwNC8pJLlHSchGB7iOahRsBao4PeW+QdXhwtnhyjRHlSh+xFjavGjOxHF8LI5jdLVGDU9NaJwvZpF\nD59lZ7rGXRzx05sHz3/YX/iL5/DRDB7tLG8ujle2fXH7z0k8u3bg2e+76he+6tr32fVt7rcd2d3fp7\nXQYDoe8eQHWl7a4cWWL4wvTHJmvcmQu4MTRCeanpxB5he3tISsrPa5dGbC81KY9SBE+xlRrNJLbmGr\nOUw/qxIkhCD2GiDCcxVrDyaOW9uASb15a49q1GsNhl531RVavbLJ6o8XrK0O2tmBzq7CH9wLmZivMz\nN2ZTs+e/J0773rg380fOf67p06dyo8cOcL0VJPGRIUg0IUO6F7GiRM3zu8ud8jbHruXkfY1Uo8YCk8\ntqjKSRbMryzKstccO0ypECTR/W6apEERRVBiT5IIgKBoyu7vbW6urS+x0NshVCcn0viQdKxwZ1lncC\nIbDIaPRqOkK0We8EwcqUuLds87fkeC7iYh7uC1++O+iFN+xeRWbE0iBiTVS5xjdoO8yonzA0FqGXRj\n0YOSgEYh2oosdTpSOemNFMC0sFouUJVMAhRB2H4blhS/k8Kyb0UJidOEJUNUhQmkyGTD04NqSyiCnF\niXXZiencI0ZUiRHGzNU7xb4xx5je3tz4/rm4k8v7Wz+9Hprq7m6vPodS1evf9/26ub7r1z9Mq1Wi5X\nljNXlLaJgi4k6LByBhSMzVKMpdtYkmxsxi4tDNlspQyRBOMVko0mzcpJGtU4sFFoWAsJOCjRVjA6p1\nyTrO2u8dnaNuN6iVt1me7XD5jK0N2AYFUSA6emIqdnj/WPH7/7NE6fu/3cnTp7+7NTMgp87cpx6Y4p\nms0kYjMm++T5KRmQB1Wr1mkDhnCP1tpDmS0f0bI8hPfbsCD/ssbi4yNbuzkxSqyKDoEAU7LfLvkKmp\nDXWOryXBKEmy4esbyy31zaW8GRUwyJzFbYAxAkh8V6TYbES8mxEno2qztqbrMtK3fp3TQC+K08+50G\n4IiMXzsZ4i5aeJNAEypJoqEpNQkiGI69Z0m7Ods9T07ZXlQ5TMun0GB3si7mOOkS88RSuQXCzB7tWq\nhFHAZVanQmhqMqCIJypEO0gPtKg09ZMJNU17Rx9NySXIYFUBRXMx8wmC0ydmOdeMoY22+22Oz+7sbz\n+s1sra9XV1T//keXl5b9y9erVb1peucH29iK9vRXevJJz9compJuQV9BygV43AKoYAiJVoxbNUw2bR\nCpAuCHWZmQ+I88dLhe0O46dHY+zk+zs7PLFL95ASks1grn6BCdOzTBzx5H23Nz8rx+/7c6fO3Hizs/\nNHb2N5vQxKtVJtEkwYbzfKMvzDOsytCzk1kubNpKkumbxpM4zSlMyl+N8TppldO2AvWwAuWZzc5PRa\nNQQquzOGQ0+Rwh1kx/iPhrDg3dF098EApdBng4Y9Ns9QUoFqGpIbSFhIRghUUhVQOl8AMpbJC4uOuk\nHXvE36df/WfB9hZOxBB3afEQ2Ghg7GqCcxUhPJBXOD4gDRSg8TkJQiRANw+pOj4nAp5HICEgLFAxmn\n04gfCFbsd8A8qWr7FjcxxX/uiyPA22oV6rUECSZxXmJMSFGSAZ9x0Slxky10ZImIpGmWAAcKBQLrVB\nSFKYdQcRE0uDo1FHS2/vd0YBf6PeHv7C1sx2tr6/+hc3tpb+ysvbmt1y99LpcWrzGm69fZXsrx7k9Y\nJaECXTSIKomJGqSSmSItMDnpYU2MEhH9PYGbG0N2On0cDJmonqS6ckppudy7r3rju37Tz/66bmpkz8\n3vTD9J41Gg8bENFG1igkSZBABhsz5cfe/uHraoPCF0psohG+F0CSVWguhyF2hJGfTEdYPGdi0ICS5o\ntHVardJ0zQ+cK+9qZ94SxOvtChwbv9zCeGJEkVzKkk7kyF6NKIZF6OIXIIvx1VeOLwez3EzvHVGlCO\nC/fGC//+4Xfk1nXaOZxH+rQ0ai8NmKaNhT9pRH+1yYiWIPQhbOBNpmeEE1KOAOIiQ1jKZKBeSgstQt\nwJgvS3HDmX24YoxhBcl87vEYgkhVKACwiBA9wdQWn0hLFIWEnXGC5T1Q/ojbGSQiS4oVN4ThuqQXY/\nEOYdRGm0UQSOgWoEpBcdPzg/7w/f8Sub6v9If7OqVlWvftnzj+sf++A+/8Jd+97c+z5Vr24QIavUqj\neYcYaVKGCdEwQCtDHme461gaHP2eh3ae3tsd9qMrMd7S6N5nA9+8CGeeOruR267febFo3OzNBuTiKC\n+Lw6MAGc9zolCeFkKsnLxj2FXGlkqr/nSqVUQBNEwy3L6o5R2v0uWDnB2jx5tEClDn0FqabVaDNORy\nqxHK4/NHVp/FWUhIZFS7KujC5EzMVHlxPFZN1iu0VkfMV0R+FDhrMbnisw6BvmQkacAROQp3qbS2xz\nMAbZYiP8fuihfC8H31nDztzRdCtGhUEoXBkbFpjBc0i4nMuBkhpQeHUqaMWjl6RpHM1JSZanFu0ODf\nnnAxBjvu4eEcguq3QEQdao5aZuNCV3Pc+JhirICm4MzEVZqajM1er1dEl1IjRlbbCR5eYNH1hXS8hQ\n2yNJLcMVJJXJ3MGKRECYQqYTqRJLPzE3/5ul73/ObSdxMX33tqlld3aOWxDRqMfVaQlSto1WEFKsIn\n2BTT5p5+r09dtsb9Ifb9OwODk1gakxOz/PQg9+Yvu+pR16caAKqg9AO0gLQ7csY8FIU7lilvfOYh+i\nxBZy4hFspoUrfdUUQhIVIrfeFdLzR5EIXU4Ryqi100XARQlhT8ueULtJODgHy3a1dx3JDdi5HkhMGj\nlpDy0bDwBBy5fHCgpQ4KRiMUpwvMhohi9peFrnrLeNpf8tI/es47RRv94PwJfzOEQQBSSXKGpVE6Sz\nADPv4HMIIrPAYA9XEUEs0djQicBmR8oH0+WAfn7evfFtKoXAg8SZ8aYBZOhX5EvVtgnCgg7AmS/dcJ\nTU6NIggJpUa1/fY1EKaR1j6lIZjY0NItY9qtkUjXch97wSMBF22GIVCCkXmLLm1COmI4oTmdHM5jM2\npSlUzORkTKAkiQ3pXdGj9XuE/kEuGfUervUer0yL1O+Rsk+NoVCJmZhs0J2dX4rhgdWXCIRgVkhPuQ\nCO4PKCLsYsYa74ckspDgvM4Uaa5qSfPXNQbjhilOTkCYwKE0Phc7s/UpPeMRiPSNB1kuUUbhfPuEMD\nhoATz4mBDtNYihCqV8SxZ3sfZXhAmOdNTAm8F3ilsLsjSgiAsFEQKbChLIxmZqbdTzxbvnrNPviOv6\nr9CoScL9rtzrqjHrCXQauBdTiUMMEpST1Thg+EhCQXKpTRCzWQlYrZZZbZRqwibg1TkWRmA5UnjRKH\nFaG0ZeGIs++1w3iGEAiXxUrTjSo3cK4TUmDCiWmugg4ikUsO6Yh6mvZqgnxap5bDQUyn454VXRKG/6\nQ+5Ro5Bghn4FOdHeDKkLNgYRhZ2zWEcvrBwfBbr+vT7WzQahuZETCVJUELjc0E6yun19mh1dukN+gz\nSId2sS8aQZjPg+Kk6tYZAB/aFKC5eV8kAhy9ItJKbFJcFoJVEF0rB+9A959x+MEipca6QpVhdXptIR\nzn9NGOYpfSyEb10yJCUgS2A74M0p1avoLVuj2u+fIxsGm9+4hbWi/cHgectUnlq1Yjp6WplomEwxpM\nYT6QzarEj0hnVGOamJBM1qFc0jVqMkG5QKKEfBLgUEv8uOvnekeAT4qvnoUoqhJLk3uGc6zqXY7O8u\nBkelBKEBiItCRWE0hIrT6QELssaNktvfmI/dlySeGThOckBYxlf/L7gBSp0EG4KrZEmIEhqqCBBhTG\nmUiv+jWOQimFvME+vD6lHe3lI23Gs1ywOlK+4BeNa8ujEWOChtEpz1nH82MJvve99j3Dq1CzIPrnbw\n+YDbJrS2W2TD0N63ZxWe5et1jrbvQ32GGBRGJmwsHCM6ZmYkycjji8Ev4UowCSisI3cP/GKE2osoJT\nDIaMAX/oXCiEK3Ut54P6Rjzzd7mA+yyzWwcg6Bnla2qod2EEbCXEYoaXaPLj3f4r+ni/YKO6QlqLSj\niD0jSSBWg2qMVQDSEJHNYZaFep1zUTD0GzEVBJDGOiuKY++cfA53l1f8p16UfW2AG2/D/cRJTYzDMP\ndMAyRCoxUKAmqtKsKjcEoMMITKQiFJe3vTbs0KyDzohjmukMXP983Az1UCYiCjmRlaQRpgmVfmANgk\nmrhU65DVJQgggpBtYpUIb3e4BS7e+Vr6QMW9L7dZqnjViLn3RhLno/tV1RZcxaSgqE0GKWpJcH/ee/\ndJzdPnprC21263XWs7xIYTxgG5KMq3U5Gp9ein25jGaAJiMUkE/UjTDdnmJk0LCxI5uaHn1a6j6eHw\nCCo4USGF7cGXAHBE5Spsh+feGJfmGlcRWWDjN3N3VODQeGjMXIZgzzDygJDK8vucagVlUoFpdTy+Jo\nL+dWXnBfjgU+JzZWFGUwSi+l6TVFvQC1RVCqCJIZKpQi+Rl1Tr2uqNUO9GpGEwS5S3hTo/yWEb7/ma\nj75dk0XX8jcHZ63KW2o1+vbExMTyLRFYAO0A2MkJlZEgUD5jFB6QiGpGEVn1J8bDfrgCgHew3g8dQg\nTvs9WFjdnw1ZIZBhfVXEFGUUYHRU6MmhMWMU5j6poVNJilNnTg96AOBf7SF0v3Fvhup6SWSHJAenDf\nVrW2BNCjmXbsUg/JFDDmePHEs4GHW4svki7NWSyYVFimtZOznZnk/ZgkwEtCvnYKlLH1KoRlcQwN6u\nJky36o3O/VPXZfxMGM0AFn0uUtrfsfGOe9sGpJYXCy4PAs9bjfdFAGg1Strd3Tw/6I1Jryy1mHLqFC\nJHNc5RS1Ks1IhNcVWpcFY8Vlt9uEbj9X+43wZ1FSEtg/FycSORIk0rDaMg+CdkpUJEjt4VLUBQbtJH\nbX7nB92cNl6+Yerr9FghESWU9jivk0qB1EXxRpIliQxBZAm+JjSIS0EhC+riFbNgDm6O0vAkbWwR9X\nuIK2S84itpMlsEHYaV6oT45SbaxjcwsKgebK4hibOrQCVQbEzgdnEmHGXG5Y4jcj12kkftLeXy6Kmz\nJ5RSl37uzkDtbaIcIifcjhN2j01784V73Oo8+ukCrfTv/z2fPs9u6QKeTUq0cZ9CpszfcwIkO3u/hh\nCUOKkw2a9x9ep57Toc8+LChUt1kdfmLfzGJ/Q9X6+ankRW0CN8m4yvO6XF+JoS6CUDsfclHkID09Dt\nddrZ2zwwGRcNFK03qJNZ7LA4jZUGUDgImJyYIw/DCzXxU9zaoSsdbUlPAW4u1GUK6hTAQiAgSYVDag\nRdI47ACZCTJRoU6tQkEQrA+Fsa5yar6Jjfir9dRg//KfZiiVyhL8Vu1LJXC+nL2JFTR7NASLSyhURj\nh0DhiExBJfyrr7UE+hKBseZdiHbJEuAh/06xhv9O5byITRq82ZmZoL63A3gAVV3ApOB2Q+2JxRY0GA\n62fHHQHNEYpuAqoAmCe75/fHJLS8GV9JQ/SYO8Q5GglEMKSDzqMeivvWbzx4r+0bpWHH54jTB5mY2u\nRZ7/co9O6xGDUJc+n6bOOEF10YDEG4kgRVTOakzkPnJnjsccrpOkNdttX2N1q/kujJv4oTOLXURM33\nXaBKsEGB8FXSLvIg8ATrrB7do4sT1ldWWdna/vJ4XDIcDhEmgDlMvK8tx+xWkOtVmN+fp5qUnl17Mx\n0kx/0ftXjbi4DxaHupLd4lyOlO6WNgFAgrcUgC689U5zbBIqRKHC7URSitVweP2nJLHtXdTrfseArU\ni3PLcXXWy6Ml4IwjG/EcYVMBwQ+LAwy1Njt1JWdT1v40qmAQKq7RoMejEYQpQU73BYkTbGv+RCpogA\nAIABJREFU/hK+5UX3hfUEiEC/0JiaZhAn5L0RYRiRCY9TpkB6KEUQJ3T6g+M7Ozv3zXd655hrFt1ac\n3PDYjzu8OVRMtab8SWKR2kQwuLzPq2dRbbXz//aXmeRRn3EKN/C+WV00MPEcM/CJLXkGJ5prq/sEVY\nTGtOTTE+eJB8GrCxe5Prys7T27sIyT3MqLwSG2ssI3vy12SPVe4KKw7s5xs7AeHGoDzROMQ+QEM45l\nCpSRetS2u1drl+7dt/29u7x4TBlMBghRPG5rHcYrXEuIwoDZianOHbkKNVq9YXieR1Cy1tOO/n262O\nM7XUO7x1KiruiUOHSAG0NJvDoIECnKZn3OK0JpcUTUK0mhJG5wf4Gwj64gq/3Od9N2Na3QZqPZTaMC\nqhUKleq1SppFKFlisodWhYSgUIUkgtKgHSeQCtCqU7naVrkdM4f+Ao6QLmipym+yuRDgNRhL6rXnw+\nTyqNCddHaEErIlEFLCp86IRmMhrR2O9867HbPRbkFLYq/SV92zcvk2XNw/OKRWpT1ngORF/qYnW1WV\n678qxtXz949N2epVjwvvPIlXnn1DVp7cPwkfN//8N/z4P0f/kJ/aI699Orzp5zM0mMn71g5ceL+F1Y\nXt5779P/9s5+4ce13o2dfuMLxk6d575nbqdciNtZ2SNOlu6v1o/8qCNUPeDFfSNU73gJq520RWMUFT\nNMh7c4ua2tr39rf65JlGWmaQiD3RzZKKWzmMCakXq8zOTn5fBRFPcqxhWYs3aBuOvXcIQsC5zjolZT\nmMkqp08YYfKiJCREl+yFNDakrRJVH5HgfkFQiVBheKe2a3irJ8vUcfKmEEIHIS2076UDZ8g0plJcYw\nMkqo2T6YrBwEn/tZaqjPpNpiwSL0Ak2jOk5zcgIKgkEPqeRbZ+WS+cSrl3o89BxkJJeVNzqyIXoVJI\nGpVmjUCgUykOMA+eRzuJ9yiBUn8vvvv3RvSCm1e5SywRhmhMNU/biGdAJQS8jbw8/Mrix/s+j40dgr\no7MLanyBCpkLP0yppBpVfyYihYBFYYDB5kkSTTLN85+54U3f/Ov1yfbRJMxV9Y2WVp3PP88rC/Ct//\n5v8wHHv/vvvO2k6d/tc0WJ2d2aeo+jfn3kMk72V44TRwOL/3Sp65/evH5F3lhokYQTnDi9pijJx071\n5/jytk/+OsPnTn9Wdn8xKeFq+NJCjsyDY52KT9skNSQGLJ8SKwt3o4QvkKNGV54eYXnFrsf2RIJ7Wy\ndIMgZDrdIyKkJR3fURaEZpJ6w2WTmtuOfs5FEkBMYRZ5l5Kbg8GknitvuKOaruksuhgyVIaSB0TGZ6\n5LLi0kwsXTa9S2IBayyRMZhzAjLHmGWY1QNX2nSiG9n5ugDZLJ20UvPINujYirlri7Ah++aTod8R1/\n9K7i+jAtkqSCO44tJkqSBidBBSBAnJElCHFcITIRSCi1VaREsMEqj8A+TDcCm+8+/70ki8v3BrvSH+\ny5iv9gXUUJSq362UqsT1yqEcYWwkhAkFUyc4AVESUJjahpp9Ad2O+376PZBCLQxhaTdeLrrfIkNdfv\ni3hLFKBuRJAFR4nn5xT8+8ual135+cqrB1NQM7c6Iy5fXef7ZC7R34cyZB3niqff965m56V81kSSKE\noIgwhgDQYCJQyYmAm677bZffeyxx/51pVrn1Vff4E++9CJr67vgAyq1CWwOZ18/9/OrK+ePONoInY1\nRbuRekDmNJN6vWMc6OEIZEJLdrS6rq6v39fv9D0hZYFaF89TCGpGJEEJRD+pUq1WOHDnGfQ/cz9Tsz\nGeVUiVOU2CMKQcxvrgnkkNqYqqUOlL7521u+1g3elhIhwkNcRLSbNap1RIqlZg4DjGRIUkSqtUqQRy\nRJElqguCiQh1o+Yxr2ndR0feOBZ/jLXPwA4/NQ2lCEIVUqrVXTRjhhUIYgw6KoBOiMLwX3hagaTxae\nmzafcx2d2DUBj/c/5CeFFRhcy39W4f9Qgi8KNOhKP5MUq+2giRBVyJ0kmAqFVQU44xBVRLiRg2nNOu\nt3Y+12i2wviB5HkbtKwFGFWMUMYZshXib41yX5ZVzvHnl2U9nbjtqTlZxVvDa2at88ZlzPPvl4mmef\nvrDFx5/4skfaE7VIQSlo2KGOV5MqtCDWji5wJPve/oHzjz02IX19TbPPPM6L750nrX1PaK4Sa0xQ6c\nzjG6sPvfpwfAysE2WtwslOVFH+zoQo7wpEC9l17nQuRHcuHGDxcXrHxsNh8Um5cRYtIogCBBCUKvVm\nZqa4vjx4zz00EOtWq32GUqWw1tXQH4YZV8uR40UukTXFGBt5wePKe2JYk1cjWlMVAoScawxYWFZHcY\nRSbWCMYYkSV6lvI/ysBOUeFeVfO9M8N0ceG9VvPbe77cegyCgVmu8bOK4sPnwpoRIFfWcQqBK5TMlP\nEo6+r3WU53tVRhsAz0UQwrPpBy0f1uUjUCUQ93SGlZJdBT/uqlUEHGCqMSISgyVCFOt4sMQmSTIJKa\nf5z+42+kkfjjEubHmalnMloiCYi0U8zSbeeIoZHn5As8997v/aGSXn5qaMXT6O1y6tMTzz17m7MtF2\nfrwmQ/x8KNPf3Rmdr5QeZJ5oaGBwjqKBexSnC/QJHfeeTcf+sZv/eip2+5nawv+5EvneOXlK/R7gnp\n9nonJOTZ3XnlqY+eVf+TcDYKgC+RID4E05MMD52gAlwtwmvZOl4sXriQrKys/2Nvr0u928d4ThiFKG\nYwJqVarVKtVpqdnOXZ8gRMnTvy6EALrCnn6/Xu7P4axRckhDy9Hg9536+1j/R6IwVPaeII4IIwNYQQ\nq8CgDKpSoQKEDgwkiTBChTfgy3iORCHeIuCvkn518b2lyeFl66ZTpjjroCUsTUWtOPp/UpsDEZMJgy\n+6hlJIwMEShIdKa2BQP8vSDw84WpB2QA7QYIkixpAdpJrdsuuUfhBB4KcAE6Erll4N6nbBeR1Sq5FG\nMjRNUNUHEAUGzQW1uFhGEtZ1252+1W3vFmWdBOFHIse/DyYoOqMcirKPf3eHNN1/4wOLyy/9QBy1U0\nGNp6Qavnr3E66/32NmG0/few3/1rf/t37jzngfPCRPgpMOKHHyAkmGxoFVhDZX7YkzeaE7zwAOPnXv\n6qW/5G82JSV5/zfLl5y5y5foO3b6nUptFBzssLj/3D7d2X/uAEB1gSDYqHKZiU7x/l5fluAjJB5LrV\nze4dOnq39rYWq912x12t3cQOOIwwmY5xhimp6ep1Ko0mhOcPHWKI0eP/vL4RCyCz92y6HJgdJDqeIM\nkLIW3MqANooNUow8GgSQIFTpQxXglcJgAwlgT1xJ0FKLCgEq9ThTFz+M91tt9rua7iEP7zgbfPp31r\nav/pmGrLzg6VOuNL9eaU4i4RiZD8nIZSykwRhEbXULNCumHJFRz2ajzKKM2uAGSERJHZn3hYeD9/g7\n8dpvCPus6jD4TNOrng2YDl0TkUUAWB+QSRBQS1+tUpyZRccz2TufH11bWJ7NuVliiydIkJs/BFZpcu\nlQv8S7jueeeSc6ff/bTQdwnqmQMRi02N7d5440lrl8FEygeevCDv3H/g0/+9ERzFq80QhgKGSANsrB\nGLi0A8SIvvA6ihOn5Uzz88Ad++s47HvmNzh68/tomr7x8haXVLlo3WVios7NzmVdf/6NPt/YuJLCHG\nkvLl5msliCFRiDZ3cp58+LS5OrK5o93u12ydIjEkUQxUVRIvhtjqNSqxHFMc2qKe++99/zMzNxntCl\nQB7mzZd13q0qmLaJ9vAK8RHpVBKVrg2s/qtVoLggVJtQIDVKN0JFHBA4dG6JqBWE0XhkmpqaJK7UvI\n03RUBPyJnzn133a+Xap55hrJzgAY1pbcLaS2sRLjekju2FtChdWEabAiokyzSx8yMtdVUISB+SjvW+\nhuwODNti0kJPwGntoxufLhkgxEjiMrhmXH5qgVvs3wUQDWa2QxyGuEiNCg4wCbKBQcUhUrZJntra5s\nvGJ9cVV6HPgxVeqtY7TrOFoj6tXXuONc8//Yq+3OTs9WwGRce3aNS5evMHFiyOUgofPfGjz8ce/4Xs\nmp+bxSkPpI2cxxYkkA2wxiKOQTSzx+kJD0uT2Ox/iqff/199zzz13bW5uwzN//BovvXiRlfU9tNREs\nWJx+cLsl5/9zC9urJ9D6UHB6csOBtM2g34bLl1c49xr1z/RaQ9qaZqSjQbUKgnVOMYoQRzHRElIFEU\n0mk3uu+8+Hjjz8L8xUVgO7YtxwbjuEzd12Q7VfmPLMgfCD7D5Ls63v0UqSxBoTBCgAomOHHFFokKJD\nDVhNcHpAK80UzNHdnUUv8T+ehIH91r82cnHzR6yb9cFLY02ZdEKM9UGyeTM58PGNCJpIEODCCTSlLo\nissAcClU8jFHkw+632+4O9DowZjl4c0id/wBgLTw3nYSWwkfAKtBJ9ElTq+7JaoKoJahGlbhWxSQRO\nYJcSiq1Okkck/WGH99d2vimvNWHgTsUyQ68Jx3s0dnZ5oWXPv9Dw3T3IzOzdRqNGp12j5devsBzz2+\nwtAS33XYX3/hNf/67Hnn8ff1qfaJkXGhSK7EEKHWAQMHbW8FZ4AOmpk/w1NPf3H//+7/1u5QMeOlsh\nz959jyvnL3G8mKHuenjJJHm3Lkvf+SNi1/4oe7wGkL00QE4nwMw7Fk2VoZcPr/yTdcurX2830uxmaO\n7t0tgJFp5nLNUa0lhKprEzMzNct/979m7/c47PmmdY5QVxFkp5KG6j30FMz+OOH+wLIQHXA/vWnjX/\nXZBgROVRiINhJEkSgwmlOhQEyQJ6BBhYmoTU58vLOkk3vp9ZgnvQqDnO0MpOvzC/nCna7/KL3oVRpB\nlKeiA6WMLf2CDCn1ZqES7EuSL8OR5yjAbknkHWhHGAaGR7+vsrN5B3gPlwHqiMCoZE2IfMT+eOxzGE\n7r9YTv4QPaIzL8QSYiqxqhaQrVeK+pCDSYJCMOQSlQhRpHu7v3UztKqREjIIB/2S3MKz/rKMl/8/Of\nufePCCz8TRpDUYhZvrPPqq1d5/rk2F87D9DQ8+eQ3/JMPfeM3f26i2SB3GbKkOykV4q0iyyDP80Ntd\nI8qxRIRAUiwTrKwcBdPvf/Pfe7+B5/6J87C+Yu7nDu3xPK1nL2OZmZqgUo14MrVl37mued/+17LKsg\nWeb4L5HR2u3zhj5+XL714/qc67QFbGzsMBiNmmg2UsHibEoWKOA6IooBGo8bc3Bx3n77nX3T7/Z5Si\nsAEN3WTnbVFiedFybIo9eUOS5/LDG9b2HzrDmz3fbIo/pFaIQOBI8X6DBMaknoDKw1htc7CiTuJk8Y\nfoCvgBEoeCMwqJf4s+N6263KLpEPhY1VeKKVBKWRS//1gYhIbVBAmAG0QsgBDS63QUYCMIrxRqEgSV\niTCD7+TwW6B8xS+8PF0tyJa3P57uHXsaAFXQG3+qYyClkxCZBygAo2OA3QcoLRGh5o4jEh0RGDFA6O\nd7qdYb0N/hNYG8pyl61d57ewrvPHqq79WaWh0JOgPc65e3eDF56/z5oVC2Pf++x//0mNPPP0Pji4cJ\napEqNLk0LuS/+1LnIy3SO9KnNqYpHUw4tABRLHh9jvv4f0f/PA/uOPOO7/UasHZ167z+tltttYE2kw\nyPTtL7tpcX37p164uPotnkzB27O3ucOHCm1y6cOVTm2ubDzgHRsfkuaNRj1HeEgaSiWYVoyXWpcwem\neV973+qNTM/908r1fgQUcnvk1jlTbo64/csbzbWsT2gA77znUKMSsU0jdAKYWyBYAkUXhU247nXoBJ\n0Uiepzfz+fiGMRPh3K6fhHePz/SnIcun30ymhdLGz1Zvna3MLr/mkjgwiVBQhTFCkmkajkwqqGkOs0\nRVFpaaQYu+7/d4qpK2igD9kqeS/ygU5LHbliu5DR8fBT+g4QEQGHQiCikHFBh9IlNbEcUxiQoyF1ur\nG9y++eflvd9c3QSm6ey1efuVFXn311U922runZ+Ynsc5z7doGL7x0lddfg0EfTp48Mnr0sQ98x4NnH\nqZar+83J6z3+6lTAQworKIPZmf6kAit3BdFcQLmjy7wwQ99M08++Q3fYQI9unChxzOfv8jLL6+ytWG\npV2eQWrKxdeX0y6/+wSevL72C911efP5P+OIzf/y311dXvr/X77KztclgMKCeNAi0Q4gUE0AlCanWI\nhYWjnLmzIM89sSjP1Ft1jtSqQPTSSkPLCmFKIx0PHg/DpJb2s++hXdbCL/73YIRSsgi+JRHBUX9V3R\n6NUIF5GicCgmixmsyqZ+HALzaDzzBuzPtfMf4fPJPAb0c7g1nAoKkxsT8wm+b+uX7ZRZjjEGZUiZAC\nYgMMg6KeVokiBLBQHXPDPpLH0hGG89QP47wk6W68a2v7/Z3X/E2aBupwXn5z8jU9/hMPGyVRUqFQjN\nyOVaUilxKYr2g096jPWz/5MZgd22O7i9d2bjGl5977qOt9vYPHpmfQZic1s6AS1fWuXhhh70unDjV5\nMmnv/l7n3j6g6szc3NF3WVBaUNui8G92Mc95nhXdka8Lh7i0NUt5N+K/6cEx0+c4IPf8OHVa9evfu/\nnv/Af//2Fiy2a05cR2vHex26jWm/S6fW4eOmVHxwO/GePza3/2u//zsvfc/7szk9qMcug7+n2d4gCS\nRw16HevUatG1OtVlPYEQch977mbBx564KXaRP2fjSea42iSZeA55woVcSnK2ytKROchfp8c4fMtvF/\n/AOye0SItwO5SgnI4leJQCKUJdIC3MQxDEBVUUPttZAzW7F+Tgs3gDwLcf90HnzvYCQ/ZiN1cB/r97\nNMKDWFEdXb+16szR35ctCvFridTvHPksjBK1IFChEULWiYjlMhwdvNjjJafwd4GagLBxAHO+u0CkJu\ntgsfq2VICyv69nPT3clkYbQohsSOPlQ4lix3e+eJ02lhbZ+X6+V9Mz4nhSnvtC0sbN35hfnaS2kSNl\nfWrLC1tc+3qDsvLYLTg/vuf+Nmnn/7GX3nve99LY6IGvrRrLv3UnbcF+MoP8aR4nxUB6kUxHxuTT8d\nplixqJ0dGGIa899En2Frf/pWlleWfffHl83/tjfNLCO2ZnJnixG1NZmccmxtv8MrZF3/hmY3X/87rr\n+z8zMZSTmymiaMmlaROEifYzBJHiulmjVq9wmg0oN6scccdt3P02OzfQwq8z3He4w+deAV9aoxuyIr\nT2hUzVS98ybP04NpYv4n3Gx9DtNAqwypTsBtUjpBDRFZHSYEyMcNhSOYVQVAljCd+vWCsqFv6CYeyn\na93ASXBf8LMRcp93SGLxCpDZWLq2cmjx18L4yZSRXhvEDpEGEOuFM4IZKSQiUVGGWEyQunWX/Xp+hH\nSNRAdlBx+hUH/oS5soXhcEoCKh5QSpdRnlFI/JQLwRuCMKCSzAl0Ag73H5ZZBv8/a2hpfevbL/Mbv/\nPavvvDaK2smjuLmzDTdQZ8r19c4+8plzr5+jdEA5o/c/uYjj7zv++99z/3UGtUy6Iqgwkmw43nViCj\nKQWSF6rPzZVEqbybll4tOiXKIo+DI/DEeefR9PPDg49/fmKq8ub414I0Lq7z6yhKbGylRNMH0zDxRF\nMXtdvtnOp0W2zsr7LYXcW4bE6YERhBFCadOHCWKNVk2YGp6gvc+8hAPnLnvp6qTE58Bh5ASIcUBRQl\n3wBmEcrCe3fSGiw2lB+zg/fYRz+5fFbKLNjkmKDCaQlukHqCUwUtF7iTD1JJmAh1WX4uixrNj256b7\nAfehQP2d0/D5dZUvBSv9YfYlQ6BrtaZXVj45Xp9FmUqeGHQQUgUVwiSCEKFiCUyBEyKruTESY7NNn+\nI4SbQRtD9yrZQb2dj7UuJBekJAk0chz8iQ/W8U55cOVSgMUmA1II0T+mXgXf1+jWuL96gN+hTnWgwe\n3QeGRqW1ld5881lzl24wd421KameOKJb/joo48/xbFjx0owcY7NC61Qm5VBpASFwdUAIR2erKz5xP4\nxvX+9nAPlcQwRWKTWIDVHjhzjQx/8Jt772JmPBqFme6vPSy9f5uyr19jc6DLRmOXY0ROcOnU78/OzR\nLECOcCLHsPhDtZlNJtT1KoxlSRkemqCM2ce5EMf+sDzx+6640fQemxyeGiCVwSeFKrIHjzF5xjX9GW\ne4clx9HC2g/OtH/K+hZJDjPFEJsAYhTYCFTqkVGXjRuK9wgQJjebML1eqjXK8I99md3V/Fnz7L/q2i\nIPy7Vi7/6fxWNYKCWFAY2LyF2vVCQITI5TGmJAwqRBEETowyFAVKhHaQiggBuv7H8+yTgIpvrBe/E8\n6mcddxfEJKLQkigOklj/gsLnDg1GYMEBoRZ7n9Ed9NjY3WV1dZZRlHDtxnDvuup24UmG31WJlbY2rV\nxdp7WYkzRoPn3n8bz7yyKOvnbztFLWJGqExCFnyFFWZQI0vSz7A00f68UlyCA10eOPQ5QjGF3WhFgp\nvLbVqg8cff5InnnjstZmZmb+ZpnDt2hoX3rjO1Wsr5JknjitEUcSxo0eZmm4wGLbYba2R2wFaKwIT0\ne12mJyc4MyZMzz5xGP5kbvu+AGUgnRQvE9nb5LoU0Lt19JZNhZtyt8y+3UuxbpBYl3/454hQuZIJRB\naFcoFZtz8Vihl0CYkiGJqjQmmpqZ/ERUVPixfI1/qE5/4xDuQduoC5CoPuuPyUMXlpS5nb4XTQuA90\noH1El9rtLZH6cMrvn+6l+wQz3YIKm0ikyN1FVwdTANbNaSVjGGlRx7lkVJyoG34jMCg9GzZeJGkXpB\n7gSu9rCUjsCOEzRAOpC9kY610DEXOUFl80lzt7PWupp32R6elRLRbdLdX6Yz2eG31Gp+/dI4L3T1qd\n9zO9Kk7IaySecHiyhoXr13jxpUbuB4cq8a/9ReefupHvvPDH+au+QUCpxEmJs0FmOKiCJ3jRQoix0t\nFZg2hW6fd2qNPjXpzChFmBPQKx1eZk7kBSkuMC9DESKsQowxlJBWl2DbrrG6tPLu4eP2R9ra/Z9AVB\nO4YWh0jrEwhKgqf9GgPltnY6uJHQ+aqUxxJJqjkOcGs476HTnPmqYeZvfv49+m6+kyqLGkg8TIAYVB\neoZ1AO4l0IJwtJPyVpS/fRIoIKWr4AchUI6REuXOMss/9XSfOfptUu8W19xLPEKfaePZw3tExQ4gT+\nnmT1c0a1fojvzF37MlPWVtD6hCUR0hbnsLyJnFQ946ne++WtPMrAlzEWx5Syv3H5MyxfzsxPUcQVwr\nLe60h1BAqqBgINcqE6CBG6QStQqSUfxc/mMB3y/QtO9DUPFyUe1EQCUU5fxKy+N6LciAMLrdMTEz8w\nsTExN/PnCN3FhMVttHLa+vsDQYktTozs/M0mlMArK2s8vqrr3Pu7OtkHYgjmGpO/3AtblANq8ioCio\nGq9AEaK8LZWerkFYjvEEREagqvp/hcomRIUJHjI0mfQb5yGF0AtbQ7aQwUoABk7C33eP8+Wu88OzrY\nKPJk8fv3IwjydraLq+ff50bS4t0ukOcVTQnj3LqztPMHq2jQkOGQ8aa6lSFhRPHufPuuzh1x51/v9J\no/ELRryxgem8RpZVvxfAq6ngMzrGvbk2+TZ7vTuR28HeldwXGE4UUAVKZQk1NGBwKoysIDN4rJhpTN\nKdm/q2RIYEOb6YQvTuX9zt78v3nBqMR8oJm8NE03ZzTskMlFqhIgTLFqo4kVBQyUUijQcUoUQ2lTBR\nCfhZ9tAQQKpwvRg/7IwZfCsp7WcwYhCpP6bHaceFHVAkDDOKZYbdba+/uPbW10+Liles8/+p51vf6J\nJNTzJ08gYlDOu1dFm9c5eqlC4xaXZAw15ylYap/TaUIMRIvuH6WiVxQSaoIr/alHIQXYBXeSlzuyXM\nQvR3a7T54TTWZQOoaiBghE6SICi09IRAuJEsFO+tdXn3pDZ555sv84R9+IXnu7Cs/trXa/rTI1ZN5m\njPo9un1e2QuJfOWI8ePU7AeY/AR/Z6j2xkw0ZzkPQ/czwc//BR3v+fen4wnm/8A4XDC7WuPeu9Ronj\n/N/mSiLINLMFhEFQQXpeSiW2su0JuL//PgpVv8r6FwqK9QYgAUHjvcCWk3ooGo1FIrxdTb9x5dnb23\nh9RqsnhTqfYZ1DfjGzx76KQ1HwNfe3DwsIJqs1jnxz0Fj7p+tuIpA1iVHQnTApRDMaAUgXx1Osy4Wj\n/GM7/X7jd1xBJ2RGsFqcGY1V3PRauvAl5IUqiiwfCkh6jtSZM6j+aq1ZweWX94y9fvMz6Xp/a7BHmb\njtFc2aenc4Gq6trXLt8lc5aIdwchwmJqiBSVdtd3v2JN8+++eNpK//U4tG1n5u/vn7u2G0niWt16hN\nVVFLcJSEEikKvBlUnlD2814g0hjwqNh4LaR9GGYxGltWVTa5cucaVNy+zdGPxvs3N7Y+1d1s/uL2b1\nZYXt9DKksRVJpsjttsdLl++gTWS6YWTBGGM1k3mF+6hvSPYFpvUjk1zxyN3c/qhB/6PaKLxo2BJh0N\nUGCDL2b4U/q2LWx40zYpB02SR0guHND3IlshGV+53buXHtOrhshzhBF4U4xyEQhAgVYQS4PM6o1STp\nwGN2vwnA9Mgtx6txjYo4mtiPb/rg2+ffHl4+q0TRHX2U3Fz4X8aitXjqbJIYZHGISoCtCsq81JEUwi\nP9znQBj/6x7iNv4SsI0QB+C1GvxonwIlCAkK+jXWZRJUSCK50ZlRUGhNMHsn/pqhcS9u5+DtUatTmj\nlCbmQcTsrXTYWV5g531bcigUokIZUx/tw/ZgMnpGLuX1Vqr2z+2ubz7YxfPXXmmeXT+P1QnGr83N3/\n03Mz8DPWJBiaJkIFGakWc5vQ7HqSjZVJUp0V/aNnZ7bG2vsva+g6t3S5raxv3ra5sfGu/O/iItfYDo\n/6QdCRQgwq+a+i7AcoqlNAIB8M+7HWGfP7zz3Pv/Q9x2x13E9QSmscGzBw5zqMffD/3v/+xn5RR8qO\nFOJEniCtFs6QMd7CqAAAgAElEQVT0u9CH8JRe3Nxn3G8PZeWGpgfAOrm7zCi7+I+lWyIQe0hhSxn/g\nyGrUBpJBWSAyCdRKKJodrFanfkUhDhfKoB/FTiZe5dVffprIfBu/V4YAbJO1Fz43zO3+s/T0RCpIY4\nsVIKCkqSLG+d8wU4vArCPEIOP2HztexWjn8cUO6uiqCVUKS447m8qcauf+7g+yYqftEIoxeTRY8zfd\nvePNo4u/p1+PMHUseP4MGJ1c5tLl6+ydGOZdJgRmJiZyWm6OwMG3S7Ga/J+ytbKGoOtPVLg/2XvzYM\nsO8/zvt+3nO3uvffsCzBYBhgsFCASkLGQEjeTFBHGiu3EkURWYkk2VYq1REuKTiKpXLTlhFoiS1YiW\n+WyltiyRFKiJHCTCHMndhDAYJkZzNbTMz293P2c823545zuGVByySXHBinNnbrV042pRve95z3f973\nv8/weF8X3TZ95/j6VZv9HZ6Z3dmZu9ovNbufJuJkdj7P0FZmo1eWW27q0vj5xNsg066SlpTeZ2uWtr\nenBi2sbN507t3pHWbg3gNxX5AYtNFprBlsDptMpURQxm87Sn1jGgy2SDLrtBluTCSvn15AbE5Jsns7\nMXmZ68yzsqkBX7aVlOruWflhuGza8QEiPFLLaKPgrssFw1QV/BaZYX3Rqu8E2AVZx/vR/L7j4kKSP8\nEUdRSbrrX+lqQv1GdyHiCJvAykzvf0f0tFcvT2OK+XL1WUe5NdMtfy14vtPXf2CAiETos6uD2X2uh+\nYDooDIk6hOQU5BeEIqkqt3RbXCukRopo8uXLlZ6Qo/1Co+DIyQ5IhRIwjqofC1cnB1rvPP/MILytOe\nWFgamDoecg1mix05+nML7K2scbZlQucOnWa8aW1ykyrNG5cko/6NEXMnrklds3OYCcTNjYGmCAoBBi\nlMcFz/rTcp5N4n4j0d6AlPlIIrZhpSfpbA0IQSBEzzQ0hVFuz8WgKKLyDWCcMBiNcaWikGd57GkmCx\nJPOzZConPPDdaTTzPYWyM0lJtMpTnhefvkkcaPLHXfeRdbusbm5yUtnVnny+dMPfdP1Bz4cAc5W/Jx\nGGgESuS0sCY6A2g4jqoFMcieQWwXwGIpiFWdPzXu3+jNajomEqYxG23lhMlRUOwHeawoH1mnGw4Qon\nT09M3PoQ9DBWomSMcFXvk4h/qNGy9eK7887421zG69+FHi0AJ3NELcPfDA3o1/yOiFEmxTlCmlTVTz\nMbV2fkFdScBEEf3lJePWz+O7fIXRBtBCigZJRxVgh4HZSCq5u2lUYCGQEQWI8DKaWC2uDxRdOr/z6W\nn/MwZsOcfbSKufPn+XUmdOMt7YAaDdbRD6nmOZEGpT3aGVxJmc8yMF40Amj6RSnFWNjKI3DSwVSUOB\nrcK8gEpWlKEubaB2Rj0sEEbGOsaWrAE5Bolst4nKCFIJunAKBNAXSQJY1SPUMG8Nz2NLhSkEr66Cyj\nOFoxHj9MmdOnWRufoHdew8jVINzF4d86jOP/fpc1ji0b8/CpUaiUehKsxlsdWiWsgZRXcl+qGmcr7r\nwbbHKZHIGY87/rJYbS42oQAtZAY6pi06Fyg6GxlhBWWqKUpOXTZJ07oNRuhto4J0mSqLqfy/kFV7rn\nyEx+3oqv6/Lbmf4c4AbRpZ18EmE1OmjaZK+y+F2lz5HJ2BFUTUplKgCSepmCaGCEikC+bi4zU3ERa1\n7jxKaVbdQRBWhWSqMLypVxrYaNzicKVBSQtCsbw7IWglnV4d87ON/8gfnLm1e3+jNMzGWV06fYXNzn\nZdefJawtorINDONBF/kuKIktzlHDu5ld28OP5lUX3cGhKc922a9vw44bDBM7IjcjfHeErBYlzPOc7z\nb1t55nLEU5ZRQGlIliUWgGUlS5YiFYbYV02vFaEoSLO2ZQJYpApY4iplOCzbHA5IkIWs2MKHEllPG0\nyFSRczP72J+bi/exaxeHEb5ZOP1+w8d+bVWo3pNtRA7xlXqcE3na4Mz4JwlOEusJBqJMGucPPFlTp7\n83Pe68vyPtzJLIivDsVRRta2PAFnibI4NEqE7GNNiNIJO65sfW1q6/u+qaL4qvpAglaop15W5+lWzj\nZ0cm6qw5Z/KibhWfP/RDyfyajtJjBQx3olV5/3f9qIkqBIV+4rytb1qCV2lpgaJM6AxiKA598rGO9c\nv5B+bbe9dIZ0Fux1b7BDyivBabHfxts+AUqOShAtrOZ/74pMfeOHUue9WSRsRJWwNBpw9d5pnn3kce\n+Yk2fIc33TbUdtOI9nfWGcyHTE/n9HOUqLgiQOkUYSOFIUv2Bz3afRa5C6nKKdsB1XmTMj9GOdLkqi\nB1hIlBTIE8JZYSBqRohEpEulItKedSNIIOg1Nu6HIYs9MNyHuGZqtGB1r4jSj2emxuGs3Nx69ietvO\nEx/sG63xluSvGBaGoKP6XV30WwuMR0HJsXmgUbW8nt3Lz4SKXAF6EhW81E8Qmp88FgfUEgiJdFSIox\nlstnnpec/xdNPfuau0yce/4iSQ+a6GY0kRoc6FDMClIHIIWOFlwl5nlGaLkrN02nf9X1pY/4FZLc67\n4loZ6tZZQp+jVbpWvH9pw3Zr34GDJXaP0ZUw9cXvAg3BWFuFcqitEfWtDDhq+G4EJVI2TtJsGO21ic\n88aWXeeIrJ97gpum/2t3ba0TcrIp621ERLNZbvLeIUHVARQgMC804hy89/vS9X3r8q/96aqDZnmVSl\npw6eYKXXniO0Ssvg4b77nv9//Tud7z1HbfdcuO4mSXfLIJPk5ai02wy0+yQKMV0PGaSjzHCY5Vnfdx\nnaqdYTIXFl67GJAaUqpQ+Eg++xJkC6Q1ppGjEmkQHOs2UZqrptBMamaLR0MSJR2lPp9tAtRxRlpC1O\nxy64Sbe8Nfu58E3fxv3v/GBrdtfd9sHSjd5+3S0tbU53HqbMR7nI+Zm97Br6RBx1GaYb1JMyzcePHj\n9J+ba8iwVQOCqpJtKFKGlxDuLrPscfqvPKy+8zMN/9KuNrz7xxY9evnRqababsHd5gWYjQ2mFiBRog\nw85QTpElFCWGYN+incLNLN9v9Xu3fGPEC0QGT7E1d6kHtaHYOsZ6X9o5bti2b525vsLyXIqUuw2Nkm\nqFBV3fyKI+fcQJrHzplav1RSsUP2qQkiUCkhpuLxyjrMnz/Lo5y/fduY4v9ZSB/+bW9+0F+JK76bwe\nBxKVYRlXEBIBd6RO3j+5dPJ408d/+3cwszcEkFKRlt9Lq2cZ/2VExAJjt127GPvfPubf+6d3/YAzST\n6p3fedvRXXjx+/Eeee/GJH1h75Vx7cuEyRV7ghEc2EqSWmGLK+tYWnd4MqUyZDIYUZVHhGAIUdoqSA\ni0jtIyQIhCrmHYW0UpjYqVpJDFCBJKGJo4laTOrViY8ndku01jSm1mks7CPIze/joM3HRv2FhZ/Lmr\nonxnn/UHhBpTl9OcGg8mbz13aesfWxTVeeO5Z0nSR/ftvoNVa4OzKOo899uxvzzdvP7TQoSCAMwEVS\n4wx6KgC72LrzIyi5OWnnuWPH/44f/LHn/g164e37dqb4aaKcipxVkMSqrx6ESomqVA4FzMtUkrbJos\nWy2Z64CdQHfAK79VOvLX31Cd1f1VfWn7Nue9qs9i1le8vtjIikFXYV71SgpB+S2CHAfc2ZwtUrUQRo\nU7iqVqkVe76tODZJ0/x9KNnefaxDS6c7t+CbbTnm72Pzy0uV99QB7xzaFXh87yv1Ca2tKyMNI898dX\nfeunUudfPzC7SaHTZ2NjizOnTvPT8V5leXmHPgeWNd7/9Tfc99M63lTceOUirmTE7P1McveXoH1935\nIafn59b3Gynrf1JnM4TJE5KchxDU2IiiU4TvLcYW6KVJGtkJEmMEoJOK6bTSul1mvQ6LWY6LeZmOsz\nMdOl1OzTbDeI0Jm6lxM2UxmyP9uwMrbkec3t2ceOtxzj2uru4/a7XH7/u1lv+cWt+5m/5KDwsElXIS\nNCd6SCC5MLKpd9bObf2PfmwyDaGEzyC2blZ4laP6WjC2oUL7WbauGl5cf7fxqpi7jgPKlIUhSE4R6R\njmOacf/Y4n/jwR3n4dz/yT0+eOPc/SA+znSZzcx3mF7p0ZxrEDY9jjNAWYomQKca1MMU8kTpAu3njD\n8XNw3+EnK1VPDF10FI1NxShHg/5GsKlrr5oroqgE9eK7y9cfF7twFB97firXvDwJUJ4g7f+ei1kxUe\nq5f47CDnvGaxu8exTZ3j2sbNcPOMRZZP1C5N7NzfG+fWHDn+uPdeBJAZnCVIS0AQnUFoyHOT8yWMv/\nI8vvHz6R41TdGcWGY7GvPD8cZ7/6jNcfOEZFvct8+1vf9M7/+uH/voLNx05iFQBFwxxEpM1Wswu7jb\n79x38/NEjR3/xhsM3fXH3nr2mMz97KJuZSRuzPbxWjPKc4XCIVppGo0kkI6RUxHGCllNUcCgZSGNNF\nkfEUYXWi2JN0qhy41szM7QXF9h16BCHbr6R/TffxI233bZ1y7G7fnPfkaM/3ty96x/IVvZ5EmFKYdG\nxRmhBGmV0O3OMx2W5cn7t0fXB6Lt8XlBiSVsR3ZnraDWb9Dc2sNPp0dlOb2V2pv14hasJKF0Bg+M4g\niBYefY4n/zwR/nCw5/80ZUTr/zD3OWkKqKRxbTbCfMLDRZ2tUg6npIBIrYEpTAhw5gekj000hv+KEu\nPfD9yHnyCJ6pOeK/yYzsk9kqP9c8svvB1U3zfkNvOba9RtbW0eCrrjJQRUrZ/QEbmKRVkiqvORUI6I\nMeZkqKYMuyXDDZzcDGzrSbCzDHZnPL0V57+4L//5CPDBzL5z5aOXYeKr6S4Si0opoETJ07f8NjTz/6\nKKT3d3jxFYTh75jwvPPcC506cJGq1efMD933wPe/665++55vuJFBgyylp1qjGym6KoEmWdWktN9i9s\nP/hY6+/9+Giv/m+l8+cfOvZyxfe/PzLxx84f/b0XZdXVis3gvWMB0OKyRiAVKxTFAYhFN1Wh05nhjR\npk6VtskabKGvR7PaY372bzuwMy/v3Prr7wL7PNDrtTyS95sMMgAjKvCAIi0gEKha42ubjPCwu7eVb7\nn0jq6uDT5fuTz74/MmXfmwwuMjLLz1Bb/Eu9u9aYKY3z4WVSzz62FO/MtPJPnPocO9FpMCG6tyej8e\nce/5lPv3hj/L5P3z47108dfqDDaGxYonEB9xUMt6y9LdGDEd9MqMgNRgc1gS8VcjQIUl25ane9QPIO\nfAdvKjyZUO4oneoqIRVAKl6tZ7mz9K6XSu+v/DjStRdNVCnCkmRaFDJizK034/J/x/vYvBxlbKDwTl\nDXkxYX+tz/txqDTXTjLYmQMxwY8inPv6pX/QN7IMN9SvzB5YQjQxEpZU8dfI0n/j4p36nYI5ms03Wb\nHBxdYPV1UusrKyAdbzh3ru/8sYH7//xG66/niSW+KCI45SAoMAQqRjrIUoqPguj6ndJZma4qXPs4Rv\nS2x++c+tuRqNBc7y+8U3Tzf6xyVb/xvFm/9B0NN5jjFmQ5enu1tYgCxY1N7vk5ueWpllzpt9sdNbSV\nu981uye6iwsvdBdXnoGpR8ji8ckUJZVYam0eudjmeA0WAwWg0Lhg0AnCTFw7NY7GQxKVi9v/vjFzbV\nv3ZwO7u4PLnH+/AVSpTiw3GNtbYXjx1/g+kPLv9Pp3njrzHxGaT0mzzn5wnE+9ZGP8bnf+4O/u3Hy9\nC/qSQEURCyjvEf6QLCKySRnc3OdxkJMM6vSi0zhCQ6ypEWazL4f2XsRm4KrzdL1TaJC2m/3VARfX6a\nhv4zFJ0bVNkLIeqOR1JniIEMKpL8aVHK3S7LvkaKLzc8TucvErsRcXOHlF5usXZhhOikwE0/iI5Zb8\n1Bq5DNDzpon//nZUUfPPfC6f6aP7IL5FpMLF/jov/k3v/DyK6dvKW+9hyiTXMo3OXHhZV448RQmv8x\ndd99sHnrr/e9554P3MtOJoazU/iDxEjQRpQOlxgQdY4QjtASxjiAofFlFac3Oz9Ob6405eOARoXjEe\nEthSnywBCEo8xGXXvwEXbPKof134GdvZ121CZGj6R0ZTbxImUYOKUs0AeUTdARWGMp4vLMB2+4Iylq\nLEomKFk2ISBPLHcf2c/ny/WxtbL7nsSefP7l2fjN6KvwuStxOt3eMqBd46ZUT/Pbv9W9RvOsX3nDbs\ne/X0zGnnnycL37sY3z1Tz7196YnT/xi25cktcjMxCfZ1ztIK8yRXkxxl2bIxwm5yZnBIwcSVRzCJm/\nANe//51ty/69qoCk8Qk3xIdk566fR1czVqH7+6UWuDnO6Vnz/f/Q7r3yUyLoBI+p5uJARQqXfi0tvl\n7LxBmwDSQM73mI0sozWJ/jcEYqA8pJIJyQ6whlBpCRnT53kjz9R/uI4jNoPdL/1H/vJkM9+5o+//dH\nPfun9QUnSvSMKr1lf2+DFp5/m0tlX6M51ef29d3/Xt77tW8/F7aSyOGl21BZSSKLtzreOqlVGCoLzO\nBcIrto/JVFc/3oxzlUgolgpoiitxyyeqUrIG7O0TYlo9FBZl4Zsg7JkOFQZoUQMosJNyKB3On4BUGT\nsRFTvkFJ9/WoGnDEQKZJGytLuDnfeeTtrG8NzIoq+6/Nf+Mpv9C+scKbVJA2eTMesnjvN+ePHyYx9f\n+hvfSIui49+/pMf50uf+tSPDi6ufDDTEcoEQjBodJ0EBT4vmQ4dww3NsO+ZjGA4gaZuEiVddNr9otH\nx95Y7IyjJTpz1X4LHN+jKF+3YfMTVbs0aQ159KUHSfC/Sfl5GvRlnpvTHigsXc0aXxqhSk3gIWtOKu\nrSSjNJ5GklK2omY9vs8+9gTH7TCLAxE8cEvPv3Ub5z76suoJKHVeJlps8XJs6c5/eyzdLtt3vaWB3/\ntzW97428evGkJHWp5FGabXQciQYTqvuy8IkhR+d9UHaCJwgePs5YQqlQfESofm0ShZKXOMaUh012ya\nJaUAnQXaBELTUBXYMQ6CksLWXnnRI1FrM9ikUuuOA7E10roQEVxzaUQKA37D+zlgQfvpQzmN8+tnHn\nLs8+Nvnv99Gm+cu4MmY5x+ZTpeJPpygrTc+d/Iwv+4MvPPPljq2dO/VALiVQagiAmodfuUGpDR7dIZ\nULw4EeeyaZnMs7IywbNZAGd7tkkW3zvdljnzqolrhXfa92kfdXsZpvTXNlQxI4RNsjsuCB8J6r4vdK\nN2dySnD43ZXpxSlREZE6hgqalYxJAK0UrTVAV0ZXBpTVOPPPcDxWKH2rbmEPtBS5cvszpR75M3My4s\nHGZFMf933bnyb/x7ne879gdN1OGgFIei6nmTsLXQ34JIULUANyrcyIAgvD0tza4cOEi7XabLK2CHoM\nQqCih2UxRCiIZ4S3gEqRPwMYVp7L+1V8FDwrU7oCvmZK6qzg1r0qJuvLF4KocBqEVOpbs27/Esdtu4\nOlnrnvf5NLW/aurq4eLcoLF0yBmVqTYwYBnvvTlpsyna9pZZuMusbco70hURitNyOKUTtaiFzVpxU1\nE6hFFYHw5MB61COyBdA+kB74TZo9LYpQHvQPUlfxleXyDrnxy5/r62rs2VIGOMo7wZCjk7yPt9wUx/\naXxtM36uqLlW4g0Im8HjNQkokumWuiGot1uU9qcsSkxhSMpPbGOSOM2Ytf17Ern+czzLzHsXyai4Na\nbb+ftf+1b3nPn0RvDbLcy4loqSJDHVnFhQtacegNOoCK90zlyziK8wzvHhdWzfOGLX0CrmE6nQ7vdJ\nY4atDodFheWmZmZQydxNXP0dcu8XsLUTvHVPQexXX+vWjcq09TXXsDh1WqsKtG6ztRTgiTWCN3ghiM\nHuP++u8Pqky+9Z+PMqScTAomMEd4x32jTUAqz2SdyjkgrkiDQVpDphJlmk1QrvHXMp7M0UHRlglaCQ\nT6h7GtCuYyKb0Rle74Pln8fOgQv0dsKmlf9kNeK77WctO98CFff6eutlUfVsyCJlPyy0uWiihb/d8Q\nCXZWTxJY886BipE9IZEYjaRDHMT4ouiJha9yHYcm0HJN2uhxsL7A7mydTXY6fOsFYGL719ff84Dvuv\nfepvQtNxgZkHHA4rgAL6qP+dgC5EoRtbJ64kk+nooDUHmMnDEcbKO1pdxo0WpJWOyFOBEp7Yg2TwoE\noa/ZlCcHipa6htG5nZ1A56AxBOISMaqW/qVwZf87rWsWu1ZOx4Ei14sCeZe6755tZf+LEU2unT/zg5\ntbW/9lSEutLVDFBCIW0JR3dQJgSgSMloqVTmjKhnTRIOhFLrR6xDbRUhYDXskXa2suu2WP0Zm79X6H\n3y5YGmgbCS6KrwMqvis29VnyvzZwvAG4HzhxePUmtJUc2VJKyBEGSLPxkp7n79m5733ui/BTTcYnMK\n6ye8IJYC9JEYcsxG/1N5udnaSmNDBJJRDMkxCEmNyWvO3iYxUaDsTR/eMvu3R9ajBOkhcQanA/oVNU\n6iiqa2AeB8PXXZKU/tNZWmQNa4pxFKsmufcvcfuctXLp0iV5vlsXFRXrdWZKkiVACE6Z4U+JlIOgcX\nF75F+WEIDv1lKtEygiEJghHwBBQtc3H4TEEPb6y5d3Zpm7fKGqynAJjApSOEDyCgHKOXpZx683Xs2/\n3wofsePTmRIW3K2IyKQhFTlckNGoXSUZEJ0lpRzGZjOkmDWa7PTpJRKI9LSkJ2jM7O8Oe6+5iz4G7f\n0cke34yJ8LVISq6ErOC8wQpEDWc+FX3i2/QM+A3ZPEFcTUtwFWev+Drs15FHAtU71nFAtEI1RLtZO5\nf9hqL72kkW1glsDqQZS2CV7SyKk+837fMdJtEKuBLQyNtEmuBH+fkY0PwgtKVHF5cxGbqY/RHnH3qW\nQ6Lo8TLXdARFGFHyOsFuCBqvkmVXamErnDqtdbCuoBQ0OvOcOOtRzlUXo+UVRc2jpNKEhckcZwQ6Yh\nBvglRgVAlaAPaEESoBOfCsY14qP6I6qMItY87YITZwdTInSK8khZkCk+UVt1VLXSF5Chyhpc3WD1zl\nueee5rxpI/S7mPCh7drBJQez4RW3CYLklglZAjaMmY2bdJptGjoGDEpkcGTKEVa13u32WXv7uugd/h\nfYmJhIxHc9tAgVO8xwRIQVQMpfOMX3jds8W3T4bab5UpsJ5xUhx3rDEFERLIWljkBpQvjtdF9o7URc\npiTyJgkk0Rao6Um+JxBf4qSEik8ZZHTzFKEs0QiRiqFdxJPIDjLeLCJ9sn/Nb44/bZnPjv+wOba2lc\nPH7uR3vICemm+0iZGgjpMh6CrwBdb7wyTONqZtUVxmxAMFk+vt4y1ZRUGKarsh8pQrBBIXAjotCJDu\n+BrIphgW1Zs8CQIgqiARdXaK/FB44WtBwox4NAEfI2d10rWoSugoqiiZVtPaQxmPOLC2Vf4yhc/xxO\nPPcpnPvGpW6ej6U+5snio+u4RGsGs7NKQkqj0zGUtmlLRkBEdFdMUikxKmlkDbQsaqSSRgSiOcJMJ0\n7MXyUb+PmLx+9ujuh3mSrAgPEJUcncp1Dd84X3jrnxXSV3kqyJN62y6SGO2GzEehHG49a3rB6tr7wt\nbY9IoxkkHSLSWFRHC1Yk6UkKIdy54WW8XvQuVodU5nHdgJGZsKHMesoP+Q3Yy/ZnR2uY/StrtrSPHb\nmHx4AHY16pWwClMhIeGpAafVabPegWvBOLxVSL8KgY6IPChXtmvijcugsUEgduGPHmJU3WAJhkhVNH\nRQUe1jSZCBoEXMRJwxDsCoUhYnC/xtqJIl8ZjvUZJjbWei+fP8/gXv8BnP/0Jnnr0i72L58/9hED9S\nJHnSOdRIiVSglQqUimJgYaSNISgFcV0opi5dptGHKGEJMYTR5JECaR0SFXtWszWiGxt8300s/9bxbz\ns1JVgk+09chAe93Xjxvur3HB5FRPr6r9fsZN4AgkCjBXDldV3bL5yRoitMVmkCVrVYKUauSPrTHexH\naioELV41ztwweOExdeQCWs9zkFuDZMyZ7i++SPr5y59T9DRP1k7c+lDh4/eOLnujqM0980jZmKaXYm\nThpySlGZdSPUY8KqObZAgRXTVKEDtQLy2bzzexRBiJA0QKXiNldRhKhLh69m+Ay8rUbivx3/oajIa3\nDbIWVdzSVmxPtMQGE1Lnnn2eZ588mmee/opnnv8scbLzz71D6bjwf+cSTrBKwSeGE0qNZmKaHhFS0U\n0hGK+3aCrU5pS0U5juo2YRpSAt4gAWaxJYk3AoyKJloJicwPOrwj27H5H4vj5oHZSxF41D/Ffh5kLf\n7W2nfV2Tb5Kx+d3znq2fpOEr+VdRZ5MVi8dzVcvzjXKnFhHV2BMoQqZ9FTbGikCvj4/BukrQhcgpEN\nXzVPiSID1eGvxJsdOppSTknJcdpyQP315de2HL54/9wunz7z4S/NHli4s3bjM0k2LpPMpUhYgFisWp\nVTgVXUnD7U/zV81+5NXwk/U1f0kkSCICV6D11VE2HbM2tUJRRK8kCh5BWQSqDSTwdSNqpBDKMGVbKx\nf5vS5C3zuK4/z5S8/xZcfe3zX5qXL3xem0+/35bCXAJGsUjcTUlpRSlvFZF7SEJqGUnRUxHK3R0trY\ng+JEMQyEElLEB4pBFF9RPBSEJREKUE56JOfOz2X3nLkqGx3kxhyBzUfpj4s/+VpdH5jr3zbBXhltZM\n7e7lqmxYqu633MBzvyS9ffC/9LbrOEym/U3zOORSeIEQNSAoVk0RUhelCteohAjKqCq8IlaNdElAhE\nEyVCe8nE4yHcZH3htOND5xefe4D/jHzL3oHm7929J4b/v3tf+0W9hxeBj0EkVRPFVORliNkqLDvOJB\nU2IsrAKkq09o7V3M2RW1UrVYCvTPkNGBrXikGIad1vrUGaYlCDqEHlOBGUPTxeZ+Lqys88vkv8IlHP\nsfnvvzMfZc2p989GJj3SXQ1La1faWsDs8S0dZNO0iAJksh5WlIzGzeYSVI6cUwnTolw6BCq11tWabp\nKKZSXlQFWK7yO8ALMaMBk5SzppfPvZfVX5S0AACAASURBVD79J5rohKcSpm+Ha1a3QXut+L4uDn3bs\n7N6K1J196qEHomsLsjphMml1b8/vnhZJnlBSnUnrjieAYUlyFDL1KphuNQRPkisr7EE3mNDdecOQlC\nOC6zJcQRwDucsRTGltFB6S+Es07UNpusD8qj/vt4wel/aPf/k0u6t3+o0Dv52b37hhFApRA3QTRAdK\nhZJC0hROgF0JZUL/qo9p0Xi0DTRuDpQ0lVFJRICFilzoGLcICZIOa32mEFCKMBPYHqeUAwxky3K8Tr\nDrTXOnDt93cvPf+5vPPf0U39r/TJ3GF9BsIO1FMESI4lJaTUa9CaBjmrQlQ0iD7H29OKUhaxFL0nRP\npAoyOKYWAh0tN0cE2gNDdmgjAQiq3I1pIqQZU6xcQnOn5YcmP37JO0flFETJwTCKZTabqdpvr4AgH8\nVi09ckU1eLV/3XOVUDuBG40OXzq0cmmxcVqmHjhB44eviq3LhJKCkrs93onZMCEQQeCGxwhCCw3tbU\na2LHFeWWOkw1lGaCYU1dTRcQATLJN+iVH26PTiwO2PPLHckdvWO8aXJB2Xc/IJSyce0bj0sVPdRrWc\nQqodQMwjZAtWugjG3CcxCbOeVIbCEoIEcRQF+CmZYEfdUDnZcubxxYIe4coswzTHTkrwckTMkv3SKf\nNzHTvt3+aL/1vGo/4619fV7YnmB66+DzSms9WFaVq9xJGNSH6NkhHGKGRLaMqMlEiIZaOqI+VaTuax\nBpgQ6OGIpiIVAKo/Scmf11rEgFilWemSaISKNlBBLiZsMyVdOq3Sw/xANechHyakg9I5hlr80ZfcN3\n3DhyqD4yj70VYEYhEAxmswMNta/vRhPmBGCTCsmZVHTAB34ahsXCQg+YEPAW0+okxyFEFWR1zh0hyO\nSgpJtZF9OnueUxiB0hNAKpav7s04li4sN9u+aYdd8g3bmScSU8Xj1HimSe1Ctn5aic1HquUe0mvm8i\nkZfEar3hNbjSSAl7HBnFLrWVzlvMDatVl5bQD6EsMFA5IgoJ7Mjys0xzhsmfoNxvkq+tcVoa9jYGq/\nfOXabd6v+iXvLyfD+RNqlRuSZjIas90cEH9i9nHBwVGDPwKSoFsxEJ8QhQRMTxwkdH9PUGamISJWgE\nyf0Gm2acYz2hkxFaFnZo4K3SKXQuiKNy0jhS4/1vsL1I7CuMsD6PGe0uUY6Hny7K9o/RSucEuJKNPd\n2k+pa8b2WD2MhhlxAiSRBkriKk6sFFDEYB9p6wvrgR5PVTblsPc0ENtYuEssmWmucUlgnyEuPk55UR\nTSFrhiYoUCEymbqlKWILQOfM7QFZXtEbidELsKNHfHQ0kTTV5Zhq+RyvIndPWXXkZT2zU26Bxxzu9Z\nZSjZoTQ39eBcwwoUBQqwsRVH0HVEUfUd1BvXoqHHcWY5L3XhJiuQV79S5INKLSiWXcaHvB+fHifXl0\nAY/GH1J+qDivAzNydR0TennN/qjJVO6vcPh6GC/3z9SFMVNwYubiqJgmo/Joo3qeAzEcYVfdLaN8Io\nZmbBPXCSJA3MKhjlIMySLNFmakkQtjgymRJHEZBLbUESdmBCD9o45H9EKAu0VIY4pYgiRIsQRSipcg\nLxxHh81KLUHnyBKyYzz9LKI0eo67sQpqeaXflSF6G8aD6qeiygzpKEMQcxcK77XtNvCq+Bwr/pvzlX\nHQZfndxeDwUEzyVGlwTpLrOrcu51/X1mhvajOdYSAweFDRafWWqJCwBcG70oiAsPcMp1YnI8QcUzUi\n7DBYooBuR/S7Dhm9qUcuq7H4f0ddi/HtNsgoup7OlvNGEIAX+stfbB477HGMw7jm6zhJoGGEFOWjuC\nr2V1ZWkajAQ5BPrVMpiXWVVrWae4Zj3JWL22wtTmkMJY0TQHJeDzGW0eSJIzqOWMcQ9Z0RFFlYxJUO\nInDN+xjbsHS7m5x4sSEyxvgzSaNVoP2TBc/SBCNhFYzQzdisigmEwKpJGQJ1lXAXKkFiZIgBUorZL1\n6i5rPKWsBgQ+WMjiEFZTGs7W2Rm9r66BaMHdLGX0l1PmWqKhq54ZrK9/XQfFJoquHrpIqn0FV/UMzG\ne8era/f7qdTlDV4Z4iTiNhHBARlcHhV6S1FqMYT1nmCtjjrcd7jrcfZkmI6xJqCoATFBMpc4ZViag0\njM2HoBozEJqprmNsVceONPY7c2GJpOWJ5JiNVAes8LkqQchvs6ncQGN56rDUYY3AuYMqqILyT5FNDW\nXrKwjKZTOn3DVJqxtOCrf6I0ggCMaNxyfrmiNGwaoQ6BwRTZaFTfe5cTltXwTFxQxFEio4CzhXo2NG\nKI8ZmSNJusetgB6dBvTJhPIRCXGZrWjBs7SdppzSaTVpRRCoVWgaiSCFaGYUtEUJUNi0CWqmK4amp9\nJkuqmRrQlb6XAU2VDkapZNML14kvXz59uae6W7VjCq7owAhNdvJD9eK77V6SMnVbZbt4gsCrNzWK3r\nGa2vvH11YTcR0irKWYC1KS2IUxjmUr9DikoAXlb3HBl9hA4PHuJK8NBRFgTAObT2+CBRT8CLFxgljY\nDM4xqEgNAzz+yUHDkfcfH3MgWXIspxWFCFFggkxZdxGUNQz7QpDDwEfSgiO4F1lgK8s+bh6oBKswZc\nWm+dMxwVSakzpqsDM0lGWnn5/ytZmrYuWCuccZbkdoSBxzpPngGojhKclIqJEIWyOcY4YRxSmBG1wj\nNDtlKX9TYglK+dG9DcLxqOCc/EScUMz18wq8bSUxInGKY8RDhFJSjzaByIX0Hhk3Sl2ArRUFXYfWcn\n5tMNLsKq6IRX9LdzaesJo8H6yzkeErAYMob5ko2vF91oWXz1Irgkp29sQLyungwSKwdZbBmfP3TK5e\nJFWnhN7hzMlLoC3Ed5XWQhBhtoB4XGumptZ65BCYrAVOdp5lKhyH2w+wQuNShOKNKYfpgy0gqzJzFL\nMwZuaXHdQcGBPi4UOCGmJtcNLQSk0RZRAUSJE7XBAgHdVBzPESF8NlqsbvAYX8IXDFxG28LhSoVSEt\nR7vQcoq3dWUpsL2SXBOsN535CWkicB5wXBY/ftmU7I5lOhI4aQgRCCUxQCZAl1OSJoZ1njiSNOamSF\nqesqwihF9ihzU3mWypT0ksgFbOcIJsjjCYZmUOTpRKAJBVnoUrxxSGVCKEBzGVTcUhScoj1cOpz1BB\nYT2MBliL12Ctcu30J17i4iyj1tZye5CrTu6Vnyv1aRBVFtOEXgVIc7tGEhtOllfv3WyeqEnhgNSZ0m\nEYFpN5gjegncIb1GiTo5zFu9KvAfrHUIoSu8oXMnIGArrGRclk7xk0jQcOXojSzfeyKqZcrp/ga18l\nUZzzNLhBnv2CbodTxoVKFmidEKpIpxUjDE0VMWl9EIQgq9XvmpvJYQmeA9BE7zEm4ApDDb3uFwRygQ\ntHCY4TOkoC8d0ahlPLc4qojhi0i8wFoyB0gacDeR5LcQTgThUWQrSQBgZgi4Rqlp5/DgQ+5LgFRkSF\nac0eg2uu3mJG25t0m7NcfD6N7EUZYiVTTaffpH+2haRV7SkJpEVLkNIUUXZK4+PFD4WICwieGyo9sA\nimGq1jwKFMkhliBBEpac4fw7OnO6xuHgrWfQISufVHkFdm/O9ps1OKruJuMpAi9zmkVjsdGDGF1beV\nVy6mMXjEYmzRK6swA6hEuiGYBCyyj8IziBsXkMgQSrJJC8YWcM4OPrOMDIGkaRksz0OHJnhW97xxsk\ndb/q278yj+HOvbF566OS5F7/v8qWXblvulizMlmi9hVADhJrgJXilKo+csChtkdIjQhX15Zyt/RkOL\nyobUjXeU/hgcU5Q2kDwleazdKN6wCmZ5lNGY0NegHGK0kBpBSqJUXjGI0Npqu/lPAzHjpmWw0mYWMN\n0nCMiT5JVxyk3EcwkPdKsTaO9RNZeZKa7l11L13Po0M3sWt77dJku/ZK24cNbJ05/i86ifzV9/nTDr\no+QhaMrU7A5XkjKSOAij0tBaon0DmUcQcfEVV5R1eiSDhdZgvJELhA5z3T1PMPTJ7L2dYfexVzn54h\nafM299lrxvRaPbSm1ugqZcKUX4zGDzXdN1y48aC9fJJ0OEYXHljnOF7gAxutKoBscwllwJaLIq3OVB\nBGnjMsJW4WhUBGjVDDUETNLiywfPOhe99++8SuHj97yAXbPfVIZx/7lI7+864YDv9zfuPXb26p433T\ntxLspL2DDBugRjhFOGnTi8cEQ3CZeiKq7KSpIbPCh0piGgPMB7yUEh/GO0o4xzuKEx0vHNDfEUYpQC\nusm5CVYLymtYDg1GK/Y2CrIS4h0jBewNSgJARpZwsiMUV4QyhInAkkKMslIRAOIcWGG5d1HufnoHRz\nYfxOLi/uZm939ER01/4WzfHRU096iRvzvombW35yb/anp0y/dXZ5dV8F6lFdIGXBK4aJAiCTIil0jh\nSdKmkTeowk4GbDaU+pQB9EGdDBM+jl27SIM1h+kXH6XSOIPOxlfK77/7MXl/Z/yal39udv+wbczh23\nFENIK8umgM127+NbJ+TMlW+txIxhi4Sl8jjMFhfGUItDMGrjSMO5vIQXV3Cp4ptOS8WTM0AXGArZ8o\nC8FjX3L4egD94l7H3zwl9qvO/BvUfoRpEM1YiBCRglLy9lHpTUfbSZzh0Sx+d+Z6crfzPOVW0t3Cee\n28GWO0A4nN6rsOi2Q0gIFNpSE4BBS4pxBSMl0lNMfjzAYVKYwefWzTUswLlCUgdJLSge5CYwLz7QUD\nIYGJyRBCoa5pcirZoeOIoSOOb82ZHYWOp123cJXJI1FDh26gT37DnDkhps5fPgGDhy87qtJ1v5/Bfr\nXpUpPVYm3ZdXtl4K402bh6HWfnJ+fLYu9e75j89Hn3r/51RdDpr3oNloEkTOcrIN3NLpNhHcMR2NCL\nNFxghSC3E4oMZBUZ2CbF6iyYCZJmVw8y8zKqZIbD75Vm/jTOokHAXb0rl8bnPq1CcbXiu8vMkm46sX\n7s15I97V7fr3dALWosmiXq6u3i/WNWE2GaGdrf41B14JqG0kmZogtSlQsEc4zHo6Y2BLZyOgPpqxbw\n0peUrRbHLrrbr7lrW+/fMvd3/yb6cLCj+WZnlb709rxgK0HHhFCxUSd5ins4k/r9u6fju3lb7blxf/\nKuovvdHbjVhcmmNIRXKi9gdX80IWC0hUE6yjtlOA8uXFMnaAMIIJj6g3TYEE1MUimzpIbzdQqcgOlU\n1VSQaRwhaCwlkkRKG31OqooRWVtFnfB0tIudu/bz8L8IosLuzl4+DqOXH8TS7t2fzVOG7/f6XR/N0r\nTLztjKL0jkqC0IErjClAYAiZU57l4ef4RncRf8Yn2arH9t7eef3khH/TRBXQ7c2hpCEWOd45Ob4ZBE\nXDBUtbjBaVcpTgyHm8sOIsUloQcu7Ea67WV23XWaqdJGJTXAEr/5YrvP7Tx9Nt8zu0ZkKja8W5z64H\nR2bP3hI3LJOUE6as32ocqzVZLjUsCRZlTmAmp0EgpmDpDfzrFhkCZJAwJpHtmueWee7jrLW99/PDtd\n/zrZHb2Q15IjEpqnb1DBoMMtqZXVF4KG4A4RsRzaGa+rMPClzG7fhy7eRNu/Ja83P+msizvN/l0xro\ncR4FngrADSj/ChkphU4YRRmQ4keOFxzCmRGNCRlFaBhPHuFAUJmFqAqXXBBVTmDGGCJU16LZikrhJs\n91hbnaeTqfD/v372bVrD9ddd4R9ew9uzs8tP9Jo9T4dR8nHkRwX+so8VWpFJKqcQE+ODx5NE+XrAbm\nWeB3Bwuw0a2U/oPctvJLPZH9n8sKJ15VnV2g4T+ShsAU2SFSqifEEW2IpEJFHa4mzFudKpK0FByEnQ\ntNfOcns6b33iKXdD0Rp5zeCSq4V32s7Y6+REWGHJ1HZf6bTrt3YfK9ZuRBUf1MkZoqUUDrD1JYEL5B\nSMTUeGwwGgzUlUZRgIs1QwMZ4wpZWqKVFbn/g/vL+h959eu7WY9/thTw59o4ky7gSOqyQ+OoZLEJIA\noqpZ8cAK4UkYRYRZaDnjhPM8TSLfj4tS0w2udPZ/PXel3dZM76jyIfHymIYb/XX8G6KFwOCGGBtXmk\nkozFejTBmgKEgzkpmdKA1oymdJIgUqRtMCk+StunNLDC/uMzi4i4WFhdZXFwue73eM1naezKJs0ezr\nPklrdUT28YQ52uHUllvFlQgikVt0rVVkIpwkBvQGi0jcIGJspRC4rIGan/yK91UfjLpZP9uqMSB0em\nV2E4CUZIi0Iy9JYlDZd4KHhUJNI6yLBHWIp3Ay4DHosgZXTpLdPZE6By9/b005j6m0H2uQXP/M44S/\nhz1rKzV1J4qLRZVZeeRT47ZjY0lsdkXyXhMUuecG0oKnyO8QlrJ0E8AsKLK5ekXlo1pzrq3jLOEeHk\nXtz744Pib3vqWj8xdf+Qn0dELQick242eq54aXSMAq+6PoJKwuat6QdZDFDIIWW0RkhBBpHgigicQt\nbvV5YRQ3LAHe0Pw+eGiGO83xWRPwC3h3VxR5jOTyag13VrN+qNhVBovG62ez7KuCSqdKpWNdNrcTNL\n2ulDxxTjJzsdp64zW+qRQ6kWl1Itaa7RIdzbuvg4bCaFizWyT+XwA5331XoiaXk1U0cLVtsui9lK6q\nmliqsnrOF5cfKYR1Lua6H84TpJ3mwurzbKYYF1OYXJ0UeCFwUmLEJ5gHaK0RF4QaQW+pJQGrKeclBQ\nXVwRba0v0lo8pGX/W6/ha8b1WRRiEZ8chtsOr9NjJ9Nbi0tqxeDIls5YYg5DVaEHEAll6hAsYW2K9x\n3tBieLyeMK5rQF0Z5m74fpwz7veLQ7dfdf/0rvxpj9A6pdyG0h0VWy28MSJrIfE9bKLfBV4Vl1lbJJ\nchZp0QJB4VceX7+ji6k+iFAEvgnlReE+aGFJntznv4BxlWSCWVlhfX6c0gdm5RVqzC4AiyASRNCgmO\nUHUPjmtqpHFdhNLSiZTi1KKKBJXDOLbXBl5lY5BVr9QCBCCQso6pTdy9TIZQEbEWte58WAJKDTp7Ow\nL7dtv+d+6s70vb7z0ws9eevnFMNkohUPTnBY4THV6dwZlHdo6tIjRIqKQghJHMFOkMZSXV+Hs2WMsH\nrqVrPPZa9vO/8Jnv6sL0WOri03Usz0BFKY92uz/8PrZ8zSKksj8f+2deYxd1X3HP2e5975t/Gb1jMf\nGO/bYYBswBgMBgp0GXBkqIG2DQqqoahU1SEGqUrXqH5XaP6q2qVSlCKqqTdp/0gZFbYIapS1UJUogU\nkRD2Yyx8Ybt8Xj29S13O6d/nPvevJkxhQQCM9Yc6cqekWd83znnt/9+32+MTGJSz84PwgImTklkndh\nYapGhZgSJ79G1dRO9u/ey5cAtr+07dPffic7OJ/F9Ujw8PV9TzCkJhNlLqayZVC+IR62JkVI4DvcmY\nG72zyxYlSzoUBTY+c9nRJYJVWAD0C1zUp5rhsZKgqogIcTPd0LQ4cQlAWxAUMjPW7amwnLT4xII8u5\n9LWBMTGpcptXzPCwQRTFaa5T0nRIxztLYJKMY81OHxy1sw4ijwHFfpILUZvRnnWve9kr6a+1tKgkL8\nrft6bP76hOT+PUJIhJiU8fGMaQpOTQa6cotys2HRVGITRLmRi8z+tYxejbv+grl7m+igtlV4fsIhW5\nBBrTBrdMAP7IQ1asPzExOBBMjo+TDkDSsY6IakTDURUoUG2RdYKshdS/CCkW1HjOXWDo2bmH7gdsZu\nOuefyvdcMM36Oz6Ll6+OStO6p55sORaNhnugfUXwq1LiZQqQ45OsTbJujL8ZqiSMtNA03Q8Dg0uBwR\nWuQkFgUQK6XA3WzCirAVlNWEkqdddQd3HA6EyRGpJmmRVmAzHxS4a/4jTEGtTlJIZv7uLow11LBLfl\nxm7qyWNXWyttNtuN1GegM4m7RHExuLHGUW3BWkERkIoDcLXBFvWP7mxlBssFwu/OXLi9P2FmWGkgSS\nqYxLXbKCFRBhBkiSInHQOfBohjaEyOUH4zjk6J8YD1V95gKDtm6vC9zHFfIIqxiT4op0kAc8z0s4Mb\nUtffX7D9qkTeLODzMkKM4FApAG52EfUq4zXp5iws4xX11CVkqjcSXnnLq755Kemtn7i0E9yG7Z8oWb\n9GV/7CJM5gxJQCVbFJKSkJAS0z88zyXfbVk1DP4iFL49P5/v7/FkW12Hm2qb0TSd5/MIMXbWTlAIP0\nk5Cr43UM+i0ii8KrglLgSFGk1lo6XgkAtkSM1lwOJ4tDerWzusT1cgutwiwyTewrZu/xHhLUaQ94/j\nyrChgutq+J29a+8O2nTf+0+Dz6taRc+fak0vQqTyCoIZOK/jxKH5SpTZdJwk8ZizUdY6a9fCGh1Gv/\nM8GOjq2xR1dErRJjCEQHtpCGjokNGwK2pJgSRzKJxqBb7XzDBIgvzzu+YqkfHFWwfUnWgG1arU0Nnj\n5sdr0LPVqhSiqY5IQEYdYE1ELq0xVK1TSBOvnifwcaZCjf9sODh05OnT7PYef6OhZ+6hBTPg5fyFCj\n23dKpFhiHzMhyZla0dCE0RJNHBHPwTP44M81s670Y0/lVJJEAQTxWLx0YFbDj5xzcDAUKFvHUmxjbo\nfEHoBsQyIYoGnAmQsCKx0j4QorDJ86RwMX3jM1GslZWOkSR2AgQDlzHdDW2S6US694GLV8n2gFeAhh\nEeMa96tTc598fLp8+3x+BRerYaKaigiZAqVeoQ1PmngMx3GDE1OEXetY+CmG5NbPv3p6rqDt32Btf0\n/RQfjAq/ZKqpFa8CkmxZMLoMGJyll85Jn2ZCs/CGQQr4v4fpFhw3N92tZvu+jlBpTW7Z9bYPnvVDqK\nH979u2ThcqpN3U4WmeN9WkL1hDOzhDVq2jPR4kITynCNGb48hl6x8+167D+RR0EX5VCZDGBahj2pqK\nUGV43GTTW/++prArfksvxbu6nNpBKSSwEnqG3Mjq2Y+r0ed+bmCap10jSCGvqCCMRVlJJYMJqZoMct\ntDHtbffw8HDh/+j97bb/oZi8dkkjLG6gEETpZacEu5MRUvWQmoH374MhG9JHCzEPFvTMjm/xVaw0Qo\nmpSQWwXhu/aZn17d3PDLb3f07Fz19dFoopseGSecU2sbYNCGnPMKw5mYfpWVq5B3Mhbd8Oz2xg2KhV\n0o1bI0AqZro1q4yIskqUFhMJn6mOQe6Knzv8xCvKICRhJxwEVi1LiuDg/dHg4MEk9OYKKQe1wmjKsY\noIlFiNIwYlYKe3ddx860HuO7wI38ddHb9I6X2/8XTGN8B8hlALaagaiQbLRngj1w2wpeZwWbiyeKGg\nOVH+f+/h3JoIoIb0yx3xCrASMi1dX2/uNUf2uDlzhS7er48/uorXDp2jK5iBzmr3VlUa5i4jhIxszM\nVzrz+El0HL9zvl9f8EcUSQlhSFFa62qpqfHgrUYKFkxCrlu9D0PjksjpaQmVy+PHqhbO9ufExctU5S\nGNmowiLZC5MmQgrRJ39XHvzAa47/KlTG/fs+T7X7H7cUfBIUqFIgSjLSTZZbiVLEQvs8ooZhGhkZJZ\nXx4fJYlApZdNFbgihEC5HaqxPJA1+oeOV0rbc46q4hkh6v1yzcvvEmTN4oaEeVYmNwCQGKRL8esLYq\nbcRZ071dmza8Dj5/B841kxL3CJbooXPT0iZEQeAEGa+7LMqfD9v0OOBNQjCHZVLZ/fXzr1JYXoEXZk\niVhEzRpJIn1Brgu51XHvbXey5/+gbwXW7/xIveLoeC3KlwKYCIqCWuKJzE6buXYJzK+Y7XJZNzLc44\nfIRXK73ihmVUk0BXPwzUkpUAkJlfbBgY51H9m74/e4b9culrt6vXPjJj6+ffPMNpi6eI+fn8UyIjiN\nyQhGNRpw79jrbdu/aT3f3Dqw+CZDYFIxECYHXCvJpnABaTKZLzUIArVXh+xldTwtxGAnSuZ760Ok90\ncUTFGaHiecmmckZ5vw8w3Mp5a713HToaGX3ffedYWDnQ5QK5xFEAUFz6l0CBa3nU78mRUm1VPjE/AT\nTsst2tuyPWAamWQhHKf2uMXt2hm6YClKh8b1SvdS/+Z/b2jtfzLWX//WY1lsvRNViPCVR4zGqWiOXK\nirTKZffeoupSxf2tG/a2EObfBuVs1JohMqSKylLqK6Xy9ktOMeV4mouiCEM5PzAzgy+87lLb7zUy9Q\nlVDzNXHWKyPcZsz7d19/KgQd/I9195OGvs3Pv5ymWT1nhRQjXFS9tk7C5WZVTGHzZ4ANwnHDuaSXj/\nOgSFo3Pv3gPkiSZF0AhIFMey43BZ/Fo2Pw7O/g/bSGXPa6fW0dJvu2U6lv/+X33/8rXdx05mkbrrmG\nyWGaqUGYoEkwJOHP6NC+//HIvlcrn0J6N0ihrS1hZa0W6nWkMyk/3MjV+pHb5ohUz4yKVMWkhYDQRd\nF9/k73urqN25x33fpn+Dc8QyMFQOrg8kaR4mWFTC7SjWagfRUOFZow6SOyyKDRcBUulWYlEo6xAGde\niZiSkeBTKPa+qtra/2HHnPSeKa8pPHP/Bf4sTP/qBmJyN0RGcPHuR7teP213nLx5Zt37z3kAHr0WZE\nxBHDt7zSmGDWBW+D8EaarSZntk/cup0KRyfFCKOGDEp+S3buHbnXrYfeuCF7t23Pk3/5qfwJLMYlHB\nIZ0lcw5OLTqS1f2vJKdmMvNK0JMs+Xh0rRFbBWqGjNREpSkiUSDPUJgfJr1KXrTRKE1s1mF/b/9TWg\n0Xht5V/XZTa73zthR9x/q0TyHrIifPnxevHT5a6du/b73cV3tQ40g0dLHI5pSs3yOa3VhMuH8xX9kk\nqg6N3D588212drCBybei+NWy865fYfNd9/86Om/8UEbyQ2pSahVTLZiIl7+Xnhcs2BI+MlTIbArpCV\nlM2I4flcXgrmRK50UKkGi5oY8+zM5GAEAFWJMi2zievueHAq6We/j9Myj1HzsbfQQ5e5NTQCC+/ebx\n74M7xu9eXu//BWOnQBNRSwTPNLKhcViZwRbaXhcns/qnR4UdmHKb3TAAAAyxJREFUhsZJ04Dyjr1sP\n/qZoc1HP/MMu29+GL/0IkqDD1obRwNm4/lTb8Zyi6ydzWjCMuoxmz1iwbMqeB/80mVN5I0bqLJG2gy\nPlTh1uKbCB+ljc20vdm4deHjPoXuf+cSvPTpU3riJmvQ5fXGIS8Njj2D1fl8pTBS30PwaUtyzINGyj\nOKGlWj5vJnK2IOnjx+L49nQ37nrAAOH75xuv/XmP6Nv078YE9RkaEGnSBUCKRqBFj5e1o1ksxMQjYK\nelQuEsLUwK2m1kpmlVB+/8K1kAQxaNtBmjeMOl8LtcRzV8WQuG6FQGIQVWtbW79zz2L19Gx/uL5f+J\nP+fz5YHR8Z56aevxNt37n2wu7fnNd/TsfNaXBiRZiGDwKDRLbB3q8L3867y+MTlXdMTo8WBbbvi/Qf\nvGOLAvt+qrl37w3EIcxLag4x11laIRAWPAI8Ot/ExpH6jWC8yF2devkyLrInFgmeWh7OwRPBWGG+Wi\nF0jppWWRJBNHxikcD21XjFwUpk6AkatJEkC1orBclf73x564IHjhb7+v3/uv55fNz45VRy+fHlXd09\nPmSgZc0hPNhvYAruYN27V8n2gtXV8fOShnq5O9t+492kG9n2LQv65KWAaWAMUDPhEaG0oIFyOMgkhy\nYOaz2HKRVHc4lqQbf3LMisUrWjrl9XhhBCkwnWnNLiFDVCParR5BeeRJE47aungOASE1gueu+OTh76\n0dt3Gzx47dvzRUnHNQ8Cf2yQZE7mg+XtslqVWi5XocjlDu7K0pgS+dfbs2V8tFotPlUqlr+ZyuXNO+\nduFtaSrZF3pfCpiGjN2imToJJ39m6BjG1XZRwrkAI8YUKSZWlEZQDAIrNArHnyvpXtmM/B7wJeAbwO\nfBcxKuQMrzfLdBoz29fX9led5v6u1XnBJW7vnr/YlrXEoNo22LRYOYlxZ1S6rkOfDcLvPAY/hGmWC7\nH68uFI+x0oSPg2MAN/L5/M/vtqSED/T5cMu9J4Wf7HMGsB/4TEv/DFwe3Y/NPN57VXh+5BWApwFLlh\nr661tV1eju/ne8YJrkWtES0tmRe2VOviv2j2aBp5nHihiRaz/A4oCnsAsje/+AAAAAElFTkSuQmCC\"\n    dpi100aspect2\n\"iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAACXBIWXMAAA9hAAAewgEw8YEEAAAA\nFklEQVR4nGP4+vXrP11lJgYGhj9xSQAzOwXsETZ69QAAAABJRU5ErkJggg==\"\n\t}\n\n# $encoded(basn0g08), $encoded(basn2c08), $encoded(basn3p08), $encoded(basn6a08)\n\n#\n# TESTS\n#\n\ntest imgPNG-1.1 {reading basic images; grayscale} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $encoded(basn0g08)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {32 32}\ntest imgPNG-1.2 {reading basic images; color} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $encoded(basn2c08)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {32 32}\ntest imgPNG-1.3 {reading basic images; color with palette} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $encoded(basn3p08)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {32 32}\ntest imgPNG-1.4 {reading basic images; alpha} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $encoded(basn6a08)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {32 32}\n\ntest imgPNG-2.1 {reading a bad image} -body {\n    image create photo -data $encoded(BadX)\n} -returnCodes error -result {unfinalized data stream in PNG data}\ntest imgPNG-2.2 {reading a good image with multiple IDATs} -setup {\n    set i [image create photo]\n} -body {\n    $i put $encoded(MultiIDAT)\n    return [image width $i]x[image height $i]\n} -cleanup {\n    image delete $i\n} -result 223x212\n\ntest imgPNG-3.1 {reading image with unknown ancillary chunk - bug [1c659ef0f1]} -setup {\n    set fileName [file join [file dirname [info script]] iDOT.png]\n} -body {\n    # the image contains an unknown chunk iDOT\n    # since the name of this chunk starts with a lowercase letter,\n    # it's an ancillary chunk that shall not trigger an error\n    catch {set i [image create photo -file $fileName]}\n} -cleanup {\n    image delete $i\n} -result 0\n\ntest imgPNG-4.1 {data image with metadata} -body {\n    image create photo i1 -data $encoded(dpi100aspect2)\n    i1 cget -metadata\n} -cleanup {\n    image delete i1\n} -result {DPI 99.9998 aspect 2.0}\n\ntest imgPNG-4.2 {file image with metadata} -setup {\n    set path [file join [tcltest::configure -tmpdir] test.png]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts -nonewline $h [binary decode base64 $encoded(dpi100aspect2)]\n    close $h\n} -body {\n    image create photo i1 -file $path\n    i1 cget -metadata\n} -cleanup {\n    image delete i1\n    file delete $path\n} -result {DPI 99.9998 aspect 2.0}\n\ntest imgPNG-4.3 {data output with metadata} -setup {\n    image create photo i1 -data $encoded(dpi100aspect2)\n} -body {\n    set imgData [i1 data -format png]\n    image delete i1\n    image create photo i1 -data $imgData\n    i1 cget -metadata\n} -cleanup {\n    image delete i1\n} -result {DPI 99.9998 aspect 2.0}\n\ntest imgPNG-4.4 {file output with metadata} -setup {\n    image create photo i1 -data $encoded(dpi100aspect2)\n    set path [file join [tcltest::configure -tmpdir] test.png]\n} -body {\n    i1 write $path -format png\n    image delete i1\n    image create photo i1 -file $path\n    i1 cget -metadata\n} -cleanup {\n    image delete i1\n    file delete $path\n} -result {DPI 99.9998 aspect 2.0}\n\n}\n\n#\n# TESTFILE CLEANUP\n#\n\nnamespace delete png\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "tests/imgPPM.test",
    "content": "# This file is a Tcl script to test out the code in tkImgFmtPPM.c,\n# which reads and write PPM-format image files for photo widgets.\n#\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# Note that we do not use [tcltest::makeFile] because it is\n# only suitable for text files\nproc put {file data} {\n    set f [open $file w]\n    fconfigure $f -translation lf\n    puts -nonewline $f $data\n    close $f\n}\n\n#\n# TESTS\n#\n\ntest imgPPM-1.1 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n0 256\\n255\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has dimension(s) <= 0}\ntest imgPPM-1.2 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n-2 256\\n255\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has dimension(s) <= 0}\ntest imgPPM-1.3 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n10 0\\n255\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has dimension(s) <= 0}\ntest imgPPM-1.4 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n10 -2\\n255\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has dimension(s) <= 0}\ntest imgPPM-1.5 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n10 20\\n100000\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has bad maximum intensity value 100000}\ntest imgPPM-1.6 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n10 20\\n0\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {PPM image file \"test.ppm\" has bad maximum intensity value 0}\ntest imgPPM-1.7 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n10 10\\n255\\nabcdef\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {error reading PPM image file \"test.ppm\": not enough data}\ntest imgPPM-1.8 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n5 4\\n255\\n01234567890123456789012345678901234567890123456789012345678\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {error reading PPM image file \"test.ppm\": not enough data}\ntest imgPPM-1.9 {FileReadPPM procedure} -body {\n    put test.ppm \"P6\\n5 4\\n150\\n012345678901234567890123456789012345678901234567890123456789\"\n    list [image create photo p1 -file test.ppm] [image width p1] [image height p1]\n} -returnCodes ok -result {p1 5 4}\n\n\ntest imgPPM-2.1 {FileWritePPM procedure} -setup {\n    catch {image delete p1}\n} -body {\n    put test.ppm \"P6\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n    list [catch {p1 write not_a_dir/bar/baz/gorp} msg] [string tolower $msg] \\\n\t    [string tolower $errorCode]\n} -cleanup {\n    image delete p1\n} -result {1 {couldn't open \"not_a_dir/bar/baz/gorp\": no such file or directory} {posix enoent {no such file or directory}}}\n\ntest imgPPM-2.2 {FileWritePPM procedure} -setup {\n    catch {image delete p1}\n    catch {unset data}\n} -body {\n    put test.ppm \"P6\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n    p1 write -format ppm test.ppm\n    set fd [open test.ppm]\n    set data [read $fd]\n    close $fd\n    set data\n} -cleanup {\n    image delete p1\n} -result {P6\n5 4\n255\n012345678901234567890123456789012345678901234567890123456789}\n\n\ntest imgPPM-3.1 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"#   \\n#\\n#\\nP6\\n#\\n##\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -cleanup {\n    image delete p1\n} -returnCodes ok -result p1\ntest imgPPM-3.2 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6\\n5\\n 4   \t                                                                 255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -cleanup {\n    image delete p1\n} -returnCodes ok -result p1\ntest imgPPM-3.3 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6\\n#                                                                      asdfasdf\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -cleanup {\n    image delete p1\n} -returnCodes ok -result p1\ntest imgPPM-3.4 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6 \\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -cleanup {\n    image delete p1\n} -returnCodes ok -result p1\ntest imgPPM-3.5 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P5\\n5 4\\n255\\n01234567890123456789\"\n    image create photo p1 -file test.ppm\n} -cleanup {\n    image delete p1\n} -returnCodes ok -result p1\ntest imgPPM-3.6 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P3\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.7 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6x\\n5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.8 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6\\nxy5 4\\n255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.9 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6\\n5\\n255\\n!012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.10 {ReadPPMFileHeader procedure} -body {\n    put test.ppm \"P6\\n5 4\\nzz255\\n012345678901234567890123456789012345678901234567890123456789\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.11 {ReadPPMFileHeader procedure, empty file} -body {\n    put test.ppm \"     \"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.12 {ReadPPMFileHeader procedure, file ends too soon} -body {\n    put test.ppm \"P6\\n566\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\ntest imgPPM-3.13 {ReadPPMFileHeader procedure, file ends too soon} -body {\n    put test.ppm \"P6\\n566\\n#asdf\"\n    image create photo p1 -file test.ppm\n} -returnCodes error -result {couldn't recognize data in image file \"test.ppm\"}\n\n\ntest imgPPM-4.1 {StringReadPPM procedure, data too short [Bug 1822391]} -body {\n    image create photo I -width 1103 -height 997\n    I put \"P5\\n1103 997\\n255\\n\"\n} -cleanup {\n    image delete I\n} -returnCodes error -result {truncated PPM data}\n\ntest imgPPM-5.1 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n0 256\\n255\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has dimension(s) <= 0}\ntest imgPPM-5.2 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n-2 256\\n255\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has dimension(s) <= 0}\ntest imgPPM-5.3 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n10 0\\n255\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has dimension(s) <= 0}\ntest imgPPM-5.4 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n10 -2\\n255\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has dimension(s) <= 0}\ntest imgPPM-5.5 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n10 20\\n100000\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has bad maximum intensity value 100000}\ntest imgPPM-5.6 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n10 20\\n0\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {PPM image data has bad maximum intensity value 0}\ntest imgPPM-5.7 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n10 10\\n255\\nabcdef\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {truncated PPM data}\ntest imgPPM-5.8 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n5 4\\n255\\n01234567890123456789012345678901234567890123456789012345678\"\n} -returnCodes error -cleanup {\n    image delete ppm\n} -result {truncated PPM data}\ntest imgPPM-5.9 {StringReadPPM procedure} -setup {\n    image create photo ppm\n} -body {\n    ppm put \"P6\\n5 4\\n150\\n012345678901234567890123456789012345678901234567890123456789\"\n    list [image width ppm] [image height ppm]\n} -cleanup {\n    image delete ppm\n} -result {5 4}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ncatch {file delete test.ppm}\ntestutils forget image\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/imgPhoto.test",
    "content": "# This file is a Tcl script to test out the \"photo\" image type and the other\n# procedures in the file tkImgPhoto.c.\n#\n# Copyright © 1994 The Australian National University\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2002-2008 Donal K. Fellows\n# All rights reserved.\n#\n# Author: Paul Mackerras (paulus@cs.anu.edu.au)\n\n# NOTES\n#\n# This file is somewhat chaotic: the order of the tests does not\n# really follow the order of the corresponding functions in\n# tkImgPhoto.c. Probably, because early versions had only a few tests\n# and over time test cases were added in bits and pieces.\n# To be noted, also, that this file is not complete: large portions of\n# code in tkImgPhoto.c have no test coverage.\n#\n# To help keeping the overview, the table below lists where to find\n# tests for each of the functions in tkImgPhoto.c. The function are\n# listed in the order as they appear in the source file.\n#\n# Function name                         Tests for function\n#--------------------------------------------------------------------------\n# PhotoFormatThreadExitProc             no tests\n# Tk_Create*PhotoImageFormat            no tests\n# ImgPhotoCreate                        imgPhoto-2.*\n# ImgPhotoCmd                           imgPhoto-4.*, imgPhoto-17.*\n# GetExtension:                         no tests\n# ParseSubcommandOptions:               imgPhoto-1.*\n# ImgPhotoConfigureModel:              imgPhoto-3.*, imgPhoto-15.*\n# toggleComplexAlphaIfNeeded:           no tests\n# ImgPhotoDelete:                       imgPhoto-8.*\n# ImgPhotoCmdDeleteProc:                imgPhoto-9.*\n# ImgPhotoSetSize:                      no tests\n# MatchFileFormat:                      imgPhoto-18.*\n# MatchSringFormat:                     imgPhoto-19.*\n# Tk_FindPhoto:                         imgPhoto-11.*\n# Tk_PhotoPutBlock:                     imgPhoto-10.*, imgPhoto-16.*\n# Tk_PhotoPutZoomedBlock:               imgPhoto-12.*\n# Tk_DitherPhoto:                       no tets\n# Tk_PhotoBlank:                        no tests\n# Tk_PhotoExpand:                       no tests\n# Tk_PhotoGetSize:                      no tests\n# Tk_PhotoSetSize:                      no tests\n# TkGetPhotoValidRegion:                no tests\n# ImgGetPhoto:                          no tests\n# Tk_PhotoGetImage                      no tests\n# ImgPostscriptPhoto                    no tests\n# Tk_PhotoGetMetadata:                  imgPhoto-21.*\n# Tk_PhotoSetMetadata:                  imgPhoto-22.*\n#--------------------------------------------------------------------------\n#\n#\n# Some tests are not specific to a function in tkImgPhoto.c. They are:\n#\n# Test name(s)          Description\n#--------------------------------------------------------------------------\n# imgPhoto-5.*          Do not really belong to this file. ImgPhotoGet and\n#                       ImgPhotoFree are defined in tkImgPhInstance.c.\n# imgPhoto-6.*          Do not really belong to this file. ImgPhotoDisplay\n#                       is defined in tkImgPhInstance.c.\n# imgPhoto-7.*          Do not really belong to this file. ImgPhotoFree is\n#                       defined in tkImgPhInstance.c.\n# imgPhoto-13.*         Tests for separation in different interpreters\n# imgPhoto-14.*         Test GIF format. Would belong to imgGIF.test\n#                       - which does not exist.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc checkImgTrans {img} {\n    set result {}\n    foreachPixel $img x y {\n\tif {[$img transparency get $x $y]} {\n\t    lappend result $x,$y\n\t}\n    }\n    return $result\n}\n\nproc checkImgTransLoop {img script1 script2} {\n    set result {}\n    foreachPixel $img x y {\n\teval $script1\n\tlappend result {*}[checkImgTrans $img]\n\tappend result :\n\teval $script2\n\tlappend result {*}[checkImgTrans $img]\n\tappend result .\n    }\n    return $result\n}\n\n#\n# Used for imgPhoto-4.65 - imgPhoto-4.73\n#\nproc foreachPixel {img xVar yVar script} {\n    upvar 1 $xVar x $yVar y\n    set width [image width $img]\n    set height [image height $img]\n    for {set x 0} {$x<$width} {incr x} {\n\tfor {set y 0} {$y<$height} {incr y} {\n\t    uplevel 1 $script\n\t}\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\nimageInit\nset README [makeFile {\n    README -- Tk test suite design document.\n} README-imgPhoto]\n\nset teapotPhotoFile [file join [file dirname [info script]] teapot.ppm]\nset transpTeapotPhotoFile [file join [file dirname [info script]] teapotTransparent.png]\n\n#\n# TESTS\n#\n\ntest imgPhoto-1.1 {options for photo images} -body {\n    image create photo photo1 -width 79 -height 83\n    list [photo1 cget -width] [photo1 cget -height] \\\n\t[image width photo1] [image height photo1]\n} -cleanup {\n    image delete photo1\n} -result {79 83 79 83}\ntest imgPhoto-1.2 {options for photo images} -body {\n    list [catch {image create photo photo1 -file no.such.file} err] \\\n\t[string tolower $err]\n} -result {1 {couldn't open \"no.such.file\": no such file or directory}}\ntest imgPhoto-1.3 {options for photo images} -body {\n    image create photo photo1 -file $teapotPhotoFile -format no.such.format\n} -returnCodes error -result {image file format \"no.such.format\" is not supported}\ntest imgPhoto-1.4 {options for photo images} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    image delete photo1\n} -result {256 256}\ntest imgPhoto-1.5 {options for photo images} -body {\n    image create photo photo1 -file $teapotPhotoFile \\\n\t-format ppm -width 79 -height 83\n    list [image width photo1] [image height photo1] [photo1 cget -file] [photo1 cget -format]\n} -cleanup {\n    image delete photo1\n} -result [list 79 83 $teapotPhotoFile ppm]\ntest imgPhoto-1.6 {options for photo images} -body {\n    image create photo photo1 -palette 2/2/2 -gamma 2.2\n    list [format %.1f [photo1 cget -gamma]] [photo1 cget -palette]\n} -cleanup {\n    image delete photo1\n} -result {2.2 2/2/2}\ntest imgPhoto-1.7 {options for photo images} -returnCodes error -body {\n    image create photo photo1 -file $README\n} -result [subst {couldn't recognize data in image file \"$README\"}]\ntest imgPhoto-1.8 {options for photo images} -body {\n    image create photo -blah blah\n} -returnCodes error -result {unknown option \"-blah\"}\ntest imgPhoto-1.9 {options for photo images - error case} -body {\n    image create photo -format\n} -returnCodes error -result {value for \"-format\" missing}\ntest imgPhoto-1.10 {options for photo images - error case} -body {\n    image create photo -data\n} -returnCodes error -result {value for \"-data\" missing}\ntest imgPhoto-1.11 {options for photo images - error case} -body {\n    image create photo photo1 -format\n} -returnCodes error -result {value for \"-format\" missing}\ntest imgPhoto-1.12 {option -alpha, normal use} -setup {\n    image create photo photo1\n} -body {\n    photo1 put \"white\" -to 0 0\n    photo1 transparency get 0 0 -alpha\n} -cleanup {\n    imageCleanup\n} -result 255\ntest imgPhoto-1.13 {option -withalpha, normal use} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{blue green}}\n    photo1 get 1 0 -withalpha\n} -cleanup {\n    imageCleanup\n} -result {0 128 0 255}\ntest imgPhoto-1.14 {options for photo images - error case} -body {\n    image create photo photo1 -metadata\n} -returnCodes error -result {value for \"-metadata\" missing}\n\ntest imgPhoto-2.1 {ImgPhotoCreate procedure} -setup {\n    imageCleanup\n} -body {\n    catch {image create photo -blah blah}\n    imageNames\n} -result {}\ntest imgPhoto-2.2 {ImgPhotoCreate procedure} -setup {\n    imageCleanup\n} -body {\n    image create photo image1\n    list [info commands image1] [imageNames] \\\n\t[image width image1] [image height image1]\n} -cleanup {\n    image delete image1\n} -result {image1 image1 0 0}\n# test imgPhoto-2.3 {ImgPhotoCreate procedure: creation failure} {\n#     image create photo photo1\n#     image create photo photo2 -width 10 -height 10\n#     catch {image create photo photo2 -file bogus.img} msg\n#     photo1 copy photo2\n#     set msg\n# } {couldn't open \"bogus.img\": no such file or directory}\n\ntest imgPhoto-3.1 {ImgPhotoConfigureModel procedure} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    photo1 configure -file $teapotPhotoFile\n} -cleanup {\n    image delete photo1\n} -result {}\ntest imgPhoto-3.2 {ImgPhotoConfigureModel procedure} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    list [catch {photo1 configure -file bogus} err] [string tolower $err] \\\n\t[image width photo1] [image height photo1]\n} -cleanup {\n    image delete photo1\n} -result {1 {couldn't open \"bogus\": no such file or directory} 256 256}\ntest imgPhoto-3.3 {ImgPhotoConfigureModel procedure} -setup {\n    destroy .c\n    pack [canvas .c]\n    update\n} -body {\n    image create photo photo1\n    .c create image 10 10 -image photo1 -tags photo1.1 -anchor nw\n    .c create image 300 10 -image photo1 -tags photo1.2 -anchor nw\n    update\n    photo1 configure -file $teapotPhotoFile\n    update\n    list [image width photo1] [image height photo1] [.c bbox photo1.1] [.c bbox photo1.2]\n} -cleanup {\n    destroy .c\n    image delete photo1\n} -result {256 256 {10 10 266 266} {300 10 556 266}}\ntest imgPhoto-3.4 {ImgPhotoConfigureModel: -data <ppm>} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    photo2 configure -data [photo1 data -format ppm -from 100 100 120 120]\n    list [image width photo2] [image height photo2]\n} -cleanup {\n    imageCleanup\n} -result {20 20}\n# This testcase fails with Tcl < 8.6.7, due to [25842c]\ntest imgPhoto-3.5 {ImgPhotoConfigureModel: -data <png>} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    photo2 configure -data [photo1 data -format png -from 120 120 140 140]\n    list [image width photo2] [image height photo2]\n} -cleanup {\n    imageCleanup\n} -result {20 20}\ntest imgPhoto-3.6 {ImgPhotoConfigureModel: -data <default>} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    photo2 configure -data [photo1 data -from 80 90 100 110]\n    list [image width photo2] [image height photo2]\n} -cleanup {\n    imageCleanup\n} -result {20 20}\n\ntest imgPhoto-4.1 {ImgPhotoCmd procedure} -setup {\n    image create photo photo1\n} -body {\n    photo1\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 option ?arg ...?\"}\ntest imgPhoto-4.2 {ImgPhotoCmd procedure} -setup {\n    image create photo photo1\n} -body {\n    photo1 blah\n} -returnCodes error -cleanup {\n    image delete photo1\n} -match glob -result {bad option \"blah\": must be *}\ntest imgPhoto-4.3 {ImgPhotoCmd procedure: blank option} -setup {\n    image create photo photo1\n} -body {\n    photo1 blank\n    photo1 blank x\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {wrong # args: should be \"photo1 blank\"}\ntest imgPhoto-4.4 {ImgPhotoCmd procedure: cget option} -setup {\n    image create photo photo1\n} -body {\n    photo1 cget\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {wrong # args: should be \"photo1 cget option\"}\ntest imgPhoto-4.5 {ImgPhotoCmd procedure: cget option} -setup {\n    image create photo photo2 -width 25 -height 30\n} -body {\n    list [photo2 cget -width] [photo2 cget -height]\n} -cleanup {\n    image delete photo2\n} -result {25 30}\ntest imgPhoto-4.6 {ImgPhotoCmd procedure: configure option} -setup {\n    image create photo photo1\n} -body {\n    llength [photo1 configure]\n} -cleanup {\n    image delete photo1\n} -result 8\ntest imgPhoto-4.7 {ImgPhotoCmd procedure: configure option} -setup {\n    image create photo photo1\n} -body {\n    photo1 conf -palette 3/4/2\n    photo1 configure -palette\n} -cleanup {\n    image delete photo1\n} -result {-palette {} {} {} 3/4/2}\ntest imgPhoto-4.8 {ImgPhotoCmd procedure: configure option} -setup {\n    image create photo photo1\n} -body {\n    photo1 configure -blah\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {unknown option \"-blah\"}\ntest imgPhoto-4.9 {ImgPhotoCmd procedure: configure option} -setup {\n    image create photo photo1\n} -body {\n    photo1 configure -palette {} -gamma\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {value for \"-gamma\" missing}\ntest imgPhoto-4.10 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -width 25 -height 30\n} -body {\n    image create photo photo2 -file $teapotPhotoFile\n    photo1 configure -width 0 -height 0 -palette {} -gamma 1\n    photo1 copy photo2\n    list [image width photo1] [image height photo1] [photo1 get 100 100]\n} -cleanup {\n    image delete photo1 photo2\n} -result {256 256 {169 117 90}}\ntest imgPhoto-4.11 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n} -body {\n    photo1 copy\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 copy source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?\"}\ntest imgPhoto-4.12 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n} -body {\n    photo1 copy blah\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {image \"blah\" does not exist or is not a photo image}\ntest imgPhoto-4.13 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2\n} -body {\n    photo1 copy photo2 -blah\n} -returnCodes error -cleanup {\n    image delete photo1 photo2\n} -result {unrecognized option \"-blah\": must be -compositingrule, -from, -shrink, -subsample, -to, or -zoom}\ntest imgPhoto-4.14 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2\n} -body {\n    photo1 copy photo2 -from -to\n} -returnCodes error -cleanup {\n    image delete photo1 photo2\n} -result {the \"-from\" option requires one to four integer values}\ntest imgPhoto-4.15 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2\n    photo1 copy photo2 -from 0 70 60 120 -shrink\n    list [image width photo1] [image height photo1] [photo1 get 20 10]\n} -cleanup {\n    image delete photo1 photo2\n} -result {60 50 {215 154 120}}\ntest imgPhoto-4.16 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2 -from 60 120 0 70 -to 20 50\n    list [image width photo1] [image height photo1] [photo1 get 40 80]\n} -cleanup {\n    image delete photo1 photo2\n} -result {80 100 {19 92 192}}\ntest imgPhoto-4.17 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2 -from 0 120 60 70 -to 0 0 100 100\n    list [image width photo1] [image height photo1] [photo1 get 80 60]\n} -cleanup {\n    image delete photo1 photo2\n} -result {100 100 {215 154 120}}\ntest imgPhoto-4.18 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2 -from 60 70 0 120 -zoom 2\n    list [image width photo1] [image height photo1] [photo1 get 100 50]\n} -cleanup {\n    image delete photo1 photo2\n} -result {120 100 {169 99 47}}\ntest imgPhoto-4.19 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2 -from 0 70 60 120 -zoom 2\n    list [image width photo1] [image height photo1] [photo1 get 100 50]\n} -cleanup {\n    image delete photo1 photo2\n} -result {120 100 {169 99 47}}\ntest imgPhoto-4.20 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2 -from 20 20 200 180 -subsample 2 -shrink\n    list [image width photo1] [image height photo1] [photo1 get 50 30]\n} -cleanup {\n    image delete photo1 photo2\n} -result {90 80 {207 146 112}}\ntest imgPhoto-4.21 {ImgPhotoCmd procedure: copy option} -setup {\n    image create photo photo1\n    image create photo photo2 -file $teapotPhotoFile\n} -body {\n    photo1 copy photo2\n    set result [list [image width photo1] [image height photo1]]\n    photo1 conf -width 49 -height 51\n    lappend result [image width photo1] [image height photo1]\n    photo1 copy photo2\n    lappend result [image width photo1] [image height photo1]\n    photo1 copy photo2 -from 0 0 10 10 -shrink\n    lappend result [image width photo1] [image height photo1]\n    photo1 conf -width 0\n    photo1 copy photo2 -from 0 0 10 10 -shrink\n    lappend result [image width photo1] [image height photo1]\n    photo1 conf -height 0\n    photo1 copy photo2 -from 0 0 10 10 -shrink\n    lappend result [image width photo1] [image height photo1]\n} -cleanup {\n    image delete photo1 photo2\n} -result {256 256 49 51 49 51 49 51 10 51 10 10}\n# tests for <imageName> data: imgPhoto-4.\ntest imgPhoto-4.22 {ImgPhotoCmd procedure: get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $transpTeapotPhotoFile\n    list [photo1 get 100 100 -withalpha] \\\n\t[photo1 get 150 100 -withalpha] \\\n\t[photo1 get 100 150] [photo1 get 150 150]\n} -cleanup {\n    image delete photo1\n} -result {{175 71 0 162} {179 73 0 168} {14 8 0} {0 0 0}}\ntest imgPhoto-4.23 {ImgPhotoCmd procedure: get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 get 256 0\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {photo1 get: coordinates out of range}\ntest imgPhoto-4.24 {ImgPhotoCmd procedure: get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 get 0 -1\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {photo1 get: coordinates out of range}\ntest imgPhoto-4.25 {ImgPhotoCmd procedure: get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 get 0\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 get x y ?-withalpha?\"}\n# more test for image get: 4.101-4.102\ntest imgPhoto-4.26 {ImgPhotoCmd procedure: put option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 put data ?-option value ...?\"}\ntest imgPhoto-4.27 {ImgPhotoCmd procedure: put option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{white} {white white}}\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {invalid row # 1: all rows must have the same number of elements}\ntest imgPhoto-4.28 {ImgPhotoCmd procedure: put option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{blahgle}}\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {invalid color name \"blahgle\"}\ntest imgPhoto-4.29 {ImgPhotoCmd procedure: put option} -setup {\n    image create photo photo1\n} -body {\n    # SB: odd thing - this test passed with tk 8.6.6, even if the data\n    # is in the wrong position:\n    #photo1 put -to 10 10 20 20 {{white}}\n\n    # this is how it's supposed to be:\n    photo1 put {{white}} -to 10 10 20 20\n    photo1 get 19 19\n} -cleanup {\n    image delete photo1\n} -result {255 255 255}\n# more tests for image put: 4.90-4.100\ntest imgPhoto-4.30 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 read fileName ?-option value ...?\"}\ntest imgPhoto-4.31 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $teapotPhotoFile -zoom 2\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {unrecognized option \"-zoom\": must be -format, -from, -metadata, -shrink, or -to}\ntest imgPhoto-4.32 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    list [catch {photo1 read bogus} err] [string tolower $err]\n} -cleanup {\n    image delete photo1\n} -result {1 {couldn't open \"bogus\": no such file or directory}}\ntest imgPhoto-4.33 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $teapotPhotoFile -format bogus\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {image file format \"bogus\" is not supported}\ntest imgPhoto-4.34 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $README\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result [subst {couldn't recognize data in image file \"$README\"}]\ntest imgPhoto-4.35 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $teapotPhotoFile\n    list [image width photo1] [image height photo1] [photo1 get 120 120]\n} -cleanup {\n    image delete photo1\n} -result {256 256 {161 109 82}}\ntest imgPhoto-4.36 {ImgPhotoCmd procedure: read option} -setup {\n    image create photo photo1\n} -body {\n    photo1 read $teapotPhotoFile -from 0 70 60 120 -to 10 10 -shrink\n    list [image width photo1] [image height photo1] [photo1 get 29 19]\n} -cleanup {\n    image delete photo1\n} -result {70 60 {244 180 144}}\ntest imgPhoto-4.37 {ImgPhotoCmd procedure: redither option} -setup {\n    image create photo photo1\n} -body {\n    photo1 redither\n    photo1 redither x\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {wrong # args: should be \"photo1 redither\"}\ntest imgPhoto-4.38 {ImgPhotoCmd procedure: write option} -setup {\n    image create photo photo1\n} -body {\n    photo1 write\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 write fileName ?-option value ...?\"}\ntest imgPhoto-4.39 {ImgPhotoCmd procedure: write option} -setup {\n    image create photo photo1\n} -body {\n    photo1 write teapot.tmp -format bogus\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {image file format \"bogus\" is unknown}\n# more tests on \"imageName write\": imgPhoto-17.*\ntest imgPhoto-4.40 {ImgPhotoCmd procedure: transparency option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 transparency option ?arg ...?\"}\ntest imgPhoto-4.41 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 transparency get x y ?-option?\"}\ntest imgPhoto-4.42 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 transparency get x y ?-option?\"}\ntest imgPhoto-4.43 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 0 0 0 -alpha\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {wrong # args: should be \"photo1 transparency get x y ?-option?\"}\ntest imgPhoto-4.44 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get bogus 0\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest imgPhoto-4.45 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 0 bogus\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest imgPhoto-4.46 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white\n    photo1 transparency get 0 0\n} -cleanup {\n    image delete photo1\n} -result 0\ntest imgPhoto-4.47 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 1 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency get: coordinates out of range}\ntest imgPhoto-4.48 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get -1 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency get: coordinates out of range}\ntest imgPhoto-4.49 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 0 1\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency get: coordinates out of range}\ntest imgPhoto-4.50 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency get 0 -1\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency get: coordinates out of range}\ntest imgPhoto-4.51 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white\n    photo1 blank\n    photo1 transparency get 0 0\n} -cleanup {\n    image delete photo1\n} -result 1\n# more tests for transparency get: 4.65, 4.66, 4.76-4.81\ntest imgPhoto-4.52 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result \\\n    {wrong # args: should be \"photo1 transparency set x y newVal ?-option?\"}\ntest imgPhoto-4.53 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result \\\n    {wrong # args: should be \"photo1 transparency set x y newVal ?-option?\"}\ntest imgPhoto-4.54 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result \\\n    {wrong # args: should be \"photo1 transparency set x y newVal ?-option?\"}\ntest imgPhoto-4.55 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 0 0 0 -alpha\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result \\\n    {wrong # args: should be \"photo1 transparency set x y newVal ?-option?\"}\ntest imgPhoto-4.56 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set bogus 0 0\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest imgPhoto-4.57 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 bogus 0\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest imgPhoto-4.58 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n    photo1 put blue\n} -body {\n    photo1 transparency set 0 0 bogus\n} -cleanup {\n    image delete photo1\n} -returnCodes error -result {expected boolean value but got \"bogus\"}\ntest imgPhoto-4.59 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 1 0 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency set: coordinates out of range}\ntest imgPhoto-4.60 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set -1 0 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency set: coordinates out of range}\ntest imgPhoto-4.61 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 1 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency set: coordinates out of range}\ntest imgPhoto-4.62 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 -1 0\n} -returnCodes error -cleanup {\n    image delete photo1\n} -result {photo1 transparency set: coordinates out of range}\ntest imgPhoto-4.63 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white\n    photo1 transparency set 0 0 false\n    photo1 transparency get 0 0\n} -cleanup {\n    image delete photo1\n} -result 0\ntest imgPhoto-4.64 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white\n    photo1 transparency set 0 0 true\n    photo1 transparency get 0 0\n} -cleanup {\n    image delete photo1\n} -result 1\n# more tests for transparency set: 4.67, 4.68, 4.82-4.89\n# Now for some heftier testing, checking that setting and resetting of pixels'\n# transparency status doesn't \"leak\" with any one-off errors.\ntest imgPhoto-4.65 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 3 3\n    checkImgTrans photo1\n} -cleanup {\n    image delete photo1\n} -result {}\ntest imgPhoto-4.66 {ImgPhotoCmd procedure: transparency get option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 3 3\n    photo1 blank\n    checkImgTrans photo1\n} -result {0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2}\ntest imgPhoto-4.67 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 3 3\n    checkImgTransLoop photo1 {\n\tphoto1 put white -to 0 0 3 3\n\tphoto1 transparency set $x $y 1\n    } {\n\tphoto1 transparency set $x $y 0\n    }\n} -cleanup {\n    image delete photo1\n} -result {0,0:. 0,1:. 0,2:. 1,0:. 1,1:. 1,2:. 2,0:. 2,1:. 2,2:.}\ntest imgPhoto-4.68 {ImgPhotoCmd procedure: transparency set option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 3 3\n    checkImgTransLoop photo1 {\n\tphoto1 blank\n\tphoto1 transparency set $x $y 0\n    } {\n\tphoto1 transparency set $x $y 1\n    }\n} -cleanup {\n    image delete photo1\n} -result {0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,2 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 1,0 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,1 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,2 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 2,0 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,1 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,2: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2. 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2.}\ntest imgPhoto-4.69 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {\n    # Test the compositing rules for copying images\n    image create photo photo1 -width 3 -height 3\n    image create photo photo2 -width 2 -height 2\n} -body {\n    photo1 copy photo2 -to 1 1 -compositingrule\n} -cleanup {\n    image delete photo1 photo2\n} -returnCodes error -result {the \"-compositingrule\" option requires a value}\ntest imgPhoto-4.70 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {\n    # Test the compositing rules for copying images\n    image create photo photo1 -width 3 -height 3\n    image create photo photo2 -width 2 -height 2\n} -body {\n    photo1 copy photo2 -to 1 1 -compositingrule BAD\n} -returnCodes error -cleanup {\n    image delete photo1 photo2\n} -result {bad compositing rule \"BAD\": must be overlay or set}\ntest imgPhoto-4.71 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {\n    # Test the compositing rules for copying images\n    image create photo photo1 -width 3 -height 3\n    image create photo photo2 -width 2 -height 2\n} -body {\n    # Tests default compositing rule\n    photo1 blank\n    photo2 blank\n    photo1 put white -to 0 0 2 2\n    photo2 put white -to 0 0 2 2\n    photo2 transparency set 0 0 true\n    photo1 copy photo2 -to 1 1\n    checkImgTrans photo1\n} -cleanup {\n    image delete photo1 photo2\n} -result {0,2 2,0}\ntest imgPhoto-4.72 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {\n    # Test the compositing rules for copying images\n    image create photo photo1 -width 3 -height 3\n    image create photo photo2 -width 2 -height 2\n} -body {\n    photo1 blank\n    photo2 blank\n    photo1 put white -to 0 0 2 2\n    photo2 put white -to 0 0 2 2\n    photo2 transparency set 0 0 true\n    photo1 copy photo2 -to 1 1 -compositingrule overlay\n    checkImgTrans photo1\n} -cleanup {\n    image delete photo1 photo2\n} -result {0,2 2,0}\ntest imgPhoto-4.73 {ImgPhotoCmd procedure: copy with -compositingrule} -setup {\n    # Test the compositing rules for copying images\n    image create photo photo1 -width 3 -height 3\n    image create photo photo2 -width 2 -height 2\n} -body {\n    photo1 blank\n    photo2 blank\n    photo1 put white -to 0 0 2 2\n    photo2 put white -to 0 0 2 2\n    photo2 transparency set 0 0 true\n    photo1 copy photo2 -to 1 1 -compositingrule set\n    checkImgTrans photo1\n} -cleanup {\n    image delete photo1 photo2\n} -result {0,2 1,1 2,0}\ntest imgPhoto-4.74 {ImgPhotoCmd procedure: put option error handling} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{white}} -to 10 10 20 20 {{white}}\n} -cleanup {\n    image delete photo1\n} -returnCodes 1 -result {wrong # args: should be \"photo1 put data ?-option value ...?\"}\ntest imgPhoto-4.75 {<photo> read command: filename starting with '-'} -body {\n    file copy -force $teapotPhotoFile -teapotPhotoFile\n    image create photo photo1\n    photo1 read -teapotPhotoFile\n} -cleanup {\n    image delete photo1\n    file delete ./-teapotPhotoFile\n} -result {}\ntest imgPhoto-4.75.1 {ImgPhotoCmd procedure: copy to same image} -setup {\n    imageCleanup\n    image create photo photo1 -file $teapotPhotoFile\n} -body {\n    # non-regression test for bug [5239fd749b] - shall just not crash\n    photo1 copy photo1 -to 0 0 2000 1000\n    photo1 copy photo1 -subsample 2 2 -shrink\n} -cleanup {\n    imageCleanup\n} -result {}\ntest imgPhoto-4.76 {ImgPhotoCmd, transparency get: too many options} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 1 1\n    photo1 transparency get 0 0 -alpha -bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 transparency get x y ?-option?\"}\ntest imgPhoto-4.77 {ImgPhotoCmd, transparency get: invalid option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 1 1\n    photo1 transparency get 0 0 -bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {unrecognized option \"-bogus\": must be -alpha}\ntest imgPhoto-4.78 {ImgPhotoCmd, transparency get: normal use} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 1 1\n    set result [photo1 transparency get 0 0]\n    lappend result [photo1 transparency get 0 0 -alpha]\n} -cleanup {\n    imageCleanup\n} -result {0 255}\ntest imgPhoto-4.79 {ImgPhotoCmd, transparency get: no option} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n    set result {}\n} -body {\n    set pixelCoords {{156 239} {76 207} {153 213} {139 43} {75 112}}\n    foreach coord $pixelCoords {\n\tlappend result [photo1 transparency get {*}$coord]\n    }\n    set result\n} -cleanup {\n    imageCleanup\n} -result {0 1 0 0 0}\n# test imgPhoto-4.80: deleted (was transparency get: -boolean)\ntest imgPhoto-4.81 {ImgPhotoCmd, transparency get: -alpha} -setup {\n    image create photo photo1 -file $transpTeapotPhotoFile\n    set result {}\n} -body {\n    set pixelCoords {{156 239} {76 207} {153 213} {139 43} {75 112}}\n    foreach coord $pixelCoords {\n\tlappend result [photo1 transparency get {*}$coord -alpha]\n    }\n    set result\n} -cleanup {\n    imageCleanup\n} -result {255 0 1 254 206}\ntest imgPhoto-4.82 {ImgPhotoCmd, transparency set: too many opts} -setup {\n    image create photo photo1\n} -body {\n    photo1 transparency set 0 0 -alpha -bogus 1\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 transparency set x y newVal ?-option?\"}\ntest imgPhoto-4.83 {ImgPhotoCmd, transparency set: invalid opt} -setup {\n    image create photo photo1 -data black\n} -body {\n    photo1 transparency set 0 0 0 -bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {unrecognized option \"-bogus\": must be -alpha}\ntest imgPhoto-4.84 {ImgPhotoCmd, transparency set: invalid newVal} -setup {\n    image create photo photo1 -data white\n} -body {\n    photo1 transparency set 0 0 bogus -alpha\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest imgPhoto-4.85 {ImgPhotoCmd, transparency set: invalid newVal} -setup {\n    image create photo photo1 -data red\n} -body {\n    photo1 transparency set 0 0 -1 -alpha\n} -returnCodes error -result \\\n    {invalid alpha value \"-1\": must be integer between 0 and 255}\ntest imgPhoto-4.86 {ImgPhotoCmd, transparency set: invalid newVal} -setup {\n    image create photo photo1 -data green\n} -body {\n    photo1 transparency set 0 0 256 -alpha\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {invalid alpha value \"256\": must be integer between 0 and 255}\ntest imgPhoto-4.87 {ImgPhotoCmd, transparency set: no opt} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 2 1\n    photo1 transparency set 0 0 0\n    photo1 transparency set 1 0 1\n    list [photo1 transparency get 0 0 -alpha] \\\n\t[photo1 transparency get 1 0 -alpha]\n} -cleanup {\n    imageCleanup\n} -result {255 0}\n# deleted: test imgPhoto-4.88 {ImgPhotoCmd, transparency set: -boolean}\ntest imgPhoto-4.89 {ImgPhotoCmd, transparency set: -alpha} -setup {\n    image create photo photo1\n} -body {\n    photo1 put white -to 0 0 2 2\n    photo1 transparency set 0 0 0 -alpha\n    photo1 transparency set 1 0 1 -alpha\n    photo1 transparency set 0 1 254 -alpha\n    photo1 transparency set 1 1 255 -alpha\n    list [photo1 transparency get 0 0] [photo1 transparency get 1 0] \\\n\t[photo1 transparency get 0 1] [photo1 transparency get 1 1]\n} -cleanup {\n    imageCleanup\n} -result {1 0 0 0}\ntest imgPhoto-4.90 {ImgPhotoCmd put: existing but not allowed opt} -setup {\n    image create photo photo1\n} -body {\n    photo1 put yellow -from 0 0 1 1\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {unrecognized option \"-from\": must be -format, -metadata, or -to}\ntest imgPhoto-4.91 {ImgPhotoCmd put: invalid option} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{0 1 2 3}} -bogus x\n} -returnCodes error -result \\\n    {unrecognized option \"-bogus\": must be -format, -metadata, or -to}\ntest imgPhoto-4.92 {ImgPhotocmd put: missing data} -setup {\n    image create photo photo1\n} -body {\n    photo1 put -to 0 0\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 put data ?-option value ...?\"}\ntest imgPhoto-4.93 {ImgPhotoCmd put: data in ppm format} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    set imgdata [photo1 data -format ppm]\n    photo2 put $imgdata -format ppm\n    set result {}\n    if {[image width photo1] != [image width photo2] \\\n\t    || [image height photo1] != [image height photo2]} {\n\tlappend result [list [image width photo2] [image height photo2]]\n    } else {\n\tlappend result 1\n    }\n    foreach point {{206 125} {67 12} {13 46} {19 184}} {\n\tif {[photo1 get {*}$point] ne [photo2 get {*}$point]} {\n\t    lappend result [photo2 get {*}$point]\n\t} else {\n\t    lappend result 1\n\t}\n    }\n    set result\n} -cleanup {\n    imageCleanup\n} -result {1 1 1 1 1}\ntest imgPhoto-4.94 {ImgPhotoCmd put: unknown format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {no real data} -format bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image format \"bogus\" is not supported}\ntest imgPhoto-4.95 {ImgPhotoCmd put: default fmt, invalid data} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{red green blue} {red \" blue}}\n    #\"\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {unmatched open quote in list}\ntest imgPhoto-4.96 {ImgPhotoCmd put: \"default\" handler is selected} -setup {\n    image create photo photo1\n    image create photo photo2\n    set imgData {{{1 2 3 4} {5 6 7 8} {9 10 11 12}}\n\t{{13 14 15 15} {17 18 19 20} {21 22 23 24}}}\n} -body {\n    photo1 put $imgData\n    photo2 put $imgData -format default\n    set result {}\n    lappend result [list [image width photo1] [image height photo1]]\n    lappend result [list [image width photo2] [image height photo2]]\n    lappend result [string equal \\\n\t[photo1 data -format \"default -colorformat rgba\"] \\\n\t[photo2 data -format \"default -colorformat rgba\"]]\n    set result\n} -cleanup {\n    imageCleanup\n    unset result\n    unset imgData\n} -result {{3 2} {3 2} 1}\ntest imgPhoto-4.97 {ImgPhotoCmd put: image size} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{red green blue} {blue red green}}\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {3 2}\ntest imgPhoto-4.98 {ImgPhotoCmd put: -to with 2 coords} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{\"alice blue\" \"blanched almond\"}\n\t\t{\"deep sky blue\" \"ghost white\"}\n\t\t{#AABBCC #AABBCCDD}} -to 5 6\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {7 9}\ntest imgPhoto-4.99 {ImgPhotoCmd put: -to with 4 coords} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{#123 #456 #678} {#9AB #CDE #F01}} -to 1 2 20 21\n    set result {}\n    lappend result [photo1 get 19 20 -withalpha]\n    lappend result [string equal \\\n\t[photo1 data -from 1 2 4 4] [photo1 data -from 4 2 7 4]]\n    lappend result [string equal \\\n\t[photo1 data -from 10 12 13 14] [photo1 data -from 16 16 19 18]]\n    set result\n} -cleanup {\n    imageCleanup\n} -result {{17 34 51 255} 1 1}\ntest imgPhoto-4.100 {ImgPhotoCmd put: no changes on empty data} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{brown blue} {cyan coral}}\n    set imgData [photo1 data]\n    photo1 put {}\n    string equal $imgData [photo1 data]\n} -cleanup {\n    imageCleanup\n} -result 1\ntest imgPhoto-4.101 {ImgPhotoCmd get: too many args} -setup {\n    image create photo photo1\n} -body {\n    photo1 get 0 0 -withalpha bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 get x y ?-withalpha?\"}\ntest imgPhoto-4.102 {ImgPhotoCmd get: invalid option} -setup {\n    image create photo photo1\n} -body {\n    photo1 get 0 0 -bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {unrecognized option \"-bogus\": must be -withalpha}\ntest imgPhoto-4.103 {ImgPhotoCmd data: accepted opts} -setup {\n    image create photo photo1 -data black\n} -body {\n    photo1 data -format default -from 0 0 -grayscale -background blue\n} -cleanup {\n    imageCleanup\n} -result {{#000000}}\ntest imgPhoto-4.104 {ImgPhotoCmd data: existing but not accepted opt} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -to\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n{unrecognized option \"-to\": must be -background, -format, -from, -grayscale, or -metadata}\ntest imgPhoto-4.105 {ImgPhotoCmd data: invalid option} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n{unrecognized option \"-bogus\": must be -background, -format, -from, -grayscale, or -metadata}\ntest imgPhoto-4.106 {ImgPhotoCmd data: extra arg before options} -setup {\n    image create photo photo1\n} -body {\n    photo1 data bogus -grayscale\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 data ?-option value ...?\"}\ntest imgPhoto-4.107 {ImgPhotoCmd data: extra arg after options} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format default bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {wrong # args: should be \"photo1 data ?-option value ...?\"}\ntest imgPhoto-4.108 {ImgPhotoCmd data: invalid -from coords #1} -setup {\n    image create photo photo1 -data blue\n} -body {\n    photo1 data -from 2 0\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {coordinates for -from option extend outside image}\ntest imgPhoto-4.109 {ImgPhotoCmd data: invalid -from coords #2} -setup {\n    image create photo photo1 -data blue\n} -body {\n    photo1 data -from 0 2\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {coordinates for -from option extend outside image}\ntest imgPhoto-4.110 {ImgPhotoCmd data: invalid -from coords #3} -setup {\n    image create photo photo1 -data blue\n} -body {\n    photo1 data -from 0 0 2 1\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {coordinates for -from option extend outside image}\ntest imgPhoto-4.111 {ImgPhotoCmd data: invalid -from coords #4} -setup {\n    image create photo photo1 -data blue\n} -body {\n    photo1 data -from 0 0 1 2\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result \\\n    {coordinates for -from option extend outside image}\ntest imgPhoto-4.112 {ImgPhotoCmd data: -from with 2 coords} -setup {\n    image create photo photo1 -data {\n\t{black black black black black}\n\t{white white white white white}\n\t{green green green green green}}\n} -body {\n    set imgData [photo1 data -from 2 1]\n    list [llength [lindex $imgData 0]] [llength $imgData]\n} -cleanup {\n    imageCleanup\n    unset imgData\n} -result {3 2}\ntest imgPhoto-4.113 {ImgPhotoCmd data: default is rgb format} -setup {\n    image create photo photo1 -data red\n} -body {\n    photo1 data\n} -cleanup {\n    imageCleanup\n} -result {{#ff0000}}\ntest imgPhoto-4.114 {ImgPhotoCmd data: unknown format} -setup {\n    image create photo photo1\n} -body {\n    photo1 data -format bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image string format \"bogus\" is unknown}\ntest imgPhoto-4.115 {ImgPhotoCmd data: rgb colorformat} -setup {\n    image create photo photo1 -data {{red#a green#b} {blue#c white}}\n} -body {\n    photo1 data -format {default -colorformat rgb}\n} -result {{#ff0000 #008000} {#0000ff #ffffff}}\ntest imgPhoto-4.116 {ImgPhotoCmd data: rgba colorformat} -setup {\n    image create photo photo1 -data {{red green} {blue white}}\n} -body {\n    photo1 data -format {default -colorformat rgba}\n} -result {{#ff0000ff #008000ff} {#0000ffff #ffffffff}}\ntest imgPhoto-4.117 {ImgPhotoCmd data: list colorformat} -setup {\n    image create photo photo1 -data {{red#a green} {blue#c white#d}}\n} -body {\n    photo1 data -format {default -colorformat list}\n} -result {{{255 0 0 170} {0 128 0 255}} {{0 0 255 204} {255 255 255 221}}}\n# This testcase fails with Tcl < 8.6.7, due to [25842c]\ntest imgPhoto-4.118 {ImgPhotoCmd data: using data for new image\n    results in same image as orignial } -setup {\n    image create photo teapot -file $teapotPhotoFile\n    teapot copy teapot -from 50 60 70 80 -shrink\n    image create photo teapotTransp -file $transpTeapotPhotoFile\n    teapotTransp copy teapotTransp -from 100 110 120 130 -shrink\n    image create photo photo1\n} -body {\n    set result {}\n    # We don't test gif here, as there seems to be a problem with\n    # <imgName> data and gif format (\"too many colors\", probably a bug)\n    foreach fmt {ppm png {default -colorformat rgba} \\\n\t    {default -colorformat list}} {\n\tset imgData [teapotTransp data -format $fmt]\n\tphoto1 blank\n\tphoto1 put $imgData\n\tif { ! [string equal [photo1 data] [teapotTransp data]]} {\n\t    lappend result $fmt\n\t}\n    }\n    set imgData [teapot data -format default]\n    photo1 blank\n    photo1 put $imgData\n    if { ! [string equal [photo1 data] [teapot data]]} {\n\tlappend result default\n    }\n    set result\n} -cleanup {\n    unset imgData\n    unset result\n    imageCleanup\n} -result {}\n\ntest imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -setup {\n    destroy .c\n    pack [canvas .c]\n    imageCleanup\n} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    .c create image 0 0 -image photo1 -tags photo1.1\n    .c create image 256 0 -image photo1 -tags photo1.2\n    .c create image 0 256 -image photo1 -tags photo1.3\n    update\n    .c delete i1.1\n    photo1 configure -width 1\n    update\n    .c delete i1.2\n    photo1 configure -height 1\n    update\n    image delete photo1\n} -cleanup {\n    destroy .c\n} -result {}\n\ntest imgPhoto-6.1 {ImgPhotoDisplay procedure, blank display} -setup {\n    destroy .c\n    pack [canvas .c]\n    imageCleanup\n} -body {\n    image create photo photo1 -width 10 -height 10\n    photo1 blank\n    .c create image 10 10 -image photo1\n    update\n} -cleanup {\n    destroy .c\n    image delete photo1\n} -result {}\n\ntest imgPhoto-7.1 {ImgPhotoFree procedure, resource freeing} -setup {\n    destroy .c\n    pack [canvas .c]\n    imageCleanup\n} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    .c create image 0 0 -image photo1 -anchor nw\n    update\n    .c delete all\n    image delete photo1\n} -cleanup {\n    destroy .c\n}  -result {}\ntest imgPhoto-7.2 {ImgPhotoFree procedures, unlinking} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    pack [canvas .c]\n    .c create image 10 10 -image photo1 -anchor nw\n    button .b1 -image photo1\n    button .b2 -image photo1\n    button .b3 -image photo1\n    pack .b1 .b2 .b3\n    update\n    destroy .b2\n    update\n    destroy .b3\n    update\n    destroy .b1\n    update\n    .c delete all\n} -cleanup {\n    destroy .c\n    image delete photo1\n} -result {}\ntest imgPhoto-7.3 {ImgPhotoFree procedures, multiple visuals} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create photo photo1 -file $teapotPhotoFile\n    button .b1 -image photo1\n    frame .f -visual best\n    button .f.b2 -image photo1\n    pack .f.b2\n    pack .b1 .f\n    update\n    destroy .b1\n    update\n    .f.b2 configure -image {}\n    update\n    destroy .f\n    image delete photo1\n} -result {}\n\ntest imgPhoto-8.1 {ImgPhotoDelete procedure} -body {\n    image create photo photo2 -file $teapotPhotoFile\n    image delete photo2\n} -result {}\ntest imgPhoto-8.2 {ImgPhotoDelete procedure} -setup {\n    set x {}\n} -body {\n    image create photo photo2 -file $teapotPhotoFile\n    rename photo2 newphoto2\n    lappend x [info command photo2] [info command new*] [newphoto2 cget -file]\n    image delete photo2\n    lappend x [info command new*]\n} -result [list {} newphoto2 $teapotPhotoFile {}]\ntest imgPhoto-8.3 {ImgPhotoDelete procedure, name cleanup} -body {\n    image create photo photo1\n    image create photo photo2 -width 10 -height 10\n    image delete photo2\n    photo1 copy photo2\n} -returnCodes error -cleanup {\n    imageCleanup\n} -result {image \"photo2\" does not exist or is not a photo image}\n\ntest imgPhoto-9.1 {ImgPhotoCmdDeletedProc procedure} -body {\n    image create photo photo2 -file $teapotPhotoFile\n    rename photo2 {}\n    list [expr {\"photo2\" in [imageNames]}] [catch {photo2 foo} msg] $msg\n} -result {0 1 {invalid command name \"photo2\"}}\n\ntest imgPhoto-10.1 {Tk_ImgPhotoPutBlock procedure} -setup {\n    imageCleanup\n} -body {\n    image create photo photo1\n    photo1 put \"{#ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000}\" -to 0 0\n    photo1 put \"{#00ff00 #00ff00}\" -to 2 0\n    list [photo1 get 2 0] [photo1 get 3 0] [photo1 get 4 0]\n} -result {{0 255 0} {0 255 0} {255 0 0}}\ntest imgPhoto-10.2 {Tk_ImgPhotoPutBlock, same source and dest img} -setup {\n    imageCleanup\n} -body {\n    # Test for bug e4336bef5d\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2 -file $teapotPhotoFile\n    photo2 copy photo1 -to 1 2\n    photo1 copy photo1 -to 1 2\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    imageCleanup\n} -result 1\ntest imgPhoto-10.3 {Tk_ImgPhotoPutBlock, same source and dest img} -setup {\n    imageCleanup\n} -body {\n    # Test for bug e4336bef5d\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2 -file $teapotPhotoFile\n    photo2 copy photo1 -from 2 1 -to 4 5 300 300\n    photo1 copy photo1 -from 2 1 -to 4 5 300 300\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    imageCleanup\n} -result 1\ntest imgPhoto-10.4 {Tk_ImgPhotoPutBlock, empty image} -setup {\n    imageCleanup\n} -body {\n    image create photo photo1\n    photo1 copy photo1 -to 0 5 10 20\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {0 0}\ntest imgPhoto-11.1 {Tk_FindPhoto} -setup {\n    imageCleanup\n} -body {\n    image create bitmap i1\n    image create photo photo1\n    photo1 copy i1\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image \"i1\" does not exist or is not a photo image}\n\ntest imgPhoto-12.1 {Tk_PhotoPutZoomedBlock} -body {\n    image create photo p3 -file $teapotPhotoFile\n    set result [list [p3 get 50 50] [p3 get 100 100]]\n    p3 copy p3 -zoom 2\n    lappend result [image width p3] [image height p3] [p3 get 100 100]\n} -cleanup {\n    image delete p3\n} -result {{19 92 192} {169 117 90} 512 512 {19 92 192}}\ntest imgPhoto-12.2 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -setup {\n    imageCleanup\n} -body {\n    # Test for bug e4336bef5d\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2 -file $teapotPhotoFile\n    photo2 copy photo1 -to 0 1 200 200 -zoom 2 3\n    photo1 copy photo1 -to 0 1 200 200 -zoom 2 3\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    imageCleanup\n} -result 1\ntest imgPhoto-12.3 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -setup {\n    imageCleanup\n} -body {\n    # Test for bug e4336bef5d\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2 -file $teapotPhotoFile\n    photo2 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2\n    photo1 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    imageCleanup\n} -result 1\ntest imgPhoto-12.4 {Tk_ImgPhotoPutZoomedBlock, empty image} -setup {\n    imageCleanup\n} -body {\n    image create photo photo1\n    photo1 copy photo1 -to 0 5 10 20\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {0 0}\ntest imgPhoto-12.5 {Tk_ImgPhotoPutZoomedBlock, copy from area outside the image, bug [a0241c0e25]} -setup {\n    imageCleanup\n} -body {\n    image create photo photo1 -width 20 -height 20\n    image create photo photo2 -width 9 -height 10\n    # next line used to loop for a very long time; if the bug is present\n    # the CI runner will time out, leading to test suite failure\n    photo2 copy photo1 -to 0 5 3 8 -from 21 0\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {coordinates for -from option extend outside source image}\n\ntest imgPhoto-13.1 {check separation of images in different interpreters} -setup {\n    imageCleanup\n    set data {\n\tR0lGODlhQgBkAPUAANbWxs7Wxs7OxsbOxsbGxsbGvb3Gvca9vcDAwL21vbW1vbW1tbWtta2t\n\tta2ltaWltaWlraWctaWcrZycrZyUrZSUrZSMrZSMpYyMrYyMpYyEpYSEpYR7pYR7nHp7pYRz\n\tpYRynHtzpXtznHtrnHNrnHNjnGtjnGtjlGtalGNalGNSlGNSjFpSlFpKlFpKjFJKjFJCjFI5\n\tjEo5jEo5hEoxhEIxhDkphDkhhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAQgBkAAAG\n\t/kCEcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P\n\t7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmOBZxXnAQEnKIIBUQJCguoDKkIBgWhpUev\n\tCA4TDwgEUpwKERUaHCIiJCQjIiEUQhwqKiwqLjDQMCwoIha3oUO5ESMuLSwtLSIMsU4Tzi4o\n\tJBwWFA8ODQoMCkIMq6sNDQ4UFhwlzC4qSGhgkMvCsAoM6E0oAWMCOSUFGrgQcauAgAACSqGa\n\tl6SAK1EaJXBA0SIDBw0KBiCg8EtEBgEWYCxoooAigFwIJGgQYQIF/goTAjk6sXhxAwwFnHRO\n\tmEmAwoQAIUo8lCWhRgoOElJVkJBQFCwhCRqkYlUE1QMKHEywoBCrQaeIMCgQeOCi3AkYMmRI\n\tS5EuxEkN7OApkGDhF4fDxoSVMAFUBAWkRxI0a+XghVAkBSqMsFCBwj4OI0igSKGCdLN0wYKd\n\tzGDBwUYhn6YOKUCioQECGk7INpIArQgUKkr87TyhAYIDQxQgLkYsRIcQIDjcgi2Lw8RYKaAz\n\tMXCgAs8UJrZGmOA5AkeQBlqRKsIpvYMQDx4S4NCCxIJSKJpFYMIgnPlSF2ygAQWuCUHAAp6x\n\tE4EEE5BXQQUWYLABBySoAIMLHBSBWwso/jxwIAoyzMAWEw3AEEJCt6nUwAQagCDCYcCQwJcK\n\t6QD3DDQxwNDCCSg9NIAGKpwwgQAOtDADDBbsdkQDIPhkwosDPgDPAg1EAME++1jTnhAKdAnb\n\tVAR04EIJFAhwwQs0sBDfE7cZwEAE++yU2joOtDcKE7GUcoIKH6RSmwwnQCZFKAo8cE2es7my\n\tHnuxKTDgAA6owEEBjoL3wqRUNDBCCnyRYMFMRSDoWYPvyBPPA738lt1KKTxgpjolrDDiFAWU\n\tcAMKE+CipAMRZMDTCSSUQMIJPQHLwWOcrDKBCBpokAIJgmYqQgosxIAOCS8iJEQD7HR2QbMh\n\tWCCEK7Ck90Cz/oAFu+YVigpTwTsLyJOcBJ6N6plxRihA3E4cOKTkFCU6FMoAA7wiygAZgURA\n\tekYsEJYFGTSATRccQEMjti8eZsEFFuA7z2WkEJAAl7iEQekEhQHGzgQR4INUKLB8pYAFJaQA\n\tKhleKdwAByEkFswHIoxQQn4AcYBvGRosisDICCjQAIMJGnZYBsUd4JEZBIhQwgPzKFwAwggL\n\tIHbOQzCtxZ1NL0BlKmmhIOwwHGTg2YMUEBdtKzBfbQWlhMHoHIXBnvABBGE9UMKNMKhgQgnG\n\tnNQO0wVQoI4FEohFyr9GzDIYaaPxxWy0rCjKQJUMQvxBaMOgNMQChcU4DAkZ6PoV/hIUoP4i\n\tZ7g/YHZHIPXeyWyONgsaCi4AOoLjXP8uhAAvPpCQ2Akr38UpXW60Ij8yPkMmwwj8KAI8QWtQ\n\t+eXSixEb37WhcHQBERz2rdZ8leCBBcXNY3XevQ8VG/6+F5CACDYgATlmYYD27aRmLngBNADC\n\tGGxxQEAWUJDzqpcctc2DARN4kNRgtJxhnKAFV0kIEhYAJ34IQwUhqkENYFCCE5BmGf9wwWmA\n\t5UGgXAAVtfCFMIgRLMbFLQIPYFACcMI7TjQoH2eJQIs2poEMYMAp5XGAvFrBCYS9ImzQG1vT\n\tarGTEQhIhE7QjLA+MKDOxClGwuoJtWi0uBIUIxjDSE2wQ4iHl7ywQDjGwZws/NcAlgBjaKQJ\n\tJDVuoQBeUeACoFkMcFqgQL1IgxpRSsjsqHA/gy0tHvmAx2z2BxIupaJrnVxCEAAAOw==\n    }\n    interp create x1\n    interp create x2\n    x1 eval {load {} Tk}\n    x2 eval {load {} Tk}\n} -body {\n    x1 eval [list image create photo T1_data -data $data]\n    x2 eval [list image create photo T1_data -data $data]\n} -cleanup {\n    interp delete x1\n    interp delete x2\n} -result T1_data\n\ntest imgPhoto-14.1 {GIF writes work correctly} -setup {\n    set data {\n\tR0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM\n\thASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/\n\tAP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD\n\thxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN\n\tmzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC\n\tBUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J\n\tqlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn\n\tuqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0\n\thciva9/Ovbv37+BzBgEEADs=\n    }\n    set tmpfilename [makeFile {} imgPhoto-14.1.gif]\n    removeFile $tmpfilename\n} -body {\n    image create photo photo1 -data $data\n    photo1 write $tmpfilename -format gif\n    image create photo photo2 -file $tmpfilename\n    string equal [photo1 data] [photo2 data]\n} -cleanup {\n    catch {image delete photo1 photo2}\n    catch {file delete -force $tmpfilename}\n} -result 1\ntest imgPhoto-14.2 {GIF -index handler buffer sizing} -setup {\n    set data {\n\tR0lGODlhIAAgAKEAAPkOSQsi7////////yH/C05FVFNDQVBFMi4wAwEAAAAh\n\t+QQJMgAAACwGAAYAFAAUAAACEYyPqcvtD6OctNqLs968+68VACH5BAkyAAEA\n\tLAMAAwAaABoAAAI0jH+gq+gfmFzQzUsr3gBybn1gIm5kaUaoubbuC8fyTNel\n\tOhv1CSO533u8KrgbUfc5Ci/EAgA7\n    }\n} -body {\n    # Bug 1458234 makes this crash when trying to access buffers of the wrong\n    # size, caused when the initial frame is not the largest frame.\n    set i [image create photo]\n    $i configure -data $data -format {gif -index 2}\n} -cleanup {\n    image delete $i\n} -returnCodes error -result {no image data for this index}\ntest imgPhoto-14.3 {GIF -index interleaving and small frames} -body {\n    # Interleaved GIFs used to crash us when a smaller subsequent frame was\n    # accessed.\n    set i [image create photo]\n    $i configure -format {GIF -index 1} -data {\n\tR0lGODdhAQAFAPAAAP8AAAAAACwAAAAAAQAFAEACAoRdACwAAAAAAQAEAEACAoRRADs=\n    }\n} -cleanup {\n    image delete $i\n}\ntest imgPhoto-14.4 {GIF buffer overflow} -setup {\n    set data {\n\tR0lGODlhCgAKAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/\n\tAP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBm\n\tmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/\n\tAAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMz\n\tmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPM\n\tADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYA\n\tmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZ\n\tAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/\n\tmWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lm\n\tAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnM\n\tmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wz\n\tAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZ\n\tmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8A\n\tAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9m\n\tmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////\n\tAP//M///Zv//mf//zP///yH5BAEAABAALAAAAAAKAAoAABUSAAD/HEiwoMGD\n\tCBMqXMiwYcKAADs=\n    }\n} -body {\n    # This crashes Tk up to 8.4.17 and 8.5.0\n    set i [image create photo]\n    $i configure -data $data\n} -cleanup {\n    image delete $i\n} -returnCodes error -result {malformed image}\ntest imgPhoto-14.5 {Bug [fbaed1f66b] - GIF decoder with deferred clear code} -setup {\n    set fileName [file join [file dirname [info script]] deferredClearCode.gif]\n} -body {\n    # This erroneously produced \"malformed image\" error.\n    # The animated GIF \"deferredClearCode.gif\" has two frames, and calling for -index 2\n    # simply is an easy way to trigger the problem of improper management of a deferred\n    # clear code. The effect was that the GIF decoder bailed out before the end of the\n    # image reading, and produced the inappropriate \"malformed image error\".\n    image create photo -file $fileName -format \"gif -index 2\"\n} -returnCodes error -result {no image data for this index}\n\ntest imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup {\n    set data {\n\tR0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM\n\thASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/\n\tAP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD\n\thxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN\n\tmzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC\n\tBUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J\n\tqlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn\n\tuqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0\n\thciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7\n    }\n} -body {\n    image create photo photo1 -data $data -format \"GIF -index 1\"\n} -cleanup {\n    catch {image delete photo1}\n} -result photo1\n\ntest imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {\n    nonPortable\n} -body {\n    # This is not portable to very large machines with more than around 3GB of\n    # free memory available...\n    image create photo -width 32000 -height 32000\n} -returnCodes error -result {not enough free memory for image buffer}\n\ntest imgPhoto-16.1 {copying to self doesn't access freed memory} -setup {\n    set i [image create photo]\n} -body {\n    # Bug 877950 makes this crash when trying to copy out of a deallocated\n    # area.\n    $i put red -to 0 0 1000 1000\n    $i copy $i -from 0 0 1000 1000 -to 500 0\n} -cleanup {\n    image delete $i\n} -result {}\n\n# Check that we can guess our supported output formats [Bug 2983824]\ntest imgPhoto-17.1 {photo write: format guessing from filename} -setup {\n    set i [image create photo -width 3 -height 3]\n} -body {\n    set f [makeFile {} test.png]\n    $i write $f\n    set fd [open $f]\n    seek $fd 1\n    read $fd 3\n} -cleanup {\n    catch {close $fd}\n    image delete $i\n    catch {removeFile $f}\n} -result PNG\ntest imgPhoto-17.2 {photo write: format guessing from filename} -setup {\n    set i [image create photo -width 3 -height 3]\n} -body {\n    set f [makeFile {} test.gif]\n    $i write $f\n    set fd [open $f]\n    read $fd 3\n} -cleanup {\n    catch {close $fd}\n    image delete $i\n    catch {removeFile $f}\n} -result GIF\ntest imgPhoto-17.3 {photo write: format guessing from filename} -setup {\n    set i [image create photo -width 3 -height 3]\n} -body {\n    set f [makeFile {} test.ppm]\n    $i write $f\n    set fd [open $f]\n    read $fd 3\n} -cleanup {\n    catch {close $fd}\n    image delete $i\n    catch {removeFile $f}\n} -result \"P6\\n\"\ntest imgPhoto-17.4 {photo write: default format not supported} -setup {\n    image create photo photo1 -data {{blue blue} {red red} {green green}}\n    set f [makeFile {} test.txt]\n} -body {\n    photo1 write $f -format default\n} -cleanup {\n    imageCleanup\n    catch {removeFile $f}\n    unset f\n} -returnCodes error -result \\\n    {image file format \"default\" has no file writing capability}\ntest imgPhoto-17.5 {photo write: file with extension .default} -setup {\n    image create photo photo1 -data {{black}}\n    set f [makeFile {} test.default]\n} -body {\n    photo1 write $f\n} -cleanup {\n    imageCleanup\n    catch {removeFile $f}\n    unset f\n} -returnCodes error -result \\\n    {image file format \"default\" has no file writing capability}\n\ntest imgPhoto-18.1 {MatchFileFormat: \"default\" format not supported} -setup {\n    image create photo photo1\n    set f [makeFile {} test.txt]\n} -body {\n    photo1 read $f -format default\n} -cleanup {\n    imageCleanup\n    catch {removeFile $f}\n    unset f\n} -returnCodes error -result {-file option isn't supported for default images}\n\ntest imgPhoto-19.1 {MatchStringFormat: with \"-format default\"} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {{red blue red} {yellow green yellow}} -format default\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {3 2}\ntest imgPhoto-19.2 {MatchStringFormat: without -format option,\n\tdefault fmt} -body {\n    image create photo photo1\n    photo1 put {{red} {green}}\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    imageCleanup\n} -result {1 2}\ntest imgPhoto-19.3 {MatchStringFormat: \"-format ppm\"} -setup {\n    image create photo photo1\n    image create photo photo2\n    photo2 put {cyan cyan}\n    set imgData [photo2 data -format ppm]\n} -body {\n    photo1 put $imgData -format ppm\n    list [image width photo1] [image height photo1]\n} -cleanup {\n    unset imgData\n    imageCleanup\n} -result {1 2}\ntest imgPhoto-19.4 {MatchStringFormat: ppm fmt, without opt} -setup {\n    image create photo photo1 -file $teapotPhotoFile\n    image create photo photo2\n} -body {\n    set imgData [photo1 data -format ppm]\n    photo2 put $imgData\n    list [image width photo2] [image height photo2]\n} -cleanup {\n    imageCleanup\n    unset imgData\n} -result {256 256}\ntest imgPhoto-19.5 {MatchStirngFormat: unknown -format} -setup {\n    image create photo photo1\n} -body {\n    photo1 put {} -format bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {image format \"bogus\" is not supported}\ntest imgPhoto-19.6 {MatchStringFormat: invalid data for default} -setup {\n    image create photo photo1\n} -body {\n    photo1 put bogus\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"bogus\"}\ntest imgPhoto-19.7 {MatchStringFormat: invalid data for default} -setup {\n    image create photo photo1\n} -body {\n    photo1 put bogus -format dEFault\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {invalid color name \"bogus\"}\ntest imgPhoto-19.8 {MatchStirngFormat: invalid data for gif} -setup {\n    image create photo photo1\n} -body {\n    photo1 put bogus -format giF\n} -cleanup {\n    imageCleanup\n} -returnCodes error -result {couldn't recognize image data}\n\n# Reject corrupted or truncated image [Bug b601ce3ab1].\n# WARNING - tests 20.1-20.9 will cause a segfault on 8.5.19 and lower,\n#           and on 8.6.6 and lower.\ntest imgPhoto-20.1 {Reject corrupted GIF (binary string)} -setup {\n    set data [binary decode base64 {\n\tR0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV\n\t5qpraXIvM1JlNyAgOw==\n    }]\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.2 {Reject corrupted GIF (base 64 string)} -setup {\n    set data {\n\tR0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV\n\t5qpraXIvM1JlNyAgOw==\n    }\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.3 {Reject corrupted GIF (file)} -setup {\n    set fileName [file join [file dirname [info script]] corruptMangled.gif]\n} -body {\n    image create photo gif1 -file $fileName\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.4 {Reject truncated GIF (binary string)} -setup {\n    set data [binary decode base64 {\n\tR0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=\n    }]\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map}\ntest imgPhoto-20.5 {Reject truncated GIF (base 64 string)} -setup {\n    set data {\n\tR0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=\n    }\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map}\ntest imgPhoto-20.6 {Reject truncated GIF (file)} -setup {\n    set fileName [file join [file dirname [info script]] corruptTruncated.gif]\n} -body {\n    image create photo gif1 -file $fileName\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map}\ntest imgPhoto-20.6.1 {Reject truncated GIF in Colormap - ticket 865af0148c - file} -setup {\n    set fileName [file join [file dirname [info script]] corruptTruncatedColormap.gif]\n} -body {\n    image create photo gif1 -file $fileName\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {GIF file truncated}\ntest imgPhoto-20.6.2 {Reject truncated GIF in Colormap - ticket 865af0148c - data} -setup {\n    set fileName [file join [file dirname [info script]] corruptTruncatedColormap.gif]\n    set h [open $fileName rb]\n    set d [read $h]\n    close $h\n} -body {\n    image create photo gif1 -data $d\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {GIF file truncated}\ntest imgPhoto-20.7 {Reject corrupted GIF (> 4Gb) (binary string)} -constraints {\n    nonPortable\n} -setup {\n    # About the non portability constraint of this test: see ticket [cc42cc18a5]\n    # If there is insufficient memory, the error message\n    # {not enough free memory for image buffer} should be returned.\n    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.\n    set data [binary decode base64 {\n\tR0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe\n\tLrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==\n    }]\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.8 {Reject corrupted GIF (> 4Gb) (base 64 string)} -constraints {\n    nonPortable\n} -setup {\n    # About the non portability constraint of this test: see ticket [cc42cc18a5]\n    # If there is insufficient memory, the error message\n    # {not enough free memory for image buffer} should be returned.\n    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.\n    set data {\n\tR0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe\n\tLrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==\n    }\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.9 {Reject corrupted GIF (> 4Gb) (file)} -constraints {\n    nonPortable\n} -setup {\n    # About the non portability constraint of this test: see ticket [cc42cc18a5]\n    # If there is insufficient memory, the error message\n    # {not enough free memory for image buffer} should be returned.\n    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.\n    set fileName [file join [file dirname [info script]] corruptMangled4G.gif]\n} -body {\n    image create photo gif1 -file $fileName\n} -cleanup {\n    catch {image delete gif1}\n} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp\ntest imgPhoto-20.10 {Valid GIF (binary string)} -setup {\n    # Test the binary string reader with a valid GIF.\n    # This is not tested elsewhere.\n    # Tests 20.11, 20.12, with matching data, are included for completeness.\n    set data [binary decode base64 {\n\tR0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA\n\tAAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=\n    }]\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -result gif1\ntest imgPhoto-20.11 {Valid GIF (base 64 string)} -setup {\n    set data {\n\tR0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA\n\tAAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=\n    }\n} -body {\n    image create photo gif1 -data $data\n} -cleanup {\n    catch {image delete gif1}\n} -result gif1\ntest imgPhoto-20.12 {Valid GIF (file)} -setup {\n    set fileName [file join [file dirname [info script]] red.gif]\n} -body {\n    image create photo gif1 -file $fileName\n} -cleanup {\n    catch {image delete gif1}\n} -result gif1\n\n# imgPhoto-21.x : Tk_PhotoGetMetadata\n\ntest imgPhoto-21.1 {option -metadata, get configure list} -setup {\n    image create photo photo1 -metadata {dpi 100}\n} -body {\n    photo1 configure -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {-metadata {} {} {} {dpi 100}}\n\ntest imgPhoto-21.2 {option -metadata, get value} -setup {\n    image create photo photo1 -metadata {dpi 100}\n} -body {\n    photo1 cget -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {dpi 100}\n\ntest imgPhoto-21.3 {option -metadata, get default value} -setup {\n    image create photo photo1\n} -body {\n    photo1 cget -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {}\n\ntest imgPhoto-21.4 {bug daa10097: only 3 metadata list items on configure} -setup {\n    image create photo photo1\n} -body {\n    set a {}\n    foreach line [photo1 configure] {\n\tif {[lindex $line 0] eq {-metadata}} {\n\t    set a $line\n\t}\n    }\n    set a\n} -cleanup {\n    catch {image delete photo1}\n} -result {-metadata {} {} {} {}}\n\n\n# imgPhoto-22.x : Tk_PhotoSetMetadata\n\ntest imgPhoto-22.1 {option -metadata, set value} -setup {\n    image create photo photo1\n} -body {\n    photo1 configure -metadata {dpi 100}\n    photo1 cget -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {dpi 100}\n\ntest imgPhoto-22.2 {option -metadata, change value} -setup {\n    image create photo photo1 -metadata {dpi 200}\n} -body {\n    photo1 configure -metadata {dpi 100}\n    photo1 cget -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {dpi 100}\n\ntest imgPhoto-22.3 {option -metadata, clear value} -setup {\n    image create photo photo1 -metadata {dpi 200}\n} -body {\n    photo1 configure -metadata {}\n    photo1 cget -metadata\n} -cleanup {\n    catch {image delete photo1}\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests imgPhoto-23.* : GIF images with metadata\n#\n\n# The following gif core data is used by the following data.\n# N.B. this is the same image as test imgPhoto-18.10\n\n# size 16x16, global color table size: 8\nset gifstart \"GIF89a\\x10\\x00\\x10\\x00\\xc2\\x07\\x00\"\n# color table\nappend gifstart \"\\x00\\x00\\x00\\x33\\x33\\xff\\xff\\x33\\x33\\xff\\x33\\xff\\x33\\xff\\x33\\x33\\xff\\xff\\xff\\xff\\x33\\xff\\xff\\xff\"\n# Graphic control extension: Transparent color index: 7 (not needed here)\n# append gifdata \"\\x21\\xf9\\x04\\x01\\x0a\\x00\\x07\\x00\"\n# Image descriptor: 16x16, no local color table\nset gifdata \"\\x2c\\x00\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\x00\"\n# Image data\nappend gifdata \"\\x03\\x21\\x78\\xba\\xdc\\x2d\\x30\\x42\\x77\\xa4\\x15\\xef\\xda\\xa5\\xb5\\xea\\xd7\\x07\\x4a\\xe2\\x38\\x55\\xe6\\x99\\xaa\\x6b\\x69\\x72\\x2f\\x33\\x52\\x1d\\x65\\x37\\x09\\x00\"\nset gifend \"\\x3b\"\n\ntest imgPhoto-23.1 {GIF comment before image data (-data)} -setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {comment ABCD}\n\ntest imgPhoto-23.2 {GIF file comment before image data (-file)} -setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts -nonewline $h $data\n    close $h\n} -body {\n    image create photo gif1 -file $path\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {comment ABCD}\n\ntest imgPhoto-23.3 {GIF comment after image data (-data)} -setup {\n    set data $::gifstart\n    append data $::gifdata\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {comment ABCD}\n\ntest imgPhoto-23.4 {GIF comment after image data (-file)} -setup {\n    set data $::gifstart\n    append data $::gifdata\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifend\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    image create photo gif1 -file $path\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {comment ABCD}\n\ntest imgPhoto-23.5 {Two GIF comment blocks (-data)} -setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"1234\"\n    append data \"\\x21\\xfe\\x04\" \"1234\" \"\\x0\"\n    append data $::gifdata\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {comment ABCD}\n\ntest imgPhoto-23.6 {Two GIF comment blocks (-file)} -setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"1234\"\n    append data \"\\x21\\xfe\\x04\" \"1234\" \"\\x0\"\n    append data $::gifdata\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifend\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    image create photo gif1 -file $path\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {comment ABCD}\n\ntest imgPhoto-23.7 {create: test if shared metadata object is not preserved\\\n\t(-data)}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    image create photo gif1 -data $data -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.8 {create: test if shared metadata object is not preserved\\\n\t(-file)}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    image create photo gif1 -file $path -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.9 {configure: test if shared metadata object is not\\\n\tpreserved (empty image, -data)}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    gif1 configure -data $data -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.10 {configure: test if shared metadata object is not preserved\\\n\t(empty image, -file)}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    image create photo gif1\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    gif1 configure -file $path -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.11 {configure: test if shared metadata object is not preserved\\\n\t(metadata replace, -data}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data \"$::gifstart$::gifdata$::gifend\"\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    gif1 configure -data $data -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.12 {configure: test if shared metadata object is not preserved\\\n\t(metadata replace, -file}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    image create photo gif1 -data \"$::gifstart$::gifdata$::gifend\"\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    gif1 configure -file $path -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.13 {configure: test if shared metadata object is not preserved\\\n\t(-data)}\\\n-setup {\n    set data $::gifstart$::gifdata$::gifend\n} -body {\n    image create photo gif1 -data $data\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n    gif1 configure -data $data -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.14 {configure: test if shared metadata object is not preserved\\\n\t(-file)}\\\n-setup {\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n    set h [open $path \"WRONLY BINARY CREAT\"]\n    puts $h $data\n    close $h\n} -body {\n    image create photo gif1 -data \"$::gifstart$::gifdata$::gifend\"\n    set metadataDict [dict create A 1]\n    set metadataDict2 $metadataDict\n    gif1 configure -file $path -format gif -metadata $metadataDict\n    list [dict get [gif1 cget -metadata]] $metadataDict $metadataDict2\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {{A 1 comment ABCD} {A 1} {A 1}}\n\ntest imgPhoto-23.15 {output data with comment (from -metadata argument)}\\\n-setup {\n    set data $::gifstart$::gifdata$::gifend\n} -body {\n    image create photo gif1 -data $data\n    set gifData [gif1 data -format gif -metadata [dict create comment ABCD]]\n} -cleanup {\n    catch {image delete gif1}\n} -match glob -result {*ABCD*}\n\ntest imgPhoto-23.16 {output data with comment (from -metadata property)}\\\n-setup {\n    set data $::gifstart$::gifdata$::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 configure -metadata [dict create comment ABCD]\n    set gifData [gif1 data -format gif]\n} -cleanup {\n    catch {image delete gif1}\n} -match glob -result {*ABCD*}\n\ntest imgPhoto-23.17 {output file with comment (from -metadata property)}\\\n-setup {\n    set data $::gifstart$::gifdata$::gifend\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n} -body {\n    image create photo gif1 -data $data\n    gif1 configure -metadata [dict create comment ABCD]\n    gif1 write $path -format gif\n    image delete gif1\n    image create photo gif1 -file $path\n    dict get [gif1 cget -metadata] comment\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {ABCD}\n\ntest imgPhoto-23.18 {configure: empty metadata parameter overwrites image metadata} -setup {\n    image create photo gif1 -data $::gifstart$::gifdata$::gifend\\\n\t    -metadata {foo bar}\n    set data $::gifstart\n    # Append a comment extension block with data \"ABCD\"\n    append data \"\\x21\\xfe\\x04\" \"ABCD\" \"\\x0\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    gif1 configure -data $data -metadata {}\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {comment ABCD}\n\ntest imgPhoto-23.19 {write: empty metadata parameter overwrites image metadata} -setup {\n    image create photo gif1 -data $::gifstart$::gifdata$::gifend\\\n\t    -metadata {comment bar}\n    set path [file join [tcltest::configure -tmpdir] test.gif]\n} -body {\n    gif1 write $path -format gif -metadata {}\n    image delete gif1\n    image create photo gif1 -file $path\n    dict size [gif1 cget -metadata]\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {0}\n\ntest imgPhoto-23.20 {data: empty metadata parameter overwrites image metadata} -setup {\n    image create photo gif1 -data $::gifstart$::gifdata$::gifend\\\n\t    -metadata {comment bar}\n} -body {\n    set data [gif1 data -format gif -metadata {}]\n    image delete gif1\n    image create photo gif1 -data $data\n    dict size [gif1 cget -metadata]\n} -cleanup {\n    catch {image delete gif1}\n    file delete $path\n} -result {0}\n\ntest imgPhoto-23.21 {GIF delay time metadata} -setup {\n    set data $::gifstart\n    # Graphic control extension: 10 1/100s delay time\n    append data \"\\x21\\xf9\\x04\\x00\\x0a\\x00\\x00\\x00\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{delay time} 10}\n\ntest imgPhoto-23.22 {GIF disposal method \"do not dispose\" metadata} -setup {\n    set data $::gifstart\n    # Graphic control extension: disposdal method:\n    append data \"\\x21\\xf9\\x04\\x04\\x00\\x00\\x00\\x00\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{disposal method} {do not dispose}}\n\ntest imgPhoto-23.23 {GIF disposal method \"restore to background color\" metadata} -setup {\n    set data $::gifstart\n    # Graphic control extension: disposdal method:\n    append data \"\\x21\\xf9\\x04\\x08\\x00\\x00\\x00\\x00\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{disposal method} {restore to background color}}\n\ntest imgPhoto-23.24 {GIF disposal method \"restore to previous\" metadata} -setup {\n    set data $::gifstart\n    # Graphic control extension: disposdal method:\n    append data \"\\x21\\xf9\\x04\\x0C\\x00\\x00\\x00\\x00\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{disposal method} {restore to previous}}\n\ntest imgPhoto-23.25 {GIF user input flag metadata} -setup {\n    set data $::gifstart\n    # Graphic control extension: disposdal method:\n    append data \"\\x21\\xf9\\x04\\x02\\x00\\x00\\x00\\x00\"\n    # Trailer\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{user interaction} 1}\n\ntest imgPhoto-23.26 {GIF update region metadata} -setup {\n    # size 32x32, global color table size: 8\n    set data \"GIF89a\\x20\\x00\\x20\\x00\\xc2\\x07\\x00\"\n    # color table\n    append data \"\\x00\\x00\\x00\\x33\\x33\\xff\\xff\\x33\\x33\\xff\\x33\\xff\\x33\\xff\\x33\\x33\\xff\\xff\\xff\\xff\\x33\\xff\\xff\\xff\"\n    # Trailer\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{update region} {0 0 16 16}}\n\ntest imgPhoto-23.27 {GIF multiple options metadata} -setup {\n    # size 32x32, global color table size: 8\n    set data \"GIF89a\\x20\\x00\\x20\\x00\\xc2\\x07\\x00\"\n    # color table\n    append data \"\\x00\\x00\\x00\\x33\\x33\\xff\\xff\\x33\\x33\\xff\\x33\\xff\\x33\\xff\\x33\\x33\\xff\\xff\\xff\\xff\\x33\\xff\\xff\\xff\"\n    # Graphic control extension: do not dispose, user interaction, transparent color, delay time 10\n    append data \"\\x21\\xf9\\x04\\x07\\x0a\\x00\\x01\\x00\"\n    # Image data and trailer\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{update region} {0 0 16 16} {delay time} 10 {disposal method} {do not dispose} {user interaction} 1}\n\ntest imgPhoto-23.28 {GIF multiple options metadata in -index 0} -setup {\n    # size 32x32, global color table size: 8\n    set data \"GIF89a\\x20\\x00\\x20\\x00\\xc2\\x07\\x00\"\n    # color table\n    append data \"\\x00\\x00\\x00\\x33\\x33\\xff\\xff\\x33\\x33\\xff\\x33\\xff\\x33\\xff\\x33\\x33\\xff\\xff\\xff\\xff\\x33\\xff\\xff\\xff\"\n    # Graphic control extension: do not dispose, user interaction, transparent color, delay time 4096\n    append data \"\\x21\\xf9\\x04\\x07\\x00\\x10\\x01\\x00\"\n    # Image data\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata\n    # Graphic control extension: restore to background, delay time 1\n    append data \"\\x21\\xf9\\x04\\x08\\x01\\x00\\x02\\x00\"\n    # Image data and trailer\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data -format \"gif -index 0\"\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{update region} {0 0 16 16} {delay time} 4096 {disposal method} {do not dispose} {user interaction} 1}\n\ntest imgPhoto-23.29 {GIF multiple options metadata in -index 1} -setup {\n    # size 32x32, global color table size: 8\n    set data \"GIF89a\\x20\\x00\\x20\\x00\\xc2\\x07\\x00\"\n    # color table\n    append data \"\\x00\\x00\\x00\\x33\\x33\\xff\\xff\\x33\\x33\\xff\\x33\\xff\\x33\\xff\\x33\\x33\\xff\\xff\\xff\\xff\\x33\\xff\\xff\\xff\"\n    # Graphic control extension: restore to background, delay time 1\n    append data \"\\x21\\xf9\\x04\\x08\\x01\\x00\\x02\\x00\"\n    # Image data\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata\n    # Graphic control extension: do not dispose, user interaction, transparent color, delay time 4096\n    append data \"\\x21\\xf9\\x04\\x07\\x00\\x10\\x01\\x00\"\n    # Image data and trailer\n    # As this is 16x16, we will get an update region setting\n    append data $::gifdata $::gifend\n} -body {\n    image create photo gif1 -data $data -format \"gif -index 1\"\n    gif1 cget -metadata\n} -cleanup {\n    catch {image delete gif1}\n} -result {{update region} {0 0 16 16} {delay time} 4096 {disposal method} {do not dispose} {user interaction} 1}\n\n#\n# COMMON TEST SETUP\n#\n# For tests imgPhoto-24.*\n#\nunset -nocomplain gifstart gifdata gifend\nset earthPhotoFile [file join [file dirname [info script]] earth.gif]\n\ntest imgPhoto-24.1 {Read GIF file with -from option - Bug [1576528]} -body {\n    set earthPhotoFile [file join [file dirname [info script]] earth.gif]\n    image create photo gif1\n    gif1 read $earthPhotoFile -from 152 62 185 97\n    list [lindex [lindex [gif1 data] 0] 0] [image width gif1] [image height gif1]\n} -cleanup {\n    catch {image delete gif1}\n} -result {{#d8c8b8} 33 35}\ntest imgPhoto-24.2 {Read GIF file, copy with -from option} -body {\n    set earthPhotoFile [file join [file dirname [info script]] earth.gif]\n    image create photo gif1 -file $earthPhotoFile\n    image create photo gif2\n    gif2 copy gif1 -from 152 62 185 97\n    list [lindex [lindex [gif2 data] 0] 0] [image width gif2] [image height gif2]\n} -cleanup {\n    catch {image delete gif1 ; image delete gif2}\n} -result {{#d8c8b8} 33 35}\ntest imgPhoto-24.3 {Read GIF file with -to option} -body {\n    image create photo gif1\n    gif1 read $earthPhotoFile -to 100 200\n    list [lindex [lindex [gif1 data] 262] 252] [image width gif1] [image height gif1]\n} -cleanup {\n    catch {image delete gif1}\n} -result {{#d8c8b8} 420 400}\ntest imgPhoto-24.4 {Read GIF file with -from and -to options} -body {\n    set earthPhotoFile [file join [file dirname [info script]] earth.gif]\n    image create photo gif1\n    gif1 read $earthPhotoFile -from 152 62 185 97 -to 100 200\n    list [lindex [lindex [gif1 data] 200] 100] [image width gif1] [image height gif1]\n} -cleanup {\n    catch {image delete gif1}\n} -result {{#d8c8b8} 133 235}\ntest imgPhoto-24.5 {Read GIF file with -from, -to and -shrink options} -body {\n    set earthPhotoFile [file join [file dirname [info script]] earth.gif]\n    image create photo gif1 -file $teapotPhotoFile\n    gif1 read $earthPhotoFile -from 152 62 185 97 -to 80 120 -shrink\n    list [lindex [lindex [gif1 data] 120] 80] [image width gif1] [image height gif1]\n} -cleanup {\n    catch {image delete gif1}\n} -result {{#d8c8b8} 113 155}\ntest imgPhoto-24.6 {Read GIF file with -from option, read large region from small file} -body {\n    set earthPhotoFile [file join [file dirname [info script]] earth.gif]\n    image create photo gif1\n    catch {gif1 read $earthPhotoFile -from 152 62 2000 1000} msg\n    list $msg [image width gif1] [image height gif1]\n} -cleanup {\n    catch {image delete gif1}\n} -result {{coordinates for -from option extend outside source image} 0 0}\n\n#\n# COMMON TEST SETUP\n#\n# For tests imgPhoto-25.*\n#\nunset earthPhotoFile\nset ousterPhotoFile [file join [file dirname [info script]] ouster.png]\n\ntest imgPhoto-25.1 {Read PNG file with -from option - Bug [1576528]} -body {\n    image create photo png1\n    png1 read $ousterPhotoFile -from 102 62 135 97\n    list [lindex [lindex [png1 data] 0] 0] [image width png1] [image height png1]\n} -cleanup {\n    catch {image delete png1}\n} -result {{#c97962} 33 35}\ntest imgPhoto-25.2 {Read PNG file, copy with -from option} -body {\n    image create photo png1 -file $ousterPhotoFile\n    image create photo png2\n    png2 copy png1 -from 102 62 135 97\n    list [lindex [lindex [png2 data] 0] 0] [image width png2] [image height png2]\n} -cleanup {\n    catch {image delete png1 ; image delete png2}\n} -result {{#c97962} 33 35}\ntest imgPhoto-25.3 {Read PNG file with -to option} -body {\n    image create photo png1\n    png1 read $ousterPhotoFile -to 100 200\n    list [lindex [lindex [png1 data] 262] 202] [image width png1] [image height png1]\n} -cleanup {\n    catch {image delete png1}\n} -result {{#c97962} 242 381}\ntest imgPhoto-25.4 {Read PNG file with -from and -to options} -body {\n    image create photo png1\n    png1 read $ousterPhotoFile -from 102 62 135 97 -to 100 200\n    list [lindex [lindex [png1 data] 200] 100] [image width png1] [image height png1]\n} -cleanup {\n    catch {image delete png1}\n} -result {{#c97962} 133 235}\ntest imgPhoto-25.5 {Read PNG file with -from, -to and -shrink options} -body {\n    image create photo png1 -file $teapotPhotoFile\n    png1 read $ousterPhotoFile -from 102 62 135 97 -to 80 120 -shrink\n    list [lindex [lindex [png1 data] 120] 80] [image width png1] [image height png1]\n} -cleanup {\n    catch {image delete png1}\n} -result {{#c97962} 113 155}\ntest imgPhoto-25.6 {Read PNG file with -from option, read large region from small file} -body {\n    image create photo png1\n    catch {png1 read $ousterPhotoFile -from 102 62 2000 1000} msg\n    list $msg [image width png1] [image height png1]\n} -cleanup {\n    catch {image delete png1}\n} -result {{coordinates for -from option extend outside source image} 0 0}\n\n#\n# TESTFILE CLEANUP\n#\n\nunset ousterPhotoFile\ncatch {rename foreachPixel {}}\ncatch {rename checkImgTrans {}}\ncatch {rename checkImgTransLoop {}}\nimageFinish\nremoveFile README-imgPhoto\n\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/imgSVGnano.test",
    "content": "# This file is a Tcl script to test out the code in tkImgSVGnano.c, which reads\n# and write SVG-format image files for photo widgets.\n#\n# Copyright © 2018 Rene Zaumseil\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\nnamespace eval svgnano {\n\n    #\n    # COMMON TEST SETUP\n    #\n\n    variable data\n\n    set data(plus) {\\\n\t    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\">\n\t\t<path fill=\"none\" stroke=\"#000000\" d=\"M0 0 h16 v16 h-16 z\"/>\n\t\t<path fill=\"none\" stroke=\"#000000\" d=\"M8 4 v 8 M4 8 h 8\"/>\n\t\t<circle fill=\"yellow\" stroke=\"red\" cx=\"10\" cy=\"80\" r=\"10\" />\n\t\t<ellipse fill=\"none\" stroke=\"blue\" stroke-width=\"3\" cx=\"60\" cy=\"60\" rx=\"10\" ry=\"20\" />\n\t\t<line x1=\"10\" y1=\"90\" x2=\"50\" y2=\"99\"/>\n\t\t<rect fill=\"none\" stroke=\"green\"  x=\"20\" y=\"20\" width=\"60\" height=\"50\" rx=\"3\" ry=\"3\"/>\n\t\t<polyline fill=\"red\" stroke=\"purple\" points=\"80,10 90,20 85,40\"/>\n\t\t<polygon fill =\"yellow\" points=\"80,80 70,85 90,90\"/>\n\t\t</svg>}\n\t\tset data(bad) {<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0\" height=\"0:w\">\n\t    </svg>\\\n    }\n\n    tcltest::makeFile $data(plus) plus.svg\n    set data(plusFilePath) [file join [tcltest::configure -tmpdir] plus.svg]\n\n    tcltest::makeFile $data(bad) bad.svg\n    set data(badFilePath) [file join [tcltest::configure -tmpdir] bad.svg]\n\n#\n# TESTS\n#\n\ntest imgSVGnano-1.1 {reading simple image} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $data(plus)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {100 100}\n\ntest imgSVGnano-1.2 {simple image with options} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $data(plus) -format {svg -dpi 100 -scale 3}\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {300 300}\n\n# test on crash found by Koen Danckaert\ntest imgSVGnano-1.3 {reformat image options} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $data(plus)\n    catch {foo configure -format {svg -scale}}\n    list {}\n} -cleanup {\n    rename foo \"\"\n} -result {{}}\n\ntest imgSVGnano-1.4 {image options} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -data $data(plus)\n    foo configure -format {svg -scale 2}\n    foo configure -format {svg -dpi 600}\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {100 100}\n\ntest imgSVGnano-1.5 {reading simple image from file} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -file $data(plusFilePath)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {100 100}\ntest imgSVGnano-1.6 {simple image from file with options} -setup {\n    catch {rename foo \"\"}\n} -body {\n    image create photo foo -file $data(plusFilePath) -format {svg -dpi 100 -scale 3}\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {300 300}\n\ntest imgSVGnano-1.7 {very small scale gives 1x1 image} -body {\n    image create photo foo -format \"svg -scale 0.000001\"\\\n\t    -data $data(plus)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {1 1}\ntest imgSVGnano-1.8 {very small scale gives 1x1 image, from file} -body {\n    image create photo foo -format \"svg -scale 0.000001\"\\\n\t    -file $data(plusFilePath)\n    list [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n} -result {1 1}\n\ntest imgSVGnano-2.1 {reading a bad image} -body {\n    image create photo foo -format svg -data $data(bad)\n} -returnCodes error -result {couldn't recognize image data}\ntest imgSVGnano-2.2 {using bad option} -body {\n    image create photo foo -data $data(plus) -format {svg -scale 0}\n} -returnCodes error -result {-scale value must be positive}\ntest imgSVGnano-2.3 {using bad option} -body {\n    image create photo foo -data $data(plus)\n    foo configure -format {svg 1.0}\n} -cleanup {\n    rename foo \"\"\n} -returnCodes error -result {bad option \"1.0\": must be -dpi, -scale, -scaletoheight, or -scaletowidth}\ntest imgSVGnano-2.4 {reading a bad image from file} -body {\n    image create photo foo -format svg -file $data(badFilePath)\n} -returnCodes error -match glob\\\n    -result {couldn't recognize data in image file \"*/bad.svg\"}\n\n# -scaletoheight and -scaletowidth options\ntest imgSVGnano-3.1 {multiple scale options} -body {\n    image create photo foo -format \"svg -scale 1 -scaletowidth 20\"\\\n\t    -data $data(bad)\n} -returnCodes error -result {only one of -scale, -scaletoheight, -scaletowidth may be given}\n\ntest imgSVGnano-3.2 {no number parameter to -scaletowidth} -body {\n    image create photo foo -format \"svg -scaletowidth invalid\"\\\n\t    -data $data(plus)\n} -returnCodes error -result {expected integer but got \"invalid\"}\n\ntest imgSVGnano-3.3 {no number parameter to -scaletoheight} -body {\n    image create photo foo -format \"svg -scaletoheight invalid\"\\\n\t    -data $data(plus)\n} -returnCodes error -result {expected integer but got \"invalid\"}\n\ntest imgSVGnano-3.4 {zero parameter to -scaletowidth} -body {\n    image create photo foo -format \"svg -scaletowidth 0\"\\\n\t    -data $data(plus)\n} -returnCodes error -result {-scaletowidth value must be positive}\n\ntest imgSVGnano-3.5 {zero parameter to -scaletoheight} -body {\n    image create photo foo -format \"svg -scaletoheight 0\"\\\n\t    -data $data(plus)\n} -returnCodes error -result {-scaletoheight value must be positive}\n\ntest imgSVGnano-3.6 {no number parameter to -scaletoheight} -body {\n    image create photo foo -format \"svg -scaletoheight invalid\"\\\n\t    -data $data(plus)\n} -returnCodes error -result {expected integer but got \"invalid\"}\n\ntest imgSVGnano-3.7 {option -scaletowidth} -body {\n    image create photo foo -format \"svg -scaletowidth 20\"\\\n\t    -data $data(plus)\n    image width foo\n} -cleanup {\n    rename foo \"\"\n} -result 20\n\ntest imgSVGnano-3.8 {option -scaletoheight} -body {\n    image create photo foo -format \"svg -scaletoheight 20\"\\\n\t    -data $data(plus)\n    image height foo\n} -cleanup {\n    rename foo \"\"\n} -result 20\n\ntest imgSVGnano-3.10 {change from -scaletoheight to -scale} -body {\n    set res {}\n    image create photo foo -format \"svg -scaletoheight 16\"\\\n\t    -data $data(plus)\n    lappend res [image width foo] [image height foo]\n    foo configure -format \"svg -scale 2\"\n    lappend res [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n    unset res\n} -result {16 16 200 200}\n\n# svg file access\ntest imgSVGnano-4.1 {reread file on configure -scale} -setup {\n    catch {rename foo \"\"}\n    set res {}\n} -body {\n    image create photo foo -file $data(plusFilePath)\n    lappend res [image width foo] [image height foo]\n    foo configure -format \"svg -scale 2\"\n    lappend res [image width foo] [image height foo]\n} -cleanup {\n    rename foo \"\"\n    unset res\n} -result {100 100 200 200}\n\ntest imgSVGnano-4.2 {error on file not accessible on reread due to configure} -setup {\n    catch {rename foo \"\"}\n    tcltest::makeFile $data(plus) tmpplus.svg\n    image create photo foo -file [file join [tcltest::configure -tmpdir] tmpplus.svg]\n    tcltest::removeFile tmpplus.svg\n} -body {\n    foo configure -format \"svg -scale 2\"\n} -cleanup {\n    rename foo \"\"\n} -returnCodes error -match glob -result {couldn't open \"*/tmpplus.svg\": no such file or directory}\n\n# Special images\ntest imgSVGnano-5.0 {image without any of  \"width\", \"height\" and \"viewbox\"} -body {\n    image create photo foo -data\\\n\t\t\t{<?xml version=\"1.0\"?><!DOCTYPE svg PUBLIC\\\n\t\t\t\"-//W3C//DTD SVG 1.0//EN\\\"\\\n\t\t\t\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\\\n\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\">\\\n\t\t\t<g style=\"fill-opacity:0.7;\">\\\n\t\t\t<circle cx=\"6.5cm\" cy=\"2cm\" r=\"100\" style=\"fill:green;\\\n\t\t\tstroke:black; stroke-width:0.1cm\" transform=\"translate(-70,150)\"/>\\\n\t\t\t</g></svg>}\n} -cleanup {\n    rename foo \"\"\n} -result {foo}\n\ntest imgSVGnano-5.1 {bug ea665e08f3 - too many values in parameters of the transform attribute} -body {\n    # shall not loop endlessly\n    image create photo foo -data\\\n\t\t\t{<?xml version=\"1.0\"?><!DOCTYPE svg PUBLIC\\\n\t\t\t\"-//W3C//DTD SVG 1.0//EN\\\"\\\n\t\t\t\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\\\n\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\">\\\n\t\t\t<circle cx=\"6.5cm\" cy=\"2cm\" r=\"100\" transform=\"skewX(1 1)\"/>\\\n\t\t\t</g></svg>}\n} -cleanup {\n    rename foo \"\"\n} -result {foo}\n\ntest imgSVGnano-5.2 {bug d6e9b4db40 - \"<svg\" and \">\" must be present} -body {\n    image create photo foo -format svg -data\\\n\t\t\t{<?xml version=\"1.0\"?><!DOCTYPE svg PUBLIC\\\n\t\t\t\"-//W3C//DTD SVG 1.0//EN\\\" \\\n\t\t\t\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\\\n\t\t\t<sERRORvBADFILEg xmlns=\"http://www.w3.org/2000/svg\">\\\n\t\t\t<circle cx=\"6.5cm\" cy=\"2cm\" r=\"100\" transform=\"skewX(1 1)\"/>\\\n\t\t\t</g></svg>}\n} -returnCodes error -result {couldn't recognize image data}\n\n    #\n    # COMMON TEST CLEANUP\n    #\n    tcltest::removeFile plus.svg\n    tcltest::removeFile bad.svg\n\n};# end of namespace svgnano\n\n#\n# TESTFILE CLEANUP\n#\n\nnamespace delete svgnano\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "tests/listbox.test",
    "content": "# This file is a Tcl script to test out the \"listbox\" command\n# of Tk.\n#\n# Copyright © 1993-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc getsize w {\n    regexp {(^[^+-]*)} [wm geometry $w] foo x\n    return $x\n}\n\n# mkPartial --\n#\n# Creates a second listbox for checking things related\n# to partially visible lines.\n#\nproc mkPartial {{w .partial}} {\n    destroy $w\n    toplevel $w\n    wm geometry $w +0+0\n    listbox $w.l -width 30 -height 5\n    pack $w.l -expand 1 -fill both\n    $w.l insert end one two three four five six seven eight nine ten \\\n\t    eleven twelve thirteen fourteen fifteen\n    update\n    scan [wm geometry $w] \"%dx%d\" width height\n    wm geometry $w ${width}x[expr {$height-3}]\n    update\n}\n\nproc record {name args} {\n    global log\n    lappend log [format {%s %.6g %.6g} $name {*}$args]\n}\n\nproc resetGridInfo {} {\n    # Some window managers, such as mwm, don't reset gridding information\n    # unless the window is withdrawn and re-mapped.  If this procedure\n    # isn't invoked, the window manager will stay in gridded mode, which\n    # can cause all sorts of problems.  The \"wm positionfrom\" command is\n    # needed so that the window manager doesn't ask the user to\n    # manually position the window when it is re-mapped.\n\n    wm withdraw .\n    wm positionfrom . user\n    wm deiconify .\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset fixed {Courier -12}\n\n# Create entries in the option database to be sure that geometry options\n# like border width have predictable values.\noption add *Listbox.borderWidth 2\noption add *Listbox.selectBorderWidth 1\noption add *Listbox.highlightThickness 2\noption add *Listbox.font {Helvetica -12 bold}\n\nlistbox .l\npack .l\nupdate\n\nresetGridInfo\n\n#\n# TESTS\n#\n\ntest listbox-1.1 {configuration options} -body {\n    .l configure -activestyle under\n    list [lindex [.l configure -activestyle] 4] [.l cget -activestyle]\n} -cleanup {\n    .l configure -activestyle [lindex [.l configure -activestyle] 3]\n} -result {underline underline}\ntest listbox-1.2 {configuration options} -body {\n    .l configure -activestyle foo\n} -returnCodes error -result {bad activestyle \"foo\": must be dotbox, none, or underline}\ntest listbox-1.3 {configuration options} -body {\n    .l configure -background #ff0000\n    list [lindex [.l configure -background] 4] [.l cget -background]\n} -cleanup {\n    .l configure -background [lindex [.l configure -background] 3]\n} -result {{#ff0000} #ff0000}\ntest listbox-1.4 {configuration options} -body {\n    .l configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest listbox-1.5 {configuration options} -body {\n    .l configure -bd 4\n    list [lindex [.l configure -bd] 4] [.l cget -bd]\n} -cleanup {\n    .l configure -bd [lindex [.l configure -bd] 3]\n} -result {4 4}\ntest listbox-1.6 {configuration options} -body {\n    .l configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest listbox-1.7 {configuration options} -body {\n    .l configure -bg #ff0000\n    list [lindex [.l configure -bg] 4] [.l cget -bg]\n} -cleanup {\n    .l configure -bg [lindex [.l configure -bg] 3]\n} -result {{#ff0000} #ff0000}\ntest listbox-1.8 {configuration options} -body {\n    .l configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest listbox-1.9 {configuration options} -body {\n    .l configure -borderwidth 1.3\n    list [lindex [.l configure -borderwidth] 4] [.l cget -borderwidth]\n} -cleanup {\n    .l configure -borderwidth [lindex [.l configure -borderwidth] 3]\n} -result {1.3 1.3}\ntest listbox-1.10 {configuration options} -body {\n    .l configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest listbox-1.11 {configuration options} -body {\n    .l configure -cursor arrow\n    list [lindex [.l configure -cursor] 4] [.l cget -cursor]\n} -cleanup {\n    .l configure -cursor [lindex [.l configure -cursor] 3]\n} -result {arrow arrow}\ntest listbox-1.12 {configuration options} -body {\n    .l configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest listbox-1.13 {configuration options} -body {\n    .l configure -disabledforeground #110022\n    list [lindex [.l configure -disabledforeground] 4] [.l cget -disabledforeground]\n} -cleanup {\n    .l configure -disabledforeground [lindex [.l configure -disabledforeground] 3]\n} -result {{#110022} #110022}\ntest listbox-1.14 {configuration options} -body {\n    .l configure -disabledforeground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.15 {configuration options} -body {\n    .l configure -exportselection yes\n    list [lindex [.l configure -exportselection] 4] [.l cget -exportselection]\n} -cleanup {\n    .l configure -exportselection [lindex [.l configure -exportselection] 3]\n} -result {1 1}\ntest listbox-1.16 {configuration options} -body {\n    .l configure -exportselection xyzzy\n} -returnCodes error -result {expected boolean value but got \"xyzzy\"}\ntest listbox-1.17 {configuration options} -body {\n    .l configure -fg #110022\n    list [lindex [.l configure -fg] 4] [.l cget -fg]\n} -cleanup {\n    .l configure -fg [lindex [.l configure -fg] 3]\n} -result {{#110022} #110022}\ntest listbox-1.18 {configuration options} -body {\n    .l configure -fg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.19 {configuration options} -body {\n    .l configure -font {Helvetica 12}\n    list [lindex [.l configure -font] 4] [.l cget -font]\n} -cleanup {\n    .l configure -font [lindex [.l configure -font] 3]\n} -result {{Helvetica 12} {Helvetica 12}}\ntest listbox-1.21 {configuration options} -body {\n    .l configure -foreground #110022\n    list [lindex [.l configure -foreground] 4] [.l cget -foreground]\n} -cleanup {\n    .l configure -foreground [lindex [.l configure -foreground] 3]\n} -result {{#110022} #110022}\ntest listbox-1.22 {configuration options} -body {\n    .l configure -foreground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.23 {configuration options} -body {\n    .l configure -height 30\n    list [lindex [.l configure -height] 4] [.l cget -height]\n} -cleanup {\n    .l configure -height [lindex [.l configure -height] 3]\n} -result {30 30}\ntest listbox-1.24 {configuration options} -body {\n    .l configure -height 20p\n} -returnCodes error -result {expected integer but got \"20p\"}\ntest listbox-1.25 {configuration options} -body {\n    .l configure -highlightbackground #112233\n    list [lindex [.l configure -highlightbackground] 4] [.l cget -highlightbackground]\n} -cleanup {\n    .l configure -highlightbackground [lindex [.l configure -highlightbackground] 3]\n} -result {{#112233} #112233}\ntest listbox-1.26 {configuration options} -body {\n    .l configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest listbox-1.27 {configuration options} -body {\n    .l configure -highlightcolor #123456\n    list [lindex [.l configure -highlightcolor] 4] [.l cget -highlightcolor]\n} -cleanup {\n    .l configure -highlightcolor [lindex [.l configure -highlightcolor] 3]\n} -result {{#123456} #123456}\ntest listbox-1.28 {configuration options} -body {\n    .l configure -highlightcolor bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.29 {configuration options} -body {\n    .l configure -highlightthickness 6\n    list [lindex [.l configure -highlightthickness] 4] [.l cget -highlightthickness]\n} -cleanup {\n    .l configure -highlightthickness [lindex [.l configure -highlightthickness] 3]\n} -result {6 6}\ntest listbox-1.30 {configuration options} -body {\n    .l configure -highlightthickness bogus\n} -returnCodes error -result {expected screen distance but got \"bogus\"}\ntest listbox-1.31 {configuration options} -body {\n    .l configure -highlightthickness -2\n    list [lindex [.l configure -highlightthickness] 4] [.l cget -highlightthickness]\n} -cleanup {\n    .l configure -highlightthickness [lindex [.l configure -highlightthickness] 3]\n} -returnCodes error -result {expected screen distance but got \"-2\"}\ntest listbox-1.32.1 {configuration options} -setup {\n    set res {}\n} -body {\n    .l configure -justify left\n    set res [list [lindex [.l configure -justify] 4] [.l cget -justify]]\n    .l configure -justify center\n    lappend res [lindex [.l configure -justify] 4] [.l cget -justify]\n    .l configure -justify right\n    lappend res [lindex [.l configure -justify] 4] [.l cget -justify]\n} -cleanup {\n    .l configure -justify [lindex [.l configure -justify] 3]\n} -result {left left center center right right}\ntest listbox-1.32.2 {configuration options} -body {\n    .l configure -justify bogus\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\ntest listbox-1.33 {configuration options} -body {\n    .l configure -relief groove\n    list [lindex [.l configure -relief] 4] [.l cget -relief]\n} -cleanup {\n    .l configure -relief [lindex [.l configure -relief] 3]\n} -result {groove groove}\ntest listbox-1.34 {configuration options} -body {\n    .l configure -relief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest listbox-1.35 {configuration options} -body {\n    .l configure -selectbackground #110022\n    list [lindex [.l configure -selectbackground] 4] [.l cget -selectbackground]\n} -cleanup {\n    .l configure -selectbackground [lindex [.l configure -selectbackground] 3]\n} -result {{#110022} #110022}\ntest listbox-1.36 {configuration options} -body {\n    .l configure -selectbackground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.37 {configuration options} -body {\n    .l configure -selectborderwidth 1.3\n    list [lindex [.l configure -selectborderwidth] 4] [.l cget -selectborderwidth]\n} -cleanup {\n    .l configure -selectborderwidth [lindex [.l configure -selectborderwidth] 3]\n} -result {1.3 1.3}\ntest listbox-1.38 {configuration options} -body {\n    .l configure -selectborderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest listbox-1.39 {configuration options} -body {\n    .l configure -selectforeground #654321\n    list [lindex [.l configure -selectforeground] 4] [.l cget -selectforeground]\n} -cleanup {\n    .l configure -selectforeground [lindex [.l configure -selectforeground] 3]\n} -result {{#654321} #654321}\ntest listbox-1.40 {configuration options} -body {\n    .l configure -selectforeground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.41 {configuration options} -body {\n    .l configure -selectmode string\n    list [lindex [.l configure -selectmode] 4] [.l cget -selectmode]\n} -cleanup {\n    .l configure -selectmode [lindex [.l configure -selectmode] 3]\n} -result {string string}\ntest listbox-1.43 {configuration options} -body {\n    .l configure -setgrid false\n    list [lindex [.l configure -setgrid] 4] [.l cget -setgrid]\n} -cleanup {\n    .l configure -setgrid [lindex [.l configure -setgrid] 3]\n} -result {0 0}\ntest listbox-1.44 {configuration options} -body {\n    .l configure -setgrid lousy\n} -returnCodes error -result {expected boolean value but got \"lousy\"}\ntest listbox-1.45 {configuration options} -body {\n    .l configure -state disabled\n    list [lindex [.l configure -state] 4] [.l cget -state]\n} -cleanup {\n    .l configure -state [lindex [.l configure -state] 3]\n} -result {disabled disabled}\ntest listbox-1.46 {configuration options} -body {\n    .l configure -state foo\n} -returnCodes error -result {bad state \"foo\": must be disabled or normal}\ntest listbox-1.47 {configuration options} -body {\n    .l configure -takefocus {any string}\n    list [lindex [.l configure -takefocus] 4] [.l cget -takefocus]\n} -cleanup {\n    .l configure -takefocus [lindex [.l configure -takefocus] 3]\n} -result {{any string} {any string}}\ntest listbox-1.49 {configuration options} -body {\n    .l configure -width 45\n    list [lindex [.l configure -width] 4] [.l cget -width]\n} -cleanup {\n    .l configure -width [lindex [.l configure -width] 3]\n} -result {45 45}\ntest listbox-1.50 {configuration options} -body {\n    .l configure -width 3p\n} -returnCodes error -result {expected integer but got \"3p\"}\ntest listbox-1.51 {configuration options} -body {\n    .l configure -xscrollcommand {Some command}\n    list [lindex [.l configure -xscrollcommand] 4] [.l cget -xscrollcommand]\n} -cleanup {\n    .l configure -xscrollcommand [lindex [.l configure -xscrollcommand] 3]\n} -result {{Some command} {Some command}}\ntest listbox-1.53 {configuration options} -body {\n    .l configure -yscrollcommand {Another command}\n    list [lindex [.l configure -yscrollcommand] 4] [.l cget -yscrollcommand]\n} -cleanup {\n    .l configure -yscrollcommand [lindex [.l configure -yscrollcommand] 3]\n} -result {{Another command} {Another command}}\ntest listbox-1.55 {configuration options} -body {\n    .l configure -listvar testVariable\n    list [lindex [.l configure -listvar] 4] [.l cget -listvar]\n} -cleanup {\n    .l configure -listvar [lindex [.l configure -listvar] 3]\n} -result {testVariable testVariable}\ntest listbox-1.56 {configuration options} -body {\n    .l configure -inactiveselectbackground #110022\n    list [lindex [.l configure -inactiveselectbackg] 4] [.l cget -inactiveselectbackg]\n} -cleanup {\n    .l configure -inactiveselectbackg [lindex [.l configure -inactiveselectbackg] 3]\n} -result {{#110022} #110022}\ntest listbox-1.57 {configuration options} -body {\n    .l configure -inactiveselectbackg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-1.58 {configuration options} -body {\n    .l configure -inactiveselectforeground #654321\n    list [lindex [.l configure -inactiveselectforeg] 4] [.l cget -inactiveselectforeg]\n} -cleanup {\n    .l configure -inactiveselectforeg [lindex [.l configure -inactiveselectforeg] 3]\n} -result {{#654321} #654321}\ntest listbox-1.59 {configuration options} -body {\n    .l configure -inactiveselectforeg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\n\ntest listbox-2.1 {Tk_ListboxCmd procedure} -body {\n    listbox\n} -returnCodes error -result {wrong # args: should be \"listbox pathName ?-option value ...?\"}\ntest listbox-2.2 {Tk_ListboxCmd procedure} -body {\n    listbox gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest listbox-2.3 {Tk_ListboxCmd procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    list [winfo exists .l] [winfo class .l] [info commands .l]\n} -result {1 Listbox .l}\ntest listbox-2.4 {Tk_ListboxCmd procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l -gorp foo\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest listbox-2.4.1 {Tk_ListboxCmd procedure} -setup {\n    destroy .l\n} -body {\n    catch {listbox .l -gorp foo}\n    list [winfo exists .l] [info commands .l]\n} -cleanup {\n    destroy .l\n} -result {0 {}}\ntest listbox-2.5 {Tk_ListboxCmd procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l\n} -cleanup {\n    destroy .l\n} -result {.l}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-3.1 - 3.115\n#\ndestroy .l\nlistbox .l -width 20 -height 5 -bd 4 -highlightthickness 1 -selectborderwidth 2\npack .l\n.l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11 el12 el13 el14 \\\n\tel15 el16 el17\nupdate\n\ntest listbox-3.1 {ListboxWidgetCmd procedure} -body {\n    .l\n} -returnCodes error -result {wrong # args: should be \".l option ?arg ...?\"}\ntest listbox-3.2 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate\n} -returnCodes error -result {wrong # args: should be \".l activate index\"}\ntest listbox-3.3 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate a b\n} -returnCodes error -result {wrong # args: should be \".l activate index\"}\ntest listbox-3.4 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate fooey\n} -returnCodes error -result {bad listbox index \"fooey\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.5 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate 3\n    .l index active\n} -result 3\ntest listbox-3.6 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate {}\n    .l index active\n} -result 0\ntest listbox-3.7 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate 30\n    .l index active\n} -result 17\ntest listbox-3.8 {ListboxWidgetCmd procedure, \"activate\" option} -body {\n    .l activate end\n    .l index active\n} -result 17\ntest listbox-3.9 {ListboxWidgetCmd procedure, \"bbox\" option} -body {\n    .l bbox\n} -returnCodes error -result {wrong # args: should be \".l bbox index\"}\ntest listbox-3.10 {ListboxWidgetCmd procedure, \"bbox\" option} -body {\n    .l bbox a b\n} -returnCodes error -result {wrong # args: should be \".l bbox index\"}\ntest listbox-3.11 {ListboxWidgetCmd procedure, \"bbox\" option} -body {\n    .l bbox fooey\n} -returnCodes error -result {bad listbox index \"fooey\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.12 {ListboxWidgetCmd procedure, \"bbox\" option} -body {\n    .l yview 3\n    update\n    list [.l bbox 2] [.l bbox 8]\n} -result {{} {}}\ntest listbox-3.13 {ListboxWidgetCmd procedure, \"bbox\" option} -cleanup {\n    destroy .l2\n} -body {\n    # Used to generate a core dump before a bug was fixed (the last\n    # element would be on-screen if it existed, but it doesn't exist).\n\n    listbox .l2\n    pack .l2 -side top\n    tkwait visibility .l2\n    set x [.l2 bbox 0]\n    destroy .l2\n    set x\n} -cleanup {\n    destroy .l2\n} -result {}\ntest listbox-3.14 {ListboxWidgetCmd procedure, \"bbox\" option} -constraints {\n\tfonts\n} -body {\n    .l yview 3\n    update\n    list [.l bbox 3] [.l bbox 4]\n} -result {{7 7 17 14} {7 26 17 14}}\ntest listbox-3.15 {ListboxWidgetCmd procedure, \"bbox\" option} -constraints {\n\tfonts\n} -body {\n    .l yview 0\n    update\n    list [.l bbox {}] [.l bbox 0]\n} -result {{} {7 7 17 14}}\ntest listbox-3.16 {ListboxWidgetCmd procedure, \"bbox\" option} -constraints {\n\tfonts\n} -body {\n    .l yview end\n    update\n    list [.l bbox 17] [.l bbox end] [.l bbox 18]\n} -result {{7 83 24 14} {7 83 24 14} {}}\ntest listbox-3.17 {ListboxWidgetCmd procedure, \"bbox\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geom .t +0+0\n    listbox .t.l -width 10 -height 5\n    .t.l insert 0 \"Short\" \"Somewhat longer\" \"Really, quite a whole lot longer than can possibly fit on the screen\" \"Short\"\n    pack .t.l\n    update\n    .t.l xview moveto .2\n    .t.l bbox 2\n} -cleanup {\n    destroy .t\n} -result {-72 39 393 14}\ntest listbox-3.18 {ListboxWidgetCmd procedure, \"bbox\" option, partial last line} -constraints {\n\tfonts\n} -body {\n    mkPartial\n    list [.partial.l bbox 3] [.partial.l bbox 4]\n} -result {{5 56 24 14} {5 73 23 14}}\ntest listbox-3.18a {ListboxWidgetCmd procedure, \"bbox\" option, justified} -constraints {\n\tfonts\n} -setup {\n    destroy .top.l .top\n    unset -nocomplain res\n} -body {\n    toplevel .top\n    listbox .top.l -justify left\n    .top.l insert end Item1 LongerItem2 MuchLongerItem3\n    pack .top.l\n    update\n    lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n    .top.l configure -justify center\n    lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n    .top.l configure -justify right\n    lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n} -cleanup {\n    destroy .top.l .top\n    unset -nocomplain res\n} -result [list \\\n    {5 5 34 14} {5 22 74 14} {5 39 106 14}     \\\n    {58 5 34 14} {38 22 74 14} {22 39 106 14}  \\\n    {111 5 34 14} {71 22 74 14} {39 39 106 14} \\\n]\ntest listbox-3.18b {ListboxWidgetCmd procedure, \"bbox\" option, justified, non-default borderwidth} -setup {\n    destroy .top.l .top\n    unset -nocomplain lres res\n} -body {\n    # This test checks whether all \"x\" values from bbox for different size\n    # items with different justification settings are all positive or zero\n    # This checks a bit the calculation of this x value with non-default\n    # borders widths of the listbox\n    toplevel .top\n    listbox .top.l -justify left -borderwidth 17 -highlightthickness 19 -selectborderwidth 22\n    .top.l insert end Item1 LongerItem2 MuchLongerItem3\n    .top.l selection set 1\n    pack .top.l\n    update\n    lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n    .top.l configure -justify center\n    lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n    .top.l configure -justify right\n    lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]\n    set res 1\n    for {set i 0} {$i < [llength $lres]} {incr i 4} {\n\tset res [expr {$res * [expr {[lindex $lres $i] >= 0}] }]\n    }\n    set res\n} -cleanup {\n    destroy .top.l .top\n    unset -nocomplain lres res\n} -result 1\ntest listbox-3.19 {ListboxWidgetCmd procedure, \"cget\" option} -body {\n    .l cget\n} -returnCodes error -result {wrong # args: should be \".l cget option\"}\ntest listbox-3.20 {ListboxWidgetCmd procedure, \"cget\" option} -body {\n    .l cget a b\n} -returnCodes error -result {wrong # args: should be \".l cget option\"}\ntest listbox-3.21 {ListboxWidgetCmd procedure, \"cget\" option} -body {\n    .l cget -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest listbox-3.22 {ListboxWidgetCmd procedure, \"cget\" option} -body {\n    .l cget -setgrid\n} -result 0\ntest listbox-3.23 {ListboxWidgetCmd procedure, \"configure\" option} -body {\n    llength [.l configure]\n} -result 30\ntest listbox-3.24 {ListboxWidgetCmd procedure, \"configure\" option} -body {\n    .l configure -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest listbox-3.25 {ListboxWidgetCmd procedure, \"configure\" option} -body {\n    .l configure -setgrid\n} -result {-setgrid setGrid SetGrid 0 0}\ntest listbox-3.26 {ListboxWidgetCmd procedure, \"configure\" option} -body {\n    .l configure -gorp is_messy\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest listbox-3.27 {ListboxWidgetCmd procedure, \"configure\" option} -body {\n    set oldbd [.l cget -bd]\n    set oldht [.l cget -highlightthickness]\n    .l configure -bd 3 -highlightthickness 0\n    set x \"[.l cget -bd] [.l cget -highlightthickness]\"\n    .l configure -bd $oldbd -highlightthickness $oldht\n    set x\n} -result {3 0}\ntest listbox-3.28 {ListboxWidgetCmd procedure, \"curselection\" option} -body {\n    .l curselection a\n} -returnCodes error -result {wrong # args: should be \".l curselection\"}\ntest listbox-3.29 {ListboxWidgetCmd procedure, \"curselection\" option} -body {\n    .l selection clear 0 end\n    .l selection set 3 6\n    .l selection set 9\n    .l curselection\n} -result {3 4 5 6 9}\ntest listbox-3.30 {ListboxWidgetCmd procedure, \"delete\" option} -body {\n    .l delete\n} -returnCodes error -result {wrong # args: should be \".l delete firstIndex ?lastIndex?\"}\ntest listbox-3.31 {ListboxWidgetCmd procedure, \"delete\" option} -body {\n    .l delete a b c\n} -returnCodes error -result {wrong # args: should be \".l delete firstIndex ?lastIndex?\"}\ntest listbox-3.32 {ListboxWidgetCmd procedure, \"delete\" option} -body {\n    .l delete badIndex\n} -returnCodes error -result {bad listbox index \"badIndex\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.33 {ListboxWidgetCmd procedure, \"delete\" option} -body {\n    .l delete 2 123ab\n} -returnCodes error -result {bad listbox index \"123ab\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.34 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete 3\n    list [.l2 get 2] [.l2 get 3] [.l2 index end]\n} -cleanup {\n    destroy .l2\n} -result {el2 el4 7}\ntest listbox-3.35 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete 2 4\n    list [.l2 get 1] [.l2 get 2] [.l2 index end]\n} -cleanup {\n    destroy .l2\n} -result {el1 el5 5}\ntest listbox-3.36 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete {} 2\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el3 el4 el5 el6 el7}\ntest listbox-3.37 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete {} {}\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el0 el1 el2 el3 el4 el5 el6 el7}\ntest listbox-3.38 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete 2 end\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el0 el1}\ntest listbox-3.39 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete 5 20\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el0 el1 el2 el3 el4}\ntest listbox-3.40 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete end 20\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el0 el1 el2 el3 el4 el5 el6}\ntest listbox-3.41 {ListboxWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    .l2 delete 8 20\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {el0 el1 el2 el3 el4 el5 el6 el7}\ntest listbox-3.42 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get\n} -returnCodes error -result {wrong # args: should be \".l get firstIndex ?lastIndex?\"}\ntest listbox-3.43 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get a b c\n} -returnCodes error -result {wrong # args: should be \".l get firstIndex ?lastIndex?\"}\ntest listbox-3.44 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get 2.4\n} -returnCodes error -result {bad listbox index \"2.4\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.45 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get end bogus\n} -returnCodes error -result {bad listbox index \"bogus\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.46 {ListboxWidgetCmd procedure, \"get\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7\n    list [.l2 get 0] [.l2 get 3] [.l2 get end]\n} -cleanup {\n    destroy .l2\n} -result {el0 el3 el7}\ntest listbox-3.47 {ListboxWidgetCmd procedure, \"get\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    list [.l2 get 0] [.l2 get end]\n} -cleanup {\n    destroy .l2\n} -result {{} {}}\ntest listbox-3.48 {ListboxWidgetCmd procedure, \"get\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el0 el1 el2 \"two words\" el4 el5 el6 el7\n    .l2 get 3 end\n} -cleanup {\n    destroy .l2\n} -result {{two words} el4 el5 el6 el7}\ntest listbox-3.49 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get {}\n} -result {}\ntest listbox-3.50 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get {} {}\n} -result {}\ntest listbox-3.51 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get {} 3\n} -result {el0 el1 el2 el3}\ntest listbox-3.52 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get 12 end\n} -result {el12 el13 el14 el15 el16 el17}\ntest listbox-3.53 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get 12 20\n} -result {el12 el13 el14 el15 el16 el17}\ntest listbox-3.54 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get end\n} -result {el17}\ntest listbox-3.55 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get 30\n} -result {}\ntest listbox-3.56 {ListboxWidgetCmd procedure, \"get\" option} -body {\n    .l get 30 35\n} -result {}\ntest listbox-3.57 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index\n} -returnCodes error -result {wrong # args: should be \".l index index\"}\ntest listbox-3.58 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index a b\n} -returnCodes error -result {wrong # args: should be \".l index index\"}\ntest listbox-3.59 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index @\n} -returnCodes error -result {bad listbox index \"@\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.60 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index 2\n} -result 2\ntest listbox-3.61 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    expr {[.l index {}]<0}\n} -result 1\ntest listbox-3.62 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index end\n} -result 18\ntest listbox-3.63 {ListboxWidgetCmd procedure, \"index\" option} -body {\n    .l index 34\n} -result 18\ntest listbox-3.64 {ListboxWidgetCmd procedure, \"insert\" option} -body {\n    .l insert\n} -returnCodes error -result {wrong # args: should be \".l insert index ?element ...?\"}\ntest listbox-3.65 {ListboxWidgetCmd procedure, \"insert\" option} -body {\n    .l insert badIndex\n} -returnCodes error -result {bad listbox index \"badIndex\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.66 {ListboxWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c d e\n    .l2 insert 3 x y z\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {a b c x y z d e}\ntest listbox-3.67 {ListboxWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c\n    .l2 insert 0 x\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {x a b c}\ntest listbox-3.68 {ListboxWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c\n    .l2 insert end x\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {a b c x}\ntest listbox-3.69 {ListboxWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c\n    .l2 insert 43 x\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result {a b c x}\ntest listbox-3.70 {ListboxWidgetCmd procedure, \"nearest\" option} -body {\n    .l nearest\n} -returnCodes error -result {wrong # args: should be \".l nearest y\"}\ntest listbox-3.71 {ListboxWidgetCmd procedure, \"nearest\" option} -body {\n    .l nearest a b\n} -returnCodes error -result {wrong # args: should be \".l nearest y\"}\ntest listbox-3.72 {ListboxWidgetCmd procedure, \"nearest\" option} -body {\n    .l nearest 20p\n} -returnCodes error -result {expected integer but got \"20p\"}\ntest listbox-3.73 {ListboxWidgetCmd procedure, \"nearest\" option} -body {\n    .l yview 3\n    .l nearest 1000\n} -result 7\ntest listbox-3.74 {ListboxWidgetCmd procedure, \"scan\" option} -body {\n    .l scan a b\n} -returnCodes error -result {wrong # args: should be \".l scan mark|dragto x y\"}\ntest listbox-3.75 {ListboxWidgetCmd procedure, \"scan\" option} -body {\n    .l scan a b c d\n} -returnCodes error -result {wrong # args: should be \".l scan mark|dragto x y\"}\ntest listbox-3.76 {ListboxWidgetCmd procedure, \"scan\" option} -body {\n    .l scan foo bogus 2\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest listbox-3.77 {ListboxWidgetCmd procedure, \"scan\" option} -body {\n    .l scan foo 2 2.3\n} -returnCodes error -result {expected integer but got \"2.3\"}\ntest listbox-3.78 {ListboxWidgetCmd procedure, \"scan\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geom .t +0+0\n    listbox .t.l -width 10 -height 5\n    .t.l insert 0 \"Short\" \"Somewhat longer\" \"Really, quite a whole lot longer than can possibly fit on the screen\" \"Short\" a b c d e f g h i j\n    pack .t.l\n    update\n    .t.l scan mark 100 140\n    .t.l scan dragto 90 137\n    update\n    list [format {%.6g %.6g} {*}[.t.l xview]] [format {%.6g %.6g} {*}[.t.l yview]]\n} -cleanup {\n    destroy .t\n} -result {{0.249364 0.427481} {0.0714286 0.428571}}\ntest listbox-3.79 {ListboxWidgetCmd procedure, \"scan\" option} -body {\n    .l scan foo 2 4\n} -returnCodes error -result {bad option \"foo\": must be dragto or mark}\ntest listbox-3.80 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l see\n} -returnCodes error -result {wrong # args: should be \".l see index\"}\ntest listbox-3.81 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l see a b\n} -returnCodes error -result {wrong # args: should be \".l see index\"}\ntest listbox-3.82 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l see gorp\n} -returnCodes error -result {bad listbox index \"gorp\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.83 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 7\n    .l index @0,0\n} -result 7\ntest listbox-3.84 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 11\n    .l index @0,0\n} -result 7\ntest listbox-3.85 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 6\n    .l index @0,0\n} -result 6\ntest listbox-3.86 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 5\n    .l index @0,0\n} -result 3\ntest listbox-3.87 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 12\n    .l index @0,0\n} -result 8\ntest listbox-3.88 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 13\n    .l index @0,0\n} -result 11\ntest listbox-3.89 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see {}\n    .l index @0,0\n} -result 0\ntest listbox-3.90 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see end\n    .l index @0,0\n} -result 13\ntest listbox-3.91 {ListboxWidgetCmd procedure, \"see\" option} -body {\n    .l yview 7\n    .l see 322\n    .l index @0,0\n} -result 13\ntest listbox-3.92 {ListboxWidgetCmd procedure, \"see\" option, partial last line} -body {\n    mkPartial\n    .partial.l see 4\n    .partial.l index @0,0\n} -result 1\ntest listbox-3.93 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l select a\n} -returnCodes error -result {wrong # args: should be \".l selection option index ?index?\"}\ntest listbox-3.94 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l select a b c d\n} -returnCodes error -result {wrong # args: should be \".l selection option index ?index?\"}\ntest listbox-3.95 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection a bogus\n} -returnCodes error -result {bad listbox index \"bogus\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.96 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection a 0 lousy\n} -returnCodes error -result {bad listbox index \"lousy\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.97 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection anchor 0 0\n} -returnCodes error -result {wrong # args: should be \".l selection anchor index\"}\ntest listbox-3.98 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    list [.l selection anchor 5; .l index anchor] \\\n\t    [.l selection anchor 0; .l index anchor]\n} -result {5 0}\ntest listbox-3.99 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection anchor {}\n    .l index anchor\n} -result 0\ntest listbox-3.100 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection anchor end\n    .l index anchor\n} -result 17\ntest listbox-3.101 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection anchor 44\n    .l index anchor\n} -result 17\ntest listbox-3.102 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection clear 0 end\n    .l selection set 2 8\n    .l selection clear 3 4\n    .l curselection\n} -result {2 5 6 7 8}\ntest listbox-3.103 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection includes 0 0\n} -returnCodes error -result {wrong # args: should be \".l selection includes index\"}\ntest listbox-3.104 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection clear 0 end\n    .l selection set 2 8\n    .l selection clear 4\n    list [.l selection includes 3] [.l selection includes 4] \\\n\t    [.l selection includes 5]\n} -result {1 0 1}\ntest listbox-3.105 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection set 0 end\n    .l selection includes {}\n} -result 0\ntest listbox-3.106 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection clear 0 end\n    .l selection set end\n    .l selection includes end\n} -result 1\ntest listbox-3.107 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection set 0 end\n    .l selection includes 44\n} -result 0\ntest listbox-3.108 {ListboxWidgetCmd procedure, \"selection\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 selection includes 0\n} -cleanup {\n    destroy .l2\n} -result 0\ntest listbox-3.109 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection clear 0 end\n    .l selection set 2\n    .l selection set 5 7\n    .l curselection\n} -result {2 5 6 7}\ntest listbox-3.110 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection clear 0 end\n    .l selection set 2\n    .l selection set 5 7\n    .l selection set 5 7\n    .l curselection\n} -result {2 5 6 7}\ntest listbox-3.111 {ListboxWidgetCmd procedure, \"selection\" option} -body {\n    .l selection badOption 0 0\n} -returnCodes error -result {bad option \"badOption\": must be anchor, clear, includes, or set}\ntest listbox-3.112 {ListboxWidgetCmd procedure, \"size\" option} -body {\n    .l size a\n} -returnCodes error -result {wrong # args: should be \".l size\"}\ntest listbox-3.113 {ListboxWidgetCmd procedure, \"size\" option} -body {\n    .l size\n} -result 18\ntest listbox-3.114 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0 1}\ntest listbox-3.115 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2 -width 10 -height 5 -font $fixed\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    pack .l2\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0 1}\n\ntest listbox-3.116 {ListboxWidgetCmd procedure, \"xview\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 insert 1 \"0123456789a123456789b123456789c123456789d123456789\"\n    .l2 xview 4\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0.08 0.28}\ntest listbox-3.117 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l xview foo\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest listbox-3.118 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l xview zoom a b\n} -returnCodes error -result {unknown option \"zoom\": must be moveto or scroll}\ntest listbox-3.119 {ListboxWidgetCmd procedure, \"xview\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 insert 1 \"0123456789a123456789b123456789c123456789d123456789\"\n    .l xview 0\n    .l2 xview moveto .4\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0.4 0.6}\ntest listbox-3.120 {ListboxWidgetCmd procedure, \"xview\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 insert 1 \"0123456789a123456789b123456789c123456789d123456789\"\n    .l2 xview 0\n    .l2 xview scroll 2 units\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0.04 0.24}\ntest listbox-3.121 {ListboxWidgetCmd procedure, \"xview\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 insert 1 \"0123456789a123456789b123456789c123456789d123456789\"\n    .l2 xview 30\n    .l2 xview scroll -1 pages\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0.44 0.64}\ntest listbox-3.122 {ListboxWidgetCmd procedure, \"xview\" option} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 insert 1 \"0123456789a123456789b123456789c123456789d123456789\"\n    .l2 configure -width 1\n    update\n    .l2 xview 30\n    .l2 xview scroll -4 pages\n    update\n    format {%.6g %.6g} {*}[.l2 xview]\n} -cleanup {\n    destroy .l2\n} -result {0.52 0.54}\ntest listbox-3.123 {ListboxWidgetCmd procedure, \"yview\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    pack  .l2\n    update\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0 1}\ntest listbox-3.124 {ListboxWidgetCmd procedure, \"yview\" option} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 el1\n    pack  .l2\n    update\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0 1}\n\ntest listbox-3.125 {ListboxWidgetCmd procedure, \"yview\" option} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 yview 4\n    update\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0.2 0.45}\ntest listbox-3.126 {ListboxWidgetCmd procedure, \"yview\" option, partial last line} -setup {\n    destroy .l\n    listbox .l -width 10 -height 5 -font $fixed\n    pack .l\n    update\n} -body {\n    .l insert 0 a b c d e f g h i j k l m n o p q r s t\n    mkPartial\n    format {%.6g %.6g} {*}[.partial.l yview]\n} -cleanup {\n    destroy .l\n} -result {0 0.266667}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-3.127 - 3.137\n#\ndestroy .l\nlistbox .l -width 20 -height 5 -bd 4 -highlightthickness 1 -selectborderwidth 2\npack .l\n.l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11 el12 el13 el14 \\\n\tel15 el16 el17\nupdate\n\ntest listbox-3.127 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l yview foo\n} -returnCodes error -result {bad listbox index \"foo\": must be active, anchor, end, @x,y, or an index}\ntest listbox-3.128 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l yview foo a b\n} -returnCodes error -result {unknown option \"foo\": must be moveto or scroll}\ntest listbox-3.129 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 yview 0\n    .l2 yview moveto .31\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0.3 0.55}\ntest listbox-3.130 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 yview 2\n    .l2 yview scroll 2 pages\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0.4 0.65}\ntest listbox-3.131 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 yview 10\n    .l2 yview scroll -3 units\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0.35 0.6}\ntest listbox-3.132 {ListboxWidgetCmd procedure, \"xview\" option} -setup {\n    destroy .l2\n    listbox .l2 -width 10 -height 5 -font $fixed\n    pack .l2\n    update\n} -body {\n    .l2 insert 0 a b c d e f g h i j k l m n o p q r s t\n    .l2 configure -height 2\n    update\n    .l2 yview 15\n    .l2 yview scroll -4 pages\n    format {%.6g %.6g} {*}[.l2 yview]\n} -cleanup {\n    destroy .l2\n} -result {0.55 0.65}\ntest listbox-3.133 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l whoknows\n} -returnCodes error -result {bad option \"whoknows\": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}\ntest listbox-3.134 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l c\n} -returnCodes error -result {ambiguous option \"c\": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}\ntest listbox-3.135 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l in\n} -returnCodes error -result {ambiguous option \"in\": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}\ntest listbox-3.136 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l s\n} -returnCodes error -result {ambiguous option \"s\": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}\ntest listbox-3.137 {ListboxWidgetCmd procedure, \"xview\" option} -body {\n    .l se\n} -returnCodes error -result {ambiguous option \"se\": must be activate, bbox, cget, configure, curselection, delete, get, index, insert, itemcget, itemconfigure, nearest, scan, see, selection, size, xview, or yview}\n\n# No tests for DestroyListbox:  I can't come up with anything to test\n# in this procedure.\n\n\ntest listbox-4.1 {ConfigureListbox procedure} -constraints {\n\tfonts\n} -setup {\n    deleteWindows\n    destroy .l\n    listbox .l -setgrid 1 -width 25 -height 15\n    pack .l\n    update\n} -body {\n    update\n    set x [getsize .]\n    .l configure -setgrid 0\n    update\n    list $x [getsize .]\n} -cleanup {\n    deleteWindows\n} -result {25x15 185x263}\n\n#\n# COMMON TEST CLEANUP\n#\nresetGridInfo\n\ntest listbox-4.2 {ConfigureListbox procedure} -setup {\n    deleteWindows\n    destroy .l\n    listbox .l -setgrid 1 -width 25 -height 15\n    pack .l\n    update\n} -body {\n    .l configure -highlightthickness -3\n    .l cget -highlightthickness\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected screen distance but got \"-3\"}\ntest listbox-4.3 {ConfigureListbox procedure} -setup {\n    deleteWindows\n    destroy .l\n    listbox .l -setgrid 1 -width 25 -height 15\n    pack .l\n    update\n} -body {\n    .l configure -exportselection 0\n    .l delete 0 end\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8\n    .l selection set 3 5\n    .l configure -exportselection 1\n    selection get\n} -cleanup {\n    deleteWindows\n} -result {el3\nel4\nel5}\ntest listbox-4.4 {ConfigureListbox procedure} -setup {\n    deleteWindows\n    listbox .l -setgrid 1 -width 25 -height 15\n    pack .l\n    update\n} -body {\n    entry .e\n    .e insert 0 abc\n    .e select from 0\n    .e select to 2\n    .l configure -exportselection 0\n    .l delete 0 end\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8\n    .l selection set 3 5\n    .l selection clear 3 5\n    .l configure -exportselection 1\n    list [selection own] [selection get]\n} -cleanup {\n    deleteWindows\n} -result {.e ab}\ntest listbox-4.5 {-exportselection option} -setup {\n    deleteWindows\n    listbox .l -setgrid 1 -width 25 -height 15\n    pack .l\n    update\n} -body {\n    selection clear .\n    .l configure -exportselection 1\n    .l delete 0 end\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8\n    .l selection set 1 1\n    set x {}\n    lappend x [catch {selection get} msg] $msg [.l curselection]\n    .l config -exportselection 0\n    lappend x [catch {selection get} msg] $msg [.l curselection]\n    .l selection clear 0 end\n    lappend x [catch {selection get} msg] $msg [.l curselection]\n    .l selection set 1 3\n    lappend x [catch {selection get} msg] $msg [.l curselection]\n    .l config -exportselection 1\n    lappend x [catch {selection get} msg] $msg [.l curselection]\n} -cleanup {\n    deleteWindows\n} -result {0 el1 1 1 {PRIMARY selection doesn't exist or form \"STRING\" not defined} 1 1 {PRIMARY selection doesn't exist or form \"STRING\" not defined} {} 1 {PRIMARY selection doesn't exist or form \"STRING\" not defined} {1 2 3} 0 {el1\nel2\nel3} {1 2 3}}\ntest listbox-4.6 {ConfigureListbox procedure} -constraints {\n\tfonts\n} -setup {\n    deleteWindows\n} -body {\n\n    # The following code (reset geometry, withdraw, etc.) is necessary\n    # to reset the state of some window managers like olvwm under\n    # SunOS 4.1.3.\n\n    wm geom . 300x300\n    update\n    wm geom . {}\n    wm withdraw .\n    listbox .l2 -font $fixed -width 15 -height 20\n    pack .l2\n    update\n    wm deiconify .\n    set x [getsize .]\n    .l2 configure -setgrid 1\n    update\n    list $x [getsize .]\n} -cleanup {\n    deleteWindows\n} -result {115x328 15x20}\ntest listbox-4.7 {ConfigureListbox procedure} -setup {\n    deleteWindows\n} -body {\n    wm withdraw .\n    listbox .l2 -font $fixed -width 30 -height 20 -setgrid 1\n    wm geom . +25+25\n    pack .l2\n    update\n    wm deiconify .\n    set result [getsize .]\n    wm geom . 26x15\n    update\n    lappend result [getsize .]\n    .l2 configure -setgrid 1\n    update\n    lappend result [getsize .]\n} -cleanup {\n    deleteWindows\n    wm geom . {}\n} -result {30x20 26x15 26x15}\n\n#\n# COMMON TEST CLEANUP\n#\nresetGridInfo\n\ntest listbox-4.8 {ConfigureListbox procedure} -setup {\n    destroy .l2\n} -body {\n    listbox .l2 -width 15 -height 20 -xscrollcommand \"record x\" \\\n\t    -yscrollcommand \"record y\"\n    pack .l2\n    update\n    .l2 configure -fg black\n    set log {}\n    update\n    set log\n} -cleanup {\n    destroy .l2\n} -result {{y 0 1} {x 0 1}}\ntest listbox-4.9 {ConfigureListbox procedure, -listvar} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result [list a b c d]\ntest listbox-4.10 {ConfigureListbox, no listvar -> existing listvar} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2\n    .l2 insert end 1 2 3 4\n    .l2 configure -listvar x\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result [list a b c d]\ntest listbox-4.11 {ConfigureListbox procedure, listvar -> no listvar} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 configure -listvar {}\n    .l2 insert end 1 2 3 4\n    list $x [.l2 get 0 end]\n} -cleanup {\n    destroy .l2\n} -result [list [list a b c d] [list a b c d 1 2 3 4]]\ntest listbox-4.12 {ConfigureListbox procedure, listvar -> different listvar} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    set y [list 1 2 3 4]\n    listbox .l2\n    .l2 configure -listvar x\n    .l2 configure -listvar y\n    .l2 insert end 5 6 7 8\n    list $x $y\n} -cleanup {\n    destroy .l2\n} -result [list [list a b c d] [list 1 2 3 4 5 6 7 8]]\ntest listbox-4.13 {ConfigureListbox, no listvar -> non-existant listvar} -setup {\n    destroy .l2\n} -body {\n    catch {unset x}\n    listbox .l2\n    .l2 insert end a b c d\n    .l2 configure -listvar x\n    set x\n} -cleanup {\n    destroy .l2\n} -result [list a b c d]\ntest listbox-4.14 {ConfigureListbox, non-existant listvar} -setup {\n    destroy .l2\n} -body {\n    catch {unset x}\n    listbox .l2 -listvar x\n    list [info exists x] $x\n} -cleanup {\n    destroy .l2\n} -result [list 1 {}]\ntest listbox-4.15 {ConfigureListbox, listvar -> non-existant listvar} -setup {\n    destroy .l2\n} -body {\n    catch {unset y}\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 configure -listvar y\n    list [info exists y] $y\n} -cleanup {\n    destroy .l2\n} -result [list 1 [list a b c d]]\ntest listbox-4.16 {ConfigureListbox, listvar -> same listvar} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 configure -listvar x\n    set x\n} -cleanup {\n    destroy .l2\n} -result [list a b c d]\ntest listbox-4.17 {ConfigureListbox, no listvar -> no listvar} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c d\n    .l2 configure -listvar {}\n    .l2 get 0 end\n} -cleanup {\n    destroy .l2\n} -result [list a b c d]\ntest listbox-4.18 {ConfigureListbox, no listvar -> bad listvar} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert end a b c d\n    set x \"this is a \\\" bad list\"\n    catch {.l2 configure -listvar x} result\n    list [.l2 get 0 end] [.l2 cget -listvar] $result\n} -cleanup {\n    destroy .l2\n} -result [list [list a b c d] {} \\\n\t\"unmatched open quote in list: invalid -listvariable value\"]\ntest listbox-4.19 {ConfigureListbox, no listvar -> bad non-existent listvar} -setup {\n    destroy .l2\n} -body {\n    unset -nocomplain ::foo\n    listbox .l2 -listvar foo\n    .l2 insert end a b c d\n    catch {.l2 configure -listvar ::zoo::bar::foo} result\n    list [.l2 get 0 end] [.l2 cget -listvar] $foo $result\n} -cleanup {\n    destroy .l2\n} -result [list [list a b c d] foo [list a b c d] \\\n\t{can't set \"::zoo::bar::foo\": parent namespace doesn't exist}]\n\n\n# No tests for DisplayListbox:  I don't know how to test this procedure.\n\ntest listbox-5.1 {ListboxComputeGeometry procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 15 -height 20\n    pack .l\n    list [winfo reqwidth .l] [winfo reqheight .l]\n} -result {115 328}\ntest listbox-5.2 {ListboxComputeGeometry procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 0 -height 10\n    pack .l\n    update\n    list [winfo reqwidth .l] [winfo reqheight .l]\n} -result {17 168}\ntest listbox-5.3 {ListboxComputeGeometry procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 0 -height 10 -bd 3\n    .l insert 0 Short \"Really much longer\" Longer\n    pack .l\n    update\n    list [winfo reqwidth .l] [winfo reqheight .l]\n} -result {138 170}\ntest listbox-5.4 {ListboxComputeGeometry procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 10 -height 0\n    pack .l\n    update\n    list [winfo reqwidth .l] [winfo reqheight .l]\n} -result {80 24}\ntest listbox-5.5 {ListboxComputeGeometry procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 10 -height 0 -highlightthickness 0\n    .l insert 0 Short \"Really much longer\" Longer\n    pack .l\n    update\n    list [winfo reqwidth .l] [winfo reqheight .l]\n} -result {76 52}\ntest listbox-5.6 {ListboxComputeGeometry procedure} -setup {\n    destroy .l\n} -body {\n    # If \"0\" in selected font had 0 width, caused divide-by-zero error.\n\n    pack [listbox .l -font {{open look glyph}}]\n    update\n} -cleanup {\n    destroy .l\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-6.* and listbox-7.*\ndestroy .l\nlistbox .l -height 2 -xscrollcommand \"record x\" -yscrollcommand \"record y\"\npack .l\nupdate\n\ntest listbox-6.1 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert end a b c d\n    .l insert 5 x y z\n    .l insert 2 A\n    .l insert 0 q r s\n    .l get 0 end\n} -result {q r s a b A c d x y z}\ntest listbox-6.2 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 2\n    .l insert 2 A B\n    .l index anchor\n} -result 4\ntest listbox-6.3 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 2\n    .l insert 3 A B\n    .l index anchor\n} -result 2\ntest listbox-6.4 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l insert 2 A B\n    .l index @0,0\n} -result 5\ntest listbox-6.5 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l insert 3 A B\n    .l index @0,0\n} -result 3\ntest listbox-6.6 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 5\n    .l insert 5 A B\n    .l index active\n} -result 7\ntest listbox-6.7 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 5\n    .l insert 6 A B\n    .l index active\n} -result 5\ntest listbox-6.8 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c\n    .l index active\n} -result 2\ntest listbox-6.9 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0\n    .l index active\n} -result 0\ntest listbox-6.10 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b \"two words\"  c d e f g h i j\n    update\n    set log {}\n    .l insert 0 word\n    update\n    set log\n} -result {{y 0 0.166667}}\ntest listbox-6.11 {InsertEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b \"two words\"  c d e f g h i j\n    update\n    set log {}\n    .l insert 0 \"much longer entry\"\n    update\n    set log\n} -result {{y 0 0.166667} {x 0 1}}\ntest listbox-6.12 {InsertEls procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n} -body {\n    listbox .l2 -width 0 -height 0\n    pack .l2 -side top\n    .l2 insert 0 a b \"two words\"  c d\n    set x {}\n    lappend x [winfo reqwidth .l2] [winfo reqheight .l2]\n    .l2 insert 0 \"much longer entry\"\n    lappend x [winfo reqwidth .l2] [winfo reqheight .l2]\n} -cleanup {\n    destroy .l2\n} -result {80 93 122 110}\ntest listbox-6.13 {InsertEls procedure, check -listvar update} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 insert 0 1 2 3 4\n    set x\n} -cleanup {\n    destroy .l2\n} -result [list 1 2 3 4 a b c d]\ntest listbox-6.14 {InsertEls procedure, check selection update} -setup {\n    destroy .l2\n} -body {\n    listbox .l2\n    .l2 insert 0 0 1 2 3 4\n    .l2 selection set 2 4\n    .l2 insert 0 a\n    .l2 curselection\n} -cleanup {\n    destroy .l2\n} -result [list 3 4 5]\ntest listbox-6.15 {InsertEls procedure, lost namespaced listvar} -body {\n    destroy .l2\n    namespace eval test { variable foo {a b} }\n    listbox .l2 -listvar ::test::foo\n    namespace delete test\n    .l2 insert end c d\n    .l2 delete end\n    .l2 insert end e f\n    catch {set ::test::foo} result\n    list [.l2 get 0 end] [.l2 cget -listvar] $result\n} -cleanup {\n    destroy .l2\n} -result [list [list a b c e f] ::test::foo \\\n\t{can't read \"::test::foo\": no such variable}]\n\n\ntest listbox-7.1 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection set 1 6\n    .l delete 4 3\n    list [.l size] [selection get]\n} -result {10 {b\nc\nd\ne\nf\ng}}\ntest listbox-7.2 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection set 3 6\n    .l delete 4 4\n    list [.l size] [.l get 4] [.l curselection]\n} -result {9 f {3 4 5}}\ntest listbox-7.3 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l delete 0 3\n    list [.l size] [.l get 0] [.l get 1]\n} -result {6 e f}\ntest listbox-7.4 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l delete 8 1000\n    list [.l size] [.l get 7]\n} -result {8 h}\ntest listbox-7.5 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 2\n    .l delete 0 1\n    .l index anchor\n} -result 0\ntest listbox-7.6 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 2\n    .l delete 2\n    .l index anchor\n} -result 2\ntest listbox-7.7 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 4\n    .l delete 2 5\n    .l index anchor\n} -result 2\ntest listbox-7.8 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l selection anchor 3\n    .l delete 4 5\n    .l index anchor\n} -result 3\ntest listbox-7.9 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l delete 1 2\n    .l index @0,0\n} -result 1\ntest listbox-7.10 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l delete 3 4\n    .l index @0,0\n} -result 3\ntest listbox-7.11 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l delete 4 6\n    .l index @0,0\n} -result 3\ntest listbox-7.12 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    .l delete 3 end\n    .l index @0,0\n} -result 1\ntest listbox-7.13 {DeleteEls procedure, updating view with partial last line} -body {\n    mkPartial\n    .partial.l yview 8\n    update\n    .partial.l delete 10 13\n    .partial.l index @0,0\n} -result 7\ntest listbox-7.14 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 6\n    .l delete 3 4\n    .l index active\n} -result 4\ntest listbox-7.15 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 6\n    .l delete 5 7\n    .l index active\n} -result 5\ntest listbox-7.16 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 6\n    .l delete 5 end\n    .l index active\n} -result 4\ntest listbox-7.17 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j\n    .l activate 6\n    .l delete 0 end\n    .l index active\n} -result 0\ntest listbox-7.18 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c \"two words\" d e f g h i j\n    update\n    set log {}\n    .l delete 4 6\n    update\n    set log\n} -result {{y 0 0.25}}\ntest listbox-7.19 {DeleteEls procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c \"two words\" d e f g h i j\n    update\n    set log {}\n    .l delete 3\n    update\n    set log\n} -result {{y 0 0.2} {x 0 1}}\ntest listbox-7.20 {DeleteEls procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l2\n} -body {\n    listbox .l2 -width 0 -height 0\n    pack .l2 -side top\n    .l2 insert 0 a b \"two words\" c d e f g\n    set x {}\n    lappend x [winfo reqwidth .l2] [winfo reqheight .l2]\n    .l2 delete 2 4\n    lappend x [winfo reqwidth .l2] [winfo reqheight .l2]\n} -result {80 144 17 93}\ntest listbox-7.21 {DeleteEls procedure, check -listvar update} -setup {\n    destroy .l2\n} -body {\n    set x [list a b c d]\n    listbox .l2 -listvar x\n    .l2 delete 0 1\n    set x\n} -result [list c d]\n\n\ntest listbox-8.1 {ListboxEventProc procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -setgrid 1\n    pack .l\n    update\n    set x [getsize .]\n    destroy .l\n    list $x [getsize .] [winfo exists .l] [info command .l]\n} -cleanup {\n    destroy .l\n} -result {20x10 150x178 0 {}}\n\n#\n# COMMON TEST CLEANUP\n#\nresetGridInfo\n\ntest listbox-8.2 {ListboxEventProc procedure} -constraints {\n\tfonts\n} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5 -width 10\n    .l insert 0 a b c \"A string that is very very long\" d e f g h i j k\n    pack .l\n    update\n    place .l -width 50 -height 80\n    update\n    list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]\n} -cleanup {\n    destroy .l\n} -result {{0 0.222222} {0 0.333333}}\ntest listbox-8.3 {ListboxEventProc procedure} -setup {\n    deleteWindows\n} -body {\n    listbox .l1 -bg #543210\n    rename .l1 .l2\n    set x {}\n    lappend x [winfo children .]\n    lappend x [.l2 cget -bg]\n    destroy .l1\n    lappend x [info command .l*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {.l1 #543210 {} {}}\n\n\ntest listbox-9.1 {ListboxCmdDeletedProc procedure} -setup {\n    deleteWindows\n} -body {\n    listbox .l1\n    rename .l1 {}\n    list [info command .l*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest listbox-9.2 {ListboxCmdDeletedProc procedure, disabling -setgrid} -constraints {\n\tfonts\n} -setup {\n    destroy .top\n} -body {\n    toplevel .top\n    wm geom .top +0+0\n    listbox .top.l -setgrid 1 -width 20 -height 10\n    pack .top.l\n    update\n    set x [getsize .top]\n    rename .top.l {}\n    update\n    lappend x [getsize .top]\n} -cleanup {\n    destroy .top\n} -result {20x10 150x178}\n\ntest listbox-10.1 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    .l activate 3\n    update\n    list [.l activate 3; .l index active] [.l activate 6; .l index active]\n} -cleanup {\n    destroy .l\n} -result {3 6}\ntest listbox-10.2 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    .l selection anchor 2\n    update\n    .l index anchor\n} -cleanup {\n    destroy .l\n} -result 2\ntest listbox-10.3 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    .l insert end A B C D E\n    .l selection anchor end\n    update\n    .l delete 12 end\n    list [.l index anchor] [.l index end]\n} -cleanup {\n    destroy .l\n} -result {12 12}\ntest listbox-10.4 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index a\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"a\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.5 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index end\n} -cleanup {\n    destroy .l\n} -result 12\ntest listbox-10.6 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l get end\n} -cleanup {\n    destroy .l\n} -result {el11}\ntest listbox-10.7 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    .l delete 0 end\n    update\n    .l index end\n} -cleanup {\n    destroy .l\n} -result 0\ntest listbox-10.8 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.9 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @foo\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@foo\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.10 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @1x3\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@1x3\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.11 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @1,\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@1,\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.12 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @1,foo\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@1,foo\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.13 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index @1,2x\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"@1,2x\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.14 {GetListboxIndex procedure} -constraints {\n    fonts\n} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    list [.l index @5,57] [.l index @5,58]\n} -cleanup {\n    .l delete 0 end\n} -cleanup {\n    destroy .l\n} -result {3 3}\ntest listbox-10.15 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index 1xy\n} -cleanup {\n    destroy .l\n} -returnCodes error -result {bad listbox index \"1xy\": must be active, anchor, end, @x,y, or an index}\ntest listbox-10.16 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index 3\n} -cleanup {\n    destroy .l\n} -result 3\ntest listbox-10.17 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l index 20\n} -cleanup {\n    destroy .l\n} -result 12\ntest listbox-10.18 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    .l get 20\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-10.19 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    update\n    expr {[.l index {}]<0}\n} -cleanup {\n    destroy .l\n} -result 1\ntest listbox-10.20 {GetListboxIndex procedure} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11\n    .l delete 0 end\n    update\n    .l index 1\n} -cleanup {\n    destroy .l\n} -result 0\n\n\ntest listbox-11.1 {ChangeListboxView procedure, boundary conditions for index} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5\n    pack .l\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    set x [.l index @0,0]\n    .l yview {}\n    update\n    lappend x [.l index @0,0]\n} -cleanup {\n    destroy .l\n} -result {3 0}\ntest listbox-11.2 {ChangeListboxView procedure, boundary conditions for index} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5\n    pack .l\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    set x [.l index @0,0]\n    .l yview 20\n    update\n    lappend x [.l index @0,0]\n} -cleanup {\n    destroy .l\n} -result {3 5}\ntest listbox-11.3 {ChangeListboxView procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5 -yscrollcommand \"record y\"\n    pack .l\n    .l insert 0 a b c d e f g h i j\n    update\n    set log {}\n    .l yview 2\n    update\n    list [format {%.6g %.6g} {*}[.l yview]] $log\n} -cleanup {\n    destroy .l\n} -result {{0.2 0.7} {{y 0.2 0.7}}}\ntest listbox-11.4 {ChangeListboxView procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5 -yscrollcommand \"record y\"\n    pack .l\n    .l insert 0 a b c d e f g h i j\n    update\n    set log {}\n    .l yview 8\n    update\n    list [format {%.6g %.6g} {*}[.l yview]] $log\n} -cleanup {\n    destroy .l\n} -result {{0.5 1} {{y 0.5 1}}}\ntest listbox-11.5 {ChangeListboxView procedure} -setup {\n    destroy .l\n} -body {\n    listbox .l -height 5 -yscrollcommand \"record y\"\n    pack .l\n    update\n    .l insert 0 a b c d e f g h i j\n    .l yview 3\n    update\n    set log {}\n    .l yview 3\n    update\n    list [format {%.6g %.6g} {*}[.l yview]] $log\n} -cleanup {\n    destroy .l\n} -result {{0.3 0.8} {}}\ntest listbox-11.6 {ChangeListboxView procedure, partial last line} -body {\n    mkPartial\n    .partial.l yview 13\n    .partial.l index @0,0\n} -cleanup {\n    destroy .l\n} -result 11\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-12.*\n#\ndestroy .l\nlistbox .l -font $fixed -xscrollcommand \"record x\" -width 10\n.l insert 0 0123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789\npack .l\nupdate\n\ntest listbox-12.1 {ChangeListboxOffset procedure} -constraints {\n\tfonts\n} -body {\n    set log {}\n    .l xview 99\n    update\n    list [format {%.6g %.6g} {*}[.l xview]] $log\n} -result {{0.9 1} {{x 0.9 1}}}\ntest listbox-12.2 {ChangeListboxOffset procedure} -constraints {\n\tfonts\n} -body {\n    set log {}\n    .l xview 99\n    .l xview moveto -.25\n    update\n    list [format {%.6g %.6g} {*}[.l xview]] $log\n} -result {{0 0.1} {{x 0 0.1}}}\ntest listbox-12.3 {ChangeListboxOffset procedure} -constraints {\n\tfonts\n} -body {\n    .l xview 10\n    update\n    set log {}\n    .l xview 10\n    update\n    list [format {%.6g %.6g} {*}[.l xview]] $log\n} -result {{0.1 0.2} {}}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-13.*\n#\ndestroy .l\nlistbox .l -font $fixed -width 10 -height 5\npack .l\n.l insert 0 a bb c d e f g h i j k l m n o p q r s\n.l insert 0 0123456789a123456789b123456789c123456789d123456789\nupdate\nset width [expr {[lindex [.l bbox 2] 2] - [lindex [.l bbox 1] 2]}]\nset height [expr {[lindex [.l bbox 2] 1] - [lindex [.l bbox 1] 1]}]\n\ntest listbox-13.1 {ListboxScanTo procedure} -constraints {\n\tfonts\n} -body {\n    .l yview 0\n    .l xview 0\n    .l scan mark 10 20\n    .l scan dragto [expr {10-$width}] [expr {20-$height}]\n    update\n    list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]\n} -result {{0.2 0.4} {0.5 0.75}}\ntest listbox-13.2 {ListboxScanTo procedure} -constraints {\n\tfonts\n} -body {\n    .l yview 5\n    .l xview 10\n    .l scan mark 10 20\n    .l scan dragto 20 40\n    update\n    set x [list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]]\n    .l scan dragto [expr {20-$width}] [expr {40-$height}]\n    update\n    lappend x [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]\n} -result {{0 0.2} {0 0.25} {0.2 0.4} {0.5 0.75}}\ntest listbox-13.3 {ListboxScanTo procedure} -constraints {\n\tfonts\n} -body {\n    .l yview moveto 1.0\n    .l xview moveto 1.0\n    .l scan mark 10 20\n    .l scan dragto 5 10\n    update\n    set x [list [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]]\n    .l scan dragto [expr {5+$width}] [expr {10+$height}]\n    update\n    lappend x [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]\n} -result {{0.8 1} {0.75 1} {0.6 0.8} {0.25 0.5}}\n\n\ntest listbox-14.1 {NearestListboxElement procedure, partial last line} -body {\n    mkPartial\n    .partial.l nearest [winfo height .partial.l]\n} -result 4\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-14.*\n#\ndestroy .l\nlistbox .l -font $fixed -width 20 -height 10\n.l insert 0 a b c d e f g h i j k l m n o p q r s t\n.l yview 4\npack .l\nupdate\n\ntest listbox-14.2 {NearestListboxElement procedure} -constraints {\n\tfonts\n} -body {\n    .l index @50,0\n} -result 4\ntest listbox-14.3 {NearestListboxElement procedure} -constraints {\n\tfonts\n} -body {\n    list [.l index @50,35] [.l index @50,36]\n} -result {5 6}\ntest listbox-14.4 {NearestListboxElement procedure} -constraints {\n\tfonts\n} -body {\n    .l index @50,200\n} -result 13\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-15.* 16.* and 17.*\n#\ndestroy .l\nlistbox .l -font $fixed -width 20 -height 10\npack .l\nupdate\n\ntest listbox-15.1 {ListboxSelect procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j k l m n o p\n    .l select set 2 4\n    .l select set 7 12\n    .l select clear 4 7\n    .l curselection\n} -result {2 3 8 9 10 11 12}\ntest listbox-15.2 {ListboxSelect procedure} -setup {\n    destroy .e\n} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f g h i j k l m n o p\n    entry .e\n    .e insert 0 \"This is some text\"\n    .e select from 0\n    .e select to 7\n    .l selection clear 2 4\n    set x [selection own]\n    .l selection set 3\n    list $x [selection own] [selection get]\n} -cleanup {\n    destroy .e\n} -result {.e .l d}\ntest listbox-15.3 {ListboxSelect procedure} -body {\n    .l delete 0 end\n    .l selection clear 0 end\n    .l select set 0 end\n    .l curselection\n} -result {}\ntest listbox-15.4 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set {} {}\n    .l curselection\n} -result {}\ntest listbox-15.5 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set {} 3\n    .l curselection\n} -result {0 1 2 3}\ntest listbox-15.6 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set 2 4\n    .l curselection\n} -result {2 3 4}\ntest listbox-15.7 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set 4 end\n    .l curselection\n} -result {4 5}\ntest listbox-15.8 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set 4 30\n    .l curselection\n} -result {4 5}\ntest listbox-15.9 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set end 30\n    .l curselection\n} -result 5\ntest listbox-15.10 {ListboxSelect procedure, boundary conditions for indices} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e f\n    .l select clear 0 end\n    .l select set 20 25\n    .l curselection\n} -result {}\n\n\ntest listbox-16.1 {ListboxFetchSelection procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c \"two words\" e f g h i \\\\ k l m n o p\n    .l selection set 2 4\n    .l selection set 9\n    .l selection set 11 12\n    selection get\n} -result \"c\\ntwo words\\ne\\n\\\\\\nl\\nm\"\ntest listbox-16.2 {ListboxFetchSelection procedure} -body {\n    .l delete 0 end\n    .l insert 0 a b c \"two words\" e f g h i \\\\ k l m n o p\n    .l selection set 3\n    selection get\n} -result \"two words\"\ntest listbox-16.3 {ListboxFetchSelection procedure, retrieve in several parts} -body {\n    set long \"This is quite a long string\\n\"\n    append long $long $long $long $long\n    append long $long $long $long $long\n    append long $long $long\n    .l delete 0 end\n    .l insert 0 1$long 2$long 3$long 4$long 5$long\n    .l selection set 0 end\n    set sel [selection get]\n    string compare 1$long\\n2$long\\n3$long\\n4$long\\n5$long $sel\n} -cleanup {\n    catch {unset long sel}\n} -result 0\n\n\ntest listbox-17.1 {ListboxLostSelection procedure} -setup {\n    destroy .e\n} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e\n    .l select set 0 end\n    entry .e\n    .e insert 0 \"This is some text\"\n    .e select from 0\n    .e select to 5\n    .l curselection\n} -cleanup {\n    destroy .e\n} -result {}\ntest listbox-17.2 {ListboxLostSelection procedure} -setup {\n    destroy .e\n} -body {\n    .l delete 0 end\n    .l insert 0 a b c d e\n    .l select set 0 end\n    .l configure -exportselection 0\n    entry .e\n    .e insert 0 \"This is some text\"\n    .e select from 0\n    .e select to 5\n    .l curselection\n} -cleanup {\n    destroy .e\n} -result {0 1 2 3 4}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-18.*\n#\ndestroy .l\nlistbox .l -font $fixed -width 10 -height 5\npack .l\nupdate\n\ntest listbox-18.1 {ListboxUpdateVScrollbar procedure} -body {\n    .l configure -yscrollcommand \"record y\"\n    set log {}\n    .l insert 0 a b c\n    update\n    .l insert end d e f g h\n    update\n    .l delete 0 end\n    update\n    set log\n} -result {{y 0 1} {y 0 0.625} {y 0 1}}\ntest listbox-18.2 {ListboxUpdateVScrollbar procedure, partial last line} -body {\n    mkPartial\n    .partial.l configure -yscrollcommand \"record y\"\n    set log {}\n    .partial.l yview 3\n    update\n    set log\n} -result {{y 0.2 0.466667}}\ntest listbox-18.3 {ListboxUpdateVScrollbar procedure} -body {\n    proc bgerror args {\n\t    global x errorInfo\n\t    set x [list $args $errorInfo]\n    }\n    .l configure -yscrollcommand gorp\n    .l insert 0 foo\n    update\n    set x\n} -cleanup {\n    rename bgerror {}\n} -result {{{invalid command name \"gorp\"}} {invalid command name \"gorp\"\n    while executing\n\"gorp 0.0 1.0\"\n    (vertical scrolling command executed by listbox)}}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-19.*\n#\ndestroy .l\nlistbox .l -font $fixed -width 10 -height 5\npack .l\nupdate\n\ntest listbox-19.1 {ListboxUpdateVScrollbar procedure} -constraints {\n\tfonts\n} -body {\n    .l configure -xscrollcommand \"record x\"\n    set log {}\n    .l insert 0 abc\n    update\n    .l insert 0 \"This is a much longer string...\"\n    update\n    .l delete 0 end\n    update\n    set log\n} -result {{x 0 1} {x 0 0.322581} {x 0 1}}\ntest listbox-19.2 {ListboxUpdateVScrollbar procedure} -body {\n    proc bgerror args {\n\t    global x errorInfo\n\t    set x [list $args $errorInfo]\n    }\n    .l configure -xscrollcommand bogus\n    .l insert 0 foo\n    update\n    set x\n} -result {{{invalid command name \"bogus\"}} {invalid command name \"bogus\"\n    while executing\n\"bogus 0.0 1.0\"\n    (horizontal scrolling command executed by listbox)}}\n\n\ntest listbox-20.1 {listbox vs hidden commands} -setup {\n    deleteWindows\n} -body {\n    set l [interp hidden]\n    listbox .l\n    interp hide {} .l\n    destroy .l\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 eq $res2}\n} -result 1\n\n\n# tests for ListboxListVarProc\ntest listbox-21.1 {ListboxListVarProc} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -listvar x\n    set x [list a b c d]\n    .l get 0 end\n} -cleanup {\n    destroy .l\n} -result [list a b c d]\ntest listbox-21.2 {ListboxListVarProc} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    unset x\n    set x\n} -cleanup {\n    destroy .l\n} -result [list a b c d]\ntest listbox-21.3 {ListboxListVarProc} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    .l configure -listvar {}\n    unset x\n    info exists x\n} -cleanup {\n    destroy .l\n} -result 0\ntest listbox-21.4 {ListboxListVarProc} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    lappend x e f g\n    .l size\n} -cleanup {\n    destroy .l\n} -result 7\ntest listbox-21.5 {ListboxListVarProc, test selection after listvar mod} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d e f g]\n    listbox .l -listvar x\n    .l selection set end\n    set x [list a b c d]\n    set x [list 0 1 2 3 4 5 6]\n    .l curselection\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-21.6 {ListboxListVarProc, test selection after listvar mod} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    .l selection set 3\n    lappend x e f g\n    .l curselection\n} -cleanup {\n    destroy .l\n} -result 3\ntest listbox-21.7 {ListboxListVarProc, test selection after listvar mod} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    .l selection set 0\n    set x [linsert $x 0 1 2 3 4]\n    .l curselection\n} -cleanup {\n    destroy .l\n} -result 0\ntest listbox-21.8 {ListboxListVarProc, test selection after listvar mod} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d]\n    listbox .l -listvar x\n    .l selection set 2\n    set x [list a b c]\n    .l curselection\n} -cleanup {\n    destroy .l\n} -result 2\ntest listbox-21.9 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {\n    destroy .l\n} -body {\n    set x {}\n    listbox .l -font $fixed -width 10 -xscrollcommand \"record x\" -listvar x\n    pack .l\n    update idletasks\n    set log {}\n    lappend x \"0000000000\"\n    update idletasks\n    lappend x \"00000000000000000000\"\n    update idletasks\n    set log\n} -cleanup {\n    destroy .l\n} -result [list {x 0 1} {x 0 0.5}]\ntest listbox-21.10 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -font $fixed -width 10 -xscrollcommand \"record x\" -listvar x\n    pack .l\n    update idletasks\n    set log {}\n    lappend x \"0000000000\"\n    update idletasks\n    lappend x \"00000000000000000000\"\n    update idletasks\n    set x [list \"0000000000\"]\n    update idletasks\n    set log\n} -cleanup {\n    destroy .l\n} -result [list {x 0 1} {x 0 0.5} {x 0 1}]\ntest listbox-21.11 {ListboxListVarProc, bad list} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -listvar x\n    set x [list a b c d]\n    catch {set x \"this is a \\\" bad list\"} result\n    set result\n} -cleanup {\n    destroy .l\n} -result {can't set \"x\": invalid listvar value}\ntest listbox-21.12 {ListboxListVarProc, cleanup item attributes} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d e f g]\n    listbox .l -listvar x\n    .l itemconfigure end -fg red\n    set x [list a b c d]\n    set x [list 0 1 2 3 4 5 6]\n    .l itemcget end -fg\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-21.12a {ListboxListVarProc, cleanup item attributes} -setup {\n    destroy .l\n} -body {\n    set x [list a b c d e f g]\n    listbox .l -listvar x\n    .l itemconfigure end -fg red\n    set x [list a b c d]\n    set x [list 0 1 2 3 4 5 6]\n    .l itemcget end -fg\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-21.13 {listbox item configurations and listvar based deletions} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -listvar x\n    .l insert end a b c\n    .l itemconfigure 1 -fg red\n    set x [list b c]\n    .l itemcget 1 -fg\n} -cleanup {\n    destroy .l\n} -result red\ntest listbox-21.14 {listbox item configurations and listvar based inserts} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -listvar x\n    .l insert end a b c\n    .l itemconfigure 0 -fg red\n    set x [list 1 2 3 4 a b c]\n    .l itemcget 0 -fg\n} -cleanup {\n    destroy .l\n} -result red\ntest listbox-21.15 {ListboxListVarProc, update vertical scrollbar} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -font $fixed -height 3 -yscrollcommand \"record y\" -listvar x\n    update\n    set log {}\n    pack .l\n    set timeout [after 500 {lappend log timeout3}]\n    vwait log\n    update\n    lappend x a b c d e f\n    vwait log\n    set log\n} -cleanup {\n    destroy .l\n    after cancel $timeout\n} -result [list {y 0 1} {y 0 0.5}]\ntest listbox-21.16 {ListboxListVarProc, update vertical scrollbar} -setup {\n    destroy .l\n} -body {\n    catch {unset x}\n    listbox .l -listvar x -height 3\n    pack .l\n    set x [list 0 1 2 3 4 5]\n    .l yview scroll 3 units\n    update\n    set result {}\n    lappend result [format {%.6g %.6g} {*}[.l yview]]\n    set x [lreplace $x 3 3]\n    set x [lreplace $x 3 3]\n    set x [lreplace $x 3 3]\n    update\n    lappend result [format {%.6g %.6g} {*}[.l yview]]\n    set result\n} -cleanup {\n    destroy .l\n} -result [list {0.5 1} {0 1}]\n\n\n# UpdateHScrollbar\ntest listbox-22.1 {UpdateHScrollbar} -setup {\n    destroy .l\n} -body {\n    listbox .l -font $fixed -width 10 -xscrollcommand \"record x\"\n    pack .l\n    update idletasks\n    set log {}\n    set timeout [after 500 {lappend log timeout4}]\n    .l insert end \"0000000000\"\n    vwait log\n    .l insert end \"00000000000000000000\"\n    vwait log\n    set log\n} -cleanup {\n    destroy .l\n    after cancel $timeout\n} -result [list {x 0 1} {x 0 0.5}]\n\n\n# ConfigureListboxItem\ntest listbox-23.1 {ConfigureListboxItem} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    catch {.l itemconfigure 0} result\n    set result\n} -cleanup {\n    destroy .l\n} -result {item number \"0\" out of range}\ntest listbox-23.2 {ConfigureListboxItem} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    .l itemconfigure 0\n} -cleanup {\n    destroy .l\n} -result [list {-background {} {} {} {}} \\\n\t{-bg -background} \\\n\t{-fg -foreground} \\\n\t{-foreground {} {} {} {}} \\\n\t{-selectbackground {} {} {} {}} \\\n\t{-selectforeground {} {} {} {}}]\ntest listbox-23.3 {ConfigureListboxItem, itemco shortcut} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    .l itemco 0 -background\n} -cleanup {\n    destroy .l\n} -result {-background {} {} {} {}}\ntest listbox-23.4 {ConfigureListboxItem, wrong num args} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a\n    catch {.l itemco} result\n    set result\n} -cleanup {\n    destroy .l\n} -result {wrong # args: should be \".l itemconfigure index ?-option value ...?\"}\ntest listbox-23.5 {ConfigureListboxItem, multiple calls} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    set i 0\n    foreach color {red orange yellow green blue white violet} {\n\t.l insert end $color\n\t.l itemconfigure $i -bg $color\n\tincr i\n    }\n    pack .l\n    update\n    list [.l itemcget 0 -bg] [.l itemcget 1 -bg] [.l itemcget 2 -bg] \\\n\t    [.l itemcget 3 -bg] [.l itemcget 4 -bg] [.l itemcget 5 -bg] \\\n\t    [.l itemcget 6 -bg]\n} -cleanup {\n    destroy .l\n} -result {red orange yellow green blue white violet}\n\n#\n# COMMON TEST SETUP\n#\n# For tests listbox-23.6 - 23.17\n#\ndestroy .l\nlistbox .l\n.l insert end a b c d\n\ntest listbox-23.6 {configuration options} -body {\n    .l itemconfigure 0 -background #ff0000\n    list [lindex [.l itemconfigure 0 -background] 4] [.l itemcget 0 -background]\n} -cleanup {\n    .l configure -background #ffffff\n} -result {{#ff0000} #ff0000}\ntest listbox-23.7 {configuration options} -body {\n    .l configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest listbox-23.8 {configuration options} -body {\n    .l itemconfigure 0 -bg #ff0000\n    list [lindex [.l itemconfigure 0 -bg] 4] [.l itemcget 0 -bg]\n} -cleanup {\n    .l configure -bg #ffffff\n} -result {{#ff0000} #ff0000}\ntest listbox-23.9 {configuration options} -body {\n    .l configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest listbox-23.10 {configuration options} -body {\n    .l itemconfigure 0 -fg #110022\n    list [lindex [.l itemconfigure 0 -fg] 4] [.l itemcget 0 -fg]\n} -cleanup {\n    .l configure -fg #000000\n} -result {{#110022} #110022}\ntest listbox-23.11 {configuration options} -body {\n    .l configure -fg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-23.12 {configuration options} -body {\n    .l itemconfigure 0 -foreground #110022\n    list [lindex [.l itemconfigure 0 -foreground] 4] [.l itemcget 0 -foreground]\n} -cleanup {\n    .l configure -foreground #000000\n} -result {{#110022} #110022}\ntest listbox-23.13 {configuration options} -body {\n    .l configure -foreground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-23.14 {configuration options} -body {\n    .l itemconfigure 0 -selectbackground #110022\n    list [lindex [.l itemconfigure 0 -selectbackground] 4] [.l itemcget 0 -selectbackground]\n} -cleanup {\n    .l configure -selectbackground #c3c3c3\n} -result {{#110022} #110022}\ntest listbox-23.15 {configuration options} -body {\n    .l configure -selectbackground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest listbox-23.16 {configuration options} -body {\n    .l itemconfigure 0 -selectforeground #654321\n    list [lindex [.l itemconfigure 0 -selectforeground] 4] [.l itemcget 0 -selectforeground]\n} -cleanup {\n    .l configure -selectforeground #000000\n} -result {{#654321} #654321}\ntest listbox-23.17 {configuration options} -body {\n    .l configure -selectforeground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\n\n# ListboxWidgetObjCmd, itemcget\ntest listbox-24.1 {itemcget} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    .l itemcget 0 -fg\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-24.2 {itemcget} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    .l itemconfigure 0 -fg red\n    .l itemcget 0 -fg\n} -cleanup {\n    destroy .l\n} -result red\ntest listbox-24.3 {itemcget} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    catch {.l itemcget 0} result\n    set result\n} -cleanup {\n    destroy .l\n} -result {wrong # args: should be \".l itemcget index option\"}\ntest listbox-24.4 {itemcget, itemcg shortcut} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c d\n    catch {.l itemcg 0} result\n    set result\n} -cleanup {\n    destroy .l\n} -result {wrong # args: should be \".l itemcget index option\"}\n\n\n# General item configuration issues\ntest listbox-25.1 {listbox item configurations and widget based deletions} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a\n    .l itemconfigure 0 -fg red\n    .l delete 0 end\n    .l insert end a\n    .l itemcget 0 -fg\n} -cleanup {\n    destroy .l\n} -result {}\ntest listbox-25.2 {listbox item configurations and widget based inserts} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l itemconfigure 0 -fg red\n    .l insert 0 1 2 3 4\n    list [.l itemcget 0 -fg] [.l itemcget 4 -fg]\n} -cleanup {\n    destroy .l\n} -result {{} red}\n\n\n# state issues\ntest listbox-26.1 {listbox disabled state disallows inserts} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l configure -state disabled\n    .l insert end d e f\n    .l get 0 end\n} -cleanup {\n    destroy .l\n} -result [list a b c]\ntest listbox-26.2 {listbox disabled state disallows deletions} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l configure -state disabled\n    .l delete 0 end\n    .l get 0 end\n} -cleanup {\n    destroy .l\n} -result [list a b c]\ntest listbox-26.3 {listbox disabled state disallows selection modification} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l selection set 0\n    .l selection set 2\n    .l configure -state disabled\n    .l selection clear 0 end\n    .l selection set 1\n    .l curselection\n} -cleanup {\n    destroy .l\n} -result [list 0 2]\ntest listbox-26.4 {listbox disabled state disallows anchor modification} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l selection anchor 0\n    .l configure -state disabled\n    .l selection anchor 2\n    .l index anchor\n} -cleanup {\n    destroy .l\n} -result 0\ntest listbox-26.5 {listbox disabled state disallows active modification} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end a b c\n    .l activate 0\n    .l configure -state disabled\n    .l activate 2\n    .l index active\n} -cleanup {\n    destroy .l\n} -result 0\n\n\ntest listbox-27.1 {widget deletion while active} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l]\n    update\n    .l configure -cursor xterm -xscrollcommand { destroy .l }\n    update idle\n    winfo exists .l\n} -cleanup {\n    destroy .l\n} -result 0\n\n\ntest listbox-28.1 {listbox -activestyle} -setup {\n    destroy .l\n} -body {\n    listbox .l -activ non\n    .l cget -activestyle\n} -cleanup {\n    destroy .l\n} -result none\ntest listbox-28.2 {listbox -activestyle} -constraints {\n\tmacOrUnix\n} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l cget -activestyle\n} -cleanup {\n    destroy .l\n} -result dotbox\ntest listbox-28.3 {listbox -activestyle} -constraints {\n\twin\n} -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l cget -activestyle\n} -cleanup {\n    destroy .l\n} -result underline\ntest listbox-28.4 {listbox -activestyle} -setup {\n    destroy .l\n} -body {\n    listbox .l -activestyle und\n    .l cget -activestyle\n} -cleanup {\n    destroy .l\n} -result underline\n\n\ntest listbox-29.1 {listbox selection behavior, -state disabled}  -setup {\n    destroy .l\n} -body {\n    listbox .l\n    .l insert end 1 2 3\n    .l selection set 2\n    set out [.l selection includes 2]\n    .l configure -state disabled\n    # still return 1 when disabled, because 'selection get' will work,\n    # but selection cannot be changed (new behavior since 8.4)\n    .l selection set 3\n    lappend out [.l selection includes 2] [.l curselection]\n} -cleanup {\n    destroy .l\n} -result {1 1 2}\n\ntest listbox-30.1 {Bug 3607326} -setup {\n    destroy .l\n    unset -nocomplain a\n} -body {\n    array set a {}\n    listbox .l -listvariable a\n} -cleanup {\n    destroy .l\n    unset -nocomplain a\n} -result * -match glob -returnCodes error\n\ntest listbox-31.1 {<<ListboxSelect>> event} -setup {\n    destroy .l\n    unset -nocomplain res\n} -body {\n    pack [listbox .l -state normal]\n    update\n    bind .l <<ListboxSelect>> {lappend res [%W curselection]}\n    .l insert end a b c\n    focus -force .l\n    event generate .l <Button-1> -x 5 -y 5  ; # <<ListboxSelect>> fires\n    .l configure -state disabled\n    focus -force .l\n    event generate .l <Control-Home> ; # <<ListboxSelect>> does NOT fire\n    .l configure -state normal\n    focus -force .l\n    event generate .l <Control-End>  ; # <<ListboxSelect>> fires\n    .l selection clear 0 end         ; # <<ListboxSelect>> does NOT fire\n    .l selection set 1 1             ; # <<ListboxSelect>> does NOT fire\n    lappend res [.l curselection]\n} -cleanup {\n    destroy .l\n    unset -nocomplain res\n} -result {0 2 1}\n\ntest listbox-31.2 {<<ListboxSelect>> event on lost selection} -setup {\n    destroy .l\n} -body {\n    pack [listbox .l -exportselection true]\n    update\n    bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}\n    .l insert end a b c\n    focus -force .l\n    event generate .l <Button-1> -x 5 -y 5  ; # <<ListboxSelect>> fires\n    selection clear                  ; # <<ListboxSelect>> fires again\n    update\n    set res\n} -cleanup {\n    destroy .l\n} -result {{.l 0} {{} {}}}\n\ntest listbox-32.1 {Bug [5d991b822e]} {\n    # Want this not to segfault, or write to variable with empty name\n    set var INIT\n    listbox .b -listvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -listvariable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n    info exists {}\n} 0\ntest listbox-32.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    listbox .b -listvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -listvariable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\n\n#\n# TESTFILE CLEANUP\n#\n\nresetGridInfo\ndeleteWindows\noption clear\nrename getsize {}\ncleanupTests\n"
  },
  {
    "path": "tests/main.tcl",
    "content": "# main.tcl --\n#\n# This file holds initialization code that is common to all test files.\n# It performs an initial Tk setup for the root window, imports commands from\n# the tcltest namespace, and loads definitions of global utility procs and\n# test constraints.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nif {[namespace exists ::tk::test]} {\n    # This file has already been sourced by a previous test file in mode -singleproc 1\n    return\n}\n\n#\n# SETUP FOR APPLICATION AND ROOT WINDOW\n#\nencoding system utf-8\nif {[tcltest::configure -singleproc] == 0} {\n    # Support test suite invocation by tclsh (as is the case with \"-singleproc 1\")\n    package require tk\n}\ntk appname tktest\nwm title . tktest\n\n#\n# IMPORT TCLTEST COMMANDS\n#\nnamespace import -force tcltest::cleanupTests tcltest::interpreter \\\n\ttcltest::makeDirectory tcltest::makeFile tcltest::removeDirectory \\\n\ttcltest::removeFile tcltest::test tcltest::testsDirectory\n\n#\n# SOURCE DEFINITIONS OF GLOBAL UTILITY PROCS AND CONSTRAINTS\n#\nset mainTestDir [tcltest::configure -testdir]\nif {[file tail $mainTestDir] eq \"ttk\"} {\n    set mainTestDir [file dirname $mainTestDir]\n}\nsource [file join $mainTestDir testutils.tcl]\nsource [file join $mainTestDir constraints.tcl]\nunset mainTestDir\n\n# EOF\n"
  },
  {
    "path": "tests/main.test",
    "content": "# This file contains tests for the tkMain.c file.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest main-1.1 {StdinProc} -constraints stdio -setup {\n    set script [makeFile {close stdin; exit} script]\n} -body {\n    exec [interpreter] <$script\n} -cleanup {\n    removeFile script\n} -returnCodes ok\n\ntest main-2.1 {Tk_MainEx: -encoding option} -constraints stdio -setup {\n\tset script [makeFile {} script]\n\tfile delete $script\n\tset f [open $script w]\n\tfconfigure $f -encoding utf-8\n\tputs $f {puts [list $argv0 $argv $tcl_interactive]}\n\tputs $f {puts [string equal \\u20AC €]; exit}\n\tclose $f\n\tcatch {set f [open \"|[list [interpreter] -encoding utf-8 script]\" r]}\n} -body {\n\tread $f\n} -cleanup {\n\tclose $f\n\tremoveFile script\n} -result \"script {} 0\\n1\\n\"\n\ntest main-2.2 {Tk_MainEx: -encoding option} -constraints stdio -setup {\n\tset script [makeFile {} script]\n\tfile delete $script\n\tset f [open $script w]\n\tfconfigure $f -encoding utf-8\n\tputs $f {puts [list $argv0 $argv $tcl_interactive]}\n\tputs $f {puts [string equal \\u20AC €]; exit}\n\tclose $f\n\tcatch {set f [open \"|[list [interpreter] -encoding iso8859-1 script]\" r]}\n} -body {\n\tread $f\n} -cleanup {\n\tclose $f\n\tremoveFile script\n} -result \"script {} 0\\n0\\n\"\n\n    # Procedure to simulate interactive typing of commands, line by line,\n\t# for test 2.3\n    proc type {chan script} {\n\tforeach line [split $script \\n] {\n\t    if {[catch {\n\t\tputs $chan $line\n\t\tflush $chan\n\t    }]} {\n\t\treturn\n\t    }\n\t    # Grrr... Behavior depends on this value.\n\t    after 1000\n\t}\n    }\n\ntest main-2.3 {Tk_MainEx: -encoding option} -constraints stdio -setup {\n\tset script [makeFile {} script]\n\tfile delete $script\n\tset f [open $script w]\n\tfconfigure $f -encoding utf-8\n\tputs $f {puts [list $argv0 $argv $tcl_interactive]}\n\tputs $f {puts [string equal \\u20AC €]}\n\tclose $f\n\tcatch {set f [open \"|[list [interpreter] -enc utf-8 script]\" r+]}\n} -body {\n\ttype $f {\n\t\tputs $argv\n\t\texit\n\t}\n\tgets $f\n} -cleanup {\n\tclose $f\n\tremoveFile script\n} -returnCodes ok -result {-enc utf-8 script}\n\n\ntest main-3.1 {Tk_ParseArgv: -help option} -constraints {unix !withXft} -body {\n    # Constraints: Running on win32 pops up a dialog, so disable on Windows.\n    # On Unix, Xft with bidi support added can cause hangs, reasons unclear. Skip\n    # test if compiled with Xft.\n    exec [interpreter] -help\n} -returnCodes error -match glob -result {*application-specific initialization failed: Command-specific options:*}\n\ntest main-3.2 {Tk_ParseArgv: -help option} -setup {\n    set maininterp [interp create]\n} -body {\n    $maininterp eval { set argc 1 ; set argv -help }\n    load {} Tk $maininterp\n} -cleanup {\n    interp delete $maininterp\n} -returnCodes error -match glob -result {Command-specific options:*}\n\ntest main-3.3 {Tk_ParseArgv: -help option} -setup {\n    set maininterp [interp create]\n} -body {\n    # Repeat of 3.2 to catch cleanup, eg Bug 1927135\n    $maininterp eval { set argc 1 ; set argv -help }\n    load {} Tk $maininterp\n} -cleanup {\n    interp delete $maininterp\n} -returnCodes error -match glob -result {Command-specific options:*}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/menu.test",
    "content": "# This file is a Tcl script to test platform-indifferent features of menus in Tk.\n#\n# Copyright © 1995-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding the menu system that\n# are specific to the unix platform (this includes macOS), or to the windows\n# platform go into the test files unixMenu.test or winMenu.test respectively.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# TESTS\n#\n\ntest menu-1.1 {Tk_MenuCmd procedure} -body {\n    menu\n} -returnCodes error -result {wrong # args: should be \"menu pathName ?-option value ...?\"}\ntest menu-1.2 {Tk_MenuCmd procedure} -body {\n    menu bogus\n} -returnCodes error -result {bad window path name \"bogus\"}\ntest menu-1.3 {Tk_MenuCmd procedure} -body {\n    destroy .m1\n    menu .m1 foo\n} -returnCodes error -result {unknown option \"foo\"}\ntest menu-1.4 {Tk_MenuCmd procedure} -body {\n    destroy .m1\n    menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menu-1.5 {Tk_MenuCmd - creating menubar} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label Test -menu \"\"\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-1.6 {Tk_MenuCmd procedure menu ref no cascade} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menu-1.7 {Tk_MenuCmd procedure one clone cascade} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    menu .m1\n    .m1 add cascade -menu .m2\n    menu .m2\n} -cleanup {\n    deleteWindows\n} -result {.m2}\ntest menu-1.8 {Tk_MenuCmd procedure two clone cascades} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    menu .m2\n} -cleanup {\n    deleteWindows\n} -result {.m2}\ntest menu-1.9 {Tk_MenuCmd procedure two clone cascades different order} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    menu .m1\n    .m1 add cascade -menu .m2\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    list [menu .m2]\n} -cleanup {\n    deleteWindows\n} -result {.m2}\ntest menu-1.10 {Tk_MenuCmd procedure two clone cascades menus last} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    menu .m1\n    .m1 add cascade -menu .m2\n    list [menu .m2]\n} -cleanup {\n    deleteWindows\n} -result {.m2}\ntest menu-1.11 {Tk_MenuCmd procedure three clones cascades} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    toplevel .t4 -menu .m1\n    wm geometry .t4 +0+0\n    menu .m1\n    .m1 add cascade -menu .m2\n    list [menu .m2]\n} -cleanup {\n    deleteWindows\n} -result {.m2}\ntest menu-1.12 {Tk_MenuCmd procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    list [menu .m1]\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menu-1.13 {Tk_MenuCmd procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    list [menu .m1]\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menu-1.14 {Tk_MenuCmd procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    toplevel .t4 -menu .m1\n    wm geometry .t4 +0+0\n    list [menu .m1]\n} -cleanup {\n    deleteWindows\n} -result {.m1}\n\n#\n# COMMON TEST SETUP\n#\n# For tests 2.1 - 2.30\n#\ndestroy .m1\nmenu .m1\n\ntest menu-2.1 {configuration options -activebackground #012345} -body {\n    .m1 configure -activebackground #012345\n    .m1 cget -activebackground\n} -result {#012345}\ntest menu-2.2 {configuration options -activebackground non-existent} -body {\n    .m1 configure -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.3 {configuration options -activeborderwidth 1.3} -body {\n    .m1 configure -activeborderwidth 1.3\n    .m1 cget -activeborderwidth\n} -result {1.3}\ntest menu-2.4 {configuration options -activeborderwidth badValue} -body {\n    .m1 configure -activeborderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest menu-2.5 {configuration options -activeforeground #ff0000} -body {\n    .m1 configure -activeforeground #ff0000\n    .m1 cget -activeforeground\n} -result {#ff0000}\ntest menu-2.6 {configuration options -activeforeground non-existent} -body {\n    .m1 configure -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.6a {configuration options -activerelief sunken} -body {\n    .m1 configure -activerelief sunken\n    .m1 cget -activerelief\n} -result {sunken}\ntest menu-2.6b {configuration options -activerelief badValue} -body {\n    .m1 configure -activerelief badValue\n} -returnCodes error -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest menu-2.7 {configuration options -background #ff0000} -body {\n    .m1 configure -background #ff0000\n    .m1 cget -background\n} -result {#ff0000}\ntest menu-2.8 {configuration options -background non-existent} -body {\n    .m1 configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.9 {configuration options -bg #110022} -body {\n    .m1 configure -bg #110022\n    .m1 cget -bg\n} -result {#110022}\ntest menu-2.10 {configuration options -bg bogus} -body {\n    .m1 configure -bg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest menu-2.11 {configuration options -borderwidth 1.3} -body {\n    .m1 configure -borderwidth 1.3\n    .m1 cget -borderwidth\n} -result {1.3}\ntest menu-2.12 {configuration options -borderwidth badValue} -body {\n    .m1 configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest menu-2.13 {configuration options -cursor arrow} -body {\n    .m1 configure -cursor arrow\n    .m1 cget -cursor\n} -result {arrow}\ntest menu-2.14 {configuration options -cursor badValue} -body {\n    .m1 configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest menu-2.15 {configuration options -disabledforeground #00ff00} -body {\n    .m1 configure -disabledforeground #00ff00\n    .m1 cget -disabledforeground\n} -result {#00ff00}\ntest menu-2.16 {configuration options -disabledforeground xyzzy} -body {\n    .m1 configure -disabledforeground xyzzy\n} -returnCodes error -result {unknown color name \"xyzzy\"}\n\ntest menu-2.17 {configuration options -fg #110022} -body {\n    .m1 configure -fg #110022\n    .m1 cget -fg\n} -result {#110022}\ntest menu-2.18 {configuration options -fg bogus} -body {\n    .m1 configure -fg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest menu-2.19 {configuration options -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*} -body {\n    .m1 configure -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    .m1 cget -font\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\ntest menu-2.20 {configuration options -foreground #110022} -body {\n    .m1 configure -foreground #110022\n    .m1 cget -foreground\n} -result {#110022}\ntest menu-2.21 {configuration options -foreground bogus} -body {\n    .m1 configure -foreground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest menu-2.22 {configuration options -postcommand {any old string}} -body {\n    .m1 configure -postcommand {any old string}\n    .m1 cget -postcommand\n} -result {any old string}\ntest menu-2.23 {configuration options -relief groove} -body {\n    .m1 configure -relief groove\n    .m1 cget -relief\n} -result {groove}\ntest menu-2.24 {configuration options -relief 1.5} -body {\n    .m1 configure -relief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest menu-2.25 {configuration options -selectcolor #110022} -body {\n    .m1 configure -selectcolor #110022\n    .m1 cget -selectcolor\n} -result {#110022}\ntest menu-2.26 {configuration options -selectcolor bogus} -body {\n    .m1 configure -selectcolor bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest menu-2.27 {configuration options -takefocus {any string}} -body {\n    .m1 configure -takefocus {any string}\n    .m1 cget -takefocus\n} -result {any string}\ntest menu-2.28 {configuration options -tearoff 0} -body {\n    .m1 configure -tearoff 0\n    .m1 cget -tearoff\n} -result 0\ntest menu-2.29 {configuration options -tearoff 1} -body {\n    .m1 configure -tearoff 1\n    .m1 cget -tearoff\n} -result 1\ntest menu-2.30 {configuration options -tearoffcommand {any old string}} -body {\n    .m1 configure -tearoffcommand {any old string}\n    .m1 cget -tearoffcommand\n} -result {any old string}\n\n#\n# COMMON TEST SETUP\n#\n# For tests 2.31 - 2.228\n#\n\n# We need to test all of the options with all of the different types of\n# menu entries. The following code sets up .m1 with 6 items. It then\n# runs through the 2.31 - 2.228 tests below\n# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton,\n# 5 radiobutton\ndeleteWindows\nmenu .m1 -tearoff 1\n.m1 add command -label \"command\"\nmenu .m2 -tearoff 1\n.m2 add command -label \"test\"\n.m1 add cascade -label \"cascade\" -menu .m2\n.m1 add separator\n.m1 add checkbutton -label \"checkbutton\" -variable check -onvalue on -offvalue off\n.m1 add radiobutton -label \"radiobutton\" -variable radio\n\nset earthPhotoFile [file join [file dirname [info script]] earth.gif]\nimage create photo image1 -file $earthPhotoFile\n\ntest menu-2.31 {entry configuration options 0 -activebackground #012345 tearoff} -body {\n    .m1 entryconfigure 0 -activebackground #012345\n} -returnCodes error -result {unknown option \"-activebackground\"}\n\ntest menu-2.32 {entry configuration options 1 -activebackground #012345 command} -body {\n    .m1 entryconfigure 1 -activebackground #012345\n    lindex [.m1 entryconfigure 1 -activebackground] 4\n} -result {#012345}\n\ntest menu-2.33 {entry configuration options 2 -activebackground #012345 cascade} -body {\n    .m1 entryconfigure 2 -activebackground #012345\n    lindex [.m1 entryconfigure 2 -activebackground] 4\n} -result {#012345}\n\ntest menu-2.34 {entry configuration options 3 -activebackground #012345 separator} -body {\n    .m1 entryconfigure 3 -activebackground #012345\n} -returnCodes error -result {unknown option \"-activebackground\"}\n\ntest menu-2.35 {entry configuration options 4 -activebackground #012345 checkbutton} -body {\n    .m1 entryconfigure 4 -activebackground #012345\n    lindex [.m1 entryconfigure 4 -activebackground] 4\n} -result {#012345}\n\ntest menu-2.36 {entry configuration options 5 -activebackground #012345 radiobutton} -body {\n    .m1 entryconfigure 5 -activebackground #012345\n    lindex [.m1 entryconfigure 5 -activebackground] 4\n} -result {#012345}\n\ntest menu-2.37 {entry configuration options 0 -activebackground non-existent tearoff} -body {\n    .m1 entryconfigure 0 -activebackground non-existent\n} -returnCodes error -result {unknown option \"-activebackground\"}\n\ntest menu-2.38 {entry configuration options 1 -activebackground non-existent command} -body {\n    .m1 entryconfigure 1 -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.39 {entry configuration options 2 -activebackground non-existent cascade} -body {\n    .m1 entryconfigure 2 -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.40 {entry configuration options 3 -activebackground non-existent separator} -body {\n    .m1 entryconfigure 3 -activebackground non-existent\n} -returnCodes error -result {unknown option \"-activebackground\"}\n\ntest menu-2.41 {entry configuration options 4 -activebackground non-existent checkbutton} -body {\n    .m1 entryconfigure 4 -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.42 {entry configuration options 5 -activebackground non-existent radiobutton} -body {\n    .m1 entryconfigure 5 -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.43 {entry configuration options 0 -activeforeground #ff0000 tearoff} -body {\n    .m1 entryconfigure 0 -activeforeground #ff0000\n} -returnCodes error -result {unknown option \"-activeforeground\"}\n\ntest menu-2.44 {entry configuration options 1 -activeforeground #ff0000 command} -body {\n    .m1 entryconfigure 1 -activeforeground #ff0000\n    lindex [.m1 entryconfigure 1 -activeforeground] 4\n} -result {#ff0000}\n\ntest menu-2.45 {entry configuration options 2 -activeforeground #ff0000 cascade} -body {\n    .m1 entryconfigure 2 -activeforeground #ff0000\n    lindex [.m1 entryconfigure 2 -activeforeground] 4\n} -result {#ff0000}\n\ntest menu-2.46 {entry configuration options 3 -activeforeground #ff0000 separator} -body {\n    .m1 entryconfigure 3 -activeforeground #ff0000\n} -returnCodes error -result {unknown option \"-activeforeground\"}\n\ntest menu-2.47 {entry configuration options 4 -activeforeground #ff0000 checkbutton} -body {\n    .m1 entryconfigure 4 -activeforeground #ff0000\n    lindex [.m1 entryconfigure 4 -activeforeground] 4\n} -result {#ff0000}\n\ntest menu-2.48 {entry configuration options 5 -activeforeground #ff0000 radiobutton} -body {\n    .m1 entryconfigure 5 -activeforeground #ff0000\n    lindex [.m1 entryconfigure 5 -activeforeground] 4\n} -result {#ff0000}\n\ntest menu-2.49 {entry configuration options 0 -activeforeground non-existent tearoff} -body {\n    .m1 entryconfigure 0 -activeforeground non-existent\n} -returnCodes error -result {unknown option \"-activeforeground\"}\n\ntest menu-2.50 {entry configuration options 1 -activeforeground non-existent command} -body {\n    .m1 entryconfigure 1 -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.51 {entry configuration options 2 -activeforeground non-existent cascade} -body {\n    .m1 entryconfigure 2 -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.52 {entry configuration options 3 -activeforeground non-existent separator} -body {\n    .m1 entryconfigure 3 -activeforeground non-existent\n} -returnCodes error -result {unknown option \"-activeforeground\"}\n\ntest menu-2.53 {entry configuration options 4 -activeforeground non-existent checkbutton} -body {\n    .m1 entryconfigure 4 -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.54 {entry configuration options 5 -activeforeground non-existent radiobutton} -body {\n    .m1 entryconfigure 5 -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.55 {entry configuration options 0 -accelerator Ctrl+S tearoff} -body {\n    .m1 entryconfigure 0 -accelerator Ctrl+S\n} -returnCodes error -result {unknown option \"-accelerator\"}\n\ntest menu-2.56 {entry configuration options 1 -accelerator Ctrl+S command} -body {\n    .m1 entryconfigure 1 -accelerator Ctrl+S\n    lindex [.m1 entryconfigure 1 -accelerator] 4\n} -result {Ctrl+S}\n\ntest menu-2.57 {entry configuration options 2 -accelerator Ctrl+S cascade} -body {\n    .m1 entryconfigure 2 -accelerator Ctrl+S\n    lindex [.m1 entryconfigure 2 -accelerator] 4\n} -result {Ctrl+S}\n\ntest menu-2.58 {entry configuration options 3 -accelerator Ctrl+S separator} -body {\n    .m1 entryconfigure 3 -accelerator Ctrl+S\n} -returnCodes error -result {unknown option \"-accelerator\"}\n\ntest menu-2.59 {entry configuration options 4 -accelerator Ctrl+S checkbutton} -body {\n    .m1 entryconfigure 4 -accelerator Ctrl+S\n    lindex [.m1 entryconfigure 4 -accelerator] 4\n} -result {Ctrl+S}\n\ntest menu-2.60 {entry configuration options 5 -accelerator Ctrl+S radiobutton} -body {\n    .m1 entryconfigure 5 -accelerator Ctrl+S\n    lindex [.m1 entryconfigure 5 -accelerator] 4\n} -result {Ctrl+S}\n\ntest menu-2.61 {entry configuration options 0 -background #ff0000 tearoff} -body {\n    .m1 entryconfigure 0 -background #ff0000\n    lindex [.m1 entryconfigure 0 -background] 4\n} -result {#ff0000}\n\ntest menu-2.62 {entry configuration options 1 -background #ff0000 command} -body {\n    .m1 entryconfigure 1 -background #ff0000\n    lindex [.m1 entryconfigure 1 -background] 4\n} -result {#ff0000}\n\ntest menu-2.63 {entry configuration options 2 -background #ff0000 cascade} -body {\n    .m1 entryconfigure 2 -background #ff0000\n    lindex [.m1 entryconfigure 2 -background] 4\n} -result {#ff0000}\n\ntest menu-2.64 {entry configuration options 3 -background #ff0000 separator} -body {\n    .m1 entryconfigure 3 -background #ff0000\n    lindex [.m1 entryconfigure 3 -background] 4\n} -result {#ff0000}\n\ntest menu-2.65 {entry configuration options 4 -background #ff0000 checkbutton} -body {\n    .m1 entryconfigure 4 -background #ff0000\n    lindex [.m1 entryconfigure 4 -background] 4\n} -result {#ff0000}\n\ntest menu-2.66 {entry configuration options 5 -background #ff0000 radiobutton} -body {\n    .m1 entryconfigure 5 -background #ff0000\n    lindex [.m1 entryconfigure 5 -background] 4\n} -result {#ff0000}\n\ntest menu-2.67 {entry configuration options 0 -background non-existent tearoff} -body {\n    .m1 entryconfigure 0 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.68 {entry configuration options 1 -background non-existent command} -body {\n    .m1 entryconfigure 1 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.69 {entry configuration options 2 -background non-existent cascade} -body {\n    .m1 entryconfigure 2 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.70 {entry configuration options 3 -background non-existent separator} -body {\n    .m1 entryconfigure 3 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.71 {entry configuration options 4 -background non-existent checkbutton} -body {\n    .m1 entryconfigure 4 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.72 {entry configuration options 5 -background non-existent radiobutton} -body {\n    .m1 entryconfigure 5 -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.73 {entry configuration options 0 -bitmap questhead tearoff} -body {\n    .m1 entryconfigure 0 -bitmap questhead\n} -returnCodes error -result {unknown option \"-bitmap\"}\n\ntest menu-2.74 {entry configuration options 1 -bitmap questhead command} -body {\n    .m1 entryconfigure 1 -bitmap questhead\n    lindex [.m1 entryconfigure 1 -bitmap] 4\n} -result {questhead}\n\ntest menu-2.75 {entry configuration options 2 -bitmap questhead cascade} -body {\n    .m1 entryconfigure 2 -bitmap questhead\n    lindex [.m1 entryconfigure 2 -bitmap] 4\n} -result {questhead}\n\ntest menu-2.76 {entry configuration options 3 -bitmap questhead separator} -body {\n    .m1 entryconfigure 3 -bitmap questhead\n} -returnCodes error -result {unknown option \"-bitmap\"}\n\ntest menu-2.77 {entry configuration options 4 -bitmap questhead checkbutton} -body {\n    .m1 entryconfigure 4 -bitmap questhead\n    lindex [.m1 entryconfigure 4 -bitmap] 4\n} -result {questhead}\n\ntest menu-2.78 {entry configuration options 5 -bitmap questhead radiobutton} -body {\n    .m1 entryconfigure 5 -bitmap questhead\n    lindex [.m1 entryconfigure 5 -bitmap] 4\n} -result {questhead}\n\ntest menu-2.79 {entry configuration options 0 -bitmap badValue tearoff} -body {\n    .m1 entryconfigure 0 -bitmap badValue\n} -returnCodes error -result {unknown option \"-bitmap\"}\n\ntest menu-2.80 {entry configuration options 1 -bitmap badValue command} -body {\n    .m1 entryconfigure 1 -bitmap badValue\n} -returnCodes error -result {bitmap \"badValue\" not defined}\n\ntest menu-2.81 {entry configuration options 2 -bitmap badValue cascade} -body {\n    .m1 entryconfigure 2 -bitmap badValue\n} -returnCodes error -result {bitmap \"badValue\" not defined}\n\ntest menu-2.82 {entry configuration options 3 -bitmap badValue separator} -body {\n    .m1 entryconfigure 3 -bitmap badValue\n} -returnCodes error -result {unknown option \"-bitmap\"}\n\ntest menu-2.83 {entry configuration options 4 -bitmap badValue checkbutton} -body {\n    .m1 entryconfigure 4 -bitmap badValue\n} -returnCodes error -result {bitmap \"badValue\" not defined}\n\ntest menu-2.84 {entry configuration options 5 -bitmap badValue radiobutton} -body {\n    .m1 entryconfigure 5 -bitmap badValue\n} -returnCodes error -result {bitmap \"badValue\" not defined}\n\ntest menu-2.85 {entry configuration options 0 -columnbreak 1 tearoff} -body {\n    .m1 entryconfigure 0 -columnbreak 1\n} -returnCodes error -result {unknown option \"-columnbreak\"}\n\ntest menu-2.86 {entry configuration options 1 -columnbreak 1 command} -body {\n    .m1 entryconfigure 1 -columnbreak 1\n    lindex [.m1 entryconfigure 1 -columnbreak] 4\n} -result 1\n\ntest menu-2.87 {entry configuration options 2 -columnbreak 1 cascade} -body {\n    .m1 entryconfigure 2 -columnbreak 1\n    lindex [.m1 entryconfigure 2 -columnbreak] 4\n} -result 1\n\ntest menu-2.88 {entry configuration options 3 -columnbreak 1 separator} -body {\n    .m1 entryconfigure 3 -columnbreak 1\n} -returnCodes error -result {unknown option \"-columnbreak\"}\n\ntest menu-2.89 {entry configuration options 4 -columnbreak 1 checkbutton} -body {\n    .m1 entryconfigure 4 -columnbreak 1\n    lindex [.m1 entryconfigure 4 -columnbreak] 4\n} -result 1\n\ntest menu-2.90 {entry configuration options 5 -columnbreak 1 radiobutton} -body {\n    .m1 entryconfigure 5 -columnbreak 1\n    lindex [.m1 entryconfigure 5 -columnbreak] 4\n} -result 1\n\ntest menu-2.91 {entry configuration options 0 -command beep tearoff} -body {\n    .m1 entryconfigure 0 -command beep\n} -returnCodes error -result {unknown option \"-command\"}\n\ntest menu-2.92 {entry configuration options 1 -command beep command} -body {\n    .m1 entryconfigure 1 -command beep\n    lindex [.m1 entryconfigure 1 -command] 4\n} -result {beep}\n\ntest menu-2.93 {entry configuration options 2 -command beep cascade} -body {\n    .m1 entryconfigure 2 -command beep\n    lindex [.m1 entryconfigure 2 -command] 4\n} -result {beep}\n\ntest menu-2.94 {entry configuration options 3 -command beep separator} -body {\n    .m1 entryconfigure 3 -command beep\n} -returnCodes error -result {unknown option \"-command\"}\n\ntest menu-2.95 {entry configuration options 4 -command beep checkbutton} -body {\n    .m1 entryconfigure 4 -command beep\n    lindex [.m1 entryconfigure 4 -command] 4\n} -result {beep}\n\ntest menu-2.96 {entry configuration options 5 -command beep radiobutton} -body {\n    .m1 entryconfigure 5 -command beep\n    lindex [.m1 entryconfigure 5 -command] 4\n} -result {beep}\n\ntest menu-2.97 {entry configuration options 0 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* tearoff} -body {\n    .m1 entryconfigure 0 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n} -returnCodes error -result {unknown option \"-font\"}\n\ntest menu-2.98 {entry configuration options 1 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* command} -body {\n    .m1 entryconfigure 1 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    lindex [.m1 entryconfigure 1 -font] 4\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\n\ntest menu-2.99 {entry configuration options 2 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* cascade} -body {\n    .m1 entryconfigure 2 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    lindex [.m1 entryconfigure 2 -font] 4\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\n\ntest menu-2.100 {entry configuration options 3 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* separator} -body {\n    .m1 entryconfigure 3 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n} -returnCodes error -result {unknown option \"-font\"}\n\ntest menu-2.101 {entry configuration options 4 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* checkbutton} -body {\n    .m1 entryconfigure 4 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    lindex [.m1 entryconfigure 4 -font] 4\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\n\ntest menu-2.102 {entry configuration options 5 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-* radiobutton} -body {\n    .m1 entryconfigure 5 -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    lindex [.m1 entryconfigure 5 -font] 4\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\n\ntest menu-2.103 {entry configuration options 0 -font {kill rock stars} tearoff} -body {\n    .m1 entryconfigure 0 -font {kill rock stars}\n} -returnCodes error -result {unknown option \"-font\"}\n\ntest menu-2.104 {entry configuration options 1 -font {kill rock stars} command} -body {\n    .m1 entryconfigure 1 -font {kill rock stars}\n} -returnCodes error -result {expected integer but got \"rock\"}\n\ntest menu-2.105 {entry configuration options 2 -font {kill rock stars} cascade} -body {\n    .m1 entryconfigure 2 -font {kill rock stars}\n} -returnCodes error -result {expected integer but got \"rock\"}\n\ntest menu-2.106 {entry configuration options 3 -font {kill rock stars} separator} -body {\n    .m1 entryconfigure 3 -font {kill rock stars}\n} -returnCodes error -result {unknown option \"-font\"}\n\ntest menu-2.107 {entry configuration options 4 -font {kill rock stars} checkbutton} -body {\n    .m1 entryconfigure 4 -font {kill rock stars}\n} -returnCodes error -result {expected integer but got \"rock\"}\n\ntest menu-2.108 {entry configuration options 5 -font {kill rock stars} radiobutton} -body {\n    .m1 entryconfigure 5 -font {kill rock stars}\n} -returnCodes error -result {expected integer but got \"rock\"}\n\ntest menu-2.109 {entry configuration options 0 -foreground #110022 tearoff} -body {\n    .m1 entryconfigure 0 -foreground #110022\n} -returnCodes error -result {unknown option \"-foreground\"}\n\ntest menu-2.110 {entry configuration options 1 -foreground #110022 command} -body {\n    .m1 entryconfigure 1 -foreground #110022\n    lindex [.m1 entryconfigure 1 -foreground] 4\n} -result {#110022}\n\ntest menu-2.111 {entry configuration options 2 -foreground #110022 cascade} -body {\n    .m1 entryconfigure 2 -foreground #110022\n    lindex [.m1 entryconfigure 2 -foreground] 4\n} -result {#110022}\n\ntest menu-2.112 {entry configuration options 3 -foreground #110022 separator} -body {\n    .m1 entryconfigure 3 -foreground #110022\n} -returnCodes error -result {unknown option \"-foreground\"}\n\ntest menu-2.113 {entry configuration options 4 -foreground #110022 checkbutton} -body {\n    .m1 entryconfigure 4 -foreground #110022\n    lindex [.m1 entryconfigure 4 -foreground] 4\n} -result {#110022}\n\ntest menu-2.114 {entry configuration options 5 -foreground #110022 radiobutton} -body {\n    .m1 entryconfigure 5 -foreground #110022\n    lindex [.m1 entryconfigure 5 -foreground] 4\n} -result {#110022}\n\ntest menu-2.115 {entry configuration options 0 -foreground non-existent tearoff} -body {\n    .m1 entryconfigure 0 -foreground non-existent\n} -returnCodes error -result {unknown option \"-foreground\"}\n\ntest menu-2.116 {entry configuration options 1 -foreground non-existent command} -body {\n    .m1 entryconfigure 1 -foreground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.117 {entry configuration options 2 -foreground non-existent cascade} -body {\n    .m1 entryconfigure 2 -foreground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.118 {entry configuration options 3 -foreground non-existent separator} -body {\n    .m1 entryconfigure 3 -foreground non-existent\n} -returnCodes error -result {unknown option \"-foreground\"}\n\ntest menu-2.119 {entry configuration options 4 -foreground non-existent checkbutton} -body {\n    .m1 entryconfigure 4 -foreground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.120 {entry configuration options 5 -foreground non-existent radiobutton} -body {\n    .m1 entryconfigure 5 -foreground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.121 {entry configuration options 0 -image image1 tearoff} -body {\n    .m1 entryconfigure 0 -image image1\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.122 {entry configuration options 1 -image image1 command} -setup {\n    .m1 entryconfigure 1 -image {}\n} -body {\n    .m1 entryconfigure 1 -image image1\n    lindex [.m1 entryconfigure 1 -image] 4\n} -cleanup {\n    .m1 entryconfigure 1 -image {}\n} -result {image1}\n\ntest menu-2.123 {entry configuration options 2 -image image1 cascade} -setup {\n    .m1 entryconfigure 2 -image {}\n} -body {\n    .m1 entryconfigure 2 -image image1\n    lindex [.m1 entryconfigure 2 -image] 4\n} -cleanup {\n    .m1 entryconfigure 2 -image {}\n} -result {image1}\n\ntest menu-2.124 {entry configuration options 3 -image image1 separator} -body {\n    .m1 entryconfigure 3 -image image1\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.125 {entry configuration options 4 -image image1 checkbutton} -setup {\n    .m1 entryconfigure 4 -image {}\n} -body {\n    .m1 entryconfigure 4 -image image1\n    lindex [.m1 entryconfigure 4 -image] 4\n} -cleanup {\n    .m1 entryconfigure 4 -image {}\n} -result {image1}\n\ntest menu-2.126 {entry configuration options 5 -image image1 radiobutton} -setup {\n    .m1 entryconfigure 5 -image {}\n} -body {\n    .m1 entryconfigure 5 -image image1\n    lindex [.m1 entryconfigure 5 -image] 4\n} -cleanup {\n    .m1 entryconfigure 5 -image {}\n} -result {image1}\n\ntest menu-2.127 {entry configuration options 0 -image bogus tearoff} -body {\n    .m1 entryconfigure 0 -image bogus\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.128 {entry configuration options 1 -image bogus command} -body {\n    .m1 entryconfigure 1 -image bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.129 {entry configuration options 2 -image bogus cascade} -body {\n    .m1 entryconfigure 2 -image bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.130 {entry configuration options 3 -image bogus separator} -body {\n    .m1 entryconfigure 3 -image bogus\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.131 {entry configuration options 4 -image bogus checkbutton} -body {\n    .m1 entryconfigure 4 -image bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.132 {entry configuration options 5 -image bogus radiobutton} -body {\n    .m1 entryconfigure 5 -image bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.133 {entry configuration options 0 -image {} tearoff} -body {\n    .m1 entryconfigure 0 -image\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.134 {entry configuration options 1 -image {} command} -setup {\n    .m1 entryconfigure 1 -image {}\n} -body {\n    .m1 entryconfigure 1 -image\n    lindex [.m1 entryconfigure 1 -image] 4\n} -result {}\n\ntest menu-2.135 {entry configuration options 2 -image {} cascade} -setup {\n    .m1 entryconfigure 2 -image {}\n} -body {\n    .m1 entryconfigure 2 -image\n    lindex [.m1 entryconfigure 2 -image] 4\n} -result {}\n\ntest menu-2.136 {entry configuration options 3 -image {} separator} -body {\n    .m1 entryconfigure 3 -image\n} -returnCodes error -result {unknown option \"-image\"}\n\ntest menu-2.137 {entry configuration options 4 -image {} checkbutton} -body {\n    .m1 entryconfigure 4 -image\n    lindex [.m1 entryconfigure 4 -image] 4\n} -result {}\n\ntest menu-2.138 {entry configuration options 5 -image {} radiobutton} -body {\n    .m1 entryconfigure 5 -image\n    lindex [.m1 entryconfigure 5 -image] 4\n} -result {}\n\ntest menu-2.139 {entry configuration options 0 -indicatoron 1 tearoff} -body {\n    .m1 entryconfigure 0 -indicatoron 1\n} -returnCodes error -result {unknown option \"-indicatoron\"}\n\ntest menu-2.140 {entry configuration options 1 -indicatoron 1 command} -body {\n    .m1 entryconfigure 1 -indicatoron 1\n} -returnCodes error -result {unknown option \"-indicatoron\"}\n\ntest menu-2.141 {entry configuration options 2 -indicatoron 1 cascade} -body {\n    .m1 entryconfigure 2 -indicatoron 1\n} -returnCodes error -result {unknown option \"-indicatoron\"}\n\ntest menu-2.142 {entry configuration options 3 -indicatoron 1 separator} -body {\n    .m1 entryconfigure 3 -indicatoron 1\n} -returnCodes error -result {unknown option \"-indicatoron\"}\n\ntest menu-2.143 {entry configuration options 4 -indicatoron 1 checkbutton} -body {\n    .m1 entryconfigure 4 -indicatoron 1\n    lindex [.m1 entryconfigure 4 -indicatoron] 4\n} -result 1\n\ntest menu-2.144 {entry configuration options 5 -indicatoron 1 radiobutton} -body {\n    .m1 entryconfigure 5 -indicatoron 1\n    lindex [.m1 entryconfigure 5 -indicatoron] 4\n} -result 1\n\ntest menu-2.145 {entry configuration options 0 -label test tearoff} -body {\n    .m1 entryconfigure 0 -label test\n} -returnCodes error -result {unknown option \"-label\"}\n\ntest menu-2.146 {entry configuration options 1 -label test command} -body {\n    .m1 entryconfigure 1 -label test\n    lindex [.m1 entryconfigure 1 -label] 4\n} -result {test}\n\ntest menu-2.147 {entry configuration options 2 -label test cascade} -body {\n    .m1 entryconfigure 2 -label test\n    lindex [.m1 entryconfigure 2 -label] 4\n} -result {test}\n\ntest menu-2.148 {entry configuration options 3 -label test separator} -body {\n    .m1 entryconfigure 3 -label test\n} -returnCodes error -result {unknown option \"-label\"}\n\ntest menu-2.149 {entry configuration options 4 -label test checkbutton} -body {\n    .m1 entryconfigure 4 -label test\n    lindex [.m1 entryconfigure 4 -label] 4\n} -result {test}\n\ntest menu-2.150 {entry configuration options 5 -label test radiobutton} -body {\n    .m1 entryconfigure 5 -label test\n    lindex [.m1 entryconfigure 5 -label] 4\n} -result {test}\n\ntest menu-2.151 {entry configuration options 0 -menu .m2 tearoff} -body {\n    .m1 entryconfigure 0 -menu .m2\n} -returnCodes error -result {unknown option \"-menu\"}\n\ntest menu-2.152 {entry configuration options 1 -menu .m2 command} -body {\n    .m1 entryconfigure 1 -menu .m2\n} -returnCodes error -result {unknown option \"-menu\"}\n\ntest menu-2.153 {entry configuration options 2 -menu .m2 cascade} -body {\n    .m1 entryconfigure 2 -menu .m2\n    lindex [.m1 entryconfigure 2 -menu] 4\n} -result {.m2}\n\ntest menu-2.154 {entry configuration options 3 -menu .m2 separator} -body {\n    .m1 entryconfigure 3 -menu .m2\n} -returnCodes error -result {unknown option \"-menu\"}\n\ntest menu-2.155 {entry configuration options 4 -menu .m2 checkbutton} -body {\n    .m1 entryconfigure 4 -menu .m2\n} -returnCodes error -result {unknown option \"-menu\"}\n\ntest menu-2.156 {entry configuration options 5 -menu .m2 radiobutton} -body {\n    .m1 entryconfigure 5 -menu .m2\n} -returnCodes error -result {unknown option \"-menu\"}\n\ntest menu-2.157 {entry configuration options 0 -offvalue off tearoff} -body {\n    .m1 entryconfigure 0 -offvalue off\n} -returnCodes error -result {unknown option \"-offvalue\"}\n\ntest menu-2.158 {entry configuration options 1 -offvalue off command} -body {\n    .m1 entryconfigure 1 -offvalue off\n} -returnCodes error -result {unknown option \"-offvalue\"}\n\ntest menu-2.159 {entry configuration options 2 -offvalue off cascade} -body {\n    .m1 entryconfigure 2 -offvalue off\n} -returnCodes error -result {unknown option \"-offvalue\"}\n\ntest menu-2.160 {entry configuration options 3 -offvalue off separator} -body {\n    .m1 entryconfigure 3 -offvalue off\n} -returnCodes error -result {unknown option \"-offvalue\"}\n\ntest menu-2.161 {entry configuration options 4 -offvalue off checkbutton} -body {\n    .m1 entryconfigure 4 -offvalue off\n    lindex [.m1 entryconfigure 4 -offvalue] 4\n} -result {off}\n\ntest menu-2.162 {entry configuration options 5 -offvalue off radiobutton} -body {\n    .m1 entryconfigure 5 -offvalue off\n} -returnCodes error -result {unknown option \"-offvalue\"}\n\ntest menu-2.163 {entry configuration options 0 -onvalue on tearoff} -body {\n    .m1 entryconfigure 0 -onvalue on\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest menu-2.164 {entry configuration options 1 -onvalue on command} -body {\n    .m1 entryconfigure 1 -onvalue on\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest menu-2.165 {entry configuration options 2 -onvalue on cascade} -body {\n    .m1 entryconfigure 2 -onvalue on\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest menu-2.166 {entry configuration options 3 -onvalue on separator} -body {\n    .m1 entryconfigure 3 -onvalue on\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest menu-2.167 {entry configuration options 4 -onvalue on checkbutton} -body {\n    .m1 entryconfigure 4 -onvalue on\n    lindex [.m1 entryconfigure 4 -onvalue] 4\n} -result {on}\n\ntest menu-2.168 {entry configuration options 5 -onvalue on radiobutton} -body {\n    .m1 entryconfigure 5 -onvalue on\n} -returnCodes error -result {unknown option \"-onvalue\"}\n\ntest menu-2.169 {entry configuration options 0 -selectcolor #110022 tearoff} -body {\n    .m1 entryconfigure 0 -selectcolor #110022\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.170 {entry configuration options 1 -selectcolor #110022 command} -body {\n    .m1 entryconfigure 1 -selectcolor #110022\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.171 {entry configuration options 2 -selectcolor #110022 cascade} -body {\n    .m1 entryconfigure 2 -selectcolor #110022\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.172 {entry configuration options 3 -selectcolor #110022 separator} -body {\n    .m1 entryconfigure 3 -selectcolor #110022\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.173 {entry configuration options 4 -selectcolor #110022 checkbutton} -body {\n    .m1 entryconfigure 4 -selectcolor #110022\n    lindex [.m1 entryconfigure 4 -selectcolor] 4\n} -result {#110022}\n\ntest menu-2.174 {entry configuration options 5 -selectcolor #110022 radiobutton} -body {\n    .m1 entryconfigure 5 -selectcolor #110022\n    lindex [.m1 entryconfigure 5 -selectcolor] 4\n} -result {#110022}\n\ntest menu-2.175 {entry configuration options 0 -selectcolor non-existent tearoff} -body {\n    .m1 entryconfigure 0 -selectcolor non-existent\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.176 {entry configuration options 1 -selectcolor non-existent command} -body {\n    .m1 entryconfigure 1 -selectcolor non-existent\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.177 {entry configuration options 2 -selectcolor non-existent cascade} -body {\n    .m1 entryconfigure 2 -selectcolor non-existent\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.178 {entry configuration options 3 -selectcolor non-existent separator} -body {\n    .m1 entryconfigure 3 -selectcolor non-existent\n} -returnCodes error -result {unknown option \"-selectcolor\"}\n\ntest menu-2.179 {entry configuration options 4 -selectcolor non-existent checkbutton} -body {\n    .m1 entryconfigure 4 -selectcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.180 {entry configuration options 5 -selectcolor non-existent radiobutton} -body {\n    .m1 entryconfigure 5 -selectcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest menu-2.181 {entry configuration options 0 -selectimage image1 tearoff} -body {\n    .m1 entryconfigure 0 -selectimage image1\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.182 {entry configuration options 1 -selectimage image1 command} -body {\n    .m1 entryconfigure 1 -selectimage image1\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.183 {entry configuration options 2 -selectimage image1 cascade} -body {\n    .m1 entryconfigure 2 -selectimage image1\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.184 {entry configuration options 3 -selectimage image1 separator} -body {\n    .m1 entryconfigure 3 -selectimage image1\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.185 {entry configuration options 4 -selectimage image1 checkbutton} -setup {\n    .m1 entryconfigure 4 -selectimage {}\n} -body {\n    .m1 entryconfigure 4 -selectimage image1\n    lindex [.m1 entryconfigure 4 -selectimage] 4\n} -cleanup {\n    .m1 entryconfigure 4 -selectimage {}\n} -result {image1}\n\ntest menu-2.186 {entry configuration options 5 -selectimage image1 radiobutton} -setup {\n    .m1 entryconfigure 5 -selectimage {}\n} -body {\n    .m1 entryconfigure 5 -selectimage image1\n    lindex [.m1 entryconfigure 5 -selectimage] 4\n} -cleanup {\n    .m1 entryconfigure 5 -selectimage {}\n} -result {image1}\n\ntest menu-2.187 {entry configuration options 0 -selectimage bogus tearoff} -body {\n    .m1 entryconfigure 0 -selectimage bogus\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.188 {entry configuration options 1 -selectimage bogus command} -body {\n    .m1 entryconfigure 1 -selectimage bogus\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.189 {entry configuration options 2 -selectimage bogus cascade} -body {\n    .m1 entryconfigure 2 -selectimage bogus\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.190 {entry configuration options 3 -selectimage bogus separator} -body {\n    .m1 entryconfigure 3 -selectimage bogus\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.191 {entry configuration options 4 -selectimage bogus checkbutton} -body {\n    .m1 entryconfigure 4 -selectimage bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.192 {entry configuration options 5 -selectimage bogus radiobutton} -body {\n    .m1 entryconfigure 5 -selectimage bogus\n} -returnCodes error -result {image \"bogus\" does not exist}\n\ntest menu-2.193 {entry configuration options 0 -selectimage {} tearoff} -body {\n    .m1 entryconfigure 0 -selectimage\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.194 {entry configuration options 1 -selectimage {} command} -body {\n    .m1 entryconfigure 1 -selectimage\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.195 {entry configuration options 2 -selectimage {} cascade} -body {\n    .m1 entryconfigure 2 -selectimage\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.196 {entry configuration options 3 -selectimage {} separator} -body {\n    .m1 entryconfigure 3 -selectimage\n} -returnCodes error -result {unknown option \"-selectimage\"}\n\ntest menu-2.197 {entry configuration options 4 -selectimage {} checkbutton} -body {\n    .m1 entryconfigure 4 -selectimage\n    lindex [.m1 entryconfigure 4 -selectimage] 4\n} -result {}\n\ntest menu-2.198 {entry configuration options 5 -selectimage {} radiobutton} -body {\n    .m1 entryconfigure 5 -selectimage\n    lindex [.m1 entryconfigure 5 -selectimage] 4\n} -result {}\n\ntest menu-2.199 {entry configuration options 0 -state normal tearoff} -body {\n    .m1 entryconfigure 0 -state normal\n    lindex [.m1 entryconfigure 0 -state] 4\n} -result {normal}\n\ntest menu-2.200 {entry configuration options 1 -state normal command} -body {\n    .m1 entryconfigure 1 -state normal\n    lindex [.m1 entryconfigure 1 -state] 4\n} -result {normal}\n\ntest menu-2.201 {entry configuration options 2 -state normal cascade} -body {\n    .m1 entryconfigure 2 -state normal\n    lindex [.m1 entryconfigure 2 -state] 4\n} -result {normal}\n\ntest menu-2.202 {entry configuration options 3 -state normal separator} -body {\n    .m1 entryconfigure 3 -state normal\n} -returnCodes error -result {unknown option \"-state\"}\n\ntest menu-2.203 {entry configuration options 4 -state normal checkbutton} -body {\n    .m1 entryconfigure 4 -state normal\n    lindex [.m1 entryconfigure 4 -state] 4\n} -result {normal}\n\ntest menu-2.204 {entry configuration options 5 -state normal radiobutton} -body {\n    .m1 entryconfigure 5 -state normal\n    lindex [.m1 entryconfigure 5 -state] 4\n} -result {normal}\n\ntest menu-2.205 {entry configuration options 0 -value {any string} tearoff} -body {\n    .m1 entryconfigure 0 -value {any string}\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest menu-2.206 {entry configuration options 1 -value {any string} command} -body {\n    .m1 entryconfigure 1 -value {any string}\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest menu-2.207 {entry configuration options 2 -value {any string} cascade} -body {\n    .m1 entryconfigure 2 -value {any string}\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest menu-2.208 {entry configuration options 3 -value {any string} separator} -body {\n    .m1 entryconfigure 3 -value {any string}\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest menu-2.209 {entry configuration options 4 -value {any string} checkbutton} -body {\n    .m1 entryconfigure 4 -value {any string}\n} -returnCodes error -result {unknown option \"-value\"}\n\ntest menu-2.210 {entry configuration options 5 -value {any string} radiobutton} -body {\n    .m1 entryconfigure 5 -value {any string}\n    lindex [.m1 entryconfigure 5 -value] 4\n} -result {any string}\n\ntest menu-2.211 {entry configuration options 0 -variable {any string} tearoff} -body {\n    .m1 entryconfigure 0 -variable {any string}\n} -returnCodes error -result {unknown option \"-variable\"}\n\ntest menu-2.212 {entry configuration options 1 -variable {any string} command} -body {\n    .m1 entryconfigure 1 -variable {any string}\n} -returnCodes error -result {unknown option \"-variable\"}\n\ntest menu-2.213 {entry configuration options 2 -variable {any string} cascade} -body {\n    .m1 entryconfigure 2 -variable {any string}\n} -returnCodes error -result {unknown option \"-variable\"}\n\ntest menu-2.214 {entry configuration options 3 -variable {any string} separator} -body {\n    .m1 entryconfigure 3 -variable {any string}\n} -returnCodes error -result {unknown option \"-variable\"}\n\ntest menu-2.215 {entry configuration options 4 -variable {any string} checkbutton} -body {\n    .m1 entryconfigure 4 -variable {any string}\n    lindex [.m1 entryconfigure 4 -variable] 4\n} -result {any string}\n\ntest menu-2.216 {entry configuration options 5 -variable {any string} radiobutton} -body {\n    .m1 entryconfigure 5 -variable {any string}\n    lindex [.m1 entryconfigure 5 -variable] 4\n} -result {any string}\n\ntest menu-2.217 {entry configuration options 0 -underline 0 tearoff} -body {\n    .m1 entryconfigure 0 -underline 0\n} -returnCodes error -result {unknown option \"-underline\"}\n\ntest menu-2.218 {entry configuration options 1 -underline 0 command} -body {\n    .m1 entryconfigure 1 -underline 0\n    lindex [.m1 entryconfigure 1 -underline] 4\n} -result 0\n\ntest menu-2.219 {entry configuration options 2 -underline 0 cascade} -body {\n    .m1 entryconfigure 2 -underline 0\n    lindex [.m1 entryconfigure 2 -underline] 4\n} -result 0\n\ntest menu-2.220 {entry configuration options 3 -underline 0 separator} -body {\n    .m1 entryconfigure 3 -underline 0\n} -returnCodes error -result {unknown option \"-underline\"}\n\ntest menu-2.221 {entry configuration options 4 -underline 0 checkbutton} -body {\n    .m1 entryconfigure 4 -underline 0\n    lindex [.m1 entryconfigure 4 -underline] 4\n} -result 0\n\ntest menu-2.222 {entry configuration options 5 -underline 0 radiobutton} -body {\n    .m1 entryconfigure 5 -underline 0\n    lindex [.m1 entryconfigure 5 -underline] 4\n} -result 0\n\ntest menu-2.223 {entry configuration options 0 -underline 3p tearoff} -body {\n    .m1 entryconfigure 0 -underline 3p\n} -returnCodes error -result {unknown option \"-underline\"}\n\ntest menu-2.224 {entry configuration options 1 -underline 3p command} -body {\n    .m1 entryconfigure 1 -underline 3p\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\n\ntest menu-2.225 {entry configuration options 2 -underline 3p cascade} -body {\n    .m1 entryconfigure 2 -underline 3p\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\n\ntest menu-2.226 {entry configuration options 3 -underline 3p separator} -body {\n    .m1 entryconfigure 3 -underline 3p\n} -returnCodes error -result {unknown option \"-underline\"}\n\ntest menu-2.227 {entry configuration options 4 -underline 3p checkbutton} -body {\n    .m1 entryconfigure 4 -underline 3p\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\n\ntest menu-2.228 {entry configuration options 5 -underline 3p radiobutton} -body {\n    .m1 entryconfigure 5 -underline 3p\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\nimage delete image1\n\ntest menu-3.1 {MenuWidgetCmd procedure} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 option ?arg ...?\"}\ntest menu-3.2 {MenuWidgetCmd, Tcl_Preserve and Tcl_Release} -constraints {\n    nonUnixUserInteraction\n} -setup {\n    destroy .m1\n} -body  {\n    menu .m1 -postcommand \"destroy .m1\"\n    .m1 add command -label \"menu-3.2: Hit Escape\"\n    .m1 post 40 40\n} -cleanup {\n    destroy .m1\n} -returnCodes ok -result {}\ntest menu-3.3 {MenuWidgetCmd procedure, \"activate\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 activate\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 activate index\"}\ntest menu-3.4 {MenuWidgetCmd procedure, \"activate\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 activate \"foo\"\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.5 {MenuWidgetCmd procedure, \"activate\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add separator\n    .m1 activate 2\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.6 {MenuWidgetCmd procedure, \"activate\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 entryconfigure 1 -state disabled\n    .m1 activate 1\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.7 {MenuWidgetCmd procedure, \"activate\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 activate 1\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.8 {MenuWidgetCmd procedure, \"add\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 add type ?-option value ...?\"}\ntest menu-3.9 {MenuWidgetCmd procedure, \"add\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {bad menu entry type \"foo\": must be cascade, checkbutton, command, radiobutton, or separator}\ntest menu-3.10 {MenuWidgetCmd procedure, \"add\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n} -cleanup {\n    destroy .m1\n} -result {e001}\ntest menu-3.11 {MenuWidgetCmd procedure, \"cget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 cget\n} -returnCodes error -result {wrong # args: should be \".m1 cget option\"}\ntest menu-3.12 {MenuWidgetCmd procedure, \"cget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 cget -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest menu-3.13 {MenuWidgetCmd procedure, \"cget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 configure -postcommand \"Some string\"\n    .m1 cget -postcommand\n} -cleanup {\n    destroy .m1\n} -result {Some string}\ntest menu-3.14 {MenuWidgetCmd procedure, \"clone\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 clone\n} -returnCodes error -result {wrong # args: should be \".m1 clone newMenuName ?menuType?\"}\ntest menu-3.15 {MenuWidgetCmd procedure, \"clone\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 clone a b c d\n} -returnCodes error -result {wrong # args: should be \".m1 clone newMenuName ?menuType?\"}\ntest menu-3.16 {MenuWidgetCmd procedure, \"clone\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 clone .m1.clone1\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.17 {MenuWidgetCmd procedure, \"clone\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 clone .m1.clone1 tearoff\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.18 {MenuWidgetCmd procedure, \"configure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    llength [.m1 configure]\n} -cleanup {\n    destroy .m1\n} -result 21\ntest menu-3.19 {MenuWidgetCmd procedure, \"configure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 configure -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest menu-3.20 {MenuWidgetCmd procedure, \"configure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 configure -postcommand \"A random String\"\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.21 {MenuWidgetCmd procedure, \"configure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 configure -postcommand \"Another string\"\n    lindex [.m1 configure -postcommand] 4\n} -cleanup {\n    destroy .m1\n} -result {Another string}\ntest menu-3.22 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 delete\n} -returnCodes error -result {wrong # args: should be \".m1 delete first ?last?\"}\ntest menu-3.23 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 delete foo\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.24 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 1\n    .m1 delete 0 \"foo\"\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.25 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 delete 0\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.26 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    .m1 delete 1 0\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.27 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"1\"\n    .m1 add command -label \"2\"\n    .m1 add command -label \"3\"\n    .m1 delete 1 3\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.28 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"1\"\n    .m1 add command -label \"2\"\n    .m1 add command -label \"3\"\n    .m1 activate 2\n    .m1 delete 1 3\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.29 {MenuWidgetCmd procedure, \"delete\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"1\"\n    .m1 add command -label \"2\"\n    .m1 add command -label \"3\"\n    .m1 activate 3\n    .m1 delete 1\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.29+1 {MenuWidgetCmd, \"delete\", Bug 220950} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"bogus\"\n    .m1 add command -label \"ok\"\n    .m1 delete 10 20\n    .m1 entrycget last -label\n} -cleanup {\n    destroy .m1\n} -result ok\ntest menu-3.30 {MenuWidgetCmd procedure, \"entrycget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 entrycget\n} -returnCodes error -result {wrong # args: should be \".m1 entrycget index option\"}\ntest menu-3.31 {MenuWidgetCmd procedure, \"entrycget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 entrycget index option foo\n} -returnCodes error -result {wrong # args: should be \".m1 entrycget index option\"}\ntest menu-3.32 {MenuWidgetCmd procedure, \"entrycget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 entrycget foo -label\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.33 {MenuWidgetCmd procedure, \"entrycget\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 entrycget 1 -label\n} -cleanup {\n    destroy .m1\n} -result {test}\ntest menu-3.34 {MenuWidgetCmd procedure, \"entryconfigure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 entryconfigure\n} -returnCodes error -result {wrong # args: should be \".m1 entryconfigure index ?-option value ...?\"}\ntest menu-3.35 {MenuWidgetCmd procedure, \"entryconfigure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 entryconfigure foo\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.36 {MenuWidgetCmd procedure, \"entryconfigure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    llength [.m1 entryconfigure 1]\n} -cleanup {\n    destroy .m1\n} -result 15\ntest menu-3.37 {MenuWidgetCmd procedure, \"entryconfigure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    lindex [.m1 entryconfigure 1 -label] 4\n} -cleanup {\n    destroy .m1\n} -result {test}\ntest menu-3.38 {MenuWidgetCmd procedure, \"entryconfigure\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 entryconfigure 1 -label \"changed\"\n    lindex [.m1 entryconfigure 1 -label] 4\n} -cleanup {\n    destroy .m1\n} -result {changed}\ntest menu-3.39 {MenuWidgetCmd procedure, \"index\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 index\n} -returnCodes error -result {wrong # args: should be \".m1 index string\"}\ntest menu-3.40 {MenuWidgetCmd procedure, \"index\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 index foo\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.41 {MenuWidgetCmd procedure, \"index\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"3\"\n    .m1 add command -label \"another label\"\n    .m1 add command -label \"end\"\n    .m1 add command -label \"3a\"\n    .m1 add command -label \"final entry\"\n    list [.m1 index \"test\"] [.m1 index \"3\"] [.m1 index \"3a\"] [.m1 index \"end\"]\n} -cleanup {\n    destroy .m1\n} -result {1 3 5 6}\ntest menu-3.42 {MenuWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 insert\n} -returnCodes error -result {wrong # args: should be \".m1 insert index type ?-option value ...?\"}\ntest menu-3.43 {MenuWidgetCmd procedure, \"insert\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 insert 1 command -label \"test\"\n    .m1 entrycget 1 -label\n} -cleanup {\n    destroy .m1\n} -result {test}\ntest menu-3.44 {MenuWidgetCmd procedure, \"invoke\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 invoke\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 invoke index\"}\ntest menu-3.45 {MenuWidgetCmd procedure, \"invoke\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 invoke foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.46 {MenuWidgetCmd procedure, \"invoke\" option} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add command -label \"set foo\" -command \"set foo hello\"\n    list [.m1 invoke 1] [set foo] [unset foo]\n} -cleanup {\n    destroy .m1\n} -returnCodes ok -result {hello hello {}}\ntest menu-3.47 {MenuWidgetCmd procedure, \"post\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"On Windows, hit Escape to get this menu to go away\"\n    .m1 post\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 post x y ?index?\"}\ntest menu-3.48 {MenuWidgetCmd procedure, \"post\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 post foo 40\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest menu-3.49 {MenuWidgetCmd procedure, \"post\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 post 40 bar\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {expected integer but got \"bar\"}\ntest menu-3.50 {MenuWidgetCmd procedure, \"post\" option} -constraints {\n    nonUnixUserInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"menu-3.50: hit Escape\" -command \"puts hello\"\n    .m1 post 40 40\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.51 {MenuWidgetCmd procedure, \"postcascade\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 postcascade\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 postcascade index\"}\ntest menu-3.52 {MenuWidgetCmd procedure, \"postcascade\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 postcascade foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.53 {MenuWidgetCmd procedure, \"postcascade\" option} -constraints {\n    nonUnixUserInteraction\n} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 add command -label \"menu-3.53 - hit Escape\"\n    menu .m2\n    .m1 post 40 40\n    .m1 add cascade -menu .m2\n    .m1 postcascade 1\n} -cleanup {\n    destroy .m1 .m2\n} -result {}\ntest menu-3.54 {MenuWidgetCmd procedure, \"postcascade\" option} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2 -label \"menu-3.57 - hit Escape\"\n    .m1 postcascade 1\n    .m1 postcascade {}\n} -cleanup {\n    destroy .m1 .m2\n} -result {}\ntest menu-3.55 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 type\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 type index\"}\ntest menu-3.56 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 type foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-3.57 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 type 1\n} -cleanup {\n    destroy .m1\n} -result {command}\ntest menu-3.58 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    .m1 type 1\n} -cleanup {\n    destroy .m1\n} -result {separator}\ntest menu-3.59 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label \"test\"\n    .m1 type 1\n} -cleanup {\n    destroy .m1\n} -result {checkbutton}\ntest menu-3.60 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label \"test\"\n    .m1 type 1\n} -cleanup {\n    destroy .m1\n} -result {radiobutton}\ntest menu-3.61 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label \"test\"\n    .m1 type 1\n} -cleanup {\n    destroy .m1\n} -result {cascade}\ntest menu-3.62 {MenuWidgetCmd procedure, \"type\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 1\n    .m1 type 0\n} -cleanup {\n    destroy .m1\n} -result {tearoff}\ntest menu-3.63 {MenuWidgetCmd procedure, \"unpost\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 unpost foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 unpost\"}\ntest menu-3.64 {MenuWidgetCmd procedure, \"unpost\" option} -constraints {\n    nonUnixUserInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"menu-3.64 - hit Escape\"\n    .m1 post 40 40\n    .m1 unpost\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.65 {MenuWidgetCmd procedure, \"yposition\" option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 yposition\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 yposition index\"}\ntest menu-3.66a {MenuWidgetCmd procedure, \"yposition\" option, no tearoff} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 yposition 1\n} -cleanup {\n    destroy .m1\n} -result 0\ntest menu-3.66b {MenuWidgetCmd procedure, \"yposition\" option, with tearoff} -constraints {\n    notAqua\n} -setup {\n    destroy .m1\n} -body {\n    # on Win or Linux, tearoff menus are supported\n    # see menu-3.66c for aqua\n    menu .m1 -tearoff 1\n    .m1 yposition 1\n} -cleanup {\n    destroy .m1\n} -result 1\ntest menu-3.66c {MenuWidgetCmd procedure, \"yposition\" option, with tearoff} -constraints {\n    aqua\n} -setup {\n    destroy .m1\n} -body {\n    # on OS X, tearoff menus are not supported\n    # see menu-3.66b for win or linux\n    menu .m1 -tearoff 1\n    .m1 yposition 1\n} -cleanup {\n    destroy .m1\n} -result 0\ntest menu-3.67 {MenuWidgetCmd procedure, bad option} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 foo\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {bad option \"foo\": must be activate, add, cget, clone, configure, delete, entrycget, entryconfigure, id, index, insert, invoke, post, postcascade, type, unpost, xposition, or yposition}\ntest menu-3.68 {MenuWidgetCmd procedure, fix for bug#508988} -setup {\n    deleteWindows\n} -body {\n    set t .t\n    set m1 .t.m1\n    set c1 .t.c1\n    set c2 .t.c2\n    toplevel .t\n    menu $m1 -tearoff 1\n    menu $c1 -tearoff 1\n    $c1 add command -label c1\n    menu $c2 -tearoff 1\n    $c2 add command -label c2\n    $m1 add cascade -label c1 -menu $c1\n    $t configure -menu $m1\n    $m1 entryconfigure 1 -menu $c2 -label c2\n    $t configure -menu \"\"\n    list [winfo exists $c1] [winfo exists $c2]\n} -cleanup {\n    deleteWindows\n} -result {1 1}\ntest menu-3.69 {MenuWidgetCmd procedure, \"xposition\" option} -setup {\n    destroy .m1\n    menu .m1\n} -body {\n    .m1 xposition\n} -cleanup {\n    destroy .m1\n} -returnCodes error -result {wrong # args: should be \".m1 xposition index\"}\ntest menu-3.70 {MenuWidgetCmd procedure, \"xposition\" option} -setup {\n    destroy .m1\n    menu .m1\n} -body {\n    .m1 xposition 1\n    subst {} ;# just checking that the xposition does not produce an error...\n} -cleanup {\n    destroy .m1\n} -result {}\ntest menu-3.71 {MenuWidgetCmd procedure, \"index end\" option, bug [f3cd942e9e]} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 index \"end\"\n} -cleanup {\n    destroy .m1\n} -result {}\n\n\ntest menu-4.1 {TkInvokeMenu: disabled} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -label \"test\" -variable foo -onvalue on -offvalue off \\\n    -state disabled\n    list [catch {.m1 invoke 1} msg] $foo\n} -cleanup {\n    destroy .m1\n} -result {0 off}\ntest menu-4.2 {TkInvokeMenu: tearoff} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    catch {.m1 invoke 0}\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-4.3 {TkInvokeMenu: checkbutton -on} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -label \"test\" -variable foo -onvalue on -offvalue off\n    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 \\\n\t    [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 on 0 {}}\ntest menu-4.4 {TkInvokeMenu: checkbutton -off} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -label \"test\" -variable foo -onvalue on -offvalue off\n    .m1 invoke 1\n    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 off 0 {}}\ntest menu-4.5 {TkInvokeMenu: checkbutton array element} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -label \"test\" -variable foo(1) -onvalue on\n    list [catch {.m1 invoke 1} msg] $msg [catch {set foo(1)} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 on 0 {}}\ntest menu-4.6 {TkInvokeMenu: radiobutton} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1 -tearoff 1\n    .m1 add radiobutton -label \"1\" -variable foo -value one\n    .m1 add radiobutton -label \"2\" -variable foo -value two\n    .m1 add radiobutton -label \"3\" -variable foo -value three\n    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 one 0 {}}\ntest menu-4.7 {TkInvokeMenu: radiobutton} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1 -tearoff 1\n    .m1 add radiobutton -label \"1\" -variable foo -value one\n    .m1 add radiobutton -label \"2\" -variable foo -value two\n    .m1 add radiobutton -label \"3\" -variable foo -value three\n    list [catch {.m1 invoke 2} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 two 0 {}}\ntest menu-4.8 {TkInvokeMenu: radiobutton} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add radiobutton -label \"1\" -variable foo -value one\n    .m1 add radiobutton -label \"2\" -variable foo -value two\n    .m1 add radiobutton -label \"3\" -variable foo -value three\n    list [catch {.m1 invoke 3} msg] $msg [catch {set foo} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 three 0 {}}\ntest menu-4.9 {TkInvokeMenu: radiobutton array element} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add radiobutton -label \"1\" -variable foo(2) -value one\n    .m1 add radiobutton -label \"2\" -variable foo(2) -value two\n    .m1 add radiobutton -label \"3\" -variable foo(2) -value three\n    list [catch {.m1 invoke 3} msg] $msg [catch {set foo(2)} msg2] $msg2 [catch {unset foo} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 {} 0 three 0 {}}\ntest menu-4.10 {TkInvokeMenu} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add command -label \"test\" -command \"set menu_test menu-4.8\"\n    list [catch {.m1 invoke 1} msg] $msg [catch {set menu_test} msg2] $msg2 [catch {unset menu_test} msg3] $msg3\n} -cleanup {\n    destroy .m1\n} -result {0 menu-4.8 0 menu-4.8 0 {}}\ntest menu-4.11 {TkInvokeMenu} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label \"test\" -menu .m1.m2\n    list [catch {.m1 invoke 1} msg] $msg\n} -cleanup {\n    destroy .m1\n} -result {0 {}}\ntest menu-4.12 {TkInvokeMenu} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"test\" -command \".m1 delete 1\"\n    list [catch {.m1 invoke 1} msg] $msg [catch {.m1 type \"test\"} msg2] $msg2\n} -cleanup {\n    destroy .m1\n} -result {0 {} 1 {bad menu entry index \"test\"}}\n\ntest menu-5.1 {DestroyMenuInstance} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -returnCodes ok\ntest menu-5.2 {DestroyMenuInstance - cascade menu} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    menu .m2\n    destroy .m1 .m2\n} -returnCodes ok\ntest menu-5.3 {DestroyMenuInstance - multiple cascade parents} -setup {\n    destroy .m1 .m2 .m3\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m3\n    menu .m2\n    .m2 add cascade -menu .m3\n    menu .m3\n    list [destroy .m3] [destroy .m1 .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-5.4 {DestroyMenuInstance - multiple cascade parents} -setup {\n    destroy .m1 .m2 .m3 .m4\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m4\n    menu .m2\n    .m2 add cascade -menu .m4\n    menu .m3\n    .m3 add cascade -menu .m4\n    menu .m4\n    list [destroy .m4] [destroy .m1 .m2 .m3]\n} -returnCodes ok -result {{} {}}\ntest menu-5.5 {DestroyMenuInstance - cascades of cloned menus} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    . configure -menu .m1\n    list [destroy .m2] [.m1 entrycget 1 -menu] [. configure -menu \"\"] [destroy .m1]\n} -returnCodes ok -result {{} .m2 {} {}}\ntest menu-5.6 {DestroyMenuInstance - cascades of cloned menus} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2\n    wm geometry .t2 +0+0\n    .t2 configure -menu .m1\n    list [destroy .m2] [. configure -menu \"\"] [destroy .t2 .m1]\n} -returnCodes ok -result {{} {} {}}\ntest menu-5.7 {DestroyMenuInstance - basic clones} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    set tearoff [tk::TearOffMenu .m1]\n    list [destroy $tearoff] [destroy .m1]\n} -result {{} {}}\ntest menu-5.8 {DestroyMenuInstance - multiple clones} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    set tearoff1 [tk::TearOffMenu .m1]\n    set tearoff2 [tk::TearOffMenu .m1]\n    list [destroy $tearoff1] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest menu-5.9 {DestroyMenuInstace - main menu} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    tk::TearOffMenu .m1\n    destroy .m1\n} -returnCodes ok\ntest menu-5.10 {DestroyMenuInstance - freeing entries} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    destroy .m1\n} -returnCodes ok\ntest menu-5.11 {DestroyMenuInstace - no entries} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 configure -tearoff 0\n    destroy .m1\n} -returnCodes ok\ntest menu-5.12 {DestroyMenuInstance - platform data} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -returnCodes ok\ntest menu-5.13 {DestroyMenuInstance - clones when mismatched tearoffs} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [destroy .m2] [destroy .m1]\n} -result {{} {}}\n\n\ntest menu-6.1 {TkDestroyMenu} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -returnCodes ok\ntest menu-6.2 {TkDestroyMenu - reentrancy} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    bind .m1 <Destroy> {destroy .m1}\n    menu .m2\n    bind .m2 <Destroy> {destroy .m2}\n    list [destroy .m1] [destroy .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-6.3 {TkDestroyMenu - reentrancy} -setup {\n    destroy .m1 .m2 .m3\n} -body {\n    menu .m1\n    bind .m1 <Destroy> {destroy .m2}\n    .m1 clone .m2\n    .m1 clone .m3\n    list [destroy .m1] [winfo exists .m2]\n} -returnCodes ok -result {{} 0}\ntest menu-6.4 {TkDestroyMenu - reentrancy - clones} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m1.m3\n    destroy .m1\n} -cleanup {\n    deleteWindows\n} -returnCodes ok\ntest menu-6.5 {TkDestroyMenu} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 clone .m2\n    destroy .m1\n    winfo exists .m2\n} -result 0\ntest menu-6.6 {TkDestroyMenu} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 clone .m2 tearoff\n    destroy .m1\n} -result {}\ntest menu-6.7 {TkDestroyMenu} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1\n    .m1 clone .m2\n    destroy .m2\n    destroy .m1\n} -returnCodes ok -result {}\ntest menu-6.8 {TkDestroyMenu} -setup {\n    destroy .m1 .m2 .m3\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    destroy .m1\n    list [winfo exists .m2] [winfo exists .m3]\n} -result {0 0}\ntest menu-6.9 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    list [destroy .m2] [destroy .m3] [destroy .m1]\n} -returnCodes ok -result {{} {} {}}\ntest menu-6.10 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    list [destroy .m3] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest menu-6.11 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    .m1 clone .m4\n    list [destroy .m2] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest menu-6.12 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    .m1 clone .m4\n    list [destroy .m3] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest menu-6.13 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n    .m1 clone .m4\n    list [destroy .m4] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest menu-6.14 {TkDestroyMenu} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    . configure -menu .m1\n    list [destroy .m1] [. configure -menu \"\"]\n} -returnCodes ok -result {{} {}}\ntest menu-6.15 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    toplevel .t2\n    wm geometry .t2 +0+0\n    . configure -menu .m1\n    .t2 configure -menu .m1\n    list [destroy .m1] [destroy .t2] [. configure -menu \"\"]\n} -result {{} {} {}}\ntest menu-6.16 {TkDestroyMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    toplevel .t2\n    wm geometry .t2 +0+0\n    toplevel .t3\n    wm geometry .t3 +0+0\n    . configure -menu .m1\n    .t2 configure -menu .m1\n    .t3 configure -menu .m1\n    list [destroy .m1] [destroy .t2] [destroy .t3] [. configure -menu \"\"]\n} -result {{} {} {} {}}\ntest menu-6.17 {TkDestroyMenu - bug 14a9b62e1d} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -command {destroy .m1}\n    .m1 invoke end\n    winfo exists .m1\n} -result {0}\n\ntest menu-7.1 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    destroy .m1\n} -returnCodes ok\ntest menu-7.2 {UnhookCascadeEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    destroy .m1\n} -returnCodes ok\ntest menu-7.3 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m2 add cascade -menu .cascade\n    .m1 add cascade -menu .cascade\n    list [destroy .m1] [destroy .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-7.4 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .cascade\n    .m2 add cascade -menu .cascade\n    list [destroy .m1] [destroy .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-7.5 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    menu .m3\n    .m1 add cascade -menu .cascade\n    .m2 add cascade -menu .cascade\n    .m3 add cascade -menu .cascade\n    list [destroy .m1] [destroy .m2 .m3]\n} -returnCodes ok -result {{} {}}\ntest menu-7.6 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    menu .m3\n    .m1 add cascade -menu .cascade\n    .m2 add cascade -menu .cascade\n    .m3 add cascade -menu .cascade\n    list [destroy .m2] [destroy .m1 .m3]\n} -returnCodes ok -result {{} {}}\ntest menu-7.7 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    menu .m3\n    .m1 add cascade -menu .cascade\n    .m2 add cascade -menu .cascade\n    .m3 add cascade -menu .cascade\n    list [destroy .m3] [destroy .m1 .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-7.8 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    list [destroy .m1] [destroy .m2]\n} -returnCodes ok -result {{} {}}\ntest menu-7.9 {UnhookCascadeEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    destroy .m1\n    destroy .m2\n} -returnCodes ok\n\ntest menu-8.1 {DestroyMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    list [.m1 delete 1] [destroy .m1 .m2]\n} -result {{} {}}\ntest menu-8.2 {DestroyMenuEntry} -setup {\n    deleteWindows\n    catch {image delete image1a}\n} -body {\n    image create photo image1a -file $earthPhotoFile\n    menu .m1\n    .m1 add command -image image1a\n    list [.m1 delete 1] [destroy .m1] [image delete image1a]\n} -result {{} {} {}}\ntest menu-8.3 {DestroyMenuEntry} -constraints testImageType -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image create test image2\n    menu .m1\n    .m1 add checkbutton -image image1 -selectimage image2\n    .m1 invoke 1\n    list [.m1 delete 1] [destroy .m1]\n} -cleanup {\n    imageCleanup\n    deleteWindows\n} -result {{} {}}\ntest menu-8.4 {DestroyMenuEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -variable foo\n    list [.m1 delete 1] [destroy .m1]\n} -result {{} {}}\ntest menu-8.5 {DestroyMenuEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [.m1 delete 1] [destroy .m1]\n} -result {{} {}}\ntest menu-8.6 {DestroyMenuEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\"\n    list [.m1 delete 1] [.m1 entrycget 1 -label] [destroy .m1]\n} -result {{} two {}}\ntest menu-8.7 {DestroyMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 clone .m2 tearoff\n    list [.m2 delete 1] [destroy .m1]\n} -result {{} {}}\n\n# test menu-9 - Can only change when fonts change on system, which cannot\n# be done from tcl.\ntest menu-9.1 {ConfigureMenu} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [.m1 configure -postcommand \"beep\"] [.m1 cget -postcommand]\n} -cleanup {\n    deleteWindows\n} -result {{} beep}\ntest menu-9.2 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [.m1 configure -tearoff 0] [.m1 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {{} test}\ntest menu-9.3 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [.m1 configure -postcommand \"beep\"] [.m1 cget -postcommand]\n} -cleanup {\n    deleteWindows\n} -result {{} beep}\ntest menu-9.4 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -fg red\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-9.5 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"two\"\n    .m1 configure -fg red\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-9.6 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"two\"\n    .m1 add command -label \"three\"\n    .m1 configure -fg red\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-9.7 {ConfigureMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 tearoff\n    list [.m1 configure -fg red] [.m2 cget -fg]\n} -cleanup {\n    deleteWindows\n} -result {{} red}\ntest menu-9.8 {ConfigureMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 tearoff\n    list [.m2 configure -fg red] [.m1 cget -fg]\n} -cleanup {\n    deleteWindows\n} -result {{} red}\ntest menu-9.9 {ConfigureMenu}  -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\n\ntest menu-10.1 {PostProcessEntry: array variable} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    set foo(1) on\n    .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label \"Nonsense\"\n    set foo(1)\n} -cleanup {\n    deleteWindows\n} -result {on}\ntest menu-10.2 {PostProcessEntry: array variable} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label \"Nonsense\"\n    set foo(1)\n} -cleanup {\n    deleteWindows\n} -result {off}\n\n\ntest menu-11.1 {ConfigureMenuEntry} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -variable foo -onvalue on -offvalue off -label \"Nonsense\"\n    list [.m1 entryconfigure 1 -variable bar] [.m1 entrycget 1 -variable]\n} -cleanup {\n    deleteWindows\n} -result {{} bar}\ntest menu-11.2 {ConfigureMenuEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [.m1 entryconfigure 1 -label \"\"] [.m1 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-11.3 {ConfigureMenuEntry} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command\n    list [.m1 entryconfigure 1 -label \"test\"] [.m1 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {{} test}\ntest menu-11.4 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n    list [.m1 entryconfigure 1 -accel \"S\"] [.m1 entrycget 1 -accel]\n} -cleanup {\n    deleteWindows\n} -result {{} S}\ntest menu-11.5 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n    list [.m1 entryconfigure 1 -label \"test\"] [.m1 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {{} test}\ntest menu-11.6 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n    .m1 entryconfigure 1 -label \"test\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.7 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m2\n    menu .m1\n    .m1 add cascade\n    .m1 entryconfigure 1 -label \"test\" -menu .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.8 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade\n    .m1 entryconfigure 1 -label \"test\" -menu .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.9 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m3\n    .m1 entryconfigure 1 -label \"test\" -menu .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.10 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade\n    .m1 entryconfigure 1 -label \"test\" -menu .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.11 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    .m1 entryconfigure 1 -label \"test\" -menu .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.12 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m2 add cascade -menu .m1\n    menu .m3\n    .m3 add cascade -menu .m1\n    menu .m4\n    .m4 add cascade -menu .m1\n    menu .m5\n    .m5 add cascade\n    .m5 entryconfigure 1 -label \"test\" -menu .m1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.13 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m2 add cascade -menu .m1\n    menu .m3\n    .m3 add cascade -menu .m1\n    menu .m4\n    .m4 add cascade -menu .m1\n    .m3 entryconfigure 1 -label \"test\" -menu .m1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-11.14 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add checkbutton\n    list [.m1 entryconfigure 1 -variable \"test\"] [.m1 entrycget 1 -variable]\n} -cleanup {\n    deleteWindows\n} -result {{} test}\ntest menu-11.15 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    list [.m1 add checkbutton -label \"test\"] [.m1 entrycget 1 -variable]\n} -cleanup {\n    deleteWindows\n} -result {e001 test}\ntest menu-11.16 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add radiobutton -label \"test\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-11.17 {ConfigureMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add checkbutton\n    list [.m1 entryconfigure 1 -onvalue \"test\"] [.m1 entrycget 1 -onvalue]\n} -cleanup {\n    deleteWindows\n} -result {{} test}\ntest menu-11.18 {ConfigureMenuEntry} -constraints testImageType -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    menu .m1\n    .m1 add command\n    image create test image1\n    .m1 entryconfigure 1 -image image1\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {}\ntest menu-11.19 {ConfigureMenuEntry} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image create photo image2 -file $earthPhotoFile\n    menu .m1\n    .m1 add command -image image1\n    .m1 entryconfigure 1 -image image2\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {}\ntest menu-11.20 {ConfigureMenuEntry} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create photo image1 -file $earthPhotoFile\n    image create test image2\n    menu .m1\n    .m1 add checkbutton -image image1\n    .m1 entryconfigure 1 -selectimage image2\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {}\ntest menu-11.21 {ConfigureMenuEntry} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create photo image1 -file $earthPhotoFile\n    image create test image2\n    image create test image3\n    menu .m1\n    .m1 add checkbutton -image image1 -selectimage image2\n    .m1 entryconfigure 1 -selectimage image3\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {}\n\n\ntest menu-12.1 {ConfigureMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m2 configure -tearoff 0\n    .m1 clone .m3\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\"\n    .m1 entryconfigure 1 -gork \"foo\"\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-gork\"}\ntest menu-12.2 {ConfigureMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    menu .m3\n    .m1 add cascade -menu .m3\n    menu .m4\n    .m1 entryconfigure 1 -menu .m4\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-12.3 {ConfigureMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 add cascade -label dummy\n    .m1 entryconfigure dummy -menu .m3\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-12.4 {ConfigureMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n     menu .m1\n     .m1 add cascade -label File -menu .m1.foo\n     menu .m1.foo\n     .m1.foo add command -label bar\n     .m1 clone .m2\n     .m1 entryconfigure File -state disabled\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menu-13.1 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"active\"\n    .m1 add command -label \"test2\"\n    .m1 add command -label \"test3\"\n    .m1 activate 2\n    .m1 entrycget active -label\n} -cleanup {\n    deleteWindows\n} -result {test2}\ntest menu-13.2 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"last\"\n    .m1 add command -label \"test2\"\n    .m1 add command -label \"test3\"\n    .m1 activate 2\n    .m1 entrycget last -label\n} -cleanup {\n    deleteWindows\n} -result {test3}\ntest menu-13.3 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"last\"\n    .m1 add command -label \"test2\"\n    .m1 add command -label \"test3\"\n    .m1 activate 2\n    .m1 entrycget end -label\n} -cleanup {\n    deleteWindows\n} -result {test3}\ntest menu-13.4 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [.m1 insert last command -label \"test2\"] [.m1 entrycget last -label]\n} -cleanup {\n    deleteWindows\n} -result {e002 test2}\ntest menu-13.5 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [.m1 insert end command -label \"test2\"] [.m1 entrycget end -label]\n} -cleanup {\n    deleteWindows\n} -result {e002 test2}\ntest menu-13.6 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"active\"\n    .m1 add command -label \"test2\"\n    .m1 add command -label \"test3\"\n    .m1 activate 2\n    .m1 entrycget {} -label\n} -cleanup {\n    deleteWindows\n} -result {}\n#test menu-13.7 - Need to add @test here.\ntest menu-13.7 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"active\"\n    .m1 add command -label \"test2\"\n    .m1 add command -label \"test3\"\n    .m1 entrycget 1 -label\n} -cleanup {\n    deleteWindows\n} -result {active}\ntest menu-13.8 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"active\"\n    .m1 entrycget -1 -label\n} -returnCodes error -result {bad menu entry index \"-1\"}\ntest menu-13.9 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\"\n    .m1 entrycget 999 -label\n} -cleanup {\n    deleteWindows\n} -result {test2}\ntest menu-13.10 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 insert 999 command -label \"test\"\n    .m1 entrycget 1 -label\n} -cleanup {\n    deleteWindows\n} -result {test}\ntest menu-13.11 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"1test\"\n    .m1 entrycget 1test -label\n} -cleanup {\n    deleteWindows\n} -result {1test}\ntest menu-13.12 {TkGetMenuIndex} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\" -command \"beep\"\n    .m1 add command -label \"test3\"\n    .m1 entrycget test2 -command\n} -cleanup {\n    deleteWindows\n} -result {beep}\n\ntest menu-14.1 {MenuCmdDeletedProc} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    destroy .m1\n} -cleanup {\n    deleteWindows\n} -returnCodes ok\ntest menu-14.2 {MenuCmdDeletedProc} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    destroy .m1\n} -cleanup {\n    deleteWindows\n} -returnCodes ok\n\ntest menu-15.1 {MenuNewEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-15.2 {MenuNewEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test3\"\n    .m1 insert 2 command -label \"test2\"\n} -cleanup {\n    deleteWindows\n} -result {e003}\ntest menu-15.3 {MenuNewEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\"\n} -cleanup {\n    deleteWindows\n} -result {e002}\ntest menu-15.4 {MenuNewEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\n\ntest menu-16.1 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 insert foo command -label \"test\"\n} -returnCodes error -result {bad menu entry index \"foo\"}\ntest menu-16.2 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 insert test command -label \"foo\"\n} -cleanup {\n    deleteWindows\n} -result {e002}\ntest menu-16.3 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 insert -1 command -label \"test\"\n} -returnCodes error -result {bad menu entry index \"-1\"}\ntest menu-16.4 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 1\n    .m1 add command -label \"test\"\n    .m1 insert 0 command -label \"test2\"\n    .m1 entrycget 1 -label\n} -cleanup {\n    deleteWindows\n} -result {test2}\ntest menu-16.5 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.6 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add checkbutton\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.7 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.8 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add radiobutton\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.9 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add separator\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.10 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add blork\n} -returnCodes error -result {bad menu entry type \"blork\": must be cascade, checkbutton, command, radiobutton, or separator}\ntest menu-16.11 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menu-16.12 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m2 clone .m3\n    list [.m2 add command -label \"test\"] [.m1 entrycget 1 -label] [.m3 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {e001 test test}\ntest menu-16.13 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m2 clone .m3\n    list [.m3 add command -label \"test\"] [.m1 entrycget 1 -label] [.m2 entrycget 1 -label]\n} -cleanup {\n    deleteWindows\n} -result {e001 test test}\ntest menu-16.14 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -blork fish\n} -returnCodes error -result {unknown option \"-blork\"}\ntest menu-16.15 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"File\"\n    menu .container\n    . configure -menu .container\n    list [.container add cascade -label \"File\" -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {e001 {}}\ntest menu-16.16 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    set tearoff [tk::TearOffMenu .m2]\n    list [.m2 add cascade -menu .m1] [$tearoff unpost]\n} -cleanup {\n    deleteWindows\n} -result {e001 {}}\ntest menu-16.17 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .container\n    . configure -menu .container\n    set tearoff [tk::TearOffMenu .container]\n    list [.container add cascade -label \"File\" -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {e001 {}}\ntest menu-16.18 {MenuAddOrInsert} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .container\n    .container add cascade -menu .m1\n    . configure -menu .container\n    list [.container add cascade -label \"File\" -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {e002 {}}\ntest menu-16.19 {MenuAddOrInsert - Insert a cascade deep into the tree} -setup {\n    deleteWindows\n} -body {\n    menu .menubar\n    menu .menubar.test -tearoff 0\n    .menubar add cascade -label Test -underline 0 -menu .menubar.test\n    menu .menubar.test.cascade -tearoff 0\n    .menubar.test.cascade add command -label SubItem -command \"puts SubItemSelected\"\n    . configure -menu .menubar\n    list [catch {.menubar.test add cascade -label SubMenu \\\n\t    -menu .menubar.test.cascade}] \\\n\t    [info commands .\\#menubar.\\#menubar\\#test.\\#menubar\\#test\\#cascade] \\\n\t    [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {0 .#menubar.#menubar#test.#menubar#test#cascade {}}\n\n\ntest menu-17.1 {MenuVarProc} -setup {\n    deleteWindows\n} -body {\n    catch {unset foo}\n    menu .m1\n    set foo \"hello\"\n    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \\\n\t    [unset foo]\n} -cleanup {\n    deleteWindows\n} -result {e001 {}}\n# menu-17.2 - Don't know how to generate the flags in the if\ntest menu-17.2 {MenuVarProc} -setup {\n    deleteWindows\n} -body {\n    catch {unset foo}\n    menu .m1\n    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \\\n\t    [set foo \"\"]\n} -cleanup {\n    deleteWindows\n} -result {e001 {}}\ntest menu-17.3 {MenuVarProc} -setup {\n    deleteWindows\n} -body {\n    catch {unset foo}\n    menu .m1\n    set foo \"hello\"\n    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \\\n\t    [set foo \"hello\"] [unset foo]\n} -cleanup {\n    deleteWindows\n} -result {e001 hello {}}\ntest menu-17.4 {MenuVarProc} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    set foo \"goodbye\"\n    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \\\n\t    [set foo \"hello\"] [unset foo]\n} -cleanup {\n    deleteWindows\n} -result {e001 hello {}}\ntest menu-17.5 {MenuVarProc} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    set foo \"hello\"\n    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \\\n\t    [set foo \"goodbye\"] [unset foo]\n} -cleanup {\n    deleteWindows\n} -result {e001 goodbye {}}\ntest menu-17.6 {MenuVarProc [5d991b822e]} -setup {\n    deleteWindows\n} -body {\n    # Want this not to crash\n    menu .b\n    set var INIT\n    .b add checkbutton -variable var\n    trace add variable var unset {apply {args {\n\t.b entryconfigure 1 -variable {}\n    }}}\n    unset var\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-17.7 {MenuVarProc [5d991b822e]} -setup {\n    deleteWindows\n} -body {\n    # Want this not to duplicate traces\n    menu .b\n    set var INIT\n    .b add checkbutton -variable var\n    trace add variable var unset {apply {args {\n\t.b entryconfigure 1 -variable new\n    }}}\n    unset var\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menu-18.1 {TkActivateMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 activate 1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-18.2 {TkActivateMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 activate 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-18.3 {TkActivateMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\"\n    .m1 activate 1\n    .m1 activate 2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-18.4 {TkActivateMenuEntry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test2\"\n    .m1 activate 1\n    .m1 activate 1\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menu-19.1 {TkPostCommand} -constraints nonUnixUserInteraction -setup {\n    deleteWindows\n} -body {\n    menu .m1 -postcommand \"set menu_test menu-19.1\"\n    .m1 add command -label \"menu-19.1 - hit Escape\"\n    list [.m1 post 40 40] [.m1 unpost] [set menu_test]\n} -cleanup {\n    deleteWindows\n} -result {menu-19.1 {} menu-19.1}\ntest menu-19.2 {TkPostCommand} -constraints nonUnixUserInteraction -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"menu-19.2 - hit Escape\"\n    list [.m1 post 40 40] [.m1 unpost]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\ntest menu-20.1 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2]\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.2 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 normal\n    deleteWindows\n} -result {}\ntest menu-20.3 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 tearoff\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.4 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 menubar\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.5 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2 foo\n} -returnCodes error -result {bad menu type \"foo\": must be menubar, normal, or tearoff}\ntest menu-20.6 {CloneMenu - hooking up bookeeping ptrs} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.7 {CloneMenu - hooking up bookeeping ptrs - multiple children} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 clone .m2\n    .m1 clone .m3\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.8 {CloneMenu - cascade entries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    .m1 clone .foo\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.9 {CloneMenu - cascades entries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    menu .m2\n    .m1 clone .foo\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-20.10 {CloneMenu - tearoff fields} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 1\n    list [.m1 clone .m2 normal] [.m2 cget -tearoff]\n} -cleanup {\n    deleteWindows\n} -result {{} 1}\ntest menu-20.11 {CloneMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m2\n    .m1 clone .m2\n} -returnCodes error -result {window name \"m2\" already exists in parent}\ntest menu-20.12 {CloneMenu - copied bindings on empty menu} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    menu .m1 -tearoff 0\n    bind .m1 <<Test>> {append x <<Test>>}\n    .m1 clone .m2 tearoff\n    .m2 post 100 100\n    event generate .m2 <<Test>>\n    return $x\n} -result {<<Test>>}\ntest menu-20.13 {CloneMenu - copied bindings on non-empty menu} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    menu .m1 -tearoff 1\n    bind .m1 <<Test>> {append x <<Test>>}\n    .m1 clone .m2 tearoff\n    .m2 post 100 100\n    event generate .m2 <<Test>>\n    return $x\n} -result {<<Test>>}\ntest menu-20.14 {CloneMenu - new binding on empty menu} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    menu .m1 -tearoff 0\n    .m1 clone .m2 tearoff\n    .m2 post 100 100\n    bind .m1 <<Test>> {append x <<Test>>}\n    event generate .m2 <<Test>>\n    return $x\n} -result {<<Test>>}\ntest menu-20.15 {CloneMenu - new binding on non-empty menu} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    menu .m1 -tearoff 1\n    .m1 clone .m2 tearoff\n    .m2 post 100 100\n    bind .m1 <<Test>> {append x <<Test>>}\n    event generate .m2 <<Test>>\n    return $x\n} -result {<<Test>>}\ntest menu-20.16 {CloneMenu - bindtags} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    bindtags .m1 [linsert [bindtags .m1] 1 .m1.sub1]\n    .m1 clone .m2\n    bindtags .m2\n} -result {.m2 .m1 .m1.sub1 Menu all}\n\ntest menu-21.1 {MenuDoYPosition} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 yposition glorp\n} -returnCodes error -result {bad menu entry index \"glorp\"}\ntest menu-21.2 {MenuDoYPosition} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"Test\"\n    .m1 yposition 1\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -match glob -result {*}\n\ntest menu-22.1 {GetIndexFromCoords} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -tearoff 0\n    .m1 index @5\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-22.2 {GetIndexFromCoords} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -tearoff 0\n    .m1 index @5,5\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-22.3 {GetIndexFromCoords: mapped window, y only} -setup {\n    deleteWindows\n} -constraints {x11} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -tearoff 0\n    tk_popup .m1 0 0\n    tkwait visibility .m1\n    .m1 index @5\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-22.4 {GetIndexFromCoords: mapped window x,y} -setup {\n    deleteWindows\n} -constraints {x11} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -tearoff 0\n    tk_popup .m1 0 0\n    tkwait visibility .m1\n    update\n    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]\n    .m1 index @$x,5\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-22.5 {GetIndexFromCoords: mapped wide window} -setup {\n    deleteWindows\n} -constraints {x11} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 configure -tearoff 0\n    tk_popup .m1 0 0\n    tkwait visibility .m1\n    wm geometry .m1 200x100\n    update\n    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]\n    .m1 index @$x,5\n} -cleanup {\n    deleteWindows\n} -result 0\ntest menu-22.6 {GetIndexFromCoords: syntax error in @x,y indices} -setup {\n    deleteWindows\n} -body {\n    menu .m\n    .m add command -label \"First entry\"\n    .m add command -label \"Second entry\"\n    .m add command -label \"Last entry\"\n    .m index @4bogus\n} -cleanup {\n    deleteWindows\n}  -returnCodes error -result {bad menu entry index \"@4bogus\"}\ntest menu-22.7 {GetIndexFromCoords: syntax error in @x,y indices} -setup {\n    deleteWindows\n} -body {\n    menu .m\n    .m add command -label \"First entry\"\n    .m add command -label \"Second entry\"\n    .m add command -label \"Last entry\"\n    .m index @10,4bogus\n} -cleanup {\n    deleteWindows\n}  -returnCodes error -result {bad menu entry index \"@10,4bogus\"}\ntest menu-22.8 {GetIndexFromCoords: syntax error in @x,y indices} -setup {\n    deleteWindows\n} -body {\n    menu .m\n    .m add command -label \"First entry\"\n    .m add command -label \"Second entry\"\n    .m add command -label \"Last entry\"\n    .m index @10,bogus\n} -cleanup {\n    deleteWindows\n}  -returnCodes error -result {bad menu entry index \"@10,bogus\"}\ntest menu-22.9 {GetIndexFromCoords: index type pecedence} -setup {\n    deleteWindows\n} -body {\n    menu .m -tearoff 0\n    .m add command -label \"First entry\"\n    .m add command -label \"@42nd street\"\n    .m add command -label \"Last entry\"\n    .m index \"@42nd*\"  ; # shall be interpreted as a pattern, not as @42\n} -cleanup {\n    deleteWindows\n} -result {1}\n\ntest menu-22.10 {tk_popup on separator entry} -setup {\n    deleteWindows\n} -constraints {x11} -body {\n    menu .m1\n    label .l -text ClickMe!\n    .m1 add command -label \"Example 1\" -command bell\n    .m1 add command -label \"Example 2\" -command bell\n    .m1 add separator\n    .m1 add command -label \"Example Other\" -command \"bell;bell\"\n    tk_popup .m1 100 100 2\n    set waiting 0\n    tkwait visibility .m1\n    after 333 incr waiting\n    vwait waiting\n    .m1 invoke 4\n    after 333 incr waiting\n    vwait waiting\n    destroy .m1\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest menu-23.1 {RecursivelyDeleteMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    . configure -menu .m1\n    . configure -menu \"\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-23.2 {RecursivelyDeleteMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m2\n    .m2 add command -label \"test2\"\n    menu .m1\n    .m1 add cascade -label \"test1\" -menu .m2\n    . configure -menu .m1\n    . configure -menu \"\"\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest menu-24.1 {TkNewMenuName} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-24.2 {TkNewMenuName} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    menu .m1\\#0\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-24.3 {TkNewMenuName} -setup {\n    deleteWindows\n} -body {\n    menu .#m\n    rename .#m hideme\n    list [catch {. configure -menu [menu .m]}] [. configure -menu \"\"] [destroy .#m] \\\n\t    [destroy .m] [destroy hideme]\n} -result {0 {} {} {} {}}\n\n\ntest menu-25.1 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.2 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.3 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    destroy .m1\n    menu .m1\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.4 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    . configure -menu .m1\n    menu .m2\n    list [. configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.5 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    . configure -menu .m1\n    .m1 clone .m2\n    menu .m3\n    list [. configure -menu .m3] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.6 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 clone .m2\n    . configure -menu .m2\n    menu .m3\n    list [. configure -menu .m3] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.7 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2\n    .t2 configure -menu .m1\n    list [.t2 configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.8 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2\n    wm geometry .t2 +0+0\n    .t2 configure -menu .m1\n    list [. configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.9 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    list [.t3 configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.10 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    list [.t2 configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.11 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    . configure -menu .m1\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    toplevel .t3 -menu .m1\n    wm geometry .t3 +0+0\n    list [. configure -menu .m2] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.12 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.13 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.14 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.15 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menu-25.16 {Tk_SetWindowMenubar} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    . configure -menu .m1\n    list [toplevel .t2 -menu m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {.t2 {}}\n\n\ntest menu-26.1 {DestroyMenuHashTable} -setup {\n    catch {interp delete testinterp}\n    deleteWindows\n} -body {\n    interp create testinterp\n    load {} Tk testinterp\n    interp eval testinterp {menu .m1}\n    interp delete testinterp\n} -returnCodes ok -result {}\n\n\ntest menu-27.1 {GetMenuHashTable} -setup {\n    catch {interp delete testinterp}\n    deleteWindows\n} -body {\n    interp create testinterp\n    load {} Tk testinterp\n    list [catch {interp eval testinterp {menu .m1}} msg] $msg [interp delete testinterp]\n} -cleanup {\n    deleteWindows\n} -result {0 .m1 {}}\n\n\ntest menu-28.1 {TkCreateMenuReferences - not there before} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menu-28.2 {TkCreateMenuReferences - there already} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m2\n    menu .m2\n} -cleanup {\n    deleteWindows\n} -result {.m2}\n\n\ntest menu-29.1 {TkFindMenuReferences - not there} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add cascade -menu .m2\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\n\ntest menu-30.1 {TkFindMenuReferences - there already} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    menu .m2\n    .m1 add cascade -menu .m2\n    list [. configure -menu .m1] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\n\ntest menu-31.1 {TkFreeMenuReferences - menuPtr} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    destroy .m1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-31.2 {TkFreeMenuReferences - cascadePtr} -setup {\n    deleteWindows\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add cascade -menu .m2\n    .m1 entryconfigure 1 -menu .m3\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-31.3 {TkFreeMenuReferences - topLevelListPtr} -setup {\n    deleteWindows\n} -body {\n    . configure -menu .m1\n    . configure -menu \"\"\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -result {}\ntest menu-31.4 {TkFreeMenuReferences - not empty} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m3\n    menu .m2\n    .m2 add cascade -menu .m3\n    .m2 entryconfigure 1 -menu \".foo\"\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menu-32.1 {DeleteMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    .m1 clone .m2\n    .m1 delete 1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.2 {DeleteMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n\n    menu .m1\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 add command -label three\n    .m1 add command -label four\n    .m1 clone .m2\n    .m1 delete 2 3\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.3 {DeleteMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 add command -label three\n    .m1 add command -label four\n    .m1 clone .m2\n    .m2 configure -tearoff 1\n    .m1 delete 1 2\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.4 {DeleteMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 add command -label three\n    .m1 add command -label four\n    .m1 clone .m2\n    .m2 configure -tearoff 0\n    .m1 delete 2 3\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.5 {DeleteMenuCloneEntries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 clone .m2\n    .m1 activate one\n    .m1 delete one\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.6 {DeleteMenuCloneEntries - reentrancy - crashes tk8.0} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label test \\\n\t    -command \".m1 delete test ; .m1 add command -label test -command \\\".m1 delete test\\\"; .m1 delete test\"\n    .m1 invoke test\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.7 {DeleteMenuCloneEntries - one entry} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello\n    .m1 delete Hello\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.8 {Ensure all menu clone commands are deleted} -setup {\n    deleteWindows\n} -body {\n    # SF bug #465324\n    menu .menubar\n    . configure -menu .menubar\n    menu .menubar.test\n    .menubar.test add command -label \"hi\"\n    for {set i 0} {$i < 10} {incr i} {\n\t.menubar add cascade -menu .menubar.test -label \"Test\"\n\t.menubar delete Test\n    }\n\n    info commands .#menubar*test*\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menu-32.9 {Ensure deleting of clones doesn't corrupt menu refs} -setup {\n    set res {}\n    deleteWindows\n} -body {\n    menu .menubar\n    . configure -menu .menubar\n    menu .menubar.test\n    .menubar add cascade -menu .menubar.test -label \"Test\"\n    menu .menubar.cascade\n\n    .menubar.test add cascade -menu .menubar.cascade -label \"Cascade\"\n    lappend res [.menubar.test entrycget 1 -menu]\n    lappend res [.#menubar.#menubar#test entrycget 1 -menu]\n    destroy .menubar.test\n    menu .menubar.test\n    .menubar.test add cascade -menu .menubar.cascade -label \"Cascade\"\n    lappend res [.menubar.test entrycget 1 -menu]\n    lappend res [.#menubar.#menubar#test entrycget 1 -menu]\n    return $res\n} -cleanup {\n    deleteWindows\n} -result {.menubar.cascade .#menubar.#menubar#test.#menubar#cascade .menubar.cascade .#menubar.#menubar#test.#menubar#cascade}\n\n\ntest menu-33.1 {menu vs command hiding} -setup {\n    deleteWindows\n} -body {\n    set l [interp hidden]\n    menu .m\n    interp hide {} .m\n    destroy .m\n    set result [list [winfo children .] [interp hidden]]\n    expr {$result eq [list {} $l]}\n} -result 1\n\n# menu-34 MenuInit only called at boot time\n\n# creating menus on two different screens then deleting the\n# menu from the first screen crashes Tk8.3.1\n#\ntest menu-34.1 {menus on multiple screens - crashes tk8.3.1, Bug 5454} -constraints {\n    altDisplay\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .one\n    menu .one.m\n    toplevel .two -screen $::env(TK_ALT_DISPLAY)\n    menu .two.m\n    destroy .one\n    destroy .two\n} -result {}\n\ntest menu-35.1 {menu -underline string overruns Bug 1599877} -setup {\n   destroy .m\n} -body {\n    # ensure that -underline does not do string overruns [Bug 1599877]\n    menu .m\n    .m add command -label \"File\" -underline [expr {1<<30}]\n    . configure -menu .m\n    update\n    tk::TraverseToMenu . \"e\"\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest menu-37.1 {menubar menues cannot be posted - bug 2160206} -setup {\n    catch {destroy .m}\n} -body {\n    # On Linux the following used to panic\n    # It now returns an error (on all platforms)\n    menu .m -type menubar\n    list [catch \".m post 1 1\" msg] $msg\n} -cleanup {\n    destroy .m\n} -result {1 {a menubar menu cannot be posted}}\n\ntest menu-38.1 {Can't dismiss ttk::menubutton menu until mouse has hovered over it - bug fa32290898} -setup {\n} -constraints {x11} -body {\n    toplevel .top\n    ttk::menubutton .top.mb -text \"Some menu\";\n    menu .top.mb.m;\n    .top.mb.m add command -label \"Item 1\";\n    .top.mb.m add command -label \"Item 2\";\n    .top.mb configure -menu .top.mb.m;\n    pack .top.mb\n    update\n    # simulate mouse click on the menubutton, which posts its menu\n    event generate .top.mb <Button-1> -warp 1\n    controlPointerWarpTiming\n    event generate .top.mb <ButtonRelease-1>\n    update\n    # simulate mouse click on the menu again, i.e. without\n    # entering/leaving the posted menu\n    event generate .top.mb <Button-1>\n    update\n    after 50\n    event generate .top.mb <ButtonRelease-1>\n    update\n    # the menu shall have been unposted by the second click\n    winfo ismapped .top.mb.m\n} -cleanup {\n    destroy .top.mb.m .top.m .top\n} -result 0\n\ntest menu-39.1 {empty -type - bug be8f5b9fc2} -setup {\n    catch {destroy .m}\n} -body {\n    menu .m -type {}\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {ambiguous type \"\": must be menubar, normal, or tearoff}\n\ntest menu-39.2 {use-after-free fix - bug 1797555fff} -setup {\n    toplevel .t\n    menu .t.menubar -type menubar\n    menu .t.menubar.select -title Select\n    menu .t.menubar.select.chain -title Chain\n    .t.menubar.select insert 1 cascade -menu .t.menubar.select.chain -label Chain\n    .t.menubar add cascade -menu .t.menubar.select -label Select\n    .t configure -menu .t.menubar\n    .t.menubar.select.chain insert 1 command\n    update idletasks\n} -body {\n    # The following two lines caused Tk to read from and write to freed memory\n    destroy .t.menubar.select.chain\n    .t.menubar.select delete 1\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest menu-40.1 {Use-after-free if menu destroyed while posted - bug 09a11fb1228f} -setup {\n} -constraints {testpressbutton} -body {\n    set done false\n    event generate {} <Motion> -x 100 -y 100\n    toplevel .t\n    menu .t.m\n    .t.m add command -command {puts Marco} -label Marco\n    .t.m add command -command {puts Polo} -label Polo\n    after 1000 {.t.m post 500 500}\n    after 2000 {destroy .t}\n    after 2500 {testpressbutton 530 510}\n    after 3000 {set done true}\n    tkwait variable done\n}\n\ntest menu-40.2 {Use-after-free if menu destroyed while posted - bug 09a11fb1228f} -setup {\n} -constraints {testmovemouse} -body {\n    set done false\n    event generate {} <Motion> -x 100 -y 100\n    toplevel .t\n    menu .t.m\n    .t.m add command -command {puts Marco} -label Marco\n    .t.m add command -command {puts Polo} -label Polo\n    after 1000 {.t.m post 500 500}\n    after 2000 {testmovemouse 530 510}\n    after 3000 {destroy .t}\n    after 3500 {testmovemouse 530 530}\n    after 4000 testpressbutton 530 530\n    after 4500 {set done true}\n    tkwait variable done\n    testpressbutton 530 510\n}\n\ntest menu-41.1 {identifiers - auto generated} -setup {\n    destroy .m\n} -body {\n    menu .m\n    list [.m add command -label 1] [.m add command -label 2] [.m add command -label 3]\n} -cleanup {\n    destroy .m\n} -result {e001 e002 e003}\ntest menu-41.2 {identifiers - out of sequence} -setup {\n    destroy .m\n} -body {\n    menu .m -tearoff 0\n    .m add command -label 1\n    .m insert 0 command -label 2\n    .m add command -label 3\n    list [.m index e001] [.m index e002] [.m index e003]\n} -cleanup {\n    destroy .m\n} -result {1 0 2}\ntest menu-41.3 {identifiers - out of sequence with tearoff} -setup {\n    destroy .m\n} -body {\n    menu .m -tearoff 1\n    .m add command -label 1\n    .m insert 0 command -label 2\n    .m add command -label 3\n    list [.m index e001] [.m index e002] [.m index e003]\n} -cleanup {\n    destroy .m\n} -result {2 1 3}\ntest menu-41.4 {identifiers - entry id} -setup {\n    destroy .m\n} -body {\n    menu .m -tearoff 1\n    .m add command -label 1\n    .m insert 0 command -label 2\n    .m add command -label 3\n    list [.m id 0] [.m id 1] [.m id 2] [.m id 3]\n} -cleanup {\n    destroy .m\n} -result {{} e002 e001 e003}\ntest menu-41.5 {identifiers - assigned} -setup {\n    destroy .m\n} -body {\n    menu .m\n    list [.m add command cmd1 -label 1] [.m insert 0 command cmd2 -label 2] [.m add command cmd3 -label 3]\n} -cleanup {\n    destroy .m\n} -result {cmd1 cmd2 cmd3}\ntest menu-41.6 {identifiers - mixed} -setup {\n    destroy .m\n} -body {\n    menu .m\n    list [.m add command -label 1] [.m insert 0 command cmd2 -label 2] [.m add command -label 3]\n} -cleanup {\n    destroy .m\n} -result {e001 cmd2 e002}\ntest menu-41.7 {identifiers - conflict} -setup {\n    destroy .m\n} -body {\n    menu .m\n    list [.m add command e002 -label 1] [.m add command -label 2] [.m add command -label 3]\n} -cleanup {\n    destroy .m\n} -result {e002 e001 e003}\ntest menu-41.8 {identifiers - clone of complete menu} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label 1\n    .m1 insert 0 command -label 2\n    .m1 add command cmd3 -label 3\n    .m1 clone .m2\n    list [.m2 index e001] [.m2 index e002] [.m2 index cmd3]\n} -cleanup {\n    destroy .m1 .m2\n} -result {1 0 2}\ntest menu-41.9 {identifiers - modify after cloning} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1 -tearoff 0\n    .m1 clone .m2\n    .m1 add command -label 1\n    .m1 insert 0 command -label 2\n    .m1 add command cmd3 -label 3\n    list [.m2 index e001] [.m2 index e002] [.m2 index cmd3]\n} -cleanup {\n    destroy .m1 .m2\n} -result {1 0 2}\ntest menu-41.10 {identifiers - modify clone} -setup {\n    destroy .m1 .m2\n} -body {\n    menu .m1 -tearoff 0\n    .m1 clone .m2\n    .m2 add command -label 1\n    .m2 insert 0 command -label 2\n    .m2 add command cmd3 -label 3\n    list [.m1 index e001] [.m1 index e002] [.m1 index cmd3]\n} -cleanup {\n    destroy .m1 .m2\n} -result {1 0 2}\ntest menu-41.11 {identifiers - entrycget by id} -setup {\n    destroy .m\n} -body {\n    menu .m\n    .m add command -label 1\n    .m add command -label 2\n    .m add command cmd3 -label 3\n    list [.m entrycget e001 -label] [.m entrycget e002 -label] [.m entrycget cmd3 -label]\n} -cleanup {\n    destroy .m\n} -result {1 2 3}\ntest menu-41.12 {identifiers - delete by id} -setup {\n    destroy .m\n} -body {\n    menu .m\n    .m add command -label 1\n    .m add command -label 2\n    .m add command -label 3\n    .m add command -label 4\n    .m add command -label 5\n    .m add command -label 6\n    .m add command -label 7\n    .m add command cmd8 -label 8\n    .m add command cmd9 -label 9\n    .m delete e003 cmd8\n    list [.m id 0] [.m id 1] [.m id 2]\n} -cleanup {\n    destroy .m\n} -result {e001 e002 cmd9}\ntest menu-41.13 {identifiers - duplicate} -setup {\n    destroy .m\n} -body {\n    menu .m\n    .m add command foo -label 1\n    .m add command bar -label 2\n    .m add command foo -label 3\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {entry \"foo\" already exists}\ntest menu-41.14 {identifiers - reserved word} -setup {\n    destroy .m\n} -body {\n    menu .m -tearoff 0\n    .m add command last -label 1\n    .m add command -label 2\n    .m add command -label 3\n    .m index last\n} -cleanup {\n    destroy .m\n} -result {2}\n\n#\n# TESTFILE CLEANUP\n#\n\nunset earthPhotoFile\nimageFinish\ndeleteWindows\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/menuDraw.test",
    "content": "# This file is a Tcl script to test drawing of menus in Tk.\n#\n# Copyright © 1996-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# TESTS\n#\n\ntest menuDraw-1.1 {TkMenuInitializeDrawingFields} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.m1}\n\n\ntest menuDraw-2.1 {TkInitializeMenuEntryDrawingFields} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command\n} -cleanup {\n    deleteWindows\n} -result {e001}\n\n\ntest menuDraw-3.1 {TkMenuFreeDrawOptions} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    destroy .m1\n} -result {}\n\n\ntest menuDraw-4.1 {TkMenuEntryFreeDrawOptions} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"This is a test\"\n    destroy .m1\n} -result {}\ntest menuDraw-4.2 {TkMenuEntryFreeDrawOptions} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add checkbutton -label \"This is a test.\" -font \"Courier 12\" \\\n\t-activeforeground red -background green -selectcolor purple\n    destroy .m1\n} -result {}\n\n\ntest menuDraw-5.1 {TkMenuConfigureDrawOptions - new menu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n} -cleanup {\n    deleteWindows\n} -result {.m1}\ntest menuDraw-5.2 {TkMenuConfigureDrawOptions - old menu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 configure -fg red\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-5.3 {TkMenuConfigureDrawOptions - no disabledFg} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -disabledforeground \"\"\n} -cleanup {\n    deleteWindows\n} -result {.m1}\n\n\ntest menuDraw-6.1 {TkMenuConfigureEntryDrawOptions - no tkfont specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.2 {TkMenuConfigureEntryDrawOptions - tkfont specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -font \"Courier 12\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.3 {TkMenuConfigureEntryDrawOptions - active state - wrong entry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    .m1 entryconfigure 1 -state active\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.4 {TkMenuConfigureEntryDrawOptions - active state - correct entry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    .m1 activate 1\n    .m1 entryconfigure 1 -state active\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.5 {TkMenuConfigureEntryDrawOptions - deactivate entry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    .m1 activate 1\n    .m1 entryconfigure 1 -state normal\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.6 {TkMenuConfigureEntryDrawOptions - bad state} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    .m1 entryconfigure 1 -state foo\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad state \"foo\": must be active, disabled, or normal}\ntest menuDraw-6.7 {TkMenuConfigureEntryDrawOptions - tkfont specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -font \"Courier 12\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.8 {TkMenuConfigureEntryDrawOptions - border specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -background \"red\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.9 {TkMenuConfigureEntryDrawOptions - foreground specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -foreground \"red\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.10 {TkMenuConfigureEntryDrawOptions - activeBorder specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -activebackground \"red\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.11 {TkMenuConfigureEntryDrawOptions - activeforeground specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -activeforeground \"red\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.12 {TkMenuConfigureEntryDrawOptions - selectcolor specified} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add radiobutton -label \"foo\" -selectcolor \"red\"\n} -cleanup {\n    deleteWindows\n} -result {e001}\ntest menuDraw-6.13 {TkMenuConfigureEntryDrawOptions - textGC disposal} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -font \"Helvetica 12\"\n    .m1 entryconfigure 1 -font \"Courier 12\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.14 {TkMenuConfigureEntryDrawOptions - activeGC disposal} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -activeforeground \"red\"\n    .m1 entryconfigure 1 -activeforeground \"green\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.15 {TkMenuConfigureEntryDrawOptions - disabledGC disposal} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -disabledforeground \"red\"\n    .m1 add command -label \"foo\"\n    .m1 configure -disabledforeground \"green\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-6.16 {TkMenuConfigureEntryDrawOptions - indicatorGC disposal} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add radiobutton -label \"foo\" -selectcolor \"red\"\n    .m1 entryconfigure 1 -selectcolor \"green\"\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-7.1 {TkEventuallyRecomputeMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"This is a long label\"\n    set tearoff [tk::TearOffMenu .m1]\n    update idletasks\n    .m1 entryconfigure 1 -label \"foo\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-7.2 {TkEventuallyRecomputeMenu - update pending} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"This is a long label\"\n    set tearoff [tk::TearOffMenu .m1]\n    .m1 entryconfigure 1 -label \"foo\"\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-8.1 {TkRecomputeMenu} -constraints {\n    win userInteraction\n} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 configure -postcommand [.m1 add command -label foo]\n    .m1 add command -label \"Hit ESCAPE to make this menu go away.\"\n    .m1 post 0 0\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-9.1 {TkEventuallyRedrawMenu - entry test} -setup {\n    deleteWindows\n} -body {\n    catch {unset foo}\n    menu .m1\n    set foo 0\n    .m1 add radiobutton -variable foo -label test\n    tk::TearOffMenu .m1\n    update idletasks\n    list [set foo test] [destroy .m1] [unset foo]\n} -result {test {} {}}\ntest menuDraw-9.2 {TkEventuallyRedrawMenu - whole menu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    tk::TearOffMenu .m1\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -match glob -result *\n\n\n# Don't know how to test when window has been deleted and ComputeMenuGeometry\n# gets called.\ntest menuDraw-10.1 {ComputeMenuGeometry - menubar} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label test\n    . configure -menu .m1\n    list [update idletasks] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menuDraw-10.2 {ComputeMenuGeometry - non-menubar} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label test\n    update idletasks\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-10.3 {ComputeMenuGeometry - Resize necessary} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label test\n    update idletasks\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-10.4 {ComputeMenuGeometry - resize not necessary} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label test\n    update idletasks\n    .m1 entryconfigure 1 -label test\n    update idletasks\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-11.1 {TkMenuSelectImageProc - entry selected; redraw not pending} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image create test image2\n    menu .m1\n    .m1 add checkbutton -image image1 -selectimage image2\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update idletasks\n    list [image delete image2] [destroy .m1]\n} -cleanup {\n    imageCleanup\n} -result {{} {}}\ntest menuDraw-11.2 {TkMenuSelectImageProc - entry selected; redraw pending} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image create test image2\n    menu .m1\n    .m1 add checkbutton -image image1 -selectimage image2\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [image delete image2] [destroy .m1]\n} -cleanup {\n    imageCleanup\n} -result {{} {}}\ntest menuDraw-11.3 {TkMenuSelectImageProc - entry not selected} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image create test image2\n    menu .m1\n    .m1 add checkbutton -image image1 -selectimage image2\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update idletasks\n    list [image delete image2] [destroy .m1]\n} -cleanup {\n    imageCleanup\n} -result {{} {}}\n\n#Don't know how to test missing tkwin in DisplayMenu\ntest menuDraw-12.1 {DisplayMenu - menubar background} -constraints unix -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label foo -menu .m2\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menuDraw-12.2 {Display menu - no entries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-12.3 {DisplayMenu - one entry} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-12.4 {DisplayMenu - two entries} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw.12.5 {DisplayMenu - two columns - first bigger} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\"\n    .m1 add command -label \"three\" -columnbreak 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-12.5 {DisplayMenu - two column - second  bigger} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\" -columnbreak 1\n    .m1 add command -label \"three\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw.12.7 {DisplayMenu - three columns} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\" -columnbreak 1\n    .m1 add command -label \"three\"\n    .m1 add command -label \"four\"\n    .m1 add command -label \"five\"\n    .m1 add command -label \"six\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-12.6 {Display menu - testing for extra space and menubars} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    . configure -menu .m1\n    update\n    . configure -menu \"\"\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-12.7 {Display menu - extra space at end of menu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    wm geometry $tearoff 200x100\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-13.1 {TkMenuEventProc - Expose} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    menu .m2\n    .m2 add command -label \"two\"\n    set tearoff1 [tk::TearOffMenu .m1 40 40]\n    set tearoff2 [tk::TearOffMenu .m2 40 40]\n    list [raise $tearoff2] [update]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menuDraw-13.2 {TkMenuEventProc - ConfigureNotify} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [wm geometry $tearoff 200x100] [update]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n# Testing deletes is hard, and I am going to do my best. Don't know how\n# to test the case where we have already cleared the tkwin field in the\n# menuPtr.\ntest menuDraw-13.4 {TkMenuEventProc - simple delete} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    destroy .m1\n} -result {}\ntest menuDraw-13.5 {TkMenuEventProc - nothing pending} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    update idletasks\n    destroy .m1\n} -result {}\n\n\ntest menuDraw-14.1 {TkMenuImageProc} -constraints testImageType -setup {\n    deleteWindows\n} -body {\n    catch {image delete image1}\n    menu .m1\n    image create test image1\n    .m1 add command -image image1\n    update idletasks\n    image delete image1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-14.2 {TkMenuImageProc} -constraints testImageType -setup {\n    deleteWindows\n} -body {\n    catch {image delete image1}\n    menu .m1\n    image create test image1\n    .m1 add command -image image1\n    image delete image1\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest menuDraw-15.1 {TkPostTearoffMenu - Basic posting} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    tk::TearOffMenu .m1 40 40\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -match glob -result *\ntest menuDraw-15.2 {TkPostTearoffMenu - Deactivation} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\" -state active\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    expr {[$tearoff index active]<0}\n} -cleanup {\n    deleteWindows\n} -result 1\ntest menuDraw-15.3 {TkPostTearoffMenu - post command} -setup {\n    deleteWindows\n} -body {\n    catch {unset foo}\n    menu .m1 -postcommand \"set foo .m1\"\n    .m1 add command -label \"foo\"\n    list [catch {tk::TearOffMenu .m1 40 40}] [set foo] [unset foo] [destroy .m1]\n} -result {0 .m1 {} {}}\ntest menuDraw-15.4 {TkPostTearoffMenu - post command deleting the menu} -setup {\n    deleteWindows\n} -body {\n    menu .m1 -postcommand \"destroy .m1\"\n    .m1 add command -label \"foo\"\n    list [catch {tk::TearOffMenu .m1 40 40} msg] $msg [winfo exists .m1]\n} -result {0 {} 0}\ntest menuDraw-15.5 {TkPostTearoffMenu - tearoff at edge of screen} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    set height [winfo screenheight .m1]\n    tk::TearOffMenu .m1 40 $height\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -match glob -result *\ntest menuDraw-15.6 {TkPostTearoffMenu - tearoff off right} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add command -label \"foo\"\n    set width [winfo screenwidth .m1]\n    tk::TearOffMenu .m1 $width 40\n} -cleanup {\n    deleteWindows\n} -returnCodes ok -match glob -result *\n\n\ntest menuDraw-16.1 {TkPostSubmenu} -constraints nonUnixUserInteraction -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m2\n    menu .m2\n    .m2 add command -label \"Hit ESCAPE to make this menu go away.\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade 0\n    $tearoff postcascade 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-16.2 {TkPostSubMenu} -constraints nonUnixUserInteraction -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label \"two\" -menu .m2\n    .m1 add cascade -label \"three\" -menu .m3\n    menu .m2\n    .m2 add command -label \"two\"\n    menu .m3\n    .m3 add command -label \"three\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade 0\n    $tearoff postcascade 1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-16.3 {TkPostSubMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m2\n    .m1 postcascade 1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-16.4 {TkPostSubMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-16.5 {TkPostSubMenu} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m2\n    menu .m2 -postcommand \"glorp\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade test\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid command name \"glorp\"}\ntest menuDraw-16.6 {TkPostSubMenu} -constraints {\n    win userInteraction\n} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m2\n    menu .m2\n    .m2 add command -label \"Hit ESCAPE to get rid of this menu\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest menuDraw-16.7 {Recursive menu, TkPostSubMenu [bug 7f67bb4054]} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m1\n    .m1 post 100 100\n    .m1 postcascade 0\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {cannot add recursive cascade menu \".m1\"}\ntest menuDraw-16.8 {Recursive cloned menu [bug 7f67bb4054]} -setup {\n    deleteWindows\n} -body {\n    menu .mbar -title MENU\n    menu .mbar.edit\n    .mbar.edit add cascade -label COMMAND -menu .foo\n    .mbar add cascade -label CASCADE -menu .mbar.edit\n    . configure -menu .mbar\n    .#mbar.#mbar#edit entryconfigure last -menu .mbar\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {cannot add recursive cascade menu \".mbar\"}\n\ntest menuDraw-17.1 {AdjustMenuCoords - menubar} -constraints unix -setup {\n    deleteWindows\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label test -menu .m2\n    menu .m2 -tearoff 0\n    .m2 add command -label foo\n    . configure -menu .m1\n    foreach w [winfo children .] {\n\tif {[$w cget -type] eq \"menubar\"} {\n\t    break\n\t}\n    }\n    list [$w postcascade 0] [. configure -menu \"\"]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\ntest menuDraw-17.2 {AdjustMenuCoords - menu} -constraints {\n    win userInteraction\n} -setup {\n    deleteWindows\n} -body {\n    menu .m1\n    .m1 add cascade -label test -menu .m2\n    menu .m2\n    .m2 add command -label \"Hit ESCAPE to make this menu go away\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff postcascade 0\n} -cleanup {\n    deleteWindows\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ndeleteWindows\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/menubut.test",
    "content": "# This file is a Tcl script to test menubuttons in Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is woefully incomplete right now. Many procedures have no\n# tests. The tests for ConfigureMenuButton are incomplete.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n\n# Create entries in the option database to be sure that geometry options\n# like border width have predictable values.\n\noption add *Menubutton.borderWidth 2\noption add *Menubutton.highlightThickness 2\noption add *Menubutton.font {Helvetica -12 bold}\noption add *Button.borderWidth 2\noption add *Button.highlightThickness 2\noption add *Button.font {Helvetica -12 bold}\n\nmenubutton .mb -text \"Test\"\npack .mb\nupdate\n\n#\n# TESTS\n#\n\ntest menubutton-1.1 {configuration options} -body {\n    .mb configure -activebackground #012345\n    .mb cget -activebackground\n} -cleanup {\n    .mb configure -activebackground [lindex [.mb configure -activebackground] 3]\n} -result {#012345}\ntest menubutton-1.2 {configuration options} -body {\n    .mb configure -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest menubutton-1.3 {configuration options} -body {\n    .mb configure -activeforeground #ff0000\n    .mb cget -activeforeground\n} -cleanup {\n    .mb configure -activeforeground [lindex [.mb configure -activeforeground] 3]\n} -result {#ff0000}\ntest menubutton-1.4 {configuration options} -body {\n    .mb configure -activeforeground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest menubutton-1.5 {configuration options} -body {\n    .mb configure -anchor nw\n    .mb cget -anchor\n} -cleanup {\n    .mb configure -anchor [lindex [.mb configure -anchor] 3]\n} -result {nw}\ntest menubutton-1.6 {configuration options} -body {\n    .mb configure -anchor bogus\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest menubutton-1.7 {configuration options} -body {\n    .mb configure -background #ff0000\n    .mb cget -background\n} -cleanup {\n    .mb configure -background [lindex [.mb configure -background] 3]\n} -result {#ff0000}\ntest menubutton-1.8 {configuration options} -body {\n    .mb configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest menubutton-1.9 {configuration options} -body {\n    .mb configure -bd 4\n    .mb cget -bd\n} -cleanup {\n    .mb configure -bd [lindex [.mb configure -bd] 3]\n} -result 4\ntest menubutton-1.10 {configuration options} -body {\n    .mb configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest menubutton-1.11 {configuration options} -body {\n    .mb configure -bg #ff0000\n    .mb cget -bg\n} -cleanup {\n    .mb configure -bg [lindex [.mb configure -bg] 3]\n} -result {#ff0000}\ntest menubutton-1.12 {configuration options} -body {\n    .mb configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest menubutton-1.13 {configuration options} -body {\n    .mb configure -bitmap questhead\n    .mb cget -bitmap\n} -cleanup {\n    .mb configure -bitmap [lindex [.mb configure -bitmap] 3]\n} -result {questhead}\ntest menubutton-1.14 {configuration options} -body {\n    .mb configure -bitmap badValue\n} -returnCodes error -result {bitmap \"badValue\" not defined}\ntest menubutton-1.15 {configuration options} -body {\n    .mb configure -borderwidth 1.3\n    .mb cget -borderwidth\n} -cleanup {\n    .mb configure -borderwidth [lindex [.mb configure -borderwidth] 3]\n} -result 1.3\ntest menubutton-1.16 {configuration options} -body {\n    .mb configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest menubutton-1.17 {configuration options} -body {\n    .mb configure -cursor arrow\n    .mb cget -cursor\n} -cleanup {\n    .mb configure -cursor [lindex [.mb configure -cursor] 3]\n} -result {arrow}\ntest menubutton-1.18 {configuration options} -body {\n    .mb configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest menubutton-1.19 {configuration options} -body {\n    .mb configure -direction below\n    .mb cget -direction\n} -cleanup {\n    .mb configure -direction [lindex [.mb configure -direction] 3]\n} -result {below}\ntest menubutton-1.20 {configuration options} -body {\n    .mb configure -direction badValue\n} -returnCodes error -result {bad direction \"badValue\": must be above, below, flush, left, or right}\ntest menubutton-1.21 {configuration options} -body {\n    .mb configure -disabledforeground #00ff00\n    .mb cget -disabledforeground\n} -cleanup {\n    .mb configure -disabledforeground [lindex [.mb configure -disabledforeground] 3]\n} -result {#00ff00}\ntest menubutton-1.22 {configuration options} -body {\n    .mb configure -disabledforeground xyzzy\n} -returnCodes error -result {unknown color name \"xyzzy\"}\ntest menubutton-1.23 {configuration options} -body {\n    .mb configure -fg #110022\n    .mb cget -fg\n} -cleanup {\n    .mb configure -fg [lindex [.mb configure -fg] 3]\n} -result {#110022}\ntest menubutton-1.24 {configuration options} -body {\n    .mb configure -fg bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest menubutton-1.25 {configuration options} -body {\n    .mb configure -font {Helvetica 12}\n    .mb cget -font\n} -cleanup {\n    .mb configure -font [lindex [.mb configure -font] 3]\n} -result {Helvetica 12}\ntest menubutton-1.26 {configuration options} -body {\n    .mb configure -foreground #110022\n    .mb cget -foreground\n} -cleanup {\n    .mb configure -foreground [lindex [.mb configure -foreground] 3]\n} -result {#110022}\ntest menubutton-1.27 {configuration options} -body {\n    .mb configure -foreground bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest menubutton-1.28 {configuration options} -body {\n    .mb configure -height 18\n    .mb cget -height\n} -cleanup {\n    .mb configure -height [lindex [.mb configure -height] 3]\n} -result 18\ntest menubutton-1.29 {configuration options} -body {\n    .mb configure -height 20.0\n} -returnCodes error -result {expected integer but got \"20.0\"}\ntest menubutton-1.30 {configuration options} -body {\n    .mb configure -highlightbackground #112233\n    .mb cget -highlightbackground\n} -cleanup {\n    .mb configure -highlightbackground [lindex [.mb configure -highlightbackground] 3]\n} -result {#112233}\ntest menubutton-1.31 {configuration options} -body {\n    .mb configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest menubutton-1.32 {configuration options} -body {\n    .mb configure -highlightcolor #110022\n    .mb cget -highlightcolor\n} -cleanup {\n    .mb configure -highlightcolor [lindex [.mb configure -highlightcolor] 3]\n} -result {#110022}\ntest menubutton-1.33 {configuration options} -body {\n    .mb configure -highlightcolor bogus\n} -returnCodes error -result {unknown color name \"bogus\"}\ntest menubutton-1.34 {configuration options} -body {\n    .mb configure -highlightthickness 18\n    .mb cget -highlightthickness\n} -cleanup {\n    .mb configure -highlightthickness [lindex [.mb configure -highlightthickness] 3]\n} -result 18\ntest menubutton-1.35 {configuration options} -body {\n    .mb configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest menubutton-1.36 {configuration options} -constraints {\n    testImageType\n} -setup {\n    catch {image delete image1}\n    image create test image1\n} -body {\n    .mb configure -image image1\n    .mb cget -image\n} -cleanup {\n    .mb configure -image [lindex [.mb configure -image] 3]\n    image create test image1\n} -result {image1}\ntest menubutton-1.37 {configuration options} -setup {\n    catch {image delete bogus}\n} -body {\n    .mb configure -image bogus\n} -cleanup {\n    .mb configure -image [lindex [.mb configure -image] 3]\n} -returnCodes error -result {image \"bogus\" does not exist}\ntest menubutton-1.38 {configuration options} -body {\n    .mb configure -indicatoron yes\n    .mb cget -indicatoron\n} -cleanup {\n    .mb configure -indicatoron [lindex [.mb configure -indicatoron] 3]\n} -result 1\ntest menubutton-1.39 {configuration options} -body {\n    .mb configure -indicatoron no_way\n} -returnCodes error -result {expected boolean value but got \"no_way\"}\ntest menubutton-1.40 {configuration options} -body {\n    .mb configure -justify right\n    .mb cget -justify\n} -cleanup {\n    .mb configure -justify [lindex [.mb configure -justify] 3]\n} -result {right}\ntest menubutton-1.41 {configuration options} -body {\n    .mb configure -justify bogus\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\ntest menubutton-1.42 {configuration options} -body {\n    .mb configure -menu {any old string}\n    .mb cget -menu\n} -cleanup {\n    .mb configure -menu [lindex [.mb configure -menu] 3]\n} -result {any old string}\ntest menubutton-1.43 {configuration options} -body {\n    .mb configure -padx 12\n    .mb cget -padx\n} -cleanup {\n    .mb configure -padx [lindex [.mb configure -padx] 3]\n} -result 12\ntest menubutton-1.44 {configuration options} -body {\n    .mb configure -padx 420x\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest menubutton-1.45 {configuration options} -body {\n    .mb configure -pady 12\n    .mb cget -pady\n} -cleanup {\n    .mb configure -pady [lindex [.mb configure -pady] 3]\n} -result 12\ntest menubutton-1.46 {configuration options} -body {\n    .mb configure -pady 420x\n} -returnCodes error -result {expected screen distance but got \"420x\"}\ntest menubutton-1.47 {configuration options} -body {\n    .mb configure -relief groove\n    .mb cget -relief\n} -cleanup {\n    .mb configure -relief [lindex [.mb configure -relief] 3]\n} -result {groove}\ntest menubutton-1.48 {configuration options} -body {\n    .mb configure -relief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest menubutton-1.49 {configuration options} -body {\n    .mb configure -state normal\n    .mb cget -state\n} -cleanup {\n    .mb configure -state [lindex [.mb configure -state] 3]\n} -result {normal}\ntest menubutton-1.50 {configuration options} -body {\n    .mb configure -state bogus\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\ntest menubutton-1.51 {configuration options} -body {\n    .mb configure -takefocus {any string}\n    .mb cget -takefocus\n} -cleanup {\n    .mb configure -takefocus [lindex [.mb configure -takefocus] 3]\n} -result {any string}\ntest menubutton-1.52 {configuration options} -body {\n    .mb configure -text {Sample text}\n    .mb cget -text\n} -cleanup {\n    .mb configure -text [lindex [.mb configure -text] 3]\n} -result {Sample text}\ntest menubutton-1.53 {configuration options} -body {\n    .mb configure -textvariable i\n    .mb cget -textvariable\n} -cleanup {\n    .mb configure -textvariable [lindex [.mb configure -textvariable] 3]\n} -result {i}\ntest menubutton-1.54 {configuration options} -body {\n    .mb configure -underline 5\n    .mb cget -underline\n} -cleanup {\n    .mb configure -underline [lindex [.mb configure -underline] 3]\n} -result 5\ntest menubutton-1.55 {configuration options} -body {\n    .mb configure -underline 3p\n} -returnCodes error -result {bad index \"3p\": must be integer?[+-]integer?, end?[+-]integer?, or \"\"}\ntest menubutton-1.56 {configuration options} -body {\n    .mb configure -width 402\n    .mb cget -width\n} -cleanup {\n    .mb configure -width [lindex [.mb configure -width] 3]\n} -result 402\ntest menubutton-1.57 {configuration options} -body {\n    .mb configure -width 3p\n} -returnCodes error -result {expected integer but got \"3p\"}\ntest menubutton-1.58 {configuration options} -body {\n    .mb configure -wraplength 100\n    .mb cget -wraplength\n} -cleanup {\n    .mb configure -wraplength [lindex [.mb configure -wraplength] 3]\n} -result 100\ntest menubutton-1.59 {configuration options} -body {\n    .mb configure -wraplength 6x\n} -returnCodes error -result {expected screen distance but got \"6x\"}\n\n#\n# COMMON TEST SETUP\n#\ndeleteWindows\nmenubutton .mb -text \"Test\"\npack .mb\nupdate\n\ntest menubutton-2.1 {Tk_MenubuttonCmd procedure} -body {\n    menubutton\n} -returnCodes error -result {wrong # args: should be \"menubutton pathName ?-option value ...?\"}\ntest menubutton-2.2 {Tk_MenubuttonCmd procedure} -body {\n    menubutton foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest menubutton-2.3 {Tk_MenubuttonCmd procedure} -body {\n    catch {destroy .mb}\n    menubutton .mb\n    winfo class .mb\n} -result {Menubutton}\ntest menubutton-2.4 {Tk_ButtonCmd procedure} -setup {\n    destroy .mb\n} -body {\n    menubutton .mb -gorp foo\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest menubutton-2.5 {Tk_ButtonCmd procedure} -setup {\n    destroy .mb\n} -body {\n    catch {menubutton .mb -gorp foo}\n    winfo exists .mb\n} -result 0\n\n#\n# COMMON TEST SETUP\n#\ndeleteWindows\nmenubutton .mb -text \"Test Menu\"\npack .mb\n\ntest menubutton-3.1 {MenuButtonWidgetCmd procedure} -body {\n    .mb\n} -returnCodes error -result {wrong # args: should be \".mb option ?arg ...?\"}\ntest menubutton-3.2 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    .mb c\n} -returnCodes error -result {ambiguous option \"c\": must be cget or configure}\ntest menubutton-3.3 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    .mb cget\n} -returnCodes error -result {wrong # args: should be \".mb cget option\"}\ntest menubutton-3.4 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    .mb cget a b\n} -returnCodes error -result {wrong # args: should be \".mb cget option\"}\ntest menubutton-3.5 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    .mb cget -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest menubutton-3.6 {ButtonWidgetCmd procedure, \"cget\" option} -body {\n    .mb configure -highlightthickness 3\n    .mb cget -highlightthickness\n} -result 3\ntest menubutton-3.7 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    llength [.mb configure]\n} -result 33\ntest menubutton-3.8 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    .mb configure -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest menubutton-3.9 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    .mb co -bg #ffffff -fg\n} -returnCodes error -result {value for \"-fg\" missing}\ntest menubutton-3.10 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    .mb configure -fg #123456\n    .mb configure -bg #654321\n    lindex [.mb configure -fg] 4\n} -result {#123456}\ntest menubutton-3.11 {ButtonWidgetCmd procedure, \"configure\" option} -body {\n    .mb foobar\n} -returnCodes error -result {bad option \"foobar\": must be cget or configure}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest menubutton-4.1 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -text \"Menubutton 1\"\n    .mb1 configure -width 1i\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"1i\"}\ntest menubutton-4.2 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -text \"Menubutton 1\"\n    catch {.mb1 configure -width 1i}\n    return $errorInfo\n} -cleanup {\n    deleteWindows\n} -result {expected integer but got \"1i\"\n    (processing \"-width\" option)\n    invoked from within\n\".mb1 configure -width 1i\"}\n\ntest menubutton-4.3 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -text \"Menubutton 1\"\n    .mb1 configure -height 0.5c\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"0.5c\"}\ntest menubutton-4.4 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -text \"Menubutton 1\"\n    catch {.mb1 configure -height 0.5c}\n    return $errorInfo\n} -cleanup {\n    deleteWindows\n} -result {expected integer but got \"0.5c\"\n    (processing \"-height\" option)\n    invoked from within\n\".mb1 configure -height 0.5c\"}\n\ntest menubutton-4.5 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -bitmap questhead\n    .mb1 configure -width abc\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected screen distance but got \"abc\"}\ntest menubutton-4.6 {ConfigureMenuButton procedure} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -bitmap questhead\n    catch {.mb1 configure -width abc}\n    return $errorInfo\n} -cleanup {\n    deleteWindows\n} -result {expected screen distance but got \"abc\"\n    (processing \"-width\" option)\n    invoked from within\n\".mb1 configure -width abc\"}\n\ntest menubutton-4.7 {ConfigureMenuButton procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    button .mb1 -image image1\n    .mb1 configure -height 0.5x\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -returnCodes error -result {expected screen distance but got \"0.5x\"}\ntest menubutton-4.8 {ConfigureMenuButton procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    button .mb1 -image image1\n    catch {.mb1 configure -height 0.5x}\n    return $errorInfo\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {expected screen distance but got \"0.5x\"\n    (processing \"-height\" option)\n    invoked from within\n\".mb1 configure -height 0.5x\"}\n\ntest menubutton-4.9 {ConfigureMenuButton procedure} -constraints {\n    nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    button .mb1 -text \"Sample text\" -width 10 -height 2\n    pack .mb1\n    set result \"[winfo reqwidth .mb1] [winfo reqheight .mb1]\"\n    .mb1 configure -bitmap questhead\n    lappend result [winfo reqwidth .mb1] [winfo reqheight .mb1]\n} -cleanup {\n    deleteWindows\n} -result {102 46 20 12}\n\ntest menubutton-4.10 {ConfigureMenuButton procedure - bad direction} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text \"Test\"\n    .mb configure -direction badValue\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad direction \"badValue\": must be above, below, flush, left, or right}\ntest menubutton-4.11 {ConfigureMenuButton procedure - bad direction} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text \"Test\"\n    catch {.mb configure -direction badValue}\n    list [.mb cget -direction] [destroy .mb]\n} -cleanup {\n    deleteWindows\n} -result {below {}}\n\ntest menubutton-5.1 {MenuButtonEventProc procedure} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    menubutton .mb1 -bg #543210\n    rename .mb1 .mb2\n    lappend x [winfo children .]\n    lappend x [.mb2 cget -bg]\n    destroy .mb1\n    lappend x [info command .mb*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {.mb1 #543210 {} {}}\n\n\ntest menubutton-6.1 {MenuButtonCmdDeletedProc procedure} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb1\n    rename .mb1 {}\n    list [info command .mb*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\n#\n# COMMON TEST SETUP\n#\nif {[tk windowingsystem] eq \"aqua\"} {\n    set extraWidth 36\n} else {\n    set extraWidth 0\n}\n\ntest menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    menubutton .mb -image image1 -bd 4 -highlightthickness 0\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result [list [expr {38 + $extraWidth}] 23]\ntest menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    menubutton .mb -image image1 -bd 3 -highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result [list [expr {38 + $extraWidth}] 23]\ntest menubutton-7.3 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    menubutton .mb -image image1 -bd 1 -highlightthickness 3 -padx 5 -pady 5\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result [list [expr {38 + $extraWidth}] 23]\ntest menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    menubutton .mb -image image1 -bd 2 -relief raised -width 40 \\\n\t-highlightthickness 2\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result [list [expr {48 + $extraWidth}] 23]\ntest menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    menubutton .mb -image image1 -bd 2 -relief raised -height 30 \\\n\t-highlightthickness 2\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result [list [expr {38 + $extraWidth}] 38]\ntest menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -bitmap question -bd 2 -relief raised \\\n\t-highlightthickness 2\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result [list [expr {25 + $extraWidth}] 35]\ntest menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -bitmap question -bd 2 -relief raised -width 40 \\\n\t-highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result [list [expr {46 + $extraWidth}] 33]\ntest menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -bitmap question -bd 2 -relief raised -height 50 \\\n\t-highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result [list [expr {23 + $extraWidth}] 56]\ntest menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text String -bd 2 -relief raised -padx 0 -pady 0 \\\n\t-highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result {42 20}\ntest menubutton-7.10 {ComputeMenuButtonGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text String -bd 2 -relief raised -width 20 \\\n\t-padx 0 -pady 0 -highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result {146 20}\ntest menubutton-7.11 {ComputeMenuButtonGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text String -bd 2 -relief raised -height 2 \\\n\t-padx 0 -pady 0 -highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result {42 34}\ntest menubutton-7.12 {ComputeMenuButtonGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text String -bd 2 -relief raised -padx 10 -pady 5 \\\n\t-highlightthickness 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result {62 30}\ntest menubutton-7.13 {ComputeMenuButtonGeometry procedure} -constraints {\n    nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    menubutton .mb -text String -bd 2 -relief raised \\\n\t-highlightthickness 1 -indicatoron 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n} -result {78 28}\ntest menubutton-7.14 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType unix nonPortable\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    # The following test is non-portable because the indicator's pixel\n    # size varies to maintain constant absolute size.\n\n    menubutton .mb -image image1 -bd 2 -relief raised \\\n\t-highlightthickness 2 -indicatoron 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {64 23}\ntest menubutton-7.15 {ComputeMenuButtonGeometry procedure} -constraints {\n    testImageType win nonPortable\n} -setup {\n    deleteWindows\n    image create test image1\n} -body {\n    # The following test is non-portable because the indicator's pixel\n    # size varies to maintain constant absolute size.\n\n    menubutton .mb -image image1 -bd 2 -relief raised \\\n\t-highlightthickness 2 -indicatoron 1\n    pack .mb\n    list [winfo reqwidth .mb] [winfo reqheight .mb]\n} -cleanup {\n    deleteWindows\n    imageCleanup\n} -result {65 23}\n\n\ntest menubutton-8.1 {menubutton vs hidden commands} -body {\n    set l [interp hidden]\n    deleteWindows\n    menubutton .mb\n    interp hide {} .mb\n    destroy .mb\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 eq $res2}\n} -result 1\n\ntest menubutton-9.1 {Bug [5d991b822e]} {\n    # Want this not to segfault, or write to variable with empty name\n    unset -nocomplain {}\n    set var INIT\n    menubutton .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n    info exists {}\n} 0\ntest menubutton-9.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    menubutton .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\noption clear\nimageFinish\n\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/message.test",
    "content": "# This file is a Tcl script to test out the \"message\" command\n# of Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Ajuba Solutions.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest message-1.1 {configuration option: \"anchor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -anchor w\n    .m cget -anchor\n} -cleanup {\n    destroy .m\n} -result {w}\ntest message-1.2 {configuration option: \"anchor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -anchor bogus\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {bad anchor \"bogus\": must be n, ne, e, se, s, sw, w, nw, or center}\n\ntest message-1.3 {configuration option: \"aspect\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -aspect 3\n    .m cget -aspect\n} -cleanup {\n    destroy .m\n} -result 3\ntest message-1.4 {configuration option: \"aspect\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -aspect bogus\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected integer but got \"bogus\"}\n\ntest message-1.5 {configuration option: \"background\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -background #ff0000\n    .m cget -background\n} -cleanup {\n    destroy .m\n} -result {#ff0000}\ntest message-1.6 {configuration option: \"background\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -background non-existent\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest message-1.7 {configuration option: \"bd\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -bd 4\n    .m cget -bd\n} -cleanup {\n    destroy .m\n} -result 4\ntest message-1.8 {configuration option: \"bd\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -bd badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest message-1.9 {configuration option: \"bg\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -bg #ff0000\n    .m cget -bg\n} -cleanup {\n    destroy .m\n} -result {#ff0000}\ntest message-1.10 {configuration option: \"bg\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -bg non-existent\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest message-1.11 {configuration option: \"borderwidth\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -borderwidth 1.3\n    .m cget -borderwidth\n} -cleanup {\n    destroy .m\n} -result 1.3\ntest message-1.12 {configuration option: \"borderwidth\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -borderwidth badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest message-1.13 {configuration option: \"cursor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -cursor arrow\n    .m cget -cursor\n} -cleanup {\n    destroy .m\n} -result {arrow}\ntest message-1.14 {configuration option: \"cursor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -cursor badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest message-1.15 {configuration option: \"fg\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -fg #00ff00\n    .m cget -fg\n} -cleanup {\n    destroy .m\n} -result {#00ff00}\ntest message-1.16 {configuration option: \"fg\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -fg badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"badValue\"}\n\ntest message-1.17 {configuration option: \"font\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -font fixed\n    .m cget -font\n} -cleanup {\n    destroy .m\n} -result {fixed}\ntest message-1.18 {configuration option: \"font\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -font {}\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {font \"\" does not exist}\n\ntest message-1.19 {configuration option: \"-foreground\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -foreground  green\n    .m cget -foreground\n} -cleanup {\n    destroy .m\n} -result {green}\ntest message-1.20 {configuration option: \"-foreground\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -foreground  badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"badValue\"}\n\ntest message-1.21 {configuration option: \"highlightbackground\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightbackground  #112233\n    .m cget -highlightbackground\n} -cleanup {\n    destroy .m\n} -result {#112233}\ntest message-1.22 {configuration option: \"highlightbackground\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightbackground  ugly\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"ugly\"}\n\ntest message-1.23 {configuration option: \"highlightcolor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightcolor #123456\n    .m cget -highlightcolor\n} -cleanup {\n    destroy .m\n} -result {#123456}\ntest message-1.24 {configuration option: \"highlightcolor\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightcolor non-existent\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest message-1.25 {configuration option: \"highlightthickness\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightthickness  2\n    .m cget -highlightthickness\n} -cleanup {\n    destroy .m\n} -result 2\ntest message-1.26 {configuration option: \"highlightthickness\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -highlightthickness  badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest message-1.27 {configuration option: \"justify\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -justify  right\n    .m cget -justify\n} -cleanup {\n    destroy .m\n} -result {right}\ntest message-1.28 {configuration option: \"justify\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -justify bogus\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\n\ntest message-1.29 {configuration option: \"padx\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -padx  12m\n    .m cget -padx\n} -cleanup {\n    destroy .m\n} -result {12m}\ntest message-1.30 {configuration option: \"padx\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -padx 420x\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance or \"\" but got \"420x\"}\n\ntest message-1.31 {configuration option: \"pady\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -pady  12m\n    .m cget -pady\n} -cleanup {\n    destroy .m\n} -result {12m}\ntest message-1.32 {configuration option: \"pady\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -pady 420x\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance or \"\" but got \"420x\"}\n\ntest message-1.33 {configuration option: \"relief\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -relief ridge\n    .m cget -relief\n} -cleanup {\n    destroy .m\n} -result {ridge}\ntest message-1.34 {configuration option: \"relief\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -relief  badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest message-1.35 {configuration options: \"text\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -text \"Sample text\"\n    .m cget -text\n} -cleanup {\n    destroy .m\n} -result {Sample text}\n\ntest message-1.36 {configuration option: \"textvariable\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -textvariable  i\n    .m cget -textvariable\n} -cleanup {\n    destroy .m\n} -result {i}\n\ntest message-1.37 {configuration option: \"width\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -width  2\n    .m cget -width\n} -cleanup {\n    destroy .m\n} -result 2\ntest message-1.38 {configuration option: \"width\"} -setup {\n    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -width badValue\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest message-1.39 {configuration options, fallback to default} -setup {\n    message .m -borderwidth 0 -highlightthickness 0 -font {Helvetica -12 bold}\n    pack .m\n    update\n} -body {\n    .m configure -padx -2 -pady -2 -width -2\n    list [.m cget -padx] [.m cget -pady] [.m cget -borderwidth] [.m cget -highlightthickness]  [.m cget -width]\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {expected screen distance or \"\" but got \"-2\"}\n\n\ntest message-2.1 {Tk_MessageObjCmd procedure} -body {\n    message\n} -returnCodes error -result {wrong # args: should be \"message pathName ?-option value ...?\"}\n\ntest message-2.2 {Tk_MessageObjCmd procedure} -body {\n    message foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest message-2.3 {Tk_MessageObjCmd procedure} -body {\n    catch {message foo}\n    winfo children .\n} -result {}\n\ntest message-2.4 {Tk_MessageObjCmd procedure} -body {\n    message .s -gorp dump\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest message-2.5 {Tk_MessageObjCmd procedure} -body {\n    catch {message .s -gorp dump}\n    winfo children .\n} -result {}\n\n\ntest message-3.1 {MessageWidgetObjCmd procedure} -setup {\n    message .m\n} -body {\n    .m\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {wrong # args: should be \".m option ?arg ...?\"}\ntest message-3.2 {MessageWidgetObjCmd procedure, \"cget\"} -setup {\n    message .m\n} -body {\n    .m cget\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {wrong # args: should be \".m cget option\"}\ntest message-3.3 {MessageWidgetObjCmd procedure, \"cget\"} -setup {\n    message .m\n} -body {\n    .m cget -gorp\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown option \"-gorp\"}\n\ntest message-3.4 {MessageWidgetObjCmd procedure, \"configure\"} -setup {\n    message .m\n} -body {\n    .m configure -text foobar\n    lindex [.m configure -text] 4\n} -cleanup {\n    destroy .m\n} -result {foobar}\ntest message-3.5 {MessageWidgetObjCmd procedure, \"configure\"} -setup {\n    message .m\n} -body {\n    llength [.m configure]\n} -cleanup {\n    destroy .m\n} -result 21\ntest message-3.6 {MessageWidgetObjCmd procedure, \"configure\"} -setup {\n    message .m\n} -body {\n    .m configure -foo\n} -cleanup {\n    destroy .m\n} -returnCodes error -result {unknown option \"-foo\"}\ntest message-3.7 {MessageWidgetObjCmd procedure, \"configure\"} -setup {\n    message .m\n} -body {\n    .m configure -bd 4\n    .m configure -bg #ffffff\n    lindex [.m configure -bd] 4\n} -cleanup {\n    destroy .m\n} -result 4\n\ntest message-4.1 {Bug [5d991b822e]} {\n    # Want this not to segfault, or write to variable with empty name\n    unset -nocomplain {}\n    set var INIT\n    message .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n    info exists {}\n} 0\ntest message-4.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    message .b -textvariable var\n    trace add variable var unset {apply {args {\n\t.b configure -textvariable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/msgbox.test",
    "content": "# This file is a Tcl script to test out Tk's \"tk_messageBox\" command.\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding message boxes that\n# are specific to the windows platform go into the test file winMsgBox.test.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc ChooseMsg {parent btn} {\n    if {! $::dialogIsNative} {\n\tafter 100 SendButtonPress $parent $btn mouse\n    }\n}\n\nproc ChooseMsgByKey {parent btn} {\n    if {! $::dialogIsNative} {\n\tafter 100 SendButtonPress $parent $btn key\n    }\n}\n\n#\n# TESTS\n#\n\ntest msgbox-1.1.1 {tk_messageBox command} -constraints notAqua -body {\n    tk_messageBox -foo\n} -returnCodes error -result {bad option \"-foo\": must be -default, -detail, -icon, -message, -parent, -title, or -type}\ntest msgbox-1.1.2 {tk_messageBox command} -constraints aqua -body {\n    tk_messageBox -foo\n} -returnCodes error -result {bad option \"-foo\": must be -default, -detail, -icon, -message, -parent, -title, -type, or -command}\ntest msgbox-1.2.1 {tk_messageBox command} -constraints notAqua -body {\n    tk_messageBox -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -default, -detail, -icon, -message, -parent, -title, or -type}\ntest msgbox-1.2.2 {tk_messageBox command} -constraints aqua -body {\n    tk_messageBox -foo bar\n} -returnCodes error -result {bad option \"-foo\": must be -default, -detail, -icon, -message, -parent, -title, -type, or -command}\n\ntest msgbox-1.3 {tk_messageBox command} -body {\n    tk_messageBox -default\n} -returnCodes error -result {value for \"-default\" missing}\ntest msgbox-1.4 {tk_messageBox command} -body {\n    tk_messageBox -detail\n} -returnCodes error -result {value for \"-detail\" missing}\ntest msgbox-1.5 {tk_messageBox command} -body {\n    tk_messageBox -icon\n} -returnCodes error -result {value for \"-icon\" missing}\ntest msgbox-1.6 {tk_messageBox command} -body {\n    tk_messageBox -message\n} -returnCodes error -result {value for \"-message\" missing}\ntest msgbox-1.7 {tk_messageBox command} -body {\n    tk_messageBox -parent\n} -returnCodes error -result {value for \"-parent\" missing}\ntest msgbox-1.8 {tk_messageBox command} -body {\n    tk_messageBox -title\n} -returnCodes error -result {value for \"-title\" missing}\ntest msgbox-1.9 {tk_messageBox command} -body {\n    tk_messageBox -type\n} -returnCodes error -result {value for \"-type\" missing}\n\ntest msgbox-1.10 {tk_messageBox command} -body {\n    tk_messageBox -default\n} -returnCodes error -result {value for \"-default\" missing}\n\ntest msgbox-1.11 {tk_messageBox command} -body {\n    tk_messageBox -type foo\n} -returnCodes error -result {bad -type value \"foo\": must be abortretryignore, ok, okcancel, retrycancel, yesno, or yesnocancel}\n\ntest msgbox-1.13 {tk_messageBox command} -body {\n    tk_messageBox -default 1.1\n} -returnCodes error -result {bad -default value \"1.1\": must be abort, retry, ignore, ok, cancel, no, or yes}\n\ntest msgbox-1.14 {tk_messageBox command} -body {\n    tk_messageBox -default foo\n} -returnCodes error -result {bad -default value \"foo\": must be abort, retry, ignore, ok, cancel, no, or yes}\n\ntest msgbox-1.16 {tk_messageBox command} -body {\n    tk_messageBox -type yesno -default 3\n} -returnCodes error -result {bad -default value \"3\": must be abort, retry, ignore, ok, cancel, no, or yes}\n\ntest msgbox-1.18 {tk_messageBox command} -body {\n    tk_messageBox -icon foo\n} -returnCodes error -result {bad -icon value \"foo\": must be error, info, question, or warning}\n\ntest msgbox-1.19 {tk_messageBox command} -body {\n    tk_messageBox -parent foo.bar\n} -returnCodes error -result {bad window path name \"foo.bar\"}\n\n#\n# Try out all combinations of (type) x (default button) and\n# (type) x (icon).\n#\ntest msgbox-2.1 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" -type abortretryignore\n} -result {abort}\ntest msgbox-2.2 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" \\\n\t-type abortretryignore -icon warning\n} -result {abort}\ntest msgbox-2.3 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" \\\n\t-type abortretryignore -icon error\n} -result {abort}\ntest msgbox-2.4 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" \\\n\t-type abortretryignore -icon info\n} -result {abort}\ntest msgbox-2.5 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" \\\n\t-type abortretryignore -icon question\n} -result {abort}\ntest msgbox-2.6 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . abort\n    tk_messageBox -title Hi -message \"Please press abort\" \\\n\t-type abortretryignore -default abort\n} -result {abort}\ntest msgbox-2.7 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type abortretryignore -default retry\n} -result {retry}\ntest msgbox-2.8 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ignore\n    tk_messageBox -title Hi -message \"Please press ignore\" \\\n\t-type abortretryignore -default ignore\n} -result {ignore}\ntest msgbox-2.9 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" -type ok\n} -result {ok}\ntest msgbox-2.10 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type ok -icon warning\n} -result {ok}\ntest msgbox-2.11 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type ok -icon error\n} -result {ok}\ntest msgbox-2.12 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type ok -icon info\n} -result {ok}\ntest msgbox-2.13 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type ok -icon question\n} -result {ok}\ntest msgbox-2.14 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type ok -default ok\n} -result {ok}\ntest msgbox-2.15 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" -type okcancel\n} -result {ok}\ntest msgbox-2.16 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type okcancel -icon warning\n} -result {ok}\ntest msgbox-2.17 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type okcancel -icon error\n} -result {ok}\ntest msgbox-2.18 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type okcancel -icon info\n} -result {ok}\ntest msgbox-2.19 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type okcancel -icon question\n} -result {ok}\ntest msgbox-2.20 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . ok\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t-type okcancel -default ok\n} -result {ok}\ntest msgbox-2.21 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . cancel\n    tk_messageBox -title Hi -message \"Please press cancel\" \\\n\t-type okcancel -default cancel\n} -result {cancel}\ntest msgbox-2.22 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" -type retrycancel\n} -result {retry}\ntest msgbox-2.23 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type retrycancel -icon warning\n} -result {retry}\ntest msgbox-2.24 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type retrycancel -icon error\n} -result {retry}\ntest msgbox-2.25 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type retrycancel -icon info\n} -result {retry}\ntest msgbox-2.26 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type retrycancel -icon question\n} -result {retry}\ntest msgbox-2.27 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . retry\n    tk_messageBox -title Hi -message \"Please press retry\" \\\n\t-type retrycancel -default retry\n} -result {retry}\ntest msgbox-2.28 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . cancel\n    tk_messageBox -title Hi -message \"Please press cancel\" \\\n\t-type retrycancel -default cancel\n} -result {cancel}\ntest msgbox-2.29 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" -type yesno\n} -result {yes}\ntest msgbox-2.30 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesno -icon warning\n} -result {yes}\ntest msgbox-2.31 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesno -icon error\n} -result {yes}\ntest msgbox-2.32 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesno -icon info\n} -result {yes}\ntest msgbox-2.33 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesno -icon question\n} -result {yes}\ntest msgbox-2.34 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesno -default yes\n} -result {yes}\ntest msgbox-2.35 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . no\n    tk_messageBox -title Hi -message \"Please press no\" \\\n\t-type yesno -default no\n} -result {no}\ntest msgbox-2.36 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" -type yesnocancel\n} -result {yes}\ntest msgbox-2.37 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesnocancel -icon warning\n} -result {yes}\ntest msgbox-2.38 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesnocancel -icon error\n} -result {yes}\ntest msgbox-2.39 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesnocancel -icon info\n} -result {yes}\ntest msgbox-2.40 {tk_messageBox command -icon option} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesnocancel -icon question\n} -result {yes}\ntest msgbox-2.41 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . yes\n    tk_messageBox -title Hi -message \"Please press yes\" \\\n\t-type yesnocancel -default yes\n} -result {yes}\ntest msgbox-2.42 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . no\n    tk_messageBox -title Hi -message \"Please press no\" \\\n\t-type yesnocancel -default no\n} -result {no}\ntest msgbox-2.43 {tk_messageBox command} -constraints {\n    nonUnixUserInteraction\n} -body {\n    ChooseMsg . cancel\n    tk_messageBox -title Hi -message \"Please press cancel\" \\\n\t-type yesnocancel -default cancel\n} -result {cancel}\n\n\n# These tests will hang your test suite if they fail.\ntest msgbox-3.1 {tk_messageBox handles withdrawn parent} -constraints {\n\tnonUnixUserInteraction\n} -body {\n    wm withdraw .\n    ChooseMsg . \"ok\"\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t    -type ok -default ok\n} -cleanup {\n    wm deiconify .\n} -result {ok}\n\ntest msgbox-3.2 {tk_messageBox handles iconified parent} -constraints {\n\tnonUnixUserInteraction\n} -body {\n    wm iconify .\n    ChooseMsg . \"ok\"\n    tk_messageBox -title Hi -message \"Please press ok\" \\\n\t    -type ok -default ok\n} -cleanup {\n    wm deiconify .\n} -result {ok}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget dialog\ncleanupTests\n"
  },
  {
    "path": "tests/obj.test",
    "content": "# This file is a Tcl script to test new object types in Tk.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest obj-1.1 {TkGetPixelsFromObj} -body {\n} -result {}\n\ntest obj-2.1 {FreePixelInternalRep} -body {\n} -result {}\n\ntest obj-3.1 {DupPixelInternalRep} -body {\n} -result {}\n\ntest obj-4.1 {SetPixelFromAny} -body {\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/option.file1",
    "content": "! This file is a sample option (resource) database used to test\n! Tk's option-handling capabilities.\n\n! Comment line \\\n  with a backslash-newline sequence embedded in it.\n\n*x1: \tblue\n\t tktest.x2\t\t: green\n*\\\nx3 \\\n  : pur\\\nple\n*x 4:\tbrown\n# More comments, this time delimited by hash-marks.\n\t# Comment-line with space.\n*x6:\n*x9: \\ \\\t\\\\\\101\\n\n# comment line as last line of file.\n"
  },
  {
    "path": "tests/option.file2",
    "content": "*foo1: magenta\nfoo2 missing colon\n"
  },
  {
    "path": "tests/option.file3",
    "content": "! This file is a sample option (resource) database used to test\n! Tk's option-handling capabilities.\n\n! Comment line \\\n  with a backslash-newline sequence embedded in it.\n\n*x1: \tblue\n\t tktest.x2\t\t: green\n*\\\nx3 \\\n  : pur\\\nple\n*x 4:\tbrówn\n# More comments, this time delimited by hash-marks.\n\t# Comment-line with space.\n*x6:\n*x9: \\ \\\t\\\\\\101\\n\n# comment line as last line of file.\n"
  },
  {
    "path": "tests/option.test",
    "content": "# This file is a Tcl script to test out the option-handling facilities\n# of Tk.\n#\n# Copyright © 1991-1993 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\ntestConstraint appNameIsTktest [expr {[winfo name .] eq \"tktest\"}]\n\n#\n# COMMON TEST SETUP\n#\n\ndeleteWindows\nset appName [winfo name .]\n\n# First, test basic retrievals, being sure to trigger all the various\n# types of NodeElements (EXACT_LEAF_NAME, WILDCARD_NODE_CLASS, and\n# everything in-between).\n\nframe .op1 -class Class1\nframe .op2 -class Class2\nframe .op1.op3 -class Class1\nframe .op1.op4 -class Class3\nframe .op2.op5 -class Class2\nframe .op1.op3.op6 -class Class4\n\n# Configurations for tests 1.* - 12.*\noption clear\noption add *Color1 red\noption add *x blue\noption add *Class1.x yellow\noption add $appName.op1.x green\noption add *Class2.Color1 orange\noption add $appName.op2.op5.Color2 purple\noption add $appName.Class1.Class3.y brown\noption add $appName*op6*Color2 black\noption add $appName*Class1.op1.Color2 grey\n\n#\n# TESTS\n#\n\ntest option-1.1 {basic option retrieval} -body {\n    option get . x Color1\n} -result blue\ntest option-1.2 {basic option retrieval} -body {\n    option get . y Color1\n} -result red\ntest option-1.3 {basic option retrieval} -body {\n    option get . z Color1\n} -result red\ntest option-1.4 {basic option retrieval} -body {\n    option get . x Color2\n} -result blue\ntest option-1.5 {basic option retrieval} -body {\n    option get . y Color2\n} -result {}\ntest option-1.6 {basic option retrieval} -body {\n    option get . z Color2\n} -result {}\n\n\ntest option-2.1 {basic option retrieval} -body {\n    option get .op1 x Color1\n} -result green\ntest option-2.2 {basic option retrieval} -body {\n    option get .op1 y Color1\n} -result red\ntest option-2.3 {basic option retrieval} -body {\n    option get .op1 z Color1\n} -result red\ntest option-2.4 {basic option retrieval} -body {\n    option get .op1 x Color2\n} -result green\ntest option-2.5 {basic option retrieval} -body {\n    option get .op1 y Color2\n} -result {}\ntest option-2.6 {basic option retrieval} -body {\n    option get .op1 z Color2\n} -result {}\n\n\ntest option-3.1 {basic option retrieval} -body {\n    option get .op1.op3 x Color1\n} -result yellow\ntest option-3.2 {basic option retrieval} -body {\n    option get .op1.op3 y Color1\n} -result red\ntest option-3.3 {basic option retrieval} -body {\n    option get .op1.op3 z Color1\n} -result red\ntest option-3.4 {basic option retrieval} -body {\n    option get .op1.op3 x Color2\n} -result yellow\ntest option-3.5 {basic option retrieval} -body {\n    option get .op1.op3 y Color2\n} -result {}\ntest option-3.6 {basic option retrieval} -body {\n    option get .op1.op3 z Color2\n} -result {}\n\n\ntest option-4.1 {basic option retrieval} -body {\n    option get .op1.op3.op6 x Color1\n} -result blue\ntest option-4.2 {basic option retrieval} -body {\n    option get .op1.op3.op6 y Color1\n} -result red\ntest option-4.3 {basic option retrieval} -body {\n    option get .op1.op3.op6 z Color1\n} -result red\ntest option-4.4 {basic option retrieval} -body {\n    option get .op1.op3.op6 x Color2\n} -result black\ntest option-4.5 {basic option retrieval} -body {\n    option get .op1.op3.op6 y Color2\n} -result black\ntest option-4.6 {basic option retrieval} -body {\n    option get .op1.op3.op6 z Color2\n} -result black\n\n\ntest option-5.1 {basic option retrieval} -body {\n    option get .op1.op4 x Color1\n} -result blue\ntest option-5.2 {basic option retrieval} -body {\n    option get .op1.op4 y Color1\n} -result brown\ntest option-5.3 {basic option retrieval} -body {\n    option get .op1.op4 z Color1\n} -result red\ntest option-5.4 {basic option retrieval} -body {\n    option get .op1.op4 x Color2\n} -result blue\ntest option-5.5 {basic option retrieval} -body {\n    option get .op1.op4 y Color2\n} -result brown\ntest option-5.6 {basic option retrieval} -body {\n    option get .op1.op4 z Color2\n} -result {}\n\n\ntest option-6.1 {basic option retrieval} -body {\n    option get .op2 x Color1\n} -result orange\ntest option-6.2 {basic option retrieval} -body {\n    option get .op2 y Color1\n} -result orange\ntest option-6.3 {basic option retrieval} -body {\n    option get .op2 z Color1\n} -result orange\ntest option-6.4 {basic option retrieval} -body {\n    option get .op2 x Color2\n} -result blue\ntest option-6.5 {basic option retrieval} -body {\n    option get .op2 y Color2\n} -result {}\ntest option-6.6 {basic option retrieval} -body {\n    option get .op2 z Color2\n} -result {}\n\n\ntest option-7.1 {basic option retrieval} -body {\n    option get .op2.op5 x Color1\n} -result orange\ntest option-7.2 {basic option retrieval} -body {\n    option get .op2.op5 y Color1\n} -result orange\ntest option-7.3 {basic option retrieval} -body {\n    option get .op2.op5 z Color1\n} -result orange\ntest option-7.4 {basic option retrieval} -body {\n    option get .op2.op5 x Color2\n} -result purple\ntest option-7.5 {basic option retrieval} -body {\n    option get .op2.op5 y Color2\n} -result purple\ntest option-7.6 {basic option retrieval} -body {\n    option get .op2.op5 z Color2\n} -result purple\n\n#\n# COMMON TEST SETUP\n#\n\n# Now try similar tests to above, except jump around non-hierarchically\n# between windows to make sure that the option stacks are pushed and\n# popped correctly.\noption get . foo Foo\n\ntest option-8.1 {stack pushing/popping} -body {\n    option get .op2.op5 x Color1\n} -result orange\ntest option-8.2 {stack pushing/popping} -body {\n    option get .op2.op5 y Color1\n} -result orange\ntest option-8.3 {stack pushing/popping} -body {\n    option get .op2.op5 z Color1\n} -result orange\ntest option-8.4 {stack pushing/popping} -body {\n    option get .op2.op5 x Color2\n} -result purple\ntest option-8.5 {stack pushing/popping} -body {\n    option get .op2.op5 y Color2\n} -result purple\ntest option-8.6 {stack pushing/popping} -body {\n    option get .op2.op5 z Color2\n} -result purple\n\n\ntest option-9.1 {stack pushing/popping} -body {\n    option get . x Color1\n} -result blue\ntest option-9.2 {stack pushing/popping} -body {\n    option get . y Color1\n} -result red\ntest option-9.3 {stack pushing/popping} -body {\n    option get . z Color1\n} -result red\ntest option-9.4 {stack pushing/popping} -body {\n    option get . x Color2\n} -result blue\ntest option-9.5 {stack pushing/popping} -body {\n    option get . y Color2\n} -result {}\ntest option-9.6 {stack pushing/popping} -body {\n    option get . z Color2\n} -result {}\n\n\ntest option-10.1 {stack pushing/popping} -body {\n    option get .op1.op3.op6 x Color1\n} -result blue\ntest option-10.2 {stack pushing/popping} -body {\n    option get .op1.op3.op6 y Color1\n} -result red\ntest option-10.3 {stack pushing/popping} -body {\n    option get .op1.op3.op6 z Color1\n} -result red\ntest option-10.4 {stack pushing/popping} -body {\n    option get .op1.op3.op6 x Color2\n} -result black\ntest option-10.5 {stack pushing/popping} -body {\n    option get .op1.op3.op6 y Color2\n} -result black\ntest option-10.6 {stack pushing/popping} -body {\n    option get .op1.op3.op6 z Color2\n} -result black\n\n\ntest option-11.1 {stack pushing/popping} -body {\n    option get .op1.op3 x Color1\n} -result yellow\ntest option-11.2 {stack pushing/popping} -body {\n    option get .op1.op3 y Color1\n} -result red\ntest option-11.3 {stack pushing/popping} -body {\n    option get .op1.op3 z Color1\n} -result red\ntest option-11.4 {stack pushing/popping} -body {\n    option get .op1.op3 x Color2\n} -result yellow\ntest option-11.5 {stack pushing/popping} -body {\n    option get .op1.op3 y Color2\n} -result {}\ntest option-11.6 {stack pushing/popping} -body {\n    option get .op1.op3 z Color2\n} -result {}\n\n\ntest option-12.1 {stack pushing/popping} -body {\n    option get .op1 x Color1\n} -result green\ntest option-12.2 {stack pushing/popping} -body {\n    option get .op1 y Color1\n} -result red\ntest option-12.3 {stack pushing/popping} -body {\n    option get .op1 z Color1\n} -result red\ntest option-12.4 {stack pushing/popping} -body {\n    option get .op1 x Color2\n} -result green\ntest option-12.5 {stack pushing/popping} -body {\n    option get .op1 y Color2\n} -result {}\ntest option-12.6 {stack pushing/popping} -body {\n    option get .op1 z Color2\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# Test the major priority levels (widgetDefault, etc.)\n# Configurations for tests 13.*\n#\noption clear\noption add $appName.op1.a 100 100\noption add $appName.op1.A interactive interactive\noption add $appName.op1.b userDefault userDefault\noption add $appName.op1.B startupFile startupFile\noption add $appName.op1.c widgetDefault widgetDefault\noption add $appName.op1.C 0 0\n\ntest option-13.1 {priority levels} -body {\n    option get .op1 a A\n} -result 100\ntest option-13.2 {priority levels} -body {\n    option get .op1 b A\n} -result interactive\ntest option-13.3 {priority levels} -body {\n    option get .op1 b B\n} -result userDefault\ntest option-13.4 {priority levels} -body {\n    option get .op1 c B\n} -result startupFile\ntest option-13.5 {priority levels} -body {\n    option get .op1 c C\n} -result widgetDefault\n\n#\n# COMMON TEST SETUP\n#\noption add $appName.op1.B file2 widget\n\ntest option-13.6 {priority levels} -body {\n    option get .op1 c B\n} -result startupFile\n\n#\n# COMMON TEST SETUP\n#\noption add $appName.op1.B file2 startupFile\n\ntest option-13.7 {priority levels} -body {\n    option get .op1 c B\n} -result file2\n\n\n# Test various error conditions\n\ntest option-14.1 {error conditions} -body {\n    option\n} -returnCodes error -result {wrong # args: should be \"option cmd arg ?arg ...?\"}\ntest option-14.2 {error conditions} -body {\n    option x\n} -returnCodes error -result {bad option \"x\": must be add, clear, get, or readfile}\ntest option-14.3 {error conditions} -body {\n    option foo 3\n} -returnCodes error -result {bad option \"foo\": must be add, clear, get, or readfile}\ntest option-14.4 {error conditions} -body {\n    option add 3\n} -returnCodes error -result {wrong # args: should be \"option add pattern value ?priority?\"}\ntest option-14.5 {error conditions} -body {\n    option add . a b c\n} -returnCodes error -result {wrong # args: should be \"option add pattern value ?priority?\"}\ntest option-14.6 {error conditions} -body {\n    option add . a -1\n} -returnCodes error -result {bad priority level \"-1\": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}\ntest option-14.7 {error conditions} -body {\n    option add . a 101\n} -returnCodes error -result {bad priority level \"101\": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}\ntest option-14.8 {error conditions} -body {\n    option add . a gorp\n} -returnCodes error -result {bad priority level \"gorp\": must be widgetDefault, startupFile, userDefault, interactive, or a number between 0 and 100}\ntest option-14.9 {error conditions} -body {\n    option get 3\n} -returnCodes error -result {wrong # args: should be \"option get window name class\"}\ntest option-14.10 {error conditions} -body {\n    option get 3 4\n} -returnCodes error -result {wrong # args: should be \"option get window name class\"}\ntest option-14.11 {error conditions} -body {\n    option get 3 4 5 6\n} -returnCodes error -result {wrong # args: should be \"option get window name class\"}\ntest option-14.12 {error conditions} -body {\n    option get .gorp.gorp a A\n} -returnCodes error -result {bad window path name \".gorp.gorp\"}\n\n#\n# COMMON TEST SETUP\n#\nset option1 [file join [testsDirectory] option.file1]\n\ntest option-15.1 {database files} -body {\n    list [catch {option read non-existent} msg] [string tolower $msg]\n} -result {1 {couldn't open \"non-existent\": no such file or directory}}\ntest option-15.2 {database files} -body {\n    option read $option1\n    option get . x1 color\n} -result blue\ntest option-15.3 {database files} -constraints appNameIsTktest -body {\n    option read $option1\n    option get . x2 color\n} -result green\ntest option-15.4 {database files} -body {\n    option read $option1\n    option get . x3 color\n} -result purple\ntest option-15.5 {database files} -body {\n    option read $option1\n    option get . {x 4} color\n} -result brown\ntest option-15.6 {database files} -body {\n    option read $option1\n\toption get . x6 color\n} -result {}\ntest option-15.7 {database files} -body {\n    option read $option1\n\toption get . x9 color\n} -result \" \\\\\\t\\\\A\\n\"\ntest option-15.8 {database files} -body {\n    option read $option1 widget foo\n} -returnCodes error -result {wrong # args: should be \"option readfile fileName ?priority?\"}\ntest option-15.9 {database files} -body {\n    option add *x3 burgundy\n    catch {option read $option1 userDefault}\n    option get . x3 color\n} -result burgundy\ntest option-15.10 {database files} -body {\n    set option2 [file join [testsDirectory] option.file2]\n    option read $option2\n} -returnCodes error -result {missing colon on line 2}\n\ntest option-15.11 {database files} -setup {\n    set option3 [file join [testsDirectory] option.file3]\n    option read $option3\n} -body {\n    option get . {x 4} color\n} -result brówn\n\ntest option-16.1 {ReadOptionFile} -body {\n    set option4 [makeFile {} option.file4]\n    set file [open $option4 w]\n    fconfigure $file -translation crlf\n    puts $file \"*x7: true\\n*x8: false\"\n    close $file\n    option read $option4 userDefault\n    list [option get . x7 color] [option get . x8 color]\n} -cleanup {\n    removeFile $option4\n} -result {true false}\n\ntest option-16.2 {ticket 766ef52f3} -setup {\n    set expected [split {label {\n  foo bar\n}\n} \\n]\n} -body {\n    set option5 [makeFile {} option.file5]\n    set file [open $option5 w]\n    fconfigure $file -translation crlf\n    puts $file \"*notok: $expected\"\n    close $file\n    option read $option5 userDefault\n    expr {[option get . notok notok] eq $expected}\n} -cleanup {\n    removeFile $option5\n    unset expected\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ncleanupTests\n"
  },
  {
    "path": "tests/pack.test",
    "content": "# This file is a Tcl script to test out the \"pack\" command of Tk.\n#\n# Copyright © 1993 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\n# Create some test windows.\n\ndestroy .pack\ntoplevel .pack\nwm geom .pack 300x200+0+0\nwm minsize .pack 1 1\nupdate idletasks\nforeach i {a b c d} {\n    frame .pack.$i\n    label .pack.$i.label -text $i -relief raised\n    place .pack.$i.label -relwidth 1.0 -relheight 1.0\n}\n.pack.a config -width 20 -height 40\n.pack.b config -width 50 -height 30\n.pack.c config -width 80 -height 80\n.pack.d config -width 40 -height 30\n\n#\n# TESTS\n#\n\ntest pack-1.1 {-side option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+0 300x160+0+40}\ntest pack-1.2 {-side option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+160 300x160+0+0}\ntest pack-1.3 {-side option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side left\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+0+80 280x200+20+0}\ntest pack-1.4 {-side option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+280+80 280x200+0+0}\n\n\ntest pack-2.1 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -padx 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+260+80 240x200+0+0}\ntest pack-2.2 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -padx {10 30}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+250+80 240x200+0+0}\ntest pack-2.3 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -padx {35 5}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+275+80 240x200+0+0}\ntest pack-2.4 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipadx 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {60x40+240+80 240x200+0+0}\ntest pack-2.5 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipadx 5 -padx 10\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {30x40+260+80 250x200+0+0}\ntest pack-2.6 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -padx 20 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+260+80 240x200+0+0}\ntest pack-2.7 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -padx {9 31} -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+249+80 240x200+0+0}\ntest pack-2.8 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipadx 20 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {60x40+240+80 240x200+0+0}\ntest pack-2.9 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipadx 5 -padx 10 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {30x40+260+80 250x200+0+0}\ntest pack-2.10 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipadx 5 -padx {5 15} -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {30x40+255+80 250x200+0+0}\ntest pack-2.11 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+0 300x160+0+40}\ntest pack-2.12 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx {0 40}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+120+0 300x160+0+40}\ntest pack-2.13 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx {31 9}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+151+0 300x160+0+40}\ntest pack-2.14 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {60x40+120+0 300x160+0+40}\ntest pack-2.15 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {30x40+135+0 300x160+0+40}\ntest pack-2.16 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx {5 15}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {30x40+130+0 300x160+0+40}\ntest pack-2.17 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx 20 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {260x40+20+0 300x160+0+40}\ntest pack-2.18 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx {25 15} -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {260x40+25+0 300x160+0+40}\ntest pack-2.19 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 20 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {300x40+0+0 300x160+0+40}\ntest pack-2.20 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {280x40+10+0 300x160+0+40}\ntest pack-2.21 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx {5 15} -fill x\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {280x40+5+0 300x160+0+40}\ntest pack-2.22 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx 1c\n    set x [pack info .pack.a]\n    set res1 [lindex $x [expr {[lsearch -exact $x -padx]+1}]]\n    set res2 [winfo pixels .pack 1c]\n    expr {$res1 eq $res2}\n} -result 1\ntest pack-2.23 {x padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipadx 1c\n    set x [pack info .pack.a]\n    set res1 [lindex $x [expr {[lsearch -exact $x -ipadx]+1}]]\n    set res2 [winfo pixels .pack 1c]\n    expr {$res1 eq $res2}\n} -result 1\n\ntest pack-3.1 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -pady 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+280+80 280x200+0+0}\ntest pack-3.2 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -pady {5 35}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+280+65 280x200+0+0}\ntest pack-3.3 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -pady {40 0}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+280+100 280x200+0+0}\ntest pack-3.4 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x80+280+60 280x200+0+0}\ntest pack-3.5 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 5 -pady 10\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+280+75 280x200+0+0}\ntest pack-3.6 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 5 -pady {5 15}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+280+70 280x200+0+0}\ntest pack-3.7 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -pady 20 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x160+280+20 280x200+0+0}\ntest pack-3.8 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -pady {35 5} -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x160+280+35 280x200+0+0}\ntest pack-3.9 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 20 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x200+280+0 280x200+0+0}\ntest pack-3.10 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 5 -pady 10 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x180+280+10 280x200+0+0}\ntest pack-3.11 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -ipady 5 -pady {0 20} -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x180+280+0 280x200+0+0}\ntest pack-3.12 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -pady 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+20 300x120+0+80}\ntest pack-3.13 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -pady {40 0}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+40 300x120+0+80}\ntest pack-3.14 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 20\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x80+140+0 300x120+0+80}\ntest pack-3.15 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 5 -pady 10\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+140+10 300x130+0+70}\ntest pack-3.16 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 5 -pady {3 17}\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+140+3 300x130+0+70}\ntest pack-3.17 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -pady 20 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+20 300x120+0+80}\ntest pack-3.18 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -pady {39 1} -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x40+140+39 300x120+0+80}\ntest pack-3.19 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 20 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x80+140+0 300x120+0+80}\ntest pack-3.20 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 5 -pady 10 -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+140+10 300x130+0+70}\ntest pack-3.21 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipady 5 -pady {1 19} -fill y\n    pack .pack.b -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b]\n} -result {20x50+140+1 300x130+0+70}\ntest pack-3.22 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady 1c\n    set x [pack info .pack.a]\n    set res1 [lindex $x [expr {[lsearch -exact $x -pady]+1}]]\n    set res2 [winfo pixels .pack 1c]\n    expr {$res1 eq $res2}\n} -result 1\ntest pack-3.23 {y padding and filling} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipady 1c\n    set x [pack info .pack.a]\n    set res1 [lindex $x [expr {[lsearch -exact $x -ipady]+1}]]\n    set res2 [winfo pixels .pack 1c]\n    expr {$res1 eq $res2}\n} -result 1\n\ntest pack-4.1 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor n\n    update\n    winfo geometry .pack.a\n} -result {30x70+135+20}\ntest pack-4.2 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor ne\n    update\n    winfo geometry .pack.a\n} -result {30x70+260+20}\ntest pack-4.3 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor e\n    update\n    winfo geometry .pack.a\n} -result {30x70+260+65}\ntest pack-4.4 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor se\n    update\n    winfo geometry .pack.a\n} -result {30x70+260+110}\ntest pack-4.5 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor s\n    update\n    winfo geometry .pack.a\n} -result {30x70+135+110}\ntest pack-4.6 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor sw\n    update\n    winfo geometry .pack.a\n} -result {30x70+10+110}\ntest pack-4.7 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor w\n    update\n    winfo geometry .pack.a\n} -result {30x70+10+65}\ntest pack-4.8 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor nw\n    update\n    winfo geometry .pack.a\n} -result {30x70+10+20}\ntest pack-4.9 {anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center\n    update\n    winfo geometry .pack.a\n} -result {30x70+135+65}\n\n# Repeat above tests, but with a frame that isn't at (0,0), so that\n# we can be sure that the frame offset is being added in correctly.\n\ntest pack-5.1 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor n\n    update\n    winfo geometry .pack.b\n} -result {60x60+160+60}\ntest pack-5.2 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor ne\n    update\n    winfo geometry .pack.b\n} -result {60x60+230+60}\ntest pack-5.3 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor e\n    update\n    winfo geometry .pack.b\n} -result {60x60+230+90}\ntest pack-5.4 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor se\n    update\n    winfo geometry .pack.b\n} -result {60x60+230+120}\ntest pack-5.5 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor s\n    update\n    winfo geometry .pack.b\n} -result {60x60+160+120}\ntest pack-5.6 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor sw\n    update\n    winfo geometry .pack.b\n} -result {60x60+90+120}\ntest pack-5.7 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor w\n    update\n    winfo geometry .pack.b\n} -result {60x60+90+90}\ntest pack-5.8 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor nw\n    update\n    winfo geometry .pack.b\n} -result {60x60+90+60}\ntest pack-5.9 {more anchors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side  top\n    pack .pack.c -side left\n    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center\n    update\n    winfo geometry .pack.b\n} -result {60x60+160+90}\n\ntest pack-6.1 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side left\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+0+80 50x30+20+85 80x80+70+60 40x30+150+85}\ntest pack-6.2 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side left -expand yes\n    pack .pack.b -side left\n    pack .pack.c .pack.d -side left -expand 1\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+18+80 50x30+56+85 80x80+124+60 40x30+241+85}\ntest pack-6.3 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+140+0 50x30+125+40 80x80+110+70 40x30+130+150}\ntest pack-6.4 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -expand yes\n    pack .pack.b -side top\n    pack .pack.c .pack.d -side top -expand 1\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+140+3 50x30+125+46 80x80+110+79 40x30+130+166}\ntest pack-6.5 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side right\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+280+80 50x30+230+85 80x80+150+60 40x30+110+85}\ntest pack-6.6 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right -expand yes\n    pack .pack.b -side right\n    pack .pack.c .pack.d -side right -expand 1\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+262+80 50x30+194+85 80x80+95+60 40x30+18+85}\ntest pack-6.7 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side bottom\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+140+160 50x30+125+130 80x80+110+50 40x30+130+20}\ntest pack-6.8 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom -expand yes\n    pack .pack.b -side bottom\n    pack .pack.c .pack.d -side bottom -expand 1\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {20x40+140+157 50x30+125+124 80x80+110+40 40x30+130+3}\ntest pack-6.9 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom -expand yes -fill both\n    pack .pack.b -side right\n    pack .pack.c -side top -expand 1 -fill both\n    pack .pack.d -side left\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {300x65+0+135 50x30+250+52 250x105+0+0 40x30+0+105}\ntest pack-6.10 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side left -expand yes -fill both\n    pack .pack.b -side top\n    pack .pack.c -side right -expand 1 -fill both\n    pack .pack.d -side bottom\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {100x200+0+0 50x30+175+0 160x170+140+30 40x30+100+170}\ntest pack-6.11 {-expand option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side left -expand yes -fill both\n    pack .pack.b -side top -expand yes -fill both\n    pack .pack.c -side right -expand 1 -fill both\n    pack .pack.d -side bottom -expand yes -fill both\n    update\n    list [winfo geometry .pack.a] [winfo geometry .pack.b] \\\n\t[winfo geometry .pack.c] [winfo geometry .pack.d]\n} -result {100x200+0+0 200x100+100+0 160x100+140+100 40x100+100+100}\ntest pack-6.12 {-expand option} -setup {\n    toplevel .pack2 -height 400 -width 400\n    wm geometry .pack2 +0+0\n    pack propagate .pack2 0\n    foreach i {w1 w2 w3} {\n\tframe .pack2.$i -width 30 -height 30 -bd 2 -relief raised\n\tlabel .pack2.$i.l -text $i\n\tplace .pack2.$i.l -relwidth 1.0 -relheight 1.0\n    }\n} -body {\n    pack .pack2.w1 .pack2.w2 .pack2.w3 -padx 5 -ipadx 4 -pady 2 -ipady 6 -expand 1 -side left\n    update\n    list [winfo geometry .pack2.w1] [winfo geometry .pack2.w2] [winfo geometry .pack2.w3]\n} -cleanup {\n    destroy .pack2\n} -result {38x42+47+179 38x42+180+179 38x42+314+179}\ntest pack-6.13 {-expand option} -setup {\n    toplevel .pack2 -height 400 -width 400\n    wm geometry .pack2 +0+0\n    pack propagate .pack2 0\n    foreach i {w1 w2 w3} {\n\tframe .pack2.$i -width 30 -height 30 -bd 2 -relief raised\n\tlabel .pack2.$i.l -text $i\n\tplace .pack2.$i.l -relwidth 1.0 -relheight 1.0\n    }\n} -body {\n    pack .pack2.w1 .pack2.w2 .pack2.w3 -padx 5 -ipadx 4 -pady 2 \\\n\t-ipady 6 -expand 1 -side top\n    update\n    list [winfo geometry .pack2.w1] [winfo geometry .pack2.w2] [winfo geometry .pack2.w3]\n} -cleanup {\n    destroy .pack2\n} -result {38x42+181+45 38x42+181+178 38x42+181+312}\n\n#\n# COMMON TEST SETUP\n#\nwm geometry .pack {}\n\ntest pack-7.1 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side left -padx 5 -pady 10\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {230 100}\ntest pack-7.2 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top -padx 5 -pady 10\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {90 260}\ntest pack-7.3 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side right -padx 5 -pady 10\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {230 100}\ntest pack-7.4 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side bottom -padx 5 -pady 10\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {90 260}\ntest pack-7.5 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top -padx 5 -pady 10\n    pack .pack.b -side right -padx 5 -pady 10\n    pack .pack.c -side bottom -padx 5 -pady 10\n    pack .pack.d -side left -padx 5 -pady 10\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {150 210}\ntest pack-7.6 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top\n    pack .pack.c -side left\n    pack .pack.d -side bottom\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {120 120}\ntest pack-7.7 {requesting size for parent} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right\n    pack .pack.c -side bottom\n    pack .pack.d -side top\n    update\n    list [winfo reqwidth .pack] [winfo reqheight .pack]\n} -result {100 110}\n\n#\n# COMMON TEST SETUP\n#\n\n# For the tests below, create a couple of \"pad\" windows to shrink\n# the available space for the remaining windows.  The tests have to\n# be done this way rather than shrinking the whole window, because\n# some window managers like mwm won't let a top-level window get\n# very small.\n\npack forget .pack.a .pack.b .pack.c .pack.d\nframe .pack.right -width 200 -height 10 -bd 2 -relief raised\nframe .pack.bottom -width 10 -height 150 -bd 2 -relief raised\npack .pack.right -side right\npack .pack.bottom -side bottom\npack .pack.a .pack.b .pack.c -side top\nupdate\n\ntest pack-8.1 {insufficient space} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+30+0 1 50x30+15+40 1 80x80+0+70 1}\n\ntest pack-8.2 {insufficient space} -setup {\n    wm geom .pack 270x250\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+25+0 1 50x30+10+40 1 70x30+0+70 1}\n\ntest pack-8.3 {insufficient space} -setup {\n    wm geom .pack 240x220\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+10+0 1 40x30+0+40 1 70x30+0+70 0}\n\ntest pack-8.4 {insufficient space} -setup {\n    wm geom .pack 350x350\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+65+0 1 50x30+50+40 1 80x80+35+70 1}\n\n#\n# COMMON TEST SETUP\n#\n\npack .pack.a -side left\npack .pack.b -side right\npack .pack.c -side left\nupdate\n\ntest pack-8.5 {insufficient space} -setup {\n    wm geom .pack {}\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+0+20 1 50x30+100+25 1 80x80+20+0 1}\n\ntest pack-8.6 {insufficient space} -setup {\n    wm geom .pack 320x180\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x30+0+0 1 50x30+70+0 1 50x30+20+0 1}\n\n#\n# COMMON TEST SETUP\n#\nwm geom .pack 250x180\nupdate\n\ntest pack-8.7 {insufficient space} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x30+0+0 1 30x30+20+0 1 50x30+20+0 0}\n\ntest pack-8.8 {insufficient space} -setup {\n    pack forget .pack.b\n    update\n} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x30+0+0 1 30x30+20+0 0 30x30+20+0 1}\n\n#\n# COMMON TEST SETUP\n#\npack .pack.b -side right -after .pack.a\nwm geom .pack {}\nupdate\n\ntest pack-8.9 {insufficient space} -body {\n    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \\\n\t[winfo geometry .pack.b] [winfo ismapped .pack.b] \\\n\t[winfo geometry .pack.c] [winfo ismapped .pack.c]\n} -result {20x40+0+20 1 50x30+100+25 1 80x80+20+0 1}\n\n#\n# COMMON TEST SETUP\n#\npack forget .pack.right .pack.bottom\n\ntest pack-9.1 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.a -after .pack.b\n    pack content .pack\n} -result {.pack.b .pack.a .pack.c .pack.d}\ntest pack-9.2 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.a -after .pack.a\n    pack content .pack\n} -result {.pack.a .pack.b .pack.c .pack.d}\ntest pack-9.3 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.a -before .pack.d\n    pack content .pack\n} -result {.pack.b .pack.c .pack.a .pack.d}\ntest pack-9.4 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.d -before .pack.a\n    pack content .pack\n} -result {.pack.d .pack.a .pack.b .pack.c}\ntest pack-9.5 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack propagate .pack.c 0\n    pack .pack.a -in .pack.c\n    list [pack content .pack] [pack content .pack.c]\n} -result {{.pack.b .pack.c .pack.d} .pack.a}\ntest pack-9.6 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.a -in .pack\n    pack content .pack\n} -result {.pack.b .pack.c .pack.d .pack.a}\ntest pack-9.7 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d -side top\n    pack .pack.a -padx 0\n    pack content .pack\n} -result {.pack.a .pack.b .pack.c .pack.d}\ntest pack-9.8 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c\n    pack .pack.d\n    pack content .pack\n} -result {.pack.a .pack.b .pack.c .pack.d}\ntest pack-9.9 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d\n    pack .pack.b .pack.d .pack.c -before .pack.a\n    pack content .pack\n} -result {.pack.b .pack.d .pack.c .pack.a}\ntest pack-9.10 {window ordering} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d\n    pack .pack.a .pack.c .pack.d .pack.b -after .pack.a\n    pack content .pack\n} -result {.pack.a .pack.c .pack.d .pack.b}\n\ntest pack-10.1 {retaining/clearing configuration state} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \\\n    -fill both -expand 1\n    pack forget .pack.a\n    pack .pack.a\n    pack info .pack.a\n} -result {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}\ntest pack-10.2 {retaining/clearing configuration state} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \\\n    -fill both -expand 1\n    pack .pack.a -pady 14\n    pack info .pack.a\n} -result {-in .pack -anchor n -expand 1 -fill both -ipadx 3 -ipady 4 -padx 1 -pady 14 -side bottom}\ntest pack-10.3 {bad -in window does not change container window} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    set result [list [winfo manager .pack.a]]\n    catch {pack .pack.a -in .pack.a}\n    lappend result [winfo manager .pack.a]\n} -result {{} {}}\ntest pack-10.4 {bad -in window does not change container window} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    winfo manager .pack.a\n    pack .pack.a -in .pack.a\n} -returnCodes error -result {can't pack \".pack.a\" inside itself}\ntest pack-10.5 {prevent management loops} -body {\n    frame .f1\n    frame .f2\n    pack .f1 -in .f2\n    pack .f2 -in .f1\n} -cleanup {\n    destroy .f1\n    destroy .f2\n} -returnCodes error -result {can't put \".f2\" inside \".f1\": would cause management loop}\ntest pack-10.6 {prevent management loops} -body {\n    frame .f1\n    frame .f2\n    frame .f3\n    pack .f1 -in .f2\n    pack .f2 -in .f3\n    pack .f3 -in .f1\n} -cleanup {\n    destroy .f1\n    destroy .f2\n    destroy .f3\n} -returnCodes error -result {can't put \".f3\" inside \".f1\": would cause management loop}\n\ntest pack-11.1 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -in .pack\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -in]+1}]\n} -result .pack\ntest pack-11.2 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -anchor n\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -anchor]+1}]\n} -result n\ntest pack-11.3 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -anchor sw\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -anchor]+1}]\n} -result sw\ntest pack-11.4 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -expand yes\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -expand]+1}]\n} -result 1\ntest pack-11.5 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -expand no\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -expand]+1}]\n} -result 0\ntest pack-11.6 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -fill x\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -fill]+1}]\n} -result x\ntest pack-11.7 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -fill y\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -fill]+1}]\n} -result y\ntest pack-11.8 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -fill both\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -fill]+1}]\n} -result both\ntest pack-11.9 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -fill none\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -fill]+1}]\n} -result none\ntest pack-11.10 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipadx 14\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -ipadx]+1}]\n} -result 14\ntest pack-11.11 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipady 22\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -ipady]+1}]\n} -result 22\ntest pack-11.12 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx 2\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -padx]+1}]\n} -result 2\ntest pack-11.13 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx {2 9}\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -padx]+1}]\n} -result {2 9}\ntest pack-11.14 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady 3\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -pady]+1}]\n} -result 3\ntest pack-11.15 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady {3 11}\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -pady]+1}]\n} -result {3 11}\ntest pack-11.16 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side top\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -side]+1}]\n} -result top\ntest pack-11.17 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bottom\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -side]+1}]\n} -result bottom\ntest pack-11.18 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side left\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -side]+1}]\n} -result left\ntest pack-11.19 {info option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side right\n    set i [pack info .pack.a]\n    lindex $i [expr {[lsearch -exact $i -side]+1}]\n} -result right\n\ntest pack-12.1 {command options and errors} -body {\n    pack\n} -returnCodes error -result {wrong # args: should be \"pack option arg ?arg ...?\"}\ntest pack-12.2 {command options and errors} -body {\n    pack foo\n} -returnCodes error -result {wrong # args: should be \"pack option arg ?arg ...?\"}\ntest pack-12.3 {command options and errors} -body {\n    pack configure x\n} -returnCodes error -result {bad argument \"x\": must be name of window}\ntest pack-12.4 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack configure .pack.b .pack.c\n    pack content .pack\n} -result {.pack.b .pack.c}\ntest pack-12.5 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest pack-12.6 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack\n} -returnCodes error -result {can't pack \".pack\": it's a top-level window}\ntest pack-12.7 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -after .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest pack-12.8 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -after .pack.b\n} -returnCodes error -result {window \".pack.b\" isn't packed}\ntest pack-12.9 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -anchor gorp\n} -returnCodes error -result {bad anchor \"gorp\": must be n, ne, e, se, s, sw, w, nw, or center}\ntest pack-12.10 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -before gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest pack-12.11 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -before .pack.b\n} -returnCodes error -result {window \".pack.b\" isn't packed}\ntest pack-12.12 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -expand \"who_cares?\"\n} -returnCodes error -result {expected boolean value but got \"who_cares?\"}\ntest pack-12.13 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -fill z\n} -returnCodes error -result {bad fill style \"z\": must be none, x, y, or both}\ntest pack-12.14 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -in z\n} -returnCodes error -result {bad window path name \"z\"}\ntest pack-12.15 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx abc\n} -returnCodes error -result {bad pad value \"abc\": must be positive screen distance}\ntest pack-12.16 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx {5 abc}\n} -returnCodes error -result {bad 2nd pad value \"abc\": must be positive screen distance}\ntest pack-12.17 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx -1\n} -returnCodes error -result {bad pad value \"-1\": must be positive screen distance}\ntest pack-12.18 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx {5 -1}\n} -returnCodes error -result {bad 2nd pad value \"-1\": must be positive screen distance}\ntest pack-12.19 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady abc\n} -returnCodes error -result {bad pad value \"abc\": must be positive screen distance}\ntest pack-12.20 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady {0 abc}\n} -returnCodes error -result {bad 2nd pad value \"abc\": must be positive screen distance}\ntest pack-12.21 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady -1\n} -returnCodes error -result {bad pad value \"-1\": must be positive screen distance}\ntest pack-12.22 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -pady {0 -1}\n} -returnCodes error -result {bad 2nd pad value \"-1\": must be positive screen distance}\ntest pack-12.23 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipadx abc\n} -returnCodes error -result {bad ipadx value \"abc\": must be positive screen distance}\ntest pack-12.24 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipadx -1\n} -returnCodes error -result {bad ipadx value \"-1\": must be positive screen distance}\ntest pack-12.25 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipadx {5 5}\n} -returnCodes error -result {bad ipadx value \"5 5\": must be positive screen distance}\ntest pack-12.26 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipady abc\n} -returnCodes error -result {bad ipady value \"abc\": must be positive screen distance}\ntest pack-12.27 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipady -1\n} -returnCodes error -result {bad ipady value \"-1\": must be positive screen distance}\ntest pack-12.28 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -ipady {5 5}\n} -returnCodes error -result {bad ipady value \"5 5\": must be positive screen distance}\ntest pack-12.29 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -side bac\n} -returnCodes error -result {bad side \"bac\": must be bottom, left, right, or top}\ntest pack-12.30 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -lousy bac\n} -returnCodes error -result {bad option \"-lousy\": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side}\ntest pack-12.31 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -padx\n} -returnCodes error -result {extra option \"-padx\" (option with no value?)}\ntest pack-12.32 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a ? 22\n} -returnCodes error -result {bad option \"?\": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side}\ntest pack-12.33 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -in .\n} -returnCodes error -result {can't pack \".pack.a\" inside \".\"}\ntest pack-12.34 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    frame .pack.a.a\n    pack .pack.a.a -in .pack.b\n} -returnCodes error -result {can't pack \".pack.a.a\" inside \".pack.b\"}\ntest pack-12.35 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a -in .pack.a\n} -returnCodes error -result {can't pack \".pack.a\" inside itself}\ntest pack-12.36 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a .pack.b .pack.c .pack.d\n    pack forget .pack.a .pack.d\n    pack content .pack\n} -result {.pack.b .pack.c}\ntest pack-12.37 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    .pack configure -width 300 -height 200\n    pack propagate .pack 0\n    pack .pack.a\n    update\n    set result [list [winfo reqwidth .pack] [winfo reqheight .pack]]\n    pack propagate .pack 1\n    update\n    lappend result [winfo reqwidth .pack] [winfo reqheight .pack]\n    return $result\n} -result {300 200 20 40}\ntest pack-12.38 {command options and errors} -body {\n    set result [pack propagate .pack.d]\n    pack propagate .pack.d 0\n    lappend result [pack propagate .pack.d]\n    pack propagate .pack.d 1\n    lappend result [pack propagate .pack.d]\n    return $result\n} -result {1 0 1}\ntest pack-12.39 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack propagate .dum\n} -returnCodes error -result {bad window path name \".dum\"}\ntest pack-12.40 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack propagate .pack foo\n} -returnCodes error -result {expected boolean value but got \"foo\"}\ntest pack-12.41 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack propagate .pack foo bar\n} -returnCodes error -result {wrong # args: should be \"pack propagate window ?boolean?\"}\ntest pack-12.42 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack content\n} -returnCodes error -result {wrong # args: should be \"pack option arg ?arg ...?\"}\ntest pack-12.43 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack content a b\n} -returnCodes error -result {wrong # args: should be \"pack content window\"}\ntest pack-12.44 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack content .x\n} -returnCodes error -result {bad window path name \".x\"}\ntest pack-12.45 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack content .pack.a\n} -returnCodes ok -result {}\ntest pack-12.46 {command options and errors} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack lousy .pack\n} -returnCodes error -result {bad option \"lousy\": must be configure, content, forget, info, or propagate}\n\ntest pack-13.1 {window deletion} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom\n} -body {\n    pack .pack.right -side right\n    pack .pack.bottom -side bottom\n    pack .pack.a .pack.d .pack.b .pack.c -side top\n    update\n    destroy .pack.d\n    update\n    set result [list [pack content .pack] [winfo geometry .pack.a] \\\n\t[winfo geometry .pack.b] [winfo geometry .pack.c]]\n} -result {{.pack.right .pack.bottom .pack.a .pack.b .pack.c} 20x40+30+0 50x30+15+40 80x80+0+70}\n\ntest pack-14.1 {respond to changes in expansion} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom\n} -body {\n    pack .pack.right -side right\n    pack .pack.bottom -side bottom\n    wm geom .pack {}\n    pack .pack.a\n    update\n    set result [winfo geom .pack.a]\n    wm geom .pack 400x300\n    update\n    lappend result [winfo geom .pack.a]\n    pack .pack.a -expand true -fill both\n    update\n    lappend result [winfo geom .pack.a]\n} -cleanup {\n    wm geom .pack {}\n} -result {20x40+0+0 20x40+90+0 200x150+0+0}\n\n\ntest pack-15.1 {managing geometry with -in option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    destroy .pack.f\n} -body {\n    pack .pack.a -side top\n    frame .pack.f\n    lower .pack.f\n    pack .pack.f -side top\n    frame .pack.f.f2\n    lower .pack.f.f2\n    pack .pack.f.f2 -side top\n    pack .pack.b -in .pack.f.f2\n    update\n    set result [winfo geom .pack.b]\n    pack forget .pack.a\n    update\n    lappend result [winfo geom .pack.b]\n} -cleanup {\n    destroy .pack.f\n} -result {50x30+0+40 50x30+0+0}\ntest pack-15.2 {managing geometry with -in option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    destroy .pack.f\n} -body {\n    frame .pack.f\n    lower .pack.f\n    pack .pack.a -in .pack.f -side top\n    update\n    set result [winfo ismapped .pack.a]\n    place .pack.f -x 30 -y 45\n    update\n    lappend result [winfo ismapped .pack.a] [winfo geometry .pack.a]\n    place forget .pack.f\n    update\n    lappend result [winfo ismapped .pack.a]\n} -cleanup {\n    destroy .pack.f\n} -result {0 1 20x40+30+45 0}\ntest pack-15.3 {managing geometry with -in option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    destroy .pack.f\n} -body {\n    pack .pack.a -side top\n    frame .pack.f\n    lower .pack.f\n    pack .pack.f -side top\n    frame .pack.f.f2\n    lower .pack.f.f2\n    pack .pack.f.f2 -side top\n    pack .pack.b -in .pack.f.f2\n    update\n    set result [winfo ismapped .pack.b]\n    pack forget .pack.f\n    update\n    lappend result [winfo ismapped .pack.b]\n} -cleanup {\n    destroy .pack.f\n} -result {1 0}\ntest pack-15.4 {managing geometry with -in option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    destroy .pack.f1 .pack.f2\n} -body {\n    foreach i {1 2} {\n\tframe .pack.f$i -width 100 -height 40 -bd 2 -relief raised\n\tlower .pack.f$i\n\tpack propagate .pack.f$i 0\n\tpack .pack.f$i -side top\n    }\n    pack .pack.b -in .pack.f1 -side right\n    update\n    set result {}\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n    pack .pack.b -in .pack.f2 -side bottom\n    update\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n    .pack.f1 configure -width 50 -height 20\n    update\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n    pack forget .pack.b\n    update\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n} -cleanup {\n    destroy .pack.f1 .pack.f2\n} -result {50x30+48+5 1 50x30+25+48 1 50x30+25+28 1 50x30+25+28 0}\ntest pack-15.5 {managing geometry with -in option} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    destroy .pack.f1 .pack.f2\n} -body {\n    foreach i {1 2} {\n\tframe .pack.f$i -width 100 -height 20 -bd 2 -relief raised\n\tlower .pack.f$i\n\tpack propagate .pack.f$i 0\n\tpack .pack.f$i -side top\n    }\n    pack .pack.b -in .pack.f2 -side top\n    update\n    set result {}\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n    pack .pack.a -before .pack.b -side top\n    update\n    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]\n} -cleanup {\n    destroy .pack.f1 .pack.f2\n} -result {50x16+25+22 1 50x16+25+22 0}\n\ntest pack-16.1 {geometry manager name} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n    set result {}\n} -body {\n    lappend result [winfo manager .pack.a]\n    pack .pack.a\n    lappend result [winfo manager .pack.a]\n    pack forget .pack.a\n    lappend result [winfo manager .pack.a]\n} -result {{} pack {}}\n\ntest pack-17.1 {PackLostContentProc procedure} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a\n    update\n    place .pack.a -x 40 -y 10\n    update\n    list [winfo manager .pack.a] [winfo geometry .pack.a]\n} -result {place 20x40+40+10}\ntest pack-17.2 {PackLostContentProc procedure} -setup {\n    pack forget .pack.a .pack.b .pack.c .pack.d\n} -body {\n    pack .pack.a\n    update\n    place .pack.a -x 40 -y 10\n    update\n    winfo manager .pack.a\n    winfo geometry .pack.a\n    pack info .pack.a\n} -returnCodes error -result {window \".pack.a\" isn't packed}\n\n# Tests pack-18.1.1 and pack-18.2 are constrained with failsOnCILinux\n# because they are failing in the GitHub CI environment, using Linux Ubuntu.\n# These tests are also constrained with failsOnXQuartz because they fail\n# on macOS when building with clang --disable-aqua (which uses XQuartz)\n# (this is the case both at GitHub CI and on a real Mac).\n# Analysis shows that, on both cases, WaitForMapNotify is giving up on\n# waiting for the MapNotify event that should show up when running\n# 'wm iconify'. The timeout delay (2s) is exceeded without the unmapping\n# having happened. The cause for this is unknown (see comments in WaitForMapNotify).\n\n# Tests pack-18.1.* are constrained because on Windows, when the width/height\n# is configured while the window is unmapped, the changes don't take\n# effect until the window is remapped. This is apparently by design of the\n# OS, and Tk accommodates this behavior (see UpdateGeometryInfo() and\n# ConfigureTopLevel() in tkWinWm.c).\n# pack-18.1.1 checks that, on Linux or macOS, width/height changes are taken\n# into account while the window is unmapped.\n# pack-18.1.2 checks that, on Windows, width/height changes are taken into\n# account on window remapping.\n#\n# While these tests pass on macOS, one can see by watching the tests\n# that the window .pack is sometimes black, even though the frame is\n# colored.  So, evidently, even though the size changes are honored,\n# the window is sometimes not completely configured.\ntest pack-18.1.1 {unmap content when container unmapped} -constraints {\n    macOrUnix failsOnCILinux failsOnXQuartz\n} -setup {\n    destroy {*}[winfo children .pack]\n    # adjust the position of .pack before test to avoid a screen switch\n    # that occurs with window managers that have desktops four times as big\n    # as the screen (screen switch causes scale and other tests to fail).\n    wm geometry .pack +100+100\n} -body {\n    frame .pack.a -width 100 -height 50 -relief raised -bd 2 -bg green\n    after 100\n    pack .pack.a\n    update\n    set result [winfo ismapped .pack.a]\n    wm iconify .pack\n    lappend result [winfo ismapped .pack.a]\n    .pack.a configure -width 200 -height 75\n    update\n    lappend result [winfo width .pack.a] [winfo height .pack.a] \\\n\t    [winfo ismapped .pack.a]\n    wm deiconify .pack\n    update\n    lappend result [winfo ismapped .pack.a]\n} -result {1 0 200 75 0 1}\ntest pack-18.1.2 {unmap content when container unmapped} -constraints {\n    win\n} -setup {\n    destroy {*}[winfo children .pack]\n    # adjust the position of .pack before test to avoid a screen switch\n    # that occurs with window managers that have desktops four times as big\n    # as the screen (screen switch causes scale and other tests to fail).\n    wm geometry .pack +100+100\n} -body {\n    frame .pack.a -width 100 -height 50 -relief raised -bd 2 -bg green\n    pack .pack.a\n    update\n    set result [winfo ismapped .pack.a]\n    wm iconify .pack\n    lappend result [winfo ismapped .pack.a]\n    .pack.a configure -width 200 -height 75\n    update\n    wm deiconify .pack\n    update\n    lappend result [winfo width .pack.a] [winfo height .pack.a]\n    lappend result [winfo ismapped .pack.a]\n} -result {1 0 200 75 1}\n\ntest pack-18.2 {unmap content when container unmapped} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    destroy {*}[winfo children .pack]\n    # adjust the position of .pack before test to avoid a screen switch\n    # that occurs with window managers that have desktops four times as big\n    # as the screen (screen switch causes scale and other tests to fail).\n    wm geometry .pack +100+100\n} -body {\n    frame .pack.a -relief raised -bd 2 -bg green\n    frame .pack.b -width 70 -height 30 -relief sunken -bd 2 -bg red\n    pack .pack.a\n    pack .pack.b -in .pack.a\n    update\n    set result [winfo ismapped .pack.b]\n    wm iconify .pack\n    lappend result [winfo ismapped .pack.b]\n    .pack.b configure -width 100 -height 30\n    update\n    lappend result [winfo width .pack.b] [winfo height .pack.b] \\\n\t    [winfo ismapped .pack.b]\n    wm deiconify .pack\n    update\n    lappend result [winfo ismapped .pack.b]\n} -result {1 0 100 30 0 1}\n\ntest pack-19.1 {test respect for internalborder} -setup {\n    catch {pack forget {*}[pack content .pack]}\n    destroy .pack.l .pack.lf\n} -body {\n    wm geometry .pack 200x200\n    frame .pack.l -width 15 -height 10\n    labelframe .pack.lf -labelwidget .pack.l\n    pack .pack.lf -fill both -expand 1\n    frame .pack.lf.f\n    pack .pack.lf.f -fill both -expand 1\n    update\n    set res [list [winfo geometry .pack.lf.f]]\n    .pack.lf configure -labelanchor e -padx 3 -pady 5\n    update\n    lappend res [winfo geometry .pack.lf.f]\n} -cleanup {\n    destroy .pack.l .pack.lf\n} -result {196x188+2+10 177x186+5+7}\ntest pack-19.2 {test support for minreqsize} -setup {\n    catch {pack forget {*}[pack content .pack]}\n    destroy .pack.l .pack.lf\n} -body {\n    wm geometry .pack {}\n    frame .pack.l -width 150 -height 100\n    labelframe .pack.lf -labelwidget .pack.l\n    pack .pack.lf -fill both -expand 1\n    frame .pack.lf.f -width 20 -height 25\n    pack .pack.lf.f\n    update\n    set res [list [winfo geometry .pack.lf]]\n    .pack.lf configure -labelanchor ws\n    update\n    lappend res [winfo geometry .pack.lf]\n} -cleanup {\n    destroy .pack.l .pack.lf\n} -result {162x127+0+0 172x112+0+0}\n\ntest pack-20.1 {<<NoManagedChild>> fires on last pack forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    pack forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    destroy .1\n} -result 1\ntest pack-20.2 {<<NoManagedChild>> fires on last packed child destruction} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    update\n    bind . <<NoManagedChild>> {incr A}\n    destroy .1\n    update\n    set A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    destroy .1\n} -result 1\ntest pack-20.3 {<Configure> does not fire on last pack forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    update\n    bind . <Configure> {set A 1}\n    pack forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <Configure> {}\n    destroy .1\n} -result 0\ntest pack-20.4 {<<NoManagedChild>> does not fire on forelast pack forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    pack [frame .2]\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    pack forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    destroy .1 .2\n} -result 0\ntest pack-20.5 {<Configure> does not fire on last pack forget} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    pack [frame .2]\n    update\n    bind . <Configure> {set A 1}\n    pack forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <Configure> {}\n    destroy .1 .2\n} -result 1\ntest pack-20.6 {<<NoManagedChild>> does not fire on last pack forget if propagation is off} -setup {\n    global A\n    unset -nocomplain A\n} -body {\n    pack [frame .1]\n    pack propagate . 0\n    update\n    bind . <<NoManagedChild>> {set A 1}\n    pack forget .1\n    update\n    info exists A\n} -cleanup {\n    bind . <<NoManagedChild>> {}\n    destroy .1\n} -result 0\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/packgrid.test",
    "content": "# This file is a Tcl script to test out interaction between Tk's \"pack\" and\n# \"grid\" commands.\n#\n# Copyright © 2008 Peter Spjuth\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest packgrid-1.1 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Basic conflict\n    grid .g\n    pack .p\n} -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"pack\" inside \".\": grid is already managing its content windows}\n\ntest packgrid-1.2 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Basic conflict\n    pack .p\n    grid .g\n} -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"grid\" inside \".\": pack is already managing its content windows}\n\ntest packgrid-1.3 {pack and grid in same container window} -setup {\n    grid propagate . false\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok if one is non-propagating\n    grid .g\n    pack .p\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-1.4 {pack and grid in same container window} -setup {\n    grid propagate . false\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok if one is non-propagating\n    pack .p\n    grid .g\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-1.5 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . false\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok if one is non-propagating\n    grid .g\n    pack .p\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-1.6 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . false\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok if one is non-propagating\n    pack .p\n    grid .g\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-1.7 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Basic conflict should stop widget from being handled\n    grid .g\n    catch { pack .p }\n    pack content .\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-1.8 {pack and grid in same container window} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Basic conflict should stop widget from being handled\n    pack .p\n    catch { grid .g }\n    grid content .\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-2.1 {pack and grid in same container window, change propagation} -setup {\n    grid propagate . false\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n    pack .p\n    grid .g\n    update\n} -body {\n    grid propagate . true\n} -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"grid\" inside \".\": pack is already managing its content windows}\n\ntest packgrid-2.2 {pack and grid in same container window, change propagation} -setup {\n    grid propagate . true\n    pack propagate . false\n    label .p -text PACK\n    label .g -text GRID\n    pack .p\n    grid .g\n    update\n} -body {\n    pack propagate . true\n} -returnCodes error -cleanup {\n    destroy .p\n    update\n    destroy .g\n} -result {cannot use geometry manager \"pack\" inside \".\": grid is already managing its content windows}\n\ntest packgrid-2.3 {pack and grid in same container window, change propagation} -setup {\n    grid propagate . false\n    pack propagate . false\n    label .p -text PACK\n    label .g -text GRID\n    pack .p\n    grid .g\n    update\n} -body {\n    grid propagate . true\n    update\n    pack propagate . true\n} -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"pack\" inside \".\": grid is already managing its content windows}\n\ntest packgrid-2.4 {pack and grid in same container window, change propagation} -setup {\n    grid propagate . false\n    pack propagate . false\n    label .p -text PACK\n    label .g -text GRID\n    pack .p\n    grid .g\n    update\n} -body {\n    pack propagate . true\n    grid propagate . true\n} -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"grid\" inside \".\": pack is already managing its content windows}\n\ntest packgrid-3.1 {stealing content} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok to steal if the other one is emptied\n    grid .g\n    pack .g\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-3.2 {stealing content} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Ok to steal if the other one is emptied\n    pack .g\n    grid .g\n} -cleanup {\n    destroy .p\n    destroy .g\n} -result {}\n\ntest packgrid-3.3 {stealing content} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Not ok to steal if the other one is not emptied\n    grid .g\n    grid .p\n    pack .g\n}  -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"pack\" inside \".\": grid is already managing its content windows}\n\ntest packgrid-3.4 {stealing content} -setup {\n    grid propagate . true\n    pack propagate . true\n    label .p -text PACK\n    label .g -text GRID\n} -body {\n    # Not ok to steal if the other one is not emptied\n    pack .g\n    pack .p\n    grid .g\n}  -returnCodes error -cleanup {\n    destroy .p\n    destroy .g\n} -result {cannot use geometry manager \"grid\" inside \".\": pack is already managing its content windows}\n\ntest packgrid-4.1 {content stolen after container destruction - bug [aa7679685e]} -setup {\n    frame .f\n    button .b -text hello\n} -body {\n    pack .f\n    grid .b -in .f\n    destroy .f\n    set res [winfo manager .b]\n    # shall not crash\n    pack .b\n    set res\n} -cleanup {\n    destroy .b\n} -result {}\n\ntest packgrid-4.2 {content stolen after container destruction - bug [aa7679685e]} -setup {\n    frame .f\n    button .b -text hello\n} -body {\n    pack .f\n    pack .b -in .f\n    destroy .f\n    set res [winfo manager .b]\n    # shall not crash\n    grid .b\n    set res\n} -cleanup {\n    destroy .b\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/panedwindow.test",
    "content": "# This file is a Tcl script to test paned window widgets in Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\ndeleteWindows\n# Panedwindow for tests 1.*\npanedwindow .p\n# Buttons for tests 1.33 - 1.52\n.p add [button .b]\n.p add [button .c]\n\n#\n# TESTS\n#\n\ntest panedwindow-1.1 {configuration options: -background (good)} -body {\n    .p configure -background #ff0000\n    list [lindex [.p configure -background] 4] [.p cget -background]\n} -cleanup {\n    .p configure -background [lindex [.p configure -background] 3]\n} -result {{#ff0000} #ff0000}\ntest panedwindow-1.2 {configuration options: -background (bad)} -body {\n    .p configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest panedwindow-1.3 {configuration options: -bd (good)} -body {\n    .p configure -bd 4\n    list [lindex [.p configure -bd] 4] [.p cget -bd]\n} -cleanup {\n    .p configure -bd [lindex [.p configure -bd] 3]\n} -result {4 4}\ntest panedwindow-1.4 {configuration options: -bd (bad)} -body {\n    .p configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.5 {configuration options: -bg (good)} -body {\n    .p configure -bg #ff0000\n    list [lindex [.p configure -bg] 4] [.p cget -bg]\n} -cleanup {\n    .p configure -bg [lindex [.p configure -bg] 3]\n} -result {{#ff0000} #ff0000}\ntest panedwindow-1.6 {configuration options: -bg (bad)} -body {\n    .p configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest panedwindow-1.7 {configuration options: -borderwidth (good)} -body {\n    .p configure -borderwidth 1.3\n    list [lindex [.p configure -borderwidth] 4] [.p cget -borderwidth]\n} -cleanup {\n    .p configure -borderwidth [lindex [.p configure -borderwidth] 3]\n} -result {1.3 1.3}\ntest panedwindow-1.8 {configuration options: -borderwidth (bad)} -body {\n    .p configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.9 {configuration options: -cursor (good)} -body {\n    .p configure -cursor arrow\n    list [lindex [.p configure -cursor] 4] [.p cget -cursor]\n} -cleanup {\n    .p configure -cursor [lindex [.p configure -cursor] 3]\n} -result {arrow arrow}\ntest panedwindow-1.10 {configuration options: -cursor (bad)} -body {\n    .p configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest panedwindow-1.11 {configuration options: -handlesize (good)} -body {\n    .p configure -handlesize 20\n    list [lindex [.p configure -handlesize] 4] [.p cget -handlesize]\n} -cleanup {\n    .p configure -handlesize [lindex [.p configure -handlesize] 3]\n} -result {20 20}\ntest panedwindow-1.12 {configuration options: -handlesize (bad)} -body {\n    .p configure -handlesize badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.13 {configuration options: -height (good)} -body {\n    .p configure -height 20\n    list [lindex [.p configure -height] 4] [.p cget -height]\n} -cleanup {\n    .p configure -height [lindex [.p configure -height] 3]\n} -result {20 20}\ntest panedwindow-1.14 {configuration options: -height (bad)} -body {\n    .p configure -height badValue\n} -returnCodes error -result {expected screen distance or \"\" but got \"badValue\"}\ntest panedwindow-1.15 {configuration options: -opaqueresize (good)} -body {\n    .p configure -opaqueresize true\n    list [lindex [.p configure -opaqueresize] 4] [.p cget -opaqueresize]\n} -cleanup {\n    .p configure -opaqueresize [lindex [.p configure -opaqueresize] 3]\n} -result {1 1}\ntest panedwindow-1.16 {configuration options: -opaqueresize (bad)} -body {\n    .p configure -opaqueresize foo\n} -returnCodes error -result {expected boolean value but got \"foo\"}\ntest panedwindow-1.17 {configuration options: -orient (good)} -body {\n    .p configure -orient horizontal\n    list [lindex [.p configure -orient] 4] [.p cget -orient]\n} -cleanup {\n    .p configure -orient [lindex [.p configure -orient] 3]\n} -result {horizontal horizontal}\ntest panedwindow-1.18 {configuration options: -orient (bad)} -body {\n    .p configure -orient badValue\n} -returnCodes error -result {bad orient \"badValue\": must be horizontal or vertical}\ntest panedwindow-1.19 {configuration options: -proxybackground (good)} -body {\n    .p configure -proxybackground \"#f0a0a0\"\n    list [lindex [.p configure -proxybackground] 4] [.p cget -proxybackground]\n} -cleanup {\n    .p configure -proxybackground [lindex [.p configure -proxybackground] 3]\n} -result {{#f0a0a0} #f0a0a0}\ntest panedwindow-1.20 {configuration options: -proxybackground (bad)} -body {\n    .p configure -proxybackground badValue\n} -returnCodes error -result {unknown color name \"badValue\"}\ntest panedwindow-1.21 {configuration options: -proxyborderwidth (good)} -body {\n    .p configure -proxyborderwidth 1.3\n    list [lindex [.p configure -proxyborderwidth] 4] [.p cget -proxyborderwidth]\n} -cleanup {\n    .p configure -proxyborderwidth [lindex [.p configure -proxyborderwidth] 3]\n} -result {1.3 1.3}\ntest panedwindow-1.22 {configuration options: -proxyborderwidth (bad)} -body {\n    .p configure -proxyborderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.23 {configuration options: -proxyrelief (good)} -body {\n    .p configure -proxyrelief groove\n    list [lindex [.p configure -proxyrelief] 4] [.p cget -proxyrelief]\n} -cleanup {\n    .p configure -proxyrelief [lindex [.p configure -proxyrelief] 3]\n} -result {groove groove}\ntest panedwindow-1.24 {configuration options: -proxyrelief (bad)} -body {\n    .p configure -proxyrelief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\ntest panedwindow-1.25 {configuration options: -relief (good)} -body {\n    .p configure -relief groove\n    list [lindex [.p configure -relief] 4] [.p cget -relief]\n} -cleanup {\n    .p configure -relief [lindex [.p configure -relief] 3]\n} -result {groove groove}\ntest panedwindow-1.26 {configuration options: -relief (bad)} -body {\n    .p configure -relief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest panedwindow-1.27 {configuration options: -sashcursor (good)} -body {\n    .p configure -sashcursor arrow\n    list [lindex [.p configure -sashcursor] 4] [.p cget -sashcursor]\n} -cleanup {\n    .p configure -sashcursor [lindex [.p configure -sashcursor] 3]\n} -result {arrow arrow}\ntest panedwindow-1.28 {configuration options: -sashcursor (bad)} -body {\n    .p configure -sashcursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest panedwindow-1.29 {configuration options: -sashpad (good)} -body {\n    .p configure -sashpad 1.3\n    list [lindex [.p configure -sashpad] 4] [.p cget -sashpad]\n} -cleanup {\n    .p configure -sashpad [lindex [.p configure -sashpad] 3]\n} -result {1.3 1.3}\ntest panedwindow-1.30 {configuration options: -sashpad (bad)} -body {\n    .p configure -sashpad badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.31 {configuration options: -sashrelief (good)} -body {\n    .p configure -sashrelief groove\n    list [lindex [.p configure -sashrelief] 4] [.p cget -sashrelief]\n} -cleanup {\n    .p configure -sashrelief [lindex [.p configure -sashrelief] 3]\n} -result {groove groove}\ntest panedwindow-1.32 {configuration options: -sashrelief (bad)} -body {\n    .p configure -sashrelief 1.5\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\ntest panedwindow-1.33 {configuration options: -sashwidth (good)} -body {\n    .p configure -sashwidth 10\n    list [lindex [.p configure -sashwidth] 4] [.p cget -sashwidth]\n} -cleanup {\n    .p configure -sashwidth [lindex [.p configure -sashwidth] 3]\n} -result {10 10}\ntest panedwindow-1.34 {configuration options: -sashwidth (bad)} -body {\n    .p configure -sashwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.35 {configuration options: -showhandle (good)} -body {\n    .p configure -showhandle true\n    list [lindex [.p configure -showhandle] 4] [.p cget -showhandle]\n} -cleanup {\n    .p configure -showhandle [lindex [.p configure -showhandle] 3]\n} -result {1 1}\ntest panedwindow-1.36 {configuration options: -showhandle (bad)} -body {\n    .p configure -showhandle foo\n} -returnCodes error -result {expected boolean value but got \"foo\"}\ntest panedwindow-1.37 {configuration options: -width (good)} -body {\n    .p configure -width 402\n    list [lindex [.p configure -width] 4] [.p cget -width]\n} -cleanup {\n    .p configure -width [lindex [.p configure -width] 3]\n} -result {402 402}\ntest panedwindow-1.38 {configuration options: -width (bad)} -body {\n    .p configure -width badValue\n} -returnCodes error -result {expected screen distance or \"\" but got \"badValue\"}\n\ntest panedwindow-1.39 {configuration options: -after (good)} -body {\n    .p paneconfigure .b -after .c\n    list [lindex [.p paneconfigure .b -after] 4] \\\n\t[.p panecget .b -after]\n} -cleanup {\n    .p paneconfig .b -after [lindex [.p paneconfig .b -after] 3]\n} -result {.c .c}\ntest panedwindow-1.40 {configuration options: -after (bad)} -body {\n    .p paneconfigure .b -after badValue\n} -returnCodes error -result {bad window path name \"badValue\"}\ntest panedwindow-1.41 {configuration options: -before (good)} -body {\n    .p paneconfigure .b -before .c\n    list [lindex [.p paneconfigure .b -before] 4] \\\n\t[.p panecget .b -before]\n} -cleanup {\n    .p paneconfig .b -before [lindex [.p paneconfig .b -before] 3]\n} -result {.c .c}\ntest panedwindow-1.42 {configuration options: -before (bad)} -body {\n    .p paneconfigure .b -before badValue\n} -returnCodes error -result {bad window path name \"badValue\"}\ntest panedwindow-1.43 {configuration options: -height (good)} -body {\n    .p paneconfigure .b -height 10\n    list [lindex [.p paneconfigure .b -height] 4] \\\n\t[.p panecget .b -height]\n} -cleanup {\n    .p paneconfig .b -height [lindex [.p paneconfig .b -height] 3]\n} -result {10 10}\ntest panedwindow-1.44 {configuration options: -height (bad)} -body {\n    .p paneconfigure .b -height badValue\n} -returnCodes error -result {expected screen distance or \"\" but got \"badValue\"}\ntest panedwindow-1.45 {configuration options: -hide (good)} -body {\n    .p paneconfigure .b -hide false\n    list [lindex [.p paneconfigure .b -hide] 4] \\\n\t[.p panecget .b -hide]\n} -cleanup {\n    .p paneconfig .b -hide [lindex [.p paneconfig .b -hide] 3]\n} -result {0 0}\ntest panedwindow-1.46 {configuration options: -hide (bad)} -body {\n    .p paneconfigure .b -hide foo\n} -returnCodes error -result {expected boolean value but got \"foo\"}\ntest panedwindow-1.47 {configuration options: -minsize (good)} -body {\n    .p paneconfigure .b -minsize 10\n    list [lindex [.p paneconfigure .b -minsize] 4] \\\n\t[.p panecget .b -minsize]\n} -cleanup {\n    .p paneconfig .b -minsize [lindex [.p paneconfig .b -minsize] 3]\n} -result {10 10}\ntest panedwindow-1.48 {configuration options: -minsize (bad)} -body {\n    .p paneconfigure .b -minsize badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.49 {configuration options: -padx (good)} -body {\n    .p paneconfigure .b -padx 1.3\n    list [lindex [.p paneconfigure .b -padx] 4] \\\n\t[.p panecget .b -padx]\n} -cleanup {\n    .p paneconfig .b -padx [lindex [.p paneconfig .b -padx] 3]\n} -result {1.3 1.3}\ntest panedwindow-1.50 {configuration options: -padx (bad)} -body {\n    .p paneconfigure .b -padx badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.51 {configuration options: -pady (good)} -body {\n    .p paneconfigure .b -pady 1.3\n    list [lindex [.p paneconfigure .b -pady] 4] \\\n\t[.p panecget .b -pady]\n} -cleanup {\n    .p paneconfig .b -pady [lindex [.p paneconfig .b -pady] 3]\n} -result {1.3 1.3}\ntest panedwindow-1.52 {configuration options: -pady (bad)} -body {\n    .p paneconfigure .b -pady badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest panedwindow-1.53 {configuration options: -sticky (good)} -body {\n    .p paneconfigure .b -sticky nsew\n    list [lindex [.p paneconfigure .b -sticky] 4] \\\n\t[.p panecget .b -sticky]\n} -cleanup {\n    .p paneconfig .b -sticky [lindex [.p paneconfig .b -sticky] 3]\n} -result {nesw nesw}\ntest panedwindow-1.54 {configuration options: -sticky (bad)} -body {\n    .p paneconfigure .b -sticky abcd\n} -returnCodes error -result {bad stickyness value \"abcd\": must be a string containing zero or more of n, e, s, and w}\ntest panedwindow-1.55 {configuration options: -stretch (good)} -body {\n    .p paneconfigure .b -stretch alw\n    list [lindex [.p paneconfigure .b -stretch] 4] \\\n\t[.p panecget .b -stretch]\n} -cleanup {\n    .p paneconfig .b -stretch [lindex [.p paneconfig .b -stretch] 3]\n} -result {always always}\ntest panedwindow-1.56 {configuration options: -stretch (bad)} -body {\n    .p paneconfigure .b -stretch foo\n} -returnCodes error -result {bad stretch \"foo\": must be always, first, last, middle, or never}\ntest panedwindow-1.57 {configuration options: -width (good)} -body {\n    .p paneconfigure .b -width 10\n    list [lindex [.p paneconfigure .b -width] 4] \\\n\t[.p panecget .b -width]\n} -cleanup {\n    .p paneconfig .b -width [lindex [.p paneconfig .b -width] 3]\n} -result {10 10}\ntest panedwindow-1.58 {configuration options: -width (bad)} -body {\n    .p paneconfigure .b -width badValue\n} -returnCodes error -result {expected screen distance or \"\" but got \"badValue\"}\n\n\ntest panedwindow-2.1 {panedwindow widget command} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p foo\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad command \"foo\": must be add, cget, configure, forget, identify, panecget, paneconfigure, panes, proxy, or sash}\n\n\ntest panedwindow-3.1 {panedwindow panes subcommand} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    set result [list [.p panes]]\n    .p forget .b\n    lappend result [.p panes]\n} -cleanup {\n    deleteWindows\n} -result [list [list .b .c] [list .c]]\n\n\ntest panedwindow-4.1 {forget subcommand} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p forget\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p forget widget ?widget ...?\"}\ntest panedwindow-4.2 {forget subcommand, forget one from start} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    set result [list [.p panes]]\n    .p forget .b\n    lappend result [.p panes]\n} -cleanup {\n    deleteWindows\n} -result [list {.b .c} .c]\ntest panedwindow-4.3 {forget subcommand, forget one from end} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    .p add [button .d]\n    set result [list [.p panes]]\n    .p forget .d\n    update\n    lappend result [.p panes]\n} -cleanup {\n    deleteWindows\n} -result [list {.b .c .d} {.b .c}]\ntest panedwindow-4.4 {forget subcommand, forget multiple} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    .p add [button .d]\n    set result [list [.p panes]]\n    .p forget .b .c\n    update\n    lappend result [.p panes]\n} -cleanup {\n    deleteWindows\n} -result [list {.b .c .d} .d]\ntest panedwindow-4.5 {forget subcommand, panes are unmapped} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    pack .p\n    update\n    set result [list [winfo ismapped .b] [winfo ismapped .c]]\n    .p forget .b\n    update\n    lappend result [winfo ismapped .b] [winfo ismapped .c]\n} -cleanup {\n    deleteWindows\n} -result [list 1 1 0 1]\ntest panedwindow-4.6 {forget subcommand, changes reqsize of panedwindow} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false\n    .p add [frame .f -width 20 -height 20] [frame .g -width 20 -height 20]\n    set result [list [winfo reqwidth .p]]\n    .p forget .f\n    lappend result [winfo reqwidth .p]\n} -cleanup {\n    deleteWindows\n} -result [list 44 20]\n\n\ntest panedwindow-5.1 {sash subcommand} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p sash option ?arg ...?\"}\ntest panedwindow-5.2 {sash subcommand} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash foo\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad option \"foo\": must be coord, dragto, mark, or place}\n\n\ntest panedwindow-6.1 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash coord\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p sash coord index\"}\ntest panedwindow-6.2 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid sash index}\ntest panedwindow-6.3 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash coord foo\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-6.4 {sash coord subcommand sashes correctly placed} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false\n    .p add [frame .p.f -width 20 -height 20] \\\n\t    [frame .p.f2 -width 20 -height 20] \\\n\t    [frame .p.f3 -width 20 -height 20]\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 22 0]\ntest panedwindow-6.5 {sash coord subcommand sashes correctly placed} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false\n    .p add [frame .p.f -width 20 -height 20] \\\n\t    [frame .p.f2 -width 20 -height 20] \\\n\t    [frame .p.f3 -width 20 -height 20]\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 50 0]\ntest panedwindow-6.6 {sash coord subcommand, sashes correctly placed} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \\\n\t    -showhandle false\n    .p add [frame .p.f -width 20 -height 20] \\\n\t    [frame .p.f2 -width 20 -height 20] \\\n\t    [frame .p.f3 -width 20 -height 20]\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 22]\ntest panedwindow-6.7 {sash coord subcommand, sashes correctly placed} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \\\n\t    -showhandle false\n    .p add [frame .p.f -width 20 -height 20] \\\n\t    [frame .p.f2 -width 20 -height 20] \\\n\t    [frame .p.f3 -width 20 -height 20]\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 0 50]\ntest panedwindow-6.8 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    list [catch {.p sash coord -1} msg] $msg \\\n\t[catch {.p sash coord  0} msg] $msg \\\n\t[catch {.p sash coord  1} msg] $msg\n} -cleanup {\n    deleteWindows\n} -result [list 1 \"invalid sash index\" 1 \"invalid sash index\" 1 \"invalid sash index\"]\ntest panedwindow-6.9 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    # There are no sashes until you have 2 panes\n    panedwindow .p\n    .p add [frame .p.f]\n    list [catch {.p sash coord -1} msg] $msg \\\n\t    [catch {.p sash coord  0} msg] $msg \\\n\t    [catch {.p sash coord  1} msg] $msg\n} -cleanup {\n    deleteWindows\n} -result [list 1 \"invalid sash index\" 1 \"invalid sash index\" 1 \"invalid sash index\"]\ntest panedwindow-6.10 {sash coord subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    # There are no sashes until you have 2 panes\n    panedwindow .p\n    .p add [frame .p.f] [frame .p.f2]\n    list [catch {.p sash coord -1} msg] $msg \\\n\t    [catch {.p sash coord  0} msg] \\\n\t    [catch {.p sash coord  1} msg] $msg \\\n\t    [catch {.p sash coord  2} msg] $msg\n} -cleanup {\n    deleteWindows\n} -result [list 1 \"invalid sash index\" 0 1 \"invalid sash index\" 1 \"invalid sash index\"]\n\n\ntest panedwindow-7.1 {sash mark subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash mark\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p sash mark index ?x y?\"}\ntest panedwindow-7.2 {sash mark subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash mark foo\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-7.3 {sash mark subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash mark 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid sash index}\ntest panedwindow-7.4 {sash mark subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash mark 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-7.5 {sash mark subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash mark 0 0 bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"bar\"}\ntest panedwindow-7.6 {sash mark subcommand, mark defaults to 0 0} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash mark 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 0]\ntest panedwindow-7.7 {sash mark subcommand, set mark} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash mark 0 10 10\n    .p sash mark 0\n} -cleanup {\n    deleteWindows\n} -result [list 10 10]\n\n\ntest panedwindow-8.1 {sash dragto subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash dragto\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p sash dragto index x y\"}\ntest panedwindow-8.2 {sash dragto subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash dragto foo bar baz\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-8.3 {sash dragto subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash dragto 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid sash index}\ntest panedwindow-8.4 {sash dragto subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash dragto 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-8.5 {sash dragto subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash dragto 0 0 bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"bar\"}\n\n\ntest panedwindow-9.1 {sash mark/sash dragto interaction} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false\n    .p add [frame .f -width 20 -height 20] [button .c -text foobar]\n    .p sash mark 0 10 10\n    .p sash dragto 0 20 10\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 30 0]\ntest panedwindow-9.2 {sash mark/sash dragto interaction} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical \\\n\t    -showhandle false\n    .p add [frame .p.f -width 20 -height 20] [button .p.c -text foobar]\n    .p sash mark 0 10 10\n    .p sash dragto 0 10 20\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 30]\ntest panedwindow-9.3 {sash mark/sash dragto, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false\n    .p add [frame .f -width 20 -height 20] [button .c] -minsize 15\n    .p sash mark 0 20 10\n    .p sash dragto 0 10 10\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 15 0]\n\n\ntest panedwindow-10.1 {sash place subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash place\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p sash place index x y\"}\ntest panedwindow-10.2 {sash place subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash place foo bar baz\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-10.3 {sash place subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p sash place 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid sash index}\ntest panedwindow-10.4 {sash place subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash place 0 foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-10.5 {sash place subcommand, errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p sash place 0 0 bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"bar\"}\ntest panedwindow-10.6 {sash place subcommand, moves sash} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 20] [button .c]\n    .p sash place 0 10 0\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 10 0]\ntest panedwindow-10.7 {sash place subcommand, moves sash} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical\n    .p add [frame .f -width 20 -height 20] [button .c]\n    .p sash place 0 0 10\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 10]\ntest panedwindow-10.8 {sash place subcommand, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false\n    .p add [frame .f -width 20 -height 20] [button .c] -minsize 15\n    .p sash place 0 10 0\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 15 0]\ntest panedwindow-10.9 {sash place subcommand, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [frame .f -width 20 -height 20 -bg pink]\n    .p sash place 0 2 0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {invalid sash index}\n\n\ntest panedwindow-11.1 {moving sash changes size of pane to left} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false\n    .p add [frame .f -width 20 -height 20] [button .c -text foobar] -sticky nsew\n    .p sash place 0 30 0\n    pack .p\n    update\n    winfo width .f\n} -result 30\ntest panedwindow-11.2 {moving sash changes size of pane to right} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]\n    pack .p\n    update\n    set result [winfo width .f2]\n    .p sash place 0 30 0\n    update\n    lappend result [winfo width .f2]\n} -cleanup {\n    deleteWindows\n} -result {20 10}\ntest panedwindow-11.3 {moving sash does not change reqsize of panedwindow} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]\n    .p sash place 0 30 0\n    winfo reqwidth .p\n} -result 44\ntest panedwindow-11.4 {moving sash changes size of pane above} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .f -width 20 -height 10] [button .c -text foobar] -sticky nsew\n    .p sash place 0 0 20\n    pack .p\n    update\n    set result [winfo height .f]\n    set result\n} -result 20\ntest panedwindow-11.5 {moving sash changes size of pane below} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]\n    pack .p\n    update\n    set result [winfo height .f2]\n    .p sash place 0 0 15\n    update\n    lappend result [winfo height .f2]\n    set result\n} -cleanup {\n    deleteWindows\n} -result {10 5}\ntest panedwindow-11.6 {moving sash does not change reqsize of panedwindow} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]\n    set result [winfo reqheight .p]\n    .p sash place 0 0 20\n    lappend result [winfo reqheight .p]\n    set result\n} -cleanup {\n    deleteWindows\n} -result [list 24 24]\ntest panedwindow-11.7 {moving sash does not alter reqsize of widget} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]\n    set result [winfo reqheight .f]\n    .p sash place 0 0 20\n    lappend result [winfo reqheight .f]\n} -cleanup {\n    deleteWindows\n} -result [list 10 10]\ntest panedwindow-11.8 {moving sash restricted to minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 20] [button .c] -minsize 15\n    .p sash place 0 10 0\n    pack .p\n    update\n    winfo width .f\n} -result 15\ntest panedwindow-11.9 {moving sash restricted to minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .f -width 20 -height 30] [button .c] -minsize 10\n    .p sash place 0 0 5\n    pack .p\n    update\n    winfo height .f\n} -result 10\ntest panedwindow-11.10 {moving sash in unmapped window restricted to reqsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20]\n    set result [list [.p sash coord 0]]\n    .p sash place 0 100 0\n    lappend result [.p sash coord 0]\n} -cleanup {\n    deleteWindows\n} -result [list {20 0} {40 0}]\ntest panedwindow-11.11 {moving sash right pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \\\n\t    [frame .f3 -width 20 -height 30]\n    .p sash place 0 80 0\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{60 0} {64 0}}\ntest panedwindow-11.12 {moving sash left pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \\\n\t    [frame .f3 -width 20 -height 30]\n    .p sash place 1 0 0\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 0} {4 0}}\ntest panedwindow-11.13 {move sash in mapped window restricted to visible win} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \\\n\t    [frame .f3 -width 20 -height 30]\n    place .p -width 50\n    update\n    .p sash place 1 100 0\n    update\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result {46 0}\ntest panedwindow-11.14 {move sash in mapped window restricted to visible win} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \\\n\t    [frame .f3 -width 20 -height 30]\n    place .p -width 100\n    update\n    .p sash place 1 200 0\n    update\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result {96 0}\ntest panedwindow-11.15 {moving sash into \"virtual\" space on last pane increases reqsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \\\n\t    [frame .f3 -width 20 -height 30]\n    place .p -width 100\n    set result [winfo reqwidth .p]\n    update\n    .p sash place 1 200 0\n    update\n    lappend result [winfo reqwidth .p]\n} -cleanup {\n    deleteWindows\n} -result {68 100}\n\n\ntest panedwindow-12.1 {horizontal panedwindow lays out widgets properly} -setup {\n    deleteWindows\n    set result {}\n} -body {\n    panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2\n    foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}\n    pack .p\n    update\n    foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result [list 2 2 28 2 54 2]\ntest panedwindow-12.2 {vertical panedwindow lays out widgets properly} -setup {\n    deleteWindows\n    set result {}\n} -body {\n    panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2 \\\n\t    -orient vertical\n    foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}\n    pack .p\n    update\n    foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result [list 2 2 2 18 2 34]\ntest panedwindow-12.3 {horizontal panedwindow lays out widgets properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    foreach {win color} {.p.f blue .p.f2 green} {\n\t.p add [frame $win -width 20 -height 20 -bg $color] -padx 10 -pady 5 \\\n\t\t-sticky \"\"\n    }\n    pack .p\n    update\n    set result [list [winfo reqwidth .p] [winfo reqheight .p]]\n    foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}\n    .p paneconfigure .p.f -padx 0 -pady 0\n    update\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n    foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result [list 80 30 10 5 50 5 60 30 0 5 30 5]\ntest panedwindow-12.4 {vertical panedwindow lays out widgets properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \\\n\t    -orient vertical\n    foreach win {.p.f .p.f2} {\n\t.p add [frame $win -width 20 -height 20] -padx 10 -pady 5 -sticky \"\"\n    }\n    pack .p\n    update\n    set result [list [winfo reqwidth .p] [winfo reqheight .p]]\n    foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}\n    .p paneconfigure .p.f -padx 0 -pady 0\n    update\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n    foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result [list 40 60 10 5 10 35 40 50 10 0 10 25]\ntest panedwindow-12.5 {panedwindow respects reqsize of panes when possible} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -width 20 -height 20] -sticky \"\"\n    place .p -width 40\n    update\n    set result [list [winfo width .p.f]]\n    .p.f configure -width 30\n    update\n    lappend result [winfo width .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 20 30]\ntest panedwindow-12.6 {panedwindow takes explicit widget width over reqwidth} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -width 20 -height 20] -width 20 -sticky \"\"\n    place .p -width 40\n    update\n    set result [list [winfo width .p.f]]\n    .p.f configure -width 30\n    update\n    lappend result [winfo width .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 20 20]\ntest panedwindow-12.7 {horizontal panedwindow reqheight is max pane height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]\n    set result [winfo reqheight .p]\n    .p.f config -height 40\n    lappend result [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 40}\ntest panedwindow-12.8 {horizontal panedwindow reqheight is max pane height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}\n    .p paneconfigure .p.f -height 15\n    set result [winfo reqheight .p]\n    .p.f config -height 40\n    lappend result [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\ntest panedwindow-12.9 {panedwindow pane width overrides widget width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4\n    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}\n    .p sash place 0 10 0\n    pack .p\n    update\n    set result [winfo width .p.f]\n    .p paneconfigure .p.f -width 30\n    lappend result [winfo width .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 10 10]\ntest panedwindow-12.10 {panedwindow respects reqsize of panes when possible} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -width 20 -height 20] -sticky \"\"\n    place .p -height 40\n    update\n    set result [list [winfo height .p.f]]\n    .p.f configure -height 30\n    update\n    lappend result [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 20 30]\ntest panedwindow-12.11 {panedwindow takes explicit height over reqheight} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -width 20 -height 20] -height 20 -sticky \"\"\n    place .p -height 40\n    update\n    set result [list [winfo height .p.f]]\n    .p.f configure -height 30\n    update\n    lappend result [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 20 20]\ntest panedwindow-12.12 {vertical panedwindow reqwidth is max pane width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]\n    set result [winfo reqwidth .p]\n    .p.f config -width 40\n    lappend result [winfo reqwidth .p]\n} -cleanup {\n    deleteWindows\n} -result {20 40}\ntest panedwindow-12.13 {vertical panedwindow reqwidth is max pane width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}\n    .p paneconfigure .p.f -width 15\n    set result [winfo reqwidth .p]\n    .p.f config -width 40\n    lappend result [winfo reqwidth .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\ntest panedwindow-12.14 {panedwindow pane height overrides widget width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \\\n\t    -orient vertical\n    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}\n    .p sash place 0 0 10\n    pack .p\n    update\n    set result [winfo height .p.f]\n    .p paneconfigure .p.f -height 30\n    lappend result [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result [list 10 10]\n\n\ntest panedwindow-13.1 {PanestructureProc, widget yields managements} -setup {\n    deleteWindows\n} -body {\n    # Check that the panedwindow correctly yields geometry management of\n    # a pane when the pane is destroyed.\n\n    # This test should not cause a core dump, and it should not cause\n    # a memory leak.\n    panedwindow .p\n    .p add [button .b]\n    destroy .p\n    pack .b\n    destroy .b\n    set result \"\"\n} -result {}\ntest panedwindow-13.2 {PanedWindowLostPaneProc, widget yields management} -setup {\n    deleteWindows\n} -body {\n    # Check that the paned window correctly yields geometry management of\n    # a pane when some other geometry manager steals the pane from us.\n\n    # This test should not cause a core dump, and it should not cause a\n    # memory leak.\n    panedwindow .p\n    .p add [button .b]\n    pack .p\n    update\n    pack .b\n    update\n    set result [.p panes]\n    destroy .p .b\n    set result\n} -result {}\n\n\ntest panedwindow-14.1 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky n\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {n}\ntest panedwindow-14.2 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky s\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {s}\ntest panedwindow-14.3 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky e\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {e}\ntest panedwindow-14.4 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky w\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {w}\ntest panedwindow-14.5 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky sn\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {ns}\ntest panedwindow-14.6 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky ns\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {ns}\ntest panedwindow-14.7 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky en\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {ne}\ntest panedwindow-14.8 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky ne\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {ne}\ntest panedwindow-14.9 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky wn\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nw}\ntest panedwindow-14.10 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky nw\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nw}\ntest panedwindow-14.11 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky esn\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nes}\ntest panedwindow-14.12 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky nse\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nes}\ntest panedwindow-14.13 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky nsw\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nsw}\ntest panedwindow-14.14 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky nsew\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {nesw}\ntest panedwindow-14.15 {panedwindow sticky settings} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    .p add [button .b]\n    .p paneconfigure .b -sticky \"\"\n    .p panecget .b -sticky\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest panedwindow-15.1 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky {}\n    place .p -width 40 -height 40\n    update\n    list {} [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {{} 10 10 20 20}\ntest panedwindow-15.2 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky n\n    place .p -width 40 -height 40\n    update\n    list n [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {n 10 0 20 20}\ntest panedwindow-15.3 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky s\n    place .p -width 40 -height 40\n    update\n    list s [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {s 10 20 20 20}\ntest panedwindow-15.4 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky e\n    place .p -width 40 -height 40\n    update\n    list e [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {e 20 10 20 20}\ntest panedwindow-15.5 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky w\n    place .p -width 40 -height 40\n    update\n    list w [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {w 0 10 20 20}\ntest panedwindow-15.6 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ns\n    place .p -width 40 -height 40\n    update\n    list ns [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {ns 10 0 20 40}\ntest panedwindow-15.7 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ew\n    place .p -width 40 -height 40\n    update\n    list ew [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {ew 0 10 40 20}\ntest panedwindow-15.8 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nw\n    place .p -width 40 -height 40\n    update\n    list nw [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {nw 0 0 20 20}\ntest panedwindow-15.9 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky ne\n    place .p -width 40 -height 40\n    update\n    list ne [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {ne 20 0 20 20}\ntest panedwindow-15.10 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky se\n    place .p -width 40 -height 40\n    update\n    list se [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {se 20 20 20 20}\ntest panedwindow-15.11 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky sw\n    place .p -width 40 -height 40\n    update\n    list sw [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {sw 0 20 20 20}\ntest panedwindow-15.12 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nse\n    place .p -width 40 -height 40\n    update\n    list nse [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {nse 20 0 20 40}\ntest panedwindow-15.13 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky nsw\n    place .p -width 40 -height 40\n    update\n    list nsw [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {nsw 0 0 20 40}\ntest panedwindow-15.14 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky sew\n    place .p -width 40 -height 40\n    update\n    list sew [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {sew 0 20 40 20}\ntest panedwindow-15.15 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky new\n    place .p -width 40 -height 40\n    update\n    list new [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {new 0 0 40 20}\ntest panedwindow-15.16 {panedwindow sticky works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    .p add [frame .p.f -height 20 -width 20 -bg red] -sticky news\n    place .p -width 40 -height 40\n    update\n    list news [winfo x .p.f] [winfo y .p.f]  [winfo width .p.f] [winfo height .p.f]\n} -cleanup {\n    deleteWindows\n} -result {news 0 0 40 40}\n\n\ntest panedwindow-16.1 {setting minsize when pane is too small snaps width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .p.f -height 20 -width 20 -bg red]\n    set result [winfo reqwidth .p]\n    .p paneconfigure .p.f -minsize 40\n    lappend result [winfo reqwidth .p]\n} -cleanup {\n    deleteWindows\n} -result [list 20 40]\n\n\ntest panedwindow-17.1 {MoveSash, move right} -setup {\n    deleteWindows\n    set result {}\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Get the requested width of the paned window\n    lappend result [winfo reqwidth .p]\n\n    .p sash place 0 30 0\n\n    # Get the reqwidth again, to make sure it hasn't changed\n    lappend result [winfo reqwidth .p]\n\n    # Check that the sash moved\n    lappend result [.p sash coord 0]\n} -cleanup {\n    deleteWindows\n} -result [list 42 42 {30 0}]\ntest panedwindow-17.2 {MoveSash, move right (unmapped) clipped by reqwidth} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should be clipped by the reqwidth of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 40 0]\ntest panedwindow-17.3 {MoveSash, move right (mapped, width < reqwidth) clipped by width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Put the panedwindow up on the display and give it a width < reqwidth\n    place .p -x 0 -y 0 -width 32\n    update\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should be clipped by the visible width of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 30 0]\ntest panedwindow-17.4 {MoveSash, move right (mapped, width > reqwidth) clipped by width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Put the panedwindow up on the display and give it a width > reqwidth\n    place .p -x 0 -y 0 -width 102\n    update\n\n    .p sash place 0 200 0\n\n    # Get the new sash coord; it should be clipped by the visible width of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 100 0]\ntest panedwindow-17.5 {MoveSash, move right respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 30 0]\ntest panedwindow-17.6 {MoveSash, move right respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should have moved as far as possible.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 40 0]\ntest panedwindow-17.7 {MoveSash, move right pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 62 0]\ntest panedwindow-17.8 {MoveSash, move right pushes other sashes, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 52 0]\ntest panedwindow-17.9 {MoveSash, move right respects minsize, exludes pad} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 10 -padx 5\n    }\n\n    .p sash place 0 100 0\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 50 0]\ntest panedwindow-17.10 {MoveSash, move right, zero minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 0\n    }\n\n    .p sash place 0 50 0\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result [list [list 50 0] [list 52 0]]\ntest panedwindow-17.11 {MoveSash, move left} -setup {\n    deleteWindows\n} -body {\n    set result {}\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Get the requested width of the paned window\n    lappend result [winfo reqwidth .p]\n\n    .p sash place 0 10 0\n\n    # Get the reqwidth again, to make sure it hasn't changed\n    lappend result [winfo reqwidth .p]\n\n    # Check that the sash moved\n    lappend result [.p sash coord 0]\n} -cleanup {\n    deleteWindows\n} -result [list 42 42 {10 0}]\ntest panedwindow-17.12 {MoveSash, move left, can't move outside of window} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 -100 0\n\n    # Get the new sash coord; it should be clipped by the reqwidth of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 0]\ntest panedwindow-17.13 {MoveSash, move left respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 10 0]\ntest panedwindow-17.14 {MoveSash, move left respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 22 0]\ntest panedwindow-17.15 {MoveSash, move left pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 0]\ntest panedwindow-17.16 {MoveSash, move left pushes other sashes, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 10 0]\ntest panedwindow-17.17 {MoveSash, move left respects minsize, exludes pad} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 10 -padx 5\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 42 0]\ntest panedwindow-17.18 {MoveSash, move left, zero minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    foreach w {.f1 .f2 .f3} c {red blue green} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 0\n    }\n\n    .p sash place 1 10 0\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result [list [list 8 0] [list 10 0]]\n\n\ntest panedwindow-18.1 {MoveSash, move down} -setup {\n    deleteWindows\n} -body {\n    set result {}\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Get the requested width of the paned window\n    lappend result [winfo reqheight .p]\n\n    .p sash place 0 0 30\n\n    # Get the reqwidth again, to make sure it hasn't changed\n    lappend result [winfo reqheight .p]\n\n    # Check that the sash moved\n    lappend result [.p sash coord 0]\n} -cleanup {\n    deleteWindows\n} -result [list 42 42 {0 30}]\ntest panedwindow-18.2 {MoveSash, move down (unmapped) clipped by reqheight} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should be clipped by the reqheight of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 40]\ntest panedwindow-18.3 {MoveSash, move down (mapped, height < reqheight) clipped by height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Put the panedwindow up on the display and give it a height < reqheight\n    place .p -x 0 -y 0 -height 32\n    update\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should be clipped by the visible height of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 30]\ntest panedwindow-18.4 {MoveSash, move down (mapped, height > reqheight) clipped by height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Put the panedwindow up on the display and give it a width > reqwidth\n    place .p -x 0 -y 0 -height 102\n    update\n\n    .p sash place 0 0 200\n\n    # Get the new sash coord; it should be clipped by the visible width of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 100]\ntest panedwindow-18.5 {MoveSash, move down respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 30]\ntest panedwindow-18.6 {MoveSash, move down respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 40]\ntest panedwindow-18.7 {MoveSash, move down pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 0 62]\ntest panedwindow-18.8 {MoveSash, move down pushes other sashes, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 0 52]\ntest panedwindow-18.9 {MoveSash, move down respects minsize, exludes pad} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 10 -pady 5\n    }\n\n    .p sash place 0 0 100\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 50]\ntest panedwindow-18.10 {MoveSash, move right, zero minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 0\n    }\n\n    .p sash place 0 0 50\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result [list [list 0 50] [list 0 52]]\ntest panedwindow-18.11 {MoveSash, move up} -setup {\n    deleteWindows\n} -body {\n    set result {}\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    # Get the requested width of the paned window\n    lappend result [winfo reqheight .p]\n\n    .p sash place 0 0 10\n\n    # Get the reqwidth again, to make sure it hasn't changed\n    lappend result [winfo reqheight .p]\n\n    # Check that the sash moved\n    lappend result [.p sash coord 0]\n} -cleanup {\n    deleteWindows\n} -result [list 42 42 {0 10}]\ntest panedwindow-18.12 {MoveSash, move up, can't move outside of window} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 0 0 -100\n\n    # Get the new sash coord; it should be clipped by the reqwidth of\n    # the panedwindow.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 0]\ntest panedwindow-18.13 {MoveSash, move up respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 0 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 10]\ntest panedwindow-18.14 {MoveSash, move up respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 0 22]\ntest panedwindow-18.15 {MoveSash, move up pushes other sashes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 0]\ntest panedwindow-18.16 {MoveSash, move up pushes other sashes, respects minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible while\n    # respecting minsizes.\n    .p sash coord 0\n} -cleanup {\n    deleteWindows\n} -result [list 0 10]\ntest panedwindow-18.17 {MoveSash, move up respects minsize, exludes pad} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 10 -pady 5\n    }\n\n    .p sash place 1 0 0\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    .p sash coord 1\n} -cleanup {\n    deleteWindows\n} -result [list 0 42]\ntest panedwindow-18.18 {MoveSash, move up, zero minsize} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} c {red blue green} {\n\t.p add [frame $w -height 20 -width 20 -bg $c] \\\n\t\t-sticky nsew -minsize 0\n    }\n\n    .p sash place 1 0 10\n\n    # Get the new sash coord; it should have moved as far as possible,\n    # respecting minsizes.\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result [list [list 0 8] [list 0 10]]\n\n\n# The following tests check that the panedwindow is correctly computing its\n# geometry based on the various configuration options that can affect the\n# geometry.\n\ntest panedwindow-19.1 {ComputeGeometry, reqheight taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue]\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .f3 configure -height 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 60 20] [list 60 40]]\n\ntest panedwindow-19.2 {ComputeGeometry, reqheight taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue]\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .p paneconfigure .f3 -height 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 60 20] [list 60 40]]\n\ntest panedwindow-19.3 {ComputeGeometry, reqheight taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -pady 20\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .p paneconfigure .f3 -height 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 60 60] [list 60 80]]\n\ntest panedwindow-19.4 {ComputeGeometry, reqwidth taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue]\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .f3 configure -width 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 20 60] [list 40 60]]\n\ntest panedwindow-19.5 {ComputeGeometry, reqwidth taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue]\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .p paneconfigure .f3 -width 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 20 60] [list 40 60]]\n\ntest panedwindow-19.6 {ComputeGeometry, reqwidth taken from widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \\\n\t    -orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -padx 20\n    }\n    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]\n    .p paneconfigure .f3 -width 40\n    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]\n} -cleanup {\n    deleteWindows\n} -result [list [list 60 60] [list 80 60]]\n\ntest panedwindow-19.7 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.8 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {60 20}\n\ntest panedwindow-19.9 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{20 0} {40 0}}\n\ntest panedwindow-19.10 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {53 3 20 20} {95 3 20 20}}\n\ntest panedwindow-19.11 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.12 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 60}\n\ntest panedwindow-19.13 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 20} {0 40}}\n\ntest panedwindow-19.14 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 53 20 20} {3 95 20 20}}\ntest panedwindow-19.15 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {22 20}\n\ntest panedwindow-19.16 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {72 20}\n\ntest panedwindow-19.17 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{23 0} {49 0}}\n\ntest panedwindow-19.18 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}\n\ntest panedwindow-19.19 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 22}\n\ntest panedwindow-19.20 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 72}\n\ntest panedwindow-19.21 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 23} {0 49}}\n\ntest panedwindow-19.22 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}\ntest panedwindow-19.23 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.24 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {66 20}\n\ntest panedwindow-19.25 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{20 0} {43 0}}\n\ntest panedwindow-19.26 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {56 3 20 20} {101 3 20 20}}\n\ntest panedwindow-19.27 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.28 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 66}\n\ntest panedwindow-19.29 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 20} {0 43}}\n\ntest panedwindow-19.30 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 56 20 20} {3 101 20 20}}\ntest panedwindow-19.31 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {22 20}\n\ntest panedwindow-19.32 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {72 20}\n\ntest panedwindow-19.33 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{21 0} {47 0}}\n\ntest panedwindow-19.34 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}\n\ntest panedwindow-19.35 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 22}\n\ntest panedwindow-19.36 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 72}\n\ntest panedwindow-19.37 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 21} {0 47}}\n\ntest panedwindow-19.38 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}\ntest panedwindow-19.39 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.40 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {80 20}\n\ntest panedwindow-19.41 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{25 0} {55 0}}\n\ntest panedwindow-19.42 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {63 3 20 20} {115 3 20 20}}\n\ntest panedwindow-19.43 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.44 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 80}\n\ntest panedwindow-19.45 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 25} {0 55}}\n\ntest panedwindow-19.46 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 63 20 20} {3 115 20 20}}\ntest panedwindow-19.47 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {22 20}\n\ntest panedwindow-19.48 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {92 20}\n\ntest panedwindow-19.49 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{28 0} {64 0}}\n\ntest panedwindow-19.50 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}\n\ntest panedwindow-19.51 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 22}\n\ntest panedwindow-19.52 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 92}\n\ntest panedwindow-19.53 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 28} {0 64}}\n\ntest panedwindow-19.54 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}\ntest panedwindow-19.55 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.56 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {86 20}\n\ntest panedwindow-19.57 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{25 0} {58 0}}\n\ntest panedwindow-19.58 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {66 3 20 20} {121 3 20 20}}\n\ntest panedwindow-19.59 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 20}\n\ntest panedwindow-19.60 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 86}\n\ntest panedwindow-19.61 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 25} {0 58}}\n\ntest panedwindow-19.62 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 66 20 20} {3 121 20 20}}\ntest panedwindow-19.63 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {22 20}\n\ntest panedwindow-19.64 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {92 20}\n\ntest panedwindow-19.65 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{26 0} {62 0}}\n\ntest panedwindow-19.66 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}\n\ntest panedwindow-19.67 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 22}\n\ntest panedwindow-19.68 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {20 92}\n\ntest panedwindow-19.69 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{0 26} {0 62}}\n\ntest panedwindow-19.70 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}\ntest panedwindow-19.71 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.72 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {64 24}\n\ntest panedwindow-19.73 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{22 2} {42 2}}\n\ntest panedwindow-19.74 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {55 5 20 20} {97 5 20 20}}\n\ntest panedwindow-19.75 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.76 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 64}\n\ntest panedwindow-19.77 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 22} {2 42}}\n\ntest panedwindow-19.78 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 55 20 20} {5 97 20 20}}\ntest panedwindow-19.79 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {26 24}\n\ntest panedwindow-19.80 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {76 24}\n\ntest panedwindow-19.81 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{25 2} {51 2}}\n\ntest panedwindow-19.82 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}\n\ntest panedwindow-19.83 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 26}\n\ntest panedwindow-19.84 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 76}\n\ntest panedwindow-19.85 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 25} {2 51}}\n\ntest panedwindow-19.86 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}\ntest panedwindow-19.87 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.88 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {70 24}\n\ntest panedwindow-19.89 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{22 2} {45 2}}\n\ntest panedwindow-19.90 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {58 5 20 20} {103 5 20 20}}\n\ntest panedwindow-19.91 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.92 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 70}\n\ntest panedwindow-19.93 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 22} {2 45}}\n\ntest panedwindow-19.94 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 58 20 20} {5 103 20 20}}\ntest panedwindow-19.95 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {26 24}\n\ntest panedwindow-19.96 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {76 24}\n\ntest panedwindow-19.97 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{23 2} {49 2}}\n\ntest panedwindow-19.98 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}\n\ntest panedwindow-19.99 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 26}\n\ntest panedwindow-19.100 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 76}\n\ntest panedwindow-19.101 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 23} {2 49}}\n\ntest panedwindow-19.102 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 0 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}\ntest panedwindow-19.103 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.104 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {84 24}\n\ntest panedwindow-19.105 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{27 2} {57 2}}\n\ntest panedwindow-19.106 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {65 5 20 20} {117 5 20 20}}\n\ntest panedwindow-19.107 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.108 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 84}\n\ntest panedwindow-19.109 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 27} {2 57}}\n\ntest panedwindow-19.110 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 65 20 20} {5 117 20 20}}\ntest panedwindow-19.111 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {26 24}\n\ntest panedwindow-19.112 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {96 24}\n\ntest panedwindow-19.113 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{30 2} {66 2}}\n\ntest panedwindow-19.114 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}\n\ntest panedwindow-19.115 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-orient vertical -sashwidth 0 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 26}\n\ntest panedwindow-19.116 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 96}\n\ntest panedwindow-19.117 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 30} {2 66}}\n\ntest panedwindow-19.118 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 0 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 71 20 20} {5 129 20 20}}\ntest panedwindow-19.119 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.120 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {90 24}\n\ntest panedwindow-19.121 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{27 2} {60 2}}\n\ntest panedwindow-19.122 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {68 5 20 20} {123 5 20 20}}\n\ntest panedwindow-19.123 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 0\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 24}\n\ntest panedwindow-19.124 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 90}\n\ntest panedwindow-19.125 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 27} {2 60}}\n\ntest panedwindow-19.126 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 0 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 68 20 20} {5 123 20 20}}\ntest panedwindow-19.127 {ComputeGeometry, one pane, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {26 24}\n\ntest panedwindow-19.128 {ComputeGeometry, three panes, reqsize set properly} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {96 24}\n\ntest panedwindow-19.129 {ComputeGeometry, sash coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{28 2} {64 2}}\n\ntest panedwindow-19.130 {ComputeGeometry/ArrangePanes, pane coords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 3 -padx 11\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}\n\ntest panedwindow-19.131 {ComputeGeometry, one pane, vertical} -setup {\n    deleteWindows\n} -body {\n    # With just one pane, sashpad and sashwidth should not\n    # affect the panedwindow's geometry, since no sash should\n    # ever be drawn.\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-orient vertical -sashwidth 3 -handlesize 6 \\\n\t-showhandle 1\n    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \\\n\t\t    -sticky \"\"\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 26}\n\ntest panedwindow-19.132 {ComputeGeometry, three panes, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {24 96}\n\ntest panedwindow-19.133 {ComputeGeometry, sash coords, vertical} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.f1 .f2 .f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t\t\t    -sticky \"\"\n    }\n    list [.p sash coord 0] [.p sash coord 1]\n} -cleanup {\n    deleteWindows\n} -result {{2 28} {2 64}}\n\ntest panedwindow-19.134 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 2 -sashpad 5 \\\n\t-sashwidth 3 -handlesize 6 -showhandle 1 \\\n\t-orient vertical\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\t.p add [frame $w -width 20 -height 20 -bg blue] \\\n\t    -sticky nsew -pady 11 -padx 3\n    }\n    pack .p\n    update\n    set result {}\n    foreach w {.p.f1 .p.f2 .p.f3} {\n\tlappend result [list [winfo x $w] [winfo y $w] \\\n\t    [winfo width $w] [winfo height $w]]\n\t}\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {{5 13 20 20} {5 71 20 20} {5 129 20 20}}\n\n\ntest panedwindow-20.1 {destroyed widgets are removed from panedwindow} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [frame .f -width 20 -height 20 -bg blue]\n    destroy .f\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-20.2 {destroyed pane causes geometry recomputation} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red]\n    destroy .f\n    winfo reqwidth .p\n} -cleanup {\n    deleteWindows\n} -result 20\n\n\ntest panedwindow-21.1 {ArrangePanes, extra space is given to the last pane} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red] -sticky nsew\n    place .p -width 100 -x 0 -y 0\n    update\n    winfo width .f2\n} -cleanup {\n    deleteWindows\n} -result 78\ntest panedwindow-21.2 {ArrangePanes, extra space is given to the last pane} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red] -sticky nsew\n    place .p -height 100 -x 0 -y 0\n    update\n    winfo height .f2\n} -cleanup {\n    deleteWindows\n} -result 78\ntest panedwindow-21.3 {ArrangePanes, explicit height/width are preferred} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red] -sticky \"\"\n    .p paneconfigure .f1 -width 10 -height 15\n    pack .p\n    update\n    list [winfo width .f1] [winfo height .f1]\n} -cleanup {\n    deleteWindows\n} -result {10 15}\ntest panedwindow-21.4 {ArrangePanes, panes clipped by size of pane} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red]\n    .p sash place 0 10 0\n    pack .p\n    update\n    list [winfo width .f1] [winfo height .f1]\n} -cleanup {\n    deleteWindows\n} -result {10 20}\ntest panedwindow-21.5 {ArrangePanes, panes clipped by size of pane} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red]\n    .p sash place 0 0 10\n    pack .p\n    update\n    list [winfo width .f1] [winfo height .f1]\n} -cleanup {\n    deleteWindows\n} -result {20 10}\ntest panedwindow-21.6 {ArrangePanes, height of pane taken from total height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .p.f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .p.f2 -width 20 -height 40 -bg red] -sticky \"\"\n    pack .p\n    update\n    winfo y .p.f1\n} -cleanup {\n    deleteWindows\n} -result 10\ntest panedwindow-21.7 {ArrangePanes, width of pane taken from total width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    .p add [frame .p.f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .p.f2 -width 40 -height 40 -bg red] -sticky \"\"\n    pack .p\n    update\n    winfo x .p.f1\n} -cleanup {\n    deleteWindows\n} -result 10\ntest panedwindow-21.8 {ArrangePanes, panes with width <= 0 are unmapped} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 40 -bg red]\n    pack .p\n    update\n    set result [winfo ismapped .f1]\n    .p sash place 0 0 0\n    update\n    lappend result [winfo ismapped .f1]\n} -cleanup {\n    deleteWindows\n} -result {1 0}\ntest panedwindow-21.9 {ArrangePanes, panes with width <= 0 are unmapped} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .p.f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .p.f2 -width 20 -height 40 -bg red]\n    pack .p\n    update\n    set result [winfo ismapped .p.f1]\n    .p sash place 0 0 0\n    update\n    lappend result [winfo ismapped .p.f1]\n} -cleanup {\n    deleteWindows\n} -result {1 0}\ntest panedwindow-21.10 {ArrangePanes, panes with width <= 0 are unmapped} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 -orient vertical\n    .p add [frame .p.f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .p.f2 -width 20 -height 40 -bg red]\n    pack .p\n    update\n    set result [winfo ismapped .p.f1]\n    .p sash place 0 0 0\n    update\n    lappend result [winfo ismapped .p.f1]\n} -cleanup {\n    deleteWindows\n} -result {1 0}\ntest panedwindow-21.11 {ArrangePanes, last pane shrinks} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red] -sticky nsew\n    place .p -width 40 -x 0 -y 0\n    update\n    winfo width .f2\n} -cleanup {\n    deleteWindows\n} -result 18\ntest panedwindow-21.12 {ArrangePanes, last pane shrinks} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \\\n\t    -orient vertical\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 20 -bg red] -sticky nsew\n    place .p -height 40 -x 0 -y 0\n    update\n    winfo height .f2\n} -cleanup {\n    deleteWindows\n} -result 18\ntest panedwindow-21.13 {ArrangePanes, panedwindow resizes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -width 200 -borderwidth 0\n    frame .f1 -height 50 -bg blue\n    set result [list]\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n    .p add .f1\n    pack .p\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {200 1 200 50}\ntest panedwindow-21.14 {ArrangePanes, panedwindow resizes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -height 200 -borderwidth 0 -orient vertical\n    frame .f1 -width 50 -bg blue\n    set result [list]\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n    .p add .f1\n    pack .p\n    lappend result [winfo reqwidth .p] [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {1 200 50 200}\ntest panedwindow-21.15 {ArrangePanes, last pane grows} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -height 50\n    .p add [frame .f1 -width 50 -bg red] [frame .f2 -width 50 -bg white] \\\n\t    [frame .f3 -width 50 -bg blue] [frame .f4 -width 50 -bg green]\n    .p sash place 1 250 0\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n    .p configure -width 300\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n} -cleanup {\n    deleteWindows\n} -result {50 150 1 1 211 50 150 1 89 300}\n\n\ntest panedwindow-22.1 {PanedWindowReqProc, react to pane geometry changes} -setup {\n    deleteWindows\n} -body {\n    # Basically just want to make sure that the PanedWindowReqProc is called\n    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 20 -height 20 -bg blue] \\\n\t    [frame .f2 -width 20 -height 40 -bg red]\n    set result [winfo reqheight .p]\n    .f1 configure -height 80\n    lappend result [winfo reqheight .p]\n} -cleanup {\n    deleteWindows\n} -result {40 80}\ntest panedwindow-22.2 {PanedWindowReqProc, react to pane geometry changes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -orient horizontal -sashpad 0 -sashwidth 2\n    .p add [frame .f1 -width 10] [frame .f2 -width 10]\n    set result [winfo reqwidth .p]\n    .f1 configure -width 20\n    lappend result [winfo reqwidth .p]\n    destroy .p .f1 .f2\n    expr {[lindex $result 1] - [lindex $result 0]}\n} -cleanup {\n    deleteWindows\n} -result 10\n\n\ntest panedwindow-23.1 {ConfigurePanes, can't add panedwindow to itself} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add .p\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {cannot add .p to itself}\ntest panedwindow-23.2 {ConfigurePanes, bad window throws error} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add .b\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad window path name \".b\"}\ntest panedwindow-23.3 {ConfigurePanes, bad window aborts processing} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .b\n    catch {.p add .b .a}\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-23.4 {ConfigurePanes, bad option aborts processing} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .b\n    catch {.p add .b -sticky foobar}\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-23.5 {ConfigurePanes, after win isn't managed by panedwin} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .b\n    button .c\n    .p add .b -after .c\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {window \".c\" is not managed by .p}\ntest panedwindow-23.6 {ConfigurePanes, before win isn't managed by panedwin} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .b\n    button .c\n    .p add .b -before .c\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {window \".c\" is not managed by .p}\ntest panedwindow-23.7 {ConfigurePanes, -after {} is a no-op} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p paneconfigure .b -after {}\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.b .c}\ntest panedwindow-23.8 {ConfigurePanes, -before {} is a no-op} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p paneconfigure .b -before {}\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.b .c}\ntest panedwindow-23.9 {ConfigurePanes, new panes are added} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c]\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.b .c}\ntest panedwindow-23.10 {ConfigurePanes, options applied to all panes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] [button .c] -sticky ne -height 5 -width 5 -minsize 10\n    set result {}\n    foreach w {.b .c} {\n\tset val {}\n\tforeach option {-sticky -height -width -minsize} {\n\t    lappend val $option [.p panecget $w $option]\n\t}\n\tlappend result $w $val\n    }\n    return $result\n} -cleanup {\n    deleteWindows\n} -result {.b {-sticky ne -height 5 -width 5 -minsize 10} .c {-sticky ne -height 5 -width 5 -minsize 10}}\n\ntest panedwindow-23.11 {ConfigurePanes, existing panes are reconfigured} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b] -sticky nw -height 10\n    .p add .b [button .c] -sticky se -height 2\n    list [.p panes] [.p panecget .b -sticky] [.p panecget .b -height] \\\n\t    [.p panecget .c -sticky] [.p panecget .c -height]\n} -cleanup {\n    deleteWindows\n} -result [list {.b .c} es 2 es 2]\ntest panedwindow-23.12 {ConfigurePanes, widgets added to end by default} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p add [button .b]\n    .p add [button .c]\n    .p add [button .d]\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.b .c .d}\ntest panedwindow-23.13 {ConfigurePanes, -after, single addition} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n\n    .p add .a .b\n    .p add .c -after .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .c .b}\ntest panedwindow-23.14 {ConfigurePanes, -after, multiple additions} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b\n    .p add .c .d -after .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .c .d .b}\ntest panedwindow-23.15 {ConfigurePanes, -after, relocates existing widget} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c .d\n    .p add .d -after .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .d .b .c}\ntest panedwindow-23.16 {ConfigurePanes, -after, relocates existing widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c .d\n    .p add .b .d -after .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .b .d .c}\ntest panedwindow-23.17 {ConfigurePanes, -after, relocates existing widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c .d\n    .p add .d .a -after .b\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.b .d .a .c}\ntest panedwindow-23.18 {ConfigurePanes, -after, relocates existing widgets} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c .d\n    .p add .d .a -after .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.d .a .b .c}\ntest panedwindow-23.19 {ConfigurePanes, -after, after last window} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c\n    .p add .d -after .c\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .b .c .d}\ntest panedwindow-23.20 {ConfigurePanes, -before, before first window} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c\n    .p add .d -before .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.d .a .b .c}\ntest panedwindow-23.21 {ConfigurePanes, -before, relocate existing windows} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n    button .d\n\n    .p add .a .b .c\n    .p add .d .b -before .a\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.d .b .a .c}\ntest panedwindow-23.22 {ConfigurePanes, pane specified multiple times} -setup {\n    deleteWindows\n} -body {\n    # This test should not cause a core dump\n\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n\n    .p add .a .a .b .c\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.a .b .c}\ntest panedwindow-23.23 {ConfigurePanes, pane specified multiple times} -setup {\n    deleteWindows\n} -body {\n    # This test should not cause a core dump\n\n    panedwindow .p\n    button .a\n    button .b\n    button .c\n\n    .p add .a .a .b .c\n    .p add .a .b .a -after .c\n    .p panes\n} -cleanup {\n    deleteWindows\n} -result {.c .a .b}\ntest panedwindow-23.24 {ConfigurePanes, panedwindow cannot manage toplevels} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    toplevel .t\n    .p add .t\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {cannot add toplevel .t to .p}\ntest panedwindow-23.25 {ConfigurePanes, restrict possible panes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    frame .f\n    button .f.b\n   .p add .f.b\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {cannot add .f.b to .p}\ntest panedwindow-23.26 {ConfigurePanes, restrict possible panes} -setup {\n    deleteWindows\n} -body {\n    frame .f\n    panedwindow .f.p\n    button .b\n    .f.p add .b\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-23.27 {ConfigurePanes, restrict possible panes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    button .p.b\n    .p add .p.b\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-23.28 {ConfigurePanes, restrict possible panes} -setup {\n    deleteWindows\n} -body {\n    frame .f\n    frame .f.f\n    frame .f.f.f\n    panedwindow .f.f.f.p\n    button .b\n    .f.f.f.p add .b\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-23.29 {ConfigurePanes, -hide works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false\n    frame .f1 -width 40 -height 100 -bg red\n    frame .f2 -width 40 -height 100 -bg white\n    frame .f3 -width 40 -height 100 -bg blue\n    frame .f4 -width 40 -height 100 -bg green\n    .p add .f1 .f2 .f3 .f4\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo ismapped .f1] [winfo ismapped .f2] \\\n\t    [winfo ismapped .f3] [winfo ismapped .f4]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo ismapped .f1] [winfo ismapped .f2] \\\n\t    [winfo ismapped .f3] [winfo ismapped .f4]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n} -cleanup {\n    deleteWindows\n} -result {1 1 1 1 40 40 40 40 171 1 0 1 1 40 40 40 40 128}\ntest panedwindow-23.30 {ConfigurePanes, -hide works} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -width 130 -height 100\n    frame .f1 -width 40 -bg red\n    frame .f2 -width 40 -bg white\n    frame .f3 -width 40 -bg blue\n    frame .f4 -width 40 -bg green\n    .p add .f1 .f2 .f3 .f4\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo ismapped .f1] [winfo ismapped .f2] \\\n\t    [winfo ismapped .f3] [winfo ismapped .f4]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo ismapped .f1] [winfo ismapped .f2] \\\n\t    [winfo ismapped .f3] [winfo ismapped .f4]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4] [winfo width .p]\n} -cleanup {\n    deleteWindows\n} -result {1 1 1 0 39 40 40 1 130 1 0 1 1 40 40 40 42 130}\ntest panedwindow-23.30a {ConfigurePanes, hidden panes are unmapped} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p1 -sashrelief raised\n    panedwindow .p2 -sashrelief raised\n    label .l1 -text Label1\n    label .l2 -text Label2\n    label .l3 -text Label3\n    .p2 add .l2 -sticky nsew\n    .p2 add .l3 -sticky nsew\n    .p1 add .p2 -sticky nsew\n    .p1 add .l1 -sticky nsew\n    pack .p1 -side top -expand 1 -fill both\n    update\n    set result [list]\n    lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \\\n\t    [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]\n    .p2 paneconfigure .l1 -hide 1\n    update\n    lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \\\n\t    [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]\n    .p1 paneconfigure .p2 -hide 1\n    update\n    lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \\\n\t    [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]\n    .p1 paneconfigure .p2 -hide 0\n    update\n    lappend result [list [winfo ismapped .p1] [winfo ismapped .p2] \\\n\t    [winfo ismapped .l1] [winfo ismapped .l2] [winfo ismapped .l3]]\n} -cleanup {\n    deleteWindows\n} -result {{1 1 1 1 1} {1 1 0 1 1} {1 0 0 0 0} {1 1 0 1 1}}\ntest panedwindow-23.31 {ConfigurePanes, -hide works, last pane stretches} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -width 200 -height 200 -borderwidth 0\n    frame .f1 -width 50 -bg red\n    frame .f2 -width 50 -bg green\n    frame .f3 -width 50 -bg blue\n    .p add .f1 .f2 .f3\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3]\n} -cleanup {\n    deleteWindows\n} -result {50 50 94 50 50 147}\ntest panedwindow-23.32 {ConfigurePanes, -hide works, last pane stretches} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -width 200 -height 200 \\\n\t    -borderwidth 0 -orient vertical\n    frame .f1 -height 50 -bg red\n    frame .f2 -height 50 -bg green\n    frame .f3 -height 50 -bg blue\n    .p add .f1 .f2 .f3\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo height .f1] [winfo height .f2] [winfo height .f3]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo height .f1] [winfo height .f2] [winfo height .f3]\n} -cleanup {\n    deleteWindows\n} -result {50 50 94 50 50 147}\n\ntest panedwindow-23.33 {ConfigurePanes, -stretch first} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -height 100 -width 182\n    frame .f1 -width 40 -bg red\n    frame .f2 -width 40 -bg white\n    frame .f3 -width 40 -bg blue\n    frame .f4 -width 40 -bg green\n    .p add .f1 .f2 .f3 .f4 -stretch first\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n} -cleanup {\n    deleteWindows\n} -result {51 40 40 40 94 40 40 40}\ntest panedwindow-23.34 {ConfigurePanes, -stretch middle} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -height 100 -width 182\n    frame .f1 -width 40 -bg red\n    frame .f2 -width 40 -bg white\n    frame .f3 -width 40 -bg blue\n    frame .f4 -width 40 -bg green\n    .p add .f1 .f2 .f3 .f4 -stretch middle\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n} -cleanup {\n    deleteWindows\n} -result {40 45 46 40 40 45 94 40}\ntest panedwindow-23.35 {ConfigurePanes, -stretch always} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -height 100 -width 182\n    frame .f1 -width 40 -bg red\n    frame .f2 -width 40 -bg white\n    frame .f3 -width 40 -bg blue\n    frame .f4 -width 40 -bg green\n    .p add .f1 .f2 .f3 .f4 -stretch always\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n} -cleanup {\n    deleteWindows\n} -result {42 43 43 43 58 43 58 58}\ntest panedwindow-23.36 {ConfigurePanes, -stretch never} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -height 100 -width 182\n    frame .f1 -width 40 -bg red\n    frame .f2 -width 40 -bg white\n    frame .f3 -width 40 -bg blue\n    frame .f4 -width 40 -bg green\n    .p add .f1 .f2 .f3 .f4 -stretch never\n    pack .p\n    update\n    set result [list]\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n    .p paneconfigure .f2 -hide 1\n    update\n    lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \\\n\t    [winfo width .f4]\n} -cleanup {\n    deleteWindows\n} -result {40 40 40 40 40 40 40 40}\n\n\ntest panedwindow-24.1 {Unlink, remove a paned with -before/-after refs} -setup {\n    deleteWindows\n} -body {\n    # Bug 928413\n    set result {}\n    panedwindow .pw\n    label .pw.l1 -text Label1\n    label .pw.l2 -text Label2\n    label .pw.l3 -text Label3\n    .pw add .pw.l1\n    .pw add .pw.l3\n    .pw add .pw.l2 -before .pw.l3\n    lappend result [.pw panecget .pw.l2 -before]\n    destroy .pw.l3\n    lappend result [.pw panecget .pw.l2 -before]\n    .pw paneconfigure .pw.l2 -before .pw.l1\n    lappend result [.pw panecget .pw.l2 -before]\n} -cleanup {\n    deleteWindows\n} -result {.pw.l3 {} .pw.l1}\n\n\ntest panedwindow-25.1 {DestroyPanedWindow} -setup {\n    deleteWindows\n} -body {\n    # This test should not result in any memory leaks.\n    panedwindow .p\n    foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .q .r .s .t} {\n\t.p add [button $w]\n    }\n    foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t} {\n\tdestroy $w\n    }\n    set result {}\n} -result {}\ntest panedwindow-25.2 {UnmapNotify and MapNotify events are propagated to panes} -setup {\n    deleteWindows\n} -body {\n    panedwindow .pw\n    .pw add [button .pw.b]\n    pack .pw\n    update\n    set result [winfo ismapped .pw.b]\n    pack forget .pw\n    update\n    lappend result [winfo ismapped .pw.b]\n    lappend result [winfo ismapped .pw]\n    pack .pw\n    update\n    lappend result [winfo ismapped .pw]\n    lappend result [winfo ismapped .pw.b]\n    destroy .pw .pw.b\n    set result\n} -cleanup {\n    deleteWindows\n} -result {1 0 0 1 1}\n\n\ntest panedwindow-26.1 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.2 {PanedWindowIdentifyCoords, padding is included} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 20 0\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.3 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 22 0\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.4 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 24 0\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.5 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 26 0\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.6 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 26 -1\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.7 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 26 100\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.8 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 6\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 22 4\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.9 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 6\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 22 5\n} -cleanup {\n    deleteWindows\n} -result {0 handle}\ntest panedwindow-26.10 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 8\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 20 5\n} -cleanup {\n    deleteWindows\n} -result {0 handle}\ntest panedwindow-26.11 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 8\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 20 0\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.12 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20] \\\n\t    [frame .f3 -bg green -width 20 -height 20]\n    .p identify 48 0\n} -cleanup {\n    deleteWindows\n} -result {1 sash}\ntest panedwindow-26.13 {identify subcommand errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4\n    .p identify\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {wrong # args: should be \".p identify x y\"}\ntest panedwindow-26.14 {identify subcommand errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p identify foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"foo\"}\ntest panedwindow-26.15 {identify subcommand errors} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p\n    .p identify 0 bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"bar\"}\ntest panedwindow-26.16 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 0\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.17 {PanedWindowIdentifyCoords, padding is included} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 20\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.18 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 22\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.19 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 24\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.20 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 26\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.21 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify -1 26\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.22 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 100 26\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-26.23 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 6 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 4 22\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.24 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 6 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 5 22\n} -cleanup {\n    deleteWindows\n} -result {0 handle}\ntest panedwindow-26.25 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 8 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 5 20\n} -cleanup {\n    deleteWindows\n} -result {0 handle}\ntest panedwindow-26.26 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \\\n\t    -handlesize 8 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20]\n    .p identify 0 20\n} -cleanup {\n    deleteWindows\n} -result {0 sash}\ntest panedwindow-26.27 {PanedWindowIdentifyCoords} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2 -orient vertical\n    .p add [frame .f -bg red -width 20 -height 20] \\\n\t    [frame .f2 -bg blue -width 20 -height 20] \\\n\t    [frame .f3 -bg green -width 20 -height 20]\n    .p identify 0 48\n} -cleanup {\n    deleteWindows\n} -result {1 sash}\n\n\ntest panedwindow-27.1 {destroy the window cleanly on error [Bug #616589]} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bogusopt bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-bogusopt\"}\ntest panedwindow-27.2 {destroy the window cleanly on rename [Bug #616589]} -setup {\n    deleteWindows\n} -body {\n    destroy .p\n    panedwindow .p\n    rename .p {}\n    winfo exists .p\n} -cleanup {\n    deleteWindows\n} -result 0\n\n\ntest panedwindow-28.1 {resizing width} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -bd 5\n    frame .f1 -width 100 -height 50 -bg blue\n    frame .f2 -width 100 -height 50 -bg red\n\n    .p add .f1 -sticky news\n    .p add .f2 -sticky news\n    pack .p -side top -fill both -expand 1\n    wm geometry . \"\"\n    update\n    # Note the width\n    set a [winfo width .f2]\n    # Increase the size by 10\n    regexp {^(\\d+)x(\\d+)} [wm geometry .] -> w h\n    wm geometry . [expr {$w + 10}]x$h\n    update\n    set b \"$a [winfo width .f2]\"\n} -cleanup {\n    deleteWindows\n} -result {100 110}\n\ntest panedwindow-28.2 {resizing height} -setup {\n    deleteWindows\n} -body {\n    panedwindow .p -orient vertical -bd 5\n    frame .f1 -width 50 -height 100 -bg blue\n    frame .f2 -width 50 -height 100 -bg red\n\n    .p add .f1 -sticky news\n    .p add .f2 -sticky news\n    pack .p -side top -fill both -expand 1\n    wm geometry . \"\"\n    update\n    # Note the height\n    set a [winfo height .f2]\n    # Increase the size by 10\n    regexp {^(\\d+)x(\\d+)} [wm geometry .] -> w h\n    wm geometry . ${w}x[expr {$h + 10}]\n    update\n    set b \"$a [winfo height .f2]\"\n} -cleanup {\n    deleteWindows\n} -result {100 110}\n\n\ntest panedwindow-29.1 {display on depths other than the default one} -constraints {\n    pseudocolor8 haveTruecolor24\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -visual {truecolor 24}\n    pack [panedwindow .t.p]\n    .t.p add [frame .t.p.f1] [frame .t.p.f2]\n    update\n    # If we got here, we didn't crash and that's good\n} -cleanup {\n    deleteWindows\n} -result {}\ntest panedwindow-29.2 {display on depths other than the default one} -constraints {\n    pseudocolor8 haveTruecolor24\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -visual {pseudocolor 8}\n    pack [frame .t.f -visual {truecolor 24}]\n    pack [panedwindow .t.f.p]\n    .t.f.p add [frame .t.f.p.f1 -width 5] [frame .t.f.p.f2 -width 5]\n    update\n    .t.f.p proxy place 1 1\n    update\n    .t.f.p proxy forget\n    update\n    # If we got here, we didn't crash and that's good\n} -cleanup {\n    deleteWindows\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/pkgconfig.test",
    "content": "# This file is a Tcl script to test the command \"pkgconfig\".\n#\n# Copyright © 1991-1993 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2017 Stuart Cassoff <stwo@users.sourceforge.net>\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest pkgconfig-1.1 {query keys} -constraints macOrUnix -body {\n    lsort [::tk::pkgconfig list]\n} -match glob -result [list \\\n    *bindir,install bindir,runtime *demodir,install \\\n    demodir,runtime*docdir,install docdir,runtime fontsystem \\\n    includedir,install includedir,runtime \\\n    libdir,install libdir,runtime*\\\n    scriptdir,install scriptdir,runtime*\\\n]\ntest pkgconfig-1.2 {query keys multiple times} {\n    string compare [::tk::pkgconfig list] [::tk::pkgconfig list]\n} 0\ntest pkgconfig-1.3 {query value multiple times} {\n    string compare \\\n\t    [::tk::pkgconfig get fontsystem] \\\n\t    [::tk::pkgconfig get fontsystem]\n} 0\n\n\ntest pkgconfig-2.0 {error: missing subcommand} {\n    catch {::tk::pkgconfig} msg\n    set msg\n} {wrong # args: should be \"::tk::pkgconfig subcommand ?arg?\"}\ntest pkgconfig-2.1 {error: illegal subcommand} {\n    catch {::tk::pkgconfig foo} msg\n    set msg\n} {bad subcommand \"foo\": must be get or list}\ntest pkgconfig-2.2 {error: list with arguments} {\n    catch {::tk::pkgconfig list foo} msg\n    set msg\n} {wrong # args: should be \"::tk::pkgconfig list\"}\ntest pkgconfig-2.3 {error: get without arguments} {\n    catch {::tk::pkgconfig get} msg\n    set msg\n} {wrong # args: should be \"::tk::pkgconfig get key\"}\ntest pkgconfig-2.4 {error: query unknown key} {\n    catch {::tk::pkgconfig get foo} msg\n    set msg\n} {key not known}\ntest pkgconfig-2.5 {error: query with to many arguments} {\n    catch {::tk::pkgconfig get foo bar} msg\n    set msg\n} {wrong # args: should be \"::tk::pkgconfig subcommand ?arg?\"}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/place.test",
    "content": "# This file is a Tcl script to test out the \"place\" command.\n#\n# Copyright © 1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is woefully incomplete.  At present, only a\n# few of the features are tested.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\n# Used for constraining memory leak tests\ntestConstraint memory [llength [info commands memory]]\n\n#\n# COMMON TEST SETUP\n#\n# For tests 1.* - 8.*\n#\n\ntoplevel .t -width 300 -height 200 -bd 0\nwm geom .t +0+0\nframe .t.f -width 154 -height 84 -bd 2 -relief raised\nplace .t.f -x 48 -y 38\nframe .t.f2 -width 30 -height 60 -bd 2 -relief raised\nupdate\n\n#\n# TESTS\n#\n\ntest place-1.1 {Tk_PlaceCmd procedure, \"info\" option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -x 0\n    place info .t.f2\n} -result {-in .t -x 0 -relx 0 -y 0 -rely 0 -width {} -relwidth {} -height {} -relheight {} -anchor nw -bordermode inside}\ntest place-1.2 {Tk_PlaceCmd procedure, \"info\" option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -x 1 -y 2 -width 3 -height 4 -relx 0.1 -rely 0.2 \\\n\t-relwidth 0.3 -relheight 0.4 -anchor se -in .t.f  \\\n\t-bordermode outside\n    place info .t.f2\n} -result {-in .t.f -x 1 -relx 0.1 -y 2 -rely 0.2 -width 3 -relwidth 0.3 -height 4 -relheight 0.4 -anchor se -bordermode outside}\ntest place-1.3 {Tk_PlaceCmd procedure, \"info\" option} -setup {\n    place forget .t.f2\n    destroy .t.a.b\n} -body {\n    # Make sure the result is built as a proper list by using a space in parent\n    frame \".t.a b\"\n    place .t.f2 -x 1 -y 2 -width {} -height 4 -relx 0.2 -rely 0.2 \\\n\t-relwidth 0.3 -relheight {} -anchor w -in \".t.a b\"  \\\n\t-bordermode ignore\n    place info .t.f2\n} -cleanup {\n    destroy \".t.a.b\"\n} -result {-in {.t.a b} -x 1 -relx 0.2 -y 2 -rely 0.2 -width {} -relwidth 0.3 -height 4 -relheight {} -anchor w -bordermode ignore}\n\n\ntest place-2.1 {ConfigureContent procedure, -height option} -body {\n    place .t.f2 -height abcd\n} -returnCodes error -result {expected screen distance or \"\" but got \"abcd\"}\ntest place-2.2 {ConfigureContent procedure, -height option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -height 40\n    update\n    winfo height .t.f2\n} -result 40\ntest place-2.3 {ConfigureContent procedure, -height option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -height 120\n    update\n    place .t.f2 -height {}\n    update\n    winfo height .t.f2\n} -result 60\n\n\ntest place-3.1 {ConfigureContent procedure, -relheight option} -body {\n    place .t.f2 -relheight abcd\n} -returnCodes error -result {expected floating-point number or \"\" but got \"abcd\"}\ntest place-3.2 {ConfigureContent procedure, -relheight option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -relheight .5\n    update\n    winfo height .t.f2\n} -result 40\ntest place-3.3 {ConfigureContent procedure, -relheight option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -relheight .8\n    update\n    place .t.f2 -relheight {}\n    update\n    winfo height .t.f2\n} -result 60\n\n\ntest place-4.1 {ConfigureContent procedure, bad -in options} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f2\n} -returnCodes error -result {can't place \".t.f2\" relative to itself}\ntest place-4.2 {ConfigureContent procedure, bad -in option} -setup {\n    place forget .t.f2\n} -body {\n    set result [list [winfo manager .t.f2]]\n    catch {place .t.f2 -in .t.f2}\n    lappend result [winfo manager .t.f2]\n} -result {{} {}}\ntest place-4.3 {ConfigureContent procedure, bad -in option} -setup {\n    place forget .t.f2\n} -body {\n    winfo manager .t.f2\n    place .t.f2 -in .t.f2\n} -returnCodes error -result {can't place \".t.f2\" relative to itself}\ntest place-4.4 {ConfigureContent procedure, bad -in option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .\n} -returnCodes error -result {can't place \".t.f2\" relative to \".\"}\ntest place-4.5 {ConfigureContent procedure, bad -in option} -setup {\n} -body {\n    frame .t.f1\n    place .t.f1 -in .t.f1\n} -returnCodes error -result {can't place \".t.f1\" relative to itself}\ntest place-4.6 {prevent management loops} -setup {\n    place forget .t.f1\n} -body {\n    place .t.f1 -in .t.f2\n    place .t.f2 -in .t.f1\n} -returnCodes error -result {can't put \".t.f2\" inside \".t.f1\": would cause management loop}\ntest place-4.7 {prevent management loops} -setup {\n    place forget .t.f1\n    place forget .t.f2\n} -body {\n    frame .t.f3\n    place .t.f1 -in .t.f2\n    place .t.f2 -in .t.f3\n    place .t.f3 -in .t.f1\n} -returnCodes error -result {can't put \".t.f3\" inside \".t.f1\": would cause management loop}\n\ntest place-5.1 {ConfigureContent procedure, -relwidth option} -body {\n    place .t.f2 -relwidth abcd\n} -returnCodes error -result {expected floating-point number or \"\" but got \"abcd\"}\ntest place-5.2 {ConfigureContent procedure, -relwidth option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -relwidth .5\n    update\n    winfo width .t.f2\n} -result 75\ntest place-5.3 {ConfigureContent procedure, -relwidth option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -relwidth .8\n    update\n    place .t.f2 -relwidth {}\n    update\n    winfo width .t.f2\n} -result 30\n\ntest place-6.1 {ConfigureContent procedure, -width option} -body {\n    place .t.f2 -width abcd\n} -returnCodes error -result {expected screen distance or \"\" but got \"abcd\"}\ntest place-6.2 {ConfigureContent procedure, -width option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -width 100\n    update\n    winfo width .t.f2\n} -result 100\ntest place-6.3 {ConfigureContent procedure, -width option} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -width 120\n    update\n    place .t.f2 -width {}\n    update\n    winfo width .t.f2\n} -result 30\n\n\ntest place-7.1 {ReconfigurePlacement procedure, computing position} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -x -2 -relx .5 -y 3 -rely .4\n    update\n    winfo geometry .t.f2\n} -result {30x60+123+75}\ntest place-7.2 {ReconfigurePlacement procedure, position rounding} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -x -1.4 -y -2.3\n    update\n    winfo geometry .t.f2\n} -result {30x60+49+38}\ntest place-7.3 {ReconfigurePlacement procedure, position rounding} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -x 1.4 -y 2.3\n    update\n    winfo geometry .t.f2\n} -result {30x60+51+42}\ntest place-7.4 {ReconfigurePlacement procedure, position rounding} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -x -1.6 -y -2.7\n    update\n    winfo geometry .t.f2\n} -result {30x60+48+37}\ntest place-7.5 {ReconfigurePlacement procedure, position rounding} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -x 1.6 -y 2.7\n    update\n    winfo geometry .t.f2\n} -result {30x60+52+43}\ntest place-7.6 {ReconfigurePlacement procedure, position rounding} -setup {\n    destroy .t.f3\n} -body {\n    frame .t.f3 -width 100 -height 100 -bg #f00000 -bd 0\n    place .t.f3 -x 0 -y 0\n    raise .t.f2\n    place forget .t.f2\n    place .t.f2 -in .t.f3 -relx .303 -rely .406 -relwidth .304 -relheight .206\n    update\n    winfo geometry .t.f2\n} -cleanup {\n    destroy .t.f3\n} -result {31x20+30+41}\ntest place-7.7 {ReconfigurePlacement procedure, computing size} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -width 120 -height 89\n    update\n    list [winfo width .t.f2] [winfo height .t.f2]\n} -result {120 89}\ntest place-7.8 {ReconfigurePlacement procedure, computing size} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -relwidth .4 -relheight .5\n    update\n    list [winfo width .t.f2] [winfo height .t.f2]\n} -result {60 40}\ntest place-7.9 {ReconfigurePlacement procedure, computing size} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -width 10 -relwidth .4 -height -4 -relheight .5\n    update\n    list [winfo width .t.f2] [winfo height .t.f2]\n} -result {70 36}\ntest place-7.10 {ReconfigurePlacement procedure, computing size} -setup {\n    place forget .t.f2\n} -body {\n    place .t.f2 -in .t.f -width 10 -relwidth .4 -height -4 -relheight .5\n    place .t.f2 -width {} -relwidth {} -height {} -relheight {}\n    update\n    list [winfo width .t.f2] [winfo height .t.f2]\n} -result {30 60}\n\n# Tests place-8.1 and place-8.2 are constrained with failsOnCILinux\n# because they are failing in the GitHub CI environment, using Linux Ubuntu.\n# These tests are also constrained with failsOnXQuartz because they fail\n# on macOS when building with clang --disable-aqua (which uses XQuartz)\n# (this is the case both at GitHub CI and on a real Mac).\n# Analysis shows that, on both cases, WaitForMapNotify is giving up on\n# waiting for the MapNotify event that should show up when running\n# 'wm iconify'. The timeout delay (2s) is exceeded without the unmapping\n# having happened. The cause for this is unknown (see comments in WaitForMapNotify).\n\ntest place-8.1 {PlaceStructureProc, mapping and unmapping content} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    place forget .t.f2\n    place forget .t.f\n} -body {\n    place .t.f2 -relx 1.0 -rely 1.0 -anchor sw\n    update\n    set result [winfo ismapped .t.f2]\n    wm iconify .t\n    lappend result [winfo ismapped .t.f2]\n    place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw\n    update\n    lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]\n    wm deiconify .t\n    update\n    lappend result [winfo ismapped .t.f2]\n} -result {1 0 40 30 0 1}\ntest place-8.2 {PlaceStructureProc, mapping and unmapping content} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    place forget .t.f2\n    place forget .t.f\n} -body {\n    place .t.f -x 0 -y 0 -width 200 -height 100\n    place .t.f2 -in .t.f -relx 1.0 -rely 1.0 -anchor sw -width 50 -height 20\n    update\n    set result [winfo ismapped .t.f2]\n    wm iconify .t\n    update idletasks\n    lappend result [winfo ismapped .t.f2]\n    place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw\n    update\n    lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]\n    wm deiconify .t\n    update\n    lappend result [winfo ismapped .t.f2]\n} -result {1 0 42 32 0 1}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\ntest place-9.1 {PlaceObjCmd} -body {\n    place\n} -returnCodes error -result {wrong # args: should be \"place option|pathName args\"}\ntest place-9.2 {PlaceObjCmd} -body {\n    place foo\n} -returnCodes error -result {wrong # args: should be \"place option|pathName args\"}\ntest place-9.3 {PlaceObjCmd} -setup {\n    destroy .foo\n} -body {\n    place .foo bar\n} -returnCodes error -result {bad window path name \".foo\"}\ntest place-9.4 {PlaceObjCmd} -setup {\n    destroy .foo\n} -body {\n    place bar .foo\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {bad window path name \".foo\"}\ntest place-9.5 {PlaceObjCmd} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place badopt .foo\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {bad option \"badopt\": must be configure, content, forget, or info}\ntest place-9.6 {PlaceObjCmd, configure errors} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place configure .foo\n} -cleanup {\n    destroy .foo\n} -returnCodes ok -result {}\ntest place-9.7 {PlaceObjCmd, configure errors} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place configure .foo bar\n} -cleanup {\n    destroy .foo\n} -returnCodes ok -result {}\ntest place-9.8 {PlaceObjCmd, configure} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -x 0 -y 0\n    place configure .foo\n} -cleanup {\n    destroy .foo\n} -result [list {-anchor {} {} nw nw} {-bordermode {} {} inside inside} {-height {} {} {} {}} {-in {} {} {} .} {-relheight {} {} {} {}} {-relwidth {} {} {} {}} {-relx {} {} 0.0 0.0} {-rely {} {} 0.0 0.0} {-width {} {} {} {}} {-x {} {} 0 0} {-y {} {} 0 0}]\ntest place-9.9 {PlaceObjCmd, configure} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -x 0 -y 0\n    place configure .foo -x\n} -cleanup {\n    destroy .foo\n} -result {-x {} {} 0 0}\ntest place-9.10 {PlaceObjCmd, forget errors} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place forget .foo bar\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {wrong # args: should be \"place forget pathName\"}\ntest place-9.11 {PlaceObjCmd, info errors} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place info .foo bar\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {wrong # args: should be \"place info pathName\"}\ntest place-9.12 {PlaceObjCmd, content errors} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place content .foo bar\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {wrong # args: should be \"place content pathName\"}\n\n\ntest place-10.1 {ConfigureContent} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -badopt\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {unknown option \"-badopt\"}\ntest place-10.2 {ConfigureContent} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -anchor\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {value for \"-anchor\" missing}\ntest place-10.3 {ConfigureContent} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -bordermode j\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {bad bordermode \"j\": must be inside, ignore, or outside}\ntest place-10.4 {ConfigureContent} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place configure .foo -x 0 -y\n} -cleanup {\n    destroy .foo\n} -returnCodes error -result {value for \"-y\" missing}\n\n\ntest place-11.1 {PlaceObjCmd, content command} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place content .foo\n} -cleanup {\n    destroy .foo\n} -result {}\ntest place-11.2 {PlaceObjCmd, content command} -setup {\n    destroy .foo .bar\n} -body {\n    frame .foo\n    frame .bar\n    place .bar -in .foo\n    place content .foo\n} -cleanup {\n    destroy .foo .bar\n} -result [list .bar]\n\n\ntest place-12.1 {PlaceObjCmd, forget command} -setup {\n    destroy .foo\n} -body {\n    frame .foo\n    place .foo -width 50 -height 50\n    update\n    set res [winfo ismapped .foo]\n    place forget .foo\n    update\n    lappend res [winfo ismapped .foo]\n} -cleanup {\n    destroy .foo\n} -result {1 0}\n\n\ntest place-13.1 {test respect for internalborder} -setup {\n    destroy .pack\n} -body {\n    toplevel .pack\n    wm geometry .pack 200x200\n    frame .pack.l -width 15 -height 10\n    labelframe .pack.lf -labelwidget .pack.l\n    pack .pack.lf -fill both -expand 1\n    frame .pack.lf.f\n    place .pack.lf.f -x 0 -y 0 -relwidth 1.0 -relheight 1.0\n    update\n    set res [list [winfo geometry .pack.lf.f]]\n    .pack.lf configure -labelanchor e -padx 3 -pady 5\n    update\n    lappend res [winfo geometry .pack.lf.f]\n} -cleanup {\n    destroy .pack\n} -result {196x188+2+10 177x186+5+7}\n\n\ntest place-14.1 {memory leak testing} -constraints memory -setup {\n    destroy .f\n    proc getbytes {} {\n\tset lines [split [memory info] \"\\n\"]\n\tlindex [lindex $lines 3] 3\n    }\n    # Repeat each body checking that memory does not increase\n    proc stress {args} {\n\tset res {}\n\tforeach body $args {\n\t    set end 0\n\t    for {set i 0} {$i < 5} {incr i} {\n\t\tuplevel 1 $body\n\t\tset tmp $end\n\t\tset end [getbytes]\n\t    }\n\t    lappend res [expr {$end - $tmp}]\n\t}\n\treturn $res\n    }\n} -body {\n    # Test all manners of forgetting content\n    frame .f\n    frame .f.f\n    stress {\n\tplace .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]\n\tplace forget .f.f\n    } {\n\tplace .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]\n\tpack .f.f\n\tupdate; # Needed because of TIP #518, handle <<NoManagedChild>> event.\n    } {\n\tplace .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]\n\tdestroy .f\n\tframe .f\n\tframe .f.f\n    }\n} -cleanup {\n    destroy .f\n    rename getbytes {}\n    rename stress {}\n} -result {0 0 0}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/raise.test",
    "content": "# This file is a Tcl script to test out Tk's \"raise\" and\n# \"lower\" commands, plus associated code to manage window\n# stacking order.\n#\n# Copyright © 1993-1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# raise_getOrder --\n#\n# Return information about which windows are on top of which other windows.\n#\nproc raise_getOrder {} {\n    set x [winfo rootx .raise]\n    set y [winfo rooty .raise]\n    list [winfo name [winfo containing [expr {$x+50}] [expr {$y+70}]]] \\\n\t    [winfo name [winfo containing [expr {$x+90}] [expr {$y+70}]]] \\\n\t    [winfo name [winfo containing [expr {$x+130}] [expr {$y+70}]]] \\\n\t    [winfo name [winfo containing [expr {$x+70}] [expr {$y+100}]]] \\\n\t    [winfo name [winfo containing [expr {$x+110}] [expr {$y+100}]]] \\\n\t    [winfo name [winfo containing [expr {$x+50}] [expr {$y+130}]]] \\\n\t    [winfo name [winfo containing [expr {$x+90}] [expr {$y+130}]]] \\\n\t    [winfo name [winfo containing [expr {$x+130}] [expr {$y+130}]]]\n}\n\n# raise_makeToplevels --\n#\n# Set up a collection of top-level windows\n#\nproc raise_makeToplevels {} {\n    deleteWindows\n    foreach i {.raise1 .raise2 .raise3} {\n\ttoplevel $i\n\twm geom $i 150x100+0+0\n\tupdate\n    }\n}\n\n# raise_setup --\n#\n# Create a bunch of overlapping windows, which should make it easy to detect\n# differences in order.\n#\nproc raise_setup {} {\n    destroy {*}[winfo children .raise]\n    update idletasks\n    foreach i {a b c d e} {\n\t    label .raise.$i -text $i -relief raised -bd 2\n    }\n    place .raise.a -x 20 -y 60 -width 60 -height 80\n    place .raise.b -x 60 -y 60 -width 60 -height 80\n    place .raise.c -x 100 -y 60 -width 60 -height 80\n    place .raise.d -x 40 -y 20 -width 100 -height 60\n    place .raise.e -x 40 -y 120 -width 100 -height 60\n}\n\n#\n# COMMON TEST SETUP\n#\n\nwm geometry . +400+400\ntoplevel .raise\nwm geom .raise 250x200+0+0\n\n#\n# TESTS\n#\n\ntest raise-1.1 {preserve creation order} -body {\n    raise_setup\n    tkwait visibility .raise.e\n    raise_getOrder\n} -result {d d d b c e e e}\ntest raise-1.2 {preserve creation order} -constraints testmakeexist -body {\n    raise_setup\n    testmakeexist .raise.a\n    update\n    raise_getOrder\n} -result {d d d b c e e e}\ntest raise-1.3 {preserve creation order} -constraints testmakeexist -body {\n    raise_setup\n    testmakeexist .raise.c\n    update\n    raise_getOrder\n} -result {d d d b c e e e}\ntest raise-1.4 {preserve creation order} -constraints testmakeexist -body {\n    raise_setup\n    testmakeexist .raise.e\n    update\n    raise_getOrder\n} -result {d d d b c e e e}\ntest raise-1.5 {preserve creation order} -constraints testmakeexist -body {\n    raise_setup\n    testmakeexist .raise.d .raise.c .raise.b\n    update\n    raise_getOrder\n} -result {d d d b c e e e}\n\n\ntest raise-2.1 {raise internal windows before creation} -body {\n    raise_setup\n    raise .raise.a\n    update\n    raise_getOrder\n} -result {a d d a c a e e}\ntest raise-2.2 {raise internal windows before creation} -body {\n    raise_setup\n    raise .raise.c\n    update\n    raise_getOrder\n} -result {d d c b c e e c}\ntest raise-2.3 {raise internal windows before creation} -body {\n    raise_setup\n    raise .raise.e\n    update\n    raise_getOrder\n} -result {d d d b c e e e}\ntest raise-2.4 {raise internal windows before creation} -body {\n    raise_setup\n    raise .raise.e .raise.a\n    update\n    raise_getOrder\n} -result {d d d b c e b c}\ntest raise-2.5 {raise internal windows before creation} -body {\n    raise_setup\n    raise .raise.a .raise.d\n    update\n    raise_getOrder\n} -result {a d d a c e e e}\n\n\ntest raise-3.1 {raise internal windows after creation} -body {\n    raise_setup\n    update\n    raise .raise.a .raise.d\n    raise_getOrder\n} -result {a d d a c e e e}\ntest raise-3.2 {raise internal windows after creation} -constraints {\n\ttestmakeexist\n} -body {\n    raise_setup\n    testmakeexist .raise.a .raise.b\n    raise .raise.a .raise.b\n    update\n    raise_getOrder\n} -result {d d d a c e e e}\ntest raise-3.3 {raise internal windows after creation} -constraints {\n\ttestmakeexist\n} -body {\n    raise_setup\n    testmakeexist .raise.a .raise.d\n    raise .raise.a .raise.b\n    update\n    raise_getOrder\n} -result {d d d a c e e e}\ntest raise-3.4 {raise internal windows after creation} -constraints {\n\ttestmakeexist\n} -body {\n    raise_setup\n    testmakeexist .raise.a .raise.c .raise.d\n    raise .raise.a .raise.b\n    update\n    raise_getOrder\n} -result {d d d a c e e e}\n\n\ntest raise-4.1 {raise relative to nephews} -body {\n    raise_setup\n    update\n    frame .raise.d.child\n    raise .raise.a .raise.d.child\n    raise_getOrder\n} -result {a d d a c e e e}\ntest raise-4.2 {raise relative to nephews} -setup {\n    destroy .raise2\n} -body {\n    raise_setup\n    update\n    frame .raise2\n    raise .raise.a .raise2\n} -cleanup {\n    destroy .raise2\n} -returnCodes error -result {can't raise \".raise.a\" above \".raise2\"}\n\n\ntest raise-5.1 {lower internal windows} -body {\n    raise_setup\n    update\n    lower .raise.d\n    raise_getOrder\n} -result {a b c b c e e e}\ntest raise-5.2 {lower internal windows} -body {\n    raise_setup\n    update\n    lower .raise.d .raise.b\n    raise_getOrder\n} -result {d b c b c e e e}\ntest raise-5.3 {lower internal windows} -body {\n    raise_setup\n    update\n    lower .raise.a .raise.e\n    raise_getOrder\n} -result {a d d a c e e e}\ntest raise-5.4 {lower internal windows} -setup {\n    destroy .raise2\n} -body {\n    raise_setup\n    update\n    frame .raise2\n    lower .raise.a .raise2\n} -cleanup {\n    destroy .raise2\n} -returnCodes error -result {can't lower \".raise.a\" below \".raise2\"}\n\n\ntest raise-6.1 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    update\n    raise .raise1\n    winfo containing [winfo rootx .raise1] [winfo rooty .raise1]\n} -result {.raise1}\ntest raise-6.2 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    update\n    raise .raise2\n    winfo containing [winfo rootx .raise1] [winfo rooty .raise1]\n} -result {.raise2}\ntest raise-6.3 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    update\n    raise .raise3\n    raise .raise2\n    raise .raise1 .raise3\n    set result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n    destroy .raise2\n    update\n    after 500\n    list $result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n} -result {.raise2 .raise1}\ntest raise-6.4 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    update\n    raise .raise2\n    raise .raise1\n    lower .raise3 .raise1\n    set result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n    wm geometry .raise2 +30+30\n    wm geometry .raise1 +60+60\n    destroy .raise1\n    update\n    after 500\n    list $result [winfo containing [winfo rootx .raise2] \\\n\t    [winfo rooty .raise2]]\n} -result {.raise1 .raise3}\ntest raise-6.5 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    raise .raise1\n    set time [lindex [time {raise .raise1}] 0]\n    expr {$time < 2000000}\n} -result 1\ntest raise-6.6 {raise/lower toplevel windows} -constraints {\n\tnonPortable\n} -body {\n    raise_makeToplevels\n    update\n    raise .raise2\n    raise .raise1\n    raise .raise3\n    frame .raise1.f1\n    frame .raise1.f1.f2\n    lower .raise3 .raise1.f1.f2\n    set result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n    destroy .raise1\n    update\n    after 500\n    list $result [winfo containing [winfo rootx .raise2] \\\n\t    [winfo rooty .raise2]]\n} -result {.raise1 .raise3}\n\n\ntest raise-7.1 {errors in raise/lower commands} -body {\n    raise\n} -returnCodes error -result {wrong # args: should be \"raise window ?aboveThis?\"}\ntest raise-7.2 {errors in raise/lower commands} -body {\n    raise a b c\n} -returnCodes error -result {wrong # args: should be \"raise window ?aboveThis?\"}\ntest raise-7.3 {errors in raise/lower commands} -body {\n    raise badName\n} -returnCodes error -result {bad window path name \"badName\"}\ntest raise-7.4 {errors in raise/lower commands} -body {\n    raise . badName2\n} -returnCodes error -result {bad window path name \"badName2\"}\ntest raise-7.5 {errors in raise/lower commands} -body {\n    lower\n} -returnCodes error -result {wrong # args: should be \"lower window ?belowThis?\"}\ntest raise-7.6 {errors in raise/lower commands} -body {\n    lower a b c\n} -returnCodes error -result {wrong # args: should be \"lower window ?belowThis?\"}\ntest raise-7.7 {errors in raise/lower commands} -body {\n    lower badName3\n} -returnCodes error -result {bad window path name \"badName3\"}\ntest raise-7.8 {errors in raise/lower commands} -body {\n    lower . badName4\n} -returnCodes error -result {bad window path name \"badName4\"}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ncleanupTests\n"
  },
  {
    "path": "tests/safe.test",
    "content": "# This file is a Tcl script to test the Safe Tk facility.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# Any time tests fail here with an error like:\n#\n#     Can't find a usable tk.tcl in the following directories:\n#\t{$p(:26:)}\n#\n#     $p(:26:)/tk.tcl: script error\n#     script error\n#\tinvoked from within\n#     \"source {$p(:26:)/tk.tcl}\"\n#\t(\"uplevel\" body line 1)\n#\tinvoked from within\n#     \"uplevel #0 [list source $file]\"\n#\n#\n#     This probably means that tk wasn't installed properly.\n#\n# it indicates that something went wrong sourcing tk.tcl.\n# Ensure that any changes that occurred to tk.tcl will work or are properly\n# prevented in a safe interpreter.  -- hobbs\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n# Avoid hard-coding the set of commands hidden in a baseline Safe Tcl interp\n# as it is subject to change in point releases without announcement.\nset hidden_cmds [apply { {} {\n    set i [interp create -safe]\n    try {\n\treturn [interp hidden $i]\n    } finally {\n\tinterp delete $i\n    }\n}}]\n\n# The set of hidden commands is platform dependent:\n\nlappend hidden_cmds \\\n\tbell clipboard grab menu selection toplevel wm\nif {[tk windowingsystem] ne \"x11\"} {\n    lappend hidden_cmds tk_chooseColor tk_chooseDirectory \\\n\ttk_getOpenFile tk_getSaveFile tk_messageBox\n}\nif {[llength [info commands send]]} {\n    lappend hidden_cmds send\n}\n\nset saveAutoPath $::auto_path\nset auto_path [list [info library] $::tk_library]\nset hidden_cmds [lsort $hidden_cmds]\n\n#\n# TESTS\n#\n\ntest safe-1.1 {Safe Tk loading into an interpreter} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::loadTk [safe::interpCreate a]\n    safe::interpDelete a\n    set x {}\n    return $x\n} -result {}\ntest safe-1.2 {Safe Tk loading into an interpreter, see bug [https://core.tcl-lang.org/tcl/tktview/8f5e7a2633]} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    lsort [interp hidden a]\n} -cleanup {\n    safe::interpDelete a\n} -result $hidden_cmds\ntest safe-1.3 {Safe Tk loading into an interpreter} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    lsort [interp aliases a]\n} -cleanup {\n    safe::interpDelete a\n} -match glob -result {*encoding*exit*glob*load*source*}\n\ntest safe-2.1 {Unsafe commands not available} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status broken\n    if {[catch {interp eval a {toplevel .t}} msg]} {\n\tset status ok\n    }\n    return $status\n} -cleanup {\n    safe::interpDelete a\n} -result ok\ntest safe-2.2 {Unsafe commands not available} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status broken\n    if {[catch {interp eval a {menu .m}} msg]} {\n\tset status ok\n    }\n    return $status\n} -cleanup {\n    safe::interpDelete a\n} -result ok\ntest safe-2.3 {Unsafe subcommands not available} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status broken\n    if {[catch {interp eval a {tk appname}} msg]} {\n\tset status ok\n    }\n    list $status $msg\n} -cleanup {\n    safe::interpDelete a\n} -result {ok {appname not accessible in a safe interpreter}}\ntest safe-2.4 {Unsafe subcommands not available} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status broken\n    if {[catch {interp eval a {tk scaling 1}} msg]} {\n\tset status ok\n    }\n    list $status $msg\n} -cleanup {\n    safe::interpDelete a\n} -result {ok {setting the scaling not accessible in a safe interpreter}}\n\ntest safe-3.1 {Unsafe commands are available hidden} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status ok\n    if {[catch {interp invokehidden a toplevel .t} msg]} {\n\tset status broken\n    }\n    return $status\n} -cleanup {\n    safe::interpDelete a\n} -result ok\ntest safe-3.2 {Unsafe commands are available hidden} -setup {\n    catch {safe::interpDelete a}\n} -body {\n    safe::interpCreate a\n    safe::loadTk a\n    set status ok\n    if {[catch {interp invokehidden a menu .m} msg]} {\n\tset status broken\n    }\n    return $status\n} -cleanup {\n    safe::interpDelete a\n} -result ok\n\ntest safe-4.1 {testing loadTk} -body {\n    # no error shall occur, the user will eventually see a new toplevel\n    set i [safe::loadTk [safe::interpCreate]]\n    interp eval $i {button .b -text \"hello world!\"; pack .b}\n    # lets don't update because it might imply that the user has to position\n    # the window (if the wm does not do it automatically) and thus make the\n    # test suite not runable non interactively\n    safe::interpDelete $i\n} -result {}\ntest safe-4.2 {testing loadTk -use} -setup {\n    destroy .safeTkFrame\n} -body {\n    set w .safeTkFrame\n    frame $w -container 1;\n    pack $w\n    set i [safe::loadTk [safe::interpCreate] -use [winfo id $w]]\n    interp eval $i {button .b -text \"hello world!\"; pack .b}\n    safe::interpDelete $i\n    destroy $w\n} -result {}\n\ntest safe-5.1 {loading Tk in safe interps without parent's clearance} -body {\n    set i [safe::interpCreate]\n    interp eval $i {load {} Tk}\n} -cleanup {\n    safe::interpDelete $i\n} -returnCodes error -match glob -result {*not allowed}\ntest safe-5.2 {multi-level Tk loading with clearance} -setup {\n    set safeParent [safe::interpCreate]\n} -body {\n    # No error shall occur in that test and no window shall remain at the end.\n    set i [safe::interpCreate [list $safeParent x]]\n    safe::loadTk $i\n    interp eval $i {\n\tbutton .b -text Ok -command {destroy .}\n\tpack .b\n#\ttkwait window . ; # for interactive testing/debugging\n    }\n} -cleanup {\n    catch {safe::interpDelete $i}\n    safe::interpDelete $safeParent\n} -result {}\n\ntest safe-6.1 {loadTk -use windowPath} -setup {\n    destroy .safeTkFrame\n} -body {\n    set w .safeTkFrame\n    frame $w -container 1;\n    pack $w\n    set i [safe::loadTk [safe::interpCreate] -use $w]\n    interp eval $i {button .b -text \"hello world!\"; pack .b}\n    safe::interpDelete $i\n    destroy $w\n} -result {}\ntest safe-6.2 {loadTk -use windowPath, conflicting -display} -setup {\n    destroy .safeTkFrame\n} -body {\n    set w .safeTkFrame\n    frame $w -container 1;\n    pack $w\n    set i     [safe::interpCreate]\n    catch {safe::loadTk $i -use $w -display :23.56} msg\n    string range $msg 0 36\n} -cleanup {\n    safe::interpDelete $i\n    destroy $w\n} -result {conflicting -display :23.56 and -use }\n\ntest safe-7.1 {canvas printing} -body {\n    set i [safe::loadTk [safe::interpCreate]]\n    interp eval $i {canvas .c; .c postscript}\n} -cleanup {\n    safe::interpDelete $i\n} -returnCodes ok -match glob -result *\n\n#\n# TESTFILE CLEANUP\n#\n\nset ::auto_path $saveAutoPath\nunset hidden_cmds\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# fill-column: 78\n# End:\n"
  },
  {
    "path": "tests/safePrimarySelection.test",
    "content": "# This file is a Tcl script to test that a Safe Base interpreter cannot write\n# to the PRIMARY selection.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# - Tests 3.*, 6.* test that the fix for ticket de156e9efe implemented in branch\n#   bug-de156e9efe has been applied and still works.  They test that a Safe Base\n#   child interpreter cannot write to the PRIMARY selection.\n# - The other tests verify that the parent interpreter and a child interpreter\n#   CAN write to the PRIMARY selection, and therefore that the test scripts\n#   themselves are valid.\n# - A text, entry, ttk::entry, listbox, spinbox or ttk::spinbox widget can have\n#   option -exportselection 1, meaning (in an unsafe interpreter) that a\n#   selection made in one of these widgets is automatically written to the\n#   PRIMARY selection.\n# - A safe interpreter must not write to the PRIMARY selection.\n# - The spinbox, ttk::spinbox are variants of entry, ttk::entry respectively.\n# - The command \"childTkInterp\" is not needed for Safe Base children because\n#   safe::loadTk does something similar and works correctly.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# COMMON TEST SETUP\n#\n\nnamespace eval ::_test_tmp {}\n\nset ::_test_tmp::script {\n    package require tk\n    namespace eval ::_test_tmp {}\n\n    proc ::_test_tmp::getPrimarySelection {} {\n\tif {[catch {::tk::GetSelection . PRIMARY} sel]} {\n\t    set sel {}\n\t}\n\treturn $sel\n    }\n\n    proc ::_test_tmp::setPrimarySelection {} {\n\tdestroy .preset\n\ttext .preset -exportselection 1\n\t.preset insert end OLD_VALUE\n\t# pack .preset\n\t.preset tag add sel 1.0 end-1c\n\tupdate\n\treturn\n    }\n\n    # Clearing the PRIMARY selection is troublesome.\n    # The window need not be mapped.\n    # However, the window must continue to exist, or some X11 servers\n    # will set the PRIMARY selection to something else.\n    proc ::_test_tmp::clearPrimarySelection {} {\n\tdestroy .clear\n\ttext .clear -exportselection 1\n\t.clear insert end TMP_VALUE\n\t# pack .clear\n\t.clear tag add sel 1.0 end-1c\n\tupdate\n\t.clear tag remove sel 1.0 end-1c\n\tupdate\n\treturn\n    }\n\n    # If this interpreter can write to the PRIMARY\n    # selection, the commands below will do so.\n\n    proc ::_test_tmp::tryText {} {\n\ttext .t -exportselection 1\n\t.t insert end PAYLOAD\n\tpack .t\n\t.t tag add sel 1.0 end-1c\n\tupdate\n\treturn\n    }\n\n    proc ::_test_tmp::tryEntry {} {\n\tentry .t -exportselection 1\n\t.t insert end PAYLOAD\n\tpack .t\n\t.t selection range 0 end\n\tupdate\n\treturn\n    }\n\n    proc ::_test_tmp::tryTtkEntry {} {\n\t::ttk::entry .t -exportselection 1\n\t.t insert end PAYLOAD\n\tpack .t\n\t.t selection range 0 end\n\tupdate\n\treturn\n    }\n\n    proc ::_test_tmp::tryListbox {} {\n\tlistbox .t -exportselection 1\n\t.t insert end list1 PAYLOAD list3\n\tpack .t\n\t.t selection set 1\n\tupdate\n\treturn\n    }\n\n    proc ::_test_tmp::trySpinbox {ver} {\n\tif {$ver == 1} {\n\t    # spinbox as entry\n\t    spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    .t delete 0 end\n\t    .t insert end PAYLOAD\n\t    pack .t\n\t    .t selection range 0 end\n\t    update\n\t    return\n\t    # selects PAYLOAD\n\t} elseif {$ver == 2} {\n\t    # spinbox spun\n\t    spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    .t invoke buttonup\n\t    pack .t\n\t    .t selection range 0 end\n\t    update\n\t    return\n\t    # selects 2\n\t} else {\n\t    # spinbox spun/selected/spun\n\t    spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    .t invoke buttonup\n\t    pack .t\n\t    .t selection range 0 end\n\t    update\n\t    .t invoke buttonup\n\t    update\n\t    return\n\t    # selects 3\n\t}\n    }\n\n    proc ::_test_tmp::tryTtkSpinbox {ver} {\n\tif {$ver == 1} {\n\t    # ttk::spinbox as entry\n\t    ::ttk::spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    .t delete 0 end\n\t    .t insert end PAYLOAD\n\t    pack .t\n\t    .t selection range 0 end\n\t    update\n\t    return\n\t} elseif {$ver == 2} {\n\t    # ttk::spinbox spun\n\t    ::ttk::spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    ::ttk::spinbox::Spin .t +1\n\t    ::ttk::spinbox::Spin .t +1\n\t    pack .t\n\t    # ttk::spinbox::Spin sets selection\n\t    update\n\t    return\n\t    # selects 2\n\t} else {\n\t    # ttk::spinbox spun/selected/spun\n\t    ::ttk::spinbox .t -exportselection 1 -values {1 2 3 4 5}\n\t    ::ttk::spinbox::Spin .t +1\n\t    ::ttk::spinbox::Spin .t +1\n\t    pack .t\n\t    # ttk::spinbox::Spin sets selection\n\t    update\n\t    ::ttk::spinbox::Spin .t +1\n\t    update\n\t    return\n\t    # selects 3\n\t}\n    }\n}\n\n# Do this once for the parent interpreter.\neval $::_test_tmp::script\n\n#\n# TESTS\n#\n\ntest safePrimarySelection-1.1 {parent interpreter, text, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryText\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.2 {parent interpreter, entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryEntry\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.3 {parent interpreter, ttk::entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkEntry\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.4 {parent interpreter, listbox, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryListbox\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.5 {parent interpreter, spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 1\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.6 {parent interpreter, spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 2\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-1.7 {parent interpreter, spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 3\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-1.8 {parent interpreter, ttk::spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 1\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-1.9 {parent interpreter, ttk::spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 2\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-1.10 {parent interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 3\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-2.1 {child interpreter, text, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryText\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.2 {child interpreter, entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryEntry\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.3 {child interpreter, ttk::entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkEntry\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.4 {child interpreter, listbox, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryListbox\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.5 {child interpreter, spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 1\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.6 {child interpreter, spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 2\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-2.7 {child interpreter, spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 3\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-2.8 {child interpreter, ttk::spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 1\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-2.9 {child interpreter, ttk::spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 2\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-2.10 {child interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 3\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-3.1 {IMPORTANT, safe interpreter, text, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryText\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.2 {IMPORTANT, safe interpreter, entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryEntry\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.3 {IMPORTANT, safe interpreter, ttk::entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkEntry\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.4 {IMPORTANT, safe interpreter, listbox, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryListbox\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.5 {IMPORTANT, safe interpreter, spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 1\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.6 {IMPORTANT, safe interpreter, spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 2\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.7 {IMPORTANT, safe interpreter, spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 3\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.8 {IMPORTANT, safe interpreter, ttk::spinbox as entry, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 1\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.9 {IMPORTANT, safe interpreter, ttk::spinbox spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 2\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-3.10 {IMPORTANT, safe interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 3\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {----}\n\ntest safePrimarySelection-4.1 {parent interpreter, text, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryText\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.2 {parent interpreter, entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryEntry\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.3 {parent interpreter, ttk::entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkEntry\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.4 {parent interpreter, listbox, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryListbox\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.5 {parent interpreter, spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 1\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.6 {parent interpreter, spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 2\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-4.7 {parent interpreter, spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::trySpinbox 3\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-4.8 {parent interpreter, ttk::spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 1\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-4.9 {parent interpreter, ttk::spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 2\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-4.10 {parent interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    ::_test_tmp::tryTtkSpinbox 3\n    ::_test_tmp::getPrimarySelection\n} -cleanup {\n    destroy {*}[winfo children .]\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-5.1 {child interpreter, text, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryText\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.2 {child interpreter, entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryEntry\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.3 {child interpreter, ttk::entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkEntry\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.4 {child interpreter, listbox, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryListbox\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.5 {child interpreter, spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 1\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.6 {child interpreter, spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 2\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-5.7 {child interpreter, spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 3\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-5.8 {child interpreter, ttk::spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 1\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result {PAYLOAD}\n\ntest safePrimarySelection-5.9 {child interpreter, ttk::spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 2\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 2\n\ntest safePrimarySelection-5.10 {child interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set int2 child2\n    childTkInterp $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 3\n    $int2 eval ::_test_tmp::getPrimarySelection\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2\n    ::_test_tmp::clearPrimarySelection\n} -result 3\n\ntest safePrimarySelection-6.1 {IMPORTANT, safe interpreter, text, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryText\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.2 {IMPORTANT, safe interpreter, entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryEntry\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.3 {IMPORTANT, safe interpreter, ttk::entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkEntry\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.4 {IMPORTANT, safe interpreter, listbox, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryListbox\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.5 {IMPORTANT, safe interpreter, spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 1\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.6 {IMPORTANT, safe interpreter, spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 2\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.7 {IMPORTANT, safe interpreter, spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::trySpinbox 3\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.8 {IMPORTANT, safe interpreter, ttk::spinbox as entry, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 1\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.9 {IMPORTANT, safe interpreter, ttk::spinbox spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 2\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\ntest safePrimarySelection-6.10 {IMPORTANT, safe interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {\n    catch {interp delete child2}\n    destroy {*}[winfo children .]\n    ::_test_tmp::setPrimarySelection\n} -body {\n    set res0 [::_test_tmp::getPrimarySelection]\n    set int2 child2\n    ::safe::interpCreate $int2\n    ::safe::loadTk $int2\n    $int2 eval $::_test_tmp::script\n    $int2 eval ::_test_tmp::tryTtkSpinbox 3\n    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]\n    set res2 [::_test_tmp::getPrimarySelection]\n    set res3 $res0--$res1--$res2\n} -cleanup {\n    interp delete $int2\n    destroy {*}[winfo children .]\n    unset int2 res0 res1 res2 res3\n    ::_test_tmp::clearPrimarySelection\n} -result {OLD_VALUE----OLD_VALUE}\n\n#\n# TESTFILE CLEANUP\n#\n\nnamespace delete ::_test_tmp\ntestutils forget child\ncleanupTests\n"
  },
  {
    "path": "tests/scale.test",
    "content": "# This file is a Tcl script to test out the \"scale\" command\n# of Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Create entries in the option database to be sure that geometry options\n# like border width have predictable values.\n\noption add *Scale.borderWidth 2\noption add *Scale.highlightThickness 2\noption add *Scale.font {Helvetica -12 bold}\n\n#\n# COMMON TEST SETUP\n#\n# For tests 1.*\n#\nscale .s -from 100 -to 300\npack .s\nupdate\n\n#\n# TESTS\n#\n\ntest scale-1.1 {configuration options} -body {\n    .s configure -activebackground #ff0000\n    .s cget -activebackground\n} -cleanup {\n    .s configure -activebackground [lindex [.s configure -activebackground] 3]\n} -result {#ff0000}\ntest scale-1.2 {configuration options} -body {\n\t.s configure -activebackground non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest scale-1.3 {configuration options} -body {\n    .s configure -background #ff0000\n    .s cget -background\n} -cleanup {\n    .s configure -background [lindex [.s configure -background] 3]\n} -result {#ff0000}\ntest scale-1.4 {configuration options} -body {\n\t.s configure -background non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest scale-1.5 {configuration options} -body {\n    .s configure -bd 4\n    .s cget -bd\n} -cleanup {\n    .s configure -bd [lindex [.s configure -bd] 3]\n} -result 4\ntest scale-1.6 {configuration options} -body {\n\t.s configure -bd badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest scale-1.7 {configuration options} -body {\n    .s configure -bigincrement 12.5\n    .s cget -bigincrement\n} -cleanup {\n    .s configure -bigincrement [lindex [.s configure -bigincrement] 3]\n} -result {12.5}\ntest scale-1.8 {configuration options} -body {\n\t.s configure -bigincrement badValue\n} -returnCodes error -result {expected floating-point number but got \"badValue\"}\ntest scale-1.9 {configuration options} -body {\n    .s configure -bg #ff0000\n    .s cget -bg\n} -cleanup {\n    .s configure -bg [lindex [.s configure -bg] 3]\n} -result {#ff0000}\ntest scale-1.10 {configuration options} -body {\n\t.s configure -bg non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest scale-1.11 {configuration options} -body {\n    .s configure -borderwidth 1.3\n    .s cget -borderwidth\n} -cleanup {\n    .s configure -borderwidth [lindex [.s configure -borderwidth] 3]\n} -result 1.3\ntest scale-1.12 {configuration options} -body {\n\t.s configure -borderwidth badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest scale-1.13 {configuration options} -body {\n    .s configure -command {set x}\n    .s cget -command\n} -cleanup {\n    .s configure -command [lindex [.s configure -command] 3]\n} -result {set x}\ntest scale-1.15 {configuration options} -body {\n    .s configure -cursor arrow\n    .s cget -cursor\n} -cleanup {\n    .s configure -cursor [lindex [.s configure -cursor] 3]\n} -result {arrow}\ntest scale-1.16 {configuration options} -body {\n\t.s configure -cursor badValue\n} -returnCodes error -result {bad cursor spec \"badValue\"}\ntest scale-1.17 {configuration options} -body {\n    .s configure -digits 5\n    .s cget -digits\n} -cleanup {\n    .s configure -digits [lindex [.s configure -digits] 3]\n} -result 5\ntest scale-1.18 {configuration options} -body {\n\t.s configure -digits badValue\n} -returnCodes error -result {expected integer but got \"badValue\"}\ntest scale-1.19 {configuration options} -body {\n    .s configure -fg #00ff00\n    .s cget -fg\n} -cleanup {\n    .s configure -fg [lindex [.s configure -fg] 3]\n} -result {#00ff00}\ntest scale-1.20 {configuration options} -body {\n\t.s configure -fg badValue\n} -returnCodes error -result {unknown color name \"badValue\"}\ntest scale-1.21 {configuration options} -body {\n    .s configure -font fixed\n    .s cget -font\n} -cleanup {\n    .s configure -font [lindex [.s configure -font] 3]\n} -result {fixed}\ntest scale-1.23 {configuration options} -body {\n    .s configure -foreground green\n    .s cget -foreground\n} -cleanup {\n    .s configure -foreground [lindex [.s configure -foreground] 3]\n} -result {green}\ntest scale-1.24 {configuration options} -body {\n\t.s configure -foreground badValue\n} -returnCodes error -result {unknown color name \"badValue\"}\ntest scale-1.25 {configuration options} -body {\n    .s configure -from -15.0\n    .s cget -from\n} -cleanup {\n    .s configure -from [lindex [.s configure -from] 3]\n} -result {-15.0}\ntest scale-1.26 {configuration options} -body {\n\t.s configure -from badValue\n} -returnCodes error -result {expected floating-point number but got \"badValue\"}\ntest scale-1.27 {configuration options} -body {\n    .s configure -highlightbackground #112233\n    .s cget -highlightbackground\n} -cleanup {\n    .s configure -highlightbackground [lindex [.s configure -highlightbackground] 3]\n} -result {#112233}\ntest scale-1.28 {configuration options} -body {\n\t.s configure -highlightbackground ugly\n} -returnCodes error -result {unknown color name \"ugly\"}\ntest scale-1.29 {configuration options} -body {\n    .s configure -highlightcolor #123456\n    .s cget -highlightcolor\n} -cleanup {\n    .s configure -highlightcolor [lindex [.s configure -highlightcolor] 3]\n} -result {#123456}\ntest scale-1.30 {configuration options} -body {\n\t.s configure -highlightcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest scale-1.31 {configuration options} -body {\n    .s configure -highlightthickness 2\n    .s cget -highlightthickness\n} -cleanup {\n    .s configure -highlightthickness [lindex [.s configure -highlightthickness] 3]\n} -result 2\ntest scale-1.32 {configuration options} -body {\n\t.s configure -highlightthickness badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest scale-1.33 {configuration options} -body {\n    .s configure -label {Some text}\n    .s cget -label\n} -cleanup {\n    .s configure -label [lindex [.s configure -label] 3]\n} -result {Some text}\ntest scale-1.35 {configuration options} -body {\n    .s configure -length 130\n    .s cget -length\n} -cleanup {\n    .s configure -length [lindex [.s configure -length] 3]\n} -result 130\ntest scale-1.36 {configuration options} -body {\n\t.s configure -length badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest scale-1.37 {configuration options} -body {\n    .s configure -orient horizontal\n    .s cget -orient\n} -cleanup {\n    .s configure -orient [lindex [.s configure -orient] 3]\n} -result {horizontal}\ntest scale-1.38 {configuration options} -body {\n\t.s configure -orient badValue\n} -returnCodes error -result {bad orient \"badValue\": must be horizontal or vertical}\ntest scale-1.39 {configuration options} -body {\n    .s configure -orient horizontal\n    .s cget -orient\n} -cleanup {\n    .s configure -orient [lindex [.s configure -orient] 3]\n} -result {horizontal}\ntest scale-1.41 {configuration options} -body {\n    .s configure -relief ridge\n    .s cget -relief\n} -cleanup {\n    .s configure -relief [lindex [.s configure -relief] 3]\n} -result {ridge}\ntest scale-1.42 {configuration options} -body {\n\t.s configure -relief badValue\n} -returnCodes error -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\ntest scale-1.43 {configuration options} -body {\n    .s configure -repeatdelay 14\n    .s cget -repeatdelay\n} -cleanup {\n    .s configure -repeatdelay [lindex [.s configure -repeatdelay] 3]\n} -result 14\ntest scale-1.44 {configuration options} -body {\n\t.s configure -repeatdelay bogus\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest scale-1.45 {configuration options} -body {\n    .s configure -repeatinterval 14\n    .s cget -repeatinterval\n} -cleanup {\n    .s configure -repeatinterval [lindex [.s configure -repeatinterval] 3]\n} -result 14\ntest scale-1.46 {configuration options} -body {\n\t.s configure -repeatinterval bogus\n} -returnCodes error -result {expected integer but got \"bogus\"}\ntest scale-1.47 {configuration options} -body {\n    .s configure -resolution 2.0\n    .s cget -resolution\n} -cleanup {\n    .s configure -resolution [lindex [.s configure -resolution] 3]\n} -result {2.0}\ntest scale-1.48 {configuration options} -body {\n\t.s configure -resolution badValue\n} -returnCodes error -result {expected floating-point number but got \"badValue\"}\ntest scale-1.49 {configuration options} -body {\n    .s configure -showvalue 0\n    .s cget -showvalue\n} -cleanup {\n    .s configure -showvalue [lindex [.s configure -showvalue] 3]\n} -result 0\ntest scale-1.50 {configuration options} -body {\n\t.s configure -showvalue badValue\n} -returnCodes error -result {expected boolean value but got \"badValue\"}\ntest scale-1.51 {configuration options} -body {\n    .s configure -sliderlength 86\n    .s cget -sliderlength\n} -cleanup {\n    .s configure -sliderlength [lindex [.s configure -sliderlength] 3]\n} -result 86\ntest scale-1.52 {configuration options} -body {\n\t.s configure -sliderlength badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\ntest scale-1.53 {configuration options} -body {\n    .s configure -sliderrelief raised\n    .s cget -sliderrelief\n} -cleanup {\n    .s configure -sliderrelief [lindex [.s configure -sliderrelief] 3]\n} -result {raised}\ntest scale-1.54 {configuration options} -body {\n\t.s configure -sliderrelief badValue\n} -returnCodes error -result {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}\ntest scale-1.55 {configuration options} -body {\n    .s configure -state d\n    .s cget -state\n} -cleanup {\n    .s configure -state [lindex [.s configure -state] 3]\n} -result {disabled}\ntest scale-1.56 {configuration options} -body {\n\t.s configure -state badValue\n} -returnCodes error -result {bad state \"badValue\": must be active, disabled, or normal}\ntest scale-1.57 {configuration options} -body {\n    .s configure -state n\n    .s cget -state\n} -cleanup {\n    .s configure -state [lindex [.s configure -state] 3]\n} -result {normal}\ntest scale-1.59 {configuration options} -body {\n    .s configure -takefocus {any string}\n    .s cget -takefocus\n} -cleanup {\n    .s configure -takefocus [lindex [.s configure -takefocus] 3]\n} -result {any string}\ntest scale-1.61 {configuration options} -body {\n    .s configure -tickinterval 4.3\n    .s cget -tickinterval\n} -cleanup {\n    .s configure -tickinterval [lindex [.s configure -tickinterval] 3]\n} -result {4.0}\ntest scale-1.62 {configuration options} -body {\n\t.s configure -tickinterval badValue\n} -returnCodes error -result {expected floating-point number but got \"badValue\"}\ntest scale-1.63 {configuration options} -body {\n    .s configure -to 14.9\n    .s cget -to\n} -cleanup {\n    .s configure -to [lindex [.s configure -to] 3]\n} -result {15.0}\ntest scale-1.64 {configuration options} -body {\n\t.s configure -to badValue\n} -returnCodes error -result {expected floating-point number but got \"badValue\"}\ntest scale-1.65 {configuration options} -body {\n    .s configure -troughcolor #ff0000\n    .s cget -troughcolor\n} -cleanup {\n    .s configure -troughcolor [lindex [.s configure -troughcolor] 3]\n} -result {#ff0000}\ntest scale-1.66 {configuration options} -body {\n\t.s configure -troughcolor non-existent\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest scale-1.67 {configuration options} -body {\n    .s configure -variable x\n    .s cget -variable\n} -cleanup {\n    .s configure -variable [lindex [.s configure -variable] 3]\n} -result {x}\ntest scale-1.69 {configuration options} -body {\n    .s configure -width 32\n    .s cget -width\n} -cleanup {\n    .s configure -width [lindex [.s configure -width] 3]\n} -result 32\ntest scale-1.70 {configuration options} -body {\n\t.s configure -width badValue\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scale-2.1 {Tk_ScaleCmd procedure} -body {\n    scale\n} -returnCodes error -result {wrong # args: should be \"scale pathName ?-option value ...?\"}\ntest scale-2.2 {Tk_ScaleCmd procedure} -body {\n    scale foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest scale-2.3 {Tk_ScaleCmd procedure} -body {\n    catch {scale foo}\n    winfo children .\n} -result {}\ntest scale-2.4 {Tk_ScaleCmd procedure} -body {\n    scale .s -gorp dumb\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest scale-2.5 {Tk_ScaleCmd procedure} -body {\n    catch {scale .s -gorp dumb}\n    winfo children .\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n# For tests 3.*\n#\ndestroy .s\nscale .s -from 100 -to 200\npack .s\nupdate idletasks\n\ntest scale-3.1 {ScaleWidgetCmd procedure} -body {\n    .s\n} -returnCodes error -result {wrong # args: should be \".s option ?arg ...?\"}\ntest scale-3.2 {ScaleWidgetCmd procedure, cget option} -body {\n    .s cget\n} -returnCodes error -result {wrong # args: should be \".s cget option\"}\ntest scale-3.3 {ScaleWidgetCmd procedure, cget option} -body {\n    .s cget a b\n} -returnCodes error -result {wrong # args: should be \".s cget option\"}\ntest scale-3.4 {ScaleWidgetCmd procedure, cget option} -body {\n    .s cget -gorp\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest scale-3.5 {ScaleWidgetCmd procedure, cget option} -body {\n    .s configure -highlightthickness 2\n    .s cget -highlightthickness\n} -result 2\ntest scale-3.6 {ScaleWidgetCmd procedure, configure option} -body {\n    list [llength [.s configure]] [lindex [.s configure] 6]\n} -result {33 {-command command Command {} {}}}\ntest scale-3.7 {ScaleWidgetCmd procedure, configure option} -body {\n    .s configure -foo\n} -returnCodes error -result {unknown option \"-foo\"}\ntest scale-3.8 {ScaleWidgetCmd procedure, configure option} -body {\n    .s configure -borderwidth 2 -bg\n} -returnCodes error -result {value for \"-bg\" missing}\ntest scale-3.9 {ScaleWidgetCmd procedure, coords option} -body {\n    .s coords a b\n} -returnCodes error -result {wrong # args: should be \".s coords ?value?\"}\ntest scale-3.10 {ScaleWidgetCmd procedure, coords option} -body {\n    .s coords bad\n} -returnCodes error -result {expected floating-point number but got \"bad\"}\ntest scale-3.11 {ScaleWidgetCmd procedure} -constraints {\n\tfonts\n} -body {\n    .s configure -from 100 -to 200\n    update idletasks\n    .s set 120\n    .s coords\n} -result {38 34}\ntest scale-3.12 {ScaleWidgetCmd procedure, coords option} -constraints {\n\tfonts\n} -body {\n    .s configure -from 100 -to 200 -orient horizontal\n    update idletasks\n    .s set 120\n    .s coords\n} -result {34 31}\ntest scale-3.13 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical\n    update\n    .s get a\n} -returnCodes error -result {wrong # args: should be \".s get ?x y?\"}\ntest scale-3.14 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical\n    update\n    .s get a b c\n} -returnCodes error -result {wrong # args: should be \".s get ?x y?\"}\ntest scale-3.15 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical\n    update\n    .s get a 11\n} -returnCodes error -result {expected integer but got \"a\"}\ntest scale-3.16 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical\n    update\n    .s get 12 b\n} -returnCodes error -result {expected integer but got \"b\"}\ntest scale-3.17 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical\n    update\n    .s set 133\n    .s get\n} -result 133\ntest scale-3.18 {ScaleWidgetCmd procedure, get option} -body {\n    .s configure -orient vertical -resolution 0.5\n    update\n    .s set 150\n    .s get 37 34\n} -result {119.5}\n\n#\n# COMMON TEST SETUP\n#\n# For tests from scale-3.19\n#\n.s configure -resolution 1\n\ntest scale-3.19 {ScaleWidgetCmd procedure, identify option} -body {\n    .s identify\n} -returnCodes error -result {wrong # args: should be \".s identify x y\"}\ntest scale-3.20 {ScaleWidgetCmd procedure, identify option} -body {\n    .s identify 1 2 3\n} -returnCodes error -result {wrong # args: should be \".s identify x y\"}\ntest scale-3.21 {ScaleWidgetCmd procedure, identify option} -body {\n    .s identify boo 16\n} -returnCodes error -result {expected integer but got \"boo\"}\ntest scale-3.22 {ScaleWidgetCmd procedure, identify option} -body {\n    .s identify 17 bad\n} -returnCodes error -result {expected integer but got \"bad\"}\ntest scale-3.23 {ScaleWidgetCmd procedure, identify option} -constraints {\n\tfonts\n} -body {\n    .s configure -from 100 -to 200 -orient vertical -resolution 1\n    update\n    .s set 120\n    list [.s identify 35 10] [.s identify 35 30] [.s identify 35 80] [.s identify 5 80]\n} -result {trough1 slider trough2 {}}\ntest scale-3.24 {ScaleWidgetCmd procedure, set option} -body {\n    .s set\n} -returnCodes error -result {wrong # args: should be \".s set value\"}\ntest scale-3.25 {ScaleWidgetCmd procedure, set option} -body {\n    .s set a b\n} -returnCodes error -result {wrong # args: should be \".s set value\"}\ntest scale-3.26 {ScaleWidgetCmd procedure, set option} -body {\n    .s set bad\n} -returnCodes error -result {expected floating-point number but got \"bad\"}\ntest scale-3.27 {ScaleWidgetCmd procedure, set option} -body {\n    .s configure -from 100 -to 200 -orient vertical -resolution 0.5\n    update\n    .s set 142\n} -result {}\ntest scale-3.28 {ScaleWidgetCmd procedure, set option} -body {\n    .s configure -from 100 -to 200 -orient vertical -resolution 1\n    update\n    .s set 118\n    .s configure -state disabled\n    .s set 181\n    .s configure -state normal\n    .s get\n} -result 118\ntest scale-3.29 {ScaleWidgetCmd procedure} -body {\n    .s dumb\n} -returnCodes error -result {bad option \"dumb\": must be cget, configure, coords, get, identify, or set}\ntest scale-3.30 {ScaleWidgetCmd procedure} -body {\n    .s c\n} -returnCodes error -result {ambiguous option \"c\": must be cget, configure, coords, get, identify, or set}\ntest scale-3.31 {ScaleWidgetCmd procedure} -body {\n    .s co\n} -returnCodes error -result {ambiguous option \"co\": must be cget, configure, coords, get, identify, or set}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scale-3.32 {ScaleWidgetCmd procedure, Tk_Preserve} -setup {\n    destroy .s\n} -body {\n    proc kill args {\n\t    destroy .s\n    }\n    scale .s -variable x -from 0 -to 100 -orient horizontal\n    pack .s\n    update\n    .s configure -command kill\n    .s set 55\n} -cleanup {\n    destroy .s\n} -result {}\n\n\ntest scale-4.1 {DestroyScale procedure} -setup {\n    deleteWindows\n} -body {\n    set x 50\n    scale .s -variable x -from 0 -to 100 -orient horizontal\n    pack .s\n    update\n    destroy .s\n    list [catch {set x foo} msg] $msg $x\n} -result {0 foo foo}\n\n\ntest scale-5.1 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    set x 66\n    set y 77\n    scale .s -variable x -from 0 -to 100\n    pack .s\n    update\n    .s configure -variable y\n    list [catch {set x foo} msg] $msg $x [.s get]\n} -cleanup {\n    deleteWindows\n} -result {0 foo foo 77}\ntest scale-5.2 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100\n    .s configure -foo bar\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-foo\"}\ntest scale-5.3 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    catch {unset x}\n    scale .s -from 0 -to 100 -variable x\n    set result $x\n    lappend result [.s get]\n    set x 92\n    lappend result [.s get]\n    .s set 3\n    lappend result $x\n    unset x\n    lappend result [set x]\n} -cleanup {\n    deleteWindows\n} -result {0 0 92 3 3}\ntest scale-5.4 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100\n    .s configure -orient dumb\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad orient \"dumb\": must be horizontal or vertical}\ntest scale-5.5 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 1.11 -to 1.89 -resolution .1 -tickinterval .76\n    list [format %.1f [.s cget -from]] [format %.1f [.s cget -to]] \\\n\t[format %.1f [.s cget -tickinterval]]\n} -cleanup {\n    deleteWindows\n} -result {1.1 1.9 0.8}\ntest scale-5.6 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 1 -to 10 -tickinterval -2\n    pack .s\n    set result [lindex [.s configure -tickinterval] 4]\n    .s configure -from 10 -to 1 -tickinterval 2\n    lappend result [lindex [.s configure -tickinterval] 4]\n} -cleanup {\n    deleteWindows\n} -result {2.0 -2.0}\ntest scale-5.7 {ConfigureScale procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -state bogus\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad state \"bogus\": must be active, disabled, or normal}\n\n#\n# COMMON TEST SETUP\n#\n# For tests scale-6.*\n#\n\ndestroy .s\nscale .s -orient horizontal -length 200\npack .s\n\ntest scale-6.1 {ComputeFormat procedure} -body {\n    .s configure -from 10 -to 100 -resolution 10\n    .s set 49.3\n    .s get\n} -result 50\ntest scale-6.2 {ComputeFormat procedure} -body {\n    .s configure -from 100 -to 1000 -resolution 100\n    .s set 493\n    .s get\n} -result 500\ntest scale-6.3 {ComputeFormat procedure} -body {\n    .s configure -from 1000 -to 10000 -resolution 1000\n    .s set 4930\n    .s get\n} -result 5000\ntest scale-6.4 {ComputeFormat procedure} -body {\n    .s configure -from 10000 -to 100000 -resolution 10000\n    .s set 49000\n    .s get\n} -result 50000\ntest scale-6.5 {ComputeFormat procedure} -body {\n    .s configure -from 100000 -to 1000000 -resolution 100000\n    .s set 493000\n    .s get\n} -result 500000\ntest scale-6.6 {ComputeFormat procedure} -constraints {\n\tnonPortable\n} -body {\n    # This test is non-portable because some platforms format the\n    # result as 5e+06.\n    .s configure -from 1000000 -to 10000000 -resolution 1000000\n    .s set 4930000\n    .s get\n} -result 5000000\ntest scale-6.7 {ComputeFormat procedure} -body {\n    .s configure -from 1000000000 -to 10000000000 -resolution 1000000000\n    .s set 4930000000\n    expr {[.s get] == 5.0e+09}\n} -result 1\ntest scale-6.8 {ComputeFormat procedure} -body {\n    .s configure -from .1 -to 1 -resolution .1\n    .s set .6\n    .s get\n} -result {0.6}\ntest scale-6.9 {ComputeFormat procedure} -body {\n    .s configure -from .01 -to .1 -resolution .01\n    .s set .06\n    .s get\n} -result {0.06}\ntest scale-6.10 {ComputeFormat procedure} -body {\n    .s configure -from .001 -to .01 -resolution .001\n    .s set .006\n    .s get\n} -result {0.006}\ntest scale-6.11 {ComputeFormat procedure} -body {\n    .s configure -from .0001 -to .001 -resolution .0001\n    .s set .0006\n    .s get\n} -result {0.0006}\ntest scale-6.12 {ComputeFormat procedure} -body {\n    .s configure -from .00001 -to .0001 -resolution .00001\n    .s set .00006\n    .s get\n} -result {0.00006}\ntest scale-6.13 {ComputeFormat procedure} -body {\n    .s configure -from .000001 -to .00001 -resolution .000001\n    .s set .000006\n    expr {[.s get] == 6.0e-06}\n} -result 1\ntest scale-6.14 {ComputeFormat procedure} -body {\n    .s configure -to .00001 -from .0001 -resolution .00001\n    .s set .00006\n    .s get\n} -result {0.00006}\ntest scale-6.15 {ComputeFormat procedure} -body {\n    .s configure -to .000001 -from .00001 -resolution .000001\n    .s set .000006\n    expr {[.s get] == 6.0e-06}\n} -result 1\ntest scale-6.16 {ComputeFormat procedure} -body {\n    .s configure -from .00001 -to .0001 -resolution .00001 -digits 1\n    .s set .00006\n    expr {[.s get] == 6e-05}\n} -result 1\ntest scale-6.17 {ComputeFormat procedure} -body {\n    .s configure -from 10000000 -to 100000000 -resolution 10000000 -digits 3\n    .s set 49300000\n    .s get\n} -result 50000000\ntest scale-6.18 {ComputeFormat procedure} -body {\n    .s configure -length 200 -from 0 -to 10 -resolution 0 -digits 0\n    .s set .111111111\n    .s get\n} -result {0.11}\ntest scale-6.19 {ComputeFormat procedure} -body {\n    .s configure -length 200 -from 1000 -to 1002 -resolution 0 -digits 0\n    .s set 1001.23456789\n    .s get\n} -result {1001.23}\ntest scale-6.20 {ComputeFormat procedure} -body {\n    .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 0\n    .s set 1001.23456789\n    .s get\n} -result {1001.235}\ntest scale-6.21 {ComputeFormat procedure} -body {\n    .s configure -length 200 -from 1000 -to 1001.8 -resolution 0 -digits 200\n    .s set 1001.23456789\n    .s get\n} -result {1001.235}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scale-7.1 {ComputeScaleGeometry procedure} -constraints {\n    nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 10 -label \"Short\" -orient vertical -length 5i\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {88 458}\ntest scale-7.2 {ComputeScaleGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -label \"Long string\" -orient vertical -tick 200\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {168 108}\ntest scale-7.3 {ComputeScaleGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -orient vertical -showvalue 0 -width 10 \\\n\t-sliderlength 10\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {22 108}\ntest scale-7.4 {ComputeScaleGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -orient vertical -showvalue 0 -bd 5 \\\n\t-relief sunken\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {39 114}\ntest scale-7.5 {ComputeScaleGeometry procedure} -constraints {\n    nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 10 -label \"Short\" -orient horizontal -length 5i\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {458 61}\ntest scale-7.6 {ComputeScaleGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -label \"Long string\" -orient horizontal \\\n\t-tick 500\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {108 79}\ntest scale-7.7 {ComputeScaleGeometry procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -orient horizontal -showvalue 0\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {108 27}\ntest scale-7.8 {ComputeScaleGeometry procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 1000 -orient horizontal -showvalue 0 -bd 5 \\\n\t-relief raised -highlightthickness 2\n    pack .s\n    update\n    list [winfo reqwidth .s] [winfo reqheight .s]\n} -cleanup {\n    deleteWindows\n} -result {114 39}\n\n\ntest scale-8.1 {ScaleElement procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient vertical -bd 1 -tick 20 -length 300\n    pack .s\n    .s set 30\n    update\n    list [.s identify 53 52] [.s identify 54 52] [.s identify 70 52] \\\n\t[.s identify 71 52]\n} -cleanup {\n    deleteWindows\n} -result {{} trough1 trough1 {}}\ntest scale-8.2 {ScaleElement procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient vertical -bd 1 -tick 20 -length 300\n    pack .s\n    .s set 30\n    update\n    list [.s identify 60 2] [.s identify 60 3] [.s identify 60 302] \\\n\t[.s identify 60 303]\n} -cleanup {\n    deleteWindows\n} -result {{} trough1 trough2 {}}\ntest scale-8.3 {ScaleElement procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient vertical -bd 1 -tick 20 -length 300\n    pack .s\n    .s set 30\n    update\n    list [.s identify 60 83] [.s identify 60 84] [.s identify 60 113] \\\n\t[.s identify 60 114] \\\n} -cleanup {\n    deleteWindows\n} -result {trough1 slider slider trough2}\ntest scale-8.4 {ScaleElement procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient vertical -bd 4 -width 10 \\\n\t-highlightthickness 1 -length 300 -showvalue 0\n    pack .s\n    .s set 30\n    update\n    list [.s identify 4 40] [.s identify 5 40] [.s identify 22 40] \\\n\t[.s identify 23 40] \\\n} -cleanup {\n    deleteWindows\n} -result {{} trough1 trough1 {}}\ntest scale-8.5 {ScaleElement procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient horizontal -bd 1 \\\n\t-highlightthickness 2 -tick 20 -sliderlength 20 \\\n\t-length 200 -label Test\n    pack .s\n    .s set 30\n    update\n    list [.s identify 150 36] [.s identify 150 37] [.s identify 150 53] \\\n\t[.s identify 150 54]\n} -cleanup {\n    deleteWindows\n} -result {{} trough2 trough2 {}}\ntest scale-8.6 {ScaleElement procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient horizontal -bd 2 \\\n\t-highlightthickness 1 -tick 20 -length 200\n    pack .s\n    .s set 30\n    update\n    list [.s identify 150 20] [.s identify 150 21] [.s identify 150 39] \\\n\t[.s identify 150 40]\n} -cleanup {\n    deleteWindows\n} -result {{} trough2 trough2 {}}\ntest scale-8.7 {ScaleElement procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient horizontal -bd 4 -highlightthickness 2 \\\n\t-length 200 -width 10 -showvalue 0\n    pack .s\n    .s set 30\n    update\n    list [.s identify 30 5] [.s identify 30 6] [.s identify 30 23] \\\n\t[.s identify 30 24]\n} -cleanup {\n    deleteWindows\n} -result {{} trough1 trough1 {}}\ntest scale-8.8 {ScaleElement procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient horizontal -bd 1 -highlightthickness 2 \\\n\t-tick 20 -sliderlength 20 -length 200 -label Test -showvalue 0\n    pack .s\n    .s set 30\n    update\n    list [.s identify 2 28] [.s identify 3 28] [.s identify 202 28] \\\n\t[.s identify 203 28]\n} -cleanup {\n    deleteWindows\n} -result {{} trough1 trough2 {}}\ntest scale-8.9 {ScaleElement procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -orient horizontal -bd 1 -highlightthickness 2 \\\n\t-tick 20 -sliderlength 20 -length 200 -label Test -showvalue 0\n    pack .s\n    .s set 80\n    update\n    list [.s identify 145 28] [.s identify 146 28] [.s identify 165 28] \\\n\t[.s identify 166 28]\n} -cleanup {\n    deleteWindows\n} -result {trough1 slider slider trough2}\n\n#\n# COMMON TEST SETUP\n#\n# For tests scale-9.*\n#\n\ndestroy .s\npack [scale .s]\n\ntest scale-9.1 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get 46 0\n} -result 0\ntest scale-9.2 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 9\n} -result 0\ntest scale-9.3 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 12\n} -result 1\ntest scale-9.4 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 46\n} -result 35\ntest scale-9.5 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 110\n} -result 99\ntest scale-9.6 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 111\n} -result 100\ntest scale-9.7 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 112\n} -result 100\ntest scale-9.8 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2\n    update\n    .s get -10 154\n} -result 100\ntest scale-9.9 {PixelToValue procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal\n    update\n    .s get 76 152\n} -result 65\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scale-10.1 {ValueToPixel procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 0 -to 100 -sliderlength 20 -length 124 -bd 2 \\\n\t-orient horizontal -label Test -tick 20\n    pack .s\n    update\n    list [.s coords -10] [.s coords 40] [.s coords 1000]\n} -cleanup {\n    deleteWindows\n} -result {{16 47} {56 47} {116 47}}\ntest scale-10.2 {ValueToPixel procedure} -constraints {\n    fonts\n} -setup {\n    deleteWindows\n} -body {\n    scale .s -from 100 -to 0 -sliderlength 20 -length 122 -bd 1 \\\n\t-orient vertical -label Test -tick 20\n    pack .s\n    update\n    list [.s coords -10] [.s coords 40] [.s coords 1000]\n} -cleanup {\n    deleteWindows\n} -result {{62 114} {62 74} {62 14}}\n\n\ntest scale-11.1 {ScaleEventProc procedure} -setup {\n    deleteWindows\n} -body {\n    proc killScale value {\n\tglobal x\n\tif {$value > 30} {\n\t    destroy .s1\n\t    lappend x [winfo exists .s1] [info commands .s1]\n\t}\n    }\n    set x initial\n    scale .s1 -from 0 -to 100 -command killScale\n    .s1 set 20\n    pack .s1\n    update idletasks\n    lappend x [winfo exists .s1]\n    .s1 set 40\n    update idletasks\n    return $x\n} -cleanup {\n    rename killScale {}\n    deleteWindows\n} -result {initial 1 0 {}}\ntest scale-11.2 {ScaleEventProc procedure} -setup {\n    deleteWindows\n    set x {}\n} -body {\n    scale .s1 -bg #543210\n    rename .s1 .s2\n    lappend x [winfo children .]\n    lappend x [.s2 cget -bg]\n    destroy .s1\n    lappend x [info command .s*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {.s1 #543210 {} {}}\n\ntest scale-12.1 {ScaleCmdDeletedProc procedure} -setup {\n    deleteWindows\n} -body {\n    scale .s1\n    rename .s1 {}\n    list [info command .s*] [winfo children .]\n} -cleanup {\n    deleteWindows\n} -result {{} {}}\n\n#\n# COMMON TEST SETUP\n#\n# For tests scale-13.*\n#\ndestroy .s\npack [scale .s]\nupdate\n\ntest scale-13.1 {SetScaleValue procedure} -body {\n    .s configure -from 0 -to 100 -command {set x} -variable y\n    update\n    set x xyzzy\n    .s set 44\n    set result [list $x $y]\n    update\n    lappend result $x $y\n} -result {xyzzy 44 44 44}\ntest scale-13.2 {SetScaleValue procedure} -body {\n    .s set -3\n    .s get\n} -result 0\ntest scale-13.3 {SetScaleValue procedure} -body {\n    .s set 105\n    .s get\n} -result 100\n\n#\n# COMMON TEST SETUP\n#\n# For tests scale-13.4 -\n#\n.s configure -from 100 -to 0\n\ntest scale-13.4 {SetScaleValue procedure} -body {\n    .s set -3\n    .s get\n} -result 0\ntest scale-13.5 {SetScaleValue procedure} -body {\n    .s set 105\n    .s get\n} -result 100\ntest scale-13.6 {SetScaleValue procedure} -body {\n    proc varTrace args {\n\tglobal traceInfo\n\tset traceInfo $args\n    }\n    .s configure -from 0 -to 100 -command {set x} -variable y\n    update\n\n    .s set 50\n    update\n    trace add variable y write varTrace\n    set traceInfo empty\n    set x untouched\n    .s set 50\n    update\n    list $x $traceInfo\n} -result {untouched empty}\n\n#\n# COMMON TEST SETUP\n#\n# For tests from scale-14.1\n#\ndestroy .s\npack [scale .s]\nupdate\n\ntest scale-14.1 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 84 152\n} -result 72\ntest scale-14.2 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 86 152\n} -result 76\n\ntest scale-14.3 {RoundValueToResolution procedure} -body {\n    .s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 84 152\n} -result 28\ntest scale-14.4 {RoundValueToResolution procedure} -body {\n    .s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 86 152\n} -result 24\n\ntest scale-14.5 {RoundValueToResolution procedure} -body {\n    .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 84 152\n} -result -28\ntest scale-14.6 {RoundValueToResolution procedure} -body {\n    .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 86 152\n} -result -24\n\ntest scale-14.7 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 84 152\n} -result -72\ntest scale-14.8 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 4.0\n    update\n    .s get 86 152\n} -result -76\n\ntest scale-14.9 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 2.25  -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 0\n    update\n    .s get 84 152\n} -result {1.64}\ntest scale-14.10 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 2.25  -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 0\n    update\n    .s get 86 152\n} -result {1.69}\n\ntest scale-14.11 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 0 -digits 5\n    update\n    .s get 84 152\n} -result {164.25}\ntest scale-14.12 {RoundValueToResolution procedure} -body {\n    .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \\\n\t-orient horizontal -resolution 0 -digits 5\n    update\n    .s get 86 152\n} -result {168.75}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scale-14.13 {RoundValueToResolution procedure, round-off errors} -setup {\n    # see [220665ffff], and duplicates [220265ffff] and [779559ffff]\n    set x NotSet\n    pack [scale .s -orient horizontal -resolution .1 -from -180 -to 180 -command \"set x\"]\n    update\n} -body {\n    .s configure -background red\n    update\n    set x\n} -cleanup {\n    destroy .s\n} -result {NotSet}\n\ntest scale-14a.1 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {\n    pack [scale .s -orient horizontal]\n    update\n} -body {\n    .s configure -length 400 -bd 0 -from 1 -to 9 -resolution 2 -tickinterval 1\n    update\n    .s get 200 0\n} -cleanup {\n    destroy .s\n} -result 5\ntest scale-14a.2 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {\n    pack [scale .s -orient horizontal]\n    update\n} -body {\n    .s configure -length 400 -bd 0 -from -1.5 -to 1.5 -resolution 1 \\\n\t    -tickinterval 1 -digits 2\n    update\n    .s get 250 0\n} -cleanup {\n    destroy .s\n} -result {0.5}\n\n\ntest scale-15.1 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y -130\n    scale .s -from 0 -to -200 -variable y -orient horizontal -length 150\n    pack .s\n    return $y\n} -result -130\ntest scale-15.2 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y -130\n    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150\n    pack .s\n    set y -87\n    .s get\n} -result -87\ntest scale-15.3 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y -130\n    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150\n    pack .s\n    set y 40q\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {can't set \"y\": cannot assign a non-numeric value to a scale variable}\ntest scale-15.4 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y -130\n    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150\n    pack .s\n    catch {set y 40q}\n    .s get\n} -cleanup {\n    deleteWindows\n} -result -130\ntest scale-15.5 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y 1\n    scale .s -from 1 -to 0 -variable y -orient horizontal -length 150\n    pack .s\n    set y x\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {can't set \"y\": cannot assign a non-numeric value to a scale variable}\ntest scale-15.6 {ScaleVarProc procedure} -setup {\n    deleteWindows\n} -body {\n    set y 1\n    scale .s -from 1 -to 0 -variable y -orient horizontal -length 150\n    pack .s\n    catch {set y x}\n    .s get\n} -cleanup {\n    deleteWindows\n} -result 1\ntest scale-15.7 {ScaleVarProc procedure, variable deleted} -setup {\n    deleteWindows\n} -body {\n    set y 6\n    scale .s -from 10 -to 0 -variable y -orient horizontal -length 150 \\\n\t-command \"set x\"\n    pack .s\n    update\n    set x untouched\n    unset y\n    update\n    list [catch {set y} msg] $msg [.s get] $x\n} -cleanup {\n    deleteWindows\n} -result {0 6 6 untouched}\ntest scale-15.8 {ScaleVarProc procedure, don't call -command} -setup {\n    deleteWindows\n} -body {\n    set y 6\n    scale .s -from 0 -to 100 -variable y -orient horizontal -length 150 \\\n\t-command \"set x\"\n    pack .s\n    update\n    set x untouched\n    set y 60\n    update\n    list $x [.s get]\n} -cleanup {\n    deleteWindows\n} -result {untouched 60}\n\n\ntest scale-16.1 {scale widget vs hidden commands} -body {\n    set l [interp hidden]\n    deleteWindows\n    scale .s\n    interp hide {} .s\n    destroy .s\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 eq $res2}\n} -cleanup {\n    deleteWindows\n} -result 1\n\n\ntest scale-17.1 {bug fix 1786} -setup {\n    deleteWindows\n} -body {\n    # Perhaps x is set to {}, depending on what other tests have run.\n    # If x is unset, or set to something not convertable to a double,\n    # then the scale try to initialize its value with the contents\n    # of uninitialized memory.  Sometimes that causes an FPE.\n\n    set x {}\n    scale .s -from 100 -to 300\n    pack .s\n    update\n    .s configure -variable x   ;# CRASH! -> Floating point exception\n\n    # Bug 4833 changed the result to realize that x should pick up\n    # a value from the scale.  In an FPE occurs, it is due to the\n    # lack of errno being set to 0 by some libc's. (see bug 4942)\n    return $x\n} -cleanup {\n    deleteWindows\n} -result 100\n\n\ntest scale-18.1 {DestroyScale, -cursor option [Bug: 3897]} -setup {\n    deleteWindows\n} -body {\n    scale .s -cursor trek\n    destroy .s\n} -result {}\n\ntest scale-18.2 {Scale button 1 events [Bug 787065]} -setup {\n    destroy .s\n    set ::error {}\n    proc bgerror {args} {set ::error $args}\n} -body {\n    set y 5\n    scale .s -from 0 -to 10 -variable y -orient horizontal -length 150\n    pack .s\n    tkwait visibility .s\n    list [catch {\n\tevent generate .s <Button-1> -x 0 -y 0\n\tevent generate .s <ButtonRelease-1> -x 0 -y 0\n\tupdate\n\tset ::error\n    } msg] $msg\n} -cleanup {\n    unset ::error\n    rename bgerror {}\n    destroy .s\n} -result {0 {}}\n\ntest scale-18.3 {Scale button 2 events [Bug 787065]} -setup {\n    destroy .s\n    set ::error {}\n    proc bgerror {args} {set ::error $args}\n} -body {\n    set y 5\n    scale .s -from 0 -to 10 -variable y -orient horizontal -length 150\n    pack .s\n    tkwait visibility .s\n    list [catch {\n\tevent generate .s <Button-2> -x 0 -y 0\n\tevent generate .s <ButtonRelease-2> -x 0 -y 0\n\tupdate\n\tset ::error\n    } msg] $msg\n} -cleanup {\n    unset ::error\n    rename bgerror {}\n    destroy .s\n} -result {0 {}}\n\ntest scale-18.4 {Bug [415415ffff] - Long callback: One click -> Several steps} -setup {\n    catch {destroy .s}\n    scale .s -from 0 -to 5 -resolution 1 -variable x1 -orient horizontal -length 100 \\\n\t    -command longCmd -repeatdelay 300\n    pack .s\n    update\n    proc longCmd {unused} {\n      after 500  ; # larger than -repeatdelay\n    }\n} -body {\n    foreach {x y} [.s coord 50] {}\n    event generate .s <Button-1> -x $x -y $y\n    update\n    event generate .s <ButtonRelease-1> -x $x -y $y\n    update\n    set x1\n} -cleanup {\n    destroy .s\n} -result {1}\n\ntest scale-19 {Bug [3529885fff] - Click in through goes in wrong direction} \\\n    -setup {\n\tcatch {destroy .s}\n\tcatch {destroy .s1 .s2 .s3 .s4}\n\tunset -nocomplain x1 x2 x3 x4 x y\n\tscale .s1 -from 0 -to 100 -resolution 1  -variable x1 -digits 4 -orient horizontal -length 100\n\tscale .s2 -from 0 -to 100 -resolution -1 -variable x2 -digits 4 -orient horizontal -length 100\n\tscale .s3 -from 100 -to 0 -resolution 1  -variable x3 -digits 4 -orient horizontal -length 100\n\tscale .s4 -from 100 -to 0 -resolution -1 -variable x4 -digits 4 -orient horizontal -length 100\n\tpack .s1 .s2 .s3 .s4 -side left\n\tupdate\n    } \\\n    -body {\n\tforeach {x y} [.s1 coord 50] {}\n\tevent generate .s1 <Button-1> -x $x -y $y\n\tevent generate .s1 <ButtonRelease-1> -x $x -y $y\n\tforeach {x y} [.s2 coord 50] {}\n\tevent generate .s2 <Button-1> -x $x -y $y\n\tevent generate .s2 <ButtonRelease-1> -x $x -y $y\n\tforeach {x y} [.s3 coord 50] {}\n\tevent generate .s3 <Button-1> -x $x -y $y\n\tevent generate .s3 <ButtonRelease-1> -x $x -y $y\n\tforeach {x y} [.s4 coord 50] {}\n\tevent generate .s4 <Button-1> -x $x -y $y\n\tevent generate .s4 <ButtonRelease-1> -x $x -y $y\n\tupdate\n\tlist $x1 $x2 $x3 $x4\n    } \\\n    -cleanup {\n\tunset x1 x2 x3 x4 x y\n\tdestroy .s1 .s2 .s3 .s4\n    } \\\n    -result {1.0 1.0 1.0 1.0}\n\ntest scale-20.1 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 1} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n} -body {\n    scale .s -from 1 -to 50 -command {set commandedVar}\n    pack .s\n    update  ; # -command callback shall NOT fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n} -result {1 -1}\ntest scale-20.2 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 2} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n    set scaleVar 7\n} -body {\n    scale .s -from 1 -to 50 -variable scaleVar -command {set commandedVar}\n    pack .s\n    update  ; # -command callback shall NOT fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n} -result {7 -1}\ntest scale-20.3 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 3} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n} -body {\n    scale .s -from 1 -to 50\n    .s set 10\n    .s configure -command {set commandedVar}\n    pack .s\n    update  ; # -command callback shall NOT fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n} -result {10 -1}\ntest scale-20.4 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 4} -setup {\n    catch {destroy .s}\n    set res {}\n} -body {\n    scale .s -from 1 -to 50 -command {set commandedVar}\n    pack .s\n    update idletasks\n    .s set 10\n    set timeout [after 500 {set $commandedVar \"timeout\"}]\n    set commandedVar -1\n    vwait commandedVar  ; # -command callback shall fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    after cancel $timeout\n    destroy .s\n} -result {10 10}\ntest scale-20.5 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 5} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n} -body {\n    scale .s -from 1 -to 50\n    pack .s\n    update idletasks\n    .s set 10\n    .s configure -command {set commandedVar}\n    update  ; # -command callback shall NOT fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n} -result {10 -1}\ntest scale-20.6 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 6} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n} -body {\n    scale .s -from 1 -to 50\n    pack .s\n    update idletasks\n    .s configure -command {set commandedVar}\n    .s set 10\n    set timeout [after 500 {set $commandedVar \"timeout\"}]\n    vwait commandedVar  ; # -command callback shall fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n    after cancel $timeout\n} -result {10 10}\ntest scale-20.7 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 7} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n} -body {\n    scale .s -from 1 -to 50 -command {set commandedVar}\n    pack .s\n    update idletasks\n    .s set 10\n    set timeout [after 500 {set $commandedVar \"timeout\"}]\n    vwait commandedVar  ; # -command callback shall fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n    after cancel $timeout\n} -result {10 10}\ntest scale-20.8 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 8} -setup {\n    catch {destroy .s}\n    set res {}\n    set commandedVar -1\n    set scaleVar 7\n} -body {\n    scale .s -from 1 -to 50 -variable scaleVar -command {set commandedVar}\n    pack .s\n    update idletasks\n    .s set 10\n    set timeout [after 500 {set $commandedVar \"timeout\"}]\n    vwait commandedVar  ; # -command callback shall fire\n    set res [list [.s get] $commandedVar]\n} -cleanup {\n    destroy .s\n    after cancel $timeout\n} -result {10 10}\n\ntest scale-21.1 {Bug [55b95f578a] - Associating variable with bignum value with scale crashes it} -setup {\n    catch {destroy .s}\n} -body {\n    pack [scale .s]\n    set foo 5.79e99\n    # non-regression test for bug [55b95f578a] - shall just not crash\n    .s configure -variable foo\n} -cleanup {\n    destroy .s\n} -result {}\ntest scale-21.2 {Bug [55b95f578a] again - Bignum value for -from/-to with scale crashes it} -setup {\n    catch {destroy .s}\n} -body {\n    pack [scale .s]\n    # non-regression test for bug [55b95f578a] - shall just not crash\n    .s configure -from -6.8e99 -to 8.8e99\n} -cleanup {\n    destroy .s\n} -result {}\n\ntest scale-22.1 {Bug [5d991b822e]} {\n    # Want this not to crash\n    set var INIT\n    scale .b -variable var\n    trace add variable var unset {apply {args {\n\t.b configure -variable {}\n    }}}\n    pack .b\n    bind .b <Configure> {unset var}\n    update\n    destroy .b\n} {}\ntest scale-22.2 {Bug [5d991b822e]} {\n    # Want this not to leak traces\n    set var INIT\n    scale .b -variable var\n    trace add variable var unset {apply {args {\n\t.b configure -variable new\n    }}}\n    pack .b\n    bind .b <Configure> {unset -nocomplain var}\n    update\n    destroy .b\n    unset new\n} {}\n\n#\n# TESTFILE CLEANUP\n#\n\noption clear\ncleanupTests\n"
  },
  {
    "path": "tests/scrollbar.test",
    "content": "# This file is a Tcl script to test out scrollbar widgets and\n# the \"scrollbar\" command of Tk.  It is organized in the standard\n# fashion for Tcl tests.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# Note: this test file is woefully incomplete.  Right now there are\n# only bits and pieces of tests.  Please make this file more complete\n# as you fix bugs and add features.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc getTroughSize {w} {\n    if {[testConstraint testmetrics]} {\n\t# Only Windows has [testmetrics]\n\tif [string match v* [$w cget -orient]] {\n\t    return [expr {[winfo height $w] - 2*[testmetrics cyvscroll $w]}]\n\t} else {\n\t    return [expr {[winfo width $w] - 2*[testmetrics cxhscroll $w]}]\n\t}\n    } else {\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    # Calculations here assume that the arrow area is a square.\n\t    if [string match v* [$w cget -orient]] {\n\t\treturn [expr {[winfo height $w] \\\n\t\t\t- ([winfo width $w] \\\n\t\t\t    - [$w cget -highlightthickness] \\\n\t\t\t    - [$w cget -bd] + 1)*2}]\n\t    } else {\n\t\treturn [expr {[winfo width $w] \\\n\t\t\t- ([winfo height $w] \\\n\t\t\t    - [$w cget -highlightthickness] \\\n\t\t\t    - [$w cget -bd] + 1)*2}]\n\t    }\n\t} else {\n\t    # macOS aqua\n\t    if [string match v* [$w cget -orient]] {\n\t\treturn [expr {[winfo height $w] \\\n\t\t\t- ([$w cget -highlightthickness] \\\n\t\t\t  +[$w cget -bd])*2}]\n\t    } else {\n\t\treturn [expr {[winfo width $w] \\\n\t\t\t- ([$w cget -highlightthickness] \\\n\t\t\t  +[$w cget -bd])*2}]\n\t    }\n\t}\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n# For tests scrollbar-1.*\n#\n\nforeach {width height} [wm minsize .] {\n    set height [expr {($height < 200) ? 200 : $height}]\n    set width [expr {($width < 1) ? 1 : $width}]\n}\n\nframe .f -height $height -width $width\npack .f -side left\nscrollbar .s\npack .s -side right -fill y\nupdate\n\n#\n# TESTS\n#\n\nset i 1\nforeach test {\n    {-activebackground #ff0000 #ff0000 non-existent\n\t    {unknown color name \"non-existent\"}}\n    {-activerelief sunken sunken non-existent\n\t    {bad relief \"non-existent\": must be flat, groove, raised, ridge, solid, or sunken}}\n    {-background #ff0000 #ff0000 non-existent\n\t    {unknown color name \"non-existent\"}}\n    {-bd 4 4 badValue {expected screen distance but got \"badValue\"}}\n    {-bg #ff0000 #ff0000 non-existent\n\t    {unknown color name \"non-existent\"}}\n    {-borderwidth 1.3 1.3 badValue {expected screen distance but got \"badValue\"}}\n    {-command \"set x\" {set x} {} {}}\n    {-elementborderwidth 4 4 badValue {expected screen distance or \"\" but got \"badValue\"}}\n    {-cursor arrow arrow badValue {bad cursor spec \"badValue\"}}\n    {-highlightbackground #112233 #112233 ugly {unknown color name \"ugly\"}}\n    {-highlightcolor #123456 #123456 bogus {unknown color name \"bogus\"}}\n    {-highlightthickness 6 6 -2 {expected screen distance but got \"-2\"}}\n    {-jump true 1 silly {expected boolean value but got \"silly\"}}\n    {-orient horizontal horizontal badValue\n\t    {bad orientation \"badValue\": must be vertical or horizontal}}\n    {-orient horizontal horizontal bogus {bad orientation \"bogus\": must be vertical or horizontal}}\n    {-relief ridge ridge badValue {bad relief \"badValue\": must be flat, groove, raised, ridge, solid, or sunken}}\n    {-repeatdelay 140 140 129.3 {expected integer but got \"129.3\"}}\n    {-repeatinterval 140 140 129.3 {expected integer but got \"129.3\"}}\n    {-takefocus \"any string\" \"any string\" {} {}}\n    {-troughcolor #432 #432 lousy {unknown color name \"lousy\"}}\n    {-width 32 32 badValue {expected screen distance but got \"badValue\"}}\n} {\n    lassign $test name value okResult badValue badResult\n    # Assume $name is plain; true of all our in-use options!\n    test scrollbar-1.$i {configuration options} \\\n\t\".s configure $name [list $value]; .s cget $name\" $okResult\n    incr i\n    if {$badValue ne \"\"} {\n\ttest scrollbar-1.$i {configuration options} \\\n\t    -body [list .s configure $name $badValue] \\\n\t    -returnCodes error -result $badResult\n\tincr i\n    }\n    .s configure $name [lindex [.s configure $name] 3]\n}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s\n\ntest scrollbar-2.1 {Tk_ScrollbarCmd procedure} -returnCodes error -body {\n    scrollbar\n} -result {wrong # args: should be \"scrollbar pathName ?-option value ...?\"}\ntest scrollbar-2.2 {Tk_ScrollbarCmd procedure} -body {\n    scrollbar gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest scrollbar-2.3 {Tk_ScrollbarCmd procedure} -setup {\n    scrollbar .s\n} -body {\n    list [winfo class .s] [info command .s]\n} -cleanup {\n    destroy .s\n} -result {Scrollbar .s}\ntest scrollbar-2.4 {Tk_ScrollbarCmd procedure} {\n    list [catch {scrollbar .s -gorp blah} msg] $msg [winfo exists .s] \\\n\t    [info command .s]\n} {1 {unknown option \"-gorp\"} 0 {}}\ntest scrollbar-2.5 {Tk_ScrollbarCmd procedure} -setup {\n    catch {destroy .s}\n} -body {\n    scrollbar .s\n} -cleanup {\n    destroy .s\n} -result .s\n\n\n#\n# COMMON TEST SETUP\n#\nscrollbar .s -orient vertical -highlightthickness 2 -bd 2\npack .s -side right -fill y\nupdate\n\ntest scrollbar-3.1 {ScrollbarWidgetCmd procedure} {\n    list [catch {.s} msg] $msg\n} {1 {wrong # args: should be \".s option ?arg ...?\"}}\ntest scrollbar-3.2 {ScrollbarWidgetCmd procedure, \"cget\" option} {\n    list [catch {.s cget} msg] $msg\n} {1 {wrong # args: should be \".s cget option\"}}\ntest scrollbar-3.3 {ScrollbarWidgetCmd procedure, \"cget\" option} {\n    list [catch {.s cget -gorp} msg] $msg\n} {1 {unknown option \"-gorp\"}}\ntest scrollbar-3.4 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    list [catch {.s activate a b} msg] $msg\n} {1 {wrong # args: should be \".s activate element\"}}\ntest scrollbar-3.5 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    .s activate arrow1\n    .s activate\n} {arrow1}\ntest scrollbar-3.6 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    .s activate slider\n    .s activate\n} {slider}\ntest scrollbar-3.7 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    .s activate arrow2\n    .s activate\n} {arrow2}\ntest scrollbar-3.8 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    .s activate s\n    .s activate {}\n    .s activate\n} {}\ntest scrollbar-3.9 {ScrollbarWidgetCmd procedure, \"activate\" option} {\n    list [catch {.s activate trough1} msg] $msg\n} {0 {}}\ntest scrollbar-3.10 {ScrollbarWidgetCmd procedure, \"cget\" option} {\n    list [catch {.s cget -orient} msg] $msg\n} {0 vertical}\n\n#\n# COMMON TEST SETUP\n#\nscrollbar .s2\n\ntest scrollbar-3.11 {ScrollbarWidgetCmd procedure, \"cget\" option} {\n    expr {[.s2 cget -bd] == [lindex [.s2 configure -bd] 3]}\n} 1\ntest scrollbar-3.12 {ScrollbarWidgetCmd procedure, \"cget\" option} emptyTest {\n    # empty test; duplicated scrollbar-3.11\n} {}\ntest scrollbar-3.12.1 {ScrollbarWidgetCmd procedure, \"cget\" option} emptyTest {\n    # empty test; duplicated scrollbar-3.11\n} {}\ntest scrollbar-3.13 {ScrollbarWidgetCmd procedure, \"cget\" option} {\n    expr {[.s2 cget -highlightthickness] == [lindex [.s2 configure -highlightthickness] 3]}\n} 1\ntest scrollbar-3.14 {ScrollbarWidgetCmd procedure, \"cget\" option} emptyTest {\n    # empty test; duplicated scrollbar-3.13\n} {}\ntest scrollbar-3.14.1 {ScrollbarWidgetCmd procedure, \"cget\" option} emptyTest {\n    # empty test; duplicated scrollbar-3.13\n} {}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .s2\n\ntest scrollbar-3.15 {ScrollbarWidgetCmd procedure, \"configure\" option} {\n    llength [.s configure]\n} 20\ntest scrollbar-3.16 {ScrollbarWidgetCmd procedure, \"configure\" option} {\n    list [catch {.s configure -bad} msg] $msg\n} {1 {unknown option \"-bad\"}}\ntest scrollbar-3.17 {ScrollbarWidgetCmd procedure, \"configure\" option} {\n    .s configure -orient\n} {-orient orient Orient vertical vertical}\ntest scrollbar-3.18 {ScrollbarWidgetCmd procedure, \"configure\" option} {\n    .s configure -orient horizontal\n    set x [.s cget -orient]\n    .s configure -orient vertical\n    set x\n} {horizontal}\ntest scrollbar-3.19 {ScrollbarWidgetCmd procedure, \"configure\" option} {\n    list [catch {.s configure -bad worse} msg] $msg\n} {1 {unknown option \"-bad\"}}\ntest scrollbar-3.20 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    list [catch {.s delta 24} msg] $msg\n} {1 {wrong # args: should be \".s delta xDelta yDelta\"}}\ntest scrollbar-3.21 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    list [catch {.s delta 24 35 42} msg] $msg\n} {1 {wrong # args: should be \".s delta xDelta yDelta\"}}\ntest scrollbar-3.22 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    list [catch {.s delta silly 24} msg] $msg\n} {1 {expected integer but got \"silly\"}}\ntest scrollbar-3.23 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    list [catch {.s delta 18 xxyz} msg] $msg\n} {1 {expected integer but got \"xxyz\"}}\ntest scrollbar-3.24 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    list [catch {.s delta 18 xxyz} msg] $msg\n} {1 {expected integer but got \"xxyz\"}}\ntest scrollbar-3.25 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    format {%.6g} [.s delta 20 0]\n} 0\ntest scrollbar-3.26 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    format {%.6g} [.s delta 0 20]\n} [format %.6g [expr {20.0/([getTroughSize .s]-1)}]]\ntest scrollbar-3.27 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    format {%.6g} [.s delta 0 -20]\n} [format %.6g [expr {-20.0/([getTroughSize .s]-1)}]]\ntest scrollbar-3.28 {ScrollbarWidgetCmd procedure, \"delta\" option} {\n    toplevel .t -width 250 -height 100\n    wm geom .t +0+0\n    scrollbar .t.s -orient horizontal -borderwidth 2\n    place .t.s -width 201\n    update\n    set result [list [format {%.6g} [.t.s delta 0 20]] \\\n\t    [format {%.6g} [.t.s delta [expr {[getTroughSize .t.s] - 1}] 0]]]\n    destroy .t\n    set result\n} {0 1}\ntest scrollbar-3.29 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    list [catch {.s fraction 24} msg] $msg\n} {1 {wrong # args: should be \".s fraction x y\"}}\ntest scrollbar-3.30 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    list [catch {.s fraction 24 30 32} msg] $msg\n} {1 {wrong # args: should be \".s fraction x y\"}}\ntest scrollbar-3.31 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    list [catch {.s fraction silly 24} msg] $msg\n} {1 {expected integer but got \"silly\"}}\ntest scrollbar-3.32 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    list [catch {.s fraction 24 bogus} msg] $msg\n} {1 {expected integer but got \"bogus\"}}\ntest scrollbar-3.33 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.s fraction 0 0]\n} 0\ntest scrollbar-3.34 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.s fraction 0 1000]\n} 1\ntest scrollbar-3.35 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.s fraction 4 21]\n} [format %.6g [expr {(21.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \\\n       /([getTroughSize .s] - 1)}]]\ntest scrollbar-3.36 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.s fraction 4 179]\n} [format %.6g [expr {(179.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \\\n       /([getTroughSize .s] - 1)}]]\ntest scrollbar-3.37 {ScrollbarWidgetCmd procedure, \"fraction\" option} {testmetrics} {\n    format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s]}]]\n} 1\ntest scrollbar-3.38 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.s fraction 4 178]\n} [format %.6g [expr {(178.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \\\n       /([getTroughSize .s] - 1)}]]\ntest scrollbar-3.39 {ScrollbarWidgetCmd procedure, \"fraction\" option} {testmetrics win} {\n    expr {\n    [format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s] - 2}]]]\n\t== [format %g [expr {(200.0 - [testmetrics cyvscroll .s]*2 - 2)\n\t\t\t   / ($height - 1 - [testmetrics cyvscroll .s]*2)}]]}\n} 1\n\n#\n# COMMON TEST SETUP\n#\n\ntoplevel .t -width 250 -height 100\nwm geom .t +0+0\nscrollbar .t.s -orient horizontal -borderwidth 2\nplace .t.s -width 201\nupdate\n\ntest scrollbar-3.41 {ScrollbarWidgetCmd procedure, \"fraction\" option} {\n    format {%.6g} [.t.s fraction 100 0]\n} {0.5}\n\ntest scrollbar-3.42 {ScrollbarWidgetCmd procedure, \"fraction\" option} -setup {\n    if {[testConstraint testmetrics]} {\n\t# Only Windows has [testmetrics]\n\tplace configure .t.s -width [expr {2*[testmetrics cxhscroll .t.s]+1}]\n    } else {\n\tif {[tk windowingsystem] eq \"x11\"} {\n\t    place configure .t.s -width [expr {[winfo height .t.s] - 2*([.t.s cget -highlightthickness] + [.t.s cget -bd] + 1)}]\n\t} else {\n\t    # macOS aqua\n\t    place configure .t.s -width [expr {2*([.t.s cget -highlightthickness] + [.t.s cget -bd])}]\n\t}\n    }\n    update\n} -body {\n    format {%.6g} [.t.s fraction 100 0]\n} -result 0\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\ntest scrollbar-3.43 {ScrollbarWidgetCmd procedure, \"get\" option} {\n    list [catch {.s get a} msg] $msg\n} {1 {wrong # args: should be \".s get\"}}\ntest scrollbar-3.45 {ScrollbarWidgetCmd procedure, \"get\" option} {\n    .s set 0.6 0.8\n    set result {}\n    foreach element [.s get] {\n\tlappend result [format %.1f $element]\n    }\n    set result\n} {0.6 0.8}\ntest scrollbar-3.46 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    list [catch {.s identify 0} msg] $msg\n} {1 {wrong # args: should be \".s identify x y\"}}\ntest scrollbar-3.47 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    list [catch {.s identify 0 0 1} msg] $msg\n} {1 {wrong # args: should be \".s identify x y\"}}\ntest scrollbar-3.48 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    list [catch {.s identify bogus 2} msg] $msg\n} {1 {expected integer but got \"bogus\"}}\ntest scrollbar-3.49 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    list [catch {.s identify -1 bogus} msg] $msg\n} {1 {expected integer but got \"bogus\"}}\ntest scrollbar-3.50.1 {ScrollbarWidgetCmd procedure, \"identify\" option} notAqua {\n    .s identify 5 5\n} {arrow1}\ntest scrollbar-3.50.2 {ScrollbarWidgetCmd procedure, \"identify\" option} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 5 5\n} {trough1}\ntest scrollbar-3.51 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    .s identify 5 35\n} {trough1}\ntest scrollbar-3.52 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    .s set .3 .6\n    .s identify 5 80\n} {slider}\ntest scrollbar-3.53 {ScrollbarWidgetCmd procedure, \"identify\" option} {\n    .s identify 5 145\n} {trough2}\ntest scrollbar-3.54.1 {ScrollbarWidgetCmd procedure, \"identify\" option} notAqua {\n    .s identify 5 195\n} {arrow2}\ntest scrollbar-3.54.2 {ScrollbarWidgetCmd procedure, \"identify\" option} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 5 195\n} {trough2}\ntest scrollbar-3.56 {ScrollbarWidgetCmd procedure, \"identify\" option} unix {\n    .s identify 0 0\n} {}\ntest scrollbar-3.57 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    list [catch {.s set abc def} msg] $msg\n} {1 {expected floating-point number but got \"abc\"}}\ntest scrollbar-3.58 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    list [catch {.s set 0.6 def} msg] $msg\n} {1 {expected floating-point number but got \"def\"}}\ntest scrollbar-3.59 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    .s set -.2 .3\n    set result {}\n    foreach element [.s get] {\n\tlappend result [format %.1f $element]\n    }\n    set result\n} {0.0 0.3}\ntest scrollbar-3.60 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    .s set 1.1 .4\n    .s get\n} {1.0 1.0}\ntest scrollbar-3.61 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    .s set .5 -.3\n    .s get\n} {0.5 0.5}\ntest scrollbar-3.62 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    .s set .5 87\n    .s get\n} {0.5 1.0}\ntest scrollbar-3.63 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    .s set .4 .3\n    set result {}\n    foreach element [.s get] {\n\tlappend result [format %.1f $element]\n    }\n    set result\n} {0.4 0.4}\ntest scrollbar-3.71 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    list [catch {.s set 1 2 3} msg] $msg\n} {1 {wrong # args: should be \".s set firstFraction lastFraction\"}}\ntest scrollbar-3.72 {ScrollbarWidgetCmd procedure, \"set\" option} {\n    list [catch {.s set 1 2 3 4 5} msg] $msg\n} {1 {wrong # args: should be \".s set firstFraction lastFraction\"}}\ntest scrollbar-3.73 {ScrollbarWidgetCmd procedure} {\n    list [catch {.s bogus} msg] $msg\n} {1 {bad option \"bogus\": must be activate, cget, configure, delta, fraction, get, identify, or set}}\ntest scrollbar-3.74 {ScrollbarWidgetCmd procedure} {\n    list [catch {.s c} msg] $msg\n} {1 {ambiguous option \"c\": must be activate, cget, configure, delta, fraction, get, identify, or set}}\n\ntest scrollbar-4.1 {ScrollbarEventProc procedure} {\n    catch {destroy .s1}\n    scrollbar .s1 -bg #543210\n    rename .s1 .s2\n    set x {}\n    lappend x [winfo exists .s1]\n    lappend x [.s2 cget -bg]\n    destroy .s1\n    lappend x [info command .s?] [winfo exists .s1] [winfo exists .s2]\n} {1 #543210 {} 0 0}\n\ntest scrollbar-5.1 {ScrollbarCmdDeletedProc procedure} {\n    catch {destroy .s1}\n    scrollbar .s1\n    rename .s1 {}\n    list [info command .s?] [winfo exists .s1]\n} {{} 0}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .s}\nscrollbar .s -orient vertical -relief sunken -bd 2 -highlightthickness 2\npack .s -side left -fill y\n.s set .2 .4\nupdate\n\ntest scrollbar-6.1 {ScrollbarPosition procedure} unix {\n    .s identify 8 3\n} {}\ntest scrollbar-6.3 {ScrollbarPosition procedure} unix {\n    .s identify 8 196\n} {}\ntest scrollbar-6.4 {ScrollbarPosition procedure} unix {\n    .s identify 3 100\n} {}\ntest scrollbar-6.6 {ScrollbarPosition procedure} unix {\n    .s identify 19 100\n} {}\ntest scrollbar-6.7 {ScrollbarPosition procedure} {\n    .s identify [expr {[winfo width .s] / 2}] -1\n} {}\ntest scrollbar-6.8 {ScrollbarPosition procedure} {\n    .s identify [expr {[winfo width .s] / 2}] [winfo height .s]\n} {}\ntest scrollbar-6.9 {ScrollbarPosition procedure} {\n    .s identify -1 [expr {[winfo height .s] / 2}]\n} {}\ntest scrollbar-6.10 {ScrollbarPosition procedure} {\n    .s identify [winfo width .s] [expr {[winfo height .s] / 2}]\n} {}\ntest scrollbar-6.11.1 {ScrollbarPosition procedure} x11 {\n    .s identify 8 4\n} {arrow1}\ntest scrollbar-6.11.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 8 4\n} {trough1}\ntest scrollbar-6.12.1 {ScrollbarPosition procedure} x11 {\n    # x11 scrollbars have arrows 19 pixels height,\n    # but on XQuartz they are 15 pixels height\n    .s identify 8 15\n} {arrow1}\ntest scrollbar-6.12.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 8 15\n} {trough1}\ntest scrollbar-6.14 {ScrollbarPosition procedure} win {\n    .s identify [expr {[winfo width .s] / 2}] 0\n} {arrow1}\ntest scrollbar-6.15 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [expr {[testmetrics cyvscroll .s] - 1}]\n} {arrow1}\ntest scrollbar-6.16 {ScrollbarPosition procedure} unix {\n    .s identify 8 20\n} {trough1}\ntest scrollbar-6.17 {ScrollbarPosition procedure} {unix nonPortable} {\n    # Don't know why this is non-portable, but it doesn't work on\n    # some platforms.\n    .s identify 8 51\n} {trough1}\ntest scrollbar-6.18 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [testmetrics cyvscroll .s]\n} {trough1}\ntest scrollbar-6.19 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [expr {int(.2 / [.s delta 0 1])\n\t\t\t\t\t\t+ [testmetrics cyvscroll .s] - 1}]\n} {trough1}\ntest scrollbar-6.20 {ScrollbarPosition procedure} unix {\n    .s identify 8 52\n} {slider}\ntest scrollbar-6.21 {ScrollbarPosition procedure} {unix nonPortable} {\n    # Don't know why this is non-portable, but it doesn't work on\n    # some platforms.\n    .s identify 8 83\n} {slider}\ntest scrollbar-6.22 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] \\\n\t[expr {int(.2 / [.s delta 0 1] + 0.5) + [testmetrics cyvscroll .s]}]\n} {slider}\ntest scrollbar-6.23 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [expr {int(.4 / [.s delta 0 1])\n\t\t\t\t\t\t + [testmetrics cyvscroll .s] - 1}]\n} {slider}\ntest scrollbar-6.24 {ScrollbarPosition procedure} unix {\n    .s identify 8 84\n} {trough2}\ntest scrollbar-6.25 {ScrollbarPosition procedure} unix {\n    .s identify 8 179\n} {trough2}\ntest scrollbar-6.27 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [expr {int(.4 / [.s delta 0 1])\n\t\t\t\t\t\t + [testmetrics cyvscroll .s]}]\n} {trough2}\ntest scrollbar-6.28 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s]\n\t\t\t\t\t\t - [testmetrics cyvscroll .s] - 1}]\n} {trough2}\ntest scrollbar-6.29.1 {ScrollbarPosition procedure} x11 {\n    # x11 scrollbars have arrows at least 19 pixels height\n    # but on XQuartz they are 15 pixels height\n    .s identify 8 184\n} {arrow2}\ntest scrollbar-6.29.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 8 184\n} {trough2}\ntest scrollbar-6.30.1 {ScrollbarPosition procedure} x11 {\n    .s identify 8 195\n} {arrow2}\ntest scrollbar-6.30.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 8 195\n} {trough2}\ntest scrollbar-6.32 {ScrollbarPosition procedure} {testmetrics win} {\n    .s identify [expr {[winfo width .s] / 2}]  [expr {[winfo height .s]\n\t\t\t\t\t\t  - [testmetrics cyvscroll .s]}]\n} {arrow2}\ntest scrollbar-6.33 {ScrollbarPosition procedure} win {\n    .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s] - 1}]\n} {arrow2}\ntest scrollbar-6.34 {ScrollbarPosition procedure} unix {\n    .s identify 4 100\n} {trough2}\ntest scrollbar-6.35 {ScrollbarPosition procedure} unix {\n    # Linux x11 scrollbars have arrows 18 pixels width\n    # macOS XQuartz scrollbars have arrows 14 pixels width\n    # macOS aqua scrollbars have no arrows nowadays\n    .s identify 14 100\n} {trough2}\ntest scrollbar-6.37 {ScrollbarPosition procedure} win {\n    .s identify 0 100\n} {trough2}\ntest scrollbar-6.38 {ScrollbarPosition procedure} win {\n    .s identify [expr {[winfo width .s] - 1}] 100\n} {trough2}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .t}\ntoplevel .t -width 250 -height 150\nwm geometry .t +0+0\nscrollbar .t.s -orient horizontal -relief sunken -bd 2 -highlightthickness 2\nplace .t.s -width 200\n.t.s set .2 .4\nupdate\n\ntest scrollbar-6.39.1 {ScrollbarPosition procedure} x11 {\n    .t.s identify 4 8\n} {arrow1}\ntest scrollbar-6.39.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .t.s identify 4 8\n} {trough1}\ntest scrollbar-6.40 {ScrollbarPosition procedure} win {\n    .t.s identify 0 [expr {[winfo height .t.s] / 2}]\n} {arrow1}\ntest scrollbar-6.41.1 {ScrollbarPosition procedure} x11 {\n    .t.s identify 82 8\n} {slider}\ntest scrollbar-6.41.2 {ScrollbarPosition procedure} aqua {\n    # macOS aqua scrollbars have no arrows nowadays\n    .t.s identify 82 8\n} {trough2}\ntest scrollbar-6.43 {ScrollbarPosition procedure} {testmetrics win} {\n    .t.s identify [expr {int(.4 / [.t.s delta 1 0]) + [testmetrics cxhscroll .t.s]\n\t\t       - 1}] [expr {[winfo height .t.s] / 2}]\n} {slider}\ntest scrollbar-6.44 {ScrollbarPosition procedure} unix {\n    # Linux x11 scrollbars have arrows 18 pixels height\n    # macOS XQuartz scrollbars have arrows 14 pixels height\n    # macOS aqua scrollbars have no arrows nowadays\n    .t.s identify 100 14\n} {trough2}\ntest scrollbar-6.46 {ScrollbarPosition procedure} win {\n    .t.s identify 100 [expr {[winfo height .t.s] - 1}]\n} {trough2}\n\ntest scrollbar-7.1 {EventuallyRedraw} {\n    .s configure -orient horizontal\n    update\n    set result [.s cget -orient]\n    .s configure -orient vertical\n    update\n    lappend result [.s cget -orient]\n} {horizontal vertical}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .t}\ntoplevel .t\nwm geometry .t +0+0\n\ntest scrollbar-8.1 {TkScrollbarEventProc: recursive deletion} notAqua {\n    # constrained by notAqua because this test clicks on an arrow of the\n    # scrollbar - but macOS has no such arrows in modern scrollbars\n    proc doit {args} { destroy .t.f }\n    proc bgerror {args} {}\n    destroy .t.f\n    frame .t.f\n    scrollbar .t.f.s -command doit\n    pack .t.f -fill both -expand 1\n    pack .t.f.s -fill y -expand 1 -side right\n    wm geometry .t 100x100\n    .t.f.s set 0 .5\n    update\n    set result [winfo exists .t.f.s]\n    event generate .t.f.s <Button> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5\n    event generate .t <ButtonRelease> -button 1\n    update\n    lappend result [winfo exists .t.f.s] [winfo exists .t.f]\n    rename bgerror {}\n    set result\n} {1 0 0}\ntest scrollbar-8.2 {TkScrollbarEventProc: recursive deletion} notAqua {\n    # constrained by notAqua because this test clicks on an arrow of the\n    # scrollbar - but macOS has no such arrows in modern scrollbars\n    proc doit {args} { destroy .t.f.s }\n    proc bgerror {args} {}\n    destroy .t.f\n    frame .t.f\n    scrollbar .t.f.s -command doit\n    pack .t.f -fill both -expand 1\n    pack .t.f.s -fill y -expand 1 -side right\n    wm geometry .t 100x100\n    .t.f.s set 0 .5\n    update\n    set result [winfo exists .t.f.s]\n    event generate .t.f.s <Button> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5\n    event generate .t.f <ButtonRelease> -button 1\n    update\n    lappend result [winfo exists .t.f.s] [winfo exists .t.f]\n    rename bgerror {}\n    set result\n} {1 0 1}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest scrollbar-9.1 {scrollbar widget vs hidden commands} {\n    catch {destroy .s}\n    scrollbar .s\n    interp hide {} .s\n    destroy .s\n    list [winfo children .] [interp hidden]\n} [list {} [interp hidden]]\n\ntest scrollbar-10.1 {<MouseWheel> event on scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -yscrollcommand {.s set}] -side left\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Line $i\\n\"}\n    pack [scrollbar .s -command {.t yview}] -fill y -expand 1 -side left\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {4.0}\n\ntest scrollbar-10.2 {<MouseWheel> event on scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -xscrollcommand {.s set} -wrap none] -side top\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Char $i \"}\n    pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <Shift-MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {1.3}\ntest scrollbar-10.3 {<MouseWheel> event on horizontal scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -xscrollcommand {.s set} -wrap none] -side top\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Char $i \"}\n    pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {1.3}\n\ntest scrollbar-11.1 {bug fix: [011706ec42] Scrollbar unsafe wrt widget destruction} -body {\n    proc destroy_scrollbar {} {\n\tif {[winfo exists .top.s]} {\n\t    destroy .top.s\n\t}\n    }\n    toplevel .top\n    scrollbar .top.s\n    bind .top.s <Button-2> {destroy_scrollbar}\n    pack .top.s\n    focus -force .top.s\n    update\n    event generate .top.s <Button-2>\n    update  ; # shall not trigger error  invalid command name \".top.s\"\n} -cleanup {\n    destroy .top.s .top\n} -result {}\ntest scrollbar-11.2 {bug fix: [011706ec42] Scrollbar unsafe wrt widget destruction} -body {\n    proc destroy_scrollbar {{y 0}} {\n\tif {[winfo exists .top.s]} {\n\t    destroy .top.s\n\t}\n    }\n    toplevel .top\n    wm minsize .top 50 400\n    update\n    scrollbar .top.s\n    bind .top.s <Button-2> {after idle destroy_scrollbar}\n    pack .top.s -expand true -fill y\n    focus -force .top.s\n    update\n    event generate .top.s <Button-2> -x 2 -y [expr {[winfo height .top.s] / 2}]\n    update  ; # shall not trigger error  invalid command name \".top.s\"\n} -cleanup {\n    destroy .top.s .top\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncatch {destroy .s}\ncatch {destroy .t}\ncleanupTests\n"
  },
  {
    "path": "tests/select.test",
    "content": "# This file is a Tcl script to test out Tk's selection management code,\n# especially the \"selection\" command.\n#\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is platform-indifferent. Tests regarding the selection\n#   that are specific to the unix platform (this includes macOS) go into the\n#   test file unixSelect.test.\n# * Multiple display selection handling will only be tested if the environment\n#   variable TK_ALT_DISPLAY is set to an alternate display.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child select\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint cliboardManagerPresent 0\nif {![catch {selection get -selection CLIPBOARD_MANAGER -type TARGETS}]} {\n    if {\"SAVE_TARGETS\" in [selection get -selection CLIPBOARD_MANAGER -type TARGETS]} {\n\ttestConstraint cliboardManagerPresent 1\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# Eliminate any existing selection on the screen.  This is needed in case\n# there is a selection in some other application, in order to prevent races\n# from causing false errors in the tests below.\nselection clear .\nafter 1500\n\n# set up a very large buffer to test INCR retrievals\nset longValue \"\"\nforeach i {a b c d e f g j h i j k l m o p q r s t u v w x y z} {\n    set j $i.1$i.2$i.3$i.4$i.5$i.6$i.7$i.8$i.9$i.10$i.11$i.12$i.13$i.14\n    append longValue A$j B$j C$j D$j E$j F$j G$j H$j I$j K$j L$j M$j N$j\n}\n\n#\n# TESTS\n#\n\ntest select-1.1 {Tk_CreateSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    lsort [selection get TARGETS]\n} -result {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}\ntest select-1.2 {Tk_CreateSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    lsort [selection get TARGETS]\n} -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}\ntest select-1.3 {Tk_CreateSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get TEST] $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-1.4.1 {Tk_CreateSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    selection handle .f1 {handler STRING}\n    lsort [selection get TARGETS]\n} -result {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}\ntest select-1.4.2 {Tk_CreateSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    selection handle .f1 {handler STRING}\n    lsort [selection get TARGETS]\n} -result {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}\ntest select-1.5 {Tk_CreateSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    selection handle .f1 {handler STRING}\n    set selValue \"\"\n    set selInfo \"\"\n    list [selection get] $selInfo\n} -result {{} {STRING 0 4000}}\ntest select-1.6.1 {Tk_CreateSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    selection handle .f1 {handler STRING}\n    set selValue \"\"\n    set selInfo \"\"\n    selection get\n    selection get -type TEST\n    selection handle .f1 {handler TEST2} TEST\n    selection get -type TEST\n    list $selInfo [lsort [selection get TARGETS]]\n} -result {{STRING 0 4000 TEST 0 4000 TEST2 0 4000} {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}}\ntest select-1.6.2 {Tk_CreateSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST} TEST\n    selection handle .f1 {handler STRING}\n    set selValue \"\"\n    set selInfo \"\"\n    selection get\n    selection get -type TEST\n    selection handle .f1 {handler TEST2} TEST\n    selection get -type TEST\n    list $selInfo [lsort [selection get TARGETS]]\n} -result {{STRING 0 4000 TEST 0 4000 TEST2 0 4000} {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-1.7.1 {Tk_CreateSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    selection handle -selection CLIPBOARD .f1 {handler TEST} TEST\n    selection handle -selection PRIMARY .f1 {handler TEST2} STRING\n    list [lsort [selection get -selection PRIMARY TARGETS]] \\\n\t[lsort [selection get -selection CLIPBOARD TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-1.7.2 {Tk_CreateSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    selection handle -selection CLIPBOARD .f1 {handler TEST} TEST\n    selection handle -selection PRIMARY .f1 {handler TEST2} STRING\n    list [lsort [selection get -selection PRIMARY TARGETS]] \\\n\t[lsort [selection get -selection CLIPBOARD TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-1.8 {Tk_CreateSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle -format INTEGER -type TEST .f1 {handler TEST}\n    lsort [selection get TARGETS]\n} -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}\n\n##############################################################################\n\ntest select-2.1 {Tk_DeleteSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type USER .f1 {handler USER}\n    set result [list [lsort [selection get TARGETS]]]\n    selection handle -type TEST .f1 {}\n    lappend result [lsort [selection get TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW USER UTF8_STRING} {MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW USER UTF8_STRING}}\ntest select-2.2 {Tk_DeleteSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type USER .f1 {handler USER}\n    set result [list [lsort [selection get TARGETS]]]\n    selection handle -type USER .f1 {}\n    lappend result [lsort [selection get TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW USER UTF8_STRING} {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}}\ntest select-2.3 {Tk_DeleteSelHandler procedure} -constraints unix -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    selection handle -selection PRIMARY .f1 {handler STRING}\n    selection handle -selection CLIPBOARD .f1 {handler STRING}\n    selection handle -selection CLIPBOARD .f1 {}\n    list [lsort [selection get TARGETS]] \\\n\t[lsort [selection get -selection CLIPBOARD TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-2.4 {Tk_DeleteSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type USER .f1 {handler USER}\n    set result [list [lsort [selection get TARGETS]]]\n    selection handle -type TEST .f1 {}\n    lappend result [lsort [selection get TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW USER} {MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW USER}}\ntest select-2.5 {Tk_DeleteSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type USER .f1 {handler USER}\n    set result [list [lsort [selection get TARGETS]]]\n    selection handle -type USER .f1 {}\n    lappend result [lsort [selection get TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW USER} {MULTIPLE STRING TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-2.6 {Tk_DeleteSelHandler procedure} -constraints win -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    selection handle -selection PRIMARY .f1 {handler STRING}\n    selection handle -selection CLIPBOARD .f1 {handler STRING}\n    selection handle -selection CLIPBOARD .f1 {}\n    list [lsort [selection get TARGETS]] \\\n\t[lsort [selection get -selection CLIPBOARD TARGETS]]\n} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-2.7 {Tk_DeleteSelHandler procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    list [selection handle .f1 {}] [selection handle .f1 {}]\n} -result {{} {}}\n\n##############################################################################\n\ntest select-3.1 {Tk_OwnSelection procedure} -setup {\n    selectionSetup\n} -body {\n    selection own\n} -result {.f1}\ntest select-3.2 {Tk_OwnSelection procedure} -body {\n    selectionSetup .f1\n    set result [selection own]\n    selectionSetup .f2\n    lappend result [selection own]\n} -result {.f1 .f2}\ntest select-3.3 {Tk_OwnSelection procedure} -setup {\n    selectionSetup .f1\n    selectionSetup .f2\n} -body {\n    selection own -selection CLIPBOARD .f1\n    list [selection own] [selection own -selection CLIPBOARD]\n} -result {.f2 .f1}\ntest select-3.4 {Tk_OwnSelection procedure} -setup {\n    global lostSel\n    selectionSetup\n} -body {\n    set lostSel {owned}\n    selection own -command { set lostSel {lost} } .f1\n    selection clear .f1\n    set lostSel\n} -result {lost}\ntest select-3.5 {Tk_OwnSelection procedure} -setup {\n    global lostSel\n    selectionSetup .f1\n    selectionSetup .f2\n} -body {\n    set lostSel {owned}\n    selection own -command { set lostSel {lost1} } .f1\n    selection own -command { set lostSel {lost2} } .f2\n    list $lostSel [selection own]\n} -result {lost1 .f2}\ntest select-3.6 {Tk_OwnSelection procedure} -setup {\n    global lostSel\n    selectionSetup\n} -body {\n    set lostSel {owned}\n    selection own -command { set lostSel {lost1} } .f1\n    selection own -command { set lostSel {lost2} } .f1\n    set result $lostSel\n    selection clear .f1\n    lappend result $lostSel\n} -result {owned lost2}\ntest select-3.7 {Tk_OwnSelection procedure} -constraints x11 -setup {\n    global lostSel\n    selectionSetup\n    childTkProcess create\n} -body {\n    set lostSel {owned}\n    selection own -command { set lostSel {lost1} } .f1\n    update\n    set result {}\n    lappend result [childTkProcess eval { selection own . }]\n    lappend result [childTkProcess eval {selection own}]\n    update\n    childTkProcess exit\n    lappend result $lostSel\n} -result {{} . lost1}\n\n# check reentrancy on selection replacement\n\ntest select-3.8 {Tk_OwnSelection procedure} -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD -command { destroy .f1 } .f1\n    selection own -selection CLIPBOARD .\n} -result {}\ntest select-3.9 {Tk_OwnSelection procedure} -setup {\n    selectionSetup .f2\n    selectionSetup .f1\n} -body {\n    selection own -selection CLIPBOARD -command { destroy .f2 } .f1\n    selection own -selection CLIPBOARD .f2\n} -result {}\n\n# multiple display tests\n\ntest select-3.10 {Tk_OwnSelection procedure} -constraints {\n    altDisplay\n} -body {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n    list [selection own -displayof .f1] [selection own -displayof .f2]\n} -result {.f1 .f2}\ntest select-3.11 {Tk_OwnSelection procedure} -constraints {\n    altDisplay\n} -setup {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n    childTkProcess create\n    update\n    set result \"\"\n} -body {\n    lappend result [childTkProcess eval \"toplevel .t -screen $env(TK_ALT_DISPLAY); wm geom .t +0+0; selection own .t; update\"]\n    lappend result [selection own -displayof .f1] \\\n\t    [selection own -displayof .f2]\n} -cleanup {\n    childTkProcess exit\n} -result {{} .f1 {}}\n\n##############################################################################\n\ntest select-4.1 {Tk_ClearSelection procedure} -setup {\n    selectionSetup\n} -body {\n    set result [selection own]\n    selection clear .f1\n    lappend result [selection own]\n} -result {.f1 {}}\ntest select-4.2 {Tk_ClearSelection procedure} -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    selection clear .f1\n    selection own -selection CLIPBOARD\n} -result {.f1}\ntest select-4.3 {Tk_ClearSelection procedure} -setup {\n    selectionSetup\n} -body {\n    list [selection clear .f1] [selection clear .f1]\n} -result {{} {}}\ntest select-4.4 {Tk_ClearSelection procedure} -constraints x11 -setup {\n    global lostSel\n    selectionSetup\n    childTkProcess create\n} -body {\n    set lostSel {owned}\n    selection own -command { set lostSel {lost1} } .f1\n    update\n    set result {}\n    lappend result [childTkProcess eval {selection clear; update}]\n    update\n    childTkProcess exit\n    lappend result [selection own]\n} -result {{} {}}\n\n# multiple display tests\n\ntest select-4.5 {Tk_ClearSelection procedure} -constraints {\n    altDisplay\n} -setup {\n    global lostSel lostSel2\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n} -body {\n    set lostSel {owned}\n    set lostSel2 {owned2}\n    selection own -command { set lostSel {lost1} } .f1\n    selection own -command { set lostSel2 {lost2} } .f2\n    update\n    selection clear -displayof .f2\n    update\n    list $lostSel $lostSel2\n} -result {owned lost2}\ntest select-4.6 {Tk_ClearSelection procedure} -constraints {\n    x11 altDisplay\n} -setup {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n    childTkProcess create\n} -body {\n    set lostSel {owned}\n    set lostSel2 {owned2}\n    selection own -command { set lostSel {lost1} } .f1\n    selection own -command { set lostSel2 {lost2} } .f2\n    update\n    set result \"\"\n    lappend result [childTkProcess eval \"toplevel .t -screen $env(TK_ALT_DISPLAY); wm geom .t +0+0; selection own .t; update\"]\n    lappend result [selection own -displayof .f1] \\\n\t    [selection own -displayof .f2] $lostSel $lostSel2\n    childTkProcess exit\n    set result\n} -result {{} .f1 {} owned lost2}\n\n##############################################################################\n\ntest select-5.1 {Tk_GetSelection procedure} -returnCodes error -setup {\n    selectionSetup\n} -body {\n    selection get TEST\n} -result {PRIMARY selection doesn't exist or form \"TEST\" not defined}\ntest select-5.2 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -body {\n    selection get TK_WINDOW\n} -result {.f1}\ntest select-5.3 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get TEST] $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-5.4 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -returnCodes error -body {\n    selection handle .f1 ERROR errHandler\n    selection get ERROR\n} -result {PRIMARY selection doesn't exist or form \"ERROR\" not defined}\ntest select-5.5 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {handler STRING}\n    list [selection get] $selInfo\n} -result \"$longValue {STRING 0 4000 STRING 4000 4000 STRING 8000 4000 STRING 12000 4000 STRING 16000 4000}\"\ntest select-5.6 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -returnCodes error -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {apply {{type offset count} {\n\tselection handle .f1 {}\n\thandler $type $offset $count\n    }} STRING}\n    selection get\n} -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest select-5.7 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -returnCodes error -body {\n    set selValue \"Test Value\"\n    set selInfo \"\"\n    selection handle .f1 {apply {{type offset count} {\n\tdestroy .f1\n\thandler $type $offset $count\n    }} STRING}\n    selection get\n} -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest select-5.8 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n} -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {apply {{type offset count} {\n\tselection clear\n\thandler $type $offset $count\n    }} STRING}\n    list [selection get] $selInfo [catch {selection get} msg] $msg\n} -result \"$longValue {STRING 0 4000 STRING 4000 4000 STRING 8000 4000 STRING 12000 4000 STRING 16000 4000} 1 {PRIMARY selection doesn't exist or form \\\"STRING\\\" not defined}\"\ntest select-5.9 {Tk_GetSelection procedure} -constraints x11 -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    update\n    set selValue \"Test value\"\n    set selInfo \"\"\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-5.10 {Tk_GetSelection procedure} -constraints x11 -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    update\n    set selValue \"Test value\"\n    set selInfo \"\"\n    selection own .f1\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST} 1]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{selection owner didn't respond} {}}\n\n# multiple display tests\n\ntest select-5.11 {Tk_GetSelection procedure} -constraints {\n    altDisplay\n} -setup {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    selection handle -selection PRIMARY .f2 {handler TEST2} TEST\n    set selValue \"Test value\"\n    set selInfo \"\"\n    set result [list [selection get TEST] $selInfo]\n    set selValue \"Test value2\"\n    set selInfo \"\"\n    lappend result [selection get -displayof .f2 TEST] $selInfo\n} -result {{Test value} {TEST 0 4000} {Test value2} {TEST2 0 4000}}\ntest select-5.12 {Tk_GetSelection procedure} -constraints {\n    altDisplay\n} -setup {\n    global lostSel lostSel2\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    selection handle -selection PRIMARY .f2 {} TEST\n    set selValue \"Test value\"\n    set selInfo \"\"\n    set result [list [catch {selection get TEST} msg] $msg $selInfo]\n    set selValue \"Test value2\"\n    set selInfo \"\"\n    lappend result [catch {selection get -displayof .f2 TEST} msg] $msg \\\n\t    $selInfo\n} -result {0 {Test value} {TEST 0 4000} 1 {PRIMARY selection doesn't exist or form \"TEST\" not defined} {}}\ntest select-5.13 {Tk_GetSelection procedure} -constraints {\n    x11 altDisplay\n} -setup {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n    childTkProcess create\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    selection own .f1\n    selection handle -selection PRIMARY .f2 {handler TEST2} TEST\n    selection own .f2\n    set selValue \"Test value\"\n    set selInfo \"\"\n    update\n    set result \"\"\n    lappend result [childTkProcess eval \"toplevel .t -screen $env(TK_ALT_DISPLAY); wm geom .t +0+0; selection get -displayof .t TEST\"]\n    set selValue \"Test value2\"\n    lappend result [childTkProcess eval \"selection get TEST\"]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{Test value} {Test value2} {TEST2 0 4000 TEST 0 4000}}\ntest select-5.14 {Tk_GetSelection procedure} -constraints {\n    x11 altDisplay\n} -setup {\n    selectionSetup .f1\n    selectionSetup .f2 $env(TK_ALT_DISPLAY)\n    childTkProcess create\n} -body {\n    selection handle -selection PRIMARY .f1 {handler TEST} TEST\n    selection own .f1\n    selection handle -selection PRIMARY .f2 {} TEST\n    selection own .f2\n    set selValue \"Test value\"\n    set selInfo \"\"\n    update\n    set result \"\"\n    lappend result [childTkProcess eval \"toplevel .t -screen $env(TK_ALT_DISPLAY); wm geom .t +0+0; selection get -displayof .t TEST\"]\n    set selValue \"Test value2\"\n    lappend result [childTkProcess eval \"selection get TEST\"]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{PRIMARY selection doesn't exist or form \"TEST\" not defined} {Test value2} {TEST 0 4000}}\ntest select-5.15 {Tk_GetSelection procedure} -setup {\n    selectionSetup\n    if {[llength [info command ::bgerror]]} {\n\trename ::bgerror ::TMPbgerror\n    }\n    set ::bgerrors {}\n} -body {\n    proc ::bgerror msg {lappend ::bgerrors $msg}\n    selection handle -type ERROR .f1 errHandler\n    list [catch {selection get ERROR} msg] $msg [update] {*}$::bgerrors\n} -cleanup {\n    rename ::bgerror {}\n    if {[llength [info command ::TMPbgerror]]} {\n\trename ::TMPbgerror ::bgerror\n    }\n} -result {1 {PRIMARY selection doesn't exist or form \"ERROR\" not defined} {} {selection handler aborted}}\n\n##############################################################################\n\ntest select-6.1 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection\n} -result {wrong # args: should be \"selection option ?arg ...?\"}\n# selection clear\ntest select-6.2 {Tk_SelectionCmd procedure} -body {\n    selection clear -selection\n} -returnCodes error -result {value for \"-selection\" missing}\ntest select-6.3 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own .\n    set result [selection own]\n    selection clear -displayof .f1\n    lappend result [selection own]\n} -result {. {}}\ntest select-6.4 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    set result [list [selection own] [selection own -selection CLIPBOARD]]\n    selection clear -selection CLIPBOARD .f1\n    lappend result [selection own] [selection own -selection CLIPBOARD]\n} -result {.f1 .f1 .f1 {}}\ntest select-6.5 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .\n    set result [list [selection own] [selection own -selection CLIPBOARD]]\n    selection clear -selection CLIPBOARD -displayof .f1\n    lappend result [selection own] [selection own -selection CLIPBOARD]\n} -result {.f1 . .f1 {}}\ntest select-6.6 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection clear -badopt foo\n} -result {bad option \"-badopt\": must be -displayof or -selection}\ntest select-6.7 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection clear -selectionfoo foo\n} -result {bad option \"-selectionfoo\": must be -displayof or -selection}\ntest select-6.8 {Tk_SelectionCmd procedure} -body {\n    destroy .f2\n    selection clear -displayof .f2\n} -returnCodes error -result {bad window path name \".f2\"}\ntest select-6.9 {Tk_SelectionCmd procedure} -body {\n    destroy .f2\n    selection clear .f2\n} -returnCodes error -result {bad window path name \".f2\"}\ntest select-6.10 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    set result [selection own -selection PRIMARY]\n    selection clear\n    lappend result [selection own -selection PRIMARY]\n} -result {.f1 {}}\ntest select-6.11 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own -selection CLIPBOARD .f1\n    set result [selection own -selection CLIPBOARD]\n    selection clear -selection CLIPBOARD\n    lappend result [selection own -selection CLIPBOARD]\n} -result {.f1 {}}\ntest select-6.12 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection clear foo bar\n} -result {wrong # args: should be \"selection clear ?-option value ...?\"}\n\n# selection get\n\ntest select-6.13 {Tk_SelectionCmd procedure} -body {\n    selection get -selection\n} -returnCodes error -result {value for \"-selection\" missing}\ntest select-6.14 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler TEST}\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get -displayof .f1] $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-6.15 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 {handler STRING}\n    selection handle -selection CLIPBOARD .f1 {handler TEST}\n    selection own -selection CLIPBOARD .f1\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get -selection CLIPBOARD] $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-6.16 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type STRING .f1 {handler STRING}\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get -type TEST] $selInfo\n} -result {{Test value} {TEST 0 4000}}\ntest select-6.17 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection get -badopt foo\n} -result {bad option \"-badopt\": must be -displayof, -selection, or -type}\ntest select-6.18 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection get -selectionfoo foo\n} -result {bad option \"-selectionfoo\": must be -displayof, -selection, or -type}\ntest select-6.19 {Tk_SelectionCmd procedure} -body {\n    catch { destroy .f2 }\n    selection get -displayof .f2\n} -returnCodes error -result {bad window path name \".f2\"}\ntest select-6.20 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection get foo bar\n} -result {wrong # args: should be \"selection get ?-option value ...?\"}\ntest select-6.21 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection handle -type TEST .f1 {handler TEST}\n    selection handle -type STRING .f1 {handler STRING}\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection get TEST] $selInfo\n} -result {{Test value} {TEST 0 4000}}\n\n# selection handle\n# most of the handle section has been covered earlier\n\ntest select-6.22 {Tk_SelectionCmd procedure} -body {\n    selection handle -selection\n} -returnCodes error -result {value for \"-selection\" missing}\ntest select-6.23 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    set selValue \"Test value\"\n    set selInfo \"\"\n    list [selection handle -format INTEGER .f1 {handler TEST}] [selection get -displayof .f1] $selInfo\n} -result {{} {Test value} {TEST 0 4000}}\ntest select-6.24 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection handle -badopt foo\n} -result {bad option \"-badopt\": must be -format, -selection, or -type}\ntest select-6.25 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection handle -selectionfoo foo\n} -result {bad option \"-selectionfoo\": must be -format, -selection, or -type}\ntest select-6.26 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection handle\n} -result {wrong # args: should be \"selection handle ?-option value ...? window command\"}\ntest select-6.27 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection handle .\n} -result {wrong # args: should be \"selection handle ?-option value ...? window command\"}\ntest select-6.28 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection handle . foo bar baz blat\n} -result {wrong # args: should be \"selection handle ?-option value ...? window command\"}\ntest select-6.29 {Tk_SelectionCmd procedure} -body {\n    catch { destroy .f2 }\n    selection handle .f2 dummy\n} -returnCodes error -result {bad window path name \".f2\"}\n\n# selection own\n\ntest select-6.30 {Tk_SelectionCmd procedure} -body {\n    selection own -selection\n} -returnCodes error -result {value for \"-selection\" missing}\ntest select-6.31 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own .\n    selection own -displayof .f1\n} -result {.}\ntest select-6.32 {Tk_SelectionCmd procedure} -setup {\n    selectionSetup\n} -body {\n    selection own .\n    selection own -selection CLIPBOARD .f1\n    list [selection own] [selection own -selection CLIPBOARD]\n} -result {. .f1}\ntest select-6.33 {Tk_SelectionCmd procedure} -setup {\n    global lostSel\n    selectionSetup\n} -body {\n    set lostSel owned\n    selection own -command { set lostSel lost } .\n    selection own -selection CLIPBOARD .f1\n    set result $lostSel\n    selection own .f1\n    lappend result $lostSel\n} -result {owned lost}\ntest select-6.34 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection own -badopt foo\n} -result {bad option \"-badopt\": must be -command, -displayof, or -selection}\ntest select-6.35 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection own -selectionfoo foo\n} -result {bad option \"-selectionfoo\": must be -command, -displayof, or -selection}\ntest select-6.36 {Tk_SelectionCmd procedure} -body {\n    destroy .f2\n    selection own -displayof .f2\n} -returnCodes error -result {bad window path name \".f2\"}\ntest select-6.37 {Tk_SelectionCmd procedure} -body {\n    destroy .f2\n    selection own .f2\n} -returnCodes error -result {bad window path name \".f2\"}\ntest select-6.38 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection own foo bar baz\n} -result {wrong # args: should be \"selection own ?-option value ...? ?window?\"}\ntest select-6.39 {Tk_SelectionCmd procedure} -returnCodes error -body {\n    selection foo\n} -result {bad option \"foo\": must be clear, get, handle, or own}\n\n##############################################################################\n\n# This test is non-portable because some old X11/News servers ignore a\n# selection request when the window doesn't exist, which causes a different\n# error message.\ntest select-7.1 {TkSelDeadWindow procedure} -constraints nonPortable -setup {\n    selectionSetup\n} -body {\n    selection handle .f1 { handler TEST }\n    set result [selection own]\n    destroy .f1\n    lappend result [selection own] [catch {selection get} msg] $msg\n} -result {.f1 {} 1 {PRIMARY selection doesn't exist or form \"STRING\" not defined}}\n\n##############################################################################\n\n# Check reentrancy on losing selection\ntest select-8.1 {TkSelEventProc procedure} -constraints x11 -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    selection own -selection CLIPBOARD -command {destroy .f1} .f1\n    update\n    childTkProcess eval {selection own -selection CLIPBOARD .}\n    winfo children .\n} -cleanup {\n    childTkProcess exit\n} -result {}\n\n##############################################################################\n\ntest select-9.1 {SelCvtToX and SelCvtFromX procedures} -setup {\n    selectionSetup\n    childTkProcess create\n} -constraints x11 -body {\n    set selValue \"1024\"\n    set selInfo \"\"\n    selection handle -selection PRIMARY -format INTEGER -type TEST \\\n\t.f1 {handler TEST}\n    update\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{0x400 } {TEST 0 4000}}\ntest select-9.2 {SelCvtToX and SelCvtFromX procedures} -setup {\n    selectionSetup\n    childTkProcess create\n} -constraints {x11 failsOnCILinux} -body {\n    set selValue \"1024 0xffff  2048 -2  \"\n    set selInfo \"\"\n    selection handle -selection PRIMARY -format INTEGER -type TEST \\\n\t.f1 {handler TEST}\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{0x400 0xffff 0x800 0xfffffffe } {TEST 0 4000}}\ntest select-9.3 {SelCvtToX and SelCvtFromX procedures} -setup {\n    selectionSetup\n    childTkProcess create\n} -constraints {x11 failsOnCILinux} -body {\n    set selValue \"   \"\n    set selInfo \"\"\n    selection handle -selection PRIMARY -format INTEGER -type TEST \\\n\t.f1 {handler TEST}\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{ } {TEST 0 4000}}\ntest select-9.4 {SelCvtToX and SelCvtFromX procedures} -setup {\n    selectionSetup\n    childTkProcess create\n} -constraints {x11 failsOnCILinux} -body {\n    set selValue \"16 foobar 32\"\n    set selInfo \"\"\n    selection handle -selection PRIMARY -format INTEGER -type TEST \\\n\t.f1 {handler TEST}\n    set result \"\"\n    lappend result [childTkProcess eval {selection get TEST}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{0x10 0x0 0x20 } {TEST 0 4000}}\ntest select-9.5 {SelCvtToX and SelCvtFromX procedures} -setup {\n    selectionSetup\n    childTkProcess create\n} -constraints x11 -body {\n    # Ensure that lists of atoms are constructed correctly, even when the\n    # atom names have spaces in. [Bug 1353414]\n    set selValue \"foo bar\"\n    set selInfo \"\"\n    set selType {text/x-tk-test;detail=\"foo bar\"}\n    selection handle -selection PRIMARY -format STRING -type $selType \\\n    .f1 [list handler $selType]\n    lsort [childTkProcess eval {selection get TARGETS}]\n} -cleanup {\n    childTkProcess exit\n} -result {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW {text/x-tk-test;detail=\"foo bar\"}}\n\n##############################################################################\n# note, we are not testing MULTIPLE style selections\n\n# most control paths have been exercised above\n\ntest select-10.1 {ConvertSelection procedure, race with selection clear} -constraints {\n    x11\n} -setup {\n    selectionSetup\n} -body {\n    proc Ready {fd} {\n\tvariable x\n\tlappend x [gets $fd]\n    }\n    set fd [open \"|[list [interpreter] -geometry +0+0 -name tktest]\" r+]\n    puts $fd \"puts foo; [loadTkCommand]; flush stdout\"\n    flush $fd\n    gets $fd\n    fileevent $fd readable [list Ready $fd]\n    set selValue \"Just a simple test\"\n    set selInfo \"\"\n    selection handle .f1 {handler STRING}\n    update\n    puts $fd {puts \"[catch {selection get} msg]:$msg\"; puts **DONE**; flush stdout}\n    flush $fd\n    after 200\n    selection own .\n    set x {}\n    vwait [namespace which -variable x]\n    puts $fd {exit}\n    flush $fd\n    # Don't understand why, but the [loadTkCommand] above causes\n    # a \"broken pipe\" error when Tk was actually [load]ed in the child.\n    catch {close $fd}\n    lappend x $selInfo\n} -result {{1:PRIMARY selection doesn't exist or form \"STRING\" not defined} {}}\ntest select-10.2 {ConvertSelection procedure} -constraints x11 -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    set selValue [string range $longValue 0 3999]\n    set selInfo \"\"\n    selection handle .f1 {handler STRING}\n    set result \"\"\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result [list [string range $longValue 0 3999] {STRING 0 4000 STRING 4000 4000 STRING 0 4000 STRING 4000 4000}]\ntest select-10.3 {ConvertSelection procedure} -constraints x11 -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    selection handle .f1 ERROR errHandler\n    childTkProcess eval {selection get ERROR}\n} -cleanup {\n    childTkProcess exit\n} -result {PRIMARY selection doesn't exist or form \"ERROR\" not defined}\n\n# testing timers\n\n# This one hangs in Exceed\ntest select-10.4 {ConvertSelection procedure} -constraints {\n    x11 failsOnCILinux\n} -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {errIncrHandler STRING}\n    set result \"\"\n    set pass 0\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{selection owner didn't respond} {STRING 0 4000 STRING 4000 4000 STRING 8000 4000 STRING 12000 4000 STRING 16000 4000 STRING 0 4000 STRING 4000 4000}}\ntest select-10.5 {ConvertSelection procedure, reentrancy issues} -constraints {\n    x11 failsOnCILinux\n} -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    set selValue \"Test value\"\n    set selInfo \"\"\n    selection handle -type TEST .f1 { handler TEST }\n    selection handle -type STRING .f1 { badHandler .f1 STRING }\n    set result \"\"\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{PRIMARY selection doesn't exist or form \"STRING\" not defined} {.f1 STRING 0 4000}}\ntest select-10.6 {ConvertSelection procedure, reentrancy issues} -constraints {\n    x11 failsOnCILinux\n} -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    proc weirdHandler {type offset count} {\n\tdestroy .f1\n\thandler $type $offset $count\n    }\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {weirdHandler STRING}\n    set result \"\"\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -cleanup {\n    rename weirdHandler {}\n} -result {{PRIMARY selection doesn't exist or form \"STRING\" not defined} {STRING 0 4000}}\n\n##############################################################################\n\n# testing reentrancy\ntest select-11.1 {TkSelPropProc procedure} -constraints {x11 failsOnCILinux} -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle -type TEST .f1 { handler TEST }\n    selection handle -type STRING .f1 { reallyBadHandler .f1 STRING }\n    set result \"\"\n    set pass 0\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{selection owner didn't respond} {.f1 STRING 0 4000 .f1 STRING 4000 4000 .f1 STRING 8000 4000 .f1 STRING 12000 4000 .f1 STRING 16000 4000 .f1 STRING 0 4000 .f1 STRING 4000 4000}}\n\n##############################################################################\n\n# Note, this assumes we are using CurrentTtime\ntest select-12.1 {DefaultSelection procedure} -constraints x11 -body {\n    selectionSetup\n    set result [selection get -type TIMESTAMP]\n    childTkProcess create\n    lappend result [childTkProcess eval {selection get -type TIMESTAMP}]\n    childTkProcess exit\n    set result\n} -result {0x0 {0x0 }}\ntest select-12.2 {DefaultSelection procedure} -constraints x11 -body {\n    selectionSetup\n    set result [lsort [list [selection get -type TARGETS]]]\n    childTkProcess create\n    lappend result [childTkProcess eval {lsort [selection get -type TARGETS]}]\n    childTkProcess exit\n    set result\n} -result {{MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-12.3 {DefaultSelection procedure} -constraints x11 -body {\n    selectionSetup\n    selection handle .f1 {handler TEST} TEST\n    set result [list [lsort [selection get -type TARGETS]]]\n    childTkProcess create\n    lappend result [childTkProcess eval {lsort [selection get -type TARGETS]}]\n    childTkProcess exit\n    set result\n} -result {{MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}\ntest select-12.4 {DefaultSelection procedure} -constraints x11 -setup {\n    selectionSetup\n    set result \"\"\n} -body {\n    lappend result [selection get -type TK_APPLICATION]\n    childTkProcess create\n    lappend result [childTkProcess eval {selection get -type TK_APPLICATION}]\n    childTkProcess exit\n    set result\n} -result [list [winfo name .] [winfo name .]]\ntest select-12.5 {DefaultSelection procedure} -constraints x11 -body {\n    selectionSetup\n    set result [selection get -type TK_WINDOW]\n    childTkProcess create\n    lappend result [childTkProcess eval {selection get -type TK_WINDOW}]\n    childTkProcess exit\n    set result\n} -result {.f1 .f1}\ntest select-12.6 {DefaultSelection procedure} -body {\n    selectionSetup\n    selection handle .f1 {handler TARGETS.f1} TARGETS\n    set selValue \"Targets value\"\n    set selInfo \"\"\n    set result [list [selection get TARGETS] $selInfo]\n    selection handle .f1 {} TARGETS\n    lappend result [selection get TARGETS]\n} -result {{Targets value} {TARGETS.f1 0 4000} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}\n\ntest select-13.1 {SelectionSize procedure, handler deleted} -constraints {\n    x11 failsOnCILinux\n} -setup {\n    selectionSetup\n    childTkProcess create\n} -body {\n    set selValue $longValue\n    set selInfo \"\"\n    selection handle .f1 {badHandler2 .f1 STRING}\n    set result \"\"\n    set abortCount 2\n    lappend result [childTkProcess eval {selection get}]\n    childTkProcess exit\n    lappend result $selInfo\n} -result {{PRIMARY selection doesn't exist or form \"STRING\" not defined} {.f1 STRING 0 4000 .f1 STRING 4000 4000}}\n\ntest select-14.1 {Bug [73ba07efcd]: Use correct property type when handling MULTIPLE conversion requests} -constraints {\n    cliboardManagerPresent\n} -setup {\n    proc get_clip {offset maxChars} {return abcd}\n} -body {\n    selection handle -selection CLIPBOARD . get_clip\n    selection own -selection CLIPBOARD .\n    selection get -selection CLIPBOARD_MANAGER -type SAVE_TARGETS\n    clipboard get\n} -cleanup {\n    rename get_clip {}\n} -result {abcd}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget child select\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/send.test",
    "content": "# This file is a Tcl script to test out the \"send\" command and the\n# other procedures in the file tkSend.c.\n#\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2001 ActiveState Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n# NOTES\n#\n# This test file is platform-indifferent. Tests regarding the send command\n# that are specific to the windows platform go into the test file winSend.test.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed for \"-singleproc 0\"\n\n# Load the main script \"main.tcl\", which takes care of:\n# - setup for the application and the root window\n# - loading and configuration of the tcltest test harness\n# - loading of the testutils mechanism together with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\n\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\ntcltest::loadTestedCommands\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint xhost [llength [auto_execok xhost]]\n\n#\n# COMMON TEST SETUP\n#\n\nset name [tk appname]\nset commId \"\"\ncatch {\n    set registry [testsend prop root InterpRegistry]\n    set commId [lindex [testsend prop root InterpRegistry] 0]\n}\ntk appname tktest\ncatch {send t_s_1 destroy .}\ncatch {send t_s_2 destroy .}\n\n#\n# TESTS\n#\n\ntest send-1.1 {RegOpen procedure, bogus property} {secureserver testsend} {\n    testsend bogus\n    set result [winfo interps]\n    tk appname tktest\n    list $result [winfo interps]\n} {{} tktest}\ntest send-1.2 {RegOpen procedure, bogus property} {secureserver testsend} {\n    testsend prop root InterpRegistry {}\n    set result [winfo interps]\n    tk appname tktest\n    list $result [winfo interps]\n} {{} tktest}\ntest send-1.3 {RegOpen procedure, bogus property} {secureserver testsend} {\n    testsend prop root InterpRegistry abcdefg\n    tk appname tktest\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" tktest\\nabcdefg\\n\"\n\n#\n# COMMON TEST SETUP\n#\n\nframe .f -width 1 -height 1\nset id [string range [winfo id .f] 2 end]\n\ntest send-2.1 {RegFindName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry {}\n    list [catch {send foo bar} msg] $msg\n} {1 {no application named \"foo\"}}\ntest send-2.2 {RegFindName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \" abc\\n def\\nghi\\n\\n$id foo\\n\"\n    tk appname foo\n} {foo #2}\ntest send-2.3 {RegFindName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"gyz foo\\n\"\n    tk appname foo\n} {foo}\ntest send-2.4 {RegFindName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"${id}z foo\\n\"\n    tk appname foo\n} {foo}\n\ntest send-3.1 {RegDeleteName procedure} {secureserver testsend} {\n    tk appname tktest\n    testsend prop root InterpRegistry \"012345 gorp\\n12345 foo\\n12345 tktest\"\n    tk appname x\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" x\\n012345 gorp\\n12345 foo\\n\"\ntest send-3.2 {RegDeleteName procedure} {secureserver testsend} {\n    tk appname tktest\n    testsend prop root InterpRegistry \"012345 gorp\\n12345 tktest\\n23456 tktest\"\n    tk appname x\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" x\\n012345 gorp\\n23456 tktest\\n\"\ntest send-3.3 {RegDeleteName procedure} {secureserver testsend} {\n    tk appname tktest\n    testsend prop root InterpRegistry \"012345 tktest\\n12345 bar\\n23456 tktest\"\n    tk appname x\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" x\\n12345 bar\\n23456 tktest\\n\"\ntest send-3.4 {RegDeleteName procedure} {secureserver testsend} {\n    tk appname tktest\n    testsend prop root InterpRegistry \"foo\"\n    tk appname x\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" x\\nfoo\\n\"\ntest send-3.5 {RegDeleteName procedure} {secureserver testsend} {\n    tk appname tktest\n    testsend prop root InterpRegistry \"\"\n    tk appname x\n    set x [testsend prop root InterpRegistry]\n    string range $x [string first \" \" $x] end\n} \" x\\n\"\n\ntest send-4.1 {RegAddName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"\"\n    tk appname bar\n    testsend prop root InterpRegistry\n} \"$commId bar\\n\"\ntest send-4.2 {RegAddName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"abc def\"\n    tk appname bar\n    tk appname foo\n    testsend prop root InterpRegistry\n} \"$commId foo\\nabc def\\n\"\n\n# Previous checks should already cover the Regclose procedure.\n\ntest send-5.1 {ValidateName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"123 abc\\n\"\n    winfo interps\n} {}\ntest send-5.2 {ValidateName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"$id Hi there\"\n    winfo interps\n} {{Hi there}}\ntest send-5.3 {ValidateName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"$id Bogus\"\n    list [catch {send Bogus set a 44} msg] $msg\n} {1 {target application died or uses a Tk version before 4.0}}\ntest send-5.4 {ValidateName procedure} {secureserver testsend} {\n    tk appname test\n    testsend prop root InterpRegistry \"$commId Bogus\\n$commId test\\n\"\n    winfo interps\n} {test}\n\n#\n# COMMON TEST SETUP\n#\n# For tests send-6.*\n#\n\nif {[testConstraint nonPortable] && [testConstraint xhost] && [testConstraint notAqua]} {\n    winfo interps\n    tk appname tktest\n    update\n    childTkProcess create\n    set x [split [exec xhost] \\n]\n    foreach i [lrange $x 1 end]  {\n\texec xhost - $i\n    }\n}\n\n# For aqua, just start the child Tk process.\nif {[testConstraint aqua]} {\n    childTkProcess create\n}\n\ntest send-6.1 {ServerSecure procedure} {nonPortable secureserver notAqua} {\n    set a 44\n    list [childTkProcess eval [list send [tk appname] set a 55]] $a\n} {55 55}\ntest send-6.2 {ServerSecure procedure} {nonPortable secureserver xhost notAqua} {\n    set a 22\n    exec xhost [exec hostname]\n    list [catch {childTkProcess eval [list send [tk appname] set a 33]} msg] $a $msg\n} {0 22 {X server insecure (must use xauth-style authorization); command ignored}}\ntest send-6.3 {ServerSecure procedure} {nonPortable secureserver xhost notAqua} {\n    set a abc\n    exec xhost - [exec hostname]\n    list [childTkProcess eval [list send [tk appname] set a new]] $a\n} {new new}\n\n#\n# COMMON TEST CLEANUP\n#\nchildTkProcess exit\n\ntest send-7.1 {Tk_SetAppName procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \"\"\n    tk appname newName\n    list [tk appname oldName] [testsend prop root InterpRegistry]\n} \"oldName {$commId oldName\\n}\"\ntest send-7.2 {Tk_SetAppName procedure, name not in use} {secureserver testsend} {\n    testsend prop root InterpRegistry \"\"\n    list [tk appname gorp] [testsend prop root InterpRegistry]\n} \"gorp {$commId gorp\\n}\"\ntest send-7.3 {Tk_SetAppName procedure, name in use by us} {secureserver testsend} {\n    tk appname name1\n    testsend prop root InterpRegistry \"$commId name2\\n\"\n    list [tk appname name2] [testsend prop root InterpRegistry]\n} \"name2 {$commId name2\\n}\"\ntest send-7.4 {Tk_SetAppName procedure, name in use} {secureserver testsend} {\n    tk appname name1\n    testsend prop root InterpRegistry \"$id foo\\n$id foo #2\\n$id foo #3\\n\"\n    list [tk appname foo] [testsend prop root InterpRegistry]\n} \"{foo #4} {$commId foo #4\\n$id foo\\n$id foo #2\\n$id foo #3\\n}\"\n\n# This passes on real macOS systems but fails on macOS CI runners because\n# AppleScript cannot be enabled on the runner.\ntest send-8.1 {Tk_SendCmd procedure, options} {secureserver notMacCI} {\n    childTkProcess create\n    set app [childTkProcess eval {tk appname}]\n    set a 66\n    send -async $app [list send [tk appname] set a 77]\n    set result $a\n    after 200 set x 40\n    tkwait variable x\n    childTkProcess exit\n    lappend result $a\n} {66 77}\ntest send-8.2 {Tk_SendCmd procedure, options} {secureserver altDisplay} {\n    childTkProcess create -display $env(TK_ALT_DISPLAY)\n    tk appname xyzgorp\n    set a homeDisplay\n    set result [childTkProcess eval \"\n    toplevel .t -screen [winfo screen .]\n    wm geometry .t +0+0\n    set a altDisplay\n    tk appname xyzgorp\n    list \\[send xyzgorp set a\\] \\[send -displayof .t xyzgorp set a\\]\n    \"]\n    childTkProcess exit\n    set result\n} {altDisplay homeDisplay}\n\ntest send-8.3 {Tk_SendCmd procedure, options} {secureserver} {\n    list [catch {send -- -async foo bar baz} msg] $msg\n} {1 {no application named \"-async\"}}\ntest send-8.4 {Tk_SendCmd procedure, options} {secureserver} {\n    list [catch {send -gorp foo bar baz} msg] $msg\n} {1 {bad option \"-gorp\": must be -async, -displayof, or --}}\ntest send-8.5 {Tk_SendCmd procedure, options} {secureserver} {\n    list [catch {send -async foo} msg] $msg\n} {1 {wrong # args: should be \"send ?-option value ...? interpName arg ?arg ...?\"}}\ntest send-8.6 {Tk_SendCmd procedure, options} {secureserver} {\n    list [catch {send foo} msg] $msg\n} {1 {wrong # args: should be \"send ?-option value ...? interpName arg ?arg ...?\"}}\ntest send-8.7 {Tk_SendCmd procedure, local execution} {secureserver} {\n    set a initial\n    send [tk appname] {set a new}\n    set a\n} {new}\ntest send-8.8 {Tk_SendCmd procedure, local execution} {secureserver} {\n    set a initial\n    send [tk appname] set a new\n    set a\n} {new}\ntest send-8.9 {Tk_SendCmd procedure, local execution} {secureserver} {\n    set a initial\n    string tolower [list [catch {send [tk appname] open bad_file} msg] \\\n\t    $msg $errorInfo $errorCode]\n} {1 {couldn't open \"bad_file\": no such file or directory} {couldn't open \"bad_file\": no such file or directory\n    while executing\n\"open bad_file\"\n    invoked from within\n\"send [tk appname] open bad_file\"} {posix enoent {no such file or directory}}}\ntest send-8.10 {Tk_SendCmd procedure, no such interpreter} {secureserver} {\n    list [catch {send bogus_name bogus_command} msg] $msg\n} {1 {no application named \"bogus_name\"}}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {\n    childTkInterp t_s_1 -class Test\n    t_s_1 eval wm withdraw .\n}\n\ntest send-8.11 {Tk_SendCmd procedure, local execution, different interp} {secureserver testsend} {\n    set a us\n    send t_s_1 set a them\n    list $a [send t_s_1 set a]\n} {us them}\ntest send-8.12 {Tk_SendCmd procedure, local execution, different interp} {secureserver testsend} {\n    set a us\n    send t_s_1 {set a them}\n    list $a [send t_s_1 {set a}]\n} {us them}\ntest send-8.13 {Tk_SendCmd procedure, local execution, different interp} {secureserver testsend} {\n    set a us\n    send t_s_1 {set a them}\n    list $a [send t_s_1 {set a}]\n} {us them}\ntest send-8.14 {Tk_SendCmd procedure, local interp killed by send} -constraints {secureserver testsend} -body {\n    childTkInterp t_s_2 -class Test\n    list [catch {send t_s_2 {destroy .; concat result}} msg] $msg\n} -cleanup {\n    catch {interp delete t_s_2}\n} -result {0 result}\ntest send-8.15 {Tk_SendCmd procedure, local interp, error info} {secureserver testsend failsOnCILinux} {\n    catch {error foo}\n    list [catch {send t_s_1 {if 1 {open bogus_file_name}}} msg] $msg $errorInfo $errorCode\n} {1 {couldn't open \"bogus_file_name\": no such file or directory} {couldn't open \"bogus_file_name\": no such file or directory\n    while executing\n\"open bogus_file_name\"\n    invoked from within\n\"if 1 {open bogus_file_name}\"\n    invoked from within\n\"send t_s_1 {if 1 {open bogus_file_name}}\"} {POSIX ENOENT {no such file or directory}}}\ntest send-8.16 {Tk_SendCmd procedure, bogusCommWindow} {secureserver testsend failsOnCILinux failsOnXQuartz} {\n    testsend prop root InterpRegistry \"10234 bogus\\n\"\n    set result [list [catch {send bogus bogus command} msg] $msg]\n    winfo interps\n    tk appname tktest\n    set result\n} {1 {no application named \"bogus\"}}\n\n#\n# COMMON TEST CLEANUP\n#\ncatch {interp delete t_s_1}\n\ntest send-8.17 {Tk_SendCmd procedure, deferring events} {secureserver nonPortable notAqua} {\n    # Non-portable because some window managers ignore \"raise\"\n    # requests so can't guarantee that new app's window won't\n    # obscure .f, thereby masking the Expose event.\n\n    childTkProcess create\n    set app [childTkProcess eval {tk appname}]\n    raise .\t\t; # Don't want new app obscuring .f\n    catch {destroy .f}\n    frame .f\n    place .f -x 0 -y 0\n    bind .f <Expose> {set a exposed}\n    set a {no event yet}\n    set result \"\"\n    lappend result [send $app send [list [tk appname]] set a]\n    lappend result $a\n    update\n    childTkProcess exit\n    lappend result $a\n} {{no event yet} {no event yet} exposed}\n\nif {[testConstraint aqua]} {\n    set result_8_18 {1 {couldn't open \"bad_name\": no such file or directory} {couldn't open \"bad_name\": no such file or directory\n    invoked from within\n\"send $app open bad_name\"} {couldn't open \"bad_name\": no such file or directory}}\n} else {\n    set result_8_18 {1 {couldn't open \"bad_name\": no such file or directory} {couldn't open \"bad_name\": no such file or directory\n    while executing\n\"open bad_name\"\n    invoked from within\n\"send $app open bad_name\"} {posix enoent {no such file or directory}}}\n}\n\n# This passes on real macOS systems but fails on macOS CI runners because\n# AppleScript cannot be enabled on the runner.\ntest send-8.18 {Tk_SendCmd procedure, error in remote app} {secureserver notMacCI} {\n    childTkProcess create\n    set app [childTkProcess eval {tk appname}]\n    set result [string tolower [list [catch {send $app open bad_name} msg] \\\n\t    $msg $errorInfo $errorCode]]\n    childTkProcess exit\n    set result\n} $result_8_18\n\n# This passes on real macOS systems but fails on macOS CI runners\n# because AppleScript cannot be enabled on the runner.  However, on\n# real macOS systems it produces a different result than on X11\n# because the event loop is re-entered when running the send command\n# on macOS.\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    set result_8_19 {{x y z} yes yes}\n} else {\n    set result_8_19 {{x y z} no yes}\n}\n\ntest send-8.19 {Tk_SendCmd, using modal timeouts} {secureserver notMacCI} {\n    childTkProcess create\n    set app [childTkProcess eval {tk appname}]\n    set x no\n    set result \"\"\n    after 0 {set x yes}\n    # On X11 the after 0 command runs after these calls.\n    lappend result [send $app {concat x y z}]\n    lappend result $x\n    update\n    childTkProcess exit\n    lappend result $x\n} $result_8_19\n\n#\n# COMMON TEST SETUP\n#\n\ntk appname tktest\ncatch {destroy .f}\nframe .f\nset id [string range [winfo id .f] 2 end]\n\ntest send-9.1 {Tk_GetInterpNames procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \\\n\t    \"$commId tktest\\nfoo bar\\n$commId tktest\\n$id frame .f\\n\\n\\n\"\n    list [winfo interps] [testsend prop root InterpRegistry]\n} \"{tktest tktest {frame .f}} {$commId tktest\\n$commId tktest\\n$id frame .f\n}\"\ntest send-9.2 {Tk_GetInterpNames procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry \\\n\t    \"$commId tktest\\nfoobar\\n$commId gorp\\n\"\n    list [winfo interps] [testsend prop root InterpRegistry]\n} \"tktest {$commId tktest\\n}\"\ntest send-9.3 {Tk_GetInterpNames procedure} {secureserver testsend} {\n    testsend prop root InterpRegistry {}\n    list [winfo interps] [testsend prop root InterpRegistry]\n} {{} {}}\n\n#\n# COMMON TEST SETUP\n#\ncatch {testsend prop root InterpRegistry \"$commId tktest\\n$id dummy\\n\"}\n\ntest send-10.1 {SendEventProc procedure, bogus comm property} {secureserver testsend} {\n    testsend prop comm Comm {abc def}\n    testsend prop comm Comm {}\n    update\n} {}\ntest send-10.2 {SendEventProc procedure, simultaneous messages} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-s set a 44\\nc\\n-n tktest\\n-s set b 45\\n\"\n    set a null\n    set b xyzzy\n    update\n    list $a $b\n} {44 45}\ntest send-10.3 {SendEventProc procedure, simultaneous messages} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-s set a newA\\nr\\n-s [testsend serial]\\n-r 12345\\nc\\n-n tktest\\n-s set b newB\\n\"\n    set a null\n    set b xyzzy\n    set x [send dummy bogus]\n    list $x $a $b\n} {12345 newA newB}\ntest send-10.4 {SendEventProc procedure, leading nulls, bogus commands} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"\\n\\nx\\n-bogus\\n\\nc\\n-n tktest\\n-s set a 44\\n\"\n    set a null\n    update\n    set a\n} 44\ntest send-10.5 {SendEventProc procedure, extraneous command options} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-x miscellanous\\n-y who knows?\\n-s set a new\\n\"\n    set a null\n    update\n    set a\n} new\ntest send-10.6 {SendEventProc procedure, unknown interpreter} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n unknown\\n-r $id 44\\n-s set a new\\n\"\n    set a null\n    update\n    list [testsend prop [winfo id .f] Comm] $a\n} \"{\\nr\\n-s 44\\n-r receiver never heard of interpreter \\\"unknown\\\"\\n-c 1\\n} null\"\ntest send-10.7 {SendEventProc procedure, error in script} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-r $id 62\\n-s foreach i {1 2 3} {error {test error} {Initial errorInfo} {test code}}\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} {\nr\n-s 62\n-r test error\n-i Initial errorInfo\n    (\"foreach\" body line 1)\n    invoked from within\n\"foreach i {1 2 3} {error {test error} {Initial errorInfo} {test code}}\"\n-e test code\n-c 1\n}\ntest send-10.8 {SendEventProc procedure, exceptional return} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-r $id 62\\n-s break\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} \"\\nr\\n-s 62\\n-r \\n-c 3\\n\"\ntest send-10.9 {SendEventProc procedure, empty return} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-r $id 62\\n-s concat\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} \"\\nr\\n-s 62\\n-r \\n\"\ntest send-10.10 {SendEventProc procedure, asynchronous calls} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-s foreach i {1 2 3} {error {test error} {Initial errorInfo} {test code}}\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} {}\ntest send-10.11 {SendEventProc procedure, exceptional return} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-s break\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} {}\ntest send-10.12 {SendEventProc procedure, empty return} {secureserver testsend} {\n    testsend prop [winfo id .f] Comm {}\n    testsend prop comm Comm \\\n\t    \"c\\n-n tktest\\n-s concat\\n\"\n    update\n    testsend prop [winfo id .f] Comm\n} {}\ntest send-10.13 {SendEventProc procedure, return processing} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"r\\n-c 1\\n-e test1\\n-i test2\\n-r test3\\n-s [testsend serial]\\n\"\n    list [catch {send dummy foo} msg] $msg $errorInfo $errorCode\n} {1 test3 {test2\n    invoked from within\n\"send dummy foo\"} test1}\ntest send-10.14 {SendEventProc procedure, extraneous return options} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"r\\n-x test1\\n-y test2\\n-r result\\n-s [testsend serial]\\n\"\n    list [catch {send dummy foo} msg] $msg\n} {0 result}\ntest send-10.15 {SendEventProc procedure, serial number} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"r\\n-r response\\n\"\n    list [catch {send dummy foo} msg] $msg\n} {1 {target application died or uses a Tk version before 4.0}}\ntest send-10.16 {SendEventProc procedure, serial number} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"r\\n-r response\\n\\n-s 0\"\n    list [catch {send dummy foo} msg] $msg\n} {1 {target application died or uses a Tk version before 4.0}}\ntest send-10.17 {SendEventProc procedure, errorCode and errorInfo} {secureserver testsend} {\n    testsend prop comm Comm \\\n\t    \"r\\n-i test1\\n-e test2\\n-c 4\\n-s [testsend serial]\\n\"\n    set errorCode oldErrorCode\n    set errorInfo oldErrorInfo\n    list [catch {send dummy foo} msg] $msg $errorInfo $errorCode\n} {4 {} oldErrorInfo oldErrorCode}\ntest send-10.18 {SendEventProc procedure, send kills application} {secureserver testsend} {\n    childTkProcess create\n    childTkProcess eval {tk appname t_s_3}\n    set x [list [catch {send t_s_3 destroy .} msg] $msg]\n    childTkProcess exit\n    set x\n} {0 {}}\ntest send-10.19 {SendEventProc procedure, send exits} {secureserver testsend} {\n    childTkProcess create\n    childTkProcess eval {tk appname t_s_3}\n    set x [list [catch {send t_s_3 exit} msg] $msg]\n    childTkProcess exit\n    set x\n} {1 {target application died}}\n\ntest send-11.1 {AppendPropCarefully and AppendErrorProc procedures} -constraints {secureserver testsend} -body {\n    testsend prop root InterpRegistry \"0x21447 dummy\\n\"\n    send dummy foo\n} -returnCodes 1 -match regexp -result {^(target application died|no application named \"dummy\")$}\ntest send-11.2 {AppendPropCarefully and AppendErrorProc procedures} {secureserver testsend} {\n    testsend prop comm Comm \"c\\n-r0x123 44\\n-n tktest\\n-s concat a b c\\n\"\n    update\n} {}\n\n#\n# COMMON TEST SETUP\n#\nwinfo interps\ntk appname tktest\n\ntest send-12.1 {TimeoutProc procedure} -constraints {secureserver testsend} -setup {\n    catch {destroy .f}\n    frame .f\n    set id [string range [winfo id .f] 2 end]\n} -body {\n    testsend prop root InterpRegistry \"$id dummy\\n\"\n    list [catch {send dummy foo} msg] $msg\n} -cleanup {\n    unset id\n    destroy .f\n} -result {1 {target application died or uses a Tk version before 4.0}}\n\n#\n# COMMON TEST CLEANUP\n#\n\ncatch {testsend prop root InterpRegistry \"\"}\n\ntest send-12.2 {TimeoutProc procedure} {secureserver} {\n    winfo interps\n    tk appname tktest\n    update\n    childTkProcess create\n    set app [childTkProcess eval {\n\tafter 10 {after 10 {after 5000; exit}}\n\ttk appname\n    }]\n    after 200\n    set result [list [catch {send $app foo} msg] $msg]\n    childTkProcess exit\n    set result\n} {1 {target application died}}\n\n#\n# COMMON TEST SETUP\n#\n\nwinfo interps\ntk appname tktest\n\ntest send-13.1 {DeleteProc procedure} -constraints {secureserver} -body {\n    childTkProcess create\n    set app [childTkProcess eval {rename send {}; tk appname}]\n    set result [list [catch {send $app foo} msg] $msg [winfo interps]]\n    childTkProcess exit\n    set result\n}  -match regexp -result {1 {no application named \"tktest[0-9]+\"} tktest}\n\ntest send-13.2 {DeleteProc procedure} {secureserver} {\n    winfo interps\n    tk appname tktest\n    rename send {}\n    set result {}\n    lappend result [winfo interps] [info commands send]\n    tk appname foo\n    lappend result [winfo interps] [info commands send]\n} {{} {} foo send}\n\ntest send-14.1 {SendRestrictProc procedure, sends crossing from different displays} {secureserver altDisplay} {\n    childTkProcess create -display $env(TK_ALT_DISPLAY)\n    set result [childTkProcess eval \"\n    toplevel .t -screen [winfo screen .]\n    wm geometry .t +0+0\n    tk appname xyzgorp1\n    set x child\n    \"]\n    toplevel .t -screen $env(TK_ALT_DISPLAY)\n    wm geometry .t +0+0\n    tk appname xyzgorp2\n    update\n    set y parent\n    set result [send -displayof .t xyzgorp1 {list $x [send -displayof .t xyzgorp2 set y]}]\n    destroy .t\n    childTkProcess exit\n    set result\n} {child parent}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {\n    testsend prop root InterpRegister $registry\n    tk appname tktest\n}\n\ntest send-15.1 {UpdateCommWindow procedure} {secureserver testsend} {\n    set x [list [testsend prop comm TK_APPLICATION]]\n    childTkInterp t_s_1 -class Test\n    send t_s_1 wm withdraw .\n    childTkInterp t_s_2 -class Test\n    send t_s_2 wm withdraw .\n    lappend x [testsend prop comm TK_APPLICATION]\n    interp delete t_s_1\n    lappend x [testsend prop comm TK_APPLICATION]\n    interp delete t_s_2\n    lappend x [testsend prop comm TK_APPLICATION]\n} {tktest {t_s_2 t_s_1 tktest} {t_s_2 tktest} tktest}\n\n# This passes on real macOS systems but fails on macOS CI runners because\n# AppleScript cannot be enabled on the runner.\ntest send-16.1 {set variable - app in child interpreter} {unix notMacCI} {\n    set a \"a\"\n    childTkInterp t_s_1 -class Test\n    set app [t_s_1 eval {tk appname}]\n    set result {}\n    catch {send $app {set a}} msg\n    lappend result $msg\n    lappend result [send $app {set a 25}]\n    lappend result [set a]\n    interp delete t_s_1\n    set result\n} {{can't read \"a\": no such variable} 25 a}\n\n# This passes on real macOS systems but fails on macOS CI runners because\n# AppleScript cannot be enabled on the runner.\ntest send-16.2 {recursive send - app in child process} {unix notMacCI} {\n    childTkProcess create\n    set a no\n    set this [tk appname]\n    set that [childTkProcess eval {tk appname}]\n    catch {send $that \"send {$this} set a yes\"} result\n    childTkProcess exit\n    set result\n} {yes}\n\n# This passes on real macOS systems but fails on macOS CI runners because\n# AppleScript cannot be enabled on the runner.\ntest send-17.1 {set variable - app in child process} {unix notMacCI} {\n    set a \"a\"\n    childTkProcess create\n    set app [childTkProcess eval {tk appname}]\n    set result {}\n    catch {send $app {set a}} msg\n    lappend result $msg\n    lappend result [send $app {set a 25}]\n    lappend result [set a]\n    childTkProcess exit\n    set result\n} {{can't read \"a\": no such variable} 25 a}\n\n#\n# TESTFILE CLEANUP\n#\n\ncatch {\n    tk appname $name\n    testsend prop root InterpRegistry $registry\n    testdeleteapps\n}\n\ntestutils forget child\ncleanupTests\n"
  },
  {
    "path": "tests/spinbox.test",
    "content": "# This file is a Tcl script to test spinbox widgets in Tk.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# Collected comments about lacks from the test\n# - Still need to write tests for SpinboxBlinkProc, SpinboxFocusProc,\n#   and SpinboxTextVarProc.\n# - No tests for DisplaySpinbox.\n# - Still need to write tests for SpinboxScanTo and SpinboxSelectTo.\n# - No tests for EventuallyRedraw\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import entry scroll\n\n#\n# COMMON TEST SETUP\n#\n\nforeach i {1 2 3} {\n    set validateCmd$i [list validateCommand$i %W %d %i %P %s %S %v %V]\n}\nset cy [font metrics {Courier -12} -linespace]\n\n#\n# TESTS\n#\n\ntest spinbox-1.1 {configuration option: \"activebackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t    -relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -activebackground #ff0000\n    .e cget -activebackground\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest spinbox-1.2 {configuration option: \"activebackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t    -relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -activebackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.3 {configuration option: \"background\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t    -relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -background #ff0000\n    .e cget -background\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest spinbox-1.4 {configuration option: \"background\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -background non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.5 {configuration option: \"bd\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -bd 4\n    .e cget -bd\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-1.6 {configuration option: \"bd\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -bd badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest spinbox-1.7 {configuration option: \"bg\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -bg #ff0000\n    .e cget -bg\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest spinbox-1.8 {configuration option: \"bg\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -bg non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.9 {configuration option: \"borderwidth\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -borderwidth 1.3\n    .e cget -borderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest spinbox-1.10 {configuration option: \"borderwidth\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -borderwidth badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest spinbox-1.11 {configuration option: \"buttonbackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -buttonbackground #ff0000\n    .e cget -buttonbackground\n} -cleanup {\n    destroy .e\n} -result {#ff0000}\ntest spinbox-1.12 {configuration option: \"buttonbackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -buttonbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.13 {configuration option: \"buttoncursor\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -buttoncursor arrow\n    .e cget -buttoncursor\n} -cleanup {\n    destroy .e\n} -result {arrow}\ntest spinbox-1.14 {configuration option: \"buttoncursor\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -buttoncursor badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest spinbox-1.15 {configuration option: \"command\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -command {a command}\n    .e cget -command\n} -cleanup {\n    destroy .e\n} -result {a command}\n\ntest spinbox-1.16 {configuration option: \"cursor\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -cursor arrow\n    .e cget -cursor\n} -cleanup {\n    destroy .e\n} -result {arrow}\ntest spinbox-1.17 {configuration option: \"cursor\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -cursor badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad cursor spec \"badValue\"}\n\ntest spinbox-1.18 {configuration option: \"disabledbackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -disabledbackground green\n    .e cget -disabledbackground\n} -cleanup {\n    destroy .e\n} -result {green}\ntest spinbox-1.19 {configuration option: \"disabledbackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -disabledbackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.20 {configuration option: \"disabledforeground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -disabledforeground #110022\n    .e cget -disabledforeground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest spinbox-1.21 {configuration option: \"disabledforeground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -disabledforeground bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.22 {configuration option: \"exportselection\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -exportselection yes\n    .e cget -exportselection\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-1.23 {configuration option: \"exportselection\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -exportselection xyzzy\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected boolean value but got \"xyzzy\"}\n\ntest spinbox-1.24 {configuration option: \"fg\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -fg #110022\n    .e cget -fg\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest spinbox-1.25 {configuration option: \"fg\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -fg bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.26 {configuration option: \"font\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -font -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*\n    .e cget -font\n} -cleanup {\n    destroy .e\n} -result {-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*}\ntest spinbox-1.27 {configuration option: \"font\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -font {}\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {font \"\" does not exist}\n\ntest spinbox-1.28 {configuration option: \"foreground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -foreground #110022\n    .e cget -foreground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest spinbox-1.29 {configuration option: \"foreground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -foreground bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.30 {configuration option: \"format\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -format %0.5f\n    .e cget -format\n} -cleanup {\n    destroy .e\n} -result {%0.5f}\ntest spinbox-1.31 {configuration option: \"format\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -format %d\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox format specifier \"%d\"}\n\ntest spinbox-1.32 {configuration option: \"from\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -from -10\n    .e cget -from\n} -cleanup {\n    destroy .e\n} -result {-10.0}\ntest spinbox-1.33 {configuration option: \"from\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -from bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"bogus\"}\n\ntest spinbox-1.34 {configuration option: \"highlightbackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightbackground #123456\n    .e cget -highlightbackground\n} -cleanup {\n    destroy .e\n} -result {#123456}\ntest spinbox-1.35 {configuration option: \"highlightbackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightbackground ugly\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"ugly\"}\n\ntest spinbox-1.36 {configuration option: \"highlightcolor\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightcolor #123456\n    .e cget -highlightcolor\n} -cleanup {\n    destroy .e\n} -result {#123456}\ntest spinbox-1.37 {configuration option: \"highlightcolor\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightcolor bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.38 {configuration option: \"highlightthickness\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightthickness 6\n    .e cget -highlightthickness\n} -cleanup {\n    destroy .e\n} -result 6\ntest spinbox-1.39 {configuration option: \"highlightthickness\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightthickness bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"bogus\"}\n\ntest spinbox-1.40 {configuration option: \"highlightthickness\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -highlightthickness -2\n    .e cget -highlightthickness\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"-2\"}\n\ntest spinbox-1.41 {configuration option: \"increment\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -increment 1.0\n    .e cget -increment\n} -cleanup {\n    destroy .e\n} -result {1.0}\ntest spinbox-1.42 {configuration option: \"increment\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -increment bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"bogus\"}\n\ntest spinbox-1.43 {configuration option: \"insertbackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertbackground #110022\n    .e cget -insertbackground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest spinbox-1.44 {configuration option: \"insertbackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertbackground bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.45 {configuration option: \"insertborderwidth\"} -setup {\n    spinbox .e -borderwidth 2 -insertwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertborderwidth 1.3\n    .e cget -insertborderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest spinbox-1.46 {configuration option: \"insertborderwidth\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertborderwidth 2.6x\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"2.6x\"}\n\ntest spinbox-1.47 {configuration option: \"insertofftime\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertofftime 100\n    .e cget -insertofftime\n} -cleanup {\n    destroy .e\n} -result 100\ntest spinbox-1.48 {configuration option: \"insertofftime\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertofftime 3.2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3.2\"}\n\ntest spinbox-1.49 {configuration option: \"insertontime\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertontime 100\n    .e cget -insertontime\n} -cleanup {\n    destroy .e\n} -result 100\ntest spinbox-1.50 {configuration option: \"insertontime\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -insertontime 3.2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3.2\"}\n\ntest spinbox-1.51 {configuration option: \"invalidcommand\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -invalidcommand \"a command\"\n    .e cget -invalidcommand\n} -cleanup {\n    destroy .e\n} -result {a command}\n\ntest spinbox-1.52 {configuration option: \"invcmd\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -invcmd \"a command\"\n    .e cget -invcmd\n} -cleanup {\n    destroy .e\n} -result {a command}\n\ntest spinbox-1.53 {configuration option: \"justify\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -justify right\n    .e cget -justify\n} -cleanup {\n    destroy .e\n} -result {right}\ntest spinbox-1.54 {configuration option: \"justify\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -justify bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad justification \"bogus\": must be left, right, or center}\n\ntest spinbox-1.55 {configuration option: \"readonlybackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -readonlybackground green\n    .e cget -readonlybackground\n} -cleanup {\n    destroy .e\n} -result {green}\ntest spinbox-1.56 {configuration option: \"readonlybackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -readonlybackground non-existent\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"non-existent\"}\n\ntest spinbox-1.57 {configuration option: \"relief\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -relief groove\n    .e cget -relief\n} -cleanup {\n    destroy .e\n} -result {groove}\ntest spinbox-1.58 {configuration option: \"relief\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -relief 1.5\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad relief \"1.5\": must be flat, groove, raised, ridge, solid, or sunken}\n\ntest spinbox-1.59 {configuration option: \"repeatdelay\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -repeatdelay 500\n    .e cget -repeatdelay\n} -cleanup {\n    destroy .e\n} -result 500\ntest spinbox-1.60 {configuration option: \"repeatdelay\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -repeatdelay 3p\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3p\"}\n\ntest spinbox-1.61 {configuration option: \"repeatinterval\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -repeatinterval -500\n    .e cget -repeatinterval\n} -cleanup {\n    destroy .e\n} -result -500\ntest spinbox-1.62 {configuration option: \"repeatinterval\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -repeatinterval 3p\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3p\"}\n\ntest spinbox-1.63 {configuration option: \"selectbackground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectbackground #110022\n    .e cget -selectbackground\n} -cleanup {\n    destroy .e\n} -result {#110022}\ntest spinbox-1.64 {configuration option: \"selectbackground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectbackground bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.65 {configuration option: \"selectborderwidth\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectborderwidth 1.3\n    .e cget -selectborderwidth\n} -cleanup {\n    destroy .e\n} -result 1.3\ntest spinbox-1.66 {configuration option: \"selectborderwidth\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectborderwidth badValue\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected screen distance but got \"badValue\"}\n\ntest spinbox-1.67 {configuration option: \"selectforeground\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectforeground #654321\n    .e cget -selectforeground\n} -cleanup {\n    destroy .e\n} -result {#654321}\ntest spinbox-1.68 {configuration option: \"selectforeground\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -selectforeground bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown color name \"bogus\"}\n\ntest spinbox-1.69 {configuration option: \"state\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -state n\n    .e cget -state\n} -cleanup {\n    destroy .e\n} -result {normal}\ntest spinbox-1.70 {configuration option: \"state\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -state bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad state \"bogus\": must be disabled, normal, or readonly}\n\ntest spinbox-1.71 {configuration option: \"takefocus\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -takefocus \"any string\"\n    .e cget -takefocus\n} -cleanup {\n    destroy .e\n} -result {any string}\n\ntest spinbox-1.72 {configuration option: \"textvariable\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -textvariable i\n    .e cget -textvariable\n} -cleanup {\n    destroy .e\n} -result {i}\n\ntest spinbox-1.73 {configuration option: \"to\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -to 14.9\n    .e cget -to\n} -cleanup {\n    destroy .e\n} -result {14.9}\ntest spinbox-1.74 {configuration option: \"to\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -to bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"bogus\"}\n\ntest spinbox-1.75 {configuration option: \"validate\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -validate \"key\"\n    .e cget -validate\n} -cleanup {\n    destroy .e\n} -result {key}\ntest spinbox-1.76 {configuration option: \"validate\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -validate \"bogus\"\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad validate \"bogus\": must be all, key, focus, focusin, focusout, or none}\n\ntest spinbox-1.77 {configuration option: \"validatecommand\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -validatecommand \"a command\"\n    .e cget -validatecommand\n} -cleanup {\n    destroy .e\n} -result {a command}\n\ntest spinbox-1.78 {configuration option: \"values\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -values {mon tue wed thur}\n    .e cget -values\n} -cleanup {\n    destroy .e\n} -result {mon tue wed thur}\ntest spinbox-1.79 {configuration option: \"values\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -values {bad {}list}\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {list element in braces followed by \"list\" instead of space}\n\ntest spinbox-1.80 {configuration option: \"validatecommand\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -validatecommand \"a command\"\n    .e cget -validatecommand\n} -cleanup {\n    destroy .e\n} -result {a command}\n\ntest spinbox-1.81 {configuration option: \"width\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -width 402\n    .e cget -width\n} -cleanup {\n    destroy .e\n} -result 402\ntest spinbox-1.82 {configuration option: \"width\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -width 3p\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"3p\"}\n\ntest spinbox-1.83 {configuration option: \"wrap\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -wrap yes\n    .e cget -wrap\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-1.84 {configuration option: \"wrap\" for spinbox} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -wrap xyzzy\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected boolean value but got \"xyzzy\"}\n\ntest spinbox-1.85 {configuration option: \"xscrollcommand\"} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \\\n\t-relief sunken\n    pack .e\n    update\n} -body {\n    .e configure -xscrollcommand {Some command}\n    .e cget -xscrollcommand\n} -cleanup {\n    destroy .e\n} -result {Some command}\n\n\ntest spinbox-2.1 {Tk_SpinboxCmd procedure} -body {\n    spinbox\n} -returnCodes error -result {wrong # args: should be \"spinbox pathName ?-option value ...?\"}\ntest spinbox-2.2 {Tk_SpinboxCmd procedure} -body {\n    spinbox gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest spinbox-2.3 {Tk_SpinboxCmd procedure} -body {\n    spinbox .e\n    pack .e\n    update\n    list [winfo exists .e] [winfo class .e] [info commands .e]\n} -cleanup {\n    destroy .e\n} -result {1 Spinbox .e}\ntest spinbox-2.4 {Tk_SpinboxCmd procedure} -body {\n    spinbox .e -gorp foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest spinbox-2.4.1 {Tk_SpinboxCmd procedure} -body {\n    catch {spinbox .e -gorp foo}\n    list [winfo exists .e] [info commands .e]\n} -cleanup {\n    destroy .e\n} -result {0 {}}\ntest spinbox-2.5 {Tk_SpinboxCmd procedure} -body {\n    spinbox .e\n} -cleanup {\n    destroy .e\n} -result {.e}\n\n\ntest spinbox-3.1 {SpinboxWidgetCmd procedure} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e option ?arg ...?\"}\ntest spinbox-3.2 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e bbox\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e bbox index\"}\ntest spinbox-3.3 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e bbox a b\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e bbox index\"}\ntest spinbox-3.4 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e bbox bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"bogus\"}\ntest spinbox-3.5 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n   .e bbox 0\n} -cleanup {\n    destroy .e\n} -result [list 5 5 0 $cy]\n\n# Originally the result was counted using measurements and metrics. It was\n# changed to less verbose solution - the result is the one that passes fonts\n# constraint (this concerns tests 3.6, 3.7, 3.8, 3.10)\ntest spinbox-3.6 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n# Tcl_UtfAtIndex(): no utf chars\n    .e insert 0 \"abc\"\n    list [.e bbox 3] [.e bbox end]\n} -cleanup {\n    destroy .e\n} -result {{19 5 7 13} {19 5 7 13}}\ntest spinbox-3.7 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n# Tcl_UtfAtIndex(): utf at end\n    .e insert 0 \"ab乎\"\n    .e bbox end\n} -cleanup {\n    destroy .e\n} -result {19 5 12 13}\ntest spinbox-3.8 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n# Tcl_UtfAtIndex(): utf before index\n    .e insert 0 \"ab乎c\"\n    .e bbox 3\n} -cleanup {\n    destroy .e\n} -result {31 5 7 13}\ntest spinbox-3.9 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n# Tcl_UtfAtIndex(): no chars\n    .e bbox end\n} -cleanup {\n    destroy .e\n} -result \"5 5 0 $cy\"\ntest spinbox-3.10 {SpinboxWidgetCmd procedure, \"bbox\" widget command} -constraints {\n\tfonts\n} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert 0 \"abcdefghij乎klmnop\"\n    list [.e bbox 0] [.e bbox 1] [.e bbox 10] [.e bbox end]\n} -cleanup {\n    destroy .e\n} -result {{5 5 7 13} {12 5 7 13} {75 5 12 13} {122 5 7 13}}\ntest spinbox-3.11 {SpinboxWidgetCmd procedure, \"cget\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e cget\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e cget option\"}\ntest spinbox-3.12 {SpinboxWidgetCmd procedure, \"cget\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e cget a b\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e cget option\"}\ntest spinbox-3.13 {SpinboxWidgetCmd procedure, \"cget\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e cget -gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest spinbox-3.14 {SpinboxWidgetCmd procedure, \"cget\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e configure -bd 4\n    .e cget -bd\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-3.15 {SpinboxWidgetCmd procedure, \"configure\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    llength [.e configure]\n} -cleanup {\n    destroy .e\n} -result 51\ntest spinbox-3.16 {SpinboxWidgetCmd procedure, \"configure\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e configure -foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"-foo\"}\ntest spinbox-3.17 {SpinboxWidgetCmd procedure, \"configure\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e configure -bd 4\n    .e configure -bg #ffffff\n    lindex [.e configure -bd] 4\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-3.18 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e delete\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e delete firstIndex ?lastIndex?\"}\ntest spinbox-3.19 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e delete a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e delete firstIndex ?lastIndex?\"}\ntest spinbox-3.20 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e delete foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"foo\"}\ntest spinbox-3.21 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e delete 0 bar\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"bar\"}\ntest spinbox-3.22 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 2 4\n    .e get\n} -cleanup {\n    destroy .e\n} -result 014567890\ntest spinbox-3.23 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 6\n    .e get\n} -cleanup {\n    destroy .e\n} -result 0123457890\ntest spinbox-3.24 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n    set textVar {}\n} -body {\n# UTF\n    .e insert end \"01234乎67890\"\n    .e delete 6\n    lappend textVar [.e get]\n    .e delete 0 end\n    .e insert end \"012345乎7890\"\n    .e delete 6\n    lappend textVar [.e get]\n    .e delete 0 end\n    .e insert end \"0123456乎890\"\n    .e delete 6\n    lappend textVar [.e get]\n} -cleanup {\n    destroy .e\n} -result [list \"01234乎7890\" \"0123457890\" \"012345乎890\"]\ntest spinbox-3.25 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e delete 6 5\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest spinbox-3.26 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state disabled\n    .e delete 2 8\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest spinbox-3.26.1 {SpinboxWidgetCmd procedure, \"delete\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state readonly\n    .e delete 2 8\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest spinbox-3.27 {SpinboxWidgetCmd procedure, \"get\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e get foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e get\"}\ntest spinbox-3.28 {SpinboxWidgetCmd procedure, \"icursor\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e icursor\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e icursor pos\"}\ntest spinbox-3.29 {SpinboxWidgetCmd procedure, \"icursor\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e icursor foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"foo\"}\ntest spinbox-3.30 {SpinboxWidgetCmd procedure, \"icursor\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert end \"01234567890\"\n    .e icursor 4\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-3.31 {SpinboxWidgetCmd procedure, \"index\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e in\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {ambiguous option \"in\": must be bbox, cget, configure, delete, get, icursor, identify, index, insert, invoke, scan, selection, set, validate, or xview}\ntest spinbox-3.32 {SpinboxWidgetCmd procedure, \"index\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e index\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e index string\"}\ntest spinbox-3.33 {SpinboxWidgetCmd procedure, \"index\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e index foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"foo\"}\ntest spinbox-3.34 {SpinboxWidgetCmd procedure, \"index\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e index 0\n} -cleanup {\n    destroy .e\n} -returnCodes {ok} -match glob -result {*}\ntest spinbox-3.35 {SpinboxWidgetCmd procedure, \"index\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n# UTF\n    .e insert 0 abc乎œdef\n    list [.e index 3] [.e index 4] [.e index end]\n} -cleanup {\n    destroy .e\n} -result {3 4 8}\ntest spinbox-3.36 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert a\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest spinbox-3.37 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest spinbox-3.38 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert foo Text\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"foo\"}\ntest spinbox-3.39 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e insert 3 xxx\n    .e get\n} -cleanup {\n    destroy .e\n} -result {012xxx34567890}\ntest spinbox-3.40 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state disabled\n    .e insert 3 xxx\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest spinbox-3.40.1 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"01234567890\"\n    .e configure -state readonly\n    .e insert 3 xxx\n    .e configure -state normal\n    .e get\n} -cleanup {\n    destroy .e\n} -result 01234567890\ntest spinbox-3.41 {SpinboxWidgetCmd procedure, \"insert\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e insert index text\"}\ntest spinbox-3.42 {SpinboxWidgetCmd procedure, \"scan\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e scan a\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e scan mark|dragto x\"}\ntest spinbox-3.43 {SpinboxWidgetCmd procedure, \"scan\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e scan a b c\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e scan mark|dragto x\"}\ntest spinbox-3.44 {SpinboxWidgetCmd procedure, \"scan\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e scan foobar 20\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad scan option \"foobar\": must be dragto or mark}\ntest spinbox-3.45 {SpinboxWidgetCmd procedure, \"scan\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e scan mark 20.1\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected integer but got \"20.1\"}\n\n# This test is non-portable because character sizes vary.\ntest spinbox-3.46 {SpinboxWidgetCmd procedure, \"scan\" widget command} -constraints {\n    fonts\n} -setup {\n    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long string, in fact a \"\n    .e insert end \"very very long string\"\n    .e scan mark 30\n    .e scan dragto 28\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 2\ntest spinbox-3.47 {SpinboxWidgetCmd procedure, \"select\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection option ?index?\"}\ntest spinbox-3.48 {SpinboxWidgetCmd procedure, \"select\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad selection option \"foo\": must be adjust, clear, element, from, present, range, or to}\n\ntest spinbox-3.49 {SpinboxWidgetCmd procedure, \"select clear\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select clear gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection clear\"}\ntest spinbox-3.50 {SpinboxWidgetCmd procedure, \"select clear\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 4\n    update\n    .e select clear\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest spinbox-3.50.1 {SpinboxWidgetCmd procedure, \"select clear\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 4\n    update\n    .e select clear\n    catch {selection get}\n    selection own\n} -cleanup {\n    destroy .e\n} -result {.e}\n\ntest spinbox-3.51 {SpinboxWidgetCmd procedure, \"selection present\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e selection present foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection present\"}\ntest spinbox-3.52 {SpinboxWidgetCmd procedure, \"selection present\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-3.53 {SpinboxWidgetCmd procedure, \"selection present\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e configure -exportselection false\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-3.54 {SpinboxWidgetCmd procedure, \"selection present\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    .e delete 0 end\n    .e selection present\n} -cleanup {\n    destroy .e\n} -result 0\ntest spinbox-3.55 {SpinboxWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select adjust x\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"x\"}\ntest spinbox-3.56 {SpinboxWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select adjust 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection adjust index\"}\ntest spinbox-3.57 {SpinboxWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    update\n    .e select adjust 4\n    selection get\n} -cleanup {\n    destroy .e\n} -result 123\ntest spinbox-3.58 {SpinboxWidgetCmd procedure, \"selection adjust\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    update\n    .e select adjust 2\n    selection get\n} -cleanup {\n    destroy .e\n} -result 234\ntest spinbox-3.59 {SpinboxWidgetCmd procedure, \"selection from\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select from 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection from index\"}\n\ntest spinbox-3.60 {SpinboxWidgetCmd procedure, \"selection range\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e select range 2\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection range start end\"}\ntest spinbox-3.61 {SpinboxWidgetCmd procedure, \"selection range\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e selection range 2 3 4\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection range start end\"}\ntest spinbox-3.62 {SpinboxWidgetCmd procedure, \"selection range\" widget command} -setup {\n    spinbox .e\n} -body {\n    .e insert end 0123456789\n    .e select from 1\n    .e select to 5\n    .e select range 4 4\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest spinbox-3.63 {SpinboxWidgetCmd procedure, \"selection range\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 7\n    .e select range 2 9\n    list [.e index sel.first] [.e index sel.last] [.e index anchor]\n} -cleanup {\n    destroy .e\n} -result {2 9 3}\ntest spinbox-3.64 {SpinboxWidgetCmd procedure, \"selection to\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n} -body {\n    .e select to 2 3\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e selection to index\"}\ntest spinbox-3.64.1 {SpinboxWidgetCmd procedure, \"selection\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state disabled\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {0 10}\ntest spinbox-3.64.2 {SpinboxWidgetCmd procedure, \"selection\" widget command} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state readonly\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 4}\n\ntest spinbox-3.65 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 5\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.053763 0.268817}\ntest spinbox-3.66 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e xview gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"gorp\"}\ntest spinbox-3.67 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 0\n    .e icursor 10\n    .e xview insert\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.107527 0.322581}\ntest spinbox-3.68 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e xview moveto foo bar\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e xview moveto fraction\"}\ntest spinbox-3.69 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e xview moveto foo\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"foo\"}\ntest spinbox-3.70 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview moveto 0.5\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.505376 0.720430}\ntest spinbox-3.71 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview scroll 24\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {wrong # args: should be \".e xview scroll number pages|units\"}\ntest spinbox-3.72 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview scroll gorp units\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {expected floating-point number but got \"gorp\"}\ntest spinbox-3.73 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview moveto 0\n    .e xview scroll 1 pages\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.193548 0.408602}\ntest spinbox-3.74 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview moveto .9\n    update\n    .e xview scroll -2 p\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.397849 0.612903}\ntest spinbox-3.75 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 30\n    update\n    .e xview scroll 2 units\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 32\ntest spinbox-3.76 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 30\n    update\n    .e xview scroll -1 units\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 29\ntest spinbox-3.77 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview scroll 23 foobars\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad argument \"foobars\": must be pages or units}\ntest spinbox-3.78 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview eat 23 hamburgers\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {unknown option \"eat\": must be moveto or scroll}\ntest spinbox-3.79 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e xview 0\n    update\n    .e xview {}\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 0\ntest spinbox-3.80 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    update\n    .e xview 300\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 73\ntest spinbox-3.81 {SpinboxWidgetCmd procedure, \"xview\" widget command} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e insert end \"This is quite a long text string, so long that it \"\n    .e insert end \"runs off the end of the window quite a bit.\"\n    .e insert 10 乎\n    update\n# UTF\n# If Tcl_NumUtfChars wasn't used, wrong answer would be:\n# 0.106383 0.117021 0.117021\n    set textVar {}\n    .e xview moveto .1\n    lappend textVar [format {%.6f} [lindex [.e xview] 0]]\n    .e xview moveto .11\n    lappend textVar [format {%.6f} [lindex [.e xview] 0]]\n    .e xview moveto .12\n    lappend textVar [format {%.6f} [lindex [.e xview] 0]]\n} -cleanup {\n    destroy .e\n} -result {0.095745 0.106383 0.117021}\n\ntest spinbox-3.82 {SpinboxWidgetCmd procedure} -setup {\n    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n    update\n} -body {\n    .e gorp\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad option \"gorp\": must be bbox, cget, configure, delete, get, icursor, identify, index, insert, invoke, scan, selection, set, validate, or xview}\n\ntest spinbox-5.1 {ConfigureSpinbox procedure, -textvariable} -body {\n    set textVar 12345\n    spinbox .e -textvariable textVar\n    .e get\n} -cleanup {\n    destroy .e\n} -result 12345\ntest spinbox-5.2 {ConfigureSpinbox procedure, -textvariable} -body {\n    set textVar 12345\n    spinbox .e -textvariable textVar\n    set y abcde\n    .e configure -textvariable y\n    set textVar 54321\n    .e get\n} -cleanup {\n    destroy .e\n} -result {abcde}\ntest spinbox-5.3 {ConfigureSpinbox procedure, -textvariable} -setup {\n    unset -nocomplain textVar\n    spinbox .e\n} -body {\n    .e insert 0 \"Some text\"\n    .e configure -textvariable textVar\n    set textVar\n} -cleanup {\n    destroy .e\n} -result {Some text}\ntest spinbox-5.4 {ConfigureSpinbox procedure, -textvariable} -setup {\n    unset -nocomplain textVar\n    spinbox .e\n} -body {\n    trace add variable textVar write override\n    .e insert 0 \"Some text\"\n    .e configure -textvariable textVar\n    list $textVar [.e get]\n} -cleanup {\n    destroy .e\n    trace remove variable textVar write override\n} -result {12345 12345}\n\ntest spinbox-5.5 {ConfigureSpinbox procedure} -setup {\n    set textVar {}\n    spinbox .e1\n    spinbox .e2\n} -body {\n    .e2 insert end \"This is some sample text\"\n    .e1 configure -exportselection false\n    .e1 insert end \"0123456789\"\n    pack .e1 .e2\n    .e2 select from 0\n    .e2 select to 10\n    lappend textVar [selection get]\n    .e1 select from 1\n    .e1 select to 5\n    lappend textVar [selection get]\n    .e1 configure -exportselection 1\n    lappend textVar [selection get]\n    set textVar\n} -cleanup {\n    destroy .e1 .e2\n} -result {{This is so} {This is so} 1234}\ntest spinbox-5.6 {ConfigureSpinbox procedure} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    .e configure -exportselection 0\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest spinbox-5.6.1 {ConfigureSpinbox procedure} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e insert end \"0123456789\"\n    .e select from 1\n    .e select to 5\n    .e configure -exportselection 0\n    catch {selection get}\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 5}\n\ntest spinbox-5.7 {ConfigureSpinbox procedure} -setup {\n    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -width 4 -xscrollcommand setScrollInfo\n    .e insert end \"01234567890\"\n    update\n    set scrollInfo wrong\n    .e configure -width 5\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.454545}\n\ntest spinbox-5.8 {ConfigureSpinbox procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -width 0 -font {Helvetica -12}\n    .e insert end \"0123\"\n    update\n    .e configure -font {Helvetica -24}\n    update\n    winfo geom .e\n} -cleanup {\n    destroy .e\n} -result {79x37+0+0}\ntest spinbox-5.9 {ConfigureSpinbox procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised\n    .e insert end \"0123\"\n    update\n    list [.e index @10] [.e index @11] [.e index @12] [.e index @13]\n} -cleanup {\n    destroy .e\n} -result {0 0 1 1}\ntest spinbox-5.10 {ConfigureSpinbox procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief flat\n    .e insert end \"0123\"\n    update\n    list [.e index @10] [.e index @11] [.e index @12] [.e index @13]\n} -cleanup {\n    destroy .e\n} -result {0 0 1 1}\ntest spinbox-5.11 {ConfigureSpinbox procedure} -setup {\n    spinbox .e -borderwidth 2 -highlightthickness 2\n    pack .e\n} -body {\n# If \"0\" in selected font had 0 width, caused divide-by-zero error.\n    .e configure -font {{open look glyph}}\n    .e scan dragto 30\n    update\n} -cleanup {\n    destroy .e\n} -result {}\ntest spinbox-5.12 {ConfigureSpinbox procedure, -from and -to swapping} -setup {\n    spinbox .e\n} -body {\n    # this statement used to trigger error \"-to value must be greater than -from value\"\n    # because default value for -to is zero (bug [841280ffff])\n    set res [catch {.e configure -from 10}]\n    .e configure -from 1971 -to 2016  ; # standard case\n    lappend res [.e cget -from] [.e cget -to]\n    .e configure -from 2016 -to 1971  ; # auto-swapping happens\n    lappend res [.e cget -from] [.e cget -to]\n    .e configure -to 1971 -from 2016 ; # auto-swapping, order of options does not matter\n    lappend res [.e cget -from] [.e cget -to]\n} -cleanup {\n    destroy .e\n} -result {0 1971.0 2016.0 1971.0 2016.0 1971.0 2016.0}\n\n# No tests for DisplaySpinbox.\n\ntest spinbox-6.1 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @61] [.e index @62]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest spinbox-6.2 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -justify center \\\n\t    -highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @96] [.e index @97]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest spinbox-6.3 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -justify right \\\n\t    -highlightthickness 3\n    .e insert end 012\\t45\n    update\n    list [.e index @131] [.e index @132]\n} -cleanup {\n    destroy .e\n} -result {3 4}\ntest spinbox-6.4 {SpinboxComputeGeometry procedure} -setup {\n    spinbox .e\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 5\n    .e insert end \"01234567890\"\n    update\n    .e xview 6\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 6\ntest spinbox-6.5 {SpinboxComputeGeometry procedure} -setup {\n    spinbox .e -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 5\n    .e insert end \"01234567890\"\n    update\n    .e xview 7\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 6\ntest spinbox-6.6 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Courier -12} -bd 2 -relief raised -width 10\n    .e insert end \"01234\\t67890\"\n    update\n    .e xview 3\n    list [.e index @39] [.e index @40]\n} -cleanup {\n    destroy .e\n} -result {5 6}\ntest spinbox-6.7 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 5\n    .e insert end \"01234567\"\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {94 39}\ntest spinbox-6.8 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0\n    .e insert end \"01234567\"\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {133 39}\ntest spinbox-6.9 {SpinboxComputeGeometry procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -highlightthickness 2\n    pack .e\n} -body {\n    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0\n    update\n    list [winfo reqwidth .e] [winfo reqheight .e]\n} -cleanup {\n    destroy .e\n} -result {42 39}\n\n\ntest spinbox-7.1 {InsertChars procedure} -setup {\n    unset -nocomplain contents\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    .e insert 0 abcde\n    update\n    set scrollInfo wrong\n    .e insert 2 XXX\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abXXXcde abXXXcde {0.000000 1.000000}}\n\ntest spinbox-7.2 {InsertChars procedure} -setup {\n    unset -nocomplain contents\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    .e insert 0 abcde\n    update\n    set scrollInfo wrong\n    .e insert 500 XXX\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abcdeXXX abcdeXXX {0.000000 1.000000}}\ntest spinbox-7.3 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 2 XXX\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {5 9 5 8}\ntest spinbox-7.4 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 3 XXX\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 9 2 8}\ntest spinbox-7.5 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 5 XXX\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 9 2 8}\ntest spinbox-7.6 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789\n    .e select from 2\n    .e select to 6\n    .e insert 6 XXX\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {2 6 2 5}\ntest spinbox-7.7 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -xscrollcommand setScrollInfo\n    .e insert 0 0123456789\n    .e icursor 4\n    .e insert 4 XXX\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 7\ntest spinbox-7.8 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789\n    .e icursor 4\n    .e insert 5 XXX\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-7.9 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    update\n    .e xview 4\n    .e insert 3 XXX\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 7\ntest spinbox-7.10 {InsertChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    update\n    .e xview 4\n    .e insert 4 XXX\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 4\n\ntest spinbox-7.11 {InsertChars procedure} -constraints {\n    fonts\n} -setup {\n    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 \"xyzzy\"\n    update\n    .e insert 2 00\n    winfo reqwidth .e\n} -cleanup {\n    destroy .e\n} -result 70\n\ntest spinbox-8.1 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    .e insert 0 abcde\n    update\n    set scrollInfo wrong\n    .e delete 2 4\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abe abe {0.000000 1.000000}}\ntest spinbox-8.2 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    .e insert 0 abcde\n    update\n    set scrollInfo wrong\n    .e delete {} 2\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {cde cde {0.000000 1.000000}}\ntest spinbox-8.3 {DeleteChars procedure} -setup {\n    unset -nocomplain contents\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e configure -textvariable contents -xscrollcommand setScrollInfo\n    .e insert 0 abcde\n    update\n    set scrollInfo wrong\n    .e delete 3 1000\n    update\n    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]\n} -cleanup {\n    destroy .e\n} -result {abc abc {0.000000 1.000000}}\ntest spinbox-8.4 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 3\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 6 1 5}\ntest spinbox-8.5 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 4\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 4\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 5 1 4}\ntest spinbox-8.6 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 7\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 5\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 2 1 5}\ntest spinbox-8.7 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 1 8\n    update\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest spinbox-8.8 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 3 7\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 4 3 8}\ntest spinbox-8.9 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 3\n    .e select to 8\n    .e delete 3 8\n    update\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest spinbox-8.10 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 8\n    .e select to 3\n    .e delete 5 8\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 8\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 5 5 8}\ntest spinbox-8.11 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e select from 8\n    .e select to 3\n    .e delete 8 10\n    update\n    set textVar \"[.e index sel.first] [.e index sel.last]\"\n    .e select to 4\n    lappend textVar [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {3 8 4 8}\ntest spinbox-8.12 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 1 4\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-8.13 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 1 5\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-8.14 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 0123456789abcde\n    .e icursor 4\n    .e delete 4 6\n    update\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-8.15 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 1 4\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-8.16 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 1 5\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-8.17 {DeleteChars procedure} -setup {\n    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 \"This is a very long string\"\n    .e xview 4\n    .e delete 4 6\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-8.18 {DeleteChars procedure} -setup {\n    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2\n    pack .e\n    focus .e\n} -body {\n    .e insert 0 \"xyzzy\"\n    update\n    .e delete 2 4\n    # To check that deletion actually happened we measure the new width\n    # of the widget, based on the measuring width of the remaining text (\"xyy\")\n    # in the widget. For that purpose we have to mirror the code in tkEntry.c\n    # for computation of the reqwidth\n    # note: XPAD corresponds to the hardcoded    #define XPAD 1\n    set XPAD 1\n    set buttonWidth [expr { [font measure [.e cget -font] \"0\"] + 2 * (1 + $XPAD) }]\n    if {$buttonWidth < 11} {\n\tset buttonWidth 11\n    }\n    set expected [expr { [font measure [.e cget -font] \"xyy\"] \\\n\t\t\t  + 2 * ( [.e cget -borderwidth] + \\\n\t\t\t\t[.e cget -highlightthickness] + $XPAD ) \\\n\t\t\t  + $buttonWidth } ]\n    expr {[winfo reqwidth .e] == $expected}\n} -cleanup {\n    destroy .e\n    unset XPAD buttonWidth expected\n} -result {1}\n\ntest spinbox-9.1 {SpinboxValueChanged procedure} -setup {\n    unset -nocomplain textVar\n} -body {\n    trace add variable textVar write override\n    spinbox .e -textvariable textVar -width 0\n    .e insert 0 foo\n    list $textVar [.e get]\n} -cleanup {\n    destroy .e\n    trace remove variable textVar write override\n} -result {12345 12345}\n\n\ntest spinbox-10.1 {SpinboxSetValue procedure} -constraints fonts -body {\n    set textVar abcde\n    set y ab\n    spinbox .e  -font {Helvetica -12} -highlightthickness 2 -bd 2  -width 0\n    pack .e\n    .e configure -textvariable textVar\n    .e configure -textvariable y\n    update\n    list [.e get] [winfo reqwidth .e]\n} -cleanup {\n    destroy .e\n} -result {ab 35}\ntest spinbox-10.2 {SpinboxSetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"a\"\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\ntest spinbox-10.3 {SpinboxSetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"abcdefg\"\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {4 7}\ntest spinbox-10.4 {SpinboxSetValue procedure, updating selection} -setup {\n    unset -nocomplain textVar\n    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstu\"\n    .e selection range 4 10\n    set textVar \"abcdefghijklmn\"\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {4 10}\ntest spinbox-10.5 {SpinboxSetValue procedure, updating display position} -setup {\n    unset -nocomplain textVar\n    spinbox .e -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e xview 10\n    update\n    set textVar \"abcdefg\"\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 0\ntest spinbox-10.6 {SpinboxSetValue procedure, updating display position} -setup {\n    unset -nocomplain textVar\n    spinbox .e -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e xview 10\n    update\n    set textVar \"1234567890123456789012\"\n    update\n    .e index @0\n} -cleanup {\n    destroy .e\n} -result 10\ntest spinbox-10.7 {SpinboxSetValue procedure, updating insertion cursor} -setup {\n    unset -nocomplain textVar\n    spinbox .e -highlightthickness 2 -bd 2\n    pack .e\n    update\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e icursor 5\n    set textVar \"123\"\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 3\ntest spinbox-10.8 {SpinboxSetValue procedure, updating insertion cursor} -setup {\n    unset -nocomplain textVar\n    spinbox .e -highlightthickness 2 -bd 2\n    pack .e\n} -body {\n    .e configure -width 10 -font {Courier -12} -textvariable textVar\n    pack .e\n    .e insert 0 \"abcdefghjklmnopqrstuvwxyz\"\n    .e icursor 5\n    set textVar \"123456\"\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 5\n\ntest spinbox-11.1 {SpinboxEventProc procedure} -setup {\n    spinbox .e -highlightthickness 2 -bd 2 -font {Helvetica -12}\n    pack .e\n} -body {\n    .e insert 0 abcdefg\n    destroy .e\n    update\n} -cleanup {\n    destroy .e\n} -result {}\ntest spinbox-11.2 {SpinboxEventProc procedure} -setup {\n    set textVar {}\n} -body {\n    spinbox .e1 -fg #112233\n    rename .e1 .e2\n    lappend textVar [winfo children .]\n    lappend textVar [.e2 cget -fg]\n    destroy .e1\n    lappend textVar [info command .e*] [winfo children .]\n} -cleanup {\n    destroy .e1\n} -result {.e1 #112233 {} {}}\n\ntest spinbox-12.1 {SpinboxCmdDeletedProc procedure} -body {\n    button .b -text \"xyz_123\"\n    rename .b {}\n    list [info command .b*] [winfo children .]\n} -cleanup {\n    destroy .b\n} -result {{} {}}\n\n\ntest spinbox-13.1 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index end\n} -cleanup {\n    destroy .e\n} -result 21\ntest spinbox-13.2 {GetSpinboxIndex procedure} -body {\n    spinbox .e\n    .e index abogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"abogus\"}\ntest spinbox-13.3 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 1\ntest spinbox-13.4 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 4\n    .e select to 1\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-13.5 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 3\n    .e select to 15\n    .e select adjust 4\n    .e index anchor\n} -cleanup {\n    destroy .e\n} -result 15\ntest spinbox-13.6 {GetSpinboxIndex procedure} -setup {\n    spinbox .e\n} -body {\n    .e index ebogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"ebogus\"}\ntest spinbox-13.7 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e icursor 2\n    .e index insert\n} -cleanup {\n    destroy .e\n} -result 2\ntest spinbox-13.8 {GetSpinboxIndex procedure} -setup {\n    spinbox .e\n} -body {\n    .e index ibogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"ibogus\"}\ntest spinbox-13.9 {GetSpinboxIndex procedure} -setup {\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n} -body {\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n} -cleanup {\n    destroy .e\n} -result {1 6}\n\ntest spinbox-13.10 {GetSpinboxIndex procedure} -constraints x11 -body {\n# On unix, when selection is cleared, spinbox widget's internal\n# selection range is reset.\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n\tpack .e\n\t.e insert 0 012345678901234567890\n\t.e xview 4\n\tupdate\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\n\ntest spinbox-13.11 {GetSpinboxIndex procedure} -constraints aquaOrWin32 -body {\n# On mac and pc, when selection is cleared, spinbox widget remembers\n# last selected range.  When selection ownership is restored to\n# spinbox, the old range will be rehighlighted.\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    catch {selection get}\n    .e index sel.first\n} -cleanup {\n    destroy .e\n} -result 1\n\ntest spinbox-13.12 {GetSpinboxIndex procedure} -constraints x11 -body {\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {selection isn't in widget .e}\n\ntest spinbox-13.12.1 {GetSpinboxIndex procedure} -constraints unix -body {\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index bogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"bogus\"}\n\ntest spinbox-13.13 {GetSpinboxIndex procedure} -constraints win -body {\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"sbogus\"}\n\ntest spinbox-13.14 {GetSpinboxIndex procedure} -constraints win -body {\n# On mac and pc, when selection is cleared, spinbox widget remembers\n# last selected range.  When selection ownership is restored to\n# spinbox, the old range will be rehighlighted.\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    selection get\n} -cleanup {\n    destroy .e\n} -returnCodes error -match glob -result {*}\n\ntest spinbox-13.14.1 {GetSpinboxIndex procedure} -constraints win -body {\n# On mac and pc, when selection is cleared, spinbox widget remembers\n# last selected range.  When selection ownership is restored to\n# spinbox, the old range will be rehighlighted.\n# Previous settings:\n    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e select from 1\n    .e select to 6\n    list [.e index sel.first] [.e index sel.last]\n# Testing:\n    selection clear .e\n    catch {selection get}\n    .e index sbogus\n} -cleanup {\n    destroy .e\n} -returnCodes error -match glob -result {*}\n\ntest spinbox-13.15 {GetSpinboxIndex procedure} -body {\n    spinbox .e\n    selection clear .e\n    .e index @xyz\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"@xyz\"}\n\ntest spinbox-13.16 {GetSpinboxIndex procedure} -constraints fonts -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @4\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-13.17 {GetSpinboxIndex procedure} -constraints fonts -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @11\n} -cleanup {\n    destroy .e\n} -result 4\ntest spinbox-13.18 {GetSpinboxIndex procedure} -constraints fonts -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @12\n} -cleanup {\n    destroy .e\n} -result 5\ntest spinbox-13.19 {GetSpinboxIndex procedure} -constraints fonts -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @[expr {[winfo width .e] - 6-11}]\n} -cleanup {\n    destroy .e\n} -result 8\ntest spinbox-13.20 {GetSpinboxIndex procedure} -constraints fonts -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @[expr {[winfo width .e] - 5}]\n} -cleanup {\n    destroy .e\n} -result 9\ntest spinbox-13.21 {GetSpinboxIndex procedure} -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index @1000\n} -cleanup {\n    destroy .e\n} -result 9\ntest spinbox-13.22 {GetSpinboxIndex procedure} -setup {\n    spinbox .e\n    pack .e\n    update\n} -body {\n    .e index 1xyz\n} -cleanup {\n    destroy .e\n} -returnCodes error -result {bad spinbox index \"1xyz\"}\ntest spinbox-13.23 {GetSpinboxIndex procedure} -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index {}\n} -cleanup {\n    destroy .e\n} -result 0\ntest spinbox-13.24 {GetSpinboxIndex procedure} -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index 12\n} -cleanup {\n    destroy .e\n} -result 12\ntest spinbox-13.25 {GetSpinboxIndex procedure} -body {\n    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \\\n\t-font {Courier -12}\n    pack .e\n    .e insert 0 012345678901234567890\n    .e xview 4\n    update\n    .e index 49\n} -cleanup {\n    destroy .e\n} -result 21\n\ntest spinbox-14.1 {SpinboxFetchSelection procedure} -body {\n    spinbox .e\n    .e insert end \"This is a test string\"\n    .e select from 1\n    .e select to 18\n    selection get\n} -cleanup {\n    destroy .e\n} -result {his is a test str}\ntest spinbox-14.3 {SpinboxFetchSelection procedure} -setup {\n    set textVar {}\n    for {set i 1} {$i <= 500} {incr i} {\n\tappend textVar \"This is line $i, out of 500\\n\"\n}\n} -body {\n    spinbox .e\n    .e insert end $textVar\n    .e select from 0\n    .e select to end\n    string compare [selection get] $textVar\n} -cleanup {\n    destroy .e\n} -result 0\n\ntest spinbox-15.1 {SpinboxLostSelection} -body {\n    spinbox .e\n    .e insert 0 \"Text\"\n    .e select from 0\n    .e select to 4\n    set result [selection get]\n    selection clear\n    .e select from 0\n    .e select to 4\n    lappend result [selection get]\n} -cleanup {\n    destroy .e\n} -result {Text Text}\n\n\ntest spinbox-16.1 {SpinboxVisibleRange procedure} -constraints fonts  -body {\n    spinbox .e -width 10 -font {Helvetica -12}\n    pack .e\n    update\n    .e insert 0 \".............................\"\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.827586}\ntest spinbox-16.2 {SpinboxVisibleRange procedure} -body {\n    spinbox .e\n    format {%.6f %.6f} {*}[.e xview]\n} -cleanup {\n    destroy .e\n} -result {0.000000 1.000000}\n\n\ntest spinbox-17.1 {SpinboxUpdateScrollbar procedure} -body {\n    spinbox .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    update\n    set scrollInfo wrong\n    .e delete 0 end\n    .e insert 0 123\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.000000 1.000000}\ntest spinbox-17.2 {SpinboxUpdateScrollbar procedure} -body {\n    spinbox .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    .e insert 0 0123456789abcdef\n    update\n    set scrollInfo wrong\n    .e xview 3\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.187500 0.812500}\ntest spinbox-17.3 {SpinboxUpdateScrollbar procedure} -body {\n    spinbox .e -width 10 -xscrollcommand setScrollInfo -font {Courier -12}\n    pack .e\n    update\n    set scrollInfo wrong\n    .e insert 0 abcdefghijklmnopqrs\n    .e xview\n    update\n    format {%.6f %.6f} {*}$scrollInfo\n} -cleanup {\n    destroy .e\n} -result {0.000000 0.526316}\ntest spinbox-17.4 {SpinboxUpdateScrollbar procedure} -setup {\n    proc bgerror msg {\n\tglobal textVar\n\tset textVar $msg\n}\n} -body {\n    spinbox .e -width 5\n    pack .e\n    update\n    set scrollInfo wrong\n    .e configure -xscrollcommand thisisnotacommand\n    update\n    list $textVar $errorInfo\n} -cleanup {\n    destroy .e\n    rename bgerror {}\n} -result {{invalid command name \"thisisnotacommand\"} {invalid command name \"thisisnotacommand\"\n    while executing\n\"thisisnotacommand 0.0 1.0\"\n    (horizontal scrolling command executed by .e)}}\n\n\ntest spinbox-18.1 {Spinbox widget vs hiding} -setup {\n    spinbox .e\n} -body {\n    set l [interp hidden]\n    interp hide {} .e\n    destroy .e\n    set res1 [list [winfo children .] [interp hidden]]\n    set res2 [list {} $l]\n    expr {$res1 eq $res2}\n} -result 1\n\n##\n## Spinbox widget VALIDATION tests\n##\n# The validation tests build each one upon the previous, so cascading\n# failures aren't good\n#\n# 19.* test cases in previous version highly depended on the previous\n# test cases. This was replaced by inserting recently set configurations\n# that matters for the test case\n\ntest spinbox-19.1 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 a\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 0 a {} a all key}\n\ntest spinbox-19.2 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 a   ;# previous settings\n    .e insert 1 b\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 1 ab a b all key}\n\ntest spinbox-19.3 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 ab   ;# previous settings\n    .e insert end c\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 1 2 abc ab c all key}\n\ntest spinbox-19.4 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 abc   ;# previous settings\n    .e insert 1 123\n    list $validationData $textVar\n} -cleanup {\n    destroy .e\n} -result {{.e 1 1 a123bc abc 123 all key} a123bc}\n\ntest spinbox-19.5 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 a123bc   ;# previous settings\n    .e delete 2\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 0 2 a13bc a123bc 2 all key}\n\ntest spinbox-19.6 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 a13bc   ;# previous settings\n    .e configure -validate key\n    .e delete 1 3\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e 0 1 abc a13bc 13 key key}\n\ntest spinbox-19.7 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focus \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abc                 ;# previous settings\n    set validationData {}\n    .e insert end d\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest spinbox-19.8 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e configure -validate focus    ;# previous settings\n    .e insert end abcd              ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focus focusin}\n\ntest spinbox-19.9 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focus \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd      ;# previous settings\n    focus -force .e         ;# previous settings\n    update                  ;# previous settings\n# update necessary to process FocusIn event\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focus focusout}\n\ntest spinbox-19.10 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd          ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} all focusin}\n\ntest spinbox-19.11 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd          ;# previous settings\n    focus -force .e             ;# previous settings\n# update necessary to process FocusIn event\n    update                      ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} all focusout}\n\ntest spinbox-19.12 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focusin \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert 0 abcd              ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focusin focusin}\n\ntest spinbox-19.13 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focusin \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd              ;# previous settings\n    set validationData {}\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest spinbox-19.14 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd              ;# previous settings\n    set validationData {}           ;# previous settings\n    focus -force .e\n# update necessary to process FocusIn event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {}\n\ntest spinbox-19.15 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd              ;# previous settings\n    set validationData {}           ;# previous settings\n    focus -force .e                 ;# previous settings\n# update necessary to process FocusIn event\n    update                          ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    set validationData\n} -cleanup {\n    destroy .e\n} -result {.e -1 -1 abcd abcd {} focusout focusout}\n\n# the same as 19.16 but added [.e validate] to returned list\ntest spinbox-19.16 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd              ;# previous settings\n    set validationData {}           ;# previous settings\n    focus -force .e                 ;# previous settings\n# update necessary to process FocusIn event\n    update                          ;# previous settings\n    focus -force .\n# update necessary to process FocusOut event\n    update\n    list [.e validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {1 {.e -1 -1 abcd abcd {} all forced}}\n\n\ntest spinbox-19.17 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate focuso \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    .e insert end abcd              ;# previous settings\n    set textVar newdata\n    list [.e cget -validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {focusout {.e -1 -1 newdata abcd {} focusout forced}}\n\n\n# Note: changed validateCmd - returns 0\ntest spinbox-19.18 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd3 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    set textVar newdata                 ;# previous settings\n    .e configure -validate all\n    set textVar nextdata\n    list [.e cget -validate] $validationData\n} -cleanup {\n    destroy .e\n} -result {none {.e -1 -1 nextdata newdata {} all forced}}\n\n\n## This sets validate to none because it shows that we prevent a possible\n## loop condition in the validation, when the spinbox textvar is also set\n# proc validateCmd2 used\ntest spinbox-19.19 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd3 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    set textVar nextdata                 ;# previous settings\n\n    .e configure -validatecommand $validateCmd2\n    .e validate\n    list [.e cget -validate] [.e get] $validationData\n} -cleanup {\n    destroy .e\n} -result {none nextdata {.e -1 -1 nextdata nextdata {} all forced}}\n\n## This leaves validate alone because we trigger validation through the\n## textvar (a write trace), and the write during validation triggers\n## nothing (by definition of avoiding loops on var traces).  This is\n## one of those \"dangerous\" conditions where the user will have a\n## different value in the spinbox widget shown as is in the textvar.\ntest spinbox-19.20 {spinbox widget validation} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate all \\\n\t-validatecommand $validateCmd1 \\\n\t-invalidcommand bell \\\n\t-textvariable textVar \\\n\t-background red -foreground white\n    pack .e\n    set textVar nextdata                 ;# previous settings\n    .e configure -validatecommand $validateCmd2 ;# prev\n    .e validate                     ;# previous settings\n\n    .e configure -validate all\n    set textVar testdata\n    list [.e cget -validate] [.e get] $textVar $validationData\n} -cleanup {\n    destroy .e\n} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}\n\n## This leaves validate alone because we trigger validation through the\n## textvar (a write trace), and the write during validation triggers\n## nothing (by definition of avoiding loops on var traces).  This is\n## one of those \"dangerous\" conditions where the user will have a\n## different value in the entry widget shown as is in the textvar.\ntest spinbox-19.21 {spinbox widget validation - bug 40e4bf6198} -setup {\n    unset -nocomplain textVar validationData\n} -body {\n    spinbox .e -validate key \\\n\t-validatecommand $validateCmd2 \\\n\t-textvariable textVar\n    pack .e\n    set textVar origdata\n    .e insert 0 A\n    list [.e cget -validate] [.e get] $textVar $validationData\n} -cleanup {\n    destroy .e\n} -result {none origdata mydata {.e 1 0 Aorigdata origdata A key key}}\n\n##\n## End validation tests\n##\n\ntest spinbox-20.1 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %2f\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.2 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %2.2f\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.3 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %.2f\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.4 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %2.f\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.5 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %2e-1f\n} -cleanup {\n    destroy .e\n}  -returnCodes error -result {bad spinbox format specifier \"%2e-1f\"}\ntest spinbox-20.6 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format 2.2\n} -cleanup {\n    destroy .e\n}  -returnCodes error -result {bad spinbox format specifier \"2.2\"}\ntest spinbox-20.7 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %2.-2f\n} -cleanup {\n    destroy .e\n}  -returnCodes error -result {bad spinbox format specifier \"%2.-2f\"}\ntest spinbox-20.8 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format %-2.02f\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.9 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format \"% 2.02f\"\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.10 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format \"% -2.200f\"\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.11 {spinbox config, -format specifier} -body {\n    spinbox .e\n    .e config -format \"%09.200f\"\n} -cleanup {\n    destroy .e\n} -returnCodes ok\ntest spinbox-20.12 {spinbox config, -format specifier does something} -setup {\n    spinbox .e\n    set out {}\n} -body {\n    .e config -format \"%02.f\"\n    .e config -values {} -from 0 -to 10 -increment 1\n    lappend out [.e set 0]; # set currently doesn't force format\n    .e invoke buttonup\n    lappend out [.e set]; # but after invoke it should be formatted\n    lappend out [.e set 3]; # set currently doesn't force format\n    .e config -format \"%03.f\"\n    lappend out [.e set]; # changing -format should cause formatting\n} -cleanup {\n    destroy .e\n} -result {0 01 3 003}\n\n\ntest spinbox-21.1 {spinbox button, out of range checking} -body {\n    spinbox .e -from -10 -to 20 -increment 2\n    set out {}\n    lappend out [.e get]; # -10\n    .e delete 0 end\n    .e insert 0 25; # set outside of range\n    .e invoke buttondown; # should constrain\n    lappend out [.e get]; # 20\n    .e delete 0 end\n    .e insert 0 25; # set outside of range\n    .e invoke buttonup; # should constrain\n    lappend out [.e get]; # 20\n    .e delete 0 end\n    .e insert 0 -100; # set outside of range\n    .e invoke buttonup; # should constrain\n    lappend out [.e get]; # -10\n    .e delete 0 end\n    .e insert 0 -100; # set outside of range\n    .e invoke buttondown; # should constrain\n    lappend out [.e get]; # -10\n    .e delete 0 end\n    .e insert 0 bogus; # set to a bogus value\n    .e invoke buttondown; # should use fromValue\n    lappend out [.e get]; # -10\n    .e delete 0 end\n    .e insert 0 19; # set just inside of range\n    .e invoke buttonup; # no wrap\n    lappend out [.e get]; # 20\n    .e invoke buttonup; # no wrap\n    lappend out [.e get]; # 20\n    .e invoke buttondown\n    lappend out [.e get]; # 18\n    .e delete 0 end\n    .e insert 0 -9; # set just inside of range\n    .e invoke buttondown; # no wrap\n    lappend out [.e get]; # -10\n    .e invoke buttondown; # no wrap\n    lappend out [.e get]; # -10\n    .e invoke buttonup; # no wrap\n    lappend out [.e get]; # -8\n\n    .e configure -wrap 1\n    .e delete 0 end\n    .e insert 0 19; # set just inside of range\n    .e invoke buttonup; # wrap\n    lappend out [.e get]; # -10\n    .e invoke buttonup\n    lappend out [.e get]; # -8\n    .e invoke buttondown\n    lappend out [.e get]; # -10\n    .e delete 0 end\n    .e insert 0 -9; # set just inside of range\n    .e invoke buttondown; # wrap\n    lappend out [.e get]; # 20\n    .e invoke buttondown\n    lappend out [.e get]; # 18\n    .e invoke buttonup; # no wrap\n    lappend out [.e get]; # 20\n} -cleanup {\n    destroy .e\n} -result {-10 20 20 -10 -10 -10 20 20 18 -10 -10 -8 -10 -8 -10 20 18 20}\n\ntest spinbox-22.1 {spinbox config, -from changes SF bug 559078} -body {\n    set val 5\n    spinbox .e -from 1 -to 10 -textvariable val\n    set val\n} -cleanup {\n    destroy .e\n} -result 5\ntest spinbox-22.2 {spinbox config, -from changes SF bug 559078} -body {\n    set val 5\n    spinbox .e -from 1 -to 10 -textvariable val\n    .e configure -from 3 -to 10\n    set val\n} -cleanup {\n    destroy .e\n} -result 5\ntest spinbox-22.3 {spinbox config, -from changes SF bug 559078} -body {\n    set val 5\n    spinbox .e -from 3 -to 10 -textvariable val\n    .e configure -from 6 -to 10\n    set val\n} -cleanup {\n    destroy .e\n} -result 6\n\ntest spinbox-23.1 {selection present while disabled, bug 637828} -body {\n    spinbox .e\n    .e insert end 0123456789\n    .e select from 3\n    .e select to 6\n    set out [.e selection present]\n    .e configure -state disabled\n# still return 1 when disabled, because 'selection get' will work,\n# but selection cannot be changed (new behavior since 8.4)\n    .e select to 9\n    lappend out [.e selection present] [selection get]\n} -cleanup {\n    destroy .e\n} -result {1 1 345}\n\ntest spinbox-24.1 {error in trace proc attached to the textvariable} -setup {\n    destroy .s\n} -body {\n    trace add variable myvar write traceit\n    proc traceit args {error \"Intentional error here!\"}\n    spinbox .s -textvariable myvar -from 1 -to 10\n    catch {.s set mystring} result1\n    catch {.s insert 0 mystring} result2\n    catch {.s delete 0} result3\n    catch {.s invoke buttonup} result4\n    list $result1 $result2 $result3 $result4\n} -cleanup {\n    destroy .s\n} -result [list {can't set \"myvar\": Intentional error here!} \\\n    {can't set \"myvar\": Intentional error here!} \\\n    {can't set \"myvar\": Intentional error here!} \\\n    {can't set \"myvar\": Intentional error here!}]\n\ntest spinbox-25.1 {textvariable lives in a non-existing namespace} -setup {\n    destroy .s\n} -body {\n    catch {spinbox .s -textvariable thisnsdoesntexist::myvar} result1\n    set result1\n} -cleanup {\n    destroy .s\n} -result {can't trace \"thisnsdoesntexist::myvar\": parent namespace doesn't exist}\ntest spinbox-25.3 {Bugs [2a32225cd1] and [9fa3e08243]} -setup {\n    destroy .s\n    pack [spinbox .s]\n    update\n    set res {}\n} -body {\n    .s insert end \"A sample text\"\n    .s icursor end\n    event generate .s <<PrevWord>>  ; # shall move insert to index 9\n    .s delete insert end\n    lappend res [.s get]\n    .s delete 0 end\n    .s insert end \"A sample text\"\n    .s icursor 2\n    event generate .s <<NextWord>>  ; # shall move insert to index 9\n    .s delete 0 insert\n    lappend res [.s get]\n} -cleanup {\n    destroy .s\n} -result {{A sample } text}\n\n#\n# TESTFILE CLEANUP\n#\n\nforeach i {1 2 3} {\n    unset validateCmd$i\n}\nunset i\ntestutils forget entry scroll\ncleanupTests\n"
  },
  {
    "path": "tests/systray.test",
    "content": "# This file is a Tcl script to test systray and sysnotify features in Tk.\n#\n# Copyright © 2020 Kevin Walzer\n# Copyright © 2020 Francois Vogel\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# TESTS\n#\n\ntest systray-1 {systray icon creation, all options} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"Systray sample\" \\\n\t    -button1 {puts \"button 1 click\"} -button3 {puts \"button 3 click\"}\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {}\n\ntest systray-2 {systray create, argument checking} -body {\n    tk systray create\n} -returnCodes error -result {missing required option \"-image\"}\n\ntest systray-3 {systray create, argument checking} -body {\n    tk systray create -text Hell\n} -returnCodes error -result {missing required option \"-image\"}\n\ntest systray-4 {systray create, argument checking} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -gorp invalidOption\n} -returnCodes error -result {unknown option \"-gorp\": must be -image, -text, -button1 or -button3}\n\ntest systray-5 {systray icon creation, only required option present} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {}\n\ntest systray-6 {systray icon creation, some options present} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -button3 {puts b3}\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {}\n\ntest systray-7 {systray icon, all parameters modification, introspection} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n    image create photo _page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7\n} -body {\n    tk systray create -image _book -text \"Systray icon text\"\n    tk systray configure -image _page\n    tk systray configure -text \"Another text for my icon\"\n    tk systray configure -button1 {set a 1}\n    tk systray configure -button3 {set b 2}\n    tk systray configure\n} -cleanup {\n    tk systray destroy\n    image delete _book\n    image delete _page\n} -result {-image _page -text {Another text for my icon} -button1 {set a 1} -button3 {set b 2}}\n\ntest systray-8 {systray icon, single parameter modification, introspection} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"Systray icon text\" -button1 {puts b1}\n    tk systray configure -button1 {set a 1}\n    tk systray configure -button1\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {set a 1}\n\ntest systray-9 {systray icon, several parameters modification at once, introspection} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"Systray icon text\" -button1 {puts b1}\n    tk systray configure -button1 {set a 1} -text NewText\n    list [tk systray configure -button1] [tk systray configure -text]\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {{set a 1} NewText}\n\ntest systray-10 {configure non-existing systray icon} -setup {\n    catch {tk systray destroy}\n} -body {\n    tk systray configure\n} -returnCodes error -result {systray not created}\n\ntest systray-11 {destroy non-existing systray icon} -setup {\n    catch {tk systray destroy}\n} -body {\n    tk systray destroy\n} -returnCodes error -result {systray not created}\n\ntest systray-12 {destroy systray icon works} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book\n    tk systray destroy\n    tk systray create -image _book\n} -result {}\n\ntest systray-13 {systray icon creation, attempt to create more than one in an interp} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book\n    tk systray create -image _book\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -returnCodes error -result {only one system tray icon supported per interpeter}\n\ntest systray-14 {systray icon creation, create one per interp, visibiliy checks} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"first interp\"\n    childTkInterp second\n    # create the icon in the 'second' interp\n    second eval {\n\t# should trigger an error: image _book unknown in 'second' interp'\n\t# image from higer interp should not be visible by 'tk systray'\n\ttk systray create -image _book -text \"second interp\"\n    }\n} -cleanup {\n    tk systray destroy\n    image delete _book\n    interp delete second\n} -returnCodes error -result {image \"_book\" does not exist}\n\ntest systray-15 {systray icon creation, create one per interp} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"first interp\"\n    childTkInterp second\n    # create the icon in the 'second' interp\n    second eval {\n\timage create photo _page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7\n\ttk systray create -image _page -text \"second interp\"\n    }\n} -cleanup {\n    second eval {\n\ttk systray destroy\n\timage delete _page\n    }\n    interp delete second\n    tk systray destroy\n    image delete _book\n} -result {}\n\ntest systray-16 {systray icon creation from a bitmap, on Linux and macOS only} -constraints {\n    macOrUnix\n} -setup {\n    set data1 {\n\t#define foo_width 16\n\t#define foo_height 16\n\tstatic unsigned char foo_bits[] = {\n\t   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t   0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0xff\n\t};\n    }\n    image create bitmap cross -data $data1\n} -body {\n    tk systray create -image cross\n} -cleanup {\n    tk systray destroy\n    image delete cross\n} -result {}\n\ntest systray-17 {systray icon existence check} -setup {\n    catch {tk systray destroy}\n} -body {\n    tk systray exists\n} -result {0}\n\ntest systray-18 {systray icon existence check} -setup {\n    catch {tk systray destroy}\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n} -body {\n    tk systray create -image _book -text \"Systray test\"\n    tk systray exists\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {1}\n\n\ntest sysnotify-1 {system notification popup} -setup {\n    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==\n    tk systray create -image _book -text \"Systray sample\"\n} -body {\n    tk sysnotify {Alert} {This is an alert}\n} -cleanup {\n    tk systray destroy\n    image delete _book\n} -result {}\n\ntest sysnotify-2.1 {system notification stems from a systray icon on Windows} -constraints {\n    win\n} -setup {\n    catch {tk systray destroy}\n} -body {\n    tk sysnotify {Alert} {This is an alert}\n} -returnCodes error -result {must create a system tray icon with the \"tk systray\" command first}\ntest sysnotify-2.2 {system notification is not linked to any systray icon on X11 or aqua} -constraints {\n    macOrUnix\n} -setup {\n    catch {tk systray destroy}\n} -body {\n    tk sysnotify {Alert} {This is an alert}\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget child\ncleanupTests\n"
  },
  {
    "path": "tests/teapot.ppm",
    "content": "P6\n256 256\n255\n\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[7 eOLjQLmSMoTMnSMlRMhPL_9 \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\nSMtVMzYN~[N~[N\\N\\O\\O]O]O]O]O\\O\\O}[NyYNtVM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\G-\u001ewXN}[N]O^O_O`O`O`O`OaOaOaOaOaOaOaOaO`O_O^O\\N\u000b\u000f\u0018\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aMLyYN_OaPbPcPcPdPdPdPdPdPdPdPdPdPePePePePePdPcP_OpUM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\wXN_OdPfPgQhQhQiQiQiQiQiQjQjQjQjQjQjQjQjQjQjQiQfP`O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJiQLbPhQkQmRnRoRoRoRoRoRoRoRoRpRpSqSqSrSrSrSqSoRjQ]O\\KK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fOLrUMcPlRqStSuTwTxTxTyTyTzTzUzUzUzUzUyTxTwTtSmRaOhPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\a0\tcNLqUM\\OfQpSwVzV|V}VVVǀVɂW̅[ՏewꪅĈgqTfQ{ZNYIK9\u001c\u0005\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\O1\u001e{G#J\u0011kRMqUMtVNiSv\\dbzZvUuTsSqSnRjQeP^OrUMH\u0011h>!T4\u001f\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\G-\u001eV5\u001fwE\"~I#M%U+e7l:g2b*a(`(^(])^-]1S,qC$`9 R3\u001fG-\u001e\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@)\u001dJ/\u001ei>!pA\"tD\"wF$yH&xH&tE$wE#yG%}M+T4S5mE*Z7!K/\u001eB*\u001d;'\u001c\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aOoR{UǀVυX<(\u001dF-\u001ea: e<!h>!j@#k@$h>\"d<!c=$hD-fF2[<)K0\u001f@)\u001d;'\u001c5$\u001c˂VǀV|U_LKYIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\_OxTɂW֒k|X>f-^(Z'W&T&N\u000f>)\u001dF-\u001eJ/\u001eb; g>#nD(jB&c<!b=%jH2_A/I0!<(\u001d8&\u001c5$\u001cJ\u000eY\u001dS%8&\u001c;'\u001c?)\u001dE,\u001d<:HA=HE?IJAISFJYIKXIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\nR}UܘqʊevUe,V&V\u0018C\r@\f|>\fy<\fu:\u000br9\u000bo7\u000bl6\nj5\nh4\ng3\n5$\u001cD,\u001dK/\u001eb; h>\"wM1tK.e=\"a<#cA,U8&E-\u001e<(\u001d9&\u001c.!\u001ba0\tb1\tc1\t\u0011\b\u0001\u0011\b\u0001\u0011\b\u0001\u0011\b\u0001\u0012\t\u0001\u0012\t\u0001\u0012\t\u0001\u0014\n\u0002\u001d\u0012\n+\u001f\u001b3#\u001c@)\u001d46G<:HMCIXHK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\U*\bvT~X{Yk+W&N$|>\fu:\u000bp8\u000bk5\nf3\na0\t_/\t].\t[-\tI\u0011\\*_(L\u0016kRMmSMmSMnSMnSMD,\u001dR3\u001fW5\u001fmA\"|O0|P1j?\"c<!a=%Y7\"N1\u001eF,\u001e;'\u001cNCJNCJNDJODJODJODJh>!a: X/\u0010K%\u0007\u0005\u0002\u0000\u0005\u0002\u0000\u0000\u0000\u0000\u0006\u0003\u0001\u0002\u0001\u0000\u0003\u0001\u0000\u0004\u0002\u0000\u0006\u0003\u0000\u0017\u0015\u0019&\u001d\u001a4$\u001c+2F=;HPEJL&\u0007\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\lRxTsTd)O$w;\u000bm6\ng3\na0\tZ-\t\\/\fT*\bQ(\bH\u0015m8kRMmSMnTMoTMpTMpUM15G15G05G04G04GpUMpTM5\u001a\u0005^9 d<!yF#O+N,rC#qB\"pB#k?\"a: Z7 6\u001b\u0005ODJPDJPEJQEJQEJREJREJREJRFJSFJSFJSFJSFJe<!X/\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0004\b\u0000\u0000\u0000\u0002\u000b\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0001\u0000\u0015\u0014\u0019- \u001b'0FqSgQ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPtSmRR%B\u000ff3\n^/\tV+\bQ(\bL&\u0007I$\u0007r9\u000bT\u0018lRMnSM46G47G47G46G46G46G46G46G36G36G25G25G15G04G/4F.3F\u0000\u0000\u0000oA\"N$O%S)R)T&T%R%O$J#xE#\u0003\u0001\u0000PDJQEJREJRFJSFJTFJTFJTGJUGJUGJUGJUGJVGJVGJVGJVGJVGJVGJY6\u001fN'\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000\u0000t;\u000eO$dPoRdP\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\pSkQS%x=\u000e[-\tR)\bI$\u0007E\"\u0006@ \u0006\u0000\u0000\u0000M\u0017]'pTM68G78G78G78G78G78G78G78G78G68G67G67G57G57G47G36G36G25Gp9\u000e8\u001c\u0005eOLpUMtVMn7\u000bf+i,i*i*h*B\r`O~[NqUM[-\tH\u0016UGJUGJVGJVGJVHJWHJWHJWHKWHKXHKXHKXHKXHKXHKXIKXIKXIKXIKXIKh>!Y0\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000\u0000W+\b].\ts=\u0013M$dPlR\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\oTMoRdPvE\"V+\bK%\u0007A \u00069\u001c\u00059\u001c\u0005\u0000\u0000\u0000F\u0015['qUMtVM99H:9H:9H:9H:9H:9H:9H:9H:9H:9H99H99H99H99H99H99H:9H;:H>;HB=HPDJ\\JKmSMwXN|ZNy[ᦆ֘u{WyU]btUnRhQaO{ZNvWNtVMvXNwXNyYNzYN{ZN|ZN}[N}[N~[N~[N~[N~[N~[N~[N~[N}[N}[N{ZNzYNxXNL$f3\n\u0000\u0000\u0000I$\u0007L&\u0007P(\bU*\b\\.\tJ#\\OjQ\b\u000e\u0017\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\kRaOo9\rL&\u0007C!\u0006:\u001d\u00054\u001a\u0005\u0000\u0000\u0000f3\nX&pUMuWMwXNxXN<:H<:H<:H<:H<;H<;H<;H<;H=;H=;H=;H=;H>;H>;H?<H@<HA=HC>HG@ILBIREJ[JKcNLjQLpRuTzU~VȁW˂X֎csҎe{VvTpSkRgQbP_O^O]O\\O\\O\\O\\O]O]O]O]O]O]O]O]O]O]O]O\\O\\O~\\N}[N|ZNxXNT%H$\u0007\u0000\u0000\u0000G#\u0007K%\u0007Q(\bW+\bzG#nTMiQ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\dOLrUMuWNwXNyYN{ZN}[N{ZNwXNsVM\u0002\u000b\u0017\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\`OcPnA\"M&\u0007@ \u00068\u001c\u0005F#\u0007\u0000\u0000\u0000m6\nW&rVMvWNyYNzYN|ZN}[N}[N><H?<H?<H?<H?<H?<H@<H@<H@<HA=HA=HB=HC>HE?IG@IIAIKBIODJSFJWHKhQlRpRb(i*n+|7|6r,q+p-l+g)b(sSpSlRiQgQePcPaPaO`O`O_O_O_O_O_O_O_O_O_O_O^O^O^O^O]O]O\\O~[N{ZNT%\u0000\u0000\u0000F#\u0007B!\u0006Y,\bL&\u0007U*\b~I#^O`O\u0013\\\u0013\\\u0013\\\u0013\\cNLrUMzYN\\O^O`ObPcPdPePfPfPfQfQfQePcPaP~[N\u0000\u0003\b\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPsVM^/\tC!\u00067\u001b\u0005\u001b\r\u0002\u0000\u0000\u0000\u0000\u0000\u0000Q%tVMwXNzYN|ZN}[N\\N\\O\\O]O]O]O]OA=HB=HB=HB>HC>HC>ID?IE?IF@IG@IIAIKBIcPdPePgQiQlRnR\\'d)i*m+s/s/o+n+l*i*g)c(_(qSoRmRkQiQgQfPePdPcPbPbPbPaPaPaOaOaO`O`O`O`O`O`O_O_O^O^O]O\\O}[NQ\u0017\u0001\u0000\u0000D\"\u0006?\u001f\u0006D\"\u0006K%\u0007_/\tkRLfPODJSFJ_ObPcPePfQgQiQjQkRlRmRnRnRoRoRoRnRmRlRiQeP_O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\B+\u001dePI#L&\u00079\u001c\u00050\u0018\u0004\u0000\u0000\u0000\u001c\u000e\u0002y<\fP\u0017xXN{ZN}[N\\N\\O]O]O^O^O^O_O_O_O_O`O`O`O`OaOaPbPbPcPdPePfPgQhQiQkRmRZ'_(e)h)k*n,n,m*l*j*f)e)c(_(]'pRnRmRkRjQiQgQgQfPePdPdPdPcPcPcPbPbPbPbPbPaPaPaOaO`O`O_O_O^O]O_(@\f\u0000\u0000\u0000B!\u0006I$\u0007B!\u0006N'\u0007w=\u000feP`LKbNLeOLkRmRnRoRpSqSrSsStStStSuSuStStSsSrSpSmRjQbPjQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\bPpTME\"\u00065\u001a\u0005\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000M$tVM{ZN}[N\\O]O^O^O_O_O_O`O`O`O`OaOaPaPbPbPbPcPcPdPdPePfPgQhQiQjQkRlRmRZ'`(d)g)g\u001bj*j*i*i*g)d)c(a(_(\\'pRoRnRmRkRjQiQiQhQgQgQfPePePePdPdPdPcPcPcPcPcPbPbPbPbPaPaO`O_O^O\\NQ\u0017\u0000\u0000\u0000\b\u0004\u0000@ \u0006<\u001e\u0006G#\u0007_LKcPlSMnTMpUMsVMtSuTvTwTwTxTxTwTwTvTuTtSsSqSpSoRnRkRhQbPeOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\wXN\\NJ%\u00070\u0018\u0004\u0000\u0000\u0000\u0000\u0000\u00001\u0018\u0004J\u0016vWN}[N\\O]O^O_O_O`O`O`OaOaPaPbPbPbPbPcPcPdPdPdPePePfQgQgQhQiQjQkQlRmRY&]'`(c(e)c\u001b\\\u0012\\\u0012\\\u0012]\u0012]\u0013^\u001aa(`(^'['['oRnRmRlRkRkQjQiQiQhQgQgQgQfQfPePePePePdPdPdPdPdPcPcPcPbPbPaPaO`O]OO\u0017\u0000\u0000\u0000\u0000\u0000\u0000G#\u00077\u001b\u0005F#\u0007uWM^OwXNxXNzYN{ZN|ZNyTyTxTwTuTsSpSmRjQgQdPbPaPaPbPcPePcP|ZN\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[JKbP^/\t1\u0018\u0004\f\u0006\u00010\u0018\u00041\u0018\u0004|>\fwXN}[N]O^O_O`O`OaOaPaPbPbPbPcPcPcPcPdPdPdPePePfPfQgQgQhQhQiQjQkQkRlRmRY&]'`(b([\u0012g\u001ci\u001dh\u001df\u001bd\u001be\u001bc\u001bU\u0011_(]'['Z'nRnRmRmRlRkRkQjQjQiQiQhQhQgQgQgQfQfQfPfPePePePePePdPdPdPcPcPbPbP`O^OD\r\u0000\u0000\u0000\u0000\u0003\b\u0000\u0003\b4\u001a\u0005M&\u0007dPnSM|[N|[O|[OzZOxXNrSnRhQcP^OvXNiQL^KKRFJMCJJAIKBISFJ\\JKnSMxYN_O\\OaMK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\B!\u0006qUMaPC!\u0006/\u0017\u00040\u0018\u00040\u0018\u0004a0\tuWN}[N]O_O`O`OaPaPbPbPcPcPcPcPdPdPdPePePePfPfQfQgQgQhQhQiQiQjQjQkRlRlRX&['^'`(Z\u0012d\u001bf\u001ci\u001eg\u001dd\u001bc\u001bc\u001ba\u001a_\u001aT\u0010\\'['Z'Y&nRmRmRlRlRkRkQjQjQjQiQiQhQhQhQhQgQgQgQgQfQfQfQfPfPePePePdPdPcPbPaO^Ox<\f\u0000\u0000\u0000\u0004\u0002\u0000\u0000\u0000\u0000:\u001d\u0005aP]Oj8\u0012sVMmSMfOL^KKUGJIAIQEJ?<H*1F(\u001e\u001b\u0015\u000e\n\n\b\t\b\u0007\b\u0007\u0006\b\u0011\n\u0005@%\u0010<-$G?@pfdNLuWM\\NdNL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TFJvWNaP.\u0017\u0004/\u0017\u00040\u0018\u00041\u0018\u0004E\u0015}[N]O_O`OaPbPbPcPcPcPdPdPdPePePePePfPfQfQgQgQgQhQhQhQiQiQjQjQkQkRlRlRY&\\'^'^\u001ab\u001ac\u001be\u001ci g\u001ec\u001bb\u001aa\u001b`\u001a^\u001a]\u001aX\u0014['Z'Y&mRmRmRlRlRlRkRkQkQjQjQjQiQiQiQiQhQhQhQhQgQgQgQgQgQfQfQfQfPePePdPcPaPO\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`O`OoTMQEJC>IeZY638*\u0019\u000e\u0005\f\u0017\u0006 B\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u000e\u001b,\u0001\u0005\u000b\u0001\u0005\u000b4\u001c\t.\u0017\u0004G1!\\TUrsVM{ZN`MK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[JKyYNbP/\u0017\u00040\u0018\u0004\u0000\u0000\u0000\u0000\u0000\u0000N$]O_O`ObPbPcPcPdPdPdPePePePfPfPfQfQgQgQgQgQhQhQhQiQiQiQjQjQkQkRkRlRO\u0012Z'\\'^'V\u0011a\u001ab\u001be\u001di!f\u001eb\u001ba\u001a`\u001a_\u001b]\u001a\\\u0019Z\u0012['Z'Y&Q\u0017mRmRmRlRlRlRkRkRkQkQjQjQjQjQiQiQiQiQiQhQhQhQhQhQhQgQgQgQgQfQfPdPcPW&\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000dPaPrUM\u001b\u0011\n\u0006 B\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0019%7\u0003\u0010!\u0003\u0010!C*\u0019F#\u0007P)\f{dYzep\\OgPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ`LKvWNaPm6\n\f\u0006\u0001\u0000\u0000\u0000X,\buWM]O`ObPcPdPdPdPePePfPfPfQfQgQgQgQgQgQhQhQhQiQiQiQiQjQjQjQkQkQkRlRlRZ'\\']'_\u001a`\u001aa\u001ab\u001be\u001ei\"e\u001ea\u001b`\u001a_\u001b_\u001b]\u001a\\\u0019\\\u0019Y\u0019Z'Z'Z'mRmRmRlRlRlRlRlRkRkRkRkQkQjQjQjQjQjQjQiQiQiQiQiQiQiQhQhQhQgQgQfQdP_Oq8\u000b\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000gQ`OuWMT%\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0003\u0010!\u0003\u0010!T,\u000ec5\u0011F\u0016T3ț~Ɠq^OfOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XHK_LKsVM`OcP\u0000\u0000\u0000\u0000\u0000\u0000\u0013\t\u0001S%]ObPcPdPePePfPfQfQgQgQgQgQgQhQhQhQhQiQiQiQiQiQjQjQjQjQkQkRkRlRlRlR\\']'^'V\u0011`\u001aa\u001ab\u001bf\u001ei\"e\u001ea\u001b`\u001a_\u001b_\u001b]\u001a\\\u0019\\\u0019R\u0010Z'Z'['mRmRmRmRmRlRlRlRlRlRlRkRkRkRkRkQkQjQjQjQjQjQjQjQjQjQjQiQiQiQhQgQePS\u0010q8\u000b\u0000\u0000\u0000\u0000\u0000\u0000aOgQ`OtVMX&\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0006 B\u0002\u000b\u0017l@!{A\u0014L$Y'afPaO]KK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ODJ[JKaMKqUM\\OcP^O\u0000\u0000\u0000\u0000\u0000\u0000vE\"]OaPdPePfPfQgQgQgQhQhQhQhQhQiQiQiQiQiQjQjQjQjQjQkQkQkRkRkRlRlRlRlR^'^'_(W\u0011a\u001aa\u001ac\u001cg i\"e\u001ea\u001b`\u001a_\u001b_\u001c^\u001b\\\u001a\\\u0019R\u0010['[']'mRmRmRmRmRmRmRlRlRlRlRlRlRlRlRlRlRkRkRkRkRkRkRkRkRkQkQkQjQjQiQhQePW&M&\u0007\u0000\u0000\u0000oTMiQeP_OtVMmSMdOL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0006 B\u0002\u000b\u0017\u001a\u0017\u0019J\u0011Z'_(kQiQ`OSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TFJ\\JKcNLlRMzYN`OePzZN\u0000\u0000\u0000\t\u0004\u0000\\N`OdPfQgQgQhQhQhQiQiQiQiQiQiQjQjQjQjQjQjQkQkQkRkRkRlRlRlRlRlRlRmRa(`(`([\u0012a\u001ab\u001bd\u001ch!i\"d\u001da\u001b`\u001a_\u001b_\u001b^\u001b]\u001a]\u0019S\u0010\\']'_(nRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRlRlRlRlRlRlRlRlRlRlRlRlRlRkRkQiQePt:\u000b\u0000\u0000\u0000\u0000\u0000\u0000kQhQcP]OtVMlSMa2\r\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\n\u000f\u0018\u0012\u0013\u0018$\u001c\u001a5 \u000f`(e)nRjQ^OJAI\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XIK^KKdNLhPLuWM]ObPfQeP\r\u0006\u0001m6\n`OcPfQhQhQiQiQjQjQjQjQjQjQjQkQkQkQkRkRkRkRlRlRlRlRlRlRlRmRmRmRmRg)c(c(b(V\u0011c\u001be\u001di!i!d\u001db\u001b`\u001a`\u001a_\u001b_\u001b^\u001aQ\u0010]'_(`(f)nRnRnRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRmRmRmRmRnRmRmRnRmRmRmRmRkRhQG\u0015a0\tbPmRjQfQaP}[NrUMmSML$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\r#C\u0012\u0013\u0018\u0018\u0016\u0019, \u001b8&\u001cH.\u001fZ7 pRjQ{ZN\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QEJ[JK`LKdNLhQLqUM{ZN_OcPgQhQ\u0000\u0000\u0000\u0018\u000f\nbPePhQiQjQjQkQkQkRkRkRlRlRlRlRlRlRlRlRlRlRmRmRmRmRmRmRmRmRmRnRnRj*g)e)d)d\u001bX\u0011g\u001dh\u001fe\u001cc\u001bb\u001ab\u001bb\u001bU\u0011`(a(a(c(i*oRoRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRoRoRoRoRoRoRoRoRoRoRoRoRnRmRjQQ%Z-\tjQnRlRhQdP_OuWMpTMnSMkRLa: \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B\u0013&D\u001b\u0017\u0019\u001e\u0019\u001a2\u001c\r@*\u001dS6#G@IPDJhQmSM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ]KKbMLeOLiQLlRMvWN\\OaOePhQjQgQ\u0007\u0003\u0000oTMgQiQkQlRlRlRmRmRmRmRmRmRmRmRmRmRmRmRmRmRnRnRnRnRnRnRnRnRnRnRnRnRl*l+j+g)f)e)d)e)e)e)e)f)i*s0s.oRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRpRpRpRpRpRpSpSpSqSqSqSqSpSqSpSnRlRI\u0011hQpRoRmRiQePaP\\OsVMpTMnTMlRMX)\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0011%C\u001a)D\u001d\u0018\u0019$\u001c\u001a;\u001d\u0005J/\u001f[8\"LBITGJYIKWHK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK_LKcNLgPLjQLlRMpUMzYN^ObPePhQkQlRfQ- \u001bhQjQlRmRnRnRnRnRnRnRnRnRnRnRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRoRpRpRpRp\u0016y-w-w-y.{-u\u001epSpSpSpSpSpSpSpSpSpSpSpSpSpSpSqSqSqSqSqSqSqSqSqSrSrSrSrSrSrSrSsSrSqSoRiQiQqSqSpRmRjQgQcP_O{ZNtVMpUMoTMmSMjQL_9 \u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u000b\"C\u0017(D\u001b\u0017\u0019#\u001b\u001a*\u001f\u001bA$\u000e[<)d<!QEJWHKXHKD>I\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JKaMKeOLhPLkRLmSMoTMuWM}[N_ObPePhQkRmRnRkR!-EkRmRnRoRpRpRpSpSpSpSpSpSpSpRpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSpSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSqSrSrSrSrSrSrSrSrSrSrSsSsSsSsStStStStStSuStSsSrSnRoRsSsSrSpRmRjQgQdPaO\\OyYNuWMqUMoTMnSMkRLo8\r\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0015'D\u001e+E$\u001c\u001a(\u001e\u001b1\u001b\u000bJ/\u001ejH1NCJUGJYIKUGJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\XHK]KKbNLfOLiQLkRMmSMoTMqUMxXN\\N_ObPfPhQkQmRoRpSpRhQmRoRpSqSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSrSsSsSsSsSsSsSsSsSsSsSsSsStStStSuSuSuTuTuTuTuTvTwTvTvTuTtSmRtSuTuStSrSpRmRkQhQePaP^O\\N{ZNvXNqUMpTMnSMlRMP%\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u000e#C\u001b*E$.E- \u001b.!\u001bG$\u0007Y:%d<\"SFJYIKZIKNCJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\PDJZIK_LKdNLgPLjQLlRMnSMpTMqUMuWMyYN\\O`OcPfPhQjQmRoRqSrSrSrSmR\u0002\u0001\u0000rSsStStStStStStStStStStStStStStStSsSsSsSsSsSsSsSsSsStStStStStStStStStStStStStStStStSuSuSuTuTvTvTvTvTvTwTwTwTwTxTxTxTyTyUxU\\'qSvTwTwTvTuTtTrSoRmRkQhQePbP`O^O\\O|ZNxXNtVMpTMoTMmSMjQLh7\u0012\u0013\\\u0013\\\u0013\\\u0006 B\u0018(D\"-E*1F, \u001b4#\u001cK)\u000fpL5PEJWHK[JKXHK:9H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UGJ\\JKaMLeOLhPLkRLmSMoTMpUMrVMvWNyYN|ZN]O`OcPePhQjQlRnRpSqSsStSuStSsSmR^/\tvTvTvTwTwTwTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTvTwTwTwTwTwTwTwTxTxTxTxTxTxTxTyTyTzUzU{U{V|VgQrSwTxTyUyUzVyVxVvUtTqSoSmRjQhQePcPbP`O_O]O}[NyYNuWMpUMoTMmSMkRL}H#\u0013\\\u0013\\\u0002\u000b\u0017\u0012&D -E(1F/!\u001b2#\u001c8\u001d\tW7\"iA&UGJ[JK\\JKREJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MCIXIK^KKcNLfOLiQLkRMmSMoTMqUMsVMwXNzYN}[N\\O^O`ObPePgQjQkRmRoRqSrStSuSvTvTwTwTuTsSlR_(yTyTyTyTyTyTyTyTyTyTxTxTxTxTxTxTyTyTyTyTyTyTyTyTyTyTyTyTyTyTyTzTzTzU{U{U{U|U|U}V~VWÀYiQrSwTyTzU|V}XZ]]]~[zYwWtUqSnSlRjQgQfPePcPbP`O_O]O~\\NzZNvXNqUMoTMnSMlRMiQLg=!\u0013\\\n!C\u001d+E'0F.4F7%\u001c8%\u001cU/\u0012lG.SFJZIK]KKZIKB=H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\REJZJK`LKdNLgPLjQLlRMnSMpTMqUMtWMxXN{ZN~[N]O^O`OaObPdPgQiQkQlRnRpSrSsStTuTvTwTxTyTyTyTyTyTxTvTrSnRhQ|U|U|U|U|U|U|U|U|U|U|U|U|U|U}U}U}U}U}U}U}U~U~U~V~VVŀWƁXa(lRrSvTyTzU|U~VXƂ[Ɇ_΋dӑjԓmԓnБlʌhĆd_{[vWsUpSnRkRiQhQgQfQePdPbPaO_O^O\\O|ZNxXNsVMpTMnTMmSMjQLC\u0015\u0006 B\u0019)D&/F-3F47G6%\u001c>\"\fY7 kA$YIK]KK^KKSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ\\KKbMLeOLhPLkRLmSMnTMpTMrUMuWNyYN|ZN\\N]O_O`OaPbPcPePfPhQjQlRnRoSqTsTuUvUwVxVyVyUzUzU{U{U{U|U|U|U|U|U{U{U{UzUzTyTyTxTwTvTvTvTvTwTwTwTxTyTzTzU{U{U|U|U}UVŀWǂYɄ\\͈_ьdٔlu|쩂ﬅ명榁ޟ{՗sˎld^yZuWqUoSlRkRjQiQhQgQfQePdPcPaP`O^O]O}[NyYNuWMpTMoTMmSMkRLgPL\u0013&D#.E,3F46G;'\u001c<(\u001dD\"\u0007iB(VGJ]KK`LK[JKB>H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^LKcNLfOLiQLkRMmSMoTMqUMsVMvXNzYN}[N\\O^O_O`OaPcPdPePfQgQhQiQkRmSoTrUtWwYzZ}\\]^^^^\\ZYX~W~W~V~V~V~V~U~U~U~UUUVVVVVƀVƀVǀWǁWȂXɃZ˅[͇^ЊaӍdؒiܗntz驅~֘vˏmÇf`z[vXrUpToSnSlRkRkRjQiQhQfQePdPcPbP`O_O]O~[NzYNvWNpTMoTMnSMkRMhQLo7\u000b,2F36G99HC+\u001d@ \u0006]8 nA\"\\JK`ML_LKSFJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JK`LKdNLgPLjQLlRMnSMpTMqUMtVMwXNzZN}[N]O^O_OaObPcPdPePfQgQhQiQjRlRmSoUrWvZ{]afŊjˏnГqӕsՖsՖrՖqՔoӒmяjύg͊cˈaɆ^Ȅ\\ǂ[ƁYŀXŀWWWVVWŀWƀWǁXȂYɃ[ʅ\\͇_ϊaҍeՑhٕmݙqvz}꧀멃몄騃奀ߠ|ٛwӕȑmƉhc~^yZvXtWsVqUpToSnSmRlRkRjQiQhQgQfPePcPbPaO_O^O\\N{ZNwXNsVMoTMnSMlRMiQL~I#26G99G?<HA*\u001dE$\ti@$ZIKaMLbML[JK;:H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\WHJ]KKbMLeOLhPLjRLlSMnTMpTMrUMuWMxXN{ZN~\\N]O^O`OaObPcPdPePfQgQhQiQkRlSmToUrWuZy]~afl˒sԚzܡ㧆諉뮋묈訄~ߞyڙt֕oҐjΌfˈbȅ_ƃ\\ŁZĀYXW~W~W~WXÀXĀYŁZƃ\\ǅ^Ɇ`ˈb̊d͋f΍gΎiΎjΎj͎jˌiǉgÆda^}]|\\{[yZxYvXtWsVqUpToSnSmRlRkRjQiQhQgQfPePdPbPaO_O^O\\O|ZNxXNtVMpTMnSMmSMjQLgPL99G?<HG-\u001eE&\u000eb;!YIK`MLdOM`LKNCJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\lRyT~UʂXʃYX{WtUW'[(hQlRcP\\OhQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^LKcNLfOLiQLkRLmSMoTMqUMrVMvWNyYN|ZN\\N]O_O`OaPbPcPdPfPgQhQiQjRkRlSnTpUsWvZz]bglɑsИy؞ޤ㩊譍챐ﳑﳑ뭊穅⣀ݞzؘtғn΍iɉdƅ`Â][~Y}X|W|V{V{V{V{V{V|W|W}X}Y~Z~Z~Z}[}[}[~\\~\\~]~]~]~]}]|\\z[yZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPaP`O^O]O}[NyYNuWNpTMnTMmSMkRLhPL|H$D>IQ2\u001fP+\u0010XHK_LLfQOcNLXIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\qSyT~VΈ`遲ޜv]qSL\u0011G\u000e|>\fg3\nS)\b?\u001f\u0006*\u0015\u0004%\u0012\u0003.\u0017\u0004hQhQeP`OuWM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SFJ[JK`LKdNLgPLjQLlRMnSMoTMqUMsVMwXNzYN}[N\\O^O_O`OaPbPdPePfPgQhQiQjRkRlSnTpVsXvZz^bgËmʒsјz؟ޤ㩊譍ꯏ및ꯎ謋娇ं۞|֙wѓq̎lǉgÅb_\\}Z{XzWyVyUxUxUxTxTxUxUxUyVyVyWzW{X{Y|Z}[}[}\\~\\~]~]}]|\\{\\z[yZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPbP`O_O]O~[NzZNvWNrUMoTMmSMlRMiQLeOLJAIJ(\u000fh>!]KKfQOgQN_LKD>I\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\iQtSyT{UYΌeרּ՗u|\\Z'L\u000fD\r|>\f\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000ePoRqSoRmRjQeP^OhPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\WHJ\\KKaMLeOLhPLjQLlRMnSMpTMqUMtVMwXNzZN}[N]O^O_O`ObPcPdPePfQgQhQiQjRkRmSnTqVsXw[{_chČn˒tҙz؟ޥ㩉筍ꯎꯎꮍ竊䧆ߣ۞|՘vГpˎkǉfÅb_\\}Y{XzWyVxUxUxTxTxTxUxUxUxUyVyVzWzX{Y|Y|Z}[}[}\\}\\}\\}\\|\\{[zZyZwYvXtWsVrUpToSnSmRlRkRjQiQhQgQfQePdPcPbP`O_O^O\\N{ZNwXNsVMoTMnSMlRMiQLfOLJ(\u000fV.\u0010]KKePNkUQcNLQEJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]OmRqSrStSvTwTxU{WĆbғqךxʏo\u0012\n\u0004\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000K\u0016rSvTwTvTuTsSqSnRkQgQ`OuWNY,\b\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\NCJYIK^KKbNLfOLhQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O^O_OaObPcPdPePfQgQhQiQjRkRmSoTqVtXw[|_diČn˓tҙz؟ޥ㩉笌鮎ꮎ魌檉㧅ߢڝ{՗uϒpˍjƈfb^\\|Y{XzVyVxUxUxTxTxTxUxUxUxUyVyVyWzW{X{Y|Z|Z|[}[}\\}\\|\\|[{[zZxYwXvXtWsVrUpToSnSmRlRkRjQjQiQhQgQfPdPcPbPaO_O^O\\O|ZNxXNtVMoTMnSMlRMjQLgPLzG#\\JKcOMoXUgPMZIK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\fPgQgQhQiQkQlRnRpRqSsStS\u0000\u0000\u0000\u0000\u0000\u0000:\"\u0010r<\u0010zYNsSyT|U~WƄ^ˊeˋgƈeaz[tVpSmRkQgQbPzYNkRL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RFJZJK`LKcNLfPLiQLkRMmSMoTMqUMrVMvWNyYN|ZN\\N]O^O`OaObPcPdPePfQgQhQiQjRlRmSoUqVtYx\\|`diōo˓uҙ{ٟޥ㩉笌鮍鮍謋婈⦄ޡٜzԗtϑoʌjƈea^~[|Y{XzVyVxUxUxTxTxTxTxUxUxUxVyVyWzWzX{Y{Y|Z|Z|[|[|[|[{[z[yZxYwXvWtWsVrUpToSnSmRlRkRkRjQiQhQgQfPePdPbPaP`O^O]O}[NyYNuWNqUMnSMlSMkRLhPLcNLbNLpYVlUP`LK>;H\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\jQ`O{ZN^'^'`(e)h)k*o+b(nRyT~UǁXҍdw詅ݟ}Ԙvȍme}_x[y\\x[tWqTmRjQgQbP}[NlRM\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VGJ\\JKaMKdNLgPLjQLlRMnSMpTMqUMsVMvXNzYN|[N\\O]O_O`OaPbPcPdPePfQgQhQiQjRlSmSoUrWuYx\\|`djōo̓uҚ{٠ޥ㩉欋譍譌竊婇᥃ݠ~؛yӖtΑoʌjňea^~[|Y{WzVyVxUxUxTxTxTxTxUxUxUxUxVyVyWzXzX{Y{Z{Z|Z|[|[{[{[zZyZxYwXuWtVsVrUpToSnSmRlRkRkRjQiQhQgQfQePdPcPaP`O^O]O~[NzYNvWNrUMnSMmSMkRLiQLeOLoXUu]XdOLKBI\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\:9H\\NhQ}\\uUsTtTtSqSnRnRnRlRjQiQhQhQgQfQePePhQkRmSpUtXuYsWqUmSjQgQB\u000fS%jQL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LBIXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMtVMwXNzYN}[N\\O^O_O`OaPbPcPePfPfQgQhQiRkRlSnTpUrWuYy]}`ejŎp̔vӚ{٠ޤ⨉櫋笌笋櫊䨆ंܟ~ךxҕsΐnɌiŇea^~[|Y{WyVyVxUxUxTwTwTwTxTxUxUxUxVyVyWzWzXzY{Y{Z{Z{Z{Z{ZzZyZyYxYvXuWtVsUrUpToSnSmRlRlRkRjQiQhQgQfQePdPcPaP`O_O]O\\N{ZNwXNsVMnSMmSMkRMiQLfOL_LKhQMUGJ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ (6BFP>=DKHMqjktrwf`~kcndqesete{w`v[\\N_OcPfPiQjRlSoTqVqVoTlRiQ^\u0015`OQ%hPL\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QEJZIK_LKcNLfOLiQLkRLmSMoTMpUMrUMuWMxXN{ZN~[N]O^O_O`OaPcPdPePfPgQhQiQjRkRlSnTpUrWuZy]}aekƎp̔vӚ{ٟޤ⨈媊櫋櫊婈⦅ߣ۞}֚xѕr͐mȋićda]~[|YzWyVyUxUxUwTwTwTwTwTxUxUxUxUxVyVyWzXzXzYzY{Y{Z{ZzZzZyYxYwXvXuWtVsUrUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbP`O_O]O\\O|ZNxXNtVMoTMmSMlRMjQLgPLbML[JK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0010\b\u0001\u001a%5 (6\u001f$/79CEEKjgkrc_{uf{w_q]O`OcPfQhQjRlRnToTnTkRhQdP]'Q%\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UGJ[JK`MKdNLgPLiQLkRMmSMoTMqUMrUMuWNxXN{ZN~[N]O^O_O`ObPcPdP['d)gQhQiQjRkRlSnTpUrWvZy]~afkƎp̔vӚ{؟ݤᧇ䩉媊媉䨇᥄ޡڝ|՘wДȑmȊhĆd`]}[|YzWyVxUxUxUwTwTwTwTwTwUwUxUxUxVxVyWyWyXzXzYzYzYzYzYyYyYxYwXvWuWtVsUqUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbPaO_O^O\\O|[NxYNtWMpUMmSMlRMjQLgPLcNLA;=\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\#*6+.8;:AHEJmgjd\\]pe}xcw^p^OaPePgQiQlRmSnTmSjRgQh*X&M$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\C+\u001dWHJ]KKaMLdOLgPLjQLlRMnSMoTMqUMrVMvWNyYN|ZN\\N]O^O_OaObPcPY&_(c(gQhQiQjRkRlSnTpVsXvZz^~bfkƎp̔vҚ{؟ݣই㩉䩉䩈⧆ःܠ؜{ԗvϓqˎlǉgÆc`]}Z{YzWyVxUxUwUwTwTwTwTwTwTwUwUxUxVxVxVyWyWyXyXyYzYyYyYyYxYwXwXvWuVtVrUqUpToSnSmSmRlRkRjQiQhQgQfQePdPcPbPaO_O^O\\O}[NyYNuWNqUMmSMlRMjQLhPLdNL\\1\u000f\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\+.775;ICFphhztre}yavZ]OaPePgQiQkRlSnTlSiQq.b*S%zG#\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MCJXHK^KKbMLeOLhPLjRLlSMnSMpTMqUMsVMvWNyYN|ZN\\N]O^O`OaObPU&\\'a(g)r/hQiQjRkRmSnTpVsXv[z^~bfkƎp̔vҙ{מܣআ⨈㨈㨇ᦅޣ۟~כyӖuΒpʍkƉgc_]}Z{XzWyVxUxUwTwTwTwTwTwTwTwUwUwUxUxVxVxWyWyWyXyXyXyYyYxXxXwXvWuWtVsVrUqTpToSnSmRmRlRkRjQiQhQgQfQePdPcPbPaO`O^O]O}[NzYNvWNrUMmSMlRMjQLhQLeOL_LK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\,)/ZTVXONuqod}ybs]OaPePgQiQkRlRlSkRhQg*\\(Q%`LK\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B_LKcNLfOLiQLkRLmSMoTMpTMrUMtVMwXNzYN}[N\\O]O_O`OaOQ%Y&^'b(i*{8hQiQjRkRmSnTqVsXv[z^~bfkƎp̔vҙ{מۢߥᧇ⧇ᦆऄݢڞ}֚xҕt͑oɌjňfb_\\}Z{XzWyVxUxUwTwTwTwTwTwTwTwTwUwUwUxVxVxVxWxWyWyXyXxXxXxXwXwWvWuWtVsUrUqTpToSnSmRmRlRkRjQiQhQgQgQfPdPcPbPaP`O^O]O~[N{ZNvXNrVMnSMlRMjRLhQLeOLaML+O+O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\HFLXQRTJH~pmla}zcttTaPdPgQiQjRlRlSjR|:e*V&N$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0006 B\u0006 B`LKdNLgPLiQLkRMmSMoTMpUMrUMtVMwXNzYN}[N\\O]O_O`OaPW&['_(d)l,݃@t.iQjRkRmSoUqVsXw[z^bgkƎp̔uљz֝~ڡޤॆআॅޣܠ؝{ՙwєs̐nȌjňfb_~\\|Z{XyWyVxUwUwTwTwTwTwTwTwTwTwUwUwUwUwVxVxVxWxWxWxWxXxXwXwWvWuWuVtVsUrUqTpToSnSmRlRlRkRjQiQhQhQgQfPdPcPbPaP`O^O]O~[N{ZNwXNsVMoTMlRMjRLiQLfOLbML+O+O+O+O\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\6./fZXeVRHAIZIKiQLuWMtUaOdPgQjQkRlRkRiQn/b,R%rC\"\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\"Fx\"Fx!Fx!Fx\u0006 B\u0006 B\u0006 BdNLgPLjQLlRMmSMoTMqUMrUMtWMwXNzZN}[N\\O^O_O`OS%X&\\'a(g+s2{9j*iQjRkSmSoUqVsXw[z^bgkƎp˓uИy՜}٠ܢޤߤޣݡڟ~כzӗvϓrˏmǋićea^~\\|ZzXyWxVxUwUwTwTwTwTwTwTwTwTwTwUwUwUwUwVwVxVxWxWwWwWwWwWvWvWuVtVsUsUrTqTpToSnSmRlRlRkRjQiQhQgQgQfPePcPbPaP`O_O]O~\\N{ZNxXNsVMoTMlRMjRLiQLfPLbNL\u0005\t\u000f+O+O+P+P+P\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@89dWT@<HE?IXHKiQLvWN]ObPePhQjQlRlRkRp+f*[)O$\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\:^:^:^:^\"Fx\"Fx\"Fx\u0006 B\u0006 B\u0006 B\u0006 BeOLhPLjQLlRMnSMoTMqUMrUMuWMxXN{ZN~[N\\O^O_OO$V&Z']'d+g+}<h*hQiQjRkSmSoUqVtYw[z_bgkōpʒtЗyԛ}؟ۡݣݣܢ۠؝|՚yҖuΒpʎlƊhÆda^~[|YzXyWxVxUwUwTwTwTvTvTvTvTvTvTvTwUwUwUwUwVwVwVwVwWwWwWvWvWuVuVtVsUrUqTqTpSoSnSmRlRlRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNxXNtVMpTMlRMjRLiQLgPLcNL\\JK+P+P+P+P+P+P,P\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\D::hZUC>IIAI\\JKlRMyYN^OcPgQiQkRlRkRiRt3d-S%I#\u0013\\\u0013\\\u0013\\:^:^:^:^:^:^:^:^:^\"Fx\"Fx\u0006 B\u0006 B\u0006 B\u0006 BeOLhPLjRLlSMnSMpTMqUMrVMuWMxXN{ZN~[N]O^O_OS%W&['^(k2i+{:gQhQiQjRkSmToUqVtYw[{_bfkčoʒtϖxӚ|ם~٠ۡۡ۠ٞ~כ{ԘwДs̐oɌkŉgc`]}[{YzXyVxVwUwUwTwTvTvTvTvTvTvTvTvTvUvUvUwUwUwVwVwVwVvVvVvVuVuVtVtUsUrUqTpTpSoSnSmRlRlRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNxYNtWMpTMlRMjRLiQLgPLcNL_LK+P+P+P,P,P,P,P,PNr\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]QNl\\VG@IMCI_LKoTM|ZN`OdPgQjQkRlRkRhQh*^,P%X3\u0019:_:_:_:_:_:_:_:_:^:^:^:^\"Fx\u0006 B\u0006 B\u0006 B\u0006 BfOLiQLkRLmSMnTMpTMqUMrVMuWNxYN{ZN~[N]O^OP%U&X&['`)n4n/j*gQhQiQjRkSmToUqWtYw[z^~bfjČoɑsΕwҙ{՜}؞ٟڟٞ~ל|՚yҗvϓrˏnǋjĈfc`]}[{YzWxVxUwUwTwTvTvTvTvTvTvTvTvTvTvTvUvUvUvUvUvVvVvVvVvVuVuVuVtUsUrUrTqTpToSoSnSmRlRkRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\N|ZNyYNuWMpUMlRMjQLiQLgPLdNL_LK,P,P,P,P,PNrNrNrNrNrNr\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\aSOD>IJAIQEJbNLrUM~[NaOePhQjQkRlRjRs0e,T&K$;_;_;_;_;_;_;_:_:_:_:_:_:_\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRLmSMoTMpTMqUMsVMuWNxYN{ZN~[N]OM$S%V&Y&\\'e-j/z:fQgQhQiRjRkSmToUqWtYw[z^~bfjÌnȐr͔vјyԛ|֝~מ~؞~ם}՛{ӘxЕt͒qʎmƊiÇeb_~\\|Z{YyWxVxUwUwTvTvTvTvTvTvTvTvTvTvTvTvTvUvUvUvUvUvUvVvVuVuVuVtUsUsUrUqTqTpSoSnSnRmRlRkRkRjQiQhQgQgQfPePdPbPaP`O_O]O\\O|ZNyYNuWMqUMlSMjQLhQLfPLdNL_LK,P,PNrNrNrNrNrNrNrNsNsNsNs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\dUOG@IMCITFJeOLtWM]ObPfPiQkRlRkRiQj,c/P%[JK;_;_;_;_;_;_;_;_;_;_;_;_\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRMmSMoTMpTMqUMsVMvWNyYN{ZN~[N|H#Q%T%W&Z']'m5f*v5fQgQhQiRjRkSmToUqWsYv[z^~beinǏq˓uϖxҙzԛ|֜}֜|՛{ԙyіvϓs̐oȍlŉhea_~\\|ZzXyWxVwUwUvTvTvTvTvTvTvTvTvTvTvTvTvTvTvUvUvUuUuUuUuUuUtUtUtUsUrUrTqTpTpSoSnSmRmRlRkRjRjQiQhQgQfQfPePcPbPaP`O_O^O\\O|ZNyYNuWNqUMmSMjQLhQLfPLdNL`LKNrNrNrNrNrNsNsNsNsOsOsOsOsOsOs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\2#\u001cTB<JBIODJXHKiQLxXN^OcPgQjQlRlRkRo,d+U'L$;_;_;_;_;_;_;_;_;_;_;_\u0007\u000b\u0011\u0006 B\u0006 B\u0006 B\u0006 BgPLiQLkRMmSMoTMpUMrUMsVMtVMyYN|ZN~[NO$S%U&X&['_(s;h+`\u001afQgQhQiRjRkSmToUqWsYv[z^}aeimŎpʒt͕wЗyҙzӚ{Ԛzәyїwϔt͒qʏnǋjĈgda^}\\{ZzXyWxVwUwUvTvTvTvTvTvTvTvTuTuTuTuTuTuTuTuUuUuUuUuUuUtUtUtUsUsUrTqTqTpSoSoSnSmRmRlRkRjQjQiQhQgQfQePdPcPbPaP`O_O]O\\O|ZNyYNuWNqUMmSMiQLhPLfOLdNL`LKkPANrNsNsNsNsOsOsOsOsOsOsOsOsOsOsOs\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\#Gy#GybSNP<3NCJRFJ^LKoTM}[NaOePiQkQlRlRiQm-g2Q%]8 ;_;_;_;_;_;_;_;_;_;_\u0014!2\u0006 B\u0006 B\u0006 B\u0006 BgPLjQLlRMmSMoTMpUMrUMsVMtVMyYN|ZNM$Q%T%V&Y&['b+q8r3ePfQgQhQiRjRkSmToUqVsYv[y^}adhlčoȐr˓uΖwЗxјyјxїwϕu͒rːpȍlŊifc`~]|[{YyXxWwVwUvUvTvTvTvTuTuTuTuTuTuTuTuTuTuTuTuTuTuUuUtUtUtUtUsUsTrTrTqTqTpSoSoSnSmRlRlRkRjQiQiQhQgQfQePdPcPbPaP`O_O]O\\N|ZNyYNvWNqUMmSMiQLhPLfOLdNL`LKZIKNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOtOt\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d#Gy#Gy#Gy#Gy#GyhVPKBIQEJUGJeOLtVM]ObPgQjQlRlRkRgQd*X)N$;`;`;`;`;`;`;`\"Gy\"Gy\"Gy\u0014!2\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMsVMtVMyYNK$P%S%U&W&Y&\\'i2h.x8ePfQgQhQiQjRkSmTnUqVsXv[y]|`dgkËnƏqʒs̔uΕvϖwϖvΕu͓sˑqɎnƋkÈheb_~]|[zYyWxVwVwUvTvTvTuTuTuTuTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTsTsTrTrTqTqTpSpSoSnSnRmRlRkRkRjQiQiQhQgQfQePdPcPbPaP`O_O]O\\N|ZNyYNuWNqUMmSMiQLgPLfOLcNL`MKZIKOsOsOsOsOsOsOsOsOsOsOsOsOtOtOtOtPtPtPtPt\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvv#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GyYE<NDJTFJYIKkRLyYN_OdPhQkQlRlRjRo.h2R%c; <`<`#Gy#Gy#Gy#Gy\"Gy\"Gy\"Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMqUMrUMsVMtVM~I#N$R%T%V&X&Z'^(q9e*j+ePfQgQhQiQjRkSmTnUpVsXuZx]|`cfjmōpȐrʒt̓u͔u͓t̒sˑqɏoǌlĊifda^}\\{ZzXxWwVwUvUvTvTuTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTtTtTsTsTsTrTrTrTqTpSpSoSoSnSmRmRlRkRkRjQiQhQhQgQfQePdPcPbPaO`O_O]O\\N|ZNyYNuWNqUMmSMhQLgPLeOLcNL`LKZIK,P,POsOsOsOsOsOsOsOtOtOtOtPtPtPtPt-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvvv=a#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GygUOT>3REJVGJ`LKpTM}[NaOePiQkRlRlRhQe)^.P%^8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMsVMxF#M$Q%S%U&W&Y&['a+s;g+dPePfQgQhQiQjRkSlSnUpVrXuZx]{_~beikÌnƎpȐrʑs˒sˑrʐqɏoǍmŋkÈheb`~^|[{ZyXxWwVvUvUvTuTuTuTuTuTuTuTuTuTuTtTtTtTtTtTtTtTtTsTsTsTsTrTrTrTqTqSpSpSoSnSnRmRlRlRkRjQjQiQhQgQgQfPePdPcPbPaO`O^O]O\\N|ZNxXNuWMqUMmSMhPLgPLeOLcNL`LKZIK,P,P,QOsOsOtOtOtOtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvvvvww=a=a=a#Gy#Gy#Gy#Gy#Gy#Gy#Gy#GymYPODJUGJXIKeOLtWM]OcPgQjQlRmRkRp.g0T&N$]8 #Gy#Gy#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMrUMv>\u0013L$P%R%T%V&X&Z'\\'f0m5q3dPePfQgQgQhQjRkSlSnTpVrXtZw\\z_}adgjlČnƎpǏqȏqȏpǎoƍmŋkÉigda_}]|[zYyXxWwVvUvUuTuTuTuTuTuTuSuStStStStStTtTtTtTtTsTsTsTsTsTrTrTrTqTqSpSpSoSoSnSmRmRlRlRkRjQjQiQhQgQfQfPePdPcPbPaO`O^O]O~\\N{ZNxXNuWMqUMiQLgPLfOLeOLbNL_LKZIK,Q,Q,Q,Q,QOtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\vvvvwwwwwwww=a=a=a=a=a#Gz#Gz#Gz#Gz#Gz#Gz#GzgUOS=2RFJWHJ[JKlRMzYN`OePiQkRmRlRiQh*h4R%N$^9 [JK#Gy#Gy#Gy#Gy#Gy\f\u0018*\u0006 B\u0006 B\u0006 B\u0006 B\u0006 BjQLlRMnSMoTMpUMI#L$O$Q%S%U&W&X&Z'](l5f,t5dPePfPfQgQhQiRkRlSmToVqWtYv[y^|acfhklÌnōnōoōnŌmċkigec`~^|\\{ZyYxWwVvUvUuTuTuTuTuTtStStStStStStStStStStSsSsTsTsTsTrTrTrTrSqSqSpSpSoSoSnSnRmRmRlRkRkRjQiQiQhQgQfQePePdPcPbP`O_O^O]O~[N{ZNxXNtVMqUMhPLgPLfOLdNLbML_LKbE6,Q,Q,Q,Q-Q-Q-QPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@dwwwwwwwwwwwwww=a=a=a=a=a=a=a#Hz#Gz#Gz#Gz#Gz#Gz#GzmYPPDJUGJYIKbMLqUM\\NbPfQjQlRmRlRp,e+\\+R%N$b; ]8 [7 XHKO+\u000fN1\u001eL/\u001eL/\u001eL/\u001eK/\u001eK/\u001e\u0002\u000b\u0017e<!J#{=\fJ$L$N$O$P%S%T%V&X&Y&['`+m7d)h*dPdPePfQgQhQiRjRlSmToUqWsYv[x]{`~begijllËlÊlkihfca_}]{[zYxXwWwVvUuUuTuTuTtTtTtStStStStStStStStSsSsSsSsSsSsSrSrSrSrSqSqSqSpSpSoSoSnRnRmRlRlRkRjQjQiQhQhQgQfQePdPcPbPaP`O_O^O]O~[NzZNwXNtVMpTMgPLfOLeOLcNLaMK^KKbE6,Q-Q-Q-Q-Q-QPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-R-R\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@d@d@dwwwwwwwwwwwxx=b=b=b=b=b=b=b=b#Hz#Hz#Hz#Hz=a=agUOS=2RFJWHKZJKiQLvXN^OcPhQkRmRmRkRm-j3W(R%O$e<!c; a: ^9 ]8 [7 X6\u001fX6\u001fX6\u001fK$M$_(yF#U&N$N$O$P%R%S%U&W&X&Z'\\(d.j2f*bPcPdPePfQgQhQiRjRkSmTnUpWsXuZw\\z_}acegijjjjigfdb`~^|\\zZyYxXwWvVuUuUuTtTtTtTtStStStStStStSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSpSpSoSoSnRnRmRmRlRkRkRjQiQiQhQgQgQfPePdPcPbPaP`O_O^O\\O}[NzYNwXNsVMoTMgPLfOLdOLcNL`MK]KKaE6-Q-Q-QPtPtPtPtPtPtPtPt-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-R-R-R-R-R-R-R\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@d@d@d@e@e@e@e@ewwwxxxxxxxx>b>b>b>b>b>b>b>b=b=b=b=b=b=b=b=bYE<bJ>UGJYIK_LKnSM|ZN`OePiQlRmRmRiQg*j4W'R%Q%h>!g=!f=!d<!c; b; `: N$`(b(d)f)|H#X&X&W&Q%R%T%V&W&Y&['](d.e,n1bPcPdPePfQgQhQiRjRkSlTnUpVrXtZv\\y^{`~bdeghhhhgfdba~_|]{[yZxXwWvVvUuUuTtTtTtTtStStStStStSsSsSsSsSsSsSsSsSrSrSrSrSqSqSqSqSpSpSoSoSnRnRmRmRlRlRkRkQjQiQiQhQgQfQfPePdPcPbPaO`O^O]O\\O}[NyYNvWNrVMoTMfOLeOLdNLbML`LK\\KKaE6PtPtPtPtPtPtPtPtPuPuPuQuQu-Q-Q-Q-Q-Q-Q-Q-Q-R-R-R-R-R-R-R-R-R.R.R~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@d@d@d@e@e@e@e@e@e@e@eAeAeAexxxxxxxxxx>b>b>b>b>b>b>b$Hz$Hz$Hz$Hz$Hz>b>b>b>b>bgVOS=2RFJWHK[JKeOLsVM]ObPgQjQlRmRlRr/g*h2U&S%R%Q%Q%P%[']'`(b(d)f)g)i*j*I#Z'Z'Z'Z'Z'['['\\']'_)d,d)q3bPcPdPePfQfQgQhQiRkSlSmUoVqWsYu[x]z^|`~bdeffffedba~_}^{\\zZyYwXwWvVuUuUtTtTtTtStStSsSsSsSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSpSpSpSoSoSoRnRnRmRmRlRkRkRjQjQiQhQhQgQfQePdPcPcPbP`O_O^O]O\\N|ZNyYNuWNrUMnSMjQLdNLcNLaMK_LK[JK`D6PtPtPtPtPtPuPuPuPuQuQuQuQuQuQu-Q-Q-Q-R-R-R-R-R-R-R-R-R.R.RRvRvRv~~~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\@e@e@e@eAeAeAeAeAeAeAeAeAeAeAexxxxxxxyy>b>b>b$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>b>bYD<W?3UGJYIK\\JKjRLxXN_OdPhQkRmRmRkRp.h,f/[(X&X&Z'\\'^'`(c(e)g)i*j*l*m*o+\\'\\'\\'\\'\\']']'^'_(a)c*e*i+bPcPdPdPePfQgQhQiRjRkSmTnUpWrXtZv[x]z_|`~bcddddcba~_}^{\\z[yZxXwWvVuUuUtTtTtTtTsSsSsSsSsSsSsSsSsSsSsSrSrSrSrSrSqSqSqSqSpSpSpSoSoSoRnRnRmRmRlRlRkRkQjQiQiQhQgQfQfPePdPcPbPaP`O_O^O]O~[N{ZNxXNtWMqUMmSMiQLcNLbML`LK^KKbR_D5PtPtPuPuPuPuQuQuQuQuQuQuQuQuQuQuQu-R-R-R-R-R-R-R.R.RRvRvRvRvRv~~~~~~~~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeyyyyyyyAe$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>bQ@:R<2fL@WHJZJKaMKoTM|ZN`OePiQlRmRmRjRo-i-h0`)]']'`(b(d)f)h)j*k*m*n+p+q+r,]']']'^'_(_(`(`(b)c)i.`OaPbPcPdPePfQgQhQiRjRkSlTnUoVqWsYuZw\\y]{_|`}a~bbbba~`}_|^{]z[yZxYwXvWuVuUtUtTtTsTsSsSsSsSsSsSsSsSsSrSrSrSrSrSrSrSqSqSqSqSpSpSpSoSoRoRnRnRmRmRlRlRkRkRjQjQiQhQhQgQfQePdPdPcPbPaO`O_O]O\\O}[NzYNwXNtVMpTMlRMhPLcNLaMK_LK]KKbR]C5PuPuPuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQv-R-R.R.R.RRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeAeyyyAfAfAf$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>b>b>b>bWD<V>3TFJXHK[JKfOLsVM]ObPgQjQlRmRmRkRm,i,j/d+c)c(e)f)h*j*l*n+o+q+r+s,t,K$^(_(_(`(a(a)b)d*f+m1`OaPbPcPdPePfQfQgQhRiRkSlTmToVpWrXtYv[w\\y]z^{_|`}`}`}`}_|^{^{\\z[yZxYwXvWuVtUtUtTsTsTsSsSsSsSsSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSpSpSpSoSoRoRnRnRmRmRmRlRlRkRjQjQiQiQhQgQfQfPePdPcPbPaP`O_O^O]O\\N|ZNyYNvWNsVMoTMkRLgPLbML`LK^KK\\JK~aR[B5PuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAeAeAeAeAeAeAfAfAfyAfAfAfAfAfBf$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c>c>b>bO?:[E<dK?UGJYIK\\KKjRLxXN^OcPhQkQlRmRmRt.q.j+k-i,h*h*j*k*l*n+p+q+s,t,u,v,w,`(`(a)b)c*d+f+g,k0m1`OaObPcPcPdPePfQgQhQiRjRkSlTnUoVqWsXtZv[w\\y]z^z^{^{^{^{^z]z\\y[xZwYvXvWuVtVtUsTsTsTsTsSrSrSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSpSpSpSpSoRoRoRnRnRmRmRmRlRlRkRkQjQiQiQhQgQgQfQePePdPcPbPaP`O_O^O\\O~[N{ZNxYNuWNqUMmSMiQLeOLaMK_LK]KKlN>|aRZA5-QQuQuQuQuQuQuQuQuQuQuQvQvQvQvRvRvRvRv.R.R.R.RRvRvRvRvRvRw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AeAeAeAeAeAeAeAfAfAfAfAfyyyzzzBfBfBfBfBf$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz$Hz$Hz$Hz>c>c>c>cVC<T=3}cVWHJZIKaMLoTM|ZN`OePhQkQlRnRnSt.v2m+l+l+l+m+n+o+p+r+s,u,u,v,w-x-y-b*c+e,g-i/k0m2p4i-_O`OaPbPcPdPePfQfQgQhRiRjSlTmTnUpVqWsYtZv[w[x\\y]y]y]y]y\\y\\x[xZwYvXuWuWtVtUsUsTsTrTrSrSrSrSrSrSrSrSrSrSrSqSqSqSqSqSqSpSpSpSpSpRoRoRoRnRnRmRmRmRlRlRkRkQjQjQiQhQhQgQfQfPePdPcPbPaP`O_O^O]O\\O}[NzYNwXNtVMpTMlRMhPLdNL`LK^KKmO?kN>^C6W@5-Q-QQuQuQuQuQuQuQvQvQvQvRvRvRvRv.R.R.R.R.R.R.R.R.RRvRwRwRwրրրրրրրրրրր\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AfAfAfAfAfAfAfAfzzzzzzzzzzzBfBfBfBf$I{$I{$I{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$H{$Hz$Hz$Hz$Hz$Hz\u0007\u000b\u0011YE<W?4gYXHKZJKfOLsVM\\NaOePiQkRmRnSnSmS|7s/o,o,p+q+r,s,t,v,w-x-y-z.{/|/e-g/j1m3o5o5r7n3c)_O`OaPbPcPdPdPeQfQgQhQiRjRkSlTmUoVpVqWsXtYuZv[w[w[w[w[w[wZwZvYvXuWtWtVsUsUsTrTrTrSrSrSrSrSrSrSqSqSqSqSqSqSqSqSqSpSpSpSpSpRoRoRoRnRnRnRmRmRmRlRlRkRkQjQjQiQiQhQgQgQfQePdPdPcPbPaO`O_O^O]O~[N{ZNyYNvWNsVMoTMkRLgPLbML^LKnP?lO?iM>\\C6T>4-Q-Q-Q-RQuQuQvQvQvQvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.RRwSwրրրրրրրրրրրրրրրրրEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\AfAfBfBfBfzzzzzzzzzzzzzzzBfBfBf$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$H{$H{$H{$H{?c?c?c?c$H{$H{$H{SB;R<2zbVUGJXIK[JK[JKuWN\\OaPfPiQlRmRnSnSpT99w2w0v/v.x/z0z0|1~235688m4o7q8u;s9s8j0]O^O_O`OaPbPcPdPePfQfQgQhRiRjSkSlTnUoVpVqWrXsYtYuYuZuZvZvYuYuXuXtWtVsVsUsUrTrTrTrSqSqSqSqSqSqSqSqSqSqSqSqSqSqSpSpSpSpRpRoRoRoRoRnRnRnRmRmRmRlRlRkRkRjQjQiQiQhQgQgQfQePePdPcPbPaP`O_O^O]O\\O}[NzYNwXNtVMqUMnSMiQLeOL`LK]KKmP?kN?|aSZA5P<4-R-R-R-R-R-RQvRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R׀׀׀׀׀׀׀׀׀׀׀׀׀׀׀EiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\Bfzzzzzzzzzzzzz{{{{{{BfBfBf%I{$I{$I{$I{$I{$I{$I{$I{$I{$I{$I{?c?c?c?c?c?c?c?c?c$H{$H{$H{jXP^H=}dXUGJXHKZIKkRLwXN]ObPfQiQkRmRnSpTqUrU;>?<9;==>ADHKEr:t;t;t<t:n4f,]O^O_O`OaObPcPcPdPePfQgQhQiRjRkSlSmTnUoVpVqWrWrXsXtXtXtXtXtXtWsWsVsVrUrUrTqTqTqSqSqSqSqSqSqSqSqSqSqSpSpSpSpSpSpSpRpRoRoRoRoRnRnRnRnRmRmRmRlRlRkRkRjQjQiQiQhQhQgQfQfPePdPcPcPbPaO`O_O^O]O~[N{ZNyYNvWNsVMpTMlRMgPLcNLgUeUlO?~bT{`SW@5-R-R-R-R-R-R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.REiEiEi׀׀׀׀׀׀׀׀׀׀׀EiEiEiEiEiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\zzzzzzzz{{{{{{{{{{{{{BgBgBg%I{%I{%I{%I{%I{%I{%I{@d?d?d?d?d?d?d?d?d?c?c?c?c$I{$I{L=:WD<v_TgZuZLWHKYIKmSMyYN^OcPfQiQkQmRnSpTqTsVwX8CIJNRTUVZ_Su=t=s;q9o6h.a)\\O]O_O_O`OaPbPcPdPePeQfQgQhRiRjRkSlTmTnUoUpVpVqWrWrWrWrWrWrWrVrVrUrUqUqTqTqTqSqSpSpSpSpSpSpSpSpSpSpSpSpSpRpRpRoRoRoRoRoRoRnRnRnRmRmRmRlRlRlRkRkQjQjQiQiQhQhQgQfQfPePdPdPcPbPaP`O_O^O]O\\O}[NzYNwXNtWMqUMnSMjQLeOLiVfUeUcT|bTcK>`KA-R-R-R.R.R.R.RRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.REiEiEiEiEiEiׁׁׁׁׁׁEiEiEiEiEiEiEiEiEiEiEiEiEiEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\zz{{{{{{{{{{{{{{{{{{{|CgCg%I{%I{%I{@d@d@d@d@d@d@d@d@d@d@d@d?d?d?d?d?d?d$I{$I{dUPYE<xaVlSGw]OVHJbMLoTMzYN^OvRePhQjQmRnRpSqTuVyZ{[^acʌiΏlђnX_aSUq:n7k3h0c*^(\\N]O^O_O`OaObPbPcPdPePfQfQgQhRiRjRkSlSmTmTnUoUpVpVqVqVqVqVqVqUqUqUqTqTpTpTpSpSpSpSpSpSpSpSpSpRpRpRpRpRpRoRoRoRoRoRoRoRnRnRnRnRmRmRmRlRlRlRkRkQjQjQiQiQhQhQgQfQfPePdPdPcPbPaP`O_O^O]O\\O~[N{ZNyYNvWNrVMoTMlRM|WBwUAhVfVlO@~cTzaTaI>XG@-R.R.R.RRvRvRvRvRvRvRvRv.R.R.R.R.R.R.R.R.R.R.R.R.R.R.SEiEiEiEjEjEjEjEjׁׁEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEiEiEi\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\{{{{{{{{{{{{{{|||||||||Cg@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d?d$I{$I{RA;P<3zcXnVIuh~pdNLpUMwzZvSePgQjQlRmRoSpTuVvWxY|\\_ÆdƉgȊhʌi̎kΏlRFk4g1d-b+_(Z'}[N\\O]O^O_O`OaPbPcPcPdPeQfQgQgQhRiRjRkSkSlTmTnTnUoUoUpUpUpUpUpUpTpTpTpTpSpSoSoSoSoSoSoSoRoRoRoRoRoRoRoRoRoRoRoRoRnRnRnRnRnRmRmRmRlRlRlRkRkRkQjQjQiQiQhQhQgQgQfPePePdPcPbPbPaO`O_O^O]O~\\N|[NzYNwXNtVMpUMpYoXzWBuUBgVlP@jO@|bUx`TcMB3!\u0014.RRvRvRvRvRvRvRvRvRvRvRwRwRw.R.R.R.R.R.R.R.R.R.S.S.SEjEjEjEjEjEjEjEjEj؁EjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEjEj\u0013\\\u0013\\\u0013\\\u0013\\Bg{{{{{{{||||||||||||CgCgCgCg|@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d%I{;0/SB;R=4fODpXLxkrvbzx{[ÏldPgQiQjQlRnRpSqTrTtUwW{Z}\\|\\}\\~]]}+~6d.a+_)^(\\'zYN|ZN~\\N]O^O_O_O`OaPbPcPdPdPeQfQgQgQhRiRjRjSkSlSlTmTmTnTnTnToToToToToToSoSoSoSoSoSoSoRoRoRoRoRoRoRoRoRoRoRoRnRnRnRnRnRnRmRmRmRmRlRlRlRlRkRkQjQjQjQiQiQhQhQgQgQfQePePdPcPbPbPaO`O_O^O]O\\N}[NzZNxXNuWMrUMrZpY|XCxVCsTBmQAkOA~cVzaU`I>\\IARvRvRvRvRvRvRvRvRvRvRwRwRwSwSwSwSw.R.R.R.R.R.S.S.S.SFjFjFjFjFjFjFjFj؂؂؂؂؂FjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFj\u0013\\\u0013\\Bg{||||||||||||||CgCgCgCgCgCgCgCg}@e@e@e@e@e@e@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d@d%I{<1/J82^I@gQFqYNxlsvc{dy{\\wUčiePgQhQkQmRmRnRoSpSrTtUtUtUtUtUtUt.L&](['Z'Y&xYN{ZN}[N\\N]O^O_O`OaOaPbPcPdPePeQfQgQgQhRiRiRjRkSkSlSlSmSmSmSnSnSnSnSnSnSnSnSnSnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRlRlRlRlRkRkRkQjQjQiQiQiQhQhQgQfQfPePePdPcPbPbPaO`O_O^O]O\\O}[N{ZNxYNvWNsVMs[rZ~ZDnYkYqSBkPAiOA|cVbK?\\G>NB?RvRvRvRvRvRvRvRvRwRwRwSwSwSwSwSwSwSwSw.S.S.S.S.S.SFjFjFjFjFjFj؂؂؂؂؂؂؂؂؂؂FjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjCgCg|||||||||||CgCgCgCgCgCgCgCgCgCgCgCg}AeAeAe@e@e@e@e@e@e@e@e@d@d@d@d@d@d@d@d@d@d%I{@d@d<1/H72\\I@ePGpYNxmtvc{ezupwUuQePgQiQjQjQlRmRnRnRoRoRoRoRoRg\u001cb; Z'Y&W&S%vXNyYN{ZN~[N\\O]O^O_O`OaOaPbPcPdPdPeQfQgQgQhQiRiRjRjRkSkSlSlSlSlSmSmSmSmSmSmRmRmRmRmRmRnRnRnRnRnRnRnRnRnRnRmRmRmRmRmRmRmRmRlRlRlRlRkRkRkQjQjQjQiQiQhQhQgQgQfQfPePdPdPcPbPbPaO`O_O^O]O\\O}[N{ZNyYNvXNtVMu\\]E[EoZmZkYnRBjOB}cVdL@`I?XGARvRvRvRvRvRvRwRwRwRwSwSwSwSwSwSwSwSwSwSwSw.S.S.S.S/SFjFjFjFjققققققققققققققFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjقCgCg|||||||CgCgCgCgCgCgCgCgCgCgCgCgChChChChCh}AeAeAeAeAeAeAeAeAe@e@e@e@e@e@e@e@d%I{%I{%I{%I{%I{@d@d<10F61o]Vye]oexmuud{e}d|atpÏluQdPePfQgQiQjQjQjQjQjQkQkQkQ_9 X&V&T%rUMuWMwXNzYN|ZN~[N\\O]O^O_O`OaObPbPcPdPdPeQfQfQgQhQhRiRiRjRjRkRkRkRlRlRlRlRlRlRlRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRmRlRlRlRlRlRkRkRkRkQjQjQjQiQiQiQhQhQgQgQfQfPePdPdPcPbPbPaO`O_O^O]O\\O~[N{ZNyYNwXNtVMrUM^F]Fq\\o[lZqTDfX}dWeMAbK@O=6NB@RvRvRvRvRwRwRwRwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSx/S/SFjFjFjككككككككككككككككككFjFjFjFjFjFjFjFjFjFjFjFjFjFjFjكككCgCgCg}}}CgCgCgCgCgCgCgCgChChChChChChChChChChDhDhDh~AeAeAeAeAeAeAeAeAeAeAeAeAe%I{%I{%I{%I{%I{%I{%I{%I{%I{@d@dE:9D61m\\Vwe]lXOuaXk_z||e|c|`z]yXnÏlĎkĎidPePfPfPfPfPfPfPfP[7 U&T%P%pTMsVMuWMxXNzYN|ZN~[N\\O]O^O_O`OaObPbPcPdPdPePeQfQgQgQhQhQiRiRjRjRjRkRkRkRkRkRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRkRkRkRkQkQjQjQjQiQiQiQhQhQgQgQfQfPePePdPdPcPbPbPaO`O_O^O]O\\O~[N|ZNyYNwXNuWMrUM`G^Gr]|ZFxXFtVEgY~eY{cXbLA[H?REA.R.RRvRwRwRwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxSxTxTxTxككككككككككككككككككككككككFjFjFjFjFjFjFjFjFjFjFjكككككCgCg}}CgCgCgCgChChChChChChChChChDhDhDhDhDhDhDhDhDhDh~AeAeAeAeAeAeAeAeAe%I|%I|%I|%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{%I{@e@eB99B51k[Vud]iWPr_Wye]y|}|e|cw{^z\\yZpxWwUwUwUwUÎlÎlllkD(S%P%nSMoTMqUMsVMvWNxXNzYN|ZN~[N\\O]O^O_O`OaOaPbPcPcPdPePeQfQfQgQgQhQhQiQiRiRjRjRjRjRkRkRkRkRkRkRkRlRlRlRlRlRlRlRlRlRlRlRlRkRkRkRkRkQkQkQjQjQjQjQiQiQiQhQhQgQgQgQfQfPePePdPcPcPbPaPaO`O_O^O]O\\O~[N|ZNyYNwXNuWMrUMw_v_t^~\\GzYGvWFj[fZ|dYybX\\I@VGB5/2.R.R.R.RSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxSxTxTxTxTxFkFkFkFkڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃFkFkFkFkFkFkFkFkڃڃڃڃڃڃڃ}}}}ChChChChChChChDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDh~AeAeAeAeAe%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{%I{%I{%I{%I{@e@e<68?31gYVpa\\bRMjYTq`Zj`z}}|{zxwz^tsssrrrrh2O$L$mSMnSMnTMoTMtVMvWNxXNzYN|ZN~[N\\O]O^O_O`OaOaPbPcPcPdPdPePeQfQfQgQgQhQhQhQiQiQiQiQjQjQjQjQjQkQkQkQkRkRkRkRkRkRkRkRkRkQkQkQkQjQjQjQjQjQjQiQiQiQhQhQhQgQgQgQfQfPePePdPdPcPbPbPaP`O`O_O^O]O\\O~[N|ZNyYNwXNtWMz`y`w`u_]I|[HwXGl\\i[}eZycYr_WjZU;23.R.R.R.R.R.R.RSwSwSwSwSwSwSwSwSxSxSxTxTxTxTx/S/SGkGkGkGkGkGkGkڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃڃGkGkGkڃڃڃڃڃڃڃڃڃڃ}}}}~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhAf%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I|%I{%I{AeAeAe?89H=<gZXpb_aSPi[Vud]x{ufwfyf||{yyzbzbzayayaya^=%V)kRLlRMmSMmSMnSMoTMoTMvWNxXNzYN|ZN~[N\\O]O^O_O`O`OaPbPbPcPdPdPePePfQfQfQgQgQhQhQhQhQiQiQiQiQiQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQjQiQiQiQiQiQhQhQhQgQgQgQfQfPePePdPdPcPcPbPaPaO`O_O^O^O]O\\O}[N{ZNyYNwXNtVM{bzaxawa_J~\\IyZItWHj]g[dNDr`Xj[VOCB.R.R.R.R.R.R.R.R.SSwSwSwSwSxSxSxSxTxTxTxTx/S/S/SGkGkGkGkGkGkGkGkGkڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄGkڄڄڄڄڄڄڄڄڄڄڄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDh%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|%I|%I|%I|AeAeAe4285.0G??g\\[XMK`TRg[Yyt{h`lbodreufvfwfwewe{{{zzbD.T+\\EkRLkRMlRMmSMnSMnSMsVMvWNxXNzYN|ZN~[N\\O]O^O_O_O`OaOaPbPcPcPdPdPePePfQfQfQgQgQgQhQhQhQhQhQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQiQhQhQhQhQgQgQgQfQfQfPePePdPdPcPcPbPbPaP`O`O_O^O]O]O\\N}[N{ZNyYNvXNtVMfLdLcLbLvbtar`o_pVHkSGcOE]KDj[WNCB\u0000\u0000\u0000.R.R.R.R.R.S.S.S.S.S.SSxSxSxSxTxTxTx/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄGkGkGkGkGkڄڄڄڄڄڄڄڄڄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDhDi&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|AeAeAe\u001a\u0015\u0014-*.3-0G@Ae\\]jabs`Ssjk|qovrtd_{halcmcmcncncyyyy\\A.~ZE[F]G^GkRLlRMlSMmSMqUMsVMuWNwXNyYN{ZN}[N\\O]O]O^O_O`O`OaPaPbPcPcPdPdPdPePePfQfQfQgQgQgQgQhQhQhQhQhQhQhQiQiQiQiQiQiQiQiQiQhQhQhQhQhQhQgQgQgQgQfQfQfPePePePdPdPcPcPbPbPaPaO`O_O_O^O]O\\O~[N|ZNzYNxXNvWNsVMgNfMdMcMwcubsbparWIkSHbOF]KEj\\X_UT@<?.R.R.R.R.S.S.S.S.S.S/S/S/S/STxTxTx/S/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkۄۄۄۄۄۄۄۄۄۄۄۄۄۄGkGkGkGkGkGkGkGkGkۄۄۄۄۄۄۄ~~~~~~DhDhDhDhDhDhDhDhDhDhDhDiDiրրրEiEi&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|('.,*/>:?YUY`QGfVLudXjeitlm{po|qp}rp~rpsqsqtqr_=1+xJ)o[~[F\\G^H_I`IkRLlRMnSMpTMrVMuWMwXNyYN{ZN}[N~\\N\\O]O^O_O_O`O`OaPbPbPcPcPcPdPdPePePePfPfQfQfQgQgQgQgQgQgQgQhQhQhQhQhQhQhQhQhQgQgQgQgQgQgQfQfQfQfPePePePdPdPdPcPcPbPbPaPaO`O_O_O^O]O\\O~\\N}[N{ZNyYNwXNuWMiOhOgOeOzeydwdtcrbtYKjTIaOG[KFj]Y^UU?;@.R.R.S.S.S.S.S.S/S/S/S/S/S/S/S/S/S/S/S/S/S/S/SGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkGkۅۅۅۅۅۅۅۅۅۅGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅۅۅDhDhDhDhDiDiDiDiDiրրրրրրրրրրրEiEi&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|AfAeAe%J|%J|%J|%I|%I|%I|%I|\u0000\u0000\u0000\u001f#-#%.()1MEAQIEUMI]SL]TM=4.1+(=.#6,&5( 1%\u001e\"\u001d\u001blYn[p\\r]]H_I`JwaybkRLmSMpTMrUMtVMvWNxXNzYN|ZN}[N\\N]O]O^O_O_O`OaOaPaPbPbPcPcPdPdPdPePePePePfPfPfQfQfQfQfQgQgQgQgQgQgQgQgQfQfQfQfQfQfPfPePePePePdPdPdPcPcPcPbPbPaPaO`O_O_O^O]O]O\\O}[N|ZNzYNxXNvWNggghPfP|fzfxevdscsYLiTK_NHYKFh\\Z]UV=;@.R.S.S.S.S.S.S/S/S/S/S/S/S/STxTxTxTxTx/S/S/S/SGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅۅۅۅGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlGlۅۅۅDiDiDiDiDiDiրրրրրրրրրրրրրրր׀׀׀Ei&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfAfAfAfAfAf%J|%J|%J|%J|%J|%J|%I|%I|%I|\u0007\u0006\u0005\u0017\u001e,\r\u001a+\u000e\u001b,\u001b!.\u0018\u0016\u0018! \"\u0016\u0015\u0018\u0015\u0015\u0018\u0014\u0014\u0017\u0014\u0015\u0018\u0015\u0017\u0019`E6iYlZo\\q]s^^Jvawbyczd{e}foTMqUMsVMuWNwXNyYN{ZN|ZN~[N\\O]O]O^O_O_O`O`OaOaPbPbPcPcPcPdPdPdPdPePePePePePePePePfPfPfPfPfPfPfPePePePePePePePdPdPdPdPcPcPcPbPbPaPaO`O`O_O_O^O]O]O\\O~[N|[N{ZNyYNwXNiiiihhRfQdQbPwfx]Opdkbtd_m`]OEDG?A;:@.S.S.S.S.S/S/S/S/S/S/S/S/STxTxTxTxTxTxTxTxTy/SGlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܅܅HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܅Eiրրրրրրրրրրրր׀׀׀׀׀׀BgBgBgBgBg&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfBfBfBfBfBfBfBfAfAf%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|%I|\u0000\u0000\u0000\u0014\u0018\u001e\r\u001a+\u000e\u001b,YA5jPBpSDl[o]q^t`_Kwbycze{f}ghilSrVMtWMvWNxXNyYN{ZN|[N~[N\\O]O]O^O_O_O`O`O`OaPaPbPbPbPcPcPcPcPdPdPdPdPdPdPdPdPePePePePePdPdPdPdPdPdPdPcPcPcPcPbPbPbPaPaO`O`O`O_O^O^O]O]O\\O~[N|[N{ZNyYNxXNjjjjjjhSgSeRcR|`Qsfoe}jcrd`k_]LCDC=@,,3(4F(4F.S.S/S/S/S/S/S/S/STxTxTxTxTxTxTxTxTxTyTyTyHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlChChրրրրEiEiEiրրրրրր׀׀׀CgCgCgCgCgCgCgCgCgCgCgCgBgBg&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|BfBfBfBfBfBfBfBfBfBfBfBfBfBfBf&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|%I|%I|%I|\u0017#5H71O;3V?4iOBoSDsVFo]{[I^K`LbNdO{f}g~hjkTmUoVqWrWwXNxXNzYN{ZN}[N~[N\\O]O]O^O^O_O_O`O`O`OaOaPaPbPbPbPbPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPcPbPbPbPbPaPaPaO`O`O_O_O_O^O^O]O\\O\\N~[N|ZN{ZNyYNoToToTnTllljUiThTfTcSvirgnfyidqdah^^HBD?<@)+3OZkMYk(5F(5F(5F/S/S/S/S/STxTxTxTxTxTxTxTxTyTyTyTyUy܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlDhDhDhCh&K}&K}&K}&K}&K}&K}ChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|&J|&J|&J|&J|&J|BgBgBgBfBfBfBfBfBfBfBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%J|%I|%I|A99N?;L:2T>4gNBlRDk\\n^z[J~^LaNcOdPfQgRhTjUlVnWpXrXsYqqrrrsz[z[z[{[{[{ZœrŒqŒqŒpŒpőoyVxVxUwTwTaPbPbPbPbPbPbPbPbPbPbPbPbPbPaPaPaPaPaOaO`O`O`O_O_O^O^O^O]O]O\\O~\\N}[N|ZNzYNpTpUpUpUoVoVnVmVlVkVjVhVfU~cUujqh~mfugdkaad\\^E@D98?$(2minffm^blV^lMYk(5F(5F/STxTxTxTxTxTxTxTxTxTyTyTyUyUy܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݆݆݆݆݆݆݆݆݆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}ChChChChChChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|CgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|&J|%J|%J|%J|%J|%J|%J|%J|AeAe;GY<68I=:I82Q=4XA6~fZj\\m^p`|]L`NcPeQgSjlmnoXqYrZt[rsstttz]{]{]{\\{\\{\\{[ēsērĒrĒqĒpđpyWĐoÐnÏmÏllkkaOaOaOaOaOaOaO`O`O`O`O`O`O_O_O_O_O^O^O]O]O]O\\O~\\N}[N|ZNllmqVqVqVpWpWoWnnnnn~neWxltkpiykfodcf_`JDG@>C*,5\u001d$1MYktr~tstmolinadmX_lNZkMZkTxTxTxTxTxTxTxTyTyTyUyUyUy݆݆݆݆݆݆݆݆݆HlHlHmHmHmHmHmHmHmHmHmHm݆݆݇݇݇݇݇݇݇݇݇݇HmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHmHm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhChChChChChChChCgCgCgCgCgCgCgCgCgCgCg&J}&J}&J}CgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|&J|&J|&J|&J|AfAfAfAf;GY;GY;GY1'!D:9N?;N;3]I?zdYh[l^oascuebQdRfTlmnopqrsv]w]uuuuv{^{^|^|]|]{\\{\\{[{[zZzZyYyXxXonnmmuTuStStStRsRsQ_O_O_O^O^O^O^O^O]O]O]OrSrSrSkllmmmnnqWqXqXooppppp}o{cXv`Vp]U}nishfhaba\\_DAF::B$)4\u0002\u0001\u0000MYkMYkMYktctq\\QPPIKFDI;>H/8GMZkTxTxTxTxTyTyTyUyUyUy݆݆݇݇݇݇݇݇݇݇݇݇݇HmHmHmImImImImIm݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇ImImImImImImImImImImImImImImImImImIm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhChChChChChChChChCgCg&K}&K}&K}&K}&J}&J}CgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBfBfBfBf&J|&J|&J|&J|&J|&J|BfBfBfBfBfBf;HY;HY;GY;GY;GY;GY;,#I=:H82YF?^JA|e[j]n`qctewgyi|k~lnopqssu]v^w^x_y_z_z_{_wwvvvuut{\\{\\z[zZyZyYxXpowWvVvVuUuUuTtTlkkkkkksTrTrTrTrTrUrUrVnnnoooppqYqqrrrrqgZ{dYvaXp^WiYU`TRVNOb]aEBH<<D36@\u0019\u0019\u001cMYkMYkMYkMYkMZk-.1W>+[NL^SQWNNKFJ?AI2:HTxTyTyTyUyUyUyUyUy݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇ImImImIm݇݇݇݇އއއއއއއއއއއއއއއއImImImImImImImImImImImImImImImIm'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhDhDhDhDhDhCh&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}CgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBgBgBgBfBfBf&J|&J|BfBfBfBfBfBfBfBfBf;HY;HY;HY;HY;HY;HY;GY3(\"D::B41RB=YG@wcZ}g\\k_nbrdug}aRdTgViXkYqrstp^q^w`x`y`z`za{axxwwwvvvuutssrrqqppoovWnnnnnnmtVsVsVsVsVsWsWsXsXpppsYsYrZr[r\\q\\p]ttssh\\{e[vbYo^XhZV`USXPQNJMECJRS[47A+((\u000f\u0013\u0019MYkMYkMYkMZk(5F(5F(5FOHJT=+YML_SRZQQMGJABI2:H/TUyUyUyUyUyUy݇݇݇݇݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއވވވވވވވImImImImImImImImImImImImވ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDhDhDhDhDh'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}CgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgBgBgBgBg&J|&J|BfBfBfBfBfBfBfBfBf;HY;HY;HY;HY;HY;HY>DM>DM;HY89<:+#9&\u001aB52I94ZHAxd[}g^k`ncrey_R}bTeVgXiYk[l\\n]o^vvvawaxaybzb{b{axx|a|a|`{`{_{_{^z^uttssrrwZwZvYvYvYuXuXuXuXpppppppqqtZt[s\\s\\s]r]r^q^p^o^n^l^j^h]{f\\ub[n^YgZW_UTWPQOKOEEKST]JNY>=?\u0015\u0017\u001cJJIMYkMYk(5F(5F(5F(5F(5F)5G)5GK=4S<*XMLbWVYPPLGJ@AI/T/TUyUyUyއއއއއއއއއއއވވވވވވވImImImImވވވވވވވވވވވވވވވވވވވވވވވވވImImImImImImImImވވވ'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhDhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}ChChCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCgCg&J|&J|&J|&J|&J|BgBgBgBfBfBfBfBfBf;HY;HY;HY;HY;HY;HYCIR>DMCIR;HYCIR.$\u001d0\"\u00198&\u001a?*\u001cG/\u001fV=+w[F{g^kanXMs\\Px_S{bU~dWfYhZj\\l]m^vwxyyzzzzz{b{b{b{b{a{a{`{`z_z_z^uy]y]x]x\\w\\w[w[v[v[v[v[rrrsssstuut^s_s_r_r`q`p`wvvu~twd]sb[l^ZeYW]TUUORLJOYYaRU^JOZ>>@!$)\u0010\u0012\u0015RXaMYk39B-3<-3<(5F)5G)5G)5G)5G)5GFDJK9*^K=YONg\\\\TLMIFJ:>I0T0TImވވވވވވވވވވވވވވވވވImImInInInInInInވވވވވވވވވ߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈InInInInIn߈߈߈߈߈'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DiDiDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}ChChChChChCgCgCgCgCgCgCgCgCgCgCg&J}&J}&J}&J}&J|&J|&J|&J|&J|BgBgBgBgBgBfBf<HZ<HZ<HZ<HZ;HY;HYCIR>EM>EMCIR;HY;HYCIRCIR)\u001d\u00156&\u001a8&\u001b@*\u0019H0\u001dI1!\\B0}_JhTKjM8q[Pt]Sw`U{cW~eYg[i\\k^m_vwxyzz{{{{{zdzdzczczcyyyxxxwwwww_w_w_vvvvwwwwwwxxxxxxxxwv~v|tysvrh\\YcXX[TUSNRIHOUXaNS^JFE>>A')+\"%(\u0001\b\u00104:C(5F(5F3:B3:B-3<-3<)5G)5G)5G)5G)5G)5GE:4O:*TKLbXWcZZPIKDCJImImImImވވވވވވވވވވވ߈߈߈InInInInInInJnJnJnJnJn߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߈߉߉߉߉߉Jn߉߉߉߈߈߈߈'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhChChChChChChCgCgCgCg&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J|&J|&J|CgCgCgBgBgBg<HZ<HZ<HZ<HZ<HZMS\\CIR>EMCIRCIRCIR888DGNCJRCIRBBB(\u001d\u00150 \u00158&\u001b<)\u001cG0\u001fM5\"X@0z^KbFkUlXPp[Rs^TvaVzcX}fZg\\i]uvwxyzz{{vevewewe||{{{{{{zzzzzyvbvbvbububuctctcsbscrcqcyyyxxww|uytvs~sqyooslmVQTOLR[\\dQU`KHHAAD:<@68;\u001c &\u0001\u0001\u0001\u0000\u0002\u0005Z`i-4<%');AJ4:C4:C4:C-4<)5G)5G)5G)5G)6G)6G@84H8-N?5YPQmccoghd`dInInInInInIn߈߈߈߈߈߈߈߈߈JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJn߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉߉JnJnJn߉߉߉߉߉߉'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~EiEiEiEi'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDhDhChChCh&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}&J}&J}&J}CgCgCgCg<IZ<IZ<HZ<HZ<HZ<HZ?EN?ENCJRCJRCJRCJRCJRUU\\CJRCJRBDG''''''(\u001c\u0014. \u00159(\u001c:(\u001cB-\u001eO8'kUFt[IhQyic}leogrjtlwnypzq|s|g]~h_j`kalaobpcqdrdrdseteteue||||||||ueududtdtdsdsdrdrdqdqdpcocncyyx~w}w{vyuvs}srxopqknkgkdbhGGOVYcPLLBCF;>B9;>68;\u001b\u001d\u001f\u0000\u0000\u0000\u0002\u0002\u0002\u0000\u0002\u0005Z`iZ`iMZk)5G4:C-4<4:C4:C-4<;BJ)5G)6G)6G)6G)6G)6GC6-L;.leg{{ypqhbeVYcJnJnJnJnJnJnJn߉߉߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJn߉߉߉߉߉߉JnJnJnJnJnJnJn'L~'L~'L~'L~'L~'L~'K~'K~'K~EiEiEiEiEiEiEiEi'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDhDhDhDh'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}&J}&J}CgCgCg<IZ<IZ<IZ<IZ<IZ<IZ?ENDJSDJSDJS?EN?EN?EN<HZ04?'.6'.6&(+''''''\u001d\u001d\u001d,\u001f\u0018)\u001d\u00151#\u00187&\u0019;)\u001dM8)S;+mVGdKseawhc{kfnhpjrltmvotaZvc[wd]yf^zg_{h`|i`~jakblbmcncodpdpdpdpdpe{pepepepepdododndmdmclckc}jc|jbyhb}w{wyvwuut}sryqqunpojmhfkKKRDFOD><535=AG=?D?AD<?B&(+\"$'\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0005KRZTZcMZkKOVRYaSYb.4=.4=4:C.4=4:C)6G)6G)6G)6G)6G)6GWMFaRGhbe{su}}kde_^dJnJnJnJnJnJnJnJn߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJoJoJoJoJoJoJoJoJoJoFjFjFjFjFj'L~EiEiEiEiEiEiEiEiEiEiEi'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}Dh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}&J}&J}&J}Cg>==<IZ<IZ<IZ<IZ<IZMT\\DJS?ENDJS?EN?EN?EN\")1\")1C5+//3(.7&),'''''''''\"\"\"\u001c\u001c\u001c\u001a\u0012\r.\u001e\u0011, \u00187(\u001d8'\u001bA1&F4(L8*oXIw]Jpdasfcvhexkg{mi~ojqll\\Xn^Yp`Zpa[qa\\rb]rc^sc^sd_ue`wf`xgayhayhayhbxyyyyyy~ywgbvfateasd`qd`pc`nb_la_ut|ssxqrunpZUXVRWROUMMSHIRIC@967-/3'+0(*-ACF?AD;=@#%(\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001JMPU[dSYbKPVW]fY`hSYbSYb.4=4;C4:C.4=)6G)6G)6GCPaCPaCPaFED]PGdaesmomefb_dJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoFjFjكككڃڃڃڃEiEiEiEiEiEiEiEi'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}DhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&K}&J}@K[=IZ<IZ<IZ<IZ<IZNT]DJS?ENDJS#)2#)2#)2#)2#)2'.6A4+028(.7'),)))######\"\"\"\u001c\u001c\u001c6$\u0016nP?\u001a\u0013\r.\u001e\u0011+\u001f\u0017>1(B3)B2&F4'E4)gTGlXJs^OzcTzaPqfethgvjhbVTcWUdXVeYWfZXg[Yh\\Zi]Zi][j^\\usususts~tt~tt}tt|st{stut~tt|sszrsyqrwpquoqsmpqloXTXTQWPOULLSSJEA<:=99757335./2113)+.'),)+.8:=\u001e\"(\u0000\u0000\u00003@Q\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001JMPV\\eT[cNZlNZlZ`iZ`iZ`iZ`iSYbY`h4;C.4=)6GCPaCPaCPaCPaCPaEQbZOGa_emhknfgeaeJnJnJnJnJnJnJoJoJoJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoኮኮኮኮኮኮKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoڃڃڃڃڃڃڃڄڄڄڄڄڄEjEiEiEiEi'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K}'K}'K}'K}'K}'K}'K}DiDiDiDiDhDh'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}&K}&K}&K}&K}$.>=I[=I[<IZ<IZ<IZ?FN'.6#)2#)2#)2#)2#)2#)2(.7#)2\u001f,=@<A348)/8\"$'\"$'######\"\"\"\u001c\u001c\u001c\u001c\u001c\u001c\"\u0014\tkF+;(\u0019\u001a\u0013\r\"\u001b\u00166*#5*\">2)>0&A2'C3(I8-^OFbRHfUJjXMq^RwcVzfYfRDfQCdN@zdTqijrjksklrklrklrklqjmpjmpjmojmojmnimmimkhliflscYm`Xg\\VbYT^VRE>;A<:>98:77645:873220/0,-/)+.*,/#%(\u001b &\u0000\u0000\u0000\u0000\u0000\u000015;5BS\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000KKKJMP]dlU[dNZlNZlZ`iTZcZaiZaiZ`iZ`iSZbLS[V]eDPbDPbDPbDPbDPbDPbWMF^^dieirkeaeJoJoJoJoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoኯኯኯKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoڃڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄڄۄGk'L~'L~'L~'L~'L~'L~'K~'K~'K~'K~'K~'K~'K~'K~'K~'K~EiEiEiEiEiDiDiDiDiDi'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}&K}&K}&K}&K}%/> ,>=I[=I[ ,> ,>#)2(.7#)2(.7#)2#)2#)2#)2(.7(.7(.767@D>A214$+3#%(\"$'###\"\"\"\"\"\"&&&\u001c\u001c\u001c888888cB*}\\I@!\b\u001b\u0017\u0014%\u001e\u0019+%!5*$:/(;0)<1*>3+@4+>1(bUKN@6OA6L=3QB8M?4_RKaTLbUMcVNcVNcVObVOaVOaUO`UO_UO^UO^TO\\SOYRNWPNUOMWPKYSOWRN;63953:76755333,/2'),%(+\"%(\u001c!'\t\t\t\u0000\u0000\u0000\u000f\u0010\u0012\"&,KXi04:\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0003\u0003JMP]_b^emU[dNZlNZlT[cU[dU[dU[d[ajW]fDPbDPbDPbDPbDPbDPbnSw|mqjKoKoKoኮኮኮኮኮኯኯኯKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpڄڄڄڄڄڄڄڄڄڄڄۄۄۄۄۄۄۄۄGkGkGkGkGkGk'L~'L~'L~'L~'K~'K~'K~EiEiEiEiEiEiEiEiEiEiEiEiDiDi'K}'K}'K}'K}HlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}'K}&K}*2? ->=I[=I[ ,> ,> ,>#)2#)2#)2(.7(.7#)2#)2(.7(.7(.7(.7/28:79G@A<89',4#%(#%(######\"\"\"\"\"\"\u001c\u001c\u001c8888888887'\u001avS:jW;)\u001c\b\u0004\u0000\u000f\f\n\u0016\u0011\r\u0019\u0013\u000e\u001e\u0016\u0011&\u001e\u001a3#\u0018.$\u001e-% .% .& /&!,#\u001d,#\u001d@70A71XNHXNHWNHWNHZRLYQLYQLXQLWQLWPLUOLSNLQMKOLJMJJ0//.-.,,-&(+\u001e\"(\u001d!'\u0013\u0016\u0019\u000b\u000b\u000b\t\t\t\u0000\u0000\u0000\u0014\u0018\u001e\u0013\u0014\u001615;6CT37=\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000MMMKMP^ad_enY`hNZlNZlU\\dV\\eDQbDQbDQbDQbDQbMUcyl|oiKoኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpKpKpKpKpKpKp⋯⋯⋯LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpڄڄڄڄڄۄۄۄۄۄۄۄۄۄۅۅۅۅۅۅGkGkGkGkGkGkGkGkGkۅ܅܅܅܅܅܅܅܅܅܅܅܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}'K}'K}'K}'K}'K}HO\\=J[=J[=J[ -> ,> ,>(.7#)2#)2(.7(.7(.7#)2(.7(.7(/7(/7)/8/28114H7,99@.05&,5$&)$$$######\"\"\"(((8888888888888884\"\u0014nO9gXjZE/ (\u0019\u000e\u0007\u0003\u0000-\"\u001c\r\u000b\n\u0012\u000f\f\u0015\u0011\u000e\u0016\u0012\u000e\u0018\u0013\u000f\u0019\u0014\u0010\u001c\u0017\u0012\u001c\u0019\u0017%\u001f\u001b' \u001c%\u001a\u0012$\u0019\u0012#\u0019\u0011\"\u0018\u0011 \u0017\u0011\u001f\u0016\u0010\u001c\u0019\u0018\u001b\u0019\u0018\u001a\u0019\u0018!\u001f \u001f!$\u0017\u001a\u001d\r\r\r\f\f\f\f\f\f\u000b\u000b\u000b\t\t\t\t\t\t\u0004\u0006\b\u0001\u0001\u0001\u0000\u0000\u0000\u0013\u0015\u001748>7CU:GX\u000b\u000f\u0015\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000JJJLLLKMPagp_enNZlLPVDQbDQbDQbDQbNVcuorjѼዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp⋰⋰⋰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpۄۄۄۄۄۄۄۄۅۅۅۅۅۅۅۅۅۅۅۅGkGkGkGlGlGl܅܅܅܅܅܅܅܅܆܆܆܆܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl'K}'K}'K}'K}DhDhDhIP\\=J[=J[=J[=J[ -> ->(.7#)2#)2(.7(.7(.7#)2(.7(/7(/7)/8)/8)/803966:E?AC>A856,07%'*%')$$$######(((DDDBBB888888888\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c0 \u0014cF1w]OcS{`QS;+5\u001b\u00067'\u001c\u0017\r\u0004\r\u0006\u0001\u0017\r\u0005\u001c\u0011\b* \u001b\u001f\u0016\u000f\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\u0005\u0003\u0001\u0004\u0002\u0000\u0004\u0002\u0000\t\u0007\u0004\f\r\u000f\f\u0010\u0016\b\b\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u0007\t\u0011\u0014\u0017;?E7CU;HY=I[\f\u0011\u0017\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000JJJMMMKMPacfbhqEQcHScNVdȵዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⋰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpۄۄۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅۅ܅܅GlGl܅܅܅܅܅܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇DhDhDhDh=J[=J[=J[=J[=J[=J[ ->(/7#)2#)2(.7(.7(.7#*2(/7)/8)/8)/8)/8)08*0903:56:88@KBB=;@348*08&(+'(*%%%$$$(((EEE(((&&&\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u0000\u0000\u0000\"\u0018\u0010>-\"bF3oXMs[Ow]Py^PqbpXMdH5R<,Q;,\u001b &\u001b\u001f%\u001a\u001e%#'-\"'-&3DS_qP\\nR_p>J\\?K]<AG\u0010\u0015\u001b\u000e\u0010\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000%%%DDDACF⋯⋯⋰⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰LpLpLpLpLpLpLpLpLpLpLpLpLp⌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰㌰LqLqLqLqLqLqLqLqLqLqLqLqLqLqLqLqۅۅۅۅۅۅۅۅۅۅۅۅ܅܅܅܅܅܅܅܅GlGl܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆܆݆݆݆݆݆݆݆݆HlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇DhDh=J[=J[=J[=J[=J[=J[=J[(/739B#)2(.7(/7(/7#*2$*3)/8)/8)/8)08*09+19(-5*.5/16437D>AG@B::@66:-29'),)'%BBBFFFEEE)))))))))&&&\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b@@@FFFACFZ\\_[ajagpEQcGRcKTdPWd⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌰LpLpLqLqLqLqLqLqLq㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMqMqMqMqMqMqMqMqMqMqMqMqMqMqۅۅۅۅۅۅ܅܅܅܅܅܅܅܅܅܅܆HlHlHlHlHl܆܆܆܆܆܆܆܆܆܆܆݆݆݆݆݆݆݆݆݆݆݆݇݇݇݇݇HlHlHlHlHlHlHl݇݇݇݇݇݇݇݇އއއށ>J\\>J\\=J[=J[=J[=J[FLU39B#*2(/7)/7)/8$*3$*3$*3)/8)08*09*09*19',5(-5*.6.17338@<=G@BH@BXW]UUXLPWFHKDFHKKKHHH+++%%%%%%$$$###!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b777777777777777777777\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001bAAAFFFACFACF\\^aeltbhqDQbDQbDQbERcERcERcERcHScLUdRXd|nj⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌰㌱㌱㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱MqMqMqMqMqMq㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMqMqMqMqMqMqMqMqMqMqMqMq܅܅܅܅܅܅܅܅܅܅܆܆܆܆HlHlHlHlHlHlHlHlHl܆܆܆݆݆݆݆݆݆݆݆݆݆݆݇݇݇݇݇݇݇݇݇݇݇݇HlHlHlHlHl݇݇݇އއއއއއއއއއށ>J\\=J[=J[FLUFLU(/7(/7*08*08%+3$*3$+3$+3*09*09*19&,5&,5'-6).6*/7-18NPURRVXUVc]^f^_[X]\\XYTUZLQYKMPFHJ)))(((&&&%%%%%%$$$$$$###!!!!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b777777777\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001bBBBEEEACGADGFIL\\ckZ`iTZcDQbDQbDQbagpbiqcircirY`hY_hERcERcERcGSdJTdNVdTYeLpLp㌰㌰㌰㌱㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱MqMq㍱㍱㍱䍱䍱䍱䍱䍱䍱䍱䍱䍱䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲䍲MqMqMqMqMqMqMqMqMqMqMq܅܅܅܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHl݆݆݆݆݆݆݆݆݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇HmއއއއއއއއއއއވވވވވށFLUFLUFLU)/8+08+08&+3&+3%+4%+4%+4*19+1:&,5'-5'-6(.6FLTHMTINUKOVOQWSTXYWX`[^lbac]_f_\\a_aY\\aRX_,.1*,.*+-***((('''&&&%%%%%%$$$$$$$$$###!!!!!!!!!!!!!!!\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001c\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b\u001b%%%%%%%%%%%%\"\"\"\"\"\"\"\"\"KKKJJJFFFGIL]_b^dm\\bkV]eDQbEQcEQcEQccirdjsdksektdjsdjscir[ajZ`iOU^ERcERcFRdFRdITdLUdPWeVZeLpLqLqLq㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱䍱䍱䍱䍱䍱䍲䍲䍲Mq䍲䍲䍲䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲MrMrMrMrMrMrMrMrMrMr܆܆܆܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇݇އއއއHmHmHmއއއއވވވވވވވވވވވވށ-18,18',3',4',4&,4%,4+1:,2:'-5DJSEKSEKTFLTFLUHMUINVKOWLPWQSYTUZWWZpjje^`offb\\_h`]eaaCCG8;A27?-/2+-/.+)******)))((('''&&&&&&%%%%%%$$$$$$$$$$$$$$$$$$######???EEEEEEEEE((((((###&&&%%%HJMHJMHJMHJM_en]dlZ`i_enEQcEQcEQcEQcbhqektflufluflufluektektdksdjscjr\\ckQW`[ajZaiOU^FRdFRdFRdHSdKUdNVeRXeX\\fLqMqMqMqMq㍱㍱㍱㍱㍱䍱䍱䍱䍱䍲䍲䍲䍲䍲䍲䍲䍲䎲䎲䎲䎲䎲MrMrMrMrMr䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲厲厲厲厲厲厲厲厲NrNrNrNrNrNrNrNr܆܆܆܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇݇݇݇݇݇݇݇އއއއއއއއHmHmHmHmImImImވވވވވވވވވވވވވވވނPT[KOVJOV(-4(-4'-5'-5JOXEKSEKSEKTFLTFLTGMUGMUHNVIOWKPWLQXMRYPTZTV[\\]a_^asljd^azporjkE@CLEBIEFEDG29A28A17@135,.1+-0+,/./1..0'),)))++++++++++++***FFFFFFACFACFEEEACFACFJLOJLOKQZ_en]clY_hU[dEQcEQcEQcEQcEQcagp[aj\\bk\\bkgnvgnvgmvgmvfluflueltektdksdjscjrcirTZcSYbRYaRXaQW`[bj[ajZ`iFSdFSdGSdJTdLVePXeTZfZ]fMqMqMqMqMqMqMq䍲䍲䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲NrNrNrNrNrNrNrNrNr厲厲厲厳厳厳厳厳厳厳厳厳厳厳厳厳厳厳厳右右右右右右右NrNrNrNrNr右冪܆܆HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHl݇݇݇݇݇އއއއއއއއއއއއImImImImImImImImImImވވވވވވވވވ߈߈߈߈߈߈߂LPVLPWKPWFLTFLTFLUGMUGMUHMVHNVINWIOWKPXLQYMRYNSZTX`X[a[]b]^c__ccacib`JDGi__aYYPJLD@C=;AKEDTQR@?A>>A;<A17@06?/6>/5>.4=-4<IOXHOWMS\\QX`EQcEQcEQcEQcEQcEQc`fo[bj\\bk]cl]dl^dm^dm]dlhnwhnwgnvgmvgmvfluflueltektdksdjscircirV\\eU[d_fn^emSYbRXaQX`[bjPV_OV^FSdGSdITeLVeNWeRYfW[f\\^gMqMqMqMqMqMqMqMq䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲䎲厲厲厲厲NrNrNrNrNrNrNrNrNrNrNrNr右右右右右右右右右右右右右右右右右右右右右右右右右右右Ns右右右HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHmHmHmއއއއއއއއއވވވވވImImImImImImImImImImImImImވ߈߈߈߈߈߈߈߈߈߈߈߈߉߂JPXJPXKQYQW_RW_SX`TY`UZaW[bZ]c\\^c^_dCDHDDHTRSWQO@=BNHKbYZ^VWUNPMGJFAEgcgcafEQc`go[aj]cl]cl^dm^em_en_en_en_en^em^dm^dmioxhnwhnwgnvgmvgmvfluflueltektdjsdjscirW]fagp`go`fo_enSYbRXa\\ck[bj[ajFSdGSdITeKUeNWeQXfTZfY]g``gMqMqMrMrMrMrMrMrNr厲厲厲厲厳厳厳厳厳厳右右NrNrNrNrNrNrNrNrNrNrNrNrNsNsNsNs右右右右右揳揳揳揳揳揳揳揳揳揳揳揳援援援援援援援援OsOs援援HlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmއވވވވވވވވވImImImImImImImImImImImImImImImImIm߈߈߈߈߈߉߉߉߉߉߉߉߉߂PRWOQWTW\\`dkbek^af_ag`bgabgiko_en^emhnw`fo`fo`fo`fo`fo`fo`fo_fn_fn_en_en^em^dm^dmioxhowhnwgnvgmvgmvflufluektektahpagp`foTZcSYbRYa\\ck\\bkPV_GSeITeKUeMWePXfSZfW[f\\^gdbhMrNrNrNrNrNrNrNrNrNrNr右右右右右右右右NrNrNrNsNsNsNsNsNsNsNsOsOsOsOsOsOsOsOs援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴OsOsOsOsOs搴HlHlHlHlHlHlHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmHmHmImImImImވވވވވވވImImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉߉߃CPaCPaOVbRSWQRWPRWUW]U[dU\\dW]eW]eX]eV\\eagpagp`go`go`fo`fo`fo`fo_fn_en_en^em^dmioxioxhowhnwgnvgmvgmv`foTZcSZbRYaQX`\\bkGSeITeKUeMWfPXfSYfV[gZ]g_`hNrNrNrNrNrNrNrNrNrNrNrNrNr右右右右右NsNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOs搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴OsOsOsOsOsOsOsOsOsHlHlHlHlHlHmHmHmHmHmHmHmHmHmHmHmHmHmImImImImImImImImImImImވވވImImImImImImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉CPaCPaCPaCPaCPaQWcYY\\XX\\RSXWX]bdiU[dU[dU[dagpagpagp`go`go`fo`fo`fo_fn_en_en_enipxioxioxhowhnwTZcSYbRYa\\ck\\bjIUeKVeMWfOXfRYfU[gX\\g\\^gcbhNrNrNrNrNrNrNrNrNsNsNsNsNsNsOs援OsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOt琴琴琵琵琵琵琵琵琵琵琵琵琵琵琵PtPtPtPtPtPtPtPtPtPtPt\u0013\\HmHmHmHmHmHmHmHmHmHmHmImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImImIm߉߉߉KQZFLUFMUCPaCPaCPaCPaSXcRWcddgddhddiceicejU[dagpagpagp`go`fo`fo`fo_fn_en_enjpyipxioxSYbRXa]ckIUeKVfMWfOXfQYfT[gX\\g[^h_`hgdiNrNrNsNsNsNsNsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOsOtOtOtOtOtOtOtOtPtPtPtPtPtPtPtPt瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPt\u0013\\HmHmHmHmHmImImImImImImImImImImImImImImImImImImImImIm߈߈ImImImImImImImImImImImImImImImImImImImImImImInInInInInInInCPaCPaKQZFMUKRZKRZCPaCPaCPaCPaUYcTXcRWceeheeieeiefjefkZ`iZ`iZ`iU[dagpagpagp`go`fo`fo`fo_fn_enjpyJUfKVfMWfOXfRYgTZgW\\g[^h^`hcbijfiNsOsOsOsOsOsOsOsOsOsOsOs搴搴搴琴OsOsOsOtOtOtOtOtOtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPt瑵瑵葵葵葵葵葵葵PtPtPtPtPtPtPtPtPtPtPtPtPtPtPt\u0013\\\u0013\\ImImImImImImImImImImImImImImImImImImImImImImIm߈߈߈߈߉ImImImImImImImImImImImImImImImInInInInInInInInInInInInJnJnCPaCPaT[cKQZFMUKRZKRZLR[GMV@BDCPaDPbWZcVYcTXcSXcgfi\\[_ggjggkfglioxioxipxjpyjpyjqy`foagpagpagp`go`fo`foNWfPXgRYgT[gW\\gZ]h^_hbaigdimgjOsOsOsOsOsOsOsOsOsOs琵琵琵琵琵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPtPuPuPuPu蒶蒶蒶蒶PuPuPuPuPuPuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\ImImImImImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉ImImImImImImImImInInInInInInInInInInInInInJnJnJnJnJnJnJnJnJnJnCPaCPaU[dKRZGMVLR[LR[LR[GMVGNVHNWDPbDPbY[dWZdVZdUYcTYchgi]\\_hhkhhl]^bjowjpxjpxjpxjpyjpykqykqzkqzkqz`foagpagpagpRZgU[gW\\hZ^h]_haaiecijfjOsOsOsOsOsOsOsOtOt瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵PtPtPtPtPtPtPtPtPtPtPtPtPuPuPuPuPuPuPuPuQuQuQuQuQuQuQuQuQu蒶QuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\\u0013\\ImImImImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉ImImInInInInInInInInInInInInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnCPaCPaCPaKRZV\\eGMVLR[LR[LR[GNVHNWHOWIOXIOXDPb[\\dZ[dX[dWZdVZdUYd_]__]`jil_^b__clpwlpwlpxlqxlqylqylqylqylqzlrzlrzlr{lr{agpW\\hZ^h]_i`aidciiejmgjOsOtOtOtOtPtPt瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶葶PtPuPuPuPuPuPuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQu\u0013\\\u0013\\\u0013\\ImImImImImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉߉߉߉߉InInInInInInInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኮJnJnAFLCPaDPbLR[LR[V]eLR[LR[LS[HNWHOWIOXIPXJPYKQZBFL^]d\\]d[\\dY[dX[dWZdVZd`^``_akjma`ca`dmpvmpwmqwmqxmqxmqxmrymrymrymrzmrzmrzmr{ms{ms{ms{ahpms|ahpagplr{`aiccihejlgjpikPtPtPtPtPt瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶QuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQuQvQvQv铷铷铷QvQvQvQvQvQvQvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\ImImImImImImImImIm߉߉߉߉߉߉߉߉߉߉InInInJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኮኮኯኯኯJnDPbDPbLR[LR[W]fLR[LS[MS\\HNWIOXIPXJPYKQZLR[PRUQSVDQb^^e]]e\\]eZ\\dY[dX[dWZdb_ab`bb`cbadcekcfkoqwoqworxorxoryoryosyoszoszoszns{ns{ns{ns{chpchqchqchqnt|bhqms|ms|ls{lr{lr{gejlgkohkPtPtPtPt葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷QuQuQuQuQuQuQuQuQuQvQvQvQvQvQvQvQvRvRvRvRvRv铷ꓷꓷꓷꓷꓷꓷRvRvRvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ImImImImImIm߉߉߉߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኯኯኯኯዯዯዯᄑDPbDPbV\\eW]fLR[GNVHNWHOWIOXJPYQW`RXaSYbRYaTUXTUXBFLa_e`^e^^e]]e\\]eZ\\eY[eX[dW[dnlmomndbdeeiefjefkefkegleglegmpsxpsypsypszptzptzpt{pt{pt{pt{pt|diqdiqdiqdiqdiqdiqot}bhqbhqms|ms|ms|ls{lr{lr{krzkqzkqznhkqjkPtPt蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷钷钷铷铷铷铷铷铷铷铷QvQvQvQvRvRvRvRvRvRvRvRvRvRvRvRvRvRvꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸRvRvRvRvRvRvRvRvRvRvRvRvRvRvRv\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ImImIm߉߉߉JnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnJnኯዯዯዯዯዯዯዯዯᄑU\\dV]eLS[HNWHNWIOXOU^JQYQW`RYaTZcagpacfmjiflugnvaVPb`ea_e_^e^^e]]e[]eZ\\eZ\\eY[epmnpnoecefehffigfjggjggkgglghlghmghmghnrtyrtzrtzrtzru{ru{ru{qu{fjpfjqfjqejqejqejqejqejrdjrou}mt|bhqms|ms|ms|ls{ls{lr{lr{krzkqzkqzjqyjpyPu蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓷRvRvRvRvRvRvRvRvRvRvRvRvRvRvRvꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸSwSwSwSwSwSwSwSwSwSwSwSwSw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\JnJnJnJnJnJnJnJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯዯᄑLR[GNVHNWHNWIOXOU^[ajRXaSYbU[dahpcirektgmvioxjpyBGMbWPc`fb`f`_e_^e^^e]]e\\]e[\\eZ\\eY[eropgegsqssqtsruhgjhhkhhlhhlhimhimhinhjnhjosuzsu{su{sv{hjphkqgkqgkqgkqgkqgkqfkrfkrfjrfjrejrpu}mt|bhqbhqbhqms|ls{ls{lr{lr{krzkqzkqzjqyjpyjpyioxioxsklQuQu钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸRvRvRvRvRvRwRwRwRwRwRw딸딸딸딹딹딹딹딹딹딹딹딹딹땹땹땹땹SwSwSwSwSwSwSwSwSwSwSwSw\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮJnJnJnJnJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯዯዯዯ⅑HNWHNWIOXOU^\\bk]cl^emU\\dbhqdjsfluhnwipxkqzlr{ahpeXPdWPdafc`fa`f`_f__f^^e]^eifgtrsurtusuutvjiljiljimjjmjjnjjnjkojkojkpikpikpikpikqikqikqhkqhkqhkqhkrgkrgkrgkrgkrfkrqv}bhqbhqbhqahpahpagpagplr{lr{krzkqzkqzjqyjpyjpyioxiox]cl\\ckgnvpjlrklulmQuQuQu铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸RwSwSwSwSwSwSwSw땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹땹SwSwSwSxSxSxSxSxSxSx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯJnJnJnJnJnJnJnዯዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋰⅑NT]OV^[bj]cl_enagpX^gdksfmuhnwjpykrzagpbhqahphZQfYQgcfebfdafc`fb`fjghkgivsuvtvvtwvuwkjmkjmkknkknkkovwzvw{vw{vw{klpjlqjlqjlqjlqilqilqilqhkrhkrhkrhkrgkrgkrfkrbhqbhqahpahpbhpagpagp`go`go`fokqzkqzjqyjpyjpyipxioxiox]cl\\ck\\bk[bjfmuflunilpjlrklulmQuQuQuQuQv铷ꓷꓸꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딸딸딹딹딹딹딹땹땹땹SwSwSwSwSwSw땹땹땹땹땹땹땹앹앹앹앹앹앹앺앺앺앺앺앺앺앺앺앺앺TxTxTxTxTxTxTxTx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯዯዯዯዯዯዯJnJnJnJnዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰→[aj]cl_enagpX^gZ`i\\bkioxjqylr{ahpbhqahpagp_fnj[QiZQhcgkghlhiwtuxuvxuwxvxxvxmkmxwyxwzxwzxw{ww{ww{ww{wx|klqklqklqjlqjlqjlqjlqilqikqhkqhkqhkqgkqgjqeiqeipdipdipchpchpbhobgoagoafo_en_en_enjpyipxioxiox]cl]cl\\bk\\bk[aj[ajfluZ`iY_hZ_hlhlnilpjlrkmtlmwnmQvQvRvRvRvRvRvꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딸딹딹딹딹땹땹땹땹땹땹땹땹땹땹땹땹땹땹SxSx앺앺앺앺앺앺앺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺TxTxTxTxTxTxTx\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኮኮኮኯኯኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯJoዯዯዯዯ⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⅒QX`_emagpY_gZai\\bk^dm`folr{ahpahpchpbgolqyhnwl\\Q\\]fmiimijmjknjknklnkmnkmywyywzywzyx{xx{xx{xx{xx{wx|llpklpklqklqjlqjlqjkqikqikqhkpsv|sv|su|ru{fipfipeipeiodhodhocgocgnbgnbfnafn^dm^dm]dliox]cl^cl]ck]bk\\bj[aj[aifltektY_hX_gIVgMXhNXhlhmojmqjmpjmskmtlmvmmRvRvRvRvRvRvRvRvRvꔸ딸딸딹딹딹딹땹땹땹땹땹땹땹땹땹땹땹땹앹앹앹앺앺앺앺앺얺Tx얺얺얺얺얺얺얺얺얺얺얺얺얺얺얺햺햺햺햺햺햺햺햻햻햻햻햻햻햻햻TyTyTyTyTy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኮኮኯኯኯኯኯኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯJoJoJo⋯⋯⋯⋰⋰⋰⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⋕choZ_g\\ai^dk^dm`folr{ls{agpdipchomqx]^f]^f\\^fzvvzvwoklokmolmolnnlnzxzzxzyxzyx{yx{xx{xx{xx{llpllpklpklpvw{uw{uv{tv{tv{ruzfiofhnehnehndgncgmcgmbfmbfmaellpxlpwkpwkov^cj^cj]bj]bihmugltgltfksKWhKWhOYhPYhQZhR[iS[iU\\ilimojmrknslmtlmrkmvmmvmnyonRvRvRvRvRvRvRwRwRwRw땹땹땹땹땹땹땹땹땹땹앹앹앹앺앺앺앺얺얺얺얺얺얺얺얺TxTxTxTxTx햺햺햺햺햻햻햻햻햻햻햻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻UyUyUyUy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ኯኯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯ⋯⋯JoJoJoJoJo⋰⋰⋰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰→^bi`dkbfmdhokrzlr{lr{qt{psy__g^_g^_g]^g{vv{ww{wxolmolmolmolnzxzzxzzxzyxzyxzmlomlollolkowwzvwzvvzrtyqsyegmegmdglorxoqwnqwmqwmpvlpvlovkouknu_bijntimtimthlsNXhNXhPZhQZhR[iS[iT\\iU\\iW]iX^jY^j[_jnjnpkorlotmnumnvmnvnnwnnxnnyonRvRvRwRwRwRwSwSwSwSwSwSw땹땹땹앹앹앺앺앺얺얺얺얺얺얺얺얺얺얺얺얺얺햺TxTxTxTyTyTyTyTy헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻헻UyUy\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯JoJoJoKoKoKoKoKoKo⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㏗dglfhnru{krzsu{rtzªĬ©baga`g``g``g__g^_g]_gpkkpklpll{wx{wx{wyzwynlmnlnnlnmknmknlknlknfglegkefkdfkoqvoqvnpunpumoumou`ci`bh_bh_bhPYhPYhQZhRZiS[iT[iU\\iV]iW]iX^jY^jZ_j[_j\\`j^ak`bkackokormpunpvopwoownoxnnxonyonzon{pn{poRwSwSwSwSwSwSwSwSwSwSwSwSwSx얺얺얺얺얺얺얺얺얺얺얺햺햺햻햻햻햻헻TyTyUyUyUyUyUyUyUyUyUy헻헻Vz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯዯዯዯዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰KoKoKoKoKoKoKoKoKoKoKoKoKo⌰⌰⌰⌰⌰⌰⌰⌰㌰㌰㌰㌱㌱㌱㌱㌱㑘rtyhjotv{Ȯϳϳǫdbhcbhbahaaha`h``h_`g__g^_g]_gokkokk{wxzwxzwxzwxyvxmjlefjeeideioptoptnotbchachabgS[hS[hS[iT[iU\\iU\\iV\\iW]iW]iX^jY^jZ_j[_j\\`j]aj_ak`bkbckcdkeelgfligmqlptoqwpryqrzqqzppzppzpozpo{po|po|qo|qoSwSwSwSwSwSwSwSwSwSxSxSxTxTxTxTx얺얺얺햺햺햻햻햻햻헻헻헻헻헻헻UyUyUyUyUyUyUyUyUyUyUyUyUyUyUz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ዯዯዯ⋯⋯⋯⋯⋯⋰⋰⋰⋰⋰⋰⋰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKo⌰⌰⌰㌰㌰㌰㌱㌱㌱㌱㌱㌱㍱㍱㍱㌇ͱҵҳаfciechdbhcbhbahbahaahaah``h_`h_`h^_h]_hzvvzvvqptppsV\\iV\\iV\\iU\\iU\\iV\\iV]iW]iX]iX^iY^jZ_jZ_j[_j\\`j]`j^aj_ak`bkbckcckddkeelgfligmkinnjoqlpwpszst}tu~tt}ss}rr|rq|qp}qo}qo~qo~ro~roSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTx햻헻헻헻헻헻헻헻헻헻헻헻UyUyUyUyUyUyUyUyUzUzUzUzUzVzVzVzVzVz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⋰⋰⋰⋰⋰⋰⋰⋰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKo㌱㌱㌱㌱㌱㌱㍱㍱㍱㍱㍱㍱㍱㍱㔚TYeSYekjmvvyŸĬҳұұѰiejhejfdieciecidbicbicbhbahaahaahY^iX^iY^iY^iY^iZ^iZ_i[_j\\_j\\`j]`j^aj^aj_aj`bkabkbckcdkddkfelgflhfljgmkhmnjnplo¹xxwvvuustrsqrprpspspspspSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUy헻헻헻UyUyUzUzUzUzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVz\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⋰⌰⌰⌰⌰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKo㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱㗛VZeVZeVZeVZeVZeVZeVZe̾ĢұԬήѰmilkgljfkhejgejfdjfdieci]`j]`j^`j^aj^aj_aj`aj`bjabkbckcckcdkddkedkfelgflifljglkhmmimnjnpkosmpżȾʿɾȽǻwuustrtqtptptptptpSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{V{W{W{\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⌰⌰⌰⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKp㍱㍱㍱㍱㍱㍱㍱㍱㍱㍱䍱䍱䍱䙜Y\\eY\\eX\\eX\\eX\\fX\\fX\\fX\\fX\\fY\\fY\\fŷþźֲŪɬ̮ٲrmqpkoojnmimkhlbcjbckcckcckddkedkeekfekgelhflifljgljglkhmmimnjmpknrlotnpwprż¿ʾɼǺvruququpupuquqTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{W{W{W{W{W{W{W{W{W{W{W{W{\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\⌰⌰KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKp㍱㍱㍱㍱䍱䍱䍱䍱䍲䍲䍲䍲䛞[]f[]f[]f[]f[]f[]f[]f[]f[]f[]f[]f[]fa`g˼ɾ꽛ĥ˭ѰӳúĻżĽüztvxruhfkhfkiflifljglkgllhllhlmimnimojmpjmqknsmovopyqr|st¹Ƽ̾ʼɺȹvqvqvqvqvqvqTxTxTxTxTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzVzVzV{V{V{V{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W|W|W|W|W|\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpLpLp䍱䍱䍱䍲䍲䍲䍲䍲䎲䎲䎲䘜]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^f]^fdbghdhmfhõ÷ؾͮղĹƽɿňƿýnilnilnilojmpjmqkmrkmslntmnvnowopzqq}sswvǽÿ;˼ʺɺɹwqwqwqwqTxTyTyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{W{W{W{W{W{W{W{W{W{W{W{W|W|W|W|W|X|X|X|X|X|X|X|X|X|\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLp䍲䍲䎲䎲䎲䎲䎲䎲䎲䎲䛞]^f^^f^_f^_f^_f__f__f__f__f__g__g__g__g__g__gfchkehoghtjizmjƶüǼٿ۾öŹȻ˿žºslmtlmumnvnnwnoyoo{qp|rrtsvuzx½Ͽͽ̼˻˺˺˺xrxrUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzVzV{W{W{W{W{W{W{W{W{W{W|W|W|W|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X}X}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKoKoKoKoKoKoKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLp䎲䎲䎲䎲䎲䎲䎲䎲Lp[]f^^f__f``f``g``ga`ga`ga`ga`ga`ga`gbagbagbaghdhmfiqiivki|okvpz¶پ搴濱´öŷǺzw~z~ɿƽúzpo|qo}rptrusxu{x~{ľпνμͼͻͻͻͻxrUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{W|W|W|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X}X}X}X}X}Y}Y}Y}Y}Y}Y}Y}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KoKoKpKpKpKpKpKpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp䎲䎲䎲䎲䎲LpLpLqLq]^f__f``ga`gbagbagcagcagcagcagdbgdbhdbhechieiogisjixljpkxqz}ۿ°搴搴濱²²³³³³³³óóôôĵtpvrxt{w~z}¿˿ȼƺĸ¶µöķvsxu{w~y|ž¼оϽϽϼϼϼμͼUyUyUzUzUzVzVzVzVzVzVzVzVzVzV{V{V{W{W{W{X|X|X|X|X|X|X|X|X|X|X|X}X}X}X}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\KpKpKpKpKpKpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLp厲厲LqLqLqLqLqLq__fa`gb`gcagcagdbgdbgebgebhfchfchhdihejlgkqikukjzmjqkxqzy}o}m搴搴搴搴搴²óóĴĴĴŴĴŴŴŴrlsmsntoupwqys{v}x{~þͿ˽ɻǹƸŷŷĶĶĶõõĶĶŷƷǸȹɺʻ̼ξ~y{ƿüҿѾѾѾѽннϽVzVzVzVzVzVzVzVzV{V{V{W{W{W{W{W{W{X|X|X|X}X}X}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y~Y~Y~Y~Y~Y~Z~Z~Z~Z~Z~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLqMqMqMqMq``gbagcagdbgebgfchfchgchgdhhdijfjlhlpjnumnxml|olqkwpyv|n}nNrNr琴琴琵琵琵ĳŴŴƵƵƵƵǵslslsmsmtmtnuovpwqys{u}wy{}~Ŀýξ̽˼ʻʺɹɹȸȸȸȸȸɹʹʺ˻̼νϿ¼|ǿļºӿӿҿҾҾҾѾVzVzVzV{V{W{W{W{W{W{W{W{W{W{Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y}Y~Y~Y~Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLq厳右MqMqMqMqMqMqMqMqa`gcagdbgebhfchgchhdhidhjeikgjnjmqmpzrr}rq~qnrlwowu|n~nNrNrNrNr琵瑵瑵瑵瑵ĴŴƵǵȶȶtltmtmtmtmtmtmununvowoxpyrzs|u}wxy{{ſƿƿſľý¼пνͼͼ̻̻˺˺˺˺˺̺̻ͼνϾѿ»z}ǿżúԿԿӿҿV{W{W{W{W{W{W{W{W{W|W|Y}Y}Y}Y}Y~Y~Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~ZZZ\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLq右右右右右右MqMqMqMqMqMqMqa`gdbgfchfchhdhhdhjehkfilgjpknups~vwwvuqsmvnuu|nNrNrNrNrNrNrNr瑵瑵瑵瑵盖ŵǶȶtmtmumumumumumumumvnvnvnwowoxpyqzr{s|t}v~wwxûüû»ºҿѿоϽϽμμμλλμμϼнѾҿºyz|Ⱦżú¹ѾW{W{W{W{W|W|W|X|Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~Z~ZZZZZ[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLpLpLpLpLpLpLqLqLqLqLqLqLqMq右右右右右右右右右MqMqMqMqMq[QIbagebhgchhdhidhjehkfimgjqkmwqs~wz~}{wuovm}rt|nNrNrNrNrNrNsNsNs瑵瑵葵葶葶qlsltmumumumvmvmvmvnvnvnvnwnwnwoxoxoypyqzq{r{s|t}t}u~uӿҿҾѾѽѽнннѽѽѾҾӿwxz|~ȾƼĺù¸¸W|W|X|X|X|Z~Z~Z~Z~Z~ZZZZ[[[[[[[[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLpLpLpLpLpLpLqLqLqLqLqLqLqLqMqMqMq右右右右右右右揳揳揳援MqMqMqMqMq]^gcahechgdhiehjeikfimgioikvoqyz{uvnzpt|nNrNrNrNsNsNsNsOsOsOs葶葶OsOsOsrltmumvmvmvnwnwnwnwnwnwnxnxnxoxoxoyoypzpzq{q{r|r|s|s}sԿԿԿԿӿӾӾӾӾӾӾӾӾԿԿvwxy{}~ʿȽƻźĹøø¸¸¸¸X|X|Z[[[[[[[[[[[[[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LpLpLpLqLqLqLqLqLqLqLqLqMqMqMqMqMq右右右右右揳揳揳援援援援援搴搴MqMqMrMr^_gdbhfchhdhjeilfimgiohjslm|uw|xpyot}o{nNsNsNsNsOsOsOsOsOsOsOsOsOsOsOsOtOtsmumvmvnwnwnxnxnxnxnxoxoyoyoyoyoyozpzpzp{q{q{q|r|r|r|rտտտտտտտտտտտտտtuvwxz{}~ɾȽƻźĹĸøøøøø¸X|X|[[[[[[[[[[\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\LqLqLqLqLqLqMqMqMqMqMqMqMqMq右右揳揳揳援援援援援搴搴搴搴搴搴搴搴MrMrNr_`gdbhgdhieikfimgiohjqjkxpq|}}vxn}r~q{nNsNsOsOsOsOsOsOsOsOs蒶蒶OsOtOtOtPtPttmvnwnwnxnxnxnyoyoyoyozozozozozpzp{p{p{p{q|q|q|q|q|r|rֿ~ttuvvwxz{|}~~˿ʾɽȼǻƺŹĹĸĸĸĸøø¸X}X}Y}Y}[\\\\\\\\\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMqMqMqMqMqMqMq揳揳揳援援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴NrNrNr``hechhdijeilfingipijtlm~uv~yp{or{nOsOsOsOsOsOsOsOs蒶蒶蒶蒶蒶OtPtPtPtPtPtPtunwnxnxnyoyoyozozozozo{o{p{p{p{p{p|p|p|q|q|q}q}q}q}r}rssttuvvwxyz{|}}}~}}}|{zȼȻǻƺƹŹŹŹŹĹĹĹùY}Y}Y}Y}Y}Y}Y}\\\\\\\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMqMqMqMq援援援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵NrNraahechheikfimgiohjrjkxop}|~vynr|oYTROsOsOsOsOsOs蒶蒶蒶钶钷钷钷铷PtPtPtPtPtPtPtvnxnxoyozozozo{o{p{p{p|p|p|p|p|p|q}q}q}q}q}q}q~q~r~rµ¶ssssttuuvvwxyyz{{{{{{{{zyxxǺǺƺƹƹƹŹŹŹŹĹY}Y}Y}Y}Y}Y}Y~Y~Y~Z~\\\\]]]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMqMqMqMq援援援搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琵琵琵琵琵瑵瑵瑵Nraahfciieilfingjpijtlm}tu~zp|pqznOsOsOsOsOs蒶蒶钶钷钷钷铷铷铷铷铷PtPtPtPtPuPuPuwnxoyozozo{p{p|p|p|p|p}p}q}q}q}q}q~q~q~q~q~r~rrrrµµ¶¶ssssstttuuvvwwxxyyzzzzyyyxxwwwǺǺƹƹƹƹƹŹĹY}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\MqMq搴搴搴搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵X\\gbahfdiieilgjohjqjkvno{{vzor|oOsOsOsOs钶钷钷钷铷铷铷铷铷铷铷铷铷ꓷPuPuPuQuQuQuQuxoyozo{p{p|p|p|p}p}q}q~q~q~q~q~q~qrrrrrrrrrösssssttttuuuvvvwwxxxxyyxxxxwwwwwvǺǺǺǺƺƺźY}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\搴搴搴搴搴搴搴搴搴搴搴搴琴琴琴琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵蝡bbigdijeimgjohjskl{rr~{q|p~qynOs钶钷钷钷铷铷铷铷铷铷铷铷铷ꓷꓸꓸꓸQuQuQuQuQuQuQuQuxozp{p{p|p}p}q}q~q~q~q~qqrrrrrrrrrssĶĶsssstttttuuuvvvwwwwxxxxxxxwwwwwwwwȺǺǺǺƺĺY}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\搴搴搴搴搴琴琴琴琵琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葶葶蠢cbigdijfjmgjpikvmnyyvzor|o钷钷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꔸꔸꔸꔸꔸQuQuQuQuQuQuQvQvypzp{p|q}q}q~q~q~qqrrrrrrrrsssŶŶŶŷŷttttttuuuuuvvvvwwwwwwwwwwwwwwwwwwwȺǺƺY}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[[\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\琴琴琴琵琵琵琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葶葶葶葶蒶蒶蒶蠢hdikfjnhjrjlyqr{q|p´Լ铷铷铷铷铷铷铷铷ꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸ딸QuQuQvQvQvRvRvRvzp{p|q}q~q~qqrrrrrrrssssŶŷŷƷƷƷƷƷtttuuuuuuvvvvvwwwwwwwwwwwwwwwwwwwwǻY~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\琵琵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒍lgjohktlnvwwվµʸ铷铷铷铷ꓷꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹땹땹QvRvRvRvRvRvRvRvzp|q}q~q~rrrrrrsssssŷƷƷƷƷƷǷǷǸǸǸuuuuuuuvvvvvwwwwwwwwwwwwwwwwxxxxxY}Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\\\\\\]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蚟lgjpikwoqԿõ־铷铷ꓷꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹땹땹땹땹땹땹RvRvRvRvRvRvRwRw|q|q~r~rrrrrssssƷƷƷƷǷǷǷǸǸȸȸȸȸȸuuuuvvvvvvwwwwwwwwwwxxxxxxxxxxY}Y}Y}Y}Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\瑵瑵瑵瑵瑵葵葵葵葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷霡rkmûԾµлꓸꓸꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹RvRvRvRvRwRwSwSwSwSw}r~rrrssssŷƷƷƷǷǷǸǸȸȸȸȸȸɹɹɹɹvvvvvvvwwwwwwwwxxxxxxxxxxxxxY}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]]^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\葵葵葶葶葶葶葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钶钷钷钷铷锜mhkunqӾöؿꔸꔸꔸꔸꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺얺얺RwRwRwSwSwSwSwSwSwSwSwrsssŷŷƷƷǷǸǸȸȸȸȸɸɹɹɹɹʹʹʹʹvvvvwwwwwwwwxxxxxxxxxxxxxY}Y}Y~Y~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]]^^^^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\葶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷闞edjifknilzsuԾöԽꔸꔸꔸꔸꔸ딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺SwSwSwSwSwSwSwSxSxTxTxTxķŷŷƷƷǸǸǸȸȸȸɸɹɹɹʹʹʹʹʺ˺˺vvwwwwwwwxxxxxxxxxxxyyyY}Y}Y~Y~Z~Z~[[[[[[[\\\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^^^_\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\蒶蒶蒶蒶蒶蒶蒶蒶蒶蒶钶钶钷钷钷钷铷铷铷铷铷铷铷铷铷鍙\\_iabjfdjjfkpkn~xzҽķꔸꔸ딸딸딹딹딹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺햺햻햻SwSwSwSwSxSxTxTxTxŷƷƸǸǸȸȸɹɹɹɹʹʹʹʺ˺˺˺˺˺̺wwwwwwxxxxxxxxxyyyyyY}Y~Y~Z~Z~Z~[[[[\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^^______\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\蒶蒶蒶钶钶钶钷钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷ꓷPtPYhW]i]`ibbjfekkgltnr{tӾĸµվ딹딹딹땹땹땹땹땹땹땹땹땹앹앺앺얺얺얺얺얺얺얺얺햺햻햻헻헻헻SwSxSxTxTxTxTxɸǸȸȹɹɹɹʹʹʺʺ˺˺˺˺̺̻̻̻̻wwxxxxxxxxyyyyyyY}Y}Y~Z~Z~Z~Z~\\\\\\\\\\\\\\\\]]]]]]]]^^^^^^^^__________`\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\钶钷钷钷钷铷铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸPtPtJVhRZhX]i]`jbcjgekmimwru~|wyp·ķ땹땹땹땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺얺햺햻햻헻헻헻헻헻헻헻TxTxTxTxɹɹʹʺʺ˺˺˺˺̺̻̻̻ͻͻͻͻxxxxxxyyyyyyY}Y}Y~Y~Z~Z~Z~Z~\\\\\\\\]]]]]]]]^^^^^^^^_________``````\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷铷铷铷铷铷铷铷铷铷铷铷ꓷꓷꓸꓸꓸꓸPtPtPtJVhMXhT[iY^i^ajccjgeknjo}uwzwxq{rvֿ땹땹땹땹땹땹앹앺앺앺얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻Tx̺˺˺̻̻̻̻ͻͻͻͼͼμμxxxyyyyY}Y}Y}Y}Y~Z~Z~Z~Z~Z~Z~]]]]]]]]^^^^^^^^________`````````aa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷铷铷铷铷铷铷ꓷꓷꓷꓸꓸꓸꓸꔸꔸPtPtPtPuJVhJVhOYiU\\iZ_j_ajcckhflpkputvqxpws}p땹땹땹앹앺앺앺얺얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻TxTx򕓒мѼѽѽѽX}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~]]]]^^^^^^^^________`````````aaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\铷ꓷꓷꓷꓸꓸꓸꓸꔸꔸꔸꔸPtPuPuPuPuPuJWhJWhJWhQZiV]i[_j`bkddkhglunpsqvpuv~qQv앹앺앺얺얺얺얺얺얺얺얺얺햺햻햻헻헻헻헻헻헻헻헻TxTxTyTyUyY}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z^^^^^^^^________````````aaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꓸꓸꓸꔸꔸꔸꔸꔸꔸꔸPuPuPuPuQuQuQuJWhJWhJWhJWhR[iW]j\\`jabkedknjmzpoto|ty~qRvRvRv얺얺얺얺얺얺얺햺햻햻햻헻헻헻헻헻헻헻TxTyTyUyUyUyUyY~Y~Z~Z~Z~Z~Z~Z~Z^^^^________````````aaaaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꔸꔸꔸꔸꔸꔸꔸPuPuQuQuQuQuQuQuJWhJWhJWhKWiKWiS\\iX^j]`kackgeltlnroyrzrIMSRvRvRv얺얺얺얺햺햻햻헻헻헻헻헻헻헻헻TxTyTyTyUyUyUyUyUyUyUyZ~Z~Z~Z~Z~Z________````````aaaaaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\ꔸꔸꔸꔸ딸QuQuQuQuQuQuQuQuQuKWiKWiKWiKWiKWiOZiT\\jY_j^akbcknimzonvp|sqRvRvRvRvRw햻햻햻헻헻헻헻헻헻헻헻TxTyTyUyUyUyUyUyUyUyUyUzUzVzZ~ZZ____````````aaaaaaaab\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\딹QuQuQuQuQuQuQuQuQuQuQuKWiKWiKWiKWiKWiMXiQ[jV]jZ_k_akbclumntp|trRvRvRwRwRwSwSw헻헻헻헻헻헻TyTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVz[````````aaaaaaabbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QuQuQuQuQuQuQuQuQuQuQuQvKWiKWiKXiKXiKXiKXiNYjS\\jW^k\\`k_bkqkm~ro{vRwRwRwRwSwSwSwSwSw헻헻헻TyTyUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVz[````aaaaaaabbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QuQuQuQuQuQuQvQvQvQvKXiKXiKXiKXiKXiKXiLXiPZjT]jY_k]akmim{pozuRwSwSwSwSwSwSwSwSwSwSwTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzV{V{W{W{[[[[aaaaaaabbbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\QvQvQvQvQvRvRvRvKXiKXiKXiKXiKXiKXiLXjMYjQ[jV]kZ`kigmwnn|sSwSwSwSwSwSwSwSwSwSxSxSxTxUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{[[[[\\\\\\aaabbbbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRvRvRvKXiKXiLXjLXjLXjLXjLXjOZjS\\kW^kigmtpsSwSwSwSwSwSwSwSwSxSxSxTxTxTxTxUyUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|[[[[\\\\\\\\\\\\bbbbbbbc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRvRvLXjLXjLXjLXjLXjMYjR[kW^k]alrosSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxUyUyUyUyUyUyUzUzUzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|[[[[\\\\\\\\\\\\\\]]bbbcc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RvRvRvRvRvRwRwLYjLYjLYjLYjT]kZ_lhfmuqSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|[[[\\\\\\\\\\\\\\]]]]]]cc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\RwRwRwRwSwSwSwddmaclupr{SwSwSwSwSwSxSxSxSxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}Y}Y}[[[\\\\\\\\\\\\\\]]]]]]]^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSwSwSwSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUzUzVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}[[[\\\\\\\\\\\\\\]]]]]]]^^^^^\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSwSwSwSwSwSxSxSxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyVzVzVzVzVzVzVzVzV{V{W{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}Y}Y}Y}Y}Y}Y}Y}Y~Y~[\\\\\\\\\\\\\\]]]]]]]^^^^^^^__\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SwSwSwSxSxSxSxTxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyVzVzVzVzVzV{V{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~[\\\\\\\\\\\\\\]]]]]]]^^^^^^^____\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\SxSxTxTxTxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyVzV{V{V{W{W{W{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~[\\\\\\\\\\\\\\]]]]]]]^^^^^^_______`\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTxTxTxTxTxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzW{W{W{W{W{W{W{W|W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[\\\\\\\\\\\\\\]]]]]]]^^^^^^^_______````\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTxTxTxTxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUzUzUzW{W{W{W{W{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Z~Z~Z~Z~Z~Z~Z~Z[[[[[[\\\\\\\\\\\\\\]]]]]]]^^^^^^^______```````a\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\TxTyTyTyUyUyUyUyUyUyUyUyUyUyUyUyUzUzVzVzW{W|W|X|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[\\\\\\\\\\\\\\\\]]]]]]]^^^^^^_______``````aaaaa\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUyUyUyUyUyUyUyUyUyUzUzUzVzVzVzX|X|X|X|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~Z[[[[[[[[\\\\\\\\]]]]]]]^^^^^^^_______``````aaaaaabb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUyUyUyUyUyUzUzUzVzVzVzVzX|X|X|X|X}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\]]]]]]]^^^^^^^______```````aaaaaabbbbb\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UyUyUzUzUzVzVzVzVzVzVzX}X}Y}Y}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\]]]]^^^^^^_______``````aaaaaaabbbbbbcc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\UzVzVzVzVzVzVzVzVzY}Y}Y}Y}Y}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\^^^^^^^_______``````aaaaaabbbbbbbccccc\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VzVzVzVzVzVzY}Y}Y~Y~Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\^^^^^______```````aaaaaabbbbbbcccccccd\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\VzVzVzV{Z~Z~Z~Z~Z~Z~Z~ZZ[[[[[[[[\\\\\\\\\\^_______``````aaaaaaabbbbbbccccccddddd\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\V{Z~Z~Z~Z~ZZ[[[[[[[[[\\\\\\\\\\_____``````aaaaaabbbbbbbccccccddddddee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\Z~ZZ[[[[[[[[\\\\\\\\\\\\_```````aaaaaabbbbbbcccccccddddddee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[[[[[[[\\\\\\\\\\\\\\`````aaaaaaabbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[[[[[\\\\\\\\\\\\\\\\``aaaaaaabbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\[\\\\\\\\\\\\\\\\]aaaaabbbbbbbccccccddddddeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\\\\\\\\\\]]aabbbbbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\\\\]]]bbbbbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]bbbccccccddddddeeeeee\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]ccccccddddddeeeeeef\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]]ccddddddeeeeeeff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\]]^^^^dddddeeeeeeff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^dddeeeeeefff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^^__eeeeeffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^^______eeffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^^________`ffff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\^^^^^________`````ff\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\\u0013\\"
  },
  {
    "path": "tests/testutils.GUIDE",
    "content": "================================================================================\n             TESTUTILS GUIDE FOR TEST AUTHORS AND MAINTAINERS\n\n                            Erik Leunissen\n================================================================================\n\n\nINTRODUCTION\n============\n\"testutils\" is a mechanism that manages utility procs that are used by multiple\ntest files:\n- it keeps them in a central place to prevent code duplication.\n- it provides these utility procs to test files, similar to what a Tcl package\n  (using a namespace) does: it exports the utilities, and the test files import\n  them.\nThe entire mechanism is implemented in a single file \"testutils.tcl\".\n\nSection A of this document explains the usage of the mechanism, targeted at\ntest authors. Section B provides a more detailed description of the innards and\nworkings of the testutils mechanism. This information is specifically targeted\nat developers carrying out maintenance of the testutils mechanism.\n\n\nA. USING UTILITY PROCS IN TESTS AND TEST FILES\n==============================================\nThis section explains to test authors how utility procs are organized, how to\nuse existing utility procs in a test file, and how to create new utility procs.\n\nA1. Organization of utility procs using namespaces\n--------------------------------------------------\nThe utility procs that testutils provides are grouped into functional areas.\nThese functional areas are also called \"domains\", or \"utility domains\". They\ncarry names such as \"dialog\",\"entry\", \"text\", which conform more or less to\nnames of test files in the Tk test suite.\n\nUtility procs are imported on demand by test files, using the command \"testutils\".\n(See the explanation of this command in the next section.) Utility procs for\nthe domain \"generic\" are an exception to this general rule: these procs are\nimported into the global namespace as a standard policy. They are readily\navailable to the test author, in each test file.\n\nEach domain has its own namespace below ::tk::test in which utility procs are\ndefined. For example: utilities that are specific for Tk dialogs are stored\ninside the namespace ::tk::test::dialog.\n\nA2. Using existing utility procs in test files\n----------------------------------------------\nThe command \"testutils\" is the interface to the testutils mechanism for the test\nauthor. The test author may use it to import utility procs into the namespace\nin which tests are executed (normally, this is the global namespace). The command\ntakes the following form:\n\n    testutils (import|forget) domain ?domain domain ...?\n\nThe command \"testutils import\" is typically invoked at the top of a test file.\nThe command \"testutils forget\" is typically invoked at the end of a test file.\nThese commands take care of the importing and cleaning up of utility procs\nfor a specific domain. They also take care of importing any namespace variables\nassociated with these procs so that they can be accessed from within a test.\n\nTypical invocations in a test file (using the domain \"dialog\" as an example), are:\n\n┃    testutils import dialog\n┃    ⋮\n┃    test foo-1.0 -body {\n┃        ⋮\n┃        ⋮\n┃        SendButtonPress; # invoke utility proc imported from domain \"dialog\"\n┃        ⋮\n┃        ⋮\n┃    } -result {foo_result}\n┃    ⋮\n┃    testutils forget dialog\n\nThe command \"testutils import\" fails if a proc or variable, unrelated to the\ntestutils mechanism, but having the same name as a utility proc or associated\nvariable, was already defined in the importing namespace. Therefore, test\nauthors need to take care that such procs and variables are cleaned up before\nthe end of a test file.\n\nA3. Adding new utility procs\n----------------------------\nTest authors may define new utility procs in the file \"testutils.tcl\". When doing\nso, there are several points to be aware of:\n\n1. Consider whether the new utility proc is used in multiple test files. If\n   it's not, it may as well be defined inside the specific test file that uses\n   it, because in that case the issue of code duplication doesn't exist.\n\n2. Add the proc definition to the proper domain namespace. If necessary, create\n   a new domain namespace.\n\n3. It may be the case that tests need to access (read/write) variables that are\n   associated with the new utility proc. The command \"testutils\" also handles\n   the importing and initialization of these associated variables, but attention\n   is needed for the following:\n\n   Their definition needs to be to placed in the reserved proc \"init\" (inside\n   the proper domain namespace). The command \"testutils import\" will import any\n   variables defined in this proc into the namespace where tests are executing.\n\n   Note that just placing associated namespace variables inside the \"namespace eval\"\n   scope for the specific domain, but outside the init proc, isn't good enough\n   because that foregoes the importing of the namespace variables as well as their\n   automatic initialization.\n\n   Also: any namespace variables initialized inside the \"namespace eval\" scope\n   for the specific domain, but outside the init proc, will NOT be cleaned up\n   upon the invocation of \"testutils forget\", in contrast to imported\n   namespace variables.\n\n4. If you created a new domain namespace in step 2, then export the test\n   utilities using the command \"testutils export\". This ensures that all utility\n   procs in the domain namespace are exported, except any init proc.\n\nThe file testutils.tcl contains various examples showing this practice.\n\n\nB. INNER WORKINGS OF THE TESTUTILS MECHANISM\n============================================\nThis section is targeted at developers carrying out maintenance of the testutils\nmechanism, whether debugging or improving it otherwise.\n\nB1. Files and file loading\n--------------------------\nThe entire testutils mechanism is implemented in a single file \"testutils.tcl\".\nThis file is sourced by the file \"main.tcl\", which in turn is sourced by\neach testfile.\n\nB2. Importing procs and associated namespace variables\n------------------------------------------------------\nThe command \"testutils\" makes utility procs available to the namespace in which\ntest files execute. The command employs a plain \"namespace export/namespace import\"\nfor importing procs; there is nothing special about that. However, special\nattention is needed for those utility procs that store state in a namespace\nvariable that is also accessed from the namespace in which tests are executing.\nSuch variables are made available to the namespace in which tests are executing\nusing an upvar statement. The process of importing these associated namespace\nvariables needs to handle some specifics:\n\nBesides making them available to test files, some tests require such variables\nto be initialized, regardless whatever the previous test file did to them.\nTherefore, the proc \"testutils\" needs to re-initialize these upvar'ed variables\nfor each test file that imports them. The steps in this auto-initialization\nprocess are as follows:\n\n- if a namespace for a specific functional area holds a proc \"init\", the\n  command \"testutils import xxx\" will invoke it, thus initializing namespace\n  variables. It subsequently imports the variables into the namespace where\n  tests are executing, using \"upvar\";\n- upon test file cleanup, \"testutils forget xxx\" removes the imported utility\n  procs and unsets the upvar'ed variables. (Note that this doesn't remove the\n  upvar link in the source namespace.) When a subsequent test file invokes\n  \"testutils import xxx\" again, the command will re-initialize the namespace\n  variables.\n\nA typical init proc (for a fictitious domain \"cuisine\") is:\n\n    proc init {} {\n\tvariable doneNess medium-rare\n\tvariable seasonings [list salt pepper]\n\tvariable tasteVerdict\n    }\n\nNote that the namespace variables \"doneNess\" and \"seasonings\" are initialized\nwith a value, while the namespace variable \"tasteVerdict\" is not. Both variants\nof declaring/defining a namespace variable are supported.\n\nB3. Tricky aspects of repeated initialization (in mode \"-singleproc 1\")\n-----------------------------------------------------------------------\nWhile the entire Tk test suite is running, many test files are loaded, each of\nwhich may import and subsequently forget utility domains. When tracking a single\nutility domain across test files that come and go, associated namespace variables\nmay be imported, initialized and cleaned up repeatedly. This repetitive cycle\npresents tricky aspects for the re-initialization of those namespace variables\nthat were declared using the \"variable\" command without supplying a value. This\nis caused by the fact that, once established, the upvar link for imported\nnamespace variables cannot be removed. The tricky details are explicitly\ndescribed by comments in the proc testutils.\n\nAnother tricky detail - that testutils currently evades - is the fact that\nunsetting an upvar'ed namespace variable changes its visibility for \"info vars\"\nin the utility namespace where the variable was defined, but not in the namespace\nwhere the upvar statement was invoked.\n\nB4. Test file\n-------------\nThe correct functioning of the testutils mechanism is tested by the test\nfile \"testutils.test\".\n"
  },
  {
    "path": "tests/testutils.tcl",
    "content": "# testutils.tcl --\n#\n# This file is sourced into each test file by \"main.tcl\". It implements the\n# testutils mechanism which is used to import utility procs into test files\n# that need them.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n#\n# DOCUMENTATION FOR TEST AUTHORS AND MAINTAINERS\n#\n# The testutils mechanism is documented in the separate file \"testutils.GUIDE\",\n# which is placed in the same directory as this file \"testutils.tcl\".\n#\n\nnamespace eval ::tk::test {\n    #\n    # The namespace ::tk::test itself doesn't contain any procs or variables.\n    # The contents of this namespace exist solely in child namespaces that\n    # are defined hereafter.\n    #\n    # Each child namespace represents a functional area, also called \"domain\".\n    #\n}\n\n\nnamespace eval ::tk::test::generic {\n\n    proc assert {expr} {\n\tif {! [uplevel 1 [list expr $expr]]} {\n\t    return -code error \"assertion failed: \\\"[uplevel 1 [list subst -nocommands $expr]]\\\"\"\n\t}\n    }\n\n    # controlPointerWarpTiming --\n    #\n    # This proc is intended to ensure that the (mouse) pointer has actually\n    # been moved to its new position after a Tk test issued:\n    #\n    #    [event generate $w $event -warp 1 ...]\n    #\n    # It takes care of the following timing details of pointer warping:\n    #\n    # a. Allow pointer warping to happen if it was scheduled for execution at\n    #    idle time. This happens synchronously if $w refers to the\n    #    whole screen or if the -when option to [event generate] is \"now\".\n    #\n    # b. Work around a race condition associated with OS notification of\n    #    mouse motion on Windows.\n    #\n    #    When calling [event generate $w $event -warp 1 ...], the following\n    #    sequence occurs:\n    #    - At some point in the processing of this command, either via a\n    #      synchronous execution path, or asynchronously at idle time, Tk calls\n    #      an OS function* to carry out the mouse cursor motion.\n    #    - Tk has previously registered a callback function** with the OS, for\n    #      the OS to call in order to notify Tk when a mouse move is completed.\n    #    - Tk doesn't wait for the callback function to receive the notification\n    #      from the OS, but continues processing. This suits most use cases\n    #      because usually the notification arrives fast enough (within a few tens\n    #      of microseconds). However ...\n    #    - A problem arises if Tk performs some processing, immediately following\n    #      up on [event generate $w $event -warp 1 ...], and that processing\n    #      relies on the mouse pointer having actually moved. If such processing\n    #      happens just before the notification from the OS has been received,\n    #      Tk will be using not yet updated info (e.g. mouse coordinates).\n    #\n    #         Hickup, choke etc ... !\n    #\n    #            *  the function SendInput() of the Win32 API\n    #            ** the callback function is TkWinChildProc()\n    #\n    #    This timing issue can be addressed by putting the Tk process on hold\n    #    (do nothing at all) for a somewhat extended amount of time, while\n    #    letting the OS complete its job in the meantime. This is what is\n    #    accomplished by calling [after ms].\n    #\n    #    ----\n    #    For the history of this issue please refer to Tk ticket [69b48f427e],\n    #    specifically the comment on 2019-10-27 14:24:26.\n    #\n    #\n    # Beware: there are cases, not (yet) exercised by the Tk test suite, where\n    # [controlPointerWarpTiming] doesn't ensure the new position of the pointer.\n    # For example, when issued under Tk8.7+, if the value for the -when option\n    # to [event generate $w] is not \"now\", and $w refers to a Tk window, i.e. not\n    # the whole screen.\n    #\n    proc controlPointerWarpTiming {{duration 50}} {\n\tupdate idletasks ;# see a. above\n\tif {[tk windowingsystem] eq \"win32\"} {\n\t    after $duration ;# see b. above\n\t}\n    }\n\n    proc deleteWindows {} {\n\tdestroy {*}[winfo children .]\n\t# This update is needed to avoid intermittent failures on macOS in unixEmbed.test\n\t# with the (GitHub Actions) CI runner.\n\t# Reason for the failures is unclear but could have to do with window ids being deleted\n\t# after the destroy command returns. The detailed mechanism of such delayed deletions\n\t# is not understood, but it appears that this update prevents the test failures.\n\tupdate\n    }\n\n    proc fixfocus {} {\n\tcatch {destroy .focus}\n\ttoplevel .focus\n\twm geometry .focus +0+0\n\tentry .focus.e\n\t.focus.e insert 0 \"fixfocus\"\n\tpack .focus.e\n\tupdate\n\tfocus -force .focus.e\n\tdestroy .focus\n    }\n\n    proc loadTkCommand {} {\n\tvariable TkLoadCmd\n\tif {! [info exists TkLoadCmd]} {\n\t    foreach pkg [info loaded] {\n\t\tif {[lindex $pkg 1] eq \"Tk\"} {\n\t\t    set TkLoadCmd [list load {*}$pkg]\n\t\t    break\n\t\t}\n\t    }\n\t}\n\treturn $TkLoadCmd\n    }\n\n    # Suspend script execution for a given amount of time, but continue\n    # processing events.\n    proc pause {ms} {\n\tvariable _pause\n\n\tset num [incr _pause(count)]\n\tset _pause($num) 1\n\n\tafter $ms [list unset [namespace current]::_pause($num)]\n\tvwait [namespace current]::_pause($num)\n    }\n\n    # resetWindows --\n    #\n    #\tRestores a proper initial window setup for a test file, cleaning up from\n    #\tthe state brought about by a previous test file.\n    #\n    proc resetWindows {} {\n\tdeleteWindows\n\n\t# Reset the geometry of the Tk root window:\n\t# - use 200x200 as a standard size\n\t# - use a fixed position on the screen where we expect no interference of\n\t#   areas with a special function provided by a desktop environment\n\t#   (dock, hotspots, ...), i.e. away from screen borders and corners.\n\t# - make it adapt its size to its children\n\twm deiconify .\n\t. configure -width 200 -height 200\n\twm geometry . {}\n\tupdate\n    }\n\n    # On macOS windows are not allowed to overlap the menubar at the top of the\n    # screen or the dock.  So tests which move a window and then check whether it\n    # got moved to the requested location should use a y coordinate larger than the\n    # height of the menubar (normally 23 pixels) and an x coordinate larger than the\n    # width of the dock, if it happens to be on the left.\n    # The C-level command \"testmenubarheight\" deals with this issue but it may\n    # not be available on each platform. Therefore, provide a fallback here.\n    if {[llength [info commands testmenubarheight]] == 0} {\n\tif {[tk windowingsystem] ne \"aqua\"} {\n\t    # Windows may overlap the menubar\n\t    proc testmenubarheight {} {\n\t\treturn 0\n\t    }\n\t} else {\n\t    # Windows may not overlap the menubar\n\t    proc testmenubarheight {} {\n\t\treturn 30 ;  # arbitrary value known to be larger than the menubar height\n\t    }\n\t}\n    }\n\n    # testutils --\n    #\n    #    Takes care of exporting/importing/forgetting utility procs and any\n    #    associated variables from a specific test domain (functional area).\n    #\n    #    More information is available in the file \"testutils.GUIDE\"\n    #\n    # Arguments:\n    #    subCmd : \"export\", \"import\" or \"forget\"\n    #    args   : a sequence of domains that need to be imported/forgotten,\n    #             unused for \"export\"\n    #\n    proc testutils {subCmd args} {\n\tvariable importedDomains\n\tvariable importVars\n\n\tif {$subCmd ni [list export import forget]} {\n\t    return -code error \"invalid subCmd \\\"$subCmd\\\". Usage: [lindex [info level 0] 0] export|import|forget ?domain domain ...?\"\n\t}\n\n\tset argc [llength $args]\n\tif {$subCmd eq \"export\"} {\n\t    if {$argc != 0} {\n\t\treturn -code error \"invalid #args. Usage: [lindex [info level 0] 0] export\"\n\t    }\n\n\t    # export all procs from the invoking domain namespace except \"init\"\n\t    uplevel 1 {\n\t\tif {[info procs init] eq \"init\"} {\n\t\t    set exports [info procs]\n\t\t    namespace export {*}[lremove $exports [lsearch $exports \"init\"]]\n\t\t    unset exports\n\t\t} else {\n\t\t    namespace export *\n\t\t}\n\t    }\n\t    return\n\t}\n\tif {$argc < 1} {\n\t    return -code error \"invalid #args. Usage: [lindex [info level 0] 0] import|forget domain ?domain ...?\"\n\t}\n\n\t# determine the requesting namespace\n\tset ns [uplevel 1 {namespace current}]\n\n\t# import/forget domains\n\tforeach domain $args {\n\t    if {! [namespace exists ::tk::test::$domain]} {\n\t\treturn -code error \"testutils domain \\\"$domain\\\" doesn't exist\"\n\t    }\n\n\t    switch -- $subCmd {\n\t\timport {\n\t\t    if {[info exists importedDomains($ns)] && ($domain in $importedDomains($ns))} {\n\t\t\treturn -code error \"testutils domain \\\"$domain\\\" was already imported\"\n\t\t    } else {\n\n\t\t\t# import procs\n\t\t\tif {[catch {\n\t\t\t    uplevel 1 [list namespace import ::tk::test::${domain}::*]\n\t\t\t} errMsg]} {\n\t\t\t    # revert import of procs already done\n\t\t\t    uplevel 1 [list namespace forget ::tk::test::${domain}::*]\n\t\t\t    return -code error \"import from testutils domain \\\"$domain\\\" failed: $errMsg\"\n\t\t\t}\n\n\t\t\t# import associated namespace variables declared in the init proc\n\t\t\tif {\"init\" in [namespace inscope ::tk::test::$domain {info procs init}]} {\n\t\t\t    if {[info exists importVars($ns,$domain)]} {\n\t\t\t\t#\n\t\t\t\t# Note [A1]:\n\t\t\t\t# If test files inadvertently leave behind a variable with the same name\n\t\t\t\t# as an upvar'ed namespace variable, its last value will serve as a new\n\t\t\t\t# initial value in case that the init proc declares that variable without\n\t\t\t\t# a value. Also, the result of \"info exists varName\" would be different\n\t\t\t\t# between test files.\n\t\t\t\t#\n\t\t\t\t# The next unset prevents such artefacts. See also note [A2] below.\n\t\t\t\t#\n\t\t\t\tuplevel 1 [list unset -nocomplain {*}$importVars($ns,$domain)]\n\t\t\t    }\n\t\t\t    ::tk::test::${domain}::init\n\t\t\t    if {($ns ne \"::\") || (! [info exists importVars($ns,$domain)])} {\n\t\t\t\t#\n\t\t\t\t# Importing associated namespace variables into the global namespace where\n\t\t\t\t# tests are normally executing, needs to be done only once because an upvar\n\t\t\t\t# link cannot be removed from a namespace. For other requesting namespaces\n\t\t\t\t# we need to reckon with deletion and re-creation of the namespace in the\n\t\t\t\t# meantime.\n\t\t\t\t#\n\t\t\t\tif {[info exists importVars($ns,$domain)]} {\n\t\t\t\t    set associatedVars $importVars($ns,$domain)\n\t\t\t\t} else {\n\t\t\t\t    set associatedVars [namespace inscope ::tk::test::$domain {info vars}]\n\t\t\t\t}\n\t\t\t\tforeach varName $associatedVars {\n\t\t\t\t    if {[catch {\n\t\t\t\t\tuplevel 1 [list upvar #0 ::tk::test::${domain}::$varName $varName]\n\t\t\t\t    } errMsg]} {\n\t\t\t\t\t# revert imported procs and partial variable import\n\t\t\t\t\tuplevel 1 [list unset -nocomplain {*}$associatedVars]\n\t\t\t\t\tuplevel 1 [list namespace forget ::tk::test::${domain}::*]\n\t\t\t\t\treturn -code error \"import from testutils domain \\\"$domain\\\" failed: $errMsg\"\n\t\t\t\t    }\n\t\t\t\t}\n\t\t\t\tset importVars($ns,$domain) $associatedVars\n\t\t\t    }\n\t\t\t}\n\n\t\t\t# register domain as imported\n\t\t\tlappend importedDomains($ns) $domain\n\t\t    }\n\t\t}\n\t\tforget {\n\t\t    if {(! [info exists importedDomains($ns)]) || ($domain ni $importedDomains($ns))} {\n\t\t\treturn -code error \"testutils domain \\\"$domain\\\" was not imported\"\n\t\t    }\n\n\t\t    # remove imported utility procs from the namespace where tests are executing\n\t\t    uplevel 1 [list namespace forget ::tk::test::${domain}::*]\n\n\t\t    #\n\t\t    # Some namespace variables are meant to persist across test files\n\t\t    # in the entire Tk test suite (notably the variable ImageNames,\n\t\t    # domain \"image\"). These variables are also not meant to be accessed\n\t\t    # from, and imported into the namespace where tests are executing,\n\t\t    # and they should not be cleaned up here.\n\t\t    #\n\n\t\t    if {[info exists importVars($ns,$domain)]} {\n\t\t\t#\n\t\t\t# Remove imported namespace variables.\n\t\t\t#\n\t\t\t# Note [A2]:\n\t\t\t# The upvar link in the namespace where tests are executing cannot be removed.\n\t\t\t# Without specific attention, this can cause surprising behaviour upon\n\t\t\t# re-initialization. See also note [A1] above.\n\t\t\t#\n\t\t\tuplevel 1 [list unset -nocomplain {*}$importVars($ns,$domain)]\n\t\t    }\n\t\t    set importedDomains($ns) [lremove $importedDomains($ns) [lsearch $importedDomains($ns) $domain]]\n\t\t}\n\t    }\n\t}\n    }\n\n    testutils export\n}\n\n# Import generic utility procs into the global namespace (in which tests are\n# normally executing) as a standard policy.\n::tk::test::generic::testutils import generic\n\nnamespace eval ::tk::test::button {\n    proc bogusTrace args {\n\terror \"trace aborted\"\n    }\n    testutils export\n}\n\nnamespace eval ::tk::test::child {\n\n    # childTkInterp --\n    #\n    #\tCreate a new Tk application in a child interpreter, with\n    #\ta given name and class.\n    #\n    proc childTkInterp {name args} {\n\tset index [lsearch $args \"-safe\"]\n\tif {$index >= 0} {\n\t    set safe 1\n\t    set options [lremove $args $index]\n\t} else {\n\t    set safe 0\n\t    set options $args\n\t}\n\tif {[llength $options] ni {0 2}} {\n\t    return -code error \"invalid #args\"\n\t}\n\n\tset cmdArgs [list -name $name]\n\tforeach {key value} $options {\n\t    if {$key ne \"-class\"} {\n\t\treturn -code error \"invalid option \\\"$key\\\"\"\n\t    }\n\t    lappend cmdArgs $key $value\n\t}\n\n\tif {$safe} {\n\t    interp create -safe $name\n\t} else {\n\t    interp create $name\n\t}\n\n\t$name eval [list set argv $cmdArgs]\n\tcatch {eval [loadTkCommand] $name}\n    }\n\n    # childTkProcess --\n    #\n    #\tCreate a new Tk application in a child process, and enable it to\n    #\tevaluate scripts on our behalf.\n    #\n    #\tSuggestion: replace with child interp or thread ?\n    #\n    proc childTkProcess {subcmd args} {\n\tvariable fd\n\tvariable interpCount\n\tswitch -- $subcmd {\n\t    create {\n\t\tif {[info exists fd] && [string length $fd]} {\n\t\t    childTkProcess exit\n\t\t}\n\t\t# Beware of bug #280189e35d. We prevent that bug by not relying\n\t\t# on the automatic detection of duplicate interp names, as\n\t\t# advertised by the manual page for \"tk appname\". Instead, we\n\t\t# pass a unique appname to the executable that is being invoked\n\t\t# below.\n\t\tif {! [info exists interpCount]} {\n\t\t    set interpCount 1\n\t\t}\n\t\tset fd [open \"|[list [::tcltest::interpreter] \\\n\t\t\t-geometry +100+100 -name tktest[incr interpCount]] $args\" r+]\n\t\tputs $fd \"puts foo; flush stdout\"\n\t\tflush $fd\n\t\tif {[gets $fd data] < 0} {\n\t\t    error \"unexpected EOF from \\\"[::tcltest::interpreter]\\\"\"\n\t\t}\n\t\tif {$data ne \"foo\"} {\n\t\t    error \"unexpected output from\\\n\t\t\t    background process: \\\"$data\\\"\"\n\t\t}\n\t\tputs $fd [loadTkCommand]\n\t\tflush $fd\n\t\tfileevent $fd readable [namespace code {childTkProcess read}]\n\t    }\n\t    eval {\n\t\tvariable Data\n\t\tvariable Done\n\n\t\tset script [lindex $args 0]\n\t\tset block 0\n\t\tif {[llength $args] == 2} {\n\t\t    set block [lindex $args 1]\n\t\t}\n\n\t\tif {$block} {\n\t\t    fileevent $fd readable {}\n\t\t}\n\t\tputs $fd \"[list catch $script msg]; update; puts \\$msg;\\\n\t\t\tputs **DONE**; flush stdout\"\n\t\tflush $fd\n\t\tset Data {}\n\t\tif {$block} {\n\t\t    while {![eof $fd]} {\n\t\t\tset line [gets $fd]\n\t\t\tif {$line eq \"**DONE**\"} {\n\t\t\t    break\n\t\t\t}\n\t\t\tappend Data $line\n\t\t    }\n\t\t} else {\n\t\t    set Done 0\n\t\t    vwait [namespace which -variable Done]\n\t\t}\n\t\treturn $Data\n\t    }\n\t    exit {\n\t\t# catch in case the child process has closed $fd\n\t\tcatch {puts $fd exit}\n\t\tcatch {close $fd}\n\t\tset fd \"\"\n\t    }\n\t    read {\n\t\tvariable Data\n\t\tvariable Done\n\t\tset x [gets $fd]\n\t\tif {[eof $fd]} {\n\t\t    fileevent $fd readable {}\n\t\t    set Done 1\n\t\t} elseif {$x eq \"**DONE**\"} {\n\t\t    set Done 1\n\t\t} else {\n\t\t    append Data $x\n\t\t}\n\t    }\n\t}\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::colors {\n    # colorsFree --\n    #\n    # Returns 1 if there appear to be free colormap entries in a window, 0\n    # otherwise.\n    #\n    # Arguments:\n    #\tw                : name of window in which to check.\n    #\tred, green, blue : intensities to use in a trial color allocation\n    #\t                   to see if there are colormap entries free.\n    #\n    proc colorsFree {w {red 31} {green 245} {blue 192}} {\n\tlassign [winfo rgb $w [format \"#%02x%02x%02x\" $red $green $blue]] r g b\n\texpr {($r/256 == $red) && ($g/256 == $green) && ($b/256 == $blue)}\n    }\n\n    # eatColors --\n    #\n    # Creates a toplevel window and allocates enough colors in it to use up all\n    # the slots in an 8-bit colormap.\n    #\n    # Arguments:\n    #\tw : name of toplevel window to create.\n    #\n    proc eatColors {w} {\n\tcatch {destroy $w}\n\ttoplevel $w\n\twm geom $w +0+0\n\tcanvas $w.c -width 400 -height 200 -bd 0\n\tpack $w.c\n\tfor {set y 0} {$y < 8} {incr y} {\n\t    for {set x 0} {$x < 40} {incr x} {\n\t\tset color [format #%02x%02x%02x [expr {$x*6}] [expr {$y*30}] 0]\n\t\t$w.c create rectangle [expr {10*$x}] [expr {20*$y}] \\\n\t\t    [expr {10*$x + 10}] [expr {20*$y + 20}] -outline {} \\\n\t\t    -fill $color\n\t    }\n\t}\n\tupdate\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::dialog {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable dialogType [file rootname [file tail [info script]]]\n\tvariable dialogIsNative [isNative $dialogType]\n\tvariable testDialog\n\tvariable testDialogFont\n    }\n\n    proc Click {button} {\n\tvariable dialogType\n\tvariable testDialog\n\n\tswitch -- $dialogType {\n\t    \"fontchooser\" {\n\t\tif {$button ni \"ok cancel apply\"} {\n\t\t    return -code error \"invalid button name \\\"$button\\\"\"\n\t\t}\n\t\t$testDialog.$button invoke\n\t    }\n\t    \"winDialog\" {\n\t\tswitch -exact -- $button {\n\t\t    ok     { set button 1 }\n\t\t    cancel { set button 2 }\n\t\t}\n\t\ttestwinevent $testDialog $button WM_LBUTTONDOWN 1 0x000a000b\n\t\ttestwinevent $testDialog $button WM_LBUTTONUP 0 0x000a000b\n\t    }\n\t    default {\n\t\treturn -code error \"invalid dialog type \\\"$dialogType\\\"\"\n\t    }\n\t}\n    }\n\n    proc isNative {type} {\n\tswitch -- $type {\n\t    \"choosedir\" {\n\t\tset cmd ::tk_chooseDirectory\n\t    }\n\t    \"clrpick\" {\n\t\tset cmd ::tk_chooseColor\n\t    }\n\t    \"filebox\" {\n\t\tset cmd ::tk_getOpenFile\n\t    }\n\t    \"msgbox\" {\n\t\tset cmd ::tk_messageBox\n\t    }\n\t    \"dialog\" -\n\t    \"fontchooser\" -\n\t    \"winDialog\" {\n\t\treturn \"N/A\"\n\t    }\n\t    default {\n\t\treturn -code error \"invalid dialog type \\\"$type\\\"\"\n\t    }\n\t}\n\treturn [expr {[info procs $cmd] eq \"\"}]\n    }\n\n    proc PressButton {btn} {\n\tevent generate $btn <Enter>\n\tevent generate $btn <Button-1> -x 5 -y 5\n\tevent generate $btn <ButtonRelease-1> -x 5 -y 5\n    }\n\n    proc SendButtonPress {parent btn buttonType} {\n\tvariable dialogType\n\tswitch -- $dialogType {\n\t    \"choosedir\" {\n\t\tif {$parent eq \".\"} {\n\t\t    set w .__tk_choosedir\n\t\t} else {\n\t\t    set w $parent.__tk_choosedir\n\t\t}\n\t\tupvar ::tk::dialog::file::__tk_choosedir data\n\t    }\n\t    \"clrpick\" {\n\t\tset w .__tk__color\n\t\tupvar ::tk::dialog::color::[winfo name $w] data\n\t    }\n\t    \"filebox\" {\n\t\tif {$parent eq \".\"} {\n\t\t    set w .__tk_filedialog\n\t\t} else {\n\t\t    set w $parent.__tk_filedialog\n\t\t}\n\t\tupvar ::tk::dialog::file::__tk_filedialog data\n\t    }\n\t    \"msgbox\" {\n\t\tif {$parent eq \".\"} {\n\t\t    set w .__tk__messagebox\n\t\t} else {\n\t\t    set w $parent.__tk__messagebox\n\t\t}\n\t    }\n\t    default {\n\t\treturn -code error \"invalid dialog type \\\"$dialogType\\\"\"\n\t    }\n\t}\n\n\tif {$dialogType eq \"msgbox\"} {\n\t    set button $w.$btn\n\t} else {\n\t    set button $data($btn\\Btn)\n\t}\n\tif {! [winfo ismapped $button]} {\n\t    update\n\t}\n\n\tif {$buttonType eq \"mouse\"} {\n\t    PressButton $button\n\t} else {\n\t    event generate $w <Enter>\n\t    focus $w\n\t    event generate $button <Enter>\n\t    event generate $w <Key> -keysym Return\n\t}\n    }\n\n    proc testDialog {stage {script \"\"}} {\n\tvariable testDialogCmd\n\tvariable testDialogResult\n\tvariable testDialogFont\n\tvariable iter_after\n\tvariable testDialog; # On MS Windows, this variable is set at the C level\n\t\t\t     # by SetTestDialog() in tkWinDialog.c\n\n\tswitch -- $stage {\n\t    launch {\n\t\tset iter_after 0\n\t\tset testDialog {}\n\t\tif {$::tcl_platform(platform) eq \"windows\"} {\n\t\t    variable testDialogClass \"#32770\"\n\t\t}\n\n\t\tafter 1 $script\n\t    }\n\t    onDisplay {\n\t\tset testDialogCmd $script\n\t\tset testDialogResult {}\n\t\tset testDialogFont {}\n\n\t\tif {$::tcl_platform(platform) eq \"windows\"} {\n\t\t    # Do not make the delay too short. The newer Vista dialogs take\n\t\t    # time to come up.\n\t\t    after 500 [list [namespace current]::testDialog onDisplay2]\n\t\t} else {\n\t\t    testDialog onDisplay2\n\t\t}\n\t\tvwait ::tk::test::dialog::testDialogResult\n\t\treturn $testDialogResult\n\t    }\n\t    onDisplay2 {\n\t\tset doRepeat 0\n\n\t\tif {$::tcl_platform(platform) eq \"windows\"} {\n\t\t    # On Vista and later, using the new file dialogs we have to\n\t\t    # find the window using its title as testDialog will not be\n\t\t    # set at the C level.\n\t\t    variable testDialogClass\n\t\t    if {[catch {testfindwindow \"\" $testDialogClass} testDialog]} {\n\t\t\tset doRepeat 1\n\t\t    }\n\t\t} elseif {$testDialog eq \"\"} {\n\t\t    set doRepeat 1\n\t\t}\n\n\t\tif {$doRepeat} {\n\t\t    if {[incr iter_after] > 30} {\n\t\t\tset testDialogResult \">30 iterations waiting for testDialog\"\n\t\t\treturn\n\t\t    }\n\t\t    after 150 [list ::tk::test::dialog::testDialog onDisplay2]\n\t\t    return\n\t\t}\n\t\tset testDialogResult [uplevel #0 $testDialogCmd]\n\t    }\n\t    default {\n\t\treturn -code error \"invalid parameter \\\"$stage\\\"\"\n\t    }\n\t}\n    }\n\n    proc ToPressButton {parent btn} {\n\tvariable dialogIsNative\n\tif {! $dialogIsNative} {\n\t    after 100 SendButtonPress $parent $btn mouse\n\t}\n    }\n\n    testutils export\n}\n\n\nnamespace eval ::tk::test::entry {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable textVar\n\tvariable validationData\n    }\n\n    # Handler for variable trace on namespace variable textVar\n    proc override args {\n\tvariable textVar 12345\n    }\n\n    # Procedures used by widget validation tests\n    proc validateCommand1 {W d i P s S v V} {\n\tvariable validationData [list $W $d $i $P $s $S $v $V]\n\treturn 1\n    }\n    proc validateCommand2 {W d i P s S v V} {\n\tvariable validationData [list $W $d $i $P $s $S $v $V]\n\tvariable textVar mydata\n\treturn 1\n    }\n    proc validateCommand3 {W d i P s S v V} {\n\tvariable validationData [list $W $d $i $P $s $S $v $V]\n\treturn 0\n    }\n    proc validateCommand4 {W d i P s S v V} {\n\tvariable validationData [list $W $d $i $P $s $S $v $V]\n\t.e delete 0 end;\n\t.e insert end dovaldata\n\treturn 0\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::geometry {\n    proc getsize {w} {\n\tupdate\n\treturn \"[winfo reqwidth $w] [winfo reqheight $w]\"\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::image {\n\n    proc imageCleanup {} {\n\tvariable ImageNames\n\tforeach img [image names] {\n\t    if {$img ni $ImageNames} {image delete $img}\n\t}\n    }\n\n    proc imageFinish {} {\n\tvariable ImageNames\n\tset imgs [lsearch -all -inline -glob -not [lsort [image names]] ::tk::icons::indicator*]\n\tif {$imgs ne $ImageNames} {\n\t    return -code error \"images remaining: [image names] != $ImageNames\"\n\t}\n\timageCleanup\n    }\n\n    proc imageInit {} {\n\tvariable ImageNames\n\tif {![info exists ImageNames]} {\n\t    set ImageNames [lsearch -all -inline -glob -not [lsort [image names]] ::tk::icons::indicator*]\n\t}\n\timageCleanup\n\tif {[lsort [image names]] ne $ImageNames} {\n\t    return -code error \"IMAGE NAMES mismatch: [image names] != $ImageNames\"\n\t}\n    }\n\n    proc imageNames {} {\n\tvariable ImageNames\n\tset r {}\n\tforeach img [image names] {\n\t    if {$img ni $ImageNames} {lappend r $img}\n\t}\n\treturn $r\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::scroll {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable scrollInfo {}\n    }\n\n    # Used as the scrolling command for widgets, set with \"-[xy]scrollcommand\".\n    # It saves the scrolling information in a namespace variable \"scrollInfo\".\n    proc setScrollInfo {args} {\n\tvariable scrollInfo $args\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::select {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable selValue {} selInfo {}\n\tvariable abortCount\n\tvariable pass\n    }\n\n    proc badHandler {path type offset count} {\n\tvariable selInfo\n\tvariable selValue\n\tselection handle -type $type $path {}\n\tlappend selInfo $path $type $offset $count\n\tset numBytes [expr {[string length $selValue] - $offset}]\n\tif {$numBytes <= 0} {\n\t    return \"\"\n\t}\n\tstring range $selValue $offset [expr {$numBytes+$offset}]\n    }\n\n    proc badHandler2 {path type offset count} {\n\tvariable abortCount\n\tvariable selInfo\n\tvariable selValue\n\tincr abortCount -1\n\tif {$abortCount == 0} {\n\t    selection handle -type $type $path {}\n\t}\n\tlappend selInfo $path $type $offset $count\n\tset numBytes [expr {[string length $selValue] - $offset}]\n\tif {$numBytes <= 0} {\n\t    return \"\"\n\t}\n\tstring range $selValue $offset [expr {$numBytes+$offset}]\n    }\n\n    proc errHandler args {\n\terror \"selection handler aborted\"\n    }\n\n    proc errIncrHandler {type offset count} {\n\tvariable selInfo\n\tvariable selValue\n\tvariable pass\n\tif {$offset == 4000} {\n\t    if {$pass == 0} {\n\t\t# Just sizing the selection;  don't do anything here.\n\t\tset pass 1\n\t    } else {\n\t\t# Fetching the selection;  wait long enough to cause a timeout.\n\t\tafter 6000\n\t    }\n\t}\n\tlappend selInfo $type $offset $count\n\tset numBytes [expr {[string length $selValue] - $offset}]\n\tif {$numBytes <= 0} {\n\t    return \"\"\n\t}\n\tstring range $selValue $offset [expr {$numBytes+$offset}]\n    }\n\n    proc handler {type offset count} {\n\tvariable selInfo\n\tvariable selValue\n\tlappend selInfo $type $offset $count\n\tset numBytes [expr {[string length $selValue] - $offset}]\n\tif {$numBytes <= 0} {\n\t    return \"\"\n\t}\n\tstring range $selValue $offset [expr {$numBytes+$offset}]\n    }\n\n    proc reallyBadHandler {path type offset count} {\n\tvariable selInfo\n\tvariable selValue\n\tvariable pass\n\tif {$offset == 4000} {\n\t    if {$pass == 0} {\n\t\tset pass 1\n\t    } else {\n\t\tselection handle -type $type $path {}\n\t    }\n\t}\n\tlappend selInfo $path $type $offset $count\n\tset numBytes [expr {[string length $selValue] - $offset}]\n\tif {$numBytes <= 0} {\n\t    return \"\"\n\t}\n\tstring range $selValue $offset [expr {$numBytes+$offset}]\n    }\n\n    proc selectionSetup {{path .f1} {display {}}} {\n\tcatch {destroy $path}\n\tif {$display eq \"\"} {\n\t    frame $path\n\t} else {\n\t    toplevel $path -screen $display\n\t    wm geom $path +0+0\n\t}\n\tselection own $path\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::text {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable fixedFont {Courier -12}\n\tvariable fixedWidth [font measure $fixedFont m]\n\tvariable fixedHeight [font metrics $fixedFont -linespace]\n\tvariable fixedAscent [font metrics $fixedFont -ascent]\n    }\n\n    # full border size of the text widget, i.e. first x or y coordinate inside the text widget\n    # warning:  -padx  is supposed to be the same as  -pady  (same border size horizontally and\n    # vertically around the widget)\n    proc bo {{w .t}} {\n\treturn [expr {[$w cget -borderwidth] + [$w cget -highlightthickness] + [$w cget -padx]}]\n    }\n\n    # x-coordinate of the first pixel of $n-th char (count starts at zero), left justified\n    proc xchar {n {w .t}} {\n\treturn [expr {[bo $w] + [xw $n]}]\n    }\n\n    # x-width of $n chars, fixed width font\n    proc xw {n} {\n\tvariable fixedWidth\n\treturn [expr {$n * $fixedWidth}]\n    }\n\n    # y-coordinate of the first pixel of $l-th display line (count starts at 1)\n    proc yline {l {w .t}} {\n\tvariable fixedHeight\n\treturn [expr {[bo $w] + ($l - 1) * $fixedHeight}]\n    }\n\n    testutils export\n}\n\nnamespace eval ::tk::test::timing {\n\n    # init --\n    #\n    # This is a reserved proc that is part of the mechanism that the proc\n    # testutils employs when making utility procs and associated namespace\n    # variables available to test files.\n    #\n    # Test authors should define and initialize namespace variables here if\n    # they need to be imported into the namespace in which tests are executing.\n    # This proc must not be exported.\n    #\n    # For more information, see the documentation in the file \"testutils.GUIDE\"\n    #\n    proc init {} {\n\tvariable dt\n\tset dt(granularity) milliseconds\n\tset dt(t0) [clock milliseconds]\n    }\n\n    proc dt.get {} {\n\tvariable dt\n\tset now [clock $dt(granularity)]\n\tset result [expr {$now - $dt(t0)}]\n\tset dt(t0) $now\n\treturn $result\n    }\n\n    proc dt.reset {{granularity milliseconds}} {\n\tif {$granularity ni \"microseconds milliseconds seconds\"} {\n\t    return -code error \"invalid parameter \\\"$granularity\\\", expected \\\"microseconds\\\", \\\"milliseconds\\\" or \\\"seconds\\\"\"\n\t}\n\tvariable dt\n\tset dt(granularity) $granularity\n\tset dt(t0) [clock $dt(granularity)]\n    }\n\n    # progress.* --\n    #\n    #\tThis set of procs monitors progress and total duration of a procedure\n    #\tin a loop.\n    #\n    #\tDerived from tests/ttk/ttk.test, see:\n    #\n    #\thttps://core.tcl-lang.org/tk/file?ci=f94f84b254b0c5ad&name=tests/ttk/ttk.test&ln=335-340\n    #\n    proc progress.init {{granularity milliseconds}} {\n\tdt.reset $granularity\n    }\n\n    proc progress.update {} {\n\tputs -nonewline stderr \".\" ; flush stderr\n    }\n\n    proc progress.end {} {\n\tputs stderr \" [dt.get] $::tk::test::timing::dt(granularity)\"\n    }\n\n    testutils export\n}\n\n# EOF\n"
  },
  {
    "path": "tests/testutils.test",
    "content": "# Tests for the \"testutils\" command, defined in testutils.tcl\n#\n# © 2025 Erik Leunissen\n#\n# See the file \"license.terms\" for information on usage and redistribution of\n# this file, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n\n# NOTE\n#\n# All tests in this test file have been constrained with test constraint \"testutils\".\n# This constraint isn't set anywhere, and therefore false by default. Therefore,\n# the tests in this file are skipped in a regular invocation of the Tk test suite.\n# In order to run these test, you need to use the tcltest option\n# \"-constraints testutils\" in the invocation, possibly combined with the option\n# \"-file testutils.test\" to exclude other test files, or with\n# \"-limitconstraints true\" to exclude other tests.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\nassert {\"testutils\" in [info procs testutils]}\n\n#\n# TESTS\n#\n\n#\n# Testutils domain \"generic\"\n#\n\ntest resetWindows-4b705991cf {Reset of root window geometry is effective. Bug #4b705991cf} -constraints testutils -setup {\n    unset -nocomplain result\n    # Beware that some windowing systems / window managers impose a minimum\n    # width or height on toplevels. The following windowing systems/window managers\n    # have been investigated for imposing such a minimum size:\n    # x11: no wm (i.e. the bare display server), e16, Fluxbox, Fvwm, Icewm,\n    #      KDE/Plasma, Metacity, Openbox, TWM, WindowMaker, Xvwm\n    # win32 and macOS/aqua. Those exhibiting such a minimum size are:\n    #\n    # ws-wm\t\twidth\theight\n    # ----------------------------------\n    # win32\t\t116\t1\n    # x11-KDE/Plasma\t8\t33\n    # x11-WindowMaker\t5\t5\n    # ----------------------------------\n    #\n    # Therefore, don't use a width less than 116, or a height less than 33 for\n    # this test.\n    #\n} -body {\n    . configure -width 151 -height 94\n    wm geometry . +123+123\n    resetWindows\n    lappend result [wm geometry .]\n    pack [frame .f -width 137 -height 109 -bg blue]\n    update\n    lappend result [winfo width .] [winfo height .]\n} -cleanup {\n    unset -nocomplain result\n    destroy .f\n    resetWindows\n} -result {200x200+100+100 137 109}\n\n#\n# testutils command section 1: invalid invocations\n#\ntest testutils-1.1 {invalid subcommand} -constraints testutils -body {\n    testutils foo\n} -result {invalid subCmd \"foo\". Usage: testutils export|import|forget ?domain domain ...?} -returnCodes error\n\ntest testutils-1.2 {invalid #args for subCmd export} -constraints testutils -body {\n    testutils export foo\n} -result {invalid #args. Usage: testutils export} -returnCodes error\n\ntest testutils-1.3 {invalid #args for subCmd import} -constraints testutils -body {\n    testutils import\n} -result {invalid #args. Usage: testutils import|forget domain ?domain ...?} -returnCodes error\n\ntest testutils-1.4 {invalid #args for subCmd forget} -constraints testutils -body {\n    testutils forget\n} -result {invalid #args. Usage: testutils import|forget domain ?domain ...?} -returnCodes error\n\ntest testutils-1.5 {invalid domain for subCmd import} -constraints testutils -body {\n    testutils import foo\n} -result {testutils domain \"foo\" doesn't exist} -returnCodes error\n\ntest testutils-1.6 {invalid domain for subCmd forget} -constraints testutils -body {\n    testutils forget foo\n} -result {testutils domain \"foo\" doesn't exist} -returnCodes error\n\n#\n# COMMON TEST SETUP\n#\n\n# Create a domain namespace for testing export, import, forget\nassert {\"::tk::test::foo\" ni [namespace children ::tk::test]}\nassert {\"::tk::test::zez\" ni [namespace children ::tk::test]}\ncatch {rename init {}}\ncatch {rename kuk {}}\nunset -nocomplain bar pip\nnamespace eval ::tk::test::foo {\n    proc init {} {\n\tvariable bar 123\n\tvariable pip\n    }\n    proc kuk {} {}\n    testutils export\n}\nset initVars [info vars]; lappend initVars initVars\n\n#\n# testutils command section 2: Domain failures for forget and import\n#\ntest testutils-2.1 {forget not-imported domain} -constraints testutils -body {\n    testutils forget foo\n} -result {testutils domain \"foo\" was not imported} -returnCodes error\n\ntest testutils-2.2 {duplicate import} -constraints testutils -body {\n    testutils import foo\n    testutils import foo\n} -result {testutils domain \"foo\" was already imported} -returnCodes error -cleanup {\n    testutils forget foo\n}\n\n#\n# testutils command section 3. Import procs\n#\ntest testutils-3.1 {utility proc is imported and init proc is not} -constraints testutils -body {\n    testutils import foo\n    expr {([info procs kuk] eq \"kuk\") && ([info procs init] eq \"\")}\n} -result 1 -cleanup {\n    testutils forget foo\n}\n\ntest testutils-3.2 {forget removes utility proc} -constraints testutils -body {\n    testutils import foo\n    testutils forget foo\n    info procs kuk\n} -result {}\n\ntest testutils-3.3 {import fails: proc already exists} -constraints testutils -setup {\n    namespace eval ::zez {\n\tproc kuk {} {}\n    }\n} -body {\n    namespace eval ::zez {\n\ttestutils import foo\n    }\n} -result \"import from testutils domain \\\"foo\\\" failed: can't import command \\\"kuk\\\": already exists\" -returnCodes error -cleanup {\n    namespace delete ::zez\n}\n\n#\n# testutils command section 4. Import variables\n#\ntest testutils-4.1 {associated variables are imported} -constraints testutils -body {\n    testutils import foo\n    set varNames [info vars]\n    foreach name $initVars {\n\tset varNames [lremove $varNames [lsearch $varNames $name]]\n    }\n    list [lsort $varNames] [info exists bar] [info exists pip] $bar\n} -result [list {bar pip} 1 0 123] -cleanup {\n    unset -nocomplain name varNames\n    testutils forget foo\n}\n\ntest testutils-4.2 {\n    Repeated initialization keeps imported variable non-existent if it was\n    defined without a value, even if a test file inadvertently assigns it\n    a value in the meantime.\n} -constraints testutils -body {\n    catch {\n\ttestutils import foo\n    }\n    testutils forget foo\n    set pip 11111\n    testutils import foo\n    info exists pip\n} -result 0 -cleanup {\n    testutils forget foo\n}\n\ntest testutils-4.3 {import fails: variable already exists} -constraints testutils -setup {\n    #\n    # We need a pristine new namespace in which the variable bar was never imported\n    # and hence no upvar link for it exists.\n    #\n    namespace eval ::zez {\n\tset bar 11\n    }\n} -body {\n    namespace eval ::zez {\n\ttestutils import foo\n    }\n} -result \"import from testutils domain \\\"foo\\\" failed: variable \\\"bar\\\" already exists\" -returnCodes error -cleanup {\n    namespace delete ::zez\n}\n\ntest testutils-4.4 {repeated creation/deletion of requesting namespace doesn't fool testutils} -constraints testutils -body {\n    namespace eval ::zez {\n\ttestutils import foo\n\ttestutils forget foo\n    }\n    namespace delete ::zez\n    namespace eval ::zez {\n\tset pip 22\n\ttestutils import foo\n\tlist [info exists bar] [info exists pip] $bar\n    }\n} -result {1 0 123} -cleanup {\n    namespace delete ::zez\n}\n\n#\n# Testutils domain \"timing\"\n#\n\n#\n# COMMON TEST SETUP\n#\ntestutils import timing\n\ntest dt-1.1 {Exercise a timing run, default granularity (milliseconds)} -constraints testutils -setup {\n} -body {\n    dt.reset\n    expr {[dt.get] <= 1}\n} -result 1\n\ntest dt-1.2 {Exercise granularity microseconds} -constraints testutils -body {\n    dt.reset microseconds\n    expr {[dt.get] <= 1000}\n} -result 1\n\ntest dt-1.3 {Exercise granularity seconds} -constraints testutils -body {\n    dt.reset seconds\n    dt.get\n} -result 0\n\ntest dt-1.4 {Invalid value for granularity} -constraints testutils -body {\n    dt.reset bogus\n} -returnCodes error -result {invalid parameter \"bogus\", expected \"microseconds\", \"milliseconds\" or \"seconds\"}\n\ntest progress-1.1 {Exercise a timing run for a loop, granularity microseconds} -constraints testutils -body {\n    progress.init microseconds\n    while {[incr i] < 10} {\n\tprogress.update\n    }\n    progress.end\n} -errorOutput \"......... * microseconds\\n\" -match glob -cleanup {\n    unset i\n}\n\n#\n# COMMON TEST CLEANUP\n#\ntestutils forget timing\n\n\n#\n# TESTFILE CLEANUP\n#\n\nnamespace delete ::tk::test::foo\nunset -nocomplain bar initVars pip\ncleanupTests\n\n# EOF\n"
  },
  {
    "path": "tests/text.test",
    "content": "# This file is a Tcl script to test the code in the file tkText.c.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\nwm geometry . {}\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\n\f\n#\n# TESTS\n#\n\ntest text-1.1 {configuration option: \"autoseparators\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -autoseparators yes\n    .t cget -autoseparators\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-1.1b {configuration option: \"autoseparators\", default} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t cget -autoseparators\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-1.2 {configuration option: \"autoseparators\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -autoseparators nah\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.3 {configuration option: \"background\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -background #ff00ff\n    .t cget -background\n} -cleanup {\n    destroy .t\n} -result {#ff00ff}\ntest text-1.4 {configuration option: \"background\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -background <gorp>\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.5 {configuration option: \"bd\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -bd 4\n    .t cget -bd\n} -cleanup {\n    destroy .t\n} -result 4\ntest text-1.6 {configuration option: \"bd\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -bd foo\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.7 {configuration option: \"bg\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -bg blue\n    .t cget -bg\n} -cleanup {\n    destroy .t\n} -result {blue}\ntest text-1.8 {configuration option: \"bg\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -bg #xx\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.9 {configuration option: \"blockcursor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -blockcursor 0\n    .t cget -blockcursor\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-1.10 {configuration option: \"blockcursor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -blockcursor xx\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.11 {configuration option: \"borderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -borderwidth 7\n    .t cget -borderwidth\n} -cleanup {\n    destroy .t\n} -result 7\ntest text-1.12 {configuration option: \"borderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -borderwidth ++\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.13 {configuration option: \"cursor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -cursor watch\n    .t cget -cursor\n} -cleanup {\n    destroy .t\n} -result {watch}\ntest text-1.14 {configuration option: \"cursor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -cursor lousy\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.15 {configuration option: \"exportselection\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -exportselection no\n    .t cget -exportselection\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-1.16 {configuration option: \"exportselection\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -exportselection maybe\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.17 {configuration option: \"fg\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -fg red\n    .t cget -fg\n} -cleanup {\n    destroy .t\n} -result {red}\ntest text-1.18 {configuration option: \"fg\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -fg stupid\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.19 {configuration option: \"font\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -font fixed\n    .t cget -font\n} -cleanup {\n    destroy .t\n} -result {fixed}\ntest text-1.20 {configuration option: \"font\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -font {}\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.21 {configuration option: \"foreground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -foreground #012\n    .t cget -foreground\n} -cleanup {\n    destroy .t\n} -result {#012}\ntest text-1.22 {configuration option: \"foreground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -foreground bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.23 {configuration option: \"height\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -height 5\n    .t cget -height\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-1.24 {configuration option: \"height\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -height bad\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.25 {configuration option: \"highlightbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightbackground #123\n    .t cget -highlightbackground\n} -cleanup {\n    destroy .t\n} -result {#123}\ntest text-1.26 {configuration option: \"highlightbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightbackground bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.27 {configuration option: \"highlightcolor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightcolor #234\n    .t cget -highlightcolor\n} -cleanup {\n    destroy .t\n} -result {#234}\ntest text-1.28 {configuration option: \"highlightcolor\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightcolor bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.29 {configuration option: \"highlightthickness\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightthickness -2\n    .t cget -highlightthickness\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"-2\"}\ntest text-1.30 {configuration option: \"highlightthickness\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -highlightthickness bad\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.31 {configuration option: \"inactiveselectbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -inactiveselectbackground #ffff01234567\n    .t cget -inactiveselectbackground\n} -cleanup {\n    destroy .t\n} -result {#ffff01234567}\ntest text-1.32 {configuration option: \"inactiveselectbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -inactiveselectbackground bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.33 {configuration option: \"insertbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertbackground green\n    .t cget -insertbackground\n} -cleanup {\n    destroy .t\n} -result {green}\ntest text-1.34 {configuration option: \"insertbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertbackground <bogus>\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.35 {configuration option: \"insertborderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertborderwidth 45\n    .t cget -insertborderwidth\n} -cleanup {\n    destroy .t\n} -result 45\ntest text-1.36 {configuration option: \"insertborderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertborderwidth bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.37 {configuration option: \"insertofftime\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertofftime 100\n    .t cget -insertofftime\n} -cleanup {\n    destroy .t\n} -result 100\ntest text-1.38 {configuration option: \"insertofftime\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertofftime 2.4\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.39 {configuration option: \"insertontime\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertontime 47\n    .t cget -insertontime\n} -cleanup {\n    destroy .t\n} -result 47\ntest text-1.40 {configuration option: \"insertontime\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertontime e1\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.41 {configuration option: \"insertwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertwidth 2.3\n    .t cget -insertwidth\n} -cleanup {\n    destroy .t\n} -result 2.3\ntest text-1.42 {configuration option: \"insertwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertwidth 47d\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.43 {configuration option: \"maxundo\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -maxundo 5\n    .t cget -maxundo\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-1.43b {configuration option: \"maxundo\", default} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t cget -maxundo\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-1.44 {configuration option: \"maxundo\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -maxundo noway\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.45 {configuration option: \"padx\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -padx 3.4\n    .t cget -padx\n} -cleanup {\n    destroy .t\n} -result 3.4\ntest text-1.46 {configuration option: \"padx\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -padx 2.4.\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.47 {configuration option: \"pady\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -pady 82\n    .t cget -pady\n} -cleanup {\n    destroy .t\n} -result 82\ntest text-1.48 {configuration option: \"pady\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -pady bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.49 {configuration option: \"relief\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -relief raised\n    .t cget -relief\n} -cleanup {\n    destroy .t\n} -result {raised}\ntest text-1.50 {configuration option: \"relief\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -relief bumpy\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.51 {configuration option: \"selectbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectbackground #ffff01234567\n    .t cget -selectbackground\n} -cleanup {\n    destroy .t\n} -result {#ffff01234567}\ntest text-1.52 {configuration option: \"selectbackground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectbackground bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.53 {configuration option: \"selectborderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectborderwidth 21\n    .t cget -selectborderwidth\n} -cleanup {\n    destroy .t\n} -result 21\ntest text-1.54 {configuration option: \"selectborderwidth\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectborderwidth 3x\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.55 {configuration option: \"selectforeground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectforeground yellow\n    .t cget -selectforeground\n} -cleanup {\n    destroy .t\n} -result {yellow}\ntest text-1.56 {configuration option: \"selectforeground\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -selectforeground #12345\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.57 {configuration option: \"spacing1\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing1 20\n    .t cget -spacing1\n} -cleanup {\n    destroy .t\n} -result 20\ntest text-1.58 {configuration option: \"spacing1\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing1 1.3x\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.59 {configuration option: \"spacing1\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing1 -5\n    .t cget -spacing1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"-5\"}\ntest text-1.60 {configuration option: \"spacing1\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing1 bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.61 {configuration option: \"spacing2\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing2 5\n    .t cget -spacing2\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-1.62 {configuration option: \"spacing2\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing2 bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.63 {configuration option: \"spacing2\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing2 -1\n    .t cget -spacing2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"-1\"}\ntest text-1.64 {configuration option: \"spacing2\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing2 bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.65 {configuration option: \"spacing3\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing3 20\n    .t cget -spacing3\n} -cleanup {\n    destroy .t\n} -result 20\ntest text-1.66 {configuration option: \"spacing3\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing3 bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.67 {configuration option: \"spacing3\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing3 -10\n    .t cget -spacing3\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"-10\"}\ntest text-1.68 {configuration option: \"spacing3\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -spacing3 bogus\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.69 {configuration option: \"state\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -state d\n    .t cget -state\n} -cleanup {\n    destroy .t\n} -result {disabled}\ntest text-1.70 {configuration option: \"state\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -state foo\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.71 {configuration option: \"tabs\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -tabs {1i 2i 3i 4i}\n    .t cget -tabs\n} -cleanup {\n    destroy .t\n} -result {1i 2i 3i 4i}\ntest text-1.72 {configuration option: \"tabs\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -tabs bad_tabs\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.73 {configuration option: \"tabstyle\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -tabstyle wordprocessor\n    .t cget -tabstyle\n} -cleanup {\n    destroy .t\n} -result {wordprocessor}\ntest text-1.74 {configuration option: \"tabstyle\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -tabstyle garbage\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.75 {configuration option: \"undo\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -undo 1\n    .t cget -undo\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-1.75b {configuration option: \"undo\", default} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t cget -undo\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-1.76 {configuration option: \"undo\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -undo eh\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.77 {configuration option: \"width\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -width 73\n    .t cget -width\n} -cleanup {\n    destroy .t\n} -result 73\ntest text-1.78 {configuration option: \"width\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -width 2.4\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.79 {configuration option: \"wrap\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -wrap w\n    .t cget -wrap\n} -cleanup {\n    destroy .t\n} -result {word}\ntest text-1.80 {configuration option: \"wrap\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -wrap bad_wrap\n} -cleanup {\n    destroy .t\n} -match glob -returnCodes error -result {*}\ntest text-1.81 {text options} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -takefocus \"any old thing\"\n    .t cget -takefocus\n} -cleanup {\n    destroy .t\n} -result {any old thing}\ntest text-1.82 {text options} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -xscrollcommand \"x scroll command\"\n    .t configure -xscrollcommand\n} -cleanup {\n    destroy .t\n} -result {-xscrollcommand xScrollCommand ScrollCommand {} {x scroll command}}\ntest text-1.83 {text options} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -yscrollcommand \"test command\"\n    .t configure -yscrollcommand\n} -cleanup {\n    destroy .t\n} -result {-yscrollcommand yScrollCommand ScrollCommand {} {test command}}\ntest text-1.83.1 {configuration option: \"insertunfocussed\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertunfocussed none\n    .t cget -insertunfocussed\n} -cleanup {\n    destroy .t\n} -result none\ntest text-1.84 {configuration option: \"insertunfocussed\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertunfocussed hollow\n    .t cget -insertunfocussed\n} -cleanup {\n    destroy .t\n} -result hollow\ntest text-1.85 {configuration option: \"insertunfocussed\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -body {\n    .t configure -insertunfocussed solid\n    .t cget -insertunfocussed\n} -cleanup {\n    destroy .t\n} -result solid\ntest text-1.86 {configuration option: \"insertunfocussed\"} -setup {\n    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}\n    pack .t\n    update\n} -returnCodes error -body {\n    .t configure -insertunfocussed gorp\n} -cleanup {\n    destroy .t\n} -result {bad insertunfocussed \"gorp\": must be hollow, none, or solid}\n\n\ntest text-2.1 {Tk_TextCmd procedure} -body {\n    text\n} -returnCodes error -result {wrong # args: should be \"text pathName ?-option value ...?\"}\ntest text-2.2 {Tk_TextCmd procedure} -body {\n    text foobar\n} -returnCodes error -result {bad window path name \"foobar\"}\ntest text-2.3 {Tk_TextCmd procedure} -body {\n    text .t -gorp nofun\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest text-2.4 {Tk_TextCmd procedure} -body {\n    catch {text .t -gorp nofun}\n    winfo exists .t\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-2.5 {Tk_TextCmd procedure} -body {\n    text .t -bd 2 -fg red\n} -cleanup {\n    destroy .t\n} -returnCodes ok -result {.t}\ntest text-2.6 {Tk_TextCmd procedure} -body {\n    text .t -bd 2 -fg red\n\tlist [lindex [.t config -bd] 4] [lindex [.t config -fg] 4]\n} -cleanup {\n    destroy .t\n} -result {2 red}\ntest text-2.7 {Tk_TextCmd procedure} -constraints {\n    win\n} -body {\n    catch {destroy .t}\n    text .t\n    .t tag cget sel -relief\n} -cleanup {\n    destroy .t\n} -result {flat}\ntest text-2.8 {Tk_TextCmd procedure} -constraints {\n    aqua\n} -body {\n    catch {destroy .t}\n    text .t\n    .t tag cget sel -relief\n} -cleanup {\n    destroy .t\n} -result {flat}\ntest text-2.9 {Tk_TextCmd procedure} -constraints {\n    unix notAqua\n} -body {\n    catch {destroy .t}\n    text .t\n    .t tag cget sel -relief\n} -cleanup {\n    destroy .t\n} -result {raised}\ntest text-2.10 {Tk_TextCmd procedure} -body {\n    list [text .t] [winfo class .t]\n} -cleanup {\n    destroy .t\n} -result {.t Text}\n\n\ntest text-3.1 {TextWidgetCmd procedure, basics} -setup {\n    text .t\n} -body {\n    .t\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t option ?arg ...?\"}\ntest text-3.2 {TextWidgetCmd procedure} -setup {\n    text .t\n} -body {\n    .t gorp 1.0 z 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad option \"gorp\": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}\n\ntest text-4.1 {TextWidgetCmd procedure, \"bbox\" option} -setup {\n    text .t\n} -body {\n    .t bbox\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t bbox index\"}\ntest text-4.2 {TextWidgetCmd procedure, \"bbox\" option} -setup {\n    text .t\n} -body {\n    .t bbox a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t bbox index\"}\ntest text-4.3 {TextWidgetCmd procedure, \"bbox\" option} -setup {\n    text .t\n} -body {\n    .t bbox bad_mark\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"bad_mark\"}\n\ntest text-5.1 {TextWidgetCmd procedure, \"cget\" option} -setup {\n    text .t\n} -body {\n    .t cget\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t cget option\"}\ntest text-5.2 {TextWidgetCmd procedure, \"cget\" option} -setup {\n    text .t\n} -body {\n    .t cget a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t cget option\"}\ntest text-5.3 {TextWidgetCmd procedure, \"cget\" option} -setup {\n    text .t\n} -body {\n    .t cget -gorp\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest text-5.4 {TextWidgetCmd procedure, \"cget\" option} -setup {\n    text .t\n} -body {\n    .t configure -bd 17\n    .t cget -bd\n} -cleanup {\n    destroy .t\n} -result 17\n\n\ntest text-6.1 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t compare a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t compare index1 op index2\"}\ntest text-6.2 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t compare a b c d\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t compare index1 op index2\"}\ntest text-6.3 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t compare @x == 1.0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@x\"}\ntest text-6.4 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t compare 1.0 < @y\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@y\"}\ntest text-6.5 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t compare 1.1 < 1.0] [.t compare 1.1 < 1.1] [.t compare 1.1 < 1.2]\n} -cleanup {\n    destroy .t\n} -result {0 0 1}\ntest text-6.6 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t compare 1.1 <= 1.0] [.t compare 1.1 <= 1.1] [.t compare 1.1 <= 1.2]\n} -cleanup {\n    destroy .t\n} -result {0 1 1}\ntest text-6.7 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t compare 1.1 == 1.0] [.t compare 1.1 == 1.1] [.t compare 1.1 == 1.2]\n} -cleanup {\n    destroy .t\n} -result {0 1 0}\ntest text-6.8 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t compare 1.1 >= 1.0] [.t compare 1.1 >= 1.1] [.t compare 1.1 >= 1.2]\n} -cleanup {\n    destroy .t\n} -result {1 1 0}\ntest text-6.9 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t compare 1.1 > 1.0] [.t compare 1.1 > 1.1] [.t compare 1.1 > 1.2]\n} -cleanup {\n    destroy .t\n} -result {1 0 0}\ntest text-6.10 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    list [.t com 1.1 != 1.0] [.t compare 1.1 != 1.1] [.t compare 1.1 != 1.2]\n} -cleanup {\n    destroy .t\n} -result {1 0 1}\ntest text-6.11 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t compare 1.0 <x 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad comparison operator \"<x\": must be <, <=, ==, >=, >, or !=}\ntest text-6.12 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t compare 1.0 >> 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad comparison operator \">>\": must be <, <=, ==, >=, >, or !=}\ntest text-6.13 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t compare 1.0 z 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad comparison operator \"z\": must be <, <=, ==, >=, >, or !=}\ntest text-6.14 {TextWidgetCmd procedure, \"compare\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t co 1.0 z 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous option \"co\": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}\n\n# \"configure\" option is already covered above\n\ntest text-7.1 {TextWidgetCmd procedure, \"debug\" option} -setup {\n    text .t\n} -body {\n    .t debug 0 1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t debug boolean\"}\ntest text-7.2 {TextWidgetCmd procedure, \"debug\" option} -setup {\n    text .t\n} -body {\n    .t de 0 1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous option \"de\": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}\ntest text-7.3 {TextWidgetCmd procedure, \"debug\" option} -setup {\n    text .t\n} -body {\n    .t debug true\n    .t deb\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-7.4 {TextWidgetCmd procedure, \"debug\" option} -setup {\n    text .t\n} -body {\n    .t debug false\n    .t debug\n} -cleanup {\n    destroy .t\n} -result 0\n\n\ntest text-8.1 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t delete\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t delete index1 ?index2 ...?\"}\ntest text-8.2 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t delete a b c\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"a\"}\ntest text-8.3 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t delete @x 2.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@x\"}\ntest text-8.4 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\"\n    .t delete 2.3 @y\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@y\"}\ntest text-8.5 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t configure -state disabled\n    .t delete 2.3\n    .t get 2.0 2.end\n} -cleanup {\n    destroy .t\n} -result {abcdefghijklm}\ntest text-8.6 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t delete 2.3\n    .t get 2.0 2.end\n} -cleanup {\n    destroy .t\n} -result {abcefghijklm}\ntest text-8.7 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t delete 2.1 2.3\n    .t get 2.0 2.end\n} -cleanup {\n    destroy .t\n} -result {adefghijklm}\ntest text-8.8 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\"\n    # All indices are checked before we actually delete anything\n    .t delete 2.1 2.3 foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"foo\"}\ntest text-8.9 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\"\n# All indices are checked before we actually delete anything\n    catch {.t delete 2.1 2.3 foo}\n    .t get 2.0 2.end\n} -cleanup {\n    destroy .t\n} -result {abcdefghijklm}\ntest text-8.10 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    # auto-forward one byte if the last \"pair\" is just one\n    .t delete 1.0 end\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.1 2.3 2.3\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\naefghijklm}\ntest text-8.11 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # all indices will be ordered before deletion\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.3 2.7 2.9 2.4\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\ndfgjklm}\ntest text-8.12 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # and check again with even pairs\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.2 2.7 2.9 2.4 2.5\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\ncdfgjklm}\ntest text-8.13 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # we should get the longest range on equal start indices\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.2 2.0 2.5 2.0 2.3 2.8 2.7\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\nfghijklm}\ntest text-8.14 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # we should get the longest range on equal start indices\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.2 1.2 2.6 2.0 2.5\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foghijklm}\ntest text-8.15 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # we should get the longest range on equal start indices\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.2 2.0 2.5 1.1 2.3 2.8 2.7\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {ffghijklm}\ntest text-8.16 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # we should get the watch for overlapping ranges - they should\n    # essentially be merged into one span.\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.6 2.2 2.8\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\nijklm}\ntest text-8.17 {TextWidgetCmd procedure, \"delete\" option} -setup {\n    text .t\n} -body {\n    # we should get the watch for overlapping ranges - they should\n    # essentially be merged into one span.\n    .t insert 1.0 \"foo\\nabcdefghijklm\"\n    .t delete 2.0 2.6 2.2 2.4\n    .t get 1.0 end-1c\n} -cleanup {\n    destroy .t\n} -result {foo\nghijklm}\ntest text-8.18 {TextWidgetCmd procedure, \"replace\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\"\n    .t replace 1.3 2.3\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t replace index1 index2 chars ?tagList chars tagList ...?\"}\ntest text-8.19 {TextWidgetCmd procedure, \"replace\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\"\n    .t replace 3.1 2.3 foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {index \"2.3\" before \"3.1\" in the text}\ntest text-8.20 {TextWidgetCmd procedure, \"replace\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t replace 2.1 2.3 foo\n} -cleanup {\n    destroy .t\n} -returnCodes ok -result {}\ntest text-8.21 {TextWidgetCmd procedure, \"replace\" option with undo} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    set prevtext [.t get 1.0 end-1c]\n    .t configure -undo 0\n    .t configure -undo 1\n    # Ensure it is treated as a single undo action\n    .t replace 2.1 2.3 foo\n    .t edit undo\n    string equal [.t get 1.0 end-1c] $prevtext\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-8.22 {TextWidgetCmd procedure, \"replace\" option with undo} -setup {\n    text .t\n    set res {}\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t configure -undo 0\n    .t configure -undo 1\n    .t replace 2.1 2.3 foo\n    # Ensure we can override a text widget and intercept undo\n    # actions.  If in the future a different mechanism is available\n    # to do this, then we should be able to change this test.  The\n    # behaviour tested for here is not, strictly speaking, documented.\n    rename .t test.t\n    proc .t {args} { lappend ::res $args ; uplevel 1 test.t $args }\n    .t edit undo\n    return $res\n} -cleanup {\n    rename .t {}\n    rename test.t .t\n    destroy .t\n} -result [list {edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} \\\n\t\t{mark set tk::undoMarkL2 2.1} {mark set tk::undoMarkR2 2.4} \\\n\t\t{mark gravity tk::undoMarkL2 left} {mark gravity tk::undoMarkR2 right} \\\n\t\t{insert 2.1 ef} {mark set insert 2.3} {see insert} \\\n\t\t{mark set tk::undoMarkL1 2.1} {mark set tk::undoMarkR1 2.3} \\\n\t\t{mark gravity tk::undoMarkL1 left} {mark gravity tk::undoMarkR1 right} \\\n\t\t{mark names} \\\n\t\t{index tk::undoMarkL1} {index tk::undoMarkR1} \\\n\t\t{mark unset tk::undoMarkL1 tk::undoMarkR1} \\\n\t\t{index tk::undoMarkL2} {index tk::undoMarkR2} \\\n\t\t{mark unset tk::undoMarkL2 tk::undoMarkR2} \\\n\t\t{compare 2.1 > 2.3} {compare 2.6 > 2.3} ]\n\ntest text-8.23 {TextWidgetCmd procedure, \"replace\" option with undo} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    set prevtext [.t get 1.0 end-1c]\n    .t configure -undo 0\n    .t configure -undo 1\n    # Ensure that undo (even composite undo like 'replace')\n    # works when the widget shows nothing useful.\n    .t replace 2.1 2.3 foo\n    .t configure -startline 1 -endline 1\n    .t edit undo\n    .t configure -startline {} -endline {}\n    .t configure -undo 0\n    string equal [.t get 1.0 end-1c] $prevtext\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-8.24 {TextWidgetCmd procedure, \"replace\" option with peers, undo} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    set prevtext [.t get 1.0 end-1c]\n    .t configure -undo 0\n    .t configure -undo 1\n    .t peer create .tt -undo 1\n# Ensure that undo (even composite undo like 'replace')\n# works when the the event took place in one peer, which\n# is then deleted, before the undo takes place in another peer.\n    .tt replace 2.1 2.3 foo\n    .tt configure -startline 1 -endline 1\n    destroy .tt\n    .t edit undo\n    .t configure -startline {} -endline {}\n    .t configure -undo 0\n    string equal [.t get 1.0 end-1c] $prevtext\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-8.25 {TextWidgetCmd procedure, \"replace\" option with peers, undo} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    set prevtext [.t get 1.0 end-1c]\n    .t configure -undo 0\n    .t configure -undo 1\n    .t peer create .tt -undo 1\n# Ensure that undo (even composite undo like 'replace')\n# works when the the event took place in one peer, which\n# is then deleted, before the undo takes place in another peer\n# which isn't showing everything.\n    .tt replace 2.1 2.3 foo\n    set res [.tt get 2.1 2.4]\n    .tt configure -startline 1 -endline 1\n    destroy .tt\n    .t configure -startline 3 -endline 4\n# msg will actually be set to a silently ignored error message here,\n# (that the .tt command doesn't exist), but that is not important.\n    lappend res [catch {.t edit undo}]\n    .t configure -undo 0\n    .t configure -startline {} -endline {}\n    lappend res [string equal [.t get 1.0 end-1c] $prevtext]\n} -cleanup {\n    destroy .t\n} -result {foo 0 1}\ntest text-8.26 {TextWidgetCmd procedure, \"replace\" option crash} -setup {\n    text .tt\n} -body {\n    .tt insert 0.0 foo\\n\n    .tt replace end-1l end bar\n} -cleanup {\n    destroy .tt\n} -result {}\ntest text-8.27 {TextWidgetCmd procedure, \"replace\" option crash} -setup {\n    text .tt\n} -body {\n    .tt insert 0.0 \\na\n    for {set i 0} {$i < 2} {incr i} {\n\t.tt replace 2.0 3.0 b\n    }\n} -cleanup {\n    destroy .tt\n} -result {}\ntest text-8.28 {TextWidgetCmd procedure, \"replace\" option crash} -setup {\n    text .tt\n} -body {\n    .tt insert end \"foo\\n\"\n    .tt tag add sel 1.0 end\n    .tt replace sel.first sel.last \"bar\"\n} -cleanup {\n    destroy .tt\n} -result {}\n\n\ntest text-9.1 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t get\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t get ?-displaychars? ?--? index1 ?index2 ...?\"}\ntest text-9.2 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t get a b c\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"a\"}\ntest text-9.3 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t get @q 3.1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@q\"}\ntest text-9.4 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t get 3.1 @r\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@r\"}\ntest text-9.5 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.7 5.3\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-9.6 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.3 5.5\n} -cleanup {\n    destroy .t\n} -result { G}\ntest text-9.7 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.3 end\n} -cleanup {\n    destroy .t\n} -result { GIrl .#@? x_yz\n!@#$%\nLine 7\n}\ntest text-9.8 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.7\n} -cleanup {\n    destroy .t\n} -result {y GIr}\ntest text-9.9 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2\n} -cleanup {\n    destroy .t\n} -result {y}\ntest text-9.10 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4\n} -cleanup {\n    destroy .t\n} -result {y }\ntest text-9.11 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4 5.4\n} -cleanup {\n    destroy .t\n} -result {{y } G}\ntest text-9.12 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4 5.4 5.5\n} -cleanup {\n    destroy .t\n} -result {{y } G}\ntest text-9.13 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4 5.5 \"5.5+5c\"\n} -cleanup {\n    destroy .t\n} -result {{y } {Irl .}}\ntest text-9.14 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4 5.4 5.5 end-3c\n} -cleanup {\n    destroy .t\n} -result {{y } G { }}\ntest text-9.15 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.4 5.4 5.5 end-3c end\n} -cleanup {\n    destroy .t\n} -result {{y } G { 7\n}}\ntest text-9.16 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t get 5.2 5.3 5.4 5.3\n} -cleanup {\n    destroy .t\n} -result {y}\ntest text-9.17 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t index \"5.2 +3 indices\"\n} -cleanup {\n    destroy .t\n} -result {5.5}\ntest text-9.18 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t index \"5.2 +3chars\"\n} -cleanup {\n    destroy .t\n} -result {5.5}\ntest text-9.19 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t index \"5.2 +3displayindices\"\n} -cleanup {\n    destroy .t\n} -result {5.5}\ntest text-9.20 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t get 5.2 5.4 5.5 foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"foo\"}\ntest text-9.21 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t get 5.2 5.4 5.4 5.5 end-3c end\n} -cleanup {\n    destroy .t\n} -result {{y } G { 7\n}}\ntest text-9.22 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t get -displaychars 5.2 5.4 5.4 5.5 end-3c end\n} -cleanup {\n    destroy .t\n} -result {{} G { 7\n}}\ntest text-9.23 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    list [.t index \"5.1 +4indices\"] [.t index \"5.1+4d indices\"]\n} -cleanup {\n    destroy .t\n} -result {5.5 5.7}\ntest text-9.24 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    list [.t index \"5.1 +4a chars\"] [.t index \"5.1+4d chars\"]\n} -cleanup {\n    destroy .t\n} -result {5.5 5.7}\ntest text-9.25 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    list [.t index \"5.5 -4indices\"] [.t index \"5.7-4d indices\"]\n} -cleanup {\n    destroy .t\n} -result {5.1 5.1}\ntest text-9.26 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    list [.t index \"5.5 -4a chars\"] [.t index \"5.7-4d chars\"]\n} -cleanup {\n    destroy .t\n} -result {5.1 5.1}\ntest text-9.27 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t window create 5.4\n    list [.t index \"5.1 +4indices\"] [.t index \"5.1+4d indices\"]\n} -cleanup {\n    destroy .t\n} -result {5.5 5.7}\ntest text-9.28 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t window create 5.4\n    list [.t index \"5.1 +4a chars\"] [.t index \"5.1+4d chars\"]\n} -cleanup {\n    destroy .t\n} -result {5.6 5.8}\ntest text-9.29 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t window create 5.4\n    list [.t index \"5.5 -4indices\"] [.t index \"5.7-4d indices\"]\n} -cleanup {\n    destroy .t\n} -result {5.1 5.1}\ntest text-9.30 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t window create 5.4\n    list [.t index \"5.6 -4a chars\"] [.t index \"5.8-4d chars\"]\n} -cleanup {\n    destroy .t\n} -result {5.1 5.1}\ntest text-9.31 {TextWidgetCmd procedure, \"get\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 5.2 5.4\n    .t window create 5.4\n    .t delete 5.4\n    .t tag add elide 5.5 5.6\n    .t get -displaychars 5.2 5.8\n} -cleanup {\n    destroy .t\n} -result {Grl}\n\n\ntest text-10.1 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t count\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t count ?-option value ...? index1 index2\"}\ntest text-10.2 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t count blah 1.0 2.0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad option \"blah\": must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}\ntest text-10.3 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t count a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"a\"}\ntest text-10.4 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t count @q 3.1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@q\"}\ntest text-10.5 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t count 3.1 @r\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@r\"}\ntest text-10.6 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.7 5.3\n} -cleanup {\n    destroy .t\n} -result -4\ntest text-10.7 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.3 5.5\n} -cleanup {\n    destroy .t\n} -result 2\ntest text-10.8 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t count 5.3 end\n} -cleanup {\n    destroy .t\n} -result 29\ntest text-10.9 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.2 5.7\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-10.10 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.2 5.3\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-10.11 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.2 5.4\n} -cleanup {\n    destroy .t\n} -result 2\ntest text-10.12 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t count 5.2 foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"foo\"}\ntest text-10.13 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t count -displayindices 2.0 3.0\n} -cleanup {\n    destroy .t\n} -result 2\ntest text-10.14 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t count -displayindices 2.2 3.0\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.15 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n    .t count -displayindices 2.0 4.2\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-10.16 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displayindices 2.0 3.0\n} -cleanup {\n    destroy .t\n} -result 3\ntest text-10.17 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displayindices 2.2 3.0\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-10.18 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n    .t mark set a 2.2\n# Creating this window here means that the elided text\n# now starts at 2.3, but 'a' is automatically moved to 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displayindices a 3.0\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.19 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displayindices 2.0 4.2\n} -cleanup {\n    destroy .t\n} -result 6\ntest text-10.20 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 3.0\n} -cleanup {\n    destroy .t\n} -result 2\ntest text-10.21 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.2 3.0\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-10.22 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n    .t mark set a 2.2\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3, but 'a' is automatically moved to 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars a 3.0\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.23 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 4.2\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-10.24 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 4.2\n    list [.t count -indices 2.2 3.0] [.t count 2.2 3.0]\n} -cleanup {\n    destroy .t\n} -result {10 10}\ntest text-10.25 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n    .t mark set a 2.2\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3, but 'a' is automatically moved to 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    list [.t count -indices a 3.0] [.t count a 3.0]\n} -cleanup {\n    destroy .t\n} -result {9 9}\ntest text-10.26 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 4.2\n    .t count -indices 2.0 4.2\n} -cleanup {\n    destroy .t\n} -result 21\ntest text-10.27 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 4.2\n    .t count -chars 2.2 3.0\n} -cleanup {\n    destroy .t\n} -result 10\ntest text-10.28 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n    .t mark set a 2.2\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3, but 'a' is automatically moved to 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -chars a 3.0\n} -cleanup {\n    destroy .t\n} -result 9\ntest text-10.29 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t tag configure elide -elide 1\n    .t tag add elide 2.2 3.4\n    .t tag add elide 4.0 4.1\n# Create one visible and one invisible window\n    frame .t.w1\n    frame .t.w2\n# Creating this window here means that the elided text\n# now starts at 2.3\n    .t window create 2.1 -window .t.w1\n    .t window create 3.1 -window .t.w2\n    .t count -displaychars 2.0 4.2\n    .t count -chars 2.0 4.2\n} -cleanup {\n    destroy .t\n} -result 19\ntest text-10.30 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines 1.0 end\n} -cleanup {\n    destroy .t\n} -result 3\ntest text-10.31 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines end 1.0\n} -cleanup {\n    destroy .t\n} -result -3\ntest text-10.32 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines 1.0 2.0 3.0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad option \"1.0\": must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}\ntest text-10.33 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines end end\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.34 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines 1.5 2.5\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-10.35 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines 2.5 \"2.5 lineend\"\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.36 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines 2.7 \"1.0 lineend\"\n} -cleanup {\n    destroy .t\n} -result -1\ntest text-10.37 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n} -body {\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t configure -wrap none\n    .t count -displaylines 1.0 end\n} -cleanup {\n    destroy .t\n} -result 3\ntest text-10.38 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t -expand 1 -fill both\n} -body {\n    .t configure -width 20 -height 10\n    update\n    .t insert end [string repeat \"abcde \" 50]\\n\n    .t insert end [string repeat \"fghij \" 50]\\n\n    .t insert end [string repeat \"klmno \" 50]\n    .t count -lines -chars -indices -displaylines 1.0 end\n} -cleanup {\n    destroy .t\n} -result {3 903 903 45}\ntest text-10.39 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    pack .t\n    update\n    set res {}\n} -body {\n    .t insert end \"Line 1 - This is Line 1\\n\"\n    .t insert end \"Line 2 - This is Line 2\\n\"\n    .t insert end \"Line 3 - This is Line 3\\n\"\n    .t insert end \"Line 4 - This is Line 4\\n\"\n    .t insert end \"Line 5 - This is Line 5\\n\"\n    lappend res [.t count -displaylines 1.19 3.24] [.t count -displaylines 1.0 end]\n    .t tag add hidden 2.9 3.17\n    .t tag configure hidden -elide true\n    lappend res [.t count -displaylines 1.19 3.24] [.t count -displaylines 1.0 end]\n} -cleanup {\n    destroy .t\n} -result {2 6 1 5}\ntest text-10.40 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    pack .t\n    update\n    set res {}\n} -body {\n    for {set i 1} {$i < 5} {incr i} {\n      .t insert end \"Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr {64+$i}]]\\n\"\n    }\n    .t tag configure hidden -elide true\n    .t tag add hidden 2.15 3.10\n    .t configure -wrap none\n    set res [.t count -displaylines 2.0 3.0]\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-10.41 {TextWidgetCmd procedure, \"count\" option} -setup {\n    toplevel .mytop\n    pack [text .mytop.t -font TkFixedFont -bd 0 -padx 0 -wrap char]\n    set spec [font measure TkFixedFont \"Line 1+++Line 1---Li\"]  ; # 20 chars\n    append spec x300+0+0\n    wm geometry .mytop $spec\n    .mytop.t delete 1.0 end\n    update\n    set res {}\n} -body {\n    for {set i 1} {$i < 5} {incr i} {\n      #                    0          1          2          3          4\n      #                    012345 678901234 567890123 456789012 34567890123456789\n      .mytop.t insert end \"Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr {64+$i}]]\\n\"\n    }\n    .mytop.t tag configure hidden -elide true\n    .mytop.t tag add hidden 2.30 3.10\n    lappend res [.mytop.t count -displaylines 2.0 3.0]\n    lappend res [.mytop.t count -displaylines 2.0 3.50]\n} -cleanup {\n    destroy .mytop\n} -result {1 3}\ntest text-10.42 {TextWidgetCmd procedure, \"count\" option} -setup {\n    text .t\n    pack .t\n    update\n    set res {}\n} -body {\n    for {set i 1} {$i < 25} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    .t tag configure hidden -elide true\n    .t tag add hidden 5.7 11.0\n    update\n    # next line to be fully sure that asynchronous line heights calculation is\n    # up-to-date otherwise this test may fail (depending on the computer\n    # performance), especially when the . toplevel has small height\n    .t sync\n    set y1 [lindex [.t yview] 1]\n    .t count -displaylines 5.0 11.0\n    set y2 [lindex [.t yview] 1]\n    .t count -displaylines 5.0 12.0\n    set y3 [lindex [.t yview] 1]\n    list [expr {$y1 == $y2}] [expr {$y1 == $y3}]\n} -cleanup {\n    destroy .t\n} -result {1 1}\n\n\ntest text-11.1 {counting with tag priority eliding} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t -expand 1 -fill both\n} -body {\n    .t insert end \"hello\"\n    .t configure -wrap none\n    list [.t count -displaychars 1.0 1.0] \\\n      [.t count -displaychars 1.0 1.1] \\\n      [.t count -displaychars 1.0 1.2] \\\n      [.t count -displaychars 1.0 1.3] \\\n      [.t count -displaychars 1.0 1.4] \\\n      [.t count -displaychars 1.0 1.5] \\\n      [.t count -displaychars 1.0 1.6] \\\n      [.t count -displaychars 1.0 2.6] \\\n} -cleanup {\n    destroy .t\n} -result {0 1 2 3 4 5 5 6}\ntest text-11.2 {counting with tag priority eliding} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t -expand 1 -fill both\n} -body {\n    .t insert end \"hello\"\n    .t tag configure elide1 -elide 0\n    .t tag add elide1 1.2 1.4\n    .t count -displaychars 1.0 1.5\n} -cleanup {\n    destroy .t\n} -result 5\ntest text-11.3 {counting with tag priority eliding} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .t insert end \"hello\"\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag add elide1 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    .t count -displaychars 1.0 1.5\n} -cleanup {\n    destroy .t\n} -result 3\ntest text-11.4 {counting with tag priority eliding}  -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    set res {}\n} -body {\n    .t insert end \"hello\"\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag add elide1 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    .t tag add elide1 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    .t delete 1.0 end\n    .t insert end \"hello\"\n    .t tag add elide1 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n} -cleanup {\n    destroy .t\n} -result {3 3}\ntest text-11.5 {counting with tag priority eliding}  -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    set res {}\n} -body {\n    .t insert end \"hello\"\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag configure elide3 -elide 0\n    .t tag add elide1 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    .t delete 1.0 end\n    .t insert end \"hello\"\n    .t tag add elide3 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n} -cleanup {\n    destroy .t\n} -result {5 5}\ntest text-11.6 {counting with tag priority eliding}  -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    set res {}\n} -body {\n    .t insert end \"hello\"\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag configure elide3 -elide 0\n    .t tag configure elide4 -elide 1\n    .t tag add elide2 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    .t tag add elide4 1.2 1.4\n    .t tag add elide1 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    .t delete 1.0 end\n    .t insert end \"hello\"\n    .t tag add elide1 1.2 1.4\n    .t tag add elide4 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n} -cleanup {\n    destroy .t\n} -result {3 3}\ntest text-11.7 {counting with tag priority eliding}  -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    set res {}\n} -body {\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag configure elide3 -elide 0\n    .t insert end \"hello\"\n    .t tag add elide2 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    .t tag add elide1 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    .t delete 1.0 end\n    .t insert end \"hello\"\n    .t tag add elide1 1.2 1.4\n    .t tag add elide2 1.2 1.4\n    .t tag add elide3 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n} -cleanup {\n    destroy .t\n} -result {5 5}\ntest text-11.8 {counting with tag priority eliding} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t -expand 1 -fill both\n    set res {}\n} -body {\n    .t insert end \"hello\"\n# Newer tags are higher priority\n    .t tag configure elide1 -elide 0\n    .t tag configure elide2 -elide 1\n    .t tag add elide2 1.0 1.5\n    .t tag add elide1 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    lappend res [.t count -displaychars 1.1 1.5]\n    lappend res [.t count -displaychars 1.2 1.5]\n    lappend res [.t count -displaychars 1.3 1.5]\n    .t delete 1.0 end\n    .t insert end \"hello\"\n    .t tag add elide1 1.0 1.5\n    .t tag add elide2 1.2 1.4\n    lappend res [.t count -displaychars 1.0 1.5]\n    lappend res [.t count -displaychars 1.1 1.5]\n    lappend res [.t count -displaychars 1.2 1.5]\n    lappend res [.t count -displaychars 1.3 1.5]\n} -cleanup {\n    destroy .t\n} -result {0 0 0 0 3 2 1 1}\ntest text-11.9 {counting with tag priority eliding} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t -expand 1 -fill both\n    set res {}\n} -body {\n    .t tag configure WELCOME -elide 1\n    .t tag configure SYSTEM -elide 0\n    .t tag configure TRAFFIC -elide 1\n    .t insert end \"\\n\" {SYSTEM TRAFFIC}\n    .t insert end \"\\n\" WELCOME\n    lappend res [.t count -displaychars 1.0 end]\n    lappend res [.t count -displaychars 1.0 end-1c]\n    lappend res [.t count -displaychars 1.0 1.2]\n    lappend res [.t count -displaychars 2.0 end]\n    lappend res [.t count -displaychars 2.0 end-1c]\n    lappend res [.t index \"1.0 +1 indices\"]\n    lappend res [.t index \"1.0 +1 display indices\"]\n    lappend res [.t index \"1.0 +1 display chars\"]\n    lappend res [.t index end]\n    lappend res [.t index \"end -1 indices\"]\n    lappend res [.t index \"end -1 display indices\"]\n    lappend res [.t index \"end -1 display chars\"]\n    lappend res [.t index \"end -2 indices\"]\n    lappend res [.t index \"end -2 display indices\"]\n    lappend res [.t index \"end -2 display chars\"]\n} -cleanup {\n    destroy .t\n} -result {1 0 0 1 0 2.0 4.0 4.0 4.0 3.0 3.0 3.0 2.0 1.0 1.0}\n\ntest text-11a.1 {TextWidgetCmd procedure, \"pendingsync\" option} -setup {\n    destroy .yt\n} -body {\n    text .yt\n    list [catch {.yt pendingsync mytext} msg] $msg\n} -cleanup {\n    destroy .yt\n} -result {1 {wrong # args: should be \".yt pendingsync\"}}\n\ntest text-11a.2 {TextWidgetCmd procedure, \"pendingsync\" option} -setup {\n    destroy .top.yt .top\n} -body {\n    toplevel .top\n    pack [text .top.yt]\n    update\n    set content {}\n    for {set i 1} {$i < 300} {incr i} {\n\tappend content [string repeat \"$i \" 15] \\n\n    }\n    .top.yt insert 1.0 $content\n    # wait for end of line metrics calculation to get correct $fraction1\n    # as a reference\n    while {[.top.yt pendingsync]} {update}\n    .top.yt yview moveto 1\n    set fraction1 [lindex [.top.yt yview] 0]\n    set res [expr {$fraction1 > 0}]\n    .top.yt delete 1.0 end\n    .top.yt insert 1.0 $content\n    # ensure the test is relevant\n    lappend res [.top.yt pendingsync]\n    # asynchronously wait for completion of line metrics calculation\n    while {[.top.yt pendingsync]} {update}\n    .top.yt yview moveto $fraction1\n    set fraction2 [lindex [.top.yt yview] 0]\n    lappend res [expr {$fraction1 == $fraction2}]\n} -cleanup {\n    destroy .top.yt .top\n} -result {1 1 1}\n\ntest text-11a.11 {TextWidgetCmd procedure, \"sync\" option} -setup {\n    destroy .yt\n} -body {\n    text .yt\n    list [catch {.yt sync mytext} msg] $msg\n} -cleanup {\n    destroy .yt\n} -result {1 {wrong # args: should be \".yt sync ?-command command?\"}}\ntest text-11a.12 {TextWidgetCmd procedure, \"sync\" option} -setup {\n    destroy .top.yt .top\n} -body {\n    toplevel .top\n    pack [text .top.yt]\n    update\n    set content {}\n    # Use long lines so the line metrics will need updating.\n    for {set i 1} {$i < 30} {incr i} {\n\tappend content [string repeat \"$i \" 200] \\n\n    }\n    .top.yt insert 1.0 $content\n    # wait for end of line metrics calculation to get correct $fraction1\n    # as a reference\n    .top.yt sync\n    .top.yt yview moveto 1\n    set fraction1 [lindex [.top.yt yview] 0]\n    set res [expr {$fraction1 > 0}]\n    # first case: do not wait for completion of line metrics calculation\n    .top.yt delete 1.0 end\n    .top.yt insert 1.0 $content\n    .top.yt yview moveto $fraction1\n    set fraction2 [lindex [.top.yt yview] 0]\n    lappend res [expr {$fraction1 == $fraction2}]\n    # second case: wait for completion of line metrics calculation\n    .top.yt delete 1.0 end\n    .top.yt insert 1.0 $content\n    .top.yt sync\n    .top.yt yview moveto $fraction1\n    set fraction2 [lindex [.top.yt yview] 0]\n    lappend res [expr {$fraction1 == $fraction2}]\n} -cleanup {\n    destroy .top.yt .top\n} -result {1 0 1}\n\ntest text-11a.21 {TextWidgetCmd procedure, \"sync\" option with -command} -setup {\n    destroy .yt\n} -body {\n    text .yt\n    list [catch {.yt sync -comx foo} msg] $msg\n} -cleanup {\n    destroy .yt\n} -result {1 {wrong option \"-comx\": should be \"-command\"}}\ntest text-11a.22 {TextWidgetCmd procedure, \"sync\" option with -command} -setup {\n    destroy .top.yt .top\n} -body {\n    set res {}\n    set ::x 0\n    toplevel .top\n    pack [text .top.yt]\n    update\n    set content {}\n    for {set i 1} {$i < 30} {incr i} {\n\tappend content [string repeat \"$i \" 15] \\n\n    }\n    .top.yt insert 1.0 $content\n    # first case: line metrics calculation still running when launching 'sync -command'\n    lappend res [.top.yt pendingsync]       ; # {1}\n    .top.yt sync -command [list set ::x 1]\n    lappend res $::x                        ; # {1 0}\n    # now finish line metrics calculations\n    while {[.top.yt pendingsync]} {update}\n    lappend res [.top.yt pendingsync] $::x  ; # {1 0 0 1}\n    # second case: line metrics calculation completed when launching 'sync -command'\n    .top.yt sync -command [list set ::x 2]\n    lappend res $::x                        ; # {1 0 0 1 1}\n    vwait ::x\n    lappend res $::x                        ; # {1 0 0 1 1 2}\n} -cleanup {\n    destroy .top.yt .top\n} -result {1 0 0 1 1 2}\n\ntest text-11a.31 {\"<<WidgetViewSync>>\" event} -setup {\n    destroy .top.yt .top\n} -body {\n    toplevel .top\n    pack [text .top.yt]\n    update\n    set content {}\n    for {set i 1} {$i < 300} {incr i} {\n\tappend content [string repeat \"$i \" 15] \\n\n    }\n    # Sync the widget and process <<WidgetViewSync>> events before binding.\n    .top.yt sync\n    update\n    bind .top.yt <<WidgetViewSync>> { if {%d} {set yud(%W) 1} }\n    .top.yt insert 1.0 $content\n    .top.yt yview moveto 1\n    set fraction1 [lindex [.top.yt yview] 0]\n    set res [expr {$fraction1 > 0}]\n    .top.yt delete 1.0 end\n    .top.yt insert 1.0 $content\n    # synchronously wait for completion of line metrics calculation\n    # and verify that the fractions agree.\n    set waited 0\n    if {[.top.yt pendingsync]} {set waited 1 ; vwait yud(.top.yt)}\n    lappend res $waited\n    .top.yt yview moveto $fraction1\n    set fraction2 [lindex [.top.yt yview] 0]\n    lappend res [expr {$fraction1 == $fraction2}]\n} -cleanup {\n    destroy .top.yt .top\n} -result {1 1 1}\n\ntest text-11a.41 {\"sync\" \"pendingsync\" and <<WidgetViewSync>>} -setup {\n    destroy .top.yt .top\n} -body {\n    toplevel .top\n    pack [text .top.yt]\n    update\n    set content {}\n    for {set i 1} {$i < 300} {incr i} {\n\tappend content [string repeat \"$i \" 50] \\n\n    }\n    # Sync the widget and process all <<WidgetViewSync>> events before binding.\n    .top.yt sync\n    update\n    bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d}\n    set res {}\n    # The next line triggers <<WidgetViewSync>> with %d==0 i.e. out of sync.\n    .top.yt insert 1.0 $content\n    vwait res\n    # Verify that the line metrics are not up-to-date (pendingsync is 1).\n    lappend res \"Pending:[.top.yt pendingsync]\"\n    # Update all line metrics by calling the sync command.\n    .top.yt sync\n    # <<WidgetViewSync>> should fire with %d==1 i.e. back in sync.\n    vwait res\n    # At this time the line metrics should be up-to-date (pendingsync is 0).\n    lappend res \"Pending:[.top.yt pendingsync]\"\n    set res\n} -cleanup {\n    destroy .top.yt .top\n} -result {Sync:0 Pending:1 Sync:1 Pending:0}\n\ntest text-11a.51 {<<WidgetViewSync>> calls Tk_SendVirtualEvent(),\n\t\t  NOT Tk_HandleEvent().\n\t\t  Bug [b362182e45704dd7bbd6aed91e48122035ea3d16]} -setup {\n    destroy .top.t .top\n} -body {\n    set res {}\n    toplevel .top\n    pack [text .top.t]\n    update\n    for {set i 1} {$i < 10000} {incr i} {\n\t.top.t insert end \"Hello world!\\n\"\n    }\n    bind .top.t <<WidgetViewSync>> {destroy .top.t}\n    .top.t tag add mytag 1.5 8000.8    ; # shall not crash\n    update\n    set res \"Still doing fine!\"\n} -cleanup {\n    destroy .top.t .top\n} -result {Still doing fine!}\n\ntest text-12.1 {TextWidgetCmd procedure, \"index\" option} -setup {\n    text .t\n} -body {\n    .t index\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t index index\"}\ntest text-12.2 {TextWidgetCmd procedure, \"index\" option} -setup {\n    text .t\n} -body {\n    .t ind a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t index index\"}\ntest text-12.3 {TextWidgetCmd procedure, \"index\" option} -setup {\n    text .t\n} -body {\n    .t in a b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous option \"in\": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview}\ntest text-12.4 {TextWidgetCmd procedure, \"index\" option} -setup {\n    text .t\n} -body {\n    .t index @xyz\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"@xyz\"}\ntest text-12.5 {TextWidgetCmd procedure, \"index\" option} -setup {\n    [text .t] insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t index 1.2\n} -cleanup {\n    destroy .t\n} -result 1.2\n\n\ntest text-13.1 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    [text .t] insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n} -body {\n    .t insert 1.2\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t insert index chars ?tagList chars tagList ...?\"}\ntest text-13.2 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t config -state disabled\n    .t insert 1.2 xyzzy\n    .t get 1.0 1.end\n} -cleanup {\n    destroy .t\n} -result {Line 1}\ntest text-13.3 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t insert 1.2 xyzzy\n    .t get 1.0 1.end\n} -cleanup {\n    destroy .t\n} -result {Lixyzzyne 1}\ntest text-13.4 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1\naefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n    .t delete 1.0 end\n    .t insert 1.0 \"Sample text\" x\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.0 1.11}\ntest text-13.5 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Sample text\" x\n    .t insert 1.2 \"XYZ\" y\n    list [.t tag ranges x] [.t tag ranges y]\n} -cleanup {\n    destroy .t\n} -result {{1.0 1.2 1.5 1.14} {1.2 1.5}}\ntest text-13.6 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Sample text\" {x y z}\n    list [.t tag ranges x] [.t tag ranges y] [.t tag ranges z]\n} -cleanup {\n    destroy .t\n} -result {{1.0 1.11} {1.0 1.11} {1.0 1.11}}\ntest text-13.7 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Sample text\" {x y z}\n    .t insert 1.3 \"A\" {a b z}\n    list [.t tag ranges a] [.t tag ranges b] [.t tag ranges x] [.t tag ranges y] [.t tag ranges z]\n} -cleanup {\n    destroy .t\n} -result {{1.3 1.4} {1.3 1.4} {1.0 1.3 1.4 1.12} {1.0 1.3 1.4 1.12} {1.0 1.12}}\ntest text-13.8 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"Sample text\" \"a \\{b\"\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {unmatched open brace in list}\ntest text-13.9 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"First\" bold \" \" {} second \"x y z\" \" third\"\n    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges x] \\\n\t    [.t tag ranges y] [.t tag ranges z]\n} -cleanup {\n    destroy .t\n} -result {{First second third} {1.0 1.5} {1.6 1.12} {1.6 1.12} {1.6 1.12}}\ntest text-13.10 {TextWidgetCmd procedure, \"insert\" option} -setup {\n    text .t\n} -body {\n    .t insert 1.0 \"First\" bold \" second\" silly\n    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges silly]\n} -cleanup {\n    destroy .t\n} -result {{First second} {1.0 1.5} {1.5 1.12}}\n\n# Edit, mark, scan, search, see, tag, window, xview, and yview actions are tested elsewhere.\n\ntest text-14.1 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -state foobar\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad state \"foobar\": must be disabled or normal}\ntest text-14.2 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -spacing1 -2 -spacing2 1 -spacing3 1\n    list [.t cget -spacing1] [.t cget -spacing2] [.t cget -spacing3]\n} -cleanup {\n    destroy .t\n} -returnCodes {error} -result {expected screen distance but got \"-2\"}\ntest text-14.3 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -spacing1 1 -spacing2 -1 -spacing3 1\n    list [.t cget -spacing1] [.t cget -spacing2] [.t cget -spacing3]\n} -cleanup {\n    destroy .t\n} -returnCodes {error} -result {expected screen distance but got \"-1\"}\ntest text-14.4 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -spacing1 1 -spacing2 1 -spacing3 -3\n    list [.t cget -spacing1] [.t cget -spacing2] [.t cget -spacing3]\n} -cleanup {\n    destroy .t\n} -returnCodes {error} -result {expected screen distance but got \"-3\"}\ntest text-14.5 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -tabs {30 foo}\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad tab alignment \"foo\": must be left, right, center, or numeric}\ntest text-14.6 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    catch {.t configure -tabs {30 foo}}\n    .t configure -tabs {10 20 30}\n    return $errorInfo\n} -cleanup {\n    destroy .t\n} -result {bad tab alignment \"foo\": must be left, right, center, or numeric\n    (while processing -tabs option)\n    invoked from within\n\".t configure -tabs {30 foo}\"}\ntest text-14.7 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -tabs {10 20 30}\n    .t configure -tabs {}\n    .t cget -tabs\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-14.8 {ConfigureText procedure} -setup {\n   text .t\n} -body {\n    .t configure -wrap bogus\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad wrap \"bogus\": must be char, none, or word}\ntest text-14.9 {ConfigureText procedure} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .t configure -selectborderwidth 17 -selectforeground #332211 \\\n\t    -selectbackground #abc\n    list [lindex [.t tag config sel -borderwidth] 4] \\\n\t   [lindex [.t tag config sel -foreground] 4] \\\n\t   [lindex [.t tag config sel -background] 4]\n} -cleanup {\n    destroy .t\n} -result {17 #332211 #abc}\ntest text-14.10 {ConfigureText procedure} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .t configure -selectborderwidth 0\n    .t tag cget sel -borderwidth\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-14.11 {ConfigureText procedure} -setup {\n    text .t\n} -body {\n    .t configure -selectborderwidth foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"foo\"}\ntest text-14.12 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    .t.e select to 2\n    text .t2 -exportselection 1\n    selection get\n} -cleanup {\n    destroy .t .t2\n} -result {ab}\ntest text-14.13 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    .t.e select to 2\n    text .t2 -exportselection 0\n    .t2 insert insert 1234657890\n    .t2 tag add sel 1.0 1.4\n    selection get\n} -cleanup {\n    destroy .t .t2\n} -result {ab}\ntest text-14.14 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    .t.e select to 1\n    text .t2 -exportselection 1\n    .t2 insert insert 1234657890\n    .t2 tag add sel 1.0 1.4\n    selection get\n} -cleanup {\n    destroy .t .t2\n} -result 1234\ntest text-14.15 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    .t.e select to 1\n    text .t2 -exportselection 0\n    .t2 insert insert 1234657890\n    .t2 tag add sel 1.0 1.4\n    .t2 configure -exportselection 1\n    selection get\n} -cleanup {\n    destroy .t2 .t\n} -result 1234\ntest text-14.16 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    text .t2 -exportselection 1\n    .t2 insert insert 1234657890\n    .t2 tag add sel 1.0 1.4\n    selection get\n    .t2 configure -exportselection 0\n    selection get\n} -cleanup {\n    destroy .t .t2\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest text-14.17 {ConfigureText procedure} -body {\n    text .t\n    entry .t.e\n    .t.e insert end abcdefg\n    .t.e select from 0\n    text .t2 -exportselection 1\n    .t2 insert insert 1234657890\n    .t2 tag add sel 1.0 1.4\n    set result [selection get]\n    .t2 configure -exportselection 0\n    catch {selection get}\n    return $result\n} -cleanup {\n    destroy .t .t2\n} -result 1234\ntest text-14.18 {ConfigureText procedure} -constraints fonts -setup {\n    toplevel .top\n    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .top.t configure -width 20 -height 10\n    pack .top.t\n    update\n    set geom [wm geometry .top]\n    set x [string range $geom 0 [string first + $geom]]\n} -cleanup {\n    destroy .top\n} -result {150x140+}\n\n#\n# COMMON TEST SETUP\n#\n\n# Tests text-14.19 and text-14.20 were failing on Windows because the title bar\n# on .t was a certain minimum size and it was interfering with the size requested\n# by the -setgrid. The \"overrideredirect\" gets rid of the titlebar so the\n# toplevel can shrink to the appropriate size.\n# On macOS, however, there is no way to make the window overlap the\n# menubar. Starting with macOS 15 (Sequoia) it became impossible for\n# the y coordinate of the top of a window to be less than 10 plus the\n# menubar height (as reported by [[NSApp mainMenu] menuBarHeight]).\n#\nif {[tk windowingsystem] eq \"aqua\"} {\n    set minY [expr {[testmenubarheight] + 11}]\n} else {\n    set minY 0\n}\n\ntest text-14.19 {ConfigureText procedure} -setup {\n    toplevel .top\n    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .top.t configure -width 20 -height 10 -setgrid 1\n    wm overrideredirect .top 1\n    pack .top.t\n    wm geometry .top +0+$minY\n    update\n    wm geometry .top\n} -cleanup {\n    destroy .top\n} -result \"20x10+0+$minY\"\ntest text-14.20 {ConfigureText procedure} -setup {\n    toplevel .top\n    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n} -body {\n    .top.t configure -width 20 -height 10 -setgrid 1\n    wm overrideredirect .top 1\n    pack .top.t\n    wm geometry .top +0+$minY\n    update\n    set result [wm geometry .top]\n    wm geometry .top 15x8\n    update\n    lappend result [wm geometry .top]\n    .top.t configure -wrap word\n    update\n    lappend result [wm geometry .top]\n} -cleanup {\n    destroy .top\n} -result \"20x10+0+$minY 15x8+0+$minY 15x8+0+$minY\"\n\n\ntest text-15.1 {TextWorldChanged procedure, spacing options} -constraints {\n    fonts\n} -body {\n    text .t -width 20 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    set result [winfo reqheight .t]\n    .t configure -spacing1 2\n    lappend result [winfo reqheight .t]\n    .t  configure -spacing3 1\n    lappend result [winfo reqheight .t]\n    .t configure -spacing1 0\n    lappend result [winfo reqheight .t]\n} -cleanup {\n    destroy .t\n} -result {140 160 170 150}\n\n\ntest text-16.1 {TextEventProc procedure} -body {\n    text .tx1 -bg #543210\n    rename .tx1 .tx2\n    set x {}\n    lappend x [winfo exists .tx1]\n    lappend x [.tx2 cget -bg]\n    destroy .tx1\n    lappend x [info command .tx*] [winfo exists .tx1] [winfo exists .tx2]\n} -cleanup {\n    destroy .txt1\n} -result {1 #543210 {} 0 0}\n\n\ntest text-17.1 {TextCmdDeletedProc procedure} -body {\n    text .tx1\n    rename .tx1 {}\n    list [info command .tx*] [winfo exists .tx1]\n} -cleanup {\n    destroy .txt1\n} -result {{} 0}\ntest text-17.2 {TextCmdDeletedProc procedure, disabling -setgrid} -constraints {\n    fonts\n} -body {\n   toplevel .top\n   text .top.t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} \\\n    -setgrid 1 -width 20 -height 10\n   pack .top.t\n   update\n   set geom [wm geometry .top]\n   set x [string range $geom 0 [string first + $geom]]\n   rename .top.t {}\n   update\n   set geom [wm geometry .top]\n   lappend x [string range $geom 0 [string first + $geom]]\n   return $x\n} -cleanup {\n    destroy .top\n} -result {20x10+ 150x140+}\n\n\ntest text-18.1 {InsertChars procedure} -body {\n    text .t\n    .t insert 2.0 abcd\\n\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {abcd\n\n}\ntest text-18.2 {InsertChars procedure} -body {\n    text .t\n    .t insert 1.0 abcd\\n\n    .t insert end 123\\n\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {abcd\n123\n\n}\ntest text-18.3 {InsertChars procedure} -body {\n    text .t\n    .t insert 1.0 abcd\\n\n    .t insert 10.0 123\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {abcd\n123\n}\ntest text-18.4 {InsertChars procedure, inserting on top visible line} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t\n} -body {\n    .t configure -width 20 -height 4 -wrap word\n    .t insert insert \"Now is the time for all great men to come to the \"\n    .t insert insert \"aid of their party.\\n\"\n    .t insert insert \"Now is the time for all great men.\\n\"\n    .t see end\n    update\n    .t insert 1.0 \"Short\\n\"\n    .t index @0,0\n} -cleanup {\n    destroy .t\n} -result {2.56}\ntest text-18.5 {InsertChars procedure, inserting on top visible line} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t\n} -body {\n    .t configure -width 20 -height 4 -wrap word\n    .t insert insert \"Now is the time for all great men to come to the \"\n    .t insert insert \"aid of their party.\\n\"\n    .t insert insert \"Now is the time for all great men.\\n\"\n    .t see end\n    update\n    .t insert 1.55 \"Short\\n\"\n    .t index @0,0\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-18.6 {InsertChars procedure, inserting on top visible line} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t\n} -body {\n    .t configure -width 20 -height 4 -wrap word\n    .t insert insert \"Now is the time for all great men to come to the \"\n    .t insert insert \"aid of their party.\\n\"\n    .t insert insert \"Now is the time for all great men.\\n\"\n    .t see end\n    update\n    .t insert 1.56 \"Short\\n\"\n    .t index @0,0\n} -cleanup {\n    destroy .t\n} -result {1.56}\ntest text-18.7 {InsertChars procedure, inserting on top visible line} -setup {\n    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .t\n} -body {\n    .t configure -width 20 -height 4 -wrap word\n    .t insert insert \"Now is the time for all great men to come to the \"\n    .t insert insert \"aid of their party.\\n\"\n    .t insert insert \"Now is the time for all great men.\\n\"\n    .t see end\n    update\n    .t insert 1.57 \"Short\\n\"\n    .t index @0,0\n} -cleanup {\n    destroy .t\n} -result {1.56}\n\n\ntest text-19.1 {DeleteChars procedure} -body {\n    text .t\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {\n}\ntest text-19.2 {DeleteChars procedure} -body {\n    text .t\n    .t delete foobar\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"foobar\"}\ntest text-19.3 {DeleteChars procedure} -body {\n    text .t\n    .t delete 1.0 lousy\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"lousy\"}\ntest text-19.4 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t delete 2.1\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {Line 1\nacde\n12345\nLine 4\n}\ntest text-19.5 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t delete 2.3\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {Line 1\nabce\n12345\nLine 4\n}\ntest text-19.6 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t delete 2.end\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {Line 1\nabcde12345\nLine 4\n}\ntest text-19.7 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t tag add sel 4.2 end\n    .t delete 4.2 end\n    list [.t tag ranges sel] [.t get 1.0 end]\n} -cleanup {\n    destroy .t\n} -result {{} {Line 1\nabcde\n12345\nLi\n}}\ntest text-19.8 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t tag add sel 1.0 end\n    .t delete 4.0 end\n    list [.t tag ranges sel] [.t get 1.0 end]\n} -cleanup {\n    destroy .t\n} -result {{1.0 3.5} {Line 1\nabcde\n12345\n}}\ntest text-19.9 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t delete 2.2 2.2\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {Line 1\nabcde\n12345\nLine 4\n}\ntest text-19.10 {DeleteChars procedure} -body {\n    text .t\n    .t insert 1.0 \"Line 1\nabcde\n12345\nLine 4\"\n    .t delete 2.3 2.1\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result {Line 1\nabcde\n12345\nLine 4\n}\ntest text-19.11 {DeleteChars procedure} -body {\n    toplevel .top\n    text .top.t -width 20 -height 5\n    pack .top.t\n    wm geometry .top +0+0\n    .top.t insert 1.0 \"abc\\n123\\nx\\ny\\nz\\nq\\nr\\ns\"\n    update\n    .top.t delete 1.0 3.0\n    list [.top.t index @0,0] [.top.t get @0,0]\n} -cleanup {\n    destroy .top\n} -result {1.0 x}\ntest text-19.12 {DeleteChars procedure} -body {\n    toplevel .top\n    text .top.t -width 20 -height 5\n    pack .top.t\n    wm geometry .top +0+0\n    .top.t insert 1.0 \"abc\\n123\\nx\\ny\\nz\\nq\\nr\\ns\"\n    .top.t yview 3.0\n    update\n    .top.t delete 2.0 4.0\n    list [.top.t index @0,0] [.top.t get @0,0]\n} -cleanup {\n    destroy .top\n} -result {2.0 y}\ntest text-19.13 {DeleteChars procedure, updates affecting topIndex} -setup {\n    toplevel .top\n    text .top.t -width 1 -height 10 -wrap char\n    pack .top.t -side left\n    wm geometry .top +0+0\n    update\n} -body {\n    .top.t insert end \"abcde\\n12345\\nqrstuv\"\n    .top.t yview 2.1\n    .top.t delete 1.4 2.3\n    .top.t index @0,0\n} -cleanup {\n    destroy .top\n} -result {1.2}\ntest text-19.14 {DeleteChars procedure, updates affecting topIndex} -setup {\n    toplevel .top\n    text .top.t -width 1 -height 10 -wrap char\n    pack .top.t -side left\n    wm geometry .top +0+0\n    update\n} -body {\n    .top.t insert end \"abcde\\n12345\\nqrstuv\"\n    .top.t yview 2.1\n    .top.t delete 2.3 2.4\n    .top.t index @0,0\n} -cleanup {\n    destroy .top\n} -result {2.0}\ntest text-19.15 {DeleteChars procedure, updates affecting topIndex} -setup {\n    toplevel .top\n    text .top.t -width 1 -height 10 -wrap char\n    pack .top.t -side left\n    wm geometry .top +0+0\n    update\n} -body {\n    .top.t insert end \"abcde\\n12345\\nqrstuv\"\n    .top.t yview 1.3\n    .top.t delete 1.0 1.2\n    .top.t index @0,0\n} -cleanup {\n    destroy .top\n} -result {1.1}\ntest text-19.16 {DeleteChars procedure, updates affecting topIndex} -setup {\n    toplevel .top\n    text .top.t -width 6 -height 10 -wrap word\n    frame .top.f -width 200 -height 20 -relief raised -bd 2\n    pack .top.f .top.t -side left\n    wm geometry .top +0+0\n    update\n} -body {\n    .top.t insert end \"abc def\\n01 2a345 678 9101112\\nLine 3\\nLine 4\\nLine 5\\n6\\n7\\n8\\n\"\n    .top.t yview 2.4\n    .top.t delete 2.5\n    set x [.top.t index @0,0]\n    .top.t delete 2.5\n    list $x [.top.t index @0,0]\n} -cleanup {\n    destroy .top\n} -result {2.3 2.0}\n\n\ntest text-20.1 {TextFetchSelection procedure} -setup {\n    text .t -width 20 -height 10\n    pack .t -expand 1 -fill both\n    update\n} -body {\n    foreach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {\n\t.t insert end $i.0$i.1$i.2$i.3$i.4\\n\n    }\n    .t tag add sel 1.3 3.4\n    selection get\n} -cleanup {\n    destroy .t\n} -result {a.1a.2a.3a.4\nb.0b.1b.2b.3b.4\nc.0c}\ntest text-20.2 {TextFetchSelection procedure} -setup {\n    text .t -width 20 -height 10\n    pack .t -expand 1 -fill both\n    update\n} -body {\n    foreach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {\n\t.t insert end $i.0$i.1$i.2$i.3$i.4\\n\n    }\n    .t tag add x 1.2\n    .t tag add x 1.4\n    .t tag add x 2.0\n    .t tag add x 2.3\n    .t tag remove sel 1.0 end\n    .t tag add sel 1.0 3.4\n    selection get\n} -cleanup {\n    destroy .t\n} -result {a.0a.1a.2a.3a.4\nb.0b.1b.2b.3b.4\nc.0c}\ntest text-20.3 {TextFetchSelection procedure}  -setup {\n    text .t -width 20 -height 10\n    pack .t -expand 1 -fill both\n    update\n} -body {\n    foreach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {\n\t.t insert end $i.0$i.1$i.2$i.3$i.4\\n\n    }\n    .t tag remove sel 1.0 end\n    .t tag add sel 13.3\n    selection get\n} -cleanup {\n    destroy .t\n} -result {m}\ntest text-20.4 {TextFetchSelection procedure}  -setup {\n    text .t -width 20 -height 10\n    pack .t -expand 1 -fill both\n    update\n} -body {\n    foreach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {\n\t.t insert end $i.0$i.1$i.2$i.3$i.4\\n\n    }\n    .t tag remove x 1.0 end\n    .t tag add sel 1.0 3.4\n    .t tag remove sel 1.0 end\n    .t tag add sel 1.2 1.5\n    .t tag add sel 2.4 3.1\n    .t tag add sel 10.0 10.end\n    .t tag add sel 13.3\n    selection get\n} -cleanup {\n    destroy .t\n} -result {0a..1b.2b.3b.4\ncj.0j.1j.2j.3j.4m}\ntest text-20.5 {TextFetchSelection procedure, long selections} -setup {\n    text .t -width 20 -height 10\n    pack .t -expand 1 -fill both\n    update\n    set x \"\"\n} -body {\n    for {set i 1} {$i < 200} {incr i} {\n\tappend x \"This is line $i, padded to just about 53 characters.\\n\"\n    }\n    .t insert end $x\n    .t tag add sel 1.0 end\n    expr {[selection get] eq \"$x\\n\"}\n} -cleanup {\n    destroy .t\n} -result 1\n\n\ntest text-21.1 {TkTextLostSelection procedure} -constraints {x11} -setup {\n    text .t\n    .t insert 1.0 \"Line 1\"\n    entry .t.e\n    .t.e insert end \"abcdefg\"\n    text .t2\n    .t2 insert 1.0 \"abc\\ndef\\nghijk\\n1234\"\n} -body {\n    .t2 tag add sel 1.2 3.3\n    .t.e select from 0\n    .t.e select to 1\n    .t2 tag ranges sel\n} -cleanup {\n    destroy .t .t2\n} -result {}\ntest text-21.2 {TkTextLostSelection procedure} -constraints aquaOrWin32 -setup {\n    text .t\n    .t insert 1.0 \"Line 1\"\n    entry .t.e\n    .t.e insert end \"abcdefg\"\n    text .t2\n    .t2 insert 1.0 \"abc\\ndef\\nghijk\\n1234\"\n} -body {\n    .t2 tag add sel 1.2 3.3\n    .t.e select from 0\n    .t.e select to 1\n    .t2 tag ranges sel\n} -cleanup {\n    destroy .t .t2\n} -result {1.2 3.3}\ntest text-21.3 {TkTextLostSelection procedure} -body {\n    text .t\n    .t insert 1.0 \"abcdef\\nghijk\\n1234\"\n    .t tag add sel 1.0 1.3\n    selection get\n    selection clear\n    selection get\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {PRIMARY selection doesn't exist or form \"STRING\" not defined}\ntest text-21.4 {TkTextLostSelection procedure} -body {\n    text .t\n    .t insert 1.0 \"abcdef\\nghijk\\n1234\"\n    .t tag add sel 1.0 1.3\n    set x [selection get]\n    selection clear\n    catch {selection get}\n    .t tag add sel 1.0 1.3\n    lappend x [selection get]\n} -cleanup {\n    destroy .t\n} -result {abc abc}\n\n\ntest text-22.1 {TextSearchCmd procedure, argument parsing} -body {\n    text .t\n    .t search -\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous switch \"-\": must be --, -all, -backwards, -count, -elide, -exact, -forwards, -nocase, -nolinestop, -overlap, -regexp, or -strictlimits}\ntest text-22.2 {TextSearchCmd procedure, -backwards option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards xyz 1.4\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.3 {TextSearchCmd procedure, -all option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -all xyz 1.4\n} -cleanup {\n    destroy .t\n} -result {1.5 3.0 3.5 1.1}\ntest text-22.4 {TextSearchCmd procedure, -forwards option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -forwards xyz 1.4\n} -cleanup {\n    destroy .t\n} -result {1.5}\ntest text-22.5 {TextSearchCmd procedure, -exact option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -f -exact x. 1.0\n} -cleanup {\n    destroy .t\n} -result {1.9}\ntest text-22.6 {TextSearchCmd procedure, -regexp option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -b -regexp x.z 1.4\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.7 {TextSearchCmd procedure, -count option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    set length unmodified\n    list [.t search -count length x. 1.4] $length\n} -cleanup {\n    destroy .t\n} -result {1.9 2}\ntest text-22.8 {TextSearchCmd procedure, -count option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -count\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {no value given for \"-count\" option}\ntest text-22.9 {TextSearchCmd procedure, -nocase option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search -nocase BaR 1.1] [.t search BaR 1.1]\n} -cleanup {\n    destroy .t\n} -result {2.13 2.23}\ntest text-22.10 {TextSearchCmd procedure, -n ambiguous option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -n BaR 1.1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous switch \"-n\": must be --, -all, -backwards, -count, -elide, -exact, -forwards, -nocase, -nolinestop, -overlap, -regexp, or -strictlimits}\ntest text-22.11 {TextSearchCmd procedure, -nocase option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -noc BaR 1.1\n} -cleanup {\n    destroy .t\n} -result {2.13}\ntest text-22.12 {TextSearchCmd procedure, -nolinestop option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -nolinestop BaR 1.1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {the \"-nolinestop\" option requires the \"-regexp\" option to be present}\ntest text-22.13 {TextSearchCmd procedure, -nolinestop option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    set msg \"\"\n    list [.t search -nolinestop -regexp -count msg e.*o 1.1] $msg\n} -cleanup {\n    destroy .t\n} -result {1.14 32}\ntest text-22.14 {TextSearchCmd procedure, -- option} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -- -forward 1.0\n} -cleanup {\n    destroy .t\n} -result {2.4}\ntest text-22.15 {TextSearchCmd procedure, argument parsing} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search abc\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t search ?switches? pattern index ?stopIndex?\"}\ntest text-22.16 {TextSearchCmd procedure, argument parsing} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search abc d e f\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t search ?switches? pattern index ?stopIndex?\"}\ntest text-22.17 {TextSearchCmd procedure, check index} -body {\n    text .t\n    .t search abc gorp\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"gorp\"}\ntest text-22.18 {TextSearchCmd procedure, startIndex == \"end\"} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search non-existent end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.19 {TextSearchCmd procedure, startIndex == \"end\"} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search non-existent end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.20 {TextSearchCmd procedure, bad stopIndex} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search abc 1.0 lousy\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"lousy\"}\ntest text-22.21 {TextSearchCmd procedure, pattern case conversion} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search -nocase BAR 1.1] [.t search BAR 1.1]\n} -cleanup {\n    destroy .t\n} -result {2.13 {}}\ntest text-22.22 {TextSearchCmd procedure, bad regular expression pattern} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -regexp a( 1.0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {cannot compile regular expression pattern: parentheses () not balanced}\ntest text-22.23 {TextSearchCmd procedure, skip dummy last line} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards BaR end 1.0\n} -cleanup {\n    destroy .t\n} -result {2.23}\ntest text-22.24 {TextSearchCmd procedure, skip dummy last line} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards \\n end 1.0\n} -cleanup {\n    destroy .t\n} -result {3.9}\ntest text-22.25 {TextSearchCmd procedure, skip dummy last line} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search \\n end\n} -cleanup {\n    destroy .t\n} -result {1.15}\ntest text-22.26 {TextSearchCmd procedure, skip dummy last line} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -back \\n 1.0\n} -cleanup {\n    destroy .t\n} -result {3.9}\ntest text-22.27 {TextSearchCmd procedure, extract line contents} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t tag add foo 1.2\n    .t tag add x 1.3\n    .t mark set silly 1.2\n    .t search xyz 3.6\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.28 {TextSearchCmd procedure, stripping newlines} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search the\\n 1.0\n} -cleanup {\n    destroy .t\n} -result {1.12}\ntest text-22.29 {TextSearchCmd procedure, handling newlines} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -regexp the\\n 1.0\n} -cleanup {\n    destroy .t\n} -result {1.12}\ntest text-22.30 {TextSearchCmd procedure, stripping newlines} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -regexp {the$} 1.0\n} -cleanup {\n    destroy .t\n} -result {1.12}\ntest text-22.31 {TextSearchCmd procedure, handling newlines} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -regexp \\n 1.0\n} -cleanup {\n    destroy .t\n} -result {1.15}\ntest text-22.32 {TextSearchCmd procedure, line case conversion} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search -nocase bar 2.18] [.t search bar 2.18]\n} -cleanup {\n    destroy .t\n} -result {2.23 2.13}\ntest text-22.33 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards xyz 1.6\n} -cleanup {\n    destroy .t\n} -result {1.5}\ntest text-22.34 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards xyz 1.5\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.35 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search xyz 1.5\n} -cleanup {\n    destroy .t\n} -result {1.5}\ntest text-22.36 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search xyz 1.6\n} -cleanup {\n    destroy .t\n} -result {3.0}\ntest text-22.37 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search {} 1.end\n} -cleanup {\n    destroy .t\n} -result {1.15}\ntest text-22.38 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search f 1.end\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.39 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search {} end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.40 {TextSearchCmd procedure, regexp finds empty lines} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n# Test for fix of bug #1643\n    .t insert end \"\\n\"\n    tk::TextSetCursor .t 4.0\n    .t search -forward -regexp {^$} insert end\n} -cleanup {\n    destroy .t\n} -result {4.0}\ntest text-22.41 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search his 2.6\n} -cleanup {\n    destroy .top\n} -result {2.6}\ntest text-22.42 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search this 2.6\n} -cleanup {\n    destroy .top\n} -result {3.4}\ntest text-22.43 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search is 2.6\n} -cleanup {\n    destroy .top\n} -result {2.7}\ntest text-22.44 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search his 2.7\n} -cleanup {\n    destroy .top\n} -result {3.5}\ntest text-22.45 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search -backwards \"his is another\" 2.6\n} -cleanup {\n    destroy .top\n} -result {2.6}\ntest text-22.46 {TextSearchCmd procedure, firstChar and lastChar} -setup {\n    toplevel .top\n    text .top.t -width 30 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2\n    pack .top.t\n} -body {\n    .top.t insert 1.0 \"This is a line\\nand this is another\"\n    .top.t insert end \"\\nand this is yet another\"\n    frame .top.f -width 20 -height 20 -bd 2 -relief raised\n    .top.t window create 2.5 -window .top.f\n    .top.t search -backwards \"his is\" 2.6\n} -cleanup {\n    destroy .top\n} -result {1.1}\ntest text-22.47 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards forw 2.5\n} -cleanup {\n    destroy .t\n} -result {2.5}\ntest text-22.48 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search forw 2.5\n} -cleanup {\n    destroy .t\n} -result {2.5}\ntest text-22.49 {TextSearchCmd procedure, firstChar and lastChar} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    catch {destroy .t}\n    text .t2\n    list [.t2 search a 1.0] [.t2 search -backward a 1.0]\n} -cleanup {\n    destroy .t .t2\n} -result {{} {}}\ntest text-22.50 {TextSearchCmd procedure, regexp match length} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    set length unchanged\n    list [.t search -regexp -count length x(.)(.*)z 1.1] $length\n} -cleanup {\n    destroy .t\n} -result {1.1 7}\ntest text-22.51 {TextSearchCmd procedure, regexp match length} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    set length unchanged\n    list [.t search -regexp -backward -count length fo* 2.5] $length\n} -cleanup {\n    destroy .t\n} -result {2.0 3}\ntest text-22.52 {TextSearchCmd procedure, checking stopIndex} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search bar 2.1 2.13] [.t search bar 2.1 2.14] \\\n\t    [.t search bar 2.12 2.14] [.t search bar 2.14 2.14]\n} -cleanup {\n    destroy .t\n} -result {{} 2.13 2.13 {}}\ntest text-22.53 {TextSearchCmd procedure, checking stopIndex} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search -backwards bar 2.20 2.13] \\\n      [.t search -backwards bar 2.20 2.14] \\\n      [.t search -backwards bar 2.14 2.13] \\\n      [.t search -backwards bar 2.13 2.13]\n} -cleanup {\n    destroy .t\n} -result {2.13 {} 2.13 {}}\ntest text-22.54 {TextSearchCmd procedure, checking stopIndex} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    list [.t search -backwards -strict bar 2.20 2.13] \\\n      [.t search -backwards -strict bar 2.20 2.14] \\\n      [.t search -backwards -strict bar 2.14 2.13] \\\n      [.t search -backwards -strict bar 2.13 2.13]\n} -cleanup {\n    destroy .t\n} -result {2.13 {} {} {}}\ntest text-22.55 {TextSearchCmd procedure, embedded windows and index/count} -setup {\n    text .t\n    frame .t.f1 -width 20 -height 20 -relief raised -bd 2\n    frame .t.f2 -width 20 -height 20 -relief raised -bd 2\n    frame .t.f3 -width 20 -height 20 -relief raised -bd 2\n    frame .t.f4 -width 20 -height 20 -relief raised -bd 2\n    set result \"\"\n} -body {\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t window create 2.10 -window .t.f3\n    .t window create 2.8 -window .t.f2\n    .t window create 2.8 -window .t.f1\n    .t window create 2.1 -window .t.f4\n    lappend result [.t search -count x forward 1.0] $x\n    lappend result [.t search -count x wa 1.0] $x\n    return $result\n} -cleanup {\n    destroy .t\n} -result {2.6 10 2.11 2}\ntest text-22.56 {TextSearchCmd procedure, error setting variable} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    set a 44\n    .t search -count a(2) xyz 1.0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {can't set \"a(2)\": variable isn't array}\ntest text-22.57 {TextSearchCmd procedure, wrap-around} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards xyz 1.1\n} -cleanup {\n    destroy .t\n} -result {3.5}\ntest text-22.58 {TextSearchCmd procedure, wrap-around} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -backwards xyz 1.1 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.59 {TextSearchCmd procedure, wrap-around} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search xyz 3.6\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.60 {TextSearchCmd procedure, wrap-around} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search xyz 3.6 end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.61 {TextSearchCmd procedure, no match} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search non_existent 3.5\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.62 {TextSearchCmd procedure, no match} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -regexp non_existent 3.5\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.63 {TextSearchCmd procedure, special cases} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -back x 1.1\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.64 {TextSearchCmd procedure, special cases} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search -back x 1.0\n} -cleanup {\n    destroy .t\n} -result {3.8}\ntest text-22.65 {TextSearchCmd procedure, special cases} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search \\n {end-2c}\n} -cleanup {\n    destroy .t\n} -result {3.9}\ntest text-22.66 {TextSearchCmd procedure, special cases} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search \\n end\n} -cleanup {\n    destroy .t\n} -result {1.15}\ntest text-22.67 {TextSearchCmd procedure, special cases} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n    .t search x 1.0\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.68 {TextSearchCmd, freeing copy of pattern} -body {\n    text .t\n    .t insert end \"xxyz xyz x. the\\nfoo -forward bar xxxxx BaR foo\\nxyz xxyzx\"\n# This test doesn't return a result, but it will generate\n# a core leak if the pattern copy isn't properly freed.\n# (actually in Tk 8.5 objectification means there is no\n# longer a copy of the pattern, but we leave this test in\n# anyway).\n    set p abcdefg1234567890\n    set p $p$p$p$p$p$p$p$p\n    set p $p$p$p$p$p\n    .t search -nocase $p 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.69 {TextSearchCmd, unicode} -body {\n    text .t\n    .t insert end \"fooドナbar\"\n    .t search ドナ 1.0\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.70 {TextSearchCmd, unicode} -body {\n    text .t\n    .t insert end \"fooドナbar\"\n    list [.t search -count n ドナ 1.0] $n\n} -cleanup {\n    destroy .t\n} -result {1.3 2}\ntest text-22.71 {TextSearchCmd, unicode with non-text segments} -body {\n    text .t\n    button .b1 -text baz\n    .t insert end \"fooド\"\n    .t window create end -window .b1\n    .t insert end \"ナbar\"\n    list [.t search -count n ドナ 1.0] $n\n} -cleanup {\n    destroy .t .b1\n} -result {1.3 3}\ntest text-22.72 {TextSearchCmd, hidden text does not affect match index} -body {\n    pack [text .t]\n    .t insert end \"12345H7890\"\n    .t search 7 1.0\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.73 {TextSearchCmd, hidden text does not affect match index} -body {\n    pack [text .t]\n    .t insert end \"12345H7890\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.5\n    .t search 7 1.0\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.74 {TextSearchCmd, hidden text does not affect match index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nbarbaz\\nbazboo\"\n    .t search boo 1.0\n} -cleanup {\n    destroy .t\n} -result {3.3}\ntest text-22.75 {TextSearchCmd, hidden text does not affect match index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nbarbaz\\nbazboo\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 2.0 3.0\n    .t search boo 1.0\n} -cleanup {\n    destroy .t\n} -result {3.3}\ntest text-22.76 {TextSearchCmd, -regexp -nocase searches} -body {\n    pack [text .t]\n    .t insert end \"word1 word2\"\n    .t search -nocase -regexp {\\mword.} 1.0 end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.77 {TextSearchCmd, -regexp -nocase searches} -body {\n    pack [text .t]\n    .t insert end \"word1 word2\"\n    .t search -nocase -regexp {word.\\M} 1.0 end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.78 {TextSearchCmd, -regexp -nocase searches} -body {\n    pack [text .t]\n    .t insert end \"word1 word2\"\n    .t search -nocase -regexp {word.\\W} 1.0 end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.79 {TextSearchCmd, hidden text and start index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search bar 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.80 {TextSearchCmd, hidden text shouldn't influence start index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.0 1.2\n    .t search bar 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.81 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    list [.t search -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 6}\ntest text-22.82 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    list \\\n      [.t search -strict -count foo foar 1.3] \\\n      [.t search -strict -count foo foar 2.3] $foo\n} -cleanup {\n    destroy .t\n} -result {{} 1.0 6}\ntest text-22.83 {TextSearchCmd, hidden text and start index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -regexp bar 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.84 {TextSearchCmd, hidden text shouldn't influence start index} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.0 1.2\n    .t search -regexp bar 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.85 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    list [.t search -regexp -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 6}\ntest text-22.86 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    list [.t search -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 6}\ntest text-22.87 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    .t search -strict -count foo foar 1.3\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.88 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    .t tag add hidden 2.2 2.4\n    list [.t search -regexp -all -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {{2.0 3.0 1.0} {6 4 6}}\ntest text-22.89 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    .t tag add hidden 2.2 2.4\n    list [.t search -all -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {{2.0 3.0 1.0} {6 4 6}}\ntest text-22.90 {TextSearchCmd, hidden text inside match must count in length} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoar\"\n    .t tag configure hidden -elide true\n    .t tag add hidden 1.2 1.4\n    .t tag add hidden 2.2 2.4\n    list [.t search -strict -all -count foo foar 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {{2.0 3.0} {6 4}}\ntest text-22.91 {TextSearchCmd, single line with -all} -body {\n    pack [text .t]\n    .t insert end \" X\\n X\\n X\\n X\\n X\\n X\\n\"\n    .t search -all -regexp { +| *\\n} 1.0 end\n} -cleanup {\n    destroy .t\n} -result {1.0 1.2 2.0 2.2 3.0 3.2 4.0 4.2 5.0 5.2 6.0 6.2 7.0}\ntest text-22.92 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -count foo foobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 10}\ntest text-22.93 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -count foo bar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 7}\ntest text-22.94 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -count foo \\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.6 4}\ntest text-22.95 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -count foo bar\\nfoobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 14}\ntest text-22.96 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -count foo bar\\nfoobar\\nfoobanearly 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.97 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -regexp -count foo foobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 10}\ntest text-22.98 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -regexp -count foo bar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 7}\ntest text-22.99 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -regexp -count foo \\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.6 4}\ntest text-22.100 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -regexp -count foo bar\\nfoobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 14}\ntest text-22.101 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -regexp -count foo bar\\nfoobar\\nfoobanearly 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.102 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfaoobar\\nfoobar\"\n    .t search -regexp -count foo bar\\nfoo 1.0\n} -cleanup {\n    destroy .t\n} -result {2.4}\ntest text-22.103 {TextSearchCmd, multiline matching end of window} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfaoobar\\nfoobar\"\n    .t search -regexp -count foo bar\\nfoobar\\n\\n 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.104 {TextSearchCmd, multiline matching end of window} -body {\n    pack [text .t]\n    .t search \"\\n\\n\" 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.105 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -count foo foobar\\nfoo end] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 10}\ntest text-22.106 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -count foo bar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.3 7}\ntest text-22.107 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -count foo \\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.6 4}\ntest text-22.108 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -count foo bar\\nfoobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 14}\ntest text-22.109 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -backwards -count foo bar\\nfoobar\\nfoobanearly 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.110 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -regexp -count foo foobar\\nfoo end] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 10}\ntest text-22.111 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -regexp -count foo foobar\\nfo end] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 9}\ntest text-22.112 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -regexp -count foo bar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.3 7}\ntest text-22.113 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -regexp -count foo \\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.6 4}\ntest text-22.114 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    list [.t search -backwards -regexp -count foo bar\\nfoobar\\nfoo 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 14}\ntest text-22.115 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -backwards -regexp -count foo bar\\nfoobar\\nfoobanearly 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.116 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfaoobar\\nfoobar\"\n    .t search -backwards -regexp -count foo bar\\nfoo 1.0\n} -cleanup {\n    destroy .t\n} -result {2.4}\ntest text-22.117 {TextSearchCmd, multiline matching end of window} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfaoobar\\nfoobar\"\n    .t search -backwards -regexp -count foo bar\\nfoobar\\n\\n 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.118 {TextSearchCmd, multiline matching end of window} -body {\n    pack [text .t]\n    .t search -backwards \"\\n\\n\" 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.119 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 {    Tcl_Obj *objPtr));\nstatic Tcl_Obj*         FSNormalizeAbsolutePath\n\t\t\t    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}\n    set markExpr \"^(\\[A-Za-z0-9~_\\]+\\[ \\t\\n\\r\\]*\\\\(|(\\[^ \\t\\(#\\n\\r/@:\\*\\]\\[^=\\(\\r\\n\\]*\\[ \\t\\]+\\\\*?)?\"\n    append markExpr \"(\\[A-Za-z0-9~_\\]+(<\\[^>\\]*>)?(::)?(\\[A-Za-z0-9~_\\]+::)*\\[-A-Za-z0-9~_+ <>\\|\\\\*/\\]+|\\[A-Za-z0-9~_\\]+)\"\n    append markExpr \"\\[ \\n\\t\\r\\]*\\\\()\"\n    .t search -forwards -regexp $markExpr 1.41 end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.120 {TextSearchCmd, multiline regexp matching} -body {\n# Practical example which used to crash Tk, but only after the\n# search is complete.  This is memory corruption caused by\n# a bug in Tcl's handling of string objects.\n# (Tcl bug 635200)\n    pack [text .t]\n    .t insert 1.0 {static int\t\tSetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *objPtr));\nstatic Tcl_Obj*         FSNormalizeAbsolutePath\n\t\t\t    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}\n    set markExpr \"^(\\[A-Za-z0-9~_\\]+\\[ \\t\\n\\r\\]*\\\\(|(\\[^ \\t\\(#\\n\\r/@:\\*\\]\\[^=\\(\\r\\n\\]*\\[ \\t\\]+\\\\*?)?\"\n    append markExpr \"(\\[A-Za-z0-9~_\\]+(<\\[^>\\]*>)?(::)?(\\[A-Za-z0-9~_\\]+::)*\\[-A-Za-z0-9~_+ <>\\|\\\\*/\\]+|\\[A-Za-z0-9~_\\]+)\"\n    append markExpr \"\\[ \\n\\t\\r\\]*\\\\()\"\n    .t search -forwards -regexp $markExpr 1.41 end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.121 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 {\nstatic int\t\tSetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *objPtr));\nstatic Tcl_Obj*         FSNormalizeAbsolutePath\n\t\t\t    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}\n    set markExpr \"^(\\[A-Za-z0-9~_\\]+\\[ \\t\\n\\r\\]*\\\\(|(\\[^ \\t\\(#\\n\\r/@:\\*\\]\\[^=\\(\\r\\n\\]*\\[ \\t\\]+\\\\*?)?\"\n    append markExpr \"(\\[A-Za-z0-9~_\\]+(<\\[^>\\]*>)?(::)?(\\[A-Za-z0-9~_\\]+::)*\\[-A-Za-z0-9~_+ <>\\|\\\\*/\\]+|\\[A-Za-z0-9~_\\]+)\"\n    append markExpr \"\\[ \\n\\t\\r\\]*\\\\()\"\n    .t search -backwards -all -regexp $markExpr end\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.122 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -all -regexp -count foo bar\\nfoo 1.0\n} -cleanup {\n    destroy .t\n} -result {1.3 2.3}\ntest text-22.123 {TextSearchCmd, multiline matching} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -all -backwards -regexp -count foo bar\\nfoo 1.0\n} -cleanup {\n    destroy .t\n} -result {2.3 1.3}\ntest text-22.124 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -- \"blah\" 3.3 1.3\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.125 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"foobar\\nfoobar\\nfoobar\"\n    .t search -backwards -- \"blah\" 1.3 3.3\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.126 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -backwards -regexp -- \"\\[\\]\\\")\\}\\[(\\{\\]\" \"1.32\" 1.0\n} -cleanup {\n    destroy .t\n} -result {1.31}\ntest text-22.127 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -regexp -- \"\\[\\]\\\")\\}\\[(\\{\\]\" 1.30 \"1.0 lineend\"\n} -cleanup {\n    destroy .t\n} -result {1.31}\ntest text-22.128 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -backwards -all -regexp -- \"\\[\\]\\\")\\}\\[(\\{\\]\" \"1.32\" 1.0\n} -cleanup {\n    destroy .t\n} -result {1.31 1.29 1.3}\ntest text-22.129 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -all -regexp -- \"\\[\\]\\\")\\}\\[(\\{\\]\" 1.0 \"1.0 lineend\"\n} -cleanup {\n    destroy .t\n} -result {1.3 1.29 1.31}\ntest text-22.130 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -backwards -- \"\\{\" \"1.32\" 1.0\n} -cleanup {\n    destroy .t\n} -result {1.31}\ntest text-22.131 {TextSearchCmd, wrapping and limits} -body {\n    pack [text .t]\n    .t insert end \"if (stringPtr->uallocated > 0) \\{x\"\n    .t search -- \"\\{\" 1.30 \"1.0 lineend\"\n} -cleanup {\n    destroy .t\n} -result {1.31}\ntest text-22.132 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 {\n\nvoid\nTcl_SetObjLength(objPtr, length)\n    Tcl_Obj *objPtr;\t\t/* Pointer to object.  This object must\n\t\t\t\t * not currently be shared. */\n    int length;\t\t\t/* Number of bytes desired for string\n\t\t\t\t * representation of object, not including\n\t\t\t\t * terminating null byte. */\n\\{\n    char *new;\n}\n    set markExpr \"^(\\[A-Za-z0-9~_\\]+\\[ \\t\\n\\r\\]*\\\\(|(\\[^ \\t\\(#\\n\\r/@:\\*\\]\\[^=\\(\\r\\n\\]*\\[ \\t\\]+\\\\*?)?\"\n    append markExpr \"(\\[A-Za-z0-9~_\\]+(<\\[^>\\]*>)?(::)?(\\[A-Za-z0-9~_\\]+::)*\\[-A-Za-z0-9~_+ <>\\|\\\\*/\\]+|\\[A-Za-z0-9~_\\]+)\"\n    append markExpr \"\\[ \\n\\t\\r\\]*\\\\()\"\n    .t search -all -regexp -- $markExpr 1.0\n} -cleanup {\n    destroy .t\n} -result {4.0}\ntest text-22.133 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    set markExpr {^[a-z]+}\n# This should not match, and should not wrap\n    .t search -regexp -- $markExpr end end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.134 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    set markExpr {^[a-z]+}\n# This should not match, and should not wrap\n    .t search -regexp -- $markExpr end+10c end\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.135 {TextSearchCmd, multiline regexp matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    set markExpr {^[a-z]+}\n# This should not match, and should not wrap\n    .t search -regexp -backwards -- $markExpr 1.0 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.136 {TextSearchCmd, regexp linestop} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    .t search -regexp -- {i.*x} 1.0\n} -cleanup {\n    destroy .t\n} -result {2.6}\ntest text-22.137 {TextSearchCmd, multiline regexp nolinestop matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    .t search -regexp -nolinestop -- {i.*x} 1.0\n} -cleanup {\n    destroy .t\n} -result {1.1}\ntest text-22.138 {TextSearchCmd, regexp linestop} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    .t search -regexp -all -overlap -- {i.*x} 1.0\n} -cleanup {\n    destroy .t\n} -result {2.6}\ntest text-22.139 {TextSearchCmd, regexp linestop} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    .t search -regexp -all -- {i.*x} 1.0\n} -cleanup {\n    destroy .t\n} -result {2.6}\ntest text-22.140 {TextSearchCmd, multiline regexp nolinestop matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    list [.t search -regexp -all -overlap -count c -nolinestop -- {i.*x} 1.0] $c\n} -cleanup {\n    destroy .t\n} -result {{1.1 2.6} {26 10}}\ntest text-22.141 {TextSearchCmd, multiline regexp nolinestop matching} -body {\n    pack [text .t]\n    .t insert 1.0 \"first line\\nlast line of text\"\n    list [.t search -regexp -all -count c -nolinestop -- {i.*x} 1.0] $c\n} -cleanup {\n    destroy .t\n} -result {1.1 26}\ntest text-22.142 {TextSearchCmd, stop at end of line} -body {\n    pack [text .t]\n    .t insert 1.0 \"  \\t\\n   last line of text\"\n    .t search -regexp -nolinestop -- {[^ \\t]} 1.0\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.143 {TextSearchCmd, overlapping all matches} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde abcde\"\n    list [.t search -regexp -all -overlap -count c -- {\\w+} 1.0] $c\n} -cleanup {\n    destroy .t\n} -result {{1.0 1.6} {5 5}}\ntest text-22.144 {TextSearchCmd, non-overlapping all matches} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde abcde\"\n    list [.t search -regexp -all -count c -- {\\w+} 1.0] $c\n} -cleanup {\n    destroy .t\n} -result {{1.0 1.6} {5 5}}\ntest text-22.145 {TextSearchCmd, stop at end of line} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde abcde\"\n    list [.t search -backwards -regexp -all -count c -- {\\w+} 1.0] $c\n} -cleanup {\n    destroy .t\n} -result {{1.6 1.0} {5 5}}\ntest text-22.146 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -regexp -count c -- {Z\\w+} 1.21 1.5] $c\n} -cleanup {\n    destroy .t\n} -result {1.8 8}\ntest text-22.147 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -all -overlap -regexp -count c -- {Z\\w+} 1.21 1.5] $c\n} -cleanup {\n    destroy .t\n} -result {1.8 8}\ntest text-22.148 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -all -regexp -count c -- {Z\\w+} 1.21 1.5] $c\n} -cleanup {\n    destroy .t\n} -result {1.8 8}\ntest text-22.149 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -overlap -all -regexp -count c -- {Z\\w+} 1.21 1.1] $c\n} -cleanup {\n    destroy .t\n} -result {1.4 12}\ntest text-22.150 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -overlap -all -regexp -count c -- {Z[^Z]+Z} 1.21 1.1] $c\n} -cleanup {\n    destroy .t\n} -result {{1.8 1.4} {5 5}}\ntest text-22.151 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    list [.t search -backwards -all -regexp -count c -- {Z\\w+} 1.21 1.1] $c\n} -cleanup {\n    destroy .t\n} -result {1.4 12}\ntest text-22.152 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\\n\"\n    list [.t search -backwards -all -overlap -regexp -count c -- {Z\\w+} 2.21 1.5] $c\n} -cleanup {\n    destroy .t\n} -result {{2.4 1.8} {12 8}}\ntest text-22.153 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\\n\"\n    list [.t search -backwards -all -regexp -count c -- {Z\\w+} 2.21 1.5] $c\n} -cleanup {\n    destroy .t\n} -result {{2.4 1.8} {12 8}}\ntest text-22.154 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\\n\"\n    list [.t search -backwards -overlap -all -regexp -count c -- {Z\\w+} 2.21 1.1] $c\n} -cleanup {\n    destroy .t\n} -result {{2.4 1.4} {12 12}}\ntest text-22.155 {TextSearchCmd, backwards search stop index } -body {\n    pack [text .t]\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\"\n    .t insert 1.0 \"bla ZabcZdefZghi and some text again\\n\"\n    list [.t search -backwards -all -regexp -count c -- {Z\\w+} 2.21 1.1] $c\n} -cleanup {\n    destroy .t\n} -result {{2.4 1.4} {12 12}}\ntest text-22.156 {TextSearchCmd, search -all example} -body {\n    pack [text .t]\n    .t insert 1.0 {\n\nSee the package: supersearch for more information.\n\n\nSee the package: incrementalSearch for more information.\n\npackage: Brws .\n\n\nSee the package: marks for more information.\n\n}\n    set pat {package: ([a-zA-Z0-9][-a-zA-Z0-9._+#/]*)}\n    list [.t search -nolinestop -regexp -nocase -all -forwards \\\n      -count c -- $pat 1.0 end] $c\n} -cleanup {\n    destroy .t\n} -result {{3.8 6.8 8.0 11.8} {20 26 13 14}}\ntest text-22.157 {TextSearchCmd, backwards search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foobarfoobaaaaaaaaaaarfoo\"\n    .t search -backwards -regexp {fooba+rfoo} end\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.158 {TextSearchCmd, backwards search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foobarfoobaaaaaaaaaaarfoo\"\n    .t search -backwards -overlap -all -regexp {fooba+rfoo} end\n} -cleanup {\n    destroy .t\n} -result {1.6 1.0}\ntest text-22.159 {TextSearchCmd, backwards search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foobarfoobaaaaaaaaaaarfoo\"\n    .t search -backwards -all -regexp {fooba+rfoo} end\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.160 {TextSearchCmd, forwards search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foobarfoobaaaaaaaaaaarfoo\"\n    .t search -all -overlap -regexp {fooba+rfoo} end\n} -cleanup {\n    destroy .t\n} -result {1.0 1.6}\ntest text-22.161 {TextSearchCmd, forwards search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foobarfoobaaaaaaaaaaarfoo\"\n    .t search -all -regexp {fooba+rfoo} end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.162 {TextSearchCmd, forward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abababab\"\n    .t search -exact -overlap -all {abab} 1.0\n} -cleanup {\n    destroy .t\n} -result {1.0 1.2 1.4}\ntest text-22.163 {TextSearchCmd, forward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abababab\"\n    .t search -exact -all {abab} 1.0\n} -cleanup {\n    destroy .t\n} -result {1.0 1.4}\ntest text-22.164 {TextSearchCmd, backward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"ababababab\"\n    .t search -exact -overlap -backwards -all {abab} end\n} -cleanup {\n    destroy .t\n} -result {1.6 1.4 1.2 1.0}\ntest text-22.165 {TextSearchCmd, backward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"ababababab\"\n    .t search -exact -backwards -all {abab} end\n} -cleanup {\n    destroy .t\n} -result {1.6 1.2}\ntest text-22.166 {TextSearchCmd, backward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abababababab\"\n    .t search -exact -backwards -all {abab} end\n} -cleanup {\n    destroy .t\n} -result {1.8 1.4 1.0}\ntest text-22.167 {TextSearchCmd, forward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -exact -overlap -all \"foo\\nbar\\nfoo\" 1.0\n} -cleanup {\n    destroy .t\n} -result {1.0 3.0 5.0}\ntest text-22.168 {TextSearchCmd, forward exact search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -exact -all \"foo\\nbar\\nfoo\" 1.0\n} -cleanup {\n    destroy .t\n} -result {1.0 5.0}\ntest text-22.169 {TextSearchCmd, backward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -exact -overlap -backward -all \"foo\\nbar\\nfoo\" end\n} -cleanup {\n    destroy .t\n} -result {5.0 3.0 1.0}\ntest text-22.170 {TextSearchCmd, backward exact search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -exact -backward -all \"foo\\nbar\\nfoo\" end\n} -cleanup {\n    destroy .t\n} -result {5.0 1.0}\ntest text-22.171 {TextSearchCmd, backward exact search overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -regexp -backward -overlap -all \"foo\\nbar\\nfoo\" end\n} -cleanup {\n    destroy .t\n} -result {5.0 3.0 1.0}\ntest text-22.172 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"foo\\nbar\\nfoo\\nbar\\nfoo\\nbar\\nfoo\\n\"\n    .t search -regexp -backward -all \"foo\\nbar\\nfoo\" end\n} -cleanup {\n    destroy .t\n} -result {5.0 1.0}\ntest text-22.173 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -- {(\\$)?[\\w:_]+} 1.9\n} -cleanup {\n    destroy .t\n} -result {1.7}\ntest text-22.174 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -- {(\\$)?[\\w:_]+} 1.9 1.5\n} -cleanup {\n    destroy .t\n} -result {1.7}\ntest text-22.175 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -- {(\\$)?[\\w:_]+} 1.9 1.7\n} -cleanup {\n    destroy .t\n} -result {1.7}\ntest text-22.176 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -- {(\\$)?[\\w:_]+} 1.9 1.8\n} -cleanup {\n    destroy .t\n} -result {1.8}\ntest text-22.177 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -all -- {(\\$)?[\\w:_]+} 1.9 1.3\n} -cleanup {\n    destroy .t\n} -result {1.7 1.3}\ntest text-22.178 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -all -- {(\\$)?[\\w:_]+} 1.9 1.13\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.179 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -all -- {(\\$)?[\\w:_]+} 2.0 1.3\n} -cleanup {\n    destroy .t\n} -result {1.12 1.7 1.3}\ntest text-22.180 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \" aasda asdj werwer\"\n    .t search -regexp -backward -all -- {(\\$)?[\\w:_]+} 1.3\n} -cleanup {\n    destroy .t\n} -result {1.1 1.12 1.7 1.3}\ntest text-22.181 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\n\"\n    .t search -regexp -backward -all -- {(\\w+\\n)+} end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.182 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\n\"\n    .t search -regexp -backward -all -- {(\\w+\\n)+} end 1.5\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.183 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    .t search -regexp -backward -all -- {(\\w+\\n\\w)+} end 1.5\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.184 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -all -count foo -- {(\\w+\\n)+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 20}\ntest text-22.185 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    set res {}\n    lappend res \\\n      [list [.t search -regexp -all -count foo -- {(\\w+\\n)+} 1.0] $foo] \\\n      [list [.t search -regexp -all -count foo -- {(\\w+)+} 1.0] $foo]\n} -cleanup {\n    destroy .t\n} -result {{1.0 20} {{1.0 2.0 3.0 4.0} {5 5 5 1}}}\ntest text-22.186 {TextSearchCmd, regexp search greedy} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -all -nolinestop -count foo -- {.*} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 20}\ntest text-22.187 {TextSearchCmd, regexp search greedy} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -all -count foo -- {.*} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {{1.0 2.0 3.0 4.0} {5 5 5 1}}\ntest text-22.188 {TextSearchCmd, regexp search greedy multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -count foo -- {(\\w+\\n\\w)+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 19}\ntest text-22.189 {TextSearchCmd, regexp search greedy multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -backwards -count foo -- {(\\w+\\n\\w)+} end] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 19}\ntest text-22.190 {TextSearchCmd, regexp search greedy multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -all -backwards -count foo -- {(\\w+\\n\\w)+} end] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 19}\ntest text-22.191 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    .t search -regexp -backward -all -- {(\\w+\\n\\w)+} end 1.5\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.192 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    .t search -regexp -backward -all -- {(\\w+\\n\\w)+} end 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3}\ntest text-22.193 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -forward -count foo -- {(\\w+\\n\\w)+} 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {1.3 16}\ntest text-22.194 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -forward -all -count foo -- {(\\w+\\n\\w)+} 1.3] $foo\n# This result is somewhat debatable -- the two results do overlap,\n# but only because the search has totally wrapped around back to\n# the start.\n} -cleanup {\n    destroy .t\n} -result {{1.3 1.0} {16 19}}\ntest text-22.195 {TextSearchCmd, backward regexp search no-overlaps} -body {\n    pack [text .t]\n    .t insert 1.0 \"abcde\\nabcde\\nabcde\\na\"\n    list [.t search -regexp -forward -all -count foo -- {(\\w+\\n\\w)+} 1.0 1.3] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 19}\ntest text-22.196 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\naaaa\\nbbbb\\n\"\n    list [.t search -regexp -forward -all -count foo -- {(a+\\n(b+\\n))+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 20}\ntest text-22.197 {TextSearchCmd, regexp search complex cases} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\naaaa\\nbbbb\\n\"\n    list [.t search -regexp -forward -all -count foo \\\n      -- {(a+\\n(b+\\n))+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 20}\ntest text-22.198 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\ncccc\\nbbbb\\naaaa\\n\"\n    set foo {}\n    list [.t search -regexp -forward -all -count foo \\\n      -- {(b+\\nc+\\nb+)\\na+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 19}\ntest text-22.199 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\ncccc\\nbbbb\\naaaa\\n\"\n    set foo {}\n    list [.t search -regexp -forward -all -count foo \\\n      -- {(a+|b+\\nc+\\nb+)\\na+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 19}\ntest text-22.200 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\ncccc\\nbbbb\\naaaa\\n\"\n    set foo {}\n    list [.t search -regexp -forward -all -count foo \\\n      -- {(a+|b+\\nc+\\nb+)+\\na+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {2.0 19}\ntest text-22.201 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\ncccc\\nbbbb\\naaaa\\n\"\n    set foo {}\n    list [.t search -regexp -forward -all -count foo \\\n      -- {((a+|b+\\nc+\\nb+)+\\n)+a+} 1.0] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 24}\ntest text-22.202 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\nbbbb\\nbbbb\\nbbbb\\n\"\n    list [.t search -regexp -backward -all -count foo \\\n      -- {(b+\\n|a+\\n)(b+\\n)+} end] $foo\n} -cleanup {\n    destroy .t\n} -result {1.0 25}\ntest text-22.203 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"aaaa\\nbbbb\\nbbbb\\nbbbb\\nbbbb\\n\"\n    .t search -regexp -backward -- {(b+\\n|a+\\n)(b+\\n)+} end\n} -cleanup {\n    destroy .t\n} -result {1.0}\ntest text-22.204 {TextSearchCmd, regexp search multi-line} -body {\n    pack [text .t]\n    .t insert 1.0 \"line0\\nline1\\nline1\\nline1\\nline1\\nline2\\nline2\\nline2\\nline3\\n\"\n    .t search -nolinestop -regexp -nocase -forwards -- {^(.*)\\n(\\1\\n)+} 1.0 end\n# Matches at 6.0 currently\n} -cleanup {\n    destroy .t\n} -result {2.0}\ntest text-22.205 {TextSearchCmd, regexp search multi-line} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"\\naaaxxx\\nyyy\\n\"\n    lappend res [.t search -count c -regexp -- {x*\\ny*} 2.0] $c\n    lappend res [.t search -count c -regexp -- {x*\\ny*} 2.1] $c\n    return $res\n} -cleanup {\n    destroy .t\n} -result {2.3 7 2.3 7}\ntest text-22.206 {TextSearchCmd, regexp search multi-line} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"\\naaa\\n\\n\\n\\n\\nxxx\\n\"\n    lappend res [.t search -count c -regexp -- {\\n+} 2.0] $c\n    lappend res [.t search -count c -regexp -- {\\n+} 2.1] $c\n    return $res\n} -cleanup {\n    destroy .t\n} -result {2.3 5 2.3 5}\ntest text-22.207 {TextSearchCmd, regexp search multi-line} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"\\naaa\\n\\n\\t  \\n\\t\\t\\t  \\n\\nxxx\\n\"\n    lappend res [.t search -count c -regexp -- {(\\n+(\\t+ *)*)+} 2.0] $c\n    return $res\n} -cleanup {\n    destroy .t\n} -result {2.3 13}\ntest text-22.208 {TextSearchCmd, empty search range} -body {\n    pack [text .t]\n    .t insert 1.0 \"a\\na\\na\\n\"\n    .t search -- a 2.0 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.209 {TextSearchCmd, empty search range} -body {\n    pack [text .t]\n    .t insert 1.0 \"a\\na\\na\\n\"\n    .t search -backwards -- a 1.0 2.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.210 {TextSearchCmd, empty search range} -body {\n    pack [text .t]\n    .t insert 1.0 \"a\\na\\na\\n\"\n    .t search -- a 1.0 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.211 {TextSearchCmd, empty search range} -body {\n    pack [text .t]\n    .t insert 1.0 \"a\\na\\na\\n\"\n    .t search -backwards -- a 2.0 2.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.212 {TextSearchCmd, elide up to match} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"a\\nb\\nc\"\n    .t tag configure e -elide 1\n    lappend res [.t search -regexp a 1.0]\n    lappend res [.t search -regexp b 1.0]\n    lappend res [.t search -regexp c 1.0]\n    .t tag add e 1.0 2.0\n    lappend res [.t search -regexp a 1.0]\n    lappend res [.t search -regexp b 1.0]\n    lappend res [.t search -regexp c 1.0]\n    lappend res [.t search -elide -regexp a 1.0]\n    lappend res [.t search -elide -regexp b 1.0]\n    lappend res [.t search -elide -regexp c 1.0]\n} -cleanup {\n    destroy .t\n} -result {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}\ntest text-22.213 {TextSearchCmd, elide up to match, backwards} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"a\\nb\\nc\"\n    .t tag configure e -elide 1\n    lappend res [.t search -backward -regexp a 1.0]\n    lappend res [.t search -backward -regexp b 1.0]\n    lappend res [.t search -backward -regexp c 1.0]\n    .t tag add e 1.0 2.0\n    lappend res [.t search -backward -regexp a 1.0]\n    lappend res [.t search -backward -regexp b 1.0]\n    lappend res [.t search -backward -regexp c 1.0]\n    lappend res [.t search -backward -elide -regexp a 1.0]\n    lappend res [.t search -backward -elide -regexp b 1.0]\n    lappend res [.t search -backward -elide -regexp c 1.0]\n} -cleanup {\n    destroy .t\n} -result {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}\ntest text-22.214 {TextSearchCmd, elide up to match} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"a\\nb\\nc\"\n    .t tag configure e -elide 1\n    lappend res [.t search a 1.0]\n    lappend res [.t search b 1.0]\n    lappend res [.t search c 1.0]\n    .t tag add e 1.0 2.0\n    lappend res [.t search a 1.0]\n    lappend res [.t search b 1.0]\n    lappend res [.t search c 1.0]\n    lappend res [.t search -elide a 1.0]\n    lappend res [.t search -elide b 1.0]\n    lappend res [.t search -elide c 1.0]\n} -cleanup {\n    destroy .t\n} -result {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}\ntest text-22.215 {TextSearchCmd, elide up to match, backwards} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"a\\nb\\nc\"\n    .t tag configure e -elide 1\n    lappend res [.t search -backward a 1.0]\n    lappend res [.t search -backward b 1.0]\n    lappend res [.t search -backward c 1.0]\n    .t tag add e 1.0 2.0\n    lappend res [.t search -backward a 1.0]\n    lappend res [.t search -backward b 1.0]\n    lappend res [.t search -backward c 1.0]\n    lappend res [.t search -backward -elide a 1.0]\n    lappend res [.t search -backward -elide b 1.0]\n    lappend res [.t search -backward -elide c 1.0]\n} -cleanup {\n    destroy .t\n} -result {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}\ntest text-22.216 {TextSearchCmd, elide up to match} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"aa\\nbb\\ncc\"\n    .t tag configure e -elide 1\n    lappend res [.t search ab 1.0]\n    lappend res [.t search bc 1.0]\n    .t tag add e 1.1 2.1\n    lappend res [.t search ab 1.0]\n    lappend res [.t search b 1.0]\n    .t tag remove e 1.0 end\n    .t tag add e 2.1 3.1\n    lappend res [.t search bc 1.0]\n    lappend res [.t search c 1.0]\n    .t tag remove e 1.0 end\n    .t tag add e 2.1 3.0\n    lappend res [.t search bc 1.0]\n    lappend res [.t search c 1.0]\n} -cleanup {\n    destroy .t\n} -result {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}\ntest text-22.217 {TextSearchCmd, elide up to match} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t insert 1.0 \"aa\\nbb\\ncc\"\n    .t tag configure e -elide 1\n    lappend res [.t search -regexp ab 1.0]\n    lappend res [.t search -regexp bc 1.0]\n    .t tag add e 1.1 2.1\n    lappend res [.t search -regexp ab 1.0]\n    lappend res [.t search -regexp b 1.0]\n    .t tag remove e 1.0 end\n    .t tag add e 2.1 3.1\n    lappend res [.t search -regexp bc 1.0]\n    lappend res [.t search -regexp c 1.0]\n    .t tag remove e 1.0 end\n    .t tag add e 2.1 3.0\n    lappend res [.t search -regexp bc 1.0]\n    lappend res [.t search -regexp c 1.0]\n} -cleanup {\n    destroy .t\n} -result {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}\ntest text-22.217.1 {elide up to match, with UTF-8 chars before the match} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    .t tag configure e -elide 0\n    .t insert end A {} xyz e bb\\n\n    .t insert end Ä {} xyz e bb\n    set res {}\n    lappend res [.t search bb 1.0 \"1.0 lineend\"]\n    lappend res [.t search bb 2.0 \"2.0 lineend\"]\n    lappend res [.t search -regexp bb 1.0 \"1.0 lineend\"]\n    lappend res [.t search -regexp bb 2.0 \"2.0 lineend\"]\n    .t tag configure e -elide 1\n    lappend res [.t search bb 1.0 \"1.0 lineend\"]\n    lappend res [.t search bb 2.0 \"2.0 lineend\"]\n    lappend res [.t search -regexp bb 1.0 \"1.0 lineend\"]\n    lappend res [.t search -regexp -elide bb 2.0 \"2.0 lineend\"]\n    lappend res [.t search -regexp bb 2.0 \"2.0 lineend\"]\n} -cleanup {\n    destroy .t\n} -result {1.4 2.4 1.4 2.4 1.4 2.4 1.4 2.4 2.4}\ntest text-22.218 {TextSearchCmd, strict limits} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -- \"world\" 1.3 1.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.219 {TextSearchCmd, strict limits} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -- \"world\" 1.3 1.10\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.220 {TextSearchCmd, strict limits} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -- \"world\" 1.3 1.11\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.221 {TextSearchCmd, strict limits backwards} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -backward -- \"world\" 2.3 1.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.222 {TextSearchCmd, strict limits backwards} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -backward -- \"world\" 2.3 1.6\n} -cleanup {\n    destroy .t\n} -result {1.6}\ntest text-22.223 {TextSearchCmd, strict limits backwards} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -strictlimits -backward -- \"world\" 2.3 1.7\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.224 {TextSearchCmd, strict limits} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -regexp -strictlimits -- \"world\" 1.3 1.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.225 {TextSearchCmd, strict limits} -body {\n    pack [text .t]\n    .t insert 1.0 \"Hello world!\\nThis is a test\\n\"\n    .t search -regexp -strictlimits -backward -- \"world\" 2.3 1.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-22.226 {TextSearchCmd, exact search for the empty string} -body {\n    text .t\n    set res [.t search -count C \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.227 {TextSearchCmd, exact search for the empty string} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C \"\" 2.5]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 0}\ntest text-22.228 {TextSearchCmd, exact search all empty strings} -body {\n    text .t\n    set res [.t search -count C -all \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.229 {TextSearchCmd, exact search all empty strings} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -all \"\" 2.5 2.8]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 2.6 2.7 {0 0 0}}\ntest text-22.230 {TextSearchCmd, exact search all empty strings, with overlap} -body {\n    text .t\n    set res [.t search -count C -all -overlap \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.231 {TextSearchCmd, exact search all empty strings, with overlap} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -all -overlap \"\" 2.5 2.8]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 2.6 2.7 {0 0 0}}\ntest text-22.232 {TextSearchCmd, regexp search for the empty string} -body {\n    text .t\n    set res [.t search -count C -regexp \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.233 {TextSearchCmd, regexp search for the empty string} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -regexp \"\" 2.5]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 0}\ntest text-22.234 {TextSearchCmd, regexp search all empty strings} -body {\n    text .t\n    set res [.t search -count C -all -regexp \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.235 {TextSearchCmd, regexp search all empty strings} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -all -regexp \"\" 2.5 2.8]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 2.6 2.7 {0 0 0}}\ntest text-22.236 {TextSearchCmd, regexp search all empty strings, with overlap} -body {\n    text .t\n    set res [.t search -count C -all -regexp -overlap \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.237 {TextSearchCmd, regexp search all empty strings, with overlap} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -all -regexp -overlap \"\" 2.5 2.8]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.5 2.6 2.7 {0 0 0}}\ntest text-22.238 {TextSearchCmd, exact backwards search for the empty string} -body {\n    text .t\n    set res [.t search -count C -backwards \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.239 {TextSearchCmd, exact backwards search for the empty string} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards \"\" 2.5]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 0}\ntest text-22.240 {TextSearchCmd, exact backwards search all empty strings} -body {\n    text .t\n    set res [.t search -count C -backwards -all \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.241 {TextSearchCmd, exact backwards search all empty strings} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards -all \"\" 2.5 2.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}}\ntest text-22.242 {TextSearchCmd, exact backwards search all empty strings, with overlap} -body {\n    text .t\n    set res [.t search -count C -backwards -all -overlap \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.243 {TextSearchCmd, exact backwards search all empty strings, with overlap} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards -all -overlap \"\" 2.5 2.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}}\ntest text-22.244 {TextSearchCmd, regexp backwards search for the empty string} -body {\n    text .t\n    set res [.t search -count C -backwards -regexp \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.245 {TextSearchCmd, regexpbackwards search for the empty string} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards -regexp \"\" 2.5]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 0}\ntest text-22.246 {TextSearchCmd, regexp backwards search all empty strings} -body {\n    text .t\n    set res [.t search -count C -backwards -all -regexp \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.247 {TextSearchCmd, regexp backwards search all empty strings} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards -all -regexp \"\" 2.5 2.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}}\ntest text-22.248 {TextSearchCmd, regexp backwards search all empty strings, with overlap} -body {\n    text .t\n    set res [.t search -count C -backwards -all -regexp -overlap \"\" 1.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {1.0 0}\ntest text-22.249 {TextSearchCmd, regexp backwards search all empty strings, with overlap} -body {\n    text .t\n    .t insert end \"Searching for the\\nempty string!\"\n    set res [.t search -count C -backwards -all -regexp -overlap \"\" 2.5 2.0]\n    lappend res $C\n} -cleanup {\n    destroy .t\n    unset -nocomplain res C\n} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}}\ntest text-22.250 {TextSearchCmd, backwards search all matching at start of line} -body {\n    text .t\n    .t insert end \"abc\"\n    set res [.t search -backwards -all b end]      ; # works\n    lappend res [.t search -backwards a end]       ; # works\n    lappend res [.t search -backwards -all a end]  ; # used to hang\n} -cleanup {\n    destroy .t\n} -result {1.1 1.0 1.0}\n\ntest text-23.1 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs \"\\{{}\"\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {unmatched open brace in list}\ntest text-23.2 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs xyz\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"xyz\"}\ntest text-23.3 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs {100 200}\n    update idletasks\n    list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.4] 0]\n} -cleanup {\n    destroy .t\n} -result {100 200}\ntest text-23.4 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs {100 right 200 left 300 center 400 numeric}\n    update idletasks\n    list [expr {[lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]}] \\\n\t    [lindex [.t bbox 1.4] 0] \\\n\t    [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2}] \\\n\t    [lindex [.t bbox 1.10] 0]\n} -cleanup {\n    destroy .t\n} -result {100 200 300 400}\ntest text-23.5 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs {105 r 205 l 305 c 405 n}\n    update idletasks\n    list [expr {[lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]}] \\\n\t    [lindex [.t bbox 1.4] 0] \\\n\t    [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2}] \\\n\t    [lindex [.t bbox 1.10] 0]\n} -cleanup {\n    destroy .t\n} -result {105 205 305 405}\ntest text-23.6 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs {100 left 200 lork}\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad tab alignment \"lork\": must be left, right, center, or numeric}\ntest text-23.7 {TkTextGetTabs procedure} -setup {\n    text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 150\n    pack .t\n} -body {\n    .t insert end \"1\\t2\\t3\\t4\\t55.5\"\n    .t configure -tabs {100 !44 200 lork}\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected screen distance but got \"!44\"}\n\n\ntest text-24.1 {TextDumpCmd procedure, bad args} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}\ntest text-24.2 {TextDumpCmd procedure, bad args} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump -all\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}\ntest text-24.3 {TextDumpCmd procedure, bad args} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump -command\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}\ntest text-24.4 {TextDumpCmd procedure, bad args} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump -bogus\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad option \"-bogus\": must be -all, -command, -image, -mark, -tag, -text, or -window}\ntest text-24.5 {TextDumpCmd procedure, bad args} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump bogus\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"bogus\"}\ntest text-24.6 {TextDumpCmd procedure, one index} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t dump -text 1.2\n} -cleanup {\n    destroy .t\n} -result {text e 1.2}\ntest text-24.7 {TextDumpCmd procedure, two indices} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t dump -text 1.0 1.end\n} -cleanup {\n    destroy .t\n} -result {text {One Line} 1.0}\ntest text-24.8 {TextDumpCmd procedure, \"end\" index} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t dump -text 1.end end\n} -cleanup {\n    destroy .t\n} -result {text {\n} 1.8}\ntest text-24.9 {TextDumpCmd procedure, same indices} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t dump 1.5 1.5\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-24.10 {TextDumpCmd procedure, negative range} -body {\n    pack [text .t]\n    .t insert 1.0 \"One Line\"\n    .t mark set insert 1.0\n    .t dump 1.5 1.0\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-24.11 {TextDumpCmd procedure, stop at begin-line} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t dump -text 1.0 2.0\n} -cleanup {\n    destroy .t\n} -result {text {Line One\n} 1.0}\ntest text-24.12 {TextDumpCmd procedure, span multiple lines} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t dump -text 1.5 3.end\n} -cleanup {\n    destroy .t\n} -result {text {One\n} 1.5 text {Line Two\n} 2.0 text {Line Three} 3.0}\ntest text-24.13 {TextDumpCmd procedure, tags only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t tag add x 2.0 2.end\n    .t tag add y 1.0 end\n    .t dump -tag 2.1 2.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-24.14 {TextDumpCmd procedure, tags only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t tag add x 2.0 2.end\n    .t tag add y 1.0 end\n    .t dump -tag 2.0 2.8\n} -cleanup {\n    destroy .t\n} -result {tagon x 2.0}\ntest text-24.15 {TextDumpCmd procedure, tags only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t tag add x 2.0 2.end\n    .t tag add y 1.0 end\n    .t dump -tag 1.0 4.end\n} -cleanup {\n    destroy .t\n} -result {tagon y 1.0 tagon x 2.0 tagoff x 2.8}\ntest text-24.16 {TextDumpCmd procedure, tags only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t tag add x 2.0 2.end\n    .t tag add y 1.0 end\n    .t dump -tag 1.0 end\n} -cleanup {\n    destroy .t\n} -result {tagon y 1.0 tagon x 2.0 tagoff x 2.8 tagoff y 5.0}\ntest text-24.17 {TextDumpCmd procedure, marks only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t mark set m 2.4\n    .t mark set n 4.0\n    .t mark set END end\n    .t dump -mark 1.1 1.8\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-24.18 {TextDumpCmd procedure, marks only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t mark set m 2.4\n    .t mark set n 4.0\n    .t mark set END end\n    .t dump -mark 2.0 2.8\n} -cleanup {\n    destroy .t\n} -result {mark m 2.4}\ntest text-24.19 {TextDumpCmd procedure, marks only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t mark set m 2.4\n    .t mark set n 4.0\n    .t mark set END end\n    .t dump -mark 1.1 4.end\n} -cleanup {\n    destroy .t\n} -result {mark m 2.4 mark n 4.0}\ntest text-24.20 {TextDumpCmd procedure, marks only} -body {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t mark set m 2.4\n    .t mark set n 4.0\n    .t mark set END end\n    .t dump -mark 1.0 end\n} -cleanup {\n    destroy .t\n} -result {mark current 1.0 mark insert 1.0 mark m 2.4 mark n 4.0 mark END 5.0}\ntest text-24.21 {TextDumpCmd procedure, windows only} -setup {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    for {set i 0} {$i < 100} {incr i} {.t insert end \"-\\n\"}\n    button .hello -text Hello\n} -body {\n    .t window create 3.end -window .hello\n    .t window create 100.0 -create { }\n    .t dump -window 1.0 5.0\n} -cleanup {\n    destroy .t\n} -result {window .hello 3.10}\ntest text-24.22 {TextDumpCmd procedure, windows only} -setup {\n    pack [text .t]\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    for {set i 0} {$i < 100} {incr i} {.t insert end \"-\\n\"}\n    button .hello -text Hello\n} -body {\n    .t window create 3.end -window .hello\n    .t window create 100.0 -create { }\n    .t dump -window 5.0 end\n} -cleanup {\n    destroy .t\n} -result {window {} 100.0}\ntest text-24.23 {TextDumpCmd procedure, command script} -setup {\n    set x {}\n    pack [text .t]\n    proc Append {varName key value index} {\n\tupvar #0 $varName x\n\tlappend x $key $index $value\n    }\n} -body {\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t tag add x 2.0 2.end\n    .t mark set m 2.4\n    .t dump -command {Append x} -all 1.0 end\n    return $x\n} -cleanup {\n    destroy .t\n    rename Append {}\n} -result {mark 1.0 current mark 1.0 insert text 1.0 {Line One\n} tagon 2.0 x text 2.0 Line mark 2.4 m text 2.4 { Two} tagoff 2.8 x text 2.8 {\n} text 3.0 {Line Three\n} text 4.0 {Line Four\n}}\ntest text-24.24 {TextDumpCmd procedure, command script} -setup {\n    set x {}\n    pack [text .t]\n    proc Append {varName key value index} {\n\tupvar #0 $varName x\n\tlappend x $key $index $value\n    }\n} -body {\n    .t insert end \"Line One\\nLine Two\\nLine Three\\nLine Four\"\n    .t mark set insert 1.0\n    .t mark set current 1.0\n    .t mark set m 2.4\n    .t dump -mark -command {Append x} 1.0 end\n    return $x\n} -cleanup {\n    destroy .t\n    rename Append {}\n} -result {mark 1.0 current mark 1.0 insert mark 2.4 m}\ntest text-24.25 {TextDumpCmd procedure, unicode characters} -body {\n    text .t\n    .t insert 1.0 ±±±\n    .t dump -all 1.0 2.0\n} -cleanup {\n    destroy .t\n} -result \"text ±±± 1.0 mark insert 1.3 mark current 1.3 text {\\n} 1.3\"\ntest text-24.26 {TextDumpCmd procedure, unicode characters} -body {\n    text .t\n    .t delete 1.0 end\n    .t insert 1.0 abc±±±\n    .t dump -all 1.0 2.0\n} -cleanup {\n    destroy .t\n} -result \"text abc±±± 1.0 mark insert 1.6 mark current 1.6 text {\\n} 1.6\"\ntest text-24.27 {TextDumpCmd procedure, peer present} -body {\n    text .t\n    .t peer create .t.t\n    .t dump -all 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"mark insert 1.0 mark current 1.0 text {\\n} 1.0\"\n\ntest text-25.1 {text widget vs hidden commands} -body {\n    text .t\n    set y [list {} [interp hidden]]\n    interp hide {} .t\n    destroy .t\n    set x [list [winfo children .] [interp hidden]]\n    expr {$x eq $y}\n} -result 1\n\n\ntest text-26.1 {bug fix - 1642} -body {\n    pack [text .t]\n    .t insert end \"line 1\\n\"\n    .t insert end \"line 2\\n\"\n    .t insert end \"line 3\\n\"\n    .t insert end \"line 4\\n\"\n    .t insert end \"line 5\\n\"\n    tk::TextSetCursor .t 3.0\n    .t search -backward -regexp \"\\$\" insert 1.0\n} -cleanup {\n    destroy .t\n} -result {2.6}\n\n\ntest text-27.1 {TextEditCmd procedure, argument parsing} -body {\n    pack [text .t]\n    .t edit\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t edit option ?arg ...?\"}\ntest text-27.2 {TextEditCmd procedure, argument parsing} -body {\n    pack [text .t]\n    .t edit gorp\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad edit option \"gorp\": must be canundo, canredo, modified, redo, reset, separator, or undo}\ntest text-27.3 {TextEditUndo procedure, undoing changes} -body {\n    text .t -undo 1\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t delete 1.4 1.6\n    .t insert end \"should be gone after undo\\n\"\n    .t edit undo\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"line\\n\\n\"\ntest text-27.4 {TextEditRedo procedure, redoing changes} -body {\n    text .t -undo 1\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t delete 1.4 1.6\n    .t insert end \"should be back after redo\\n\"\n    .t edit undo\n    .t edit redo\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"line\\nshould be back after redo\\n\\n\"\ntest text-27.5 {TextEditUndo procedure, resetting stack} -body {\n    text .t -undo 1\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t delete 1.4 1.6\n    .t insert end \"should be back after redo\\n\"\n    .t edit reset\n    catch {.t edit undo} msg\n    return $msg\n} -cleanup {\n    destroy .t\n} -result \"nothing to undo\"\ntest text-27.6 {TextEditCmd procedure, insert separator} -body {\n    text .t -undo 1\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t edit separator\n    .t insert end \"line 2\\n\"\n    .t edit undo\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"line 1\\n\\n\"\ntest text-27.7 {-autoseparators configuration option} -body {\n    text .t -undo 1 -autoseparators 0\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t delete 1.4 1.6\n    .t insert end \"line 2\\n\"\n    .t edit undo\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"\\n\"\ntest text-27.8 {TextEditCmd procedure, modified flag} -body {\n    text .t\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t edit modified\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-27.9 {TextEditCmd procedure, reset modified flag} -body {\n    text .t\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t edit modified 0\n    .t edit modified\n} -cleanup {\n    destroy .t\n} -result 0\ntest text-27.10 {TextEditCmd procedure, set modified flag} -body {\n    text .t\n    pack .t\n    .t edit modified 1\n    .t edit modified\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-27.11 {TextEditCmd procedure, set modified flag repeat} -setup {\n    text .t\n    pack .t\n# Make sure the Text is mapped before we start\n    update\n    set ::retval {}\n} -body {\n    bind .t <<Modified>> \"lappend ::retval modified\"\n# Shouldn't require [update idle] to trigger event [Bug 1809538]\n    lappend ::retval [.t edit modified]\n    .t edit modified 1\n    update\n    lappend ::retval [.t edit modified]\n    .t edit modified 1 ; # binding should only fire once [Bug 1799782]\n    update idletasks\n    lappend ::retval [.t edit modified]\n} -cleanup {\n    destroy .t\n} -result {0 modified 1 1}\ntest text-27.12 {<<Modified>> virtual event} -body {\n    set ::retval unmodified\n    text .t -undo 1\n    pack .t\n    bind .t <<Modified>> \"set ::retval modified\"\n    update idletasks\n    .t insert end \"nothing special\\n\"\n    update\n    return $::retval\n} -cleanup {\n    destroy .t\n} -result {modified}\ntest text-27.13 {<<Modified>> virtual event - insert before Modified} -body {\n    set ::retval {}\n    pack [text .t -undo 1]\n    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }\n    update idletasks\n    .t insert end \"nothing special\"\n    update\n    return $::retval\n} -cleanup {\n    destroy .t\n} -result {nothing special}\ntest text-27.14 {<<Modified>> virtual event - delete before Modified} -body {\n# Bug 1737288, make sure we delete chars before triggering <<Modified>>\n    set ::retval {}\n    pack [text .t -undo 1]\n    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }\n    .t insert end \"nothing special\"\n    .t edit modified 0\n    .t delete 1.0 1.2\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {thing special}\ntest text-27.14a {<<Modified>> virtual event - propagation to peers} -body {\n# Bug [fd3a4dc111], <<Modified>> event is not always sent to peers\n    set ::retval 0\n    text .t -undo 1\n    .t peer create .tt\n    pack .t .tt\n    bind .t <<Modified>> {incr ::retval}\n    bind .tt <<Modified>> {incr ::retval}\n    .t insert end \"This increments ::retval once for each peer, i.e. twice.\"\n    .t edit modified 0  ; # shall increment twice as well, not just once\n    update\n    set ::retval\n} -cleanup {\n    destroy .t .tt\n} -result 4\ntest text-27.15 {<<Selection>> virtual event on sel tagging} -body {\n    set ::retval no_selection\n    pack [text .t]\n    bind .t <<Selection>> \"set ::retval selection_changed\"\n    update idletasks\n    .t insert end \"nothing special\\n\"\n    .t tag add sel 1.0 1.1\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {selection_changed}\ntest text-27.15a {<<Selection>> virtual event on sel removal} -body {\n    set ::retval no_selection\n    pack [text .t]\n    .t insert end \"nothing special\\n\"\n    .t tag add sel 1.0 1.1\n    bind .t <<Selection>> \"set ::retval selection_changed\"\n    update idletasks\n    .t tag remove 1.0 end\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {selection_changed}\ntest text-27.15b {<<Selection>> virtual event on <<PasteSelection>> inside widget selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"and it will be impacted by the <<PasteSelection>> event received.\\n\"\n    .t insert end \"Therefore a <<Selection>> event must fire back.\"\n    .t tag add sel 1.0 1.28\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    event generate .t <<PasteSelection>> -x 15 -y [lindex [.t dlineinfo 1.0] 1]\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {<<Selection>>_fired}\ntest text-27.15c {No <<Selection>> virtual event on <<PasteSelection>> outside widget selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"but it will not be impacted by the <<PasteSelection>> event received.\"\n    .t tag add sel 1.0 1.28\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    event generate .t <<PasteSelection>> -x 15 -y [lindex [.t dlineinfo 2.0] 1]\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {no_<<Selection>>_event_fired}\ntest text-27.15d {<<Selection>> virtual event on <Delete> with cursor inside selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"and it will be impacted by the <Delete> event received.\\n\"\n    .t insert end \"Therefore a <<Selection>> event must fire back.\"\n    .t tag add sel 1.0 1.28\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    .t mark set insert 1.15\n    update idletasks\n    focus -force .t\n    event generate .t <Delete>\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {<<Selection>>_fired}\ntest text-27.15e {No <<Selection>> virtual event on <Delete> with cursor outside selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"but it will not be impacted by the <Delete> event received.\"\n    .t tag add sel 1.0 1.28\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    .t mark set insert 2.15\n    focus .t\n    event generate .t <Delete>\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {no_<<Selection>>_event_fired}\ntest text-27.15f {<<Selection>> virtual event on <<Cut>> with a widget selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"and it will be impacted by the <<Cut>> event received.\\n\"\n    .t insert end \"Therefore a <<Selection>> event must fire back.\"\n    .t tag add sel 1.0 1.28\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    event generate .t <<Cut>>\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {<<Selection>>_fired}\ntest text-27.15g {No <<Selection>> virtual event on <<Cut>> without widget selection} -body {\n    pack [text .t]\n    .t insert end \"There is a selection in this text widget,\\n\"\n    .t insert end \"and it will be impacted by the <<Cut>> event received.\\n\"\n    .t insert end \"Therefore a <<Selection>> event must fire back.\"\n    bind .t <<Selection>> \"set ::retval <<Selection>>_fired\"\n    update\n    set ::retval no_<<Selection>>_event_fired\n    event generate .t <<Cut>>\n    update\n    set ::retval\n} -cleanup {\n    destroy .t\n} -result {no_<<Selection>>_event_fired}\ntest text-27.16 {-maxundo configuration option} -body {\n    text .t -undo 1 -autoseparators 1 -maxundo 2\n    pack .t\n    .t insert end \"line 1\\n\"\n    .t delete 1.4 1.6\n    .t insert end \"line 2\\n\"\n    catch {.t edit undo}\n    catch {.t edit undo}\n    catch {.t edit undo}\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"line 1\\n\\n\"\ntest text-27.16a {undo configuration options with peers} -body {\n    text .t -undo 1 -autoseparators 0 -maxundo 100\n    .t peer create .tt\n    set res     [.t  cget -undo]\n    lappend res [.tt cget -undo]\n    lappend res [.t  cget -autoseparators]\n    lappend res [.tt cget -autoseparators]\n    lappend res [.t  cget -maxundo]\n    lappend res [.tt cget -maxundo]\n    .t insert end \"The undo stack is common between peers\"\n    lappend res [.t  edit canundo]\n    lappend res [.tt edit canundo]\n} -cleanup {\n    destroy .t .tt\n} -result {1 1 0 0 100 100 1 1}\ntest text-27.16b {undo configuration options with peers, defaults} -body {\n    text .t\n    .t peer create .tt\n    set res     [.t  cget -undo]\n    lappend res [.tt cget -undo]\n    lappend res [.t  cget -autoseparators]\n    lappend res [.tt cget -autoseparators]\n    lappend res [.t  cget -maxundo]\n    lappend res [.tt cget -maxundo]\n    .t insert end \"The undo stack is common between peers\"\n    lappend res [.t  edit canundo]\n    lappend res [.tt edit canundo]\n} -cleanup {\n    destroy .t .tt\n} -result {0 0 1 1 0 0 0 0}\ntest text-27.17 {bug fix 1536735 - undo with empty text} -body {\n    text .t -undo 1\n    set r [.t edit modified]\n    .t delete 1.0\n    lappend r [.t edit modified]\n    lappend r [catch {.t edit undo}]\n    lappend r [.t edit modified]\n} -cleanup {\n    destroy .t\n} -result {0 0 1 0}\ntest text-27.18 {patch 1469210 - inserting after undo} -setup {\n    destroy .t\n} -body {\n    text .t -undo 1\n    .t insert end foo\n    .t edit modified 0\n    .t edit undo\n    .t insert end bar\n    .t edit modified\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-27.19 {patch 1669632 (i) - undo after <Control-Button-1>} -setup {\n    destroy .t\n} -body {\n    text .t -undo 1\n    .t insert end foo\\nbar\n    .t edit reset\n    .t insert 2.2 WORLD\n    event generate .t <Control-Button-1> -x 1 -y 1\n    .t insert insert HELLO\n    .t edit undo\n    .t get 2.2 2.7\n} -cleanup {\n    destroy .t\n} -result WORLD\ntest text-27.20 {patch 1669632 (iv) - undo after <<SelectNone>>} -setup {\n    destroy .top .top.t\n} -body {\n    toplevel .top\n    pack [text .top.t -undo 1]\n    .top.t insert end \"This is an example text\"\n    .top.t edit reset\n    .top.t mark set insert 1.5\n    .top.t insert 1.5 HELLO\n    .top.t tag add sel 1.10 1.12\n    update\n    focus -force .top.t\n    event generate .top.t <<SelectNone>>\n    .top.t insert insert \" WORLD \"\n    .top.t edit undo\n    .top.t get 1.5 1.10\n} -cleanup {\n    destroy .top.t .top\n} -result HELLO\ntest text-27.21 {patch 1669632 (vii) - <<Undo>> shall not remove separators} -setup {\n    destroy .t\n} -body {\n    text .t -undo 1\n    .t insert end \"This is an example text\"\n    .t edit reset\n    .t insert 1.5 \"WORLD \"\n    event generate .t <Control-Button-1> -x 1 -y 1\n    .t insert insert HELLO\n    event generate .t <<Undo>>\n    .t insert insert E\n    event generate .t <<Undo>>\n    .t get 1.0 \"1.0 lineend\"\n} -cleanup {\n    destroy .t\n} -result \"This WORLD is an example text\"\ntest text-27.22 {patch 1669632 (v) - <<Clear>> is atomic} -setup {\n    destroy .t\n} -body {\n    toplevel .top\n    pack [text .top.t -undo 1]\n    .top.t insert end \"This is an example text\"\n    .top.t edit reset\n    .top.t mark set insert 1.5\n    .top.t insert 1.5 \"A\"\n    update\n    focus -force .top.t\n    event generate .top.t <Delete>\n    event generate .top.t <<SelectNextChar>>\n    event generate .top.t <<Clear>>\n    event generate .top.t <Delete>\n    event generate .top.t <<Undo>>\n    .top.t get 1.0 \"1.0 lineend\"\n} -cleanup {\n    destroy .top.t .top\n} -result \"This A an example text\"\n test text-27.23 {patch 1669632 (v) - <<Cut>> is atomic} -setup {\n    destroy .t\n} -body {\n    toplevel .top\n    pack [text .top.t -undo 1]\n    .top.t insert end \"This is an example text\"\n    .top.t edit reset\n    .top.t mark set insert 1.5\n    .top.t insert 1.5 \"A\"\n    update\n    focus -force .top.t\n    event generate .top.t <Delete>\n    event generate .top.t <<SelectNextChar>>\n    event generate .top.t <<Cut>>\n    event generate .top.t <Delete>\n    event generate .top.t <<Undo>>\n    .top.t get 1.0 \"1.0 lineend\"\n} -cleanup {\n    destroy .top.t .top\n} -result \"This A an example text\"\ntest text-27.24 {TextEditCmd procedure, canundo and canredo} -setup {\n    destroy .t\n    set res {}\n} -body {\n    text .t -undo false -autoseparators false\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t configure -undo true\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t insert end \"DO\\n\"\n    .t edit separator\n    .t insert end \"IT\\n\"\n    .t insert end \"YOURSELF\\n\"\n    .t edit separator\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t edit undo\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t configure -undo false\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t configure -undo true\n    lappend res [.t edit canundo] [.t edit canredo]\n    .t edit redo\n    lappend res [.t edit canundo] [.t edit canredo]\n} -cleanup {\n    destroy .t\n} -result {0 0 0 0 1 0 1 1 0 0 1 1 1 0}\ntest text-27.25 {<<UndoStack>> virtual event} -setup {\n    destroy .t\n    set res {}\n    set nbUS 0\n} -body {\n    text .t -undo false -autoseparators false\n    bind .t <<UndoStack>> {incr nbUS}\n    update ; lappend res $nbUS\n    .t configure -undo true\n    update ; lappend res $nbUS\n    .t insert end \"DO\\n\"\n    .t edit separator\n    .t insert end \"IT\\n\"\n    .t insert end \"YOURSELF\\n\"\n    .t edit separator\n    .t insert end \"MAN\\n\"\n    .t edit separator\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit redo\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit redo\n    update ; lappend res $nbUS\n    .t edit redo\n    update ; lappend res $nbUS\n    .t edit redo\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit undo\n    update ; lappend res $nbUS\n    .t edit reset\n    update ; lappend res $nbUS\n} -cleanup {\n    destroy .t\n} -result {0 0 1 2 3 4 4 5 6 6 7 8 8 9}\ntest text-27.26 {edit undo and edit redo return ranges} -setup {\n    destroy .t\n    set res {}\n} -body {\n    text .t -undo true -autoseparators false\n    .t insert end \"Hello \"\n    .t edit separator\n    .t insert end \"World!\\n\"\n    .t insert 1.6 \"GREAT \"\n    .t insert end \"Another edit here!!\"\n    lappend res [.t edit undo]\n    lappend res [.t edit redo]\n    .t edit separator\n    .t delete 1.6\n    .t delete 1.9 1.10\n    .t insert 1.9 L\n    lappend res [.t edit undo]\n    lappend res [.t edit redo]\n    .t replace 1.6 1.10 Tcl/Tk\n    .t replace 2.8 2.12 \"one bites the dust\"\n    lappend res [.t edit undo]\n    lappend res [.t edit redo]\n} -cleanup {\n    destroy .t\n} -result [list {1.6 2.0}           \\\n\t\t{1.6 2.19}          \\\n\t\t{1.6 1.7 1.10 1.12} \\\n\t\t{1.6 1.7 1.9 1.11}  \\\n\t\t{1.6 1.16 2.8 2.19} \\\n\t\t{1.6 1.16 2.8 2.30} ]\ntest text-27.27 {edit undo and edit redo return ranges} -setup {\n    destroy .t\n    set res {}\n} -body {\n    text .t -undo true -autoseparators false\n    for {set i 3} {$i >= 1} {incr i -1} {\n\t.t insert 1.0 \"Line $i\\n\"\n    }\n    lappend res [.t edit undo]\n    lappend res [.t edit redo]\n} -cleanup {\n    destroy .t\n} -result [list {1.0 2.0} \\\n\t\t{1.0 4.0} ]\ntest text-27.28 {edit undo and edit redo do not leave \\\n\t\t spurious temporary marks behind them} -setup {\n    destroy .t\n    set res {}\n} -body {\n    pack [text .t -undo true -autoseparators false]\n    .t insert end \"Hello World.\\n\"\n    .t edit separator\n    .t insert end \"Again hello.\\n\"\n    .t edit undo\n    lappend res [expr {[lsearch [.t mark names] tk::undoMark*]<0}]\n    .t edit redo\n    lappend res [expr {[lsearch [.t mark names] tk::undoMark*]<0}]\n} -cleanup {\n    destroy .t\n} -result {1 1}\ntest text-27.29 {bug ab839efc5f - .text edit undo inserts separators} -setup {\n    destroy .t\n} -body {\n    text .t -undo 1\n    .t insert 1.0 \"1. 123 5 789012  LINE-1\\n2.\\n3. 123 5 789012  LINE-3\\n\"\n    .t tag add sel 3.0 3.end\n    .t delete sel.first sel.last\n    .t edit undo\n    .t tag add sel 3.0 3.end\n    .t delete sel.first sel.last\n    .t edit undo\n    .t get 3.0 3.end\n} -cleanup {\n    destroy .t\n} -result {3. 123 5 789012  LINE-3}\n\ntest text-28.1 {bug fix - 624372, ControlUtfProc long lines} -body {\n    pack [text .t -wrap none]\n    .t insert end [string repeat \"\\1\" 500]\n} -cleanup {\n    destroy .t\n} -result {}\n\n\ntest text-29.1 {tabs - must be positive and must be increasing} -body {\n    pack [text .t -wrap none]\n    .t configure -tabs 0\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {tab stop \"0\" is not at a positive distance}\ntest text-29.2 {tabs - must be positive and must be increasing} -body {\n    pack [text .t -wrap none]\n    .t configure -tabs -5\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {tab stop \"-5\" is not at a positive distance}\ntest text-29.3 {tabs - must be positive and must be increasing} -constraints {\n    knownBug\n} -body {\n# This bug will be fixed in Tk 9.0, when we can allow a minor\n# incompatibility with Tk 8.x\n    pack [text .t -wrap none]\n    .t configure -tabs {10c 5c}\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {tabs must be monotonically increasing, but \"5c\" is smaller than or equal to the previous tab}\ntest text-29.4 {tabs - must be positive and must be increasing} -body {\n    pack [text .t -wrap none]\n    .t insert end \"a\\tb\\tc\\td\\te\"\n    catch {.t configure -tabs {10c 5c}}\n    update ; update ; update\n# This test must simply not go into an infinite loop to succeed\n    set result 1\n} -cleanup {\n    destroy .t\n} -result 1\n\n\ntest text-30.1 {repeated insert and scroll} -body {\n    pack [text .t]\n    for {set i 0} {$i < 30} {incr i} {\n\t.t insert end \"blabla\\n\"\n\teval .t yview moveto 1\n    }\n# This test must simply not crash to succeed\n    set result 1\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-30.2 {repeated insert and scroll} -body {\n    pack [text .t]\n    for {set i 0} {$i < 30} {incr i} {\n\t.t insert end \"blabla\\n\"\n\teval .t yview scroll 1 pages\n    }\n# This test must simply not crash to succeed\n    set result 1\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-30.3 {repeated insert and scroll} -body {\n    pack [text .t]\n    for {set i 0} {$i < 30} {incr i} {\n\t.t insert end \"blabla\\n\"\n\teval .t yview scroll 100 pixels\n    }\n# This test must simply not crash to succeed\n    set result 1\n} -cleanup {\n    destroy .t\n} -result 1\ntest text-30.4 {repeated insert and scroll} -body {\n    pack [text .t]\n    for {set i 0} {$i < 30} {incr i} {\n\t.t insert end \"blabla\\n\"\n\teval .t yview scroll 10 units\n    }\n# This test must simply not crash to succeed\n    set result 1\n} -cleanup {\n    destroy .t\n} -result 1\n\n\ntest text-31.1 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    pack [.t peer create .top.t]\n    destroy .t .top\n} -result {}\ntest text-31.2 {peer widgets} -body {\n    toplevel .top1\n    toplevel .top2\n    pack [text .t]\n    pack [.t peer create .top1.t]\n    pack [.t peer create .top2.t]\n    .t insert end \"abcd\\nabcd\"\n    update\n    destroy .top1\n    update\n    .t insert end \"abcd\\nabcd\"\n    update\n    destroy .t .top2\n    update\n} -result {}\ntest text-31.3 {peer widgets} -body {\n    toplevel .top1\n    toplevel .top2\n    pack [text .t]\n    pack [.t peer create .top1.t]\n    pack [.t peer create .top2.t]\n    .t insert end \"abcd\\nabcd\"\n    update\n    destroy .t\n    update\n    .top2.t insert end \"abcd\\nabcd\"\n    update\n    destroy .t .top2\n    update\n} -result {}\ntest text-31.4 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    update\n    destroy .t .top\n} -result {}\ntest text-31.5 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    pack [.top.t peer create .top.t2]\n    set res [list [.top.t index end] [.top.t2 index end]]\n    update\n    return $res\n} -cleanup {\n    destroy .t .top\n} -result {7.0 7.0}\ntest text-31.6 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    pack [.top.t peer create .top.t2 -startline {} -endline {}]\n    set res [list [.top.t index end] [.top.t2 index end]]\n    update\n    return $res\n} -cleanup {\n    destroy .t .top\n} -result {7.0 21.0}\ntest text-31.7 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    update ; update\n    set p1 [.top.t count -update -ypixels 1.0 end]\n    set p2 [.t count -update -ypixels 5.0 11.0]\n    expr {$p1 eq $p2}\n} -cleanup {\n    destroy .t .top\n} -result 1\ntest text-31.8 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    update ; update\n    .t delete 3.0 6.0\n    .top.t index end\n} -cleanup {\n    destroy .t .top\n} -result {6.0}\ntest text-31.9 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    update ; update\n    .t delete 8.0 12.0\n    .top.t index end\n} -cleanup {\n    destroy .t .top\n} -result {4.0}\ntest text-31.10 {peer widgets} -body {\n    toplevel .top\n    pack [text .t]\n\tfor {set i 1} {$i < 20} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    pack [.t peer create .top.t -startline 5 -endline 11]\n    update ; update\n    .t delete 3.0 13.0\n    .top.t index end\n} -cleanup {\n    destroy .t .top\n} -result {1.0}\ntest text-31.11 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 end-1c\n    lappend res [.t tag ranges sel]\n    .t configure -startline 10 -endline 20\n    lappend res [.t tag ranges sel]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{1.0 100.0} {1.0 11.0}}\ntest text-31.12 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 end-1c\n    lappend res [.t tag ranges sel]\n    .t configure -startline 11\n    lappend res [.t tag ranges sel]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{1.0 100.0} {1.0 90.0}}\ntest text-31.13 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 end-1c\n    lappend res [.t tag ranges sel]\n    .t configure -endline 90\n    lappend res [.t tag ranges sel]\n    destroy .t\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{1.0 100.0} {1.0 90.0}}\ntest text-31.14 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0\n    lappend res [.t tag prevrange sel 1.0]\n    .t configure -startline 6 -endline 12\n    lappend res [.t tag ranges sel]\n    lappend res \"next\" [.t tag nextrange sel 4.0] \\\n      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \\\n      [.t tag nextrange sel 7.0]\n    lappend res \"prev\" [.t tag prevrange sel 1.0] \\\n      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \\\n      [.t tag prevrange sel 4.0]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{} {1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}\ntest text-31.15 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 3.0 9.0 11.0 13.0 15.0 17.0 19.0\n    .t configure -startline 6 -endline 12\n    lappend res [.t tag ranges sel]\n    lappend res \"next\" [.t tag nextrange sel 4.0] \\\n      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \\\n      [.t tag nextrange sel 7.0]\n    lappend res \"prev\" [.t tag prevrange sel 1.0] \\\n      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \\\n      [.t tag prevrange sel 4.0]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{4.0 6.0} next {4.0 6.0} {} {} {} prev {} {} {} {}}\ntest text-31.16 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 20} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0\n    .t configure -startline 6 -endline 12\n    lappend res [.t tag ranges sel]\n    lappend res \"next\" [.t tag nextrange sel 4.0] \\\n      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \\\n      [.t tag nextrange sel 7.0]\n    lappend res \"prev\" [.t tag prevrange sel 1.0] \\\n      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \\\n      [.t tag prevrange sel 4.0]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}\ntest text-31.17 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 11.0\n    lappend res [.t tag ranges sel]\n    lappend res [catch {.t configure -startline 15 -endline 10}]\n    lappend res [.t tag ranges sel]\n    .t configure -startline 6 -endline 12\n    lappend res [.t tag ranges sel]\n    .t configure -startline {} -endline {}\n    lappend res [.t tag ranges sel]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{1.0 11.0} 1 {1.0 11.0} {1.0 6.0} {1.0 11.0}}\ntest text-31.18 {peer widgets} -setup {\n    pack [text .t]\n    set res {}\n} -body {\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 1.0 11.0\n    lappend res [.t index sel.first]\n    lappend res [.t index sel.last]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {1.0 11.0}\ntest text-31.19 {peer widgets} -body {\n    pack [text .t]\n    for {set i 1} {$i < 20} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag delete sel\n    .t index sel.first\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {text doesn't contain any characters tagged with \"sel\"}\n\n\ntest text-32.1 {line heights on creation} -setup {\n    text .t\n    proc makeText {} {\n\tset w .g\n\tset font \"Times 11\"\n\tdestroy .g\n\ttoplevel .g\n\tframe $w.f -highlightthickness 2 -borderwidth 2 -relief sunken\n\tset t $w.f.text\n\ttext $t -yscrollcommand \"$w.scroll set\" -setgrid true -font $font \\\n\t    -width 70 -height 35 -wrap word -highlightthickness 0 \\\n\t    -borderwidth 0\n\tpack $t -expand  yes -fill both\n\tscrollbar $w.scroll -command \"$t yview\"\n\tpack $w.scroll -side right -fill y\n\tpack $w.f -expand yes -fill both\n\t$t tag configure center -justify center -spacing1 5m -spacing3 5m\n\t$t tag configure buttons -lmargin1 1c -lmargin2 1c -rmargin 1c \\\n\t    -spacing1 3m -spacing2 0 -spacing3 0\n\tfor {set i 0} {$i < 40} {incr i} {\n\t    $t insert end \"${i}word \"\n\t}\n\treturn $t\n    }\n} -body {\n    set w [makeText]\n    update ; after 1000 ; update\n    set before [$w count -ypixels 1.0 2.0]\n    $w insert 1.0 \"a\"\n    update\n    set after [$w count -ypixels 1.0 2.0]\n    destroy .g\n    expr {$before eq $after}\n} -cleanup {\n    destroy .t\n} -result 1\n\ntest text-32.2 {peer widget -start, -endline and deletion (bug 1630262)} -setup {\n    destroy .t .pt\n    set res {}\n} -body {\n    text .t\n    .t peer create .pt\n    for {set i 1} {$i < 100} {incr i} {\n      .t insert end \"Line $i\\n\"\n    }\n    .t configure -startline 5\n    # none of the following delete shall crash\n    # (all did before fixing bug 1630262)\n    # 1. delete on the same line: line1 == line2 in DeleteIndexRange,\n    #    and resetView is true neither for .t not for .pt\n    .pt delete 2.0 2.2\n    # 2. delete just one line: line1 < line2 in DeleteIndexRange,\n    #    and resetView is true only for .t, not for .pt\n    .pt delete 2.0 3.0\n    # 3. delete several lines: line1 < line2 in DeleteIndexRange,\n    #    and resetView is true only for .t, not for .pt\n    .pt delete 2.0 5.0\n    # 4. delete to the end line: line1 < line2 in DeleteIndexRange,\n    #    and resetView is true only for .t, not for .pt\n    .pt delete 2.0 end\n    # this test succeeds provided there is no crash\n    set res 1\n} -cleanup {\n    destroy .pt\n} -result 1\n\ntest text-32.3 {peer widget -start, -endline and deletion (bug 1630262)} -setup {\n    destroy .t .pt\n    set res {}\n} -body {\n    text .t\n    .t peer create .pt\n    for {set i 1} {$i < 100} {incr i} {\n      .t insert end \"Line $i\\n\"\n    }\n    .t configure -startline 5\n    .pt configure -startline 3\n    # the following delete shall not crash\n    # (it did before fixing bug 1630262)\n    .pt delete 2.0 3.0\n    # moreover -startline shall be correct\n    # (was wrong before fixing bug 1630262)\n    lappend res [.t cget -start] [.pt cget -start] [.t get @0,0 \"@0,0 lineend\"]\n} -cleanup {\n    destroy .pt\n} -result {4 3 {Line 5}}\n\ntest text-32.4 {peer widget -start, -endline and deletion (bug 1630262)} -setup {\n    destroy .t .pt\n    set res {}\n} -body {\n    text .t\n    .t peer create .pt\n    for {set i 1} {$i < 100} {incr i} {\n      .t insert end \"Line $i\\n\"\n    }\n    .t configure -startline 5 -endline 15\n    .pt configure -startline 8 -endline 12\n    # .pt now shows a range entirely inside the range of .pt\n    # from .t, delete lines located after [.pt cget -end]\n    .t delete 9.0 10.0\n    # from .t, delete lines straddling [.pt cget -end]\n    .t delete 6.0 9.0\n    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]\n    .t configure -startline 5 -endline 12\n    .pt configure -startline 8 -endline 12\n    # .pt now shows again a range entirely inside the range of .pt\n    # from .t, delete lines located before [.pt cget -start]\n    .t delete 2.0 3.0\n    # from .t, delete lines straddling [.pt cget -start]\n    .t delete 2.0 5.0\n    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]\n    .t configure -startline 22 -endline 31\n    .pt configure -startline 42 -endline 51\n    # .t now shows a range entirely before the range of .pt\n    # from .t, delete some lines, then do it from .pt\n    .t delete 2.0 3.0\n    .t delete 2.0 5.0\n    .pt delete 2.0 5.0\n    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]\n    .t configure -startline 55 -endline 75\n    .pt configure -startline 60 -endline 70\n    # .pt now shows a range entirely inside the range of .t\n    # from .t, delete a range straddling the entire range of .pt\n    .t delete 3.0 18.0\n    lappend res [.t cget -start] [.t cget -end] [.pt cget -start] [.pt cget -end]\n} -cleanup {\n    destroy .pt .t\n} -result {5 11 8 10 5 8 6 8 22 27 38 44 55 60 57 57}\n\n\ntest text-33.1 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n} -body {\n    .t peer foo 1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad peer option \"foo\": must be create or names}\ntest text-33.2 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n} -body {\n    .t peer names foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t peer names\"}\ntest text-33.3 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n} -body {\n    .t peer names\n} -cleanup {\n    destroy .t\n} -returnCodes {ok} -result {}\ntest text-33.4 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n} -body {\n    .t peer names\n} -cleanup {\n    destroy .t\n} -result {}\ntest text-33.5 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n} -body {\n    .t peer create foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad window path name \"foo\"}\ntest text-33.6 {TextWidgetCmd procedure, \"peer\" option} -setup {\n    text .t\n    set res {}\n} -body {\n    .t peer create .t2\n    lappend res [.t peer names]\n    lappend res [.t2 peer names]\n    destroy .t2\n    lappend res [.t peer names]\n} -cleanup {\n    destroy .t\n} -result {.t2 .t {}}\ntest text-33.7 {peer widget -start, -end} -body {\n    text .t\n    set res [.t configure -startline 10 -endline 5]\n    return $res\n} -cleanup {\n    destroy .t\n} -returnCodes 2 -result {}\ntest text-33.8 {peer widget -start, -end} -body {\n    text .t\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t configure -startline 10 -endline 5\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {-startline must be less than or equal to -endline}\ntest text-33.9 {peer widget -start, -end} -body {\n    text .t\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    .t configure -startline 5 -endline 10\n} -cleanup {\n    destroy .t\n} -returnCodes {ok} -result {}\ntest text-33.10 {peer widget -start, -end} -body {\n    text .t\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    set res [.t index end]\n    lappend res [catch {.t configure -startline 5 -endline 10 -tab foo}]\n    lappend res [.t index end]\n    lappend res [catch {.t configure -tab foo -startline 15 -endline 20}]\n    lappend res [.t index end]\n    .t configure -startline {} -endline {}\n    lappend res [.t index end]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {101.0 1 101.0 1 101.0 101.0}\ntest text-33.11 {peer widget -start, -end} -body {\n    text .t\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    set res [.t index end]\n    lappend res [catch {.t configure -startline 5 -endline 15}]\n    lappend res [.t index end]\n    lappend res [catch {.t configure -startline 10 -endline 40}]\n    lappend res [.t index end]\n    .t configure -startline {} -endline {}\n    lappend res [.t index end]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {101.0 0 11.0 0 31.0 101.0}\n\ntest text-34.1 {peer widget -start, -endline and selection} -setup {\n    text .t\n    set res {}\n} -body {\n    for {set i 1} {$i < 100} {incr i} {\n\t   .t insert end \"Line $i\\n\"\n    }\n    .t tag add sel 10.0 20.0\n    lappend res [.t tag ranges sel]\n    .t configure -startline 5 -endline 30\n    lappend res [.t tag ranges sel]\n    .t configure -startline 5 -endline 15\n    lappend res [.t tag ranges sel]\n    .t configure -startline 15 -endline 30\n    lappend res [.t tag ranges sel]\n    .t configure -startline 15 -endline 16\n    lappend res [.t tag ranges sel]\n    .t configure -startline 25 -endline 30\n    lappend res [.t tag ranges sel]\n    .t configure -startline {} -endline {}\n    lappend res [.t tag ranges sel]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}\n\ntest text-35.1 {widget dump -command alters tags} -setup {\n     proc Dumpy {key value index} {\n      .t tag add $value [list $index linestart] [list $index lineend]\n    }\n    text .t\n} -body {\n    .t insert end \"abc\\n\" a \"---\" {} \"def\" b \"   \\n\" {} \"ghi\\n\" c\n    .t tag configure b -background red\n    .t dump -all -command Dumpy 1.0 end\n    set result \"ok\"\n} -cleanup {\n    destroy .t\n} -result {ok}\ntest text-35.2 {widget dump -command makes massive changes} -setup {\n    proc Dumpy {key value index} {\n      .t delete 1.0 end\n    }\n    text .t\n} -body {\n    .t insert end \"abc\\n\" a \"---\" {} \"def\" b \"   \\n\" {} \"ghi\\n\" c\n    .t tag configure b -background red\n    .t dump -all -command Dumpy 1.0 end\n    set result \"ok\"\n} -cleanup {\n    destroy .t\n} -result {ok}\ntest text-35.3 {widget dump -command destroys widget} -setup {\n    proc Dumpy {key value index} {\n\tdestroy .t\n    }\n    text .t\n} -body {\n    .t insert end \"abc\\n\" a \"---\" {} \"def\" b \"   \\n\" {} \"ghi\\n\" c\n    .t tag configure b -background red\n    .t dump -all -command Dumpy 1.0 end\n    set result \"ok\"\n} -cleanup {\n    destroy .t\n} -result {ok}\n\n\ntest text-36.1 \"bug #1777362: event handling with hyphenated windows\" -setup {\n    set save [interp bgerror {}]\n    interp bgerror {} returnerror-36.1\n    proc returnerror-36.1 {m opts} {set ::my_error $m}\n    set ::my_error {}\n    pack [set w [text .t-1]]\n} -body {\n    tkwait visibility $w\n    event generate $w <Button-1>\n    event generate $w <Button-1>\n    update\n    set ::my_error\n} -cleanup {\n    destroy .t-1\n    rename returnerror-36.1 \"\"\n    interp bgerror {} $save\n    unset -nocomplain save ::my_error w\n} -result {}\ntest text-36.2 \"bug #1777362: event handling with hyphenated windows\" -setup {\n    set save [interp bgerror {}]\n    interp bgerror {} returnerror-36.2\n    proc returnerror-36.2 {m opts} {set ::my_error $m}\n    set ::my_error {}\n    pack [set w [text .t+1]]\n} -body {\n    tkwait visibility $w\n    event generate $w <Button-1>\n    event generate $w <Button-1>\n    update\n    set ::my_error\n} -cleanup {\n    destroy $w\n    rename returnerror-36.2 \"\"\n    interp bgerror {} $save\n    unset -nocomplain save ::my_error w\n} -result {}\ntest text-36.3 \"bug #1777362: event handling with hyphenated windows\" -setup {\n    set save [interp bgerror {}]\n    interp bgerror {} returnerror-36.3\n    proc returnerror-36.3 {m opts} {set ::my_error $m}\n    set ::my_error {}\n    pack [set w [text .t*1]]\n} -body {\n    tkwait visibility $w\n    event generate $w <Button-1>\n    event generate $w <Button-1>\n    update\n    set ::my_error\n} -cleanup {\n    destroy $w\n    rename returnerror-36.3 \"\"\n    interp bgerror {} $save\n    unset -nocomplain save ::my_error w\n} -result {}\n\n\ntest text-37.1 \"bug #dd9667635d: text anchor not set\" -setup {\n    set save [interp bgerror {}]\n    interp bgerror {} returnerror-37.1\n    proc returnerror-37.1 {m opts} {set ::my_error $m}\n    destroy .t\n    set ::my_error {}\n    pack [text .t]\n} -body {\n    .t insert end \"Hello world!\"\n    .t tag add sel 1.0 end\n    # this line shall not trigger error:\n    #     bad text index \"tk::anchorN\"\n    event generate .t <<SelectPrevLine>>\n    update\n    set ::my_error\n} -cleanup {\n    destroy .t\n    rename returnerror-37.1 \"\"\n    interp bgerror {} $save\n    unset -nocomplain save ::my_error\n} -result {}\n\n\ntest text-38.1 {Extending selection with mouse going outside the widget - Bug a9cf210a42} -setup {\n    pack [text .t -width 40 -height 10]\n    for {set n 1} {$n <= 5} {incr n} {\n\t.t insert end \"This is line $i of text\\n\"\n    }\n    update\n} -body {\n    event generate .t <Button-1> -x 50 -y 50\n    event generate .t <B1-Motion> -x 50 -y -50\n    .t index sel.first\n} -cleanup {\n    destroy .t\n} -result {1.0}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/textBTree.test",
    "content": "# This file is a Tcl script to test out the B-tree facilities of\n# Tk's text widget (the contents of the file \"tkTextBTree.c\".  There are\n# several files with additional tests for other features of text widgets.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc setup {} {\n    .t delete 1.0 100000.0\n    .t tag delete x y\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 1.1\n    .t tag add x 1.5 1.13\n    .t tag add x 2.2 2.6\n    .t tag add y 1.5\n}\n\n# setup procedure for tests 10.*, 11.*, 12.*\nproc msetup {} {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t mark set m1 1.2\n    .t mark set l1 1.2\n    .t mark gravity l1 left\n    .t mark set next 1.6\n    .t mark set x 1.6\n    .t mark set m2 2.0\n    .t mark set m3 2.100\n    .t tag add x 1.3 1.8\n}\n\n# setup procedure for tests 16.*, 17.*, 18.9\nproc setupBig {} {\n    .t delete 1.0 end\n    .t tag delete x y\n    .t tag configure x -foreground blue\n    .t tag configure y -underline true\n    # Create a Btree with 2002 lines (2000 + already existing + phantom at end)\n    # This generates a level 3 node with 9 children\n    # Most level 2 nodes cover 216 lines and have 6 children, except the last\n    # level 2 node covers 274 lines and has 7 children.\n    # Most level 1 nodes cover 36 lines and have 6 children, except the\n    # rightmost node has 58 lines and 9 children.\n    # Level 2: 2002 = 8*216 + 274\n    # Level 1: 2002 = 54*36 + 58\n    # Level 0: 2002 = 332*6 + 10\n    for {set i 0} {$i < 2000} {incr i} {\n\tappend x \"Line $i abcd efgh ijkl\\n\"\n    }\n    .t insert insert $x\n    .t debug 1\n}\n\n#\n# COMMON TEST SETUP\n#\n# For tests 1.* - 13.*\n#\ndestroy .t\ntext .t\n.t debug on\n\n#\n# TESTS\n#\n\ntest btree-1.1 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-1.2 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 1.3 XXX\n    .t get 1.0 1000000.0\n} -result \"LinXXXe 1\\nLine 2\\nLine 3\\n\"\ntest btree-1.3 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 3.0 YYY\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nYYYLine 3\\n\"\ntest btree-1.4 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 2.1 X\\nYY\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLX\\nYYine 2\\nLine 3\\n\"\ntest btree-1.5 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 2.0 X\\n\\n\\n\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nX\\n\\n\\nLine 2\\nLine 3\\n\"\ntest btree-1.6 {basic insertions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 2.6 X\\n\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2X\\n\\nLine 3\\n\"\ntest btree-1.7 {insertion before start of text} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 0.4 XXX\n    .t get 1.0 1000000.0\n} -result \"XXXLine 1\\nLine 2\\nLine 3\\n\"\ntest btree-1.8 {insertion past end of text} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 100.0 ZZ\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3ZZ\\n\"\ntest btree-1.9 {insertion before start of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 2.-3 Q\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nQLine 2\\nLine 3\\n\"\ntest btree-1.10 {insertion past end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 2.40 XYZZY\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2XYZZY\\nLine 3\\n\"\ntest btree-1.11 {insertion past end of last line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t insert 3.40 ABC\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3ABC\\n\"\n\n\ntest btree-2.1 {basic deletions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.0 1.3\n    .t get 1.0 1000000.0\n} -result \"e 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.2 {basic deletions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 2.2\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLie 2\\nLine 3\\n\"\ntest btree-2.3 {basic deletions} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 2.0 2.3\n    .t get 1.0 1000000.0\n} -result \"Line 1\\ne 2\\nLine 3\\n\"\ntest btree-2.4 {deleting whole lines} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.2 3.0\n    .t get 1.0 1000000.0\n} -result \"LiLine 3\\n\"\ntest btree-2.5 {deleting whole lines} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\n\\n\\nLine 5\"\n    .t delete 1.0 5.2\n    .t get 1.0 1000000.0\n} -result \"ne 5\\n\"\ntest btree-2.6 {deleting before start of file} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 0.3 1.2\n    .t get 1.0 1000000.0\n} -result \"ne 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.7 {deleting after end of file} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 10.3\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.8 {deleting before start of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.-1 3.3\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\ne 3\\n\"\ntest btree-2.9 {deleting before start of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.-1 1.0\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.10 {deleting after end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.8 2.1\n    .t get 1.0 1000000.0\n} -result \"Line 1ine 2\\nLine 3\\n\"\ntest btree-2.11 {deleting after end of last line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.8 4.1\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.12 {deleting before start of file} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.8 0.0\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.13 {deleting past end of file} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.8 4.0\n    .t get 1.0 1000000.0\n} -result \"Line 1\\n\"\ntest btree-2.14 {deleting with end before start of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.3 2.-3\n    .t get 1.0 1000000.0\n} -result \"LinLine 2\\nLine 3\\n\"\ntest btree-2.15 {deleting past end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.3 1.9\n    .t get 1.0 1000000.0\n} -result \"Lin\\nLine 2\\nLine 3\\n\"\ntest btree-2.16 {deleting past end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.2 3.15\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLi\\n\"\ntest btree-2.17 {deleting past end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.0 3.15\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\n\\n\"\ntest btree-2.18 {deleting past end of line} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 1.0 3.15\n    .t get 1.0 1000000.0\n} -result \"\\n\"\ntest btree-2.19 {deleting with negative range} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.2 2.4\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.20 {deleting with negative range} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.2 3.1\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.21 {deleting with negative range} -body {\n    .t delete 1.0 100000.0\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    .t delete 3.2 3.2\n    .t get 1.0 1000000.0\n} -result \"Line 1\\nLine 2\\nLine 3\\n\"\ntest btree-2.22 {deleting into beginning of elided range} -setup {\n    .t delete 1.0 end\n} -body {\n    for {set n 1} {$n <= 10} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 end\n    .t delete 5.0 \"5.0 + 8 chars\"\n    .t get 4.0 7.0\n} -cleanup {\n    .t tag delete Elided\n    .t delete 1.0 end\n} -result \"Line 4\\nine 6\\nLine 7\\n\"\ntest btree-2.23 {deleting from within elided range} -body {\n    for {set n 1} {$n <= 10} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 8.0\n    .t delete 7.0 9.0\n    .t get 6.0 8.0\n} -cleanup {\n    .t tag delete Elided\n    .t delete 1.0 end\n} -result \"Line 6\\nLine 9\\n\"\ntest btree-2.24 {deleting whole elided range} -body {\n    for {set n 1} {$n <= 10} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 8.0\n    .t delete 5.0 9.0\n    .t get 4.0 6.0\n} -cleanup {\n    .t tag delete Elided\n    .t delete 1.0 end\n} -result \"Line 4\\nLine 9\\n\"\ntest btree-2.25 {deleting several elided ranges} -body {\n    for {set n 1} {$n <= 10} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 6.2 6.4 6.5 7.2 7.6\n    .t delete 5.0 9.0\n    .t get 4.0 7.0\n} -cleanup {\n    .t tag delete Elided\n    .t delete 1.0 end\n} -result \"Line 4\\nLine 9\\nLine 10\\n\"\ntest btree-2.26 {deleting first char of elided range} -body {\n    for {set n 1} {$n <= 10} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 end\n    .t delete 6.0 6.1\n    .t get 5.0 7.0\n} -cleanup {\n    .t tag delete Elided\n    .t delete 1.0 end\n} -result \"Line 5\\nine 6\\n\"\n\n\ntest btree-3.1 {inserting with tags} -body {\n    setup\n    .t insert 1.0 XXX\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.4 1.5 1.8 1.16 2.2 2.6} {1.8 1.9}}\ntest btree-3.2 {inserting with tags} -body {\n    setup\n    .t insert 1.15 YYY\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.13 2.2 2.6} {1.5 1.6}}\ntest btree-3.3 {inserting with tags} -body {\n    setup\n    .t insert 1.7 ZZZZ\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.17 2.2 2.6} {1.5 1.6}}\ntest btree-3.4 {inserting with tags} -body {\n    setup\n    .t insert 1.7 \\n\\n\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 3.6 4.2 4.6} {1.5 1.6}}\ntest btree-3.5 {inserting with tags} -body {\n    setup\n    .t insert 1.5 A\\n\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 2.0 2.8 3.2 3.6} {2.0 2.1}}\ntest btree-3.6 {inserting with tags} -body {\n    setup\n    .t insert 1.13 A\\n\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.13 3.2 3.6} {1.5 1.6}}\n\n\ntest btree-4.1 {deleting with tags} -body {\n    setup\n    .t delete 1.6 1.9\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.10 2.2 2.6} {1.5 1.6}}\ntest btree-4.2 {deleting with tags} -body {\n    setup\n    .t delete 1.1 2.3\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.4} {}}\ntest btree-4.3 {deleting with tags} -body {\n    setup\n    .t delete 1.4 2.1\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.9} {}}\ntest btree-4.4 {deleting with tags} -body {\n    setup\n    .t delete 1.14 2.1\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.13 1.15 1.19} {1.5 1.6}}\ntest btree-4.5 {deleting with tags} -body {\n    setup\n    .t delete 1.0 2.10\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{} {}}\ntest btree-4.6 {deleting with tags} -body {\n    setup\n    .t delete 1.0 1.5\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.0 1.8 2.2 2.6} {1.0 1.1}}\ntest btree-4.7 {deleting with tags} -body {\n    setup\n    .t delete 1.6 1.9\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 1.5 1.10 2.2 2.6} {1.5 1.6}}\ntest btree-4.8 {deleting with tags} -body {\n    setup\n    .t delete 1.5 1.13\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 2.2 2.6} {}}\n\n\ntest btree-5.1 {very large inserts, with tags} -setup {\n    set bigText1 {}\n    for {set i 0} {$i < 10} {incr i} {\n\tappend bigText1 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.0 $bigText1\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{11.1 11.2 11.5 11.13 12.2 12.6} {11.5 11.6}}\ntest btree-5.2 {very large inserts, with tags} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.2 $bigText2\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.1 1.2 201.3 201.11 202.2 202.6} {201.3 201.4}}\ntest btree-5.3 {very large inserts, with tags} -body {\n    setup\n    for {set i 0} {$i < 200} {incr i} {\n\t.t insert 1.8 \"longer line $i\\n\"\n    }\n    list [.t tag ranges x] [.t tag ranges y] [.t get 1.0 1.100] \\\n\t[.t get 198.0 198.100]\n} -result {{1.1 1.2 1.5 201.5 202.2 202.6} {1.5 1.6} {Text forlonger line 199} {longer line 2}}\n\n\ntest btree-6.1 {very large deletes, with tags}  -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    .t delete 1.2 201.2\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.4 1.12 2.2 2.6} {1.4 1.5}}\ntest btree-6.2 {very large deletes, with tags}  -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    for {set i 0} {$i < 200} {incr i} {\n\t.t delete 1.2 2.2\n    }\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{1.4 1.12 2.2 2.6} {1.4 1.5}}\ntest btree-6.3 {very large deletes, with tags}  -setup {\n    set bigText2 {}\n     for {set i 0} {$i < 200} {incr i} {\n\t    append bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    .t delete 2.3 10000.0\n    .t get 1.0 1000.0\n} -result {TLine 0\nLin\n}\ntest btree-6.4 {very large deletes, with tags} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    for {set i 0} {$i < 100} {incr i} {\n\t.t delete 30.0 31.0\n    }\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{101.0 101.1 101.4 101.12 102.2 102.6} {101.4 101.5}}\ntest btree-6.5 {very large deletes, with tags} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    for {set i 0} {$i < 100} {incr i} {\n\tset j [expr {$i+2}]\n\tset k [expr {1+2*$i}]\n\t.t tag add x $j.1 $j.3\n\t.t tag add y $k.1 $k.6\n    }\n    .t delete 2.0 200.0\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{3.0 3.1 3.4 3.12 4.2 4.6} {1.1 1.6 3.4 3.5}}\ntest btree-6.6 {very large deletes, with tags} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.1 $bigText2\n    for {set i 0} {$i < 100} {incr i} {\n\tset j [expr {$i+2}]\n\tset k [expr {1+2*$i}]\n\t.t tag add x $j.1 $j.3\n\t.t tag add y $k.1 $k.6\n    }\n    for {set i 199} {$i >= 2} {incr i -1} {\n\t.t delete $i.0 [expr {$i+1}].0\n    }\n    list [.t tag ranges x] [.t tag ranges y]\n} -result {{3.0 3.1 3.4 3.12 4.2 4.6} {1.1 1.6 3.4 3.5}}\n\n\ntest btree-7.1 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.3 1.6 1.7 2.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.3 1.6 1.7 2.0}\ntest btree-7.2 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.3 1.6 1.6 2.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.3 2.0}\ntest btree-7.3 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.3 1.6 1.4 2.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.3 2.0}\ntest btree-7.4 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {2.0 4.3 1.4 1.10}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.4 1.10 2.0 4.3}\ntest btree-7.5 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {2.0 4.3 1.4 1.end}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.4 1.19 2.0 4.3}\ntest btree-7.6 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {2.0 4.3 1.4 2.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.4 4.3}\ntest btree-7.7 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {2.0 4.3 1.4 3.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.4 4.3}\ntest btree-7.8 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.2 1.3 1.6 1.7 1.end 2.0 2.4 2.7 3.0 4.0 1.1 4.2}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.1 4.2}\ntest btree-7.9 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.2 1.3 1.6 1.7 1.end 2.0 2.4 2.7 3.0 4.0 1.3 4.2}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.2 4.2}\ntest btree-7.10 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.2 1.3 1.6 1.7 1.end 2.0 2.4 2.7 3.0 4.0 1.1 3.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.1 4.0}\ntest btree-7.11 {tag addition and removal} -setup {\n    .t delete 1.0 end\n    .t tag remove x 1.0 end\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    set check {1.2 1.3 1.6 1.7 1.end 2.0 2.4 2.7 3.0 4.0 1.2 3.0}\n    while {[llength $check]} {\n\t.t tag add x [lindex $check 0] [lindex $check 1]\n\tset check [lrange $check 2 end]\n    }\n    .t tag ranges x\n} -result {1.2 4.0}\n\n\ntest btree-8.1 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 0.0 1.3\n    .t tag ranges x\n} -result {1.0 1.3}\ntest btree-8.2 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 1.40 2.4\n    .t tag ranges x\n} -result {1.19 2.4}\ntest btree-8.3 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 4.40 4.41\n    .t tag ranges x\n} -result {}\ntest btree-8.4 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 5.1 5.2\n    .t tag ranges x\n} -result {}\ntest btree-8.5 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 1.1 9.0\n    .t tag ranges x\n} -result {1.1 5.0}\ntest btree-8.6 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 1.1 1.90\n    .t tag ranges x\n} -result {1.1 1.19}\ntest btree-8.7 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 1.1 4.90\n    .t tag ranges x\n} -result {1.1 4.17}\ntest btree-8.8 {tag addition and removal, weird ranges} -body {\n    .t delete 1.0 100000.0\n    .t tag delete x\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 3.0 3.0\n    .t tag ranges x\n} -result {}\n\n\ntest btree-9.1 {tag names} -body {\n    setup\n    .t tag names\n} -result {sel x y}\ntest btree-9.2 {tag names} -body {\n    setup\n    .t tag add tag1 1.8\n    .t tag add tag2 1.8\n    .t tag add tag3 1.7 1.9\n    .t tag names 1.8\n} -result {x tag1 tag2 tag3}\ntest btree-9.3 {lots of tag names} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.2 $bigText2\n    foreach i {tag1 foo ThisOne {x space} q r s t} {\n    .t tag add $i 150.2\n    }\n    foreach i {u tagA tagB tagC and more {$} \\{} {\n    .t tag add $i 150.1 150.3\n    }\n    .t tag names 150.2\n} -result {tag1 foo ThisOne {x space} q r s t u tagA tagB tagC and more {$} \\{}\ntest btree-9.4 {lots of tag names} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.2 $bigText2\n    .t tag delete tag1 foo ThisOne more {x space} q r s t u\n    .t tag delete tagA tagB tagC and {$} \\{ more\n    foreach i {tag1 foo ThisOne more {x space} q r s t} {\n    .t tag add $i 150.2\n    }\n    foreach i {foo ThisOne u tagA tagB tagC and more {$} \\{} {\n    .t tag add $i 150.4\n    }\n    .t tag delete tag1 more q r tagA\n    .t tag names 150.2\n} -result {foo ThisOne {x space} s t}\n\n\ntest btree-10.1 {basic mark facilities} -body {\n    msetup\n    list [lsort [.t mark names]] [.t index m1] [.t index m2] [.t index m3]\n} -result {{current insert l1 m1 m2 m3 next x} 1.2 2.0 2.11}\ntest btree-10.2 {basic mark facilities} -body {\n    msetup\n    .t mark unset m2\n    lsort [.t mark names]\n} -result {current insert l1 m1 m3 next x}\ntest btree-10.3 {basic mark facilities} -body {\n    msetup\n    .t mark set m2 1.8\n    list [lsort [.t mark names]] [.t index m1] [.t index m2] [.t index m3]\n} -result {{current insert l1 m1 m2 m3 next x} 1.2 1.8 2.11}\n\n\ntest btree-11.1 {marks and inserts} -body {\n    msetup\n    .t insert 1.1 abcde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.7 1.7 1.11 1.11 2.0 2.11}\ntest btree-11.2 {marks and inserts} -body {\n    msetup\n    .t insert 1.2 abcde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.7 1.11 1.11 2.0 2.11}\ntest btree-11.3 {marks and inserts} -body {\n    msetup\n    .t insert 1.3 abcde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.11 1.11 2.0 2.11}\ntest btree-11.4 {marks and inserts} -body {\n    msetup\n    .t insert 1.1 ab\\n\\ncde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {3.4 3.4 3.8 3.8 4.0 4.11}\ntest btree-11.5 {marks and inserts} -body {\n    msetup\n    .t insert 1.4 ab\\n\\ncde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 3.5 3.5 4.0 4.11}\ntest btree-11.6 {marks and inserts} -body {\n    msetup\n    .t insert 1.7 ab\\n\\ncde\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.6 1.6 4.0 4.11}\n\n\ntest btree-12.1 {marks and deletes} -body {\n    msetup\n    .t delete 1.3 1.5\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.4 1.4 2.0 2.11}\ntest btree-12.2 {marks and deletes} -body {\n    msetup\n    .t delete 1.3 1.8\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.3 1.3 2.0 2.11}\ntest btree-12.3 {marks and deletes} -body {\n    msetup\n    .t delete 1.2 1.8\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.2 1.2 2.0 2.11}\ntest btree-12.4 {marks and deletes} -body {\n    msetup\n    .t delete 1.1 1.8\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.1 1.1 1.1 1.1 2.0 2.11}\ntest btree-12.5 {marks and deletes} -body {\n    msetup\n    .t delete 1.5 3.1\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.5 1.5 1.5 1.5}\ntest btree-12.6 {marks and deletes} -body {\n    msetup\n    .t mark set m2 4.5\n    .t delete 1.5 4.1\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.2 1.5 1.5 1.9 1.5}\ntest btree-12.7 {marks and deletes} -body {\n    msetup\n    .t mark set m2 4.5\n    .t mark set m3 4.5\n    .t mark set m1 4.7\n    .t delete 1.5 4.1\n    list [.t index l1] [.t index m1] [.t index next] [.t index x] [.t index m2] [.t index m3]\n} -result {1.2 1.11 1.5 1.5 1.9 1.9}\n\n\ntest btree-13.1 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag next x 2.2 2.1\n} -result {}\ntest btree-13.2 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.2 2.4\n    .t tag next x 2.2 2.3\n} -result {2.2 2.4}\ntest btree-13.3 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.2 2.4\n    .t tag next x 2.3 2.6\n} -result {}\ntest btree-13.4 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.5 2.8\n    .t tag next x 2.1 2.6\n} -result {2.5 2.8}\ntest btree-13.5 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.5 2.8\n    .t tag next x 2.1 2.5\n} -result {}\ntest btree-13.6 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.1 2.4\n    .t tag next x 2.5 2.8\n} -result {}\ntest btree-13.7 {tag searching} -setup {\n    .t delete 1.0 100000.0\n} -body {\n    .t insert 1.0 \"Text for first line\\nSecond line\\n\\nLast line of info\"\n    .t tag add x 2.5 2.8\n    .t tag next x 2.1 2.4\n} -result {}\ntest btree-13.8 {tag searching} -setup {\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.2 $bigText2\n    .t tag add x 190.3 191.2\n    .t tag next x 3.5\n} -result {190.3 191.2}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\ntest btree-14.1 {check tag presence} -setup {\n    destroy .t\n    text .t\n    set bigText2 {}\n    for {set i 0} {$i < 200} {incr i} {\n\tappend bigText2 \"Line $i\\n\"\n    }\n} -body {\n    setup\n    .t insert 1.2 $bigText2\n    .t tag add x 3.5 3.7\n    .t tag add y 133.9 141.5\n    .t tag add z 1.5 180.2\n    .t tag add q 141.4 142.3\n    .t tag add x 130.2 145.1\n    .t tag add a 141.0\n    .t tag add b 4.3\n    .t tag add b 7.5\n    .t tag add b 140.3\n    for {set i 120} {$i < 160} {incr i} {\n    .t tag add c $i.4\n    }\n    foreach i {a1 a2 a3 a4 a5 a6 a7 a8 a9 10 a11 a12 a13} {\n    .t tag add $i 122.2\n    }\n    .t tag add x 141.3\n    .t tag names 141.1\n} -cleanup {\n    destroy .t\n} -result {x y z}\ntest btree-14.2 {TkTextIsElided} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t delete 1.0 end\n    .t tag config hidden -elide 1\n    .t insert end \"Line1\\nLine2\\nLine3\\n\"\n    .t tag add hidden 2.0 3.0\n    .t tag add sel 1.2 3.2\n    # next line used to panic because of \"Bad tag priority being toggled on\"\n    # (see bug [382da038c9])\n    .t index \"2.0 - 1 display line linestart\"\n} -cleanup {\n    destroy .t\n} -result {1.0}\n\ntest btree-15.1 {rebalance with empty node} -setup {\n    destroy .t\n} -body {\n    text .t\n    .t debug 1\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\\n18\\n19\\n20\\n21\\n22\\n23\"\n    .t delete 6.0 12.0\n    .t get 1.0 end\n} -cleanup {\n    destroy .t\n} -result \"1\\n2\\n3\\n4\\n5\\n12\\n13\\n14\\n15\\n16\\n17\\n18\\n19\\n20\\n21\\n22\\n23\\n\"\n\n\ntest btree-16.1 {add tag does not push root above level 0} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t debug 0\n    .t tag add x 1.1 1.10\n    .t tag add x 5.1 5.10\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 1.10 5.1 5.10}\ntest btree-16.2 {add tag pushes root up to level 1 node} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 1.10\n    .t tag add x 8.1 8.10\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 1.10 8.1 8.10}\ntest btree-16.3 {add tag pushes root up to level 2 node} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 8.1 9.10\n    .t tag add x 180.1 180.end\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {8.1 9.10 180.1 180.23}\ntest btree-16.4 {add tag pushes root up to level 3 node} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add y 1.1 2000.0\n    .t tag add x 1.1 8.10\n    .t tag add x 180.end 217.0\n    list [.t tag ranges x] [.t tag ranges y]\n} -cleanup {\n    destroy .t\n} -result {{1.1 8.10 180.23 217.0} {1.1 2000.0}}\ntest btree-16.5 {add tag doesn't push root up} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 8.10\n    .t tag add x 2000.0 2000.3\n    .t tag add x 180.end 217.0\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 8.10 180.23 217.0 2000.0 2000.3}\ntest btree-16.6 {two node splits at once pushes root up} -setup {\n    destroy .t\n    text .t\n} -body {\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n    .t tag add x 8.0 8.end\n    .t tag add y 9.0 end\n    set x {}\n    for {} {$i < 50} {incr i} {\n\tappend x \"Line $i\\n\"\n    }\n    .t insert end $x y\n    list [.t tag ranges x] [.t tag ranges y]\n} -cleanup {\n    destroy .t\n} -result {{8.0 8.6} {9.0 51.0}}\n# The following find bugs in the SearchStart procedures\ntest btree-16.7 {Partial tag remove from before first range} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 2.0 2.6\n    .t tag remove x 1.0 2.0\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {2.0 2.6}\ntest btree-16.8 {Partial tag remove from before first range} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 2.0 2.6\n    .t tag remove x 1.0 2.1\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {2.1 2.6}\ntest btree-16.9 {Partial tag remove from before first range} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 2.0 2.6\n    .t tag remove x 1.0 2.3\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {2.3 2.6}\ntest btree-16.10 {Partial tag remove from before first range} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 1.0 2.6\n    .t tag remove x 1.0 2.5\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {2.5 2.6}\ntest btree-16.11 {StartSearchBack boundary case} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 1.3 1.4\n    .t tag prevr x 2.0 1.4\n} -cleanup {\n    destroy .t\n} -result {}\ntest btree-16.12 {StartSearchBack boundary case} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 1.3 1.4\n    .t tag prevr x 2.0 1.3\n} -cleanup {\n    destroy .t\n} -result {1.3 1.4}\ntest btree-16.13 {StartSearchBack boundary case} -setup {\n    destroy .t\n    text .t\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i\\n\"\n    }\n} -body {\n    .t tag add x 1.0 1.4\n    .t tag prevr x 1.3\n} -cleanup {\n    destroy .t\n} -result {1.0 1.4}\n\n\ntest btree-17.1 {remove tag does not push root down} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t debug 0\n    setupBig\n    .t tag add x 1.1 5.10\n    .t tag remove x 3.1 5.end\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 3.1}\ntest btree-17.2 {remove tag pushes root from level 1 to level 0} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 8.10\n    .t tag remove x 3.1 end\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 3.1}\ntest btree-17.3 {remove tag pushes root from level 2 to level 1} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 180.10\n    .t tag remove x 35.1 end\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 35.1}\ntest btree-17.4 {remove tag doesn't change level 2} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 180.10\n    .t tag remove x 35.1 180.0\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1.1 35.1 180.0 180.10}\ntest btree-17.5 {remove tag pushes root from level 3 to level 0} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 1.10\n    .t tag add x 2000.1 2000.10\n    .t tag remove x 1.0 2000.0\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {2000.1 2000.10}\ntest btree-17.6 {text deletion pushes root from level 3 to level 0} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.1 1.10\n    .t tag add x 2000.1 2000.10\n    .t delete 1.0 \"1000.0 lineend +1 char\"\n    .t tag ranges x\n} -cleanup {\n    destroy .t\n} -result {1000.1 1000.10}\n\n\ntest btree-18.1 {tag search back, no tag} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag prev x 1.1 1.1\n} -cleanup {\n    destroy .t\n} -result {}\ntest btree-18.2 {tag search back, start at existing range} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.8 1.11\n    .t tag add x 1.16\n    .t tag prev x 1.1\n} -cleanup {\n    destroy .t\n} -result {}\ntest btree-18.3 {tag search back, end at existing range} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.8 1.11\n    .t tag add x 1.16\n    .t tag prev x 1.3 1.1\n} -cleanup {\n    destroy .t\n} -result {1.1 1.4}\ntest btree-18.4 {tag search back, start within range} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.8 1.11\n    .t tag add x 1.16\n    .t tag prev x 1.10 1.0\n} -cleanup {\n    destroy .t\n} -result {1.8 1.11}\ntest btree-18.5 {tag search back, start at end of range} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.8 1.11\n    .t tag add x 1.16\n    list [.t tag prev x 1.4 1.0] [.t tag prev x 1.11 1.0]\n} -cleanup {\n    destroy .t\n} -result {{1.1 1.4} {1.8 1.11}}\ntest btree-18.6 {tag search back, start beyond range, same level 0 node} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.8 1.11\n    .t tag add x 1.16\n    .t tag prev x 3.0\n} -cleanup {\n    destroy .t\n} -result {1.16 1.17}\ntest btree-18.7 {tag search back, outside any range} -setup {\n    destroy .t\n    text .t\n} -body {\n    .t insert 1.0 \"Line 1 abcd efgh ijkl\\n\"\n    .t tag add x 1.1 1.4\n    .t tag add x 1.16\n    .t tag prev x 1.8 1.5\n} -cleanup {\n    destroy .t\n} -result {}\ntest btree-18.8 {tag search back, start at start of node boundary} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 2.5 2.8\n    .t tag prev x 19.0\n} -cleanup {\n    destroy .t\n} -result {2.5 2.8}\ntest btree-18.9 {tag search back, large complex btree spans} -setup {\n    destroy .t\n    text .t\n} -body {\n    setupBig\n    .t tag add x 1.3 1.end\n    .t tag add x 200.0 220.0\n    .t tag add x 500.0 520.0\n    list [.t tag prev x end] [.t tag prev x 433.0]\n} -cleanup {\n    destroy .t\n} -result {{500.0 520.0} {200.0 220.0}}\n\n#\n# TESTFILE CLEANUP\n#\n\nrename setup {}\ncleanupTests\n"
  },
  {
    "path": "tests/textDisp.test",
    "content": "# This file is a Tcl script to test the code in the file tkTextDisp.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import scroll text\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc bizarre_scroll args {\n    .t2.t delete 5.0 end\n}\n\n# lequal --\n#\n# Return 1 if the two given lists are the same, otherwise return the two lists.\n# This is used to compare a test actual result with a test expected result.\n#\nproc lequal {res expected} {\n    if {[llength $res] != [llength $expected]} {\n\treturn [list \"Lengths differ\"  result: $res - expected: $expected]\n    }\n    for {set i 0} {$i < [llength $res]} {incr i} {\n\tif {[lindex $res $i] ne [lindex $expected $i]} {\n\t    return [list result: $res - expected: $expected]\n\t}\n    }\n    return 1\n}\n\n# delay --\n#\n# Wait long enough for the asynchronous updates performed by the text widget to run.\n#\nproc delay {} {\n    update\n    after 100\n    update\n}\n\n# scrollError --\n#\n# Generate errors during scrolling commands\n#\nproc scrollError args {\n    error \"scrolling error\"\n}\n\n# xcharr --\n#\n# Return x-coordinate in widget $w of the first pixel of $n-th char\n# counted from the right, right justified\n#\nproc xcharr {n {w .t}} {\n    return [expr {[winfo width $w] - [bo $w] - [xw $n]}]\n}\n\n# xe --\n#\n# Return x-pixels of empty space in widget $w on a line containing $n chars\n#\nproc xe {n {w .t}} {\n    return [expr {[winfo width $w] - (2 * [bo $w]) - [xw $n]}]\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# Create entries in the option database to be sure that geometry options\n# like border width have selected values.\noption add *Text.borderWidth 2         ; # tests work with [1-3]\noption add *Text.highlightThickness 2  ; # tests work with [0-5]\noption add *Text.padX 1  ; # same padding in x and y, see proc bo; tests work with [0-4]\noption add *Text.padY 1  ; # same padding in x and y, see proc bo; tests work with [0-4]\n\n# The frame .f is needed to make sure that the overall window is always\n# fairly wide, even if the text window is very narrow.  This is needed\n# because some window managers don't allow the overall width of a window\n# to get very narrow.\n\ncatch {destroy .f .t}\nframe .f -width 100 -height 20\npack .f -side left\n\nset bigFont {Helvetica -24}  ; # note: not a fixed-width font!\nset bigHeight [font metrics $bigFont -linespace]\nset bigAscent [font metrics $bigFont -ascent]\n\nset ascentDiff [expr {$bigAscent - $fixedAscent}]\nset heightDiff [expr {$bigHeight - $fixedHeight}]\n\n# On Windows at least, the tests do work with {Courier -10}, {Courier -12} or {Courier -14} as fixedFont.\n# Warn the user if the actual font is too different from what was requested.\nif {[font metrics [font actual $fixedFont] -fixed] != 1} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\ndoes not seem to be a fixed-width font as expected. If this is really the case, many upcoming\\\ntests will fail.\"\n}\nif {$fixedHeight < 12 || $fixedHeight > 17} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\nis $fixedHeight pixels height while the tests expect between 12 and 17 (inclusive) pixels.\\\nSome of the upcoming tests will probably fail.\"\n}\nif {$fixedWidth < 6 || $fixedWidth > 8} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\nis $fixedWidth pixels in width while the tests expect between 6 and 8 (inclusive) pixels.\\\nSome of the upcoming tests will probably fail.\"\n}\n\n# Option  -width 20  (characters) below is a fundamental assumption of many\n# upcoming tests when wrapping enters in play\n# Also  -height 10  (lines) is an important assumption\ntext .t -font $fixedFont -width 20 -height 10 -yscrollcommand setScrollInfo\npack .t -expand 1 -fill both\n.t tag configure big -font $bigFont\n.t debug on\n\nwm geometry . {}\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\nupdate\n\n# Some window managers (like olwm under SunOS 4.1.3) misbehave in a way\n# that tends to march windows off the top and left of the screen.  If\n# this happens, some tests will fail because parts of the window will\n# not need to be displayed (because they're off-screen).  To keep this\n# from happening, move the window if it's getting near the left or top\n# edges of the screen.\n\nif {([winfo rooty .] < 50) || ([winfo rootx .] < 50)} {\n    wm geom . +50+50\n}\n\n#\n# TESTS\n#\n\ntest textDisp-0.1 {double tag elide transition} {\n    # Example from tkchat crash.  For some reason can only\n    # get this test case to crash when first.\n    catch {destroy .top}\n    pack [text .top]\n\n    foreach val {0 1 2 3} {\n\t.top insert 1.0 \"hello\\n\"\n\t.top tag configure tag$val\n\t.top tag add tag$val 1.0 2.0\n\tset ::Options(tag$val) 0\n    }\n\n    proc DoVis {tag} {\n\t.top tag config $tag -elide $::Options($tag)\n    }\n\n    proc NickVis {val} {\n\tforeach t [array names ::Options ] {\n\t    if {$::Options($t) != $val} {\n\t\tset ::Options($t) $val\n\t\tDoVis $t\n\t    }\n\t}\n    }\n    NickVis 1\n    unset ::Options\n    destroy .top\n} {}\n\ntest textDisp-0.2 {double tag elide transition} {\n    # Example from tkchat crash.  For some reason can only\n    # get this test case to crash when first.\n    catch {destroy .top}\n    pack [text .top]\n\n    foreach val {0 1 2 3} {\n\t.top insert 1.0 \"hello\"\n\t.top tag configure tag$val\n\t.top tag add tag$val 1.0 1.5\n\tset ::Options(tag$val) 0\n    }\n\n    proc DoVis {tag} {\n\t.top tag config $tag -elide $::Options($tag)\n    }\n\n    proc NickVis {val} {\n\tforeach t [array names ::Options ] {\n\t    if {$::Options($t) != $val} {\n\t\tset ::Options($t) $val\n\t\tDoVis $t\n\t    }\n\t}\n    }\n    NickVis 1\n    unset ::Options\n    destroy .top\n} {}\n\ntest textDisp-0.3 {double tag elide transition} {\n    catch {destroy .txt}\n    pack [text .txt]\n    # Note that TRAFFIC should have a higher priority than SYSTEM\n    # in terms of the tag effects.\n    .txt tag configure SYSTEM -elide 0\n    .txt tag configure TRAFFIC -elide 1\n    .txt insert end \"\\n\" {TRAFFIC SYSTEM}\n    update\n    destroy .txt\n} {}\n\ntest textDisp-0.4 {double tag elide transition} {\n    catch {destroy .txt}\n    pack [text .txt]\n    # Note that TRAFFIC should have a higher priority than SYSTEM\n    # in terms of the tag effects.\n    .txt tag configure SYSTEM -elide 0\n    .txt tag configure TRAFFIC -elide 1\n    .txt insert end \"\\n\" {SYSTEM TRAFFIC}\n    # Crash was here.\n    update\n    destroy .txt\n} {}\n\ntest textDisp-0.5 {double tag elide transition} {\n    catch {destroy .txt}\n    pack [text .txt]\n    .txt tag configure WELCOME -elide 1\n    .txt tag configure SYSTEM -elide 0\n    .txt tag configure TRAFFIC -elide 1\n\n    .txt insert end \"\\n\" {SYSTEM TRAFFIC}\n    .txt insert end \"\\n\" WELCOME\n    # Crash was here.\n    update\n    destroy .txt\n} {}\n\ntest textDisp-1.1 {GetStyle procedure, priorities and tab stops} {\n    .t delete 1.0 end\n    .t insert 1.0 \"x\\ty\"\n    .t tag delete x y z\n    .t tag configure x -tabs 50\n    .t tag configure y -foreground black\n    .t tag configure z -tabs 70\n    .t tag add x 1.0 1.end\n    .t tag add y 1.0 1.end\n    .t tag add z 1.0 1.end\n    update idletasks\n    set x [lindex [.t bbox 1.2] 0]\n    .t tag configure z -tabs {}\n    lappend x [lindex [.t bbox 1.2] 0]\n    .t tag configure z -tabs 30\n    .t tag raise x\n    update idletasks\n    lappend x [lindex [.t bbox 1.2] 0]\n} [list [expr {[bo]+70}] [expr {[bo]+50}] [expr {[bo]+50}]]\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag delete x y z\n\ntest textDisp-1.2 {GetStyle procedure, wrapmode} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcd\\nefg hijkl mnop qrstuv wxyz\"\n    .t tag configure x -wrap word\n    .t tag configure y -wrap none\n    .t tag raise y\n    update\n    set result [list [.t bbox 2.20]]\n    .t tag add x 2.0 2.1\n    lappend result [.t bbox 2.20]\n    .t tag add y 1.end 2.2\n    lappend result [.t bbox 2.20]\n} [list [list [xchar 0] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 5] [yline 3] $fixedWidth $fixedHeight] \\\n\t    {}]\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag delete x y\n\ntest textDisp-2.1 {LayoutDLine, basics} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"This is some sample text for testing.\"\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.2 {LayoutDLine, basics} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"This isx some sample text for testing.\"\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.3 {LayoutDLine, basics} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"This isxxx some sample text for testing.\"\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.4 {LayoutDLine, word wrap} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This is some sample text for testing.\"\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.5 {LayoutDLine, word wrap} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This isx some sample text for testing.\"\n    list [.t bbox 1.13] [.t bbox 1.19] [.t bbox 1.20] [.t bbox 1.21]\n} [list [list [xchar 13] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t    [list [xchar 20] [yline 1] 0  $fixedHeight] \\\n\t    [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.6 {LayoutDLine, word wrap} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This isxxx some sample text for testing.\"\n    list [.t bbox 1.15] [.t bbox 1.16]\n} [list [list [xchar 15] [yline 1] [xe 15] $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.7 {LayoutDLine, marks and tags} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This isxxx some sample text for testing.\"\n    .t tag add foo 1.4 1.6\n    .t mark set insert 1.8\n    list [.t bbox 1.2] [.t bbox 1.5] [.t bbox 1.11]\n} [list [list [xchar 2] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 5] [yline 1] $fixedWidth $fixedHeight] \\\n\t    [list [xchar 11] [yline 1] $fixedWidth $fixedHeight]]\n\n#\n# COMMON TEST CLEANUP\n#\nforeach m [.t mark names] {\n    catch {.t mark unset $m}\n}\n\ntest textDisp-2.8 {LayoutDLine, extra chunk at end of dline} -setup {\n    scan [wm geom .] %dx%d width height\n} -body {\n    wm geom . [expr {$width+1}]x$height\n    update\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"This isxx some sample text for testing.\"\n    .t mark set foo 1.20\n    list [.t bbox 1.19] [.t bbox 1.20]\n} -cleanup {\n    wm geom . {}\n    update\n} -result [list [list [xchar 19] [yline 1] [expr {$fixedWidth+1}] $fixedHeight] \\\n\t\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.9 {LayoutDLine, marks and tags} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This is a very_very_long_word_that_wraps.\"\n    list [.t bbox 1.9] [.t bbox 1.10] [.t bbox 1.25]\n} [list [list [xchar 9] [yline 1] [xe 9] $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t    [list [xchar 15] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.10 {LayoutDLine, marks and tags} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This is a very_very_long_word_that_wraps.\"\n    .t tag add foo 1.13\n    .t tag add foo 1.15\n    .t tag add foo 1.17\n    .t tag add foo 1.19\n    list [.t bbox 1.9] [.t bbox 1.10] [.t bbox 1.25]\n} [list [list [xchar 9] [yline 1] [xe 9] $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t    [list [xchar 15] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-2.11 {LayoutDLine, newline width} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a\\nbb\\nccc\\ndddd\"\n    list [.t bbox 2.2] [.t bbox 3.3]\n} [list [list [xchar 2] [yline 2] [xe 2] $fixedHeight] \\\n\t[list [xchar 3] [yline 3] [xe 3] $fixedHeight]]\ntest textDisp-2.12 {LayoutDLine, justification} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"\\na\\nbb\\nccc\\ndddd\"\n    .t tag configure x -justify center\n    .t tag add x 1.0 end\n    .t tag add y 3.0 3.2\n    list [.t bbox 1.0] [.t bbox 2.0] [.t bbox 4.0] [.t bbox 4.2]\n} [list [list [expr {[bo]+[xe 0]/2}] [yline 1] [expr {[xe 0]-[xe 0]/2}] $fixedHeight] \\\n\t[list [expr {[bo]+[xe 1]/2}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 3]/2}] [yline 4] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 3]/2+[xw 2]}] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.13 {LayoutDLine, justification} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"\\na\\nbb\\nccc\\ndddd\"\n    .t tag configure x -justify right\n    .t tag add x 1.0 end\n    .t tag add y 3.0 3.2\n    list [.t bbox 1.0] [.t bbox 2.0] [.t bbox 4.0] [.t bbox 4.2]\n} [list [list [xcharr 0] [yline 1] 0 $fixedHeight] \\\n\t[list [xcharr 1] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xcharr 3] [yline 4] $fixedWidth $fixedHeight] \\\n\t[list [xcharr 1] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.14 {LayoutDLine, justification} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"\\na\\nbb\\nccc\\ndddd\"\n    .t tag configure x -justify center\n    .t tag add x 2.0 3.1\n    .t tag configure y -justify right\n    .t tag add y 3.0 4.0\n    .t tag raise y\n    list [.t bbox 2.0] [.t bbox 3.0] [.t bbox 3.end] [.t bbox 4.0]\n} [list [list [expr {[bo]+[xe 1]/2}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xcharr 2] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xcharr 0] [yline 3] 0 $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.15 {LayoutDLine, justification} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"\\na\\nbb\\nccc\\ndddd\"\n    .t tag configure x -justify center\n    .t tag add x 2.0 3.1\n    .t tag configure y -justify right\n    .t tag add y 3.0 4.0\n    .t tag lower y\n    list [.t bbox 2.0] [.t bbox 3.0] [.t bbox 3.end] [.t bbox 4.0]\n} [list [list [expr {[bo]+[xe 1]/2}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 2]/2}] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 2]/2+[xw 2]}] [yline 3] [expr {[xe 2]/2}] $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.16 {LayoutDLine, justification} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Lots of long words, enough to force word wrap\\nThen\\nmore lines\"\n    .t tag configure x -justify center\n    .t tag add x 1.1 1.20\n    .t tag add x 1.21 1.end\n    list [.t bbox 1.0] [.t bbox 1.20] [.t bbox 1.41] [.t bbox 2.0]\n} [list [list [xchar 0] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 4]/2}] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.17 {LayoutDLine, justification} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Lots of very long words, enough to force word wrap\\nThen\\nmore lines\"\n    .t tag configure x -justify center\n    .t tag add x 1.18\n    list [.t bbox 1.0] [.t bbox 1.18] [.t bbox 1.35] [.t bbox 2.0]\n} [list [list [xchar 0] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 17]/2}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.18 {LayoutDLine, justification} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert 1.0 \"Lots of long words, enough to extend out of the window\\n\"\n    .t insert end \"Then\\nmore lines\\nThat are shorter\"\n    .t tag configure x -justify center\n    .t tag configure y -justify right\n    .t tag add x 2.0\n    .t tag add y 3.0\n    .t xview scroll 5 units\n    list [.t bbox 2.0] [.t bbox 3.0]\n} [list [list [expr {[bo]+[xe 4]/2-[xw 5]}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[xcharr 10]-[xw 5]}] [yline 3] $fixedWidth $fixedHeight]]\n\n#\n# COMMON TEST CLEANUP\n#\n\n.t tag delete x\n.t tag delete y\n\ntest textDisp-2.19 {LayoutDLine, margins} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Lots of long words, enough to force word wrap\\nThen\\nmore lines\"\n    # margins in pixels depend on the font width for more flexibility\n    set lm1 [expr {3*$fixedWidth}]\n    set lm2 [expr {2*$lm1}]\n    set rm [expr {2*$fixedWidth}]\n    .t tag configure x -lmargin1 $lm1 -lmargin2 $lm2 -rmargin $rm\n    .t tag add x 1.0 end\n    set expected [list [list [expr {[bo]+$lm1}] [yline 1] $fixedWidth $fixedHeight] \\\n\t\t       [list [expr {[bo]+$lm1+[xw 12]}] [yline 1] [expr {[xe 12]-$lm1}] $fixedHeight] \\\n\t\t       [list [expr {[bo]+$lm2}] [yline 2] $fixedWidth $fixedHeight] \\\n\t\t       [list [expr {[bo]+$lm1}] [yline 6] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.0] [.t bbox 1.12] [.t bbox 1.13] [.t bbox 2.0]] $expected\n} {1}\ntest textDisp-2.20 {LayoutDLine, margins} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Lots of long words, enough to force word wrap\\nThen\\nmore lines\"\n    .t tag configure x -lmargin1 20 -lmargin2 10 -rmargin 3\n    .t tag configure y -lmargin1 15 -lmargin2 5 -rmargin 0\n    .t tag raise y\n    .t tag add x 1.0 end\n    .t tag add y 1.13\n    list [.t bbox 1.0] [.t bbox 1.13] [.t bbox 1.30] [.t bbox 2.0]\n} [list [list [expr {[bo]+20}] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+5}] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+10}] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+20}] [yline 4] $fixedWidth $fixedHeight]]\ntest textDisp-2.21 {LayoutDLine, margins} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Sample text\"\n    .t tag configure x -lmargin1 80 -lmargin2 80 -rmargin 100\n    .t tag add x 1.0 end\n    list [.t bbox 1.0] [.t bbox 1.1] [.t bbox 1.2]\n} [list [list [expr {[bo]+80}] [yline 1] [expr {[xe 0]-80}] $fixedHeight] \\\n\t[list [expr {[bo]+80}] [yline 2] [expr {[xe 0]-80}] $fixedHeight] \\\n\t[list [expr {[bo]+80}] [yline 3] [expr {[xe 0]-80}] $fixedHeight]]\n\n#\n# COMMON TEST CLEANUP\n#\n\n.t tag delete x\n.t tag delete y\n\ntest textDisp-2.22 {LayoutDLine, spacing options} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t tag delete x y\n    .t insert end \"Short line\\nLine 2 is long enough \"\n    .t insert end \"to wrap around a couple of times\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    set i [.t dlineinfo 1.0]\n    set b1 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 2.0]\n    set b2 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 2.end]\n    set b3 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 3.0]\n    set b4 [expr {[lindex $i 1] + [lindex $i 4]}]\n    .t configure -spacing1 2 -spacing2 1 -spacing3 3\n    set i [.t dlineinfo 1.0]\n    set b1 [expr {[lindex $i 1] + [lindex $i 4] - $b1}]\n    set i [.t dlineinfo 2.0]\n    set b2 [expr {[lindex $i 1] + [lindex $i 4] - $b2}]\n    set i [.t dlineinfo 2.end]\n    set b3 [expr {[lindex $i 1] + [lindex $i 4] - $b3}]\n    set i [.t dlineinfo 3.0]\n    set b4 [expr {[lindex $i 1] + [lindex $i 4] - $b4}]\n    list $b1 $b2 $b3 $b4\n} [list 2 7 10 15]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -spacing1 0 -spacing2 0 -spacing3 0\n\ntest textDisp-2.23 {LayoutDLine, spacing options} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t tag delete x y\n    .t insert end \"Short line\\nLine 2 is long enough \"\n    .t insert end \"to wrap around a couple of times\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    set i [.t dlineinfo 1.0]\n    set b1 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 2.0]\n    set b2 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 2.end]\n    set b3 [expr {[lindex $i 1] + [lindex $i 4]}]\n    set i [.t dlineinfo 3.0]\n    set b4 [expr {[lindex $i 1] + [lindex $i 4]}]\n    .t configure -spacing1 4 -spacing2 4 -spacing3 4\n    .t tag configure x -spacing1 1 -spacing2 2 -spacing3 3\n    .t tag add x 1.0 end\n    .t tag configure y -spacing1 0 -spacing2 3\n    .t tag add y 2.19 end\n    .t tag raise y\n    set i [.t dlineinfo 1.0]\n    set b1 [expr {[lindex $i 1] + [lindex $i 4] - $b1}]\n    set i [.t dlineinfo 2.0]\n    set b2 [expr {[lindex $i 1] + [lindex $i 4] - $b2}]\n    set i [.t dlineinfo 2.end]\n    set b3 [expr {[lindex $i 1] + [lindex $i 4] - $b3}]\n    set i [.t dlineinfo 3.0]\n    set b4 [expr {[lindex $i 1] + [lindex $i 4] - $b4}]\n    list $b1 $b2 $b3 $b4\n} [list 1 5 13 16]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -spacing1 0 -spacing2 0 -spacing3 0\n\ntest textDisp-2.24 {LayoutDLine, tabs, saving from first chunk} {\n    .t delete 1.0 end\n    .t tag delete x y\n    .t tag configure x -tabs 70\n    .t tag configure y -tabs 80\n    .t insert 1.0 \"ab\\tcde\"\n    .t tag add x 1.0 end\n    .t tag add y 1.1 end\n    lindex [.t bbox 1.3] 0\n} [expr {[bo]+70}]\ntest textDisp-2.25 {LayoutDLine, tabs, breaking chunks at tabs} {\n    .t delete 1.0 end\n    .t tag delete x\n    # compute a tab width allowing to let 4 tab stops (followed by a single char) on a single line\n    set tw [expr {([winfo width .t]-2*[bo]-$fixedWidth)/4}]\n    .t tag configure x -tabs [list $tw [expr {$tw*2}] [expr {$tw*3}] [expr {$tw*4}]]\n    .t insert 1.0 \"a\\tb\\tc\\td\\te\"\n    .t mark set dummy1 1.1\n    .t mark set dummy2 1.2\n    .t tag add x 1.0 end\n    set expected [list [expr {[bo]+$tw}] [expr {[bo]+2*$tw}] [expr {[bo]+3*$tw}] [expr {[bo]+4*$tw}]]\n    set res [list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.4] 0] \\\n\t\t  [lindex [.t bbox 1.6] 0] [lindex [.t bbox 1.8] 0]]\n    lequal $res $expected\n} {1}\n# Next test is currently constrained to not run on mac (aqua) because on\n# aqua it fails due to wrong implementation of tabs with right justification\n# (the text is not rendered at all). This is a bug.\ntest textDisp-2.26 {LayoutDLine, tabs, breaking chunks at tabs} {notAqua} {\n    .t delete 1.0 end\n    .t tag delete x\n    .t tag configure x -tabs [list 30 60 90 120] -justify right\n    .t insert 1.0 \"a\\tb\\tc\\td\\te\"\n    .t mark set dummy1 1.1\n    .t mark set dummy2 1.2\n    .t tag add x 1.0 end\n    list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.4] 0] \\\n\t     [lindex [.t bbox 1.6] 0] [lindex [.t bbox 1.8] 0]\n} [list [xcharr 4] [xcharr 3] [xcharr 2] [xcharr 1]]\ntest textDisp-2.27 {LayoutDLine, tabs, calling AdjustForTab} {\n    .t delete 1.0 end\n    .t tag delete x\n    .t tag configure x -tabs [list 30 60]\n    .t insert 1.0 \"a\\tb\\tcd\"\n    .t tag add x 1.0 end\n    list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.4] 0]\n} [list [expr {[bo]+30}] [expr {[bo]+60}]]\ntest textDisp-2.28 {LayoutDLine, tabs, running out of space in dline} {\n    .t delete 1.0 end\n    .t insert 1.0 \"a\\tb\\tc\\td\"\n    .t bbox 1.6\n} [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]\ntest textDisp-2.29 {LayoutDLine, tabs, running out of space in dline} {\n    .t delete 1.0 end\n    .t insert 1.0 \"a\\tx\\tabcd\"\n    .t bbox 1.4\n} [list [xchar [expr {2*8}]] [yline 1] $fixedWidth $fixedHeight]\ntest textDisp-2.30 {LayoutDLine, tabs, running out of space in dline} {\n    .t delete 1.0 end\n    .t insert 1.0 \"a\\tx\\tabc\"\n    .t bbox 1.4\n} [list [xchar [expr {2*8}]] [yline 1] $fixedWidth $fixedHeight]\n\ntest textDisp-3.1 {different character sizes} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert end \"Some sample text, including both large\\n\"\n    .t insert end \"characters and\\nsmall\\n\"\n    .t insert end \"abc\\nd\\ne\\nfghij\"\n    .t tag add big 1.5 1.10\n    .t tag add big 2.11 2.14\n    list [.t bbox 1.1] [.t bbox 1.6] [.t dlineinfo 1.0] [.t dlineinfo 3.0]\n} [list [list [xchar 1] [expr {[yline 1]+$ascentDiff}] $fixedWidth $fixedHeight] \\\n\t[list [expr {[xchar 5]+[font measure $bigFont s]}] [yline 1] [font measure $bigFont a] $bigHeight] \\\n\t[list [bo] [yline 1] [expr {[xw 5]+[font measure $bigFont sampl]+[xw 2]}] $bigHeight $bigAscent] \\\n\t[list [bo] [expr {[bo]+2*$bigHeight+2*$fixedHeight}] [xw 5] $fixedHeight $fixedAscent]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char\n\ntest textDisp-4.1 {UpdateDisplayInfo, basic} {\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2\\nLine 3\\n\"\n    update\n    .t delete 2.0 2.end\n    update\n    set res $tk_textRelayout\n    .t insert 2.0 \"New Line 2\"\n    update\n    lappend res [.t bbox 1.0] [.t bbox 2.0] [.t bbox 3.0] $tk_textRelayout\n} [list 2.0 \\\n\t[list [xchar 0] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 3] $fixedWidth $fixedHeight] \\\n\t2.0]\ntest textDisp-4.2 {UpdateDisplayInfo, re-use tail of text line} {\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    .t mark set x 2.21\n    .t delete 2.2\n    update\n    set res $tk_textRelayout\n    .t insert 2.0 X\n    update\n    lappend res [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout\n} [list 2.0 2.20 \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 1] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight] \\\n\t{2.0 2.20}]\ntest textDisp-4.3 {UpdateDisplayInfo, tail of text line shifts} {\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    .t mark set x 2.21\n    .t delete 2.2\n    update\n    list [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout\n} [list [list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 4] $fixedWidth $fixedHeight] \\\n\t{2.0 2.20}]\n\n#\n# COMMON TEST CLEANUP\n#\n.t mark unset x\n\ntest textDisp-4.4 {UpdateDisplayInfo, wrap-mode \"none\"} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    list [.t bbox 2.0] [.t bbox 2.25] [.t bbox 3.0] $tk_textRelayout\n} [list [list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t{} \\\n\t[list [xchar 0] [yline 3] $fixedWidth  $fixedHeight] \\\n\t{1.0 2.0 3.0}]\ntest textDisp-4.5 {UpdateDisplayInfo, tiny window} {\n    if {[tk windowingsystem] eq \"win32\"} {\n\twm overrideredirect . 1\n    }\n    wm geom . 103x$height\n    update\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    list [.t bbox 2.0] [.t bbox 2.1] [.t bbox 3.0] $tk_textRelayout\n} [list [list [xchar 0] [yline 2] 1 $fixedHeight] \\\n\t{} \\\n\t[list [xchar 0] [yline 3] 1 $fixedHeight] \\\n\t{1.0 2.0 3.0}]\n\n#\n# COMMON TEST SETUP\n#\n\nif {[tk windowingsystem] eq \"win32\"} {\n    wm overrideredirect . 0\n}\n\ntest textDisp-4.6 {UpdateDisplayInfo, tiny window} {\n    # This test was failing on Windows because the title bar on .\n    # was a certain minimum size and it was interfering with the size\n    # requested.  The \"overrideredirect\" gets rid of the titlebar so\n    # the toplevel can shrink to the appropriate size.  On Unix, setting\n    # the overrideredirect on \".\" confuses the window manager and\n    # causes subsequent tests to fail.\n\n    if {[tk windowingsystem] eq \"win32\"} {\n\twm overrideredirect . 1\n    }\n    frame .f2 -width 20 -height 100\n    pack .f2 -before .f\n    wm geom . 103x103\n    update\n    .t configure -wrap none -borderwidth 2\n    .t delete 1.0 end\n    .t insert end \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    set x [list [.t bbox 1.0] [.t bbox 2.0] $tk_textRelayout]\n    wm overrideredirect . 0\n    update\n    set expected [list [list [xchar 0] [yline 1] 1 1] {} 1.0]\n    lequal $x $expected\n} {1}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .f2}\n.t configure -borderwidth 0 -wrap char\nwm geom . {}\nupdate\n\ntest textDisp-4.7 {UpdateDisplayInfo, filling in extra vertical space} {\n    # This test was failing on Windows because the title bar on .\n    # was a certain minimum size and it was interfering with the size\n    # requested.  The \"overrideredirect\" gets rid of the titlebar so\n    # the toplevel can shrink to the appropriate size.  On Unix, setting\n    # the overrideredirect on \".\" confuses the window manager and\n    # causes subsequent tests to fail.\n\n    if {[tk windowingsystem] eq \"win32\"} {\n\twm overrideredirect . 1\n    }\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\"\n    .t yview 1.0\n    update\n    .t yview 16.0\n    update\n    set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]\n    wm overrideredirect . 0\n    update\n    set x\n} {8.0 {16.0 17.0 15.0 14.0 13.0 12.0 11.0 10.0 9.0 8.0} {8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0}}\ntest textDisp-4.8 {UpdateDisplayInfo, filling in extra vertical space} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\"\n    .t yview 16.0\n    update\n    .t delete 5.0 14.0\n    update\n    set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]\n} {1.0 {5.0 4.0 3.0 2.0 1.0} {1.0 2.0 3.0 4.0 5.0 eof}}\ntest textDisp-4.9 {UpdateDisplayInfo, filling in extra vertical space} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\"\n    .t yview 16.0\n    update\n    .t delete 15.0 end\n    list [.t bbox 7.0] [.t bbox 12.0]\n} [list [list [xchar 0] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 8] $fixedWidth $fixedHeight]]\ntest textDisp-4.10 {UpdateDisplayInfo, filling in extra vertical space} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\nLine 6 is such a long line that it wraps around.\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\"\n    .t yview end\n    update\n    .t delete 13.0 end\n    update\n    list [.t index @0,0] $tk_textRelayout $tk_textRedraw\n} {5.0 {12.0 7.0 6.40 6.20 6.0 5.0} {5.0 6.0 6.20 6.40 7.0 12.0}}\ntest textDisp-4.11 {UpdateDisplayInfo, filling in extra vertical space} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\nLine 6 is such a long line that it wraps around, not once but really quite a few times.\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\\n17\"\n    .t yview end\n    update\n    .t delete 14.0 end\n    update\n    list [.t index @0,0] $tk_textRelayout $tk_textRedraw\n} {6.40 {13.0 7.0 6.80 6.60 6.40} {6.40 6.60 6.80 7.0 13.0}}\ntest textDisp-4.12 {UpdateDisplayInfo, filling in extra vertical space} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n7\\n8\\n9\\n10\\n11\\n12\\n13\\n14\\n15\\n16\"\n    button .b -text \"Test\" -bd 2 -highlightthickness 2\n    .t window create 3.end -window .b\n    .t yview moveto 1\n    update\n    .t yview moveto 0\n    update\n    .t yview moveto 1\n    update\n    winfo ismapped .b\n} 0\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap word\n.t delete 1.0 end\n.t insert end \"Line 1\\nLine 2\\nLine 3\\nLine 4\\nLine 5\\nLine 6\\nLine 7\\n\"\n.t insert end \"Line 8\\nLine 9\\nLine 10\\nLine 11\\nLine 12\\nLine 13\\n\"\n.t insert end \"Line 14\\nLine 15\\nLine 16\"\n.t tag delete x\n.t tag configure x -relief raised -borderwidth 2 -background white\n\ntest textDisp-4.13 {UpdateDisplayInfo, special handling for top/bottom lines} {\n    .t tag add x 1.0 end\n    .t yview 1.0\n    update\n    .t yview scroll 3 units\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{11.0 12.0 13.0} {4.0 10.0 11.0 12.0 13.0}}\ntest textDisp-4.14 {UpdateDisplayInfo, special handling for top/bottom lines} {\n    .t tag remove x 1.0 end\n    .t yview 1.0\n    update\n    .t yview scroll 3 units\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{11.0 12.0 13.0} {11.0 12.0 13.0}}\ntest textDisp-4.15 {UpdateDisplayInfo, special handling for top/bottom lines} {\n    .t tag add x 1.0 end\n    .t yview 4.0\n    update\n    .t yview scroll -2 units\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 3.0} {2.0 3.0 4.0 11.0}}\ntest textDisp-4.16 {UpdateDisplayInfo, special handling for top/bottom lines} {\n    .t tag remove x 1.0 end\n    .t yview 4.0\n    update\n    .t yview scroll -2 units\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 3.0} {2.0 3.0}}\ntest textDisp-4.17 {UpdateDisplayInfo, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    update\n    .t xview scroll 3 units\n    update\n    list $tk_textRelayout $tk_textRedraw [.t bbox 2.0] [.t bbox 2.5] \\\n\t    [.t bbox 2.23]\n} [list {} {1.0 2.0 3.0 4.0} \\\n\t{} \\\n\t[list [expr {[xchar 5]-[xw 3]}] [yline 2] $fixedWidth $fixedHeight] \\\n\t{}]\ntest textDisp-4.18 {UpdateDisplayInfo, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    update\n    .t xview scroll 100 units\n    update\n    list $tk_textRelayout $tk_textRedraw [.t bbox 2.25]\n} [list {} {1.0 2.0 3.0 4.0} \\\n\t[list [xcharr 19] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-4.19 {UpdateDisplayInfo, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    update\n    .t xview moveto 0\n    .t xview scroll -10 units\n    update\n    list $tk_textRelayout $tk_textRedraw [.t bbox 2.5]\n} [list {} {1.0 2.0 3.0 4.0} \\\n\t[list [xchar 5] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-4.20 {UpdateDisplayInfo, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    .t xview moveto 0.0\n    .t xview scroll 100 units\n    update\n    .t delete 2.30 2.44\n    update\n    list $tk_textRelayout $tk_textRedraw [.t bbox 2.25]\n} [list 2.0 {1.0 2.0 3.0 4.0} \\\n\t[list [xcharr 5] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-4.21 {UpdateDisplayInfo, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    .t xview moveto .9\n    update\n    .t xview moveto .6\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {}}\ntest textDisp-4.22 {UpdateDisplayInfo, no horizontal scrolling except for -wrap none} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    .t xview scroll 25 units\n    update\n    .t configure -wrap word\n    list [.t bbox 2.0] [.t bbox 2.16]\n} [list [list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 1] [yline 3] $fixedWidth $fixedHeight]]\ntest textDisp-4.23 {UpdateDisplayInfo, no horizontal scrolling except for -wrap none} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"Short line 1\\nLine 2 is long enough to scroll horizontally\"\n    .t insert end \"\\nLine 3\\nLine 4\"\n    .t xview scroll 25 units\n    update\n    .t configure -wrap char\n    list [.t bbox 2.0] [.t bbox 2.16]\n} [list [list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 16] [yline 2] $fixedWidth $fixedHeight]]\n\ntest textDisp-5.1 {DisplayDLine, handling of spacing} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijkl\\nmnopqrstuvwzyz\"\n    .t tag configure spacing -spacing1 8 -spacing3 2\n    .t tag add spacing 1.0 end\n    frame .t.f1 -width 10 -height 4 -bg black\n    frame .t.f2 -width 10 -height 4 -bg black\n    frame .t.f3 -width 10 -height 4 -bg black\n    frame .t.f4 -width 10 -height 4 -bg black\n    .t window create 1.3 -window .t.f1 -align top\n    .t window create 1.7 -window .t.f2 -align center\n    .t window create 2.1 -window .t.f3 -align bottom\n    .t window create 2.10 -window .t.f4 -align baseline\n    update\n    list [winfo geometry .t.f1] [winfo geometry .t.f2] \\\n\t    [winfo geometry .t.f3] [winfo geometry .t.f4]\n} -cleanup {\n    .t tag delete spacing\n} -result [list 10x4+[xchar 3]+[expr {[yline 1]+8}] \\\n\t10x4+[expr {[xchar 6]+10}]+[expr {[yline 1]+8+($fixedHeight-4)/2}] \\\n\t10x4+[xchar 1]+[expr {[yline 2]+8+2+8+($fixedHeight-4)}] \\\n\t10x4+[expr {[xchar 9]+10}]+[expr {[yline 2]+8+2+8+($fixedAscent-4)}]]\n\n# Although the following test produces a useful result, its main\n# effect is to produce a core dump if Tk doesn't handle display\n# relayout that occurs during redisplay.\ntest textDisp-5.2 {DisplayDLine, line resizes during display} {\n    .t delete 1.0 end\n    frame .t.f -width 20 -height 20 -bd 2 -relief raised\n    bind .t.f <Configure> {.t.f configure -width 30 -height 30}\n    .t window create insert -window .t.f\n    update\n    list [winfo width .t.f] [winfo height .t.f]\n} [list 30 30]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char\n\ntest textDisp-6.1 {scrolling in DisplayText, scroll up} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 2.0 3.0\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 10.0} {2.0 10.0}}\ntest textDisp-6.2 {scrolling in DisplayText, scroll down} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t insert 2.0 \"New Line 2\\n\"\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 3.0} {2.0 3.0}}\ntest textDisp-6.3 {scrolling in DisplayText, multiple scrolls} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t insert 2.end \"is so long that it wraps\"\n    .t insert 4.end \"is so long that it wraps\"\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 2.20 4.0 4.20} {2.0 2.20 4.0 4.20}}\ntest textDisp-6.4 {scrolling in DisplayText, scrolls interfere} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t insert 2.end \"is so long that it wraps around, not once but three times\"\n    .t insert 4.end \"is so long that it wraps\"\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 2.20 2.40 2.60 4.0 4.20} {2.0 2.20 2.40 2.60 4.0 4.20 6.0}}\ntest textDisp-6.5 {scrolling in DisplayText, scroll source obscured} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    .t configure -wrap char\n    frame .f2 -bg red\n    place .f2 -in .t -relx 0.5 -rely 0.5 -relwidth 0.5 -relheight 0.5\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, a couple of times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.6 1.end\n    update\n    destroy .f2\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 9.0 10.0} {1.0 4.0 5.0 9.0 10.0}}\ntest textDisp-6.6 {scrolling in DisplayText, Expose events after scroll} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    # this test depends on all of the expose events being handled at once\n    .t configure -wrap char\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.2 -rely 0.5 -relwidth 0.5 -relheight 0.5\n    .t configure -bd 2 -relief raised\n    .t delete 1.0 end\n    # Line 1 must wrap exactly twice to get the expected result\n    .t insert 1.0 \"Line 1 is so long that it occupies 3 display lines\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.6 1.end\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 9.0 10.0} {1.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0}}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -bd 0\n\ntest textDisp-6.7 {DisplayText, vertical scrollbar updates} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    update\n    .t count -update -ypixels 1.0 end\n    update\n    set scrollInfo\n} {0.0 1.0}\ntest textDisp-6.8 {DisplayText, vertical scrollbar updates} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    update\n    set scrollInfo \"unchanged\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t count -update -ypixels 1.0 end ; update\n    set scrollInfo\n} [list 0.0 [expr {10.0/13}]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -yscrollcommand {} -xscrollcommand setScrollInfo\n\ntest textDisp-6.9 {DisplayText, horizontal scrollbar updates} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    update\n    set scrollInfo unchanged\n    .t insert end xxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx\n    update\n    set scrollInfo\n} [list 0.0 [expr {4.0/11}]]\ntest textDisp-6.10 {DisplayText, redisplay embedded windows after scroll} {aqua} {\n    # For this test to pass line 8 must be out of the text widget.\n    # With macOS 14 this requires making the buttons a little larger.\n    # So we set the pady option.  This may depend on the OS version.\n    .t configure -wrap char\n    update\n    .t delete 1.0 end\n    update\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\n\"\n    .t window create end -create {\n\tbutton %W.button_one -text \"Button 1\" -pady 5}\n    .t insert end \"\\nLine 6\\n\"\n    .t window create end -create {\n\tbutton %W.button_two -text \"Button 2\" -pady 5}\n    .t insert end \"\\nLine 8\\n\"\n    .t window create end -create {\n\tbutton %W.button_three -text \"Button 3\" -pady 5}\n    update\n    set tk_textEmbWinDisplay {}\n    .t delete 2.0 3.0\n    update\n    list $tk_textEmbWinDisplay\n} {{4.0 6.0}}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -bd 2 -relief raised -wrap char\n.t delete 1.0 end\n.t insert 1.0 \"Line 1 is so long that it wraps around, a couple of times\"\nforeach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n    .t insert end \"\\nLine $i\"\n}\n\ntest textDisp-7.1 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.2 -relwidth 0.6 -rely 0.22 -relheight 0.55\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {1.40 2.0 3.0 4.0 5.0 6.0}}\ntest textDisp-7.2 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0 -relwidth 0.5 -rely 0 -relheight 0.5\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {1.0 1.20 1.40 2.0 3.0}}\ntest textDisp-7.3 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.5 -relwidth 0.5 -rely 0.5 -relheight 0.5\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {4.0 5.0 6.0 7.0 8.0}}\ntest textDisp-7.4 {TkTextRedrawRegion} {aquaKnownBug} {\n # constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n   frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.4 -relwidth 0.2 -rely 0 -relheight 0.2 \\\n\t    -bordermode ignore\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {borders 1.0 1.20}}\ntest textDisp-7.5 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.4 -relwidth 0.2 -rely 1.0 -relheight 0.2 \\\n\t    -anchor s -bordermode ignore\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {borders 7.0 8.0}}\ntest textDisp-7.6 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0 -relwidth 0.2 -rely 0.55 -relheight 0.2 \\\n\t    -anchor w -bordermode ignore\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {borders 3.0 4.0 5.0}}\ntest textDisp-7.7 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 1.0 -relwidth 0.2 -rely 0.55 -relheight 0.2 \\\n\t    -anchor e -bordermode ignore\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {borders 3.0 4.0 5.0}}\ntest textDisp-7.8 {TkTextRedrawRegion} {aquaKnownBug} {\n# constrained by aquaKnownBug until ticket [aad0231f07] is fixed\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\\nLine 4\\nLine 5\\nLine 6\\n\"\n    frame .f2 -bg #ff0000\n    place .f2 -in .t -relx 0.0 -relwidth 0.4 -rely 0.35 -relheight 0.4 \\\n\t    -anchor nw -bordermode ignore\n    update\n    destroy .f2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{} {borders 4.0 5.0 6.0 7.0 eof}}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -bd 0\n\ntest textDisp-8.1 {TkTextChanged: redisplay whole lines} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is so long that it wraps around, two times\"\n    foreach i {3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 2.36 2.38\n    update\n    list $tk_textRelayout $tk_textRedraw [.t bbox 2.32]\n} [list {2.0 2.18 2.38} {2.0 2.18 2.38} [list [xchar 14] [yline 3] $fixedWidth $fixedHeight]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char\n\ntest textDisp-8.2 {TkTextChanged, redisplay whole lines} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t insert 1.2 xx\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 1.20 1.40} {1.0 1.20 1.40}}\ntest textDisp-8.3 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t insert 2.0 xx\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {2.0 2.0}\ntest textDisp-8.4 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.5\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 1.20 1.40} {1.0 1.20 1.40}}\ntest textDisp-8.5 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.40 1.44\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 1.20 1.40} {1.0 1.20 1.40}}\ntest textDisp-8.6 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.41 1.44\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 1.20 1.40} {1.0 1.20 1.40}}\ntest textDisp-8.7 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 1.2 1.end\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 9.0 10.0} {1.0 9.0 10.0}}\ntest textDisp-8.8 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 2.2\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {2.0 2.0}\ntest textDisp-8.9 {TkTextChanged} {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1 is so long that it wraps around, two times\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    .t delete 2.0 3.0\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 8.0} {2.0 8.0}}\ntest textDisp-8.10 {TkTextChanged} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 2.19\n    update\n    .t delete 2.19\n    update\n    set tk_textRedraw\n} {2.0 2.20 eof}\ntest textDisp-8.11 {TkTextChanged, scrollbar notification when changes are off-screen} {\n    .t delete 1.0 end\n    .t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12\\n\"\n    .t configure -yscrollcommand setScrollInfo\n    update\n    set scrollInfo \"\"\n    .t insert end \"a\\nb\\nc\\n\"\n    # We need to wait for our asychronous callbacks to update the\n    # scrollbar\n    update\n    .t count -update -ypixels 1.0 end\n    update\n    .t configure -yscrollcommand \"\"\n    set scrollInfo\n} {0.0 0.625}\ntest textDisp-8.12 {TkTextChanged, moving the insert cursor redraws only past and new lines} {\n    .t delete 1.0 end\n    .t configure -wrap none\n    for {set i 1} {$i < 25} {incr i} {\n\t.t insert end \"Line $i Line $i\\n\"\n    }\n    .t tag add hidden 5.0 8.0\n    .t tag configure hidden -elide true\n    .t mark set insert 9.0\n    update\n    .t mark set insert 8.0        ; # up one line\n    update\n    set res [list $tk_textRedraw]\n    .t mark set insert 12.2       ; # in the visible text\n    update\n    lappend res $tk_textRedraw\n    .t mark set insert 6.5        ; # in the hidden text\n    update\n    lappend res $tk_textRedraw\n    .t mark set insert 3.5        ; # in the visible text again\n    update\n    lappend res $tk_textRedraw\n    .t mark set insert 3.8        ; # within the same line\n    update\n    lappend res $tk_textRedraw\n} {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {3.0 4.0}}\ntest textDisp-8.13 {TkTextChanged, used to crash, see [06c1433906]} {\n    .t delete 1.0 end\n    .t insert 1.0 \\nLine2\\nLine3\\n\n    update\n    .t insert 3.0 \"\"\n    .t delete 1.0 2.0\n    update idletasks\n} {}\n\ntest textDisp-9.1 {TkTextRedrawTag} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap around\\nLine 3\\nLine 4\"\n    update\n    .t tag add big 2.2 2.4\n    update\n   list $tk_textRelayout $tk_textRedraw\n# glob matching is to have some tolerance on actually used font size\n# while still testing what we want to test\n} -match glob -result {{2.0 2.1[78]} {2.0 2.1[78]}}\ntest textDisp-9.2 {TkTextRedrawTag} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap around\\nLine 3\\nLine 4\"\n    update\n    .t tag add big 1.2 2.4\n    update\n    list $tk_textRelayout $tk_textRedraw\n# glob matching is to have some tolerance on actually used font size\n# while still testing what we want to test\n} -match glob -result {{1.0 2.0 2.1[678]} {1.0 2.0 2.1[678]}}\ntest textDisp-9.3 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap around\\nLine 3\\nLine 4\"\n    update\n    .t tag add big 2.2 2.4\n    update\n    .t tag remove big 1.0 end\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 2.20} {2.0 2.20 eof}}\ntest textDisp-9.4 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap around\\nLine 3\\nLine 4\"\n    update\n    .t tag add big 2.2 2.20\n    update\n    .t tag remove big 1.0 end\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 2.20} {2.0 2.20 eof}}\ntest textDisp-9.5 {TkTextRedrawTag} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -setup {\n    .t configure -wrap char -height [expr {[.t cget -height]+10}]\n} -body {\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap around\\nLine 3\\nLine 4\"\n    update\n    .t tag add big 2.2 2.end\n    update\n    .t tag remove big 1.0 end\n    update\n    list $tk_textRelayout $tk_textRedraw\n} -cleanup {\n    .t configure -height [expr {[.t cget -height]-10}]\n    update\n} -result {{2.0 2.20} {2.0 2.20 eof}}\ntest textDisp-9.6 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\"\n    update\n    .t tag add big 2.2 3.5\n    update\n    .t tag remove big 1.0 end\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 2.20 3.0 3.20} {2.0 2.20 3.0 3.20 eof}}\ntest textDisp-9.7 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 2.19\n    update\n    .t tag remove big 2.19\n    update\n    set tk_textRedraw\n} {2.0 2.20 eof}\ntest textDisp-9.8 {TkTextRedrawTag} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 1.0 2.0\n    update\n    .t tag add big 2.0 2.5\n    update\n    set tk_textRedraw\n# glob matching is to have some tolerance on actually used font size\n# while still testing what we want to test\n} -match glob -result {2.0 2.1[678]}\ntest textDisp-9.9 {TkTextRedrawTag} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 1.0 2.0\n    update\n    .t tag add big 1.5 2.5\n    update\n    set tk_textRedraw\n# glob matching is to have some tolerance on actually used font size\n# while still testing what we want to test\n} -match glob -result {2.0 2.1[678]}\ntest textDisp-9.10 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 1.0 2.0\n    update\n    set tk_textRedraw none\n    .t tag add big 1.3 1.5\n    update\n    set tk_textRedraw\n} none\ntest textDisp-9.11 {TkTextRedrawTag} haveBigFontTwiceLargerThanTextFont {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    .t tag add big 1.0 2.0\n    update\n    .t tag add big 1.0 2.0\n    update\n    set tk_textRedraw\n} {}\ntest textDisp-9.12 {TkTextRedrawTag} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    for {set i 1} {$i < 5} {incr i} {\n      .t insert end \"Line $i+++Line $i\\n\"\n    }\n    .t tag configure hidden -elide true\n    .t tag add hidden 2.6 3.6\n    update\n    .t tag add hidden 3.11 4.6\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {2.0 {2.0 eof}}\ntest textDisp-9.13 {TkTextRedrawTag} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i - This is Line [format %c [expr {64+$i}]]\\n\"\n    }\n    .t tag add hidden 2.8 2.17\n    .t tag add hidden 6.8 7.17\n    .t tag configure hidden -background red\n    .t tag configure hidden -elide true\n    update\n    .t tag configure hidden -elide false\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{2.0 6.0 7.0} {2.0 6.0 7.0}}\ntest textDisp-9.14 {TkTextRedrawTag} {\n    pack [text .tnocrash]\n    for {set i 1} {$i < 6} {incr i} {\n\t.tnocrash insert end \\nfoo$i\n    }\n    .tnocrash tag configure mytag1 -relief raised\n    .tnocrash tag configure mytag2 -relief solid\n    update\n    proc doit {} {\n\t.tnocrash tag add mytag1 4.0 5.0\n\t.tnocrash tag add mytag2 4.0 5.0\n\tafter idle {\n\t    .tnocrash tag remove mytag1 1.0 end\n\t    .tnocrash tag remove mytag2 1.0 end\n\t}\n\t.tnocrash delete 1.0 2.0\n    }\n    doit  ; # must not crash\n    after 500 {\n\tdestroy .tnocrash\n\tset done 1\n    }\n    vwait done\n} {}\n\ntest textDisp-10.1 {TkTextRelayoutWindow} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2 is long enough to wrap\\nLine 3 is also long enough to wrap\\nLine 4\"\n    update\n    .t configure -bg black\n    update\n    list $tk_textRelayout $tk_textRedraw\n} {{1.0 2.0 2.20 3.0 3.20 4.0} {borders 1.0 2.0 2.20 3.0 3.20 4.0 eof}}\n\n#\n# COMMON TEST SETUP\n#\n.t configure -bg [lindex [.t configure -bg] 3]\n\ntest textDisp-10.2 {TkTextRelayoutWindow} -body {\n    toplevel .top -width 300 -height 200\n    wm geometry .top +0+0\n    text .top.t -font $fixedFont -width 20 -height 10 -relief raised -bd 2\n    place .top.t -x 0 -y 0 -width 20 -height 20\n    .top.t insert end \"First line\"\n    .top.t see insert\n    tkwait visibility .top.t\n    place .top.t -width 150 -height 100\n    update\n    .top.t index @0,0\n} -result {1.0} -cleanup {\n    destroy .top\n}\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\n.t insert end \"Line 1\"\nfor {set i 2} {$i <= 200} {incr i} {\n    .t insert end \"\\nLine $i\"\n}\nupdate\n\ntest textDisp-11.1 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    .t index @0,0\n} {30.0}\ntest textDisp-11.2 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    .t yview 32.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {32.0 {40.0 41.0}}\ntest textDisp-11.3 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    .t yview 28.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {28.0 {28.0 29.0}}\ntest textDisp-11.4 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    .t yview 31.4\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {31.0 40.0}\ntest textDisp-11.5 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview -pickplace 31.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {30.0 {}}\ntest textDisp-11.6 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview -pickplace 28.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {28.0 {28.0 29.0}}\ntest textDisp-11.7 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview -pickplace 26.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {21.0 {21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0}}\ntest textDisp-11.8 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview -pickplace 41.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {32.0 {40.0 41.0}}\ntest textDisp-11.9 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview -pickplace 43.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {38.0 {40.0 41.0 42.0 43.0 44.0 45.0 46.0 47.0 48.0}}\ntest textDisp-11.10 {TkTextSetYView} {\n    .t yview 30.0\n    update\n    set tk_textRedraw {}\n    .t yview 10000.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {191.0 {191.0 192.0 193.0 194.0 195.0 196.0 197.0 198.0 199.0 200.0}}\ntest textDisp-11.11 {TkTextSetYView} {\n    .t yview 195.0\n    update\n    set tk_textRedraw {}\n    .t yview 197.0\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {191.0 {191.0 192.0 193.0 194.0 195.0 196.0}}\ntest textDisp-11.12 {TkTextSetYView, wrapped line is off-screen} {\n    .t insert 10.0 \"Long line with enough text to wrap\\n\"\n    .t yview 1.0\n    update\n    set tk_textRedraw {}\n    .t see 10.30\n    update\n    list [.t index @0,0] $tk_textRedraw\n} {2.0 10.20}\n\n#\n# COMMON TEST CLEANUP\n#\n.t delete 10.0 11.0\n\ntest textDisp-11.13 {TkTestSetYView, partially visible last line} {\n    catch {destroy .top}\n    toplevel .top\n    wm geometry .top +0+0\n    text .top.t -width 20 -height 5\n    pack .top.t\n    .top.t insert end \"Line 1\"\n    for {set i 2} {$i <= 100} {incr i} {\n\t.top.t insert end \"\\nLine $i\"\n    }\n    update\n    scan [wm geometry .top] \"%dx%d\" w2 h2\n    wm geometry .top ${w2}x[expr {$h2-2}]\n    update\n    .top.t yview 1.0\n    update\n    set tk_textRedraw {}\n    .top.t see 5.0\n    update\n    # Note, with smooth scrolling, the results of this test\n    # have changed, and the old '2.0 {5.0 6.0}' is quite wrong.\n    list [.top.t index @0,0] $tk_textRedraw\n} {1.0 5.0}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .top}\ntoplevel .top\nwm geometry .top +0+0\ntext .top.t -width 30 -height 3\npack .top.t\n.top.t insert end \"Line 1\"\nfor {set i 2} {$i <= 20} {incr i} {\n    .top.t insert end \"\\nLine $i\"\n}\nupdate\n\ntest textDisp-11.14 {TkTextSetYView, only a few lines visible} {\n    .top.t yview 5.0\n    update\n    .top.t see 10.0\n    .top.t index @0,0\n} {8.0}\ntest textDisp-11.15 {TkTextSetYView, only a few lines visible} {\n    .top.t yview 5.0\n    update\n    .top.t see 11.0\n    .top.t index @0,0\n    # The index 9.0 should be just visible by a couple of pixels\n} {9.0}\ntest textDisp-11.16 {TkTextSetYView, only a few lines visible} {\n    .top.t yview 8.0\n    update\n    .top.t see 5.0\n    .top.t index @0,0\n} {5.0}\ntest textDisp-11.17 {TkTextSetYView, only a few lines visible} {\n    .top.t yview 8.0\n    update\n    .top.t see 4.0\n    .top.t index @0,0\n    # The index 2.0 should be just visible by a couple of pixels\n} {2.0}\ntest textDisp-11.18 {TkTextSetYView, see in elided lines} {\n    .top.t delete 1.0 end\n    for {set i 1} {$i < 20} {incr i} {\n\t.top.t insert end [string repeat \"Line $i\" 10]\n\t.top.t insert end \"\\n\"\n    }\n    .top.t yview 4.0\n    .top.t tag add hidden 4.10 \"4.10 lineend\"\n    .top.t tag add hidden 5.15 10.3\n    .top.t tag configure hidden -elide true\n    update\n    .top.t see \"8.0 lineend\"\n    # The index \"8.0 lineend\" is on screen despite elided -> no scroll\n    .top.t index @0,0\n} {4.0}\ntest textDisp-11.19 {TkTextSetYView, see in elided lines} {\n    .top.t delete 1.0 end\n    for {set i 1} {$i < 50} {incr i} {\n\t.top.t insert end \"Line $i\\n\"\n    }\n    # button just for having a line with a larger height\n    button .top.t.b -text \"Test\" -bd 2 -highlightthickness 2\n    .top.t window create 21.0 -window .top.t.b\n    .top.t tag add hidden 15.36 21.0\n    .top.t tag configure hidden -elide true\n    .top.t configure -height 15\n    wm geometry .top 300x200+0+0\n    # Indices 21.0, 17.0 and 15.0 are all on the same display line\n    # therefore index @0,0 shall be the same for all of them\n    .top.t see end\n    update\n    .top.t see 21.0\n    update\n    set ind1 [.top.t index @0,0]\n    .top.t see end\n    update\n    .top.t see 17.0\n    update\n    set ind2 [.top.t index @0,0]\n    .top.t see end\n    update\n    .top.t see 15.0\n    update\n    set ind3 [.top.t index @0,0]\n    list [expr {$ind1 == $ind2}] [expr {$ind1 == $ind3}]\n} {1 1}\ntest textDisp-11.20 {TkTextSetYView, see in elided lines} {\n    .top.t delete 1.0 end\n    .top.t configure -wrap none\n    for {set i 1} {$i < 5} {incr i} {\n\t.top.t insert end [string repeat \"Line $i \" 50]\n\t.top.t insert end \"\\n\"\n    }\n    .top.t delete 3.11 3.14\n    .top.t tag add hidden 3.0 4.0\n    # this shall not crash (null chunkPtr in TkTextSeeCmd is tested)\n    .top.t see 3.0\n} {}\ntest textDisp-11.21 {TkTextSetYView, window height smaller than the line height} {\n    .top.t delete 1.0 end\n    for {set i 1} {$i <= 10} {incr i} {\n\t.top.t insert end \"Line $i\\n\"\n    }\n    set lineheight [font metrics [.top.t cget -font] -linespace]\n    wm geometry .top 200x[expr {$lineheight / 2}]\n    update\n    .top.t see 1.0\n    .top.t index @0,[expr {$lineheight - 2}]\n} {1.0}\ntest textDisp-11.22 {TkTextSetYView, peer has -startline} {\n    .top.t delete 1.0 end\n    for {set i 1} {$i <= 50} {incr i} {\n\t.top.t insert end \"Line $i\\n\"\n    }\n    pack [.top.t peer create .top.p] -side left\n    pack [scrollbar .top.sb -command {.top.p yview}] -side left -fill y\n    .top.p configure -startline 5 -endline 35 -yscrollcommand {.top.sb set}\n    update\n    .top.p yview moveto 0\n    update\n    set res [.top.p get @0,0 \"@0,0 lineend\"]\n    destroy .top.p\n    set res\n} {Line 5}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap word\n.t delete 50.0 51.0\n.t insert 50.0 \"This is a long line, one that will wrap around twice.\\n\"\n\ntest textDisp-12.1 {MeasureUp} {\n    .t yview 100.0\n    update\n    .t yview -pickplace 52.0\n    update\n    .t index @0,0\n} {49.0}\ntest textDisp-12.2 {MeasureUp} {\n    .t yview 100.0\n    update\n    .t yview -pickplace 53.0\n    update\n    .t index @0,0\n} {50.0}\ntest textDisp-12.3 {MeasureUp} {\n    .t yview 100.0\n    update\n    .t yview -pickplace 50.10\n    update\n    .t index @0,0\n} {45.0}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap none\n\ntest textDisp-12.4 {MeasureUp} {\n    .t yview 100.0\n    update\n    .t yview -pickplace 53.0\n    update\n    .t index @0,0\n} {48.0}\ntest textDisp-12.5 {MeasureUp} {\n    .t yview 100.0\n    update\n    .t yview -pickplace 50.10\n    update\n    .t index @0,0\n} {45.0}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap none\n.t delete 1.0 end\nfor {set i 1} {$i < 99} {incr i} {\n    .t insert end \"Line $i\\n\"\n}\n.t insert end \"Line 100\"\n.t insert 30.end { is quite long, so that it flows way off the end of the window and we can use it to test out the horizontal positioning features of the \"see\" command.}\n\ntest textDisp-13.1 {TkTextSeeCmd procedure} {\n    list [catch {.t see} msg] $msg\n} {1 {wrong # args: should be \".t see index\"}}\ntest textDisp-13.2 {TkTextSeeCmd procedure} {\n    list [catch {.t see a b} msg] $msg\n} {1 {wrong # args: should be \".t see index\"}}\ntest textDisp-13.3 {TkTextSeeCmd procedure} {\n    list [catch {.t see badIndex} msg] $msg\n} {1 {bad text index \"badIndex\"}}\ntest textDisp-13.4 {TkTextSeeCmd procedure} {\n    .t xview moveto 0\n    .t yview moveto 0\n    update\n    .t see 4.2\n    .t index @0,0\n} {1.0}\ntest textDisp-13.5 {TkTextSeeCmd procedure} {\n    .t configure -wrap char\n    .t xview moveto 0\n    .t yview moveto 0\n    update\n    .t see 12.1\n    .t index @0,0\n} {3.0}\ntest textDisp-13.6 {TkTextSeeCmd procedure} {\n    .t configure -wrap char\n    .t xview moveto 0\n    .t yview moveto 0\n    update\n    .t see 30.50\n    set x [.t index @0,0]\n    .t configure -wrap none\n    set x\n} {27.0}\ntest textDisp-13.7 {TkTextSeeCmd procedure} {\n    .t xview moveto 0\n    .t yview moveto 0\n    .t tag add sel 30.20\n    .t tag add sel 30.40\n    update\n    .t see 30.50\n    .t yview 25.0\n    .t see 30.50\n    set x [list [.t bbox 30.50]]\n    .t see 30.39\n    lappend x [.t bbox 30.39]\n    .t see 30.38\n    lappend x [.t bbox 30.38]\n    .t see 30.20\n    lappend x [.t bbox 30.20]\n} [list [list [xchar 10] [yline 6] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 6] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 6] $fixedWidth $fixedHeight] \\\n\t[list [xchar 10] [yline 6] $fixedWidth $fixedHeight]]\ntest textDisp-13.8 {TkTextSeeCmd procedure} {\n    .t xview moveto 0\n    .t yview moveto 0\n    .t tag add sel 30.20\n    .t tag add sel 30.50\n    update\n    .t see 30.50\n    set x [list [.t bbox 30.50]]\n    .t see 30.60\n    lappend x [.t bbox 30.60]\n    .t see 30.65\n    lappend x [.t bbox 30.65]\n    .t see 30.90\n    lappend x [.t bbox 30.90]\n    # contrary to textDisp-13.7 above there is no yview command in this test\n    # therefore take into account that the top line is partially hidden\n    set y [expr {[yline 6] + [lindex [.t bbox @0,0] 1] - [bo]}]\n    set expected [list [list [xchar 10] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 19] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 19] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 10] $y $fixedWidth $fixedHeight]]\n    lequal $x $expected\n} {1}\ntest textDisp-13.9 {TkTextSeeCmd procedure} {\n    wm geom . [expr {$width-2}]x$height\n    .t xview moveto 0\n    .t yview moveto 0\n    .t tag add sel 30.20\n    .t tag add sel 30.50\n    update\n    .t see 30.50\n    set x [list [.t bbox 30.50]]\n    .t see 30.60\n    lappend x [.t bbox 30.60]\n    .t see 30.65\n    lappend x [.t bbox 30.65]\n    .t see 30.90\n    lappend x [.t bbox 30.90]\n    # contrary to textDisp-13.7 above there is no yview command in this test\n    # therefore take into account that the top line is partially hidden\n    set y [expr {[yline 6] + [lindex [.t bbox @0,0] 1] - [bo]}]\n    set expected [list [list [expr {[bo]+round([winfo width .t]-2*[bo])/2}] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [xcharr 1] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [xcharr 1] $y $fixedWidth $fixedHeight] \\\n\t\t       [list [expr {[bo]+round([winfo width .t]-2*[bo])/2}] $y $fixedWidth $fixedHeight]]\n    lequal $x $expected\n} {1}\ntest textDisp-13.10 {TkTextSeeCmd procedure} {\n    # SF Bug 641778\n    set w .tsee\n    destroy $w\n    text $w -font {Helvetica 8 normal} -bd 16\n    $w insert end Hello\n    $w see end\n    set res [$w bbox end]\n    destroy $w\n    set res\n} {}\ntest textDisp-13.11 {TkTextSeeCmd procedure} {} {\n    # insertion of a character at end of a line containing multi-byte\n    # characters and calling see at the line end shall actually show\n    # this character\n    toplevel .top2\n    pack [text .top2.t2 -wrap none]\n    for {set i 1} {$i < 5} {incr i} {\n\t.top2.t2 insert end [string repeat \"Line $i: éèàçù\" 5]\\n\n    }\n    wm geometry .top2 300x200+0+0\n    update\n    .top2.t2 see \"1.0 lineend\"\n    update\n    set ref [.top2.t2 index @0,0]\n    .top2.t2 insert \"1.0 lineend\" ç\n    .top2.t2 see \"1.0 lineend\"\n    update\n    set new [.top2.t2 index @0,0]\n    set res [.top2.t2 compare $ref == $new]\n    destroy .top2\n    set res\n} 0\n\n#\n# COMMON TEST SETUP\n#\n\nwm geom . {}\n.t configure -wrap none\n\ntest textDisp-14.1 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    update\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\\n\"\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto .5\n    .t xview\n} [list 0.5 [expr {6./7.}]]\n\ntest textDisp-14.2 {TkTextXviewCmd procedure} -setup {\n    .t configure -wrap char\n} -body {\n    .t delete 1.0 end\n    update\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx\\n\"\n    .t insert end \"xxxx\"\n    .t xview\n} -cleanup {\n    .t configure -wrap none\n} -result {0.0 1.0}\n\ntest textDisp-14.3 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    update\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx\\n\"\n    .t insert end \"xxxx\"\n    .t xview\n} {0.0 1.0}\ntest textDisp-14.4 {TkTextXviewCmd procedure} {\n    list [catch {.t xview moveto} msg] $msg\n} {1 {wrong # args: should be \".t xview moveto fraction\"}}\ntest textDisp-14.5 {TkTextXviewCmd procedure} {\n    list [catch {.t xview moveto a b} msg] $msg\n} {1 {wrong # args: should be \".t xview moveto fraction\"}}\ntest textDisp-14.6 {TkTextXviewCmd procedure} {\n    list [catch {.t xview moveto a} msg] $msg\n} {1 {expected floating-point number but got \"a\"}}\ntest textDisp-14.7 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\\n\" ; # 56 chars on this line\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto .3\n    .t xview\n} [list [expr {round(0.3*(56*$fixedWidth))/(56.0*$fixedWidth)}] [expr {round(0.3*(56*$fixedWidth)+20*$fixedWidth)/(56.0*$fixedWidth)}]]\ntest textDisp-14.8 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\\n\" ; # 56 chars on this line\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto -.4\n    .t xview\n} [list 0.0 [expr {20.0/56}]]\ntest textDisp-14.9 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\\n\" ; # 56 chars on this line\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview m 1.4\n    .t xview\n} [list [expr {(56.0-20)/56}] 1.0]\ntest textDisp-14.10 {TkTextXviewCmd procedure} {\n    list [catch {.t xview scroll a} msg] $msg\n} {1 {wrong # args: should be \".t xview scroll number pages|pixels|units\"}}\ntest textDisp-14.11 {TkTextXviewCmd procedure} {\n    list [catch {.t xview scroll a b c} msg] $msg\n} {1 {wrong # args: should be \".t xview scroll number pages|pixels|units\"}}\ntest textDisp-14.12 {TkTextXviewCmd procedure} {\n    list [catch {.t xview scroll gorp units} msg] $msg\n} {1 {expected floating-point number but got \"gorp\"}}\ntest textDisp-14.13 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9\\n\"\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto 0\n    .t xview scroll 2 pa\n    set x [.t index @0,22]\n    .t xview scroll -1 pa\n    lappend x [.t index @0,22]\n    .t xview scroll -2 pages\n    lappend x [.t index @0,22]\n} {2.36 2.18 2.0}\ntest textDisp-14.14 {TkTextXviewCmd procedure} {\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9\\n\"\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto 0\n    .t xview scroll 21 u\n    set x [.t index @0,22]\n    .t xview scroll -1 u\n    lappend x [.t index @0,22]\n    .t xview scroll 100 units\n    lappend x [.t index @0,22]\n    .t xview scroll -15 units\n    lappend x [.t index @0,22]\n} {2.21 2.20 2.99 2.84}\ntest textDisp-14.15 {TkTextXviewCmd procedure} {\n    list [catch {.t xview scroll 14 globs} msg] $msg\n} {1 {bad argument \"globs\": must be pages, pixels, or units}}\ntest textDisp-14.16 {TkTextXviewCmd procedure} {\n    list [catch {.t xview flounder} msg] $msg\n} {1 {bad option \"flounder\": must be moveto or scroll}}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char\n.t delete 1.0 end\nfor {set i 1} {$i < 99} {incr i} {\n    .t insert end \"Line $i\\n\"\n}\n.t insert end \"Line 100\"\n.t delete 50.0 51.0\n.t insert 50.0 \"This is a long line, one that will wrap around twice.\\n\"\n\ntest textDisp-15.1 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 45.0\n    update\n    .t yview scroll -3 units\n    .t index @0,0\n} {42.0}\ntest textDisp-15.2 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 51.0\n    update\n    .t yview scroll -2 units\n    .t index @0,0\n} {50.20}\ntest textDisp-15.3 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 51.0\n    update\n    .t yview scroll -4 units\n    .t index @0,0\n} {49.0}\ntest textDisp-15.4 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 50.20\n    update\n    .t yview scroll -2 units\n    .t index @0,0\n} {49.0}\ntest textDisp-15.5 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 50.40\n    update\n    .t yview scroll -2 units\n    .t index @0,0\n} {50.0}\ntest textDisp-15.6 {ScrollByLines procedure, scrolling backwards} {\n    .t yview 3.2\n    update\n    .t yview scroll -5 units\n    .t index @0,0\n} {1.0}\ntest textDisp-15.7 {ScrollByLines procedure, scrolling forwards} {\n    .t yview 48.0\n    update\n    .t yview scroll 4 units\n    .t index @0,0\n} {50.40}\n\ntest textDisp-15.8 {Scrolling near end of window} {\n    set textheight 12\n    set textwidth 30\n\n    toplevel .tf\n    frame .tf.f -relief sunken -borderwidth 2\n    pack .tf.f -padx 10 -pady 10\n\n    text .tf.f.t -font {Courier 9} -height $textheight \\\n      -width $textwidth -yscrollcommand \".tf.f.sb set\"\n    scrollbar .tf.f.sb -command \".tf.f.t yview\"\n    pack .tf.f.t -side left -expand 1 -fill both\n    pack .tf.f.sb -side right -fill y\n\n    .tf.f.t tag configure Header -font {Helvetica 14 bold italic} \\\n      -wrap word -spacing1 12 -spacing3 4\n\n    .tf.f.t insert end \"Foo\" Header\n    for {set i 1} {$i < $textheight} {incr i} {\n\t.tf.f.t insert end \"\\nLine $i\"\n    }\n    update\n    set refind [.tf.f.t index @0,[winfo height .tf.f.t]]\n    # Should scroll and should not crash!\n    .tf.f.t yview scroll 1 unit\n    # Check that it has scrolled\n    set newind [.tf.f.t index @0,[winfo height .tf.f.t]]\n    set res [.tf.f.t compare $newind > $refind]\n    destroy .tf\n    set res\n} 1\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char\n.t delete 1.0 end\n.t insert insert \"Line 1\"\nfor {set i 2} {$i <= 200} {incr i} {\n    .t insert end \"\\nLine $i\"\n}\n.t tag add big 100.0 105.0\n.t insert 151.end { has a lot of extra text, so that it wraps around on the screen several times over.}\n.t insert 153.end { also has largely enough extra text to wrap.}\nupdate\nset totpix [.t count -update -ypixels 1.0 end]\n# check that the wrapping lines wrap exactly 6 times in total (4 times for line 151, and twice for line 153),\n# this is an assumption of the upcoming tests\nif {double(($totpix-5*$heightDiff)/$fixedHeight) != 206.0} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual [.t cget -font]]\\\",\\\nis too different from the requested \\\"[.t cget -font]\\\". Some of the upcoming tests will probably fail.\"\n}\n\ntest textDisp-16.1 {TkTextYviewCmd procedure} {\n    .t yview 21.0\n    set x [.t yview]\n    .t yview 1.0\n    list [expr {int([lindex $x 0]*100)}] [expr {int([lindex $x 1]*100)}]\n} {9 14}\ntest textDisp-16.2 {TkTextYviewCmd procedure} {\n    list [catch {.t yview 2 3} msg] $msg\n} {1 {bad option \"2\": must be moveto or scroll}}\ntest textDisp-16.3 {TkTextYviewCmd procedure} {\n    list [catch {.t yview -pickplace} msg] $msg\n} {1 {wrong # args: should be \".t yview -pickplace lineNum|index\"}}\ntest textDisp-16.4 {TkTextYviewCmd procedure} {\n    list [catch {.t yview -pickplace 2 3} msg] $msg\n} {1 {wrong # args: should be \".t yview -pickplace lineNum|index\"}}\ntest textDisp-16.5 {TkTextYviewCmd procedure} {\n    list [catch {.t yview -bogus 2} msg] $msg\n} {1 {bad option \"-bogus\": must be moveto or scroll}}\ntest textDisp-16.6 {TkTextYviewCmd procedure, integer position} {\n    .t yview 100.0\n    update\n    .t yview 98\n    .t index @0,0\n} {99.0}\ntest textDisp-16.7 {TkTextYviewCmd procedure} {\n    .t yview 2.0\n    .t yv -pickplace 13.0\n    .t index @0,0\n} {4.0}\ntest textDisp-16.8 {TkTextYviewCmd procedure} {\n    list [catch {.t yview bad_mark_name} msg] $msg\n} {1 {bad text index \"bad_mark_name\"}}\ntest textDisp-16.9 {TkTextYviewCmd procedure, \"moveto\" option} {\n    list [catch {.t yview moveto a b} msg] $msg\n} {1 {wrong # args: should be \".t yview moveto fraction\"}}\ntest textDisp-16.10 {TkTextYviewCmd procedure, \"moveto\" option} {\n    list [catch {.t yview moveto gorp} msg] $msg\n} {1 {expected floating-point number but got \"gorp\"}}\ntest textDisp-16.11 {TkTextYviewCmd procedure, \"moveto\" option} haveBigFontTwiceLargerThanTextFont {\n# constrained because text tagged with the big font plays a role\n    .t yview moveto 0.5\n    .t index @0,0\n} {103.0}\ntest textDisp-16.12 {TkTextYviewCmd procedure, \"moveto\" option} {\n    .t yview moveto -1\n    .t index @0,0\n} {1.0}\ntest textDisp-16.13 {TkTextYviewCmd procedure, \"moveto\" option} {\n    .t yview moveto 1.1\n    .t index @0,0\n} {191.0}\ntest textDisp-16.14 {TkTextYviewCmd procedure, \"moveto\" option} {\n    # y move to 3/4 of text widget content height\n    .t yview moveto .75\n    # target y position is inside line 151, which wraps 4 times\n    # exactly which display line depends on actual font size\n    set ytargetline [expr {150*$fixedHeight+5*$heightDiff}]\n    set expected 151.0\n    while {[expr {$ytargetline+$fixedHeight}] <= [expr {round(0.75*$totpix)}]} {\n\tincr ytargetline $fixedHeight\n\tset expected [.t index \"$expected + 1 display line\"]\n    }\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-16.15 {TkTextYviewCmd procedure, \"moveto\" option} {\n    # y move to 3/4 of text widget content height plus just one line height minus one pixel\n    .t yview moveto .75\n    set pixtonextline [expr {-[bo] + [lindex [.t bbox @0,0] 1] + [lindex [.t bbox @0,0] 3]}]\n    .t yview moveto [expr {0.75 + ($pixtonextline-1)/double($totpix)}]\n    # target y position is inside line 151, which wraps 4 times\n    # exactly which display line depends on actual font size\n    set ytargetline [expr {150*$fixedHeight+5*$heightDiff}]\n    set expected 151.0\n    while {[expr {$ytargetline+$fixedHeight}] <= [expr {round(0.75*$totpix + ($pixtonextline-1))}]} {\n\tincr ytargetline $fixedHeight\n\tset expected [.t index \"$expected + 1 display line\"]\n    }\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-16.16 {TkTextYviewCmd procedure, \"moveto\" option} {\n    # y move to 3/4 of text widget content height plus exactly one line height\n    .t yview moveto .75\n    set pixtonextline [expr {-[bo] + [lindex [.t bbox @0,0] 1] + [lindex [.t bbox @0,0] 3]}]\n    .t yview moveto [expr {0.75 + $pixtonextline/double($totpix)}]\n    # target y position is inside line 151, which wraps 4 times\n    # exactly which display line depends on actual font size\n    set ytargetline [expr {150*$fixedHeight+5*$heightDiff}]\n    set expected 151.0\n    while {[expr {$ytargetline+$fixedHeight}] <= [expr {round(0.75*$totpix + $pixtonextline)}]} {\n\tincr ytargetline $fixedHeight\n\tset expected [.t index \"$expected + 1 display line\"]\n    }\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-16.17 {TkTextYviewCmd procedure, \"moveto\" option} haveBigFontTwiceLargerThanTextFont {\n# constrained because text tagged with the big font plays a role\n    .t yview moveto .755\n    .t index @0,0\n} {151.80}\ntest textDisp-16.18 {TkTextYviewCmd procedure, \"moveto\" roundoff} {\n    catch {destroy .top1}\n    toplevel .top1\n    wm geometry .top1 +0+0\n    text .top1.t -height 3 -width 4 -wrap none -setgrid 1 -padx 6 \\\n\t-spacing3 6\n    pack .top1.t\n    update\n    .top1.t insert end \"1\\n2\\n3\\n4\\n5\\n6\"\n    .top1.t yview moveto 0.3333\n    set result [.top1.t yview]\n    destroy .top1\n    set result\n} [list [expr {1.0/3}] [expr {5.0/6}]]\ntest textDisp-16.19 {TkTextYviewCmd procedure, \"scroll\" option} {\n    list [catch {.t yview scroll a} msg] $msg\n} {1 {wrong # args: should be \".t yview scroll number pages|pixels|units\"}}\ntest textDisp-16.20 {TkTextYviewCmd procedure, \"scroll\" option} {\n    list [catch {.t yview scroll a b c} msg] $msg\n} {1 {wrong # args: should be \".t yview scroll number pages|pixels|units\"}}\ntest textDisp-16.21 {TkTextYviewCmd procedure, \"scroll\" option} {\n    list [catch {.t yview scroll bogus bogus} msg] $msg\n} {1 {bad argument \"bogus\": must be pages, pixels, or units}}\ntest textDisp-16.21.2 {TkTextYviewCmd procedure, \"scroll\" option} {\n    list [catch {.t yview scroll bogus units} msg] $msg\n} {1 {expected floating-point number but got \"bogus\"}}\ntest textDisp-16.22 {TkTextYviewCmd procedure, \"scroll\" option, back pages} {\n    .t yview 50.0\n    update\n    .t yview scroll -1 pages\n    .t index @0,0\n} {42.0}\ntest textDisp-16.22.1 {TkTextYviewCmd procedure, \"scroll\" option, back pages} {\n    list [catch {.t yview scroll -3 p} res] $res\n} {1 {ambiguous argument \"p\": must be pages, pixels, or units}}\ntest textDisp-16.23 {TkTextYviewCmd procedure, \"scroll\" option, back pages} {\n    .t yview 50.0\n    update\n    .t yview scroll -3 pa\n    .t index @0,0\n} {26.0}\ntest textDisp-16.24 {TkTextYviewCmd procedure, \"scroll\" option, back pages} {\n    .t yview 5.0\n    update\n    .t yview scroll -3 pa\n    .t index @0,0\n} {1.0}\ntest textDisp-16.25 {TkTextYviewCmd procedure, \"scroll\" option, back pages} -setup {\n    # this frame is needed because some window managers don't allow the overall\n    # height of a window to get very narrow, triggering false test failure\n    frame .f2 -height 20\n    pack .f2 -side top\n} -body {\n    .t configure -height 1\n    update\n    .t yview 50.0\n    update\n    .t yview scroll -1 pages\n    set x [.t index @0,0]\n    .t configure -height 10\n    update\n    set x\n} -cleanup {\n    destroy .f2\n} -result {49.0}\ntest textDisp-16.26 {TkTextYviewCmd procedure, \"scroll\" option, forward pages} {\n    .t yview 50.0\n    update\n    .t yview scroll 1 pages\n    .t index @0,0\n} {58.0}\ntest textDisp-16.27 {TkTextYviewCmd procedure, \"scroll\" option, forward pages} {\n    .t yview 50.0\n    update\n    .t yview scroll 2 pages\n    .t index @0,0\n} {66.0}\ntest textDisp-16.28 {TkTextYviewCmd procedure, \"scroll\" option, forward pages} {\n    .t yview 98.0\n    update\n    # The man page does not say it but the code does: scrolling 1 page actually uses the\n    # window height minus two lines, so that there's some overlap between adjacent pages.\n    # Note: it's a bit tricky but we only need to subtract one [bo] from [winfo height .t] here\n    # because the origin of @x,y coordinates is at borderwidth start, not at text area start.\n    set expected [.t index @0,[expr {[winfo height .t]-[bo]-2*$fixedHeight}]]\n    .t yview scroll 1 page\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-16.29 {TkTextYviewCmd procedure, \"scroll\" option, forward pages} {\n    .t configure -height 1\n    update\n    .t yview 50.0\n    update\n    .t yview scroll 1 pages\n    set x [.t index @0,0]\n    .t configure -height 10\n    update\n    set x\n} {51.0}\ntest textDisp-16.30 {TkTextYviewCmd procedure, \"scroll units\" option} {\n    .t yview 45.0\n    update\n    .t yview scroll -3 units\n    .t index @0,0\n} {42.0}\ntest textDisp-16.31 {TkTextYviewCmd procedure, \"scroll units\" option} {\n    .t yview 149.0\n    update\n    .t yview scroll 4 units\n    .t index @0,0\n} {151.40}\ntest textDisp-16.32 {TkTextYviewCmd procedure} {\n    list [catch {.t yview scroll 12 bogoids} msg] $msg\n} {1 {bad argument \"bogoids\": must be pages, pixels, or units}}\ntest textDisp-16.33 {TkTextYviewCmd procedure} {\n    list [catch {.t yview bad_arg 1 2} msg] $msg\n} {1 {bad option \"bad_arg\": must be moveto or scroll}}\ntest textDisp-16.34 {TkTextYviewCmd procedure} {\n    set res {}\n    .t yview 1.0\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n    .t yview scroll 1 pixels\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n    .t yview scroll 1 pixels\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n    .t yview scroll 1 pixels\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n    .t yview scroll 1 pixels\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n    .t yview scroll 1 pixels\n    lappend res [format %.12g [expr {[lindex [.t yview] 0]\n\t* [.t count -ypixels 1.0 end]}]]\n} {0 1 2 3 4 5}\ntest textDisp-16.35 {TkTextYviewCmd procedure} {\n    set res {}\n    .t yview 1.0\n    lappend res [expr {round([lindex [.t yview] 0] * [.t count -ypixels 1.0 end])}]\n    .t yview scroll 13 pixels\n    lappend res [expr {round([lindex [.t yview] 0] * [.t count -ypixels 1.0 end])}]\n    .t yview scroll -4 pixels\n    lappend res [expr {round([lindex [.t yview] 0] * [.t count -ypixels 1.0 end])}]\n    .t yview scroll -9 pixels\n    lappend res [expr {round([lindex [.t yview] 0] * [.t count -ypixels 1.0 end])}]\n} {0 13 9 0}\ntest textDisp-16.36 {TkTextYviewCmd procedure} {\n    set res {}\n    .t yview 1.0\n    .t yview scroll 5 pixels\n    .t yview scroll -1 pages\n    lappend res [expr {[lindex [.t yview] 0] * [.t count -ypixels 1.0 end]}]\n    .t yview scroll 5 pixels\n    .t yview scroll -1 units\n    lappend res [expr {[lindex [.t yview] 0] * [.t count -ypixels 1.0 end]}]\n} {0.0 0.0}\ntest textDisp-16.37 {TkTextYviewCmd procedure} {\n    list [catch {.t yview scroll 1.3 pixels} msg] $msg\n} {0 {}}\ntest textDisp-16.38 {TkTextYviewCmd procedure} {\n    list [catch {.t yview scroll 1.3blah pixels} msg] $msg\n} {1 {expected screen distance but got \"1.3blah\"}}\ntest textDisp-16.39 {TkTextYviewCmd procedure} {\n    list [catch {.t yview scroll 1.3i pixels} msg] $msg\n} {0 {}}\ntest textDisp-16.40 {text count -xpixels} {\n    set res {}\n    lappend res [.t count -xpixels 1.0 1.5] \\\n      [.t count -xpixels 1.5 1.0] \\\n      [.t count -xpixels 1.0 13.0] \\\n      [.t count -xpixels 1.0 \"1.0 displaylineend\"] \\\n      [.t count -xpixels 1.0 \"1.0 lineend\"] \\\n      [.t count -xpixels 1.0 \"1.0 displaylineend\"] \\\n      [.t count -xpixels 1.0 end]\n} [list [expr {5*$fixedWidth}] [expr {-5*$fixedWidth}] 0 [expr {6*$fixedWidth}] [expr {6*$fixedWidth}] [expr {6*$fixedWidth}] 0]\ntest textDisp-16.41 {text count -xpixels with indices in elided lines} {\n    set res {}\n    .t delete 1.0 end\n    for {set i 1} {$i < 40} {incr i} {\n\t.t insert end [string repeat \"Line $i\" 20]\n\t.t insert end \"\\n\"\n    }\n    .t configure -wrap none\n    .t tag add hidden 5.15 20.15\n    .t tag configure hidden -elide true\n    lappend res [.t count -xpixels 5.15 6.0] \\\n      [.t count -xpixels 5.15 6.1] \\\n      [.t count -xpixels 6.0 6.1] \\\n      [.t count -xpixels 6.1 6.2] \\\n      [.t count -xpixels 6.1 6.0] \\\n      [.t count -xpixels 6.0 7.0] \\\n      [.t count -xpixels 6.1 7.1] \\\n      [.t count -xpixels 15.0 20.15] \\\n      [.t count -xpixels 20.15 20.16] \\\n      [.t count -xpixels 20.16 20.15]\n    .t tag remove hidden 20.0 20.15\n    lappend res [expr {[.t count -xpixels 5.0 20.0] != 0}]\n} [list 0 0 0 0 0 0 0 0 $fixedWidth -$fixedWidth 1]\ntest textDisp-16.42 {TkTextYviewCmd procedure with indices in elided lines} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end [string repeat \"Line $i\" 20]\n\t.t insert end \"\\n\"\n    }\n    .t tag add hidden 5.15 20.15\n    .t tag configure hidden -elide true\n    .t yview 35.0\n    .t yview scroll [expr {- 15 * $fixedHeight}] pixels\n    update\n    .t index @0,0\n} {5.0}\ntest textDisp-16.43 {TkTextYviewCmd procedure with indices in elided lines} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end [string repeat \"Line $i\" 20]\n\t.t insert end \"\\n\"\n    }\n    .t tag add hidden 5.15 20.15\n    .t tag configure hidden -elide true\n    .t yview 35.0\n    .t yview scroll -15 units\n    update\n    .t index @0,0\n} {5.0}\ntest textDisp-16.44 {TkTextYviewCmd procedure, scroll down, with elided lines} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    foreach x [list 0 1 2 3 4 5 6 7 8 9 0] {\n      .t insert end \"$x aaa1\\n$x bbb2\\n$x ccc3\\n$x ddd4\\n$x eee5\\n$x fff6\"\n      .t insert end \"$x 1111\\n$x 2222\\n$x 3333\\n$x 4444\\n$x 5555\\n$x 6666\" hidden\n    }\n    .t tag configure hidden -elide true ; # 5 hidden lines\n    update\n    .t see [expr {5 + [winfo height .t] / $fixedHeight + 1}].0\n    update\n    .t index @0,0\n} {2.0}\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\nforeach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {\n    .t insert end \"\\nLine $i 11111 $i 22222 $i 33333 $i 44444 $i 55555\"\n    .t insert end \" $i 66666 $i 77777 $i 88888 $i\"\n}\n.t configure -wrap none\n\ntest textDisp-17.1 {TkTextScanCmd procedure} {\n    list [catch {.t scan a b} msg] $msg\n} {1 {wrong # args: should be \".t scan mark x y\" or \".t scan dragto x y ?gain?\"}}\ntest textDisp-17.2 {TkTextScanCmd procedure} {\n    list [catch {.t scan a b c d} msg] $msg\n} {1 {expected integer but got \"b\"}}\ntest textDisp-17.3 {TkTextScanCmd procedure} {\n    list [catch {.t scan stupid b 20} msg] $msg\n} {1 {expected integer but got \"b\"}}\ntest textDisp-17.4 {TkTextScanCmd procedure} {\n    list [catch {.t scan stupid -2 bogus} msg] $msg\n} {1 {expected integer but got \"bogus\"}}\ntest textDisp-17.5 {TkTextScanCmd procedure} {\n    list [catch {.t scan stupid 123 456} msg] $msg\n} {1 {bad scan option \"stupid\": must be dragto or mark}}\ntest textDisp-17.6 {TkTextScanCmd procedure} {\n    .t yview 1.0\n    .t xview moveto 0\n    update\n    set expected [.t index @[expr {[bo]+50}],[expr {[bo]+50}]]\n    .t scan mark 40 60\n    .t scan dragto 35 55\n    update\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-17.7 {TkTextScanCmd procedure} {\n    # 1st result\n    .t yview 1.0\n    .t xview moveto 0\n    update\n    set expected [.t index @[expr {[bo]+20*$fixedWidth-50}],[expr {[bo]+9*$fixedHeight-50}]]\n    .t yview 10.0\n    .t xview scroll 20 units\n    update\n    .t scan mark -10 60\n    .t scan dragto -5 65\n    update\n    set x [.t index @0,0]\n    # 2nd result\n    .t yview 1.0\n    .t xview moveto 0\n    update\n    lappend expected [.t index @[expr {[bo]+20*$fixedWidth-50-50}],[expr {[bo]+9*$fixedHeight-50-70}]]\n    .t yview 10.0\n    .t xview scroll 20 units\n    update\n    .t scan mark -10 60\n    .t scan dragto -5 65\n    update\n    .t scan dragto 0 72\n    update\n    lequal [list $x [.t index @0,0]] $expected\n} {1}\ntest textDisp-17.8 {TkTextScanCmd procedure} {\n    .t yview 1.0\n    .t xview moveto 0\n    update\n    set expected [.t index @[expr {[bo]+50}],[expr {[bo]+50}]]\n    .t scan mark 0 60\n    .t scan dragto 30 100\n    update\n    .t scan dragto 25 95\n    update\n    lequal [.t index @0,0] $expected\n} {1}\ntest textDisp-17.9 {TkTextScanCmd procedure} {\n    .t yview end\n    .t xview moveto 0\n    update\n    # this brings us at lower right corner of the text\n    .t xview scroll 100 units\n    update\n    # this does not trigger any scroll, we're already at the corner\n    .t scan mark 90 60\n    .t scan dragto 10 0\n    update\n    set expected [.t index @[expr {[winfo width .t]-[bo]-40}],[expr {[winfo height .t]-[bo]-50}]]\n    set expected [.t index \"$expected - [.t cget -height] lines - [.t cget -width] chars\"]\n    .t scan dragto 14 5\n    update\n    lequal [.t index @0,0] $expected\n} {1}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap word\n\ntest textDisp-17.10 {TkTextScanCmd procedure, word wrapping} {\n    .t yview 10.0\n    update\n    set origin [.t index @0,0]\n    set expected [.t index \"$origin - [expr {int(ceil(50.0/$fixedHeight))}] display lines\"]\n    .t scan mark -10 60\n    .t scan dragto -5 65\n    update\n    set x [.t index @0,0]\n    lappend expected [.t index \"$origin - [expr {int(ceil((50.0+70.0)/$fixedHeight))}] display lines\"]\n    .t scan dragto 0 72\n    update\n    lequal [list $x [.t index @0,0]] $expected\n} {1}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -xscrollcommand setScrollInfo -yscrollcommand {}\n\ntest textDisp-18.1 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx\n    update\n    set scrollInfo\n} [list 0.0 [expr {4.0/11}]]\ntest textDisp-18.2 {GetXView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx\n    update\n    set scrollInfo\n} {0.0 1.0}\ntest textDisp-18.3 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    update\n    set scrollInfo\n} {0.0 1.0}\ntest textDisp-18.4 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end xxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxx\n    update\n    set scrollInfo\n} {0.0 1.0}\ntest textDisp-18.5 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx\n    .t xview scroll 31 units\n    update\n    set scrollInfo\n} [list [expr {31.0/55}] [expr {51.0/55}]]\ntest textDisp-18.6 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end xxxxxxxxx\\n\n    .t insert end \"xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\\n\"\n    .t insert end \"xxxx xxxxxxxxx xxxxxxxxxxxxx\"\n    .t xview moveto 0\n    .t xview scroll 31 units\n    update\n    set x {}\n    lappend x $scrollInfo\n    .t configure -wrap char\n    update\n    lappend x $scrollInfo\n    .t configure -wrap word\n    update\n    lappend x $scrollInfo\n    .t configure -wrap none\n    update\n    lappend x $scrollInfo\n} [list [list [expr {31.0/56}] [expr {51.0/56}]] {0.0 1.0} {0.0 1.0} [list 0.0 [expr {5.0/14}]]]\ntest textDisp-18.7 {GetXView procedure} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    update\n    set scrollInfo unchanged\n    .t insert end xxxxxx\\n\n    .t insert end xxx\n    update\n    set scrollInfo\n} {unchanged}\ntest textDisp-18.8 {GetXView procedure} {\n    proc bgerror msg {\n\tglobal x errorInfo\n\tset x [list $msg $errorInfo]\n    }\n    proc bogus args {\n\terror \"bogus scroll proc\"\n    }\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n\n    update\n    .t delete 1.0 end\n    .t configure -xscrollcommand scrollError\n    update\n    set x\n} {{scrolling error} {scrolling error\n    while executing\n\"error \"scrolling error\"\"\n    (procedure \"scrollError\" line 2)\n    invoked from within\n\"scrollError 0.0 1.0\"\n    (horizontal scrolling command executed by text)}}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {rename bgerror {}}\ncatch {rename bogus {}}\n.t configure -xscrollcommand {} -yscrollcommand setScrollInfo\n\ntest textDisp-19.1 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    update\n    set scrollInfo\n} {0.0 1.0}\ntest textDisp-19.2 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    update\n    set scrollInfo \"unchanged\"\n    .t insert 1.0 \"Line1\\nLine2\"\n    update\n    set scrollInfo\n} {unchanged}\ntest textDisp-19.3 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    update\n    set scrollInfo \"unchanged\"\n    .t insert 1.0 \"Line 1\\nLine 2 is so long that it wraps around\\nLine 3\"\n    update\n    set scrollInfo\n} {unchanged}\ntest textDisp-19.4 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    update\n    set scrollInfo \"unchanged\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    update\n    set scrollInfo\n} [list 0.0 [expr {70.0/91}]]\ntest textDisp-19.5 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert 2.end \" is really quite long; in fact it's so long that it wraps three times\"\n    update\n    set x $scrollInfo\n} {0.0 0.625}\ntest textDisp-19.6 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert 2.end \" is really quite long; in fact it's so long that it wraps three times\"\n    .t yview 4.0\n    update\n    set x $scrollInfo\n} {0.375 1.0}\ntest textDisp-19.7 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert 2.end \" is really quite long; in fact it's so long that it wraps three times\"\n    .t yview 2.26\n    update\n    set x $scrollInfo\n} {0.125 0.75}\ntest textDisp-19.8 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert 10.end \" is really quite long; in fact it's so long that it wraps three times\"\n    .t yview 2.0\n    update\n    .t count -update -ypixels 1.0 end\n    set x $scrollInfo\n} {0.0625 0.6875}\ntest textDisp-19.9 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t yview 3.0\n    update\n    set scrollInfo\n} [list [expr {4.0/30}] 0.8]\ntest textDisp-19.10 {GetYView procedure} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t yview 11.0\n    update\n    set scrollInfo\n} [list [expr {1.0/3}] 1.0]\ntest textDisp-19.10.1 {Widget manipulation causes height miscount} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t yview 11.0\n    update\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\nThis last line wraps around four \"\n    .t insert end \"times with a little bit left on the last line.\"\n    .t yview insert\n    update\n    .t count -update -ypixels 1.0 end\n    set scrollInfo\n} {0.5 1.0}\ntest textDisp-19.11 {GetYView procedure} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\nThis last line wraps around four \"\n    .t insert end \"times with a little bit left on the last line.\"\n    .t yview insert\n    update\n    .t count -update -ypixels 1.0 end\n    set scrollInfo\n} {0.5 1.0}\ntest textDisp-19.11.2 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 1.0 end\n} 20\ntest textDisp-19.11.3 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines end 1.0\n} -20\ntest textDisp-19.11.4 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 1.1 1.3\n} 0\ntest textDisp-19.11.5 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 16.1\n} 0\ntest textDisp-19.11.5.1 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 16.5\n} 0\ntest textDisp-19.11.6 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 16.24\n} 1\ntest textDisp-19.11.7 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 16.40\n} 2\ntest textDisp-19.11.8 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines \"16.0 displaylineend +1c\" \"16.0 lineend\"\n} 3\ntest textDisp-19.11.9 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 \"16.0 lineend\"\n} 4\ntest textDisp-19.11.10 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 \"16.0 +4displaylines\"\n} 4\ntest textDisp-19.11.11 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines 16.0 \"16.0 +2displaylines\"\n} 2\ntest textDisp-19.11.12 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t count -displaylines \"16.0 +1displayline\" \"16.0 +2displaylines -1c\"\n} 0\n\n#\n# COMMON TEST SETUP\n#\n.t tag configure elide -elide 1\n\ntest textDisp-19.11.13 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"16.0 +1displaylines\" \"16.0 +1displaylines +6c\"\n    .t count -displaylines 16.0 \"16.0 +4displaylines\"\n} 4\ntest textDisp-19.11.14 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"16.0 +1displaylines\" \"16.0 +1displaylines displaylineend\"\n    .t count -displaylines 16.0 \"16.0 +4displaylines\"\n} 4\ntest textDisp-19.11.15 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"16.0 +1displaylines\" \"16.0 +2displaylines\"\n    .t count -displaylines 16.0 \"16.0 +4displaylines -1c\"\n} 3\ntest textDisp-19.11.15a {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"16.0 +1displaylines\" \"16.0 +2displaylines\"\n    .t count -displaylines 16.0 \"16.0 +4displaylines\"\n} 4\ntest textDisp-19.11.16 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"14.0\"\n    .t count -displaylines 12.0 16.0\n} 2\ntest textDisp-19.11.17 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"14.0\"\n    list [.t index \"11.5 +2d lines\"] \\\n      [.t index \"12.0 +2d lines\"] [.t index \"11.0 +2d lines\"] \\\n      [.t index \"13.0 +2d lines\"] [.t index \"13.1 +3d lines\"] \\\n      [.t index \"13.0 +4d lines\"]\n} {15.5 16.0 15.0 16.0 16.21 16.39}\ntest textDisp-19.11.18 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"14.0\"\n    list [.t index \"15.5 -2d lines\"] \\\n      [.t index \"16.0 -2d lines\"] [.t index \"15.0 -2d lines\"] \\\n      [.t index \"16.0 -3d lines\"] [.t index \"16.23 -4d lines\"] \\\n      [.t index \"16.42 -5d lines\"]\n} {11.5 14.0 11.0 11.0 11.2 11.3}\ntest textDisp-19.11.19 {TextWidgetCmd procedure, \"count -displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"16.0 +1displaylines\"\n    .t count -displaylines 12.0 17.0\n} 4\ntest textDisp-19.11.20 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"16.0 +1displaylines\"\n    list [.t index \"11.5 +2d lines\"] \\\n      [.t index \"12.0 +2d lines\"] [.t index \"11.0 +2d lines\"] \\\n      [.t index \"13.0 +2d lines\"] [.t index \"13.0 +3d lines\"] \\\n      [.t index \"13.0 +4d lines\"]\n} {16.44 16.57 16.39 16.57 16.74 17.0}\ntest textDisp-19.11.21 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.0\" \"16.0 +1displaylines\"\n    list [.t index \"16.44 -2d lines\"] \\\n      [.t index \"16.57 -3d lines\"] [.t index \"16.39 -2d lines\"] \\\n      [.t index \"16.60 -4d lines\"] [.t index \"16.76 -4d lines\"] \\\n      [.t index \"17.0 -5d lines\"]\n} {11.5 11.0 11.0 10.3 11.2 11.0}\ntest textDisp-19.11.22 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    list [.t index \"end +5d lines\"] \\\n      [.t index \"end -3d lines\"] [.t index \"1.0 -2d lines\"] \\\n      [.t index \"1.0 +4d lines\"] [.t index \"1.0 +50d lines\"] \\\n      [.t index \"end -50d lines\"]\n} {17.0 16.39 1.0 5.0 17.0 1.0}\ntest textDisp-19.11.23 {TextWidgetCmd procedure, \"index +displaylines\"} {\n    .t tag remove elide 1.0 end\n    .t tag add elide \"12.3\" \"16.0 +1displaylines\"\n    list [.t index \"11.5 +1d lines\"] [.t index \"11.5 +2d lines\"] \\\n      [.t index \"12.0 +1d lines\"] \\\n      [.t index \"12.0 +2d lines\"] [.t index \"11.0 +2d lines\"] \\\n      [.t index \"13.0 +2d lines\"] [.t index \"13.0 +3d lines\"] \\\n      [.t index \"13.0 +4d lines\"]\n} {16.23 16.44 16.39 16.57 16.39 16.60 16.77 16.79}\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag remove elide 1.0 end\n\ntest textDisp-19.11.24 {TextWidgetCmd procedure, \"index +/-displaylines\"} {\n    list [.t index \"11.5 + -1 display lines\"] \\\n      [.t index \"11.5 + +1 disp lines\"] \\\n      [.t index \"11.5 - -1 disp lines\"] \\\n      [.t index \"11.5 - +1 disp lines\"] \\\n      [.t index \"11.5 -1 disp lines\"] \\\n      [.t index \"11.5 +1 disp lines\"] \\\n      [.t index \"11.5 +0 disp lines\"]\n} {10.5 12.5 12.5 10.5 10.5 12.5 11.5}\n\ntest textDisp-19.12 {GetYView procedure, partially visible last line} {\n    catch {destroy .top}\n    toplevel .top\n    wm geometry .top +0+0\n    text .top.t -width 40 -height 5 -font $fixedFont\n    pack .top.t -expand yes -fill both\n    .top.t insert end \"Line 1\\nLine 2\\nLine 3\\nLine 4\\nLine 5\"\n    # Need to wait for asychronous calculations to complete.\n    update\n    scan [wm geom .top] %dx%d twidth theight\n    wm geom .top ${twidth}x[expr {$theight - 3}]\n    update\n    .top.t yview\n} [list 0.0 [expr {(5.0 * $fixedHeight - 3.0)/ (5.0 * $fixedHeight)}]]\ntest textDisp-19.13 {GetYView procedure, partially visible last line} {\n    catch {destroy .top}\n    toplevel .top\n    wm geometry .top +0+0\n    text .top.t -width 40 -height 5 -font $fixedFont\n    pack .top.t -expand yes -fill both\n    .top.t insert end \"Line 1\\nLine 2\\nLine 3\\nLine 4 has enough text to wrap around at least once\"\n    # Need to wait for asychronous calculations to complete.\n    update\n    scan [wm geom .top] %dx%d twidth theight\n    wm geom .top ${twidth}x[expr {$theight - 3}]\n    update\n    .top.t yview\n} [list 0.0 [expr {(5.0 * $fixedHeight - 3.0)/ (5.0 * $fixedHeight)}]]\n\n#\n# COMMON TEST CLEANUP\n#\ncatch {destroy .top}\n\ntest textDisp-19.14 {GetYView procedure} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\nThis last line wraps around four \"\n    .t insert end \"times with a little bit left on the last line.\"\n    # Need to update so everything is calculated.\n    update\n    .t count -update -ypixels 1.0 end\n    delay\n    set scrollInfo \"unchanged\"\n    .t mark set insert 3.0\n    .t tag configure x -background red\n    .t tag add x 1.0 5.0\n    update\n    .t tag delete x\n    set scrollInfo\n} {unchanged}\ntest textDisp-19.15 {GetYView procedure} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\nThis last line wraps around four \"\n    .t insert end \"times with a bit little left on the last line.\"\n    update\n    .t configure -yscrollcommand scrollError\n    proc bgerror args {\n\tglobal x errorInfo errorCode\n\tset x [list $args $errorInfo $errorCode]\n    }\n    .t delete 1.0 end\n    update\n    rename bgerror {}\n    .t configure -yscrollcommand setScrollInfo\n    set x\n} {{{scrolling error}} {scrolling error\n    while executing\n\"error \"scrolling error\"\"\n    (procedure \"scrollError\" line 2)\n    invoked from within\n\"scrollError 0.0 1.0\"\n    (vertical scrolling command executed by text)} NONE}\n\ntest textDisp-19.16 {count -ypixels} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\"\n    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {\n\t.t insert end \"\\nLine $i\"\n    }\n    .t insert end \"\\nThis last line wraps around four \"\n    .t insert end \"times with a little bit left on the last line.\"\n    # Need to update so everything is calculated.\n    update\n    .t count -update -ypixels 1.0 end\n    update\n    set res [list \\\n      [.t count -ypixels 1.0 end] \\\n      [.t count -update -ypixels 1.0 end] \\\n      [.t count -ypixels 15.0 16.0] \\\n      [.t count -ypixels 15.0 \"16.0 displaylineend +1c\"] \\\n      [.t count -ypixels 16.0 \"16.0 displaylineend +1c\"] \\\n      [.t count -ypixels \"16.0 +1 displaylines\" \"16.0 +4 displaylines +3c\"] ]\n} [list [expr {20 * $fixedHeight}] \\\n\t[expr {20 * $fixedHeight}] \\\n\t$fixedHeight \\\n\t[expr {2*$fixedHeight}] \\\n\t$fixedHeight \\\n\t[expr {3*$fixedHeight}]]\ntest textDisp-19.17 {count -ypixels with indices in elided lines} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end [string repeat \"Line $i\" 20]\n\t.t insert end \"\\n\"\n    }\n    .t tag add hidden 5.15 20.15\n    .t tag configure hidden -elide true\n    update\n    .t count -update -ypixels 1.0 end\n    update\n    set res [list \\\n      [.t count -ypixels 1.0 6.0] \\\n      [.t count -ypixels 2.0 7.5] \\\n      [.t count -ypixels 5.0 8.5] \\\n      [.t count -ypixels 6.1 6.2] \\\n      [.t count -ypixels 6.1 18.8] \\\n      [.t count -ypixels 18.0 20.50] \\\n      [.t count -ypixels 5.2 20.60] \\\n      [.t count -ypixels 20.60 20.70] \\\n      [.t count -ypixels 5.0 25.0] \\\n      [.t count -ypixels 25.0 5.0] \\\n      [.t count -ypixels 25.4 27.50] \\\n      [.t count -ypixels 35.0 38.0] ]\n    .t yview 35.0\n    lappend res [.t count -ypixels 5.0 25.0]\n} [list [expr {4 * $fixedHeight}] \\\n\t[expr {3 * $fixedHeight}] \\\n\t0 0 0 0 0 0 \\\n\t[expr {5 * $fixedHeight}] \\\n\t[expr {- 5 * $fixedHeight}] \\\n\t[expr {2 * $fixedHeight}] \\\n\t[expr {3 * $fixedHeight}] \\\n\t[expr {5 * $fixedHeight}]]\ntest textDisp-19.18 {count -ypixels with indices in elided lines} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    for {set i 1} {$i < 100} {incr i} {\n\t.t insert end [string repeat \"Line $i\" 20]\n\t.t insert end \"\\n\"\n    }\n    .t tag add hidden 5.15 20.15\n    .t tag configure hidden -elide true\n    .t yview 35.0\n    update\n    .t count -update -ypixels 1.0 end\n    update\n    set res [.t count -ypixels 5.0 25.0]\n    .t yview scroll [expr {- 15 * $fixedHeight}] pixels\n    update\n    lappend res [.t count -ypixels 5.0 25.0]\n} [list [expr {5 * $fixedHeight}] [expr {5 * $fixedHeight}]]\ntest textDisp-19.19 {count -ypixels with indices in elided lines} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    for {set i 1} {$i < 25} {incr i} {\n\t.t insert end [string repeat \"Line $i -\" 6]\n\t.t insert end \"\\n\"\n    }\n    .t tag add hidden 5.27 11.0\n    .t tag configure hidden -elide true\n    .t yview 5.0\n    update\n    set res [list [.t count -ypixels 5.0 11.0] [.t count -ypixels 5.0 11.20]]\n} [list [expr {1 * $fixedHeight}] [expr {2 * $fixedHeight}]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\n.t insert end \"Line 1\"\nfor {set i 2} {$i <= 200} {incr i} {\n    .t insert end \"\\nLine $i\"\n}\n.t configure -wrap word\n.t delete 50.0 51.0\n.t insert 50.0 \"This is a long line, one that will wrap around twice.\\n\"\n\ntest textDisp-20.1 {FindDLine} {\n    .t yview 48.0\n    list [.t dlineinfo 46.0] [.t dlineinfo 47.0] [.t dlineinfo 49.0] \\\n\t    [.t dlineinfo 58.0]\n} [list {} {} [list [bo] [yline 2] [xw 7] $fixedHeight $fixedAscent] {}]\ntest textDisp-20.2 {FindDLine} {\n    .t yview 100.0\n    .t yview -pickplace 53.0\n    set centlineY [lindex [.t bbox 53.0] 1]\n    set expectedY [expr {$centlineY - int(($centlineY-[bo])/$fixedHeight)*$fixedHeight - $fixedHeight}]\n    set expected [list [list [bo] $expectedY [xw 20] $fixedHeight $fixedAscent] \\\n\t\t       [list [bo] $expectedY [xw 20] $fixedHeight $fixedAscent] \\\n\t\t       [list [bo] [expr {$expectedY+$fixedHeight}] [xw 19] $fixedHeight $fixedAscent]]\n    set res [list [.t dlineinfo 50.0] [.t dlineinfo 50.14] [.t dlineinfo 50.21]]\n    lequal $res $expected\n} {1}\ntest textDisp-20.3 {FindDLine} {\n    .t yview 100.0\n    .t yview 49.0\n    list [.t dlineinfo 50.0] [.t dlineinfo 50.24] [.t dlineinfo 57.0]\n} [list [list [bo] [yline 2] [xw 20] $fixedHeight $fixedAscent] \\\n\t[list [bo] [yline 3] [xw 19] $fixedHeight $fixedAscent] \\\n\t{}]\ntest textDisp-20.4 {FindDLine} {\n    .t yview 100.0\n    .t yview 42.0\n    list [.t dlineinfo 50.0] [.t dlineinfo 50.24] [.t dlineinfo 50.40]\n} [list [list [bo] [yline 9] [xw 20] $fixedHeight $fixedAscent] \\\n\t[list [bo] [yline 10] [xw 19] $fixedHeight $fixedAscent] \\\n\t{}]\n\ntest textDisp-20.5 {FindDLine} -setup {\n    .t config -wrap none\n} -body {\n    .t yview 100.0\n    .t yview 48.0\n    list [.t dlineinfo 50.0] [.t dlineinfo 50.20] [.t dlineinfo 50.40]\n} -cleanup {\n    .t config -wrap word\n} -result [list [list [bo] [yline 3] [xw 53] $fixedHeight $fixedAscent] \\\n\t\t[list [bo] [yline 3] [xw 53] $fixedHeight $fixedAscent] \\\n\t\t[list [bo] [yline 3] [xw 53] $fixedHeight $fixedAscent]]\n\ntest textDisp-21.1 {TkTextPixelIndex} {\n    .t yview 48.0\n    set off [expr {[bo]+3}]\n    list [.t index @-10,-10] [.t index @$off,$off] [.t index @[expr {[xchar 2]+2}],$off] \\\n\t    [.t index @[expr {[xchar 14]+1}],$off] [.t index @[xchar 5],[yline 5]]\n} {48.0 48.0 48.2 48.7 50.45}\n\n#\n# COMMON TEST SETUP\n#\n\n.t insert end \\n\n\ntest textDisp-21.2 {TkTextPixelIndex} {\n    .t yview 195.0\n    set off [expr {[xchar 1]+1}]\n    list [.t index @$off,[expr {[yline 6]+2}]] \\\n\t [.t index @$off,[expr {[yline 7]+2}]] \\\n\t [.t index @$off,[expr {[yline 8]+2}]] \\\n\t [.t index @$off,1002]\n} {197.1 198.1 199.1 201.0}\ntest textDisp-21.3 {TkTextPixelIndex, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"12345\\n\"\n    .t insert end \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n    .t xview scroll 2 units\n    set off [expr {[yline 1]+4}]\n    list [.t index @-5,$off] [.t index @[expr {[xchar 1]-2}],$off] [.t index @[expr {[xchar 4]+2}],[expr {[yline 2]+2}]]\n} {1.2 1.2 2.6}\ntest textDisp-21.4 {count -displaylines regression} {\n    set message {\n   QOTW:  \"C/C++, which is used by 16% of users, is the most popular programming language, but Tcl, used by 0%, seems to be the language of choice for the highest scoring users.\"\n(new line)\nUse the Up (cursor) key to scroll up one line at a time.  At the second press, the cursor either gets locked or jumps several lines.\n\nConnect with Tkcon.  The command\n.u count -displaylines \\\n3.10 2.173\nshould give answer -1; it gives me 5.\n\nUsing 8.5a4 (ActiveState beta 4) under Linux.  No problem with ActiveState beta 3.\n}\n\ntoplevel .tt\npack [text .tt.u] -side right\n.tt.u configure -width 30 -height 27 -wrap word -bg #FFFFFF\n.tt.u insert end $message\n.tt.u mark set insert 3.10\ntkwait visibility .tt.u\nset res [.tt.u count -displaylines 3.10 2.173]\ndestroy .tt\nunset message\nset res\n} -1\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\n.t insert end \"Line 1\"\nfor {set i 2} {$i <= 200} {incr i} {\n    .t insert end \"\\nLine $i\"\n}\n.t configure -wrap word\n.t delete 50.0 51.0\n.t insert 50.0 \"This is a long line, one that will wrap around twice.\\n\"\nupdate\n.t tag add x 50.1\n\ntest textDisp-22.1 {TkTextCharBbox} {\n    .t config -wrap word\n    .t yview 48.0\n    list [.t bbox 47.2] [.t bbox 48.0] [.t bbox 50.5] [.t bbox 50.40] \\\n\t    [.t bbox 58.0]\n} [list {} \\\n\t[list [xchar 0] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 5] [yline 3] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 5] $fixedWidth $fixedHeight] \\\n\t{}]\ntest textDisp-22.2 {TkTextCharBbox} {\n    .t config -wrap none\n    .t yview 48.0\n    list [.t bbox 50.5] [.t bbox 50.40] [.t bbox 57.0]\n} [list [list [xchar 5] [yline 3] $fixedWidth $fixedHeight] \\\n\t{} \\\n\t[list [xchar 0] [yline 10] $fixedWidth $fixedHeight]]\ntest textDisp-22.3 {TkTextCharBbox, cut-off lines} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t config -wrap char\n    .t yview 10.0\n    wm geom . ${width}x[expr {$height-1}]\n    update\n    set expected [list [list [xchar 1] [yline 10] $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 1] [yline 11] $fixedWidth [expr {($height-1)-$oriHeight}]]]\n    lequal [list [.t bbox 19.1] [.t bbox 20.1]] $expected\n} {1}\ntest textDisp-22.4 {TkTextCharBbox, cut-off lines} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t config -wrap char\n    .t yview 10.0\n    wm geom . ${width}x[expr {$height+1}]\n    update\n    set expected [list [list [xchar 1] [yline 10] $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 1] [yline 11] $fixedWidth [expr {($height+1)-$oriHeight}]]]\n    lequal [list [.t bbox 19.1] [.t bbox 20.1]] $expected\n} {1}\ntest textDisp-22.5 {TkTextCharBbox, cut-off char} {\n    wm geometry . {}\n    update\n    .t config -wrap none\n    .t yview 10.0\n    wm geom . [expr {$width-(20-7)*$fixedWidth}]x$height\n    update\n    .t bbox 15.6\n} [list [xchar 6] [yline 6] $fixedWidth $fixedHeight]\ntest textDisp-22.6 {TkTextCharBbox, line visible but not char} haveBigFontTwiceLargerThanTextFont {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t config -wrap char\n    .t yview 10.0\n    .t tag add big 20.2 20.5\n    wm geom . ${width}x[expr {$height+3}]\n    update\n    set expected [list [list [xchar 1] [yline 10] $fixedWidth $fixedHeight] \\\n\t\t       {} \\\n\t\t       [list [xchar 2] [yline 11] [font measure $bigFont \"n\"] [expr {($height+3)-$oriHeight}]]]\n    lequal [list [.t bbox 19.1] [.t bbox 20.1] [.t bbox 20.2]] $expected\n} {1}\n\n#\n# COMMON TEST SETUP\n#\n\nwm geom . {}\nupdate\n\ntest textDisp-22.7 {TkTextCharBbox, different character sizes} haveBigFontTwiceLargerThanTextFont {\n    .t config -wrap char\n    .t yview 10.0\n    .t tag add big 12.2 12.5\n    update\n    list [.t bbox 12.1] [.t bbox 12.2]\n} [list [list [xchar 1] [expr {[yline 3]+$ascentDiff}] $fixedWidth $fixedHeight] \\\n\t[list [xchar 2] [yline 3] [font measure $bigFont \"n\"] $bigHeight]]\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag remove big 1.0 end\n\ntest textDisp-22.8 {TkTextCharBbox, horizontal scrolling} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert end \"12345\\n\"\n    .t insert end \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n    .t xview scroll 4 units\n    list [.t bbox 1.3] [.t bbox 1.4] [.t bbox 2.3] [.t bbox 2.4] \\\n\t    [.t bbox 2.23] [.t bbox 2.24]\n} [list {} \\\n\t[list [xchar 0] [yline 1] $fixedWidth $fixedHeight] \\\n\t{} \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 19] [yline 2] $fixedWidth $fixedHeight] \\\n\t{}]\ntest textDisp-22.9 {TkTextCharBbox, handling of spacing} -body {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijkl\\nmnopqrstuvwzyz\"\n    .t tag configure spacing -spacing1 8 -spacing3 2\n    .t tag add spacing 1.0 end\n    frame .t.f1 -width 10 -height 4 -bg black\n    frame .t.f2 -width 10 -height 4 -bg black\n    frame .t.f3 -width 10 -height 4 -bg black\n    frame .t.f4 -width 10 -height 4 -bg black\n    .t window create 1.3 -window .t.f1 -align top\n    .t window create 1.7 -window .t.f2 -align center\n    .t window create 2.1 -window .t.f3 -align bottom\n    .t window create 2.10 -window .t.f4 -align baseline\n    update\n    list [.t bbox .t.f1] [.t bbox .t.f2] [.t bbox .t.f3] [.t bbox .t.f4] \\\n\t    [.t bbox 1.1] [.t bbox 2.9]\n} -cleanup {\n    .t tag delete spacing\n} -result [list [list [xchar 3] [expr {[yline 1]+8}] 10 4] \\\n\t\t[list [expr {[xchar 3]+10+[xw 3]}] [expr {[yline 1]+8+($fixedHeight-4)/2}] 10 4] \\\n\t\t[list [xchar 1] [expr {[yline 2]+8+2+8+($fixedHeight-4)}] 10 4] \\\n\t\t[list [expr {[xchar 1]+10+[xw 8]}] [expr {[yline 2]+8+2+8+($fixedAscent-4)}] 10 4] \\\n\t\t[list [xchar 1] [expr {[yline 1]+8}] $fixedWidth $fixedHeight] \\\n\t\t[list [expr {[xchar 1]+10+[xw 7]}] [expr {[yline 2]+8+2+8}] $fixedWidth $fixedHeight]]\ntest textDisp-22.10 {TkTextCharBbox, handling of elided lines} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i - Line [format %c [expr {64+$i}]]\\n\"\n    }\n    .t tag add hidden 2.8 2.13\n    .t tag add hidden 6.8 7.13\n    .t tag configure hidden -elide true\n    update\n    list \\\n\t[expr {[lindex [.t bbox 2.9]  0] - [lindex [.t bbox 2.8] 0]}] \\\n\t[expr {[lindex [.t bbox 2.10] 0] - [lindex [.t bbox 2.8] 0]}] \\\n\t[expr {[lindex [.t bbox 2.13] 0] - [lindex [.t bbox 2.8] 0]}] \\\n\t[expr {[lindex [.t bbox 6.9]  0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 6.10] 0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 6.13] 0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 6.14] 0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 6.15] 0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 7.0]  0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 7.1]  0] - [lindex [.t bbox 6.8] 0]}] \\\n\t[expr {[lindex [.t bbox 7.12] 0] - [lindex [.t bbox 6.8] 0]}]\n} [list 0 0 0 0 0 0 0 0 0 0 0]\ntest textDisp-22.11 {TkTextCharBbox, handling of wrapped elided lines} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    for {set i 1} {$i < 10} {incr i} {\n\t.t insert end \"Line $i - Line _$i - Lines .$i - Line [format %c [expr {64+$i}]]\\n\"\n    }\n    .t tag add hidden 1.30 2.5\n    .t tag configure hidden -elide true\n    update\n    list \\\n\t[expr {[lindex [.t bbox 1.30] 0] - [lindex [.t bbox 2.4]  0]}] \\\n\t[expr {[lindex [.t bbox 1.30] 0] - [lindex [.t bbox 2.5]  0]}]\n} [list 0 0]\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\n.t insert end \"Line 1\"\nfor {set i 2} {$i <= 200} {incr i} {\n    .t insert end \"\\nLine $i\"\n}\n.t configure -wrap word\n.t delete 50.0 51.0\n.t insert 50.0 \"This is a long line, one that will wrap around twice.\\n\"\nupdate\n\ntest textDisp-23.1 {TkTextDLineInfo} {\n    .t config -wrap word\n    .t yview 48.0\n    list [.t dlineinfo 47.3] [.t dlineinfo 48.0] [.t dlineinfo 50.40] \\\n\t    [.t dlineinfo 56.0]\n} [list {} \\\n\t[list [bo] [yline 1] [xw 7] $fixedHeight $fixedAscent] \\\n\t[list [bo] [yline 5] [xw 13] $fixedHeight $fixedAscent] \\\n\t{}]\n\n.t config -bd 4\n\ntest textDisp-23.2 {TkTextDLineInfo} -setup {\n    .t config -bd 4\n} -body {\n    .t config -wrap word\n    update\n    .t yview 48.0\n    .t dlineinfo 50.40\n} -cleanup {\n    .t config -bd 0\n} -result [list [bo] [yline 5] [xw 13] $fixedHeight $fixedAscent]\ntest textDisp-23.3 {TkTextDLineInfo} {\n    .t config -wrap none\n    update\n    .t yview 48.0\n    list [.t dlineinfo 50.40] [.t dlineinfo 57.3]\n} [list [list [bo] [yline 3] [xw 53] $fixedHeight $fixedAscent] \\\n\t[list [bo] [yline 10] [xw 7] $fixedHeight $fixedAscent]]\ntest textDisp-23.4 {TkTextDLineInfo, cut-off lines} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t config -wrap char\n    .t yview 10.0\n    wm geom . ${width}x[expr {$height-1}]\n    update\n    set expected [list [list [bo] [yline 10] [xw 7] $fixedHeight $fixedAscent] \\\n\t\t       [list [bo] [yline 11] [xw 7] [expr {($height-1)-$oriHeight}] $fixedAscent]]\n    lequal [list [.t dlineinfo 19.0] [.t dlineinfo 20.0]] $expected\n} {1}\ntest textDisp-23.5 {TkTextDLineInfo, cut-off lines} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t config -wrap char\n    .t yview 10.0\n    wm geom . ${width}x[expr {$height+1}]\n    update\n    set expected [list [list [bo] [yline 10] [xw 7] $fixedHeight $fixedAscent] \\\n\t\t       [list [bo] [yline 11] [xw 7] [expr {($height+1)-$oriHeight}] $fixedAscent]]\n    lequal [list [.t dlineinfo 19.0] [.t dlineinfo 20.0]] $expected\n} {1}\n\n#\n# COMMON TEST SETUP\n#\n\nwm geom . {}\nupdate\n\ntest textDisp-23.6 {TkTextDLineInfo, horizontal scrolling} {\n    .t config -wrap none\n    .t delete 1.0 end\n    .t insert end \"First line\\n\"\n    .t insert end \"Second line is a very long one that doesn't all fit.\\n\"\n    .t insert end \"Third\"\n    .t xview scroll 6 units\n    update\n    list [.t dlineinfo 1.0] [.t dlineinfo 2.0] [.t dlineinfo 3.0]\n} [list [list [expr {[xw -6]+[bo]}] [yline 1] [xw 10] $fixedHeight $fixedAscent] \\\n\t[list [expr {[xw -6]+[bo]}] [yline 2] [xw 52] $fixedHeight $fixedAscent] \\\n\t[list [expr {[xw -6]+[bo]}] [yline 3] [xw 5] $fixedHeight $fixedAscent]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t xview moveto 0\n\ntest textDisp-23.7 {TkTextDLineInfo, centering} -body {\n    .t config -wrap word\n    .t delete 1.0 end\n    .t insert end \"First line\\n\"\n    .t insert end \"Second line is a very long one that doesn't all fit.\\n\"\n    .t insert end \"Third\"\n    .t tag configure x -justify center\n    .t tag configure y -justify right\n    .t tag add x 1.0\n    .t tag add y 3.0\n    list [.t dlineinfo 1.0] [.t dlineinfo 2.0] [.t dlineinfo 3.0]\n} -cleanup {\n    .t tag delete x y\n} -result [list [list [expr {[bo]+[xe 10]/2}] [yline 1] [xw 10] $fixedHeight $fixedAscent] \\\n\t[list [bo] [yline 2] [xw 17] $fixedHeight $fixedAscent] \\\n\t[list [xcharr 5] [yline 5] [xw 5] $fixedHeight $fixedAscent]]\n\ntest textDisp-24.1 {TkTextCharLayoutProc} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-24.2 {TkTextCharLayoutProc} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    # be tolerant about borderwidth et al. - don't let another char fit on the line\n    set wi $width\n    while {$wi+1-$oriWidth >= $fixedWidth} {\n\tincr wi -$fixedWidth\n    }\n    wm geom . [expr {$wi+1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($wi+1-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.3 {TkTextCharLayoutProc} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    wm geom . [expr {$width-1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($width-1-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.4 {TkTextCharLayoutProc, newline not visible} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 01234567890123456789\\n012345678901234567890\n    wm geom . {}\n    update\n    list [.t bbox 1.19] [.t bbox 1.20] [.t bbox 2.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 20] [yline 1] 0 $fixedHeight] \\\n\t[list [xchar 0] [yline 3] $fixedWidth $fixedHeight]]\ntest textDisp-24.5 {TkTextCharLayoutProc, char doesn't fit, newline not visible} macOrUnix {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 0\\n1\\n\n    # set text widget width to 1-char width minus [bo] pixels\n    # note: windows refuses to shrink enough therefore the constraint\n    set wi [expr {[winfo width .f]+[bo]+[xw 1]}]\n    wm geom . ${wi}x$height\n    update\n    list [.t bbox 1.0] [.t bbox 1.1] [.t bbox 2.0]\n} [list [list [xchar 0] [yline 1] [expr {$fixedWidth-[bo]}] $fixedHeight] \\\n\t[list [expr {[xchar 1]-[bo]}] [yline 1] 0 $fixedHeight] \\\n\t[list [xchar 0] [yline 2] [expr {$fixedWidth-[bo]}] $fixedHeight]]\ntest textDisp-24.6 {TkTextCharLayoutProc, line ends with space} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a b c d e f g h i j k l m n o p\"\n    wm geom . {}\n    update\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-24.7 {TkTextCharLayoutProc, line ends with space} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a b c d e f g h i j k l m n o p\"\n    # be tolerant about borderwidth et al. - don't let another char fit on the line\n    set wi $width\n    while {$wi+1-$oriWidth >= $fixedWidth} {\n\tincr wi -$fixedWidth\n    }\n    wm geom . [expr {$wi+1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($wi+1-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.8 {TkTextCharLayoutProc, line ends with space} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a b c d e f g h i j k l m n o p\"\n    wm geom . [expr {$width-1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($width-1-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.9 {TkTextCharLayoutProc, line ends with space} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a b c d e f g h i j k l m n o p\"\n    wm geom . [expr {$width-6}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($width-6-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.10 {TkTextCharLayoutProc, line ends with space} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"a b c d e f g h i j k l m n o p\"\n    wm geom . [expr {$width-7}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] [expr {$fixedWidth+($width-7-$oriWidth)}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.11 {TkTextCharLayoutProc, line ends with space that doesn't quite fit} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"01234567890123456789 \\nabcdefg\"\n    # set text widget width to 2 pixels more than 20-char width\n    set wi [expr {[winfo width .f]+2*[bo]+[xw 20]+2}]\n    wm geom . ${wi}x$height\n    update\n    set result [list [.t bbox 1.21] [.t bbox 2.0]]\n    .t mark set insert 1.21\n    lappend result [.t bbox 1.21] [.t bbox 2.0]\n} [list [list [expr {[xchar 20]+2}] [yline 1] 0 $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [expr {[xchar 20]+2}] [yline 1] 0 $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n\n#\n# COMMON TEST SETUP\n#\n\nwm geom . {}\nupdate\n\ntest textDisp-24.12 {TkTextCharLayoutProc, tab causes wrap} {\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghi\"\n    .t mark set insert 1.4\n    .t insert insert \\t\\t\\t\n    set expected [list [list [expr {[xchar 0]+2*8*$fixedWidth}] [yline 1] [expr {[winfo width .t]-([xchar 0]+2*8*$fixedWidth)-[bo]}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox {insert -1c}] [.t bbox insert]] $expected\n} {1}\ntest textDisp-24.13 {TkTextCharLayoutProc, -wrap none} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    wm geom . {}\n    update\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] {}]\ntest textDisp-24.14 {TkTextCharLayoutProc, -wrap none} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    wm geom . [expr {$width+1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 20] [yline 1] [expr {$width+1-$oriWidth}] $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.15 {TkTextCharLayoutProc, -wrap none} {\n    wm geometry . {}\n    update\n    scan [wm geom .] %dx%d oriWidth oriHeight\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    wm geom . [expr {$width-1}]x$height\n    update\n    set expected [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t\t       [list [xchar 20] [yline 1] [expr {$width-1-$oriWidth}] $fixedHeight]]\n    lequal [list [.t bbox 1.19] [.t bbox 1.20]] $expected\n} {1}\ntest textDisp-24.16 {TkTextCharLayoutProc, no chars fit} {\n    if {[tk windowingsystem] eq \"win32\"} {\n\twm overrideredirect . 1\n    }\n    .t configure -wrap char\n    .t delete 1.0 end\n    .t insert 1.0 \"abcdefghijklmnopqrstuvwxyz\"\n    # set text widget width to [bo] pixels (no chars fit in the widget at all)\n    set wi [expr {[winfo width .f]+[bo]}]\n    wm geom . ${wi}x$height\n    update\n    list [.t bbox 1.0] [.t bbox 1.1] [.t bbox 1.2]\n} [list [list [xchar 0] [yline 1] 1 $fixedHeight] \\\n\t[list [xchar 0] [yline 2] 1 $fixedHeight] \\\n\t[list [xchar 0] [yline 3] 1 $fixedHeight]]\n\n#\n# COMMON TEST SETUP\n#\n\nif {[tk windowingsystem] eq \"win32\"} {\n    wm overrideredirect . 0\n}\n\ntest textDisp-24.17 {TkTextCharLayoutProc, -wrap word} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"This is a line that wraps around\"\n    wm geom . {}\n    update\n    list [.t bbox 1.19] [.t bbox 1.20]\n} [list [list [xchar 19] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-24.18 {TkTextCharLayoutProc, -wrap word} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"xxThis is a line that wraps around\"\n    wm geom . {}\n    update\n    list [.t bbox 1.15] [.t bbox 1.16] [.t bbox 1.17] [.t bbox 1.21]\n} [list [list [xchar 15] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 16] [yline 1] [xe 16] $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 4] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-24.19 {TkTextCharLayoutProc, -wrap word} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"xxThis is a line that wraps around\"\n    wm geom . {}\n    update\n    list [.t bbox 1.14] [.t bbox 1.15] [.t bbox 1.16]\n} [list [list [xchar 14] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 15] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 16] [yline 1] [xe 16] $fixedHeight]]\ntest textDisp-24.20 {TkTextCharLayoutProc, vertical offset} {\n    .t configure -wrap none\n    .t delete 1.0 end\n    .t insert 1.0 \"Line 1\\nLine 2\\nLine 3\"\n    set result {}\n    lappend result [.t bbox 2.1] [.t dlineinfo 2.1]\n    .t tag configure up -offset 6\n    .t tag add up 2.1\n    lappend result [.t bbox 2.1] [.t dlineinfo 2.1]\n    .t tag configure up -offset -2\n    lappend result [.t bbox 2.1] [.t dlineinfo 2.1]\n    .t tag delete up\n    set result\n} [list [list [xchar 1] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [bo] [yline 2] [xw 6] $fixedHeight $fixedAscent] \\\n\t[list [xchar 1] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [bo] [yline 2] [xw 6] [expr {$fixedHeight+6}] [expr {$fixedAscent+6}]] \\\n\t[list [xchar 1] [expr {[yline 2]+2}] $fixedWidth $fixedHeight] \\\n\t[list [bo] [yline 2] [xw 6] [expr {$fixedHeight+2}] $fixedAscent]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -width 30\nupdate\n\ntest textDisp-24.21 {TkTextCharLayoutProc, word breaks} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    .t insert 1.0 \"Sample text xxxxxxx yyyyy zzzzzzz qqqqq rrrr ssss tt u vvvvv\"\n    frame .t.f -width 30 -height 20 -bg black\n    .t window create 1.36 -window .t.f\n    .t bbox 1.26\n} [list [xchar 0] [expr {[yline 2]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]\ntest textDisp-24.22 {TkTextCharLayoutProc, word breaks} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    frame .t.f -width 30 -height 20 -bg black\n    .t insert 1.0 \"Sample text xxxxxxx yyyyyyy\"\n    .t window create end -window .t.f\n    .t insert end \"zzzzzzz qqqqq rrrr ssss tt u vvvvv\"\n   .t bbox 1.28\n} [list [expr {[bo]+30}] [expr {[yline 2]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]\ntest textDisp-24.23 {TkTextCharLayoutProc, word breaks} {\n    .t configure -wrap word\n    .t delete 1.0 end\n    frame .t.f -width 50 -height 20 -bg black\n    .t insert 1.0 \"Sample text xxxxxxx yyyyyyy \"\n    .t insert end \"zzzzzzz qqqqq rrrr ssss tt\"\n    .t window create end -window .t.f\n    .t insert end \"u vvvvv\"\n    .t bbox .t.f\n} [list [xchar 0] [yline 3] 50 20]\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .t.f}\n.t configure -width 20\nupdate\n\n# Next test is currently constrained to not run on mac (aqua) because on\n# aqua it fails due to wrong implementation of tabs with right justification\n# (the text is not rendered at all). This is a bug.\ntest textDisp-24.24 {TkTextCharLayoutProc, justification and tabs} notAqua {\n    .t delete 1.0 end\n    .t tag configure x -justify center\n    .t insert 1.0 aa\\tbb\\tcc\\tdd\\t\n    .t tag add x 1.0 end\n    list [.t bbox 1.0] [.t bbox 1.10]\n} [list [list [expr {[bo]+[xe 8]/2}] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [expr {[bo]+[xe 8]/2+[xw 7]}] [yline 1] $fixedWidth $fixedHeight]]\ntest textDisp-24.25 {TkTextCharLayoutProc, justification and tabs} -setup {\n    text .tt -tabs {40 right} -wrap none -font $fixedFont\n    pack .tt\n} -body {\n    .tt insert end \\t9\\n\\t99\\n\\t999\n    update\n    set expected [list [list [expr {[bo .tt]+40-$fixedWidth}] [yline 1 .tt] $fixedWidth $fixedHeight] \\\n\t\t       [list [expr {[bo .tt]+40-$fixedWidth}] [yline 2 .tt] $fixedWidth $fixedHeight] \\\n\t\t       [list [expr {[bo .tt]+40-$fixedWidth}] [yline 3 .tt] $fixedWidth $fixedHeight]]\n    lequal [list [.tt bbox 1.1] [.tt bbox 2.2] [.tt bbox 3.3]] $expected\n} -cleanup {\n    destroy .tt\n} -result {1}\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -width 40 -bd 0 -relief flat -highlightthickness 0 \\\n    -tabs 100\nupdate\n\ntest textDisp-25.1 {CharBboxProc procedure, check tab width} {\n    .t delete 1.0 end\n    .t insert 1.0 abc\\td\\tfgh\n    list [.t bbox 1.3] [.t bbox 1.5] [.t bbox 1.6]\n} [list [list [xchar 3] [yline 1] [expr {100-3*$fixedWidth}] $fixedHeight] \\\n\t[list [expr {[bo]+100+$fixedWidth}] [yline 1] [expr {200-(100+$fixedWidth)}] $fixedHeight] \\\n\t[list [expr {[bo]+200}] [yline 1] $fixedWidth $fixedHeight]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -width 40 -bd 0 -relief flat -highlightthickness 0 -padx 0 -pady 0 \\\n\t-tabs {}\nupdate\n\ntest textDisp-26.1 {AdjustForTab procedure, no tabs} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbcdefghij\\tc\\td\n    list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.12] 0] \\\n\t    [lindex [.t bbox 1.14] 0]\n} [list [expr {[bo]+8*$fixedWidth}] \\\n\t[expr {[bo]+2*8*$fixedWidth+2*$fixedWidth}] \\\n\t[expr {[bo]+3*8*$fixedWidth}]]\ntest textDisp-26.1.2 {AdjustForTab procedure, no tabs} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbcdefghij\\tc\\td\n    .t configure -tabstyle wordprocessor\n    set res [list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.12] 0] \\\n      [lindex [.t bbox 1.14] 0]]\n    .t configure -tabstyle tabular\n    set res\n} [list [expr {[bo]+8*$fixedWidth}] \\\n\t[expr {[bo]+3*8*$fixedWidth}] \\\n\t[expr {[bo]+4*8*$fixedWidth}]]\ntest textDisp-26.2 {AdjustForTab procedure, not enough tabs specified} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tb\\tc\\td\n    .t tag delete x\n    .t tag configure x -tabs 40\n    .t tag add x 1.0 end\n    list [lindex [.t bbox 1.2] 0] [lindex [.t bbox 1.4] 0] \\\n\t    [lindex [.t bbox 1.6] 0]\n} [list 40 80 120]\ntest textDisp-26.3 {AdjustForTab procedure, not enough tabs specified} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tb\\tc\\td\\te\n    .t tag delete x\n    .t tag configure x -tabs {40 70 right}\n    .t tag add x 1.0 end\n    list [lindex [.t bbox 1.2] 0] \\\n\t    [expr {[lindex [.t bbox 1.4] 0] + [lindex [.t bbox 1.4] 2]}] \\\n\t    [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]}] \\\n\t    [expr {[lindex [.t bbox 1.8] 0] + [lindex [.t bbox 1.8] 2]}]\n} [list 40 70 100 130]\ntest textDisp-26.4 {AdjustForTab procedure, different alignments} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbc\\tde\\tfg\\thi\n    .t tag delete x\n    .t tag configure x -tabs {40 center 80 left 130 right}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    .t tag add y 1.5\n    .t tag add y 1.8\n    list [lindex [.t bbox 1.3] 0] [lindex [.t bbox 1.5] 0] \\\n\t    [lindex [.t bbox 1.10] 0]\n} [list 40 80 130]\ntest textDisp-26.5 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t1.234\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    .t tag add y 1.5\n    lindex [.t bbox 1.3] 0\n} 120\ntest textDisp-26.6 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t1,456.234\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    lindex [.t bbox 1.7] 0\n} 120\ntest textDisp-26.7 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t1.456.234,7\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    lindex [.t bbox 1.11] 0\n} 120\ntest textDisp-26.8 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\ttest\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    lindex [.t bbox 1.6] 0\n} 120\ntest textDisp-26.9 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t1234\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.2\n    lindex [.t bbox 1.6] 0\n} 120\ntest textDisp-26.10 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t1.234567\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.5\n    lindex [.t bbox 1.3] 0\n} 120\ntest textDisp-26.11 {AdjustForTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tx=1.234567\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.7\n    .t tag add y 1.9\n    lindex [.t bbox 1.5] 0\n} 120\ntest textDisp-26.12 {AdjustForTab procedure, adjusting chunks} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tx1.234567\n    .t tag delete x\n    .t tag configure x -tabs {120 numeric}\n    .t tag add x 1.0 end\n    .t tag add y 1.7\n    .t tag add y 1.9\n    button .b -text \"=\"\n    .t window create 1.3 -window .b\n    update\n    lindex [.t bbox 1.5] 0\n} 120\ntest textDisp-26.13 {AdjustForTab procedure, not enough space} {\n    .t delete 1.0 end\n    .t insert 1.0 \"abc\\txyz\\tqrs\\txyz\\t0\"\n    .t tag delete x\n    set t1 [expr {   $fixedWidth+3}]\n    set t2 [expr { 4*$fixedWidth+2}]\n    set t3 [expr { 7*$fixedWidth+1}]\n    set t4 [expr {17*$fixedWidth+1}]\n    .t tag configure x -tabs \"$t1 $t2 center $t3 right $t4\"\n    .t tag add x 1.0 end\n    set expected [list [xchar 4] [xchar 8] [xchar 12] $t4]\n    set res [list [lindex [.t bbox 1.4] 0] [lindex [.t bbox 1.8] 0] \\\n\t    [lindex [.t bbox 1.12] 0] [lindex [.t bbox 1.16] 0]]\n    lequal $res $expected\n} {1}\ntest textDisp-26.13.2 {AdjustForTab procedure, not enough space} {\n    .t delete 1.0 end\n    .t insert 1.0 \"abc\\txyz\\tqrs\\txyz\\t0\"\n    .t tag delete x\n    set t1 [expr {   $fixedWidth+3}]\n    set t2 [expr { 4*$fixedWidth+2}]\n    set t3 [expr { 7*$fixedWidth+1}]\n    set t4 [expr {17*$fixedWidth+1}]\n    .t tag configure x -tabs \"$t1 $t2 center $t3 right $t4\" -tabstyle wordprocessor\n    .t tag add x 1.0 end\n    set expected [list [xchar 4] [xchar 8] $t4 [expr {$t4+($t4-$t3)}]]\n    set res [list [lindex [.t bbox 1.4] 0] [lindex [.t bbox 1.8] 0] \\\n      [lindex [.t bbox 1.12] 0] [lindex [.t bbox 1.16] 0]]\n    .t tag configure x -tabstyle tabular\n    lequal $res $expected\n} {1}\ntest textDisp-26.14 {AdjustForTab procedure, not enough space} {\n    .t delete 1.0 end\n    .t insert end \"a \\tb \\tc \\td \\te \\tf \\tg\\n\"\n    .t insert end \"Watch the \\tX and the \\t\\t\\tY\\n\"\n    .t tag configure moop -tabs [expr {8*$fixedWidth}]\n    .t insert end \"Watch the \\tX and the \\t\\t\\tY\\n\" moop\n    list [lindex [.t bbox 2.11] 0] [lindex [.t bbox 2.24] 0] \\\n\t    [lindex [.t bbox 3.11] 0] [lindex [.t bbox 3.24] 0]\n} [list [xchar 11] [xchar 32] [xchar 11] [xchar 32]]\ntest textDisp-26.14.2 {AdjustForTab procedure, not enough space} {\n    .t delete 1.0 end\n    .t configure -tabstyle wordprocessor\n    .t insert end \"a \\tb \\tc \\td \\te \\tf \\tg\\n\"\n    .t insert end \"Watch the \\tX and the \\t\\t\\tY\\n\"\n    .t tag configure moop -tabs [expr {8*$fixedWidth}]\n    .t insert end \"Watch the \\tX and the \\t\\t\\tY\\n\" moop\n    set res [list [lindex [.t bbox 2.11] 0] [lindex [.t bbox 2.24] 0] \\\n      [lindex [.t bbox 3.11] 0] [lindex [.t bbox 3.24] 0]]\n    .t configure -tabstyle tabular\n    set res\n} [list [xchar 16] [xchar 8] [xchar 16] [xchar 8]]\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -width 20 -bd 2 -highlightthickness 2 -relief sunken -tabs {} \\\n\t-wrap char\nupdate\n\ntest textDisp-27.1 {SizeOfTab procedure, old-style tabs} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbcdefghij\\tc\\td\n    list [.t bbox 1.2] [.t bbox 1.10] [.t bbox 1.12]\n} [list [list [xchar 8] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar [expr {8+8}]] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar [expr {8+8+1+1}]] [yline 1] $fixedWidth $fixedHeight]]\ntest textDisp-27.1.1 {SizeOfTab procedure, old-style tabs} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbcdefghij\\tc\\td\n    .t configure -tabstyle wordprocessor\n    set res [list [.t bbox 1.2] [.t bbox 1.10] [.t bbox 1.12]]\n    .t configure -tabstyle tabular\n    set res\n} [list [list [xchar 8] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar [expr {8+8}]] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-27.2 {SizeOfTab procedure, choosing tabX and alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\tbcd\n    .t tag delete x\n    # compute a tab width such that the first display line is just not large enough\n    # to show the last char 'd', which then wraps on display line 2\n    set tw [expr {(20-2)*$fixedWidth-($fixedWidth-1)}]\n    .t tag configure x -tabs $tw\n    .t tag add x 1.0 end\n    set expected [list [list [expr {[bo]+$tw+[xw 1]}] [yline 1] [expr {[winfo width .t]-([bo]+$tw+[xw 1])-[bo]}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.3] [.t bbox 1.4]] $expected\n} {1}\ntest textDisp-27.3 {SizeOfTab procedure, choosing tabX and alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t\\t\\tbcd\n    .t tag delete x\n    # compute a tab width such that the first display line is just not large enough\n    # to show the last char 'd', which then wraps on display line 2\n    set tw [expr {int(ceil(((20-2)*$fixedWidth-($fixedWidth-1))/3.0))}]\n    .t tag configure x -tabs $tw\n    .t tag add x 1.0 end\n    set expected [list [list [expr {[bo]+3*$tw+[xw 1]}] [yline 1] [expr {[winfo width .t]-([bo]+3*$tw+[xw 1])-[bo]}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.5] [.t bbox 1.6]] $expected\n} {1}\ntest textDisp-27.4 {SizeOfTab procedure, choosing tabX and alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t\\t\\tbcd\n    .t tag delete x\n    # compute a tab width such that the first display line is just not large enough\n    # to show the last char 'd', which then wraps on display line 2\n    set tw [expr {int(ceil(((20-2)*$fixedWidth-($fixedWidth-1) + 20)/2.0))}]\n    .t tag configure x -tabs \"20 center $tw left\"\n    .t tag add x 1.0 end\n    set expected [list [list [expr {[bo]+$tw+($tw-20)+[xw 1]}] [yline 1] [expr {[winfo width .t]-([bo]+$tw+($tw-20)+[xw 1])-[bo]}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.5] [.t bbox 1.6]] $expected\n} {1}\ntest textDisp-27.5 {SizeOfTab procedure, center alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\txyzzyabc\n    .t tag delete x\n    # compute a tab width such that the last y on the first display line is the last displayed char\n    # while 'xyzzyabc' is centered at the tab stop; the 'abc\" part of the line wraps on display line 2\n    set tw [expr {[winfo width .t]-2*[bo]-3*$fixedWidth+1}]\n    .t tag configure x -tabs \"$tw center\"\n    .t tag add x 1.0 end\n    set expected [list [list [expr {[bo]+$tw+round(1.5*$fixedWidth)}] [yline 1] [expr {[winfo width .t]-([bo]+$tw+round(1.5*$fixedWidth))-[bo]}] $fixedHeight] \\\n\t\t       [list [xchar 0] [yline 2] $fixedWidth $fixedHeight]]\n    lequal [list [.t bbox 1.6] [.t bbox 1.7]] $expected\n} {1}\ntest textDisp-27.6 {SizeOfTab procedure, center alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\txyzzyabc\n    .t tag delete x\n    .t tag configure x -tabs \"[expr {round(21.4*$fixedWidth)}] center\"\n    .t tag add x 1.0 end\n    list [.t bbox 1.6] [.t bbox 1.7]\n} [list [list [xchar 4] [yline 2] $fixedWidth $fixedHeight] \\\n\t[list [xchar 5] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-27.7 {SizeOfTab procedure, center alignment, wrap -none (potential numerical problems)} {\n    .t delete 1.0 end\n    set cm [winfo fpixels .t 1c]\n    .t configure -tabs {1c 2c center 3c 4c 5c 6c 7c 8c} -wrap none -width 40\n    .t insert 1.0 a\\tb\\tc\\td\\te\\n012345678934567890a\\tbb\\tcc\\tdd\n    set width [expr {$fixedWidth * 19}]\n    set tab $cm\n    while {$tab < $width} {\n\tset tab [expr {$tab + $cm}]\n    }\n    # Now we've calculated to the end of the tab after 'a', add one\n    # more for 'bb\\t' and we're there, with some pixels for the border.  Since\n    # Tk_GetPixelsFromObj uses the standard 'int(0.5 + float)' rounding,\n    # so must we.\n    set tab [expr {[bo] + int(0.5 + $tab + $cm)}]\n    update\n    set res [.t bbox 2.23]\n    set expected [list [expr {[xchar 23]-$tab}] [yline 2] $fixedWidth $fixedHeight]\n    lequal [lset res 0 [expr {[lindex $res 0] - $tab}]] $expected\n} {1}\ntest textDisp-27.7.1 {SizeOfTab procedure, center alignment, wrap -none (potential numerical problems)} {\n    .t delete 1.0 end\n    .t configure -tabstyle wordprocessor\n    set cm [winfo fpixels .t 1c]\n    .t configure -tabs {1c 2c center 3c 4c 5c 6c 7c 8c} -wrap none -width 40\n    .t insert 1.0 a\\tb\\tc\\td\\te\\n012345678934567890a\\tbb\\tcc\\tdd\n    set width [expr {$fixedWidth * 19}]\n    set tab $cm\n    while {$tab < $width} {\n\tset tab [expr {$tab + $cm}]\n    }\n    # Now we've calculated to the end of the tab after 'a', add one\n    # more for 'bb\\t' and we're there, with some pixels for the border.  Since\n    # Tk_GetPixelsFromObj uses the standard 'int(0.5 + float)' rounding,\n    # so must we.\n    set tab [expr {[bo] + int(0.5 + $tab + $cm)}]\n    update\n    set res [.t bbox 2.23]\n    .t configure -tabstyle tabular\n    lset res 0 [expr {[lindex $res 0] - $tab}]\n} [list 0 [yline 2] $fixedWidth $fixedHeight]\ntest textDisp-27.7.2 {SizeOfTab procedure, fractional tab interpolation problem} {\n    .t delete 1.0 end\n    set interpolatetab {1c 2c}\n    set precisetab {}\n    for {set i 1} {$i < 20} {incr i} {\n\tlappend precisetab \"${i}c\"\n    }\n    .t configure -tabs $interpolatetab -wrap none -width 150\n    .t insert 1.0 [string repeat \"a\\t\" 20]\n    update\n    set res [.t bbox 1.20]\n    # Now, Tk's interpolated tabs should be the same as\n    # non-interpolated.\n    .t configure -tabs $precisetab\n    update\n    expr {[lindex $res 0] - [lindex [.t bbox 1.20] 0]}\n} 0\n\n#\n# COMMON TEST SETUP\n#\n\n.t configure -wrap char -tabs {} -width 20\nupdate\n\ntest textDisp-27.8 {SizeOfTab procedure, right alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t\\txyzzyabc\n    .t tag delete x\n    .t tag configure x -tabs \"[expr {14.3*$fixedWidth}] left [expr {[.t cget -width]*$fixedWidth}] right\"\n    .t tag add x 1.0 end\n    list [.t bbox 1.6] [.t bbox 1.7]\n} [list [list [xcharr 1] [yline 1] $fixedWidth $fixedHeight] \\\n\t[list [bo] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-27.9 {SizeOfTab procedure, left alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\txyzzyabc\n    .t tag delete x\n    .t tag configure x -tabs \"[expr {17.14*$fixedWidth}]\"\n    .t tag add x 1.0 end\n    list [.t bbox 1.3] [.t bbox 1.4]\n} [list [list [expr {round([bo]+17.14*$fixedWidth+$fixedWidth)}] [yline 1] [expr {[winfo width .t]-round([bo]+17.14*$fixedWidth+$fixedWidth)-[bo]}] $fixedHeight] \\\n\t[list [bo] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-27.10 {SizeOfTab procedure, numeric alignment} {\n    .t delete 1.0 end\n    .t insert 1.0 a\\t123.4\n    .t tag delete x\n    .t tag configure x -tabs \"[expr {17.14*$fixedWidth}] numeric\"\n    .t tag add x 1.0 end\n    list [.t bbox 1.3] [.t bbox 1.4]\n} [list [list [expr {round([bo]+17.14*$fixedWidth-$fixedWidth)}] [yline 1] [expr {[winfo width .t]-round([bo]+17.14*$fixedWidth-$fixedWidth)-[bo]}] $fixedHeight] \\\n\t[list [bo] [yline 2] $fixedWidth $fixedHeight]]\ntest textDisp-27.11 {SizeOfTab procedure, making tabs at least as wide as a space} {\n    .t delete 1.0 end\n    .t insert 1.0 abc\\tdefghijklmnopqrst\n    .t tag delete x\n    .t tag configure x -tabs \"[expr {17.14*$fixedWidth}]\"\n    .t tag add x 1.0 end\n    list [.t bbox 1.5] [.t bbox 1.6]\n} [list [list [expr {round([bo]+17.14*$fixedWidth+$fixedWidth)}] [yline 1] [expr {[winfo width .t]-round([bo]+17.14*$fixedWidth+$fixedWidth)-[bo]}] $fixedHeight] \\\n\t[list [bo] [yline 2] $fixedWidth $fixedHeight]]\n\ntest textDisp-28.1 {\"yview\" option with bizarre scroll command} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    text .t2.t -width 40 -height 4\n    .t2.t insert end \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n\"\n    pack .t2.t\n    wm geometry .t2 +0+0\n    update\n    .t2.t configure -yscrollcommand bizarre_scroll\n    .t2.t yview 100.0\n    set result [.t2.t index @0,0]\n    update\n    lappend result [.t2.t index @0,0]\n} -cleanup {\n    destroy .t2\n} -result {6.0 1.0}\n\ntest textDisp-29.1 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    set expected [list [list 0.0 [expr {20.0*$fixedWidth/300}]] \\\n\t\t       300x50+[bo .t2.t]+[yline 2 .t2.t] \\\n\t\t       [list [xchar 1 .t2.t] [expr {[yline 2 .t2.t]+50}] $fixedWidth $fixedHeight]]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-29.2 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    .t2.t xview scroll 1 unit\n    update\n    set expected [list [list [expr {1.0*$fixedWidth/300}] [expr {21.0*$fixedWidth/300}]] \\\n\t\t       300x50+[expr {[bo .t2.t]-$fixedWidth}]+[yline 2 .t2.t] \\\n\t\t       [list [expr {[bo .t2.t]-$fixedWidth+$fixedWidth}] [expr {[yline 2 .t2.t]+50}] $fixedWidth $fixedHeight]]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap none -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 1\\n\n    .t2.t insert end [string repeat \"abc\" 30]\n    update\n    .t2.t xview scroll 5 unit\n    update\n    .t2.t xview\n} -cleanup {\n    destroy .t2\n} -result [list [expr {5.0/90}] [expr {25.0/90}]]\ntest textDisp-29.2.2 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    .t2.t xview scroll 2 unit\n    update\n    set expected [list [list [expr {2.0*$fixedWidth/300}] [expr {22.0*$fixedWidth/300}]] \\\n\t\t       300x50+[expr {[bo .t2.t]-2*$fixedWidth}]+[yline 2 .t2.t] \\\n\t\t       {}]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    .t2.t xview scroll 7 pixels\n    update\n    set expected [list [list [expr {7.0/300}] [expr {(20.0*$fixedWidth+7)/300}]] \\\n\t\t       300x50+[expr {[bo .t2.t]-7}]+[yline 2 .t2.t] \\\n\t\t       [list [expr {[bo .t2.t]+$fixedWidth-7}] [expr {[yline 2 .t2.t]+50}] $fixedWidth $fixedHeight]]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    .t2.t xview scroll 17 pixels\n    update\n    set expected [list [list [expr {17.0/300}] [expr {(20.0*$fixedWidth+17)/300}]] \\\n\t\t       300x50+[expr {[bo .t2.t]-17}]+[yline 2 .t2.t] \\\n\t\t       {}]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-29.2.5 {miscellaneous: can show last character} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 121x141+200+200\n    text .t2.t -width 5 -height 5 -font {Arial 10} \\\n      -wrap none -xscrollcommand \".t2.s set\" \\\n      -bd 2 -highlightthickness 0 -padx 1\n    .t2.t insert end \"WWWWWWWWWWWWi\"\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    grid .t2.t -row 0 -column 0 -sticky nsew\n    grid .t2.s -row 1 -column 0 -sticky ew\n    grid columnconfigure .t2 0 -weight 1\n    grid rowconfigure .t2 0 -weight 1\n    grid rowconfigure .t2 1 -weight 0\n    update\n    set xv [.t2.t xview]\n    set xd [expr {[lindex $xv 1] - [lindex $xv 0]}]\n    .t2.t xview moveto [expr {1.0-$xd}]\n    set iWidth [lindex [.t2.t bbox end-2c] 2]\n    .t2.t xview scroll 2 units\n    set iWidth2 [lindex [.t2.t bbox end-2c] 2]\n    if {($iWidth == $iWidth2) && $iWidth >= 2} {\n\tset result \"correct\"\n    } else {\n\tset result \"last character is not completely visible when it should be\"\n    }\n} -cleanup {\n    destroy .t2\n} -result {correct}\ntest textDisp-29.3 {miscellaneous: lines wrap but are still too long} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    wm geometry .t2 +0+0\n    text .t2.t -width 20 -height 10 -font $fixedFont \\\n\t    -wrap char -xscrollcommand \".t2.s set\"\n    pack .t2.t -side top\n    scrollbar .t2.s -orient horizontal -command \".t2.t xview\"\n    pack .t2.s -side bottom -fill x\n    .t2.t insert end 123\n    frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised\n    .t2.t window create 1.1 -window .t2.t.f\n    update\n    .t2.t xview scroll 200 units\n    update\n    set expected [list [list [expr {double(300-20*$fixedWidth)/300}] 1.0] \\\n\t\t       300x50+[expr {-(300-20*$fixedWidth-[bo .t2.t])}]+[yline 2 .t2.t] \\\n\t\t       {}]\n    lequal [list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]] $expected\n} -cleanup {\n    destroy .t2\n} -result {1}\n\ntest textDisp-30.1 {elided text joining multiple logical lines} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    text .t2.t -width 20 -height 10 -font $fixedFont\n    pack .t2.t -side top\n    .t2.t delete 1.0 end\n    .t2.t insert 1.0 \"1111\\n2222\\n3333\"\n    .t2.t tag configure elided -elide 1 -background red\n    .t2.t tag add elided 1.2 3.2\n    update\n    .t2.t count -update -displaylines 1.0 end\n} -cleanup {\n    destroy .t2\n} -result {1}\ntest textDisp-30.2 {elided text joining multiple logical lines} -setup {\n    catch {destroy .t2}\n} -body {\n    toplevel .t2\n    text .t2.t -width 20 -height 10 -font $fixedFont\n    pack .t2.t -side top\n    .t2.t delete 1.0 end\n    .t2.t insert 1.0 \"1111\\n2222\\n3333\"\n    .t2.t tag configure elided -elide 1 -background red\n    .t2.t tag add elided 1.2 2.2\n    update\n    .t2.t count -update -displaylines 1.0 end\n} -cleanup {\n    destroy .t2\n} -result {2}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .t2}\n.t configure -height 1\nupdate\n\ntest textDisp-31.1 {line embedded window height update} {\n    set res {}\n    .t delete 1.0 end\n    .t insert end \"abcd\\nefgh\\nijkl\\nmnop\\nqrst\\nuvwx\\nyx\"\n    frame .t.f -background red -width 50 -height 100\n    .t window create 3.0 -window .t.f\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t.f configure -height 10\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*6}] \\\n\t[expr {$fixedHeight*7}]]\ntest textDisp-31.2 {line update index shifting} {\n    set res {}\n    .t.f configure -height 100\n    update\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t.f configure -height 10\n    .t insert 1.0 \"abc\\n\"\n    .t insert 1.0 \"abc\\n\"\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t.f configure -height 100\n    .t delete 1.0 3.0\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*8}] \\\n\t[expr {$fixedHeight*9}] \\\n\t[expr {$fixedHeight*7}] \\\n\t[expr {100+$fixedHeight*6}]]\ntest textDisp-31.3 {line update index shifting} {\n    # Should do exactly the same as the above, as long\n    # as we are correctly tagging the correct lines for\n    # recalculation.  The 'update' and 'delay' must be\n    # long enough to ensure all asynchronous updates\n    # have been performed.\n    set res {}\n    .t.f configure -height 100\n    update\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t.f configure -height 10\n    .t insert 1.0 \"abc\\n\"\n    .t insert 1.0 \"abc\\n\"\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    .t.f configure -height 100\n    .t delete 1.0 3.0\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    set res\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*8}] \\\n\t[expr {$fixedHeight*9}] \\\n\t[expr {$fixedHeight*7}] \\\n\t[expr {100+$fixedHeight*6}]]\ntest textDisp-31.4 {line embedded image height update} {\n    set res {}\n    image create photo textest -height 100 -width 10\n    .t delete 3.0\n    .t image create 3.0 -image textest\n    update\n    lappend res [.t count -update -ypixels 1.0 end]\n    textest configure -height 10\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n    set res\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*6}] \\\n\t[expr {$fixedHeight*7}]]\ntest textDisp-31.5 {line update index shifting} {\n    set res {}\n    textest configure -height 100\n    update\n    lappend res [.t count -update -ypixels 1.0 end]\n    textest configure -height 10\n    .t insert 1.0 \"abc\\n\"\n    .t insert 1.0 \"abc\\n\"\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n    textest configure -height 100\n    .t delete 1.0 3.0\n    lappend res [.t count -ypixels 1.0 end]\n    lappend res [.t count -update -ypixels 1.0 end]\n    set res\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*8}] \\\n\t[expr {$fixedHeight*9}] \\\n\t[expr {$fixedHeight*7}] \\\n\t[expr {100+$fixedHeight*6}]]\ntest textDisp-31.6 {line update index shifting} {\n    # Should do exactly the same as the above, as long\n    # as we are correctly tagging the correct lines for\n    # recalculation.  The 'update' and 'delay' must be\n    # long enough to ensure all asynchronous updates\n    # have been performed.\n    set res {}\n    textest configure -height 100\n    lappend res [.t count -update -ypixels 1.0 end]\n    textest configure -height 10\n    .t insert 1.0 \"abc\\n\"\n    .t insert 1.0 \"abc\\n\"\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    textest configure -height 100\n    .t delete 1.0 3.0\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    set res\n} [list [expr {100+$fixedHeight*6}] \\\n\t[expr {100+$fixedHeight*8}] \\\n\t[expr {$fixedHeight*9}] \\\n\t[expr {$fixedHeight*7}] \\\n\t[expr {100+$fixedHeight*6}]]\ntest textDisp-31.7 {line update index shifting, elided} {\n    # The 'update' and 'delay' must be long enough to ensure all\n    # asynchronous updates have been performed.\n    set res {}\n    .t delete 1.0 end\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t insert 1.0 \"abc\\nabc\"\n    .t insert 1.0 \"abc\\n\"\n    lappend res [.t count -update -ypixels 1.0 end]\n    .t tag configure elide -elide 1\n    .t tag add elide 1.3 2.1\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    .t delete 1.0 3.0\n    lappend res [.t count -ypixels 1.0 end]\n    delay\n    lappend res [.t count -ypixels 1.0 end]\n    set res\n} [list [expr {$fixedHeight*1}] \\\n\t[expr {$fixedHeight*3}] \\\n\t[expr {$fixedHeight*3}] \\\n\t[expr {$fixedHeight*2}] \\\n\t[expr {$fixedHeight*1}] \\\n\t[expr {$fixedHeight*1}]]\n\ntest textDisp-32.0 {everything elided} {\n    # Must not crash\n    pack [text .tt]\n    .tt insert 0.0 HELLO\n    .tt tag configure HIDE -elide 1\n    .tt tag add HIDE 0.0 end\n    update\n    destroy .tt\n} {}\ntest textDisp-32.1 {everything elided} {\n    # Must not crash\n    pack [text .tt]\n    update\n    .tt insert 0.0 HELLO\n    update\n    .tt tag configure HIDE -elide 1\n    update\n    .tt tag add HIDE 0.0 end\n    update\n    destroy .tt\n} {}\ntest textDisp-32.2 {elide and tags} {\n    pack [text .tt -height 30 -width 100 -bd 0 \\\n      -highlightthickness 0 -padx 0]\n    .tt insert end \\\n      {test text using tags 1 and 3 } \\\n      {testtag1 testtag3} \\\n      {[this bit here uses tags 2 and 3]} \\\n      {testtag2 testtag3}\n    update\n    # indent left margin of tag 1 by 20 pixels\n    # text should be indented\n    .tt tag configure testtag1 -lmargin1 20\n    update\n    #1\n    set res {}\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    # hide tag 1, remaining text should not be indented, since\n    # the indented tag and character is hidden.\n    .tt tag configure testtag1 -elide 1\n    update\n    #2\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    # reset\n    .tt tag configure testtag1 -lmargin1 0\n    .tt tag configure testtag1 -elide 0\n    # indent left margin of tag 2 by 20 pixels\n    # text should not be indented, since tag1 has lmargin1 of 0.\n    .tt tag configure testtag2 -lmargin1 20\n    update\n    #3\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    # hide tag 1, remaining text should now be indented, but\n    # the bbox of 1.0 should have zero width and zero indent,\n    # since it is elided at that position.\n    .tt tag configure testtag1 -elide 1\n    update\n    #4\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    # reset\n    .tt tag configure testtag2 -lmargin1 {}\n    .tt tag configure testtag1 -elide 0\n    # indent left margin of tag 3 by 20 pixels\n    # text should be indented, since this tag takes\n    # precedence over testtag1, and is applied to the\n    # start of the text.\n    .tt tag configure testtag3 -lmargin1 20\n    update\n    #5\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    # hide tag 1, remaining text should still be indented,\n    # since it still has testtag3 on it.  Again the\n    # bbox of 1.0 should have 0.\n    .tt tag configure testtag1 -elide 1\n    update\n    #6\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    .tt tag configure testtag3 -lmargin1 {} -elide 0\n    .tt tag configure testtag1 -elide 1 -lmargin1 20\n    #7\n    lappend res [list [.tt index \"1.0 + 0 displaychars\"] \\\n      [lindex [.tt bbox 1.0] 0] \\\n      [lindex [.tt bbox \"1.0 + 0 displaychars\"] 0]]\n    destroy .tt\n    set res\n} {{1.0 20 20} {1.29 0 0} {1.0 0 0} {1.29 0 20}\\\n  {1.0 20 20} {1.29 0 20} {1.0 20 20}}\ntest textDisp-32.3 \"NULL undisplayProc problems: #1791052\" -setup {\n    set img [image create photo -data {\n\tR0lGODlhEgASANUAAAAAAP/////iHP/mIPrWDPraEP/eGPfOAPbKAPbOBPrS\n\tCP/aFPbGAPLCAPLGAN62ANauAMylAPbCAPW/APK+AN6uALKNAPK2APK5ANal\n\tAOyzArGHBZp3B+6uAHFVBFVACO6qAOqqAOalAMGMAbF+Am1QBG5QBeuiAOad\n\tAM6NAJ9vBW1MBFlACFQ9CVlBCuaZAOKVANyVAZlpBMyFAKZtBJVhBEAUEP//\n\t/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADcALAAAAAASABIAAAa+\n\twJtw+Ckah0iiZwNhODKk0icp/HAShEKBoEBgVFOkK0Iw2GyCs+BAGbGIlrIt\n\tEJjXBYgL6X3zJMx1Z2d3EyEmNx9xaYGCdwgaNEUPBYt0do4XKUUOlAOCnmcD\n\tCwcXMZsEAgOqq6oLBY+mHxUKBqysCwQSIDNFJAidtgKjFyeRfRQHB2ipAmZs\n\tIDArVSTIyoI2bB0oxkIsIxcNyeIXICh7SR8yIhoXFxogJzE1YegrNCkoLzM0\n\tK/RUiEY+tKASBAA7\n    }]\n    destroy .tt\n} -body {\n    text .tt\n    .tt tag configure emoticon -elide 1\n    .tt insert end X\n    .tt mark set MSGLEFT \"end - 1 char\"\n    .tt mark gravity MSGLEFT left\n    .tt insert end \":)\" emoticon\n    .tt image create end -image $img\n    pack .tt\n    update\n} -cleanup {\n    image delete $img\n    destroy .tt\n}\ntest textDisp-32.4 {Button-1 click with elided lines - Bug 18371b7ce7} -setup {\n    pack [text .tt -borderwidth 0 -highlightthickness 0]\n    for {set n 1} {$n <= 5} {incr n} {\n\t.tt insert end \"Line $n\\n\"\n    }\n    .tt tag configure Elided -elide 1\n    .tt tag add Elided 1.2 4.0\n    update\n} -body {\n    event generate .tt <Button-1> -x 1 -y 1\n    .tt index insert\n} -cleanup {\n    destroy .tt\n} -result {1.0}\n\ntest textDisp-33.0 {one line longer than fits in the widget} {\n    pack [text .tt -wrap char]\n    update\n    .tt insert 1.0 [string repeat \"more wrap + \" 300]\n    update\n    .tt see 1.0\n    lindex [.tt yview] 0\n} {0.0}\ntest textDisp-33.1 {one line longer than fits in the widget} {\n    destroy .tt\n    pack [text .tt -wrap char]\n    update\n    .tt insert 1.0 [string repeat \"more wrap + \" 300]\n    update\n    .tt yview \"1.0 +1 displaylines\"\n    update\n    if {[lindex [.tt yview] 0] > 0.1} {\n\tset result \"window should be scrolled to the top\"\n    } else {\n\tset result \"ok\"\n    }\n} {ok}\ntest textDisp-33.2 {one line longer than fits in the widget} {\n    destroy .tt\n    pack [text .tt -wrap char]\n    .tt debug 1\n    update\n    set tk_textHeightCalc \"\"\n    set timer [after 200 lappend tk_textHeightCalc \"Timed out\"]\n    .tt insert 1.0 [string repeat \"more wrap + \" 1]\n    vwait tk_textHeightCalc\n    after cancel $timer\n    set tk_textHeightCalc\n} {1.0}\ntest textDisp-33.3 {one line longer than fits in the widget} {\n    destroy .tt\n    pack [text .tt -wrap char]\n    set tk_textHeightCalc \"\"\n    .tt insert 1.0 [string repeat \"more wrap + \" 300]\n    update\n    .tt sync\n    # Each line should have been recalculated just once\n    expr {[llength $tk_textHeightCalc] == [.tt count -displaylines 1.0 end]}\n} 1\ntest textDisp-33.4 {one line longer than fits in the widget} {\n    destroy .tt\n    pack [text .tt -wrap char]\n    .tt insert 1.0 [string repeat \"more wrap + \" 300]\n    update\n    set idx [.tt index \"1.0 + 1 displaylines\"]\n    .tt yview $idx\n    if {[lindex [.tt yview] 0] > 0.1} {\n\tset result \"window should be scrolled to the top\"\n    } else {\n\tset result \"ok\"\n    }\n    set idx [.tt index \"1.0 + 1 displaylines\"]\n    set result\n} {ok}\ntest textDisp-33.5 {bold or italic fonts} win {\n    destroy .tt\n    pack [text .tt -wrap char -font {{MS Sans Serif} 15}]\n    font create no -family [lindex [.tt cget -font] 0] -size 24\n    font create bi -family [lindex [.tt cget -font] 0] -size 24\n    font configure bi -weight bold -slant italic\n    .tt tag configure bi -font bi\n    .tt tag configure no -font no\n    .tt insert end abcd no efgh bi ijkl\\n no\n    update\n    set bb {}\n    for {set i 0} {$i < 12} {incr i 4} {\n\tlappend bb [lindex [.tt bbox 1.$i] 0]\n    }\n    foreach {a b c} $bb {}\n    unset bb\n    if {($b - $a) * 1.5 < ($c - $b)} {\n\tset result \"italic font has much too much space\"\n    } else {\n\tset result \"italic font measurement ok\"\n    }\n} {italic font measurement ok}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .tt\n\ntest textDisp-34.1 {Line heights recalculation problem: bug 2677890} -setup {\n    pack [text .t1] -expand 1 -fill both\n    set txt \"\"\n    for {set i 1} {$i < 100} {incr i} {\n\tappend txt \"Line $i\\n\"\n    }\n    set result {}\n} -body {\n    .t1 insert end $txt\n    set ge [winfo geometry .]\n    scan $ge \"%dx%d+%d+%d\" width height left top\n    update\n    .t1 sync\n    set negative 0\n    bind .t1 <<WidgetViewSync>> { if {%d < 0} {set negative 1} }\n    # Without the fix for bug 2677890, changing the width of the toplevel\n    # will launch recomputation of the line heights, but will produce negative\n    # number of still remaining outdated lines, which is obviously wrong.\n    # Thus we use this way to check for regression regarding bug 2677890,\n    # i.e. to check that the fix for this bug really is still in.\n    wm geometry . \"[expr {$width * 2}]x$height+$left+$top\"\n    update\n    .t1 sync\n    set negative\n} -cleanup {\n    destroy .t1\n} -result 0\n\ntest textDisp-35.1 {Init value of charHeight - Dancing scrollbar bug 1499165} -setup {\n    pack [text .t1] -fill both -expand y -side left\n    # We don't want debug for this test case, because it takes some hours\n    # if valgrind check is fully enabled. In this test case only the scrollbar\n    # behavior is relevant, all other involved functions (insert, see, ...) are\n    # already tested with debug mode in other test cases.\n    .t debug off\n    .t insert end \"[string repeat a\\nb\\nc\\n 500000]THE END\\n\"\n    set res {}\n} -body {\n    .t see 10000.0\n    after 300 {set fr1 [.t yview] ; set done 1}\n    vwait done\n    after 300 {set fr2 [.t yview] ; set done 1}\n    vwait done\n    lappend res [expr {[lindex $fr1 0] == [lindex $fr2 0]}]\n    lappend res [expr {[lindex $fr1 1] == [lindex $fr2 1]}]\n} -cleanup {\n    .t debug on ;# re-enable debugging\n    destroy .t1\n} -result {1 1}\n\ntest textDisp-36.1 {Display bug with 'yview insert'} -constraints {knownBug} -setup {\n   text .t1 -font $fixedFont -width 20 -height 3 -wrap word\n   pack .t1\n   .t1 delete 1.0 end\n   .t1 tag configure elide -elide 1\n   .t1 insert end \"Line 1\\nThis line is wrapping around two times.\"\n} -body {\n   .t1 tag add elide 1.3 2.0\n   .t1 yview insert\n   update\n   # wish now panics: \"CalculateDisplayLineHeight called with bad indexPtr\"\n   .t1 yview scroll -1 pixels\n} -cleanup {\n    destroy .t1\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget scroll text\ndeleteWindows\noption clear\ncleanupTests\n"
  },
  {
    "path": "tests/textImage.test",
    "content": "# textImage.test -- test images embedded in text widgets\n#\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n\n# One time setup.  Create a font to insure the tests are font metric invariant.\ndestroy .t\nfont create test_font -family courier -size 14\ntext .t -font test_font\ndestroy .t\n\n#\n# TESTS\n#\n\ntest textImage-1.1 {basic argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t image option ?arg ...?\"}\n\ntest textImage-1.2 {basic argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image c\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {ambiguous option \"c\": must be cget, configure, create, or names}\n\ntest textImage-1.3 {cget argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image cget\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t image cget index option\"}\n\ntest textImage-1.4 {cget argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image cget blurf -flurp\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"blurf\"}\n\ntest textImage-1.5 {cget argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image cget 1.1 -flurp\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {no embedded image at index \"1.1\"}\n\ntest textImage-1.6 {configure argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image configure\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t image configure index ?-option value ...?\"}\n\ntest textImage-1.7 {configure argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image configure blurf\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"blurf\"}\n\ntest textImage-1.8 {configure argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image configure 1.1\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {no embedded image at index \"1.1\"}\n\ntest textImage-1.9 {create argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t image create index ?-option value ...?\"}\n\ntest textImage-1.10 {create argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create blurf\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad text index \"blurf\"}\n\ntest textImage-1.11 {basic argument checking} -setup {\n    destroy .t\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create 1000.1000 -image small\n} -cleanup {\n    destroy .t\n    image delete small\n} -returnCodes ok -result {small}\n\ntest textImage-1.12 {names argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image names dates places\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {wrong # args: should be \".t image names\"}\n\n\ntest textImage-1.13 {names argument checking} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    lappend result [.t image names]\n    .t image create insert -image small\n    lappend result [.t image names]\n    .t image create insert -image small\n    lappend result [lsort [.t image names]]\n    .t image create insert -image small -name little\n    lappend result [lsort [.t image names]]\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {{} small {small small#1} {little small small#1}}\n\ntest textImage-1.14 {basic argument checking} -setup {\n    destroy .t\n} -body {\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image huh\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad option \"huh\": must be cget, configure, create, or names}\n\ntest textImage-1.15 {align argument checking} -setup {\n    destroy .t\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image small -align wrong\n} -cleanup {\n    destroy .t\n    image delete small\n} -returnCodes error -result {bad align \"wrong\": must be baseline, bottom, center, or top}\n\ntest textImage-1.16 {configure} -setup {\n    destroy .t\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image small\n    .t image configure small\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {{-align {} {} center center} {-padx {} {} 0 {}} {-pady {} {} 0 {}} {-image {} {} {} small} {-name {} {} {} {}}}\n\ntest textImage-1.17 {basic cget options} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image small\n    foreach i {align padx pady image name} {\n\tlappend result $i:[.t image cget small -$i]\n    }\n    return $result\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {align:center padx: pady: image:small name:}\n\ntest textImage-1.18 {basic configure options} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n\timage create photo large -width 50 -height 50\n\tlarge put green -to 0 0 50 50\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image small\n    foreach {option value}  {align top padx 5 pady 7 image large name none} {\n\t.t image configure small -$option $value\n    }\n    update\n    .t image configure small\n} -cleanup {\n    destroy .t\n    image delete small large\n} -result {{-align {} {} center top} {-padx {} {} 0 5} {-pady {} {} 0 7} {-image {} {} {} large} {-name {} {} {} none}}\n\ntest textImage-1.19 {basic image naming} -setup {\n    destroy .t\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image small\n    .t image create end -image small -name small\n    .t image create end -image small -name small#6342\n    .t image create end -image small -name small\n    lsort [.t image names]\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {small small#1 small#2 small#6342}\n\ntest textImage-2.1 {debug} -setup {\n    destroy .t\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t debug 1\n    .t insert end front\n    .t image create end -image small\n    .t insert end back\n    .t delete small\n    .t image names\n    .t debug 0\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {}\n\n\ntest textImage-3.1 {image change propagation} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo vary -width 5 -height 5\n\tvary put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image vary -align top\n    update\n    lappend result base:[.t bbox vary]\n    foreach i {10 20 40} {\n\tvary configure -width $i -height $i\n\tupdate\n\tlappend result $i:[.t bbox vary]\n    }\n    return $result\n} -cleanup {\n    destroy .t\n    image delete vary\n} -result {{base:0 0 5 5} {10:0 0 10 10} {20:0 0 20 20} {40:0 0 40 40}}\n\ntest textImage-3.2 {delayed image management, see also bug 1591493} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -name test\n    update\n    foreach {x1 y1 w1 h1} [.t bbox test] {}\n    lappend result [list $x1 $w1 $h1]\n    .t image configure test -image small -align top\n    update\n    foreach {x2 y2 w2 h2} [.t bbox test] {}\n    lappend result [list [expr {$x1==$x2}] [expr {$w2>0}] [expr {$h2>0}]]\n} -cleanup {\n    destroy .t\n    image delete small\n} -result {{0 0 0} {1 1 1}}\n\n\n# some temporary random tests\n\ntest textImage-4.1 {alignment checking - except baseline} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n\timage create photo large -width 50 -height 50\n\tlarge put green -to 0 0 50 50\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image large\n    .t image create end -image small\n    .t insert end test\n    update\n    lappend result default:[.t bbox small]\n    foreach i {top bottom center} {\n\t.t image configure small -align $i\n\tupdate\n\tlappend result [.t image cget small -align]:[.t bbox small]\n    }\n    return $result\n} -cleanup {\n    destroy .t\n    image delete small large\n} -result {{default:50 22 5 5} {top:50 0 5 5} {bottom:50 45 5 5} {center:50 22 5 5}}\n\ntest textImage-4.2 {alignment checking - baseline} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n\timage create photo large -width 50 -height 50\n\tlarge put green -to 0 0 50 50\n    }\n    font create test_font2 -size 5\n    text .t -font test_font2 -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image large\n    .t image create end -image small -align baseline\n    .t insert end test\n    update\n    # Sizes larger than 25 can be too big and lead to a negative 'norm',\n    # at least on Windows XP with certain settings.\n    foreach size {10 15 20 25} {\n\tfont configure test_font2 -size $size\n\tarray set Metrics [font metrics test_font2]\n\tupdate  ; # services the idle \"TheWorldHasChanged\" event, queues \"TkWorldChanged\" events\n\tupdate  ; # services the queued \"TkWorldChanged\" events\n\tforeach {x y w h} [.t bbox small] {}\n\tset norm [expr {\n\t\t(([image height large] - $Metrics(-linespace))/2\n\t\t+ $Metrics(-ascent) - [image height small] - $y)\n\t}]\n\tlappend result \"$size $norm\"\n    }\n    return $result\n} -cleanup {\n    destroy .t\n    image delete small large\n    font delete test_font2\n    unset Metrics\n} -result {{10 0} {15 0} {20 0} {25 0}}\n\ntest textImage-4.3 {alignment and padding checking} -constraints {\n    fonts\n} -setup {\n    destroy .t\n    set result \"\"\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n\timage create photo large -width 50 -height 50\n\tlarge put green -to 0 0 50 50\n    }\n    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0\n    pack .t\n    .t image create end -image large\n    .t image create end -image small -padx 5 -pady 10\n    .t insert end test\n    update\n    lappend result default:[.t bbox small]\n    foreach i {top bottom center baseline} {\n\t.t image configure small -align $i\n\tupdate\n\tlappend result $i:[.t bbox small]\n    }\n    return $result\n} -cleanup {\n    destroy .t\n    image delete small large\n} -result {{default:55 22 5 5} {top:55 10 5 5} {bottom:55 35 5 5} {center:55 22 5 5} {baseline:55 22 5 5}}\n\n\ntest textImage-5.1 {peer widget images} -setup {\n    destroy .t .tt\n} -body {\n    catch {\n\timage create photo small -width 5 -height 5\n\tsmall put red -to 0 0 4 4\n\timage create photo large -width 50 -height 50\n\tlarge put green -to 0 0 50 50\n    }\n    pack [text .t]\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t image create end -image large\n    .t image create end -image small -padx 5 -pady 10\n    .t insert end test\n    update\n    destroy .t .tt\n} -cleanup {\n    image delete small large\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .t\nfont delete test_font\nimageFinish\ntestutils forget image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/textIndex.test",
    "content": "# This file is a Tcl script to test the code in the file tkTextIndex.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import text\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc getword index {\n    .t get [.t index \"$index wordstart\"] [.t index \"$index wordend\"]\n}\n\nproc text_test_word {startend chars start} {\n    destroy .t\n    text .t\n    .t insert end $chars\n    if {[regexp {end} $start]} {\n\tset start [.t index \"${start}chars -2c\"]\n    } else {\n\tset start [.t index \"1.0 + ${start}chars\"]\n    }\n    if {[.t compare $start >= \"end-1c\"]} {\n\tset start \"end-2c\"\n    }\n    set res [.t index \"$start $startend\"]\n    .t count 1.0 $res\n}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .t}\ntext .t -font {Courier -12} -width 20 -height 10\npack .t -expand 1 -fill both\nupdate\n.t debug on\nwm geometry . {}\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\n\n.t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nb乏y GIrl .#@? x_yz\n!@#$%\nLine 7\"\n\nimage create photo textimage -width 10 -height 10\ntextimage put red -to 0 0 9 9\n\n#\n# TESTS\n#\n\ntest textIndex-1.1 {TkTextMakeByteIndex} {testtext} {\n    # (lineIndex < 0)\n    testtext .t byteindex -1 3\n} {1.0 0}\ntest textIndex-1.2 {TkTextMakeByteIndex} {testtext} {\n    # (lineIndex < 0), because lineIndex == strtol(argv[2]) - 1\n    testtext .t byteindex 0 3\n} {1.0 0}\ntest textIndex-1.3 {TkTextMakeByteIndex} {testtext} {\n    # not (lineIndex < 0)\n    testtext .t byteindex 1 3\n} {1.3 3}\ntest textIndex-1.4 {TkTextMakeByteIndex} {testtext} {\n    # (byteIndex < 0)\n    testtext .t byteindex 3 -1\n} {3.0 0}\ntest textIndex-1.5 {TkTextMakeByteIndex} {testtext} {\n    # not (byteIndex < 0)\n    testtext .t byteindex 3 3\n} {3.3 3}\ntest textIndex-1.6 {TkTextMakeByteIndex} {testtext} {\n    # (indexPtr->linePtr == NULL)\n    testtext .t byteindex 9 2\n} {8.0 0}\ntest textIndex-1.7 {TkTextMakeByteIndex} {testtext} {\n    # not (indexPtr->linePtr == NULL)\n    testtext .t byteindex 7 2\n} {7.2 2}\ntest textIndex-1.8 {TkTextMakeByteIndex: shortcut for 0} {testtext} {\n    # (byteIndex == 0)\n    testtext .t byteindex 1 0\n} {1.0 0}\ntest textIndex-1.9 {TkTextMakeByteIndex: shortcut for 0} {testtext} {\n    # not (byteIndex == 0)\n    testtext .t byteindex 3 80\n} {3.5 5}\ntest textIndex-1.10 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # one segment\n\n    testtext .t byteindex 3 5\n} {3.5 5}\ntest textIndex-1.11 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    #     index += segPtr->size\n    # Multiple segments, make sure add segment size to index.\n\n    .t mark set foo 3.2\n    set x [testtext .t byteindex 3 7]\n    .t mark unset foo\n    set x\n} {3.5 5}\ntest textIndex-1.12 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # (segPtr == NULL)\n    testtext .t byteindex 3 7\n} {3.5 5}\ntest textIndex-1.13 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # not (segPtr == NULL)\n    testtext .t byteindex 3 4\n} {3.4 4}\ntest textIndex-1.14 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # (index + segPtr->size > byteIndex)\n    # in this segment.\n\n    testtext .t byteindex 3 4\n} {3.4 4}\ntest textIndex-1.15 {TkTextMakeByteIndex: verify index is in range} {testtext} {\n    # (index + segPtr->size > byteIndex), index != 0\n    # in this segment.\n\n    .t mark set foo 3.2\n    set x [testtext .t byteindex 3 4]\n    .t mark unset foo\n    set x\n} {3.4 4}\ntest textIndex-1.16 {TkTextMakeByteIndex: UTF-8 characters} {testtext} {\n    testtext .t byteindex 5 100\n} {5.18 20}\ntest textIndex-1.17 {TkTextMakeByteIndex: prevent splitting UTF-8 character} \\\n\t{testtext} {\n    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType))\n    # Wrong answer would be ¹ (the 2nd byte of UTF rep of 0x4e4f).\n\n    set x [testtext .t byteindex 5 2]\n    list $x [.t get insert]\n} {{5.2 4} y}\ntest textIndex-1.18 {TkTextMakeByteIndex: prevent splitting UTF-8 character} \\\n\t{testtext} {\n    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType))\n    testtext .t byteindex 5 1\n    .t get insert\n} \"乏\"\n\ntest textIndex-2.1 {TkTextMakeCharIndex} {\n    # (lineIndex < 0)\n    .t index -1.3\n} 1.0\ntest textIndex-2.2 {TkTextMakeCharIndex} {\n    # (lineIndex < 0), because lineIndex == strtol(argv[2]) - 1\n    .t index 0.3\n} 1.0\ntest textIndex-2.3 {TkTextMakeCharIndex} {\n    # not (lineIndex < 0)\n    .t index 1.3\n} 1.3\ntest textIndex-2.4 {TkTextMakeCharIndex} {\n    # (charIndex < 0)\n    .t index 3.-1\n} 3.0\ntest textIndex-2.5 {TkTextMakeCharIndex} {\n    # (charIndex < 0)\n    .t index 3.3\n} 3.3\ntest textIndex-2.6 {TkTextMakeCharIndex} {\n    # (indexPtr->linePtr == NULL)\n    .t index 9.2\n} 8.0\ntest textIndex-2.7 {TkTextMakeCharIndex} {\n    # not (indexPtr->linePtr == NULL)\n    .t index 7.2\n} 7.2\ntest textIndex-2.8 {TkTextMakeCharIndex: verify index is in range} {\n    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # one segment\n\n    .t index 3.5\n} 3.5\ntest textIndex-2.9 {TkTextMakeCharIndex: verify index is in range} {\n    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # Multiple segments, make sure add segment size to index.\n\n    .t mark set foo 3.2\n    set x [.t index 3.7]\n    .t mark unset foo\n    set x\n} 3.5\ntest textIndex-2.10 {TkTextMakeCharIndex: verify index is in range} {\n    # (segPtr == NULL)\n    .t index 3.7\n} 3.5\ntest textIndex-2.11 {TkTextMakeCharIndex: verify index is in range} {\n    # not (segPtr == NULL)\n    .t index 3.4\n} 3.4\ntest textIndex-2.12 {TkTextMakeCharIndex: verify index is in range} {\n    # (segPtr->typePtr == &tkTextCharType)\n    # Wrong answer would be ¹ (the 2nd byte of UTF rep of 0x4e4f).\n\n    .t mark set insert 5.2\n    .t get insert\n} y\ntest textIndex-2.13 {TkTextMakeCharIndex: verify index is in range} {\n    # not (segPtr->typePtr == &tkTextCharType)\n\n    .t image create 5.2 -image textimage\n    .t mark set insert 5.5\n    set x [.t get insert]\n    .t delete 5.2\n    set x\n} \"G\"\ntest textIndex-2.14 {TkTextMakeCharIndex: verify index is in range} {\n    # (charIndex < segPtr->size)\n\n    .t image create 5.0 -image textimage\n    set x [.t index 5.0]\n    .t delete 5.0\n    set x\n} 5.0\n\n#\n# COMMON TEST SETUP\n#\n\n.t mark set foo 3.2\n.t tag add x 2.8 2.11\n.t tag add x 6.0 6.2\nset weirdTag \"funny . +- 22.1\\n\\t{\"\n.t tag add $weirdTag 2.1  2.6\nset weirdMark \"asdf \\n{-+ 66.2\\t\"\n.t mark set $weirdMark 4.0\n.t tag config y -relief raised\nset weirdImage \"foo-1\"\n.t image create 2.1 -image [image create photo $weirdImage]\nset weirdEmbWin \".t.bar-1\"\nentry $weirdEmbWin\n.t window create 3.1 -window $weirdEmbWin\n\ntest textIndex-3.1 {TkTextGetIndex, weird mark names} {\n    list [catch {.t index $weirdMark} msg] $msg\n} {0 4.0}\ntest textIndex-3.2 {TkTextGetIndex, weird mark names} knownBug {\n    list [catch {.t index \"$weirdMark -1char\"} msg] $msg\n} {0 4.0}\ntest textIndex-3.3 {TkTextGetIndex, weird embedded window names} {\n    list [catch {.t index $weirdEmbWin} msg] $msg\n} {0 3.1}\ntest textIndex-3.4 {TkTextGetIndex, weird embedded window names} knownBug {\n    list [catch {.t index \"$weirdEmbWin -1char\"} msg] $msg\n} {0 3.0}\ntest textIndex-3.5 {TkTextGetIndex, weird image names} {\n    list [catch {.t index $weirdImage} msg] $msg\n} {0 2.1}\ntest textIndex-3.6 {TkTextGetIndex, weird image names} knownBug {\n    list [catch {.t index \"$weirdImage -1char\"} msg] $msg\n} {0 2.0}\n\n#\n# COMMON TEST CLEANUP\n#\n.t delete 3.1  ; # remove the weirdEmbWin\n.t delete 2.1  ; # remove the weirdImage\n\ntest textIndex-4.1 {TkTextGetIndex, tags} {\n    list [catch {.t index x.first} msg] $msg\n} {0 2.8}\ntest textIndex-4.2 {TkTextGetIndex, tags} {\n    list [catch {.t index x.last} msg] $msg\n} {0 6.2}\ntest textIndex-4.3 {TkTextGetIndex, weird tags} {\n    list [.t index $weirdTag.first+1c] [.t index $weirdTag.last+2c]\n} {2.2 2.8}\ntest textIndex-4.4 {TkTextGetIndex, tags} {\n    list [catch {.t index x.gorp} msg] $msg\n} {1 {bad text index \"x.gorp\"}}\ntest textIndex-4.5 {TkTextGetIndex, tags} {\n    list [catch {.t index foo.last} msg] $msg\n} {1 {bad text index \"foo.last\"}}\ntest textIndex-4.6 {TkTextGetIndex, tags} {\n    list [catch {.t index y.first} msg] $msg\n} {1 {text doesn't contain any characters tagged with \"y\"}}\ntest textIndex-4.7 {TkTextGetIndex, tags} {\n    list [catch {.t index x.last,} msg] $msg\n} {1 {bad text index \"x.last,\"}}\ntest textIndex-4.8 {TkTextGetIndex, tags} {\n    .t tag add z 1.0\n    set result [list [.t index z.first] [.t index z.last]]\n    .t tag delete z\n    set result\n} {1.0 1.1}\n\ntest textIndex-5.1 {TkTextGetIndex, \"@\"} {fonts} {\n    .t index @12,9\n} 1.1\ntest textIndex-5.2 {TkTextGetIndex, \"@\"} {fonts} {\n    .t index @-2,7\n} 1.0\ntest textIndex-5.3 {TkTextGetIndex, \"@\"} {fonts} {\n    .t index @10,-7\n} 1.0\ntest textIndex-5.4 {TkTextGetIndex, \"@\"} {fonts} {\n    list [catch {.t index @x} msg] $msg\n} {1 {bad text index \"@x\"}}\ntest textIndex-5.5 {TkTextGetIndex, \"@\"} {fonts} {\n    list [catch {.t index @10q} msg] $msg\n} {1 {bad text index \"@10q\"}}\ntest textIndex-5.6 {TkTextGetIndex, \"@\"} {fonts} {\n    list [catch {.t index @10,} msg] $msg\n} {1 {bad text index \"@10,\"}}\ntest textIndex-5.7 {TkTextGetIndex, \"@\"} {fonts} {\n    list [catch {.t index @10,a} msg] $msg\n} {1 {bad text index \"@10,a\"}}\ntest textIndex-5.8 {TkTextGetIndex, \"@\"} {fonts} {\n    list [catch {.t index @10,9,} msg] $msg\n} {1 {bad text index \"@10,9,\"}}\n\ntest textIndex-6.1 {TkTextGetIndex, numeric} {\n    list [catch {.t index 2.3} msg] $msg\n} {0 2.3}\ntest textIndex-6.2 {TkTextGetIndex, numeric} {\n    list [catch {.t index -} msg] $msg\n} {1 {bad text index \"-\"}}\ntest textIndex-6.3 {TkTextGetIndex, numeric} {\n    list [catch {.t index 2.end} msg] $msg\n} {0 2.13}\ntest textIndex-6.4 {TkTextGetIndex, numeric} {\n    list [catch {.t index 2.x} msg] $msg\n} {1 {bad text index \"2.x\"}}\ntest textIndex-6.5 {TkTextGetIndex, numeric} {\n    list [catch {.t index 2.3x} msg] $msg\n} {1 {bad text index \"2.3x\"}}\n\ntest textIndex-7.1 {TkTextGetIndex, miscellaneous other bases} {\n    list [catch {.t index end} msg] $msg\n} {0 8.0}\ntest textIndex-7.2 {TkTextGetIndex, miscellaneous other bases} {\n    list [catch {.t index foo} msg] $msg\n} {0 3.2}\ntest textIndex-7.3 {TkTextGetIndex, miscellaneous other bases} {\n    list [catch {.t index foo+1c} msg] $msg\n} {0 3.3}\n\ntest textIndex-8.1 {TkTextGetIndex, modifiers} {\n    list [catch {.t index 2.1+1char} msg] $msg\n} {0 2.2}\ntest textIndex-8.2 {TkTextGetIndex, modifiers} {\n    list [catch {.t index \"2.1  \t+1char\"} msg] $msg\n} {0 2.2}\ntest textIndex-8.3 {TkTextGetIndex, modifiers} {\n    list [catch {.t index 2.1-1char} msg] $msg\n} {0 2.0}\ntest textIndex-8.4 {TkTextGetIndex, modifiers} {\n    list [catch {.t index {2.1  }} msg] $msg\n} {0 2.1}\ntest textIndex-8.5 {TkTextGetIndex, modifiers} {\n    list [catch {.t index {2.1+foo bar}} msg] $msg\n} {1 {bad text index \"2.1+foo bar\"}}\ntest textIndex-8.6 {TkTextGetIndex, modifiers} {\n    list [catch {.t index {2.1 foo bar}} msg] $msg\n} {1 {bad text index \"2.1 foo bar\"}}\n\ntest textIndex-9.1 {TkTextIndexCmp} {\n    list [.t compare 3.1 < 3.2] [.t compare 3.1 == 3.2]\n} {1 0}\ntest textIndex-9.2 {TkTextIndexCmp} {\n    list [.t compare 3.2 < 3.2] [.t compare 3.2 == 3.2]\n} {0 1}\ntest textIndex-9.3 {TkTextIndexCmp} {\n    list [.t compare 3.3 < 3.2] [.t compare 3.3 == 3.2]\n} {0 0}\ntest textIndex-9.4 {TkTextIndexCmp} {\n    list [.t compare 2.1 < 3.2] [.t compare 2.1 == 3.2]\n} {1 0}\ntest textIndex-9.5 {TkTextIndexCmp} {\n    list [.t compare 4.1 < 3.2] [.t compare 4.1 == 3.2]\n} {0 0}\n\ntest textIndex-10.1 {ForwBack} {\n    list [catch {.t index {2.3 + x}} msg] $msg\n} {1 {bad text index \"2.3 + x\"}}\ntest textIndex-10.2 {ForwBack} {\n    list [catch {.t index {2.3 + 2 chars}} msg] $msg\n} {0 2.5}\ntest textIndex-10.3 {ForwBack} {\n    list [catch {.t index {2.3 + 2c}} msg] $msg\n} {0 2.5}\ntest textIndex-10.4 {ForwBack} {\n    list [catch {.t index {2.3 - 3ch}} msg] $msg\n} {0 2.0}\ntest textIndex-10.5 {ForwBack} {\n    list [catch {.t index {1.3 + 3 lines}} msg] $msg\n} {0 4.3}\ntest textIndex-10.6 {ForwBack} {\n    list [catch {.t index {2.3 -1l}} msg] $msg\n} {0 1.3}\ntest textIndex-10.7 {ForwBack} {\n    list [catch {.t index {2.3 -1 gorp}} msg] $msg\n} {1 {bad text index \"2.3 -1 gorp\"}}\ntest textIndex-10.8 {ForwBack} {\n    list [catch {.t index {2.3 - 4 lines}} msg] $msg\n} {0 1.3}\ntest textIndex-10.9 {ForwBack} {\n    .t mark set insert 2.0\n    list [catch {.t index {insert -0 chars}} msg] $msg\n} {0 2.0}\ntest textIndex-10.10 {ForwBack} {\n    .t mark set insert 2.end\n    list [catch {.t index {insert +0 chars}} msg] $msg\n} {0 2.13}\n\ntest textIndex-11.1 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 -7\n} {1.3 3}\ntest textIndex-11.2 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 5\n} {2.8 8}\ntest textIndex-11.3 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 10\n} {2.13 13}\ntest textIndex-11.4 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 11\n} {3.0 0}\ntest textIndex-11.5 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 57\n} {7.6 6}\ntest textIndex-11.6 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 58\n} {8.0 0}\ntest textIndex-11.7 {TkTextIndexForwBytes} {testtext} {\n    testtext .t forwbytes 2.3 59\n} {8.0 0}\n\ntest textIndex-12.1 {TkTextIndexForwChars} {\n    # (charCount < 0)\n    .t index {2.3 + -7 chars}\n} 1.3\ntest textIndex-12.2 {TkTextIndexForwChars} {\n    # not (charCount < 0)\n    .t index {2.3 + 5 chars}\n} 2.8\ntest textIndex-12.3 {TkTextIndexForwChars: find index} {\n    # for ( ; segPtr != NULL; segPtr = segPtr->nextPtr)\n    # one loop\n    .t index {2.3 + 9 chars}\n} 2.12\ntest textIndex-12.4 {TkTextIndexForwChars: find index} {\n    # for ( ; segPtr != NULL; segPtr = segPtr->nextPtr)\n    # multiple loops\n    .t mark set foo 2.5\n    set x [.t index {2.3 + 9 chars}]\n    .t mark unset foo\n    set x\n} 2.12\ntest textIndex-12.5 {TkTextIndexForwChars: find index} {\n    # for ( ; segPtr != NULL; segPtr = segPtr->nextPtr)\n    # border condition: last char\n\n    .t index {2.3 + 10 chars}\n} 2.13\ntest textIndex-12.6 {TkTextIndexForwChars: find index} {\n    # for ( ; segPtr != NULL; segPtr = segPtr->nextPtr)\n    # border condition: segPtr == NULL -> beginning of next line\n\n    .t index {2.3 + 11 chars}\n} 3.0\ntest textIndex-12.7 {TkTextIndexForwChars: find index} {\n    # (segPtr->typePtr == &tkTextCharType)\n    .t index {2.3 + 2 chars}\n} 2.5\ntest textIndex-12.8 {TkTextIndexForwChars: find index} {\n    # (charCount == 0)\n    # No more chars, so we found byte offset.\n\n    .t index {2.3 + 2 chars}\n} 2.5\ntest textIndex-12.9 {TkTextIndexForwChars: find index} {\n    # not (segPtr->typePtr == &tkTextCharType)\n\n    .t image create 2.4 -image textimage\n    set x [.t get {2.3 + 3 chars}]\n    .t delete 2.4\n    set x\n} \"f\"\ntest textIndex-12.10 {TkTextIndexForwChars: find index} {\n    # dstPtr->byteIndex += segPtr->size - byteOffset\n    # When moving to next segment, account for bytes in last segment.\n    # Wrong answer would be 2.4\n\n    .t mark set foo 2.4\n    set x [.t index {2.3 + 5 chars}]\n    .t mark unset foo\n    set x\n} 2.8\ntest textIndex-12.11 {TkTextIndexForwChars: go to next line} {\n    # (linePtr == NULL)\n    .t index {7.6 + 3 chars}\n} 8.0\ntest textIndex-12.12 {TkTextIndexForwChars: go to next line} {\n    # Reset byteIndex to 0 now that we are on a new line.\n    # Wrong answer would be 2.9\n    .t index {1.3 + 6 chars}\n} 2.2\ntest textIndex-12.13 {TkTextIndexForwChars} {\n    # right to end\n    .t index {2.3 + 56 chars}\n} 8.0\ntest textIndex-12.14 {TkTextIndexForwChars} {\n    # try to go past end\n    .t index {2.3 + 57 chars}\n} 8.0\n\ntest textIndex-13.1 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 -10\n} {4.6 6}\ntest textIndex-13.2 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 2\n} {3.0 0}\ntest textIndex-13.3 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 3\n} {2.13 13}\ntest textIndex-13.4 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 22\n} {1.1 1}\ntest textIndex-13.5 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 23\n} {1.0 0}\ntest textIndex-13.6 {TkTextIndexBackBytes} {testtext} {\n    testtext .t backbytes 3.2 24\n} {1.0 0}\n\ntest textIndex-14.1 {TkTextIndexBackChars} {\n    # (charCount < 0)\n    .t index {3.2 - -10 chars}\n} 4.6\ntest textIndex-14.2 {TkTextIndexBackChars} {\n    # not (charCount < 0)\n    .t index {3.2 - 2 chars}\n} 3.0\ntest textIndex-14.3 {TkTextIndexBackChars: find starting segment} {\n    # for (segPtr = dstPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # single loop\n\n    .t index {3.2 - 3 chars}\n} 2.13\ntest textIndex-14.4 {TkTextIndexBackChars: find starting segment} {\n    # for (segPtr = dstPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # multiple loop\n\n    .t mark set foo1 2.5\n    .t mark set foo2 2.7\n    .t mark set foo3 2.10\n    set x [.t index {2.9 - 1 chars}]\n    .t mark unset foo1 foo2 foo3\n    set x\n} 2.8\ntest textIndex-14.5 {TkTextIndexBackChars: find starting seg and offset} {\n    # for (segPtr = dstPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)\n    # Make sure segSize was decremented.  Wrong answer would be 2.10\n\n    .t mark set foo 2.2\n    set x [.t index {2.9 - 1 char}]\n    .t mark unset foo\n    set x\n} 2.8\ntest textIndex-14.6 {TkTextIndexBackChars: back over characters} {\n    # (segPtr->typePtr == &tkTextCharType)\n\n    .t index {3.2 - 22 chars}\n} 1.1\ntest textIndex-14.7 {TkTextIndexBackChars: loop backwards over chars} {\n    # (charCount == 0)\n    # No more chars, so we found byte offset.\n\n    .t index {3.4 - 2 chars}\n} 3.2\ntest textIndex-14.8 {TkTextIndexBackChars: loop backwards over chars} {\n    # (p == start)\n    # Still more chars, but we reached beginning of segment\n\n    .t image create 5.6 -image textimage\n    set x [.t index {5.8 - 3 chars}]\n    .t delete 5.6\n    set x\n} 5.5\ntest textIndex-14.9 {TkTextIndexBackChars: back over image} {\n    # not (segPtr->typePtr == &tkTextCharType)\n\n    .t image create 5.6 -image textimage\n    set x [.t get {5.8 - 4 chars}]\n    .t delete 5.6\n    set x\n} \"G\"\ntest textIndex-14.10 {TkTextIndexBackChars: move to previous segment} {\n    # (segPtr != oldPtr)\n    # More segments to go\n\n    .t mark set foo 3.4\n    set x [.t index {3.5 - 2 chars}]\n    .t mark unset foo\n    set x\n} 3.3\ntest textIndex-14.11 {TkTextIndexBackChars: move to previous segment} {\n    # not (segPtr != oldPtr)\n    # At beginning of line.\n\n    .t mark set foo 3.4\n    set x [.t index {3.5 - 10 chars}]\n    .t mark unset foo\n    set x\n} 2.9\ntest textIndex-14.12 {TkTextIndexBackChars: move to previous line} {\n    # (lineIndex == 0)\n    .t index {1.5 - 10 chars}\n} 1.0\ntest textIndex-14.13 {TkTextIndexBackChars: move to previous line} {\n    # not (lineIndex == 0)\n    .t index {2.5 - 10 chars}\n} 1.2\ntest textIndex-14.14 {TkTextIndexBackChars: move to previous line} {\n    # for (segPtr = oldPtr; segPtr != NULL; segPtr = segPtr->nextPtr)\n    # Set byteIndex to end of previous line so we can subtract more\n    # bytes from it.  Otherwise we get an TkTextIndex with a negative\n    # byteIndex.\n\n    .t index {2.5 - 6 chars}\n} 1.6\ntest textIndex-14.15 {TkTextIndexBackChars: UTF} {\n    .t get {5.3 - 1 chars}\n} y\ntest textIndex-14.16 {TkTextIndexBackChars: UTF} {\n    .t get {5.3 - 2 chars}\n} 乏\ntest textIndex-14.17 {TkTextIndexBackChars: UTF} {\n    .t get {5.3 - 3 chars}\n} b\n\ntest textIndex-15.1 {StartEnd} {\n    list [catch {.t index {2.3 lineend}} msg] $msg\n} {0 2.13}\ntest textIndex-15.2 {StartEnd} {\n    list [catch {.t index {2.3 linee}} msg] $msg\n} {0 2.13}\ntest textIndex-15.3 {StartEnd} {\n    list [catch {.t index {2.3 line}} msg] $msg\n} {1 {bad text index \"2.3 line\"}}\ntest textIndex-15.4 {StartEnd} {\n    list [catch {.t index {2.3 linestart}} msg] $msg\n} {0 2.0}\ntest textIndex-15.5 {StartEnd} {\n    list [catch {.t index {2.3 lines}} msg] $msg\n} {0 2.0}\ntest textIndex-15.6 {StartEnd} {\n    getword 5.3\n} { }\ntest textIndex-15.7 {StartEnd} {\n    getword 5.4\n} GIrl\ntest textIndex-15.8 {StartEnd} {\n    getword 5.7\n} GIrl\ntest textIndex-15.9 {StartEnd} {\n    getword 5.8\n} { }\ntest textIndex-15.10 {StartEnd} {\n    getword 5.14\n} x_yz\ntest textIndex-15.11 {StartEnd} {\n    getword 6.2\n} #\ntest textIndex-15.12 {StartEnd} {\n    getword 3.4\n} 12345\ntest textIndex-15.13 {StartEnd} {\n    list [catch {.t index {2.2 worde}} msg] $msg\n} {0 2.13}\ntest textIndex-15.14 {StartEnd} {\n    list [catch {.t index {2.12 words}} msg] $msg\n} {0 2.0}\ntest textIndex-15.15 {StartEnd} {\n    list [catch {.t index {2.12 word}} msg] $msg\n} {1 {bad text index \"2.12 word\"}}\n\ntest textIndex-16.1 {TkTextPrintIndex} {\n    set t [text .t2]\n    $t insert end \\n\n    $t window create end -window [button $t.b]\n    set result [$t index end-2c]\n    pack $t\n    catch {destroy $t}\n} 0\n\ntest textIndex-16.2 {TkTextPrintIndex} {\n    set t [text .t2]\n    $t insert end \\n\n    $t window create end -window [button $t.b]\n    set result [$t tag add {} end-2c]\n    pack $t\n    catch {destroy $t}\n} 0\n\ntest textIndex-17.1 {Object indices} {\n    set res {}\n    set t [text .t2 -height 20]\n    for {set i 0} {$i < 100} {incr i} {\n\t$t insert end $i\\n\n    }\n    pack $t\n    update\n    set idx @0,0\n    lappend res $idx [$t index $idx]\n    $t yview scroll 2 pages\n    lappend res $idx [$t index $idx]\n    catch {destroy $t}\n    unset i\n    unset idx\n    list $res\n} {{@0,0 1.0 @0,0 37.0}}\n\ntest textIndex-18.1 {Object indices don't cache mark names} {\n    set res {}\n    text .t2\n    .t2 insert 1.0 1234\\n1234\\n1234\n    set pos \"insert\"\n    lappend res [.t2 index $pos]\n    .t2 mark set $pos 3.0\n    lappend res [.t2 index $pos]\n    .t2 mark set $pos 1.0\n    lappend res [.t2 index $pos]\n    catch {destroy .t2}\n    set res\n} {3.4 3.0 1.0}\n\n#\n# COMMON TEST SETUP\n#\n\nframe .f -width 100 -height 20\npack .f -side left\n\nset varFont {Times -14}\nset bigFont {Helvetica -24}\ndestroy .t\ntext .t -font $fixedFont -width 20 -height 10 -wrap char\npack .t -expand 1 -fill both\n.t tag configure big -font $bigFont\n.t debug on\nwm geometry . {}\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\nupdate\n\n# Some window managers (like olwm under SunOS 4.1.3) misbehave in a way\n# that tends to march windows off the top and left of the screen.  If\n# this happens, some tests will fail because parts of the window will\n# not need to be displayed (because they're off-screen).  To keep this\n# from happening, move the window if it's getting near the left or top\n# edges of the screen.\n\nif {([winfo rooty .] < 50) || ([winfo rootx .] < 50)} {\n    wm geom . +50+50\n}\n\nset str [string repeat \"hello \" 20]\n\n.t insert end \"$str one two three four five six seven height nine ten\\n\"\n.t insert end \"$str one two three four five six seven height nine ten\\n\"\n.t insert end \"$str one two three four five six seven height nine ten\\n\"\nupdate\n\ntest textIndex-19.1 {Display lines} {\n    .t index \"2.7 displaylinestart\"\n} {2.0}\n\ntest textIndex-19.2 {Display lines} {\n    .t index \"2.7 displaylineend\"\n} {2.19}\n\ntest textIndex-19.3 {Display lines} {\n    .t index \"2.30 displaylinestart\"\n} {2.20}\n\ntest textIndex-19.4 {Display lines} {\n    .t index \"2.30 displaylineend\"\n} {2.39}\n\ntest textIndex-19.5 {Display lines} {\n    .t index \"2.40 displaylinestart\"\n} {2.40}\n\ntest textIndex-19.6 {Display lines} {\n    .t index \"2.40 displaylineend\"\n} {2.59}\n\ntest textIndex-19.7 {Display lines} {\n    .t index \"2.7 +1displaylines\"\n} {2.27}\n\ntest textIndex-19.8 {Display lines} {\n    .t index \"2.7 -1displaylines\"\n} {1.167}\n\ntest textIndex-19.9 {Display lines} {\n    .t index \"2.30 +1displaylines\"\n} {2.50}\n\ntest textIndex-19.10 {Display lines} {\n    .t index \"2.30 -1displaylines\"\n} {2.10}\n\ntest textIndex-19.11 {Display lines} {\n    .t index \"2.40 +1displaylines\"\n} {2.60}\n\ntest textIndex-19.12 {Display lines} {\n    .t index \"2.40 -1displaylines\"\n} {2.20}\n\ntest textIndex-19.12.1 {Display lines} {\n    .t index \"2.50 - 100 displaylines\"\n} {1.0}\n\ntest textIndex-19.12.2 {Display lines} {\n    .t compare [.t index \"2.50 + 100 displaylines\"] == \"end - 1 c\"\n} 1\n\ntest textIndex-19.13 {Display lines} {\n    destroy {*}[pack content .]\n    text .txt -height 1 -wrap word -yscroll \".sbar set\" -width 400\n    scrollbar .sbar -command \".txt yview\"\n    grid .txt .sbar -sticky news\n    grid configure .sbar -sticky ns\n    grid rowconfigure    . 0 -weight 1\n    grid columnconfigure . 0 -weight 1\n    .txt configure -width 10\n    .txt tag config STAMP -elide 1\n    .txt tag config NICK-tick -elide 0\n    .txt insert end \"+++++ Loading History ++++++++++++++++\\n\"\n    .txt mark set HISTORY {2.0 - 1 line}\n    .txt insert HISTORY {\t} STAMP\n    .txt insert HISTORY {tick\t} {NICK NICK-tick}\n    .txt insert HISTORY \"\\n\" {NICK NICK-tick}\n    .txt insert HISTORY {[23:51]\t} STAMP\n    .txt insert HISTORY \"\\n\" {NICK NICK-tick}\n    # Must not crash\n    .txt index \"2.0 - 2 display lines\"\n    destroy .txt .sbar\n} {}\n\ntest textIndex-19.14 {Display lines with elided lines} {\n    catch {destroy .t}\n    pack [text .t]\n    for {set n 1} {$n <= 1000} {incr n} {\n\t.t insert end \"Line $n\\n\"\n    }\n    .t tag configure Elided -elide 1\n    .t tag add Elided 6.0 951.0\n    update\n    set res [.t index \"951.0 + 1 displaylines\"]\n} {952.0}\n\n# Following tests copied from tests from string wordstart/end in Tcl\n\ntest textIndex-21.4 {text index wordend} {\n    text_test_word wordend abc. -1\n} 3\ntest textIndex-21.5 {text index wordend} {\n    text_test_word wordend abc. 100\n} 4\ntest textIndex-21.6 {text index wordend} {\n    text_test_word wordend \"word_one two three\" 2\n} 8\ntest textIndex-21.7 {text index wordend} {\n    text_test_word wordend \"one .&# three\" 5\n} 6\ntest textIndex-21.8 {text index wordend} {\n    text_test_word worde \"x.y\" 0\n} 1\ntest textIndex-21.9 {text index wordend} {\n    text_test_word worde \"x.y\" end-1\n} 2\ntest textIndex-21.10 {text index wordend, unicode} {\n    text_test_word wordend \"xyzÇde fg\" 0\n} 6\ntest textIndex-21.11 {text index wordend, unicode} {\n    text_test_word wordend \"xyz윀de fg\" 0\n} 6\ntest textIndex-21.12 {text index wordend, unicode} {\n    text_test_word wordend \"xyz‿de fg\" 0\n} 6\ntest textIndex-21.13 {text index wordend, unicode} {\n    text_test_word wordend \"xyz⁅de fg\" 0\n} 3\ntest textIndex-21.14 {text index wordend, unicode} {\n    text_test_word wordend \"윀윀 abc\" 8\n} 6\n\ntest textIndex-22.5 {text index wordstart} {\n    text_test_word wordstart \"one two three_words\" 400\n} 8\ntest textIndex-22.6 {text index wordstart} {\n    text_test_word wordstart \"one two three_words\" 2\n} 0\ntest textIndex-22.7 {text index wordstart} {\n    text_test_word wordstart \"one two three_words\" -2\n} 0\ntest textIndex-22.8 {text index wordstart} {\n    text_test_word wordstart \"one .*&^ three\" 6\n} 6\ntest textIndex-22.9 {text index wordstart} {\n    text_test_word wordstart \"one two three\" 4\n} 4\ntest textIndex-22.10 {text index wordstart} {\n    text_test_word wordstart \"one two three\" end-5\n} 7\ntest textIndex-22.11 {text index wordstart, unicode} {\n    text_test_word wordstart \"one twÇo three\" 7\n} 4\ntest textIndex-22.12 {text index wordstart, unicode} {\n    text_test_word wordstart \"ab윀윀 cdef ghi\" 12\n} 10\ntest textIndex-22.13 {text index wordstart, unicode} {\n    text_test_word wordstart \"윀윀 abc\" 8\n} 3\ntest textIndex-22.14 {text index wordstart, unicode, start index at internal segment start} {\n    catch {destroy .t}\n    text .t\n    .t insert end \"C'est du texte en français\\n\"\n    .t insert end \"Это текст на русском\"\n    .t mark set insert 1.23\n    set res [.t index \"1.23 wordstart\"]\n    .t mark set insert 2.16\n    lappend res [.t index \"2.16 wordstart\"] [.t index \"2.15 wordstart\"]\n} {1.18 2.13 2.13}\ntest textIndex-22.15 {text index display wordstart} {\n    catch {destroy .t}\n    text .t\n    .t index \"1.0 display wordstart\"  ; # used to crash\n} 1.0\ntest textIndex-22.16 {text index wordstart, bug [57b821d2db]} {\n    catch {destroy .t}\n    text .t\n    .t insert 1.0 \" 123 5 789012  LINE-1\\n\\n 123 5 789000 LINE-3\\n\\n0123 5 789012  LINE-5\"\n    set res [.t index \"1.1 wordstart\"]\n    lappend res [.t index \"5.0 wordstart\"]\n    .t mark set insert 1.1\n    lappend res [.t index \"insert wordstart\"]\n    lappend res [.t index \"5.1 wordstart\"]\n} {1.1 5.0 1.1 5.0}\n\ntest textIndex-23.1 {text paragraph start} {\n    pack [text .t2]\n    .t2 insert end \" Text\"\n    set res 2.0\n    for {set i 0} {$i < 2} {incr i} {\n\tlappend res [::tk::TextPrevPara .t2 [lindex $res end]]\n    }\n    destroy .t2\n    set res\n} {2.0 1.1 1.1}\n\ntest textIndex-24.1 {text mark prev} {\n    pack [text .t2]\n    .t2 insert end [string repeat \"1 2 3 4 5 6 7 8 9 0\\n\" 12]\n    .t2 mark set 1.0 10.0\n    update\n    # then this crash Tk:\n    set res [.t2 mark previous 10.10]\n    destroy .t2\n    set res\n} {1.0}\n\ntest textIndex-25.1 {IndexCountBytesOrdered, bug [3f1f79abcf]} {\n    pack [text .t2]\n    .t2 tag configure elided -elide 1\n    .t2 insert end \"01\\n02\\n03\\n04\\n05\\n06\\n07\\n08\\n09\\n10\\n\"\n    .t2 insert end \"11\\n12\\n13\\n14\\n15\\n16\\n17\\n18\\n19\\n20\\n\"\n    .t2 insert end \"21\\n22\\n23\\n25\\n26\\n27\\n28\\n29\\n30\\n31\"\n    .t2 insert end \"32\\n33\\n34\\n36\\n37\\n38\\n39\" elided\n    # then this used to crash Tk:\n    .t2 see end\n    focus -force .t2   ; # to see the cursor blink\n    destroy .t2\n} {}\n\ntest textIndex-26.1 {GetIndex restricts the returned index to -startline/-endline in peers, bug [34db75c0ac]} {\n    set res {}\n    pack [text .t2]\n    .t2 insert end \"line 1\\nline 2\\nline 3\\nline 4\\nline 5\\nline 6\\n\"\n    pack [.t2 peer create .p2 -startline 2 -endline 3]\n    lappend res [.p2 index \"end\"]\n    lappend res [.p2 index \"end lineend\"]\n    lappend res [.p2 index \"end display lineend\"]\n    destroy .t2 .p2\n    set res\n} {2.0 2.0 2.0}\ntest textIndex-26.2 {GetIndex errors out if mark, image, window, or tag is outside peer -startline/-endline, bug [34db75c0ac]} {\n    set res {}\n    pack [text .t2]\n    .t2 insert end \"line 1\\nline 2\\nline 3\\nline 4\\nline 5\\nline 6\\n\"\n    pack [.t2 peer create .p2 -startline 2 -endline 3]\n    .p2 configure -startline 3 -endline {}\n    .t2 mark set mymark 1.0\n    catch {.p2 index mymark} msg\n    lappend res [.t2 index mymark] $msg\n    image create photo redsquare -width 5 -height 5\n    redsquare put red -to 0 0 4 4\n    .t2 image create 1.0 -image redsquare\n    catch {.p2 index redsquare} msg\n    lappend res [.t2 index redsquare] $msg\n    frame .f -width 10 -height 10 -bg blue\n    .t2 window create 1.2 -window .f\n    catch {.p2 index .f} msg\n    lappend res [.t2 index .f] $msg\n    .t2 tag add mytag 1.3\n    catch {.p2 index mytag.first} msg\n    lappend res [.t2 index mytag.first] $msg\n    destroy .t2 .p2\n    set res\n} {1.0 {bad text index \"mymark\"} 1.0 {bad text index \"redsquare\"} 1.2\\\n   {bad text index \".f\"} 1.3 {text doesn't contain any characters tagged with \"mytag\"}}\n\n#\n# TESTFILE CLEANUP\n#\n\nrename textimage {}\ncatch {destroy .t}\ntestutils forget text\ncleanupTests\n"
  },
  {
    "path": "tests/textMark.test",
    "content": "# This file is a Tcl script to test the code in the file tkTextMark.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ntext .t -width 20 -height 10\npack .t -expand 1 -fill both\nupdate\n.t debug on\nwm geometry . {}\nentry .t.e\n.t peer create .pt\n\n.t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n\n# The statements below reset the main window; it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\n\f\n#\n# TESTS\n#\n\ntest textMark-1.1 {TkTextMarkCmd - missing option} -returnCodes error -body {\n    .t mark\n} -result {wrong # args: should be \".t mark option ?arg ...?\"}\ntest textMark-1.2 {TkTextMarkCmd - bogus option} -returnCodes error -body {\n    .t mark gorp\n} -match glob -result {bad mark option \"gorp\": must be *}\ntest textMark-1.3 {TkTextMarkCmd - \"gravity\" option} -returnCodes error -body {\n    .t mark gravity foo\n} -result {there is no mark named \"foo\"}\ntest textMark-1.4 {TkTextMarkCmd - \"gravity\" option} -body {\n    .t mark set x 1.3\n    .t insert 1.3 x\n    list [.t mark gravity x] [.t index x]\n} -result {right 1.4}\ntest textMark-1.5 {TkTextMarkCmd - \"gravity\" option} -body {\n    .t mark set x 1.3\n    .t mark gr x left\n    .t insert 1.3 x\n    list [.t mark gravity x] [.t index x]\n} -result {left 1.3}\ntest textMark-1.6 {TkTextMarkCmd - \"gravity\" option} -body {\n    .t mark set x 1.3\n    .t mark gravity x right\n    .t insert 1.3 x\n    list [.t mark gravity x] [.t index x]\n} -result {right 1.4}\ntest textMark-1.7 {TkTextMarkCmd - \"gravity\" option} -returnCodes error -body {\n    .t mark set x 1.3\n    .t mark gravity x gorp\n} -result {bad mark gravity \"gorp\": must be left or right}\ntest textMark-1.8 {TkTextMarkCmd - \"gravity\" option} -returnCodes error -body {\n    .t mark gravity\n} -result {wrong # args: should be \".t mark gravity markName ?gravity?\"}\n\ntest textMark-2.1 {TkTextMarkCmd - \"names\" option} -body {\n    .t mark names 2\n} -returnCodes error -result {wrong # args: should be \".t mark names\"}\ntest textMark-2.2 {TkTextMarkCmd - \"names\" option} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    lsort [.t mark na]\n} -result {current insert}\ntest textMark-2.3 {TkTextMarkCmd - \"names\" option} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set a 1.1\n    .t mark set \"b c\" 2.3\n    lsort [.t mark names]\n} -result {a {b c} current insert}\n\ntest textMark-3.1 {TkTextMarkCmd - \"set\" option} -returnCodes error -body {\n    .t mark set a\n} -result {wrong # args: should be \".t mark set markName index\"}\ntest textMark-3.2 {TkTextMarkCmd - \"set\" option} -returnCodes error -body {\n    .t mark s a b c\n} -result {wrong # args: should be \".t mark set markName index\"}\ntest textMark-3.3 {TkTextMarkCmd - \"set\" option} -body {\n    .t mark set a @x\n} -returnCodes error -result {bad text index \"@x\"}\ntest textMark-3.4 {TkTextMarkCmd - \"set\" option} -body {\n    .t mark set a 1.2\n    .t index a\n} -result 1.2\ntest textMark-3.5 {TkTextMarkCmd - \"set\" option} -body {\n    .t mark set a end\n    .t index a\n} -result {8.0}\n\ntest textMark-4.1 {TkTextMarkCmd - \"unset\" option} -body {\n    .t mark unset\n} -result {}\ntest textMark-4.2 {TkTextMarkCmd - \"unset\" option} -body {\n    .t mark set a 1.2\n    .t mark set b 2.3\n    .t mark unset a b\n    .t index a\n} -returnCodes error -result {bad text index \"a\"}\ntest textMark-4.2.1 {TkTextMarkCmd - \"unset\" option} -body {\n    .t mark set a 1.2\n    .t mark set b 2.3\n    .t mark unset a b\n    .t index b\n} -returnCodes error -result {bad text index \"b\"}\ntest textMark-4.3 {TkTextMarkCmd - \"unset\" option} -body {\n    .t mark set a 1.2\n    .t mark set b 2.3\n    .t mark set 49ers 3.1\n    .t mark unset {*}[.t mark names]\n    lsort [.t mark names]\n} -result {current insert}\n\ntest textMark-5.1 {TkTextMarkCmd - miscellaneous} -returnCodes error -body {\n    .t mark\n} -result {wrong # args: should be \".t mark option ?arg ...?\"}\ntest textMark-5.2 {TkTextMarkCmd - miscellaneous} -returnCodes error -body {\n    .t mark foo\n} -result {bad mark option \"foo\": must be gravity, names, next, previous, set, or unset}\n\ntest textMark-6.1 {TkTextMarkSegToIndex} -body {\n    .t mark set a 1.2\n    .t mark set b 1.2\n    .t mark set c 1.2\n    .t mark set d 1.4\n    list [.t index a] [.t index b] [.t index c ] [.t index d]\n} -result {1.2 1.2 1.2 1.4}\ntest textMark-6.2 {TkTextMarkNameToIndex, with mark outside -startline/-endline range - bug 1630271} -body {\n  .t mark set insert 1.0\n  .t configure -startline 2\n  set res [list [.t index insert] [.t index insert-1c] [.t get insert]]\n  .t mark set insert end\n  .t configure -endline 4\n  lappend res [.t index insert]\n} -cleanup {\n  .t configure -startline {} -endline {}\n} -result {1.0 1.0 a 2.5}\ntest textMark-6.3 {TkTextMarkNameToIndex, with mark outside -startline/-endline range - bug 1630271} -body {\n  .t mark set mymark 1.0\n  .t configure -startline 2\n  list [catch {.t index mymark} msg] $msg\n} -cleanup {\n  .t configure -startline {} -endline {}\n  .t mark unset mymark\n} -result {1 {bad text index \"mymark\"}}\ntest textMark-6.4 {TkTextMarkNameToIndex, with mark outside -startline/-endline range - bug 1630271} -body {\n  .t mark set mymark 1.0\n  .t configure -startline 2\n  set res [list [catch {.t index mymark} msg] $msg]\n  lappend res [.pt index mymark]\n  .t configure -startline {}\n  .pt configure -startline 4\n  lappend res [.t index mymark]\n  lappend res [catch {.pt index mymark} msg] $msg\n  lappend res [.t get mymark]\n  lappend res [catch {.pt get mymark} msg] $msg\n} -cleanup {\n  .t configure -startline {} -endline {}\n  .pt configure -startline {} -endline {}\n  .t mark unset mymark\n} -result {1 {bad text index \"mymark\"} 1.0 1.0 1 {bad text index \"mymark\"} L 1 {bad text index \"mymark\"}}\ntest textMark-6.5 {insert and current marks in an empty peer - bug 3487407} -body {\n  .t mark set insert 1.0\n  .t configure -startline 5 -endline 5\n  set res [.t index insert]\n} -cleanup {\n  .t configure -startline {} -endline {}\n} -result {1.0}\ntest textMark-6.6 {attempt to move the insert mark beyond peer -endline - bug 34db75c0ac} -body {\n  .t peer create .p -startline 1 -endline 2\n  pack .p\n  update\n  .p mark set insert 1.2\n  focus -force .p\n  event generate .p <<NextLine>>  ; # shall not error out\n  set res [.p index insert]\n} -cleanup {\n  destroy .p\n} -result {1.9}\n\ntest textMark-7.1 {MarkFindNext - invalid mark name} -body {\n    .t mark next bogus\n} -returnCodes error -result {bad text index \"bogus\"}\ntest textMark-7.2 {MarkFindNext - marks at same location} -body {\n    .t mark set insert 2.0\n    .t mark set current 2.0\n    .t mark next current\n} -result {insert}\ntest textMark-7.3 {MarkFindNext - numerical starting mark} -body {\n    .t mark set current 1.0\n    .t mark set insert 1.0\n    .t mark next 1.0\n} -result {insert}\ntest textMark-7.4 {MarkFindNext - mark on the same line} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.0\n    .t mark set insert 1.1\n    .t mark next current\n} -result {insert}\ntest textMark-7.5 {MarkFindNext - mark on the next line} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.end\n    .t mark set insert 2.0\n    .t mark next current\n} -result {insert}\ntest textMark-7.6 {MarkFindNext - mark far away} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.2\n    .t mark set insert 7.0\n    .t mark next current\n} -result {insert}\ntest textMark-7.7 {MarkFindNext - mark on top of end} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current end\n    .t mark next end\n} -result {current}\ntest textMark-7.8 {MarkFindNext - no next mark} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.0\n    .t mark set insert 3.0\n    .t mark next insert\n} -result {}\ntest textMark-7.9 {MarkFindNext - mark set in a text widget and retrieved from a peer} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set mymark 1.0\n    lsort [list [.pt mark next 1.0] [.pt mark next mymark] [.pt mark next insert]]\n} -result {current insert mymark}\n\ntest textMark-8.1 {MarkFindPrev - invalid mark name} -body {\n    .t mark prev bogus\n} -returnCodes error -result {bad text index \"bogus\"}\ntest textMark-8.2 {MarkFindPrev - marks at same location} -body {\n    .t mark set insert 2.0\n    .t mark set current 2.0\n    .t mark prev insert\n} -result {current}\ntest textMark-8.3 {MarkFindPrev - numerical starting mark} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.0\n    .t mark set insert 1.0\n    .t mark prev 1.1\n} -result {current}\ntest textMark-8.4 {MarkFindPrev - mark on the same line} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.0\n    .t mark set insert 1.1\n    .t mark prev insert\n} -result {current}\ntest textMark-8.5 {MarkFindPrev - mark on the previous line} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.end\n    .t mark set insert 2.0\n    .t mark prev insert\n} -result {current}\ntest textMark-8.6 {MarkFindPrev - mark far away} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.2\n    .t mark set insert 7.0\n    .t mark prev insert\n} -result {current}\ntest textMark-8.7 {MarkFindPrev - mark on top of end} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set insert 3.0\n    .t mark set current end\n    .t mark prev end\n} -result {insert}\ntest textMark-8.8 {MarkFindPrev - no previous mark} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set current 1.0\n    .t mark set insert 3.0\n    .t mark prev current\n} -result {}\ntest textMark-8.9 {MarkFindPrev - mark set in a text widget and retrieved from a peer} -setup {\n    .t mark unset {*}[.t mark names]\n} -body {\n    .t mark set mymark 1.0\n    lsort [list [.pt mark prev end] [.pt mark prev current] [.pt mark prev insert]]\n} -result {current insert mymark}\n\f\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .pt\ndestroy .t\ncleanupTests\n\n# Local Variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/textTag.test",
    "content": "# This file is a Tcl script to test the code in the file tkTextTag.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\n#\n# Don't use the variable name \"fixedFont\" since that variable is already defined\n# in utility namespace ::tk::test::text for importing in the namespace in which\n# test files are executing.\n#\nset fixedFont2 {Courier 12}\nset bigFont   {Helvetica 24}\n\n# Warn the user if the actual font is too different from what was requested.\nif {[font metrics [font actual $fixedFont2] -fixed] != 1} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont2]\\\",\\\ndoes not seem to be a fixed-width font as expected. If this is really the case, many upcoming\\\ntests will fail.\"\n}\n\ndestroy .t\ntext .t -width 20 -height 10 -font $fixedFont2\n\npack .t -expand 1 -fill both\nupdate\n.t debug on\n\nwm geometry . {}\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm, to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\n\n.t insert 1.0 \"Line 1\nabcdefghijklm\n12345\nLine 4\nbOy GIrl .#@? x_yz\n!@#$%\nLine 7\"\n\n#\n# TESTS\n#\n\ntest textTag-1.1 {tag configuration options} -body {\n    .t tag configure x -background #012345\n    .t tag cget x -background\n} -cleanup {\n    .t tag configure x -background [lindex [.t tag configure x -background] 3]\n} -result {#012345}\ntest textTag-1.2 {configuration options} -body {\n    .t tag configure x -background non-existent\n} -cleanup {\n    .t tag configure x -background [lindex [.t tag configure x -background] 3]\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest textTag-1.3 {tag configuration options} -body {\n    .t tag configure x -bgstipple gray50\n    .t tag cget x -bgstipple\n} -cleanup {\n    .t tag configure x -bgstipple [lindex [.t tag configure x -bgstipple] 3]\n} -result {gray50}\ntest textTag-1.4 {configuration options} -body {\n    .t tag configure x -bgstipple badStipple\n} -cleanup {\n    .t tag configure x -bgstipple [lindex [.t tag configure x -bgstipple] 3]\n} -returnCodes error -result {bitmap \"badStipple\" not defined}\ntest textTag-1.5 {tag configuration options} -body {\n    .t tag configure x -borderwidth 2\n    .t tag cget x -borderwidth\n} -cleanup {\n    .t tag configure x -borderwidth [lindex [.t tag configure x -borderwidth] 3]\n} -result {2}\ntest textTag-1.6 {configuration options} -body {\n    .t tag configure x -borderwidth 46q\n} -cleanup {\n    .t tag configure x -borderwidth [lindex [.t tag configure x -borderwidth] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"46q\"}\ntest textTag-1.7 {tag configuration options} -body {\n    .t tag configure x -fgstipple gray25\n    .t tag cget x -fgstipple\n} -cleanup {\n    .t tag configure x -fgstipple [lindex [.t tag configure x -fgstipple] 3]\n} -result {gray25}\ntest textTag-1.8 {configuration options} -body {\n    .t tag configure x -fgstipple bogus\n} -cleanup {\n    .t tag configure x -fgstipple [lindex [.t tag configure x -fgstipple] 3]\n} -returnCodes error -result {bitmap \"bogus\" not defined}\ntest textTag-1.9 {tag configuration options} -body {\n    .t tag configure x -font fixed\n    .t tag cget x -font\n} -cleanup {\n    .t tag configure x -font [lindex [.t tag configure x -font] 3]\n} -result {fixed}\ntest textTag-1.10 {tag configuration options} -body {\n    .t tag configure x -foreground #001122\n    .t tag cget x -foreground\n} -cleanup {\n    .t tag configure x -foreground [lindex [.t tag configure x -foreground] 3]\n} -result {#001122}\ntest textTag-1.11 {configuration options} -body {\n    .t tag configure x -foreground {silly color}\n} -cleanup {\n    .t tag configure x -foreground [lindex [.t tag configure x -foreground] 3]\n} -returnCodes error -result {unknown color name \"silly color\"}\ntest textTag-1.12 {tag configuration options} -body {\n    .t tag configure x -justify left\n    .t tag cget x -justify\n} -cleanup {\n    .t tag configure x -justify [lindex [.t tag configure x -justify] 3]\n} -result {left}\ntest textTag-1.13 {configuration options, bug [026e2bb685]} -body {\n    .t tag configure x -justify right\n    catch {.t tag configure x -justify middle} msg\n    list $msg [.t tag configure x -justify]\n} -cleanup {\n    .t tag configure x -justify [lindex [.t tag configure x -justify] 3]\n} -result {{bad justification \"middle\": must be left, right, center, or \"\"} {-justify {} {} {} right}}\ntest textTag-1.14 {tag configuration options} -body {\n    .t tag configure x -lmargin1 10\n    .t tag cget x -lmargin1\n} -cleanup {\n    .t tag configure x -lmargin1 [lindex [.t tag configure x -lmargin1] 3]\n} -result {10}\ntest textTag-1.15 {configuration options} -body {\n    .t tag configure x -lmargin1 bad\n} -cleanup {\n    .t tag configure x -lmargin1 [lindex [.t tag configure x -lmargin1] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"bad\"}\ntest textTag-1.16 {tag configuration options} -body {\n    .t tag configure x -lmargin2 10\n    .t tag cget x -lmargin2\n} -cleanup {\n    .t tag configure x -lmargin2 [lindex [.t tag configure x -lmargin2] 3]\n} -result {10}\ntest textTag-1.17 {configuration options} -body {\n    .t tag configure x -lmargin2 bad\n} -cleanup {\n    .t tag configure x -lmargin2 [lindex [.t tag configure x -lmargin2] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"bad\"}\ntest textTag-1.17a {tag configuration options} -body {\n    .t tag configure x -lmargincolor lightgreen\n    .t tag cget x -lmargincolor\n} -cleanup {\n    .t tag configure x -lmargincolor [lindex [.t tag configure x -lmargincolor] 3]\n} -result {lightgreen}\ntest textTag-1.17b {configuration options} -body {\n    .t tag configure x -lmargincolor non-existent\n} -cleanup {\n    .t tag configure x -lmargincolor [lindex [.t tag configure x -lmargincolor] 3]\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest textTag-1.18 {tag configuration options} -body {\n    .t tag configure x -offset 2\n    .t tag cget x -offset\n} -cleanup {\n    .t tag configure x -offset [lindex [.t tag configure x -offset] 3]\n} -result {2}\ntest textTag-1.19 {configuration options} -body {\n    .t tag configure x -offset 100xyz\n} -cleanup {\n    .t tag configure x -offset [lindex [.t tag configure x -offset] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"100xyz\"}\ntest textTag-1.20 {tag configuration options} -body {\n    .t tag configure x -overstrike on\n    .t tag cget x -overstrike\n} -cleanup {\n    .t tag configure x -overstrike [lindex [.t tag configure x -overstrike] 3]\n} -result 1\ntest textTag-1.21 {configuration options} -body {\n    .t tag configure x -overstrike stupid\n} -cleanup {\n    .t tag configure x -overstrike [lindex [.t tag configure x -overstrike] 3]\n} -returnCodes error -result {expected boolean value or \"\" but got \"stupid\"}\ntest textTag-1.21a {tag configuration options} -body {\n    .t tag configure x -overstrikefg red\n    .t tag cget x -overstrikefg\n} -cleanup {\n    .t tag configure x -overstrikefg [lindex [.t tag configure x -overstrikefg] 3]\n} -result {red}\ntest textTag-1.21b {configuration options} -body {\n    .t tag configure x -overstrikefg stupid\n} -cleanup {\n    .t tag configure x -overstrikefg [lindex [.t tag configure x -overstrikefg] 3]\n} -returnCodes error -result {unknown color name \"stupid\"}\ntest textTag-1.22 {tag configuration options} -body {\n    .t tag configure x -relief raised\n    .t tag cget x -relief\n} -cleanup {\n    .t tag configure x -relief [lindex [.t tag configure x -relief] 3]\n} -result {raised}\ntest textTag-1.23 {configuration options} -body {\n    .t tag configure x -relief stupid\n} -cleanup {\n    .t tag configure x -relief [lindex [.t tag configure x -relief] 3]\n} -returnCodes error -result {bad relief \"stupid\": must be flat, groove, raised, ridge, solid, sunken, or \"\"}\ntest textTag-1.24 {tag configuration options} -body {\n    .t tag configure x -rmargin 10\n    .t tag cget x -rmargin\n} -cleanup {\n    .t tag configure x -rmargin [lindex [.t tag configure x -rmargin] 3]\n} -result {10}\ntest textTag-1.25 {configuration options} -body {\n    .t tag configure x -rmargin bad\n} -cleanup {\n    .t tag configure x -rmargin [lindex [.t tag configure x -rmargin] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"bad\"}\ntest textTag-1.25a {tag configuration options} -body {\n    .t tag configure x -rmargincolor darkblue\n    .t tag cget x -rmargincolor\n} -cleanup {\n    .t tag configure x -rmargincolor [lindex [.t tag configure x -rmargincolor] 3]\n} -result {darkblue}\ntest textTag-1.25b {configuration options} -body {\n    .t tag configure x -rmargincolor non-existent\n} -cleanup {\n    .t tag configure x -rmargincolor [lindex [.t tag configure x -rmargincolor] 3]\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest textTag-1.25c {tag configuration options} -body {\n    .t tag configure x -selectbackground #012345\n    .t tag cget x -selectbackground\n} -cleanup {\n    .t tag configure x -selectbackground [lindex [.t tag configure x -selectbackground] 3]\n} -result {#012345}\ntest textTag-1.25d {configuration options} -body {\n    .t tag configure x -selectbackground non-existent\n} -cleanup {\n    .t tag configure x -selectbackground [lindex [.t tag configure x -selectbackground] 3]\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest textTag-1.25e {tag configuration options} -body {\n    .t tag configure x -selectforeground #012345\n    .t tag cget x -selectforeground\n} -cleanup {\n    .t tag configure x -selectforeground [lindex [.t tag configure x -selectforeground] 3]\n} -result {#012345}\ntest textTag-1.25f {configuration options} -body {\n    .t tag configure x -selectforeground non-existent\n} -cleanup {\n    .t tag configure x -selectforeground [lindex [.t tag configure x -selectforeground] 3]\n} -returnCodes error -result {unknown color name \"non-existent\"}\ntest textTag-1.26 {tag configuration options} -body {\n    .t tag configure x -spacing1 10\n    .t tag cget x -spacing1\n} -cleanup {\n    .t tag configure x -spacing1 [lindex [.t tag configure x -spacing1] 3]\n} -result {10}\ntest textTag-1.27 {configuration options} -body {\n    .t tag configure x -spacing1 bad\n} -cleanup {\n    .t tag configure x -spacing1 [lindex [.t tag configure x -spacing1] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"bad\"}\ntest textTag-1.28 {tag configuration options} -body {\n    .t tag configure x -spacing2 10\n    .t tag cget x -spacing2\n} -cleanup {\n    .t tag configure x -spacing2 [lindex [.t tag configure x -spacing2] 3]\n} -result {10}\ntest textTag-1.29 {configuration options, bug [026e2bb685]} -body {\n    catch {.t tag configure x -spacing3 5 -spacing2 bad -spacing1 morebad} msg\n    list $msg [.t tag configure x -spacing1] [.t tag configure x -spacing2] [.t tag configure x -spacing3]\n} -cleanup {\n    .t tag configure x -spacing1 [lindex [.t tag configure x -spacing1] 3] -spacing2 [lindex [.t tag configure x -spacing2] 3] -spacing3 [lindex [.t tag configure x -spacing3] 3]\n} -result {{expected screen distance or \"\" but got \"bad\"} {-spacing1 {} {} {} {}} {-spacing2 {} {} {} {}} {-spacing3 {} {} {} 5}}\ntest textTag-1.30 {tag configuration options} -body {\n    .t tag configure x -spacing3 10\n    .t tag cget x -spacing3\n} -cleanup {\n    .t tag configure x -spacing3 [lindex [.t tag configure x -spacing3] 3]\n} -result {10}\ntest textTag-1.31 {configuration options} -body {\n    .t tag configure x -spacing3 bad\n} -cleanup {\n    .t tag configure x -spacing3 [lindex [.t tag configure x -spacing3] 3]\n} -returnCodes error -result {expected screen distance or \"\" but got \"bad\"}\ntest textTag-1.32 {tag configuration options} -body {\n    .t tag configure x -tabs {10 20 30}\n    .t tag cget x -tabs\n} -cleanup {\n    .t tag configure x -tabs [lindex [.t tag configure x -tabs] 3]\n} -result {10 20 30}\ntest textTag-1.33 {configuration options} -body {\n    .t tag configure x -tabs {10 fork}\n} -cleanup {\n    .t tag configure x -tabs [lindex [.t tag configure x -tabs] 3]\n} -returnCodes error -result {bad tab alignment \"fork\": must be left, right, center, or numeric}\ntest textTag-1.34 {tag configuration options} -body {\n    .t tag configure x -underline no\n    .t tag cget x -underline\n} -cleanup {\n    .t tag configure x -underline [lindex [.t tag configure x -underline] 3]\n} -result 0\ntest textTag-1.35 {configuration options} -body {\n    .t tag configure x -underline stupid\n} -cleanup {\n    .t tag configure x -underline [lindex [.t tag configure x -underline] 3]\n} -returnCodes error -result {expected boolean value or \"\" but got \"stupid\"}\ntest textTag-1.36 {tag configuration options} -body {\n    .t tag configure x -underlinefg red\n    .t tag cget x -underlinefg\n} -cleanup {\n    .t tag configure x -underlinefg [lindex [.t tag configure x -underlinefg] 3]\n} -result {red}\ntest textTag-1.37 {configuration options} -body {\n    .t tag configure x -underlinefg stupid\n} -cleanup {\n    .t tag configure x -underlinefg [lindex [.t tag configure x -underlinefg] 3]\n} -returnCodes error -result {unknown color name \"stupid\"}\n\n\ntest textTag-2.1 {TkTextTagCmd - \"add\" option} -body {\n    .t tag\n} -returnCodes error -result {wrong # args: should be \".t tag option ?arg ...?\"}\ntest textTag-2.2 {TkTextTagCmd - \"add\" option} -body {\n    .t tag gorp\n} -returnCodes error -result {bad tag option \"gorp\": must be add, bind, cget, configure, delete, lower, names, nextrange, prevrange, raise, ranges, or remove}\ntest textTag-2.3 {TkTextTagCmd - \"add\" option} -body {\n    .t tag add foo\n} -returnCodes error -result {wrong # args: should be \".t tag add tagName index1 ?index2 index1 index2 ...?\"}\ntest textTag-2.4 {TkTextTagCmd - \"add\" option} -body {\n    .t tag add x gorp\n} -returnCodes error -result {bad text index \"gorp\"}\ntest textTag-2.5 {TkTextTagCmd - \"add\" option} -body {\n    .t tag add x 1.2 gorp\n} -returnCodes error -result {bad text index \"gorp\"}\ntest textTag-2.6 {TkTextTagCmd - \"add\" option} -setup {\n    .t tag delete sel\n} -body {\n    .t tag add sel 3.2 3.4\n    .t tag add sel 3.2 3.0\n    .t tag ranges sel\n} -result {3.2 3.4}\ntest textTag-2.7 {TkTextTagCmd - \"add\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 1.0 1.end\n    .t tag ranges x\n} -cleanup {\n    .t tag delete x\n} -result {1.0 1.6}\ntest textTag-2.8 {TkTextTagCmd - \"add\" option} -setup {\n    .t tag remove x 1.0 end\n} -body {\n    .t tag add x 1.2\n    .t tag ranges x\n} -cleanup {\n    .t tag delete x\n} -result {1.2 1.3}\ntest textTag-2.9 {TkTextTagCmd - \"add\" option} -setup {\n    destroy .t.e\n} -body {\n    entry .t.e\n    .t.e insert 0 \"Text\"\n    .t.e select from 0\n    .t.e select to 4\n    .t tag add sel 3.2 3.4\n    selection get\n} -cleanup {\n    destroy .t.e\n} -result 34\ntest textTag-2.10 {TkTextTagCmd - \"add\" option} -setup {\n    destroy .t.e\n} -body {\n    entry .t.e\n    .t.e insert 0 \"Text\"\n    .t.e select from 0\n    .t.e select to 4\n    .t configure -exportselection 0\n    .t tag add sel 3.2 3.4\n    selection get\n} -cleanup {\n    destroy .t.e\n}  -result {Text}\ntest textTag-2.11 {TkTextTagCmd - \"add\" option} -body {\n    .t tag remove sel 1.0 end\n    .t tag add sel 1.1 1.5 2.4 3.1 4.2 4.4\n    .t tag ranges sel\n} -result {1.1 1.5 2.4 3.1 4.2 4.4}\ntest textTag-2.12 {TkTextTagCmd - \"add\" option} -body {\n    .t tag remove sel 1.0 end\n    .t tag add sel 1.1 1.5 2.4\n    .t tag ranges sel\n} -cleanup {\n    .t tag remove sel 1.0 end\n} -result {1.1 1.5 2.4 2.5}\ntest textTag-2.14 {tag add before -startline - Bug 1615425} -body {\n    text .tt\n    for {set i 1} {$i <10} {incr i} {\n\t.tt insert end \"Line $i\\n\"\n    }\n    .tt tag configure mytag -offset 2\n    .tt peer create .ptt\n    .ptt configure -startline 3 -endline 7\n    # the test succeeds if next line does not crash\n    .tt tag add mytag 1.0 1.end\n    destroy .ptt .tt\n    set res 1\n} -result {1}\n\n\ntest textTag-3.1 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag bind\n} -returnCodes error -result {wrong # args: should be \".t tag bind tagName ?sequence? ?command?\"}\ntest textTag-3.2 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag bind 1 2 3 4\n} -returnCodes error -result {wrong # args: should be \".t tag bind tagName ?sequence? ?command?\"}\ntest textTag-3.3 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag bind x <Enter> script1\n    .t tag bind x <Enter>\n} -cleanup {\n    .t tag delete x\n} -result {script1}\ntest textTag-3.4 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag bind x <Gorp> script2\n} -returnCodes error -result {bad event type or keysym \"Gorp\"}\ntest textTag-3.5 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <Enter> script1\n    .t tag bind x <FocusIn> script2\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {requested illegal events; only key, button, motion, enter, leave, and virtual events may be used}\ntest textTag-3.6 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <Enter> script1\n    catch {.t tag bind x <FocusIn> script2}\n    .t tag bind x\n} -cleanup {\n    .t tag delete x\n} -result {<Enter>}\ntest textTag-3.7 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <Enter> script1\n    .t tag bind x <Leave> script2\n    .t tag bind x a xyzzy\n    list [lsort [.t tag bind x]] [.t tag bind x <Enter>] [.t tag bind x a]\n} -cleanup {\n    .t tag delete x\n} -result {{<Enter> <Leave> a} script1 xyzzy}\ntest textTag-3.8 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <Enter> script1\n    .t tag bind x <Enter> +script2\n    .t tag bind x <Enter>\n} -cleanup {\n    .t tag delete x\n} -result {script1\nscript2}\ntest textTag-3.9 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <Enter>\n} -cleanup {\n    .t tag delete x\n} -returnCodes ok -result {}\ntest textTag-3.10 {TkTextTagCmd - \"bind\" option} -body {\n    .t tag delete x\n    .t tag bind x <\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {no event type or button # or keysym}\n\n\ntest textTag-4.1 {TkTextTagCmd - \"cget\" option} -body {\n    .t tag cget a\n} -returnCodes error -result {wrong # args: should be \".t tag cget tagName option\"}\ntest textTag-4.2 {TkTextTagCmd - \"cget\" option} -body {\n    .t tag cget a b c\n} -returnCodes error -result {wrong # args: should be \".t tag cget tagName option\"}\ntest textTag-4.3 {TkTextTagCmd - \"cget\" option} -body {\n    .t tag delete foo\n    .t tag cget foo bar\n} -returnCodes error -result {tag \"foo\" isn't defined in text widget}\ntest textTag-4.4 {TkTextTagCmd - \"cget\" option} -body {\n    .t tag cget sel bogus\n} -returnCodes error -result {unknown option \"bogus\"}\ntest textTag-4.5 {TkTextTagCmd - \"cget\" option} -body {\n    .t tag delete x\n    .t tag configure x -background red\n    .t tag cget x -background\n} -cleanup {\n    .t tag delete x\n} -result {red}\n\n\ntest textTag-5.1 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag configure\n} -returnCodes error -result {wrong # args: should be \".t tag configure tagName ?-option value ...?\"}\ntest textTag-5.2 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag configure x -foo\n} -returnCodes error -result {unknown option \"-foo\"}\ntest textTag-5.3 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag configure x -background red -underline\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {value for \"-underline\" missing}\ntest textTag-5.4 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -underline yes\n    .t tag configure x -underline\n} -cleanup {\n    .t tag delete x\n} -result {-underline {} {} {} 1}\ntest textTag-5.4a {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -underlinefg lightgreen\n    .t tag configure x -underlinefg\n} -cleanup {\n    .t tag delete x\n} -result {-underlinefg {} {} {} lightgreen}\ntest textTag-5.5 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -overstrike on\n    .t tag cget x -overstrike\n} -cleanup {\n    .t tag delete x\n} -result 1\ntest textTag-5.5a {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -overstrikefg lightgreen\n    .t tag configure x -overstrikefg\n} -cleanup {\n    .t tag delete x\n} -result {-overstrikefg {} {} {} lightgreen}\ntest textTag-5.6 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag configure x -overstrike foo\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected boolean value or \"\" but got \"foo\"}\ntest textTag-5.7 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -underline stupid\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected boolean value or \"\" but got \"stupid\"}\ntest textTag-5.8 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -justify left\n    .t tag configure x -justify\n} -cleanup {\n    .t tag delete x\n} -result {-justify {} {} {} left}\ntest textTag-5.9 {TkTextTagCmd - \"configure\" option, bug [026e2bb685]} -body {\n   .t tag delete x\n    catch {.t tag configure x -justify bogus} msg\n    list $msg [.t tag configure x -justify]\n} -cleanup {\n    .t tag delete x\n} -result {{bad justification \"bogus\": must be left, right, center, or \"\"} {-justify {} {} {} {}}}\ntest textTag-5.10 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -justify fill\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {bad justification \"fill\": must be left, right, center, or \"\"}\ntest textTag-5.11 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -offset 2\n    .t tag configure x -offset\n} -cleanup {\n    .t tag delete x\n} -result {-offset {} {} {} 2}\ntest textTag-5.12 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -offset 1.0q\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"1.0q\"}\ntest textTag-5.13 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -lmargin1 2 -lmargin2 4 -rmargin 5 \\\n\t-lmargincolor darkblue -rmargincolor lightgreen\n    list [.t tag configure x -lmargin1] [.t tag configure x -lmargin2] \\\n\t[.t tag configure x -rmargin] [.t tag configure x -lmargincolor] \\\n\t[.t tag configure x -rmargincolor]\n} -cleanup {\n    .t tag delete x\n} -result [list {-lmargin1 {} {} {} 2} {-lmargin2 {} {} {} 4} \\\n\t\t{-rmargin {} {} {} 5} \\\n\t\t{-lmargincolor {} {} {} darkblue} {-rmargincolor {} {} {} lightgreen} \\\n\t  ]\ntest textTag-5.14 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -lmargin1 2.0x\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"2.0x\"}\ntest textTag-5.15 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -lmargin2 gorp\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"gorp\"}\ntest textTag-5.15a {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -lmargincolor rainbow\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {unknown color name \"rainbow\"}\ntest textTag-5.16 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -rmargin 140.1.1\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"140.1.1\"}\ntest textTag-5.16a {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -rmargincolor rainbow\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {unknown color name \"rainbow\"}\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag delete x\n\ntest textTag-5.17 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -spacing1 2 -spacing2 4 -spacing3 6\n    list [.t tag configure x -spacing1] [.t tag configure x -spacing2] \\\n\t[.t tag configure x -spacing3]\n} -cleanup {\n    .t tag delete x\n} -result {{-spacing1 {} {} {} 2} {-spacing2 {} {} {} 4} {-spacing3 {} {} {} 6}}\ntest textTag-5.18 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -spacing1 2.0x\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"2.0x\"}\ntest textTag-5.19 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -spacing1 lousy\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"lousy\"}\ntest textTag-5.20 {TkTextTagCmd - \"configure\" option} -body {\n    .t tag delete x\n    .t tag configure x -spacing1 4.2.3\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {expected screen distance or \"\" but got \"4.2.3\"}\ntest textTag-5.21 {TkTextTagCmd - \"configure\" option} -body {\n    .t configure -selectborderwidth 2 -selectforeground blue \\\n\t-selectbackground black\n    .t tag configure sel -borderwidth 4 -foreground green -background yellow\n    set x {}\n    foreach i {-selectborderwidth -selectforeground -selectbackground} {\n\tlappend x [lindex [.t configure $i] 4]\n    }\n    return $x\n} -result {4 green yellow}\ntest textTag-5.22 {TkTextTagCmd - \"configure\" option} -body {\n    .t configure -selectborderwidth 20\n    .t tag configure sel -borderwidth {}\n    .t cget -selectborderwidth\n} -result {}\ntest textTag-5.23 {TkTextTagCmd - \"configure\" option} -body {\n    set x {}\n    # when [.t tag cget sel -selectbackground] == \"\", mirroring happens between\n    #     the text widget option -selectbackground\n    # and the tag         option -background\n    .t tag configure sel -selectbackground {}\n    .t configure -selectbackground black\n    .t tag configure sel -background yellow\n    lappend x [.t cget -selectbackground]\n    .t tag configure sel -background orange\n    .t configure -selectbackground blue\n    lappend x [.t tag cget sel -background]\n    # when [.t tag cget sel -selectbackground] != \"\", mirroring happens between\n    #     the text widget option -selectbackground\n    # and the tag         option -selectbackground\n    .t tag configure sel -selectbackground green\n    .t configure -selectbackground red\n    lappend x [.t tag cget sel -selectbackground]\n    .t configure -selectbackground black\n    .t tag configure sel -selectbackground white\n    lappend x [.t cget -selectbackground]\n    return $x\n} -result {yellow blue red white}\ntest textTag-5.24 {TkTextTagCmd - \"configure\" option} -body {\n    set x {}\n    # when [.t tag cget sel -selectforeground] == \"\", mirroring happens between\n    #     the text widget option -selectforeground\n    # and the tag         option -foreground\n    .t tag configure sel -selectforeground {}\n    .t configure -selectforeground black\n    .t tag configure sel -foreground yellow\n    lappend x [.t cget -selectforeground]\n    .t tag configure sel -foreground orange\n    .t configure -selectforeground blue\n    lappend x [.t tag cget sel -foreground]\n    # when [.t tag cget sel -selectforeground] != \"\", mirroring happens between\n    #     the text widget option -selectforeground\n    # and the tag         option -selectforeground\n    .t tag configure sel -selectforeground green\n    .t configure -selectforeground red\n    lappend x [.t tag cget sel -selectforeground]\n    .t configure -selectforeground black\n    .t tag configure sel -selectforeground white\n    lappend x [.t cget -selectforeground]\n    return $x\n} -result {yellow blue red white}\n\ntest textTag-6.1 {TkTextTagCmd - \"delete\" option} -body {\n    .t tag delete\n} -returnCodes error -result {wrong # args: should be \".t tag delete tagName ?tagName ...?\"}\ntest textTag-6.2 {TkTextTagCmd - \"delete\" option} -body {\n    .t tag delete zork\n} -returnCodes ok -result {}\ntest textTag-6.3 {TkTextTagCmd - \"delete\" option} -setup {\n    .t tag delete {*}[.t tag names]\n} -body {\n    .t tag config x -background black\n    .t tag config y -foreground white\n    .t tag config z -background black\n    .t tag delete y z\n    lsort [.t tag names]\n} -cleanup {\n    .t tag delete x\n} -result {sel x}\ntest textTag-6.4 {TkTextTagCmd - \"delete\" option} -setup {\n    .t tag delete {*}[.t tag names]\n} -body {\n    .t tag config x -background black\n    .t tag config y -foreground white\n    .t tag config z -background black\n    eval .t tag delete [.t tag names]\n    .t tag names\n} -result {sel}\ntest textTag-6.5 {TkTextTagCmd - \"delete\" option} -body {\n    .t tag bind x <Enter> foo\n    .t tag delete x\n    .t tag configure x -background black\n    .t tag bind x\n} -cleanup {\n    .t tag delete x\n} -result {}\n\n\ntest textTag-7.1 {TkTextTagCmd - \"lower\" option} -body {\n    .t tag lower\n} -returnCodes error -result {wrong # args: should be \".t tag lower tagName ?belowThis?\"}\ntest textTag-7.2 {TkTextTagCmd - \"lower\" option} -body {\n    .t tag lower foo\n} -returnCodes error -result {tag \"foo\" isn't defined in text widget}\ntest textTag-7.3 {TkTextTagCmd - \"lower\" option} -body {\n    .t tag lower sel bar\n} -returnCodes error -result {tag \"bar\" isn't defined in text widget}\ntest textTag-7.4 {TkTextTagCmd - \"lower\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag lower c\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {c sel a b d}\ntest textTag-7.5 {TkTextTagCmd - \"lower\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag lower d b\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel a d b c}\ntest textTag-7.6 {TkTextTagCmd - \"lower\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag lower a c\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel b a c d}\n\n\ntest textTag-8.1 {TkTextTagCmd - \"names\" option} -body {\n    .t tag names a b\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -returnCodes error -result {wrong # args: should be \".t tag names ?index?\"}\ntest textTag-8.2 {TkTextTagCmd - \"names\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel a b c d}\ntest textTag-8.3 {TkTextTagCmd - \"names\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag add \"a b\" 2.1 2.6\n    .t tag add c 2.4 2.7\n    .t tag names 2.5\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {c {a b}}\n\n\ntest textTag-9.1 {TkTextTagCmd - \"nextrange\" option} -body {\n    .t tag nextrange x\n} -returnCodes error -result {wrong # args: should be \".t tag nextrange tagName index1 ?index2?\"}\ntest textTag-9.2 {TkTextTagCmd - \"nextrange\" option} -body {\n    .t tag nextrange x 1 2 3\n} -returnCodes error -result {wrong # args: should be \".t tag nextrange tagName index1 ?index2?\"}\ntest textTag-9.3 {TkTextTagCmd - \"nextrange\" option} -body {\n    .t tag nextrange foo 1.0\n} -returnCodes ok -result {}\ntest textTag-9.4 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag nextrange x foo\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {bad text index \"foo\"}\ntest textTag-9.5 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 1.0 bar\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {bad text index \"bar\"}\ntest textTag-9.6 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 1.0\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-9.7 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.2\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-9.8 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.3\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-9.9 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.4\n} -cleanup {\n    .t tag delete x\n} -result {2.9 3.1}\ntest textTag-9.10 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.4 2.9\n} -cleanup {\n    .t tag delete x\n} -result {}\ntest textTag-9.11 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.4 2.10\n} -cleanup {\n    .t tag delete x\n} -result {2.9 3.1}\ntest textTag-9.12 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 2.4 2.11\n} -cleanup {\n    .t tag delete x\n} -result {2.9 3.1}\ntest textTag-9.13 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 7.0\n} -cleanup {\n    .t tag delete x\n} -result {7.2 7.3}\ntest textTag-9.14 {TkTextTagCmd - \"nextrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag nextrange x 7.3\n} -cleanup {\n    .t tag delete x\n} -result {}\n\n\ntest textTag-10.1 {TkTextTagCmd - \"prevrange\" option} -body {\n    .t tag prevrange x\n} -returnCodes error -result {wrong # args: should be \".t tag prevrange tagName index1 ?index2?\"}\ntest textTag-10.2 {TkTextTagCmd - \"prevrange\" option} -body {\n    .t tag prevrange x 1 2 3\n} -returnCodes error -result {wrong # args: should be \".t tag prevrange tagName index1 ?index2?\"}\ntest textTag-10.3 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag prevrange foo end\n} -cleanup {\n    .t tag delete x\n} -returnCodes ok -result {}\ntest textTag-10.4 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x foo\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {bad text index \"foo\"}\ntest textTag-10.5 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x end bar\n} -cleanup {\n    .t tag delete x\n} -returnCodes error -result {bad text index \"bar\"}\ntest textTag-10.6 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x end\n} -cleanup {\n    .t tag delete x\n} -result {7.2 7.3}\ntest textTag-10.7 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.4\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-10.8 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.5\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-10.9 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.9\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-10.10 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.9 2.6\n} -cleanup {\n    .t tag delete x\n} -result {}\ntest textTag-10.11 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.9 2.5\n} -cleanup {\n    .t tag delete x\n} -result {}\ntest textTag-10.12 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.9 2.3\n} -cleanup {\n    .t tag delete x\n} -result {2.3 2.5}\ntest textTag-10.13 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 7.0\n} -cleanup {\n    .t tag delete x\n} -result {2.9 3.1}\ntest textTag-10.14 {TkTextTagCmd - \"prevrange\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.3 2.5\n    .t tag add x 2.9 3.1\n    .t tag add x 7.2\n    .t tag prevrange x 2.3\n} -cleanup {\n    .t tag delete x\n} -result {}\n\n\ntest textTag-11.1 {TkTextTagCmd - \"raise\" option} -body {\n    .t tag raise\n} -returnCodes error -result {wrong # args: should be \".t tag raise tagName ?aboveThis?\"}\ntest textTag-11.2 {TkTextTagCmd - \"raise\" option} -body {\n    .t tag raise foo\n} -returnCodes error -result {tag \"foo\" isn't defined in text widget}\ntest textTag-11.3 {TkTextTagCmd - \"raise\" option} -body {\n    .t tag raise sel bar\n} -returnCodes error -result {tag \"bar\" isn't defined in text widget}\ntest textTag-11.4 {TkTextTagCmd - \"raise\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag raise c\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel a b d c}\ntest textTag-11.5 {TkTextTagCmd - \"raise\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag raise d b\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel a b d c}\ntest textTag-11.6 {TkTextTagCmd - \"raise\" option} -setup {\n    .t tag delete {*}[.t tag names]\n    .t tag remove sel 1.0 end\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n} -body {\n    .t tag raise a c\n    .t tag names\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {sel b c a d}\n\n\ntest textTag-12.1 {TkTextTagCmd - \"ranges\" option} -body {\n    .t tag ranges\n} -returnCodes error -result {wrong # args: should be \".t tag ranges tagName\"}\ntest textTag-12.2 {TkTextTagCmd - \"ranges\" option} -body {\n    .t tag delete x\n    .t tag ranges x\n} -result {}\ntest textTag-12.3 {TkTextTagCmd - \"ranges\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.2\n    .t tag add x 2.7 4.15\n    .t tag add x 5.2 5.5\n    .t tag ranges x\n} -cleanup {\n    .t tag delete x\n} -result {2.2 2.3 2.7 4.6 5.2 5.5}\ntest textTag-12.4 {TkTextTagCmd - \"ranges\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 1.0 3.0\n    .t tag add x 4.0 end\n    .t tag ranges x\n} -cleanup {\n    .t tag delete x\n} -result {1.0 3.0 4.0 8.0}\n\n\ntest textTag-13.1 {TkTextTagCmd - \"remove\" option} -body {\n    .t tag remove\n} -returnCodes error -result {wrong # args: should be \".t tag remove tagName index1 ?index2 index1 index2 ...?\"}\ntest textTag-13.2 {TkTextTagCmd - \"remove\" option} -setup {\n    .t tag delete x\n} -body {\n    .t tag add x 2.2 2.11\n    .t tag remove x 2.3 2.7\n    .t tag ranges x\n} -cleanup {\n    .t tag delete x\n} -result {2.2 2.3 2.7 2.11}\ntest textTag-13.3 {TkTextTagCmd - \"remove\" option} -setup {\n    destroy .t.e\n} -body {\n    entry .t.e\n    .t.e insert 0 \"Text\"\n    .t configure -exportselection 1\n    .t tag remove sel 1.0 end\n    .t tag add sel 2.4 3.3\n    .t.e select to 4\n    .t tag remove sel 2.7 3.1\n    selection get\n} -cleanup {\n    destroy .t.e\n} -result {Text}\n\n\ntest textTag-14.1 {SortTags} -setup {\n    .t tag delete a b c d\n} -body {\n    foreach i {a b c d} {\n\t.t tag add $i 2.0 2.2\n    }\n    .t tag names 2.1\n} -cleanup {\n    .t tag delete a b c d\n} -result {a b c d}\n\n#\n# COMMON TEST CLEANUP\n#\n.t tag delete a b c d\n\ntest textTag-14.2 {SortTags} -setup {\n    .t tag delete a b c d\n} -body {\n    foreach i {a b c d} {\n\t.t tag configure $i -background black\n    }\n    foreach i {d c b a} {\n\t.t tag add $i 2.0 2.2\n    }\n    .t tag names 2.1\n} -cleanup {\n    .t tag delete a b c d\n} -result {a b c d}\ntest textTag-14.3 {SortTags} -setup {\n    .t tag delete {*}[.t tag names]\n} -body {\n    for {set i 0} {$i < 30} {incr i} {\n\t.t tag add x$i 2.0 2.2\n    }\n    .t tag names 2.1\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29}\ntest textTag-14.4 {SortTags} -setup {\n    .t tag delete {*}[.t tag names]\n} -body {\n    for {set i 0} {$i < 30} {incr i} {\n\t.t tag configure x$i -background black\n    }\n    for {set i 29} {$i >= 0} {incr i -1} {\n\t.t tag add x$i 2.0 2.2\n    }\n    .t tag names 2.1\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29}\n\n#\n# COMMON TEST SETUP\n#\n\nset c [.t bbox 2.1]\nset x1 [expr {[lindex $c 0] + [lindex $c 2]/2}]\nset y1 [expr {[lindex $c 1] + [lindex $c 3]/2}]\nset c [.t bbox 3.2]\nset x2 [expr {[lindex $c 0] + [lindex $c 2]/2}]\nset y2 [expr {[lindex $c 1] + [lindex $c 3]/2}]\nset c [.t bbox 4.3]\nset x3 [expr {[lindex $c 0] + [lindex $c 2]/2}]\nset y3 [expr {[lindex $c 1] + [lindex $c 3]/2}]\n\ntest textTag-15.1 {TkTextBindProc} -setup {\n    .t tag delete x y\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    bind .t <ButtonRelease> {lappend x up}\n    .t tag bind x <ButtonRelease> {lappend x x-up}\n    .t tag bind y <ButtonRelease> {lappend x y-up}\n    set x {}\n    .t tag add x 2.0 2.4\n    .t tag add y 4.3\n    event gen .t <Button> -x $x1 -y $y1\n    event gen .t <Motion> -x $x1 -y $y1\n    event gen .t <ButtonRelease> -x $x1 -y $y1\n    event gen .t <Button> -x $x1 -y $y1\n    event gen .t <Motion> -x $x2 -y $y2\n    event gen .t <ButtonRelease> -x $x2 -y $y2\n    event gen .t <Button> -x $x2 -y $y2\n    event gen .t <Motion> -x $x3 -y $y3\n    event gen .t <ButtonRelease> -x $x3 -y $y3\n    return $x\n} -cleanup {\n    .t tag delete x y\n    bind .t <ButtonRelease> {}\n} -result {x-up up up y-up up}\n\ntest textTag-15.2 {TkTextBindProc} -setup {\n    .t tag delete x y\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag bind x <Enter> {lappend x x-enter}\n    .t tag bind x <Button> {lappend x x-down}\n    .t tag bind x <ButtonRelease> {lappend x x-up}\n    .t tag bind x <Leave> {lappend x x-leave}\n    .t tag bind y <Enter> {lappend x y-enter}\n    .t tag bind y <Button> {lappend x y-down}\n    .t tag bind y <ButtonRelease> {lappend x y-up}\n    .t tag bind y <Leave> {lappend x y-leave}\n    event gen .t <Motion> -x 0 -y 0\n    set x {}\n    .t tag add x 2.0 2.4\n    .t tag add y 4.3\n    event gen .t <Motion> -x $x1 -y $y1\n    lappend x |\n    event gen .t <Button> -x $x1 -y $y1\n    lappend x |\n    event gen .t <Motion> -x $x3 -y $y3 -state 0x100\n    lappend x |\n    event gen .t <ButtonRelease> -x $x3 -y $y3\n    return $x\n} -cleanup {\n    .t tag delete x y\n} -result {x-enter | x-down | | x-up x-leave y-enter}\n\ntest textTag-15.3 {TkTextBindProc} -setup {\n    .t tag delete x y\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag bind x <Enter> {lappend x x-enter}\n    .t tag bind x <Button-1> {lappend x x-down}\n    .t tag bind x <ButtonRelease-1> {lappend x x-up}\n    .t tag bind x <Leave> {lappend x x-leave}\n    .t tag bind y <Enter> {lappend x y-enter}\n    .t tag bind y <Button-1> {lappend x y-down}\n    .t tag bind y <ButtonRelease-1> {lappend x y-up}\n    .t tag bind y <Leave> {lappend x y-leave}\n    event gen .t <Motion> -x 0 -y 0\n    set x {}\n    .t tag add x 2.0 2.4\n    .t tag add y 4.3\n    event gen .t <Motion> -x $x1 -y $y1\n    lappend x |\n    event gen .t <Button-1> -x $x1 -y $y1\n    lappend x |\n    event gen .t <Button-2> -x $x1 -y $y1 -state 0x100\n    lappend x |\n    event gen .t <Motion> -x $x3 -y $y3  -state 0x300\n    lappend x |\n    event gen .t <ButtonRelease-1> -x $x3 -y $y3 -state 0x300\n    lappend x |\n    event gen .t <ButtonRelease-2> -x $x3 -y $y3 -state 0x200\n    return $x\n} -cleanup {\n    .t tag delete x y\n} -result {x-enter | x-down | | | x-up | x-leave y-enter}\n\ntest textTag-15.4 {TkTextBindProc, key event with mouse outside the widget} -setup {\n    .t tag delete {*}[.t tag names]\n    wm geometry . +200+200 ; update\n} -body {\n    set res {}\n    .t tag add tag1 1.0 end\n    .t tag bind tag1 <Key> {lappend res %K}\n    .t mark set insert 1.2\n    update\n    event generate .t <Motion> -warp 1 -x -50 -y -50\n    controlPointerWarpTiming\n    focus -force .t\n    event generate .t <Key> -keysym a\n    set res\n} -cleanup {\n    .t tag delete tag1\n} -result {a}\n\n\ntest textTag-16.1 {TkTextPickCurrent procedure} -setup {\n    .t tag delete {*}[.t tag names]\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    event gen .t <ButtonRelease-1> -state 0x100 -x $x1 -y $y1\n    set x [.t index current]\n    event gen .t <Motion> -x $x2 -y $y2\n    lappend x [.t index current]\n    event gen .t <Button-1> -x $x2 -y $y2\n    lappend x [.t index current]\n    event gen .t <Motion> -x $x3 -y $y3 -state 0x100\n    lappend x [.t index current]\n    event gen .t <Button-3> -state 0x100 -x $x3 -y $y3\n    lappend x [.t index current]\n    event gen .t <ButtonRelease-3> -state 0x300 -x $x3 -y $y3\n    lappend x [.t index current]\n    event gen .t <ButtonRelease-1> -state 0x100 -x $x3 -y $y3\n    lappend x [.t index current]\n} -result {2.1 3.2 3.2 3.2 3.2 3.2 4.3}\n\ntest textTag-16.2 {TkTextPickCurrent procedure} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -setup {\n    .t tag delete {*}[.t tag names]\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag configure big -font $bigFont\n    # update needed here to stabilize the test\n    update\n    event gen .t <ButtonRelease-1> -state 0x100 -x $x1 -y $y1\n    event gen .t <Motion> -x $x2 -y $y2\n    set x [.t index current]\n    .t tag add big 3.0\n    update\n    lappend x [.t index current]\n} -cleanup {\n    .t tag delete big\n} -result {3.2 3.1}\n\ntest textTag-16.3 {TkTextPickCurrent procedure} -setup {\n    foreach i {a b c d} {\n\t.t tag remove $i 1.0 end\n    }\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    foreach i {a b c d} {\n\t.t tag bind $i <Enter> \"lappend x enter-$i\"\n\t.t tag bind $i <Leave> \"lappend x leave-$i\"\n    }\n    .t tag lower b\n    .t tag lower a\n    set x {}\n    event gen .t <Motion> -x $x1 -y $y1\n    .t tag add a 2.1 3.3\n    .t tag add b 2.1\n    .t tag add c 3.2\n    update\n    lappend x |\n    event gen .t <Motion> -x $x2 -y $y2\n    lappend x |\n    event gen .t <Motion> -x $x3 -y $y3\n    return $x\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {enter-a enter-b | leave-b enter-c | leave-a leave-c}\n\ntest textTag-16.4 {TkTextPickCurrent procedure} -setup {\n    foreach i {a b c d} {\n\t.t tag remove $i 1.0 end\n    }\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    foreach i {a b c d} {\n\t.t tag bind $i <Enter> \"lappend x enter-$i\"\n\t.t tag bind $i <Leave> \"lappend x leave-$i\"\n    }\n    .t tag lower b\n    .t tag lower a\n    set x {}\n    event gen .t <Motion> -x $x1 -y $y1\n    .t tag add a 2.1 3.3\n    .t tag add b 2.1\n    .t tag add c 2.1\n    update\n    lappend x |\n    .t tag lower c\n    event gen .t <Motion> -x $x2 -y $y2\n    return $x\n} -cleanup {\n    .t tag delete {*}[.t tag names]\n} -result {enter-a enter-b enter-c | leave-c leave-b}\n\ntest textTag-16.5 {TkTextPickCurrent procedure} -setup {\n    foreach i {big a b c d} {\n\t.t tag remove $i 1.0 end\n    }\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag configure big -font $bigFont\n    event gen .t <Motion> -x $x1 -y $y1\n    .t tag bind a <Enter> {.t tag add big 3.0 3.2}\n    .t tag add a 3.2\n    event gen .t <Motion> -x $x2 -y $y2\n    .t index current\n} -cleanup {\n    .t tag delete a big\n} -result {3.2}\n\ntest textTag-16.6 {TkTextPickCurrent procedure} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -setup {\n    foreach i {big a b c d} {\n\t.t tag remove $i 1.0 end\n    }\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag configure big -font $bigFont\n    event gen .t <Motion> -x $x1 -y $y1\n    .t tag bind a <Enter> {.t tag add big 3.0 3.2}\n    .t tag add a 3.2\n    event gen .t <Motion> -x $x2 -y $y2\n    update\n    .t index current\n} -cleanup {\n    .t tag delete a big\n} -result {3.1}\n\ntest textTag-16.7 {TkTextPickCurrent procedure} -constraints {\n    haveBigFontTwiceLargerThanTextFont\n} -setup {\n    foreach i {big a b c d} {\n\t.t tag remove $i 1.0 end\n    }\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    .t tag configure big -font $bigFont\n    .t tag bind a <Enter> {.t tag add big 3.0 3.2}\n    .t tag add a 3.2\n\n    event gen .t <Motion> -x $x1 -y $y1\n    .t tag bind a <Leave> {.t tag add big 3.0 3.2}\n    .t tag add a 2.1\n    event gen .t <Motion> -x $x2 -y $y2\n    update\n    .t index current\n} -cleanup {\n    .t tag delete a big\n} -result {3.1}\n\n\ntest textTag-17.1 {insert procedure inserts tags} -setup {\n    .t delete 1.0 end\n} -body {\n    # Objectification of the text widget had a problem\n    # with inserting tags when using 'end'. Check that\n    # bug has been fixed.\n    .t insert end abcd {x} \\n {} efgh {y} \\n {}\n    .t dump -tag 1.0 end\n} -result {tagon x 1.0 tagoff x 1.4 tagon y 2.0 tagoff y 2.4}\n\n\ntest textTag-18.1 {TkTextPickCurrent tag bindings} -setup {\n    destroy .t\n    wm geometry . +200+200 ; update\n    event generate {} <Motion> -warp 1 -x 5 -y 5\n    controlPointerWarpTiming\n} -body {\n    # Move the cursor out of the way.\n    event generate . <Motion> -warp 1 -x 800 -y 500\n    controlPointerWarpTiming\n    text .t -width 30 -height 4 -relief sunken -borderwidth 10 \\\n      -highlightthickness 10 -pady 2\n    pack .t\n    update ; # map the window, otherwise -warp can't be done\n\n    .t insert end \" Tag here \" TAG \" no tag here\"\n    .t tag configure TAG -borderwidth 4 -relief raised\n    .t tag bind TAG <Enter>  {lappend res \"%x %y tag-Enter\"}\n    .t tag bind TAG <Leave>  {lappend res \"%x %y tag-Leave\"}\n    bind .t <Enter> {lappend res Enter}\n    bind .t <Leave> {lappend res Leave}\n\n    set res {}\n    # Bindings must not trigger on the widget border, only over\n    # the actual tagged characters themselves.\n    # Note that we don't need to call controlPointerWarpTiming\n    # in the following six calls because we're not checking that\n    # the mouse pointer has actually moved but rather that the\n    # tag binding mechanism of the text widget correctly triggers.\n    event gen .t <Motion> -warp 1 -x 0 -y 0 ; update\n    event gen .t <Motion> -warp 1 -x 10 -y 10 ; update\n    event gen .t <Motion> -warp 1 -x 25 -y 25 ; update\n    event gen .t <Motion> -warp 1 -x 20 -y 20 ; update\n    event gen .t <Motion> -warp 1 -x 10 -y 10 ; update\n    event gen .t <Motion> -warp 1 -x 25 -y 25 ; update\n    set res\n} -cleanup {\n    destroy .t\n} -result {Enter {25 25 tag-Enter} {20 20 tag-Leave} {25 25 tag-Enter}}\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .t\ncleanupTests\n"
  },
  {
    "path": "tests/textWind.test",
    "content": "# This file is a Tcl script to test the code in the file tkTextWind.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import text\n\n#\n# COMMON TEST SETUP\n#\n\ndeleteWindows\n\n# On Windows at least, the tests do work with {Courier -10}, {Courier -12} or {Courier -14} as fixedFont.\n# Warn the user if the actual font is too different from what was requested.\nif {[font metrics [font actual $fixedFont] -fixed] != 1} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\ndoes not seem to be a fixed-width font as expected. If this is really the case, many upcoming\\\ntests will fail.\"\n}\nif {$fixedHeight < 12 || $fixedHeight > 17} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\nis $fixedHeight pixels height while the tests expect between 12 and 17 (inclusive) pixels.\\\nSome of the upcoming tests will probably fail.\"\n}\nif {$fixedWidth < 6 || $fixedWidth > 8} {\n    puts \"---> Warning: the font actually used by the tests, which is \\\"[font actual $fixedFont]\\\",\\\nis $fixedWidth pixels in width while the tests expect between 6 and 8 (inclusive) pixels.\\\nSome of the upcoming tests will probably fail.\"\n}\n\n# Widget used in almost all tests\n# Option  -width 30  (characters) below is a fundamental assumption of many\n# upcoming tests when wrapping enters in play\n# Also  -height 6  (lines) is an important assumption\n# Moreover the widget must have the same padding in x and y (see proc bo)\n# However the tests are not sensitive to  -borderwidth  and  -highlightthickness\ntext .t -font $fixedFont -width 30 -height 6 -borderwidth 2 -highlightthickness 2\npack .t -expand 1 -fill both\nupdate\n.t debug on\n\nwm geometry . {}\n\nset color [expr {[winfo depth .t] > 1 ? \"green\" : \"black\"}]\n\n# The statements below reset the main window;  it's needed if the window\n# manager is mwm to make mwm forget about a previous minimum size setting.\n\nwm withdraw .\nwm minsize . 1 1\nwm positionfrom . user\nwm deiconify .\n\n# This update is needed on MacOS to make sure that the window is mapped\n# when the tests begin.\n\nupdate\n\n#\n# TESTS\n#\n\ntest textWind-1.1 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 3 -height 3 -bg $color\n    .t window create 2.2 -window .f\n    update\n    list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] \\\n\t[.t window configure .f -window]\n} -result [list \\\n    1 \\\n    3x3+[xchar 2]+[expr {[yline 2]+($fixedHeight-3)/2}] \\\n    [list [xchar 2] [expr {[yline 2]+($fixedHeight-3)/2}] 3 3] \\\n    {-window {} {} {} .f}]\n\ntest textWind-1.2 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 3 -height 3 -bg $color\n    .t window create 2.2 -window .f -align top\n    update\n    list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] \\\n\t[.t window configure .f -align]\n} -result [list \\\n    1 \\\n    3x3+[xchar 2]+[yline 2] \\\n    [list [xchar 2] [yline 2] 3 3] \\\n    {-align {} {} center top}]\n\ntest textWind-1.3 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    .t window create 2.2 -create \"Test script\"\n    .t window configure 2.2 -create\n} -result {-create {} {} {} {Test script}}\n\ntest textWind-1.4 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    # the window .f should be wider than the fixed width\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 2.2 -window .f -padx 5\n    update\n    list [winfo geom .f] [.t window configure .f -padx] [.t bbox 2.3]\n} -result [list \\\n    10x20+[expr {[xchar 2]+5}]+[yline 2] \\\n    {-padx {} {} 0 5} \\\n    [list [expr {[xchar 2]+10+2*5}] [expr {[yline 2]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]]\n\ntest textWind-1.5 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 2.2 -window .f -pady 4\n    update\n    list [winfo geom .f] [.t window configure .f -pady] [.t bbox 2.31]\n} -result [list \\\n    10x20+[xchar 2]+[expr {[yline 2]+4}] \\\n    {-pady {} {} 0 4} \\\n    [list [xchar 2] [expr {[yline 2]+20+2*4}] $fixedWidth $fixedHeight]]\n\ntest textWind-1.6 {basic tests of options} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 2.2 -window .f -stretch 1\n    update\n    list [winfo geom .f] [.t window configure .f -stretch]\n} -result [list \\\n    5x$fixedHeight+[xchar 2]+[yline 2] \\\n    {-stretch {} {} 0 1}]\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\n.t insert end \"This is the first line\"\n\ntest textWind-2.1 {TkTextWindowCmd procedure} -body {\n    .t window\n} -returnCodes error -result {wrong # args: should be \".t window option ?arg ...?\"}\ntest textWind-2.2 {TkTextWindowCmd procedure, \"cget\" option} -body {\n    .t window cget\n} -returnCodes error -result {wrong # args: should be \".t window cget index option\"}\ntest textWind-2.3 {TkTextWindowCmd procedure, \"cget\" option} -body {\n    .t window cget a b c\n} -returnCodes error -result {wrong # args: should be \".t window cget index option\"}\ntest textWind-2.4 {TkTextWindowCmd procedure, \"cget\" option} -body {\n    .t window cget gorp -padx\n} -returnCodes error -result {bad text index \"gorp\"}\ntest textWind-2.5 {TkTextWindowCmd procedure, \"cget\" option} -body {\n    .t window cget 1.2 -padx\n} -returnCodes error -result {no embedded window at index \"1.2\"}\ntest textWind-2.6 {TkTextWindowCmd procedure, \"cget\" option} -setup {\n    destroy .f\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.3 -window .f -padx 1 -pady 2\n    .t window cget .f -bogus\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {unknown option \"-bogus\"}\ntest textWind-2.7 {TkTextWindowCmd procedure, \"cget\" option} -setup {\n    destroy .f\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.3 -window .f -padx 1 -pady 2\n    .t window cget .f -pady\n} -cleanup {\n    destroy .f\n} -returnCodes ok -result 2\ntest textWind-2.8 {TkTextWindowCmd procedure} -body {\n    .t window co\n} -returnCodes error -result {wrong # args: should be \".t window configure index ?-option value ...?\"}\ntest textWind-2.9 {TkTextWindowCmd procedure} -body {\n    .t window configure gorp\n} -returnCodes error -result {bad text index \"gorp\"}\ntest textWind-2.10 {TkTextWindowCmd procedure} -body {\n    .t delete 1.0 end\n    .t window configure 1.0\n} -returnCodes error -result {no embedded window at index \"1.0\"}\ntest textWind-2.11 {TkTextWindowCmd procedure} -setup {\n# I kept this as it \"influenced\" the test case in previous releases\n    destroy .f\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.3 -window .f -padx 1 -pady 2\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2 -create foo\n    update\n    .t window configure .f\n} -cleanup {\n    destroy .f\n} -result  {{-align {} {} center baseline} {-create {} {} {} foo} {-padx {} {} 0 1} {-pady {} {} 0 2} {-stretch {} {} 0 0} {-window {} {} {} .f}}\ntest textWind-2.12 {TkTextWindowCmd procedure} -setup {\n    destroy .f\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2 -create foo\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2 -create foo\n    update\n    list [.t window configure .f -padx 33] [.t window configure .f -padx]\n} -cleanup {\n    destroy .f\n} -result {{} {-padx {} {} 0 33}}\ntest textWind-2.13 {TkTextWindowCmd procedure} -setup {\n    destroy .f\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2 -create foo\n    .t delete 1.0 end\n} -body {\n    .t insert end \"This is the first line\"\n    .t insert end \"\\nAnd this is a second line, which wraps around\"\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2\n    update\n    list [.t window configure .f -padx 14 -pady 15] \\\n\t[.t window configure .f -padx] [.t window configure .f -pady]\n} -cleanup {\n    destroy .f\n} -result {{} {-padx {} {} 0 14} {-pady {} {} 0 15}}\ntest textWind-2.14 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t window create\n} -returnCodes error -result {wrong # args: should be \".t window create index ?-option value ...?\"}\ntest textWind-2.15 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t window create gorp\n} -returnCodes error -result {bad text index \"gorp\"}\ntest textWind-2.16 {TkTextWindowCmd procedure, don't insert after end} -setup {\n    destroy .f\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 2.2 -window .f -align baseline -padx 1 -pady 2\n    .t delete 1.0 end\n} -body {\n    .t insert end \"Line 1\\nLine 2\"\n    frame .f -width 20 -height 10 -bg $color\n    .t window create end -window .f\n    .t index .f\n} -result {2.6}\ntest textWind-2.17 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    list [catch {.t window create 1.0} msg] $msg [.t window configure 1.0]\n} -result {0 {} {{-align {} {} center center} {-create {} {} {} {}} {-padx {} {} 0 {}} {-pady {} {} 0 {}} {-stretch {} {} 0 0} {-window {} {} {} {}}}}\ntest textWind-2.18 {TkTextWindowCmd procedure} -setup {\n    destroy .f\n    frame .f -width 20 -height 10 -bg $color\n    .t window create end -window .f\n    .t delete 1.0 end\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.0 -window .f -gorp stupid\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest textWind-2.19 {TkTextWindowCmd procedure} -setup {\n    destroy .f\n    frame .f -width 20 -height 10 -bg $color\n    .t window create end -window .f\n    .t delete 1.0 end\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    catch {.t window create 1.0 -window .f -gorp stupid}\n    list [winfo exists .f] [.t index 1.end] [catch {.t index .f}]\n} -result {0 1.0 1}\ntest textWind-2.20 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.0 -gorp -window .f stupid\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest textWind-2.21 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    catch {.t window create 1.0 -gorp -window .f stupid}\n    list [winfo exists .f] [.t index 1.end] [catch {.t index .f}]\n} -result {1 1.0 1}\ntest textWind-2.22 {TkTextWindowCmd procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t window c\n} -returnCodes error -result {ambiguous window option \"c\": must be cget, configure, create, or names}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .f\n\ntest textWind-2.23 {TkTextWindowCmd procedure, \"names\" option} -setup {\n    .t delete 1.0 end\n} -body {\n    .t window names foo\n} -returnCodes error -result {wrong # args: should be \".t window names\"}\ntest textWind-2.24 {TkTextWindowCmd procedure, \"names\" option} -setup {\n    .t delete 1.0 end\n} -body {\n    .t window names\n} -result {}\ntest textWind-2.25 {TkTextWindowCmd procedure, \"names\" option} -setup {\n    .t delete 1.0 end\n    destroy .f .f2 .t.f .t.f2\n} -body {\n    foreach i {.f .f2 .t.f .t.f2} {\n\tframe $i -width 20 -height 20\n\t.t window create end -window $i\n    }\n    lsort [.t window names]\n} -cleanup {\n    destroy .f .f2 .t.f .t.f2\n} -result {.f .f2 .t.f .t.f2}\n\ntest textWind-3.1 {EmbWinConfigure procedure} -setup {\n    destroy .f\n} -body {\n    frame .f -width 10 -height 6 -bg $color\n    .t window create 1.0 -window .f\n    .t window configure 1.0 -foo bar\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {unknown option \"-foo\"}\n\ntest textWind-3.2 {EmbWinConfigure procedure} -setup {\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.3 -window .f\n    update\n    .t window configure 1.3 -window {}\n    update\n    .t index .f\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {bad text index \".f\"}\n\ntest textWind-3.3 {EmbWinConfigure procedure} -setup {\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.3 -window .f\n    update\n    set res [winfo ismapped .f]\n    .t window configure 1.3 -window {}\n    update\n    lappend res [winfo ismapped .f] [.t bbox 1.4]\n} -cleanup {\n    destroy .f\n} -result [list 1 0 \\\n    [list [xchar 3] [yline 1] $fixedWidth $fixedHeight]]\n\ntest textWind-3.4 {EmbWinConfigure procedure} -setup {\n    destroy .t.f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .t.f -width 10 -height 20 -bg $color\n    .t window create 1.3 -window .t.f\n    update\n    .t window configure 1.3 -window {}\n    update\n    .t index .t.f\n} -cleanup {\n    destroy .t.f\n} -returnCodes error -result {bad text index \".t.f\"}\n\ntest textWind-3.5 {EmbWinConfigure procedure} -setup {\n    destroy .t.f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .t.f -width 10 -height 20 -bg $color\n    .t window create 1.3 -window .t.f\n    update\n    set res [winfo ismapped .t.f]\n    .t window configure 1.3 -window {}\n    update\n    lappend res [winfo ismapped .t.f] [.t bbox 1.4]\n} -cleanup {\n    destroy .t.f\n} -result [list 1 0 \\\n    [list [xchar 3] [yline 1] $fixedWidth $fixedHeight]]\n\ntest textWind-3.6 {EmbWinConfigure procedure} -setup {\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.3\n    update\n    .t window configure 1.3 -window .f\n    update\n    list [catch {.t index .f} msg] $msg [winfo ismapped .f] [.t bbox 1.4]\n} -cleanup {\n    destroy .f\n} -result [list 0 1.3 1 \\\n    [list [expr {[xchar 3]+10}] [expr {[yline 1]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]]\n\ntest textWind-3.7 {EmbWinConfigure procedure} -setup {\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f\n    frame .f.f -width 15 -height 20 -bg $color\n    pack .f.f\n    .t window create 1.3 -window .f.f\n} -cleanup {\n    destroy .f\n} -returnCodes error -result {can't embed .f.f in .t}\n\ntest textWind-3.8 {EmbWinConfigure procedure} -setup {\n    destroy .t2\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    toplevel .t2 -width 20 -height 10 -bg $color\n    .t window create 1.3\n    .t window configure 1.3 -window .t2\n} -cleanup {\n    destroy .t2\n} -returnCodes error -result {can't embed .t2 in .t}\n\ntest textWind-3.9 {EmbWinConfigure procedure} -setup {\n    destroy .t2\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    toplevel .t2 -width 20 -height 10 -bg $color\n    .t window create 1.3\n    catch {.t window configure 1.3 -window .t2}\n    .t window configure 1.3 -window\n} -cleanup {\n    destroy .t2\n} -result {-window {} {} {} {}}\n\ntest textWind-3.10 {EmbWinConfigure procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.3\n    .t window configure 1.3 -window .t\n} -returnCodes error -result {can't embed .t in .t}\n\ntest textWind-3.11 {EmbWinConfigure procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    # This test checks for various errors when the text claims\n    # a window away from itself.\n    .t insert 1.0 \"Some sample text\"\n    button .t.b -text \"Hello!\"\n    .t window create 1.4 -window .t.b\n    .t window create 1.6 -window .t.b\n    update\n    .t index .t.b\n} -result {1.6}\n\n#\n# COMMON TEST SETUP\n#\n\n.t delete 1.0 end\nframe .f -width 10 -height 20 -bg $color\n.t window create 1.0 -window .f\n\ntest textWind-4.1 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align baseline\n    .t window configure 1.0 -align\n} -result {-align {} {} center baseline}\ntest textWind-4.2 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align bottom\n    .t window configure 1.0 -align\n} -result {-align {} {} center bottom}\ntest textWind-4.3 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align center\n    .t window configure 1.0 -align\n} -result {-align {} {} center center}\ntest textWind-4.4 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align top\n    .t window configure 1.0 -align\n} -result {-align {} {} center top}\ntest textWind-4.5 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align top\n    .t window configure 1.0 -align gorp\n} -returnCodes error -result {bad align \"gorp\": must be baseline, bottom, center, or top}\ntest textWind-4.6 {AlignParseProc and AlignPrintProc procedures} -body {\n    .t window configure 1.0 -align top\n    catch {.t window configure 1.0 -align gorp}\n    .t window configure 1.0 -align\n} -result {-align {} {} center top}\n\ntest textWind-5.1 {EmbWinStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    destroy .f\n    .t index .f\n} -returnCodes error -result {bad text index \".f\"}\n\ntest textWind-5.2 {EmbWinStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    destroy .f\n    catch {.t index .f}\n    list [.t bbox 1.2] [.t bbox 1.3]\n} -result [list \\\n    [list [xchar 2] [expr {[yline 1]+$fixedHeight/2}] 0 0] \\\n    [list [xchar 2] [yline 1] $fixedWidth $fixedHeight]]\n\ntest textWind-5.3 {EmbWinStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -align bottom\n    .t window configure 1.2 -window .f\n    update\n    destroy .f\n    .t index .f\n} -returnCodes error -result {bad text index \".f\"}\n\ntest textWind-5.4 {EmbWinStructureProc procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -align bottom\n    .t window configure 1.2 -window .f\n    update\n    destroy .f\n    catch {.t index .f}\n    list [.t bbox 1.2] [.t bbox 1.3]\n} -result [list \\\n    [list [xchar 2] [yline 2] 0 0] \\\n    [list [xchar 2] [yline 1] $fixedWidth $fixedHeight]]\n\ntest textWind-5.5 {EmbWinStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.2 -create {frame .f -width 10 -height 20 -bg $color}\n    update\n    .t window configure 1.2 -create {frame .f -width 20 -height 10 -bg $color}\n    destroy .f\n    update\n    list [catch {.t index .f} msg] $msg [.t bbox 1.2] [.t bbox 1.3]\n} -result [list 0 1.2 \\\n    [list [xchar 2] [expr {[yline 1]+($fixedHeight-10)/2}] 20 10] \\\n    [list [expr {[xchar 2]+20}] [yline 1] $fixedWidth $fixedHeight]]\n\ntest textWind-6.1 {EmbWinRequestProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n    set result {}\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    lappend result [.t bbox 1.2] [.t bbox 1.3]\n    .f configure -width 25 -height 30\n    lappend result [.t bbox 1.2] [.t bbox 1.3]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 2] [yline 1] 10 20] \\\n    [list [expr {[xchar 2]+10}] [expr {[yline 1]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight] \\\n    [list [xchar 2] [yline 1] 25 30] \\\n    [list [expr {[xchar 2]+25}] [expr {[yline 1]+(30-$fixedHeight)/2}] $fixedWidth $fixedHeight]]\n\ntest textWind-7.1 {EmbWinLostContentProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    place .f -in .t -x 100 -y 50\n    update\n    list [winfo geom .f] [.t bbox 1.2]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    10x20+[expr {[bo]+100}]+[expr {[bo]+50}] \\\n    [list [xchar 2] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-7.2 {EmbWinLostContentProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .t.f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .t.f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .t.f\n    update\n    place .t.f -x 100 -y 50\n    update\n    list [winfo geom .t.f] [.t bbox 1.2]\n} -cleanup {\n    destroy .t.f\n} -result [list \\\n    10x20+[expr {[bo]+100}]+[expr {[bo]+50}] \\\n    [list [xchar 2] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-8.1 {EmbWinDeleteProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    bind .f <Destroy> {set x destroyed}\n    set x XXX\n    .t delete 1.2\n    list $x [.t bbox 1.2] [.t bbox 1.3] [winfo exists .f]\n} -result [list destroyed \\\n    [list [xchar 2] [yline 1] $fixedWidth $fixedHeight] \\\n    [list [xchar 3] [yline 1] $fixedWidth $fixedHeight] \\\n    0]\n\ntest textWind-8.2 {EmbWinDeleteProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    bind .f <Destroy> {set x destroyed}\n    set x XXX\n    .t delete 1.2\n    .t index .f\n} -returnCodes error -result {bad text index \".f\"}\n\ntest textWind-9.1 {EmbWinCleanupProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\\nA second line.\"\n    frame .f -width 10 -height 20 -bg $color\n    .t window create 2.3 -window .f\n    .t delete 1.5 2.1\n    .t index .f\n} -cleanup {\n    destroy .f\n} -result {1.7}\n\ntest textWind-10.1 {EmbWinLayoutProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.5 -create {\n\tframe .f -width 10 -height 20 -bg $color\n    }\n    update\n    list [winfo exists .f] [winfo width .f] [winfo height .f] [.t index .f]\n} -cleanup {\n    destroy .f\n} -result {1 10 20 1.5}\n\ntest textWind-10.2 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    proc bgerror args {\n\tglobal msg\n\tset msg $args\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.5 -create {\n\terror \"couldn't create window\"\n    }\n    set msg xyzzy\n    update\n    list $msg [.t bbox 1.5]\n} -cleanup {\n    rename bgerror {}\n} -result [list \\\n    {{couldn't create window}} \\\n    [list [xchar 5] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-10.3 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    proc bgerror args {\n\tglobal msg\n\tset msg $args\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.5 -create {\n\tconcat gorp\n    }\n    set msg xyzzy\n    update\n    list $msg [.t bbox 1.5]\n} -cleanup {\n    rename bgerror {}\n} -result [list \\\n    {{bad window path name \"gorp\"}} \\\n    [list [xchar 5] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-10.4 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    destroy .t.f\n    proc bgerror args {\n\tglobal msg\n\tlappend msg $args\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    set msg {}\n    after idle {\n\t.t window create 1.5 -create {\n\t    frame .t.f\n\t    frame .t.f.f -width 10 -height 20 -bg $color\n\t}\n    }\n    set count 0\n    while {([llength $msg] < 2) && ($count < 100)} {\n\tupdate\n\tincr count\n\t.t bbox 1.5\n\tafter 10\n    }\n    lappend msg [.t bbox 1.5] [winfo exists .t.f.f]\n} -cleanup {\n    destroy .t.f\n    rename bgerror {}\n} -result [list \\\n    {{can't embed .t.f.f relative to .t}} {{window name \"f\" already exists in parent}} \\\n    [list [xchar 5] [expr {[yline 1]+$fixedHeight/2}] 0 0] \\\n    1]\n\ntest textWind-10.5 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    destroy .t.f\n    proc bgerror args {\n\tglobal msg\n\tif {$msg eq \"\"} {\n\t    lappend msg $args\n\t}\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    set msg {}\n    .t window create 1.5 -create {\n\tframe .t.f\n\tframe .t.f.f -width 10 -height 20 -bg $color\n    }\n    update\n    lappend msg [winfo exists .t.f.f]\n} -cleanup {\n    destroy .t.f\n    rename bgerror {}\n} -result {{{can't embed .t.f.f relative to .t}} 1}\n\ntest textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    proc bgerror args {\n\tglobal msg\n\tif {[lsearch -exact $msg $args] < 0} {\n\t    lappend msg $args\n\t}\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    update\n    .t window create 1.5 -create {\n\tconcat .t\n    }\n    set msg {}\n    update\n    lappend msg [.t bbox 1.5]\n} -cleanup {\n    rename bgerror {}\n} -result [list \\\n    {{can't embed .t relative to .t}} \\\n    [list [xchar 5] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    destroy .t2\n    proc bgerror args {\n\tglobal msg\n\tlappend msg $args\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.5 -create {\n\ttoplevel .t2 -width 100 -height 150\n\twm geom .t2 +0+0\n\tconcat .t2\n    }\n    set msg {}\n    update idletasks ; after 100 ; update\n    lappend msg [.t bbox 1.5]\n} -cleanup {\n    rename bgerror {}\n} -result [list \\\n    {{can't embed .t2 relative to .t}} {{window name \"t2\" already exists in parent}} \\\n    [list [xchar 5] [expr {[yline 1]+$fixedHeight/2}] 0 0]]\n\ntest textWind-10.8 {EmbWinLayoutProc procedure, error in creating window} -setup {\n    .t delete 1.0 end\n    destroy .t2\n    proc bgerror args {\n\tglobal msg\n\tlappend msg $args\n    }\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.5 -create {\n\ttoplevel .t2 -width 100 -height 150\n\twm geom .t2 +0+0\n\tconcat .t2\n    }\n    set msg {}\n    update\n    set i 0\n    while {[llength $msg] == 1 && [incr i] < 200} { update }\n    return $msg\n} -cleanup {\n    destroy .t2\n    rename bgerror {}\n} -result {{{can't embed .t2 relative to .t}} {{window name \"t2\" already exists in parent}}}\n\ntest textWind-10.9 {EmbWinLayoutProc procedure, steal window from self} -setup {\n    .t delete 1.0 end\n    destroy .t.b\n} -body {\n    .t insert 1.0 ABCDEFGHIJKLMNOP\n    button .t.b -text \"Hello!\"\n    .t window create 1.5 -window .t.b\n    update\n    .t window create 1.3 -create {concat .t.b}\n    update\n    .t index .t.b\n} -cleanup {\n    destroy .t.b\n} -result {1.3}\n\ntest textWind-10.10 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap char\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width [expr {([.t cget -width]-12)*$fixedWidth-1}] -height 20 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 12] [yline 1] [xw [expr {[.t cget -width]-12}]] 20] \\\n    [list [xchar 0] [expr {[yline 1]+20}] $fixedWidth $fixedHeight]]\n\ntest textWind-10.11 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap char\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width [expr {([.t cget -width]-12)*$fixedWidth}] -height 20 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    update\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 12] [yline 1] [xw [expr {[.t cget -width]-12}]] 20] \\\n    [list [xchar 0] [expr {[yline 1]+20}] $fixedWidth $fixedHeight]]\n\ntest textWind-10.12 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap char\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width [expr {([.t cget -width]-12)*$fixedWidth+1}] -height 20 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    update\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 0] [yline 2] [expr {[xw [expr {[.t cget -width]-12}]]+1}] 20] \\\n    [list [expr {[xchar 0]+[expr {[xw [expr {[.t cget -width]-12}]]+1}]}] [expr {[yline 2]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]]\n\ntest textWind-10.13 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width [expr {([.t cget -width]-12)*$fixedWidth+5}] -height 20 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    update\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 12] [yline 1] [xw [expr {[.t cget -width]-12}]] 20] \\\n    {}]\n\ntest textWind-10.14 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width [expr {([.t cget -width]-12)*$fixedWidth+5}] -height 220 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    update\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 12] [yline 1] [xw [expr {[.t cget -width]-12}]] [expr {[.t cget -height]*$fixedHeight}]] \\\n    {}]\n\ntest textWind-10.15 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap char\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 250 -height 220 -bg $color -bd 2 -relief raised\n    .t window create 1.12 -window .f\n    update\n    list [.t bbox .f] [.t bbox 1.13]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    [list [xchar 0] [yline 2] [xw [.t cget -width]] [expr {([.t cget -height]-1)*$fixedHeight}]] \\\n    {}]\n\ntest textWind-11.1 {EmbWinDisplayProc procedure, geometry transforms} -setup {\n    .t delete 1.0 end\n    destroy .f\n    place forget .t\n    pack .t\n    # Make sure the Text is mapped before we start\n    update\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    pack forget .t\n    place .t -x 30 -y 50\n    update\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.12 -window .f\n    update\n    winfo geom .f\n} -cleanup {\n    destroy .f\n    place forget .t\n} -result [list 30x20+[expr {[xchar 12]+30}]+[expr {[yline 1]+50}]]\n\ntest textWind-11.2 {EmbWinDisplayProc procedure, geometry transforms} -setup {\n    .t delete 1.0 end\n    destroy .t.f\n    place forget .t\n    pack .t\n    # Make sure the Text is mapped before we start\n    update\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    pack forget .t\n    place .t -x 30 -y 50\n    update\n    frame .t.f -width 30 -height 20 -bg $color\n    .t window create 1.12 -window .t.f\n    update\n    winfo geom .t.f\n} -cleanup {\n    destroy .t.f\n    place forget .t\n    pack .t\n} -result [list 30x20+[xchar 12]+[yline 1]]\n\ntest textWind-11.3 {EmbWinDisplayProc procedure, configuration optimization} -setup {\n    .t delete 1.0 end\n    destroy .f\n    place forget .t\n    pack .t\n    # Make sure the Text is mapped before we start\n    update\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.12 -window .f\n    update\n    bind .f <Configure> {set x \".f configured\"}\n    set x {no configures}\n    .t delete 1.0\n    .t insert 1.0 \"X\"\n    update\n    return $x\n} -cleanup {\n    destroy .f\n    place forget .t\n    pack .t\n} -result {no configures}\n\ntest textWind-11.4 {EmbWinDisplayProc procedure, horizontal scrolling} -setup {\n    .t delete 1.0 end\n    destroy .f .f2\n} -body {\n    .t insert 1.0 \"xyzzy\\nFirst window here: \"\n    .t configure -wrap none\n    frame .f -width 30 -height 20 -bg $color\n    .t window create end -window .f\n    .t insert end \" and second here: \"\n    frame .f2 -width 40 -height 10 -bg $color\n    .t window create end -window .f2\n    .t insert end \" with junk after it.\"\n    .t xview moveto 0\n    .t xview scroll 5 units\n    update\n    list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] [winfo ismapped .f2]\n} -cleanup {\n    destroy .f .f2\n} -result [list 1 \\\n    30x20+[xchar 14]+[yline 2] \\\n    [list [xchar 14] [yline 2] 30 20] \\\n    0]\n\ntest textWind-11.5 {EmbWinDisplayProc procedure, horizontal scrolling} -setup {\n    .t delete 1.0 end\n    destroy .f .f2\n} -body {\n    .t insert 1.0 \"xyzzy\\nFirst window here: \"\n    .t configure -wrap none\n    frame .f -width 30 -height 20 -bg $color\n    .t window create end -window .f\n    .t insert end \" and second here: \"\n    frame .f2 -width 40 -height 10 -bg $color\n    .t window create end -window .f2\n    .t insert end \" with junk after it.\"\n    update\n    .t xview moveto 0\n    .t xview scroll 25 units\n    update\n    list [winfo ismapped .f] [winfo ismapped .f2] [winfo geom .f2] [.t bbox .f2]\n} -cleanup {\n  destroy .f .f2\n  .t configure -wrap char\n} -result [list 0 1 \\\n    40x10+[expr {[xchar [expr {37-25}]]+30}]+[expr {[yline 2]+(20-10)/2}] \\\n    [list [expr {[xchar [expr {37-25}]]+30}] [expr {[yline 2]+(20-10)/2}] 40 10]]\n\ntest textWind-12.1 {EmbWinUndisplayProc procedure, mapping/unmapping} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    bind .f <Map> {lappend x mapped}\n    bind .f <Unmap> {lappend x unmapped}\n    set x created\n    update\n    lappend x modified\n    .t delete 1.0\n    update\n    lappend x replaced\n    .t window configure .f -window {}\n    .t delete 1.1\n    update\n    .t window create 1.4 -window .f\n    update\n    lappend x off-screen\n    .t configure -wrap none\n    .t insert 1.0 \"Enough text to make the line run off-screen\"\n    update\n    return $x\n} -cleanup {\n    destroy .f\n} -result {created mapped modified replaced unmapped mapped off-screen unmapped}\n\ntest textWind-13.1 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align top -padx 2 -pady 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x5+[expr {[xchar 2]+2}]+[expr {[yline 1]+1}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1}] 5 5]]\n\ntest textWind-13.2 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align center -padx 2 -pady 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x5+[expr {[xchar 2]+2}]+[expr {[yline 1]+1+(($fixedHeight-7)/2)}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1+(($fixedHeight-7)/2)}] 5 5]]\n\ntest textWind-13.3 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align baseline -padx 2 -pady 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x5+[expr {[xchar 2]+2}]+[expr {[yline 1]+1+($fixedAscent-6)}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1+($fixedAscent-6)}] 5 5]]\n\ntest textWind-13.4 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align bottom -padx 2 -pady 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x5+[expr {[xchar 2]+2}]+[expr {[yline 1]+1+($fixedHeight-7)}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1+($fixedHeight-7)}] 5 5]]\n\ntest textWind-13.5 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align top -padx 2 -pady 1 -stretch 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x[expr {$fixedHeight-2}]+[expr {[xchar 2]+2}]+[expr {[yline 1]+1}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1}] 5 [expr {$fixedHeight-2}]]]\n\ntest textWind-13.6 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align center -padx 2 -pady 1 -stretch 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x[expr {$fixedHeight-2}]+[expr {[xchar 2]+2}]+[expr {[yline 1]+1}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1}] 5 [expr {$fixedHeight-2}]]]\n\ntest textWind-13.7 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align baseline -padx 2 -pady 1 -stretch 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x[expr {$fixedAscent-1}]+[expr {[xchar 2]+2}]+[expr {[yline 1]+1}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1}] 5 [expr {$fixedAscent-1}]]]\n\ntest textWind-13.8 {EmbWinBboxProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align bottom -padx 2 -pady 1 -stretch 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f\n} -result [list \\\n    5x[expr {$fixedHeight-2}]+[expr {[xchar 2]+2}]+[expr {[yline 1]+1}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+1}] 5 [expr {$fixedHeight-2}]]]\n\ntest textWind-13.9 {EmbWinBboxProc procedure, spacing options} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -spacing1 5 -spacing3 2\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 5 -height 5 -bg $color\n    .t window create 1.2 -window .f -align center -padx 2 -pady 1\n    update\n    list [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    .t configure -spacing1 0 -spacing3 0\n    destroy .f\n} -result [list \\\n    5x5+[expr {[xchar 2]+2}]+[expr {[yline 1]+5+(($fixedHeight-5)/2)}] \\\n    [list [expr {[xchar 2]+2}] [expr {[yline 1]+5+(($fixedHeight-5)/2)}] 5 5]]\n\ntest textWind-14.1 {EmbWinDelayedUnmap procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    bind .f <Unmap> {lappend x unmapped}\n    set x modified\n    .t insert 1.0 x\n    lappend x removed\n    .t window configure .f -window {}\n    lappend x updated\n    update\n    return $x\n} -cleanup {\n    destroy .f\n} -result {modified removed unmapped updated}\n\ntest textWind-14.2 {EmbWinDelayedUnmap procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    bind .f <Unmap> {lappend x unmapped}\n    set x modified\n    .t insert 1.0 x\n    lappend x deleted\n    .t delete .f\n    lappend x updated\n    update\n    return $x\n} -cleanup {\n    destroy .f\n} -result {modified deleted updated}\n\ntest textWind-14.3 {EmbWinDelayedUnmap procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t insert 1.0 \"Some sample text\\nAnother line\\n3\\n4\\n5\\n6\\n7\\n8\\n9\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.2 -window .f\n    update\n    .t yview 2.0\n    set result [winfo ismapped .f]\n    update ; after 10\n    list $result [winfo ismapped .f]\n} -cleanup {\n    destroy .f\n} -result {1 0}\n\ntest textWind-14.4 {EmbWinDelayedUnmap procedure} -setup {\n    .t delete 1.0 end\n    destroy .t.f\n} -body {\n    .t insert 1.0 \"Some sample text\\nAnother line\\n3\\n4\\n5\\n6\\n7\\n8\\n9\"\n    frame .t.f -width 30 -height 20 -bg $color\n    .t window create 1.2 -window .t.f\n    update\n    .t yview 2.0\n    set result [winfo ismapped .t.f]\n    update\n    list $result [winfo ismapped .t.f]\n} -cleanup {\n    destroy .t.f\n} -result {1 0}\n\ntest textWind-15.1 {TkTextWindowIndex procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t index .foo\n} -returnCodes error -result {bad text index \".foo\"}\n\ntest textWind-15.2 {TkTextWindowIndex procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -spacing1 0 -spacing2 0 -spacing3 0 \\\n\t-wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.6 -window .f\n    .t tag add a 1.1\n    .t tag add a 1.3\n    list [.t index .f] [.t bbox 1.7]\n} -cleanup {\n    destroy .f\n} -result [list 1.6 \\\n    [list [expr {[xchar 6]+30}] [expr {[yline 1]+(20-$fixedHeight)/2}] $fixedWidth $fixedHeight]]\n\ntest textWind-16.1 {EmbWinTextStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f\n} -body {\n    .t configure -wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.6 -window .f\n    update\n    pack forget .t\n    update\n    winfo ismapped .f\n} -cleanup {\n    pack .t\n} -result 0\n\ntest textWind-16.2 {EmbWinTextStructureProc procedure} -setup {\n    .t delete 1.0 end\n    destroy .f .f2\n} -body {\n    .t configure -spacing1 0 -spacing2 0 -spacing3 0 \\\n\t-wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .f -width 30 -height 20 -bg $color\n    .t window create 1.6 -window .f\n    update\n    set result {}\n    lappend result [winfo geom .f] [.t bbox .f]\n    frame .f2 -width 150 -height 30 -bd 2 -relief raised\n    pack .f2 -before .t\n    update\n    lappend result [winfo geom .f] [.t bbox .f]\n} -cleanup {\n    destroy .f .f2\n} -result [list \\\n    30x20+[expr {[xchar 6]}]+[yline 1] \\\n    [list [expr {[xchar 6]}] [yline 1] 30 20] \\\n    30x20+[expr {[xchar 6]}]+[expr {[yline 1]+30}] \\\n    [list [expr {[xchar 6]}] [yline 1] 30 20]]\n\ntest textWind-16.3 {EmbWinTextStructureProc procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t configure -wrap none\n    .t insert 1.0 \"Some sample text\"\n    .t window create 1.6\n    update\n    pack forget .t\n    update\n} -cleanup {\n    pack .t\n} -result {}\n\ntest textWind-16.4 {EmbWinTextStructureProc procedure} -setup {\n    .t delete 1.0 end\n} -body {\n    .t configure -spacing1 0 -spacing2 0 -spacing3 0 \\\n\t-wrap none\n    .t insert 1.0 \"Some sample text\"\n    frame .t.f -width 30 -height 20 -bg $color\n    .t window create 1.6 -window .t.f\n    update\n    pack forget .t\n    update\n    list [winfo ismapped .t.f] [.t bbox .t.f]\n} -cleanup {\n    pack .t\n} -result [list 1 [list [expr {[xchar 6]}] [yline 1] 30 20]]\n\ntest textWind-17.1 {peer widgets and embedded windows} -setup {\n    destroy .t .tt .f\n} -body {\n    pack [text .t]\n    .t insert end \"Line 1\"\n    frame .f -width 20 -height 10 -bg blue\n    .t window create 1.3 -window .f\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    update\n    destroy .t .tt\n    winfo exists .f\n} -result 0\n\ntest textWind-17.2 {peer widgets and embedded windows} -setup {\n    destroy .t .f .tt\n} -body {\n    pack [text .t]\n    .t insert end \"Line 1\\nLine 2\"\n    frame .f -width 20 -height 10 -bg blue\n    .t window create 1.4 -window .f\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    update\n    destroy .t\n    .tt.t insert 1.0 \"foo\"\n    update\n    destroy .tt\n} -result {}\n\ntest textWind-17.3 {peer widget and -create} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    update\n    .t window create 1.2 -create {frame %W.f -width 10 -height 20 -bg blue}\n    update\n    destroy .t .tt\n} -result {}\n\ntest textWind-17.4 {peer widget deleted one window shouldn't delete others} -setup {\n    destroy .t .tt\n    set res {}\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -create {frame %W.f -width 10 -height 20 -bg blue}\n    update\n    destroy .tt\n    lappend res [.t get 1.2]\n    update\n    lappend res [.t get 1.2]\n} -cleanup {\n    destroy .t\n} -result {{} {}}\n\ntest textWind-17.5 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -create {frame %W.f -width 10 -height 20 -bg blue}\n    update\n    list [.t window cget 1.2 -window] [.tt.t window cget 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n} -result {.t.f .tt.t.f}\n\ntest textWind-17.6 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -create {frame %W.f -width 10 -height 20 -bg blue}\n    update\n    list [.t window configure 1.2 -window] \\\n\t[.tt.t window configure 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n}  -result {{-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}}\n\ntest textWind-17.7 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -window [frame .t.f -width 10 -height 20 -bg blue]\n    update\n    list [.t window cget 1.2 -window] [.tt.t window cget 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n}  -result {.t.f {}}\n\ntest textWind-17.8 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -window [frame .t.f -width 10 -height 20 -bg blue]\n    update\n    list [.t window configure 1.2 -window] \\\n\t[.tt.t window configure 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n}  -result {{-window {} {} {} .t.f} {-window {} {} {} {}}}\n\ntest textWind-17.9 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    .t window create 1.2 -window [frame .t.f -width 10 -height 20 -bg blue]\n    update\n    .tt.t window configure 1.2 -window [frame .tt.t.f -width 10 -height 20 -bg red]\n    list [.t window configure 1.2 -window] [.tt.t window configure 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n}  -result {{-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}}\n\ntest textWind-17.10 {peer widget window configuration} -setup {\n    destroy .t .tt\n} -body {\n    set res {}\n    pack [text .t]\n    .t delete 1.0 end\n    .t insert 1.0 \"Some sample text\"\n    toplevel .tt\n    pack [.t peer create .tt.t]\n    update\n    .t window create 1.2 -window [frame .t.f -width 10 -height 20 -bg blue]\n    update\n    # There is a blue window in the main widget .t but not in the peer .tt.t\n    lappend res [.t window cget 1.2 -window]\n    lappend res [.tt.t window cget 1.2 -window]\n    # Insert a green window in the peer. Warning: the blue window previously\n    # inserted in .t at index 1.2 will now be found in .t at index 1.3\n    # The underlying linked segments are common in a text widget and its peers.\n    .tt.t window create 1.2 -window [frame .tt.t.f -width 25 -height 20 -bg green]\n    update\n    lappend res [.t window cget 1.2 -window]\n    lappend res [.t window cget 1.3 -window]\n    # In the peer, the green window still is at 1.2, and there is no window at 1.3\n    lappend res [.tt.t window cget 1.2 -window]\n    lappend res [.tt.t window cget 1.3 -window]\n    # Insert a red window in .t at index 1.2. This replaces the blue window originally at 1.2\n    # in .t, because the green window inserted in the peer is not visible from .t, therefore\n    # the embedded window found at index 1.2 in .t is the one originally at 1.2 in .t, i.e.\n    # the blue one\n    .t window configure 1.2 -create {destroy %W.f ; update ; frame %W.f -width 50 -height 7 -bg red}\n    update\n    # The main widget .t still has a window named .t.f at 1.2. This is NOT the blue\n    # frame but the red frame from the -create script, which bears the same name.\n    lappend res [.t window cget 1.2 -window]\n    # The peer still has its green .tt.t.f at 1.2\n    lappend res [.tt.t window cget 1.2 -window]\n    # When removing the -window option the create script plays, therefore .t still has\n    # the red frame .t.f at 1.2\n    .t window configure 1.2 -window {}\n    update\n    lappend res [.t window cget 1.2 -window]\n    # The -create script associated to index 1.2 applies to all peers (that's the reason\n    # why the manual states that \"If multiple peer widgets are in use, it is usually simpler\n    # to use the -create option if embedded windows are desired in each peer.\"). Therefore\n    # when removing the -window option in the peer, the -create script is run, which replaces\n    # the green frame by the red one named as per the -create script, i.e. .tt.t.f\n    .tt.t window configure 1.2 -window {}\n    update\n    lappend res [.tt.t window cget 1.2 -window]\n} -cleanup {\n    destroy .tt .t\n}  -result {.t.f {} {} .t.f .tt.t.f {} .t.f .tt.t.f .t.f .tt.t.f}\n\ntest textWind-18.1 {embedded window deletion triggered by a script bound to <Map>} -setup {\n    catch {destroy .t .f .f2}\n} -body {\n    pack [text .t]\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Line $i\\n\"}\n    .t window create end -window [frame .f -background red -width 80 -height 80]\n    .t window create end -window [frame .f2 -background blue -width 80 -height 80]\n    bind .f <Map> {.t delete .f}\n    update\n    # this shall not crash (bug 1501749)\n    after 100 {.t yview end}\n    tkwait visibility .f2\n    after 200\n    update\n} -cleanup {\n    destroy .t .f .f2\n} -result {}\n\ntest textWind-18.2 {text widget deletion triggered by a script bound to embedded window mapping} -setup {\n    catch {destroy .t .f}\n} -body {\n    pack [text .t]\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Line $i\\n\"}\n    .t window create end -window [frame .f -background red -width 80 -height 80]\n    bind .f <Map> {destroy .t}\n    update\n    # this shall not crash (bug 1501749)\n    after 100 {.t yview end}\n    tkwait window .t\n} -cleanup {\n    destroy .t .f\n} -result {}\n\ntest textWind-18.3 {embedded window destruction in cascade} -setup {\n    catch {destroy .t .f}\n    set x 0\n} -body {\n    pack [text .t]\n    button .t.b1\n    .t window create 1.0 -window .t.b1\n    bind .t.b1 <Destroy> {destroy .t.b2 ; set x 1}\n    button .t.b2\n    .t window create 2.0 -window .t.b2\n    update\n    # this shall not crash (bug 54fe7a5e71)\n    after 100 {.t delete 1.0 end}\n    tkwait variable x\n} -cleanup {\n    destroy .t .f\n} -result {}\n\n\n#\n# TESTFILE CLEANUP\n#\n\noption clear\ntestutils forget text\ncleanupTests\n"
  },
  {
    "path": "tests/tk.test",
    "content": "# This file is a Tcl script to test the \"tk\" command, except for:\n# - \"tk attribtable\", which has its tests in the test file attribtable.test\n# - \"tk busy\", which has its tests in the test file busy.test\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 2002 ActiveState Corporation.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint testprintf [llength [info command testprintf]]\n\n#\n# TESTS\n#\n\ntest tk-1.1 {tk command: general} -body {\n    tk\n} -returnCodes error -result {wrong # args: should be \"tk subcommand ?arg ...?\"}\ntest tk-1.2 {tk command: general} -constraints {aquaOrWin32 failsOnXQuartz} -body {\n    tk xyz\n} -returnCodes error -result {unknown or ambiguous subcommand \"xyz\": must be accessible, appname, attribtable, busy, caret, fileicon, fontchooser, inactive, print, scaling, sysnotify, systray, useinputmethods, or windowingsystem}\n\n#\n# COMMON TEST SETUP\n#\n\n# Value stored to restore default settings after 2.* tests\nset appname [tk appname]\n\ntest tk-2.1 {tk command: appname} -body {\n    tk appname xyz abc\n} -returnCodes error -result {wrong # args: should be \"tk appname ?newName?\"}\ntest tk-2.2 {tk command: appname} -body {\n    tk appname foobazgarply\n} -result {foobazgarply}\ntest tk-2.3 {tk command: appname} -constraints {unix notMacCI} -body {\n    tk appname bazfoogarply\n    expr {[lsearch -exact [winfo interps] [tk appname]] >= 0}\n} -result 1\ntest tk-2.4 {tk command: appname} -body {\n    tk appname [tk appname]\n} -result [tk appname]\n\n#\n# COMMON TEST CLEANUP\n#\ntk appname $appname\n\n#\n# COMMON TEST SETUP\n#\n\n# Value stored to restore default settings after 3.* tests\nset scaling [tk scaling]\n\ntest tk-3.1 {tk command: scaling} -body {\n    tk scaling -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest tk-3.2 {tk command: scaling: get current} -body {\n    tk scaling 1\n    format %.2g [tk scaling]\n}  -result 1\ntest tk-3.3 {tk command: scaling: get current} -body {\n    tk scaling -displayof . 1.25\n    format %.3g [tk scaling]\n}  -result 1.25\ntest tk-3.4 {tk command: scaling: set new} -body {\n    tk scaling xyz\n} -returnCodes error -result {expected floating-point number but got \"xyz\"}\ntest tk-3.5 {tk command: scaling: set new} -body {\n    tk scaling -displayof . xyz\n} -returnCodes error -result {expected floating-point number but got \"xyz\"}\ntest tk-3.6 {tk command: scaling: set new} -body {\n    tk scaling 1\n    format %.2g [tk scaling]\n} -result 1\ntest tk-3.7 {tk command: scaling: set new} -body {\n    tk scaling -displayof . 1.25\n    format %.3g [tk scaling]\n} -result 1.25\ntest tk-3.8 {tk command: scaling: negative} -body {\n    tk scaling -1\n    expr {[tk scaling] > 0}\n} -result 1\ntest tk-3.9 {tk command: scaling: too big} -body {\n    tk scaling 1000000\n    expr {[tk scaling] < 10000}\n} -result 1\ntest tk-3.10 {tk command: scaling: widthmm} -body {\n    tk scaling 1.25\n    expr {int((25.4*[winfo screenwidth .])/(72*1.25) + 0.5) \\\n\t- [winfo screenmmwidth .]}\n} -result 0\ntest tk-3.11 {tk command: scaling: heightmm} -body {\n    tk scaling 1.25\n    expr {int((25.4*[winfo screenheight .])/(72*1.25) + 0.5) \\\n\t- [winfo screenmmheight .]}\n} -result 0\n\n#\n# COMMON TEST CLEANUP\n#\ntk scaling $scaling\n\n#\n# COMMON TEST SETUP\n#\n\n# Value stored to restore default settings after 4.* tests\nset useim [tk useinputmethods]\n\ntest tk-4.1 {tk command: useinputmethods} -body {\n    tk useinputmethods -displayof\n} -returnCodes error -result {value for \"-displayof\" missing}\ntest tk-4.2 {tk command: useinputmethods: get current} -body {\n    tk useinputmethods no\n} -cleanup {\n    tk useinputmethods $useim\n} -result 0\ntest tk-4.3 {tk command: useinputmethods: get current} -body {\n    tk useinputmethods no\n    tk useinputmethods -displayof .\n} -cleanup {\n    tk useinputmethods $useim\n} -result 0\ntest tk-4.4 {tk command: useinputmethods: set new} -body {\n    tk useinputmethods xyz\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\ntest tk-4.5 {tk command: useinputmethods: set new} -body {\n    tk useinputmethods -displayof . xyz\n} -returnCodes error -result {expected boolean value but got \"xyz\"}\ntest tk-4.6 {tk command: useinputmethods: set new} -body {\n    # This isn't really a test, but more of a check... The answer is what was\n    # given, because we may be on a Unix system that doesn't have the XIM\n    # stuff\n    if {[tk useinputmethods 1] == 0} {\n\tputs \"this wish doesn't have XIM (X Input Methods) support\"\n    }\n    return $useim\n} -result $useim\ntest tk-4.7 {tk command: useinputmethods: set new} -constraints win -body {\n    # Mac and Windows don't have X Input Methods, so this should always return\n    # 0\n    tk useinputmethods 1\n} -cleanup {\n    tk useinputmethods $useim\n} -result 0\n\ntest tk-5.1 {tk caret} -body {\n    tk caret\n} -returnCodes error -result {wrong # args: should be \"tk caret window ?-x x? ?-y y? ?-height height?\"}\ntest tk-5.2 {tk caret} -body {\n    tk caret bogus\n} -returnCodes error -result {bad window path name \"bogus\"}\ntest tk-5.3 {tk caret} -body {\n    tk caret . -foo\n} -returnCodes error -result {bad caret option \"-foo\": must be -x, -y, or -height}\ntest tk-5.4 {tk caret} -body {\n    tk caret . -x 0 -y\n} -returnCodes error -result {wrong # args: should be \"tk caret window ?-x x? ?-y y? ?-height height?\"}\ntest tk-5.5 {tk caret} -body {\n    tk caret . -x 10 -y 11 -h 12; tk caret .\n} -result {-height 12 -x 10 -y 11}\ntest tk-5.6 {tk caret} -body {\n    tk caret . -x 20 -y 25 -h 30; tk caret . -hei\n} -result 30\n\n# tk inactive\ntest tk-6.1 {tk inactive} -body {\n    string is integer [tk inactive]\n} -result 1\ntest tk-6.2 {tk inactive reset} -body {\n    tk inactive reset\n} -returnCodes ok -match glob -result *\ntest tk-6.3 {tk inactive wrong argument} -body {\n    tk inactive foo\n} -returnCodes 1 -result {bad option \"foo\": must be reset}\ntest tk-6.4 {tk inactive too many arguments} -body {\n    tk inactive reset foo\n} -returnCodes 1 -result {wrong # args: should be \"tk inactive ?-displayof window? ?reset?\"}\ntest tk-6.5 {tk inactive} -body {\n    tk inactive reset\n    update\n    after 100\n    set i [tk inactive]\n    expr {$i < 0 || ( $i > 90 && $i < 300 )}\n} -result 1\n\ntest tk-7.1 {tk inactive in a safe interpreter} -body {\n# tk inactive in safe interpreters\n    safe::interpCreate foo\n    safe::loadTk foo\n    foo eval {tk inactive}\n} -cleanup {\n    ::safe::interpDelete foo\n} -result -1\ntest tk-7.2 {tk inactive reset in a safe interpreter} -body {\n# tk inactive in safe interpreters\n    safe::interpCreate foo\n    safe::loadTk foo\n    foo eval {tk inactive reset}\n} -cleanup {\n    ::safe::interpDelete foo\n} -returnCodes 1 -result {resetting the user inactivity timer is not allowed in a safe interpreter}\n\ntest tk-8.1 {Test for ticket [1cc44617e2], see if TCL_LL_MODIFIER works as expected on all platforms} -constraints testprintf -body {\n    testprintf -21474836480\n} -result {-21474836480 18446744052234715136}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/ttk/all.tcl",
    "content": "# all.tcl --\n#\n# This file contains a top-level script to run all of the ttk\n# tests. Execute it by invoking \"source all.tcl\" when running tktest\n# in this directory.\n#\n# Copyright © 2007 the Tk developers.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n#\n# REQUIREMENTS\n#\npackage require tk ;# This is the Tk test suite; fail early if no Tk!\npackage require tcltest 2.2\n\n#\n# TCLTEST CONFIGURATION\n#\n\n# Set defaults for the Tk test suite\ntcltest::configure -singleproc 1\n\n# Handle command line parameters\nif {[llength $argv] & 1} {\n    puts stderr \"error: the number of command line parameters must be even (name - value pairs).\"\n    exit 1\n}\nset ignoredOptions [list -testdir]\nset ignoredIndices [list ]\nset index 0\nforeach {key value} $argv {\n    if {$key in $ignoredOptions} {\n\tlappend ignoredIndices $index\n\tputs stderr \"warning: the Tk test suite ignores the option \\\"$key\\\" on the command line.\"\n    }\n    incr index 2\n}\nset tcltestOptions $argv\nforeach index [lreverse $ignoredIndices] {\n    set tcltestOptions [lreplace $tcltestOptions $index [expr {$index + 1}]]\n}\ntcltest::configure {*}$tcltestOptions\nunset ignoredIndices ignoredOptions index tcltestOptions\n\n# Set tcltest options that are not user-configurable for the Tk test suite\ntcltest::configure -testdir [file normalize [file dirname [info script]]]\n\n# Determine test files to skip\nset skipFiles [tcltest::configure -notfile]\nif {\"vista\" ni [ttk::style theme names]} {\n    lappend skipFiles vsapi.test\n    tcltest::configure -notfile [lsort -unique $skipFiles]\n}\nunset skipFiles\n\n#\n# RUN ALL TESTS\n#\n\n# Note: the environment variable ERROR_ON_FAILURES is set by Github CI\nif {[tcltest::runAllTests] && [info exists env(ERROR_ON_FAILURES)]} {\n    exit 1\n}\n"
  },
  {
    "path": "tests/ttk/checkbutton.test",
    "content": "#\n# ttk::checkbutton widget tests.\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest checkbutton-1.1 \"Checkbutton check\" -body {\n    pack [ttk::checkbutton .cb -text \"TCheckbutton\" -variable cb]\n}\ntest checkbutton-1.2 \"Checkbutton invoke\" -body {\n    .cb invoke\n    list [set ::cb] [.cb instate selected]\n} -result [list 1 1]\ntest checkbutton-1.3 \"Checkbutton reinvoke\" -body {\n    .cb invoke\n    list [set ::cb] [.cb instate selected]\n} -result [list 0 0]\n\ntest checkbutton-1.4 \"Checkbutton variable\" -body {\n    set result []\n    set ::cb 1\n    lappend result [.cb instate selected]\n    set ::cb 0\n    lappend result [.cb instate selected]\n} -result {1 0}\n\ntest checkbutton-1.5 \"Unset checkbutton variable\" -body {\n    set result []\n    unset ::cb\n    lappend result [.cb instate alternate] [info exists ::cb]\n    set ::cb 1\n    lappend result [.cb instate alternate] [info exists ::cb]\n} -result {1 0 0 1}\n\n# See #1257319\ntest checkbutton-1.6 \"Checkbutton default variable\" -body {\n    destroy .cb ; unset -nocomplain {} ; set result [list]\n    ttk::checkbutton .cb -onvalue on -offvalue off\n    lappend result [.cb cget -variable] [info exists .cb] [.cb state]\n    .cb invoke\n    lappend result [info exists .cb] [set .cb] [.cb state]\n    .cb invoke\n    lappend result [info exists .cb] [set .cb] [.cb state]\n} -result [list .cb 0 alternate   1 on selected  1 off {}]\n\n# Bug [109865fa01]\ntest checkbutton-1.7 \"Button destroyed by click\" -body {\n    proc destroy_button {} {\n\tdestroy .top\n    }\n    toplevel .top\n    ttk::menubutton .top.mb -text Button -style TLabel\n    bind .top.mb <ButtonRelease-1> destroy_button\n    pack .top.mb\n    focus -force .top.mb\n    update\n    event generate .top.mb <Button-1>\n    event generate .top.mb <ButtonRelease-1>\n    update  ; # shall not trigger error  invalid command name \".top.b\"\n} -result {}\n\n# Bug [fa8de77936]\ntest checkbutton-1.8 \"Empty -variable\" -body {\n    # shall simply not crash\n    ttk::checkbutton .cbev -variable {}\n    .cbev invoke\n} -cleanup {\n    destroy .cbev\n} -result {}\n\ntest checkbutton-2.1 \"style command\" -body {\n    ttk::checkbutton .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TCheckbutton TCheckbutton}\ntest checkbutton-2.2 \"style command\" -body {\n    ttk::style configure customStyle.TCheckbutton\n    ttk::checkbutton .w -style customStyle.TCheckbutton\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TCheckbutton customStyle.TCheckbutton TCheckbutton}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/combobox.test",
    "content": "#\n# ttk::combobox widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest combobox-1.0 \"Combobox tests -- setup\" -body {\n    ttk::combobox .cb\n} -result .cb\n\ntest combobox-1.1 \"Bad -values list\" -body {\n    .cb configure -values \"bad \\{list\"\n} -result \"unmatched open brace in list\" -returnCodes error\n\ntest combobox-1.end \"Combobox tests -- cleanup\" -body {\n    destroy .cb\n}\n\ntest combobox-2.0 \"current command\" -body {\n    ttk::combobox .cb -values [list a b c d e a]\n    expr {[.cb current]<0}\n} -result 1\n\ntest combobox-2.1 \"current -- set index\" -body {\n    .cb current 5\n    .cb get\n} -result a\n\ntest combobox-2.2 \"current -- change -values\" -body {\n    .cb configure -values [list c b a d e]\n    .cb current\n} -result 2\n\ntest combobox-2.3 \"current -- change value\" -body {\n    .cb set \"b\"\n    .cb current\n} -result 1\n\ntest combobox-2.4 \"current -- value not in list\" -body {\n    .cb set \"z\"\n    expr {[.cb current]<0}\n} -result 1\n\ntest combobox-2.5 \"current -- set to end index\" -body {\n    .cb configure -values [list a b c d e thelastone]\n    .cb current end\n    .cb get\n} -result thelastone\n\ntest combobox-2.6 \"current -- set to unknown index\" -body {\n    .cb configure -values [list a b c d e]\n    .cb current notanindex\n} -returnCodes error -result {bad index \"notanindex\"}\n\ntest combobox-2.7 {current -- set to 0 index when empty [bug 924835c36d]} -body {\n    .cb configure -values {}\n    .cb current 0\n} -returnCodes error -result {index \"0\" out of range}\n\ntest combobox-2.8 \"current -- set to end index in an empty combobox\" -body {\n    .cb configure -values {}\n    .cb current end\n} -returnCodes error -result {index \"end\" out of range}\n\ntest combobox-2.end \"Cleanup\" -body { destroy .cb }\n\ntest combobox-3 \"Read postoffset value dynamically from current style\" -body {\n    ttk::combobox .cb -values [list a b c] -style \"DerivedStyle.TCombobox\"\n    pack .cb -expand true -fill both\n    update idletasks\n    ttk::style configure DerivedStyle.TCombobox -postoffset [list 25 0 0 0]\n    if {[tk windowingsystem] eq \"aqua\"} {\n\tafter 500 {\n\t    testpressbutton [expr {[winfo rootx .cb] + 25}] [expr {[winfo rooty .cb] + 25}]\n\t}\n    }\n    ttk::combobox::Post .cb\n    expr {[winfo rootx .cb.popdown] - [winfo rootx .cb]}\n} -result 25 -cleanup {\n    destroy .cb\n}\n\ntest combobox-1890211 \"ComboboxSelected event after listbox unposted\" \\\n    -constraints {notAqua} -body {\n    # whitebox test...\n    pack [ttk::combobox .cb -values [list a b c]]\n    update idletasks\n    set result [list]\n    bind .cb <<ComboboxSelected>> {\n\tlappend result Event [winfo ismapped .cb.popdown] [.cb get]\n    }\n    lappend result Start 0 [.cb get]\n    ttk::combobox::Post .cb\n    lappend result Post [winfo ismapped .cb.popdown] [.cb get]\n    .cb.popdown.f.l selection clear 0 end; .cb.popdown.f.l selection set 1\n    ttk::combobox::LBSelected .cb.popdown.f.l\n    lappend result Select [winfo ismapped .cb.popdown] [.cb get]\n    update\n    set result\n} -result [list Start 0 {} Post 1 {} Select 0 b Event 0 b] -cleanup {\n    destroy .cb\n}\n\ntest combobox-4.1 \"style command\" -body {\n    ttk::combobox .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TCombobox TCombobox}\ntest combobox-4.2 \"style command\" -body {\n    ttk::style configure customStyle.TCombobox\n    ttk::combobox .w -style customStyle.TCombobox\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TCombobox customStyle.TCombobox TCombobox}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/entry.test",
    "content": "#\n# ttk::entry widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script \"main.tcl\", which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import entry scroll\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# Some of the tests raise background errors;\n# override default bgerror to catch them.\n#\nvariable bgerror \"\"\nproc bgerror {error} {\n    variable bgerror $error\n    variable bgerrorInfo $::errorInfo\n    variable bgerrorCode $::errorCode\n}\n\n#\n# TESTS\n#\n\ntest entry-1.1 \"Create entry widget\" -body {\n    ttk::entry .e\n} -result .e\n\ntest entry-1.2 \"Insert\" -body {\n    .e insert end abcde\n    .e get\n} -result abcde\n\ntest entry-1.3 \"Selection\" -body {\n    .e selection range 1 3\n    selection get\n} -result bc\n\ntest entry-1.4 \"Delete\" -body {\n    .e delete 1 3\n    .e get\n} -result ade\n\ntest entry-1.5 \"Deletion - insert cursor\" -body {\n    .e insert end abcde\n    .e icursor 0\n    .e delete 0 end\n    .e index insert\n} -result 0\n\ntest entry-1.6 \"Deletion - insert cursor at end\" -body {\n    .e insert end abcde\n    .e icursor end\n    .e delete 0 end\n    .e index insert\n} -result 0\n\ntest entry-1.7 \"Deletion - insert cursor in the middle \" -body {\n    .e insert end abcde\n    .e icursor 3\n    .e delete 0 end\n    .e index insert\n} -result 0\n\ntest entry-1.8 \"Index is between 0 and end\" -body {\n    .e delete 0 end\n    .e insert end abcde\n    set res [list [.e index -1] [.e index -4] [.e index 999]]\n} -result {0 0 5}\n\ntest entry-1.done \"Cleanup\" -body { destroy .e }\n\n# Scrollbar tests.\n\ntest entry-2.1 \"Create entry before scrollbar\" -body {\n    pack [ttk::entry .te -xscrollcommand [list .tsb set]] \\\n\t-expand true -fill both\n    pack [ttk::scrollbar .tsb -orient horizontal -command [list .te xview]] \\\n\t-expand false -fill x\n}  -cleanup {destroy .te .tsb}\n\ntest entry-2.1.1 \"Create entry before scrollbar - scrollbar catches up\" -body {\n    pack [ttk::entry .te -xscrollcommand [list .tsb set]] \\\n\t    -expand true -fill both\n    .te insert end [string repeat \"abc\" 50]\n    catch {update} ; # error triggers because the -xscrollcommand callback\n\t\t     # errors out: invalid command name \".tsb\"\n    focus -force .te ; # needed on some systems such as Ubuntu (see ticket [3c2a3a988f])\n    pack [ttk::scrollbar .tsb -orient horizontal -command [list .te xview]] \\\n\t    -expand false -fill x\n    update ; # no error\n    set res [expr {[lindex [.tsb get] 1] < 1}] ; # scrollbar did update\n} -result 1 -cleanup {destroy .te .tsb}\n\ntest entry-2.2 \"Initial scroll position\" -body {\n    ttk::entry .e -font fixed -width 5 -xscrollcommand setScrollInfo\n    .e insert end \"0123456789\"\n    pack .e;\n    set timeout [after 500 {set scrollInfo \"timeout\"}]\n    vwait scrollInfo\n    set scrollInfo\n} -cleanup {\n    destroy .e\n    after cancel $timeout\n} -result {0.0 0.5}\n# NOTE: result can vary depending on font.\n\n# Bounding box / scrolling tests.\ntest entry-3.0 \"Series 3 setup\" -body {\n    ttk::style theme use default\n    variable fixed TkFixedFont\n    variable cw [font measure $fixed a]\n    variable ch [font metrics $fixed -linespace]\n    variable bd 3\t;# border + padding + extra space for focus ring\n    variable ux [font measure $fixed 乎]\n\n    pack [ttk::entry .e -font $fixed -width 20]\n    update\n}\n\ntest entry-3.1 \"bbox widget command\" -body {\n    .e delete 0 end\n    .e bbox 0\n} -result [list $bd $bd 0 $ch]\n\ntest entry-3.2 \"xview\" -body {\n    .e delete 0 end;\n    .e insert end [string repeat \"0\" 40]\n    set result [.e xview]\n} -result {0.0 0.5}\n\ntest entry-3.3 \"xview\" -body {\n    .e delete 0 end;\n    .e insert end abcdefghijklmnopqrstuvwxyz\n    .e xview end\n    set result [.e index @0]\n} -result 7\n\ntest entry-3.4 \"xview\" -body {\n    .e delete 0 end;\n    .e insert end abcdefghijklmnopqrstuvwxyz\n    .e xview moveto 1.0\n    set result [.e index @0]\n} -result 7\n\ntest entry-3.5 \"xview\" -body {\n    .e delete 0 end;\n    .e insert end abcdefghijklmnopqrstuvwxyz\n    .e xview scroll 5 units\n    set result [.e index @0]\n} -result 5\n\ntest entry-3.6 \"xview\" -body {\n    .e delete 0 end;\n    .e insert end [string repeat abcdefghijklmnopqrstuvwxyz 5]\n    .e xview scroll 2 pages\n    set result [.e index @0]\n} -result 40\n\ntest entry-3.last \"Series 3 cleanup\" -body {\n    destroy .e\n}\n\n# Selection tests:\n\ntest entry-4.0 \"Selection test - setup\" -body {\n    ttk::entry .e\n    .e insert end asdfasdf\n    .e selection range 0 end\n}\n\ntest entry-4.1 \"Selection test\" -body {\n    selection get\n} -result asdfasdf\n\ntest entry-4.2 \"Disable -exportselection\" -body {\n    .e configure -exportselection false\n    selection get\n} -returnCodes error -result \"PRIMARY selection doesn't exist*\" -match glob\n\ntest entry-4.3 \"Reenable -exportselection\" -body {\n    .e configure -exportselection true\n    selection get\n} -result asdfasdf\n\ntest entry-4.4 \"Force selection loss\" -body {\n    selection own .\n    .e index sel.first\n} -returnCodes error -result \"selection isn't in widget .e\"\n\ntest entry-4.5 \"Allow selection changes if readonly\" -body {\n    .e delete 0 end\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state readonly\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -result {2 4}\n\ntest entry-4.6 \"Disallow selection changes if disabled\" -body {\n    .e delete 0 end\n    .e insert end 0123456789\n    .e selection range 0 end\n    .e configure -state disabled\n    .e selection range 2 4\n    .e configure -state normal\n    list [.e index sel.first] [.e index sel.last]\n} -result {0 10}\n\ntest entry-4.7 {sel.first and sel.last gravity} -body {\n    set result [list]\n    .e delete 0 end\n    .e insert 0 0123456789\n    .e select range 2 6\n    .e insert 2 XXX\n    lappend result [.e index sel.first] [.e index sel.last]\n    .e insert 6 YYY\n    lappend result [.e index sel.first] [.e index sel.last] [.e get]\n} -result {5 9 5 12 01XXX2YYY3456789}\n\n# Self-destruct tests.\n\ntest entry-5.1 {widget deletion while active} -body {\n    destroy .e\n    pack [ttk::entry .e]\n    update\n    .e config -xscrollcommand { destroy .e }\n    update idletasks\n    winfo exists .e\n} -result 0\n\n# TODO: test killing .e in -validatecommand, -invalidcommand, variable trace;\n\n\n# -textvariable tests.\n\ntest entry-6.1 {Update linked variable in write trace} -body {\n    catch {destroy .e}\n    set textVar \"\"\n    trace add variable textVar write override\n    ttk::entry .e -textvariable textVar\n    .e insert 0 \"Some text\"\n    set result [list $textVar [.e get]]\n    set result\n} -result {12345 12345} -cleanup {\n    trace remove variable textVar write override\n    unset textVar\n    destroy .e\n}\n\ntest entry-6.2 {-textvariable tests} -body {\n    set result [list]\n    ttk::entry .e -textvariable textVar\n    set textVar \"text\"\n    lappend result [.e get]\n    unset textVar\n    lappend result [.e get]\n    .e insert end \"newtext\"\n    lappend result [.e get] $textVar\n} -result [list \"text\" \"\" \"newtext\" \"newtext\"] -cleanup {\n    destroy .e\n    unset -nocomplain textVar\n}\n\ntest entry-7.1 {Bad style options} -body {\n    ttk::style theme create entry-7.1 -settings {\n\tttk::style configure TEntry -foreground BadColor\n\tttk::style map TEntry -foreground {readonly AnotherBadColor}\n\tttk::style map TEntry -font {readonly ABadFont}\n\tttk::style map TEntry \\\n\t    -selectbackground {{} BadColor} \\\n\t    -selectforeground {{} BadColor} \\\n\t    -insertcolor {{} BadColor}\n    }\n    pack [ttk::entry .e -text \"Don't crash\"]\n    ttk::style theme use entry-7.1\n    update\n    .e selection range 0 end\n    update\n    .e state readonly;\n    update\n} -cleanup { destroy .e ; ttk::style theme use default }\n\ntest entry-8.1 \"Unset linked variable\" -body {\n    variable foo \"bar\"\n    pack [ttk::entry .e -textvariable foo]\n    unset foo\n    .e insert end \"baz\"\n    list [.e cget -textvariable] [.e get] [set foo]\n} -result [list foo \"baz\" \"baz\"] -cleanup { destroy .e }\n\ntest entry-8.2 \"Unset linked variable by deleting namespace\" -body {\n    namespace eval ::test  { variable foo \"bar\" }\n    pack [ttk::entry .e -textvariable ::test::foo]\n    namespace delete ::test\n    .e insert end \"baz\"\t\t;# <== error here\n    list [.e cget -textvariable] [.e get] [set foo]\n} -returnCodes error -result \"*parent namespace doesn't exist*\" -match glob\n# '-result [list ::test::foo \"baz\" \"baz\"]' would also be sensible,\n# but Tcl namespaces don't work that way.\n\ntest entry-8.2a \"Followup to test 8.2\" -body {\n    .e cget -textvariable\n} -result ::test::foo -cleanup { destroy .e }\n# For 8.2a, -result {} would also be sensible.\n\ntest entry-9.1 \"Index range invariants\" -setup {\n    # See bug#1721532 for discussion\n    proc entry-9.1-trace {n1 n2 op} {\n\tset ::V NO!\n    }\n    variable V\n    trace add variable V write entry-9.1-trace\n    ttk::entry .e -textvariable V\n} -body {\n    set result [list]\n    .e insert insert a ; lappend result [.e index insert] [.e index end]\n    .e insert insert b ; lappend result [.e index insert] [.e index end]\n    .e insert insert c ; lappend result [.e index insert] [.e index end]\n    .e insert insert d ; lappend result [.e index insert] [.e index end]\n    .e insert insert e ; lappend result [.e index insert] [.e index end]\n    set result\n} -result [list 1 3  2 3  3 3  3 3  3 3] -cleanup {\n    unset V\n    destroy .e\n}\n\ntest entry-10.1 {configuration option: \"-placeholder\"} -setup {\n    pack [ttk::entry .e]\n} -body {\n    .e configure -placeholder {Some text}\n    .e cget -placeholder\n} -cleanup {\n    destroy .e\n} -result {Some text}\n\ntest entry-10.2 {configuration option: \"-placeholderforeground\"} -setup {\n    pack [ttk::entry .e]\n} -body {\n    .e configure -placeholder {Some text} -placeholderforeground red\n    .e cget -placeholderforeground\n} -cleanup {\n    destroy .e\n} -result {red}\n\ntest entry-10.3 {styling option: \"-placeholderforeground\"} -setup {\n    pack [ttk::entry .e]\n} -body {\n    set current [ttk::style configure TEntry -placeholderforeground]\n    ttk::style configure TEntry -placeholderforeground blue\n    set res [ttk::style configure TEntry -placeholderforeground]\n    ttk::style configure TEntry -placeholderforeground $current\n    set res\n} -cleanup {\n    destroy .e\n} -result {blue}\n\ntest entry-11.1 {Bug [2830360fff] - Don't loose invalid at focus events} -setup {\n    pack [ttk::entry .e]\n    update\n} -body {\n    .e state invalid\n    set res [.e state]\n    event generate .e <FocusOut>\n    lappend res [.e state]\n} -result {invalid invalid} -cleanup {\n    destroy .e\n}\ntest entry-11.2 {Bug [2a32225cd1] - Navigation in a password made of several words} -setup {\n    destroy .e\n    pack [ttk::entry .e -show *]\n    update\n    set res {}\n} -body {\n    .e insert end \"A sample password made of several words\"\n    .e icursor end\n    event generate .e <<PrevWord>>  ; # shall move insert to index 0\n    .e delete insert end\n    lappend res [.e get]\n    .e insert end \"A sample password made of several words\"\n    .e icursor 2\n    event generate .e <<NextWord>>  ; # shall move insert to index end\n    .e delete 0 insert\n    lappend res [.e get]\n} -cleanup {\n    destroy .e\n} -result {{} {}}\n\ntest entry-12.1 \"style command\" -body {\n    ttk::entry .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TEntry TEntry}\ntest entry-12.2 \"style command\" -body {\n    ttk::style configure customStyle.TEntry\n    ttk::entry .w -style customStyle.TEntry\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TEntry customStyle.TEntry TEntry}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget entry scroll\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/image.test",
    "content": "#\n# Tests for images in various ttk widgets\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest image-1.1 \"Bad image element\" -body {\n    ttk::style element create BadImage image badimage\n} -returnCodes error -result {image \"badimage\" does not exist}\n\ntest image-1.2 \"Duplicate element\" -setup {\n    image create photo test.element -width 10 -height 10\n    ttk::style element create testElement image test.element\n} -body {\n    ttk::style element create testElement image test.element\n} -returnCodes error -result \"Duplicate element testElement\"\n\ntest image-2.0 \"Deletion of displayed image (label)\" -setup {\n     image create photo test.image -width 10 -height 10\n} -body {\n    pack [set w [ttk::label .ttk_image20 -image test.image]]\n    tkwait visibility $w\n    image delete test.image\n    update\n} -cleanup {\n    destroy .ttk_image20\n} -result {}\n\ntest image-2.1 \"Deletion of displayed image (checkbutton)\" -setup {\n     image create photo test.image -width 10 -height 10\n} -body {\n    pack [set w [ttk::checkbutton .ttk_image21 -image test.image]]\n    tkwait visibility $w\n    image delete test.image\n    update\n} -cleanup {\n    destroy .ttk_image21\n} -result {}\n\ntest image-2.2 \"Deletion of displayed image (radiobutton)\" -setup {\n     image create photo test.image -width 10 -height 10\n} -body {\n    pack [set w [ttk::radiobutton .ttk_image22 -image test.image]]\n    tkwait visibility $w\n    image delete test.image\n    update\n} -cleanup {\n    destroy .ttk_image22\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/labelframe.test",
    "content": "#\n# ttk::labelframe widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest labelframe-1.0 \"Setup\" -body {\n    pack [ttk::labelframe .lf] -expand true -fill both\n}\n\ntest labelframe-2.1 \"Can't use indirect descendant as labelwidget\" -body {\n    ttk::frame .lf.t\n    ttk::checkbutton .lf.t.cb\n    .lf configure -labelwidget .lf.t.cb\n} -returnCodes error -result {cannot add \".lf.t.cb\" as content of \".lf\"} \\\n  -cleanup { destroy .lf.t } ;\n\ntest labelframe-2.2 \"Can't use toplevel as labelwidget\" -body {\n    toplevel .lf.t\n    .lf configure -labelwidget .lf.t\n} -returnCodes error -result {cannot add \".lf.t\" as content of \".lf\"} \\\n  -cleanup { destroy .lf.t } ;\n\ntest labelframe-2.3 \"Can't use non-windows as -labelwidget\" -body {\n    .lf configure -labelwidget BogusWindowName\n} -returnCodes error -result {bad window path name \"BogusWindowName\"}\n\ntest labelframe-2.4 \"Can't use nonexistent-windows as -labelwidget\" -body {\n    .lf configure -labelwidget .nosuchwindow\n} -returnCodes error -result {bad window path name \".nosuchwindow\"}\n\n\n###\n# See also series labelframe-4.x\n#\ntest labelframe-3.1 \"Add child content\" -body {\n    checkbutton .lf.cb -text \"abcde\"\n    .lf configure -labelwidget .lf.cb\n    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]\n} -result [list 1 labelframe]\n\ntest labelframe-3.2 \"Remove child content\" -body {\n    .lf configure -labelwidget {}\n    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]\n} -result [list 0 {}]\n\ntest labelframe-3.3 \"Re-add child content\" -body {\n    .lf configure -labelwidget .lf.cb\n    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]\n} -result [list 1 labelframe]\n\ntest labelframe-3.4 \"Re-manage child content\" -body {\n    pack .lf.cb -side right\n    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] [.lf cget -labelwidget]\n} -result [list 1 pack {}]\n\ntest labelframe-3.5 \"Re-add child content\" -body {\n    .lf configure -labelwidget .lf.cb\n    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]\n} -result [list 1 labelframe]\n\ntest labelframe-3.6 \"Destroy child content\" -body {\n    destroy .lf.cb\n    .lf cget -labelwidget\n} -result {}\n\n###\n# Re-run series labelframe-3.x with nonchild content.\n#\n# @@@ ODDITY, 14 Nov 2005:\n# @@@ labelframe-4.1 fails if .cb is a [checkbutton],\n# @@@ but seems to succeed if it's some other widget class.\n# @@@ I suspect a race condition; unable to track it down ATM.\n#\n# @@@ FOLLOWUP: This *may* have been caused by a bug in ManagerIdleProc\n# @@@ (see manager.c r1.11). There's still probably a race condition in here.\n#\ntest labelframe-4.1 \"Add nonchild content\" -body {\n    checkbutton .cb -text \"abcde\"\n    .lf configure -labelwidget .cb\n    update\n    list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb]\n\n} -result [list 1 1 labelframe]\n\ntest labelframe-4.2 \"Remove nonchild content\" -body {\n    .lf configure -labelwidget {}\n    update;\n    list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb]\n} -result [list 0 0 {}]\n\ntest labelframe-4.3 \"Re-add nonchild content\" -body {\n    .lf configure -labelwidget .cb\n    list [update; winfo viewable .cb] [winfo manager .cb]\n} -result [list 1 labelframe]\n\ntest labelframe-4.4 \"Re-manage nonchild content\" -body {\n    pack .cb -side right\n    list [update; winfo viewable .cb] \\\n\t[winfo manager .cb] \\\n\t[.lf cget -labelwidget]\n} -result [list 1 pack {}]\n\ntest labelframe-4.5 \"Re-add nonchild content\" -body {\n    .lf configure -labelwidget .cb\n    list [update; winfo viewable .cb] \\\n\t[winfo manager .cb] \\\n\t[.lf cget -labelwidget]\n} -result [list 1 labelframe .cb]\n\ntest labelframe-4.6 \"Destroy nonchild content\" -body {\n    destroy .cb\n    .lf cget -labelwidget\n} -result {}\n\ntest labelframe-5.0 \"Cleanup\" -body {\n    destroy .lf\n}\n\n# 1342876 -- labelframe should raise sibling -labelwidget above self.\n#\ntest labelframe-6.1 \"Stacking order\" -body {\n    toplevel .t\n    pack [ttk::checkbutton .t.x1]\n    pack [ttk::labelframe .t.lf -labelwidget [ttk::label .t.lb]]\n    pack [ttk::checkbutton .t.x2]\n    winfo children .t\n} -cleanup {\n    destroy .t\n} -result [list .t.x1 .t.lf .t.lb .t.x2]\n\ntest labelframe-7.1 \"style command\" -body {\n    ttk::labelframe .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TLabelframe TLabelframe}\ntest labelframe-7.2 \"style command\" -body {\n    ttk::style configure customStyle.TLabelframe\n    ttk::labelframe .w -style customStyle.TLabelframe\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TLabelframe customStyle.TLabelframe TLabelframe}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/layout.test",
    "content": "#\n# Tests for the \"ttk::style layout\" command\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest layout-1.1 \"Size computations for mixed-orientation layouts\" -body {\n    ttk::style theme use default\n\n    set block [image create photo -width 10 -height 10]\n    ttk::style element create block image $block\n    ttk::style layout Blocks {\n\tborder -children { block } -side left\n\tborder -children { block } -side top\n\tborder -children { block } -side bottom\n    }\n    ttk::style configure Blocks -borderwidth 1 -relief raised\n    ttk::button .b -style Blocks\n\n    pack .b -expand true -fill both\n\n    list [winfo reqwidth .b] [winfo reqheight .b]\n\n} -cleanup { destroy .b } -result [list 24 24]\n\ntest layout-2 \"Empty -children not allowed\" -body {\n    ttk::style layout Test.Tentry {Entry.field -children {}}\n} -returnCodes error -result {Invalid -children value}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/notebook.test",
    "content": "#\n# ttk::notebook widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc inoperative {args} {}\n\n#\n# TESTS\n#\n\ntest notebook-1.0 \"Setup\" -body {\n    ttk::notebook .nb\n} -result .nb\n\n#\n# Error handling tests:\n#\ntest notebook-1.1 \"Cannot add ancestor\" -body {\n    .nb add .\n} -returnCodes error -result \"*\" -match glob\n\n\ninoperative test notebook-1.2 \"Cannot add siblings\" -body {\n    # This is legal now\n    .nb add [frame .sibling]\n} -returnCodes error -result \"*\" -match glob\n\ntest notebook-1.3 \"Cannot add toplevel\" -body {\n    .nb add [toplevel .nb.t]\n} -cleanup {\n    destroy .t.nb\n} -returnCodes error -result {cannot add \".nb.t\" as content of \".nb\"}\n\ntest notebook-1.4 \"Try to select bad tab\" -body {\n    .nb select @6000,6000\n} -returnCodes error -match glob -result \"* not found\"\n\n#\n# Now add stuff:\n#\ntest notebook-2.0 \"Add children\" -body {\n    pack .nb -expand true -fill both\n    .nb add [frame .nb.foo] -text \"Foo\"\n    pack [label .nb.foo.l -text \"Foo\"]\n\n    .nb add [frame .nb.bar -relief raised -borderwidth 2] -text \"Bar\"\n    pack [label .nb.bar.l -text \"Bar\"]\n\n    .nb tabs\n} -result [list .nb.foo .nb.bar]\n\ntest notebook-2.1 \"select pane\" -body {\n    .nb select .nb.foo\n    update\n    list [winfo viewable .nb.foo] [winfo viewable .nb.bar] [.nb index current]\n} -result [list 1 0 0]\n\ntest notebook-2.2 \"select another pane\" -body {\n    .nb select 1\n    update\n    list [winfo viewable .nb.foo] [winfo viewable .nb.bar] [.nb index current]\n} -result [list 0 1 1]\n\ntest notebook-2.3 \"tab - get value\" -body {\n    .nb tab .nb.foo -text\n} -result \"Foo\"\n\ntest notebook-2.4 \"tab - set value\" -body {\n    .nb tab .nb.foo -text \"Changed Foo\"\n    .nb tab .nb.foo -text\n} -result \"Changed Foo\"\n\ntest notebook-2.5 \"tab - get all options\" -body {\n    .nb tab .nb.foo -underline 0\n    .nb tab .nb.foo\n} -result [list \\\n    -padding 0 -sticky nsew \\\n    -state normal -text \"Changed Foo\" -image \"\" -compound {} -underline 0]\n\ntest notebook-4.1 \"Test .nb index end\" -body {\n    .nb index end\n} -result 2\n\ntest notebook-4.2 \"'end' is not a selectable index\" -body {\n    .nb select end\n} -returnCodes error -result \"*\" -match glob\n\ntest notebook-4.3 \"Select index out of range\" -body {\n    .nb select 2\n} -returnCodes error -result \"*\" -match glob\n\ntest notebook-4.4 \"-padding option\" -body {\n    .nb configure -padding \"5 5 5 5\"\n}\n\ntest notebook-4.end \"Cleanup test suite 1-4.*\" -body { destroy .nb }\n\ntest notebook-5.1 \"Virtual events\" -body {\n    toplevel .t\n    update\n    set ::events [list]\n    pack [set nb [ttk::notebook .t.nb]] -expand true -fill both; update\n    bind .t <<NotebookTabChanged>> { lappend events changed %W }\n\n    $nb add [frame $nb.f1] ;  # triggers <<NotebookTabChanged>> (first tab gets autoselected)\n    $nb add [frame $nb.f2]\n    $nb add [frame $nb.f3]\n    update\n    $nb select $nb.f1 ; # does not trigger <<NotebookTabChanged>> (tab to select is already selected)\n    update; set events\n} -result [list changed .t.nb]\n\ntest notebook-5.2 \"Virtual events, continued\" -body {\n    set events [list]\n    $nb select $nb.f3\n    update ; set events\n} -result [list changed .t.nb]\n# OR: [list deselected .t.nb.f1 selected .t.nb.f3 changed .t.nb]\n\ntest notebook-5.3 \"Disabled tabs\" -body {\n    set events [list]\n    $nb tab $nb.f2 -state disabled\n    $nb select $nb.f2\n    update\n    list $events [$nb index current]\n} -result [list [list] 2]\n\ntest notebook-5.4 \"Reenable tab\" -body {\n    set events [list]\n    $nb tab $nb.f2 -state normal\n    $nb select $nb.f2\n    update\n    list $events [$nb index current]\n} -result [list [list changed .t.nb] 1]\n\ntest notebook-5.end \"Virtual events, cleanup\" -body { destroy .t }\n\ntest notebook-6.0 \"Select hidden tab\" -setup {\n    set nb [ttk::notebook .nb]\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    $nb tab $nb.f1 -state hidden\n    lappend result [$nb tab $nb.f1 -state]\n    $nb select $nb.f1\n    lappend result [$nb tab $nb.f1 -state]\n} -result [list hidden normal]\n\ntest notebook-6.1 \"Hide selected tab\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb hide $nb.f2\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    lappend result [winfo ismapped $nb.f3]\n} -result [list 1 1 2 0 1]\n\n# See 1370833\ntest notebook-6.2 \"Forget selected tab\" -setup {\n    ttk::notebook .n\n    pack .n\n    label .n.l -text abc\n    .n add .n.l\n} -body {\n    update\n    after 100\n    .n forget .n.l\n    update\t\t;# Yowch!\n} -cleanup {\n    destroy .n\n} -result {}\n\ntest notebook-6.3 \"Hide first tab when it's the current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f1\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f1]\n    $nb hide $nb.f1\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f1]\n} -result [list 0 1 1 0]\n\ntest notebook-6.4 \"Forget first tab when it's the current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f1\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f1]\n    $nb forget $nb.f1\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f1]\n} -result [list 0 1 0 0]\n\ntest notebook-6.5 \"Hide last tab when it's the current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f3\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f3]\n    $nb hide $nb.f3\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f3]\n} -result [list 2 1 1 0]\n\ntest notebook-6.6 \"Forget a middle tab when it's the current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb forget $nb.f2\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 1 0]\n\ntest notebook-6.7 \"Hide a middle tab when it's the current\" -setup {\n    pack [set nb [ttk::notebook .nb]]; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb hide $nb.f2\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 2 0]\n\ntest notebook-6.8 \"Forget a non-current tab < current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb forget $nb.f1\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 0 1]\n\ntest notebook-6.9 \"Hide a non-current tab < current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb hide $nb.f1\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 1 1]\n\ntest notebook-6.10 \"Forget a non-current tab > current\" -setup {\n    pack [set nb [ttk::notebook .nb]] ; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb forget $nb.f3\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 1 1]\n\ntest notebook-6.11 \"Hide a non-current tab > current\" -setup {\n    pack [set nb [ttk::notebook .nb]]; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n    $nb hide $nb.f3\n    update idletasks\n    lappend result [$nb index current] [winfo ismapped $nb.f2]\n} -result [list 1 1 1 1]\n\ntest notebook-6.12 \"Hide and re-add a tab\" -setup {\n    pack [set nb [ttk::notebook .nb]]; update\n    $nb add [ttk::frame $nb.f1]\n    $nb add [ttk::frame $nb.f2]\n    $nb add [ttk::frame $nb.f3]\n    $nb select $nb.f2\n} -cleanup  {\n    destroy $nb\n} -body {\n    set result [list]\n    lappend result [$nb index current] [$nb tab $nb.f2 -state]\n    $nb hide $nb.f2\n    update idletasks\n    lappend result [$nb index current] [$nb tab $nb.f2 -state]\n    $nb add $nb.f2\n    update idletasks\n    lappend result [$nb index current] [$nb tab $nb.f2 -state]\n} -result [list 1 normal 2 hidden 2 normal]\n\n#\n# COMMON TEST CLEANUP\n#\nunset nb\n\n#\n# Insert:\n#\ntest notebook-7.0 \"insert - setup\" -body {\n    pack [ttk::notebook .nb]\n    for {set i 0} {$i < 5} {incr i} {\n\t.nb add [ttk::frame .nb.f$i] -text \"$i\"\n    }\n    .nb select .nb.f1\n    list [.nb index current] [.nb tabs]\n} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]]\n\ntest notebook-7.1 \"insert - move backwards\" -body {\n    .nb insert 1 3\n    list [.nb index current] [.nb tabs]\n} -result [list 2 [list .nb.f0 .nb.f3 .nb.f1 .nb.f2 .nb.f4]]\n\ntest notebook-7.2 \"insert - move backwards again\" -body {\n    .nb insert 1 3\n    list [.nb index current] [.nb tabs]\n} -result [list 3 [list .nb.f0 .nb.f2 .nb.f3 .nb.f1 .nb.f4]]\n\ntest notebook-7.3 \"insert - move backwards again\" -body {\n    .nb insert 1 3\n    list [.nb index current] [.nb tabs]\n} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]]\n\ntest notebook-7.4 \"insert - move forwards\" -body {\n    .nb insert 3 1\n    list [.nb index current] [.nb tabs]\n} -result [list 3 [list .nb.f0 .nb.f2 .nb.f3 .nb.f1 .nb.f4]]\n\ntest notebook-7.5 \"insert - move forwards again\" -body {\n    .nb insert 3 1\n    list [.nb index current] [.nb tabs]\n} -result [list 2 [list .nb.f0 .nb.f3 .nb.f1 .nb.f2 .nb.f4]]\n\ntest notebook-7.6 \"insert - move forwards again\" -body {\n    .nb insert 3 1\n    list [.nb index current] [.nb tabs]\n} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]]\n\ntest notebook-7.7a \"insert - current tab undisturbed\" -body {\n    .nb select 0\n    .nb insert 3 1\n    .nb index current\n} -result 0\n\ntest notebook-7.7b \"insert - current tab undisturbed\" -body {\n    .nb select 0\n    .nb insert 1 3\n    .nb index current\n} -result 0\n\ntest notebook-7.7c \"insert - current tab undisturbed\" -body {\n    .nb select 4\n    .nb insert 3 1\n    .nb index current\n} -result 4\n\ntest notebook-7.7d \"insert - current tab undisturbed\" -body {\n    .nb select 4\n    .nb insert 1 3\n    .nb index current\n} -result 4\n\ntest notebook-7.8a \"move tabs - current tab undisturbed - exhaustive\" -body {\n    .nb select .nb.f0\n    foreach i {0 1 2 3 4} {\n\t.nb insert $i .nb.f$i\n    }\n\n    foreach i {0 1 2 3 4} {\n\t.nb select .nb.f$i\n\tforeach j {0 1 2 3 4} {\n\t    foreach k {0 1 2 3 4} {\n\t\t.nb insert $j $k\n\t\tset current [lindex [.nb tabs] [.nb index current]]\n\t\tif {$current ne \".nb.f$i\"} {\n\t\t    error \"($i,$j,$k) current = $current\"\n\t\t}\n\t\t.nb insert $k $j\n\t\tif {[.nb tabs] ne [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]} {\n\t\t    error \"swap $j $k; swap $k $j => [.nb tabs]\"\n\t\t}\n\t    }\n\t}\n    }\n    .nb tabs\n} -result [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]\n\ntest notebook-7.8b \"insert new - current tab undisturbed - exhaustive\" -body {\n    foreach i {0 1 2 3 4} {\n\t.nb select .nb.f$i\n\tforeach j {0 1 2 3 4} {\n.nb select .nb.f$i\n\t    .nb insert $j [frame .nb.newf]\n\t    set current [lindex [.nb tabs] [.nb index current]]\n\t    if {$current ne \".nb.f$i\"} {\n\t\tputs stderr \"new tab at $j, current = $current, expect .nb.f$i\"\n\t    }\n\t    destroy .nb.newf\n\t    if {[.nb tabs] ne [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]} {\n\t\terror \"tabs disturbed\"\n\t    }\n\t}\n    }\n}\n\ntest notebook-7.end \"insert - cleanup\" -body {\n    destroy .nb\n}\n\ntest notebook-1817596-1 \"insert should autoselect first tab\" -body {\n    pack [ttk::notebook .nb]\n    list \\\n\t[.nb insert end [ttk::label .nb.l1 -text One] -text One] \\\n\t[.nb select] \\\n\t;\n} -result [list \"\" .nb.l1] -cleanup { destroy .nb }\n\ntest notebook-1817596-2 \"error in insert should have no effect\" -body {\n    pack [ttk::notebook .nb]\n    .nb insert end [ttk::label .nb.l1]\n    .nb insert end [ttk::label .nb.l2]\n    list \\\n\t[catch { .nb insert .l2 0 -badoption badvalue } err] \\\n\t[.nb tabs] \\\n} -result [list 1 [list .nb.l1 .nb.l2]] -cleanup { destroy .nb }\n\ntest notebook-1817596-3 \"insert/configure\" -body {\n    pack [ttk::notebook .nb]\n    .nb insert end [ttk::label .nb.l0] -text \"L0\"\n    .nb insert end [ttk::label .nb.l1] -text \"L1\"\n    .nb insert end [ttk::label .nb.l2] -text \"XX\"\n    .nb insert 0 2 -text \"L2\"\n\n    list [.nb tabs] [.nb tab 0 -text] [.nb tab 1 -text] [.nb tab 2 -text]\n\n} -result [list [list .nb.l2 .nb.l0 .nb.l1] L2 L0 L1] -cleanup { destroy .nb }\n\ntest notebook-readd-1 \"add same widget twice\" -body {\n    pack [ttk::notebook .nb]\n    .nb add [ttk::button .nb.b1] -text \"Button\"\n    .nb add .nb.b1\n    .nb tabs\n} -result [list .nb.b1] -cleanup { destroy .nb }\n\ntest notebook-readd-2 \"add same widget twice, with options\" -body {\n    pack [ttk::notebook .nb]\n    .nb add [ttk::button .nb.b1] -text \"Tab label\"\n    .nb add .nb.b1 -text \"Changed tab label\"\n    .nb tabs\n} -result [list .nb.b1] -cleanup { destroy .nb }\n\ntest notebook-readd-3 \"insert same widget twice, with options\" -body {\n    pack [ttk::notebook .nb]\n    .nb insert end [ttk::button .nb.b1] -text \"Tab label\"\n    .nb insert end .nb.b1 -text \"Changed tab label\"\n    .nb tabs\n} -result [list .nb.b1] -cleanup { destroy .nb }\n\n\n# See #1343984\ntest notebook-1343984-1 \"don't autoselect on destroy - setup\" -body {\n    ttk::notebook .nb\n    set ::history [list]\n    bind TestFrame <Map> { lappend history MAP %W }\n    bind TestFrame <Destroy> { lappend history DESTROY %W }\n    .nb add [ttk::frame .nb.frame1 -class TestFrame] -text \"Frame 1\"\n    .nb add [ttk::frame .nb.frame2 -class TestFrame] -text \"Frame 2\"\n    .nb add [ttk::frame .nb.frame3 -class TestFrame] -text \"Frame 3\"\n    pack .nb -fill both -expand 1\n    update\n    set ::history\n} -result [list MAP .nb.frame1]\n\ntest notebook-1343984-2 \"don't autoselect on destroy\" -body {\n    set ::history [list]\n    destroy .nb\n    update\n    set ::history\n} -result [list DESTROY .nb.frame1 DESTROY .nb.frame2 DESTROY .nb.frame3]\n\ntest notebook-198376af5a {moving tab position to a different edge} -body {\n    destroy .nb\n    ttk::notebook .nb -width 200 -height 100 -padding 0\n    ttk::frame .nb.f1\n    ttk::frame .nb.f2\n    .nb add .nb.f1 -text \"One\"\n    .nb add .nb.f2 -text \"Two\"\n    pack .nb\n    update\n    ttk::style configure TNotebook -tabposition s\n    update\n    expr {[winfo y .nb.f1] < 10}\n} -result 1\n\ntest notebook-8.1 \"style command\" -body {\n    ttk::notebook .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TNotebook TNotebook}\ntest notebook-8.2 \"style command\" -body {\n    ttk::style configure customStyle.TNotebook\n    ttk::notebook .w -style customStyle.TNotebook\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TNotebook customStyle.TNotebook TNotebook}\n\ntest notebook-9.1 \"move last tab by numerical index\" -body {\n    ::ttk::notebook .n\n    foreach tabs {TabA TabB TabC} {\n\t::ttk::entry .n.[string tolower $tabs]\n\t.n add .n.[string tolower $tabs] -text $tabs\n    }\n   .n insert 0 2  ; # allowed: TabC moves to first tab position\n   .n insert 0 3  ; # not allowed: position 3 is after last tab\n} -cleanup {\n    destroy .n\n} -result {Managed window index \"3\" out of bounds} -returnCodes error\ntest notebook-9.2 \"move first tab to last position by numerical index\" -body {\n    ::ttk::notebook .n\n    foreach tabs {TabA TabB TabC} {\n\t::ttk::entry .n.[string tolower $tabs]\n\t.n add .n.[string tolower $tabs] -text $tabs\n    }\n   .n insert 2 0  ; # allowed: TabA moves to last tab position\n   .n insert 3 0  ; # not allowed: position 3 is after last tab\n} -cleanup {\n    destroy .n\n} -result {Managed window index \"3\" out of bounds} -returnCodes error\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/panedwindow.test",
    "content": "#\n# ttk::panedwindow widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# checkorder --\n#\tEnsure that Y coordinates windows in $winlist are strictly increasing.\n#\nproc checkorder {winlist} {\n    set pos -1\n    set positions [list]\n    foreach win $winlist {\n\tlappend positions [set nextpos [winfo y $win]]\n\tif {$nextpos <= $pos} {\n\t    error \"window $win out of order ($positions)\"\n\t}\n\tset pos $nextpos\n    }\n}\n\nproc propagate-geometry {} { update idletasks }\n\nproc sashpositions {pw} {\n    set positions [list]\n    set npanes [llength [winfo children $pw]]\n    for {set i 0} {$i < $npanes - 1} {incr i} {\n\tlappend positions [$pw sashpos $i]\n    }\n    return $positions\n}\n\n#\n# TESTS\n#\n\n# Basic sanity checks:\n#\ntest panedwindow-1.0 \"Setup\" -body {\n    ttk::panedwindow .pw\n} -result .pw\n\ntest panedwindow-1.0.1 \"Make sure pane 0 command doesn't crash on empty pane - bug e6140f3404\" -body {\n    .pw pane 0\n} -result {Managed window index \"0\" out of bounds} -returnCodes error\n\ntest panedwindow-1.0.2 \"Make sure pane end command doesn't crash on empty pane - bug e6140f3404\" -body {\n    .pw pane end\n} -result {Managed window index \"end\" out of bounds} -returnCodes error\n\ntest panedwindow-1.0.3 \"Make sure forget 0 command doesn't crash on empty pane - bug e6140f3404\" -body {\n    .pw forget 0\n} -result {Managed window index \"0\" out of bounds} -returnCodes error\n\ntest panedwindow-1.0.4 \"Make sure forget end command doesn't crash on empty pane - bug e6140f3404\" -body {\n    .pw forget end\n} -result {Managed window index \"end\" out of bounds} -returnCodes error\n\ntest panedwindow-1.1 \"Make sure empty panedwindow doesn't crash\" -body {\n    pack .pw -expand true -fill both\n    update\n}\n\ntest panedwindow-1.2 \"Add a pane\" -body {\n    .pw add [ttk::frame .pw.f1]\n    winfo manager .pw.f1\n} -result \"panedwindow\"\n\ntest panedwindow-1.3 \"Steal pane\" -body {\n    pack .pw.f1 -side bottom\n    winfo manager .pw.f1\n} -result \"pack\"\n\ntest panedwindow-1.4 \"Make sure empty panedwindow still doesn't crash\" -body {\n    update\n}\n\ntest panedwindow-1.5 \"Remanage pane\" -body {\n    #XXX .pw insert 0 .pw.f1\n    .pw add .pw.f1\n    winfo manager .pw.f1\n} -result \"panedwindow\"\n\ntest panedwindow-1.6 \"Forget pane\" -body {\n    .pw forget .pw.f1\n    winfo manager .pw.f1\n} -result \"\"\n\ntest panedwindow-1.7 \"Make sure empty panedwindow still still doesn't crash\" -body {\n    update\n}\n\ntest panedwindow-1.8 \"Re-forget pane\" -body {\n    .pw forget .pw.f1\n} -returnCodes error -result \".pw.f1 is not managed by .pw\"\n\ntest panedwindow-1.end \"Cleanup\" -body {\n    destroy .pw\n}\n\n# Resize behavior:\n#\ntest panedwindow-2.1 \"...\" -body {\n    ttk::panedwindow .pw -orient horizontal\n\n    .pw add [listbox .pw.l1]\n    .pw add [listbox .pw.l2]\n    .pw add [listbox .pw.l3]\n    .pw add [listbox .pw.l4]\n\n    pack .pw -expand true -fill both\n    update\n    set w1 [winfo width .]\n\n    # This should make the window shrink:\n    destroy .pw.l2\n\n    update\n    set w2 [winfo width .]\n\n    expr {$w2 < $w1}\n} -result 1\n\ntest panedwindow-2.2 \"..., cont'd\" -body {\n\n    # This should keep the window from shrinking:\n    wm geometry . [wm geometry .]\n\n    set rw2 [winfo reqwidth .pw]\n\n    destroy .pw.l1\n    update\n\n    set w3 [winfo width .]\n    set rw3 [winfo reqwidth .pw]\n\n    expr {$w3 == $w2 && $rw3 < $rw2}\n    # problem: [winfo reqwidth] shrinks, but sashes haven't moved\n    # since we haven't gotten a ConfigureNotify.\n    # How to (a) check for this, and (b) fix it?\n} -result 1\n\ntest panedwindow-2.3 \"..., cont'd\" -body {\n\n    .pw add [listbox .pw.l5]\n    update\n    set rw4 [winfo reqwidth .pw]\n\n    expr {$rw4 > $rw3}\n} -result 1\n\ntest panedwindow-2.end \"Cleanup\" -body { destroy .pw }\n\ntest panedwindow-3.0 \"configure pane\" -body {\n    ttk::panedwindow .pw\n    .pw add [listbox .pw.lb1]\n    .pw add [listbox .pw.lb2]\n    .pw pane 1 -weight 2\n    .pw pane 1 -weight\n} -result 2\n\ntest panedwindow-3.1 \"configure pane -- errors\" -body {\n    .pw pane 1 -weight -4\n} -returnCodes error -match glob -result \"-weight must be non-negative\"\n\ntest panedwindow-3.2 \"add pane -- errors\" -body {\n    .pw add [ttk::label .pw.l] -weight -1\n} -returnCodes error -match glob -result \"-weight must be non-negative\"\n\n\ntest panedwindow-3.end \"cleanup\" -body { destroy .pw }\n\n\ntest panedwindow-4.1 \"forget\" -body {\n    pack [ttk::panedwindow .pw -orient vertical] -expand true -fill both\n    .pw add [label .pw.l1 -text \"L1\"]\n    .pw add [label .pw.l2 -text \"L2\"]\n    .pw add [label .pw.l3 -text \"L3\"]\n    .pw add [label .pw.l4 -text \"L4\"]\n\n    update\n\n    .pw forget .pw.l1\n    .pw forget .pw.l2\n    .pw forget .pw.l3\n    .pw forget .pw.l4\n    update\n}\n\ntest panedwindow-4.2 \"forget forgotten\" -body {\n    .pw forget .pw.l1\n} -returnCodes error -result \".pw.l1 is not managed by .pw\"\n\ntest panedwindow-4.3 \"insert command\" -body {\n    .pw insert end .pw.l1\n    .pw insert end .pw.l3\n    .pw insert 1 .pw.l2\n    .pw insert end .pw.l4\n\n    update;\n    checkorder {.pw.l1 .pw.l2 .pw.l3 .pw.l4}\n}\n\ntest panedwindow-4.END \"cleanup\" -body {\n    destroy .pw\n}\n\n# See #1292219\n\ntest panedwindow-5.1 \"Propagate Map/Unmap state to children\" -body {\n    set result [list]\n    pack [ttk::panedwindow .pw]\n    .pw add [ttk::button .pw.b]\n    update\n\n    lappend result [winfo ismapped .pw] [winfo ismapped .pw.b]\n\n    pack forget .pw\n    update\n    lappend result [winfo ismapped .pw] [winfo ismapped .pw.b]\n\n    set result\n} -result [list 1 1 0 0] -cleanup {\n    destroy .pw\n}\n\n### sashpos tests.\n#\n\ntest paned-sashpos-setup \"Setup for sash position test\" -body {\n    ttk::style theme use default\n    ttk::style configure Sash -sashthickness 5\n\n    ttk::panedwindow .pw\n    .pw add [frame .pw.f1 -width 20 -height 20]\n    .pw add [frame .pw.f2 -width 20 -height 20]\n    .pw add [frame .pw.f3 -width 20 -height 20]\n    .pw add [frame .pw.f4 -width 20 -height 20]\n\n    propagate-geometry\n    list [winfo reqwidth .pw] [winfo reqheight .pw]\n} -result [list 20 [expr {20*4 + 5*3}]]\n\ntest paned-sashpos-attempt-restore \"Attempt to set sash positions\" -body {\n    # This is not expected to succeed, since .pw isn't large enough yet.\n    #\n    .pw sashpos 0 30\n    .pw sashpos 1 60\n    .pw sashpos 2 90\n\n    list [winfo reqwidth .pw] [winfo reqheight .pw] [sashpositions .pw]\n} -result [list 20 95 [list 0 5 10]]\n\ntest paned-sashpos-restore \"Set height then sash positions\" -body {\n    # Setting sash positions after setting -height _should_ succeed.\n    #\n    .pw configure -height 120\n    .pw sashpos 0 30\n    .pw sashpos 1 60\n    .pw sashpos 2 90\n    list [winfo reqwidth .pw] [winfo reqheight .pw] [sashpositions .pw]\n} -result [list 20 120 [list 30 60 90]]\n\ntest paned-sashpos-cleanup \"Clean up\" -body { destroy .pw }\n\ntest paned-propagation-setup \"Setup.\" -body {\n    ttk::style theme use default\n    ttk::style configure Sash -sashthickness 5\n    wm geometry . {}\n    ttk::panedwindow .pw -orient vertical\n\n    frame .pw.f1 -width 100 -height 50\n    frame .pw.f2 -width 100 -height 50\n\n    list [winfo reqwidth .pw.f1] [winfo reqheight .pw.f1]\n} -result [list 100 50]\n\ntest paned-propagation-1 \"Initial request size\" -body {\n    .pw add .pw.f1\n    .pw add .pw.f2\n    propagate-geometry\n    list [winfo reqwidth .pw] [winfo reqheight .pw]\n} -result [list 100 105]\n\ntest paned-propagation-2 \"Pane change before map\" -body {\n    .pw.f1 configure -width 200 -height 100\n    propagate-geometry\n    list [winfo reqwidth .pw] [winfo reqheight .pw]\n} -result [list 200 155]\n\ntest paned-propagation-3 \"Map window\" -body {\n    pack .pw -expand true -fill both\n    update\n    list [winfo width .pw] [winfo height .pw] [.pw sashpos 0]\n} -result [list 200 155 100]\n\ntest paned-propagation-4 \"Pane change after map, off-axis\" -body {\n    .pw.f1 configure -width 100 ;# should be granted\n    propagate-geometry\n    list [winfo reqwidth .pw] [winfo reqheight .pw] [.pw sashpos 0]\n} -result [list 100 155 100]\n\ntest paned-propagation-5 \"Pane change after map, on-axis\" -body {\n    .pw.f1 configure -height 50 ;# should be denied\n    propagate-geometry\n    list [winfo reqwidth .pw] [winfo reqheight .pw] [.pw sashpos 0]\n} -result [list 100 155 100]\n\ntest paned-propagation-cleanup \"Clean up.\" -body { destroy .pw }\n\ntest panedwindow-6.1 \"style command\" -body {\n    # Contrary to ttk::scrollbar, ttk::progressbar and ttk::scale,\n    # ttk::panedwindow has same style TPanedwindow whatever -orient is\n    ttk::panedwindow .wv  ; # default is  -orient vertical\n    ttk::panedwindow .wh -orient horizontal\n    list [.wv cget -style] [.wv style] [winfo class .wv]\\\n\t    [.wh cget -style] [.wh style] [winfo class .wh]\n} -cleanup {\n    destroy .wv .wh\n} -result {{} TPanedwindow TPanedwindow {} TPanedwindow TPanedwindow}\ntest panedwindow-6.2 \"style command\" -body {\n    ttk::style configure customStyle.TPanedwindow\n    ttk::panedwindow .w -style customStyle.TPanedwindow\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TPanedwindow customStyle.TPanedwindow TPanedwindow}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/progressbar.test",
    "content": "#\n# ttk::progressbar widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest progressbar-1.1 \"Setup\" -body {\n    ttk::progressbar .pb\n} -result .pb\n\ntest progressbar-1.2 \"Linked variable\" -body {\n    set PB 50\n    .pb configure -variable PB\n    .pb cget -value\n} -result 50\n\ntest progressbar-1.3 \"Change linked variable\" -body {\n    set PB 80\n    .pb cget -value\n} -result 80\n\ntest progressbar-1.4 \"Set linked variable to bad value\" -body {\n    set PB \"bogus\"\n    .pb instate invalid\n} -result 1\n\ntest progressbar-1.4.1 \"Set linked variable back to a good value\" -body {\n    set PB 80\n    .pb instate invalid\n} -result 0\n\ntest progressbar-1.5 \"Set -variable to illegal variable\" -body {\n    set BAD \"bogus\"\n    .pb configure -variable BAD\n    .pb instate invalid\n} -result 1\n\ntest progressbar-1.6 \"Unset -variable\" -body {\n    unset -nocomplain UNSET\n    .pb configure -variable UNSET\n    .pb instate disabled\n} -result 1\n\ntest progressbar-2.0 \"step command\" -body {\n    .pb configure -variable {}\t\t;# @@@\n    .pb configure -value 5 -maximum 10 -mode determinate\n    .pb step\n    .pb cget -value\n} -result 6.0\n\ntest progressbar-2.1 \"step command, with stepamount\" -body {\n    .pb step 3\n    .pb cget -value\n} -result 9.0\n\ntest progressbar-2.2 \"step wraps at -maximum in determinate mode\" -body {\n    .pb step\n    .pb cget -value\n} -result 0.0\n\ntest progressbar-2.3 \"step doesn't wrap in indeterminate mode\" -body {\n    .pb configure -value 8 -maximum 10 -mode indeterminate\n    .pb step\n    .pb step\n    .pb step\n    .pb cget -value\n} -result 11.0\n\ntest progressbar-2.4 \"step with linked variable\" -body {\n    .pb configure -variable PB\t\t;# @@@\n    set PB 5\n    .pb step\n    set PB\n} -result 6.0\n\ntest progressbar-2.5 \"error in write trace\" -body {\n    trace add variable PB write { error \"YIPES!\" ;# }\n    .pb step\n    set PB\t\t;# NOTREACHED\n} -cleanup { unset PB } -returnCodes error -match glob -result \"*YIPES!\"\n\ntest progressbar-end \"Cleanup\" -body {\n    destroy .pb\n}\n\n# check existence and default value of each non-core option of the widget\ntest progressbar-3.1 \"progressbar non-core options\" -setup {\n    set res {}\n    ttk::progressbar .defaultpb\n} -body {\n    foreach option {-anchor -foreground -justify -style -text -wraplength \\\n\t\t    -length -maximum -mode -orient -phase -value -variable} {\n\tlappend res [.defaultpb cget $option]\n    }\n    set res\n} -cleanup {\n    unset res\n    destroy .defaultpb\n} -result {w black left {} {} 0 75p 100.0 determinate horizontal 0 0.0 {}}\n\ntest progressbar-3.2 \"TIP #442 options are taken into account\" -setup {\n    set res {}\n    pack [ttk::progressbar .p -value 0 -maximum 50 -orient horizontal -mode determinate -length 500]\n    set thefont [font actual {Arial 10}]\n} -body {\n    .p configure -anchor c -foreground blue -justify right \\\n\t    -text \"TIP #442\\noptions are now tested\" -wraplength 100\n    update\n    .p step 10\n    .p configure -anchor e -font $thefont -foreground green -justify center \\\n\t    -text \"Changing the value of each option\\nfrom TIP #442\" -wraplength 250\n    update\n    .p step 20\n    .p configure -orient vertical -text \"Cannot be seen\"\n    update\n    foreach option {-anchor -foreground -justify -text -wraplength} {\n\tlappend res [list $option [.p cget $option]]\n    }\n    set res\n} -cleanup {\n    unset res thefont\n    destroy .p\n} -result {{-anchor e} {-foreground green} {-justify center} {-text {Cannot be seen}} {-wraplength 250}}\n\ntest progressbar-3.3 {horizontal progressbar height with no -text (TIP #442) specified - Bug [8bee4b2009]} -setup {\n    set res {}\n    set oldTheme [ttk::style theme use]\n} -body {\n    ttk::style theme use default\n    set imga [image create photo -file [file join [file dirname [info script]] pb_image.svg] -format {svg -scale 0.8}]\n    ::ttk::style element create Horizontal.Progressbar.pbar image $imga\n    # -text \"\": progressbar height does not depend on font height\n    pack [ttk::progressbar .p -orient horizontal -font {TkDefaultFont 24}]\n    .p step 25\n    update\n    set res [expr {[winfo reqheight .p] == [image height $imga] + 2}]\n    # -text \"something\": progressbar height adjusts to contain the font height\n    .p configure -text Hello -font {TkDefaultFont 24}\n    update\n    lappend res [expr {[winfo reqheight .p] == [font metrics [.p cget -font] -linespace] + 2}]\n} -cleanup {\n    destroy .p\n    ttk::style theme use $oldTheme\n    # there's no way I know to undo  '::ttk::style element create...'\n} -result {1 1}\n\ntest progressbar-4.1 \"style command\" -body {\n    ttk::progressbar .wh  ; # default is  -orient horizontal\n    ttk::progressbar .wv -orient vertical\n    list [.wh cget -style] [.wh style] [winfo class .wh]\\\n\t [.wv cget -style] [.wv style] [winfo class .wv]\n} -cleanup {\n    destroy .wh .wv\n} -result {{} Horizontal.TProgressbar TProgressbar {} Vertical.TProgressbar TProgressbar}\ntest progressbar-4.2 \"style command\" -body {\n    ttk::style configure customStyle.Vertical.TProgressbar\n    ttk::progressbar .w -orient vertical -style customStyle.Vertical.TProgressbar\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.Vertical.TProgressbar Vertical.customStyle.Vertical.TProgressbar TProgressbar}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/radiobutton.test",
    "content": "#\n# ttk::radiobutton widget tests.\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest radiobutton-1.1 \"Radiobutton check\" -body {\n    pack \\\n\t[ttk::radiobutton .rb1 -text \"One\" -variable choice -value 1] \\\n\t[ttk::radiobutton .rb2 -text \"Two\" -variable choice -value 2] \\\n\t[ttk::radiobutton .rb3 -text \"Three\" -variable choice -value 3] \\\n\t;\n}\ntest radiobutton-1.2 \"Radiobutton invoke\" -body {\n    .rb1 invoke\n    set ::choice\n} -result 1\n\ntest radiobutton-1.3 \"Radiobutton state\" -body {\n    .rb1 instate selected\n} -result 1\n\ntest radiobutton-1.4 \"Other radiobutton invoke\" -body {\n    .rb2 invoke\n    set ::choice\n} -result 2\n\ntest radiobutton-1.5 \"Other radiobutton state\" -body {\n    .rb2 instate selected\n} -result 1\n\ntest radiobutton-1.6 \"First radiobutton state\" -body {\n    .rb1 instate selected\n} -result 0\n\ntest radiobutton-1.7 \"Unset radiobutton variable\" -body {\n    unset ::choice\n    list [info exists ::choice] [.rb1 instate alternate] [.rb2 instate alternate]\n} -result {0 1 1}\n\ntest radiobutton-1.8 \"Reset radiobutton variable\" -body {\n    set ::choice 2\n    list [info exists ::choice] [.rb1 instate alternate] [.rb2 instate alternate]\n} -result {1 0 0}\n\ntest radiobutton-2.1 \"style command\" -body {\n    ttk::radiobutton .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TRadiobutton TRadiobutton}\ntest radiobutton-2.2 \"style command\" -body {\n    ttk::style configure customStyle.TRadiobutton\n    ttk::radiobutton .w -style customStyle.TRadiobutton\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TRadiobutton customStyle.TRadiobutton TRadiobutton}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/scale.test",
    "content": "#\n# ttk::scale widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest scale-1.0 \"Self-destruction\" -body {\n    trace add variable v write { destroy .s ;# }\n    ttk::scale .s -variable v\n    pack .s ; update\n    .s set 1 ; update\n} -returnCodes error -match glob -result \"*\"\n\ntest scale-2.1 \"-state option\" -setup {\n    ttk::scale .s\n    set res \"\"\n} -body {\n    # defaults\n    lappend res [.s instate disabled] [.s cget -state]\n    # set -state: instate returns accordingly\n    .s configure -state disabled\n    lappend res [.s instate disabled] [.s cget -state]\n    # back to normal\n    .s configure -state normal\n    lappend res [.s instate disabled] [.s cget -state]\n    # use state command: -state does NOT reflect it\n    .s state disabled\n    lappend res [.s instate disabled] [.s cget -state]\n    # further use state command\n    .s state readonly\n    lappend res [.s state] [.s cget -state]\n} -cleanup {\n    destroy .s\n    unset -nocomplain res\n} -result {0 normal 1 disabled 0 normal 1 normal {disabled readonly} normal}\n\ntest scale-3.1 \"style command\" -body {\n    ttk::scale .wh  ; # default is  -orient horizontal\n    ttk::scale .wv -orient vertical\n    list [.wh cget -style] [.wh style] [winfo class .wh] \\\n\t    [.wv cget -style] [.wv style] [winfo class .wv]\n} -cleanup {\n    destroy .wh .wv\n} -result {{} Horizontal.TScale TScale {} Vertical.TScale TScale}\ntest scale-3.2 \"style command\" -body {\n    ttk::style configure customStyle.Vertical.TScale\n    ttk::scale .w -orient vertical -style customStyle.Vertical.TScale\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.Vertical.TScale Vertical.customStyle.Vertical.TScale TScale}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n\n"
  },
  {
    "path": "tests/ttk/scrollbar.test",
    "content": "#\n# ttk::scrollbar widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n# * Before 2019 the code in library/ttk/scrollbar.tcl would replace the\n#   constructor of ttk::scrollbar with the constructor of tk::scrollbar\n#   unless the -class or -style options were specified..\n#   Now there is an implementation of ttk::scrollbar for macOS.  The\n#   tests are left in place, though, except that scrollbar-swapout-1\n#   test was changed to expect the class to be TScrollbar instead of\n#   Scrollbar.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest scrollbar-swapout-1 \"Don't use core scrollbars on OSX...\" \\\n -constraints {\n     aqua\n} -body {\n    ttk::scrollbar .sb -command \"yadda\"\n    list [winfo class .sb] [.sb cget -command]\n} -result [list TScrollbar yadda] -cleanup {\n    destroy .sb\n}\n\ntest scrollbar-swapout-2 \"... regardless of whether -style ...\" \\\n-constraints {\n    aqua\n} -body {\n    ttk::style layout Vertical.Custom.TScrollbar \\\n\t[ttk::style layout Vertical.TScrollbar] ; # See #1833339\n    ttk::scrollbar .sb -command \"yadda\" -style Custom.TScrollbar\n    list [winfo class .sb] [.sb cget -command] [.sb cget -style]\n} -result [list TScrollbar yadda Custom.TScrollbar] -cleanup {\n    destroy .sb\n}\n\ntest scrollbar-swapout-3 \"... or -class is specified.\" -constraints {\n    aqua\n} -body {\n    ttk::scrollbar .sb -command \"yadda\" -class Custom.TScrollbar\n    list [winfo class .sb] [.sb cget -command]\n} -result [list Custom.TScrollbar yadda] -cleanup {\n    destroy .sb\n}\n\ntest scrollbar-1.0 \"Setup\" -body {\n    ttk::scrollbar .tsb\n} -result .tsb\n\ntest scrollbar-1.1 \"Set method\" -body {\n    .tsb set 0.2 0.4\n    .tsb get\n} -result [list 0.2 0.4]\n\ntest scrollbar-1.2 \"Set orientation\" -body {\n    .tsb configure -orient vertical\n    pack .tsb -side right -anchor e -expand 1 -fill y\n    wm geometry . 200x200\n    update\n    set w [winfo width .tsb] ; set h [winfo height .tsb]\n    expr {$h > $w}\n} -result 1\n\ntest scrollbar-1.3 \"Change orientation\" -body {\n    .tsb configure -orient horizontal\n    pack .tsb -side bottom -anchor s -expand 1 -fill x\n    wm geometry . 200x200\n    update\n    set w [winfo width .tsb] ; set h [winfo height .tsb]\n    expr {$h < $w}\n} -result 1\n\ntest scrollbar-10.1.1 {<MouseWheel> event on scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -yscrollcommand {.s set}] -side left\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Line $i\\n\"}\n    pack [ttk::scrollbar .s -command {.t yview}] -fill y -expand 1 -side left\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {4.0}\n\ntest scrollbar-10.2.1 {<Shift-MouseWheel> event on horizontal scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -xscrollcommand {.s set} -wrap none] -side top\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Char $i \"}\n    pack [ttk::scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <Shift-MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {1.3}\ntest scrollbar-10.2.2 {<MouseWheel> event on horizontal scrollbar} -setup {\n    destroy .t .s\n} -body {\n    pack [text .t -xscrollcommand {.s set} -wrap none] -side top\n    for {set i 1} {$i < 100} {incr i} {.t insert end \"Char $i \"}\n    pack [ttk::scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top\n    update\n    focus -force .s\n    event generate .s <Enter>\n    event generate .s <MouseWheel> -delta -120\n    after 200 {set eventprocessed 1} ; vwait eventprocessed\n    .t index @0,0\n} -cleanup {\n    destroy .t .s\n} -result {1.3}\n\ntest scrollbar-11.1 \"style command\" -body {\n    ttk::scrollbar .wv  ; # default is  -orient vertical\n    ttk::scrollbar .wh -orient horizontal\n    list [.wv cget -style] [.wv style] [winfo class .wv] \\\n\t    [.wh cget -style] [.wh style] [winfo class .wh]\n} -cleanup {\n    destroy .wv .wh\n} -result {{} Vertical.TScrollbar TScrollbar {} Horizontal.TScrollbar TScrollbar}\ntest scrollbar-11.2 \"style command\" -body {\n    ttk::style configure customStyle.Horizontal.TScrollbar\n    ttk::scrollbar .w -orient horizontal -style customStyle.Horizontal.TScrollbar\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.Horizontal.TScrollbar Horizontal.customStyle.Horizontal.TScrollbar TScrollbar}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/spinbox.test",
    "content": "#\n# ttk::spinbox widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest spinbox-1.0 \"Spinbox tests -- setup\" -body {\n    ttk::spinbox .sb\n} -cleanup { destroy .sb } -result .sb\n\ntest spinbox-1.1 \"Bad -values list\" -setup {\n    ttk::spinbox .sb\n} -body {\n    .sb configure -values \"bad \\{list\"\n} -cleanup {\n    destroy .sb\n} -returnCodes error -result \"unmatched open brace in list\"\n\ntest spinbox-1.3.1 \"get retrieves value\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb set 50\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 50\n\ntest spinbox-1.3.2 \"get retrieves value\" -setup {\n    ttk::spinbox .sb -from 0 -to 100 -values 55\n} -body {\n     .sb set 55\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 55\n\ntest spinbox-1.4.1 \"set changes value\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb set 33\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 33\n\ntest spinbox-1.4.2 \"set changes value\" -setup {\n    ttk::spinbox .sb -from 0 -to 100 -values 55\n} -body {\n    .sb set 33\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 33\n\n\ntest spinbox-1.6.1 \"insert start\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb set 5\n    .sb insert 0 4\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 45\n\ntest spinbox-1.6.2 \"insert end\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb set 5\n    .sb insert end 4\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 54\n\ntest spinbox-1.6.3 \"insert invalid index\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb set 5\n    .sb insert 100 4\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result 54\n\ntest spinbox-1.7.1 \"-command option: set doesnt fire\" -setup {\n    ttk::spinbox .sb -from 0 -to 100 -command {set ::spinbox_test 1}\n} -body {\n    set ::spinbox_test 0\n    .sb set 50\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n} -result 0\n\ntest spinbox-1.7.2 \"-command option: button handler will fire\" -setup {\n    ttk::spinbox .sb -from 0 -to 100 -command {set ::spinbox_test 1}\n} -body {\n    set ::spinbox_test 0\n    .sb set 50\n    event generate .sb <<Increment>>\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n} -result 1\n\ntest spinbox-1.8.1 \"option -validate\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb configure -validate all\n    .sb cget -validate\n} -cleanup {\n    destroy .sb\n} -result {all}\n\ntest spinbox-1.8.2 \"option -validate\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb configure -validate key\n    .sb configure -validate focus\n    .sb configure -validate focusin\n    .sb configure -validate focusout\n    .sb configure -validate none\n    .sb cget -validate\n} -cleanup {\n    destroy .sb\n} -result none\n\ntest spinbox-1.8.3 \"option -validate\" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n} -body {\n    .sb configure -validate bogus\n} -cleanup {\n    destroy .sb\n} -returnCodes error -result {bad validate \"bogus\": must be all, key, focus, focusin, focusout, or none}\n\ntest spinbox-1.8.4 \"-validate option: \" -setup {\n    ttk::spinbox .sb -from 0 -to 100\n    set ::spinbox_test {}\n} -body {\n    .sb configure -validate all -validatecommand {set ::spinbox_test %P}\n    pack .sb\n    update idletasks\n    .sb set 50\n    focus -force .sb\n    set ::spinbox_wait 0\n    set timer [after 100 {set ::spinbox_wait 1}]\n    vwait ::spinbox_wait\n    after cancel $timer\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n} -result 50\n\n\ntest spinbox-2.0 \"current command -- unset should be 0\" -constraints nyi -setup {\n    ttk::spinbox .sb -values [list a b c d e a]\n} -body {\n    .sb current\n} -cleanup {\n    destroy .sb\n} -result 0\n# @@@ for combobox, this is -1.\n\ntest spinbox-2.1 \"current command -- set index\" -constraints nyi -setup {\n    ttk::spinbox .sb -values [list a b c d e a]\n} -body {\n    .sb current 5\n    .sb get\n} -cleanup {\n    destroy .sb\n} -result a\n\ntest spinbox-2.2 \"current command -- change -values\" -constraints nyi -setup {\n    ttk::spinbox .sb -values [list a b c d e a]\n} -body {\n    .sb current 5\n    .sb configure -values [list c b a d e]\n    .sb current\n} -cleanup {\n    destroy .sb\n} -result 2\n\ntest spinbox-2.3 \"current command -- change value\" -constraints nyi -setup {\n    ttk::spinbox .sb -values [list c b a d e]\n} -body {\n    .sb current 2\n    .sb set \"b\"\n    .sb current\n} -cleanup {\n    destroy .sb\n} -result 1\n\ntest spinbox-2.4 \"current command -- value not in list\" -constraints nyi -setup {\n    ttk::spinbox .sb -values [list c b a d e]\n} -body {\n    .sb current 2\n    .sb set \"z\"\n    .sb current\n} -cleanup {\n    destroy .sb\n} -result -1\n\ntest spinbox-3.0 \"textarea should expand to fill widget\" -setup {\n    set SBV 5\n    set ::spinbox_test {}\n    ttk::spinbox .sb -from 0 -to 10 -textvariable SBV\n} -body {\n    grid columnconfigure . 0 -weight 1\n    update idletasks\n    set timer [after 500 {set ::spinbox_test timedout}]\n    bind . <Map> {\n\tafter idle {\n\t    wm geometry . \"210x80\"\n\t    update idletasks\n\t    set ::spinbox_test [.sb identify element 25 5]\n\t}\n\tbind . <Map> {}\n    }\n    grid .sb -sticky ew\n    vwait ::spinbox_test\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n    unset -nocomplain ::spinbox_test SBV\n} -result {textarea}\n\ntest spinbox-4.0 \"Increment with duplicates in -values, wrap\" -setup {\n    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap true\n    set max [expr {[llength [.sb cget -values]] + 2}]\n} -body {\n    set ::spinbox_test [.sb get]\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Increment>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Decrement>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n    unset -nocomplain ::spinbox_test max\n} -result {one two three 4 5 two six one two one six two 5 4 three two one six}\n\ntest spinbox-4.1 \"Increment with duplicates in -values, wrap, initial value set\" -setup {\n    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap true\n    set max [expr {[llength [.sb cget -values]] + 2}]\n} -body {\n    .sb set three\n    set ::spinbox_test [.sb get]\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Increment>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    .sb set two    ; # the first \"two\" in the -values list becomes the current value\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Decrement>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n    unset -nocomplain ::spinbox_test max\n} -result {three 4 5 two six one two three 4 5 one six two 5 4 three two one six}\n\ntest spinbox-4.2 \"Increment with duplicates in -values, no wrap\" -setup {\n    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap false\n    set max [expr {[llength [.sb cget -values]] + 2}]\n} -body {\n    set ::spinbox_test [.sb get]\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Increment>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    for {set i 0} {$i < $max} {incr i} {\n\tevent generate .sb <<Decrement>>\n\tlappend ::spinbox_test [.sb get]\n    }\n    set ::spinbox_test\n} -cleanup {\n    destroy .sb\n    unset -nocomplain ::spinbox_test max\n} -result {one two three 4 5 two six six six two 5 4 three two one one one one}\n\ntest spinbox-11.2 {Bugs [2a32225cd1] and [9fa3e08243]} -setup {\n    destroy .s\n    pack [ttk::spinbox .s]\n    update\n    set res {}\n} -body {\n    .s insert end \"A sample text\"\n    .s icursor end\n    event generate .s <<PrevWord>>  ; # shall move insert to index 9\n    .s delete insert end\n    lappend res [.s get]\n    .s delete 0 end\n    .s insert end \"A sample text\"\n    .s icursor 2\n    event generate .s <<NextWord>>  ; # shall move insert to index 9\n    .s delete 0 insert\n    lappend res [.s get]\n} -cleanup {\n    destroy .s\n} -result {{A sample } text}\n\n\n# nostomp: NB intentional difference between ttk::spinbox and tk::spinbox;\n# see also #1439266\n#\ntest spinbox-nostomp-1 \"don't stomp on -variable (init; -from/to)\" -body {\n    set SBV 55\n    ttk::spinbox .sb -textvariable SBV -from 0 -to 100 -increment 5\n    list $SBV [.sb get]\n} -cleanup {\n   unset SBV\n   destroy .sb\n} -result [list 55 55]\n\ntest spinbox-nostomp-2 \"don't stomp on -variable (init; -values)\" -body {\n    set SBV Apr\n    ttk::spinbox .sb -textvariable SBV -values {Jan Feb Mar Apr May Jun Jul Aug}\n    list $SBV [.sb get]\n} -cleanup {\n   unset SBV\n   destroy .sb\n} -result [list Apr Apr]\n\ntest spinbox-nostomp-3 \"don't stomp on -variable (configure; -from/to)\" -body {\n    set SBV 55\n    ttk::spinbox .sb\n    .sb configure -textvariable SBV -from 0 -to 100 -increment 5\n    list $SBV [.sb get]\n} -cleanup {\n   unset SBV\n   destroy .sb\n} -result [list 55 55]\n\ntest spinbox-nostomp-4 \"don't stomp on -variable (configure; -values)\" -body {\n    set SBV Apr\n    ttk::spinbox .sb\n    .sb configure -textvariable SBV -values {Jan Feb Mar Apr May Jun Jul Aug}\n    list $SBV [.sb get]\n} -cleanup {\n   unset SBV\n   destroy .sb\n} -result [list Apr Apr]\n\ntest spinbox-dieoctaldie-1 \"Cope with leading zeros\" -body {\n    # See SF#2358545 -- ttk::spinbox also affected\n    set secs 07\n    ttk::spinbox .sb -from 0 -to 59 -format %02.0f -textvariable secs\n\n    set result [list $secs]\n    event generate .sb <<Increment>>; lappend result $secs\n    event generate .sb <<Increment>>; lappend result $secs\n    event generate .sb <<Increment>>; lappend result $secs\n    event generate .sb <<Increment>>; lappend result $secs\n\n    event generate .sb <<Decrement>>; lappend result $secs\n    event generate .sb <<Decrement>>; lappend result $secs\n    event generate .sb <<Decrement>>; lappend result $secs\n    event generate .sb <<Decrement>>; lappend result $secs\n\n    set result\n} -result [list 07 08 09 10 11 10 09 08 07] -cleanup {\n    destroy .sb\n    unset secs\n}\n\ntest spinbox-dieoctaldie-2 \"Cope with general bad input\" -body {\n    set result [list]\n    ttk::spinbox .sb -from 0 -to 100 -format %03.0f\n    .sb set asdfasdf ; lappend result [.sb get]\n    event generate .sb <<Increment>> ; lappend result [.sb get]\n    .sb set asdfasdf ; lappend result [.sb get]\n    event generate .sb <<Decrement>> ; lappend result [.sb get]\n} -result [list asdfasdf 000 asdfasdf 000] -cleanup {\n    destroy .sb\n}\n\ntest spinbox-5.1 \"style command\" -body {\n    ttk::spinbox .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} TSpinbox TSpinbox}\ntest spinbox-5.2 \"style command\" -body {\n    ttk::style configure customStyle.TSpinbox\n    ttk::spinbox .w -style customStyle.TSpinbox\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.TSpinbox customStyle.TSpinbox TSpinbox}\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/ttk/toggleswitch.test",
    "content": "#\n# ttk::toggleswitch widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed for \"-singleproc 0\"\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest toggleswitch-1.1 \"Toggleswitch\" -body {\n    pack [ttk::toggleswitch .sw -variable sw]\n}\n\ntest toggleswitch-1.2 \"Toggleswitch toggle\" -body {\n    .sw toggle\n    list [set sw] [.sw instate selected] [expr {[.sw get] == [.sw get max]}]\n} -result [list 1 1 1]\n\ntest toggleswitch-1.3 \"Toggleswitch switchstate\" -body {\n    .sw switchstate 0\n    list [set sw] [.sw instate selected] [expr {[.sw get] == [.sw get min]}]\n} -result [list 0 0 1]\n\ntest toggleswitch-1.4 \"Toggleswitch variable\" -body {\n    set result [list]\n    set sw 1\n    lappend result [.sw instate selected] [expr {[.sw get] == [.sw get max]}]\n    set sw 0\n    lappend result [.sw instate selected] [expr {[.sw get] == [.sw get min]}]\n} -result {1 1 0 1}\n\ntest toggleswitch-1.5 \"Unset toggleswitch variable\" -body {\n    set result [list]\n    unset sw\n    lappend result [.sw instate invalid] [info exists sw]\n    set sw 1\n    lappend result [.sw instate invalid] [info exists sw]\n} -cleanup {\n    destroy .sw\n} -result {1 0 0 1}\n\ntest toggleswitch-1.6 \"Toggleswitch default variable\" -body {\n    set result [list]\n    ttk::toggleswitch .sw -onvalue on -offvalue off\n    lappend result [.sw cget -variable] [info exists .sw] [.sw state]\n    .sw toggle\n    lappend result [info exists .sw] [set .sw] [.sw state]\n    .sw toggle\n    lappend result [info exists .sw] [set .sw] [.sw state]\n} -cleanup {\n    destroy .sw\n} -result [list .sw 0 invalid  1 on selected  1 off {}]\n\ntest toggleswitch-1.7 \"Toggleswitch empty variable\" -body {\n    # shall simply not crash\n    ttk::toggleswitch .sw -variable {}\n    .sw toggle\n} -cleanup {\n    destroy .sw\n} -result {}\n\ntest toggleswitch-2.1 \"-size option\" -body {\n    ttk::toggleswitch .sw -size 1\n    set w1 [winfo reqwidth .sw]; set h1 [winfo reqheight .sw]\n    .sw configure -size 2\n    set w2 [winfo reqwidth .sw]; set h2 [winfo reqheight .sw]\n    .sw configure -size 3\n    set w3 [winfo reqwidth .sw]; set h3 [winfo reqheight .sw]\n    list [expr {$w1 < $w2 && $h1 < $h2}] [expr {$w2 < $w3 && $h2 < $h3}]\n} -cleanup {\n    destroy .sw\n} -result {1 1}\n\ntest toggleswitch-2.2 \"default -size and -style option values\" -body {\n    ttk::toggleswitch .sw\n    list [.sw cget -size] [.sw cget -style] [.sw style] [winfo class .sw]\n} -cleanup {\n    destroy .sw\n} -result {2 Toggleswitch2 Toggleswitch2 Toggleswitch}\n\ntest toggleswitch-2.3 \"-size and -style options\" -body {\n    ttk::toggleswitch .sw -size 3 -style My.Toggleswitch3\n    list [.sw cget -size] [.sw cget -style] [.sw style] [winfo class .sw]\n} -cleanup {\n    destroy .sw\n} -result {3 My.Toggleswitch3 My.Toggleswitch3 Toggleswitch}\n\ntest toggleswitch-2.4 \"-style option\" -body {\n    ttk::toggleswitch .sw\n    .sw configure -style My.Toggleswitch3\n    list [.sw cget -size] [.sw cget -style] [.sw style] [winfo class .sw]\n} -cleanup {\n    destroy .sw\n} -result {3 My.Toggleswitch3 My.Toggleswitch3 Toggleswitch}\n\ntest toggleswitch-2.5 \"-size option takes precedence over -style\" -body {\n    ttk::toggleswitch .sw -style My.Toggleswitch3\t;# intentionally 3\n    list [.sw cget -size] [.sw cget -style] [.sw style] [winfo class .sw]\n} -cleanup {\n    destroy .sw\n} -result {2 My.Toggleswitch2 My.Toggleswitch2 Toggleswitch}\n\ntest toggleswitch-3.1 \"switchstate triggers the associated cmd\" -body {\n    ttk::toggleswitch .sw -command { expr {10 * [.sw switchstate]} }\n    .sw switchstate 1\n} -result 10\n\ntest toggleswitch-3.2 \"toggle triggers the associated cmd\" -body {\n    .sw toggle\n} -result 0\n\ntest toggleswitch-3.3 \"changing the variable doesn't trigger the cmd\" -body {\n    .sw configure -offvalue OFF -onvalue ON -variable var\n    set var ON\n} -cleanup {\n    destroy .sw\n} -result ON\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/treetags.test",
    "content": "#\n# Tests for tags in the ttk::treeview widget\n#\n\n# NOTES\n#\n# * The ttk test suite holds many tests that build upon a previous one. This\n#   is not incidental; it occurs systematically for groups of contiguous tests\n#   in most ttk test files.\n#\n#   A consequence of this practice is that attempts to run tests selectively/\n#   individually using the tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\"\n#   lead to unintended failures. Therefore, invocations using these options\n#   may be considered invalid for the ttk test suite (but not for the\n#   corresponding core Tk tests).\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# Treeview tag invariants:\n\nproc itemConstraints {tv item} {\n    # $tag in [$tv item $item -tags] <==> [$tv tag has $tag $item]\n    foreach tag [$tv item $item -tags] {\n\tassert {$item in [$tv tag has $tag]}\n    }\n    foreach child [$tv children $item] {\n\titemConstraints $tv $child\n    }\n}\n\nproc treeConstraints {tv} {\n    # $item in [$tv tag has $tag] <==> [$tv tag has $tag $item]\n    #\n    foreach tag [$tv tag names] {\n\tforeach item [$tv tag has $tag] {\n\t    assert {$tag in [$tv item $item -tags]}\n\t}\n    }\n\n    itemConstraints $tv {}\n}\n\n#\n# TESTS\n#\n\ntest treetags-1.0 \"Setup\" -body {\n\n    set tv [ttk::treeview .tv -columns \"A B C\"]\n    .tv insert {} end -id item1 -text \"Item 1\"\n    pack .tv\n} -cleanup {\n    treeConstraints $tv\n}\n\ntest treetags-1.1 \"Bad tag list\" -body {\n    $tv item item1 -tags {bad {list}here bad}\n    $tv item item1 -tags\n} -returnCodes error -result \"list element in braces *\" -match glob\n\ntest treetags-1.2 \"Good tag list\" -body {\n    $tv item item1 -tags tag1\n    $tv item item1 -tags\n} -cleanup {\n    assert {[$tv tag has tag1 item1]}\n    treeConstraints $tv\n} -result [list tag1]\n\ntest treetags-1.3 \"tag has - test\" -body {\n    $tv insert {} end -id item2 -text \"Item 2\" -tags tag2\n    set result [list]\n    foreach item {item1 item2} {\n\tforeach tag {tag1 tag2 tag3} {\n\t    lappend result $item $tag [$tv tag has $tag $item]\n\t}\n    }\n    set result\n} -cleanup {\n    treeConstraints $tv\n} -result [list \\\n\titem1 tag1 1 item1 tag2 0 item1 tag3 0 \\\n\titem2 tag1 0 item2 tag2 1 item2 tag3 0 ]\n\ntest treetags-1.4 \"tag has - query\" -body {\n    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]\n} -cleanup {\n    treeConstraints $tv\n} -result [list [list item1] [list item2] [list]]\n\ntest treetags-1.5 \"tag add\" -body {\n    $tv tag add tag3 {item1 item2}\n    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]\n} -cleanup {\n    treeConstraints $tv\n} -result [list [list item1] [list item2] [list item1 item2]]\n\ntest treetags-1.6 \"tag remove - list\" -body {\n    $tv tag remove tag3 {item1 item2}\n    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]\n} -cleanup {\n    treeConstraints $tv\n} -result [list [list item1] [list item2] [list]]\n\ntest treetags-1.7 \"tag remove - all items\" -body {\n    $tv tag remove tag1\n    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]\n} -cleanup {\n    treeConstraints $tv\n} -result [list [list] [list item2] [list]]\n\ntest treetags-1.8 \"tag names\" -body {\n    lsort [$tv tag names]\n} -result [list tag1 tag2 tag3]\n\ntest treetags-1.9 \"tag names - tag added to item\" -body {\n    $tv item item1 -tags tag4\n    lsort [$tv tag names]\n} -result [list tag1 tag2 tag3 tag4]\n\ntest treetags-1.10 \"tag names - tag configured\" -body {\n    $tv tag configure tag5\n    lsort [$tv tag names]\n} -result [list tag1 tag2 tag3 tag4 tag5]\n\ntest treetags-1.11 \"tag delete\" -body {\n    $tv tag delete tag5\n    $tv tag delete tag4\n    lsort [$tv tag names]\n} -result [list tag1 tag2 tag3]\n\ntest treetags-1.end \"cleanup\" -body {\n    $tv item item1 -tags tag1\n    $tv item item2 -tags tag2\n    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]\n} -cleanup {\n    treeConstraints $tv\n} -result [list [list item1] [list item2] [list]]\n\ntest treetags-2.0 \"tag bind\" -body {\n    $tv tag bind tag1 <Key> {set ::KEY %A}\n    $tv tag bind tag1 <Key>\n} -cleanup {\n    treeConstraints $tv\n} -result {set ::KEY %A}\n\ntest treetags-2.1 \"Events delivered to tags\" -body {\n    focus -force $tv ; update\t;# needed so [event generate] delivers Key\n    $tv focus item1\n    event generate $tv <a>\n    set ::KEY\n} -cleanup {\n    treeConstraints $tv\n} -result a\n\ntest treetags-2.2 \"Events delivered to correct tags\" -body {\n    $tv tag bind tag2 <Key> [list set ::KEY2 %A]\n\n    $tv focus item1\n    event generate $tv <b>\n    $tv focus item2\n    event generate $tv <c>\n\n    list $::KEY $::KEY2\n} -cleanup {\n    treeConstraints $tv\n} -result [list b c]\n\ntest treetags-2.3 \"Virtual events delivered to focus item\" -body {\n    set ::bong 0\n    $tv tag bind tag2 <<Bing>> { incr bong }\n    $tv focus item2\n    event generate $tv <<Bing>>\n    $tv focus item1\n    event generate $tv <<Bing>>\n    set bong\n} -cleanup {\n    treeConstraints $tv\n} -result 1\n\ntest treetags-2.4 \"Bad events\" -body {\n    $tv tag bind bad <Enter> { puts \"Entered!\" }\n} -returnCodes error -result \"unsupported event <Enter>*\" -match glob\n\ntest treetags-3.0 \"tag configure - set\" -body {\n    $tv tag configure tag1 -foreground blue -background red\n} -cleanup {\n    treeConstraints $tv\n} -result {}\n\ntest treetags-3.1 \"tag configure - get\" -body {\n    $tv tag configure tag1 -foreground\n} -cleanup {\n    treeConstraints $tv\n} -result blue\n\n# @@@ fragile test\ntest treetags-3.2 \"tag configure - enumerate\" -body {\n    $tv tag configure tag1\n} -cleanup {\n    treeConstraints $tv\n} -result [list \\\n\t-image {} -imageanchor {} -background red -stripedbackground {} -foreground blue \\\n\t-font {} -padding {} ]\ntest treetags-4.1 \"tag cell add\" -body {\n    $tv tag cell add _thetag\n} -returnCodes 1 -result {wrong # args: should be \".tv tag cell add tagName cells\"}\n\ntest treetags-4.2 \"tag cell remove\" -body {\n    $tv tag cell remove _thetag\n    $tv tag cell remove\n} -returnCodes 1 -result {wrong # args: should be \".tv tag cell remove tagName ?cells?\"}\n\ntest treetags-4.3 \"tag cell has\" -body {\n    $tv tag cell has _thetag\n    $tv tag cell has\n} -returnCodes 1 -result {wrong # args: should be \".tv tag cell has tagName ?cell?\"}\n\ntest treetags-4.3.1 \"tag cell has\" -body {\n    $tv tag cell add tag1 \"item1 #2\"\n    set res [$tv tag cell has tag1 \"item1 #2\"]\n    lappend res [$tv tag cell has tag1 \"item1 #1\"]\n    lappend res [$tv tag cell has tag1 \"item1 #3\"]\n    lappend res {*}[$tv tag cell has tag1]\n    $tv tag cell remove tag1 \"item1 B\"\n    lappend res {*}[$tv tag cell has tag1]\n    lappend res [$tv tag cell has tag1 \"item1 #2\"]\n} -result {1 0 0 {item1 B} 0}\n\ntest treetags-4.4 \"tag cell add\" -body {\n    $tv tag cell add tag1 \"item1 A\"\n    $tv tag cell add tag1 \"item1 #3\"\n    $tv tag cell has tag1\n} -result {{item1 A} {item1 C}}\n\ntest treetags-4.5 \"tag cell add\" -body {\n    $tv tag cell add tag2 \"item1 A\"\n    $tv tag cell add tag2 \"item1 #2\"\n    $tv tag cell has tag2\n} -result {{item1 A} {item1 B}}\n\ntest treetags-4.6 \"tag cell remove\" -body {\n    $tv tag cell remove tag1 \"item1 A\"\n    $tv tag cell has tag1\n} -result {{item1 C}}\n\ntest treetags-4.7 \"tag cell remove\" -body {\n    $tv tag cell remove tag2\n    $tv tag cell has tag2\n} -result {}\n\ntest treetags-4.8 \"tag delete with tagged cells\" -body {\n    $tv tag cell add tag6 \"item1 A\"\n    $tv tag delete tag6\n    $tv tag cell has tag6\n} -result {}\n\n# The next test exercises tag resource management.\n# If options are not properly freed, the message:\n# Test file error: \"Font times 20 still in cache.\"\n# will show up on stderr at program exit.\n#\ntest treetags-3.3 \"tag configure - set font\" -body {\n    $tv tag configure tag2 -font {times 20}\n}\n\ntest treetags-3.4 \"stomp tags in tag binding procedure\" -body {\n    set result [list]\n    $tv tag bind rm1 <<Remove>> { lappend ::result rm1 [%W focus] <<Remove>> }\n    $tv tag bind rm2 <<Remove>> {\n\tlappend ::result rm2 [%W focus] <<Remove>>\n\t%W item [%W focus] -tags {tag1}\n    }\n    $tv tag bind rm3 <<Remove>> { lappend ::result rm3 [%W focus] <<Remove>> }\n\n    $tv item item1 -tags {rm1 rm2 rm3}\n    $tv focus item1\n    event generate $tv <<Remove>>\n    set result\n} -cleanup {\n    treeConstraints $tv\n} -result [list rm1 item1 <<Remove>> rm2 item1 <<Remove>> rm3 item1 <<Remove>>]\n\ntest treetags-end \"Cleanup\" -body { destroy $tv }\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/treeview.test",
    "content": "#\n# ttk::treeview widget tests\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n# * [7Jun2005] TO CHECK: [$tv see {}] -- shouldn't work (at least, shouldn't do\n#   what it currently does)\n#\n# * NEED: tests for focus item, selection\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import scroll\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# get list of column IDs from list of display column ids.\n#\nproc columnids {tv dcols} {\n    set result [list]\n    foreach dcol $dcols {\n\tif {[catch {\n\t    lappend result [$tv column $dcol -id]\n\t}]} {\n\t    lappend result ERROR\n\t}\n    }\n    return $result\n}\n\n# consistencyCheck --\n#\tTraverse the tree to make sure the item data structures\n#\tare properly linked.\n#\n#\tSince [$tv children] follows ->next links and [$tv index]\n#\tfollows ->prev links, this should cover all invariants.\n#\nproc consistencyCheck {tv {item {}}} {\n    set i 0\n    foreach child [$tv children $item] {\n\tassert {[$tv parent $child] eq $item}\n\tassert {[$tv index $child] == $i}\n\tincr i\n\tconsistencyCheck $tv $child\n    }\n}\n\nproc identify* {tv comps args} {\n    foreach {x y} $args {\n\tforeach comp $comps {\n\t    lappend result [$tv identify $comp $x $y]\n\t}\n    }\n    return $result\n}\n\nproc nostretch {tv} {\n    foreach col [$tv cget -columns] {\n\t$tv column $col -stretch 0\n    }\n    $tv column #0 -stretch 0\n    update idletasks ; # redisplay $tv\n}\n\nproc tvSetup {} {\n    destroy .tv\n    ttk::treeview .tv -columns {a b c}\n    pack .tv -expand true -fill both\n    .tv column #0 -width 50\n    .tv column a -width 50\n    .tv column b -width 50\n    .tv column c -width 50\n    # Make sure everything is created and updated\n    tkwait visibility .tv\n    update\n    after 10\n    update\n}\n\nproc tvSetupWithItems {} {\n    tvSetup\n    .tv insert {} end -id nn -text \"nn\"\n    .tv insert nn end -id nn.n1 -text \"nn.1\"\n    .tv insert nn end -id nn.n2 -text \"nn.3\"\n    .tv insert nn end -id nn.n3 -text \"nn.3\"\n    for {set t 2} {$t < 100} {incr t} {\n\t.tv insert {} end -id nn$t -text \"nn$t\"\n\tif {$t % 3 == 0} {\n\t    .tv insert nn$t end -id nn$t.n1 -text \"nn$t.n1\"\n\t    .tv insert nn$t end -id nn$t.n2 -text \"nn$t.n2\"\n\t    .tv insert nn$t end -id nn$t.n3 -text \"nn$t.n3\"\n\t}\n    }\n}\n\n#\n# TESTS\n#\n\ntest treeview-1.1 \"columns\" -body {\n    tvSetup\n    .tv configure -columns {a b c}\n}\n\ntest treeview-1.2 \"Bad columns\" -body {\n    #.tv configure -columns {illegal \"list\"value}\n    ttk::treeview .badtv -columns {illegal \"list\"value}\n} -returnCodes error -result \"list element in quotes followed by*\" -match glob\n\ntest treeview-1.3 \"bad displaycolumns\" -body {\n    .tv configure -displaycolumns {a b d}\n} -returnCodes error -result {Invalid column index \"d\"}\n\ntest treeview-1.4 \"more bad displaycolumns\" -body {\n    .tv configure -displaycolumns {1 2 3}\n} -returnCodes error -result {Column index \"3\" out of bounds}\n\ntest treeview-1.5 \"Don't forget to check negative numbers\" -body {\n    .tv configure -displaycolumns {1 {} 3}\n} -returnCodes error -result {Column index \"\" out of bounds}\n\n# Item creation.\n#\ntest treeview-2.1 \"insert -- not enough args\" -body {\n    .tv insert\n} -returnCodes error -result \"wrong # args: *\" -match glob\n\ntest treeview-2.3 \"insert -- bad integer index\" -body {\n    .tv insert {} badindex\n} -returnCodes error -result \"expected integer *\" -match glob\n\ntest treeview-2.4 \"insert -- bad parent node\" -body {\n    .tv insert badparent end\n} -returnCodes error -result \"Item badparent not found\" -match glob\n\ntest treeview-2.5 \"insert -- finaly insert a node\" -body {\n    .tv insert {} end -id newnode -text \"New node\"\n} -result newnode\n\ntest treeview-2.6 \"insert -- make sure node was inserted\" -body {\n    .tv children {}\n} -result [list newnode]\n\ntest treeview-2.7 \"insert -- prevent duplicate node names\" -body {\n    .tv insert {} end -id newnode\n} -returnCodes error -result \"Item newnode already exists\"\n\ntest treeview-2.8 \"insert -- new node at end\" -body {\n    .tv insert {} end -id lastnode\n    consistencyCheck .tv\n    .tv children {}\n} -result [list newnode lastnode]\n\ntest treeview-2.9 \"insert -- new node at beginning\" -body {\n    .tv insert {} 0 -id firstnode\n    consistencyCheck .tv\n    .tv children {}\n} -result [list firstnode newnode lastnode]\n\ntest treeview-2.10 \"insert -- one more node\" -body {\n    .tv insert {} 2 -id onemore\n    consistencyCheck .tv\n    .tv children {}\n} -result [list firstnode newnode onemore lastnode]\n\ntest treeview-2.11 \"insert -- and another one\" -body {\n    .tv insert {} 2 -id anotherone\n    consistencyCheck .tv\n    .tv children {}\n} -result [list firstnode newnode anotherone onemore lastnode]\n\ntest treeview-2.12 \"insert -- one more at end\" -body {\n    .tv insert {} end -id newlastone\n    consistencyCheck .tv\n    .tv children {}\n} -result [list firstnode newnode anotherone onemore lastnode newlastone]\n\ntest treeview-2.13 \"insert -- one more at beginning\" -body {\n    .tv insert {} 0 -id newfirstone\n    consistencyCheck .tv\n    .tv children {}\n} -result [list newfirstone firstnode newnode anotherone onemore lastnode newlastone]\n\ntest treeview-2.14 \"insert -- bad options\" -body {\n    .tv insert {} end -badoption foo\n} -returnCodes error -result {unknown option \"-badoption\"}\n\ntest treeview-2.15 \"insert -- at position 0 w/no children\" -body {\n    .tv insert newnode 0 -id newnode.n2 -text \"Foo\"\n    .tv children newnode\n} -result newnode.n2\t;# don't crash\n\ntest treeview-2.16 \"insert -- insert way past end\" -body {\n    .tv insert newnode 99 -id newnode.n3 -text \"Foo\"\n    consistencyCheck .tv\n    .tv children newnode\n} -result [list newnode.n2 newnode.n3]\n\ntest treeview-2.17 \"insert -- insert before beginning\" -body {\n    .tv insert newnode -1 -id newnode.n1 -text \"Foo\"\n    consistencyCheck .tv\n    .tv children newnode\n}  -result [list newnode.n1 newnode.n2 newnode.n3]\n\n###\n#\ntest treeview-3.1 \"parent\" -body {\n    .tv parent newnode.n1\n} -result newnode\ntest treeview-3.2 \"parent - top-level node\" -body {\n    .tv parent newnode\n} -result {}\ntest treeview-3.3 \"parent - root node\" -body {\n    .tv parent {}\n} -result {}\ntest treeview-3.4 \"index\" -body {\n    list [.tv index newnode.n3] [.tv index newnode.n2] [.tv index newnode.n1]\n} -result [list 2 1 0]\ntest treeview-3.5 \"index - exhaustive test\" -body {\n    set result [list]\n    foreach item [.tv children {}] {\n\tlappend result [.tv index $item]\n    }\n    set result\n} -result [list 0 1 2 3 4 5 6]\n\ntest treeview-3.6 \"detach\" -body {\n    set before [.tv detached newnode]\n    .tv detach newnode\n    consistencyCheck .tv\n    list [.tv children {}] [.tv detached] $before [.tv detached newnode]\n} -result {{newfirstone firstnode anotherone onemore lastnode newlastone} newnode 0 1}\n# XREF: treeview-2.13\n\ntest treeview-3.7 \"detach didn't screw up internal links\" -body {\n    consistencyCheck .tv\n    set result [list]\n    foreach item [.tv children {}] {\n\tlappend result [.tv index $item]\n    }\n    set result\n} -result [list 0 1 2 3 4 5]\n\ntest treeview-3.8 \"detached node has no parent, index 0\" -body {\n    list [.tv parent newnode] [.tv index newnode]\n} -result [list {} 0]\n# @@@ Can't distinguish detached nodes from first root node\n\ntest treeview-3.9 \"detached node's children undisturbed\" -body {\n    .tv children newnode\n} -result [list newnode.n1 newnode.n2 newnode.n3]\n\ntest treeview-3.10 \"detach is idempotent\" -body {\n    .tv detach newnode\n    consistencyCheck .tv\n    .tv children {}\n} -result [list newfirstone firstnode anotherone onemore lastnode newlastone]\n\ntest treeview-3.11 \"Can't detach root item\" -body {\n    .tv detach [list {}]\n} -cleanup {\n    update\n    consistencyCheck .tv\n} -returnCodes error -result \"Cannot detach root item\"\n\ntest treeview-3.12 \"Reattach\" -body {\n    set before [.tv detached newnode]\n    .tv move newnode {} end\n    consistencyCheck .tv\n    list [.tv children {}] $before [.tv detached newnode] [.tv detached]\n} -result {{newfirstone firstnode anotherone onemore lastnode newlastone newnode} 1 0 {}}\n\n# Bug # ?????\ntest treeview-3.13 \"Re-reattach\" -body {\n    set before [.tv detached newnode]\n    .tv move newnode {} end\n    consistencyCheck .tv\n    list [.tv children {}] $before [.tv detached newnode]\n} -result {{newfirstone firstnode anotherone onemore lastnode newlastone newnode} 0 0}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {\n    .tv insert newfirstone end -id x1\n    .tv insert newfirstone end -id x2\n    .tv insert newfirstone end -id x3\n}\n\ntest treeview-3.14 \"Duplicated entry in children list\" -body {\n    .tv children newfirstone [list x3 x1 x2 x3]\n    # ??? Maybe this should raise an error?\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x3 x1 x2]\n\ntest treeview-3.14.1 \"Duplicated entry in children list\" -body {\n    .tv children newfirstone [list x1 x2 x3 x3 x2 x1]\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x1 x2 x3]\n\ntest treeview-3.15 \"Consecutive duplicate entries in children list\" -body {\n    .tv children newfirstone [list x1 x2 x2 x3]\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x1 x2 x3]\n\ntest treeview-3.16 \"Insert child after self\" -body {\n    .tv move x2 newfirstone 1\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x1 x2 x3]\n\ntest treeview-3.17 \"Insert last child after self\" -body {\n    .tv move x3 newfirstone 2\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x1 x2 x3]\n\ntest treeview-3.18 \"Insert last child after end\" -body {\n    .tv move x3 newfirstone 3\n    consistencyCheck .tv\n    .tv children newfirstone\n} -result [list x1 x2 x3]\n\ntest treeview-4.1 \"opened - initial state\" -body {\n    .tv item newnode -open\n} -result 0\ntest treeview-4.2 \"opened - open node\" -body {\n    .tv item newnode -open 1\n    .tv item newnode -open\n} -result 1\ntest treeview-4.3 \"opened - closed node\" -body {\n    .tv item newnode -open 0\n    .tv item newnode -open\n} -result 0\n\ntest treeview-5.1 \"item -- error checks\" -body {\n    .tv item newnode -text \"Bad values\" -values \"{bad}list\"\n} -returnCodes error -result \"list element in braces followed by*\" -match glob\n\ntest treeview-5.2 \"item -- error leaves options unchanged \" -body {\n    .tv item newnode -text\n} -result \"New node\"\n\ntest treeview-5.3 \"Heading\" -body {\n    .tv heading #0 -text \"Heading\"\n}\n\ntest treeview-5.4 \"get cell\" -body {\n    set l [list a b c]\n    .tv item newnode -values $l\n    .tv set newnode 1\n} -result b\n\ntest treeview-5.5 \"set cell\" -body {\n    .tv set newnode 1 XXX\n    .tv item newnode -values\n} -result [list a XXX c]\n\ntest treeview-5.6 \"set illegal cell\" -body {\n    .tv set newnode #0 YYY\n} -returnCodes error -result \"Display column #0 cannot be set\"\n\ntest treeview-5.7 \"set illegal cell\" -body {\n    .tv set newnode 3 YY\t;# 3 == current #columns\n} -returnCodes error -result {Column index \"3\" out of bounds}\n\ntest treeview-5.8 \"set display columns\" -body {\n    .tv configure -displaycolumns [list 2 1 0]\n    .tv set newnode #1 X\n    .tv set newnode #2 Y\n    .tv set newnode #3 Z\n    .tv item newnode -values\n} -result [list Z Y X]\n\ntest treeview-5.9 \"display columns part 2\" -body {\n    list [.tv column #1 -id] [.tv column #2 -id] [.tv column #3 -id]\n} -result [list c b a]\n\ntest treeview-5.10 \"cannot set column -id\" -body {\n    .tv column #1 -id X\n} -returnCodes error -result \"Attempt to change read-only option\"\n\ntest treeview-5.11 \"get\" -body {\n    .tv set newnode #1\n} -result X\n\ntest treeview-5.12 \"get dictionary\" -body {\n    .tv set newnode\n} -result [list a Z b Y c X]\n\ntest treeview-5.13 \"get, no value\" -body {\n    set newitem [.tv insert {} end]\n    set result [.tv set $newitem #1]\n    .tv delete $newitem\n    set result\n} -result {}\n\ntest treeview-5.14 \"set illegal height\" -body {\n    # For now, -height can only be integer\n    .tv item newnode -height 1.5\n} -returnCodes 1 -result {expected integer but got \"1.5\"}\n\ntest treeview-5.15 \"set illegal height\" -body {\n    .tv item newnode -height 0\n} -returnCodes 1 -result \"Invalid item height 0\"\n\ntest treeview-5.16 \"no change after illegal attempt\" -body {\n    .tv item newnode -height\n} -result 1\n\ntest treeview-6.1 \"deletion - setup\" -body {\n    .tv insert {} end -id dtest\n    foreach id [list a b c d e] {\n\t.tv insert dtest end -id $id\n    }\n    .tv children dtest\n} -result [list a b c d e]\n\ntest treeview-6.1.1 \"delete\" -body {\n    .tv delete b\n    consistencyCheck .tv\n    list [.tv exists b] [.tv children dtest]\n} -result [list 0 [list a c d e]]\n\ntest treeview-6.2 \"delete - duplicate items in list\" -body {\n    .tv delete [list a e a e]\n    consistencyCheck .tv\n    .tv children dtest\n} -result [list c d]\n\ntest treeview-6.3 \"delete - descendants removed\" -body {\n    .tv insert c  end -id c1\n    .tv insert c  end -id c2\n    .tv insert c1 end -id c11\n    consistencyCheck .tv\n    .tv delete c\n    consistencyCheck .tv\n    list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11]\n} -result [list 0 0 0 0]\n\ntest treeview-6.4 \"delete - delete parent and descendants\" -body {\n    .tv insert dtest end -id c\n    .tv insert c  end -id c1\n    .tv insert c  end -id c2\n    .tv insert c1 end -id c11\n    consistencyCheck .tv\n    .tv delete [list c c1 c2 c11]\n    consistencyCheck .tv\n    list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11]\n} -result [list 0 0 0 0]\n\ntest treeview-6.5 \"delete - delete descendants and parent\" -body {\n    .tv insert dtest end -id c\n    .tv insert c  end -id c1\n    .tv insert c  end -id c2\n    .tv insert c1 end -id c11\n    consistencyCheck .tv\n    .tv delete [list c11 c1 c2 c]\n    consistencyCheck .tv\n    list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11]\n} -result [list 0 0 0 0]\n\ntest treeview-6.6 \"delete - end\" -body {\n    consistencyCheck .tv\n    .tv children dtest\n} -result [list d]\n\ntest treeview-7.1 \"move\" -body {\n    .tv insert d end -id d1\n    .tv insert d end -id d2\n    .tv insert d end -id d3\n    .tv move d3 d 0\n    consistencyCheck .tv\n    .tv children d\n} -result [list d3 d1 d2]\n\ntest treeview-7.2 \"illegal move\" -body {\n   .tv move d d2 end\n} -returnCodes error -result \"Cannot insert d as descendant of d2\"\n\ntest treeview-7.3 \"illegal move has no effect\" -body {\n    consistencyCheck .tv\n    .tv children d\n} -result [list d3 d1 d2]\n\ntest treeview-7.4 \"Replace children\" -body {\n    .tv children d [list d3 d2 d1]\n    consistencyCheck .tv\n    .tv children d\n} -result [list d3 d2 d1]\n\ntest treeview-7.5 \"replace children - precondition\" -body {\n    # Just check to make sure the test suite so far has left\n    # us in the state we expect to be in:\n    list [.tv parent newnode] [.tv children newnode]\n} -result [list {} [list newnode.n1 newnode.n2 newnode.n3]]\n\ntest treeview-7.6 \"Replace children - illegal move\" -body {\n    .tv children newnode.n1 [list newnode.n1 newnode.n2 newnode.n3]\n} -cleanup {\n    consistencyCheck .tv\n} -returnCodes error -result \"Cannot insert newnode.n1 as descendant of newnode.n1\"\n\ntest treeview-8.0 \"Selection set\" -body {\n    .tv selection set [list newnode.n1 newnode.n3 newnode.n2]\n    .tv selection\n} -result [list newnode.n1 newnode.n2 newnode.n3]\n\ntest treeview-8.1 \"Selection add\" -body {\n    .tv selection add [list newnode]\n    .tv selection\n} -result [list newnode newnode.n1 newnode.n2 newnode.n3]\n\ntest treeview-8.2 \"Selection toggle\" -body {\n    .tv selection toggle [list newnode.n2 d3]\n    .tv selection\n} -result [list newnode newnode.n1 newnode.n3 d3]\n\ntest treeview-8.3 \"Selection remove\" -body {\n    .tv selection remove [list newnode.n2 d3]\n    .tv selection\n} -result [list newnode newnode.n1 newnode.n3]\n\ntest treeview-8.4 \"Selection - clear\" -body {\n    .tv selection set {}\n    .tv selection\n} -result {}\n\ntest treeview-8.5 \"Selection - bad operation\" -body {\n    .tv selection badop foo\n} -returnCodes error -match glob -result {bad selection operation \"badop\": must be *}\n\ntest treeview-8.7 \"<<TreeviewSelect>> when deleting items\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv insert \"\" end -id myItem2 -text SecondItem\n    .tv selection add myItem1\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv delete myItem2  ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 2\n    .tv delete myItem1  ; # <<TreeviewSelect>> triggers\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {2}\n\ntest treeview-8.8 \"<<TreeviewSelect>> when setting the selection\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv insert \"\" end -id myItem2 -text SecondItem\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv selection set \"\"       ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 2\n    .tv selection set myItem1  ; # <<TreeviewSelect>> triggers\n    update\n    # Current implementation generates an event for this case\n    set val 3\n    .tv selection set myItem1  ; # (already selected)\n    update\n    set val 4\n    .tv selection set {myItem1 myItem2}  ; # <<TreeviewSelect>> triggers\n    update\n    set val 5\n    .tv selection set {myItem2}  ; # <<TreeviewSelect>> triggers\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {2 3 4 5}\n\ntest treeview-8.9 \"<<TreeviewSelect>> when removing items from the selection\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv selection set myItem1\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv selection remove \"\"       ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 2\n    .tv selection remove myItem1  ; # <<TreeviewSelect>> triggers\n    update\n    set val 3\n    .tv selection remove myItem1  ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {2}\n\ntest treeview-8.10 \"<<TreeviewSelect>> when adding items in the selection\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv insert \"\" end -id myItem2 -text SecondItem\n    .tv insert \"\" end -id myItem3 -text ThirdItem\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv selection add myItem2  ; # <<TreeviewSelect>> triggers\n    update\n    set val 2\n    .tv selection add myItem2  ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 3\n    .tv selection add myItem3  ; # <<TreeviewSelect>> triggers\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {1 3}\n\ntest treeview-8.11 \"<<TreeviewSelect>> when toggling\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv insert \"\" end -id myItem2 -text SecondItem\n    .tv insert \"\" end -id myItem3 -text ThirdItem\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv selection toggle \"\"  ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 2\n    .tv selection toggle {myItem1 myItem3}  ; # <<TreeviewSelect>> triggers\n    update\n    set val 3\n    .tv selection toggle {myItem3 myItem2}  ; # <<TreeviewSelect>> triggers\n    update\n    set val 4\n    .tv selection toggle {myItem3 myItem2}  ; # <<TreeviewSelect>> triggers\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {2 3 4}\n\n### NEED: more tests for see/yview/scrolling\n\ntest treeview-9.0 \"scroll callback - empty tree\" -body {\n    tvSetup\n    .tv configure -yscrollcommand setScrollInfo\n    .tv delete [.tv children {}]\n    update\n    set scrollInfo\n} -result [list 0.0 1.0]\n\ntest treeview-9.1 \"scrolling\" -setup {\n    pack [ttk::treeview .tree -show tree] -fill y\n    for {set i 1} {$i < 100} {incr i} {\n\t.tree insert {} end -text $i\n    }\n} -body {\n    .tree yview scroll 5 units\n    # This is sensitive to the exact layout of a tree.\n    # It assumes that (8,8) should be far enough in to be in the tree,\n    # while still being in the first item.\n    .tree identify item 8 8\n} -cleanup {\n    destroy .tree\n} -result {I006}\n\ntest treeview-9.2 {scrolling on see command - bug [14188104c3]} -setup {\n    toplevel .top\n    ttk::treeview .top.tree -show {} -height 10 -columns {label} \\\n\t    -yscrollcommand [list .top.vs set]\n    ttk::scrollbar .top.vs -command {.top.tree yview}\n    grid .top.tree -row 0 -column 0 -sticky ns\n    grid .top.vs -row 0 -column 1 -sticky ns\n    update\n    proc setrows {n} {\n\t.top.tree delete [.top.tree children {}]\n\tfor {set i 1} {$i <= $n} {incr i} {\n\t    .top.tree insert {} end -id row$i \\\n\t\t    -values [list [format \"Row %2.2d\" $i]]\n\t}\n\t.top.tree see row1\n\tupdate idletasks\n    }\n} -body {\n    setrows 10\n    set res [.top.vs get]\n    setrows 20\n    lappend res [expr {[lindex [.top.vs get] 1] < 1}]\n} -cleanup {\n    destroy .top\n} -result {0.0 1.0 1}\n\ntest treeview-9.3 {scrolling on see command, requested item is closed} -setup {\n    toplevel .top\n    ttk::treeview .top.tree -show tree -height 10 -columns {label} \\\n\t    -yscrollcommand [list .top.vs set]\n    ttk::scrollbar .top.vs -command {.top.tree yview}\n    grid .top.tree -row 0 -column 0 -sticky ns\n    grid .top.vs -row 0 -column 1 -sticky ns\n\n    .top.tree insert {} end -id a -text a\n    .top.tree insert a  end -id b -text b\n    .top.tree insert b  end -id c -text c\n    .top.tree insert c  end -id d -text d\n    .top.tree insert d  end -id e -text e\n    for {set i 6} {$i <= 15} {incr i} {\n\t.top.tree insert {} end -id row$i \\\n\t\t-values [list [format \"Row %2.2d\" $i]]\n    }\n    update\n} -body {\n    set before [lindex [.top.vs get] 1]\n    .top.tree see e\n    update idletasks\n    set after [lindex [.top.vs get] 1]\n    expr {$after < $before}\n} -cleanup {\n    destroy .top\n} -result 1\ntest treeview-9.4 {no scrolling on see command on an item below a detached item; bbox on such item is empty} -setup {\n    toplevel .top\n    ttk::treeview .top.tree -show tree -height 10 -columns {label} \\\n\t    -yscrollcommand [list .top.vs set]\n    ttk::scrollbar .top.vs -command {.top.tree yview}\n    grid .top.tree -row 0 -column 0 -sticky ns\n    grid .top.vs -row 0 -column 1 -sticky ns\n\n    foreach dir {A B C D E F G H} {\n\tset id [string cat dir $dir]\n\t.top.tree insert {} end -id $id -text \"dir $dir\" -open 1\n\tfor {set i 1} {$i <= 10} {incr i} {\n\t    .top.tree insert $id end -id $id-$i -text \"dir $dir item $i\"\n\t}\n    }\n    update\n    .top.tree detach dirD\n    .top.tree item dirC -open 0\n    update\n} -body {\n    set before [lindex [.top.vs get] 1]\n    .top.tree see dirD-4\n    update\n    set after [lindex [.top.vs get] 1]\n    set res [expr {$after == $before}]\n    lappend res [.top.tree bbox dirD-4]\n} -cleanup {\n    destroy .top\n} -result {1 {}}\n\ntest treeview-10.0 \"See command\" -setup {\n    # Setup common for all 10.* tests\n    ttk::style configure Treeview -rowheight 20\n    tvSetupWithItems\n    set ::baseBbY [lindex [.tv bbox nn \"#1\"] 1]\n    proc bbY {item} {\n\tset bb [.tv bbox $item \"#1\"]\n\tset y [lindex $bb 1]\n\tif {$y eq \"\"} {return \"_\"}\n\treturn [expr {$y - $::baseBbY}]\n    }\n} -body {\n    set res \"\"\n    lappend res [bbY nn99]\n    .tv see nn99\n    lappend res [bbY nn99]\n    set res\n} -result {_ 180}\n\ntest treeview-10.1 \"See command, auto-open\" -body {\n    set res \"\"\n    lappend res [bbY nn96]\n    # Not yet visible\n    lappend res [bbY nn96.n1]\n    .tv see nn96.n1\n    lappend res [bbY nn96.n1]\n    # Pushed out by the opening, not visible\n    lappend res [bbY nn99]\n    set res\n} -result {120 _ 140 _}\n\ntest treeview-10.2 \"See command, height\" -setup {\n    .tv item nn34 -height 4\n    .tv item nn55 -height 30\n    .tv item nn76 -height 5\n} -body {\n    set res \"\"\n    lappend res [bbY nn34]\n    .tv see nn34\n    lappend res [bbY nn34]\n    .tv see nn33\n    lappend res [bbY nn34]\n\n    lappend res [bbY nn76]\n    .tv see nn76\n    lappend res [bbY nn76]\n\n    .tv see nn53\n    lappend res [bbY nn53]\n    # Partly visible\n    lappend res [bbY nn55]\n    .tv see nn55\n    # Scrolled to top\n    lappend res [bbY nn55]\n    set res\n} -result {_ 0 20 _ 100 0 40 0}\n\ntest treeview-11.0 \"Cellselection set rectangle\" -setup {\n    # Setup common for all 11.* tests\n    tvSetupWithItems\n    .tv configure -columns {a b c d}\n    .tv configure -displaycolumns {a b c}\n} -body {\n    .tv cellselection set \"nn.n3 #2\" \"nn.n1 a\"\n    .tv cellselection\n} -result [list \"nn.n1 a\" \"nn.n1 b\" \"nn.n2 a\" \"nn.n2 b\" \"nn.n3 a\" \"nn.n3 b\"]\n\ntest treeview-11.1 \"Cellselection set\" -body {\n    .tv cellselection set [list \"nn.n1 a\" \"nn.n2 a\" \"nn.n3 #2\" \"nn.n2 d\"]\n    .tv cellselection\n} -result [list \"nn.n1 a\" \"nn.n2 a\" \"nn.n2 d\" \"nn.n3 b\"]\n\ntest treeview-11.2 \"Cellselection add\" -body {\n    .tv cellselection add \"nn b\"\n    .tv cellselection\n} -result [list \"nn b\" \"nn.n1 a\" \"nn.n2 a\" \"nn.n2 d\" \"nn.n3 b\"]\n\ntest treeview-11.3 \"Cellselection toggle\" -body {\n    .tv cellselection toggle [list \"nn.n2 a\" \"nn2 b\" \"nn2 #0\"]\n    .tv cellselection\n} -result [list \"nn b\" \"nn.n1 a\" \"nn.n2 d\" \"nn.n3 b\" \"nn2 b\" \"nn2 #0\"]\n\ntest treeview-11.4 \"Cellselection remove\" -body {\n    .tv cellselection remove [list \"nn.n2 d\" \"nn b\" \"nn2 #0\"]\n    .tv cellselection\n} -result [list \"nn.n1 a\" \"nn.n3 b\" \"nn2 b\"]\n\ntest treeview-11.5 \"Cellselection add rectangle\" -body {\n    .tv cellselection add \"nn a\" \"nn.n1 c\"\n    .tv cellselection\n} -result [list \\\n\t\t   \"nn a\" \"nn b\" \"nn c\" \\\n\t\t   \"nn.n1 a\" \"nn.n1 b\" \"nn.n1 c\" \\\n\t\t   \"nn.n3 b\" \\\n\t\t   \"nn2 b\"]\n\ntest treeview-11.6 \"Cellselection toggle rectangle\" -body {\n    .tv cellselection toggle \"nn.n1 b\" \"nn.n3 c\"\n    .tv cellselection\n} -result [list \\\n\t\t   \"nn a\" \"nn b\" \"nn c\" \\\n\t\t   \"nn.n1 a\" \\\n\t\t   \"nn.n2 b\" \"nn.n2 c\" \\\n\t\t   \"nn.n3 c\" \\\n\t\t   \"nn2 b\"]\n\ntest treeview-11.7 \"Cellselection remove rectangle\" -body {\n    .tv cellselection remove \"nn.n1 a\" \"nn.n3 b\"\n    .tv cellselection\n} -result [list \\\n\t\t   \"nn a\" \"nn b\" \"nn c\" \\\n\t\t   \"nn.n2 c\" \\\n\t\t   \"nn.n3 c\" \\\n\t\t   \"nn2 b\"]\n\ntest treeview-11.8 \"Cellselection set rectangle\" -body {\n    # This tests that \"set\" clears out all old selections\n    .tv cellselection set \"nn b\" \"nn.n1 c\"\n    .tv cellselection\n} -result [list \"nn b\" \"nn c\" \"nn.n1 b\" \"nn.n1 c\"]\n\ntest treeview-11.9 \"Cellselection - clear\" -body {\n    .tv cellselection set {}\n    .tv cellselection\n} -result {}\n\ntest treeview-11.10 \"Cellselection - bad operation\" -body {\n    .tv cellselection badop foo\n} -returnCodes 1 -match glob -result {bad cellselection operation \"badop\": must be *}\n\ntest treeview-11.11 \"Cellselection - <<TreeviewSelect>> on cellselection add\" -body {\n    .tv cellselection set {}\n    bind .tv <<TreeviewSelect>> {set res 1}\n    set res 0\n    .tv cellselection add {\"nn.n1 b\"}\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result 1\n\ntest treeview-11.12 \"<<TreeviewSelect>> on selected cell deletion\" -body {\n    .tv cellselection set {}\n    .tv insert \"\" end -id selectedDoomed -text DeadItem\n    .tv insert \"\" end -id doomed -text AlsoDead\n    .tv cellselection add {\"selectedDoomed c\"}\n    .tv cellselection add {\"doomed c\"}\n    .tv cellselection remove {\"doomed c\"}\n    update\n    bind .tv <<TreeviewSelect>> {lappend res 1}\n    set res 0\n    .tv delete doomed\n    update\n    set res [expr {$res == 0}]\n    .tv delete selectedDoomed\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {1 1}\n\ntest treeview-11.13 \"Cellselection - error\" -body {\n    .tv cellselection set [list \"apa a\"]\n} -returnCodes 1 -match glob -result {Item apa not found}\n\ntest treeview-11.14 \"Cellselection - error\" -body {\n    .tv cellselection set [list \"nn xx \"]\n} -returnCodes 1 -match glob -result {Invalid column index \"xx\"}\n\ntest treeview-11.15 \"Cellselection - error\" -body {\n    .tv cellselection set \"nn c\" \"nn d\"\n} -returnCodes 1 -match glob -result {Cell id must be in a visible column}\n\ntest treeview-11.16 \"Cellselection - non visible\" -body {\n    .tv cellselection set [list \"nn d\"]\n    .tv cellselection\n} -result {{nn d}}\n\n# Same as 8.8, but for cell selection\ntest treeview-11.17 \"<<TreeviewSelect>> when setting the selection\" -body {\n    .tv delete [.tv children {}]\n    .tv insert \"\" end -id myItem1 -text FirstItem\n    .tv insert \"\" end -id myItem2 -text SecondItem\n    update\n    bind .tv <<TreeviewSelect>> {lappend res $val}\n    set res {}\n    set val 1\n    .tv cellselection set \"\"   ; # no <<TreeviewSelect>> (selection unchanged)\n    update\n    set val 2\n    .tv cellselection set \"myItem1 a\"  ; # <<TreeviewSelect>> triggers\n    update\n    # Current implementation generates an event for this case\n    set val 3\n    .tv cellselection set \"myItem1 a\"  ; # (already selected)\n    update\n    set val 4\n    .tv cellselection set {{myItem1 a} {myItem2 a}} ; # <<TreeviewSelect>>\n    update\n    set val 5\n    .tv cellselection set {myItem2 a}  ; # <<TreeviewSelect>> triggers\n    update\n    set res\n} -cleanup {\n    bind .tv <<TreeviewSelect>> {}\n} -result {2 3 4 5}\n\n#\n# identify tests\n#\n\ntest treeview-identify-setup \"identify series - setup\" -body {\n    destroy .tv\n    ttk::setTheme default\n    ttk::style configure Treeview -rowheight 10m\n    ttk::style configure Treeview.Heading -font {Arial 10}\n    ttk::treeview .tv -columns [list A B C]\n    .tv insert {} end -id branch -text branch -open true\n    .tv insert branch end -id item1 -text item1 -height 2\n    .tv insert branch end -id item2 -text item2\n    .tv insert branch end -id item3 -text item3\n    .tv insert {} end -id item4 -text item4\n\n    .tv column #0 -width 200\t;# 0-200\n    .tv column A -width 200\t;# 200-400\n    .tv column B -width 200\t;# 400-600\n    .tv column C -width 200\t;# 600-800 (plus slop for margins)\n\n    wm geometry . {} ; pack .tv ; update\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# treeview-identify-setup sets heading row font to Arial with size 10 points,\n# so the heading line center y-coordinate is (in pixels):\nset yHLC [expr {([font metrics {Arial 10} -linespace] + 2) / 2.0}]\n# which makes the following in millimeters:\nset yHLC [expr {$yHLC / [winfo screenwidth .] * [winfo screenmmwidth .]}]\n\ntest treeview-identify-1 \"identify heading\" -body {\n    .tv configure -show {headings tree}\n    update idletasks\n    identify* .tv {region column} 10 ${yHLC}m\n} -result [list heading #0]\n\ntest treeview-identify-2 \"identify columns\" -body {\n    .tv configure -displaycolumns #all\n    update idletasks\n    columnids .tv [identify* .tv column 100 ${yHLC}m  300 ${yHLC}m  500 ${yHLC}m  700 ${yHLC}m]\n} -result [list \\#0 A B C]\n\ntest treeview-identify-3 \"reordered columns\" -body {\n    .tv configure -displaycolumns {B A C}\n    update idletasks\n    columnids .tv [identify* .tv column 100 ${yHLC}m  300 ${yHLC}m  500 ${yHLC}m  700 ${yHLC}m]\n} -result [list \\#0 B A C]\n\ntest treeview-identify-4 \"no tree column\" -body {\n    .tv configure -displaycolumns #all -show {headings}\n    update idletasks\n    identify* .tv {region column} 100 ${yHLC}m  300 ${yHLC}m  500 ${yHLC}m  700 ${yHLC}m\n} -result [list heading #1 heading #2 heading #3 nothing {}]\n\n# Item height (-rowheight) is 10 millimeters (set in treeview-identify-setup)\ntest treeview-identify-5 \"vertical scan - no headings\" -body {\n    .tv configure -displaycolumns #all -show {tree}\n    update idletasks\n    identify* .tv {region item} 100 5m  100 15m  100 35m  100 45m  100 55m  100 65m\n} -result [list tree branch tree item1 tree item2 tree item3 tree item4 nothing {}]\n\ntest treeview-identify-6 \"vertical scan - with headings\" -body {\n    .tv configure -displaycolumns #all -show {tree headings}\n    update idletasks\n    identify* .tv {region item} 100 ${yHLC}m  100 [expr {$yHLC+5}]m  100 [expr {$yHLC+15}]m  100 [expr {$yHLC+35}]m  100 [expr {$yHLC+45}]m\n} -result [list heading {} tree branch tree item1 tree item2 tree item3]\n\ntest treeview-identify-7 \"vertical scan - headings, no tree\" -body {\n    .tv configure -displaycolumns #all -show {headings}\n    update idletasks\n    identify* .tv {region item cell} 100 ${yHLC}m  100 [expr {$yHLC+5}]m  100 [expr {$yHLC+15}]m  300 [expr {$yHLC+35}]m  100 [expr {$yHLC+45}]m\n} -result [list heading {} {} cell branch {branch #1} cell item1 {item1 #1} cell item2 {item2 #2} cell item3 {item3 #1}]\n\n# Disclosure element name is \"Treeitem.indicator\"\ntest treeview-identify-8 \"identify element\" -body {\n    .tv configure -show {tree}\n    .tv insert branch  0 -id branch2 -open true\n    .tv insert branch2 0 -id branch3 -open true\n    .tv insert branch3 0 -id leaf3\n    ttk::style configure Treeview -indent 8m\n    update idletasks\n    identify* .tv {item element} 4m 5m  12m 15m  20m 25m\n} -match glob -result [list \\\n\tbranch \"*.indicator\" branch2 \"*.indicator\" branch3 \"*.indicator\"]\n\ntest treeview-identify-8.1 \"identify element\" -body {\n    .tv configure -show {tree headings}\n    update\n    identify* .tv element 1 1  40 ${yHLC}m  10m [expr {$yHLC+6}]m\n    # Heading elements are currently not reported\n} -result [list {} {} text]\n\n#\n# COMMON TEST SETUP\n#\n\nttk::style configure Treeview -rowheight 20\n\n# See #2381555\ntest treeview-identify-9 \"identify works when horizontally scrolled\" -setup {\n    .tv configure -show {tree headings}\n    foreach column {#0 A B C} {\n\t.tv column $column -stretch 0 -width 50\n    }\n    # Scrollable area is 200, visible is 100\n    place .tv -x 0 -y 0 -width 100\n} -body {\n    set result [list]\n    foreach xoffs {0 50 100} {\n\t.tv xview $xoffs ; update\n\tlappend result [identify* .tv {region column} 10 10 60 10]\n    }\n    set result\n} -result [list \\\n\t[list heading #0 heading #1] \\\n\t[list heading #1 heading #2] \\\n\t[list heading #2 heading #3] ]\n\ntest treeview-identify-10 \"identify works when horizontally scrolled\" -setup {\n    .tv configure -show {tree headings}\n    .tv configure -titlecolumns 1\n    foreach column {\"#0\" A B C} {\n\t.tv column $column -stretch 0 -width 50\n    }\n    # Scrollable area is 200, visible is 150\n    place .tv -x 0 -y 0 -width 150\n} -body {\n    set result [list]\n    foreach xoffs {0 25 50} {\n\t.tv xview $xoffs\n\tupdate\n\tlappend result [identify* .tv {region column} 10 10 60 10]\n\tlappend result [identify* .tv {region column} 10 50 60 50]\n    }\n    set result\n} -result [list \\\n\t[list heading #0 heading #1] [list tree #0 cell #1] \\\n\t[list heading #0 heading #1] [list tree #0 cell #1] \\\n\t[list heading #0 heading #2] [list tree #0 cell #2] ]\n\n# Hijack the setup above to check bbox too\ntest treeview-identify-10b \"bbox works when horizontally scrolled\" -body {\n    # Establish a point of reference\n    .tv configure -titlecolumns 0\n    .tv xview 0\n    update\n    set base [lindex [.tv bbox branch \"#0\"] 0]\n    set result [list]\n    foreach tc {0 1 2 3} {\n\t.tv configure -titlecolumns $tc\n\tforeach xoffs {0 25 50} {\n\t    .tv xview $xoffs\n\t    update\n\t    # Extract x coordinate for each column\n\t    lappend result [expr {[lindex [.tv bbox branch \"#0\"] 0] - $base}]\n\t    lappend result [expr {[lindex [.tv bbox branch A   ] 0] - $base}]\n\t    lappend result [expr {[lindex [.tv bbox branch B   ] 0] - $base}]\n\t    lappend result [expr {[lindex [.tv bbox branch C   ] 0] - $base}]\n\t}\n    }\n    set result\n} -result [list 0 50 100 150  -25 25  75 125   -50  0  50 100 \\\n\t\t0 50 100 150    0 25  75 125     0  0  50 100 \\\n\t\t0 50 100 150    0 50  75 125     0 50  50 100 \\\n\t\t0 50 100 150    0 50 100 125     0 50 100 101]\n\n# Followup to trigger crash that happened when title > display\ntest treeview-identify-10c \"title more than display\" -body {\n    .tv configure -titlecolumns 10\n    .tv xview 0\n    update\n    set x1 [.tv xview]\n    # It shouldn't be possible to scroll\n    .tv xview 50\n    update\n    set x2 [.tv xview]\n    set result [list $x1 $x2]\n} -result {{0.0 1.0} {0.0 1.0}}\n\n\ntest treeview-identify-11 \"bbox supporting -height\" -body {\n    .tv configure -titlecolumns 0\n    .tv xview 0\n    .tv item branch2 -open false\n    # Add extra items to make sure it scrolls\n    .tv insert {} end -id item5 -text item5\n    .tv insert {} end -id item6 -text item6\n    # Height needs to be big enough to show the items we measure\n    # and small enough to make scrolling happen.\n    .tv configure -height 6\n    pack .tv -side top\n    update\n    set base [lindex [.tv bbox branch A] 1]\n    set result {}\n    foreach yv {0 1} {\n\t.tv yview $yv\n\tupdate\n\tforeach item {item1 item2 item3} {\n\t    set bb [.tv bbox $item A]\n\t    set y [lindex $bb 1]\n\t    if {$y eq \"\"} {\n\t\t# This is to get a clearer error if this goes wrong\n\t\tlappend result {}\n\t    } else {\n\t\tlappend result [expr {$y - $base}]\n\t    }\n\t    lappend result [lindex $bb 3]\n\t}\n    }\n    set result\n} -result [list 40 40 80 20 100 20  20 40 60 20 80 20]\n\ntest treeview-identify-cleanup \"identify - cleanup\" -body {\n    destroy .tv\n}\n\n\ntest treeview-rowheight-1 \"rowheight - setup\" -body {\n    destroy .tv\n    ttk::setTheme default\n    # Test that style rowheight is in control\n    ttk::style configure Treeview -rowheight 73\n    tvSetupWithItems\n    lindex [.tv bbox nn a] 3\n} -result 73\n\ntest treeview-rowheight-2 \"rowheight change\" -body {\n    # Reacts to style changes\n    ttk::style configure Treeview -rowheight 25\n    update\n    lindex [.tv bbox nn a] 3\n} -cleanup {\n    ttk::style configure Treeview -rowheight {}\n} -result 25\n\ntest treeview-rowheight-3 \"rowheight adapts to font\" -constraints haveBigFontTwiceLargerThanTextFont -body {\n    ttk::style configure Treeview -font \"Courier 12\"\n    update\n    set baseline [lindex [.tv bbox nn a] 3]\n    ttk::style configure Treeview -font \"Helvetica 24\"\n    update\n    set after [lindex [.tv bbox nn a] 3]\n    set diff [expr {$after - $baseline}]\n    # We only want to check there is an increase,\n    # its exact magnitude does not matter\n    expr {0 < $diff ? \"OK\" : $diff}\n} -result OK\n\ntest treeview-rowheight-3b \"rowheight adapts to named font\" -constraints haveBigFontTwiceLargerThanTextFont -body {\n    font create __tf -family Courier -size 12\n    ttk::style configure Treeview -font __tf\n    update\n    set baseline [lindex [.tv bbox nn a] 3]\n    font configure __tf -family Helvetica -size 24\n    update\n    set after [lindex [.tv bbox nn a] 3]\n    set diff [expr {$after - $baseline}]\n    # We only want to check there is an increase,\n    # its exact magnitude does not matter\n    expr {0 < $diff ? \"OK\" : $diff}\n} -result OK\n\ntest treeview-rowheight-4 \"rowheight adapts to item padding\" -body {\n    # Test that things from Item style is picked up.\n    ttk::style configure Item -padding \"2 2 2 2\"\n    update\n    set baseline [lindex [.tv bbox nn a] 3]\n    ttk::style configure Item -padding \"2 3 2 5\"\n    update\n    set after [lindex [.tv bbox nn a] 3]\n    set diff [expr {$after - $baseline}]\n} -cleanup {\n    ttk::style configure Item -padding {}\n} -result [expr {3-2 + 5-2}]\n\ntest treeview-rowheight-5 \"rowheight adapts to cell padding\" -body {\n    # Test that things from Cell style is picked up.\n    ttk::style configure Cell -padding \"2 5 2 5\"\n    update\n    set baseline [lindex [.tv bbox nn a] 3]\n    ttk::style configure Cell -padding \"2 8 2 9\"\n    update\n    set after [lindex [.tv bbox nn a] 3]\n    set diff [expr {$after - $baseline}]\n} -cleanup {\n    ttk::style configure Cell -padding {}\n} -result [expr {8-5 + 9-5}]\n\n#\n# COMMON TEST CLEANUP\n#\n\ndestroy .tv\n\n### Misc. tests:\n\ntest treeview-1541739 \"Root node properly initialized (#1541739)\" -setup {\n    ttk::treeview .tv\n    .tv insert {} end -id a\n    .tv see a\n} -cleanup {\n    destroy .tv\n}\n\ntest treeview-3006842 \"Null bindings\" -setup {\n    ttk::treeview .tv -show tree\n} -body {\n    .tv tag bind empty <Button-1> {}\n    .tv insert {} end -text \"Click me\" -tags empty\n    event generate .tv <Button-1> -x 10 -y 10\n    .tv tag bind empty\n} -result {} -cleanup {\n    destroy .tv\n}\n\ntest treeview-3085489-1 \"tag add, no -tags\" -setup {\n    ttk::treeview .tv\n} -body {\n    set item [.tv insert {} end]\n    .tv tag add foo $item\n    .tv item $item -tags\n} -cleanup {\n    destroy .tv\n} -result [list foo]\n\ntest treeview-3085489-2 \"tag remove, no -tags\" -setup {\n    ttk::treeview .tv\n} -body {\n    set item [.tv insert {} end]\n    .tv tag remove foo $item\n    .tv item $item -tags\n} -cleanup {\n    destroy .tv\n} -result [list]\n\ntest treeview-368fa4561e \"indicators cannot be clicked on leafs\" -setup {\n    pack [ttk::treeview .tv]\n    .tv insert {} end -id foo -text \"<-- (1) Click the blank space to my left\"\n    update\n} -body {\n    foreach {x y w h} [.tv bbox foo #0] {}\n    set res [.tv item foo -open]\n    # using $h even for x computation is intentional here in order to simulate\n    # a mouse click on the (invisible since we're on a leaf) indicator\n    event generate .tv <Button-1> \\\n\t    -x [expr {$x + $h / 2}] \\\n\t    -y [expr {$y + $h / 2}]\n    lappend res [.tv item foo -open]\n    .tv insert foo end -text \"sub\"\n    lappend res [.tv item foo -open]\n} -cleanup {\n    destroy .tv\n} -result {0 0 0}\n\ntest treeview-ce470f20fd-1 \"dragging further than the right edge of the treeview is allowed\" -setup {\n    pack [ttk::treeview .tv]\n    .tv heading #0 -text \"Drag my right edge -->\"\n    update\n} -body {\n    set res [.tv column #0 -width]\n    .tv drag #0 400\n    lappend res [expr {[.tv column #0 -width] > $res}]\n} -cleanup {\n    destroy .tv\n} -result {200 1}\n\ntest treeview-ce470f20fd-2 \"changing -stretch resizes columns\" -setup {\n    pack [ttk::treeview .tv -columns {bar colA colB colC foo}]\n    foreach col [.tv cget -columns] {\n\t.tv heading $col -text $col\n    }\n    nostretch .tv\n    .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created\n    update idletasks ; # redisplay treeview\n} -body {\n    # when no column is stretchable and one of them becomes stretchable\n    # the stretchable column takes the slack and the widget is redisplayed\n    # automatically at idle time\n    set res [.tv column colA -width]\n    .tv column colA -stretch 1\n    update idletasks ; # no slack anymore, widget redisplayed\n    lappend res [expr {[.tv column colA -width] > $res}]\n} -cleanup {\n    destroy .tv\n} -result {50 1}\n\ntest treeview-ce470f20fd-3 \"changing -stretch resizes columns\" -setup {\n    pack [ttk::treeview .tv -columns {bar colA colB colC foo}]\n    foreach col [.tv cget -columns] {\n\t.tv heading $col -text $col\n    }\n    .tv configure -displaycolumns {colB colA colC}\n    nostretch .tv\n    .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created\n    update idletasks ; # redisplay treeview\n} -body {\n    # only some columns are displayed (and in a different order than declared\n    # in -columns), a displayed column becomes stretchable  --> the stretchable\n    # column expands\n    set res [.tv column colA -width]\n    .tv column colA -stretch 1\n    update idletasks ; # no slack anymore, widget redisplayed\n    lappend res [expr {[.tv column colA -width] > $res}]\n} -cleanup {\n    destroy .tv\n} -result {50 1}\n\ntest treeview-ce470f20fd-4 \"changing -stretch resizes columns\" -setup {\n    pack [ttk::treeview .tv -columns {bar colA colB colC foo}]\n    foreach col [.tv cget -columns] {\n\t.tv heading $col -text $col\n    }\n    .tv configure -displaycolumns {colB colA colC}\n    nostretch .tv\n    .tv column colA -width 50 ; .tv column bar -width 60 ; # slack created\n    update idletasks ; # redisplay treeview\n} -body {\n    # only some columns are displayed (and in a different order than declared\n    # in -columns), a non-displayed column becomes stretchable  --> nothing\n    # happens\n    set origTreeWidth [winfo width .tv]\n    set res [list [.tv column bar -width] [.tv column colA -width]]\n    .tv column bar -stretch 1\n    update idletasks ; # no change, widget redisplayed\n    lappend res [.tv column bar -width] [.tv column colA -width]\n    # this column becomes visible  --> widget resizes\n    .tv configure -displaycolumns {bar colC colA colB}\n    update idletasks ; # no slack anymore because the widget resizes (shrinks)\n    lappend res [.tv column bar -width] [.tv column colA -width] \\\n\t\t[expr {[winfo width .tv] < $origTreeWidth}]\n} -cleanup {\n    destroy .tv\n} -result {60 50 60 50 60 50 1}\n\ntest treeview-bc602049ab \"treeview with custom background does not change size when switching themes\" -setup {\n    image create photo tvbg -data {\n\tiVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAnXAAAJ1wG\n\txbhe3AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAACJJREFUOI\n\t1jPLF9+38GKgImaho2auCogaMGjho4auBQMhAAyR0DXUEyypsAAAAASUVORK5CYII=\n    }\n    ttk::style theme create foo-bc602049ab -parent clam -settings {\n      ttk::style element create Treeview.field image tvbg -width 0 -height 0\n    }\n    ttk::style theme use foo-bc602049ab\n    pack [ttk::treeview .tv]\n    update idletasks\n} -body {\n    set g1 [winfo geometry .tv]\n    ttk::style theme use foo-bc602049ab\n    update idletasks\n    set g2 [winfo geometry .tv]\n    expr {$g1 eq $g2 ? 1 : \"$g1 --> $g2\"}\n} -cleanup {\n    destroy .tv\n    image delete tvbg\n} -result {1}\n\ntest treeview-6ee162c3d9 \"style configure Treeview -rowheight 0\" -setup {\n    tvSetupWithItems\n} -body {\n    ttk::style configure Treeview -rowheight 0  ; # shall not crash\n    update\n} -result {}\n\ntest treeview-column0-leak \"Test for leak in tree column\" -setup {\n    destroy .ttt\n    set heading [string range _Hej_ 1 3]\n} -body {\n    for {set t 0} {$t < 3} {incr t} {\n\tttk::treeview .tapa -columns \"hej hopp\"\n\t.tapa heading #0 -text $heading\n\tdestroy .tapa\n    }\n    tcl::unsupported::representation $heading\n} -match glob -result {*refcount of 3,*}\n\ntest treeview-21.1 \"style command\" -body {\n    ttk::treeview .w\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {{} Treeview Treeview}\ntest treeview-21.2 \"style command\" -body {\n    ttk::style configure customStyle.Treeview\n    ttk::treeview .w -style customStyle.Treeview\n    list [.w cget -style] [.w style] [winfo class .w]\n} -cleanup {\n    destroy .w\n} -result {customStyle.Treeview customStyle.Treeview Treeview}\n\ntest treeview-22.1 \"tag bindings\" -setup {\n    tvSetupWithItems\n    .tv tag configure t1 -background red\n    .tv tag configure t2 -background blue\n    .tv item nn -open 1\n    # Tags on item and cell to spot the difference\n    .tv tag add t1 \"nn.n1\"\n    .tv tag cell add t2 \"nn.n1 a\"\n    .tv tag cell add t2 \"nn.n2 c\"\n    update\n    proc cellEvent {item col} {\n\t# Find midpoint of cell\n\tlassign [.tv bbox $item $col] aX aY aW aH\n\tset aX [expr {$aX + $aW / 2}]\n\tset aY [expr {$aY + $aH / 2}]\n\tevent generate .tv <Button-1> -x $aX -y $aY\n    }\n} -body {\n    .tv tag bind t1 <Button-1> {lappend ::tagtest t1}\n    .tv tag bind t2 <Button-1> {lappend ::tagtest t2}\n    # Cell with both binds\n    set ::tagtest a\n    cellEvent nn.n1 a\n    # Cell with just item tag\n    lappend ::tagtest b\n    cellEvent nn.n1 b\n    # Cell with just cell tag\n    lappend ::tagtest c\n    cellEvent nn.n2 c\n    # Same tag on both cell and item should fire once\n    .tv tag cell add t1 \"nn.n1 b\"\n    lappend ::tagtest b\n    cellEvent nn.n1 b\n    # Break in first bind\n    .tv tag bind t1 <Button-1> {lappend ::tagtest t1;break}\n    lappend ::tagtest a\n    cellEvent nn.n1 a\n    set ::tagtest\n} -cleanup {\n    rename cellEvent {}\n    destroy .tv\n} -result {a t1 t2 b t1 c t2 b t1 a t1}\ntest treeview-12.2 \"tag bindings deletion on tag delete\" -setup {\n    tvSetupWithItems\n    .tv tag bind nn.n1 <Button-1> {puts Triggered}\n} -body {\n    .tv tag delete nn.n1\n    .tv tag bind nn.n1\n} -cleanup {\n    destroy .tv\n} -result {}\n\ntest treeview-23.1 \"cell padding\" -setup {\n    tvSetupWithItems\n} -body {\n    .tv tag cell add mytag \"nn b\"\n    set redcross [image create photo -format gif -data {R0lGODlhBwAHAIABAP8AAP///\n\t    yH5BAEKAAEALAAAAAAHAAcAAAIMBIKmsWrIXnLxuDMLADs=}]\n    .tv tag configure mytag -image $redcross\n    .tv tag configure mytag -imageanchor nw\n    .tv tag configure mytag -padding {2 4 6 8}\n    .tv tag configure mytag -padding\n} -cleanup {\n    destroy .tv\n} -result {2 4 6 8}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget scroll\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/ttk.test",
    "content": "#\n# Diverse tests for ttk\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc bgerror {error} {\n    variable bgerror $error\n    variable bgerrorInfo $::errorInfo\n    variable bgerrorCode $::errorCode\n}\n\n# Tests using this will fail if the top-level window contains the cursor\nproc checkstate {w} {\n    foreach statespec {\n\t{!active !disabled}\n\t{!active disabled}\n\t{active !disabled}\n\t{active disabled}\n\tactive\n\tdisabled\n    } {\n\tlappend result [$w instate $statespec]\n    }\n    set result\n}\n\nproc selfdestruct {w args} {\n    destroy $w\n}\n\nproc wrong#args {args} {\n    return \"wrong # args: should be \\\"$args\\\"\"\n}\n\nproc wrong#varargs {varpart args} {\n    set usage $args\n    append usage \" ?$varpart ...?\"\n    return \"wrong # args: should be \\\"$usage\\\"\"\n}\n\n#\n# COMMON TEST SETUP\n#\n\nvariable widgetClasses {\n    button checkbutton radiobutton menubutton label entry\n    frame labelframe scrollbar\n    notebook progressbar combobox separator\n    panedwindow treeview sizegrip\n    scale\n}\n\n#\n# TESTS\n#\n\n#\n# Self-destruct tests.\n# Do these early, so any memory corruption has a longer time to cause a crash.\n#\n\ntest ttk-6.1 \"Self-destructing checkbutton\" -body {\n    pack [ttk::checkbutton .sd -text \"Self-destruction\" -variable ::sd]\n    trace add variable sd write [list selfdestruct .sd]\n    update\n    .sd invoke\n} -returnCodes error\ntest ttk-6.2 \"Checkbutton self-destructed\" -body {\n    winfo exists .sd\n} -result 0\n\n# test ttk-6.3 not applicable [see #2175411]\n\ntest ttk-6.4 \"Destroy widget in configure\" -setup {\n    set OUCH ouch\n    trace add variable OUCH read { kill.b }\n    proc kill.b {args} { destroy .b }\n} -cleanup {\n    unset OUCH\n} -body {\n    pack [ttk::checkbutton .b]\n    set rc [catch { .b configure -variable OUCH } msg]\n    list $rc $msg [winfo exists .b] [info commands .b]\n} -result [list 1 \"widget has been destroyed\" 0 {}]\n\ntest ttk-6.5 \"Clean up -textvariable traces\" -body {\n    foreach class {ttk::button ttk::checkbutton ttk::radiobutton} {\n\t$class .b1 -textvariable V\n\tset V \"asdf\"\n\tdestroy .b1\n\tset V \"\"\n    }\n}\n\ntest ttk-6.6 \"Bad color spec in styles\" -body {\n    pack [ttk::button .b1 -text Hi!]\n    ttk::style configure TButton -foreground badColor\n    event generate .b1 <Expose>\n    update\n    ttk::style configure TButton -foreground black\n    destroy .b1\n    set ::bgerror\n} -result {unknown color name \"badColor\"}\n\ntest ttk-6.7 \"Basic destruction test\" -body {\n    foreach widget $widgetClasses {\n\tttk::$widget .w\n\tpack .w\n\tdestroy .w\n    }\n}\n\ntest ttk-6.8 \"Button command removes itself\" -body {\n    ttk::button .b -command \".b configure -command {}; set ::A {it worked}\"\n    .b invoke\n    destroy .b\n    set ::A\n} -result {it worked}\n\ntest ttk-6.9 \"Bad font spec in styles\" -setup {\n    ttk::style theme create badfont -settings {\n\tttk::style configure . -font {Helvetica 12 Bogus}\n    }\n    ttk::style theme use badfont\n} -cleanup {\n    ttk::style theme use default\n} -body {\n    pack [ttk::label .l -text Hi! -font {}]\n    event generate .l <Expose>\n    update\n    destroy .l\n    set ::bgerror\n} -result {unknown font style \"Bogus\"}\n\ntest ttk-construction-failure-1 \"Excercise construction failure path\" -setup {\n    option add *TLabel.cursor badCursor 1\n} -cleanup {\n    option add *TLabel.cursor {} 1\n} -body {\n    catch {ttk::label .l} errmsg\n    list $errmsg [info commands .l] [winfo exists .l]\n} -result [list {bad cursor spec \"badCursor\"} {} 0]\n\ntest ttk-construction-failure-2 \"Destroy widget in constructor\" -setup {\n    set OUCH ouch\n    trace add variable OUCH read { kill.b }\n    proc kill.b {args} { destroy .b }\n} -cleanup {\n    unset OUCH\n} -body {\n    list \\\n\t[catch { ttk::checkbutton .b -variable OUCH } msg] \\\n\t$msg \\\n\t[winfo exists .b] \\\n\t[info commands .b] \\\n\t;\n} -result [list 1 \"widget has been destroyed\" 0 {}]\n\ntest ttk-selfdestruct-ok-1 \"Intentional self-destruction\" -body {\n    # see #2298720\n    toplevel .t\n    ttk::button .t.b -command [list destroy .t]\n    .t.b invoke\n    list [winfo exists .t] [winfo exists .t.b]\n} -result [list 0 0]\n\n#\n# Basic tests.\n#\ntest ttk-1.1 \"Create multiline button showing justified text\" -body {\n    wm geometry . +100+100\n    event generate . <Motion> -warp 1 -x 600 -y 600\n    pack [ttk::button .t -text \"Hello\\nWorld!!\" -justify center] -expand true -fill both\n    update\n}\n\ntest ttk-1.2 \"Check style\" -body {\n    .t cget -style\n} -result {}\n\ntest ttk-1.3 \"Set bad style\" -body {\n    .t configure -style \"nosuchstyle\"\n} -returnCodes error -result {Layout nosuchstyle not found}\n\ntest ttk-1.4 \"Original style preserved\" -body {\n    .t cget -style\n} -result \"\"\n\ntest ttk-2.0 \"Check state\" -body {\n    checkstate .t\n} -result [list 1 0 0 0 0 0]\n\ntest ttk-2.1 \"Change state\" -body {\n    .t state active\n} -result !active\n\ntest ttk-2.2 \"Check state again\" -body {\n    checkstate .t\n} -result [list 0 0 1 0 1 0]\n\ntest ttk-2.3 \"Change state again\" -body {\n    .t state {!active disabled}\n} -result {active !disabled}\n\ntest ttk-2.4 \"Check state again\" -body {\n    checkstate .t\n} -result [list 0 1 0 0 0 1]\n\ntest ttk-2.5 \"Change state again\" -body {\n    .t state !disabled\n} -result {disabled}\n\ntest ttk-2.6 \"instate scripts, false\" -body {\n    set x 0\n    .t instate disabled { set x 1 }\n    set x\n} -result 0\n\ntest ttk-2.7 \"instate scripts, true\" -body {\n    set x 0\n    .t instate !disabled { set x 1 }\n    set x\n} -result 1\n\ntest ttk-2.8 {Bug [3223850]: Button remains stuck when disabled as depressed on XP} -setup {\n    destroy .b\n    set ttk28 {}\n    pack [ttk::button .b -command {set ::ttk28 failed}]\n    update\n} -body {\n    bind .b <Button-1> {after 0 {.b configure -state disabled}}\n    after 1 {event generate .b <Button-1>}\n    after 50 {event generate .b <ButtonRelease-1>}\n    set aid [after 100 {set ::ttk28 [.b instate {disabled !pressed}]}]\n    vwait ::ttk28\n    after cancel $aid\n    set ttk28\n} -cleanup {\n    destroy .b\n    unset -nocomplain ttk28 aid\n} -result 1\n\ntest ttk-2.9 {Bug [7231bf99]: Setting ttk state may change the variable passed by value} -body {\n    pack [ttk::button .b1 -text Hi!]\n    set state [list invalid disabled]\n    .b1 state $state\n    set state\n} -cleanup {\n    unset state\n    destroy .b1\n} -result [list invalid disabled]\n\nforeach wc $widgetClasses {\n    test ttk-coreoptions-$wc \"$wc has all core options\" -body {\n\tttk::$wc .w\n\tforeach option {-class -style -cursor -takefocus} {\n\t    .w cget $option\n\t}\n    } -cleanup {\n\tcatch {destroy .w}\n    }\n}\n\n# misc. error detection\ntest ttk-3.0 \"Bad option\" -body {\n    ttk::button .bad -badoption foo\n} -returnCodes error -result {unknown option \"-badoption\"} -match glob\n\ntest ttk-3.1 \"Make sure widget command not created\" -body {\n    .bad state disabled\n} -returnCodes error -result {invalid command name \".bad\"} -match glob\n\ntest ttk-3.2 \"Propagate errors from variable traces\" -body {\n    set A 0\n    trace add variable A write {error \"failure\" ;# }\n    ttk::checkbutton .cb -variable A\n    .cb invoke\n} -cleanup {\n    unset ::A ; destroy .cb\n} -returnCodes error -result {can't set \"A\": failure}\n\ntest ttk-3.3 \"Constructor failure with cursor\" -body {\n    ttk::button .b -cursor bottom_right_corner -style BadStyle\n} -returnCodes error -result \"Layout BadStyle not found\"\n\ntest ttk-3.4 {Bug [2009213]: Segfault after setting bad -sliderrelief and packing scale} -body {\n    ttk::style configure TScale -sliderrelief {}\n    pack [ttk::scale .s]\n    update\n} -cleanup {\n    ttk::style configure TScale -sliderrelief raised\n    destroy .s\n}\n\n# Test resource allocation\n# (@@@ \"-font\" is a compatibility option now, so tests 4.1-4.3\n# don't really test anything useful at the moment.)\n#\n\ntest ttk-4.0 \"Setup\" -body {\n    catch { destroy .t }\n    pack [ttk::label .t -text \"Button 1\"]\n    testConstraint fontOption [expr {![catch { set prevFont [.t cget -font] }]}]\n    return -code ok\n}\n\ntest ttk-4.1 \"Change font\" -constraints fontOption -body {\n    .t configure -font \"Helvetica 18 bold\"\n}\ntest ttk-4.2 \"Check font\" -constraints fontOption -body {\n    .t cget -font\n} -result \"Helvetica 18 bold\"\n\ntest ttk-4.3 \"Restore font\" -constraints fontOption -body {\n    .t configure -font $prevFont\n}\n\ntest ttk-4.4 \"Bad resource specifications\" -body {\n    ttk::style theme settings alt {\n\tttk::style configure TButton -font {Bad font}\n\t# @@@ it would be best to raise an error at this point,\n\t# @@@ but that's not really feasible in the current framework.\n    }\n    pack [ttk::button .tb1 -text \"Ouch\"]\n    ttk::style theme use alt\n    update;\n    # As long as we haven't crashed, everything's OK\n    ttk::style theme settings alt {\n\tttk::style configure TButton -font TkDefaultFont\n    }\n    ttk::style theme use default\n    destroy .tb1\n}\n\n#\n# COMMON TEST SETUP\n#\n# For tests ttk-8.*\n#\n\n#\n# -compound tests:\n#\nvariable iconData \\\n{R0lGODlhIAAgAKIAANnZ2YQAAP8AAISEhP///////////////yH5BAEAAAAALAAAAAAgACAA\nAAP/CLoMGLqKoMvtGIqiqxEYCLrcioGiyxwIusyBgaLLLRiBoMsQKLrcjYGgu4Giy+2CAkFX\nA0WX2wXFIOgGii7trkCEohsDCACBoktEKLpKhISiGwAIECiqSKooukiqKKoxgACBooukKiIo\nSKooujGDECi6iqQqsopEV2MQAkV3kXQZRXdjEAJFl5F0FUWXY3ACRZcFSRdFlyVwJlB0WZB0\nUXRZAmcCRZeRdBVFl2NwAkV3kXQZRXdjcAJFV5FURVaR6GoMDgSKLpKqiKAgqaLoxgwOBIoq\nkiqKLpIqimrM4ECg6BIRiq4SIaHoxgyCBoou7a5AhKIbMzgAAIGiy+2CTWJmBhAAAkWX2wXF\nzCDoBooud2PMDIKuRqDocgtGzMwg6O4Eii5z4Kgi6DIMhqLoagQGjiqCLvPgYOgqji6CLrfi\n6DIj6HI7jq4i6DIkADs=}\n\nvariable compoundStrings {text image center top bottom left right none}\n\ntest ttk-8.0 \"Setup for 8.X\" -body {\n    ttk::button .ctb\n    image create photo icon -data $::iconData;\n    pack .ctb\n}\n\ntest ttk-8.1 \"Test -compound options\" -body {\n    # Exhaustively test each combination.\n    # Main goal is to make sure no code paths crash.\n    foreach image {icon \"\"} {\n\tforeach text {\"Hi!\" \"\"} {\n\t    foreach compound $::compoundStrings {\n\t\t.ctb configure -image $image -text $text -compound $compound\n\t\tupdate\n\t    }\n\t}\n    }\n}\n\ntest ttk-8.2 \"Test -compound options with regular button\" -body {\n    button .rtb\n    pack .rtb\n\n    foreach image {\"\" icon} {\n\tforeach text {\"Hi!\" \"\"} {\n\t    foreach compound [lrange $::compoundStrings 2 end] {\n\t\t.rtb configure -image $image -text $text -compound $compound\n\t\tupdate\n\t    }\n\t}\n    }\n}\n\ntest ttk-8.3 \"Rerun test 8.1\" -body {\n    foreach image {icon \"\"} {\n\tforeach text {\"Hi!\" \"\"} {\n\t    foreach compound $::compoundStrings {\n\t\t.ctb configure -image $image -text $text -compound $compound\n\t\tupdate\n\t    }\n\t}\n    }\n}\n\ntest ttk-8.4 \"ImageChanged\" -body {\n    ttk::button .b -image icon\n    icon blank\n} -cleanup { destroy .b }\n\n\ntest ttk-9.1 \"Traces on nonexistant namespaces\" -body {\n    ttk::checkbutton .tcb -variable foo::bar\n} -returnCodes error -result {can't trace \"foo::bar\": parent namespace doesn't exist}\n\ntest ttk-9.2 \"Traces on nonexistant namespaces II\" -body {\n    ttk::checkbutton .tcb -variable X\n    .tcb configure -variable foo::bar\n} -returnCodes error -result {can't trace \"foo::bar\": parent namespace doesn't exist}\n\ntest ttk-9.3 \"Restore saved options on configure error\" -body {\n    .tcb cget -variable\n} -result X\n\ntest ttk-9.4 \"Textvariable tests\" -body {\n    set tcbLabel \"Testing...\"\n    .tcb configure -textvariable tcbLabel\n    .tcb cget -text\n} -result \"Testing...\"\n\n# Changing -text has no effect if there is a linked -textvariable.\n# Compatible with core widget.\ntest ttk-9.5 \"Change -text\" -body {\n    .tcb configure -text \"Changed -text\"\n    .tcb cget -text\n} -result \"Testing...\"\n\n# Unset -textvariable clears the text.\n# NOTE: this is different from core widgets, which automagically reinitalize\n# the -textvariable to the last value of -text.\n#\ntest ttk-9.6 \"Unset -textvariable\" -body {\n    unset tcbLabel\n    list [info exists tcbLabel] [.tcb cget -text]\n} -result [list 0 \"\"]\n\ntest ttk-9.7 \"Unset textvariable, comparison\" -body {\n#\n# NB: ttk::label behaves differently from the standard label here;\n# NB: this is on purpose: I believe the standard behaviour is the Wrong Thing\n#\n    unset -nocomplain V1  V2\n    label .l -text Foo ; ttk::label .tl -text Foo\n\n    .l configure -textvariable V1 ; .tl configure -textvariable V2\n    list [set V1] [info exists V2]\n} -cleanup { destroy .l .tl } -result [list Foo 0]\n\ntest ttk-9.8 \"-textvariable overrides -text\" -body {\n    ttk::label .tl -textvariable TV\n    set TV Foo\n    .tl configure -text Bar\n    .tl cget -text\n} -cleanup { destroy .tl } -result \"Foo\"\n\ntest ttk-9.9 \"default for -justify\" -body {\n    ttk::label .tl\n    .tl cget -justify\n} -cleanup { destroy .tl } -result \"left\"\ntest ttk-9.10 \"default for -anchor\" -body {\n    ttk::label .tl\n    .tl cget -anchor\n} -cleanup { destroy .tl } -result \"w\"\n\n#\n# Frame widget tests:\n#\n\ntest ttk-10.1 \"ttk::frame -class resource\" -body {\n    ttk::frame .f -class Foo\n} -result .f\n\ntest ttk-10.2 \"Check widget class\" -body {\n    winfo class .f\n} -result Foo\n\ntest ttk-10.3 \"Check class resource\" -body {\n    .f cget -class\n} -result Foo\n\ntest ttk-10.4 \"Try to modify class resource\" -body {\n    .f configure -class Bar\n} -returnCodes error -match glob -result \"*read-only option*\"\n\ntest ttk-10.5 \"Check class resource again\" -body {\n    .f cget -class\n} -result Foo\n\ntest ttk-11.1 \"-state test, setup\" -body {\n    ttk::button .b\n    .b instate disabled\n} -result 0\n\ntest ttk-11.2 \"-state test, disable\" -body {\n    .b configure -state disabled\n    .b instate disabled\n} -result 1\n\ntest ttk-11.3 \"-state test, reenable\" -body {\n    .b configure -state normal\n    .b instate disabled\n} -result 0\n\ntest ttk-11.4 \"-state test, unrecognized -state value\" -body {\n    .b configure -state bogus\n    .b state\n} -result [list]\n\ntest ttk-11.5 \"-state test, 'active'\" -body {\n    .b configure -state active\n    .b state\n} -result [list active] -cleanup  { .b state !active }\n\ntest ttk-11.6 \"-state test, 'readonly'\" -body {\n    .b configure -state readonly\n    .b state\n} -result [list readonly] -cleanup { .b state !readonly }\n\ntest ttk-11.7 \"-state test, cleanup\" -body {\n    destroy .b\n}\n\ntest ttk-12.1 \"-cursor option\" -body {\n    ttk::button .b\n    .b cget -cursor\n} -result {}\n\ntest ttk-12.2 \"-cursor option\" -body {\n    .b configure -cursor arrow\n    .b cget -cursor\n} -result arrow\n\ntest ttk-12.2.1 \"-cursor option, widget doesn't overwrite it\" -setup {\n    ttk::treeview .tr\n    pack .tr\n    update\n} -body {\n    .tr configure -cursor X_cursor\n    event generate .tr <Motion>\n    update\n    .tr cget -cursor\n} -cleanup {\n    destroy .tr\n} -result {X_cursor}\n\ntest ttk-12.3 \"-borderwidth frame option\" -body {\n    destroy .t\n    toplevel .t\n    raise .t\n    pack [set t [ttk::frame .t.f]] -expand true -fill x ;\n    pack [ttk::label $t.l -text \"ASDF QWERTY\"] -expand true -fill both\n    foreach theme {default alt} {\n\tttk::style theme use $theme\n\tforeach relief {flat raised sunken ridge groove solid} {\n\t    $t configure -relief $relief\n\t    for {set i 5} {$i >= 0} {incr i -1} {\n\t\t$t configure -borderwidth $i\n\t\tupdate\n\t    }\n\t}\n    }\n}\n\ntest ttk-12.4 \"-borderwidth frame option\" -body {\n    .t.f configure -relief raised\n    .t.f configure -borderwidth 1\n    ttk::style theme use alt\n    update\n}\n\ntest ttk-13.1 \"Custom styles -- bad -style option\" -body {\n    ttk::button .tb1 -style badstyle\n} -returnCodes error -result \"*badstyle not found*\" -match glob\n\ntest ttk-13.4 \"Custom styles -- bad -style option\" -body {\n    ttk::button .tb1\n    .tb1 configure -style badstyle\n} -cleanup {\n    destroy .tb1\n} -returnCodes error -result \"*badstyle not found*\" -match glob\n\ntest ttk-13.5 \"Custom layouts -- missing element definition\" -body {\n    ttk::style layout badstyle {\n\tNoSuchElement\n    }\n    ttk::button .tb1 -style badstyle\n} -cleanup {\n    destroy .tb1\n} -result .tb1\n# @@@ Should: signal an error, possibly a background error.\n\n#\n# See #793909\n#\n\ntest ttk-14.1 \"-variable in nonexistant namespace\" -body {\n    ttk::checkbutton .tw -variable ::nsn::foo\n} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \\\n  -match glob -cleanup { destroy .tw }\n\ntest ttk-14.2 \"-textvariable in nonexistant namespace\" -body {\n    ttk::label .tw -textvariable ::nsn::foo\n} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \\\n  -match glob -cleanup { destroy .tw }\n\ntest ttk-14.3 \"-textvariable in nonexistant namespace\" -body {\n    ttk::entry .tw -textvariable ::nsn::foo\n} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \\\n  -match glob -cleanup { destroy .tw }\n\ntest ttk-15.1 {Tcl bug [3062331]: segfault in variable traces with ttk::* widgets} -setup {\n    destroy .b\n} -body {\n    set Y {}\n    ttk::button .b -textvariable Y\n    trace add variable Y unset \"destroy .b; #\"\n    unset Y\n} -cleanup {\n    destroy .b\n} -result {}\n\ntest ttk-15.2 {Bug [3341056]: Usage of recreated ttk::checkbutton causes crash} -setup {\n    proc foo {} {\n\tdestroy .lf\n\tttk::labelframe .lf\n\tttk::checkbutton .lf.cb -text xxx\n    }\n} -body {\n    ttk::button .b -text xxx -command foo\n    .b invoke\n    .b invoke\n    .lf.cb invoke\n    destroy .b\n} -cleanup {\n    rename foo {}\n    destroy .lf\n} -result {}\n\n## Test ensemble processing:\n#\n# (See also: SF#2021443)\n#\n\ntest ttk-ensemble-0 \"style element create: insufficient args\" -body {\n     ttk::style\n} -returnCodes error -result \\\n    [wrong#varargs arg ttk::style option]\n\ntest ttk-ensemble-1 \"style element create: insufficient args\" -body {\n     ttk::style element\n} -returnCodes error -result \\\n    [wrong#varargs arg ttk::style element option]\n\ntest ttk-ensemble-2 \"style element create: insufficient args\" -body {\n     ttk::style element create\n} -returnCodes error -result \\\n    [wrong#varargs {-option value} ttk::style element create name type]\n\ntest ttk-ensemble-3 \"style element create: insufficient args\" -body {\n     ttk::style element create plain.background\n} -returnCodes error -result \\\n    [wrong#varargs {-option value} ttk::style element create name type]\n\ntest ttk-ensemble-4 \"style element create: insufficient args\" -body {\n     ttk::style element create plain.background from\n} -returnCodes error -result [wrong#args theme ?element?]\n\ntest ttk-ensemble-5 \"style element create: valid\" -body {\n     ttk::style element create plain.background from default\n} -returnCodes 0 -result \"\"\n\ntest ttk-16.1 {ttk::style theme styles - no such theme} -body {\n    ttk::style theme styles noSuchTheme\n} -returnCodes 1 -result {theme \"noSuchTheme\" does not exist}\ntest ttk-16.2 {ttk::style theme styles - theme exists} -body {\n    # simply check this produces a list with some style names,\n    # without checking exact content (not needed, and may vary\n    # depending on platform, versions, improvements...)\n    expr {[llength [ttk::style theme styles alt]] > 0}\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy {*}[winfo children .]\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/validate.test",
    "content": "#\n# Entry widget validation tests\n# Derived from core test suite entry-19.1 through entry-19.20\n#\n\n# NOTES\n#\n# * Many tests in this test file build upon a previous one. This occurs\n#   systematically for groups of contiguous tests sharing the same major\n#   test number. All test files for ttk widgets exhibit this practice.\n#\n#   As a consequence, attempts to run tests selectively/individually using the\n#   tcltest options \"-match\", \"-skip\" or \"-limitconstraints 1\" lead to\n#   unexpected failures. Therefore, invocations using these options should be\n#   considered as \"de facto invalid\" for the ttk test suite.\n#\n#   As an exception, using \"-match\" or \"-skip\" to select or deselect entire\n#   groups of contiguous tests does not seem to raise problems.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import entry\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint ttkEntry 1\ntestConstraint coreEntry [expr {![testConstraint ttkEntry]}]\ntestConstraint NA 0\n\n#\n# COMMON TEST SETUP\n#\n\nforeach i {1 2 3 4} {\n    set validateCmd$i [list validateCommand$i %W %d %i %P %s %S %v %V]\n}\n\n#\n# TESTS\n#\n\ntest validate-0.0 \"Setup\" -constraints ttkEntry -body {\n    rename entry {}\n    interp alias {} entry {} ttk::entry\n    return;\n}\n\ntest validate-0.1 \"More setup\" -body {\n    destroy .e\n    catch {unset textVar}\n    unset -nocomplain validationData; # not necessary\n    entry .e -validate all \\\n\t    -validatecommand $validateCmd1 \\\n\t    -invalidcommand bell \\\n\t    -textvariable textVar \\\n\t    ;\n    pack .e\n}\n\ntest validate-1.1 {entry widget validation - insert} -body {\n    .e insert 0 a\n    set validationData\n} -result {.e 1 0 a {} a all key}\n\ntest validate-1.2 {entry widget validation - insert} -body {\n    .e insert 1 b\n    set validationData\n} -result {.e 1 1 ab a b all key}\n\ntest validate-1.3 {entry widget validation - insert} -body {\n    .e insert end c\n    set validationData\n} -result {.e 1 2 abc ab c all key}\n\ntest validate-1.4 {entry widget validation - insert} -body {\n    .e insert 1 123\n    list $validationData $textVar\n} -result {{.e 1 1 a123bc abc 123 all key} a123bc}\n\ntest validate-1.5 {entry widget validation - delete} -body {\n    .e delete 2\n    set validationData\n} -result {.e 0 2 a13bc a123bc 2 all key}\n\ntest validate-1.6 {entry widget validation - delete} -body {\n    .e configure -validate key\n    .e delete 1 3\n    set validationData\n} -result {.e 0 1 abc a13bc 13 key key}\n\ntest validate-1.7 {entry widget validation - vmode focus} -body {\n    set validationData {}\n    .e configure -validate focus\n    .e insert end d\n    set validationData\n} -result {}\n\ntest validate-1.8 {entry widget validation - vmode focus} -body {\n    set validationData {}\n    set timer [after 300 validationData lappend timeout]\n    focus -force .e\n    vwait validationData\n    after cancel $timer\n    set validationData\n} -result {.e -1 -1 abcd abcd {} focus focusin}\n\ntest validate-1.9 {entry widget validation - vmode focus} -body {\n    set validationData {}\n    set timer [after 300 validationData lappend timeout]\n    focus -force .\n    vwait validationData\n    after cancel $timer\n    set validationData\n} -result {.e -1 -1 abcd abcd {} focus focusout}\n\n#\n# COMMON TEST SETUP\n#\n\n.e configure -validate all\n\ntest validate-1.10 {entry widget validation - vmode all} -body {\n    set validationData {}\n    set timer [after 300 validationData lappend timeout]\n    focus -force .e\n    vwait validationData\n    after cancel $timer\n    set validationData\n} -result {.e -1 -1 abcd abcd {} all focusin}\n\ntest validate-1.11 {entry widget validation} -body {\n    set validationData {}\n    set timer [after 300 validationData lappend timeout]\n    focus -force .\n    vwait validationData\n    after cancel $timer\n    set validationData\n} -result {.e -1 -1 abcd abcd {} all focusout}\n\n#\n# COMMON TEST SETUP\n#\n\n.e configure -validate focusin\n\ntest validate-1.12 {entry widget validation} -body {\n    set validationData {}\n    set timer [after 300 validationData lappend timeout]\n    focus -force .e\n    vwait validationData\n    after cancel $timer\n    set validationData\n} -result {.e -1 -1 abcd abcd {} focusin focusin}\n\ntest validate-1.13 {entry widget validation} -body {\n    set validationData {}\n    focus -force .\n    update\n    set validationData\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n\n.e configure -validate focuso\n\ntest validate-1.14 {entry widget validation} -body {\n    set validationData {}\n    focus -force .e\n    update\n    set validationData\n} -result {}\n\ntest validate-1.15 {entry widget validation} -body {\n    focus -force .\n    # update necessary to process FocusOut event\n    update\n    set validationData\n} -result {.e -1 -1 abcd abcd {} focusout focusout}\n\n# DIFFERENCE: core entry temporarily sets \"-validate all\", ttk::entry doesn't.\ntest validate-1.16 {entry widget validation} -body {\n    .e configure -validate all\n    list [.e validate] $validationData\n} -result {1 {.e -1 -1 abcd abcd {} all forced}}\n\n# DIFFERENCE: ttk::entry does not perform validation when setting the -variable\ntest validate-1.17 {entry widget validation} -constraints coreEntry -body {\n    .e configure -validate all\n    set textVar newdata\n    list [.e cget -validate] $validationData\n} -result {all {.e -1 -1 newdata abcd {} all forced}}\n\ntest validate-1.18 {entry widget validation} -constraints coreEntry -body {\n    .e configure -validate all -validatecommand $validateCmd3\n    set textVar nextdata\n    list [.e cget -validate] $validationData\n} -result {none {.e -1 -1 nextdata newdata {} all forced}}\n# DIFFERENCE: ttk::entry doesn't validate when setting linked -variable\n# DIFFERENCE: ttk::entry doesn't disable validation\n\n## This sets validate to none because it shows that we prevent a possible\n## loop condition in the validation, when the entry textvar is also set\ntest validate-1.19 {entry widget validation} -constraints coreEntry -body {\n    .e configure -validate all -validatecommand $validateCmd2\n    .e validate\n    list [.e cget -validate] [.e get] $validationData\n} -result {none mydata {.e -1 -1 nextdata nextdata {} all forced}}\n\n## This leaves validate alone because we trigger validation through the\n## textvar (a write trace), and the write during validation triggers\n## nothing (by definition of avoiding loops on var traces).  This is\n## one of those \"dangerous\" conditions where the user will have a\n## different value in the entry widget shown as is in the textvar.\n\n# DIFFERENCE: ttk entry doesn't get out of sync w/textvar\ntest validate-1.20 {entry widget validation} -constraints coreEntry -body {\n    .e configure -validate all -validatecommand $validateCmd2\n    set textVar testdata\n    list [.e cget -validate] [.e get] $textVar $validationData\n} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}\n\ntest validate-2.1 \"Validation script changes value\" -body {\n    .e configure -validate none -validatecommand $validateCmd4\n    set textVar testdata\n    .e configure -validate all\n    .e validate\n    list [.e get] $textVar $validationData\n} -result {dovaldata dovaldata {.e -1 -1 testdata testdata {} all forced}}\n# DIFFERENCE: core entry disables validation, ttk entry does not.\n\n#\n# COMMON TEST CLEANUP\n#\n\ndestroy .e\ncatch {unset textVar}\n\n# See bug #1236979\n\ntest validate-2.2 \"configure in -validatecommand\" -body {\n    proc validate-2.2 {win str} {\n\t$win configure -foreground black\n\treturn 1\n    }\n    ttk::entry .e -textvariable var -validatecommand {validate-2.2 %W %P}\n    .e validate\n} -result 1 -cleanup { destroy .e }\n\n\n### invalid state behavior\n#\n\ntest validate-3.0 \"Setup\" -body {\n    set ::E \"123\"\n    ttk::entry .e \\\n\t-validatecommand {string is integer -strict %P} \\\n\t-validate all \\\n\t-textvariable ::E \\\n\t;\n    return [list [.e get] [.e state]]\n} -result [list 123 {}]\n\ntest validate-3.1 \"insert - valid\" -body {\n    .e insert end \"4\"\n    return [list [.e get] [.e state]]\n} -result [list 1234 {}]\n\ntest validate-3.2 \"insert - invalid\" -body {\n    .e insert end \"X\"\n    return [list [.e get] [.e state]]\n} -result [list 1234 {}]\n\ntest validate-3.3 \"force invalid value\" -body {\n    append ::E \"XY\"\n    return [list [.e get] [.e state]]\n} -result [list 1234XY {}]\n\ntest validate-3.4 \"revalidate\" -body {\n    return [list [.e validate] [.e get] [.e state]]\n} -result [list 0 1234XY {invalid}]\n\n# the next two tests (used to) exercise validation lockout protection --\n# if the widget is currently invalid, all edits are allowed.\n# This behavior is currently disabled.\n#\ntest validate-3.5 \"all edits allowed while invalid\" -constraints NA -body {\n    .e delete 4\n    return [list [.e get] [.e state]]\n} -result [list 1234Y {invalid}]\n\ntest validate-3.6 \"...until the value becomes valid\" -constraints NA -body {\n    .e delete 4\n    return [list [.e get] [.e state]]\n} -result [list 1234 {}]\n\ntest validate-3.last \"Cleanup\" -body { destroy .e }\n\n#\n# TESTFILE CLEANUP\n#\n\nforeach i {1 2 3 4} {\n    unset validateCmd$i\n}\nunset i\ntestutils forget entry\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/ttk/vsapi.test",
    "content": "#\n# Tests exercising Microsoft Visual Styles elements, defined through\n# the command \"ttk::style element create XXX vsapi\"\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [file dirname [tcltest::configure -testdir]] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint vista \\\n    [expr {\"vista\" in [ttk::style theme names]}]\n\n#\n# TESTS\n#\n\ntest vsapi-1.1 \"WINDOW WP_SMALLCLOSEBUTTON\" -constraints vista -body {\n    ttk::style element create smallclose vsapi \\\n\tWINDOW 19 {disabled 4 pressed 3 active 2 {} 1}\n    ttk::style layout CloseButton {CloseButton.smallclose -sticky news}\n    ttk::button .b -style CloseButton\n    pack .b -expand true -fill both\n    list [winfo reqwidth .b] [winfo reqheight .b]\n} -cleanup { destroy .b } -result [list 13 13]\n\ntest vsapi-1.2 \"EXPLORERBAR EBP_HEADERPIN\" -constraints vista -body {\n    ttk::style element create pin vsapi \\\n\tEXPLORERBAR 3 {\n\t    {pressed !selected} 3\n\t    {active !selected} 2\n\t    {pressed selected} 6\n\t    {active selected} 5\n\t    {selected} 4\n\t    {} 1\n\t}\n    ttk::style layout Explorer.Pin {Explorer.Pin.pin -sticky news}\n    ttk::checkbutton .pin -style Explorer.Pin\n    pack .pin -expand true -fill both\n    list [winfo reqwidth .pin] [winfo reqheight .pin]\n} -cleanup { destroy .pin } -result [list 16 16]\n\ntest vsapi-1.3 \"EXPLORERBAR EBP_HEADERCLOSE\" -constraints vista -body {\n    ttk::style element create headerclose vsapi \\\n\tEXPLORERBAR 2 {pressed 3 active 2 {} 1}\n    ttk::style layout Explorer.CloseButton {\n\tExplorer.CloseButton.headerclose -sticky news\n    }\n    ttk::button .b -style Explorer.CloseButton\n    pack .b -expand true -fill both\n    list [winfo reqwidth .b] [winfo reqheight .b]\n} -cleanup { destroy .b } -result [list 16 16]\n\n#\n# TESTFILE CLEANUP\n#\n\ntcltest::cleanupTests\n"
  },
  {
    "path": "tests/unixButton.test",
    "content": "# This file is a Tcl script to test the Unix specific behavior of\n# labels, buttons, checkbuttons, and radiobuttons in Tk (i.e., all the\n# widgets defined in tkUnixButton.c).\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. This includes macOS.\n#   Tests regarding buttons that are specific to the MS Windows platform\n#   go into the test file winButton.test. Tests that are platform-indifferent go\n#   into the test file button.test. Or they may exist as each other's counterparts\n#   in both unixButton.test and winButton.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-unix platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import button image\n\nimageInit\n\n#\n# COMMON TEST SETUP\n#\n\n# Create entries in the option database to be sure that geometry options\n# like border width have predictable values.\n\noption add *Label.borderWidth 2\noption add *Label.highlightThickness 0\noption add *Label.font {Helvetica -12 bold}\noption add *Button.borderWidth 2\noption add *Button.highlightThickness 2\noption add *Button.font {Helvetica -12 bold}\noption add *Checkbutton.borderWidth 2\noption add *Checkbutton.highlightThickness 2\noption add *Checkbutton.font {Helvetica -12 bold}\noption add *Radiobutton.borderWidth 2\noption add *Radiobutton.highlightThickness 2\noption add *Radiobutton.font {Helvetica -12 bold}\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    set smallIndicator 20\n    set bigIndicator 20\n    set defaultBorder 10\n} else {\n    set smallIndicator 27\n    set bigIndicator 40\n    set defaultBorder 20\n}\n\n#\n# TESTS\n#\n\ntest unixbutton-1.1 {TkpComputeButtonGeometry procedure} -constraints {\n    unix testImageType\n} -setup {\n    deleteWindows\n    imageCleanup\n} -body {\n    image create test image1\n    image1 changed 0 0 0 0 60 40\n    label .b1 -image image1 -bd 4 -padx 0 -pady 2\n    button .b2 -image image1 -bd 4 -padx 0 -pady 2\n    checkbutton .b3 -image image1 -bd 4 -padx 1 -pady 1\n    radiobutton .b4 -image image1 -bd 4 -padx 2 -pady 0\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n    image delete image1\n} -result [list 68 48 \\\n\t\t74 54 \\\n\t\t[expr {72 + $bigIndicator}] 52 \\\n\t\t[expr {72 + $bigIndicator}] 52]\ntest unixbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -bitmap question -bd 3 -padx 0 -pady 2\n    button .b2 -bitmap question -bd 3 -padx 0 -pady 2\n    checkbutton .b3 -bitmap question -bd 3 -padx 1 -pady 1\n    radiobutton .b4 -bitmap question -bd 3 -padx 2 -pady 0\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result [list 23 33 \\\n\t\t29 39 \\\n\t\t[expr {27 + $smallIndicator}] 37 \\\n\t\t[expr {27 + $smallIndicator}] 37]\ntest unixbutton-1.3 {TkpComputeButtonGeometry procedure} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -bitmap question -bd 3 -highlightthickness 4\n    button .b2 -bitmap question -bd 3 -highlightthickness 0\n    checkbutton .b3 -bitmap question -bd 3 -highlightthickness 1 \\\n\t-indicatoron 0\n    radiobutton .b4 -bitmap question -bd 3 -highlightthickness 1 \\\n    -indicatoron false\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {31 41 25 35 25 35 25 35}\ntest unixbutton-1.4 {TkpComputeButtonGeometry procedure} -constraints {\n    unix nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -padx 0 -pady 2 -font {Helvetica -18 bold}\n    button .b2 -text Xagqpim -padx 0 -pady 2 -font {Helvetica -18 bold}\n    checkbutton .b3 -text Xagqpim -padx 1 -pady 1 -font {Helvetica -18 bold}\n    radiobutton .b4 -text Xagqpim -padx 2 -pady 0 -font {Helvetica -18 bold}\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {82 29 88 35 114 31 121 29}\ntest unixbutton-1.5 {TkpComputeButtonGeometry procedure} -constraints {\n    unix nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    label .l1 -text \"This is a long string that will wrap around on several lines.\\n\\nIt also has a blank line (above).\" -wraplength 1.5i -padx 0 -pady 0\n    pack .l1\n    update\n    list [winfo reqwidth .l1] [winfo reqheight .l1]\n} -cleanup {\n    deleteWindows\n} -result {136 88}\ntest unixbutton-1.6 {TkpComputeButtonGeometry procedure} -constraints {\n    unix nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    label .l1 -text \"This is a long string without wrapping.\\n\\nIt also has a blank line (above).\" -padx 0 -pady 0\n    pack .l1\n    update\n    list [winfo reqwidth .l1] [winfo reqheight .l1]\n} -cleanup {\n    deleteWindows\n} -result {231 46}\ntest unixbutton-1.7 {TkpComputeButtonGeometry procedure} -constraints {\n    unix nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -bd 2 -padx 0 -pady 2 -width 10\n    button .b2 -text Xagqpim -bd 2 -padx 0 -pady 2 -height 5\n    checkbutton .b3 -text Xagqpim -bd 2 -padx 1 -pady 1 -width 20 -height 2\n    radiobutton .b4 -text Xagqpim -bd 2 -padx 2 -pady 0 -width 4\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {74 22 60 84 168 38 61 22}\ntest unixbutton-1.8 {TkpComputeButtonGeometry procedure} -constraints {\n    unix nonPortable fonts\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -bd 2 -padx 0 -pady 2 \\\n    -highlightthickness 4\n    button .b2 -text Xagqpim -bd 2 -padx 0 -pady 2 \\\n    -highlightthickness 0\n    checkbutton .b3 -text Xagqpim -bd 2 -padx 1 -pady 1  \\\n    -highlightthickness 1 -indicatoron no\n    radiobutton .b4 -text Xagqpim -bd 2 -padx 2 -pady 0 -indicatoron 0\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {62 30 56 24 58 22 62 22}\ntest unixbutton-1.9 {TkpComputeButtonGeometry procedure} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    button .b2 -bitmap question -default active\n    list [winfo reqwidth .b2] [winfo reqheight .b2]\n} -cleanup {\n    deleteWindows\n} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]\ntest unixbutton-1.10 {TkpComputeButtonGeometry procedure} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    button .b2 -bitmap question -default normal\n    list [winfo reqwidth .b2] [winfo reqheight .b2]\n} -cleanup {\n    deleteWindows\n} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]\ntest unixbutton-1.11 {TkpComputeButtonGeometry procedure} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    button .b2 -bitmap question -default disabled\n    list [winfo reqwidth .b2] [winfo reqheight .b2]\n} -cleanup {\n    deleteWindows\n} -result {27 37}\n\n\ntest unixbutton-2.1 {disabled coloring check, bug 669595} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {unset value}\n} -body {\n    # this was just a visual bug, but at least this shows the visual\n    set on 1\n    set off 0\n    label .l -text \"The following widgets should\\\n\t\\nshow significant visible diffs\\\n\t\\nfor selected vs unselected.\"\n    checkbutton .cb0 -anchor w -state disabled \\\n\t-text Unselected -variable off\n    checkbutton .cb1 -anchor w -state disabled \\\n\t-text Selected -variable on\n    checkbutton .cb2 -anchor w -state disabled \\\n\t-text Unselected -variable off -disabledforeground \"\"\n    checkbutton .cb3 -anchor w -state disabled \\\n\t-text Selected -variable on -disabledforeground \"\"\n    radiobutton .rb0 -anchor w -state disabled \\\n\t-text Unselected -variable off\n    radiobutton .rb1 -anchor w -state disabled \\\n\t-text Selected -variable on -value 1\n    radiobutton .rb2 -anchor w -state disabled \\\n\t-text Unselected -variable off -disabledforeground \"\"\n    radiobutton .rb3 -anchor w -state disabled \\\n\t-text Selected -variable on -value 1 -disabledforeground \"\"\n    pack .l .cb0 .cb1 .cb2 .cb3 .rb0 .rb1 .rb2 .rb3 -side top -fill x\n    after 400\n    set on\n} -cleanup {\n    deleteWindows\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ntestutils forget button image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/unixEmbed.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkUnixEmbed.c.\n#\n# Copyright © 1996-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. This includes macOS.\n#   Tests that are platform-indifferent go into the test file embed.test.\n# * This test file is skipped entirely on non-unix platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import colors child\n\n#\n# COMMON TEST SETUP\n#\n\nchildTkProcess create\nchildTkProcess eval {wm withdraw .}\n\n#\n# TESTS\n#\n\ntest unixEmbed-1.1 {Tk_UseWindow procedure, bad window identifier} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -use xyz\n} -returnCodes error -result {expected integer but got \"xyz\"}\ntest unixEmbed-1.2 {Tk_UseWindow procedure, bad window identifier} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -use 47\n} -returnCodes error -result {couldn't create child of window \"47\"}\ntest unixEmbed-1.3 {Tk_UseWindow procedure, inheriting colormap} -constraints {\n    unix nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -colormap new\n    wm geometry .t +0+0\n    eatColors .t.t\n    frame .t.f -container 1\n    toplevel .x -use [winfo id .t.f]\n    colorsFree .x\n} -cleanup {\n    deleteWindows\n} -result 0\ntest unixEmbed-1.4 {Tk_UseWindow procedure, inheriting colormap} -constraints {\n    unix nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t -container 1 -colormap new\n    wm geometry .t +0+0\n    eatColors .t2\n    toplevel .x -use [winfo id .t]\n    colorsFree .x\n} -cleanup {\n    deleteWindows\n} -result 1\n\ntest unixEmbed-1.5 {Tk_UseWindow procedure, creating Container records} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    pack .f1 .f2\n    childTkProcess eval \"set w [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t -use $w\n\tlist [testembed] [expr {[lindex [lindex [testembed all] 0] 0] - $w}]\n    }\n} -cleanup {\n    deleteWindows\n} -result {{{XXX {} {} .t}} 0}\ntest unixEmbed-1.5a {Tk_UseWindow procedure, creating Container records} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    pack .f1 .f2\n    child alias w winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t -use [w]\n\tlist [testembed] [expr {[lindex [lindex [testembed all] 0] 0] - [w]}]\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{{XXX {} {} .t}} 0}\ntest unixEmbed-1.6 {Tk_UseWindow procedure, creating Container records} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    pack .f1 .f2\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval \"set w2 [winfo id .f2]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\ttoplevel .t2 -use $w2\n\ttestembed\n    }\n} -cleanup {\n    deleteWindows\n} -result {{XXX {} {} .t2} {XXX {} {} .t1}}\ntest unixEmbed-1.6a {Tk_UseWindow procedure, creating Container records} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    pack .f1 .f2\n    child alias w1 winfo id .f1\n    child alias w2 winfo id .f2\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\ttoplevel .t2 -use [w2]\n\ttestembed\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{XXX {} {} .t2} {XXX {} {} .t1}}\ntest unixEmbed-1.7 {Tk_UseWindow procedure, container and embedded in same app} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    pack .f1 .f2\n    toplevel .t1 -use [winfo id .f1]\n    toplevel .t2 -use [winfo id .f2]\n    testembed\n} -cleanup {\n    deleteWindows\n} -result {{XXX .f2 {} .t2} {XXX .f1 {} .t1}}\n\n# Can't think of any way to test the procedures Tk_MakeWindow,\n# Tk_MakeContainer, or EmbedErrorProc.\n\n\ntest unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\ttestembed\n    }\n    destroy .f1\n    update\n    childTkProcess eval {\n\ttestembed\n    }\n} -cleanup {\n    deleteWindows\n} -result {}\ntest unixEmbed-2.1a {EmbeddedEventProc procedure} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\ttestembed\n    }\n    destroy .f1\n    update\n    child eval {\n\ttestembed\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {}\ntest unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\ttestembed\n\tdestroy .t1\n\ttestembed\n    }\n} -cleanup {\n    deleteWindows\n} -result {}\ntest unixEmbed-2.2a {EmbeddedEventProc procedure} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\ttestembed\n\tdestroy .t1\n\ttestembed\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {}\ntest unixEmbed-2.3 {EmbeddedEventProc procedure} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    toplevel .t1 -use [winfo id .f1]\n    update\n    destroy .f1\n    testembed\n} -result {}\ntest unixEmbed-2.4 {EmbeddedEventProc procedure} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n} -body {\n    pack [frame .f1 -container 1 -width 200 -height 50]\n    toplevel .t1 -use [winfo id .f1]\n    set x [testembed]\n    update\n    destroy .t1\n    update\n    list $x [winfo exists .t1] [winfo exists .f1] [testembed]\n} -cleanup {\n    deleteWindows\n} -result \"{{XXX .f1 {} .t1}} 0 0 {}\"\n\n\ntest unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints {\n    unix testembed nonPortable\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    set x [testembed]\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\twm withdraw .t1\n    }\n    list $x [testembed]\n} -cleanup {\n    deleteWindows\n} -result {{{XXX .f1 {} {}}} {{XXX .f1 XXX {}}}}\ntest unixEmbed-3.1a {ContainerEventProc procedure, detect creation} -constraints {\n    unix testembed\n} -setup {\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    set x [testembed]\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\twm withdraw .t1\n    }\n    list $x [testembed]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{{XXX .f1 {} {}}} {{XXX .f1 {} {}}}}\ntest unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    update\n} -body {\n    toplevel .t1 -container 1\n    wm geometry .t1 +0+0\n    toplevel .t2 -use [winfo id .t1] -bg red\n    update\n    wm geometry .t2\n} -cleanup {\n    deleteWindows\n} -result {200x200+0+0}\ntest unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1 -bd 2 -relief raised\n\tupdate\n\twm geometry .t1 +30+40\n    }\n    update\n    childTkProcess eval {\n\twm geometry .t1\n    }\n} -cleanup {\n    deleteWindows\n} -result {200x200+0+0}\ntest unixEmbed-3.3a {ContainerEventProc procedure, disallow position changes} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1] -bd 2 -relief raised\n\tupdate\n\twm geometry .t1 +30+40\n\tupdate\n\twm geometry .t1\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {200x200+0+0}\ntest unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tupdate\n\twm geometry .t1 300x100+30+40\n    }\n    update\n    childTkProcess eval {\n\twm geometry .t1\n    }\n} -cleanup {\n    deleteWindows\n} -result {300x100+0+0}\ntest unixEmbed-3.4a {ContainerEventProc procedure, disallow position changes} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\twm geometry .t1 300x100+30+40\n\tupdate\n\twm geometry .t1\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {300x100+0+0}\ntest unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    childTkProcess eval {\n\t.t1 configure -width 300 -height 80\n    }\n    update\n    list [winfo width .f1] [winfo height .f1] [childTkProcess eval {wm geometry .t1}]\n} -cleanup {\n    deleteWindows\n} -result {300 80 300x80+0+0}\ntest unixEmbed-3.5a {ContainerEventProc procedure, geometry requests} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\t.t1 configure -width 300 -height 80\n\tupdate\n    }\n    list [winfo width .f1] [winfo height .f1] [child eval {wm geometry .t1}]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {300 80 300x80+0+0}\ntest unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tset x unmapped\n\tbind .t1 <Map> {set x mapped}\n    }\n    update\n    childTkProcess eval {\n\tafter 100\n\tupdate\n\tset x\n    }\n} -cleanup {\n    deleteWindows\n} -result {mapped}\ntest unixEmbed-3.6a {ContainerEventProc procedure, map requests} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tset x unmapped\n\tbind .t1 <Map> {set x mapped}\n\tupdate\n\tafter 100\n\tupdate\n\tset x\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {mapped}\ntest unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    bind .f1 <Destroy> {set x dead}\n    set x alive\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    childTkProcess eval {\n\tdestroy .t1\n    }\n    update\n    list $x [winfo exists .f1]\n} -cleanup {\n    deleteWindows\n} -result {dead 0}\ntest unixEmbed-3.7a {ContainerEventProc procedure, destroy events} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    bind .f1 <Destroy> {set x dead}\n    set x alive\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\tdestroy .t1\n    }\n    update\n    list $x [winfo exists .f1]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {dead 0}\n\ntest unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    childTkProcess eval {\n\t.t1 configure -width 180 -height 100\n    }\n    update\n    childTkProcess eval {\n\twinfo geometry .t1\n    }\n} -cleanup {\n    deleteWindows\n} -result {180x100+0+0}\ntest unixEmbed-4.1a {EmbedStructureProc procedure, configure events} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\t.t1 configure -width 180 -height 100\n\tupdate\n\twinfo geometry .t1\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {180x100+0+0}\ntest unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    set x [testembed]\n    destroy .f1\n    update\n    list $x [testembed]\n} -cleanup {\n    deleteWindows\n} -result {{{XXX .f1 XXX {}}} {}}\ntest unixEmbed-4.2a {EmbedStructureProc procedure, destroy events} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n    }\n    set x [testembed]\n    destroy .f1\n    list $x [testembed]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result \"{{XXX .f1 {} {}}} {}\"\n\n\ntest unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tbind .t1 <FocusIn> {lappend x \"focus in %W\"}\n\tbind .t1 <FocusOut> {lappend x \"focus out %W\"}\n\tset x {}\n    }\n    focus -force .f1\n    update\n    childTkProcess eval {set x}\n} -cleanup {\n    deleteWindows\n} -result {{focus in .t1}}\ntest unixEmbed-5.1a {EmbedFocusProc procedure, FocusIn events} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tbind .t1 <FocusIn> {lappend x \"focus in %W\"}\n\tbind .t1 <FocusOut> {lappend x \"focus out %W\"}\n\tupdate\n\tset x {}\n    }\n    focus -force .f1\n    update\n    child eval {set x}\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{focus in .t1}}\ntest unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    childTkProcess eval {\n\tafter 200 {destroy .t1}\n    }\n    after 400\n    focus -force .f1\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest unixEmbed-5.2a {EmbedFocusProc procedure, focusing on dead window} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\tafter 200 {destroy .t1}\n    }\n    after 400\n    focus -force .f1\n    update\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {}\ntest unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tbind .t1 <FocusIn> {lappend x \"focus in %W\"}\n\tbind .t1 <FocusOut> {lappend x \"focus out %W\"}\n\tset x {}\n    }\n    focus -force .f1\n    update\n    set x [childTkProcess eval {update; set x}]\n    focus .\n    update\n    list $x [childTkProcess eval {update; set x}]\n} -cleanup {\n    deleteWindows\n} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}\ntest unixEmbed-5.3a {EmbedFocusProc procedure, FocusOut events} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tset x {}\n\tbind .t1 <FocusIn> {lappend x \"focus in %W\"}\n\tbind .t1 <FocusOut> {lappend x \"focus out %W\"}\n\tupdate\n    }\n    focus -force .f1\n    update\n    set x [child eval {update; set x }]\n    focus .\n    update\n    list $x [child eval {update; set x}]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}\n\n\ntest unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tupdate\n\tbind .t1 <Configure> {lappend x {configure .t1 %w %h}}\n\tset x {}\n\t.t1 configure -width 300 -height 120\n\tupdate\n\tlist $x [winfo geom .t1]\n    }\n} -cleanup {\n    deleteWindows\n} -result {{{configure .t1 300 120}} 300x120+0+0}\ntest unixEmbed-6.1a {EmbedGeometryRequest procedure, window changes size} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\tbind .t1 <Configure> {set x {configure .t1 %w %h}}\n\tset x {}\n\t.t1 configure -width 300 -height 120\n\tupdate\n\tlist $x [winfo geom .t1]\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{configure .t1 300 120} 300x120+0+0}\ntest unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    place .f1 -width 200 -height 200\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n\tupdate\n\tbind .t1 <Configure> {lappend x {configure .t1 %w %h}}\n\tset x {}\n\t.t1 configure -width 300 -height 120\n\tupdate\n\tlist $x [winfo geom .t1]\n    }\n} -cleanup {\n    deleteWindows\n} -result {{{configure .t1 200 200}} 200x200+0+0}\ntest unixEmbed-6.2a {EmbedGeometryRequest procedure, window changes size} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    place .f1 -width 200 -height 200\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n\tupdate\n\tbind .t1 <Configure> {set x {configure .t1 %w %h}}\n\tset x {}\n\t.t1 configure -width 300 -height 120\n\tupdate\n\tlist $x [winfo geom .t1]\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{configure .t1 200 200} 200x200+0+0}\n\n# Can't think up any tests for Tk_GetOtherWindow procedure.\n\ntest unixEmbed-7.1 {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    deleteWindows\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    focus -force .\n    bind . <Key> {lappend x {key %A %E}}\n    set x {}\n    set y [childTkProcess eval {\n\tupdate\n\tbind .t1 <Key> {lappend y {key %A}}\n\tset y {}\n\tevent generate .t1 <Key> -keysym a\n\tset y\n    }]\n    update\n    list $x $y\n} -cleanup {\n    deleteWindows\n    bind . <Key> {}\n} -result {{{key a 1}} {}}\n# TkpRedirectKeyEvent is not implemented in win or aqua.  If someone\n# implements it they should change the constraints for this test.\ntest unixEmbed-7.1a {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {\n    unix notAqua failsOnXQuartz\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    deleteWindows\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n    }\n    focus -force .\n    bind . <Key> {lappend x {key %A %E}}\n    set x {}\n    set y [child eval {\n\tupdate\n\tbind .t1 <Key> {lappend y {key %A}}\n\tset y {}\n\tevent generate .t1 <Key> -keysym a\n\tset y\n    }]\n    update\n    list $x $y\n} -cleanup {\n    interp delete child\n    deleteWindows\n    bind . <Key> {}\n} -result {{{key a 1}} {}}\ntest unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {\n    unix notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1\n    }\n    update\n    focus -force .f1\n    update\n    bind . <Key> {lappend x {key %A}}\n    set x {}\n    set y [childTkProcess eval {\n\tupdate\n\tbind .t1 <Key> {lappend y {key %A}}\n\tset y {}\n\tevent generate .t1 <Key> -keysym b\n\tset y\n    }]\n    update\n    list $x $y\n} -cleanup {\n    deleteWindows\n    bind . <Key> {}\n} -result {{} {{key b}}}\ntest unixEmbed-7.2a {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {\n    unix\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1]\n    }\n    update\n    focus -force .f1\n    update\n    bind . <Key> {lappend x {key %A}}\n    set x {}\n    set y [child eval {\n\tupdate\n\tbind .t1 <Key> {lappend y {key %A}}\n\tset y {}\n\tevent generate .t1 <Key> -keysym b\n\tset y\n    }]\n    update\n    list $x $y\n} -cleanup {\n    interp delete child\n    deleteWindows\n    bind . <Key> {}\n} -result {{} {{key b}}}\n\ntest unixEmbed-8.1 {TkpClaimFocus procedure} -constraints {\n    unix notAqua failsOnCILinux failsOnXQuartz\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -width 200 -height 50\n    pack .f1 .f2\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1 -highlightthickness 2 -bd 2 -relief sunken\n    }\n    focus -force .f2\n    update\n    list [childTkProcess eval {\n\tfocus .t1\n\tset x [list [focus]]\n\tupdate\n\tafter 500\n\tupdate\n\tlappend x [focus]\n    }] [focus]\n} -cleanup {\n    deleteWindows\n} -result {{{} .t1} .f1}\ntest unixEmbed-8.1a {TkpClaimFocus procedure} -constraints unix -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -width 200 -height 50\n    pack .f1 .f2\n    update\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken\n    }\n    # This should clear focus from the application embedded in .f1\n    focus -force .f2\n    update\n    list [child eval {\n\tset x [list [focus]]\n\tfocus .t1\n\tupdate\n\tlappend x [focus]\n    }] [focus]\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{{} .t1} .f1}\ntest unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {\n    deleteWindows\n    catch {interp delete child}\n    interp create child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -width 200 -height 50\n    pack .f1 .f2\n    update\n    set w1 [winfo id .f1]\n    child eval \"set argv {-use [winfo id .f1]}\"\n    load {} Tk child\n    child eval {\n\t. configure -bd 2 -highlightthickness 2 -relief sunken\n    }\n    focus -force .f2\n    update\n    list [child eval {\n\tfocus .\n\tset x [list [focus]]\n\tupdate\n\tlappend x [focus]\n    }] [focus]\n} -cleanup {\n    deleteWindows\n} -result {{{} .} .f1}\n\n#\n# COMMON TEST CLEANUP\n#\ncatch {interp delete child}\n\ntest unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    frame .f2 -container 1 -width 200 -height 50\n    frame .f3 -container 1 -width 200 -height 50\n    frame .f4 -container 1 -width 200 -height 50\n    pack .f1 .f2 .f3 .f4\n    set x {}\n    lappend x [testembed]\n    foreach w {.f3 .f4 .f1 .f2} {\n\tdestroy $w\n\tlappend x [testembed]\n    }\n    set x\n} -cleanup {\n    deleteWindows\n} -result {{{XXX .f4 {} {}} {XXX .f3 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f4 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}}} {}}\ntest unixEmbed-9.2 {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {\n    unix testembed notAqua\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    childTkProcess eval \"set w1 [winfo id .f1]\"\n    childTkProcess eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use $w1 -highlightthickness 2 -bd 2 -relief sunken\n\tset x {}\n\tlappend x [testembed]\n\tdestroy .t1\n\tlappend x [testembed]\n    }\n} -cleanup {\n    deleteWindows\n} -result {{{XXX {} {} .t1}} {}}\ntest unixEmbed-9.2a {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {\n    unix testembed\n} -setup {\n    deleteWindows\n    catch {interp delete child}\n    childTkInterp child\n    load {} Tktest child\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    child alias w1 winfo id .f1\n    child eval {\n\tdestroy {*}[winfo children .]\n\ttoplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken\n\tset x {}\n\tlappend x [testembed]\n\tdestroy .t1\n\tlappend x [testembed]\n    }\n} -cleanup {\n    interp delete child\n    deleteWindows\n} -result {{{XXX {} {} .t1}} {}}\n\n\ntest unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    toplevel .t1 -use [winfo id .f1] -width 150 -height 80\n    update\n    wm geometry .t1 +40+50\n    update\n    wm geometry .t1\n} -cleanup {\n    deleteWindows\n} -result {150x80+0+0}\ntest unixEmbed-10.2 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -container 1 -width 200 -height 50\n    pack .f1\n    update\n    toplevel .t1 -use [winfo id .f1] -width 150 -height 80\n    update\n    wm geometry .t1 70x300+10+20\n    update\n    wm geometry .t1\n} -cleanup {\n    deleteWindows\n} -result {70x300+0+0}\n\ntest unixEmbed-11.1 {focus -force works for embedded toplevels} -constraints {\n    unix\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t\n    pack [frame .t.f -container 1 -width 200 -height 200] -fill both\n    update\n    toplevel .embed -use [winfo id .t.f] -bg green\n    update\n    focus -force .t\n    focus -force .embed\n    focus\n} -cleanup {\n    deleteWindows\n} -result .embed\ntest unixEmbed-11.2 {mouse coordinates in embedded toplevels} -constraints {\n    unix testpressbutton\n} -setup {\n    deleteWindows\n} -body {\n    set result {}\n    toplevel .main\n    update\n    frame .main.f -container 1 -width 200 -height 200\n    button .main.b -text \"Main Button\" -command {lappend result \"pushed .main.b\"}\n    wm geometry .main 200x400+100+100\n    pack .main.f -fill both\n    pack .main.b -padx 30 -pady 30\n    update\n    toplevel .embed -use [winfo id .main.f] -bg green\n    button .embed.b -text \"Emb Button\" -command {lappend result \"pushed .embed.b\"}\n    pack .embed.b -padx 30 -pady 30\n    update\n    focus -force .main\n    update\n    set x [expr {[winfo rootx .main.b] + [winfo width .main.b]/2}]\n    set y [expr {[winfo rooty .main.b] + [winfo height .main.b]/2}]\n    lappend result [winfo containing $x $y]\n    testpressbutton $x $y\n    update\n    set x [expr {[winfo rootx .embed.b] + [winfo width .embed.b]/2}]\n    set y [expr {[winfo rooty .embed.b] + [winfo height .embed.b]/2}]\n    lappend result [winfo containing $x $y]\n    testpressbutton $x $y\n    update\n    set result\n} -cleanup {\n    deleteWindows\n} -result {.main.b {pushed .main.b} .embed.b {pushed .embed.b}}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\nchildTkProcess exit\ntestutils forget child colors\ncleanupTests\n"
  },
  {
    "path": "tests/unixFont.test",
    "content": "# This file is a Tcl script that tests the unix-specific features of the Tk font\n# system (implemented in tkUnixFont.c).\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. Tests regarding the font\n#   system that are specific to the MS Windows platform go into the test file\n#   winFont.test. Tests that are platform-indifferent go into the test file\n#   font.test. Or they may exist as each other's counterparts in both\n#   unixFont.test and winFont.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * All tests in this test file are currently specific for the x11 windowing\n#   system. The file doesn't contain any tests (yet) that can be run on macOS/aqua\n#   (see also: https://core.tcl-lang.org/tk/info/98db50bdad).\n# * This test file is skipped entirely on non-unix platforms.\n# * Many of the tests are visually oriented. They do exercise the code in\n#   question, but there are no results that can be checked programmatically\n#   (such as \"does an underlined font appear to be underlined?\").\n# * Some tests depend on the fonts having or not having certain properties,\n#   which may not be valid at all sites.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import geometry\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\nif {[tk windowingsystem] eq \"x11\"} {\n    if {[testConstraint withXft]} {\n\tset fontsystemcmd [auto_execok fc-list]\n    } else {\n\tset fontsystemcmd [auto_execok xlsfonts]\n    }\n}\n\nforeach {constraint font} {\n    hasArial      arial\n    hasCourierNew \"courier new\"\n    hasTimesNew   \"times new roman\"\n} {\n    testConstraint $constraint 0\n    if {([tk windowingsystem] eq \"x11\") && [llength $fontsystemcmd]} {\n\tif {[testConstraint withXft]} {\n\t    if {[exec $fontsystemcmd $font family] ne \"\"} {\n\t\ttestConstraint $constraint 1\n\t    }\n\t} else {\n\t    # With the old font system, the constraint is true by default,\n\t    # except on the mac with XQuartz\n\t    testConstraint $constraint [expr {!(($tcl_platform(os) eq \"Darwin\") \\\n\t\t\t\t\t     && ([tk windowingsystem] eq \"x11\"))}]\n\t    if {![catch {eval exec $fontsystemcmd [list *-$font-*]} res]\n\t\t    && ![string match *unmatched* $res]} {\n\t\t# Newer Unix systems have more default fonts installed,\n\t\t# so we can't rely on fallbacks for fonts to need to\n\t\t# fall back on anything.\n\t\ttestConstraint $constraint 0\n\t    }\n\t}\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\ncatch {destroy .b}\ntoplevel .b\nwm geom .b +0+0\nupdate idletasks\n\n# Fonts must be fixed width and have chars missing below char 32, so that\n# tests can control char expansion and missing character code. Therefore\n# we're using TkFixedFont here for both the label and the canvas.\n\nlabel .b.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left -text \"0\" -font TkFixedFont\npack .b.l\ncanvas .b.c -closeenough 0\n\nset t [.b.c create text 0 0 -anchor nw -just left -font TkFixedFont]\npack .b.c\nupdate\n\nset cx [font measure TkFixedFont 0]\n\nset ax [winfo reqwidth .b.l]\nset ay [winfo reqheight .b.l]\n\n#\n# TESTS\n#\n\ntest unixfont-1.1 {TkpGetNativeFont procedure: not native} {x11} {\n    list [catch {font measure {} xyz} msg] $msg\n} {1 {font \"\" does not exist}}\ntest unixfont-1.2 {TkpGetNativeFont procedure: native} {x11 haveFixedFamilyFont} {\n    font measure fixed 0\n} 6\n\ntest unixfont-2.1 {TkpGetFontFromAttributes procedure: no family} x11 {\n    font actual {-size 10}\n    set x {}\n} {}\ntest unixfont-2.2 {TkpGetFontFromAttributes procedure: Times relatives} \\\n\t{x11 hasTimesNew} {\n    set x {}\n    lappend x [lindex [font actual {-family \"Times New Roman\"}] 1]\n    lappend x [lindex [font actual {-family \"New York\"}] 1]\n    lappend x [lindex [font actual {-family \"Times\"}] 1]\n} {times times times}\ntest unixfont-2.3 {TkpGetFontFromAttributes procedure: Courier relatives} \\\n\t{x11 hasCourierNew} {\n    set x {}\n    lappend x [lindex [font actual {-family \"Courier New\"}] 1]\n    lappend x [lindex [font actual {-family \"Monaco\"}] 1]\n    lappend x [lindex [font actual {-family \"Courier\"}] 1]\n} {courier courier courier}\ntest unixfont-2.4 {TkpGetFontFromAttributes procedure: Helvetica relatives} \\\n\t{x11 hasArial} {\n    set x {}\n    lappend x [lindex [font actual {-family \"Arial\"}] 1]\n    lappend x [lindex [font actual {-family \"Geneva\"}] 1]\n    lappend x [lindex [font actual {-family \"Helvetica\"}] 1]\n} {helvetica helvetica helvetica}\ntest unixfont-2.5 {TkpGetFontFromAttributes procedure: fallback} x11 {\n    font actual {-xyz-xyz-*-*-*-*-*-*-*-*-*-*-*-*}\n    set x {}\n} {}\ntest unixfont-2.6 {TkpGetFontFromAttributes: fallback to fixed family} {x11 haveFixedFamilyFont} {\n    lindex [font actual {-family fixed -size 10}] 1\n} {fixed}\ntest unixfont-2.7 {TkpGetFontFromAttributes: fixed family not available!} x11 {\n    # no test available\n} {}\ntest unixfont-2.8 {TkpGetFontFromAttributes: loop over returned font names} {x11 haveFixedFamilyFont} {\n    lindex [font actual {-family fixed -size 31}] 1\n} {fixed}\ntest unixfont-2.10 {TkpGetFontFromAttributes: scalable font found} {x11 havePointsize37Font} {\n    lindex [font actual {-family courier -size 37}] 3\n} 37\ntest unixfont-2.11 {TkpGetFontFromAttributes: font cannot be loaded} x11 {\n    # On Linux, XListFonts() was returning names for fonts that do not\n    # actually exist, causing the subsequent XLoadQueryFont() to fail\n    # unexpectedly.  Now falls back to another font if that happens.\n\n    font actual {-size 14}\n    set x {}\n} {}\n\ntest unixfont-3.1 {TkpDeleteFont procedure} x11 {\n    font actual {-family xyz}\n    set x {}\n} {}\n\ntest unixfont-4.1 {TkpGetFontFamilies procedure} x11 {\n    font families\n    set x {}\n} {}\n\ntest unixfont-5.1 {Tk_MeasureChars procedure: no chars to be measured} x11 {\n    .b.l config -text \"000000\" -wrap [expr {$ax*3}]\n    .b.l config -wrap 0\n} {}\ntest unixfont-5.2 {Tk_MeasureChars procedure: no right margin} x11 {\n    .b.l config -text \"000000\"\n} {}\ntest unixfont-5.3 {Tk_MeasureChars procedure: loop over chars} x11 {\n    .b.l config -text \"0\"\n    .b.l config -text \"\\377\"\n    .b.l config -text \"0\\3770\\377\"\n    .b.l config -text \"000000000000000\"\n} {}\n\n#\n# COMMON TEST SETUP\n#\n\n.b.l config -wrap [expr {$ax*10}]\n\ntest unixfont-5.4 {Tk_MeasureChars procedure: reached right edge} x11 {\n    .b.l config -text \"0000000000000\"\n    getsize .b.l\n} \"[expr {$ax*10}] [expr {$ay*2}]\"\ntest unixfont-5.5 {Tk_MeasureChars procedure: ran out of chars} x11 {\n    .b.l config -text \"000000\"\n    getsize .b.l\n} \"[expr {$ax*6}] $ay\"\ntest unixfont-5.6 {Tk_MeasureChars procedure: find last word} {x11 !withXft} {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    .b.l config -text \"000000 00000\"\n    getsize .b.l\n} \"[expr {$ax*6}] [expr {$ay*2}]\"\ntest unixfont-5.7 {Tk_MeasureChars procedure: already saw space in line} {x11 !withXft} {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    .b.l config -text \"000000     00000\"\n    getsize .b.l\n} \"[expr {$ax*6}] [expr {$ay*2}]\"\ntest unixfont-5.8 {Tk_MeasureChars procedure: internal spaces significant} {x11 !withXft} {\n    # Text measurements may differ slightly from legacy Tk due to proper font shaping;\n    # skip test if compiled with Xft.\n    .b.l config -text \"00  000     00000\"\n    getsize .b.l\n} \"[expr {$ax*7}] [expr {$ay*2}]\"\ntest unixfont-5.9 {Tk_MeasureChars procedure: TK_PARTIAL_OK} {x11} {\n    .b.c dchars $t 0 end\n    .b.c insert $t 0 \"0000\"\n    .b.c index $t @[expr {int($ax*2.5)}],1\n} 2\ntest unixfont-5.10 {Tk_MeasureChars procedure: TK_AT_LEAST_ONE} x11 {\n    .b.l config -text \"000000000000\"\n    getsize .b.l\n} \"[expr {$ax*10}] [expr {$ay*2}]\"\ntest unixfont-5.11 {Tk_MeasureChars: TK_AT_LEAST_ONE + not even one char fit!} x11 {\n    set a [.b.l cget -wrap]\n    .b.l config -text \"000000\" -wrap 1\n    set x [getsize .b.l]\n    .b.l config -wrap $a\n    set x\n} \"$ax [expr {$ay*6}]\"\ntest unixfont-5.12 {Tk_MeasureChars procedure: include eol spaces} {x11} {\n    .b.l config -text \"000   \\n000\"\n    getsize .b.l\n} \"[expr {$ax*6}] [expr {$ay*2}]\"\n\ntest unixfont-6.1 {Tk_DrawChars procedure: loop test} x11 {\n    .b.l config -text \"a\"\n    update\n} {}\ntest unixfont-6.2 {Tk_DrawChars procedure: loop test} x11 {\n    .b.l config -text \"abcd\"\n    update\n} {}\ntest unixfont-6.3 {Tk_DrawChars procedure: special char} x11 {\n    .b.l config -text \"\\001\"\n    update\n} {}\ntest unixfont-6.4 {Tk_DrawChars procedure: normal then special} x11 {\n    .b.l config -text \"ab\\001\"\n    update\n} {}\ntest unixfont-6.5 {Tk_DrawChars procedure: ends with special} x11 {\n    .b.l config -text \"ab\\001\"\n    update\n} {}\ntest unixfont-6.6 {Tk_DrawChars procedure: more normal chars at end} x11 {\n    .b.l config -text \"ab\\001def\"\n    update\n} {}\n\ntest unixfont-7.1 {DrawChars procedure: no effects} x11 {\n    .b.l config -text \"abc\"\n    update\n} {}\ntest unixfont-7.2 {DrawChars procedure: underlining} x11 {\n    set f [.b.l cget -font]\n    .b.l config -text \"abc\" -font \"courier 10 underline\"\n    update\n    .b.l config -font $f\n} {}\ntest unixfont-7.3 {DrawChars procedure: overstrike} x11 {\n    set f [.b.l cget -font]\n    .b.l config -text \"abc\" -font \"courier 10 overstrike\"\n    update\n    .b.l config -font $f\n} {}\n\ntest unixfont-8.1 {InitFont procedure: use old font} x11 {\n    font create xyz\n    button .c -font xyz\n    font configure xyz -family times\n    update\n    destroy .c\n    font delete xyz\n} {}\ntest unixfont-8.2 {InitFont procedure: parse information from XLFD} x11 {\n    expr {[lindex [font actual {-family times -size 0}] 3] == 0}\n} 0\ntest unixfont-8.3 {InitFont procedure: can't parse info from name} x11 {\n    catch {unset fontArray}\n    # check that font actual returns the correct attributes.\n    # the values of those attributes are system dependent.\n    array set fontArray [font actual a12biluc]\n    set result [lsort [array names fontArray]]\n    catch {unset fontArray}\n    set result\n} {-family -overstrike -size -slant -underline -weight}\ntest unixfont-8.4 {InitFont procedure: classify characters} {x11 nonPortable} {\n# Constrained by nonPortable because this test highly relies on fonts availability.\n# - without Xft, I couldn't find any font featuring a glyph of 6 charwidths\n#   for character \\u4000. The 'unifont' package provides this glyph but the\n#   width of \\u4000 is only 2 character widths (which seems visually fine).\n# - with Xft the problem is identical for \\u4000, and moreover the width\n#   of, say, \\002 depends on which fonts are installed.\n    set x 0\n    incr x [font measure TkFixedFont \"䀀\"]   ;# 6\n    incr x [font measure TkFixedFont \"\\002\"]   ;# 4\n    incr x [font measure TkFixedFont \"\\012\"]   ;# 2\n    incr x [font measure TkFixedFont \"\\101\"]   ;# 1\n    set x\n} [expr {$cx*13}]\ntest unixfont-8.5 {InitFont procedure: setup widths of normal chars} x11 {\n    font metrics TkFixedFont -fixed\n} 1\ntest unixfont-8.6 {InitFont procedure: setup widths of special chars} {x11 nonPortable} {\n# Constrained by nonPortable, see unixfont-8.4\n    set x 0\n    incr x [font measure TkFixedFont \"\\001\"]   ;# 4\n    incr x [font measure TkFixedFont \"\\002\"]   ;# 4\n    incr x [font measure TkFixedFont \"\\012\"]   ;# 2\n    set x\n} [expr {$cx*10}]\ntest unixfont-8.7 {InitFont procedure: XA_UNDERLINE_POSITION} x11 {\n    catch {font actual -adobe-courier-bold-i-normal--0-0-0-0-m-0-iso8859-1}\n    set x {}\n} {}\ntest unixfont-8.8 {InitFont procedure: no XA_UNDERLINE_POSITION} x11 {\n    catch {font actual --symbol-medium-r-normal--0-0-0-0-p-0-sun-fontspecific}\n    set x {}\n} {}\ntest unixfont-8.9 {InitFont procedure: XA_UNDERLINE_THICKNESS} x11 {\n    catch {font actual -adobe-courier-bold-i-normal--0-0-0-0-m-0-iso8859-1}\n    set x {}\n} {}\ntest unixfont-8.10 {InitFont procedure: no XA_UNDERLINE_THICKNESS} x11 {\n    catch {font actual --symbol-medium-r-normal--0-0-0-0-p-0-sun-fontspecific}\n    set x {}\n} {}\ntest unixfont-8.11 {InitFont procedure: XA_UNDERLINE_POSITION was 0} x11 {\n    catch {font actual -adobe-courier-bold-i-normal--0-0-0-0-m-0-iso8859-1}\n    set x {}\n} {}\n\ntest unixfont-9.1 {2 chars substituted in inserted text} {x11 nonPortable} {\n# Constrained by nonPortable, see unixfont-8.4\n    .b.c dchars $t 0 end\n    .b.c insert $t 0 \"0\\a0\"\n    set x {}\n    lappend x [.b.c index $t @[expr {$ax*0}],0]\n    lappend x [.b.c index $t @[expr {$ax*1}],0]\n    lappend x [.b.c index $t @[expr {$ax*2}],0]\n    lappend x [.b.c index $t @[expr {$ax*3}],0]\n} {0 1 1 2}\ntest unixfont-9.2 {4 chars substituted in inserted text} {x11 nonPortable} {\n# Constrained by nonPortable, see unixfont-8.4\n    .b.c dchars $t 0 end\n    .b.c insert $t 0 \"0\\0010\"\n    set x {}\n    lappend x [.b.c index $t @[expr {$ax*0}],0]\n    lappend x [.b.c index $t @[expr {$ax*1}],0]\n    lappend x [.b.c index $t @[expr {$ax*2}],0]\n    lappend x [.b.c index $t @[expr {$ax*3}],0]\n    lappend x [.b.c index $t @[expr {$ax*4}],0]\n    lappend x [.b.c index $t @[expr {$ax*5}],0]\n} {0 1 1 1 1 2}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget geometry\ncleanupTests\n"
  },
  {
    "path": "tests/unixMenu.test",
    "content": "# This file is a Tcl script that tests the unix-specific features of the Tk menu\n# system.\n#\n# Copyright © 1995-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. This includes macOS.\n#   Tests regarding the menu system that are specific to the MS Windows platform\n#   go into the test file winMenu.test. Tests that are platform-indifferent go\n#   into the test file menu.test. Or they may exist as each other's counterparts\n#   in both unixMenu.test and winMenu.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-unix platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest unixMenu-1.1 {TkpNewMenu - normal menu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    list [menu .m1] [destroy .m1]\n} -returnCodes ok -result {.m1 {}}\ntest unixMenu-1.2 {TkpNewMenu - help menu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    . configure -menu .m1\n    .m1 add cascade -label Help -menu .m1.help\n    list [menu .m1.help] [. configure -menu \"\"] [destroy .m1]\n} -returnCodes ok -result {.m1.help {} {}}\n\n\ntest unixMenu-2.1 {TkpDestroyMenu - nothing to do} -constraints unix -body {}\n\n\ntest unixMenu-3.1 {TkpDestroymenuEntry - nothing to do} -constraints unix -body {}\n\n\ntest unixMenu-4.1 {TkpConfigureMenuEntry - non-cascade entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label test\n    list [.m1 entryconfigure test -label foo] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest unixMenu-4.2 {TkpConfigureMenuEntry - cascade entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -menu .m2 -label test\n    menu .m1.foo -tearoff 0\n    list [.m1 entryconfigure test -menu .m1.foo] [destroy .m1]\n} -returnCodes ok -result {{} {}}\n\n\ntest unixMenu-5.1 {TkpMenuNewEntry - nothing to do} -constraints unix -body {}\n\n\ntest unixMenu-6.1 {TkpSetWindowMenuBar - null menu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    . configure -menu .m1\n    list [. configure -menu \"\"] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest unixMenu-6.2 {TkpSetWindowMenuBar - menu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    list [. configure -menu .m1] [. configure -menu \"\"] [destroy .m1]\n} -returnCodes ok -result {{} {} {}}\n\n\ntest unixMenu-7.1 {Tk_SetMainMenubar - nothing to do} -constraints unix -body {}\n\n\ntest unixMenu-8.1 {GetMenuIndicatorGeometry - indicator off} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -indicatoron 0\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.2 {GetMenuIndicatorGeometry - not checkbutton or radio} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.3 {GetMenuIndicatorGeometry - checkbutton image} -constraints {\n    unix testImageType\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    menu .m1\n    image create test image1\n    .m1 add checkbutton -image image1 -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -cleanup {\n    image delete image1\n} -returnCodes ok\ntest unixMenu-8.4 {GetMenuIndicatorGeometry - checkbutton bitmap} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -bitmap questhead -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.5 {GetMenuIndicatorGeometry - checkbutton} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.6 {GetMenuIndicatorGeometry - radiobutton image} -constraints {\n    unix testImageType\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    menu .m1\n    image create test image1\n    .m1 add radiobutton -image image1 -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n    image delete image1\n} -returnCodes ok\ntest unixMenu-8.7 {GetMenuIndicatorGeometry - radiobutton bitmap} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -bitmap questhead -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.8 {GetMenuIndicatorGeometry - radiobutton} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-8.9 {GetMenuIndicatorGeometry - hideMargin} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo -hidemargin 1\n    .m1 invoke foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest unixMenu-9.1 {GetMenuAccelGeometry - cascade entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-9.2 {GetMenuAccelGeometry - non-null label} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -accel \"Ctrl+S\"\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest unixMenu-9.3 {GetMenuAccelGeometry - null label} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest unixMenu-10.1 {DrawMenuEntryBackground - active menubar} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    . configure -menu .m1\n    .m1 activate 1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -returnCodes ok -result {{} {} {}}\ntest unixMenu-10.2 {DrawMenuEntryBackground - active} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff activate 0\n    list [update] [destroy .m1]\n} -returnCodes ok -result {{} {}}\ntest unixMenu-10.3 {DrawMenuEntryBackground - non-active} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -returnCodes ok -result {{} {}}\n\n\ntest unixMenu-11.1 {DrawMenuEntryAccelerator - menubar} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -accel \"Ctrl+U\"\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\n# drawArrow parameter is never false under Unix\ntest unixMenu-11.2 {DrawMenuEntryAccelerator - cascade entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n}  -result {{} {}}\ntest unixMenu-11.3 {DrawMenuEntryAccelerator - normal entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -accel \"Ctrl+U\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-11.4 {DrawMenuEntryAccelerator - null entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-12.1 {DrawMenuEntryIndicator - non-check or radio} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.2 {DrawMenuEntryIndicator - checkbutton - indicator off} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -indicatoron 0\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.3 {DrawMenuEntryIndicator - checkbutton - not selected} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.4 {DrawMenuEntryIndicator - checkbutton - selected} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.5 {DrawMenuEntryIndicator - radiobutton - indicator off} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo -indicatoron 0\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.6 {DrawMenuEntryIndicator - radiobutton - not selected} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-12.7 {DrawMenuEntryIndicator - radiobutton - selected} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-13.1 {DrawMenuSeparator - menubar case} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-13.2 {DrawMenuSepartor - normal menu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-14.1 {DrawMenuEntryLabel} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-15.1 {DrawMenuUnderline - menubar} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -underline 0\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-15.2 {DrawMenuUnderline - no menubar} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -underline 0\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-16.1 {TkpPostMenu} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest unixMenu-17.1 {GetMenuSeparatorGeometry} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest unixMenu-18.1 {GetTearoffEntryGeometry} -constraints {\n    unix nonUnixUserInteraction\n} -setup {\n    destroy .mb\n} -body {\n    menubutton .mb -text \"test\" -menu .mb.m\n    menu .mb.m\n    .mb.m add command -label test\n    pack .mb\n    raise .\n    list [tk::MbPost .mb] [tk::MenuUnpost .mb.m] [destroy .mb]\n} -result {{} {} {}}\n\n\n# Don't know how to reproduce the case where the tkwin has been deleted.\n\ntest unixMenu-19.1 {TkpComputeMenubarGeometry - zero entries} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\n# Don't know how to generate one width windows\ntest unixMenu-19.2 {TkpComputeMenubarGeometry - one entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label File\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.3 {TkpComputeMenubarGeometry - entry with different font} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -font \"Courier 24\"\n    .m1 add cascade -label File -font \"Helvetica 18\"\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.4 {TkpComputeMenubarGeometry - separator} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.5 {TkpComputeMenubarGeometry - First entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.6 {TkpComputeMenubarGeometry - First entry too wide} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File -font \"Times 72\"\n    . configure -menu .m1\n    wm geometry . 10x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.7 {TkpComputeMenubarGeometry - two entries fit} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File\n    .m1 add cascade -label Edit\n    . configure -menu .m1\n    wm geometry . 200x200\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.8 {TkpComputeMenubarGeometry - two entries; 2nd don't fit} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File\n    .m1 add cascade -label Edit -font \"Times 72\"\n    . configure -menu .m1\n    wm geometry . 100x100\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.9 {TkpComputeMenubarGeometry - two entries; 1st dont fit} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File -font \"Times 72\"\n    .m1 add cascade -label Edit\n    . configure -menu .m1\n    wm geometry . 100x100\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.10 {TkpComputeMenubarGeometry - two entries; neither fit} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0 -font \"Times 72\"\n    .m1 add cascade -label File\n    .m1 add cascade -label Edit\n    . configure -menu .m1\n    wm geometry . 10x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\n# ABC notation; capital A means first window fits, small a means it\n# does not. capital B menu means second window fist, etc.\ntest unixMenu-19.11 {TkpComputeMenubarGeometry - abc} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0 -font \"Times 72\"\n    .m1 add cascade -label \"aaaaa\"\n    .m1 add cascade -label \"bbbbb\"\n    .m1 add cascade -label \"ccccc\"\n    . configure -menu .m1\n    wm geometry . 10x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.12 {TkpComputeMenubarGeometry - abC} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"aaaaa\" -font \"Times 72\"\n    .m1 add cascade -label \"bbbbb\" -font \"Times 72\"\n    .m1 add cascade -label \"C\"\n    . configure -menu .m1\n    wm geometry . 10x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.13 {TkpComputeMenubarGeometry - aBc} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"aaaaa\" -font \"Times 72\"\n    .m1 add cascade -label \"B\"\n    .m1 add cascade -label \"ccccc\" -font \"Times 72\"\n    . configure -menu .m1\n    wm geometry . 10x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.14 {TkpComputeMenubarGeometry - aBC} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"aaaaa\" -font \"Times 72\"\n    .m1 add cascade -label \"B\"\n    .m1 add cascade -label \"C\"\n    . configure -menu .m1\n    wm geometry . 60x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.15 {TkpComputeMenubarGeometry - Abc} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"A\"\n    .m1 add cascade -label \"bbbbb\" -font \"Times 72\"\n    .m1 add cascade -label \"ccccc\" -font \"Times 72\"\n    . configure -menu .m1\n    wm geometry . 60x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.16 {TkpComputeMenubarGeometry - AbC} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"A\"\n    .m1 add cascade -label \"bbbbb\" -font \"Times 72\"\n    .m1 add cascade -label \"C\"\n    . configure -menu .m1\n    wm geometry . 60x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.17 {TkpComputeMenubarGeometry - ABc} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"A\"\n    .m1 add cascade -label \"B\"\n    .m1 add cascade -label \"ccccc\" -font \"Times 72\"\n    . configure -menu .m1\n    wm geometry . 60x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.18 {TkpComputeMenubarGeometry - ABC} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label \"A\"\n    .m1 add cascade -label \"B\"\n    .m1 add cascade -label \"C\"\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.19 {TkpComputeMenubarGeometry - help menu in first position} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help\n    menu .m1.help -tearoff 0\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file -tearoff 0\n    .m1 add cascade -label Edit -menu .m1.edit\n    menu .m1.edit -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.20 {TkpComputeMenubarGeometry - help menu in middle} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label Edit -menu .m1.edit\n    menu .m1.edit -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help\n    menu .m1.help -tearoff 0\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.21 {TkpComputeMenubarGeometry - help menu in first position} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file -tearoff 0\n    .m1 add cascade -label Edit -menu .m1.edit\n    menu .m1.edit -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help\n    menu .m1.help -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.22 {TkpComputeMenubarGeometry - help item fits} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help\n    menu .m1.help -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.23 {TkpComputeMenubarGeometry - help item does not fit} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help -font \"Helvetica 72\"\n    menu .m1.help -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-19.24 {TkpComputeMenubarGeometry - help item only one} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label Help -menu .m1.help\n    menu .m1.help -tearoff 0\n    . configure -menu .m1\n    wm geometry . 100x10\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\n\n\ntest unixMenu-20.1 {DrawTearoffEntry - menubar} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label File\n    . configure -menu .m1\n    list [update] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\ntest unixMenu-20.2 {DrawTearoffEntry - non-menubar} -constraints {\n    unix nonUnixUserInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    .m1 post 40 40\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-21.1 {TkpInitializeMenuBindings - nothing to do} -constraints unix -body {}\n\n\ntest unixMenu-22.1 {SetHelpMenu - no menubars} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label test -menu .m1.test\n    list [menu .m1.test] [destroy .m1]\n} -result {.m1.test {}}\n# Don't know how to automate missing tkwins\ntest unixMenu-22.2 {SetHelpMenu - menubar but no help menu} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    . configure -menu .m1\n    .m1 add cascade -label .m1.file\n    list [menu .m1.file] [. configure -menu \"\"] [destroy .m1]\n} -result {.m1.file {} {}}\ntest unixMenu-22.3 {SetHelpMenu - menubar with help menu} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    . configure -menu .m1\n    .m1 add cascade -label .m1.help\n    list [menu .m1.help] [. configure -menu \"\"] [destroy .m1]\n} -result {.m1.help {} {}}\ntest unixMenu-22.4 {SetHelpMenu - multiple menubars with same help menu} -constraints {\n    unix\n} -setup {\n    destroy .m1 .t2\n} -body {\n    toplevel .t2\n    wm geometry .t2 +40+40\n    menu .m1 -tearoff 0\n    . configure -menu .m1\n    .t2 configure -menu .m1\n    .m1 add cascade -label .m1.help\n    list [menu .m1.help] [. configure -menu \"\"] [destroy .m1] [destroy .t2]\n} -result {.m1.help {} {} {}}\n\n\ntest unixMenu-23.1 {TkpDrawMenuEntry - gc for active and not strict motif} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.2 {TkpDrawMenuEntry - gc for active menu item with its own gc} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activeforeground red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.3 {TkpDrawMenuEntry - gc for active and strict motif} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    set tk_strictMotif 1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1] [set tk_strictMotif 0]\n} -result {{} {} 0}\ntest unixMenu-23.4 {TkpDrawMenuEntry - gc for disabled with disabledfg and custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground blue\n    .m1 add command -label foo -state disabled -background red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.5 {TkpDrawMenuEntry - gc for disabled with disabledFg} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground blue\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.6 {TkpDrawMenuEntry - gc for disabled - no disabledFg} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground \"\"\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.7 {TkpDrawMenuEntry - gc for normal - custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -foreground red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.8 {TkpDrawMenuEntry - gc for normal} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.9 {TkpDrawMenuEntry - gc for indicator - custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -selectcolor orange\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.10 {TkpDrawMenuEntry - gc for indicator} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.11 {TkpDrawMenuEntry - border - custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activebackground green\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.12 {TkpDrawMenuEntry - border} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.13 {TkpDrawMenuEntry - active border - strict motif} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    set tk_strictMotif 1\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1] [set tk_strictMotif 0]\n} -result {{} {} 0}\ntest unixMenu-23.14 {TkpDrawMenuEntry - active border - custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activeforeground yellow\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.15 {TkpDrawMenuEntry - active border} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.16 {TkpDrawMenuEntry - font - custom entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -font \"Helvectica 72\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.17 {TkpDrawMenuEntry - font} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1 -font \"Courier 72\"\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.18 {TkpDrawMenuEntry - separator} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.19 {TkpDrawMenuEntry - standard} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.20 {TkpDrawMenuEntry - disabled cascade item} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file\n    .m1.file add command -label foo\n    .m1 entryconfigure File -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.21 {TkpDrawMenuEntry - indicator} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label Foo\n    .m1 invoke Foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-23.22 {TkpDrawMenuEntry - hide margin} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label Foo -hidemargin 1\n    .m1 invoke Foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-24.1 {GetMenuLabelGeometry - image} -constraints {\n    testImageType unix\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    menu .m1\n    image create test image1\n    .m1 add command -image image1\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest unixMenu-24.2 {GetMenuLabelGeometry - bitmap} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -bitmap questhead\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-24.3 {GetMenuLabelGeometry - no text} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-24.4 {GetMenuLabelGeometry - text} -constraints unix -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"This is a test.\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-25.1 {TkpComputeStandardMenuGeometry - no entries} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.2 {TkpComputeStandardMenuGeometry - one entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.3 {TkpComputeStandardMenuGeometry - more than one entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.4 {TkpComputeStandardMenuGeometry - separator} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.5 {TkpComputeStandardMenuGeometry - tearoff entry} -constraints {\n    unix nonUnixUserInteraction\n} -setup {\n    destroy .mb\n} -body {\n    menubutton .mb -text \"test\" -menu .mb.m\n    menu .mb.m\n    .mb.m add command -label test\n    pack .mb\n    catch {tk::MbPost .mb}\n    list [update] [tk::MenuUnpost .mb.m] [destroy .mb]\n} -result {{} {} {}}\ntest unixMenu-25.6 {TkpComputeStandardMenuGeometry - standard label geometry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.7 {TkpComputeStandardMenuGeometry - different font for entry} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -font \"Helvetica 12\"\n    .m1 add command -label \"test\" -font \"Courier 12\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.8 {TkpComputeStandardMenuGeometry - second entry larger} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.9 {TkpComputeStandardMenuGeometry - first entry larger} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test test\"\n    .m1 add command -label \"test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.10 {TkpComputeStandardMenuGeometry - accelerator} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"Ctrl+S\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.11 {TkpComputeStandardMenuGeometry - second accel larger} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"1\"\n    .m1 add command -label \"test\" -accel \"1 1\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.12 {TkpComputeStandardMenuGeometry - second accel smaller} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"1 1\"\n    .m1 add command -label \"test\" -accel \"1\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.13 {TkpComputeStandardMenuGeometry - indicator} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label test\n    .m1 invoke 1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.14 {TkpComputeStandardMenuGeometry - second indicator less or equal } -constraints {\n    unix testImageType\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    image create test image1\n    menu .m1\n    .m1 add checkbutton -image image1\n    .m1 invoke 1\n    .m1 add checkbutton -label test\n    .m1 invoke 2\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest unixMenu-25.15 {TkpComputeStandardMenuGeometry - second indicator larger } -constraints {\n    unix testImageType\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    image create test image1\n    menu .m1\n    .m1 add checkbutton -image image1\n    .m1 invoke 1\n    .m1 add checkbutton -label test\n    .m1 invoke 2\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest unixMenu-25.16 {TkpComputeStandardMenuGeometry - zero sized menus} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.17 {TkpComputeStandardMenuGeometry - first column bigger} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 add command -label three -columnbreak 1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.18 {TkpComputeStandardMenuGeometry - second column bigger} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two -columnbreak 1\n    .m1 add command -label three\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.19 {TkpComputeStandardMenuGeometry - three columns} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two -columnbreak 1\n    .m1 add command -label three\n    .m1 add command -label four\n    .m1 add command -label five -columnbreak 1\n    .m1 add command -label six\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest unixMenu-25.20 {TkpComputeStandardMenuGeometry - hide margin} -constraints {\n    unix\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add checkbutton -label one -hidemargin 1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\n\n\ntest unixMenu-26.1 {TkpMenuInit - nothing to do} -constraints unix -body {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ncleanupTests\n"
  },
  {
    "path": "tests/unixSelect.test",
    "content": "# This file contains tests for the tkUnixSelect.c file.\n#\n# Copyright © 1999 Scriptics Corporation.\n#\n# See the file \"license.terms\" for information on usage and redistribution\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. Tests that are platform-\n#   indifferent go into the test file select.test.\n# * All tests in this test file are currently specific for the x11 windowing\n#   system. The file doesn't contain any tests (yet) that can be run on macOS/aqua.\n# * This test file is skipped entirely on non-unix platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child select\n\n#\n# COMMON TEST SETUP\n#\n\n# Eliminate any existing selection on the screen.  This is needed in case\n# there is a selection in some other application, in order to prevent races\n# from causing false errors in the tests below.\nselection clear .\nafter 1500\n\n# set up a very large buffer to test INCR retrievals\nset longValue \"\"\nforeach i {a b c d e f g j h i j k l m o p q r s t u v w x y z} {\n    set j $i.1$i.2$i.3$i.4$i.5$i.6$i.7$i.8$i.9$i.10$i.11$i.12$i.13$i.14\n    append longValue A$j B$j C$j D$j E$j F$j G$j H$j I$j K$j L$j M$j N$j\n}\n\n#\n# TESTS\n#\n\ntest unixSelect-1.1 {TkSelGetSelection procedure: simple i18n text} -constraints {\n    x11\n} -setup {\n    destroy .e\n    childTkProcess create\n} -body {\n    pack [entry .e]\n    update\n    .e insert 0 über\n    .e selection range 0 end\n    childTkProcess eval {string length [selection get]}\n} -cleanup {\n    childTkProcess exit\n    destroy .e\n} -result 4\n\ntest unixSelect-1.2 {TkSelGetSelection procedure: simple i18n text, iso8859-1} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 üф\n\t.e selection range 0 end\n    }\n    selection get\n} -cleanup {\n    childTkProcess exit\n} -result ü?\n\ntest unixSelect-1.3 {TkSelGetSelection procedure: simple i18n text, iso2022} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n    selectionSetup\n} -body {\n    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \\\n\t{handler COMPOUND_TEXT}\n    selection own .\n    set selValue üф\n    set selInfo {}\n    set result [childTkProcess eval {\n\tset x [selection get -type COMPOUND_TEXT]\n\tlist [string equal üф $x] [string length $x]\n    }]\n    lappend result $selInfo\n} -cleanup {\n    childTkProcess exit\n} -result {1 2 {COMPOUND_TEXT 0 4000}}\n\ntest unixSelect-1.4 {TkSelGetSelection procedure: INCR i18n text, iso2022} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n    selectionSetup\n} -body {\n    # This test is subtle.  The selection ends up getting fetched twice by\n    # Tk:  once to compute the length, and again to actually send the data.\n    # The first time through, we don't convert the data to ISO2022, so the\n    # buffer boundaries end up being different in the two passes.\n    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \\\n\t{handler COMPOUND_TEXT}\n    selection own .\n    set selValue [string repeat x 3999]üф[string repeat x 3999]\n    set selInfo {}\n    set result [childTkProcess eval {\n\tset x [selection get -type COMPOUND_TEXT]\n\tlist [string equal \\\n\t    [string repeat x 3999]üф[string repeat x 3999] $x] \\\n\t    [string length $x]\n    }]\n    lappend result $selInfo\n} -cleanup {\n    childTkProcess exit\n} -result {1 8000 {COMPOUND_TEXT 0 4000 COMPOUND_TEXT 4000 3999 COMPOUND_TEXT 7998 4000 COMPOUND_TEXT 0 4000 COMPOUND_TEXT 4000 3998 COMPOUND_TEXT 7997 4000}}\n\ntest unixSelect-1.5 {TkSelGetSelection procedure: simple i18n text, iso2022} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n    selectionSetup\n} -body {\n    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \\\n\t{handler COMPOUND_TEXT}\n    selection own .\n    set selValue üф\n    set selInfo {}\n    set result [childTkProcess eval {\n\tset x [selection get -type COMPOUND_TEXT]\n\tlist [string equal üф $x] [string length $x]\n    }]\n    lappend result $selInfo\n} -cleanup {\n    childTkProcess exit\n} -result {1 2 {COMPOUND_TEXT 0 4000}}\n\ntest unixSelect-1.6 {TkSelGetSelection procedure: INCR i18n text} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval [subst -nobackslashes {entry .e; pack .e; update\n    .e insert 0 über$longValue\n    .e selection range 0 end}]\n    string length [selection get]\n} -cleanup {\n    childTkProcess exit\n} -result [expr {4 + [string length $longValue]}]\n\ntest unixSelect-1.7 {TkSelGetSelection procedure: INCR i18n text} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 [string repeat x 3999]ü\n\t.e selection range 0 end\n    }\n    selection get\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat x 3999]ü\n\ntest unixSelect-1.8 {TkSelGetSelection procedure: INCR i18n text} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 ü[string repeat x 3999]\n\t.e selection range 0 end\n    }\n    selection get\n} -cleanup {\n    childTkProcess exit\n} -result ü[string repeat x 3999]\n\ntest unixSelect-1.9 {TkSelGetSelection procedure: INCR i18n text} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 [string repeat x 3999]ü[string repeat x 4000]\n\t.e selection range 0 end\n    }\n    selection get\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat x 3999]ü[string repeat x 4000]\n\n# Now some tests to make sure that the right thing is done when\n# transferring UTF8 selections, to prevent [Bug 614650] and its ilk\n# from rearing its ugly head again.\n\ntest unixSelect-1.10 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 [string repeat x 3999]ü\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat x 3999]ü\n\ntest unixSelect-1.11 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 ü[string repeat x 3999]\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result ü[string repeat x 3999]\n\ntest unixSelect-1.12 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 [string repeat x 3999]ü[string repeat x 4000]\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat x 3999]ü[string repeat x 4000]\n\ntest unixSelect-1.13 {TkSelGetSelection procedure: simple i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    destroy .e\n    childTkProcess create\n} -body {\n    pack [entry .e]\n    update\n    .e insert 0 überф\n    .e selection range 0 end\n    childTkProcess eval {string length [selection get -type UTF8_STRING]}\n} -cleanup {\n    destroy .e\n    childTkProcess exit\n} -result 5\n\ntest unixSelect-1.14 {TkSelGetSelection procedure: simple i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 üф\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result üф\n\ntest unixSelect-1.15 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 [string repeat [string repeat Ää 50]\\n 21]\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat [string repeat Ää 50]\\n 21]\n\ntest unixSelect-1.16 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [entry .e]\n\tupdate\n\t.e insert 0 i[string repeat [string repeat Ää 50]\\n 21]\n\t.e selection range 0 end\n    }\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result i[string repeat [string repeat Ää 50]\\n 21]\n\ntest unixSelect-1.17 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [text .t]\n\tupdate\n\t.t insert 1.0 [string repeat [string repeat Ää 50]\\n 21]\n\t# Has to be selected in a separate stage\n\t.t tag add sel 1.0 21.end+1c\n    }\n    after 10\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result [string repeat [string repeat Ää 50]\\n 21]\n\ntest unixSelect-1.18 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {\n    x11\n} -setup {\n    childTkProcess create\n} -body {\n    childTkProcess eval {\n\tpack [text .t]\n\tupdate\n\t.t insert 1.0 i[string repeat [string repeat Ää 50]\\n 21]\n\t# Has to be selected in a separate stage\n\t.t tag add sel 1.0 21.end+1c\n    }\n    after 10\n    selection get -type UTF8_STRING\n} -cleanup {\n    childTkProcess exit\n} -result i[string repeat [string repeat Ää 50]\\n 21]\n\ntest unixSelect-1.19 {Automatic UTF8_STRING support for selection handle} -constraints {\n    unix\n} -setup {\n    destroy .l\n} -body {\n    # See Bug #666346 \"Selection handling crashes under KDE 3.0\"\n    label .l\n    selection handle .l  [list handler STRING]\n    set selValue \"This is the selection value\"\n    selection own .l\n    selection get -type UTF8_STRING\n} -cleanup {\n    destroy .l\n} -result {This is the selection value}\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget child select\ncleanupTests\n"
  },
  {
    "path": "tests/unixWm.test",
    "content": "# This file is a Tcl script to test out interactions with the window manager\n# that are specific for the unix platform, including the \"wm\" command.\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the unix platform. This includes macOS.\n#   Tests regarding the window manager that are specific to the MS Windows\n#   platform go into the test file winWm.test. Tests that are platform-\n#   indifferent go into the test file wm.test. Or they may exists as each\n#   other's counterparts in both unixWm.test and winWm.test, but only if\n#   they are an integral part of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-unix platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# makeToplevels --\n#\n#\tSet up a collection of top-level windows\n#\nproc makeToplevels {} {\n    deleteWindows\n    foreach i {.raise1 .raise2 .raise3} {\n\ttoplevel $i\n\twm geom $i 150x100+0+0\n\tupdate\n    }\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# On macOS windows are not allowed to overlap the menubar at the top of the\n# screen or the dock.  So tests which move a window and then check whether it\n# got moved to the requested location should use a y coordinate larger than the\n# height of the menubar (normally 23 pixels) and an x coordinate larger than\n# the width of the dock, if it happens to be on the left.  Starting with\n# macOS 15 (Sequoia) it became impossible for the y coordinate of the top\n# of a window to be less than 10 plus the menubar height (as reported by\n# [[NSApp mainMenu] menuBarHeight]).\nif {[tk windowingsystem] eq \"aqua\"} {\n    set mb [expr {[testmenubarheight] + 11}]\n    set X  100\n    set Y0 $mb\n    set Y2 [expr {$mb + 2}]\n    set Y5 [expr {$mb + 5}]\n} else {\n    set X  20\n    set Y0 0\n    set Y2 2\n    set Y5 5\n}\n\n#\n# TESTS\n#\n\nset i 1\nforeach geom \"+$X+80 +80+$Y0 +$X+$Y0\" {\n    destroy .t\n    test unixWm-1.$i {initial window position} unix {\n\ttoplevel .t -width 200 -height 150\n\twm geom .t $geom\n\tupdate\n\twm geom .t\n    } 200x150$geom\n    incr i\n}\n\n#\n# COMMON TEST SETUP\n#\n\n# The tests below are tricky because window managers don't all move\n# windows correctly.  Try one motion and compute the window manager's\n# error, then factor this error into the actual tests.  In other words,\n# this just makes sure that things are consistent between moves.\ndestroy .t\ntoplevel .t -width 100 -height 150\nwm geom .t +200+200\nupdate\nwm geom .t +150+150\nupdate\nscan [wm geom .t] %dx%d+%d+%d width height x y\nset xerr [expr {150-$x}]\nset yerr [expr {150-$y}]\n\nset i 1\nforeach geom \"+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5\" {\n    test unixWm-2.$i {moving window while mapped} unix {\n\twm geom .t $geom\n\tupdate\n\tscan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y\n\tformat \"%s%d%s%d\" $xsign [eval expr $x$xsign$xerr] $ysign \\\n\t\t[eval expr $y$ysign$yerr]\n    } $geom\n    incr i\n}\n\nset i 1\nforeach geom \"+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5\" {\n    test unixWm-3.$i {moving window while iconified} unix {\n\tupdate\n\twm iconify .t\n\tupdate idletasks\n\twm geom .t $geom\n\tupdate idletasks\n\twm deiconify .t\n\tupdate idletasks\n\tscan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y\n\tformat \"%s%d%s%d\" $xsign [eval expr $x$xsign$xerr] $ysign \\\n\t\t[eval expr $y$ysign$yerr]\n    } $geom\n    incr i\n}\n\nset i 1\nforeach geom \"+$X+80 +$X+40 +$X+$Y0\" {\n    test unixWm-4.$i {moving window while withdrawn} unix {\n\twm withdraw .t\n\tpause 10\n\twm geom .t $geom\n\tupdate idletasks\n\twm deiconify .t\n\tpause 10\n\twm geom .t\n    } 100x150$geom\n    incr i\n}\n\ntest unixWm-5.1 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm withdraw .t\n    wm deiconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {1 normal}\ntest unixWm-5.2 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm withdraw .t\n    wm deiconify .t\n    wm withdraw .t\n    list [winfo ismapped .t] [wm state .t]\n} {0 withdrawn}\ntest unixWm-5.3 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm iconify .t\n    wm deiconify .t\n    wm iconify .t\n    wm deiconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {1 normal}\ntest unixWm-5.4 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm iconify .t\n    wm deiconify .t\n    wm iconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {0 iconic}\ntest unixWm-5.5 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm iconify .t\n    wm withdraw .t\n    list [winfo ismapped .t] [wm state .t]\n} {0 withdrawn}\ntest unixWm-5.6 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm iconify .t\n    wm withdraw .t\n    wm deiconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {1 normal}\ntest unixWm-5.7 {compounded state changes} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 100\n    wm geometry .t +100+100\n    update\n    wm withdraw .t\n    wm iconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {0 iconic}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ntoplevel .t -width 200 -height 100\nwm geom .t +100+$Y0\nwm minsize .t 1 1\nupdate\n\ntest unixWm-6.1 {size changes} unix {\n    .t config -width 180 -height 150\n    update\n    wm geom .t\n} 180x150+100+$Y0\ntest unixWm-6.2 {size changes} unix {\n    wm geom .t 250x60\n    .t config -width 170 -height 140\n    update\n    wm geom .t\n} 250x60+100+$Y0\ntest unixWm-6.3 {size changes} unix {\n    wm geom .t 250x60\n    .t config -width 170 -height 140\n    wm geom .t {}\n    update\n    wm geom .t\n} 170x140+100+$Y0\ntest unixWm-6.4 {size changes} {unix nonPortable userInteraction} {\n    wm minsize .t 1 1\n    update\n    puts stdout \"Please resize window \\\"t\\\" with the mouse (but don't move it!),\"\n    puts -nonewline stdout \"then hit return: \"\n    flush stdout\n    gets stdin\n    update\n    set width [winfo width .t]\n    set height [winfo height .t]\n    .t config -width 230 -height 110\n    update\n    incr width -[winfo width .t]\n    incr height -[winfo height .t]\n    wm geom .t {}\n    update\n    set w2 [winfo width .t]\n    set h2 [winfo height .t]\n    .t config -width 114 -height 261\n    update\n    list $width $height $w2 $h2 [wm geom .t]\n} {0 0 230 110 114x261+10+10}\n\ntest unixWm-6.5 {window initially iconic} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 100 -height 30\n    wm geometry .t +0+0\n    wm title .t 2\n    wm iconify .t\n    update idletasks\n    wm withdraw .t\n    wm deiconify .t\n    list [winfo ismapped .t] [wm state .t]\n} {1 normal}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .m\ntoplevel .m\nwm overrideredirect .m 1\nforeach i {{Test label} Another {Yet another} {Last label}} j {1 2 3} {\n    label .m.$j -text $i\n}\nwm geometry .m +[expr {100 - [winfo vrootx .]}]+[expr {200 - [winfo vrooty .]}]\nupdate\n\ntest unixWm-7.1 {override_redirect and Tk_MoveTopLevelWindow} unix {\n    list [winfo ismapped .m] [wm state .m] [winfo x .m] [winfo y .m]\n} {1 normal 100 200}\n\ntest unixWm-7.2 {override_redirect and Tk_MoveTopLevelWindow} -constraints unix -setup {\n    wm geometry .m +[expr {150 - [winfo vrootx .]}]+[expr {210 - [winfo vrooty .]}]\n    update\n} -body {\n    list [winfo ismapped .m] [wm state .m] [winfo x .m] [winfo y .m]\n} -result {1 normal 150 210}\n\ntest unixWm-7.3 {override_redirect and Tk_MoveTopLevelWindow} -constraints unix -setup {\n    wm withdraw .m\n} -body {\n    list [winfo ismapped .m]\n} -cleanup {\n    destroy .m\n    destroy .t\n} -result 0\n\ntest unixWm-8.1 {icon windows} unix {\n    destroy .t\n    destroy .icon\n    toplevel .t -width 100 -height 30\n    wm geometry .t +0+0\n    toplevel .icon -width 50 -height 50 -bg red\n    wm iconwindow .t .icon\n    list [catch {wm withdraw .icon} msg] $msg\n} {1 {can't withdraw .icon: it is an icon for .t}}\ntest unixWm-8.2 {icon windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 30\n    list [catch {wm iconwindow} msg] $msg\n} {1 {wrong # args: should be \"wm option window ?arg ...?\"}}\ntest unixWm-8.3 {icon windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 30\n    list [catch {wm iconwindow .t b c} msg] $msg\n} {1 {wrong # args: should be \"wm iconwindow window ?pathName?\"}}\ntest unixWm-8.4 {icon windows} {unix failsOnCILinux failsOnXQuartz} {\n    destroy .t\n    destroy .icon\n    toplevel .t -width 100 -height 30\n    wm geom .t +0+0\n    update idletasks\n    set result [wm iconwindow .t]\n    toplevel .icon -width 50 -height 50 -bg red\n    wm iconwindow .t .icon\n    lappend result [wm iconwindow .t] [wm state .icon]\n    wm iconwindow .t {}\n    lappend result [wm iconwindow .t] [wm state .icon]\n    update\n    lappend result [winfo ismapped .t] [winfo ismapped .icon]\n    wm iconify .t\n    update idletasks\n    lappend result [winfo ismapped .t] [winfo ismapped .icon]\n} {.icon icon {} withdrawn 1 0 0 0}\ntest unixWm-8.5 {icon windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 30\n    list [catch {wm iconwindow .t .gorp} msg] $msg\n} {1 {bad window path name \".gorp\"}}\ntest unixWm-8.6 {icon windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 30\n    frame .t.icon -width 50 -height 50 -bg red\n    list [catch {wm iconwindow .t .t.icon} msg] $msg\n} {1 {can't use .t.icon as icon window: not at top level}}\ntest unixWm-8.7 {icon windows} -constraints unix -body {\n    destroy .t\n    destroy .icon\n    toplevel .t -width 100 -height 30\n    wm geom .t +0+0\n    toplevel .icon -width 50 -height 50 -bg red\n    toplevel .icon2 -width 50 -height 50 -bg green\n    wm iconwindow .t .icon\n    set result \"[wm iconwindow .t] [wm state .icon] [wm state .icon2]\"\n    wm iconwindow .t .icon2\n    lappend result [wm iconwindow .t] [wm state .icon] [wm state .icon2]\n} -cleanup {\n    destroy .icon2\n} -result {.icon icon normal .icon2 withdrawn icon}\ntest unixWm-8.8 {icon windows} unix {\n    destroy .t\n    destroy .icon\n    toplevel .icon -width 50 -height 50 -bg red\n    wm geom .icon +0+0\n    update\n    set result [winfo ismapped .icon]\n    toplevel .t -width 100 -height 30\n    wm geom .t +0+0\n    tkwait visibility .t\t;# Needed to keep tvtwm happy.\n    wm iconwindow .t .icon\n    lappend result [winfo ismapped .t] [winfo ismapped .icon]\n} {1 1 0}\ntest unixWm-8.9 {icon windows} {unix nonPortable} {\n    # This test is non-portable because some window managers will\n    # destroy an icon window when it's associated window is destroyed.\n\n    destroy .t\n    destroy .icon\n    toplevel .t -width 100 -height 30\n    toplevel .icon -width 50 -height 50 -bg red\n    wm geom .t +0+0\n    wm iconwindow .t .icon\n    update\n    set result \"[wm state .icon] [winfo ismapped .t] [winfo ismapped .icon]\"\n    destroy .t\n    wm geom .icon +0+0\n    update\n    lappend result [winfo ismapped .icon] [wm state .icon]\n    wm deiconify .icon\n    update\n    lappend result [winfo ismapped .icon] [wm state .icon]\n} {icon 1 0 0 withdrawn 1 normal}\n\ntest unixWm-8.10.1 {test for memory leaks} unix {\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    wm title .t \"This is a long long long long long long title\"\n    set x 1\n} 1\ntest unixWm-8.10.2 {test for memory leaks} unix {\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    wm group .t .\n    set x 1\n} 1\n\ntest unixWm-9.1 {TkWmMapWindow procedure, client property} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 100 -height 50\n    wm geom .t +0+0\n    wm client .t Test_String\n    update\n    testprop [testwrapper .t] WM_CLIENT_MACHINE\n} {Test_String}\ntest unixWm-9.2 {TkWmMapWindow procedure, command property} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 100 -height 50\n    wm geom .t +0+0\n    wm command .t \"test command\"\n    update\n    testprop [testwrapper .t] WM_COMMAND\n} {test\ncommand\n}\ntest unixWm-9.3 {TkWmMapWindow procedure, iconic windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 300 -bg blue\n    wm geom .t +0+0\n    wm iconify .t\n    winfo ismapped .t\n} 0\ntest unixWm-9.4 {TkWmMapWindow procedure, icon windows} unix {\n    destroy .t\n    toplevel .t -width 100 -height 50 -bg blue\n    tkwait visibility .t\n    wm iconwindow . .t\n    update\n    set result [winfo ismapped .t]\n} 0\ntest unixWm-9.5 {TkWmMapWindow procedure, normal windows} unix {\n    destroy .t\n    toplevel .t -width 200 -height 20\n    wm geom .t +0+0\n    update\n    winfo ismapped .t\n} 1\n\ntest unixWm-10.1 {TkWmDeadWindow procedure, canceling UpdateGeometry idle handler} unix {\n    destroy .t\n    toplevel .t -width 100 -height 50\n    wm geom .t +0+0\n    update\n    .t configure -width 200 -height 100\n    destroy .t\n} {}\ntest unixWm-10.2 {TkWmDeadWindow procedure, destroying menubar} {unix testmenubar} {\n    destroy .t\n    destroy .f\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    frame .f -width 400 -height 30 -bd 2 -relief raised -bg green\n    bind .f <Destroy> {lappend result destroyed}\n    testmenubar window .t .f\n    update\n    set result {}\n    destroy .t\n    lappend result [winfo exists .f]\n} {destroyed 0}\n\ntest unixWm-11.1 {Tk_WmCmd procedure, miscellaneous errors} unix {\n    list [catch {wm} msg] $msg\n} {1 {wrong # args: should be \"wm option window ?arg ...?\"}}\ntest unixWm-11.2 {Tk_WmCmd procedure, miscellaneous errors} unix {\n    list [catch {wm aspect} msg] $msg\n} {1 {wrong # args: should be \"wm option window ?arg ...?\"}}\ntest unixWm-11.3 {Tk_WmCmd procedure, miscellaneous errors} unix {\n    list [catch {wm iconify bogus} msg] $msg\n} {1 {bad window path name \"bogus\"}}\ntest unixWm-11.4 {Tk_WmCmd procedure, miscellaneous errors} unix {\n    destroy .b\n    button .b -text hello\n    list [catch {wm geometry .b} msg] $msg\n} {1 {window \".b\" isn't a top-level window}}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ndestroy .icon\ntoplevel .t -width 100 -height 50\nwm geom .t +0+0\nupdate\n\ntest unixWm-12.1 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 12} msg] $msg\n} {1 {wrong # args: should be \"wm aspect window ?minNumer minDenom maxNumer maxDenom?\"}}\ntest unixWm-12.2 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 12 13 14 15 16} msg] $msg\n} {1 {wrong # args: should be \"wm aspect window ?minNumer minDenom maxNumer maxDenom?\"}}\ntest unixWm-12.3 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    set result {}\n    lappend result [wm aspect .t]\n    wm aspect .t 3 4 10 2\n    lappend result [wm aspect .t]\n    wm aspect .t {} {} {} {}\n    lappend result [wm aspect .t]\n} {{} {3 4 10 2} {}}\ntest unixWm-12.4 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t bad 14 15 16} msg] $msg\n} {1 {expected integer but got \"bad\"}}\ntest unixWm-12.5 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 foo 15 16} msg] $msg\n} {1 {expected integer but got \"foo\"}}\ntest unixWm-12.6 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 14 bar 16} msg] $msg\n} {1 {expected integer but got \"bar\"}}\ntest unixWm-12.7 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 14 15 baz} msg] $msg\n} {1 {expected integer but got \"baz\"}}\ntest unixWm-12.8 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 0 14 15 16} msg] $msg\n} {1 {aspect number can't be <= 0}}\ntest unixWm-12.9 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 0 15 16} msg] $msg\n} {1 {aspect number can't be <= 0}}\ntest unixWm-12.10 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 14 0 16} msg] $msg\n} {1 {aspect number can't be <= 0}}\ntest unixWm-12.11 {Tk_WmCmd procedure, \"aspect\" option} unix {\n    list [catch {wm aspect .t 13 14 15 0} msg] $msg\n} {1 {aspect number can't be <= 0}}\n\ntest unixWm-13.1 {Tk_WmCmd procedure, \"client\" option} unix {\n    list [catch {wm client .t x y} msg] $msg\n} {1 {wrong # args: should be \"wm client window ?name?\"}}\ntest unixWm-13.2 {Tk_WmCmd procedure, \"client\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm client .t]\n    wm client .t Test_String\n    lappend result [testprop [testwrapper .t] WM_CLIENT_MACHINE]\n    wm client .t New\n    lappend result [wm client .t]\n    wm client .t {}\n    lappend result [wm client .t] [testprop [testwrapper .t] WM_CLIENT_MACHINE]\n} {{} Test_String New {} {}}\ntest unixWm-13.3 {Tk_WmCmd procedure, \"client\" option, unmapped window} unix {\n    destroy .t2\n    toplevel .t2\n    wm client .t2 Test_String\n    wm client .t2 {}\n    wm client .t2 Test_String\n    destroy .t2\n} {}\n\ntest unixWm-14.1 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    list [catch {wm colormapwindows .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm colormapwindows window ?windowList?\"}}\ntest unixWm-14.2 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 200 -height 200 -colormap new\n    wm geom .t2 +0+0\n    frame .t2.a -width 100 -height 30\n    frame .t2.b -width 100 -height 30 -colormap new\n    pack .t2.a .t2.b -side top\n    update\n    set x [wm colormapwindows .t2]\n    frame .t2.c -width 100 -height 30 -colormap new\n    pack .t2.c -side top\n    update\n    list $x [wm colormapwindows .t2]\n} {{.t2.b .t2} {.t2.b .t2.c .t2}}\ntest unixWm-14.3 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    list [catch {wm col . \"a \\{\"} msg] $msg\n} {1 {unmatched open brace in list}}\ntest unixWm-14.4 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    list [catch {wm colormapwindows . foo} msg] $msg\n} {1 {bad window path name \"foo\"}}\ntest unixWm-14.5 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 200 -height 200 -colormap new\n    wm geom .t2 +0+0\n    frame .t2.a -width 100 -height 30\n    frame .t2.b -width 100 -height 30\n    frame .t2.c -width 100 -height 30\n    pack .t2.a .t2.b .t2.c -side top\n    wm colormapwindows .t2 {.t2.c .t2 .t2.a}\n    wm colormapwindows .t2\n} {.t2.c .t2 .t2.a}\ntest unixWm-14.6 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 200 -height 200\n    wm geom .t2 +0+0\n    frame .t2.a -width 100 -height 30\n    frame .t2.b -width 100 -height 30\n    frame .t2.c -width 100 -height 30\n    pack .t2.a .t2.b .t2.c -side top\n    wm colormapwindows .t2 {.t2.b .t2.a}\n    wm colormapwindows .t2\n} {.t2.b .t2.a}\ntest unixWm-14.7 {Tk_WmCmd procedure, \"colormapwindows\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 200 -height 200 -colormap new\n    wm geom .t2 +0+0\n    set x [wm colormapwindows .t2]\n    wm colormapwindows .t2 {}\n    list $x [wm colormapwindows .t2]\n} {{} {}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t2\n\ntest unixWm-15.1 {Tk_WmCmd procedure, \"command\" option} unix {\n    list [catch {wm command .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm command window ?value?\"}}\ntest unixWm-15.2 {Tk_WmCmd procedure, \"command\" option} unix {\n    list [catch {wm command .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm command window ?value?\"}}\ntest unixWm-15.3 {Tk_WmCmd procedure, \"command\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm command .t]\n    wm command .t \"test command\"\n    lappend result [testprop [testwrapper .t] WM_COMMAND]\n    wm command .t \"new command\"\n    lappend result [wm command .t]\n    wm command .t {}\n    lappend result [wm command .t] [testprop [testwrapper .t] WM_COMMAND]\n} {{} {test\ncommand\n} {new command} {} {}}\ntest unixWm-15.4 {Tk_WmCmd procedure, \"command\" option, window not mapped} unix {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm command .t2 \"test command\"\n    wm command .t2 \"new command\"\n    wm command .t2 {}\n    destroy .t2\n} {}\ntest unixWm-15.5 {Tk_WmCmd procedure, \"command\" option} unix {\n    list [catch {wm command .t \"a \\{b\"} msg] $msg\n} {1 {unmatched open brace in list}}\n\ntest unixWm-16.1 {Tk_WmCmd procedure, \"deiconify\" option} unix {\n    list [catch {wm deiconify .t 12} msg] $msg\n} {1 {wrong # args: should be \"wm deiconify window\"}}\ntest unixWm-16.2 {Tk_WmCmd procedure, \"deiconify\" option} unix {\n    destroy .icon\n    toplevel .icon -width 50 -height 50 -bg red\n    wm iconwindow .t .icon\n    set result [list [catch {wm deiconify .icon} msg] $msg]\n    destroy .icon\n    set result\n} {1 {can't deiconify .icon: it is an icon for .t}}\ntest unixWm-16.3 {Tk_WmCmd procedure, \"deiconify\" option} {unix failsOnCILinux failsOnXQuartz} {\n    wm iconify .t\n    set result {}\n    lappend result [winfo ismapped .t] [wm state .t]\n    wm deiconify .t\n    lappend result [winfo ismapped .t] [wm state .t]\n} {0 iconic 1 normal}\n\ntest unixWm-17.1 {Tk_WmCmd procedure, \"focusmodel\" option} unix {\n    list [catch {wm focusmodel .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm focusmodel window ?active|passive?\"}}\ntest unixWm-17.2 {Tk_WmCmd procedure, \"focusmodel\" option} unix {\n    list [catch {wm focusmodel .t bogus} msg] $msg\n} {1 {bad argument \"bogus\": must be active or passive}}\ntest unixWm-17.3 {Tk_WmCmd procedure, \"focusmodel\" option} unix {\n    set result {}\n    lappend result [wm focusmodel .t]\n    wm focusmodel .t active\n    lappend result [wm focusmodel .t]\n    wm focusmodel .t passive\n    lappend result [wm focusmodel .t]\n    set result\n} {passive active passive}\n\ntest unixWm-18.1 {Tk_WmCmd procedure, \"frame\" option} unix {\n    list [catch {wm frame .t 12} msg] $msg\n} {1 {wrong # args: should be \"wm frame window\"}}\ntest unixWm-18.2 {Tk_WmCmd procedure, \"frame\" option} {unix nonPortable} {\n    expr {[wm frame .t] == [winfo id .t]}\n} 0\ntest unixWm-18.3 {Tk_WmCmd procedure, \"frame\" option} {unix nonPortable} {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm overrideredirect .t2 1\n    update\n    set result [expr {[wm frame .t2] == [winfo id .t2]}]\n    destroy .t2\n    set result\n} 1\n\ntest unixWm-19.1 {Tk_WmCmd procedure, \"geometry\" option} unix {\n    list [catch {wm geometry .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm geometry window ?newGeometry?\"}}\ntest unixWm-19.2 {Tk_WmCmd procedure, \"geometry\" option} {unix nonPortable} {\n    wm geometry .t -1+5\n    update\n    wm geometry .t\n} {100x50-1+5}\ntest unixWm-19.3 {Tk_WmCmd procedure, \"geometry\" option} {unix nonPortable} {\n    wm geometry .t +10-4\n    update\n    wm geometry .t\n} {100x50+10-4}\ntest unixWm-19.4 {Tk_WmCmd procedure, \"geometry\" option} {unix nonPortable} {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 -5+10\n    listbox .t2.l -width 30 -height 12 -setgrid 1\n    pack .t2.l\n    update\n    set result [wm geometry .t2]\n    destroy .t2\n    set result\n} {30x12-5+10}\ntest unixWm-19.5 {Tk_WmCmd procedure, \"geometry\" option} {unix nonPortable} {\n    wm geometry .t 150x300+5+6\n    update\n    set result {}\n    lappend result [wm geometry .t]\n    wm geometry .t {}\n    update\n    lappend result [wm geometry .t]\n} {150x300+5+6 100x50+5+6}\ntest unixWm-19.6 {Tk_WmCmd procedure, \"geometry\" option} unix {\n    list [catch {wm geometry .t qrs} msg] $msg\n} {1 {bad geometry specifier \"qrs\"}}\n\ntest unixWm-20.1 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm grid window ?baseWidth baseHeight widthInc heightInc?\"}}\ntest unixWm-20.2 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 12 13 14 15 16} msg] $msg\n} {1 {wrong # args: should be \"wm grid window ?baseWidth baseHeight widthInc heightInc?\"}}\ntest unixWm-20.3 {Tk_WmCmd procedure, \"grid\" option} unix {\n    set result {}\n    lappend result [wm grid .t]\n    wm grid .t 5 6 20 10\n    lappend result [wm grid .t]\n    wm grid .t {} {} {} {}\n    lappend result [wm grid .t]\n} {{} {5 6 20 10} {}}\ntest unixWm-20.4 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t bad 10 11 12} msg] $msg\n} {1 {expected integer but got \"bad\"}}\ntest unixWm-20.5 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t -1 11 12 13} msg] $msg\n} {1 {baseWidth can't be < 0}}\ntest unixWm-20.6 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 foo 12 13} msg] $msg\n} {1 {expected integer but got \"foo\"}}\ntest unixWm-20.7 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 -11 12 13} msg] $msg\n} {1 {baseHeight can't be < 0}}\ntest unixWm-20.8 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 11 bar 13} msg] $msg\n} {1 {expected integer but got \"bar\"}}\ntest unixWm-20.9 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 11 -2 13} msg] $msg\n} {1 {widthInc can't be <= 0}}\ntest unixWm-20.10 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 11 12 bogus} msg] $msg\n} {1 {expected integer but got \"bogus\"}}\ntest unixWm-20.11 {Tk_WmCmd procedure, \"grid\" option} unix {\n    list [catch {wm grid .t 10 11 12 -1} msg] $msg\n} {1 {heightInc can't be <= 0}}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ndestroy .icon\ntoplevel .t -width 100 -height 50\nwm geom .t +0+0\nupdate\n\ntest unixWm-21.1 {Tk_WmCmd procedure, \"group\" option} unix {\n    list [catch {wm group .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm group window ?pathName?\"}}\ntest unixWm-21.2 {Tk_WmCmd procedure, \"group\" option} unix {\n    list [catch {wm group .t bogus} msg] $msg\n} {1 {bad window path name \"bogus\"}}\ntest unixWm-21.3 {Tk_WmCmd procedure, \"group\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm group .t]\n    wm group .t .\n    set bit [format 0x%x [expr {0x40 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm group .t] $bit\n    wm group .t {}\n    set bit [format 0x%x [expr {0x40 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm group .t] $bit\n} {{} . 0x40 {} 0x0}\ntest unixWm-21.4 {Tk_WmCmd procedure, \"group\" option, make window exist} {unix testwrapper} {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm group .t .t2\n    set hints [testprop [testwrapper .t] WM_HINTS]\n    set result [expr {[testwrapper .t2] - [lindex $hints 8]}]\n    destroy .t2\n    set result\n} 0\ntest unixWm-21.5 {Tk_WmCmd procedure, \"group\" option, create leader wrapper} {unix testwrapper} {\n    destroy .t2\n    destroy .t3\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    toplevel .t3 -width 120 -height 300\n    wm geometry .t2 +0+0\n    set result [list [testwrapper .t2]]\n    wm group .t3 .t2\n    lappend result [expr {[testwrapper .t2] eq \"\"}]\n    destroy .t2 .t3\n    set result\n} {{} 0}\n\ntest unixWm-22.1 {Tk_WmCmd procedure, \"iconbitmap\" option} unix {\n    list [catch {wm iconbitmap .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm iconbitmap window ?bitmap?\"}}\ntest unixWm-22.2 {Tk_WmCmd procedure, \"iconbitmap\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm iconbitmap .t]\n    wm iconbitmap .t questhead\n    set bit [format 0x%x [expr {0x4 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconbitmap .t] $bit\n    wm iconbitmap .t {}\n    set bit [format 0x%x [expr {0x4 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconbitmap .t] $bit\n} {{} questhead 0x4 {} 0x0}\ntest unixWm-22.3 {Tk_WmCmd procedure, \"iconbitmap\" option} unix {\n    list [catch {wm iconbitmap .t bad-bitmap} msg] $msg\n} {1 {bitmap \"bad-bitmap\" not defined}}\n\ntest unixWm-23.1 {Tk_WmCmd procedure, \"iconify\" option} unix {\n    list [catch {wm iconify .t 12} msg] $msg\n} {1 {wrong # args: should be \"wm iconify window\"}}\ntest unixWm-23.2 {Tk_WmCmd procedure, \"iconify\" option} unix {\n    destroy .t2\n    toplevel .t2\n    wm overrideredirect .t2 1\n    set result [list [catch {wm iconify .t2} msg] $msg]\n    destroy .t2\n    set result\n} {1 {can't iconify \".t2\": override-redirect flag is set}}\ntest unixWm-23.3 {Tk_WmCmd procedure, \"iconify\" option} unix {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm transient .t2 .t\n    set result [list [catch {wm iconify .t2} msg] $msg]\n    destroy .t2\n    set result\n} {1 {can't iconify \".t2\": it is a transient}}\ntest unixWm-23.4 {Tk_WmCmd procedure, \"iconify\" option} unix {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm iconwindow .t .t2\n    set result [list [catch {wm iconify .t2} msg] $msg]\n    destroy .t2\n    set result\n} {1 {can't iconify \".t2\": it is an icon for \".t\"}}\ntest unixWm-23.5 {Tk_WmCmd procedure, \"iconify\" option} {unix failsOnCILinux failsOnXQuartz} {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 +0+0\n    update idletasks\n    wm iconify .t2\n    update idletasks\n    set result [winfo ismapped .t2]\n    destroy .t2\n    set result\n} 0\ntest unixWm-23.6 {Tk_WmCmd procedure, \"iconify\" option} {unix failsOnCILinux failsOnXQuartz} {\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 -0+0\n    update idletasks\n    set result [winfo ismapped .t2]\n    wm iconify .t2\n    update idletasks\n    lappend result [winfo ismapped .t2]\n    destroy .t2\n    set result\n} {1 0}\n\ntest unixWm-24.1 {Tk_WmCmd procedure, \"iconmask\" option} unix {\n    list [catch {wm iconmask .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm iconmask window ?bitmap?\"}}\ntest unixWm-24.2 {Tk_WmCmd procedure, \"iconmask\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm iconmask .t]\n    wm iconmask .t questhead\n    set bit [format 0x%x [expr {0x20 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconmask .t] $bit\n    wm iconmask .t {}\n    set bit [format 0x%x [expr {0x20 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconmask .t] $bit\n} {{} questhead 0x20 {} 0x0}\ntest unixWm-24.3 {Tk_WmCmd procedure, \"iconmask\" option} unix {\n    list [catch {wm iconmask .t bogus} msg] $msg\n} {1 {bitmap \"bogus\" not defined}}\n\ntest unixWm-25.1 {Tk_WmCmd procedure, \"iconname\" option} unix {\n    list [catch {wm icon .t} msg] $msg\n} {1 {ambiguous option \"icon\": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbadge, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}}\ntest unixWm-25.2 {Tk_WmCmd procedure, \"iconname\" option} unix {\n    list [catch {wm iconname .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm iconname window ?newName?\"}}\ntest unixWm-25.3 {Tk_WmCmd procedure, \"iconname\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm iconname .t]\n    wm iconname .t test_name\n    lappend result [wm iconname .t] [testprop [testwrapper .t] WM_ICON_NAME]\n    wm iconname .t {}\n    lappend result [wm iconname .t] [testprop [testwrapper .t] WM_ICON_NAME]\n} {{} test_name test_name {} {}}\n\ntest unixWm-26.1 {Tk_WmCmd procedure, \"iconposition\" option} unix {\n    list [catch {wm iconposition .t 12} msg] $msg\n} {1 {wrong # args: should be \"wm iconposition window ?x y?\"}}\ntest unixWm-26.2 {Tk_WmCmd procedure, \"iconposition\" option} unix {\n    list [catch {wm iconposition .t 12 13 14} msg] $msg\n} {1 {wrong # args: should be \"wm iconposition window ?x y?\"}}\ntest unixWm-26.3 {Tk_WmCmd procedure, \"iconposition\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm iconposition .t]\n    wm iconposition .t 10 15\n    set prop [testprop [testwrapper .t] WM_HINTS]\n    lappend result [wm iconposition .t] [lindex $prop 5] [lindex $prop 6]\n    lappend result  [format 0x%x [expr {0x10 & [lindex $prop 0]}]]\n    wm iconposition .t {} {}\n    set bit [format 0x%x [expr {0x10 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconposition .t] $bit\n} {{} {10 15} 0xa 0xf 0x10 {} 0x0}\ntest unixWm-26.4 {Tk_WmCmd procedure, \"iconposition\" option} unix {\n    list [catch {wm iconposition .t bad 13} msg] $msg\n} {1 {expected integer but got \"bad\"}}\ntest unixWm-26.5 {Tk_WmCmd procedure, \"iconposition\" option} unix {\n    list [catch {wm iconposition .t 13 lousy} msg] $msg\n} {1 {expected integer but got \"lousy\"}}\n\ntest unixWm-27.1 {Tk_WmCmd procedure, \"iconwindow\" option} unix {\n    list [catch {wm iconwindow .t 12 13} msg] $msg\n} {1 {wrong # args: should be \"wm iconwindow window ?pathName?\"}}\ntest unixWm-27.2 {Tk_WmCmd procedure, \"iconwindow\" option} {unix testwrapper} {\n    destroy .icon\n    toplevel .icon -width 50 -height 50 -bg green\n    set result {}\n    lappend result [wm iconwindow .t]\n    wm iconwindow .t .icon\n    set prop [testprop [testwrapper .t] WM_HINTS]\n    lappend result [wm iconwindow .t] [wm state .icon]\n    lappend result [format 0x%x [expr {0x8 & [lindex $prop 0]}]]\n    lappend result [expr {[testwrapper .icon] == [lindex $prop 4]}]\n    wm iconwindow .t {}\n    set bit [format 0x%x [expr {0x8 & [lindex [testprop [testwrapper .t] \\\n\t    WM_HINTS] 0]}]]\n    lappend result [wm iconwindow .t]  [wm state .icon] $bit\n    destroy .icon\n    set result\n} {{} .icon icon 0x8 1 {} withdrawn 0x0}\ntest unixWm-27.3 {Tk_WmCmd procedure, \"iconwindow\" option} unix {\n    list [catch {wm iconwindow .t bogus} msg] $msg\n} {1 {bad window path name \"bogus\"}}\ntest unixWm-27.4 {Tk_WmCmd procedure, \"iconwindow\" option} unix {\n    destroy .b\n    button .b -text Help\n    set result [list [catch {wm iconwindow .t .b} msg] $msg]\n    destroy .b\n    set result\n} {1 {can't use .b as icon window: not at top level}}\ntest unixWm-27.5 {Tk_WmCmd procedure, \"iconwindow\" option} unix {\n    destroy .icon\n    toplevel .icon -width 50 -height 50 -bg green\n    destroy .t2\n    toplevel .t2\n    wm geom .t2 -0+0\n    wm iconwindow .t2 .icon\n    set result [list [catch {wm iconwindow .t .icon} msg] $msg]\n    destroy .t2\n    destroy .icon\n    set result\n} {1 {.icon is already an icon for .t2}}\ntest unixWm-27.6 {Tk_WmCmd procedure, \"iconwindow\" option, changing icons} unix {\n    destroy .icon\n    destroy .icon2\n    toplevel .icon -width 50 -height 50 -bg green\n    toplevel .icon2 -width 50 -height 50 -bg red\n    set result {}\n    wm iconwindow .t .icon\n    lappend result [wm state .icon] [wm state .icon2]\n    wm iconwindow .t .icon2\n    lappend result [wm state .icon] [wm state .icon2]\n    destroy .icon .icon2\n    set result\n} {icon normal withdrawn icon}\ntest unixWm-27.7 {Tk_WmCmd procedure, \"iconwindow\" option, withdrawing icon} unix {\n    destroy .icon\n    toplevel .icon -width 50 -height 50 -bg green\n    wm geometry .icon +0+0\n    update\n    set result {}\n    lappend result [wm state .icon] [winfo viewable .icon]\n    wm iconwindow .t .icon\n    lappend result [wm state .icon] [winfo viewable .icon]\n    destroy .icon\n    set result\n} {normal 1 icon 0}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ndestroy .icon\ntoplevel .t -width 100 -height 50\nwm geom .t +0+0\nupdate\n\ntest unixWm-28.1 {Tk_WmCmd procedure, \"maxsize\" option, setting the\n\tmaxsize should update WM_NORMAL_HINTS} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm maxsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 7] [lindex $hints 8]\n} {300 300}\n\ntest unixWm-28.2 {Tk_WmCmd procedure, \"maxsize\" option, setting the\n\tmaxsize to a value smaller than the current size should\n\tset the maxsize in WM_NORMAL_HINTS} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm geom .t 400x400\n    wm maxsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 7] [lindex $hints 8]\n} {300 300}\n\ntest unixWm-28.3 {Tk_WmCmd procedure, \"maxsize\" option, setting the\n\tmaxsize to a value smaller than the current size should\n\tset the maxsize in WM_NORMAL_HINTS even if the\n\tinteractive resizable flag is set to 0} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm geom .t 400x400\n    wm resizable .t 0 0\n    wm maxsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 7] [lindex $hints 8]\n} {300 300}\n\ntest unixWm-29.1 {Tk_WmCmd procedure, \"minsize\" option, setting the\n\tminsize should update WM_NORMAL_HINTS} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm minsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 5] [lindex $hints 6]\n} {300 300}\n\ntest unixWm-29.2 {Tk_WmCmd procedure, \"minsize\" option, setting the\n\tminsize to a value larger than the current size should\n\tset the maxsize in WM_NORMAL_HINTS} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm geom .t 200x200\n    wm minsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 5] [lindex $hints 6]\n} {300 300}\n\ntest unixWm-29.3 {Tk_WmCmd procedure, \"minsize\" option, setting the\n\tminsize to a value larger than the current size should\n\tset the minsize in WM_NORMAL_HINTS even if the\n\tinteractive resizable flag is set to 0} {testwrapper} {\n    destroy .t\n    toplevel .t\n    wm geom .t 200x200\n    wm resizable .t 0 0\n    wm minsize .t 300 300\n    update\n    set hints [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    format {%d %d} [lindex $hints 5] [lindex $hints 6]\n} {300 300}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t .icon\ntoplevel .t -width 100 -height 50\nwm geom .t +0+0\nupdate\n\ntest unixWm-30.1 {Tk_WmCmd procedure, \"overrideredirect\" option} unix {\n    list [catch {wm overrideredirect .t 1 2} msg]  $msg\n} {1 {wrong # args: should be \"wm overrideredirect window ?boolean?\"}}\ntest unixWm-30.2 {Tk_WmCmd procedure, \"overrideredirect\" option} unix {\n    list [catch {wm overrideredirect .t boo} msg]  $msg\n} {1 {expected boolean value but got \"boo\"}}\ntest unixWm-30.3 {Tk_WmCmd procedure, \"overrideredirect\" option} unix {\n    set result {}\n    lappend result [wm overrideredirect .t]\n    wm overrideredirect .t true\n    lappend result [wm overrideredirect .t]\n    wm overrideredirect .t off\n    lappend result [wm overrideredirect .t]\n} {0 1 0}\n\ntest unixWm-31.1 {Tk_WmCmd procedure, \"positionfrom\" option} unix {\n    list [catch {wm positionfrom .t 1 2} msg]  $msg\n} {1 {wrong # args: should be \"wm positionfrom window ?user/program?\"}}\ntest unixWm-31.2 {Tk_WmCmd procedure, \"positionfrom\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm positionfrom .t]\n    wm positionfrom .t program\n    update\n    set bit [format 0x%x [expr {0x5 & [lindex [testprop [testwrapper .t] \\\n\t    WM_NORMAL_HINTS] 0]}]]\n    lappend result [wm positionfrom .t] $bit\n    wm positionfrom .t user\n    update\n    set bit [format 0x%x [expr {0x5 & [lindex [testprop [testwrapper .t] \\\n\t    WM_NORMAL_HINTS] 0]}]]\n    lappend result [wm positionfrom .t] $bit\n} {user program 0x4 user 0x1}\ntest unixWm-31.3 {Tk_WmCmd procedure, \"positionfrom\" option} unix {\n    list [catch {wm positionfrom .t none} msg]  $msg\n} {1 {bad argument \"none\": must be program or user}}\n\ntest unixWm-32.1 {Tk_WmCmd procedure, \"protocol\" option} unix {\n    list [catch {wm protocol .t 1 2 3} msg]  $msg\n} {1 {wrong # args: should be \"wm protocol window ?name? ?command?\"}}\ntest unixWm-32.2 {Tk_WmCmd procedure, \"protocol\" option} unix {\n    wm protocol .t {foo a} {a b c}\n    wm protocol .t bar {test script for bar}\n    set result [wm protocol .t]\n    wm protocol .t {foo a} {}\n    wm protocol .t bar {}\n    set result\n} {bar {foo a}}\ntest unixWm-32.3 {Tk_WmCmd procedure, \"protocol\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm protocol .t]\n    set x {}\n    foreach i [testprop [testwrapper .t] WM_PROTOCOLS] {\n\tlappend x [winfo atomname $i]\n    }\n    lappend result $x\n    wm protocol .t foo {test script}\n    wm protocol .t bar {test script}\n    set x {}\n    foreach i [testprop [testwrapper .t] WM_PROTOCOLS] {\n\tlappend x [winfo atomname $i]\n    }\n    lappend result [wm protocol .t] $x\n    wm protocol .t foo {}\n    wm protocol .t bar {}\n    set x {}\n    foreach i [testprop [testwrapper .t] WM_PROTOCOLS] {\n\tlappend x [winfo atomname $i]\n    }\n    lappend result [wm protocol .t] $x\n} {{} WM_DELETE_WINDOW {bar foo} {WM_DELETE_WINDOW bar foo} {} WM_DELETE_WINDOW}\ntest unixWm-32.4 {Tk_WmCmd procedure, \"protocol\" option} unix {\n    set result {}\n    wm protocol .t foo {a b c}\n    wm protocol .t bar {test script for bar}\n    lappend result [wm protocol .t foo] [wm protocol .t bar]\n    wm protocol .t foo {}\n    wm protocol .t bar {}\n    lappend result [wm protocol .t foo] [wm protocol .t bar]\n} {{a b c} {test script for bar} {} {}}\ntest unixWm-32.5 {Tk_WmCmd procedure, \"protocol\" option} unix {\n    wm protocol .t foo {a b c}\n    wm protocol .t foo {test script}\n    set result [wm protocol .t foo]\n    wm protocol .t foo {}\n    set result\n} {test script}\n\ntest unixWm-33.1 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    list [catch {wm resizable . a} msg]  $msg\n} {1 {wrong # args: should be \"wm resizable window ?width height?\"}}\ntest unixWm-33.2 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    list [catch {wm resizable . a b c} msg]  $msg\n} {1 {wrong # args: should be \"wm resizable window ?width height?\"}}\ntest unixWm-33.3 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    list [catch {wm resizable .foo a b c} msg]  $msg\n} {1 {bad window path name \".foo\"}}\ntest unixWm-33.4 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    list [catch {wm resizable . x 1} msg]  $msg\n} {1 {expected boolean value but got \"x\"}}\ntest unixWm-33.5 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    list [catch {wm resizable . 0 gorp} msg]  $msg\n} {1 {expected boolean value but got \"gorp\"}}\ntest unixWm-33.6 {Tk_WmCmd procedure, \"resizable\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 200 -height 100\n    wm geom .t2 +0+0\n    set result \"\"\n    lappend result [wm resizable .t2]\n    wm resizable .t2 1 0\n    lappend result [wm resizable .t2]\n    wm resizable .t2 no off\n    lappend result [wm resizable .t2]\n    wm resizable .t2 false true\n    lappend result [wm resizable .t2]\n    destroy .t2\n    set result\n} {{1 1} {1 0} {0 0} {0 1}}\n\ntest unixWm-34.1 {Tk_WmCmd procedure, \"sizefrom\" option} unix {\n    list [catch {wm sizefrom .t 1 2} msg]  $msg\n} {1 {wrong # args: should be \"wm sizefrom window ?user|program?\"}}\ntest unixWm-34.2 {Tk_WmCmd procedure, \"sizefrom\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm sizefrom .t]\n    wm sizefrom .t program\n    update\n    set bit [format 0x%x [expr {0xa & [lindex [testprop [testwrapper .t] \\\n\t    WM_NORMAL_HINTS] 0]}]]\n    lappend result [wm sizefrom .t] $bit\n    wm sizefrom .t user\n    update\n    set bit [format 0x%x [expr {0xa & [lindex [testprop [testwrapper .t] \\\n\t    WM_NORMAL_HINTS] 0]}]]\n    lappend result [wm sizefrom .t] $bit\n} {{} program 0x8 user 0x2}\ntest unixWm-34.3 {Tk_WmCmd procedure, \"sizefrom\" option} unix {\n    list [catch {wm sizefrom .t none} msg]  $msg\n} {1 {bad argument \"none\": must be program or user}}\ntest unixWm-35.1.1 {Tk_WmCmd procedure, \"state\" option} {unix notAqua} {\n    list [catch {wm state .t 1} msg]  $msg\n} {1 {bad argument \"1\": must be iconic, normal, or withdrawn}}\ntest unixWm-35.1.2 {Tk_WmCmd procedure, \"state\" option} {unix aqua} {\n    list [catch {wm state .t 1} msg]  $msg\n} {1 {bad argument \"1\": must be iconic, normal, withdrawn, or zoomed}}\ntest unixWm-35.2 {Tk_WmCmd procedure, \"state\" option} unix {\n    list [catch {wm state .t iconic 1} msg]  $msg\n} {1 {wrong # args: should be \"wm state window ?state?\"}}\ntest unixWm-35.3 {Tk_WmCmd procedure, \"state\" option} unix {\n    set result {}\n    destroy .t2\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    lappend result [wm state .t2]\n    update\n    lappend result [wm state .t2]\n    wm withdraw .t2\n    lappend result [wm state .t2]\n    wm iconify .t2\n    lappend result [wm state .t2]\n    wm deiconify .t2\n    lappend result [wm state .t2]\n    destroy .t2\n    set result\n} {normal normal withdrawn iconic normal}\ntest unixWm-35.4 {Tk_WmCmd procedure, \"state\" option} unix {\n    set result {}\n    destroy .t2\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    lappend result [wm state .t2]\n    update\n    lappend result [wm state .t2]\n    wm state .t2 withdrawn\n    lappend result [wm state .t2]\n    wm state .t2 iconic\n    lappend result [wm state .t2]\n    wm state .t2 normal\n    lappend result [wm state .t2]\n    destroy .t2\n    set result\n} {normal normal withdrawn iconic normal}\n\ntest unixWm-36.1 {Tk_WmCmd procedure, \"title\" option} unix {\n    list [catch {wm title .t 1 2} msg]  $msg\n} {1 {wrong # args: should be \"wm title window ?newTitle?\"}}\ntest unixWm-36.2 {Tk_WmCmd procedure, \"title\" option} {unix testwrapper} {\n    set result {}\n    lappend result [wm title .t] [testprop [testwrapper .t] WM_NAME]\n    wm title .t \"Test window\"\n    set bit [format 0x%x [expr {0xa & [lindex [testprop [testwrapper .t] \\\n\t    WM_NORMAL_HINTS] 0]}]]\n    lappend result [wm title .t] [testprop [testwrapper .t] WM_NAME]\n} {t t {Test window} {Test window}}\n\ntest unixWm-37.3 {Tk_WmCmd procedure, \"transient\" option} {unix testwrapper} {\n    set result {}\n    destroy .t2\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    update\n    lappend result [wm transient .t2] \\\n\t    [testprop [testwrapper .t2] WM_TRANSIENT_FOR]\n    wm transient .t2 .t\n    set transient [testprop [testwrapper .t2] WM_TRANSIENT_FOR]\n    lappend result [wm transient .t2] [expr {[testwrapper .t] - $transient}]\n    wm transient .t2 {}\n    lappend result [wm transient .t2] \\\n\t    [testprop [testwrapper .t2] WM_TRANSIENT_FOR]\n    destroy .t2\n    set result\n} {{} {} .t 0 {} {}}\ntest unixWm-37.4 {TkWmDeadWindow, destroy on toplevel should clear transient} {unix testwrapper} {\n    destroy .t2\n    toplevel .t2\n    destroy .t3\n    toplevel .t3\n    wm transient .t2 .t3\n    update\n    destroy .t3\n    update\n    list [wm transient .t2] [testprop [testwrapper .t2] WM_TRANSIENT_FOR]\n} {{} {}}\ntest unixWm-37.5 {Tk_WmCmd procedure, \"transient\" option, create toplevel wrapper} {unix testwrapper} {\n    destroy .t2\n    destroy .t3\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    toplevel .t3 -width 120 -height 300\n    wm geometry .t2 +0+0\n    set result [list [testwrapper .t2]]\n    wm transient .t3 .t2\n    lappend result [expr {[testwrapper .t2] eq \"\"}]\n    destroy .t2 .t3\n    set result\n} {{} 0}\n\ntest unixWm-38.1 {Tk_WmCmd procedure, \"withdraw\" option} unix {\n    list [catch {wm withdraw .t 1} msg]  $msg\n} {1 {wrong # args: should be \"wm withdraw window\"}}\ntest unixWm-38.2 {Tk_WmCmd procedure, \"withdraw\" option} unix {\n    destroy .t2\n    toplevel .t2 -width 120 -height 300\n    wm geometry .t2 +0+0\n    wm iconwindow .t .t2\n    set result [list [catch {wm withdraw .t2} msg]  $msg]\n    destroy .t2\n    set result\n} {1 {can't withdraw .t2: it is an icon for .t}}\ntest unixWm-38.3 {Tk_WmCmd procedure, \"withdraw\" option} unix {\n    set result {}\n    wm withdraw .t\n    lappend result [wm state .t] [winfo ismapped .t]\n    wm deiconify .t\n    lappend result [wm state .t] [winfo ismapped .t]\n} {withdrawn 0 normal 1}\n\ntest unixWm-39.1 {Tk_WmCmd procedure, miscellaneous} unix {\n    list [catch {wm unknown .t} msg] $msg\n} {1 {bad option \"unknown\": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbadge, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t .icon\n\ntest unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on grid} {unix nonPortable} {\n    destroy .t\n    toplevel .t\n    wm geometry .t 30x10+0+0\n    listbox .t.l -height 20 -width 20 -setgrid 1\n    pack .t.l -fill both -expand 1\n    update\n    wm geometry .t\n} {30x10+0+0}\ntest unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {\n    update\n    destroy .t\n    update\n    toplevel .t\n    wm geometry .t 200x100+100+$Y0\n    listbox .t.l -height 20 -width 20\n    pack .t.l -fill both -expand 1\n    update\n    .t.l configure -setgrid 1\n    update\n    wm geometry .t\n} \"20x20+100+$Y0\"\n\ntest unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {\n    destroy .t\n    toplevel .t -width 400 -height 150\n    tkwait visibility .t\n    wm geometry .t +0+0\n    update idletasks\n    set result {}\n    lappend result [winfo width .t] [winfo height .t]\n    .t configure -width 200 -height 300\n    update idletasks\n    lappend result [winfo width .t] [winfo height .t]\n} {400 150 200 300}\ntest unixWm-41.2 {ConfigureEvent procedure, menubars} {nonPortable testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .t.m -bd 2 -relief raised -height 20\n    testmenubar window .t .t.m\n    update\n    set result {}\n    bind .t <Configure> {\n\tif {\"%W\" eq \".t\"} {\n\t    lappend result \"%W: %wx%h\"\n\t}\n    }\n    bind .t.m <Configure> {lappend result \"%W: %wx%h\"}\n    wm geometry .t 200x300\n    update\n    lappend result [expr {[winfo rootx .t.m] - $x}] \\\n\t    [expr {[winfo rooty .t.m] - $y}] \\\n\t    [winfo width .t.m] [winfo height .t.m] \\\n\t    [expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}] \\\n\t    [winfo width .t] [winfo height .t]\n} {{.t.m: 200x20} {.t: 200x300} 0 0 200 20 0 20 200 300}\ntest unixWm-41.3 {ConfigureEvent procedure, synthesized Configure events} unix {\n    destroy .t\n    toplevel .t -width 400 -height 150\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set result {no event}\n    bind .t <Configure> {set result \"configured: %w %h\"}\n    wm geometry .t +10+20\n    update\n    set result\n} {configured: 400 150}\ntest unixWm-41.4 {ConfigureEvent procedure, synthesized Configure events} unix {\n    destroy .t\n    toplevel .t -width 400 -height 150\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set result {no event}\n    bind .t <Configure> {set result \"configured: %w %h\"}\n    wm geometry .t 130x200\n    update\n    set result\n} {configured: 130 200}\n\n# No tests for ReparentEvent or ComputeReparentGeometry; I can't figure\n# out how to exercise these procedures reliably.\n\ntest unixWm-42.1 {WrapperEventProc procedure, map and unmap events} {unix failsOnCILinux failsOnXQuartz} {\n    destroy .t\n    toplevel .t -width 400 -height 150\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set result {}\n    bind .t <Map> {set x \"mapped\"}\n    bind .t <Unmap> {set x \"unmapped\"}\n    set x {no event}\n    wm iconify .t\n    update idletasks\n    lappend result $x [winfo ismapped .t]\n    set x {no event}\n    wm deiconify .t\n    update idletasks\n    lappend result $x [winfo ismapped .t]\n} {unmapped 0 mapped 1}\n\ntest unixWm-43.1 {TopLevelReqProc procedure, embedded in same process} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200\n    wm geom .t +0+0\n    frame .t.f -container 1 -bd 2 -relief raised\n    place .t.f -x 20 -y 10\n    tkwait visibility .t.f\n    toplevel .t2 -use [winfo id .t.f] -width 30 -height 20 -bg blue\n    tkwait visibility .t2\n    set result {}\n    .t2 configure -width 70 -height 120\n    update\n    lappend result [winfo reqwidth .t.f] [winfo reqheight .t.f]\n    lappend result [winfo width .t2] [winfo height .t2]\n    # destroy .t2\n    set result\n} {70 120 70 120}\ntest unixWm-43.2 {TopLevelReqProc procedure, resize causes window to move} \\\n\t{unix nonPortable} {\n    destroy .t\n    toplevel .t -width 200 -height 200\n    wm geom .t +0+0\n    update\n    wm geom .t -0-0\n    update\n    set x [winfo x .t]\n    set y [winfo y .t]\n    .t configure -width 300 -height 150\n    update\n    list [expr {[winfo x .t] - $x}] [expr {[winfo y .t] - $y}] \\\n\t    [winfo width .t] [winfo height .t]\n} {-100 50 300 150}\n\ntest unixWm-44.1 {UpdateGeometryInfo procedure, width/height computation} unix {\n    destroy .t\n    toplevel .t -width 100 -height 200\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    .t configure  -width 180 -height 20\n    update\n    list [winfo width .t] [winfo height .t]\n} {180 20}\ntest unixWm-44.2 {UpdateGeometryInfo procedure, width/height computation} unix {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm grid .t 5 4 10 12\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    wm geometry .t 10x2\n    update\n    list [winfo width .t] [winfo height .t]\n} {130 36}\ntest unixWm-44.3 {UpdateGeometryInfo procedure, width/height computation} unix {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm grid .t 5 4 10 12\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    wm geometry .t 1x10\n    update\n    list [winfo width .t] [winfo height .t]\n} {40 132}\ntest unixWm-44.4 {UpdateGeometryInfo procedure, width/height computation} unix {\n    destroy .t\n    toplevel .t -width 100 -height 200\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    wm geometry .t 300x150\n    update\n    list [winfo width .t] [winfo height .t]\n} {300 150}\ntest unixWm-44.5 {UpdateGeometryInfo procedure, negative width} unix {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm grid .t 18 7 10 12\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    wm geometry .t 5x8\n    update\n    list [winfo width .t] [winfo height .t]\n} {1 72}\n\ntest unixWm-44.6 {UpdateGeometryInfo procedure, negative height} -constraints unix -setup {\n    destroy .t\n    toplevel .t -width 80 -height 60\n} -body {\n    wm grid .t 18 7 10 12\n    wm geometry .t +30+40\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    wm geometry .t 20x1\n    update\n    list [winfo width .t] [winfo height .t]\n} -result {100 1}\n\n#\n# COMMON TEST SETUP\n#\nif {! [winfo exists .t]} {\n    # The expected results for tests 44.7 and 44.8 require that window .t exists.\n    # That might not be the case if no previous tests are being run that create\n    # the window (because of the constraint unix or because of test selection\n    # using the tcltest option \"-match\" or \"-skip\"). Therefore, we create a dummy\n    # window .t here.\n    frame .t\n}\n\ntest unixWm-44.7 {UpdateGeometryInfo procedure, computing position} -constraints unix -setup {\n    destroy .t\n    toplevel .t -width 80 -height 60\n} -body {\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    update\n    wm geometry .t +5-10\n    update\n    list [winfo x .t] [winfo y .t]\n} -result [list 5 [expr {[winfo screenheight .t] - 70}]]\ntest unixWm-44.8 {UpdateGeometryInfo procedure, computing position} -constraints unix -setup {\n    destroy .t\n    toplevel .t -width 80 -height 60\n} -body {\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    update\n    wm geometry .t -30+$Y2\n    update\n    list [winfo x .t] [winfo y .t]\n} -cleanup {\n    destroy .t\n} -result [list [expr {[winfo screenwidth .t] - 110}] $Y2]\n\ntest unixWm-44.9 {UpdateGeometryInfo procedure, updating fixed dimensions} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm resizable .t 0 0\n    wm geometry .t +0+0\n    tkwait visibility .t\n    .t configure  -width 180 -height 20\n    update\n    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    list [expr [lindex $property 5]] [expr [lindex $property 6]] \\\n\t    [expr [lindex $property 7]] [expr [lindex $property 8]]\n} {180 20 180 20}\ntest unixWm-44.10 {UpdateGeometryInfo procedure, menubar changing} testmenubar {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm resizable .t 0 0\n    wm geometry .t +0+0\n    tkwait visibility .t\n    .t configure -width 180 -height 50\n    frame .t.m -bd 2 -relief raised -width 100 -height 50\n    testmenubar window .t .t.m\n    update\n    .t configure -height 70\n    .t.m configure -height 30\n    list [update] [destroy .t]\n} {{} {}}\n\ntest unixWm-45.1 {UpdateSizeHints procedure, grid information} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm grid .t 6 10 10 5\n    wm minsize .t 2 4\n    wm maxsize .t 30 40\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    list [expr [lindex $property 5]] [expr [lindex $property 6]] \\\n\t    [expr [lindex $property 7]] [expr [lindex $property 8]] \\\n\t    [expr [lindex $property 9]] [expr [lindex $property 10]]\n} {40 30 320 210 10 5}\ntest unixWm-45.2 {UpdateSizeHints procedure} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    wm minsize .t 30 40\n    wm maxsize .t 200 500\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    list [expr [lindex $property 5]] [expr [lindex $property 6]] \\\n\t    [expr [lindex $property 7]] [expr [lindex $property 8]] \\\n\t    [expr [lindex $property 9]] [expr [lindex $property 10]]\n} {30 40 200 500 1 1}\ntest unixWm-45.3 {UpdateSizeHints procedure, grid with menu} {testmenubar testwrapper} {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    frame .t.menu -height 23 -width 50\n    testmenubar window .t .t.menu\n    wm grid .t 6 10 10 5\n    wm minsize .t 2 4\n    wm maxsize .t 30 40\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    list [winfo height .t] \\\n\t    [expr [lindex $property 5]] [expr [lindex $property 6]] \\\n\t    [expr [lindex $property 7]] [expr [lindex $property 8]] \\\n\t    [expr [lindex $property 9]] [expr [lindex $property 10]]\n} {60 40 53 320 233 10 5}\ntest unixWm-45.4 {UpdateSizeHints procedure, not resizable with menu} {testmenubar testwrapper} {\n    destroy .t\n    toplevel .t -width 80 -height 60\n    frame .t.menu -height 23 -width 50\n    testmenubar window .t .t.menu\n    wm resizable .t 0 0\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]\n    list [winfo height .t] \\\n\t    [expr [lindex $property 5]] [expr [lindex $property 6]] \\\n\t    [expr [lindex $property 7]] [expr [lindex $property 8]] \\\n\t    [expr [lindex $property 9]] [expr [lindex $property 10]]\n} {60 80 83 80 83 1 1}\n\n# I don't know how to test WaitForConfigureNotify.\n\ntest unixWm-46.1 {WaitForEvent procedure, use of modal timeout} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200\n    wm geom .t +0+0\n    update\n    wm iconify .t\n    set x no\n    after 0 {set x yes}\n    wm deiconify .t\n    set result $x\n    update\n    list $result $x\n} {no yes}\n\ntest unixWm-47.1 {WaitRestrictProc procedure} {unix nonPortable} {\n    destroy .t\n    toplevel .t -width 300 -height 200\n    frame .t.f -bd 2 -relief raised\n    place .t.f -x 20 -y 30 -width 100 -height 20\n    wm geometry .t +0+0\n    tkwait visibility .t\n    set result {}\n    bind .t.f <Configure> {lappend result {configure on .t.f}}\n    bind .t <Map> {lappend result {map on .t}}\n    bind .t <Unmap> {lappend result {unmap on .t}; bind .t <Unmap> {}}\n    bind .t <Button> {lappend result {button %b on .t}}\n    event generate .t.f <Configure> -when tail\n    event generate .t <Configure> -when tail\n    event generate .t <Button> -button 3 -when tail\n    event generate .t <ButtonRelease> -button 3 -when tail\n    event generate .t <Map> -when tail\n    lappend result iconify\n    wm iconify .t\n    lappend result done\n    update\n    set result\n} {iconify {unmap on .t} done {configure on .t.f} {button 3 on .t} {map on .t}}\n\n# I don't know how to test WaitTimeoutProc, WaitForMapNotify, or UpdateHints.\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ntoplevel .t -width 300 -height 200\nwm geometry .t +0+0\ntkwait visibility .t\n\ntest unixWm-48.1 {ParseGeometry procedure} unix {\n    wm geometry .t =100x120\n    update\n    list [winfo width .t] [winfo height .t]\n} {100 120}\ntest unixWm-48.2 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t =10zx120} msg] $msg\n} {1 {bad geometry specifier \"=10zx120\"}}\ntest unixWm-48.3 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t x120} msg] $msg\n} {1 {bad geometry specifier \"x120\"}}\ntest unixWm-48.4 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t =100x120a} msg] $msg\n} {1 {bad geometry specifier \"=100x120a\"}}\ntest unixWm-48.5 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t z} msg] $msg\n} {1 {bad geometry specifier \"z\"}}\ntest unixWm-48.6 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t +20&} msg] $msg\n} {1 {bad geometry specifier \"+20&\"}}\ntest unixWm-48.7 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t +-} msg] $msg\n} {1 {bad geometry specifier \"+-\"}}\ntest unixWm-48.8 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t +20a} msg] $msg\n} {1 {bad geometry specifier \"+20a\"}}\ntest unixWm-48.9 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t +20-} msg] $msg\n} {1 {bad geometry specifier \"+20-\"}}\ntest unixWm-48.10 {ParseGeometry procedure} unix {\n    list [catch {wm geometry .t +20+10z} msg] $msg\n} {1 {bad geometry specifier \"+20+10z\"}}\ntest unixWm-48.11 {ParseGeometry procedure} unix {\n    catch {wm geometry .t +-10+20}\n} 0\ntest unixWm-48.12 {ParseGeometry procedure} unix {\n    catch {wm geometry .t +30+-10}\n} 0\ntest unixWm-48.13 {ParseGeometry procedure, resize causes window to move} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200\n    wm geom .t +0+0\n    update\n    wm geom .t -0-0\n    update\n    set x [winfo x .t]\n    set y [winfo y .t]\n    wm geometry .t 150x300\n    update\n    list [expr {[winfo x .t] - $x}] [expr {[winfo y .t] - $y}] \\\n\t    [winfo width .t] [winfo height .t]\n} {50 -100 150 300}\n\ntest unixWm-49.1 {Tk_GetRootCoords procedure} unix {\n    destroy .t\n    toplevel .t -width 300 -height 200\n    frame .t.f -width 150 -height 100 -bd 2 -relief raised\n    place .t.f -x 150 -y 120\n    frame .t.f.f -width 20 -height 20 -bd 2 -relief raised\n    place .t.f.f -x 10 -y 20\n    wm overrideredirect .t 1\n    wm geometry .t +40+50\n    tkwait visibility .t\n    list [winfo rootx .t.f.f] [winfo rooty .t.f.f]\n} {202 192}\ntest unixWm-49.2 {Tk_GetRootCoords procedure, menubars} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .t.m -bd 2 -relief raised -width 100 -height 30\n    frame .t.m.f -width 20 -height 10 -bd 2 -relief raised\n    place .t.m.f -x 50 -y 5\n    frame .t.f -width 20 -height 30 -bd 2 -relief raised\n    place .t.f -x 10 -y 30\n    testmenubar window .t .t.m\n    update\n    list [expr {[winfo rootx .t.m.f] - $x}] [expr {[winfo rooty .t.m.f] - $y}] \\\n\t    [expr {[winfo rootx .t.f] - $x}] [expr {[winfo rooty .t.f] - $y}]\n} {52 7 12 62}\n\n#\n# COMMON TEST SETUP\n#\n\ndeleteWindows\n# Make sure that the root window is out of the way!\nwm geom . +700+700\nwm withdraw .\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    # Modern mac windows have no border.\n    set result_50_1 {{} {} .t .t .t2 {} .t2 .t .t}\n} else {\n    # Windows are assumed to have a border (invisible in Gnome 3).\n    set result_50_1 {{} {} .t {} .t2 {} .t2 {} .t}\n}\n\nif {[tk windowingsystem] eq \"aqua\"} {\n    after 1000; # Give Apple's _windowserver some time to catch up.\n}\n\ntest unixWm-50.1 {Tk_CoordsToWindow procedure, finding a toplevel, x-coords, title bar} {unix failsOnCILinux failsOnXQuartz} {\n    update\n    toplevel .t -width 300 -height 400 -bg green\n    wm geom .t +100+100\n    tkwait visibility .t\n    toplevel .t2 -width 100 -height 200 -bg red\n    wm geom .t2 +200+200\n    tkwait visibility .t2\n    raise .t2\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    list [winfo containing [expr {$x - 30}]  [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x - 1}]   [expr {$y + 250}]] \\\n\t [winfo containing $x              [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x + 99}]  [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x + 100}] [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x + 150}] [expr {$y + 90}]] \\\n\t [winfo containing [expr {$x + 199}] [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x + 200}] [expr {$y + 250}]] \\\n\t [winfo containing [expr {$x + 220}] [expr {$y + 250}]] \\\n} $result_50_1\ntest unixWm-50.2 {Tk_CoordsToWindow procedure, finding a toplevel, y-coords and overrideredirect} unix {\n    deleteWindows\n    toplevel .t -width 400 -height 300 -bg yellow\n    tkwait visibility .t\n    wm geom .t +100+100\n    update\n    toplevel .t2 -width 200 -height 100 -bg blue\n    wm overrideredirect .t2 1\n    tkwait visibility .t2\n    wm geom .t2 +200+200\n    update\n    raise .t2\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    set y2 [winfo rooty .t2]\n    list [winfo containing [expr {$x +200}] [expr {$y - 30}]] \\\n\t [winfo containing [expr {$x +200}] [expr {$y - 1}]] \\\n\t [winfo containing [expr {$x +200}] $y] \\\n\t [winfo containing [expr {$x +200}] [expr {$y2 - 1}]] \\\n\t [winfo containing [expr {$x +200}] $y2] \\\n\t [winfo containing [expr {$x +200}] [expr {$y2 + 99}]] \\\n\t [winfo containing [expr {$x +200}] [expr {$y2 + 100}]] \\\n\t [winfo containing [expr {$x +200}] [expr {$y + 450}]]\n} {{} {} .t .t .t2 .t2 .t {}}\ntest unixWm-50.3 {\n    Tk_CoordsToWindow procedure, finding a toplevel with embedding\n} tempNotWin {\n    deleteWindows\n    catch {interp delete child}\n    toplevel .t -width 300 -height 400 -bg blue\n    wm geom .t +100+100\n    frame .t.f -container 1 -bg red\n    place .t.f -x 150 -y 50\n    tkwait visibility .t.f\n    update\n    interp create child\n    load {} Tk child\n    child alias frameid winfo id .t.f\n    child eval {\n\twm withdraw .\n\ttoplevel .x -width 100 -height 80 -use [frameid] -bg yellow\n\ttkwait visibility .x\n\tupdate\n\tset x [winfo rootx .x]\n\tset y [winfo rooty .x]\n    }\n    set result [list [child eval {winfo containing [expr {$x - 1}]  [expr {$y + 50}]}] \\\n\t[child eval {winfo containing $x [expr {$y + 50}]}]]\n    interp delete child\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    lappend result [winfo containing [expr {$x + 200}] [expr {$y + 49}]] \\\n\t[winfo containing [expr {$x + 200}] [expr {$y +50}]]\n    set result\n} {{} .x .t .t.f}\ntest unixWm-50.4 {Tk_CoordsToWindow procedure, window in other application} unix {\n    destroy .t\n    catch {interp delete child}\n    toplevel .t -width 200 -height 200 -bg green\n    tkwait visibility .t\n    wm geometry .t +100+100\n    update\n    interp create child\n    load {} Tk child\n    child eval {wm geometry . 200x200+100+100; after 100; update}\n    set result [list [winfo containing 200 200] \\\n\t[child eval {winfo containing 200 200}]]\n    interp delete child\n    set result\n} {{} .}\ntest unixWm-50.5 {Tk_CoordsToWindow procedure, handling menubars} {unix testmenubar} {\n    deleteWindows\n    toplevel .t -width 300 -height 400 -bd 2 -relief raised\n    frame .t.f -width 150 -height 120 -bg green\n    place .t.f -x 10 -y 150\n    wm geom .t +0+50\n    frame .t.menu -width 100 -height 30 -bd 2 -relief raised\n    frame .t.menu.f -width 40 -height 20 -bg purple\n    place .t.menu.f -x 30 -y 10\n    testmenubar window .t .t.menu\n    tkwait visibility .t.menu\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    list [winfo containing $x             [expr {$y - 31}]] \\\n\t [winfo containing $x             [expr {$y - 30}]] \\\n\t [winfo containing [expr {$x + 50}] [expr {$y - 19}]] \\\n\t [winfo containing [expr {$x + 50}] [expr {$y - 18}]] \\\n\t [winfo containing [expr {$x + 50}] $y] \\\n\t [winfo containing [expr {$x + 11}] [expr {$y + 152}]] \\\n\t [winfo containing [expr {$x + 12}] [expr {$y + 152}]]\n} {{} .t.menu .t.menu .t.menu.f .t .t .t.f}\ntest unixWm-50.6 {Tk_CoordsToWindow procedure, embedding within one app.} unix {\n    deleteWindows\n    toplevel .t -width 300 -height 400 -bg orange\n    wm geom .t +0+50\n    frame .t.f -container 1\n    place .t.f -x 150 -y 50\n    tkwait visibility .t.f\n    toplevel .t2 -width 100 -height 80 -bg green -use [winfo id .t.f]\n    tkwait visibility .t2\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    list [winfo containing [expr {$x +149}] [expr {$y + 80}]] \\\n\t    [winfo containing [expr {$x +150}] [expr {$y +80}]] \\\n\t    [winfo containing [expr {$x +249}] [expr {$y +80}]] \\\n\t    [winfo containing [expr {$x +250}] [expr {$y +80}]]\n} {.t .t2 .t2 .t}\ntest unixWm-50.7 {Tk_CoordsToWindow procedure, more basics} unix {\n    destroy .t\n    toplevel .t -width 300 -height 400 -bg green\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 200 -bd 2 -relief raised\n    place .t.f -x 100 -y 100\n    frame .t.f.f -width 100 -height 200 -bd 2 -relief raised\n    place .t.f.f -x 0 -y 100\n    tkwait visibility .t.f.f\n    set x [expr {[winfo rootx .t] + 150}]\n    set y [winfo rooty .t]\n    list [winfo containing $x [expr {$y + 50}]] \\\n\t    [winfo containing $x [expr {$y + 150}]] \\\n\t    [winfo containing $x [expr {$y + 250}]] \\\n\t    [winfo containing $x [expr {$y + 350}]] \\\n\t    [winfo containing $x [expr {$y + 450}]]\n} {.t .t.f .t.f.f .t {}}\ntest unixWm-50.8 {Tk_CoordsToWindow procedure, more basics} unix {\n    destroy .t\n    toplevel .t -width 400 -height 300 -bg green\n    wm geom .t +0+30\n    frame .t.f -width 200 -height 100 -bd 2 -relief raised\n    place .t.f -x 100 -y 100\n    frame .t.f.f -width 200 -height 100 -bd 2 -relief raised\n    place .t.f.f -x 100 -y 0\n    update\n    set x [winfo rootx .t]\n    set y [expr {[winfo rooty .t] + 150}]\n    list [winfo containing [expr {$x + 50}] $y] \\\n\t    [winfo containing [expr {$x + 150}] $y] \\\n\t    [winfo containing [expr {$x + 250}] $y] \\\n\t    [winfo containing [expr {$x + 350}] $y] \\\n\t    [winfo containing [expr {$x + 450}] $y]\n} {.t .t.f .t.f.f .t {}}\ntest unixWm-50.9 {Tk_CoordsToWindow procedure, unmapped windows} {unix failsOnCILinux failsOnXQuartz} {\n    destroy .t\n    destroy .t2\n    update\n    toplevel .t -width 200 -height 200 -bg green\n    tkwait visibility .t\n    wm geometry .t +20+20\n    after 200\n    update\n    toplevel .t2 -width 200 -height 200 -bg red\n    tkwait visibility .t2\n    wm geometry .t2 +20+20\n    after 200\n    update\n    set result [list [winfo containing 120 120]]\n    destroy .t2\n    after 200\n    update\n    lappend result [winfo containing 120 120]\n} {.t2 .t}\ntest unixWm-50.10 {Tk_CoordsToWindow procedure, unmapped windows} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200 -bg green\n    wm geometry .t +0+0\n    frame .t.f -width 150 -height 150 -bd 2 -relief raised\n    place .t.f -x 25 -y 25\n    tkwait visibility .t.f\n    update idletasks\n    set result [list [winfo containing 100 100]]\n    place forget .t.f\n    update idletasks\n    lappend result [winfo containing 100 100]\n} {.t.f .t}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\nwm deiconify .\n\n# No tests for UpdateVRootGeometry, Tk_GetVRootGeometry,\n# Tk_MoveToplevelWindow, UpdateWmProtocols, or TkWmProtocolEventProc.\n\ntest unixWm-51.1 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {\n    makeToplevels\n    update\n    raise .raise1\n    winfo containing [winfo rootx .raise1] [winfo rooty .raise1]\n} .raise1\ntest unixWm-51.2 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {\n    makeToplevels\n    update\n    raise .raise2\n    winfo containing [winfo rootx .raise1] [winfo rooty .raise1]\n} .raise2\ntest unixWm-51.3 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {\n    makeToplevels\n    update\n    raise .raise3\n    raise .raise2\n    raise .raise1 .raise3\n    set result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n    destroy .raise2\n    list $result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n} {.raise2 .raise1}\ntest unixWm-51.4 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {\n    makeToplevels\n    raise .raise2\n    raise .raise1\n    lower .raise3 .raise1\n    set result [winfo containing 100 100]\n    destroy .raise1\n    lappend result [winfo containing 100 100]\n} {.raise1 .raise3}\ntest unixWm-51.5 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {\n    makeToplevels\n    update\n    raise .raise2\n    raise .raise1\n    raise .raise3\n    frame .raise1.f1\n    frame .raise1.f1.f2\n    lower .raise3 .raise1.f1.f2\n    set result [winfo containing [winfo rootx .raise1] \\\n\t    [winfo rooty .raise1]]\n    destroy .raise1\n    list $result [winfo containing [winfo rootx .raise2] \\\n\t    [winfo rooty .raise2]]\n} {.raise1 .raise3}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest unixWm-51.6 {TkWmRestackToplevel procedure, window to be stacked isn't mapped} unix {\n    wm geometry . +300+300\n    destroy .t\n    update idletasks\n    toplevel .t -width 200 -height 200 -bg green\n    tkwait visibility .t\n    wm geometry .t +0+0\n    update\n    destroy .t2\n    toplevel .t2 -width 200 -height 200 -bg red\n    # This test assumes that .t2 is not mapped yet, but that is not really guaranteed.\n    winfo containing 100 100\n} {.t}\ntest unixWm-51.7 {TkWmRestackToplevel procedure, other window isn't mapped} {unix failsOnXQuartz} {\n    foreach w {.t .t2 .t3} {\n\tdestroy $w\n\ttoplevel $w -width 200 -height 200 -bg green\n\ttkwait visibility $w\n\twm geometry $w +100+100\n\tafter 200\n\tupdate\n    }\n    update\n    raise .t .t2\n    update\n    set result [list [winfo containing 200 200]]\n    lower .t3\n    update\n    lappend result [winfo containing 200 200]\n} {.t3 .t}\ntest unixWm-51.8 {TkWmRestackToplevel procedure, overrideredirect windows} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200 -bg green\n    wm overrideredirect .t 1\n    wm geometry .t +0+0\n    tkwait visibility .t\n    destroy .t2\n    toplevel .t2 -width 200 -height 200 -bg red\n    wm overrideredirect .t2 1\n    wm geometry .t2 +0+0\n    tkwait visibility .t2\n\n    # Need to use vrootx and vrooty to make tests work correctly with\n    # virtual root window measures managers: overrideredirect windows\n    # come up at (0,0) in display coordinates, not virtual root\n    # coordinates.\n\n    set x [expr {100-[winfo vrootx .]}]\n    set y [expr {100-[winfo vrooty .]}]\n    set result [list [winfo containing $x $y]]\n    raise .t\n    lappend result [winfo containing $x $y]\n    raise .t2\n    lappend result [winfo containing $x $y]\n} {.t2 .t .t2}\n\ntest unixWm-51.9 {TkWmRestackToplevel procedure, other window overrideredirect} -constraints unix -setup {\n    # The mac won't put an overrideredirect window above the root,\n    if {[tk windowingsystem] eq \"aqua\"} {\n\twm withdraw .\n\tupdate\n    }\n} -body {\n    foreach w {.t .t2 .t3} {\n\tdestroy $w\n\tupdate\n\ttoplevel $w -width 200 -height 200 -bg green\n\twm overrideredirect $w 1\n\ttkwait visibility $w\n\twm geometry $w +0+0\n\tupdate\n    }\n    lower .t3 .t2\n    update\n\n    # Need to use vrootx and vrooty to make tests work correctly with\n    # virtual root window measures managers: overrideredirect windows\n    # come up at (0,0) in display coordinates, not virtual root\n    # coordinates.\n\n    set x [expr {100-[winfo vrootx .]}]\n    set y [expr {100-[winfo vrooty .]}]\n    set result [list [winfo containing $x $y]]\n    lower .t2\n    update\n    lappend result [winfo containing $x $y]\n} -cleanup {\n    if {[tk windowingsystem] eq \"aqua\"} {\n\twm deiconify .\n\tupdate\n    }\n} -result {.t2 .t3}\ntest unixWm-51.10 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix {\n    makeToplevels\n    raise .raise1\n    set time [lindex [time {raise .raise1}] 0]\n    expr {$time < 2000000}\n} 1\ntest unixWm-51.11 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix {\n    makeToplevels\n    set time [lindex [time {lower .raise1}] 0]\n    expr {$time < 2000000}\n} 1\ntest unixWm-51.12 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix {\n    makeToplevels\n    set time [lindex [time {raise .raise3 .raise2}] 0]\n    expr {$time < 2000000}\n} 1\ntest unixWm-51.13 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix {\n    makeToplevels\n    set time [lindex [time {lower .raise1 .raise2}] 0]\n    expr {$time < 2000000}\n} 1\n\ntest unixWm-52.1 {TkWmAddToColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -width 200 -height 200 -colormap new -relief raised -bd 2\n    wm geom .t +0+0\n    update\n    wm colormap .t\n} {}\ntest unixWm-52.2 {TkWmAddToColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -colormap new -relief raised -bd 2\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f\n    update\n    wm colormap .t\n} {.t.f .t}\ntest unixWm-52.3 {TkWmAddToColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -colormap new\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f\n    frame .t.f2 -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f2\n    update\n    wm colormap .t\n} {.t.f .t.f2 .t}\ntest unixWm-52.4 {TkWmAddToColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -colormap new\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f\n    update\n    wm colormapwindows .t .t.f\n    frame .t.f2 -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f2\n    update\n    wm colormapwindows .t\n} {.t.f}\n\ntest unixWm-53.1 {TkWmRemoveFromColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -colormap new\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f\n    frame .t.f2 -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f2\n    update\n    destroy .t.f2\n    wm colormap .t\n} {.t.f .t}\ntest unixWm-53.2 {TkWmRemoveFromColormapWindows procedure} unix {\n    destroy .t\n    toplevel .t -colormap new\n    wm geom .t +0+0\n    frame .t.f -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f\n    frame .t.f2 -width 100 -height 100 -colormap new -relief sunken -bd 2\n    pack .t.f2\n    update\n    wm colormapwindows .t .t.f2\n    destroy .t.f2\n    wm colormap .t\n} {}\n\ntest unixWm-54.1 {TkpMakeMenuWindow procedure, setting save_under} {unix nonUnixUserInteraction} {\n    destroy .t\n    destroy .m\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    bind .t <Expose> {set x exposed}\n    wm geom .t +0+0\n    update\n    menu .m\n    .m add command -label First\n    .m add command -label Second\n    .m add command -label Third\n    .m post 30 30\n    update\n    set x {no event}\n    destroy .m\n    set x\n} {no event}\ntest unixWm-54.2 {TkpMakeMenuWindow procedure, setting override_redirect} {unix nonUnixUserInteraction} {\n    destroy .m\n    menu .m\n    .m add command -label First\n    .m add command -label Second\n    .m add command -label Third\n    .m post 30 30\n    update\n    set result [wm overrideredirect .m]\n    destroy .m\n    set result\n} 1\n\n# No tests for TkGetPointerCoords, CreateWrapper, or GetMaxSize.\n\ntest unixWm-55.1 {TkUnixSetMenubar procedure} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    list [winfo ismapped .t.f] [winfo geometry .t.f] \\\n\t    [expr {[winfo rootx .t] - [winfo rootx .t.f]}] \\\n\t    [expr {[winfo rooty .t] - [winfo rooty .t.f]}]\n} {1 300x30+0+0 0 30}\ntest unixWm-55.2 {TkUnixSetMenubar procedure, removing menubar} {unix testmenubar} {\n    destroy .t\n    destroy .f\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .f\n    update\n    testmenubar window .t {}\n    update\n    list [winfo ismapped .f] [winfo geometry .f] \\\n\t    [expr {[winfo rootx .t] - $x}] \\\n\t    [expr {[winfo rooty .t] - $y}] \\\n\t    [expr {[winfo rootx .] - [winfo rootx .f]}] \\\n\t    [expr {[winfo rooty .] - [winfo rooty .f]}]\n} {0 300x30+0+0 0 0 0 0}\ntest unixWm-55.3 {TkUnixSetMenubar procedure, removing geometry manager} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    testmenubar window .t {}\n    update\n    set result \"[expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\"\n    .t.f configure -height 100\n    update\n    lappend result [expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\n} {0 0 0 0}\ntest unixWm-55.4 {TkUnixSetMenubar procedure, toplevel not yet created} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    wm geom .t +0+0\n    update\n    list [winfo ismapped .t.f] [winfo geometry .t.f] \\\n\t    [expr {[winfo rootx .t] - [winfo rootx .t.f]}] \\\n\t    [expr {[winfo rooty .t] - [winfo rooty .t.f]}]\n} {1 300x30+0+0 0 30}\ntest unixWm-55.5 {TkUnixSetMenubar procedure, changing menubar} {unix testmenubar} {\n    destroy .t\n    destroy .f\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    wm geom .t +0+0\n    update\n    set y [winfo rooty .t]\n    frame .f -width 400 -height 50 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    set result {}\n    lappend result [winfo ismapped .f] [winfo ismapped .t.f]\n    lappend result [expr {[winfo rooty .t.f] - $y}]\n    testmenubar window .t .f\n    update\n    lappend result [winfo ismapped .f] [winfo ismapped .t.f]\n    lappend result [expr {[winfo rooty .f] - $y}]\n} {0 1 0 1 0 0}\ntest unixWm-55.6 {TkUnixSetMenubar procedure, changing menubar to self} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    wm geom .t +0+0\n    update\n    testmenubar window .t .t.f\n    update\n    list [winfo ismapped .t.f] [winfo geometry .t.f] \\\n\t    [expr {[winfo rootx .t] - [winfo rootx .t.f]}] \\\n\t    [expr {[winfo rooty .t] - [winfo rooty .t.f]}]\n} {1 300x30+0+0 0 30}\ntest unixWm-55.7 {TkUnixSetMenubar procedure, unsetting event handler} {unix testmenubar} {\n    destroy .t\n    destroy .f\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    frame .f -width 400 -height 40 -bd 2 -relief raised -bg blue\n    wm geom .t +0+0\n    update\n    set y [winfo rooty .t]\n    testmenubar window .t .t.f\n    update\n    set result [expr {[winfo rooty .t] - $y}]\n    testmenubar window .t .f\n    update\n    lappend result [expr {[winfo rooty .t] - $y}]\n    destroy .t.f\n    update\n    lappend result [expr {[winfo rooty .t] - $y}]\n} {30 40 40}\n\ntest unixWm-56.1 {MenubarDestroyProc procedure} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set y [winfo rooty .t]\n    frame .t.f -width 400 -height 30 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    set result [expr {[winfo rooty .t] - $y}]\n    destroy .t.f\n    update\n    lappend result [expr {[winfo rooty .t] - $y}]\n} {30 0}\n\ntest unixWm-57.1 {MenubarReqProc procedure} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .t.f -width 400 -height 10 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    set result \"[expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\"\n    .t.f configure -height 100\n    update\n    lappend result [expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\n} {0 10 0 100}\ntest unixWm-57.2 {MenubarReqProc procedure} {unix testmenubar} {\n    destroy .t\n    toplevel .t -width 300 -height 200 -bd 2 -relief raised\n    wm geom .t +0+0\n    update\n    set x [winfo rootx .t]\n    set y [winfo rooty .t]\n    frame .t.f -width 400 -height 20 -bd 2 -relief raised -bg green\n    testmenubar window .t .t.f\n    update\n    set result \"[expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\"\n    .t.f configure -height 0\n    update\n    lappend result [expr {[winfo rootx .t] - $x}] [expr {[winfo rooty .t] - $y}]\n} {0 20 0 1}\n\ntest unixWm-58.1 {UpdateCommand procedure, DString gets reallocated} {unix testwrapper} {\n    destroy .t\n    toplevel .t -width 100 -height 50\n    wm geom .t +0+0\n    wm command .t \"argumentNumber0 argumentNumber1 argumentNumber2 argumentNumber0 argumentNumber3 argumentNumber4 argumentNumber5 argumentNumber6 argumentNumber0 argumentNumber7 argumentNumber8 argumentNumber9 argumentNumber10 argumentNumber0 argumentNumber11 argumentNumber12 argumentNumber13 argumentNumber14 argumentNumber15 argumentNumber16 argumentNumber17 argumentNumber18\"\n    update\n    testprop [testwrapper .t] WM_COMMAND\n} {argumentNumber0\nargumentNumber1\nargumentNumber2\nargumentNumber0\nargumentNumber3\nargumentNumber4\nargumentNumber5\nargumentNumber6\nargumentNumber0\nargumentNumber7\nargumentNumber8\nargumentNumber9\nargumentNumber10\nargumentNumber0\nargumentNumber11\nargumentNumber12\nargumentNumber13\nargumentNumber14\nargumentNumber15\nargumentNumber16\nargumentNumber17\nargumentNumber18\n}\n\n# Test exit processing and cleanup:\n\ntest unixWm-59.1 {exit processing} unix {\n    set script [makeFile {\n\tupdate\n\texit\n    } script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} {0 {}}\ntest unixWm-59.2 {exit processing} unix {\n    set code [loadTkCommand]\n    append code  {\n\tinterp create x\n\tx eval {set argc 2}\n\tx eval {set argv \"-geometry 10x10+0+0\"}\n\tx eval {load {} Tk}\n\tupdate\n\texit\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} {0 {}}\ntest unixWm-59.3 {exit processing} unix {\n    set code [loadTkCommand]\n    append code  {\n\tinterp create x\n\tx eval {set argc 2}\n\tx eval {set argv \"-geometry 10x10+0+0\"}\n\tx eval {load {} Tk}\n\tx eval {\n\t    button .b -text hello\n\t    bind .b <Destroy> foo\n\t}\n\tx alias foo destroy_x\n\tproc destroy_x {} {interp delete x}\n\tupdate\n\texit\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} {0 {}}\n\n#\n# wm attributes tests:\n#\n# NOTE: since [wm attributes] is not guaranteed to have any effect,\n# the only thing we can really test here is the syntax.\n#\ntest unixWm-60.1.1 {wm attributes - test} -constraints {unix notAqua} -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t\n} -match exact -result {-alpha 1.0 -fullscreen 0 -topmost 0 -type {} -zoomed 0}\n\ntest unixWm-60.1.2 {wm attributes - test} -constraints {unix aqua} -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t\n} -match glob -result {-alpha 1.0 -appearance auto -buttons {close miniaturize zoom} -fullscreen 0 -isdark [01] -modified 0 -notify 0 -titlepath {} -topmost 0 -transparent 0 -stylemask {titled closable miniaturizable resizable} -class nswindow -tabbingid .t -tabbingmode auto -type unsupported}\n\ntest unixWm-60.2 {wm attributes - test} -constraints unix -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t -topmost\n} -result 0\n\ntest unixWm-60.3 {wm attributes - set (unrealized)} -constraints unix -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t -topmost 1\n}\n\ntest unixWm-60.4 {wm attributes - set (realized)} -constraints unix -body {\n    destroy .t\n    toplevel .t\n    tkwait visibility .t\n    wm attributes .t -topmost 1\n}\n\ntest unixWm-60.5 {wm attributes - bad attribute} -constraints unix -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t -foo\n} -returnCodes 1 -match glob -result {bad attribute \"-foo\":*}\n\ntest unixWm-61.1 {Tk_WmCmd procedure, \"iconphoto\" option} unix {\n    list [catch {wm iconph .} msg] $msg\n} {1 {wrong # args: should be \"wm iconphoto window ?-default? image1 ?image2 ...?\"}}\ntest unixWm-61.2 {Tk_WmCmd procedure, \"iconphoto\" option} unix {\n    destroy .t\n    toplevel .t\n    image create photo blank16 -width 16 -height 16\n    image create photo blank32 -width 32 -height 32\n    # This should just make blank icons for the window\n    wm iconphoto .t blank16 blank32\n    image delete blank16 blank32\n} {}\n\ntest unixWm-62.0 {wm attributes -type void} -constraints unix -setup {\n    destroy .t\n    toplevel .t\n} -body {\n    wm attributes .t -type {}\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest unixWm-62.1 {wm attributes -type name} -constraints unix -setup {\n    destroy .t\n    toplevel .t\n} -body {\n    wm attributes .t -type dialog\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest unixWm-62.2 {wm attributes -type name} -constraints unix -setup {\n    destroy .t\n    toplevel .t\n} -body {\n    tkwait visibility .t\n    wm attributes .t -type dialog\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest unixWm-62.3 {wm attributes -type list} -constraints unix -setup {\n    destroy .t\n    toplevel .t\n} -body {\n    wm attributes .t -type {xyzzy dialog}\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest unixWm-62.4 {wm attributes -type list} -constraints unix -setup {\n    destroy .t\n    toplevel .t\n} -body {\n    tkwait visibility .t\n    wm attributes .t -type {xyzzy dialog}\n} -cleanup {\n    destroy .t\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .t\ncleanupTests\n"
  },
  {
    "path": "tests/util.test",
    "content": "# This file is a Tcl script to test out the procedures in the file\n# tkUtil.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\nlistbox .l -width 20 -height 5 -relief sunken -bd 2\npack .l\n.l insert 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\nupdate\n\n#\n# TESTS\n#\n\ntest util-1.1 {Tk_GetScrollInfo procedure} -body {\n    .l yview moveto a b\n} -returnCodes error -result {wrong # args: should be \".l yview moveto fraction\"}\ntest util-1.2 {Tk_GetScrollInfo procedure} -body {\n    .l yview moveto xyz\n} -returnCodes error -result {expected floating-point number but got \"xyz\"}\ntest util-1.3 {Tk_GetScrollInfo procedure} -body {\n    .l yview 0\n    .l yview moveto .5\n    .l yview\n} -result {0.5 0.75}\ntest util-1.4 {Tk_GetScrollInfo procedure} -body {\n    .l yview scroll a\n} -returnCodes error -result {wrong # args: should be \".l yview scroll number pages|units\"}\ntest util-1.5 {Tk_GetScrollInfo procedure} -body {\n    .l yview scroll a b c\n} -returnCodes error -result {wrong # args: should be \".l yview scroll number pages|units\"}\ntest util-1.6 {Tk_GetScrollInfo procedure} -body {\n    .l yview scroll xyz units\n} -returnCodes error -result {expected floating-point number but got \"xyz\"}\ntest util-1.7 {Tk_GetScrollInfo procedure} -body {\n    .l yview 0\n    .l yview scroll 2 pages\n    .l nearest 0\n} -result 6\ntest util-1.8 {Tk_GetScrollInfo procedure} -body {\n    .l yview 15\n    .l yview scroll -2 pages\n    .l nearest 0\n} -result 9\ntest util-1.9 {Tk_GetScrollInfo procedure} -body {\n    .l yview 0\n    .l yview scroll 2 units\n    .l nearest 0\n} -result 2\ntest util-1.10 {Tk_GetScrollInfo procedure} -body {\n    .l yview 15\n    .l yview scroll -2 units\n    .l nearest 0\n} -result 13\ntest util-1.11 {Tk_GetScrollInfo procedure} -body {\n    .l yview scroll 3 zips\n} -returnCodes error -result {bad argument \"zips\": must be pages or units}\ntest util-1.12 {Tk_GetScrollInfo procedure} -body {\n    .l yview dropdead 3 times\n} -returnCodes error -result {unknown option \"dropdead\": must be moveto or scroll}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n"
  },
  {
    "path": "tests/visual.test",
    "content": "# This file is a Tcl script to test the visual- and colormap-handling\n# procedures in the file tkVisual.c.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import colors\n\n#\n# COMMON TEST SETUP\n#\n\nupdate\n\n# If more than one visual type is available for the screen, pick one\n# that is *not* the default.\n\nset default \"[winfo visual .] [winfo depth .]\"\nset avail [winfo visualsavailable .]\nset other {}\nset 32bitsVisual {}\nif {[llength $avail] > 1} {\n    foreach visual $avail {\n\tif {$visual ne $default} {\n\t    set other $visual\n\t    break\n\t}\n    }\n    foreach visual $avail {\n\tif {[lindex $visual 1] == 32} {\n\t    set 32bitsVisual $visual\n\t    break\n\t}\n    }\n}\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint haveOtherVisual [expr {$other ne \"\"}]\ntestConstraint havePseudocolorVisual [string match *pseudocolor* $avail]\ntestConstraint haveMultipleVisuals [expr {[llength $avail] > 1}]\ntestConstraint haveDefault24bitsVisual [expr {[winfo depth .] == 24}]\ntestConstraint have32bitsVisual [expr {$32bitsVisual ne \"\"}]\n\n#\n# TESTS\n#\n\ntest visual-1.1 {Tk_GetVisual, copying from other window} -body {\n    toplevel .t -visual .foo.bar\n} -returnCodes error -result {bad window path name \".foo.bar\"}\ntest visual-1.2 {Tk_GetVisual, copying from other window} -constraints {\n    haveOtherVisual nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual $other\n    wm geom .t1 +0+0\n    toplevel .t2 -width 200 -height 80 -visual .t1\n    wm geom .t2 +5+5\n    concat \"[winfo visual .t2] [winfo depth .t2]\"\n} -cleanup {\n    deleteWindows\n} -result $other\ntest visual-1.3 {Tk_GetVisual, copying from other window} -constraints {\n    haveOtherVisual\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual $other\n    wm geom .t1 +0+0\n    toplevel .t2 -width 200 -height 80 -visual .\n    wm geom .t2 +5+5\n    concat \"[winfo visual .t2] [winfo depth .t2]\"\n} -cleanup {\n    deleteWindows\n} -result $default\n# Make sure reference count is incremented when copying visual (the\n# following test will cause the colormap to be freed prematurely if\n# the reference count isn't incremented).\ntest visual-1.4 {Tk_GetVisual, colormap reference count} -constraints {\n    haveOtherVisual\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual $other\n    wm geom .t1 +0+0\n    set result [toplevel .t2 -gorp 80 -visual .t1]\n    update\n    return $result\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown option \"-gorp\"}\ntest visual-1.5 {Tk_GetVisual, default colormap} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual default\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result $default\n\n\ntest visual-2.1 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.2 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.3 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.4 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.5 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.6 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.7 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.8 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 24}\ntest visual-2.9 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.10 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.11 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.12 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.13 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.14 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.15 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.16 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {directcolor 24}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {directcolor 24}\ntest visual-2.17 {Tk_GetVisual, different visual types} -constraints {\n    nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual {truecolor 32}\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result {truecolor 32}\n\n\ntest visual-3.1 {Tk_GetVisual, parsing visual string} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 \\\n\t-visual \"[winfo visual .][winfo depth .]\"\n    wm geometry .t1 +0+0\n    update\n    concat \"[winfo visual .t1] [winfo depth .t1]\"\n} -cleanup {\n    deleteWindows\n} -result $default\ntest visual-3.2 {Tk_GetVisual, parsing visual string} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual goop20\n    wm geometry .t1 +0+0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown or ambiguous visual name \"goop20\": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}\ntest visual-3.3 {Tk_GetVisual, parsing visual string} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual d\n    wm geometry .t1 +0+0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown or ambiguous visual name \"d\": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}\ntest visual-3.4 {Tk_GetVisual, parsing visual string} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual static\n    wm geometry .t1 +0+0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {unknown or ambiguous visual name \"static\": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}\ntest visual-3.5 {Tk_GetVisual, parsing visual string} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual \"pseudocolor 48x\"\n    wm geometry .t1 +0+0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {expected integer but got \"48x\"}\n\n\ntest visual-4.1 {Tk_GetVisual, numerical visual id}  -constraints {\n    haveOtherVisual nonPortable\n} -setup {\n    deleteWindows\n    toplevel .t1 -width 250 -height 100 -visual $other\n    wm geom .t1 +0+0\n    toplevel .t2 -width 200 -height 80 -visual [winfo visual .]\n    wm geom .t2 +5+5\n    toplevel .t3 -width 150 -height 250 -visual [winfo visual .t1]\n    wm geom .t3 +10+10\n} -body {\n    set v1 [list [winfo visualid .t2] [winfo visualid .t3]]\n    set v2 [list [winfo visualid .] [winfo visualid .t1]]\n    expr {$v1 eq $v2 ? \"OK\" : \"[list $v1] ne [list $v2]\"}\n} -cleanup {\n    deleteWindows\n} -result OK\ntest visual-4.2 {Tk_GetVisual, numerical visual id} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -visual 12xyz\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad X identifier for visual: \"12xyz\"}\ntest visual-4.3 {Tk_GetVisual, numerical visual id} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -visual 1291673\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {couldn't find an appropriate visual}\n\n\ntest visual-5.1 {Tk_GetVisual, no matching visual} -constraints {\n    !havePseudocolorVisual\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual \"pseudocolor 8\"\n    wm geometry .t1 +0+0\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {couldn't find an appropriate visual}\n\n\ntest visual-6.1 {Tk_GetVisual, no matching visual} -constraints {\n    havePseudocolorVisual haveMultipleVisuals nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 250 -height 100 -visual \"best\"\n    wm geometry .t1 +0+0\n    update\n    winfo visual .t1\n} -cleanup {\n    deleteWindows\n} -result {pseudocolor}\n\n\n# These tests are non-portable due to variations in how many colors\n# are already in use on the screen.\ntest visual-7.1 {Tk_GetColormap, \"new\"} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    eatColors .t1\n    toplevel .t2 -width 30 -height 20\n    wm geom .t2 +0+0\n    update\n    colorsFree .t2\n} -cleanup {\n    deleteWindows\n} -result 0\ntest visual-7.2 {Tk_GetColormap, \"new\"} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    eatColors .t1\n    toplevel .t2 -width 30 -height 20 -colormap new\n    wm geom .t2 +0+0\n    update\n    colorsFree .t2\n} -cleanup {\n    deleteWindows\n} -result 1\ntest visual-7.3 {Tk_GetColormap, copy from other window} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    eatColors .t1\n    toplevel .t3 -width 400 -height 50 -colormap new\n    wm geom .t3 +0+0\n    toplevel .t2 -width 30 -height 20 -colormap .t3\n    wm geom .t2 +0+0\n    update\n    destroy .t3\n    colorsFree .t2\n} -cleanup {\n    deleteWindows\n} -result 1\ntest visual-7.4 {Tk_GetColormap, copy from other window} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    eatColors .t1\n    toplevel .t3 -width 400 -height 50 -colormap new\n    wm geom .t3 +0+0\n    toplevel .t2 -width 30 -height 20 -colormap .\n    wm geom .t2 +0+0\n    update\n    destroy .t3\n    colorsFree .t2\n} -cleanup {\n    deleteWindows\n} -result 0\ntest visual-7.5 {Tk_GetColormap, copy from other window} -constraints {\n    defaultPseudocolor8 nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 400 -height 50 -colormap .choke.lots\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {bad window path name \".choke.lots\"}\ntest visual-7.6 {Tk_GetColormap, copy from other window} -constraints {\n    defaultPseudocolor8 haveOtherVisual nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 300 -height 150 -visual $other\n    wm geometry .t1 +0+0\n    toplevel .t2 -width 400 -height 50 -colormap .t1\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result {can't use colormap for .t1: incompatible visuals}\n\n\ntest visual-8.1 {Tk_FreeColormap procedure} -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 300 -height 180 -colormap new\n    wm geometry .t1 +0+0\n    foreach i {.t2 .t3 .t4} {\n\ttoplevel $i -width 250 -height 150 -colormap .t1\n\twm geometry $i +0+0\n    }\n    destroy .t1\n    destroy .t3\n    destroy .t4\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\ntest visual-8.2 {Tk_FreeColormap procedure} -constraints haveOtherVisual -setup {\n    deleteWindows\n} -body {\n    toplevel .t1 -width 300 -height 180 -visual $other\n    wm geometry .t1 +0+0\n    foreach i {.t2 .t3 .t4} {\n\ttoplevel $i -width 250 -height 150 -visual $other\n\twm geometry $i +0+0\n    }\n    destroy .t2\n    destroy .t3\n    destroy .t4\n    update\n} -cleanup {\n    deleteWindows\n} -result {}\n\n\ntest visual-9.1 {Using two different visuals on the same screen - bug c23f79ef96} -constraints {\n    haveDefault24bitsVisual have32bitsVisual\n} -setup {\n    deleteWindows\n} -body {\n    set res [winfo depth .]\n    toplevel .t -visual $32bitsVisual\n    pack [label .t.l -text \"Any text\"]  ; # Shall not crash (\"X Error of failed request:  BadValue [...]\")\n    update\n    lappend res [winfo depth .t]\n} -cleanup {\n    deleteWindows\n} -result {24 32}\n\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ntestutils forget colors\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/visual_bb.test",
    "content": "# This script displays provides visual tests for many of Tk's features.\n# Each test displays a window with various information in it, along\n# with instructions about how the window should appear.  You can look\n# at the window to make sure it appears as expected.  Individual tests\n# are kept in separate \".tcl\" files in this directory.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\nset testNum 1\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc end {} {\n    cleanupTests\n    set ::EndOfVisualTests 1\n}\n\n# lpr --\n#\n#\tPrint the contents of a canvas\n#\nproc lpr {c args} {\n    exec lpr <<[eval [list $c postscript] $args]\n}\n\nproc runTest {file} {\n    global testNum\n\n    test \"2.$testNum\" \"testing $file\" {userInteraction} {\n    uplevel #0 [list source [file join [testsDirectory] $file]]\n    concat \"\"\n    } {}\n    incr testNum\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset auto_path \". $auto_path\"\nwm title . \"Visual Tests for Tk\"\n\n#\n# TESTS\n#\n\n# Each menu entry invokes a visual test file\n\ntest 1.1 {running visual tests} -constraints userInteraction -body {\n    #-------------------------------------------------------\n    # The code below create the main window, consisting of a\n    # menu bar and a message explaining the basic operation\n    # of the program.\n    #-------------------------------------------------------\n\n    frame .menu -relief raised -borderwidth 1\n    message .msg -font {Times 18} -relief raised -width 4i \\\n\t-borderwidth 1 -text \"This application provides a collection of visual tests for the Tk toolkit.  Each menu entry invokes a test, which displays information on the screen.  You can then verify visually that the information is being displayed in the correct way.  The tests under the \\\"Postscript\\\" menu exercise the Postscript-generation capabilities of canvas widgets.\"\n\n    pack .menu -side top -fill x\n    pack .msg -side bottom -expand yes -fill both\n\n    #-------------------------------------------------------\n    # The code below creates all the menus, which invoke procedures\n    # to create particular demonstrations of various widgets.\n    #-------------------------------------------------------\n\n    menubutton .menu.file -text \"File\" -menu .menu.file.m\n    menu .menu.file.m\n    .menu.file.m add command -label \"Quit\" -command end\n\n    menubutton .menu.group1 -text \"Group 1\" -menu .menu.group1.m\n    menu .menu.group1.m\n    .menu.group1.m add command -label \"Canvas arcs\" -command {runTest arc.tcl}\n    .menu.group1.m add command -label \"Beveled borders in text widgets\" \\\n\t-command {runTest bevel.tcl}\n    .menu.group1.m add command -label \"Colormap management\" \\\n\t-command {runTest cmap.tcl}\n    .menu.group1.m add command -label \"Label/button geometry\" \\\n\t-command {runTest butGeom.tcl}\n    .menu.group1.m add command -label \"Label/button colors\" \\\n\t-command {runTest butGeom2.tcl}\n\n    menubutton .menu.ps -text \"Canvas Postscript\" -menu .menu.ps.m\n    menu .menu.ps.m\n    .menu.ps.m add command -label \"Rectangles and other graphics\" \\\n\t-command {runTest canvPsGrph.tcl}\n    .menu.ps.m add command -label \"Text\" \\\n\t-command {runTest canvPsText.tcl}\n    .menu.ps.m add command -label \"Bitmaps\" \\\n\t-command {runTest canvPsBmap.tcl}\n    .menu.ps.m add command -label \"Images\" \\\n\t-command {runTest canvPsImg.tcl}\n    .menu.ps.m add command -label \"Arcs\" \\\n\t-command {runTest canvPsArc.tcl}\n\n    pack .menu.file .menu.group1 .menu.ps -side left -padx 1m\n\n    # Set up for keyboard-based menu traversal\n\n    bind . <FocusIn> {\n    if {(\"%d\" eq \"NotifyVirtual\") && (\"%m\" eq \"NotifyNormal\")} {\n\tfocus .menu\n    }\n    }\n    tk_menuBar .menu .menu.file .menu.group1 .menu.ps\n\n    # Set up a class binding to allow objects to be deleted from a canvas\n    # by clicking with mouse button 1:\n\n    bind Canvas <Button-1> {%W delete [%W find closest %x %y]}\n\n    concat \"\"\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\nif {![testConstraint userInteraction]} {\n    cleanupTests\n} else {\n    vwait EndOfVisualTests\n}\n"
  },
  {
    "path": "tests/winButton.test",
    "content": "# This file is a Tcl script to test the Windows specific behavior of\n# labels, buttons, checkbuttons, and radiobuttons in Tk (i.e., all the\n# widgets defined in tkWinButton.c).\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests regarding\n#   buttons that are specific to the unix platform (this includes macOS)\n#   go into the test file unixButton.test. Tests that are platform-indifferent go\n#   into test file button.test. Or they may exists as each other's counterparts in\n#   both unixButton.test and winButton.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import button image\n\nimageInit\n\noption clear\n\n#\n# TESTS\n#\n\ntest winbutton-1.1 {TkpComputeButtonGeometry procedure} -constraints {\n    testImageType win nonPortable\n} -setup {\n    # nonPortable because of [3e3e25f483]: on Win7 first started with a high DPI screen\n    # the smallest size (i.e. 8) is not available for \"MS Sans Serif\" font\n    deleteWindows\n} -body {\n    image create test image1\n    image1 changed 0 0 0 0 60 40\n    label .b1 -image image1 -bd 4 -padx 0 -pady 2\n    button .b2 -image image1 -bd 4 -padx 0 -pady 2\n    checkbutton .b3 -image image1 -bd 4 -padx 1 -pady 1 \\\n\t-font {{MS Sans Serif} 8}\n    radiobutton .b4 -image image1 -bd 4 -padx 2 -pady 0 \\\n\t-font {{MS Sans Serif} 8}\n    pack .b1 .b2 .b3 .b4\n    update\n    # with patch 463234 with native L&F enabled, this returns:\n    # {68 48 70 50 88 50 88 50}\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n    image delete image1\n} -result {68 48 70 50 90 52 90 52}\n\ntest winbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    # nonPortable because of [3e3e25f483]: on Win7 first started with a high DPI screen\n    # the smallest size (i.e. 8) is not available for \"MS Sans Serif\" font\n    deleteWindows\n} -body {\n    label .b1 -bitmap question -bd 3 -padx 0 -pady 2\n    button .b2 -bitmap question -bd 3 -padx 0 -pady 2\n    checkbutton .b3 -bitmap question -bd 3 -padx 1 -pady 1 \\\n\t-font {{MS Sans Serif} 8}\n    radiobutton .b4 -bitmap question -bd 3 -padx 2 -pady 0 \\\n\t-font {{MS Sans Serif} 8}\n    pack .b1 .b2 .b3 .b4\n    update\n    # with patch 463234 with native L&F enabled, this returns:\n    # {23 33 25 35 43 35 43 35}\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {23 33 25 35 45 37 45 37}\n\ntest winbutton-1.3 {TkpComputeButtonGeometry procedure} -constraints win -setup {\n    deleteWindows\n} -body {\n    label .b1 -bitmap question -bd 3 -highlightthickness 4\n    button .b2 -bitmap question -bd 3 -highlightthickness 0\n    checkbutton .b3 -bitmap question -bd 3 -highlightthickness 1 \\\n\t-indicatoron 0\n    radiobutton .b4 -bitmap question -bd 3 -indicatoron false\n    pack .b1 .b2 .b3 .b4\n    update\n    # with patch 463234 with native L&F enabled, this returns:\n    # {31 41 23 33 25 35 25 35}\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {31 41 23 33 27 37 27 37}\n\ntest winbutton-1.4 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -bd 2 -padx 0 -pady 2 -font {{MS Sans Serif} 8}\n    button .b2 -text Xagqpim -bd 2 -padx 0 -pady 2 -font {{MS Sans Serif} 8}\n    checkbutton .b3 -text Xagqpim -bd 2 -padx 1 -pady 1 -font {{MS Sans Serif} 8}\n    radiobutton .b4 -text Xagqpim -bd 2 -padx 2 -pady 0 -font {{MS Sans Serif} 8}\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {58 24 67 33 88 30 90 28}\n\ntest winbutton-1.5 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    label .l1 -wraplength 1.5i -padx 0 -pady 0 \\\n\t-text \"This is a long string that will wrap around on several lines.\\n\\nIt also has a blank line (above).\"\n    pack .l1\n    update\n    list [winfo reqwidth .l1] [winfo reqheight .l1]\n} -cleanup {\n    deleteWindows\n} -result {178 84}\n\ntest winbutton-1.6 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    label .l1 -padx 0 -pady 0 \\\n\t-text \"This is a long string without wrapping.\\n\\nIt also has a blank line (above).\"\n    pack .l1\n    update\n    list [winfo reqwidth .l1] [winfo reqheight .l1]\n} -cleanup {\n    deleteWindows\n} -result {222 52}\n\ntest winbutton-1.7 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -bd 2 -padx 0 -pady 2 -width 10\n    button .b2 -text Xagqpim -bd 2 -padx 0 -pady 2 -height 5\n    checkbutton .b3 -text Xagqpim -bd 2 -padx 1 -pady 1 -width 20 -height 2\n    radiobutton .b4 -text Xagqpim -bd 2 -padx 2 -pady 0 -width 4\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {74 24 67 97 174 46 64 28}\n\ntest winbutton-1.8 {TkpComputeButtonGeometry procedure} -constraints {\n    win nonPortable\n} -setup {\n    deleteWindows\n} -body {\n    label .b1 -text Xagqpim -bd 2 -padx 0 -pady 2 \\\n    -highlightthickness 4\n    button .b2 -text Xagqpim -bd 2 -padx 0 -pady 2 \\\n    -highlightthickness 0\n    checkbutton .b3 -text Xagqpim -bd 2 -padx 1 -pady 1  \\\n    -highlightthickness 1 -indicatoron no\n    radiobutton .b4 -text Xagqpim -bd 2 -padx 2 -pady 0 -indicatoron 0\n    pack .b1 .b2 .b3 .b4\n    update\n    list [winfo reqwidth .b1] [winfo reqheight .b1] \\\n\t[winfo reqwidth .b2] [winfo reqheight .b2] \\\n\t[winfo reqwidth .b3] [winfo reqheight .b3] \\\n\t[winfo reqwidth .b4] [winfo reqheight .b4]\n} -cleanup {\n    deleteWindows\n} -result {66 32 65 31 69 31 71 29}\n\ntest winbutton-1.9 {TkpComputeButtonGeometry procedure} -constraints win -setup {\n    deleteWindows\n} -body {\n    button .b2 -bitmap question -default normal\n    list [winfo reqwidth .b2] [winfo reqheight .b2]\n} -cleanup {\n    deleteWindows\n} -result {23 33}\n\n#\n# TESTFILE CLEANUP\n#\n\nimageFinish\ndeleteWindows\ntestutils forget button image\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n\n"
  },
  {
    "path": "tests/winClipboard.test",
    "content": "# This file is a Tcl script to test out Tk's Windows specific\n# clipboard code.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-2000 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests that are\n#   platform-indifferent go into the test file clipboard.test.\n# * This test file is skipped entirely on non-windows platforms.\n# * Some of these tests may fail if another application is grabbing the clipboard\n#   (e.g. an X server, or a VNC viewer) #\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest winClipboard-1.1 {TkSelGetSelection} -constraints win -setup {\n    clipboard clear\n} -body {\n    selection get -selection CLIPBOARD\n} -cleanup {\n    clipboard clear\n} -returnCodes error -result {CLIPBOARD selection doesn't exist or form \"STRING\" not defined}\n\ntest winClipboard-1.2 {TkSelGetSelection} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    clipboard append {}\n    list [selection get -selection CLIPBOARD] [testclipboard]\n} -cleanup {\n    clipboard clear\n} -result {{} {}}\n\ntest winClipboard-1.3 {TkSelGetSelection & TkWinClipboardRender} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    clipboard append abcd\n    update\n    list [selection get -selection CLIPBOARD] [testclipboard]\n} -cleanup {\n    clipboard clear\n} -result {abcd abcd}\n\ntest winClipboard-1.4 {TkSelGetSelection & TkWinClipboardRender} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    set map [list \"\\r\" \"\\\\r\" \"\\n\" \"\\\\n\"]\n    clipboard append \"line 1\\nline 2\"\n    list [string map $map [selection get -selection CLIPBOARD]]\\\n\t[string map $map [testclipboard]]\n} -cleanup {\n    clipboard clear\n} -result [list \"line 1\\\\nline 2\" \"line 1\\\\nline 2\"]\n\ntest winClipboard-1.5 {TkSelGetSelection & TkWinClipboardRender} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    set map [list \"\\r\" \"\\\\r\" \"\\n\" \"\\\\n\"]\n    clipboard append \"line 1Ç\\nline 2\"\n    list [string map $map [selection get -selection CLIPBOARD]]\\\n\t[string map $map [testclipboard]]\n} -cleanup {\n    clipboard clear\n} -result [list \"line 1Ç\\\\nline 2\" \"line 1Ç\\\\nline 2\"]\n\ntest winClipboard-1.6 {TkSelGetSelection & TkWinClipboardRender} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    clipboard append \"привет миф\"\n    list [selection get -selection CLIPBOARD] [testclipboard]\n} -cleanup {\n    clipboard clear\n} -result [list \"привет миф\" \"привет миф\"]\n\ntest winClipboard-2.1 {TkSelUpdateClipboard reentrancy problem} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    clipboard append -type OUR_ACTION \"action data\"\n    clipboard append \"string data\"\n    update\n    list [selection get -selection CLIPBOARD -type OUR_ACTION] [testclipboard]\n} -cleanup {\n    clipboard clear\n} -result {{action data} {string data}}\n\ntest winClipboard-2.2 {TkSelUpdateClipboard reentrancy problem} -constraints {\n    win testclipboard\n} -setup {\n    clipboard clear\n} -body {\n    clipboard append -type OUR_ACTION \"new data\"\n    clipboard append \"more data in string\"\n    update\n    list [testclipboard] [selection get -selection CLIPBOARD -type OUR_ACTION]\n} -cleanup {\n    clipboard clear\n} -result {{more data in string} {new data}}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/winDialog.test",
    "content": "# This file is a Tcl script to test the Windows specific behavior of\n# the common dialog boxes.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Copyright © 1998-1999 ActiveState Corporation.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests that are\n#   platform-indifferent go into the test file dialog.test.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import dialog\nset applyFontCmd [list set testDialogFont]\n\nif {[testConstraint testwinevent]} {\n    catch {testwinevent debug 1}\n}\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc GetText {id} {\n    variable testDialog\n    switch -exact -- $id {\n\tok     { set id 1 }\n\tcancel { set id 2 }\n    }\n    return [testwinevent $testDialog $id WM_GETTEXT]\n}\n\nproc SetText {id text} {\n    variable testDialog\n    return [testwinevent $testDialog $id WM_SETTEXT $text]\n}\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\n# Locale identifier LANG_ENGLISH is 0x09\ntestConstraint english [expr {\n    [llength [info commands testwinlocale]]\n    && (([testwinlocale] & 0xff) == 9)\n}]\n\n#\n# COMMON TEST SETUP\n#\n\nset initialDir [tcltest::temporaryDirectory]\n\n#\n# TESTS\n#\n\ntest winDialog-1.1 {Tk_ChooseColorObjCmd} -constraints {\n    testwinevent\n} -body {\n    testDialog launch {tk_chooseColor}\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-1.2 {Tk_ChooseColorObjCmd} -constraints {\n    testwinevent\n} -body {\n    testDialog launch {set clr [tk_chooseColor -initialcolor \"#ff9933\"]}\n    testDialog onDisplay {\n\tset x [Click cancel]\n    }\n    list $x $clr\n} -result {0 {}}\ntest winDialog-1.3 {Tk_ChooseColorObjCmd} -constraints {\n    testwinevent\n} -body {\n    testDialog launch {set clr [tk_chooseColor -initialcolor \"#ff9933\"]}\n    testDialog onDisplay {\n\tset x [Click ok]\n    }\n    list $x $clr\n} -result [list 0 \"#ff9933\"]\ntest winDialog-1.4 {Tk_ChooseColorObjCmd: -title} -constraints {\n    testwinevent\n} -setup {\n    catch {unset a x}\n} -body {\n    set x {}\n    testDialog launch {set clr [tk_chooseColor -initialcolor \"#ff9933\" -title \"Hello\"]}\n    testDialog onDisplay {\n\tif {[catch {\n\t    array set a [testgetwindowinfo $testDialog]\n\t    if {[info exists a(text)]} {lappend x $a(text)}\n\t} err]} { lappend x $err }\n\tlappend x [Click ok]\n    }\n    lappend x $clr\n} -result [list Hello 0 \"#ff9933\"]\ntest winDialog-1.5 {Tk_ChooseColorObjCmd: -title} -constraints {\n    testwinevent\n} -setup {\n    catch {unset a x}\n} -body {\n    set x {}\n    testDialog launch {\n\tset clr [tk_chooseColor -initialcolor \"#ff9933\" \\\n\t\t     -title \"Привет\"]\n    }\n    testDialog onDisplay {\n\tif {[catch {\n\t    array set a [testgetwindowinfo $testDialog]\n\t    if {[info exists a(text)]} {lappend x $a(text)}\n\t} err]} { lappend x $err }\n\tlappend x [Click ok]\n    }\n    lappend x $clr\n} -result [list \"Привет\" 0 \"#ff9933\"]\ntest winDialog-1.6 {Tk_ChooseColorObjCmd: -parent} -constraints {\n    testwinevent\n} -setup {\n    catch {unset a x}\n} -body {\n    testDialog launch {set clr [tk_chooseColor -initialcolor \"#ff9933\" -parent .]}\n    set x {}\n    testDialog onDisplay {\n\tif {[catch {\n\t    array set a [testgetwindowinfo $testDialog]\n\t    if {[info exists a(parent)]} {\n\t\tappend x [expr {$a(parent) == [wm frame .]}]\n\t    }\n\t} err]} {lappend x $err}\n\tClick ok\n    }\n    list $x $clr\n} -result [list 1 \"#ff9933\"]\ntest winDialog-1.7 {Tk_ChooseColorObjCmd: -parent} -constraints {\n    testwinevent\n} -body {\n    tk_chooseColor -initialcolor \"#ff9933\" -parent .xyzzy12\n} -returnCodes error -match glob -result {bad window path name*}\n\n\ntest winDialog-2.1 {ColorDlgHookProc} -constraints {emptyTest nt} -body {}\n\ntest winDialog-3.1 {Tk_GetOpenFileObjCmd} -constraints {\n    nt testwinevent english\n} -body {\n    testDialog launch {tk_getOpenFile}\n    testDialog onDisplay {\n\tset x [GetText cancel]\n\tClick cancel\n    }\n    return $x\n} -result {Cancel}\n\n\ntest winDialog-4.1 {Tk_GetSaveFileObjCmd} -constraints {\n    nt testwinevent english\n} -body {\n    testDialog launch {tk_getSaveFile}\n    testDialog onDisplay {\n\tset x [GetText cancel]\n\tClick cancel\n    }\n    return $x\n} -result {Cancel}\n\ntest winDialog-5.1 {GetFileName: no arguments} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {tk_getOpenFile -title Open}\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-5.2 {GetFileName: one argument} -constraints {\n    nt\n} -body {\n    tk_getOpenFile -foo\n} -returnCodes error -result {bad option \"-foo\": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}\ntest winDialog-5.3 {GetFileName: many arguments} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {tk_getOpenFile -initialdir $initialDir -parent . -title test -initialfile foo}\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-5.4 {GetFileName: Tcl_GetIndexFromObj() != TCL_OK} -constraints {\n    nt\n} -body {\n    tk_getOpenFile -foo bar -abc\n} -returnCodes error -result {bad option \"-foo\": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}\ntest winDialog-5.5 {GetFileName: Tcl_GetIndexFromObj() == TCL_OK} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getOpenFile -title bar]}\n    set y [testDialog onDisplay {\n\tClick cancel\n    }]\n    # Note this also tests fix for\n    # https://core.tcl-lang.org/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6\n    # $x is expected to be empty\n    append x $y\n} -result 0\ntest winDialog-5.6 {GetFileName: valid option, but missing value} -constraints {\n    nt\n} -body {\n    tk_getOpenFile -initialdir bar -title\n} -returnCodes error -result {value for \"-title\" missing}\n\ntest winDialog-5.7 {GetFileName: extension begins with .} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getSaveFile -defaultextension .foo -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.foo\n\ntest winDialog-5.7.1 {GetFileName: extension {} } -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getSaveFile -defaultextension {} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar\n\ntest winDialog-5.7.2 {GetFileName: extension {} Bug 47af31bd3ac6fbbb33cde1a5bab1e756ff2a6e00 } -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getSaveFile -filetypes {{All *}} -defaultextension {} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar\n\ntest winDialog-5.7.3 {GetFileName: extension {} Bug 47af31bd3ac6fbbb33cde1a5bab1e756ff2a6e00 } -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getSaveFile -filetypes {{All *}} -defaultextension {} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar.c} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.c\n\ntest winDialog-5.7.4 {GetFileName: extension {} } -constraints {\n    nt testwinevent\n} -body {\n    # Although the docs do not explicitly mention, -filetypes seems to\n    # override -defaultextension\n    testDialog launch {set x [tk_getSaveFile -filetypes {{C .c} {Tcl .tcl}} -defaultextension {foo} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.c\n\ntest winDialog-5.7.5 {GetFileName: extension {} } -constraints {\n    nt testwinevent\n} -body {\n    # Although the docs do not explicitly mention, -filetypes seems to\n    # override -defaultextension\n    testDialog launch {set x [tk_getSaveFile -filetypes {{C .c} {Tcl .tcl}} -defaultextension {} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.c\n\n\ntest winDialog-5.7.6 {GetFileName: All/extension } -constraints {\n    nt testwinevent\n} -body {\n    # In 8.6.4 this combination resulted in bar.aaa.aaa which is bad\n    testDialog launch {set x [tk_getSaveFile -filetypes {{All *}} -defaultextension {aaa} -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.aaa\n\ntest winDialog-5.7.7 {tk_getOpenFile: -defaultextension} -constraints {\n    nt testwinevent\n} -body {\n    unset -nocomplain x\n    tcltest::makeFile \"\" \"5 7 7.aaa\" $initialDir\n    testDialog launch {set x [tk_getOpenFile \\\n\t\t      -defaultextension aaa \\\n\t\t      -initialdir [file nativename $initialDir] \\\n\t\t      -initialfile \"5 7 7\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    return $x\n} -result [file join $initialDir \"5 7 7.aaa\"]\n\ntest winDialog-5.7.8 {tk_getOpenFile: -defaultextension} -constraints {\n    nt testwinevent\n} -body {\n    unset -nocomplain x\n    tcltest::makeFile \"\" \"5 7 8.aaa\" $initialDir\n    testDialog launch {set x [tk_getOpenFile \\\n\t\t      -defaultextension aaa \\\n\t\t      -initialdir [file nativename $initialDir] \\\n\t\t      -initialfile \"5 7 8.aaa\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    return $x\n} -result [file join $initialDir \"5 7 8.aaa\"]\n\ntest winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_getSaveFile -defaultextension foo -title Save]}\n    set msg {}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 bar} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    set x \"[file tail $x]$msg\"\n} -cleanup {\n    unset msg\n} -result bar.foo\ntest winDialog-5.9 {GetFileName: file types} -constraints {\n    nt testwinevent knownBug\n} -body {\n    #\n    # This test was used with MS Windows versions before Windows Vista.\n    # Starting from that version, the test is not valid anymore because the\n    # dialog's file types control has no control ID and we don't have a\n    # mechanism to locate it.\n    # The test remains at this place, with constraint knownBug, to serve as an\n    # example/template in the event that the situation changes in the future\n    # somehow.\n    #\n    testDialog launch {tk_getSaveFile -filetypes {{\"foo files\" .foo FOOF}} -title Foo}\n    testDialog onDisplay {\n\tset x [GetText 0x470]\n\tClick cancel\n    }\n    return $x\n} -result {foo files (*.foo)}\ntest winDialog-5.10 {GetFileName: file types: MakeFilter() fails} -constraints {\n    nt\n} -body {\n#        if (MakeFilter(interp, string, &utfFilterString) != TCL_OK)\n\n    tk_getSaveFile -filetypes {{\"foo\" .foo FOO}}\n} -returnCodes error -result {bad Macintosh file type \"FOO\"}\ntest winDialog-5.11 {GetFileName: initial directory} -constraints {\n    nt testwinevent\n} -body {\n#        case FILE_INITDIR:\n    unset -nocomplain x\n    testDialog launch {set x [tk_getSaveFile \\\n\t\t      -initialdir $initialDir \\\n\t\t      -initialfile \"12x 455\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    return $x\n} -result [file join $initialDir \"12x 455\"]\n\ntest winDialog-5.12.4 {tk_getSaveFile: initial directory: unicode} -constraints {\n    nt testwinevent\n} -body {\n    set dir [tcltest::makeDirectory \"ŧéŝŧ\"]\n    unset -nocomplain x\n    testDialog launch {set x [tk_getSaveFile \\\n\t\t      -initialdir $dir \\\n\t\t      -initialfile \"testfile\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    string equal $x [file join $dir testfile]\n} -result 1\n\ntest winDialog-5.12.5 {tk_getSaveFile: initial directory: nativename} -constraints {\n    nt testwinevent\n} -body {\n    unset -nocomplain x\n    testDialog launch {set x [tk_getSaveFile \\\n\t\t      -initialdir [file nativename $initialDir] \\\n\t\t      -initialfile \"5 12 5\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    return $x\n} -result [file join $initialDir \"5 12 5\"]\n\ntest winDialog-5.12.6 {tk_getSaveFile: initial directory: relative} -constraints {\n    nt testwinevent\n} -body {\n    # Windows remembers dirs from previous selections so use\n    # a subdir for this test, not $initialDir itself\n    set dir [tcltest::makeDirectory \"5 12 6\"]\n    set cur [pwd]\n    try {\n\tcd [file dirname $dir]\n\tunset -nocomplain x\n\ttestDialog launch {set x [tk_getSaveFile \\\n\t\t\t  -initialdir \"5 12 6\" \\\n\t\t\t  -initialfile \"testfile\" -title Foo]}\n\ttestDialog onDisplay {\n\t    Click ok\n\t}\n    } finally {\n\tcd $cur\n    }\n    string equal $x [file join $dir testfile]\n} -result 1\n\ntest winDialog-5.12.8 {tk_getOpenFile: initial directory: .} -constraints {\n    nt testwinevent\n} -body {\n    # Windows remembers dirs from previous selections so use\n    # a subdir for this test, not $initialDir itself\n    set newdir [tcltest::makeDirectory \"5 12 8\"]\n    set path [tcltest::makeFile \"\" \"testfile\" $newdir]\n    set cur [pwd]\n    try {\n\tcd $newdir\n\tunset -nocomplain x\n\ttestDialog launch {set x [tk_getOpenFile \\\n\t\t\t  -initialdir . \\\n\t\t\t  -initialfile \"testfile\" -title Foo]}\n\ttestDialog onDisplay {\n\t    Click ok\n\t}\n    } finally {\n\tcd $cur\n    }\n    string equal $x $path\n} -result 1\n\ntest winDialog-5.12.9 {tk_getOpenFile: initial directory: unicode} -constraints {\n    nt testwinevent\n} -body {\n    set dir [tcltest::makeDirectory \"ŧéŝŧ\"]\n    set path [tcltest::makeFile \"\" testfile $dir]\n    unset -nocomplain x\n    testDialog launch {set x [tk_getOpenFile \\\n\t\t      -initialdir $dir \\\n\t\t      -initialfile \"testfile\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    string equal $x $path\n} -result 1\n\ntest winDialog-5.12.10 {tk_getOpenFile: initial directory: nativename} -constraints {\n    nt testwinevent\n} -body {\n    unset -nocomplain x\n    tcltest::makeFile \"\" \"5 12 10\" $initialDir\n    testDialog launch {set x [tk_getOpenFile \\\n\t\t      -initialdir [file nativename $initialDir] \\\n\t\t      -initialfile \"5 12 10\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    return $x\n} -result [file join $initialDir \"5 12 10\"]\n\ntest winDialog-5.12.11 {tk_getOpenFile: initial directory: relative} -constraints {\n    nt testwinevent\n} -body {\n    # Windows remembers dirs from previous selections so use\n    # a subdir for this test, not $initialDir itself\n    set dir [tcltest::makeDirectory \"5 12 11\"]\n    set path [tcltest::makeFile \"\" testfile $dir]\n    set cur [pwd]\n    try {\n\tcd [file dirname $dir]\n\tunset -nocomplain x\n\ttestDialog launch {set x [tk_getOpenFile \\\n\t\t\t  -initialdir [file tail $dir] \\\n\t\t\t  -initialfile \"testfile\" -title Foo]}\n\ttestDialog onDisplay {\n\t    Click ok\n\t}\n    } finally {\n\tcd $cur\n    }\n    string equal $x $path\n} -result 1\n\ntest winDialog-5.13 {GetFileName: initial file} -constraints {\n    nt testwinevent\n} -body {\n#        case FILE_INITFILE:\n\n    testDialog launch {set x [tk_getSaveFile -initialfile \"12x 456\" -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    file tail $x\n} -result \"12x 456\"\n\ntest winDialog-5.16 {GetFileName: parent} -constraints {\n    nt\n} -body {\n#        case FILE_PARENT:\n\n    toplevel .t\n    set x 0\n    testDialog launch {tk_getOpenFile -parent .t -title Parent; set x 1}\n    testDialog onDisplay {\n\tdestroy .t\n    }\n    return $x\n} -result 1\ntest winDialog-5.17 {GetFileName: title} -constraints {\n    nt testwinevent\n} -body {\n#        case FILE_TITLE:\n\n    testDialog launch {tk_getOpenFile -title Narf}\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\n# In the newer file dialogs, the file type widget does not even exist\n# if no file types specified\ntest winDialog-5.18 {GetFileName: no filter specified} -constraints {\n    nt testwinevent\n} -body {\n    #    if (ofn.lpstrFilter == NULL)\n    testDialog launch {tk_getOpenFile -title Filter}\n    testDialog onDisplay {\n\tcatch {set x [GetText 0x470]} y\n\tClick cancel\n    }\n    return $y\n} -result {Could not find control with id 1136}\ntest winDialog-5.19 {GetFileName: parent HWND doesn't yet exist} -constraints {\n    nt\n} -setup {\n    destroy .t\n} -body {\n#    if (Tk_WindowId(parent) == None)\n\n    toplevel .t\n    testDialog launch {tk_getOpenFile -parent .t -title Open}\n    testDialog onDisplay {\n\tdestroy .t\n    }\n} -result {}\ntest winDialog-5.20 {GetFileName: parent HWND already exists} -constraints {\n    nt\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    update\n    testDialog launch {tk_getOpenFile -parent .t -title Open}\n    testDialog onDisplay {\n\tdestroy .t\n    }\n} -result {}\ntest winDialog-5.21 {GetFileName: call GetOpenFileName} -constraints {\n    nt testwinevent english\n} -body {\n#        winCode = GetOpenFileName(&ofn);\n\n    testDialog launch {tk_getOpenFile -title Open}\n    testDialog onDisplay {\n\tset x [GetText ok]\n\tClick cancel\n    }\n    return $x\n} -result {&Open}\ntest winDialog-5.22 {GetFileName: call GetSaveFileName} -constraints {\n    nt testwinevent english\n} -body {\n#        winCode = GetSaveFileName(&ofn);\n\n    testDialog launch {tk_getSaveFile -title Save}\n    testDialog onDisplay {\n\tset x [GetText ok]\n\tClick cancel\n    }\n    return $x\n} -result {&Save}\ntest winDialog-5.23 {GetFileName: convert \\ to /} -constraints {\n    nt testwinevent\n} -body {\n    set msg {}\n    testDialog launch {set x [tk_getSaveFile -title Back]}\n    testDialog onDisplay {\n\tif {[catch {SetText 0x3e9 [file nativename \\\n\t\t[file join $initialDir \"12x 457\"]]} msg]} {\n\t    Click cancel\n\t} else {\n\t    Click ok\n\t}\n    }\n    return $x$msg\n} -cleanup {\n    unset msg\n} -result [file join $initialDir \"12x 457\"]\ntest winDialog-5.24 {GetFileName: file types: MakeFilter() succeeds} -constraints {\n    nt\n} -body {\n    # MacOS type that is correct, but has embedded nulls.\n\n    testDialog launch {set x [catch {tk_getSaveFile -filetypes {{\"foo\" .foo {\\0\\0\\0\\0}}}}]}\n    testDialog onDisplay {\n\tClick cancel\n    }\n    return $x\n} -result 0\ntest winDialog-5.25 {GetFileName: file types: MakeFilter() succeeds} -constraints {\n    nt\n} -body {\n    # MacOS type that is correct, but has embedded high-bit chars.\n\n    testDialog launch {set x [catch {tk_getSaveFile -filetypes {{\"foo\" .foo {••••}}}}]}\n    testDialog onDisplay {\n\tClick cancel\n    }\n    return $x\n} -result 0\n\n\ntest winDialog-6.1 {MakeFilter} -constraints {emptyTest nt} -body {}\n\n\ntest winDialog-7.1 {Tk_MessageBoxObjCmd} -constraints {emptyTest nt} -body {}\n\n\ntest winDialog-8.1 {OFNHookProc} -constraints {emptyTest nt} -body {}\n\n\n## The Tk_ChooseDirectoryObjCmd hang on the static build of Windows\n## because somehow the GetOpenFileName ends up a noop in the static\n## build.\n##\ntest winDialog-9.1 {Tk_ChooseDirectoryObjCmd: no arguments} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {set x [tk_chooseDirectory]}\n    set y [testDialog onDisplay {\n\tClick cancel\n    }]\n    # $x should be \"\" on a Cancel\n    append x $y\n} -result 0\ntest winDialog-9.2 {Tk_ChooseDirectoryObjCmd: one argument} -constraints {\n    nt\n} -body {\n    tk_chooseDirectory -foo\n} -returnCodes error -result {bad option \"-foo\": must be -initialdir, -mustexist, -parent, or -title}\ntest winDialog-9.3 {Tk_ChooseDirectoryObjCmd: many arguments} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk_chooseDirectory -initialdir $initialDir -mustexist 1 -parent . -title test\n    }\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-9.4 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() != TCL_OK} -constraints {\n    nt\n} -body {\n    tk_chooseDirectory -foo bar -abc\n} -returnCodes error -result {bad option \"-foo\": must be -initialdir, -mustexist, -parent, or -title}\ntest winDialog-9.5 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() == TCL_OK} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {tk_chooseDirectory -title bar}\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-9.6 {Tk_ChooseDirectoryObjCmd: valid option, but missing value} -constraints {\n    nt\n} -body {\n    tk_chooseDirectory -initialdir bar -title\n} -returnCodes error -result {value for \"-title\" missing}\ntest winDialog-9.7 {Tk_ChooseDirectoryObjCmd: -initialdir} -constraints {\n    nt testwinevent\n} -body {\n#        case DIR_INITIAL:\n\n    testDialog launch {set x [tk_chooseDirectory -initialdir $initialDir -title Foo]}\n    testDialog onDisplay {\n\tClick ok\n    }\n    string tolower [set x]\n} -result [string tolower $initialDir]\n\n\ntest winDialog-10.1 {Tk_FontchooserObjCmd: no arguments} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {tk fontchooser show}\n    list [testDialog onDisplay {\n\tClick cancel\n    }] $testDialogFont\n} -result {0 {}}\ntest winDialog-10.2 {Tk_FontchooserObjCmd: -initialfont} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -font system\n\ttk fontchooser show\n    }\n    list [testDialog onDisplay {\n\tClick cancel\n    }] $testDialogFont\n} -result {0 {}}\ntest winDialog-10.3 {Tk_FontchooserObjCmd: -initialfont} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -font system\n\ttk fontchooser show\n    }\n    list [testDialog onDisplay {\n\tClick 1\n    }] [expr {[llength $testDialogFont] > 0}]\n} -result {0 1}\ntest winDialog-10.4 {Tk_FontchooserObjCmd: -title} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -title \"tk test\"\n\ttk fontchooser show\n    }\n    list [testDialog onDisplay {\n\tClick cancel\n    }] $testDialogFont\n} -result {0 {}}\ntest winDialog-10.5 {Tk_FontchooserObjCmd: -parent} -constraints {\n    nt testwinevent\n} -setup {\n    array set a {parent {}}\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -parent .\n\ttk fontchooser show\n    }\n    testDialog onDisplay {\n\tarray set a [testgetwindowinfo $testDialog]\n\tClick cancel\n    }\n    list [expr {$a(parent) == [wm frame .]}] $testDialogFont\n} -result {1 {}}\ntest winDialog-10.6 {Tk_FontchooserObjCmd: -apply} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command FooBarBaz\n\ttk fontchooser show\n    }\n    testDialog onDisplay {\n\tClick cancel\n    }\n} -result 0\ntest winDialog-10.7 {Tk_FontchooserObjCmd: -apply} -constraints {\n    nt testwinevent\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -parent .\n\ttk fontchooser show\n    }\n    list [testDialog onDisplay {\n\tClick [expr {0x0402}] ;# value from XP\n\tClick cancel\n    }] [expr {[llength $testDialogFont] > 0}]\n} -result {0 1}\ntest winDialog-10.8 {Tk_FontchooserObjCmd: -title} -constraints {\n    nt testwinevent\n} -setup {\n    array set a {text failed}\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd -title \"Hello\"\n\ttk fontchooser show\n    }\n    testDialog onDisplay {\n\tarray set a [testgetwindowinfo $testDialog]\n\tClick cancel\n    }\n    set a(text)\n} -result \"Hello\"\ntest winDialog-10.9 {Tk_FontchooserObjCmd: -title} -constraints {\n    nt testwinevent\n} -setup {\n    array set a {text failed}\n} -body {\n    testDialog launch {\n\ttk fontchooser configure -command $applyFontCmd \\\n\t    -title  \"Привет\"\n\ttk fontchooser show\n    }\n    testDialog onDisplay {\n\tarray set a [testgetwindowinfo $testDialog]\n\tClick cancel\n    }\n    set a(text)\n} -result \"Привет\"\n\n#\n# TESTFILE CLEANUP\n#\n\nif {[testConstraint testwinevent]} {\n    catch {testwinevent debug 0}\n}\n\nunset applyFontCmd initialDir\ntestutils forget dialog\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n\n"
  },
  {
    "path": "tests/winFont.test",
    "content": "# This file is a Tcl script to test out the procedures in tkWinFont.c.\n# It is organized in the standard fashion for Tcl tests.\n#\n# Copyright © 1996-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the windows platform. Tests regarding the font\n#   system that are specific to the unix platform go into the test file\n#   unixFont.test. Tests that are platform-indifferent go into the test file\n#   font.test. Or they may exists as each other's counterparts in both\n#   unixFont.test and winFont.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-windows platforms.\n# * Many of the tests are visually oriented. They do exercise the code in\n#   question, but there are no results that can be checked programmatically\n#   (such as \"does an underlined font appear to be underlined?\").\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import geometry\n\n#\n# TESTS\n#\n\ntest winfont-1.1 {TkpGetNativeFont procedure: not native} -constraints {\n    win\n} -body {\n    catch {font delete xyz}\n    font measure {} xyz\n} -returnCodes error -result {font \"\" does not exist}\ntest winfont-1.2 {TkpGetNativeFont procedure: native} -constraints win -body {\n    font measure ansifixed 0\n    font measure ansi 0\n    font measure device 0\n    font measure oemfixed 0\n    font measure systemfixed 0\n    font measure system 0\n    set x {}\n} -result {}\n\n\ntest winfont-2.1 {TkpGetFontFromAttributes procedure: pointsize} -constraints {\n    win\n} -body {\n    expr {[font actual {-size -10} -size] > 0}\n} -result 1\ntest winfont-2.2 {TkpGetFontFromAttributes procedure: pointsize} -constraints {\n    win\n} -body {\n    expr {[font actual {-family Arial} -size] > 0}\n} -result 1\ntest winfont-2.3 {TkpGetFontFromAttributes procedure: normal weight} -constraints {\n    win\n} -body {\n    font actual {-weight normal} -weight\n} -result {normal}\ntest winfont-2.4 {TkpGetFontFromAttributes procedure: bold weight} -constraints {\n    win\n} -body {\n    font actual {-weight bold} -weight\n} -result {bold}\ntest winfont-2.5 {TkpGetFontFromAttributes procedure: no family} -constraints {\n    win\n} -body {\n    catch {expr {[font actual {-size 10} -size]}}\n} -result 0\ntest winfont-2.6 {TkpGetFontFromAttributes procedure: family} -constraints {\n    win\n} -body {\n    font actual {-family Arial} -family\n} -result {Arial}\ntest winfont-2.7 {TkpGetFontFromAttributes procedure: Times fonts} -constraints {\n    win\n} -setup {\n    set x {}\n} -body {\n    lappend x [font actual {-family \"Times\"} -family]\n    lappend x [font actual {-family \"New York\"} -family]\n    lappend x [font actual {-family \"Times New Roman\"} -family]\n} -result {Times Times {Times New Roman}}\ntest winfont-2.8 {TkpGetFontFromAttributes procedure: Courier fonts} -constraints {\n    win\n} -setup {\n    set x {}\n} -body {\n    lappend x [font actual {-family \"Courier\"} -family]\n    lappend x [font actual {-family \"Monaco\"} -family]\n    lappend x [font actual {-family \"Courier New\"} -family]\n} -match regexp -result {Courier (Courier|Monaco) {Courier New}}\ntest winfont-2.9 {TkpGetFontFromAttributes procedure: Helvetica fonts} -constraints {\n    win\n} -setup {\n    set x {}\n} -body {\n    lappend x [font actual {-family \"Helvetica\"} -family]\n    lappend x [font actual {-family \"Geneva\"} -family]\n    lappend x [font actual {-family \"Arial\"} -family]\n} -match regexp -result {Helvetica (Helvetica|Geneva) Arial}\ntest winfont-2.10 {TkpGetFontFromAttributes procedure: fallback} -constraints {\n    win\n} -body {\n    # No way to get it to fail! Any font name is acceptable.\n} -result {}\n\n\ntest winfont-3.1 {TkpDeleteFont procedure} -constraints win -body {\n    catch {font delete xyz}\n    font actual {-family xyz}\n    set x {}\n} -result {}\n\n\ntest winfont-4.1 {TkpGetFontFamilies procedure} -constraints win -body {\n    font families\n    set x {}\n} -result {}\n\n#\n# COMMON TEST SETUP\n#\n\ndestroy .t\ntoplevel .t\nwm geometry .t +0+0\nupdate idletasks\nlabel .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left -text \"0\" -font systemfixed\npack .t.l\ncanvas .t.c -closeenough 0\n\nset courier {Courier 14}\nset cx [font measure $courier 0]\nset t [.t.c create text 0 0 -anchor nw -just left -font $courier]\npack .t.c\nupdate\n\nset ax [winfo reqwidth .t.l]\nset ay [winfo reqheight .t.l]\n\ntest winfont-5.1 {Tk_MeasureChars procedure: unbounded right margin} -constraints {\n    win\n} -setup {\n    destroy .t.l\n} -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap 0 -text \"000000\"\n    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq $ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.2 {Tk_MeasureChars procedure: static width buffer exceeded} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap 100000 -text \"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"\n    list [expr {[winfo reqwidth .t.l] eq 256*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq $ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.3 {Tk_MeasureChars procedure: all chars did fit} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*10}] -text \"00000000\"\n    list [expr {[winfo reqwidth .t.l] eq 8*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq $ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.4 {Tk_MeasureChars procedure: not all chars fit} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*6}] -text \"00000000\"\n    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 2*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.5 {Tk_MeasureChars procedure: include last partial char} -constraints {\n    win\n} -setup {\n    destroy .t.c\n}  -body {\n    canvas .t.c -closeenough 0\n    set t [.t.c create text 0 0 -anchor nw -just left -font $courier]\n    pack .t.c\n    update\n\n    .t.c dchars $t 0 end\n    .t.c insert $t 0 \"0000\"\n    .t.c index $t @[expr {int($cx*2.5)}],1\n} -cleanup {\n    destroy .t.c\n} -result 2\n\ntest winfont-5.6 {Tk_MeasureChars procedure: at least one char on line} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -text \"000000\" -wrap 1\n    list [expr {[winfo reqwidth .t.l] eq $ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 6*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.7 {Tk_MeasureChars procedure: whole words} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*8}] -text \"000000 0000\"\n    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 2*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.8 {Tk_MeasureChars procedure: already saw space in line} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*12}] -text \"000000    0000000\"\n    list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 2*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.9 {Tk_MeasureChars procedure: internal spaces significant} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*12}] -text \"000  00   00000\"\n    list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 2*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.10 {Tk_MeasureChars procedure: make first part of word fit} -constraints {\n    win\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    set ax [winfo reqwidth .t.l]\n    set ay [winfo reqheight .t.l]\n\n    .t.l config -wrap [expr {$ax*12}] -text \"0000000000000000\"\n    list [expr {[winfo reqwidth .t.l] eq 12*$ax}] \\\n\t[expr {[winfo reqheight .t.l] eq 2*$ay}]\n} -cleanup {\n    destroy .t.l\n} -result {1 1}\n\ntest winfont-5.11 {Tk_MeasureChars procedure: check for kerning} -constraints {\n    win nonPortable\n} -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n\n    set font [.t.l cget -font]\n    .t.l config -font {{MS Sans Serif} 8} -text \"W\"\n    set width [winfo reqwidth .t.l]\n    .t.l config -text \"XaYoYaKaWx\"\n    set x [lindex [getsize .t.l] 0]\n    .t.l config -font $font\n    expr {$x < ($width*10)}\n} -cleanup {\n    destroy .t.l\n} -result 1\n\n\ntest winfont-6.1 {Tk_DrawChars procedure: loop test} -constraints win -setup {\n    destroy .t.l\n}  -body {\n    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \\\n\t-text \"0\" -font systemfixed\n    pack .t.l\n    update\n    .t.l config -text \"a\"\n    update\n} -cleanup {\n    destroy .t.l\n} -result {}\n\n\ntest winfont-7.1 {InitFont procedure: use old font} -constraints win -setup {\n    destroy .c\n} -setup {\n    catch {font delete xyz}\n} -body {\n    font create xyz\n    button .c -font xyz\n    font configure xyz -family times\n    update\n    destroy .c\n    font delete xyz\n} -result {}\ntest winfont-7.2 {InitFont procedure: extract info from logfont} -constraints {\n    win\n} -body {\n    font actual {arial 10 bold italic underline overstrike}\n} -result {-family Arial -size 10 -weight bold -slant italic -underline 1 -overstrike 1}\ntest winfont-7.3 {InitFont procedure: extract info from textmetric} -constraints {\n    win\n} -body {\n    font metric {arial 10 bold italic underline overstrike} -fixed\n} -result 0\ntest winfont-7.4 {InitFont procedure: extract info from textmetric} -constraints {\n    win\n} -body {\n    font metric systemfixed -fixed\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\ntestutils forget geometry\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/winMenu.test",
    "content": "# This file is a Tcl script that tests the features of the Tk menu system that\n# are specific to MS Windows.\n#\n# Copyright © 1995-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests regarding\n#   the menu system that are specific to the unix platform (this includes macOS)\n#   go into the test file unixMenu.test. Tests that are platform-indifferent go\n#   into test file menu.test. Or they may exists as each other's counterparts in\n#   both unixMenu.test and winMenu.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest winMenu-1.1 {GetNewID} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n} -cleanup {\n    destroy .m1\n} -returnCodes ok -result {.m1}\ntest winMenu-1.2 {GetNewID} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -result {}\n\n\n# Basically impossible to test menu IDs wrapping.\n\ntest winMenu-2.1 {FreeID} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -returnCodes ok\n\n\ntest winMenu-3.1 {TkpNewMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    list [catch {menu .m1} msg] $msg [catch {destroy .m1} msg2] $msg2\n} -result {0 .m1 0 {}}\ntest winMenu-3.2 {TkpNewMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add command -label \"foo\"\n    list [catch {. configure -menu .m1} msg] $msg [. configure -menu \"\"] [catch {destroy .m1} msg2] $msg2\n} -result {0 {} {} 0 {}}\n\n\ntest winMenu-4.1 {TkpDestroyMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    destroy .m1\n} -returnCodes ok\ntest winMenu-4.2 {TkpDestroyMenu - help menu} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m1.system\n    . configure -menu .m1\n    list [catch {destroy .m1.system} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\n\n\ntest winMenu-5.1 {TkpDestroyMenuEntry} -constraints win -setup {\n    destroy .m1\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add command -label \"test\"\n    update idletasks\n    list [catch {.m1 delete 1} msg] $msg [destroy .m1]\n} -result {0 {} {}}\n\n\ntest winMenu-6.1 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    list [catch {menu .m1} msg] $msg [destroy .m1]\n} -result {0 .m1 {}}\ntest winMenu-6.2 {GetEntryText} -constraints {\n    testImageType win\n} -setup {\n    destroy .m1\n} -body {\n    catch {image delete image1}\n    menu .m1\n    image create test image1\n    list [catch {.m1 add command -image image1} msg] $msg [destroy .m1] [image delete image1]\n} -result {0 e001 {} {}}\ntest winMenu-6.3 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -bitmap questhead} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.4 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.5 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"foo\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.6 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"This string has one & in it\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.7 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The & should be underlined.\" -underline 4} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.8 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The * should be underlined.\" -underline 4} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.9 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"foo\" -accel \"bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.10 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"This string has one & in it\" -accel \"bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.11 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The & should be underlined.\" -underline 4 -accel \"bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.12 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The * should be underlined.\" -underline 4 -accel \"bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.13 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"foo\" -accel \"&bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.14 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"This string has one & in it\" -accel \"&bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.15 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The & should be underlined.\" -underline 4 -accel \"&bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\ntest winMenu-6.16 {GetEntryText} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command -label \"The * should be underlined.\" -underline 4 -accel \"&bar\"} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\n\ntest winMenu-7.1 {ReconfigureWindowsMenu - system menu item removal} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -menu .m1.system\n    menu .m1.system\n    .m1.system add command -label foo\n    update idletasks\n    .m1.system add command -label bar\n    list [catch {update idletasks} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\ntest winMenu-7.2 {ReconfigureWindowsMenu - menu item removal} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label Hello\n    update idletasks\n    .m1 add command -label foo\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.3 {ReconfigureWindowsMenu - zero items} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello\n    .m1 delete Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.4 {ReconfigureWindowsMenu - one item} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.5 {ReconfigureWindowsMenu - two items} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label One\n    .m1 add command -label Two\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.6 {ReconfigureWindowsMenu - separator item} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add separator\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.7 {ReconfigureWindowsMenu - non-text item} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.8 {ReconfigureWindowsMenu - disabled item} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello -state disabled\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.9 {ReconfigureWindowsMenu - non-selected checkbutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add checkbutton -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.10 {ReconfigureWindowsMenu - non-selected radiobutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add radiobutton -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.11 {ReconfigureWindowsMenu - selected checkbutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add checkbutton -label Hello\n    .m1 invoke Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.12 {ReconfigureWindowsMenu - selected radiobutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add radiobutton -label Hello\n    .m1 invoke Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.13 {ReconfigureWindowsMenu - cascade missing} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\ntest winMenu-7.14 {ReconfigureWindowsMenu - cascade} -constraints win -setup {\n    destroy .m1\n} -body {\n    catch {destroy .m2}\n    menu .m1 -tearoff 0\n    menu .m2\n    .m1 add cascade -menu .m2 -label Hello\n    list [catch {update idletasks} msg] $msg [destroy .m1] [destroy .m2]\n} -result {0 {} {} {}}\ntest winMenu-7.15 {ReconfigureWindowsMenu - menubar without system menu} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -menu .m1.file\n    menu .m1.file -tearoff 0\n    . configure -menu .m1\n    list [catch {update idletasks} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\ntest winMenu-7.16 {ReconfigureWindowsMenu - system menu already created} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -menu .m1.system\n    menu .m1.system -tearoff 0\n    . configure -menu .m1\n    update idletasks\n    .m1.system add command -label Hello\n    list [catch {update idletasks} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\ntest winMenu-7.17 {ReconfigureWindowsMenu - system menu update pending} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -menu .m1.system\n    menu .m1.system -tearoff 0\n    . configure -menu .m1\n    list [catch {update idletasks} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\ntest winMenu-7.18 {ReconfigureWindowsMenu - system menu update not pending} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add cascade -menu .m1.system\n    menu .m1.system -tearoff 0\n    .m1.system add command -label Hello\n    update idletasks\n    . configure -menu .m1\n    list [catch {update idletasks} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\ntest winMenu-7.19 {ReconfigureWindowsMenu - column break} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two -columnbreak 1\n    list [catch {update idletasks} msg] $msg [destroy .m1]\n} -result {0 {} {}}\n\n\n#Don't know how to generate nested post menus\n\ntest winMenu-8.1 {TkpPostMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -postcommand \"blork\"\n    .m1 post 40 40\n} -returnCodes error -result {invalid command name \"blork\"}\ntest winMenu-8.2 {TkpPostMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -postcommand \"blork\"\n    .m1 post 40 40\n    destroy .m1\n} -returnCodes error -result {invalid command name \"blork\"}\ntest winMenu-8.3 {TkpPostMenu} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -postcommand \"destroy .m1\"\n    list [.m1 post 40 40] [winfo exists .m1]\n} -result {{} 0}\ntest winMenu-8.4 {TkpPostMenu - popup menu} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-8.3: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\ntest winMenu-8.5 {TkpPostMenu - menu button} -constraints {\n    win userInteraction\n} -setup {\n    destroy .mb\n} -body {\n    menubutton .mb -text test -menu .mb.menu\n    menu .mb.menu\n    .mb.menu add command -label \"winMenu-8.4 - Hit ESCAPE.\"\n    pack .mb\n    list [tk::MbPost .mb] [destroy .mb]\n} -result {{} {}}\ntest winMenu-8.6 {TkpPostMenu - update not pending} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-8.5 - Hit ESCAPE.\"\n    update idletasks\n    list [catch {.m1 post 40 40} msg] $msg [destroy .m1]\n} -result {0 {} {}}\n\n\ntest winMenu-9.1 {TkpMenuNewEntry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [catch {.m1 add command} msg] $msg [destroy .m1]\n} -result {0 e001 {}}\n\n\ntest winMenu-10.1 {TkwinMenuProc} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-10.1: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\n\n\n# Can't generate a WM_INITMENU without a Tk menu yet.\n\ntest winMenu-11.1 {TkWinHandleMenuEvent - WM_INITMENU} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1 -postcommand \"set foo test\"\n    .m1 add command -label \"winMenu-11.1: Hit ESCAPE.\"\n    list [.m1 post 40 40] [set foo] [unset foo] [destroy .m1]\n} -result {test test {} {}}\ntest winMenu-11.2 {TkWinHandleMenuEvent - WM_COMMAND} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    menu .m1\n    .m1 add checkbutton -variable foo -label \"winMenu-11.2: Please select this menu item.\"\n    list [.m1 post 40 40] [update] [set foo] [unset foo] [destroy .m1]\n} -result {{} {} 1 {} {}}\ntest winMenu-11.3 {TkWinHandleMenuEvent - WM_COMMAND} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    catch {unset foo}\n    proc bgerror {args} {\n\tglobal foo errorInfo\n\tset foo [list $args $errorInfo]\n    }\n    menu .m1\n    .m1 add command -command {error 1} -label \"winMenu-11.2: Please select this menu item.\"\n    list [.m1 post 40 40] [update] [set foo] [unset foo] [destroy .m1]\n} -result {{} {} {1 {1\n    while executing\n\"error 1\"\n    (menu invoke)}} {} {}}\n\n\n# Can't test WM_MENUCHAR\n\ntest winMenu-11.4 {TkWinHandleMenuEvent - WM_MEASUREITEM} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-11.3: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\ntest winMenu-11.5 {TkWinHandleMenuEvent - WM_MEASUREITEM} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label \"winMenu-11.4: Hit ESCAPE\" -hidemargin 1\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\ntest winMenu-11.6 {TkWinHandleMenuEvent - WM_DRAWITEM} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-11.5: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\ntest winMenu-11.7 {TkWinHandleMenuEvent - WM_DRAWITEM - item disabled} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-11.6: Hit ESCAPE.\" -state disabled\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\ntest winMenu-11.8 {TkWinHandleMenuEvent - WM_INITMENU - not pending} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label \"winMenu-11.7: Hit ESCAPE\"\n    update idletasks\n    list [catch {.m1 post 40 40} msg] $msg [destroy .m1]\n} -result {0 {} {}}\n\n\ntest winMenu-12.1 {TkpSetWindowMenuBar} -constraints win -setup {\n    destroy .m1\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add command -label foo\n    list [catch {. configure -menu .m1} msg] $msg [. configure -menu \"\"] [catch {destroy .m1} msg2] $msg2\n} -result {0 {} {} 0 {}}\ntest winMenu-12.2 {TkpSetWindowMenuBar} -constraints win -setup {\n    destroy .m1\n} -body {\n    . configure -menu \"\"\n    menu .m1\n    .m1 add command -label foo\n    . configure -menu .m1\n    list [catch {. configure -menu \"\"} msg] $msg [catch {destroy .m1} msg2] $msg2\n} -result {0 {} 0 {}}\ntest winMenu-12.3 {TkpSetWindowMenuBar - no update pending} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    . configure -menu \"\"\n    menu .m1 -tearoff 0\n    .m1 add command -label foo\n    update idletasks\n    list [catch {. configure -menu .m1} msg] $msg [. configure -menu \"\"] [destroy .m1]\n} -result {0 {} {} {}}\n\n\ntest winMenu-13.1 {Tk_SetMainMenubar - nothing to do} -constraints {\n    emptyTest win\n} -body {}\n\n\ntest winMenu-14.1 {GetMenuIndicatorGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest winMenu-14.2 {GetMenuIndicatorGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -hidemargin 1\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest winMenu-15.1 {GetMenuAccelGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo -accel Ctrl+U\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest winMenu-15.2 {GetMenuAccelGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\ntest winMenu-15.3 {GetMenuAccelGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -accel \"Ctrl+U\"\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\ntest winMenu-16.1 {GetTearoffEntryGeometry} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-19.1: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-17.1 {GetMenuSeparatorGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    tk::TearOffMenu .m1 40 40\n    destroy .m1\n} -returnCodes ok\n\n\n# Currently, the only callers to DrawWindowsSystemBitmap want things\n# centered vertically, and either centered or right aligned horizontally.\ntest winMenu-18.1 {DrawWindowsSystemBitmap - center aligned} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-18.2 {DrawWindowsSystemBitmap - right aligned} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-19.1 {DrawMenuEntryIndicator - not checkbutton or radiobutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-19.2 {DrawMenuEntryIndicator - not selected} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-19.3 {DrawMenuEntryIndicator - checkbutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-19.4 {DrawMenuEntryIndicator - radiobutton} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add radiobutton -label foo\n    .m1 invoke foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-19.5 {DrawMenuEntryIndicator - disabled} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke foo\n    .m1 entryconfigure foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-19.6 {DrawMenuEntryIndicator - indicator not on} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -indicatoron 0\n    .m1 invoke foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-20.1 {DrawMenuEntryAccelerator - disabled} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground red\n    .m1 add command -label foo -accel \"Ctrl+U\" -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-20.2 {DrawMenuEntryAccelerator - normal text} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -accel \"Ctrl+U\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-20.3 {DrawMenuEntryAccelerator - disabled, no disabledforeground} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground \"\"\n    .m1 add command -label foo -accel \"Ctrl+U\" -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-20.4 {DrawMenuEntryAccelerator - cascade, drawArrow true} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-20.5 {DrawMenuEntryAccelerator - cascade, drawArrow false} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label \"winMenu-23.5: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-21.1 {DrawMenuSeparator} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-22.1 {DrawMenuUnderline} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -underline 0\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-23.1 {Don't know how to test MenuKeyBindProc} -constraints {\n    win emptyTest\n} -body {}\n\n\ntest winMenu-24.1 {TkpInitializeMenuBindings called at boot time} -constraints {\n    win emptyTest\n} -body {}\n\n\ntest winMenu-25.1 {DrawMenuEntryLabel - normal} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-25.2 {DrawMenuEntryLabel - disabled with fg} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground red\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-25.3 {DrawMenuEntryLabel - disabled with no fg} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground \"\"\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-26.1 {TkpComputeMenubarGeometry} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label File\n    list [. configure -menu .m1] [. configure -menu \"\"] [destroy .m1]\n} -result {{} {} {}}\n\n\ntest winMenu-27.1 {DrawTearoffEntry} -constraints {\n    win userInteraction\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"winMenu-24.4: Hit ESCAPE.\"\n    list [.m1 post 40 40] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-28.1 {TkpConfigureMenuEntry - update pending} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label Hello\n    list [catch {.m1 add command -label Two} msg] $msg [destroy .m1]\n} -result {0 e002 {}}\ntest winMenu-28.2 {TkpConfigureMenuEntry - update not pending} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label One\n    update idletasks\n    list [catch {.m1 add command -label Two} msg] $msg [destroy .m1]\n} -result {0 e002 {}}\n\n\ntest winMenu-29.1 {TkpDrawMenuEntry - gc for active and not strict motif} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.2 {TkpDrawMenuEntry - gc for active menu item with its own gc} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activeforeground red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.3 {TkpDrawMenuEntry - gc for active and strict motif} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    set tk_strictMotif 1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1] [set tk_strictMotif 0]\n} -result {{} {} 0}\ntest winMenu-29.4 {TkpDrawMenuEntry - gc for disabled with disabledfg and custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground blue\n    .m1 add command -label foo -state disabled -background red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.5 {TkpDrawMenuEntry - gc for disabled with disabledFg} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground blue\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.6 {TkpDrawMenuEntry - gc for disabled - no disabledFg} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -disabledforeground \"\"\n    .m1 add command -label foo -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.7 {TkpDrawMenuEntry - gc for normal - custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -foreground red\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.8 {TkpDrawMenuEntry - gc for normal} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.9 {TkpDrawMenuEntry - gc for indicator - custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo -selectcolor orange\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.10 {TkpDrawMenuEntry - gc for indicator} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label foo\n    .m1 invoke 1\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.11 {TkpDrawMenuEntry - border - custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activebackground green\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.12 {TkpDrawMenuEntry - border} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.13 {TkpDrawMenuEntry - active border - strict motif} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    set tk_strictMotif 1\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1] [set tk_strictMotif 0]\n} -result {{} {} 0}\ntest winMenu-29.14 {TkpDrawMenuEntry - active border - custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -activeforeground yellow\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.15 {TkpDrawMenuEntry - active border} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    .m1 entryconfigure 1 -state active\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.16 {TkpDrawMenuEntry - font - custom entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo -font \"Helvectica 72\"\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.17 {TkpDrawMenuEntry - font} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1 -font \"Courier 72\"\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.18 {TkpDrawMenuEntry - separator} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.19 {TkpDrawMenuEntry - standard} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.20 {TkpDrawMenuEntry - disabled cascade item} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add cascade -label File -menu .m1.file\n    menu .m1.file\n    .m1.file add command -label foo\n    .m1 entryconfigure File -state disabled\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.21 {TkpDrawMenuEntry - indicator} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label winMenu-31.20\n    .m1 invoke winMenu-31.20\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-29.22 {TkpDrawMenuEntry - indicator} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label winMenu-31.21 -hidemargin 1\n    .m1 invoke winMenu-31.21\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-30.1 {GetMenuLabelGeometry - image} -constraints {\n    testImageType win\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    menu .m1\n    image create test image1\n    .m1 add command -image image1\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest winMenu-30.2 {GetMenuLabelGeometry - bitmap} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -bitmap questhead\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-30.3 {GetMenuLabelGeometry - no text} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-30.4 {GetMenuLabelGeometry - text} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"This is a test.\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-31.1 {DrawMenuEntryBackground} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    list [update] [destroy .m1]\n} -result {{} {}}\ntest winMenu-31.2 {DrawMenuEntryBackground} -constraints win -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label foo\n    set tearoff [tk::TearOffMenu .m1 40 40]\n    $tearoff activate 0\n    list [update] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-32.1 {TkpComputeStandardMenuGeometry - no entries} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.2 {TkpComputeStandardMenuGeometry - one entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.3 {TkpComputeStandardMenuGeometry - more than one entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"one\"\n    .m1 add command -label \"two\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.4 {TkpComputeStandardMenuGeometry - separator} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add separator\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.5 {TkpComputeStandardMenuGeometry - tearoff entry} -constraints {\n    win nonUnixUserInteraction\n} -setup {\n    destroy .mb\n} -body {\n    menubutton .mb -text \"test\" -menu .mb.m\n    menu .mb.m\n    .mb.m add command -label test\n    pack .mb\n    catch {tk::MbPost .mb}\n    list [update] [destroy .mb]\n} -result {{} {}}\ntest winMenu-32.6 {TkpComputeStandardMenuGeometry - standard label geometry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.7 {TkpComputeStandardMenuGeometry - different font for entry} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -font \"Helvetica 12\"\n    .m1 add command -label \"test\" -font \"Courier 12\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.8 {TkpComputeStandardMenuGeometry - second entry larger} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\"\n    .m1 add command -label \"test test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.9 {TkpComputeStandardMenuGeometry - first entry larger} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test test\"\n    .m1 add command -label \"test\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.10 {TkpComputeStandardMenuGeometry - accelerator} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"Ctrl+S\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.11 {TkpComputeStandardMenuGeometry - second accel larger} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"1\"\n    .m1 add command -label \"test\" -accel \"1 1\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.12 {TkpComputeStandardMenuGeometry - second accel smaller} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label \"test\" -accel \"1 1\"\n    .m1 add command -label \"test\" -accel \"1\"\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.13 {TkpComputeStandardMenuGeometry - indicator} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add checkbutton -label test\n    .m1 invoke 1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.14 {TkpComputeStandardMenuGeometry - second indicator less or equal} -constraints {\n    testImageType win\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    image create test image1\n    menu .m1\n    .m1 add checkbutton -image image1\n    .m1 invoke 1\n    .m1 add checkbutton -label test\n    .m1 invoke 2\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest winMenu-32.15 {TkpComputeStandardMenuGeometry - second indicator larger} -constraints {\n    testImageType win\n} -setup {\n    destroy .m1\n    catch {image delete image1}\n} -body {\n    image create test image1\n    menu .m1\n    .m1 add checkbutton -image image1\n    .m1 invoke 1\n    .m1 add checkbutton -label test\n    .m1 invoke 2\n    list [update idletasks] [destroy .m1] [image delete image1]\n} -result {{} {} {}}\ntest winMenu-32.16 {TkpComputeStandardMenuGeometry - zero sized menus} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.17 {TkpComputeStandardMenuGeometry - first column bigger} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1\n    .m1 add command -label one\n    .m1 add command -label two\n    .m1 add command -label three -columnbreak 1\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.18 {TkpComputeStandardMenuGeometry - second column bigger} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two -columnbreak 1\n    .m1 add command -label three\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\ntest winMenu-32.19 {TkpComputeStandardMenuGeometry - three columns} -constraints {\n    win\n} -setup {\n    destroy .m1\n} -body {\n    menu .m1 -tearoff 0\n    .m1 add command -label one\n    .m1 add command -label two -columnbreak 1\n    .m1 add command -label three\n    .m1 add command -label four\n    .m1 add command -label five -columnbreak 1\n    .m1 add command -label six\n    list [update idletasks] [destroy .m1]\n} -result {{} {}}\n\n\ntest winMenu-33.1 {TkpNotifyTopLevelCreate - no menu yet} -constraints {\n    win\n} -setup {\n    destroy .m1 .t2\n} -body {\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    list [update idletasks] [destroy .t2]\n} -result {{} {}}\ntest winMenu-33.2 {TkpNotifyTopLevelCreate - menu} -constraints win -setup {\n    destroy .m1 .t2\n} -body {\n    menu .m1\n    menu .m1.system\n    .m1 add cascade -menu .m1.system\n    .m1.system add separator\n    .m1.system add command -label foo\n    toplevel .t2 -menu .m1\n    wm geometry .t2 +0+0\n    list [update idletasks] [destroy .m1] [destroy .t2]\n} -result {{} {} {}}\n\n\ntest winMenu-34.1 {TkpMenuInit called at boot time} -constraints {\n    emptyTest win\n} -body {}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/winMsgbox.test",
    "content": "# This file is a Tcl script to test the Windows specific message box\n#\n# Copyright © 2007 Pat Thoyts <patthoyts@users.sourceforge.net>\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests that are\n#   platform-indifferent go into the test file msgbox.test.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\ntestConstraint getwindowinfo [expr {[llength [info command ::testgetwindowinfo]] > 0}]\n\n#\n# COMMON TEST SETUP\n#\n\nif {[testConstraint testwinevent]} {\n    catch {testwinevent debug 1}\n}\n\nproc GetWindowInfo {title button} {\n    global windowInfo\n    set windowInfo {}\n    set hwnd [testfindwindow $title \"#32770\"]\n    set windowInfo [testgetwindowinfo $hwnd]\n    array set a $windowInfo\n    set childinfo {} ; set childtext \"\"\n    foreach child $a(children) {\n\tlappend childinfo $child [set info [testgetwindowinfo $child]]\n\tarray set ca $info\n\tif {$ca(class) eq \"Static\"} {\n\t    append childtext $ca(text)\n\t}\n    }\n    set a(children) $childinfo\n    set a(childtext) $childtext\n    set windowInfo [array get a]\n    testwinevent $hwnd $button WM_COMMAND\n}\n\n#\n# TESTS\n#\n\ntest winMsgbox-1.1 {tk_messageBox ok} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.0 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    tk_messageBox -icon info -type ok -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {ok}\n\ntest winMsgbox-1.2 {tk_messageBox okcancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.1 [pid]\"\n    after 100 [list GetWindowInfo $title 1]\n    tk_messageBox -icon info -type okcancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {ok}\n\ntest winMsgbox-1.3 {tk_messageBox okcancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.2 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    tk_messageBox -icon info -type okcancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {cancel}\n\ntest winMsgbox-1.4 {tk_messageBox yesno} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.3 [pid]\"\n    after 100 [list GetWindowInfo $title 6]\n    tk_messageBox -icon info -type yesno -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {yes}\n\ntest winMsgbox-1.5 {tk_messageBox yesno} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.4 [pid]\"\n    after 100 [list GetWindowInfo $title 7]\n    tk_messageBox -icon info -type yesno -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {no}\n\ntest winMsgbox-1.6 {tk_messageBox abortretryignore} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.5 [pid]\"\n    after 100 [list GetWindowInfo $title 3]\n    tk_messageBox -icon info -type abortretryignore -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {abort}\n\ntest winMsgbox-1.7 {tk_messageBox abortretryignore} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.6 [pid]\"\n    after 100 [list GetWindowInfo $title 4]\n    tk_messageBox -icon info -type abortretryignore -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {retry}\n\ntest winMsgbox-1.8 {tk_messageBox abortretryignore} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.7 [pid]\"\n    after 100 [list GetWindowInfo $title 5]\n    tk_messageBox -icon info -type abortretryignore -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {ignore}\n\ntest winMsgbox-1.9 {tk_messageBox retrycancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.8 [pid]\"\n    after 100 [list GetWindowInfo $title 4]\n    tk_messageBox -icon info -type retrycancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {retry}\n\ntest winMsgbox-1.10 {tk_messageBox retrycancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.9 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    tk_messageBox -icon info -type retrycancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {cancel}\n\ntest winMsgbox-1.11 {tk_messageBox yesnocancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.10 [pid]\"\n    after 100 [list GetWindowInfo $title 6]\n    tk_messageBox -icon info -type yesnocancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {yes}\n\ntest winMsgbox-1.12 {tk_messageBox yesnocancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.11 [pid]\"\n    after 100 [list GetWindowInfo $title 7]\n    tk_messageBox -icon info -type yesnocancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {no}\n\ntest winMsgbox-1.13 {tk_messageBox yesnocancel} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n} -body {\n    global windowInfo\n    set title \"winMsgbox-1.12 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    tk_messageBox -icon info -type yesnocancel -title $title -message Message\n} -cleanup {\n    wm deiconify .\n} -result {cancel}\n\n\ntest winMsgbox-2.1 {tk_messageBox message} -constraints {win getwindowinfo} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-2.0 [pid]\"\n    set message \"message\"\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title -message $message]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok \"message\"]\n\ntest winMsgbox-2.2 {tk_messageBox message (long)} -constraints {\n    win getwindowinfo\n} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-2.1 [pid]\"\n    set message [string repeat Ab 80]\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title -message $message]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok [string repeat Ab 80]]\n\ntest winMsgbox-2.3 {tk_messageBox message (unicode)} -constraints {\n    win getwindowinfo\n} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-2.2 [pid]\"\n    set message \"Поиск страниц\"\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title -message $message]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok \"Поиск страниц\"]\n\ntest winMsgbox-2.4 {tk_messageBox message (empty)} -constraints {\n    win getwindowinfo\n} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-2.3 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok \"\"]\n\n\ntest winMsgbox-3.1 {tk_messageBox detail (sourceforge bug #1692927)} -constraints {\n    win getwindowinfo\n} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-3.0 [pid]\"\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title \\\n\t       -message Hello -detail \"Pleased to meet you\"]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok \"Hello\\n\\nPleased to meet you\"]\n\ntest winMsgbox-3.2 {tk_messageBox detail (unicode)} -constraints {\n    win getwindowinfo\n} -setup {\n    wm iconify .\n    unset -nocomplain info\n} -body {\n    global windowInfo\n    set title \"winMsgbox-3.1 [pid]\"\n    set message \"Поиск\"\n    set detail \"страниц\"\n    after 100 [list GetWindowInfo $title 2]\n    set r [tk_messageBox -type ok -title $title -message $message -detail $detail]\n    array set info $windowInfo\n    lappend r $info(childtext)\n} -cleanup {\n    wm deiconify .\n} -result [list ok \"Поиск\\n\\nстраниц\"]\n\n#\n# TESTFILE CLEANUP\n#\n\nif {[testConstraint testwinevent]} {\n    catch {testwinevent debug 0}\n}\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# indent-tabs-mode: nil\n# End:\n"
  },
  {
    "path": "tests/winSend.test",
    "content": "# This file is a Tcl script to test out the \"send\" command and the\n# other procedures in the file tkSend.c.\n#\n# Copyright © 1994 Sun Microsystems, Inc.\n# Copyright © 1994-1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests that are\n#   platform-indifferent go into the test file send.test.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import child\n\n#\n# COMMON TEST SETUP\n#\n\nset currentInterps [winfo interps]\n\n#\n# LOCAL TEST CONSTRAINTS\n#\n\nif {\n    [testConstraint win] &&\n    [llength [info commands send]] &&\n    [catch {exec [interpreter] &}] == 0\n} then {\n    # Wait until the child application has launched.\n    while {[llength [winfo interps]] == [llength $currentInterps]} {}\n\n    # Now find an interp to send to\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch -exact $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n\n    # Now we have found our interpreter we are going to send to.\n    # Make sure that it works first.\n    testConstraint winSend [expr {![catch {\n\tsend $interp {\n\t    console hide\n\t    update\n\t}\n    }]}]\n} else {\n    testConstraint winSend 0\n}\n\n#\n# TESTS\n#\n\n# setting up dde server is done when the first interp is created and\n# cannot be tested very easily.\ntest winSend-1.1 {Tk_SetAppName - changing name of interp} winSend {\n    childTkInterp testApp\n    list [testApp eval tk appname testApp2] [interp delete testApp]\n} {testApp2 {}}\ntest winSend-1.2 {Tk_SetAppName - changing name - not front of linked list} winSend {\n    childTkInterp testApp\n    childTkInterp testApp2\n    list [testApp eval tk appname testApp3] [interp delete testApp] [interp delete testApp2]\n} {testApp3 {} {}}\ntest winSend-1.3 {Tk_SetAppName - unique name - no conflicts} winSend {\n    childTkInterp testApp\n    list [testApp eval tk appname testApp] [interp delete testApp]\n} {testApp {}}\ntest winSend-1.4 {Tk_SetAppName - unique name - one conflict} winSend {\n    childTkInterp testApp\n    childTkInterp foobar\n    list [foobar eval tk appname testApp] [interp delete foobar] [interp delete testApp]\n} {{testApp #2} {} {}}\ntest winSend-1.5 {Tk_SetAppName - unique name - one conflict} winSend {\n    childTkInterp testApp\n    childTkInterp foobar\n    childTkInterp blaz\n    foobar eval tk appname testApp\n    list [blaz eval tk appname testApp] [interp delete foobar] [interp delete testApp] [interp delete blaz]\n} {{testApp #3} {} {} {}}\ntest winSend-1.6 {Tk_SetAppName - safe interps} winSend {\n    childTkInterp testApp -safe\n    list [catch {testApp eval send testApp {set foo a}} msg] $msg [interp delete testApp]\n} {1 {invalid command name \"send\"} {}}\n\ntest winSend-2.1 {Tk_SendObjCmd - # of args} winSend {\n    list [catch {send tktest} msg] $msg\n} {1 {wrong # args: should be \"send ?-option value ...? interpName arg ?arg ...?\"}}\ntest winSend-2.1a {Tk_SendObjCmd: arguments} winSend {\n    list [catch {send -bogus tktest} msg] $msg\n} {1 {bad option \"-bogus\": must be -async, -displayof, or --}}\ntest winSend-2.1b {Tk_SendObjCmd: arguments} winSend {\n    list [catch {send -async bogus foo} msg] $msg\n} {1 {no registered server named \"bogus\"}}\ntest winSend-2.1c {Tk_SendObjCmd: arguments} winSend {\n    list [catch {send -displayof . bogus foo} msg] $msg\n} {1 {no registered server named \"bogus\"}}\ntest winSend-2.1d {Tk_SendObjCmd: arguments} winSend {\n    list [catch {send -- -bogus foo} msg] $msg\n} {1 {no registered server named \"-bogus\"}}\ntest winSend-2.2 {Tk_SendObjCmd - sending to ourselves} winSend {\n    list [send [tk appname] {set foo a}]\n} {a}\ntest winSend-2.3 {Tk_SendObjCmd - sending to ourselves in a different interpreter} winSend {\n    childTkInterp testApp\n    list [catch {send testApp {set foo b}} msg] $msg [interp delete testApp]\n} {0 b {}}\ntest winSend-2.4 {Tk_SendObjCmd - sending to ourselves in a different interp with errors} winSend {\n    childTkInterp testApp\n    list [catch {send testApp {expr {2 / 0}}} msg] $msg $errorCode $errorInfo [interp delete testApp]\n} \"1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\\n    while executing\\n\\\"expr {2 / 0}\\\"\\n    invoked from within\\n\\\"send testApp {expr {2 / 0}}\\\"} {}\"\ntest winSend-2.5 {Tk_SendObjCmd - sending to another app async} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {send -async $interp {set foo a}} msg] $msg\n} {0 {}}\ntest winSend-2.6 {Tk_SendObjCmd - sending to another app sync - no error} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {send $interp {set foo a}} msg] $msg\n} {0 a}\ntest winSend-2.7 {Tk_SendObjCmd - sending to another app - error} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {send $interp {expr {2 / 0}}} msg] $msg $errorCode $errorInfo\n} \"1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\\n    while executing\\n\\\"expr {2 / 0}\\\"\\n    invoked from within\\n\\\"send \\$interp {expr {2 / 0}}\\\"}\"\n\ntest winSend-3.1 {TkGetInterpNames} winSend {\n    set origLength [llength $currentInterps]\n    set newLength [llength [winfo interps]]\n    expr {($newLength - 2) == $origLength}\n} 1\n\ntest winSend-4.1 {DeleteProc - changing name of app} winSend {\n    childTkInterp a\n    list [a eval tk appname foo] [interp delete a]\n} {foo {}}\ntest winSend-4.2 {DeleteProc - normal} winSend {\n    childTkInterp a\n    list [interp delete a]\n} {{}}\n\ntest winSend-5.1 {ExecuteRemoteObject - no error} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [send $interp {send [tk appname] {expr {2 / 1}}}]\n} 2\ntest winSend-5.2 {ExecuteRemoteObject - error} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {send $interp {send [tk appname] {expr {2 / 0}}}} msg] $msg\n} {1 {divide by zero}}\n\ntest winSend-6.1 {SendDDEServer - XTYP_CONNECT} winSend {\n    set foo \"Hello, World\"\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde request Tk [tk appname] foo\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 {Hello, World}}\ntest winSend-6.2 {SendDDEServer - XTYP_CONNECT_CONFIRM} winSend {\n    set foo \"Hello, World\"\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde request Tk [tk appname] foo\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 {Hello, World}}\ntest winSend-6.3 {SendDDEServer - XTYP_DISCONNECT} winSend {\n    set foo \"Hello, World\"\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde request Tk [tk appname] foo\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 {Hello, World}}\ntest winSend-6.4 {SendDDEServer - XTYP_REQUEST variable} winSend {\n    set foo \"Hello, World\"\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde request Tk [tk appname] foo\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 {Hello, World}}\ntest winSend-6.5 {SendDDEServer - XTYP_REQUEST array} winSend {\n    catch {unset foo}\n    set foo(test) \"Hello, World\"\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde request Tk [tk appname] foo(test)\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg [catch {unset foo}]\n} {0 {Hello, World} 0}\ntest winSend-6.6 {SendDDEServer - XTYP_REQUEST return results} winSend {\n    set foo 3\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"send [tk appname] {expr {$foo + 1}}\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 4}\ntest winSend-6.7 {SendDDEServer - XTYP_EXECUTE} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"send [tk appname] {expr {4 / 2}}\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\" msg] $msg\n} {0 2}\ntest winSend-6.8 {SendDDEServer - XTYP_WILDCONNECT} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    set command \"dde services Tk {}\"\n    list [catch \"send \\{$interp\\} \\{$command\\}\"]\n} 0\n\ntest winSend-7.1 {DDEExitProc} winSend {\n    childTkInterp testApp\n    list [interp delete testApp]\n} {{}}\n\ntest winSend-8.1 {SendDdeConnect} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [send $interp {set tk foo}]\n} {foo}\n\ntest winSend-9.1 {SetDDEError} winSend {\n    list [catch {dde execute Tk foo {set foo hello}} msg] $msg\n} {1 {dde command failed}}\n\ntest winSend-10.1 {Tk_DDEObjCmd - wrong num args} winSend {\n    list [catch {dde} msg] $msg\n} {1 {wrong # args: should be \"dde ?-async? serviceName topicName value\"}}\ntest winSend-10.2 {Tk_DDEObjCmd - unknown subcommand} winSend {\n    list [catch {dde foo} msg] $msg\n} {1 {bad command \"foo\": must be execute, request, or services}}\ntest winSend-10.3 {Tk_DDEObjCmd - execute - wrong num args} winSend {\n    list [catch {dde execute} msg] $msg\n} {1 {wrong # args: should be \"dde execute ?-async? serviceName topicName value\"}}\ntest winSend-10.4 {Tk_DDEObjCmd - execute - wrong num args} winSend {\n    list [catch {dde execute 3 4 5 6 7} msg] $msg\n} {1 {wrong # args: should be \"dde execute ?-async? serviceName topicName value\"}}\ntest winSend-10.5 {Tk_DDEObjCmd - execute async - wrong num args} winSend {\n    list [catch {dde execute -async} msg] $msg\n} {1 {wrong # args: should be \"dde execute ?-async? serviceName topicName value\"}}\ntest winSend-10.6 {Tk_DDEObjCmd - request - wrong num args} winSend {\n    list [catch {dde request} msg] $msg\n} {1 {wrong # args: should be \"dde request serviceName topicName value\"}}\ntest winSend-10.7 {Tk_DDEObjCmd - services wrong num args} winSend {\n    list [catch {dde services} msg] $msg\n} {1 {wrong # args: should be \"dde services serviceName topicName\"}}\ntest winSend-10.8 {Tk_DDEObjCmd - null service name} winSend {\n    list [catch {dde services {} {tktest #2}}]\n} 0\ntest winSend-10.9 {Tk_DDEObjCmd - null topic name} winSend {\n    list [catch {dde services {Tk} {}}]\n} 0\ntest winSend-10.10 {Tk_DDEObjCmd - execute - nothing to execute} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {dde execute Tk $interp {}} msg] $msg\n} {1 {cannot execute null data}}\ntest winSend-10.11 {Tk_DDEObjCmd - execute - no such conversation} winSend {\n    list [catch {dde execute Tk foo {set foo hello}} msg] $msg\n} {1 {dde command failed}}\ntest winSend-10.12 {Tk_DDEObjCmd - execute - async} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {dde execute -async Tk $interp {set foo hello}} msg] $msg\n} {0 {}}\ntest winSend-10.13 {Tk_DDEObjCmd - execute} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {dde execute Tk $interp {set foo goodbye}} msg] $msg\n} {0 {}}\ntest winSend-10.14 {Tk_DDEObjCmd - request - nothing to request} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {dde request Tk $interp {}} msg] $msg\n} {1 {cannot request value of null data}}\ntest winSend-10.15 {Tk_DDEObjCmd - request - invalid interp} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    list [catch {dde request Tk foo foo} msg] $msg\n} {1 {dde command failed}}\ntest winSend-10.16 {Tk_DDEObjCmd - invalid variable} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    send $interp {unset foo}\n    list [catch {dde request Tk $interp foo} msg] $msg\n} {1 {remote server cannot handle this command}}\ntest winSend-10.17 {Tk_DDEObjCmd - valid variable} winSend {\n    set newInterps [winfo interps]\n    foreach interp $newInterps {\n\tif {[lsearch $currentInterps $interp] < 0} {\n\t    break\n\t}\n    }\n    send $interp {set foo winSend-10.17}\n    list [catch {dde request Tk $interp foo} msg] $msg\n} {0 winSend-10.17}\ntest winSend-10.18 {Tk_DDEObjCmd - services} winSend {\n    set currentService [list Tk [tk appname]]\n    list [catch {dde services Tk {}} msg] [expr {[lsearch $msg $currentService] >= 0}]\n} {0 1}\n\n#\n# TESTFILE CLEANUP\n#\n\n# Get rid of the other app and all of its interps\n\nset newInterps [winfo interps]\nwhile {[llength $newInterps] != [llength $currentInterps]} {\n    foreach interp $newInterps {\n\tif {[lsearch -exact $currentInterps $interp] < 0} {\n\t    catch {send $interp exit}\n\t    set newInterps [winfo interps]\n\t    break\n\t}\n    }\n}\n\ntestutils forget child\ncleanupTests\n"
  },
  {
    "path": "tests/winWm.test",
    "content": "# This file is a Tcl script to test out interactions with the window manager\n# that are specific for the windows platform, including the \"wm\" command\n# (these are implemented in the file tkWinWm.c).\n#\n# Copyright © 1996 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTES\n#\n# * This test file is specific for the MS Windows platform. Tests regarding\n#   the window manager that are specific to the unix platform (this includes\n#   macOS) go into the test file unixWm.test. Tests that are platform-indifferent\n#   go into test file wm.test. Or they may exists as each other's counterparts\n#   in both unixWm.test and winWm.test, but only if they are an integral part\n#   of a contiguous sequence of tests.\n# * This test file is skipped entirely on non-windows platforms.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# TESTS\n#\n\ntest winWm-1.1 {TkWmMapWindow} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm override .t 1\n    wm geometry .t +0+0\n    update\n    list [winfo rootx .t] [winfo rooty .t]\n} -cleanup {\n    destroy .t\n} -result {0 0}\ntest winWm-1.2 {TkWmMapWindow} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm transient .t .\n    update\n    wm iconify .\n    update\n    wm deiconify .\n    update\n    wm iconify .t\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {can't iconify \".t\": it is a transient}\ntest winWm-1.3 {TkWmMapWindow} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    update\n    toplevel .t2\n    update\n    expr {[winfo x .t] != [winfo x .t2]}\n} -cleanup {\n    destroy .t .t2\n} -result 1\ntest winWm-1.4 {TkWmMapWindow} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t +10+10\n    update\n    toplevel .t2\n    wm geometry .t2 +40+10\n    update\n    list [winfo x .t] [winfo x .t2]\n} -cleanup {\n    destroy .t .t2\n} -result {10 40}\ntest winWm-1.5 {TkWmMapWindow} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm iconify .t\n    update\n    wm state .t\n} -result {iconic}\n\n\ntest winWm-2.1 {TkpWmSetState} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t 150x50+10+10\n    update\n    set result [wm state .t]\n    wm iconify .t\n    update\n    lappend result [wm state .t]\n    wm deiconify .t\n    update\n    lappend result [wm state .t]\n} -cleanup {\n    destroy .t\n} -result {normal iconic normal}\ntest winWm-2.2 {TkpWmSetState} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t 150x50+10+10\n    update\n    set result [wm state .t]\n    wm withdraw .t\n    update\n    lappend result [wm state .t]\n    wm iconify .t\n    update\n    lappend result [wm state .t]\n    wm deiconify .t\n    update\n    lappend result [wm state .t]\n} -cleanup {\n    destroy .t\n} -result {normal withdrawn iconic normal}\ntest winWm-2.3 {TkpWmSetState} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t 150x50+10+10\n    update\n    set result [wm state .t]\n    wm state .t withdrawn\n    update\n    lappend result [wm state .t]\n    wm state .t iconic\n    update\n    lappend result [wm state .t]\n    wm state .t normal\n    update\n    lappend result [wm state .t]\n} -cleanup {\n    destroy .t\n} -result {normal withdrawn iconic normal}\ntest winWm-2.4 {TkpWmSetState} -constraints win -setup {\n    destroy .t\n    set result {}\n} -body {\n    toplevel .t\n    wm geometry .t 150x50+10+10\n    update\n    lappend result [list [wm state .t] [wm geometry .t]]\n    wm iconify .t\n    update\n    lappend result [list [wm state .t] [wm geometry .t]]\n    wm geometry .t 200x50+10+10\n    update\n    lappend result [list [wm state .t] [wm geometry .t]]\n    wm deiconify .t\n    update\n    lappend result [list [wm state .t] [wm geometry .t]]\n} -cleanup {\n    destroy .t\n} -result {{normal 150x50+10+10} {iconic 150x50+10+10} {iconic 150x50+10+10} {normal 200x50+10+10}}\n\n\ntest winWm-3.1 {ConfigureTopLevel: window geometry propagation} -constraints {\n    win\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm geometry .t +0+0\n    button .t.b\n    pack .t.b\n    update\n    set x [winfo x .t.b]\n    destroy .t\n    toplevel .t\n    wm geometry .t +0+0\n    button .t.b\n    update\n    pack .t.b\n    update\n    expr {$x == [winfo x .t.b]}\n} -cleanup {\n    destroy .t\n} -result 1\n\n\ntest winWm-4.1 {ConfigureTopLevel: menu resizing} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    frame .t.f -width 100 -height 50\n    pack .t.f\n    menu .t.m\n    .t.m add command -label \"thisisreallylong\"\n    .t configure -menu .t.m\n    wm geometry .t -0-0\n    update\n    set menuheight [winfo y .t]\n    .t.m add command -label \"thisisreallylong\"\n    wm geometry .t -0-0\n    update\n    set menuheight [expr {$menuheight - [winfo y .t]}]\n    destroy .t\n\n    toplevel .t\n    frame .t.f -width 150 -height 50 -background red\n    pack .t.f\n    wm geometry .t -0-0\n    update\n    set y [winfo y .t]\n    menu .t.m\n    .t.m add command -label foo\n    .t configure -menu .t.m\n    update\n    expr {$y - [winfo y .t]  eq  $menuheight + 1}\n} -cleanup {\n    destroy .t\n} -result 1\n\n\n# This test works on 8.0p2 but has not worked on anything since 8.2.\n# It would be very strange to have a windows application increase the size\n# of the clientarea when a menu wraps so I believe this test to be wrong.\n# Original result was {50 50 50} new result may depend on the default menu\n# font\ntest winWm-5.1 {UpdateGeometryInfo: menu resizing} -constraints win -setup {\n    destroy .t\n    set result {}\n} -body {\n    toplevel .t\n    frame .t.f -width 150 -height 50 -background red\n    pack .t.f\n    update\n    set result [winfo height .t]\n    menu .t.m\n    .t.m add command -label foo\n    .t configure -menu .t.m\n    update\n    lappend result [winfo height .t]\n    .t.m add command -label \"thisisreallylong\"\n    .t.m add command -label \"thisisreallylong\"\n    update\n    lappend result [winfo height .t]\n} -cleanup {\n    destroy .t\n} -result {50 50 31}\ntest winWm-5.2 {UpdateGeometryInfo: menu resizing} -constraints win -setup {\n    destroy .t\n} -body {\n    set result {}\n    toplevel .t\n    frame .t.f -width 150 -height 50 -background red\n    pack .t.f\n    wm geometry .t -0-0\n    update\n    set y [winfo rooty .t]\n    lappend result [winfo height .t]\n    menu .t.m -tearoff 1\n    .t configure -menu .t.m\n    .t.m add command -label foo\n    .t.m add command -label \"thisisreallylong\"\n    .t.m add command -label \"thisisreallylong\"\n    update\n    lappend result [winfo height .t]\n    lappend result [expr {$y - [winfo rooty .t]}]\n    destroy .t\n    return $result\n} -cleanup {\n    destroy .t\n} -result {50 50 0}\n\ntest winWm-6.1 {wm attributes} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm attributes .t\n} -cleanup {\n    destroy .t\n} -result {-alpha 1.0 -transparentcolor {} -disabled 0 -fullscreen 0 -toolwindow 0 -topmost 0}\ntest winWm-6.2 {wm attributes} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm attributes .t -disabled\n} -cleanup {\n    destroy .t\n} -result 0\ntest winWm-6.3 {wm attributes} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm attributes .t -foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad attribute \"-foo\": must be -alpha, -disabled, -fullscreen, -toolwindow, -topmost, or -transparentcolor}\n\ntest winWm-6.4 {wm attributes -alpha} -constraints win -setup {\n    destroy .t\n} -body {\n    # Expect this to return all 1.0 {} on pre-2K/XP\n    toplevel .t\n    set res [wm attributes .t -alpha]\n    # we don't return on set yet\n    lappend res [wm attributes .t -alpha 0.5]\n    lappend res [wm attributes .t -alpha]\n    lappend res [wm attributes .t -alpha -100]\n    lappend res [wm attributes .t -alpha]\n    lappend res [wm attributes .t -alpha 100]\n    lappend res [wm attributes .t -alpha]\n    return $res\n} -cleanup {\n    destroy .t\n} -result {1.0 {} 0.5 {} 0.0 {} 1.0}\n\ntest winWm-6.5 {wm attributes -alpha} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    wm attributes .t -alpha foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {expected floating-point number but got \"foo\"}\n\ntest winWm-6.6 {wm attributes -alpha} -constraints win -setup {\n    destroy .t\n} -body {\n    # This test is just to show off -alpha\n    toplevel .t\n    wm attributes .t -alpha 0.2\n    pack [label .t.l -text \"Alpha Toplevel\" -font \"Helvetica 18 bold\"]\n    tk::PlaceWindow .t center\n    update\n    if {$::tcl_platform(osVersion) >= 5.0} {\n    for {set i 0.2} {$i < 0.99} {set i [expr {$i+0.02}]} {\n\twm attributes .t -alpha $i\n\tupdate idle\n\tafter 20\n    }\n    for {set i 0.99} {$i > 0.2} {set i [expr {$i-0.02}]} {\n\twm attributes .t -alpha $i\n\tupdate idle\n\tafter 20\n    }\n    }\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest winWm-6.7 {wm attributes -transparentcolor} -constraints win -setup {\n    destroy .t\n    set res {}\n} -body {\n    # Expect this to return all \"\" on pre-2K/XP\n    toplevel .t\n    lappend res [wm attributes .t -transparentcolor]\n    # we don't return on set yet\n    lappend res [wm attributes .t -trans black]\n    lappend res [wm attributes .t -trans]\n    lappend res [wm attributes .t -trans \"#FFFFFF\"]\n    lappend res [wm attributes .t -trans]\n} -cleanup {\n    destroy .t\n} -result [list {} {} black {} \"#FFFFFF\"]\n\ntest winWm-6.8 {wm attributes -transparentcolor} -constraints win -setup {\n    destroy .t\n} -body {\n    destroy .t\n    toplevel .t\n    wm attributes .t -tr foo\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {unknown color name \"foo\"}\n\n\ntest winWm-7.1 {deiconify on an unmapped toplevel will raise \\\n\tthe window and set the focus} -constraints {\n    win\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    lower .t\n    focus -force .\n    wm deiconify .t\n    update\n    list [wm stackorder .t isabove .] [focus]\n} -cleanup {\n    destroy .t\n} -result {1 .t}\n\ntest winWm-7.2 {deiconify on an already mapped toplevel\\\n\twill raise the window and set the focus} -constraints {\n    win\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    lower .t\n    update\n    focus -force .\n    wm deiconify .t\n    update\n    list [wm stackorder .t isabove .] [focus]\n} -cleanup {\n    destroy .t\n} -result {1 .t}\n\ntest winWm-7.3 {UpdateWrapper must maintain Z order} -constraints win -setup {\n    destroy .t\n} -body {\n    destroy .t\n    toplevel .t\n    lower .t\n    update\n    set res [wm stackorder .t isbelow .]\n    wm resizable .t 0 0\n    update\n    list $res [wm stackorder .t isbelow .]\n} -cleanup {\n    destroy .t\n} -result {1 1}\n\ntest winWm-7.4 {UpdateWrapper must maintain focus} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    focus -force .t\n    update\n    set res [focus]\n    wm resizable .t 0 0\n    update\n    list $res [focus]\n} -cleanup {\n    destroy .t\n} -result {.t .t}\n\n\ntest winWm-8.1 {Tk_WmCmd procedure, \"iconphoto\" option} -constraints win -body {\n    wm iconph .\n} -returnCodes error -result {wrong # args: should be \"wm iconphoto window ?-default? image1 ?image2 ...?\"}\ntest winWm-8.2 {Tk_WmCmd procedure, \"iconphoto\" option} -constraints win -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    image create photo blank16 -width 16 -height 16\n    image create photo blank32 -width 32 -height 32\n    # This should just make blank icons for the window\n    wm iconphoto .t blank16 blank32\n    image delete blank16 blank32\n} -cleanup {\n    destroy .t\n} -result {}\n\ntest winWm-9.0 \"Bug #2799589 - delayed activation of destroyed window\" -constraints win -setup {\n    proc winwm90click {w} {\n\tif {![winfo ismapped $w]} { update }\n\tevent generate $w <Enter>\n\tfocus -force $w\n\tevent generate $w <Button-1> -x 5 -y 5\n\tevent generate $w <ButtonRelease-1> -x 5 -y 5\n    }\n    proc winwm90proc3 {} {\n\tglobal winwm90done winwm90check\n\tset w .sd\n\ttoplevel $w\n\tpack [button $w.b -text \"OK\" -command {set winwm90check 1}]\n\tbind $w.b <Map> {after idle {winwm90click %W}}\n\tupdate idletasks\n\ttkwait visibility $w\n\tgrab $w\n\ttkwait variable winwm90check\n\tgrab release $w\n\tdestroy $w\n\tafter idle {set winwm90done ok}\n    }\n    proc winwm90proc2 {w} { winwm90proc3; destroy $w }\n    proc winwm90proc1 {w} {\n\ttoplevel $w\n\tpack [button $w.b -text \"Do dialog\" -command [list winwm90proc2 $w]]\n\tbind $w.b <Map> {bind %W <Map> {}; after idle {winwm90click %W}}\n    }\n    global winwm90done\n    set winwm90done wait\n    toplevel .t\n} -body {\n    pack [button .t.b -text \"Show\" -command {winwm90proc1 .tx}]\n    bind .t.b <Map> {bind %W <Map> {}; after idle {winwm90click %W}}\n    after 5000 {set winwm90done timeout}\n    vwait winwm90done\n    set winwm90done\n} -cleanup {\n    foreach cmd {proc1 proc2 proc3 click} {\n\trename winwm90$cmd {}\n    }\n    destroy .tx .t .sd\n} -result ok\n\ntest winWm-9.1 \"delayed activation of grabbed destroyed window\" -constraints win -setup {\n    proc winwm91click {w} {\n\tif {![winfo ismapped $w]} { update }\n\tevent generate $w <Enter>\n\tfocus -force $w\n\tevent generate $w <Button-1> -x 5 -y 5\n\tevent generate $w <ButtonRelease-1> -x 5 -y 5\n    }\n    proc winwm91proc3 {} {\n\tglobal winwm91done winwm91check\n\tset w .sd\n\ttoplevel $w\n\tpack [button $w.b -text \"OK\" -command {set winwm91check 1}]\n\tbind $w.b <Map> {after idle {winwm91click %W}}\n\tupdate idletasks\n\ttkwait visibility $w\n\tgrab $w\n\ttkwait variable winwm91check\n\t#skip the release:  #grab release $w\n\tdestroy $w\n\tafter idle {set winwm91done ok}\n    }\n    proc winwm91proc2 {w} { winwm91proc3; destroy $w }\n    proc winwm91proc1 {w} {\n\ttoplevel $w\n\tpack [button $w.b -text \"Do dialog\" -command [list winwm91proc2 $w]]\n\tbind $w.b <Map> {bind %W <Map> {}; after idle {winwm91click %W}}\n    }\n    destroy .t\n    global winwm91done\n    set winwm91done wait\n    toplevel .t\n} -body {\n    pack [button .t.b -text \"Show\" -command {winwm91proc1 .tx}]\n    bind .t.b <Map> {bind %W <Map> {}; after idle {winwm91click %W}}\n    after 5000 {set winwm91done timeout}\n    vwait winwm91done\n    set winwm91done\n} -cleanup {\n    foreach cmd {proc1 proc2 proc3 click} {\n\trename winwm91$cmd {}\n    }\n    destroy .tx .t .sd\n} -result ok\n\n#\n# Moved test winWm-9.2 to wm-forget-1.5 in wm.test (cf. ticket #83eed90f93).\n#\n\n#\n# TESTFILE CLEANUP\n#\n\ndestroy .t\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/window.test",
    "content": "# This file is a Tcl script to test the procedures in the file\n# tkWindow.c.\n#\n# Copyright © 1995 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This file is woefully incomplete.  Right now it only tests\n# a few parts of a few procedures in tkWindow.c\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# COMMON TEST SETUP\n#\n\nupdate\n# Move the mouse out of the way for window-2.1\nevent generate {} <Motion> -warp 1 -x 640 -y 10\n\n#\n# TESTS\n#\n\ntest window-1.1 {Tk_CreateWindowFromPath procedure, parent dead} -setup {\n    destroy .t\n} -body {\n    proc bgerror msg {\n\tglobal x errorInfo\n\tset x [list $msg $errorInfo]\n    }\n\n    set x unchanged\n    frame .t -width 100 -height 50\n    place .t -x 10 -y 10\n    bind .t <Destroy> {button .t.b -text hello; pack .t.b}\n    update\n    destroy .t\n    update\n    set x\n} -cleanup {\n    rename bgerror {}\n} -result {{can't create window: parent has been destroyed} {can't create window: parent has been destroyed\n    while executing\n\"button .t.b -text hello\"\n    (command bound to event)}}\n\n\n# Most of the tests below don't produce meaningful results;  they\n# will simply dump core if there are bugs.\n\ntest window-2.1 {Tk_DestroyWindow procedure, destroy handler deletes parent} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200\n    wm geometry .t +0+0\n    frame .t.f  -width 200 -height 200 -relief raised -bd 2\n    place .t.f -x 0 -y 0\n    frame .t.f.f -width 100 -height 100 -relief raised -bd 2\n    place .t.f.f -relx 1 -rely 1 -anchor se\n    bind .t.f <Destroy> {destroy .t}\n    update\n    destroy .t.f\n} -result {}\ntest window-2.2 {Tk_DestroyWindow procedure, destroy handler deletes parent} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200\n    wm geometry .t +0+0\n    frame .t.f  -width 200 -height 200 -relief raised -bd 2\n    place .t.f -x 0 -y 0\n    frame .t.f.f -width 100 -height 100 -relief raised -bd 2\n    place .t.f.f -relx 1 -rely 1 -anchor se\n    bind .t.f.f <Destroy> {destroy .t}\n    update\n    destroy .t.f\n} -result {}\ntest window-2.3 {Tk_DestroyWindow procedure, destroy handler deletes parent} -setup {\n    destroy .f\n} -body {\n    frame .f -width 80 -height 120 -relief raised -bd 2\n    place .f -relx 0.5 -rely 0.5 -anchor center\n    toplevel .f.t -width 300 -height 200\n    wm geometry .f.t +0+0\n    frame .f.t.f  -width 200 -height 200 -relief raised -bd 2\n    place .f.t.f -x 0 -y 0\n    frame .f.t.f.f -width 100 -height 100 -relief raised -bd 2\n    place .f.t.f.f -relx 1 -rely 1 -anchor se\n    update\n    destroy .f\n} -result {}\n\ntest window-2.4 {Tk_DestroyWindow, cleanup half dead window at exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\tupdate\n\tbind . <Destroy> exit\n\tdestroy .\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {}}\n\ntest window-2.5 {Tk_DestroyWindow, cleanup half dead windows at exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t\n\tupdate\n\tbind .t <Destroy> exit\n\tdestroy .t\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {}}\n\ntest window-2.6 {Tk_DestroyWindow, cleanup half dead windows at exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t\n\tupdate\n\tbind .t <Destroy> exit\n\tdestroy .\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {}}\n\ntest window-2.7 {Tk_DestroyWindow, cleanup half dead windows at exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t\n\ttoplevel .t.f\n\tupdate\n\tbind .t.f <Destroy> exit\n\tdestroy .\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {}}\n\ntest window-2.8 {Tk_DestroyWindow, cleanup half dead windows at exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t1\n\ttoplevel .t2\n\ttoplevel .t3\n\tupdate\n\tbind .t3 <Destroy> {destroy .t2}\n\tbind .t2 <Destroy> {destroy .t1}\n\tbind .t1 <Destroy> {exit 0}\n\tdestroy .t3\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {}}\n\ntest window-2.9 {Tk_DestroyWindow, Destroy bindings evaluated after exit} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t1\n\ttoplevel .t2\n\tupdate\n\tbind .t2 <Destroy> {puts \"Destroy .t2\" ; exit 1}\n\tbind .t1 <Destroy> {puts \"Destroy .t1\" ; exit 0}\n\tdestroy .t2\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {Destroy .t2\nDestroy .t1}}\n\ntest window-2.10 {Tk_DestroyWindow, Destroy binding evaluated once} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\tupdate\n\tbind . <Destroy> {\n\t    puts \"Destroy .\"\n\t    bind . <Destroy> {puts \"Re-Destroy .\"}\n\t    exit 0\n\t}\n\tdestroy .\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {Destroy .}}\n\ntest window-2.11 {Tk_DestroyWindow, don't reanimate a half-dead window} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\ttoplevel .t1\n\ttoplevel .t2\n\tupdate\n\tbind .t1 <Destroy> {\n\t    if {[catch {entry .t2.newchild}]} {\n\t\tputs YES\n\t    } else {\n\t\tputs NO\n\t    }\n\t}\n\tbind .t2 <Destroy> {exit}\n\tdestroy .t2\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 YES}\n\ntest window-2.12 {Test for ticket [9b6065d1fd] - restore Tcl [update] command} -constraints {\n    unixOrWin\n} -body {\n    set code [loadTkCommand]\n    append code {\n\tafter 1000 {set forever 1}\n\tafter 100 {destroy .}\n\tafter 200 {catch bell msg; puts \"ringing the bell -> $msg\"}\n\tafter 250 {update idletasks}\n\tafter 300 {update}\n\tputs \"waiting\"\n\tvwait forever\n\tputs \"done waiting\"\n\tcatch {bell} msg\n\tputs \"bell -> $msg\"\n\tcatch update msg\n\tputs \"update -> $msg\"\n    }\n    set script [makeFile $code script]\n    if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} {\n\tset error 1\n    } else {\n\tset error 0\n    }\n    removeFile script\n    list $error $msg\n} -result {0 {waiting\nringing the bell -> cannot invoke \"bell\" command: application has been destroyed\ndone waiting\nbell -> cannot invoke \"bell\" command: application has been destroyed\nupdate -> }}\n\n\ntest window-3.1 {Tk_MakeWindowExist procedure, stacking order and menubars} -constraints {\n    unix testmenubar\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200\n    wm geometry .t +0+0\n    pack [entry .t.e]\n    frame .t.f -bd 2 -relief raised\n    testmenubar window .t .t.f\n    update\n    # If stacking order isn't handle properly, generates an X error.\n} -cleanup {\n    destroy .t\n} -result {}\ntest window-3.2 {Tk_MakeWindowExist procedure, stacking order and menubars} -constraints {\n    unix testmenubar\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200\n    wm geometry .t +0+0\n    pack [entry .t.e]\n    pack [entry .t.e2]\n    update\n    frame .t.f -bd 2 -relief raised\n    raise .t.f .t.e\n    testmenubar window .t .t.f\n    update\n    # If stacking order isn't handled properly, generates an X error.\n} -cleanup {\n    destroy .t\n} -result {}\n\n\ntest window-4.1 {Tk_NameToWindow procedure} -constraints {\n    testmenubar\n} -setup {\n    destroy .t\n} -body {\n    winfo geometry .t\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {bad window path name \".t\"}\ntest window-4.2 {Tk_NameToWindow procedure} -constraints {\n    testmenubar\n} -setup {\n    destroy .t\n} -body {\n    frame .t -width 100 -height 50\n    place .t -x 10 -y 10\n    update\n    winfo geometry .t\n} -cleanup {\n    destroy .t\n} -returnCodes ok -result {100x50+10+10}\n\n\ntest window-5.1 {Tk_MakeWindowExist procedure, stacking order and menubars} -constraints {\n    unix testmenubar\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 300 -height 200\n    wm geometry .t +0+0\n    pack [entry .t.e]\n    pack [entry .t.e2]\n    frame .t.f -bd 2 -relief raised\n    testmenubar window .t .t.f\n    update\n    lower .t.e2 .t.f\n    update\n    # If stacking order isn't handled properly, generates an X error.\n} -cleanup {\n    destroy .t\n} -result {}\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/winfo.test",
    "content": "# This file is a Tcl script to test out the \"winfo\" command.\n#\n# Copyright © 1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is woefully incomplete.  At present, only a\n# few of the winfo options are tested.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n# Import utility procs for specific functional areas\ntestutils import colors\n\n#\n# TESTS\n#\n\ntest winfo-1.1 {\"winfo atom\" command} -body {\n    winfo atom\n} -returnCodes error -result {wrong # args: should be \"winfo atom ?-displayof window? name\"}\ntest winfo-1.2 {\"winfo atom\" command} -body {\n    winfo atom a b\n} -returnCodes error -result {wrong # args: should be \"winfo atom ?-displayof window? name\"}\ntest winfo-1.3 {\"winfo atom\" command} -body {\n    winfo atom a b c d\n} -returnCodes error -result {wrong # args: should be \"winfo atom ?-displayof window? name\"}\ntest winfo-1.4 {\"winfo atom\" command} -body {\n    winfo atom -displayof geek foo\n} -returnCodes error -result {bad window path name \"geek\"}\ntest winfo-1.5 {\"winfo atom\" command} -body {\n    winfo atom PRIMARY\n} -result 1\ntest winfo-1.6 {\"winfo atom\" command} -body {\n    winfo atom -displayof . PRIMARY\n} -result 1\n\n\ntest winfo-2.1 {\"winfo atomname\" command} -body {\n    winfo atomname\n} -returnCodes error -result {wrong # args: should be \"winfo atomname ?-displayof window? id\"}\ntest winfo-2.2 {\"winfo atomname\" command} -body {\n    winfo atomname a b\n} -returnCodes error -result {wrong # args: should be \"winfo atomname ?-displayof window? id\"}\ntest winfo-2.3 {\"winfo atomname\" command} -body {\n    winfo atomname a b c d\n} -returnCodes error -result {wrong # args: should be \"winfo atomname ?-displayof window? id\"}\ntest winfo-2.4 {\"winfo atomname\" command} -body {\n    winfo atomname -displayof geek foo\n} -returnCodes error -result {bad window path name \"geek\"}\ntest winfo-2.5 {\"winfo atomname\" command} -body {\n    winfo atomname 44215\n} -returnCodes error -result {no atom exists with id \"44215\"}\ntest winfo-2.6 {\"winfo atomname\" command} -body {\n    winfo atomname 2\n} -result SECONDARY\ntest winfo-2.7 {\"winfo atom\" command} -body {\n    winfo atomname -displayof . 2\n} -result SECONDARY\n\n\ntest winfo-3.1 {\"winfo colormapfull\" command} -constraints {\n    defaultPseudocolor8\n} -body {\n    winfo colormapfull\n} -returnCodes error -result {wrong # args: should be \"winfo colormapfull window\"}\ntest winfo-3.2 {\"winfo colormapfull\" command} -constraints {\n    defaultPseudocolor8\n} -body {\n    winfo colormapfull a b\n} -returnCodes error -result {wrong # args: should be \"winfo colormapfull window\"}\ntest winfo-3.3 {\"winfo colormapfull\" command} -constraints {\n    defaultPseudocolor8\n} -body {\n    winfo colormapfull foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest winfo-3.4 {\"winfo colormapfull\" command} -constraints {\n    unix defaultPseudocolor8\n} -body {\n    eatColors .t {-colormap new}\n    set result [list [winfo colormapfull .] [winfo colormapfull .t]]\n    .t.c delete 34\n    lappend result [winfo colormapfull .t]\n    .t.c create rectangle 30 30 80 80 -fill #441739\n    lappend result [winfo colormapfull .t]\n    .t.c create rectangle 40 40 90 90 -fill #ffeedd\n    lappend result [winfo colormapfull .t]\n    destroy .t.c\n    lappend result [winfo colormapfull .t]\n} -cleanup {\n    destroy .t\n} -result {0 1 0 0 1 0}\n\n\n\ntest winfo-4.1 {\"winfo containing\" command} -body {\n    winfo containing 22\n} -returnCodes error -result {wrong # args: should be \"winfo containing ?-displayof window? rootX rootY\"}\ntest winfo-4.2 {\"winfo containing\" command} -body {\n    winfo containing a b c\n} -returnCodes error -result {wrong # args: should be \"winfo containing ?-displayof window? rootX rootY\"}\ntest winfo-4.3 {\"winfo containing\" command} -body {\n    winfo containing a b c d e\n} -returnCodes error -result {wrong # args: should be \"winfo containing ?-displayof window? rootX rootY\"}\ntest winfo-4.4 {\"winfo containing\" command} -body {\n    winfo containing -displayof geek 25 30\n} -returnCodes error -result {bad window path name \"geek\"}\ntest winfo-4.5 {\"winfo containing\" command} -body {\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 550 -height 400\n    frame .t.f -width 80 -height 60 -bd 2 -relief raised\n    place .t.f -x 50 -y 50\n    wm geom .t +0+0\n    update\n\n    raise .t\n    winfo containing [winfo rootx .t.f] [winfo rooty .t.f]\n} -cleanup {\n    destroy .t\n} -result .t.f\ntest winfo-4.6 {\"winfo containing\" command} -constraints {\n    nonPortable\n} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 550 -height 400\n    frame .t.f -width 80 -height 60 -bd 2 -relief raised\n    place .t.f -x 50 -y 50\n    wm geom .t +0+0\n    update\n\n    winfo containing [expr {[winfo rootx .t.f]-1}] [expr {[winfo rooty .t.f]-1}]\n} -cleanup {\n    destroy .t\n} -result .t\ntest winfo-4.7 {\"winfo containing\" command} -setup {\n    destroy .t\n} -body {\n    toplevel .t -width 550 -height 400\n    frame .t.f -width 80 -height 60 -bd 2 -relief raised\n    place .t.f -x 50 -y 50\n    wm geom .t +0+0\n    update\n\n    set x [winfo containing -display .t.f [expr {[winfo rootx .t]+600}] \\\n\t[expr {[winfo rooty .t.f]+450}]]\n    expr {($x eq \".\") || ($x eq \"\")}\n} -cleanup {\n    destroy .t\n} -result 1\ntest winfo-4.8 {\"winfo containing\": don't consider unmapped toplevel windows (bug #591829e948-B)} -setup {\n    wm geometry . 200x200+100+100\n    after 10; update\n    wm withdraw .\n} -body {\n    toplevel .one\n    wm geometry .one 200x200+350+100\n    after 10; update\n    wm withdraw .one\n    after 10; update\n    winfo containing 450 200\n} -cleanup {\n    wm deiconify .\n} -result \"\"\n\ntestutils import child\n\ntest winfo-5.1 {\"winfo interps\" command} -body {\n    winfo interps a\n} -returnCodes error -result {wrong # args: should be \"winfo interps ?-displayof window?\"}\ntest winfo-5.2 {\"winfo interps\" command} -body {\n    winfo interps a b c\n} -returnCodes error -result {wrong # args: should be \"winfo interps ?-displayof window?\"}\ntest winfo-5.3 {\"winfo interps\" command} -body {\n    winfo interps -displayof geek\n} -returnCodes error -result {bad window path name \"geek\"}\n\n# The winfo command does not work on macOS CI runnters because it requires writing\n# to a database file, which in turn requires interactively dismissing a system\n# privacy dialog\n\ntest winfo-5.4 {\"winfo interps\" command} -constraints {unix notMacCI} -body {\n    childTkInterp child\n    set appname [child eval tk appname]\n    set res [expr {[lsearch -exact [winfo interps] $appname] >= 0}]\n    interp delete child\n    lappend res [expr {[lsearch -exact [winfo interps] $appname] >= 0}]\n    set res\n} -result {1 0}\ntest winfo-5.5 {\"winfo interps\" command} -constraints {unix notMacCI} -body {\n    childTkInterp child\n    set appname [child eval tk appname]\n    set res [expr {[lsearch -exact [winfo interps -displayof .] $appname] >= 0}]\n    interp delete child\n    lappend res [expr {[lsearch -exact [winfo interps -displayof .] $appname] >= 0}]\n    set res\n} -result {1 0}\ntest winfo-5.6 {\"winfo interps\" command} -constraints {unix notMacCI} -body {\n    childTkProcess create\n    set appname [childTkProcess eval [list tk appname]]\n    set res [expr {[lsearch -exact [winfo interps] $appname] >= 0}]\n    childTkProcess exit\n    lappend res [expr {[lsearch -exact [winfo interps] $appname] >= 0}]\n    set res\n} -result {1 0}\ntest winfo-5.7 {\"winfo interps\" command} -constraints {unix notMacCI} -body {\n    childTkProcess create\n    set appname [childTkProcess eval [list tk appname]]\n    set res [expr {[lsearch -exact [winfo interps -displayof .] $appname] >= 0}]\n    childTkProcess exit\n    lappend res [expr {[lsearch -exact [winfo interps -displayof .] $appname] >= 0}]\n    set res\n} -result {1 0}\n\ntestutils forget child\n\ntest winfo-6.1 {\"winfo exists\" command} -body {\n    winfo exists\n} -returnCodes error -result {wrong # args: should be \"winfo exists window\"}\ntest winfo-6.2 {\"winfo exists\" command} -body {\n    winfo exists a b\n} -returnCodes error -result {wrong # args: should be \"winfo exists window\"}\ntest winfo-6.3 {\"winfo exists\" command} -body {\n    winfo exists gorp\n} -result 0\ntest winfo-6.4 {\"winfo exists\" command} -body {\n    winfo exists .\n} -result 1\ntest winfo-6.5 {\"winfo exists\" command} -setup {\n    destroy .b\n} -body {\n    button .b -text \"Test button\"\n    set x [winfo exists .b]\n    pack .b\n    update\n    bind .b <Destroy> {lappend x [winfo exists .x]}\n    destroy .b\n    lappend x [winfo exists .x]\n} -result {1 0 0}\n\n\ntest winfo-7.1 {\"winfo pathname\" command} -body {\n    winfo pathname\n} -returnCodes error -result {wrong # args: should be \"winfo pathname ?-displayof window? id\"}\ntest winfo-7.2 {\"winfo pathname\" command} -body {\n    winfo pathname a b\n} -returnCodes error -result {wrong # args: should be \"winfo pathname ?-displayof window? id\"}\ntest winfo-7.3 {\"winfo pathname\" command} -body {\n    winfo pathname a b c d\n} -returnCodes error -result {wrong # args: should be \"winfo pathname ?-displayof window? id\"}\ntest winfo-7.4 {\"winfo pathname\" command} -body {\n    winfo pathname -displayof geek 25\n} -returnCodes error -result {bad window path name \"geek\"}\ntest winfo-7.5 {\"winfo pathname\" command} -body {\n    winfo pathname xyz\n} -returnCodes error -result {expected integer but got \"xyz\"}\ntest winfo-7.6 {\"winfo pathname\" command} -body {\n    winfo pathname 224\n} -returnCodes error -result {window id \"224\" does not exist in this application}\ntest winfo-7.7 {\"winfo pathname\" command} -setup {\n    destroy .b\n    button .b -text \"Help\"\n    update\n} -body {\n    winfo pathname -displayof .b [winfo id .]\n} -cleanup {\n    destroy .b\n} -result {.}\ntest winfo-7.8 {\"winfo pathname\" command} -constraints {\n    unix testwrapper\n} -body {\n    winfo pathname [testwrapper .]\n} -result {}\n\n\ntest winfo-8.1 {\"winfo pointerx\" command} -setup {\n    destroy .b\n    button .b -text \"Help\"\n    update\n} -body {\n    catch [winfo pointerx .b]\n} -result 1\ntest winfo-8.2 {\"winfo pointery\" command} -setup {\n    destroy .b\n    button .b -text \"Help\"\n    update\n} -body {\n    catch [winfo pointery .b]\n} -result 1\ntest winfo-8.3 {\"winfo pointerxy\" command} -setup {\n    destroy .b\n    button .b -text \"Help\"\n    update\n} -body {\n    catch [winfo pointerxy .b]\n} -result 1\n\n\ntest winfo-9.1 {\"winfo viewable\" command} -body {\n    winfo viewable\n} -returnCodes error -result {wrong # args: should be \"winfo viewable window\"}\ntest winfo-9.2 {\"winfo viewable\" command} -body {\n    winfo viewable foo\n} -returnCodes error -result {bad window path name \"foo\"}\ntest winfo-9.3 {\"winfo viewable\" command} -body {\n    winfo viewable .\n} -result 1\ntest winfo-9.4 {\"winfo viewable\" command} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    wm iconify .\n    winfo viewable .\n} -cleanup {\n    wm deiconify .\n} -result 0\ntest winfo-9.5 {\"winfo viewable\" command} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -width 100 -height 100 -relief raised -bd 2\n    place .f1 -x 0 -y 0\n    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2\n    place .f1.f2 -x 0 -y 0\n    update\n    list [winfo viewable .f1] [winfo viewable .f1.f2]\n} -cleanup {\n    deleteWindows\n} -result {1 1}\ntest winfo-9.6 {\"winfo viewable\" command} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -width 100 -height 100 -relief raised -bd 2\n    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2\n    place .f1.f2 -x 0 -y 0\n    update\n    list [winfo viewable .f1] [winfo viewable .f1.f2]\n} -cleanup {\n    deleteWindows\n} -result {0 0}\ntest winfo-9.7 {\"winfo viewable\" command} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    deleteWindows\n} -body {\n    frame .f1 -width 100 -height 100 -relief raised -bd 2\n    place .f1 -x 0 -y 0\n    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2\n    place .f1.f2 -x 0 -y 0\n    update\n    wm iconify .\n    list [winfo viewable .f1] [winfo viewable .f1.f2]\n} -cleanup {\n    wm deiconify .\n    deleteWindows\n} -result {0 0}\n\n\ntest winfo-10.1 {\"winfo visualid\" command} -body {\n    winfo visualid\n} -returnCodes error -result {wrong # args: should be \"winfo visualid window\"}\ntest winfo-10.2 {\"winfo visualid\" command} -body {\n    winfo visualid gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest winfo-10.3 {\"winfo visualid\" command} -body {\n    expr {2 + [winfo visualid .] - [winfo visualid .]}\n} -result 2\n\n\ntest winfo-11.1 {\"winfo visualsavailable\" command} -body {\n    winfo visualsavailable\n} -returnCodes error -result {wrong # args: should be \"winfo visualsavailable window ?includeids?\"}\ntest winfo-11.2 {\"winfo visualsavailable\" command} -body {\n    winfo visualsavailable gorp\n} -returnCodes error -result {bad window path name \"gorp\"}\ntest winfo-11.3 {\"winfo visualsavailable\" command} -body {\n    winfo visualsavailable . includeids foo\n} -returnCodes error -result {wrong # args: should be \"winfo visualsavailable window ?includeids?\"}\ntest winfo-11.4 {\"winfo visualsavailable\" command} -body {\n    llength [lindex [winfo visualsa .] 0]\n} -result 2\ntest winfo-11.5 {\"winfo visualsavailable\" command} -body {\n    llength [lindex [winfo visualsa . includeids] 0]\n} -result 3\ntest winfo-11.6 {\"winfo visualsavailable\" command} -body {\n    set x [lindex [lindex [winfo visualsa . includeids] 0] 2]\n    expr {$x + 2 - $x}\n} -result 2\n\n\ntest winfo-12.1 {GetDisplayOf procedure} -body {\n    winfo atom - foo x\n} -returnCodes error -result {wrong # args: should be \"winfo atom ?-displayof window? name\"}\ntest winfo-12.2 {GetDisplayOf procedure} -body {\n    winfo atom -d bad_window x\n} -returnCodes error -result {bad window path name \"bad_window\"}\n\n\n# Some embedding tests\n#\ntest winfo-13.1 {root coordinates of embedded toplevel} -setup {\n    deleteWindows\n} -body {\n    frame .con -container 1\n    pack .con -expand yes -fill both\n    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0\n    button .emb.b\n    pack .emb.b -expand yes -fill both\n    update\n\n    list rootx [expr {[winfo rootx .emb] == [winfo rootx .con]}] \\\n\trooty [expr {[winfo rooty .emb] == [winfo rooty .con]}]\n} -cleanup {\n    deleteWindows\n} -result {rootx 1 rooty 1}\n\n# Windows does not destroy the container when an embedded window is\n# destroyed.  Unix and macOS do destroy it.  See ticket [67384bce7d].\ntest winfo-13.2 {destroying embedded toplevel} -setup {\n    deleteWindows\n} -body {\n    frame .con -container 1\n    pack .con -expand yes -fill both\n    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0\n    button .emb.b\n    pack .emb.b -expand yes -fill both\n    update\n\n    destroy .emb\n    update\n    list embedded [winfo exists .emb.b] container [winfo exists .con]\n} -cleanup {\n    deleteWindows\n} -result [expr {[tk windowingsystem] eq \"win32\"?{embedded 0 container 1}:{embedded 0 container 0}}]\n\ntest winfo-13.3 {destroying container window} -setup {\n    deleteWindows\n} -body {\n    frame .con -container 1\n    pack .con -expand yes -fill both\n    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0\n    button .emb.b\n    pack .emb.b -expand yes -fill both\n    update\n\n    destroy .con\n    update\n    list child [winfo exists .emb.b] parent [winfo exists .emb]\n} -cleanup {\n    deleteWindows\n} -result {child 0 parent 0}\n\ntest winfo-13.4 {[winfo containing] with embedded windows} -setup {\n    deleteWindows\n} -body {\n    wm geometry . +100+100\n    frame .con -container 1\n    pack .con -expand yes -fill both\n    update\n    toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0\n    button .emb.b\n    pack .emb.b -expand yes -fill both\n    update\n\n    button .b\n    pack .b -expand yes -fill both\n    update\n    string compare .emb.b \\\n\t[winfo containing [winfo rootx .emb.b] [winfo rooty .emb.b]]\n} -cleanup {\n    deleteWindows\n} -result 0\n\n\ntest winfo-14.1 {\"winfo ismapped\" command, usage} -body {\n    winfo ismapped\n} -returnCodes error -result {wrong # args: should be \"winfo ismapped window\"}\n\ntest winfo-14.2 {\"winfo ismapped\" command, usage} -body {\n    winfo ismapped . .\n} -returnCodes error -result {wrong # args: should be \"winfo ismapped window\"}\n\ntest winfo-14.3 {\"winfo ismapped\" command, new toplevel is initially unmapped} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    winfo ismapped .t\n} -cleanup {\n    destroy .t\n} -result 0\n\ntest winfo-14.4 {\"winfo ismapped\" command, new toplevel is mapped at idle time} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    update idletasks\n    winfo ismapped .t\n} -cleanup {\n    destroy .t\n} -result 1\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ntestutils forget colors\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/wm.test",
    "content": "# This file is a Tcl script to test out platform-indifferent interactions\n# with the window manager, including the \"wm\" command.\n\n#\n# Copyright © 1992-1994 The Regents of the University of California.\n# Copyright © 1994-1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# All rights reserved.\n\n# NOTE\n#\n# This test file is platform-indifferent. Tests regarding the window manager that\n# are specific to the unix platform (this includes macOS), or to the windows\n# platform go into the test files unixWm.test or winWm.test respectively.\n#\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\n# [raise] and [lower] may return before the window manager has completed the\n# operation. The raiseDelay procedure idles for a while to give the operation\n# a chance to complete.\n#\nproc raiseDelay {} {\n    after 300;\n    update idletasks\n    update\n}\n\nproc stdWindow {} {\n    destroy .t\n    toplevel .t -width 100 -height 50\n    wm geom .t +0+0\n    update\n}\n\n#\n# COMMON TEST SETUP\n#\n\nimage create photo icon -data {\n    iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAA\n    CBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/w\n    D/AP+gvaeTAAAACXBIWXMAArQNAAK0DQEdFIm+AAAJQElEQVRYw+WXW2xdV5nHf/ty7lc\n    f2/FxYsdOnMSNC0HTpDiRKJWAQjWCEQNUSEAFfUOiQqrEC2+IxwpemDLSzNBBCCQeQEKq\n    RJgBSikiuGlN22TqhsR27OPL8eWc43Pdt7X22osHHydOm4FBPM6Slr69paX9/32Xtb614\n    f/7MP6vC3O5f8L3G7HJyZPHBwfz5wrF7HQ6nRwxLTOhQuU4PW+z3eq9Xa+33rq9cms7k8\n    pHjvfS3w8wOfk52u1u8oHpiUff897JJ8+dO/nI6LHho6OjQ3ahkMYwTTZ2O2zXutS3G/7\n    ayubq7Vtr/7Ve2f7RytLam4ViXq1t/vRvB0ilPsjzz3+LZ5/9j7MzM5Nf/8hj5//5H97/\n    YNbK5hkfTFLMxAEQQvD766v0yBGIEBEEuPUGi9dv7lx77cb3Vm9vfqc0WNi9evUKWr/xL\n    h3rfuLj45+l0bjM7m768U98/OJ/fulLH/3wiemxeCafxRcKw7TJxKC+12RpbYdAx7HsOC\n    rSRNpg+sQQj1w8nS0N5h8JAvm+rWr99ZmZB2qWdZq9vWt/GWBm5im+9rUn6HRGPv7EE4/\n    ++2P/eOFkV0FkJTDQgCaXTbO1tcV2R2EmCxBJQixs2+R9EwV00MFAceJE2ZiZOT7VaTsP\n    LyxU5orFTK1cfphq9bX7A8zOfoV8Ps3c3NsXPvWpD37vc5//0ETNt8gNjDAzlsdAE0vli\n    TCRxEhnC2CaRIZNMmZiaonv9mh1PcrDJQZzCfK5OGNjQ8e2tvZO37y5+ctk0naq1fn7A4\n    yOnmd5uVp4/PGHn/vylz8xe+zoEIP5JAMpA0OHeK6DG4TEk2li8ThaQxRpIg0q6DGUNjg\n    6UuLYSInhYoYoigiCgHQ6TrGYnlpd3Q1ffvk3L128+ITe2Hj1XoBLl55menqcbDb1haee\n    evyrDz102tJaE7ctLBMqG1X23Ag7kcKOJzAADSilCVWEZdmMDaXJJCxSiRimaaK1RkqJ7\n    /uUSlk6Hed0oxG9HI9bm+Pjs2xsvIp5AKC15oUX/lA8f/7MF2dnz8YADMNASslypYqrUx\n    SHyqSy+f31hzaRZRpMDKVYr+7y4usVri1WWavWCWSIZZkYhoFSIRcuTI1MTAw9OTf33Tu\n    7zz54SCRinD17/Pzs7AMPFQqZPlTE8vo2DlmGhgbo12BffD/8SmukitiuNxHKoDwyzPJG\n    nTdXmtiWwdnRNCN5GxWGDA/nOH26/NGpqSfHgPU7AJcuPc0nP/kBrl698YGZmYmMEIJmx\n    6Hn+my0DUZGC6gIzEOnhu4Lh2GEbRocGyxRSO/7c3QgiRuEVOtdEvEQrSN8IVEq5MSJ4Y\n    lSKX3OMKJ14G4KnnnmM9bkZPk92VyKy3M3eentJjd3FUYyjxuEeELt7/NoP+eBVAipCFX\n    EsYE4xcydYFIeSHKynOXhUwM0mh32egH1tsdL16oo007kcskHs7kYly49fRcALqby+fQo\n    pklkZ4jHY3g6gQgjHF/QcgQdV+7DHJoGmnzSQuvD0QGlIsJQkU4luLXR4kgxxcRgjM1mQ\n    CyZHrv0sUe4JwKFXMmu7/VSXV9xaXqI0YzC8328QOJ4gq4raHQDGt2AtitwfIEbSAwibO\n    vdJ7pSCiElR3IxGh2X5Y0GV66v0wnAsq3MN5759L1FqKMoCkQoX19u0QkkD47lKSYiTh1\n    NoSLYafu0ehrTNNBaE2mNUop2z+DEUJKBbPxecSEIgoAoUjwwmmZpdZPlmuL4oIFWkbx8\n    rXIvQMfZ9p2e1xBCstOJcFe6nB1NcWokhW1ZHMkazK90qXXDfZFII0NFIBW/XQiZHraoN\n    bsU81mmjhbxfZ8gCAiCgELKQitJGCoIQ6SQO//2ze/fm4Kf/Px50dzr3Aoch1Ap2o4kn8\n    tgW/sHynAxzcVTBQYzFp4v6boBjidwfcFCpcmPf7/Oz+ZrvPBalb12D9/370DUGk1evr6\n    NacWIfD/yveDmXq3F3NxzdwH+5dkfUq8155rb9dA2QcqQcjFx57DRGgaySR47d4RHZ0pY\n    eh/C9QSOJ3EECGWw3fJZ323j+x6e5xH4Pgu3d6g0FMWUjdvu7bo9/5oK1d0IzM09hwhCG\n    rvNubXFylI2pum4AZXtDqEURFGE1hoNxGMW5ZyB22nS8wQ9r1+QvsDzBc1uQGW7jee6eN\n    4+RMfxMdHkYgatWmtur9ZaOnD8TgQMA27c+uH68s3KT8O9BoYBv3pjkxuVGo7Tw+1/MAh\n    83lreYm1P9r3fT4XjSVxf4voC1/NwHAfXdXFcB891KGVjhO2e16q3fzR2cjQwDPPeZrSx\n    8SqXL2/RqDU2EnH7I8dPjQ8v7Tqs1RwmSzEsQoQQSBHw1lKVha0AEUb4IiQQIb4I8YUkk\n    CHTQwa5WIjne9xY2mT+VouRfI7NxfVfrK8sfTuRSAavXP3Xd7fjavWPRq1+3TeiQTVcGn\n    h0oHwktlZzmBq0SNsRQgiuXLvNL/+nQU/aBFL1xSW+kAghEb5PEkE5q3Bdl7dv72LGCrT\n    Xdzf+9Nb8N5dXfrG6Wf1jeNDP3nkjigOFWm2xpvx0+tjI8LnMYMnMxQT5eIjruVye36LS\n    TRAqRSD3vZdCIqUgEj5R4CEDj2O5kMZei3rHoLXV6Sy88cp3Fhf/ew6IAAGE9wOIARmtw\n    9Tu7vKa1yY+Wiqeee+ZYdsi4HdvrjK/HiKUiZQhoZREQhDJAC18tPSIhEfouwSuQ9cx2V\n    xpNK/PX/n+4uKvXwQdAAHgA/J+AAaQABJRJOydnVsrzZ1O13eMcSuezC61LJzQRgY+KvC\n    JhI+WPpH0IAywIkEhaVIupAhdHS0t3F66Nv/iD9bW/nAFtAM4QA9wAXX3RnEvQBoYODSL\n    +fzEmalTsx+emjl3YWjsaMlMpcwg0ggZEimFoSNsI8JSCtF1wtpmdWt1aeGVSuW133leY\n    wNoA01gr297BzVwv/8CA0gBBaDYtzkw87ns6PhI+czM0JHjp/PFUjmZSmUM07RCKUPP6X\n    Vae/Vqfbdys1ZbvOX5ja2+ULcP0Opbt18H/G8Ah+shDWQPzVQ/RSnLTGRsO5U0TMuMVKj\n    C0PUjLd1+fgPAOxTybl9YcvdC9VcBDobV3x0JINm3MfYbmdX/hu57FfZFDgot6Fe8eqfw\n    3wLwzvVmX9jsvx8AHEAcnn91/BlySEFKTpuCtgAAABN0RVh0QXV0aG9yAHdhcnN6YXdpY\n    W5rYQy+S5cAAABYdEVYdENvcHlyaWdodABDQzAgUHVibGljIERvbWFpbiBEZWRpY2F0aW\n    9uIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL3B1YmxpY2RvbWFpbi96ZXJvLzEuMC/\n    G4735AAAAIXRFWHRDcmVhdGlvbiBUaW1lADIwMTAtMDMtMjlUMDg6MDg6MzD47LxwAAAA\n    JXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTA4LTE1VDIwOjU0OjM5LTA0OjAwNBT3DQAAACV0R\n    Vh0ZGF0ZTptb2RpZnkAMjAyMS0wOC0xNVQyMDo1NDoxMS0wNDowMDSDBqsAAADIelRYdE\n    Rlc2NyaXB0aW9uAAAY042OwQqCQBCGn6B3GOy+Cl0qTAjEc1HRJVhWHXUrd2pmLXr7tDr\n    VpcMP838w/F+wxxxyprsgB2ALclAxtRAbaBirRdB4f5mHoTeuJlUxYoly8nRRxHW4HahO\n    30SvmI5Y+CCBF4dPhzg0CYwOLs45GdKfG+sKhBuy2H4xUlM1i76+BhcBwwirLj/bAlJqj\n    XXzP9UyxmuHzp8feiknLPW6Q/H9moy3yK1oqvROUE2yH99suX45PwEyf2MTOoCNrQAAAB\n    l0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABWdEVYdFNvdXJjZQBodHR\n    wczovL29wZW5jbGlwYXJ0Lm9yZy9kZXRhaWwvMzUyMzMvdGFuZ28taW5ldHJuZXQtd2Vi\n    LWJyb3dzZXItYnktd2Fyc3phd2lhbmth5nAuRgAAACB0RVh0VGl0bGUAdGFuZ28gaW5ld\n    HJuZXQgd2ViIGJyb3dzZXLyr62TAAAAAElFTkSuQmCC\n}\n\nwm deiconify .\nif {![winfo ismapped .]} {\n    tkwait visibility .\n}\n\ndeleteWindows\nstdWindow\n\n#\n# TESTS\n#\n\ntest wm-1.1 {Tk_WmObjCmd procedure, miscellaneous errors} -returnCodes error -body {\n    wm\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\n# Next test will fail every time set of subcommands is changed\ntest wm-1.2 {Tk_WmObjCmd procedure, miscellaneous errors} -returnCodes error -body {\n    wm foo\n} -result {bad option \"foo\": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbadge, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}\ntest wm-1.3 {Tk_WmObjCmd procedure, miscellaneous errors} -returnCodes error -body {\n    wm command\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-1.4 {Tk_WmObjCmd procedure, miscellaneous errors} -returnCodes error -body {\n    wm aspect bogus\n} -result {bad window path name \"bogus\"}\ntest wm-1.5 {Tk_WmObjCmd procedure, miscellaneous errors} -body {\n    button .b -text hello\n    wm geometry .b\n} -returnCodes error -cleanup {\n    destroy .b\n} -result {window \".b\" isn't a top-level window}\n\n\n### wm aspect ###\ntest wm-aspect-1.1 {usage} -returnCodes error -body {\n    wm aspect\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-aspect-1.2 {usage} -returnCodes error -body {\n    wm aspect . _\n} -result {wrong # args: should be \"wm aspect window ?minNumer minDenom maxNumer maxDenom?\"}\ntest wm-aspect-1.3 {usage} -returnCodes error -body {\n    wm aspect . _ _ _\n} -result {wrong # args: should be \"wm aspect window ?minNumer minDenom maxNumer maxDenom?\"}\ntest wm-aspect-1.4 {usage} -returnCodes error -body {\n    wm aspect . _ _ _ _ _\n} -result {wrong # args: should be \"wm aspect window ?minNumer minDenom maxNumer maxDenom?\"}\ntest wm-aspect-1.5 {usage} -returnCodes error -body {\n    wm aspect . bad 14 15 16\n} -result {expected integer but got \"bad\"}\ntest wm-aspect-1.6 {usage} -returnCodes error -body {\n    wm aspect . 13 foo 15 16\n} -result {expected integer but got \"foo\"}\ntest wm-aspect-1.7 {usage} -returnCodes error -body {\n    wm aspect . 13 14 bar 16\n} -result {expected integer but got \"bar\"}\ntest wm-aspect-1.8 {usage} -returnCodes error -body {\n    wm aspect . 13 14 15 baz\n} -result {expected integer but got \"baz\"}\ntest wm-aspect-1.9 {usage} -returnCodes error -body {\n    wm aspect . 0 14 15 16\n} -result {aspect number can't be <= 0}\ntest wm-aspect-1.10 {usage} -returnCodes error -body {\n    wm aspect . 13 0 15 16\n} -result {aspect number can't be <= 0}\ntest wm-aspect-1.11 {usage} -returnCodes error -body {\n    wm aspect . 13 14 0 16\n} -result {aspect number can't be <= 0}\ntest wm-aspect-1.12 {usage} -returnCodes error -body {\n    wm aspect . 13 14 15 0\n} -result {aspect number can't be <= 0}\n\ntest wm-aspect-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm aspect .t]\n    wm aspect .t 3 4 10 2\n    lappend result [wm aspect .t]\n    wm aspect .t {} {} {} {}\n    lappend result [wm aspect .t]\n} -result [list {} {3 4 10 2} {}]\n\n\n### wm attributes ###\ntest wm-attributes-1.1 {usage} -returnCodes error -body {\n    wm attributes\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-attributes-1.2.1 {usage} -constraints win -returnCodes error -body {\n    wm attributes . _\n} -result {bad attribute \"_\": must be -alpha, -disabled, -fullscreen, -toolwindow, -topmost, or -transparentcolor}\ntest wm-attributes-1.2.2 {usage} -constraints win -returnCodes error -body {\n    wm attributes . -alpha 1.0 -disabled\n} -result {wrong # args: should be \"wm attributes window ?-alpha ?double?? ?-transparentcolor ?color?? ?-disabled ?bool?? ?-fullscreen ?bool?? ?-toolwindow ?bool?? ?-topmost ?bool??\"}\ntest wm-attributes-1.2.3 {usage} -constraints win -returnCodes error -body {\n    wm attributes . -to\n} -result {bad attribute \"-to\": must be -alpha, -disabled, -fullscreen, -toolwindow, -topmost, or -transparentcolor}\ntest wm-attributes-1.2.5.1 {usage} -constraints x11 -returnCodes error -body {\n    wm attributes . _\n} -result {bad attribute \"_\": must be -alpha, -fullscreen, -topmost, -type, or -zoomed}\ntest wm-attributes-1.2.5.2 {usage} -constraints win32 -returnCodes error -body {\n    wm attributes . _\n} -result {bad attribute \"_\": must be -alpha, -disabled, -fullscreen, -toolwindow, -topmost, or -transparentcolor}\ntest wm-attributes-1.2.5.3 {usage} -constraints aqua -returnCodes error -body {\n    wm attributes . _\n} -result {bad attribute \"_\": must be -alpha, -appearance, -buttons, -fullscreen, -isdark, -modified, -notify, -titlepath, -topmost, -transparent, -stylemask, -class, -tabbingid, -tabbingmode, or -type}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-attributes-1.3.0 {default -fullscreen value} -constraints win -body {\n    toplevel .t\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 0\ntest wm-attributes-1.3.1 {change -fullscreen before map} -constraints win -body {\n    toplevel .t\n    wm attributes .t -fullscreen 1\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.2 {change -fullscreen before map} -constraints win -body {\n    toplevel .t\n    wm attributes .t -fullscreen 1\n    update\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.3 {change -fullscreen after map} -constraints win -body {\n    toplevel .t\n    update\n    wm attributes .t -fullscreen 1\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.4 {change -fullscreen after map} -setup {\n    set booleans [list]\n} -constraints win -body {\n    toplevel .t\n    update\n    lappend booleans [wm attributes .t -fullscreen]\n    wm attributes .t -fullscreen 1\n    lappend booleans [wm attributes .t -fullscreen]\n    # Query above should not clear fullscreen state\n    lappend booleans [wm attributes .t -fullscreen]\n    wm attributes .t -fullscreen 0\n    lappend booleans [wm attributes .t -fullscreen]\n} -cleanup {\n    deleteWindows\n} -result {0 1 1 0}\ntest wm-attributes-1.3.5 {change -fullscreen after map} -setup {\n    set results [list]\n    set normal_geom \"301x302+101+102\"\n    set fullscreen_geom \"[winfo screenwidth .]x[winfo screenheight .]+0+0\"\n} -constraints win -body {\n    toplevel .t\n    wm geom .t $normal_geom\n    update\n    lappend results [string equal [wm geom .t] $normal_geom]\n    wm attributes .t -fullscreen 1\n    lappend results [string equal [wm geom .t] $fullscreen_geom]\n    wm attributes .t -fullscreen 0\n    lappend results [string equal [wm geom .t] $normal_geom]\n} -cleanup {\n    deleteWindows\n} -result {1 1 1}\ntest wm-attributes-1.3.6 {state change does not change -fullscreen} -constraints win -body {\n    toplevel .t\n    update\n    wm attributes .t -fullscreen 1\n    wm withdraw .t\n    wm deiconify .t\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.7 {state change does not change -fullscreen} -constraints win -body {\n    toplevel .t\n    update\n    wm attributes .t -fullscreen 1\n    wm iconify .t\n    wm deiconify .t\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.8 {override-redirect not compatible with fullscreen attribute} -constraints win -body {\n    toplevel .t\n    update\n    wm overrideredirect .t 1\n    wm attributes .t -fullscreen 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't set fullscreen attribute for \".t\": override-redirect flag is set}\ntest wm-attributes-1.3.9 {max height too small} -constraints win -body {\n    toplevel .t\n    update\n    wm maxsize .t 5000 450\n    wm attributes .t -fullscreen 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't set fullscreen attribute for \".t\": max width/height is too small}\ntest wm-attributes-1.3.10 {max height too small} -constraints win -body {\n    toplevel .t\n    update\n    wm maxsize .t 450 5000\n    wm attributes .t -fullscreen 1\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't set fullscreen attribute for \".t\": max width/height is too small}\ntest wm-attributes-1.3.11 {another attribute, then -fullscreen} -constraints win -body {\n    toplevel .t\n    update\n    wm attributes .t -alpha 1.0 -fullscreen 1\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-attributes-1.3.12 {another attribute, then -fullscreen, then another} -constraints win -body {\n    toplevel .t\n    update\n    wm attributes .t -toolwindow 0 -fullscreen 1 -topmost 0\n    wm attributes .t -fullscreen\n} -cleanup {\n    deleteWindows\n} -result 1\n\ntest wm-attributes-1.4.0 {setting/unsetting fullscreen does not change the focus} -setup {\n    set results [list]\n} -constraints win -body {\n    focus -force .\n    toplevel .t\n    lower .t\n    update\n    lappend results [focus]\n\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [focus]\n\n    wm attributes .t -fullscreen 0\n    pause 200\n    lappend results [focus]\n} -cleanup {\n    deleteWindows\n} -result {. . .}\ntest wm-attributes-1.4.1 {setting fullscreen does not generate FocusIn on wrapper create} -setup {\n    catch {unset focusin}\n} -constraints win -body {\n    focus -force .\n    toplevel .t\n    pack [entry .t.e]\n    lower .t\n    bind .t <FocusIn> {lappend focusin %W}\n    pause 200\n\n    lappend focusin 1\n    focus -force .t.e\n    pause 200\n\n    lappend focusin 2\n    wm attributes .t -fullscreen 1\n    pause 200\n\n    lappend focusin 3\n    wm attributes .t -fullscreen 0\n    pause 200\n\n    lappend focusin final [focus]\n} -cleanup {\n    bind . <FocusIn> {}\n    bind .t <FocusIn> {}\n    deleteWindows\n} -result {1 .t .t.e 2 3 final .t.e}\n\ntest wm-attributes-1.5.0 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .t\n    lappend results [wm stackorder .]\n    pause 200\n    lappend results [wm stackorder .]\n\n    # Default stacking is on top of other windows on the display. Setting the\n    # fullscreen attribute does not change this.\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {. {. .t} {. .t}}\ntest wm-attributes-1.5.1 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .t\n    lower .t\n    pause 200\n    lappend results [wm stackorder .]\n\n    # If stacking order is explicitly set, then setting the fullscreen\n    # attribute should not change it.\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {{.t .} {.t .}}\ntest wm-attributes-1.5.2 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .t\n    # lower forces the window to be mapped, it would not be otherwise\n    lower .t\n    lappend results [wm stackorder .]\n\n    # If stacking order is explicitly set for an unmapped window, then setting\n    # the fullscreen attribute should not change it.\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {{.t .} {.t .}}\ntest wm-attributes-1.5.3 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .t\n    pause 200\n    lappend results [wm stackorder .]\n\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n\n    # Unsetting the fullscreen attribute should not change the stackorder.\n    wm attributes .t -fullscreen 0\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {{. .t} {. .t} {. .t}}\ntest wm-attributes-1.5.4 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .t\n    lower .t\n    pause 200\n    lappend results [wm stackorder .]\n\n    wm attributes .t -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n\n    # Unsetting the fullscreen attribute should not change the stackorder.\n    wm attributes .t -fullscreen 0\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {{.t .} {.t .} {.t .}}\ntest wm-attributes-1.5.5 {fullscreen stackorder} -setup {\n    set results [list]\n} -constraints win -body {\n    toplevel .a\n    toplevel .b\n    toplevel .c\n    raise .a\n    raise .b\n    raise .c\n    pause 200\n    lappend results [wm stackorder .]\n\n    wm attributes .b -fullscreen 1\n    pause 200\n    lappend results [wm stackorder .]\n\n    # Unsetting the fullscreen attribute should not change the stackorder.\n    wm attributes .b -fullscreen 0\n    pause 200\n    lappend results [wm stackorder .]\n} -cleanup {\n    deleteWindows\n} -result {{. .a .b .c} {. .a .b .c} {. .a .b .c}}\n\n### wm client ###\ntest wm-client-1.1 {usage} -returnCodes error -body {\n    wm client\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-client-1.2 {usage} -returnCodes error -body {\n    wm client . _ _\n} -result {wrong # args: should be \"wm client window ?name?\"}\n\ntest wm-client-2.1 {setting and reading values} -setup {\n    toplevel .t\n    set result {}\n} -body {\n    lappend result [wm client .t]\n    wm client .t Miffo\n    lappend result [wm client .t]\n    wm client .t {}\n    lappend result [wm client .t]\n} -cleanup {\n    destroy .t\n} -result [list {} Miffo {}]\n\n#\n# COMMON TEST SETUP\n#\nstdWindow\n\n### wm colormapwindows ###\ntest wm-colormapwindows-1.1 {usage} -returnCodes error -body {\n    wm colormapwindows\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-colormapwindows-1.2 {usage} -returnCodes error -body {\n    wm colormapwindows . _ _\n} -result {wrong # args: should be \"wm colormapwindows window ?windowList?\"}\ntest wm-colormapwindows-1.3 {usage} -returnCodes error -body {\n    wm colormapwindows . \"a \\{\"\n} -result {unmatched open brace in list}\ntest wm-colormapwindows-1.4 {usage} -returnCodes error -body {\n    wm colormapwindows . foo\n} -result {bad window path name \"foo\"}\n\ntest wm-colormapwindows-2.1 {reading values} -body {\n    toplevel .t2 -width 200 -height 200 -colormap new\n    wm geom .t2 +0+0\n    frame .t2.a -width 100 -height 30\n    frame .t2.b -width 100 -height 30 -colormap new\n    pack .t2.a .t2.b -side top\n    update\n    set x [wm colormapwindows .t2]\n    frame .t2.c -width 100 -height 30 -colormap new\n    pack .t2.c -side top\n    update\n    list $x [wm colormapwindows .t2]\n} -cleanup {\n    destroy .t2\n} -result {{.t2.b .t2} {.t2.b .t2.c .t2}}\ntest wm-colormapwindows-2.2 {setting and reading values} -body {\n    toplevel .t2 -width 200 -height 200\n    wm geom .t2 +0+0\n    frame .t2.a -width 100 -height 30\n    frame .t2.b -width 100 -height 30\n    frame .t2.c -width 100 -height 30\n    pack .t2.a .t2.b .t2.c -side top\n    wm colormapwindows .t2 {.t2.b .t2.a}\n    wm colormapwindows .t2\n} -cleanup {\n    destroy .t2\n} -result {.t2.b .t2.a}\n\n\n### wm command ###\ntest wm-command-1.1 {usage} -returnCodes error -body {\n    wm command\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-command-1.2 {usage} -returnCodes error -body {\n    wm command . _ _\n} -result {wrong # args: should be \"wm command window ?value?\"}\ntest wm-command-1.3 {usage} -returnCodes error -body {\n    wm command . \"a \\{\"\n} -result {unmatched open brace in list}\n\ntest wm-command-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm command .t]\n    wm command .t [list Miffo Foo]\n    lappend result [wm command .t]\n    wm command .t {}\n    lappend result [wm command .t]\n} -result [list {} [list Miffo Foo] {}]\n\n\n### wm deiconify ###\ntest wm-deiconify-1.1 {usage} -returnCodes error -body {\n    wm deiconify\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-deiconify-1.2 {usage} -returnCodes error -body {\n    wm deiconify . _\n} -result {wrong # args: should be \"wm deiconify window\"}\ntest wm-deiconify-1.3 {usage} -returnCodes error -body {\n    wm deiconify _\n} -result {bad window path name \"_\"}\ntest wm-deiconify-1.4 {usage} -setup {\n    destroy .icon\n} -body {\n    toplevel .icon -width 50 -height 50 -bg red\n    wm iconwindow .t .icon\n    wm deiconify .icon\n} -returnCodes error -cleanup {\n    destroy .icon\n} -result {can't deiconify .icon: it is an icon for .t}\n# test embedded window for Windows\ntest wm-deiconify-1.5 {usage} -constraints win -setup {\n    destroy .embed\n} -body {\n    frame .t.f -container 1\n    toplevel .embed -use [winfo id .t.f]\n    wm deiconify .embed\n} -returnCodes error -cleanup {\n    destroy .t.f .embed\n} -result {can't deiconify .embed: the container does not support the request}\n# test embedded window for other platforms\ntest wm-deiconify-1.6 {usage} -constraints macOrUnix -setup {\n    destroy .embed\n} -body {\n    frame .t.f -container 1\n    toplevel .embed -use [winfo id .t.f]\n    wm deiconify .embed\n} -returnCodes error -cleanup {\n    destroy .t.f .embed\n} -result {can't deiconify .embed: it is an embedded window}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-deiconify-2.1 {a window that has never been mapped\\\n\tshould not be mapped by a call to deiconify} -body {\n    toplevel .t\n    wm deiconify .t\n    winfo ismapped .t\n} -cleanup {\n    deleteWindows\n} -result 0\ntest wm-deiconify-2.2 {a window that has already been\\\n\tmapped should be mapped by deiconify} -body {\n    toplevel .t\n    update idletasks\n    wm withdraw .t\n    wm deiconify .t\n    winfo ismapped .t\n} -cleanup {\n    deleteWindows\n} -result 1\ntest wm-deiconify-2.3 {geometry for an unmapped window\\\n\tshould not be calculated by a call to deiconify,\\\n\tit should be done at idle time} -setup {\n    set results {}\n} -body {\n    toplevel .t -width 200 -height 200\n    lappend results [wm geometry .t]\n    wm deiconify .t\n    lappend results [wm geometry .t]\n    update idletasks\n    lappend results [lindex [split \\\n\t[wm geometry .t] +] 0]\n} -cleanup {\n    deleteWindows\n} -result {1x1+0+0 1x1+0+0 200x200}\ntest wm-deiconify-2.4 {invoking destroy after a deiconify\\\n\tshould not result in a crash because of a callback\\\n\tset on the toplevel} -body {\n    toplevel .t\n    wm withdraw .t\n    wm deiconify .t\n    destroy .t\n    update\n} -cleanup {\n    deleteWindows\n}\n\n\n### wm focusmodel ###\ntest wm-focusmodel-1.1 {usage} -returnCodes error -body {\n    wm focusmodel\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-focusmodel-1.2 {usage} -returnCodes error -body {\n    wm focusmodel . _ _\n} -result {wrong # args: should be \"wm focusmodel window ?active|passive?\"}\ntest wm-focusmodel-1.3 {usage} -returnCodes error -body {\n    wm focusmodel . bogus\n} -result {bad argument \"bogus\": must be active or passive}\n\n#\n# COMMON TEST SETUP\n#\nstdWindow\n\ntest wm-focusmodel-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm focusmodel .t]\n    wm focusmodel .t active\n    lappend result [wm focusmodel .t]\n    wm focusmodel .t passive\n    lappend result [wm focusmodel .t]\n} -result {passive active passive}\n\n\n### wm frame ###\ntest wm-frame-1.1 {usage} -returnCodes error -body {\n    wm frame\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-frame-1.2 {usage} -returnCodes error -body {\n    wm frame . _\n} -result {wrong # args: should be \"wm frame window\"}\n\n\n### wm geometry ###\ntest wm-geometry-1.1 {usage} -returnCodes error -body {\n    wm geometry\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-geometry-1.2 {usage} -returnCodes error -body {\n    wm geometry . _ _\n} -result {wrong # args: should be \"wm geometry window ?newGeometry?\"}\ntest wm-geometry-1.3 {usage} -returnCodes error -body {\n    wm geometry . bogus\n} -result {bad geometry specifier \"bogus\"}\n\ntest wm-geometry-2.1 {setting values} -body {\n    wm geometry .t 150x150+50+50\n    update\n    set result [wm geometry .t]\n    wm geometry .t {}\n    update\n    return [list $result [string equal [wm geometry .t] $result]]\n} -cleanup {\n    unset result\n} -match glob -result [list 150x150+*+* 0]\n\n\n### wm grid ###\ntest wm-grid-1.1 {usage} -returnCodes error -body {\n    wm grid\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-grid-1.2 {usage} -returnCodes error -body {\n    wm grid . _\n} -result {wrong # args: should be \"wm grid window ?baseWidth baseHeight widthInc heightInc?\"}\ntest wm-grid-1.3 {usage} -returnCodes error -body {\n    wm grid . _ _ _\n} -result {wrong # args: should be \"wm grid window ?baseWidth baseHeight widthInc heightInc?\"}\ntest wm-grid-1.4 {usage} -returnCodes error -body {\n    wm grid . _ _ _ _ _\n} -result {wrong # args: should be \"wm grid window ?baseWidth baseHeight widthInc heightInc?\"}\ntest wm-grid-1.5 {usage} -returnCodes error -body {\n    wm grid . bad 14 15 16\n} -result {expected integer but got \"bad\"}\ntest wm-grid-1.6 {usage} -returnCodes error -body {\n    wm grid . 13 foo 15 16\n} -result {expected integer but got \"foo\"}\ntest wm-grid-1.7 {usage} -returnCodes error -body {\n    wm grid . 13 14 bar 16\n} -result {expected integer but got \"bar\"}\ntest wm-grid-1.8 {usage} -returnCodes error -body {\n    wm grid . 13 14 15 baz\n} -result {expected integer but got \"baz\"}\ntest wm-grid-1.9 {usage} -returnCodes error -body {\n    wm grid . -1 14 15 16\n} -result {baseWidth can't be < 0}\ntest wm-grid-1.10 {usage} -returnCodes error -body {\n    wm grid . 13 -1 15 16\n} -result {baseHeight can't be < 0}\ntest wm-grid-1.11 {usage} -returnCodes error -body {\n    wm grid . 13 14 -1 16\n} -result {widthInc can't be <= 0}\ntest wm-grid-1.12 {usage} -returnCodes error -body {\n    wm grid . 13 14 15 -1\n} -result {heightInc can't be <= 0}\n\ntest wm-grid-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm grid .t]\n    wm grid .t 3 4 10 2\n    lappend result [wm grid .t]\n    wm grid .t {} {} {} {}\n    lappend result [wm grid .t]\n} -result [list {} {3 4 10 2} {}]\n\n\n### wm group ###\ntest wm-group-1.1 {usage} -returnCodes error -body {\n    wm group\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-group-1.2 {usage} -returnCodes error -body {\n    wm group .t 12 13\n} -result {wrong # args: should be \"wm group window ?pathName?\"}\ntest wm-group-1.3 {usage} -returnCodes error -body {\n    wm group .t bogus\n} -result {bad window path name \"bogus\"}\n\ntest wm-group-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm group .t]\n    wm group .t .\n    lappend result [wm group .t]\n    wm group .t {}\n    lappend result [wm group .t]\n} -result [list {} . {}]\n\n\n### wm iconbadge ###\ntest wm-iconbadge-1.1 {usage} -body {\n    wm iconbadge\n} -returnCodes error -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconbadge-1.2 {usage} -body {\n    frame .f\n    set ::tk::icons::base_icon(.f) icon\n    wm iconbadge .f icon\n} -cleanup {\n    destroy .f\n    unset ::tk::icons::base_icon(.f)\n} -returnCodes error -result {window \".f\" isn't a top-level window}\ntest wm-iconbadge-1.3 {::tk::icons::base_icon($win) must be set on X11} -constraints {\n    x11\n} -setup {\n    unset -nocomplain ::tk::icons::base_icon(.)\n} -body {\n    wm iconbadge . !\n} -returnCodes error -result {::tk::icons::base_icon(.) must be set on X11}\ntest wm-iconbadge-1.4 {::tk::icons::base_icon($win) must be a Tk photo on X11} -constraints {\n    x11\n} -setup {\n    catch {image delete book}\n} -body {\n    set ::tk::icons::base_icon(.) book\n    wm iconbadge . 27\n} -returnCodes error -result {can't use \"book\" as iconphoto: not a photo image}\ntest wm-iconbadge-1.5 {illegal badge number} -body {\n    image create photo book -data {\n\tR0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAAC\n\twAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IM\n\tQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc\n\t0yv+DVSEUuFxIAOw==\n    }\n    set ::tk::icons::base_icon(.) book\n    wm iconbadge . illegal\n} -cleanup {\n    image delete book\n} -returnCodes error -result {can't use \"illegal\" as icon badge}\ntest wm-iconbadge-1.6 {non-integer badge number} -body {\n    image create photo book -data {\n\tR0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAAC\n\twAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IM\n\tQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc\n\t0yv+DVSEUuFxIAOw==\n    }\n    set ::tk::icons::base_icon(.) book\n    wm iconbadge . 3.2\n} -cleanup {\n    image delete book\n} -returnCodes error -result {can't use \"3.2\" as icon badge}\ntest wm-iconbadge-1.7 {negative or zero badge number} -body {\n    image create photo book -data {\n\tR0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAAC\n\twAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IM\n\tQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc\n\t0yv+DVSEUuFxIAOw==\n    }\n    set ::tk::icons::base_icon(.) book\n    wm iconbadge . 0\n} -cleanup {\n    image delete book\n} -returnCodes error -result {can't use \"0\" as icon badge}\ntest wm-iconbadge-1.8 {usage, no need to call iconphoto on aqua or win32} -constraints {\n    aquaOrWin32\n} -body {\n    wm iconbadge . 3\n    wm iconbadge . 5000\n    wm iconbadge . !\n    wm iconbadge . \"\"\n} -result {}\n\n\n### wm iconbitmap ###\ntest wm-iconbitmap-1.1 {usage} -returnCodes error -body {\n    wm iconbitmap\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconbitmap-1.2.1 {usage} -constraints unix -returnCodes error -body {\n    wm iconbitmap .t 12 13\n} -result {wrong # args: should be \"wm iconbitmap window ?bitmap?\"}\ntest wm-iconbitmap-1.2.2 {usage} -constraints win -returnCodes error -body {\n    wm iconbitmap .t 12 13 14\n} -result {wrong # args: should be \"wm iconbitmap window ?-default? ?image?\"}\ntest wm-iconbitmap-1.3 {usage} -constraints win -returnCodes error -body {\n    wm iconbitmap .t 12 13\n} -result {illegal option \"12\" must be \"-default\"}\ntest wm-iconbitmap-1.4 {usage} -returnCodes error -body {\n    wm iconbitmap .t bad-bitmap\n} -result {bitmap \"bad-bitmap\" not defined}\n\ntest wm-iconbitmap-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm iconbitmap .t]\n    wm iconbitmap .t hourglass\n    lappend result [wm iconbitmap .t]\n    wm iconbitmap .t {}\n    lappend result [wm iconbitmap .t]\n} -result [list {} hourglass {}]\n\n\n### wm iconify ###\ntest wm-iconify-1.1 {usage} -returnCodes error -body {\n    wm iconify\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconify-1.2 {usage} -returnCodes error -body {\n    wm iconify .t _\n} -result {wrong # args: should be \"wm iconify window\"}\n\n#\n# COMMON TEST SETUP\n#\ndestroy .t2\n\ntest wm-iconify-2.1 {Misc errors} -body {\n    toplevel .t2\n    wm overrideredirect .t2 1\n    wm iconify .t2\n} -returnCodes error -cleanup {\n    destroy .t2\n} -result {can't iconify \".t2\": override-redirect flag is set}\ntest wm-iconify-2.2 {Misc errors} -body {\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm transient .t2 .t\n    wm iconify .t2\n} -returnCodes error -cleanup {\n    destroy .t2\n} -result {can't iconify \".t2\": it is a transient}\ntest wm-iconify-2.3 {Misc errors} -body {\n    toplevel .t2\n    wm geom .t2 +0+0\n    wm iconwindow .t .t2\n    wm iconify .t2\n} -returnCodes error -cleanup {\n    destroy .t2\n} -result {can't iconify \".t2\": it is an icon for \".t\"}\n# test embedded window for Windows\ntest wm-iconify-2.4.1 {Misc errors} -constraints win -setup {\n    destroy .t2\n} -body {\n    frame .t.f -container 1\n    toplevel .t2 -use [winfo id .t.f]\n    wm iconify .t2\n} -returnCodes error -cleanup {\n    destroy .t2 .r.f\n} -result {can't iconify \".t2\": the container does not support the request}\n# test embedded window for other platforms\ntest wm-iconify-2.4.2 {Misc errors} -constraints macOrUnix -setup {\n    destroy .t2\n} -body {\n    frame .t.f -container 1\n    toplevel .t2 -use [winfo id .t.f]\n    wm iconify .t2\n} -returnCodes error -cleanup {\n    destroy .t2 .r.f\n} -result {can't iconify \".t2\": it is an embedded window}\n\ntest wm-iconify-3.1 {iconify behavior} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .t2\n    wm geom .t2 -0+0\n    update idletasks\n    set result [winfo ismapped .t2]\n    wm iconify .t2\n    update idletasks\n    lappend result [winfo ismapped .t2]\n} -cleanup {\n    destroy .t2\n} -result {1 0}\n\n\n### wm iconmask ###\ntest wm-iconmask-1.1 {usage} -returnCodes error -body {\n    wm iconmask\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconmask-1.2 {usage} -returnCodes error -body {\n    wm iconmask .t 12 13\n} -result {wrong # args: should be \"wm iconmask window ?bitmap?\"}\ntest wm-iconmask-1.3 {usage} -returnCodes error -body {\n    wm iconmask .t bad-bitmap\n} -result {bitmap \"bad-bitmap\" not defined}\n\ntest wm-iconmask-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm iconmask .t]\n    wm iconmask .t hourglass\n    lappend result [wm iconmask .t]\n    wm iconmask .t {}\n    lappend result [wm iconmask .t]\n} -result [list {} hourglass {}]\n\n\n### wm iconname ###\ntest wm-iconname-1.1 {usage} -returnCodes error -body {\n    wm iconname\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconname-1.2 {usage} -returnCodes error -body {\n    wm iconname .t 12 13\n} -result {wrong # args: should be \"wm iconname window ?newName?\"}\n\ntest wm-iconname-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm iconname .t]\n    wm iconname .t ThisIconHasAName\n    lappend result [wm iconname .t]\n    wm iconname .t {}\n    lappend result [wm iconname .t]\n} -result [list {} ThisIconHasAName {}]\n\n\n### wm iconphoto ###\ntest wm-iconphoto-1.1 {usage} -returnCodes error -body {\n    wm iconphoto\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconphoto-1.2 {usage} -returnCodes error -body {\n    wm iconphoto .\n} -result {wrong # args: should be \"wm iconphoto window ?-default? image1 ?image2 ...?\"}\ntest wm-iconphoto-1.3 {usage} -returnCodes error -body {\n    wm iconphoto . notanimage\n} -result {can't use \"notanimage\" as iconphoto: not a photo image}\ntest wm-iconphoto-1.4 {usage} -returnCodes error -body {\n    # we currently have no return info\n    wm iconphoto . -default\n} -result {wrong # args: should be \"wm iconphoto window ?-default? image1 ?image2 ...?\"}\ntest wm-iconphoto-1.5.1 {usage} -constraints aquaOrWin32 -returnCodes error -body {\n    wm iconphoto . -default [image create photo -file {}]\n} -match glob -result {failed to create an iconphoto with image *}\ntest wm-iconphoto-1.5.2 {usage} -constraints x11 -body {\n    wm iconphoto . -default [image create photo -file {}]\n} -result {}\n\n\n# All other iconphoto tests are platform specific\n\n\n### wm iconposition ###\ntest wm-iconposition-1.1 {usage} -returnCodes error -body {\n    wm iconposition\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconposition-1.2 {usage} -returnCodes error -body {\n    wm iconposition .t 12\n} -result {wrong # args: should be \"wm iconposition window ?x y?\"}\ntest wm-iconposition-1.3 {usage} -returnCodes error -body {\n    wm iconposition .t 12 13 14\n} -result {wrong # args: should be \"wm iconposition window ?x y?\"}\ntest wm-iconposition-1.4 {usage} -returnCodes error -body {\n    wm iconposition .t bad 13\n} -result {expected integer but got \"bad\"}\ntest wm-iconposition-1.5 {usage} -returnCodes error -body {\n    wm iconposition .t 13 lousy\n} -result {expected integer but got \"lousy\"}\n\ntest wm-iconposition-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm iconposition .t]\n    wm iconposition .t 10 20\n    lappend result [wm iconposition .t]\n    wm iconposition .t {} {}\n    lappend result [wm iconposition .t]\n} -result [list {} {10 20} {}]\n\n\n### wm iconwindow ###\ntest wm-iconwindow-1.1 {usage} -returnCodes error -body {\n    wm iconwindow\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-iconwindow-1.2 {usage} -returnCodes error -body {\n    wm iconwindow .t 12 13\n} -result {wrong # args: should be \"wm iconwindow window ?pathName?\"}\ntest wm-iconwindow-1.3 {usage} -returnCodes error -body {\n    wm iconwindow .t bogus\n} -result {bad window path name \"bogus\"}\ntest wm-iconwindow-1.4 {usage} -setup {\n    destroy .b\n} -body {\n    button .b -text Help\n    wm iconwindow .t .b\n} -returnCodes error -cleanup {\n    destroy .b\n} -result {can't use .b as icon window: not at top level}\ntest wm-iconwindow-1.5 {usage} -setup {\n    destroy .icon .t2\n} -body {\n    toplevel .icon -width 50 -height 50 -bg green\n    toplevel .t2\n    wm geom .t2 -0+0\n    wm iconwindow .t2 .icon\n    wm iconwindow .t .icon\n} -returnCodes error -cleanup {\n    destroy .t2 .icon\n} -result {.icon is already an icon for .t2}\n\ntest wm-iconwindow-2.1 {setting and reading values} -setup {\n    # without this macOS crashes for unknown reasons\n    wm iconwindow .t {}\n    destroy .icon\n    set result {}\n} -body {\n    lappend result [wm iconwindow .t]\n    toplevel .icon -width 50 -height 50 -bg green\n    wm iconwindow .t .icon\n    lappend result [wm iconwindow .t]\n    wm iconwindow .t {}\n    destroy .icon\n    lappend result [wm iconwindow .t]\n} -result {{} .icon {}}\n\n\n### wm maxsize ###\ntest wm-maxsize-1.1 {usage} -returnCodes error -body {\n    wm maxsize\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-maxsize-1.2 {usage} -returnCodes error -body {\n    wm maxsize . a\n} -result {wrong # args: should be \"wm maxsize window ?width height?\"}\ntest wm-maxsize-1.3 {usage} -returnCodes error -body {\n    wm maxsize . a b c\n} -result {wrong # args: should be \"wm maxsize window ?width height?\"}\ntest wm-maxsize-1.4 {usage} -returnCodes error -body {\n    wm maxsize . x 100\n} -result {expected screen distance but got \"x\"}\ntest wm-maxsize-1.5 {usage} -returnCodes error -body {\n    wm maxsize . 100 bogus\n} -result {expected screen distance but got \"bogus\"}\ntest wm-maxsize-1.6 {usage} -setup {\n    destroy .t2\n} -body {\n    toplevel .t2\n    wm maxsize .t2 300 200\n    wm maxsize .t2\n} -cleanup {\n    destroy .t2\n} -result {300 200}\ntest wm-maxsize-1.7 {maxsize must be <= screen size} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    lassign [wm maxsize .t] t_width t_height\n    set s_width [winfo screenwidth .t]\n    set s_height [winfo screenheight .t]\n    expr {($t_width <= $s_width) && ($t_height <= $s_height)}\n} -cleanup {\n    destroy .t\n} -result 1\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\ntest wm-maxsize-2.1 {setting the maxsize to a value smaller\\\n\tthan the current size will resize a toplevel} -body {\n    toplevel .t -width 300 -height 300\n    update\n    wm maxsize .t 200 150\n    # UpdateGeometryInfo invoked at idle\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {200 150}\ntest wm-maxsize-2.2 {setting the maxsize to a value smaller\\\n\tthan the current size will resize a gridded toplevel} -body {\n    toplevel .t\n    wm grid .t 0 0 50 50\n    wm geometry .t 6x6\n    update\n    wm maxsize .t 4 3\n    # UpdateGeometryInfo invoked at idle\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {4 3}\ntest wm-maxsize-2.3 {attempting to resize to a value\\\n\tbigger than the current maxsize will set it to the max size} -body {\n    toplevel .t -width 200 -height 200\n    wm maxsize .t 300 250\n    update\n    wm geom .t 400x300\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {300 250}\ntest wm-maxsize-2.4 {attempting to resize to a value bigger than the\\\n\tcurrent maxsize will set it to the max size when gridded} -body {\n    toplevel .t\n    wm grid .t 1 1 50 50\n    wm geom .t 4x4\n    wm maxsize .t 6 5\n    update\n    wm geom .t 8x6\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {6 5}\ntest wm-maxsize-2.5 {Use max size if window size is not explicitly set\\\n\tand the reqWidth/reqHeight are bigger than the max size} -body {\n    toplevel .t\n    pack [frame .t.f -width 400 -height 400]\n    update idletasks\n    set req [list [winfo reqwidth .t] [winfo reqheight .t]]\n    wm maxsize .t 300 300\n    update\n    list $req [lrange [split [wm geom .t] x+] 0 1]\n} -cleanup {\n    destroy .t\n} -result {{400 400} {300 300}}\n\n\n### wm minsize ###\ntest wm-minsize-1.1 {usage} -returnCodes error -body {\n    wm minsize\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-minsize-1.2 {usage} -returnCodes error -body {\n    wm minsize . a\n} -result {wrong # args: should be \"wm minsize window ?width height?\"}\ntest wm-minsize-1.3 {usage} -returnCodes error -body {\n    wm minsize . a b c\n} -result {wrong # args: should be \"wm minsize window ?width height?\"}\ntest wm-minsize-1.4 {usage} -returnCodes error -body {\n    wm minsize . x 100\n} -result {expected screen distance but got \"x\"}\ntest wm-minsize-1.5 {usage} -returnCodes error -body {\n    wm minsize . 100 bogus\n} -result {expected screen distance but got \"bogus\"}\ntest wm-minsize-1.6 {usage} -setup {\n    destroy .t2\n} -body {\n    toplevel .t2\n    wm minsize .t2 300 200\n    wm minsize .t2\n} -cleanup {\n    destroy .t2\n} -result {300 200}\n\ntest wm-minsize-2.1 {setting the minsize to a value larger\\\n\tthan the current size will resize a toplevel} -body {\n    toplevel .t -width 200 -height 200\n    update\n    wm minsize .t 400 300\n    # UpdateGeometryInfo invoked at idle\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {400 300}\ntest wm-minsize-2.2 {setting the minsize to a value larger\\\n\tthan the current size will resize a gridded toplevel} -body {\n    toplevel .t\n    wm grid .t 1 1 50 50\n    wm geom .t 4x4\n    update\n    wm minsize .t 8 8\n    # UpdateGeometryInfo invoked at idle\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {8 8}\ntest wm-minsize-2.3 {attempting to resize to a value\\\n\tsmaller than the current minsize will set it to the minsize} -body {\n    toplevel .t -width 400 -height 400\n    wm minsize .t 300 300\n    update\n    wm geom .t 200x200\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {300 300}\ntest wm-minsize-2.4 {attempting to resize to a value smaller than the\\\n\tcurrent minsize will set it to the minsize when gridded} -body {\n    toplevel .t\n    wm grid .t 1 1 50 50\n    wm geom .t 8x8\n    wm minsize .t 6 6\n    update\n    wm geom .t 4x4\n    update\n    lrange [split [wm geom .t] x+] 0 1\n} -cleanup {\n    destroy .t\n} -result {6 6}\ntest wm-minsize-2.5 {Use min size if window size is not explicitly set\\\n\tand the reqWidth/reqHeight are smaller than the min size} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    pack [frame .t.f -width 250 -height 250]\n    update idletasks\n    lappend result [list [winfo reqwidth .t] [winfo reqheight .t]]\n    wm minsize .t 300 300\n    update\n    lappend result [lrange [split [wm geom .t] x+] 0 1]\n} -cleanup {\n    destroy .t\n} -result {{250 250} {300 300}}\n\n#\n# COMMON TEST SETUP\n#\nstdWindow\n\n### wm overrideredirect ###\ntest wm-overrideredirect-1.1 {usage} -returnCodes error -body {\n    wm overrideredirect\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-overrideredirect-1.2 {usage} -returnCodes error -body {\n    wm overrideredirect .t 1 2\n} -result {wrong # args: should be \"wm overrideredirect window ?boolean?\"}\ntest wm-overrideredirect-1.3 {usage} -returnCodes error -body {\n    wm overrideredirect .t boo\n} -result {expected boolean value but got \"boo\"}\n\ntest wm-overrideredirect-2.1 {setting and reading values} -setup {\n    set result {}\n} -body {\n    lappend result [wm overrideredirect .t]\n    wm overrideredirect .t true\n    lappend result [wm overrideredirect .t]\n    wm overrideredirect .t off\n    lappend result [wm overrideredirect .t]\n} -result {0 1 0}\n\n\n### wm positionfrom ###\ntest wm-positionfrom-1.1 {usage} -returnCodes error -body {\n    wm positionfrom\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-positionfrom-1.2 {usage} -returnCodes error -body {\n    wm positionfrom .t 1 2\n} -result {wrong # args: should be \"wm positionfrom window ?user/program?\"}\ntest wm-positionfrom-1.3 {usage} -returnCodes error -body {\n    wm positionfrom .t none\n} -result {bad argument \"none\": must be program or user}\n\ntest wm-positionfrom-2.1 {setting and reading values} -setup {\n    destroy .t2\n    set result {}\n} -body {\n    toplevel .t2\n    wm positionfrom .t user\n    lappend result [wm positionfrom .t]\n    wm positionfrom .t program\n    lappend result [wm positionfrom .t]\n    wm positionfrom .t {}\n    lappend result [wm positionfrom .t]\n} -cleanup {\n    destroy .t2\n} -result {user program {}}\n\n\n### wm protocol ###\ntest wm-protocol-1.1 {usage} -returnCodes error -body {\n    wm protocol\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-protocol-1.2 {usage} -returnCodes error -body {\n    wm protocol .t 1 2 3\n} -result {wrong # args: should be \"wm protocol window ?name? ?command?\"}\n\ntest wm-protocol-2.1 {setting and reading values} -body {\n    wm protocol .t {foo a} {a b c}\n    wm protocol .t bar {test script for bar}\n    wm protocol .t\n} -cleanup {\n    wm protocol .t {foo a} {}\n    wm protocol .t bar {}\n} -result {bar {foo a}}\ntest wm-protocol-2.2 {setting and reading values} -setup {\n    set result {}\n} -body {\n    wm protocol .t foo {a b c}\n    wm protocol .t bar {test script for bar}\n    lappend result [wm protocol .t foo] [wm protocol .t bar]\n    wm protocol .t foo {}\n    wm protocol .t bar {}\n    lappend result [wm protocol .t foo] [wm protocol .t bar]\n} -result {{a b c} {test script for bar} {} {}}\ntest wm-protocol-2.3 {setting and reading values} -body {\n    wm protocol .t foo {a b c}\n    wm protocol .t foo {test script}\n    wm protocol .t foo\n} -cleanup {\n    wm protocol .t foo {}\n} -result {test script}\n\n\n### wm resizable ###\ntest wm-resizable-1.1 {usage} -returnCodes error -body {\n    wm resizable\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-resizable-1.2 {usage} -returnCodes error -body {\n    wm resizable .t 1\n} -result {wrong # args: should be \"wm resizable window ?width height?\"}\ntest wm-resizable-1.3 {usage} -returnCodes error -body {\n    wm resizable .t 1 2 3\n} -result {wrong # args: should be \"wm resizable window ?width height?\"}\ntest wm-resizable-1.4 {usage} -returnCodes error -body {\n    wm resizable .t bad 0\n} -result {expected boolean value but got \"bad\"}\ntest wm-resizable-1.5 {usage} -returnCodes error -body {\n    wm resizable .t 1 bad\n} -result {expected boolean value but got \"bad\"}\n\ntest wm-resizable-2.1 {setting and reading values} {\n    wm resizable .t 0 0\n    set result [wm resizable .t]\n    wm resizable .t 0 1\n    lappend result [wm resizable .t]\n    wm resizable .t 1 0\n    lappend result [wm resizable .t]\n    wm resizable .t 1 1\n    lappend result [wm resizable .t]\n} {0 0 {0 1} {1 0} {1 1}}\n\n\n### wm sizefrom ###\ntest wm-sizefrom-1.1 {usage} -returnCodes error -body {\n    wm sizefrom\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-sizefrom-1.2 {usage} -returnCodes error -body {\n    wm sizefrom .t 1 2\n} -result {wrong # args: should be \"wm sizefrom window ?user|program?\"}\ntest wm-sizefrom-1.4 {usage} -returnCodes error -body {\n    wm sizefrom .t bad\n} -result {bad argument \"bad\": must be program or user}\n\ntest wm-sizefrom-2.1 {setting and reading values} {\n    set result [list [wm sizefrom .t]]\n    wm sizefrom .t user\n    lappend result [wm sizefrom .t]\n    wm sizefrom .t program\n    lappend result [wm sizefrom .t]\n    wm sizefrom .t {}\n    lappend result [wm sizefrom .t]\n} {{} user program {}}\n\n#\n# COMMON TEST CLEANUP\n#\ndestroy .t\n\n### wm stackorder ###\ntest wm-stackorder-1.1 {usage} -returnCodes error -body {\n    wm stackorder\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-stackorder-1.2 {usage} -returnCodes error -body {\n    wm stackorder . _\n} -result {wrong # args: should be \"wm stackorder window ?isabove|isbelow window?\"}\ntest wm-stackorder-1.3 {usage} -returnCodes error -body {\n    wm stackorder . _ _ _\n} -result {wrong # args: should be \"wm stackorder window ?isabove|isbelow window?\"}\ntest wm-stackorder-1.4 {usage} -returnCodes error -body {\n    wm stackorder . is .\n} -result {ambiguous argument \"is\": must be isabove or isbelow}\ntest wm-stackorder-1.5 {usage} -returnCodes error -body {\n    wm stackorder _\n} -result {bad window path name \"_\"}\ntest wm-stackorder-1.6 {usage} -returnCodes error -body {\n    wm stackorder . isabove _\n} -result {bad window path name \"_\"}\ntest wm-stackorder-1.7 {usage} -body {\n    toplevel .t\n    button .t.b\n    wm stackorder .t.b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {window \".t.b\" isn't a top-level window}\ntest wm-stackorder-1.8 {usage} -body {\n    toplevel .t\n    button .t.b\n    pack .t.b\n    update\n    wm stackorder . isabove .t.b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {window \".t.b\" isn't a top-level window}\ntest wm-stackorder-1.9 {usage} -body {\n    toplevel .t\n    button .t.b\n    pack .t.b\n    update\n    wm stackorder . isbelow .t.b\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {window \".t.b\" isn't a top-level window}\ntest wm-stackorder-1.10 {usage, isabove|isbelow toplevels must be mapped} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    wm stackorder .t isabove .\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {window \".t\" isn't mapped}\ntest wm-stackorder-1.11 {usage, isabove|isbelow toplevels must be mapped} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    wm stackorder . isbelow .t\n} -cleanup {\n    destroy .t\n} -returnCodes error -result {window \".t\" isn't mapped}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-stackorder-2.1 {stacking order} -body {\n    toplevel .t ; update\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t\n} -result {. .t}\ntest wm-stackorder-2.2 {stacking order} -body {\n    toplevel .t ; update\n    raise .\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t\n} -result {.t .}\ntest wm-stackorder-2.3 {stacking order} -body {\n    set res {}\n    toplevel .t\n    tkwait visibility .t\n    raiseDelay\n    toplevel .t2\n    tkwait visibility .t2\n    raiseDelay\n    lappend res [wm stackorder .]\n    raise .\n    raiseDelay\n    lappend res [wm stackorder .]\n    raise .t2\n    raiseDelay\n    lappend res [wm stackorder .]\n    set res\n} -cleanup {\n    destroy .t .t2\n} -result {{. .t .t2} {.t .t2 .} {.t . .t2}}\ntest wm-stackorder-2.4 {stacking order} -body {\n    toplevel .t ; update\n    toplevel .t2 ; update\n    raise .\n    lower .t2\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t .t2\n} -result {.t2 .t .}\ntest wm-stackorder-2.5 {stacking order} -setup {\n    destroy .parent\n} -body {\n    toplevel .parent ; update\n    destroy .parent.child1\n    toplevel .parent.child1 ; update\n    destroy .parent.child2\n    toplevel .parent.child2 ; update\n    destroy .extra\n    toplevel .extra ; update\n    raise .parent\n    lower .parent.child2\n    raiseDelay\n    wm stackorder .parent\n} -cleanup {\n    deleteWindows\n} -result {.parent.child2 .parent.child1 .parent}\ntest wm-stackorder-2.6 {stacking order: non-toplevel widgets ignored} -body {\n    toplevel .t1\n    raiseDelay\n    button .t1.b\n    pack .t1.b\n    update\n    wm stackorder .\n} -cleanup {\n    destroy .t1\n} -result {. .t1}\ntest wm-stackorder-2.7 {stacking order: no children returns self} -setup {\n    deleteWindows\n} -body {\n    wm stackorder .\n} -result {.}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-stackorder-3.1 {unmapped toplevel} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .t1 ; update\n    raiseDelay\n    toplevel .t2 ; update\n    raiseDelay\n    wm iconify .t1\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t1 .t2\n} -result {. .t2}\ntest wm-stackorder-3.2 {unmapped toplevel} -body {\n    toplevel .t1 ; update\n    toplevel .t2 ; update\n    wm withdraw .t2\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t1 .t2\n} -result {. .t1}\ntest wm-stackorder-3.3 {unmapped toplevel} -body {\n    toplevel .t1 ; update\n    toplevel .t2 ; update\n    wm withdraw .t2\n    wm stackorder .t2\n} -cleanup {\n    destroy .t1 .t2\n} -result {}\ntest wm-stackorder-3.4 {unmapped toplevel} -body {\n    toplevel .t1 ; update\n    toplevel .t1.t2 ; update\n    wm withdraw .t1.t2\n    wm stackorder .t1\n} -cleanup {\n    destroy .t1\n} -result {.t1}\ntest wm-stackorder-3.5 {unmapped toplevel} -body {\n    toplevel .t1 ; update\n    toplevel .t1.t2 ; update\n    wm withdraw .t1\n    wm stackorder .t1\n} -cleanup {\n    destroy .t1\n} -result {.t1.t2}\ntest wm-stackorder-3.6 {unmapped toplevel} -body {\n    toplevel .t1\n    tkwait visibility .t1\n    toplevel .t1.t2\n    tkwait visibility .t1.t2\n    toplevel .t1.t2.t3\n    tkwait visibility .t1.t2.t3\n    wm withdraw .t1.t2\n    raiseDelay\n    wm stackorder .t1\n} -cleanup {\n    destroy .t1\n} -result {.t1 .t1.t2.t3}\ntest wm-stackorder-3.7 {unmapped toplevel, mapped children returned} -body {\n    toplevel .t1 ; update\n    toplevel .t1.t2 ; update\n    wm withdraw .t1\n    wm stackorder .t1\n} -cleanup {\n    destroy .t1\n} -result {.t1.t2}\ntest wm-stackorder-3.8 {toplevel mapped in idle callback} -body {\n    toplevel .t1\n    wm stackorder .\n} -cleanup {\n    destroy .t1\n} -result {.}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-stackorder-4.1 {wm stackorder isabove|isbelow} -body {\n    toplevel .t ; update\n    raise .t\n    wm stackorder . isabove .t\n} -cleanup {\n    destroy .t\n} -result 0\ntest wm-stackorder-4.2 {wm stackorder isabove|isbelow} -body {\n    toplevel .t ; update\n    raise .t\n    wm stackorder . isbelow .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest wm-stackorder-4.3 {wm stackorder isabove|isbelow} -body {\n    toplevel .t\n    tkwait visibility .t\n    raise .\n    raiseDelay\n    wm stackorder .t isabove .\n} -cleanup {\n    destroy .t\n} -result 0\ntest wm-stackorder-4.4 {wm stackorder isabove|isbelow} -body {\n    toplevel .t ; update\n    raise .\n    raiseDelay\n    wm stackorder .t isb .\n} -cleanup {\n    destroy .t\n} -result 1\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-stackorder-5.1 {a menu is not a toplevel} -body {\n    toplevel .t\n    menu .t.m -type menubar\n    .t.m add cascade -label \"File\"\n    .t configure -menu .t.m\n    update\n    raise .\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    destroy .t\n} -result {.t .}\ntest wm-stackorder-5.2 {A normal toplevel can't be raised above an \\\n    overrideredirect toplevel on unix} -constraints {x11 failsOnCILinux failsOnXQuartz} -body {\n    toplevel .t\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    raise .\n    update\n    raiseDelay\n    wm stackorder . isabove .t\n} -cleanup {\n    destroy .t\n} -result 0\ntest wm-stackorder-5.2.1 {A normal toplevel can be raised above an \\\n    overrideredirect toplevel on macOS or win} -constraints aquaOrWin32 -body {\n    toplevel .t\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    raise .\n    update\n    raiseDelay\n    wm stackorder . isabove .t\n} -cleanup {\n    destroy .t\n} -result 1\ntest wm-stackorder-5.3 {An overrideredirect window\\\n\tcan be explicitly lowered} -body {\n    toplevel .t\n    wm overrideredirect .t 1\n    tkwait visibility .t\n    lower .t\n    update\n    raiseDelay\n    wm stackorder .t isbelow .\n} -cleanup {\n    destroy .t\n} -result 1\n\ntest wm-stackorder-6.1 {An embedded toplevel does not appear in the \\\n\t stacking order} -body {\n    toplevel .real -container 1\n    raiseDelay\n    toplevel .embd -bg blue -use [winfo id .real]\n    raiseDelay\n    wm stackorder .\n} -cleanup {\n    deleteWindows\n} -result {. .real}\n\n#\n# COMMON TEST SETUP\n#\nstdWindow\n\n### wm title ###\ntest wm-title-1.1 {usage} -returnCodes error -body {\n    wm title\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-title-1.2 {usage} -returnCodes error -body {\n    wm title . 1 2\n} -result {wrong # args: should be \"wm title window ?newTitle?\"}\n\ntest wm-title-2.1 {setting and reading values} -setup {\n    destroy .t\n} -body {\n    toplevel .t\n    set result [wm title .t]\n    wm title .t Apa\n    lappend result [wm title .t]\n    wm title .t {}\n    lappend result [wm title .t]\n} -result {t Apa {}}\n\n\n### wm transient ###\ntest wm-transient-1.1 {usage} -returnCodes error -body {\n    catch {destroy .t} ; toplevel .t\n    wm transient .t 1 2\n} -result {wrong # args: should be \"wm transient window ?window?\"}\ntest wm-transient-1.2 {usage} -returnCodes error -body {\n    catch {destroy .t} ; toplevel .t\n    wm transient .t foo\n} -result {bad window path name \"foo\"}\ntest wm-transient-1.3 {usage} -returnCodes error -body {\n    catch {destroy .t} ; toplevel .t\n    wm transient foo .t\n} -result {bad window path name \"foo\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-transient-1.4 {usage} -returnCodes error -body {\n    toplevel .top\n    toplevel .subject\n    wm transient .subject .top\n    wm iconify .subject\n} -cleanup {\n    deleteWindows\n} -result {can't iconify \".subject\": it is a transient}\ntest wm-transient-1.5 {usage} -returnCodes error -body {\n    toplevel .icon -bg blue\n    toplevel .top\n    wm iconwindow .top .icon\n    toplevel .dummy\n    wm transient .icon .dummy\n} -cleanup {\n    deleteWindows\n} -result {can't make \".icon\" a transient: it is an icon for .top}\ntest wm-transient-1.6 {usage} -returnCodes error -body {\n    toplevel .icon -bg blue\n    toplevel .top\n    wm iconwindow .top .icon\n    toplevel .dummy\n    wm transient .dummy .icon\n} -cleanup {\n    deleteWindows\n} -result {can't make \".icon\" a container: it is an icon for .top}\ntest wm-transient-1.7 {usage} -returnCodes error -body {\n    toplevel .top\n    wm transient .top .top\n} -cleanup {\n    deleteWindows\n} -result {can't set \".top\" as container: would cause management loop}\ntest wm-transient-1.8 {usage} -returnCodes error -body {\n    toplevel .t1\n    toplevel .t2\n    toplevel .t3\n    wm transient .t2 .t1\n    wm transient .t3 .t2\n    wm transient .t1 .t3\n} -cleanup {\n    deleteWindows\n} -result {can't set \".t3\" as container: would cause management loop}\ntest wm-transient-1.9 {usage} -returnCodes error -body {\n    toplevel .top\n    frame .top.f\n    wm transient .top .top.f\n} -cleanup {\n    deleteWindows\n} -result {can't set \".top\" as container: would cause management loop}\n\ntest wm-transient-2.1 {basic get/set of toplevel} -setup {\n    set results [list]\n} -body {\n    toplevel .top\n    toplevel .subject\n    lappend results [wm transient .subject]\n    wm transient .subject .top\n    lappend results [wm transient .subject]\n    wm transient .subject {}\n    lappend results [wm transient .subject]\n} -cleanup {\n    deleteWindows\n} -result {{} .top {}}\ntest wm-transient-2.2 {first toplevel parent of non-toplevel container window is used} -body {\n    toplevel .top\n    frame .top.f\n    toplevel .subject\n    wm transient .subject .top.f\n    wm transient .subject\n} -cleanup {\n    deleteWindows\n} -result {.top}\n\ntest wm-transient-3.1 {transient toplevel is withdrawn\n\twhen mapped if toplevel is withdrawn} -body {\n    toplevel .top\n    wm withdraw .top\n    update\n    toplevel .subject\n    wm transient .subject .top\n    update\n    list [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0}\ntest wm-transient-3.2 {already mapped transient toplevel\n\ttakes on withdrawn state of toplevel} -body {\n    toplevel .top\n    wm withdraw .top\n    update\n    toplevel .subject\n    update\n    wm transient .subject .top\n    update\n    list [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0}\ntest wm-transient-3.3 {withdraw/deiconify on the toplevel\n\talso does a withdraw/deiconify on the transient} -setup {\n    set results [list]\n} -body {\n    toplevel .top\n    toplevel .subject\n    update\n    wm transient .subject .top\n    wm withdraw .top\n    update\n    lappend results [wm state .subject] [winfo ismapped .subject]\n    wm deiconify .top\n    update\n    lappend results [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0 normal 1}\n\ntest wm-transient-4.1 {transient toplevel is withdrawn\n\twhen mapped if toplevel is iconic} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .top\n    wm iconify .top\n    update\n    toplevel .subject\n    wm transient .subject .top\n    update\n    list [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0}\ntest wm-transient-4.2 {already mapped transient toplevel\n\tis withdrawn if toplevel is iconic} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .top\n    raiseDelay\n    wm iconify .top\n    update idletasks\n    toplevel .subject\n    update idletasks\n    wm transient .subject .top\n    update idletasks\n    list [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0}\ntest wm-transient-4.3 {iconify/deiconify on the toplevel\n\tdoes a withdraw/deiconify on the transient} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    set results [list]\n} -body {\n    toplevel .top\n    toplevel .subject\n    update idletasks\n    wm transient .subject .top\n    wm iconify .top\n    update idletasks\n    lappend results [wm state .subject] [winfo ismapped .subject]\n    wm deiconify .top\n    update idletasks\n    lappend results [wm state .subject] [winfo ismapped .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0 normal 1}\n\ntest wm-transient-5.1 {an error during transient command should not\n\tcause the map/unmap binding to be deleted} -setup {\n    set results [list]\n} -body {\n    toplevel .top\n    toplevel .subject\n    update\n    wm transient .subject .top\n    # Expect a bad window path error here\n    lappend results [catch {wm transient .subject .bad}]\n    wm withdraw .top\n    update\n    lappend results [wm state .subject]\n    wm deiconify .top\n    update\n    lappend results [wm state .subject]\n} -cleanup {\n    deleteWindows\n} -result {1 withdrawn normal}\ntest wm-transient-5.2 {remove transient property when toplevel\n\tis destroyed} -body {\n    toplevel .top\n    toplevel .subject\n    wm transient .subject .top\n    update\n    destroy .top\n    update\n    wm transient .subject\n} -cleanup {\n    deleteWindows\n} -result {}\ntest wm-transient-5.3 {remove transient property from window\n\tthat had never been mapped when toplevel is destroyed} -body {\n    toplevel .top\n    toplevel .subject\n    wm transient .subject .top\n    destroy .top\n    wm transient .subject\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest wm-transient-6.1 {a withdrawn transient does not track\n\tstate changes in the toplevel} -body {\n    toplevel .top\n    toplevel .subject\n    update\n    wm transient .subject .top\n    wm withdraw .subject\n    wm withdraw .top\n    wm deiconify .top\n    # idle handler should not map the transient\n    update\n    wm state .subject\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\ntest wm-transient-6.2 {a withdrawn transient does not track\n\tstate changes in the toplevel} -setup {\n    set results [list]\n} -body {\n    toplevel .top\n    toplevel .subject\n    update\n    wm transient .subject .top\n    wm withdraw .subject\n    wm withdraw .top\n    wm deiconify .top\n    # idle handler should not map the transient\n    update\n    lappend results [wm state .subject]\n    wm deiconify .subject\n    lappend results [wm state .subject]\n    wm withdraw .top\n    lappend results [wm state .subject]\n    wm deiconify .top\n    # idle handler should map transient\n    update\n    lappend results [wm state .subject]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn normal withdrawn normal}\ntest wm-transient-6.3 {a withdrawn transient does not track\n\tstate changes in the toplevel} -body {\n    toplevel .top\n    toplevel .subject\n    update\n    # withdraw before making window a transient\n    wm withdraw .subject\n    wm transient .subject .top\n    wm withdraw .top\n    wm deiconify .top\n    # idle handler should not map the transient\n    update\n    wm state .subject\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\n\n# wm-transient-7.*: See SF Tk Bug #592201 \"wm transient fails with two toplevels\"\n# wm-transient-7.3 through 7.5 all caused panics on Unix in Tk 8.4b1.\n# 7.1 and 7.2 added to catch (potential) future errors.\n#\ntest wm-transient-7.1 {Destroying transient} -body {\n    toplevel .t\n    toplevel .transient\n    wm transient .transient .t\n    destroy .transient\n    destroy .t\n    # OK: the above did not cause a panic.\n} -cleanup {\n    deleteWindows\n}\ntest wm-transient-7.2 {Destroying toplevel} -body {\n    toplevel .top\n    toplevel .transient\n    wm transient .transient .top\n    destroy .top\n    wm transient .transient\n} -cleanup {\n    deleteWindows\n} -result {}\ntest wm-transient-7.3 {Reassign transient, destroy old toplevel} -body {\n    toplevel .t1\n    toplevel .t2\n    toplevel .transient\n    wm transient .transient .t1\n    wm transient .transient .t2\n    destroy .t1\t;# Caused panic in 8.4b1\n    destroy .t2\n    destroy .transient\n} -cleanup {\n    deleteWindows\n}\ntest wm-transient-7.4 {Reassign transient, destroy new toplevel} -body {\n    toplevel .t1\n    toplevel .t2\n    toplevel .transient\n    wm transient .transient .t1\n    wm transient .transient .t2\n    destroy .t2\t\t;# caused panic in 8.4b1\n    destroy .t1\n    destroy .transient\n} -cleanup {\n    deleteWindows\n}\ntest wm-transient-7.5 {Reassign transient, destroy transient} -body {\n    toplevel .t1\n    toplevel .t2\n    toplevel .transient\n    wm transient .transient .t1\n    wm transient .transient .t2\n    destroy .transient\n    destroy .t2\t\t;# caused panic in 8.4b1\n    destroy .t1\t\t;# so did this\n} -cleanup {\n    deleteWindows\n}\n\ntest wm-transient-8.1 {transient to withdrawn window, Bug 1163496} -constraints {failsOnCILinux failsOnXQuartz} -setup {\n    deleteWindows\n    set result {}\n} -body {\n    # Verifies that transients stay on top of their toplevels, even if they were\n    # made transients when those toplevels were withdrawn.\n    toplevel .t1; wm withdraw  .t1;     update\n    toplevel .t2; wm transient .t2 .t1; update\n    lappend result [winfo ismapped .t1] [winfo ismapped .t2]\n    wm deiconify .t1; update\n    lappend result [winfo ismapped .t1] [winfo ismapped .t2]\n    raise .t1; raiseDelay; update\n    lappend result [lsearch -all -inline -glob [wm stackorder .] \".t?\"]\n} -cleanup {\n    deleteWindows\n} -result {0 0 1 1 {.t1 .t2}}\n\n\n### wm state ###\ntest wm-state-1.1 {usage} -returnCodes error -body {\n    wm state\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-state-1.2 {usage} -returnCodes error -body {\n    wm state . _ _\n} -result {wrong # args: should be \"wm state window ?state?\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-state-2.1 {initial state} -body {\n    toplevel .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.2 {state change before map} -body {\n    toplevel .t\n    wm state .t withdrawn\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\ntest wm-state-2.3 {state change before map} -body {\n    toplevel .t\n    wm withdraw .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\ntest wm-state-2.4 {state change after map} -body {\n    toplevel .t\n    update\n    wm state .t withdrawn\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\ntest wm-state-2.5 {state change after map} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {withdrawn}\ntest wm-state-2.6 {state change before map} -body {\n    toplevel .t\n    wm state .t iconic\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {iconic}\ntest wm-state-2.7 {state change before map} -body {\n    toplevel .t\n    wm iconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {iconic}\ntest wm-state-2.8 {state change after map} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .t\n    update\n    wm state .t iconic\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {iconic}\ntest wm-state-2.9 {state change after map} -constraints {failsOnCILinux failsOnXQuartz} -body {\n    toplevel .t\n    update\n    wm iconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {iconic}\ntest wm-state-2.10 {state change before map} -body {\n    toplevel .t\n    wm withdraw .t\n    wm state .t normal\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.11 {state change before map} -body {\n    toplevel .t\n    wm withdraw .t\n    wm deiconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.12 {state change after map} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    wm state .t normal\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.13 {state change after map} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    wm deiconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.14 {state change before map} -body {\n    toplevel .t\n    wm iconify .t\n    wm state .t normal\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.15 {state change before map} -body {\n    toplevel .t\n    wm iconify .t\n    wm deiconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.16 {state change after map} -body {\n    toplevel .t\n    update\n    wm iconify .t\n    wm state .t normal\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.17 {state change after map} -body {\n    toplevel .t\n    update\n    wm iconify .t\n    wm deiconify .t\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {normal}\ntest wm-state-2.18 {state change after map} -constraints win -body {\n    toplevel .t\n    update\n    wm state .t zoomed\n    wm state .t\n} -cleanup {\n    deleteWindows\n} -result {zoomed}\n\n\n### wm withdraw ###\ntest wm-withdraw-1.1 {usage} -returnCodes error -body {\n    wm withdraw\n} -result {wrong # args: should be \"wm option window ?arg ...?\"}\ntest wm-withdraw-1.2 {usage} -returnCodes error -body {\n    wm withdraw . _\n} -result {wrong # args: should be \"wm withdraw window\"}\n\n#\n# COMMON TEST CLEANUP\n#\ndeleteWindows\n\ntest wm-withdraw-2.1 {Misc errors} -body {\n    toplevel .t\n    toplevel .t2\n    wm iconwindow .t .t2\n    wm withdraw .t2\n} -returnCodes error -cleanup {\n    deleteWindows\n} -result {can't withdraw .t2: it is an icon for .t}\n\ntest wm-withdraw-3.1 {} -setup {\n    set result {}\n} -body {\n    toplevel .t\n    update\n    wm withdraw .t\n    lappend result [wm state .t] [winfo ismapped .t]\n    wm deiconify .t\n    lappend result [wm state .t] [winfo ismapped .t]\n} -cleanup {\n    deleteWindows\n} -result {withdrawn 0 normal 1}\n\n\n### Misc. wm tests ###\ntest wm-deletion-epoch-1.1 {Deletion epoch on multiple displays} -constraints altDisplay -body {\n    # See Tk Bug #671330 \"segfault when e.g. deiconifying destroyed window\"\n    set w [toplevel .t -screen $env(TK_ALT_DISPLAY)]\n    wm deiconify $w         ;# this caches the WindowRep\n    destroy .t\n    wm deiconify $w\n} -returnCodes error -result {bad window path name \".t\"} -cleanup {\n    deleteWindows\n}\n\n### Docking test (manage, forget) ###\ntest wm-manage-1.1 {managing a frame} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    frame .t.f\n    pack [label .t.f.l -text hello]\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -result {wm .t.f}\ntest wm-manage-1.2 {managing a toplevel} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    pack [label .t.l -text hello]\n    wm manage .t\n    raise .t\n    update\n    lappend result [winfo manage .t]\n    lappend result [winfo toplevel .t]\n} -cleanup {\n    deleteWindows\n} -result {wm .t}\ntest wm-manage-1.3 {managing a labelframe} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    labelframe .t.f -text Labelframe\n    pack [label .t.f.l -text hello]\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -result {wm .t.f}\ntest wm-manage-1.4 {managing a ttk::frame} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    ttk::frame .t.f\n    pack [label .t.f.l -text hello]\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result \"window \\\".t.f\\\" is not manageable: must be a frame, labelframe or toplevel\"\ntest wm-manage-1.5 {managing a text widget} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    text .t.f\n    .t.f insert end \"Manage text\\n\" {}\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result \"window \\\".t.f\\\" is not manageable: must be a frame, labelframe or toplevel\"\ntest wm-manage-1.6 {managing a button} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    button .t.f -text Button\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -returnCodes error -result \"window \\\".t.f\\\" is not manageable: must be a frame, labelframe or toplevel\"\ntest wm-manage-1.7 {managing a frame} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    frame .t.f\n    pack [label .t.f.l -text Label]\n    pack .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n    wm manage .t.f\n    raise .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n    wm forget .t.f\n    pack .t.f\n    update\n    lappend result [winfo manage .t.f]\n    lappend result [winfo toplevel .t.f]\n} -cleanup {\n    deleteWindows\n} -result {pack .t wm .t.f pack .t}\ntest wm-manage-1.8 {unmanaging a toplevel} -setup {\n    set result [list]\n} -body {\n    toplevel .t\n    toplevel .t.t\n    button .t.t.b -text \"Manage This\"\n    pack .t.t.b\n    update\n    lappend result [winfo manage .t.t]\n    lappend result [winfo toplevel .t.t.b]\n    wm forget .t.t\n    wm forget .t.t ; # second call should be a no-op\n    pack .t.t\n    update\n    lappend result [winfo manage .t.t]\n    lappend result [winfo toplevel .t.t.b]\n    wm manage .t.t\n    wm manage .t.t ; # second call should be a no-op\n    wm deiconify .t.t\n    update\n    lappend result [winfo manage .t.t]\n    lappend result [winfo toplevel .t.t.b]\n} -cleanup {\n    deleteWindows\n} -result {wm .t.t pack .t wm .t.t}\n\ntest wm-forget-1.1 \"bug #2009788: forget toplevel can cause crash\" -body {\n    toplevel .parent\n    toplevel .parent.child\n    wm forget .parent.child\n    winfo exists .parent.child\n} -cleanup {\n    deleteWindows\n}  -result 1\ntest wm-forget-1.2 \"bug #2009788: forget toplevel can cause crash\" -body {\n    toplevel .parent\n    update\n    toplevel .parent.child\n    wm forget .parent.child\n    winfo exists .parent.child\n} -cleanup {\n    deleteWindows\n}  -result 1\ntest wm-forget-1.3 \"bug #2009788: forget toplevel can cause crash\" -body {\n    toplevel .parent\n    toplevel .parent.child\n    wm forget .parent.child\n    wm manage .parent.child\n    winfo exists .parent.child\n} -cleanup {\n    deleteWindows\n}  -result 1\ntest wm-forget-1.4 \"pack into unmapped toplevel causes crash\" -body {\n    toplevel .parent\n    toplevel .parent.child\n    wm forget .parent.child\n    pack [button .parent.child.button -text Hello]\n    after 250 {destroy .parent}\n    tkwait window .parent\n} -cleanup {\n    deleteWindows\n} -result {}\n\ntest wm-forget-1.5 {check wm forget for unmapped parent (ref. #3205464,#2967911,#3567786,#3381288)\n    #\n    # Moved here from winWm.test, test winWm-9.2 (cf. ticket #83eed90f93).\n    #\n} -constraints {\n    failsOnCILinux failsOnXQuartz\n} -setup {\n    destroy .t\n    toplevel .t\n    frame .t.f -background blue -height 200 -width 200\n    frame .t.f.x -background red -height 100 -width 100\n    set result {}\n} -body {\n    pack .t.f.x\n    pack .t.f\n    lappend aid [after 5000 {set ::result timeout}] [after 500 {\n\twm manage .t.f\n\twm iconify .t\n\tlappend aid [after 500 {\n\t    wm forget .t.f\n\t    wm deiconify .t\n\t    lappend aid [after 500 {\n\t\tpack .t.f\n\t\tlappend aid [after 500 {\n\t\t    set ::result [expr {\n\t\t\t    [winfo rooty .t.f.x] == 0 ? \"failed\" : \"ok\"}]}]\n\t    }]\n\t}]\n    }]\n    vwait ::result\n    foreach id $aid {\n\tafter cancel $id\n    }\n    set result\n} -cleanup {\n    destroy .t.f.x .t.f .t\n    unset -nocomplain result aid id\n} -result ok\n\ntest wm-forget-2 {bug [e9112ef96e] - [wm forget] doesn't completely} -setup {\n    catch {destroy .l .f.b .f}\n    set res {}\n} -body {\n    label .l -text \"Top Dot\"\n    frame .f\n    button .f.b -text Hello -command \"puts Hello!\"\n    pack .l -side top\n    pack .f.b\n    pack .f -side bottom\n    set res [winfo manager .f]\n    pack forget .f\n    update\n    lappend res [winfo manager .f]\n    wm manage .f\n    update\n    lappend res [winfo manager .f]\n    wm forget .f\n    update\n    lappend res [winfo manager .f]\n} -cleanup {\n    destroy .l .f.b .f\n    unset res\n} -result {pack {} wm {}}\n\ntest wm-forget-2.1 {bug [c77b426dc9] - panic with [menu]+[wm forget]} -constraints {\n    x11\n} -setup {\n    catch {destroy .l .f.b .f}\n    set res {}\n} -body {\n    menu .m\n    .m post 100 100\n    update\n    lappend res [winfo ismapped .m]\n    wm forget .m\n    update\n    lappend res [winfo ismapped .m]\n} -cleanup {\n    destroy .m\n    unset res\n} -result {1 1}\n\n#\n# TESTFILE CLEANUP\n#\n\ndeleteWindows\ncleanupTests\ncatch {unset results}\ncatch {unset focusin}\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "tests/xmfbox.test",
    "content": "# This file is a Tcl script to test the file dialog that's used\n# when the tk_strictMotif flag is set. Because the file dialog\n# runs in a modal loop, the only way to test it sufficiently is\n# to call the internal Tcl procedures in xmfbox.tcl directly.\n#\n# Copyright © 1997 Sun Microsystems, Inc.\n# Copyright © 1998-1999 Scriptics Corporation.\n# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)\n# All rights reserved.\n\n#\n# TESTFILE INITIALIZATION\n#\n\npackage require tcltest 2.2; # needed in mode -singleproc 0\n\n# Load the main script main.tcl, which takes care of:\n# - setup for the application and the root window\n# - importing commands from the tcltest namespace\n# - loading of the testutils mechanism along with its utility procs\n# - loading of Tk specific test constraints (additionally to constraints\n#   provided by the package tcltest)\nsource [file join [tcltest::configure -testdir] main.tcl]\n\n# Ensure a pristine initial window state\nresetWindows\n\n#\n# LOCAL UTILITY PROCS\n#\n\nproc cleanup {} {\n    global testPWD\n\n    set err0 [catch {\n\t    cd $testPWD\n    } msg0]\n\n    set err1 [catch {\n\t    if [file exists ./~nosuchuser1] {\n\t\tfile delete ./~nosuchuser1\n\t    }\n    } msg1]\n\n    set err2 [catch {\n\t    if [file exists ./~nosuchuser2] {\n\t\tfile delete ./~nosuchuser2\n\t    }\n    } msg2]\n\n    set err3 [catch {\n\t    if [file exists ./~nosuchuser3] {\n\t\tfile delete ./~nosuchuser3\n\t    }\n    } msg3]\n\n    set err4 [catch {\n\t    if [file exists ./~nosuchuser4] {\n\t\tfile delete ./~nosuchuser4\n\t    }\n    } msg4]\n\n    if {$err0 || $err1 || $err2 || $err3 || $err4} {\n\t    error [list $msg0 $msg1 $msg2 $msg3 $msg4]\n    }\n    catch {unset foo}\n    destroy .foo\n    update\n}\n\n#\n# COMMON TEST SETUP\n#\n\nset testPWD [pwd]\ncatch {unset data foo}\n\n#\n# TESTS\n#\n\ntest xmfbox-1.1 {tk::MotifFDialog_Create, -parent switch} -constraints {\n    unix\n} -setup {\n    catch {unset foo}\n} -body {\n    set x [tk::MotifFDialog_Create foo open {-parent .}]\n} -cleanup {\n    destroy $x\n} -result {.foo}\n\ntest xmfbox-1.2 {tk::MotifFDialog_Create, -parent switch} -constraints {\n    unix\n} -setup {\n    catch {unset foo}\n    deleteWindows\n} -body {\n    toplevel .bar\n    wm geometry .bar +0+0\n    update\n    set x [tk::MotifFDialog_Create foo open {-parent .bar}]\n} -cleanup {\n    destroy $x\n    destroy .bar\n}  -result {.bar.foo}\n\n\ntest xmfbox-2.1 {tk::MotifFDialog_InterpFilter, ~ in dir names} -constraints {\n    unix\n} -body {\n    cleanup\n    file mkdir ./~nosuchuser1\n    set x [tk::MotifFDialog_Create foo open {}]\n    update\n    $::tk::dialog::file::foo(fEnt) delete 0 end\n    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1\n    file normalize [file join {*}[tk::MotifFDialog_InterpFilter $x]]\n} -result \"$testPWD/~nosuchuser1/*\"\n\ntest xmfbox-2.2 {tk::MotifFDialog_InterpFilter, ~ in file names} -constraints {\n    unix\n} -body {\n    cleanup\n    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]\n    set x [tk::MotifFDialog_Create foo open {}]\n    update\n    $::tk::dialog::file::foo(fEnt) delete 0 end\n    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1\n    file normalize [file join {*}[tk::MotifFDialog_InterpFilter $x]]\n} -result \"$testPWD/~nosuchuser1\"\n\ntest xmfbox-2.3 {tk::MotifFDialog_Update, ~ in file names} -constraints {\n    unix\n} -body {\n    cleanup\n    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]\n    set x [tk::MotifFDialog_Create foo open {}]\n    update\n    $::tk::dialog::file::foo(fEnt) delete 0 end\n    $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1\n    tk::MotifFDialog_InterpFilter $x\n    tk::MotifFDialog_Update $x\n    $::tk::dialog::file::foo(fList) get end\n} -result {~nosuchuser1}\n\ntest xmfbox-2.4 {tk::MotifFDialog_LoadFile, ~ in file names} -constraints {\n    unix\n} -body {\n    cleanup\n    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]\n    set x [tk::MotifFDialog_Create foo open {}]\n    update\n    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]\n    expr {$i >= 0}\n} -result 1\n\ntest xmfbox-2.5 {tk::MotifFDialog_BrowseFList, ~ in file names} -constraints {\n    unix\n} -body {\n    cleanup\n    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]\n    set x [tk::MotifFDialog_Create foo open {}]\n    update\n    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]\n    $::tk::dialog::file::foo(fList) selection clear 0 end\n    $::tk::dialog::file::foo(fList) selection set $i\n    tk::MotifFDialog_BrowseFList $x\n    file normalize [$::tk::dialog::file::foo(sEnt) get]\n} -result \"$testPWD/~nosuchuser1\"\n\ntest xmfbox-2.6 {tk::MotifFDialog_ActivateFList, ~ in file names} -constraints {\n    unix\n} -body {\n    cleanup\n    close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}]\n    set x [tk::MotifFDialog_Create foo open {}]\n    set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1]\n    $::tk::dialog::file::foo(fList) selection clear 0 end\n    $::tk::dialog::file::foo(fList) selection set $i\n    tk::MotifFDialog_BrowseFList $x\n    tk::MotifFDialog_ActivateFList $x\n    list $::tk::dialog::file::foo(selectPath) \\\n\t    $::tk::dialog::file::foo(selectFile) [file normalize $tk::Priv(selectFilePath)]\n} -result \"$testPWD ~nosuchuser1 $testPWD/~nosuchuser1\"\n\n#\n# TESTFILE CLEANUP\n#\n\ncleanup\ncleanupTests\n\n# Local variables:\n# mode: tcl\n# End:\n"
  },
  {
    "path": "unix/Makefile.in",
    "content": "#\n# This file is a Makefile for Tk.  If it has the name \"Makefile.in\"\n# then it is a template for a Makefile;  to generate the actual Makefile,\n# run \"./configure\", which is a configuration script generated by the\n# \"autoconf\" program (constructs like \"@foo@\" will get replaced in the\n# actual Makefile.\n\n# Current Tk version;  used in various names.\n\nTCLVERSION\t\t= @TCL_VERSION@\nTCLPATCHL\t\t= @TCL_PATCH_LEVEL@\nVERSION\t\t\t= @TK_VERSION@\nMAJOR_VERSION\t\t= @TK_MAJOR_VERSION@\nMINOR_VERSION\t\t= @TK_MINOR_VERSION@\nPATCH_LEVEL\t\t= @TK_PATCH_LEVEL@\nLOCALES\t\t\t= @LOCALES@\n\n#----------------------------------------------------------------\n# Things you can change to personalize the Makefile for your own\n# site (you can make these changes in either Makefile.in or\n# Makefile, but changes to Makefile will get lost if you re-run\n# the configuration script).\n#----------------------------------------------------------------\n\n# Default top-level directories in which to install architecture-\n# specific files (exec_prefix) and machine-independent files such\n# as scripts (prefix).  The values specified here may be overridden\n# at configure-time with the --exec-prefix and --prefix options\n# to the \"configure\" script.  The *dir vars are standard configure\n# substitutions that are based off prefix and exec_prefix.\n\nprefix\t\t\t= @prefix@\nexec_prefix\t\t= @exec_prefix@\nbindir\t\t\t= @bindir@\nlibdir\t\t\t= @libdir@\nincludedir\t\t= @includedir@\ndatarootdir\t\t= @datarootdir@\nrunstatedir\t\t= @runstatedir@\nmandir\t\t\t= @mandir@\n\n# The following definition can be set to non-null for special systems\n# like AFS with replication.  It allows the pathnames used for installation\n# to be different than those used for actually reference files at\n# run-time.  INSTALL_ROOT is prepended to $prefix and $exec_prefix\n# when installing files.\nINSTALL_ROOT\t\t= $(DESTDIR)\n\n# Directory from which applications will reference the library of Tcl\n# scripts (note: you can set the TK_LIBRARY environment variable at\n# run-time to override the compiled-in location):\nTK_LIBRARY\t\t= @TK_LIBRARY@\n\n# Path to use at runtime to refer to LIB_INSTALL_DIR:\nLIB_RUNTIME_DIR\t\t= @LIB_RUNTIME_DIR@\n\n# Directory in which to install the program wish:\nBIN_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(bindir)\n\n# Directory in which to install the .a or .so binary for the Tk library:\nLIB_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(libdir)\nDLL_INSTALL_DIR\t\t= @DLL_INSTALL_DIR@\n\n# Path name to use when installing library scripts.\nSCRIPT_INSTALL_DIR\t= $(INSTALL_ROOT)$(TK_LIBRARY)\n\n# Directory in which to install the include file tk.h:\nINCLUDE_INSTALL_DIR\t= $(INSTALL_ROOT)$(includedir)\n\n# Path to the private tk header dir:\nPRIVATE_INCLUDE_DIR\t= @PRIVATE_INCLUDE_DIR@\n\n# Directory in which to (optionally) install the private tk headers:\nPRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(PRIVATE_INCLUDE_DIR)\n\n# Top-level directory in which to install manual entries:\nMAN_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(mandir)\n\n# Directory in which to install manual entry for wish:\nMAN1_INSTALL_DIR\t= $(MAN_INSTALL_DIR)/man1\n\n# Directory in which to install manual entries for Tk's C library\n# procedures:\nMAN3_INSTALL_DIR\t= $(MAN_INSTALL_DIR)/man3\n\n# Directory in which to install manual entries for the built-in\n# Tcl commands implemented by Tk:\nMANN_INSTALL_DIR\t= $(MAN_INSTALL_DIR)/mann\n\n# Path to the html documentation dir:\nHTML_DIR\t\t= @HTML_DIR@\n\n# Directory in which to install html documentation:\nHTML_INSTALL_DIR\t= $(INSTALL_ROOT)$(HTML_DIR)\n\n# Directory in which to install the configuration file tkConfig.sh:\nCONFIG_INSTALL_DIR\t= $(INSTALL_ROOT)$(libdir)\n\n# Directory in which to install the demo files:\nDEMO_INSTALL_DIR\t= $(INSTALL_ROOT)@DEMO_DIR@\n\n# The directory containing the Tcl sources and headers appropriate\n# for this version of Tk (\"srcdir\" will be replaced or has already\n# been replaced by the configure script):\nTCLDIR   = @TCL_SRC_DIR@\nTCL_GENERIC_DIR\t\t= $(TCLDIR)/generic\n\n# The directory containing the platform specific Tcl sources and headers\n# appropriate for this version of Tk:\nTCL_PLATFORM_DIR\t= $(TCLDIR)/unix\n\n# The directory containing the Tcl library archive file appropriate\n# for this version of Tk:\nTCL_BIN_DIR\t\t= @TCL_BIN_DIR@\n\n# The linker flags needed to link in the Tcl library (ex: -ltcl9.1)\nTCL_LIB_FLAG\t\t= @TCL_LIB_FLAG@\n\n# Flag, 1: we're building a shared lib, 0 we're not\nTK_SHARED_BUILD\t\t= @TK_SHARED_BUILD@\n\n# Subdirectory of $(libdir) containing the pkgIndex.tcl file for loadable Tk\nTK_PKG_DIR\t\t= @TK_PKG_DIR@\n\n# Directory in which to install the pkgIndex.tcl file for loadable Tk\nPKG_INSTALL_DIR\t\t= $(LIB_INSTALL_DIR)/$(TK_PKG_DIR)\n\n# Package index file for loadable Tk\nPKG_INDEX\t\t= $(PKG_INSTALL_DIR)/pkgIndex.tcl\n\n# warning flags\nCFLAGS_WARNING\t\t= @CFLAGS_WARNING@\n\n# The default switches for optimization or debugging\nCFLAGS_DEBUG\t\t= @CFLAGS_DEBUG@\nCFLAGS_OPTIMIZE\t\t= @CFLAGS_OPTIMIZE@\n\n# To change the compiler switches, for example to change from optimization to\n# debugging symbols, change the following line:\n#CFLAGS\t\t\t= $(CFLAGS_DEBUG)\n#CFLAGS\t\t\t= $(CFLAGS_OPTIMIZE)\n#CFLAGS\t\t\t= $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)\nCFLAGS\t\t\t= @CFLAGS_DEFAULT@ @CFLAGS@\n\n# Flags to pass to the linker\nLDFLAGS_DEBUG\t\t= @LDFLAGS_DEBUG@\nLDFLAGS_OPTIMIZE\t= @LDFLAGS_OPTIMIZE@\nLDFLAGS\t\t\t= @LDFLAGS_DEFAULT@ @LDFLAGS@\n\n# A \"-I\" switch that can be used when compiling to make all of the\n# X11 include files accessible (the configure script will try to\n# set this value, and will cause it to be an empty string if the\n# include files are accessible via /usr/include).\nX11_INCLUDES\t\t= @XINCLUDES@\n\nAQUA_INCLUDES\t\t= -I$(MAC_OSX_DIR) -I$(XLIB_DIR)\n\n# Linker switch(es) to use to link with the X11 library archive (the\n# configure script will try to set this value automatically, but you\n# can override it).\nX11_LIB_SWITCHES\t= $(XFT_LIBS) $(HB_LIBS) @XLIBSW@\n\n# To turn off the security checks that disallow incoming sends when\n# the X server appears to be insecure, reverse the comments on the\n# following lines:\nSECURITY_FLAGS\t\t=\n#SECURITY_FLAGS\t\t= -DTK_NO_SECURITY\n\n# To disable ANSI-C procedure prototypes reverse the comment characters\n# on the following lines:\nPROTO_FLAGS\t\t=\n#PROTO_FLAGS\t\t= -DNO_PROTOTYPE\n\n# To enable memory debugging reverse the comment characters on the following\n# lines or call configure with --enable-symbols=mem\n# Warning:  if you enable memory debugging, you must do it *everywhere*,\n# including all the code that calls Tcl, and you must use Tcl_Alloc and\n# Tcl_Free everywhere instead of malloc and free.\nMEM_DEBUG_FLAGS\t\t=\n#MEM_DEBUG_FLAGS\t= -DTCL_MEM_DEBUG\n\n# If your X server is X11R4 or earlier, then you may wish to reverse\n# the comment characters on the following two lines.  This will enable\n# extra code to speed up XStringToKeysym.  In X11R5 and later releases\n# XStringToKeysym is plenty fast, so you needn't define REDO_KEYSYM_LOOKUP.\nKEYSYM_FLAGS\t\t=\n#KEYSYM_FLAGS\t\t= -DREDO_KEYSYM_LOOKUP\n\n# Tk does not used deprecated Tcl constructs so it should\n# compile fine with -DTCL_NO_DEPRECATED. To remove its own\n# set of deprecated code uncomment the second line.\nNO_DEPRECATED_FLAGS\t=\n#NO_DEPRECATED_FLAGS\t= -DTCL_NO_DEPRECATED -DTK_NO_DEPRECATED\n\n# Some versions of make, like SGI's, use the following variable to\n# determine which shell to use for executing commands:\nSHELL\t\t\t= @SHELL@\n\n# BUILD_TCLSH is the fully qualified path name of the tclsh shell\n# in the Tcl build directory. Test that need to be run in the\n# version of tclsh that we are building against should use this\n# path. Targets that need an installed tclsh should not depend\n# on this variable.\n\nBUILD_TCLSH\t\t= @BUILD_TCLSH@\n\n# TCL_EXE is the name of a tclsh executable that is available *BEFORE*\n# running make for the first time. Certain build targets (make genstubs)\n# need it to be available on the PATH. This executable should *NOT* be\n# required just to do a normal build although it can be required to run\n# make dist. This variable is set to \"\" if no tclsh is available.\nEXE_SUFFIX\t\t= @EXEEXT@\nTCL_EXE\t\t\t= @TCLSH_PROG@\nWISH_EXE\t\t= wish${EXE_SUFFIX}\nTKTEST_EXE\t\t= tktest${EXE_SUFFIX}\n\n# Tk used to let the configure script choose which program to use\n# for installing, but there are just too many different versions of\n# \"install\" around;  better to use the install-sh script that comes\n# with the distribution, which is slower but guaranteed to work.\n\nINSTALL_STRIP_PROGRAM\t= strip\nINSTALL_STRIP_LIBRARY\t= strip -x\n\nINSTALL\t\t\t= $(SHELL) $(UNIX_DIR)/install-sh -c\nINSTALL_PROGRAM\t\t= ${INSTALL} -m 755\nINSTALL_LIBRARY\t\t= ${INSTALL} -m 755\nINSTALL_DATA\t\t= ${INSTALL} -m 644\nINSTALL_DATA_DIR\t= ${INSTALL} -d -m 755\n\n# The symbol below provides support for dynamic loading and shared\n# libraries.  See configure.ac for a description of what it means.\n# The value of the symbol is normally set by the configure script.\n\nSHLIB_CFLAGS\t\t= @SHLIB_CFLAGS@ -DBUILD_tk\n\n# To enable support for stubs in Tcl.\nSTUB_LIB_FILE\t\t= @TK_STUB_LIB_FILE@\n\nTK_STUB_LIB_FILE\t= @TK_STUB_LIB_FILE@\n#TK_STUB_LIB_FILE\t= libtkstub.a\n\n# Generic stub lib name used in rules that apply to tcl and tk\nSTUB_LIB_FILE\t\t= ${TK_STUB_LIB_FILE}\n\nTK_STUB_LIB_FLAG\t= @TK_STUB_LIB_FLAG@\n#TK_STUB_LIB_FLAG\t= -ltkstub\n\nTK_LIB_FILE\t\t= @TK_LIB_FILE@\n#TK_LIB_FILE\t\t= libtk.a\n\n# Generic lib name used in rules that apply to tcl and tk\nLIB_FILE\t\t= ${TK_LIB_FILE}\n\nTK_LIB_FLAG\t\t= @TK_LIB_FLAG@\n#TK_LIB_FLAG\t\t= -ltk\n\nTCL_LIB_SPEC\t\t= @TCL_LIB_SPEC@\nTCL_STUB_LIB_SPEC\t= @TCL_STUB_LIB_SPEC@\nTCL_STUB_LIB_FLAG\t= @TCL_STUB_LIB_FLAG@\nTCL_STUB_LIB_FILE\t= @TCL_STUB_LIB_FILE@\n\nTCL_STUB_FLAGS\t\t= @TCL_STUB_FLAGS@\n\n# Libraries to use when linking.  This definition is determined by the\n# configure script.\nLIBS = @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@ @CUPS_LIBS@ @ATK_LIBS@ @HB_LIBS@\nWISH_LIBS = $(TCL_LIB_SPEC) @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@ @CUPS_LIBS@ @ATK_LIBS@ @HB_LIBS@ @EXTRA_WISH_LIBS@\n\n# The symbols below provide support for dynamic loading and shared\n# libraries.  See configure.ac for a description of what the\n# symbols mean.  The values of the symbols are normally set by the\n# configure script.  You shouldn't normally need to modify any of\n# these definitions by hand.\n\nSTLIB_LD\t\t= @STLIB_LD@\nSHLIB_LD\t\t= @SHLIB_LD@\nSHLIB_LD_LIBS\t\t= @SHLIB_LD_LIBS@\nTK_SHLIB_LD_EXTRAS\t= @TK_SHLIB_LD_EXTRAS@\n\n# Additional search flags needed to find the various shared libraries\n# at run-time.  The first symbol is for use when creating a binary\n# with cc, and the second is for use when running ld directly.\nCC_SEARCH_FLAGS\t= @CC_SEARCH_FLAGS@\nLD_SEARCH_FLAGS\t= @LD_SEARCH_FLAGS@\n\n# support for embedded libraries on Darwin / Mac OS X\nDYLIB_INSTALL_DIR\t= $(libdir)\n\n# support for building the Aqua resource file\nTK_RSRC_FILE\t\t= @TK_RSRC_FILE@\nWISH_RSRC_FILE\t\t= @WISH_RSRC_FILE@\nREZ\t\t\t= @REZ@\nREZ_SWITCHES = @REZ_FLAGS@ -i $(GENERIC_DIR) -i $(TCL_GENERIC_DIR)\n\n# support for Xft:\nXFT_CFLAGS\t\t= @XFT_CFLAGS@\nXFT_LIBS\t\t= @XFT_LIBS@\n\n# support for HarfBuzz (hard dependency when --enable-bidi is used)\nHB_CFLAGS\t\t= @HB_CFLAGS@\nHB_LIBS\t\t\t= @HB_LIBS@\n\n# support for libcups\nCUPS_CFLAGS\t\t= @CUPS_CFLAGS@\nCUPS_LIBS\t\t= @CUPS_LIBS@\n\n#support for atk\nATK_CFLAGS\t\t= @ATK_CFLAGS@\nATK_LIBS\t\t= @ATK_LIBS@\n\n# Bidi support (SheenBidi + HarfBuzz text shaping)\nBIDI_CFLAGS\t\t= @BIDI_CFLAGS@\n\n# Font system (core, xft, or bidi)\nFONTSYSTEM\t\t= @FONTSYSTEM@\n\n#----------------------------------------------------------------\n# The information below is modified by the configure script when\n# Makefile is generated from Makefile.in.  You shouldn't normally\n# modify any of this stuff by hand.\n#----------------------------------------------------------------\n\nAC_FLAGS\t\t= @DEFS@\nAR\t\t\t= @AR@\nRANLIB\t\t\t= @RANLIB@\nSRC_DIR\t\t\t= @srcdir@\nTOP_DIR\t\t\t= $(SRC_DIR)/..\nGENERIC_DIR\t\t= $(TOP_DIR)/generic\nTTK_DIR\t\t\t= $(GENERIC_DIR)/ttk\nUNIX_DIR\t\t= $(TOP_DIR)/unix\nBMAP_DIR\t\t= $(TOP_DIR)/bitmaps\nTOOL_DIR\t\t= $(TCLDIR)/tools\nTEST_DIR\t\t= $(TOP_DIR)/tests\nMAC_OSX_DIR\t\t= $(TOP_DIR)/macosx\nXLIB_DIR\t\t= $(TOP_DIR)/xlib\n\n#----------------------------------------------------------------\n# The information below should be usable as is.  The configure\n# script won't modify it and you shouldn't need to modify it\n# either.\n#----------------------------------------------------------------\n\n# Flags to be passed to installManPage to control how the manpages\n# should be installed (symlinks, compression, package name suffix).\nMAN_FLAGS               = @MAN_FLAGS@\n\nCC\t\t\t= @CC@\n\nCC_SWITCHES_NO_STUBS = -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \\\n\t${@TK_WINDOWINGSYSTEM@_INCLUDES} ${CFLAGS} ${CFLAGS_WARNING} \\\n\t${SHLIB_CFLAGS} -I${TCL_GENERIC_DIR} -I${TCL_PLATFORM_DIR} ${AC_FLAGS} \\\n\t${PROTO_FLAGS} ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} \\\n\t${NO_DEPRECATED_FLAGS} @EXTRA_CC_SWITCHES@ $(XFT_CFLAGS) $(BIDI_CFLAGS) $(HB_CFLAGS)\n\nCC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @TCL_STUB_FLAGS@\n\nAPP_CC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @EXTRA_APP_CC_SWITCHES@\n\nDEPEND_SWITCHES = -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \\\n\t${@TK_WINDOWINGSYSTEM@_INCLUDES} ${CFLAGS} -I${TCL_GENERIC_DIR} \\\n\t-I${TCL_PLATFORM_DIR} ${AC_FLAGS} ${PROTO_FLAGS} ${SECURITY_FLAGS} \\\n\t${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} @EXTRA_CC_SWITCHES@ $(XFT_CFLAGS) $(BIDI_CFLAGS) $(HB_CFLAGS)\n\nWISH_OBJS = tkAppInit.o\n\nTKTEST_OBJS = tkTestInit.o tkTest.o tkSquare.o \\\n\t$(@TK_WINDOWINGSYSTEM@_TKTEST_OBJS)\n\nWIDG_OBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \\\n\ttkMenu.o tkMenubutton.o tkMenuDraw.o tkMessage.o \\\n\ttkPanedWindow.o tkScale.o tkScrollbar.o\n\nCANV_OBJS = tkCanvas.o tkCanvArc.o tkCanvBmap.o tkCanvImg.o \\\n\ttkCanvLine.o tkCanvPoly.o tkCanvPs.o tkCanvText.o \\\n\ttkCanvUtil.o tkCanvWind.o tkRectOval.o tkTrig.o\n\nIMAGE_OBJS = tkImage.o tkImgBmap.o tkImgGIF.o tkImgPNG.o tkImgPPM.o \\\n\ttkImgPhoto.o tkImgPhInstance.o tkImgListFormat.o tkImgSVGnano.o\n\nTEXT_OBJS = tkText.o tkTextBTree.o tkTextDisp.o tkTextImage.o tkTextIndex.o \\\n\ttkTextMark.o tkTextTag.o tkTextWind.o\n\n# either tkUnixFont.o (default) or tkUnixRFont.o (if --enable-xft) or tkUnixBidiFont.o (if --enable-bidi)\nFONT_OBJS = @UNIX_FONT_OBJS@\n\nGENERIC_OBJS = tk3d.o tkAccessibility.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o tkBusy.o \\\n\ttkClipboard.o \\\n\ttkCmds.o tkColor.o tkConfig.o tkConsole.o tkCursor.o tkError.o \\\n\ttkEvent.o tkFocus.o tkFont.o tkGet.o tkGC.o tkGeometry.o tkGrab.o \\\n\ttkGrid.o tkMain.o tkObj.o tkOldConfig.o tkOption.o tkPack.o \\\n\ttkPkgConfig.o tkPlace.o\ttkSelect.o tkStyle.o tkUndo.o tkUtil.o \\\n\ttkVisual.o tkWindow.o\n\nTTK_OBJS = \\\n\tttkBlink.o ttkButton.o ttkCache.o ttkClamTheme.o ttkClassicTheme.o \\\n\tttkDefaultTheme.o ttkElements.o ttkEntry.o ttkFrame.o ttkImage.o \\\n\tttkInit.o ttkLabel.o ttkLayout.o ttkManager.o ttkNotebook.o \\\n\tttkPanedwindow.o ttkProgress.o ttkScale.o ttkScrollbar.o ttkScroll.o \\\n\tttkSeparator.o ttkSquare.o ttkState.o \\\n\tttkTagSet.o ttkTheme.o ttkToggleswitch.o ttkTrace.o ttkTrack.o \\\n\tttkTreeview.o ttkWidget.o ttkStubInit.o\n\nSTUB_OBJS = tkStubInit.o\n\nSTUB_LIB_OBJS = tkStubLib.o ttkStubLib.o\n\n# X11 objects including SheenBidi unity build\nX11_OBJS = tkUnix.o tkUnixAccessibility.o tkUnix3d.o tkUnixButton.o\\\n\ttkUnixColor.o tkUnixConfig.o \\\n\ttkUnixCursor.o tkUnixDraw.o tkUnixEmbed.o tkUnixEvent.o tkIcu.o \\\n\ttkUnixFocus.o  $(FONT_OBJS) tkUnixInit.o tkUnixKey.o tkUnixMenu.o \\\n\ttkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \\\n\ttkUnixSend.o tkUnixSysNotify.o tkUnixSysTray.o tkUnixWm.o tkUnixXId.o \\\n\ttkUnixPrint.o \n\nAQUA_OBJS = tkMacOSXAccessibility.o tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \\\n\ttkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \\\n\ttkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \\\n\ttkMacOSXEvent.o tkMacOSXFileTypes.o tkMacOSXFont.o tkMacOSXHLEvents.o \\\n\ttkMacOSXImage.o tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o \\\n\ttkMacOSXMenu.o tkMacOSXMenubutton.o tkMacOSXMenus.o \\\n\ttkMacOSXMouseEvent.o tkMacOSXNotify.o tkMacOSXPrint.o tkMacOSXRegion.o \\\n\ttkMacOSXScrlbr.o tkMacOSXSend.o tkMacOSXServices.o \\\n\ttkMacOSXSubwindows.o tkMacOSXSysTray.o tkMacOSXWindowEvent.o tkMacOSXWm.o \\\n\ttkMacOSXXStubs.o tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o \\\n\ttkUnixScale.o xcolors.o xdraw.o xgc.o ximage.o xutil.o \\\n\tttkMacOSXTheme.o\n\nAQUA_TKTEST_OBJS = tkMacOSXTest.o\n\nOBJS =  $(GENERIC_OBJS) $(WIDG_OBJS) $(CANV_OBJS) $(IMAGE_OBJS) $(TEXT_OBJS) \\\n\t$(STUB_OBJS) $(TTK_OBJS) \\\n\t$(@TK_WINDOWINGSYSTEM@_OBJS) @PLAT_OBJS@\n\nTK_DECLS = \\\n\t$(GENERIC_DIR)/tk.decls \\\n\t$(GENERIC_DIR)/tkInt.decls\n\nTTK_DECLS = \\\n\t$(TTK_DIR)/ttk.decls\n\nGENERIC_SRCS = \\\n\t$(GENERIC_DIR)/tk3d.c $(GENERIC_DIR)/tkAccessibility.c $(GENERIC_DIR)/tkArgv.c \\\n\t$(GENERIC_DIR)/tkAtom.c $(GENERIC_DIR)/tkBind.c\t\\\n\t$(GENERIC_DIR)/tkBitmap.c $(GENERIC_DIR)/tkBusy.c \\\n\t$(GENERIC_DIR)/tkClipboard.c \\\n\t$(GENERIC_DIR)/tkCmds.c $(GENERIC_DIR)/tkColor.c \\\n\t$(GENERIC_DIR)/tkConfig.c $(GENERIC_DIR)/tkCursor.c \\\n\t$(GENERIC_DIR)/tkError.c $(GENERIC_DIR)/tkEvent.c \\\n\t$(GENERIC_DIR)/tkFocus.c $(GENERIC_DIR)/tkFont.c \\\n\t$(GENERIC_DIR)/tkGet.c $(GENERIC_DIR)/tkGC.c \\\n\t$(GENERIC_DIR)/tkGeometry.c $(GENERIC_DIR)/tkGrab.c \\\n\t$(GENERIC_DIR)/tkGrid.c $(GENERIC_DIR)/tkConsole.c \\\n\t$(GENERIC_DIR)/tkMain.c $(GENERIC_DIR)/tkOption.c \\\n\t$(GENERIC_DIR)/tkPack.c $(GENERIC_DIR)/tkPlace.c \\\n\t$(GENERIC_DIR)/tkPkgConfig.c \\\n\t$(GENERIC_DIR)/tkSelect.c $(GENERIC_DIR)/tkStyle.c \\\n\t$(GENERIC_DIR)/tkUndo.c $(GENERIC_DIR)/tkUtil.c \\\n\t$(GENERIC_DIR)/tkVisual.c $(GENERIC_DIR)/tkWindow.c \\\n\t$(GENERIC_DIR)/tkButton.c $(GENERIC_DIR)/tkObj.c \\\n\t$(GENERIC_DIR)/tkEntry.c $(GENERIC_DIR)/tkFrame.c \\\n\t$(GENERIC_DIR)/tkListbox.c $(GENERIC_DIR)/tkMenu.c \\\n\t$(GENERIC_DIR)/tkMenubutton.c $(GENERIC_DIR)/tkMenuDraw.c \\\n\t$(GENERIC_DIR)/tkMessage.c $(GENERIC_DIR)/tkPanedWindow.c \\\n\t$(GENERIC_DIR)/tkScale.c $(GENERIC_DIR)/tkScrollbar.c \\\n\t$(GENERIC_DIR)/tkCanvas.c $(GENERIC_DIR)/tkCanvArc.c \\\n\t$(GENERIC_DIR)/tkCanvBmap.c $(GENERIC_DIR)/tkCanvImg.c \\\n\t$(GENERIC_DIR)/tkCanvLine.c $(GENERIC_DIR)/tkCanvPoly.c \\\n\t$(GENERIC_DIR)/tkCanvPs.c $(GENERIC_DIR)/tkCanvText.c \\\n\t$(GENERIC_DIR)/tkCanvUtil.c \\\n\t$(GENERIC_DIR)/tkCanvWind.c $(GENERIC_DIR)/tkRectOval.c \\\n\t$(GENERIC_DIR)/tkTrig.c $(GENERIC_DIR)/tkImage.c \\\n\t$(GENERIC_DIR)/tkImgBmap.c $(GENERIC_DIR)/tkImgGIF.c \\\n\t$(GENERIC_DIR)/tkImgPNG.c $(GENERIC_DIR)/tkImgPPM.c \\\n\t$(GENERIC_DIR)/tkImgSVGnano.c $(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhInstance.c \\\n\t$(GENERIC_DIR)/tkImgListFormat.c $(GENERIC_DIR)/tkText.c \\\n\t$(GENERIC_DIR)/tkTextBTree.c $(GENERIC_DIR)/tkTextDisp.c \\\n\t$(GENERIC_DIR)/tkTextImage.c \\\n\t$(GENERIC_DIR)/tkTextIndex.c $(GENERIC_DIR)/tkTextMark.c \\\n\t$(GENERIC_DIR)/tkTextTag.c $(GENERIC_DIR)/tkTextWind.c \\\n\t$(GENERIC_DIR)/tkOldConfig.c \\\n\t$(GENERIC_DIR)/tkSquare.c $(GENERIC_DIR)/tkTest.c \\\n\t$(GENERIC_DIR)/tkStubInit.c\n\nTTK_SRCS = \\\n\t$(TTK_DIR)/ttkBlink.c \\\n\t$(TTK_DIR)/ttkButton.c \\\n\t$(TTK_DIR)/ttkCache.c \\\n\t$(TTK_DIR)/ttkClamTheme.c \\\n\t$(TTK_DIR)/ttkClassicTheme.c \\\n\t$(TTK_DIR)/ttkDefaultTheme.c \\\n\t$(TTK_DIR)/ttkElements.c \\\n\t$(TTK_DIR)/ttkEntry.c \\\n\t$(TTK_DIR)/ttkFrame.c \\\n\t$(TTK_DIR)/ttkImage.c \\\n\t$(TTK_DIR)/ttkInit.c \\\n\t$(TTK_DIR)/ttkLabel.c \\\n\t$(TTK_DIR)/ttkLayout.c \\\n\t$(TTK_DIR)/ttkManager.c \\\n\t$(TTK_DIR)/ttkNotebook.c \\\n\t$(TTK_DIR)/ttkPanedwindow.c \\\n\t$(TTK_DIR)/ttkProgress.c \\\n\t$(TTK_DIR)/ttkScale.c \\\n\t$(TTK_DIR)/ttkScrollbar.c \\\n\t$(TTK_DIR)/ttkScroll.c \\\n\t$(TTK_DIR)/ttkSeparator.c \\\n\t$(TTK_DIR)/ttkSquare.c \\\n\t$(TTK_DIR)/ttkState.c \\\n\t$(TTK_DIR)/ttkTagSet.c \\\n\t$(TTK_DIR)/ttkTheme.c \\\n\t$(TTK_DIR)/ttkToggleswitch.c \\\n\t$(TTK_DIR)/ttkTrace.c \\\n\t$(TTK_DIR)/ttkTrack.c \\\n\t$(TTK_DIR)/ttkTreeview.c \\\n\t$(TTK_DIR)/ttkWidget.c\n\nTTK_STUB_SRCS = \\\n\t$(TTK_DIR)/ttkStubInit.c $(TTK_DIR)/ttkStubLib.c\n\n# X11 sources including SheenBidi unity build\nX11_SRCS = \\\n\t$(UNIX_DIR)/tkAppInit.c $(UNIX_DIR)/tkUnix.c \\\n\t$(UNIX_DIR)/tkUnix3d.c \\\n\t$(UNIX_DIR)/tkUnixAccessibility.c \\\n\t$(UNIX_DIR)/tkUnixButton.c $(UNIX_DIR)/tkUnixColor.c \\\n\t$(UNIX_DIR)/tkUnixConfig.c \\\n\t$(UNIX_DIR)/tkUnixCursor.c \\\n\t$(UNIX_DIR)/tkUnixDraw.c \\\n\t$(UNIX_DIR)/tkUnixEmbed.c $(UNIX_DIR)/tkUnixEvent.c \\\n\t$(UNIX_DIR)/tkUnixFocus.c $(GENERIC_DIR)/tkIcu.c \\\n\t$(UNIX_DIR)/tkUnixInit.c \\\n\t$(UNIX_DIR)/tkUnixKey.c \\\n\t$(UNIX_DIR)/tkUnixMenu.c $(UNIX_DIR)/tkUnixMenubu.c \\\n\t$(UNIX_DIR)/tkUnixScale.c $(UNIX_DIR)/tkUnixScrlbr.c \\\n\t$(UNIX_DIR)/tkUnixSelect.c $(UNIX_DIR)/tkUnixSend.c \\\n\t$(UNIX_DIR)/tkUnixSysNotify.c $(UNIX_DIR)/tkUnixSysTray.c \\\n\t$(UNIX_DIR)/tkUnixWm.c $(UNIX_DIR)/tkUnixXId.c \\\n\t$(UNIX_DIR)/tkUnixPrint.c $(UNIX_DIR)/bidi/SheenBidi.c\n\nAQUA_SRCS = \\\n\t$(MAC_OSX_DIR)/tkMacOSXAccessibility.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXBitmap.c $(MAC_OSX_DIR)/tkMacOSXButton.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXClipboard.c $(MAC_OSX_DIR)/tkMacOSXColor.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXConfig.c $(MAC_OSX_DIR)/tkMacOSXCursor.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXDebug.c $(MAC_OSX_DIR)/tkMacOSXDialog.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXFileTypes.c\\\n\t$(MAC_OSX_DIR)/tkMacOSXHLEvents.c $(MAC_OSX_DIR)/tkMacOSXImage.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXKeyEvent.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXMenu.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXServices.c $(MAC_OSX_DIR)/tkMacOSXSysTray.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \\\n\t$(MAC_OSX_DIR)/tkMacOSXWm.c $(MAC_OSX_DIR)/tkMacOSXXStubs.c \\\n\t$(GENERIC_DIR)/tkFileFilter.c $(GENERIC_DIR)/tkMacWinMenu.c \\\n\t$(GENERIC_DIR)/tkPointer.c $(UNIX_DIR)/tkUnix3d.c \\\n\t$(UNIX_DIR)/tkUnixScale.c $(XLIB_DIR)/xcolors.c $(XLIB_DIR)/xdraw.c \\\n\t$(XLIB_DIR)/xgc.c $(XLIB_DIR)/ximage.c $(XLIB_DIR)/xutil.c \\\n\t$(TTK_DIR)/ttkMacOSXTheme.c\n\nSRCS = $(GENERIC_SRCS) $(@TK_WINDOWINGSYSTEM@_SRCS) @PLAT_SRCS@\n\n###\n# Tip 430 - ZipFS Modifications\n###\n\nTK_ZIP_FILE\t\t= @TK_ZIP_FILE@\nTK_VFS_ROOT\t\t= libtk.vfs\nTK_VFS_PATH\t\t= ${TK_VFS_ROOT}/tk_library\n\nHOST_CC\t\t\t= @CC_FOR_BUILD@\nHOST_EXEEXT\t\t= @EXEEXT_FOR_BUILD@\nHOST_OBJEXT\t\t= @OBJEXT_FOR_BUILD@\nZIPFS_BUILD\t\t= @ZIPFS_BUILD@\nNATIVE_ZIP\t\t= @ZIP_PROG@\nZIP_PROG_OPTIONS\t= @ZIP_PROG_OPTIONS@\nZIP_PROG_VFSSEARCH\t= @ZIP_PROG_VFSSEARCH@\nSHARED_BUILD\t\t= @SHARED_BUILD@\nINSTALL_LIBRARIES\t= @INSTALL_LIBRARIES@\nINSTALL_MSGS\t\t= @INSTALL_MSGS@\n\nZIP_INSTALL_OBJS\t= @ZIP_INSTALL_OBJS@\n\n\nAQUA_RESOURCES = \\\n\t$(MAC_OSX_DIR)/tkAboutDlg.r $(MAC_OSX_DIR)/tkMacOSXCursors.r \\\n\t$(MAC_OSX_DIR)/tkMacOSXXCursors.r\n\nAQUA_WISH_RESOURCES = $(MAC_OSX_DIR)/tkMacOSXAETE.r\n\nAQUA_HDRS = $(MAC_OSX_DIR)/tkMacOSX.h $(GENERIC_DIR)/tkIntXlibDecls.h\n\nAQUA_XLIB_HDRS = $(XLIB_DIR)/X11/*.h $(XLIB_DIR)/xbytes.h\n\nAQUA_PRIVATE_HDRS = $(MAC_OSX_DIR)/tkMacOSXPort.h $(MAC_OSX_DIR)/tkMacOSXInt.h\n\nX11_PRIVATE_HDRS = $(UNIX_DIR)/tkUnixPort.h $(UNIX_DIR)/tkUnixInt.h $(GENERIC_DIR)/tkIntXlibDecls.h \\\n\t$(UNIX_DIR)/tkUnixDefault.h\n\n# Currently private, eventually public\nTTK_HDRS = $(TTK_DIR)/ttkTheme.h $(TTK_DIR)/ttkDecls.h\n\nPUBLIC_HDRS = $(GENERIC_DIR)/tk.h $(GENERIC_DIR)/tkDecls.h \\\n\t$(GENERIC_DIR)/tkPlatDecls.h $(@TK_WINDOWINGSYSTEM@_HDRS)\n\n# The private headers we want installed for install-private-headers\nPRIVATE_HDRS = $(GENERIC_DIR)/tkInt.h $(GENERIC_DIR)/tkIntDecls.h \\\n\t$(GENERIC_DIR)/tkIntPlatDecls.h $(GENERIC_DIR)/tkPort.h \\\n\t$(TTK_HDRS) $(@TK_WINDOWINGSYSTEM@_PRIVATE_HDRS)\n\nDEMOPROGS = accessiblewidget browse hello ixset rmt rolodex square tcolor timer widget\n\nSHELL_ENV = \\\n\t@LD_LIBRARY_PATH_VAR@=\"`pwd`:${TCL_BIN_DIR}:$${@LD_LIBRARY_PATH_VAR@}\"; \\\n\texport @LD_LIBRARY_PATH_VAR@; \\\n\tTCL_LIBRARY=$(TCLDIR)/library; export TCL_LIBRARY; \\\n\tTK_LIBRARY=@TK_SRC_DIR@/library; export TK_LIBRARY;\n\nall: binaries libraries\n\nbinaries: ${LIB_FILE} ${WISH_EXE}\n\nlibraries:\n\ntkzipfile: ${TK_ZIP_FILE}\n\n${TK_ZIP_FILE}: ${ZIP_INSTALL_OBJS}\n\t@rm -rf ${TK_VFS_ROOT}\n\t@mkdir -p ${TK_VFS_PATH}\n\t@echo \"creating ${TK_VFS_PATH} (prepare compression)\"\n\t@if \\\n\t    ln -s $(TOP_DIR)/library/* ${TK_VFS_PATH}/; \\\n\tthen : ; else \\\n\t    cp -a $(TOP_DIR)/library/* ${TK_VFS_PATH}; \\\n\tfi\n\trm -rf ${TK_VFS_PATH}/demos\n\t@find ${TK_VFS_ROOT} -type d -empty -delete\n\t@echo \"creating ${TK_ZIP_FILE} from ${TK_VFS_PATH}\"\n\t-@if test \"${ZIPFS_BUILD}\" = \"2\" ; then \\\n\t    cp ${TCL_BIN_DIR}/tclsh ${TK_VFS_ROOT}/../${TK_ZIP_FILE} || cp ${TCL_BIN_DIR}/../bin/tclsh${TCLVERSION} ${TK_VFS_ROOT}/../${TK_ZIP_FILE}; \\\n\t    (zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}') 2>/dev/null || \\\n\t\t(echo '${NATIVE_ZIP}' | sed \"s?^\\./?$$(pwd)/?\")`; \\\n\t\tcd ${TK_VFS_ROOT} && $$zip -A ../${TK_ZIP_FILE} && $$zip -J ../${TK_ZIP_FILE}) \\\n\tfi\n\t@(zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}' || \\\n\t    echo '${NATIVE_ZIP}' | sed \"s?^\\./?$$(pwd)/?\")  2>/dev/null`; \\\n\t    echo 'cd ${TK_VFS_ROOT} &&' $$zip '${ZIP_PROG_OPTIONS} ../${TK_ZIP_FILE} ${ZIP_PROG_VFSSEARCH}'; \\\n\t    cd ${TK_VFS_ROOT} && \\\n\t    $$zip ${ZIP_PROG_OPTIONS} ../${TK_ZIP_FILE} ${ZIP_PROG_VFSSEARCH} >/dev/null)\n\n# The following target is configured by autoconf to generate either\n# a shared library or non-shared library for Tk.\n${LIB_FILE}: ${STUB_LIB_FILE} @LIB_RSRC_FILE@ ${OBJS} ${TK_ZIP_FILE}\n\trm -f $@\n\t@MAKE_LIB@\n\t@if test \"${ZIPFS_BUILD}\" = \"1\" ; then \\\n\t    if test \"x$(MACHER)\" = \"x\" ; then \\\n\t\tcat ${TK_ZIP_FILE} >> ${LIB_FILE}; \\\n\t    else $(MACHER) append ${LIB_FILE} ${TK_ZIP_FILE} /tmp/macher_output; \\\n\t\t mv /tmp/macher_output ${LIB_FILE}; chmod u+x ${LIB_FILE}; \\\n\t    fi; \\\n\tfi\n\n${STUB_LIB_FILE}: ${STUB_LIB_OBJS}\n\t@if test \"x${LIB_FILE}\" = \"xcygtcl9tk${MAJOR_VERSION}.${MINOR_VERSION}.dll\"; then \\\n\t    (cd ${TOP_DIR}/win; ${MAKE} tcl9tk${MAJOR_VERSION}${MINOR_VERSION}.dll); \\\n\t    cp \"${TOP_DIR}/win/tcl9tk${MAJOR_VERSION}${MINOR_VERSION}.dll\" .; \\\n\tfi\n\trm -f $@\n\t@MAKE_STUB_LIB@\n\n# Build Aqua resource files\n${TK_RSRC_FILE}: $(AQUA_RESOURCES)\n\trm -f $@\n\tif test \"$(REZ)\" != \"\"; then \\\n\t    $(REZ) -o $@ $(REZ_SWITCHES) $(AQUA_RESOURCES); fi\n\n${WISH_RSRC_FILE}: $(AQUA_WISH_RESOURCES)\n\trm -f $@\n\tif test \"$(REZ)\" != \"\"; then \\\n\t    $(REZ) -o $@ $(REZ_SWITCHES) $(AQUA_WISH_RESOURCES); fi\n\n# Make target which outputs the list of the .o contained in the Tk lib\n# usefull to build a single big shared library containing Tcl/Tk and other\n# extensions.  used for the Tcl Plugin.  -- dl\ntkLibObjs:\n\t@echo ${OBJS}\n# This targets actually build the objects needed for the lib in the above\n# case\nobjs: ${OBJS}\n\n\n${WISH_EXE}: $(TK_STUB_LIB_FILE) $(WISH_OBJS) $(TK_LIB_FILE) @APP_RSRC_FILE@\n\t${CC} ${CFLAGS} $(WISH_OBJS) @TK_BUILD_LIB_SPEC@ ${LDFLAGS} \\\n\t\t$(WISH_LIBS) $(CC_SEARCH_FLAGS) -o ${WISH_EXE}\n\t@if test \"${ZIPFS_BUILD}\" = \"2\" ; then \\\n\t    if test \"x$(MACHER)\" = \"x\" ; then \\\n\t\tcat ${TK_ZIP_FILE} >> ${WISH_EXE}; \\\n\t    else $(MACHER) append ${WISH_EXE} ${TK_ZIP_FILE} /tmp/macher_output; \\\n\t\t mv /tmp/macher_output ${LIB_FILE}; chmod u+x ${LIB_FILE}; \\\n\t    fi; \\\n\tfi\n\n# Resetting the LIB_RUNTIME_DIR below is required so that\n# the generated tktest executable gets the build directory\n# burned into its ld search path. This keeps tktest from\n# picking up an already installed version of the Tcl or\n# Tk shared libraries.\n\n$(TKTEST_EXE): $(TKTEST_OBJS) $(TK_LIB_FILE)\n\t$(MAKE) tktest-real LIB_RUNTIME_DIR=\"`pwd`:$(TCL_BIN_DIR)\"\n\ntktest-real: ${TK_STUB_LIB_FILE}\n\t${CC} ${CFLAGS} $(TKTEST_OBJS) @TK_BUILD_LIB_SPEC@ ${LDFLAGS} $(WISH_LIBS) \\\n\t\t${TK_STUB_LIB_FILE} ${TCL_STUB_LIB_SPEC} $(CC_SEARCH_FLAGS) -o $(TKTEST_EXE)\n\n# # FIXME: This xttest rule seems to be broken in a number of ways.  It should\n# # use CC_SEARCH_FLAGS, it does not include the shared lib location logic from\n# # tktest, and it is not clear where this test.o object file comes from.\n#\n# xttest: test.o tkTest.o tkSquare.o $(TK_LIB_FILE) ${TK_STUB_LIB_FILE}\n#\t${CC} ${CFLAGS} test.o tkTest.o tkSquare.o \\\n#\t\t@TK_BUILD_LIB_SPEC@ ${LDFLAGS} ${TK_STUB_LIB_FILE}  ${TCL_STUB_LIB_SPEC} \\\n#\t\t$(WISH_LIBS) $(LD_SEARCH_FLAGS) -lXt -o xttest\n\n# Note, in the target below TCL_LIBRARY needs to be set or else\n# \"make test\" won't work in the case where the compilation directory\n# isn't the same as the source directory.\n# Specifying TESTFLAGS on the command line is the standard way to pass\n# args to tcltest, ie:\n#\t% make test TESTFLAGS=\"-verbose bps -file fileName.test\"\n\ntest: test-classic test-ttk\n\ntest-classic: $(TKTEST_EXE)\n\t$(SHELL_ENV) ./$(TKTEST_EXE) $(TEST_DIR)/all.tcl $(TESTFLAGS)\n\ntest-ttk: $(TKTEST_EXE)\n\t$(SHELL_ENV) ./$(TKTEST_EXE) $(TEST_DIR)/ttk/all.tcl \\\n\t$(TESTFLAGS)\n\n# Tests with different languages\ntestlang: $(TKTEST_EXE)\n\t$(SHELL_ENV) \\\n\tfor lang in $(LOCALES) ;  \\\n\tdo \\\n\tLANG=$(lang); export LANG; \\\n\t./$(TKTEST_EXE) $(TEST_DIR)/all.tcl \\\n\t$(TESTFLAGS); \\\n\tdone\n\n# Useful target to launch a built tktest with the proper path,...\nruntest: $(TKTEST_EXE)\n\t$(SHELL_ENV) ./$(TKTEST_EXE)\n\n# This target can be used to run wish from the build directory\n# via `make shell` or `make shell SCRIPT=/tmp/foo.tcl`\nshell: ${WISH_EXE}\n\t$(SHELL_ENV) ./${WISH_EXE} $(SCRIPT)\n\ndemo:\n\t$(SHELL_ENV) ./${WISH_EXE} $(TOP_DIR)/library/demos/widget\n\n# This target can be used to run wish inside either gdb or insight\ngdb: ${WISH_EXE}\n\t@echo \"set env @LD_LIBRARY_PATH_VAR@=\\\"`pwd`:${TCL_BIN_DIR}:$${@LD_LIBRARY_PATH_VAR@}\\\"\" > gdb.run\n\t@echo \"set env TCL_LIBRARY=$(TCLDIR)/library\" >> gdb.run\n\t@echo \"set env TK_LIBRARY=@TK_SRC_DIR@/library\" >> gdb.run\n\tgdb ./${WISH_EXE} --command=gdb.run\n\trm gdb.run\n\nVALGRINDARGS=--tool=memcheck --num-callers=8 --leak-resolution=high --leak-check=yes --show-reachable=yes -v\n\nvalgrind: $(TKTEST_EXE)\n\t$(SHELL_ENV) valgrind $(VALGRINDARGS) ./$(TKTEST_EXE) $(TEST_DIR)/all.tcl -singleproc 1 $(TESTFLAGS)\n\nvalgrindshell: $(TKTEST_EXE)\n\t$(SHELL_ENV) valgrind $(VALGRINDARGS) ./$(TKTEST_EXE) $(SCRIPT)\n\nINSTALL_BASE_TARGETS = install-binaries ${INSTALL_LIBRARIES}\nINSTALL_DOC_TARGETS = install-doc\nINSTALL_DEV_TARGETS = install-headers\nINSTALL_DEMO_TARGETS = install-demos\nINSTALL_EXTRA_TARGETS = @EXTRA_INSTALL@\nINSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DEV_TARGETS) \\\n\t\t$(INSTALL_DEMO_TARGETS) $(INSTALL_DOC_TARGETS) $(INSTALL_EXTRA_TARGETS)\n\ninstall: $(INSTALL_TARGETS)\n\ninstall-strip:\n\t$(MAKE) $(INSTALL_TARGETS) \\\n\t\tINSTALL_PROGRAM=\"STRIPPROG='${INSTALL_STRIP_PROGRAM}' $(INSTALL_PROGRAM) -s\" \\\n\t\tINSTALL_LIBRARY=\"STRIPPROG='${INSTALL_STRIP_LIBRARY}' $(INSTALL_LIBRARY) -s\"\n\ninstall-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE) ${WISH_EXE}\n\t@for i in \"$(LIB_INSTALL_DIR)\" \"$(BIN_INSTALL_DIR)\" \\\n\t    \"$(PKG_INSTALL_DIR)\" \"$(CONFIG_INSTALL_DIR)\" ; \\\n\t    do \\\n\t    if [ ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@if test \"x$(TK_SHARED_BUILD)\" = \"x1\"; then \\\n\t    echo \"Creating package index $(PKG_INDEX)\"; \\\n\t    rm -f \"$(PKG_INDEX)\"; \\\n\t    (\\\n\t    echo \"if {![package vsatisfies [package provide Tcl] 9.0]} return\";\\\n\t    relative=`echo | awk '{ORS=\" \"; split(\"$(TK_PKG_DIR)\",a,\"/\"); for (f in a) {print \"..\"}}'`;\\\n\t    if test \"x$(DLL_INSTALL_DIR)\" != \"x$(BIN_INSTALL_DIR)\"; then \\\n\t    echo \"package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \\$$dir $${relative}$(TK_LIB_FILE)]]]\";\\\n\t    else \\\n\t    echo \"if {(\\$$::tcl_platform(platform) eq \\\"unix\\\") && ([info exists ::env(DISPLAY)]\";\\\n\t    echo \"\t|| ([info exists ::argv] && (\\\"-display\\\" in \\$$::argv)))} {\";\\\n\t    echo \"    package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \\$$dir $${relative}.. bin $(TK_LIB_FILE)]]]\";\\\n\t    echo \"} else {\";\\\n\t    echo \"    package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \\$$dir $${relative}.. bin tcl9tk${MAJOR_VERSION}${MINOR_VERSION}.dll]]]\";\\\n\t    echo \"}\";\\\n\t    fi; \\\n\t    echo \"package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list package require -exact tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL)]\"\\\n\t    ) > \"$(PKG_INDEX)\"; \\\n\t    fi\n\t@echo \"Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/\"\n\t@@INSTALL_LIB@\n\t@if test -f \"tk${MAJOR_VERSION}${MINOR_VERSION}.dll\"; then \\\n\t    $(INSTALL_LIBRARY) \"tk${MAJOR_VERSION}${MINOR_VERSION}.dll\" \"$(DLL_INSTALL_DIR)\";\\\n\tfi\n\t@echo \"Installing ${WISH_EXE} as $(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}\"\n\t@$(INSTALL_PROGRAM) ${WISH_EXE} \"$(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}\"\n\t@echo \"Installing tkConfig.sh to $(CONFIG_INSTALL_DIR)/\"\n\t@$(INSTALL_DATA) tkConfig.sh \"$(CONFIG_INSTALL_DIR)/tkConfig.sh\"\n\t@if test \"$(STUB_LIB_FILE)\" != \"\" ; then \\\n\t    echo \"Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/\"; \\\n\t    @INSTALL_STUB_LIB@ ; \\\n\tfi\n\t@EXTRA_INSTALL_BINARIES@\n\t@echo \"Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/\"\n\t@$(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/pkgconfig\"\n\t@$(INSTALL_DATA) tk.pc \"$(LIB_INSTALL_DIR)/pkgconfig/tk.pc\"\n\ninstall-libraries: libraries\n\t@for i in \"$(SCRIPT_INSTALL_DIR)\" \"$(SCRIPT_INSTALL_DIR)/images\" \\\n\t\t\"$(SCRIPT_INSTALL_DIR)/msgs\" \"$(SCRIPT_INSTALL_DIR)/ttk\"; \\\n\t    do \\\n\t    if [ -n \"$$i\" -a ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing Tk library files to $(SCRIPT_INSTALL_DIR)/\";\n\t@for i in $(TOP_DIR)/library/*.tcl $(TOP_DIR)/library/tclIndex \\\n\t\t$(UNIX_DIR)/tkAppInit.c; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i \"$(SCRIPT_INSTALL_DIR)\"; \\\n\t    done;\n\t@echo \"Installing Ttk library files to $(SCRIPT_INSTALL_DIR)/ttk/\";\n\t@for i in $(TOP_DIR)/library/ttk/*.tcl; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i \"$(SCRIPT_INSTALL_DIR)/ttk\"; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing library image files to $(SCRIPT_INSTALL_DIR)/images/\";\n\t@for i in $(TOP_DIR)/library/images/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i \"$(SCRIPT_INSTALL_DIR)/images\"; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing message catalog files to $(SCRIPT_INSTALL_DIR)/msgs/\";\n\t@for i in $(TOP_DIR)/library/msgs/*.msg; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i \"$(SCRIPT_INSTALL_DIR)/msgs\"; \\\n\t    fi; \\\n\t    done;\n\ninstall-demos:\n\t@for i in \"$(DEMO_INSTALL_DIR)\" \"$(DEMO_INSTALL_DIR)/images\" ; \\\n\t    do \\\n\t    if [ ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing demo files to $(DEMO_INSTALL_DIR)/\";\n\t@for i in $(TOP_DIR)/library/demos/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\tsed -e '3 s|exec wish|exec wish$(VERSION)|' \\\n\t\t\t$$i > \"$(DEMO_INSTALL_DIR)\"/`basename $$i`; \\\n\t    fi; \\\n\t    done;\n\t@for i in $(DEMOPROGS); \\\n\t    do \\\n\t    if test $$i = \"square\"; then \\\n\t    rm -f  \"$(DEMO_INSTALL_DIR)/$$i\"; \\\n\t    else \\\n\t    chmod 755 \"$(DEMO_INSTALL_DIR)/$$i\"; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing demo image files to $(DEMO_INSTALL_DIR)/images/\";\n\t@for i in $(TOP_DIR)/library/demos/images/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i \"$(DEMO_INSTALL_DIR)/images\"; \\\n\t\tfi; \\\n\t    done;\n\ninstall-doc:\n\t@for i in \"$(MAN_INSTALL_DIR)\" \"$(MAN1_INSTALL_DIR)\" \"$(MAN3_INSTALL_DIR)\" \"$(MANN_INSTALL_DIR)\" ; \\\n\t    do \\\n\t    if [ ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing and cross-linking top-level (.1) docs to $(MAN1_INSTALL_DIR)/\";\n\t@for i in $(TOP_DIR)/doc/*.1; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MAN1_INSTALL_DIR)\"; \\\n\tdone\n\t@echo \"Installing and cross-linking C API (.3) docs to $(MAN3_INSTALL_DIR)/\";\n\t@for i in $(TOP_DIR)/doc/*.3; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MAN3_INSTALL_DIR)\"; \\\n\tdone\n\t@echo \"Installing and cross-linking command (.n) docs to $(MANN_INSTALL_DIR)/\";\n\t@for i in $(TOP_DIR)/doc/*.n; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MANN_INSTALL_DIR)\"; \\\n\tdone\n\ninstall-headers:\n\t@if test \"$(@TK_WINDOWINGSYSTEM@_XLIB_HDRS)\" != \"\"; then \\\n\t    XLIB_INCLUDE_INSTALL_DIR=\"$(INCLUDE_INSTALL_DIR)\"/X11; fi; \\\n\tfor i in \"$(INCLUDE_INSTALL_DIR)\" \"$${XLIB_INCLUDE_INSTALL_DIR}\"; \\\n\t    do \\\n\t    if [ -n \"$$i\" -a ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing header files to $(INCLUDE_INSTALL_DIR)/\";\n\t@for i in $(PUBLIC_HDRS); \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i \"$(INCLUDE_INSTALL_DIR)\"; \\\n\t    done;\n\t@list='$(@TK_WINDOWINGSYSTEM@_XLIB_HDRS)'; for i in $$list ; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i \"$(INCLUDE_INSTALL_DIR)/X11\"; \\\n\t    done;\n\n# Optional target to install private headers\ninstall-private-headers:\n\t@for i in \"$(PRIVATE_INCLUDE_INSTALL_DIR)\"; \\\n\t    do \\\n\t    if [ ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(INSTALL_DATA_DIR) \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/\";\n\t@for i in $(PRIVATE_HDRS); \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i \"$(PRIVATE_INCLUDE_INSTALL_DIR)\"; \\\n\t    done;\n\t@if test -f tkConfig.h; then\\\n\t    $(INSTALL_DATA) tkConfig.h \"$(PRIVATE_INCLUDE_INSTALL_DIR)\"; \\\n\t    fi;\n\nMakefile: $(UNIX_DIR)/Makefile.in\n\t$(SHELL) config.status\n\nclean:\n\trm -rf *.vfs\n\trm -f *.a *.o libtk* libtcl9tk* cygtcl9tk* core errs *~ \\#* TAGS *.E a.out \\\n\t\terrors ${WISH_EXE} $(TKTEST_EXE) lib.exp Tk *.rsrc \\\n\t\t *.zip\n\ndistclean: clean\n\trm -rf Makefile config.status config.cache config.log tkConfig.sh \\\n\t\ttkConfig.h *.plist Tk.framework tk.pc tkUuid.h\n\ndepend:\n\tmakedepend -- $(DEPEND_SWITCHES) -- $(SRCS)\n\n# Test binaries.  The rule for tkTestInit.o is complicated because\n# it is is compiled from tkAppInit.c.  Can't use the \"-o\" option\n# because this doesn't work on some strange compilers (e.g. UnixWare).\n# To enable concurrent parallel make of wish and tktest, this target has to\n# depend on wish, this ensures that linking of wish with tkTestInit.o does not\n# execute concurrently with the renaming and recompiling of that same object\n# file in the target below.\n\ntkTestInit.o: $(UNIX_DIR)/tkAppInit.c ${WISH_EXE}\n\t@if test -f tkAppInit.o ; then \\\n\t    rm -f tkAppInit.sav; \\\n\t    mv tkAppInit.o tkAppInit.sav; \\\n\tfi;\n\t$(CC) -c $(APP_CC_SWITCHES) -DTK_TEST $(UNIX_DIR)/tkAppInit.c\n\trm -f tkTestInit.o\n\tmv tkAppInit.o tkTestInit.o\n\t@if test -f tkAppInit.sav ; then \\\n\t    mv tkAppInit.sav tkAppInit.o; \\\n\tfi;\n\ntkAppInit.o: $(UNIX_DIR)/tkAppInit.c\n\t$(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tkAppInit.c\n\n# Stub library objects - fixed rules\ntkStubLib.o: $(GENERIC_DIR)/tkStubLib.c\n\t$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ $(GENERIC_DIR)/tkStubLib.c\n\nttkStubLib.o: $(TTK_DIR)/ttkStubLib.c\n\t$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ $(TTK_DIR)/ttkStubLib.c\n\ntkUnixBidiFont.o: $(UNIX_DIR)/tkUnixBidiFont.c\n\t$(CC) -c $(CC_SWITCHES) $(XFT_CFLAGS) $(BIDI_CFLAGS) $(HB_CFLAGS) $(UNIX_DIR)/tkUnixBidiFont.c\n\nSheenBidi.o: $(UNIX_DIR)/bidi/SheenBidi.c\n\t$(CC) -c $(CC_SWITCHES) $(BIDI_CFLAGS) $(UNIX_DIR)/bidi/SheenBidi.c\n\ntk3d.o: $(GENERIC_DIR)/tk3d.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tk3d.c\n\ntkAccessibility.o: $(GENERIC_DIR)/tkAccessibility.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkAccessibility.c\n\ntkArgv.o: $(GENERIC_DIR)/tkArgv.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkArgv.c\n\ntkAtom.o: $(GENERIC_DIR)/tkAtom.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkAtom.c\n\ntkBind.o: $(GENERIC_DIR)/tkBind.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBind.c\n\ntkBitmap.o: $(GENERIC_DIR)/tkBitmap.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBitmap.c\n\ntkBusy.o: $(GENERIC_DIR)/tkBusy.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBusy.c\n\ntkClipboard.o: $(GENERIC_DIR)/tkClipboard.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkClipboard.c\n\ntkCmds.o: $(GENERIC_DIR)/tkCmds.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCmds.c\n\ntkColor.o: $(GENERIC_DIR)/tkColor.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkColor.c\n\ntkConfig.o: $(GENERIC_DIR)/tkConfig.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkConfig.c\n\ntkConsole.o: $(GENERIC_DIR)/tkConsole.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkConsole.c\n\ntkCursor.o: $(GENERIC_DIR)/tkCursor.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCursor.c\n\ntkError.o: $(GENERIC_DIR)/tkError.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkError.c\n\ntkEvent.o: $(GENERIC_DIR)/tkEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkEvent.c\n\ntkFocus.o: $(GENERIC_DIR)/tkFocus.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFocus.c\n\ntkFont.o: $(GENERIC_DIR)/tkFont.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFont.c\n\ntkGet.o: $(GENERIC_DIR)/tkGet.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGet.c\n\ntkGC.o: $(GENERIC_DIR)/tkGC.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGC.c\n\ntkGeometry.o: $(GENERIC_DIR)/tkGeometry.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGeometry.c\n\ntkGrab.o: $(GENERIC_DIR)/tkGrab.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGrab.c\n\ntkGrid.o: $(GENERIC_DIR)/tkGrid.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGrid.c\n\ntkMain.o: $(GENERIC_DIR)/tkMain.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMain.c\n\ntkObj.o: $(GENERIC_DIR)/tkObj.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkObj.c\n\ntkOldConfig.o: $(GENERIC_DIR)/tkOldConfig.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOldConfig.c\n\ntkOption.o: $(GENERIC_DIR)/tkOption.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOption.c\n\ntkPack.o: $(GENERIC_DIR)/tkPack.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPack.c\n\n# TIP #59, embedding of configuration information into the binary library.\n#\n# Part of Tk's configuration information are the paths where it was installed\n# and where it will look for its libraries (which can be different). We derive\n# this information from the variables which can be overridden by the user. As\n# every path can be configured separately we do not remember one general\n# prefix/exec_prefix but all the different paths individually.\n\ntkPkgConfig.o: $(GENERIC_DIR)/tkPkgConfig.c\n\t$(CC) -c $(CC_SWITCHES)\t\t\t\t\t\\\n\t\t-DCFG_INSTALL_LIBDIR=\"\\\"$(LIB_INSTALL_DIR)\\\"\" \\\n\t\t-DCFG_INSTALL_BINDIR=\"\\\"$(BIN_INSTALL_DIR)\\\"\" \\\n\t\t-DCFG_INSTALL_SCRDIR=\"\\\"$(SCRIPT_INSTALL_DIR)\\\"\" \\\n\t\t-DCFG_INSTALL_INCDIR=\"\\\"$(INCLUDE_INSTALL_DIR)\\\"\" \\\n\t\t-DCFG_INSTALL_DOCDIR=\"\\\"$(MAN_INSTALL_DIR)\\\"\" \\\n\t\t-DCFG_INSTALL_DEMODIR=\"\\\"$(DEMO_INSTALL_DIR)\\\"\" \\\n\t\t\\\n\t\t-DCFG_RUNTIME_LIBDIR=\"\\\"$(libdir)\\\"\" \\\n\t\t-DCFG_RUNTIME_BINDIR=\"\\\"$(bindir)\\\"\" \\\n\t\t-DCFG_RUNTIME_SCRDIR=\"\\\"$(TK_LIBRARY)\\\"\" \\\n\t\t-DCFG_RUNTIME_INCDIR=\"\\\"$(includedir)\\\"\" \\\n\t\t-DCFG_RUNTIME_DOCDIR=\"\\\"$(mandir)\\\"\" \\\n\t\t-DCFG_RUNTIME_DLLFILE=\"\\\"$(TK_LIB_FILE)\\\"\" \\\n\t\t-DCFG_RUNTIME_DEMODIR=\"\\\"$(DEMO_INSTALL_DIR)\\\"\" \\\n\t\t\\\n\t\t$(GENERIC_DIR)/tkPkgConfig.c\n\ntkPlace.o: $(GENERIC_DIR)/tkPlace.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPlace.c\n\ntkSelect.o: $(GENERIC_DIR)/tkSelect.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkSelect.c\n\ntkStyle.o: $(GENERIC_DIR)/tkStyle.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStyle.c\n\ntkUtil.o: $(GENERIC_DIR)/tkUtil.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkUtil.c\n\ntkVisual.o: $(GENERIC_DIR)/tkVisual.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkVisual.c\n\ntkWindow.o: $(GENERIC_DIR)/tkWindow.c tkUuid.h\n\t$(CC) -c $(CC_SWITCHES) -I. $(GENERIC_DIR)/tkWindow.c\n\ntkButton.o: $(GENERIC_DIR)/tkButton.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkButton.c\n\ntkEntry.o: $(GENERIC_DIR)/tkEntry.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkEntry.c\n\ntkFrame.o: $(GENERIC_DIR)/tkFrame.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFrame.c\n\ntkListbox.o: $(GENERIC_DIR)/tkListbox.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkListbox.c\n\ntkMenu.o: $(GENERIC_DIR)/tkMenu.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenu.c\n\ntkMenubutton.o: $(GENERIC_DIR)/tkMenubutton.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenubutton.c\n\ntkMenuDraw.o: $(GENERIC_DIR)/tkMenuDraw.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenuDraw.c\n\ntkMessage.o: $(GENERIC_DIR)/tkMessage.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMessage.c\n\ntkPanedWindow.o: $(GENERIC_DIR)/tkPanedWindow.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPanedWindow.c\n\ntkScale.o: $(GENERIC_DIR)/tkScale.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkScale.c\n\ntkScrollbar.o: $(GENERIC_DIR)/tkScrollbar.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkScrollbar.c\n\ntkSquare.o: $(GENERIC_DIR)/tkSquare.c\n\t$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tkSquare.c\n\ntkCanvas.o: $(GENERIC_DIR)/tkCanvas.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvas.c\n\ntkCanvArc.o: $(GENERIC_DIR)/tkCanvArc.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvArc.c\n\ntkCanvBmap.o: $(GENERIC_DIR)/tkCanvBmap.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvBmap.c\n\ntkCanvImg.o: $(GENERIC_DIR)/tkCanvImg.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvImg.c\n\ntkCanvLine.o: $(GENERIC_DIR)/tkCanvLine.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvLine.c\n\ntkCanvPoly.o: $(GENERIC_DIR)/tkCanvPoly.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvPoly.c\n\ntkCanvPs.o: $(GENERIC_DIR)/tkCanvPs.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvPs.c\n\ntkCanvText.o: $(GENERIC_DIR)/tkCanvText.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvText.c\n\ntkCanvUtil.o: $(GENERIC_DIR)/tkCanvUtil.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvUtil.c\n\ntkCanvWind.o: $(GENERIC_DIR)/tkCanvWind.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvWind.c\n\ntkRectOval.o: $(GENERIC_DIR)/tkRectOval.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkRectOval.c\n\ntkTrig.o: $(GENERIC_DIR)/tkTrig.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTrig.c\n\ntkIcu.o: $(GENERIC_DIR)/tkIcu.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkIcu.c\n\ntkImage.o: $(GENERIC_DIR)/tkImage.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImage.c\n\ntkImgBmap.o: $(GENERIC_DIR)/tkImgBmap.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgBmap.c\n\ntkImgListFormat.o: $(GENERIC_DIR)/tkImgListFormat.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgListFormat.c\n\ntkImgGIF.o: $(GENERIC_DIR)/tkImgGIF.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgGIF.c\n\ntkImgPNG.o: $(GENERIC_DIR)/tkImgPNG.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPNG.c\n\ntkImgPPM.o: $(GENERIC_DIR)/tkImgPPM.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPPM.c\n\ntkImgSVGnano.o: $(GENERIC_DIR)/tkImgSVGnano.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgSVGnano.c\n\ntkImgPhoto.o: $(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhoto.h\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhoto.c\n\ntkImgPhInstance.o: $(GENERIC_DIR)/tkImgPhInstance.c $(GENERIC_DIR)/tkImgPhoto.h\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhInstance.c\n\ntkTest.o: $(GENERIC_DIR)/tkTest.c tkUuid.h\n\t$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tkTest.c\n\ntkText.o: $(GENERIC_DIR)/tkText.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkText.c\n\ntkTextBTree.o: $(GENERIC_DIR)/tkTextBTree.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextBTree.c\n\ntkTextDisp.o: $(GENERIC_DIR)/tkTextDisp.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextDisp.c\n\ntkTextImage.o: $(GENERIC_DIR)/tkTextImage.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextImage.c\n\ntkTextIndex.o: $(GENERIC_DIR)/tkTextIndex.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextIndex.c\n\ntkTextMark.o: $(GENERIC_DIR)/tkTextMark.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextMark.c\n\ntkTextTag.o: $(GENERIC_DIR)/tkTextTag.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextTag.c\n\ntkTextWind.o: $(GENERIC_DIR)/tkTextWind.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextWind.c\n\ntkStubInit.o: $(GENERIC_DIR)/tkStubInit.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStubInit.c\n\ntkUndo.o: $(GENERIC_DIR)/tkUndo.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkUndo.c\n\ntkUnix.o: $(UNIX_DIR)/tkUnix.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnix.c\n\ntkUnix3d.o: $(UNIX_DIR)/tkUnix3d.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnix3d.c\n\ntkUnixAccessibility.o: $(UNIX_DIR)/tkUnixAccessibility.c\n\t$(CC) -c $(CC_SWITCHES) $(ATK_CFLAGS) $(UNIX_DIR)/tkUnixAccessibility.c\n\ntkUnixButton.o: $(UNIX_DIR)/tkUnixButton.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixButton.c\n\ntkUnixColor.o: $(UNIX_DIR)/tkUnixColor.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixColor.c\n\ntkUnixConfig.o: $(UNIX_DIR)/tkUnixConfig.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixConfig.c\n\ntkUnixCursor.o: $(UNIX_DIR)/tkUnixCursor.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixCursor.c\n\ntkUnixDraw.o: $(UNIX_DIR)/tkUnixDraw.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixDraw.c\n\ntkUnixEmbed.o: $(UNIX_DIR)/tkUnixEmbed.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixEmbed.c\n\ntkUnixEvent.o: $(UNIX_DIR)/tkUnixEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixEvent.c\n\ntkUnixFocus.o: $(UNIX_DIR)/tkUnixFocus.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixFocus.c\n\ntkUnixFont.o: $(UNIX_DIR)/tkUnixFont.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixFont.c\n\n# NB: tkUnixRFont.o uses nondefault CFLAGS\ntkUnixRFont.o: $(UNIX_DIR)/tkUnixRFont.c\n\t$(CC) -c $(CC_SWITCHES) $(XFT_CFLAGS) $(UNIX_DIR)/tkUnixRFont.c\n\ntkUnixInit.o: $(UNIX_DIR)/tkUnixInit.c tkConfig.sh\n\t$(CC) -c $(CC_SWITCHES) \\\n\t    $(UNIX_DIR)/tkUnixInit.c\n\ntkUnixKey.o: $(UNIX_DIR)/tkUnixKey.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixKey.c\n\ntkUnixMenu.o: $(UNIX_DIR)/tkUnixMenu.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixMenu.c\n\ntkUnixMenubu.o: $(UNIX_DIR)/tkUnixMenubu.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixMenubu.c\n\ntkUnixPrint.o: $(UNIX_DIR)/tkUnixPrint.c\n\t$(CC) -c $(CC_SWITCHES) $(CUPS_CFLAGS) $(UNIX_DIR)/tkUnixPrint.c\n\ntkUnixScale.o: $(UNIX_DIR)/tkUnixScale.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixScale.c\n\ntkUnixScrlbr.o: $(UNIX_DIR)/tkUnixScrlbr.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixScrlbr.c\n\ntkUnixSelect.o: $(UNIX_DIR)/tkUnixSelect.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSelect.c\n\ntkUnixSend.o: $(UNIX_DIR)/tkUnixSend.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSend.c\n\ntkUnixSysNotify.o: $(UNIX_DIR)/tkUnixSysNotify.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSysNotify.c\n\ntkUnixSysTray.o: $(UNIX_DIR)/tkUnixSysTray.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSysTray.c\n\ntkUnixWm.o: $(UNIX_DIR)/tkUnixWm.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixWm.c\n\ntkUnixXId.o: $(UNIX_DIR)/tkUnixXId.c\n\t$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixXId.c\n\ntkMacOSXAccessibility.o: $(MAC_OSX_DIR)/tkMacOSXAccessibility.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXAccessibility.c\n\ntkMacOSXBitmap.o: $(MAC_OSX_DIR)/tkMacOSXBitmap.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXBitmap.c\n\ntkMacOSXButton.o: $(MAC_OSX_DIR)/tkMacOSXButton.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXButton.c\n\ntkMacOSXClipboard.o: $(MAC_OSX_DIR)/tkMacOSXClipboard.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXClipboard.c\n\ntkMacOSXColor.o: $(MAC_OSX_DIR)/tkMacOSXColor.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXColor.c\n\ntkMacOSXConfig.o: $(MAC_OSX_DIR)/tkMacOSXConfig.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXConfig.c\n\ntkMacOSXCursor.o: $(MAC_OSX_DIR)/tkMacOSXCursor.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXCursor.c\n\ntkMacOSXDebug.o: $(MAC_OSX_DIR)/tkMacOSXDebug.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDebug.c\n\ntkMacOSXDialog.o: $(MAC_OSX_DIR)/tkMacOSXDialog.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDialog.c\n\ntkMacOSXDraw.o: $(MAC_OSX_DIR)/tkMacOSXDraw.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDraw.c\n\ntkMacOSXEmbed.o: $(MAC_OSX_DIR)/tkMacOSXEmbed.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEmbed.c\n\ntkMacOSXEntry.o: $(MAC_OSX_DIR)/tkMacOSXEntry.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEntry.c\n\ntkMacOSXEvent.o: $(MAC_OSX_DIR)/tkMacOSXEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEvent.c\n\ntkMacOSXFileTypes.o: $(MAC_OSX_DIR)/tkMacOSXFileTypes.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXFileTypes.c\n\ntkMacOSXFont.o: $(MAC_OSX_DIR)/tkMacOSXFont.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXFont.c\n\ntkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c\n\ntkMacOSXImage.o: $(MAC_OSX_DIR)/tkMacOSXImage.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXImage.c\n\ntkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh\n\t$(CC) -c $(CC_SWITCHES) \\\n\t    $(MAC_OSX_DIR)/tkMacOSXInit.c\n\ntkMacOSXKeyboard.o: $(MAC_OSX_DIR)/tkMacOSXKeyboard.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyboard.c\n\ntkMacOSXKeyEvent.o: $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c\n\ntkMacOSXMenu.o: $(MAC_OSX_DIR)/tkMacOSXMenu.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenu.c\n\ntkMacOSXMenubutton.o: $(MAC_OSX_DIR)/tkMacOSXMenubutton.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenubutton.c\n\ntkMacOSXMenus.o: $(MAC_OSX_DIR)/tkMacOSXMenus.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenus.c\n\ntkMacOSXMouseEvent.o: $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c\n\ntkMacOSXNotify.o: $(MAC_OSX_DIR)/tkMacOSXNotify.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXNotify.c\n\ntkMacOSXPrint.o: $(MAC_OSX_DIR)/tkMacOSXPrint.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXPrint.c\n\ntkMacOSXRegion.o: $(MAC_OSX_DIR)/tkMacOSXRegion.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXRegion.c\n\ntkMacOSXScrlbr.o: $(MAC_OSX_DIR)/tkMacOSXScrlbr.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXScrlbr.c\n\ntkMacOSXSend.o: $(MAC_OSX_DIR)/tkMacOSXSend.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSend.c\n\ntkMacOSXServices.o: $(MAC_OSX_DIR)/tkMacOSXServices.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXServices.c\n\ntkMacOSXSubwindows.o: $(MAC_OSX_DIR)/tkMacOSXSubwindows.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSubwindows.c\n\ntkMacOSXTest.o: $(MAC_OSX_DIR)/tkMacOSXTest.c\n\t$(CC) -c $(APP_CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXTest.c\n\ntkMacOSXWindowEvent.o: $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c\n\ntkMacOSXWm.o: $(MAC_OSX_DIR)/tkMacOSXWm.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXWm.c\n\ntkMacOSXXStubs.o: $(MAC_OSX_DIR)/tkMacOSXXStubs.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXXStubs.c\n\ntkMacOSXSysTray.o: $(MAC_OSX_DIR)/tkMacOSXSysTray.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSysTray.c\n\ntkFileFilter.o: $(GENERIC_DIR)/tkFileFilter.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFileFilter.c\n\ntkMacWinMenu.o: $(GENERIC_DIR)/tkMacWinMenu.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMacWinMenu.c\n\ntkPointer.o: $(GENERIC_DIR)/tkPointer.c\n\t$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPointer.c\n\nxcolors.o: $(XLIB_DIR)/xcolors.c\n\t$(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xcolors.c\n\nxdraw.o: $(XLIB_DIR)/xdraw.c\n\t$(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xdraw.c\n\nxgc.o: $(XLIB_DIR)/xgc.c\n\t$(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xgc.c\n\nximage.o: $(XLIB_DIR)/ximage.c\n\t$(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/ximage.c\n\nxutil.o: $(XLIB_DIR)/xutil.c\n\t$(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xutil.c\n\nttkBlink.o: $(TTK_DIR)/ttkBlink.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkBlink.c\n\nttkButton.o: $(TTK_DIR)/ttkButton.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkButton.c\n\nttkCache.o: $(TTK_DIR)/ttkCache.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkCache.c\n\nttkClamTheme.o: $(TTK_DIR)/ttkClamTheme.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkClamTheme.c\n\nttkClassicTheme.o: $(TTK_DIR)/ttkClassicTheme.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkClassicTheme.c\n\nttkDefaultTheme.o: $(TTK_DIR)/ttkDefaultTheme.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkDefaultTheme.c\n\nttkElements.o: $(TTK_DIR)/ttkElements.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkElements.c\n\nttkEntry.o: $(TTK_DIR)/ttkEntry.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkEntry.c\n\nttkFrame.o: $(TTK_DIR)/ttkFrame.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkFrame.c\n\nttkImage.o: $(TTK_DIR)/ttkImage.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkImage.c\n\nttkInit.o: $(TTK_DIR)/ttkInit.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkInit.c\n\nttkLabel.o: $(TTK_DIR)/ttkLabel.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkLabel.c\n\nttkLayout.o: $(TTK_DIR)/ttkLayout.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkLayout.c\n\nttkManager.o: $(TTK_DIR)/ttkManager.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkManager.c\n\nttkNotebook.o: $(TTK_DIR)/ttkNotebook.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkNotebook.c\n\nttkPanedwindow.o: $(TTK_DIR)/ttkPanedwindow.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkPanedwindow.c\n\nttkProgress.o: $(TTK_DIR)/ttkProgress.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkProgress.c\n\nttkScale.o: $(TTK_DIR)/ttkScale.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScale.c\n\nttkScroll.o: $(TTK_DIR)/ttkScroll.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScroll.c\n\nttkScrollbar.o: $(TTK_DIR)/ttkScrollbar.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScrollbar.c\n\nttkSeparator.o: $(TTK_DIR)/ttkSeparator.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkSeparator.c\n\nttkSquare.o: $(TTK_DIR)/ttkSquare.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkSquare.c\n\nttkState.o: $(TTK_DIR)/ttkState.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkState.c\n\nttkStubInit.o: $(TTK_DIR)/ttkStubInit.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkStubInit.c\n\nttkTagSet.o: $(TTK_DIR)/ttkTagSet.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTagSet.c\n\nttkTheme.o: $(TTK_DIR)/ttkTheme.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTheme.c\n\nttkToggleswitch.o: $(TTK_DIR)/ttkToggleswitch.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkToggleswitch.c\n\nttkTrace.o: $(TTK_DIR)/ttkTrace.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTrace.c\n\nttkTrack.o: $(TTK_DIR)/ttkTrack.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTrack.c\n\nttkTreeview.o: $(TTK_DIR)/ttkTreeview.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTreeview.c\n\nttkWidget.o: $(TTK_DIR)/ttkWidget.c\n\t$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkWidget.c\n\nttkMacOSXTheme.o: $(MAC_OSX_DIR)/ttkMacOSXTheme.c\n\t$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/ttkMacOSXTheme.c\n\ntkUuid.h: $(TOP_DIR)/manifest.uuid\n\techo \"#define TK_VERSION_UUID \\\\\" >$@\n\tcat $(TOP_DIR)/manifest.uuid >>$@\n\techo \"\" >>$@\n\n.c.o:\n\t$(CC) -c $(CC_SWITCHES) $<\n\n#\n# Target to regenerate header files and stub files from the *.decls tables.\n#\n\n$(GENERIC_DIR)/tkStubInit.c: $(GENERIC_DIR)/tk.decls \\\n\t\t$(GENERIC_DIR)/tkInt.decls\n\t@echo \"Warning: tkStubInit.c may be out of date.\"\n\t@echo \"Developers may want to run \\\"make genstubs\\\" to regenerate.\"\n\t@echo \"This warning can be safely ignored, do not report as a bug!\"\n\n$(TTK_DIR)/ttkStubInit.c: $(TTK_DIR)/ttk.decls\n\t@echo \"Warning: ttkStubInit.c may be out of date.\"\n\t@echo \"Developers may want to run \\\"make genstubs\\\" to regenerate.\"\n\t@echo \"This warning can be safely ignored, do not report as a bug!\"\n\ngenstubs:\n\t$(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \\\n\t\t$(GENERIC_DIR)/tk.decls $(GENERIC_DIR)/tkInt.decls\n\t$(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(TTK_DIR) $(TTK_DIR)/ttk.decls\n\n#\n# Target to check that all exported functions have an entry in the stubs\n# tables.\n#\n\ncheckstubs: $(TK_LIB_FILE)\n\t-@for i in `nm -p $(TK_LIB_FILE) \\\n\t\t| awk '$$2 ~ /^[TDBCS]$$/ { sub(\"^_\", \"\", $$3); print $$3 }' \\\n\t\t| sort -n`; do \\\n\t\tmatch=0; \\\n\t\tfor j in $(TK_DECLS) $(TTK_DECLS); do \\\n\t\t    if [ `grep -c \"$$i *(\" $$j` -gt 0 ]; then \\\n\t\t\tmatch=1; \\\n\t\t    fi; \\\n\t\tdone; \\\n\t\tif [ $$match -eq 0 ]; then echo $$i; fi \\\n\tdone\n\n#\n# Target to check for proper usage of UCHAR macro.\n#\n\ncheckuchar:\n\t-egrep isalnum\\|isalpha\\|iscntrl\\|isdigit\\|islower\\|isprint\\|ispunct\\|isspace\\|isupper\\|isxdigit\\|toupper\\|tolower $(SRCS) | grep -v UCHAR\n\n#\n# Target to make sure that only symbols with \"Tk\", \"tk\", \"Ttk\", \"ttk\" or \"X\"\n# prefixes are exported.\n#\n\ncheckexports: $(TK_LIB_FILE)\n\t-@nm -p $(TK_LIB_FILE) \\\n\t| awk '$$2 ~ /^[TDBCS]$$/ { sub(\"^_\", \"\", $$3); print $$3 }' \\\n\t| sort -n | grep -E -v '^([Tt]t?k|_?X)' || true\n\n#\n# Target to create a Tk RPM for Linux.  Requires that you be on a Linux\n# system.\n#\n\nrpm: all\n\trm -f THIS.TCL.SPEC\n\techo \"%define _builddir `pwd`\" > THIS.TK.SPEC\n\techo \"%define _rpmdir `pwd`/RPMS\" >> THIS.TK.SPEC\n\tcat tk.spec >> THIS.TK.SPEC\n\tmkdir -p RPMS/i386\n\trpmbuild -bb THIS.TK.SPEC\n\tmv RPMS/i386/*.rpm .\n\trm -rf RPMS THIS.TK.SPEC\n\n#\n# Target to create a proper Tk distribution from information in the\n# source directory.  DISTDIR must be defined to indicate where\n# to put the distribution.  DISTDIR must be an absolute path name.\n#\n\nDISTROOT = /tmp/dist\nDISTNAME = tk${VERSION}${PATCH_LEVEL}\nZIPNAME\t = tk${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip\nDISTDIR\t = $(DISTROOT)/$(DISTNAME)\nDIST_INSTALL_DATA   = $(INSTALL) -p -m 644\nDIST_INSTALL_SCRIPT = $(INSTALL) -p -m 755\n\n$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tcl.m4 \\\n\t\t$(UNIX_DIR)/aclocal.m4\n\t@cd $(UNIX_DIR); autoconf || \\\n\t\techo \"WARNING: Unable to rebuild $(UNIX_DIR)/configure. Please upgrade autoconf.\"\n$(UNIX_DIR)/tkConfig.h.in: $(MAC_OSX_DIR)/configure.ac\n\t@cd $(MAC_OSX_DIR); autoheader || touch $@\n\n$(TOP_DIR)/manifest.uuid:\n\tprintf \"git-\" >$(TOP_DIR)/manifest.uuid\n\t(cd $(TOP_DIR); git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid || printf \"unknown\" >$(TOP_DIR)/manifest.uuid)\n\ndist: $(UNIX_DIR)/configure $(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in \\\n\t\t$(TOP_DIR)/doc/man.macros $(TOP_DIR)/manifest.uuid\n\trm -rf $(DISTDIR)\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/unix\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/manifest.uuid $(DISTDIR)\n\t$(DIST_INSTALL_DATA) $(UNIX_DIR)/*.c $(UNIX_DIR)/tkUnixDefault.h \\\n\t\t$(UNIX_DIR)/tkUnixInt.h $(UNIX_DIR)/tkUnixPort.h $(DISTDIR)/unix\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix\n\t$(DIST_INSTALL_DATA) $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tk.spec \\\n\t\t$(UNIX_DIR)/aclocal.m4 $(UNIX_DIR)/tcl.m4 \\\n\t\t$(UNIX_DIR)/tkConfig.sh.in $(UNIX_DIR)/install-sh \\\n\t\t$(UNIX_DIR)/README $(UNIX_DIR)/installManPage \\\n\t\t$(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(DISTDIR)/unix\n\t$(DIST_INSTALL_SCRIPT) $(UNIX_DIR)/configure $(DISTDIR)/unix\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/bitmaps\n\t@(cd $(TOP_DIR); for i in bitmaps/* ; do \\\n\t    if [ -f $$i ] ; then \\\n\t\tsed -e 's/static char/static unsigned char/' \\\n\t\t       $$i > $(DISTDIR)/$$i; \\\n\t    fi; \\\n\tdone;)\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/generic\n\t$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.[ch] $(DISTDIR)/generic\n\t$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.decls $(DISTDIR)/generic\n\t$(DIST_INSTALL_DATA) $(GENERIC_DIR)/README $(DISTDIR)/generic\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/changes.md $(TOP_DIR)/README.md \\\n\t\t$(TOP_DIR)/license.terms $(DISTDIR)\n\trm -f $(DISTDIR)/generic/blt*.[ch]\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/generic/ttk\n\t$(DIST_INSTALL_DATA) $(TTK_DIR)/*.[ch] $(TTK_DIR)/ttk.decls \\\n\t\t$(DISTDIR)/generic/ttk\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/win\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.in $(DISTDIR)/win\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/win/configure.ac \\\n\t\t$(TOP_DIR)/win/aclocal.m4 $(TOP_DIR)/win/tcl.m4 \\\n\t\t$(TOP_DIR)/win/*.c $(TOP_DIR)/win/*.bat \\\n\t\t$(TOP_DIR)/win/tkWin.h $(TOP_DIR)/win/tkWinDefault.h \\\n\t\t$(TOP_DIR)/win/tkWinIco.h $(TOP_DIR)/win/tkWinInt.h \\\n\t\t$(TOP_DIR)/win/tkWinPort.h $(TOP_DIR)/win/tkWinSendCom.h \\\n\t\t$(TOP_DIR)/win/*.vc $(TOP_DIR)/win/README \\\n\t\t$(TOP_DIR)/license.terms \\\n\t\t$(DISTDIR)/win\n\t$(DIST_INSTALL_SCRIPT) $(TOP_DIR)/win/configure $(DISTDIR)/win\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/win/rc\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/win/rc/*.{rc,cur,ico} $(DISTDIR)/win/rc\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/macosx\n\t$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \\\n\t\t$(MAC_OSX_DIR)/*.icns $(MAC_OSX_DIR)/*.tiff \\\n\t\t$(MAC_OSX_DIR)/*.[ch] $(MAC_OSX_DIR)/*.in \\\n\t\t$(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.sdef \\\n\t\t$(DISTDIR)/macosx\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/macosx\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/xlib\n\t$(DIST_INSTALL_DATA) $(XLIB_DIR)/*.[ch] $(DISTDIR)/xlib\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/xlib\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/xlib/X11\n\t$(DIST_INSTALL_DATA) $(XLIB_DIR)/X11/*.h $(DISTDIR)/xlib/X11\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/xlib/X11\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \\\n\t\t$(TOP_DIR)/library/tclIndex \\\n\t\t$(DISTDIR)/library\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library/ttk\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/library/ttk/*.tcl $(DISTDIR)/library/ttk\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library/images\n\t@(cd $(TOP_DIR); for i in library/images/* ; do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \\\n\t    fi; \\\n\tdone;)\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library/msgs\n\t@(cd $(TOP_DIR); for i in library/msgs/*.msg ; do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \\\n\t    fi; \\\n\tdone;)\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library/demos\n\tcp -pr $(TOP_DIR)/library/demos/*.tcl \\\n\t\t$(TOP_DIR)/library/demos/*.msg \\\n\t\t$(TOP_DIR)/library/demos/tclIndex \\\n\t\t$(TOP_DIR)/library/demos/accessiblewidget \\\n\t\t$(TOP_DIR)/library/demos/browse \\\n\t\t$(TOP_DIR)/library/demos/hello $(TOP_DIR)/library/demos/ixset \\\n\t\t$(TOP_DIR)/library/demos/rmt $(TOP_DIR)/library/demos/rolodex \\\n\t\t$(TOP_DIR)/library/demos/square \\\n\t\t$(TOP_DIR)/library/demos/tcolor \\\n\t\t$(TOP_DIR)/library/demos/timer \\\n\t\t$(TOP_DIR)/library/demos/widget \\\n\t\t$(TOP_DIR)/library/demos/README \\\n\t\t$(TOP_DIR)/license.terms $(DISTDIR)/library/demos\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/library/demos/images\n\t@(cd $(TOP_DIR); for i in library/demos/images/* ; do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \\\n\t    fi; \\\n\tdone;)\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/doc\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \\\n\t\t$(TOP_DIR)/doc/man.macros $(DISTDIR)/doc\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/tests\n\t$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TEST_DIR)/testutils.GUIDE \\\n\t\t$(TEST_DIR)/README $(TEST_DIR)/*.{test,tcl,gif,png,ppm,xbm} \\\n\t\t$(TEST_DIR)/option.file* $(DISTDIR)/tests\n\t$(INSTALL_DATA_DIR) $(DISTDIR)/tests/ttk\n\t$(DIST_INSTALL_DATA) $(TEST_DIR)/ttk/*.{svg,test,tcl} $(DISTDIR)/tests/ttk\n\tmkdir -p $(DISTDIR)/.github/workflows\n\tcp -p $(TOP_DIR)/.github/workflows/*.yml $(DISTDIR)/.github/workflows\n\nalldist: dist\n\trm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)\n\tcd $(DISTROOT); tar cf $(DISTNAME)-src.tar $(DISTNAME); \\\n\t\tgzip -9 $(DISTNAME)-src.tar; zip -qr8 $(ZIPNAME) $(DISTNAME)\n\n#\n# This target creates the HTML folder for Tcl & Tk and places it\n# in DISTDIR/html.  It uses the tcltk-man2html.tcl tool from\n# the Tcl group's tool workspace.  It depends on the Tcl & Tk being\n# in directories called tcl9.1 & tk9.1 up two directories from the\n# TOOL_DIR.\n#\n\nhtml:\n\t$(BUILD_HTML)\n\t@EXTRA_BUILD_HTML@\nhtml-tcl:\n\t$(BUILD_HTML) --tcl\n\t@EXTRA_BUILD_HTML@\nhtml-tk:\n\t$(BUILD_HTML) --tk\n\t@EXTRA_BUILD_HTML@\n\nBUILD_HTML = \\\n\t@if test -f \"$(BUILD_TCLSH)\"; then \\\n\t$(SHELL_ENV) TCLSH=\"$(BUILD_TCLSH)\"; else \\\n\tTCLSH=\"$(TCL_EXE)\"; fi ;\\\n\t\"$${TCLSH}\" $(TOOL_DIR)/tcltk-man2html.tcl --htmldir=\"$(HTML_INSTALL_DIR)\" \\\n\t\t--srcdir=$(TOP_DIR)/.. $(BUILD_HTML_FLAGS)\n\n#\n# The list of all the targets that do not correspond to real files. This stops\n# 'make' from getting confused when someone makes an error in a rule.\n#\n\n.PHONY: all binaries libraries objs doc html html-tcl html-tk test runtest\n.PHONY: install install-strip install-binaries install-libraries\n.PHONY: install-headers install-private-headers install-doc\n.PHONY: clean distclean depend genstubs checkstubs checkexports checkuchar\n.PHONY: shell gdb valgrind valgrindshell dist alldist rpm\n.PHONY: tkLibObjs tktest-real test-classic test-ttk testlang\n.PHONY: demo install-demos\n\n# DO NOT DELETE THIS LINE -- make depend depends on it.\n"
  },
  {
    "path": "unix/README",
    "content": "Tk UNIX README\n--------------\n\nThis is the directory where you configure, compile, test, and install UNIX\nversions of Tk. This directory also contains source files for Tk that are\nspecific to UNIX.\n\nThe information in this file is maintained at:\n\thttps://www.tcl-lang.org//doc/howto/compile.html\n\nFor information on platforms where Tcl/Tk is known to compile, along with any\nporting notes for getting it to work on those platforms, see:\n\thttps://www.tcl-lang.org//software/tcltk/platforms.html\n\nThe rest of this file contains instructions on how to do this. The release\nshould compile and run either \"out of the box\" or with trivial changes on any\nUNIX-like system that approximates POSIX, BSD, or System V. We know that it\nruns on workstations from Sun, H-P, DEC, IBM, and SGI, as well as PCs running\nLinux, BSDI, and SCO UNIX. To compile for a PC running Windows, see the README\nfile in the directory ../win. To compile for MacOSX, see the README file in\nthe directory ../macosx.\n\nHow To Compile And Install Tk:\n------------------------------\n\n(a) Make sure that the Tcl release is present in the directory\n    ../../tcl<version> (or else use the \"--with-tcl\" switch described below).\n    This release of Tk will only work with the equivalently versioned Tcl\n    release. Also, be sure that you have configured Tcl before you configure\n    Tk.\n\n(b) Check for patches as described in ../README.\n\n(c) If you have already compiled Tk once in this directory and are now\n    preparing to compile again in the same directory but for a different\n    platform, or if you have applied patches, type \"make distclean\" to discard\n    all the configuration information computed previously.\n\n(d) Type \"./configure\". This runs a configuration script created by GNU\n    autoconf, which configures Tk for your system and creates a Makefile. The\n    configure script allows you to customize the Tk configuration for your\n    site; for details on how you can do this, type \"./configure -help\" or\n    refer to the autoconf documentation (not included here). Tk's \"configure\"\n    script supports the following special switches in addition to the standard\n    ones:\n\n\t--with-tcl=DIR\t\tSpecifies the directory containing the Tcl\n\t\t\t\tbinaries and Tcl's platform-dependent\n\t\t\t\tconfiguration information. By default the Tcl\n\t\t\t\tdirectory is assumed to be in the location\n\t\t\t\tgiven by (a) above.\n\t--with-x=DIR\t\tTells configure where to find an installation\n\t\t\t\tof the X Window System. Not normally needed.\n\t--enable-shared\t\tIf this switch is specified, Tk will compile\n\t\t\t\titself as a shared library if it can figure\n\t\t\t\tout how to do that on this platform. This is\n\t\t\t\tthe default on platforms where we know how to\n\t\t\t\tbuild shared libraries.\n\t--disable-shared\tIf this switch is specified, Tk will compile\n\t\t\t\titself as a static library.\n\t--disable-rpath\t\tTurns off use of the rpath link option on\n\t\t\t\tplatforms that would otherwise use it.\n\t--enable-symbols\tBuild with debugging symbols. By default\n\t\t\t\tstandard debugging symbols are used. You can\n\t\t\t\tspecify the value \"mem\" to include\n\t\t\t\tTCL_MEM_DEBUG memory debugging.\n\t--disable-symbols\tBuild without debugging symbols\n\t--enable-64bit\t\tEnable 64bit support (where applicable)\n\t--disable-64bit\t\tDisable 64bit support (where applicable)\n\t--enable-64bit-vis\tEnable 64bit Sparc VIS support\n\t--disable-64bit-vis\tDisable 64bit Sparc VIS support\n\t--disable-xft\t\tDisable support for antialiased fonts via the\n\t\t\t\tFreetype/xft library. By default, this is\n\t\t\t\tswitched on whenever the configure script can\n\t\t\t\tdetect the required libraries.\n\t--enable-man-symlinks\tUse symlinks for linking the manpages that\n\t\t\t\tshould be reachable under several names.\n\t--enable-man-compression=PROG\n\t\t\t\tCompress the manpages using PROG.\n\t--enable-man-suffix=STRING\n\t\t\t\tAdd STRING to the name of each of the manual\n\t\t\t\tpages. If specified without giving STRING, the\n\t\t\t\tsuffix will be \"tk\".\n\n    Mac OS X only:\n\n\t--enable-framework\tPackage Tk as a framework.\n\t--disable-corefoundation Disable use of CoreFoundation API.\n\t--enable-aqua\t\tUse Aqua windowingsystem rather than X11,\n\t\t\t\trequires --enable-corefoundation with Tcl and\n\t\t\t\tTk.\n\n    Note: by default gcc will be used if it can be located on the PATH. If you\n    want to use cc instead of gcc, set the CC environment variable to \"cc\"\n    before running configure. It is not safe to change the Makefile to use gcc\n    after configure is run.\n\n    Note: be sure to use only absolute path names (those starting with \"/\") in\n    the --prefix and --exec-prefix options.\n\n(e) Type \"make\". This will create a library archive called \"libtk<version>.a\"\n    or \"libtk<version>.so\" and an interpreter application called \"wish\" that\n    allows you to type Tcl/Tk commands interactively or execute script files.\n    It will also create a stub library archive \"libtkstub<version>.a\" that\n    developers may link against other C code to produce loadable extensions\n    that call into Tk's public interface routines.\n\n(f) If the make fails then you'll have to personalize the Makefile for your\n    site or possibly modify the distribution in other ways. First check the\n    porting Web page above to see if there are hints for compiling on your\n    system. If you need to modify Makefile, there are comments at the\n    beginning of it that describe the things you might want to change and how\n    to change them.\n\n(g) Type \"make install\" to install Tk's binaries and script files in standard\n    places. You'll need write permission on the installation directories to do\n    this. The installation directories are determined by the \"configure\"\n    script and may be specified with the --prefix and --exec-prefix options to\n    \"configure\". See the Makefile for information on what directories were\n    chosen. You should not override these choices by modifying the Makefile,\n    or by copying files post-install. The installed binaries have embedded\n    within them path values relative to the install directory. If you change\n    your mind about where Tk should be installed, start this procedure over\n    again from step (a) so that the path embedded in the binaries agrees with\n    the install location.\n\n(h) At this point you can play with Tk by running the installed \"wish\"\n    executable, or via the \"make shell\" target, and typing Tcl/Tk commands at\n    the interactive prompt.\n\nIf you have trouble compiling Tk, see the URL noted above about working\nplatforms. It contains information that people have provided about changes\nthey had to make to compile Tk in various environments. We're also interested\nin hearing how to change the configuration setup so that Tk compiles on\nadditional platforms \"out of the box\".\n\nNote: Do not specify either of the TCL_LIBRARY and TK_LIBRARY environment\nvariables in a production installation, as this can cause conflicts between\ndifferent versions of the libraries. Instead, the libraries should have the\ncorrect locations of their associated script directories built into them.\n\nTest suite\n----------\n\nTk has a substantial self-test suite, consisting of a set of scripts in the\nsubdirectory \"tests\". To run the test suite just type \"make test\" in this\ndirectory. You should then see a printout of the test files processed. If any\nerrors occur, you'll see a much more substantial printout for each error. In\norder to avoid false error reports, be sure to run the tests with an empty\nresource database (e.g., remove your .Xdefaults file or delete any entries\nstarting with *). Also, don't try to do anything else with your display or\nkeyboard while the tests are running, or you may get false violations. See the\nREADME file in the \"tests\" directory for more information on the test suite.\n\nIf the test suite generates errors, most likely they are due to non-portable\ntests that are interacting badly with your system configuration. We are\ngradually eliminating the non-portable tests, but this release includes many\nnew tests so there will probably be some portability problems. As long as the\ntest suite doesn't core dump, it's probably safe to conclude that any errors\nrepresent portability problems in the test suite and not fundamental flaws\nwith Tk.\n\nThere are also a number of visual tests for things such as screen layout,\nPostscript generation, etc. These tests all have to be run by manually\nenabling the \"userInteraction\" constraint when testing, and the results have\nto be verified visually. This can be done with:\n\n    make test TESTFLAGS=\"-constraints userInteraction\"\n\nSome tests will present a main window with a bunch of menus, which you can use\nto select various tests.\n"
  },
  {
    "path": "unix/aclocal.m4",
    "content": "builtin(include,../unix/tcl.m4)\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBAlgorithm.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_ALGORITHM_H\n#define _SB_PUBLIC_ALGORITHM_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBBidiType.h>\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBParagraph.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef const struct _SBAlgorithm *SBAlgorithmRef;\n\n/**\n * Creates an algorithm object for the specified code point sequence. The source string inside the\n * code point sequence should not be freed until the algorithm object is in use.\n *\n * @param codepointSequence\n *      The code point sequence to apply bidirectional algorithm on.\n * @return\n *      A reference to an algorithm object if the call was successful, NULL otherwise.\n */\nSB_PUBLIC SBAlgorithmRef SBAlgorithmCreate(const SBCodepointSequence *codepointSequence);\n\n/**\n * Returns a direct pointer to the bidirectional types of code units, stored in the algorithm\n * object.\n *\n * @param algorithm\n *      The algorithm object from which to access the bidirectional types of code units.\n * @return\n *      A valid pointer to an array of SBBidiType structures, whose length will be equal to that of\n *      string buffer.\n */\nSB_PUBLIC const SBBidiType *SBAlgorithmGetBidiTypesPtr(SBAlgorithmRef algorithm);\n\n/**\n * Determines the boundary of first paragraph within the specified range.\n *\n * The boundary of the paragraph occurs after a code point whose bidirectional type is Paragraph\n * Separator (B), or at the suggestedLength if no such code point exists before it. The exception to\n * this rule is when a Carriage Return (CR) is followed by a Line Feed (LF). Both CR and LF are\n * paragraph separators, but in that case, the boundary of the paragraph is considered after LF code\n * point.\n *\n * @param algorithm\n *      The algorithm object to use for determining paragraph boundary.\n * @param paragraphOffset\n *      The index to the first code unit of the paragraph in source string.\n * @param suggestedLength\n *      The number of code units covering the suggested length of the paragraph.\n * @param acutalLength\n *      The actual length of the first paragraph, including the paragraph separator, within the\n *      given range.\n * @param separatorLength\n *      On output, the length of paragraph separator. This parameter can be set to NULL if not\n *      needed.\n */\nSB_PUBLIC void SBAlgorithmGetParagraphBoundary(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength,\n    SBUInteger *acutalLength, SBUInteger *separatorLength);\n\n/**\n * Creates a paragraph object processed with Unicode Bidirectional Algorithm.\n *\n * This function processes only first paragraph starting at paragraphOffset with length less than or\n * equal to suggestedLength, in accordance with Rule P1 of Unicode Bidirectional Algorithm.\n *\n * The paragraph level is determined by applying Rules P2-P3 and embedding levels are resolved by\n * applying Rules X1-I2.\n *\n * @param algorithm\n *      The algorithm object to use for creating the desired paragraph.\n * @param paragraphOffset\n *      The index to the first code unit of the paragraph in source string.\n * @param suggestedLength\n *      The number of code units covering the suggested length of the paragraph.\n * @param baseLevel\n *      The desired base level of the paragraph. Rules P2-P3 would be ignored if it is neither\n *      SBLevelDefaultLTR nor SBLevelDefaultRTL.\n * @return\n *      A reference to a paragraph object if the call was successful, NULL otherwise.\n */\nSB_PUBLIC SBParagraphRef SBAlgorithmCreateParagraph(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel);\n\n/**\n * Increments the reference count of an algorithm object.\n *\n * @param algorithm\n *      The algorithm object whose reference count will be incremented.\n * @return\n *      The same algorithm object passed in as the parameter.\n */\nSB_PUBLIC SBAlgorithmRef SBAlgorithmRetain(SBAlgorithmRef algorithm);\n\n/**\n * Decrements the reference count of an algorithm object. The object will be deallocated when its\n * reference count reaches zero.\n *\n * @param algorithm\n *      The algorithm object whose reference count will be decremented.\n */\nSB_PUBLIC void SBAlgorithmRelease(SBAlgorithmRef algorithm);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBAllocator.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_ALLOCATOR_H\n#define _SB_PUBLIC_ALLOCATOR_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef const struct _SBAllocator *SBAllocatorRef;\n\n/**\n * Function type for allocating a single memory block.\n *\n * @param size\n *      Size of the memory block to allocate, in bytes.\n * @param info\n *      User-defined context pointer provided during allocator creation.\n * @return\n *      Pointer to the allocated memory block, or `NULL` on failure.\n */\ntypedef void *(*SBAllocatorAllocateBlockFunc)(SBUInteger size, void *info);\n\n/**\n * Function type for resizing a previously allocated memory block.\n *\n * @param pointer\n *      Pointer to the memory block to be resized.\n * @param newSize\n *      The new size in bytes for the memory block.\n * @param info\n *      User-defined context pointer provided during allocator creation.\n * @return\n *      Pointer to the resized memory block, or `NULL` if the operation failed.\n */\ntypedef void *(*SBAllocatorReallocateBlockFunc)(void *pointer, SBUInteger newSize, void *info);\n\n/**\n * Function type for deallocating a previously allocated memory block.\n *\n * @param pointer\n *      Pointer to the memory block to deallocate.\n * @param info\n *      User-defined context pointer provided during allocator creation.\n */\ntypedef void (*SBAllocatorDeallocateBlockFunc)(void *pointer, void *info);\n\n/**\n * Function type for allocating short-lived scratch memory.\n *\n * Scratch allocations are intended for temporary use within the scope of a public function call.\n * All memory returned by this function is automatically invalidated after a corresponding call to\n * `resetScratch`, which is typically called at the end of the same public function.\n *\n * The implementation is responsible for managing thread safety (e.g. using thread-local buffers,\n * locking, or fallback mechanisms).\n *\n * @param size\n *      The requested size of scratch memory, in bytes.\n * @param info\n *      User-defined context pointer provided during allocator creation.\n * @return\n *      Pointer to the allocated memory block, or `NULL` on failure.\n */\ntypedef void *(*SBAllocatorAllocateScratchFunc)(SBUInteger size, void *info);\n\n/**\n * Function type for resetting the scratch memory space.\n *\n * This invalidates all previous scratch allocations for the current execution context (e.g.,\n * thread). It is typically called once per public function to reuse memory without freeing\n * individual chunks.\n *\n * @param info\n *      User-defined context pointer provided during allocator creation.\n */\ntypedef void (*SBAllocatorResetScratchFunc)(void *info);\n\n/**\n * Function signature for finalizing an allocator object.\n * This is called once the reference count reaches zero.\n *\n * @param info\n *      User-defined context pointer provided during allocator creation.\n */\ntypedef void (*SBAllocatorFinalizeFunc)(void *info);\n\n/**\n * Set of function pointers defining a memory allocator protocol.\n *\n * All functions are optional except `allocateBlock` and `deallocateBlock`. Optional functions will\n * fall back to standard mechanisms if not provided.\n */\ntypedef struct _SBAllocatorProtocol {\n    /**\n     * Allocates a memory block of the given size.\n     */\n    SBAllocatorAllocateBlockFunc allocateBlock;\n    /**\n     * Reallocates a previously allocated block to a new size.\n     */\n    SBAllocatorReallocateBlockFunc reallocateBlock;\n    /**\n     * Deallocates a memory block.\n     */\n    SBAllocatorDeallocateBlockFunc deallocateBlock;\n    /**\n     * Allocates short-lived scratch memory.\n     * If `NULL`, the allocator will return `NULL` prompting the caller to use `allocateBlock`\n     * instead.\n     */\n    SBAllocatorAllocateScratchFunc allocateScratch;\n    /**\n     * Resets the scratch memory space, invalidating previous allocations.\n     * If `NULL`, the allocator will do nothing.\n     */\n    SBAllocatorResetScratchFunc resetScratch;\n    /**\n     * Optional function to finalize the allocator when its reference count drops to zero.\n     */\n    SBAllocatorFinalizeFunc finalize;\n} SBAllocatorProtocol;\n\n/**\n * Returns the global default allocator object.\n */\nSB_PUBLIC SBAllocatorRef SBAllocatorGetDefault(void);\n\n/**\n * Sets the global default allocator object.\n * \n * @param allocator\n *      The allocator object to set as the default. If `NULL`, the default allocator will be reset\n *      to a standard implementation.\n */\nSB_PUBLIC void SBAllocatorSetDefault(SBAllocatorRef allocator);\n\n/**\n * Creates a custom allocator using the provided allocation protocol and optional context.\n *\n * @param protocol\n *      The set of function pointers defining custom allocation behavior.\n * @param info\n *      An optional pointer to context data passed to each allocator function.\n * @return\n *      A reference to the allocator instance, or `NULL` on failure.\n */\nSB_PUBLIC SBAllocatorRef SBAllocatorCreate(const SBAllocatorProtocol *protocol, void *info);\n\n/**\n * Increments the reference count of an allocator object.\n * \n * @param allocator\n *      The allocator object whose reference count will be incremented.\n * @return\n *      The same allocator object passed in as the parameter.\n */\nSB_PUBLIC SBAllocatorRef SBAllocatorRetain(SBAllocatorRef allocator);\n\n/**\n * Decrements the reference count of an allocator object. The object will be deallocated when its\n * reference count reaches zero.\n * \n * @param allocator\n *      The allocator object whose reference count will be decremented.\n */\nSB_PUBLIC void SBAllocatorRelease(SBAllocatorRef allocator);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBAttributeInfo.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_ATTRIBUTE_INFO_H\n#define _SB_PUBLIC_ATTRIBUTE_INFO_H\n\n#include <SheenBidi/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\nenum {\n    SBAttributeIDNone = 0           /**< No Attribute */\n};\n/**\n * Opaque numeric identifier assigned by the registry to an attribute.\n * \n * Attribute IDs are used everywhere in the API to refer to known attributes; clients can fetch\n * metadata via the attribute registry.\n */\ntypedef SBUInteger SBAttributeID;\n\nenum {\n    SBAttributeGroupNone = 0        /**< No Special Grouping */\n};\n/**\n * Abstract grouping for attributes (e.g., shaping, paint, language).\n * \n * Groups can be used for filtering and coalescing strategies.\n */\ntypedef SBUInt8 SBAttributeGroup;\n\nenum {\n    SBAttributeScopeCharacter = 0,  /**< Applies only to the exact character range. */\n    SBAttributeScopeParagraph = 1   /**< Applies to entire paragraphs intersecting range. */\n};\n/**\n * Application scope for an attribute.\n */\ntypedef SBUInt8 SBAttributeScope;\n\n/**\n * Callback function to compare two attribute values for equality.\n *\n * @param first\n *      First attribute value pointer.\n * @param second\n *      Second attribute value pointer.\n * @return\n *      `SBTrue` if equal, `SBFalse` otherwise.\n */\ntypedef SBBoolean (*SBAttributeValueEqualCallback)(const void *first, const void *second);\n\n/**\n * Callback function to retain an attribute value.\n *\n * @param value\n *      Pointer of attribute value to retain.\n * @return\n *      Pointer of retained attribute value.\n */\ntypedef const void *(*SBAttributeValueRetainCallback)(const void *value);\n\n/**\n * Callback function to release an attribute value.\n *\n * @param value\n *      Pointer of attribute value to release.\n */\ntypedef void (*SBAttributeValueReleaseCallback)(const void *value);\n\n/**\n * Lifecycle and equality callbacks for attribute value management.\n */\ntypedef struct _SBAttributeValueCallbacks {\n    /**\n     * Equality function (optional). If `NULL`, bitwise equality (memcmp) is used to compare\n     * attribute values.\n     */\n    SBAttributeValueEqualCallback equal;\n    /**\n     * Value retention function (optional). If `NULL`, values are stored as-is without modification.\n     */\n    SBAttributeValueRetainCallback retain;\n    /**\n     * Value release function (optional). If `NULL`, no cleanup is performed when values are\n     * removed.\n     */\n    SBAttributeValueReleaseCallback release;\n} SBAttributeValueCallbacks;\n\n/**\n * Public description of a registered attribute.\n */\ntypedef struct _SBAttributeInfo {\n    /**\n     * Null-terminated unique attribute name.\n     */\n    const char *name;\n    /**\n     * Abstract group used for filtering and run coalescing policies.\n     */\n    SBAttributeGroup group;\n    /**\n     * Application scope (character/paragraph).\n     */\n    SBAttributeScope scope;\n} SBAttributeInfo;\n\n/**\n * A stored attribute item with its ID and associated value.\n */\ntypedef struct _SBAttributeItem {\n    SBAttributeID attributeID;  /**< Attribute ID. */\n    /* Additional value field follows immediately after attributeID in memory */\n} SBAttributeItem;\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBAttributeList.h",
    "content": "/*\n * Copyright (C) 2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_ATTRIBUTE_LIST_H\n#define _SB_PUBLIC_ATTRIBUTE_LIST_H\n\n#include <SheenBidi/SBAttributeInfo.h>\n#include <SheenBidi/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Opaque reference to an attribute list.\n */\ntypedef const struct _SBAttributeList *SBAttributeListRef;\n\n/**\n * Returns a pointer to the attribute item located at the given index in the list.\n *\n * @param list\n *      The attribute list to retrieve from.\n * @param index\n *      The zero-based index of the item to retrieve. Must be less than the count returned by\n *      SBAttributeListGetCount().\n * @return\n *      A pointer to the attribute item at the specified index.\n */\nSB_PUBLIC const SBAttributeItem *SBAttributeListGetItem(SBAttributeListRef list, SBUInteger index);\n\n/**\n * Returns the number of attributes in the list.\n *\n * @param list\n *      The attribute list to query.\n * @return\n *      The total count of attributes currently stored in the list.\n */\nSB_PUBLIC SBUInteger SBAttributeListGetCount(SBAttributeListRef list);\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBAttributeRegistry.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_ATTRIBUTE_REGISTRY_H\n#define _SB_PUBLIC_ATTRIBUTE_REGISTRY_H\n\n#include <SheenBidi/SBAttributeInfo.h>\n#include <SheenBidi/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Opaque reference to an attribute registry.\n */\ntypedef const struct _SBAttributeRegistry *SBAttributeRegistryRef;\n\n/**\n * Creates an attribute registry from an array of attribute infos.\n * \n * @param attributeInfos\n *      Pointer to an array of `SBAttributeInfo` entries. The array content is copied internally;\n *      the caller retains ownership.\n * @param count\n *      Number of entries in the `attributeInfos` array.\n * @param valueSize\n *      The size in bytes of the value field for each attribute.\n * @param valueCallbacks\n *      Optional pointer to an `SBAttributeValueCallbacks` structure defining custom value lifecycle\n *      and comparison behavior.\n * @return\n *      A reference to the attribute registry instance, or `NULL` on failure.\n */\nSB_PUBLIC SBAttributeRegistryRef SBAttributeRegistryCreate(const SBAttributeInfo *attributeInfos,\n    SBUInteger count, SBUInt8 valueSize, const SBAttributeValueCallbacks *valueCallbacks);\n\n/**\n * Copies the info for a given attribute ID into the `attributeInfo` parameter.\n * \n * @param registry\n *      The attribute registry object.\n * @param attributeID\n *      Attribute ID to query.\n * @param attributeInfo\n *      Output pointer to receive a copy of the attribute info; must not be `NULL`.\n * @return\n *      `SBTrue` if the attribute ID exists in the registry, `SBFalse` otherwise.\n */\nSB_PUBLIC SBBoolean SBAttributeRegistryGetAttributeInfo(SBAttributeRegistryRef registry,\n    SBAttributeID attributeID, SBAttributeInfo *attributeInfo);\n\n/**\n * Looks up an attribute ID by name.\n * \n * @param registry\n *      The attribute registry object.\n * @param name\n *      Null-terminated unique name of the attribute to find.\n * @return\n *      The attribute ID for `name`, or `SBAttributeIDNone` if not found.\n */\nSB_PUBLIC SBAttributeID SBAttributeRegistryGetAttributeID(SBAttributeRegistryRef registry,\n    const char *name);\n\n/**\n * Increments the reference count of an attribute registry object.\n * \n * @param registry\n *      The attribute registry object whose reference count will be incremented.\n * @return\n *      The same attribute registry object passed in as the parameter.\n */\nSB_PUBLIC SBAttributeRegistryRef SBAttributeRegistryRetain(SBAttributeRegistryRef registry);\n\n/**\n * Decrements the reference count of an attribute registry object. The object will be deallocated\n * when its reference count reaches zero.\n *\n * @param registry\n *      The attribute registry object whose reference count will be decremented.\n */\nSB_PUBLIC void SBAttributeRegistryRelease(SBAttributeRegistryRef registry);\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBBase.h",
    "content": "/*\n * Copyright (C) 2014-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_BASE_H\n#define _SB_PUBLIC_BASE_H\n\n#include <stdint.h>\n\n#ifdef __cplusplus\n#define SB_EXTERN_C_BEGIN extern \"C\" {\n#define SB_EXTERN_C_END }\n#else\n#define SB_EXTERN_C_BEGIN\n#define SB_EXTERN_C_END\n#endif\n\n#ifdef _WIN32\n\n#if defined(SB_CONFIG_DLL_EXPORT)\n#define SB_PUBLIC __declspec(dllexport)\n#elif defined(SB_CONFIG_DLL_IMPORT)\n#define SB_PUBLIC __declspec(dllimport)\n#endif\n\n#endif\n\n#ifndef SB_PUBLIC\n#define SB_PUBLIC\n#endif\n\n#if defined(SB_CONFIG_EXPERIMENTAL_TEXT_API)\n#define SB_TEXT_API_SUPPORTED 1\n#else\n#define SB_TEXT_API_SUPPORTED 0\n#endif\n\n#if defined(__cplusplus) && __cplusplus >= 201402L\n#define SB_DEPRECATED [[deprecated]]\n#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L\n#define SB_DEPRECATED [[deprecated]]\n#elif defined(__clang__) || defined(__GNUC__)\n#define SB_DEPRECATED __attribute__((deprecated))\n#elif defined(_MSC_VER)\n#define SB_DEPRECATED __declspec(deprecated)\n#else\n#define SB_DEPRECATED\n#endif\n\nSB_EXTERN_C_BEGIN\n\n/**\n * A type to represent an 8-bit signed integer.\n */\ntypedef int8_t                      SBInt8;\n\n/**\n * A type to represent a 16-bit signed integer.\n */\ntypedef int16_t                     SBInt16;\n\n/**\n * A type to represent a 32-bit signed integer.\n */\ntypedef int32_t                     SBInt32;\n\n/**\n * A type to represent an 8-bit unsigned integer.\n */\ntypedef uint8_t                     SBUInt8;\n\n/**\n * A type to represent a 16-bit unsigned integer.\n */\ntypedef uint16_t                    SBUInt16;\n\n/**\n * A type to represent a 32-bit unsigned integer.\n */\ntypedef uint32_t                    SBUInt32;\n\n/**\n * A signed integer type whose width is equal to the width of the machine word.\n */\ntypedef intptr_t                    SBInteger;\n\n/**\n * An unsigned integer type whose width is equal to the width of the machine word.\n */\ntypedef uintptr_t                   SBUInteger;\n\n/**\n * Constants that specify the states of a boolean.\n */\nenum {\n    SBFalse = 0, /**< A value representing the false state. */\n    SBTrue  = 1  /**< A value representing the true state. */\n};\n/**\n * A type to represent a boolean value.\n */\ntypedef SBUInt8                     SBBoolean;\n\n#define SBUInt8InRange(v, s, e)     \\\n(                                   \\\n    (SBUInt8)((v) - (s))            \\\n <= (SBUInt8)((e) - (s))            \\\n)\n\n#define SBUInt16InRange(v, s, e)    \\\n(                                   \\\n    (SBUInt16)((v) - (s))           \\\n <= (SBUInt16)((e) - (s))           \\\n)\n\n#define SBUInt32InRange(v, s, e)    \\\n(                                   \\\n    (SBUInt32)((v) - (s))           \\\n <= (SBUInt32)((e) - (s))           \\\n)\n\n\n/**\n * A type to represent a bidi level.\n */\ntypedef SBUInt8                     SBLevel;\n\n/**\n * A value representing an invalid bidi level.\n */\n#define SBLevelInvalid              0xFF\n\n/**\n * A value representing maximum explicit embedding level.\n */\n#define SBLevelMax                  125\n\n/**\n * A value specifying to set base level to zero (left-to-right) if there is no strong character.\n */\n#define SBLevelDefaultLTR           0xFE\n\n/**\n * A value specifying to set base level to one (right-to-left) if there is no strong character.\n */\n#define SBLevelDefaultRTL           0xFD\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBBidiType.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_BIDI_TYPE_H\n#define _SB_PUBLIC_BIDI_TYPE_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Constants that specify the bidirectional types of a character.\n */\nenum {\n    SBBidiTypeNil = 0x00,\n\n    SBBidiTypeL   = 0x01,   /**< Strong: Left-to-Right */\n    SBBidiTypeR   = 0x02,   /**< Strong: Right-to-Left */\n    SBBidiTypeAL  = 0x03,   /**< Strong: Right-to-Left Arabic */\n\n    SBBidiTypeBN  = 0x04,   /**< Weak: Boundary Neutral */\n    SBBidiTypeNSM = 0x05,   /**< Weak: Non-Spacing Mark */\n    SBBidiTypeAN  = 0x06,   /**< Weak: Arabic Number */\n    SBBidiTypeEN  = 0x07,   /**< Weak: European Number */\n    SBBidiTypeET  = 0x08,   /**< Weak: European Number Terminator */\n    SBBidiTypeES  = 0x09,   /**< Weak: European Number Separator */\n    SBBidiTypeCS  = 0x0A,   /**< Weak: Common Number Separator */\n\n    SBBidiTypeWS  = 0x0B,   /**< Neutral: White Space */\n    SBBidiTypeS   = 0x0C,   /**< Neutral: Segment Separator */\n    SBBidiTypeB   = 0x0D,   /**< Neutral: Paragraph Separator */\n    SBBidiTypeON  = 0x0E,   /**< Neutral: Other Neutral */\n\n    SBBidiTypeLRI = 0x0F,   /**< Format: Left-to-Right Isolate */\n    SBBidiTypeRLI = 0x10,   /**< Format: Right-to-Left Isolate */\n    SBBidiTypeFSI = 0x11,   /**< Format: First Strong Isolate */\n    SBBidiTypePDI = 0x12,   /**< Format: Pop Directional Isolate */\n    SBBidiTypeLRE = 0x13,   /**< Format: Left-to-Right Embedding */\n    SBBidiTypeRLE = 0x14,   /**< Format: Right-to-Left Embedding */\n    SBBidiTypeLRO = 0x15,   /**< Format: Left-to-Right Override */\n    SBBidiTypeRLO = 0x16,   /**< Format: Right-to-Left Override */\n    SBBidiTypePDF = 0x17    /**< Format: Pop Directional Formatting */\n};\n\n/**\n * A type to represent the bidirectional type of a character.\n */\ntypedef SBUInt8 SBBidiType;\n\n/**\n * Checks whether specified bidirectional type is strong.\n */\n#define SBBidiTypeIsStrong(t)               SBUInt8InRange(t, SBBidiTypeL, SBBidiTypeAL)\n\n/**\n * Checks whether specified bidirectional type is weak.\n */\n#define SBBidiTypeIsWeak(t)                 SBUInt8InRange(t, SBBidiTypeBN, SBBidiTypeCS)\n\n/**\n * Checks whether specified bidirectional type is neutral.\n */\n#define SBBidiTypeIsNeutral(t)              SBUInt8InRange(t, SBBidiTypeWS, SBBidiTypeON)\n\n/**\n * Checks whether specified bidirectional type is format.\n */\n#define SBBidiTypeIsFormat(t)               SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypePDF)\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBCodepoint.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_CODEPOINT_H\n#define _SB_PUBLIC_CODEPOINT_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBBidiType.h>\n#include <SheenBidi/SBGeneralCategory.h>\n#include <SheenBidi/SBScript.h>\n\nSB_EXTERN_C_BEGIN\n\n/**\n * A type to represent a Unicode code point.\n */\ntypedef SBUInt32                    SBCodepoint;\n\n/**\n * A value representing an invalid Unicode code point.\n */\n#define SBCodepointInvalid          UINT32_MAX\n\n/**\n * A value representing a faulty Unicode code point.\n * \n * This value is used as a replacement for unrecognized code points during decoding.\n */\n#define SBCodepointFaulty           0xFFFD\n\n/**\n * The maximum valid Unicode code point value.\n * \n * Unicode code points are valid in the range [0x0000, 0x10FFFF].\n */\n#define SBCodepointMax              0x10FFFF\n\n/**\n * Checks if a code point is a UTF-16 surrogate.\n * \n * Surrogate code points lie within the range [0xD800, 0xDFFF] and are not valid Unicode scalar\n * values.\n *\n * @param c\n *      The code point to check.\n * @return\n *      `true` if the code point is a surrogate, `false` otherwise.\n */\n#define SBCodepointIsSurrogate(c)   SBUInt32InRange(c, 0xD800, 0xDFFF)\n\n/**\n * Checks if a code point is a valid Unicode scalar value.\n *\n * A code point is considered valid if:\n * - It is not a surrogate (i.e., not in the range 0xD800 to 0xDFFF)\n * - It is less than or equal to SBCodepointMax (0x10FFFF).\n *\n * @param c\n *      The code point to check.\n * @return\n *      `true` if the code point is valid, `false` otherwise.\n */\n#define SBCodepointIsValid(c)       (!SBCodepointIsSurrogate(c) && (c) <= SBCodepointMax)\n\n/**\n * Returns the bidirectional type of a Unicode code point.\n *\n * @param codepoint\n *      The code point whose bidirectional type is returned.\n * @return\n *      The bidirectional type of the specified code point.\n */\nSB_PUBLIC SBBidiType SBCodepointGetBidiType(SBCodepoint codepoint);\n\n/**\n * Returns the general category of a Unicode code point.\n *\n * @param codepoint\n *      The code point whose general category is returned.\n * @return\n *      The general category of the specified code point.\n */\nSB_PUBLIC SBGeneralCategory SBCodepointGetGeneralCategory(SBCodepoint codepoint);\n\n/**\n * Returns the mirrored code point for a given Unicode code point.\n *\n * @param codepoint\n *      The code point whose mirrored counterpart is returned.\n * @return\n *      The mirrored code point if available, or 0 if no mirror exists.\n */\nSB_PUBLIC SBCodepoint SBCodepointGetMirror(SBCodepoint codepoint);\n\n/**\n * Returns the script associated with a Unicode code point.\n *\n * @param codepoint\n *      The code point whose script is returned.\n * @return\n *      The script of the specified code point.\n */\nSB_PUBLIC SBScript SBCodepointGetScript(SBCodepoint codepoint);\n\n/**\n * Decodes the next Unicode code point from a UTF-8 encoded buffer.\n *\n * @param buffer\n *      The buffer containing UTF-8 encoded code units.\n * @param length\n *      The length of the buffer.\n * @param index\n *      The index at which decoding starts. On output, it is updated to the start of the next code\n *      point.\n * @return\n *      The decoded code point, or `SBCodepointInvalid` if `index` is out of bounds.\n */\nSB_PUBLIC SBCodepoint SBCodepointDecodeNextFromUTF8(const SBUInt8 *buffer, SBUInteger length,\n    SBUInteger *index);\n\n/**\n * Decodes the previous Unicode code point from a UTF-8 encoded buffer.\n *\n * @param buffer\n *      The buffer containing UTF-8 encoded code units.\n * @param length\n *      The length of the buffer.\n * @param index\n *      The index before which decoding occurs. On output, it is updated to the start of the\n *      decoded code point.\n * @return\n *      The decoded code point, or `SBCodepointInvalid` if `index` is zero or out of bounds.\n */\nSB_PUBLIC SBCodepoint SBCodepointDecodePreviousFromUTF8(const SBUInt8 *buffer, SBUInteger length,\n    SBUInteger *index);\n\n/**\n * Decodes the next Unicode code point from a UTF-16 encoded buffer.\n *\n * @param buffer\n *      The buffer containing UTF-16 encoded code units.\n * @param length\n *      The length of the buffer.\n * @param index\n *      The index at which decoding starts. On output, it is updated to the start of the next code\n *      point.\n * @return\n *      The decoded code point, or `SBCodepointInvalid` if `index` is out of bounds.\n */\nSB_PUBLIC SBCodepoint SBCodepointDecodeNextFromUTF16(const SBUInt16 *buffer, SBUInteger length,\n    SBUInteger *index);\n\n/**\n * Decodes the previous Unicode code point from a UTF-16 encoded buffer.\n *\n * @param buffer\n *      The buffer containing UTF-16 encoded code units.\n * @param length\n *      The length of the buffer.\n * @param index\n *      The index before which decoding occurs. On output, it is updated to the start of the\n *      decoded code point.\n * @return\n *      The decoded code point, or `SBCodepointInvalid` if `index` is zero or out of bounds.\n */\nSB_PUBLIC SBCodepoint SBCodepointDecodePreviousFromUTF16(const SBUInt16 *buffer, SBUInteger length,\n    SBUInteger *index);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBCodepointSequence.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_CODEPOINT_SEQUENCE_H\n#define _SB_PUBLIC_CODEPOINT_SEQUENCE_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBCodepoint.h>\n\nSB_EXTERN_C_BEGIN\n\nenum {\n    SBStringEncodingUTF8 = 0,  /**< An 8-bit representation of Unicode code points. */\n    SBStringEncodingUTF16 = 1, /**< 16-bit UTF encoding in native endianness. */\n    SBStringEncodingUTF32 = 2  /**< 32-bit UTF encoding in native endianness. */\n};\ntypedef SBUInt32 SBStringEncoding;\n\ntypedef struct _SBCodepointSequence {\n    SBStringEncoding stringEncoding; /**< The encoding of the string. */\n    const void *stringBuffer;        /**< The source string containing the code units. */\n    SBUInteger stringLength;         /**< The length of the string in terms of code units. */\n} SBCodepointSequence;\n\n/**\n * Returns the code point before the given string index.\n *\n * @param codepointSequence\n *      The object holding the information of the string.\n * @param stringIndex\n *      The index of code unit before which to get the code point. On output, it is set to point to\n *      the first code unit of returned code point.\n * @return\n *      The code point before the given string index, or SBCodepointInvalid if stringIndex is equal \n *      to zero or larger than actual length of source string.\n */\nSB_PUBLIC SBCodepoint SBCodepointSequenceGetCodepointBefore(\n    const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);\n\n/**\n * Returns the code point at the given string index.\n *\n * @param codepointSequence\n *      The object holding the information of the string.\n * @param stringIndex\n *      The index of code unit at which to get the code point. On output, it is set to point to the\n *      first code unit of next code point.\n * @return\n *      The code point at the given string index, or SBCodepointInvalid if stringIndex is larger\n *      than or equal to actual length of source string.\n */\nSB_PUBLIC SBCodepoint SBCodepointSequenceGetCodepointAt(\n    const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBConfig.h",
    "content": "/*\n * Copyright (C) 2014-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* Suppress numerous warnings. */\n#pragma GCC system_header\n#pragma clang system_header\n\n#ifndef _SB_PUBLIC_CONFIG_H\n#define _SB_PUBLIC_CONFIG_H\n\n/* #define SB_CONFIG_DLL_EXPORT */\n/* #define SB_CONFIG_DLL_IMPORT */\n/* #define SB_CONFIG_LOG */\n/* #define SB_CONFIG_UNITY */\n/* #define SB_CONFIG_ALLOW_NON_ATOMIC_FALLBACK */\n\n/**\n * Disable scratch memory functionality of default allocator.\n * When defined, all scratch memory operations will return NULL/do nothing.\n */\n/* #define SB_CONFIG_DISABLE_SCRATCH_MEMORY */\n\n/**\n * Enables the optional text editing and analysis API, including support for inserting, removing,\n * and modifying code units, applying attributes, and querying logical, script, attribute, and\n * visual runs. These features perform incremental paragraph analysis internally.\n *\n * The API is considered experimental and may change based on production feedback.\n */\n/* #define SB_CONFIG_EXPERIMENTAL_TEXT_API */\n\n/**\n * Define the size of each scratch buffer in bytes.\n * Default is 8192 bytes (8KB) if not specified.\n */\n#ifndef SB_CONFIG_SCRATCH_BUFFER_SIZE\n#define SB_CONFIG_SCRATCH_BUFFER_SIZE 8192\n#endif\n\n/**\n * Define the number of scratch buffers in the pool.\n * Default is 3 buffers if not specified.\n */\n#ifndef SB_CONFIG_SCRATCH_POOL_SIZE\n#define SB_CONFIG_SCRATCH_POOL_SIZE 3\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBGeneralCategory.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_GENERAL_CATEGORY_H\n#define _SB_PUBLIC_GENERAL_CATEGORY_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Constants that specify the general category of a character.\n */\nenum {\n    SBGeneralCategoryNil = 0x00,\n\n    SBGeneralCategoryLU  = 0x01, /**< Letter: Uppercase Letter */\n    SBGeneralCategoryLL  = 0x02, /**< Letter: Lowercase Letter */\n    SBGeneralCategoryLT  = 0x03, /**< Letter: Titlecase Letter */\n    SBGeneralCategoryLM  = 0x04, /**< Letter: Modifier Letter */\n    SBGeneralCategoryLO  = 0x05, /**< Letter: Other Letter */\n\n    SBGeneralCategoryMN  = 0x06, /**< Mark: Nonspacing Mark */\n    SBGeneralCategoryMC  = 0x07, /**< Mark: Spacing Mark */\n    SBGeneralCategoryME  = 0x08, /**< Mark: Enclosing Mark */\n\n    SBGeneralCategoryND  = 0x09, /**< Number: Decimal Number */\n    SBGeneralCategoryNL  = 0x0A, /**< Number: Letter Number */\n    SBGeneralCategoryNO  = 0x0B, /**< Number: Other Number */\n\n    SBGeneralCategoryPC  = 0x0C, /**< Punctuation: Connector Punctuation */\n    SBGeneralCategoryPD  = 0x0D, /**< Punctuation: Dash Punctuation */\n    SBGeneralCategoryPS  = 0x0E, /**< Punctuation: Open Punctuation */\n    SBGeneralCategoryPE  = 0x0F, /**< Punctuation: Close Punctuation */\n    SBGeneralCategoryPI  = 0x10, /**< Punctuation: Initial Punctuation */\n    SBGeneralCategoryPF  = 0x11, /**< Punctuation: Final Punctuation */\n    SBGeneralCategoryPO  = 0x12, /**< Punctuation: Other Punctuation */\n\n    SBGeneralCategorySM  = 0x13, /**< Symbol: Math Symbol */\n    SBGeneralCategorySC  = 0x14, /**< Symbol: Currency Symbol */\n    SBGeneralCategorySK  = 0x15, /**< Symbol: Modifier Symbol */\n    SBGeneralCategorySO  = 0x16, /**< Symbol: Other Symbol */\n\n    SBGeneralCategoryZS  = 0x17, /**< Separator: Space Separator */\n    SBGeneralCategoryZL  = 0x18, /**< Separator: Line Separator */\n    SBGeneralCategoryZP  = 0x19, /**< Separator: Paragraph Separator */\n\n    SBGeneralCategoryCC  = 0x1A, /**< Other: Control */\n    SBGeneralCategoryCF  = 0x1B, /**< Other: Format */\n    SBGeneralCategoryCS  = 0x1C, /**< Other: Surrogate */\n    SBGeneralCategoryCO  = 0x1D, /**< Other: Private_Use */\n    SBGeneralCategoryCN  = 0x1E  /**< Other: Unassigned */\n};\n\n/**\n * A type to represent the general category of a character.\n */\ntypedef SBUInt8 SBGeneralCategory;\n\n/**\n * Checks whether specified general category is letter.\n */\n#define SBGeneralCategoryIsLetter(gc)       SBUInt8InRange(gc, SBGeneralCategoryLU, SBGeneralCategoryLO)\n\n/**\n * Checks whether specified general category is mark.\n */\n#define SBGeneralCategoryIsMark(gc)         SBUInt8InRange(gc, SBGeneralCategoryMN, SBGeneralCategoryME)\n\n/**\n * Checks whether specified general category is number.\n */\n#define SBGeneralCategoryIsNumber(gc)       SBUInt8InRange(gc, SBGeneralCategoryND, SBGeneralCategoryNO)\n\n/**\n * Checks whether specified general category is punctuation.\n */\n#define SBGeneralCategoryIsPunctuation(gc)  SBUInt8InRange(gc, SBGeneralCategoryPC, SBGeneralCategoryPO)\n\n/**\n * Checks whether specified general category is symbol.\n */\n#define SBGeneralCategoryIsSymbol(gc)       SBUInt8InRange(gc, SBGeneralCategorySM, SBGeneralCategorySO)\n\n/**\n * Checks whether specified general category is separator.\n */\n#define SBGeneralCategoryIsSeparator(gc)    SBUInt8InRange(gc, SBGeneralCategoryZS, SBGeneralCategoryZP)\n\n/**\n * Checks whether specified general category is other.\n */\n#define SBGeneralCategoryIsOther(gc)        SBUInt8InRange(gc, SBGeneralCategoryCC, SBGeneralCategoryCN)\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBLine.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_LINE_H\n#define _SB_PUBLIC_LINE_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBRun.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef const struct _SBLine *SBLineRef;\n\n/**\n * Returns the index to the first code unit of the line in source string.\n *\n * @param line\n *      The line whose offset is returned.\n * @return\n *      The offset of the line passed in.\n */\nSB_PUBLIC SBUInteger SBLineGetOffset(SBLineRef line);\n\n/**\n * Returns the number of code units coverting the length of the line.\n *\n * @param line\n *      The line whose length is returned.\n * @return\n *      The length of the line passed in.\n */\nSB_PUBLIC SBUInteger SBLineGetLength(SBLineRef line);\n\n/**\n * Returns the number of runs in the line.\n *\n * @param line\n *      The line whose run count is returned.\n * @return\n *      The number of runs in the line passed in.\n */\nSB_PUBLIC SBUInteger SBLineGetRunCount(SBLineRef line);\n\n/**\n * Returns a direct pointer to the run array, stored in the line.\n *\n * @param line\n *      The line from which to access the runs.\n * @return\n *      A valid pointer to an array of SBRun structures. \n */\nSB_PUBLIC const SBRun *SBLineGetRunsPtr(SBLineRef line);\n\n/**\n * Increments the reference count of a line object.\n *\n * @param line\n *      The line object whose reference count will be incremented.\n * @return\n *      The same line object passed in as the parameter.\n */\nSB_PUBLIC SBLineRef SBLineRetain(SBLineRef line);\n\n/**\n * Decrements the reference count of a line object. The object will be deallocated when its\n * reference count reaches zero.\n *\n * @param line\n *      The line object whose reference count will be decremented.\n */\nSB_PUBLIC void SBLineRelease(SBLineRef line);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBMirrorLocator.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_MIRROR_LOCATOR_H\n#define _SB_PUBLIC_MIRROR_LOCATOR_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBCodepoint.h>\n#include <SheenBidi/SBLine.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef struct _SBMirrorLocator *SBMirrorLocatorRef;\n\n/**\n * A structure containing the information about a code point having Bidi_Mirrored property.\n */\ntypedef struct _SBMirrorAgent {\n    SBUInteger index;      /**< The absolute index of the code point. */\n    SBCodepoint mirror;    /**< The mirrored code point. */\n    SBCodepoint codepoint; /**< The actual code point. */\n} SBMirrorAgent;\n\n/**\n * Creates a mirror locator object which can be used to find mirrors in a line.\n *\n * @return\n *      A reference to a mirror locator object.\n */\nSB_PUBLIC SBMirrorLocatorRef SBMirrorLocatorCreate(void);\n\n/**\n * Loads a line in the locator so that its mirror can be located.\n *\n * @param locator\n *      The locator in which the line will be loaded.\n * @param line\n *      The line which will be loaded in the locator.\n * @param stringBuffer\n *      The string buffer from which the line's algorithm was created.\n */\nSB_PUBLIC void SBMirrorLocatorLoadLine(SBMirrorLocatorRef locator, SBLineRef line,\n    const void *stringBuffer);\n\n/**\n * Returns the agent containing the information of current located mirror.\n *\n * @param locator\n *      The locator whose agent is returned.\n */\nSB_PUBLIC const SBMirrorAgent *SBMirrorLocatorGetAgent(SBMirrorLocatorRef locator);\n\n/**\n * Instructs the locator to find next mirror in the loaded line.\n *\n * @param locator\n *      The locator whom you want to instruct.\n * @return\n *      SBTrue if another mirror is available, SBFalse otherwise.\n * @note\n *      The locator will be reset after locating last mirror.\n */\nSB_PUBLIC SBBoolean SBMirrorLocatorMoveNext(SBMirrorLocatorRef locator);\n\n/**\n * Instructs the locator to reset itself so that mirrors of the loaded line can be obatained from\n * the beginning.\n *\n * @param locator\n *      The locator whom you want to reset.\n */\nSB_PUBLIC void SBMirrorLocatorReset(SBMirrorLocatorRef locator);\n\n/**\n * Increments the reference count of a mirror locator object.\n *\n * @param locator\n *      The mirror locator object whose reference count will be incremented.\n * @return\n *      The same mirror locator object passed in as the parameter.\n */\nSB_PUBLIC SBMirrorLocatorRef SBMirrorLocatorRetain(SBMirrorLocatorRef locator);\n\n/**\n * Decrements the reference count of a mirror locator object. The object will be deallocated when\n * its reference count reaches zero.\n *\n * @param locator\n *      The mirror locator object whose reference count will be decremented.\n */\nSB_PUBLIC void SBMirrorLocatorRelease(SBMirrorLocatorRef locator);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBParagraph.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_PARAGRAPH_H\n#define _SB_PUBLIC_PARAGRAPH_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBLine.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef const struct _SBParagraph *SBParagraphRef;\n\n/**\n * Returns the index to the first code unit of the paragraph in source string.\n *\n * @param paragraph\n *      The paragraph whose offset is returned.\n * @return\n *      The offset of the paragraph passed in.\n */\nSB_PUBLIC SBUInteger SBParagraphGetOffset(SBParagraphRef paragraph);\n\n/**\n * Returns the number of code units covering the length of the paragraph.\n *\n * @param paragraph\n *      The paragraph whose length is returned.\n * @return\n *      The length of the paragraph passed in.\n */\nSB_PUBLIC SBUInteger SBParagraphGetLength(SBParagraphRef paragraph);\n\n/**\n * Returns the base level of the paragraph.\n *\n * @param paragraph\n *      The paragraph whose base level is returned.\n * @return\n *      The base level of the paragraph passed in.\n */\nSB_PUBLIC SBLevel SBParagraphGetBaseLevel(SBParagraphRef paragraph);\n\n/**\n * Returns a direct pointer to the embedding levels, stored in the paragraph.\n *\n * @param paragraph\n *      The paragraph from which to access the embedding levels.\n * @return\n *      A valid pointer to an array of SBLevel structures.\n */\nSB_PUBLIC const SBLevel *SBParagraphGetLevelsPtr(SBParagraphRef paragraph);\n\n/**\n * Creates a line object of specified range by applying rules L1-L2 of Unicode Bidirectional\n * Algorithm.\n *\n * @param paragraph\n *      The paragraph that creates the line.\n * @param lineOffset\n *      The index to the first code unit of the line in source string. It should occur within the\n *      range of paragraph.\n * @param lineLength\n *      The number of code units covering the length of the line.\n * @return\n *      A reference to a line object if the call was successful, NULL otherwise.\n */\nSB_PUBLIC SBLineRef SBParagraphCreateLine(SBParagraphRef paragraph, SBUInteger lineOffset,\n    SBUInteger lineLength);\n\n/**\n * Increments the reference count of a paragraph object.\n *\n * @param paragraph\n *      The paragraph object whose reference count will be incremented.\n * @return\n *      The same paragraph object passed in as the parameter.\n */\nSB_PUBLIC SBParagraphRef SBParagraphRetain(SBParagraphRef paragraph);\n\n/**\n * Decrements the reference count of a paragraph object. The object will be deallocated when its\n * reference count reaches zero.\n *\n * @param paragraph\n *      The paragraph object whose reference count will be decremented.\n */\nSB_PUBLIC void SBParagraphRelease(SBParagraphRef paragraph);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBRun.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_RUN_H\n#define _SB_PUBLIC_RUN_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\n/**\n * A structure containing the information of a sequence of characters having the same embedding\n * level.\n */\ntypedef struct _SBRun {\n    SBUInteger offset; /**< The index to the first code unit of the run in source string. */\n    SBUInteger length; /**< The number of code units covering the length of the run. */\n    SBLevel level;     /**< The embedding level of the run. */\n} SBRun;\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBScript.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_SCRIPT_H\n#define _SB_PUBLIC_SCRIPT_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Constants that specify the script of a character.\n */\nenum {\n    SBScriptNil  = 0x00,\n\n    SBScriptZINH = 0x01,    /**< Inherited */\n    SBScriptZYYY = 0x02,    /**< Common */\n    SBScriptZZZZ = 0x03,    /**< Unknown */\n\n    /* Unicode 1.1  */\n    SBScriptARAB = 0x04,    /**< Arabic */\n    SBScriptARMN = 0x05,    /**< Armenian */\n    SBScriptBENG = 0x06,    /**< Bengali */\n    SBScriptBOPO = 0x07,    /**< Bopomofo */\n    SBScriptCYRL = 0x08,    /**< Cyrillic */\n    SBScriptDEVA = 0x09,    /**< Devanagari */\n    SBScriptGEOR = 0x0A,    /**< Georgian */\n    SBScriptGREK = 0x0B,    /**< Greek */\n    SBScriptGUJR = 0x0C,    /**< Gujarati */\n    SBScriptGURU = 0x0D,    /**< Gurmukhi */\n    SBScriptHANG = 0x0E,    /**< Hangul */\n    SBScriptHANI = 0x0F,    /**< Han */\n    SBScriptHEBR = 0x10,    /**< Hebrew */\n    SBScriptHIRA = 0x11,    /**< Hiragana */\n    SBScriptKANA = 0x12,    /**< Katakana */\n    SBScriptKNDA = 0x13,    /**< Kannada */\n    SBScriptLAOO = 0x14,    /**< Lao */\n    SBScriptLATN = 0x15,    /**< Latin */\n    SBScriptMLYM = 0x16,    /**< Malayalam */\n    SBScriptORYA = 0x17,    /**< Oriya */\n    SBScriptTAML = 0x18,    /**< Tamil */\n    SBScriptTELU = 0x19,    /**< Telugu */\n    SBScriptTHAI = 0x1A,    /**< Thai */\n\n    /* Unicode 2.0 */\n    SBScriptTIBT = 0x1B,    /**< Tibetan */\n\n    /* Unicode 3.0 */\n    SBScriptBRAI = 0x1C,    /**< Braille */\n    SBScriptCANS = 0x1D,    /**< Canadian_Aboriginal */\n    SBScriptCHER = 0x1E,    /**< Cherokee */\n    SBScriptETHI = 0x1F,    /**< Ethiopic */\n    SBScriptKHMR = 0x20,    /**< Khmer */\n    SBScriptMONG = 0x21,    /**< Mongolian */\n    SBScriptMYMR = 0x22,    /**< Myanmar */\n    SBScriptOGAM = 0x23,    /**< Ogham */\n    SBScriptRUNR = 0x24,    /**< Runic */\n    SBScriptSINH = 0x25,    /**< Sinhala */\n    SBScriptSYRC = 0x26,    /**< Syriac */\n    SBScriptTHAA = 0x27,    /**< Thaana */\n    SBScriptYIII = 0x28,    /**< Yi */\n\n    /* Unicode 3.1 */\n    SBScriptDSRT = 0x29,    /**< Deseret */\n    SBScriptGOTH = 0x2A,    /**< Gothic */\n    SBScriptITAL = 0x2B,    /**< Old_Italic */\n\n    /* Unicode 3.2 */\n    SBScriptBUHD = 0x2C,    /**< Buhid */\n    SBScriptHANO = 0x2D,    /**< Hanunoo */\n    SBScriptTAGB = 0x2E,    /**< Tagbanwa */\n    SBScriptTGLG = 0x2F,    /**< Tagalog */\n\n    /* Unicode 4.0 */\n    SBScriptCPRT = 0x30,    /**< Cypriot */\n    SBScriptLIMB = 0x31,    /**< Limbu */\n    SBScriptLINB = 0x32,    /**< Linear_B */\n    SBScriptOSMA = 0x33,    /**< Osmanya */\n    SBScriptSHAW = 0x34,    /**< Shavian */\n    SBScriptTALE = 0x35,    /**< Tai_Le */\n    SBScriptUGAR = 0x36,    /**< Ugaritic */\n\n    /* Unicode 4.1 */\n    SBScriptBUGI = 0x37,    /**< Buginese */\n    SBScriptCOPT = 0x38,    /**< Coptic */\n    SBScriptGLAG = 0x39,    /**< Glagolitic */\n    SBScriptKHAR = 0x3A,    /**< Kharoshthi */\n    SBScriptSYLO = 0x3B,    /**< Syloti_Nagri */\n    SBScriptTALU = 0x3C,    /**< New_Tai_Lue */\n    SBScriptTFNG = 0x3D,    /**< Tifinagh */\n    SBScriptXPEO = 0x3E,    /**< Old_Persian */\n\n    /* Unicode 5.0 */\n    SBScriptBALI = 0x3F,    /**< Balinese */\n    SBScriptNKOO = 0x40,    /**< Nko */\n    SBScriptPHAG = 0x41,    /**< Phags_Pa */\n    SBScriptPHNX = 0x42,    /**< Phoenician */\n    SBScriptXSUX = 0x43,    /**< Cuneiform */\n\n    /* Unicode 5.1 */\n    SBScriptCARI = 0x44,    /**< Carian */\n    SBScriptCHAM = 0x45,    /**< Cham */\n    SBScriptKALI = 0x46,    /**< Kayah_Li */\n    SBScriptLEPC = 0x47,    /**< Lepcha */\n    SBScriptLYCI = 0x48,    /**< Lycian */\n    SBScriptLYDI = 0x49,    /**< Lydian */\n    SBScriptOLCK = 0x4A,    /**< Ol_Chiki */\n    SBScriptRJNG = 0x4B,    /**< Rejang */\n    SBScriptSAUR = 0x4C,    /**< Saurashtra */\n    SBScriptSUND = 0x4D,    /**< Sundanese */\n    SBScriptVAII = 0x4E,    /**< Vai */\n\n    /* Unicode 5.2 */\n    SBScriptARMI = 0x4F,    /**< Imperial_Aramaic */\n    SBScriptAVST = 0x50,    /**< Avestan */\n    SBScriptBAMU = 0x51,    /**< Bamum */\n    SBScriptEGYP = 0x52,    /**< Egyptian_Hieroglyphs */\n    SBScriptJAVA = 0x53,    /**< Javanese */\n    SBScriptKTHI = 0x54,    /**< Kaithi */\n    SBScriptLANA = 0x55,    /**< Tai_Tham */\n    SBScriptLISU = 0x56,    /**< Lisu */\n    SBScriptMTEI = 0x57,    /**< Meetei_Mayek */\n    SBScriptORKH = 0x58,    /**< Old_Turkic */\n    SBScriptPHLI = 0x59,    /**< Inscriptional_Pahlavi */\n    SBScriptPRTI = 0x5A,    /**< Inscriptional_Parthian */\n    SBScriptSAMR = 0x5B,    /**< Samaritan */\n    SBScriptSARB = 0x5C,    /**< Old_South_Arabian */\n    SBScriptTAVT = 0x5D,    /**< Tai_Viet */\n\n    /* Unicode 6.0 */\n    SBScriptBATK = 0x5E,    /**< Batak */\n    SBScriptBRAH = 0x5F,    /**< Brahmi */\n    SBScriptMAND = 0x60,    /**< Mandaic */\n\n    /* Unicode 6.1 */\n    SBScriptCAKM = 0x61,    /**< Chakma */\n    SBScriptMERC = 0x62,    /**< Meroitic_Cursive */\n    SBScriptMERO = 0x63,    /**< Meroitic_Hieroglyphs */\n    SBScriptPLRD = 0x64,    /**< Miao */\n    SBScriptSHRD = 0x65,    /**< Sharada */\n    SBScriptSORA = 0x66,    /**< Sora_Sompeng */\n    SBScriptTAKR = 0x67,    /**< Takri */\n\n    /* Unicode 7.0 */\n    SBScriptAGHB = 0x68,    /**< Caucasian_Albanian */\n    SBScriptBASS = 0x69,    /**< Bassa_Vah */\n    SBScriptDUPL = 0x6A,    /**< Duployan */\n    SBScriptELBA = 0x6B,    /**< Elbasan */\n    SBScriptGRAN = 0x6C,    /**< Grantha */\n    SBScriptHMNG = 0x6D,    /**< Pahawh_Hmong */\n    SBScriptKHOJ = 0x6E,    /**< Khojki */\n    SBScriptLINA = 0x6F,    /**< Linear_A */\n    SBScriptMAHJ = 0x70,    /**< Mahajani */\n    SBScriptMANI = 0x71,    /**< Manichaean */\n    SBScriptMEND = 0x72,    /**< Mende_Kikakui */\n    SBScriptMODI = 0x73,    /**< Modi */\n    SBScriptMROO = 0x74,    /**< Mro */\n    SBScriptNARB = 0x75,    /**< Old_North_Arabian */\n    SBScriptNBAT = 0x76,    /**< Nabataean */\n    SBScriptPALM = 0x77,    /**< Palmyrene */\n    SBScriptPAUC = 0x78,    /**< Pau_Cin_Hau */\n    SBScriptPERM = 0x79,    /**< Old_Permic */\n    SBScriptPHLP = 0x7A,    /**< Psalter_Pahlavi */\n    SBScriptSIDD = 0x7B,    /**< Siddham */\n    SBScriptSIND = 0x7C,    /**< Khudawadi */\n    SBScriptTIRH = 0x7D,    /**< Tirhuta */\n    SBScriptWARA = 0x7E,    /**< Warang_Citi */\n\n    /* Unicode 8.0 */\n    SBScriptAHOM = 0x7F,    /**< Ahom */\n    SBScriptHATR = 0x80,    /**< Hatran */\n    SBScriptHLUW = 0x81,    /**< Anatolian_Hieroglyphs */\n    SBScriptHUNG = 0x82,    /**< Old_Hungarian */\n    SBScriptMULT = 0x83,    /**< Multani */\n    SBScriptSGNW = 0x84,    /**< SignWriting */\n\n    /* Unicode 9.0 */\n    SBScriptADLM = 0x85,    /**< Adlam */\n    SBScriptBHKS = 0x86,    /**< Bhaiksuki */\n    SBScriptMARC = 0x87,    /**< Marchen */\n    SBScriptNEWA = 0x88,    /**< Newa */\n    SBScriptOSGE = 0x89,    /**< Osage */\n    SBScriptTANG = 0x8A,    /**< Tangut */\n\n    /* Unicode 10.0 */\n    SBScriptGONM = 0x8B,    /**< Masaram_Gondi */\n    SBScriptNSHU = 0x8C,    /**< Nushu */\n    SBScriptSOYO = 0x8D,    /**< Soyombo */\n    SBScriptZANB = 0x8E,    /**< Zanabazar_Square */\n\n    /* Unicode 11.0 */\n    SBScriptDOGR = 0x8F,    /**< Dogra */\n    SBScriptGONG = 0x90,    /**< Gunjala_Gondi */\n    SBScriptMAKA = 0x91,    /**< Makasar */\n    SBScriptMEDF = 0x92,    /**< Medefaidrin */\n    SBScriptROHG = 0x93,    /**< Hanifi_Rohingya */\n    SBScriptSOGD = 0x94,    /**< Sogdian */\n    SBScriptSOGO = 0x95,    /**< Old_Sogdian */\n\n    /* Unicode 12.0 */\n    SBScriptELYM = 0x96,    /**< Elymaic */\n    SBScriptHMNP = 0x97,    /**< Nyiakeng_Puachue_Hmong */\n    SBScriptNAND = 0x98,    /**< Nandinagari */\n    SBScriptWCHO = 0x99,    /**< Wancho */\n\n    /* Unicode 13.0 */\n    SBScriptCHRS = 0x9A,    /**< Chorasmian */\n    SBScriptDIAK = 0x9B,    /**< Dives_Akuru */\n    SBScriptKITS = 0x9C,    /**< Khitan_Small_Script */\n    SBScriptYEZI = 0x9D,    /**< Yezidi */\n\n    /* Unicode 14.0 */\n    SBScriptCPMN = 0x9E,    /**< Cypro_Minoan */\n    SBScriptOUGR = 0x9F,    /**< Old_Uyghur */\n    SBScriptTNSA = 0xA0,    /**< Tangsa */\n    SBScriptTOTO = 0xA1,    /**< Toto */\n    SBScriptVITH = 0xA2,    /**< Vithkuqi */\n\n    /* Unicode 15.1 */\n    SBScriptKAWI = 0xA3,    /**< Kawi */\n    SBScriptNAGM = 0xA4,    /**< Nag_Mundari */\n\n    /* Unicode 16.0 */\n    SBScriptGARA = 0xA5,    /**< Garay */\n    SBScriptGUKH = 0xA6,    /**< Gurung_Khema */\n    SBScriptKRAI = 0xA7,    /**< Kirat_Rai */\n    SBScriptONAO = 0xA8,    /**< Ol_Onal */\n    SBScriptSUNU = 0xA9,    /**< Sunuwar */\n    SBScriptTODR = 0xAA,    /**< Todhri */\n    SBScriptTUTG = 0xAB,    /**< Tulu_Tigalari */\n\n    /* Unicode 17.0 */\n    SBScriptBERF = 0xAC,    /**< Beria_Erfe */\n    SBScriptSIDT = 0xAD,    /**< Sidetic */\n    SBScriptTAYO = 0xAE,    /**< Tai_Yo */\n    SBScriptTOLS = 0xAF     /**< Tolong_Siki */\n};\n\n/**\n * A type to represent the script of a character.\n */\ntypedef SBUInt8 SBScript;\n\n/**\n * Returns the OpenType tag of a script as UInt32 in big endian byte order. The association between\n * Unicode Script property and OpenType script tags is taken from the specification:\n * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags.\n *\n * If more than one tag is associated with a script, then the latest one is retured. For example,\n * Devanagari script has two tags, `deva` and `dev2`. So in this case, `dev2` will be returned.\n *\n * If no tag is associated with a script, then `DFLT` is returned.\n *\n * @param script\n *      The script whose OpenType tag is returned.\n * @return\n *      The OpenType tag of specified script as UInt32 in big endian byte order.\n */\nSB_DEPRECATED\nSB_PUBLIC SBUInt32 SBScriptGetOpenTypeTag(SBScript script);\n\n/**\n * Returns the 4-letter Unicode Script abbreviation tag for a given SBScript value.\n *\n * The tag is returned as a UInt32 value in big-endian byte order (e.g., 'Arab' is 0x41726162),\n * suitable for use in shaping engines and script tagging.\n *\n * The tag is based on the Unicode Script property aliases as defined in PropertyValueAliases.txt,\n * section: \"sc\" (Script).\n *\n * @param script\n *      The SBScript enum value.\n * @return\n *      A big-endian UInt32 representing the 4-letter script tag, or 0 if the script has no\n *      associated tag.\n */\nSB_PUBLIC SBUInt32 SBScriptGetUnicodeTag(SBScript script);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBScriptLocator.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_SCRIPT_LOCATOR_H\n#define _SB_PUBLIC_SCRIPT_LOCATOR_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBScript.h>\n\nSB_EXTERN_C_BEGIN\n\ntypedef struct _SBScriptLocator *SBScriptLocatorRef;\n\n/**\n * A structure containing the information about a run of code points having same script.\n */\ntypedef struct _SBScriptAgent {\n    SBUInteger offset; /**< The index to the first code unit of the run in source string. */\n    SBUInteger length; /**< The number of code units covering the length of the run. */\n    SBScript script;   /**< The script of the run. */\n} SBScriptAgent;\n\n/**\n * Creates a script locator object which can be used to find script runs in a string.\n *\n * @return\n *      A reference to a script locator object.\n */\nSB_PUBLIC SBScriptLocatorRef SBScriptLocatorCreate(void);\n\n/**\n * Loads a code point sequence in the locator so that its script runs can be located.\n *\n * @param locator\n *      The locator in which the code point sequence will be loaded.\n * @param codepointSequence\n *      The code point sequence which will be loaded in the locator.\n */\nSB_PUBLIC void SBScriptLocatorLoadCodepoints(SBScriptLocatorRef locator,\n    const SBCodepointSequence *codepointSequence);\n\n/**\n * Returns the agent containing the information of current located script run.\n *\n * @param locator\n *      The locator whose agent is returned.\n */\nSB_PUBLIC const SBScriptAgent *SBScriptLocatorGetAgent(SBScriptLocatorRef locator);\n\n/**\n * Instructs the locator to find next script run in the loaded code point sequence.\n *\n * @param locator\n *      The locator whom you want to instruct.\n * @return\n *      SBTrue if another script run is available, SBFalse otherwise.\n * @note\n *      The locator will be reset after locating last script run.\n */\nSB_PUBLIC SBBoolean SBScriptLocatorMoveNext(SBScriptLocatorRef locator);\n\n/**\n * Instructs the locator to reset itself so that script runs of the loaded line can be obatained\n * from the beginning.\n *\n * @param locator\n *      The locator whom you want to reset.\n */\nSB_PUBLIC void SBScriptLocatorReset(SBScriptLocatorRef locator);\n\n/**\n * Increments the reference count of a script locator object.\n *\n * @param locator\n *      The script locator object whose reference count will be incremented.\n * @return\n *      The same script locator object passed in as the parameter.\n */\nSB_PUBLIC SBScriptLocatorRef SBScriptLocatorRetain(SBScriptLocatorRef locator);\n\n/**\n * Decrements the reference count of a script locator object. The object will be deallocated when\n * its reference count reaches zero.\n *\n * @param locator\n *      The script locator object whose reference count will be decremented.\n */\nSB_PUBLIC void SBScriptLocatorRelease(SBScriptLocatorRef locator);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBText.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_TEXT_H\n#define _SB_PUBLIC_TEXT_H\n\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBTextConfig.h>\n#include <SheenBidi/SBTextIterators.h>\n#include <SheenBidi/SBTextType.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Creates an immutable text object from raw code units and configuration.\n *\n * The text object will analyze the content for bidirectional properties, script identification, and\n * paragraph boundaries upon creation.\n *\n * @param string\n *      Pointer to code units in the specified encoding.\n * @param length\n *      Number of code units in string.\n * @param encoding\n *      String encoding (UTF-8, UTF-16, or UTF-32).\n * @param config\n *      Non-NULL configuration that supplies the attribute registry and defaults.\n * @return\n *      A reference to a text object if the call was successful, `NULL` otherwise.\n */\nSB_PUBLIC SBTextRef SBTextCreate(const void *string, SBUInteger length, SBStringEncoding encoding,\n    SBTextConfigRef config);\n\n/**\n * Creates a new immutable text object that is an exact copy of the source text.\n *\n * The copy contains all code units, bidirectional properties, script information, paragraph\n * analysis, and attributes from the source.\n *\n * @param text\n *      Source text object to copy.\n * @return\n *      New immutable copy, or `NULL` on failure.\n */\nSB_PUBLIC SBTextRef SBTextCreateCopy(SBTextRef text);\n\n/**\n * Creates a new mutable text object that is an exact copy of the source text.\n *\n * The copy can be modified using the mutable text interface while the original remains unchanged.\n *\n * @param text\n *      Source text object to copy (can be immutable or mutable).\n * @return\n *      New mutable text object with the same content and properties as the source.\n */\nSB_PUBLIC SBMutableTextRef SBTextCreateMutableCopy(SBTextRef text);\n\n/**\n * Returns the encoding specified at text object creation.\n *\n * This encoding remains constant for the lifetime of the text object.\n *\n * @param text\n *      Text object.\n * @return\n *      String encoding used by this text object.\n */\nSB_PUBLIC SBStringEncoding SBTextGetEncoding(SBTextRef text);\n\n/**\n * Returns a borrowed reference to the attribute registry associated with the text object.\n *\n * The registry defines the valid attribute IDs and their value management callbacks.\n * \n * @param text\n *      Text object.\n * @return\n *      Attribute registry (borrowed; do not release).\n */\nSB_PUBLIC SBAttributeRegistryRef SBTextGetAttributeRegistry(SBTextRef text);\n\n/**\n * Returns the number of code units in the text object.\n * \n * @param text\n *      Text object.\n * @return\n *      Number of code units in the text.\n */\nSB_PUBLIC SBUInteger SBTextGetLength(SBTextRef text);\n\n/**\n * Copies code units from the text into a caller-provided buffer.\n *\n * The buffer must be large enough to hold the requested number of code units in the text's encoding\n * format.\n *\n * @param text\n *      Text object.\n * @param index\n *      Start index (in code units).\n * @param length\n *      Number of code units to copy.\n * @param buffer\n *      Output buffer (must be large enough for `length` code units).\n *\n * @warning\n *      Behavior is undefined if buffer is too small or range is invalid.\n */\nSB_PUBLIC void SBTextGetCodeUnits(SBTextRef text, SBUInteger index, SBUInteger length,\n    void *buffer);\n\n/**\n * Copies bidirectional types for a code-unit range.\n *\n * @param text\n *      Text object.\n * @param index\n *      Start index (in code units).\n * @param length\n *      Number of code units to copy bidi types for.\n * @param buffer\n *      Output array of `SBBidiType` with `length` entries.\n *\n * @warning\n *      Behavior is undefined if buffer is too small, range is invalid, or text is currently being\n *      edited.\n */\nSB_PUBLIC void SBTextGetBidiTypes(SBTextRef text, SBUInteger index, SBUInteger length,\n    SBBidiType *buffer);\n\n/**\n * Copies script identifications for a code-unit range.\n * \n * @param text\n *      Text object.\n * @param index\n *      Start index (in code units).\n * @param length\n *      Number of code units to copy the scripts for.\n * @param buffer\n *      Output array of `SBScript` with `length` entries.\n *\n * @warning\n *      Behavior is undefined if buffer is too small, range is invalid, or text is currently being\n *      edited.\n */\nSB_PUBLIC void SBTextGetScripts(SBTextRef text, SBUInteger index, SBUInteger length,\n    SBScript *buffer);\n\n/**\n * Copies resolved bidirectional levels for a code-unit range.\n * \n * @param text\n *      Text object.\n * @param index\n *      Start index (in code units).\n * @param length\n *      Number of code units to copy the bidirectional levels for.\n * @param buffer\n *      Output array of SBLevel with `length` entries.\n *\n * @warning\n *      Behavior is undefined if buffer is too small, range is invalid, or text is currently being\n *      edited.\n */\nSB_PUBLIC void SBTextGetResolvedLevels(SBTextRef text, SBUInteger index, SBUInteger length,\n    SBLevel *buffer);\n\n/**\n * Retrieves information for the paragraph containing a specific code unit.\n * \n * @param text\n *      Text object.\n * @param index\n *      Code-unit index whose paragraph is queried.\n * @param paragraphInfo\n *      Output pointer to `SBParagraphInfo` to receive data.\n *\n * @warning\n *      Index must be valid and text must not be undergoing editing.\n */\nSB_PUBLIC void SBTextGetCodeUnitParagraphInfo(SBTextRef text, SBUInteger index,\n    SBParagraphInfo *paragraphInfo);\n\n/**\n * Creates a new paragraph iterator that can traverse all paragraphs in the text object.\n *\n * The iterator starts before the first paragraph and must be advanced with MoveNext().\n * \n * @param text\n *      Text object.\n * @return\n *      Paragraph iterator on success, `NULL` on failure.\n */\nSB_PUBLIC SBParagraphIteratorRef SBTextCreateParagraphIterator(SBTextRef text);\n\n/**\n * Creates a new logical run iterator that can traverse all bidirectional level runs in logical\n * order.\n *\n * Logical runs represent contiguous sequences of text with the same resolved bidirectional level.\n * \n * @param text\n *      Text object.\n * @return\n *      Logical run iterator on success, `NULL` on failure.\n */\nSB_PUBLIC SBLogicalRunIteratorRef SBTextCreateLogicalRunIterator(SBTextRef text);\n\n/**\n * Creates a new script run iterator that can traverse all script runs in the text.\n *\n * Script runs represent contiguous sequences of text with the same Unicode script property.\n * \n * @param text\n *      Text object.\n * @return\n *      Script run iterator on success, `NULL` on failure.\n */\nSB_PUBLIC SBScriptRunIteratorRef SBTextCreateScriptRunIterator(SBTextRef text);\n\n/**\n * Creates a new attribute run iterator that can traverse all attribute runs in the text.\n *\n * Initially, the iterator has no filter applied and will return all attribute runs. Use the Setup\n * functions to apply filtering by attribute ID or group/scope.\n * \n * @param text\n *      Text object.\n * @return\n *      Attribute iterator on success, `NULL` on failure.\n */\nSB_PUBLIC SBAttributeRunIteratorRef SBTextCreateAttributeRunIterator(SBTextRef text);\n\n/**\n * Creates a new visual run iterator that can traverse bidirectional runs in visual order for a\n * specific line range.\n *\n * Visual runs represent text as it should appear on screen after bidirectional reordering.\n * \n * @param text\n *      Text object.\n * @param index \n *      Start index of the line (in code units).\n * @param length\n *      Length of the line (in code units).\n * @return\n *      Visual run iterator on success, `NULL` on failure.\n */\nSB_PUBLIC SBVisualRunIteratorRef SBTextCreateVisualRunIterator(SBTextRef text, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Increments the reference count of a text object.\n * \n * @param text\n *      The text object whose reference count will be incremented.\n * @return\n *      The same text object passed in as the parameter.\n */\nSB_PUBLIC SBTextRef SBTextRetain(SBTextRef text);\n\n/**\n * Decrements the reference count of a text object. The object will be deallocated when its\n * reference count reaches zero.\n *\n * @param text\n *      The text object whose reference count will be decremented.\n */\nSB_PUBLIC void SBTextRelease(SBTextRef text);\n\n\n/* ----------------------------------\n * Mutable Text\n * ---------------------------------- */\n\n/**\n * Creates a new mutable text object that starts empty but can be modified through the mutable text\n * interface. The encoding and attribute registry are fixed at creation.\n * \n * @param encoding\n *      Target encoding for the new text (UTF-8/16/32).\n * @param config\n *      Non-NULL configuration with registry and defaults.\n * @return\n *      A reference to a mutable text object if the call was successful, `NULL` otherwise.\n */\nSB_PUBLIC SBMutableTextRef SBTextCreateMutable(SBStringEncoding encoding, SBTextConfigRef config);\n\n/**\n * Signals the start of a batch of editing operations. While in editing mode, text analysis\n * (bidirectional processing, script identification) is deferred until SBTextEndEditing() is called.\n * This improves performance when making multiple sequential modifications.\n * \n * @param text\n *      Mutable text object.\n */\nSB_PUBLIC void SBTextBeginEditing(SBMutableTextRef text);\n\n/**\n * Signals the end of a batch editing session and triggers text analysis for all modified\n * paragraphs. This includes bidirectional analysis, script identification, and paragraph boundary\n * detection.\n * \n * @param text\n *      Mutable text object.\n */\nSB_PUBLIC void SBTextEndEditing(SBMutableTextRef text);\n\n/**\n * Adds new code units to the end of the text object. If the text is not in editing mode, analysis\n * is performed immediately on the new content.\n * \n * @param text\n *      Mutable text object.\n * @param codeUnitBuffer\n *      Pointer to code units in the text's encoding.\n * @param codeUnitCount\n *      Number of code units to append.\n */\nSB_PUBLIC void SBTextAppendCodeUnits(SBMutableTextRef text, const void *codeUnitBuffer,\n    SBUInteger codeUnitCount);\n\n/**\n * Inserts new code units at the specified position in the text. Existing content at and after the\n * insertion point is shifted right. If the text is not in editing mode, analysis is performed\n * immediately.\n * \n * @param text\n *      Mutable text object.\n * @param index\n *      Insertion index (in code units).\n * @param codeUnitBuffer\n *      Pointer to code units in the text's encoding.\n * @param codeUnitCount\n *      Number of code units to insert.\n *\n * @warning\n *      The index must be within the range [0, current length].\n *      The buffer must contain valid code units in the text's encoding format.\n */\nSB_PUBLIC void SBTextInsertCodeUnits(SBMutableTextRef text, SBUInteger index,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount);\n\n/**\n * Removes a contiguous range of code units from the text. Content after the deletion range is\n * shifted left. If the text is not in editing mode, analysis is performed immediately.\n *\n * @param text\n *      Mutable text object.\n * @param index\n *      Start index of the range to delete (in code units).\n * @param length\n *      Number of code units to delete.\n *\n * @warning\n *      The deletion range [index, index+length) must be within the current text bounds.\n */\nSB_PUBLIC void SBTextDeleteCodeUnits(SBMutableTextRef text, SBUInteger index, SBUInteger length);\n\n/**\n * Completely replaces the current text content with the new code units. This is equivalent to\n * deleting all existing content and then inserting the new content at position 0.\n * \n * @param text\n *      Mutable text object.\n * @param codeUnitBuffer\n *      Pointer to code units in the text's encoding.\n * @param codeUnitCount\n *      Number of code units in codeUnitBuffer.\n *\n * @warning\n *      All existing content and attributes are removed.\n *      The buffer must contain valid code units in the text's encoding format.\n */\nSB_PUBLIC void SBTextSetCodeUnits(SBMutableTextRef text, const void *codeUnitBuffer,\n    SBUInteger codeUnitCount);\n\n/**\n * Replaces a contiguous range of existing code units with new content. If the text is not in\n * editing mode, analysis is performed immediately.\n * \n * @param text\n *      Mutable text object.\n * @param index\n *      Start index of the range to replace (in code units).\n * @param length\n *      Length of the range to replace (in code units).\n * @param codeUnitBuffer\n *      Pointer to replacement code units in the text's encoding.\n * @param codeUnitCount\n *      Number of replacement code units.\n *\n * @warning\n *      The replacement range [index, index+length) must be within the current text bounds.\n *      The buffer must contain valid code units in the text's encoding format.\n */\nSB_PUBLIC void SBTextReplaceCodeUnits(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount);\n\n/**\n * Applies the specified attribute with the given value to the range of code units. If the attribute\n * already exists in parts of the range, those values are replaced. The attribute value is managed\n * according to the callbacks defined in the attribute registry.\n * \n * @param text\n *      Mutable text object.\n * @param index\n *      Start index of the range (in code units).\n * @param length\n *      Length of the range (in code units).\n * @param attributeID\n *      ID of the attribute to set.\n * @param attributeValue\n *      Value pointer to associate; retained via registry callbacks if applicable.\n * @return\n *      `SBTrue` on success, `SBFalse` on failure.\n *\n * @warning\n *      The range must be within the current text bounds.\n *      The attribute ID must be registered in the text's attribute registry.\n *      The attribute value must be compatible with the attribute's value type as defined in the\n *      registry.\n */\nSB_PUBLIC void SBTextSetAttribute(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    SBAttributeID attributeID, const void *attributeValue);\n\n/**\n * Removes the specified attribute from the given range of code units. If the attribute is not\n * present in the range, this operation has no effect.\n *\n * @param text\n *      Mutable text object.\n * @param index\n *      Start index of the range (in code units).\n * @param length\n *      Length of the range (in code units).\n * @param attributeID\n *      ID of the attribute to remove.\n *\n * @warning\n *      The range must be within the current text bounds.\n *      The attribute ID must be registered in the text's attribute registry.\n */\nSB_PUBLIC void SBTextRemoveAttribute(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    SBAttributeID attributeID);\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBTextConfig.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_TEXT_CONFIG_H\n#define _SB_PUBLIC_TEXT_CONFIG_H\n\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Opaque reference to a configuration object required for text creation.\n */\ntypedef struct _SBTextConfig *SBTextConfigRef;\n\n/**\n * Creates an empty text config instance.\n * \n * @return\n *      A reference to the text config instance, or `NULL` on failure.\n * @note\n *      Must be populated with an attribute registry before text creation.\n */\nSB_PUBLIC SBTextConfigRef SBTextConfigCreate(void);\n\n/**\n * Sets the attribute registry used by any text created with this config.\n * \n * @param config\n *      The text config object.\n * @param attributeRegistry\n *      Attribute registry reference; the text config retains it.\n */\nSB_PUBLIC void SBTextConfigSetAttributeRegistry(SBTextConfigRef config,\n    SBAttributeRegistryRef attributeRegistry);\n\n/**\n * Sets the base paragraph level policy for newly created texts.\n * \n * @param config\n *      The text config object.\n * @param baseLevel\n *      `SBLevelDefaultLTR`, `SBLevelDefaultRTL`, or a concrete level.\n */\nSB_PUBLIC void SBTextConfigSetBaseLevel(SBTextConfigRef config, SBLevel baseLevel);\n\nSB_PUBLIC SBTextConfigRef SBTextConfigRetain(SBTextConfigRef config);\n\nSB_PUBLIC void SBTextConfigRelease(SBTextConfigRef config);\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBTextIterators.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_TEXT_ITERATORS_H\n#define _SB_PUBLIC_TEXT_ITERATORS_H\n\n#include <SheenBidi/SBAttributeList.h>\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBTextType.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/* ----------------------------------\n * Paragraph Iterator\n * ---------------------------------- */\n\n/**\n * Opaque reference to a paragraph iterator.\n *\n * The iterator retains its parent `SBText` for its lifetime and must be released with\n * SBParagraphIteratorRelease() when no longer needed.\n *\n * @warning\n *      The parent text must not be modified during iteration. If the text is modified, the iterator\n *      behavior becomes undefined and should be reset before further use.\n */\ntypedef struct _SBParagraphIterator *SBParagraphIteratorRef;\n\n/**\n * Metadata describing a paragraph.\n */\ntypedef struct _SBParagraphInfo {\n    SBUInteger index;  /**< Start index of the paragraph in code units. */\n    SBUInteger length; /**< Length of the paragraph in code units. */\n    SBLevel baseLevel; /**< Base level of the paragraph. */\n} SBParagraphInfo;\n\n/**\n * Returns the parent text retained by the iterator.\n * \n * @param iterator\n *      Paragraph iterator.\n * @return\n *      Text associated with the iterator (borrowed).\n */\nSB_PUBLIC SBTextRef SBParagraphIteratorGetText(SBParagraphIteratorRef iterator);\n\n/**\n * Resets iteration to the specified code-unit range.\n * \n * The range is automatically normalized to fit within the text bounds. If the specified range\n * extends beyond the text length, it is clamped to the valid range.\n * \n * @param iterator\n *      Paragraph iterator.\n * @param index\n *      Start index of the iteration window (in code units).\n * @param length\n *      Length of the iteration window (in code units).\n */\nSB_PUBLIC void SBParagraphIteratorReset(SBParagraphIteratorRef iterator, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Returns a pointer to the current paragraph information owned by the iterator.\n * \n * @param iterator\n *      Paragraph iterator.\n * @return\n *      Pointer to `SBParagraphInfo` owned by the iterator.\n *\n * @note\n *      This function always returns the same pointer address for a given iterator instance. Only\n *      the content of the structure is updated with each call to MoveNext.\n * @warning\n *      The client should never modify the returned structure. The client can call this function\n *      once and keep the reference, reading from it after each MoveNext call.\n */\nSB_PUBLIC const SBParagraphInfo *SBParagraphIteratorGetCurrent(SBParagraphIteratorRef iterator);\n\n/**\n * Advances to the next paragraph intersecting the window.\n *\n * When the end of the iteration range is reached, subsequent calls return `SBFals`e and the current\n * element becomes invalid.\n *\n * @param iterator\n *      Paragraph iterator.\n * @return\n *      `SBTrue` if advanced to a valid element; `SBFalse` if end reached.\n *\n * @warning\n *      The parent text must not be modified during iteration. If modification occurs, reset the\n *      iterator before continuing.\n */\nSB_PUBLIC SBBoolean SBParagraphIteratorMoveNext(SBParagraphIteratorRef iterator);\n\n/**\n * Increases the reference count of the iterator. Each call to retain must be balanced with a call\n * to release.\n *\n * @param iterator\n *      The paragraph iterator to retain.\n * @return\n *      The same iterator object after retention.\n */\nSB_PUBLIC SBParagraphIteratorRef SBParagraphIteratorRetain(SBParagraphIteratorRef iterator);\n\n/**\n * Decreases the reference count of the iterator. When the reference count reaches zero, the\n * iterator frees its internal storage and releases the retained text.\n *\n * @param iterator\n *      The iterator to release.\n */\nSB_PUBLIC void SBParagraphIteratorRelease(SBParagraphIteratorRef iterator);\n\n/* ----------------------------------\n * Logical Run Iterator\n * ---------------------------------- */\n\n/**\n * Opaque reference to a level run iterator (logical order).\n *\n * Iterates over runs of uniform bidirectional embedding level in logical order. The iterator\n * retains its parent `SBText` and must be released when no longer needed.\n *\n * @warning\n *      The parent text must not be modified during iteration. If the text is modified, the iterator\n *      behavior becomes undefined and should be reset before further use. Multiple instances of\n *      this iterator type can be used concurrently on the same text as long as the text is not\n *      being modified.\n */\ntypedef struct _SBLogicalRunIterator *SBLogicalRunIteratorRef;\n\n/**\n * A run of uniform resolved bidi level in logical order.\n */\ntypedef struct _SBLogicalRun {\n    SBUInteger index;  /**< Start index of the run in code units. */\n    SBUInteger length; /**< Length of the run in code units. */\n    SBLevel level;     /**< Resolved bidi level of the run. */\n} SBLogicalRun;\n\n/**\n * Returns the parent text retained by the iterator.\n * \n * @param iterator\n *      Logical run iterator.\n * @return\n *      Text associated with the iterator (borrowed).\n */\nSB_PUBLIC SBTextRef SBLogicalRunIteratorGetText(SBLogicalRunIteratorRef iterator);\n\n/**\n * Resets iteration to the specified code-unit range.\n *\n * The range is automatically normalized to fit within the text bounds. If the specified range\n * extends beyond the text length, it is clamped to the valid range.\n *\n * @param iterator\n *      Logical run iterator.\n * @param index\n *      Start index of the iteration window (in code units).\n * @param length\n *      Length of the iteration window (in code units).\n */\nSB_PUBLIC void SBLogicalRunIteratorReset(SBLogicalRunIteratorRef iterator, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Returns a pointer to the current logical run information owned by the iterator.\n * \n * @param iterator\n *      Logical run iterator.\n * @return\n *      Pointer to `SBLogicalRun` owned by the iterator.\n *\n * @note\n *      This function always returns the same pointer address for a given iterator instance. Only\n *      the content of the structure is updated with each call to MoveNext.\n * @warning\n *      The client should never modify the returned structure. The client can call this function\n *      once and keep the reference, reading from it after each MoveNext call.\n */\nSB_PUBLIC const SBLogicalRun *SBLogicalRunIteratorGetCurrent(SBLogicalRunIteratorRef iterator);\n\n/**\n * Advances to the next logical run.\n *\n * When the end of the iteration range is reached, subsequent calls return `SBFalse` and the current\n * element becomes invalid.\n * \n * @param iterator\n *      Logical run iterator.\n * @return\n *      `SBTrue` if advanced to a valid element; `SBFalse` if end reached.\n *\n * @warning\n *      The parent text must not be modified during iteration. If modification occurs, reset the\n *      iterator before continuing.\n */\nSB_PUBLIC SBBoolean SBLogicalRunIteratorMoveNext(SBLogicalRunIteratorRef iterator);\n\n/**\n * Increases the reference count of the iterator. Each call to retain must be balanced with a call\n * to release.\n *\n * @param iterator\n *      The logical run iterator to retain.\n * @return\n *      The same iterator object after retention.\n */\nSB_PUBLIC SBLogicalRunIteratorRef SBLogicalRunIteratorRetain(SBLogicalRunIteratorRef iterator);\n\n/**\n * Decreases the reference count of the iterator. When the reference count reaches zero, the\n * iterator frees its internal storage and releases the retained text.\n *\n * @param iterator\n *      The logical run iterator to release.\n */\nSB_PUBLIC void SBLogicalRunIteratorRelease(SBLogicalRunIteratorRef iterator);\n\n/* ----------------------------------\n * Script Run Iterator\n * ---------------------------------- */\n\n/**\n * Opaque reference to a script run iterator.\n *\n * Iterates over runs of uniform Unicode script property. The iterator retains its parent `SBText`\n * and must be released when no longer needed.\n *\n * @warning\n *      The parent text must not be modified during iteration. If the text is modified, the iterator\n *      behavior becomes undefined and should be reset before further use. Multiple instances of\n *      this iterator type can be used concurrently on the same text as long as the text is not\n *      being modified.\n */\ntypedef struct _SBScriptRunIterator *SBScriptRunIteratorRef;\n\n/**\n * A run of uniform Unicode script property.\n */\ntypedef struct _SBScriptRun {\n    SBUInteger index;  /**< Start index of the run in code units. */\n    SBUInteger length; /**< Length of the run in code units. */\n    SBScript script;   /**< Script property value for the run. */\n} SBScriptRun;\n\n/**\n * Returns the parent text retained by the iterator.\n * \n * @param iterator\n *      Script run iterator.\n * @return\n *      Text associated with the iterator (borrowed).\n */\nSB_PUBLIC SBTextRef SBScriptRunIteratorGetText(SBScriptRunIteratorRef iterator);\n\n/**\n * Resets iteration to the specified code-unit range.\n *\n * The range is automatically normalized to fit within the text bounds. If the specified range\n * extends beyond the text length, it is clamped to the valid range.\n * \n * @param iterator\n *      Script run iterator.\n * @param index\n *      Start index of the iteration window (in code units).\n * @param length\n *      Length of the iteration window (in code units).\n */\nSB_PUBLIC void SBScriptRunIteratorReset(SBScriptRunIteratorRef iterator, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Returns a pointer to the current script run information owned by the iterator. The pointer\n * remains valid until the next call to MoveNext or Reset.\n * \n * @param iterator\n *      Script run iterator.\n * @return\n *      Pointer to `SBScriptRun` owned by the iterator.\n *\n * @note\n *      This function always returns the same pointer address for a given iterator instance. Only\n *      the content of the structure is updated with each call to MoveNext.\n * @warning\n *      The client should never modify the returned structure. The client can call this function\n *      once and keep the reference, reading from it after each MoveNext call.\n */\nSB_PUBLIC const SBScriptRun *SBScriptRunIteratorGetCurrent(SBScriptRunIteratorRef iterator);\n\n/**\n * Advances to the next script run.\n *\n * When the end of the iteration range is reached, subsequent calls return `SBFalse` and the current\n * element becomes invalid.\n *\n * @param iterator\n *      Script run iterator.\n * @return\n *      `SBTrue` if advanced to a valid element; `SBFalse` if end reached.\n *\n * @warning\n *      The parent text must not be modified during iteration. If modification occurs, reset the\n *      iterator before continuing.\n */\nSB_PUBLIC SBBoolean SBScriptRunIteratorMoveNext(SBScriptRunIteratorRef iterator);\n\n/**\n * Increases the reference count of the iterator. Each call to retain must be balanced with a call\n * to release.\n *\n * @param iterator\n *      The script run iterator to retain.\n * @return\n *      The same iterator object after retention.\n */\nSB_PUBLIC SBScriptRunIteratorRef SBScriptRunIteratorRetain(SBScriptRunIteratorRef iterator);\n\n/**\n * Decreases the reference count of the iterator. When the reference count reaches zero, the\n * iterator frees its internal storage and releases the retained text.\n *\n * @param iterator\n *      The iterator to release.\n */\nSB_PUBLIC void SBScriptRunIteratorRelease(SBScriptRunIteratorRef iterator);\n\n/* ----------------------------------\n * Attribute Run Iterator\n * ---------------------------------- */\n\n/**\n * Opaque reference to an attribute run iterator.\n *\n * Iterates over runs of text with consistent attribute properties. Supports filtering by attribute\n * ID or attribute group/scope. The iterator retains its parent `SBText` and must be released when\n * no longer needed.\n *\n * @warning\n *      The parent text must not be modified during iteration. If the text is modified, the iterator\n *      behavior becomes undefined and should be reset before further use. Multiple instances of\n *      this iterator type can be used concurrently on the same text as long as the text is not\n *      being modified.\n */\ntypedef struct _SBAttributeRunIterator *SBAttributeRunIteratorRef;\n\n /**\n * A run representing a list of attribute items over a range.\n */\ntypedef struct _SBAttributeRun {\n    SBUInteger index;              /**< Start index of the run in code units. */\n    SBUInteger length;             /**< Length of the run in code units. */\n    SBAttributeListRef attributes; /**< Attributes present on the run. */\n} SBAttributeRun;\n\n/**\n * Returns the parent text retained by the iterator.\n * \n * @param iterator\n *      Attribute run iterator.\n * @return\n *      Text associated with the iterator (borrowed).\n */\nSB_PUBLIC SBTextRef SBAttributeRunIteratorGetText(SBAttributeRunIteratorRef iterator);\n\n/**\n * Configures the iterator to only return runs that contain the specified attribute ID. Empty runs\n * (runs with no matching attributes) are automatically skipped during iteration. If no runs match\n * the filter criteria, MoveNext will return `SBFalse`.\n *\n * @param iterator\n *      Attribute run iterator.\n * @param attributeID\n *      The attribute ID by which to filter the runs.\n */\nSB_PUBLIC void SBAttributeRunIteratorSetupAttributeID(SBAttributeRunIteratorRef iterator,\n    SBAttributeID attributeID);\n\n/**\n * Configures the iterator to only return runs that contain attributes matching the specified group\n * and scope. Empty runs (runs with no matching attributes) are automatically skipped during\n * iteration. If no runs match the filter criteria, MoveNext will return `SBFalse`.\n *\n * @param iterator\n *      Attribute run iterator.\n * @param attributeGroup\n *      The attribute group by which to filter the runs.\n * @param attributeScope\n *      The attribute scope by which to filter the runs.\n */\nSB_PUBLIC void SBAttributeRunIteratorSetupAttributeCollection(SBAttributeRunIteratorRef iterator,\n    SBAttributeGroup attributeGroup, SBAttributeScope attributeScope);\n\n/**\n * Resets iteration to the specified code-unit range.\n *\n * The range is automatically normalized to fit within the text bounds. If the specified range\n * extends beyond the text length, it is clamped to the valid range.\n *\n * @param iterator\n *      Attribute run iterator.\n * @param index\n *      Start index of the iteration window (in code units).\n * @param length\n *      Length of the iteration window (in code units).\n */\nSB_PUBLIC void SBAttributeRunIteratorReset(SBAttributeRunIteratorRef iterator, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Returns a pointer to the current attribute run information owned by the iterator. The pointer\n * remains valid until the next call to MoveNext or Reset.\n * \n * @param iterator\n *      Attribute run iterator.\n * @return\n *      Pointer to `SBAttributeRun` owned by the iterator.\n *\n * @note\n *      This function always returns the same pointer address for a given iterator instance. Only\n *      the content of the structure is updated with each call to MoveNext.\n * @warning\n *      The client should never modify the returned structure. The client can call this function\n *      once and keep the reference, reading from it after each MoveNext call. The `attributes` list\n *      within the structure is also owned by the iterator and should not be modified.\n */\nSB_PUBLIC const SBAttributeRun *SBAttributeRunIteratorGetCurrent(SBAttributeRunIteratorRef iterator);\n\n/**\n * Advances to the next attribute run.\n *\n * When the end of the iteration range is reached, subsequent calls return `SBFalse` and the current\n * element becomes invalid. Runs with no attributes matching the current filter are automatically\n * skipped.\n *\n * @param iterator\n *      Attribute run iterator.\n * @return\n *      `SBTrue` if advanced to a valid element; `SBFalse` if end reached.\n *\n * @warning\n *      The parent text must not be modified during iteration. If modification occurs, reset the\n *      iterator before continuing.\n */\nSB_PUBLIC SBBoolean SBAttributeRunIteratorMoveNext(SBAttributeRunIteratorRef iterator);\n\n/**\n * Increases the reference count of the iterator. Each call to retain must be balanced with a call\n * to release.\n *\n * @param iterator\n *      The attribute run iterator to retain.\n * @return\n *      The same iterator object after retention.\n */\nSB_PUBLIC SBAttributeRunIteratorRef SBAttributeRunIteratorRetain(SBAttributeRunIteratorRef iterator);\n\n/**\n * Decreases the reference count of the iterator. When the reference count reaches zero, the\n * iterator frees its internal storage and releases the retained text.\n *\n * @param iterator\n *      The iterator to release.\n */\nSB_PUBLIC void SBAttributeRunIteratorRelease(SBAttributeRunIteratorRef iterator);\n\n/* ----------------------------------\n * Visual Run Iterator\n * ---------------------------------- */\n\n/**\n * Opaque reference to a visual-order run iterator.\n *\n * Iterates over runs of uniform resolved bidi level in visual order (display order). The iterator\n * retains its parent `SBText` and must be released when no longer needed.\n *\n * @warning\n *      The parent text must not be modified during iteration. If the text is modified, the iterator\n *      behavior becomes undefined and should be reset before further use. Multiple instances of\n *      this iterator type can be used concurrently on the same text as long as the text is not\n *      being modified.\n */\ntypedef struct _SBVisualRunIterator *SBVisualRunIteratorRef;\n\n/**\n * A run of uniform resolved bidi level in visual order.\n */\ntypedef struct _SBVisualRun {\n    SBUInteger index;  /**< Start index of the run in code units. */\n    SBUInteger length; /**< Length of the run in code units. */\n    SBLevel level;     /**< Resolved bidi level of the run. */\n} SBVisualRun;\n\n/**\n * Returns the parent text retained by the iterator.\n * \n * @param iterator\n *      Visual run iterator.\n * @return\n *      Text associated with the iterator (borrowed).\n */\nSB_PUBLIC SBTextRef SBVisualRunIteratorGetText(SBVisualRunIteratorRef iterator);\n\n/**\n * Resets iteration to the specified code-unit range.\n *\n * The range is automatically normalized to fit within the text bounds. If the specified range\n * extends beyond the text length, it is clamped to the valid range.\n *\n * @param iterator\n *      Visual run iterator.\n * @param index\n *      Start index of the iteration window (in code units).\n * @param length\n *      Length of the iteration window (in code units).\n */\nSB_PUBLIC void SBVisualRunIteratorReset(SBVisualRunIteratorRef iterator, SBUInteger index,\n    SBUInteger length);\n\n/**\n * Returns a pointer to the current visual run information owned by the iterator. The pointer\n * remains valid until the next call to MoveNext or Reset.\n * \n * @param iterator\n *      Visual run iterator.\n * @return\n *      Pointer to `SBVisualRun` owned by the iterator.\n *\n * @note\n *      This function always returns the same pointer address for a given iterator instance. Only\n *      the content of the structure is updated with each call to MoveNext.\n * @warning\n *      The client should never modify the returned structure. The client can call this function\n *      once and keep the reference, reading from it after each MoveNext call.\n */\nSB_PUBLIC const SBVisualRun *SBVisualRunIteratorGetCurrent(SBVisualRunIteratorRef iterator);\n\n/**\n * Advances to the next visual run.\n *\n * When the end of the iteration range is reached, subsequent calls return `SBFalse` and the current\n * element becomes invalid.\n *\n * @param iterator\n *      Visual run iterator.\n * @return\n *      `SBTrue` if advanced to a valid element; `SBFalse` if end reached.\n *\n * @warning\n *      The parent text must not be modified during iteration. If modification occurs, reset the\n *      iterator before continuing.\n */\nSB_PUBLIC SBBoolean SBVisualRunIteratorMoveNext(SBVisualRunIteratorRef iterator);\n\n/**\n * Increases the reference count of the iterator. Each call to retain must be balanced with a call\n * to release.\n *\n * @param iterator\n *      The visual run iterator to retain.\n * @return\n *      The same iterator object after retention.\n */\nSB_PUBLIC SBVisualRunIteratorRef SBVisualRunIteratorRetain(SBVisualRunIteratorRef iterator);\n\n/**\n * Decreases the reference count of the iterator. When the reference count reaches zero, the\n * iterator frees its internal storage and releases the retained text.\n *\n * @param iterator\n *      The iterator to release.\n */\nSB_PUBLIC void SBVisualRunIteratorRelease(SBVisualRunIteratorRef iterator);\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBTextType.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_TEXT_TYPE_H\n#define _SB_PUBLIC_TEXT_TYPE_H\n\n#include <SheenBidi/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\nSB_EXTERN_C_BEGIN\n\n/**\n * Opaque reference to an immutable text object.\n */\ntypedef const struct _SBText *SBTextRef;\n\n/**\n *  Opaque reference to a mutable text object.\n */\ntypedef struct _SBText *SBMutableTextRef;\n\nSB_EXTERN_C_END\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SBVersion.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_PUBLIC_VERSION_H\n#define _SB_PUBLIC_VERSION_H\n\n#include <SheenBidi/SBBase.h>\n\nSB_EXTERN_C_BEGIN\n\n#define SHEENBIDI_VERSION_MAJOR     3\n#define SHEENBIDI_VERSION_MINOR     0\n#define SHEENBIDI_VERSION_PATCH     0\n#define SHEENBIDI_VERSION_STRING    \"3.0.0\"\n\n/**\n * Returns the version string of the SheenBidi library.\n *\n * This function returns a constant null-terminated string representing the version of the linked\n * SheenBidi library, in the format \"MAJOR.MINOR.PATCH\".\n *\n * @return A string representing the version (e.g. \"3.0.0\").\n */\nSB_PUBLIC const char *SBVersionGetString(void);\n\nSB_EXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Headers/SheenBidi/SheenBidi.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* Suppress numerous warnings. */\n#pragma GCC system_header\n#pragma clang system_header\n\n#ifndef _SHEENBIDI_H\n#define _SHEENBIDI_H\n\n#include <SheenBidi/SBAlgorithm.h>\n#include <SheenBidi/SBAllocator.h>\n#include <SheenBidi/SBAttributeInfo.h>\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBBidiType.h>\n#include <SheenBidi/SBCodepoint.h>\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBGeneralCategory.h>\n#include <SheenBidi/SBLine.h>\n#include <SheenBidi/SBMirrorLocator.h>\n#include <SheenBidi/SBParagraph.h>\n#include <SheenBidi/SBRun.h>\n#include <SheenBidi/SBScript.h>\n#include <SheenBidi/SBScriptLocator.h>\n#include <SheenBidi/SBText.h>\n#include <SheenBidi/SBTextConfig.h>\n#include <SheenBidi/SBTextIterators.h>\n#include <SheenBidi/SBTextType.h>\n#include <SheenBidi/SBVersion.h>\n\n#endif\n"
  },
  {
    "path": "unix/bidi/LICENSE_SHEENBIDI",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "unix/bidi/SheenBidi.c",
    "content": "/*\n * Copyright (C) 2014-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n \n /* Suppress numerous warnings. */\n#pragma GCC system_header\n#pragma clang system_header\n\n#include <SheenBidi/SBConfig.h>\n#include <SheenBidi/SheenBidi.h>\n\n#ifdef SB_CONFIG_UNITY\n\n#include <API/SBAlgorithm.c>\n#include <API/SBAllocator.c>\n#include <API/SBAttributeList.c>\n#include <API/SBAttributeRegistry.c>\n#include <API/SBBase.c>\n#include <API/SBCodepoint.c>\n#include <API/SBCodepointSequence.c>\n#include <API/SBLine.c>\n#include <API/SBLog.c>\n#include <API/SBMirrorLocator.c>\n#include <API/SBParagraph.c>\n#include <API/SBScriptLocator.c>\n#include <API/SBText.c>\n#include <API/SBTextConfig.c>\n#include <API/SBTextIterators.c>\n\n#include <Core/List.c>\n#include <Core/Memory.c>\n#include <Core/Object.c>\n#include <Core/Once.c>\n\n#include <Data/BidiTypeLookup.c>\n#include <Data/GeneralCategoryLookup.c>\n#include <Data/PairingLookup.c>\n#include <Data/ScriptLookup.c>\n\n#include <Script/ScriptStack.c>\n\n#include <Text/AttributeDictionary.c>\n#include <Text/AttributeManager.c>\n\n#include <UBA/BidiChain.c>\n#include <UBA/BracketQueue.c>\n#include <UBA/IsolatingRun.c>\n#include <UBA/LevelRun.c>\n#include <UBA/RunQueue.c>\n#include <UBA/StatusStack.c>\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAlgorithm.c",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <API/SBCodepointSequence.h>\n#include <API/SBLog.h>\n#include <API/SBParagraph.h>\n#include <Core/Object.h>\n\n#include \"SBAlgorithm.h\"\n\ntypedef SBAlgorithm *SBMutableAlgorithmRef;\n\n#define ALGORITHM  0\n#define BIDI_TYPES 1\n#define COUNT      2\n\nstatic SBMutableAlgorithmRef AllocateAlgorithm(SBUInteger stringLength)\n{\n    void *pointers[COUNT] = { NULL };\n    SBUInteger sizes[COUNT] = { 0 };\n    SBMutableAlgorithmRef algorithm;\n\n    sizes[ALGORITHM]  = sizeof(SBAlgorithm);\n    sizes[BIDI_TYPES] = sizeof(SBBidiType) * stringLength;\n\n    algorithm = ObjectCreate(sizes, COUNT, pointers, NULL);\n\n    if (algorithm) {\n        algorithm->fixedTypes = pointers[BIDI_TYPES];\n    }\n\n    return algorithm;\n}\n\n#undef ALGORITHM\n#undef BIDI_TYPES\n#undef COUNT\n\nstatic SBAlgorithmRef CreateAlgorithm(const SBCodepointSequence *codepointSequence)\n{\n    SBUInteger stringLength = codepointSequence->stringLength;\n    SBMutableAlgorithmRef algorithm;\n\n    SB_LOG_BLOCK_OPENER(\"Algorithm Input\");\n    SB_LOG_STATEMENT(\"Codepoints\", 1, SB_LOG_CODEPOINT_SEQUENCE(codepointSequence));\n    SB_LOG_BLOCK_CLOSER();\n\n    algorithm = AllocateAlgorithm(stringLength);\n\n    if (algorithm) {\n        algorithm->codepointSequence = *codepointSequence;\n\n        SBCodepointSequenceDetermineBidiTypes(codepointSequence, algorithm->fixedTypes);\n\n        SB_LOG_BLOCK_OPENER(\"Determined Types\");\n        SB_LOG_STATEMENT(\"Types\",  1, SB_LOG_BIDI_TYPES_ARRAY(algorithm->fixedTypes, stringLength));\n        SB_LOG_BLOCK_CLOSER();\n\n        SB_LOG_BREAKER();\n    }\n\n    return algorithm;\n}\n\nSBAlgorithmRef SBAlgorithmCreate(const SBCodepointSequence *codepointSequence)\n{\n    SBAlgorithmRef algorithm = NULL;\n\n    if (SBCodepointSequenceIsValid(codepointSequence)) {\n        algorithm = CreateAlgorithm(codepointSequence);\n    }\n\n    return algorithm;\n}\n\nconst SBBidiType *SBAlgorithmGetBidiTypesPtr(SBAlgorithmRef algorithm)\n{\n    return algorithm->fixedTypes;\n}\n\nvoid SBAlgorithmGetParagraphBoundary(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength,\n    SBUInteger *actualLength, SBUInteger *separatorLength)\n{\n    const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;\n    SBBidiType *bidiTypes = algorithm->fixedTypes;\n\n    SBUIntegerNormalizeRange(codepointSequence->stringLength, &paragraphOffset, &suggestedLength);\n\n    SBCodepointSequenceGetParagraphBoundary(\n        codepointSequence, bidiTypes, paragraphOffset, suggestedLength,\n        actualLength, separatorLength\n    );\n}\n\nSBParagraphRef SBAlgorithmCreateParagraph(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)\n{\n    const SBCodepointSequence *codepointSequence = &algorithm->codepointSequence;\n    SBUInteger stringLength = codepointSequence->stringLength;\n    SBParagraphRef paragraph = NULL;\n\n    SBUIntegerNormalizeRange(stringLength, &paragraphOffset, &suggestedLength);\n\n    if (suggestedLength > 0) {\n        paragraph = SBParagraphCreateWithAlgorithm(\n            algorithm, paragraphOffset, suggestedLength, baseLevel\n        );\n    }\n\n    return paragraph;\n}\n\nSBAlgorithmRef SBAlgorithmRetain(SBAlgorithmRef algorithm)\n{\n    return ObjectRetain((ObjectRef)algorithm);\n}\n\nvoid SBAlgorithmRelease(SBAlgorithmRef algorithm)\n{\n    ObjectRelease((ObjectRef)algorithm);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAlgorithm.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ALGORITHM_H\n#define _SB_INTERNAL_ALGORITHM_H\n\n#include <SheenBidi/SBAlgorithm.h>\n#include <SheenBidi/SBBidiType.h>\n#include <SheenBidi/SBCodepointSequence.h>\n\n#include <Core/Object.h>\n\ntypedef struct _SBAlgorithm {\n    ObjectBase _base;\n    SBCodepointSequence codepointSequence;\n    SBBidiType *fixedTypes;\n} SBAlgorithm;\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAllocator.c",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n\n#include <API/SBBase.h>\n#include <Core/AtomicPointer.h>\n#include <Core/Object.h>\n#include <Core/Once.h>\n#include <Core/ThreadLocalStorage.h>\n\n#include \"SBAllocator.h\"\n\ntypedef SBAllocator *SBMutableAllocatorRef;\ntypedef AtomicPointerType(SBAllocator) SBAtomicAllocatorRef;\n\nstatic SBAtomicAllocatorRef DefaultAllocator = NULL;\n\n#ifndef SB_CONFIG_DISABLE_SCRATCH_MEMORY\n\n#if defined(HAS_ATOMIC_POINTER_SUPPORT) && defined(HAS_TLS_SUPPORT) && defined(HAS_ONCE_SUPPORT)\n#define USE_SCRATCH_MEMORY\n#else\n#error \"Scratch memory functionality requires atomic operations, thread-local, and once support. \\\nTo proceed without scratch memory, manually define `SB_CONFIG_DISABLE_SCRATCH_MEMORY`.\"\n#endif\n\n#endif\n\n#ifdef USE_SCRATCH_MEMORY\n\ntypedef struct _Buffer {\n    struct _Buffer *next;\n    SBUInteger offset;\n    SBUInt8 data[SB_CONFIG_SCRATCH_BUFFER_SIZE];\n} Buffer, *BufferRef;\ntypedef AtomicPointerType(Buffer) AtomicBufferRef;\n\nstatic Buffer BufferPool[SB_CONFIG_SCRATCH_POOL_SIZE];\nstatic AtomicBufferRef BufferStack = NULL;\nstatic ThreadLocalStorage ScratchBuffer;\n\n#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))\n\nstatic void InitializeBufferStack(void *info)\n{\n    SBUInteger index;\n\n    for (index = 0; index < SB_CONFIG_SCRATCH_POOL_SIZE - 1; index++) {\n        BufferPool[index].next = &BufferPool[index + 1];\n        BufferPool[index].offset = 0;\n    }\n\n    BufferPool[SB_CONFIG_SCRATCH_POOL_SIZE - 1].next = NULL;\n    BufferPool[SB_CONFIG_SCRATCH_POOL_SIZE - 1].offset = 0;\n    AtomicPointerStore(&BufferStack, &BufferPool[0]);\n}\n\nstatic SBBoolean TryLazyInitializeBufferStack(void)\n{\n    static Once once = OnceMake();\n    return OnceTryExecute(&once, InitializeBufferStack, NULL);\n}\n\nstatic BufferRef DetachBuffer(void)\n{\n    BufferRef buffer = NULL;\n\n    if (TryLazyInitializeBufferStack()) {\n        BufferRef expected = NULL;\n\n        do {\n            buffer = AtomicPointerLoad(&BufferStack);\n            expected = buffer;\n\n            if (!buffer) {\n                break;\n            }\n        } while (!AtomicPointerCompareAndSet(&BufferStack, &expected, buffer->next));\n    }\n\n    return buffer;\n}\n\nstatic void RecycleBuffer(BufferRef buffer)\n{\n    BufferRef top;\n    BufferRef expected;\n\n    buffer->offset = 0;\n\n    do {\n        top = AtomicPointerLoad(&BufferStack);\n        expected = top;\n        buffer->next = top;\n    } while (!AtomicPointerCompareAndSet(&BufferStack, &expected, buffer));\n}\n\nstatic void InitializeScratchBuffer(void *info)\n{\n    ThreadLocalStorageInitialize(ScratchBuffer);\n}\n\nstatic SBBoolean TryLazyInitializeScratchBuffer(void)\n{\n    static Once once = OnceMake();\n    return OnceTryExecute(&once, InitializeScratchBuffer, NULL);\n}\n\nstatic void *NativeAllocateScratch(SBUInteger size, void *info)\n{\n    void *pointer = NULL;\n\n    if (TryLazyInitializeScratchBuffer()) {\n        BufferRef buffer = ThreadLocalStorageGet(ScratchBuffer);\n\n        if (!buffer) {\n            buffer = DetachBuffer();\n\n            if (buffer) {\n                ThreadLocalStorageSet(ScratchBuffer, buffer);\n            }\n        }\n\n        if (buffer) {\n            SBUInteger alignedSize = ALIGN_UP(size, sizeof(void *));\n            SBUInteger limit = buffer->offset + alignedSize;\n\n            if (limit <= SB_CONFIG_SCRATCH_BUFFER_SIZE) {\n                pointer = buffer->data + buffer->offset;\n                buffer->offset += alignedSize;\n            }\n        }\n    }\n\n    return pointer;\n}\n\nstatic void NativeResetScratch(void *info)\n{\n    if (TryLazyInitializeScratchBuffer()) {\n        BufferRef buffer = ThreadLocalStorageGet(ScratchBuffer);\n\n        if (buffer) {\n            ThreadLocalStorageSet(ScratchBuffer, NULL);\n            RecycleBuffer(buffer);\n        }\n    }\n}\n\n#else\n\n#define NativeAllocateScratch   NULL\n#define NativeResetScratch      NULL\n\n#endif\n\nstatic void *NativeAllocateBlock(SBUInteger size, void *info)\n{\n    return malloc(size);\n}\n\nstatic void *NativeReallocateBlock(void *pointer, SBUInteger size, void *info)\n{\n    return realloc(pointer, size);\n}\n\nstatic void NativeDeallocateBlock(void *pointer, void *info)\n{\n    free(pointer);\n}\n\nstatic SBAllocator NativeAllocator = SBAllocatorMake(\n    NativeAllocateBlock, NativeReallocateBlock, NativeDeallocateBlock,\n    NativeAllocateScratch, NativeResetScratch, NULL);\n\nstatic void FinalizeAllocator(ObjectRef object)\n{\n    SBAllocatorRef allocator = object;\n\n    if (allocator->_protocol.finalize) {\n        allocator->_protocol.finalize(allocator->_info);\n    }\n}\n\nstatic SBAllocatorRef SBAllocatorGetCurrent(void)\n{\n    SBAllocatorRef allocator = AtomicPointerLoad(&DefaultAllocator);\n\n    if (!allocator) {\n        allocator = &NativeAllocator;\n    }\n\n    return allocator;\n}\n\nSB_INTERNAL void *SBAllocatorAllocateBlock(SBAllocatorRef allocator, SBUInteger size)\n{\n    if (!allocator) {\n        allocator = SBAllocatorGetCurrent();\n    }\n\n    return allocator->_protocol.allocateBlock(size, allocator->_info);\n}\n\nSB_INTERNAL void *SBAllocatorReallocateBlock(SBAllocatorRef allocator, void *pointer, SBUInteger newSize)\n{\n    if (!allocator) {\n        allocator = SBAllocatorGetCurrent();\n    }\n\n    return allocator->_protocol.reallocateBlock(pointer, newSize, allocator->_info);\n}\n\nSB_INTERNAL void SBAllocatorDeallocateBlock(SBAllocatorRef allocator, void *pointer)\n{\n    if (!allocator) {\n        allocator = SBAllocatorGetCurrent();\n    }\n\n    allocator->_protocol.deallocateBlock(pointer, allocator->_info);\n}\n\nSB_INTERNAL void *SBAllocatorAllocateScratch(SBAllocatorRef allocator, SBUInteger size)\n{\n    SBAllocatorAllocateScratchFunc func;\n    void *pointer = NULL;\n\n    if (!allocator) {\n        allocator = SBAllocatorGetCurrent();\n    }\n\n    func = allocator->_protocol.allocateScratch;\n\n    if (func) {\n        pointer = func(size, allocator->_info);\n    }\n\n    return pointer;\n}\n\nSB_INTERNAL void SBAllocatorResetScratch(SBAllocatorRef allocator)\n{\n    SBAllocatorResetScratchFunc func;\n\n    if (!allocator) {\n        allocator = SBAllocatorGetCurrent();\n    }\n\n    func = allocator->_protocol.resetScratch;\n\n    if (func) {\n        func(allocator->_info);\n    }\n}\n\nSBAllocatorRef SBAllocatorGetDefault(void)\n{\n    return AtomicPointerLoad(&DefaultAllocator);\n}\n\nvoid SBAllocatorSetDefault(SBAllocatorRef allocator)\n{\n    AtomicPointerStore(&DefaultAllocator, (SBAllocator *)allocator);\n}\n\nSBAllocatorRef SBAllocatorCreate(const SBAllocatorProtocol *protocol, void *info)\n{\n    const SBUInteger size = sizeof(SBAllocator);\n    void *pointer = NULL;\n    SBMutableAllocatorRef allocator = NULL;\n\n    allocator = ObjectCreate(&size, 1, &pointer, FinalizeAllocator);\n\n    if (allocator) {\n        allocator->_info = info;\n        allocator->_protocol = *protocol;\n    }\n\n    return allocator;\n}\n\nSBAllocatorRef SBAllocatorRetain(SBAllocatorRef allocator)\n{\n    return ObjectRetain((ObjectRef)allocator);\n}\n\nvoid SBAllocatorRelease(SBAllocatorRef allocator)\n{\n    ObjectRelease((ObjectRef)allocator);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAllocator.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ALLOCATOR_H\n#define _SB_INTERNAL_ALLOCATOR_H\n\n#include <SheenBidi/SBAllocator.h>\n\n#include <API/SBBase.h>\n#include <Core/Object.h>\n\ntypedef struct _SBAllocator {\n    ObjectBase _base;\n    void *_info;\n    SBAllocatorProtocol _protocol;\n} SBAllocator;\n\n#define SBAllocatorMake(allocateBlock, reallocateBlock, deallocateBlock, \\\n    allocateScratch, resetScratch, finalize)                             \\\n{                                                                        \\\n    ObjectBaseMake(),                                                    \\\n    NULL,                                                                \\\n    {                                                                    \\\n        allocateBlock, reallocateBlock, deallocateBlock,                 \\\n        allocateScratch, resetScratch, finalize                          \\\n    }                                                                    \\\n}\n\nSB_INTERNAL void *SBAllocatorAllocateBlock(SBAllocatorRef allocator, SBUInteger size);\nSB_INTERNAL void *SBAllocatorReallocateBlock(SBAllocatorRef allocator, void *pointer, SBUInteger newSize);\nSB_INTERNAL void SBAllocatorDeallocateBlock(SBAllocatorRef allocator, void *pointer);\n\nSB_INTERNAL void *SBAllocatorAllocateScratch(SBAllocatorRef allocator, SBUInteger size);\nSB_INTERNAL void SBAllocatorResetScratch(SBAllocatorRef allocator);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAssert.h",
    "content": "/*\n * Copyright (C) 2014 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ASSERT_H\n#define _SB_INTERNAL_ASSERT_H\n\n#include <assert.h>\n\n#define SBAssert(exp)   assert(exp)\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAttributeInfo.h",
    "content": "/*\n * Copyright (C) 2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATTRIBUTE_INFO_H\n#define _SB_INTERNAL_ATTRIBUTE_INFO_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <string.h>\n#include <SheenBidi/SBAttributeInfo.h>\n\n#define SBAttributeIDMake(index, size)                  \\\n    ((((SBUInt32)((index) + 1)) << 8) | ((SBUInt32)(size) & 0xFF))\n\n#define SBAttributeIDGetSize(id)                        \\\n    ((SBUInt8)((id) & 0xFF))\n\n#define SBAttributeIDGetIndex(id)                       \\\n    ((SBUInt32)(((id) >> 8) - 1))\n\n#define SBAttributeIDIsValid(id)                        \\\n    ((id) != SBAttributeIDNone)\n\n#define SBAttributeItemGetValuePtr(item)                \\\n    ((void *)(&(item)->attributeID + 1))\n\n#define SBAttributeItemSetValue(item, valuePtr)         \\\n    memcpy(SBAttributeItemGetValuePtr(item), valuePtr, SBAttributeIDGetSize((item)->attributeID))\n\n#define SBAttributeItemSet(item, id, valuePtr)          \\\ndo {                                                    \\\n    (item)->attributeID = (id);                         \\\n    SBAttributeItemSetValue(item, valuePtr);            \\\n} while (0)\n\n#define SBAttributeItemIsEqualValue(id, first, second)  \\\n    (memcmp(first, second, SBAttributeIDGetSize(id)) == 0)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAttributeList.c",
    "content": "/*\n * Copyright (C) 2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <API/SBAttributeInfo.h>\n#include <Core/List.h>\n\n#include \"SBAttributeList.h\"\n\n#define ALIGN_VALUE_SIZE(x, a) (((x) + ((a) - 1)) & ~((a) - 1))\n\nSB_INTERNAL void SBAttributeListInitialize(SBAttributeListRef list, SBUInteger valueSize)\n{\n    const SBUInteger idSize = sizeof(SBAttributeID);\n    const SBUInteger itemSize = idSize + ALIGN_VALUE_SIZE(valueSize, idSize);\n\n    ListInitialize(&list->_list, itemSize);\n}\n\nSB_INTERNAL SBUInteger SBAttributeListBinarySearchIndex(SBAttributeListRef list,\n    SBAttributeID attributeID, SBBoolean *itemFound)\n{\n    const List *innerList = &list->_list;\n\n    *itemFound = SBFalse;\n\n    if (innerList->data) {\n        SBUInteger low = 0;\n        SBUInteger high = innerList->count;\n\n        while (low < high) {\n            SBUInteger mid = low + (high - low) / 2;\n            SBAttributeItem *item = ListGetPtr(innerList, mid);\n            SBAttributeID id = item->attributeID;\n\n            if (id == attributeID) {\n                *itemFound = SBTrue;\n                return mid;\n            }\n\n            if (id < attributeID) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    return 0;\n}\n\nconst SBAttributeItem *SBAttributeListGetItem(SBAttributeListRef list, SBUInteger index)\n{\n    return ListGetPtr(&list->_list, index);\n}\n\nSBUInteger SBAttributeListGetCount(SBAttributeListRef list)\n{\n    return list->_list.count;\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAttributeList.h",
    "content": "/*\n * Copyright (C) 2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATTRIBUTE_LIST_H\n#define _SB_INTERNAL_ATTRIBUTE_LIST_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeList.h>\n#include <Core/List.h>\n\ntypedef struct _SBAttributeList {\n    List _list;\n} SBAttributeList;\n\nSB_INTERNAL void SBAttributeListInitialize(SBAttributeListRef list, SBUInteger valueSize);\n\n#define SBAttributeListFinalize(list_)                      \\\n    ListFinalize(&(list_)->_list)\n\n#define SBAttributeListSize(list_)                          \\\n    ((list_)->_list.count)\n\n#define SBAttributeListReserveRange(list_, index_, count_)  \\\n    ListReserveRange(&(list_)->_list, index_, count_)\n\n#define SBAttributeListReserveEnd(list_, count_)            \\\n    ListReserveRange(&(list_)->_list, (list_)->_list.count, count_)\n\n#define SBAttributeListGetAt(list_, index_)                 \\\n    ListGetPtr(&(list_)->_list, index_)\n\n#define SBAttributeListGetLast(list_)                       \\\n    ListGetPtr(&(list_)->_list, (list_)->_list.count - 1)\n\n#define SBAttributeListRemoveAt(list_, index_)              \\\n    ListRemoveAt(&(list_)->_list, index_)\n\n#define SBAttributeListRemoveAll(list_)                     \\\n    ListRemoveAll(&(list_)->_list)\n\n/**\n * Finds the index where an attribute with the specified ID is located or should be inserted.\n *\n * @param list\n *      The attribute list to search.\n * @param attributeID\n *      The attribute ID to search for.\n * @param itemFound\n *      Pointer to a boolean that will be set to SBTrue if the attribute is found, SBFalse\n *      otherwise.\n * @return\n *      The index of the found item, or the insertion index if not found.\n */\nSB_INTERNAL SBUInteger SBAttributeListBinarySearchIndex(SBAttributeListRef list,\n    SBAttributeID attributeID, SBBoolean *itemFound);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAttributeRegistry.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <API/SBAttributeInfo.h>\n#include <Core/Object.h>\n\n#include \"SBAttributeRegistry.h\"\n\nstatic int AttributeInfoComparison(const void *first, const void *second)\n{\n    const SBAttributeInfo *info1 = first;\n    const SBAttributeInfo *info2 = second;\n\n    return strcmp(info1->name, info2->name);\n}\n\nstatic int AttributeNameComparison(const void *key, const void *array)\n{\n    const char *name = key;\n    const SBAttributeInfo *attributeInfo = array;\n\n    return strcmp(name, attributeInfo->name);\n}\n\nstatic SBUInteger CountCombinedNamesLength(\n    const SBAttributeInfo *attributeInfos, SBUInteger attributeCount)\n{\n    SBUInteger combinedLength = 0;\n    SBUInteger index;\n\n    for (index = 0; index < attributeCount; index++) {\n        const SBAttributeInfo *currentInfo = &attributeInfos[index];\n        SBUInteger nameLength = strlen(currentInfo->name) + 1;\n        combinedLength += nameLength;\n    }\n\n    return combinedLength;\n}\n\n#define ATTRIBUTE_REGISTRY  0\n#define ATTRIBUTE_INFOS     1\n#define ATTRIBUTE_NAMES     2\n#define COUNT               3\n\nstatic SBAttributeRegistry *AllocateAttributeRegistry(\n    SBUInteger attributeCount, SBUInteger namesLength, char **namesPointer)\n{\n    void *pointers[COUNT] = { NULL };\n    SBUInteger sizes[COUNT] = { 0 };\n    SBAttributeRegistry *attributeRegistry;\n\n    sizes[ATTRIBUTE_REGISTRY] = sizeof(SBAttributeRegistry);\n    sizes[ATTRIBUTE_INFOS]    = sizeof(SBAttributeInfo) * attributeCount;\n    sizes[ATTRIBUTE_NAMES]    = namesLength;\n\n    attributeRegistry = ObjectCreate(sizes, COUNT, pointers, NULL);\n\n    if (attributeRegistry) {\n        attributeRegistry->attributeInfos = pointers[ATTRIBUTE_INFOS];\n        *namesPointer = pointers[ATTRIBUTE_NAMES];\n    }\n\n    return attributeRegistry;\n}\n\n#undef ATTRIBUTE_REGISTRY\n#undef ATTRIBUTE_INFOS\n#undef ATTRIBUTE_NAMES\n#undef COUNT\n\nstatic SBAttributeInfo *GetAttributeInfoForID(SBAttributeRegistryRef registry, SBAttributeID id)\n{\n    SBUInteger index = SBAttributeIDGetIndex(id);\n\n    if (index < registry->count) {\n        return &registry->attributeInfos[index];\n    }\n\n    return NULL;\n}\n\nSB_INTERNAL const void *SBAttributeRegistryRetainAttribute(SBAttributeRegistryRef registry,\n    const void *attributeValue)\n{\n    SBAttributeValueRetainCallback retain = registry->_valueCallbacks.retain;\n\n    if (retain) {\n        return retain(attributeValue);\n    }\n\n    return attributeValue;\n}\n\nSB_INTERNAL void SBAttributeRegistryReleaseAttribute(SBAttributeRegistryRef registry,\n    const void *attributeValue)\n{\n    SBAttributeValueReleaseCallback release = registry->_valueCallbacks.release;\n\n    if (release) {\n        release(attributeValue);\n    }\n}\n\nSB_INTERNAL SBBoolean SBAttributeRegistryIsEqualAttribute(SBAttributeRegistryRef registry,\n    SBAttributeID attributeID, const void *first, const void *second)\n{\n    SBAttributeValueEqualCallback equal = registry->_valueCallbacks.equal;\n\n    if (equal) {\n        return equal(first, second);\n    }\n\n    return SBAttributeItemIsEqualValue(attributeID, first, second);\n}\n\nSB_INTERNAL const SBAttributeInfo *SBAttributeRegistryGetInfoReference(\n    SBAttributeRegistryRef registry, SBAttributeID attributeID)\n{\n    return GetAttributeInfoForID(registry, attributeID);\n}\n\nSBAttributeRegistryRef SBAttributeRegistryCreate(const SBAttributeInfo *attributeInfos,\n    SBUInteger count, SBUInt8 valueSize, const SBAttributeValueCallbacks *valueCallbacks)\n{\n    SBUInteger namesLength = CountCombinedNamesLength(attributeInfos, count);\n    char *namesPointer;\n    SBAttributeRegistry *attributeRegistry;\n\n    attributeRegistry = AllocateAttributeRegistry(count, namesLength, &namesPointer);\n\n    if (attributeRegistry) {\n        SBAttributeInfo *destination = attributeRegistry->attributeInfos;\n        SBUInteger index;\n\n        for (index = 0; index < count; index++) {\n            destination[index].name = namesPointer;\n            destination[index].group = attributeInfos[index].group;\n            destination[index].scope = attributeInfos[index].scope;\n\n            strcpy(namesPointer, attributeInfos[index].name);\n            namesPointer += strlen(attributeInfos[index].name) + 1;\n        }\n\n        attributeRegistry->count = count;\n        attributeRegistry->valueSize = valueSize;\n\n        if (valueCallbacks) {\n            attributeRegistry->_valueCallbacks = *valueCallbacks;\n        } else {\n            attributeRegistry->_valueCallbacks.equal = NULL;\n            attributeRegistry->_valueCallbacks.release = NULL;\n            attributeRegistry->_valueCallbacks.retain = NULL;\n        }\n\n        qsort(attributeRegistry->attributeInfos, count, sizeof(SBAttributeInfo), AttributeInfoComparison);\n    }\n\n    return attributeRegistry;\n}\n\nSBBoolean SBAttributeRegistryGetAttributeInfo(SBAttributeRegistryRef registry,\n    SBAttributeID attributeID, SBAttributeInfo *attributeInfo)\n{\n    SBBoolean idExists = SBFalse;\n\n    if (SBAttributeIDIsValid(attributeID)) {\n        SBUInteger index = SBAttributeIDGetIndex(attributeID);\n\n        *attributeInfo = registry->attributeInfos[index];\n        idExists = SBTrue;\n    }\n\n    return idExists;\n}\n\nSBAttributeID SBAttributeRegistryGetAttributeID(\n    SBAttributeRegistryRef registry, const char *name)\n{\n    SBAttributeInfo *attributeInfo = bsearch(name, registry->attributeInfos, registry->count,\n        sizeof(SBAttributeInfo), AttributeNameComparison);\n\n    if (attributeInfo) {\n        SBUInteger index = attributeInfo - registry->attributeInfos;\n        SBUInt8 size = registry->valueSize;\n\n        return SBAttributeIDMake(index, size);\n    }\n\n    return SBAttributeIDNone;\n}\n\nSBAttributeRegistryRef SBAttributeRegistryRetain(SBAttributeRegistryRef registry)\n{\n    return ObjectRetain((ObjectRef)registry);\n}\n\nvoid SBAttributeRegistryRelease(SBAttributeRegistryRef registry)\n{\n    ObjectRelease((ObjectRef)registry);\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBAttributeRegistry.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATTRIBUTE_REGISTRY_H\n#define _SB_INTERNAL_ATTRIBUTE_REGISTRY_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeInfo.h>\n#include <SheenBidi/SBAttributeRegistry.h>\n\n#include <Core/Object.h>\n\ntypedef struct _SBAttributeRegistry {\n    ObjectBase _base;\n    SBAttributeInfo *attributeInfos;\n    SBUInteger count;\n    SBUInt8 valueSize;\n    SBAttributeValueCallbacks _valueCallbacks;\n} SBAttributeRegistry;\n\nSB_INTERNAL const void *SBAttributeRegistryRetainAttribute(SBAttributeRegistryRef registry,\n    const void *attributeValue);\n\nSB_INTERNAL void SBAttributeRegistryReleaseAttribute(SBAttributeRegistryRef registry,\n    const void *attributeValue);\n\nSB_INTERNAL SBBoolean SBAttributeRegistryIsEqualAttribute(SBAttributeRegistryRef registry,\n    SBAttributeID attributeID, const void *first, const void *second);\n\nSB_INTERNAL const SBAttributeInfo *SBAttributeRegistryGetInfoReference(\n    SBAttributeRegistryRef registry, SBAttributeID attributeID);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBBase.c",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <SheenBidi/SBVersion.h>\n\n#include \"SBBase.h\"\n\nstatic const char LibraryVersion[] = SHEENBIDI_VERSION_STRING;\n\n#define TAG(a, b, c, d) \\\n(SBUInt32)              \\\n(                       \\\n   ((SBUInt8)(a) << 24) \\\n | ((SBUInt8)(b) << 16) \\\n | ((SBUInt8)(c) <<  8) \\\n | ((SBUInt8)(d) <<  0) \\\n)\n\nSB_INTERNAL void SBUIntegerNormalizeRange(SBUInteger actualLength,\n    SBUInteger *rangeOffset, SBUInteger *rangeLength)\n{\n    /**\n     * Assume:\n     *      Actual Length = 10\n     *\n     * Case 1:\n     *      Offset = 0, Length = 10\n     * Result:\n     *      Offset = 0, Length = 10\n     *\n     * Case 2:\n     *      Offset = 0, Length = 11\n     * Result:\n     *      Offset = 0, Length = 10\n     *\n     * Case 3:\n     *      Offset = 1, Length = -1 (MAX)\n     * Result:\n     *      Offset = 1, Length = 9\n     *\n     * Case 4:\n     *      Offset = 10, Length = 0\n     * Result:\n     *      Offset = Invalid, Length = 0\n     *\n     * Case 5:\n     *      Offset = -1 (MAX), Length = 1\n     * Result:\n     *      Offset = Invalid, Length = 0\n     */\n\n    if (*rangeOffset < actualLength) {\n        SBUInteger possibleLimit = *rangeOffset + *rangeLength;\n\n        if (*rangeOffset <= possibleLimit && possibleLimit <= actualLength) {\n            /* The range is valid. Nothing to do here. */\n        } else {\n            *rangeLength = actualLength - *rangeOffset;\n        }\n    } else {\n        *rangeOffset = SBInvalidIndex;\n        *rangeLength = 0;\n    }\n}\n\nSB_INTERNAL SBBoolean SBUIntegerVerifyRange(SBUInteger actualLength,\n    SBUInteger rangeOffset, SBUInteger rangeLength)\n{\n    SBUInteger possibleLimit = rangeOffset + rangeLength;\n\n    return rangeOffset < actualLength\n        && rangeOffset <= possibleLimit\n        && possibleLimit <= actualLength;\n}\n\nSBUInt32 SBScriptGetOpenTypeTag(SBScript script)\n{\n    /* Reference: https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags */\n    /* Dated: 05/31/2024 */\n\n    switch (script) {\n    case SBScriptADLM:\n        return TAG('a', 'd', 'l', 'm');\n    case SBScriptAHOM:\n        return TAG('a', 'h', 'o', 'm');\n    case SBScriptHLUW:\n        return TAG('h', 'l', 'u', 'w');\n    case SBScriptARAB:\n        return TAG('a', 'r', 'a', 'b');\n    case SBScriptARMN:\n        return TAG('a', 'r', 'm', 'n');\n    case SBScriptAVST:\n        return TAG('a', 'v', 's', 't');\n    case SBScriptBALI:\n        return TAG('b', 'a', 'l', 'i');\n    case SBScriptBAMU:\n        return TAG('b', 'a', 'm', 'u');\n    case SBScriptBASS:\n        return TAG('b', 'a', 's', 's');\n    case SBScriptBATK:\n        return TAG('b', 'a', 't', 'k');\n /* case SBScriptBENG:\n        return TAG('b', 'e', 'n', 'g'); */\n    case SBScriptBENG:\n        return TAG('b', 'n', 'g', '2');\n    case SBScriptBERF:\n        return TAG('b', 'e', 'r', 'f');\n    case SBScriptBHKS:\n        return TAG('b', 'h', 'k', 's');\n    case SBScriptBOPO:\n        return TAG('b', 'o', 'p', 'o');\n    case SBScriptBRAH:\n        return TAG('b', 'r', 'a', 'h');\n    case SBScriptBRAI:\n        return TAG('b', 'r', 'a', 'i');\n    case SBScriptBUGI:\n        return TAG('b', 'u', 'g', 'i');\n    case SBScriptBUHD:\n        return TAG('b', 'u', 'h', 'd');\n /* case SBScript____:\n        return TAG('b', 'y', 'z', 'm'); */\n    case SBScriptCANS:\n        return TAG('c', 'a', 'n', 's');\n    case SBScriptCARI:\n        return TAG('c', 'a', 'r', 'i');\n    case SBScriptAGHB:\n        return TAG('a', 'g', 'h', 'b');\n    case SBScriptCAKM:\n        return TAG('c', 'a', 'k', 'm');\n    case SBScriptCHAM:\n        return TAG('c', 'h', 'a', 'm');\n    case SBScriptCHER:\n        return TAG('c', 'h', 'e', 'r');\n    case SBScriptCHRS:\n        return TAG('c', 'h', 'r', 's');\n    case SBScriptHANI:\n        return TAG('h', 'a', 'n', 'i');\n    case SBScriptCOPT:\n        return TAG('c', 'o', 'p', 't');\n    case SBScriptCPRT:\n        return TAG('c', 'p', 'r', 't');\n    case SBScriptCPMN:\n        return TAG('c', 'p', 'm', 'n');\n    case SBScriptCYRL:\n        return TAG('c', 'y', 'r', 'l');\n    case SBScriptDSRT:\n        return TAG('d', 's', 'r', 't');\n /* case SBScriptDEVA:\n        return TAG('d', 'e', 'v', 'a'); */\n    case SBScriptDEVA:\n        return TAG('d', 'e', 'v', '2');\n    case SBScriptDIAK:\n        return TAG('d', 'i', 'a', 'k');\n    case SBScriptDOGR:\n        return TAG('d', 'o', 'g', 'r');\n    case SBScriptDUPL:\n        return TAG('d', 'u', 'p', 'l');\n    case SBScriptEGYP:\n        return TAG('e', 'g', 'y', 'p');\n    case SBScriptELBA:\n        return TAG('e', 'l', 'b', 'a');\n    case SBScriptELYM:\n        return TAG('e', 'l', 'y', 'm');\n    case SBScriptETHI:\n        return TAG('e', 't', 'h', 'i');\n    case SBScriptGARA:\n        return TAG('g', 'a', 'r', 'a');\n    case SBScriptGEOR:\n        return TAG('g', 'e', 'o', 'r');\n    case SBScriptGLAG:\n        return TAG('g', 'l', 'a', 'g');\n    case SBScriptGOTH:\n        return TAG('g', 'o', 't', 'h');\n    case SBScriptGRAN:\n        return TAG('g', 'r', 'a', 'n');\n    case SBScriptGREK:\n        return TAG('g', 'r', 'e', 'k');\n /* case SBScriptGUJR:\n        return TAG('g', 'u', 'j', 'r'); */\n    case SBScriptGUJR:\n        return TAG('g', 'j', 'r', '2');\n    case SBScriptGONG:\n        return TAG('g', 'o', 'n', 'g');\n /* case SBScriptGURU:\n        return TAG('g', 'u', 'r', 'u'); */\n    case SBScriptGURU:\n        return TAG('g', 'u', 'r', '2');\n    case SBScriptGUKH:\n        return TAG('g', 'u', 'k', 'h');\n    case SBScriptHANG:\n        return TAG('h', 'a', 'n', 'g');\n /* case SBScriptHANG:\n        return TAG('j', 'a', 'm', 'o'); */\n    case SBScriptROHG:\n        return TAG('r', 'o', 'h', 'g');\n    case SBScriptHANO:\n        return TAG('h', 'a', 'n', 'o');\n    case SBScriptHATR:\n        return TAG('h', 'a', 't', 'r');\n    case SBScriptHEBR:\n        return TAG('h', 'e', 'b', 'r');\n    case SBScriptHIRA:\n        return TAG('k', 'a', 'n', 'a');\n    case SBScriptARMI:\n        return TAG('a', 'r', 'm', 'i');\n    case SBScriptPHLI:\n        return TAG('p', 'h', 'l', 'i');\n    case SBScriptPRTI:\n        return TAG('p', 'r', 't', 'i');\n    case SBScriptJAVA:\n        return TAG('j', 'a', 'v', 'a');\n    case SBScriptKTHI:\n        return TAG('k', 't', 'h', 'i');\n /* case SBScriptKNDA:\n        return TAG('k', 'n', 'd', 'a'); */\n    case SBScriptKNDA:\n        return TAG('k', 'n', 'd', '2');\n    case SBScriptKANA:\n        return TAG('k', 'a', 'n', 'a');\n    case SBScriptKAWI:\n        return TAG('k', 'a', 'w', 'i');\n    case SBScriptKALI:\n        return TAG('k', 'a', 'l', 'i');\n    case SBScriptKHAR:\n        return TAG('k', 'h', 'a', 'r');\n    case SBScriptKITS:\n        return TAG('k', 'i', 't', 's');\n    case SBScriptKHMR:\n        return TAG('k', 'h', 'm', 'r');\n    case SBScriptKHOJ:\n        return TAG('k', 'h', 'o', 'j');\n    case SBScriptSIND:\n        return TAG('s', 'i', 'n', 'd');\n    case SBScriptKRAI:\n        return TAG('k', 'r', 'a', 'i');\n    case SBScriptLAOO:\n        return TAG('l', 'a', 'o', ' ');\n    case SBScriptLATN:\n        return TAG('l', 'a', 't', 'n');\n    case SBScriptLEPC:\n        return TAG('l', 'e', 'p', 'c');\n    case SBScriptLIMB:\n        return TAG('l', 'i', 'm', 'b');\n    case SBScriptLINA:\n        return TAG('l', 'i', 'n', 'a');\n    case SBScriptLINB:\n        return TAG('l', 'i', 'n', 'b');\n    case SBScriptLISU:\n        return TAG('l', 'i', 's', 'u');\n    case SBScriptLYCI:\n        return TAG('l', 'y', 'c', 'i');\n    case SBScriptLYDI:\n        return TAG('l', 'y', 'd', 'i');\n    case SBScriptMAHJ:\n        return TAG('m', 'a', 'h', 'j');\n    case SBScriptMAKA:\n        return TAG('m', 'a', 'k', 'a');\n /* case SBScriptMLYM:\n        return TAG('m', 'l', 'y', 'm'); */\n    case SBScriptMLYM:\n        return TAG('m', 'l', 'm', '2');\n    case SBScriptMAND:\n        return TAG('m', 'a', 'n', 'd');\n    case SBScriptMANI:\n        return TAG('m', 'a', 'n', 'i');\n    case SBScriptMARC:\n        return TAG('m', 'a', 'r', 'c');\n    case SBScriptGONM:\n        return TAG('g', 'o', 'n', 'm');\n /* case SBScript____:\n        return TAG('m', 'a', 't', 'h'); */\n    case SBScriptMEDF:\n        return TAG('m', 'e', 'd', 'f');\n    case SBScriptMTEI:\n        return TAG('m', 't', 'e', 'i');\n    case SBScriptMEND:\n        return TAG('m', 'e', 'n', 'd');\n    case SBScriptMERC:\n        return TAG('m', 'e', 'r', 'c');\n    case SBScriptMERO:\n        return TAG('m', 'e', 'r', 'o');\n    case SBScriptPLRD:\n        return TAG('p', 'l', 'r', 'd');\n    case SBScriptMODI:\n        return TAG('m', 'o', 'd', 'i');\n    case SBScriptMONG:\n        return TAG('m', 'o', 'n', 'g');\n    case SBScriptMROO:\n        return TAG('m', 'r', 'o', 'o');\n    case SBScriptMULT:\n        return TAG('m', 'u', 'l', 't');\n /* case SBScript___:\n        return TAG('m', 'u', 's', 'c'); */\n /* case SBScriptMYMR:\n        return TAG('m', 'y', 'm', 'r'); */\n    case SBScriptMYMR:\n        return TAG('m', 'y', 'm', '2');\n    case SBScriptNBAT:\n        return TAG('n', 'b', 'a', 't');\n    case SBScriptNAGM:\n        return TAG('n', 'a', 'g', 'm');\n    case SBScriptNAND:\n        return TAG('n', 'a', 'n', 'd');\n    case SBScriptNEWA:\n        return TAG('n', 'e', 'w', 'a');\n    case SBScriptTALU:\n        return TAG('t', 'a', 'l', 'u');\n    case SBScriptNKOO:\n        return TAG('n', 'k', 'o', ' ');\n    case SBScriptNSHU:\n        return TAG('n', 's', 'h', 'u');\n    case SBScriptHMNP:\n        return TAG('h', 'm', 'n', 'p');\n /* case SBScriptORYA:\n        return TAG('o', 'r', 'y', 'a'); */\n    case SBScriptORYA:\n        return TAG('o', 'r', 'y', '2');\n    case SBScriptOGAM:\n        return TAG('o', 'g', 'a', 'm');\n    case SBScriptOLCK:\n        return TAG('o', 'l', 'c', 'k');\n    case SBScriptONAO:\n        return TAG('o', 'n', 'a', 'o');\n    case SBScriptITAL:\n        return TAG('i', 't', 'a', 'l');\n    case SBScriptHUNG:\n        return TAG('h', 'u', 'n', 'g');\n    case SBScriptNARB:\n        return TAG('n', 'a', 'r', 'b');\n    case SBScriptPERM:\n        return TAG('p', 'e', 'r', 'm');\n    case SBScriptXPEO:\n        return TAG('x', 'p', 'e', 'o');\n    case SBScriptSOGO:\n        return TAG('s', 'o', 'g', 'o');\n    case SBScriptSARB:\n        return TAG('s', 'a', 'r', 'b');\n    case SBScriptORKH:\n        return TAG('o', 'r', 'k', 'h');\n    case SBScriptOUGR:\n        return TAG('o', 'u', 'g', 'r');\n    case SBScriptOSGE:\n        return TAG('o', 's', 'g', 'e');\n    case SBScriptOSMA:\n        return TAG('o', 's', 'm', 'a');\n    case SBScriptHMNG:\n        return TAG('h', 'm', 'n', 'g');\n    case SBScriptPALM:\n        return TAG('p', 'a', 'l', 'm');\n    case SBScriptPAUC:\n        return TAG('p', 'a', 'u', 'c');\n    case SBScriptPHAG:\n        return TAG('p', 'h', 'a', 'g');\n    case SBScriptPHNX:\n        return TAG('p', 'h', 'n', 'x');\n    case SBScriptPHLP:\n        return TAG('p', 'h', 'l', 'p');\n    case SBScriptRJNG:\n        return TAG('r', 'j', 'n', 'g');\n    case SBScriptRUNR:\n        return TAG('r', 'u', 'n', 'r');\n    case SBScriptSAMR:\n        return TAG('s', 'a', 'm', 'r');\n    case SBScriptSAUR:\n        return TAG('s', 'a', 'u', 'r');\n    case SBScriptSHRD:\n        return TAG('s', 'h', 'r', 'd');\n    case SBScriptSHAW:\n        return TAG('s', 'h', 'a', 'w');\n    case SBScriptSIDD:\n        return TAG('s', 'i', 'd', 'd');\n    case SBScriptSIDT:\n        return TAG('s', 'i', 'd', 't');\n    case SBScriptSGNW:\n        return TAG('s', 'g', 'n', 'w');\n    case SBScriptSINH:\n        return TAG('s', 'i', 'n', 'h');\n    case SBScriptSOGD:\n        return TAG('s', 'o', 'g', 'd');\n    case SBScriptSORA:\n        return TAG('s', 'o', 'r', 'a');\n    case SBScriptSOYO:\n        return TAG('s', 'o', 'y', 'o');\n    case SBScriptXSUX:\n        return TAG('x', 's', 'u', 'x');\n    case SBScriptSUND:\n        return TAG('s', 'u', 'n', 'd');\n    case SBScriptSUNU:\n        return TAG('s', 'u', 'n', 'u');\n    case SBScriptSYLO:\n        return TAG('s', 'y', 'l', 'o');\n    case SBScriptSYRC:\n        return TAG('s', 'y', 'r', 'c');\n    case SBScriptTGLG:\n        return TAG('t', 'g', 'l', 'g');\n    case SBScriptTAGB:\n        return TAG('t', 'a', 'g', 'b');\n    case SBScriptTALE:\n        return TAG('t', 'a', 'l', 'e');\n    case SBScriptLANA:\n        return TAG('l', 'a', 'n', 'a');\n    case SBScriptTAVT:\n        return TAG('t', 'a', 'v', 't');\n    case SBScriptTAKR:\n        return TAG('t', 'a', 'k', 'r');\n /* case SBScriptTAML:\n        return TAG('t', 'a', 'm', 'l'); */\n    case SBScriptTAML:\n        return TAG('t', 'm', 'l', '2');\n    case SBScriptTNSA:\n        return TAG('t', 'n', 's', 'a');\n    case SBScriptTANG:\n        return TAG('t', 'a', 'n', 'g');\n    case SBScriptTAYO:\n        return TAG('t', 'a', 'y', 'o');\n /* case SBScriptTELU:\n        return TAG('t', 'e', 'l', 'u'); */\n    case SBScriptTELU:\n        return TAG('t', 'e', 'l', '2');\n    case SBScriptTHAA:\n        return TAG('t', 'h', 'a', 'a');\n    case SBScriptTHAI:\n        return TAG('t', 'h', 'a', 'i');\n    case SBScriptTIBT:\n        return TAG('t', 'i', 'b', 't');\n    case SBScriptTFNG:\n        return TAG('t', 'f', 'n', 'g');\n    case SBScriptTIRH:\n        return TAG('t', 'i', 'r', 'h');\n    case SBScriptTODR:\n        return TAG('t', 'o', 'd', 'r');\n    case SBScriptTOLS:\n        return TAG('t', 'o', 'l', 's');\n    case SBScriptTOTO:\n        return TAG('t', 'o', 't', 'o');\n    case SBScriptTUTG:\n        return TAG('t', 'u', 't', 'g');\n    case SBScriptUGAR:\n        return TAG('u', 'g', 'a', 'r');\n    case SBScriptVAII:\n        return TAG('v', 'a', 'i', ' ');\n    case SBScriptVITH:\n        return TAG('v', 'i', 't', 'h');\n    case SBScriptWCHO:\n        return TAG('w', 'c', 'h', 'o');\n    case SBScriptWARA:\n        return TAG('w', 'a', 'r', 'a');\n    case SBScriptYEZI:\n        return TAG('y', 'e', 'z', 'i');\n    case SBScriptYIII:\n        return TAG('y', 'i', ' ', ' ');\n    case SBScriptZANB:\n        return TAG('z', 'a', 'n', 'b');\n    default:\n        return TAG('D', 'F', 'L', 'T');\n    }\n}\n\nSBUInt32 SBScriptGetUnicodeTag(SBScript script)\n{\n    switch (script) {\n    case SBScriptADLM:\n        return TAG('A', 'd', 'l', 'm');\n    case SBScriptAGHB:\n        return TAG('A', 'g', 'h', 'b');\n    case SBScriptAHOM:\n        return TAG('A', 'h', 'o', 'm');\n    case SBScriptARAB:\n        return TAG('A', 'r', 'a', 'b');\n    case SBScriptARMI:\n        return TAG('A', 'r', 'm', 'i');\n    case SBScriptARMN:\n        return TAG('A', 'r', 'm', 'n');\n    case SBScriptAVST:\n        return TAG('A', 'v', 's', 't');\n    case SBScriptBALI:\n        return TAG('B', 'a', 'l', 'i');\n    case SBScriptBAMU:\n        return TAG('B', 'a', 'm', 'u');\n    case SBScriptBASS:\n        return TAG('B', 'a', 's', 's');\n    case SBScriptBATK:\n        return TAG('B', 'a', 't', 'k');\n    case SBScriptBENG:\n        return TAG('B', 'e', 'n', 'g');\n    case SBScriptBERF:\n        return TAG('B', 'e', 'r', 'f');\n    case SBScriptBHKS:\n        return TAG('B', 'h', 'k', 's');\n    case SBScriptBOPO:\n        return TAG('B', 'o', 'p', 'o');\n    case SBScriptBRAH:\n        return TAG('B', 'r', 'a', 'h');\n    case SBScriptBRAI:\n        return TAG('B', 'r', 'a', 'i');\n    case SBScriptBUGI:\n        return TAG('B', 'u', 'g', 'i');\n    case SBScriptBUHD:\n        return TAG('B', 'u', 'h', 'd');\n    case SBScriptCAKM:\n        return TAG('C', 'a', 'k', 'm');\n    case SBScriptCANS:\n        return TAG('C', 'a', 'n', 's');\n    case SBScriptCARI:\n        return TAG('C', 'a', 'r', 'i');\n    case SBScriptCHAM:\n        return TAG('C', 'h', 'a', 'm');\n    case SBScriptCHER:\n        return TAG('C', 'h', 'e', 'r');\n    case SBScriptCHRS:\n        return TAG('C', 'h', 'r', 's');\n    case SBScriptCOPT:\n        return TAG('C', 'o', 'p', 't');\n    case SBScriptCPMN:\n        return TAG('C', 'p', 'm', 'n');\n    case SBScriptCPRT:\n        return TAG('C', 'p', 'r', 't');\n    case SBScriptCYRL:\n        return TAG('C', 'y', 'r', 'l');\n    case SBScriptDEVA:\n        return TAG('D', 'e', 'v', 'a');\n    case SBScriptDIAK:\n        return TAG('D', 'i', 'a', 'k');\n    case SBScriptDOGR:\n        return TAG('D', 'o', 'g', 'r');\n    case SBScriptDSRT:\n        return TAG('D', 's', 'r', 't');\n    case SBScriptDUPL:\n        return TAG('D', 'u', 'p', 'l');\n    case SBScriptEGYP:\n        return TAG('E', 'g', 'y', 'p');\n    case SBScriptELBA:\n        return TAG('E', 'l', 'b', 'a');\n    case SBScriptELYM:\n        return TAG('E', 'l', 'y', 'm');\n    case SBScriptETHI:\n        return TAG('E', 't', 'h', 'i');\n    case SBScriptGARA:\n        return TAG('G', 'a', 'r', 'a');\n    case SBScriptGEOR:\n        return TAG('G', 'e', 'o', 'r');\n    case SBScriptGLAG:\n        return TAG('G', 'l', 'a', 'g');\n    case SBScriptGONG:\n        return TAG('G', 'o', 'n', 'g');\n    case SBScriptGONM:\n        return TAG('G', 'o', 'n', 'm');\n    case SBScriptGOTH:\n        return TAG('G', 'o', 't', 'h');\n    case SBScriptGRAN:\n        return TAG('G', 'r', 'a', 'n');\n    case SBScriptGREK:\n        return TAG('G', 'r', 'e', 'k');\n    case SBScriptGUJR:\n        return TAG('G', 'u', 'j', 'r');\n    case SBScriptGUKH:\n        return TAG('G', 'u', 'k', 'h');\n    case SBScriptGURU:\n        return TAG('G', 'u', 'r', 'u');\n    case SBScriptHANG:\n        return TAG('H', 'a', 'n', 'g');\n    case SBScriptHANI:\n        return TAG('H', 'a', 'n', 'i');\n    case SBScriptHANO:\n        return TAG('H', 'a', 'n', 'o');\n    case SBScriptHATR:\n        return TAG('H', 'a', 't', 'r');\n    case SBScriptHEBR:\n        return TAG('H', 'e', 'b', 'r');\n    case SBScriptHIRA:\n        return TAG('H', 'i', 'r', 'a');\n    case SBScriptHLUW:\n        return TAG('H', 'l', 'u', 'w');\n    case SBScriptHMNG:\n        return TAG('H', 'm', 'n', 'g');\n    case SBScriptHMNP:\n        return TAG('H', 'm', 'n', 'p');\n    case SBScriptHUNG:\n        return TAG('H', 'u', 'n', 'g');\n    case SBScriptITAL:\n        return TAG('I', 't', 'a', 'l');\n    case SBScriptJAVA:\n        return TAG('J', 'a', 'v', 'a');\n    case SBScriptKALI:\n        return TAG('K', 'a', 'l', 'i');\n    case SBScriptKANA:\n        return TAG('K', 'a', 'n', 'a');\n    case SBScriptKAWI:\n        return TAG('K', 'a', 'w', 'i');\n    case SBScriptKHAR:\n        return TAG('K', 'h', 'a', 'r');\n    case SBScriptKHMR:\n        return TAG('K', 'h', 'm', 'r');\n    case SBScriptKHOJ:\n        return TAG('K', 'h', 'o', 'j');\n    case SBScriptKITS:\n        return TAG('K', 'i', 't', 's');\n    case SBScriptKNDA:\n        return TAG('K', 'n', 'd', 'a');\n    case SBScriptKRAI:\n        return TAG('K', 'r', 'a', 'i');\n    case SBScriptKTHI:\n        return TAG('K', 't', 'h', 'i');\n    case SBScriptLANA:\n        return TAG('L', 'a', 'n', 'a');\n    case SBScriptLAOO:\n        return TAG('L', 'a', 'o', 'o');\n    case SBScriptLATN:\n        return TAG('L', 'a', 't', 'n');\n    case SBScriptLEPC:\n        return TAG('L', 'e', 'p', 'c');\n    case SBScriptLIMB:\n        return TAG('L', 'i', 'm', 'b');\n    case SBScriptLINA:\n        return TAG('L', 'i', 'n', 'a');\n    case SBScriptLINB:\n        return TAG('L', 'i', 'n', 'b');\n    case SBScriptLISU:\n        return TAG('L', 'i', 's', 'u');\n    case SBScriptLYCI:\n        return TAG('L', 'y', 'c', 'i');\n    case SBScriptLYDI:\n        return TAG('L', 'y', 'd', 'i');\n    case SBScriptMAHJ:\n        return TAG('M', 'a', 'h', 'j');\n    case SBScriptMAKA:\n        return TAG('M', 'a', 'k', 'a');\n    case SBScriptMAND:\n        return TAG('M', 'a', 'n', 'd');\n    case SBScriptMANI:\n        return TAG('M', 'a', 'n', 'i');\n    case SBScriptMARC:\n        return TAG('M', 'a', 'r', 'c');\n    case SBScriptMEDF:\n        return TAG('M', 'e', 'd', 'f');\n    case SBScriptMEND:\n        return TAG('M', 'e', 'n', 'd');\n    case SBScriptMERC:\n        return TAG('M', 'e', 'r', 'c');\n    case SBScriptMERO:\n        return TAG('M', 'e', 'r', 'o');\n    case SBScriptMLYM:\n        return TAG('M', 'l', 'y', 'm');\n    case SBScriptMODI:\n        return TAG('M', 'o', 'd', 'i');\n    case SBScriptMONG:\n        return TAG('M', 'o', 'n', 'g');\n    case SBScriptMROO:\n        return TAG('M', 'r', 'o', 'o');\n    case SBScriptMTEI:\n        return TAG('M', 't', 'e', 'i');\n    case SBScriptMULT:\n        return TAG('M', 'u', 'l', 't');\n    case SBScriptMYMR:\n        return TAG('M', 'y', 'm', 'r');\n    case SBScriptNAGM:\n        return TAG('N', 'a', 'g', 'm');\n    case SBScriptNAND:\n        return TAG('N', 'a', 'n', 'd');\n    case SBScriptNARB:\n        return TAG('N', 'a', 'r', 'b');\n    case SBScriptNBAT:\n        return TAG('N', 'b', 'a', 't');\n    case SBScriptNEWA:\n        return TAG('N', 'e', 'w', 'a');\n    case SBScriptNKOO:\n        return TAG('N', 'k', 'o', 'o');\n    case SBScriptNSHU:\n        return TAG('N', 's', 'h', 'u');\n    case SBScriptOGAM:\n        return TAG('O', 'g', 'a', 'm');\n    case SBScriptOLCK:\n        return TAG('O', 'l', 'c', 'k');\n    case SBScriptONAO:\n        return TAG('O', 'n', 'a', 'o');\n    case SBScriptORKH:\n        return TAG('O', 'r', 'k', 'h');\n    case SBScriptORYA:\n        return TAG('O', 'r', 'y', 'a');\n    case SBScriptOSGE:\n        return TAG('O', 's', 'g', 'e');\n    case SBScriptOSMA:\n        return TAG('O', 's', 'm', 'a');\n    case SBScriptOUGR:\n        return TAG('O', 'u', 'g', 'r');\n    case SBScriptPALM:\n        return TAG('P', 'a', 'l', 'm');\n    case SBScriptPAUC:\n        return TAG('P', 'a', 'u', 'c');\n    case SBScriptPERM:\n        return TAG('P', 'e', 'r', 'm');\n    case SBScriptPHAG:\n        return TAG('P', 'h', 'a', 'g');\n    case SBScriptPHLI:\n        return TAG('P', 'h', 'l', 'i');\n    case SBScriptPHLP:\n        return TAG('P', 'h', 'l', 'p');\n    case SBScriptPHNX:\n        return TAG('P', 'h', 'n', 'x');\n    case SBScriptPLRD:\n        return TAG('P', 'l', 'r', 'd');\n    case SBScriptPRTI:\n        return TAG('P', 'r', 't', 'i');\n    case SBScriptRJNG:\n        return TAG('R', 'j', 'n', 'g');\n    case SBScriptROHG:\n        return TAG('R', 'o', 'h', 'g');\n    case SBScriptRUNR:\n        return TAG('R', 'u', 'n', 'r');\n    case SBScriptSAMR:\n        return TAG('S', 'a', 'm', 'r');\n    case SBScriptSARB:\n        return TAG('S', 'a', 'r', 'b');\n    case SBScriptSAUR:\n        return TAG('S', 'a', 'u', 'r');\n    case SBScriptSGNW:\n        return TAG('S', 'g', 'n', 'w');\n    case SBScriptSHAW:\n        return TAG('S', 'h', 'a', 'w');\n    case SBScriptSHRD:\n        return TAG('S', 'h', 'r', 'd');\n    case SBScriptSIDD:\n        return TAG('S', 'i', 'd', 'd');\n    case SBScriptSIDT:\n        return TAG('S', 'i', 'd', 't');\n    case SBScriptSIND:\n        return TAG('S', 'i', 'n', 'd');\n    case SBScriptSINH:\n        return TAG('S', 'i', 'n', 'h');\n    case SBScriptSOGD:\n        return TAG('S', 'o', 'g', 'd');\n    case SBScriptSOGO:\n        return TAG('S', 'o', 'g', 'o');\n    case SBScriptSORA:\n        return TAG('S', 'o', 'r', 'a');\n    case SBScriptSOYO:\n        return TAG('S', 'o', 'y', 'o');\n    case SBScriptSUND:\n        return TAG('S', 'u', 'n', 'd');\n    case SBScriptSUNU:\n        return TAG('S', 'u', 'n', 'u');\n    case SBScriptSYLO:\n        return TAG('S', 'y', 'l', 'o');\n    case SBScriptSYRC:\n        return TAG('S', 'y', 'r', 'c');\n    case SBScriptTAGB:\n        return TAG('T', 'a', 'g', 'b');\n    case SBScriptTAKR:\n        return TAG('T', 'a', 'k', 'r');\n    case SBScriptTALE:\n        return TAG('T', 'a', 'l', 'e');\n    case SBScriptTALU:\n        return TAG('T', 'a', 'l', 'u');\n    case SBScriptTAML:\n        return TAG('T', 'a', 'm', 'l');\n    case SBScriptTANG:\n        return TAG('T', 'a', 'n', 'g');\n    case SBScriptTAVT:\n        return TAG('T', 'a', 'v', 't');\n    case SBScriptTAYO:\n        return TAG('T', 'a', 'y', 'o');\n    case SBScriptTELU:\n        return TAG('T', 'e', 'l', 'u');\n    case SBScriptTFNG:\n        return TAG('T', 'f', 'n', 'g');\n    case SBScriptTGLG:\n        return TAG('T', 'g', 'l', 'g');\n    case SBScriptTHAA:\n        return TAG('T', 'h', 'a', 'a');\n    case SBScriptTHAI:\n        return TAG('T', 'h', 'a', 'i');\n    case SBScriptTIBT:\n        return TAG('T', 'i', 'b', 't');\n    case SBScriptTIRH:\n        return TAG('T', 'i', 'r', 'h');\n    case SBScriptTNSA:\n        return TAG('T', 'n', 's', 'a');\n    case SBScriptTODR:\n        return TAG('T', 'o', 'd', 'r');\n    case SBScriptTOLS:\n        return TAG('T', 'o', 'l', 's');\n    case SBScriptTOTO:\n        return TAG('T', 'o', 't', 'o');\n    case SBScriptTUTG:\n        return TAG('T', 'u', 't', 'g');\n    case SBScriptUGAR:\n        return TAG('U', 'g', 'a', 'r');\n    case SBScriptVAII:\n        return TAG('V', 'a', 'i', 'i');\n    case SBScriptVITH:\n        return TAG('V', 'i', 't', 'h');\n    case SBScriptWARA:\n        return TAG('W', 'a', 'r', 'a');\n    case SBScriptWCHO:\n        return TAG('W', 'c', 'h', 'o');\n    case SBScriptXPEO:\n        return TAG('X', 'p', 'e', 'o');\n    case SBScriptXSUX:\n        return TAG('X', 's', 'u', 'x');\n    case SBScriptYEZI:\n        return TAG('Y', 'e', 'z', 'i');\n    case SBScriptYIII:\n        return TAG('Y', 'i', 'i', 'i');\n    case SBScriptZANB:\n        return TAG('Z', 'a', 'n', 'b');\n    case SBScriptZINH:\n        return TAG('Z', 'i', 'n', 'h');\n    case SBScriptZYYY:\n        return TAG('Z', 'y', 'y', 'y');\n    case SBScriptZZZZ:\n        return TAG('Z', 'z', 'z', 'z');\n    default:\n        return 0;\n    }\n}\n\nconst char *SBVersionGetString(void)\n{\n    return LibraryVersion;\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBBase.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_BASE_H\n#define _SB_INTERNAL_BASE_H\n\n#include <SheenBidi/SBBase.h>\n#include <SheenBidi/SBBidiType.h>\n#include <SheenBidi/SBConfig.h>\n#include <SheenBidi/SBGeneralCategory.h>\n#include <SheenBidi/SBScript.h>\n\n#ifdef SB_CONFIG_UNITY\n#define SB_INTERNAL static\n#else\n#define SB_INTERNAL\n#endif\n\n/* ---------- Compiler Version Detection ---------- */\n\n/* Detect GCC and its version */\n#if defined(__GNUC__) && !defined(__clang__)\n#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#else\n#define GCC_VERSION     0\n#endif\n\n/* Detect Clang and its version */\n#if defined(__clang__)\n#define CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)\n#else\n#define CLANG_VERSION   0\n#endif\n\n/* Detect MSVC and its version */\n#if defined(_MSC_VER)\n#define MSVC_VERSION    _MSC_VER\n#else\n#define MSVC_VERSION    0\n#endif\n\n/* ---------- Atomic Support Feature Detection ---------- */\n\n/* Prefer C11 atomics if available */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)\n#define USE_C11_ATOMICS\n\n/* Fallback to compiler intrinsics for GCC/Clang */\n#elif defined(__GNUC__) || defined(__clang__)\n/* Modern __atomic builtins (GCC 4.7+, Clang 3.1+) */\n#if GCC_VERSION >= 407 || CLANG_VERSION >= 301\n#define USE_ATOMIC_BUILTINS\n/* Legacy __sync builtins (GCC 4.1+, Clang 1.0+) */\n#elif GCC_VERSION >= 401 || CLANG_VERSION >= 100\n#define USE_SYNC_BUILTINS\n#endif\n\n/* Windows-specific intrinsics */\n#elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)\n\n#if MSVC_VERSION >= 1700    /* VS 2012+ */\n#define USE_WIN_INTRINSICS\n#else\n#define USE_WIN_INTERLOCKED\n#endif\n\n#endif\n\n\n/**\n * A value that indicates an invalid unsigned index.\n */\n#define SBInvalidIndex  (SBUInteger)(-1)\n\nSB_INTERNAL void SBUIntegerNormalizeRange(SBUInteger actualLength,\n    SBUInteger *rangeOffset, SBUInteger *rangeLength);\n\nSB_INTERNAL SBBoolean SBUIntegerVerifyRange(SBUInteger actualLength,\n    SBUInteger rangeOffset, SBUInteger rangeLength);\n\n\n#define SBNumberGetMax(first, second)           \\\n(                                               \\\n   (first) > (second)                           \\\n ? (first)                                      \\\n : (second)                                     \\\n)\n\n#define SBNumberLimitIncrement(number, limit)   \\\n(                                               \\\n   (number) < (limit)                           \\\n ? (number) + (1)                               \\\n : (limit)                                      \\\n)\n\n#define SBNumberLimitDecrement(number, limit)   \\\n(                                               \\\n   (number) > (limit)                           \\\n ? (number) - (1)                               \\\n : (limit)                                      \\\n)\n\n#define SBNumberRingAdd(number, count, capacity) \\\n    (((number) + (count)) % (capacity))\n\n#define SBNumberRingIncrement(number, capacity) \\\n    SBNumberRingAdd(number, 1, capacity)\n\n#define SBNumberRingSubtract(number, count, capacity) \\\n    (((number) + (capacity) - (count)) % (capacity))\n\n#define SBNumberRingDecrement(number, capacity) \\\n    SBNumberRingSubtract(number, 1, capacity)\n\n\n#define SBLevelAsNormalBidiType(level)      \\\n(                                           \\\n   ((level) & 1)                            \\\n ? SBBidiTypeR                              \\\n : SBBidiTypeL                              \\\n)\n\n#define SBLevelAsOppositeBidiType(level)    \\\n(                                           \\\n   ((level) & 1)                            \\\n ? SBBidiTypeL                              \\\n : SBBidiTypeR                              \\\n)\n\n\n#define SBBidiTypeIsEqual(t1, t2)           ((t1) == (t2))\n\n#define SBBidiTypeIsNumber(t)               SBUInt8InRange(t, SBBidiTypeAN, SBBidiTypeEN)\n#define SBBidiTypeIsIsolate(t)              SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypePDI)\n\n#define SBBidiTypeIsStrongOrNumber(t)       (SBBidiTypeIsStrong(t) || SBBidiTypeIsNumber(t))\n#define SBBidiTypeIsNumberSeparator(t)      SBUInt8InRange(t, SBBidiTypeES, SBBidiTypeCS)\n#define SBBidiTypeIsIsolateInitiator(t)     SBUInt8InRange(t, SBBidiTypeLRI, SBBidiTypeFSI)\n#define SBBidiTypeIsIsolateTerminator(t)    SBBidiTypeIsEqual(t, SBBidiTypePDI)\n#define SBBidiTypeIsNeutralOrIsolate(t)     SBUInt8InRange(t, SBBidiTypeWS, SBBidiTypePDI)\n\n#define SBScriptIsCommonOrInherited(s)      ((s) <= SBScriptZYYY)\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBCodepoint.c",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <Data/BidiTypeLookup.h>\n#include <Data/GeneralCategoryLookup.h>\n#include <Data/PairingLookup.h>\n#include <Data/ScriptLookup.h>\n\n#include \"SBCodepoint.h\"\n\ntypedef struct {\n    SBUInt8 valid;\n    SBUInt8 total;\n    SBUInt8 start;\n    SBUInt8 end;\n} UTF8State;\n\nstatic const UTF8State UTF8StateTable[9] = {\n    { 1, 0, 0x00, 0x00 }, { 0, 0, 0x00, 0x00 }, { 1, 2, 0x80, 0xBF }, { 1, 3, 0xA0, 0xBF },\n    { 1, 3, 0x80, 0xBF }, { 1, 3, 0x80, 0x9F }, { 1, 4, 0x90, 0xBF }, { 1, 4, 0x80, 0xBF },\n    { 1, 4, 0x80, 0x8F }\n};\n\nstatic const SBUInt8 UTF8LookupTable[256] = {\n    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,\n    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,\n    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,\n    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,\n/* LEAD: -- 80..BF -- */\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n/* LEAD: -- C0..C1 -- */\n    1, 1,\n/* LEAD: -- C2..DF -- */\n    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n/* LEAD: -- E0..E0 -- */\n    3,\n/* LEAD: -- E1..EC -- */\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n/* LEAD: -- ED..ED -- */\n    5,\n/* LEAD: -- EE..EF -- */\n    4, 4,\n/* LEAD: -- F0..F0 -- */\n    6,\n/* LEAD: -- F1..F3 -- */\n    7, 7, 7,\n/* LEAD: -- F4..F4 -- */\n    8,\n/* LEAD: -- F5..F7 -- */\n    1, 1, 1,\n/* LEAD: -- F8..FB -- */\n    1, 1, 1, 1,\n/* LEAD: -- FC..FD -- */\n    1, 1,\n/* LEAD: -- FE..FF -- */\n    1, 1\n};\n\nSB_INTERNAL const void *SBCodepointGetBufferOffset(const void *buffer,\n    SBStringEncoding encoding, SBUInteger index)\n{\n    switch (encoding) {\n    case SBStringEncodingUTF8:\n        return (const SBUInt8 *)buffer + index;\n    \n    case SBStringEncodingUTF16:\n        return (const SBUInt16 *)buffer + index;\n\n    case SBStringEncodingUTF32:\n        return (const SBUInt32 *)buffer + index;\n\n    default:\n        return NULL;\n    }\n}\n\nSB_INTERNAL void SBCodepointSkipToStart(const void *buffer, SBUInteger length,\n    SBStringEncoding encoding, SBUInteger *index)\n{\n    /* Index MUST be valid */\n    SBAssert(*index < length);\n\n    switch (encoding) {\n    case SBStringEncodingUTF8: {\n        const SBUInt8 *codeUnits = buffer;\n        SBUInteger start = *index;\n\n        /* Advance 4 code units to take trailing ones into account */\n        if (*index + 4 < length) {\n            *index += 4;\n        } else {\n            *index = length;\n        }\n\n        /* Get previous code point until start is reached/passed */\n        do {\n            SBCodepointDecodePreviousFromUTF8(codeUnits, length, index);\n        } while (*index > start);\n\n        break;\n    }\n\n    case SBStringEncodingUTF16: {\n        const SBUInt16 *codeUnits = buffer;\n        SBUInteger start = *index;\n\n        /* Advance one code unit to take surrogate into account. */\n        if (*index < length) {\n            *index += 1;\n        }\n\n        /* Get previous code point until start is reached/passed. */\n        do {\n            SBCodepointDecodePreviousFromUTF16(codeUnits, length, index);\n        } while (*index > start);\n\n        break;\n    }\n\n    case SBStringEncodingUTF32:\n        /* Nothing to do here. */\n        break;\n    }\n}\n\nSB_INTERNAL void SBCodepointSkipToEnd(const void *buffer, SBUInteger length,\n    SBStringEncoding encoding, SBUInteger *index)\n{\n    /* Index MUST be valid */\n    SBAssert(*index < length);\n\n    switch (encoding) {\n    case SBStringEncodingUTF8: {\n        const SBUInt8 *codeUnits = buffer;\n        SBUInteger end = *index + 1;\n\n        /* Advance 4 code units to take leading ones into account. */\n        if (*index > 4) {\n            *index -= 4;\n        } else {\n            *index = 0;\n        }\n\n        /* Get next code point until end is reached/passed. */\n        do {\n            SBCodepointDecodeNextFromUTF8(codeUnits, length, index);\n        } while (*index < end);\n\n        break;\n    }\n\n    case SBStringEncodingUTF16: {\n        const SBUInt16 *codeUnits = buffer;\n        SBUInteger end = *index + 1;\n\n        /* Advance one code unit to take surrogate into account. */\n        if (*index > 1) {\n            *index -= 1;\n        }\n\n        /* Get next code point until end is reached/passed. */\n        do {\n            SBCodepointDecodeNextFromUTF16(codeUnits, length, index);\n        } while (*index < end);\n\n        break;\n    }\n\n    case SBStringEncodingUTF32:\n        *index += 1;\n        break;\n    }\n}\n\nSB_INTERNAL SBBoolean SBCodepointIsCanonicalEquivalentBracket(\n    SBCodepoint codepoint, SBCodepoint bracket)\n{\n    SBCodepoint canonical;\n\n    switch (codepoint) {\n    case 0x2329:\n        canonical = 0x3008;\n        break;\n    case 0x3008:\n        canonical = 0x2329;\n        break;\n\n    case 0x232A:\n        canonical = 0x3009;\n        break;\n    case 0x3009:\n        canonical = 0x232A;\n        break;\n\n    default:\n        canonical = codepoint;\n        break;\n    }\n\n    return bracket == codepoint || bracket == canonical;\n}\n\nSBBidiType SBCodepointGetBidiType(SBCodepoint codepoint)\n{\n    return LookupBidiType(codepoint);\n}\n\nSBGeneralCategory SBCodepointGetGeneralCategory(SBCodepoint codepoint)\n{\n    return LookupGeneralCategory(codepoint);\n}\n\nSBCodepoint SBCodepointGetMirror(SBCodepoint codepoint)\n{\n    return LookupMirror(codepoint);\n}\n\nSBScript SBCodepointGetScript(SBCodepoint codepoint)\n{\n    return LookupScript(codepoint);\n}\n\nSBCodepoint SBCodepointDecodeNextFromUTF8(const SBUInt8 *buffer, SBUInteger length, SBUInteger *index)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    if (*index < length) {\n        SBUInt8 lead = buffer[*index];\n        UTF8State state = UTF8StateTable[UTF8LookupTable[lead]];\n        SBUInteger limit = *index + state.total;\n\n        if (limit > length) {\n            limit = length;\n            state.valid = SBFalse;\n        }\n\n        codepoint = lead & (0x7F >> state.total);\n\n        while (++(*index) < limit) {\n            SBUInt8 byte = buffer[*index];\n\n            if (byte >= state.start && byte <= state.end) {\n                codepoint = (codepoint << 6) | (byte & 0x3F);\n            } else {\n                state.valid = SBFalse;\n                break;\n            }\n\n            state.start = 0x80;\n            state.end = 0xBF;\n        }\n\n        if (!state.valid) {\n            codepoint = SBCodepointFaulty;\n        }\n    }\n\n    return codepoint;\n}\n\nSBCodepoint SBCodepointDecodePreviousFromUTF8(const SBUInt8 *buffer, SBUInteger length, SBUInteger *index)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    if ((*index - 1) < length) {\n        SBUInteger startIndex = *index;\n        SBUInteger limitIndex;\n        SBUInteger continuation;\n\n        continuation = 4;\n\n        while (continuation-- && --startIndex) {\n            SBUInt8 codeUnit = buffer[startIndex];\n\n            if ((codeUnit & 0xC0) != 0x80) {\n                break;\n            }\n        }\n\n        limitIndex = startIndex;\n        codepoint = SBCodepointDecodeNextFromUTF8(buffer, length, &limitIndex);\n\n        if (limitIndex == *index) {\n            *index = startIndex;\n        } else {\n            codepoint = SBCodepointFaulty;\n            *index -= 1;\n        }\n    }\n\n    return codepoint;\n}\n\nSBCodepoint SBCodepointDecodeNextFromUTF16(const SBUInt16 *buffer, SBUInteger length, SBUInteger *index)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    if (*index < length) {\n        SBUInt16 lead;\n\n        codepoint = SBCodepointFaulty;\n\n        lead = buffer[*index];\n        *index += 1;\n\n        if (!SBCodepointIsSurrogate(lead)) {\n            codepoint = lead;\n        } else if (lead <= 0xDBFF) {\n            if (*index < length) {\n                SBUInt16 trail = buffer[*index];\n\n                if (SBUInt16InRange(trail, 0xDC00, 0xDFFF)) {\n                    codepoint = (lead << 10) + trail - ((0xD800 << 10) + 0xDC00 - 0x10000);\n                    *index += 1;\n                }\n            }\n        }\n    }\n\n    return codepoint;\n}\n\nSBCodepoint SBCodepointDecodePreviousFromUTF16(const SBUInt16 *buffer, SBUInteger length, SBUInteger *index)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    if ((*index - 1) < length) {\n        SBUInt16 trail;\n\n        codepoint = SBCodepointFaulty;\n\n        *index -= 1;\n        trail = buffer[*index];\n\n        if (!SBCodepointIsSurrogate(trail)) {\n            codepoint = trail;\n        } else if (trail >= 0xDC00) {\n            if (*index > 0) {\n                SBUInt16 lead = buffer[*index - 1];\n\n                if (SBUInt16InRange(lead, 0xD800, 0xDBFF)) {\n                    codepoint = (lead << 10) + trail - ((0xD800 << 10) + 0xDC00 - 0x10000);\n                    *index -= 1;\n                }\n            }\n        }\n    }\n\n    return codepoint;\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBCodepoint.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_CODEPOINT_H\n#define _SB_INTERNAL_CODEPOINT_H\n\n#include <SheenBidi/SBCodepoint.h>\n#include <SheenBidi/SBCodepointSequence.h>\n\n#include <API/SBBase.h>\n\nSB_INTERNAL const void *SBCodepointGetBufferOffset(const void *buffer,\n    SBStringEncoding encoding, SBUInteger index);\n\nSB_INTERNAL void SBCodepointSkipToStart(const void *buffer, SBUInteger length,\n    SBStringEncoding encoding, SBUInteger *index);\n\nSB_INTERNAL void SBCodepointSkipToEnd(const void *buffer, SBUInteger length,\n    SBStringEncoding encoding, SBUInteger *index);\n\nSB_INTERNAL SBBoolean SBCodepointIsCanonicalEquivalentBracket(\n    SBCodepoint codepoint, SBCodepoint bracket);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBCodepointSequence.c",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <Data/BidiTypeLookup.h>\n\n#include \"SBCodepointSequence.h\"\n\nSB_INTERNAL SBBoolean SBCodepointSequenceIsValid(const SBCodepointSequence *sequence)\n{\n    if (sequence) {\n        SBBoolean encodingValid = SBFalse;\n\n        switch (sequence->stringEncoding) {\n        case SBStringEncodingUTF8:\n        case SBStringEncodingUTF16:\n        case SBStringEncodingUTF32:\n            encodingValid = SBTrue;\n            break;\n        }\n\n        return (encodingValid && sequence->stringBuffer && sequence->stringLength > 0);\n    }\n\n    return SBFalse;\n}\n\nSB_INTERNAL SBUInteger SBCodepointSequenceGetSeparatorLength(\n    const SBCodepointSequence *sequence, SBUInteger separatorIndex)\n{\n    SBUInteger stringIndex = separatorIndex;\n    SBCodepoint codepoint;\n    SBUInteger separatorLength;\n\n    codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);\n    separatorLength = stringIndex - separatorIndex;\n\n    if (codepoint == '\\r') {\n        /* Don't break in between 'CR' and 'LF'. */\n        if (stringIndex < sequence->stringLength) {\n            codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);\n\n            if (codepoint == '\\n') {\n                separatorLength = stringIndex - separatorIndex;\n            }\n        }\n    }\n\n    return separatorLength;\n}\n\nSB_INTERNAL void SBCodepointSequenceDetermineBidiTypes(\n    const SBCodepointSequence *sequence, SBBidiType *bidiTypes)\n{\n    SBUInteger stringIndex = 0;\n    SBUInteger firstIndex = 0;\n    SBCodepoint codepoint;\n\n    while ((codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex)) != SBCodepointInvalid) {\n        bidiTypes[firstIndex] = LookupBidiType(codepoint);\n\n        /* Subsequent code units get 'BN' type. */\n        while (++firstIndex < stringIndex) {\n            bidiTypes[firstIndex] = SBBidiTypeBN;\n        }\n    }\n}\n\nSB_INTERNAL void SBCodepointSequenceGetParagraphBoundary(\n    const SBCodepointSequence *sequence, const SBBidiType *bidiTypes,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength,\n    SBUInteger *actualLength, SBUInteger *separatorLength)\n{\n    SBUInteger limit = paragraphOffset + suggestedLength;\n    SBUInteger index;\n\n    if (separatorLength) {\n        *separatorLength = 0;\n    }\n\n    for (index = paragraphOffset; index < limit; index++) {\n        SBBidiType currentType = bidiTypes[index];\n\n        if (currentType == SBBidiTypeB) {\n            SBUInteger codeUnitCount = SBCodepointSequenceGetSeparatorLength(sequence, index);\n\n            index += codeUnitCount;\n\n            if (separatorLength) {\n                *separatorLength = codeUnitCount;\n            }\n            break;\n        }\n    }\n\n    if (actualLength) {\n        *actualLength = index - paragraphOffset;\n    }\n}\n\nSBCodepoint SBCodepointSequenceGetCodepointBefore(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    switch (codepointSequence->stringEncoding) {\n    case SBStringEncodingUTF8:\n        codepoint = SBCodepointDecodePreviousFromUTF8(codepointSequence->stringBuffer, codepointSequence->stringLength, stringIndex);\n        break;\n\n    case SBStringEncodingUTF16:\n        codepoint = SBCodepointDecodePreviousFromUTF16(codepointSequence->stringBuffer, codepointSequence->stringLength, stringIndex);\n        break;\n\n    case SBStringEncodingUTF32:\n        if ((*stringIndex - 1) < codepointSequence->stringLength) {\n            const SBUInt32 *buffer = codepointSequence->stringBuffer;\n\n            *stringIndex -= 1;\n            codepoint = buffer[*stringIndex];\n\n            if (!SBCodepointIsValid(codepoint)) {\n                codepoint = SBCodepointFaulty;\n            }\n        }\n        break;\n    }\n\n    return codepoint;\n}\n\nSBCodepoint SBCodepointSequenceGetCodepointAt(const SBCodepointSequence *codepointSequence, SBUInteger *stringIndex)\n{\n    SBCodepoint codepoint = SBCodepointInvalid;\n\n    switch (codepointSequence->stringEncoding) {\n    case SBStringEncodingUTF8:\n        codepoint = SBCodepointDecodeNextFromUTF8(codepointSequence->stringBuffer, codepointSequence->stringLength, stringIndex);\n        break;\n\n    case SBStringEncodingUTF16:\n        codepoint = SBCodepointDecodeNextFromUTF16(codepointSequence->stringBuffer, codepointSequence->stringLength, stringIndex);\n        break;\n\n    case SBStringEncodingUTF32:\n        if (*stringIndex < codepointSequence->stringLength) {\n            const SBUInt32 *buffer = codepointSequence->stringBuffer;\n\n            codepoint = buffer[*stringIndex];\n            *stringIndex += 1;\n\n            if (!SBCodepointIsValid(codepoint)) {\n                codepoint = SBCodepointFaulty;\n            }\n        }\n        break;\n    }\n\n    return codepoint;\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBCodepointSequence.h",
    "content": "/*\n * Copyright (C) 2016-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_CODEPOINT_SEQUENCE_H\n#define _SB_INTERNAL_CODEPOINT_SEQUENCE_H\n\n#include <SheenBidi/SBCodepointSequence.h>\n\n#include <API/SBBase.h>\n\nSB_INTERNAL SBBoolean SBCodepointSequenceIsValid(const SBCodepointSequence *sequence);\n\nSB_INTERNAL SBUInteger SBCodepointSequenceGetSeparatorLength(\n    const SBCodepointSequence *sequence, SBUInteger separatorIndex);\n\nSB_INTERNAL void SBCodepointSequenceDetermineBidiTypes(\n    const SBCodepointSequence *sequence, SBBidiType *bidiTypes);\n\nSB_INTERNAL void SBCodepointSequenceGetParagraphBoundary(\n    const SBCodepointSequence *sequence, const SBBidiType *bidiTypes,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength,\n    SBUInteger *actualLength, SBUInteger *separatorLength);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBLine.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAlgorithm.h>\n#include <API/SBAllocator.h>\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <API/SBParagraph.h>\n#include <Core/Memory.h>\n#include <Core/Object.h>\n\n#include \"SBLine.h\"\n\ntypedef SBLine *SBMutableLineRef;\n\ntypedef struct _LineContext {\n    const SBBidiType *refTypes;\n    SBLevel *fixedLevels;\n    SBUInteger runCount;\n    SBLevel maxLevel;\n} LineContext, *LineContextRef;\n\nstatic SBLevel CopyLevels(SBLevel *destination,\n    const SBLevel *source, SBUInteger length, SBUInteger *runCount);\nstatic void ResetLevels(LineContextRef context, SBLevel baseLevel, SBUInteger charCount);\n\n#define LEVELS       0\n#define COUNT        1\n\nstatic SBBoolean InitializeLineContext(LineContextRef context, MemoryRef memory,\n    const SBBidiType *types, const SBLevel *levels, SBUInteger length, SBLevel baseLevel)\n{\n    SBBoolean isInitialized = SBFalse;\n    void *pointers[COUNT] = { NULL };\n    SBUInteger sizes[COUNT];\n\n    sizes[LEVELS] = sizeof(SBLevel) * length;\n\n    if (MemoryAllocateChunks(memory, MemoryTypeScratch, sizes, COUNT, pointers)) {\n        SBLevel *fixedLevels = pointers[LEVELS];\n\n        context->refTypes = types;\n        context->fixedLevels = fixedLevels;\n        context->maxLevel = CopyLevels(fixedLevels, levels, length, &context->runCount);\n\n        ResetLevels(context, baseLevel, length);\n\n        isInitialized = SBTrue;\n    }\n\n    return isInitialized;\n}\n\n#undef LEVELS\n#undef COUNT\n\n#define LINE  0\n#define RUNS  1\n#define COUNT 2\n\nstatic SBMutableLineRef AllocateLine(SBUInteger runCount)\n{\n    SBMutableLineRef line = NULL;\n\n    if (runCount > 0) {\n        void *pointers[COUNT] = { NULL };\n        SBUInteger sizes[COUNT] = { 0 };\n\n        sizes[LINE] = sizeof(SBLine);\n        sizes[RUNS] = sizeof(SBRun) * runCount;\n\n        line = ObjectCreate(sizes, COUNT, pointers, NULL);\n\n        if (line) {\n            line->fixedRuns = pointers[RUNS];\n        }\n    }\n\n    return line;\n}\n\n#undef LINE\n#undef RUNS\n#undef COUNT\n\nstatic SBLevel CopyLevels(SBLevel *destination,\n    const SBLevel *source, SBUInteger length, SBUInteger *runCount)\n{\n    SBLevel lastLevel = SBLevelInvalid;\n    SBLevel maxLevel = 0;\n    SBUInteger totalRuns = 0;\n    SBUInteger index;\n\n    for (index = 0; index < length; index++) {\n        SBLevel level = source[index];\n        destination[index] = level;\n\n        if (level != lastLevel) {\n            totalRuns += 1;\n\n            if (level > maxLevel) {\n                maxLevel = level;\n            }\n        }\n    }\n\n    *runCount = totalRuns;\n\n    return maxLevel;\n}\n\nstatic void SetNewLevel(SBLevel *levels, SBUInteger length, SBLevel newLevel)\n{\n    SBUInteger index;\n\n    for (index = 0; index < length; index++) {\n        levels[index] = newLevel;\n    }\n}\n\nstatic void ResetLevels(LineContextRef context, SBLevel baseLevel, SBUInteger charCount)\n{\n    const SBBidiType *types = context->refTypes;\n    SBLevel *levels = context->fixedLevels;\n    SBUInteger index;\n    SBUInteger length;\n    SBBoolean reset;\n\n    index = charCount;\n    length = 0;\n    reset = SBTrue;\n\n    while (index--) {\n        SBBidiType type = types[index];\n\n        switch (type) {\n        case SBBidiTypeB:\n        case SBBidiTypeS:\n            SetNewLevel(levels + index, length + 1, baseLevel);\n            length = 0;\n            reset = SBTrue;\n            context->runCount += 1;\n            break;\n\n        case SBBidiTypeLRE:\n        case SBBidiTypeRLE:\n        case SBBidiTypeLRO:\n        case SBBidiTypeRLO:\n        case SBBidiTypePDF:\n        case SBBidiTypeBN:\n            length += 1;\n            break;\n\n        case SBBidiTypeWS:\n        case SBBidiTypeLRI:\n        case SBBidiTypeRLI:\n        case SBBidiTypeFSI:\n        case SBBidiTypePDI:\n            if (reset) {\n                SetNewLevel(levels + index, length + 1, baseLevel);\n                length = 0;\n\n                context->runCount += 1;\n            }\n            break;\n\n        default:\n            length = 0;\n            reset = SBFalse;\n            break;\n        }\n    }\n}\n\nstatic SBUInteger InitializeRuns(SBRun *runs,\n    const SBLevel *levels, SBUInteger length, SBUInteger lineOffset)\n{\n    SBUInteger runIndex = 0;\n    SBUInteger index;\n\n    runs[runIndex].offset = lineOffset;\n    runs[runIndex].level = levels[0];\n\n    for (index = 0; index < length; index++) {\n        SBLevel level = levels[index];\n\n        if (level != runs[runIndex].level) {\n            runs[runIndex].length = index + lineOffset - runs[runIndex].offset;\n\n            runIndex += 1;\n            runs[runIndex].offset = lineOffset + index;\n            runs[runIndex].level = level;\n        }\n    }\n\n    runs[runIndex].length = index + lineOffset - runs[runIndex].offset;\n\n    return runIndex + 1;\n}\n\nstatic void ReverseRunSequence(SBRun *runs, SBUInteger runCount)\n{\n    SBUInteger halfCount = runCount / 2;\n    SBUInteger finalIndex = runCount - 1;\n    SBUInteger index;\n\n    for (index = 0; index < halfCount; index++) {\n        SBUInteger tieIndex;\n        SBRun tempRun;\n\n        tieIndex = finalIndex - index;\n\n        tempRun = runs[index];\n        runs[index] = runs[tieIndex];\n        runs[tieIndex] = tempRun;\n    }\n}\n\nstatic void ReorderRuns(SBRun *runs, SBUInteger runCount, SBLevel maxLevel)\n{\n    SBLevel newLevel;\n\n    for (newLevel = maxLevel; newLevel; newLevel--) {\n        SBUInteger start = runCount;\n\n        while (start--) {\n            if (runs[start].level >= newLevel) {\n                SBUInteger count = 1;\n\n                for (; start && runs[start - 1].level >= newLevel; start--) {\n                    count += 1;\n                }\n\n                ReverseRunSequence(runs + start, count);\n            }\n        }\n    }\n}\n\nSB_INTERNAL SBLineRef SBLineCreate(SBParagraphRef paragraph,\n    SBUInteger lineOffset, SBUInteger lineLength)\n{\n    SBUInteger innerOffset = lineOffset - paragraph->offset;\n    const SBBidiType *refTypes = paragraph->refTypes + innerOffset;\n    const SBLevel *refLevels = paragraph->fixedLevels + innerOffset;\n    SBMutableLineRef line = NULL;\n    Memory memory;\n    LineContext context;\n\n    /* Line range MUST be valid. */\n    SBAssert(lineOffset < (lineOffset + lineLength)\n             && lineOffset >= paragraph->offset\n             && (lineOffset + lineLength) <= (paragraph->offset + paragraph->length));\n\n    MemoryInitialize(&memory);\n\n    if (InitializeLineContext(&context, &memory, refTypes, refLevels, lineLength, paragraph->baseLevel)) {\n        line = AllocateLine(context.runCount);\n\n        if (line) {\n            line->runCount = InitializeRuns(line->fixedRuns, context.fixedLevels, lineLength, lineOffset);\n            ReorderRuns(line->fixedRuns, line->runCount, context.maxLevel);\n\n            line->codepointSequence = paragraph->codepointSequence;\n            line->offset = lineOffset;\n            line->length = lineLength;\n        }\n    }\n\n    MemoryFinalize(&memory);\n    SBAllocatorResetScratch(NULL);\n\n    return line;\n}\n\nSBUInteger SBLineGetOffset(SBLineRef line)\n{\n    return line->offset;\n}\n\nSBUInteger SBLineGetLength(SBLineRef line)\n{\n    return line->length;\n}\n\nSBUInteger SBLineGetRunCount(SBLineRef line)\n{\n    return line->runCount;\n}\n\nconst SBRun *SBLineGetRunsPtr(SBLineRef line)\n{\n    return line->fixedRuns;\n}\n\nSBLineRef SBLineRetain(SBLineRef line)\n{\n    return ObjectRetain((ObjectRef)line);\n}\n\nvoid SBLineRelease(SBLineRef line)\n{\n    ObjectRelease((ObjectRef)line);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBLine.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_LINE_H\n#define _SB_INTERNAL_LINE_H\n\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBLine.h>\n#include <SheenBidi/SBParagraph.h>\n#include <SheenBidi/SBRun.h>\n\n#include <API/SBBase.h>\n#include <Core/Object.h>\n\ntypedef struct _SBLine {\n    ObjectBase _base;\n    SBCodepointSequence codepointSequence;\n    SBRun *fixedRuns;\n    SBUInteger runCount;\n    SBUInteger offset;\n    SBUInteger length;\n} SBLine;\n\nSB_INTERNAL SBLineRef SBLineCreate(SBParagraphRef paragraph,\n    SBUInteger lineOffset, SBUInteger lineLength);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBLog.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#ifdef SB_CONFIG_LOG\n\n#include <API/SBCodepoint.h>\n#include <API/SBCodepointSequence.h>\n#include <UBA/BidiChain.h>\n#include <UBA/IsolatingRun.h>\n#include <UBA/LevelRun.h>\n\n#include \"SBLog.h\"\n\nint _SBLogPosition = 0;\n\nSB_INTERNAL void PrintBaseLevel(SBLevel baseLevel)\n{\n    switch (baseLevel) {\n    case SBLevelDefaultLTR:\n        SB_LOG_STRING(\"Auto-LTR\");\n        break;\n\n    case SBLevelDefaultRTL:\n        SB_LOG_STRING(\"Auto-RTL\");\n        break;\n\n    case 0:\n        SB_LOG_STRING(\"LTR\");\n        break;\n\n    case 1:\n        SB_LOG_STRING(\"RTL\");\n        break;\n\n    default:\n        SB_LOG((\"Level - %d\", baseLevel));\n        break;\n    }\n}\n\nSB_INTERNAL void PrintBidiType(SBBidiType type)\n{\n    switch (type) {\n    case SBBidiTypeNil:\n        SB_LOG_STRING(\"Nil\");\n        break;\n\n    case SBBidiTypeL:\n        SB_LOG_STRING(\"L\");\n        break;\n\n    case SBBidiTypeR:\n        SB_LOG_STRING(\"R\");\n        break;\n\n    case SBBidiTypeAL:\n        SB_LOG_STRING(\"AL\");\n        break;\n\n    case SBBidiTypeEN:\n        SB_LOG_STRING(\"EN\");\n        break;\n\n    case SBBidiTypeES:\n        SB_LOG_STRING(\"ES\");\n        break;\n\n    case SBBidiTypeET:\n        SB_LOG_STRING(\"EN\");\n        break;\n\n    case SBBidiTypeAN:\n        SB_LOG_STRING(\"AN\");\n        break;\n\n    case SBBidiTypeCS:\n        SB_LOG_STRING(\"CS\");\n        break;\n\n    case SBBidiTypeNSM:\n        SB_LOG_STRING(\"NSM\");\n        break;\n\n    case SBBidiTypeBN:\n        SB_LOG_STRING(\"BN\");\n        break;\n\n    case SBBidiTypeB:\n        SB_LOG_STRING(\"B\");\n        break;\n\n    case SBBidiTypeS:\n        SB_LOG_STRING(\"S\");\n        break;\n\n    case SBBidiTypeWS:\n        SB_LOG_STRING(\"WS\");\n        break;\n\n    case SBBidiTypeON:\n        SB_LOG_STRING(\"ON\");\n        break;\n\n    case SBBidiTypeLRE:\n        SB_LOG_STRING(\"LRE\");\n        break;\n\n    case SBBidiTypeRLE:\n        SB_LOG_STRING(\"RLE\");\n        break;\n\n    case SBBidiTypeLRO:\n        SB_LOG_STRING(\"LRO\");\n        break;\n\n    case SBBidiTypeRLO:\n        SB_LOG_STRING(\"RLO\");\n        break;\n\n    case SBBidiTypePDF:\n        SB_LOG_STRING(\"PDF\");\n        break;\n\n    case SBBidiTypeLRI:\n        SB_LOG_STRING(\"LRI\");\n        break;\n\n    case SBBidiTypeRLI:\n        SB_LOG_STRING(\"RLI\");\n        break;\n\n    case SBBidiTypeFSI:\n        SB_LOG_STRING(\"FSI\");\n        break;\n\n    case SBBidiTypePDI:\n        SB_LOG_STRING(\"PDI\");\n        break;\n    }\n}\n\nSB_INTERNAL void PrintCodepointSequence(const SBCodepointSequence *codepointSequence)\n{\n    SBUInteger stringIndex = 0;\n    SBCodepoint codepoint;\n\n    while ((codepoint = SBCodepointSequenceGetCodepointAt(codepointSequence, &stringIndex)) != SBCodepointInvalid) {\n        SB_LOG((\"%04X \", codepoint));\n    }\n}\n\nSB_INTERNAL void PrintBidiTypesArray(SBBidiType *types, SBUInteger length)\n{\n    SBUInteger index;\n\n    for (index = 0; index < length; ++index) {\n        SB_LOG_BIDI_TYPE(types[index]);\n        SB_LOG_DIVIDER(1);\n    }\n}\n\nSB_INTERNAL void PrintLevelsArray(SBLevel *levels, SBUInteger length)\n{\n    SBUInteger index;\n\n    for (index = 0; index < length; ++index) {\n        SB_LOG_LEVEL(levels[index]);\n        SB_LOG_DIVIDER(1);\n    }\n}\n\ntypedef struct {\n    void *object;\n    BidiLink link;\n    SBUInteger length;\n} IsolatingContext;\n\ntypedef void (*IsolatingConsumer)(IsolatingRunRef isolatingRun, IsolatingContext *context);\n\nSB_INTERNAL void IsolatingRunForEach(IsolatingRunRef isolatingRun,\n    IsolatingContext *context, IsolatingConsumer consumer)\n{\n    BidiChainRef bidiChain = isolatingRun->bidiChain;\n    LevelRun *levelRun;\n\n    /* Iterate over individual level runs of the isolating run. */\n    for (levelRun = isolatingRun->baseLevelRun; levelRun; levelRun = levelRun->next) {\n        BidiLink breakLink = BidiChainGetNext(bidiChain, levelRun->lastLink);\n        BidiLink currentLink = levelRun->firstLink;\n        BidiLink subsequentLink = levelRun->subsequentLink;\n\n        /* Iterate over each link of the level run. */\n        while (currentLink != breakLink) {\n            BidiLink nextLink = BidiChainGetNext(bidiChain, currentLink);\n            SBUInteger linkOffset = BidiChainGetOffset(bidiChain, currentLink);\n            SBUInteger linkLength;\n            SBUInteger index;\n\n            if (nextLink != breakLink) {\n                linkLength = BidiChainGetOffset(bidiChain, nextLink) - linkOffset;\n            } else {\n                linkLength = BidiChainGetOffset(bidiChain, subsequentLink) - linkOffset;\n            }\n\n            /* Skip any sequence of BN character types. */\n            for (index = 1; index < linkLength; index++) {\n                SBBidiType bidiType = BidiChainGetType(bidiChain, currentLink + index);\n                if (bidiType == SBBidiTypeBN) {\n                    linkLength = index;\n                    break;\n                }\n            }\n\n            context->link = currentLink;\n            context->length = linkLength;\n            consumer(isolatingRun, context);\n            \n            currentLink = nextLink;\n        }\n    }\n}\n\nstatic void PrintTypesOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)\n{\n    SBBidiType bidiType = BidiChainGetType(isolatingRun->bidiChain, context->link);\n\n    while (context->length--) {\n        SB_LOG_BIDI_TYPE(bidiType);\n        SB_LOG_DIVIDER(1);\n    }\n}\n\nSB_INTERNAL void PrintRunTypes(IsolatingRunRef isolatingRun)\n{\n    IsolatingContext context;\n    IsolatingRunForEach(isolatingRun, &context, PrintTypesOperation);\n}\n\nstatic void PrintLevelsOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)\n{\n    SBLevel charLevel = BidiChainGetLevel(isolatingRun->bidiChain, context->link);\n\n    while (context->length--) {\n        SB_LOG_LEVEL(charLevel);\n        SB_LOG_DIVIDER(1);\n    }\n}\n\nSB_INTERNAL void PrintRunLevels(IsolatingRunRef isolatingRun)\n{\n    IsolatingContext context;\n    IsolatingRunForEach(isolatingRun, &context, PrintLevelsOperation);\n}\n\ntypedef struct {\n    SBUInteger offset;\n    SBUInteger length;\n} IsolatingRange;\n\nstatic void PrintRangeOperation(IsolatingRunRef isolatingRun, IsolatingContext *context)\n{\n    IsolatingRange *range = context->object;\n    SBUInteger offset = BidiChainGetOffset(isolatingRun->bidiChain, context->link);\n\n    if (range->length == 0) {\n        range->offset = offset;\n        range->length = context->length;\n    } else if (offset == (range->offset + range->length)) {\n        range->length += context->length;\n    } else {\n        SB_LOG_RANGE(range->offset, range->length);\n        SB_LOG_DIVIDER(1);\n\n        range->offset = offset;\n        range->length = context->length;\n    }\n}\n\nSB_INTERNAL void PrintRunRange(IsolatingRunRef isolatingRun)\n{\n    IsolatingRange range = { 0, 0 };\n    IsolatingContext context;\n    context.object = &range;\n\n    IsolatingRunForEach(isolatingRun, &context, PrintRangeOperation);\n    SB_LOG_RANGE(range.offset, range.length);\n    SB_LOG_DIVIDER(1);\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBLog.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_LOG_H\n#define _SB_INTERNAL_LOG_H\n\n#include <API/SBBase.h>\n\n#ifdef SB_CONFIG_LOG\n\n#include <stdio.h>\n\n#include <API/SBCodepointSequence.h>\n#include <UBA/IsolatingRun.h>\n\nSB_INTERNAL void PrintBaseLevel(SBLevel baseLevel);\nSB_INTERNAL void PrintBidiType(SBBidiType type);\n\nSB_INTERNAL void PrintCodepointSequence(const SBCodepointSequence *codepointSequence);\nSB_INTERNAL void PrintBidiTypesArray(SBBidiType *types, SBUInteger length);\nSB_INTERNAL void PrintLevelsArray(SBLevel *levels, SBUInteger length);\n\nSB_INTERNAL void PrintRunTypes(IsolatingRunRef isolatingRun);\nSB_INTERNAL void PrintRunLevels(IsolatingRunRef isolatingRun);\nSB_INTERNAL void PrintRunRange(IsolatingRunRef isolatingRun);\n\nextern int _SBLogPosition;\n\n#define SB_LOG_BEGIN()                  (++_SBLogPosition)\n#define SB_LOG_END()                    (--_SBLogPosition)\n\n#define SB_LOG(s)                       printf s\n\n#define SB_LOG_NUMBER(n)                \\\nSB_LOG((\"%ld\", (long)n))\n\n#define SB_LOG_RANGE(o, l)              \\\nSB_LOG((\"[%ld, %ld]\", (long)o, (long)(o + l - 1)))\n\n#define SB_LOG_CHAR(c)                  \\\nSBLOG((\"%c\", c))\n\n#define SB_LOG_STRING(s)                \\\nSB_LOG((\"%s\", s))\n\n#define SB_LOG_LEVEL(l)                 \\\nSB_LOG_NUMBER(l)\n\n#define SB_LOG_BREAKER()                \\\nSB_LOG((\"\\n\"))\n\n#define SB_LOG_DIVIDER(n)               \\\nSB_LOG((\"%.*s\", n, \"\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\"))\n\n#define SB_LOG_INITIATOR()              \\\nSB_LOG_DIVIDER(_SBLogPosition)\n\n#define SB_LOG_CAPTION(c)               \\\nSB_LOG((c\":\"))\n\n#define SB_LOG_STATEMENT_TEXT(t)        \\\n(t)\n\n#define SB_LOG_LINE(s)                  \\\ndo {                                    \\\n    SB_LOG(s);                          \\\n    SB_LOG_BREAKER();                   \\\n} while (0)\n\n#define SB_LOG_STATEMENT(c, d, t)       \\\ndo {                                    \\\n    SB_LOG_INITIATOR();                 \\\n    SB_LOG_CAPTION(c);                  \\\n    SB_LOG_DIVIDER(d);                  \\\n    SB_LOG_STATEMENT_TEXT(t);           \\\n    SB_LOG_BREAKER();                   \\\n} while (0)\n\n#define SB_LOG_BLOCK_OPENER(c)          \\\ndo {                                    \\\n    SB_LOG_INITIATOR();                 \\\n    SB_LOG_CAPTION(c);                  \\\n    SB_LOG_BREAKER();                   \\\n    SB_LOG_BEGIN();                     \\\n} while (0)\n\n#define SB_LOG_BLOCK_CLOSER()           SB_LOG_END()\n\n#define SB_LOG_BASE_LEVEL(l)            PrintBaseLevel(l)\n#define SB_LOG_BIDI_TYPE(t)             PrintBidiType(t)\n\n#define SB_LOG_CODEPOINT_SEQUENCE(s)    PrintCodepointSequence(s)\n#define SB_LOG_BIDI_TYPES_ARRAY(a, l)   PrintBidiTypesArray(a, l)\n#define SB_LOG_LEVELS_ARRAY(a, l)       PrintLevelsArray(a, l)\n\n#define SB_LOG_RUN_TYPES(r)             PrintRunTypes(r)\n#define SB_LOG_RUN_LEVELS(r)            PrintRunLevels(r)\n#define SB_LOG_RUN_RANGE(r)             PrintRunRange(r)\n\n#else\n\n#define SB_LOG_NONE()\n\n#define SB_LOG(s)                       SB_LOG_NONE()\n\n#define SB_LOG_NUMBER(n)                SB_LOG_NONE()\n#define SB_LOG_RANGE(o, l)              SB_LOG_NONE()\n#define SB_LOG_CHAR(c)                  SB_LOG_NONE()\n#define SB_LOG_STRING(s)                SB_LOG_NONE()\n#define SB_LOG_LEVEL(l)                 SB_LOG_NONE()\n\n#define SB_LOG_BREAKER()                SB_LOG_NONE()\n#define SB_LOG_DIVIDER(n)               SB_LOG_NONE()\n#define SB_LOG_INITIATOR()              SB_LOG_NONE()\n#define SB_LOG_CAPTION(c)               SB_LOG_NONE()\n#define SB_LOG_STATEMENT_TEXT(t)        SB_LOG_NONE()\n\n#define SB_LOG_LINE(s)                  SB_LOG_NONE()\n#define SB_LOG_STATEMENT(c, d, t)       SB_LOG_NONE()\n\n#define SB_LOG_BLOCK_OPENER(c)          SB_LOG_NONE()\n#define SB_LOG_BLOCK_CLOSER()           SB_LOG_NONE()\n\n#define SB_LOG_BASE_LEVEL(l)            SB_LOG_NONE()\n#define SB_LOG_BIDI_TYPE(t)             SB_LOG_NONE()\n\n#define SB_LOG_CODEPOINT_SEQUENCE(s)    SB_LOG_NONE()\n#define SB_LOG_BIDI_TYPES_ARRAY(a, l)   SB_LOG_NONE()\n#define SB_LOG_LEVELS_ARRAY(a, l)       SB_LOG_NONE()\n\n#define SB_LOG_RUN_TYPES(r)             SB_LOG_NONE()\n#define SB_LOG_RUN_LEVELS(r)            SB_LOG_NONE()\n\n#define SB_LOG_RUN_RANGE(r)             SB_LOG_NONE()\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBMirrorLocator.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <API/SBLine.h>\n#include <Core/Object.h>\n#include <Data/PairingLookup.h>\n\n#include \"SBMirrorLocator.h\"\n\nstatic void FinalizeMirrorLocator(ObjectRef object)\n{\n    SBMirrorLocatorRef locator = object;\n    SBLineRelease(locator->_line);\n}\n\nSBMirrorLocatorRef SBMirrorLocatorCreate(void)\n{\n    const SBUInteger size = sizeof(SBMirrorLocator);\n    void *pointer = NULL;\n    SBMirrorLocatorRef locator;\n\n    locator = ObjectCreate(&size, 1, &pointer, &FinalizeMirrorLocator);\n\n    if (locator) {\n        locator->_line = NULL;\n        SBMirrorLocatorReset(locator);\n    }\n\n    return locator;\n}\n\nvoid SBMirrorLocatorLoadLine(SBMirrorLocatorRef locator, SBLineRef line, const void *stringBuffer)\n{\n    if (locator->_line) {\n        SBLineRelease(locator->_line);\n        locator->_line = NULL;\n    }\n\n    if (line && stringBuffer == line->codepointSequence.stringBuffer) {\n        locator->_line = SBLineRetain(line);\n    }\n\n    SBMirrorLocatorReset(locator);\n}\n\nconst SBMirrorAgent *SBMirrorLocatorGetAgent(SBMirrorLocatorRef locator)\n{\n    return &locator->agent;\n}\n\nSBBoolean SBMirrorLocatorMoveNext(SBMirrorLocatorRef locator)\n{\n    SBLineRef line = locator->_line;\n\n    if (line) {\n        const SBCodepointSequence *sequence = &line->codepointSequence;\n\n        do {\n            const SBRun *run = &line->fixedRuns[locator->_runIndex];\n\n            if (run->level & 1) {\n                SBUInteger stringIndex;\n                SBUInteger stringLimit;\n\n                stringIndex = locator->_stringIndex;\n                if (stringIndex == SBInvalidIndex) {\n                    stringIndex = run->offset;\n                }\n                stringLimit = run->offset + run->length;\n\n                while (stringIndex < stringLimit) {\n                    SBUInteger initialIndex = stringIndex;\n                    SBCodepoint codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);\n                    SBCodepoint mirror = LookupMirror(codepoint);\n\n                    if (mirror) {\n                        locator->_stringIndex = stringIndex;\n                        locator->agent.index = initialIndex;\n                        locator->agent.mirror = mirror;\n                        locator->agent.codepoint = codepoint;\n\n                        return SBTrue;\n                    }\n                }\n            }\n            \n            locator->_stringIndex = SBInvalidIndex;\n        } while (++locator->_runIndex < line->runCount);\n        \n        SBMirrorLocatorReset(locator);\n    }\n    \n    return SBFalse;\n}\n\nvoid SBMirrorLocatorReset(SBMirrorLocatorRef locator)\n{\n    locator->_runIndex = 0;\n    locator->_stringIndex = SBInvalidIndex;\n    locator->agent.index = SBInvalidIndex;\n    locator->agent.mirror = 0;\n}\n\nSBMirrorLocatorRef SBMirrorLocatorRetain(SBMirrorLocatorRef locator)\n{\n    return ObjectRetain((ObjectRef)locator);\n}\n\nvoid SBMirrorLocatorRelease(SBMirrorLocatorRef locator)\n{\n    ObjectRelease((ObjectRef)locator);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBMirrorLocator.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_MIRROR_LOCATOR_H\n#define _SB_INTERNAL_MIRROR_LOCATOR_H\n\n#include <SheenBidi/SBLine.h>\n#include <SheenBidi/SBMirrorLocator.h>\n\n#include <API/SBBase.h>\n#include <Core/Object.h>\n\ntypedef struct _SBMirrorLocator {\n    ObjectBase _base;\n    SBLineRef _line;\n    SBUInteger _runIndex;\n    SBUInteger _stringIndex;\n    SBMirrorAgent agent;\n} SBMirrorLocator;\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBParagraph.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n#include <stddef.h>\n\n#include <API/SBAlgorithm.h>\n#include <API/SBAllocator.h>\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <API/SBCodepointSequence.h>\n#include <API/SBLine.h>\n#include <API/SBLog.h>\n#include <Core/Memory.h>\n#include <Core/Object.h>\n#include <UBA/BidiChain.h>\n#include <UBA/IsolatingRun.h>\n#include <UBA/LevelRun.h>\n#include <UBA/RunQueue.h>\n#include <UBA/StatusStack.h>\n\n#include \"SBParagraph.h\"\n\ntypedef SBParagraph *SBMutableParagraphRef;\n\ntypedef struct _ParagraphContext {\n    BidiChain bidiChain;\n    StatusStack statusStack;\n    RunQueue runQueue;\n    IsolatingRun isolatingRun;\n} ParagraphContext, *ParagraphContextRef;\n\nstatic void PopulateBidiChain(BidiChainRef chain, const SBBidiType *types, SBUInteger length);\nstatic SBBoolean ProcessRun(ParagraphContextRef context, const LevelRun *levelRun, SBBoolean resolveIsolatingRuns);\nstatic void FinalizeParagraph(ObjectRef object);\n\n#define BIDI_LINKS        0\n#define BIDI_TYPES        1\n#define BIDI_FLAGS        2\n#define COUNT             3\n\nstatic SBBoolean InitializeParagraphContext(ParagraphContextRef context, MemoryRef memory,\n    const SBBidiType *types, SBLevel *levels, SBUInteger length)\n{\n    SBBoolean isInitialized = SBFalse;\n    void *pointers[COUNT] = { NULL };\n    SBUInteger sizes[COUNT];\n\n    sizes[BIDI_LINKS] = sizeof(BidiLink) * (length + 2);\n    sizes[BIDI_TYPES] = sizeof(SBBidiType) * (length + 2);\n    sizes[BIDI_FLAGS] = sizeof(BidiFlag) * (length + 2);\n\n    if (MemoryAllocateChunks(memory, MemoryTypeScratch, sizes, COUNT, pointers)) {\n        BidiLink *fixedLinks = pointers[BIDI_LINKS];\n        SBBidiType *fixedTypes = pointers[BIDI_TYPES];\n        BidiFlag *fixedFlags = pointers[BIDI_FLAGS];\n\n        BidiChainInitialize(&context->bidiChain, fixedTypes, levels, fixedFlags, fixedLinks);\n        StatusStackInitialize(&context->statusStack, memory);\n        RunQueueInitialize(&context->runQueue, memory);\n        IsolatingRunInitialize(&context->isolatingRun, memory);\n\n        PopulateBidiChain(&context->bidiChain, types, length);\n\n        isInitialized = SBTrue;\n    }\n\n    return isInitialized;\n}\n\n#undef BIDI_LINKS\n#undef BIDI_TYPES\n#undef BIDI_FLAGS\n#undef COUNT\n\n#define PARAGRAPH 0\n#define LEVELS    1\n#define COUNT     2\n\nstatic SBMutableParagraphRef AllocateParagraph(SBUInteger length)\n{\n    void *pointers[COUNT] = { NULL };\n    SBUInteger sizes[COUNT] = { 0 };\n    SBMutableParagraphRef paragraph;\n\n    sizes[PARAGRAPH] = sizeof(SBParagraph);\n    sizes[LEVELS]    = sizeof(SBLevel) * (length + 2);\n\n    paragraph = ObjectCreate(sizes, COUNT, pointers, FinalizeParagraph);\n\n    if (paragraph) {\n        paragraph->fixedLevels = pointers[LEVELS];\n    }\n\n    return paragraph;\n}\n\n#undef PARAGRAPH\n#undef LEVELS\n#undef COUNT\n\nstatic void FinalizeParagraph(ObjectRef object)\n{\n    SBParagraphRef paragraph = object;\n    SBAlgorithmRef algorithm;\n\n    algorithm = paragraph->_algorithm;\n\n    if (algorithm) {\n        SBAlgorithmRelease(algorithm);\n    }\n}\n\nstatic SBUInteger DetermineBoundary(const SBCodepointSequence *codepointSequence,\n    const SBBidiType *bidiTypes, SBUInteger paragraphOffset, SBUInteger suggestedLength)\n{\n    SBUInteger suggestedLimit = paragraphOffset + suggestedLength;\n    SBUInteger stringIndex;\n\n    for (stringIndex = paragraphOffset; stringIndex < suggestedLimit; stringIndex++) {\n        if (bidiTypes[stringIndex] == SBBidiTypeB) {\n            stringIndex += SBCodepointSequenceGetSeparatorLength(codepointSequence, stringIndex);\n            goto Return;\n        }\n    }\n\nReturn:\n    return (stringIndex - paragraphOffset);\n}\n\nstatic void PopulateBidiChain(BidiChainRef chain, const SBBidiType *types, SBUInteger length)\n{\n    SBBidiType type = SBBidiTypeNil;\n    SBUInteger priorIndex = SBInvalidIndex;\n    SBUInteger index;\n\n    for (index = 0; index < length; index++) {\n        SBBidiType priorType = type;\n        type = types[index];\n\n        switch (type) {\n        case SBBidiTypeB:\n        case SBBidiTypeON:\n        case SBBidiTypeLRE:\n        case SBBidiTypeRLE:\n        case SBBidiTypeLRO:\n        case SBBidiTypeRLO:\n        case SBBidiTypePDF:\n        case SBBidiTypeLRI:\n        case SBBidiTypeRLI:\n        case SBBidiTypeFSI:\n        case SBBidiTypePDI:\n            BidiChainAdd(chain, type, index - priorIndex);\n            priorIndex = index;\n\n            if (type == SBBidiTypeB) {\n                index = length;\n                goto AddLast;\n            }\n            break;\n\n        default:\n            if (type != priorType) {\n                BidiChainAdd(chain, type, index - priorIndex);\n                priorIndex = index;\n            }\n            break;\n        }\n    }\n\nAddLast:\n    BidiChainAdd(chain, SBBidiTypeNil, index - priorIndex);\n}\n\nstatic BidiLink SkipIsolatingRun(BidiChainRef chain, BidiLink skipLink, BidiLink breakLink)\n{\n    BidiLink link = skipLink;\n    SBUInteger depth = 1;\n\n    while ((link = BidiChainGetNext(chain, link)) != breakLink) {\n        SBBidiType type = BidiChainGetType(chain, link);\n\n        switch (type) {\n        case SBBidiTypeLRI:\n        case SBBidiTypeRLI:\n        case SBBidiTypeFSI:\n            depth += 1;\n            break;\n\n        case SBBidiTypePDI:\n            if (--depth == 0) {\n                return link;\n            }\n            break;\n        }\n    }\n\n    return BidiLinkNone;\n}\n\nstatic SBLevel DetermineBaseLevel(BidiChainRef chain, BidiLink skipLink, BidiLink breakLink, SBLevel defaultLevel, SBBoolean isIsolate)\n{\n    BidiLink link = skipLink;\n\n    /* Rules P2, P3 */\n    while ((link = BidiChainGetNext(chain, link)) != breakLink) {\n        SBBidiType type = BidiChainGetType(chain, link);\n\n        switch (type) {\n        case SBBidiTypeL:\n            return 0;\n\n        case SBBidiTypeAL:\n        case SBBidiTypeR:\n            return 1;\n\n        case SBBidiTypeLRI:\n        case SBBidiTypeRLI:\n        case SBBidiTypeFSI:\n            link = SkipIsolatingRun(chain, link, breakLink);\n            if (link == BidiLinkNone) {\n                goto Default;\n            }\n            break;\n\n        case SBBidiTypePDI:\n            if (isIsolate) {\n                /*\n                 * In case of isolating run, the PDI will be the last code point.\n                 * NOTE:\n                 *      The inner isolating runs will be skipped by the case above this one.\n                 */\n                goto Default;\n            }\n            break;\n        }\n    }\n\nDefault:\n    return defaultLevel;\n}\n\nstatic SBLevel DetermineParagraphLevel(BidiChainRef chain, SBLevel baseLevel)\n{\n    if (baseLevel >= SBLevelMax) {\n        return DetermineBaseLevel(chain, chain->roller, chain->roller,\n                                  (baseLevel != SBLevelDefaultRTL ? 0 : 1),\n                                  SBFalse);\n    }\n\n    return baseLevel;\n}\n\nstatic SBBoolean DetermineLevels(ParagraphContextRef context, SBLevel baseLevel)\n{\n    BidiChainRef chain = &context->bidiChain;\n    StatusStackRef stack = &context->statusStack;\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    BidiLink priorLink;\n    BidiLink firstLink;\n    BidiLink lastLink;\n\n    SBLevel priorLevel;\n    SBBidiType sor;\n    SBBidiType eor;\n\n    SBUInteger overIsolate;\n    SBUInteger overEmbedding;\n    SBUInteger validIsolate;\n\n    priorLink = chain->roller;\n    firstLink = BidiLinkNone;\n    lastLink = BidiLinkNone;\n\n    priorLevel = baseLevel;\n    sor = SBBidiTypeNil;\n\n    /* Rule X1 */\n    overIsolate = 0;\n    overEmbedding = 0;\n    validIsolate = 0;\n\n    StatusStackPush(stack, baseLevel, SBBidiTypeON, SBFalse);\n\n    BidiChainForEach(chain, roller, link) {\n        SBBoolean forceFinish = SBFalse;\n        SBBoolean bnEquivalent = SBFalse;\n        SBBidiType type;\n\n        type = BidiChainGetType(chain, link);\n\n#define LeastGreaterOddLevel()                                              \\\n(                                                                           \\\n        (StatusStackGetEmbeddingLevel(stack) + 1) | 1                       \\\n)\n\n#define LeastGreaterEvenLevel()                                             \\\n(                                                                           \\\n        (StatusStackGetEmbeddingLevel(stack) + 2) & ~1                      \\\n)\n\n#define MergeLinkIfNeeded()                                                 \\\n{                                                                           \\\n        if (BidiChainMergeNext(chain, priorLink)) {                         \\\n            continue;                                                       \\\n        }                                                                   \\\n}\n\n#define PushEmbedding(l, o)                                                 \\\n{                                                                           \\\n        SBLevel newLevel = l;                                               \\\n                                                                            \\\n        bnEquivalent = SBTrue;                                              \\\n                                                                            \\\n        if (newLevel <= SBLevelMax && !overIsolate && !overEmbedding) {     \\\n            if (!StatusStackPush(stack, newLevel, o, SBFalse)) {            \\\n                return SBFalse;                                             \\\n            }                                                               \\\n        } else {                                                            \\\n            if (!overIsolate) {                                             \\\n                overEmbedding += 1;                                         \\\n            }                                                               \\\n        }                                                                   \\\n}\n\n#define PushIsolate(l, o)                                                   \\\n{                                                                           \\\n        SBBidiType priorStatus = StatusStackGetOverrideStatus(stack);       \\\n        SBLevel newLevel = l;                                               \\\n                                                                            \\\n        BidiChainSetLevel(chain, link,                                      \\\n                          StatusStackGetEmbeddingLevel(stack));             \\\n                                                                            \\\n        if (newLevel <= SBLevelMax && !overIsolate && !overEmbedding) {     \\\n            validIsolate += 1;                                              \\\n                                                                            \\\n            if (!StatusStackPush(stack, newLevel, o, SBTrue)) {             \\\n                return SBFalse;                                             \\\n            }                                                               \\\n        } else {                                                            \\\n            overIsolate += 1;                                               \\\n        }                                                                   \\\n                                                                            \\\n        if (priorStatus != SBBidiTypeON) {                                  \\\n            BidiChainSetType(chain, link, priorStatus);                     \\\n            MergeLinkIfNeeded();                                            \\\n        }                                                                   \\\n}\n\n        switch (type) {\n        /* Rule X2 */\n        case SBBidiTypeRLE:\n            PushEmbedding(LeastGreaterOddLevel(), SBBidiTypeON);\n            break;\n\n        /* Rule X3 */\n        case SBBidiTypeLRE:\n            PushEmbedding(LeastGreaterEvenLevel(), SBBidiTypeON);\n            break;\n\n        /* Rule X4 */\n        case SBBidiTypeRLO:\n            PushEmbedding(LeastGreaterOddLevel(), SBBidiTypeR);\n            break;\n\n        /* Rule X5 */\n        case SBBidiTypeLRO:\n            PushEmbedding(LeastGreaterEvenLevel(), SBBidiTypeL);\n            break;\n\n        /* Rule X5a */\n        case SBBidiTypeRLI:\n            PushIsolate(LeastGreaterOddLevel(), SBBidiTypeON);\n            break;\n\n        /* Rule X5b */\n        case SBBidiTypeLRI:\n            PushIsolate(LeastGreaterEvenLevel(), SBBidiTypeON);\n            break;\n\n        /* Rule X5c */\n        case SBBidiTypeFSI:\n        {\n            SBBoolean isRTL = (DetermineBaseLevel(chain, link, roller, 0, SBTrue) == 1);\n            PushIsolate(isRTL ? LeastGreaterOddLevel() : LeastGreaterEvenLevel(), SBBidiTypeON);\n            break;\n        }\n\n        /* Rule X6 */\n        default:\n            BidiChainSetLevel(chain, link, StatusStackGetEmbeddingLevel(stack));\n\n            if (StatusStackGetOverrideStatus(stack) != SBBidiTypeON) {\n                BidiChainSetType(chain, link, StatusStackGetOverrideStatus(stack));\n                MergeLinkIfNeeded();\n            }\n            break;\n\n        /* Rule X6a */\n        case SBBidiTypePDI:\n        {\n            SBBidiType overrideStatus;\n\n            if (overIsolate != 0) {\n                overIsolate -= 1;\n            } else if (validIsolate == 0) {\n                /* Do nothing */\n            } else {\n                overEmbedding = 0;\n\n                while (!StatusStackGetIsolateStatus(stack)) {\n                    StatusStackPop(stack);\n                }\n                StatusStackPop(stack);\n\n                validIsolate -= 1;\n            }\n\n            BidiChainSetLevel(chain, link, StatusStackGetEmbeddingLevel(stack));\n            overrideStatus = StatusStackGetOverrideStatus(stack);\n\n            if (overrideStatus != SBBidiTypeON) {\n                BidiChainSetType(chain, link, overrideStatus);\n                MergeLinkIfNeeded();\n            }\n            break;\n        }\n\n        /* Rule X7 */\n        case SBBidiTypePDF:\n            bnEquivalent = SBTrue;\n\n            if (overIsolate != 0) {\n                /* Do nothing */\n            } else if (overEmbedding != 0) {\n                overEmbedding -= 1;\n            } else if (!StatusStackGetIsolateStatus(stack) && stack->count >= 2) {\n                StatusStackPop(stack);\n            }\n            break;\n\n        /* Rule X8 */\n        case SBBidiTypeB:\n            /*\n             * These values are reset for clarity, in this implementation B can only occur as the\n             * last code in the array.\n             */\n            StatusStackSetEmpty(stack);\n            StatusStackPush(stack, baseLevel, SBBidiTypeON, SBFalse);\n\n            overIsolate = 0;\n            overEmbedding = 0;\n            validIsolate = 0;\n\n            BidiChainSetLevel(chain, link, baseLevel);\n            break;\n\n        case SBBidiTypeBN:\n            bnEquivalent = SBTrue;\n            break;\n\n        case SBBidiTypeNil:\n            forceFinish = SBTrue;\n            BidiChainSetLevel(chain, link, baseLevel);\n            break;\n        }\n\n        /* Rule X9 */\n        if (bnEquivalent) {\n            /* The type of this link is BN equivalent, so abandon it and continue the loop. */\n            BidiChainAbandonNext(chain, priorLink);\n            continue;\n        }\n\n        if (sor == SBBidiTypeNil) {\n            sor = SBLevelAsNormalBidiType(SBNumberGetMax(baseLevel, BidiChainGetLevel(chain, link)));\n            firstLink = link;\n            priorLevel = BidiChainGetLevel(chain, link);\n        } else if (priorLevel != BidiChainGetLevel(chain, link) || forceFinish) {\n            LevelRun levelRun;\n            SBLevel currentLevel;\n\n            /* Since the level has changed at this link, therefore the run must end at prior link. */\n            lastLink = priorLink;\n\n            /* Save the current level i.e. level of the next run. */\n            currentLevel = BidiChainGetLevel(chain, link);\n            /*\n             * Now we have both the prior level and the current level i.e. unchanged levels of both\n             * the current run and the next run. So, identify eor of the current run.\n             * NOTE:\n             *      sor of the run has been already determined at this stage.\n             */\n            eor = SBLevelAsNormalBidiType(SBNumberGetMax(priorLevel, currentLevel));\n\n            LevelRunInitialize(&levelRun, chain, firstLink, lastLink, sor, eor);\n\n            if (!ProcessRun(context, &levelRun, forceFinish)) {\n                return SBFalse;\n            }\n\n            /* The sor of next run (if any) should be technically equal to eor of this run. */\n            sor = eor;\n            /* The next run (if any) will start from this index. */\n            firstLink = link;\n\n            priorLevel = currentLevel;\n        }\n\n        priorLink = link;\n    }\n\n    return SBTrue;\n}\n\nstatic SBBoolean ProcessRun(ParagraphContextRef context, const LevelRun *levelRun, SBBoolean resolveIsolatingRuns)\n{\n    RunQueueRef queue = &context->runQueue;\n\n    if (!RunQueueEnqueue(queue, levelRun)) {\n        return SBFalse;\n    }\n\n    if (resolveIsolatingRuns) {\n        IsolatingRunRef isolatingRun = &context->isolatingRun;\n\n        /* Rule X10 */\n        for (; queue->count > 0; RunQueueDequeue(queue)) {\n            const LevelRun *front = RunQueueGetFront(queue);\n\n            if (RunKindIsAttachedTerminating(front->kind)) {\n                continue;\n            }\n\n            isolatingRun->baseLevelRun = front;\n\n            if (!IsolatingRunResolve(isolatingRun)) {\n                return SBFalse;\n            }\n        }\n    }\n\n    return SBTrue;\n}\n\nstatic void SaveLevels(BidiChainRef chain, SBLevel *levels, SBLevel baseLevel)\n{\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    SBUInteger index = 0;\n    SBLevel level = baseLevel;\n\n    BidiChainForEach(chain, roller, link) {\n        SBUInteger offset = BidiChainGetOffset(chain, link);\n\n        for (; index < offset; index++) {\n            levels[index] = level;\n        }\n\n        level = BidiChainGetLevel(chain, link);\n    }\n}\n\nstatic SBBoolean ResolveParagraph(SBMutableParagraphRef paragraph, MemoryRef memory,\n    const SBCodepointSequence *codepointSequence, const SBBidiType *refBidiTypes,\n    SBUInteger offset, SBUInteger length, SBLevel baseLevel)\n{\n    const SBBidiType *bidiTypes = &refBidiTypes[offset];\n    SBBoolean isSucceeded = SBFalse;\n    ParagraphContext context;\n\n    if (InitializeParagraphContext(&context, memory, bidiTypes, paragraph->fixedLevels, length)) {\n        SBLevel resolvedLevel = DetermineParagraphLevel(&context.bidiChain, baseLevel);\n\n        SB_LOG_BLOCK_OPENER(\"Determined Paragraph Level\");\n        SB_LOG_STATEMENT(\"Base Level\", 1, SB_LOG_LEVEL(resolvedLevel));\n        SB_LOG_BLOCK_CLOSER();\n\n        context.isolatingRun.codepointSequence = codepointSequence;\n        context.isolatingRun.bidiTypes = bidiTypes;\n        context.isolatingRun.bidiChain = &context.bidiChain;\n        context.isolatingRun.paragraphOffset = offset;\n        context.isolatingRun.paragraphLevel = resolvedLevel;\n\n        if (DetermineLevels(&context, resolvedLevel)) {\n            SaveLevels(&context.bidiChain, paragraph->fixedLevels, resolvedLevel);\n\n            SB_LOG_BLOCK_OPENER(\"Determined Embedding Levels\");\n            SB_LOG_STATEMENT(\"Levels\", 1, SB_LOG_LEVELS_ARRAY(paragraph->fixedLevels, length));\n            SB_LOG_BLOCK_CLOSER();\n\n            paragraph->codepointSequence = *codepointSequence;\n            paragraph->refTypes = bidiTypes;\n            paragraph->offset = offset;\n            paragraph->length = length;\n            paragraph->baseLevel = resolvedLevel;\n\n            isSucceeded = SBTrue;\n        }\n    }\n\n    return isSucceeded;\n}\n\nstatic SBParagraphRef CreateParagraph(SBAlgorithmRef algorithm,\n    const SBCodepointSequence *codepointSequence, const SBBidiType *refBidiTypes,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)\n{\n    SBUInteger actualLength;\n    SBMutableParagraphRef paragraph;\n\n    if (algorithm) {\n        codepointSequence = &algorithm->codepointSequence;\n        refBidiTypes = algorithm->fixedTypes;\n    }\n\n    SB_LOG_BLOCK_OPENER(\"Paragraph Input\");\n    SB_LOG_STATEMENT(\"Paragraph Offset\", 1, SB_LOG_NUMBER(paragraphOffset));\n    SB_LOG_STATEMENT(\"Suggested Length\", 1, SB_LOG_NUMBER(suggestedLength));\n    SB_LOG_STATEMENT(\"Base Direction\",   1, SB_LOG_BASE_LEVEL(baseLevel));\n    SB_LOG_BLOCK_CLOSER();\n\n    actualLength = DetermineBoundary(codepointSequence, refBidiTypes, paragraphOffset, suggestedLength);\n\n    SB_LOG_BLOCK_OPENER(\"Determined Paragraph Boundary\");\n    SB_LOG_STATEMENT(\"Actual Length\", 1, SB_LOG_NUMBER(actualLength));\n    SB_LOG_BLOCK_CLOSER();\n\n    paragraph = AllocateParagraph(actualLength);\n\n    if (paragraph) {\n        SBBoolean isResolved;\n        Memory memory;\n\n        MemoryInitialize(&memory);\n        isResolved = ResolveParagraph(\n            paragraph, &memory, codepointSequence, refBidiTypes,\n            paragraphOffset, actualLength, baseLevel\n        );\n\n        if (isResolved) {\n            paragraph->_algorithm = (algorithm ? SBAlgorithmRetain(algorithm) : NULL);\n        } else {\n            ObjectRelease(paragraph);\n            paragraph = NULL;\n        }\n\n        MemoryFinalize(&memory);\n        SBAllocatorResetScratch(NULL);\n    }\n\n    SB_LOG_BREAKER();\n\n    return paragraph;\n}\n\nSB_INTERNAL SBParagraphRef SBParagraphCreateWithAlgorithm(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)\n{\n    SBUInteger stringLength = algorithm->codepointSequence.stringLength;\n\n    /* The specified range MUST be valid */\n    SBAssert(SBUIntegerVerifyRange(stringLength, paragraphOffset, suggestedLength) && suggestedLength > 0);\n\n    return CreateParagraph(algorithm, NULL, NULL, paragraphOffset, suggestedLength, baseLevel);\n}\n\nSB_INTERNAL SBParagraphRef SBParagraphCreateWithCodepointSequence(\n    const SBCodepointSequence *codepointSequence, const SBBidiType *refBidiTypes,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel)\n{\n    SBUInteger stringLength = codepointSequence->stringLength;\n\n    /* The specified range MUST be valid */\n    SBAssert(SBUIntegerVerifyRange(stringLength, paragraphOffset, suggestedLength) && suggestedLength > 0);\n\n    return CreateParagraph(NULL, codepointSequence, refBidiTypes, paragraphOffset, suggestedLength, baseLevel);\n}\n\nSBUInteger SBParagraphGetOffset(SBParagraphRef paragraph)\n{\n    return paragraph->offset;\n}\n\nSBUInteger SBParagraphGetLength(SBParagraphRef paragraph)\n{\n    return paragraph->length;\n}\n\nSBLevel SBParagraphGetBaseLevel(SBParagraphRef paragraph)\n{\n    return paragraph->baseLevel;\n}\n\nconst SBLevel *SBParagraphGetLevelsPtr(SBParagraphRef paragraph)\n{\n    return paragraph->fixedLevels;\n}\n\nSBLineRef SBParagraphCreateLine(SBParagraphRef paragraph, SBUInteger lineOffset, SBUInteger lineLength)\n{\n    SBUInteger paragraphOffset = paragraph->offset;\n    SBUInteger paragraphLength = paragraph->length;\n    SBUInteger paragraphLimit = paragraphOffset + paragraphLength;\n    SBUInteger lineLimit = lineOffset + lineLength;\n\n    if (lineOffset < lineLimit && lineOffset >= paragraphOffset && lineLimit <= paragraphLimit) {\n        return SBLineCreate(paragraph, lineOffset, lineLength);\n    }\n\n    return NULL;\n}\n\nSBParagraphRef SBParagraphRetain(SBParagraphRef paragraph)\n{\n    return ObjectRetain((ObjectRef)paragraph);\n}\n\nvoid SBParagraphRelease(SBParagraphRef paragraph)\n{\n    ObjectRelease((ObjectRef)paragraph);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBParagraph.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_PARAGRAPH_H\n#define _SB_INTERNAL_PARAGRAPH_H\n\n#include <SheenBidi/SBAlgorithm.h>\n#include <SheenBidi/SBParagraph.h>\n\n#include <API/SBBase.h>\n#include <Core/Object.h>\n\ntypedef struct _SBParagraph {\n    ObjectBase _base;\n    SBAlgorithmRef _algorithm;\n    SBCodepointSequence codepointSequence;\n    const SBBidiType *refTypes;\n    SBLevel *fixedLevels;\n    SBUInteger offset;\n    SBUInteger length;\n    SBLevel baseLevel;\n} SBParagraph;\n\nSB_INTERNAL SBParagraphRef SBParagraphCreateWithAlgorithm(SBAlgorithmRef algorithm,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel);\n\nSB_INTERNAL SBParagraphRef SBParagraphCreateWithCodepointSequence(\n    const SBCodepointSequence *codepointSequence, const SBBidiType *refBidiTypes,\n    SBUInteger paragraphOffset, SBUInteger suggestedLength, SBLevel baseLevel);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBScriptLocator.c",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <API/SBCodepointSequence.h>\n#include <Core/Object.h>\n#include <Data/GeneralCategoryLookup.h>\n#include <Data/PairingLookup.h>\n#include <Data/ScriptLookup.h>\n#include <Script/ScriptStack.h>\n\n#include \"SBScriptLocator.h\"\n\nstatic SBBoolean IsSimilarScript(SBScript lhs, SBScript rhs)\n{\n    return SBScriptIsCommonOrInherited(lhs)\n        || SBScriptIsCommonOrInherited(rhs)\n        || lhs == rhs;\n}\n\nSBScriptLocatorRef SBScriptLocatorCreate(void)\n{\n    const SBUInteger size = sizeof(SBScriptLocator);\n    void *pointer = NULL;\n    SBScriptLocatorRef locator;\n\n    locator = ObjectCreate(&size, 1, &pointer, NULL);\n\n    if (locator) {\n        locator->_codepointSequence.stringEncoding = SBStringEncodingUTF8;\n        locator->_codepointSequence.stringBuffer = NULL;\n        locator->_codepointSequence.stringLength = 0;\n\n        SBScriptLocatorReset(locator);\n    }\n\n    return locator;\n}\n\nvoid SBScriptLocatorLoadCodepoints(SBScriptLocatorRef locator, const SBCodepointSequence *codepointSequence)\n{\n    locator->_codepointSequence = *codepointSequence;\n    SBScriptLocatorReset(locator);\n}\n\nconst SBScriptAgent *SBScriptLocatorGetAgent(SBScriptLocatorRef locator)\n{\n    return &locator->agent;\n}\n\nstatic void ResolveScriptRun(SBScriptLocatorRef locator, SBUInteger offset)\n{\n    const SBCodepointSequence *sequence = &locator->_codepointSequence;\n    ScriptStackRef stack = &locator->_scriptStack;\n    SBScript result = SBScriptZYYY;\n    SBUInteger current = offset;\n    SBUInteger next = offset;\n    SBCodepoint codepoint;\n\n    /* Iterate over the code points of specified string buffer. */\n    while ((codepoint = SBCodepointSequenceGetCodepointAt(sequence, &next)) != SBCodepointInvalid) {\n        SBBoolean isStacked = SBFalse;\n        SBScript script;\n\n        script = LookupScript(codepoint);\n\n        /* Handle paired punctuations in case of a common script. */\n        if (script == SBScriptZYYY) {\n            SBGeneralCategory generalCategory = LookupGeneralCategory(codepoint);\n\n            /* Check if current code point is an open punctuation. */\n            if (generalCategory == SBGeneralCategoryPS) {\n                SBCodepoint mirror = LookupMirror(codepoint);\n                if (mirror) {\n                    /* A closing pair exists for this punctuation, so push it onto the stack. */\n                    ScriptStackPush(stack, result, mirror);\n                }\n            }\n            /* Check if current code point is a close punctuation. */\n            else if (generalCategory == SBGeneralCategoryPE) {\n                SBBoolean isMirrored = (LookupMirror(codepoint) != 0);\n                if (isMirrored) {\n                    /* Find the matching entry in the stack, while popping the unmatched ones. */\n                    while (!ScriptStackIsEmpty(stack)) {\n                        SBCodepoint mirror = ScriptStackGetMirror(stack);\n                        if (mirror != codepoint) {\n                            ScriptStackPop(stack);\n                        } else {\n                            break;\n                        }\n                    }\n\n                    if (!ScriptStackIsEmpty(stack)) {\n                        isStacked = SBTrue;\n                        /* Paired punctuation match the script of enclosing text. */\n                        script = ScriptStackGetScript(stack);\n                    }\n                }\n            }\n        }\n\n        if (IsSimilarScript(result, script)) {\n            if (SBScriptIsCommonOrInherited(result) && !SBScriptIsCommonOrInherited(script)) {\n                /* Set the concrete script of this code point as the result. */\n                result = script;\n                /* Seal the pending punctuations with the result. */\n                ScriptStackSealPairs(stack, result);\n            }\n\n            if (isStacked) {\n                /* Pop the paired punctuation from the stack. */\n                ScriptStackPop(stack);\n            }\n        } else {\n            /* The current code point has a different script, so finish the run. */\n            break;\n        }\n\n        current = next;\n    }\n\n    ScriptStackLeavePairs(stack);\n\n    /* Set the run info in agent. */\n    locator->agent.offset = offset;\n    locator->agent.length = current - offset;\n    locator->agent.script = result;\n}\n\nSBBoolean SBScriptLocatorMoveNext(SBScriptLocatorRef locator)\n{\n    SBUInteger offset = locator->agent.offset + locator->agent.length;\n\n    if (offset < locator->_codepointSequence.stringLength) {\n        ResolveScriptRun(locator, offset);\n        return SBTrue;\n    }\n\n    SBScriptLocatorReset(locator);\n    return SBFalse;\n}\n\nvoid SBScriptLocatorReset(SBScriptLocatorRef locator)\n{\n    ScriptStackReset(&locator->_scriptStack);\n    locator->agent.offset = 0;\n    locator->agent.length = 0;\n    locator->agent.script = SBScriptNil;\n}\n\nSBScriptLocatorRef SBScriptLocatorRetain(SBScriptLocatorRef locator)\n{\n    return ObjectRetain((ObjectRef)locator);\n}\n\nvoid SBScriptLocatorRelease(SBScriptLocatorRef locator)\n{\n    ObjectRelease((ObjectRef)locator);\n}\n"
  },
  {
    "path": "unix/bidi/Source/API/SBScriptLocator.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_SCRIPT_LOCATOR_H\n#define _SB_INTERNAL_SCRIPT_LOCATOR_H\n\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBScriptLocator.h>\n\n#include <Core/Object.h>\n#include <Script/ScriptStack.h>\n\ntypedef struct _SBScriptLocator {\n    ObjectBase _base;\n    SBCodepointSequence _codepointSequence;\n    ScriptStack _scriptStack;\n    SBScriptAgent agent;\n} SBScriptLocator;\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBText.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <API/SBAssert.h>\n#include <API/SBAttributeRegistry.h>\n#include <API/SBCodepoint.h>\n#include <API/SBCodepointSequence.h>\n#include <API/SBParagraph.h>\n#include <API/SBScriptLocator.h>\n#include <API/SBTextConfig.h>\n#include <API/SBTextIterators.h>\n#include <Core/List.h>\n#include <Core/Object.h>\n#include <Text/AttributeManager.h>\n\n#include \"SBText.h\"\n\n/* =========================================================================\n * Text Paragraph Implementation\n * ========================================================================= */\n\n /**\n * Initializes a TextParagraph structure with default values.\n */\nstatic void InitializeTextParagraph(TextParagraphRef paragraph)\n{\n    paragraph->index = SBInvalidIndex;\n    paragraph->length = 0;\n    paragraph->needsReanalysis = SBTrue;\n    paragraph->bidiParagraph = NULL;\n\n    ListInitialize(&paragraph->scripts, sizeof(SBScriptRun));\n}\n\n/**\n * Releases resources associated with a TextParagraph structure.\n */\nstatic void FinalizeTextParagraph(TextParagraphRef paragraph)\n{\n    SBParagraphRef bidiParagraph = paragraph->bidiParagraph;\n\n    if (bidiParagraph) {\n        SBParagraphRelease(bidiParagraph);\n    }\n\n    ListFinalize(&paragraph->scripts);\n}\n\n/* =========================================================================\n * Text Implementation\n * ========================================================================= */\n\n/**\n * Returns the size in bytes of a single code unit for the given encoding.\n * \n * @param encoding\n *      The string encoding.\n * @return\n *      Size in bytes of a code unit, or 0 if encoding is invalid.\n */\nstatic SBUInteger GetCodeUnitSize(SBStringEncoding encoding)\n{\n    switch (encoding) {\n    case SBStringEncodingUTF8:\n        return sizeof(SBUInt8);\n\n    case SBStringEncodingUTF16:\n        return sizeof(SBUInt16);\n\n    case SBStringEncodingUTF32:\n        return sizeof(SBUInt32);\n\n    default:\n        return 0;\n    }\n}\n\n/**\n * Returns the maximum number of code units needed to represent a single code point in the given\n * encoding.\n * \n * @param text\n *      The text object.\n * @return\n *      Maximum code units per code point, or 0 if encoding is invalid.\n */\nstatic SBUInteger GetMaxCodeUnitsPerCodepoint(SBTextRef text)\n{\n    switch (text->encoding) {\n    case SBStringEncodingUTF8:\n        return 4;\n\n    case SBStringEncodingUTF16:\n        return 2;\n\n    case SBStringEncodingUTF32:\n        return 1;\n\n    default:\n        return 0;\n    }\n}\n\n/**\n * Finalizes all paragraphs in the text object by releasing their resources.\n */\nstatic void FinalizeAllParagraphs(SBTextRef text)\n{\n    SBUInteger paragraphIndex;\n\n    for (paragraphIndex = 0; paragraphIndex < text->paragraphs.count; paragraphIndex++) {\n        FinalizeTextParagraph(ListGetRef(&text->paragraphs, paragraphIndex));\n    }\n}\n\n/**\n * Comparison function for binary search to locate a paragraph containing a specific code unit. Used\n * by bsearch() to find the paragraph that contains a given code unit index.\n */\nstatic int ParagraphIndexComparison(const void *key, const void *element) {\n    const SBUInteger *codeUnitIndex = key;\n    const TextParagraph *paragraph = element;\n    SBUInteger paragraphStart;\n    SBUInteger paragraphEnd;\n\n    paragraphStart = paragraph->index;\n    paragraphEnd = paragraphStart + paragraph->length;\n\n    if (*codeUnitIndex < paragraphStart) {\n        return -1;\n    }\n    if (*codeUnitIndex >= paragraphEnd) {\n        return 1;\n    }\n\n    return 0;\n}\n\nSB_INTERNAL SBUInteger SBTextGetCodeUnitParagraphIndex(SBTextRef text, SBUInteger codeUnitIndex)\n{\n    TextParagraph *array = text->paragraphs.items;\n    SBUInteger count = text->paragraphs.count;\n    void *item = NULL;\n\n    if (array) {\n        item = bsearch(&codeUnitIndex, array, count, sizeof(TextParagraph), ParagraphIndexComparison);\n    }\n\n    if (item) {\n        return (SBUInteger)((TextParagraph *)item - array);\n    }\n\n    return SBInvalidIndex;\n}\n\nSB_INTERNAL void SBTextGetBoundaryParagraphs(SBTextRef text,\n    SBUInteger rangeStart, SBUInteger rangeEnd,\n    TextParagraphRef *firstParagraph, TextParagraphRef *lastParagraph)\n{\n    SBUInteger codeUnitCount = text->codeUnits.count;\n\n    SBAssert(firstParagraph && lastParagraph);\n\n    *firstParagraph = NULL;\n    *lastParagraph = NULL;\n\n    /* Find the first paragraph intersecting the range */\n    if (rangeStart < codeUnitCount) {\n        SBUInteger paragraphIndex;\n        SBUInteger paragraphStart;\n        SBUInteger paragraphEnd;\n\n        paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, rangeStart);\n        *firstParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n        paragraphStart = (*firstParagraph)->index;\n        paragraphEnd = paragraphStart + (*firstParagraph)->length;\n\n        /* If the range doesn't extend beyond the first paragraph, they're the same */\n        if (paragraphEnd >= rangeEnd) {\n            *lastParagraph = *firstParagraph;\n            return;\n        }\n    }\n\n    /* Find the last paragraph if it's different from the first */\n    if (rangeEnd <= codeUnitCount) {\n        SBUInteger paragraphIndex;\n\n        paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, rangeEnd - 1);\n        *lastParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n    }\n}\n\nSBTextRef SBTextCreate(const void *string, SBUInteger length, SBStringEncoding encoding,\n    SBTextConfigRef config)\n{\n    SBMutableTextRef text = SBTextCreateMutable(encoding, config);\n\n    if (text) {\n        SBTextAppendCodeUnits(text, string, length);\n        text->isMutable = SBFalse;\n    }\n\n    return text;\n}\n\nSBTextRef SBTextCreateCopy(SBTextRef text)\n{\n    SBMutableTextRef copy = SBTextCreateMutableCopy(text);\n\n    if (copy) {\n        copy->isMutable = SBFalse;\n    }\n\n    return copy;\n}\n\nSBStringEncoding SBTextGetEncoding(SBTextRef text)\n{\n    return text->encoding;\n}\n\nSBAttributeRegistryRef SBTextGetAttributeRegistry(SBTextRef text)\n{\n    return text->attributeRegistry;\n}\n\nSBUInteger SBTextGetLength(SBTextRef text)\n{\n    return text->codeUnits.count;\n}\n\nvoid SBTextGetCodeUnits(SBTextRef text, SBUInteger index, SBUInteger length, void *buffer)\n{\n    SBBoolean isRangeValid = SBUIntegerVerifyRange(text->codeUnits.count, index, length);\n    SBUInteger byteCount;\n    const void *source;\n\n    SBAssert(isRangeValid);\n\n    byteCount = length * text->codeUnits.itemSize;\n    source = ListGetPtr(&text->codeUnits, index);\n\n    memcpy(buffer, source, byteCount);\n}\n\nvoid SBTextGetBidiTypes(SBTextRef text, SBUInteger index, SBUInteger length, SBBidiType *buffer)\n{\n    SBBoolean isRangeValid = SBUIntegerVerifyRange(text->codeUnits.count, index, length);\n    const SBBidiType *bidiTypes;\n    SBUInteger byteCount;\n\n    SBAssert(isRangeValid);\n\n    bidiTypes = &text->bidiTypes.items[index];\n    byteCount = length * sizeof(SBBidiType);\n\n    memcpy(buffer, bidiTypes, byteCount);\n}\n\nvoid SBTextGetScripts(SBTextRef text, SBUInteger index, SBUInteger length, SBScript *buffer)\n{\n    SBBoolean isRangeValid = SBUIntegerVerifyRange(text->codeUnits.count, index, length);\n    SBUInteger rangeStart;\n    SBUInteger rangeEnd;\n    SBUInteger paragraphIndex;\n\n    SBAssert(isRangeValid && !text->isEditing);\n\n    rangeStart = index;\n    rangeEnd = index + length;\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, rangeStart);\n\n    while (rangeStart < rangeEnd) {\n        const TextParagraph *textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n        SBUInteger copyStart = textParagraph->index;\n        SBUInteger copyEnd = copyStart + textParagraph->length;\n        const SBScript *scriptArray;\n        SBUInteger scriptCount;\n        SBUInteger byteCount;\n\n        /* Clamp copy range to requested range */\n        if (copyStart < rangeStart) {\n            copyStart = rangeStart;\n        }\n        if (copyEnd > rangeEnd) {\n            copyEnd = rangeEnd;\n        }\n\n        scriptArray = ListGetRef(&textParagraph->scripts, copyStart - textParagraph->index);\n        scriptCount = copyEnd - copyStart;\n        byteCount = scriptCount * sizeof(SBScript);\n\n        memcpy(buffer, scriptArray, byteCount);\n\n        buffer += scriptCount;\n        rangeStart = copyEnd;\n        paragraphIndex += 1;\n    }\n}\n\nvoid SBTextGetResolvedLevels(SBTextRef text, SBUInteger index, SBUInteger length, SBLevel *buffer)\n{\n    SBBoolean isRangeValid = SBUIntegerVerifyRange(text->codeUnits.count, index, length);\n    SBUInteger rangeStart;\n    SBUInteger rangeEnd;\n    SBUInteger paragraphIndex;\n\n    SBAssert(isRangeValid && !text->isEditing);\n\n    rangeStart = index;\n    rangeEnd = index + length;\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, index);\n\n    while (rangeStart < rangeEnd) {\n        const TextParagraph *textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n        SBUInteger copyStart = textParagraph->index;\n        SBUInteger copyEnd = copyStart + textParagraph->length;\n        SBParagraphRef bidiParagraph;\n        const SBLevel *levelArray;\n        SBUInteger levelCount;\n        SBUInteger byteCount;\n\n        /* Clamp copy range to requested range */\n        if (copyStart < rangeStart) {\n            copyStart = rangeStart;\n        }\n        if (copyEnd > rangeEnd) {\n            copyEnd = rangeEnd;\n        }\n\n        bidiParagraph = textParagraph->bidiParagraph;\n        levelArray = &bidiParagraph->fixedLevels[copyStart - bidiParagraph->offset];\n        levelCount = copyEnd - copyStart;\n        byteCount = levelCount * sizeof(SBLevel);\n\n        memcpy(buffer, levelArray, byteCount);\n\n        buffer += levelCount;\n        rangeStart = copyEnd;\n        paragraphIndex += 1;\n    }\n}\n\nvoid SBTextGetCodeUnitParagraphInfo(SBTextRef text, SBUInteger index,\n    SBParagraphInfo *paragraphInfo)\n{\n    SBBoolean isValidIndex = index < text->codeUnits.count;\n    SBUInteger paragraphIndex;\n    const TextParagraph *textParagraph;\n    SBParagraphRef bidiParagraph;\n\n    SBAssert(isValidIndex && !text->isEditing);\n\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, index);\n    textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n    bidiParagraph = textParagraph->bidiParagraph;\n\n    paragraphInfo->index = textParagraph->index;\n    paragraphInfo->length = textParagraph->length;\n    paragraphInfo->baseLevel = bidiParagraph->baseLevel;\n}\n\nSBParagraphIteratorRef SBTextCreateParagraphIterator(SBTextRef text)\n{\n    return SBParagraphIteratorCreate(text);\n}\n\nSBLogicalRunIteratorRef SBTextCreateLogicalRunIterator(SBTextRef text)\n{\n    return SBLogicalRunIteratorCreate(text);\n}\n\nSBScriptRunIteratorRef SBTextCreateScriptRunIterator(SBTextRef text)\n{\n    return SBScriptRunIteratorCreate(text);\n}\n\nSBAttributeRunIteratorRef SBTextCreateAttributeRunIterator(SBTextRef text)\n{\n    return SBAttributeRunIteratorCreate(text);\n}\n\nSBVisualRunIteratorRef SBTextCreateVisualRunIterator(SBTextRef text,\n    SBUInteger index, SBUInteger length)\n{\n    SBVisualRunIteratorRef iterator = SBVisualRunIteratorCreate(text);\n\n    if (iterator) {\n        SBVisualRunIteratorReset(iterator, index, length);\n    }\n\n    return iterator;\n}\n\nSBTextRef SBTextRetain(SBTextRef text)\n{\n    return ObjectRetain((ObjectRef)text);\n}\n\nvoid SBTextRelease(SBTextRef text)\n{\n    ObjectRelease((ObjectRef)text);\n}\n\n/* =========================================================================\n * Mutable Text Implementation\n * ========================================================================= */\n\nstatic void DetermineChunkBidiTypes(SBMutableTextRef text, SBUInteger index, SBUInteger length)\n{\n    SBUInteger codeUnitCount = text->codeUnits.count;\n\n    if (codeUnitCount > 0) {\n        SBUInteger startIndex = index;\n        SBUInteger endIndex = startIndex + length;\n        SBStringEncoding encoding = text->encoding;\n        const void *buffer = text->codeUnits.data;\n        SBUInteger surround;\n        SBCodepointSequence sequence;\n\n        surround = GetMaxCodeUnitsPerCodepoint(text);\n\n        startIndex = (startIndex >= surround ? startIndex - surround : 0);\n        endIndex = ((endIndex + surround) <= codeUnitCount ? endIndex + surround : codeUnitCount);\n        endIndex -= 1;\n\n        /* Align to code point boundaries */\n        SBCodepointSkipToStart(buffer, codeUnitCount, encoding, &startIndex);\n        SBCodepointSkipToEnd(buffer, codeUnitCount, encoding, &endIndex);\n\n        sequence.stringEncoding = encoding;\n        sequence.stringBuffer = SBCodepointGetBufferOffset(buffer, encoding, startIndex);\n        sequence.stringLength = endIndex - startIndex;\n\n        SBCodepointSequenceDetermineBidiTypes(&sequence, &text->bidiTypes.items[startIndex]);\n    }\n}\n\nstatic void ReplaceBidiTypes(SBMutableTextRef text,\n    SBUInteger rangeStart, SBUInteger oldLength, SBUInteger newLength)\n{\n    if (newLength > oldLength) {\n        ListReserveRange(&text->bidiTypes, rangeStart, newLength - oldLength);\n    } else {\n        ListRemoveRange(&text->bidiTypes, rangeStart, oldLength - newLength);\n    }\n\n    DetermineChunkBidiTypes(text, rangeStart, newLength);\n}\n\nstatic TextParagraphRef InsertEmptyParagraph(SBMutableTextRef text, SBUInteger listIndex)\n{\n    SBBoolean succeeded;\n    TextParagraph paragraph;\n\n    InitializeTextParagraph(&paragraph);\n    succeeded = ListInsert(&text->paragraphs, listIndex, &paragraph);\n\n    return (succeeded ? ListGetRef(&text->paragraphs, listIndex) : NULL);\n}\n\nstatic void RemoveParagraphRange(SBMutableTextRef text, SBUInteger index, SBUInteger length)\n{\n    SBUInteger endIndex = index + length;\n    SBUInteger paragraphIndex;\n\n    /* Finalize each paragraph's resources */\n    for (paragraphIndex = index; paragraphIndex < endIndex; paragraphIndex++) {\n        TextParagraphRef paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n        FinalizeTextParagraph(paragraph);\n    }\n\n    ListRemoveRange(&text->paragraphs, index, length);\n}\n\n/**\n * Adjusts the start index of all paragraphs from a given position onward by a delta.\n * Used when text is inserted or deleted to shift paragraph boundaries.\n * \n * @param text\n *      Mutable text object.\n * @param listIndex\n *      Starting list position (inclusive).\n * @param indexDelta\n *      Amount to add to each paragraph's index (can be negative).\n */\nstatic void ShiftParagraphRanges(SBMutableTextRef text, SBUInteger listIndex, SBInteger indexDelta) {\n    while (listIndex < text->paragraphs.count) {\n        TextParagraphRef paragraph = ListGetRef(&text->paragraphs, listIndex);\n        paragraph->index += indexDelta;\n        listIndex += 1;\n    }\n}\n\nstatic void UpdateParagraphsForTextReplacement(SBMutableTextRef text,\n    SBUInteger replaceStart, SBUInteger oldLength, SBUInteger newLength)\n{\n    SBUInteger oldEnd = replaceStart + oldLength;\n    SBUInteger newEnd = replaceStart + newLength;\n    SBInteger lengthDelta = (SBInteger)(newLength - oldLength);\n    SBUInteger paragraphIndex;\n    SBUInteger removalEnd;\n    SBCodepointSequence sequence;\n    TextParagraphRef paragraph;\n    SBUInteger scanIndex;\n\n    /* Find the first affected paragraph */\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, replaceStart > 0 ? replaceStart - 1 : 0);\n    if (paragraphIndex == SBInvalidIndex) {\n        paragraphIndex = text->paragraphs.count;\n    }\n\n    /* Determine starting point for scanning */\n    if (paragraphIndex < text->paragraphs.count) {\n        paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n        scanIndex = paragraph->index;\n    } else {\n        scanIndex = replaceStart;\n    }\n\n    /* Setup for scanning */\n    sequence.stringEncoding = text->encoding;\n    sequence.stringBuffer = text->codeUnits.data;\n    sequence.stringLength = text->codeUnits.count;\n\n    while (scanIndex < sequence.stringLength) {\n        SBUInteger separatorLength;\n        SBUInteger paraLength;\n\n        SBCodepointSequenceGetParagraphBoundary(&sequence, text->bidiTypes.items,\n            scanIndex, sequence.stringLength - scanIndex, &paraLength, &separatorLength);\n\n        /* Get or create paragraph slot */\n        if (paragraphIndex < text->paragraphs.count) {\n            paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n            /* Check if this slot is within reusable range */\n            if (paragraph->index > oldEnd) {\n                /* Slot is after affected region, insert new one */\n                paragraph = InsertEmptyParagraph(text, paragraphIndex);\n            } else {\n                SBUInteger paragraphEnd = paragraph->index + paragraph->length;\n\n                /* Check for splitting */\n                if (paragraphEnd > oldEnd && separatorLength > 0) {\n                    newEnd = paragraphEnd + lengthDelta;\n                }\n            }\n        } else {\n            /* Need new slot */\n            paragraph = InsertEmptyParagraph(text, paragraphIndex);\n        }\n\n        /* Update paragraph */\n        paragraph->index = scanIndex;\n        paragraph->length = paraLength;\n        paragraph->needsReanalysis = SBTrue;\n\n        scanIndex += paraLength;\n        paragraphIndex += 1;\n\n        if (scanIndex > replaceStart && scanIndex >= newEnd) {\n            break;\n        }\n    }\n\n    /* Remove any leftover slots that weren't reused */\n    removalEnd = paragraphIndex;\n    while (removalEnd < text->paragraphs.count) {\n        paragraph = ListGetRef(&text->paragraphs, removalEnd);\n        if (paragraph->index > oldEnd) {\n            break;\n        }\n\n        removalEnd += 1;\n    }\n\n    RemoveParagraphRange(text, paragraphIndex, removalEnd - paragraphIndex);\n\n    /* Shift paragraphs after the affected region */\n    if (lengthDelta != 0 && paragraphIndex < text->paragraphs.count) {\n        ShiftParagraphRanges(text, paragraphIndex, lengthDelta);\n    }\n}\n\n#define UpdateParagraphsForTextInsertion(text, index, length) \\\n    UpdateParagraphsForTextReplacement(text, index, 0, length)\n\n#define UpdateParagraphsForTextRemoval(text, index, length) \\\n    UpdateParagraphsForTextReplacement(text, index, length, 0)\n\nstatic void GenerateBidiParagraph(SBMutableTextRef text, TextParagraphRef paragraph)\n{\n    SBCodepointSequence codepointSequence;\n    const SBBidiType *bidiTypes;\n\n    codepointSequence.stringEncoding = text->encoding;\n    codepointSequence.stringBuffer = text->codeUnits.data;\n    codepointSequence.stringLength = text->codeUnits.count;\n\n    bidiTypes = text->bidiTypes.items;\n\n    if (paragraph->bidiParagraph) {\n        /* Release old bidi paragraph */\n        SBParagraphRelease(paragraph->bidiParagraph);\n        paragraph->bidiParagraph = NULL;\n    }\n\n    paragraph->bidiParagraph = SBParagraphCreateWithCodepointSequence(\n        &codepointSequence, bidiTypes, paragraph->index, paragraph->length, text->baseLevel);\n}\n\nstatic void PopulateParagraphScripts(SBMutableTextRef text, TextParagraphRef paragraph)\n{\n    SBScriptLocatorRef scriptLocator;\n    SBCodepointSequence codepointSequence;\n    const SBScriptAgent *scriptAgent;\n\n    scriptLocator = text->scriptLocator;\n\n    codepointSequence.stringEncoding = text->encoding;\n    codepointSequence.stringBuffer = ListGetPtr(&text->codeUnits, paragraph->index);\n    codepointSequence.stringLength = paragraph->length;\n\n    ListRemoveAll(&paragraph->scripts);\n    ListReserveRange(&paragraph->scripts, 0, paragraph->length);\n\n    scriptAgent = &scriptLocator->agent;\n    SBScriptLocatorLoadCodepoints(scriptLocator, &codepointSequence);\n\n    while (SBScriptLocatorMoveNext(scriptLocator)) {\n        SBUInteger runStart = scriptAgent->offset;\n        SBUInteger runEnd = runStart + scriptAgent->length;\n        SBScript runScript = scriptAgent->script;\n\n        while (runStart < runEnd) {\n            ListSetVal(&paragraph->scripts, runStart, runScript);\n            runStart += 1;\n        }\n    }\n}\n\n/**\n * Analyzes all paragraphs marked as needing reanalysis.\n * Generates bidirectional properties and script information.\n */\nstatic void AnalyzeDirtyParagraphs(SBMutableTextRef text)\n{\n    SBUInteger paragraphCount = text->paragraphs.count;\n    SBUInteger paragraphIndex;\n\n    for (paragraphIndex = 0; paragraphIndex < paragraphCount; paragraphIndex++) {\n        TextParagraphRef paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n        if (paragraph->needsReanalysis) {\n            GenerateBidiParagraph(text, paragraph);\n            PopulateParagraphScripts(text, paragraph);\n\n            paragraph->needsReanalysis = SBFalse;\n        }\n    }\n}\n\n/**\n * Cleanup callback for mutable text objects; releases all owned resources.\n */\nstatic void FinalizeMutableText(ObjectRef object)\n{\n    SBMutableTextRef text = object;\n\n    AttributeManagerFinalize(&text->attributeManager);\n    FinalizeAllParagraphs(text);\n\n    ListFinalize(&text->codeUnits);\n    ListFinalize(&text->bidiTypes);\n    ListFinalize(&text->paragraphs);\n\n    if (text->scriptLocator) {\n        SBScriptLocatorRelease(text->scriptLocator);\n    }\n    if (text->attributeRegistry) {\n        SBAttributeRegistryRelease(text->attributeRegistry);\n    }\n}\n\nSB_INTERNAL SBMutableTextRef SBTextCreateMutableWithParameters(SBStringEncoding encoding,\n    SBAttributeRegistryRef attributeRegistry, SBLevel baseLevel)\n{\n    const SBUInteger size = sizeof(SBText);\n    void *pointer = NULL;\n    SBMutableTextRef text;\n\n    text = ObjectCreate(&size, 1, &pointer, FinalizeMutableText);\n\n    if (text) {\n        if (attributeRegistry) {\n            attributeRegistry = SBAttributeRegistryRetain(attributeRegistry);\n        }\n\n        text->encoding = encoding;\n        text->isMutable = SBTrue;\n        text->baseLevel = baseLevel;\n        text->isEditing = SBFalse;\n        text->scriptLocator = SBScriptLocatorCreate();\n        text->attributeRegistry = attributeRegistry;\n\n        AttributeManagerInitialize(&text->attributeManager, text, attributeRegistry);\n        ListInitialize(&text->codeUnits, GetCodeUnitSize(encoding));\n        ListInitialize(&text->bidiTypes, sizeof(SBBidiType));\n        ListInitialize(&text->paragraphs, sizeof(TextParagraph));\n    }\n\n    return text;\n}\n\nSBMutableTextRef SBTextCreateMutable(SBStringEncoding encoding, SBTextConfigRef config)\n{\n    SBMutableTextRef text = SBTextCreateMutableWithParameters(encoding,\n        config->attributeRegistry, config->baseLevel);\n\n    if (text) {\n        /* TODO: Apply default attributes */\n    }\n\n    return text;\n}\n\nSBMutableTextRef SBTextCreateMutableCopy(SBTextRef text)\n{\n    SBMutableTextRef copy = SBTextCreateMutableWithParameters(text->encoding,\n        text->attributeRegistry, text->baseLevel);\n\n    if (copy) {\n        SBUInteger byteCount;\n        SBUInteger paragraphCount;\n        SBUInteger paragraphIndex;\n\n        /* Copy code units */\n        ListReserveRange(&copy->codeUnits, 0, text->codeUnits.count);\n        byteCount = text->codeUnits.count * text->codeUnits.itemSize;\n        memcpy(copy->codeUnits.data, text->codeUnits.data, byteCount);\n\n        /* Copy bidi types */\n        ListReserveRange(&copy->bidiTypes, 0, text->bidiTypes.count);\n        byteCount = text->bidiTypes.count * sizeof(SBBidiType);\n        memcpy(copy->bidiTypes.items, text->bidiTypes.items, byteCount);\n\n        /* Copy paragraphs */\n        paragraphCount = text->paragraphs.count;\n        ListReserveRange(&copy->paragraphs, 0, paragraphCount);\n\n        for (paragraphIndex = 0; paragraphIndex < paragraphCount; paragraphIndex++) {\n            TextParagraphRef source = ListGetRef(&text->paragraphs, paragraphIndex);\n            TextParagraphRef destination = ListGetRef(&copy->paragraphs, paragraphIndex);\n\n            destination->index = source->index;\n            destination->length = source->length;\n            ListInitialize(&destination->scripts, sizeof(SBScript));\n\n            if (source->needsReanalysis) {\n                destination->needsReanalysis = SBTrue;\n                destination->bidiParagraph = NULL;\n            } else {\n                SBUInteger scriptCount = source->scripts.count;\n\n                destination->needsReanalysis = SBFalse;\n                destination->bidiParagraph = SBParagraphRetain(source->bidiParagraph);\n\n                ListReserveRange(&destination->scripts, 0, scriptCount);\n                byteCount = scriptCount * sizeof(SBScript);\n                memcpy(destination->scripts.items, source->scripts.items, byteCount);\n            }\n        }\n\n        AnalyzeDirtyParagraphs(copy);\n\n        /* Copy attributes */\n        AttributeManagerCopyAttributes(&copy->attributeManager, &text->attributeManager);\n    }\n\n    return copy;\n}\n\nvoid SBTextBeginEditing(SBMutableTextRef text)\n{\n    SBAssert(text->isMutable);\n\n    text->isEditing = SBTrue;\n}\n\nvoid SBTextEndEditing(SBMutableTextRef text)\n{\n    SBAssert(text->isMutable);\n\n    AnalyzeDirtyParagraphs(text);\n    text->isEditing = SBFalse;\n}\n\nvoid SBTextAppendCodeUnits(SBMutableTextRef text,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount)\n{\n    SBAssert(text->isMutable);\n\n    SBTextInsertCodeUnits(text, text->codeUnits.count, codeUnitBuffer, codeUnitCount);\n}\n\nvoid SBTextInsertCodeUnits(SBMutableTextRef text, SBUInteger index,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount)\n{\n    SBAssert(text->isMutable && index <= text->codeUnits.count);\n\n    if (codeUnitCount > 0) {\n        SBUInteger byteCount;\n        void *destination;\n\n        /* Reserve space in code units */\n        ListReserveRange(&text->codeUnits, index, codeUnitCount);\n\n        byteCount = codeUnitCount * text->codeUnits.itemSize;\n        destination = ListGetPtr(&text->codeUnits, index);\n        memcpy(destination, codeUnitBuffer, byteCount);\n\n        /* Insert bidi types */\n        ReplaceBidiTypes(text, index, 0, codeUnitCount);\n\n        /* Update paragraph structures */\n        UpdateParagraphsForTextInsertion(text, index, codeUnitCount);\n\n        /* Reserve attribute manager space */\n        AttributeManagerReserveRange(&text->attributeManager, index, codeUnitCount);\n\n        /* Perform immediate analysis if not in batch editing mode */\n        if (!text->isEditing) {\n            AnalyzeDirtyParagraphs(text);\n        }\n    }\n}\n\nvoid SBTextDeleteCodeUnits(SBMutableTextRef text, SBUInteger index, SBUInteger length)\n{\n    SBUInteger rangeEnd = index + length;\n    SBBoolean isRangeValid = (rangeEnd <= text->codeUnits.count && index <= rangeEnd);\n\n    SBAssert(text->isMutable && isRangeValid);\n\n    if (length > 0) {\n        /* Remove code units */\n        ListRemoveRange(&text->codeUnits, index, length);\n\n        /* Remove bidi types */\n        ReplaceBidiTypes(text, index, length, 0);\n\n        /* Update paragraph structures */\n        UpdateParagraphsForTextRemoval(text, index, length);\n\n        /* Remove from attribute manager */\n        AttributeManagerRemoveRange(&text->attributeManager, index, length);\n\n        if (!text->isEditing) {\n            /* Perform immediate analysis if not in batch editing mode */\n            AnalyzeDirtyParagraphs(text);\n        }\n    }\n}\n\nvoid SBTextSetCodeUnits(SBMutableTextRef text,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount)\n{\n    SBAssert(text->isMutable);\n\n    SBTextReplaceCodeUnits(text, 0, text->codeUnits.count, codeUnitBuffer, codeUnitCount);\n}\n\nvoid SBTextReplaceCodeUnits(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    const void *codeUnitBuffer, SBUInteger codeUnitCount)\n{\n    SBUInteger rangeEnd = index + length;\n    SBBoolean isRangeValid = (rangeEnd <= text->codeUnits.count && index <= rangeEnd);\n\n    SBAssert(text->isMutable && isRangeValid);\n\n    if (length > 0 || codeUnitCount > 0) {\n        if (codeUnitCount > length) {\n            ListReserveRange(&text->codeUnits, index, codeUnitCount - length);\n        } else {\n            ListRemoveRange(&text->codeUnits, index, length - codeUnitCount);\n        }\n\n        if (codeUnitCount > 0) {\n            SBUInteger byteCount = codeUnitCount * text->codeUnits.itemSize;\n            void *destination = ListGetPtr(&text->codeUnits, index);\n\n            memcpy(destination, codeUnitBuffer, byteCount);\n        }\n\n        /* Remove bidi types */\n        ReplaceBidiTypes(text, index, length, codeUnitCount);\n\n        /* Update paragraph structures */\n        UpdateParagraphsForTextReplacement(text, index, length, codeUnitCount);\n\n        AttributeManagerReplaceRange(&text->attributeManager, index, length, codeUnitCount);\n\n        if (!text->isEditing) {\n            /* Perform immediate analysis if not in batch editing mode */\n            AnalyzeDirtyParagraphs(text);\n        }\n    }\n}\n\nvoid SBTextSetAttribute(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    SBAttributeID attributeID, const void *attributeValue)\n{\n    SBUInteger rangeEnd = index + length;\n    SBBoolean isRangeValid = (rangeEnd <= text->codeUnits.count && index <= rangeEnd);\n\n    SBAssert(text->isMutable && isRangeValid);\n\n    if (length > 0) {\n        AttributeManagerSetAttribute(&text->attributeManager,\n            index, length, attributeID, attributeValue);\n    }\n}\n\nvoid SBTextRemoveAttribute(SBMutableTextRef text, SBUInteger index, SBUInteger length,\n    SBAttributeID attributeID)\n{\n    SBUInteger rangeEnd = index + length;\n    SBBoolean isRangeValid = (rangeEnd <= text->codeUnits.count && index <= rangeEnd);\n\n    SBAssert(text->isMutable && isRangeValid);\n\n    if (length > 0) {\n        AttributeManagerRemoveAttribute(&text->attributeManager, index, length, attributeID);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBText.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_TEXT_H\n#define _SB_INTERNAL_TEXT_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBCodepointSequence.h>\n#include <SheenBidi/SBParagraph.h>\n#include <SheenBidi/SBScriptLocator.h>\n#include <SheenBidi/SBText.h>\n\n#include <Core/List.h>\n#include <Core/Object.h>\n#include <Text/AttributeManager.h>\n\ntypedef struct _TextParagraph {\n    SBUInteger index;\n    SBUInteger length;\n    SBBoolean needsReanalysis;\n    SBParagraphRef bidiParagraph;\n    LIST(SBScript) scripts;\n} TextParagraph, *TextParagraphRef;\n\ntypedef struct _SBText {\n    ObjectBase _base;\n    SBStringEncoding encoding;\n    SBBoolean isMutable;\n    SBLevel baseLevel;\n    SBBoolean isEditing;\n    SBScriptLocatorRef scriptLocator;\n    SBAttributeRegistryRef attributeRegistry;\n    AttributeManager attributeManager;\n    List codeUnits;\n    LIST(SBBidiType) bidiTypes;\n    LIST(TextParagraph) paragraphs;\n} SBText;\n\n/**\n * Creates a mutable text object with explicit parameters.\n * \n * @param encoding\n *      String encoding.\n * @param attributeRegistry\n *      Attribute registry (can be `NULL`).\n * @param baseLevel\n *      Base bidirectional level.\n * @return\n *      New mutable text object, or `NULL` on failure.\n */\nSB_INTERNAL SBMutableTextRef SBTextCreateMutableWithParameters(SBStringEncoding encoding,\n    SBAttributeRegistryRef attributeRegistry, SBLevel baseLevel);\n\n/**\n * Finds the paragraph index containing the specified code unit index.\n * \n * @param text\n *      The text object.\n * @param codeUnitIndex\n *      The code unit index to search for.\n * @return\n *      The index of the paragraph containing the code unit, or `SBInvalidIndex` if not found.\n */\nSB_INTERNAL SBUInteger SBTextGetCodeUnitParagraphIndex(SBTextRef text, SBUInteger codeUnitIndex);\n\n/**\n * Retrieves the first and last paragraphs that intersect with a specified code unit range. If the\n * range spans a single paragraph, both output parameters reference the same paragraph.\n *\n * @param text\n *      The text object.\n * @param rangeStart\n *      The starting code unit index (inclusive).\n * @param rangeEnd\n *      The ending code unit index (exclusive).\n * @param[out] firstParagraph\n *      Pointer to receive the first intersecting paragraph reference.\n * @param[out] lastParagraph\n *      Pointer to receive the last intersecting paragraph reference.\n */\nSB_INTERNAL void SBTextGetBoundaryParagraphs(SBTextRef text,\n    SBUInteger rangeStart, SBUInteger rangeEnd,\n    TextParagraphRef *firstParagraph, TextParagraphRef *lastParagraph);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBTextConfig.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n\n#include <API/SBAttributeRegistry.h>\n#include <Core/Object.h>\n\n#include \"SBTextConfig.h\"\n\nstatic void FinalizeTextConfig(ObjectRef object)\n{\n    SBTextConfigRef config = object;\n\n    if (config->attributeRegistry) {\n        SBAttributeRegistryRelease(config->attributeRegistry);\n    }\n}\n\nSBTextConfigRef SBTextConfigCreate(void)\n{\n    const SBUInteger size = sizeof(SBTextConfig);\n    void *pointer = NULL;\n    SBTextConfigRef config;\n\n    config = ObjectCreate(&size, 1, &pointer, &FinalizeTextConfig);\n\n    if (config) {\n        config->attributeRegistry = NULL;\n        config->baseLevel = SBLevelDefaultLTR;\n    }\n\n    return config;\n}\n\nvoid SBTextConfigSetAttributeRegistry(SBTextConfigRef config,\n    SBAttributeRegistryRef attributeRegistry)\n{\n    if (config->attributeRegistry) {\n        SBAttributeRegistryRelease(config->attributeRegistry);\n        config->attributeRegistry = NULL;\n    }\n\n    if (attributeRegistry) {\n        config->attributeRegistry = SBAttributeRegistryRetain(attributeRegistry);\n    }\n}\n\nvoid SBTextConfigSetBaseLevel(SBTextConfigRef config, SBLevel baseLevel)\n{\n    config->baseLevel = baseLevel;\n}\n\nSBTextConfigRef SBTextConfigRetain(SBTextConfigRef config)\n{\n    return ObjectRetain((ObjectRef)config);\n}\n\nvoid SBTextConfigRelease(SBTextConfigRef config)\n{\n    ObjectRelease((ObjectRef)config);\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBTextConfig.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_TEXT_CONFIG_H\n#define _SB_INTERNAL_TEXT_CONFIG_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBTextConfig.h>\n\n#include <Core/Object.h>\n\ntypedef struct _SBTextConfig {\n    ObjectBase _base;\n    SBAttributeRegistryRef attributeRegistry;\n    SBLevel baseLevel;\n} SBTextConfig;\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBTextIterators.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <API/SBAttributeList.h>\n#include <API/SBAttributeRegistry.h>\n#include <API/SBLine.h>\n#include <API/SBParagraph.h>\n#include <API/SBText.h>\n#include <Core/List.h>\n#include <Core/Object.h>\n#include <Text/AttributeDictionary.h>\n#include <Text/AttributeManager.h>\n\n#include \"SBTextIterators.h\"\n\n/* ==========================================================================\n * Text Iterator Implementation\n * ========================================================================== */\n\n/**\n * Resets a text iterator to process a specific range of text.\n *\n * @param iterator\n *      The text iterator to reset.\n * @param index\n *      The starting index of the range to process.\n * @param length\n *      The length of the range to process.\n */\nstatic void ResetTextIterator(TextIteratorRef iterator, SBUInteger index, SBUInteger length);\n\n/**\n * Initializes a text iterator with the specified text and direction mode.\n *\n * Prepares the iterator to traverse through the text. The direction mode determines whether the\n * iterator will follow visual ordering (for display) or logical ordering (for processing).\n *\n * @param iterator\n *      The text iterator to initialize.\n * @param text\n *      The text object to iterate over.\n * @param visualDirectionMode\n *      `SBTrue` for visual direction mode, `SBFalse` for logical direction mode.\n */\nstatic void InitializeTextIterator(TextIteratorRef iterator, SBTextRef text,\n    SBBoolean visualDirectionMode)\n{\n    iterator->text = SBTextRetain(text);\n    iterator->visualDirectionMode = visualDirectionMode;\n\n    ResetTextIterator(iterator, 0, text->codeUnits.count);\n}\n\n/**\n * Releases the text object held by the iterator and performs any necessary cleanup.\n *\n * @param iterator\n *      The text iterator to finalize.\n */\nstatic void FinalizeTextIterator(TextIteratorRef iterator)\n{\n    SBTextRef text = iterator->text;\n\n    if (text) {\n        SBTextRelease(text);\n    }\n}\n\n/**\n * Resets a text iterator to process a specific range of text.\n *\n * This function normalizes the input range and sets up the iterator state to begin processing text\n * from the specified position. If in visual direction mode, it determines the appropriate paragraph\n * and direction based on the text's bidirectional properties.\n *\n * @param iterator\n *      The text iterator to reset.\n * @param index\n *      The starting index of the range to process.\n * @param length\n *      The length of the range to process.\n */\nstatic void ResetTextIterator(TextIteratorRef iterator, SBUInteger index, SBUInteger length)\n{\n    SBTextRef text = iterator->text;\n    SBUInteger startIndex;\n    SBUInteger endIndex;\n    SBBoolean forwardMode;\n    SBUInteger paragraphIndex;\n\n    SBUIntegerNormalizeRange(text->codeUnits.count, &index, &length);\n\n    /* Setup iterator boundary */\n    startIndex = index;\n    endIndex = index + length;\n    forwardMode = SBTrue;\n    paragraphIndex = SBInvalidIndex;\n\n    if (length > 0) {\n        /* Find out the index of the first paragraph */\n        paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, index);\n\n        if (iterator->visualDirectionMode) {\n            TextParagraphRef textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n            SBParagraphRef bidiParagraph = textParagraph->bidiParagraph;\n\n            forwardMode = (bidiParagraph->baseLevel & 1) == 0;\n\n            if (!forwardMode) {\n                SBUInteger paragraphEnd = bidiParagraph->offset + bidiParagraph->length;\n\n                if (paragraphEnd < endIndex) {\n                    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, endIndex - 1);\n                }\n            }\n        }\n    }\n\n    /* Initialize the iterator state */\n    iterator->forwardMode = forwardMode;\n    iterator->startIndex = startIndex;\n    iterator->endIndex = endIndex;\n    iterator->paragraphIndex = paragraphIndex;\n\n    /* Initialize the current element info to NULL */\n    iterator->currentParagraph = NULL;\n    iterator->paragraphStart = SBInvalidIndex;\n    iterator->paragraphEnd = SBInvalidIndex;\n}\n\nstatic SBBoolean AdvanceTextIterator(TextIteratorRef iterator)\n{\n    /* Get the text reference and calculate the remaining length */\n    SBTextRef text = iterator->text;\n    SBUInteger remainingLength = iterator->endIndex - iterator->startIndex;\n\n    if (remainingLength > 0) {\n        /* Get the current paragraph and its boundaries */\n        TextParagraphRef textParagraph = ListGetRef(&text->paragraphs, iterator->paragraphIndex);\n        SBUInteger paragraphStart = textParagraph->index;\n        SBUInteger paragraphEnd = paragraphStart + textParagraph->length;\n\n        /* Adjust the paragraph boundaries to iterator range */\n        if (paragraphStart <= iterator->startIndex) {\n            paragraphStart = iterator->startIndex;\n        }\n        if (paragraphEnd >= iterator->endIndex) {\n            paragraphEnd = iterator->endIndex;\n        }\n\n        /* Initialize the current element info */\n        iterator->currentParagraph = textParagraph;\n        iterator->paragraphStart = paragraphStart;\n        iterator->paragraphEnd = paragraphEnd;\n\n        /* Update iterator position based on the direction */\n        if (iterator->forwardMode) {\n            /* Move forward to the next paragraph */\n            iterator->startIndex = paragraphEnd;\n            iterator->paragraphIndex += 1;\n        } else {\n            /* Move backward to the previous paragraph */\n            iterator->endIndex = paragraphStart;\n            iterator->paragraphIndex -= 1;\n        }\n\n        return SBTrue;\n    }\n\n    /* No more text to process */\n    return SBFalse;\n}\n\n/* ==========================================================================\n * Paragraph Iterator Implementation\n * ========================================================================== */\n\n/**\n * Initializes a paragraph information structure.\n *\n * Sets default values for a paragraph's properties including its position, length, and base\n * embedding level.\n *\n * @param info\n *      Pointer to the paragraph info structure to initialize.\n */\nstatic void InitializeParagraphInfo(SBParagraphInfo *info)\n{\n    info->index = SBInvalidIndex;\n    info->length = 0;\n    info->baseLevel = 0;\n}\n\n/**\n * Cleans up resources associated with a paragraph iterator, including its parent text iterator.\n *\n * @param object\n *      The paragraph iterator to finalize.\n */\nstatic void FinalizeParagraphIterator(ObjectRef object)\n{\n    SBParagraphIteratorRef iterator = object;\n    FinalizeTextIterator(&iterator->parent);\n}\n\nSB_INTERNAL SBParagraphIteratorRef SBParagraphIteratorCreate(SBTextRef text)\n{\n    const SBUInteger size = sizeof(SBParagraphIterator);\n    void *pointer = NULL;\n    SBParagraphIteratorRef iterator;\n\n    /* Text MUST be available. */\n    SBAssert(text != NULL);\n\n    iterator = ObjectCreate(&size, 1, &pointer, FinalizeParagraphIterator);\n\n    if (iterator) {\n        InitializeTextIterator(&iterator->parent, text, SBFalse);\n        InitializeParagraphInfo(&iterator->currentParagraph);\n    }\n\n    return iterator;\n}\n\nSBTextRef SBParagraphIteratorGetText(SBParagraphIteratorRef iterator)\n{\n    return iterator->parent.text;\n}\n\nvoid SBParagraphIteratorReset(SBParagraphIteratorRef iterator, SBUInteger index, SBUInteger length)\n{\n    ResetTextIterator(&iterator->parent, index, length);\n    InitializeParagraphInfo(&iterator->currentParagraph);\n}\n\nconst SBParagraphInfo *SBParagraphIteratorGetCurrent(SBParagraphIteratorRef iterator)\n{\n    return &iterator->currentParagraph;\n}\n\nSBBoolean SBParagraphIteratorMoveNext(SBParagraphIteratorRef iterator)\n{\n    TextIteratorRef parent = &iterator->parent;\n\n    if (AdvanceTextIterator(parent)) {\n        TextParagraphRef textParagraph = parent->currentParagraph;\n        SBParagraphInfo *currentInfo;\n\n        currentInfo = &iterator->currentParagraph;\n        currentInfo->index = parent->paragraphStart;\n        currentInfo->length = parent->paragraphEnd - parent->paragraphStart;\n        currentInfo->baseLevel = textParagraph->bidiParagraph->baseLevel;\n\n        return SBTrue;\n    }\n\n    return SBFalse;\n}\n\nSBParagraphIteratorRef SBParagraphIteratorRetain(SBParagraphIteratorRef iterator)\n{\n    return ObjectRetain(iterator);\n}\n\nvoid SBParagraphIteratorRelease(SBParagraphIteratorRef iterator)\n{\n    ObjectRelease(iterator);\n}\n\n/* ==========================================================================\n * Logical Run Iterator Implementation\n * ========================================================================== */\n\n/**\n * Initializes a logical run structure.\n *\n * Sets default values for a logical run's properties including its position, length, and\n * bidirectional embedding level.\n *\n * @param run\n *      Pointer to the logical run structure to initialize.\n */\nstatic void InitializeLogicalRun(SBLogicalRun *run)\n{\n    run->index = SBInvalidIndex;\n    run->length = 0;\n    run->level = 0;\n}\n\n/**\n * Cleans up resources associated with a logical run iterator, including its parent text iterator.\n *\n * @param object\n *      The logical run iterator to finalize.\n */\nstatic void FinalizeLogicalRunIterator(ObjectRef object)\n{\n    SBLogicalRunIteratorRef iterator = object;\n    FinalizeTextIterator(&iterator->parent);\n}\n\nSB_INTERNAL SBLogicalRunIteratorRef SBLogicalRunIteratorCreate(SBTextRef text)\n{\n    const SBUInteger size = sizeof(SBLogicalRunIterator);\n    void *pointer = NULL;\n    SBLogicalRunIteratorRef iterator;\n\n    /* Text MUST be available. */\n    SBAssert(text != NULL);\n\n    iterator = ObjectCreate(&size, 1, &pointer, FinalizeLogicalRunIterator);\n\n    if (iterator) {\n        InitializeTextIterator(&iterator->parent, text, SBFalse);\n        InitializeLogicalRun(&iterator->currentRun);\n\n        iterator->levelIndex = SBInvalidIndex;\n    }\n\n    return iterator;\n}\n\nSBTextRef SBLogicalRunIteratorGetText(SBLogicalRunIteratorRef iterator)\n{\n    return iterator->parent.text;\n}\n\nvoid SBLogicalRunIteratorReset(SBLogicalRunIteratorRef iterator, SBUInteger index, SBUInteger length)\n{\n    ResetTextIterator(&iterator->parent, index, length);\n    InitializeLogicalRun(&iterator->currentRun);\n\n    iterator->levelIndex = SBInvalidIndex;\n}\n\nconst SBLogicalRun *SBLogicalRunIteratorGetCurrent(SBLogicalRunIteratorRef iterator)\n{\n    return &iterator->currentRun;\n}\n\nSBBoolean SBLogicalRunIteratorMoveNext(SBLogicalRunIteratorRef iterator)\n{\n    /* Get parent iterator and current paragraph */\n    TextIteratorRef parent = &iterator->parent;\n    TextParagraphRef textParagraph = parent->currentParagraph;\n\n    /* Check if we need to load a new paragraph */\n    if (iterator->levelIndex == SBInvalidIndex) {\n        SBLogicalRun *currentRun = &iterator->currentRun;\n        SBUInteger runStart = parent->startIndex;\n\n        /* Attempt to load the next paragraph */\n        if (AdvanceTextIterator(parent)) {\n            textParagraph = parent->currentParagraph;\n            iterator->levelIndex = 0;\n            currentRun->index = runStart;\n            currentRun->length = 0;\n        } else {\n            /* No more paragraphs available */\n            textParagraph = NULL;\n            InitializeLogicalRun(currentRun);\n        }\n    }\n\n    if (textParagraph) {\n        SBLogicalRun *currentRun = &iterator->currentRun;\n        SBUInteger paragraphLength = parent->paragraphEnd - parent->paragraphStart;\n        SBUInteger currentLevelStart = iterator->levelIndex;\n        SBParagraphRef bidiParagraph;\n        const SBLevel *embeddingLevels;\n        SBLevel currentLevel;\n\n        /* Get bidirectional information for the paragraph */\n        bidiParagraph = textParagraph->bidiParagraph;\n        embeddingLevels = &bidiParagraph->fixedLevels[parent->paragraphStart - bidiParagraph->offset];\n        currentLevel = embeddingLevels[iterator->levelIndex];\n\n        /* Find the end of the current level run */\n        while (++iterator->levelIndex < paragraphLength) {\n            if (embeddingLevels[iterator->levelIndex] != currentLevel) {\n                break;\n            }\n        }\n\n        /* Update the run information */\n        currentRun->index += currentRun->length;\n        currentRun->length = iterator->levelIndex - currentLevelStart;\n        currentRun->level = currentLevel;\n\n        /* Check if the end of the paragraph is reached */\n        if (iterator->levelIndex == paragraphLength) {\n            /* Prepare for the next paragraph */\n            iterator->levelIndex = SBInvalidIndex;\n        }\n\n        return SBTrue;\n    }\n\n    /* No more runs available */\n    return SBFalse;\n}\n\nSBLogicalRunIteratorRef SBLogicalRunIteratorRetain(SBLogicalRunIteratorRef iterator)\n{\n    return ObjectRetain(iterator);\n}\n\nvoid SBLogicalRunIteratorRelease(SBLogicalRunIteratorRef iterator)\n{\n    ObjectRelease(iterator);\n}\n\n/* ==========================================================================\n * Script Run Iterator Implementation\n * ========================================================================== */\n\n/**\n * Initializes a script run structure.\n *\n * Sets default values for a script run's properties including its position, length, and writing\n * script identifier.\n *\n * @param run\n *      Pointer to the script run structure to initialize.\n */\nstatic void InitializeScriptRun(SBScriptRun *run)\n{\n    run->index = SBInvalidIndex;\n    run->length = 0;\n    run->script = SBScriptNil;\n}\n\n/**\n * Cleans up resources associated with a script run iterator, including its parent text iterator.\n *\n * @param object The script run iterator to finalize.\n */\nstatic void FinalizeScriptRunIterator(ObjectRef object)\n{\n    SBScriptRunIteratorRef iterator = object;\n    FinalizeTextIterator(&iterator->parent);\n}\n\nSB_INTERNAL SBScriptRunIteratorRef SBScriptRunIteratorCreate(SBTextRef text)\n{\n    const SBUInteger size = sizeof(SBScriptRunIterator);\n    void *pointer = NULL;\n    SBScriptRunIteratorRef iterator;\n\n    /* Text MUST be available. */\n    SBAssert(text != NULL);\n\n    iterator = ObjectCreate(&size, 1, &pointer, FinalizeScriptRunIterator);\n\n    if (iterator) {\n        InitializeTextIterator(&iterator->parent, text, SBFalse);\n        InitializeScriptRun(&iterator->currentRun);\n\n        iterator->scriptIndex = SBInvalidIndex;\n    }\n\n    return iterator;\n}\n\nSBTextRef SBScriptRunIteratorGetText(SBScriptRunIteratorRef iterator)\n{\n    return iterator->parent.text;\n}\n\nvoid SBScriptRunIteratorReset(SBScriptRunIteratorRef iterator, SBUInteger index, SBUInteger length)\n{\n    ResetTextIterator(&iterator->parent, index, length);\n    InitializeScriptRun(&iterator->currentRun);\n\n    iterator->scriptIndex = SBInvalidIndex;\n}\n\nconst SBScriptRun *SBScriptRunIteratorGetCurrent(SBScriptRunIteratorRef iterator)\n{\n    return &iterator->currentRun;\n}\n\nSBBoolean SBScriptRunIteratorMoveNext(SBScriptRunIteratorRef iterator)\n{\n    /* Get parent iterator and current paragraph */\n    TextIteratorRef parent = &iterator->parent;\n    TextParagraphRef textParagraph = parent->currentParagraph;\n\n    /* Check if there's a need to load a new paragraph */\n    if (iterator->scriptIndex == SBInvalidIndex) {\n        SBScriptRun *currentRun = &iterator->currentRun;\n        SBUInteger runStart = parent->startIndex;\n\n        /* Attempt to load the next paragraph */\n        if (AdvanceTextIterator(parent)) {\n            textParagraph = parent->currentParagraph;\n            iterator->scriptIndex = 0;\n            currentRun->index = runStart;\n            currentRun->length = 0;\n        } else {\n            /* No more paragraphs available */\n            textParagraph = NULL;\n            InitializeScriptRun(currentRun);\n        }\n    }\n\n    if (textParagraph) {\n        SBScriptRun *currentRun = &iterator->currentRun;\n        SBUInteger paragraphLength = parent->paragraphEnd - parent->paragraphStart;\n        SBUInteger scriptStart = iterator->scriptIndex;\n        const SBScript *scriptArray;\n        SBScript currentScript;\n\n        /* Get script information for the paragraph */\n        scriptArray = textParagraph->scripts.items;\n        currentScript = scriptArray[iterator->scriptIndex];\n\n        /* Find the end of the current script run */\n        while (++iterator->scriptIndex < paragraphLength) {\n            if (scriptArray[iterator->scriptIndex] != currentScript) {\n                break;\n            }\n        }\n\n        /* Update the run information */\n        currentRun->index += currentRun->length;\n        currentRun->length = iterator->scriptIndex - scriptStart;\n        currentRun->script = currentScript;\n\n        /* Check if the end of the paragraph is reached */\n        if (iterator->scriptIndex == paragraphLength) {\n            /* Prepare for the next paragraph */\n            iterator->scriptIndex = SBInvalidIndex;\n        }\n\n        return SBTrue;\n    }\n\n    /* No more runs available */\n    return SBFalse;\n}\n\nSBScriptRunIteratorRef SBScriptRunIteratorRetain(SBScriptRunIteratorRef iterator)\n{\n    return ObjectRetain(iterator);\n}\n\nvoid SBScriptRunIteratorRelease(SBScriptRunIteratorRef iterator)\n{\n    ObjectRelease(iterator);\n}\n\n/* ==========================================================================\n * Attribute Run Iterator Implementation\n * ========================================================================== */\n\n/**\n * Initializes an attribute run structure.\n *\n * Sets default values for an attribute run's properties including its position, length, and\n * attribute collection information.\n *\n * @param run\n *      Pointer to the attribute run structure to initialize.\n */\nstatic void InitializeAttributeRun(SBAttributeRun *run)\n{\n    run->index = SBInvalidIndex;\n    run->length = 0;\n    run->attributes = NULL;\n}\n\n/**\n * Cleans up resources associated with an attribute run iterator, including the text reference and\n * attribute item list.\n *\n * @param object\n *      The attribute run iterator to finalize.\n */\nstatic void FinalizeAttributeRunIterator(ObjectRef object)\n{\n    SBAttributeRunIteratorRef iterator = object;\n\n    SBTextRelease(iterator->text);\n    AttributeDictionaryFinalize(&iterator->items, NULL);\n}\n\n/**\n * Advances the iterator to find the next run of text that contains attributes matching the\n * specified ID filter.\n *\n * @param iterator\n *      The attribute run iterator.\n * @return\n *      `SBTrue` if a matching run was found, `SBFalse` if the end was reached.\n */\nstatic SBBoolean LoadOnwardAttributeRunByFilteringID(SBAttributeRunIteratorRef iterator)\n{\n    SBTextRef text = iterator->text;\n    AttributeManagerRef manager = (AttributeManagerRef)&text->attributeManager;\n    SBAttributeRun *currentRun = &iterator->currentRun;\n    SBUInteger index;\n    SBBoolean result;\n\n    index = iterator->currentIndex;\n    result = AttributeManagerGetOnwardRunByFilteringID(manager, &index, iterator->endIndex,\n        iterator->filterAttributeID, &iterator->items);\n\n    /* Populate the current run */\n    currentRun->index = iterator->currentIndex;\n    currentRun->length = index - iterator->currentIndex;\n    currentRun->attributes = &iterator->items._list;\n\n    iterator->currentIndex = index;\n\n    return result;\n}\n\n/**\n * Advances the iterator to find the next run of text that contains attributes matching the\n * specified scope and group filters.\n *\n * @param iterator\n *      The attribute run iterator.\n * @return\n *      `SBTrue` if a matching run was found, `SBFalse` if the end was reached.\n */\nstatic SBBoolean LoadOnwardAttributeRunByFilteringCollection(SBAttributeRunIteratorRef iterator)\n{\n    SBTextRef text = iterator->text;\n    AttributeManagerRef manager = (AttributeManagerRef)&text->attributeManager;\n    SBAttributeRun *currentRun = &iterator->currentRun;\n    SBUInteger index;\n    SBBoolean result;\n\n    index = iterator->currentIndex;\n    result = AttributeManagerGetOnwardRunByFilteringCollection(manager, &index, iterator->endIndex,\n        iterator->filterScope, iterator->filterGroup, &iterator->items);\n\n    /* Populate the current run */\n    currentRun->index = iterator->currentIndex;\n    currentRun->length = index - iterator->currentIndex;\n    currentRun->attributes = &iterator->items._list;\n\n    iterator->currentIndex = index;\n\n    return result;\n}\n\nSB_INTERNAL SBAttributeRunIteratorRef SBAttributeRunIteratorCreate(SBTextRef text)\n{\n    const SBUInteger size = sizeof(SBAttributeRunIterator);\n    void *pointer = NULL;\n    SBAttributeRunIteratorRef iterator;\n\n    /* Text MUST be available. */\n    SBAssert(text != NULL);\n\n    iterator = ObjectCreate(&size, 1, &pointer, FinalizeAttributeRunIterator);\n\n    if (iterator) {\n        iterator->text = SBTextRetain(text);\n        iterator->startIndex = 0;\n        iterator->endIndex = text->codeUnits.count;\n        iterator->currentIndex = SBInvalidIndex;\n        iterator->filterAttributeID = SBAttributeIDNone;\n        iterator->filterGroup = SBAttributeGroupNone;\n        iterator->filterScope = SBAttributeScopeCharacter;\n\n        AttributeDictionaryInitialize(&iterator->items, text->attributeRegistry->valueSize);\n        InitializeAttributeRun(&iterator->currentRun);\n    }\n\n    return iterator;\n}\n\nSBTextRef SBAttributeRunIteratorGetText(SBAttributeRunIteratorRef iterator)\n{\n    return iterator->text;\n}\n\nvoid SBAttributeRunIteratorSetupAttributeID(SBAttributeRunIteratorRef iterator, SBAttributeID attributeID)\n{\n    iterator->filterAttributeID = attributeID;\n    iterator->filterGroup = SBAttributeGroupNone;\n\n    /* Reset the iterator */\n    iterator->currentIndex = SBInvalidIndex;\n    InitializeAttributeRun(&iterator->currentRun);\n}\n\nvoid SBAttributeRunIteratorSetupAttributeCollection(SBAttributeRunIteratorRef iterator,\n    SBAttributeGroup group, SBAttributeScope scope)\n{\n    iterator->filterAttributeID = SBAttributeIDNone;\n    iterator->filterGroup = group;\n    iterator->filterScope = scope;\n\n    /* Reset the iterator */\n    iterator->currentIndex = SBInvalidIndex;\n    InitializeAttributeRun(&iterator->currentRun);\n}\n\nvoid SBAttributeRunIteratorReset(SBAttributeRunIteratorRef iterator,\n    SBUInteger index, SBUInteger length)\n{\n    iterator->startIndex = index;\n    iterator->endIndex = index + length;\n    iterator->currentIndex = SBInvalidIndex;\n    InitializeAttributeRun(&iterator->currentRun);\n}\n\nconst SBAttributeRun *SBAttributeRunIteratorGetCurrent(SBAttributeRunIteratorRef iterator)\n{\n    return &iterator->currentRun;\n}\n\nSBBoolean SBAttributeRunIteratorMoveNext(SBAttributeRunIteratorRef iterator)\n{\n    SBBoolean hasRun = SBFalse;\n\n    if (iterator->currentIndex == SBInvalidIndex) {\n        iterator->currentIndex = iterator->startIndex;\n    }\n\n    while (iterator->currentIndex < iterator->endIndex) {\n        if (iterator->filterAttributeID != SBAttributeIDNone) {\n            hasRun = LoadOnwardAttributeRunByFilteringID(iterator);\n        } else {\n            hasRun = LoadOnwardAttributeRunByFilteringCollection(iterator);\n        }\n\n        /* Skip the empty run */\n        if (hasRun && SBAttributeListSize(iterator->currentRun.attributes) == 0) {\n            hasRun = SBFalse;\n            continue;\n        }\n\n        break;\n    }\n\n    if (!hasRun) {\n        InitializeAttributeRun(&iterator->currentRun);\n    }\n\n    return hasRun;\n}\n\nSBAttributeRunIteratorRef SBAttributeRunIteratorRetain(SBAttributeRunIteratorRef iterator)\n{\n    return ObjectRetain(iterator);\n}\n\nvoid SBAttributeRunIteratorRelease(SBAttributeRunIteratorRef iterator)\n{\n    ObjectRelease(iterator);\n}\n\n/* ==========================================================================\n * Visual Run Iterator Implementation\n * ========================================================================== */\n\n/**\n * Initializes a visual run structure.\n *\n * Sets default values for a visual run's properties including its position, length, and\n * bidirectional embedding level in visual order.\n *\n * @param run\n *      Pointer to the visual run structure to initialize.\n */\nstatic void InitializeVisualRun(SBVisualRun *run)\n{\n    run->index = SBInvalidIndex;\n    run->length = 0;\n    run->level = 0;\n}\n\n/**\n * Cleans up resources associated with a visual run iterator, including the bidirectional line\n * object and parent text iterator.\n *\n * @param object\n *      The visual run iterator to finalize.\n */\nstatic void FinalizeVisualRunIterator(ObjectRef object)\n{\n    SBVisualRunIteratorRef iterator = object;\n\n    if (iterator->bidiLine) {\n        SBLineRelease(iterator->bidiLine);\n    }\n\n    FinalizeTextIterator(&iterator->parent);\n}\n\nSB_INTERNAL SBVisualRunIteratorRef SBVisualRunIteratorCreate(SBTextRef text)\n{\n    const SBUInteger size = sizeof(SBText);\n    void *pointer = NULL;\n    SBVisualRunIteratorRef iterator;\n\n    /* Text MUST be available. */\n    SBAssert(text != NULL);\n\n    iterator = ObjectCreate(&size, 1, &pointer, FinalizeVisualRunIterator);\n\n    if (iterator) {\n        InitializeTextIterator(&iterator->parent, text, SBTrue);\n        InitializeVisualRun(&iterator->currentRun);\n\n        iterator->bidiLine = NULL;\n        iterator->runIndex = SBInvalidIndex;\n    }\n\n    return iterator;\n}\n\nSBTextRef SBVisualRunIteratorGetText(SBVisualRunIteratorRef iterator)\n{\n    return iterator->parent.text;\n}\n\nvoid SBVisualRunIteratorReset(SBVisualRunIteratorRef iterator, SBUInteger index, SBUInteger length)\n{\n    ResetTextIterator(&iterator->parent, index, length);\n    InitializeVisualRun(&iterator->currentRun);\n\n    iterator->bidiLine = NULL;\n    iterator->runIndex = SBInvalidIndex;\n}\n\nconst SBVisualRun *SBVisualRunIteratorGetCurrent(SBVisualRunIteratorRef iterator)\n{\n    return &iterator->currentRun;\n}\n\nSBBoolean SBVisualRunIteratorMoveNext(SBVisualRunIteratorRef iterator)\n{\n    SBLineRef bidiLine = iterator->bidiLine;\n\n    if (!bidiLine) {\n        TextIteratorRef parentIterator = &iterator->parent;\n\n        /* Try to advance to the next paragraph */\n        if (AdvanceTextIterator(parentIterator)) {\n            /* Get paragraph information */\n            TextParagraphRef textParagraph = parentIterator->currentParagraph;\n            SBParagraphRef bidiParagraph = textParagraph->bidiParagraph;\n            SBUInteger paragraphStart;\n            SBUInteger paragraphLength;\n\n            /* Calculate paragraph boundaries */\n            paragraphStart = parentIterator->paragraphStart;\n            paragraphLength = parentIterator->paragraphEnd - paragraphStart;\n\n            /* Create a new bidirectional line from the paragraph */\n            bidiLine = SBParagraphCreateLine(bidiParagraph, paragraphStart, paragraphLength);\n\n            /* Initialize line processing */\n            iterator->bidiLine = bidiLine;\n            iterator->runIndex = 0;\n        }\n\n        /* Reset the current run state */\n        InitializeVisualRun(&iterator->currentRun);\n    }\n\n    if (bidiLine) {\n        SBVisualRun *currentRun = &iterator->currentRun;\n        SBRun *bidiRun;\n\n        /* Get the current bidirectional run */\n        bidiRun = &bidiLine->fixedRuns[iterator->runIndex];\n\n        /* Update the current run with bidirectional properties */\n        currentRun->index = bidiRun->offset;\n        currentRun->length = bidiRun->length;\n        currentRun->level = bidiRun->level;\n\n        /* Move to the next run in the line */\n        iterator->runIndex += 1;\n\n        /* Check if all runs in the line are processed */\n        if (iterator->runIndex == bidiLine->runCount) {\n            /* Clean up and prepare for the next line */\n            SBLineRelease(bidiLine);\n            iterator->bidiLine = NULL;\n        }\n\n        return SBTrue;\n    }\n\n    /* No more runs available */\n    return SBFalse;\n}\n\nSBVisualRunIteratorRef SBVisualRunIteratorRetain(SBVisualRunIteratorRef iterator)\n{\n    return ObjectRetain(iterator);\n}\n\nvoid SBVisualRunIteratorRelease(SBVisualRunIteratorRef iterator)\n{\n    ObjectRelease(iterator);\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/API/SBTextIterators.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_TEXT_ITERATORS_H\n#define _SB_INTERNAL_TEXT_ITERATORS_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBLine.h>\n#include <SheenBidi/SBTextIterators.h>\n\n#include <API/SBText.h>\n#include <Core/Object.h>\n#include <Text/AttributeDictionary.h>\n\ntypedef struct _TextIterator {\n    SBTextRef text;\n    SBBoolean visualDirectionMode;\n    SBBoolean forwardMode;\n    SBUInteger startIndex;\n    SBUInteger endIndex;\n    SBUInteger paragraphIndex;\n    TextParagraphRef currentParagraph;\n    SBUInteger paragraphStart;\n    SBUInteger paragraphEnd;\n} TextIterator, *TextIteratorRef;\n\ntypedef struct _SBParagraphIterator {\n    ObjectBase _base;\n    TextIterator parent;\n    SBParagraphInfo currentParagraph;\n} SBParagraphIterator;\n\ntypedef struct _SBLogicalRunIterator {\n    ObjectBase _base;\n    TextIterator parent;\n    SBUInteger levelIndex;\n    SBLogicalRun currentRun;\n} SBLogicalRunIterator;\n\ntypedef struct _SBScriptRunIterator {\n    ObjectBase _base;\n    TextIterator parent;\n    SBUInteger scriptIndex;\n    SBScriptRun currentRun;\n} SBScriptRunIterator;\n\ntypedef struct _SBAttributeRunIterator {\n    ObjectBase _base;\n    SBTextRef text;\n    AttributeDictionary items;\n    SBUInteger startIndex;\n    SBUInteger endIndex;\n    SBUInteger currentIndex;\n    SBAttributeRun currentRun;\n    SBAttributeID filterAttributeID;\n    SBAttributeGroup filterGroup;\n    SBAttributeScope filterScope;\n} SBAttributeRunIterator;\n\ntypedef struct _SBVisualRunIterator {\n    ObjectBase _base;\n    TextIterator parent;\n    SBLineRef bidiLine;\n    SBUInteger runIndex;\n    SBVisualRun currentRun;\n} SBVisualRunIterator;\n\n/**\n * Creates and initializes an iterator that can traverse through paragraphs in the given text. Each\n * paragraph represents a sequence of text with consistent bidirectional properties.\n *\n * @param text\n *      The text to iterate through.\n * @return\n *      A new paragraph iterator object, or NULL if creation fails.\n */\nSB_INTERNAL SBParagraphIteratorRef SBParagraphIteratorCreate(SBTextRef text);\n\n/**\n * Creates and initializes an iterator that can traverse through runs of text with consistent\n * bidirectional embedding levels. Logical runs represent text segments that have the same\n * bidirectional properties in their logical order.\n *\n * @param text\n *      The text to iterate through.\n * @return\n *      A new logical run iterator object, or NULL if creation fails.\n */\nSB_INTERNAL SBLogicalRunIteratorRef SBLogicalRunIteratorCreate(SBTextRef text);\n\n/**\n * Creates and initializes an iterator that can traverse through runs of text with consistent\n * writing scripts. Script runs represent text segments that use the same writing system (e.g.,\n * Latin, Arabic, Devanagari).\n *\n * @param text\n *      The text to iterate through.\n * @return\n *      A new script run iterator object, or NULL if creation fails.\n */\nSB_INTERNAL SBScriptRunIteratorRef SBScriptRunIteratorCreate(SBTextRef text);\n\n/**\n * Creates and initializes an iterator that can traverse through runs of text with consistent\n * attribute properties. Attribute runs represent text segments that share common formatting or\n * metadata attributes.\n *\n * @param text\n *      The text to iterate through.\n * @return\n *      A new attribute run iterator object, or NULL if creation fails.\n */\nSB_INTERNAL SBAttributeRunIteratorRef SBAttributeRunIteratorCreate(SBTextRef text);\n\n/**\n * Creates and initializes an iterator that can traverse through runs of text in visual order\n * (display order) according to the Unicode Bidirectional Algorithm. Visual runs represent text\n * segments as they should appear on screen.\n *\n * @param text\n *      The text to iterate through.\n * @return\n *      A new visual run iterator object, or NULL if creation fails.\n */\nSB_INTERNAL SBVisualRunIteratorRef SBVisualRunIteratorCreate(SBTextRef text);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/AtomicFlag.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATOMIC_FLAG_H\n#define _SB_INTERNAL_ATOMIC_FLAG_H\n\n#include <API/SBBase.h>\n\n/* Define data type for atomic flag. */\n#ifdef USE_C11_ATOMICS\n\n#include <stdatomic.h>\n#define HAS_ATOMIC_FLAG_SUPPORT\ntypedef atomic_flag AtomicFlag;\n\n#elif defined(USE_ATOMIC_BUILTINS) || defined(USE_SYNC_BUILTINS)\n\n#define HAS_ATOMIC_FLAG_SUPPORT\ntypedef SBBoolean AtomicFlag;\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#include <intrin.h>\n#define HAS_ATOMIC_FLAG_SUPPORT\n#pragma intrinsic(_InterlockedExchange8)\ntypedef volatile char AtomicFlag;\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#include <windows.h>\n#define HAS_ATOMIC_FLAG_SUPPORT\ntypedef volatile LONG AtomicFlag;\n\n#else\n\ntypedef SBBoolean AtomicFlag;\n\n#endif\n\ntypedef AtomicFlag *AtomicFlagRef;\n\n/* Define functions for atomic flag. */\n#if defined(USE_C11_ATOMICS)\n\n#define AtomicFlagMake()            ATOMIC_FLAG_INIT\n#define AtomicFlagTestAndSet(flag)  ((SBBoolean)atomic_flag_test_and_set(flag))\n#define AtomicFlagClear(flag)       atomic_flag_clear(flag)\n\n#elif defined(USE_ATOMIC_BUILTINS)\n\n#define AtomicFlagMake()            SBFalse\n#define AtomicFlagTestAndSet(flag)  __atomic_test_and_set(flag, __ATOMIC_SEQ_CST)\n#define AtomicFlagClear(flag)       __atomic_clear(flag, __ATOMIC_SEQ_CST)\n\n#elif defined(USE_SYNC_BUILTINS)\n\n#define AtomicFlagMake()            SBFalse\n#define AtomicFlagTestAndSet(flag)  __sync_lock_test_and_set(flag, SBTrue)\n#define AtomicFlagClear(flag)       __sync_lock_release(flag)\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#define AtomicFlagMake()            0\n#define AtomicFlagTestAndSet(flag)  (_InterlockedExchange8(flag, 1) == 1)\n#define AtomicFlagClear(flag)       _InterlockedExchange8(flag, 0)\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#define AtomicFlagMake()            0\n#define AtomicFlagTestAndSet(flag)  (InterlockedExchange(flag, 1) == 1)\n#define AtomicFlagClear(flag)       InterlockedExchange(flag, 0)\n\n#else /* Non-atomic fallback */\n\n#define AtomicFlagMake()            SBFalse\n#define AtomicFlagTestAndSet(flag)  (*(flag) ? SBTrue : (*(flag) = SBTrue, SBFalse))\n#define AtomicFlagClear(flag)       (*(flag) = SBFalse)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/AtomicPointer.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATOMIC_POINTER_H\n#define _SB_INTERNAL_ATOMIC_POINTER_H\n\n#include <API/SBBase.h>\n\n/* Define data type for atomic pointer. */\n#ifdef USE_C11_ATOMICS\n\n#include <stdatomic.h>\n#define HAS_ATOMIC_POINTER_SUPPORT\ntypedef _Atomic(void *) AtomicPointer;\n#define AtomicPointerType(type) _Atomic(type *)\n\n#elif defined(USE_ATOMIC_BUILTINS) || defined(USE_SYNC_BUILTINS)\n\n#define HAS_ATOMIC_POINTER_SUPPORT\ntypedef void *AtomicPointer;\n#define AtomicPointerType(type) type *\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#include <intrin.h>\n#define HAS_ATOMIC_POINTER_SUPPORT\n#pragma intrinsic(_InterlockedExchangePointer, _InterlockedCompareExchangePointer)\ntypedef void * volatile AtomicPointer;\n#define AtomicPointerType(type) type * volatile\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#include <windows.h>\n#define HAS_ATOMIC_POINTER_SUPPORT\ntypedef void * volatile AtomicPointer;\n#define AtomicPointerType(type) type * volatile\n\n#else\n\ntypedef void *AtomicPointer;\n#define AtomicPointerType(type) type *\n\n#endif\n\ntypedef AtomicPointer *AtomicPointerRef;\n\n/* Define functions for atomic pointer. */\n#if defined(USE_C11_ATOMICS)\n\n#define AtomicPointerLoad(pointer)                              \\\n    atomic_load(pointer)\n#define AtomicPointerStore(pointer, value)                      \\\n    atomic_store(pointer, value)\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    atomic_compare_exchange_strong(pointer, expected, desired)\n\n#elif defined(USE_ATOMIC_BUILTINS)\n\n#define AtomicPointerLoad(pointer)                              \\\n    __atomic_load_n(pointer, __ATOMIC_SEQ_CST)\n#define AtomicPointerStore(pointer, value)                      \\\n    __atomic_store_n(pointer, value, __ATOMIC_SEQ_CST)\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    __atomic_compare_exchange_n(pointer, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#elif defined(USE_SYNC_BUILTINS)\n\n#define AtomicPointerLoad(pointer)                              \\\n    __sync_fetch_and_add(pointer, 0)\n#define AtomicPointerStore(pointer, value)                      \\\n    __sync_lock_test_and_set(pointer, value)\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    __sync_bool_compare_and_swap(pointer, *(expected), desired)\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#define AtomicPointerLoad(pointer)                              \\\n    _InterlockedCompareExchangePointer((AtomicPointerRef)(pointer), NULL, NULL)\n#define AtomicPointerStore(pointer, value)                      \\\n    _InterlockedExchangePointer((AtomicPointerRef)(pointer), (void *)(value))\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    (_InterlockedCompareExchangePointer((AtomicPointerRef)(pointer), (void *)(desired), (void *)(*(expected))) == *(expected))\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#ifdef _WIN64\n#define AtomicPointerLoad(pointer)                              \\\n    ((void *)InterlockedCompareExchange64((LONG64 volatile *)(pointer), 0, 0))\n#define AtomicPointerStore(pointer, value)                      \\\n    InterlockedExchange64((LONG64 volatile *)(pointer), (LONG64)(value))\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    (((void *)InterlockedCompareExchange64((LONG64 volatile *)(pointer), (LONG64)(desired), (LONG64)(*(expected)))) == *(expected))\n#else\n#define AtomicPointerLoad(pointer)                              \\\n    ((void *)InterlockedCompareExchange((LONG volatile *)(pointer), 0, 0))\n#define AtomicPointerStore(pointer, value)                      \\\n    InterlockedExchange((LONG volatile *)(pointer), (LONG)(value))\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    (((void *)InterlockedCompareExchange((LONG volatile *)(pointer), (LONG)(desired), (LONG)(*(expected)))) == *(expected))\n#endif\n\n#else /* Non-atomic fallback */\n\n#define AtomicPointerLoad(pointer)                              \\\n    (*(pointer))\n#define AtomicPointerStore(pointer, value)                      \\\n    (*(pointer) = (value))\n#define AtomicPointerCompareAndSet(pointer, expected, desired)  \\\n    ((*(pointer) == *(expected)) ? ((*(pointer) = (desired)), SBTrue) : SBFalse)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/AtomicUInt.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATOMIC_UINT_H\n#define _SB_INTERNAL_ATOMIC_UINT_H\n\n#include <API/SBBase.h>\n\n/* Define data type for atomic uint. */\n#ifdef USE_C11_ATOMICS\n\n#include <stdatomic.h>\n#define HAS_ATOMIC_UINT_SUPPORT\ntypedef _Atomic(SBUInteger) AtomicUInt;\n\n#elif defined(USE_ATOMIC_BUILTINS) || defined(USE_SYNC_BUILTINS)\n\n#define HAS_ATOMIC_UINT_SUPPORT\ntypedef SBUInteger AtomicUInt;\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#include <intrin.h>\n#define HAS_ATOMIC_UINT_SUPPORT\n#ifdef _WIN64\n#pragma intrinsic(_InterlockedExchange64, _InterlockedCompareExchange64)\n#pragma intrinsic(_InterlockedIncrement64, _InterlockedDecrement64)\ntypedef volatile __int64 AtomicUInt;\n#else\n#pragma intrinsic(_InterlockedExchange, _InterlockedCompareExchange)\n#pragma intrinsic(_InterlockedIncrement, _InterlockedDecrement)\ntypedef volatile long AtomicUInt;\n#endif\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#include <windows.h>\n#define HAS_ATOMIC_UINT_SUPPORT\n#ifdef _WIN64\ntypedef volatile LONG64 AtomicUInt;\n#else\ntypedef volatile LONG AtomicUInt;\n#endif\n\n#else\n\ntypedef SBUInteger AtomicUInt;\n\n#endif\n\ntypedef AtomicUInt *AtomicUIntRef;\n\n/* Define functions for atomic uint. */\n#if defined(USE_C11_ATOMICS)\n\n#define AtomicUIntInitialize(aui, value)    atomic_init(aui, value)\n#define AtomicUIntLoad(aui)                 atomic_load(aui)\n#define AtomicUIntStore(aui, value)         atomic_store(aui, value)\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    atomic_compare_exchange_strong(aui, expected, desired)\n#define AtomicUIntIncrement(aui)            ((SBUInteger)(atomic_fetch_add(aui, 1) + 1))\n#define AtomicUIntDecrement(aui)            ((SBUInteger)(atomic_fetch_sub(aui, 1) - 1))\n\n#elif defined(USE_ATOMIC_BUILTINS)\n\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (value))\n#define AtomicUIntLoad(aui)                 __atomic_load_n(aui, __ATOMIC_SEQ_CST)\n#define AtomicUIntStore(aui, value)         __atomic_store_n(aui, value, __ATOMIC_SEQ_CST)\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    __atomic_compare_exchange_n(aui, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n#define AtomicUIntIncrement(aui)            __atomic_add_fetch(aui, 1, __ATOMIC_SEQ_CST)\n#define AtomicUIntDecrement(aui)            __atomic_sub_fetch(aui, 1, __ATOMIC_SEQ_CST)\n\n#elif defined(USE_SYNC_BUILTINS)\n\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (value))\n#define AtomicUIntLoad(aui)                 __sync_fetch_and_add(aui, 0)\n#define AtomicUIntStore(aui, value)         __sync_lock_test_and_set(aui, value)\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    __sync_bool_compare_and_swap(aui, *(expected), desired)\n#define AtomicUIntIncrement(aui)            __sync_add_and_fetch(aui, 1)\n#define AtomicUIntDecrement(aui)            __sync_sub_and_fetch(aui, 1)\n\n#elif defined(USE_WIN_INTRINSICS)\n\n#ifdef _WIN64\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (__int64)(value))\n#define AtomicUIntLoad(aui)                 ((SBUInteger)_InterlockedCompareExchange64(aui, 0, 0))\n#define AtomicUIntStore(aui, value)         _InterlockedExchange64(aui, (__int64)(value))\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    (((SBUInteger)_InterlockedCompareExchange64(aui, (__int64)(desired), (__int64)(*(expected)))) == *(expected))\n#define AtomicUIntIncrement(aui)            ((SBUInteger)_InterlockedIncrement64(aui))\n#define AtomicUIntDecrement(aui)            ((SBUInteger)_InterlockedDecrement64(aui))\n#else\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (long)(value))\n#define AtomicUIntLoad(aui)                 ((SBUInteger)_InterlockedCompareExchange(aui, 0, 0))\n#define AtomicUIntStore(aui, value)         _InterlockedExchange(aui, (long)(value))\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    (((SBUInteger)_InterlockedCompareExchange(aui, (long)(desired), (long)(*(expected)))) == *(expected))\n#define AtomicUIntIncrement(aui)            ((SBUInteger)_InterlockedIncrement(aui))\n#define AtomicUIntDecrement(aui)            ((SBUInteger)_InterlockedDecrement(aui))\n#endif\n\n#elif defined(USE_WIN_INTERLOCKED)\n\n#ifdef _WIN64\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (LONG64)(value))\n#define AtomicUIntLoad(aui)                 ((SBUInteger)InterlockedCompareExchange64(aui, 0, 0))\n#define AtomicUIntStore(aui, value)         InterlockedExchange64(aui, (LONG64)(value))\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    (((SBUInteger)InterlockedCompareExchange64(aui, (LONG64)(desired), (LONG64)(*(expected)))) == *(expected))\n#define AtomicUIntIncrement(aui)            ((SBUInteger)InterlockedIncrement64(aui))\n#define AtomicUIntDecrement(aui)            ((SBUInteger)InterlockedDecrement64(aui))\n#else\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (LONG)(value))\n#define AtomicUIntLoad(aui)                 ((SBUInteger)InterlockedCompareExchange(aui, 0, 0))\n#define AtomicUIntStore(aui, value)         InterlockedExchange(aui, (LONG)(value))\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    (((SBUInteger)InterlockedCompareExchange(aui, (LONG)(desired), (LONG)(*(expected)))) == *(expected))\n#define AtomicUIntIncrement(aui)            ((SBUInteger)InterlockedIncrement(aui))\n#define AtomicUIntDecrement(aui)            ((SBUInteger)InterlockedDecrement(aui))\n#endif\n\n#else /* Non-atomic fallback */\n\n#define AtomicUIntInitialize(aui, value)    (*(aui) = (value))\n#define AtomicUIntLoad(aui)                 (*(aui))\n#define AtomicUIntCompareAndSet(aui, expected, desired) \\\n    ((*(aui) == *(expected)) ? ((*(aui) = (desired)), SBTrue) : SBFalse)\n#define AtomicUIntStore(aui, value)         (*(aui) = (value))\n#define AtomicUIntIncrement(aui)            (++(*(aui)))\n#define AtomicUIntDecrement(aui)            (--(*(aui)))\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/List.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <API/SBAllocator.h>\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n\n#include \"List.h\"\n\n#define DEFAULT_LIST_CAPACITY 4\n\nSB_PRIVATE void InitializeList(ListRef list, SBUInteger itemSize)\n{\n    /* Item size MUST be greater than 0. */\n    SBAssert(itemSize > 0);\n\n    list->data = NULL;\n    list->count = 0;\n    list->capacity = 0;\n    list->itemSize = itemSize;\n}\n\nSB_PRIVATE void FinalizeItemsBuffer(ListRef list)\n{\n    if (list->data) {\n        SBAllocatorDeallocateBlock(NULL, list->data);\n    }\n}\n\nSB_PRIVATE void ExtractItemsBuffer(ListRef list, void **outArray, SBUInteger *outCount)\n{\n    if (list->count > 0) {\n        SetItemCapacity(list, list->count);\n\n        *outArray = list->data;\n        *outCount = list->count;\n    } else {\n        FinalizeItemsBuffer(list);\n\n        *outArray = NULL;\n        *outCount = 0;\n    }\n}\n\nSB_PRIVATE SBBoolean SetItemCapacity(ListRef list, SBUInteger capacity)\n{\n    /* The new capacity must be larger than total number of elements in the list. */\n    SBAssert(capacity >= list->count);\n\n    if (capacity != list->capacity) {\n        SBBoolean isAllocated = SBFalse;\n        void *block;\n\n        if (list->data) {\n            block = SBAllocatorReallocateBlock(NULL, list->data, list->itemSize * capacity);\n        } else {\n            block = SBAllocatorAllocateBlock(NULL, list->itemSize * capacity);\n        }\n\n        if (block) {\n            list->data = block;\n            list->capacity = capacity;\n\n            isAllocated = SBTrue;\n        }\n\n        return isAllocated;\n    }\n\n    return SBTrue;\n}\n\nstatic SBBoolean EnsureItemCapacity(ListRef list, SBUInteger capacity)\n{\n    SBBoolean isEnsured = SBTrue;\n\n    if (list->capacity < capacity) {\n        SBUInteger newCapacity = (list->capacity ? list->count * 2 : DEFAULT_LIST_CAPACITY);\n        if (newCapacity < capacity) {\n            newCapacity = capacity;\n        }\n\n        isEnsured = SetItemCapacity(list, newCapacity);\n    }\n\n    return isEnsured;\n}\n\nstatic void MoveItemRange(ListRef list, SBUInteger srcIndex,\n    SBUInteger dstIndex, SBUInteger itemCount)\n{\n    /* The capacity must be available to move the block. */\n    SBAssert((srcIndex + itemCount) <= list->capacity && (dstIndex + itemCount) <= list->capacity);\n\n    if (itemCount) {\n        memmove(list->data + (dstIndex * list->itemSize),\n            list->data + (srcIndex * list->itemSize), list->itemSize * itemCount);\n    }\n}\n\nSB_PRIVATE SBBoolean ReserveItemRange(ListRef list, SBUInteger index, SBUInteger count)\n{\n    SBBoolean isReserved = SBFalse;\n\n    /* The index must be valid and there should be no integer overflow. */\n    SBAssert(index <= list->count && index <= (index + count));\n\n    if (EnsureItemCapacity(list, list->count + count)) {\n        MoveItemRange(list, index, index + count, list->count - index);\n        list->count += count;\n\n        isReserved = SBTrue;\n    }\n\n    return isReserved;\n}\n\nSB_PRIVATE SBBoolean InsertItemAtIndex(ListRef list, SBUInteger index, const void *itemPtr)\n{\n    SBBoolean isInserted = SBFalse;\n\n    /* Index MUST be valid. */\n    SBAssert(index <= list->count);\n\n    if (ReserveItemRange(list, index, 1)) {\n        void *destination = list->data + (index * list->itemSize);\n        memcpy(destination, itemPtr, list->itemSize);\n\n        isInserted = SBTrue;\n    }\n\n    return isInserted;\n}\n\nSB_PRIVATE void RemoveItemRange(ListRef list, SBUInteger index, SBUInteger count)\n{\n    SBUInteger nextIndex = index + count;\n\n    /* The specified item indexes must be valid and there should be no integer overflow. */\n    SBAssert(nextIndex <= list->count && index <= nextIndex);\n\n    MoveItemRange(list, nextIndex, index, list->count - nextIndex);\n    list->count -= count;\n}\n\nSB_PRIVATE void RemoveAllItems(ListRef list)\n{\n    list->count = 0;\n}\n\nSB_PRIVATE SBBoolean TrimExcessCapacity(ListRef list)\n{\n    return SetItemCapacity(list, list->count);\n}\n\nSB_PRIVATE SBUInteger SearchItemInRange(ListRef list, const void *itemPtr,\n    SBUInteger index, SBUInteger count)\n{\n    SBUInteger max = index + count;\n\n    /* The range must be valid and there should be no integer overflow. */\n    SBAssert((list->count > 0 ? max <= list->count : max == 0) && index <= max);\n\n    for (; index < max; index++) {\n        void *currentPtr = GetItemPointer(list, index);\n        if (memcmp(currentPtr, itemPtr, list->itemSize) == 0) {\n            return index;\n        }\n    }\n\n    return SBInvalidIndex;\n}\n\nSB_PRIVATE void SortItemRange(ListRef list, SBUInteger index, SBUInteger count,\n    SBComparison comparison)\n{\n    /* The range must be valid and there should be no integer overflow. */\n    SBAssert(SBUIntegerVerifyRange(list->count, index, count));\n\n    qsort(list->data, list->count, list->itemSize, comparison);\n}\n"
  },
  {
    "path": "unix/bidi/Source/Core/List.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_LIST_H\n#define _SB_INTERNAL_LIST_H\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n\ntypedef struct {\n    SBUInt8 *data;\n    SBUInteger count;\n    SBUInteger capacity;\n    SBUInteger itemSize;\n} List, *ListRef;\n\n#define LIST(type)          \\\nstruct {                    \\\n    type *items;            \\\n    SBUInteger count;       \\\n    SBUInteger capacity;    \\\n    SBUInteger _itemSize;   \\\n}\n\ntypedef int (*SBComparison)(const void *item1, const void *item2);\n\n#define SB_PRIVATE  SB_INTERNAL\n\nSB_PRIVATE void InitializeList(ListRef list, SBUInteger itemSize);\nSB_PRIVATE void FinalizeItemsBuffer(ListRef list);\nSB_PRIVATE void ExtractItemsBuffer(ListRef list, void **outArray, SBUInteger *outCount);\n\nSB_PRIVATE SBBoolean SetItemCapacity(ListRef list, SBUInteger capacity);\nSB_PRIVATE SBBoolean ReserveItemRange(ListRef list, SBUInteger index, SBUInteger count);\nSB_PRIVATE SBBoolean InsertItemAtIndex(ListRef list, SBUInteger index, const void *itemPtr);\n\nSB_PRIVATE void RemoveItemRange(ListRef list, SBUInteger index, SBUInteger count);\nSB_PRIVATE void RemoveAllItems(ListRef list);\nSB_PRIVATE SBBoolean TrimExcessCapacity(ListRef list);\n\nSB_PRIVATE SBUInteger SearchItemInRange(ListRef list, const void *itemPtr, SBUInteger index, SBUInteger count);\nSB_PRIVATE void SortItemRange(ListRef list, SBUInteger index, SBUInteger count, SBComparison comparison);\n\n#define CheckItemIndex(list_, index_)                   \\\n(                                                       \\\n    SBAssert(index_ < (list_)->count)                   \\\n)\n\n#define GetItemPointer(list_, index_)                   \\\n(                                                       \\\n    CheckItemIndex(list_, index_),                      \\\n    (void *)((list_)->data                              \\\n                + ((index_) * (list_)->itemSize))       \\\n)\n\n#define GetItemReference(list_, index_)                 \\\n(                                                       \\\n    CheckItemIndex(list_, index_),                      \\\n    &(list_)->items[index_]                             \\\n)\n\n#define GetItemValue(list_, index_)                     \\\n(                                                       \\\n    CheckItemIndex(list_, index_),                      \\\n    (list_)->items[index_]                              \\\n)\n\n#define SetItemValue(list_, index_, value_)             \\\ndo {                                                    \\\n    CheckItemIndex(list_, index_),                      \\\n    (list_)->items[index_] = value_;                    \\\n} while (0)\n\n#define InsertItemAtEnd(list_, item_)                   \\\n    InsertItemAtIndex(list_, (list_)->count, item_)\n\n\n#define ListInitialize(list, itemSize)              InitializeList((ListRef)(list), itemSize)\n#define ListFinalize(list)                          FinalizeItemsBuffer((ListRef)(list))\n#define ListFinalizeKeepingArray(list, outArray, outCount) \\\n    ExtractItemsBuffer((ListRef)(list), (void **)outArray, outCount)\n\n#define ListSetCapacity(list, capacity)             SetItemCapacity((ListRef)(list), capacity)\n#define ListReserveRange(list, index, count)        ReserveItemRange((ListRef)(list), index, count)\n#define ListRemoveRange(list, index, count)         RemoveItemRange((ListRef)(list), index, count)\n\n#define ListClear(list)                             RemoveAllItems((ListRef)(list))\n#define ListTrimExcess(list)                        TrimExcessCapacity((ListRef)(list))\n\n#define ListGetPtr(list, index)                     GetItemPointer((ListRef)(list), index)\n#define ListGetRef(list, index)                     GetItemReference(list, index)\n#define ListGetVal(list, index)                     GetItemValue(list, index)\n#define ListSetVal(list, index, item)               SetItemValue(list, index, item)\n\n#define ListAdd(list, item)                         InsertItemAtEnd((ListRef)(list), item)\n#define ListInsert(list, index, item)               InsertItemAtIndex((ListRef)(list), index, item)\n#define ListRemoveAt(list, index)                   RemoveItemRange((ListRef)(list), index, 1)\n#define ListRemoveAll(list)                         RemoveAllItems((ListRef)(list))\n\n#define ListIndexOfItem(list, item, index, count)   SearchItemInRange((ListRef)(list), item, index, count)\n#define ListContainsItem(list, item) \\\n    (SearchItemInRange((ListRef)(list), item, 0, (list)->count) != SBInvalidIndex)\n\n#define ListSort(list, index, count, comparison)    SortItemRange((ListRef)(list), index, count, comparison);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/Memory.c",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <API/SBAllocator.h>\n#include <API/SBAssert.h>\n\n#include \"Memory.h\"\n\n/**\n * Computes the total size required for a set of memory chunks.\n */\nstatic SBUInteger CalculateTotalSize(const SBUInteger *chunkSizes, SBUInteger chunkCount)\n{\n    SBUInteger totalSize = 0;\n    SBUInteger index;\n\n    for (index = 0; index < chunkCount; index++) {\n        totalSize += chunkSizes[index];\n    }\n\n    return totalSize;\n}\n\n/**\n * Splits a contiguous memory block into multiple logical chunks.\n */\nstatic void SplitMemoryBlock(void *pointer,\n    const SBUInteger *chunkSizes, SBUInteger chunkCount, void **outPointers)\n{\n    SBUInt8 *chunkPointer = pointer;\n    SBUInteger offset = 0;\n    SBUInteger index;\n\n    for (index = 0; index < chunkCount; index++) {\n        outPointers[index] = chunkPointer + offset;\n        offset += chunkSizes[index];\n    }\n}\n\nSB_INTERNAL void MemoryInitialize(MemoryRef memory)\n{\n    memory->_list = NULL;\n}\n\nSB_INTERNAL void *MemoryAllocateBlock(MemoryRef memory, MemoryType type, SBUInteger size)\n{\n    void *pointer = NULL;\n\n    /* Size MUST be greater than zero. */\n    SBAssert(size > 0);\n\n    if (type == MemoryTypeScratch) {\n        pointer = SBAllocatorAllocateScratch(NULL, size);\n    }\n\n    if (!pointer) {\n        MemoryListRef memoryList = memory->_list;\n\n        if (memoryList) {\n            const SBUInteger headerSize = sizeof(MemoryBlock);\n\n            pointer = SBAllocatorAllocateBlock(NULL, headerSize + size);\n\n            if (pointer) {\n                SBUInt8 *base = pointer;\n                MemoryBlockRef block;\n\n                block = pointer;\n                block->next = NULL;\n\n                memoryList->last->next = block;\n                memoryList->last = block;\n\n                pointer = base + headerSize;\n            }\n        } else {\n            const SBUInteger headerSize = sizeof(MemoryList);\n\n            pointer = SBAllocatorAllocateBlock(NULL, headerSize + size);\n\n            if (pointer) {\n                SBUInt8 *base = pointer;\n\n                memoryList = pointer;\n                memoryList->first.next = NULL;\n                memoryList->last = &memoryList->first;\n\n                memory->_list = memoryList;\n\n                pointer = base + headerSize;\n            }\n        }\n    }\n\n    return pointer;\n}\n\nSB_INTERNAL SBBoolean MemoryAllocateChunks(MemoryRef memory, MemoryType type,\n    const SBUInteger *chunkSizes, SBUInteger chunkCount, void **outPointers)\n{\n    SBUInteger totalSize = CalculateTotalSize(chunkSizes, chunkCount);\n    SBBoolean succeeded = SBFalse;\n    void *pointer;\n\n    /* Total size MUST be greater than zero. */\n    SBAssert(totalSize > 0);\n\n    pointer = MemoryAllocateBlock(memory, type, totalSize);\n\n    if (pointer) {\n        SplitMemoryBlock(pointer, chunkSizes, chunkCount, outPointers);\n        succeeded = SBTrue;\n    }\n\n    return succeeded;\n}\n\nSB_INTERNAL void MemoryFinalize(MemoryRef memory)\n{\n    MemoryListRef memoryList = memory->_list;\n\n    if (memoryList) {\n        MemoryBlockRef block = &memoryList->first;\n\n        while (block) {\n            MemoryBlockRef next = block->next;\n            /* Deallocate the block along with its data as they were allocated together. */\n            SBAllocatorDeallocateBlock(NULL, block);\n\n            block = next;\n        }\n    }\n}\n"
  },
  {
    "path": "unix/bidi/Source/Core/Memory.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_MEMORY_H\n#define _SB_INTERNAL_MEMORY_H\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n\n/**\n * Represents a single dynamically allocated memory block.\n * Each block stores a pointer to the next block, forming a singly linked list. The usable memory\n * begins immediately after the `MemoryBlock` structure.\n */\ntypedef struct _MemoryBlock {\n    struct _MemoryBlock *next;\n} MemoryBlock, *MemoryBlockRef;\n\n/**\n * Represents a linked list of memory blocks used for managing dynamic allocations.\n * The list always includes a sentinel `first` block, and a pointer to the last block to allow\n * efficient appending.\n */\ntypedef struct _MemoryList {\n    MemoryBlock first;\n    MemoryBlockRef last;\n} MemoryList, *MemoryListRef;\n\n/**\n * Base structure for managing internal memory allocations.\n * Intended to be embedded in other structs (e.g., Object).\n */\ntypedef struct Memory {\n    MemoryListRef _list;\n} Memory, *MemoryRef;\n\nenum {\n    MemoryTypePermanent = 0,\n    MemoryTypeScratch = 1\n};\ntypedef SBUInt8 MemoryType;\n\n#define MemoryMake() { NULL }\n\n/**\n * Initializes a Memory structure to prepare it for allocations.\n *\n * @param memory\n *      The Memory instance to initialize.\n */\nSB_INTERNAL void MemoryInitialize(MemoryRef memory);\n\n/**\n * Allocates a single contiguous memory block of the given size. The block is tracked internally\n * and released by `MemoryFinalize()`.\n *\n * @param memory\n *      The Memory to allocate from.\n * @param size\n *      Size of the memory block to allocate.\n * @return\n *      Pointer to the allocated memory block, or NULL on failure.\n */\nSB_INTERNAL void *MemoryAllocateBlock(MemoryRef memory, MemoryType type, SBUInteger size);\n\n/**\n * Allocates a single contiguous memory block and splits it into multiple chunks. The entire memory\n * block is tracked internally and released by `MemoryFinalize()`.\n *\n * @param memory\n *      The Memory to allocate from.\n * @param chunkSizes\n *      Array of chunk sizes.\n * @param chunkCount\n *      Number of chunks.\n * @param outPointers\n *      Output array to receive chunk pointers.\n * @return\n *      `SBTrue` if successful, `SBFalse` otherwise.\n */\nSB_INTERNAL SBBoolean MemoryAllocateChunks(MemoryRef memory, MemoryType type,\n    const SBUInteger *chunkSizes, SBUInteger chunkCount, void **outPointers);\n\n/**\n * Frees all memory blocks tracked by the given Memory.\n *\n * @param memory\n *      The Memory to finalize.\n */\nSB_INTERNAL void MemoryFinalize(MemoryRef memory);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/Object.c",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <API/SBAssert.h>\n#include <Core/AtomicUInt.h>\n#include <Core/Memory.h>\n\n#include \"Object.h\"\n\nSB_INTERNAL void ObjectBaseInitialize(ObjectBaseRef objectBase)\n{\n    MemoryInitialize(&objectBase->memory);\n    objectBase->finalize = NULL;\n    objectBase->retainCount = 0;\n}\n\nSB_INTERNAL ObjectRef ObjectCreate(const SBUInteger *chunkSizes, SBUInteger chunkCount,\n    void **outPointers, FinalizeFunc finalizer)\n{\n    ObjectBaseRef base = NULL;\n    Memory memory;\n\n    /* Number of chunks MUST be greater than or equal to one. */\n    SBAssert(chunkCount >= 1);\n    /* Size of first chunk MUST be greater than the size of ObjectBase structure. */\n    SBAssert(chunkSizes[0] > sizeof(ObjectBase));\n\n    MemoryInitialize(&memory);\n\n    if (MemoryAllocateChunks(&memory, MemoryTypePermanent, chunkSizes, chunkCount, outPointers)) {\n        base = outPointers[0];\n        base->memory = memory;\n        base->finalize = finalizer;\n\n        AtomicUIntInitialize(&base->retainCount, 1);\n    }\n\n    return base;\n}\n\nSB_INTERNAL SBUInteger ObjectGetRetainCount(ObjectRef object)\n{\n    ObjectBaseRef base = (ObjectBaseRef)object;\n\n    return AtomicUIntLoad(&base->retainCount);\n}\n\nSB_INTERNAL ObjectRef ObjectRetain(ObjectRef object)\n{\n    ObjectBaseRef base = (ObjectBaseRef)object;\n\n    AtomicUIntIncrement(&base->retainCount);\n\n    return object;\n}\n\nSB_INTERNAL void ObjectRelease(ObjectRef object)\n{\n    ObjectBaseRef base = (ObjectBaseRef)object;\n\n    if (AtomicUIntDecrement(&base->retainCount) == 0) {\n        if (base->finalize) {\n            base->finalize(object);\n        }\n\n        MemoryFinalize(&base->memory);\n    }\n}\n"
  },
  {
    "path": "unix/bidi/Source/Core/Object.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_OBJECT_H\n#define _SB_INTERNAL_OBJECT_H\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n#include <Core/AtomicUInt.h>\n#include <Core/Memory.h>\n\n/**\n * Represents a generic reference-counted object backed by a memory arena.\n */\ntypedef void *ObjectRef;\n\n/**\n * Function signature for finalizing a reference-counted object.\n * This is called once the reference count reaches zero.\n *\n * @param object\n *      The object being finalized.\n */\ntypedef void (*FinalizeFunc)(ObjectRef object);\n\n/**\n * Internal structure representing the base of an object.\n */\ntypedef struct ObjectBase {\n    Memory memory;\n    FinalizeFunc finalize;\n    AtomicUInt retainCount;\n} ObjectBase, *ObjectBaseRef;\n\n#ifndef SB_CONFIG_ALLOW_NON_ATOMIC_FALLBACK\n\n#if !defined(HAS_ATOMIC_UINT_SUPPORT)\n#error \"No atomic operations available. For thread-unsafe reference counting, manually define \\\n`SB_CONFIG_ALLOW_NON_ATOMIC_FALLBACK`.\"\n#endif\n\n#endif\n\n#define ObjectBaseMake() { MemoryMake(), NULL, 0 }\n\nSB_INTERNAL void ObjectBaseInitialize(ObjectBaseRef objectBase);\n\n/**\n * Creates a reference-counted object and allocates memory chunks for it.\n *\n * This function allocates a single contiguous memory block and divides it into chunks according to\n * the provided `chunkSizes`. The addresses of these chunks are returned in the `outPointers` array.\n *\n * The first chunk (i.e., `outPointers[0]`) MUST correspond to a user-defined struct that has\n * `ObjectBase` as its **first field**. This is critical because all Object-related functionalities\n * such as reference counting, memory management, and finalization rely on being able to treat the\n * object as an `ObjectBaseRef`.\n *\n * Example:\n * ```\n * typedef struct MyObject {\n *     ObjectBase base; // MUST be first\n *     int field1;\n *     float field2;\n * } MyObject;\n *\n * SBUInteger sizes[] = { sizeof(MyObject), otherSize1, otherSize2 };\n * void *pointers[3];\n * MyObject *obj = ObjectCreate(sizes, 3, pointers, FinalizeMyObject);\n * ```\n *\n * @param chunkSizes\n *      An array of sizes (in bytes) for each memory chunk.\n * @param chunkCount\n *      Number of chunks (must be >= 1).\n * @param outPointers\n *      Output array to receive the addresses of the allocated chunks.\n * @param finalizer\n *      Optional function to finalize the object when its reference count drops to zero.\n * @return\n *      A reference to the created object (same as `outPointers[0]`), or NULL if allocation failed.\n */\nSB_INTERNAL ObjectRef ObjectCreate(const SBUInteger *chunkSizes, SBUInteger chunkCount,\n    void **outPointers, FinalizeFunc finalizer);\n\n/**\n * Retrieves the current reference count of an object.\n * \n * @param object\n *      The object whose reference count is queried.\n * @return\n *      The current reference count.\n */\nSB_INTERNAL SBUInteger ObjectGetRetainCount(ObjectRef object);\n\n/**\n * Retains the object by incrementing its reference count.\n *\n * @param object\n *      The object to retain.\n * @return\n *      The same object.\n */\nSB_INTERNAL ObjectRef ObjectRetain(ObjectRef object);\n\n/**\n * Releases the object by decrementing its reference count. When the count reaches zero, the\n * finalizer (if any) is called, and all associated memory is freed.\n *\n * @param object\n *      The object to release.\n */\nSB_INTERNAL void ObjectRelease(ObjectRef object);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/Once.c",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n#include <Core/ThreadFence.h>\n\n#include \"Once.h\"\n\nSB_INTERNAL SBBoolean OnceTryExecute(OnceRef once, void(*func)(void *info), void *info)\n{\n    SBBoolean result = SBTrue;\n\n    if (!once->executed) {\n        result = AtomicFlagTestAndSet(&once->flag) == SBFalse;\n\n        if (result) {\n            func(info);\n            ThreadFence();\n            once->executed = SBTrue;\n        }\n    }\n\n    return result;\n}\n"
  },
  {
    "path": "unix/bidi/Source/Core/Once.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ONCE_H\n#define _SB_INTERNAL_ONCE_H\n\n#include <API/SBBase.h>\n#include <Core/AtomicFlag.h>\n#include <Core/ThreadFence.h>\n\n#if defined(HAS_ATOMIC_FLAG_SUPPORT) && defined(HAS_THREAD_FENCE_SUPPORT)\n#define HAS_ONCE_SUPPORT\n#endif\n\ntypedef struct _Once {\n    SBBoolean executed;\n    AtomicFlag flag;\n} Once, *OnceRef;\n\n#define OnceMake() { SBFalse, AtomicFlagMake() }\n\nSB_INTERNAL SBBoolean OnceTryExecute(OnceRef once, void(*func)(void *info), void *info);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/ThreadFence.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_THREAD_FENCE_H\n#define _SB_INTERNAL_THREAD_FENCE_H\n\n#include <API/SBBase.h>\n\n#if defined(USE_C11_ATOMICS)\n\n#include <stdatomic.h>\n#define HAS_THREAD_FENCE_SUPPORT\n#define ThreadFence()               atomic_thread_fence(memory_order_seq_cst)\n\n#elif defined(USE_ATOMIC_BUILTINS)\n\n#define HAS_THREAD_FENCE_SUPPORT\n#define ThreadFence()               __atomic_thread_fence(__ATOMIC_SEQ_CST)\n\n#elif defined(USE_SYNC_BUILTINS)\n\n#define HAS_THREAD_FENCE_SUPPORT\n#define ThreadFence()               __sync_synchronize()\n\n#elif MSVC_VERSION >= 1400\n\n#include <windows.h>\n#define HAS_THREAD_FENCE_SUPPORT\n#define ThreadFence()               MemoryBarrier()\n\n#else /* Unsafe fallback — no barrier */\n\n#define ThreadFence()\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Core/ThreadLocalStorage.h",
    "content": "/*\n * Copyright (C) 2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_THREAD_LOCAL_STORAGE_H\n#define _SB_INTERNAL_THREAD_LOCAL_STORAGE_H\n\n#include <stddef.h>\n\n#include <API/SBBase.h>\n\n/* Detect C11 support */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)\n#define USE_C11_THREAD_LOCAL\n\n/* Detect GCC thread-local support (available since GCC 3.3) */\n#elif GCC_VERSION >= 303\n#define USE_GNUC_THREAD_LOCAL\n\n/* Detect Clang thread-local support (available since Clang 1.0) */\n#elif CLANG_VERSION >= 100\n#define USE_CLANG_THREAD_LOCAL\n\n/* Detect MSVC thread-local support (available since MSVC 2005) */\n#elif MSVC_VERSION >= 1400\n#define USE_MSVC_THREAD_LOCAL\n\n/* Check for pthread availability */\n#elif defined(_POSIX_THREADS) || defined(__unix__) || defined(__unix) || defined(unix) \\\n        || (defined(__APPLE__) && defined(__MACH__)) || defined(__linux__)\n#define USE_PTHREAD_KEY\n\n/* Check for Windows availability */\n#elif defined(_WIN32)\n#define USE_WIN_TLS\n\n#endif\n\n/* Define data type for thread local storage. */\n#ifdef USE_C11_THREAD_LOCAL\n\n#define HAS_TLS_SUPPORT\n#define ThreadLocalStorage _Thread_local void *\n\n#elif defined(USE_GNUC_THREAD_LOCAL) || defined(USE_CLANG_THREAD_LOCAL)\n\n#define HAS_TLS_SUPPORT\n#define ThreadLocalStorage __thread void *\n\n#elif defined(USE_MSVC_THREAD_LOCAL)\n\n#define HAS_TLS_SUPPORT\n#define ThreadLocalStorage __declspec(thread) void *\n\n#elif defined(USE_PTHREAD_KEY)\n\n#include <pthread.h>\n#define HAS_TLS_SUPPORT\ntypedef pthread_key_t ThreadLocalStorage;\n\n#elif defined(USE_WIN_TLS)\n\n#include <windows.h>\n#define HAS_TLS_SUPPORT\ntypedef DWORD ThreadLocalStorage;\n\n#else\n\ntypedef void *ThreadLocalStorage;\n\n#endif\n\n/* Define functions for thread local storage. */\n#ifdef USE_PTHREAD_KEY\n\n#define ThreadLocalStorageInitialize(tls)   pthread_key_create(&(tls), NULL)\n#define ThreadLocalStorageGet(tls)          pthread_getspecific(tls)\n#define ThreadLocalStorageSet(tls, value)   pthread_setspecific(tls, value)\n#define ThreadLocalStorageFinalize(tls)     pthread_key_delete(tls)\n\n#elif defined(USE_WIN_TLS)\n\n#define ThreadLocalStorageInitialize(tls)   ((tls) = TlsAlloc())\n#define ThreadLocalStorageGet(tls)          TlsGetValue(tls)\n#define ThreadLocalStorageSet(tls, value)   TlsSetValue(tls, value)\n#define ThreadLocalStorageFinalize(tls)     TlsFree(tls)\n\n#else\n\n#define ThreadLocalStorageInitialize(tls)   ((tls) = NULL)\n#define ThreadLocalStorageGet(tls)          (tls)\n#define ThreadLocalStorageSet(tls, value)   ((tls) = (value))\n#define ThreadLocalStorageFinalize(tls)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Data/BidiTypeLookup.c",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n *\n * REQUIRED MEMORY: 4816+(2880*2)+(1088*2) = 12752 Bytes\n */\n\n#include \"BidiTypeLookup.h\"\n\n#define AL      SBBidiTypeAL \n#define AN      SBBidiTypeAN \n#define B       SBBidiTypeB  \n#define BN      SBBidiTypeBN \n#define CS      SBBidiTypeCS \n#define EN      SBBidiTypeEN \n#define ES      SBBidiTypeES \n#define ET      SBBidiTypeET \n#define FSI     SBBidiTypeFSI\n#define L       SBBidiTypeL  \n#define LRE     SBBidiTypeLRE\n#define LRI     SBBidiTypeLRI\n#define LRO     SBBidiTypeLRO\n#define NSM     SBBidiTypeNSM\n#define ON      SBBidiTypeON \n#define PDF     SBBidiTypePDF\n#define PDI     SBBidiTypePDI\n#define R       SBBidiTypeR  \n#define RLE     SBBidiTypeRLE\n#define RLI     SBBidiTypeRLI\n#define RLO     SBBidiTypeRLO\n#define S       SBBidiTypeS  \n#define WS      SBBidiTypeWS \n\nstatic const SBUInt8 PrimaryBidiTypeData[4816] = {\n/* DATA_BLOCK: -- 0x0000..0x000F -- */\n    BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  S,   B,   S,   WS,  B,   BN,  BN,\n/* DATA_BLOCK: -- 0x0010..0x001F -- */\n    BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  B,   B,   B,   S,\n/* DATA_BLOCK: -- 0x0020..0x002F -- */\n    WS,  ON,  ON,  ET,  ET,  ET,  ON,  ON,  ON,  ON,  ON,  ES,  CS,  ES,  CS,  CS,\n/* DATA_BLOCK: -- 0x0030..0x003F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  CS,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0040..0x004F -- */\n    ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0050..0x005F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0060..0x006F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  BN,\n/* DATA_BLOCK: -- 0x0070..0x007F -- */\n    BN,  BN,  BN,  BN,  BN,  B,   BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,\n/* DATA_BLOCK: -- 0x0080..0x008F -- */\n    BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,\n/* DATA_BLOCK: -- 0x0090..0x009F -- */\n    CS,  ON,  ET,  ET,  ET,  ET,  ON,  ON,  ON,  ON,  L,   ON,  ON,  BN,  ON,  ON,\n/* DATA_BLOCK: -- 0x00A0..0x00AF -- */\n    ET,  ET,  EN,  EN,  ON,  L,   ON,  ON,  ON,  EN,  L,   ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x00B0..0x00BF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x00C0..0x00CF -- */\n    L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x00D0..0x00DF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x00E0..0x00EF -- */\n    L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x00F0..0x00FF -- */\n    L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   ON,\n/* DATA_BLOCK: -- 0x0100..0x010F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0110..0x011F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0120..0x012F -- */\n    L,   L,   L,   L,   ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,\n/* DATA_BLOCK: -- 0x0130..0x013F -- */\n    L,   L,   L,   L,   ON,  ON,  L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0140..0x014F -- */\n    L,   L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0150..0x015F -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0160..0x016F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,   ON,  ON,  ET,\n/* DATA_BLOCK: -- 0x0170..0x017F -- */\n    R,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0180..0x018F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, R,   NSM,\n/* DATA_BLOCK: -- 0x0190..0x019F -- */\n    R,   NSM, NSM, R,   NSM, NSM, R,   NSM, R,   R,   R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x01A0..0x01AF -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x01B0..0x01BF -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  ON,  ON,  AL,  ET,  ET,  AL,  CS,  AL,  ON,  ON,\n/* DATA_BLOCK: -- 0x01C0..0x01CF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x01D0..0x01DF -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x01E0..0x01EF -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x01F0..0x01FF -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  ET,  AN,  AN,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0200..0x020F -- */\n    NSM, AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0210..0x021F -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, NSM, NSM, NSM, AN,  ON,  NSM,\n/* DATA_BLOCK: -- 0x0220..0x022F -- */\n    NSM, NSM, NSM, NSM, NSM, AL,  AL,  NSM, NSM, ON,  NSM, NSM, NSM, NSM, AL,  AL,\n/* DATA_BLOCK: -- 0x0230..0x023F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0240..0x024F -- */\n    AL,  NSM, AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0250..0x025F -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0260..0x026F -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0270..0x027F -- */\n    NSM, NSM, NSM, NSM, R,   R,   ON,  ON,  ON,  ON,  R,   R,   R,   NSM, R,   R,\n/* DATA_BLOCK: -- 0x0280..0x028F -- */\n    R,   R,   R,   R,   R,   R,   NSM, NSM, NSM, NSM, R,   NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0290..0x029F -- */\n    NSM, NSM, NSM, NSM, R,   NSM, NSM, NSM, R,   NSM, NSM, NSM, NSM, NSM, R,   R,\n/* DATA_BLOCK: -- 0x02A0..0x02AF -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   NSM, NSM, NSM, R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x02B0..0x02BF -- */\n    AN,  AN,  AL,  AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x02C0..0x02CF -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x02D0..0x02DF -- */\n    NSM, NSM, AN,  NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x02E0..0x02EF -- */\n    NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x02F0..0x02FF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0300..0x030F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0310..0x031F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0320..0x032F -- */\n    L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0330..0x033F -- */\n    L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0340..0x034F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0350..0x035F -- */\n    L,   NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0360..0x036F -- */\n    L,   L,   ET,  ET,  L,   L,   L,   L,   L,   L,   L,   ET,  L,   L,   NSM, L,\n/* DATA_BLOCK: -- 0x0370..0x037F -- */\n    L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0380..0x038F -- */\n    L,   NSM, NSM, L,   L,   L,   L,   NSM, NSM, L,   L,   NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0390..0x039F -- */\n    NSM, NSM, L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x03A0..0x03AF -- */\n    L,   NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x03B0..0x03BF -- */\n    L,   ET,  L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x03C0..0x03CF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   NSM,\n/* DATA_BLOCK: -- 0x03D0..0x03DF -- */\n    L,   L,   L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x03E0..0x03EF -- */\n    L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x03F0..0x03FF -- */\n    NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0400..0x040F -- */\n    L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ET,  ON,  L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0410..0x041F -- */\n    NSM, L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0420..0x042F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   NSM, NSM,\n/* DATA_BLOCK: -- 0x0430..0x043F -- */\n    NSM, L,   L,   L,   L,   L,   NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0440..0x044F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x0450..0x045F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0460..0x046F -- */\n    NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0470..0x047F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0480..0x048F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0490..0x049F -- */\n    L,   L,   NSM, NSM, NSM, L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x04A0..0x04AF -- */\n    L,   NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   ET,\n/* DATA_BLOCK: -- 0x04B0..0x04BF -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x04C0..0x04CF -- */\n    L,   NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x04D0..0x04DF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x04E0..0x04EF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x04F0..0x04FF -- */\n    L,   L,   L,   L,   L,   NSM, L,   NSM, L,   NSM, ON,  ON,  ON,  ON,  L,   L,\n/* DATA_BLOCK: -- 0x0500..0x050F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x0510..0x051F -- */\n    NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, L,   L,   L,   L,   L,   NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0520..0x052F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0530..0x053F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0540..0x054F -- */\n    L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0550..0x055F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0560..0x056F -- */\n    NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, L,   L,   NSM, NSM, L,\n/* DATA_BLOCK: -- 0x0570..0x057F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   L,   L,   L,   NSM, NSM,\n/* DATA_BLOCK: -- 0x0580..0x058F -- */\n    NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0590..0x059F -- */\n    L,   NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x05A0..0x05AF -- */\n    L,   L,   NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x05B0..0x05BF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x05C0..0x05CF -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x05D0..0x05DF -- */\n    WS,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x05E0..0x05EF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  L,   L,   L,\n/* DATA_BLOCK: -- 0x05F0..0x05FF -- */\n    L,   L,   NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0600..0x060F -- */\n    L,   L,   L,   L,   NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0610..0x061F -- */\n    L,   L,   L,   L,   L,   L,   NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0620..0x062F -- */\n    NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   ET,  L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0630..0x063F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  NSM, NSM, NSM, BN,  NSM,\n/* DATA_BLOCK: -- 0x0640..0x064F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0650..0x065F -- */\n    NSM, NSM, NSM, L,   L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0660..0x066F -- */\n    L,   L,   NSM, L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0670..0x067F -- */\n    ON,  L,   L,   L,   ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0680..0x068F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,\n/* DATA_BLOCK: -- 0x0690..0x069F -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   L,   NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x06A0..0x06AF -- */\n    L,   L,   L,   L,   L,   L,   NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x06B0..0x06BF -- */\n    NSM, L,   NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x06C0..0x06CF -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM,\n/* DATA_BLOCK: -- 0x06D0..0x06DF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x06E0..0x06EF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x06F0..0x06FF -- */\n    NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0700..0x070F -- */\n    L,   L,   L,   L,   NSM, L,   NSM, NSM, NSM, NSM, NSM, L,   NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0710..0x071F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0720..0x072F -- */\n    L,   L,   NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0730..0x073F -- */\n    L,   L,   L,   L,   L,   L,   NSM, L,   NSM, NSM, L,   L,   L,   NSM, L,   NSM,\n/* DATA_BLOCK: -- 0x0740..0x074F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0750..0x075F -- */\n    NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0760..0x076F -- */\n    NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0770..0x077F -- */\n    NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0780..0x078F -- */\n    L,   L,   L,   L,   NSM, L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0790..0x079F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   ON,\n/* DATA_BLOCK: -- 0x07A0..0x07AF -- */\n    ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x07B0..0x07BF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x07C0..0x07CF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  L,\n/* DATA_BLOCK: -- 0x07D0..0x07DF -- */\n    WS,  WS,  WS,  WS,  WS,  WS,  WS,  WS,  WS,  WS,  WS,  BN,  BN,  BN,  L,   R,\n/* DATA_BLOCK: -- 0x07E0..0x07EF -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  WS,  B,   LRE, RLE, PDF, LRO, RLO, CS,\n/* DATA_BLOCK: -- 0x07F0..0x07FF -- */\n    ET,  ET,  ET,  ET,  ET,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0800..0x080F -- */\n    ON,  ON,  ON,  ON,  CS,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0810..0x081F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  WS,\n/* DATA_BLOCK: -- 0x0820..0x082F -- */\n    BN,  BN,  BN,  BN,  BN,  BN,  LRI, RLI, FSI, PDI, BN,  BN,  BN,  BN,  BN,  BN,\n/* DATA_BLOCK: -- 0x0830..0x083F -- */\n    EN,  L,   L,   L,   EN,  EN,  EN,  EN,  EN,  EN,  ES,  ES,  ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x0840..0x084F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  ES,  ES,  ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x0850..0x085F -- */\n    ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,  ET,\n/* DATA_BLOCK: -- 0x0860..0x086F -- */\n    ON,  ON,  L,   ON,  ON,  ON,  ON,  L,   ON,  ON,  L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0870..0x087F -- */\n    L,   L,   L,   L,   ON,  L,   ON,  ON,  ON,  L,   L,   L,   L,   L,   ON,  ON,\n/* DATA_BLOCK: -- 0x0880..0x088F -- */\n    ON,  ON,  ON,  ON,  L,   ON,  L,   ON,  L,   ON,  L,   L,   L,   L,   ET,  L,\n/* DATA_BLOCK: -- 0x0890..0x089F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x08A0..0x08AF -- */\n    ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  L,   L,\n/* DATA_BLOCK: -- 0x08B0..0x08BF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x08C0..0x08CF -- */\n    ON,  ON,  ES,  ET,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x08D0..0x08DF -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x08E0..0x08EF -- */\n    ON,  ON,  ON,  ON,  ON,  L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x08F0..0x08FF -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0900..0x090F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,\n/* DATA_BLOCK: -- 0x0910..0x091F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0920..0x092F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0930..0x093F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0940..0x094F -- */\n    ON,  ON,  ON,  ON,  L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0950..0x095F -- */\n    L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0960..0x096F -- */\n    NSM, NSM, L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0970..0x097F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0980..0x098F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,\n/* DATA_BLOCK: -- 0x0990..0x099F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x09A0..0x09AF -- */\n    ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x09B0..0x09BF -- */\n    WS,  ON,  ON,  ON,  ON,  L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x09C0..0x09CF -- */\n    ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x09D0..0x09DF -- */\n    ON,  L,   L,   L,   L,   L,   ON,  ON,  L,   L,   L,   L,   L,   ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x09E0..0x09EF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, ON,  ON,  L,   L,   L,\n/* DATA_BLOCK: -- 0x09F0..0x09FF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0A00..0x0A0F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,\n/* DATA_BLOCK: -- 0x0A10..0x0A1F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x0A20..0x0A2F -- */\n    L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0A30..0x0A3F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0A40..0x0A4F -- */\n    L,   L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0A50..0x0A5F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,\n/* DATA_BLOCK: -- 0x0A60..0x0A6F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0A70..0x0A7F -- */\n    NSM, NSM, NSM, ON,  NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, ON,  ON,\n/* DATA_BLOCK: -- 0x0A80..0x0A8F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM,\n/* DATA_BLOCK: -- 0x0A90..0x0A9F -- */\n    ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0AA0..0x0AAF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0AB0..0x0ABF -- */\n    L,   L,   NSM, L,   L,   L,   NSM, L,   L,   L,   L,   NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0AC0..0x0ACF -- */\n    L,   L,   L,   L,   L,   NSM, NSM, L,   ON,  ON,  ON,  ON,  NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0AD0..0x0ADF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   ET,  ET,  L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0AE0..0x0AEF -- */\n    L,   L,   L,   L,   ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0AF0..0x0AFF -- */\n    L,   L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0B00..0x0B0F -- */\n    NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0B10..0x0B1F -- */\n    L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0B20..0x0B2F -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0B30..0x0B3F -- */\n    L,   L,   L,   NSM, L,   L,   NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0B40..0x0B4F -- */\n    L,   L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0B50..0x0B5F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x0B60..0x0B6F -- */\n    L,   NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0B70..0x0B7F -- */\n    L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0B80..0x0B8F -- */\n    NSM, L,   NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,   NSM, NSM,\n/* DATA_BLOCK: -- 0x0B90..0x0B9F -- */\n    L,   L,   L,   L,   L,   NSM, L,   L,   NSM, L,   L,   L,   L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0BA0..0x0BAF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   R,   NSM, R,\n/* DATA_BLOCK: -- 0x0BB0..0x0BBF -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   ES,  R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x0BC0..0x0BCF -- */\n    AL,  AL,  AL,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0BD0..0x0BDF -- */\n    ON,  ON,  ON,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0BE0..0x0BEF -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  ON,  ON,\n/* DATA_BLOCK: -- 0x0BF0..0x0BFF -- */\n    ON,  ON,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0C00..0x0C0F -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0C10..0x0C1F -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0C20..0x0C2F -- */\n    CS,  ON,  CS,  L,   ON,  CS,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ET,\n/* DATA_BLOCK: -- 0x0C30..0x0C3F -- */\n    ON,  ON,  ES,  ES,  ON,  ON,  ON,  L,   ON,  ET,  ET,  ON,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0C40..0x0C4F -- */\n    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  BN,\n/* DATA_BLOCK: -- 0x0C50..0x0C5F -- */\n    L,   ON,  ON,  ET,  ET,  ET,  ON,  ON,  ON,  ON,  ON,  ES,  CS,  ES,  CS,  CS,\n/* DATA_BLOCK: -- 0x0C60..0x0C6F -- */\n    ET,  ET,  ON,  ON,  ON,  ET,  ET,  L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x0C70..0x0C7F -- */\n    BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  ON,  ON,  ON,  ON,  ON,  BN,  BN,\n/* DATA_BLOCK: -- 0x0C80..0x0C8F -- */\n    L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0C90..0x0C9F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,\n/* DATA_BLOCK: -- 0x0CA0..0x0CAF -- */\n    NSM, EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,\n/* DATA_BLOCK: -- 0x0CB0..0x0CBF -- */\n    L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0CC0..0x0CCF -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   ON,\n/* DATA_BLOCK: -- 0x0CD0..0x0CDF -- */\n    R,   NSM, NSM, NSM, R,   NSM, NSM, R,   R,   R,   R,   R,   NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0CE0..0x0CEF -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   NSM, NSM, NSM, R,   R,   R,   R,   NSM,\n/* DATA_BLOCK: -- 0x0CF0..0x0CFF -- */\n    R,   R,   R,   R,   R,   NSM, NSM, R,   R,   R,   R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x0D00..0x0D0F -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x0D10..0x0D1F -- */\n    AL,  AL,  AL,  AL,  NSM, NSM, NSM, NSM, AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0D20..0x0D2F -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0D30..0x0D3F -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x0D40..0x0D4F -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   NSM, NSM, NSM, NSM, NSM, ON,  R,\n/* DATA_BLOCK: -- 0x0D50..0x0D5F -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,\n/* DATA_BLOCK: -- 0x0D60..0x0D6F -- */\n    AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  AN,  R,\n/* DATA_BLOCK: -- 0x0D70..0x0D7F -- */\n    R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   R,   NSM, NSM, R,   R,   R,\n/* DATA_BLOCK: -- 0x0D80..0x0D8F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  AL,  AL,  AL,  AL,  AL,  AL,  AL,\n/* DATA_BLOCK: -- 0x0D90..0x0D9F -- */\n    R,   R,   NSM, NSM, NSM, NSM, R,   R,   R,   R,   R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x0DA0..0x0DAF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0DB0..0x0DBF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0DC0..0x0DCF -- */\n    NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0DD0..0x0DDF -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0DE0..0x0DEF -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0DF0..0x0DFF -- */\n    NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0E00..0x0E0F -- */\n    L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0E10..0x0E1F -- */\n    L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x0E20..0x0E2F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0E30..0x0E3F -- */\n    NSM, NSM, L,   L,   NSM, L,   NSM, NSM, L,   L,   L,   L,   L,   L,   NSM, L,\n/* DATA_BLOCK: -- 0x0E40..0x0E4F -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0E50..0x0E5F -- */\n    L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,\n/* DATA_BLOCK: -- 0x0E60..0x0E6F -- */\n    NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,\n/* DATA_BLOCK: -- 0x0E70..0x0E7F -- */\n    NSM, L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0E80..0x0E8F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,\n/* DATA_BLOCK: -- 0x0E90..0x0E9F -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, L,   L,   L,   L,   NSM,\n/* DATA_BLOCK: -- 0x0EA0..0x0EAF -- */\n    NSM, L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0EB0..0x0EBF -- */\n    L,   L,   NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   NSM, NSM, L,   NSM,\n/* DATA_BLOCK: -- 0x0EC0..0x0ECF -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, L,   NSM,\n/* DATA_BLOCK: -- 0x0ED0..0x0EDF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   NSM, L,   L,\n/* DATA_BLOCK: -- 0x0EE0..0x0EEF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0EF0..0x0EFF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, L,   NSM,\n/* DATA_BLOCK: -- 0x0F00..0x0F0F -- */\n    L,   L,   NSM, NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F10..0x0F1F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F20..0x0F2F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,   NSM, L,\n/* DATA_BLOCK: -- 0x0F30..0x0F3F -- */\n    L,   L,   L,   L,   NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F40..0x0F4F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F50..0x0F5F -- */\n    L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, NSM, NSM, L,\n/* DATA_BLOCK: -- 0x0F60..0x0F6F -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F70..0x0F7F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0F80..0x0F8F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0F90..0x0F9F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0FA0..0x0FAF -- */\n    NSM, L,   NSM, NSM, NSM, L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0FB0..0x0FBF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x0FC0..0x0FCF -- */\n    L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0FD0..0x0FDF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x0FE0..0x0FEF -- */\n    NSM, L,   NSM, NSM, L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x0FF0..0x0FFF -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   NSM, L,   NSM, NSM, L,   NSM,\n/* DATA_BLOCK: -- 0x1000..0x100F -- */\n    NSM, NSM, L,   L,   L,   NSM, L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1010..0x101F -- */\n    L,   L,   L,   NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1020..0x102F -- */\n    L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ET,  ET,  ET,\n/* DATA_BLOCK: -- 0x1030..0x103F -- */\n    ET,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x1040..0x104F -- */\n    NSM, L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x1050..0x105F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1060..0x106F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x1070..0x107F -- */\n    L,   L,   ON,  L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1080..0x108F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, L,\n/* DATA_BLOCK: -- 0x1090..0x109F -- */\n    BN,  BN,  BN,  BN,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x10A0..0x10AF -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  ON,  ON,  ON,  L,   L,   L,\n/* DATA_BLOCK: -- 0x10B0..0x10BF -- */\n    ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x10C0..0x10CF -- */\n    L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x10D0..0x10DF -- */\n    L,   L,   L,   BN,  BN,  BN,  BN,  BN,  BN,  BN,  BN,  NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x10E0..0x10EF -- */\n    NSM, NSM, NSM, L,   L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x10F0..0x10FF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   NSM, NSM, NSM, NSM, L,   L,\n/* DATA_BLOCK: -- 0x1100..0x110F -- */\n    ON,  ON,  NSM, NSM, NSM, ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1110..0x111F -- */\n    L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1120..0x112F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1130..0x113F -- */\n    L,   L,   L,   ON,  L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   EN,  EN,\n/* DATA_BLOCK: -- 0x1140..0x114F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,\n/* DATA_BLOCK: -- 0x1150..0x115F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x1160..0x116F -- */\n    L,   L,   L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1170..0x117F -- */\n    L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x1180..0x118F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x1190..0x119F -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, NSM, L,   L,   NSM, NSM, NSM, NSM, NSM,\n/* DATA_BLOCK: -- 0x11A0..0x11AF -- */\n    NSM, NSM, L,   NSM, NSM, L,   NSM, NSM, NSM, NSM, NSM, L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x11B0..0x11BF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ET,\n/* DATA_BLOCK: -- 0x11C0..0x11CF -- */\n    L,   L,   L,   NSM, L,   L,   NSM, L,   L,   L,   L,   L,   L,   L,   NSM, NSM,\n/* DATA_BLOCK: -- 0x11D0..0x11DF -- */\n    NSM, NSM, NSM, NSM, NSM, NSM, NSM, R,   R,   R,   R,   R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x11E0..0x11EF -- */\n    R,   R,   R,   R,   NSM, NSM, NSM, NSM, NSM, NSM, NSM, R,   R,   R,   R,   R,\n/* DATA_BLOCK: -- 0x11F0..0x11FF -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1200..0x120F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,\n/* DATA_BLOCK: -- 0x1210..0x121F -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x1220..0x122F -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   ON,  L,   L,\n/* DATA_BLOCK: -- 0x1230..0x123F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x1240..0x124F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1250..0x125F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x1260..0x126F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   ON,  ON,\n/* DATA_BLOCK: -- 0x1270..0x127F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   ON,  L,   L,   L,   L,   ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x1280..0x128F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   ON,\n/* DATA_BLOCK: -- 0x1290..0x129F -- */\n    ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  L,   L,   L,   L,   ON,\n/* DATA_BLOCK: -- 0x12A0..0x12AF -- */\n    ON,  ON,  ON,  L,   ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,  ON,\n/* DATA_BLOCK: -- 0x12B0..0x12BF -- */\n    EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  EN,  ON,  L,   L,   L,   L,   L,\n/* DATA_BLOCK: -- 0x12C0..0x12CF -- */\n    L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   L,   BN,  BN\n};\n\nstatic const SBUInt16 MainBidiTypeIndexes[2880] = {\n/* INDEX_BLOCK: -- 0x0000..0x003F -- */\n    0x0000, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0040, 0x0060, 0x0070, 0x0080, 0x0090, 0x00A0,\n    0x00B0, 0x00C0, 0x00B0, 0x00C0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00D0, 0x00E0, 0x00E0, 0x00F0, 0x0100,\n    0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0120, 0x0130, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x0140,\n/* INDEX_BLOCK: -- 0x0040..0x007F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0150, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x0160, 0x0170, 0x0110, 0x0180, 0x0190, 0x01A0, 0x01A0, 0x01A0, 0x01B0, 0x01C0, 0x01D0, 0x01D0,\n    0x01E0, 0x0110, 0x01F0, 0x0200, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x0210, 0x0220, 0x0230,\n    0x01D0, 0x0240, 0x01D0, 0x0110, 0x01C0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x0250, 0x0200,\n    0x01A0, 0x01A0, 0x0260, 0x0270,\n/* INDEX_BLOCK: -- 0x0080..0x00BF -- */\n    0x01A0, 0x0280, 0x0290, 0x01A0, 0x01A0, 0x02A0, 0x01D0, 0x01D0, 0x01D0, 0x02B0, 0x01D0, 0x01D0,\n    0x02C0, 0x0110, 0x02D0, 0x0110, 0x02E0, 0x00B0, 0x00B0, 0x02F0, 0x0300, 0x0310, 0x0320, 0x00B0,\n    0x0330, 0x00B0, 0x00B0, 0x0340, 0x0350, 0x00B0, 0x0320, 0x0360, 0x0370, 0x00B0, 0x00B0, 0x0340,\n    0x0380, 0x0330, 0x00B0, 0x0390, 0x0370, 0x00B0, 0x00B0, 0x0340, 0x03A0, 0x00B0, 0x0320, 0x03B0,\n    0x0330, 0x00B0, 0x00B0, 0x03C0, 0x0350, 0x03D0, 0x0320, 0x00B0, 0x03E0, 0x00B0, 0x00B0, 0x00B0,\n    0x03F0, 0x00B0, 0x00B0, 0x0400,\n/* INDEX_BLOCK: -- 0x00C0..0x00FF -- */\n    0x0410, 0x00B0, 0x00B0, 0x0420, 0x0430, 0x03D0, 0x0320, 0x0440, 0x0330, 0x00B0, 0x00B0, 0x0340,\n    0x0450, 0x00B0, 0x0320, 0x00B0, 0x0460, 0x00B0, 0x00B0, 0x0470, 0x0350, 0x00B0, 0x0320, 0x00B0,\n    0x0330, 0x00B0, 0x00B0, 0x00B0, 0x0480, 0x0490, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x04A0,\n    0x04B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x04C0, 0x04D0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x04E0, 0x00B0, 0x04F0, 0x00B0, 0x00B0, 0x00B0, 0x0500, 0x0510, 0x0520, 0x0110, 0x0530,\n    0x0540, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0100..0x013F -- */\n    0x00B0, 0x00B0, 0x0550, 0x0560, 0x00B0, 0x0570, 0x0580, 0x0590, 0x05A0, 0x05B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0550, 0x00B0, 0x00B0, 0x00B0, 0x05C0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0140..0x017F -- */\n    0x0040, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x05D0, 0x05E0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x05F0, 0x00B0, 0x0320, 0x00B0, 0x0320, 0x00B0, 0x0320, 0x00B0, 0x00B0, 0x00B0, 0x0600,\n    0x0610, 0x0620, 0x00B0, 0x05C0,\n/* INDEX_BLOCK: -- 0x0180..0x01BF -- */\n    0x0630, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x03D0, 0x00B0, 0x0640, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0650, 0x0660, 0x0670, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0680, 0x0100, 0x0100, 0x00B0, 0x0690, 0x00B0, 0x00B0,\n    0x00B0, 0x06A0, 0x06B0, 0x06C0, 0x00B0, 0x00B0, 0x00B0, 0x0110, 0x0110, 0x06D0, 0x06E0, 0x00B0,\n    0x06F0, 0x00B0, 0x00B0, 0x0700, 0x03E0, 0x00B0, 0x0710, 0x06F0, 0x0460, 0x00B0, 0x0720, 0x00B0,\n    0x00B0, 0x00B0, 0x0730, 0x0460,\n/* INDEX_BLOCK: -- 0x01C0..0x01FF -- */\n    0x00B0, 0x00B0, 0x0740, 0x0750, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x0760, 0x0770, 0x0780, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0110, 0x0110, 0x0110, 0x0110, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0790,\n    0x07A0, 0x07B0, 0x07B0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0200..0x023F -- */\n    0x07D0, 0x0100, 0x07E0, 0x07F0, 0x0800, 0x0810, 0x0820, 0x0830, 0x0840, 0x00B0, 0x0850, 0x0850,\n    0x0850, 0x0110, 0x0110, 0x0580, 0x0860, 0x0870, 0x0880, 0x0890, 0x08A0, 0x0100, 0x00B0, 0x00B0,\n    0x08B0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x08C0, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x08D0, 0x00B0, 0x00B0, 0x00B0, 0x0050, 0x0100, 0x08E0, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100,\n/* INDEX_BLOCK: -- 0x0240..0x027F -- */\n    0x0100, 0x0100, 0x05C0, 0x00B0, 0x08F0, 0x00B0, 0x0100, 0x0100, 0x0900, 0x0910, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0920, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0930, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100,\n/* INDEX_BLOCK: -- 0x0280..0x02BF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0940, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100,\n/* INDEX_BLOCK: -- 0x02C0..0x02FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0950, 0x0960, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0970,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0110, 0x0110, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0980, 0x00B0, 0x00B0, 0x0100, 0x0990, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x09A0,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x08D0, 0x00B0, 0x0100,\n/* INDEX_BLOCK: -- 0x0300..0x033F -- */\n    0x09B0, 0x0100, 0x09C0, 0x09D0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x09E0, 0x0040, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x09F0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0A00, 0x00B0, 0x00B0, 0x07C0, 0x00B0, 0x00B0,\n    0x00B0, 0x0100, 0x00B0, 0x0A10, 0x00B0, 0x00B0, 0x00B0, 0x0A20, 0x0A30, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0A40, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x0680, 0x00B0, 0x0A50,\n/* INDEX_BLOCK: -- 0x0340..0x037F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0380..0x03BF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0100, 0x0100, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x03C0..0x03FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0100,\n    0x0A60, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x07B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0970, 0x0A70, 0x00B0, 0x0A80, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0460,\n    0x0100, 0x0100, 0x0A90, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0AA0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0400..0x043F -- */\n    0x0AB0, 0x00B0, 0x0AC0, 0x0AD0, 0x00B0, 0x00B0, 0x00B0, 0x0AE0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x0AF0, 0x00B0, 0x0110, 0x0B00, 0x00B0, 0x00B0, 0x0B10, 0x00B0, 0x0B20, 0x0460, 0x00B0, 0x00B0,\n    0x02E0, 0x00B0, 0x00B0, 0x0B30, 0x00B0, 0x00B0, 0x0B40, 0x00B0, 0x00B0, 0x00B0, 0x0B50, 0x0B60,\n    0x0B70, 0x00B0, 0x00B0, 0x0340, 0x00B0, 0x00B0, 0x00B0, 0x0B80, 0x0330, 0x00B0, 0x0450, 0x0540,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0890, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0B90, 0x00B0,\n/* INDEX_BLOCK: -- 0x0440..0x047F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x0BA0, 0x0BB0, 0x01A0, 0x01A0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0,\n    0x0BC0, 0x0BD0, 0x01D0, 0x01D0,\n/* INDEX_BLOCK: -- 0x0480..0x04BF -- */\n    0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0,\n    0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x0BE0, 0x0100, 0x01D0, 0x01D0, 0x01D0,\n    0x01D0, 0x0BF0, 0x01D0, 0x01D0, 0x0C00, 0x0080, 0x0080, 0x0C10, 0x0110, 0x05C0, 0x0110, 0x0100,\n    0x0100, 0x0C20, 0x0C30, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x0C40,\n    0x0C50, 0x0030, 0x0040, 0x0050, 0x0040, 0x0050, 0x08D0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0C60, 0x0C70,\n/* INDEX_BLOCK: -- 0x04C0..0x04FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0C80, 0x00B0, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0C90, 0x0C90, 0x0040, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x05B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0CA0, 0x0910,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0CB0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0500..0x053F -- */\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x0CC0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x0CD0, 0x01A0, 0x01A0, 0x0CE0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x0CF0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x0D00, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0,\n/* INDEX_BLOCK: -- 0x0540..0x057F -- */\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01D0, 0x01D0, 0x0D10, 0x0D20, 0x0D30, 0x01A0, 0x0D40, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x0D50, 0x0D60, 0x01A0, 0x01A0, 0x0D70, 0x01A0, 0x01D0, 0x0D80, 0x01D0, 0x02C0,\n    0x01A0, 0x01A0, 0x01A0, 0x01D0, 0x0250, 0x0200, 0x01D0, 0x01A0, 0x0D90, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0,\n/* INDEX_BLOCK: -- 0x0580..0x05BF -- */\n    0x0330, 0x00B0, 0x00B0, 0x0DA0, 0x0DB0, 0x00E0, 0x08D0, 0x0DC0, 0x0460, 0x00B0, 0x00B0, 0x0DD0,\n    0x03E0, 0x00B0, 0x00B0, 0x00B0, 0x02E0, 0x00B0, 0x0DE0, 0x0DF0, 0x00B0, 0x00B0, 0x00B0, 0x0E00,\n    0x0460, 0x00B0, 0x00B0, 0x0E10, 0x0E20, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0970, 0x0E30,\n    0x0330, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0970, 0x0E40, 0x00B0,\n    0x0460, 0x00B0, 0x00B0, 0x0470, 0x0580, 0x00B0, 0x0E50, 0x0DF0, 0x00B0, 0x00B0, 0x00B0, 0x0710,\n    0x0E60, 0x0E70, 0x0370, 0x00B0,\n/* INDEX_BLOCK: -- 0x05C0..0x05FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x0DA0, 0x0490, 0x0E80, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0E90,\n    0x0EA0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x0EB0, 0x0580, 0x0450, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0EC0,\n    0x0580, 0x00B0, 0x0C90, 0x00B0, 0x00B0, 0x00B0, 0x0ED0, 0x0EE0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x0EF0, 0x0F00, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0600..0x063F -- */\n    0x00B0, 0x00B0, 0x0970, 0x0F10, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0F20, 0x0E00, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0F30, 0x0580, 0x00B0, 0x0F40, 0x00B0, 0x00B0, 0x0F50,\n    0x0F60, 0x0F70, 0x00B0, 0x00B0, 0x0F80, 0x0F90, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0FA0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0640..0x067F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x0FB0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0FC0, 0x0FD0, 0x0FE0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0FF0, 0x0EE0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x1000, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x1010,\n    0x0460, 0x00B0, 0x00B0, 0x0CB0, 0x0E70, 0x0480, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x1020, 0x1030, 0x0A90,\n/* INDEX_BLOCK: -- 0x0680..0x06BF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x1040, 0x1050, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x06C0..0x06FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0A80, 0x1060, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0700..0x073F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0DF0,\n    0x00B0, 0x00B0, 0x00B0, 0x0DB0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0740..0x077F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0970, 0x00B0, 0x00B0, 0x00B0, 0x0970, 0x02E0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x1070, 0x00B0,\n/* INDEX_BLOCK: -- 0x0780..0x07BF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x1080, 0x1090, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x07C0..0x07FF -- */\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x08D0, 0x00B0, 0x10A0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x10B0, 0x0100, 0x0040, 0x0100, 0x0040,\n    0x0110, 0x0110, 0x06D0, 0x0110, 0x0DB0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0800..0x083F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x10C0, 0x10D0,\n    0x10E0, 0x00B0, 0x10F0, 0x00B0, 0x00B0, 0x00B0, 0x00D0, 0x00B0, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x1100, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0A60, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0840..0x087F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0C80, 0x09F0, 0x00B0, 0x09F0,\n    0x00B0, 0x1110, 0x00B0, 0x1110, 0x0A50, 0x00B0, 0x0A50, 0x00B0, 0x1120, 0x00B0, 0x1120, 0x00B0,\n    0x1130, 0x1140, 0x1140, 0x1140,\n/* INDEX_BLOCK: -- 0x0880..0x08BF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0110, 0x0110, 0x0110, 0x1150,\n    0x0110, 0x0110, 0x0530, 0x0B40, 0x1160, 0x0710, 0x1170, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x08C0..0x08FF -- */\n    0x1180, 0x1190, 0x11A0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0970, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0DB0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0E80, 0x00B0, 0x00B0, 0x00B0, 0x0740, 0x11B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0900..0x093F -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x0740, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x0A80, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x11C0, 0x0B40,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0940..0x097F -- */\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x11D0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x11E0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0,\n/* INDEX_BLOCK: -- 0x0980..0x09BF -- */\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01D0, 0x01D0, 0x01D0, 0x01D0,\n    0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x01D0, 0x0BF0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0, 0x01A0,\n    0x01A0, 0x01A0, 0x01A0, 0x01A0,\n/* INDEX_BLOCK: -- 0x09C0..0x09FF -- */\n    0x0100, 0x0100, 0x11F0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x09A0, 0x1200, 0x0A20,\n    0x0A20, 0x0A20, 0x0100, 0x08D0, 0x1210, 0x00B0, 0x0A50, 0x00B0, 0x00B0, 0x00B0, 0x0920, 0x00B0,\n    0x00B0, 0x00B0, 0x1220, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x08D0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100,\n/* INDEX_BLOCK: -- 0x0A00..0x0A3F -- */\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x1230, 0x0C90, 0x0C90,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x05C0, 0x11F0, 0x0040,\n/* INDEX_BLOCK: -- 0x0A40..0x0A7F -- */\n    0x11F0, 0x0100, 0x0100, 0x0100, 0x1240, 0x05C0, 0x0100, 0x0100, 0x1240, 0x0100, 0x0980, 0x11F0,\n    0x0A90, 0x1250, 0x00B0, 0x00B0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,\n    0x0100, 0x1240, 0x0980, 0x0C90, 0x1260, 0x0100, 0x0100, 0x0100, 0x1270, 0x1280, 0x1290, 0x1250,\n    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x12A0, 0x0100, 0x0100,\n    0x0100, 0x0100, 0x0100, 0x12B0,\n/* INDEX_BLOCK: -- 0x0A80..0x0ABF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x00B0, 0x00B0, 0x00B0, 0x12C0,\n/* INDEX_BLOCK: -- 0x0AC0..0x0AFF -- */\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110,\n    0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080,\n/* INDEX_BLOCK: -- 0x0B00..0x0B3F -- */\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080\n};\n\nstatic const SBUInt16 BranchBidiTypeIndexes[1088] = {\n    0x0000, 0x0040, 0x0080, 0x00C0, 0x0100, 0x0140, 0x0180, 0x01C0, 0x0200, 0x0240, 0x0280, 0x02C0,\n    0x0300, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0380, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x03C0, 0x0400, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0440, 0x0480, 0x04C0, 0x0340, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0680, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x06C0, 0x0340, 0x0700, 0x0740, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0780, 0x0340, 0x0340, 0x0340, 0x07C0, 0x0800, 0x0840, 0x0880, 0x0340,\n    0x08C0, 0x0900, 0x0940, 0x0980, 0x09C0, 0x0A00, 0x0A40, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80, 0x0AC0, 0x0B00, 0x0B00, 0x0B00,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0A80\n};\n\nSB_INTERNAL SBBidiType LookupBidiType(SBCodepoint codepoint)\n{\n    if (codepoint <= 0x10FFFF) {\n        return PrimaryBidiTypeData[\n                MainBidiTypeIndexes[\n                 BranchBidiTypeIndexes[\n                      codepoint / 0x0400\n                 ] + (codepoint % 0x0400) / 0x0010\n                ] + codepoint % 0x0010\n               ];\n    }\n\n    return ON;\n}\n\n#undef AL\n#undef AN\n#undef B\n#undef BN\n#undef CS\n#undef EN\n#undef ES\n#undef ET\n#undef FSI\n#undef L\n#undef LRE\n#undef LRI\n#undef LRO\n#undef NSM\n#undef ON\n#undef PDF\n#undef PDI\n#undef R\n#undef RLE\n#undef RLI\n#undef RLO\n#undef S\n#undef WS\n"
  },
  {
    "path": "unix/bidi/Source/Data/BidiTypeLookup.h",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n */\n\n#ifndef _SB_INTERNAL_BIDI_TYPE_LOOKUP_H\n#define _SB_INTERNAL_BIDI_TYPE_LOOKUP_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n\nSB_INTERNAL SBBidiType LookupBidiType(SBCodepoint codepoint);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Data/GeneralCategoryLookup.c",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool. \n * DO NOT EDIT!!\n *\n * REQUIRED MEMORY: 11472+(4288*2)+(1088*2) = 22224 Bytes\n */\n\n#include \"GeneralCategoryLookup.h\"\n\n#define Cc     SBGeneralCategoryCC\n#define Cf     SBGeneralCategoryCF\n#define Cn     SBGeneralCategoryCN\n#define Co     SBGeneralCategoryCO\n#define Cs     SBGeneralCategoryCS\n#define Ll     SBGeneralCategoryLL\n#define Lm     SBGeneralCategoryLM\n#define Lo     SBGeneralCategoryLO\n#define Lt     SBGeneralCategoryLT\n#define Lu     SBGeneralCategoryLU\n#define Mc     SBGeneralCategoryMC\n#define Me     SBGeneralCategoryME\n#define Mn     SBGeneralCategoryMN\n#define Nd     SBGeneralCategoryND\n#define Nl     SBGeneralCategoryNL\n#define No     SBGeneralCategoryNO\n#define Pc     SBGeneralCategoryPC\n#define Pd     SBGeneralCategoryPD\n#define Pe     SBGeneralCategoryPE\n#define Pf     SBGeneralCategoryPF\n#define Pi     SBGeneralCategoryPI\n#define Po     SBGeneralCategoryPO\n#define Ps     SBGeneralCategoryPS\n#define Sc     SBGeneralCategorySC\n#define Sk     SBGeneralCategorySK\n#define Sm     SBGeneralCategorySM\n#define So     SBGeneralCategorySO\n#define Zl     SBGeneralCategoryZL\n#define Zp     SBGeneralCategoryZP\n#define Zs     SBGeneralCategoryZS\n\nstatic const SBUInt8 PrimaryGeneralCategoryData[11472] = {\n/* DATA_BLOCK: -- 0x0000..0x000F -- */\n    Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc, Cc,\n/* DATA_BLOCK: -- 0x0010..0x001F -- */\n    Zs, Po, Po, Po, Sc, Po, Po, Po, Ps, Pe, Po, Sm, Po, Pd, Po, Po,\n/* DATA_BLOCK: -- 0x0020..0x002F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Po, Po, Sm, Sm, Sm, Po,\n/* DATA_BLOCK: -- 0x0030..0x003F -- */\n    Po, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x0040..0x004F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ps, Po, Pe, Sk, Pc,\n/* DATA_BLOCK: -- 0x0050..0x005F -- */\n    Sk, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0060..0x006F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ps, Sm, Pe, Sm, Cc,\n/* DATA_BLOCK: -- 0x0070..0x007F -- */\n    Zs, Po, Sc, Sc, Sc, Sc, So, Po, Sk, So, Lo, Pi, Sm, Cf, So, Sk,\n/* DATA_BLOCK: -- 0x0080..0x008F -- */\n    So, Sm, No, No, Sk, Ll, Po, Po, Sk, No, Lo, Pf, No, No, No, Po,\n/* DATA_BLOCK: -- 0x0090..0x009F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x00A0..0x00AF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Sm, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ll,\n/* DATA_BLOCK: -- 0x00B0..0x00BF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x00C0..0x00CF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Sm, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x00D0..0x00DF -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x00E0..0x00EF -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu,\n/* DATA_BLOCK: -- 0x00F0..0x00FF -- */\n    Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0100..0x010F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Lu, Ll, Lu, Ll, Lu, Ll, Ll,\n/* DATA_BLOCK: -- 0x0110..0x011F -- */\n    Ll, Lu, Lu, Ll, Lu, Ll, Lu, Lu, Ll, Lu, Lu, Lu, Ll, Ll, Lu, Lu,\n/* DATA_BLOCK: -- 0x0120..0x012F -- */\n    Lu, Lu, Ll, Lu, Lu, Ll, Lu, Lu, Lu, Ll, Ll, Ll, Lu, Lu, Ll, Lu,\n/* DATA_BLOCK: -- 0x0130..0x013F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Lu, Ll, Lu, Ll, Ll, Lu, Ll, Lu, Lu,\n/* DATA_BLOCK: -- 0x0140..0x014F -- */\n    Ll, Lu, Lu, Lu, Ll, Lu, Ll, Lu, Lu, Ll, Ll, Lo, Lu, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0150..0x015F -- */\n    Lo, Lo, Lo, Lo, Lu, Lt, Ll, Lu, Lt, Ll, Lu, Lt, Ll, Lu, Ll, Lu,\n/* DATA_BLOCK: -- 0x0160..0x016F -- */\n    Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0170..0x017F -- */\n    Ll, Lu, Lt, Ll, Lu, Ll, Lu, Lu, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0180..0x018F -- */\n    Lu, Ll, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Ll, Lu, Lu, Ll,\n/* DATA_BLOCK: -- 0x0190..0x019F -- */\n    Ll, Lu, Ll, Lu, Lu, Lu, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x01A0..0x01AF -- */\n    Ll, Ll, Ll, Ll, Lo, Lo, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x01B0..0x01BF -- */\n    Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x01C0..0x01CF -- */\n    Lm, Lm, Sk, Sk, Sk, Sk, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x01D0..0x01DF -- */\n    Lm, Lm, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x01E0..0x01EF -- */\n    Lm, Lm, Lm, Lm, Lm, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Lm, Sk, Lm, Sk,\n/* DATA_BLOCK: -- 0x01F0..0x01FF -- */\n    Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x0200..0x020F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0210..0x021F -- */\n    Lu, Ll, Lu, Ll, Lm, Sk, Lu, Ll, Cn, Cn, Lm, Ll, Ll, Ll, Po, Lu,\n/* DATA_BLOCK: -- 0x0220..0x022F -- */\n    Cn, Cn, Cn, Cn, Sk, Sk, Lu, Po, Lu, Lu, Lu, Cn, Lu, Cn, Lu, Lu,\n/* DATA_BLOCK: -- 0x0230..0x023F -- */\n    Ll, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x0240..0x024F -- */\n    Lu, Lu, Cn, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0250..0x025F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu,\n/* DATA_BLOCK: -- 0x0260..0x026F -- */\n    Ll, Ll, Lu, Lu, Lu, Ll, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0270..0x027F -- */\n    Ll, Ll, Ll, Ll, Lu, Ll, Sm, Lu, Ll, Lu, Lu, Ll, Ll, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x0280..0x028F -- */\n    Lu, Ll, So, Mn, Mn, Mn, Mn, Mn, Me, Me, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0290..0x029F -- */\n    Lu, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Ll,\n/* DATA_BLOCK: -- 0x02A0..0x02AF -- */\n    Cn, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x02B0..0x02BF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn, Lm, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x02C0..0x02CF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Po, Pd, Cn, Cn, So, So, Sc,\n/* DATA_BLOCK: -- 0x02D0..0x02DF -- */\n    Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x02E0..0x02EF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Pd, Mn,\n/* DATA_BLOCK: -- 0x02F0..0x02FF -- */\n    Po, Mn, Mn, Po, Mn, Mn, Po, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0300..0x030F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0310..0x031F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x0320..0x032F -- */\n    Lo, Lo, Lo, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0330..0x033F -- */\n    Cf, Cf, Cf, Cf, Cf, Cf, Sm, Sm, Sm, Po, Po, Sc, Po, Po, So, So,\n/* DATA_BLOCK: -- 0x0340..0x034F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po, Cf, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0350..0x035F -- */\n    Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0360..0x036F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Po, Po, Po, Po, Lo, Lo,\n/* DATA_BLOCK: -- 0x0370..0x037F -- */\n    Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0380..0x038F -- */\n    Lo, Lo, Lo, Lo, Po, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cf, So, Mn,\n/* DATA_BLOCK: -- 0x0390..0x039F -- */\n    Mn, Mn, Mn, Mn, Mn, Lm, Lm, Mn, Mn, So, Mn, Mn, Mn, Mn, Lo, Lo,\n/* DATA_BLOCK: -- 0x03A0..0x03AF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Lo, Lo, So, So, Lo,\n/* DATA_BLOCK: -- 0x03B0..0x03BF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn, Cf,\n/* DATA_BLOCK: -- 0x03C0..0x03CF -- */\n    Lo, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x03D0..0x03DF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x03E0..0x03EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x03F0..0x03FF -- */\n    Mn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0400..0x040F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0410..0x041F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0420..0x042F -- */\n    Mn, Mn, Mn, Mn, Lm, Lm, So, Po, Po, Po, Lm, Cn, Cn, Mn, Sc, Sc,\n/* DATA_BLOCK: -- 0x0430..0x043F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Lm, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0440..0x044F -- */\n    Mn, Mn, Mn, Mn, Lm, Mn, Mn, Mn, Lm, Mn, Mn, Mn, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0450..0x045F -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn,\n/* DATA_BLOCK: -- 0x0460..0x046F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Cn, Cn, Po, Cn,\n/* DATA_BLOCK: -- 0x0470..0x047F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0480..0x048F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Sk, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0490..0x049F -- */\n    Cf, Cf, Cn, Cn, Cn, Cn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x04A0..0x04AF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x04B0..0x04BF -- */\n    Mn, Mn, Cf, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x04C0..0x04CF -- */\n    Mn, Mn, Mn, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x04D0..0x04DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mc, Mn, Lo, Mc, Mc,\n/* DATA_BLOCK: -- 0x04E0..0x04EF -- */\n    Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc, Mc, Mc, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x04F0..0x04FF -- */\n    Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0500..0x050F -- */\n    Lo, Lo, Mn, Mn, Po, Po, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x0510..0x051F -- */\n    Po, Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0520..0x052F -- */\n    Lo, Mn, Mc, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x0530..0x053F -- */\n    Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0540..0x054F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0550..0x055F -- */\n    Lo, Cn, Lo, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Lo, Mc, Mc,\n/* DATA_BLOCK: -- 0x0560..0x056F -- */\n    Mc, Mn, Mn, Mn, Mn, Cn, Cn, Mc, Mc, Cn, Cn, Mc, Mc, Mn, Lo, Cn,\n/* DATA_BLOCK: -- 0x0570..0x057F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mc, Cn, Cn, Cn, Cn, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x0580..0x058F -- */\n    Lo, Lo, Mn, Mn, Cn, Cn, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x0590..0x059F -- */\n    Lo, Lo, Sc, Sc, No, No, No, No, No, No, So, Sc, Lo, Po, Mn, Cn,\n/* DATA_BLOCK: -- 0x05A0..0x05AF -- */\n    Cn, Mn, Mn, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x05B0..0x05BF -- */\n    Lo, Cn, Lo, Lo, Cn, Lo, Lo, Cn, Lo, Lo, Cn, Cn, Mn, Cn, Mc, Mc,\n/* DATA_BLOCK: -- 0x05C0..0x05CF -- */\n    Mc, Mn, Mn, Cn, Cn, Cn, Cn, Mn, Mn, Cn, Cn, Mn, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x05D0..0x05DF -- */\n    Cn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Cn,\n/* DATA_BLOCK: -- 0x05E0..0x05EF -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x05F0..0x05FF -- */\n    Mn, Mn, Lo, Lo, Lo, Mn, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0600..0x060F -- */\n    Cn, Mn, Mn, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x0610..0x061F -- */\n    Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0620..0x062F -- */\n    Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Lo, Mc, Mc,\n/* DATA_BLOCK: -- 0x0630..0x063F -- */\n    Mc, Mn, Mn, Mn, Mn, Mn, Cn, Mn, Mn, Mc, Cn, Mc, Mc, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0640..0x064F -- */\n    Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0650..0x065F -- */\n    Po, Sc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0660..0x066F -- */\n    Cn, Mn, Mc, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x0670..0x067F -- */\n    Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Lo, Mc, Mn,\n/* DATA_BLOCK: -- 0x0680..0x068F -- */\n    Mc, Mn, Mn, Mn, Mn, Cn, Cn, Mc, Mc, Cn, Cn, Mc, Mc, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0690..0x069F -- */\n    Cn, Cn, Cn, Cn, Cn, Mn, Mn, Mc, Cn, Cn, Cn, Cn, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x06A0..0x06AF -- */\n    So, Lo, No, No, No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x06B0..0x06BF -- */\n    Cn, Cn, Mn, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x06C0..0x06CF -- */\n    Lo, Cn, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Lo, Lo, Cn, Lo, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x06D0..0x06DF -- */\n    Cn, Cn, Cn, Lo, Lo, Cn, Cn, Cn, Lo, Lo, Lo, Cn, Cn, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x06E0..0x06EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Mc, Mc,\n/* DATA_BLOCK: -- 0x06F0..0x06FF -- */\n    Mn, Mc, Mc, Cn, Cn, Cn, Mc, Mc, Mc, Cn, Mc, Mc, Mc, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0700..0x070F -- */\n    Lo, Cn, Cn, Cn, Cn, Cn, Cn, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0710..0x071F -- */\n    No, No, No, So, So, So, So, So, So, Sc, So, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0720..0x072F -- */\n    Mn, Mc, Mc, Mc, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x0730..0x073F -- */\n    Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0740..0x074F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Lo, Mn, Mn,\n/* DATA_BLOCK: -- 0x0750..0x075F -- */\n    Mn, Mc, Mc, Mc, Mc, Cn, Mn, Mn, Mn, Cn, Mn, Mn, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0760..0x076F -- */\n    Cn, Cn, Cn, Cn, Cn, Mn, Mn, Cn, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0770..0x077F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po, No, No, No, No, No, No, No, So,\n/* DATA_BLOCK: -- 0x0780..0x078F -- */\n    Lo, Mn, Mc, Mc, Po, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x0790..0x079F -- */\n    Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Lo, Mc, Mn,\n/* DATA_BLOCK: -- 0x07A0..0x07AF -- */\n    Mc, Mc, Mc, Mc, Mc, Cn, Mn, Mc, Mc, Cn, Mc, Mc, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x07B0..0x07BF -- */\n    Cn, Cn, Cn, Cn, Cn, Mc, Mc, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x07C0..0x07CF -- */\n    Cn, Lo, Lo, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x07D0..0x07DF -- */\n    Mn, Mn, Mc, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x07E0..0x07EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Lo, Mc, Mc,\n/* DATA_BLOCK: -- 0x07F0..0x07FF -- */\n    Mc, Mn, Mn, Mn, Mn, Cn, Mc, Mc, Mc, Cn, Mc, Mc, Mc, Mn, Lo, So,\n/* DATA_BLOCK: -- 0x0800..0x080F -- */\n    Cn, Cn, Cn, Cn, Lo, Lo, Lo, Mc, No, No, No, No, No, No, No, Lo,\n/* DATA_BLOCK: -- 0x0810..0x081F -- */\n    No, No, No, No, No, No, No, No, No, So, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0820..0x082F -- */\n    Cn, Mn, Mc, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0830..0x083F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0840..0x084F -- */\n    Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0850..0x085F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Mn, Cn, Cn, Cn, Cn, Mc,\n/* DATA_BLOCK: -- 0x0860..0x086F -- */\n    Mc, Mc, Mn, Mn, Mn, Cn, Mn, Cn, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x0870..0x087F -- */\n    Cn, Cn, Mc, Mc, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0880..0x088F -- */\n    Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0890..0x089F -- */\n    Lo, Mn, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Sc,\n/* DATA_BLOCK: -- 0x08A0..0x08AF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lm, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po,\n/* DATA_BLOCK: -- 0x08B0..0x08BF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Po, Po, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x08C0..0x08CF -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x08D0..0x08DF -- */\n    Cn, Lo, Lo, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x08E0..0x08EF -- */\n    Lo, Lo, Lo, Lo, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x08F0..0x08FF -- */\n    Lo, Mn, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0900..0x090F -- */\n    Lo, Lo, Lo, Lo, Lo, Cn, Lm, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn,\n/* DATA_BLOCK: -- 0x0910..0x091F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0920..0x092F -- */\n    Lo, So, So, So, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0930..0x093F -- */\n    Po, Po, Po, So, Po, So, So, So, Mn, Mn, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x0940..0x094F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x0950..0x095F -- */\n    No, No, No, No, So, Mn, So, Mn, So, Mn, Ps, Pe, Ps, Pe, Mc, Mc,\n/* DATA_BLOCK: -- 0x0960..0x096F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0970..0x097F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0980..0x098F -- */\n    Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc,\n/* DATA_BLOCK: -- 0x0990..0x099F -- */\n    Mn, Mn, Mn, Mn, Mn, Po, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x09A0..0x09AF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x09B0..0x09BF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, So, So,\n/* DATA_BLOCK: -- 0x09C0..0x09CF -- */\n    So, So, So, So, So, So, Mn, So, So, So, So, So, So, Cn, So, So,\n/* DATA_BLOCK: -- 0x09D0..0x09DF -- */\n    Po, Po, Po, Po, Po, So, So, So, So, Po, Po, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x09E0..0x09EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mc, Mc, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x09F0..0x09FF -- */\n    Mn, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mn, Mc, Mc, Mn, Mn, Lo,\n/* DATA_BLOCK: -- 0x0A00..0x0A0F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0A10..0x0A1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mc, Mc, Mn, Mn, Lo, Lo, Lo, Lo, Mn, Mn,\n/* DATA_BLOCK: -- 0x0A20..0x0A2F -- */\n    Mn, Lo, Mc, Mc, Mc, Lo, Lo, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Lo, Lo,\n/* DATA_BLOCK: -- 0x0A30..0x0A3F -- */\n    Lo, Mn, Mn, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0A40..0x0A4F -- */\n    Lo, Lo, Mn, Mc, Mc, Mn, Mn, Mc, Mc, Mc, Mc, Mc, Mc, Mn, Lo, Mc,\n/* DATA_BLOCK: -- 0x0A50..0x0A5F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Mc, Mc, Mc, Mn, So, So,\n/* DATA_BLOCK: -- 0x0A60..0x0A6F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Cn, Lu, Cn, Cn, Cn, Cn, Cn, Lu, Cn, Cn,\n/* DATA_BLOCK: -- 0x0A70..0x0A7F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Po, Lm, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0A80..0x0A8F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0A90..0x0A9F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0AA0..0x0AAF -- */\n    Lo, Cn, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x0AB0..0x0ABF -- */\n    Lo, Cn, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0AC0..0x0ACF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0AD0..0x0ADF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0AE0..0x0AEF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x0AF0..0x0AFF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0B00..0x0B0F -- */\n    So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0B10..0x0B1F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn,\n/* DATA_BLOCK: -- 0x0B20..0x0B2F -- */\n    Pd, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0B30..0x0B3F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, So, Po, Lo,\n/* DATA_BLOCK: -- 0x0B40..0x0B4F -- */\n    Zs, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0B50..0x0B5F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Ps, Pe, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0B60..0x0B6F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Po, Po, Po, Nl, Nl,\n/* DATA_BLOCK: -- 0x0B70..0x0B7F -- */\n    Nl, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0B80..0x0B8F -- */\n    Lo, Lo, Mn, Mn, Mn, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x0B90..0x0B9F -- */\n    Lo, Lo, Mn, Mn, Mc, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0BA0..0x0BAF -- */\n    Lo, Lo, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0BB0..0x0BBF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo,\n/* DATA_BLOCK: -- 0x0BC0..0x0BCF -- */\n    Lo, Cn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0BD0..0x0BDF -- */\n    Lo, Lo, Lo, Lo, Mn, Mn, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x0BE0..0x0BEF -- */\n    Mc, Mc, Mc, Mc, Mc, Mc, Mn, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0BF0..0x0BFF -- */\n    Mn, Mn, Mn, Mn, Po, Po, Po, Lm, Po, Po, Po, Sc, Lo, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C00..0x0C0F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C10..0x0C1F -- */\n    No, No, No, No, No, No, No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C20..0x0C2F -- */\n    Po, Po, Po, Po, Po, Po, Pd, Po, Po, Po, Po, Mn, Mn, Mn, Cf, Mn,\n/* DATA_BLOCK: -- 0x0C30..0x0C3F -- */\n    Lo, Lo, Lo, Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0C40..0x0C4F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C50..0x0C5F -- */\n    Lo, Lo, Lo, Lo, Lo, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0C60..0x0C6F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Lo, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C70..0x0C7F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0C80..0x0C8F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x0C90..0x0C9F -- */\n    Mn, Mn, Mn, Mc, Mc, Mc, Mc, Mn, Mn, Mc, Mc, Mc, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0CA0..0x0CAF -- */\n    Mc, Mc, Mn, Mc, Mc, Mc, Mc, Mc, Mc, Mn, Mn, Mn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0CB0..0x0CBF -- */\n    So, Cn, Cn, Cn, Po, Po, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x0CC0..0x0CCF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn,\n/* DATA_BLOCK: -- 0x0CD0..0x0CDF -- */\n    Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0CE0..0x0CEF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0CF0..0x0CFF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0D00..0x0D0F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, No, Cn, Cn, Cn, So, So,\n/* DATA_BLOCK: -- 0x0D10..0x0D1F -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x0D20..0x0D2F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mc, Mc, Mn, Cn, Cn, Po, Po,\n/* DATA_BLOCK: -- 0x0D30..0x0D3F -- */\n    Lo, Lo, Lo, Lo, Lo, Mc, Mn, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn,\n/* DATA_BLOCK: -- 0x0D40..0x0D4F -- */\n    Mn, Mc, Mn, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x0D50..0x0D5F -- */\n    Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x0D60..0x0D6F -- */\n    Po, Po, Po, Po, Po, Po, Po, Lm, Po, Po, Po, Po, Po, Po, Cn, Cn,\n/* DATA_BLOCK: -- 0x0D70..0x0D7F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Me, Mn,\n/* DATA_BLOCK: -- 0x0D80..0x0D8F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0D90..0x0D9F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0DA0..0x0DAF -- */\n    Mn, Mn, Mn, Mn, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0DB0..0x0DBF -- */\n    Lo, Lo, Lo, Lo, Mn, Mc, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x0DC0..0x0DCF -- */\n    Mc, Mc, Mn, Mc, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Po, Po,\n/* DATA_BLOCK: -- 0x0DD0..0x0DDF -- */\n    Po, So, So, So, So, So, So, So, So, So, So, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0DE0..0x0DEF -- */\n    Mn, Mn, Mn, Mn, So, So, So, So, So, So, So, So, So, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0DF0..0x0DFF -- */\n    Mn, Mn, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0E00..0x0E0F -- */\n    Lo, Mc, Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mn, Mc, Mn, Mn, Mn, Lo, Lo,\n/* DATA_BLOCK: -- 0x0E10..0x0E1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mc, Mn, Mn, Mc, Mc, Mc, Mn, Mc, Mn,\n/* DATA_BLOCK: -- 0x0E20..0x0E2F -- */\n    Mn, Mn, Mc, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0E30..0x0E3F -- */\n    Lo, Lo, Lo, Lo, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0E40..0x0E4F -- */\n    Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mn, Cn, Cn, Cn, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x0E50..0x0E5F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x0E60..0x0E6F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Lm, Lm, Lm, Lm, Lm, Po, Po,\n/* DATA_BLOCK: -- 0x0E70..0x0E7F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Ll, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0E80..0x0E8F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x0E90..0x0E9F -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0EA0..0x0EAF -- */\n    Mn, Mn, Mn, Po, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x0EB0..0x0EBF -- */\n    Mn, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lo, Lo, Lo, Lo, Mn, Lo, Lo,\n/* DATA_BLOCK: -- 0x0EC0..0x0ECF -- */\n    Lo, Lo, Lo, Lo, Mn, Lo, Lo, Mc, Mn, Mn, Lo, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x0ED0..0x0EDF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x0EE0..0x0EEF -- */\n    Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0EF0..0x0EFF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lm, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x0F00..0x0F0F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x0F10..0x0F1F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x0F20..0x0F2F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x0F30..0x0F3F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn,\n/* DATA_BLOCK: -- 0x0F40..0x0F4F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Lu, Cn, Lu, Cn, Lu, Cn, Lu,\n/* DATA_BLOCK: -- 0x0F50..0x0F5F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn,\n/* DATA_BLOCK: -- 0x0F60..0x0F6F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lt, Lt, Lt, Lt, Lt, Lt, Lt, Lt,\n/* DATA_BLOCK: -- 0x0F70..0x0F7F -- */\n    Ll, Ll, Ll, Ll, Ll, Cn, Ll, Ll, Lu, Lu, Lu, Lu, Lt, Sk, Ll, Sk,\n/* DATA_BLOCK: -- 0x0F80..0x0F8F -- */\n    Sk, Sk, Ll, Ll, Ll, Cn, Ll, Ll, Lu, Lu, Lu, Lu, Lt, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x0F90..0x0F9F -- */\n    Ll, Ll, Ll, Ll, Cn, Cn, Ll, Ll, Lu, Lu, Lu, Lu, Cn, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x0FA0..0x0FAF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu, Lu, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x0FB0..0x0FBF -- */\n    Cn, Cn, Ll, Ll, Ll, Cn, Ll, Ll, Lu, Lu, Lu, Lu, Lt, Sk, Sk, Cn,\n/* DATA_BLOCK: -- 0x0FC0..0x0FCF -- */\n    Zs, Zs, Zs, Zs, Zs, Zs, Zs, Zs, Zs, Zs, Zs, Cf, Cf, Cf, Cf, Cf,\n/* DATA_BLOCK: -- 0x0FD0..0x0FDF -- */\n    Pd, Pd, Pd, Pd, Pd, Pd, Po, Po, Pi, Pf, Ps, Pi, Pi, Pf, Ps, Pi,\n/* DATA_BLOCK: -- 0x0FE0..0x0FEF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Zl, Zp, Cf, Cf, Cf, Cf, Cf, Zs,\n/* DATA_BLOCK: -- 0x0FF0..0x0FFF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Pi, Pf, Po, Po, Po, Po, Pc,\n/* DATA_BLOCK: -- 0x1000..0x100F -- */\n    Pc, Po, Po, Po, Sm, Ps, Pe, Po, Po, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1010..0x101F -- */\n    Po, Po, Sm, Po, Pc, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Zs,\n/* DATA_BLOCK: -- 0x1020..0x102F -- */\n    Cf, Cf, Cf, Cf, Cf, Cn, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf,\n/* DATA_BLOCK: -- 0x1030..0x103F -- */\n    No, Lm, Cn, Cn, No, No, No, No, No, No, Sm, Sm, Sm, Ps, Pe, Lm,\n/* DATA_BLOCK: -- 0x1040..0x104F -- */\n    No, No, No, No, No, No, No, No, No, No, Sm, Sm, Sm, Ps, Pe, Cn,\n/* DATA_BLOCK: -- 0x1050..0x105F -- */\n    Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1060..0x106F -- */\n    Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc, Sc,\n/* DATA_BLOCK: -- 0x1070..0x107F -- */\n    Sc, Sc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1080..0x108F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Me, Me, Me,\n/* DATA_BLOCK: -- 0x1090..0x109F -- */\n    Me, Mn, Me, Me, Me, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x10A0..0x10AF -- */\n    Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x10B0..0x10BF -- */\n    So, So, Lu, So, So, So, So, Lu, So, So, Ll, Lu, Lu, Lu, Ll, Ll,\n/* DATA_BLOCK: -- 0x10C0..0x10CF -- */\n    Lu, Lu, Lu, Ll, So, Lu, So, So, Sm, Lu, Lu, Lu, Lu, Lu, So, So,\n/* DATA_BLOCK: -- 0x10D0..0x10DF -- */\n    So, So, So, So, Lu, So, Lu, So, Lu, So, Lu, Lu, Lu, Lu, So, Ll,\n/* DATA_BLOCK: -- 0x10E0..0x10EF -- */\n    Lu, Lu, Lu, Lu, Ll, Lo, Lo, Lo, Lo, Ll, So, So, Ll, Ll, Lu, Lu,\n/* DATA_BLOCK: -- 0x10F0..0x10FF -- */\n    Sm, Sm, Sm, Sm, Sm, Lu, Ll, Ll, Ll, Ll, So, Sm, So, So, Ll, So,\n/* DATA_BLOCK: -- 0x1100..0x110F -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1110..0x111F -- */\n    Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl,\n/* DATA_BLOCK: -- 0x1120..0x112F -- */\n    Nl, Nl, Nl, Lu, Ll, Nl, Nl, Nl, Nl, No, So, So, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1130..0x113F -- */\n    Sm, Sm, Sm, Sm, Sm, So, So, So, So, So, Sm, Sm, So, So, So, So,\n/* DATA_BLOCK: -- 0x1140..0x114F -- */\n    Sm, So, So, Sm, So, So, Sm, So, So, So, So, So, So, So, Sm, So,\n/* DATA_BLOCK: -- 0x1150..0x115F -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, So, Sm, Sm,\n/* DATA_BLOCK: -- 0x1160..0x116F -- */\n    So, So, Sm, So, Sm, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1170..0x117F -- */\n    So, So, So, So, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x1180..0x118F -- */\n    Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x1190..0x119F -- */\n    So, So, So, So, So, So, So, So, Ps, Pe, Ps, Pe, So, So, So, So,\n/* DATA_BLOCK: -- 0x11A0..0x11AF -- */\n    Sm, Sm, So, So, So, So, So, So, So, Ps, Pe, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x11B0..0x11BF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, Sm, So, So, So,\n/* DATA_BLOCK: -- 0x11C0..0x11CF -- */\n    So, So, So, So, So, So, So, So, So, So, So, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x11D0..0x11DF -- */\n    Sm, Sm, Sm, Sm, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x11E0..0x11EF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x11F0..0x11FF -- */\n    Sm, Sm, So, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1200..0x120F -- */\n    So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1210..0x121F -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, So, So, So, So,\n/* DATA_BLOCK: -- 0x1220..0x122F -- */\n    So, So, So, So, So, So, So, So, So, So, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1230..0x123F -- */\n    So, So, So, So, So, So, So, Sm, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1240..0x124F -- */\n    So, Sm, So, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1250..0x125F -- */\n    So, So, So, So, So, So, So, So, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x1260..0x126F -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, So, So, Sm,\n/* DATA_BLOCK: -- 0x1270..0x127F -- */\n    So, So, So, So, So, So, So, So, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe,\n/* DATA_BLOCK: -- 0x1280..0x128F -- */\n    Ps, Pe, Ps, Pe, Ps, Pe, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1290..0x129F -- */\n    No, No, No, No, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x12A0..0x12AF -- */\n    Sm, Sm, Sm, Sm, Sm, Ps, Pe, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x12B0..0x12BF -- */\n    Sm, Sm, Sm, Sm, Sm, Sm, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe,\n/* DATA_BLOCK: -- 0x12C0..0x12CF -- */\n    Sm, Sm, Sm, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps,\n/* DATA_BLOCK: -- 0x12D0..0x12DF -- */\n    Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Sm, Sm, Sm, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x12E0..0x12EF -- */\n    Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Ps, Pe, Ps, Pe, Sm, Sm, Sm, Sm,\n/* DATA_BLOCK: -- 0x12F0..0x12FF -- */\n    Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Ps, Pe, Sm, Sm,\n/* DATA_BLOCK: -- 0x1300..0x130F -- */\n    Sm, Sm, Sm, Sm, Sm, So, So, Sm, Sm, Sm, Sm, Sm, Sm, So, So, So,\n/* DATA_BLOCK: -- 0x1310..0x131F -- */\n    So, So, So, So, Cn, Cn, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1320..0x132F -- */\n    Lu, Ll, Lu, Lu, Lu, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x1330..0x133F -- */\n    Lu, Ll, Lu, Ll, Ll, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Lm, Lm, Lu, Lu,\n/* DATA_BLOCK: -- 0x1340..0x134F -- */\n    Lu, Ll, Lu, Ll, Ll, So, So, So, So, So, So, Lu, Ll, Lu, Ll, Mn,\n/* DATA_BLOCK: -- 0x1350..0x135F -- */\n    Mn, Mn, Lu, Ll, Cn, Cn, Cn, Cn, Cn, Po, Po, Po, Po, No, Po, Po,\n/* DATA_BLOCK: -- 0x1360..0x136F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Cn, Ll, Cn, Cn, Cn, Cn, Cn, Ll, Cn, Cn,\n/* DATA_BLOCK: -- 0x1370..0x137F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lm,\n/* DATA_BLOCK: -- 0x1380..0x138F -- */\n    Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x1390..0x139F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x13A0..0x13AF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x13B0..0x13BF -- */\n    Po, Po, Pi, Pf, Pi, Pf, Po, Po, Po, Pi, Pf, Po, Pi, Pf, Po, Po,\n/* DATA_BLOCK: -- 0x13C0..0x13CF -- */\n    Po, Po, Po, Po, Po, Po, Po, Pd, Po, Po, Pd, Po, Pi, Pf, Po, Po,\n/* DATA_BLOCK: -- 0x13D0..0x13DF -- */\n    Pi, Pf, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Po, Po, Po, Po, Po, Lm,\n/* DATA_BLOCK: -- 0x13E0..0x13EF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Pd, Pd, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x13F0..0x13FF -- */\n    Pd, Po, Ps, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1400..0x140F -- */\n    So, So, Po, Po, Po, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Pd, Cn, Cn,\n/* DATA_BLOCK: -- 0x1410..0x141F -- */\n    So, So, So, So, So, So, So, So, So, So, Cn, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1420..0x142F -- */\n    So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1430..0x143F -- */\n    So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1440..0x144F -- */\n    Zs, Po, Po, Po, So, Lm, Lo, Nl, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe,\n/* DATA_BLOCK: -- 0x1450..0x145F -- */\n    Ps, Pe, So, So, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Pd, Ps, Pe, Pe,\n/* DATA_BLOCK: -- 0x1460..0x146F -- */\n    So, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Mn, Mn, Mn, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x1470..0x147F -- */\n    Pd, Lm, Lm, Lm, Lm, Lm, So, So, Nl, Nl, Nl, Lm, Lo, Po, So, So,\n/* DATA_BLOCK: -- 0x1480..0x148F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Mn, Sk, Sk, Lm, Lm, Lo,\n/* DATA_BLOCK: -- 0x1490..0x149F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Po, Lm, Lm, Lm, Lo,\n/* DATA_BLOCK: -- 0x14A0..0x14AF -- */\n    Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x14B0..0x14BF -- */\n    So, So, No, No, No, No, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x14C0..0x14CF -- */\n    So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, So,\n/* DATA_BLOCK: -- 0x14D0..0x14DF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, So, So, Cn,\n/* DATA_BLOCK: -- 0x14E0..0x14EF -- */\n    No, No, No, No, No, No, No, No, No, No, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x14F0..0x14FF -- */\n    So, So, So, So, So, So, So, So, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1500..0x150F -- */\n    So, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1510..0x151F -- */\n    Lo, Lo, Lo, Lo, Lo, Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1520..0x152F -- */\n    So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1530..0x153F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1540..0x154F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Lo, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1550..0x155F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lo, Mn,\n/* DATA_BLOCK: -- 0x1560..0x156F -- */\n    Me, Me, Me, Po, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po, Lm,\n/* DATA_BLOCK: -- 0x1570..0x157F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lm, Lm, Mn, Mn,\n/* DATA_BLOCK: -- 0x1580..0x158F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl,\n/* DATA_BLOCK: -- 0x1590..0x159F -- */\n    Mn, Mn, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x15A0..0x15AF -- */\n    Sk, Sk, Sk, Sk, Sk, Sk, Sk, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x15B0..0x15BF -- */\n    Sk, Sk, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x15C0..0x15CF -- */\n    Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x15D0..0x15DF -- */\n    Lm, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Lu, Ll,\n/* DATA_BLOCK: -- 0x15E0..0x15EF -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lm, Sk, Sk, Lu, Ll, Lu, Ll, Lo,\n/* DATA_BLOCK: -- 0x15F0..0x15FF -- */\n    Lu, Ll, Lu, Ll, Ll, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x1600..0x160F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Lu, Lu, Lu, Lu, Ll,\n/* DATA_BLOCK: -- 0x1610..0x161F -- */\n    Lu, Lu, Lu, Lu, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x1620..0x162F -- */\n    Lu, Ll, Lu, Ll, Lu, Lu, Lu, Lu, Ll, Lu, Ll, Lu, Lu, Ll, Lu, Ll,\n/* DATA_BLOCK: -- 0x1630..0x163F -- */\n    Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Ll, Lu, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1640..0x164F -- */\n    Cn, Lm, Lm, Lm, Lm, Lu, Ll, Lo, Lm, Lm, Ll, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1650..0x165F -- */\n    Lo, Lo, Mn, Lo, Lo, Lo, Mn, Lo, Lo, Lo, Lo, Mn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1660..0x166F -- */\n    Lo, Lo, Lo, Mc, Mc, Mn, Mn, Mc, So, So, So, So, Mn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1670..0x167F -- */\n    No, No, No, No, No, No, So, So, Sc, So, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1680..0x168F -- */\n    Lo, Lo, Lo, Lo, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1690..0x169F -- */\n    Mc, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x16A0..0x16AF -- */\n    Lo, Lo, Lo, Lo, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x16B0..0x16BF -- */\n    Mc, Mc, Mc, Mc, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po, Po,\n/* DATA_BLOCK: -- 0x16C0..0x16CF -- */\n    Mn, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Po, Po, Po, Lo, Po, Lo, Lo, Mn,\n/* DATA_BLOCK: -- 0x16D0..0x16DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po, Po,\n/* DATA_BLOCK: -- 0x16E0..0x16EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x16F0..0x16FF -- */\n    Mn, Mn, Mc, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x1700..0x170F -- */\n    Lo, Lo, Lo, Mn, Mc, Mc, Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x1710..0x171F -- */\n    Mc, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn, Lm,\n/* DATA_BLOCK: -- 0x1720..0x172F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Po, Po,\n/* DATA_BLOCK: -- 0x1730..0x173F -- */\n    Lo, Lo, Lo, Lo, Lo, Mn, Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1740..0x174F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Lo, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x1750..0x175F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mc,\n/* DATA_BLOCK: -- 0x1760..0x176F -- */\n    Mc, Mn, Mn, Mc, Mc, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1770..0x177F -- */\n    Lo, Lo, Lo, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mc, Cn, Cn,\n/* DATA_BLOCK: -- 0x1780..0x178F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1790..0x179F -- */\n    Lm, Lo, Lo, Lo, Lo, Lo, Lo, So, So, So, Lo, Mc, Mn, Mc, Lo, Lo,\n/* DATA_BLOCK: -- 0x17A0..0x17AF -- */\n    Mn, Lo, Mn, Mn, Mn, Lo, Lo, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Mn, Mn,\n/* DATA_BLOCK: -- 0x17B0..0x17BF -- */\n    Lo, Mn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x17C0..0x17CF -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lm, Po, Po,\n/* DATA_BLOCK: -- 0x17D0..0x17DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mc, Mn, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x17E0..0x17EF -- */\n    Po, Po, Lo, Lm, Lm, Mc, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x17F0..0x17FF -- */\n    Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x1800..0x180F -- */\n    Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1810..0x181F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Sk, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x1820..0x182F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lm, Sk, Sk, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1830..0x183F -- */\n    Lo, Lo, Lo, Mc, Mc, Mn, Mc, Mc, Mn, Mc, Mc, Po, Mc, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1840..0x184F -- */\n    Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1850..0x185F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1860..0x186F -- */\n    Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs, Cs,\n/* DATA_BLOCK: -- 0x1870..0x187F -- */\n    Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co,\n/* DATA_BLOCK: -- 0x1880..0x188F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1890..0x189F -- */\n    Cn, Cn, Cn, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn, Lo, Mn, Lo,\n/* DATA_BLOCK: -- 0x18A0..0x18AF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Sm, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x18B0..0x18BF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Cn,\n/* DATA_BLOCK: -- 0x18C0..0x18CF -- */\n    Lo, Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x18D0..0x18DF -- */\n    Lo, Lo, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x18E0..0x18EF -- */\n    Sk, Sk, Sk, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x18F0..0x18FF -- */\n    So, So, So, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1900..0x190F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Pe, Ps,\n/* DATA_BLOCK: -- 0x1910..0x191F -- */\n    So, So, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1920..0x192F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1930..0x193F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Sc, So, So, So,\n/* DATA_BLOCK: -- 0x1940..0x194F -- */\n    Po, Po, Po, Po, Po, Po, Po, Ps, Pe, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1950..0x195F -- */\n    Po, Pd, Pd, Pc, Pc, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps, Pe, Ps,\n/* DATA_BLOCK: -- 0x1960..0x196F -- */\n    Pe, Ps, Pe, Ps, Pe, Po, Po, Ps, Pe, Po, Po, Po, Po, Pc, Pc, Pc,\n/* DATA_BLOCK: -- 0x1970..0x197F -- */\n    Po, Po, Po, Cn, Po, Po, Po, Po, Pd, Ps, Pe, Ps, Pe, Ps, Pe, Po,\n/* DATA_BLOCK: -- 0x1980..0x198F -- */\n    Po, Po, Sm, Pd, Sm, Sm, Sm, Cn, Po, Sc, Po, Po, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1990..0x199F -- */\n    Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x19A0..0x19AF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cf,\n/* DATA_BLOCK: -- 0x19B0..0x19BF -- */\n    Cn, Po, Po, Po, Sc, Po, Po, Po, Ps, Pe, Po, Sm, Po, Pd, Po, Po,\n/* DATA_BLOCK: -- 0x19C0..0x19CF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ps, Sm, Pe, Sm, Ps,\n/* DATA_BLOCK: -- 0x19D0..0x19DF -- */\n    Pe, Po, Ps, Pe, Po, Po, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x19E0..0x19EF -- */\n    Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x19F0..0x19FF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Lm,\n/* DATA_BLOCK: -- 0x1A00..0x1A0F -- */\n    Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1A10..0x1A1F -- */\n    Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1A20..0x1A2F -- */\n    Sc, Sc, Sm, Sk, So, Sc, Sc, Cn, So, Sm, Sm, Sm, Sm, So, So, Cn,\n/* DATA_BLOCK: -- 0x1A30..0x1A3F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cf, Cf, Cf, So, So, Cn, Cn,\n/* DATA_BLOCK: -- 0x1A40..0x1A4F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1A50..0x1A5F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x1A60..0x1A6F -- */\n    Po, Po, Po, Cn, Cn, Cn, Cn, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1A70..0x1A7F -- */\n    No, No, No, No, Cn, Cn, Cn, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1A80..0x1A8F -- */\n    Nl, Nl, Nl, Nl, Nl, No, No, No, No, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x1A90..0x1A9F -- */\n    So, So, So, So, So, So, So, So, So, So, No, No, So, So, So, Cn,\n/* DATA_BLOCK: -- 0x1AA0..0x1AAF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1AB0..0x1ABF -- */\n    So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1AC0..0x1ACF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1AD0..0x1ADF -- */\n    Mn, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1AE0..0x1AEF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1AF0..0x1AFF -- */\n    No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1B00..0x1B0F -- */\n    Lo, Nl, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Nl, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1B10..0x1B1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1B20..0x1B2F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Po,\n/* DATA_BLOCK: -- 0x1B30..0x1B3F -- */\n    Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1B40..0x1B4F -- */\n    Po, Nl, Nl, Nl, Nl, Nl, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1B50..0x1B5F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x1B60..0x1B6F -- */\n    Lu, Lu, Lu, Lu, Cn, Cn, Cn, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x1B70..0x1B7F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1B80..0x1B8F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1B90..0x1B9F -- */\n    Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x1BA0..0x1BAF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x1BB0..0x1BBF -- */\n    Lu, Lu, Lu, Cn, Lu, Lu, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x1BC0..0x1BCF -- */\n    Ll, Ll, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x1BD0..0x1BDF -- */\n    Ll, Ll, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Ll, Ll, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1BE0..0x1BEF -- */\n    Lm, Lm, Lm, Lm, Lm, Lm, Cn, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x1BF0..0x1BFF -- */\n    Lm, Cn, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1C00..0x1C0F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1C10..0x1C1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Cn, Cn, Lo, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x1C20..0x1C2F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Po, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1C30..0x1C3F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, So, So, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1C40..0x1C4F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1C50..0x1C5F -- */\n    Lo, Lo, Lo, Cn, Lo, Lo, Cn, Cn, Cn, Cn, Cn, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1C60..0x1C6F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, No, No, No, No, No, No, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x1C70..0x1C7F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x1C80..0x1C8F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, No, No, Lo, Lo,\n/* DATA_BLOCK: -- 0x1C90..0x1C9F -- */\n    Cn, Cn, No, No, No, No, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1CA0..0x1CAF -- */\n    Lo, Mn, Mn, Mn, Cn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x1CB0..0x1CBF -- */\n    Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1CC0..0x1CCF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x1CD0..0x1CDF -- */\n    No, No, No, No, No, No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1CE0..0x1CEF -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1CF0..0x1CFF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, No, No, Po,\n/* DATA_BLOCK: -- 0x1D00..0x1D0F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, No, No, No,\n/* DATA_BLOCK: -- 0x1D10..0x1D1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, So, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1D20..0x1D2F -- */\n    Lo, Lo, Lo, Lo, Lo, Mn, Mn, Cn, Cn, Cn, Cn, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1D30..0x1D3F -- */\n    Po, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1D40..0x1D4F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1D50..0x1D5F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1D60..0x1D6F -- */\n    Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1D70..0x1D7F -- */\n    Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po, Po, Po, Po, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1D80..0x1D8F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1D90..0x1D9F -- */\n    Lu, Lu, Lu, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1DA0..0x1DAF -- */\n    Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn, Cn, Cn, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1DB0..0x1DBF -- */\n    Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1DC0..0x1DCF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Lo, Lo, Lo, Lm, Lo,\n/* DATA_BLOCK: -- 0x1DD0..0x1DDF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn, Cn, Mn, Mn, Mn, Mn, Mn, Pd, Lm,\n/* DATA_BLOCK: -- 0x1DE0..0x1DEF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Sm, Sm,\n/* DATA_BLOCK: -- 0x1DF0..0x1DFF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, Cn,\n/* DATA_BLOCK: -- 0x1E00..0x1E0F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Mn, Mn, Pd, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E10..0x1E1F -- */\n    Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E20..0x1E2F -- */\n    Cn, Cn, Lo, Lo, Lo, Lm, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E30..0x1E3F -- */\n    Po, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E40..0x1E4F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x1E50..0x1E5F -- */\n    No, No, No, No, No, No, No, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E60..0x1E6F -- */\n    Mn, No, No, No, No, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E70..0x1E7F -- */\n    Lo, Lo, Mn, Mn, Mn, Mn, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E80..0x1E8F -- */\n    Lo, Lo, Lo, Lo, Lo, No, No, No, No, No, No, No, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1E90..0x1E9F -- */\n    Mc, Mn, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1EA0..0x1EAF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x1EB0..0x1EBF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po, Po, Po, Po, Po, Po, Po, Cn, Cn,\n/* DATA_BLOCK: -- 0x1EC0..0x1ECF -- */\n    No, No, No, No, No, No, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x1ED0..0x1EDF -- */\n    Mn, Lo, Lo, Mn, Mn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x1EE0..0x1EEF -- */\n    Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mn, Po, Po, Cf, Po, Po,\n/* DATA_BLOCK: -- 0x1EF0..0x1EFF -- */\n    Po, Po, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cf, Cn, Cn,\n/* DATA_BLOCK: -- 0x1F00..0x1F0F -- */\n    Mn, Mn, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x1F10..0x1F1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x1F20..0x1F2F -- */\n    Mn, Mn, Mn, Mn, Mn, Cn, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x1F30..0x1F3F -- */\n    Po, Po, Po, Po, Lo, Mc, Mc, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1F40..0x1F4F -- */\n    Lo, Lo, Lo, Mn, Po, Po, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1F50..0x1F5F -- */\n    Lo, Lo, Lo, Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc,\n/* DATA_BLOCK: -- 0x1F60..0x1F6F -- */\n    Mc, Lo, Lo, Lo, Lo, Po, Po, Po, Po, Mn, Mn, Mn, Mn, Po, Mc, Mn,\n/* DATA_BLOCK: -- 0x1F70..0x1F7F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Lo, Po, Lo, Po, Po, Po,\n/* DATA_BLOCK: -- 0x1F80..0x1F8F -- */\n    Cn, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x1F90..0x1F9F -- */\n    No, No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1FA0..0x1FAF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mc, Mc, Mc, Mn,\n/* DATA_BLOCK: -- 0x1FB0..0x1FBF -- */\n    Mn, Mn, Mc, Mc, Mn, Mc, Mn, Mn, Po, Po, Po, Po, Po, Po, Mn, Lo,\n/* DATA_BLOCK: -- 0x1FC0..0x1FCF -- */\n    Lo, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x1FD0..0x1FDF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x1FE0..0x1FEF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x1FF0..0x1FFF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2000..0x200F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn,\n/* DATA_BLOCK: -- 0x2010..0x201F -- */\n    Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2020..0x202F -- */\n    Mn, Mn, Mc, Mc, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x2030..0x203F -- */\n    Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Mn, Mn, Lo, Mc, Mc,\n/* DATA_BLOCK: -- 0x2040..0x204F -- */\n    Mn, Mc, Mc, Mc, Mc, Cn, Cn, Mc, Mc, Cn, Cn, Mc, Mc, Mc, Cn, Cn,\n/* DATA_BLOCK: -- 0x2050..0x205F -- */\n    Lo, Cn, Cn, Cn, Cn, Cn, Cn, Mc, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2060..0x206F -- */\n    Lo, Lo, Mc, Mc, Cn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2070..0x207F -- */\n    Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2080..0x208F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Cn, Cn, Lo, Cn,\n/* DATA_BLOCK: -- 0x2090..0x209F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x20A0..0x20AF -- */\n    Mn, Cn, Mc, Cn, Cn, Mc, Cn, Mc, Mc, Mc, Mc, Cn, Mc, Mc, Mn, Mc,\n/* DATA_BLOCK: -- 0x20B0..0x20BF -- */\n    Mn, Lo, Mn, Lo, Po, Po, Cn, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x20C0..0x20CF -- */\n    Cn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x20D0..0x20DF -- */\n    Lo, Lo, Lo, Lo, Lo, Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x20E0..0x20EF -- */\n    Mc, Mc, Mn, Mn, Mn, Mc, Mn, Lo, Lo, Lo, Lo, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x20F0..0x20FF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Po, Po, Cn, Po, Mn, Lo,\n/* DATA_BLOCK: -- 0x2100..0x210F -- */\n    Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mc, Mc, Mc, Mc, Mn,\n/* DATA_BLOCK: -- 0x2110..0x211F -- */\n    Mn, Mc, Mn, Mn, Lo, Lo, Po, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2120..0x212F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mc,\n/* DATA_BLOCK: -- 0x2130..0x213F -- */\n    Mc, Mc, Mn, Mn, Mn, Mn, Cn, Cn, Mc, Mc, Mc, Mc, Mn, Mn, Mc, Mn,\n/* DATA_BLOCK: -- 0x2140..0x214F -- */\n    Mn, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x2150..0x215F -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Lo, Lo, Lo, Lo, Mn, Mn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2160..0x216F -- */\n    Mc, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mc, Mn,\n/* DATA_BLOCK: -- 0x2170..0x217F -- */\n    Mn, Po, Po, Po, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2180..0x218F -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2190..0x219F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mc, Mn, Mc, Mc,\n/* DATA_BLOCK: -- 0x21A0..0x21AF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Lo, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x21B0..0x21BF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd,\n/* DATA_BLOCK: -- 0x21C0..0x21CF -- */\n    Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x21D0..0x21DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Mn, Mc, Mn,\n/* DATA_BLOCK: -- 0x21E0..0x21EF -- */\n    Mc, Mc, Mn, Mn, Mn, Mn, Mc, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x21F0..0x21FF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, No, No, Po, Po, Po, So,\n/* DATA_BLOCK: -- 0x2200..0x220F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mn, Po, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2210..0x221F -- */\n    No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x2220..0x222F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Cn, Cn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2230..0x223F -- */\n    Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2240..0x224F -- */\n    Mc, Mc, Mc, Mc, Mc, Mc, Cn, Mc, Mc, Cn, Cn, Mn, Mn, Mc, Mn, Lo,\n/* DATA_BLOCK: -- 0x2250..0x225F -- */\n    Mc, Lo, Mc, Mn, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2260..0x226F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2270..0x227F -- */\n    Lo, Mc, Mc, Mc, Mn, Mn, Mn, Mn, Cn, Cn, Mn, Mn, Mc, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x2280..0x228F -- */\n    Mn, Lo, Po, Lo, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2290..0x229F -- */\n    Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x22A0..0x22AF -- */\n    Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Lo, Mn, Mn, Mn, Mn, Po,\n/* DATA_BLOCK: -- 0x22B0..0x22BF -- */\n    Po, Po, Po, Po, Po, Po, Po, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x22C0..0x22CF -- */\n    Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc, Mn, Mn, Mn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x22D0..0x22DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x22E0..0x22EF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn, Mn, Po, Po, Po, Lo, Po, Po,\n/* DATA_BLOCK: -- 0x22F0..0x22FF -- */\n    Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2300..0x230F -- */\n    Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2310..0x231F -- */\n    Mn, Mc, Mn, Mn, Mn, Mc, Mn, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2320..0x232F -- */\n    Lo, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2330..0x233F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mn,\n/* DATA_BLOCK: -- 0x2340..0x234F -- */\n    Lo, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2350..0x235F -- */\n    Po, Po, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2360..0x236F -- */\n    Cn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2370..0x237F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Mc, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2380..0x238F -- */\n    Mn, Mc, Mn, Mn, Mc, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2390..0x239F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x23A0..0x23AF -- */\n    Lo, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Mn, Cn, Mn, Mn, Cn, Mn,\n/* DATA_BLOCK: -- 0x23B0..0x23BF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Lo, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x23C0..0x23CF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x23D0..0x23DF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mc, Mc, Mc, Mc, Mc, Cn,\n/* DATA_BLOCK: -- 0x23E0..0x23EF -- */\n    Mn, Mn, Cn, Mc, Mc, Mn, Mc, Mn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x23F0..0x23FF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Lo, Lo, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2400..0x240F -- */\n    Lo, Lo, Lo, Mn, Mn, Mc, Mc, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2410..0x241F -- */\n    Mn, Mn, Lo, Mc, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2420..0x242F -- */\n    Lo, Lo, Lo, Lo, Mc, Mc, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Mc, Mc,\n/* DATA_BLOCK: -- 0x2430..0x243F -- */\n    Mn, Mc, Mn, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po, Po,\n/* DATA_BLOCK: -- 0x2440..0x244F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Mn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2450..0x245F -- */\n    No, No, No, No, No, So, So, So, So, So, So, So, So, Sc, Sc, Sc,\n/* DATA_BLOCK: -- 0x2460..0x246F -- */\n    Sc, So, So, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x2470..0x247F -- */\n    So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x2480..0x248F -- */\n    Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Cn,\n/* DATA_BLOCK: -- 0x2490..0x249F -- */\n    Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x24A0..0x24AF -- */\n    Lo, Po, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x24B0..0x24BF -- */\n    Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf,\n/* DATA_BLOCK: -- 0x24C0..0x24CF -- */\n    Mn, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x24D0..0x24DF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x24E0..0x24EF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn,\n/* DATA_BLOCK: -- 0x24F0..0x24FF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mc, Mc, Mc, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2500..0x250F -- */\n    Mn, Mn, Mn, Mn, Mn, Po, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2510..0x251F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Po, Po, Po, Po, Po, So, So, So, So,\n/* DATA_BLOCK: -- 0x2520..0x252F -- */\n    Lm, Lm, Lm, Lm, Po, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2530..0x253F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x2540..0x254F -- */\n    No, No, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2550..0x255F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2560..0x256F -- */\n    Lm, Lm, Lm, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2570..0x257F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Lm, Po, Po, Po,\n/* DATA_BLOCK: -- 0x2580..0x258F -- */\n    No, No, No, No, No, No, No, Po, Po, Po, Po, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2590..0x259F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Cn, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x25A0..0x25AF -- */\n    Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x25B0..0x25BF -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x25C0..0x25CF -- */\n    Lo, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x25D0..0x25DF -- */\n    Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x25E0..0x25EF -- */\n    Mc, Mc, Mc, Mc, Mc, Mc, Mc, Mc, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x25F0..0x25FF -- */\n    Mn, Mn, Mn, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm,\n/* DATA_BLOCK: -- 0x2600..0x260F -- */\n    Lm, Lm, Po, Lm, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2610..0x261F -- */\n    Mc, Mc, Lm, Lm, Nl, Nl, Nl, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2620..0x262F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo,\n/* DATA_BLOCK: -- 0x2630..0x263F -- */\n    Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2640..0x264F -- */\n    Lm, Lm, Lm, Lm, Cn, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Cn, Lm, Lm, Cn,\n/* DATA_BLOCK: -- 0x2650..0x265F -- */\n    Cn, Cn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2660..0x266F -- */\n    Lo, Lo, Lo, Cn, Cn, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2670..0x267F -- */\n    Cn, Cn, Cn, Cn, Lo, Lo, Lo, Lo, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2680..0x268F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Cn, So, Mn, Mn, Po,\n/* DATA_BLOCK: -- 0x2690..0x269F -- */\n    Cf, Cf, Cf, Cf, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x26A0..0x26AF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, So, So, So, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x26B0..0x26BF -- */\n    So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x26C0..0x26CF -- */\n    Sm, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x26D0..0x26DF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x26E0..0x26EF -- */\n    So, So, So, So, So, So, So, Cn, Cn, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x26F0..0x26FF -- */\n    So, So, So, So, So, Mc, Mc, Mn, Mn, Mn, So, So, So, Mc, Mc, Mc,\n/* DATA_BLOCK: -- 0x2700..0x270F -- */\n    Mc, Mc, Mc, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Cf, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2710..0x271F -- */\n    Mn, Mn, Mn, So, So, Mn, Mn, Mn, Mn, Mn, Mn, Mn, So, So, So, So,\n/* DATA_BLOCK: -- 0x2720..0x272F -- */\n    So, So, So, So, So, So, So, So, So, So, Mn, Mn, Mn, Mn, So, So,\n/* DATA_BLOCK: -- 0x2730..0x273F -- */\n    So, So, Mn, Mn, Mn, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2740..0x274F -- */\n    No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2750..0x275F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2760..0x276F -- */\n    Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x2770..0x277F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll,\n/* DATA_BLOCK: -- 0x2780..0x278F -- */\n    Ll, Ll, Ll, Ll, Ll, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2790..0x279F -- */\n    Lu, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x27A0..0x27AF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Cn, Lu, Lu,\n/* DATA_BLOCK: -- 0x27B0..0x27BF -- */\n    Cn, Cn, Lu, Cn, Cn, Lu, Lu, Cn, Cn, Lu, Lu, Lu, Lu, Cn, Lu, Lu,\n/* DATA_BLOCK: -- 0x27C0..0x27CF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll, Ll, Ll, Cn, Ll, Cn, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x27D0..0x27DF -- */\n    Ll, Ll, Ll, Ll, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x27E0..0x27EF -- */\n    Ll, Ll, Ll, Ll, Lu, Lu, Cn, Lu, Lu, Lu, Lu, Cn, Cn, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x27F0..0x27FF -- */\n    Lu, Lu, Lu, Lu, Lu, Cn, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Cn, Ll, Ll,\n/* DATA_BLOCK: -- 0x2800..0x280F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Cn, Lu, Lu, Lu, Lu, Cn,\n/* DATA_BLOCK: -- 0x2810..0x281F -- */\n    Lu, Lu, Lu, Lu, Lu, Cn, Lu, Cn, Cn, Cn, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x2820..0x282F -- */\n    Lu, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2830..0x283F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x2840..0x284F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2850..0x285F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x2860..0x286F -- */\n    Lu, Sm, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2870..0x287F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Sm, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2880..0x288F -- */\n    Ll, Ll, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x2890..0x289F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Sm, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x28A0..0x28AF -- */\n    Ll, Ll, Ll, Ll, Ll, Sm, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x28B0..0x28BF -- */\n    Lu, Lu, Lu, Lu, Lu, Sm, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x28C0..0x28CF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Sm,\n/* DATA_BLOCK: -- 0x28D0..0x28DF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu,\n/* DATA_BLOCK: -- 0x28E0..0x28EF -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Sm,\n/* DATA_BLOCK: -- 0x28F0..0x28FF -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Sm, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2900..0x290F -- */\n    Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Lu, Sm, Ll, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2910..0x291F -- */\n    Ll, Ll, Ll, Sm, Ll, Ll, Ll, Ll, Ll, Ll, Lu, Ll, Cn, Cn, Nd, Nd,\n/* DATA_BLOCK: -- 0x2920..0x292F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, So, So, So, So, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2930..0x293F -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, So, So, So,\n/* DATA_BLOCK: -- 0x2940..0x294F -- */\n    So, So, So, So, So, Mn, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x2950..0x295F -- */\n    So, So, So, So, Mn, So, So, Po, Po, Po, Po, Po, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2960..0x296F -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2970..0x297F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Lo, Ll, Ll, Ll, Ll, Ll,\n/* DATA_BLOCK: -- 0x2980..0x298F -- */\n    Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Ll, Cn,\n/* DATA_BLOCK: -- 0x2990..0x299F -- */\n    Cn, Cn, Cn, Cn, Cn, Ll, Ll, Ll, Ll, Ll, Ll, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x29A0..0x29AF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x29B0..0x29BF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Mn, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x29C0..0x29CF -- */\n    Mn, Mn, Cn, Mn, Mn, Cn, Mn, Mn, Mn, Mn, Mn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x29D0..0x29DF -- */\n    Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Cn, Cn,\n/* DATA_BLOCK: -- 0x29E0..0x29EF -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Mn,\n/* DATA_BLOCK: -- 0x29F0..0x29FF -- */\n    Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lm, Lm, Lm, Lm, Lm, Lm, Lm, Cn, Cn,\n/* DATA_BLOCK: -- 0x2A00..0x2A0F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Lo, So,\n/* DATA_BLOCK: -- 0x2A10..0x2A1F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Cn,\n/* DATA_BLOCK: -- 0x2A20..0x2A2F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2A30..0x2A3F -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Cn, Sc,\n/* DATA_BLOCK: -- 0x2A40..0x2A4F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lm, Mn, Mn, Mn, Mn,\n/* DATA_BLOCK: -- 0x2A50..0x2A5F -- */\n    Lo, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Cn, Cn, Cn, Cn, Po,\n/* DATA_BLOCK: -- 0x2A60..0x2A6F -- */\n    Lo, Lo, Lo, Mn, Lo, Lo, Mn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Mn, Mn,\n/* DATA_BLOCK: -- 0x2A70..0x2A7F -- */\n    Lo, Lo, Lo, Lo, Lo, Mn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Lo, Lm,\n/* DATA_BLOCK: -- 0x2A80..0x2A8F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Cn,\n/* DATA_BLOCK: -- 0x2A90..0x2A9F -- */\n    Lo, Lo, Lo, Lo, Lo, Cn, Cn, No, No, No, No, No, No, No, No, No,\n/* DATA_BLOCK: -- 0x2AA0..0x2AAF -- */\n    Ll, Ll, Ll, Ll, Mn, Mn, Mn, Mn, Mn, Mn, Mn, Lm, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2AB0..0x2ABF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, So, No, No, No,\n/* DATA_BLOCK: -- 0x2AC0..0x2ACF -- */\n    Sc, No, No, No, No, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2AD0..0x2ADF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, No, So, No,\n/* DATA_BLOCK: -- 0x2AE0..0x2AEF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, No, Cn, Cn,\n/* DATA_BLOCK: -- 0x2AF0..0x2AFF -- */\n    Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B00..0x2B0F -- */\n    Cn, Lo, Lo, Cn, Lo, Cn, Cn, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B10..0x2B1F -- */\n    Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Cn, Lo, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2B20..0x2B2F -- */\n    Cn, Cn, Lo, Cn, Cn, Cn, Cn, Lo, Cn, Lo, Cn, Lo, Cn, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B30..0x2B3F -- */\n    Cn, Lo, Lo, Cn, Lo, Cn, Cn, Lo, Cn, Lo, Cn, Lo, Cn, Lo, Cn, Lo,\n/* DATA_BLOCK: -- 0x2B40..0x2B4F -- */\n    Cn, Lo, Lo, Cn, Lo, Cn, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B50..0x2B5F -- */\n    Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Cn, Lo, Cn,\n/* DATA_BLOCK: -- 0x2B60..0x2B6F -- */\n    Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B70..0x2B7F -- */\n    Cn, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo, Cn, Lo, Lo, Lo, Lo, Lo,\n/* DATA_BLOCK: -- 0x2B80..0x2B8F -- */\n    Sm, Sm, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2B90..0x2B9F -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2BA0..0x2BAF -- */\n    Cn, So, So, So, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x2BB0..0x2BBF -- */\n    No, No, No, No, No, No, No, No, No, No, No, No, No, So, So, So,\n/* DATA_BLOCK: -- 0x2BC0..0x2BCF -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, So, Cn, Cn,\n/* DATA_BLOCK: -- 0x2BD0..0x2BDF -- */\n    Cn, Cn, Cn, Cn, Cn, Cn, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x2BE0..0x2BEF -- */\n    So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2BF0..0x2BFF -- */\n    So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2C00..0x2C0F -- */\n    So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2C10..0x2C1F -- */\n    So, So, So, So, So, So, So, So, So, So, So, Sk, Sk, Sk, Sk, Sk,\n/* DATA_BLOCK: -- 0x2C20..0x2C2F -- */\n    So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, So, So, So, So,\n/* DATA_BLOCK: -- 0x2C30..0x2C3F -- */\n    So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2C40..0x2C4F -- */\n    Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Sm, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2C50..0x2C5F -- */\n    So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, So, So,\n/* DATA_BLOCK: -- 0x2C60..0x2C6F -- */\n    So, So, So, So, So, So, So, Cn, So, Cn, Cn, Cn, Cn, So, So, So,\n/* DATA_BLOCK: -- 0x2C70..0x2C7F -- */\n    So, So, So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, So,\n/* DATA_BLOCK: -- 0x2C80..0x2C8F -- */\n    So, So, So, So, So, So, So, So, So, So, So, Cn, Cn, Cn, Cn, So,\n/* DATA_BLOCK: -- 0x2C90..0x2C9F -- */\n    So, So, So, Cn, So, So, So, So, So, So, So, So, So, So, So, So,\n/* DATA_BLOCK: -- 0x2CA0..0x2CAF -- */\n    Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, Nd, So, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2CB0..0x2CBF -- */\n    Cn, Cf, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn, Cn,\n/* DATA_BLOCK: -- 0x2CC0..0x2CCF -- */\n    Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Co, Cn, Cn\n};\n\nstatic const SBUInt16 MainGeneralCategoryIndexes[4288] = {\n/* INDEX_BLOCK: -- 0x0000..0x003F -- */\n    0x0000, 0x0000, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0000, 0x0000, 0x0070, 0x0080,\n    0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00D0, 0x00D0, 0x00E0, 0x00F0, 0x00D0, 0x00D0, 0x0100,\n    0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x00D0, 0x0170, 0x00D0, 0x00D0, 0x00D0, 0x0180,\n    0x0190, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x01A0, 0x00B0, 0x01B0, 0x01C0, 0x01D0, 0x01E0, 0x01F0,\n    0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0210, 0x0220, 0x0230, 0x0240, 0x00B0,\n    0x0250, 0x0260, 0x00D0, 0x0270,\n/* INDEX_BLOCK: -- 0x0040..0x007F -- */\n    0x0090, 0x0090, 0x0090, 0x00B0, 0x00B0, 0x00B0, 0x00D0, 0x00D0, 0x0280, 0x00D0, 0x00D0, 0x00D0,\n    0x0290, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x02A0, 0x0090, 0x02B0, 0x00B0, 0x00B0,\n    0x02C0, 0x02D0, 0x0200, 0x02E0, 0x02F0, 0x0300, 0x0310, 0x0320, 0x0330, 0x0340, 0x0300, 0x0300,\n    0x0350, 0x0200, 0x0360, 0x0370, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0380, 0x0390, 0x03A0,\n    0x03B0, 0x03C0, 0x0300, 0x0200, 0x03D0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x03E0, 0x03F0,\n    0x0400, 0x0300, 0x0410, 0x0420,\n/* INDEX_BLOCK: -- 0x0080..0x00BF -- */\n    0x0300, 0x0430, 0x0440, 0x0450, 0x0300, 0x0460, 0x0470, 0x0300, 0x0480, 0x0490, 0x0300, 0x0300,\n    0x04A0, 0x0200, 0x04B0, 0x0200, 0x04C0, 0x0300, 0x0300, 0x04D0, 0x04E0, 0x04F0, 0x0500, 0x0510,\n    0x0520, 0x0530, 0x0540, 0x0550, 0x0560, 0x0570, 0x0580, 0x0590, 0x05A0, 0x0530, 0x0540, 0x05B0,\n    0x05C0, 0x05D0, 0x05E0, 0x05F0, 0x0600, 0x0610, 0x0540, 0x0620, 0x0630, 0x0640, 0x0580, 0x0650,\n    0x0660, 0x0530, 0x0540, 0x0670, 0x0680, 0x0690, 0x0580, 0x06A0, 0x06B0, 0x06C0, 0x06D0, 0x06E0,\n    0x06F0, 0x0700, 0x05E0, 0x0710,\n/* INDEX_BLOCK: -- 0x00C0..0x00FF -- */\n    0x0720, 0x0730, 0x0540, 0x0740, 0x0750, 0x0760, 0x0580, 0x0770, 0x0780, 0x0730, 0x0540, 0x0790,\n    0x07A0, 0x07B0, 0x0580, 0x07C0, 0x07D0, 0x0730, 0x0300, 0x07E0, 0x07F0, 0x0800, 0x0580, 0x0810,\n    0x0820, 0x0830, 0x0300, 0x0840, 0x0850, 0x0860, 0x05E0, 0x0870, 0x0880, 0x0300, 0x0300, 0x0890,\n    0x08A0, 0x08B0, 0x08C0, 0x08C0, 0x08D0, 0x0300, 0x08E0, 0x08F0, 0x0900, 0x0910, 0x08C0, 0x08C0,\n    0x0920, 0x0930, 0x0940, 0x0950, 0x0960, 0x0300, 0x0970, 0x0980, 0x0990, 0x09A0, 0x0200, 0x09B0,\n    0x09C0, 0x09D0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0100..0x013F -- */\n    0x0300, 0x0300, 0x09E0, 0x09F0, 0x0A00, 0x0A10, 0x0A20, 0x0A30, 0x0A40, 0x0A50, 0x0090, 0x0090,\n    0x0A60, 0x00B0, 0x00B0, 0x0A70, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0A80, 0x0A90, 0x0300, 0x0300, 0x0A80, 0x0300, 0x0300, 0x0AA0, 0x0AB0, 0x0AC0, 0x0300, 0x0300,\n    0x0300, 0x0AB0, 0x0300, 0x0300, 0x0300, 0x0AD0, 0x0AE0, 0x0AF0, 0x0300, 0x0B00, 0x0090, 0x0090,\n    0x0090, 0x0090, 0x0090, 0x0B10,\n/* INDEX_BLOCK: -- 0x0140..0x017F -- */\n    0x0B20, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0B30, 0x0300, 0x0B40, 0x0B50, 0x0300, 0x0300, 0x0300, 0x0300, 0x0B60, 0x0B70,\n    0x0300, 0x0B80, 0x0300, 0x0B90, 0x0300, 0x0BA0, 0x0BB0, 0x0BC0, 0x0300, 0x0300, 0x0300, 0x0BD0,\n    0x0BE0, 0x0BF0, 0x0C00, 0x0C10,\n/* INDEX_BLOCK: -- 0x0180..0x01BF -- */\n    0x0C20, 0x0C00, 0x0300, 0x0300, 0x0C30, 0x0300, 0x0300, 0x0C40, 0x0C50, 0x0300, 0x0C60, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0C70, 0x0300, 0x0C80, 0x0C90, 0x0CA0, 0x0CB0, 0x0300, 0x0CC0, 0x0CD0,\n    0x0300, 0x0300, 0x0CE0, 0x0300, 0x0CF0, 0x0D00, 0x0D10, 0x0D10, 0x0300, 0x0D20, 0x0300, 0x0300,\n    0x0300, 0x0D30, 0x0D40, 0x0D50, 0x0C00, 0x0C00, 0x0D60, 0x0D70, 0x0200, 0x0D80, 0x0D90, 0x08C0,\n    0x0DA0, 0x0300, 0x0300, 0x0DB0, 0x0DC0, 0x0A00, 0x0DD0, 0x0DE0, 0x0DF0, 0x0300, 0x0E00, 0x0400,\n    0x0300, 0x0300, 0x0E10, 0x0E20,\n/* INDEX_BLOCK: -- 0x01C0..0x01FF -- */\n    0x0300, 0x0300, 0x0E30, 0x0E40, 0x0E50, 0x0400, 0x0300, 0x0E60, 0x0E70, 0x0090, 0x0090, 0x0E80,\n    0x0E90, 0x0EA0, 0x0EB0, 0x0EC0, 0x00B0, 0x00B0, 0x0ED0, 0x01B0, 0x01B0, 0x01B0, 0x0EE0, 0x0EF0,\n    0x00B0, 0x0F00, 0x01B0, 0x01B0, 0x0200, 0x0200, 0x0200, 0x0200, 0x00D0, 0x00D0, 0x00D0, 0x00D0,\n    0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x0F10, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0,\n    0x0F20, 0x0F30, 0x0F20, 0x0F20, 0x0F30, 0x0F40, 0x0F20, 0x0F50, 0x0F60, 0x0F60, 0x0F60, 0x0F70,\n    0x0F80, 0x0F90, 0x0FA0, 0x0FB0,\n/* INDEX_BLOCK: -- 0x0200..0x023F -- */\n    0x0FC0, 0x0FD0, 0x0FE0, 0x0FF0, 0x1000, 0x1010, 0x1020, 0x1030, 0x1040, 0x1050, 0x1060, 0x1060,\n    0x1070, 0x1080, 0x1090, 0x10A0, 0x10B0, 0x10C0, 0x10D0, 0x10E0, 0x10F0, 0x1100, 0x1110, 0x1110,\n    0x1120, 0x1130, 0x1140, 0x0D10, 0x1150, 0x1160, 0x0D10, 0x1170, 0x1180, 0x1180, 0x1180, 0x1180,\n    0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180,\n    0x1190, 0x0D10, 0x11A0, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x11B0, 0x0D10, 0x11C0, 0x1180, 0x11D0,\n    0x0D10, 0x11E0, 0x11F0, 0x0D10,\n/* INDEX_BLOCK: -- 0x0240..0x027F -- */\n    0x0D10, 0x0D10, 0x0B00, 0x08C0, 0x1200, 0x08C0, 0x1100, 0x1100, 0x1100, 0x1210, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x1220, 0x1100, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x1230, 0x1240, 0x0D10, 0x0D10, 0x1250, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x1260, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x1270, 0x1280, 0x1100, 0x1290, 0x0D10, 0x0D10,\n    0x12A0, 0x1180, 0x12B0, 0x1180,\n/* INDEX_BLOCK: -- 0x0280..0x02BF -- */\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180,\n    0x12C0, 0x12D0, 0x1180, 0x1180, 0x1180, 0x12E0, 0x1180, 0x12F0, 0x1180, 0x1180, 0x1180, 0x1180,\n    0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180, 0x1180,\n    0x0D10, 0x0D10, 0x0D10, 0x1180, 0x1300, 0x0D10, 0x0D10, 0x1310, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10,\n/* INDEX_BLOCK: -- 0x02C0..0x02FF -- */\n    0x0090, 0x0090, 0x0090, 0x00B0, 0x00B0, 0x00B0, 0x1320, 0x1330, 0x00D0, 0x00D0, 0x00D0, 0x00D0,\n    0x00D0, 0x00D0, 0x1340, 0x1350, 0x00B0, 0x00B0, 0x1360, 0x0300, 0x0300, 0x0300, 0x1370, 0x1380,\n    0x0300, 0x1390, 0x13A0, 0x13A0, 0x13A0, 0x13A0, 0x0200, 0x0200, 0x13B0, 0x13C0, 0x13D0, 0x13E0,\n    0x13F0, 0x1400, 0x08C0, 0x08C0, 0x0D10, 0x1410, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x1420,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x1430, 0x08C0, 0x0D10,\n/* INDEX_BLOCK: -- 0x0300..0x033F -- */\n    0x1440, 0x1450, 0x1460, 0x1470, 0x0880, 0x0300, 0x0300, 0x0300, 0x0300, 0x1480, 0x0B20, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x1490, 0x14A0, 0x0300, 0x0300, 0x0880, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0C80, 0x14B0, 0x0300, 0x0300, 0x0D10, 0x0D10, 0x14C0, 0x0300, 0x0D10, 0x14D0, 0x14E0, 0x0D10,\n    0x14F0, 0x1500, 0x0D10, 0x0D10, 0x14E0, 0x0D10, 0x0D10, 0x1500, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10,\n/* INDEX_BLOCK: -- 0x0340..0x037F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0380..0x03BF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x03C0..0x03FF -- */\n    0x0300, 0x1510, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0400..0x043F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0970, 0x0D10, 0x0D10, 0x0D10,\n    0x1520, 0x0300, 0x0300, 0x0E60, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x1530, 0x0300, 0x1540, 0x08C0,\n    0x00D0, 0x00D0, 0x1550, 0x1560, 0x00D0, 0x1570, 0x0300, 0x0300, 0x0300, 0x0300, 0x1580, 0x1590,\n    0x01F0, 0x15A0, 0x15B0, 0x15C0, 0x00D0, 0x00D0, 0x00D0, 0x15D0, 0x15E0, 0x15F0, 0x1600, 0x1610,\n    0x1620, 0x1630, 0x08C0, 0x1640,\n/* INDEX_BLOCK: -- 0x0440..0x047F -- */\n    0x1650, 0x0300, 0x1660, 0x1670, 0x0300, 0x0300, 0x0300, 0x1680, 0x1690, 0x0300, 0x0300, 0x16A0,\n    0x16B0, 0x0C00, 0x0200, 0x16C0, 0x0400, 0x0300, 0x16D0, 0x0300, 0x16E0, 0x16F0, 0x0300, 0x0970,\n    0x04C0, 0x0300, 0x0300, 0x1700, 0x1710, 0x1720, 0x1730, 0x1740, 0x0300, 0x0300, 0x1750, 0x1760,\n    0x1770, 0x1780, 0x0300, 0x1790, 0x0300, 0x0300, 0x0300, 0x17A0, 0x17B0, 0x17C0, 0x17D0, 0x17E0,\n    0x17F0, 0x1800, 0x13A0, 0x00B0, 0x00B0, 0x1810, 0x1820, 0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x0300, 0x0300, 0x1830, 0x0C00,\n/* INDEX_BLOCK: -- 0x0480..0x04BF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x1840, 0x0300,\n    0x1850, 0x0300, 0x0300, 0x0CE0,\n/* INDEX_BLOCK: -- 0x04C0..0x04FF -- */\n    0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860,\n    0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860,\n    0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860,\n    0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860,\n    0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860, 0x1860,\n    0x1860, 0x1860, 0x1860, 0x1860,\n/* INDEX_BLOCK: -- 0x0500..0x053F -- */\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870,\n/* INDEX_BLOCK: -- 0x0540..0x057F -- */\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0CC0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CF0, 0x08C0, 0x08C0,\n    0x1880, 0x1890, 0x18A0, 0x18B0, 0x18C0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x18D0,\n    0x18E0, 0x18F0, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0580..0x05BF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x1900, 0x0D10, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x1910, 0x0300, 0x0300, 0x1920, 0x08C0, 0x08C0, 0x1930, 0x0200, 0x1940, 0x0200, 0x1950,\n    0x1960, 0x1970, 0x1980, 0x1990, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x19A0,\n    0x19B0, 0x0020, 0x0030, 0x0040, 0x0050, 0x19C0, 0x19D0, 0x19E0, 0x0300, 0x19F0, 0x0300, 0x0C80,\n    0x1A00, 0x1A10, 0x1A20, 0x1A30,\n/* INDEX_BLOCK: -- 0x05C0..0x05FF -- */\n    0x1A40, 0x0300, 0x0AC0, 0x1A50, 0x0CC0, 0x0CC0, 0x08C0, 0x08C0, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0470, 0x1A60, 0x1100, 0x1100, 0x1A70, 0x1110, 0x1110, 0x1110, 0x1A80,\n    0x1A90, 0x1AA0, 0x1AB0, 0x08C0, 0x08C0, 0x0D10, 0x0D10, 0x1AC0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x0970, 0x0300, 0x0300, 0x0300, 0x0640, 0x1AD0, 0x1AE0,\n    0x0300, 0x0300, 0x1AF0, 0x0300, 0x1B00, 0x0300, 0x0300, 0x1B10, 0x0300, 0x1B20, 0x0300, 0x0300,\n    0x1B30, 0x1B40, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0600..0x063F -- */\n    0x0090, 0x0090, 0x1B50, 0x00B0, 0x00B0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CC0, 0x0C00, 0x0090,\n    0x0090, 0x1B60, 0x00B0, 0x1B70, 0x0300, 0x0300, 0x1B80, 0x0300, 0x0300, 0x0300, 0x1B90, 0x1BA0,\n    0x1BA0, 0x1BB0, 0x1BC0, 0x1BD0, 0x0300, 0x0300, 0x0300, 0x1840, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x1390, 0x0300, 0x0C70, 0x1B80, 0x08C0, 0x1BE0, 0x01B0, 0x01B0, 0x1BF0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0640..0x067F -- */\n    0x1C00, 0x0300, 0x0300, 0x1C10, 0x0300, 0x1C20, 0x0300, 0x1C30, 0x0300, 0x0C80, 0x1C40, 0x08C0,\n    0x08C0, 0x08C0, 0x0300, 0x1C50, 0x0300, 0x1C60, 0x0300, 0x1C70, 0x0300, 0x0CF0, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x0300, 0x1C80, 0x1100, 0x1C90, 0x1100, 0x1100, 0x1CA0, 0x1CB0, 0x0300, 0x1CC0,\n    0x1CD0, 0x1CE0, 0x0300, 0x1CF0, 0x0300, 0x1D00, 0x08C0, 0x08C0, 0x1D10, 0x0300, 0x1D20, 0x1D30,\n    0x0300, 0x0300, 0x0300, 0x1D40, 0x0300, 0x1D50, 0x0300, 0x1D60, 0x0300, 0x1D70, 0x1D80, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0680..0x06BF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0C40, 0x08C0, 0x08C0, 0x08C0, 0x0090, 0x0090, 0x0090, 0x1D90,\n    0x00B0, 0x00B0, 0x00B0, 0x1DA0, 0x0300, 0x0300, 0x1DB0, 0x0C00, 0x1DC0, 0x0090, 0x1DD0, 0x00B0,\n    0x1DE0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x1100, 0x1DF0, 0x0300, 0x0300, 0x1E00, 0x1E10, 0x1E20, 0x1E30, 0x08C0, 0x1E40,\n    0x0300, 0x1D00, 0x1E50, 0x0300, 0x03E0, 0x1E60, 0x08C0, 0x0300, 0x1E70, 0x08C0, 0x08C0, 0x0300,\n    0x1E80, 0x08C0, 0x0300, 0x1390,\n/* INDEX_BLOCK: -- 0x06C0..0x06FF -- */\n    0x1E90, 0x0300, 0x0300, 0x1EA0, 0x1EB0, 0x1C90, 0x1EC0, 0x1ED0, 0x0DF0, 0x0300, 0x0300, 0x1EE0,\n    0x1EF0, 0x0300, 0x0C40, 0x0C00, 0x1F00, 0x0300, 0x1F10, 0x1F20, 0x1F30, 0x0300, 0x0300, 0x1F40,\n    0x0DF0, 0x0300, 0x0300, 0x1F50, 0x1F60, 0x1F70, 0x1F80, 0x1F90, 0x0300, 0x0610, 0x1FA0, 0x1FB0,\n    0x1FC0, 0x08C0, 0x08C0, 0x08C0, 0x1FD0, 0x1FE0, 0x1FF0, 0x0300, 0x0300, 0x2000, 0x2010, 0x0C00,\n    0x2020, 0x0530, 0x0540, 0x2030, 0x2040, 0x2050, 0x2060, 0x2070, 0x2080, 0x0300, 0x0300, 0x2090,\n    0x20A0, 0x20B0, 0x20C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0700..0x073F -- */\n    0x0300, 0x0300, 0x0300, 0x20D0, 0x20E0, 0x20F0, 0x1E10, 0x08C0, 0x0300, 0x0300, 0x0300, 0x2100,\n    0x2110, 0x0C00, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x2120, 0x2130, 0x2140, 0x2150, 0x08C0, 0x08C0, 0x0300, 0x0300, 0x0300, 0x2160,\n    0x2170, 0x0C00, 0x2180, 0x08C0, 0x0300, 0x0300, 0x2190, 0x21A0, 0x0C00, 0x21B0, 0x21C0, 0x08C0,\n    0x0300, 0x21D0, 0x21E0, 0x21F0, 0x1390, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0740..0x077F -- */\n    0x0300, 0x0300, 0x1FA0, 0x2200, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0090, 0x0090,\n    0x00B0, 0x00B0, 0x0940, 0x2210, 0x2220, 0x2230, 0x0300, 0x2240, 0x2250, 0x0C00, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x2260, 0x0300, 0x0300, 0x2270, 0x2280, 0x08C0, 0x2290, 0x0300, 0x0300, 0x22A0,\n    0x22B0, 0x22C0, 0x0300, 0x0300, 0x22D0, 0x22E0, 0x22F0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0C40,\n    0x2300, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x2310, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x2320, 0x0C00,\n/* INDEX_BLOCK: -- 0x0780..0x07BF -- */\n    0x0540, 0x0300, 0x2120, 0x2330, 0x2340, 0x0940, 0x0AF0, 0x2350, 0x0300, 0x2360, 0x2370, 0x2380,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x2390, 0x0300, 0x0300, 0x23A0, 0x23B0, 0x0C00, 0x23C0, 0x0300,\n    0x23D0, 0x23E0, 0x0C00, 0x0300, 0x0300, 0x23F0, 0x0C00, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x2400,\n    0x2410, 0x0730, 0x0300, 0x2420, 0x2430, 0x2440, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0640,\n    0x1100, 0x2450, 0x2460, 0x2470,\n/* INDEX_BLOCK: -- 0x07C0..0x07FF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CF0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0800..0x083F -- */\n    0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x2480, 0x2490, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x1840, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0840..0x087F -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0880..0x08BF -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x24A0,\n/* INDEX_BLOCK: -- 0x08C0..0x08FF -- */\n    0x0300, 0x0300, 0x0300, 0x24B0, 0x24C0, 0x24D0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0900..0x093F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0470,\n/* INDEX_BLOCK: -- 0x0940..0x097F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x1390, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0980..0x09BF -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x24E0, 0x24F0, 0x0C00, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x09C0..0x09FF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0C40,\n    0x0300, 0x0C80, 0x1720, 0x0300, 0x0300, 0x0300, 0x0300, 0x0C80, 0x0C00, 0x0300, 0x0CC0, 0x2500,\n    0x0300, 0x0300, 0x0300, 0x2510, 0x2520, 0x2530, 0x2540, 0x2550, 0x0300, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0A00..0x0A3F -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x2560, 0x0300, 0x2570, 0x0C00,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x0090, 0x0090, 0x00B0, 0x00B0, 0x1100, 0x2580, 0x0090, 0x2590, 0x00B0, 0x25A0, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x25B0, 0x25C0, 0x25D0, 0x25D0, 0x25E0, 0x25F0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x2600, 0x2610,\n/* INDEX_BLOCK: -- 0x0A40..0x0A7F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0C70, 0x08C0, 0x2620, 0x0300, 0x0C80, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x2630, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0A80..0x0ABF -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x2640,\n/* INDEX_BLOCK: -- 0x0AC0..0x0AFF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x2630, 0x2650, 0x08C0, 0x2660, 0x2670, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CE0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0B00..0x0B3F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0470, 0x0970, 0x0C40, 0x2680, 0x2690, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0B40..0x0B7F -- */\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x26A0, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x26B0, 0x0D10, 0x1AB0, 0x0D10, 0x26C0,\n    0x0200, 0x0200, 0x0D80, 0x0200, 0x26D0, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x1420, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0B80..0x0BBF -- */\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x1430, 0x0D10, 0x0D10, 0x26E0, 0x0D10, 0x0D10, 0x0D10, 0x26F0, 0x2700,\n    0x2710, 0x0D10, 0x2720, 0x0D10, 0x0D10, 0x0D10, 0x1200, 0x08C0, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x2730, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x1100, 0x2740, 0x1100, 0x2740,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x1520, 0x1100, 0x1CD0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0BC0..0x0BFF -- */\n    0x0090, 0x2750, 0x00B0, 0x2760, 0x2770, 0x2780, 0x0F20, 0x0090, 0x2790, 0x27A0, 0x27B0, 0x27C0,\n    0x27D0, 0x0090, 0x2750, 0x00B0, 0x27E0, 0x27F0, 0x00B0, 0x2800, 0x2810, 0x2820, 0x2830, 0x0090,\n    0x2840, 0x00B0, 0x0090, 0x2750, 0x00B0, 0x2760, 0x2770, 0x00B0, 0x0F20, 0x0090, 0x2790, 0x2830,\n    0x0090, 0x2840, 0x00B0, 0x0090, 0x2750, 0x00B0, 0x2850, 0x0090, 0x2860, 0x2870, 0x2880, 0x2890,\n    0x00B0, 0x28A0, 0x0090, 0x28B0, 0x28C0, 0x28D0, 0x28E0, 0x00B0, 0x28F0, 0x0090, 0x2900, 0x00B0,\n    0x2910, 0x21B0, 0x21B0, 0x21B0,\n/* INDEX_BLOCK: -- 0x0C00..0x0C3F -- */\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0200, 0x0200, 0x0200, 0x2920,\n    0x0200, 0x0200, 0x2930, 0x2940, 0x2950, 0x2960, 0x02D0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0C40..0x0C7F -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x2970, 0x2980, 0x2990, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0C80..0x0CBF -- */\n    0x29A0, 0x29B0, 0x29C0, 0x01B0, 0x01B0, 0x01B0, 0x29D0, 0x08C0, 0x29E0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x0300, 0x0970, 0x29F0, 0x2A00, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x2A10, 0x08C0, 0x0300, 0x0300, 0x2A20, 0x2A30,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0CC0..0x0CFF -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x0300, 0x2A40, 0x0C00, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x24E0, 0x2A50, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0300, 0x0C80, 0x2A60, 0x2A70,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x2A80, 0x0C80,\n/* INDEX_BLOCK: -- 0x0D00..0x0D3F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x2A90, 0x26D0, 0x08C0, 0x08C0, 0x0090, 0x0090, 0x2790, 0x00B0, 0x2AA0, 0x1720, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0D40..0x0D7F -- */\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x1F80, 0x1100, 0x1100, 0x2AB0, 0x2AC0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x1F80, 0x1100, 0x2AD0, 0x2AE0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x2AF0, 0x0300, 0x2B00, 0x2B10,\n    0x2B20, 0x2B30, 0x2B40, 0x2B50, 0x2B60, 0x0CE0, 0x2B70, 0x0CE0, 0x08C0, 0x08C0, 0x08C0, 0x2B80,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0D80..0x0DBF -- */\n    0x0D10, 0x0D10, 0x2B90, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x1420, 0x14D0, 0x2BA0,\n    0x2BA0, 0x2BA0, 0x0D10, 0x1430, 0x2BB0, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x2BC0, 0x08C0, 0x08C0, 0x08C0, 0x2BD0, 0x0D10, 0x2BE0, 0x0D10, 0x0D10, 0x2B90,\n    0x2BF0, 0x2C00, 0x1430, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x2C10,\n/* INDEX_BLOCK: -- 0x0DC0..0x0DFF -- */\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x2C20, 0x1AA0, 0x1AA0,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0B00, 0x2B90, 0x1AB0,\n/* INDEX_BLOCK: -- 0x0E00..0x0E3F -- */\n    0x2B90, 0x0D10, 0x0D10, 0x0D10, 0x2C30, 0x0B00, 0x0D10, 0x0D10, 0x2C30, 0x0D10, 0x2BC0, 0x2B90,\n    0x2C00, 0x2C40, 0x08C0, 0x08C0, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10,\n    0x0D10, 0x2C30, 0x2BC0, 0x1AA0, 0x2C50, 0x0D10, 0x0D10, 0x0D10, 0x2C60, 0x2C70, 0x2C80, 0x2BF0,\n    0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x0D10, 0x2C90, 0x0D10, 0x0D10,\n    0x0D10, 0x0D10, 0x0D10, 0x2CA0,\n/* INDEX_BLOCK: -- 0x0E40..0x0E7F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x08C0, 0x08C0,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0E80..0x0EBF -- */\n    0x0300, 0x0CC0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0EC0..0x0EFF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CC0, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x0F00..0x0F3F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0640, 0x0300,\n/* INDEX_BLOCK: -- 0x0F40..0x0F7F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0CC0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0F80..0x0FBF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CC0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x0FC0..0x0FFF -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0470, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300,\n    0x0300, 0x0300, 0x0300, 0x0300,\n/* INDEX_BLOCK: -- 0x1000..0x103F -- */\n    0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0CF0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x1040..0x107F -- */\n    0x2CB0, 0x08C0, 0x24B0, 0x24B0, 0x24B0, 0x24B0, 0x24B0, 0x24B0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200,\n    0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0, 0x08C0,\n    0x08C0, 0x08C0, 0x08C0, 0x08C0,\n/* INDEX_BLOCK: -- 0x1080..0x10BF -- */\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870, 0x1870,\n    0x1870, 0x1870, 0x1870, 0x2CC0\n};\n\nstatic const SBUInt16 BranchGeneralCategoryIndexes[1088] = {\n    0x0000, 0x0040, 0x0080, 0x00C0, 0x0100, 0x0140, 0x0180, 0x01C0, 0x0200, 0x0240, 0x0280, 0x02C0,\n    0x0300, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0380, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x03C0, 0x0400, 0x0440, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0480, 0x04C0, 0x04C0, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, 0x0740, 0x0780,\n    0x07C0, 0x0800, 0x0840, 0x0880, 0x0340, 0x08C0, 0x0340, 0x0340, 0x0900, 0x0940, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0980, 0x0840, 0x09C0, 0x0A00, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0A40, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0A80,\n    0x0AC0, 0x0840, 0x0840, 0x0B00, 0x0840, 0x0840, 0x0840, 0x0B40, 0x0B80, 0x0BC0, 0x0C00, 0x0C40,\n    0x0C80, 0x0CC0, 0x0D00, 0x0D40, 0x0D80, 0x0DC0, 0x0E00, 0x0840, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x0E40, 0x0340, 0x0340, 0x0340, 0x0340, 0x0E80, 0x0340, 0x0340, 0x0340, 0x0340, 0x0EC0,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0F00, 0x0F40, 0x0840, 0x0840, 0x0F80, 0x0840,\n    0x0340, 0x0340, 0x0340, 0x0340, 0x0FC0, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340,\n    0x0340, 0x1000, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x1040, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840, 0x0840,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x1080, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500,\n    0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x1080\n};\n\nSB_INTERNAL SBGeneralCategory LookupGeneralCategory(SBCodepoint codepoint) {\n    if (codepoint <= 0x10FFFF) {\n        return PrimaryGeneralCategoryData[\n                MainGeneralCategoryIndexes[\n                 BranchGeneralCategoryIndexes[\n                      codepoint / 0x0400\n                 ] + (codepoint % 0x0400) / 0x0010\n                ] + (codepoint % 0x0010)\n               ];\n    }\n\n    return Cn;\n}\n\n#undef Cc\n#undef Cf\n#undef Cn\n#undef Co\n#undef Cs\n#undef Ll\n#undef Lm\n#undef Lo\n#undef Lt\n#undef Lu\n#undef Mc\n#undef Me\n#undef Mn\n#undef Nd\n#undef Nl\n#undef No\n#undef Pc\n#undef Pd\n#undef Pe\n#undef Pf\n#undef Pi\n#undef Po\n#undef Ps\n#undef Sc\n#undef Sk\n#undef Sm\n#undef So\n#undef Zl\n#undef Zp\n#undef Zs\n"
  },
  {
    "path": "unix/bidi/Source/Data/GeneralCategoryLookup.h",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool. \n * DO NOT EDIT!!\n */\n\n#ifndef _SB_INTERNAL_GENERAL_CATEGORY_LOOKUP_H\n#define _SB_INTERNAL_GENERAL_CATEGORY_LOOKUP_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n\nSB_INTERNAL SBGeneralCategory LookupGeneralCategory(SBCodepoint codepoint);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Data/PairingLookup.c",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n *\n * REQUIRED MEMORY: (37)+2310+(617*2) = 3618 Bytes\n */\n\n#include \"PairingLookup.h\"\n\nstatic const SBInt16 PairDifferences[37] = {\n    0,     1,     -1,    2,     -2,    16,    -16,   3,     -3,    2016,  2527,  1923,  1914,  1918,\n    2250,  138,   7,     -7,    1824,  2104,  2108,  2106,  1316,  -138,  8,     -8,    -1316,\n    -1914, -1918, -1923, -1824, -2016, -2104, -2106, -2108, -2250, -2527\n};\n\nstatic const SBUInt8 PairData[2310] = {\n/* DATA_BLOCK: -- 0x0000..0x0069 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   3,   0,   4,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   67,  0,   132, 0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x006A..0x00D3 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   67,  0,\n    132, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x00D4..0x013D -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x013E..0x01A7 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   65,  130, 65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x01A8..0x0211 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x0212..0x027B -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   65,  130, 0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x027C..0x02E5 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   65,  130, 0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x02E6..0x034F -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   7,   7,   7,   8,   8,   8,   0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   10,  11,  12,  13,  0,   14,  0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   0,   0,\n    0,   0,   0,   15,  0,   16,  0,   0,   0,   0,   0,   0,   17,  0,   0,   0,   0,   0,   1,\n    2,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x0350..0x03B9 -- */\n    0,   0,   0,   0,   0,   0,   1,   2,   1,   2,   1,   2,   1,   2,   0,   0,   1,   2,   1,\n    2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,\n    1,   2,   1,   2,   1,   2,   1,   2,   0,   0,   0,   1,   2,   1,   2,   0,   0,   0,   0,\n    0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   0,   0,   19,  0,   20,  21,\n    0,   21,  0,   0,   0,   0,   1,   2,   1,   2,   1,   2,   1,   2,   22,  0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x03BA..0x0423 -- */\n    0,   1,   2,   1,   2,   23,  0,   0,   1,   2,   0,   0,   0,   0,   1,   2,   1,   2,   1,\n    2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,\n    0,   0,   1,   2,   24,  24,  24,  0,   16,  16,  0,   0,   25,  25,  25,  17,  17,  0,   0,\n    0,   0,   0,   0,   0,   0,   0,   65,  130, 65,  130, 0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   65,  130, 0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x0424..0x048D -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   65,\n    130, 65,  130, 65,  130, 65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x048E..0x04F7 -- */\n    0,   0,   0,   1,   2,   65,  130, 0,   1,   2,   0,   3,   0,   4,   0,   0,   0,   0,   0,\n    0,   0,   1,   2,   0,   0,   0,   0,   0,   26,  1,   2,   0,   0,   0,   1,   2,   1,   2,\n    65,  130, 65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x04F8..0x0561 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   65,  130, 65,  130, 65,  130, 65,  130, 65,  130, 71,\n    129, 66,  136, 65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   27,  0,   0,   0,   0,   28,\n    0,   0,   29,  1,   2,   0,   0,   1,   2,   1,   2,   1,   2,   1,   2,   0,   0,   0,   0,\n    0,   0,   0,   0,   30,  0,   0,   0,   0,   0,   0,   0,   1,   2,   0,   0,   1,   2,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   1,\n/* DATA_BLOCK: -- 0x0562..0x05CB -- */\n    2,   0,   1,   2,   0,   0,   65,  130, 65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   31,  0,   0,\n    1,   2,   0,   0,   65,  130, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   1,   2,   0,   0,\n    0,   0,   0,   1,   2,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x05CC..0x0635 -- */\n    1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,\n    2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,\n    1,   2,   1,   2,   1,   2,   1,   2,   0,   0,   0,\n/* DATA_BLOCK: -- 0x0636..0x069F -- */\n    1,   2,   1,   2,   1,   2,   1,   2,   0,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,\n    1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   1,\n    2,   1,   2,   1,   2,   1,   2,   1,   2,   1,   2,   0,   0,   0,   0,   0,   0,   0,   32,\n    0,   0,   0,   0,   33,  34,  33,  0,   0,   0,   0,   0,   0,   1,   2,   35,  0,   0,   0,\n    0,   0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x06A0..0x0709 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x070A..0x0773 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   0,\n    1,   2,   0,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    1,   2,   0,   0,   1,   2,   65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   0,\n/* DATA_BLOCK: -- 0x0774..0x07DD -- */\n    65,  130, 65,  130, 65,  130, 65,  130, 65,  130, 0,   0,   65,  130, 65,  130, 65,  130, 65,\n    130, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x07DE..0x0847 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   65,  130, 65,  130, 65,  130, 0,   0,   0,\n    0,   0,   1,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x0848..0x08B1 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   65,  130, 0,   0,   0,   0,   0,   0,\n/* DATA_BLOCK: -- 0x08B2..0x0905 -- */\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   4,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   67,  0,   132, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   67,\n    0,   132, 0,   65,  130, 0,   65,  130,\n};\n\nstatic const SBUInt16 PairIndexes[617] = {\n    0x0000, 0x006A, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x013E, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x01A8, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0212, 0x027C, 0x00D4, 0x00D4, 0x00D4, 0x02E6, 0x0350,\n    0x03BA, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0424,\n    0x048E, 0x00D4, 0x00D4, 0x00D4, 0x04F8, 0x0562, 0x05CC, 0x0636, 0x00D4, 0x00D4, 0x06A0, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x070A, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0774, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,\n    0x00D4, 0x00D4, 0x07DE, 0x0848, 0x08B2\n};\n\nSB_INTERNAL SBCodepoint LookupMirror(SBCodepoint codepoint)\n{\n    if (codepoint <= 0xFF63) {\n        SBInt16 diff = PairDifferences[\n                        PairData[\n                         PairIndexes[\n                              codepoint / 0x06A\n                         ] + (codepoint % 0x06A)\n                        ] & BracketTypeInverseMask\n                       ];\n\n        if (diff != 0) {\n            return (codepoint + diff);\n        }\n    }\n\n    return 0;\n}\n\nSB_INTERNAL SBCodepoint LookupBracketPair(SBCodepoint codepoint, BracketType *type)\n{\n    if (codepoint <= 0xFF63) {\n        SBUInt8 data = PairData[\n                        PairIndexes[\n                             codepoint / 0x06A\n                        ] + (codepoint % 0x06A)\n                       ];\n        *type = (data & BracketTypePrimaryMask);\n\n        if (*type != 0) {\n            SBInt16 diff = PairDifferences[\n                            data & BracketTypeInverseMask\n                           ];\n            return (codepoint + diff);\n        }\n    } else {\n        *type = BracketTypeNone;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "unix/bidi/Source/Data/PairingLookup.h",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n */\n\n#ifndef _SB_INTERNAL_PAIRING_LOOKUP_H\n#define _SB_INTERNAL_PAIRING_LOOKUP_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <UBA/BracketType.h>\n\nSB_INTERNAL SBCodepoint LookupMirror(SBCodepoint codepoint);\nSB_INTERNAL SBCodepoint LookupBracketPair(SBCodepoint codepoint, BracketType *bracketType);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Data/ScriptLookup.c",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n *\n * REQUIRED MEMORY: 11328+(3391*2)+(1793*2) = 21696 Bytes\n */\n\n#include \"ScriptLookup.h\"\n\n#define Adlm     SBScriptADLM\n#define Aghb     SBScriptAGHB\n#define Ahom     SBScriptAHOM\n#define Arab     SBScriptARAB\n#define Armi     SBScriptARMI\n#define Armn     SBScriptARMN\n#define Avst     SBScriptAVST\n#define Bali     SBScriptBALI\n#define Bamu     SBScriptBAMU\n#define Bass     SBScriptBASS\n#define Batk     SBScriptBATK\n#define Beng     SBScriptBENG\n#define Berf     SBScriptBERF\n#define Bhks     SBScriptBHKS\n#define Bopo     SBScriptBOPO\n#define Brah     SBScriptBRAH\n#define Brai     SBScriptBRAI\n#define Bugi     SBScriptBUGI\n#define Buhd     SBScriptBUHD\n#define Cakm     SBScriptCAKM\n#define Cans     SBScriptCANS\n#define Cari     SBScriptCARI\n#define Cham     SBScriptCHAM\n#define Cher     SBScriptCHER\n#define Chrs     SBScriptCHRS\n#define Copt     SBScriptCOPT\n#define Cpmn     SBScriptCPMN\n#define Cprt     SBScriptCPRT\n#define Cyrl     SBScriptCYRL\n#define Deva     SBScriptDEVA\n#define Diak     SBScriptDIAK\n#define Dogr     SBScriptDOGR\n#define Dsrt     SBScriptDSRT\n#define Dupl     SBScriptDUPL\n#define Egyp     SBScriptEGYP\n#define Elba     SBScriptELBA\n#define Elym     SBScriptELYM\n#define Ethi     SBScriptETHI\n#define Gara     SBScriptGARA\n#define Geor     SBScriptGEOR\n#define Glag     SBScriptGLAG\n#define Gong     SBScriptGONG\n#define Gonm     SBScriptGONM\n#define Goth     SBScriptGOTH\n#define Gran     SBScriptGRAN\n#define Grek     SBScriptGREK\n#define Gujr     SBScriptGUJR\n#define Gukh     SBScriptGUKH\n#define Guru     SBScriptGURU\n#define Hang     SBScriptHANG\n#define Hani     SBScriptHANI\n#define Hano     SBScriptHANO\n#define Hatr     SBScriptHATR\n#define Hebr     SBScriptHEBR\n#define Hira     SBScriptHIRA\n#define Hluw     SBScriptHLUW\n#define Hmng     SBScriptHMNG\n#define Hmnp     SBScriptHMNP\n#define Hung     SBScriptHUNG\n#define Ital     SBScriptITAL\n#define Java     SBScriptJAVA\n#define Kali     SBScriptKALI\n#define Kana     SBScriptKANA\n#define Kawi     SBScriptKAWI\n#define Khar     SBScriptKHAR\n#define Khmr     SBScriptKHMR\n#define Khoj     SBScriptKHOJ\n#define Kits     SBScriptKITS\n#define Knda     SBScriptKNDA\n#define Krai     SBScriptKRAI\n#define Kthi     SBScriptKTHI\n#define Lana     SBScriptLANA\n#define Laoo     SBScriptLAOO\n#define Latn     SBScriptLATN\n#define Lepc     SBScriptLEPC\n#define Limb     SBScriptLIMB\n#define Lina     SBScriptLINA\n#define Linb     SBScriptLINB\n#define Lisu     SBScriptLISU\n#define Lyci     SBScriptLYCI\n#define Lydi     SBScriptLYDI\n#define Mahj     SBScriptMAHJ\n#define Maka     SBScriptMAKA\n#define Mand     SBScriptMAND\n#define Mani     SBScriptMANI\n#define Marc     SBScriptMARC\n#define Medf     SBScriptMEDF\n#define Mend     SBScriptMEND\n#define Merc     SBScriptMERC\n#define Mero     SBScriptMERO\n#define Mlym     SBScriptMLYM\n#define Modi     SBScriptMODI\n#define Mong     SBScriptMONG\n#define Mroo     SBScriptMROO\n#define Mtei     SBScriptMTEI\n#define Mult     SBScriptMULT\n#define Mymr     SBScriptMYMR\n#define Nagm     SBScriptNAGM\n#define Nand     SBScriptNAND\n#define Narb     SBScriptNARB\n#define Nbat     SBScriptNBAT\n#define Newa     SBScriptNEWA\n#define Nkoo     SBScriptNKOO\n#define Nshu     SBScriptNSHU\n#define Ogam     SBScriptOGAM\n#define Olck     SBScriptOLCK\n#define Onao     SBScriptONAO\n#define Orkh     SBScriptORKH\n#define Orya     SBScriptORYA\n#define Osge     SBScriptOSGE\n#define Osma     SBScriptOSMA\n#define Ougr     SBScriptOUGR\n#define Palm     SBScriptPALM\n#define Pauc     SBScriptPAUC\n#define Perm     SBScriptPERM\n#define Phag     SBScriptPHAG\n#define Phli     SBScriptPHLI\n#define Phlp     SBScriptPHLP\n#define Phnx     SBScriptPHNX\n#define Plrd     SBScriptPLRD\n#define Prti     SBScriptPRTI\n#define Rjng     SBScriptRJNG\n#define Rohg     SBScriptROHG\n#define Runr     SBScriptRUNR\n#define Samr     SBScriptSAMR\n#define Sarb     SBScriptSARB\n#define Saur     SBScriptSAUR\n#define Sgnw     SBScriptSGNW\n#define Shaw     SBScriptSHAW\n#define Shrd     SBScriptSHRD\n#define Sidd     SBScriptSIDD\n#define Sidt     SBScriptSIDT\n#define Sind     SBScriptSIND\n#define Sinh     SBScriptSINH\n#define Sogd     SBScriptSOGD\n#define Sogo     SBScriptSOGO\n#define Sora     SBScriptSORA\n#define Soyo     SBScriptSOYO\n#define Sund     SBScriptSUND\n#define Sunu     SBScriptSUNU\n#define Sylo     SBScriptSYLO\n#define Syrc     SBScriptSYRC\n#define Tagb     SBScriptTAGB\n#define Takr     SBScriptTAKR\n#define Tale     SBScriptTALE\n#define Talu     SBScriptTALU\n#define Taml     SBScriptTAML\n#define Tang     SBScriptTANG\n#define Tavt     SBScriptTAVT\n#define Tayo     SBScriptTAYO\n#define Telu     SBScriptTELU\n#define Tfng     SBScriptTFNG\n#define Tglg     SBScriptTGLG\n#define Thaa     SBScriptTHAA\n#define Thai     SBScriptTHAI\n#define Tibt     SBScriptTIBT\n#define Tirh     SBScriptTIRH\n#define Tnsa     SBScriptTNSA\n#define Todr     SBScriptTODR\n#define Tols     SBScriptTOLS\n#define Toto     SBScriptTOTO\n#define Tutg     SBScriptTUTG\n#define Ugar     SBScriptUGAR\n#define Vaii     SBScriptVAII\n#define Vith     SBScriptVITH\n#define Wara     SBScriptWARA\n#define Wcho     SBScriptWCHO\n#define Xpeo     SBScriptXPEO\n#define Xsux     SBScriptXSUX\n#define Yezi     SBScriptYEZI\n#define Yiii     SBScriptYIII\n#define Zanb     SBScriptZANB\n#define Zinh     SBScriptZINH\n#define Zyyy     SBScriptZYYY\n#define Zzzz     SBScriptZZZZ\n\nstatic const SBUInt8 PrimaryScriptData[11328] = {\n/* DATA_BLOCK: -- 0x0000..0x000F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0010..0x001F -- */\n    Zyyy, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0020..0x002F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0030..0x003F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Latn, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0040..0x004F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0050..0x005F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0060..0x006F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0070..0x007F -- */\n    Latn, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Bopo, Bopo, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0080..0x008F -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh,\n/* DATA_BLOCK: -- 0x0090..0x009F -- */\n    Grek, Grek, Grek, Grek, Zyyy, Grek, Grek, Grek, Zzzz, Zzzz, Grek, Grek, Grek, Grek, Zyyy, Grek,\n/* DATA_BLOCK: -- 0x00A0..0x00AF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Grek, Zyyy, Grek, Zyyy, Grek, Grek, Grek, Zzzz, Grek, Zzzz, Grek, Grek,\n/* DATA_BLOCK: -- 0x00B0..0x00BF -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek,\n/* DATA_BLOCK: -- 0x00C0..0x00CF -- */\n    Grek, Grek, Zzzz, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek,\n/* DATA_BLOCK: -- 0x00D0..0x00DF -- */\n    Grek, Grek, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt,\n/* DATA_BLOCK: -- 0x00E0..0x00EF -- */\n    Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl,\n/* DATA_BLOCK: -- 0x00F0..0x00FF -- */\n    Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Zinh, Zinh, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl,\n/* DATA_BLOCK: -- 0x0100..0x010F -- */\n    Zzzz, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn,\n/* DATA_BLOCK: -- 0x0110..0x011F -- */\n    Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn,\n/* DATA_BLOCK: -- 0x0120..0x012F -- */\n    Armn, Armn, Armn, Armn, Armn, Armn, Armn, Zzzz, Zzzz, Armn, Armn, Armn, Armn, Armn, Armn, Armn,\n/* DATA_BLOCK: -- 0x0130..0x013F -- */\n    Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Armn, Zzzz, Zzzz, Armn, Armn, Armn,\n/* DATA_BLOCK: -- 0x0140..0x014F -- */\n    Zzzz, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr,\n/* DATA_BLOCK: -- 0x0150..0x015F -- */\n    Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr,\n/* DATA_BLOCK: -- 0x0160..0x016F -- */\n    Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0170..0x017F -- */\n    Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Zzzz, Zzzz, Zzzz, Zzzz, Hebr,\n/* DATA_BLOCK: -- 0x0180..0x018F -- */\n    Hebr, Hebr, Hebr, Hebr, Hebr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0190..0x019F -- */\n    Arab, Arab, Arab, Arab, Arab, Zyyy, Arab, Arab, Arab, Arab, Arab, Arab, Zyyy, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x01A0..0x01AF -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zyyy, Arab, Arab, Arab, Zyyy,\n/* DATA_BLOCK: -- 0x01B0..0x01BF -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x01C0..0x01CF -- */\n    Zyyy, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zinh, Zinh, Zinh, Zinh, Zinh,\n/* DATA_BLOCK: -- 0x01D0..0x01DF -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x01E0..0x01EF -- */\n    Zinh, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x01F0..0x01FF -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zyyy, Arab, Arab,\n/* DATA_BLOCK: -- 0x0200..0x020F -- */\n    Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Zzzz, Syrc,\n/* DATA_BLOCK: -- 0x0210..0x021F -- */\n    Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc,\n/* DATA_BLOCK: -- 0x0220..0x022F -- */\n    Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Zzzz, Zzzz, Syrc, Syrc, Syrc,\n/* DATA_BLOCK: -- 0x0230..0x023F -- */\n    Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa, Thaa,\n/* DATA_BLOCK: -- 0x0240..0x024F -- */\n    Thaa, Thaa, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0250..0x025F -- */\n    Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo,\n/* DATA_BLOCK: -- 0x0260..0x026F -- */\n    Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Nkoo, Zzzz, Zzzz, Nkoo, Nkoo, Nkoo,\n/* DATA_BLOCK: -- 0x0270..0x027F -- */\n    Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr,\n/* DATA_BLOCK: -- 0x0280..0x028F -- */\n    Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0290..0x029F -- */\n    Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Samr, Zzzz,\n/* DATA_BLOCK: -- 0x02A0..0x02AF -- */\n    Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand,\n/* DATA_BLOCK: -- 0x02B0..0x02BF -- */\n    Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Mand, Zzzz, Zzzz, Mand, Zzzz,\n/* DATA_BLOCK: -- 0x02C0..0x02CF -- */\n    Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Syrc, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x02D0..0x02DF -- */\n    Arab, Arab, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x02E0..0x02EF -- */\n    Arab, Arab, Zyyy, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x02F0..0x02FF -- */\n    Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva,\n/* DATA_BLOCK: -- 0x0300..0x030F -- */\n    Deva, Zinh, Zinh, Zinh, Zinh, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva,\n/* DATA_BLOCK: -- 0x0310..0x031F -- */\n    Deva, Deva, Deva, Deva, Zyyy, Zyyy, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva,\n/* DATA_BLOCK: -- 0x0320..0x032F -- */\n    Beng, Beng, Beng, Beng, Zzzz, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Zzzz, Zzzz, Beng,\n/* DATA_BLOCK: -- 0x0330..0x033F -- */\n    Beng, Zzzz, Zzzz, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng,\n/* DATA_BLOCK: -- 0x0340..0x034F -- */\n    Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Zzzz, Beng, Beng, Beng, Beng, Beng, Beng,\n/* DATA_BLOCK: -- 0x0350..0x035F -- */\n    Beng, Zzzz, Beng, Zzzz, Zzzz, Zzzz, Beng, Beng, Beng, Beng, Zzzz, Zzzz, Beng, Beng, Beng, Beng,\n/* DATA_BLOCK: -- 0x0360..0x036F -- */\n    Beng, Beng, Beng, Beng, Beng, Zzzz, Zzzz, Beng, Beng, Zzzz, Zzzz, Beng, Beng, Beng, Beng, Zzzz,\n/* DATA_BLOCK: -- 0x0370..0x037F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Beng, Zzzz, Zzzz, Zzzz, Zzzz, Beng, Beng, Zzzz, Beng,\n/* DATA_BLOCK: -- 0x0380..0x038F -- */\n    Beng, Beng, Beng, Beng, Zzzz, Zzzz, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng,\n/* DATA_BLOCK: -- 0x0390..0x039F -- */\n    Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Beng, Zzzz,\n/* DATA_BLOCK: -- 0x03A0..0x03AF -- */\n    Zzzz, Guru, Guru, Guru, Zzzz, Guru, Guru, Guru, Guru, Guru, Guru, Zzzz, Zzzz, Zzzz, Zzzz, Guru,\n/* DATA_BLOCK: -- 0x03B0..0x03BF -- */\n    Guru, Zzzz, Zzzz, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru,\n/* DATA_BLOCK: -- 0x03C0..0x03CF -- */\n    Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Zzzz, Guru, Guru, Guru, Guru, Guru, Guru,\n/* DATA_BLOCK: -- 0x03D0..0x03DF -- */\n    Guru, Zzzz, Guru, Guru, Zzzz, Guru, Guru, Zzzz, Guru, Guru, Zzzz, Zzzz, Guru, Zzzz, Guru, Guru,\n/* DATA_BLOCK: -- 0x03E0..0x03EF -- */\n    Guru, Guru, Guru, Zzzz, Zzzz, Zzzz, Zzzz, Guru, Guru, Zzzz, Zzzz, Guru, Guru, Guru, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x03F0..0x03FF -- */\n    Zzzz, Guru, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Guru, Guru, Guru, Guru, Zzzz, Guru, Zzzz,\n/* DATA_BLOCK: -- 0x0400..0x040F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru, Guru,\n/* DATA_BLOCK: -- 0x0410..0x041F -- */\n    Guru, Guru, Guru, Guru, Guru, Guru, Guru, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0420..0x042F -- */\n    Zzzz, Gujr, Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Zzzz, Gujr,\n/* DATA_BLOCK: -- 0x0430..0x043F -- */\n    Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr,\n/* DATA_BLOCK: -- 0x0440..0x044F -- */\n    Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr,\n/* DATA_BLOCK: -- 0x0450..0x045F -- */\n    Gujr, Zzzz, Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Zzzz, Zzzz, Gujr, Gujr, Gujr, Gujr,\n/* DATA_BLOCK: -- 0x0460..0x046F -- */\n    Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Zzzz, Gujr, Gujr, Gujr, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0470..0x047F -- */\n    Gujr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0480..0x048F -- */\n    Gujr, Gujr, Gujr, Gujr, Zzzz, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr,\n/* DATA_BLOCK: -- 0x0490..0x049F -- */\n    Gujr, Gujr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr, Gujr,\n/* DATA_BLOCK: -- 0x04A0..0x04AF -- */\n    Zzzz, Orya, Orya, Orya, Zzzz, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Zzzz, Zzzz, Orya,\n/* DATA_BLOCK: -- 0x04B0..0x04BF -- */\n    Orya, Zzzz, Zzzz, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya,\n/* DATA_BLOCK: -- 0x04C0..0x04CF -- */\n    Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Zzzz, Orya, Orya, Orya, Orya, Orya, Orya,\n/* DATA_BLOCK: -- 0x04D0..0x04DF -- */\n    Orya, Zzzz, Orya, Orya, Zzzz, Orya, Orya, Orya, Orya, Orya, Zzzz, Zzzz, Orya, Orya, Orya, Orya,\n/* DATA_BLOCK: -- 0x04E0..0x04EF -- */\n    Orya, Orya, Orya, Orya, Orya, Zzzz, Zzzz, Orya, Orya, Zzzz, Zzzz, Orya, Orya, Orya, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x04F0..0x04FF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Orya, Orya, Orya, Zzzz, Zzzz, Zzzz, Zzzz, Orya, Orya, Zzzz, Orya,\n/* DATA_BLOCK: -- 0x0500..0x050F -- */\n    Orya, Orya, Orya, Orya, Zzzz, Zzzz, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya,\n/* DATA_BLOCK: -- 0x0510..0x051F -- */\n    Orya, Orya, Orya, Orya, Orya, Orya, Orya, Orya, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0520..0x052F -- */\n    Zzzz, Zzzz, Taml, Taml, Zzzz, Taml, Taml, Taml, Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Taml, Taml,\n/* DATA_BLOCK: -- 0x0530..0x053F -- */\n    Taml, Zzzz, Taml, Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Taml, Taml, Zzzz, Taml, Zzzz, Taml, Taml,\n/* DATA_BLOCK: -- 0x0540..0x054F -- */\n    Zzzz, Zzzz, Zzzz, Taml, Taml, Zzzz, Zzzz, Zzzz, Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Taml, Taml,\n/* DATA_BLOCK: -- 0x0550..0x055F -- */\n    Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Zzzz, Taml, Taml,\n/* DATA_BLOCK: -- 0x0560..0x056F -- */\n    Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Taml, Taml, Taml, Zzzz, Taml, Taml, Taml, Taml, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0570..0x057F -- */\n    Taml, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Taml, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0580..0x058F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml,\n/* DATA_BLOCK: -- 0x0590..0x059F -- */\n    Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x05A0..0x05AF -- */\n    Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Zzzz, Telu, Telu,\n/* DATA_BLOCK: -- 0x05B0..0x05BF -- */\n    Telu, Zzzz, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu,\n/* DATA_BLOCK: -- 0x05C0..0x05CF -- */\n    Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Zzzz, Telu, Telu, Telu, Telu, Telu, Telu,\n/* DATA_BLOCK: -- 0x05D0..0x05DF -- */\n    Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Zzzz, Zzzz, Telu, Telu, Telu, Telu,\n/* DATA_BLOCK: -- 0x05E0..0x05EF -- */\n    Telu, Telu, Telu, Telu, Telu, Zzzz, Telu, Telu, Telu, Zzzz, Telu, Telu, Telu, Telu, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x05F0..0x05FF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Telu, Telu, Zzzz, Telu, Telu, Telu, Zzzz, Telu, Telu, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0600..0x060F -- */\n    Telu, Telu, Telu, Telu, Zzzz, Zzzz, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu,\n/* DATA_BLOCK: -- 0x0610..0x061F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu, Telu,\n/* DATA_BLOCK: -- 0x0620..0x062F -- */\n    Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Zzzz, Knda, Knda,\n/* DATA_BLOCK: -- 0x0630..0x063F -- */\n    Knda, Zzzz, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda,\n/* DATA_BLOCK: -- 0x0640..0x064F -- */\n    Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Zzzz, Knda, Knda, Knda, Knda, Knda, Knda,\n/* DATA_BLOCK: -- 0x0650..0x065F -- */\n    Knda, Knda, Knda, Knda, Zzzz, Knda, Knda, Knda, Knda, Knda, Zzzz, Zzzz, Knda, Knda, Knda, Knda,\n/* DATA_BLOCK: -- 0x0660..0x066F -- */\n    Knda, Knda, Knda, Knda, Knda, Zzzz, Knda, Knda, Knda, Zzzz, Knda, Knda, Knda, Knda, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0670..0x067F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Knda, Knda, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Knda, Knda, Knda, Zzzz,\n/* DATA_BLOCK: -- 0x0680..0x068F -- */\n    Knda, Knda, Knda, Knda, Zzzz, Zzzz, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda, Knda,\n/* DATA_BLOCK: -- 0x0690..0x069F -- */\n    Zzzz, Knda, Knda, Knda, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x06A0..0x06AF -- */\n    Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Zzzz, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x06B0..0x06BF -- */\n    Mlym, Zzzz, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x06C0..0x06CF -- */\n    Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x06D0..0x06DF -- */\n    Mlym, Mlym, Mlym, Mlym, Mlym, Zzzz, Mlym, Mlym, Mlym, Zzzz, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x06E0..0x06EF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x06F0..0x06FF -- */\n    Mlym, Mlym, Mlym, Mlym, Zzzz, Zzzz, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym, Mlym,\n/* DATA_BLOCK: -- 0x0700..0x070F -- */\n    Zzzz, Sinh, Sinh, Sinh, Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x0710..0x071F -- */\n    Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Zzzz, Zzzz, Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x0720..0x072F -- */\n    Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x0730..0x073F -- */\n    Sinh, Sinh, Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Zzzz, Sinh, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0740..0x074F -- */\n    Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Zzzz, Zzzz, Zzzz, Sinh, Zzzz, Zzzz, Zzzz, Zzzz, Sinh,\n/* DATA_BLOCK: -- 0x0750..0x075F -- */\n    Sinh, Sinh, Sinh, Sinh, Sinh, Zzzz, Sinh, Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x0760..0x076F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x0770..0x077F -- */\n    Zzzz, Zzzz, Sinh, Sinh, Sinh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0780..0x078F -- */\n    Zzzz, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,\n/* DATA_BLOCK: -- 0x0790..0x079F -- */\n    Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai,\n/* DATA_BLOCK: -- 0x07A0..0x07AF -- */\n    Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x07B0..0x07BF -- */\n    Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x07C0..0x07CF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x07D0..0x07DF -- */\n    Zzzz, Laoo, Laoo, Zzzz, Laoo, Zzzz, Laoo, Laoo, Laoo, Laoo, Laoo, Zzzz, Laoo, Laoo, Laoo, Laoo,\n/* DATA_BLOCK: -- 0x07E0..0x07EF -- */\n    Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo,\n/* DATA_BLOCK: -- 0x07F0..0x07FF -- */\n    Laoo, Laoo, Laoo, Laoo, Zzzz, Laoo, Zzzz, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo,\n/* DATA_BLOCK: -- 0x0800..0x080F -- */\n    Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0810..0x081F -- */\n    Laoo, Laoo, Laoo, Laoo, Laoo, Zzzz, Laoo, Zzzz, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Zzzz,\n/* DATA_BLOCK: -- 0x0820..0x082F -- */\n    Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Laoo, Zzzz, Zzzz, Laoo, Laoo, Laoo, Laoo,\n/* DATA_BLOCK: -- 0x0830..0x083F -- */\n    Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt,\n/* DATA_BLOCK: -- 0x0840..0x084F -- */\n    Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Zzzz, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt,\n/* DATA_BLOCK: -- 0x0850..0x085F -- */\n    Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0860..0x086F -- */\n    Zzzz, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt,\n/* DATA_BLOCK: -- 0x0870..0x087F -- */\n    Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Tibt, Zzzz, Tibt, Tibt,\n/* DATA_BLOCK: -- 0x0880..0x088F -- */\n    Tibt, Tibt, Tibt, Tibt, Tibt, Zyyy, Zyyy, Zyyy, Zyyy, Tibt, Tibt, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0890..0x089F -- */\n    Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr,\n/* DATA_BLOCK: -- 0x08A0..0x08AF -- */\n    Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor,\n/* DATA_BLOCK: -- 0x08B0..0x08BF -- */\n    Geor, Geor, Geor, Geor, Geor, Geor, Zzzz, Geor, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Geor, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x08C0..0x08CF -- */\n    Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Zyyy, Geor, Geor, Geor, Geor,\n/* DATA_BLOCK: -- 0x08D0..0x08DF -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang,\n/* DATA_BLOCK: -- 0x08E0..0x08EF -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi,\n/* DATA_BLOCK: -- 0x08F0..0x08FF -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0900..0x090F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0910..0x091F -- */\n    Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz,\n/* DATA_BLOCK: -- 0x0920..0x092F -- */\n    Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi,\n/* DATA_BLOCK: -- 0x0930..0x093F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi,\n/* DATA_BLOCK: -- 0x0940..0x094F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Ethi, Ethi, Ethi,\n/* DATA_BLOCK: -- 0x0950..0x095F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0960..0x096F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0970..0x097F -- */\n    Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher, Cher,\n/* DATA_BLOCK: -- 0x0980..0x098F -- */\n    Cher, Cher, Cher, Cher, Cher, Cher, Zzzz, Zzzz, Cher, Cher, Cher, Cher, Cher, Cher, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0990..0x099F -- */\n    Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans, Cans,\n/* DATA_BLOCK: -- 0x09A0..0x09AF -- */\n    Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam,\n/* DATA_BLOCK: -- 0x09B0..0x09BF -- */\n    Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Ogam, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x09C0..0x09CF -- */\n    Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr,\n/* DATA_BLOCK: -- 0x09D0..0x09DF -- */\n    Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Zyyy, Zyyy, Zyyy, Runr, Runr,\n/* DATA_BLOCK: -- 0x09E0..0x09EF -- */\n    Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Runr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x09F0..0x09FF -- */\n    Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Tglg,\n/* DATA_BLOCK: -- 0x0A00..0x0A0F -- */\n    Tglg, Tglg, Tglg, Tglg, Tglg, Tglg, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Tglg,\n/* DATA_BLOCK: -- 0x0A10..0x0A1F -- */\n    Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano, Hano,\n/* DATA_BLOCK: -- 0x0A20..0x0A2F -- */\n    Hano, Hano, Hano, Hano, Hano, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0A30..0x0A3F -- */\n    Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd, Buhd,\n/* DATA_BLOCK: -- 0x0A40..0x0A4F -- */\n    Buhd, Buhd, Buhd, Buhd, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0A50..0x0A5F -- */\n    Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Tagb, Zzzz, Tagb, Tagb,\n/* DATA_BLOCK: -- 0x0A60..0x0A6F -- */\n    Tagb, Zzzz, Tagb, Tagb, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0A70..0x0A7F -- */\n    Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr,\n/* DATA_BLOCK: -- 0x0A80..0x0A8F -- */\n    Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0A90..0x0A9F -- */\n    Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Khmr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0AA0..0x0AAF -- */\n    Mong, Mong, Zyyy, Zyyy, Mong, Zyyy, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong,\n/* DATA_BLOCK: -- 0x0AB0..0x0ABF -- */\n    Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0AC0..0x0ACF -- */\n    Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong,\n/* DATA_BLOCK: -- 0x0AD0..0x0ADF -- */\n    Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0AE0..0x0AEF -- */\n    Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0AF0..0x0AFF -- */\n    Cans, Cans, Cans, Cans, Cans, Cans, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0B00..0x0B0F -- */\n    Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb,\n/* DATA_BLOCK: -- 0x0B10..0x0B1F -- */\n    Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Zzzz,\n/* DATA_BLOCK: -- 0x0B20..0x0B2F -- */\n    Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0B30..0x0B3F -- */\n    Limb, Zzzz, Zzzz, Zzzz, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb,\n/* DATA_BLOCK: -- 0x0B40..0x0B4F -- */\n    Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale,\n/* DATA_BLOCK: -- 0x0B50..0x0B5F -- */\n    Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Tale, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0B60..0x0B6F -- */\n    Tale, Tale, Tale, Tale, Tale, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0B70..0x0B7F -- */\n    Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu,\n/* DATA_BLOCK: -- 0x0B80..0x0B8F -- */\n    Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0B90..0x0B9F -- */\n    Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0BA0..0x0BAF -- */\n    Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Talu, Zzzz, Zzzz, Zzzz, Talu, Talu,\n/* DATA_BLOCK: -- 0x0BB0..0x0BBF -- */\n    Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi,\n/* DATA_BLOCK: -- 0x0BC0..0x0BCF -- */\n    Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Bugi, Zzzz, Zzzz, Bugi, Bugi,\n/* DATA_BLOCK: -- 0x0BD0..0x0BDF -- */\n    Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana,\n/* DATA_BLOCK: -- 0x0BE0..0x0BEF -- */\n    Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Zzzz,\n/* DATA_BLOCK: -- 0x0BF0..0x0BFF -- */\n    Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Zzzz, Zzzz, Lana,\n/* DATA_BLOCK: -- 0x0C00..0x0C0F -- */\n    Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0C10..0x0C1F -- */\n    Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Lana, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0C20..0x0C2F -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0C30..0x0C3F -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0C40..0x0C4F -- */\n    Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali,\n/* DATA_BLOCK: -- 0x0C50..0x0C5F -- */\n    Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Bali, Zzzz, Bali, Bali,\n/* DATA_BLOCK: -- 0x0C60..0x0C6F -- */\n    Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund,\n/* DATA_BLOCK: -- 0x0C70..0x0C7F -- */\n    Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk, Batk,\n/* DATA_BLOCK: -- 0x0C80..0x0C8F -- */\n    Batk, Batk, Batk, Batk, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Batk, Batk, Batk, Batk,\n/* DATA_BLOCK: -- 0x0C90..0x0C9F -- */\n    Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc,\n/* DATA_BLOCK: -- 0x0CA0..0x0CAF -- */\n    Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Zzzz, Zzzz, Zzzz, Lepc, Lepc, Lepc, Lepc, Lepc,\n/* DATA_BLOCK: -- 0x0CB0..0x0CBF -- */\n    Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Lepc, Zzzz, Zzzz, Zzzz, Lepc, Lepc, Lepc,\n/* DATA_BLOCK: -- 0x0CC0..0x0CCF -- */\n    Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck, Olck,\n/* DATA_BLOCK: -- 0x0CD0..0x0CDF -- */\n    Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0CE0..0x0CEF -- */\n    Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Geor, Zzzz, Zzzz, Geor, Geor, Geor,\n/* DATA_BLOCK: -- 0x0CF0..0x0CFF -- */\n    Sund, Sund, Sund, Sund, Sund, Sund, Sund, Sund, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0D00..0x0D0F -- */\n    Zinh, Zinh, Zinh, Zyyy, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh,\n/* DATA_BLOCK: -- 0x0D10..0x0D1F -- */\n    Zinh, Zyyy, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0D20..0x0D2F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zyyy, Zyyy, Zyyy, Zinh, Zinh, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0D30..0x0D3F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Grek, Grek, Grek, Grek, Grek, Cyrl, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0D40..0x0D4F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Grek, Grek, Grek,\n/* DATA_BLOCK: -- 0x0D50..0x0D5F -- */\n    Grek, Grek, Latn, Latn, Latn, Latn, Grek, Grek, Grek, Grek, Grek, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0D60..0x0D6F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Cyrl, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x0D70..0x0D7F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Grek,\n/* DATA_BLOCK: -- 0x0D80..0x0D8F -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Zzzz, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0D90..0x0D9F -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Grek, Zzzz, Grek, Zzzz, Grek, Zzzz, Grek,\n/* DATA_BLOCK: -- 0x0DA0..0x0DAF -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0DB0..0x0DBF -- */\n    Grek, Grek, Grek, Grek, Grek, Zzzz, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek,\n/* DATA_BLOCK: -- 0x0DC0..0x0DCF -- */\n    Grek, Grek, Grek, Grek, Zzzz, Zzzz, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Grek, Grek, Grek,\n/* DATA_BLOCK: -- 0x0DD0..0x0DDF -- */\n    Zzzz, Zzzz, Grek, Grek, Grek, Zzzz, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz,\n/* DATA_BLOCK: -- 0x0DE0..0x0DEF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zinh, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0DF0..0x0DFF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0E00..0x0E0F -- */\n    Zyyy, Latn, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Latn,\n/* DATA_BLOCK: -- 0x0E10..0x0E1F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz,\n/* DATA_BLOCK: -- 0x0E20..0x0E2F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0E30..0x0E3F -- */\n    Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0E40..0x0E4F -- */\n    Zinh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0E50..0x0E5F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Grek, Zyyy, Zyyy, Zyyy, Latn, Latn, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0E60..0x0E6F -- */\n    Zyyy, Zyyy, Latn, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0E70..0x0E7F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Latn, Zyyy,\n/* DATA_BLOCK: -- 0x0E80..0x0E8F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0E90..0x0E9F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0EA0..0x0EAF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0EB0..0x0EBF -- */\n    Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai, Brai,\n/* DATA_BLOCK: -- 0x0EC0..0x0ECF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0ED0..0x0EDF -- */\n    Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag,\n/* DATA_BLOCK: -- 0x0EE0..0x0EEF -- */\n    Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt, Copt,\n/* DATA_BLOCK: -- 0x0EF0..0x0EFF -- */\n    Copt, Copt, Copt, Copt, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Copt, Copt, Copt, Copt, Copt, Copt, Copt,\n/* DATA_BLOCK: -- 0x0F00..0x0F0F -- */\n    Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng,\n/* DATA_BLOCK: -- 0x0F10..0x0F1F -- */\n    Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Tfng, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Tfng,\n/* DATA_BLOCK: -- 0x0F20..0x0F2F -- */\n    Tfng, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Tfng,\n/* DATA_BLOCK: -- 0x0F30..0x0F3F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0F40..0x0F4F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz,\n/* DATA_BLOCK: -- 0x0F50..0x0F5F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0F60..0x0F6F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani,\n/* DATA_BLOCK: -- 0x0F70..0x0F7F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Hani, Hani, Hani, Hani, Hani,\n/* DATA_BLOCK: -- 0x0F80..0x0F8F -- */\n    Hani, Hani, Hani, Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0F90..0x0F9F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x0FA0..0x0FAF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Hani, Zyyy, Hani, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0FB0..0x0FBF -- */\n    Zyyy, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zinh, Zinh, Zinh, Zinh, Hang, Hang,\n/* DATA_BLOCK: -- 0x0FC0..0x0FCF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Hani, Hani, Hani, Hani, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x0FD0..0x0FDF -- */\n    Zzzz, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira,\n/* DATA_BLOCK: -- 0x0FE0..0x0FEF -- */\n    Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira,\n/* DATA_BLOCK: -- 0x0FF0..0x0FFF -- */\n    Hira, Hira, Hira, Hira, Hira, Hira, Hira, Zzzz, Zzzz, Zinh, Zinh, Zyyy, Zyyy, Hira, Hira, Hira,\n/* DATA_BLOCK: -- 0x1000..0x100F -- */\n    Zyyy, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana,\n/* DATA_BLOCK: -- 0x1010..0x101F -- */\n    Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana,\n/* DATA_BLOCK: -- 0x1020..0x102F -- */\n    Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Zyyy, Zyyy, Kana, Kana, Kana,\n/* DATA_BLOCK: -- 0x1030..0x103F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo,\n/* DATA_BLOCK: -- 0x1040..0x104F -- */\n    Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo, Bopo,\n/* DATA_BLOCK: -- 0x1050..0x105F -- */\n    Zzzz, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang,\n/* DATA_BLOCK: -- 0x1060..0x106F -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz,\n/* DATA_BLOCK: -- 0x1070..0x107F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x1080..0x108F -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Zyyy,\n/* DATA_BLOCK: -- 0x1090..0x109F -- */\n    Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Zyyy,\n/* DATA_BLOCK: -- 0x10A0..0x10AF -- */\n    Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x10B0..0x10BF -- */\n    Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii,\n/* DATA_BLOCK: -- 0x10C0..0x10CF -- */\n    Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x10D0..0x10DF -- */\n    Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Yiii, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x10E0..0x10EF -- */\n    Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu, Lisu,\n/* DATA_BLOCK: -- 0x10F0..0x10FF -- */\n    Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii,\n/* DATA_BLOCK: -- 0x1100..0x110F -- */\n    Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Vaii, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1110..0x111F -- */\n    Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu,\n/* DATA_BLOCK: -- 0x1120..0x112F -- */\n    Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1130..0x113F -- */\n    Zyyy, Zyyy, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x1140..0x114F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zyyy, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x1150..0x115F -- */\n    Zzzz, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x1160..0x116F -- */\n    Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo,\n/* DATA_BLOCK: -- 0x1170..0x117F -- */\n    Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Sylo, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1180..0x118F -- */\n    Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag,\n/* DATA_BLOCK: -- 0x1190..0x119F -- */\n    Phag, Phag, Phag, Phag, Phag, Phag, Phag, Phag, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x11A0..0x11AF -- */\n    Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur,\n/* DATA_BLOCK: -- 0x11B0..0x11BF -- */\n    Saur, Saur, Saur, Saur, Saur, Saur, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Saur, Saur,\n/* DATA_BLOCK: -- 0x11C0..0x11CF -- */\n    Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Saur, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x11D0..0x11DF -- */\n    Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali,\n/* DATA_BLOCK: -- 0x11E0..0x11EF -- */\n    Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Kali, Zyyy, Kali,\n/* DATA_BLOCK: -- 0x11F0..0x11FF -- */\n    Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng, Rjng,\n/* DATA_BLOCK: -- 0x1200..0x120F -- */\n    Rjng, Rjng, Rjng, Rjng, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Rjng,\n/* DATA_BLOCK: -- 0x1210..0x121F -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1220..0x122F -- */\n    Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java,\n/* DATA_BLOCK: -- 0x1230..0x123F -- */\n    Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x1240..0x124F -- */\n    Java, Java, Java, Java, Java, Java, Java, Java, Java, Java, Zzzz, Zzzz, Zzzz, Zzzz, Java, Java,\n/* DATA_BLOCK: -- 0x1250..0x125F -- */\n    Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Mymr, Zzzz,\n/* DATA_BLOCK: -- 0x1260..0x126F -- */\n    Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham,\n/* DATA_BLOCK: -- 0x1270..0x127F -- */\n    Cham, Cham, Cham, Cham, Cham, Cham, Cham, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1280..0x128F -- */\n    Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1290..0x129F -- */\n    Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Cham, Zzzz, Zzzz, Cham, Cham, Cham, Cham,\n/* DATA_BLOCK: -- 0x12A0..0x12AF -- */\n    Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt, Tavt,\n/* DATA_BLOCK: -- 0x12B0..0x12BF -- */\n    Tavt, Tavt, Tavt, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x12C0..0x12CF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Tavt, Tavt, Tavt, Tavt, Tavt,\n/* DATA_BLOCK: -- 0x12D0..0x12DF -- */\n    Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei,\n/* DATA_BLOCK: -- 0x12E0..0x12EF -- */\n    Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x12F0..0x12FF -- */\n    Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz,\n/* DATA_BLOCK: -- 0x1300..0x130F -- */\n    Zzzz, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1310..0x131F -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zyyy, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x1320..0x132F -- */\n    Latn, Latn, Latn, Latn, Latn, Grek, Latn, Latn, Latn, Latn, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1330..0x133F -- */\n    Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1340..0x134F -- */\n    Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Mtei, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1350..0x135F -- */\n    Hang, Hang, Hang, Hang, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1360..0x136F -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz, Zzzz, Zzzz, Zzzz, Hang, Hang, Hang, Hang, Hang,\n/* DATA_BLOCK: -- 0x1370..0x137F -- */\n    Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1380..0x138F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1390..0x139F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x13A0..0x13AF -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x13B0..0x13BF -- */\n    Zzzz, Zzzz, Zzzz, Armn, Armn, Armn, Armn, Armn, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Hebr, Hebr, Hebr,\n/* DATA_BLOCK: -- 0x13C0..0x13CF -- */\n    Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Zzzz, Hebr, Hebr, Hebr, Hebr, Hebr, Zzzz, Hebr, Zzzz,\n/* DATA_BLOCK: -- 0x13D0..0x13DF -- */\n    Hebr, Hebr, Zzzz, Hebr, Hebr, Zzzz, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr, Hebr,\n/* DATA_BLOCK: -- 0x13E0..0x13EF -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x13F0..0x13FF -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Cyrl, Cyrl,\n/* DATA_BLOCK: -- 0x1400..0x140F -- */\n    Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x1410..0x141F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1420..0x142F -- */\n    Arab, Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x1430..0x143F -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x1440..0x144F -- */\n    Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x1450..0x145F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana,\n/* DATA_BLOCK: -- 0x1460..0x146F -- */\n    Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x1470..0x147F -- */\n    Zzzz, Zzzz, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz, Zzzz, Hang, Hang, Hang, Hang, Hang, Hang,\n/* DATA_BLOCK: -- 0x1480..0x148F -- */\n    Zzzz, Zzzz, Hang, Hang, Hang, Hang, Hang, Hang, Zzzz, Zzzz, Hang, Hang, Hang, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1490..0x149F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz,\n/* DATA_BLOCK: -- 0x14A0..0x14AF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x14B0..0x14BF -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Zzzz, Linb, Linb, Linb,\n/* DATA_BLOCK: -- 0x14C0..0x14CF -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb,\n/* DATA_BLOCK: -- 0x14D0..0x14DF -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Zzzz, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb,\n/* DATA_BLOCK: -- 0x14E0..0x14EF -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Zzzz, Linb, Linb, Zzzz, Linb,\n/* DATA_BLOCK: -- 0x14F0..0x14FF -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1500..0x150F -- */\n    Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Linb, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1510..0x151F -- */\n    Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x1520..0x152F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x1530..0x153F -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Grek, Zzzz,\n/* DATA_BLOCK: -- 0x1540..0x154F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1550..0x155F -- */\n    Grek, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1560..0x156F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1570..0x157F -- */\n    Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci,\n/* DATA_BLOCK: -- 0x1580..0x158F -- */\n    Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Lyci, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1590..0x159F -- */\n    Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari, Cari,\n/* DATA_BLOCK: -- 0x15A0..0x15AF -- */\n    Cari, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x15B0..0x15BF -- */\n    Zinh, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x15C0..0x15CF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x15D0..0x15DF -- */\n    Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital, Ital,\n/* DATA_BLOCK: -- 0x15E0..0x15EF -- */\n    Ital, Ital, Ital, Ital, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Ital, Ital, Ital,\n/* DATA_BLOCK: -- 0x15F0..0x15FF -- */\n    Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth,\n/* DATA_BLOCK: -- 0x1600..0x160F -- */\n    Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Goth, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1610..0x161F -- */\n    Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm,\n/* DATA_BLOCK: -- 0x1620..0x162F -- */\n    Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Perm, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1630..0x163F -- */\n    Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar,\n/* DATA_BLOCK: -- 0x1640..0x164F -- */\n    Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Ugar, Zzzz, Ugar,\n/* DATA_BLOCK: -- 0x1650..0x165F -- */\n    Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo,\n/* DATA_BLOCK: -- 0x1660..0x166F -- */\n    Xpeo, Xpeo, Xpeo, Xpeo, Zzzz, Zzzz, Zzzz, Zzzz, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo,\n/* DATA_BLOCK: -- 0x1670..0x167F -- */\n    Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Xpeo, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1680..0x168F -- */\n    Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt, Dsrt,\n/* DATA_BLOCK: -- 0x1690..0x169F -- */\n    Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw, Shaw,\n/* DATA_BLOCK: -- 0x16A0..0x16AF -- */\n    Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma,\n/* DATA_BLOCK: -- 0x16B0..0x16BF -- */\n    Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x16C0..0x16CF -- */\n    Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Osma, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x16D0..0x16DF -- */\n    Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge,\n/* DATA_BLOCK: -- 0x16E0..0x16EF -- */\n    Osge, Osge, Osge, Osge, Zzzz, Zzzz, Zzzz, Zzzz, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge,\n/* DATA_BLOCK: -- 0x16F0..0x16FF -- */\n    Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Osge, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1700..0x170F -- */\n    Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba,\n/* DATA_BLOCK: -- 0x1710..0x171F -- */\n    Elba, Elba, Elba, Elba, Elba, Elba, Elba, Elba, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1720..0x172F -- */\n    Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb, Aghb,\n/* DATA_BLOCK: -- 0x1730..0x173F -- */\n    Aghb, Aghb, Aghb, Aghb, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Aghb,\n/* DATA_BLOCK: -- 0x1740..0x174F -- */\n    Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Zzzz, Vith, Vith, Vith, Vith,\n/* DATA_BLOCK: -- 0x1750..0x175F -- */\n    Vith, Vith, Vith, Zzzz, Vith, Vith, Zzzz, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith,\n/* DATA_BLOCK: -- 0x1760..0x176F -- */\n    Vith, Vith, Zzzz, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Vith,\n/* DATA_BLOCK: -- 0x1770..0x177F -- */\n    Vith, Vith, Zzzz, Vith, Vith, Vith, Vith, Vith, Vith, Vith, Zzzz, Vith, Vith, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1780..0x178F -- */\n    Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr, Todr,\n/* DATA_BLOCK: -- 0x1790..0x179F -- */\n    Todr, Todr, Todr, Todr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x17A0..0x17AF -- */\n    Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina,\n/* DATA_BLOCK: -- 0x17B0..0x17BF -- */\n    Lina, Lina, Lina, Lina, Lina, Lina, Lina, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x17C0..0x17CF -- */\n    Lina, Lina, Lina, Lina, Lina, Lina, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x17D0..0x17DF -- */\n    Lina, Lina, Lina, Lina, Lina, Lina, Lina, Lina, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x17E0..0x17EF -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Zzzz, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn,\n/* DATA_BLOCK: -- 0x17F0..0x17FF -- */\n    Latn, Zzzz, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1800..0x180F -- */\n    Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Zzzz, Zzzz, Cprt, Zzzz, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt,\n/* DATA_BLOCK: -- 0x1810..0x181F -- */\n    Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Cprt,\n/* DATA_BLOCK: -- 0x1820..0x182F -- */\n    Cprt, Cprt, Cprt, Cprt, Cprt, Cprt, Zzzz, Cprt, Cprt, Zzzz, Zzzz, Zzzz, Cprt, Zzzz, Zzzz, Cprt,\n/* DATA_BLOCK: -- 0x1830..0x183F -- */\n    Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi,\n/* DATA_BLOCK: -- 0x1840..0x184F -- */\n    Armi, Armi, Armi, Armi, Armi, Armi, Zzzz, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi, Armi,\n/* DATA_BLOCK: -- 0x1850..0x185F -- */\n    Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm, Palm,\n/* DATA_BLOCK: -- 0x1860..0x186F -- */\n    Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat,\n/* DATA_BLOCK: -- 0x1870..0x187F -- */\n    Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Zzzz,\n/* DATA_BLOCK: -- 0x1880..0x188F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat, Nbat,\n/* DATA_BLOCK: -- 0x1890..0x189F -- */\n    Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr, Hatr,\n/* DATA_BLOCK: -- 0x18A0..0x18AF -- */\n    Hatr, Hatr, Hatr, Zzzz, Hatr, Hatr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Hatr, Hatr, Hatr, Hatr, Hatr,\n/* DATA_BLOCK: -- 0x18B0..0x18BF -- */\n    Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx,\n/* DATA_BLOCK: -- 0x18C0..0x18CF -- */\n    Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Phnx, Zzzz, Zzzz, Zzzz, Phnx,\n/* DATA_BLOCK: -- 0x18D0..0x18DF -- */\n    Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi,\n/* DATA_BLOCK: -- 0x18E0..0x18EF -- */\n    Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Lydi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Lydi,\n/* DATA_BLOCK: -- 0x18F0..0x18FF -- */\n    Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt,\n/* DATA_BLOCK: -- 0x1900..0x190F -- */\n    Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Sidt, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1910..0x191F -- */\n    Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero, Mero,\n/* DATA_BLOCK: -- 0x1920..0x192F -- */\n    Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc,\n/* DATA_BLOCK: -- 0x1930..0x193F -- */\n    Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Zzzz, Zzzz, Zzzz, Zzzz, Merc, Merc, Merc, Merc,\n/* DATA_BLOCK: -- 0x1940..0x194F -- */\n    Zzzz, Zzzz, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc, Merc,\n/* DATA_BLOCK: -- 0x1950..0x195F -- */\n    Khar, Khar, Khar, Khar, Zzzz, Khar, Khar, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Khar, Khar, Khar, Khar,\n/* DATA_BLOCK: -- 0x1960..0x196F -- */\n    Khar, Khar, Khar, Khar, Zzzz, Khar, Khar, Khar, Zzzz, Khar, Khar, Khar, Khar, Khar, Khar, Khar,\n/* DATA_BLOCK: -- 0x1970..0x197F -- */\n    Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar,\n/* DATA_BLOCK: -- 0x1980..0x198F -- */\n    Khar, Khar, Khar, Khar, Khar, Khar, Zzzz, Zzzz, Khar, Khar, Khar, Zzzz, Zzzz, Zzzz, Zzzz, Khar,\n/* DATA_BLOCK: -- 0x1990..0x199F -- */\n    Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Khar, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x19A0..0x19AF -- */\n    Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb, Sarb,\n/* DATA_BLOCK: -- 0x19B0..0x19BF -- */\n    Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb, Narb,\n/* DATA_BLOCK: -- 0x19C0..0x19CF -- */\n    Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani, Mani,\n/* DATA_BLOCK: -- 0x19D0..0x19DF -- */\n    Mani, Mani, Mani, Mani, Mani, Mani, Mani, Zzzz, Zzzz, Zzzz, Zzzz, Mani, Mani, Mani, Mani, Mani,\n/* DATA_BLOCK: -- 0x19E0..0x19EF -- */\n    Mani, Mani, Mani, Mani, Mani, Mani, Mani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x19F0..0x19FF -- */\n    Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst, Avst,\n/* DATA_BLOCK: -- 0x1A00..0x1A0F -- */\n    Avst, Avst, Avst, Avst, Avst, Avst, Zzzz, Zzzz, Zzzz, Avst, Avst, Avst, Avst, Avst, Avst, Avst,\n/* DATA_BLOCK: -- 0x1A10..0x1A1F -- */\n    Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti,\n/* DATA_BLOCK: -- 0x1A20..0x1A2F -- */\n    Prti, Prti, Prti, Prti, Prti, Prti, Zzzz, Zzzz, Prti, Prti, Prti, Prti, Prti, Prti, Prti, Prti,\n/* DATA_BLOCK: -- 0x1A30..0x1A3F -- */\n    Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli,\n/* DATA_BLOCK: -- 0x1A40..0x1A4F -- */\n    Phli, Phli, Phli, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Phli, Phli, Phli, Phli, Phli, Phli, Phli, Phli,\n/* DATA_BLOCK: -- 0x1A50..0x1A5F -- */\n    Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp,\n/* DATA_BLOCK: -- 0x1A60..0x1A6F -- */\n    Phlp, Phlp, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Phlp, Phlp, Phlp, Phlp, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1A70..0x1A7F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp, Phlp,\n/* DATA_BLOCK: -- 0x1A80..0x1A8F -- */\n    Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh,\n/* DATA_BLOCK: -- 0x1A90..0x1A9F -- */\n    Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Orkh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1AA0..0x1AAF -- */\n    Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung, Hung,\n/* DATA_BLOCK: -- 0x1AB0..0x1ABF -- */\n    Hung, Hung, Hung, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1AC0..0x1ACF -- */\n    Hung, Hung, Hung, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Hung, Hung, Hung, Hung, Hung, Hung,\n/* DATA_BLOCK: -- 0x1AD0..0x1ADF -- */\n    Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg,\n/* DATA_BLOCK: -- 0x1AE0..0x1AEF -- */\n    Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1AF0..0x1AFF -- */\n    Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Rohg, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1B00..0x1B0F -- */\n    Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara, Gara,\n/* DATA_BLOCK: -- 0x1B10..0x1B1F -- */\n    Gara, Gara, Gara, Gara, Gara, Gara, Zzzz, Zzzz, Zzzz, Gara, Gara, Gara, Gara, Gara, Gara, Gara,\n/* DATA_BLOCK: -- 0x1B20..0x1B2F -- */\n    Gara, Gara, Gara, Gara, Gara, Gara, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Gara, Gara,\n/* DATA_BLOCK: -- 0x1B30..0x1B3F -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz,\n/* DATA_BLOCK: -- 0x1B40..0x1B4F -- */\n    Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi,\n/* DATA_BLOCK: -- 0x1B50..0x1B5F -- */\n    Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Yezi, Zzzz, Yezi, Yezi, Yezi, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1B60..0x1B6F -- */\n    Yezi, Yezi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1B70..0x1B7F -- */\n    Zzzz, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1B80..0x1B8F -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1B90..0x1B9F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x1BA0..0x1BAF -- */\n    Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo,\n/* DATA_BLOCK: -- 0x1BB0..0x1BBF -- */\n    Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Sogo, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1BC0..0x1BCF -- */\n    Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd,\n/* DATA_BLOCK: -- 0x1BD0..0x1BDF -- */\n    Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Sogd, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1BE0..0x1BEF -- */\n    Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr,\n/* DATA_BLOCK: -- 0x1BF0..0x1BFF -- */\n    Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Ougr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1C00..0x1C0F -- */\n    Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs,\n/* DATA_BLOCK: -- 0x1C10..0x1C1F -- */\n    Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Chrs, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1C20..0x1C2F -- */\n    Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym, Elym,\n/* DATA_BLOCK: -- 0x1C30..0x1C3F -- */\n    Elym, Elym, Elym, Elym, Elym, Elym, Elym, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1C40..0x1C4F -- */\n    Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah,\n/* DATA_BLOCK: -- 0x1C50..0x1C5F -- */\n    Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1C60..0x1C6F -- */\n    Zzzz, Zzzz, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah, Brah,\n/* DATA_BLOCK: -- 0x1C70..0x1C7F -- */\n    Brah, Brah, Brah, Brah, Brah, Brah, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Brah,\n/* DATA_BLOCK: -- 0x1C80..0x1C8F -- */\n    Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi, Kthi,\n/* DATA_BLOCK: -- 0x1C90..0x1C9F -- */\n    Kthi, Kthi, Kthi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Kthi, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1CA0..0x1CAF -- */\n    Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora,\n/* DATA_BLOCK: -- 0x1CB0..0x1CBF -- */\n    Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1CC0..0x1CCF -- */\n    Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Sora, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1CD0..0x1CDF -- */\n    Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm,\n/* DATA_BLOCK: -- 0x1CE0..0x1CEF -- */\n    Cakm, Cakm, Cakm, Cakm, Cakm, Zzzz, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm,\n/* DATA_BLOCK: -- 0x1CF0..0x1CFF -- */\n    Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Cakm, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1D00..0x1D0F -- */\n    Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj,\n/* DATA_BLOCK: -- 0x1D10..0x1D1F -- */\n    Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Mahj, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1D20..0x1D2F -- */\n    Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd,\n/* DATA_BLOCK: -- 0x1D30..0x1D3F -- */\n    Zzzz, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh, Sinh,\n/* DATA_BLOCK: -- 0x1D40..0x1D4F -- */\n    Sinh, Sinh, Sinh, Sinh, Sinh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1D50..0x1D5F -- */\n    Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj,\n/* DATA_BLOCK: -- 0x1D60..0x1D6F -- */\n    Khoj, Khoj, Zzzz, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj, Khoj,\n/* DATA_BLOCK: -- 0x1D70..0x1D7F -- */\n    Khoj, Khoj, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1D80..0x1D8F -- */\n    Mult, Mult, Mult, Mult, Mult, Mult, Mult, Zzzz, Mult, Zzzz, Mult, Mult, Mult, Mult, Zzzz, Mult,\n/* DATA_BLOCK: -- 0x1D90..0x1D9F -- */\n    Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Zzzz, Mult,\n/* DATA_BLOCK: -- 0x1DA0..0x1DAF -- */\n    Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Mult, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1DB0..0x1DBF -- */\n    Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind,\n/* DATA_BLOCK: -- 0x1DC0..0x1DCF -- */\n    Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1DD0..0x1DDF -- */\n    Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Sind, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1DE0..0x1DEF -- */\n    Gran, Gran, Gran, Gran, Zzzz, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Zzzz, Zzzz, Gran,\n/* DATA_BLOCK: -- 0x1DF0..0x1DFF -- */\n    Gran, Zzzz, Zzzz, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran,\n/* DATA_BLOCK: -- 0x1E00..0x1E0F -- */\n    Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Zzzz, Gran, Gran, Gran, Gran, Gran, Gran,\n/* DATA_BLOCK: -- 0x1E10..0x1E1F -- */\n    Gran, Zzzz, Gran, Gran, Zzzz, Gran, Gran, Gran, Gran, Gran, Zzzz, Zinh, Gran, Gran, Gran, Gran,\n/* DATA_BLOCK: -- 0x1E20..0x1E2F -- */\n    Gran, Gran, Gran, Gran, Gran, Zzzz, Zzzz, Gran, Gran, Zzzz, Zzzz, Gran, Gran, Gran, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1E30..0x1E3F -- */\n    Gran, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Gran, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Gran, Gran, Gran,\n/* DATA_BLOCK: -- 0x1E40..0x1E4F -- */\n    Gran, Gran, Gran, Gran, Zzzz, Zzzz, Gran, Gran, Gran, Gran, Gran, Gran, Gran, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1E50..0x1E5F -- */\n    Gran, Gran, Gran, Gran, Gran, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1E60..0x1E6F -- */\n    Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Zzzz, Tutg, Zzzz, Zzzz, Tutg, Zzzz,\n/* DATA_BLOCK: -- 0x1E70..0x1E7F -- */\n    Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg,\n/* DATA_BLOCK: -- 0x1E80..0x1E8F -- */\n    Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Zzzz, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Tutg,\n/* DATA_BLOCK: -- 0x1E90..0x1E9F -- */\n    Tutg, Zzzz, Tutg, Zzzz, Zzzz, Tutg, Zzzz, Tutg, Tutg, Tutg, Tutg, Zzzz, Tutg, Tutg, Tutg, Tutg,\n/* DATA_BLOCK: -- 0x1EA0..0x1EAF -- */\n    Tutg, Tutg, Tutg, Tutg, Tutg, Tutg, Zzzz, Tutg, Tutg, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1EB0..0x1EBF -- */\n    Zzzz, Tutg, Tutg, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1EC0..0x1ECF -- */\n    Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa,\n/* DATA_BLOCK: -- 0x1ED0..0x1EDF -- */\n    Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Newa, Zzzz, Newa, Newa, Newa,\n/* DATA_BLOCK: -- 0x1EE0..0x1EEF -- */\n    Newa, Newa, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1EF0..0x1EFF -- */\n    Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh,\n/* DATA_BLOCK: -- 0x1F00..0x1F0F -- */\n    Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F10..0x1F1F -- */\n    Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Tirh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F20..0x1F2F -- */\n    Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd,\n/* DATA_BLOCK: -- 0x1F30..0x1F3F -- */\n    Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Zzzz, Zzzz, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd,\n/* DATA_BLOCK: -- 0x1F40..0x1F4F -- */\n    Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Sidd, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F50..0x1F5F -- */\n    Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi,\n/* DATA_BLOCK: -- 0x1F60..0x1F6F -- */\n    Modi, Modi, Modi, Modi, Modi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F70..0x1F7F -- */\n    Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Modi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F80..0x1F8F -- */\n    Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Mong, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1F90..0x1F9F -- */\n    Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr,\n/* DATA_BLOCK: -- 0x1FA0..0x1FAF -- */\n    Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Takr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1FB0..0x1FBF -- */\n    Mymr, Mymr, Mymr, Mymr, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1FC0..0x1FCF -- */\n    Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom,\n/* DATA_BLOCK: -- 0x1FD0..0x1FDF -- */\n    Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Zzzz, Zzzz, Ahom, Ahom, Ahom,\n/* DATA_BLOCK: -- 0x1FE0..0x1FEF -- */\n    Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x1FF0..0x1FFF -- */\n    Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Ahom, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2000..0x200F -- */\n    Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr,\n/* DATA_BLOCK: -- 0x2010..0x201F -- */\n    Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Dogr, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2020..0x202F -- */\n    Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara, Wara,\n/* DATA_BLOCK: -- 0x2030..0x203F -- */\n    Wara, Wara, Wara, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Wara,\n/* DATA_BLOCK: -- 0x2040..0x204F -- */\n    Diak, Diak, Diak, Diak, Diak, Diak, Diak, Zzzz, Zzzz, Diak, Zzzz, Zzzz, Diak, Diak, Diak, Diak,\n/* DATA_BLOCK: -- 0x2050..0x205F -- */\n    Diak, Diak, Diak, Diak, Zzzz, Diak, Diak, Zzzz, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak,\n/* DATA_BLOCK: -- 0x2060..0x206F -- */\n    Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak,\n/* DATA_BLOCK: -- 0x2070..0x207F -- */\n    Diak, Diak, Diak, Diak, Diak, Diak, Zzzz, Diak, Diak, Zzzz, Zzzz, Diak, Diak, Diak, Diak, Diak,\n/* DATA_BLOCK: -- 0x2080..0x208F -- */\n    Diak, Diak, Diak, Diak, Diak, Diak, Diak, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2090..0x209F -- */\n    Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Diak, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x20A0..0x20AF -- */\n    Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Zzzz, Zzzz, Nand, Nand, Nand, Nand, Nand, Nand,\n/* DATA_BLOCK: -- 0x20B0..0x20BF -- */\n    Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand, Nand,\n/* DATA_BLOCK: -- 0x20C0..0x20CF -- */\n    Nand, Nand, Nand, Nand, Nand, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x20D0..0x20DF -- */\n    Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb,\n/* DATA_BLOCK: -- 0x20E0..0x20EF -- */\n    Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zanb, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x20F0..0x20FF -- */\n    Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo, Soyo,\n/* DATA_BLOCK: -- 0x2100..0x210F -- */\n    Soyo, Soyo, Soyo, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2110..0x211F -- */\n    Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc,\n/* DATA_BLOCK: -- 0x2120..0x212F -- */\n    Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Pauc, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2130..0x213F -- */\n    Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Deva, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2140..0x214F -- */\n    Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Shrd, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2150..0x215F -- */\n    Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu,\n/* DATA_BLOCK: -- 0x2160..0x216F -- */\n    Sunu, Sunu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2170..0x217F -- */\n    Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Sunu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2180..0x218F -- */\n    Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Zzzz, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks,\n/* DATA_BLOCK: -- 0x2190..0x219F -- */\n    Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks,\n/* DATA_BLOCK: -- 0x21A0..0x21AF -- */\n    Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Zzzz, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks,\n/* DATA_BLOCK: -- 0x21B0..0x21BF -- */\n    Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x21C0..0x21CF -- */\n    Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Bhks, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x21D0..0x21DF -- */\n    Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc,\n/* DATA_BLOCK: -- 0x21E0..0x21EF -- */\n    Zzzz, Zzzz, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc,\n/* DATA_BLOCK: -- 0x21F0..0x21FF -- */\n    Marc, Marc, Marc, Marc, Marc, Marc, Marc, Marc, Zzzz, Marc, Marc, Marc, Marc, Marc, Marc, Marc,\n/* DATA_BLOCK: -- 0x2200..0x220F -- */\n    Marc, Marc, Marc, Marc, Marc, Marc, Marc, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2210..0x221F -- */\n    Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Zzzz, Gonm, Gonm, Zzzz, Gonm, Gonm, Gonm, Gonm, Gonm,\n/* DATA_BLOCK: -- 0x2220..0x222F -- */\n    Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm,\n/* DATA_BLOCK: -- 0x2230..0x223F -- */\n    Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Zzzz, Zzzz, Zzzz, Gonm, Zzzz, Gonm, Gonm, Zzzz, Gonm,\n/* DATA_BLOCK: -- 0x2240..0x224F -- */\n    Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2250..0x225F -- */\n    Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Gonm, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2260..0x226F -- */\n    Gong, Gong, Gong, Gong, Gong, Gong, Zzzz, Gong, Gong, Zzzz, Gong, Gong, Gong, Gong, Gong, Gong,\n/* DATA_BLOCK: -- 0x2270..0x227F -- */\n    Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong,\n/* DATA_BLOCK: -- 0x2280..0x228F -- */\n    Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Zzzz,\n/* DATA_BLOCK: -- 0x2290..0x229F -- */\n    Gong, Gong, Zzzz, Gong, Gong, Gong, Gong, Gong, Gong, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x22A0..0x22AF -- */\n    Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Gong, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x22B0..0x22BF -- */\n    Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols,\n/* DATA_BLOCK: -- 0x22C0..0x22CF -- */\n    Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x22D0..0x22DF -- */\n    Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Tols, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x22E0..0x22EF -- */\n    Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka,\n/* DATA_BLOCK: -- 0x22F0..0x22FF -- */\n    Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Maka, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2300..0x230F -- */\n    Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi,\n/* DATA_BLOCK: -- 0x2310..0x231F -- */\n    Kawi, Zzzz, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi,\n/* DATA_BLOCK: -- 0x2320..0x232F -- */\n    Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Zzzz, Zzzz, Zzzz, Kawi, Kawi,\n/* DATA_BLOCK: -- 0x2330..0x233F -- */\n    Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Kawi, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2340..0x234F -- */\n    Lisu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2350..0x235F -- */\n    Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml, Taml,\n/* DATA_BLOCK: -- 0x2360..0x236F -- */\n    Taml, Taml, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Taml,\n/* DATA_BLOCK: -- 0x2370..0x237F -- */\n    Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux,\n/* DATA_BLOCK: -- 0x2380..0x238F -- */\n    Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2390..0x239F -- */\n    Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Xsux, Zzzz,\n/* DATA_BLOCK: -- 0x23A0..0x23AF -- */\n    Xsux, Xsux, Xsux, Xsux, Xsux, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x23B0..0x23BF -- */\n    Xsux, Xsux, Xsux, Xsux, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x23C0..0x23CF -- */\n    Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn, Cpmn,\n/* DATA_BLOCK: -- 0x23D0..0x23DF -- */\n    Cpmn, Cpmn, Cpmn, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x23E0..0x23EF -- */\n    Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp,\n/* DATA_BLOCK: -- 0x23F0..0x23FF -- */\n    Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2400..0x240F -- */\n    Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Egyp, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2410..0x241F -- */\n    Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw,\n/* DATA_BLOCK: -- 0x2420..0x242F -- */\n    Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Hluw, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2430..0x243F -- */\n    Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh,\n/* DATA_BLOCK: -- 0x2440..0x244F -- */\n    Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Gukh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2450..0x245F -- */\n    Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Bamu, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2460..0x246F -- */\n    Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo,\n/* DATA_BLOCK: -- 0x2470..0x247F -- */\n    Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Zzzz,\n/* DATA_BLOCK: -- 0x2480..0x248F -- */\n    Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Mroo, Zzzz, Zzzz, Zzzz, Zzzz, Mroo, Mroo,\n/* DATA_BLOCK: -- 0x2490..0x249F -- */\n    Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa,\n/* DATA_BLOCK: -- 0x24A0..0x24AF -- */\n    Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Zzzz,\n/* DATA_BLOCK: -- 0x24B0..0x24BF -- */\n    Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Tnsa, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x24C0..0x24CF -- */\n    Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass,\n/* DATA_BLOCK: -- 0x24D0..0x24DF -- */\n    Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Bass, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x24E0..0x24EF -- */\n    Bass, Bass, Bass, Bass, Bass, Bass, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x24F0..0x24FF -- */\n    Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng,\n/* DATA_BLOCK: -- 0x2500..0x250F -- */\n    Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2510..0x251F -- */\n    Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Zzzz, Hmng, Hmng, Hmng, Hmng, Hmng,\n/* DATA_BLOCK: -- 0x2520..0x252F -- */\n    Hmng, Hmng, Zzzz, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng,\n/* DATA_BLOCK: -- 0x2530..0x253F -- */\n    Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Hmng, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Hmng, Hmng, Hmng,\n/* DATA_BLOCK: -- 0x2540..0x254F -- */\n    Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai,\n/* DATA_BLOCK: -- 0x2550..0x255F -- */\n    Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Krai, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2560..0x256F -- */\n    Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf,\n/* DATA_BLOCK: -- 0x2570..0x257F -- */\n    Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Medf, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2580..0x258F -- */\n    Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf,\n/* DATA_BLOCK: -- 0x2590..0x259F -- */\n    Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Berf, Zzzz, Zzzz, Berf, Berf, Berf, Berf, Berf,\n/* DATA_BLOCK: -- 0x25A0..0x25AF -- */\n    Berf, Berf, Berf, Berf, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x25B0..0x25BF -- */\n    Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd,\n/* DATA_BLOCK: -- 0x25C0..0x25CF -- */\n    Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Zzzz, Zzzz, Zzzz, Zzzz, Plrd,\n/* DATA_BLOCK: -- 0x25D0..0x25DF -- */\n    Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Plrd, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Plrd,\n/* DATA_BLOCK: -- 0x25E0..0x25EF -- */\n    Tang, Nshu, Hani, Hani, Kits, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x25F0..0x25FF -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2600..0x260F -- */\n    Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang,\n/* DATA_BLOCK: -- 0x2610..0x261F -- */\n    Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits, Kits,\n/* DATA_BLOCK: -- 0x2620..0x262F -- */\n    Kits, Kits, Kits, Kits, Kits, Kits, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2630..0x263F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Kits,\n/* DATA_BLOCK: -- 0x2640..0x264F -- */\n    Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Tang, Zzzz,\n/* DATA_BLOCK: -- 0x2650..0x265F -- */\n    Tang, Tang, Tang, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2660..0x266F -- */\n    Kana, Kana, Kana, Kana, Zzzz, Kana, Kana, Kana, Kana, Kana, Kana, Kana, Zzzz, Kana, Kana, Zzzz,\n/* DATA_BLOCK: -- 0x2670..0x267F -- */\n    Kana, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira, Hira,\n/* DATA_BLOCK: -- 0x2680..0x268F -- */\n    Kana, Kana, Kana, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2690..0x269F -- */\n    Zzzz, Zzzz, Hira, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x26A0..0x26AF -- */\n    Hira, Hira, Hira, Zzzz, Zzzz, Kana, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x26B0..0x26BF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Kana, Kana, Kana, Kana, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x26C0..0x26CF -- */\n    Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu,\n/* DATA_BLOCK: -- 0x26D0..0x26DF -- */\n    Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Nshu, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x26E0..0x26EF -- */\n    Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl,\n/* DATA_BLOCK: -- 0x26F0..0x26FF -- */\n    Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2700..0x270F -- */\n    Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2710..0x271F -- */\n    Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2720..0x272F -- */\n    Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Dupl, Zzzz, Zzzz, Dupl, Dupl, Dupl, Dupl,\n/* DATA_BLOCK: -- 0x2730..0x273F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2740..0x274F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2750..0x275F -- */\n    Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2760..0x276F -- */\n    Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2770..0x277F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2780..0x278F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2790..0x279F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zinh, Zinh, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x27A0..0x27AF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zinh, Zinh, Zinh, Zinh,\n/* DATA_BLOCK: -- 0x27B0..0x27BF -- */\n    Zinh, Zinh, Zinh, Zyyy, Zyyy, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zinh, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x27C0..0x27CF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zinh, Zinh, Zinh, Zinh, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x27D0..0x27DF -- */\n    Grek, Grek, Grek, Grek, Grek, Grek, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x27E0..0x27EF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x27F0..0x27FF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2800..0x280F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2810..0x281F -- */\n    Zzzz, Zzzz, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2820..0x282F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2830..0x283F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2840..0x284F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2850..0x285F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2860..0x286F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz,\n/* DATA_BLOCK: -- 0x2870..0x287F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2880..0x288F -- */\n    Zyyy, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2890..0x289F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x28A0..0x28AF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x28B0..0x28BF -- */\n    Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw,\n/* DATA_BLOCK: -- 0x28C0..0x28CF -- */\n    Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x28D0..0x28DF -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw,\n/* DATA_BLOCK: -- 0x28E0..0x28EF -- */\n    Zzzz, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw, Sgnw,\n/* DATA_BLOCK: -- 0x28F0..0x28FF -- */\n    Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Latn, Zzzz,\n/* DATA_BLOCK: -- 0x2900..0x290F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Latn, Latn, Latn, Latn, Latn, Latn, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2910..0x291F -- */\n    Glag, Glag, Glag, Glag, Glag, Glag, Glag, Zzzz, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag,\n/* DATA_BLOCK: -- 0x2920..0x292F -- */\n    Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Glag, Zzzz, Zzzz, Glag, Glag, Glag, Glag, Glag,\n/* DATA_BLOCK: -- 0x2930..0x293F -- */\n    Glag, Glag, Zzzz, Glag, Glag, Zzzz, Glag, Glag, Glag, Glag, Glag, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2940..0x294F -- */\n    Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Cyrl, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2950..0x295F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Cyrl,\n/* DATA_BLOCK: -- 0x2960..0x296F -- */\n    Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp,\n/* DATA_BLOCK: -- 0x2970..0x297F -- */\n    Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2980..0x298F -- */\n    Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2990..0x299F -- */\n    Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Hmnp, Zzzz, Zzzz, Zzzz, Zzzz, Hmnp, Hmnp,\n/* DATA_BLOCK: -- 0x29A0..0x29AF -- */\n    Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto,\n/* DATA_BLOCK: -- 0x29B0..0x29BF -- */\n    Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Toto, Zzzz,\n/* DATA_BLOCK: -- 0x29C0..0x29CF -- */\n    Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho,\n/* DATA_BLOCK: -- 0x29D0..0x29DF -- */\n    Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Wcho, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Wcho,\n/* DATA_BLOCK: -- 0x29E0..0x29EF -- */\n    Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm,\n/* DATA_BLOCK: -- 0x29F0..0x29FF -- */\n    Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Nagm, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2A00..0x2A0F -- */\n    Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao,\n/* DATA_BLOCK: -- 0x2A10..0x2A1F -- */\n    Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Onao, Zzzz, Zzzz, Zzzz, Zzzz, Onao,\n/* DATA_BLOCK: -- 0x2A20..0x2A2F -- */\n    Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo,\n/* DATA_BLOCK: -- 0x2A30..0x2A3F -- */\n    Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Zzzz,\n/* DATA_BLOCK: -- 0x2A40..0x2A4F -- */\n    Tayo, Tayo, Tayo, Tayo, Tayo, Tayo, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Tayo, Tayo,\n/* DATA_BLOCK: -- 0x2A50..0x2A5F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Ethi, Ethi, Ethi, Zzzz, Ethi, Ethi, Zzzz,\n/* DATA_BLOCK: -- 0x2A60..0x2A6F -- */\n    Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Ethi, Zzzz,\n/* DATA_BLOCK: -- 0x2A70..0x2A7F -- */\n    Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend,\n/* DATA_BLOCK: -- 0x2A80..0x2A8F -- */\n    Mend, Mend, Mend, Mend, Mend, Zzzz, Zzzz, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend, Mend,\n/* DATA_BLOCK: -- 0x2A90..0x2A9F -- */\n    Mend, Mend, Mend, Mend, Mend, Mend, Mend, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2AA0..0x2AAF -- */\n    Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm,\n/* DATA_BLOCK: -- 0x2AB0..0x2ABF -- */\n    Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2AC0..0x2ACF -- */\n    Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Adlm, Zzzz, Zzzz, Zzzz, Zzzz, Adlm, Adlm,\n/* DATA_BLOCK: -- 0x2AD0..0x2ADF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2AE0..0x2AEF -- */\n    Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2AF0..0x2AFF -- */\n    Zzzz, Arab, Arab, Zzzz, Arab, Zzzz, Zzzz, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2B00..0x2B0F -- */\n    Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Zzzz, Arab, Zzzz, Arab, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2B10..0x2B1F -- */\n    Zzzz, Zzzz, Arab, Zzzz, Zzzz, Zzzz, Zzzz, Arab, Zzzz, Arab, Zzzz, Arab, Zzzz, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2B20..0x2B2F -- */\n    Zzzz, Arab, Arab, Zzzz, Arab, Zzzz, Zzzz, Arab, Zzzz, Arab, Zzzz, Arab, Zzzz, Arab, Zzzz, Arab,\n/* DATA_BLOCK: -- 0x2B30..0x2B3F -- */\n    Zzzz, Arab, Arab, Zzzz, Arab, Zzzz, Zzzz, Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2B40..0x2B4F -- */\n    Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Zzzz, Arab, Zzzz,\n/* DATA_BLOCK: -- 0x2B50..0x2B5F -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2B60..0x2B6F -- */\n    Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Arab, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2B70..0x2B7F -- */\n    Zzzz, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab, Zzzz, Arab, Arab, Arab, Arab, Arab,\n/* DATA_BLOCK: -- 0x2B80..0x2B8F -- */\n    Arab, Arab, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2B90..0x2B9F -- */\n    Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2BA0..0x2BAF -- */\n    Hira, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2BB0..0x2BBF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2BC0..0x2BCF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2BD0..0x2BDF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2BE0..0x2BEF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy, Zyyy, Zyyy,\n/* DATA_BLOCK: -- 0x2BF0..0x2BFF -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x2C00..0x2C0F -- */\n    Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zyyy,\n/* DATA_BLOCK: -- 0x2C10..0x2C1F -- */\n    Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2C20..0x2C2F -- */\n    Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Hani, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz,\n/* DATA_BLOCK: -- 0x2C30..0x2C3F -- */\n    Zzzz, Zyyy, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz, Zzzz\n};\n\nstatic const SBUInt16 MainScriptIndexes[3391] = {\n/* INDEX_BLOCK: -- 0x0000..0x001F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0010, 0x0020, 0x0010, 0x0020, 0x0000, 0x0000, 0x0030, 0x0030,\n    0x0040, 0x0050, 0x0040, 0x0050, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040,\n    0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040,\n/* INDEX_BLOCK: -- 0x0020..0x003F -- */\n    0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0060,\n    0x0000, 0x0000, 0x0070, 0x0000, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0090,\n    0x00A0, 0x00B0, 0x00C0, 0x00B0, 0x00B0, 0x00B0, 0x00D0, 0x00B0,\n/* INDEX_BLOCK: -- 0x0040..0x005F -- */\n    0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00F0, 0x00E0, 0x00E0, 0x00E0,\n    0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x0100, 0x0110, 0x0120, 0x0110, 0x0110,\n    0x0130, 0x0140, 0x0150, 0x0150, 0x0160, 0x0150, 0x0170, 0x0180,\n/* INDEX_BLOCK: -- 0x0060..0x007F -- */\n    0x0190, 0x01A0, 0x01B0, 0x01B0, 0x01C0, 0x01D0, 0x01B0, 0x01E0, 0x01B0, 0x01B0, 0x01B0, 0x01B0,\n    0x01B0, 0x01F0, 0x01B0, 0x01B0, 0x0200, 0x0210, 0x0210, 0x0210, 0x0220, 0x01B0, 0x01B0, 0x01B0,\n    0x0230, 0x0230, 0x0230, 0x0240, 0x0250, 0x0250, 0x0250, 0x0260,\n/* INDEX_BLOCK: -- 0x0080..0x009F -- */\n    0x0270, 0x0270, 0x0280, 0x0290, 0x02A0, 0x02B0, 0x02C0, 0x01B0, 0x01B0, 0x02D0, 0x01B0, 0x01B0,\n    0x01B0, 0x01B0, 0x02E0, 0x01B0, 0x02F0, 0x02F0, 0x02F0, 0x02F0, 0x02F0, 0x0300, 0x0310, 0x02F0,\n    0x0320, 0x0330, 0x0340, 0x0350, 0x0360, 0x0370, 0x0380, 0x0390,\n/* INDEX_BLOCK: -- 0x00A0..0x00BF -- */\n    0x03A0, 0x03B0, 0x03C0, 0x03D0, 0x03E0, 0x03F0, 0x0400, 0x0410, 0x0420, 0x0430, 0x0440, 0x0450,\n    0x0460, 0x0470, 0x0480, 0x0490, 0x04A0, 0x04B0, 0x04C0, 0x04D0, 0x04E0, 0x04F0, 0x0500, 0x0510,\n    0x0520, 0x0530, 0x0540, 0x0550, 0x0560, 0x0570, 0x0580, 0x0590,\n/* INDEX_BLOCK: -- 0x00C0..0x00DF -- */\n    0x05A0, 0x05B0, 0x05C0, 0x05D0, 0x05E0, 0x05F0, 0x0600, 0x0610, 0x0620, 0x0630, 0x0640, 0x0650,\n    0x0660, 0x0670, 0x0680, 0x0690, 0x06A0, 0x06B0, 0x06C0, 0x06C0, 0x06D0, 0x06E0, 0x06F0, 0x06C0,\n    0x0700, 0x0710, 0x0720, 0x0730, 0x0740, 0x0750, 0x0760, 0x0770,\n/* INDEX_BLOCK: -- 0x00E0..0x00FF -- */\n    0x0780, 0x0790, 0x0790, 0x07A0, 0x0790, 0x07B0, 0x07C0, 0x07C0, 0x07D0, 0x07E0, 0x07F0, 0x0800,\n    0x0810, 0x0820, 0x07C0, 0x07C0, 0x0830, 0x0830, 0x0830, 0x0830, 0x0840, 0x0830, 0x0850, 0x0860,\n    0x0830, 0x0840, 0x0830, 0x0870, 0x0870, 0x0880, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0100..0x011F -- */\n    0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x0890, 0x08A0, 0x08A0,\n    0x08B0, 0x08A0, 0x08A0, 0x08C0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n/* INDEX_BLOCK: -- 0x0120..0x013F -- */\n    0x08E0, 0x08E0, 0x08E0, 0x08E0, 0x08F0, 0x0900, 0x08E0, 0x08E0, 0x08F0, 0x08E0, 0x08E0, 0x0910,\n    0x0920, 0x0930, 0x08E0, 0x08E0, 0x08E0, 0x0920, 0x08E0, 0x08E0, 0x08E0, 0x0940, 0x08E0, 0x0950,\n    0x08E0, 0x0960, 0x0970, 0x0970, 0x0970, 0x0970, 0x0970, 0x0980,\n/* INDEX_BLOCK: -- 0x0140..0x015F -- */\n    0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990,\n    0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990,\n    0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990,\n/* INDEX_BLOCK: -- 0x0160..0x017F -- */\n    0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x0990, 0x09A0, 0x09B0, 0x09C0, 0x09C0,\n    0x09C0, 0x09C0, 0x09D0, 0x09E0, 0x09F0, 0x0A00, 0x0A10, 0x0A20, 0x0A30, 0x0A40, 0x0A50, 0x0A60,\n    0x0A70, 0x0A70, 0x0A70, 0x0A70, 0x0A70, 0x0A80, 0x0A90, 0x0A90,\n/* INDEX_BLOCK: -- 0x0180..0x019F -- */\n    0x0AA0, 0x0AB0, 0x0AC0, 0x0AC0, 0x0AC0, 0x0AC0, 0x0AC0, 0x0AD0, 0x0AC0, 0x0AC0, 0x0AE0, 0x0990,\n    0x0990, 0x0990, 0x0990, 0x0AF0, 0x0B00, 0x0B10, 0x0B20, 0x0B20, 0x0B30, 0x0B40, 0x0B50, 0x0B60,\n    0x0B70, 0x0B70, 0x0B80, 0x0B70, 0x0B90, 0x0BA0, 0x0A70, 0x0A70,\n/* INDEX_BLOCK: -- 0x01A0..0x01BF -- */\n    0x0BB0, 0x0BC0, 0x0BD0, 0x0BD0, 0x0BD0, 0x0BE0, 0x0BD0, 0x0BF0, 0x0C00, 0x0C00, 0x0C10, 0x0080,\n    0x0080, 0x0C20, 0x0C30, 0x07C0, 0x0C40, 0x0C40, 0x0C40, 0x0C40, 0x0C50, 0x0C40, 0x0C40, 0x0C40,\n    0x0C60, 0x0C60, 0x0C60, 0x0C60, 0x0C70, 0x0C70, 0x0C70, 0x0C80,\n/* INDEX_BLOCK: -- 0x01C0..0x01DF -- */\n    0x0C90, 0x0C90, 0x0C90, 0x0CA0, 0x0CB0, 0x0CC0, 0x0CC0, 0x0CC0, 0x0CD0, 0x08A0, 0x08A0, 0x0CE0,\n    0x0CF0, 0x0D00, 0x0D10, 0x0D20, 0x0040, 0x0040, 0x0D30, 0x0040, 0x0040, 0x0D40, 0x0D50, 0x0D60,\n    0x0040, 0x0040, 0x0040, 0x0D70, 0x0080, 0x0080, 0x0080, 0x0080,\n/* INDEX_BLOCK: -- 0x01E0..0x01FF -- */\n    0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040,\n    0x0040, 0x0040, 0x0040, 0x0040, 0x00B0, 0x0D80, 0x00B0, 0x00B0, 0x0D80, 0x0D90, 0x00B0, 0x0DA0,\n    0x00B0, 0x00B0, 0x00B0, 0x0DB0, 0x0DB0, 0x0DC0, 0x00B0, 0x0DD0,\n/* INDEX_BLOCK: -- 0x0200..0x021F -- */\n    0x0DE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0DF0, 0x0E00, 0x0E10, 0x0E20, 0x0000, 0x0000,\n    0x0E30, 0x0080, 0x0080, 0x0E40, 0x0000, 0x0000, 0x0E50, 0x0E60, 0x0E70, 0x0000, 0x0040, 0x0040,\n    0x0E80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0220..0x023F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0240..0x025F -- */\n    0x0000, 0x0000, 0x0E90, 0x07C0, 0x0EA0, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0260..0x027F -- */\n    0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0,\n    0x0EB0, 0x0EB0, 0x0EB0, 0x0EB0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0280..0x029F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0EC0,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x02A0..0x02BF -- */\n    0x0ED0, 0x0ED0, 0x0ED0, 0x0ED0, 0x0ED0, 0x0ED0, 0x0040, 0x0040, 0x0EE0, 0x0EE0, 0x0EE0, 0x0EE0,\n    0x0EE0, 0x0EE0, 0x0EE0, 0x0EF0, 0x08A0, 0x08A0, 0x08B0, 0x0F00, 0x0F00, 0x0F00, 0x0F10, 0x0F20,\n    0x08E0, 0x0F30, 0x0F40, 0x0F40, 0x0F40, 0x0F40, 0x00E0, 0x00E0,\n/* INDEX_BLOCK: -- 0x02C0..0x02DF -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0F50, 0x07C0, 0x07C0, 0x0F60, 0x0F70, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F80, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F90, 0x07C0, 0x0000,\n/* INDEX_BLOCK: -- 0x02E0..0x02FF -- */\n    0x0FA0, 0x0000, 0x0FB0, 0x0FC0, 0x0FD0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FF0, 0x1000, 0x1010,\n    0x1010, 0x1010, 0x1010, 0x1020, 0x1030, 0x1040, 0x1040, 0x1050, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x1060, 0x0000, 0x1040, 0x1040, 0x0000, 0x0000, 0x1070, 0x1010,\n/* INDEX_BLOCK: -- 0x0300..0x031F -- */\n    0x08D0, 0x1060, 0x0000, 0x0000, 0x0000, 0x0000, 0x08D0, 0x1080, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x1010, 0x1010, 0x1090, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x10A0, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0320..0x033F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0340..0x035F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0360..0x037F -- */\n    0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0,\n    0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0,\n    0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0,\n/* INDEX_BLOCK: -- 0x0380..0x039F -- */\n    0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10B0, 0x10C0, 0x10B0, 0x10B0, 0x10B0,\n    0x10D0, 0x10E0, 0x10E0, 0x10E0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0,\n    0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0, 0x10F0,\n/* INDEX_BLOCK: -- 0x03A0..0x03BF -- */\n    0x10F0, 0x10F0, 0x1100, 0x07C0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x00E0, 0x1110, 0x1110,\n    0x1110, 0x1110, 0x1110, 0x1120, 0x0000, 0x0000, 0x1130, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040,\n    0x1140, 0x0040, 0x0040, 0x0040, 0x0040, 0x0E20, 0x07C0, 0x1150,\n/* INDEX_BLOCK: -- 0x03C0..0x03DF -- */\n    0x1160, 0x1160, 0x1170, 0x0E90, 0x1180, 0x1180, 0x1180, 0x1190, 0x11A0, 0x11A0, 0x11A0, 0x11A0,\n    0x11B0, 0x11C0, 0x02F0, 0x02F0, 0x11D0, 0x11D0, 0x11E0, 0x11F0, 0x11F0, 0x1200, 0x08D0, 0x1210,\n    0x1220, 0x1220, 0x1220, 0x1220, 0x1230, 0x1240, 0x0890, 0x1250,\n/* INDEX_BLOCK: -- 0x03E0..0x03FF -- */\n    0x1260, 0x1260, 0x1260, 0x1270, 0x1280, 0x1290, 0x0890, 0x0890, 0x12A0, 0x12A0, 0x12A0, 0x12A0,\n    0x12B0, 0x12C0, 0x12D0, 0x12E0, 0x12F0, 0x1300, 0x0F40, 0x0040, 0x0040, 0x1310, 0x1320, 0x0970,\n    0x0970, 0x0970, 0x0970, 0x0970, 0x12D0, 0x12D0, 0x1330, 0x1340,\n/* INDEX_BLOCK: -- 0x0400..0x041F -- */\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n/* INDEX_BLOCK: -- 0x0420..0x043F -- */\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0, 0x08D0,\n    0x08D0, 0x08D0, 0x1350, 0x08D0, 0x1360, 0x08D0, 0x08D0, 0x1370,\n/* INDEX_BLOCK: -- 0x0440..0x045F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0460..0x047F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0480..0x049F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x1380, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x1390, 0x07C0, 0x07C0, 0x13A0, 0x13B0, 0x0150, 0x13C0, 0x13D0, 0x01B0, 0x01B0, 0x01B0,\n    0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0,\n/* INDEX_BLOCK: -- 0x04A0..0x04BF -- */\n    0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0,\n    0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x13E0, 0x01B0, 0x01B0, 0x01B0, 0x01B0,\n    0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x01B0, 0x07C0, 0x07C0, 0x01B0,\n/* INDEX_BLOCK: -- 0x04C0..0x04DF -- */\n    0x0080, 0x0E90, 0x13F0, 0x0000, 0x0000, 0x1400, 0x1410, 0x1420, 0x01B0, 0x01B0, 0x01B0, 0x01B0,\n    0x01B0, 0x01B0, 0x01B0, 0x1430, 0x1440, 0x0000, 0x0010, 0x0020, 0x0010, 0x0020, 0x1450, 0x1000,\n    0x1010, 0x1460, 0x08D0, 0x1060, 0x1470, 0x1480, 0x1490, 0x14A0,\n/* INDEX_BLOCK: -- 0x04E0..0x04FF -- */\n    0x14B0, 0x14C0, 0x14D0, 0x14E0, 0x14F0, 0x14F0, 0x07C0, 0x07C0, 0x14C0, 0x14C0, 0x14C0, 0x14C0,\n    0x14C0, 0x14C0, 0x14C0, 0x1500, 0x1510, 0x0000, 0x0000, 0x1520, 0x00B0, 0x00B0, 0x00B0, 0x00B0,\n    0x1530, 0x1540, 0x1550, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x1560,\n/* INDEX_BLOCK: -- 0x0500..0x051F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x1570, 0x1580, 0x1590, 0x1590,\n    0x1590, 0x15A0, 0x15B0, 0x15C0, 0x15D0, 0x15D0, 0x15E0, 0x15F0, 0x1600, 0x1610, 0x1610, 0x1620,\n    0x1630, 0x1640, 0x1650, 0x1650, 0x1660, 0x1670, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0520..0x053F -- */\n    0x1680, 0x1680, 0x1680, 0x1680, 0x1680, 0x1690, 0x1690, 0x1690, 0x16A0, 0x16B0, 0x16C0, 0x16D0,\n    0x16D0, 0x16E0, 0x16D0, 0x16F0, 0x1700, 0x1700, 0x1710, 0x1720, 0x1720, 0x1720, 0x1730, 0x1740,\n    0x1740, 0x1750, 0x1760, 0x1770, 0x1780, 0x1780, 0x1780, 0x1790,\n/* INDEX_BLOCK: -- 0x0540..0x055F -- */\n    0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0,\n    0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17A0, 0x17B0, 0x17A0, 0x17C0, 0x17D0, 0x07C0,\n    0x17E0, 0x0040, 0x0040, 0x17F0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0560..0x057F -- */\n    0x1800, 0x1810, 0x1810, 0x1820, 0x1830, 0x1840, 0x1850, 0x1850, 0x1860, 0x1870, 0x1880, 0x07C0,\n    0x07C0, 0x07C0, 0x1890, 0x18A0, 0x18B0, 0x18C0, 0x18D0, 0x18E0, 0x18F0, 0x1900, 0x07C0, 0x07C0,\n    0x1910, 0x1910, 0x1920, 0x1930, 0x1920, 0x1940, 0x1920, 0x1920,\n/* INDEX_BLOCK: -- 0x0580..0x059F -- */\n    0x1950, 0x1960, 0x1970, 0x1980, 0x1990, 0x1990, 0x19A0, 0x19A0, 0x19B0, 0x19B0, 0x07C0, 0x07C0,\n    0x19C0, 0x19C0, 0x19D0, 0x19E0, 0x19F0, 0x19F0, 0x19F0, 0x1A00, 0x1A10, 0x1A20, 0x1A30, 0x1A40,\n    0x1A50, 0x1A60, 0x1A70, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x05A0..0x05BF -- */\n    0x1A80, 0x1A80, 0x1A80, 0x1A80, 0x1A90, 0x07C0, 0x07C0, 0x07C0, 0x1AA0, 0x1AA0, 0x1AA0, 0x1AB0,\n    0x1AA0, 0x1AA0, 0x1AA0, 0x1AC0, 0x1AD0, 0x1AD0, 0x1AE0, 0x1AF0, 0x1B00, 0x1B00, 0x1B10, 0x1B00,\n    0x1B20, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x05C0..0x05DF -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x01B0, 0x1B30, 0x1B40, 0x1B40, 0x1B50, 0x1B60,\n    0x1B70, 0x1B80, 0x07C0, 0x1B90, 0x1BA0, 0x1BA0, 0x1BB0, 0x1BC0, 0x1BC0, 0x1BD0, 0x07C0, 0x1BE0,\n    0x1BF0, 0x07C0, 0x07C0, 0x1C00, 0x1C10, 0x07C0, 0x1C20, 0x1C30,\n/* INDEX_BLOCK: -- 0x05E0..0x05FF -- */\n    0x1C40, 0x1C40, 0x1C40, 0x1C40, 0x1C50, 0x1C60, 0x1C40, 0x1C70, 0x1C80, 0x1C80, 0x1C80, 0x1C80,\n    0x1C90, 0x1CA0, 0x1CB0, 0x1CC0, 0x1CD0, 0x1CD0, 0x1CD0, 0x1CE0, 0x1CF0, 0x1D00, 0x1D00, 0x1D10,\n    0x1D20, 0x1D20, 0x1D20, 0x1D20, 0x1D20, 0x1D20, 0x1D30, 0x1D40,\n/* INDEX_BLOCK: -- 0x0600..0x061F -- */\n    0x1D50, 0x1D60, 0x1D50, 0x1D50, 0x1D70, 0x07C0, 0x07C0, 0x07C0, 0x1D80, 0x1D90, 0x1DA0, 0x1DB0,\n    0x1DB0, 0x1DB0, 0x1DC0, 0x1DD0, 0x1DE0, 0x1DF0, 0x1E00, 0x1E10, 0x1E20, 0x1E30, 0x1E40, 0x1E50,\n    0x1E60, 0x1E70, 0x1E70, 0x1E80, 0x1E90, 0x1EA0, 0x1EB0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0620..0x063F -- */\n    0x1EC0, 0x1EC0, 0x1EC0, 0x1EC0, 0x1EC0, 0x1ED0, 0x1EE0, 0x07C0, 0x1EF0, 0x1EF0, 0x1EF0, 0x1EF0,\n    0x1F00, 0x1F10, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x1F20, 0x1F20, 0x1F20, 0x1F30, 0x1F20, 0x1F40, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0640..0x065F -- */\n    0x1F50, 0x1F50, 0x1F50, 0x1F50, 0x1F60, 0x1F70, 0x1F80, 0x07C0, 0x1F90, 0x1F90, 0x1F90, 0x1FA0,\n    0x1FA0, 0x0890, 0x1FB0, 0x07C0, 0x1FC0, 0x1FD0, 0x1FE0, 0x1FC0, 0x1FF0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0660..0x067F -- */\n    0x2000, 0x2000, 0x2000, 0x2010, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2020, 0x2020,\n    0x2020, 0x2020, 0x2020, 0x2030, 0x2040, 0x2050, 0x2060, 0x2070, 0x2080, 0x2090, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x20A0, 0x20B0, 0x20B0, 0x20A0, 0x20C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0680..0x069F -- */\n    0x20D0, 0x20D0, 0x20D0, 0x20D0, 0x20E0, 0x20F0, 0x20F0, 0x20F0, 0x20F0, 0x20F0, 0x2100, 0x0990,\n    0x2110, 0x2110, 0x2110, 0x2120, 0x2130, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2140, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2150, 0x2150, 0x2160, 0x2170,\n/* INDEX_BLOCK: -- 0x06A0..0x06BF -- */\n    0x2180, 0x2190, 0x2190, 0x21A0, 0x21B0, 0x2190, 0x21C0, 0x21D0, 0x21D0, 0x21E0, 0x21F0, 0x2200,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2210, 0x2220, 0x2220, 0x2230, 0x2240, 0x2250, 0x2260, 0x2270,\n    0x2280, 0x2290, 0x22A0, 0x22B0, 0x22B0, 0x22C0, 0x22D0, 0x07C0,\n/* INDEX_BLOCK: -- 0x06C0..0x06DF -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x22E0, 0x22F0, 0x2300, 0x2310, 0x2300, 0x2320, 0x2300, 0x2330, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x2340, 0x2350, 0x2350, 0x2350, 0x2360,\n/* INDEX_BLOCK: -- 0x06E0..0x06FF -- */\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370,\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370,\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370,\n/* INDEX_BLOCK: -- 0x0700..0x071F -- */\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370,\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370,\n    0x2370, 0x2380, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0720..0x073F -- */\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2390, 0x23A0, 0x2370, 0x2370, 0x2370, 0x2370,\n    0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x2370, 0x23B0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0740..0x075F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x23C0, 0x23C0, 0x23C0, 0x23C0, 0x23C0, 0x23C0, 0x23D0,\n/* INDEX_BLOCK: -- 0x0760..0x077F -- */\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n/* INDEX_BLOCK: -- 0x0780..0x079F -- */\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23F0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n/* INDEX_BLOCK: -- 0x07A0..0x07BF -- */\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0,\n    0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x23E0, 0x2400,\n/* INDEX_BLOCK: -- 0x07C0..0x07DF -- */\n    0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410,\n    0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410,\n    0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410, 0x2410,\n/* INDEX_BLOCK: -- 0x07E0..0x07FF -- */\n    0x2410, 0x2410, 0x2410, 0x2410, 0x2420, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0800..0x081F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2430, 0x2430, 0x2430, 0x2440, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0820..0x083F -- */\n    0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,\n    0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,\n    0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,\n/* INDEX_BLOCK: -- 0x0840..0x085F -- */\n    0x1110, 0x1110, 0x1110, 0x2450, 0x2460, 0x2470, 0x2480, 0x2490, 0x2490, 0x2490, 0x2490, 0x24A0,\n    0x24B0, 0x24C0, 0x24D0, 0x24E0, 0x24F0, 0x24F0, 0x24F0, 0x24F0, 0x2500, 0x2510, 0x2520, 0x2530,\n    0x24F0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0860..0x087F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2540, 0x2540, 0x2540, 0x2550,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0880..0x089F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2560, 0x2560, 0x2560, 0x2560, 0x2560, 0x2570, 0x2580, 0x2590,\n    0x2580, 0x25A0, 0x07C0, 0x07C0, 0x25B0, 0x25B0, 0x25B0, 0x25B0, 0x25C0, 0x25B0, 0x25B0, 0x25B0,\n    0x25D0, 0x25B0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x25E0, 0x25F0,\n/* INDEX_BLOCK: -- 0x08A0..0x08BF -- */\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600,\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600,\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600,\n/* INDEX_BLOCK: -- 0x08C0..0x08DF -- */\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600,\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610,\n    0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610,\n/* INDEX_BLOCK: -- 0x08E0..0x08FF -- */\n    0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610,\n    0x2610, 0x2620, 0x07C0, 0x2630, 0x2600, 0x2640, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2600, 0x2650,\n/* INDEX_BLOCK: -- 0x0900..0x091F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2660,\n/* INDEX_BLOCK: -- 0x0920..0x093F -- */\n    0x2670, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0,\n    0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x0FE0, 0x2680, 0x2690, 0x07C0, 0x26A0, 0x26B0, 0x26C0,\n    0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0,\n/* INDEX_BLOCK: -- 0x0940..0x095F -- */\n    0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0, 0x26C0,\n    0x26C0, 0x26C0, 0x26C0, 0x26D0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0960..0x097F -- */\n    0x26E0, 0x26E0, 0x26E0, 0x26E0, 0x26E0, 0x26E0, 0x26F0, 0x2700, 0x2710, 0x2720, 0x2730, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0980..0x099F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x1540, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x09A0..0x09BF -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2740,\n    0x0000, 0x2750, 0x0000, 0x2750, 0x0080, 0x0080, 0x0C20, 0x0080, 0x2760, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x2730, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x09C0..0x09DF -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x2770, 0x0000, 0x0000, 0x2780, 0x0000, 0x0000, 0x0000, 0x2790, 0x27A0,\n    0x27B0, 0x0000, 0x27C0, 0x0000, 0x0000, 0x0000, 0x0EA0, 0x07C0,\n/* INDEX_BLOCK: -- 0x09E0..0x09FF -- */\n    0x00B0, 0x00B0, 0x00B0, 0x00B0, 0x27D0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x0000, 0x2730, 0x0000, 0x2730, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x27E0, 0x0000, 0x27F0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0A00..0x0A1F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0DF0, 0x0000, 0x0000, 0x0000, 0x2800, 0x2810, 0x2820,\n    0x2830, 0x0000, 0x0000, 0x0000, 0x2840, 0x2850, 0x0000, 0x2860, 0x2870, 0x2880, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0A20..0x0A3F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2890, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x28A0, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0A40..0x0A5F -- */\n    0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0,\n    0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0,\n    0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0,\n/* INDEX_BLOCK: -- 0x0A60..0x0A7F -- */\n    0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28B0, 0x28C0, 0x28D0, 0x28E0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0A80..0x0A9F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0040, 0x28F0, 0x2900, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0AA0..0x0ABF -- */\n    0x2910, 0x2920, 0x2930, 0x00E0, 0x00E0, 0x00E0, 0x2940, 0x07C0, 0x2950, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2960, 0x2960, 0x2970, 0x2980, 0x2990, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0AC0..0x0ADF -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x29A0, 0x29B0, 0x07C0,\n    0x29C0, 0x29C0, 0x29C0, 0x29D0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0AE0..0x0AFF -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x29E0, 0x29E0, 0x29F0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2A00, 0x2A00, 0x2A10,\n/* INDEX_BLOCK: -- 0x0B00..0x0B1F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x2A20, 0x2A30, 0x2A20, 0x2A40, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x2A50, 0x2A60,\n/* INDEX_BLOCK: -- 0x0B20..0x0B3F -- */\n    0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70, 0x2A70,\n    0x2A80, 0x2A90, 0x07C0, 0x07C0, 0x2AA0, 0x2AA0, 0x2AA0, 0x2AA0, 0x2AB0, 0x2AC0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0B40..0x0B5F -- */\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x1440, 0x0000, 0x0000, 0x0000, 0x2AD0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x1440, 0x0000, 0x0000, 0x0F50, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0B60..0x0B7F -- */\n    0x2AE0, 0x01B0, 0x2AF0, 0x2B00, 0x2B10, 0x2B20, 0x2B30, 0x2B40, 0x2B50, 0x2B60, 0x2B70, 0x2B60,\n    0x07C0, 0x07C0, 0x07C0, 0x2B80, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0B80..0x0B9F -- */\n    0x0000, 0x0000, 0x15C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2730, 0x0E10, 0x1440,\n    0x1440, 0x1440, 0x0000, 0x2770, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0F50, 0x07C0, 0x07C0, 0x07C0, 0x2B90, 0x0000,\n/* INDEX_BLOCK: -- 0x0BA0..0x0BBF -- */\n    0x2BA0, 0x0000, 0x0000, 0x15C0, 0x27F0, 0x0E30, 0x2770, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0BC0..0x0BDF -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x2BB0, 0x1540, 0x1540, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E90, 0x15C0, 0x2750,\n/* INDEX_BLOCK: -- 0x0BE0..0x0BFF -- */\n    0x15C0, 0x0000, 0x0000, 0x0000, 0x2BC0, 0x0E90, 0x0000, 0x0000, 0x2BC0, 0x0000, 0x0F50, 0x15C0,\n    0x0E30, 0x27F0, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n/* INDEX_BLOCK: -- 0x0C00..0x0C1F -- */\n    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2BC0, 0x0F50, 0x1540, 0x2BD0, 0x0000, 0x0000, 0x0000,\n    0x2BE0, 0x2BF0, 0x2C00, 0x27F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n    0x0000, 0x1400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0EA0,\n/* INDEX_BLOCK: -- 0x0C20..0x0C3F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x07C0, 0x07C0, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0C40..0x0C5F -- */\n    0x0F60, 0x1380, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0C60..0x0C7F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x1380, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0C80..0x0C9F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x2C10, 0x0F60,\n/* INDEX_BLOCK: -- 0x0CA0..0x0CBF -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x1380, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0CC0..0x0CDF -- */\n    0x0F60, 0x1380, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0CE0..0x0CFF -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x2C20, 0x0F60, 0x0F60, 0x0F60,\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60,\n/* INDEX_BLOCK: -- 0x0D00..0x0D1F -- */\n    0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x0F60, 0x1390, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n/* INDEX_BLOCK: -- 0x0D20..0x0D3E -- */\n    0x2C30, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07C0, 0x07C0, 0x07C0, 0x07C0,\n    0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080,\n    0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080\n};\n\nstatic const SBUInt16 BranchScriptIndexes[1793] = {\n    0x0000, 0x0020, 0x0040, 0x0060, 0x0080, 0x00A0, 0x00C0, 0x00E0, 0x0100, 0x0120, 0x0140, 0x0160,\n    0x0180, 0x01A0, 0x01C0, 0x01E0, 0x0200, 0x0220, 0x0240, 0x0220, 0x0260, 0x0280, 0x02A0, 0x02C0,\n    0x02E0, 0x0300, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0340, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0360, 0x0360, 0x0380, 0x03A0,\n    0x03C0, 0x03E0, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,\n    0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0420,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0460, 0x0480, 0x04A0, 0x04C0, 0x04E0, 0x0500, 0x0520, 0x0540,\n    0x0560, 0x0580, 0x05A0, 0x05C0, 0x05E0, 0x0600, 0x0620, 0x0640, 0x0660, 0x0680, 0x06A0, 0x06C0,\n    0x06E0, 0x0700, 0x0720, 0x0440, 0x0440, 0x0440, 0x0440, 0x0740, 0x0760, 0x0760, 0x0780, 0x0760,\n    0x0760, 0x0760, 0x0760, 0x0760, 0x0760, 0x07A0, 0x07C0, 0x07E0, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0800, 0x0440, 0x0440, 0x0440,\n    0x0820, 0x0840, 0x0860, 0x0880, 0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08A0,\n    0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08A0, 0x08C0, 0x08E0, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0900,\n    0x0920, 0x0940, 0x0440, 0x0440, 0x0440, 0x0440, 0x0960, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0980, 0x09A0, 0x09C0, 0x09E0, 0x0A00, 0x0A20, 0x0A40, 0x0A60, 0x0440, 0x0A80,\n    0x0AA0, 0x0AC0, 0x0AE0, 0x0B00, 0x0B20, 0x0440, 0x0B40, 0x0B60, 0x0B80, 0x0BA0, 0x0220, 0x0BC0,\n    0x0BE0, 0x0C00, 0x0440, 0x0440, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0C20, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0C40, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0C60,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0C80, 0x0320, 0x0CA0, 0x0440, 0x0440, 0x0440, 0x0440, 0x0320, 0x0CC0, 0x0440, 0x0440,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0CE0, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320, 0x0320,\n    0x0320, 0x0320, 0x0D00, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440, 0x0440,\n    0x0440, 0x0440, 0x0440, 0x0440, 0x0D20\n};\n\nSB_INTERNAL SBScript LookupScript(SBCodepoint codepoint)\n{\n    if (codepoint <= 0x0E01EF) {\n        return PrimaryScriptData[\n                MainScriptIndexes[\n                 BranchScriptIndexes[\n                      codepoint / 0x0200\n                 ] + (codepoint % 0x0200) / 0x0010\n                ] + codepoint % 0x0010\n               ];\n    }\n\n    return Zzzz;\n}\n\n#undef Adlm\n#undef Aghb\n#undef Ahom\n#undef Arab\n#undef Armi\n#undef Armn\n#undef Avst\n#undef Bali\n#undef Bamu\n#undef Bass\n#undef Batk\n#undef Beng\n#undef Berf\n#undef Bhks\n#undef Bopo\n#undef Brah\n#undef Brai\n#undef Bugi\n#undef Buhd\n#undef Cakm\n#undef Cans\n#undef Cari\n#undef Cham\n#undef Cher\n#undef Chrs\n#undef Copt\n#undef Cpmn\n#undef Cprt\n#undef Cyrl\n#undef Deva\n#undef Diak\n#undef Dogr\n#undef Dsrt\n#undef Dupl\n#undef Egyp\n#undef Elba\n#undef Elym\n#undef Ethi\n#undef Gara\n#undef Geor\n#undef Glag\n#undef Gong\n#undef Gonm\n#undef Goth\n#undef Gran\n#undef Grek\n#undef Gujr\n#undef Gukh\n#undef Guru\n#undef Hang\n#undef Hani\n#undef Hano\n#undef Hatr\n#undef Hebr\n#undef Hira\n#undef Hluw\n#undef Hmng\n#undef Hmnp\n#undef Hung\n#undef Ital\n#undef Java\n#undef Kali\n#undef Kana\n#undef Kawi\n#undef Khar\n#undef Khmr\n#undef Khoj\n#undef Kits\n#undef Knda\n#undef Krai\n#undef Kthi\n#undef Lana\n#undef Laoo\n#undef Latn\n#undef Lepc\n#undef Limb\n#undef Lina\n#undef Linb\n#undef Lisu\n#undef Lyci\n#undef Lydi\n#undef Mahj\n#undef Maka\n#undef Mand\n#undef Mani\n#undef Marc\n#undef Medf\n#undef Mend\n#undef Merc\n#undef Mero\n#undef Mlym\n#undef Modi\n#undef Mong\n#undef Mroo\n#undef Mtei\n#undef Mult\n#undef Mymr\n#undef Nagm\n#undef Nand\n#undef Narb\n#undef Nbat\n#undef Newa\n#undef Nkoo\n#undef Nshu\n#undef Ogam\n#undef Olck\n#undef Onao\n#undef Orkh\n#undef Orya\n#undef Osge\n#undef Osma\n#undef Ougr\n#undef Palm\n#undef Pauc\n#undef Perm\n#undef Phag\n#undef Phli\n#undef Phlp\n#undef Phnx\n#undef Plrd\n#undef Prti\n#undef Rjng\n#undef Rohg\n#undef Runr\n#undef Samr\n#undef Sarb\n#undef Saur\n#undef Sgnw\n#undef Shaw\n#undef Shrd\n#undef Sidd\n#undef Sidt\n#undef Sind\n#undef Sinh\n#undef Sogd\n#undef Sogo\n#undef Sora\n#undef Soyo\n#undef Sund\n#undef Sunu\n#undef Sylo\n#undef Syrc\n#undef Tagb\n#undef Takr\n#undef Tale\n#undef Talu\n#undef Taml\n#undef Tang\n#undef Tavt\n#undef Tayo\n#undef Telu\n#undef Tfng\n#undef Tglg\n#undef Thaa\n#undef Thai\n#undef Tibt\n#undef Tirh\n#undef Tnsa\n#undef Todr\n#undef Tols\n#undef Toto\n#undef Tutg\n#undef Ugar\n#undef Vaii\n#undef Vith\n#undef Wara\n#undef Wcho\n#undef Xpeo\n#undef Xsux\n#undef Yezi\n#undef Yiii\n#undef Zanb\n#undef Zinh\n#undef Zyyy\n#undef Zzzz\n"
  },
  {
    "path": "unix/bidi/Source/Data/ScriptLookup.h",
    "content": "/*\n * Automatically generated by SheenBidiGenerator tool.\n * DO NOT EDIT!!\n */\n\n#ifndef _SB_INTERNAL_SCRIPT_LOOKUP_H\n#define _SB_INTERNAL_SCRIPT_LOOKUP_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n\nSB_INTERNAL SBScript LookupScript(SBCodepoint codepoint);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Script/ScriptStack.c",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n\n#include \"ScriptStack.h\"\n\nSB_INTERNAL void ScriptStackReset(ScriptStackRef stack)\n{\n    stack->top = -1;\n    stack->count = 0;\n    stack->open = 0;\n}\n\nSB_INTERNAL void ScriptStackPush(ScriptStackRef stack, SBScript script, SBCodepoint mirror)\n{\n    stack->count = SBNumberLimitIncrement(stack->count, _SBScriptStackCapacity);\n    stack->open = SBNumberLimitIncrement(stack->open, _SBScriptStackCapacity);\n\n    stack->top = SBNumberRingIncrement(stack->top, _SBScriptStackCapacity);\n    stack->_elements[stack->top].script = script;\n    stack->_elements[stack->top].mirror = mirror;\n}\n\nSB_INTERNAL void ScriptStackPop(ScriptStackRef stack)\n{\n    /* There must be at least one entry in the stack. */\n    SBAssert(stack->count > 0);\n\n    stack->count -= 1;\n    stack->open = SBNumberLimitDecrement(stack->open, 0);\n    stack->top = SBNumberRingDecrement(stack->top, _SBScriptStackCapacity);\n\n    if (ScriptStackIsEmpty(stack)) {\n        stack->top = -1;\n    }\n}\n\nSB_INTERNAL void ScriptStackLeavePairs(ScriptStackRef stack)\n{\n    stack->open = 0;\n}\n\nSB_INTERNAL void ScriptStackSealPairs(ScriptStackRef stack, SBScript script)\n{\n    SBInteger index = SBNumberRingSubtract(stack->top, (SBInteger)stack->open, _SBScriptStackCapacity);\n\n    while (stack->open) {\n        index = SBNumberRingIncrement(index, _SBScriptStackCapacity);\n        stack->_elements[index].script = script;\n        stack->open -= 1;\n    }\n}\n\nSB_INTERNAL SBBoolean ScriptStackIsEmpty(ScriptStackRef stack)\n{\n    return (stack->count == 0);\n}\n\nSB_INTERNAL SBScript ScriptStackGetScript(ScriptStackRef stack)\n{\n    return stack->_elements[stack->top].script;\n}\n\nSB_INTERNAL SBCodepoint ScriptStackGetMirror(ScriptStackRef stack)\n{\n    return stack->_elements[stack->top].mirror;\n}\n"
  },
  {
    "path": "unix/bidi/Source/Script/ScriptStack.h",
    "content": "/*\n * Copyright (C) 2018-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_SCRIPT_STACK_H\n#define _SB_INTERNAL_SCRIPT_STACK_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n\n#define _SBScriptStackCapacity  63\n\ntypedef struct _SBScriptStackElement {\n    SBScript script;\n    SBCodepoint mirror;\n} _SBScriptStackElement;\n\ntypedef struct _SBScriptStack {\n    _SBScriptStackElement _elements[_SBScriptStackCapacity];\n    SBInteger top;\n    SBUInteger count;\n    SBUInteger open;\n} ScriptStack, *ScriptStackRef;\n\nSB_INTERNAL void ScriptStackReset(ScriptStackRef stack);\n\nSB_INTERNAL void ScriptStackPush(ScriptStackRef stack, SBScript script, SBCodepoint mirror);\nSB_INTERNAL void ScriptStackPop(ScriptStackRef stack);\n\nSB_INTERNAL void ScriptStackLeavePairs(ScriptStackRef stack);\nSB_INTERNAL void ScriptStackSealPairs(ScriptStackRef stack, SBScript script);\n\nSB_INTERNAL SBBoolean ScriptStackIsEmpty(ScriptStackRef stack);\nSB_INTERNAL SBScript ScriptStackGetScript(ScriptStackRef stack);\nSB_INTERNAL SBCodepoint ScriptStackGetMirror(ScriptStackRef stack);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Text/AttributeDictionary.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n\n#include <API/SBAllocator.h>\n#include <API/SBAttributeInfo.h>\n#include <API/SBAttributeList.h>\n#include <API/SBAttributeRegistry.h>\n\n#include \"AttributeDictionary.h\"\n\n/**\n * Determines whether an attribute item matches the specified filter criteria.\n *\n * Checks if the attribute's scope matches the target scope. If a specific group filter is\n * provided (not SBAttributeGroupNone), also verifies that the attribute's group matches.\n * Both conditions must be satisfied for the item to be considered a match.\n *\n * @param item\n *      The attribute item to check.\n * @param registry\n *      The attribute registry used to retrieve attribute metadata.\n * @param filterScope\n *      The scope to match against (character or paragraph).\n * @param filterGroup\n *      The group to match against, or SBAttributeGroupNone to skip group filtering.\n * @return\n *      SBTrue if the item matches all filter criteria, SBFalse otherwise.\n */\nstatic SBBoolean CheckAttributeMatchesFilter(SBAttributeItem *item,\n    SBAttributeRegistryRef registry, SBAttributeScope filterScope, SBAttributeGroup filterGroup)\n{\n    const SBAttributeInfo *attributeInfo;\n    SBBoolean matchesFilter;\n\n    attributeInfo = SBAttributeRegistryGetInfoReference(registry, item->attributeID);\n\n    /* Match the scope first */\n    matchesFilter = (attributeInfo->scope == filterScope);\n\n    /* Match the group if a specific group filter is provided */\n    if (matchesFilter && filterGroup != SBAttributeGroupNone) {\n        matchesFilter = (attributeInfo->group == filterGroup);\n    }\n\n    return matchesFilter;\n}\n\nstatic void ReleaseAllAttributeItems(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry)\n{\n    SBUInteger itemIndex;\n\n    if (registry) {\n        SBUInteger itemCount = SBAttributeListSize(&dictionary->_list);\n\n        /* Release attribute values through the registry */\n        for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {\n            SBAttributeItem *item = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n            const void *valuePtr = SBAttributeItemGetValuePtr(item);\n\n            SBAttributeRegistryReleaseAttribute(registry, valuePtr);\n        }\n    }\n}\n\nSB_INTERNAL void AttributeDictionaryInitialize(AttributeDictionaryRef dictionary, SBUInt8 valueSize)\n{\n    SBUInteger itemSize = sizeof(SBAttributeItem) + valueSize;\n\n    SBAttributeListInitialize(&dictionary->_list, itemSize);\n}\n\nSB_INTERNAL void AttributeDictionaryFinalize(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry)\n{\n    ReleaseAllAttributeItems(dictionary, registry);\n    SBAttributeListFinalize(&dictionary->_list);\n}\n\nSB_INTERNAL AttributeDictionaryRef AttributeDictionaryCreate(SBUInt8 valueSize)\n{\n    AttributeDictionaryRef dictionary;\n\n    dictionary = SBAllocatorAllocateBlock(NULL, sizeof(AttributeDictionary));\n\n    if (dictionary) {\n        AttributeDictionaryInitialize(dictionary, valueSize);\n    }\n\n    return dictionary;\n}\n\nSB_INTERNAL void AttributeDictionaryDestroy(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry)\n{\n    AttributeDictionaryFinalize(dictionary, registry);\n    SBAllocatorDeallocateBlock(NULL, dictionary);\n}\n\nSB_INTERNAL SBBoolean AttributeDictionaryIsEmpty(AttributeDictionaryRef dictionary)\n{\n    return (SBAttributeListSize(&dictionary->_list) == 0);\n}\n\nSB_INTERNAL void AttributeDictionarySet(AttributeDictionaryRef dictionary,\n    AttributeDictionaryRef other, SBAttributeRegistryRef registry)\n{\n    SBUInteger itemCount = SBAttributeListSize(&other->_list);\n    SBUInteger itemIndex;\n\n    AttributeDictionaryClear(dictionary, registry);\n    SBAttributeListReserveRange(&dictionary->_list, 0, itemCount);\n\n    /* Copy each attribute item, retaining values through the registry */\n    for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {\n        const SBAttributeItem *source = SBAttributeListGetAt(&other->_list, itemIndex);\n        SBAttributeItem *destination = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n        const void *oldValue;\n        const void *newValue;\n\n        oldValue = SBAttributeItemGetValuePtr(source);\n        newValue = SBAttributeRegistryRetainAttribute(registry, oldValue);\n\n        SBAttributeItemSet(destination, source->attributeID, newValue);\n    }\n}\n\nSB_INTERNAL void AttributeDictionaryPut(AttributeDictionaryRef dictionary,\n    SBAttributeID attributeID, const void *attributeValue, SBAttributeRegistryRef registry,\n    SBBoolean *unchanged)\n{\n    SBBoolean itemFound;\n    SBUInteger itemIndex;\n    const void *newValue;\n\n    /* Find the index where the item exists or should be inserted */\n    itemIndex = SBAttributeListBinarySearchIndex(&dictionary->_list, attributeID, &itemFound);\n\n    if (registry) {\n        /* Retain the new attribute value upfront */\n        newValue = SBAttributeRegistryRetainAttribute(registry, attributeValue);\n    } else {\n        newValue = attributeValue;\n    }\n\n    if (itemFound) {\n        SBAttributeItem *item = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n        const void *previousValue = SBAttributeItemGetValuePtr(item);\n\n        if (registry) {\n            if (unchanged) {\n                *unchanged = SBAttributeRegistryIsEqualAttribute(registry, attributeID, previousValue, newValue);\n            }\n\n            /* Release the old attribute value being replaced */\n            SBAttributeRegistryReleaseAttribute(registry, previousValue);\n        } else {\n            if (unchanged) {\n                *unchanged = SBAttributeItemIsEqualValue(item->attributeID, previousValue, newValue);\n            }\n        }\n\n        /* Update with the new value */\n        SBAttributeItemSetValue(item, newValue);\n    } else {\n        SBAttributeItem *newItem;\n\n        /* Insert the new item at the correct position to maintain sorted order */\n        SBAttributeListReserveRange(&dictionary->_list, itemIndex, 1);\n\n        newItem = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n        SBAttributeItemSet(newItem, attributeID, newValue);\n\n        if (unchanged) {\n            *unchanged = SBFalse;\n        }\n    }\n}\n\nSB_INTERNAL void AttributeDictionaryMerge(AttributeDictionaryRef dictionary,\n    AttributeDictionaryRef other, SBAttributeRegistryRef registry, SBBoolean *unchanged)\n{\n    SBUInteger itemCount = SBAttributeListSize(&other->_list);\n    SBUInteger itemIndex;\n    SBBoolean remainedUnchanged;\n    SBBoolean *noImpact;\n\n    if (unchanged) {\n        *unchanged = SBTrue;\n        noImpact = &remainedUnchanged;\n    } else {\n        noImpact = NULL;\n    }\n\n    for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {\n        SBAttributeItem *currentItem = SBAttributeListGetAt(&other->_list, itemIndex);\n\n        AttributeDictionaryPut(dictionary, currentItem->attributeID,\n            SBAttributeItemGetValuePtr(currentItem), registry, noImpact);\n\n        if (noImpact && !remainedUnchanged) {\n            *unchanged = SBFalse;\n        }\n    }\n}\n\nSB_INTERNAL void AttributeDictionaryFilter(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup,\n    SBAttributeRegistryRef registry, AttributeDictionaryRef result)\n{\n    SBUInteger itemCount = SBAttributeListSize(&dictionary->_list);\n    SBUInteger itemIndex;\n\n    /* Clear the result dictionary before populating it */\n    AttributeDictionaryClear(result, NULL);\n\n    /* Iterate through all items in the dictionary */\n    for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {\n        SBAttributeItem *currentItem = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n        SBBoolean matched;\n\n        /* Check if the item matches the filter criteria */\n        matched = CheckAttributeMatchesFilter(currentItem, registry, targetScope, targetGroup);\n\n        if (matched) {\n            const void *valuePtr = SBAttributeItemGetValuePtr(currentItem);\n            SBAttributeItem *newItem;\n\n            /* Add matching item to the result dictionary */\n            SBAttributeListReserveEnd(&result->_list, 1);\n            newItem = SBAttributeListGetLast(&result->_list);\n\n            SBAttributeItemSet(newItem, currentItem->attributeID, valuePtr);\n        }\n    }\n}\n\nSB_INTERNAL const void *AttributeDictionaryFindValue(\n    AttributeDictionaryRef dictionary, SBAttributeID attributeID)\n{\n    const void *value = NULL;\n    SBUInteger itemIndex;\n    SBBoolean itemFound;\n\n    itemIndex = SBAttributeListBinarySearchIndex(&dictionary->_list, attributeID, &itemFound);\n\n    if (itemFound) {\n        SBAttributeItem *item = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n        value = SBAttributeItemGetValuePtr(item);\n    }\n\n    return value;\n}\n\nSB_INTERNAL SBBoolean AttributeDictionaryMatchAny(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup, SBAttributeRegistryRef registry)\n{\n    SBUInteger itemCount = SBAttributeListSize(&dictionary->_list);\n    SBUInteger itemIndex;\n\n    /* Iterate through all items */\n    for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {\n        SBAttributeItem *currentItem = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n\n        /* Return true if there is a match */\n        if (CheckAttributeMatchesFilter(currentItem, registry, targetScope, targetGroup)) {\n            return SBTrue;\n        }\n    }\n\n    return SBFalse;\n}\n\nSB_INTERNAL SBBoolean AttributeDictionaryMatchAll(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup,\n    SBAttributeRegistryRef registry, AttributeDictionaryRef other)\n{\n    SBUInteger dictCount = SBAttributeListSize(&dictionary->_list);\n    SBUInteger otherCount = SBAttributeListSize(&other->_list);\n    SBUInteger dictIndex;\n    SBUInteger otherIndex;\n\n    dictIndex = 0;\n    otherIndex = 0;\n\n    /* Compare filtered elements from both dictionaries */\n    while (dictIndex < dictCount && otherIndex < otherCount) {\n        SBAttributeItem *dictItem;\n        SBAttributeItem *otherItem;\n\n        dictItem = SBAttributeListGetAt(&dictionary->_list, dictIndex);\n        otherItem = SBAttributeListGetAt(&other->_list, otherIndex);\n\n        /* Skip non-matching items in the primary dictionary */\n        if (!CheckAttributeMatchesFilter(dictItem, registry, targetScope, targetGroup)) {\n            dictIndex += 1;\n            continue;\n        }\n\n        /* Skip non-matching items in the other dictionary */\n        if (!CheckAttributeMatchesFilter(otherItem, registry, targetScope, targetGroup)) {\n            otherIndex += 1;\n            continue;\n        }\n\n        /* Both items match the filter; verify they have the same ID and equal values */\n        if (dictItem->attributeID != otherItem->attributeID ||\n            !SBAttributeRegistryIsEqualAttribute(registry, dictItem->attributeID,\n                SBAttributeItemGetValuePtr(dictItem), SBAttributeItemGetValuePtr(otherItem))) {\n            return SBFalse;\n        }\n\n        dictIndex += 1;\n        otherIndex += 1;\n    }\n\n    /* Verify primary dictionary has no remaining filtered elements */\n    while (dictIndex < dictCount) {\n        SBAttributeItem *currentItem = SBAttributeListGetAt(&dictionary->_list, dictIndex);\n\n        if (CheckAttributeMatchesFilter(currentItem, registry, targetScope, targetGroup)) {\n            return SBFalse;\n        }\n\n        dictIndex += 1;\n    }\n\n    /* Verify other dictionary has no remaining filtered elements */\n    while (otherIndex < otherCount) {\n        SBAttributeItem *currentItem = SBAttributeListGetAt(&other->_list, otherIndex);\n\n        if (CheckAttributeMatchesFilter(currentItem, registry, targetScope, targetGroup)) {\n            return SBFalse;\n        }\n\n        otherIndex += 1;\n    }\n\n    return SBTrue;\n}\n\nSB_INTERNAL void AttributeDictionaryRemove(AttributeDictionaryRef dictionary,\n    SBAttributeID attributeID, SBAttributeRegistryRef registry, SBBoolean *unchanged)\n{\n    SBUInteger itemIndex;\n    SBBoolean itemFound;\n\n    itemIndex = SBAttributeListBinarySearchIndex(&dictionary->_list, attributeID, &itemFound);\n\n    if (itemFound) {\n        SBAttributeItem *item = SBAttributeListGetAt(&dictionary->_list, itemIndex);\n\n        if (registry) {\n            const void *valuePtr = SBAttributeItemGetValuePtr(item);\n\n            /* Release the attribute value through the registry before removal */\n            SBAttributeRegistryReleaseAttribute(registry, valuePtr);\n        }\n\n        /* Remove the item from the list */\n        SBAttributeListRemoveAt(&dictionary->_list, itemIndex);\n    }\n\n    if (unchanged) {\n        *unchanged = !itemFound;\n    }\n}\n\nSB_INTERNAL void AttributeDictionaryClear(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry)\n{\n    ReleaseAllAttributeItems(dictionary, registry);\n    SBAttributeListRemoveAll(&dictionary->_list);\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Text/AttributeDictionary.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATTRIBUTE_DICTIONARY_H\n#define _SB_INTERNAL_ATTRIBUTE_DICTIONARY_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <API/SBAttributeList.h>\n\ntypedef struct _AttributeDictionary {\n    SBAttributeList _list;\n} AttributeDictionary, *AttributeDictionaryRef;\n\n/**\n * Initializes an attribute dictionary.\n *\n * @param dictionary\n *      The attribute dictionary to initialize.\n * @param valueSize\n *      The size in bytes of attribute values.\n */\nSB_INTERNAL void AttributeDictionaryInitialize(AttributeDictionaryRef dictionary, SBUInt8 valueSize);\n\n/**\n * Finalizes an attribute dictionary and releases all resources.\n *\n * @param dictionary\n *      The attribute dictionary to finalize.\n * @param registry\n *      The attribute registry used to release attribute values.\n */\nSB_INTERNAL void AttributeDictionaryFinalize(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry);\n\n/**\n * Creates a new attribute dictionary.\n *\n * @param valueSize\n *      The size in bytes of attribute values.\n * @return\n *      A new attribute dictionary reference, or NULL if allocation fails.\n */\nSB_INTERNAL AttributeDictionaryRef AttributeDictionaryCreate(SBUInt8 valueSize);\n\n/**\n * Deallocates an attribute dictionary.\n *\n * @param dictionary\n *      The attribute dictionary to deallocate.\n * @param registry\n *      The attribute registry used to release attribute values.\n */\nSB_INTERNAL void AttributeDictionaryDestroy(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry);\n\n#define AttributeDictionaryGetCount(dictionary)     \\\n    SBAttributeListSize(&(dictionary)->_list)\n\n/**\n * Checks whether an attribute dictionary is empty.\n *\n * @param dictionary\n *      The attribute dictionary to check.\n * @return\n *      `SBTrue` if empty, `SBFalse` otherwise.\n */\nSB_INTERNAL SBBoolean AttributeDictionaryIsEmpty(AttributeDictionaryRef dictionary);\n\n/**\n * Clears this dictionary and copies all attributes from the source, retaining their values.\n *\n * @param dictionary\n *      The attribute dictionary to modify.\n * @param other\n *      The source dictionary to copy from.\n * @param registry\n *      The attribute registry for value lifecycle management.\n */\nSB_INTERNAL void AttributeDictionarySet(AttributeDictionaryRef dictionary,\n    AttributeDictionaryRef other, SBAttributeRegistryRef registry);\n\n/**\n * Adds or updates an attribute item in the dictionary.\n *\n * If the attribute exists, updates its value; otherwise inserts it in sorted order.\n *\n * @param dictionary\n *      The destination dictionary.\n * @param attributeID\n *      The attribute ID to add or update.\n * @param attributeValue\n *      The attribute value.\n * @param registry\n *      The attribute registry for value lifecycle management.\n * @param unchanged\n *      Optional output parameter. Set to SBTrue if the item already existed with an equal value,\n *      SBFalse if item was inserted or value was changed.\n */\nSB_INTERNAL void AttributeDictionaryPut(AttributeDictionaryRef dictionary,\n    SBAttributeID attributeID, const void *attributeValue, SBAttributeRegistryRef registry,\n    SBBoolean *unchanged);\n\n/**\n * Merges all attributes from another dictionary into this dictionary.\n *\n * @param dictionary\n *      The destination dictionary.\n * @param other\n *      The source dictionary to merge from.\n * @param registry\n *      The attribute registry for value lifecycle management.\n * @param unchanged\n *      Optional output parameter. Set to SBTrue if all items already existed with equal values,\n *      SBFalse if any item was inserted or modified.\n */\nSB_INTERNAL void AttributeDictionaryMerge(AttributeDictionaryRef dictionary,\n    AttributeDictionaryRef other, SBAttributeRegistryRef registry, SBBoolean *unchanged);\n\n/**\n * Retrieves filtered attributes matching the specified scope and group.\n *\n * @param dictionary\n *      The attribute dictionary to query.\n * @param targetScope\n *      The attribute scope to filter by (e.g., character or paragraph).\n * @param targetGroup\n *      The attribute group to filter by. If SBAttributeGroupNone is specified, all groups within\n *      the scope are included.\n * @param registry\n *      The attribute registry used to retrieve attribute metadata for filtering.\n * @param result\n *      The dictionary where matching items will be added. Will be empty if no attributes match.\n *      Always cleared at the start.\n */\nSB_INTERNAL void AttributeDictionaryFilter(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup,\n    SBAttributeRegistryRef registry, AttributeDictionaryRef result);\n\n/**\n * Searches for an attribute value by ID.\n *\n * @param dictionary\n *      The attribute dictionary to search.\n * @param attributeID\n *      The attribute ID to search for.\n * @return\n *      A pointer to the matching attribute value, or NULL if not found.\n */\nSB_INTERNAL const void *AttributeDictionaryFindValue(AttributeDictionaryRef dictionary,\n    SBAttributeID attributeID);\n\n/**\n * Checks if any attribute matching the specified scope and group exists in the dictionary.\n *\n * @param dictionary\n *      The attribute dictionary to check.\n * @param targetScope\n *      The attribute scope to filter by (e.g., character or paragraph).\n * @param targetGroup\n *      The attribute group to filter by (or SBAttributeGroupNone for no group filtering).\n * @param registry\n *      The attribute registry used to retrieve attribute metadata for filtering.\n * @return\n *      SBTrue if at least one matching attribute exists, SBFalse otherwise.\n */\nSB_INTERNAL SBBoolean AttributeDictionaryMatchAny(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup, SBAttributeRegistryRef registry);\n\n/**\n * Checks if all filtered attributes have equal values between two dictionaries.\n *\n * Compares filtered attributes (by scope and group) for equality and verifies both dictionaries\n * have the same filtered content.\n *\n * @param dictionary\n *      The attribute dictionary to check.\n * @param targetScope\n *      The attribute scope to filter by (e.g., character or paragraph).\n * @param targetGroup\n *      The attribute group to filter by, or SBAttributeGroupNone to include all groups.\n * @param registry\n *      The attribute registry used to retrieve attribute metadata and compare equality.\n * @param other\n *      The other attribute dictionary to compare against.\n * @return\n *      SBTrue if all filtered attributes exist in both dictionaries with equal values and neither\n *      dictionary has extra filtered attributes, SBFalse otherwise.\n */\nSB_INTERNAL SBBoolean AttributeDictionaryMatchAll(AttributeDictionaryRef dictionary,\n    SBAttributeScope targetScope, SBAttributeGroup targetGroup,\n    SBAttributeRegistryRef registry, AttributeDictionaryRef other);\n\n/**\n * Removes an attribute with the specified ID.\n *\n * @param dictionary\n *      The attribute dictionary from which to remove the attribute.\n * @param attributeID\n *      The ID of the attribute to remove.\n * @param registry\n *      The attribute registry used to release the attribute value.\n * @param unchanged\n *      Optional output parameter. Set to SBTrue if the attribute was not found, SBFalse if it was\n *      removed.\n */\nSB_INTERNAL void AttributeDictionaryRemove(AttributeDictionaryRef dictionary,\n    SBAttributeID attributeID, SBAttributeRegistryRef registry, SBBoolean *unchanged);\n\n/**\n * Removes all attributes from the dictionary.\n *\n * @param dictionary\n *      The attribute dictionary to clear.\n * @param registry\n *      The attribute registry used to release attribute values.\n */\nSB_INTERNAL void AttributeDictionaryClear(AttributeDictionaryRef dictionary,\n    SBAttributeRegistryRef registry);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Text/AttributeManager.c",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <stddef.h>\n\n#include <API/SBAttributeRegistry.h>\n#include <API/SBText.h>\n#include <Core/List.h>\n#include <Text/AttributeDictionary.h>\n\n#include \"AttributeManager.h\"\n\n/* =========================================================================\n * Attribute Dictionary Cache Implementation\n * ========================================================================= */\n\n/**\n * Initializes an attribute dictionary cache.\n *\n * The cache stores reusable attribute dictionaries to reduce memory allocations\n * when attributes are frequently added and removed.\n */\nstatic void InitializeAttributeDictionaryCache(AttributeDictionaryCacheRef cache, SBUInt8 valueSize)\n{\n    ListInitialize(&cache->_attributeDicts, sizeof(AttributeDictionaryRef));\n    cache->_valueSize = valueSize;\n}\n\n/**\n * Finalizes an attribute dictionary cache and destroys all cached dictionaries.\n */\nstatic void FinalizeAttributeDictionaryCache(AttributeDictionaryCacheRef cache,\n    SBAttributeRegistryRef registry)\n{\n    SBUInteger dictCount = cache->_attributeDicts.count;\n    SBUInteger dictIndex;\n\n    /* Destroy all cached attribute dictionaries */\n    for (dictIndex = 0; dictIndex < dictCount; dictIndex++) {\n        AttributeDictionaryRef dictionary = ListGetVal(&cache->_attributeDicts, dictIndex);\n        AttributeDictionaryDestroy(dictionary, registry);\n    }\n\n    /* Finalize the cache list */\n    ListFinalize(&cache->_attributeDicts);\n}\n\n/**\n * Retrieves a cached attribute dictionary or creates a new one if the cache is empty.\n */\nstatic AttributeDictionaryRef AcquireAttributeDictionaryFromCache(AttributeDictionaryCacheRef cache)\n{\n    AttributeDictionaryRef dictionary = NULL;\n    SBUInteger dictCount = cache->_attributeDicts.count;\n\n    if (dictCount == 0) {\n        /* Create a new dictionary if the cache is empty */\n        dictionary = AttributeDictionaryCreate(cache->_valueSize);\n    } else {\n        /* Reuse the last cached dictionary */\n        dictionary = ListGetVal(&cache->_attributeDicts, dictCount - 1);\n        ListRemoveAt(&cache->_attributeDicts, dictCount - 1);\n    }\n\n    return dictionary;\n}\n\n/**\n * Caches an attribute dictionary for later reuse. The dictionary is cleared before caching.\n */\nstatic void StoreAttributeDictionaryInCache(AttributeDictionaryCacheRef cache,\n    AttributeDictionaryRef dictionary, SBAttributeRegistryRef registry)\n{\n    AttributeDictionaryClear(dictionary, registry);\n    ListAdd(&cache->_attributeDicts, &dictionary);\n}\n\n/* =========================================================================\n * Attribute Manager Implementation\n * ========================================================================= */\n\n/**\n * Operation types for attribute modifications.\n */\nenum {\n    AttributeOperationApply = 1,    /**< Apply/merge new attributes. */\n    AttributeOperationRemove = 2    /**< Remove specific attribute. */\n};\ntypedef SBUInt8 AttributeOperationType;\n\n/**\n * Determines which side of the split receives the modified attributes.\n */\nenum {\n    SplitUpdateTargetRight = 0,     /**< Right segment gets modified attributes. */\n    SplitUpdateTargetLeft = 1       /**< Left segment gets modified attributes. */\n};\ntypedef SBUInt8 SplitUpdateTarget;\n\n/**\n * Parameters for attribute operations.\n *\n * Uses a union to store operation-specific parameters without memory overhead.\n */\ntypedef union _AttributeOperationParams {\n    struct {\n        AttributeDictionaryRef attributes;  /**< Attributes to merge in. */\n    } apply;\n    struct {\n        SBAttributeID attributeID;          /**< Attribute ID to remove. */\n    } remove;\n} AttributeOperationParams;\n\n/**\n * Expands the range start to include the beginning of the first paragraph.\n */\nstatic void ExpandRangeToIncludeFirstParagraph(AttributeManagerRef manager, SBUInteger *rangeStart)\n{\n    SBTextRef text = manager->parent;\n    SBUInteger paragraphIndex;\n    TextParagraphRef paragraph;\n\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, *rangeStart);\n    paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n    /* Expand to paragraph start */\n    *rangeStart = paragraph->index;\n}\n\n/**\n * Expands the range end to include the end of the last paragraph.\n */\nstatic void ExpandRangeToIncludeLastParagraph(AttributeManagerRef manager, SBUInteger *rangeEnd)\n{\n    SBTextRef text = manager->parent;\n    SBUInteger paragraphIndex;\n    TextParagraphRef paragraph;\n\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, *rangeEnd - 1);\n    paragraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n    /* Expand to paragraph end */\n    *rangeEnd = paragraph->index + paragraph->length;\n}\n\n/**\n * Expands both range boundaries to fully include any partially covered paragraphs.\n */\nstatic void ExpandRangeToIncludeBoundaryParagraphs(AttributeManagerRef manager,\n    SBUInteger *rangeStart, SBUInteger *rangeEnd)\n{\n    ExpandRangeToIncludeFirstParagraph(manager, rangeStart);\n    ExpandRangeToIncludeLastParagraph(manager, rangeEnd);\n}\n\n/**\n * Shrinks the range start to exclude the first paragraph if it's not fully covered.\n */\nstatic void ShrinkRangeToExcludeFirstParagraph(AttributeManagerRef manager,\n    SBUInteger *rangeStart, SBUInteger rangeEnd)\n{\n    SBTextRef text = manager->parent;\n    SBUInteger paragraphIndex;\n    TextParagraphRef textParagraph;\n    SBUInteger paragraphStart;\n    SBUInteger paragraphEnd;\n\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, *rangeStart);\n    textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n    paragraphStart = textParagraph->index;\n    paragraphEnd = paragraphStart + textParagraph->length;\n\n    /* Exclude the paragraph if not fully covered */\n    if (*rangeStart > paragraphStart) {\n        *rangeStart = paragraphEnd;\n\n        /* Clamp to rangeEnd */\n        if (*rangeStart > rangeEnd) {\n            *rangeStart = rangeEnd;\n        }\n    }\n}\n\n/**\n * Shrinks the range end to exclude the last paragraph if it's not fully covered.\n */\nstatic void ShrinkRangeToExcludeLastParagraph(AttributeManagerRef manager,\n    SBUInteger rangeStart, SBUInteger *rangeEnd)\n{\n    SBTextRef text = manager->parent;\n    SBUInteger paragraphIndex;\n    TextParagraphRef textParagraph;\n    SBUInteger paragraphStart;\n    SBUInteger paragraphEnd;\n\n    paragraphIndex = SBTextGetCodeUnitParagraphIndex(text, *rangeEnd - 1);\n    textParagraph = ListGetRef(&text->paragraphs, paragraphIndex);\n\n    paragraphStart = textParagraph->index;\n    paragraphEnd = paragraphStart + textParagraph->length;\n\n    /* Exclude paragraph if not fully covered */\n    if (paragraphEnd < *rangeEnd) {\n        *rangeEnd = paragraphStart;\n\n        /* Clamp to rangeStart */\n        if (*rangeEnd < rangeStart) {\n            *rangeEnd = rangeStart;\n        }\n    }\n}\n\n/**\n * Shrinks a range to exclude boundary paragraphs that are not fully covered.\n */\nstatic void ShrinkRangeToExcludeBoundaryParagraphs(AttributeManagerRef manager,\n    SBUInteger *rangeStart, SBUInteger *rangeEnd)\n{\n    ShrinkRangeToExcludeFirstParagraph(manager, rangeStart, *rangeEnd);\n\n    if (*rangeEnd > *rangeStart) {\n        ShrinkRangeToExcludeLastParagraph(manager, *rangeStart, rangeEnd);\n    }\n}\n\n/**\n * Calculates the end index (exclusive) of an attribute entry.\n *\n * For all entries except the last, the end is the start of the next entry.\n * For the last entry, the end is the total code unit count.\n */\nstatic SBUInteger GetAttributeEntryEndIndex(AttributeManagerRef manager, SBUInteger entryIndex)\n{\n    if (entryIndex < manager->_entries.count - 1) {\n        const AttributeEntry *nextEntry = ListGetRef(&manager->_entries, entryIndex + 1);\n        return nextEntry->index;\n    }\n\n    return manager->_stringLength;\n}\n\n/**\n * Shifts all entry indices starting from a given position by a delta amount.\n */\nstatic void ShiftAttributeEntryRanges(AttributeManagerRef manager,\n    SBUInteger entryIndex, SBInteger indexDelta) {\n    while (entryIndex < manager->_entries.count) {\n        AttributeEntry *currentEntry = ListGetRef(&manager->_entries, entryIndex);\n        currentEntry->index += indexDelta;\n        entryIndex += 1;\n    }\n}\n\n/**\n * Applies an attribute operation to a dictionary.\n *\n * @param attributes\n *      The attribute dictionary to modify.\n * @param operation\n *      Type of operation to perform.\n * @param params\n *      Operation-specific parameters.\n * @param unchanged\n *      Optional output: set to SBTrue if no changes were made.\n */\nstatic void ApplyOperationToAttributes(AttributeDictionaryRef attributes,\n    AttributeOperationType operation, AttributeOperationParams params,\n    SBAttributeRegistryRef registry, SBBoolean *unchanged)\n{\n    switch (operation) {\n    case AttributeOperationApply:\n        AttributeDictionaryMerge(attributes, params.apply.attributes, registry, unchanged);\n        break;\n    case AttributeOperationRemove:\n        AttributeDictionaryRemove(attributes, params.remove.attributeID, registry, unchanged);\n        break;\n    }\n}\n\n/**\n * Splits an attribute entry at specified index and applies operation to one side.\n *\n * @param manager\n *      The attribute manager containing the entries.\n * @param entryIndex\n *      Index of the entry to split.\n * @param splitIndex\n *      Code unit index where to split the entry.\n * @param operation\n *      Operation to apply after split.\n * @param params\n *      Operation parameters.\n * @param updateTarget\n *      Which side of split receives the modified attributes.\n * @return\n *      SBTrue if split was performed, SBFalse if no split needed.\n */\nstatic SBBoolean SplitAttributesEntry(AttributeManagerRef manager,\n    SBUInteger entryIndex, SBUInteger splitIndex, AttributeOperationType operation,\n    AttributeOperationParams params, SplitUpdateTarget updateTarget)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n    AttributeEntry firstEntry;\n    SBUInteger entryEnd;\n\n    firstEntry = ListGetVal(&manager->_entries, entryIndex);\n    entryEnd = GetAttributeEntryEndIndex(manager, entryIndex);\n\n    /* Only split if split index is strictly between entry boundaries */\n    if (splitIndex > firstEntry.index && splitIndex < entryEnd) {\n        SBBoolean unchanged = SBTrue;\n        AttributeDictionaryRef modifiedAttributes;\n\n        /* Create working copy of attributes for modification */\n        modifiedAttributes = AcquireAttributeDictionaryFromCache(&manager->_cache);\n        AttributeDictionarySet(modifiedAttributes, firstEntry.attributes, registry);\n\n        /* Apply operation to determine if changes would occur */\n        ApplyOperationToAttributes(modifiedAttributes, operation, params, registry, &unchanged);\n\n        if (unchanged) {\n            /* Operation produces no change - no split needed, cache the copy */\n            StoreAttributeDictionaryInCache(&manager->_cache, modifiedAttributes, registry);\n        } else {\n            AttributeEntry newEntry;\n            newEntry.index = splitIndex;\n\n            if (updateTarget == SplitUpdateTargetRight) {\n                /* Right side gets modified attributes, left side keeps original */\n                newEntry.attributes = modifiedAttributes;\n            } else {\n                AttributeEntry *original = ListGetRef(&manager->_entries, entryIndex);\n\n                /* Left side gets modified attributes, right side keeps original */\n                newEntry.attributes = original->attributes;\n                original->attributes = modifiedAttributes;\n            }\n\n            ListInsert(&manager->_entries, entryIndex + 1, &newEntry);\n\n            return SBTrue;\n        }\n    }\n\n    return SBFalse;\n}\n\n/**\n * Core implementation for applying attribute operations over a code unit range.\n *\n * Handles three cases:\n * 1. Operation covers entire entry - apply directly\n * 2. Operation is entirely within one entry - split into 3 entries\n * 3. Operation spans multiple entries - split at boundaries and apply to all\n * \n * @param manager\n *      The attribute manager to modify.\n * @param index\n *      Starting code unit index of operation range.\n * @param length\n *      Number of code units in operation range.\n * @param operation\n *      Type of operation to perform.\n * @param params\n *      Operation-specific parameters.\n */\nstatic void ApplyOperationOverRange(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length,\n    AttributeOperationType operation, AttributeOperationParams params)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n    SBUInteger rangeStart = index;\n    SBUInteger rangeEnd = index + length;\n    SBUInteger entryIndex;\n    AttributeEntry *entry;\n    SBUInteger entryEnd;\n\n    /* Locate the entry containing the range start */\n    entry = AttributeManagerFindEntry(manager, rangeStart, &entryIndex, &entryEnd);\n\n    if (rangeStart == entry->index && rangeEnd == entryEnd) {\n        /* CASE 1: Operation covers entire entry exactly */\n        ApplyOperationToAttributes(entry->attributes, operation, params, registry, NULL);\n    } else if (rangeStart > entry->index && rangeEnd < entryEnd) {\n        /* CASE 2: Operation is entirely within one entry - split into 3 */\n        AttributeDictionaryRef modifiedAttributes;\n        SBBoolean unchanged;\n\n        modifiedAttributes = AcquireAttributeDictionaryFromCache(&manager->_cache);\n        AttributeDictionarySet(modifiedAttributes, entry->attributes, registry);\n        ApplyOperationToAttributes(modifiedAttributes, operation, params, registry, &unchanged);\n\n        if (unchanged) {\n            /* No changes needed - don't split */\n            StoreAttributeDictionaryInCache(&manager->_cache, modifiedAttributes, registry);\n        } else {\n            AttributeDictionaryRef cloneAttributes;\n\n            cloneAttributes = AcquireAttributeDictionaryFromCache(&manager->_cache);\n            AttributeDictionarySet(cloneAttributes, entry->attributes, registry);\n\n            /* Reserve space for 2 new entries */\n            ListReserveRange(&manager->_entries, entryIndex + 1, 2);\n\n            /* Middle entry: gets modified attributes */\n            entry = ListGetRef(&manager->_entries, entryIndex + 1);\n            entry->index = rangeStart;\n            entry->attributes = modifiedAttributes;\n\n            /* Right entry: keeps original attributes */\n            entry = ListGetRef(&manager->_entries, entryIndex + 2);\n            entry->index = rangeEnd;\n            entry->attributes = cloneAttributes;\n        }\n    } else {\n        /* CASE 3: Operation spans multiple entries - handle boundaries and interior */\n        SBBoolean entryProcessed = SBFalse;\n\n        /* Split at range start if needed */\n        if (SplitAttributesEntry(manager, entryIndex, rangeStart,\n                operation, params, SplitUpdateTargetRight)) {\n            entryProcessed = SBTrue;    /* Split already applied operation */\n            entryIndex += 1;            /* Move to new right-side entry */\n        }\n\n        /* Process all entries intersecting with the operation range */\n        while (rangeStart < rangeEnd) {\n            entry = ListGetRef(&manager->_entries, entryIndex);\n            entryEnd = GetAttributeEntryEndIndex(manager, entryIndex);\n\n            /* Split at range end if current entry extends beyond operation range */\n            if (entryEnd > rangeEnd) {\n                /*\n                 * Split at range end - modified attributes go to left side (range interior) so the\n                 * portion inside range gets the operation applied\n                 */\n                SplitAttributesEntry(manager, entryIndex, rangeEnd,\n                    operation, params, SplitUpdateTargetLeft);\n                /* Remaining portion beyond range is unmodified */\n                break;\n            }\n\n            /* Apply operation to current entry if not already processed by split */\n            if (!entryProcessed) {\n                ApplyOperationToAttributes(entry->attributes, operation, params, registry, NULL);\n            }\n\n            /* Advance to next entry */\n            rangeStart = entryEnd;\n            entryIndex += 1;\n            entryProcessed = SBFalse;\n        }\n    }\n}\n\n/**\n * Applies a set of attributes over a range by merging them into existing attributes.\n */\nstatic void ApplyAttributesOverRange(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, AttributeDictionaryRef attributes)\n{\n    AttributeOperationParams params;\n    params.apply.attributes = attributes;\n\n    ApplyOperationOverRange(manager, index, length, AttributeOperationApply, params);\n}\n\n/**\n * Removes a specific attribute from a range of code units.\n */\nstatic void RemoveAttributeFromRange(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, SBAttributeID attributeID)\n{\n    AttributeOperationParams params;\n    params.remove.attributeID = attributeID;\n\n    ApplyOperationOverRange(manager, index, length, AttributeOperationRemove, params);\n}\n\n/**\n * Adjusts paragraph-scoped attributes after text has been removed.\n *\n * When text is removed, separate paragraphs may merge into one. This function ensures\n * paragraph-scoped attributes are consistent across the merged boundary by:\n * - Copying paragraph attributes from before the merge point to the second half\n * - Copying paragraph attributes from after the merge point to the first half\n */\nstatic void AdjustParagraphAttributesAfterMerge(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger newLength)\n{\n    SBUInteger rangeEnd = index + newLength;\n    SBUInteger mergePointIndex = rangeEnd;\n\n    if (mergePointIndex > 0 && mergePointIndex < manager->_stringLength) {\n        SBUInteger precedingIndex = mergePointIndex - 1;\n        SBBoolean paragraphsMerged;\n        TextParagraphRef precedingParagraph;\n        TextParagraphRef followingParagraph;\n\n        SBTextGetBoundaryParagraphs(manager->parent, precedingIndex, mergePointIndex,\n            &precedingParagraph, &followingParagraph);\n        paragraphsMerged = (precedingParagraph && followingParagraph\n            && precedingParagraph == followingParagraph);\n\n        if (paragraphsMerged) {\n            SBAttributeRegistryRef registry = manager->_registry;\n            SBUInteger paragraphStart = precedingParagraph->index;\n            SBUInteger paragraphEnd = paragraphStart + precedingParagraph->length;\n            AttributeDictionaryRef paragraphAttributes;\n            AttributeEntry *entry;\n\n            paragraphAttributes = &manager->_tempDict;\n\n            /* Extract paragraph-scoped attributes from before the merge point */\n            entry = AttributeManagerFindEntry(manager, precedingIndex, NULL, NULL);\n\n            AttributeDictionaryFilter(entry->attributes,\n                SBAttributeScopeParagraph, SBAttributeGroupNone, registry, paragraphAttributes);\n\n            if (!AttributeDictionaryIsEmpty(paragraphAttributes)) {\n                /* Apply to the second half of the merged paragraph */\n                ApplyAttributesOverRange(manager,\n                    mergePointIndex, paragraphEnd - mergePointIndex, paragraphAttributes);\n            }\n\n            /* Extract paragraph-scoped attributes from after the merge point */\n            entry = AttributeManagerFindEntry(manager, mergePointIndex, NULL, NULL);\n\n            AttributeDictionaryFilter(entry->attributes,\n                SBAttributeScopeParagraph, SBAttributeGroupNone, registry, paragraphAttributes);\n\n            if (!AttributeDictionaryIsEmpty(paragraphAttributes)) {\n                /* Apply to the first half of the merged paragraph */\n                ApplyAttributesOverRange(manager,\n                    paragraphStart, mergePointIndex - paragraphStart, paragraphAttributes);\n            }\n        }\n    }\n}\n\n/**\n * Inserts the first attribute entry at index 0 with an empty attribute dictionary.\n *\n * This is called during initialization to create a base entry covering the entire text.\n */\nstatic void InsertFirstAttributeEntry(AttributeManagerRef manager)\n{\n    AttributeEntry entry;\n\n    entry.index = 0;\n    entry.attributes = AcquireAttributeDictionaryFromCache(&manager->_cache);\n\n    ListAdd(&manager->_entries, &entry);\n}\n\n/**\n * Removes and caches a range of attribute entries.\n *\n * Attempts to cache each removed entry's dictionary for reuse, then removes all entries in the\n * specified range from the entries list.\n */\nstatic void RemoveAttributeEntryRange(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n    SBUInteger rangeEnd = index + length;\n    SBUInteger entryIndex;\n\n    for (entryIndex = index; entryIndex < rangeEnd; entryIndex++) {\n        AttributeEntry *entry = ListGetRef(&manager->_entries, entryIndex);\n        StoreAttributeDictionaryInCache(&manager->_cache, entry->attributes, registry);\n    }\n\n    ListRemoveRange(&manager->_entries, index, length);\n}\n\nSB_INTERNAL void AttributeManagerInitialize(AttributeManagerRef manager,\n    SBTextRef parent, SBAttributeRegistryRef registry)\n{\n    manager->parent = parent;\n    manager->_registry = registry;\n    manager->_stringLength = 0;\n\n    if (registry) {\n        /* Initialize all structures only when a registry is provided */\n        InitializeAttributeDictionaryCache(&manager->_cache, registry->valueSize);\n        AttributeDictionaryInitialize(&manager->_tempDict, registry->valueSize);\n        ListInitialize(&manager->_entries, sizeof(AttributeEntry));\n        InsertFirstAttributeEntry(manager);\n    }\n}\n\nSB_INTERNAL void AttributeManagerFinalize(AttributeManagerRef manager)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n\n    if (registry) {\n        SBUInteger entryCount = manager->_entries.count;\n        SBUInteger entryIndex;\n\n        AttributeDictionaryFinalize(&manager->_tempDict, NULL);\n        FinalizeAttributeDictionaryCache(&manager->_cache, registry);\n\n        /* Finalize all entries */\n        for (entryIndex = 0; entryIndex < entryCount; entryIndex++) {\n            AttributeEntry *entry = ListGetRef(&manager->_entries, entryIndex);\n            AttributeDictionaryDestroy(entry->attributes, registry);\n        }\n\n        ListFinalize(&manager->_entries);\n    }\n}\n\nSB_INTERNAL void AttributeManagerCopyAttributes(AttributeManagerRef manager,\n    const AttributeManager *source)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n\n    if (registry) {\n        SBUInteger entryCount = source->_entries.count;\n        SBUInteger entryIndex;\n\n        /* Clear existing entries and cache their dictionaries */\n        RemoveAttributeEntryRange(manager, 0, manager->_entries.count);\n        /* Reserve space for source entries */\n        ListReserveRange(&manager->_entries, 0, entryCount);\n\n        /* Deep copy each entry and its attributes */\n        for (entryIndex = 0; entryIndex < entryCount; entryIndex++) {\n            const AttributeEntry *sourceEntry = ListGetRef(&source->_entries, entryIndex);\n            AttributeEntry *newEntry = ListGetRef(&manager->_entries, entryIndex);\n            AttributeDictionaryRef cloneAttributes;\n\n            cloneAttributes = AcquireAttributeDictionaryFromCache(&manager->_cache);\n            AttributeDictionarySet(cloneAttributes, sourceEntry->attributes, registry);\n\n            newEntry->index = sourceEntry->index;\n            newEntry->attributes = cloneAttributes;\n        }\n\n        manager->_stringLength = source->_stringLength;\n    }\n}\n\nSB_INTERNAL AttributeEntry *AttributeManagerFindEntry(AttributeManagerRef manager,\n    SBUInteger stringIndex, SBUInteger *entryIndex, SBUInteger *entryEnd)\n{\n    AttributeEntry *entries = manager->_entries.items;\n    SBUInteger count = manager->_entries.count;\n    SBUInteger stringLength = manager->_stringLength;\n    SBUInteger low;\n    SBUInteger high;\n\n    SBAssert(entries && count > 0);\n\n    low = 0;\n    high = count - 1;\n\n    while (low <= high) {\n        SBUInteger mid = low + (high - low) / 2;\n        AttributeEntry *entry;\n        SBUInteger runStart;\n        SBUInteger runEnd;\n\n        entry = &entries[mid];\n        runStart = entry->index;\n        runEnd = (mid < count - 1) ? entries[mid + 1].index : stringLength;\n\n        if (stringIndex < runStart) {\n            /* Target is before the current entry */\n            high = mid - 1;\n        } else if (stringIndex >= runEnd) {\n            /* Target is after the current entry */\n            low = mid + 1;\n        } else {\n            /* Target is within the current entry */\n            if (entryIndex) {\n                *entryIndex = mid;\n            }\n            if (entryEnd) {\n                *entryEnd = runEnd;\n            }\n\n            return entry;\n        }\n    }\n\n    return NULL;\n}\n\nSB_INTERNAL void AttributeManagerReplaceRange(AttributeManagerRef manager,\n    SBUInteger replaceStart, SBUInteger oldLength, SBUInteger newLength)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n\n    if (registry) {\n        SBUInteger replaceEnd = replaceStart + oldLength;\n        SBInteger lengthDelta = (SBInteger)(newLength - oldLength);\n\n        if (replaceStart == manager->_stringLength) {\n            /* Appending at end - no entries to adjust */\n            manager->_stringLength += lengthDelta;\n        } else if (manager->_entries.count == 1) {\n            /* Single entry covers all text - simple update */\n            manager->_stringLength += lengthDelta;\n        } else {\n            SBUInteger stringIndex;\n            SBUInteger firstIndex;\n            SBUInteger entryEnd;\n            SBUInteger shiftStart;\n\n            /* Select which adjacent code unit's attributes to extend into the range */\n            if (oldLength == 0 && replaceStart > 0) {\n                /* Insertion: use attributes from the code unit before insertion point */\n                stringIndex = replaceStart - 1;\n            } else {\n                /* Replacement: use attributes from the first replaced code unit */\n                stringIndex = replaceStart;\n            }\n\n            /* Find the entry containing the reference code unit */\n            AttributeManagerFindEntry(manager, stringIndex, &firstIndex, &entryEnd);\n            shiftStart = firstIndex + 1;\n\n            /* Remove entries that are completely covered by the replacement range */\n            if (entryEnd < replaceEnd) {\n                SBUInteger removalStart = firstIndex + 1; /* Keep first entry */\n                SBUInteger removalCount = 0;\n                SBUInteger scanIndex;\n\n                /* Scan entries to find which ones are completely covered */\n                for (scanIndex = removalStart; scanIndex < manager->_entries.count; scanIndex++) {\n                    entryEnd = GetAttributeEntryEndIndex(manager, scanIndex);\n\n                    if (entryEnd <= replaceEnd) {\n                        /* This entry is completely within replacement range - mark for removal */\n                        removalCount += 1;\n                    } else {\n                        /* Entry extends beyond replacement range - adjust its start position */\n                        AttributeEntry *currentEntry = ListGetRef(&manager->_entries, scanIndex);\n                        currentEntry->index = replaceEnd;\n                        break;\n                    }\n                }\n\n                /* Remove all marked entries */\n                RemoveAttributeEntryRange(manager, removalStart, removalCount);\n            }\n\n            /* Special handling for pure deletions */\n            if (newLength == 0) {\n                AttributeEntry *entry = ListGetRef(&manager->_entries, firstIndex);\n                entryEnd = GetAttributeEntryEndIndex(manager, firstIndex);\n\n                /* Check if the first entry exactly matches the deleted range */\n                if (entry->index == replaceStart && entryEnd == replaceEnd) {\n                    if (firstIndex != 0 || manager->_entries.count > 1) {\n                        /* Safe to delete - not the only entry */\n                        RemoveAttributeEntryRange(manager, firstIndex, 1);\n                        shiftStart -= 1;\n                    } else {\n                        /* This is the only entry - reset it to cover the empty text */\n                        AttributeDictionaryClear(entry->attributes, registry);\n                        entry->index = 0;\n                    }\n                }\n            }\n\n            /* Shift all entries after the modified region */\n            ShiftAttributeEntryRanges(manager, shiftStart, lengthDelta);\n            manager->_stringLength += lengthDelta;\n\n            if (newLength == 0 || oldLength > 0) {\n                /* Deletion or replacement can cause paragraph merges */\n                AdjustParagraphAttributesAfterMerge(manager, replaceStart, newLength);\n            }\n        }\n    }\n}\n\nSB_INTERNAL void AttributeManagerSetAttribute(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, SBAttributeID attributeID, const void *attributeValue)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n\n    SBAssert(length > 0);\n\n    if (registry) {\n        const SBAttributeInfo *attributeInfo;\n\n        attributeInfo = SBAttributeRegistryGetInfoReference(registry, attributeID);\n\n        if (attributeInfo) {\n            AttributeDictionaryRef attributes = &manager->_tempDict;\n\n            /* Expand the range for paragraph-scoped attributes */\n            if (attributeInfo->scope == SBAttributeScopeParagraph) {\n                SBUInteger startIndex = index;\n                SBUInteger endIndex = startIndex + length;\n\n                ExpandRangeToIncludeBoundaryParagraphs(manager, &startIndex, &endIndex);\n\n                index = startIndex;\n                length = endIndex - startIndex;\n            }\n\n            /* Prepare single-item dictionary with the attribute */\n            AttributeDictionaryClear(attributes, NULL);\n            AttributeDictionaryPut(attributes, attributeID, attributeValue, NULL, NULL);\n\n            /* Apply over the (possibly expanded) range */\n            ApplyAttributesOverRange(manager, index, length, attributes);\n        }\n    }\n}\n\nSB_INTERNAL void AttributeManagerRemoveAttribute(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, SBAttributeID attributeID)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n\n    SBAssert(length > 0);\n\n    if (registry) {\n        const SBAttributeInfo *attributeInfo;\n\n        attributeInfo = SBAttributeRegistryGetInfoReference(registry, attributeID);\n\n        /* Update the range in case of paragraph scope */\n        if (attributeInfo->scope == SBAttributeScopeParagraph) {\n            SBUInteger startIndex = index;\n            SBUInteger endIndex = startIndex + length;\n\n            ShrinkRangeToExcludeBoundaryParagraphs(manager, &startIndex, &endIndex);\n\n            index = startIndex;\n            length = endIndex - startIndex;\n        }\n\n        if (length > 0) {\n            RemoveAttributeFromRange(manager, index, length, attributeID);\n        }\n    }\n}\n\nSB_INTERNAL SBBoolean AttributeManagerGetOnwardRunByFilteringID(AttributeManagerRef manager,\n    SBUInteger *runStart, SBUInteger rangeEnd,\n    SBAttributeID attributeID, AttributeDictionaryRef output)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n    SBUInteger entryIndex;\n    const AttributeEntry *entry;\n    const void *initialValue;\n\n    /* Clear output dictionary before populating */\n    AttributeDictionaryClear(output, NULL);\n\n    /* Check for the possibility of a next run first */\n    if (*runStart >= rangeEnd) {\n        return SBFalse;\n    }\n\n    /* Get the first entry and look for the attribute in it */\n    entry = AttributeManagerFindEntry(manager, *runStart, &entryIndex, runStart);\n    initialValue = AttributeDictionaryFindValue(entry->attributes, attributeID);\n\n    entryIndex += 1;\n\n    if (initialValue) {\n        /* Put the initial item to the output dictionary */\n        AttributeDictionaryPut(output, attributeID, initialValue, NULL, NULL);\n\n        /* Iterate while the attribute value remains the same */\n        while (*runStart < rangeEnd) {\n            SBBoolean valuesMatched = SBFalse;\n            const void *subsequentValue;\n\n            entry = ListGetRef(&manager->_entries, entryIndex);\n            subsequentValue = AttributeDictionaryFindValue(entry->attributes, attributeID);\n\n            /* Check if the attribute value matches */\n            if (subsequentValue) {\n                valuesMatched = SBAttributeRegistryIsEqualAttribute(registry,\n                    attributeID, initialValue, subsequentValue);\n            }\n\n            /* Stop if the value changes */\n            if (!valuesMatched) {\n                break;\n            }\n\n            *runStart = GetAttributeEntryEndIndex(manager, entryIndex);\n            entryIndex += 1;\n        }\n    } else {\n        /* Iterate while the attribute doesn't exist */\n        while (*runStart < rangeEnd) {\n            const void *subsequentItem;\n\n            entry = ListGetRef(&manager->_entries, entryIndex);\n            subsequentItem = AttributeDictionaryFindValue(entry->attributes, attributeID);\n\n            /* Stop when the attribute appears */\n            if (subsequentItem) {\n                break;\n            }\n\n            *runStart = GetAttributeEntryEndIndex(manager, entryIndex);\n            entryIndex += 1;\n        }\n    }\n\n    if (*runStart > rangeEnd) {\n        *runStart = rangeEnd;\n    }\n\n    return SBTrue;\n}\n\nSB_INTERNAL SBBoolean AttributeManagerGetOnwardRunByFilteringCollection(AttributeManagerRef manager,\n    SBUInteger *runStart, SBUInteger rangeEnd,\n    SBAttributeScope filterScope, SBAttributeGroup filterGroup, AttributeDictionaryRef output)\n{\n    SBAttributeRegistryRef registry = manager->_registry;\n    SBUInteger entryIndex;\n    const AttributeEntry *entry;\n\n    /* Clear the output dictionary before populating */\n    AttributeDictionaryClear(output, NULL);\n\n    /* Check for the possibility of a next run first */\n    if (*runStart >= rangeEnd) {\n        return SBFalse;\n    }\n\n    /* Get the first entry and filter its attributes */\n    entry = AttributeManagerFindEntry(manager, *runStart, &entryIndex, runStart);\n    AttributeDictionaryFilter(entry->attributes, filterScope, filterGroup, registry, output);\n\n    entryIndex += 1;\n\n    if (AttributeDictionaryIsEmpty(output)) {\n        /* Iterate while no matching attributes exist */\n        while (*runStart < rangeEnd) {\n            entry = ListGetRef(&manager->_entries, entryIndex);\n\n            /* Stop when matching attributes appear */\n            if (AttributeDictionaryMatchAny(entry->attributes, filterScope, filterGroup, registry)) {\n                break;\n            }\n\n            *runStart = GetAttributeEntryEndIndex(manager, entryIndex);\n            entryIndex += 1;\n        }\n    } else {\n        /* Iterate while the filtered attributes remain the same */\n        while (*runStart < rangeEnd) {\n            entry = ListGetRef(&manager->_entries, entryIndex);\n\n            /* Stop if filtered attributes change */\n            if (!AttributeDictionaryMatchAll(entry->attributes, filterScope, filterGroup, registry, output)) {\n                break;\n            }\n\n            *runStart = GetAttributeEntryEndIndex(manager, entryIndex);\n            entryIndex += 1;\n        }\n    }\n\n    if (*runStart > rangeEnd) {\n        *runStart = rangeEnd;\n    }\n\n    return SBTrue;\n}\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/Text/AttributeManager.h",
    "content": "/*\n * Copyright (C) 2025-2026 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ATTRIBUTE_MANAGER_H\n#define _SB_INTERNAL_ATTRIBUTE_MANAGER_H\n\n#include <API/SBBase.h>\n\n#if SB_TEXT_API_SUPPORTED\n\n#include <SheenBidi/SBAttributeInfo.h>\n#include <SheenBidi/SBAttributeRegistry.h>\n#include <SheenBidi/SBText.h>\n\n#include <Core/List.h>\n#include <Text/AttributeDictionary.h>\n\ntypedef struct _AttributeDictionaryCache {\n    LIST(AttributeDictionaryRef) _attributeDicts;\n    SBUInt8 _valueSize;\n} AttributeDictionaryCache, *AttributeDictionaryCacheRef;\n\ntypedef struct _AttributeEntry {\n    SBUInteger index;\n    AttributeDictionaryRef attributes;\n} AttributeEntry;\n\ntypedef struct _AttributeManager {\n    SBTextRef parent;\n    SBAttributeRegistryRef _registry;\n    SBUInteger _stringLength;\n    AttributeDictionaryCache _cache;\n    AttributeDictionary _tempDict;\n    LIST(AttributeEntry) _entries;\n} AttributeManager, *AttributeManagerRef;\n\n/**\n * Initializes an attribute manager.\n *\n * Prepares the attribute manager for use by initializing its internal data structures. When a\n * registry is provided, the manager allocates a dictionary cache, a temporary dictionary for\n * operations, an entries list, and inserts the first entry at index 0 with an empty attribute\n * dictionary. If registry is NULL, the manager remains uninitialized and all subsequent operations\n * become no-ops.\n *\n * @param manager\n *      The attribute manager to initialize.\n * @param parent\n *      The parent text object that owns this manager.\n * @param registry\n *      The attribute registry for managing attribute retention and release. If NULL, the manager\n *      will not allocate resources and all operations will be skipped.\n */\nSB_INTERNAL void AttributeManagerInitialize(AttributeManagerRef manager,\n    SBTextRef parent, SBAttributeRegistryRef registry);\n\n/**\n * Finalizes an attribute manager and releases all resources.\n *\n * Releases all attribute dictionaries managed by the manager, clears the dictionary cache, and\n * finalizes all internal data structures. After calling this function, the manager must not be used\n * until re-initialized.\n *\n * @param manager\n *      The attribute manager to finalize. If initialized with NULL registry, this function safely\n *      returns without performing any operations.\n */\nSB_INTERNAL void AttributeManagerFinalize(AttributeManagerRef manager);\n\n/**\n * Copies all attributes from a source attribute manager to this manager.\n *\n * Creates deep copies of all attribute dictionaries from the source manager, preserving both the\n * entry indices and the attribute values. The process first removes and caches all existing entries\n * in the destination manager, reserves space for entries from the source, then iterates through\n * each source entry, copying its index and deep-copying its attribute dictionary (which retains all\n * attribute values through the registry).\n *\n * @param manager\n *      The attribute manager to copy attributes into.\n * @param source\n *      The source attribute manager to copy from. Must have the same registry.\n *\n * @note\n *      If the destination manager has no registry, this function returns immediately without\n *      performing any operations.\n * @note\n *      All existing entries and attributes in the destination manager are replaced, not appended\n *      to. The code unit count is also synchronized from the source.\n */\nSB_INTERNAL void AttributeManagerCopyAttributes(AttributeManagerRef manager,\n    const AttributeManager *source);\n\n/**\n * Finds the attribute entry containing a specific code unit index.\n *\n * Performs a binary search through the entries list to locate the entry that covers the given code\n * unit index. Each entry covers a range from its index to the start of the next entry (or to the\n * total code unit count for the last entry). Returns the entry reference and optionally sets the\n * entry index.\n *\n * @param manager\n *      The attribute manager to search.\n * @param stringIndex\n *      The code unit index to find.\n * @param[out] entryIndex\n *      Optional pointer to receive the index of the found entry in the entries list.\n *      If NULL, the entry index is not returned.\n * @return\n *      Pointer to the attribute entry containing the code unit, or NULL if not found.\n *      In practice, should always return a valid entry if the index is within valid bounds.\n */\nSB_INTERNAL AttributeEntry *AttributeManagerFindEntry(AttributeManagerRef manager,\n    SBUInteger stringIndex, SBUInteger *entryIndex, SBUInteger *entryEnd);\n\n/**\n * Replaces a range of text and adjusts attribute entries accordingly.\n *\n * @param manager\n *      The attribute manager to modify\n * @param replaceStart\n *      Starting index of the range to replace\n * @param oldLength\n *      Number of code units being replaced\n * @param newLength\n *      Number of code units in the replacement text\n *\n * @note\n *      - For insertions (oldLength == 0), uses attributes from previous code unit\n *      - For replacements, uses attributes from first replaced code unit\n *      - Handles paragraph merging when text is deleted\n */\nSB_INTERNAL void AttributeManagerReplaceRange(AttributeManagerRef manager,\n    SBUInteger replaceStart, SBUInteger oldLength, SBUInteger newLength);\n\n#define AttributeManagerReserveRange(manager, index, length) \\\n    AttributeManagerReplaceRange(manager, index, 0, length)\n\n#define AttributeManagerRemoveRange(manager, index, length) \\\n    AttributeManagerReplaceRange(manager, index, length, 0)\n\n/**\n * Sets an attribute over a range of code units with automatic scope expansion.\n *\n * Applies an attribute to all code units in the specified range. For paragraph-scoped attributes,\n * automatically expands the range to include complete paragraphs at the boundaries, ensuring that\n * paragraph attributes apply uniformly across entire paragraphs rather than partial ones. The\n * attribute value is retained through the registry.\n * The implementation prepares a single-item dictionary containing the attribute and applies it over\n * the (possibly expanded) range using the standard apply operation.\n *\n * @param manager\n *      The attribute manager to modify. If manager has no registry, this function returns\n *      immediately without performing any operations.\n * @param index\n *      The starting code unit index of the range.\n * @param length\n *      The number of code units in the range. Must be greater than 0. May be expanded for\n *      paragraph-scoped attributes.\n * @param attributeID\n *      The ID of the attribute to set.\n * @param attributeValue\n *      The value of the attribute. Will be retained via the registry and applied to the specified\n *      attribute ID.\n */\nSB_INTERNAL void AttributeManagerSetAttribute(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, SBAttributeID attributeID, const void *attributeValue);\n\n/**\n * Removes an attribute from a range of code units with automatic scope shrinking.\n *\n * Removes a specific attribute from all code units in the specified range. For paragraph-scoped\n * attributes, automatically shrinks the range to exclude any partially covered paragraphs at the\n * boundaries, ensuring that paragraph attributes are only removed from fully covered paragraphs. If\n * the range shrinks to zero length, no operation is performed. If the manager has no registry, this\n * function returns immediately without performing any operations.\n *\n * @param manager\n *      The attribute manager to modify.\n * @param index\n *      The starting code unit index of the range.\n * @param length\n *      The number of code units in the range. Must be greater than 0. May be shrunk for\n *      paragraph-scoped attributes.\n * @param attributeID\n *      The ID of the attribute to remove from the range.\n */\nSB_INTERNAL void AttributeManagerRemoveAttribute(AttributeManagerRef manager,\n    SBUInteger index, SBUInteger length, SBAttributeID attributeID);\n\n/**\n * Retrieves the next contiguous run with uniform value for a specific attribute.\n *\n * Finds the next \"run\" starting from runStart, where a run is a maximal contiguous range of code\n * units that either all have the same value for the specified attribute, or all lack the attribute\n * entirely.\n * The function first clears the output dictionary, then checks if the starting position is beyond\n * rangeEnd. It locates the first entry, extracts and examines the attribute, then extends the run\n * as far as possible while the attribute remains either present with equal value (using registry\n * equality comparison) or consistently absent. Updates runStart to point to the end of the found\n * run (exclusive) and populates the output dictionary with the attribute item if present in the\n * run, or leaves it empty if the run represents absent attributes.\n *\n * @param manager\n *      The attribute manager to query.\n * @param[in,out] runStart\n *      Pointer to the starting code unit index. On return, updated to the index immediately\n *      following the end of the found run.\n * @param rangeEnd\n *      The exclusive upper bound for the search. The run does not include this index.\n * @param attributeID\n *      The ID of the attribute to filter by.\n * @param[out] output\n *      Dictionary to populate with the attribute item if present in the run; will be empty if the\n *      run represents absent attributes. Always cleared at the start.\n * @return\n *      SBTrue if runStart < rangeEnd (a run was processed), SBFalse if runStart >= rangeEnd on\n *      entry (no more runs available).\n */\nSB_INTERNAL SBBoolean AttributeManagerGetOnwardRunByFilteringID(AttributeManagerRef manager,\n    SBUInteger *runStart, SBUInteger rangeEnd,\n    SBAttributeID attributeID, AttributeDictionaryRef output);\n\n/**\n * Retrieves the next contiguous run with uniform filtered attribute collection.\n *\n * Finds the next \"run\" starting from runStart, where a run is a maximal contiguous range of code\n * units that all have the same collection of attributes matching the specified scope and group\n * filters (or all have no matching attributes).\n * The function first clears the output dictionary, then checks if the starting position is beyond\n * rangeEnd. It locates the first entry and filters its attributes according to the scope and group.\n * If no matching attributes are found in the first entry, the run extends while no matching\n * attributes appear in subsequent entries. If matching attributes are found, the run extends while\n * all subsequent entries have exactly the same matching attributes (same IDs and equal values).\n * Updates runStart to point to the end of the found run (exclusive) and populates the output\n * dictionary with all matching attribute items from the run, or leaves it empty if the run\n * represents absence of matching attributes.\n *\n * @param manager\n *      The attribute manager to query.\n * @param[in,out] runStart\n *      Pointer to the starting code unit index. On return, updated to the index immediately\n *      following the end of the found run.\n * @param rangeEnd\n *      The exclusive upper bound for the search. The run does not include this index.\n * @param filterScope\n *      The attribute scope to filter by (e.g., character or paragraph). Only attributes matching\n *      this scope are included in runs.\n * @param filterGroup\n *      The attribute group to filter by, or SBAttributeGroupNone to match all groups within the\n *      specified scope.\n * @param[out] output\n *      Dictionary to populate with all matching attribute items from the run; will be empty if the\n *      run represents absence of matching attributes. Always cleared at the start.\n * @return\n *      SBTrue if runStart < rangeEnd (a run was processed), SBFalse if runStart >= rangeEnd on\n *      entry (no more runs available).\n */\nSB_INTERNAL SBBoolean AttributeManagerGetOnwardRunByFilteringCollection(AttributeManagerRef manager,\n    SBUInteger *runStart, SBUInteger rangeEnd,\n    SBAttributeScope filterScope, SBAttributeGroup filterGroup, AttributeDictionaryRef output);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/BidiChain.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBBase.h>\n\n#include \"BidiChain.h\"\n\nSB_INTERNAL void BidiChainInitialize(BidiChainRef chain,\n    SBBidiType *types, SBLevel *levels, BidiFlag *flags, BidiLink *links)\n{\n    chain->types = types;\n    chain->levels = levels;\n    chain->flags = flags;\n    chain->links = links;\n    chain->roller = 0;\n    chain->last = 0;\n\n    /* Make first link empty. */\n    chain->types[0] = SBBidiTypeNil;\n    chain->levels[0] = SBLevelInvalid;\n    chain->flags[0] = BidiFlagNone;\n    chain->links[0] = BidiLinkNone;\n}\n\nSB_INTERNAL void BidiChainAdd(BidiChainRef chain, SBBidiType type, SBUInteger lastLinkLength)\n{\n    BidiLink last = chain->last;\n    BidiLink current = last + (SBUInt32)lastLinkLength;\n\n    chain->types[current] = type;\n    chain->flags[current] = BidiFlagNone;\n    chain->links[current] = chain->roller;\n\n    if (lastLinkLength == 1) {\n        chain->flags[last] |= BidiFlagSingle;\n    }\n\n    chain->links[last] = current;\n    chain->last = current;\n}\n\nSB_INTERNAL SBBoolean BidiChainIsSingle(BidiChainRef chain, BidiLink link)\n{\n    return chain->flags[link] & BidiFlagSingle;\n}\n\nSB_INTERNAL SBBidiType BidiChainGetType(BidiChainRef chain, BidiLink link)\n{\n    return chain->types[link];\n}\n\nSB_INTERNAL void BidiChainSetType(BidiChainRef chain, BidiLink link, SBBidiType type)\n{\n    chain->types[link] = type;\n}\n\nSB_INTERNAL SBLevel BidiChainGetLevel(BidiChainRef chain, BidiLink link)\n{\n    return chain->levels[link];\n}\n\nSB_INTERNAL void BidiChainSetLevel(BidiChainRef chain, BidiLink link, SBLevel level)\n{\n    chain->levels[link] = level;\n}\n\nSB_INTERNAL BidiLink BidiChainGetNext(BidiChainRef chain, BidiLink link)\n{\n    return chain->links[link];\n}\n\nSB_INTERNAL void BidiChainSetNext(BidiChainRef chain, BidiLink link, BidiLink next)\n{\n    chain->links[link] = next;\n}\n\nSB_INTERNAL void BidiChainAbandonNext(BidiChainRef chain, BidiLink link)\n{\n    BidiLink next = chain->links[link];\n    BidiLink limit = chain->links[next];\n\n    chain->links[link] = limit;\n}\n\nSB_INTERNAL void BidiChainAbsorbNext(BidiChainRef chain, BidiLink link)\n{\n    BidiLink next = chain->links[link];\n\n    chain->links[link] = chain->links[next];\n    chain->flags[link] &= ~BidiFlagSingle;\n}\n\nSB_INTERNAL SBBoolean BidiChainMergeNext(BidiChainRef chain, BidiLink link)\n{\n    BidiLink next = chain->links[link];\n\n    if (chain->types[link] == chain->types[next]\n        && chain->levels[link] == chain->levels[next]) {\n        BidiChainAbsorbNext(chain, link);\n        return SBTrue;\n    }\n\n    return SBFalse;\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/BidiChain.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_BIDI_CHAIN_H\n#define _SB_INTERNAL_BIDI_CHAIN_H\n\n#include <API/SBBase.h>\n\ntypedef SBUInt32 BidiLink;\n\n#define BidiLinkNone    (SBUInt32)(-1)\n\nenum {\n    BidiFlagNone   = 0x00,\n    BidiFlagSingle = 0x01\n};\ntypedef SBUInt8 BidiFlag;\n\ntypedef struct _BidiChain {\n    SBBidiType *types;\n    SBLevel *levels;\n    BidiFlag *flags;\n    BidiLink *links;\n    BidiLink roller;\n    BidiLink last;\n} BidiChain, *BidiChainRef;\n\nSB_INTERNAL void BidiChainInitialize(BidiChainRef chain,\n    SBBidiType *types, SBLevel *levels, BidiFlag *flags, BidiLink *links);\nSB_INTERNAL void BidiChainAdd(BidiChainRef chain, SBBidiType type, SBUInteger lastLinkLength);\n\n#define BidiChainGetOffset(chain, link)         \\\n(                                               \\\n    (link) - 1                                  \\\n)\n\nSB_INTERNAL SBBoolean BidiChainIsSingle(BidiChainRef chain, BidiLink link);\n\nSB_INTERNAL SBBidiType BidiChainGetType(BidiChainRef chain, BidiLink link);\nSB_INTERNAL void BidiChainSetType(BidiChainRef chain, BidiLink link, SBBidiType type);\n\nSB_INTERNAL SBLevel BidiChainGetLevel(BidiChainRef chain, BidiLink link);\nSB_INTERNAL void BidiChainSetLevel(BidiChainRef chain, BidiLink link, SBLevel level);\n\nSB_INTERNAL BidiLink BidiChainGetNext(BidiChainRef chain, BidiLink link);\nSB_INTERNAL void BidiChainSetNext(BidiChainRef chain, BidiLink link, BidiLink next);\nSB_INTERNAL void BidiChainAbandonNext(BidiChainRef chain, BidiLink link);\nSB_INTERNAL void BidiChainAbsorbNext(BidiChainRef chain, BidiLink link);\nSB_INTERNAL SBBoolean BidiChainMergeNext(BidiChainRef chain, BidiLink link);\n\n#define BidiChainForEach(chain, roller, link) \\\n    for (link = chain->links[roller]; link != roller; link = chain->links[link])\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/BracketQueue.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <Core/Memory.h>\n#include <UBA/BidiChain.h>\n\n#include \"BracketQueue.h\"\n\n#define MakeBracketQueuePosition()                  \\\n    { NULL, SBInvalidIndex }\n#define SetBracketQueuePosition(bqp, _list, _index) \\\n    ((bqp).list = (_list), (bqp).index = (_index))\n#define IsInvalidBracketQueuePosition(bqp)          \\\n    ((bqp).list == NULL)\n\nstatic const BracketQueuePosition InvalidBracketQueuePosition = MakeBracketQueuePosition();\n\n#define QUEUE_LIST      0\n#define ELEMENTS        1\n#define COUNT           2\n\nstatic BracketQueueElement *InsertBracketQueueElement(BracketQueueRef queue)\n{\n    BracketQueueListRef rearList = queue->_rearList;\n    BracketQueueElement *element = NULL;\n\n    if ((queue->_rearTop + 1) < rearList->capacity) {\n        queue->_rearTop += 1;\n        queue->_actualCount += 1;\n\n        element = &rearList->elements[queue->_rearTop];\n    } else {\n        BracketQueueListRef previousList = rearList;\n\n        rearList = previousList->next;\n\n        if (!rearList) {\n            const SBUInteger capacity = queue->_actualCount;\n            void *pointers[COUNT] = { NULL };\n            SBUInteger sizes[COUNT];\n\n            sizes[QUEUE_LIST] = sizeof(BracketQueueList);\n            sizes[ELEMENTS]   = sizeof(BracketQueueElement) * capacity;\n\n            if (MemoryAllocateChunks(queue->_memory, MemoryTypeScratch, sizes, COUNT, pointers)) {\n                rearList = pointers[QUEUE_LIST];\n                rearList->elements = pointers[ELEMENTS];\n                rearList->capacity = capacity;\n                rearList->previous = previousList;\n                rearList->next = NULL;\n\n                previousList->next = rearList;\n            }\n        }\n\n        if (rearList) {\n            queue->_rearList = rearList;\n            queue->_rearTop = 0;\n            queue->_actualCount += 1;\n\n            element = &rearList->elements[0];\n        }\n    }\n\n    return element;\n}\n\nstatic void InvalidateOpenPairs(BracketQueueRef queue, BracketQueuePosition from)\n{\n    BracketQueueListRef rearList = queue->_rearList;\n    BracketQueueListRef breakList = rearList->next;\n    SBUInteger invalidCount = 0;\n    BracketQueuePosition current;\n\n    current = from;\n\n    do {\n        SBUInteger end = (current.list == rearList ? queue->_rearTop + 1 : current.list->capacity);\n\n        while (current.index < end) {\n            BracketQueueElement *element = &current.list->elements[current.index];\n\n            if (element->openingLink != BidiLinkNone && element->closingLink == BidiLinkNone) {\n                element->openingLink = BidiLinkNone;\n                invalidCount += 1;\n            }\n\n            current.index += 1;\n        }\n\n        current.list = current.list->next;\n        current.index = 0;\n    } while (current.list != breakList);\n\n    queue->_actualCount -= invalidCount;\n}\n\nstatic void SkipToNextBracketPair(BracketQueueRef queue)\n{\n    BracketQueueListRef rearList = queue->_rearList;\n    BracketQueueListRef breakList = rearList->next;\n    SBBoolean hasProcessedFirst = SBFalse;\n    BracketQueuePosition current;\n\n    current = queue->_front;\n\n    do {\n        SBUInteger end = (current.list == rearList ? queue->_rearTop + 1 : current.list->capacity);\n\n        while (current.index < end) {\n            BracketQueueElement *element = &current.list->elements[current.index];\n\n            if (element->openingLink != BidiLinkNone && element->closingLink != BidiLinkNone) {\n                if (hasProcessedFirst) {\n                    queue->_front = current;\n                    return;\n                }\n\n                queue->pairCount -= 1;\n            }\n\n            hasProcessedFirst = SBTrue;\n            current.index += 1;\n        }\n\n        current.list = current.list->next;\n        current.index = 0;\n    } while (current.list != breakList);\n\n    /* No more pairs. */\n    queue->_front = InvalidBracketQueuePosition;\n}\n\n#undef QUEUE_LIST\n#undef ELEMENTS\n#undef COUNT\n\nSB_INTERNAL void BracketQueueInitialize(BracketQueueRef queue, MemoryRef memory)\n{\n    queue->_memory = memory;\n\n    queue->_firstList.elements = queue->_elements;\n    queue->_firstList.capacity = BracketQueueEmbeddedElementCount;\n    queue->_firstList.previous = NULL;\n    queue->_firstList.next = NULL;\n\n    BracketQueueReset(queue, SBBidiTypeNil);\n}\n\nSB_INTERNAL void BracketQueueReset(BracketQueueRef queue, SBBidiType direction)\n{\n    queue->_rearList = &queue->_firstList;\n    queue->_rearTop = SBInvalidIndex;\n    queue->_firstOpenPair = InvalidBracketQueuePosition;\n    queue->_front = InvalidBracketQueuePosition;\n    queue->_actualCount = 0;\n    queue->pairCount = 0;\n    queue->_direction = direction;\n    queue->_isPopulated = SBFalse;\n}\n\nSB_INTERNAL void BracketQueueMarkPopulated(BracketQueueRef queue)\n{\n    SBAssert(!queue->_isPopulated);\n\n    if (queue->pairCount > 0) {\n        BracketQueueElement *first = &queue->_firstList.elements[0];\n\n        SetBracketQueuePosition(queue->_front, &queue->_firstList, 0);\n\n        if (first->openingLink == BidiLinkNone\n                || first->closingLink == BidiLinkNone) {\n            SkipToNextBracketPair(queue);\n        }\n    }\n\n    queue->_actualCount = 0;\n    queue->_isPopulated = SBTrue;\n}\n\nSB_INTERNAL SBBoolean BracketQueueEnqueue(BracketQueueRef queue,\n    BidiLink priorStrongLink, BidiLink openingLink, SBCodepoint bracket)\n{\n    SBBoolean isEnqueued = SBFalse;\n    BracketQueueElement *element;\n\n    /* The queue must NOT be populated yet. */\n    SBAssert(!queue->_isPopulated);\n    /* The queue can ONLY have a maximum of 63 open pairs. */\n    SBAssert(BracketQueueGetOpenPairCount(queue) < BracketQueueMaxOpenPairs);\n\n    element = InsertBracketQueueElement(queue);\n\n    if (element) {\n        element->priorStrongLink = priorStrongLink;\n        element->openingLink = openingLink;\n        element->closingLink = BidiLinkNone;\n        element->bracket = bracket;\n        element->innerStrongType = SBBidiTypeNil;\n\n        if (IsInvalidBracketQueuePosition(queue->_firstOpenPair)) {\n            SetBracketQueuePosition(queue->_firstOpenPair, queue->_rearList, queue->_rearTop);\n        }\n\n        isEnqueued = SBTrue;\n    }\n\n    return isEnqueued;\n}\n\nSB_INTERNAL void BracketQueueDequeue(BracketQueueRef queue)\n{\n    /* The queue MUST be populated and NOT empty. */\n    SBAssert(queue->_isPopulated && queue->pairCount > 0);\n\n    SkipToNextBracketPair(queue);\n}\n\nSB_INTERNAL SBUInteger BracketQueueGetOpenPairCount(BracketQueueRef queue)\n{\n    return (queue->_actualCount - queue->pairCount);\n}\n\nSB_INTERNAL void BracketQueueAssignInnerStrongType(BracketQueueRef queue, SBBidiType strongType)\n{\n    BracketQueuePosition first = queue->_firstOpenPair;\n\n    /* The queue must NOT be populated yet. */\n    SBAssert(!queue->_isPopulated);\n    /* Passed-in bidi type MUST be valid. */\n    SBAssert(strongType == SBBidiTypeL || strongType == SBBidiTypeR);\n\n    /* Proceed if at least one open pair exists. */\n    if (!IsInvalidBracketQueuePosition(first)) {\n        BracketQueueListRef rearList = queue->_rearList;\n        BracketQueueListRef breakList = first.list->previous;\n        BracketQueuePosition current;\n\n        SetBracketQueuePosition(current, queue->_rearList, queue->_rearTop + 1);\n\n        /* Assign the strong type to all open pairs. */\n        do {\n            SBUInteger start = (current.list == first.list ? first.index : 0);\n\n            if (current.list != rearList) {\n                current.index = current.list->capacity;\n            }\n\n            while (current.index-- > start) {\n                BracketQueueElement *element = &current.list->elements[current.index];\n\n                if (element->closingLink == BidiLinkNone\n                        && element->innerStrongType != queue->_direction) {\n                    element->innerStrongType = strongType;\n                }\n            }\n\n            current.list = current.list->previous;\n        } while (current.list != breakList);\n    }\n}\n\nSB_INTERNAL void BracketQueueClosePair(BracketQueueRef queue,\n    BidiLink closingLink, SBCodepoint bracket)\n{\n    BracketQueuePosition first = queue->_firstOpenPair;\n\n    /* The queue must NOT be populated yet. */\n    SBAssert(!queue->_isPopulated);\n\n    /* Proceed if at least one open pair exists. */\n    if (!IsInvalidBracketQueuePosition(first)) {\n        BracketQueueListRef rearList = queue->_rearList;\n        BracketQueueListRef breakList = first.list->previous;\n        BracketQueuePosition current;\n\n        SetBracketQueuePosition(current, rearList, queue->_rearTop + 1);\n\n        /* Find out the matching open pair. */\n        do {\n            SBUInteger start = (current.list == first.list ? first.index : 0);\n\n            if (current.list != rearList) {\n                current.index = current.list->capacity;\n            }\n\n            while (current.index-- > start) {\n                BracketQueueElement *element = &current.list->elements[current.index];\n\n                if (element->openingLink != BidiLinkNone && element->closingLink == BidiLinkNone\n                        && SBCodepointIsCanonicalEquivalentBracket(element->bracket, bracket)) {\n                    element->closingLink = closingLink;\n                    queue->pairCount += 1;\n                    InvalidateOpenPairs(queue, current);\n\n                    if (queue->_firstOpenPair.list == current.list\n                            && queue->_firstOpenPair.index == current.index) {\n                        /* No open pair exists at this point. */\n                        queue->_firstOpenPair = InvalidBracketQueuePosition;\n                    }\n                    return;\n                }\n            }\n\n            current.list = current.list->previous;\n        } while (current.list != breakList);\n    }\n}\n\nSB_INTERNAL BidiLink BracketQueueGetPriorStrongLink(BracketQueueRef queue)\n{\n    return queue->_front.list->elements[queue->_front.index].priorStrongLink;\n}\n\nSB_INTERNAL BidiLink BracketQueueGetOpeningLink(BracketQueueRef queue)\n{\n    return queue->_front.list->elements[queue->_front.index].openingLink;\n}\n\nSB_INTERNAL BidiLink BracketQueueGetClosingLink(BracketQueueRef queue)\n{\n    return queue->_front.list->elements[queue->_front.index].closingLink;\n}\n\nSB_INTERNAL SBBidiType BracketQueueGetInnerStrongType(BracketQueueRef queue)\n{\n    return queue->_front.list->elements[queue->_front.index].innerStrongType;\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/BracketQueue.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_BRACKET_QUEUE_H\n#define _SB_INTERNAL_BRACKET_QUEUE_H\n\n#include <SheenBidi/SBCodepoint.h>\n\n#include <API/SBBase.h>\n#include <Core/Memory.h>\n#include <UBA/BidiChain.h>\n\n#define BracketQueueEmbeddedElementCount    8\n#define BracketQueueMaxOpenPairs            63\n\ntypedef struct _BracketQueueElement {\n    SBCodepoint bracket;\n    BidiLink priorStrongLink;\n    BidiLink openingLink;\n    BidiLink closingLink;\n    SBBidiType innerStrongType;\n} BracketQueueElement;\n\ntypedef struct _BracketQueueList {\n    BracketQueueElement *elements;\n    SBUInteger capacity;\n\n    struct _BracketQueueList *previous;\n    struct _BracketQueueList *next;\n} BracketQueueList, *BracketQueueListRef;\n\ntypedef struct _BracketQueuePosition {\n    BracketQueueListRef list;\n    SBUInteger index;\n} BracketQueuePosition;\n\ntypedef struct _BracketQueue {\n    MemoryRef _memory;\n    BracketQueueElement _elements[BracketQueueEmbeddedElementCount];\n    BracketQueueList _firstList;\n    BracketQueueListRef _rearList;\n    SBUInteger _rearTop;\n    BracketQueuePosition _firstOpenPair;\n    BracketQueuePosition _front;\n    SBUInteger _actualCount;\n    SBUInteger pairCount;\n    SBBidiType _direction;\n    SBBoolean _isPopulated;\n} BracketQueue, *BracketQueueRef;\n\nSB_INTERNAL void BracketQueueInitialize(BracketQueueRef queue, MemoryRef memory);\nSB_INTERNAL void BracketQueueReset(BracketQueueRef queue, SBBidiType direction);\nSB_INTERNAL void BracketQueueMarkPopulated(BracketQueueRef queue);\n\nSB_INTERNAL SBBoolean BracketQueueEnqueue(BracketQueueRef queue,\n    BidiLink priorStrongLink, BidiLink openingLink, SBCodepoint bracket);\nSB_INTERNAL void BracketQueueDequeue(BracketQueueRef queue);\n\nSB_INTERNAL SBUInteger BracketQueueGetOpenPairCount(BracketQueueRef queue);\nSB_INTERNAL void BracketQueueAssignInnerStrongType(BracketQueueRef queue, SBBidiType strongType);\nSB_INTERNAL void BracketQueueClosePair(BracketQueueRef queue,\n    BidiLink closingLink, SBCodepoint bracket);\n\nSB_INTERNAL BidiLink BracketQueueGetPriorStrongLink(BracketQueueRef queue);\nSB_INTERNAL BidiLink BracketQueueGetOpeningLink(BracketQueueRef queue);\nSB_INTERNAL BidiLink BracketQueueGetClosingLink(BracketQueueRef queue);\nSB_INTERNAL SBBidiType BracketQueueGetInnerStrongType(BracketQueueRef queue);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/BracketType.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_BRACKET_TYPE_H\n#define _SB_INTERNAL_BRACKET_TYPE_H\n\n#include <API/SBBase.h>\n\nenum {\n    BracketTypeNone  = 0x00,\n    BracketTypeOpen  = 0x40,    /**< Opening paired bracket. */\n    BracketTypeClose = 0x80,    /**< Closing paired bracket. */\n\n    BracketTypePrimaryMask = BracketTypeOpen | BracketTypeClose,\n    BracketTypeInverseMask = ~BracketTypePrimaryMask\n};\ntypedef SBUInt8 BracketType;\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/IsolatingRun.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <API/SBCodepoint.h>\n#include <API/SBLog.h>\n#include <Data/PairingLookup.h>\n#include <UBA/BidiChain.h>\n#include <UBA/BracketQueue.h>\n#include <UBA/BracketType.h>\n#include <UBA/LevelRun.h>\n\n#include \"IsolatingRun.h\"\n\nstatic void ResolveAvailableBracketPairs(IsolatingRunRef isolatingRun);\n\nstatic void AttachLevelRunLinks(IsolatingRunRef isolatingRun)\n{\n    BidiChainRef chain = isolatingRun->bidiChain;\n    const LevelRun *baseLevelRun = isolatingRun->baseLevelRun;\n    const LevelRun *current;\n    const LevelRun *next;\n\n    isolatingRun->_originalLink = BidiChainGetNext(chain, chain->roller);\n    BidiChainSetNext(chain, chain->roller, baseLevelRun->firstLink);\n\n    /* Iterate over level runs and attach their links to form an isolating run. */\n    for (current = baseLevelRun; (next = current->next); current = next) {\n        BidiChainSetNext(chain, current->lastLink, next->firstLink);\n    }\n    BidiChainSetNext(chain, current->lastLink, chain->roller);\n\n    isolatingRun->_lastLevelRun = current;\n    isolatingRun->_sos = RunExtrema_SOR(baseLevelRun->extrema);\n\n    if (!RunKindIsPartialIsolate(baseLevelRun->kind)) {\n        isolatingRun->_eos = RunExtrema_EOR(current->extrema);\n    } else {\n        SBLevel paragraphLevel = isolatingRun->paragraphLevel;\n        SBLevel runLevel = baseLevelRun->level;\n        SBLevel eosLevel = (runLevel > paragraphLevel ? runLevel : paragraphLevel);\n        isolatingRun->_eos = ((eosLevel & 1) ? SBBidiTypeR : SBBidiTypeL);\n    }\n}\n\nstatic void AttachOriginalLinks(IsolatingRunRef isolatingRun)\n{\n    BidiChainRef chain = isolatingRun->bidiChain;\n    const LevelRun *current;\n\n    BidiChainSetNext(chain, chain->roller, isolatingRun->_originalLink);\n\n    /* Iterate over level runs and attach original subsequent links. */\n    for (current = isolatingRun->baseLevelRun; current; current = current->next) {\n        BidiChainSetNext(chain, current->lastLink, current->subsequentLink);\n    }\n}\n\nstatic BidiLink ResolveWeakTypes(IsolatingRunRef isolatingRun)\n{\n    BidiChainRef chain = isolatingRun->bidiChain;\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    BidiLink priorLink;\n    SBBidiType sos;\n\n    SBBidiType w1PriorType;\n    SBBidiType w2StrongType;\n    SBBidiType w4PriorType;\n    SBBidiType w5PriorType;\n    SBBidiType w7StrongType;\n\n    priorLink = roller;\n    sos = isolatingRun->_sos;\n\n    w1PriorType = sos;\n    w2StrongType = sos;\n\n    BidiChainForEach(chain, roller, link) {\n        SBBidiType type = BidiChainGetType(chain, link);\n        SBBoolean forceMerge = SBFalse;\n\n        /* Rule W1 */\n        if (type == SBBidiTypeNSM) {\n            /* Change the 'type' variable as well because it can be EN on which W2 depends. */\n            type = (SBBidiTypeIsIsolate(w1PriorType) ? SBBidiTypeON : w1PriorType);\n            BidiChainSetType(chain, link, type);\n\n            /* Fix for 3rd point of rule N0. */\n            if (w1PriorType == SBBidiTypeON) {\n                forceMerge = SBTrue;\n            }\n        }\n        w1PriorType = type;\n\n        /* Rule W2 */\n        if (type == SBBidiTypeEN) {\n            if (w2StrongType == SBBidiTypeAL) {\n                BidiChainSetType(chain, link, SBBidiTypeAN);\n            }\n        }\n        /*\n         * Rule W3\n         * NOTE: It is safe to apply W3 in 'else-if' statement because it only depends on type AL.\n         *       Even if W2 changes EN to AN, there won't be any harm.\n         */\n        else if (type == SBBidiTypeAL) {\n            BidiChainSetType(chain, link, SBBidiTypeR);\n        }\n\n        if (SBBidiTypeIsStrong(type)) {\n            /* Save the strong type as it is checked in W2. */\n            w2StrongType = type;\n        }\n\n        if ((type != SBBidiTypeON && BidiChainGetType(chain, priorLink) == type) || forceMerge) {\n            BidiChainAbsorbNext(chain, priorLink);\n        } else {\n            priorLink = link;\n        }\n    }\n\n    priorLink = roller;\n    w4PriorType = sos;\n    w5PriorType = sos;\n    w7StrongType = sos;\n\n    BidiChainForEach(chain, roller, link) {\n        SBBidiType type = BidiChainGetType(chain, link);\n        SBBidiType nextType = BidiChainGetType(chain, BidiChainGetNext(chain, link));\n\n        /* Rule W4 */\n        if (BidiChainIsSingle(chain, link)\n            && SBBidiTypeIsNumberSeparator(type)\n            && SBBidiTypeIsNumber(w4PriorType)\n            && (w4PriorType == nextType)\n            && (w4PriorType == SBBidiTypeEN || type == SBBidiTypeCS))\n        {\n            /* Change the current type as well because it can be EN on which W5 depends. */\n            type = w4PriorType;\n            BidiChainSetType(chain, link, type);\n        }\n        w4PriorType = type;\n\n        /* Rule W5 */\n        if (type == SBBidiTypeET && (w5PriorType == SBBidiTypeEN || nextType == SBBidiTypeEN)) {\n            /* Change the current type as well because it is EN on which W7 depends. */\n            type = SBBidiTypeEN;\n            BidiChainSetType(chain, link, type);\n        }\n        w5PriorType = type;\n\n        switch (type) {\n        /* Rule W6 */\n        case SBBidiTypeET:\n        case SBBidiTypeCS:\n        case SBBidiTypeES:\n            BidiChainSetType(chain, link, SBBidiTypeON);\n            break;\n\n        /*\n         * Rule W7\n         * NOTE: W7 is expected to be applied after W6. However this is not the case here. The\n         *       reason is that W6 can only create the type ON which is not tested in W7 by any\n         *       means. So it won't affect the algorithm.\n         */\n        case SBBidiTypeEN:\n            if (w7StrongType == SBBidiTypeL) {\n                BidiChainSetType(chain, link, SBBidiTypeL);\n            }\n            break;\n\n        /*\n         * Save the strong type for W7.\n         * NOTE: The strong type is expected to be saved after applying W7 because W7 itself creates\n         *       a strong type. However the strong type being saved here is based on the type after\n         *       W5. This won't effect the algorithm because a single link contains all consecutive\n         *       EN types. This means that even if W7 creates a strong type, it will be saved in\n         *       next iteration.\n         */\n        case SBBidiTypeL:\n        case SBBidiTypeR:\n            w7StrongType = type;\n            break;\n        }\n\n        if (type != SBBidiTypeON && BidiChainGetType(chain, priorLink) == type) {\n            BidiChainAbsorbNext(chain, priorLink);\n        } else {\n            priorLink = link;\n        }\n    }\n\n    return priorLink;\n}\n\nstatic SBBoolean ResolveBrackets(IsolatingRunRef isolatingRun)\n{\n    const SBCodepointSequence *sequence = isolatingRun->codepointSequence;\n    SBUInteger paragraphOffset = isolatingRun->paragraphOffset;\n    BracketQueueRef queue = &isolatingRun->_bracketQueue;\n    BidiChainRef chain = isolatingRun->bidiChain;\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    BidiLink priorStrongLink;\n    SBLevel runLevel;\n\n    priorStrongLink = BidiLinkNone;\n    runLevel = isolatingRun->baseLevelRun->level;\n\n    BracketQueueReset(queue, SBLevelAsNormalBidiType(runLevel));\n\n    BidiChainForEach(chain, roller, link) {\n        SBUInteger stringIndex;\n        SBCodepoint codepoint;\n        SBBidiType type;\n\n        SBCodepoint bracketValue;\n        BracketType bracketType;\n\n        type = BidiChainGetType(chain, link);\n\n        switch (type) {\n        case SBBidiTypeON:\n            stringIndex = BidiChainGetOffset(chain, link) + paragraphOffset;\n            codepoint = SBCodepointSequenceGetCodepointAt(sequence, &stringIndex);\n            bracketValue = LookupBracketPair(codepoint, &bracketType);\n\n            switch (bracketType) {\n            case BracketTypeOpen:\n                if (BracketQueueGetOpenPairCount(queue) >= BracketQueueMaxOpenPairs) {\n                    /* Stop further processing. */\n                    return SBTrue;\n                }\n                if (!BracketQueueEnqueue(queue, priorStrongLink, link, bracketValue)) {\n                    return SBFalse;\n                }\n                break;\n\n            case BracketTypeClose:\n                BracketQueueClosePair(queue, link, codepoint);\n                break;\n            }\n            break;\n\n        case SBBidiTypeEN:\n        case SBBidiTypeAN:\n            type = SBBidiTypeR;\n\n        case SBBidiTypeR:\n        case SBBidiTypeL:\n            BracketQueueAssignInnerStrongType(queue, type);\n            priorStrongLink = link;\n            break;\n        }\n    }\n\n    BracketQueueMarkPopulated(queue);\n    ResolveAvailableBracketPairs(isolatingRun);\n\n    return SBTrue;\n}\n\nstatic void ResolveAvailableBracketPairs(IsolatingRunRef isolatingRun)\n{\n    BracketQueueRef queue = &isolatingRun->_bracketQueue;\n    BidiChainRef chain = isolatingRun->bidiChain;\n\n    SBLevel runLevel;\n    SBBidiType embeddingDirection;\n    SBBidiType oppositeDirection;\n\n    runLevel = isolatingRun->baseLevelRun->level;\n    embeddingDirection = SBLevelAsNormalBidiType(runLevel);\n    oppositeDirection = SBLevelAsOppositeBidiType(runLevel);\n\n    while (queue->pairCount > 0) {\n        BidiLink openingLink = BracketQueueGetOpeningLink(queue);\n        BidiLink closingLink = BracketQueueGetClosingLink(queue);\n        SBBidiType innerStrongType = BracketQueueGetInnerStrongType(queue);\n        SBBidiType pairType;\n\n        /* Rule: N0.b */\n        if (innerStrongType == embeddingDirection) {\n            pairType = innerStrongType;\n        }\n        /* Rule: N0.c */\n        else if (innerStrongType == oppositeDirection) {\n            BidiLink priorStrongLink;\n            SBBidiType priorStrongType;\n\n            priorStrongLink = BracketQueueGetPriorStrongLink(queue);\n\n            if (priorStrongLink != BidiLinkNone) {\n                BidiLink link;\n\n                priorStrongType = BidiChainGetType(chain, priorStrongLink);\n                if (SBBidiTypeIsNumber(priorStrongType)) {\n                    priorStrongType = SBBidiTypeR;\n                }\n\n                link = BidiChainGetNext(chain, priorStrongLink);\n\n                /*\n                 * Iterate over in-between links to find the proper prior strong type because there\n                 * might be resolved brackets with different strong types.\n                 */\n                while (link != openingLink) {\n                    SBBidiType type = BidiChainGetType(chain, link);\n                    if (type == SBBidiTypeL || type == SBBidiTypeR) {\n                        priorStrongType = type;\n                    }\n\n                    link = BidiChainGetNext(chain, link);\n                }\n            } else {\n                priorStrongType = isolatingRun->_sos;\n            }\n\n            /* Rule: N0.c.1 */\n            if (priorStrongType == oppositeDirection) {\n                pairType = oppositeDirection;\n            }\n            /* Rule: N0.c.2 */\n            else {\n                pairType = embeddingDirection;\n            }\n        }\n        /* Rule: N0.d */\n        else {\n            pairType = SBBidiTypeNil;\n        }\n\n        if (pairType != SBBidiTypeNil) {\n            /* Do the substitution */\n            BidiChainSetType(chain, openingLink, pairType);\n            BidiChainSetType(chain, closingLink, pairType);\n        }\n\n        BracketQueueDequeue(queue);\n    }\n}\n\nstatic void ResolveNeutrals(IsolatingRunRef isolatingRun)\n{\n    BidiChainRef chain = isolatingRun->bidiChain;\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    SBLevel runLevel;\n    SBBidiType strongType;\n    BidiLink neutralLink;\n\n    runLevel = isolatingRun->baseLevelRun->level;\n    strongType = isolatingRun->_sos;\n    neutralLink = BidiLinkNone;\n\n    BidiChainForEach(chain, roller, link) {\n        SBBidiType type = BidiChainGetType(chain, link);\n        SBBidiType nextType;\n\n        SBAssert(SBBidiTypeIsStrongOrNumber(type) || SBBidiTypeIsNeutralOrIsolate(type));\n\n        switch (type) {\n        case SBBidiTypeL:\n            strongType = SBBidiTypeL;\n            break;\n\n        case SBBidiTypeR:\n        case SBBidiTypeEN:\n        case SBBidiTypeAN:\n            strongType = SBBidiTypeR;\n            break;\n\n        case SBBidiTypeB:                           \n        case SBBidiTypeS:\n        case SBBidiTypeWS:\n        case SBBidiTypeON:\n        case SBBidiTypeLRI:\n        case SBBidiTypeRLI:                         \n        case SBBidiTypeFSI:\n        case SBBidiTypePDI:\n            if (neutralLink == BidiLinkNone) {\n                neutralLink = link;\n            }\n\n            nextType = BidiChainGetType(chain, BidiChainGetNext(chain, link));\n            if (SBBidiTypeIsNumber(nextType)) {\n                nextType = SBBidiTypeR;\n            } else if (nextType == SBBidiTypeNil) {\n                nextType = isolatingRun->_eos;\n            }\n\n            if (SBBidiTypeIsStrong(nextType)) {\n                /* Rules N1, N2 */\n                SBBidiType resolvedType = (strongType == nextType\n                                           ? strongType\n                                           : SBLevelAsNormalBidiType(runLevel));\n\n                do {\n                    BidiChainSetType(chain, neutralLink, resolvedType);\n                    neutralLink = BidiChainGetNext(chain, neutralLink);\n                } while (neutralLink != BidiChainGetNext(chain, link));\n\n                neutralLink = BidiLinkNone;\n            }\n            break;\n        }\n    }\n}\n\nstatic void ResolveImplicitLevels(IsolatingRunRef isolatingRun)\n{\n    BidiChainRef chain = isolatingRun->bidiChain;\n    BidiLink roller = chain->roller;\n    BidiLink link;\n\n    SBLevel runLevel = isolatingRun->baseLevelRun->level;\n    \n    if ((runLevel & 1) == 0) {\n        BidiChainForEach(chain, roller, link) {\n            SBBidiType type = BidiChainGetType(chain, link);\n            SBLevel level = BidiChainGetLevel(chain, link);\n            \n            SBAssert(SBBidiTypeIsStrongOrNumber(type));\n            \n            /* Rule I1 */\n            if (type == SBBidiTypeR) {\n                BidiChainSetLevel(chain, link, level + 1);\n            } else if (type != SBBidiTypeL) {\n                BidiChainSetLevel(chain, link, level + 2);\n            }\n        }\n    } else {\n        BidiChainForEach(chain, roller, link) {\n            SBBidiType type = BidiChainGetType(chain, link);\n            SBLevel level = BidiChainGetLevel(chain, link);\n            \n            SBAssert(SBBidiTypeIsStrongOrNumber(type));\n            \n            /* Rule I2 */\n            if (type != SBBidiTypeR) {\n                BidiChainSetLevel(chain, link, level + 1);\n            }\n        }\n    }\n}\n\nSB_INTERNAL void IsolatingRunInitialize(IsolatingRunRef isolatingRun, MemoryRef memory)\n{\n    BracketQueueInitialize(&isolatingRun->_bracketQueue, memory);\n}\n\nSB_INTERNAL SBBoolean IsolatingRunResolve(IsolatingRunRef isolatingRun)\n{\n    BidiLink lastLink;\n    BidiLink subsequentLink;\n\n    SB_LOG_BLOCK_OPENER(\"Identified Isolating Run\");\n\n    /* Attach level run links to form isolating run. */\n    AttachLevelRunLinks(isolatingRun);\n    /* Save last subsequent link. */\n    subsequentLink = isolatingRun->_lastLevelRun->subsequentLink;\n\n    SB_LOG_STATEMENT(\"Range\", 1, SB_LOG_RUN_RANGE(isolatingRun));\n    SB_LOG_STATEMENT(\"Types\", 1, SB_LOG_RUN_TYPES(isolatingRun));\n    SB_LOG_STATEMENT(\"Level\", 1, SB_LOG_LEVEL(isolatingRun->baseLevelRun->level));\n    SB_LOG_STATEMENT(\"SOS\", 1, SB_LOG_BIDI_TYPE(isolatingRun->_sos));\n    SB_LOG_STATEMENT(\"EOS\", 1, SB_LOG_BIDI_TYPE(isolatingRun->_eos));\n\n    /* Rules W1-W7 */\n    lastLink = ResolveWeakTypes(isolatingRun);\n    SB_LOG_BLOCK_OPENER(\"Resolved Weak Types\");\n    SB_LOG_STATEMENT(\"Types\", 1, SB_LOG_RUN_TYPES(isolatingRun));\n    SB_LOG_BLOCK_CLOSER();\n\n    /* Rule N0 */\n    if (!ResolveBrackets(isolatingRun)) {\n        return SBFalse;\n    }\n\n    SB_LOG_BLOCK_OPENER(\"Resolved Brackets\");\n    SB_LOG_STATEMENT(\"Types\", 1, SB_LOG_RUN_TYPES(isolatingRun));\n    SB_LOG_BLOCK_CLOSER();\n\n    /* Rules N1, N2 */\n    ResolveNeutrals(isolatingRun);\n    SB_LOG_BLOCK_OPENER(\"Resolved Neutrals\");\n    SB_LOG_STATEMENT(\"Types\", 1, SB_LOG_RUN_TYPES(isolatingRun));\n    SB_LOG_BLOCK_CLOSER();\n\n    /* Rules I1, I2 */\n    ResolveImplicitLevels(isolatingRun);\n    SB_LOG_BLOCK_OPENER(\"Resolved Implicit Levels\");\n    SB_LOG_STATEMENT(\"Levels\", 1, SB_LOG_RUN_LEVELS(isolatingRun));\n    SB_LOG_BLOCK_CLOSER();\n\n    /* Re-attach original links. */\n    AttachOriginalLinks(isolatingRun);\n    /* Attach new final link (of isolating run) with last subsequent link. */\n    BidiChainSetNext(isolatingRun->bidiChain, lastLink, subsequentLink);\n\n    SB_LOG_BLOCK_CLOSER();\n\n    return SBTrue;\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/IsolatingRun.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_ISOLATING_RUN_H\n#define _SB_INTERNAL_ISOLATING_RUN_H\n\n#include <API/SBBase.h>\n#include <API/SBCodepointSequence.h>\n#include <Core/Memory.h>\n#include <UBA/BidiChain.h>\n#include <UBA/BracketQueue.h>\n#include <UBA/LevelRun.h>\n\ntypedef struct _IsolatingRun {\n    const SBCodepointSequence *codepointSequence;\n    const SBBidiType *bidiTypes;\n    BidiChainRef bidiChain;\n    const LevelRun *baseLevelRun;\n    const LevelRun *_lastLevelRun;\n    BracketQueue _bracketQueue;\n    SBUInteger paragraphOffset;\n    BidiLink _originalLink;\n    SBBidiType _sos;\n    SBBidiType _eos;\n    SBLevel paragraphLevel;\n} IsolatingRun, *IsolatingRunRef;\n\nSB_INTERNAL void IsolatingRunInitialize(IsolatingRunRef isolatingRun, MemoryRef memory);\nSB_INTERNAL SBBoolean IsolatingRunResolve(IsolatingRunRef isolatingRun);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/LevelRun.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <UBA/BidiChain.h>\n#include <UBA/RunExtrema.h>\n#include <UBA/RunKind.h>\n\n#include \"LevelRun.h\"\n\nSB_INTERNAL void LevelRunInitialize(LevelRun *levelRun,\n    BidiChainRef bidiChain, BidiLink firstLink, BidiLink lastLink,\n    SBBidiType sor, SBBidiType eor)\n{\n    SBBidiType firstType = BidiChainGetType(bidiChain, firstLink);\n    SBBidiType lastType = BidiChainGetType(bidiChain, lastLink);\n\n    levelRun->next = NULL;\n    levelRun->firstLink = firstLink;\n    levelRun->lastLink = lastLink;\n    levelRun->subsequentLink = BidiChainGetNext(bidiChain, lastLink);\n    levelRun->extrema = RunExtremaMake(sor, eor);\n    levelRun->kind = RunKindMake\n                     (\n                        SBBidiTypeIsIsolateInitiator(lastType),\n                        SBBidiTypeIsIsolateTerminator(firstType)\n                     );\n    levelRun->level = BidiChainGetLevel(bidiChain, firstLink);\n}\n\nSB_INTERNAL void LevelRunAttach(LevelRun *levelRun, LevelRun *next)\n{\n    /* Only the runs of same level can be attached. */\n    SBAssert(levelRun->level == next->level);\n    /* No other run can be attached with a simple run. */\n    SBAssert(!RunKindIsSimple(levelRun->kind));\n    /* No other run can be attached with a complete isolating run. */\n    SBAssert(!RunKindIsCompleteIsolate(levelRun->kind));\n    /* Only a terminating run can be attached with an isolating run. */\n    SBAssert(RunKindIsIsolate(levelRun->kind) && RunKindIsTerminating(next->kind));\n    /* The next run must be unattached. */\n    SBAssert(!RunKindIsAttachedTerminating(next->kind));\n    \n    if (RunKindIsTerminating(next->kind)) {\n        RunKindMakeAttached(next->kind);\n    }\n    \n    if (RunKindIsIsolate(levelRun->kind)) {\n        RunKindMakeComplete(levelRun->kind);\n    }\n    \n    levelRun->next = next;\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/LevelRun.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_LEVEL_RUN_H\n#define _SB_INTERNAL_LEVEL_RUN_H\n\n#include <API/SBBase.h>\n#include <UBA/BidiChain.h>\n#include <UBA/RunExtrema.h>\n#include <UBA/RunKind.h>\n\ntypedef struct _LevelRun {\n    const struct _LevelRun *next;   /**< Reference to the next sequence of run links. */\n    BidiLink firstLink;             /**< First link of the run. */\n    BidiLink lastLink;              /**< Last link of the run. */\n    BidiLink subsequentLink;        /**< Subsequent link of the run. */\n    RunExtrema extrema;\n    RunKind kind;\n    SBLevel level;\n} LevelRun;\n\nSB_INTERNAL void LevelRunInitialize(LevelRun *levelRun,\n    BidiChainRef bidiChain, BidiLink firstLink, BidiLink lastLink,\n    SBBidiType sor, SBBidiType eor);\nSB_INTERNAL void LevelRunAttach(LevelRun *levelRun, LevelRun *next);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/RunExtrema.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_RUN_EXTREMA_H\n#define _SB_INTERNAL_RUN_EXTREMA_H\n\n#include <API/SBBase.h>\n\nenum {\n    RunExtremaLeadingL  = SBBidiTypeL << 0,\n    RunExtremaLeadingR  = SBBidiTypeR << 0,\n    \n    RunExtremaTrailingL = SBBidiTypeL << 4,\n    RunExtremaTrailingR = SBBidiTypeR << 4\n};\ntypedef SBUInt8 RunExtrema;\n\n#define RunExtremaMake(sor, eor)            \\\n(RunExtrema)                                \\\n(                                           \\\n   ((sor) << 0)                             \\\n | ((eor) << 4)                             \\\n)\n\n#define RunExtrema_SOR(e)                   \\\n(RunExtrema)                                \\\n(                                           \\\n (e) & 0xF                                  \\\n)\n\n#define RunExtrema_EOR(e)                   \\\n(RunExtrema)                                \\\n(                                           \\\n (e) >> 4                                   \\\n)\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/RunKind.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_RUN_KIND_H\n#define _SB_INTERNAL_RUN_KIND_H\n\n#include <API/SBBase.h>\n\nenum {\n    RunKindSimple         = 0x00,\n\n    RunKindIsolate        = 0x01,\n    RunKindPartial        = 0x02,\n    RunKindPartialIsolate = RunKindIsolate | RunKindPartial,\n\n    RunKindTerminating    = 0x04,\n    RunKindAttached       = 0x08\n};\ntypedef SBUInt8 RunKind;\n\n#define RunKindMake(i, t)                   \\\n(                                           \\\n   ((i) ? RunKindPartialIsolate : 0)        \\\n | ((t) ? RunKindTerminating : 0)           \\\n)\n\n#define RunKindMakeComplete(k)              \\\n(                                           \\\n (k) &= ~RunKindPartial                     \\\n)\n\n#define RunKindMakeAttached(k)              \\\n(                                           \\\n (k) |= RunKindAttached                     \\\n)\n\n#define RunKindIsSimple(k)                  \\\n(                                           \\\n (k) == RunKindSimple                       \\\n)\n\n#define RunKindIsIsolate(k)                 \\\n(                                           \\\n (k) & RunKindIsolate                       \\\n)\n\n#define RunKindIsTerminating(k)             \\\n(                                           \\\n (k) & RunKindTerminating                   \\\n)\n\n#define RunKindIsPartialIsolate(k)          \\\n(                                           \\\n (k) & RunKindPartial                       \\\n)\n\n#define RunKindIsCompleteIsolate(k)         \\\n(                                           \\\n    ((k) & RunKindPartialIsolate)           \\\n == RunKindIsolate                          \\\n)\n\n#define RunKindIsAttachedTerminating(k)     \\\n(                                           \\\n (k) & RunKindAttached                      \\\n)\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/RunQueue.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <Core/Memory.h>\n#include <UBA/LevelRun.h>\n#include <UBA/RunKind.h>\n\n#include \"RunQueue.h\"\n\n#define MakeRunQueuePosition()                      \\\n    { NULL, SBInvalidIndex }\n#define SetRunQueuePosition(rqi, _list, _index)     \\\n    ((rqi).list = (_list), (rqi).index = (_index))\n#define IsInvalidRunQueuePosition(rqi)              \\\n    ((rqi).list == NULL)\n\nstatic const RunQueuePosition InvalidRunQueuePosition = MakeRunQueuePosition();\n\nstatic RunQueueListRef AllocateRunQueueListPool(RunQueueRef queue)\n{\n    const SBUInteger newCapacity = queue->count;\n    const SBUInteger embeddedCount = RunQueueListElementCount;\n    const SBUInteger listCount = (newCapacity + embeddedCount - 1) / embeddedCount;\n    const SBUInteger blockSize = sizeof(RunQueueList) * listCount;\n    RunQueueList *pool;\n\n    pool = MemoryAllocateBlock(queue->_memory, MemoryTypeScratch, blockSize);\n\n    if (pool) {\n        RunQueueListRef previous;\n        RunQueueListRef current;\n        SBUInteger index;\n\n        /* First element. */\n        current = &pool[0];\n        current->previous = NULL;\n        previous = current;\n\n        /* Middle elements. */\n        for (index = 1; index < listCount - 1; index++) {\n            current = &pool[index];\n            current->previous = previous;\n            previous->next = current;\n            previous = current;\n        }\n\n        /* Last element. */\n        current->previous = previous;\n        current->next = NULL;\n    }\n\n    return pool;\n}\n\nstatic void AddRunQueueListToReusablePool(RunQueueRef queue, RunQueueListRef list)\n{\n    RunQueueListRef head = queue->_listPool;\n\n    if (head) {\n        head->previous = list;\n    }\n\n    list->previous = NULL;\n    list->next = head;\n\n    queue->_listPool = list;\n}\n\nstatic RunQueueListRef GetReusableRunQueueList(RunQueueRef queue)\n{\n    RunQueueListRef head = queue->_listPool;\n    RunQueueListRef list = NULL;\n\n    if (!head) {\n        head = AllocateRunQueueListPool(queue);\n    }\n\n    if (head) {\n        list = head;\n        head = head->next;\n\n        list->previous = NULL;\n        list->next = NULL;\n\n        if (head) {\n            head->previous = NULL;\n        }\n        queue->_listPool = head;\n    }\n\n    return list;\n}\n\nstatic LevelRun *InsertRunQueueElement(RunQueueRef queue)\n{\n    RunQueueListRef rearList = queue->_rearList;\n    LevelRun *element = NULL;\n\n    if ((queue->_rearTop + 1) < RunQueueListElementCount) {\n        queue->_rearTop += 1;\n        queue->count += 1;\n\n        element = &rearList->elements[queue->_rearTop];\n    } else {\n        RunQueueListRef previousList = rearList;\n\n        rearList = GetReusableRunQueueList(queue);\n\n        if (rearList) {\n            rearList->previous = previousList;\n            previousList->next = rearList;\n\n            queue->_rearList = rearList;\n            queue->_rearTop = 0;\n            queue->count += 1;\n\n            element = &rearList->elements[0];\n        }\n    }\n\n    return element;\n}\n\nstatic void FindPreviousPartialRun(RunQueueRef queue)\n{\n    RunQueuePosition partial = queue->_lastPartialRun;\n\n    if (!IsInvalidRunQueuePosition(partial)) {\n        RunQueuePosition front = queue->_front;\n        RunQueueListRef breakList = front.list->previous;\n        RunQueuePosition current;\n\n        SetRunQueuePosition(current, partial.list, partial.index + 1);\n\n        do {\n            SBUInteger start = (current.list == front.list ? front.index : 0);\n\n            while (current.index-- > start) {\n                const LevelRun *levelRun = &current.list->elements[current.index];\n\n                if (RunKindIsPartialIsolate(levelRun->kind)) {\n                    queue->_lastPartialRun = current;\n                    return;\n                }\n            }\n\n            current.list = current.list->previous;\n            current.index = RunQueueListElementCount;\n        } while (current.list != breakList);\n\n        /* No more partial run. */\n        queue->_lastPartialRun = InvalidRunQueuePosition;\n    }\n}\n\nSB_INTERNAL void RunQueueInitialize(RunQueueRef queue, MemoryRef memory)\n{\n    queue->_memory = memory;\n\n    /* Initialize first list. */\n    queue->_firstList.previous = NULL;\n    queue->_firstList.next = NULL;\n\n    /* Initialize rest of the elements. */\n    queue->_listPool = NULL;\n    queue->_rearList = &queue->_firstList;\n    queue->_rearTop = SBInvalidIndex;\n    queue->_front = InvalidRunQueuePosition;\n    queue->_lastPartialRun = InvalidRunQueuePosition;\n    queue->count = 0;\n}\n\nSB_INTERNAL SBBoolean RunQueueEnqueue(RunQueueRef queue, const LevelRun *levelRun)\n{\n    SBBoolean isEnqueued = SBFalse;\n    LevelRun *element;\n\n    element = InsertRunQueueElement(queue);\n\n    if (element) {\n        /* Copy the level run into the current element. */\n        *element = *levelRun;\n\n        /* Complete the latest isolating run with this terminating run. */\n        if (!IsInvalidRunQueuePosition(queue->_lastPartialRun)\n                && RunKindIsTerminating(element->kind)) {\n            LevelRun *incompleteRun = &queue->_lastPartialRun.list->elements[queue->_lastPartialRun.index];\n            LevelRunAttach(incompleteRun, element);\n            FindPreviousPartialRun(queue);\n        }\n\n        /* Save the location of the isolating run. */\n        if (RunKindIsIsolate(element->kind)) {\n            SetRunQueuePosition(queue->_lastPartialRun, queue->_rearList, queue->_rearTop);\n        }\n\n        if (IsInvalidRunQueuePosition(queue->_front)) {\n            /* This is the first element in the queue. */\n            SetRunQueuePosition(queue->_front, queue->_rearList, queue->_rearTop);\n        }\n\n        isEnqueued = SBTrue;\n    }\n\n    return isEnqueued;\n}\n\nSB_INTERNAL void RunQueueDequeue(RunQueueRef queue)\n{\n    /* The queue should not be empty. */\n    SBAssert(queue->count > 0);\n\n    if ((queue->_front.index + 1) < RunQueueListElementCount) {\n        queue->_front.index += 1;\n    } else {\n        RunQueueListRef frontList = queue->_front.list;\n\n        queue->_front.list = frontList->next;\n        queue->_front.index = 0;\n\n        if (queue->_front.list) {\n            queue->_front.list->previous = NULL;\n        }\n\n        AddRunQueueListToReusablePool(queue, frontList);\n    }\n\n    queue->count -= 1;\n\n    if (queue->count == 0) {\n        queue->_front = InvalidRunQueuePosition;\n    }\n}\n\nSB_INTERNAL const LevelRun *RunQueueGetFront(RunQueueRef queue)\n{\n    return &queue->_front.list->elements[queue->_front.index];\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/RunQueue.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_RUN_QUEUE_H\n#define _SB_INTERNAL_RUN_QUEUE_H\n\n#include <API/SBBase.h>\n#include <Core/Memory.h>\n#include <UBA/LevelRun.h>\n\n#define RunQueueListElementCount    8\n\ntypedef struct _RunQueueList {\n    LevelRun elements[RunQueueListElementCount];\n\n    struct _RunQueueList *previous;     /**< Reference to the previous list of queue elements */\n    struct _RunQueueList *next;         /**< Reference to the next list of queue elements */\n} RunQueueList, *RunQueueListRef;\n\ntypedef struct _RunQueuePosition {\n    RunQueueListRef list;               /**< Reference to the list containing the element */\n    SBUInteger index;                   /**< Index of the element in the list */\n} RunQueuePosition;\n\ntypedef struct _RunQueue {\n    MemoryRef _memory;\n    RunQueueList _firstList;            /**< First list of elements, which is part of the queue */\n    RunQueueListRef _listPool;          /**< Pool of reusable lists */\n    RunQueueListRef _rearList;          /**< The list containing rear element of the queue */\n    SBUInteger _rearTop;                /**< Index of rear element in rear list */\n    RunQueuePosition _front;            /**< Position of the front element */\n    RunQueuePosition _lastPartialRun;   /**< Position of the last partial run */\n    SBUInteger count;                   /**< Number of elements the queue contains */\n} RunQueue, *RunQueueRef;\n\nSB_INTERNAL void RunQueueInitialize(RunQueueRef queue, MemoryRef memory);\n\nSB_INTERNAL SBBoolean RunQueueEnqueue(RunQueueRef queue, const LevelRun *levelRun);\nSB_INTERNAL void RunQueueDequeue(RunQueueRef queue);\n\nSB_INTERNAL const LevelRun *RunQueueGetFront(RunQueueRef queue);\n\n#endif\n"
  },
  {
    "path": "unix/bidi/Source/UBA/StatusStack.c",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#include <stddef.h>\n\n#include <API/SBAssert.h>\n#include <API/SBBase.h>\n#include <Core/Memory.h>\n\n#include \"StatusStack.h\"\n\n#define STACK_LIST      0\n#define ELEMENTS        1\n#define COUNT           2\n\nstatic StatusStackElementRef InsertStatusStackElement(StatusStackRef stack)\n{\n    StatusStackListRef peekList = stack->_peekList;\n    StatusStackElementRef element = NULL;\n\n    if ((stack->_peekTop + 1) < peekList->capacity) {\n        stack->_peekTop += 1;\n        stack->count += 1;\n\n        element = &peekList->elements[stack->_peekTop];\n    } else {\n        StatusStackListRef previousList = peekList;\n\n        peekList = previousList->next;\n\n        if (!peekList) {\n            const SBUInteger capacity = stack->count;\n            void *pointers[COUNT] = { NULL };\n            SBUInteger sizes[COUNT];\n\n            sizes[STACK_LIST] = sizeof(StatusStackList);\n            sizes[ELEMENTS]   = sizeof(StatusStackElement) * capacity;\n\n            if (MemoryAllocateChunks(stack->_memory, MemoryTypeScratch, sizes, COUNT, pointers)) {\n                peekList = pointers[STACK_LIST];\n                peekList->elements = pointers[ELEMENTS];\n                peekList->capacity = capacity;\n                peekList->previous = previousList;\n                peekList->next = NULL;\n\n                previousList->next = peekList;\n            }\n        }\n\n        if (peekList) {\n            stack->_peekList = peekList;\n            stack->_peekTop = 0;\n            stack->count += 1;\n\n            element = &peekList->elements[0];\n        }\n    }\n\n    return element;\n}\n\n#undef STACK_LIST\n#undef ELEMENTS\n#undef COUNT\n\nSB_INTERNAL void StatusStackInitialize(StatusStackRef stack, MemoryRef memory)\n{\n    stack->_memory = memory;\n\n    stack->_firstList.elements = stack->_elements;\n    stack->_firstList.capacity = StatusStackEmbeddedElementCount;\n    stack->_firstList.previous = NULL;\n    stack->_firstList.next = NULL;\n\n    StatusStackSetEmpty(stack);\n}\n\nSB_INTERNAL SBBoolean StatusStackPush(StatusStackRef stack,\n    SBLevel embeddingLevel, SBBidiType overrideStatus, SBBoolean isolateStatus)\n{\n    SBBoolean isPushed = SBFalse;\n    StatusStackElementRef element;\n\n    /* The stack can hold upto 127 elements. */\n    SBAssert(stack->count <= 127);\n\n    element = InsertStatusStackElement(stack);\n\n    if (element) {\n        element->embeddingLevel = embeddingLevel;\n        element->overrideStatus = overrideStatus;\n        element->isolateStatus = isolateStatus;\n\n        isPushed = SBTrue;\n    }\n\n    return isPushed;\n}\n\nSB_INTERNAL void StatusStackPop(StatusStackRef stack)\n{\n    /* The stack should not be empty. */\n    SBAssert(stack->count > 0);\n\n    if (stack->_peekTop != 0) {\n        stack->_peekTop -= 1;\n    } else {\n        stack->_peekList = stack->_peekList->previous;\n        stack->_peekTop = stack->_peekList->capacity - 1;\n    }\n\n    stack->count -= 1;\n}\n\nSB_INTERNAL void StatusStackSetEmpty(StatusStackRef stack)\n{\n    stack->_peekList = &stack->_firstList;\n    stack->_peekTop = SBInvalidIndex;\n    stack->count = 0;\n}\n\nSB_INTERNAL SBLevel StatusStackGetEmbeddingLevel(StatusStackRef stack)\n{\n    return stack->_peekList->elements[stack->_peekTop].embeddingLevel;\n}\n\nSB_INTERNAL SBBidiType StatusStackGetOverrideStatus(StatusStackRef stack)\n{\n    return stack->_peekList->elements[stack->_peekTop].overrideStatus;\n}\n\nSB_INTERNAL SBBoolean StatusStackGetIsolateStatus(StatusStackRef stack)\n{\n    return stack->_peekList->elements[stack->_peekTop].isolateStatus;\n}\n"
  },
  {
    "path": "unix/bidi/Source/UBA/StatusStack.h",
    "content": "/*\n * Copyright (C) 2014-2025 Muhammad Tayyab Akram\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef _SB_INTERNAL_STATUS_STACK_H\n#define _SB_INTERNAL_STATUS_STACK_H\n\n#include <API/SBBase.h>\n#include <Core/Memory.h>\n\n#define StatusStackEmbeddedElementCount     16\n#define StatusStackMaxCapacity              127\n\ntypedef struct _StatusStackElement {\n    SBBoolean isolateStatus;\n    SBBidiType overrideStatus;\n    SBLevel embeddingLevel;\n} StatusStackElement, *StatusStackElementRef;\n\ntypedef struct _StatusStackList {\n    StatusStackElement *elements;\n    SBUInteger capacity;\n\n    struct _StatusStackList *previous;\n    struct _StatusStackList *next;\n} StatusStackList, *StatusStackListRef;\n\ntypedef struct _StatusStack {\n    MemoryRef _memory;\n    StatusStackElement _elements[StatusStackEmbeddedElementCount];\n    StatusStackList _firstList;\n    StatusStackListRef _peekList;\n    SBUInteger _peekTop;\n    SBUInteger count;\n} StatusStack, *StatusStackRef;\n\nSB_INTERNAL void StatusStackInitialize(StatusStackRef stack, MemoryRef memory);\n\nSB_INTERNAL SBBoolean StatusStackPush(StatusStackRef stack,\n    SBLevel embeddingLevel, SBBidiType overrideStatus, SBBoolean isolateStatus);\nSB_INTERNAL void StatusStackPop(StatusStackRef stack);\nSB_INTERNAL void StatusStackSetEmpty(StatusStackRef stack);\n\nSB_INTERNAL SBLevel StatusStackGetEmbeddingLevel(StatusStackRef stack);\nSB_INTERNAL SBBidiType StatusStackGetOverrideStatus(StatusStackRef stack);\nSB_INTERNAL SBBoolean StatusStackGetIsolateStatus(StatusStackRef stack);\n\n#endif\n"
  },
  {
    "path": "unix/configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.73 for tk 9.1.\n#\n#\n# Copyright (C) 1992-1996, 1998-2017, 2020-2026 Free Software Foundation,\n# Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as 'sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf '%s\\n' \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\ncase $# in # ((\n  0) exec $CONFIG_SHELL $as_opts \"$as_myself\" ;;\n  *) exec $CONFIG_SHELL $as_opts \"$as_myself\" \"$@\" ;;\nesac\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed 'exec'.\nprintf '%s\\n' \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test \\${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" )\nthen :\n\nelse case e in #(\n  e) exitcode=1; echo positional parameters were not saved. ;;\nesac\nfi\ntest x\\$exitcode = x0 || exit 1\nblah=\\$(echo \\$(echo blah))\ntest x\\\"\\$blah\\\" = xblah || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null\nthen :\n  as_have_required=yes\nelse case e in #(\n  e) as_have_required=no ;;\nesac\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null\nthen :\n\nelse case e in #(\n  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_suggested\" 2>/dev/null\nthen :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\nIFS=$as_save_IFS\nif $as_found\nthen :\n\nelse case e in #(\n  e) if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      as_run=a \"$SHELL\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi ;;\nesac\nfi\n\n\n      if test \"x$CONFIG_SHELL\" != x\nthen :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\ncase $# in # ((\n  0) exec $CONFIG_SHELL $as_opts \"$as_myself\" ;;\n  *) exec $CONFIG_SHELL $as_opts \"$as_myself\" \"$@\" ;;\nesac\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed 'exec'.\nprintf '%s\\n' \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno\nthen :\n  printf '%s\\n' \"$0: This script requires a shell more modern than all\"\n  printf '%s\\n' \"$0: the shells that I found on your system.\"\n  if test ${ZSH_VERSION+y} ; then\n    printf '%s\\n' \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    printf '%s\\n' \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    printf '%s\\n' \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi ;;\nesac\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf '%s\\n' \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse case e in #(\n  e) as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  } ;;\nesac\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse case e in #(\n  e) as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  } ;;\nesac\nfi # as_fn_arith\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf '%s\\n' \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      t clear\n      :clear\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { printf '%s\\n' \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.\n    # In both cases, we have to default to 'cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_sed_cpp=\"y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_cpp=\"eval sed '$as_sed_cpp'\" # deprecated\n\n# Sed expression to map a string onto a valid variable name.\nas_sed_sh=\"y%*+%pp%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_sh=\"eval sed '$as_sed_sh'\" # deprecated\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_CONFIG_STATUS=\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME='tk'\nPACKAGE_TARNAME='tk'\nPACKAGE_VERSION='9.1'\nPACKAGE_STRING='tk 9.1'\nPACKAGE_BUGREPORT=''\nPACKAGE_URL=''\n\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stddef.h>\n#ifdef HAVE_STDIO_H\n# include <stdio.h>\n#endif\n#ifdef HAVE_STDLIB_H\n# include <stdlib.h>\n#endif\n#ifdef HAVE_STRING_H\n# include <string.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_header_c_list=\nac_subst_vars='LTLIBOBJS\nREZ_FLAGS\nREZ\nAPP_RSRC_FILE\nLIB_RSRC_FILE\nWISH_RSRC_FILE\nTK_RSRC_FILE\nCFBUNDLELOCALIZATIONS\nEXTRA_WISH_LIBS\nEXTRA_BUILD_HTML\nEXTRA_INSTALL_BINARIES\nEXTRA_INSTALL\nEXTRA_APP_CC_SWITCHES\nEXTRA_CC_SWITCHES\nHTML_DIR\nPRIVATE_INCLUDE_DIR\nLIB_RUNTIME_DIR\nTK_LIBRARY\nTK_PKG_DIR\nTK_WINDOWINGSYSTEM\nLOCALES\nXLIBSW\nXINCLUDES\nTCL_STUB_FLAGS\nTK_BUILD_LIB_SPEC\nLD_LIBRARY_PATH_VAR\nTK_SHARED_BUILD\nTK_SRC_DIR\nTK_BUILD_STUB_LIB_PATH\nTK_BUILD_STUB_LIB_SPEC\nTK_INCLUDE_SPEC\nTK_STUB_LIB_PATH\nTK_STUB_LIB_SPEC\nTK_STUB_LIB_FLAG\nTK_STUB_LIB_FILE\nTK_LIB_SPEC\nTK_LIB_FLAG\nTK_LIB_FILE\nTK_YEAR\nTK_PATCH_LEVEL\nTK_MINOR_VERSION\nTK_MAJOR_VERSION\nTK_VERSION\nTK_DEMO_DIR\nDEMO_DIR\nINSTALL_MSGS\nINSTALL_LIBRARIES\nTK_ZIP_FILE\nZIPFS_BUILD\nZIP_INSTALL_OBJS\nZIP_PROG_VFSSEARCH\nZIP_PROG_OPTIONS\nZIP_PROG\nMACHER_PROG\nEXEEXT_FOR_BUILD\nCC_FOR_BUILD\nATK_LIBS\nATK_CFLAGS\nCUPS_LIBS\nCUPS_CFLAGS\nFONTSYSTEM\nUNIX_FONT_OBJS\nBIDI_CFLAGS\nHB_LIBS\nHB_CFLAGS\nXFT_LIBS\nXFT_CFLAGS\nXMKMF\nCPP\nLDFLAGS_DEFAULT\nCFLAGS_DEFAULT\nINSTALL_STUB_LIB\nDLL_INSTALL_DIR\nINSTALL_LIB\nMAKE_STUB_LIB\nMAKE_LIB\nSHLIB_SUFFIX\nSHLIB_CFLAGS\nSHLIB_LD_LIBS\nTK_SHLIB_LD_EXTRAS\nTCL_SHLIB_LD_EXTRAS\nSHLIB_LD\nSTLIB_LD\nLD_SEARCH_FLAGS\nCC_SEARCH_FLAGS\nLDFLAGS_OPTIMIZE\nLDFLAGS_DEBUG\nCFLAGS_NOLTO\nCFLAGS_WARNING\nCFLAGS_OPTIMIZE\nCFLAGS_DEBUG\nLDAIX_SRC\nPLAT_SRCS\nPLAT_OBJS\nDL_OBJS\nDL_LIBS\nTCL_LIBS\nLIBOBJS\nAR\nRANLIB\nSHARED_BUILD\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nMAN_FLAGS\nBUILD_TCLSH\nTCLSH_PROG\nTCL_STUB_LIB_SPEC\nTCL_STUB_LIB_FLAG\nTCL_STUB_LIB_FILE\nTCL_LIB_SPEC\nTCL_LIB_FLAG\nTCL_LIB_FILE\nTCL_SRC_DIR\nTCL_BIN_DIR\nTCL_PATCH_LEVEL\nTCL_VERSION\nECHO_T\nECHO_N\nECHO_C\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nrunstatedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL\nOBJEXT_FOR_BUILD'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nwith_tcl\nenable_man_symlinks\nenable_man_compression\nenable_man_suffix\nwith_encoding\nenable_shared\nenable_64bit\nenable_64bit_vis\nenable_rpath\nenable_corefoundation\nenable_load\nenable_symbols\nenable_aqua\nwith_x\nenable_xft\nenable_bidi\nenable_libcups\nenable_xss\nenable_framework\nenable_zipfs\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP\nXMKMF'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nrunstatedir='${localstatedir}/run'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE_TARNAME}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -runstatedir | --runstatedir | --runstatedi | --runstated \\\n  | --runstate | --runstat | --runsta | --runst | --runs \\\n  | --run | --ru | --r)\n    ac_prev=runstatedir ;;\n  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \\\n  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \\\n  | --run=* | --ru=* | --r=*)\n    runstatedir=$ac_optarg ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: '$ac_option'\nTry '$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: '$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    printf '%s\\n' \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      printf '%s\\n' \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`printf '%s\\n' $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     printf '%s\\n' \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir runstatedir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: '$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but 'cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n'configure' configures tk 9.1 to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print 'checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for '--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or '..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, 'make install' will install all the files in\n'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than '$ac_default_prefix' using '--prefix',\nfor instance '--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/tk]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n\nX features:\n  --x-includes=DIR    X include files are in DIR\n  --x-libraries=DIR   X library files are in DIR\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n  case $ac_init_help in\n     short | recursive ) echo \"Configuration of tk 9.1:\";;\n   esac\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n  --enable-man-symlinks   use symlinks for the manpages (default: off)\n  --enable-man-compression=PROG\n                          compress the manpages with PROG (default: off)\n  --enable-man-suffix=STRING\n                          use STRING as a suffix to manpage file names\n                          (default: no, tk if enabled without\n                          specifying STRING)\n  --enable-shared         build and link with shared libraries (default: on)\n  --enable-64bit          enable 64bit support (default: off)\n  --enable-64bit-vis      enable 64bit Sparc VIS support (default: off)\n  --disable-rpath         disable rpath support (default: on)\n  --enable-corefoundation use CoreFoundation API on MacOSX (default: on)\n  --enable-load           allow dynamic loading and \"load\" command (default:\n                          on)\n  --enable-symbols        build with debugging symbols (default: off)\n  --enable-aqua=yes|no    use Aqua windowingsystem on Mac OS X (default: no)\n  --enable-xft            use freetype/fontconfig/xft for antialiased fonts\n                          (default: yes)\n  --enable-bidi           enable bidirectional/RTL text support using\n                          SheenBidi + HarfBuzz (forces --enable-xft=yes)\n  --enable-libcups        use libcups (default: on)\n  --enable-xss            use XScreenSaver for activity timer (default: on)\n  --enable-framework      package shared libraries in MacOSX frameworks\n                          (default: off)\n  --enable-zipfs          build with Zipfs support (default: on)\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-tcl              directory containing tcl configuration\n                          (tclConfig.sh)\n  --with-encoding         encoding for configuration values (default: utf-8)\n  --with-x                use the X Window System\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n  XMKMF       Path to xmkmf, Makefile generator for X Window System\n\nUse these variables to override the choices made by 'configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf '%s\\n' \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf '%s\\n' \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for configure.gnu first; this name is used for a wrapper for\n    # Metaconfig's \"Configure\" on case-insensitive file systems.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      printf '%s\\n' \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\ntk configure 9.1\ngenerated by GNU Autoconf 2.73\n\nCopyright (C) 2026 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1 ;;\nesac\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1 ;;\nesac\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  eval \"$3=yes\"\nelse case e in #(\n  e) eval \"$3=no\" ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\neval ac_res=\\$$3\n\t       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf '%s\\n' \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_check_func LINENO FUNC VAR\n# ----------------------------------\n# Tests whether FUNC exists, setting the cache variable VAR accordingly\nac_fn_c_check_func ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n/* Define $2 to an innocuous variant, in case <limits.h> declares $2.\n   For example, HP-UX 11i <limits.h> declares gettimeofday.  */\n#define $2 innocuous_$2\n\n/* System header to define __stub macros and hopefully few prototypes,\n   which can conflict with char $2 (void); below.  */\n\n#include <limits.h>\n#undef $2\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar $2 (void);\n/* The GNU C library defines this for functions which it implements\n    to always fail with ENOSYS.  Some functions are actually named\n    something starting with __ and the normal name is an alias.  */\n#if defined __stub_$2 || defined __stub___$2\nchoke me\n#endif\n\nint\nmain (void)\n{\nreturn $2 ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  eval \"$3=yes\"\nelse case e in #(\n  e) eval \"$3=no\" ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext ;;\nesac\nfi\neval ac_res=\\$$3\n\t       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf '%s\\n' \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_func\n\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that\n# executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: program exited with status $ac_status\" >&5\n       printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status ;;\nesac\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } > conftest.i && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1 ;;\nesac\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\n\n# ac_fn_c_check_type LINENO TYPE VAR INCLUDES\n# -------------------------------------------\n# Tests whether TYPE exists after having included INCLUDES, setting cache\n# variable VAR accordingly.\nac_fn_c_check_type ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) eval \"$3=no\"\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain (void)\n{\nif (sizeof ($2))\n\t return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain (void)\n{\nif (sizeof (($2)))\n\t    return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) eval \"$3=yes\" ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\neval ac_res=\\$$3\n\t       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf '%s\\n' \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_type\nac_configure_args_raw=\nfor ac_arg\ndo\n  case $ac_arg in\n  *\\'*)\n    ac_arg=`printf '%s\\n' \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n  esac\n  as_fn_append ac_configure_args_raw \" '$ac_arg'\"\ndone\n\ncase $ac_configure_args_raw in\n  *$as_nl*)\n    ac_safe_unquote= ;;\n  *)\n    ac_unsafe_z='|&;<>()$`\\\\\"*?[ ''\t' # This string ends in space, tab.\n    ac_unsafe_a=\"$ac_unsafe_z#~\"\n    ac_safe_unquote=\"s/ '\\\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\\\)'/ \\\\1/g\"\n    ac_configure_args_raw=`      printf '%s\\n' \"$ac_configure_args_raw\" | sed \"$ac_safe_unquote\"`;;\nesac\n\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by tk $as_me 9.1, which was\ngenerated by GNU Autoconf 2.73.  Invocation command line was\n\n  $ $0$ac_configure_args_raw\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    printf '%s\\n' \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`printf '%s\\n' \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# Dump the cache to stdout.  It can be in a pipe (this is a requirement).\nac_cache_dump ()\n{\n  # The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\nprintf '%s\\n' \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # 'set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # 'set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n}\n\n# Print debugging info to stdout.\nac_dump_debugging_info ()\n{\n  echo\n\n  printf '%s\\n' \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n  echo\n  ac_cache_dump\n  echo\n\n  printf '%s\\n' \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n  echo\n  for ac_var in $ac_subst_vars\n  do\n    eval ac_val=\\$$ac_var\n    case $ac_val in\n    *\\'*) ac_val=`printf '%s\\n' \"$ac_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n    esac\n    printf '%s\\n' \"$ac_var='$ac_val'\"\n  done | sort\n  echo\n\n  if test -n \"$ac_subst_files\"; then\n    printf '%s\\n' \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n    echo\n    for ac_var in $ac_subst_files\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'*) ac_val=`printf '%s\\n' \"$ac_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n      esac\n      printf '%s\\n' \"$ac_var='$ac_val'\"\n    done | sort\n    echo\n  fi\n\n  if test -s confdefs.h; then\n    printf '%s\\n' \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n    echo\n    cat confdefs.h\n    echo\n  fi\n  test \"$ac_signal\" != 0 &&\n    printf '%s\\n' \"$as_me: caught signal $ac_signal\"\n  printf '%s\\n' \"$as_me: exit $exit_status\"\n}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.\nac_exit_trap ()\n{\n  exit_status=\n  # Sanitize IFS.\n  IFS=\" \"\"\t$as_nl\"\n  # Save into config.log some information that might help in debugging.\n  ac_dump_debugging_info >&5\n  eval \"rm -f $ac_clean_CONFIG_STATUS core *.core core.conftest.*\" &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n}\n\ntrap 'ac_exit_trap $?' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\nprintf '%s\\n' \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\nprintf '%s\\n' \"#define PACKAGE_NAME \\\"$PACKAGE_NAME\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_TARNAME \\\"$PACKAGE_TARNAME\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_VERSION \\\"$PACKAGE_VERSION\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_STRING \\\"$PACKAGE_STRING\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_BUGREPORT \\\"$PACKAGE_BUGREPORT\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_URL \\\"$PACKAGE_URL\\\"\" >>confdefs.h\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nif test -n \"$CONFIG_SITE\"; then\n  ac_site_files=\"$CONFIG_SITE\"\nelif test \"x$prefix\" != xNONE; then\n  ac_site_files=\"$prefix/share/config.site $prefix/etc/config.site\"\nelse\n  ac_site_files=\"$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site\"\nfi\n\nfor ac_site_file in $ac_site_files\ndo\n  case $ac_site_file in #(\n  */*) :\n     ;; #(\n  *) :\n    ac_site_file=./$ac_site_file ;;\nesac\n  if test -f \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\nprintf '%s\\n' \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Test code for whether the C compiler supports C23 (global declarations)\nac_c_conftest_c23_globals='\n/* Does the compiler advertise conformance to C17 or earlier?\n   Although GCC 14 does not do that, even with -std=gnu23,\n   it is close enough, and defines __STDC_VERSION == 202000L.  */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ <= 201710L\n# error \"Compiler advertises conformance to C17 or earlier\"\n#endif\n\n// Check alignas.\nchar alignas (double) c23_aligned_as_double;\nchar alignas (0) c23_no_special_alignment;\nextern char c23_aligned_as_int;\nchar alignas (0) alignas (int) c23_aligned_as_int;\n\n// Check alignof.\nenum\n{\n  c23_int_alignment = alignof (int),\n  c23_int_array_alignment = alignof (int[100]),\n  c23_char_alignment = alignof (char)\n};\nstatic_assert (0 < -alignof (int), \"alignof is signed\");\n\nint function_with_unnamed_parameter (int) { return 0; }\n\nvoid c23_noreturn ();\n\n/* Test parsing of string and char UTF-8 literals (including hex escapes).\n   The parens pacify GCC 15.  */\nbool use_u8 = (!sizeof u8\"\\xFF\") == (!u8'\\''x'\\'');\n\nbool check_that_bool_works = true | false | !nullptr;\n#if !true\n# error \"true does not work in #if\"\n#endif\n#if false\n#elifdef __STDC_VERSION__\n#else\n# error \"#elifdef does not work\"\n#endif\n\n#ifndef __has_c_attribute\n# error \"__has_c_attribute not defined\"\n#endif\n\n#ifndef __has_include\n# error \"__has_include not defined\"\n#endif\n\n#define LPAREN() (\n#define FORTY_TWO(x) 42\n#define VA_OPT_TEST(r, x, ...) __VA_OPT__ (FORTY_TWO r x))\nstatic_assert (VA_OPT_TEST (LPAREN (), 0, <:-) == 42);\n\nstatic_assert (0b101010 == 42);\nstatic_assert (0B101010 == 42);\nstatic_assert (0xDEAD'\\''BEEF == 3'\\''735'\\''928'\\''559);\nstatic_assert (0.500'\\''000'\\''000 == 0.5);\n\nenum unsignedish : unsigned int { uione = 1 };\nstatic_assert (0 < -uione);\n\n#include <stddef.h>\nconstexpr nullptr_t null_pointer = nullptr;\n\nstatic typeof (1 + 1L) two () { return 2; }\nstatic long int three () { return 3; }\n'\n\n# Test code for whether the C compiler supports C23 (body of main).\nac_c_conftest_c23_main='\n  {\n    label_before_declaration:\n      int arr[10] = {};\n      if (arr[0])\n        goto label_before_declaration;\n      if (!arr[0])\n        goto label_at_end_of_block;\n    label_at_end_of_block:\n  }\n  ok |= !null_pointer;\n  ok |= two != three;\n'\n\n# Test code for whether the C compiler supports C23 (complete).\nac_c_conftest_c23_program=\"${ac_c_conftest_c23_globals}\n\nint\nmain (int, char **)\n{\n  int ok = 0;\n  ${ac_c_conftest_c23_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C89 (global declarations)\nac_c_conftest_c89_globals='\n/* Do not test the value of __STDC__, because some compilers define it to 0\n   or do not define it, while otherwise adequately conforming.  */\n\n#include <stddef.h>\n#include <stdarg.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */\nstruct buf { int x; };\nstruct buf * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (char **p, int i)\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* C89 style stringification. */\n#define noexpand_stringify(a) #a\nconst char *stringified = noexpand_stringify(arbitrary+token=sequence);\n\n/* C89 style token pasting.  Exercises some of the corner cases that\n   e.g. old MSVC gets wrong, but not very hard. */\n#define noexpand_concat(a,b) a##b\n#define expand_concat(a,b) noexpand_concat(a,b)\nextern int vA;\nextern int vbee;\n#define aye A\n#define bee B\nint *pvA = &expand_concat(v,aye);\nint *pvbee = &noexpand_concat(v,bee);\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not \\xHH hex character constants.\n   These do not provoke an error unfortunately, instead are silently treated\n   as an \"x\".  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously \\x00 != x always comes out true, for an\n   array size at least.  It is necessary to write \\x00 == 0 to get something\n   that is true only with -std.  */\nint osf4_cc_array ['\\''\\x00'\\'' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) '\\''x'\\''\nint xlc6_cc_array[FOO(a) == '\\''x'\\'' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),\n               int, int);'\n\n# Test code for whether the C compiler supports C89 (body of main).\nac_c_conftest_c89_main='\nok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);\n'\n\n# Test code for whether the C compiler supports C99 (global declarations)\nac_c_conftest_c99_globals='\n/* Does the compiler advertise C99 conformance? */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L\n# error \"Compiler does not advertise C99 conformance\"\n#endif\n\n// See if C++-style comments work.\n\n#include <stdbool.h>\nextern int puts (const char *);\nextern int printf (const char *, ...);\nextern int dprintf (int, const char *, ...);\nextern void *malloc (size_t);\nextern void free (void *);\n\n// Check varargs macros.  These examples are taken from C99 6.10.3.5.\n// dprintf is used instead of fprintf to avoid needing to declare\n// FILE and stderr, and \"aND\" is used instead of \"and\" to work around\n// GCC bug 40564 which is irrelevant here.\n#define debug(...) dprintf (2, __VA_ARGS__)\n#define showlist(...) puts (#__VA_ARGS__)\n#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))\nstatic void\ntest_varargs_macros (void)\n{\n  int x = 1234;\n  int y = 5678;\n  debug (\"Flag\");\n  debug (\"X = %d\\n\", x);\n  showlist (The first, second, aND third items.);\n  report (x>y, \"x is %d but y is %d\", x, y);\n}\n\n// Check long long types.\n#define BIG64 18446744073709551615ull\n#define BIG32 4294967295ul\n#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)\n#if !BIG_OK\n  #error \"your preprocessor is broken\"\n#endif\n#if BIG_OK\n#else\n  #error \"your preprocessor is broken\"\n#endif\nstatic long long int bignum = -9223372036854775807LL;\nstatic unsigned long long int ubignum = BIG64;\n\nstruct incomplete_array\n{\n  int datasize;\n  double data[];\n};\n\nstruct named_init {\n  int number;\n  const wchar_t *name;\n  double average;\n};\n\ntypedef const char *ccp;\n\nstatic inline int\ntest_restrict (ccp restrict text)\n{\n  // Iterate through items via the restricted pointer.\n  // Also check for declarations in for loops.\n  for (unsigned int i = 0; *(text+i) != '\\''\\0'\\''; ++i)\n    continue;\n  return 0;\n}\n\n// Check varargs and va_copy.\nstatic bool\ntest_varargs (const char *format, ...)\n{\n  va_list args;\n  va_start (args, format);\n  va_list args_copy;\n  va_copy (args_copy, args);\n\n  const char *str = \"\";\n  int number = 0;\n  float fnumber = 0;\n\n  while (*format)\n    {\n      switch (*format++)\n\t{\n\tcase '\\''s'\\'': // string\n\t  str = va_arg (args_copy, const char *);\n\t  break;\n\tcase '\\''d'\\'': // int\n\t  number = va_arg (args_copy, int);\n\t  break;\n\tcase '\\''f'\\'': // float\n\t  fnumber = va_arg (args_copy, double);\n\t  break;\n\tdefault:\n\t  break;\n\t}\n    }\n  va_end (args_copy);\n  va_end (args);\n\n  return *str && number && fnumber;\n}\n'\n\n# Test code for whether the C compiler supports C99 (body of main).\nac_c_conftest_c99_main='\n  // Check bool.\n  _Bool success = false;\n  success |= (argc != 0);\n\n  // Check restrict.\n  if (test_restrict (\"String literal\") == 0)\n    success = true;\n  const char *restrict newvar = \"Another string\";\n\n  // Check varargs.\n  success &= test_varargs (\"s, d'\\'' f .\", \"string\", 65, 34.234);\n  test_varargs_macros ();\n\n  // Check flexible array members.\n  static struct incomplete_array *volatile incomplete_array_pointer;\n  struct incomplete_array *ia = incomplete_array_pointer;\n  ia->datasize = 10;\n  for (int i = 0; i < ia->datasize; ++i)\n    ia->data[i] = i * 1.234;\n  // Work around memory leak warnings.\n  free (ia);\n\n  // Check named initializers.\n  struct named_init ni = {\n    .number = 34,\n    .name = L\"Test wide string\",\n    .average = 543.34343,\n  };\n\n  ni.number = 58;\n\n  // Do not test for VLAs, as some otherwise-conforming compilers lack them.\n  // C code should instead use __STDC_NO_VLA__; see Autoconf manual.\n\n  // work around unused variable warnings\n  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\\''x'\\''\n\t || ni.number != 58);\n'\n\n# Test code for whether the C compiler supports C11 (global declarations)\nac_c_conftest_c11_globals='\n/* Does the compiler advertise C11 conformance? */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L\n# error \"Compiler does not advertise C11 conformance\"\n#endif\n\n// Check _Alignas.\nchar _Alignas (double) aligned_as_double;\nchar _Alignas (0) no_special_alignment;\nextern char aligned_as_int;\nchar _Alignas (0) _Alignas (int) aligned_as_int;\n\n// Check _Alignof.\nenum\n{\n  int_alignment = _Alignof (int),\n  int_array_alignment = _Alignof (int[100]),\n  char_alignment = _Alignof (char)\n};\n_Static_assert (0 < -_Alignof (int), \"_Alignof is signed\");\n\n// Check _Noreturn.\nint _Noreturn does_not_return (void) { for (;;) continue; }\n\n// Check _Static_assert.\nstruct test_static_assert\n{\n  int x;\n  _Static_assert (sizeof (int) <= sizeof (long int),\n                  \"_Static_assert does not work in struct\");\n  long int y;\n};\n\n// Check UTF-8 literals.\n#define u8 syntax error!\nchar const utf8_literal[] = u8\"happens to be ASCII\" \"another string\";\n\n// Check duplicate typedefs.\ntypedef long *long_ptr;\ntypedef long int *long_ptr;\ntypedef long_ptr long_ptr;\n\n// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.\nstruct anonymous\n{\n  union {\n    struct { int i; int j; };\n    struct { int k; long int l; } w;\n  };\n  int m;\n} v1;\n'\n\n# Test code for whether the C compiler supports C11 (body of main).\nac_c_conftest_c11_main='\n  _Static_assert ((offsetof (struct anonymous, i)\n\t\t   == offsetof (struct anonymous, w.k)),\n\t\t  \"Anonymous union alignment botch\");\n  v1.i = 2;\n  v1.w.k = 5;\n  ok |= v1.i != 5;\n'\n\n# Test code for whether the C compiler supports C11 (complete).\nac_c_conftest_c11_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n${ac_c_conftest_c11_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  ${ac_c_conftest_c11_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C99 (complete).\nac_c_conftest_c99_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C89 (complete).\nac_c_conftest_c89_program=\"${ac_c_conftest_c89_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  return ok;\n}\n\"\n\nas_fn_append ac_header_c_list \" stdio.h stdio_h HAVE_STDIO_H\"\nas_fn_append ac_header_c_list \" stdlib.h stdlib_h HAVE_STDLIB_H\"\nas_fn_append ac_header_c_list \" string.h string_h HAVE_STRING_H\"\nas_fn_append ac_header_c_list \" inttypes.h inttypes_h HAVE_INTTYPES_H\"\nas_fn_append ac_header_c_list \" stdint.h stdint_h HAVE_STDINT_H\"\nas_fn_append ac_header_c_list \" strings.h strings_h HAVE_STRINGS_H\"\nas_fn_append ac_header_c_list \" sys/stat.h sys_stat_h HAVE_SYS_STAT_H\"\nas_fn_append ac_header_c_list \" sys/types.h sys_types_h HAVE_SYS_TYPES_H\"\nas_fn_append ac_header_c_list \" unistd.h unistd_h HAVE_UNISTD_H\"\nas_fn_append ac_header_c_list \" sys/time.h sys_time_h HAVE_SYS_TIME_H\"\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=\n\tfor ac_val in x $ac_old_val; do\n\t  ac_old_val_w=\"$ac_old_val_w $ac_val\"\n\tdone\n\tac_new_val_w=\n\tfor ac_val in x $ac_new_val; do\n\t  ac_new_val_w=\"$ac_new_val_w $ac_val\"\n\tdone\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:\" >&5\nprintf '%s\\n' \"$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'\" >&5\nprintf '%s\\n' \"$as_me:   former value:  '$ac_old_val'\" >&2;}\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'\" >&5\nprintf '%s\\n' \"$as_me:   current value: '$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`printf '%s\\n' \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\nprintf '%s\\n' \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run '${MAKE-make} distclean' and/or 'rm $cache_file'\n\t    and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\n\n# Determine whether it's possible to make 'echo' print without a newline.\n# These variables are no longer used directly by Autoconf, but are AC_SUBSTed\n# for compatibility with existing Makefiles.\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n\n\nTK_VERSION=9.1\nTK_MAJOR_VERSION=9\nTK_MINOR_VERSION=1\nTK_PATCH_LEVEL=\"a2\"\nVERSION=${TK_VERSION}\nLOCALES=\"cs da de el en en_gb eo es fr hu it nl pl pt ru sv\"\n\n#--------------------------------------------------------------------\n# Find and load the tclConfig.sh file\n#--------------------------------------------------------------------\n\n\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\n# Check whether --with-tcl was given.\nif test ${with_tcl+y}\nthen :\n  withval=$with_tcl; with_tclconfig=\"${withval}\"\nfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for Tcl configuration\" >&5\nprintf %s \"checking for Tcl configuration... \" >&6; }\n\tif test ${ac_cv_c_tclconfig+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase \"${with_tclconfig}\" in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f \"${with_tclconfig}\"; then\n\t\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&5\nprintf '%s\\n' \"$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&2;}\n\t\t\t    with_tclconfig=\"`echo \"${with_tclconfig}\" | sed 's!/tclConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd \"${with_tclconfig}\"; pwd)`\"\n\t\telse\n\t\t    as_fn_error $? \"${with_tclconfig} directory doesn't contain tclConfig.sh\" \"$LINENO\" 5\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tcl.framework/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/Tcl.framework; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/pkg/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib/tcl9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib64 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tcl9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t ;;\nesac\nfi\n\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    as_fn_error $? \"Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh\" \"$LINENO\" 5\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=\"${ac_cv_c_tclconfig}\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf '%s\\n' \"found ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n\tfi\n    fi\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf %s \"checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... \" >&6; }\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: loading\" >&5\nprintf '%s\\n' \"loading\" >&6; }\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf '%s\\n' \"could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n    fi\n\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n\tTCL_LIB_SPEC=\"${TCL_BUILD_LIB_SPEC}\"\n\tTCL_STUB_LIB_SPEC=\"${TCL_BUILD_STUB_LIB_SPEC}\"\n\tTCL_STUB_LIB_PATH=\"${TCL_BUILD_STUB_LIB_PATH}\"\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tcl was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tcl.framework installed in an arbitrary location.\n\tcase ${TCL_DEFS} in\n\t    *TCL_FRAMEWORK*)\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_LIB_FILE}\"; then\n\t\t    for i in \"`cd \"${TCL_BIN_DIR}\"; pwd`\" \\\n\t\t\t     \"`cd \"${TCL_BIN_DIR}\"/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TCL_LIB_FILE}.framework\"; then\n\t\t\t    TCL_LIB_SPEC=\"-F`dirname \"$i\" | sed -e 's/ /\\\\\\\\ /g'` -framework ${TCL_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"; then\n\t\t    TCL_STUB_LIB_SPEC=\"-L`echo \"${TCL_BIN_DIR}\"  | sed -e 's/ /\\\\\\\\ /g'` ${TCL_STUB_LIB_FLAG}\"\n\t\t    TCL_STUB_LIB_PATH=\"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nif test \"${TCL_MAJOR_VERSION}\" -lt 9 ; then\n    as_fn_error $? \"${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 9.0+\nFound config for Tcl ${TCL_VERSION}\" \"$LINENO\" 5\nfi\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for tclsh\" >&5\nprintf %s \"checking for tclsh... \" >&6; }\n    if test ${ac_cv_path_tclsh+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/tclsh[8-9]* 2> /dev/null` \\\n\t\t    `ls -r $dir/tclsh* 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_tclsh\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_tclsh=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n     ;;\nesac\nfi\n\n\n    if test -f \"$ac_cv_path_tclsh\" ; then\n\tTCLSH_PROG=\"$ac_cv_path_tclsh\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG\" >&5\nprintf '%s\\n' \"$TCLSH_PROG\" >&6; }\n    else\n\t# It is not an error if an installed version of Tcl can't be located.\n\tTCLSH_PROG=\"\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH\" >&5\nprintf '%s\\n' \"No tclsh found on PATH\" >&6; }\n    fi\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for tclsh in Tcl build directory\" >&5\nprintf %s \"checking for tclsh in Tcl build directory... \" >&6; }\n    BUILD_TCLSH=\"${TCL_BIN_DIR}\"/tclsh\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $BUILD_TCLSH\" >&5\nprintf '%s\\n' \"$BUILD_TCLSH\" >&6; }\n\n\n\n#------------------------------------------------------------------------\n# Handle the --prefix=... option\n#------------------------------------------------------------------------\n\nif test \"${prefix}\" = \"NONE\"; then\n    prefix=\"$TCL_PREFIX\"\nfi\nif test \"${exec_prefix}\" = \"NONE\"; then\n    exec_prefix=$prefix\nfi\n# Make sure srcdir is fully qualified!\nsrcdir=\"`cd \"$srcdir\" ; pwd`\"\nTK_SRC_DIR=\"`cd \"$srcdir\"/..; pwd`\"\n\n#------------------------------------------------------------------------\n# Compress and/or soft link the manpages?\n#------------------------------------------------------------------------\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use symlinks for manpages\" >&5\nprintf %s \"checking whether to use symlinks for manpages... \" >&6; }\n    # Check whether --enable-man-symlinks was given.\nif test ${enable_man_symlinks+y}\nthen :\n  enableval=$enable_man_symlinks; test \"$enableval\" != \"no\" && MAN_FLAGS=\"$MAN_FLAGS --symlinks\"\nelse case e in #(\n  e) enableval=\"no\" ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enableval\" >&5\nprintf '%s\\n' \"$enableval\" >&6; }\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to compress the manpages\" >&5\nprintf %s \"checking whether to compress the manpages... \" >&6; }\n    # Check whether --enable-man-compression was given.\nif test ${enable_man_compression+y}\nthen :\n  enableval=$enable_man_compression; case $enableval in\n\t    yes) as_fn_error $? \"missing argument to --enable-man-compression\" \"$LINENO\" 5;;\n\t    no)  ;;\n\t    *)   MAN_FLAGS=\"$MAN_FLAGS --compress $enableval\";;\n\tesac\nelse case e in #(\n  e) enableval=\"no\" ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enableval\" >&5\nprintf '%s\\n' \"$enableval\" >&6; }\n    if test \"$enableval\" != \"no\"; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for compressed file suffix\" >&5\nprintf %s \"checking for compressed file suffix... \" >&6; }\n\ttouch TeST\n\t$enableval TeST\n\tZ=`ls TeST.* | sed 's/^....//'`\n\trm -f TeST*\n\tMAN_FLAGS=\"$MAN_FLAGS --extension $Z\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $Z\" >&5\nprintf '%s\\n' \"$Z\" >&6; }\n    fi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to add a package name suffix for the manpages\" >&5\nprintf %s \"checking whether to add a package name suffix for the manpages... \" >&6; }\n    # Check whether --enable-man-suffix was given.\nif test ${enable_man_suffix+y}\nthen :\n  enableval=$enable_man_suffix; case $enableval in\n\t    yes) enableval=\"tk\" MAN_FLAGS=\"$MAN_FLAGS --suffix $enableval\";;\n\t    no)  ;;\n\t    *)   MAN_FLAGS=\"$MAN_FLAGS --suffix $enableval\";;\n\tesac\nelse case e in #(\n  e) enableval=\"no\" ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enableval\" >&5\nprintf '%s\\n' \"$enableval\" >&6; }\n\n\n\n\n#------------------------------------------------------------------------\n# Standard compiler checks\n#------------------------------------------------------------------------\n\n# If the user did not set CFLAGS, set it now to keep\n# the AC_PROG_CC macro from adding \"-g -O2\".\nif test \"${CFLAGS+set}\" != \"set\" ; then\n    CFLAGS=\"\"\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir$ac_word${1+' '}$@\"\n  fi\nfi\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}clang\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}clang; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}clang\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"clang\", so it can be a program name with args.\nset dummy clang; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"clang\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\nprintf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion -version; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\nprintf %s \"checking whether the C compiler works... \" >&6; }\nac_link_default=`printf '%s\\n' \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.\n# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test ${ac_cv_exeext+y} && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an '-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse case e in #(\n  e) ac_file='' ;;\nesac\nfi\nif test -z \"$ac_file\"\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nprintf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee 'config.log' for more details\" \"$LINENO\" 5; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; } ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\nprintf %s \"checking for C compiler default output file name... \" >&6; }\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\nprintf '%s\\n' \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\nprintf %s \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)\n# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will\n# work properly (i.e., refer to 'conftest.exe'), while it won't with\n# 'rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse case e in #(\n  e) { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\nprintf '%s\\n' \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain (void)\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n if (!f)\n  return 1;\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\nprintf %s \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot run C compiled programs.\nIf you meant to cross compile, use '--host'.\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\nprintf '%s\\n' \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext \\\n  conftest.o conftest.obj conftest.out\nac_clean_files=$ac_clean_files_save\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\nprintf %s \"checking for suffix of object files... \" >&6; }\nif test ${ac_cv_objext+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\nprintf '%s\\n' \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C\" >&5\nprintf %s \"checking whether the compiler supports GNU C... \" >&6; }\nif test ${ac_cv_c_compiler_gnu+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_compiler_gnu=yes\nelse case e in #(\n  e) ac_compiler_gnu=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\nprintf '%s\\n' \"$ac_cv_c_compiler_gnu\" >&6; }\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+y}\nac_save_CFLAGS=$CFLAGS\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\nprintf %s \"checking whether $CC accepts -g... \" >&6; }\nif test ${ac_cv_prog_cc_g+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nelse case e in #(\n  e) CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_g\" >&6; }\nif test $ac_test_CFLAGS; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\nac_prog_cc_stdc=no\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C23 features\" >&5\nprintf %s \"checking for $CC option to enable C23 features... \" >&6; }\nif test ${ac_cv_prog_cc_c23+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c23=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c23_program\n_ACEOF\nfor ac_arg in '' -std=gnu23\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c23=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c23\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c23\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c23\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c23\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c23\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c23\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c23\n  ac_prog_cc_stdc=c23 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features\" >&5\nprintf %s \"checking for $CC option to enable C11 features... \" >&6; }\nif test ${ac_cv_prog_cc_c11+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c11=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c11_program\n_ACEOF\nfor ac_arg in '' -std=gnu11 -std:c11\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c11=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c11\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c11\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c11\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c11\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c11\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11\n  ac_prog_cc_stdc=c11 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features\" >&5\nprintf %s \"checking for $CC option to enable C99 features... \" >&6; }\nif test ${ac_cv_prog_cc_c99+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c99=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c99_program\n_ACEOF\nfor ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c99=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c99\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c99\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c99\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c99\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c99\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99\n  ac_prog_cc_stdc=c99 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features\" >&5\nprintf %s \"checking for $CC option to enable C89 features... \" >&6; }\nif test ${ac_cv_prog_cc_c89+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c89_program\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c89\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c89\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c89\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c89\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89\n  ac_prog_cc_stdc=c89 ;;\nesac\nfi\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for inline\" >&5\nprintf %s \"checking for inline... \" >&6; }\nif test ${ac_cv_c_inline+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_c_inline=no\nfor ac_kw in inline __inline__ __inline; do\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __cplusplus\ntypedef int foo_t;\nstatic $ac_kw foo_t static_foo (void) {return 0; }\n$ac_kw foo_t foo (void) {return 0; }\n#endif\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_c_inline=$ac_kw\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n  test \"$ac_cv_c_inline\" != no && break\ndone\n ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline\" >&5\nprintf '%s\\n' \"$ac_cv_c_inline\" >&6; }\n\ncase $ac_cv_c_inline in\n  inline | yes) ;;\n  *)\n    case $ac_cv_c_inline in\n      no) ac_val=;;\n      *) ac_val=$ac_cv_c_inline;;\n    esac\n    cat >>confdefs.h <<_ACEOF\n#ifndef __cplusplus\n#define inline $ac_val\n#endif\n_ACEOF\n    ;;\nesac\n\n\n#------------------------------------------------------------------------\n# If we're using GCC, see if the compiler understands -pipe.  If so, use it.\n# It makes compiling go faster.  (This is only a performance feature.)\n#------------------------------------------------------------------------\n\nif test -z \"$no_pipe\" && test -n \"$GCC\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe\" >&5\nprintf %s \"checking if the compiler understands -pipe... \" >&6; }\nif test ${tcl_cv_cc_pipe+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -pipe\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_cc_pipe=yes\nelse case e in #(\n  e) tcl_cv_cc_pipe=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\tCFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_pipe\" >&6; }\n    if test $tcl_cv_cc_pipe = yes; then\n\tCFLAGS=\"$CFLAGS -pipe\"\n    fi\nfi\n\n#------------------------------------------------------------------------\n# Embedded configuration information, encoding to use for the values, TIP #59\n#------------------------------------------------------------------------\n\n\n\n# Check whether --with-encoding was given.\nif test ${with_encoding+y}\nthen :\n  withval=$with_encoding; with_tcencoding=${withval}\nfi\n\n\n    if test x\"${with_tcencoding}\" != x ; then\n\ncat >>confdefs.h <<_ACEOF\n#define TCL_CFGVAL_ENCODING \"${with_tcencoding}\"\n_ACEOF\n\n    else\n\nprintf '%s\\n' \"#define TCL_CFGVAL_ENCODING \\\"utf-8\\\"\" >>confdefs.h\n\n    fi\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking how to build libraries\" >&5\nprintf %s \"checking how to build libraries... \" >&6; }\n    # Check whether --enable-shared was given.\nif test ${enable_shared+y}\nthen :\n  enableval=$enable_shared; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=yes ;;\nesac\nfi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: shared\" >&5\nprintf '%s\\n' \"shared\" >&6; }\n\tSHARED_BUILD=1\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: static\" >&5\nprintf '%s\\n' \"static\" >&6; }\n\tSHARED_BUILD=0\n\nprintf '%s\\n' \"#define STATIC_BUILD 1\" >>confdefs.h\n\n    fi\n\n\n\n#--------------------------------------------------------------------\n# The statements below define a collection of compile flags.  This\n# macro depends on the value of SHARED_BUILD, and should be called\n# after SC_ENABLE_SHARED checks the configure switches.\n#--------------------------------------------------------------------\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_RANLIB+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\nprintf '%s\\n' \"$RANLIB\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_RANLIB+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\nprintf '%s\\n' \"$ac_ct_RANLIB\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\nac_header= ac_cache=\nfor ac_item in $ac_header_c_list\ndo\n  if test $ac_cache; then\n    ac_fn_c_check_header_compile \"$LINENO\" $ac_header ac_cv_header_$ac_cache \"$ac_includes_default\"\n    if eval test \\\"x\\$ac_cv_header_$ac_cache\\\" = xyes; then\n      printf '%s\\n' \"#define $ac_item 1\" >> confdefs.h\n    fi\n    ac_header= ac_cache=\n  elif test $ac_header; then\n    ac_cache=$ac_item\n  else\n    ac_header=$ac_item\n  fi\ndone\n\n\n\n\n\n\n\n\nif test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes\nthen :\n\nprintf '%s\\n' \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\n\n    # Step 0.a: Enable 64 bit support?\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested\" >&5\nprintf %s \"checking if 64bit support is requested... \" >&6; }\n    # Check whether --enable-64bit was given.\nif test ${enable_64bit+y}\nthen :\n  enableval=$enable_64bit; do64bit=$enableval\nelse case e in #(\n  e) do64bit=no ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $do64bit\" >&5\nprintf '%s\\n' \"$do64bit\" >&6; }\n\n    # Step 0.b: Enable Solaris 64 bit VIS support?\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested\" >&5\nprintf %s \"checking if 64bit Sparc VIS support is requested... \" >&6; }\n    # Check whether --enable-64bit-vis was given.\nif test ${enable_64bit_vis+y}\nthen :\n  enableval=$enable_64bit_vis; do64bitVIS=$enableval\nelse case e in #(\n  e) do64bitVIS=no ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $do64bitVIS\" >&5\nprintf '%s\\n' \"$do64bitVIS\" >&6; }\n    # Force 64bit on with VIS\n    if test \"$do64bitVIS\" = \"yes\"\nthen :\n  do64bit=yes\nfi\n\n    # Step 0.c: Check if visibility support is available. Do this here so\n    # that platform specific alternatives can be used below if this fails.\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \\\"hidden\\\"\" >&5\nprintf %s \"checking if compiler supports visibility \\\"hidden\\\"... \" >&6; }\nif test ${tcl_cv_cc_visibility_hidden+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Werror\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t    extern __attribute__((__visibility__(\"hidden\"))) void f(void);\n\t    void f(void) {}\nint\nmain (void)\n{\nf();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_cc_visibility_hidden=yes\nelse case e in #(\n  e) tcl_cv_cc_visibility_hidden=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\tCFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_visibility_hidden\" >&6; }\n    if test $tcl_cv_cc_visibility_hidden = yes\nthen :\n\n\nprintf '%s\\n' \"#define MODULE_SCOPE extern __attribute__((__visibility__(\\\"hidden\\\")))\" >>confdefs.h\n\n\nprintf '%s\\n' \"#define HAVE_HIDDEN 1\" >>confdefs.h\n\n\nfi\n\n    # Step 0.d: Disable -rpath support?\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if rpath support is requested\" >&5\nprintf %s \"checking if rpath support is requested... \" >&6; }\n    # Check whether --enable-rpath was given.\nif test ${enable_rpath+y}\nthen :\n  enableval=$enable_rpath; doRpath=$enableval\nelse case e in #(\n  e) doRpath=yes ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $doRpath\" >&5\nprintf '%s\\n' \"$doRpath\" >&6; }\n\n    # Step 1: set the variable \"system\" to hold the name and version number\n    # for the system.\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking system version\" >&5\nprintf %s \"checking system version... \" >&6; }\nif test ${tcl_cv_sys_version+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\tif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t    tcl_cv_sys_version=windows\n\telse\n\t    tcl_cv_sys_version=`uname -s`-`uname -r`\n\t    if test \"$?\" -ne 0 ; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command\" >&5\nprintf '%s\\n' \"$as_me: WARNING: can't find uname command\" >&2;}\n\t\ttcl_cv_sys_version=unknown\n\t    else\n\t\tif test \"`uname -s`\" = \"AIX\" ; then\n\t\t    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`\n\t\tfi\n\t\tif test \"`uname -s`\" = \"NetBSD\" -a -f /etc/debian_version ; then\n\t\t    tcl_cv_sys_version=NetBSD-Debian\n\t\tfi\n\t    fi\n\tfi\n     ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version\" >&5\nprintf '%s\\n' \"$tcl_cv_sys_version\" >&6; }\n    system=$tcl_cv_sys_version\n\n\n    # Step 2: check for existence of -ldl library.  This is needed because\n    # Linux can use either -ldl or -ldld for dynamic loading.\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl\" >&5\nprintf %s \"checking for dlopen in -ldl... \" >&6; }\nif test ${ac_cv_lib_dl_dlopen+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlopen (void);\nint\nmain (void)\n{\nreturn dlopen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_dl_dlopen=yes\nelse case e in #(\n  e) ac_cv_lib_dl_dlopen=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen\" >&5\nprintf '%s\\n' \"$ac_cv_lib_dl_dlopen\" >&6; }\nif test \"x$ac_cv_lib_dl_dlopen\" = xyes\nthen :\n  have_dl=yes\nelse case e in #(\n  e) have_dl=no ;;\nesac\nfi\n\n\n    # Require ranlib early so we can override it in special cases below.\n\n\n\n    # Step 3: set configuration options based on system name and version.\n\n    do64bit_ok=no\n    # default to '{$LIBS}' and set to \"\" on per-platform necessary basis\n    SHLIB_LD_LIBS='${LIBS}'\n    LDFLAGS_ORIG=\"$LDFLAGS\"\n    # When ld needs options to work in 64-bit mode, put them in\n    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]\n    # is disabled by the user. [Bug 1016796]\n    LDFLAGS_ARCH=\"\"\n    UNSHARED_LIB_SUFFIX=\"\"\n    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'\n    ECHO_VERSION='`echo ${VERSION}`'\n    TCL_LIB_VERSIONS_OK=ok\n    CFLAGS_DEBUG=-g\n    if test \"$GCC\" = yes\nthen :\n\n\tCFLAGS_OPTIMIZE=-O2\n\tCFLAGS_WARNING=\"-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith\"\n\tcase \"${CC}\" in\n\t    *++|*++-*)\n\t\t;;\n\t    *)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers\"\n\t\t;;\n\tesac\n\n\nelse case e in #(\n  e)\n\tCFLAGS_OPTIMIZE=-O\n\tCFLAGS_WARNING=\"\"\n     ;;\nesac\nfi\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ar\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ar; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_AR+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$AR\"; then\n  ac_cv_prog_AR=\"$AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AR=\"${ac_tool_prefix}ar\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nAR=$ac_cv_prog_AR\nif test -n \"$AR\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $AR\" >&5\nprintf '%s\\n' \"$AR\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_AR\"; then\n  ac_ct_AR=$AR\n  # Extract the first word of \"ar\", so it can be a program name with args.\nset dummy ar; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_AR+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_AR\"; then\n  ac_cv_prog_ac_ct_AR=\"$ac_ct_AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_AR=\"ar\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_AR=$ac_cv_prog_ac_ct_AR\nif test -n \"$ac_ct_AR\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR\" >&5\nprintf '%s\\n' \"$ac_ct_AR\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_AR\" = x; then\n    AR=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    AR=$ac_ct_AR\n  fi\nelse\n  AR=\"$ac_cv_prog_AR\"\nfi\n\n    STLIB_LD='${AR} cr'\n    LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH\"\n    PLAT_OBJS=\"\"\n    PLAT_SRCS=\"\"\n    LDAIX_SRC=\"\"\n    if test \"x${SHLIB_VERSION}\" = x\nthen :\n  SHLIB_VERSION=\"1.0\"\nfi\n    case $system in\n\tAIX-*)\n\t    if test \"$GCC\" != \"yes\"\nthen :\n\n\t\t# AIX requires the _r compiler when gcc isn't being used\n\t\tcase \"${CC}\" in\n\t\t    *_r|*_r\\ *)\n\t\t\t# ok ...\n\t\t\t;;\n\t\t    *)\n\t\t\t# Make sure only first arg gets _r\n\t\t\tCC=`echo \"$CC\" | sed -e 's/^\\([^ ]*\\)/\\1_r/'`\n\t\t\t;;\n\t\tesac\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads\" >&5\nprintf '%s\\n' \"Using $CC for compiling with threads\" >&6; }\n\nfi\n\t    LIBS=\"$LIBS -lc\"\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    LD_LIBRARY_PATH_VAR=\"LIBPATH\"\n\n\t    # ldAix No longer needed with use of -bexpall/-brtl\n\t    # but some extensions may still reference it\n\t    LDAIX_SRC='$(UNIX_DIR)/ldAix'\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    if test \"$do64bit\" = yes\nthen :\n\n\t\tif test \"$GCC\" = yes\nthen :\n\n\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;}\n\nelse case e in #(\n  e)\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS -q64\"\n\t\t    LDFLAGS_ARCH=\"-q64\"\n\t\t    RANLIB=\"${RANLIB} -X64\"\n\t\t    AR=\"${AR} -X64\"\n\t\t    SHLIB_LD_FLAGS=\"-b64\"\n\t\t ;;\nesac\nfi\n\nfi\n\n\t    if test \"`uname -m`\" = ia64\nthen :\n\n\t\t# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\t# AIX-5 has dl* in libc.so\n\t\tDL_LIBS=\"\"\n\t\tif test \"$GCC\" = yes\nthen :\n\n\t\t    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\nelse case e in #(\n  e)\n\t\t    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'\n\t\t ;;\nesac\nfi\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\nelse case e in #(\n  e)\n\t\tif test \"$GCC\" = yes\nthen :\n\n\t\t    SHLIB_LD='${CC} -shared -Wl,-bexpall'\n\nelse case e in #(\n  e)\n\t\t    SHLIB_LD=\"/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry\"\n\t\t    LDFLAGS=\"$LDFLAGS -brtl\"\n\t\t ;;\nesac\nfi\n\t\tSHLIB_LD=\"${SHLIB_LD} ${SHLIB_LD_FLAGS}\"\n\t\tDL_LIBS=\"-ldl\"\n\t\tCC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t     ;;\nesac\nfi\n\t    ;;\n\tBeOS*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -nostart'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\n\t    #-----------------------------------------------------------\n\t    # Check for inet_ntoa in -lbind, for BeOS (which also needs\n\t    # -lsocket, even if the network functions are in -lnet which\n\t    # is always linked to, for compatibility.\n\t    #-----------------------------------------------------------\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind\" >&5\nprintf %s \"checking for inet_ntoa in -lbind... \" >&6; }\nif test ${ac_cv_lib_bind_inet_ntoa+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lbind  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar inet_ntoa (void);\nint\nmain (void)\n{\nreturn inet_ntoa ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_bind_inet_ntoa=yes\nelse case e in #(\n  e) ac_cv_lib_bind_inet_ntoa=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa\" >&5\nprintf '%s\\n' \"$ac_cv_lib_bind_inet_ntoa\" >&6; }\nif test \"x$ac_cv_lib_bind_inet_ntoa\" = xyes\nthen :\n  LIBS=\"$LIBS -lbind -lsocket\"\nfi\n\n\t    ;;\n\tBSD/OS-2.1*|BSD/OS-3*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"shlicc -r\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tBSD/OS-4.*)\n\t    SHLIB_CFLAGS=\"-export-dynamic -fPIC\"\n\t    SHLIB_LD='${CC} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tCYGWIN_*|MINGW32_*|MSYS_*)\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    SHLIB_LD='${CC} -shared -Wl,--out-implib,$(patsubst cyg%.dll,lib%.dll,$@).a'\n\t    SHLIB_SUFFIX=\".dll\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    PLAT_OBJS='${CYGWIN_OBJS}'\n\t    PLAT_SRCS='${CYGWIN_SRCS}'\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc\" >&5\nprintf %s \"checking for Cygwin version of gcc... \" >&6; }\nif test ${ac_cv_cygwin+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t\t#ifdef __CYGWIN__\n\t\t    #error cygwin\n\t\t#endif\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_cygwin=no\nelse case e in #(\n  e) ac_cv_cygwin=yes ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t     ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin\" >&5\nprintf '%s\\n' \"$ac_cv_cygwin\" >&6; }\n\t    if test \"$ac_cv_cygwin\" = \"no\"; then\n\t\tas_fn_error $? \"${CC} is not a cygwin compiler.\" \"$LINENO\" 5\n\t    fi\n\t    do64bit_ok=yes\n\t    if test \"x${SHARED_BUILD}\" = \"x1\"; then\n\t\techo \"running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32\"\n\t\t# The eval makes quoting arguments work.\n\t\tif cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32; cd ../unix\n\t\tthen :\n\t\telse\n\t\t    { echo \"configure: error: configure failed for ../win\" 1>&2; exit 1; }\n\t\tfi\n\t    fi\n\t    ;;\n\tdgux*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tHaiku*)\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-lroot\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork\" >&5\nprintf %s \"checking for inet_ntoa in -lnetwork... \" >&6; }\nif test ${ac_cv_lib_network_inet_ntoa+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lnetwork  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar inet_ntoa (void);\nint\nmain (void)\n{\nreturn inet_ntoa ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_network_inet_ntoa=yes\nelse case e in #(\n  e) ac_cv_lib_network_inet_ntoa=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa\" >&5\nprintf '%s\\n' \"$ac_cv_lib_network_inet_ntoa\" >&6; }\nif test \"x$ac_cv_lib_network_inet_ntoa\" = xyes\nthen :\n  LIBS=\"$LIBS -lnetwork\"\nfi\n\n\t    ;;\n\tHP-UX-*.11.*)\n\t    # Use updated header definitions where possible\n\nprintf '%s\\n' \"#define _XOPEN_SOURCE_EXTENDED 1\" >>confdefs.h\n\n\nprintf '%s\\n' \"#define _XOPEN_SOURCE 1\" >>confdefs.h\n\n\t    LIBS=\"$LIBS -lxnet\"               # Use the XOPEN network library\n\n\t    if test \"`uname -m`\" = ia64\nthen :\n\n\t\tSHLIB_SUFFIX=\".so\"\n\nelse case e in #(\n  e)\n\t\tSHLIB_SUFFIX=\".sl\"\n\t     ;;\nesac\nfi\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld\" >&5\nprintf %s \"checking for shl_load in -ldld... \" >&6; }\nif test ${ac_cv_lib_dld_shl_load+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar shl_load (void);\nint\nmain (void)\n{\nreturn shl_load ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_dld_shl_load=yes\nelse case e in #(\n  e) ac_cv_lib_dld_shl_load=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load\" >&5\nprintf '%s\\n' \"$ac_cv_lib_dld_shl_load\" >&6; }\nif test \"x$ac_cv_lib_dld_shl_load\" = xyes\nthen :\n  tcl_ok=yes\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\n\n\t    if test \"$tcl_ok\" = yes\nthen :\n\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\nfi\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\nelse case e in #(\n  e)\n\t\tCFLAGS=\"$CFLAGS -z\"\n\t     ;;\nesac\nfi\n\n\t    # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc\n\t    #CFLAGS=\"$CFLAGS +DAportable\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    if test \"$do64bit\" = \"yes\"\nthen :\n\n\t\tif test \"$GCC\" = yes\nthen :\n\n\t\t    case `${CC} -dumpmachine` in\n\t\t\thppa64*)\n\t\t\t    # 64-bit gcc in use.  Fix flags for GNU ld.\n\t\t\t    do64bit_ok=yes\n\t\t\t    SHLIB_LD='${CC} -shared'\n\t\t\t    if test $doRpath = yes\nthen :\n\n\t\t\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\nfi\n\t\t\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\t\t    ;;\n\t\t\t*)\n\t\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;}\n\t\t\t    ;;\n\t\t    esac\n\nelse case e in #(\n  e)\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS +DD64\"\n\t\t    LDFLAGS_ARCH=\"+DD64\"\n\t\t ;;\nesac\nfi\n\nfi ;;\n\tHP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)\n\t    SHLIB_SUFFIX=\".sl\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld\" >&5\nprintf %s \"checking for shl_load in -ldld... \" >&6; }\nif test ${ac_cv_lib_dld_shl_load+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar shl_load (void);\nint\nmain (void)\n{\nreturn shl_load ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_dld_shl_load=yes\nelse case e in #(\n  e) ac_cv_lib_dld_shl_load=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load\" >&5\nprintf '%s\\n' \"$ac_cv_lib_dld_shl_load\" >&6; }\nif test \"x$ac_cv_lib_dld_shl_load\" = xyes\nthen :\n  tcl_ok=yes\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\n\n\t    if test \"$tcl_ok\" = yes\nthen :\n\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS=\"\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\nfi ;;\n\tIRIX-5.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    case \" $LIBOBJS \" in\n  *\" mkstemp.$ac_objext \"* ) ;;\n  *) LIBOBJS=\"$LIBOBJS mkstemp.$ac_objext\"\n ;;\nesac\n\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    ;;\n\tIRIX-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    case \" $LIBOBJS \" in\n  *\" mkstemp.$ac_objext \"* ) ;;\n  *) LIBOBJS=\"$LIBOBJS mkstemp.$ac_objext\"\n ;;\nesac\n\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tCFLAGS=\"$CFLAGS -mabi=n32\"\n\t\tLDFLAGS=\"$LDFLAGS -mabi=n32\"\n\nelse case e in #(\n  e)\n\t\tcase $system in\n\t\t    IRIX-6.3)\n\t\t\t# Use to build 6.2 compatible binaries on 6.3.\n\t\t\tCFLAGS=\"$CFLAGS -n32 -D_OLD_TERMIOS\"\n\t\t\t;;\n\t\t    *)\n\t\t\tCFLAGS=\"$CFLAGS -n32\"\n\t\t\t;;\n\t\tesac\n\t\tLDFLAGS=\"$LDFLAGS -n32\"\n\t     ;;\nesac\nfi\n\t    ;;\n\tIRIX64-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    case \" $LIBOBJS \" in\n  *\" mkstemp.$ac_objext \"* ) ;;\n  *) LIBOBJS=\"$LIBOBJS mkstemp.$ac_objext\"\n ;;\nesac\n\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\n\t    if test \"$do64bit\" = yes\nthen :\n\n\t\tif test \"$GCC\" = yes\nthen :\n\n\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported by gcc\" >&2;}\n\nelse case e in #(\n  e)\n\t\t    do64bit_ok=yes\n\t\t    SHLIB_LD=\"ld -64 -shared -rdata_shared\"\n\t\t    CFLAGS=\"$CFLAGS -64\"\n\t\t    LDFLAGS_ARCH=\"-64\"\n\t\t ;;\nesac\nfi\n\nfi\n\t    ;;\n\tLinux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*)\n\t    SHLIB_CFLAGS=\"-fPIC -fno-common\"\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings\n\t    # when you inline the string and math operations.  Turn this off to\n\t    # get rid of the warnings.\n\t    #CFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES\"\n\n\t    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\n\t    case $system in\n\t    DragonFly-*|FreeBSD-*)\n\t\t# The -pthread needs to go in the LDFLAGS, not LIBS\n\t\tLIBS=`echo $LIBS | sed s/-pthread//`\n\t\tCFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n\t\tLDFLAGS=\"$LDFLAGS $PTHREAD_LIBS\"\n\t    ;;\n\t    esac\n\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    if test \"`uname -m`\" = \"alpha\"\nthen :\n  CFLAGS=\"$CFLAGS -mieee\"\nfi\n\t    if test $do64bit = yes\nthen :\n\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag\" >&5\nprintf %s \"checking if compiler accepts -m64 flag... \" >&6; }\nif test ${tcl_cv_cc_m64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t    hold_cflags=$CFLAGS\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_cc_m64=yes\nelse case e in #(\n  e) tcl_cv_cc_m64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_m64\" >&6; }\n\t\tif test $tcl_cv_cc_m64 = yes\nthen :\n\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    do64bit_ok=yes\n\nfi\n\nfi\n\n\t    # The combo of gcc + glibc has a bug related to inlining of\n\t    # functions like strtol()/strtoul(). The -fno-builtin flag should address\n\t    # this problem but it does not work. The -fno-inline flag is kind\n\t    # of overkill but it works. Disable inlining only when one of the\n\t    # files in compat/*.c is being linked in.\n\n\t    if test x\"${USE_COMPAT}\" != x\nthen :\n  CFLAGS=\"$CFLAGS -fno-inline\"\nfi\n\t    ;;\n\tLynx*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    CFLAGS_OPTIMIZE=-02\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-mshared -ldl\"\n\t    LD_FLAGS=\"-Wl,--export-dynamic\"\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\nfi\n\t    ;;\n\tOpenBSD-*)\n\t    arch=`arch -s`\n\t    case \"$arch\" in\n\t    alpha|sparc64)\n\t\tSHLIB_CFLAGS=\"-fPIC\"\n\t\t;;\n\t    *)\n\t\tSHLIB_CFLAGS=\"-fpic\"\n\t\t;;\n\t    esac\n\t    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'\n\t    LDFLAGS=\"-Wl,-export-dynamic\"\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    # On OpenBSD:\tCompile with -pthread\n\t    #\t\tDon't link with -lpthread\n\t    LIBS=`echo $LIBS | sed s/-lpthread//`\n\t    CFLAGS=\"$CFLAGS -pthread\"\n\t    # OpenBSD doesn't do version numbers with dots.\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tNetBSD-*)\n\t    # NetBSD has ELF and can use 'cc -shared' to build shared libs\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\nfi\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    # The -pthread needs to go in the CFLAGS, not LIBS\n\t    LIBS=`echo $LIBS | sed s/-pthread//`\n\t    CFLAGS=\"$CFLAGS -pthread\"\n\t    LDFLAGS=\"$LDFLAGS -pthread\"\n\t    ;;\n\tDarwin-*)\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    # To avoid discrepancies between what headers configure sees during\n\t    # preprocessing tests and compiling tests, move any -isysroot and\n\t    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:\n\t    CPPFLAGS=\"${CPPFLAGS} `echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif ($i~/^(isysroot|mmacosx-version-min)/) print \"-\"$i}'`\"\n\t    CFLAGS=\"`echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif (!($i~/^(isysroot|mmacosx-version-min)/)) print \"-\"$i}'`\"\n\t    if test $do64bit = yes\nthen :\n\n\t\tcase `arch` in\n\t\t    ppc)\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag\" >&5\nprintf %s \"checking if compiler accepts -arch ppc64 flag... \" >&6; }\nif test ${tcl_cv_cc_arch_ppc64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_cc_arch_ppc64=yes\nelse case e in #(\n  e) tcl_cv_cc_arch_ppc64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_arch_ppc64\" >&6; }\n\t\t\tif test $tcl_cv_cc_arch_ppc64 = yes\nthen :\n\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    do64bit_ok=yes\n\nfi;;\n\t\t    i386|x86_64)\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag\" >&5\nprintf %s \"checking if compiler accepts -arch x86_64 flag... \" >&6; }\nif test ${tcl_cv_cc_arch_x86_64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_cc_arch_x86_64=yes\nelse case e in #(\n  e) tcl_cv_cc_arch_x86_64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_arch_x86_64\" >&6; }\n\t\t\tif test $tcl_cv_cc_arch_x86_64 = yes\nthen :\n\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    do64bit_ok=yes\n\nfi;;\n\t\t    arm64)\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch arm64 flag\" >&5\nprintf %s \"checking if compiler accepts -arch arm64 flag... \" >&6; }\nif test ${tcl_cv_cc_arch_arm64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch arm64\"\n\t\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_cc_arch_arm64=yes\nelse case e in #(\n  e) tcl_cv_cc_arch_arm64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_arm64\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_arch_arm64\" >&6; }\n\t\t\tif test $tcl_cv_cc_arch_arm64 = yes\nthen :\n\n\t\t\t    CFLAGS=\"$CFLAGS -arch arm64\"\n\t\t\t    do64bit_ok=yes\n\nfi;;\n\t\t    *)\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \\`arch\\`\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Don't know how enable 64-bit on architecture \\`arch\\`\" >&2;};;\n\t\tesac\n\nelse case e in #(\n  e)\n\t\t# Check for combined 32-bit and 64-bit fat build\n\t\tif echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc64|x86_64|arm64) ' \\\n\t\t    && echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc|i386) '\nthen :\n\n\t\t    fat_32_64=yes\nfi\n\t     ;;\nesac\nfi\n\t    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'\n\t    SHLIB_SUFFIX=\".dylib\"\n\t    DL_OBJS=\"tclLoadDyld.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -headerpad_max_install_names\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag\" >&5\nprintf %s \"checking if ld accepts -search_paths_first flag... \" >&6; }\nif test ${tcl_cv_ld_search_paths_first+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\nint i;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_ld_search_paths_first=yes\nelse case e in #(\n  e) tcl_cv_ld_search_paths_first=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\tLDFLAGS=$hold_ldflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first\" >&5\nprintf '%s\\n' \"$tcl_cv_ld_search_paths_first\" >&6; }\n\t    if test $tcl_cv_ld_search_paths_first = yes\nthen :\n\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\nfi\n\t    if test \"$tcl_cv_cc_visibility_hidden\" != yes\nthen :\n\n\nprintf '%s\\n' \"#define MODULE_SCOPE __private_extern__\" >>confdefs.h\n\n\t\ttcl_cv_cc_visibility_hidden=yes\n\nfi\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    LD_LIBRARY_PATH_VAR=\"DYLD_FALLBACK_LIBRARY_PATH\"\n\nprintf '%s\\n' \"#define MAC_OSX_TCL 1\" >>confdefs.h\n\n\t    PLAT_OBJS='${MAC_OSX_OBJS}'\n\t    PLAT_SRCS='${MAC_OSX_SRCS}'\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation\" >&5\nprintf %s \"checking whether to use CoreFoundation... \" >&6; }\n\t    # Check whether --enable-corefoundation was given.\nif test ${enable_corefoundation+y}\nthen :\n  enableval=$enable_corefoundation; tcl_corefoundation=$enableval\nelse case e in #(\n  e) tcl_corefoundation=yes ;;\nesac\nfi\n\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation\" >&5\nprintf '%s\\n' \"$tcl_corefoundation\" >&6; }\n\t    if test $tcl_corefoundation = yes\nthen :\n\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework\" >&5\nprintf %s \"checking for CoreFoundation.framework... \" >&6; }\nif test ${tcl_cv_lib_corefoundation+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t    hold_libs=$LIBS\n\t\t    if test \"$fat_32_64\" = yes\nthen :\n\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    # On Tiger there is no 64-bit CF, so remove 64-bit\n\t\t\t    # archs from CFLAGS et al. while testing for\n\t\t\t    # presence of CF. 64-bit CF is disabled in\n\t\t\t    # tclUnixPort.h if necessary.\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc64 / /g\" -e \"s/-arch x86_64 / /g\"`\"'\n\t\t\tdone\nfi\n\t\t    LIBS=\"$LIBS -framework CoreFoundation\"\n\t\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <CoreFoundation/CoreFoundation.h>\nint\nmain (void)\n{\nCFBundleRef b = CFBundleGetMainBundle();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_lib_corefoundation=yes\nelse case e in #(\n  e) tcl_cv_lib_corefoundation=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t    if test \"$fat_32_64\" = yes\nthen :\n\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone\nfi\n\t\t    LIBS=$hold_libs ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation\" >&5\nprintf '%s\\n' \"$tcl_cv_lib_corefoundation\" >&6; }\n\t\tif test $tcl_cv_lib_corefoundation = yes\nthen :\n\n\t\t    LIBS=\"$LIBS -framework CoreFoundation\"\n\nprintf '%s\\n' \"#define HAVE_COREFOUNDATION 1\" >>confdefs.h\n\n\nelse case e in #(\n  e) tcl_corefoundation=no ;;\nesac\nfi\n\t\tif test \"$fat_32_64\" = yes -a $tcl_corefoundation = yes\nthen :\n\n\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation\" >&5\nprintf %s \"checking for 64-bit CoreFoundation... \" >&6; }\nif test ${tcl_cv_lib_corefoundation_64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc / /g\" -e \"s/-arch i386 / /g\"`\"'\n\t\t\tdone\n\t\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <CoreFoundation/CoreFoundation.h>\nint\nmain (void)\n{\nCFBundleRef b = CFBundleGetMainBundle();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_lib_corefoundation_64=yes\nelse case e in #(\n  e) tcl_cv_lib_corefoundation_64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64\" >&5\nprintf '%s\\n' \"$tcl_cv_lib_corefoundation_64\" >&6; }\n\t\t    if test $tcl_cv_lib_corefoundation_64 = no\nthen :\n\n\nprintf '%s\\n' \"#define NO_COREFOUNDATION_64 1\" >>confdefs.h\n\n\t\t\tLDFLAGS=\"$LDFLAGS -Wl,-no_arch_warnings\"\n\nfi\n\nfi\n\nfi\n\t    ;;\n\tOS/390-*)\n\t    SHLIB_LD_LIBS=\"\"\n\t    CFLAGS_OPTIMIZE=\"\"\t\t# Optimizer is buggy\n\nprintf '%s\\n' \"#define _OE_SOCKETS 1\" >>confdefs.h\n\n\t    ;;\n\tOSF1-V*)\n\t    # Digital OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    if test \"$SHARED_BUILD\" = 1\nthen :\n\n\t\tSHLIB_LD='${CC} -shared'\n\nelse case e in #(\n  e)\n\t\tSHLIB_LD='${CC} -non_shared'\n\t     ;;\nesac\nfi\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    if test $doRpath = yes\nthen :\n\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'\nfi\n\t    if test \"$GCC\" = yes\nthen :\n  CFLAGS=\"$CFLAGS -mieee\"\nelse case e in #(\n  e)\n\t\tCFLAGS=\"$CFLAGS -DHAVE_TZSET -std1 -ieee\" ;;\nesac\nfi\n\t    # see pthread_intro(3) for pthread support on osf1, k.furukawa\n\t    CFLAGS=\"$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE\"\n\t    CFLAGS=\"$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64\"\n\t    LIBS=`echo $LIBS | sed s/-lpthreads//`\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tLIBS=\"$LIBS -lpthread -lmach -lexc\"\n\nelse case e in #(\n  e)\n\t\tCFLAGS=\"$CFLAGS -pthread\"\n\t\tLDFLAGS=\"$LDFLAGS -pthread\"\n\t     ;;\nesac\nfi\n\t    ;;\n\tQNX-6*)\n\t    # QNX RTP\n\t    # This may work for all QNX, but it was only reported for v6.\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    # dlopen is in -lc on QNX\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSCO_SV-3.2*)\n\t    # Note, dlopen is available only on SCO 3.2.5 and greater. However,\n\t    # this test works, since \"uname -s\" was non-standard in 3.2.4 and\n\t    # below.\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tSHLIB_CFLAGS=\"-fPIC -melf\"\n\t\tLDFLAGS=\"$LDFLAGS -melf -Wl,-Bexport\"\n\nelse case e in #(\n  e)\n\t\tSHLIB_CFLAGS=\"-Kpic -belf\"\n\t\tLDFLAGS=\"$LDFLAGS -belf -Wl,-Bexport\"\n\t     ;;\nesac\nfi\n\t    SHLIB_LD=\"ld -G\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSunOS-5.[0-6])\n\t    # Careful to not let 5.10+ fall into this case\n\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\nprintf '%s\\n' \"#define _REENTRANT 1\" >>confdefs.h\n\n\nprintf '%s\\n' \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\nelse case e in #(\n  e)\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\tCC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t     ;;\nesac\nfi\n\t    ;;\n\tSunOS-5*)\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\nprintf '%s\\n' \"#define _REENTRANT 1\" >>confdefs.h\n\n\nprintf '%s\\n' \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    if test \"$do64bit\" = yes\nthen :\n\n\t\tarch=`isainfo`\n\t\tif test \"$arch\" = \"sparcv9 sparc\"\nthen :\n\n\t\t    if test \"$GCC\" = yes\nthen :\n\n\t\t\tif test \"`${CC} -dumpversion | awk -F. '{print $1}'`\" -lt 3\nthen :\n\n\t\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system\" >&2;}\n\nelse case e in #(\n  e)\n\t\t\t    do64bit_ok=yes\n\t\t\t    CFLAGS=\"$CFLAGS -m64 -mcpu=v9\"\n\t\t\t    LDFLAGS=\"$LDFLAGS -m64 -mcpu=v9\"\n\t\t\t    SHLIB_CFLAGS=\"-fPIC\"\n\t\t\t ;;\nesac\nfi\n\nelse case e in #(\n  e)\n\t\t\tdo64bit_ok=yes\n\t\t\tif test \"$do64bitVIS\" = yes\nthen :\n\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9a\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9a\"\n\nelse case e in #(\n  e)\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9\"\n\t\t\t ;;\nesac\nfi\n\t\t\t# Solaris 64 uses this as well\n\t\t\t#LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH_64\"\n\t\t     ;;\nesac\nfi\n\nelse case e in #(\n  e) if test \"$arch\" = \"amd64 i386\"\nthen :\n\n\t\t    if test \"$GCC\" = yes\nthen :\n\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)\n\t\t\t\tdo64bit_ok=yes\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported with GCC on $system\" >&2;};;\n\t\t\tesac\n\nelse case e in #(\n  e)\n\t\t\tdo64bit_ok=yes\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tCFLAGS=\"$CFLAGS -xarch=amd64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -xarch=amd64\";;\n\t\t\tesac\n\t\t     ;;\nesac\nfi\n\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit mode not supported for $arch\" >&2;} ;;\nesac\nfi ;;\nesac\nfi\n\nfi\n\n\t    #--------------------------------------------------------------------\n\t    # On Solaris 5.x i386 with the sunpro compiler we need to link\n\t    # with sunmath to get floating point rounding control\n\t    #--------------------------------------------------------------------\n\t    if test \"$GCC\" = yes\nthen :\n  use_sunmath=no\nelse case e in #(\n  e)\n\t\tarch=`isainfo`\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control\" >&5\nprintf %s \"checking whether to use -lsunmath for fp rounding control... \" >&6; }\n\t\tif test \"$arch\" = \"amd64 i386\" -o \"$arch\" = \"i386\"\nthen :\n\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n\t\t\tMATH_LIBS=\"-lsunmath $MATH_LIBS\"\n\t\t\tac_fn_c_check_header_compile \"$LINENO\" \"sunmath.h\" \"ac_cv_header_sunmath_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_sunmath_h\" = xyes\nthen :\n\nfi\n\n\t\t\tuse_sunmath=yes\n\nelse case e in #(\n  e)\n\t\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\t\t\tuse_sunmath=no\n\t\t ;;\nesac\nfi\n\t     ;;\nesac\nfi\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    if test \"$GCC\" = yes\nthen :\n\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tif test \"$do64bit_ok\" = yes\nthen :\n\n\t\t    if test \"$arch\" = \"sparcv9 sparc\"\nthen :\n\n\t\t\t# We need to specify -static-libgcc or we need to\n\t\t\t# add the path to the sparv9 libgcc.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -mcpu=v9 -static-libgcc\"\n\t\t\t# for finding sparcv9 libgcc, get the regular libgcc\n\t\t\t# path, remove so name and append 'sparcv9'\n\t\t\t#v9gcclibdir=\"`gcc -print-file-name=libgcc_s.so` | ...\"\n\t\t\t#CC_SEARCH_FLAGS=\"${CC_SEARCH_FLAGS},-R,$v9gcclibdir\"\n\nelse case e in #(\n  e) if test \"$arch\" = \"amd64 i386\"\nthen :\n\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -static-libgcc\"\n\nfi ;;\nesac\nfi\n\nfi\n\nelse case e in #(\n  e)\n\t\tif test \"$use_sunmath\" = yes\nthen :\n  textmode=textoff\nelse case e in #(\n  e) textmode=text ;;\nesac\nfi\n\t\tcase $system in\n\t\t    SunOS-5.[1-9][0-9]*|SunOS-5.[7-9])\n\t\t\tSHLIB_LD=\"\\${CC} -G -z $textmode \\${LDFLAGS}\";;\n\t\t    *)\n\t\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z $textmode\";;\n\t\tesac\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t     ;;\nesac\nfi\n\t    ;;\n\tUNIX_SV* | UnixWare-5*)\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers\n\t    # that don't grok the -Bexport option.  Test that it does.\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag\" >&5\nprintf %s \"checking for ld accepts -Bexport flag... \" >&6; }\nif test ${tcl_cv_ld_Bexport+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\nint i;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_ld_Bexport=yes\nelse case e in #(\n  e) tcl_cv_ld_Bexport=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t\tLDFLAGS=$hold_ldflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport\" >&5\nprintf '%s\\n' \"$tcl_cv_ld_Bexport\" >&6; }\n\t    if test $tcl_cv_ld_Bexport = yes\nthen :\n\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\nfi\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n    esac\n\n    if test \"$do64bit\" = yes -a \"$do64bit_ok\" = no\nthen :\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform\" >&5\nprintf '%s\\n' \"$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform\" >&2;}\n\nfi\n\n    if test \"$do64bit\" = yes -a \"$do64bit_ok\" = yes\nthen :\n\n\nprintf '%s\\n' \"#define TCL_CFG_DO64BIT 1\" >>confdefs.h\n\n\nfi\n\n\n\n    # Step 4: disable dynamic loading if requested via a command-line switch.\n\n    # Check whether --enable-load was given.\nif test ${enable_load+y}\nthen :\n  enableval=$enable_load; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=yes ;;\nesac\nfi\n\n    if test \"$tcl_ok\" = no\nthen :\n  DL_OBJS=\"\"\nfi\n\n    if test \"x$DL_OBJS\" != x\nthen :\n  BUILD_DLTEST=\"\\$(DLTEST_TARGETS)\"\nelse case e in #(\n  e)\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system.\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system.\" >&2;}\n\tSHLIB_CFLAGS=\"\"\n\tSHLIB_LD=\"\"\n\tSHLIB_SUFFIX=\"\"\n\tDL_OBJS=\"tclLoadNone.o\"\n\tDL_LIBS=\"\"\n\tLDFLAGS=\"$LDFLAGS_ORIG\"\n\tCC_SEARCH_FLAGS=\"\"\n\tLD_SEARCH_FLAGS=\"\"\n\tBUILD_DLTEST=\"\"\n     ;;\nesac\nfi\n    LDFLAGS=\"$LDFLAGS $LDFLAGS_ARCH\"\n\n    # If we're running gcc, then change the C flags for compiling shared\n    # libraries to the right flags for gcc, instead of those for the\n    # standard manufacturer compiler.\n\n    if test \"$DL_OBJS\" != \"tclLoadNone.o\" -a \"$GCC\" = yes\nthen :\n\n\tcase $system in\n\t    AIX-*) ;;\n\t    BSD/OS*) ;;\n\t    CYGWIN_*|MINGW32_*|MSYS_*) ;;\n\t    HP-UX*) ;;\n\t    Darwin-*) ;;\n\t    IRIX*) ;;\n\t    Linux*|GNU*) ;;\n\t    NetBSD-*|OpenBSD-*) ;;\n\t    OSF1-*) ;;\n\t    SCO_SV-3.2*) ;;\n\t    *) SHLIB_CFLAGS=\"-fPIC\" ;;\n\tesac\nfi\n\n    if test \"$tcl_cv_cc_visibility_hidden\" != yes\nthen :\n\n\nprintf '%s\\n' \"#define MODULE_SCOPE extern\" >>confdefs.h\n\n\nfi\n\n    if test \"$SHARED_LIB_SUFFIX\" = \"\"\nthen :\n\n\tSHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'\nfi\n    if test \"$UNSHARED_LIB_SUFFIX\" = \"\"\nthen :\n\n\tUNSHARED_LIB_SUFFIX='${VERSION}.a'\nfi\n    DLL_INSTALL_DIR=\"\\$(LIB_INSTALL_DIR)\"\n\n    if test \"${SHARED_BUILD}\" = 1 -a \"${SHLIB_SUFFIX}\" != \"\"\nthen :\n\n\tLIB_SUFFIX=${SHARED_LIB_SUFFIX}\n\tMAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'\n\tif test \"${SHLIB_SUFFIX}\" = \".dll\"\nthen :\n\n\t    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(BIN_INSTALL_DIR)/$(LIB_FILE)\"'\n\t    DLL_INSTALL_DIR=\"\\$(BIN_INSTALL_DIR)\"\n\nelse case e in #(\n  e)\n\t    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(LIB_INSTALL_DIR)/$(LIB_FILE)\"'\n\t ;;\nesac\nfi\n\nelse case e in #(\n  e)\n\tLIB_SUFFIX=${UNSHARED_LIB_SUFFIX}\n\n\tif test \"$RANLIB\" = \"\"\nthen :\n\n\t    MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'\n\nelse case e in #(\n  e)\n\t    MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'\n\t ;;\nesac\nfi\n\tINSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(LIB_INSTALL_DIR)/$(LIB_FILE)\"'\n     ;;\nesac\nfi\n\n    # Stub lib does not depend on shared/static configuration\n    if test \"$RANLIB\" = \"\"\nthen :\n\n\tMAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'\n\nelse case e in #(\n  e)\n\tMAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'\n     ;;\nesac\nfi\n    INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) \"$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)\"'\n\n    # Define TCL_LIBS now that we know what DL_LIBS is.\n    # The trick here is that we don't want to change the value of TCL_LIBS if\n    # it is already set when tclConfig.sh had been loaded by Tk.\n    if test \"x${TCL_LIBS}\" = x\nthen :\n\n\tTCL_LIBS=\"${DL_LIBS} ${LIBS} ${MATH_LIBS}\"\nfi\n\n\n    # See if the compiler supports casting to a union type.\n    # This is used to stop gcc from printing a compiler\n    # warning when initializing a union member.\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for cast to union support\" >&5\nprintf %s \"checking for cast to union support... \" >&6; }\nif test ${tcl_cv_cast_to_union+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n\t\tunion foo { int i; double d; };\n\t\tunion foo f = (union foo) (int) 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_cast_to_union=yes\nelse case e in #(\n  e) tcl_cv_cast_to_union=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n     ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union\" >&5\nprintf '%s\\n' \"$tcl_cv_cast_to_union\" >&6; }\n    if test \"$tcl_cv_cast_to_union\" = \"yes\"; then\n\nprintf '%s\\n' \"#define HAVE_CAST_TO_UNION 1\" >>confdefs.h\n\n    fi\n    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -fno-lto\"\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for working -fno-lto\" >&5\nprintf %s \"checking for working -fno-lto... \" >&6; }\nif test ${ac_cv_nolto+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_nolto=yes\nelse case e in #(\n  e) ac_cv_nolto=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n     ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_nolto\" >&5\nprintf '%s\\n' \"$ac_cv_nolto\" >&6; }\n    CFLAGS=$hold_cflags\n    if test \"$ac_cv_nolto\" = \"yes\" ; then\n\tCFLAGS_NOLTO=\"-fno-lto\"\n    else\n\tCFLAGS_NOLTO=\"\"\n    fi\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if the compiler understands -finput-charset\" >&5\nprintf %s \"checking if the compiler understands -finput-charset... \" >&6; }\nif test ${tcl_cv_cc_input_charset+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_cc_input_charset=yes\nelse case e in #(\n  e) tcl_cv_cc_input_charset=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\tCFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_input_charset\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_input_charset\" >&6; }\n    if test $tcl_cv_cc_input_charset = yes; then\n\tCFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n    fi\n\n    # Check for vfork, posix_spawnp() and friends unconditionally\n    ac_fn_c_check_func \"$LINENO\" \"vfork\" \"ac_cv_func_vfork\"\nif test \"x$ac_cv_func_vfork\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_VFORK 1\" >>confdefs.h\n\nfi\nac_fn_c_check_func \"$LINENO\" \"posix_spawnp\" \"ac_cv_func_posix_spawnp\"\nif test \"x$ac_cv_func_posix_spawnp\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_POSIX_SPAWNP 1\" >>confdefs.h\n\nfi\nac_fn_c_check_func \"$LINENO\" \"posix_spawn_file_actions_adddup2\" \"ac_cv_func_posix_spawn_file_actions_adddup2\"\nif test \"x$ac_cv_func_posix_spawn_file_actions_adddup2\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 1\" >>confdefs.h\n\nfi\nac_fn_c_check_func \"$LINENO\" \"posix_spawnattr_setflags\" \"ac_cv_func_posix_spawnattr_setflags\"\nif test \"x$ac_cv_func_posix_spawnattr_setflags\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_POSIX_SPAWNATTR_SETFLAGS 1\" >>confdefs.h\n\nfi\n\n\n    # FIXME: This subst was left in only because the TCL_DL_LIBS\n    # entry in tclConfig.sh uses it. It is not clear why someone\n    # would use TCL_DL_LIBS instead of TCL_LIBS.\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\ncat >>confdefs.h <<_ACEOF\n#define TCL_SHLIB_EXT \"${SHLIB_SUFFIX}\"\n_ACEOF\n\n\n\n\n\n\n\n\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for build with symbols\" >&5\nprintf %s \"checking for build with symbols... \" >&6; }\n    # Check whether --enable-symbols was given.\nif test ${enable_symbols+y}\nthen :\n  enableval=$enable_symbols; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\n\n# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'\n\nprintf '%s\\n' \"#define NDEBUG 1\" >>confdefs.h\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\nprintf '%s\\n' \"#define TCL_CFG_OPTIMIZED 1\" >>confdefs.h\n\n    else\n\tCFLAGS_DEFAULT='$(CFLAGS_DEBUG)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)\" >&5\nprintf '%s\\n' \"yes (standard debugging)\" >&6; }\n\tfi\n    fi\n\n\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\nprintf '%s\\n' \"#define TCL_MEM_DEBUG 1\" >>confdefs.h\n\n    fi\n\n\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging\" >&5\nprintf '%s\\n' \"enabled symbols mem debugging\" >&6; }\n\telse\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging\" >&5\nprintf '%s\\n' \"enabled $tcl_ok debugging\" >&6; }\n\tfi\n    fi\n\n\n#--------------------------------------------------------------------\n#\tDetect what compiler flags to set for 64-bit support.\n#--------------------------------------------------------------------\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for required early compiler flags\" >&5\nprintf %s \"checking for required early compiler flags... \" >&6; }\n    tcl_flags=\"\"\n\n    if test ${tcl_cv_flag__isoc99_source+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain (void)\n{\nchar *p = (char *)strtoll; char *q = (char *)strtoull;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__isoc99_source=no\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _ISOC99_SOURCE 1\n#include <stdlib.h>\nint\nmain (void)\n{\nchar *p = (char *)strtoll; char *q = (char *)strtoull;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__isoc99_source=yes\nelse case e in #(\n  e) tcl_cv_flag__isoc99_source=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n    if test \"x${tcl_cv_flag__isoc99_source}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define _ISOC99_SOURCE 1\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _ISOC99_SOURCE\"\n    fi\n\n\n    if test ${tcl_cv_flag__file_offset_bits+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/stat.h>\nint\nmain (void)\n{\nswitch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__file_offset_bits=no\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _FILE_OFFSET_BITS 64\n#include <sys/stat.h>\nint\nmain (void)\n{\nswitch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__file_offset_bits=yes\nelse case e in #(\n  e) tcl_cv_flag__file_offset_bits=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n    if test \"x${tcl_cv_flag__file_offset_bits}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define _FILE_OFFSET_BITS 64\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _FILE_OFFSET_BITS\"\n    fi\n\n\n    if test ${tcl_cv_flag__largefile64_source+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/stat.h>\nint\nmain (void)\n{\nstruct stat64 buf; int i = stat64(\"/\", &buf);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__largefile64_source=no\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _LARGEFILE64_SOURCE 1\n#include <sys/stat.h>\nint\nmain (void)\n{\nstruct stat64 buf; int i = stat64(\"/\", &buf);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_flag__largefile64_source=yes\nelse case e in #(\n  e) tcl_cv_flag__largefile64_source=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n    if test \"x${tcl_cv_flag__largefile64_source}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define _LARGEFILE64_SOURCE 1\" >>confdefs.h\n\n\ttcl_flags=\"$tcl_flags _LARGEFILE64_SOURCE\"\n    fi\n\n    if test \"x${tcl_flags}\" = \"x\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none\" >&5\nprintf '%s\\n' \"none\" >&6; }\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}\" >&5\nprintf '%s\\n' \"${tcl_flags}\" >&6; }\n    fi\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if 'long' and 'long long' have the same size (64-bit)?\" >&5\nprintf %s \"checking if 'long' and 'long long' have the same size (64-bit)?... \" >&6; }\n    if test ${tcl_cv_type_64bit+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\ttcl_cv_type_64bit=none\n\t# See if we could use long anyway  Note that we substitute in the\n\t# type that is our current guess for a 64-bit type inside this check\n\t# program, so it should be modified only carefully...\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\nswitch (0) {\n\t    case 1: case (sizeof(long long)==sizeof(long)): ;\n\t}\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_type_64bit=\"long long\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n    if test \"${tcl_cv_type_64bit}\" = none ; then\n\nprintf '%s\\n' \"#define TCL_WIDE_INT_IS_LONG 1\" >>confdefs.h\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\t# Now check for auxiliary declarations\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t\" >&5\nprintf %s \"checking for 64-bit time_t... \" >&6; }\nif test ${tcl_cv_time_t_64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\nint\nmain (void)\n{\nswitch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_time_t_64=yes\nelse case e in #(\n  e) tcl_cv_time_t_64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64\" >&5\nprintf '%s\\n' \"$tcl_cv_time_t_64\" >&6; }\n\tif test \"x${tcl_cv_time_t_64}\" = \"xno\" ; then\n\t    # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64\n\t    # which SC_TCL_EARLY_FLAGS has defined if necessary.\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t\" >&5\nprintf %s \"checking if _TIME_BITS=64 enables 64-bit time_t... \" >&6; }\nif test ${tcl_cv__time_bits+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _TIME_BITS 64\n#include <sys/types.h>\nint\nmain (void)\n{\nswitch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv__time_bits=yes\nelse case e in #(\n  e) tcl_cv__time_bits=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits\" >&5\nprintf '%s\\n' \"$tcl_cv__time_bits\" >&6; }\n\t    if test \"x${tcl_cv__time_bits}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define _TIME_BITS 64\" >>confdefs.h\n\n\t    fi\n\tfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for struct dirent64\" >&5\nprintf %s \"checking for struct dirent64... \" >&6; }\nif test ${tcl_cv_struct_dirent64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n#include <dirent.h>\nint\nmain (void)\n{\nstruct dirent64 p;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_struct_dirent64=yes\nelse case e in #(\n  e) tcl_cv_struct_dirent64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64\" >&5\nprintf '%s\\n' \"$tcl_cv_struct_dirent64\" >&6; }\n\tif test \"x${tcl_cv_struct_dirent64}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define HAVE_STRUCT_DIRENT64 1\" >>confdefs.h\n\n\tfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for DIR64\" >&5\nprintf %s \"checking for DIR64... \" >&6; }\nif test ${tcl_cv_DIR64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n#include <dirent.h>\nint\nmain (void)\n{\nstruct dirent64 *p; DIR64 d = opendir64(\".\");\n\t    p = readdir64(d); rewinddir64(d); closedir64(d);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_DIR64=yes\nelse case e in #(\n  e) tcl_cv_DIR64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64\" >&5\nprintf '%s\\n' \"$tcl_cv_DIR64\" >&6; }\n\tif test \"x${tcl_cv_DIR64}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define HAVE_DIR64 1\" >>confdefs.h\n\n\tfi\n\n\tac_fn_c_check_func \"$LINENO\" \"open64\" \"ac_cv_func_open64\"\nif test \"x$ac_cv_func_open64\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_OPEN64 1\" >>confdefs.h\n\nfi\nac_fn_c_check_func \"$LINENO\" \"lseek64\" \"ac_cv_func_lseek64\"\nif test \"x$ac_cv_func_lseek64\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_LSEEK64 1\" >>confdefs.h\n\nfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for off64_t\" >&5\nprintf %s \"checking for off64_t... \" >&6; }\n\tif test ${tcl_cv_type_off64_t+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\nint\nmain (void)\n{\noff64_t offset;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_type_off64_t=yes\nelse case e in #(\n  e) tcl_cv_type_off64_t=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n\t\t\tif test \"x${tcl_cv_type_off64_t}\" = \"xyes\" && \\\n\t\ttest \"x${ac_cv_func_lseek64}\" = \"xyes\" && \\\n\t\ttest \"x${ac_cv_func_open64}\" = \"xyes\" ; then\n\nprintf '%s\\n' \"#define HAVE_TYPE_OFF64_T 1\" >>confdefs.h\n\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n\telse\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\tfi\n    fi\n\n\n#--------------------------------------------------------------------\n#\tCheck endianness because we can optimize some operations\n#--------------------------------------------------------------------\n\n { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian\" >&5\nprintf %s \"checking whether byte ordering is bigendian... \" >&6; }\nif test ${ac_cv_c_bigendian+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_c_bigendian=unknown\n    # See if we're dealing with a universal compiler.\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __APPLE_CC__\n\t       not a universal capable compiler\n\t     #endif\n\t     typedef int dummy;\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\n\t# Check for potential -arch flags.  It is not universal unless\n\t# there are at least two -arch flags with different values.\n\tac_arch=\n\tac_prev=\n\tfor ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do\n\t if test -n \"$ac_prev\"; then\n\t   case $ac_word in\n\t     i?86 | x86_64 | ppc | ppc64)\n\t       if test -z \"$ac_arch\" || test \"$ac_arch\" = \"$ac_word\"; then\n\t\t ac_arch=$ac_word\n\t       else\n\t\t ac_cv_c_bigendian=universal\n\t\t break\n\t       fi\n\t       ;;\n\t   esac\n\t   ac_prev=\n\t elif test \"x$ac_word\" = \"x-arch\"; then\n\t   ac_prev=arch\n\t fi\n       done\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if sys/param.h defines the BYTE_ORDER macro.\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t     #include <sys/param.h>\n\nint\nmain (void)\n{\n#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\\\\n\t\t     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\\\\n\t\t     && LITTLE_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  # It does; now see whether it defined to BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t\t#include <sys/param.h>\n\nint\nmain (void)\n{\n#if BYTE_ORDER != BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_c_bigendian=yes\nelse case e in #(\n  e) ac_cv_c_bigendian=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain (void)\n{\n#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  # It does; now see whether it defined to _BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain (void)\n{\n#ifndef _BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_c_bigendian=yes\nelse case e in #(\n  e) ac_cv_c_bigendian=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # Compile a test program.\n      if test \"$cross_compiling\" = yes\nthen :\n  # Try to guess by grepping values from an object file.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nunsigned short int ascii_mm[] =\n\t\t  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };\n\t\tunsigned short int ascii_ii[] =\n\t\t  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };\n\t\tint use_ascii (int i) {\n\t\t  return ascii_mm[i] + ascii_ii[i];\n\t\t}\n\t\tunsigned short int ebcdic_ii[] =\n\t\t  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };\n\t\tunsigned short int ebcdic_mm[] =\n\t\t  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };\n\t\tint use_ebcdic (int i) {\n\t\t  return ebcdic_mm[i] + ebcdic_ii[i];\n\t\t}\n\t\tint\n\t\tmain (int argc, char **argv)\n\t\t{\n\t\t  /* Intimidate the compiler so that it does not\n\t\t     optimize the arrays away.  */\n\t\t  char *p = argv[0];\n\t\t  ascii_mm[1] = *p++; ebcdic_mm[1] = *p++;\n\t\t  ascii_ii[1] = *p++; ebcdic_ii[1] = *p++;\n\t\t  return use_ascii (argc) == use_ebcdic (*p);\n\t\t}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then\n\t      ac_cv_c_bigendian=yes\n\t    fi\n\t    if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then\n\t      if test \"$ac_cv_c_bigendian\" = unknown; then\n\t\tac_cv_c_bigendian=no\n\t      else\n\t\t# finding both strings is unlikely to happen, but who knows?\n\t\tac_cv_c_bigendian=unknown\n\t      fi\n\t    fi\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain (void)\n{\n\n\t     /* Are we little or big endian?  From Harbison&Steele.  */\n\t     union\n\t     {\n\t       long int l;\n\t       char c[sizeof (long int)];\n\t     } u;\n\t     u.l = 1;\n\t     return u.c[sizeof (long int) - 1] == 1;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"\nthen :\n  ac_cv_c_bigendian=no\nelse case e in #(\n  e) ac_cv_c_bigendian=yes ;;\nesac\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n    fi ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian\" >&5\nprintf '%s\\n' \"$ac_cv_c_bigendian\" >&6; }\n case $ac_cv_c_bigendian in #(\n   yes)\n     printf '%s\\n' \"#define WORDS_BIGENDIAN 1\" >>confdefs.h\n;; #(\n   no)\n      ;; #(\n   universal)\n     #\n     ;; #(\n   *)\n     as_fn_error $? \"unknown endianness\n presetting ac_cv_c_bigendian=no (or yes) will help\" \"$LINENO\" 5 ;;\n esac\n\n\n#------------------------------------------------------------------------\n# If Tcl and Tk are installed in different places, adjust the library\n# search path to reflect this.\n#------------------------------------------------------------------------\n\nLIB_RUNTIME_DIR='$(libdir)'\n\nif test \"$TCL_EXEC_PREFIX\" != \"$exec_prefix\"; then\n    LIB_RUNTIME_DIR=\"${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib\"\nfi\n\nif test \"$TCL_PREFIX\" != \"$prefix\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING:\n\tDifferent --prefix selected for Tk and Tcl!\n\t[package require tk] may not work correctly in tclsh.\" >&5\nprintf '%s\\n' \"$as_me: WARNING:\n\tDifferent --prefix selected for Tk and Tcl!\n\t[package require tk] may not work correctly in tclsh.\" >&2;}\nfi\n\n#--------------------------------------------------------------------\n#\tInclude sys/select.h if it exists and if it supplies things\n#\tthat appear to be useful and aren't already in sys/types.h.\n#\tThis appears to be true only on the RS/6000 under AIX.  Some\n#\tsystems like OSF/1 have a sys/select.h that's of no use, and\n#\tother systems like SCO UNIX have a sys/select.h that's\n#\tpernicious.  If \"fd_set\" isn't defined anywhere then set a\n#\tspecial flag.\n#--------------------------------------------------------------------\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for fd_set in sys/types\" >&5\nprintf %s \"checking for fd_set in sys/types... \" >&6; }\nif test ${tcl_cv_type_fd_set+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\nint\nmain (void)\n{\nfd_set readMask, writeMask;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_type_fd_set=yes\nelse case e in #(\n  e) tcl_cv_type_fd_set=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set\" >&5\nprintf '%s\\n' \"$tcl_cv_type_fd_set\" >&6; }\ntk_ok=$tcl_cv_type_fd_set\nif test $tk_ok = no; then\n    ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\nprintf %s \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if test ${ac_cv_prog_CPP+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)     # Double quotes because $CC needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" cpp /lib/cpp\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) # Broken: fails on valid input.\ncontinue ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  # Broken: success on invalid input.\ncontinue\nelse case e in #(\n  e) # Passes both tests.\nac_preproc_ok=:\nbreak ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok\nthen :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n   ;;\nesac\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\nprintf '%s\\n' \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) # Broken: fails on valid input.\ncontinue ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  # Broken: success on invalid input.\ncontinue\nelse case e in #(\n  e) # Passes both tests.\nac_preproc_ok=:\nbreak ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok\nthen :\n\nelse case e in #(\n  e) { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for egrep -e\" >&5\nprintf %s \"checking for egrep -e... \" >&6; }\nif test ${ac_cv_path_EGREP_TRADITIONAL+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -z \"$EGREP_TRADITIONAL\"; then\n  ac_path_EGREP_TRADITIONAL_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_prog in grep ggrep\n   do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP_TRADITIONAL=\"$as_dir$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP_TRADITIONAL\" || continue\n# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.\n  # Check for GNU $ac_path_EGREP_TRADITIONAL\ncase `\"$ac_path_EGREP_TRADITIONAL\" --version 2>&1` in #(\n*GNU*)\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\" ac_path_EGREP_TRADITIONAL_found=:;;\n#(\n*)\n  ac_count=0\n  printf %s 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    printf '%s\\n' 'EGREP_TRADITIONAL' >> \"conftest.nl\"\n    \"$ac_path_EGREP_TRADITIONAL\" -E 'EGR(EP|AC)_TRADITIONAL$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\"\n      ac_path_EGREP_TRADITIONAL_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_TRADITIONAL_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP_TRADITIONAL\"; then\n    :\n  fi\nelse\n  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL\nfi\n\n    if test \"$ac_cv_path_EGREP_TRADITIONAL\"\nthen :\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_cv_path_EGREP_TRADITIONAL -E\"\nelse case e in #(\n  e) if test -z \"$EGREP_TRADITIONAL\"; then\n  ac_path_EGREP_TRADITIONAL_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_prog in egrep\n   do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP_TRADITIONAL=\"$as_dir$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP_TRADITIONAL\" || continue\n# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.\n  # Check for GNU $ac_path_EGREP_TRADITIONAL\ncase `\"$ac_path_EGREP_TRADITIONAL\" --version 2>&1` in #(\n*GNU*)\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\" ac_path_EGREP_TRADITIONAL_found=:;;\n#(\n*)\n  ac_count=0\n  printf %s 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    printf '%s\\n' 'EGREP_TRADITIONAL' >> \"conftest.nl\"\n    \"$ac_path_EGREP_TRADITIONAL\" 'EGR(EP|AC)_TRADITIONAL$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\"\n      ac_path_EGREP_TRADITIONAL_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_TRADITIONAL_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP_TRADITIONAL\"; then\n    as_fn_error $? \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL\nfi\n ;;\nesac\nfi ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL\" >&5\nprintf '%s\\n' \"$ac_cv_path_EGREP_TRADITIONAL\" >&6; }\n EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for fd_mask in sys/select\" >&5\nprintf %s \"checking for fd_mask in sys/select... \" >&6; }\nif test ${tcl_cv_grep_fd_mask+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/select.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP_TRADITIONAL \"fd_mask\" >/dev/null 2>&1\nthen :\n  tcl_cv_grep_fd_mask=present\nelse case e in #(\n  e) tcl_cv_grep_fd_mask=missing ;;\nesac\nfi\nrm -rf conftest*\n ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask\" >&5\nprintf '%s\\n' \"$tcl_cv_grep_fd_mask\" >&6; }\n    if test $tcl_cv_grep_fd_mask = present; then\n\nprintf '%s\\n' \"#define HAVE_SYS_SELECT_H 1\" >>confdefs.h\n\n\ttk_ok=yes\n    fi\nfi\nif test $tk_ok = no; then\n\nprintf '%s\\n' \"#define NO_FD_SET 1\" >>confdefs.h\n\nfi\n\n#------------------------------------------------------------------------------\n#       Find out all about time handling differences.\n#------------------------------------------------------------------------------\n\n\n\n\n#--------------------------------------------------------------------\n#\tCheck for various typedefs and provide substitutes if\n#\tthey don't exist.\n#--------------------------------------------------------------------\n\nac_fn_c_check_type \"$LINENO\" \"mode_t\" \"ac_cv_type_mode_t\" \"$ac_includes_default\"\nif test \"x$ac_cv_type_mode_t\" = xyes\nthen :\n\nelse case e in #(\n  e)\nprintf '%s\\n' \"#define mode_t int\" >>confdefs.h\n ;;\nesac\nfi\n\n\n  ac_fn_c_check_type \"$LINENO\" \"pid_t\" \"ac_cv_type_pid_t\" \"$ac_includes_default\n\"\nif test \"x$ac_cv_type_pid_t\" = xyes\nthen :\n\nelse case e in #(\n  e)                                         cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n          #if defined _WIN64 && !defined __CYGWIN__\n          LLP64\n          #endif\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_pid_type='int'\nelse case e in #(\n  e) ac_pid_type='__int64' ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\nprintf '%s\\n' \"#define pid_t $ac_pid_type\" >>confdefs.h\n\n     ;;\nesac\nfi\n\n\nac_fn_c_check_type \"$LINENO\" \"size_t\" \"ac_cv_type_size_t\" \"$ac_includes_default\"\nif test \"x$ac_cv_type_size_t\" = xyes\nthen :\n\nelse case e in #(\n  e)\nprintf '%s\\n' \"#define size_t unsigned int\" >>confdefs.h\n ;;\nesac\nfi\n\n\nac_fn_c_check_type \"$LINENO\" \"intptr_t\" \"ac_cv_type_intptr_t\" \"\n#include <stdint.h>\n\n\"\nif test \"x$ac_cv_type_intptr_t\" = xyes\nthen :\n\nprintf '%s\\n' \"#define HAVE_INTPTR_T 1\" >>confdefs.h\n\n\nfi\nac_fn_c_check_type \"$LINENO\" \"uintptr_t\" \"ac_cv_type_uintptr_t\" \"\n#include <stdint.h>\n\n\"\nif test \"x$ac_cv_type_uintptr_t\" = xyes\nthen :\n\nprintf '%s\\n' \"#define HAVE_UINTPTR_T 1\" >>confdefs.h\n\n\nfi\n\n\n#-------------------------------------------\n#     In OS/390 struct pwd has no pw_gecos field\n#-------------------------------------------\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking pw_gecos in struct pwd\" >&5\nprintf %s \"checking pw_gecos in struct pwd... \" >&6; }\nif test ${tcl_cv_pwd_pw_gecos+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <pwd.h>\nint\nmain (void)\n{\nstruct passwd pwd; (void)pwd.pw_gecos;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_pwd_pw_gecos=yes\nelse case e in #(\n  e) tcl_cv_pwd_pw_gecos=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_pwd_pw_gecos\" >&5\nprintf '%s\\n' \"$tcl_cv_pwd_pw_gecos\" >&6; }\nif test $tcl_cv_pwd_pw_gecos = yes; then\n\nprintf '%s\\n' \"#define HAVE_PW_GECOS 1\" >>confdefs.h\n\nfi\n\n#--------------------------------------------------------------------\n#\tOn Mac OS X, we can build either with X11 or with Aqua\n#--------------------------------------------------------------------\n\nif test \"`uname -s`\" = \"Darwin\" ; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use Aqua\" >&5\nprintf %s \"checking whether to use Aqua... \" >&6; }\n    # Check whether --enable-aqua was given.\nif test ${enable_aqua+y}\nthen :\n  enableval=$enable_aqua; tk_aqua=$enableval\nelse case e in #(\n  e) tk_aqua=no ;;\nesac\nfi\n\n    if test $tk_aqua = yes -o $tk_aqua = cocoa; then\n\ttk_aqua=yes\n\tif test $tcl_corefoundation = no; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Aqua can only be used when CoreFoundation is available\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Aqua can only be used when CoreFoundation is available\" >&2;}\n\t    tk_aqua=no\n\tfi\n\tif test ! -d /System/Library/Frameworks/Cocoa.framework; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Aqua can only be used when Cocoa is available\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Aqua can only be used when Cocoa is available\" >&2;}\n\t    tk_aqua=no\n\tfi\n\tif test \"`uname -r | awk -F. '{print $1}'`\" -lt 9; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Aqua requires Mac OS X 10.5 or later\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Aqua requires Mac OS X 10.5 or later\" >&2;}\n\t    tk_aqua=no\n\tfi\n    fi\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tk_aqua\" >&5\nprintf '%s\\n' \"$tk_aqua\" >&6; }\n    if test $tk_aqua = no; then\n\t# check if weak linking whole libraries is possible.\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if ld accepts -weak-l flag\" >&5\nprintf %s \"checking if ld accepts -weak-l flag... \" >&6; }\nif test ${tcl_cv_ld_weak_l+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    hold_ldflags=$LDFLAGS\n\t    LDFLAGS=\"$LDFLAGS -Wl,-weak-lm\"\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <math.h>\nint\nmain (void)\n{\ndouble f = sin(1.0);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_ld_weak_l=yes\nelse case e in #(\n  e) tcl_cv_ld_weak_l=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t    LDFLAGS=$hold_ldflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_weak_l\" >&5\nprintf '%s\\n' \"$tcl_cv_ld_weak_l\" >&6; }\n    fi\n    ac_fn_c_check_header_compile \"$LINENO\" \"AvailabilityMacros.h\" \"ac_cv_header_AvailabilityMacros_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_AvailabilityMacros_h\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_AVAILABILITYMACROS_H 1\" >>confdefs.h\n\nfi\n\nelse\n    tk_aqua=no\nfi\n\nif test $tk_aqua = yes; then\n\nprintf '%s\\n' \"#define MAC_OSX_TK 1\" >>confdefs.h\n\n    LIBS=\"$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore -framework Security -framework CoreGraphics\"\n    if test -d \"/System/Library/Frameworks/UniformTypeIdentifiers.framework\"; then\n\tLIBS=\"$LIBS -weak_framework UniformTypeIdentifiers\"\n    fi\n    EXTRA_CC_SWITCHES='-x objective-c'\n    TK_WINDOWINGSYSTEM=AQUA\n    if test -n \"${enable_symbols}\" -a \"${enable_symbols}\" != no; then\n\nprintf '%s\\n' \"#define TK_MAC_DEBUG 1\" >>confdefs.h\n\n    fi\nelse\n    #--------------------------------------------------------------------\n    #\tLocate the X11 header files and the X11 library archive.  Try\n    #\tthe ac_path_x macro first, but if it doesn't find the X stuff\n    #\t(e.g. because there's no xmkmf program) then check through\n    #\ta list of possible directories.  Under some conditions the\n    #\tautoconf macro will return an include directory that contains\n    #\tno include files, so double-check its result just to be safe.\n    #--------------------------------------------------------------------\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for X\" >&5\nprintf %s \"checking for X... \" >&6; }\n\n\n# Check whether --with-x was given.\nif test ${with_x+y}\nthen :\n  withval=$with_x;\nfi\n\n# $have_x is 'yes', 'no', 'disabled', or empty when we do not yet know.\nif test \"x$with_x\" = xno; then\n  # The user explicitly disabled X.\n  have_x=disabled\nelse\n  case $x_includes,$x_libraries in #(\n    *\\'*) as_fn_error $? \"cannot use X directory names containing '\" \"$LINENO\" 5;; #(\n    *,NONE | NONE,*) if test ${ac_cv_have_x+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) # One or both of the vars are not set, and there is no cached value.\nac_x_includes=no\nac_x_libraries=no\n# Do we need to do anything special at all?\nac_save_LIBS=$LIBS\nLIBS=\"-lX11 $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\nint\nmain (void)\n{\nXrmInitialize ()\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  # We can compile and link X programs with no special options.\n  ac_x_includes=\n  ac_x_libraries=\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=\"$ac_save_LIBS\"\n# If that didn't work, only try xmkmf and file system searches\n# for native compilation.\nif test x\"$ac_x_includes\" = xno && test \"$cross_compiling\" = no\nthen :\n  rm -f -r conftest.dir\nif mkdir conftest.dir; then\n  cd conftest.dir\n  cat >Imakefile <<'_ACEOF'\nincroot:\n\t@printf '%s\\n' incroot='${INCROOT}'\nusrlibdir:\n\t@printf '%s\\n' usrlibdir='${USRLIBDIR}'\nlibdir:\n\t@printf '%s\\n' libdir='${LIBDIR}'\n_ACEOF\n  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then\n    # GNU make sometimes prints \"make[1]: Entering ...\", which would confuse us.\n    for ac_var in incroot usrlibdir libdir; do\n      eval \"ac_im_$ac_var=\\`\\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\\`\"\n    done\n    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.\n    for ac_extension in a so sl dylib la dll; do\n      if test ! -f \"$ac_im_usrlibdir/libX11.$ac_extension\" &&\n\t test -f \"$ac_im_libdir/libX11.$ac_extension\"; then\n\tac_im_usrlibdir=$ac_im_libdir; break\n      fi\n    done\n    # Screen out bogus values from the imake configuration.  They are\n    # bogus both because they are the default anyway, and because\n    # using them would break gcc on systems where it needs fixed includes.\n    case $ac_im_incroot in\n\t/usr/include) ac_x_includes= ;;\n\t*) test -f \"$ac_im_incroot/X11/Xos.h\" && ac_x_includes=$ac_im_incroot;;\n    esac\n    case $ac_im_usrlibdir in\n\t/usr/lib | /usr/lib64 | /lib | /lib64) ;;\n\t*) test -d \"$ac_im_usrlibdir\" && ac_x_libraries=$ac_im_usrlibdir ;;\n    esac\n  fi\n  cd ..\n  rm -f -r conftest.dir\nfi\n\n  # Standard set of common directories for X headers.\n# Check X11 before X11Rn because it is often a symlink to the current release.\nac_x_header_dirs='\n/usr/X11/include\n/usr/X11R7/include\n/usr/X11R6/include\n/usr/X11R5/include\n/usr/X11R4/include\n\n/usr/include/X11\n/usr/include/X11R7\n/usr/include/X11R6\n/usr/include/X11R5\n/usr/include/X11R4\n\n/usr/local/X11/include\n/usr/local/X11R7/include\n/usr/local/X11R6/include\n/usr/local/X11R5/include\n/usr/local/X11R4/include\n\n/usr/local/include/X11\n/usr/local/include/X11R7\n/usr/local/include/X11R6\n/usr/local/include/X11R5\n/usr/local/include/X11R4\n\n/opt/X11/include\n\n/usr/X386/include\n/usr/x386/include\n/usr/XFree86/include/X11\n\n/usr/include\n/usr/local/include\n/usr/unsupported/include\n/usr/athena/include\n/usr/local/x11r5/include\n/usr/lpp/Xamples/include\n\n/usr/openwin/include\n/usr/openwin/share/include'\n\nif test \"$ac_x_includes\" = no; then\n  # Guess where to find include files, by looking for Xlib.h.\n  # First, try using that file with no special directory specified.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  # We can compile using X headers with no special include directory.\nac_x_includes=\nelse case e in #(\n  e) for ac_dir in $ac_x_header_dirs; do\n  if test -r \"$ac_dir/X11/Xlib.h\"; then\n    ac_x_includes=$ac_dir\n    break\n  fi\ndone ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\nfi # $ac_x_includes = no\n\nif test \"$ac_x_libraries\" = no; then\n  # Check for the libraries.\n  # See if we find them without any special options.\n  # Don't add to $LIBS permanently.\n  ac_save_LIBS=$LIBS\n  LIBS=\"-lX11 $LIBS\"\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\nint\nmain (void)\n{\nXrmInitialize ()\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  LIBS=$ac_save_LIBS\n# We can link X programs with no special library path.\nac_x_libraries=\nelse case e in #(\n  e) LIBS=$ac_save_LIBS\nfor ac_dir in `printf '%s\\n' \"$ac_x_includes $ac_x_header_dirs\" | sed s/include/lib/g`\ndo\n  # Don't even attempt the hair of trying to link an X program!\n  for ac_extension in a so sl dylib la dll; do\n    if test -r \"$ac_dir/libX11.$ac_extension\"; then\n      ac_x_libraries=$ac_dir\n      break 2\n    fi\n  done\ndone ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nfi # $ac_x_libraries = no\n\nfi\n# Record the results.\ncase $ac_x_includes,$ac_x_libraries in #(\n  no,* | *,no | *\\'*) :\n    # Didn't find X, or a directory has \"'\" in its name.\n    ac_cv_have_x=\"have_x=no\" ;; #(\n  *) :\n    # Record where we found X for the cache.\n    ac_cv_have_x=\"have_x=yes\\\n\tac_x_includes='$ac_x_includes'\\\n\tac_x_libraries='$ac_x_libraries'\" ;;\nesac ;;\nesac\nfi\n;; #(\n    *) have_x=yes;;\n  esac\n  eval \"$ac_cv_have_x\"\nfi # $with_x != no\n\nif test \"$have_x\" != yes; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $have_x\" >&5\nprintf '%s\\n' \"$have_x\" >&6; }\n  no_x=yes\nelse\n  # If each of the values was on the command line, it overrides each guess.\n  test \"x$x_includes\" = xNONE && x_includes=$ac_x_includes\n  test \"x$x_libraries\" = xNONE && x_libraries=$ac_x_libraries\n  # Update the cache value to reflect the command line values.\n  ac_cv_have_x=\"have_x=yes\\\n\tac_x_includes='$x_includes'\\\n\tac_x_libraries='$x_libraries'\"\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes\" >&5\nprintf '%s\\n' \"libraries $x_libraries, headers $x_includes\" >&6; }\nfi\n\n    not_really_there=\"\"\n    if test \"$no_x\" = \"\"; then\n\tif test \"$x_includes\" = \"\"; then\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) not_really_there=\"yes\" ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\telse\n\t    if test ! -r $x_includes/X11/Xlib.h; then\n\t\tnot_really_there=\"yes\"\n\t    fi\n\tfi\n    fi\n    if test \"$no_x\" = \"yes\" -o \"$not_really_there\" = \"yes\"; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for X11 header files\" >&5\nprintf %s \"checking for X11 header files... \" >&6; }\n\tfound_xincludes=\"no\"\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <X11/Xlib.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  found_xincludes=\"yes\"\nelse case e in #(\n  e) found_xincludes=\"no\" ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\tif test \"$found_xincludes\" = \"no\"; then\n\t    dirs=\"/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include\"\n\t    for i in $dirs ; do\n\t\tif test -r $i/X11/Xlib.h; then\n\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $i\" >&5\nprintf '%s\\n' \"$i\" >&6; }\n\t\t    XINCLUDES=\" -I$i\"\n\t\t    found_xincludes=\"yes\"\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    else\n\tif test \"$x_includes\" != \"\"; then\n\t    XINCLUDES=\"-I$x_includes\"\n\t    found_xincludes=\"yes\"\n\tfi\n    fi\n    if test \"$found_xincludes\" = \"no\"; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: couldn't find any!\" >&5\nprintf '%s\\n' \"couldn't find any!\" >&6; }\n    fi\n\n    if test \"$no_x\" = yes; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for X11 libraries\" >&5\nprintf %s \"checking for X11 libraries... \" >&6; }\n\tXLIBSW=nope\n\tdirs=\"/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib\"\n\tfor i in $dirs ; do\n\t    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $i\" >&5\nprintf '%s\\n' \"$i\" >&6; }\n\t\tXLIBSW=\"-L$i -lX11\"\n\t\tx_libraries=\"$i\"\n\t\tbreak\n\t    fi\n\tdone\n    else\n\tif test \"$x_libraries\" = \"\"; then\n\t    XLIBSW=-lX11\n\telse\n\t    XLIBSW=\"-L$x_libraries -lX11\"\n\tfi\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for XCreateWindow in -lXwindow\" >&5\nprintf %s \"checking for XCreateWindow in -lXwindow... \" >&6; }\nif test ${ac_cv_lib_Xwindow_XCreateWindow+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXwindow  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XCreateWindow (void);\nint\nmain (void)\n{\nreturn XCreateWindow ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_Xwindow_XCreateWindow=yes\nelse case e in #(\n  e) ac_cv_lib_Xwindow_XCreateWindow=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xwindow_XCreateWindow\" >&5\nprintf '%s\\n' \"$ac_cv_lib_Xwindow_XCreateWindow\" >&6; }\nif test \"x$ac_cv_lib_Xwindow_XCreateWindow\" = xyes\nthen :\n  XLIBSW=-lXwindow\nfi\n\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: could not find any!  Using -lX11.\" >&5\nprintf '%s\\n' \"could not find any!  Using -lX11.\" >&6; }\n\tXLIBSW=-lX11\n    fi\n\n    TK_WINDOWINGSYSTEM=X11\nfi\n\n#--------------------------------------------------------------------\n#\tVarious manipulations on the search path used at runtime to\n#\tfind shared libraries:\n#\t1. If the X library binaries are in a non-standard directory,\n#\t   add the X library location into that search path.\n#\t2. On systems such as AIX and Ultrix that use \"-L\" as the\n#\t   search path option, colons cannot be used to separate\n#\t   directories from each other. Change colons to \" -L\".\n#\t3. Create two sets of search flags, one for use in cc lines\n#\t   and the other for when the linker is invoked directly.  In\n#\t   the second case, '-Wl,' must be stripped off and commas must\n#\t   be replaced by spaces.\n#--------------------------------------------------------------------\n\nif test \"x${x_libraries}\" != \"x\"; then\n  if test \"x${x_libraries}\" != \"xNONE\"; then\n    LIB_RUNTIME_DIR=\"${LIB_RUNTIME_DIR}:${x_libraries}\"\n  fi\nfi\nif test \"${TCL_LD_SEARCH_FLAGS}\" = '-L${LIB_RUNTIME_DIR}'; then\n    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for the existence of various libraries.  The order here\n#\tis important, so that then end up in the right order in the\n#\tcommand line generated by make.  The -lsocket and -lnsl libraries\n#\trequire a couple of special tricks:\n#\t1. Use \"connect\" and \"accept\" to check for -lsocket, and\n#\t   \"gethostbyname\" to check for -lnsl.\n#\t2. Use each function name only once:  can't redo a check because\n#\t   autoconf caches the results of the last check and won't redo it.\n#\t3. Use -lnsl and -lsocket only if they supply procedures that\n#\t   aren't already present in the normal libraries.  This is because\n#\t   IRIX 5.2 has libraries, but they aren't needed and they're\n#\t   bogus:  they goof up name resolution if used.\n#\t4. On some SVR4 systems, can't use -lsocket without -lnsl too.\n#\t   To get around this problem, check for both libraries together\n#\t   if -lsocket doesn't work by itself.\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for main in -lXbsd\" >&5\nprintf %s \"checking for main in -lXbsd... \" >&6; }\nif test ${ac_cv_lib_Xbsd_main+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXbsd  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain (void)\n{\nreturn main ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_Xbsd_main=yes\nelse case e in #(\n  e) ac_cv_lib_Xbsd_main=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xbsd_main\" >&5\nprintf '%s\\n' \"$ac_cv_lib_Xbsd_main\" >&6; }\nif test \"x$ac_cv_lib_Xbsd_main\" = xyes\nthen :\n  LIBS=\"$LIBS -lXbsd\"\nfi\n\nfi\n\n#--------------------------------------------------------------------\n# One more check related to the X libraries.  The standard releases\n# of Ultrix don't support the \"xauth\" mechanism, so send won't work\n# unless TK_NO_SECURITY is defined.  However, there are usually copies\n# of the MIT X server available as well, which do support xauth.\n# Check for the MIT stuff and use it if it exists.\n#\n# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1)\n# because it can't deal with the \"-\" in the library name.\n#--------------------------------------------------------------------\n\nif test -d /usr/include/mit -a $tk_aqua = no; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking MIT X libraries\" >&5\nprintf %s \"checking MIT X libraries... \" >&6; }\n    tk_oldCFlags=$CFLAGS\n    CFLAGS=\"$CFLAGS -I/usr/include/mit\"\n    tk_oldLibs=$LIBS\n    LIBS=\"$LIBS -lX11-mit\"\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t#include <X11/Xlib.h>\n\nint\nmain (void)\n{\n\n\tXOpenDisplay(0);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n\tXLIBSW=\"-lX11-mit\"\n\tXINCLUDES=\"-I/usr/include/mit\"\n\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; } ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n    CFLAGS=$tk_oldCFlags\n    LIBS=$tk_oldLibs\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for freetype / fontconfig / Xft support and Bidirectional text\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n\n    #--------------------------------------------------------------------\n    # --enable-xft (default: yes)\n    #--------------------------------------------------------------------\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use xft\" >&5\nprintf %s \"checking whether to use xft... \" >&6; }\n    # Check whether --enable-xft was given.\nif test ${enable_xft+y}\nthen :\n  enableval=$enable_xft; enable_xft=$enableval\nelse case e in #(\n  e) enable_xft=\"yes\" ;;\nesac\nfi\n\n\n    XFT_CFLAGS=\"\"\n    XFT_LIBS=\"\"\n\n    if test \"$enable_xft\" = \"no\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n    else\n\tfound_xft=\"yes\"\n\n\tXFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft=\"no\"\n\tXFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft=\"no\"\n\tif test \"$found_xft\" = \"no\" ; then\n\t    found_xft=yes\n\t    XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft=\"no\"\n\t    XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft=\"no\"\n\tfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $found_xft\" >&5\nprintf '%s\\n' \"$found_xft\" >&6; }\n\n\tif test \"$found_xft\" = \"yes\" ; then\n\t    tk_oldCFlags=$CFLAGS\n\t    CFLAGS=\"$CFLAGS $XINCLUDES $XFT_CFLAGS\"\n\t    tk_oldLibs=$LIBS\n\t    LIBS=\"$tk_oldLibs $XFT_LIBS $XLIBSW\"\n\n\t    ac_fn_c_check_header_compile \"$LINENO\" \"X11/Xft/Xft.h\" \"ac_cv_header_X11_Xft_Xft_h\" \"#include <X11/Xlib.h>\n\"\nif test \"x$ac_cv_header_X11_Xft_Xft_h\" = xyes\nthen :\n\nelse case e in #(\n  e) found_xft=no ;;\nesac\nfi\n\n\n\t    if test \"$found_xft\" = \"yes\" ; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for XftFontOpen in -lXft\" >&5\nprintf %s \"checking for XftFontOpen in -lXft... \" >&6; }\nif test ${ac_cv_lib_Xft_XftFontOpen+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXft  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XftFontOpen (void);\nint\nmain (void)\n{\nreturn XftFontOpen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_Xft_XftFontOpen=yes\nelse case e in #(\n  e) ac_cv_lib_Xft_XftFontOpen=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftFontOpen\" >&5\nprintf '%s\\n' \"$ac_cv_lib_Xft_XftFontOpen\" >&6; }\nif test \"x$ac_cv_lib_Xft_XftFontOpen\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_LIBXFT 1\" >>confdefs.h\n\n  LIBS=\"-lXft $LIBS\"\n\nelse case e in #(\n  e) found_xft=no ;;\nesac\nfi\n\n\t    fi\n\n\t    if test \"$found_xft\" = \"yes\" ; then\n\t\tLIBS=\"$tk_oldLibs $XFT_LIBS $XLIBSW -lfontconfig\"\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for FcFontSort in -lfontconfig\" >&5\nprintf %s \"checking for FcFontSort in -lfontconfig... \" >&6; }\nif test ${ac_cv_lib_fontconfig_FcFontSort+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lfontconfig  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar FcFontSort (void);\nint\nmain (void)\n{\nreturn FcFontSort ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_fontconfig_FcFontSort=yes\nelse case e in #(\n  e) ac_cv_lib_fontconfig_FcFontSort=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fontconfig_FcFontSort\" >&5\nprintf '%s\\n' \"$ac_cv_lib_fontconfig_FcFontSort\" >&6; }\nif test \"x$ac_cv_lib_fontconfig_FcFontSort\" = xyes\nthen :\n\n\t\t    XFT_LIBS=\"$XFT_LIBS -lfontconfig\"\n\nfi\n\n\t    fi\n\n\t    CFLAGS=$tk_oldCFlags\n\t    LIBS=$tk_oldLibs\n\tfi\n\n\tif test \"$found_xft\" = \"no\" ; then\n\t    if test \"$enable_xft\" = \"yes\" ; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Can't find xft configuration or xft is unusable -- falling back to classic fonts\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Can't find xft configuration or xft is unusable -- falling back to classic fonts\" >&2;}\n\t    fi\n\t    enable_xft=no\n\t    XFT_CFLAGS=\"\"\n\t    XFT_LIBS=\"\"\n\telse\n\t    enable_xft=yes\n\tfi\n    fi\n\n\n\n\n    #--------------------------------------------------------------------\n    # --enable-bidi  (HarfBuzz is required only when enabled)\n    #--------------------------------------------------------------------\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to enable bidirectional (Bidi) text support\" >&5\nprintf %s \"checking whether to enable bidirectional (Bidi) text support... \" >&6; }\n    # Check whether --enable-bidi was given.\nif test ${enable_bidi+y}\nthen :\n  enableval=$enable_bidi; enable_bidi=$enableval\nelse case e in #(\n  e) enable_bidi=\"no\" ;;\nesac\nfi\n\n\n    if test \"$enable_bidi\" = \"yes\"; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes (forces Xft on)\" >&5\nprintf '%s\\n' \"yes (forces Xft on)\" >&6; }\n\tif test \"$enable_xft\" = \"no\"; then\n\t   { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: --enable-bidi requested: enabling Xft as well\" >&5\nprintf '%s\\n' \"$as_me: --enable-bidi requested: enabling Xft as well\" >&6;}\n\t   enable_xft=yes\n\tfi\n\n\tBIDI_CFLAGS=\"-I${TK_SRC_DIR}/unix/bidi/Headers \\\n                     -I${TK_SRC_DIR}/unix/bidi/Source \\\n                     -I${TK_SRC_DIR}/unix/bidi \\\n                     -DSB_CONFIG_UNITY -DSB_CONFIG_EXPERIMENTAL_TEXT_API -w\"\n\nprintf '%s\\n' \"#define HAVE_BIDI 1\" >>confdefs.h\n\n\tUNIX_FONT_OBJS=\"tkUnixBidiFont.o SheenBidi.o\"\n\n        #--------------------------------------------------------------------\n        # HarfBuzz - HARD DEPENDENCY only when --enable-bidi=yes\n        #--------------------------------------------------------------------\n        { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for HarfBuzz (required for --enable-bidi)\" >&5\nprintf %s \"checking for HarfBuzz (required for --enable-bidi)... \" >&6; }\n        if pkg-config --exists harfbuzz; then\n            HB_CFLAGS=`pkg-config --cflags harfbuzz`\n            HB_LIBS=`pkg-config --libs harfbuzz`\n            { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n\n            tk_oldCFlags=$CFLAGS\n            tk_oldLibs=$LIBS\n            CFLAGS=\"$CFLAGS $XINCLUDES $XFT_CFLAGS $HB_CFLAGS\"\n            LIBS=\"$tk_oldLibs $XFT_LIBS $HB_LIBS $XLIBSW\"\n\n            ac_fn_c_check_header_compile \"$LINENO\" \"harfbuzz/hb.h\" \"ac_cv_header_harfbuzz_hb_h\" \"#include <X11/Xlib.h>\n\"\nif test \"x$ac_cv_header_harfbuzz_hb_h\" = xyes\nthen :\n\nelse case e in #(\n  e)\n                as_fn_error $? \"HarfBuzz header <harfbuzz/hb.h> not found\" \"$LINENO\" 5\n             ;;\nesac\nfi\n\n\n            { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for hb_buffer_create in -lharfbuzz\" >&5\nprintf %s \"checking for hb_buffer_create in -lharfbuzz... \" >&6; }\nif test ${ac_cv_lib_harfbuzz_hb_buffer_create+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lharfbuzz  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar hb_buffer_create (void);\nint\nmain (void)\n{\nreturn hb_buffer_create ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_harfbuzz_hb_buffer_create=yes\nelse case e in #(\n  e) ac_cv_lib_harfbuzz_hb_buffer_create=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_harfbuzz_hb_buffer_create\" >&5\nprintf '%s\\n' \"$ac_cv_lib_harfbuzz_hb_buffer_create\" >&6; }\nif test \"x$ac_cv_lib_harfbuzz_hb_buffer_create\" = xyes\nthen :\n  printf '%s\\n' \"#define HAVE_LIBHARFBUZZ 1\" >>confdefs.h\n\n  LIBS=\"-lharfbuzz $LIBS\"\n\nelse case e in #(\n  e)\n                as_fn_error $? \"HarfBuzz library (libharfbuzz) not found or unusable\" \"$LINENO\" 5\n             ;;\nesac\nfi\n\n\n            CFLAGS=$tk_oldCFlags\n            LIBS=$tk_oldLibs\n\n            BIDI_CFLAGS=\"$BIDI_CFLAGS $HB_CFLAGS\"\n\n\n        else\n            as_fn_error $? \"--enable-bidi requires HarfBuzz development files.\nPlease install the HarfBuzz development package:\n  - Debian/Ubuntu:   sudo apt install libharfbuzz-dev\n  - Fedora/RHEL:     sudo dnf install harfbuzz-devel\n  - Arch:            sudo pacman -S harfbuzz\n  - macOS (Homebrew): brew install harfbuzz\" \"$LINENO\" 5\n        fi\n\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\tBIDI_CFLAGS=\"\"\n\tHB_CFLAGS=\"\"\n\tHB_LIBS=\"\"\n\tif test \"$enable_xft\" = \"yes\" ; then\n\t   UNIX_FONT_OBJS=\"tkUnixRFont.o\"\n\nprintf '%s\\n' \"#define HAVE_XFT 1\" >>confdefs.h\n\n\telse\n\t   UNIX_FONT_OBJS=\"tkUnixFont.o\"\n\tfi\n    fi\n\n\n\n\n\n\n    # Set font system for pkgconfig\n    if test \"$enable_bidi\" = \"yes\"; then\n\tFONTSYSTEM=\"xft\"\n    elif test \"$enable_xft\" = \"yes\" ; then\n\tFONTSYSTEM=\"xft\"\n    else\n\tFONTSYSTEM=\"core\"\n    fi\n\n\nelse\n    # Aqua (macOS) path\n    enable_xft=no\n    enable_bidi=no\n    UNIX_FONT_OBJS=\"tkUnixFont.o\"\n    BIDI_CFLAGS=\"\"\n    HB_CFLAGS=\"\"\n    HB_LIBS=\"\"\n    FONTSYSTEM=\"core\"\n\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for libcups support\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to use libcups\" >&5\nprintf %s \"checking whether to use libcups... \" >&6; }\n    # Check whether --enable-libcups was given.\nif test ${enable_libcups+y}\nthen :\n  enableval=$enable_libcups; enable_libcups=$enableval\nelse case e in #(\n  e) enable_libcups=\"default\" ;;\nesac\nfi\n\n    CUPS_CFLAGS=\"\"\n    CUPS_LIBS=\"\"\n    if test \"$enable_libcups\" = \"no\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enable_libcups\" >&5\nprintf '%s\\n' \"$enable_libcups\" >&6; }\n    else\n\tfound_cups=`cups-config 2>/dev/null`\n\tif test \"$found_cups\" = \"\"; then\n\t    found_cups=no\n\telse\n\t    found_cups=yes\n\t    CUPS_CFLAGS=\"-DHAVE_CUPS\"\n\t    CUPS_LIBS=`cups-config --libs`\n\tfi\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $found_cups\" >&5\nprintf '%s\\n' \"$found_cups\" >&6; }\n\tif test \"$found_cups\" = \"yes\" ; then\n\t    tk_oldCFlags=$CFLAGS\n\t    CFLAGS=\"$CFLAGS $XINCLUDES $CUPS_CFLAGS\"\n\t    tk_oldLibs=$LIBS\n\t    LIBS=\"$tk_oldLibs $CUPS_LIBS $XLIBSW\"\n\t    ac_fn_c_check_header_compile \"$LINENO\" \"cups/cups.h\" \"ac_cv_header_cups_cups_h\" \"#include <cups/cups.h>\n\"\nif test \"x$ac_cv_header_cups_cups_h\" = xyes\nthen :\n\nelse case e in #(\n  e)\n\t\tfound_cups=no\n\t\tCUPS_CFLAGS=\"\"\n\t\tCUPS_LIBS=\"\"\n\t     ;;\nesac\nfi\n\n\t    CFLAGS=$tk_oldCFlags\n\t    LIBS=$tk_oldLibs\n\tfi\n    fi\n\n\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for Atk support\n#--------------------------------------------------------------------\n\nif test \"$tk_aqua\" = no; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for ATK and Atk-bridge\" >&5\nprintf %s \"checking for ATK and Atk-bridge... \" >&6; }\n  if pkg-config --exists atk && pkg-config --exists atk-bridge-2.0; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n    ATK_CFLAGS=\"`pkg-config --cflags atk atk-bridge-2.0`\"\n    ATK_LIBS=\"`pkg-config --libs atk atk-bridge-2.0`\"\n\nprintf '%s\\n' \"#define HAVE_ATK 1\" >>confdefs.h\n\n  else\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n    ATK_CFLAGS=\"\"\n    ATK_LIBS=\"\"\n  fi\n\n\nfi\n\n#--------------------------------------------------------------------\n# XXX Do this last.\n# It might modify XLIBSW which could affect other tests.\n#\n# Check whether the header and library for the XScreenSaver\n# extension are available, and set HAVE_XSS if so.\n# XScreenSaver is needed for Tk_GetUserInactiveTime().\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    tk_oldCFlags=$CFLAGS\n    CFLAGS=\"$CFLAGS $XINCLUDES\"\n    tk_oldLibs=$LIBS\n    LIBS=\"$tk_oldLibs $XLIBSW\"\n    xss_header_found=no\n    xss_lib_found=no\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to try to use XScreenSaver\" >&5\nprintf %s \"checking whether to try to use XScreenSaver... \" >&6; }\n    # Check whether --enable-xss was given.\nif test ${enable_xss+y}\nthen :\n  enableval=$enable_xss; enable_xss=$enableval\nelse case e in #(\n  e) enable_xss=yes ;;\nesac\nfi\n\n    if test \"$enable_xss\" = \"no\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enable_xss\" >&5\nprintf '%s\\n' \"$enable_xss\" >&6; }\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $enable_xss\" >&5\nprintf '%s\\n' \"$enable_xss\" >&6; }\n\tac_fn_c_check_header_compile \"$LINENO\" \"X11/extensions/scrnsaver.h\" \"ac_cv_header_X11_extensions_scrnsaver_h\" \"#include <X11/Xlib.h>\n\"\nif test \"x$ac_cv_header_X11_extensions_scrnsaver_h\" = xyes\nthen :\n\n\t    xss_header_found=yes\n\nfi\n\n\tac_fn_c_check_func \"$LINENO\" \"XScreenSaverQueryInfo\" \"ac_cv_func_XScreenSaverQueryInfo\"\nif test \"x$ac_cv_func_XScreenSaverQueryInfo\" = xyes\nthen :\n\nelse case e in #(\n  e)\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for XScreenSaverQueryInfo in -lXext\" >&5\nprintf %s \"checking for XScreenSaverQueryInfo in -lXext... \" >&6; }\nif test ${ac_cv_lib_Xext_XScreenSaverQueryInfo+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXext  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XScreenSaverQueryInfo (void);\nint\nmain (void)\n{\nreturn XScreenSaverQueryInfo ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_Xext_XScreenSaverQueryInfo=yes\nelse case e in #(\n  e) ac_cv_lib_Xext_XScreenSaverQueryInfo=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XScreenSaverQueryInfo\" >&5\nprintf '%s\\n' \"$ac_cv_lib_Xext_XScreenSaverQueryInfo\" >&6; }\nif test \"x$ac_cv_lib_Xext_XScreenSaverQueryInfo\" = xyes\nthen :\n\n\t\tXLIBSW=\"$XLIBSW -lXext\"\n\t\txss_lib_found=yes\n\nelse case e in #(\n  e)\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for XScreenSaverQueryInfo in -lXss\" >&5\nprintf %s \"checking for XScreenSaverQueryInfo in -lXss... \" >&6; }\nif test ${ac_cv_lib_Xss_XScreenSaverQueryInfo+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lXss -lXext $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.\n   The 'extern \"C\"' is for builds by C++ compilers;\n   although this is not generally supported in C code supporting it here\n   has little cost and some practical benefit (sr 110532).  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar XScreenSaverQueryInfo (void);\nint\nmain (void)\n{\nreturn XScreenSaverQueryInfo ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_Xss_XScreenSaverQueryInfo=yes\nelse case e in #(\n  e) ac_cv_lib_Xss_XScreenSaverQueryInfo=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xss_XScreenSaverQueryInfo\" >&5\nprintf '%s\\n' \"$ac_cv_lib_Xss_XScreenSaverQueryInfo\" >&6; }\nif test \"x$ac_cv_lib_Xss_XScreenSaverQueryInfo\" = xyes\nthen :\n\n\t\t    if test \"$tcl_cv_ld_weak_l\" = yes; then\n\t\t\tXLIBSW=\"$XLIBSW -Wl,-weak-lXss -lXext\"\n\t\t    else\n\t\t\tXLIBSW=\"$XLIBSW -lXss -lXext\"\n\t\t    fi\n\t\t    xss_lib_found=yes\n\nfi\n\n\t     ;;\nesac\nfi\n\n\t ;;\nesac\nfi\n\n    fi\n    if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then\n\nprintf '%s\\n' \"#define HAVE_XSS 1\" >>confdefs.h\n\n    fi\n    CFLAGS=$tk_oldCFlags\n    LIBS=$tk_oldLibs\nfi\n\n#--------------------------------------------------------------------\n#\tFigure out whether \"char\" is unsigned.  If so, set a\n#\t#define for __CHAR_UNSIGNED__.\n#--------------------------------------------------------------------\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether char is unsigned\" >&5\nprintf %s \"checking whether char is unsigned... \" >&6; }\nif test ${ac_cv_c_char_unsigned+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain (void)\n{\nstatic int test_array [1 - 2 * !(((char) -1) < 0)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_c_char_unsigned=no\nelse case e in #(\n  e) ac_cv_c_char_unsigned=yes ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned\" >&5\nprintf '%s\\n' \"$ac_cv_c_char_unsigned\" >&6; }\nif test $ac_cv_c_char_unsigned = yes; then\n  printf '%s\\n' \"#define __CHAR_UNSIGNED__ 1\" >>confdefs.h\n\nfi\n\n\n#--------------------------------------------------------------------\n#\tThe statements below define a collection of symbols related to\n#\tbuilding libtk as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\neval eval \"TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}\"\neval eval \"TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}\"\nif test \"$ac_cv_cygwin\" = \"yes\" -a \"$SHARED_BUILD\" != \"0\"; then\neval \"TK_LIB_FILE=cygtcl9tk${LIB_SUFFIX}\"\nEXTRA_INSTALL_BINARIES='$(INSTALL_LIBRARY) $(patsubst cyg%.dll,lib%.dll.a,${LIB_FILE}) \"$(LIB_INSTALL_DIR)\"'\nelse\neval \"TK_LIB_FILE=libtcl9tk${LIB_SUFFIX}\"\nfi\n\neval \"TK_LIB_FILE=${TK_LIB_FILE}\"\n\n# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed\n# since on some platforms TK_LIB_FILE contains shell escapes.\n\nif test \"${SHARED_BUILD}\" = \"1\" -a \"${SHLIB_SUFFIX}\" != \"\"; then\n    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\${TCL_STUB_LIB_SPEC}\"\n    TCL_STUB_FLAGS=\"-DUSE_TCL_STUBS\"\nfi\n\n# Note:  in the following variable, it's important to use the absolute\n# path name of the Tcl directory rather than \"..\":  this is because\n# AIX remembers this path and will attempt to use it at run-time to look\n# up the Tcl library.\n\ntest -z \"$TK_LIBRARY\" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'\nPRIVATE_INCLUDE_DIR='$(includedir)'\nHTML_DIR='$(DISTDIR)/html'\nTK_PKG_DIR='tk$(VERSION)'\nTK_RSRC_FILE='tk$(VERSION).rsrc'\nWISH_RSRC_FILE='wish$(VERSION).rsrc'\n\nif test \"`uname -s`\" = \"Darwin\" ; then\n\n    if test \"`uname -s`\" = \"Darwin\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking how to package libraries\" >&5\nprintf %s \"checking how to package libraries... \" >&6; }\n\t# Check whether --enable-framework was given.\nif test ${enable_framework+y}\nthen :\n  enableval=$enable_framework; enable_framework=$enableval\nelse case e in #(\n  e) enable_framework=no ;;\nesac\nfi\n\n\tif test $enable_framework = yes; then\n\t    if test $SHARED_BUILD = 0; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be built if --enable-shared is yes\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Frameworks can only be built if --enable-shared is yes\" >&2;}\n\t\tenable_framework=no\n\t    fi\n\t    if test $tcl_corefoundation = no; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be used when CoreFoundation is available\" >&5\nprintf '%s\\n' \"$as_me: WARNING: Frameworks can only be used when CoreFoundation is available\" >&2;}\n\t\tenable_framework=no\n\t    fi\n\tfi\n\tif test $enable_framework = yes; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: framework\" >&5\nprintf '%s\\n' \"framework\" >&6; }\n\t    FRAMEWORK_BUILD=1\n\telse\n\t    if test $SHARED_BUILD = 1; then\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: shared library\" >&5\nprintf '%s\\n' \"shared library\" >&6; }\n\t    else\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: static library\" >&5\nprintf '%s\\n' \"static library\" >&6; }\n\t    fi\n\t    FRAMEWORK_BUILD=0\n\tfi\n    fi\n\n    TK_SHLIB_LD_EXTRAS=\"-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk '{match($0, \"\\\\\\.[0-9]+\"); print substr($0,RSTART,RLENGTH)}'`\"\n    TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -install_name \"${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}\" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk \"/^[0-9a-f]+ . \\.objc/ {print \\$$3}\" > $$f && nm -gjp \"$(TCL_BIN_DIR)\"/$(TCL_STUB_LIB_FILE) | grep ^_[^_] >> $$f && echo $$f)'\n    echo \"$LDFLAGS \" | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -seg1addr 0xb000000'\n    TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -sectcreate __TEXT __info_plist Tk-Info.plist'\n    EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist'\n    EXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -sectcreate __TEXT __credits_html Credits.html'\n    if test \"${SHARED_BUILD}\" = \"0\"; then\n\tEXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -ObjC'\n    fi\n    ac_config_files=\"$ac_config_files Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in Credits.html:../macosx/Credits.html.in\"\n\n    for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS=\"${CFBUNDLELOCALIZATIONS}<string>$l</string>\"; done\n    TK_YEAR=\"`date +%Y`\"\nfi\n\nif test \"$FRAMEWORK_BUILD\" = \"1\" ; then\n\nprintf '%s\\n' \"#define TK_FRAMEWORK 1\" >>confdefs.h\n\n    ac_config_commands=\"$ac_config_commands Tk.framework\"\n\n    LD_LIBRARY_PATH_VAR=\"DYLD_FRAMEWORK_PATH\"\n    if test \"${libdir}\" = '${exec_prefix}/lib'; then\n\tlibdir=\"/Library/Frameworks\"\n    fi\n    TK_LIB_FILE=\"Tk\"\n    TK_LIB_FLAG=\"-framework Tk\"\n    TK_BUILD_LIB_SPEC=\"-F`pwd | sed -e 's/ /\\\\\\\\ /g'` -framework Tk\"\n    TK_LIB_SPEC=\"-F${libdir} -framework Tk\"\n    libdir=\"${libdir}/Tk.framework/Versions/\\${VERSION}\"\n    TK_LIBRARY=\"${libdir}/Resources/Scripts\"\n    TK_PKG_DIR=\"${libdir}/Resources/Scripts\"\n    TK_RSRC_FILE=\"Tk.rsrc\"\n    WISH_RSRC_FILE=\"Wish.rsrc\"\n    includedir=\"${libdir}/Headers\"\n    PRIVATE_INCLUDE_DIR=\"${libdir}/PrivateHeaders\"\n    HTML_DIR=\"${libdir}/Resources/Documentation/Reference/Tk\"\n    EXTRA_INSTALL=\"install-private-headers html-tk\"\n    EXTRA_BUILD_HTML='@ln -fs contents.htm \"$(HTML_INSTALL_DIR)\"/TkTOC.html'\n    EXTRA_INSTALL_BINARIES='@echo \"Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && $(INSTALL_DATA) Tk-Info.plist \"$(LIB_INSTALL_DIR)/Resources/Info.plist\"'\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Credits.html to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && $(INSTALL_DATA) Credits.html \"$(LIB_INSTALL_DIR)/Resources\"'\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing license.terms to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA) \"$(TOP_DIR)/license.terms\" \"$(LIB_INSTALL_DIR)/Resources\"'\n    if test $tk_aqua = yes; then\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Images to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) \"$(MAC_OSX_DIR)/$$i\" \"$(LIB_INSTALL_DIR)/Resources\"; done'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing wish$(VERSION) script to $(INSTALL_ROOT)/'\"${bindir}\"'/\" && $(INSTALL_DATA_DIR) \"$(INSTALL_ROOT)/'\"${bindir}\"'\" && printf > \"$(INSTALL_ROOT)/'\"${bindir}\"'/wish$(VERSION)\" \"#!/bin/sh\\n\\\"\\$$(dirname \\$$0)'\"`eval d=\"${bindir}\"; echo \"$d\" | sed -e 's#/[^/][^/]*#/..#g'`\"'$(bindir)/Wish\\\" \\\"\\$$@\\\"\" && chmod +x \"$(INSTALL_ROOT)/'\"${bindir}\"'/wish$(VERSION)\"'\n\tbindir=\"${libdir}/Resources/Wish.app/Contents/MacOS\"\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Info.plist to $(BIN_INSTALL_DIR)/..\" && $(INSTALL_DATA) Wish-Info.plist \"$(BIN_INSTALL_DIR)/../Info.plist\" && mv -f \"$(BIN_INSTALL_DIR)/wish$(VERSION)\" \"$(BIN_INSTALL_DIR)/Wish\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA_DIR) \"$(BIN_INSTALL_DIR)/../Resources\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && $(INSTALL_DATA) \"$(MAC_OSX_DIR)/Tk.icns\" \"$(BIN_INSTALL_DIR)/../Resources/Wish.icns\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA) \"$(MAC_OSX_DIR)/Wish.sdef\" \"$(BIN_INSTALL_DIR)/../Resources\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Credits.html to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA) Credits.html \"$(BIN_INSTALL_DIR)/../Resources\"'\n    fi\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Finalizing Tk.framework\" && rm -f \"$(LIB_INSTALL_DIR)/../Current\" && ln -s \"$(VERSION)\" \"$(LIB_INSTALL_DIR)/../Current\" && for f in \"$(LIB_FILE)\" tkConfig.sh Resources Headers PrivateHeaders; do rm -f \"$(LIB_INSTALL_DIR)/../../$$f\" && ln -s \"Versions/Current/$$f\" \"$(LIB_INSTALL_DIR)/../..\"; done && f=\"$(STUB_LIB_FILE)\" && rm -f \"$(LIB_INSTALL_DIR)/../../$$f\" && ln -s \"Versions/$(VERSION)/$$f\" \"$(LIB_INSTALL_DIR)/../..\"'\n    # Don't use AC_DEFINE for the following as the framework version define\n    # needs to go into the Makefile even when using autoheader, so that we\n    # can pick up a potential make override of VERSION. Also, don't put this\n    # into CFLAGS as it should not go into tkConfig.sh\n    EXTRA_CC_SWITCHES=\"$EXTRA_CC_SWITCHES\"' -DTK_FRAMEWORK_VERSION=\\\"$(VERSION)\\\"'\nelse\n    if test $tk_aqua = yes; then\n\tEXTRA_INSTALL_BINARIES='@echo \"Installing Images to $(LIB_INSTALL_DIR)/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)\" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) \"$(MAC_OSX_DIR)/$$i\" \"$(LIB_INSTALL_DIR)\"; done'\n    fi\n    eval libdir=\"$libdir\"\n    TK_LIB_FLAG=\"-ltcl9\"\n    if test \"${ac_cv_cygwin}\" = \"yes\" -a \"$SHARED_BUILD\" = \"1\"; then\n\tTK_LIB_FLAG=\"${TK_LIB_FLAG}tk`echo ${TK_VERSION} | tr -d .`\"\n\tTK_BUILD_LIB_SPEC=\"-L\\$(TOP_DIR)/win ${TK_LIB_FLAG}\"\n    else\n\tif test \"${TCL_LIB_VERSIONS_OK}\" = \"ok\"; then\n\t    TK_LIB_FLAG=\"${TK_LIB_FLAG}tk${TK_VERSION}\"\n\telse\n\t    TK_LIB_FLAG=\"${TK_LIB_FLAG}tk`echo ${TK_VERSION} | tr -d .`\"\n\tfi\n\tTK_BUILD_LIB_SPEC=\"-L`pwd | sed -e 's/ /\\\\\\\\ /g'` ${TK_LIB_FLAG}\"\n    fi\n    TK_LIB_SPEC=\"-L${libdir} ${TK_LIB_FLAG}\"\nfi\n\n#--------------------------------------------------------------------\n#\tZipfs support - Tip 430\n#--------------------------------------------------------------------\n# Check whether --enable-zipfs was given.\nif test ${enable_zipfs+y}\nthen :\n  enableval=$enable_zipfs; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=yes ;;\nesac\nfi\n\nif test \"$tcl_ok\" = \"yes\" -a \"x$enable_framework\" != \"xyes\"; then\n    # Put a plausible default for CC_FOR_BUILD in Makefile.\n    if test -z \"$CC_FOR_BUILD\"; then\n      if test \"x$cross_compiling\" = \"xno\"; then\n\tCC_FOR_BUILD='$(CC)'\n      else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for gcc\" >&5\nprintf %s \"checking for gcc... \" >&6; }\n\tif test ${ac_cv_path_cc+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\t    for dir in $search_path ; do\n\t\tfor j in `ls -r $dir/gcc 2> /dev/null` \\\n\t\t\t`ls -r $dir/gcc 2> /dev/null` ; do\n\t\t    if test x\"$ac_cv_path_cc\" = x ; then\n\t\t\tif test -f \"$j\" ; then\n\t\t\t    ac_cv_path_cc=$j\n\t\t\t    break\n\t\t\tfi\n\t\t    fi\n\t\tdone\n\t    done\n\t ;;\nesac\nfi\n\n      fi\n    fi\n\n    # Also set EXEEXT_FOR_BUILD.\n    if test \"x$cross_compiling\" = \"xno\"; then\n      EXEEXT_FOR_BUILD='$(EXEEXT)'\n      OBJEXT_FOR_BUILD='$(OBJEXT)'\n    else\n      OBJEXT_FOR_BUILD='.no'\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for build system executable suffix\" >&5\nprintf %s \"checking for build system executable suffix... \" >&6; }\nif test ${bfd_cv_build_exeext+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) rm -f conftest*\n\t echo 'int main () { return 0; }' > conftest.c\n\t bfd_cv_build_exeext=\n\t ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5\n\t for file in conftest.*; do\n\t   case $file in\n\t   *.c | *.o | *.obj | *.ilk | *.pdb) ;;\n\t   *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;\n\t   esac\n\t done\n\t rm -f conftest*\n\t test x\"${bfd_cv_build_exeext}\" = x && bfd_cv_build_exeext=no ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext\" >&5\nprintf '%s\\n' \"$bfd_cv_build_exeext\" >&6; }\n      EXEEXT_FOR_BUILD=\"\"\n      test x\"${bfd_cv_build_exeext}\" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}\n    fi\n\n\n    MACHER_PROG=\"\"\n    ZIP_PROG=\"\"\n    ZIP_PROG_OPTIONS=\"\"\n    ZIP_PROG_VFSSEARCH=\"\"\n    ZIP_INSTALL_OBJS=\"\"\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for macher\" >&5\nprintf %s \"checking for macher... \" >&6; }\n    if test ${ac_cv_path_macher+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/macher 2> /dev/null` \\\n\t    `ls -r $dir/macher 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_macher\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_macher=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n     ;;\nesac\nfi\n\n    if test -f \"$ac_cv_path_macher\" ; then\n\tMACHER_PROG=\"$ac_cv_path_macher\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $MACHER_PROG\" >&5\nprintf '%s\\n' \"$MACHER_PROG\" >&6; }\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: Macher not found\" >&5\nprintf '%s\\n' \"Macher not found\" >&6; }\n    fi\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for zip\" >&5\nprintf %s \"checking for zip... \" >&6; }\n    if test ${ac_cv_path_zip+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/zip 2> /dev/null` \\\n\t    `ls -r $dir/zip 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_zip\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_zip=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n     ;;\nesac\nfi\n\n    if test -f \"$ac_cv_path_zip\" ; then\n\tZIP_PROG=\"$ac_cv_path_zip\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG\" >&5\nprintf '%s\\n' \"$ZIP_PROG\" >&6; }\n\tZIP_PROG_OPTIONS=\"-rq\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\t# Use standard arguments for zip\n    else\n\t# It is not an error if an installed version of Zip can't be located.\n\t# We can use the locally distributed minizip instead\n\tZIP_PROG=\"./minizip${EXEEXT_FOR_BUILD}\"\n\tZIP_PROG_OPTIONS=\"-o -r\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\tZIP_INSTALL_OBJS=\"minizip${EXEEXT_FOR_BUILD}\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: No zip found on PATH. Building minizip\" >&5\nprintf '%s\\n' \"No zip found on PATH. Building minizip\" >&6; }\n    fi\n\n\n\n\n\n\n\tZIPFS_BUILD=1\n\tTK_ZIP_FILE=libtk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_PATCH_LEVEL}.zip\nelse\n\tZIPFS_BUILD=0\n\tTK_ZIP_FILE=\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for building with zipfs\" >&5\nprintf %s \"checking for building with zipfs... \" >&6; }\nif test \"${ZIPFS_BUILD}\" = 1; then\n    if test \"${SHARED_BUILD}\" = 0; then\n       ZIPFS_BUILD=2;\n\nprintf '%s\\n' \"#define ZIPFS_BUILD 2\" >>confdefs.h\n\n       INSTALL_LIBRARIES=install-demos\n       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n     else\n\nprintf '%s\\n' \"#define ZIPFS_BUILD 1\" >>confdefs.h\n\n       INSTALL_LIBRARIES=install-demos\n       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n    fi\nelse\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nINSTALL_LIBRARIES=install-libraries\nINSTALL_MSGS=install-msgs\nfi\n\n\n\n\n\n#--------------------------------------------------------------------\n#       The statements below define various symbols relating to Tk\n#       stub support.\n#--------------------------------------------------------------------\n\nTK_STUB_LIB_FILE=\"libtkstub.a\"\nTK_STUB_LIB_FLAG=\"-ltkstub\"\neval \"TK_STUB_LIB_DIR=\\\"${libdir}\\\"\"\n\nTK_BUILD_STUB_LIB_SPEC=\"-L`pwd | sed -e 's/ /\\\\\\\\ /g'` ${TK_STUB_LIB_FLAG}\"\nTK_STUB_LIB_SPEC=\"-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}\"\nTK_BUILD_STUB_LIB_PATH=\"`pwd`/${TK_STUB_LIB_FILE}\"\nTK_STUB_LIB_PATH=\"${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}\"\n\neval \"TK_INCLUDE_SPEC=\\\"-I${includedir}\\\"\"\n\n#------------------------------------------------------------------------\n# Demo dir\n#------------------------------------------------------------------------\n\nif test x\"${DEMO_DIR}\" = x\nthen :\n  DEMO_DIR='$(TK_LIBRARY)/demos'\nfi\neval \"TK_DEMO_DIR=\\\"`echo ${DEMO_DIR} | tr '()' '{}'`\\\"\"\n\n\n\nTK_SHARED_BUILD=${SHARED_BUILD}\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\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\n\n\n\n\n\n\nac_config_files=\"$ac_config_files Makefile:../unix/Makefile.in tkConfig.sh:../unix/tkConfig.sh.in tk.pc:../unix/tk.pc.in\"\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# 'ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* 'ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\nac_cache_dump |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test ${\\1+y} || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\n# Transform confdefs.h into DEFS.\n# Protect against shell expansion while executing Makefile rules.\n# Protect against Makefile macro expansion.\n#\n# If the first sed substitution is executed (which looks for macros that\n# take arguments), then branch to the quote section.  Otherwise,\n# look for a macro that doesn't take arguments.\nac_script='\n:mline\n/\\\\$/{\n N\n s,\\\\\\n,,\n b mline\n}\nt clear\n:clear\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t (][^\t (]*([^)]*)\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t ][^\t ]*\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\nb any\n:quote\ns/[][\t `~#$^&*(){}\\\\|;'\\''\"<>?]/\\\\&/g\ns/\\$/$$/g\nH\n:any\n${\n\tg\n\ts/^\\n//\n\ts/\\n/ /g\n\tp\n}\n'\nDEFS=`sed -n \"$ac_script\" confdefs.h`\n\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`printf '%s\\n' \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\nCFLAGS=\"${CFLAGS} ${CPPFLAGS}\"; CPPFLAGS=\"\"\n\n: \"${CONFIG_STATUS=./config.status}\"\ncase $CONFIG_STATUS in #(\n  -*) :\n    CONFIG_STATUS=./$CONFIG_STATUS ;; #(\n  */*) :\n     ;; #(\n  *) :\n    CONFIG_STATUS=./$CONFIG_STATUS ;;\nesac\n\nac_write_fail=0\nac_clean_CONFIG_STATUS='\"$CONFIG_STATUS\"'\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\nprintf '%s\\n' \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >\"$CONFIG_STATUS\" <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as 'sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf '%s\\n' \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf '%s\\n' \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse case e in #(\n  e) as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  } ;;\nesac\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse case e in #(\n  e) as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  } ;;\nesac\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.\n    # In both cases, we have to default to 'cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf '%s\\n' \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_sed_cpp=\"y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_cpp=\"eval sed '$as_sed_cpp'\" # deprecated\n\n# Sed expression to map a string onto a valid variable name.\nas_sed_sh=\"y%*+%pp%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_sh=\"eval sed '$as_sed_sh'\" # deprecated\n\n\nexec 6>&1\n## ------------------------------------- ##\n## Main body of \"$CONFIG_STATUS\" script. ##\n## ------------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x \"$CONFIG_STATUS\" || ac_write_fail=1\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by tk $as_me 9.1, which was\ngenerated by GNU Autoconf 2.73.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\n\n\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\nconfig_commands=\"$ac_config_commands\"\n\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n'$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n\nConfiguration files:\n$config_files\n\nConfiguration commands:\n$config_commands\n\nReport bugs to the package provider.\"\n\n_ACEOF\nac_cs_config=`printf '%s\\n' \"$ac_configure_args\" | sed \"$ac_safe_unquote\"`\nac_cs_config_escaped=`printf '%s\\n' \"$ac_cs_config\" | sed \"s/^ //; s/'/'\\\\\\\\\\\\\\\\''/g\"`\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nac_cs_config='$ac_cs_config_escaped'\nac_cs_version=\"\\\\\ntk config.status 9.1\nconfigured by $0, generated by GNU Autoconf 2.73,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2026 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\ntest -n \"\\$AWK\" || {\n  awk '' </dev/null ||\n    as_fn_error \\$? \"try installing gawk\"\n  AWK=awk\n}\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    printf '%s\\n' \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    printf '%s\\n' \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`printf '%s\\n' \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h |  --help | --hel | -h )\n    printf '%s\\n' \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: '$1'\nTry '$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\printf '%s\\n' \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  printf '%s\\n' \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n#\n# INIT-COMMANDS\n#\nVERSION=${TK_VERSION} && tk_aqua=${tk_aqua}\n\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"Tk-Info.plist\") CONFIG_FILES=\"$CONFIG_FILES Tk-Info.plist:../macosx/Tk-Info.plist.in\" ;;\n    \"Wish-Info.plist\") CONFIG_FILES=\"$CONFIG_FILES Wish-Info.plist:../macosx/Wish-Info.plist.in\" ;;\n    \"Credits.html\") CONFIG_FILES=\"$CONFIG_FILES Credits.html:../macosx/Credits.html.in\" ;;\n    \"Tk.framework\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS Tk.framework\" ;;\n    \"Makefile\") CONFIG_FILES=\"$CONFIG_FILES Makefile:../unix/Makefile.in\" ;;\n    \"tkConfig.sh\") CONFIG_FILES=\"$CONFIG_FILES tkConfig.sh:../unix/tkConfig.sh.in\" ;;\n    \"tk.pc\") CONFIG_FILES=\"$CONFIG_FILES tk.pc:../unix/tk.pc.in\" ;;\n\n  *) as_fn_error $? \"invalid argument: '$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files\n  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to '$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with './config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | sed -n '$='`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | sed -n '$='`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>\"$CONFIG_STATUS\" || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n\neval set X \"  :F $CONFIG_FILES      :C $CONFIG_COMMANDS\"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag '$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain ':'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: '$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`printf '%s\\n' \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is 'configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  printf '%s\\n' \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\nprintf '%s\\n' \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`printf '%s\\n' \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf '%s\\n' \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf '%s\\n' \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\nprintf '%s\\n' \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when '$srcdir' = '.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\nprintf '%s\\n' \"$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n\n\n  :C)  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: executing $ac_file commands\" >&5\nprintf '%s\\n' \"$as_me: executing $ac_file commands\" >&6;}\n ;;\n  esac\n\n\n  case $ac_file$ac_mode in\n    \"Tk.framework\":C) n=Tk &&\n\tf=$n.framework && v=Versions/$VERSION &&\n\trm -rf $f && mkdir -p $f/$v/Resources &&\n\tln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&\n\tln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&\n\tif test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi &&\n\tunset n f v\n     ;;\n\n  esac\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_CONFIG_STATUS=\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  case $CONFIG_STATUS in #(\n  -*) :\n    ac_no_opts=-- ;; #(\n  *) :\n    ac_no_opts= ;;\nesac\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $ac_no_opts \"$CONFIG_STATUS\" $ac_config_status_args ||\n    ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\nprintf '%s\\n' \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n\n\n"
  },
  {
    "path": "unix/configure.ac",
    "content": "#! /bin/bash -norc\ndnl\tThis file is an input file used by the GNU \"autoconf\" program to\ndnl\tgenerate the file \"configure\", which is run during Tk installation\ndnl\tto configure the system for the local environment.\n\nAC_INIT([tk],[9.1])\nAC_PREREQ([2.73])\n\ndnl This is only used when included from macosx/configure.ac\nm4_ifdef([SC_USE_CONFIG_HEADERS], [\n    AC_CONFIG_HEADERS([tkConfig.h:../unix/tkConfig.h.in])\n    AC_CONFIG_COMMANDS_PRE([DEFS=\"-DHAVE_TK_CONFIG_H  -imacros tkConfig.h\"])\n    AH_TOP([\n    #ifndef _TKCONFIG\n    #define _TKCONFIG])\n    AH_BOTTOM([\n    /* Undef unused package specific autoheader defines so that we can\n     * include both tclConfig.h and tkConfig.h at the same time: */\n    /* override */ #undef PACKAGE_NAME\n    /* override */ #undef PACKAGE_TARNAME\n    /* override */ #undef PACKAGE_VERSION\n    /* override */ #undef PACKAGE_STRING\n    #endif /* _TKCONFIG */])\n])\n\nTK_VERSION=9.1\nTK_MAJOR_VERSION=9\nTK_MINOR_VERSION=1\nTK_PATCH_LEVEL=\"a2\"\nVERSION=${TK_VERSION}\nLOCALES=\"cs da de el en en_gb eo es fr hu it nl pl pt ru sv\"\n\n#--------------------------------------------------------------------\n# Find and load the tclConfig.sh file\n#--------------------------------------------------------------------\n\nSC_PATH_TCLCONFIG\nSC_LOAD_TCLCONFIG\n\nif test \"${TCL_MAJOR_VERSION}\" -lt 9 ; then\n    AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 9.0+\nFound config for Tcl ${TCL_VERSION}])\nfi\n\nSC_PROG_TCLSH\nSC_BUILD_TCLSH\n\n#------------------------------------------------------------------------\n# Handle the --prefix=... option\n#------------------------------------------------------------------------\n\nif test \"${prefix}\" = \"NONE\"; then\n    prefix=\"$TCL_PREFIX\"\nfi\nif test \"${exec_prefix}\" = \"NONE\"; then\n    exec_prefix=$prefix\nfi\n# Make sure srcdir is fully qualified!\nsrcdir=\"`cd \"$srcdir\" ; pwd`\"\nTK_SRC_DIR=\"`cd \"$srcdir\"/..; pwd`\"\n\n#------------------------------------------------------------------------\n# Compress and/or soft link the manpages?\n#------------------------------------------------------------------------\n\nSC_CONFIG_MANPAGES\n\n#------------------------------------------------------------------------\n# Standard compiler checks\n#------------------------------------------------------------------------\n\n# If the user did not set CFLAGS, set it now to keep\n# the AC_PROG_CC macro from adding \"-g -O2\".\nif test \"${CFLAGS+set}\" != \"set\" ; then\n    CFLAGS=\"\"\nfi\n\nAC_PROG_CC\nAC_C_INLINE\n\n#------------------------------------------------------------------------\n# If we're using GCC, see if the compiler understands -pipe.  If so, use it.\n# It makes compiling go faster.  (This is only a performance feature.)\n#------------------------------------------------------------------------\n\nif test -z \"$no_pipe\" && test -n \"$GCC\"; then\n    AC_CACHE_CHECK([if the compiler understands -pipe],\n\ttcl_cv_cc_pipe, [\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -pipe\"\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no])\n\tCFLAGS=$hold_cflags])\n    if test $tcl_cv_cc_pipe = yes; then\n\tCFLAGS=\"$CFLAGS -pipe\"\n    fi\nfi\n\n#------------------------------------------------------------------------\n# Embedded configuration information, encoding to use for the values, TIP #59\n#------------------------------------------------------------------------\n\nSC_TCL_CFG_ENCODING\n\nSC_ENABLE_SHARED\n\n#--------------------------------------------------------------------\n# The statements below define a collection of compile flags.  This\n# macro depends on the value of SHARED_BUILD, and should be called\n# after SC_ENABLE_SHARED checks the configure switches.\n#--------------------------------------------------------------------\n\nSC_CONFIG_CFLAGS\n\nSC_ENABLE_SYMBOLS\n\n#--------------------------------------------------------------------\n#\tDetect what compiler flags to set for 64-bit support.\n#--------------------------------------------------------------------\n\nSC_TCL_EARLY_FLAGS\n\nSC_TCL_64BIT_FLAGS\n\n#--------------------------------------------------------------------\n#\tCheck endianness because we can optimize some operations\n#--------------------------------------------------------------------\n\nAC_C_BIGENDIAN(,,,[#])\n\n#------------------------------------------------------------------------\n# If Tcl and Tk are installed in different places, adjust the library\n# search path to reflect this.\n#------------------------------------------------------------------------\n\nLIB_RUNTIME_DIR='$(libdir)'\n\nif test \"$TCL_EXEC_PREFIX\" != \"$exec_prefix\"; then\n    LIB_RUNTIME_DIR=\"${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib\"\nfi\n\nif test \"$TCL_PREFIX\" != \"$prefix\"; then\n    AC_MSG_WARN([\n\tDifferent --prefix selected for Tk and Tcl!\n\t[[package require tk]] may not work correctly in tclsh.])\nfi\n\n#--------------------------------------------------------------------\n#\tInclude sys/select.h if it exists and if it supplies things\n#\tthat appear to be useful and aren't already in sys/types.h.\n#\tThis appears to be true only on the RS/6000 under AIX.  Some\n#\tsystems like OSF/1 have a sys/select.h that's of no use, and\n#\tother systems like SCO UNIX have a sys/select.h that's\n#\tpernicious.  If \"fd_set\" isn't defined anywhere then set a\n#\tspecial flag.\n#--------------------------------------------------------------------\n\nAC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[fd_set readMask, writeMask;]])],[tcl_cv_type_fd_set=yes],[tcl_cv_type_fd_set=no])])\ntk_ok=$tcl_cv_type_fd_set\nif test $tk_ok = no; then\n    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [\n\tAC_EGREP_HEADER(fd_mask, sys/select.h,\n\t     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])\n    if test $tcl_cv_grep_fd_mask = present; then\n\tAC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])\n\ttk_ok=yes\n    fi\nfi\nif test $tk_ok = no; then\n    AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])\nfi\n\n#------------------------------------------------------------------------------\n#       Find out all about time handling differences.\n#------------------------------------------------------------------------------\n\nAC_CHECK_HEADERS_ONCE([sys/time.h])\n\n#--------------------------------------------------------------------\n#\tCheck for various typedefs and provide substitutes if\n#\tthey don't exist.\n#--------------------------------------------------------------------\n\nAC_TYPE_MODE_T\nAC_TYPE_PID_T\nAC_TYPE_SIZE_T\n\nAC_CHECK_TYPES([intptr_t, uintptr_t],,,[[\n#include <stdint.h>\n]])\n\n#-------------------------------------------\n#     In OS/390 struct pwd has no pw_gecos field\n#-------------------------------------------\n\nAC_CACHE_CHECK([pw_gecos in struct pwd], tcl_cv_pwd_pw_gecos, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <pwd.h>]], [[struct passwd pwd; (void)pwd.pw_gecos;]])],[tcl_cv_pwd_pw_gecos=yes],[tcl_cv_pwd_pw_gecos=no])])\nif test $tcl_cv_pwd_pw_gecos = yes; then\n    AC_DEFINE(HAVE_PW_GECOS, 1, [Does struct password have a pw_gecos field?])\nfi\n\n#--------------------------------------------------------------------\n#\tOn Mac OS X, we can build either with X11 or with Aqua\n#--------------------------------------------------------------------\n\nif test \"`uname -s`\" = \"Darwin\" ; then\n    AC_MSG_CHECKING([whether to use Aqua])\n    AC_ARG_ENABLE(aqua,\n\tAS_HELP_STRING([--enable-aqua=yes|no],\n\t    [use Aqua windowingsystem on Mac OS X (default: no)]),\n\t[tk_aqua=$enableval], [tk_aqua=no])\n    if test $tk_aqua = yes -o $tk_aqua = cocoa; then\n\ttk_aqua=yes\n\tif test $tcl_corefoundation = no; then\n\t    AC_MSG_WARN([Aqua can only be used when CoreFoundation is available])\n\t    tk_aqua=no\n\tfi\n\tif test ! -d /System/Library/Frameworks/Cocoa.framework; then\n\t    AC_MSG_WARN([Aqua can only be used when Cocoa is available])\n\t    tk_aqua=no\n\tfi\n\tif test \"`uname -r | awk -F. '{print [$]1}'`\" -lt 9; then\n\t    AC_MSG_WARN([Aqua requires Mac OS X 10.5 or later])\n\t    tk_aqua=no\n\tfi\n    fi\n    AC_MSG_RESULT([$tk_aqua])\n    if test $tk_aqua = no; then\n\t# check if weak linking whole libraries is possible.\n\tAC_CACHE_CHECK([if ld accepts -weak-l flag], tcl_cv_ld_weak_l, [\n\t    hold_ldflags=$LDFLAGS\n\t    LDFLAGS=\"$LDFLAGS -Wl,-weak-lm\"\n\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]], [[double f = sin(1.0);]])],\n\t    [tcl_cv_ld_weak_l=yes],[tcl_cv_ld_weak_l=no])\n\t    LDFLAGS=$hold_ldflags])\n    fi\n    AC_CHECK_HEADERS(AvailabilityMacros.h)\nelse\n    tk_aqua=no\nfi\n\nif test $tk_aqua = yes; then\n    AC_DEFINE(MAC_OSX_TK, 1, [Are we building TkAqua?])\n    LIBS=\"$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore -framework Security -framework CoreGraphics\"\n    if test -d \"/System/Library/Frameworks/UniformTypeIdentifiers.framework\"; then\n\tLIBS=\"$LIBS -weak_framework UniformTypeIdentifiers\"\n    fi\n    EXTRA_CC_SWITCHES='-x objective-c'\n    TK_WINDOWINGSYSTEM=AQUA\n    if test -n \"${enable_symbols}\" -a \"${enable_symbols}\" != no; then\n\tAC_DEFINE(TK_MAC_DEBUG, 1, [Are TkAqua debug messages enabled?])\n    fi\nelse\n    #--------------------------------------------------------------------\n    #\tLocate the X11 header files and the X11 library archive.  Try\n    #\tthe ac_path_x macro first, but if it doesn't find the X stuff\n    #\t(e.g. because there's no xmkmf program) then check through\n    #\ta list of possible directories.  Under some conditions the\n    #\tautoconf macro will return an include directory that contains\n    #\tno include files, so double-check its result just to be safe.\n    #--------------------------------------------------------------------\n\n    SC_PATH_X\n    TK_WINDOWINGSYSTEM=X11\nfi\n\n#--------------------------------------------------------------------\n#\tVarious manipulations on the search path used at runtime to\n#\tfind shared libraries:\n#\t1. If the X library binaries are in a non-standard directory,\n#\t   add the X library location into that search path.\n#\t2. On systems such as AIX and Ultrix that use \"-L\" as the\n#\t   search path option, colons cannot be used to separate\n#\t   directories from each other. Change colons to \" -L\".\n#\t3. Create two sets of search flags, one for use in cc lines\n#\t   and the other for when the linker is invoked directly.  In\n#\t   the second case, '-Wl,' must be stripped off and commas must\n#\t   be replaced by spaces.\n#--------------------------------------------------------------------\n\nif test \"x${x_libraries}\" != \"x\"; then\n  if test \"x${x_libraries}\" != \"xNONE\"; then\n    LIB_RUNTIME_DIR=\"${LIB_RUNTIME_DIR}:${x_libraries}\"\n  fi\nfi\nif test \"${TCL_LD_SEARCH_FLAGS}\" = '-L${LIB_RUNTIME_DIR}'; then\n    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for the existence of various libraries.  The order here\n#\tis important, so that then end up in the right order in the\n#\tcommand line generated by make.  The -lsocket and -lnsl libraries\n#\trequire a couple of special tricks:\n#\t1. Use \"connect\" and \"accept\" to check for -lsocket, and\n#\t   \"gethostbyname\" to check for -lnsl.\n#\t2. Use each function name only once:  can't redo a check because\n#\t   autoconf caches the results of the last check and won't redo it.\n#\t3. Use -lnsl and -lsocket only if they supply procedures that\n#\t   aren't already present in the normal libraries.  This is because\n#\t   IRIX 5.2 has libraries, but they aren't needed and they're\n#\t   bogus:  they goof up name resolution if used.\n#\t4. On some SVR4 systems, can't use -lsocket without -lnsl too.\n#\t   To get around this problem, check for both libraries together\n#\t   if -lsocket doesn't work by itself.\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    AC_CHECK_LIB(Xbsd, main, [LIBS=\"$LIBS -lXbsd\"])\nfi\n\n#--------------------------------------------------------------------\n# One more check related to the X libraries.  The standard releases\n# of Ultrix don't support the \"xauth\" mechanism, so send won't work\n# unless TK_NO_SECURITY is defined.  However, there are usually copies\n# of the MIT X server available as well, which do support xauth.\n# Check for the MIT stuff and use it if it exists.\n#\n# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1)\n# because it can't deal with the \"-\" in the library name.\n#--------------------------------------------------------------------\n\nif test -d /usr/include/mit -a $tk_aqua = no; then\n    AC_MSG_CHECKING([MIT X libraries])\n    tk_oldCFlags=$CFLAGS\n    CFLAGS=\"$CFLAGS -I/usr/include/mit\"\n    tk_oldLibs=$LIBS\n    LIBS=\"$LIBS -lX11-mit\"\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n\t#include <X11/Xlib.h>\n    ]], [[\n\tXOpenDisplay(0);\n    ]])],[\n\tAC_MSG_RESULT([yes])\n\tXLIBSW=\"-lX11-mit\"\n\tXINCLUDES=\"-I/usr/include/mit\"\n    ],[AC_MSG_RESULT(no)])\n    CFLAGS=$tk_oldCFlags\n    LIBS=$tk_oldLibs\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for freetype / fontconfig / Xft support and Bidirectional text\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n\n    #--------------------------------------------------------------------\n    # --enable-xft (default: yes)\n    #--------------------------------------------------------------------\n    AC_MSG_CHECKING([whether to use xft])\n    AC_ARG_ENABLE(xft,\n\tAS_HELP_STRING([--enable-xft],\n\t    [use freetype/fontconfig/xft for antialiased fonts (default: yes)]),\n\t[enable_xft=$enableval], [enable_xft=\"yes\"])\n\n    XFT_CFLAGS=\"\"\n    XFT_LIBS=\"\"\n\n    if test \"$enable_xft\" = \"no\" ; then\n\tAC_MSG_RESULT([no])\n    else\n\tfound_xft=\"yes\"\n\n\tXFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft=\"no\"\n\tXFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft=\"no\"\n\tif test \"$found_xft\" = \"no\" ; then\n\t    found_xft=yes\n\t    XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft=\"no\"\n\t    XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft=\"no\"\n\tfi\n\n\tAC_MSG_RESULT([$found_xft])\n\n\tif test \"$found_xft\" = \"yes\" ; then\n\t    tk_oldCFlags=$CFLAGS\n\t    CFLAGS=\"$CFLAGS $XINCLUDES $XFT_CFLAGS\"\n\t    tk_oldLibs=$LIBS\n\t    LIBS=\"$tk_oldLibs $XFT_LIBS $XLIBSW\"\n\n\t    AC_CHECK_HEADER(X11/Xft/Xft.h, [], [found_xft=no], [#include <X11/Xlib.h>])\n\n\t    if test \"$found_xft\" = \"yes\" ; then\n\t\tAC_CHECK_LIB(Xft, XftFontOpen, [], [found_xft=no])\n\t    fi\n\n\t    if test \"$found_xft\" = \"yes\" ; then\n\t\tLIBS=\"$tk_oldLibs $XFT_LIBS $XLIBSW -lfontconfig\"\n\t\tAC_CHECK_LIB(fontconfig, FcFontSort, [\n\t\t    XFT_LIBS=\"$XFT_LIBS -lfontconfig\"\n\t\t], [])\n\t    fi\n\n\t    CFLAGS=$tk_oldCFlags\n\t    LIBS=$tk_oldLibs\n\tfi\n\n\tif test \"$found_xft\" = \"no\" ; then\n\t    if test \"$enable_xft\" = \"yes\" ; then\n\t\tAC_MSG_WARN([Can't find xft configuration or xft is unusable -- falling back to classic fonts])\n\t    fi\n\t    enable_xft=no\n\t    XFT_CFLAGS=\"\"\n\t    XFT_LIBS=\"\"\n\telse\n\t    enable_xft=yes\n\tfi\n    fi\n\n    AC_SUBST(XFT_CFLAGS)\n    AC_SUBST(XFT_LIBS)\n\n    #--------------------------------------------------------------------\n    # --enable-bidi  (HarfBuzz is required only when enabled)\n    #--------------------------------------------------------------------\n    AC_MSG_CHECKING([whether to enable bidirectional (Bidi) text support])\n    AC_ARG_ENABLE(bidi,\n\tAS_HELP_STRING([--enable-bidi],\n\t    [enable bidirectional/RTL text support using SheenBidi + HarfBuzz (forces --enable-xft=yes)]),\n\t[enable_bidi=$enableval], [enable_bidi=\"no\"])\n\n    if test \"$enable_bidi\" = \"yes\"; then\n\tAC_MSG_RESULT([yes (forces Xft on)])\n\tif test \"$enable_xft\" = \"no\"; then\n\t   AC_MSG_NOTICE([--enable-bidi requested: enabling Xft as well])\n\t   enable_xft=yes\n\tfi\n\n\tBIDI_CFLAGS=\"-I${TK_SRC_DIR}/unix/bidi/Headers \\\n                     -I${TK_SRC_DIR}/unix/bidi/Source \\\n                     -I${TK_SRC_DIR}/unix/bidi \\\n                     -DSB_CONFIG_UNITY -DSB_CONFIG_EXPERIMENTAL_TEXT_API -w\"\n\tAC_DEFINE(HAVE_BIDI, 1, [Define to 1 if bidirectional text support is enabled])\n\tUNIX_FONT_OBJS=\"tkUnixBidiFont.o SheenBidi.o\"\n\n        #--------------------------------------------------------------------\n        # HarfBuzz - HARD DEPENDENCY only when --enable-bidi=yes\n        #--------------------------------------------------------------------\n        AC_MSG_CHECKING([for HarfBuzz (required for --enable-bidi)])\n        if pkg-config --exists harfbuzz; then\n            HB_CFLAGS=`pkg-config --cflags harfbuzz`\n            HB_LIBS=`pkg-config --libs harfbuzz`\n            AC_MSG_RESULT([yes])\n\n            tk_oldCFlags=$CFLAGS\n            tk_oldLibs=$LIBS\n            CFLAGS=\"$CFLAGS $XINCLUDES $XFT_CFLAGS $HB_CFLAGS\"\n            LIBS=\"$tk_oldLibs $XFT_LIBS $HB_LIBS $XLIBSW\"\n\n            AC_CHECK_HEADER(harfbuzz/hb.h, [], [\n                AC_MSG_ERROR([HarfBuzz header <harfbuzz/hb.h> not found])\n            ], [#include <X11/Xlib.h>])\n\n            AC_CHECK_LIB(harfbuzz, hb_buffer_create, [], [\n                AC_MSG_ERROR([HarfBuzz library (libharfbuzz) not found or unusable])\n            ])\n\n            CFLAGS=$tk_oldCFlags\n            LIBS=$tk_oldLibs\n\n            BIDI_CFLAGS=\"$BIDI_CFLAGS $HB_CFLAGS\"\n            AC_SUBST(HB_CFLAGS)\n            AC_SUBST(HB_LIBS)\n        else\n            AC_MSG_ERROR([--enable-bidi requires HarfBuzz development files.\nPlease install the HarfBuzz development package:\n  - Debian/Ubuntu:   sudo apt install libharfbuzz-dev\n  - Fedora/RHEL:     sudo dnf install harfbuzz-devel\n  - Arch:            sudo pacman -S harfbuzz\n  - macOS (Homebrew): brew install harfbuzz])\n        fi\n\n    else\n\tAC_MSG_RESULT([no])\n\tBIDI_CFLAGS=\"\"\n\tHB_CFLAGS=\"\"\n\tHB_LIBS=\"\"\n\tif test \"$enable_xft\" = \"yes\" ; then\n\t   UNIX_FONT_OBJS=\"tkUnixRFont.o\"\n\t   AC_DEFINE(HAVE_XFT, 1, [Have we turned on XFT (antialiased fonts)?])\n\telse\n\t   UNIX_FONT_OBJS=\"tkUnixFont.o\"\n\tfi\n    fi\n\n    AC_SUBST(BIDI_CFLAGS)\n    AC_SUBST(UNIX_FONT_OBJS)\n    AC_SUBST(HB_CFLAGS)\n    AC_SUBST(HB_LIBS)\n\n    # Set font system for pkgconfig\n    if test \"$enable_bidi\" = \"yes\"; then\n\tFONTSYSTEM=\"xft\"\n    elif test \"$enable_xft\" = \"yes\" ; then\n\tFONTSYSTEM=\"xft\"\n    else\n\tFONTSYSTEM=\"core\"\n    fi\n    AC_SUBST(FONTSYSTEM)\n\nelse\n    # Aqua (macOS) path\n    enable_xft=no\n    enable_bidi=no\n    UNIX_FONT_OBJS=\"tkUnixFont.o\"\n    BIDI_CFLAGS=\"\"\n    HB_CFLAGS=\"\"\n    HB_LIBS=\"\"\n    FONTSYSTEM=\"core\"\n    AC_SUBST(FONTSYSTEM)\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for libcups support\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    AC_MSG_CHECKING([whether to use libcups])\n    AC_ARG_ENABLE(libcups,\n\tAS_HELP_STRING([--enable-libcups],\n\t    [use libcups (default: on)]),\n\t[enable_libcups=$enableval], [enable_libcups=\"default\"])\n    CUPS_CFLAGS=\"\"\n    CUPS_LIBS=\"\"\n    if test \"$enable_libcups\" = \"no\" ; then\n\tAC_MSG_RESULT([$enable_libcups])\n    else\n\tfound_cups=`cups-config 2>/dev/null`\n\tif test \"$found_cups\" = \"\"; then\n\t    found_cups=no\n\telse\n\t    found_cups=yes\n\t    CUPS_CFLAGS=\"-DHAVE_CUPS\"\n\t    CUPS_LIBS=`cups-config --libs`\n\tfi\n\tAC_MSG_RESULT([$found_cups])\n\tif test \"$found_cups\" = \"yes\" ; then\n\t    tk_oldCFlags=$CFLAGS\n\t    CFLAGS=\"$CFLAGS $XINCLUDES $CUPS_CFLAGS\"\n\t    tk_oldLibs=$LIBS\n\t    LIBS=\"$tk_oldLibs $CUPS_LIBS $XLIBSW\"\n\t    AC_CHECK_HEADER(cups/cups.h, [], [\n\t\tfound_cups=no\n\t\tCUPS_CFLAGS=\"\"\n\t\tCUPS_LIBS=\"\"\n\t    ],[#include <cups/cups.h>])\n\t    CFLAGS=$tk_oldCFlags\n\t    LIBS=$tk_oldLibs\n\tfi\n    fi\n    AC_SUBST(CUPS_CFLAGS)\n    AC_SUBST(CUPS_LIBS)\nfi\n\n#--------------------------------------------------------------------\n#\tCheck for Atk support\n#--------------------------------------------------------------------\n\nif test \"$tk_aqua\" = no; then\n  AC_MSG_CHECKING([for ATK and Atk-bridge])\n  if pkg-config --exists atk && pkg-config --exists atk-bridge-2.0; then\n    AC_MSG_RESULT([yes])\n    ATK_CFLAGS=\"`pkg-config --cflags atk atk-bridge-2.0`\"\n    ATK_LIBS=\"`pkg-config --libs atk atk-bridge-2.0`\"\n    AC_DEFINE([HAVE_ATK], [1], [Define if ATK and Atk-bridge are available])\n  else\n    AC_MSG_RESULT([no])\n    ATK_CFLAGS=\"\"\n    ATK_LIBS=\"\"\n  fi\n  AC_SUBST([ATK_CFLAGS])\n  AC_SUBST([ATK_LIBS])\nfi\n\n#--------------------------------------------------------------------\n# XXX Do this last.\n# It might modify XLIBSW which could affect other tests.\n#\n# Check whether the header and library for the XScreenSaver\n# extension are available, and set HAVE_XSS if so.\n# XScreenSaver is needed for Tk_GetUserInactiveTime().\n#--------------------------------------------------------------------\n\nif test $tk_aqua = no; then\n    tk_oldCFlags=$CFLAGS\n    CFLAGS=\"$CFLAGS $XINCLUDES\"\n    tk_oldLibs=$LIBS\n    LIBS=\"$tk_oldLibs $XLIBSW\"\n    xss_header_found=no\n    xss_lib_found=no\n    AC_MSG_CHECKING([whether to try to use XScreenSaver])\n    AC_ARG_ENABLE(xss,\n\tAS_HELP_STRING([--enable-xss],\n\t    [use XScreenSaver for activity timer (default: on)]),\n\t[enable_xss=$enableval], [enable_xss=yes])\n    if test \"$enable_xss\" = \"no\" ; then\n\tAC_MSG_RESULT([$enable_xss])\n    else\n\tAC_MSG_RESULT([$enable_xss])\n\tAC_CHECK_HEADER(X11/extensions/scrnsaver.h, [\n\t    xss_header_found=yes\n\t],,[#include <X11/Xlib.h>])\n\tAC_CHECK_FUNC(XScreenSaverQueryInfo,,[\n\t    AC_CHECK_LIB(Xext, XScreenSaverQueryInfo, [\n\t\tXLIBSW=\"$XLIBSW -lXext\"\n\t\txss_lib_found=yes\n\t    ], [\n\t\tAC_CHECK_LIB(Xss, XScreenSaverQueryInfo, [\n\t\t    if test \"$tcl_cv_ld_weak_l\" = yes; then\n\t\t\tXLIBSW=\"$XLIBSW -Wl,-weak-lXss -lXext\"\n\t\t    else\n\t\t\tXLIBSW=\"$XLIBSW -lXss -lXext\"\n\t\t    fi\n\t\t    xss_lib_found=yes\n\t\t],, -lXext)\n\t    ])\n\t])\n    fi\n    if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then\n\tAC_DEFINE(HAVE_XSS, 1, [Is XScreenSaver available?])\n    fi\n    CFLAGS=$tk_oldCFlags\n    LIBS=$tk_oldLibs\nfi\n\n#--------------------------------------------------------------------\n#\tFigure out whether \"char\" is unsigned.  If so, set a\n#\t#define for __CHAR_UNSIGNED__.\n#--------------------------------------------------------------------\n\nAC_C_CHAR_UNSIGNED\n\n#--------------------------------------------------------------------\n#\tThe statements below define a collection of symbols related to\n#\tbuilding libtk as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\neval eval \"TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}\"\neval eval \"TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}\"\nif test \"$ac_cv_cygwin\" = \"yes\" -a \"$SHARED_BUILD\" != \"0\"; then\neval \"TK_LIB_FILE=cygtcl9tk${LIB_SUFFIX}\"\nEXTRA_INSTALL_BINARIES='$(INSTALL_LIBRARY) $(patsubst cyg%.dll,lib%.dll.a,${LIB_FILE}) \"$(LIB_INSTALL_DIR)\"'\nelse\neval \"TK_LIB_FILE=libtcl9tk${LIB_SUFFIX}\"\nfi\n\neval \"TK_LIB_FILE=${TK_LIB_FILE}\"\n\n# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed\n# since on some platforms TK_LIB_FILE contains shell escapes.\n\nif test \"${SHARED_BUILD}\" = \"1\" -a \"${SHLIB_SUFFIX}\" != \"\"; then\n    SHLIB_LD_LIBS=\"${SHLIB_LD_LIBS} \\${TCL_STUB_LIB_SPEC}\"\n    TCL_STUB_FLAGS=\"-DUSE_TCL_STUBS\"\nfi\n\n# Note:  in the following variable, it's important to use the absolute\n# path name of the Tcl directory rather than \"..\":  this is because\n# AIX remembers this path and will attempt to use it at run-time to look\n# up the Tcl library.\n\ntest -z \"$TK_LIBRARY\" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'\nPRIVATE_INCLUDE_DIR='$(includedir)'\nHTML_DIR='$(DISTDIR)/html'\nTK_PKG_DIR='tk$(VERSION)'\nTK_RSRC_FILE='tk$(VERSION).rsrc'\nWISH_RSRC_FILE='wish$(VERSION).rsrc'\n\nif test \"`uname -s`\" = \"Darwin\" ; then\n    SC_ENABLE_FRAMEWORK\n    TK_SHLIB_LD_EXTRAS=\"-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk ['{match($0, \"\\\\\\.[0-9]+\"); print substr($0,RSTART,RLENGTH)}']`\"\n    TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -install_name \"${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}\" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk \"/^[[0-9a-f]]+ . \\.objc/ {print \\$$3}\" > $$f && nm -gjp \"$(TCL_BIN_DIR)\"/$(TCL_STUB_LIB_FILE) | grep ^_[[^_]] >> $$f && echo $$f)'\n    echo \"$LDFLAGS \" | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -seg1addr 0xb000000'\n    TK_SHLIB_LD_EXTRAS=\"${TK_SHLIB_LD_EXTRAS}\"' -sectcreate __TEXT __info_plist Tk-Info.plist'\n    EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist'\n    EXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -sectcreate __TEXT __credits_html Credits.html'\n    if test \"${SHARED_BUILD}\" = \"0\"; then\n\tEXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -ObjC'\n    fi\n    AC_CONFIG_FILES([Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in Credits.html:../macosx/Credits.html.in])\n    for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS=\"${CFBUNDLELOCALIZATIONS}<string>$l</string>\"; done\n    TK_YEAR=\"`date +%Y`\"\nfi\n\nif test \"$FRAMEWORK_BUILD\" = \"1\" ; then\n    AC_DEFINE(TK_FRAMEWORK, 1, [Is Tk built as a framework?])\n    AC_CONFIG_COMMANDS([Tk.framework], [n=Tk &&\n\tf=$n.framework && v=Versions/$VERSION &&\n\trm -rf $f && mkdir -p $f/$v/Resources &&\n\tln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&\n\tln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&\n\tif test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi &&\n\tunset n f v\n    ], VERSION=${TK_VERSION} && tk_aqua=${tk_aqua})\n    LD_LIBRARY_PATH_VAR=\"DYLD_FRAMEWORK_PATH\"\n    if test \"${libdir}\" = '${exec_prefix}/lib'; then\n\tlibdir=\"/Library/Frameworks\"\n    fi\n    TK_LIB_FILE=\"Tk\"\n    TK_LIB_FLAG=\"-framework Tk\"\n    TK_BUILD_LIB_SPEC=\"-F`pwd | sed -e 's/ /\\\\\\\\ /g'` -framework Tk\"\n    TK_LIB_SPEC=\"-F${libdir} -framework Tk\"\n    libdir=\"${libdir}/Tk.framework/Versions/\\${VERSION}\"\n    TK_LIBRARY=\"${libdir}/Resources/Scripts\"\n    TK_PKG_DIR=\"${libdir}/Resources/Scripts\"\n    TK_RSRC_FILE=\"Tk.rsrc\"\n    WISH_RSRC_FILE=\"Wish.rsrc\"\n    includedir=\"${libdir}/Headers\"\n    PRIVATE_INCLUDE_DIR=\"${libdir}/PrivateHeaders\"\n    HTML_DIR=\"${libdir}/Resources/Documentation/Reference/Tk\"\n    EXTRA_INSTALL=\"install-private-headers html-tk\"\n    EXTRA_BUILD_HTML='@ln -fs contents.htm \"$(HTML_INSTALL_DIR)\"/TkTOC.html'\n    EXTRA_INSTALL_BINARIES='@echo \"Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && $(INSTALL_DATA) Tk-Info.plist \"$(LIB_INSTALL_DIR)/Resources/Info.plist\"'\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Credits.html to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && $(INSTALL_DATA) Credits.html \"$(LIB_INSTALL_DIR)/Resources\"'\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing license.terms to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA) \"$(TOP_DIR)/license.terms\" \"$(LIB_INSTALL_DIR)/Resources\"'\n    if test $tk_aqua = yes; then\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Images to $(LIB_INSTALL_DIR)/Resources/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)/Resources\" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) \"$(MAC_OSX_DIR)/$$i\" \"$(LIB_INSTALL_DIR)/Resources\"; done'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing wish$(VERSION) script to $(INSTALL_ROOT)/'\"${bindir}\"'/\" && $(INSTALL_DATA_DIR) \"$(INSTALL_ROOT)/'\"${bindir}\"'\" && printf > \"$(INSTALL_ROOT)/'\"${bindir}\"'/wish$(VERSION)\" \"#!/bin/sh\\n\\\"\\$$(dirname \\$$0)'\"`eval d=\"${bindir}\"; echo \"$d\" | sed -e 's#/[^/][^/]*#/..#g'`\"'$(bindir)/Wish\\\" \\\"\\$$@\\\"\" && chmod +x \"$(INSTALL_ROOT)/'\"${bindir}\"'/wish$(VERSION)\"'\n\tbindir=\"${libdir}/Resources/Wish.app/Contents/MacOS\"\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Info.plist to $(BIN_INSTALL_DIR)/..\" && $(INSTALL_DATA) Wish-Info.plist \"$(BIN_INSTALL_DIR)/../Info.plist\" && mv -f \"$(BIN_INSTALL_DIR)/wish$(VERSION)\" \"$(BIN_INSTALL_DIR)/Wish\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA_DIR) \"$(BIN_INSTALL_DIR)/../Resources\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && $(INSTALL_DATA) \"$(MAC_OSX_DIR)/Tk.icns\" \"$(BIN_INSTALL_DIR)/../Resources/Wish.icns\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA) \"$(MAC_OSX_DIR)/Wish.sdef\" \"$(BIN_INSTALL_DIR)/../Resources\"'\n\tEXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Installing Credits.html to $(BIN_INSTALL_DIR)/../Resources\" && $(INSTALL_DATA) Credits.html \"$(BIN_INSTALL_DIR)/../Resources\"'\n    fi\n    EXTRA_INSTALL_BINARIES=\"$EXTRA_INSTALL_BINARIES\"' && echo \"Finalizing Tk.framework\" && rm -f \"$(LIB_INSTALL_DIR)/../Current\" && ln -s \"$(VERSION)\" \"$(LIB_INSTALL_DIR)/../Current\" && for f in \"$(LIB_FILE)\" tkConfig.sh Resources Headers PrivateHeaders; do rm -f \"$(LIB_INSTALL_DIR)/../../$$f\" && ln -s \"Versions/Current/$$f\" \"$(LIB_INSTALL_DIR)/../..\"; done && f=\"$(STUB_LIB_FILE)\" && rm -f \"$(LIB_INSTALL_DIR)/../../$$f\" && ln -s \"Versions/$(VERSION)/$$f\" \"$(LIB_INSTALL_DIR)/../..\"'\n    # Don't use AC_DEFINE for the following as the framework version define\n    # needs to go into the Makefile even when using autoheader, so that we\n    # can pick up a potential make override of VERSION. Also, don't put this\n    # into CFLAGS as it should not go into tkConfig.sh\n    EXTRA_CC_SWITCHES=\"$EXTRA_CC_SWITCHES\"' -DTK_FRAMEWORK_VERSION=\\\"$(VERSION)\\\"'\nelse\n    if test $tk_aqua = yes; then\n\tEXTRA_INSTALL_BINARIES='@echo \"Installing Images to $(LIB_INSTALL_DIR)/\" && $(INSTALL_DATA_DIR) \"$(LIB_INSTALL_DIR)\" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) \"$(MAC_OSX_DIR)/$$i\" \"$(LIB_INSTALL_DIR)\"; done'\n    fi\n    eval libdir=\"$libdir\"\n    TK_LIB_FLAG=\"-ltcl9\"\n    if test \"${ac_cv_cygwin}\" = \"yes\" -a \"$SHARED_BUILD\" = \"1\"; then\n\tTK_LIB_FLAG=\"${TK_LIB_FLAG}tk`echo ${TK_VERSION} | tr -d .`\"\n\tTK_BUILD_LIB_SPEC=\"-L\\$(TOP_DIR)/win ${TK_LIB_FLAG}\"\n    else\n\tif test \"${TCL_LIB_VERSIONS_OK}\" = \"ok\"; then\n\t    TK_LIB_FLAG=\"${TK_LIB_FLAG}tk${TK_VERSION}\"\n\telse\n\t    TK_LIB_FLAG=\"${TK_LIB_FLAG}tk`echo ${TK_VERSION} | tr -d .`\"\n\tfi\n\tTK_BUILD_LIB_SPEC=\"-L`pwd | sed -e 's/ /\\\\\\\\ /g'` ${TK_LIB_FLAG}\"\n    fi\n    TK_LIB_SPEC=\"-L${libdir} ${TK_LIB_FLAG}\"\nfi\n\n#--------------------------------------------------------------------\n#\tZipfs support - Tip 430\n#--------------------------------------------------------------------\nAC_ARG_ENABLE(zipfs,\n    AS_HELP_STRING([--enable-zipfs],[build with Zipfs support (default: on)]),\n    [tcl_ok=$enableval], [tcl_ok=yes])\nif test \"$tcl_ok\" = \"yes\" -a \"x$enable_framework\" != \"xyes\"; then\n    AX_CC_FOR_BUILD\n    SC_ZIPFS_SUPPORT\n\tZIPFS_BUILD=1\n\tTK_ZIP_FILE=libtk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_PATCH_LEVEL}.zip\nelse\n\tZIPFS_BUILD=0\n\tTK_ZIP_FILE=\nfi\nAC_MSG_CHECKING([for building with zipfs])\nif test \"${ZIPFS_BUILD}\" = 1; then\n    if test \"${SHARED_BUILD}\" = 0; then\n       ZIPFS_BUILD=2;\n       AC_DEFINE(ZIPFS_BUILD, 2, [Are we building with zipfs enabled?])\n       INSTALL_LIBRARIES=install-demos\n       AC_MSG_RESULT([yes])\n     else\n       AC_DEFINE(ZIPFS_BUILD, 1, [Are we building with zipfs enabled?])\n       INSTALL_LIBRARIES=install-demos\n       AC_MSG_RESULT([yes])\n    fi\nelse\nAC_MSG_RESULT([no])\nINSTALL_LIBRARIES=install-libraries\nINSTALL_MSGS=install-msgs\nfi\nAC_SUBST(ZIPFS_BUILD)\nAC_SUBST(TK_ZIP_FILE)\nAC_SUBST(INSTALL_LIBRARIES)\nAC_SUBST(INSTALL_MSGS)\n\n#--------------------------------------------------------------------\n#       The statements below define various symbols relating to Tk\n#       stub support.\n#--------------------------------------------------------------------\n\nTK_STUB_LIB_FILE=\"libtkstub.a\"\nTK_STUB_LIB_FLAG=\"-ltkstub\"\neval \"TK_STUB_LIB_DIR=\\\"${libdir}\\\"\"\n\nTK_BUILD_STUB_LIB_SPEC=\"-L`pwd | sed -e 's/ /\\\\\\\\ /g'` ${TK_STUB_LIB_FLAG}\"\nTK_STUB_LIB_SPEC=\"-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}\"\nTK_BUILD_STUB_LIB_PATH=\"`pwd`/${TK_STUB_LIB_FILE}\"\nTK_STUB_LIB_PATH=\"${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}\"\n\neval \"TK_INCLUDE_SPEC=\\\"-I${includedir}\\\"\"\n\n#------------------------------------------------------------------------\n# Demo dir\n#------------------------------------------------------------------------\n\nAS_IF([test x\"${DEMO_DIR}\" = x], [DEMO_DIR='$(TK_LIBRARY)/demos'])\neval \"TK_DEMO_DIR=\\\"`echo ${DEMO_DIR} | tr '()' '{}'`\\\"\"\nAC_SUBST(DEMO_DIR)\nAC_SUBST(TK_DEMO_DIR)\n\nTK_SHARED_BUILD=${SHARED_BUILD}\n\nAC_SUBST(TK_VERSION)\nAC_SUBST(TK_MAJOR_VERSION)\nAC_SUBST(TK_MINOR_VERSION)\nAC_SUBST(TK_PATCH_LEVEL)\nAC_SUBST(TK_YEAR)\n\nAC_SUBST(TK_LIB_FILE)\nAC_SUBST(TK_LIB_FLAG)\nAC_SUBST(TK_LIB_SPEC)\nAC_SUBST(TK_STUB_LIB_FILE)\nAC_SUBST(TK_STUB_LIB_FLAG)\nAC_SUBST(TK_STUB_LIB_SPEC)\nAC_SUBST(TK_STUB_LIB_PATH)\nAC_SUBST(TK_INCLUDE_SPEC)\nAC_SUBST(TK_BUILD_STUB_LIB_SPEC)\nAC_SUBST(TK_BUILD_STUB_LIB_PATH)\n\nAC_SUBST(TK_SRC_DIR)\n\nAC_SUBST(TK_SHARED_BUILD)\nAC_SUBST(LD_LIBRARY_PATH_VAR)\n\nAC_SUBST(TK_BUILD_LIB_SPEC)\n\nAC_SUBST(TCL_STUB_FLAGS)\nAC_SUBST(XINCLUDES)\nAC_SUBST(XLIBSW)\nAC_SUBST(LOCALES)\n\nAC_SUBST(TK_WINDOWINGSYSTEM)\nAC_SUBST(TK_PKG_DIR)\nAC_SUBST(TK_LIBRARY)\nAC_SUBST(LIB_RUNTIME_DIR)\nAC_SUBST(PRIVATE_INCLUDE_DIR)\nAC_SUBST(HTML_DIR)\n\nAC_SUBST(EXTRA_CC_SWITCHES)\nAC_SUBST(EXTRA_APP_CC_SWITCHES)\nAC_SUBST(EXTRA_INSTALL)\nAC_SUBST(EXTRA_INSTALL_BINARIES)\nAC_SUBST(EXTRA_BUILD_HTML)\nAC_SUBST(EXTRA_WISH_LIBS)\nAC_SUBST(CFBUNDLELOCALIZATIONS)\n\nAC_SUBST(TK_RSRC_FILE)\nAC_SUBST(WISH_RSRC_FILE)\nAC_SUBST(LIB_RSRC_FILE)\nAC_SUBST(APP_RSRC_FILE)\nAC_SUBST(REZ)\nAC_SUBST(REZ_FLAGS)\n\nAC_SUBST(BIDI_CFLAGS)\nAC_SUBST(HB_CFLAGS)\nAC_SUBST(HB_LIBS)\nAC_SUBST(UNIX_FONT_OBJS)\nAC_SUBST(FONTSYSTEM)\n\nAC_CONFIG_FILES([\n    Makefile:../unix/Makefile.in\n    tkConfig.sh:../unix/tkConfig.sh.in\n    tk.pc:../unix/tk.pc.in\n])\nAC_OUTPUT\n\ndnl Local Variables:\ndnl mode: autoconf\ndnl End:\n"
  },
  {
    "path": "unix/install-sh",
    "content": "#!/bin/sh\n# install - install a program, script, or datafile\n\nscriptversion=2020-11-14.01; # UTC\n\n# This originates from X11R5 (mit/util/scripts/install.sh), which was\n# later released in X11R6 (xc/config/util/install.sh) with the\n# following copyright and license.\n#\n# Copyright (C) 1994 X Consortium\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to\n# deal in the Software without restriction, including without limitation the\n# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n# sell copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-\n# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n#\n# Except as contained in this notice, the name of the X Consortium shall not\n# be used in advertising or otherwise to promote the sale, use or other deal-\n# ings in this Software without prior written authorization from the X Consor-\n# tium.\n#\n#\n# FSF changes to this file are in the public domain.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# 'make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.\n\ntab='\t'\nnl='\n'\nIFS=\" $tab$nl\"\n\n# Set DOITPROG to \"echo\" to test this script.\n\ndoit=${DOITPROG-}\ndoit_exec=${doit:-exec}\n\n# Put in absolute file names if you don't have them in your path;\n# or use environment vars.\n\nchgrpprog=${CHGRPPROG-chgrp}\nchmodprog=${CHMODPROG-chmod}\nchownprog=${CHOWNPROG-chown}\ncmpprog=${CMPPROG-cmp}\ncpprog=${CPPROG-cp}\nmkdirprog=${MKDIRPROG-mkdir}\nmvprog=${MVPROG-mv}\nrmprog=${RMPROG-rm}\nstripprog=${STRIPPROG-strip}\n\nposix_mkdir=\n\n# Desired mode of installed file.\nmode=0755\n\n# Create dirs (including intermediate dirs) using mode 755.\n# This is like GNU 'install' as of coreutils 8.32 (2020).\nmkdir_umask=22\n\nbackupsuffix=\nchgrpcmd=\nchmodcmd=$chmodprog\nchowncmd=\nmvcmd=$mvprog\nrmcmd=\"$rmprog -f\"\nstripcmd=\n\nsrc=\ndst=\ndir_arg=\ndst_arg=\n\ncopy_on_change=false\nis_target_a_directory=possibly\n\nusage=\"\\\nUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE\n   or: $0 [OPTION]... SRCFILES... DIRECTORY\n   or: $0 [OPTION]... -t DIRECTORY SRCFILES...\n   or: $0 [OPTION]... -d DIRECTORIES...\n\nIn the 1st form, copy SRCFILE to DSTFILE.\nIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.\nIn the 4th, create DIRECTORIES.\n\nOptions:\n     --help     display this help and exit.\n     --version  display version info and exit.\n\n  -c            (ignored)\n  -C            install only if different (preserve data modification time)\n  -d            create directories instead of installing files.\n  -g GROUP      $chgrpprog installed files to GROUP.\n  -m MODE       $chmodprog installed files to MODE.\n  -o USER       $chownprog installed files to USER.\n  -p            pass -p to $cpprog.\n  -s            $stripprog installed files.\n  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.\n  -t DIRECTORY  install into DIRECTORY.\n  -T            report an error if DSTFILE is a directory.\n\nEnvironment variables override the default commands:\n  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG\n  RMPROG STRIPPROG\n\nBy default, rm is invoked with -f; when overridden with RMPROG,\nit's up to you to specify -f if you want it.\n\nIf -S is not specified, no backups are attempted.\n\nEmail bug reports to bug-automake@gnu.org.\nAutomake home page: https://www.gnu.org/software/automake/\n\"\n\nwhile test $# -ne 0; do\n  case $1 in\n    -c) ;;\n\n    -C) copy_on_change=true;;\n\n    -d) dir_arg=true;;\n\n    -g) chgrpcmd=\"$chgrpprog $2\"\n        shift;;\n\n    --help) echo \"$usage\"; exit $?;;\n\n    -m) mode=$2\n        case $mode in\n          *' '* | *\"$tab\"* | *\"$nl\"* | *'*'* | *'?'* | *'['*)\n            echo \"$0: invalid mode: $mode\" >&2\n            exit 1;;\n        esac\n        shift;;\n\n    -o) chowncmd=\"$chownprog $2\"\n        shift;;\n\n    -p) cpprog=\"$cpprog -p\";;\n\n    -s) stripcmd=$stripprog;;\n\n    -S) backupsuffix=\"$2\"\n        shift;;\n\n    -t)\n        is_target_a_directory=always\n        dst_arg=$2\n        # Protect names problematic for 'test' and other utilities.\n        case $dst_arg in\n          -* | [=\\(\\)!]) dst_arg=./$dst_arg;;\n        esac\n        shift;;\n\n    -T) is_target_a_directory=never;;\n\n    --version) echo \"$0 $scriptversion\"; exit $?;;\n\n    --) shift\n        break;;\n\n    -*) echo \"$0: invalid option: $1\" >&2\n        exit 1;;\n\n    *)  break;;\n  esac\n  shift\ndone\n\n# We allow the use of options -d and -T together, by making -d\n# take the precedence; this is for compatibility with GNU install.\n\nif test -n \"$dir_arg\"; then\n  if test -n \"$dst_arg\"; then\n    echo \"$0: target directory not allowed when installing a directory.\" >&2\n    exit 1\n  fi\nfi\n\nif test $# -ne 0 && test -z \"$dir_arg$dst_arg\"; then\n  # When -d is used, all remaining arguments are directories to create.\n  # When -t is used, the destination is already specified.\n  # Otherwise, the last argument is the destination.  Remove it from $@.\n  for arg\n  do\n    if test -n \"$dst_arg\"; then\n      # $@ is not empty: it contains at least $arg.\n      set fnord \"$@\" \"$dst_arg\"\n      shift # fnord\n    fi\n    shift # arg\n    dst_arg=$arg\n    # Protect names problematic for 'test' and other utilities.\n    case $dst_arg in\n      -* | [=\\(\\)!]) dst_arg=./$dst_arg;;\n    esac\n  done\nfi\n\nif test $# -eq 0; then\n  if test -z \"$dir_arg\"; then\n    echo \"$0: no input file specified.\" >&2\n    exit 1\n  fi\n  # It's OK to call 'install-sh -d' without argument.\n  # This can happen when creating conditional directories.\n  exit 0\nfi\n\nif test -z \"$dir_arg\"; then\n  if test $# -gt 1 || test \"$is_target_a_directory\" = always; then\n    if test ! -d \"$dst_arg\"; then\n      echo \"$0: $dst_arg: Is not a directory.\" >&2\n      exit 1\n    fi\n  fi\nfi\n\nif test -z \"$dir_arg\"; then\n  do_exit='(exit $ret); exit $ret'\n  trap \"ret=129; $do_exit\" 1\n  trap \"ret=130; $do_exit\" 2\n  trap \"ret=141; $do_exit\" 13\n  trap \"ret=143; $do_exit\" 15\n\n  # Set umask so as not to create temps with too-generous modes.\n  # However, 'strip' requires both read and write access to temps.\n  case $mode in\n    # Optimize common cases.\n    *644) cp_umask=133;;\n    *755) cp_umask=22;;\n\n    *[0-7])\n      if test -z \"$stripcmd\"; then\n        u_plus_rw=\n      else\n        u_plus_rw='% 200'\n      fi\n      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;\n    *)\n      if test -z \"$stripcmd\"; then\n        u_plus_rw=\n      else\n        u_plus_rw=,u+rw\n      fi\n      cp_umask=$mode$u_plus_rw;;\n  esac\nfi\n\nfor src\ndo\n  # Protect names problematic for 'test' and other utilities.\n  case $src in\n    -* | [=\\(\\)!]) src=./$src;;\n  esac\n\n  if test -n \"$dir_arg\"; then\n    dst=$src\n    dstdir=$dst\n    test -d \"$dstdir\"\n    dstdir_status=$?\n    # Don't chown directories that already exist.\n    if test $dstdir_status = 0; then\n      chowncmd=\"\"\n    fi\n  else\n\n    # Waiting for this to be detected by the \"$cpprog $src $dsttmp\" command\n    # might cause directories to be created, which would be especially bad\n    # if $src (and thus $dsttmp) contains '*'.\n    if test ! -f \"$src\" && test ! -d \"$src\"; then\n      echo \"$0: $src does not exist.\" >&2\n      exit 1\n    fi\n\n    if test -z \"$dst_arg\"; then\n      echo \"$0: no destination specified.\" >&2\n      exit 1\n    fi\n    dst=$dst_arg\n\n    # If destination is a directory, append the input filename.\n    if test -d \"$dst\"; then\n      if test \"$is_target_a_directory\" = never; then\n        echo \"$0: $dst_arg: Is a directory\" >&2\n        exit 1\n      fi\n      dstdir=$dst\n      dstbase=`basename \"$src\"`\n      case $dst in\n\t*/) dst=$dst$dstbase;;\n\t*)  dst=$dst/$dstbase;;\n      esac\n      dstdir_status=0\n    else\n      dstdir=`dirname \"$dst\"`\n      test -d \"$dstdir\"\n      dstdir_status=$?\n    fi\n  fi\n\n  case $dstdir in\n    */) dstdirslash=$dstdir;;\n    *)  dstdirslash=$dstdir/;;\n  esac\n\n  obsolete_mkdir_used=false\n\n  if test $dstdir_status != 0; then\n    case $posix_mkdir in\n      '')\n        # With -d, create the new directory with the user-specified mode.\n        # Otherwise, rely on $mkdir_umask.\n        if test -n \"$dir_arg\"; then\n          mkdir_mode=-m$mode\n        else\n          mkdir_mode=\n        fi\n\n        posix_mkdir=false\n\t# The $RANDOM variable is not portable (e.g., dash).  Use it\n\t# here however when possible just to lower collision chance.\n\ttmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$\n\n\ttrap '\n\t  ret=$?\n\t  rmdir \"$tmpdir/a/b\" \"$tmpdir/a\" \"$tmpdir\" 2>/dev/null\n\t  exit $ret\n\t' 0\n\n\t# Because \"mkdir -p\" follows existing symlinks and we likely work\n\t# directly in world-writeable /tmp, make sure that the '$tmpdir'\n\t# directory is successfully created first before we actually test\n\t# 'mkdir -p'.\n\tif (umask $mkdir_umask &&\n\t    $mkdirprog $mkdir_mode \"$tmpdir\" &&\n\t    exec $mkdirprog $mkdir_mode -p -- \"$tmpdir/a/b\") >/dev/null 2>&1\n\tthen\n\t  if test -z \"$dir_arg\" || {\n\t       # Check for POSIX incompatibilities with -m.\n\t       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or\n\t       # other-writable bit of parent directory when it shouldn't.\n\t       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.\n\t       test_tmpdir=\"$tmpdir/a\"\n\t       ls_ld_tmpdir=`ls -ld \"$test_tmpdir\"`\n\t       case $ls_ld_tmpdir in\n\t\t d????-?r-*) different_mode=700;;\n\t\t d????-?--*) different_mode=755;;\n\t\t *) false;;\n\t       esac &&\n\t       $mkdirprog -m$different_mode -p -- \"$test_tmpdir\" && {\n\t\t ls_ld_tmpdir_1=`ls -ld \"$test_tmpdir\"`\n\t\t test \"$ls_ld_tmpdir\" = \"$ls_ld_tmpdir_1\"\n\t       }\n\t     }\n\t  then posix_mkdir=:\n\t  fi\n\t  rmdir \"$tmpdir/a/b\" \"$tmpdir/a\" \"$tmpdir\"\n\telse\n\t  # Remove any dirs left behind by ancient mkdir implementations.\n\t  rmdir ./$mkdir_mode ./-p ./-- \"$tmpdir\" 2>/dev/null\n\tfi\n\ttrap '' 0;;\n    esac\n\n    if\n      $posix_mkdir && (\n        umask $mkdir_umask &&\n        $doit_exec $mkdirprog $mkdir_mode -p -- \"$dstdir\"\n      )\n    then :\n    else\n\n      # mkdir does not conform to POSIX,\n      # or it failed possibly due to a race condition.  Create the\n      # directory the slow way, step by step, checking for races as we go.\n\n      case $dstdir in\n        /*) prefix='/';;\n        [-=\\(\\)!]*) prefix='./';;\n        *)  prefix='';;\n      esac\n\n      oIFS=$IFS\n      IFS=/\n      set -f\n      set fnord $dstdir\n      shift\n      set +f\n      IFS=$oIFS\n\n      prefixes=\n\n      for d\n      do\n        test X\"$d\" = X && continue\n\n        prefix=$prefix$d\n        if test -d \"$prefix\"; then\n          prefixes=\n        else\n          if $posix_mkdir; then\n            (umask $mkdir_umask &&\n             $doit_exec $mkdirprog $mkdir_mode -p -- \"$dstdir\") && break\n            # Don't fail if two instances are running concurrently.\n            test -d \"$prefix\" || exit 1\n          else\n            case $prefix in\n              *\\'*) qprefix=`echo \"$prefix\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n              *) qprefix=$prefix;;\n            esac\n            prefixes=\"$prefixes '$qprefix'\"\n          fi\n        fi\n        prefix=$prefix/\n      done\n\n      if test -n \"$prefixes\"; then\n        # Don't fail if two instances are running concurrently.\n        (umask $mkdir_umask &&\n         eval \"\\$doit_exec \\$mkdirprog $prefixes\") ||\n          test -d \"$dstdir\" || exit 1\n        obsolete_mkdir_used=true\n      fi\n    fi\n  fi\n\n  if test -n \"$dir_arg\"; then\n    { test -z \"$chowncmd\" || $doit $chowncmd \"$dst\"; } &&\n    { test -z \"$chgrpcmd\" || $doit $chgrpcmd \"$dst\"; } &&\n    { test \"$obsolete_mkdir_used$chowncmd$chgrpcmd\" = false ||\n      test -z \"$chmodcmd\" || $doit $chmodcmd $mode \"$dst\"; } || exit 1\n  else\n\n    # Make a couple of temp file names in the proper directory.\n    dsttmp=${dstdirslash}_inst.$$_\n    rmtmp=${dstdirslash}_rm.$$_\n\n    # Trap to clean up those temp files at exit.\n    trap 'ret=$?; rm -f \"$dsttmp\" \"$rmtmp\" && exit $ret' 0\n\n    # Copy the file name to the temp name.\n    (umask $cp_umask &&\n     { test -z \"$stripcmd\" || {\n\t # Create $dsttmp read-write so that cp doesn't create it read-only,\n\t # which would cause strip to fail.\n\t if test -z \"$doit\"; then\n\t   : >\"$dsttmp\" # No need to fork-exec 'touch'.\n\t else\n\t   $doit touch \"$dsttmp\"\n\t fi\n       }\n     } &&\n     $doit_exec $cpprog \"$src\" \"$dsttmp\") &&\n\n    # and set any options; do chmod last to preserve setuid bits.\n    #\n    # If any of these fail, we abort the whole thing.  If we want to\n    # ignore errors from any of these, just make sure not to ignore\n    # errors from the above \"$doit $cpprog $src $dsttmp\" command.\n    #\n    { test -z \"$chowncmd\" || $doit $chowncmd \"$dsttmp\"; } &&\n    { test -z \"$chgrpcmd\" || $doit $chgrpcmd \"$dsttmp\"; } &&\n    { test -z \"$stripcmd\" || $doit $stripcmd \"$dsttmp\"; } &&\n    { test -z \"$chmodcmd\" || $doit $chmodcmd $mode \"$dsttmp\"; } &&\n\n    # If -C, don't bother to copy if it wouldn't change the file.\n    if $copy_on_change &&\n       old=`LC_ALL=C ls -dlL \"$dst\"     2>/dev/null` &&\n       new=`LC_ALL=C ls -dlL \"$dsttmp\"  2>/dev/null` &&\n       set -f &&\n       set X $old && old=:$2:$4:$5:$6 &&\n       set X $new && new=:$2:$4:$5:$6 &&\n       set +f &&\n       test \"$old\" = \"$new\" &&\n       $cmpprog \"$dst\" \"$dsttmp\" >/dev/null 2>&1\n    then\n      rm -f \"$dsttmp\"\n    else\n      # If $backupsuffix is set, and the file being installed\n      # already exists, attempt a backup.  Don't worry if it fails,\n      # e.g., if mv doesn't support -f.\n      if test -n \"$backupsuffix\" && test -f \"$dst\"; then\n        $doit $mvcmd -f \"$dst\" \"$dst$backupsuffix\" 2>/dev/null\n      fi\n\n      # Rename the file to the real destination.\n      $doit $mvcmd -f \"$dsttmp\" \"$dst\" 2>/dev/null ||\n\n      # The rename failed, perhaps because mv can't rename something else\n      # to itself, or perhaps because mv is so ancient that it does not\n      # support -f.\n      {\n        # Now remove or move aside any old file at destination location.\n        # We try this two ways since rm can't unlink itself on some\n        # systems and the destination file might be busy for other\n        # reasons.  In this case, the final cleanup might fail but the new\n        # file should still install successfully.\n        {\n          test ! -f \"$dst\" ||\n          $doit $rmcmd \"$dst\" 2>/dev/null ||\n          { $doit $mvcmd -f \"$dst\" \"$rmtmp\" 2>/dev/null &&\n            { $doit $rmcmd \"$rmtmp\" 2>/dev/null; :; }\n          } ||\n          { echo \"$0: cannot unlink or rename $dst\" >&2\n            (exit 1); exit 1\n          }\n        } &&\n\n        # Now rename the file to the real destination.\n        $doit $mvcmd \"$dsttmp\" \"$dst\"\n      }\n    fi || exit 1\n\n    trap '' 0\n  fi\ndone\n\n# Local variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "unix/installManPage",
    "content": "#!/bin/sh\n\n########################################################################\n### Parse Options\n###\n\nGzip=:\nSym=\"\"\nLoc=\"\"\nGz=\"\"\nSuffix=\"\"\n\nwhile true; do\n    case $1 in\n\t-s | --symlinks  )      Sym=\"-s \"      ;;\n\t-z | --compress  )     Gzip=$2;  shift ;;\n\t-e | --extension )       Gz=$2;  shift ;;\n\t-x | --suffix    )   Suffix=$2;  shift ;;\n\t-*) cat <<EOF\nUnknown option \"$1\". Supported options:\n    -s         Use symbolic links for manpages with multiple names.\n    -z PROG    Use PROG to compress manual pages.\n    -e EXT     Defines the extension added by -z PROG when compressing.\n    -x SUFF    Defines an extra extension suffix to use.\nOption names may not be combined getopt-style.\nEOF\n\t    exit 1 ;;\n\t*)  break ;;\n    esac\n    shift\ndone\nif test \"$#\" != 2; then\n    echo \"Usage: installManPages <options> file dir\"\n    exit 1\nfi\n\n########################################################################\n### Parse Required Arguments\n###\n\nManPage=$1\nDir=$2\nif test -f $ManPage ; then : ; else\n    echo \"source manual page file must exist\"\n    exit 1\nfi\nif test -d \"$Dir\" ; then : ; else\n    echo \"target directory must exist\"\n    exit 1\nfi\ntest -z \"$Sym\" && Loc=\"$Dir/\"\n\n########################################################################\n### Extract Target Names from Manual Page\n###\n\n# A sed script to parse the alternative names out of a man page.\n#\n# Backslashes are trippled in the sed script, because it is in\n# backticks which doesn't pass backslashes literally.\n#\nNames=`sed -n '\n#                               Look for a line that starts with .SH NAME\n    /^\\.SH NAME/{\n#                               Read next line\n\tn\n#                               Remove all commas ...\n\ts/,//g\n#                               ... and backslash-escaped spaces.\n\ts/\\\\\\ //g\n#                               Delete from \\- to the end of line\n\ts/ \\\\\\-.*//\n#                               Convert all non-space non-alphanum sequences\n#                               to single underscores.\n\ts/[^ A-Za-z0-9][^ A-Za-z0-9]*/_/g\n#                               print the result and exit\n\tp;q\n    }' $ManPage`\n\nif test -z \"$Names\" ; then\n    echo \"warning: no target names found in $ManPage\"\nfi\n\n########################################################################\n### Remaining Set Up\n###\n\ncase $ManPage in\n    *.1) Section=1 ;;\n    *.3) Section=3 ;;\n    *.n) Section=n ;;\n    *)\techo \"unknown section for $ManPage\"\n\texit 2 ;;\nesac\n\nName=`basename $ManPage .$Section`\nSrcDir=`dirname $ManPage`\n\n########################################################################\n### Process Page to Create Target Pages\n###\n\nSpecials=\"DString Thread Notifier RegExp library packagens pkgMkIndex safesock FindPhoto FontId MeasureChar\"\nfor n in $Specials; do\n    if [ \"$Name\" = \"$n\" ] ; then\n\tNames=\"$n $Names\"\n    fi\ndone\n\nFirst=\"\"\nfor Target in $Names; do\n    Target=$Target.$Section$Suffix\n    rm -f \"$Dir/$Target\" \"$Dir/$Target.*\"\n    if test -z \"$First\" ; then\n\tFirst=$Target\n\tsed -e \"/man\\.macros/r $SrcDir/man.macros\" -e \"/man\\.macros/d\" \\\n\t    $ManPage > \"$Dir/$First\"\n\tchmod 644 \"$Dir/$First\"\n\t$Gzip \"$Dir/$First\"\n    else\n\tln $Sym\"$Loc$First$Gz\" \"$Dir/$Target$Gz\"\n    fi\ndone\n\n########################################################################\nexit 0\n"
  },
  {
    "path": "unix/tcl.m4",
    "content": "#------------------------------------------------------------------------\n# SC_PATH_TCLCONFIG --\n#\n#\tLocate the tclConfig.sh file and perform a sanity check on\n#\tthe Tcl compile flags\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tcl=...\n#\n#\tDefines the following vars:\n#\t\tTCL_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tclConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PATH_TCLCONFIG], [\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\tAC_ARG_WITH(tcl,\n\t    AS_HELP_STRING([--with-tcl],\n\t\t[directory containing tcl configuration (tclConfig.sh)]),\n\t    [with_tclconfig=\"${withval}\"])\n\tAC_MSG_CHECKING([for Tcl configuration])\n\tAC_CACHE_VAL(ac_cv_c_tclconfig,[\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase \"${with_tclconfig}\" in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f \"${with_tclconfig}\"; then\n\t\t\t    AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])\n\t\t\t    with_tclconfig=\"`echo \"${with_tclconfig}\" | sed 's!/tclConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd \"${with_tclconfig}\"; pwd)`\"\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tcl.framework/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/Tcl.framework; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/pkg/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib/tcl9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib64 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tcl9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=\"${ac_cv_c_tclconfig}\"\n\t    AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_PATH_TKCONFIG --\n#\n#\tLocate the tkConfig.sh file\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tk=...\n#\n#\tDefines the following vars:\n#\t\tTK_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tkConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PATH_TKCONFIG], [\n    #\n    # Ok, lets find the tk configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tk\n    #\n\n    if test x\"${no_tk}\" = x ; then\n\t# we reset no_tk in case something fails here\n\tno_tk=true\n\tAC_ARG_WITH(tk,\n\t    AS_HELP_STRING([--with-tk],\n\t\t[directory containing tk configuration (tkConfig.sh)]),\n\t    [with_tkconfig=\"${withval}\"])\n\tAC_MSG_CHECKING([for Tk configuration])\n\tAC_CACHE_VAL(ac_cv_c_tkconfig,[\n\n\t    # First check to see if --with-tkconfig was specified.\n\t    if test x\"${with_tkconfig}\" != x ; then\n\t\tcase \"${with_tkconfig}\" in\n\t\t    */tkConfig.sh )\n\t\t\tif test -f \"${with_tkconfig}\"; then\n\t\t\t    AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])\n\t\t\t    with_tkconfig=\"`echo \"${with_tkconfig}\" | sed 's!/tkConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tkconfig}/tkConfig.sh\" ; then\n\t\t    ac_cv_c_tkconfig=\"`(cd \"${with_tkconfig}\"; pwd)`\"\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tk library\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tk \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tk \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tk \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # on Darwin, check in Framework installation locations\n\t    if test \"`uname -s`\" = \"Darwin\" -a x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ~/Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Library/Frameworks 2>/dev/null` \\\n\t\t\t`ls -d /Network/Library/Frameworks 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/Tk.framework/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i/Tk.framework; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/contrib/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/pkg/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib/tk9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib 2>/dev/null` \\\n\t\t\t`ls -d /usr/lib64 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tk9.1 2>/dev/null` \\\n\t\t\t`ls -d /usr/local/lib/tcl/tk9.1 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tk \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/unix/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i/unix; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t    TK_BIN_DIR=\"# no Tk configs found\"\n\t    AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])\n\telse\n\t    no_tk=\n\t    TK_BIN_DIR=\"${ac_cv_c_tkconfig}\"\n\t    AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_LOAD_TCLCONFIG --\n#\n#\tLoad the tclConfig.sh file\n#\n# Arguments:\n#\n#\tRequires the following vars to be set:\n#\t\tTCL_BIN_DIR\n#\n# Results:\n#\n#\tSubstitutes the following vars:\n#\t\tTCL_BIN_DIR\n#\t\tTCL_SRC_DIR\n#\t\tTCL_LIB_FILE\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_LOAD_TCLCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n\tAC_MSG_RESULT([loading])\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n\tAC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])\n    fi\n\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TCL_BIN_DIR}/Makefile\" ; then\n\tTCL_LIB_SPEC=\"${TCL_BUILD_LIB_SPEC}\"\n\tTCL_STUB_LIB_SPEC=\"${TCL_BUILD_STUB_LIB_SPEC}\"\n\tTCL_STUB_LIB_PATH=\"${TCL_BUILD_STUB_LIB_PATH}\"\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tcl was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tcl.framework installed in an arbitrary location.\n\tcase ${TCL_DEFS} in\n\t    *TCL_FRAMEWORK*)\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_LIB_FILE}\"; then\n\t\t    for i in \"`cd \"${TCL_BIN_DIR}\"; pwd`\" \\\n\t\t\t     \"`cd \"${TCL_BIN_DIR}\"/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TCL_LIB_FILE}.framework\"; then\n\t\t\t    TCL_LIB_SPEC=\"-F`dirname \"$i\" | sed -e 's/ /\\\\\\\\ /g'` -framework ${TCL_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"; then\n\t\t    TCL_STUB_LIB_SPEC=\"-L`echo \"${TCL_BIN_DIR}\"  | sed -e 's/ /\\\\\\\\ /g'` ${TCL_STUB_LIB_FLAG}\"\n\t\t    TCL_STUB_LIB_PATH=\"${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    AC_SUBST(TCL_VERSION)\n    AC_SUBST(TCL_PATCH_LEVEL)\n    AC_SUBST(TCL_BIN_DIR)\n    AC_SUBST(TCL_SRC_DIR)\n\n    AC_SUBST(TCL_LIB_FILE)\n    AC_SUBST(TCL_LIB_FLAG)\n    AC_SUBST(TCL_LIB_SPEC)\n\n    AC_SUBST(TCL_STUB_LIB_FILE)\n    AC_SUBST(TCL_STUB_LIB_FLAG)\n    AC_SUBST(TCL_STUB_LIB_SPEC)\n])\n\n#------------------------------------------------------------------------\n# SC_LOAD_TKCONFIG --\n#\n#\tLoad the tkConfig.sh file\n#\n# Arguments:\n#\n#\tRequires the following vars to be set:\n#\t\tTK_BIN_DIR\n#\n# Results:\n#\n#\tSets the following vars that should be in tkConfig.sh:\n#\t\tTK_BIN_DIR\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_LOAD_TKCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])\n\n    if test -f \"${TK_BIN_DIR}/tkConfig.sh\" ; then\n\tAC_MSG_RESULT([loading])\n\t. \"${TK_BIN_DIR}/tkConfig.sh\"\n    else\n\tAC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])\n    fi\n\n    # If the TK_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TK_LIB_SPEC will be set to the value\n    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC\n    # instead of TK_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    if test -f \"${TK_BIN_DIR}/Makefile\" ; then\n\tTK_LIB_SPEC=\"${TK_BUILD_LIB_SPEC}\"\n\tTK_STUB_LIB_SPEC=\"${TK_BUILD_STUB_LIB_SPEC}\"\n\tTK_STUB_LIB_PATH=\"${TK_BUILD_STUB_LIB_PATH}\"\n    elif test \"`uname -s`\" = \"Darwin\"; then\n\t# If Tk was built as a framework, attempt to use the libraries\n\t# from the framework at the given location so that linking works\n\t# against Tk.framework installed in an arbitrary location.\n\tcase ${TK_DEFS} in\n\t    *TK_FRAMEWORK*)\n\t\tif test -f \"${TK_BIN_DIR}/${TK_LIB_FILE}\"; then\n\t\t    for i in \"`cd \"${TK_BIN_DIR}\"; pwd`\" \\\n\t\t\t     \"`cd \"${TK_BIN_DIR}\"/../..; pwd`\"; do\n\t\t\tif test \"`basename \"$i\"`\" = \"${TK_LIB_FILE}.framework\"; then\n\t\t\t    TK_LIB_SPEC=\"-F`dirname \"$i\" | sed -e 's/ /\\\\\\\\ /g'` -framework ${TK_LIB_FILE}\"\n\t\t\t    break\n\t\t\tfi\n\t\t    done\n\t\tfi\n\t\tif test -f \"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"; then\n\t\t    TK_STUB_LIB_SPEC=\"-L` echo \"${TK_BIN_DIR}\"  | sed -e 's/ /\\\\\\\\ /g'` ${TK_STUB_LIB_FLAG}\"\n\t\t    TK_STUB_LIB_PATH=\"${TK_BIN_DIR}/${TK_STUB_LIB_FILE}\"\n\t\tfi\n\t\t;;\n\tesac\n    fi\n\n    AC_SUBST(TK_VERSION)\n    AC_SUBST(TK_BIN_DIR)\n    AC_SUBST(TK_SRC_DIR)\n\n    AC_SUBST(TK_LIB_FILE)\n    AC_SUBST(TK_LIB_FLAG)\n    AC_SUBST(TK_LIB_SPEC)\n\n    AC_SUBST(TK_STUB_LIB_FILE)\n    AC_SUBST(TK_STUB_LIB_FLAG)\n    AC_SUBST(TK_STUB_LIB_SPEC)\n])\n\n#------------------------------------------------------------------------\n# SC_PROG_TCLSH\n#\tLocate a tclsh shell installed on the system path. This macro\n#\twill only find a Tcl shell that already exists on the system.\n#\tIt will not find a Tcl shell in the Tcl build directory or\n#\ta Tcl shell that has been installed from the Tcl build directory.\n#\tIf a Tcl shell can't be located on the PATH, then TCLSH_PROG will\n#\tbe set to \"\". Extensions should take care not to create Makefile\n#\trules that are run by default and depend on TCLSH_PROG. An\n#\textension can't assume that an executable Tcl shell exists at\n#\tbuild time.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following vars:\n#\t\tTCLSH_PROG\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PROG_TCLSH], [\n    AC_MSG_CHECKING([for tclsh])\n    AC_CACHE_VAL(ac_cv_path_tclsh, [\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \\\n\t\t    `ls -r $dir/tclsh* 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_tclsh\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_tclsh=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n    ])\n\n    if test -f \"$ac_cv_path_tclsh\" ; then\n\tTCLSH_PROG=\"$ac_cv_path_tclsh\"\n\tAC_MSG_RESULT([$TCLSH_PROG])\n    else\n\t# It is not an error if an installed version of Tcl can't be located.\n\tTCLSH_PROG=\"\"\n\tAC_MSG_RESULT([No tclsh found on PATH])\n    fi\n    AC_SUBST(TCLSH_PROG)\n])\n\n#------------------------------------------------------------------------\n# SC_BUILD_TCLSH\n#\tDetermine the fully qualified path name of the tclsh executable\n#\tin the Tcl build directory. This macro will correctly determine\n#\tthe name of the tclsh executable even if tclsh has not yet\n#\tbeen built in the build directory. The build tclsh must be used\n#\twhen running tests from an extension build directory. It is not\n#\tcorrect to use the TCLSH_PROG in cases like this.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following values:\n#\t\tBUILD_TCLSH\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_BUILD_TCLSH], [\n    AC_MSG_CHECKING([for tclsh in Tcl build directory])\n    BUILD_TCLSH=\"${TCL_BIN_DIR}\"/tclsh\n    AC_MSG_RESULT([$BUILD_TCLSH])\n    AC_SUBST(BUILD_TCLSH)\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_SHARED --\n#\n#\tAllows the building of shared libraries\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-shared=yes|no\n#\n#\tDefines the following vars:\n#\t\tSTATIC_BUILD\tUsed for building import/export libraries\n#\t\t\t\ton Windows.\n#\n#\tSets the following vars:\n#\t\tSHARED_BUILD\tValue of 1 or 0\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_SHARED], [\n    AC_MSG_CHECKING([how to build libraries])\n    AC_ARG_ENABLE(shared,\n\tAS_HELP_STRING([--enable-shared],\n\t    [build and link with shared libraries (default: on)]),\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n    if test \"$tcl_ok\" = \"yes\" ; then\n\tAC_MSG_RESULT([shared])\n\tSHARED_BUILD=1\n    else\n\tAC_MSG_RESULT([static])\n\tSHARED_BUILD=0\n\tAC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])\n    fi\n    AC_SUBST(SHARED_BUILD)\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_FRAMEWORK --\n#\n#\tAllows the building of shared libraries into frameworks\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-framework=yes|no\n#\n#\tSets the following vars:\n#\t\tFRAMEWORK_BUILD\tValue of 1 or 0\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_FRAMEWORK], [\n    if test \"`uname -s`\" = \"Darwin\" ; then\n\tAC_MSG_CHECKING([how to package libraries])\n\tAC_ARG_ENABLE(framework,\n\t    AS_HELP_STRING([--enable-framework],\n\t\t[package shared libraries in MacOSX frameworks (default: off)]),\n\t    [enable_framework=$enableval], [enable_framework=no])\n\tif test $enable_framework = yes; then\n\t    if test $SHARED_BUILD = 0; then\n\t\tAC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])\n\t\tenable_framework=no\n\t    fi\n\t    if test $tcl_corefoundation = no; then\n\t\tAC_MSG_WARN([Frameworks can only be used when CoreFoundation is available])\n\t\tenable_framework=no\n\t    fi\n\tfi\n\tif test $enable_framework = yes; then\n\t    AC_MSG_RESULT([framework])\n\t    FRAMEWORK_BUILD=1\n\telse\n\t    if test $SHARED_BUILD = 1; then\n\t\tAC_MSG_RESULT([shared library])\n\t    else\n\t\tAC_MSG_RESULT([static library])\n\t    fi\n\t    FRAMEWORK_BUILD=0\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_SYMBOLS --\n#\n#\tSpecify if debugging symbols should be used.\n#\tMemory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging\n#\tcan also be enabled.\n#\n# Arguments:\n#\tnone\n#\n#\tRequires the following vars to be set in the Makefile:\n#\t\tCFLAGS_DEBUG\n#\t\tCFLAGS_OPTIMIZE\n#\t\tLDFLAGS_DEBUG\n#\t\tLDFLAGS_OPTIMIZE\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-symbols\n#\n#\tDefines the following vars:\n#\t\tCFLAGS_DEFAULT\tSets to $(CFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(CFLAGS_OPTIMIZE) if false\n#\t\tLDFLAGS_DEFAULT\tSets to $(LDFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(LDFLAGS_OPTIMIZE) if false\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_SYMBOLS], [\n    AC_MSG_CHECKING([for build with symbols])\n    AC_ARG_ENABLE(symbols,\n\tAS_HELP_STRING([--enable-symbols],\n\t    [build with debugging symbols (default: off)]),\n\t[tcl_ok=$enableval], [tcl_ok=no])\n# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'\n\tAC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])\n\tAC_MSG_RESULT([no])\n\tAC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])\n    else\n\tCFLAGS_DEFAULT='$(CFLAGS_DEBUG)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    AC_MSG_RESULT([yes (standard debugging)])\n\tfi\n    fi\n    AC_SUBST(CFLAGS_DEFAULT)\n    AC_SUBST(LDFLAGS_DEFAULT)\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\tAC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])\n    fi\n\n    ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself\n\tif test \"$tcl_ok\" = \"compile\" -o \"$tcl_ok\" = \"all\"; then\n\t    AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])\n\t    AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])\n\tfi)\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging])\n\telse\n\t    AC_MSG_RESULT([enabled $tcl_ok debugging])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_LANGINFO --\n#\n#\tAllows use of modern nl_langinfo check for better l10n.\n#\tThis is only relevant for Unix.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-langinfo=yes|no (default is yes)\n#\n#\tDefines the following vars:\n#\t\tHAVE_LANGINFO\tTriggers use of nl_langinfo if defined.\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_LANGINFO], [\n    AC_ARG_ENABLE(langinfo,\n\tAS_HELP_STRING([--enable-langinfo],\n\t    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),\n\t[langinfo_ok=$enableval], [langinfo_ok=yes])\n\n    HAVE_LANGINFO=0\n    if test \"$langinfo_ok\" = \"yes\"; then\n\tAC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])\n    fi\n    AC_MSG_CHECKING([whether to use nl_langinfo])\n    if test \"$langinfo_ok\" = \"yes\"; then\n\tAC_CACHE_VAL(tcl_cv_langinfo_h, [\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]], [[nl_langinfo(CODESET);]])],\n\t\t    [tcl_cv_langinfo_h=yes], [tcl_cv_langinfo_h=no])])\n\tAC_MSG_RESULT([$tcl_cv_langinfo_h])\n\tif test $tcl_cv_langinfo_h = yes; then\n\t    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])\n\tfi\n    else\n\tAC_MSG_RESULT([$langinfo_ok])\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_CONFIG_MANPAGES\n#\n#\tDecide whether to use symlinks for linking the manpages,\n#\twhether to compress the manpages after installation, and\n#\twhether to add a package name suffix to the installed\n#\tmanpages to avoidfile name clashes.\n#\tIf compression is enabled also find out what file name suffix\n#\tthe given compression program is using.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-man-symlinks\n#\t\t--enable-man-compression=PROG\n#\t\t--enable-man-suffix[=STRING]\n#\n#\tDefines the following variable:\n#\n#\tMAN_FLAGS -\tThe apropriate flags for installManPage\n#\t\t\taccording to the user's selection.\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_CONFIG_MANPAGES], [\n    AC_MSG_CHECKING([whether to use symlinks for manpages])\n    AC_ARG_ENABLE(man-symlinks,\n\tAS_HELP_STRING([--enable-man-symlinks],\n\t    [use symlinks for the manpages (default: off)]),\n\t[test \"$enableval\" != \"no\" && MAN_FLAGS=\"$MAN_FLAGS --symlinks\"],\n\t[enableval=\"no\"])\n    AC_MSG_RESULT([$enableval])\n\n    AC_MSG_CHECKING([whether to compress the manpages])\n    AC_ARG_ENABLE(man-compression,\n\tAS_HELP_STRING([--enable-man-compression=PROG],\n\t    [compress the manpages with PROG (default: off)]),\n\t[case $enableval in\n\t    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;\n\t    no)  ;;\n\t    *)   MAN_FLAGS=\"$MAN_FLAGS --compress $enableval\";;\n\tesac],\n\t[enableval=\"no\"])\n    AC_MSG_RESULT([$enableval])\n    if test \"$enableval\" != \"no\"; then\n\tAC_MSG_CHECKING([for compressed file suffix])\n\ttouch TeST\n\t$enableval TeST\n\tZ=`ls TeST.* | sed 's/^....//'`\n\trm -f TeST*\n\tMAN_FLAGS=\"$MAN_FLAGS --extension $Z\"\n\tAC_MSG_RESULT([$Z])\n    fi\n\n    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])\n    AC_ARG_ENABLE(man-suffix,\n\tAS_HELP_STRING([--enable-man-suffix=STRING],\n\t    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),\n\t[case $enableval in\n\t    yes) enableval=\"AC_PACKAGE_NAME\" MAN_FLAGS=\"$MAN_FLAGS --suffix $enableval\";;\n\t    no)  ;;\n\t    *)   MAN_FLAGS=\"$MAN_FLAGS --suffix $enableval\";;\n\tesac],\n\t[enableval=\"no\"])\n    AC_MSG_RESULT([$enableval])\n\n    AC_SUBST(MAN_FLAGS)\n])\n\n#--------------------------------------------------------------------\n# SC_CONFIG_SYSTEM\n#\n#\tDetermine what the system is (some things cannot be easily checked\n#\ton a feature-driven basis, alas). This can usually be done via the\n#\t\"uname\" command.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tDefines the following var:\n#\n#\tsystem -\tSystem/platform/version identification code.\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_CONFIG_SYSTEM], [\n    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [\n\tif test \"${TEA_PLATFORM}\" = \"windows\" ; then\n\t    tcl_cv_sys_version=windows\n\telse\n\t    tcl_cv_sys_version=`uname -s`-`uname -r`\n\t    if test \"$?\" -ne 0 ; then\n\t\tAC_MSG_WARN([can't find uname command])\n\t\ttcl_cv_sys_version=unknown\n\t    else\n\t\tif test \"`uname -s`\" = \"AIX\" ; then\n\t\t    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`\n\t\tfi\n\t\tif test \"`uname -s`\" = \"NetBSD\" -a -f /etc/debian_version ; then\n\t\t    tcl_cv_sys_version=NetBSD-Debian\n\t\tfi\n\t    fi\n\tfi\n    ])\n    system=$tcl_cv_sys_version\n])\n\n#--------------------------------------------------------------------\n# SC_CONFIG_CFLAGS\n#\n#\tTry to determine the proper flags to pass to the compiler\n#\tfor building shared libraries and other such nonsense.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines and substitutes the following vars:\n#\n#       DL_OBJS -       Name of the object file that implements dynamic\n#                       loading for Tcl on this system.\n#       DL_LIBS -       Library file(s) to include in tclsh and other base\n#                       applications in order for the \"load\" command to work.\n#       LDFLAGS -      Flags to pass to the compiler when linking object\n#                       files into an executable application binary such\n#                       as tclsh.\n#       LD_SEARCH_FLAGS-Flags to pass to ld, such as \"-R /usr/local/tcl/lib\",\n#                       that tell the run-time dynamic linker where to look\n#                       for shared libraries such as libtcl.so.  Depends on\n#                       the variable LIB_RUNTIME_DIR in the Makefile. Could\n#                       be the same as CC_SEARCH_FLAGS if ${CC} is used to link.\n#       CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as \"-Wl,-rpath,/usr/local/tcl/lib\",\n#                       that tell the run-time dynamic linker where to look\n#                       for shared libraries such as libtcl.so.  Depends on\n#                       the variable LIB_RUNTIME_DIR in the Makefile.\n#       MAKE_LIB -      Command to execute to build the a library;\n#                       differs when building shared or static.\n#       MAKE_STUB_LIB -\n#                       Command to execute to build a stub library.\n#       INSTALL_LIB -   Command to execute to install a library;\n#                       differs when building shared or static.\n#       INSTALL_STUB_LIB -\n#                       Command to execute to install a stub library.\n#       STLIB_LD -      Base command to use for combining object files\n#                       into a static library.\n#       SHLIB_CFLAGS -  Flags to pass to cc when compiling the components\n#                       of a shared library (may request position-independent\n#                       code, among other things).\n#       SHLIB_LD -      Base command to use for combining object files\n#                       into a shared library.\n#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when\n#                       creating shared libraries.  This symbol typically\n#                       goes at the end of the \"ld\" commands that build\n#                       shared libraries. The value of the symbol defaults to\n#                       \"${LIBS}\" if all of the dependent libraries should\n#                       be specified when creating a shared library.  If\n#                       dependent libraries should not be specified (as on some\n#                       SunOS systems, where they cause the link to fail, or in\n#                       general if Tcl and Tk aren't themselves shared\n#                       libraries), then this symbol has an empty string\n#                       as its value.\n#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable\n#                       extensions.  An empty string means we don't know how\n#                       to use shared libraries on this platform.\n# TCL_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS\n#  TK_SHLIB_LD_EXTRAS   for the build of Tcl and Tk, but not recorded in the\n#                       tclConfig.sh, since they are only used for the build\n#                       of Tcl and Tk.\n#                       Examples: MacOS X records the library version and\n#                       compatibility version in the shared library.  But\n#                       of course the Tcl version of this is only used for Tcl.\n#       LIB_SUFFIX -    Specifies everything that comes after the \"libfoo\"\n#                       in a static or shared library name, using the $VERSION variable\n#                       to put the version in the right place.  This is used\n#                       by platforms that need non-standard library names.\n#                       Examples:  ${VERSION}.so.1.1 on NetBSD, since it needs\n#                       to have a version after the .so, and ${VERSION}.a\n#                       on AIX, since a shared library needs to have\n#                       a .a extension whereas shared objects for loadable\n#                       extensions have a .so extension.  Defaults to\n#                       ${VERSION}${SHLIB_SUFFIX}.\n#       TCL_LIBS -\n#                       Libs to use when linking Tcl shell or some other\n#                       shell that includes Tcl libs.\n#\tCFLAGS_DEBUG -\n#\t\t\tFlags used when running the compiler in debug mode\n#\tCFLAGS_OPTIMIZE -\n#\t\t\tFlags used when running the compiler in optimize mode\n#\tCFLAGS -\tAdditional CFLAGS added as necessary (usually 64-bit)\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_CONFIG_CFLAGS], [\n\n    # Step 0.a: Enable 64 bit support?\n\n    AC_MSG_CHECKING([if 64bit support is requested])\n    AC_ARG_ENABLE(64bit,\n\tAS_HELP_STRING([--enable-64bit],\n\t    [enable 64bit support (default: off)]),\n\t[do64bit=$enableval], [do64bit=no])\n    AC_MSG_RESULT([$do64bit])\n\n    # Step 0.b: Enable Solaris 64 bit VIS support?\n\n    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])\n    AC_ARG_ENABLE(64bit-vis,\n\tAS_HELP_STRING([--enable-64bit-vis],\n\t    [enable 64bit Sparc VIS support (default: off)]),\n\t[do64bitVIS=$enableval], [do64bitVIS=no])\n    AC_MSG_RESULT([$do64bitVIS])\n    # Force 64bit on with VIS\n    AS_IF([test \"$do64bitVIS\" = \"yes\"], [do64bit=yes])\n\n    # Step 0.c: Check if visibility support is available. Do this here so\n    # that platform specific alternatives can be used below if this fails.\n\n    AC_CACHE_CHECK([if compiler supports visibility \"hidden\"],\n\ttcl_cv_cc_visibility_hidden, [\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Werror\"\n\tAC_LINK_IFELSE([AC_LANG_PROGRAM([[\n\t    extern __attribute__((__visibility__(\"hidden\"))) void f(void);\n\t    void f(void) {}]], [[f();]])],\n\t    [tcl_cv_cc_visibility_hidden=yes],\n\t    [tcl_cv_cc_visibility_hidden=no])\n\tCFLAGS=$hold_cflags])\n    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [\n\tAC_DEFINE(MODULE_SCOPE,\n\t    [extern __attribute__((__visibility__(\"hidden\")))],\n\t    [Compiler support for module scope symbols])\n\tAC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])\n    ])\n\n    # Step 0.d: Disable -rpath support?\n\n    AC_MSG_CHECKING([if rpath support is requested])\n    AC_ARG_ENABLE(rpath,\n\tAS_HELP_STRING([--disable-rpath],\n\t    [disable rpath support (default: on)]),\n\t[doRpath=$enableval], [doRpath=yes])\n    AC_MSG_RESULT([$doRpath])\n\n    # Step 1: set the variable \"system\" to hold the name and version number\n    # for the system.\n\n    SC_CONFIG_SYSTEM\n\n    # Step 2: check for existence of -ldl library.  This is needed because\n    # Linux can use either -ldl or -ldld for dynamic loading.\n\n    AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)\n\n    # Require ranlib early so we can override it in special cases below.\n\n    AC_REQUIRE([AC_PROG_RANLIB])\n\n    # Step 3: set configuration options based on system name and version.\n\n    do64bit_ok=no\n    # default to '{$LIBS}' and set to \"\" on per-platform necessary basis\n    SHLIB_LD_LIBS='${LIBS}'\n    LDFLAGS_ORIG=\"$LDFLAGS\"\n    # When ld needs options to work in 64-bit mode, put them in\n    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]\n    # is disabled by the user. [Bug 1016796]\n    LDFLAGS_ARCH=\"\"\n    UNSHARED_LIB_SUFFIX=\"\"\n    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'\n    ECHO_VERSION='`echo ${VERSION}`'\n    TCL_LIB_VERSIONS_OK=ok\n    CFLAGS_DEBUG=-g\n    AS_IF([test \"$GCC\" = yes], [\n\tCFLAGS_OPTIMIZE=-O2\n\tCFLAGS_WARNING=\"-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith\"\n\tcase \"${CC}\" in\n\t    *++|*++-*)\n\t\t;;\n\t    *)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers\"\n\t\t;;\n\tesac\n\n    ], [\n\tCFLAGS_OPTIMIZE=-O\n\tCFLAGS_WARNING=\"\"\n    ])\n    AC_CHECK_TOOL(AR, ar)\n    STLIB_LD='${AR} cr'\n    LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH\"\n    PLAT_OBJS=\"\"\n    PLAT_SRCS=\"\"\n    LDAIX_SRC=\"\"\n    AS_IF([test \"x${SHLIB_VERSION}\" = x], [SHLIB_VERSION=\"1.0\"])\n    case $system in\n\tAIX-*)\n\t    AS_IF([test \"$GCC\" != \"yes\"], [\n\t\t# AIX requires the _r compiler when gcc isn't being used\n\t\tcase \"${CC}\" in\n\t\t    *_r|*_r\\ *)\n\t\t\t# ok ...\n\t\t\t;;\n\t\t    *)\n\t\t\t# Make sure only first arg gets _r\n\t\t\tCC=`echo \"$CC\" | sed -e 's/^\\([[^ ]]*\\)/\\1_r/'`\n\t\t\t;;\n\t\tesac\n\t\tAC_MSG_RESULT([Using $CC for compiling with threads])\n\t    ])\n\t    LIBS=\"$LIBS -lc\"\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    LD_LIBRARY_PATH_VAR=\"LIBPATH\"\n\n\t    # ldAix No longer needed with use of -bexpall/-brtl\n\t    # but some extensions may still reference it\n\t    LDAIX_SRC='$(UNIX_DIR)/ldAix'\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    AS_IF([test \"$do64bit\" = yes], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    AC_MSG_WARN([64bit mode not supported with GCC on $system])\n\t\t], [\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS -q64\"\n\t\t    LDFLAGS_ARCH=\"-q64\"\n\t\t    RANLIB=\"${RANLIB} -X64\"\n\t\t    AR=\"${AR} -X64\"\n\t\t    SHLIB_LD_FLAGS=\"-b64\"\n\t\t])\n\t    ])\n\n\t    AS_IF([test \"`uname -m`\" = ia64], [\n\t\t# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\t# AIX-5 has dl* in libc.so\n\t\tDL_LIBS=\"\"\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\t], [\n\t\t    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'\n\t\t])\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t    ], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    SHLIB_LD='${CC} -shared -Wl,-bexpall'\n\t\t], [\n\t\t    SHLIB_LD=\"/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry\"\n\t\t    LDFLAGS=\"$LDFLAGS -brtl\"\n\t\t])\n\t\tSHLIB_LD=\"${SHLIB_LD} ${SHLIB_LD_FLAGS}\"\n\t\tDL_LIBS=\"-ldl\"\n\t\tCC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ])\n\t    ;;\n\tBeOS*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} -nostart'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\n\t    #-----------------------------------------------------------\n\t    # Check for inet_ntoa in -lbind, for BeOS (which also needs\n\t    # -lsocket, even if the network functions are in -lnet which\n\t    # is always linked to, for compatibility.\n\t    #-----------------------------------------------------------\n\t    AC_CHECK_LIB(bind, inet_ntoa, [LIBS=\"$LIBS -lbind -lsocket\"])\n\t    ;;\n\tBSD/OS-2.1*|BSD/OS-3*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"shlicc -r\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tBSD/OS-4.*)\n\t    SHLIB_CFLAGS=\"-export-dynamic -fPIC\"\n\t    SHLIB_LD='${CC} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tCYGWIN_*|MINGW32_*|MSYS_*)\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    SHLIB_LD='${CC} -shared -Wl,--out-implib,$(patsubst cyg%.dll,lib%.dll,$[@]).a'\n\t    SHLIB_SUFFIX=\".dll\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    PLAT_OBJS='${CYGWIN_OBJS}'\n\t    PLAT_SRCS='${CYGWIN_SRCS}'\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    AC_CACHE_CHECK(for Cygwin version of gcc,\n\t\tac_cv_cygwin,\n\t\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t#ifdef __CYGWIN__\n\t\t    #error cygwin\n\t\t#endif\n\t\t]], [[]])],\n\t\t[ac_cv_cygwin=no],\n\t\t[ac_cv_cygwin=yes])\n\t    )\n\t    if test \"$ac_cv_cygwin\" = \"no\"; then\n\t\tAC_MSG_ERROR([${CC} is not a cygwin compiler.])\n\t    fi\n\t    do64bit_ok=yes\n\t    if test \"x${SHARED_BUILD}\" = \"x1\"; then\n\t\techo \"running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32\"\n\t\t# The eval makes quoting arguments work.\n\t\tif cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32; cd ../unix\n\t\tthen :\n\t\telse\n\t\t    { echo \"configure: error: configure failed for ../win\" 1>&2; exit 1; }\n\t\tfi\n\t    fi\n\t    ;;\n\tdgux*)\n\t    SHLIB_CFLAGS=\"-K PIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tHaiku*)\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-lroot\"\n\t    AC_CHECK_LIB(network, inet_ntoa, [LIBS=\"$LIBS -lnetwork\"])\n\t    ;;\n\tHP-UX-*.11.*)\n\t    # Use updated header definitions where possible\n\t    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])\n\t    AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])\n\t    LIBS=\"$LIBS -lxnet\"               # Use the XOPEN network library\n\n\t    AS_IF([test \"`uname -m`\" = ia64], [\n\t\tSHLIB_SUFFIX=\".so\"\n\t    ], [\n\t\tSHLIB_SUFFIX=\".sl\"\n\t    ])\n\t    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)\n\t    AS_IF([test \"$tcl_ok\" = yes], [\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\t    ])\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ], [\n\t\tCFLAGS=\"$CFLAGS -z\"\n\t    ])\n\n\t    # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc\n\t    #CFLAGS=\"$CFLAGS +DAportable\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    AS_IF([test \"$do64bit\" = \"yes\"], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    case `${CC} -dumpmachine` in\n\t\t\thppa64*)\n\t\t\t    # 64-bit gcc in use.  Fix flags for GNU ld.\n\t\t\t    do64bit_ok=yes\n\t\t\t    SHLIB_LD='${CC} -shared'\n\t\t\t    AS_IF([test $doRpath = yes], [\n\t\t\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'])\n\t\t\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\t\t    ;;\n\t\t\t*)\n\t\t\t    AC_MSG_WARN([64bit mode not supported with GCC on $system])\n\t\t\t    ;;\n\t\t    esac\n\t\t], [\n\t\t    do64bit_ok=yes\n\t\t    CFLAGS=\"$CFLAGS +DD64\"\n\t\t    LDFLAGS_ARCH=\"+DD64\"\n\t\t])\n\t    ]) ;;\n\tHP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)\n\t    SHLIB_SUFFIX=\".sl\"\n\t    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)\n\t    AS_IF([test \"$tcl_ok\" = yes], [\n\t\tSHLIB_CFLAGS=\"+z\"\n\t\tSHLIB_LD=\"ld -b\"\n\t\tSHLIB_LD_LIBS=\"\"\n\t\tDL_OBJS=\"tclLoadShl.o\"\n\t\tDL_LIBS=\"-ldld\"\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-E\"\n\t\tCC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'\n\t\tLD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'\n\t\tLD_LIBRARY_PATH_VAR=\"SHLIB_PATH\"\n\t    ]) ;;\n\tIRIX-5.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AC_LIBOBJ(mkstemp)\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    ;;\n\tIRIX-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AC_LIBOBJ(mkstemp)\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tCFLAGS=\"$CFLAGS -mabi=n32\"\n\t\tLDFLAGS=\"$LDFLAGS -mabi=n32\"\n\t    ], [\n\t\tcase $system in\n\t\t    IRIX-6.3)\n\t\t\t# Use to build 6.2 compatible binaries on 6.3.\n\t\t\tCFLAGS=\"$CFLAGS -n32 -D_OLD_TERMIOS\"\n\t\t\t;;\n\t\t    *)\n\t\t\tCFLAGS=\"$CFLAGS -n32\"\n\t\t\t;;\n\t\tesac\n\t\tLDFLAGS=\"$LDFLAGS -n32\"\n\t    ])\n\t    ;;\n\tIRIX64-6.*)\n\t    SHLIB_CFLAGS=\"\"\n\t    SHLIB_LD=\"ld -n32 -shared -rdata_shared\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AC_LIBOBJ(mkstemp)\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\n\t    AS_IF([test \"$do64bit\" = yes], [\n\t\tAS_IF([test \"$GCC\" = yes], [\n\t\t    AC_MSG_WARN([64bit mode not supported by gcc])\n\t\t], [\n\t\t    do64bit_ok=yes\n\t\t    SHLIB_LD=\"ld -64 -shared -rdata_shared\"\n\t\t    CFLAGS=\"$CFLAGS -64\"\n\t\t    LDFLAGS_ARCH=\"-64\"\n\t\t])\n\t    ])\n\t    ;;\n\tLinux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*)\n\t    SHLIB_CFLAGS=\"-fPIC -fno-common\"\n\t    SHLIB_SUFFIX=\".so\"\n\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings\n\t    # when you inline the string and math operations.  Turn this off to\n\t    # get rid of the warnings.\n\t    #CFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES\"\n\n\t    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n\n\t    case $system in\n\t    DragonFly-*|FreeBSD-*)\n\t\t# The -pthread needs to go in the LDFLAGS, not LIBS\n\t\tLIBS=`echo $LIBS | sed s/-pthread//`\n\t\tCFLAGS=\"$CFLAGS $PTHREAD_CFLAGS\"\n\t\tLDFLAGS=\"$LDFLAGS $PTHREAD_LIBS\"\n\t    ;;\n\t    esac\n\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    AS_IF([test \"`uname -m`\" = \"alpha\"], [CFLAGS=\"$CFLAGS -mieee\"])\n\t    AS_IF([test $do64bit = yes], [\n\t\tAC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [\n\t\t    hold_cflags=$CFLAGS\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],\n\t\t\t    [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no])\n\t\t    CFLAGS=$hold_cflags])\n\t\tAS_IF([test $tcl_cv_cc_m64 = yes], [\n\t\t    CFLAGS=\"$CFLAGS -m64\"\n\t\t    do64bit_ok=yes\n\t\t])\n\t   ])\n\n\t    # The combo of gcc + glibc has a bug related to inlining of\n\t    # functions like strtol()/strtoul(). The -fno-builtin flag should address\n\t    # this problem but it does not work. The -fno-inline flag is kind\n\t    # of overkill but it works. Disable inlining only when one of the\n\t    # files in compat/*.c is being linked in.\n\n\t    AS_IF([test x\"${USE_COMPAT}\" != x],[CFLAGS=\"$CFLAGS -fno-inline\"])\n\t    ;;\n\tLynx*)\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    CFLAGS_OPTIMIZE=-02\n\t    SHLIB_LD='${CC} -shared'\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-mshared -ldl\"\n\t    LD_FLAGS=\"-Wl,--export-dynamic\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'])\n\t    ;;\n\tOpenBSD-*)\n\t    arch=`arch -s`\n\t    case \"$arch\" in\n\t    alpha|sparc64)\n\t\tSHLIB_CFLAGS=\"-fPIC\"\n\t\t;;\n\t    *)\n\t\tSHLIB_CFLAGS=\"-fpic\"\n\t\t;;\n\t    esac\n\t    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'\n\t    LDFLAGS=\"-Wl,-export-dynamic\"\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    # On OpenBSD:\tCompile with -pthread\n\t    #\t\tDon't link with -lpthread\n\t    LIBS=`echo $LIBS | sed s/-lpthread//`\n\t    CFLAGS=\"$CFLAGS -pthread\"\n\t    # OpenBSD doesn't do version numbers with dots.\n\t    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'\n\t    TCL_LIB_VERSIONS_OK=nodots\n\t    ;;\n\tNetBSD-*)\n\t    # NetBSD has ELF and can use 'cc -shared' to build shared libs\n\t    SHLIB_CFLAGS=\"-fPIC\"\n\t    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -export-dynamic\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'])\n\t    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    # The -pthread needs to go in the CFLAGS, not LIBS\n\t    LIBS=`echo $LIBS | sed s/-pthread//`\n\t    CFLAGS=\"$CFLAGS -pthread\"\n\t    LDFLAGS=\"$LDFLAGS -pthread\"\n\t    ;;\n\tDarwin-*)\n\t    CFLAGS_OPTIMIZE=\"-O2\"\n\t    SHLIB_CFLAGS=\"-fno-common\"\n\t    # To avoid discrepancies between what headers configure sees during\n\t    # preprocessing tests and compiling tests, move any -isysroot and\n\t    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:\n\t    CPPFLAGS=\"${CPPFLAGS} `echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif ([$]i~/^(isysroot|mmacosx-version-min)/) print \"-\"[$]i}'`\"\n\t    CFLAGS=\"`echo \" ${CFLAGS}\" | \\\n\t\tawk 'BEGIN {FS=\" +-\";ORS=\" \"}; {for (i=2;i<=NF;i++) \\\n\t\tif (!([$]i~/^(isysroot|mmacosx-version-min)/)) print \"-\"[$]i}'`\"\n\t    AS_IF([test $do64bit = yes], [\n\t\tcase `arch` in\n\t\t    ppc)\n\t\t\tAC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],\n\t\t\t\ttcl_cv_cc_arch_ppc64, [\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],\n\t\t\t\t    [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no])\n\t\t\t    CFLAGS=$hold_cflags])\n\t\t\tAS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5\"\n\t\t\t    do64bit_ok=yes\n\t\t\t]);;\n\t\t    i386|x86_64)\n\t\t\tAC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],\n\t\t\t\ttcl_cv_cc_arch_x86_64, [\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],\n\t\t\t\t    [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no])\n\t\t\t    CFLAGS=$hold_cflags])\n\t\t\tAS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -arch x86_64\"\n\t\t\t    do64bit_ok=yes\n\t\t\t]);;\n\t\t    arm64)\n\t\t\tAC_CACHE_CHECK([if compiler accepts -arch arm64 flag],\n\t\t\t\ttcl_cv_cc_arch_arm64, [\n\t\t\t    hold_cflags=$CFLAGS\n\t\t\t    CFLAGS=\"$CFLAGS -arch arm64\"\n\t\t\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],\n\t\t\t\t    [tcl_cv_cc_arch_arm64=yes],[tcl_cv_cc_arch_arm64=no])\n\t\t\t    CFLAGS=$hold_cflags])\n\t\t\tAS_IF([test $tcl_cv_cc_arch_arm64 = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -arch arm64\"\n\t\t\t    do64bit_ok=yes\n\t\t\t]);;\n\t\t    *)\n\t\t\tAC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;\n\t\tesac\n\t    ], [\n\t\t# Check for combined 32-bit and 64-bit fat build\n\t\tAS_IF([echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc64|x86_64|arm64) ' \\\n\t\t    && echo \"$CFLAGS \" |grep -E -q -- '-arch (ppc|i386) '], [\n\t\t    fat_32_64=yes])\n\t    ])\n\t    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'\n\t    SHLIB_SUFFIX=\".dylib\"\n\t    DL_OBJS=\"tclLoadDyld.o\"\n\t    DL_LIBS=\"\"\n\t    LDFLAGS=\"$LDFLAGS -headerpad_max_install_names\"\n\t    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],\n\t\t    tcl_cv_ld_search_paths_first, [\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t\tAC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],\n\t\t\t[tcl_cv_ld_search_paths_first=yes],\n\t\t    [tcl_cv_ld_search_paths_first=no])\n\t\tLDFLAGS=$hold_ldflags])\n\t    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-search_paths_first\"\n\t    ])\n\t    AS_IF([test \"$tcl_cv_cc_visibility_hidden\" != yes], [\n\t\tAC_DEFINE(MODULE_SCOPE, [__private_extern__],\n\t\t    [Compiler support for module scope symbols])\n\t\ttcl_cv_cc_visibility_hidden=yes\n\t    ])\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    LD_LIBRARY_PATH_VAR=\"DYLD_FALLBACK_LIBRARY_PATH\"\n\t    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])\n\t    PLAT_OBJS='${MAC_OSX_OBJS}'\n\t    PLAT_SRCS='${MAC_OSX_SRCS}'\n\t    AC_MSG_CHECKING([whether to use CoreFoundation])\n\t    AC_ARG_ENABLE(corefoundation,\n\t\tAS_HELP_STRING([--enable-corefoundation],\n\t\t    [use CoreFoundation API on MacOSX (default: on)]),\n\t\t[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])\n\t    AC_MSG_RESULT([$tcl_corefoundation])\n\t    AS_IF([test $tcl_corefoundation = yes], [\n\t\tAC_CACHE_CHECK([for CoreFoundation.framework],\n\t\t\ttcl_cv_lib_corefoundation, [\n\t\t    hold_libs=$LIBS\n\t\t    AS_IF([test \"$fat_32_64\" = yes], [\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    # On Tiger there is no 64-bit CF, so remove 64-bit\n\t\t\t    # archs from CFLAGS et al. while testing for\n\t\t\t    # presence of CF. 64-bit CF is disabled in\n\t\t\t    # tclUnixPort.h if necessary.\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc64 / /g\" -e \"s/-arch x86_64 / /g\"`\"'\n\t\t\tdone])\n\t\t    LIBS=\"$LIBS -framework CoreFoundation\"\n\t\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],\n\t\t\t[[CFBundleRef b = CFBundleGetMainBundle();]])],\n\t\t\t[tcl_cv_lib_corefoundation=yes],\n\t\t\t[tcl_cv_lib_corefoundation=no])\n\t\t    AS_IF([test \"$fat_32_64\" = yes], [\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone])\n\t\t    LIBS=$hold_libs])\n\t\tAS_IF([test $tcl_cv_lib_corefoundation = yes], [\n\t\t    LIBS=\"$LIBS -framework CoreFoundation\"\n\t\t    AC_DEFINE(HAVE_COREFOUNDATION, 1,\n\t\t\t[Do we have access to Darwin CoreFoundation.framework?])\n\t\t], [tcl_corefoundation=no])\n\t\tAS_IF([test \"$fat_32_64\" = yes -a $tcl_corefoundation = yes],[\n\t\t    AC_CACHE_CHECK([for 64-bit CoreFoundation],\n\t\t\t    tcl_cv_lib_corefoundation_64, [\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval 'hold_'$v'=\"$'$v'\";'$v'=\"`echo \"$'$v' \"|sed -e \"s/-arch ppc / /g\" -e \"s/-arch i386 / /g\"`\"'\n\t\t\tdone\n\t\t\tAC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],\n\t\t\t    [[CFBundleRef b = CFBundleGetMainBundle();]])],\n\t\t\t    [tcl_cv_lib_corefoundation_64=yes],\n\t\t\t    [tcl_cv_lib_corefoundation_64=no])\n\t\t\tfor v in CFLAGS CPPFLAGS LDFLAGS; do\n\t\t\t    eval $v'=\"$hold_'$v'\"'\n\t\t\tdone])\n\t\t    AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [\n\t\t\tAC_DEFINE(NO_COREFOUNDATION_64, 1,\n\t\t\t    [Is Darwin CoreFoundation unavailable for 64-bit?])\n\t\t\tLDFLAGS=\"$LDFLAGS -Wl,-no_arch_warnings\"\n\t\t    ])\n\t\t])\n\t    ])\n\t    ;;\n\tOS/390-*)\n\t    SHLIB_LD_LIBS=\"\"\n\t    CFLAGS_OPTIMIZE=\"\"\t\t# Optimizer is buggy\n\t    AC_DEFINE(_OE_SOCKETS, 1,\t# needed in sys/socket.h\n\t\t[Should OS/390 do the right thing with sockets?])\n\t    ;;\n\tOSF1-V*)\n\t    # Digital OSF/1\n\t    SHLIB_CFLAGS=\"\"\n\t    AS_IF([test \"$SHARED_BUILD\" = 1], [\n\t\tSHLIB_LD='${CC} -shared'\n\t    ], [\n\t\tSHLIB_LD='${CC} -non_shared'\n\t    ])\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    AS_IF([test $doRpath = yes], [\n\t\tCC_SEARCH_FLAGS='\"-Wl,-rpath,${LIB_RUNTIME_DIR}\"'\n\t\tLD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])\n\t    AS_IF([test \"$GCC\" = yes], [CFLAGS=\"$CFLAGS -mieee\"], [\n\t\tCFLAGS=\"$CFLAGS -DHAVE_TZSET -std1 -ieee\"])\n\t    # see pthread_intro(3) for pthread support on osf1, k.furukawa\n\t    CFLAGS=\"$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE\"\n\t    CFLAGS=\"$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64\"\n\t    LIBS=`echo $LIBS | sed s/-lpthreads//`\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tLIBS=\"$LIBS -lpthread -lmach -lexc\"\n\t    ], [\n\t\tCFLAGS=\"$CFLAGS -pthread\"\n\t\tLDFLAGS=\"$LDFLAGS -pthread\"\n\t    ])\n\t    ;;\n\tQNX-6*)\n\t    # QNX RTP\n\t    # This may work for all QNX, but it was only reported for v6.\n\t    SHLIB_LD=\"ld -Bshareable -x\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    # dlopen is in -lc on QNX\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSCO_SV-3.2*)\n\t    # Note, dlopen is available only on SCO 3.2.5 and greater. However,\n\t    # this test works, since \"uname -s\" was non-standard in 3.2.4 and\n\t    # below.\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_CFLAGS=\"-fPIC -melf\"\n\t\tLDFLAGS=\"$LDFLAGS -melf -Wl,-Bexport\"\n\t    ], [\n\t\tSHLIB_CFLAGS=\"-Kpic -belf\"\n\t\tLDFLAGS=\"$LDFLAGS -belf -Wl,-Bexport\"\n\t    ])\n\t    SHLIB_LD=\"ld -G\"\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"\"\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n\tSunOS-5.[[0-6]])\n\t    # Careful to not let 5.10+ fall into this case\n\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\t    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n\t    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,\n\t\t[Do we really want to follow the standard? Yes we do!])\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ], [\n\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z text\"\n\t\tCC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t    ])\n\t    ;;\n\tSunOS-5*)\n\t    # Note: If _REENTRANT isn't defined, then Solaris\n\t    # won't define thread-safe library routines.\n\n\t    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n\t    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,\n\t\t[Do we really want to follow the standard? Yes we do!])\n\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\n\t    # Check to enable 64-bit flags for compiler/linker\n\t    AS_IF([test \"$do64bit\" = yes], [\n\t\tarch=`isainfo`\n\t\tAS_IF([test \"$arch\" = \"sparcv9 sparc\"], [\n\t\t    AS_IF([test \"$GCC\" = yes], [\n\t\t\tAS_IF([test \"`${CC} -dumpversion | awk -F. '{print [$]1}'`\" -lt 3], [\n\t\t\t    AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])\n\t\t\t], [\n\t\t\t    do64bit_ok=yes\n\t\t\t    CFLAGS=\"$CFLAGS -m64 -mcpu=v9\"\n\t\t\t    LDFLAGS=\"$LDFLAGS -m64 -mcpu=v9\"\n\t\t\t    SHLIB_CFLAGS=\"-fPIC\"\n\t\t\t])\n\t\t    ], [\n\t\t\tdo64bit_ok=yes\n\t\t\tAS_IF([test \"$do64bitVIS\" = yes], [\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9a\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9a\"\n\t\t\t], [\n\t\t\t    CFLAGS=\"$CFLAGS -xarch=v9\"\n\t\t\t    LDFLAGS_ARCH=\"-xarch=v9\"\n\t\t\t])\n\t\t\t# Solaris 64 uses this as well\n\t\t\t#LD_LIBRARY_PATH_VAR=\"LD_LIBRARY_PATH_64\"\n\t\t    ])\n\t\t], [AS_IF([test \"$arch\" = \"amd64 i386\"], [\n\t\t    AS_IF([test \"$GCC\" = yes], [\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)\n\t\t\t\tdo64bit_ok=yes\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tAC_MSG_WARN([64bit mode not supported with GCC on $system]);;\n\t\t\tesac\n\t\t    ], [\n\t\t\tdo64bit_ok=yes\n\t\t\tcase $system in\n\t\t\t    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)\n\t\t\t\tCFLAGS=\"$CFLAGS -m64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -m64\";;\n\t\t\t    *)\n\t\t\t\tCFLAGS=\"$CFLAGS -xarch=amd64\"\n\t\t\t\tLDFLAGS=\"$LDFLAGS -xarch=amd64\";;\n\t\t\tesac\n\t\t    ])\n\t\t], [AC_MSG_WARN([64bit mode not supported for $arch])])])\n\t    ])\n\n\t    #--------------------------------------------------------------------\n\t    # On Solaris 5.x i386 with the sunpro compiler we need to link\n\t    # with sunmath to get floating point rounding control\n\t    #--------------------------------------------------------------------\n\t    AS_IF([test \"$GCC\" = yes],[use_sunmath=no],[\n\t\tarch=`isainfo`\n\t\tAC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])\n\t\tAS_IF([test \"$arch\" = \"amd64 i386\" -o \"$arch\" = \"i386\"], [\n\t\t\tAC_MSG_RESULT([yes])\n\t\t\tMATH_LIBS=\"-lsunmath $MATH_LIBS\"\n\t\t\tAC_CHECK_HEADER(sunmath.h)\n\t\t\tuse_sunmath=yes\n\t\t\t], [\n\t\t\tAC_MSG_RESULT([no])\n\t\t\tuse_sunmath=no\n\t\t])\n\t    ])\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    AS_IF([test \"$GCC\" = yes], [\n\t\tSHLIB_LD='${CC} -shared'\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}\n\t\tAS_IF([test \"$do64bit_ok\" = yes], [\n\t\t    AS_IF([test \"$arch\" = \"sparcv9 sparc\"], [\n\t\t\t# We need to specify -static-libgcc or we need to\n\t\t\t# add the path to the sparv9 libgcc.\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -mcpu=v9 -static-libgcc\"\n\t\t\t# for finding sparcv9 libgcc, get the regular libgcc\n\t\t\t# path, remove so name and append 'sparcv9'\n\t\t\t#v9gcclibdir=\"`gcc -print-file-name=libgcc_s.so` | ...\"\n\t\t\t#CC_SEARCH_FLAGS=\"${CC_SEARCH_FLAGS},-R,$v9gcclibdir\"\n\t\t    ], [AS_IF([test \"$arch\" = \"amd64 i386\"], [\n\t\t\tSHLIB_LD=\"$SHLIB_LD -m64 -static-libgcc\"\n\t\t    ])])\n\t\t])\n\t    ], [\n\t\tAS_IF([test \"$use_sunmath\" = yes], [textmode=textoff],[textmode=text])\n\t\tcase $system in\n\t\t    SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]])\n\t\t\tSHLIB_LD=\"\\${CC} -G -z $textmode \\${LDFLAGS}\";;\n\t\t    *)\n\t\t\tSHLIB_LD=\"/usr/ccs/bin/ld -G -z $textmode\";;\n\t\tesac\n\t\tCC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'\n\t\tLD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'\n\t    ])\n\t    ;;\n\tUNIX_SV* | UnixWare-5*)\n\t    SHLIB_CFLAGS=\"-KPIC\"\n\t    SHLIB_LD='${CC} -G'\n\t    SHLIB_LD_LIBS=\"\"\n\t    SHLIB_SUFFIX=\".so\"\n\t    DL_OBJS=\"tclLoadDl.o\"\n\t    DL_LIBS=\"-ldl\"\n\t    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers\n\t    # that don't grok the -Bexport option.  Test that it does.\n\t    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [\n\t\thold_ldflags=$LDFLAGS\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t\tAC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no])\n\t\tLDFLAGS=$hold_ldflags])\n\t    AS_IF([test $tcl_cv_ld_Bexport = yes], [\n\t\tLDFLAGS=\"$LDFLAGS -Wl,-Bexport\"\n\t    ])\n\t    CC_SEARCH_FLAGS=\"\"\n\t    LD_SEARCH_FLAGS=\"\"\n\t    ;;\n    esac\n\n    AS_IF([test \"$do64bit\" = yes -a \"$do64bit_ok\" = no], [\n\tAC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])\n    ])\n\n    AS_IF([test \"$do64bit\" = yes -a \"$do64bit_ok\" = yes], [\n\tAC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?])\n    ])\n\ndnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so\ndnl # until the end of configure, as configure's compile and link tests use\ndnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's\ndnl # preprocessing tests use only CPPFLAGS.\n    AC_CONFIG_COMMANDS_PRE([CFLAGS=\"${CFLAGS} ${CPPFLAGS}\"; CPPFLAGS=\"\"])\n\n    # Step 4: disable dynamic loading if requested via a command-line switch.\n\n    AC_ARG_ENABLE(load,\n\tAS_HELP_STRING([--enable-load],\n\t    [allow dynamic loading and \"load\" command (default: on)]),\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n    AS_IF([test \"$tcl_ok\" = no], [DL_OBJS=\"\"])\n\n    AS_IF([test \"x$DL_OBJS\" != x], [BUILD_DLTEST=\"\\$(DLTEST_TARGETS)\"], [\n\tAC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])\n\tSHLIB_CFLAGS=\"\"\n\tSHLIB_LD=\"\"\n\tSHLIB_SUFFIX=\"\"\n\tDL_OBJS=\"tclLoadNone.o\"\n\tDL_LIBS=\"\"\n\tLDFLAGS=\"$LDFLAGS_ORIG\"\n\tCC_SEARCH_FLAGS=\"\"\n\tLD_SEARCH_FLAGS=\"\"\n\tBUILD_DLTEST=\"\"\n    ])\n    LDFLAGS=\"$LDFLAGS $LDFLAGS_ARCH\"\n\n    # If we're running gcc, then change the C flags for compiling shared\n    # libraries to the right flags for gcc, instead of those for the\n    # standard manufacturer compiler.\n\n    AS_IF([test \"$DL_OBJS\" != \"tclLoadNone.o\" -a \"$GCC\" = yes], [\n\tcase $system in\n\t    AIX-*) ;;\n\t    BSD/OS*) ;;\n\t    CYGWIN_*|MINGW32_*|MSYS_*) ;;\n\t    HP-UX*) ;;\n\t    Darwin-*) ;;\n\t    IRIX*) ;;\n\t    Linux*|GNU*) ;;\n\t    NetBSD-*|OpenBSD-*) ;;\n\t    OSF1-*) ;;\n\t    SCO_SV-3.2*) ;;\n\t    *) SHLIB_CFLAGS=\"-fPIC\" ;;\n\tesac])\n\n    AS_IF([test \"$tcl_cv_cc_visibility_hidden\" != yes], [\n\tAC_DEFINE(MODULE_SCOPE, [extern],\n\t    [No Compiler support for module scope symbols])\n    ])\n\n    AS_IF([test \"$SHARED_LIB_SUFFIX\" = \"\"], [\n\tSHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])\n    AS_IF([test \"$UNSHARED_LIB_SUFFIX\" = \"\"], [\n\tUNSHARED_LIB_SUFFIX='${VERSION}.a'])\n    DLL_INSTALL_DIR=\"\\$(LIB_INSTALL_DIR)\"\n\n    AS_IF([test \"${SHARED_BUILD}\" = 1 -a \"${SHLIB_SUFFIX}\" != \"\"], [\n\tLIB_SUFFIX=${SHARED_LIB_SUFFIX}\n\tMAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'\n\tAS_IF([test \"${SHLIB_SUFFIX}\" = \".dll\"], [\n\t    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(BIN_INSTALL_DIR)/$(LIB_FILE)\"'\n\t    DLL_INSTALL_DIR=\"\\$(BIN_INSTALL_DIR)\"\n\t], [\n\t    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(LIB_INSTALL_DIR)/$(LIB_FILE)\"'\n\t])\n    ], [\n\tLIB_SUFFIX=${UNSHARED_LIB_SUFFIX}\n\n\tAS_IF([test \"$RANLIB\" = \"\"], [\n\t    MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'\n\t], [\n\t    MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'\n\t])\n\tINSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) \"$(LIB_INSTALL_DIR)/$(LIB_FILE)\"'\n    ])\n\n    # Stub lib does not depend on shared/static configuration\n    AS_IF([test \"$RANLIB\" = \"\"], [\n\tMAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'\n    ], [\n\tMAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'\n    ])\n    INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) \"$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)\"'\n\n    # Define TCL_LIBS now that we know what DL_LIBS is.\n    # The trick here is that we don't want to change the value of TCL_LIBS if\n    # it is already set when tclConfig.sh had been loaded by Tk.\n    AS_IF([test \"x${TCL_LIBS}\" = x], [\n\tTCL_LIBS=\"${DL_LIBS} ${LIBS} ${MATH_LIBS}\"])\n    AC_SUBST(TCL_LIBS)\n\n    # See if the compiler supports casting to a union type.\n    # This is used to stop gcc from printing a compiler\n    # warning when initializing a union member.\n\n    AC_CACHE_CHECK(for cast to union support,\n\ttcl_cv_cast_to_union,\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[\n\t\tunion foo { int i; double d; };\n\t\tunion foo f = (union foo) (int) 0;\n\t]])],\n\t[tcl_cv_cast_to_union=yes],\n\t[tcl_cv_cast_to_union=no])\n    )\n    if test \"$tcl_cv_cast_to_union\" = \"yes\"; then\n\tAC_DEFINE(HAVE_CAST_TO_UNION, 1,\n\t\t[Defined when compiler supports casting to union type.])\n    fi\n    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -fno-lto\"\n    AC_CACHE_CHECK(for working -fno-lto,\n\tac_cv_nolto,\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],\n\t[ac_cv_nolto=yes],\n\t[ac_cv_nolto=no])\n    )\n    CFLAGS=$hold_cflags\n    if test \"$ac_cv_nolto\" = \"yes\" ; then\n\tCFLAGS_NOLTO=\"-fno-lto\"\n    else\n\tCFLAGS_NOLTO=\"\"\n    fi\n    AC_CACHE_CHECK([if the compiler understands -finput-charset],\n\ttcl_cv_cc_input_charset, [\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_input_charset=yes],[tcl_cv_cc_input_charset=no])\n\tCFLAGS=$hold_cflags])\n    if test $tcl_cv_cc_input_charset = yes; then\n\tCFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n    fi\n\n    # Check for vfork, posix_spawnp() and friends unconditionally\n    AC_CHECK_FUNCS(vfork posix_spawnp posix_spawn_file_actions_adddup2 posix_spawnattr_setflags)\n\n    # FIXME: This subst was left in only because the TCL_DL_LIBS\n    # entry in tclConfig.sh uses it. It is not clear why someone\n    # would use TCL_DL_LIBS instead of TCL_LIBS.\n    AC_SUBST(DL_LIBS)\n\n    AC_SUBST(DL_OBJS)\n    AC_SUBST(PLAT_OBJS)\n    AC_SUBST(PLAT_SRCS)\n    AC_SUBST(LDAIX_SRC)\n    AC_SUBST(CFLAGS)\n    AC_SUBST(CFLAGS_DEBUG)\n    AC_SUBST(CFLAGS_OPTIMIZE)\n    AC_SUBST(CFLAGS_WARNING)\n    AC_SUBST(CFLAGS_NOLTO)\n\n    AC_SUBST(LDFLAGS)\n    AC_SUBST(LDFLAGS_DEBUG)\n    AC_SUBST(LDFLAGS_OPTIMIZE)\n    AC_SUBST(CC_SEARCH_FLAGS)\n    AC_SUBST(LD_SEARCH_FLAGS)\n\n    AC_SUBST(STLIB_LD)\n    AC_SUBST(SHLIB_LD)\n    AC_SUBST(TCL_SHLIB_LD_EXTRAS)\n    AC_SUBST(TK_SHLIB_LD_EXTRAS)\n    AC_SUBST(SHLIB_LD_LIBS)\n    AC_SUBST(SHLIB_CFLAGS)\n    AC_SUBST(SHLIB_SUFFIX)\n    AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,\"${SHLIB_SUFFIX}\",\n\t[What is the default extension for shared libraries?])\n\n    AC_SUBST(MAKE_LIB)\n    AC_SUBST(MAKE_STUB_LIB)\n    AC_SUBST(INSTALL_LIB)\n    AC_SUBST(DLL_INSTALL_DIR)\n    AC_SUBST(INSTALL_STUB_LIB)\n    AC_SUBST(RANLIB)\n])\n\n#--------------------------------------------------------------------\n# SC_MISSING_POSIX_HEADERS\n#\n#\tSupply substitutes for missing POSIX header files.  Special\n#\tnotes:\n#\t    - stdlib.h doesn't define strtol or strtoul in some\n#\t      versions of SunOS\n#\t    - some versions of string.h don't declare procedures such\n#\t      as strstr\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tNO_SYS_WAIT_H\n#\t\tNO_DLFCN_H\n#\t\tHAVE_SYS_PARAM_H\n#\t\tHAVE_STRING_H ?\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_MISSING_POSIX_HEADERS], [\n    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)\n    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)\n    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)\n\n    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])\n    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])\n\n    # OS/390 lacks sys/param.h (and doesn't need it, by chance).\n    AC_CHECK_HEADERS([sys/param.h])\n])\n\n#--------------------------------------------------------------------\n# SC_PATH_X\n#\n#\tLocate the X11 header files and the X11 library archive.  Try\n#\tthe ac_path_x macro first, but if it doesn't find the X stuff\n#\t(e.g. because there's no xmkmf program) then check through\n#\ta list of possible directories.  Under some conditions the\n#\tautoconf macro will return an include directory that contains\n#\tno include files, so double-check its result just to be safe.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tSets the following vars:\n#\t\tXINCLUDES\n#\t\tXLIBSW\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_PATH_X], [\n    AC_PATH_X\n    not_really_there=\"\"\n    if test \"$no_x\" = \"\"; then\n\tif test \"$x_includes\" = \"\"; then\n\t    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[],[not_really_there=\"yes\"])\n\telse\n\t    if test ! -r $x_includes/X11/Xlib.h; then\n\t\tnot_really_there=\"yes\"\n\t    fi\n\tfi\n    fi\n    if test \"$no_x\" = \"yes\" -o \"$not_really_there\" = \"yes\"; then\n\tAC_MSG_CHECKING([for X11 header files])\n\tfound_xincludes=\"no\"\n\tAC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[found_xincludes=\"yes\"],[found_xincludes=\"no\"])\n\tif test \"$found_xincludes\" = \"no\"; then\n\t    dirs=\"/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include\"\n\t    for i in $dirs ; do\n\t\tif test -r $i/X11/Xlib.h; then\n\t\t    AC_MSG_RESULT([$i])\n\t\t    XINCLUDES=\" -I$i\"\n\t\t    found_xincludes=\"yes\"\n\t\t    break\n\t\tfi\n\t    done\n\tfi\n    else\n\tif test \"$x_includes\" != \"\"; then\n\t    XINCLUDES=\"-I$x_includes\"\n\t    found_xincludes=\"yes\"\n\tfi\n    fi\n    if test \"$found_xincludes\" = \"no\"; then\n\tAC_MSG_RESULT([couldn't find any!])\n    fi\n\n    if test \"$no_x\" = yes; then\n\tAC_MSG_CHECKING([for X11 libraries])\n\tXLIBSW=nope\n\tdirs=\"/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib\"\n\tfor i in $dirs ; do\n\t    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then\n\t\tAC_MSG_RESULT([$i])\n\t\tXLIBSW=\"-L$i -lX11\"\n\t\tx_libraries=\"$i\"\n\t\tbreak\n\t    fi\n\tdone\n    else\n\tif test \"$x_libraries\" = \"\"; then\n\t    XLIBSW=-lX11\n\telse\n\t    XLIBSW=\"-L$x_libraries -lX11\"\n\tfi\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\tAC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)\n    fi\n    if test \"$XLIBSW\" = nope ; then\n\tAC_MSG_RESULT([could not find any!  Using -lX11.])\n\tXLIBSW=-lX11\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_BLOCKING_STYLE\n#\n#\tThe statements below check for systems where POSIX-style\n#\tnon-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.\n#\tOn these systems (mostly older ones), use the old BSD-style\n#\tFIONBIO approach instead.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tHAVE_SYS_IOCTL_H\n#\t\tHAVE_SYS_FILIO_H\n#\t\tUSE_FIONBIO\n#\t\tO_NONBLOCK\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_BLOCKING_STYLE], [\n    AC_CHECK_HEADERS(sys/ioctl.h)\n    AC_CHECK_HEADERS(sys/filio.h)\n    SC_CONFIG_SYSTEM\n    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])\n    case $system in\n\tOSF*)\n\t    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])\n\t    AC_MSG_RESULT([FIONBIO])\n\t    ;;\n\t*)\n\t    AC_MSG_RESULT([O_NONBLOCK])\n\t    ;;\n    esac\n])\n\n#--------------------------------------------------------------------\n# SC_TIME_HANLDER\n#\n#\tChecks how the system deals with time.h, what time structures\n#\tare used on the system, and what fields the structures have.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tDefines some of the following vars:\n#\t\tUSE_DELTA_FOR_TZ\n#\t\tHAVE_TM_GMTOFF\n#\t\tHAVE_TM_TZADJ\n#\t\tHAVE_TIMEZONE_VAR\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TIME_HANDLER], [\n    AC_CHECK_HEADERS(sys/time.h)\n    AC_CHECK_HEADERS_ONCE([sys/time.h])\n\n    AC_CHECK_FUNCS(gmtime_r localtime_r)\n\n    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_tzadj;]])],\n\t    [tcl_cv_member_tm_tzadj=yes],\n\t    [tcl_cv_member_tm_tzadj=no])])\n    if test $tcl_cv_member_tm_tzadj = yes ; then\n\tAC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])\n    fi\n\n    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_gmtoff;]])],\n\t    [tcl_cv_member_tm_gmtoff=yes],\n\t    [tcl_cv_member_tm_gmtoff=no])])\n    if test $tcl_cv_member_tm_gmtoff = yes ; then\n\tAC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])\n    fi\n\n    #\n    # Its important to include time.h in this check, as some systems\n    # (like convex) have timezone functions, etc.\n    #\n    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>\n#include <stdlib.h>]],\n\t[[extern long timezone;\n\t    timezone += 1;\n\t    exit (0);]])],\n\t    [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])])\n    if test $tcl_cv_timezone_long = yes ; then\n\tAC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])\n    else\n\t#\n\t# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.\n\t#\n\tAC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>\n#include <stdlib.h>]],\n\t    [[extern time_t timezone;\n\t\ttimezone += 1;\n\t\texit (0);]])],\n\t\t[tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])])\n\tif test $tcl_cv_timezone_time = yes ; then\n\t    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])\n\tfi\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_LINK_LIBS\n#\n#\tSearch for the libraries needed to link the Tcl shell.\n#\tThings like the math library (-lm), socket stuff (-lsocket vs.\n#\t-lnsl), zlib (-lz) and libtommath (-ltommath) or thread library\n#\t(-lpthread) are dealt with here.\n#\n# Arguments:\n#\tNone.\n#\n# Results:\n#\n#\tSets the following vars:\n#\t\tTHREADS_LIBS\tThread library(s)\n#\n#\tDefines the following vars:\n#\t\t_REENTRANT\n#\t\t_THREAD_SAFE\n#\n#\tMight append to the following vars:\n#\t\tLIBS\n#\t\tMATH_LIBS\n#\n#\tMight define the following vars:\n#\t\tHAVE_NET_ERRNO_H\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_LINK_LIBS], [\n    #--------------------------------------------------------------------\n    # On a few very rare systems, all of the libm.a stuff is\n    # already in libc.a.  Set compiler flags accordingly.\n    #--------------------------------------------------------------------\n\n    AC_CHECK_FUNC(sin, MATH_LIBS=\"\", MATH_LIBS=\"-lm\")\n\n    #--------------------------------------------------------------------\n    # Interactive UNIX requires -linet instead of -lsocket, plus it\n    # needs net/errno.h to define the socket-related error codes.\n    #--------------------------------------------------------------------\n\n    AC_CHECK_LIB(inet, main, [LIBS=\"$LIBS -linet\"])\n    AC_CHECK_HEADER(net/errno.h, [\n\tAC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])\n\n    #--------------------------------------------------------------------\n    #\tCheck for the existence of the -lsocket and -lnsl libraries.\n    #\tThe order here is important, so that they end up in the right\n    #\torder in the command line generated by make.  Here are some\n    #\tspecial considerations:\n    #\t1. Use \"connect\" and \"accept\" to check for -lsocket, and\n    #\t   \"gethostbyname\" to check for -lnsl.\n    #\t2. Use each function name only once:  can't redo a check because\n    #\t   autoconf caches the results of the last check and won't redo it.\n    #\t3. Use -lnsl and -lsocket only if they supply procedures that\n    #\t   aren't already present in the normal libraries.  This is because\n    #\t   IRIX 5.2 has libraries, but they aren't needed and they're\n    #\t   bogus:  they goof up name resolution if used.\n    #\t4. On some SVR4 systems, can't use -lsocket without -lnsl too.\n    #\t   To get around this problem, check for both libraries together\n    #\t   if -lsocket doesn't work by itself.\n    #--------------------------------------------------------------------\n\n    tcl_checkBoth=0\n    AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)\n    if test \"$tcl_checkSocket\" = 1; then\n\tAC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,\n\t    LIBS=\"$LIBS -lsocket\", tcl_checkBoth=1)])\n    fi\n    if test \"$tcl_checkBoth\" = 1; then\n\ttk_oldLibs=$LIBS\n\tLIBS=\"$LIBS -lsocket -lnsl\"\n\tAC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])\n    fi\n    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,\n\t    [LIBS=\"$LIBS -lnsl\"])])\n\n    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])\n    AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])\n    AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)\n    if test \"$tcl_ok\" = \"no\"; then\n\t# Check a little harder for __pthread_mutex_init in the same\n\t# library, as some systems hide it there until pthread.h is\n\t# defined.  We could alternatively do an AC_TRY_COMPILE with\n\t# pthread.h, but that will work with libpthread really doesn't\n\t# exist, like AIX 4.2.  [Bug: 4359]\n\tAC_CHECK_LIB(pthread, __pthread_mutex_init,\n\t\ttcl_ok=yes, tcl_ok=no)\n    fi\n\n    if test \"$tcl_ok\" = \"yes\"; then\n\t# The space is needed\n\tTHREADS_LIBS=\" -lpthread\"\n    else\n\tAC_CHECK_LIB(pthreads, pthread_mutex_init,\n\t_ok=yes, tcl_ok=no)\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    # The space is needed\n\t    THREADS_LIBS=\" -lpthreads\"\n\telse\n\t    AC_CHECK_LIB(c, pthread_mutex_init,\n\t\t    tcl_ok=yes, tcl_ok=no)\n\t    if test \"$tcl_ok\" = \"no\"; then\n\t\tAC_CHECK_LIB(c_r, pthread_mutex_init,\n\t\t\ttcl_ok=yes, tcl_ok=no)\n\t\tif test \"$tcl_ok\" = \"yes\"; then\n\t\t    # The space is needed\n\t\t    THREADS_LIBS=\" -pthread\"\n\t\telse\n\t\t    AC_MSG_WARN([Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile...])\n\t\tfi\n\t    fi\n\tfi\n    fi\n\n    # Does the pthread-implementation provide\n    # 'pthread_attr_setstacksize' ?\n\n    ac_saved_libs=$LIBS\n    LIBS=\"$LIBS $THREADS_LIBS\"\n    AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)\n    LIBS=$ac_saved_libs\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_EARLY_FLAGS\n#\n#\tCheck for what flags are needed to be passed so the correct OS\n#\tfeatures are available.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\t_ISOC99_SOURCE\n#\t\t_FILE_OFFSET_BITS\n#\t\t_LARGEFILE64_SOURCE\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_EARLY_FLAG],[\n    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])],\n\t    [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[\n]$2]], [[$3]])],\n\t[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,\n\t[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)]))\n    if test [\"x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}\" = \"xyes\"] ; then\n\tAC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building])\n\ttcl_flags=\"$tcl_flags $1\"\n    fi\n])\n\nAC_DEFUN([SC_TCL_EARLY_FLAGS],[\n    AC_MSG_CHECKING([for required early compiler flags])\n    tcl_flags=\"\"\n    SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],\n\t[char *p = (char *)strtoll; char *q = (char *)strtoull;])\n    SC_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include <sys/stat.h>],\n\t[switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64)\n    SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],\n\t[struct stat64 buf; int i = stat64(\"/\", &buf);])\n    if test \"x${tcl_flags}\" = \"x\" ; then\n\tAC_MSG_RESULT([none])\n    else\n\tAC_MSG_RESULT([${tcl_flags}])\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_64BIT_FLAGS\n#\n#\tCheck for what is defined in the way of 64-bit features.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tTCL_WIDE_INT_IS_LONG\n#\t\tHAVE_STRUCT_DIRENT64, HAVE_DIR64\n#\t\tHAVE_TYPE_OFF64_T\n#\t\t_TIME_BITS\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_64BIT_FLAGS], [\n    AC_MSG_CHECKING([if 'long' and 'long long' have the same size (64-bit)?])\n    AC_CACHE_VAL(tcl_cv_type_64bit,[\n\ttcl_cv_type_64bit=none\n\t# See if we could use long anyway  Note that we substitute in the\n\t# type that is our current guess for a 64-bit type inside this check\n\t# program, so it should be modified only carefully...\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) {\n\t    case 1: case (sizeof(long long)==sizeof(long)): ;\n\t}]])],[tcl_cv_type_64bit=\"long long\"],[])])\n    if test \"${tcl_cv_type_64bit}\" = none ; then\n\tAC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?])\n\tAC_MSG_RESULT([yes])\n    else\n\tAC_MSG_RESULT([no])\n\t# Now check for auxiliary declarations\n\tAC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]],\n\t\t[[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])],\n\t\t[tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])])\n\tif test \"x${tcl_cv_time_t_64}\" = \"xno\" ; then\n\t    # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64\n\t    # which SC_TCL_EARLY_FLAGS has defined if necessary.\n\t    AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[\n\t\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64\n#include <sys/types.h>]],\n\t\t    [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])],\n\t\t    [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])])\n\t    if test \"x${tcl_cv__time_bits}\" = \"xyes\" ; then\n\t\tAC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.])\n\t    fi\n\tfi\n\n\tAC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>\n#include <dirent.h>]], [[struct dirent64 p;]])],\n\t\t[tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])])\n\tif test \"x${tcl_cv_struct_dirent64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])\n\tfi\n\n\tAC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>\n#include <dirent.h>]], [[struct dirent64 *p; DIR64 d = opendir64(\".\");\n\t    p = readdir64(d); rewinddir64(d); closedir64(d);]])],\n\t\t[tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])])\n\tif test \"x${tcl_cv_DIR64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])\n\tfi\n\n\tAC_CHECK_FUNCS(open64 lseek64)\n\tAC_MSG_CHECKING([for off64_t])\n\tAC_CACHE_VAL(tcl_cv_type_off64_t,[\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[off64_t offset;\n]])],\n\t\t[tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])])\n\tdnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the\n\tdnl functions lseek64 and open64 are defined.\n\tif test \"x${tcl_cv_type_off64_t}\" = \"xyes\" && \\\n\t\ttest \"x${ac_cv_func_lseek64}\" = \"xyes\" && \\\n\t\ttest \"x${ac_cv_func_open64}\" = \"xyes\" ; then\n\t    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])\n\t    AC_MSG_RESULT([yes])\n\telse\n\t    AC_MSG_RESULT([no])\n\tfi\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_CFG_ENCODING\tTIP #59\n#\n#\tDeclare the encoding to use for embedded configuration information.\n#\n# Arguments:\n#\tNone.\n#\n# Results:\n#\tMight append to the following vars:\n#\t\tDEFS\t(implicit)\n#\n#\tWill define the following vars:\n#\t\tTCL_CFGVAL_ENCODING\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_CFG_ENCODING], [\n    AC_ARG_WITH(encoding,\n\tAS_HELP_STRING([--with-encoding],\n\t    [encoding for configuration values (default: utf-8)]),\n\t[with_tcencoding=${withval}])\n\n    if test x\"${with_tcencoding}\" != x ; then\n\tAC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,\"${with_tcencoding}\",\n\t    [What encoding should be used for embedded configuration info?])\n    else\n\tAC_DEFINE(TCL_CFGVAL_ENCODING,\"utf-8\",\n\t    [What encoding should be used for embedded configuration info?])\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_CHECK_BROKEN_FUNC\n#\n#\tCheck for broken function.\n#\n# Arguments:\n#\tfuncName - function to test for\n#\tadvancedTest - the advanced test to run if the function is present\n#\n# Results:\n#\tMight cause compatibility versions of the function to be used.\n#\tMight affect the following vars:\n#\t\tUSE_COMPAT\t(implicit)\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[\n    AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)\n    if test [\"$tcl_ok\"] = 1; then\n\tAC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],\n\t    AC_RUN_IFELSE([AC_LANG_SOURCE([[[\n#include <stdlib.h>\n#include <string.h>\nint main() {]$2[}]]])],[tcl_cv_$1_unbroken=ok],\n\t\t[tcl_cv_$1_unbroken=broken],[tcl_cv_$1_unbroken=unknown]))\n\tif test [\"$tcl_cv_]$1[_unbroken\"] = \"ok\"; then\n\t    tcl_ok=1\n\telse\n\t    tcl_ok=0\n\tfi\n    fi\n    if test [\"$tcl_ok\"] = 0; then\n\tAC_LIBOBJ($1)\n\tUSE_COMPAT=1\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETHOSTBYADDR_R\n#\n#\tCheck if we have MT-safe variant of gethostbyaddr().\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETHOSTBYADDR_R\n#\t\tHAVE_GETHOSTBYADDR_R_7\n#\t\tHAVE_GETHOSTBYADDR_R_8\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [\n    # Avoids picking hidden internal symbol from libc\n    SC_TCL_GETHOSTBYADDR_R_DECL\n\n    if test \"$tcl_cv_api_gethostbyaddr_r\" = yes; then\n\tSC_TCL_GETHOSTBYADDR_R_TYPE\n    fi\n])\n\nAC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [\n    tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include <netdb.h>])\n])\n\nAC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [\n    AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <netdb.h>\n    ]], [[\n\tchar *addr;\n\tint length;\n\tint type;\n\tstruct hostent *result;\n\tchar buffer[2048];\n\tint buflen = 2048;\n\tint h_errnop;\n\n\t(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,\n\t\t\t       &h_errnop);\n    ]])],[tcl_cv_api_gethostbyaddr_r_7=yes],[tcl_cv_api_gethostbyaddr_r_7=no])])\n    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,\n\t    [Define to 1 if gethostbyaddr_r takes 7 args.])\n    else\n\tAC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <netdb.h>\n\t]], [[\n\t    char *addr;\n\t    int length;\n\t    int type;\n\t    struct hostent *result, *resultp;\n\t    char buffer[2048];\n\t    int buflen = 2048;\n\t    int h_errnop;\n\n\t    (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,\n\t\t\t\t   &resultp, &h_errnop);\n\t]])],[tcl_cv_api_gethostbyaddr_r_8=yes],[tcl_cv_api_gethostbyaddr_r_8=no])])\n\ttcl_ok=$tcl_cv_api_gethostbyaddr_r_8\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,\n\t\t[Define to 1 if gethostbyaddr_r takes 8 args.])\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETHOSTBYADDR_R, 1,\n\t    [Define to 1 if gethostbyaddr_r is available.])\n    fi\n])])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETHOSTBYNAME_R\n#\n#\tCheck to see what variant of gethostbyname_r() we have.\n#\tBased on David Arnold's example from the comp.programming.threads\n#\tFAQ Q213\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETHOSTBYNAME_R\n#\t\tHAVE_GETHOSTBYNAME_R_3\n#\t\tHAVE_GETHOSTBYNAME_R_5\n#\t\tHAVE_GETHOSTBYNAME_R_6\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [\n    # Avoids picking hidden internal symbol from libc\n    SC_TCL_GETHOSTBYNAME_R_DECL\n\n    if test \"$tcl_cv_api_gethostbyname_r\" = yes; then\n\tSC_TCL_GETHOSTBYNAME_R_TYPE\n    fi\n])\n\nAC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [\n    tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include <netdb.h>])\n])\n\nAC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [\n    AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <netdb.h>\n    ]], [[\n\tchar *name;\n\tstruct hostent *he, *res;\n\tchar buffer[2048];\n\tint buflen = 2048;\n\tint h_errnop;\n\n\t(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);\n    ]])],[tcl_cv_api_gethostbyname_r_6=yes],[tcl_cv_api_gethostbyname_r_6=no])])\n    tcl_ok=$tcl_cv_api_gethostbyname_r_6\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,\n\t    [Define to 1 if gethostbyname_r takes 6 args.])\n    else\n\tAC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <netdb.h>\n\t]], [[\n\t    char *name;\n\t    struct hostent *he;\n\t    char buffer[2048];\n\t    int buflen = 2048;\n\t    int h_errnop;\n\n\t    (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);\n\t]])],[tcl_cv_api_gethostbyname_r_5=yes],[tcl_cv_api_gethostbyname_r_5=no])])\n\ttcl_ok=$tcl_cv_api_gethostbyname_r_5\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,\n\t\t[Define to 1 if gethostbyname_r takes 5 args.])\n\telse\n\t    AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t#include <netdb.h>\n\t    ]], [[\n\t\tchar *name;\n\t\tstruct hostent *he;\n\t\tstruct hostent_data data;\n\n\t\t(void) gethostbyname_r(name, he, &data);\n\t    ]])],[tcl_cv_api_gethostbyname_r_3=yes],[tcl_cv_api_gethostbyname_r_3=no])])\n\t    tcl_ok=$tcl_cv_api_gethostbyname_r_3\n\t    if test \"$tcl_ok\" = yes; then\n\t\tAC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,\n\t\t    [Define to 1 if gethostbyname_r takes 3 args.])\n\t    fi\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETHOSTBYNAME_R, 1,\n\t    [Define to 1 if gethostbyname_r is available.])\n    fi\n])])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETPWUID_R\n#\n#\tCheck if we have MT-safe variant of getpwuid() and if yes,\n#\twhich one exactly.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETPWUID_R\n#\t\tHAVE_GETPWUID_R_4\n#\t\tHAVE_GETPWUID_R_5\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [\n    AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <sys/types.h>\n\t#include <pwd.h>\n    ]], [[\n\tuid_t uid;\n\tstruct passwd pw, *pwp;\n\tchar buf[512];\n\tint buflen = 512;\n\n\t(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);\n    ]])],[tcl_cv_api_getpwuid_r_5=yes],[tcl_cv_api_getpwuid_r_5=no])])\n    tcl_ok=$tcl_cv_api_getpwuid_r_5\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETPWUID_R_5, 1,\n\t    [Define to 1 if getpwuid_r takes 5 args.])\n    else\n\tAC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <sys/types.h>\n\t    #include <pwd.h>\n\t]], [[\n\t    uid_t uid;\n\t    struct passwd pw;\n\t    char buf[512];\n\t    int buflen = 512;\n\n\t    (void)getpwnam_r(uid, &pw, buf, buflen);\n\t]])],[tcl_cv_api_getpwuid_r_4=yes],[tcl_cv_api_getpwuid_r_4=no])])\n\ttcl_ok=$tcl_cv_api_getpwuid_r_4\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETPWUID_R_4, 1,\n\t\t[Define to 1 if getpwuid_r takes 4 args.])\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETPWUID_R, 1,\n\t    [Define to 1 if getpwuid_r is available.])\n    fi\n])])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETPWNAM_R\n#\n#\tCheck if we have MT-safe variant of getpwnam() and if yes,\n#\twhich one exactly.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETPWNAM_R\n#\t\tHAVE_GETPWNAM_R_4\n#\t\tHAVE_GETPWNAM_R_5\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [\n    AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <sys/types.h>\n\t#include <pwd.h>\n    ]], [[\n\tchar *name;\n\tstruct passwd pw, *pwp;\n\tchar buf[512];\n\tint buflen = 512;\n\n\t(void) getpwnam_r(name, &pw, buf, buflen, &pwp);\n    ]])],[tcl_cv_api_getpwnam_r_5=yes],[tcl_cv_api_getpwnam_r_5=no])])\n    tcl_ok=$tcl_cv_api_getpwnam_r_5\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETPWNAM_R_5, 1,\n\t    [Define to 1 if getpwnam_r takes 5 args.])\n    else\n\tAC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <sys/types.h>\n\t    #include <pwd.h>\n\t]], [[\n\t    char *name;\n\t    struct passwd pw;\n\t    char buf[512];\n\t    int buflen = 512;\n\n\t    (void)getpwnam_r(name, &pw, buf, buflen);\n\t]])],[tcl_cv_api_getpwnam_r_4=yes],[tcl_cv_api_getpwnam_r_4=no])])\n\ttcl_ok=$tcl_cv_api_getpwnam_r_4\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETPWNAM_R_4, 1,\n\t\t[Define to 1 if getpwnam_r takes 4 args.])\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETPWNAM_R, 1,\n\t    [Define to 1 if getpwnam_r is available.])\n    fi\n])])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETGRGID_R\n#\n#\tCheck if we have MT-safe variant of getgrgid() and if yes,\n#\twhich one exactly.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETGRGID_R\n#\t\tHAVE_GETGRGID_R_4\n#\t\tHAVE_GETGRGID_R_5\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [\n    AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <sys/types.h>\n\t#include <grp.h>\n    ]], [[\n\tgid_t gid;\n\tstruct group gr, *grp;\n\tchar buf[512];\n\tint buflen = 512;\n\n\t(void) getgrgid_r(gid, &gr, buf, buflen, &grp);\n    ]])],[tcl_cv_api_getgrgid_r_5=yes],[tcl_cv_api_getgrgid_r_5=no])])\n    tcl_ok=$tcl_cv_api_getgrgid_r_5\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETGRGID_R_5, 1,\n\t    [Define to 1 if getgrgid_r takes 5 args.])\n    else\n\tAC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <sys/types.h>\n\t    #include <grp.h>\n\t]], [[\n\t    gid_t gid;\n\t    struct group gr;\n\t    char buf[512];\n\t    int buflen = 512;\n\n\t    (void)getgrgid_r(gid, &gr, buf, buflen);\n\t]])],[tcl_cv_api_getgrgid_r_4=yes],[tcl_cv_api_getgrgid_r_4=no])])\n\ttcl_ok=$tcl_cv_api_getgrgid_r_4\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETGRGID_R_4, 1,\n\t\t[Define to 1 if getgrgid_r takes 4 args.])\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETGRGID_R, 1,\n\t    [Define to 1 if getgrgid_r is available.])\n    fi\n])])\n\n#--------------------------------------------------------------------\n# SC_TCL_GETGRNAM_R\n#\n#\tCheck if we have MT-safe variant of getgrnam() and if yes,\n#\twhich one exactly.\n#\n# Arguments:\n#\tNone\n#\n# Results:\n#\n#\tMight define the following vars:\n#\t\tHAVE_GETGRNAM_R\n#\t\tHAVE_GETGRNAM_R_4\n#\t\tHAVE_GETGRNAM_R_5\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [\n    AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t#include <sys/types.h>\n\t#include <grp.h>\n    ]], [[\n\tchar *name;\n\tstruct group gr, *grp;\n\tchar buf[512];\n\tint buflen = 512;\n\n\t(void) getgrnam_r(name, &gr, buf, buflen, &grp);\n    ]])],[tcl_cv_api_getgrnam_r_5=yes],[tcl_cv_api_getgrnam_r_5=no])])\n    tcl_ok=$tcl_cv_api_getgrnam_r_5\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETGRNAM_R_5, 1,\n\t    [Define to 1 if getgrnam_r takes 5 args.])\n    else\n\tAC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #include <sys/types.h>\n\t    #include <grp.h>\n\t]], [[\n\t    char *name;\n\t    struct group gr;\n\t    char buf[512];\n\t    int buflen = 512;\n\n\t    (void)getgrnam_r(name, &gr, buf, buflen);\n\t]])],[tcl_cv_api_getgrnam_r_4=yes],[tcl_cv_api_getgrnam_r_4=no])])\n\ttcl_ok=$tcl_cv_api_getgrnam_r_4\n\tif test \"$tcl_ok\" = yes; then\n\t    AC_DEFINE(HAVE_GETGRNAM_R_4, 1,\n\t\t[Define to 1 if getgrnam_r takes 4 args.])\n\tfi\n    fi\n    if test \"$tcl_ok\" = yes; then\n\tAC_DEFINE(HAVE_GETGRNAM_R, 1,\n\t    [Define to 1 if getgrnam_r is available.])\n    fi\n])])\n\nAC_DEFUN([SC_TCL_IPV6],[\n\tNEED_FAKE_RFC2553=0\n\tAC_CHECK_FUNCS(getnameinfo getaddrinfo freeaddrinfo gai_strerror,,[NEED_FAKE_RFC2553=1])\n\tAC_CHECK_TYPES([\n\t\tstruct addrinfo,\n\t\tstruct in6_addr,\n\t\tstruct sockaddr_in6,\n\t\tstruct sockaddr_storage],,[NEED_FAKE_RFC2553=1],[[\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netdb.h>\n]])\nif test \"x$NEED_FAKE_RFC2553\" = \"x1\"; then\n   AC_DEFINE([NEED_FAKE_RFC2553], 1,\n\t[Use compat implementation of getaddrinfo() and friends])\n   AC_LIBOBJ([fake-rfc2553])\n   AC_CHECK_FUNC(strlcpy)\nfi\n])\n\n#------------------------------------------------------------------------\n# SC_CC_FOR_BUILD\n#\tFor cross compiles, locate a C compiler that can generate native binaries.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following vars:\n#\t\tCC_FOR_BUILD\n#\t\tEXEEXT_FOR_BUILD\n#------------------------------------------------------------------------\n\ndnl Get a default for CC_FOR_BUILD to put into Makefile.\nAC_DEFUN([AX_CC_FOR_BUILD],[# Put a plausible default for CC_FOR_BUILD in Makefile.\n    if test -z \"$CC_FOR_BUILD\"; then\n      if test \"x$cross_compiling\" = \"xno\"; then\n\tCC_FOR_BUILD='$(CC)'\n      else\n\tAC_MSG_CHECKING([for gcc])\n\tAC_CACHE_VAL(ac_cv_path_cc, [\n\t    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\t    for dir in $search_path ; do\n\t\tfor j in `ls -r $dir/gcc 2> /dev/null` \\\n\t\t\t`ls -r $dir/gcc 2> /dev/null` ; do\n\t\t    if test x\"$ac_cv_path_cc\" = x ; then\n\t\t\tif test -f \"$j\" ; then\n\t\t\t    ac_cv_path_cc=$j\n\t\t\t    break\n\t\t\tfi\n\t\t    fi\n\t\tdone\n\t    done\n\t])\n      fi\n    fi\n    AC_SUBST(CC_FOR_BUILD)\n    # Also set EXEEXT_FOR_BUILD.\n    if test \"x$cross_compiling\" = \"xno\"; then\n      EXEEXT_FOR_BUILD='$(EXEEXT)'\n      OBJEXT_FOR_BUILD='$(OBJEXT)'\n    else\n      OBJEXT_FOR_BUILD='.no'\n      AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,\n\t[rm -f conftest*\n\t echo 'int main () { return 0; }' > conftest.c\n\t bfd_cv_build_exeext=\n\t ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5\n\t for file in conftest.*; do\n\t   case $file in\n\t   *.c | *.o | *.obj | *.ilk | *.pdb) ;;\n\t   *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;\n\t   esac\n\t done\n\t rm -f conftest*\n\t test x\"${bfd_cv_build_exeext}\" = x && bfd_cv_build_exeext=no])\n      EXEEXT_FOR_BUILD=\"\"\n      test x\"${bfd_cv_build_exeext}\" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}\n    fi\n    AC_SUBST(EXEEXT_FOR_BUILD)])dnl\n    AC_SUBST(OBJEXT_FOR_BUILD)])dnl\n])\n\n\n#------------------------------------------------------------------------\n# SC_ZIPFS_SUPPORT\n#\tLocate a zip encoder installed on the system path, or none.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following vars:\n#       MACHER_PROG\n#       ZIP_PROG\n#       ZIP_PROG_OPTIONS\n#       ZIP_PROG_VFSSEARCH\n#       ZIP_INSTALL_OBJS\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ZIPFS_SUPPORT], [\n    MACHER_PROG=\"\"\n    ZIP_PROG=\"\"\n    ZIP_PROG_OPTIONS=\"\"\n    ZIP_PROG_VFSSEARCH=\"\"\n    ZIP_INSTALL_OBJS=\"\"\n\n    AC_MSG_CHECKING([for macher])\n    AC_CACHE_VAL(ac_cv_path_macher, [\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/macher 2> /dev/null` \\\n\t    `ls -r $dir/macher 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_macher\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_macher=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n    ])\n    if test -f \"$ac_cv_path_macher\" ; then\n\tMACHER_PROG=\"$ac_cv_path_macher\"\n\tAC_MSG_RESULT([$MACHER_PROG])\n    else\n\tAC_MSG_RESULT([Macher not found])\n    fi\n    AC_MSG_CHECKING([for zip])\n    AC_CACHE_VAL(ac_cv_path_zip, [\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/zip 2> /dev/null` \\\n\t    `ls -r $dir/zip 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_zip\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_zip=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n    ])\n    if test -f \"$ac_cv_path_zip\" ; then\n\tZIP_PROG=\"$ac_cv_path_zip\"\n\tAC_MSG_RESULT([$ZIP_PROG])\n\tZIP_PROG_OPTIONS=\"-rq\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\t# Use standard arguments for zip\n    else\n\t# It is not an error if an installed version of Zip can't be located.\n\t# We can use the locally distributed minizip instead\n\tZIP_PROG=\"./minizip${EXEEXT_FOR_BUILD}\"\n\tZIP_PROG_OPTIONS=\"-o -r\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\tZIP_INSTALL_OBJS=\"minizip${EXEEXT_FOR_BUILD}\"\n\tAC_MSG_RESULT([No zip found on PATH. Building minizip])\n    fi\n    AC_SUBST(MACHER_PROG)\n    AC_SUBST(ZIP_PROG)\n    AC_SUBST(ZIP_PROG_OPTIONS)\n    AC_SUBST(ZIP_PROG_VFSSEARCH)\n    AC_SUBST(ZIP_INSTALL_OBJS)\n])\n\n# Local Variables:\n# mode: autoconf\n# End:\n"
  },
  {
    "path": "unix/tk.pc.in",
    "content": "# tk pkg-config source file\n\nprefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\nincludedir=@includedir@\ndemodir=@TK_DEMO_DIR@\n\nName: The Tk Toolkit\nDescription: Tk is a cross-platform graphical user interface toolkit, the standard GUI not only for Tcl, but for many other dynamic languages as well.\nURL: https://www.tcl-lang.org/\nVersion: @TK_VERSION@@TK_PATCH_LEVEL@\nRequires: tcl >= 9.0\nLibs: -L${libdir} @TK_LIB_FLAG@ @TK_STUB_LIB_FLAG@\nLibs.private: @XFT_LIBS@ @XLIBSW@\nCflags: -I${includedir}\n"
  },
  {
    "path": "unix/tk.spec",
    "content": "# This file is the basis for a binary Tk Linux RPM.\n\n%{!?directory:%define directory /usr/local}\n\nName:          tk\nSummary:       Tk graphical toolkit for the Tcl scripting language.\nVersion:       9.1a2\nRelease:       2\nLicense:       BSD\nGroup:         Development/Languages\nSource:        https://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz\nURL:           https://www.tcl-lang.org/\nBuildroot:     /var/tmp/%{name}%{version}\nBuildrequires: XFree86-devel tcl >= 9.0.0\nRequires:      tcl >= 9.0.0\n\n%description\nThe Tcl (Tool Command Language) provides a powerful platform for\ncreating integration applications that tie together diverse\napplications, protocols, devices, and frameworks.  When paired with\nthe Tk toolkit, Tcl provides the fastest and most powerful way to\ncreate GUI applications that run on PCs, Unix, and Mac OS X.  Tcl\ncan also be used for a variety of web-related tasks and for creating\npowerful command languages for applications.\n\n%prep\n%setup -q -n %{name}%{version}\n\n%build\ncd unix\nCFLAGS=\"%optflags\" ./configure \\\n\t--prefix=%{directory} \\\n\t--exec-prefix=%{directory} \\\n\t--libdir=%{directory}/%{_lib}\nmake\n\n%install\ncd unix\nmake INSTALL_ROOT=%buildroot install\n\n%clean\nrm -rf %buildroot\n\n%files -n tk\n%defattr(-,root,root)\n%if %{_lib} != lib\n%{directory}/%{_lib}\n%endif\n%{directory}/lib\n%{directory}/bin\n%{directory}/include\n%{directory}/man/man1\n%{directory}/man/man3\n%{directory}/man/mann\n"
  },
  {
    "path": "unix/tkAppInit.c",
    "content": "/*\n * tkAppInit.c --\n *\n *\tProvides a default version of the main program and Tcl_AppInit\n *\tprocedure for wish and other Tk-based applications.\n *\n * Copyright © 1993 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Explanation on following undef USE_TCL_STUBS by JN 2023-12-19 on the core list:\n * What's going on is related to TIP #596:\n *  Stubs support for Embedding Tcl in other applications\n *\n * If an application using Tcl_Main() is compiled with USE_TCL_STUBS,\n * Tcl_Main() will be replaced by a stub function, which loads\n * libtcl9.1.so/tcl91.dll and then calls its Tcl_MainEx(). If\n * libtcl9.1.so/tcl91.dll is not present (at runtime), a crash is what happens.\n *\n * So ... tkAppInit.c should not be compiled with USE_TCL_STUBS\n * (unless you want to use the TIP #596 functionality)\n *\n * The proper solution is to make sure that Makefile.in doesn't use\n * TCL_USE_STUBS when compiling tkAppInit.c. But that's a\n * quite big re-organization just before a b1 release. Simpler\n * is just to #undef'ine USE_TCL_STUBS, it has the same effect.\n */\n#undef USE_TCL_STUBS\n#undef BUILD_tk\n#undef STATIC_BUILD\n#include \"tk.h\"\n#include \"tkPort.h\"\n#if (TCL_MAJOR_VERSION < 9)\n#   define Tcl_LibraryInitProc Tcl_PackageInitProc\n#   define Tcl_StaticLibrary Tcl_StaticPackage\n#endif\n\n#ifdef TK_TEST\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nextern Tcl_LibraryInitProc Tktest_Init;\n#ifdef __cplusplus\n}\n#endif\n#endif /* TK_TEST */\n\n/*\n * The following #if block allows you to change the AppInit function by using\n * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The\n * #if checks for that #define and uses Tcl_AppInit if it doesn't exist.\n */\n\n#ifndef TK_LOCAL_APPINIT\n#define TK_LOCAL_APPINIT Tcl_AppInit\n#endif\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#\tdefine MODULE_SCOPE extern \"C\"\n#   else\n#\tdefine MODULE_SCOPE extern\n#   endif\n#endif\nMODULE_SCOPE int TK_LOCAL_APPINIT(Tcl_Interp *);\nMODULE_SCOPE int main(int, char **);\n\n/*\n * The following #if block allows you to change how Tcl finds the startup\n * script, prime the library or encoding paths, fiddle with the argv, etc.,\n * without needing to rewrite Tk_Main()\n */\n\n#ifdef TK_LOCAL_MAIN_HOOK\nMODULE_SCOPE int TK_LOCAL_MAIN_HOOK(int *argc, char ***argv);\n#endif\n\n/* Make sure the stubbed variants of those are never used. */\n#undef Tcl_ObjSetVar2\n#undef Tcl_NewStringObj\n\f\n/*\n *----------------------------------------------------------------------\n *\n * main --\n *\n *\tThis is the main program for the application.\n *\n * Results:\n *\tNone: Tk_Main never returns here, so this procedure never returns\n *\teither.\n *\n * Side effects:\n *\tJust about anything, since from here we call arbitrary Tcl code.\n *\n *----------------------------------------------------------------------\n */\n\nint\nmain(\n    int argc,\t\t\t/* Number of command-line arguments. */\n    char **argv)\t\t/* Values of command-line arguments. */\n{\n#ifdef TK_LOCAL_MAIN_HOOK\n    TK_LOCAL_MAIN_HOOK(&argc, &argv);\n#elif TCL_MAJOR_VERSION > 8\n    /* This doesn't work with Tcl 8.6 */\n    TclZipfs_AppHook(&argc, &argv);\n#endif\n\n    Tk_Main(argc, argv, TK_LOCAL_APPINIT);\n    return 0;\t\t\t/* Needed only to prevent compiler warning. */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tcl_AppInit --\n *\n *\tThis procedure performs application-specific initialization. Most\n *\tapplications, especially those that incorporate additional packages,\n *\twill have their own version of this procedure.\n *\n * Results:\n *\tReturns a standard Tcl completion code, and leaves an error message in\n *\tthe interp's result if an error occurs.\n *\n * Side effects:\n *\tDepends on the startup script.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTcl_AppInit(\n    Tcl_Interp *interp)\t\t/* Interpreter for application. */\n{\n    if ((Tcl_Init)(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n\n    if (Tk_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Tk\", Tk_Init, Tk_SafeInit);\n\n#if defined(USE_CUSTOM_EXIT_PROC)\n    if (TkpWantsExitProc()) {\n\tTcl_SetExitProc(TkpExitProc);\n    }\n#endif\n\n#ifdef TK_TEST\n    if (Tktest_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Tktest\", Tktest_Init, 0);\n#endif /* TK_TEST */\n\n    /*\n     * Call the init procedures for included packages. Each call should look\n     * like this:\n     *\n     * if (Mod_Init(interp) == TCL_ERROR) {\n     *     return TCL_ERROR;\n     * }\n     *\n     * where \"Mod\" is the name of the module. (Dynamically-loadable packages\n     * should have the same entry-point name.)\n     */\n\n    /*\n     * Call Tcl_CreateObjCommand2 for application-specific commands, if they\n     * weren't already created by the init procedures called above.\n     */\n\n    /*\n     * Specify a user-specific startup file to invoke if the application is\n     * run interactively. Typically the startup file is \"~/.apprc\" where \"app\"\n     * is the name of the application. If this line is deleted then no\n     * user-specific startup file will be run under any conditions.\n     */\n\n    (void) Tcl_EvalEx(interp,\n\t    \"set tcl_rcFileName [file tildeexpand ~/.wishrc]\",\n\t    -1, TCL_EVAL_GLOBAL);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkConfig.h.in",
    "content": "/* ../unix/tkConfig.h.in.  Generated from configure.ac by autoheader.  */\n\n\n    #ifndef _TKCONFIG\n    #define _TKCONFIG\n\n/* Define if ATK and Atk-bridge are available */\n#undef HAVE_ATK\n\n/* Define to 1 if you have the <AvailabilityMacros.h> header file. */\n#undef HAVE_AVAILABILITYMACROS_H\n\n/* Define to 1 if bidirectional text support is enabled */\n#undef HAVE_BIDI\n\n/* Defined when compiler supports casting to union type. */\n#undef HAVE_CAST_TO_UNION\n\n/* Do we have access to Darwin CoreFoundation.framework? */\n#undef HAVE_COREFOUNDATION\n\n/* Is 'DIR64' in <sys/types.h>? */\n#undef HAVE_DIR64\n\n/* Compiler support for module scope symbols */\n#undef HAVE_HIDDEN\n\n/* Define to 1 if the system has the type 'intptr_t'. */\n#undef HAVE_INTPTR_T\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#undef HAVE_INTTYPES_H\n\n/* Define to 1 if you have the 'harfbuzz' library (-lharfbuzz). */\n#undef HAVE_LIBHARFBUZZ\n\n/* Define to 1 if you have the 'Xft' library (-lXft). */\n#undef HAVE_LIBXFT\n\n/* Define to 1 if you have the 'lseek64' function. */\n#undef HAVE_LSEEK64\n\n/* Define to 1 if you have the 'open64' function. */\n#undef HAVE_OPEN64\n\n/* Define to 1 if you have the 'posix_spawnattr_setflags' function. */\n#undef HAVE_POSIX_SPAWNATTR_SETFLAGS\n\n/* Define to 1 if you have the 'posix_spawnp' function. */\n#undef HAVE_POSIX_SPAWNP\n\n/* Define to 1 if you have the 'posix_spawn_file_actions_adddup2' function. */\n#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2\n\n/* Does struct password have a pw_gecos field? */\n#undef HAVE_PW_GECOS\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#undef HAVE_STDINT_H\n\n/* Define to 1 if you have the <stdio.h> header file. */\n#undef HAVE_STDIO_H\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#undef HAVE_STDLIB_H\n\n/* Define to 1 if you have the <strings.h> header file. */\n#undef HAVE_STRINGS_H\n\n/* Define to 1 if you have the <string.h> header file. */\n#undef HAVE_STRING_H\n\n/* Is 'struct dirent64' in <sys/types.h>? */\n#undef HAVE_STRUCT_DIRENT64\n\n/* Should we include <sys/select.h>? */\n#undef HAVE_SYS_SELECT_H\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#undef HAVE_SYS_STAT_H\n\n/* Define to 1 if you have the <sys/time.h> header file. */\n#undef HAVE_SYS_TIME_H\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#undef HAVE_SYS_TYPES_H\n\n/* Is off64_t in <sys/types.h>? */\n#undef HAVE_TYPE_OFF64_T\n\n/* Define to 1 if the system has the type 'uintptr_t'. */\n#undef HAVE_UINTPTR_T\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#undef HAVE_UNISTD_H\n\n/* Define to 1 if you have the 'vfork' function. */\n#undef HAVE_VFORK\n\n/* Have we turned on XFT (antialiased fonts)? */\n#undef HAVE_XFT\n\n/* Is XScreenSaver available? */\n#undef HAVE_XSS\n\n/* Is this a Mac I see before me? */\n#undef MAC_OSX_TCL\n\n/* Are we building TkAqua? */\n#undef MAC_OSX_TK\n\n/* No Compiler support for module scope symbols */\n#undef MODULE_SCOPE\n\n/* Is no debugging enabled? */\n#undef NDEBUG\n\n/* Is Darwin CoreFoundation unavailable for 64-bit? */\n#undef NO_COREFOUNDATION_64\n\n/* Do we have fd_set? */\n#undef NO_FD_SET\n\n/* Define to the address where bug reports for this package should be sent. */\n#undef PACKAGE_BUGREPORT\n\n/* Define to the full name of this package. */\n#undef PACKAGE_NAME\n\n/* Define to the full name and version of this package. */\n#undef PACKAGE_STRING\n\n/* Define to the one symbol short name of this package. */\n#undef PACKAGE_TARNAME\n\n/* Define to the home page for this package. */\n#undef PACKAGE_URL\n\n/* Define to the version of this package. */\n#undef PACKAGE_VERSION\n\n/* Is this a static build? */\n#undef STATIC_BUILD\n\n/* Define to 1 if all of the C89 standard headers exist (not just the ones\n   required in a freestanding environment). This macro is provided for\n   backward compatibility; new code need not use it. */\n#undef STDC_HEADERS\n\n/* What encoding should be used for embedded configuration info? */\n#undef TCL_CFGVAL_ENCODING\n\n/* Is this a 64-bit build? */\n#undef TCL_CFG_DO64BIT\n\n/* Is this an optimized build? */\n#undef TCL_CFG_OPTIMIZED\n\n/* Is bytecode debugging enabled? */\n#undef TCL_COMPILE_DEBUG\n\n/* Are bytecode statistics enabled? */\n#undef TCL_COMPILE_STATS\n\n/* Is memory debugging enabled? */\n#undef TCL_MEM_DEBUG\n\n/* What is the default extension for shared libraries? */\n#undef TCL_SHLIB_EXT\n\n/* Do 'long' and 'long long' have the same size (64-bit)? */\n#undef TCL_WIDE_INT_IS_LONG\n\n/* Is Tk built as a framework? */\n#undef TK_FRAMEWORK\n\n/* Are TkAqua debug messages enabled? */\n#undef TK_MAC_DEBUG\n\n/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most\n   significant byte first (like Motorola and SPARC, unlike Intel). */\n#if defined AC_APPLE_UNIVERSAL_BUILD\n# if defined __BIG_ENDIAN__\n#  define WORDS_BIGENDIAN 1\n# endif\n#else\n# ifndef WORDS_BIGENDIAN\n#  undef WORDS_BIGENDIAN\n# endif\n#endif\n\n/* Are we building with zipfs enabled? */\n#undef ZIPFS_BUILD\n\n/* Add the _FILE_OFFSET_BITS flag when building */\n#undef _FILE_OFFSET_BITS\n\n/* Add the _ISOC99_SOURCE flag when building */\n#undef _ISOC99_SOURCE\n\n/* Add the _LARGEFILE64_SOURCE flag when building */\n#undef _LARGEFILE64_SOURCE\n\n/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */\n#undef _OE_SOCKETS\n\n/* Do we really want to follow the standard? Yes we do! */\n#undef _POSIX_PTHREAD_SEMANTICS\n\n/* Do we want the reentrant OS API? */\n#undef _REENTRANT\n\n/* _TIME_BITS=64 enables 64-bit time_t. */\n#undef _TIME_BITS\n\n/* Do we want to use the XOPEN network library? */\n#undef _XOPEN_SOURCE\n\n/* Do we want to use the XOPEN network library? */\n#undef _XOPEN_SOURCE_EXTENDED\n\n/* Define to 1 if type 'char' is unsigned and your compiler does not\n   predefine this macro.  */\n#ifndef __CHAR_UNSIGNED__\n# undef __CHAR_UNSIGNED__\n#endif\n\n/* Define to '__inline__' or '__inline' if that's what the C compiler\n   calls it, or to nothing if 'inline' is not supported under any name.  */\n#ifndef __cplusplus\n#undef inline\n#endif\n\n/* Define to 'int' if <sys/types.h> does not define. */\n#undef mode_t\n\n/* Define as a signed integer type capable of holding a process identifier. */\n#undef pid_t\n\n/* Define as 'unsigned int' if <stddef.h> doesn't define. */\n#undef size_t\n\n\n    /* Undef unused package specific autoheader defines so that we can\n     * include both tclConfig.h and tkConfig.h at the same time: */\n    /* override */ #undef PACKAGE_NAME\n    /* override */ #undef PACKAGE_TARNAME\n    /* override */ #undef PACKAGE_VERSION\n    /* override */ #undef PACKAGE_STRING\n    #endif /* _TKCONFIG */\n"
  },
  {
    "path": "unix/tkConfig.sh.in",
    "content": "# tkConfig.sh --\n#\n# This shell script (for sh) is generated automatically by Tk's\n# configure script.  It will create shell variables for most of\n# the configuration options discovered by the configure script.\n# This script is intended to be included by the configure scripts\n# for Tk extensions so that they don't have to figure this all\n# out for themselves.  This file does not duplicate information\n# already provided by tclConfig.sh, so you may need to use that\n# file in addition to this one.\n#\n# The information in this file is specific to a single platform.\n\n# Tk's version number.\nTK_VERSION='@TK_VERSION@'\nTK_MAJOR_VERSION='@TK_MAJOR_VERSION@'\nTK_MINOR_VERSION='@TK_MINOR_VERSION@'\nTK_PATCH_LEVEL='@TK_PATCH_LEVEL@'\n\n# -D flags for use with the C compiler.\nTK_DEFS='@DEFS@'\n\n# Flag, 1: we built a shared lib, 0 we didn't\nTK_SHARED_BUILD=@TK_SHARED_BUILD@\n\n# TK_DBGX used to be used to distinguish debug vs. non-debug builds.\n# This was a righteous pain so the core doesn't do that any more.\nTK_DBGX=\n\n# The name of the Tk library (may be either a .a file or a shared library):\nTK_LIB_FILE='@TK_LIB_FILE@'\n\n# Additional libraries to use when linking Tk.\nTK_LIBS='@XLIBSW@ @XFT_LIBS@ @LIBS@ @TCL_LIBS@'\n\n# Top-level directory in which Tk's platform-independent files are\n# installed.\nTK_PREFIX='@prefix@'\n\n# Top-level directory in which Tk's platform-specific files (e.g.\n# executables) are installed.\nTK_EXEC_PREFIX='@exec_prefix@'\n\n# -I switch(es) to use to make all of the X11 include files accessible:\nTK_XINCLUDES='@XINCLUDES@'\n\n# Linker switch(es) to use to link with the X11 library archive.\nTK_XLIBSW='@XLIBSW@'\n\n# -l flag to pass to the linker to pick up the Tk library\nTK_LIB_FLAG='@TK_LIB_FLAG@'\n\n# String to pass to linker to pick up the Tk library from its\n# build directory.\nTK_BUILD_LIB_SPEC='@TK_BUILD_LIB_SPEC@'\n\n# String to pass to linker to pick up the Tk library from its\n# installed directory.\nTK_LIB_SPEC='@TK_LIB_SPEC@'\n\n# String to pass to the compiler so that an extension can\n# find installed Tk headers.\nTK_INCLUDE_SPEC='@TK_INCLUDE_SPEC@'\n\n# Location of the top-level source directory from which Tk was built.\n# This is the directory that contains a README file as well as\n# subdirectories such as generic, unix, etc.  If Tk was compiled in a\n# different place than the directory containing the source files, this\n# points to the location of the sources, not the location where Tk was\n# compiled.\nTK_SRC_DIR='@TK_SRC_DIR@'\n\n# Needed if you want to make a 'fat' shared library library\n# containing tk objects or link a different wish.\nTK_CC_SEARCH_FLAGS='@CC_SEARCH_FLAGS@'\nTK_LD_SEARCH_FLAGS='@LD_SEARCH_FLAGS@'\n\n# The name of the Tk stub library (.a):\nTK_STUB_LIB_FILE='@TK_STUB_LIB_FILE@'\n\n# -l flag to pass to the linker to pick up the Tk stub library\nTK_STUB_LIB_FLAG='@TK_STUB_LIB_FLAG@'\n\n# String to pass to linker to pick up the Tk stub library from its\n# build directory.\nTK_BUILD_STUB_LIB_SPEC='@TK_BUILD_STUB_LIB_SPEC@'\n\n# String to pass to linker to pick up the Tk stub library from its\n# installed directory.\nTK_STUB_LIB_SPEC='@TK_STUB_LIB_SPEC@'\n\n# Path to the Tk stub library in the build directory.\nTK_BUILD_STUB_LIB_PATH='@TK_BUILD_STUB_LIB_PATH@'\n\n# Path to the Tk stub library in the install directory.\nTK_STUB_LIB_PATH='@TK_STUB_LIB_PATH@'\n\n# Top-level directory in which Tk's demo files are installed.\nTK_DEMO_DIR='@TK_DEMO_DIR@'\n\n# Font system used by Tk (core, xft, or bidi)\nTK_FONTSYSTEM='@FONTSYSTEM@'\n"
  },
  {
    "path": "unix/tkUnix.c",
    "content": "/*\n * tkUnix.c --\n *\n *\tThis file contains procedures that are UNIX/X-specific, and will\n *\tprobably have to be written differently for Windows or Macintosh\n *\tplatforms.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#ifdef HAVE_XSS\n#   include <X11/extensions/scrnsaver.h>\n#   ifdef __APPLE__\n/* Support for weak-linked libXss. */\n#\tdefine HaveXSSLibrary()\t(&XScreenSaverQueryInfo != NULL)\n#   else\n/* Other platforms always link libXss. */\n#\tdefine HaveXSSLibrary()\t(1)\n#   endif\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetServerInfo --\n *\n *\tGiven a window, this procedure returns information about the window\n *\tserver for that window. This procedure provides the guts of the \"winfo\n *\tserver\" command.\n *\n * Results:\n *\tSets the interpreter result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetServerInfo(\n    Tcl_Interp *interp,\t\t/* The server information is returned in this\n\t\t\t\t * interpreter's result. */\n    Tk_Window tkwin)\t\t/* Token for window; this selects a particular\n\t\t\t\t * display and server. */\n{\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"X%dR%d %s %d\",\n\t    ProtocolVersion(Tk_Display(tkwin)),\n\t    ProtocolRevision(Tk_Display(tkwin)),\n\t    ServerVendor(Tk_Display(tkwin)),\n\t    VendorRelease(Tk_Display(tkwin))));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetDefaultScreenName --\n *\n *\tReturns the name of the screen that Tk should use during\n *\tinitialization.\n *\n * Results:\n *\tReturns the argument or a string that should not be freed by the\n *\tcaller.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkGetDefaultScreenName(\n    Tcl_Interp *interp,\t\t/* Interp used to find environment\n\t\t\t\t * variables. */\n    const char *screenName)\t/* Screen name from command line, or NULL. */\n{\n    if ((screenName == NULL) || (screenName[0] == '\\0')) {\n\tscreenName = Tcl_GetVar2(interp, \"env\", \"DISPLAY\", TCL_GLOBAL_ONLY);\n    }\n    return screenName;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UpdatePointer --\n *\n *\tUnused function in UNIX\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UpdatePointer(\n    Tk_Window tkwin,\t\t/* Window to which pointer event is reported.\n\t\t\t\t * May be NULL. */\n    int x, int y,\t\t/* Pointer location in root coords. */\n    int state)\t\t\t/* Modifier state mask. */\n{\n  (void)tkwin;\n  (void)x;\n  (void)y;\n  (void)state;\n\n  /*\n   * This function intentionally left blank\n   */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCopyRegion --\n *\n *\tMakes the destination region a copy of the source region.\n *\tCurrently unused on X11.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nextern int XUnionRegion(Region srca, Region srcb, Region dr_return);\n\nvoid\nTkpCopyRegion(\n    Region dst,\n    Region src)\n{\n    /* XUnionRegion() in Xlib is optimized to detect copying */\n    XUnionRegion(src, src, dst);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpBuildRegionFromAlphaData --\n *\n *\tSet up a rectangle of the given region based on the supplied alpha\n *\tdata.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe region is updated, with extra pixels added to it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpBuildRegionFromAlphaData(\n    Region region,\t\t/* Region to be updated. */\n    unsigned x, unsigned y,\t/* Where in region to update. */\n    unsigned width, unsigned height,\n\t\t\t\t/* Size of rectangle to update. */\n    unsigned char *dataPtr,\t/* Data to read from. */\n    unsigned pixelStride,\t/* Num bytes from one piece of alpha data to\n\t\t\t\t * the next in the line. */\n    unsigned lineStride)\t/* Num bytes from one line of alpha data to\n\t\t\t\t * the next line. */\n{\n    unsigned char *lineDataPtr;\n    unsigned int x1, y1, end;\n    XRectangle rect;\n\n    for (y1 = 0; y1 < height; y1++) {\n\tlineDataPtr = dataPtr;\n\tfor (x1 = 0; x1 < width; x1 = end) {\n\t    /*\n\t     * Search for first non-transparent pixel.\n\t     */\n\n\t    while ((x1 < width) && !*lineDataPtr) {\n\t\tx1++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    end = x1;\n\n\t    /*\n\t     * Search for first transparent pixel.\n\t     */\n\n\t    while ((end < width) && *lineDataPtr) {\n\t\tend++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    if (end > x1) {\n\t\trect.x = (short)(x + x1);\n\t\trect.y = (short)(y + y1);\n\t\trect.width = (unsigned short)(end - x1);\n\t\trect.height = 1;\n\t\tXUnionRectWithRegion(&rect, region, region);\n\t    }\n\t}\n\tdataPtr += lineStride;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetUserInactiveTime --\n *\n *\tReturn the number of milliseconds the user was inactive.\n *\n * Results:\n *\tThe number of milliseconds since the user's latest interaction with\n *\tthe system on the given display, or -1 if the XScreenSaver extension\n *\tis not supported by the client libraries or the X server\n *\timplementation.\n *\n * Side effects:\n *\tNone.\n *----------------------------------------------------------------------\n */\n\nlong\nTk_GetUserInactiveTime(\n #ifdef HAVE_XSS\n   Display *dpy)\t\t/* The display for which to query the inactive\n\t\t\t\t * time. */\n#else\n  TCL_UNUSED(Display *))\n#endif /* HAVE_XSS */\n{\n    long inactiveTime = -1;\n#ifdef HAVE_XSS\n    int eventBase, errorBase, major, minor;\n\n    /*\n     * Calling XScreenSaverQueryVersion seems to be needed to prevent a crash\n     * on some buggy versions of XFree86.\n     */\n\n    if (HaveXSSLibrary()\n\t    && XScreenSaverQueryExtension(dpy, &eventBase, &errorBase)\n\t    && XScreenSaverQueryVersion(dpy, &major, &minor)) {\n\tXScreenSaverInfo *info = XScreenSaverAllocInfo();\n\n\tif (info == NULL) {\n\t    /*\n\t     * We are out of memory.\n\t     */\n\n\t    Tcl_Panic(\"Out of memory: XScreenSaverAllocInfo failed in Tk_GetUserInactiveTime\");\n\t}\n\tif (XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info)) {\n\t    inactiveTime = (long)info->idle;\n\t}\n\tXFree(info);\n    }\n#endif /* HAVE_XSS */\n    return inactiveTime;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ResetUserInactiveTime --\n *\n *\tReset the user inactivity timer\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tThe user inactivity timer of the underlaying windowing system is reset\n *\tto zero.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ResetUserInactiveTime(\n    Display *dpy)\n{\n    XResetScreenSaver(dpy);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnix3d.c",
    "content": "/*\n * tkUnix3d.c --\n *\n *\tThis file contains the platform specific routines for drawing 3d\n *\tborders in the Motif style.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tk3d.h\"\n\n#if defined(MAC_OSX_TK)\n#include \"tkMacOSXInt.h\"\n#else\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * This structure is used to keep track of the extra colors used by Unix 3D\n * borders.\n */\n\ntypedef struct {\n    TkBorder info;\n    GC solidGC;\t\t/* Used to draw solid relief. */\n} UnixBorder;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetBorder --\n *\n *\tThis function allocates a new TkBorder structure.\n *\n * Results:\n *\tReturns a newly allocated TkBorder.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkBorder *\nTkpGetBorder(void)\n{\n    UnixBorder *borderPtr = (UnixBorder *)Tcl_Alloc(sizeof(UnixBorder));\n\n    borderPtr->solidGC = NULL;\n    return (TkBorder *) borderPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeBorder --\n *\n *\tThis function frees any colors allocated by the platform specific part\n *\tof this module.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay deallocate some colors.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeBorder(\n    TkBorder *borderPtr)\n{\n    UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;\n    Display *display = DisplayOfScreen(borderPtr->screen);\n\n    if (unixBorderPtr->solidGC != NULL) {\n\tTk_FreeGC(display, unixBorderPtr->solidGC);\n    }\n}\n/*\n *--------------------------------------------------------------\n *\n * Tk_3DVerticalBevel --\n *\n *\tThis procedure draws a vertical bevel along one side of an object. The\n *\tbevel is always rectangular in shape:\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\tAn appropriate shadow color is chosen for the bevel based on the\n *\tleftBevel and relief arguments. Normally this procedure is called\n *\tfirst, then Tk_3DHorizontalBevel is called next to draw neat corners.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGraphics are drawn in drawable.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_3DVerticalBevel(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Area of vertical bevel. */\n    int leftBevel,\t\t/* Non-zero means this bevel forms the left\n\t\t\t\t * side of the object; 0 means it forms the\n\t\t\t\t * right side. */\n    int relief)\t\t\t/* Kind of bevel to draw. For example,\n\t\t\t\t * TK_RELIEF_RAISED means interior of object\n\t\t\t\t * should appear higher than exterior. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    GC left, right;\n    Display *display = Tk_Display(tkwin);\n\n    if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n\n    if (relief == TK_RELIEF_RAISED) {\n\tXFillRectangle(display, drawable,\n\t\t(leftBevel) ? borderPtr->lightGC : borderPtr->darkGC,\n\t\tx, y, (unsigned) width, (unsigned) height);\n    } else if (relief == TK_RELIEF_SUNKEN) {\n\tXFillRectangle(display, drawable,\n\t\t(leftBevel) ? borderPtr->darkGC : borderPtr->lightGC,\n\t\tx, y, (unsigned) width, (unsigned) height);\n    } else if (relief == TK_RELIEF_RIDGE) {\n\tint half;\n\n\tleft = borderPtr->lightGC;\n\tright = borderPtr->darkGC;\n    ridgeGroove:\n\thalf = width/2;\n\tif (!leftBevel && (width & 1)) {\n\t    half++;\n\t}\n\tXFillRectangle(display, drawable, left, x, y, (unsigned) half,\n\t\t(unsigned) height);\n\tXFillRectangle(display, drawable, right, x+half, y,\n\t\t(unsigned) (width-half), (unsigned) height);\n    } else if (relief == TK_RELIEF_GROOVE) {\n\tleft = borderPtr->darkGC;\n\tright = borderPtr->lightGC;\n\tgoto ridgeGroove;\n    } else if (relief == TK_RELIEF_FLAT) {\n\tXFillRectangle(display, drawable, borderPtr->bgGC, x, y,\n\t\t(unsigned) width, (unsigned) height);\n    } else if (relief == TK_RELIEF_SOLID) {\n\tUnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;\n\tif (unixBorderPtr->solidGC == NULL) {\n\t    XGCValues gcValues;\n\n\t    gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);\n\t    unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\t}\n\tXFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y,\n\t\t(unsigned) width, (unsigned) height);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_3DHorizontalBevel --\n *\n *\tThis procedure draws a horizontal bevel along one side of an object.\n *\tThe bevel has mitered corners (depending on leftIn and rightIn\n *\targuments).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_3DHorizontalBevel(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Bounding box of area of bevel. Height gives\n\t\t\t\t * width of border. */\n    int leftIn, int rightIn,\t/* Describes whether the left and right edges\n\t\t\t\t * of the bevel angle in or out as they go\n\t\t\t\t * down. For example, if \"leftIn\" is true, the\n\t\t\t\t * left side of the bevel looks like this:\n\t\t\t\t *\t___________\n\t\t\t\t *\t __________\n\t\t\t\t *\t  _________\n\t\t\t\t *\t   ________\n\t\t\t\t */\n    int topBevel,\t\t/* Non-zero means this bevel forms the top\n\t\t\t\t * side of the object; 0 means it forms the\n\t\t\t\t * bottom side. */\n    int relief)\t\t\t/* Kind of bevel to draw. For example,\n\t\t\t\t * TK_RELIEF_RAISED means interior of object\n\t\t\t\t * should appear higher than exterior. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    Display *display = Tk_Display(tkwin);\n    int bottom, halfway, x1, x2, x1Delta, x2Delta;\n    UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;\n    GC topGC = NULL, bottomGC = NULL;\n\t\t\t\t/* Initializations needed only to prevent\n\t\t\t\t * compiler warnings. */\n\n    if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT) &&\n\t    (relief != TK_RELIEF_SOLID)) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n\n    /*\n     * Compute a GC for the top half of the bevel and a GC for the bottom half\n     * (they're the same in many cases).\n     */\n\n    switch (relief) {\n    case TK_RELIEF_FLAT:\n\ttopGC = bottomGC = borderPtr->bgGC;\n\tbreak;\n    case TK_RELIEF_GROOVE:\n\ttopGC = borderPtr->darkGC;\n\tbottomGC = borderPtr->lightGC;\n\tbreak;\n    case TK_RELIEF_RAISED:\n\ttopGC = bottomGC = (topBevel? borderPtr->lightGC : borderPtr->darkGC);\n\tbreak;\n    case TK_RELIEF_RIDGE:\n\ttopGC = borderPtr->lightGC;\n\tbottomGC = borderPtr->darkGC;\n\tbreak;\n    case TK_RELIEF_SOLID:\n\tif (unixBorderPtr->solidGC == NULL) {\n\t    XGCValues gcValues;\n\n\t    gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);\n\t    unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\t}\n\tXFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y,\n\t\t(unsigned) width, (unsigned) height);\n\treturn;\n    case TK_RELIEF_SUNKEN:\n\ttopGC = bottomGC = (topBevel? borderPtr->darkGC : borderPtr->lightGC);\n\tbreak;\n    }\n\n    /*\n     * Compute various other geometry-related stuff.\n     */\n\n    x1 = x;\n    if (!leftIn) {\n\tx1 += height;\n    }\n    x2 = x+width;\n    if (!rightIn) {\n\tx2 -= height;\n    }\n    x1Delta = (leftIn) ? 1 : -1;\n    x2Delta = (rightIn) ? -1 : 1;\n    halfway = y + height/2;\n    if (!topBevel && (height & 1)) {\n\thalfway++;\n    }\n    bottom = y + height;\n\n    /*\n     * Draw one line for each y-coordinate covered by the bevel.\n     */\n\n    for ( ; y < bottom; y++) {\n\t/*\n\t * X Dimensions are 16-bit, so avoid wraparound or display errors by\n\t * limiting these here.\n\t */\n\n\tif (x1 < -32767) {\n\t    x1 = -32767;\n\t}\n\tif (x2 > 32767) {\n\t    x2 = 32767;\n\t}\n\n\t/*\n\t * In some weird cases (such as large border widths for skinny\n\t * rectangles) x1 can be >= x2. Don't draw the lines in these cases.\n\t */\n\n\tif (x1 < x2) {\n\t    XFillRectangle(display, drawable,\n\t\t    (y < halfway) ? topGC : bottomGC, x1, y,\n\t\t    (unsigned) (x2-x1), (unsigned) 1);\n\t}\n\tx1 += x1Delta;\n\tx2 += x2Delta;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetShadows --\n *\n *\tThis procedure computes the shadow colors for a 3-D border and fills\n *\tin the corresponding fields of the Border structure. It's called\n *\tlazily, so that the colors aren't allocated until something is\n *\tactually drawn with them. That way, if a border is only used for flat\n *\tbackgrounds the shadow colors will never be allocated.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe lightGC and darkGC fields in borderPtr get filled in, if they\n *\tweren't already.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetShadows(\n    TkBorder *borderPtr,\t/* Information about border. */\n    Tk_Window tkwin)\t\t/* Window where border will be used for\n\t\t\t\t * drawing. */\n{\n    XColor lightColor, darkColor;\n    int stressed, tmp1, tmp2;\n    int r, g, b;\n    XGCValues gcValues;\n\n    if (borderPtr->lightGC != NULL) {\n\treturn;\n    }\n    stressed = TkpCmapStressed(tkwin, borderPtr->colormap);\n\n    /*\n     * First, handle the case of a color display with lots of colors. The\n     * shadow colors get computed using whichever formula results in the\n     * greatest change in color:\n     * 1. Lighter shadow is half-way to white, darker shadow is half way to\n     *    dark.\n     * 2. Lighter shadow is 40% brighter than background, darker shadow is 40%\n     *    darker than background.\n     */\n\n    if (!stressed && (Tk_Depth(tkwin) >= 6)) {\n\t/*\n\t * This is a color display with lots of colors. For the dark shadow,\n\t * cut 40% from each of the background color components. But if the\n\t * background is already very dark, make the dark color a little\n\t * lighter than the background by increasing each color component\n\t * 1/4th of the way to MAX_INTENSITY.\n\t *\n\t * For the light shadow, boost each component by 40% or half-way to\n\t * white, whichever is greater (the first approach works better for\n\t * unsaturated colors, the second for saturated ones). But if the\n\t * background is already very bright, instead choose a slightly darker\n\t * color for the light shadow by reducing each color component by 10%.\n\t *\n\t * Compute the colors using integers, not using lightColor.red etc.:\n\t * these are shorts and may have problems with integer overflow.\n\t */\n\n\t/*\n\t * Compute the dark shadow color.\n\t */\n\n\tr = (int) borderPtr->bgColorPtr->red;\n\tg = (int) borderPtr->bgColorPtr->green;\n\tb = (int) borderPtr->bgColorPtr->blue;\n\n\tif (r*0.5*r + g*1.0*g + b*0.28*b < MAX_INTENSITY*0.05*MAX_INTENSITY) {\n\t    darkColor.red = (MAX_INTENSITY + 3*r)/4;\n\t    darkColor.green = (MAX_INTENSITY + 3*g)/4;\n\t    darkColor.blue = (MAX_INTENSITY + 3*b)/4;\n\t} else {\n\t    darkColor.red = (60 * r)/100;\n\t    darkColor.green = (60 * g)/100;\n\t    darkColor.blue = (60 * b)/100;\n\t}\n\n\t/*\n\t * Allocate the dark shadow color and its GC.\n\t */\n\n\tborderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor);\n\tgcValues.foreground = borderPtr->darkColorPtr->pixel;\n\tborderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\n\t/*\n\t * Compute the light shadow color.\n\t */\n\n\tif (g > MAX_INTENSITY*0.95) {\n\t    lightColor.red = (90 * r)/100;\n\t    lightColor.green = (90 * g)/100;\n\t    lightColor.blue = (90 * b)/100;\n\t} else {\n\t    tmp1 = (14 * r)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + r)/2;\n\t    lightColor.red = (tmp1 > tmp2) ? tmp1 : tmp2;\n\t    tmp1 = (14 * g)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + g)/2;\n\t    lightColor.green = (tmp1 > tmp2) ? tmp1 : tmp2;\n\t    tmp1 = (14 * b)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + b)/2;\n\t    lightColor.blue = (tmp1 > tmp2) ? tmp1 : tmp2;\n\t}\n\n\t/*\n\t * Allocate the light shadow color and its GC.\n\t */\n\n\tborderPtr->lightColorPtr = Tk_GetColorByValue(tkwin, &lightColor);\n\tgcValues.foreground = borderPtr->lightColorPtr->pixel;\n\tborderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\treturn;\n    }\n\n    if (borderPtr->shadow == None) {\n\tborderPtr->shadow = Tk_GetBitmap(NULL, tkwin,\n\t\t\"gray50\");\n\tif (borderPtr->shadow == None) {\n\t    Tcl_Panic(\"TkpGetShadows couldn't allocate bitmap for border\");\n\t}\n    }\n    if (borderPtr->visual->map_entries > 2) {\n\t/*\n\t * This isn't a monochrome display, but the colormap either ran out of\n\t * entries or didn't have very many to begin with. Generate the light\n\t * shadows with a white stipple and the dark shadows with a black\n\t * stipple.\n\t */\n\n\tgcValues.foreground = borderPtr->bgColorPtr->pixel;\n\tgcValues.background = BlackPixelOfScreen(borderPtr->screen);\n\tgcValues.stipple = borderPtr->shadow;\n\tgcValues.fill_style = FillOpaqueStippled;\n\tborderPtr->darkGC = Tk_GetGC(tkwin,\n\t\tGCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n\tgcValues.background = WhitePixelOfScreen(borderPtr->screen);\n\tborderPtr->lightGC = Tk_GetGC(tkwin,\n\t\tGCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n\treturn;\n    }\n\n    /*\n     * This is just a measly monochrome display, hardly even worth its\n     * existence on this earth. Make one shadow a 50% stipple and the other\n     * the opposite of the background.\n     */\n\n    gcValues.foreground = WhitePixelOfScreen(borderPtr->screen);\n    gcValues.background = BlackPixelOfScreen(borderPtr->screen);\n    gcValues.stipple = borderPtr->shadow;\n    gcValues.fill_style = FillOpaqueStippled;\n    borderPtr->lightGC = Tk_GetGC(tkwin,\n\t    GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n    if (borderPtr->bgColorPtr->pixel\n\t    == WhitePixelOfScreen(borderPtr->screen)) {\n\tgcValues.foreground = BlackPixelOfScreen(borderPtr->screen);\n\tborderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    } else {\n\tborderPtr->darkGC = borderPtr->lightGC;\n\tborderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixAccessibility.c",
    "content": "/*\n * tkUnixAccessibility.c --\n *\n * This file implements accessibility/screen-reader support\n * on Unix-like systems based on the Gnome Accessibility Toolkit.\n * the standard accessibility library for X11 systems.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n * Copyright © 2006, Marcus von Appen\n * Copyright © 2019-2025 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n\n#include <stdlib.h>\n#include \"tkInt.h\"\n\n#ifdef HAVE_ATK\n#include <atk/atk.h>\n#include <atk-bridge.h>\n\n/* Structs for custom ATK objects bound to Tk. */\ntypedef struct _TkAtkAccessible {\n    AtkObject parent;\n    Tk_Window tkwin;\n    Tcl_Interp *interp;\n    gint x, y, width, height;\n    char *path;\n    bool is_focused;\n    int virtual_count;\n} TkAtkAccessible;\n\ntypedef struct _TkAtkAccessibleClass {\n    AtkObjectClass parent_class;\n} TkAtkAccessibleClass;\n\n/* Structs to map Tk roles into ATK roles. */\n\nstatic const struct AtkRoleMap {\n    const char *tkrole;\n    AtkRole atkrole;\n} roleMap[] = {\n    {\"Button\", ATK_ROLE_PUSH_BUTTON},\n    {\"Checkbox\", ATK_ROLE_CHECK_BOX},\n    {\"Combobox\", ATK_ROLE_COMBO_BOX},\n    {\"Entry\", ATK_ROLE_ENTRY},\n    {\"Label\", ATK_ROLE_LABEL},\n    {\"Listbox\", ATK_ROLE_LIST_BOX},\n    {\"Menu\", ATK_ROLE_MENU},\n    {\"Menubar\", ATK_ROLE_MENU_BAR},\n    {\"Tree\", ATK_ROLE_TREE},\n    {\"Notebook\", ATK_ROLE_PAGE_TAB},\n    {\"Progressbar\", ATK_ROLE_PROGRESS_BAR},\n    {\"Radiobutton\",ATK_ROLE_RADIO_BUTTON},\n    {\"Scale\", ATK_ROLE_SLIDER},\n    {\"Spinbox\", ATK_ROLE_SPIN_BUTTON},\n    {\"Table\", ATK_ROLE_TREE_TABLE},\n    {\"Text\", ATK_ROLE_TEXT},\n    {\"Toplevel\", ATK_ROLE_WINDOW},\n    {\"Frame\", ATK_ROLE_PANEL},\n    {\"Canvas\", ATK_ROLE_CANVAS},\n    {\"Scrollbar\", ATK_ROLE_SCROLL_BAR},\n    {\"Toggleswitch\", ATK_ROLE_TOGGLE_BUTTON},\n    {NULL, ATK_ROLE_INVALID }\n};\n\n\n#define ATK_CONTEXT g_main_context_default()\n\n/* Variables for managing ATK objects. */\nstatic AtkObject *tk_root_accessible = NULL;\nstatic GList *toplevel_accessible_objects = NULL;\nstatic GHashTable *tk_to_atk_map = NULL;\nextern Tcl_HashTable *TkAccessibilityObject;\nstatic GMainContext *acc_context = NULL;\n\n/* GLib-Tcl event loop integration. */\nstatic void Atk_Event_Setup (void *clientData, int flags);\nstatic void Atk_Event_Check(void *clientData, int flags);\nstatic int Atk_Event_Run(Tcl_Event *event, int flags);\nstatic void ignore_atk_critical(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data);\n\n/* ATK component interface. */\nstatic void tk_get_extents(AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type);\nstatic gboolean tk_contains(AtkComponent *component, gint x, gint y, AtkCoordType coord_type);\nstatic gboolean tk_grab_focus(AtkComponent *component);\nstatic void tk_atk_component_interface_init(AtkComponentIface *iface);\n\n/* ATK child, attribute and state management. */\nstatic gint tk_get_n_children(AtkObject *obj);\nstatic AtkObject *tk_ref_child(AtkObject *obj, gint i);\nstatic AtkRole GetAtkRoleForWidget(Tk_Window win);\nstatic AtkRole tk_get_role(AtkObject *obj);\nstatic gchar *GetAtkNameForWidget(Tk_Window win);\nstatic const gchar *tk_get_name(AtkObject *obj);\nstatic void tk_set_name(AtkObject *obj, const gchar *name);\nstatic gchar *GetAtkDescriptionForWidget(Tk_Window win);\nstatic const gchar *tk_get_description(AtkObject *obj);\nstatic AtkStateSet *tk_ref_state_set(AtkObject *obj);\n\n/* ATK value interface. */\nstatic gchar *GetAtkValueForWidget(Tk_Window win);\nstatic void tk_get_value_and_text(AtkValue *obj, gdouble *value, gchar **text);\nstatic AtkRange *tk_get_range(AtkValue *obj);\nstatic void tk_get_current_value(AtkValue *obj, GValue *value);\nstatic void tk_get_minimum_value(AtkValue *obj, GValue *value);\nstatic void tk_get_maximum_value(AtkValue *obj, GValue *value);\nstatic void tk_atk_value_interface_init(AtkValueIface *iface);\n\n/* ATK action interface. */\nstatic gboolean tk_action_do_action(AtkAction *action, gint i);\nstatic gint tk_action_get_n_actions(AtkAction *action);\nstatic const gchar *tk_action_get_name(AtkAction *action, gint i);\nstatic void tk_atk_action_interface_init(AtkActionIface *iface);\n\n/* ATK text interface. */\nstatic gchar *tk_text_get_text(AtkText *text, gint start_offset, gint end_offset);\nstatic gint tk_text_get_caret_offset(AtkText *text);\nstatic gint tk_text_get_character_count(AtkText *text);\nstatic void tk_atk_text_interface_init(AtkTextIface *iface);\n\n/* ATK selection interface. */\nstatic gboolean tk_selection_add_selection(AtkSelection *selection, gint i);\nstatic gboolean tk_selection_remove_selection(AtkSelection *selection, gint i);\nstatic gboolean tk_selection_clear_selection(AtkSelection *selection);\nstatic gint tk_selection_get_selection_count(AtkSelection *selection);\nstatic gboolean tk_selection_is_child_selected(AtkSelection *selection, gint i);\nstatic AtkObject *tk_selection_ref_selection(AtkSelection *selection, gint i);\nstatic gboolean tk_selection_select_all_selection(AtkSelection *selection);\nstatic void tk_atk_selection_interface_init(AtkSelectionIface *iface);\n\n/* Object lifecycle functions. */\nstatic void tk_atk_accessible_class_init(TkAtkAccessibleClass *klass);\nstatic void tk_atk_accessible_init(TkAtkAccessible *accessible);\nstatic void tk_atk_accessible_finalize(GObject *gobject);\n\n/* Registration and mapping functions. */\nstatic void RegisterToplevelWindow(Tcl_Interp *interp, Tk_Window tkwin, AtkObject *accessible);\nstatic void UnregisterToplevelWindow(AtkObject *accessible);\nstatic void RegisterWidgetRecursive(Tcl_Interp *interp, Tk_Window tkwin);\nstatic void EnsureWidgetInAtkHierarchy(Tcl_Interp *interp, Tk_Window tkwin);\nstatic void UpdateAtkFocusChain(Tk_Window focused);\nTk_Window GetToplevelOfWidget(Tk_Window tkwin);\nAtkObject *TkCreateAccessibleAtkObject(Tcl_Interp *interp, Tk_Window tkwin, const char *path);\nvoid InitAtkTkMapping(void);\nvoid RegisterAtkObjectForTkWindow(Tk_Window tkwin, AtkObject *atkobj);\nAtkObject *GetAtkObjectForTkWindow(Tk_Window tkwin);\nvoid UnregisterAtkObjectForTkWindow(Tk_Window tkwin);\nstatic AtkObject *tk_util_get_root(void);\nAtkObject *atk_get_root(void);\n\n/* Event handlers. */\nvoid TkAtkAccessible_RegisterEventHandlers(Tk_Window tkwin, void *tkAccessible);\nstatic void TkAtkAccessible_DestroyHandler(void *clientData, XEvent *eventPtr);\nstatic void TkAtkAccessible_FocusHandler(void *clientData, XEvent *eventPtr);\nstatic void TkAtkAccessible_CreateHandler(void *clientData, XEvent *eventPtr);\nstatic void TkAtkAccessible_ConfigureHandler(void *clientData, XEvent *eventPtr);\n\n/* Tcl command implementations. */\nstatic int EmitSelectionChanged(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int EmitFocusChanged(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic int IsScreenReaderRunning(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\nstatic bool IsScreenReaderActive(void);\nint TkAtkAccessibleObjCmd(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]);\nint TkAtkAccessibility_Init(Tcl_Interp *interp);\n\n/* Signal IDs for custom AT-SPI signals. */\nstatic guint window_create_signal_id;\nstatic guint window_activate_signal_id;\nstatic guint window_deactivate_signal_id;\n\n/* Define custom ATK object bridged to Tcl/Tk. */\n#define TK_ATK_TYPE_ACCESSIBLE (tk_atk_accessible_get_type())\n#define TK_ATK_IS_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TK_ATK_TYPE_ACCESSIBLE))\nG_DEFINE_TYPE_WITH_CODE(TkAtkAccessible, tk_atk_accessible, ATK_TYPE_OBJECT,\n\t\t\tG_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT, tk_atk_component_interface_init)\n\t\t\tG_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION, tk_atk_action_interface_init)\n\t\t\tG_IMPLEMENT_INTERFACE(ATK_TYPE_VALUE, tk_atk_value_interface_init)\n\t\t\tG_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT, tk_atk_text_interface_init)\n\t\t\tG_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, tk_atk_selection_interface_init)\n\t\t\t)\n/*\n *----------------------------------------------------------------------\n *\n * GLib integration functions. These create a Tcl event source so that\n * the GLib event loop can be smoothly integrated with Tcl/Tk.\n *\n *----------------------------------------------------------------------\n */\n\n/* Configure event loop. */\nstatic void Atk_Event_Setup(\n    TCL_UNUSED(void *), /* clientData */\n    int flags)\n{\n    static Tcl_Time block_time = {0, 10000};\n\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn;\n    }\n\n    if (g_main_context_pending(acc_context)) {\n\tblock_time.usec = 0;\n    }\n    Tcl_SetMaxBlockTime(&block_time);\n}\n\n/* Check event queue. */\nstatic void Atk_Event_Check(\n    TCL_UNUSED(void *), /* clientData */\n    int flags)\n{\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn;\n    }\n\n    if (g_main_context_pending(acc_context)) {\n\tTcl_Event *event = (Tcl_Event *)Tcl_Alloc(sizeof(Tcl_Event));\n\tevent->proc = Atk_Event_Run;\n\tTcl_QueueEvent(event, TCL_QUEUE_TAIL);\n    }\n}\n\n/* Run the event. */\nstatic int Atk_Event_Run(\n    TCL_UNUSED(Tcl_Event *), /* event */\n    int flags)\n{\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn 0;\n    }\n\n    while (g_main_context_pending(acc_context)) {\n\tg_main_context_iteration(acc_context, FALSE);\n    }\n\n    return 1;\n}\n\n/* Disable GLib warnings that can pollute the console - dummy function.  */\nstatic void ignore_atk_critical(\n    TCL_UNUSED(const gchar *), /* log_domain */\n    TCL_UNUSED(GLogLevelFlags), /* log_level */\n    TCL_UNUSED(const gchar *), /* message */\n    TCL_UNUSED(gpointer)) /* user_data */\n{\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * ATK interface functions. These do the heavy lifting of mapping Tk to ATK\n * functionality. ATK has a more rigid structure than NSAccessibility and\n * Microsoft Active Accessibility and requires a great deal more specific\n * implementation for accessibility to work properly.\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * ATK component interface. This tracks widget location/geometry.\n */\n\nstatic void tk_get_extents(AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)component;\n\n    if (!acc || !acc->tkwin) {\n\t*x = *y = *width = *height = 0;\n\treturn;\n    }\n\n    int wx, wy;\n    Tk_GetRootCoords(acc->tkwin, &wx, &wy);\n    int w = Tk_Width(acc->tkwin);\n    int h = Tk_Height(acc->tkwin);\n\n    if (coord_type == ATK_XY_SCREEN) {\n\t/* Absolute screen coords. */\n\t*x = wx;\n\t*y = wy;\n    } else {\n\t/* Relative to toplevel window. */\n\tTk_Window top = GetToplevelOfWidget(acc->tkwin);\n\tint tx, ty;\n\tTk_GetRootCoords(top, &tx, &ty);\n\t*x = wx - tx;\n\t*y = wy - ty;\n    }\n\n    *width = w;\n    *height = h;\n}\n\nstatic gboolean tk_contains(AtkComponent *component, gint x, gint y, AtkCoordType coord_type)\n{\n    gint comp_x, comp_y, comp_width, comp_height;\n    if (!component) return FALSE;\n    tk_get_extents(component, &comp_x, &comp_y, &comp_width, &comp_height, coord_type);\n\n    return (x >= comp_x && x < comp_x + comp_width &&\n\t    y >= comp_y && y < comp_y + comp_height);\n}\n\n/* Force accessible focus on a Tk widget. */\nstatic gboolean tk_grab_focus(AtkComponent *component)\n{\n   TkAtkAccessible *acc = (TkAtkAccessible *)component;\n   if (!acc || !acc->tkwin || !acc->interp) return FALSE;\n\n   /* Actually give Tk focus to the widget. */\n   char cmd[256];\n   snprintf(cmd, sizeof(cmd), \"focus -force %s\", Tk_PathName(acc->tkwin));\n   Tcl_Eval(acc->interp, cmd);\n\n   /* Update internal state. */\n   acc->is_focused = true;\n   AtkObject *obj = ATK_OBJECT(acc);\n\n   /* Force ATK notifications for focus change. */\n   atk_object_notify_state_change(obj, ATK_STATE_FOCUSED, TRUE);\n   g_signal_emit_by_name(obj, \"focus-event\", TRUE);\n\n   /* Help Orca with container navigation. */\n   AtkObject *parent = atk_object_get_parent(obj);\n   if (parent) {\n       /* Notify parent about active descendant */\n       g_signal_emit_by_name(parent, \"active-descendant-changed\", obj);\n\n       /* Also emit children-changed to ensure ATK hierarchy is refreshed. */\n       g_signal_emit_by_name(parent, \"children-changed::add\",\n\t\t\t     atk_object_get_n_accessible_children(parent) - 1,\n\t\t\t     obj);\n   }\n\n   return TRUE;\n}\n\nstatic void tk_atk_component_interface_init(AtkComponentIface *iface)\n{\n    iface->get_extents = tk_get_extents;\n    iface->contains    = tk_contains;\n    iface->grab_focus  = tk_grab_focus;\n}\n\n/*\n * Accessible children, attributes and state. Here we create create accessible\n * objects from native Tk widgets (buttons, entries, etc.), map them them to\n * the appropriate role, and track them.\n */\n\nstatic gint tk_get_n_children(AtkObject *obj)\n{\n    if (obj == tk_root_accessible) {\n\treturn g_list_length(toplevel_accessible_objects);\n    }\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc || !acc->tkwin || !acc->interp) return 0;\n\n    /* Count only real/native children. */\n    int native_count = 0;\n    for (TkWindow *childPtr = ((TkWindow*)acc->tkwin)->childList;\n\t    childPtr != NULL; childPtr = childPtr->nextPtr) {\n\tnative_count++;\n    }\n\n    return native_count;\n}\n\nstatic AtkObject *tk_ref_child(AtkObject *obj, gint i)\n{\n    if (obj == tk_root_accessible) {\n\tif (i < 0 || i >= (gint)g_list_length(toplevel_accessible_objects)) return NULL;\n\tGList *child = g_list_nth(toplevel_accessible_objects, i);\n\tif (child) {\n\t    g_object_ref(child->data);\n\t    return ATK_OBJECT(child->data);\n\t}\n\treturn NULL;\n    }\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc || !acc->tkwin || !acc->interp || i < 0) return NULL;\n\n    /* Only handle real/native children. */\n    TkWindow *childPtr;\n    gint index = 0;\n    for (childPtr = ((TkWindow*)acc->tkwin)->childList;\n\t childPtr != NULL;\n\t childPtr = childPtr->nextPtr, index++) {\n\n\tif (index == i) {\n\t    Tk_Window child_tkwin = (Tk_Window)childPtr;\n\t    AtkObject *child_obj = GetAtkObjectForTkWindow(child_tkwin);\n\n\t    /* Always create accessible object if it doesn't exist. */\n\t    if (!child_obj) {\n\t\tchild_obj = TkCreateAccessibleAtkObject(acc->interp, child_tkwin,\n\t\t\t\t\t\t       Tk_PathName(child_tkwin));\n\t\tif (child_obj) {\n\t\t    atk_object_set_parent(child_obj, obj);\n\t\t    RegisterAtkObjectForTkWindow(child_tkwin, child_obj);\n\t\t    TkAtkAccessible_RegisterEventHandlers(child_tkwin,\n\t\t\t\t\t\t\t  (TkAtkAccessible *)child_obj);\n\n\t\t    /* Notify ATK about the new child. */\n\t\t    gint childCount = atk_object_get_n_accessible_children(obj);\n\t\t    g_signal_emit_by_name(obj, \"children-changed::add\", childCount - 1, child_obj);\n\t\t}\n\t    }\n\n\t    if (child_obj) {\n\t\tg_object_ref(child_obj);\n\t\treturn child_obj;\n\t    }\n\t    break;\n\t}\n    }\n\n    return NULL;\n}\n\nstatic AtkRole GetAtkRoleForWidget(Tk_Window win)\n{\n    if (!win) return ATK_ROLE_UNKNOWN;\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (hPtr) {\n\tTcl_HashTable *attrs = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\tif (attrs) {\n\t    Tcl_HashEntry *roleEntry = Tcl_FindHashEntry(attrs, \"role\");\n\t    if (roleEntry) {\n\t\tconst char *result = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(roleEntry));\n\t\tif (result) {\n\t\t    for (int i = 0; roleMap[i].tkrole != NULL; i++) {\n\t\t\tif (strcmp(roleMap[i].tkrole, result) == 0) {\n\t\t\t    return roleMap[i].atkrole;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n    /* Fallback to widget class. */\n    const char *widgetClass = Tk_Class(win);\n    if (widgetClass) {\n\tfor (int i = 0; roleMap[i].tkrole != NULL; i++) {\n\t    if (strcasecmp(roleMap[i].tkrole, widgetClass) == 0) {\n\t\treturn roleMap[i].atkrole;\n\t    }\n\t}\n    }\n\n    if (Tk_IsTopLevel(win)) {\n\treturn ATK_ROLE_WINDOW;\n    }\n\n    return ATK_ROLE_UNKNOWN;\n}\n\nstatic AtkRole tk_get_role(AtkObject *obj)\n{\n    if (obj == tk_root_accessible) {\n\treturn ATK_ROLE_APPLICATION;\n    }\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc) return ATK_ROLE_UNKNOWN;\n\n    if (!acc->tkwin) {\n\t/* Virtual child: return the role already stored in obj->role. */\n\treturn obj->role;\n    }\n\n    return GetAtkRoleForWidget(acc->tkwin);\n}\n\nstatic gchar *GetAtkNameForWidget(Tk_Window win)\n{\n    if (!win) return NULL;\n\n    AtkRole role = GetAtkRoleForWidget(win);\n    /* If label, return the value instead of the name so Orca does not say \"label\" twice. */\n    if (role == ATK_ROLE_LABEL) {\n\treturn GetAtkValueForWidget(win);\n    }\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (!hPtr) return NULL;\n\n    Tcl_HashTable *attrs = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    if (!attrs) return NULL;\n\n    Tcl_HashEntry *nameEntry = Tcl_FindHashEntry(attrs, \"name\");\n    if (!nameEntry) return NULL;\n\n    const char *name = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(nameEntry));\n    return name ? g_utf8_make_valid(name, -1) : NULL;\n}\n\nstatic const gchar *tk_get_name(AtkObject *obj)\n{\n    if (obj == tk_root_accessible) {\n\treturn \"Tk Application\";\n    }\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc) return NULL;\n\n    return GetAtkNameForWidget(acc->tkwin);\n}\n\nstatic void tk_set_name(AtkObject *obj, const gchar *name)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n\n    if (!acc) return;\n    atk_object_set_name(obj, name);\n}\n\nstatic gchar *GetAtkDescriptionForWidget(Tk_Window win)\n{\n    if (!win) return NULL;\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (!hPtr) return NULL;\n\n    Tcl_HashTable *attrs = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    if (!attrs) return NULL;\n\n    Tcl_HashEntry *descriptionEntry = Tcl_FindHashEntry(attrs, \"description\");\n    if (!descriptionEntry) return NULL;\n\n    const char *description = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(descriptionEntry));\n    return description ? g_utf8_make_valid(description, -1) : NULL;\n}\n\nstatic const gchar *tk_get_description(AtkObject *obj)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    return GetAtkDescriptionForWidget(acc->tkwin);\n}\n\nstatic AtkStateSet *tk_ref_state_set(AtkObject *obj)\n{\n    AtkStateSet *state_set = atk_state_set_new();\n    TkAtkAccessible *acc = (TkAtkAccessible *) obj;\n\n    if (!acc) {\n\treturn state_set;\n    }\n\n    /* Always add these basic states. */\n    atk_state_set_add_state(state_set, ATK_STATE_ENABLED);\n    atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);\n\n    /* Only add FOCUSABLE if widget can receive focus. */\n    if (acc->tkwin) {\n\tAtkRole role = GetAtkRoleForWidget(acc->tkwin);\n\n\t/* Use if-else to avoid switch warning and handle all roles. */\n\tif (role == ATK_ROLE_PUSH_BUTTON ||\n\t    role == ATK_ROLE_CHECK_BOX ||\n\t    role == ATK_ROLE_RADIO_BUTTON ||\n\t    role == ATK_ROLE_ENTRY ||\n\t    role == ATK_ROLE_TEXT ||\n\t    role == ATK_ROLE_COMBO_BOX ||\n\t    role == ATK_ROLE_SPIN_BUTTON ||\n\t    role == ATK_ROLE_SLIDER ||\n\t    role == ATK_ROLE_TOGGLE_BUTTON ||\n\t    role == ATK_ROLE_LIST_BOX ||\n\t    role == ATK_ROLE_TREE ||\n\t    role == ATK_ROLE_LIST_ITEM ||\n\t    role == ATK_ROLE_TREE_ITEM) {\n\t    atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);\n\t}\n\n\t/* Entry widgets should be EDITABLE, not read-only. */\n\tif (role == ATK_ROLE_ENTRY || role == ATK_ROLE_TEXT) {\n\t    /* Check if widget has -state normal or is not disabled */\n\t    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)acc->tkwin);\n\t    int is_editable = 1; /* Default to editable. */\n\n\t    if (hPtr) {\n\t\tTcl_HashTable *attrs = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\t\tif (attrs) {\n\t\t    Tcl_HashEntry *stateEntry = Tcl_FindHashEntry(attrs, \"state\");\n\t\t    if (stateEntry) {\n\t\t\tconst char *state = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(stateEntry));\n\t\t\tif (state && (strcmp(state, \"disabled\") == 0 || strcmp(state, \"readonly\") == 0)) {\n\t\t\t    is_editable = 0;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\n\t    /* Add EDITABLE state for normal entry widgets. */\n\t    if (is_editable) {\n\t\tatk_state_set_add_state(state_set, ATK_STATE_EDITABLE);\n\t    }\n\n\t    /* Add SINGLE_LINE for entry widgets (not multiline text). */\n\t    if (role == ATK_ROLE_ENTRY) {\n\t\tatk_state_set_add_state(state_set, ATK_STATE_SINGLE_LINE);\n\t    } else if (role == ATK_ROLE_TEXT) {\n\t\tatk_state_set_add_state(state_set, ATK_STATE_MULTI_LINE);\n\t    }\n\t}\n    }\n\n    /* Add FOCUSED if widget has focus. */\n    if (acc->is_focused) {\n\tatk_state_set_add_state(state_set, ATK_STATE_FOCUSED);\n    }\n\n    /* Always add VISIBLE/SHOWING if widget is mapped. */\n    if (acc->tkwin && Tk_IsMapped(acc->tkwin)) {\n\tatk_state_set_add_state(state_set, ATK_STATE_VISIBLE);\n\tatk_state_set_add_state(state_set, ATK_STATE_SHOWING);\n    }\n\n    /* Toggle state for checkboxes/radiobuttons. */\n    if (acc->tkwin) {\n\tAtkRole role = GetAtkRoleForWidget(acc->tkwin);\n\tif (role == ATK_ROLE_CHECK_BOX ||\n\t    role == ATK_ROLE_RADIO_BUTTON ||\n\t    role == ATK_ROLE_TOGGLE_BUTTON) {\n\n\t    const char *value = GetAtkValueForWidget(acc->tkwin);\n\t    /* Check for proper state values. */\n\t    if (value) {\n\t\t/* For checkboxes/radiobuttons, check if value equals \"selected\" or \"1\" or onvalue. */\n\t\tif (strcmp(value, \"selected\") == 0 ||\n\t\t    strcmp(value, \"1\") == 0 ||\n\t\t    (value[0] != '0' && value[0] != '\\0')) {\n\t\t    atk_state_set_add_state(state_set, ATK_STATE_CHECKED);\n\t\t}\n\t    }\n\t}\n    }\n    return state_set;\n}\n\n\n/*\n * ATK value interface.\n */\n\nstatic gchar *GetAtkValueForWidget(Tk_Window win)\n{\n    if (!win) return NULL;\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (!hPtr) return NULL;\n\n    Tcl_HashTable *attrs = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    if (!attrs) return NULL;\n\n    Tcl_HashEntry *valueEntry = Tcl_FindHashEntry(attrs, \"value\");\n\n    if (!valueEntry) return NULL;\n\n    const char *value = Tcl_GetString((Tcl_Obj *)Tcl_GetHashValue(valueEntry));\n    return value ? g_utf8_make_valid(value, -1) : NULL;\n}\n\n/* Modern AtkValue methods (replace deprecated stubs). */\nstatic void tk_get_value_and_text(AtkValue *obj, gdouble *value, gchar **text)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc || !acc->tkwin || !acc->interp) {\n\tif (value) *value = 0.0;\n\tif (text) *text = g_strdup(\"0.0\");\n\treturn;\n    }\n\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n    if (role != ATK_ROLE_SPIN_BUTTON) {\n\tif (value) *value = 0.0;\n\tif (text) *text = g_strdup(\"0\");\n\treturn;\n    }\n\n    gchar *val = GetAtkValueForWidget(acc->tkwin);\n    double cur_val = val ? atof(val) : 0.0;\n\n    if (value) *value = cur_val;\n    if (text) *text = g_strdup(val ? val : \"0\");\n}\n\n\nstatic AtkRange *tk_get_range(AtkValue *obj)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)obj;\n    if (!acc || !acc->tkwin || !acc->interp) {\n\treturn NULL;\n    }\n\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n    double min_val = 0.0, max_val = 0.0;\n    char cmd[256];\n\n    if (role == ATK_ROLE_SPIN_BUTTON || role == ATK_ROLE_SLIDER) {\n\t/* Spinbox/Scale: -from .. -to. */\n\tsnprintf(cmd, sizeof(cmd), \"%s cget -from\", Tk_PathName(acc->tkwin));\n\tif (Tcl_Eval(acc->interp, cmd) == TCL_OK) {\n\t    Tcl_GetDoubleFromObj(acc->interp, Tcl_GetObjResult(acc->interp), &min_val);\n\t}\n\n\tsnprintf(cmd, sizeof(cmd), \"%s cget -to\", Tk_PathName(acc->tkwin));\n\tif (Tcl_Eval(acc->interp, cmd) == TCL_OK) {\n\t    Tcl_GetDoubleFromObj(acc->interp, Tcl_GetObjResult(acc->interp), &max_val);\n\t}\n    }\n    else if (role == ATK_ROLE_PROGRESS_BAR || role == ATK_ROLE_SCROLL_BAR) {\n\t/* Progressbar/Scrollbar: 0 .. -maximum (default 100.) */\n\tmin_val = 0.0;\n\tmax_val = 100.0;\n\n\tsnprintf(cmd, sizeof(cmd), \"%s cget -maximum\", Tk_PathName(acc->tkwin));\n\tif (Tcl_Eval(acc->interp, cmd) == TCL_OK) {\n\t    Tcl_GetDoubleFromObj(acc->interp, Tcl_GetObjResult(acc->interp), &max_val);\n\t}\n    }\n    else {\n\treturn NULL; /* Not applicable. */\n    }\n\n    return atk_range_new(min_val, max_val, NULL);\n}\n\n/* Deprecated methods - updated to call modern ones (for compatibility). */\nstatic void tk_get_current_value(AtkValue *obj, GValue *value)\n{\n    gdouble val = 0.0;\n    gchar *text = NULL;\n    tk_get_value_and_text(obj, &val, &text);\n    g_value_init(value, G_TYPE_DOUBLE);\n    g_value_set_double(value, val);\n    g_free(text);\n}\n\nstatic void tk_get_minimum_value(AtkValue *obj, GValue *value)\n{\n    AtkRange *range = tk_get_range(obj);\n    gdouble min_val = range ? atk_range_get_lower_limit(range) : 0.0;\n    if (range) g_object_unref(range);\n    g_value_init(value, G_TYPE_DOUBLE);\n    g_value_set_double(value, min_val);\n}\n\nstatic void tk_get_maximum_value(AtkValue *obj, GValue *value)\n{\n    AtkRange *range = tk_get_range(obj);\n    gdouble max_val = range ? atk_range_get_upper_limit(range) : 0.0;\n    if (range) g_object_unref(range);\n    g_value_init(value, G_TYPE_DOUBLE);\n    g_value_set_double(value, max_val);\n}\n\nstatic void tk_atk_value_interface_init(AtkValueIface *iface)\n{\n    iface->get_value_and_text = tk_get_value_and_text;\n    iface->get_range = tk_get_range;\n    iface->get_current_value = tk_get_current_value;  /* Deprecated fallback. */\n    iface->get_minimum_value = tk_get_minimum_value;  /* Deprecated fallback. */\n    iface->get_maximum_value = tk_get_maximum_value;  /* Deprecated fallback. */\n}\n\n/*\n * ATK action interface.\n */\n\nstatic gboolean tk_action_do_action(AtkAction *action, gint i)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *) action;\n    Tcl_Interp *interp;\n    Tcl_Obj *cmd[2];\n    int result;\n\n    if (!acc || !acc->tkwin || i != 0) {\n\treturn FALSE;\n    }\n\n    interp = acc->interp;\n    if (!interp) {\n\treturn FALSE;\n    }\n\n    /*\n     * Call: <widgetPath> invoke\n     * This is the ONLY supported way to activate a Tk button from C.\n     */\n    cmd[0] = Tcl_NewStringObj(Tk_PathName(acc->tkwin), -1);\n    cmd[1] = Tcl_NewStringObj(\"invoke\", -1);\n\n    Tcl_IncrRefCount(cmd[0]);\n    Tcl_IncrRefCount(cmd[1]);\n\n    result = Tcl_EvalObjv(interp, 2, cmd, TCL_EVAL_GLOBAL);\n\n    Tcl_DecrRefCount(cmd[0]);\n    Tcl_DecrRefCount(cmd[1]);\n\n    if (result != TCL_OK) {\n\tTcl_ResetResult(interp);\n\treturn FALSE;\n    }\n\n    /*\n     * Toggle state notification.\n     */\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n    if (role == ATK_ROLE_CHECK_BOX ||\n\trole == ATK_ROLE_RADIO_BUTTON) {\n\n\tconst char *value = GetAtkValueForWidget(acc->tkwin);\n\tbool checked = (value && value[0] != '0');\n\n\tatk_object_notify_state_change(\n\t    ATK_OBJECT(acc),\n\t    ATK_STATE_CHECKED,\n\t    checked\n\t);\n    }\n\n    return TRUE;\n}\n\n\nstatic gint tk_action_get_n_actions(AtkAction *action)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *) action;\n    if (!acc || !acc->tkwin) {\n\treturn 0;\n    }\n\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n\n    switch (role) {\n    case ATK_ROLE_PUSH_BUTTON:\n    case ATK_ROLE_CHECK_BOX:\n    case ATK_ROLE_RADIO_BUTTON:\n    case ATK_ROLE_TOGGLE_BUTTON:\n\treturn 1;\n    default:\n\treturn 0;\n    }\n}\n\nstatic const gchar *tk_action_get_name(AtkAction *action, gint i)\n{\n    if (i != 0) {\n\treturn NULL;\n    }\n\n    TkAtkAccessible *acc = (TkAtkAccessible *) action;\n    if (!acc || !acc->tkwin) {\n\treturn NULL;\n    }\n\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n\n    switch (role) {\n    case ATK_ROLE_PUSH_BUTTON:\n\treturn \"press\";\n    case ATK_ROLE_CHECK_BOX:\n    case ATK_ROLE_RADIO_BUTTON:\n    case ATK_ROLE_TOGGLE_BUTTON:\n\treturn \"toggle\";\n    default:\n\treturn NULL;\n    }\n}\n\nstatic void tk_atk_action_interface_init(AtkActionIface *iface)\n{\n    iface->do_action = tk_action_do_action;\n    iface->get_n_actions = tk_action_get_n_actions;\n    iface->get_name = tk_action_get_name;\n}\n\n/*\n * ATK text interface. These are stub functions to ensure that Orca recognizes\n * text widgets. All accessibility in text data is managed at the script level.\n */\n\nstatic gchar *tk_text_get_text(\n    TCL_UNUSED(AtkText *),\n    TCL_UNUSED(gint),\n    TCL_UNUSED(gint))\n{\n    return NULL;\n}\n\nstatic gint tk_text_get_caret_offset(\n    TCL_UNUSED(AtkText *))\n{\n    return -1;\n}\n\nstatic gint tk_text_get_character_count(\n    TCL_UNUSED(AtkText *))\n{\n    return 0;\n}\n\n\nstatic void tk_atk_text_interface_init(AtkTextIface *iface)\n{\n    iface->get_text = tk_text_get_text;\n    iface->get_caret_offset = tk_text_get_caret_offset;\n    iface->get_character_count = tk_text_get_character_count;\n    iface->get_selection = NULL;\n    iface->get_text_at_offset = NULL;\n    iface->get_text_after_offset = NULL;\n    iface->get_text_before_offset = NULL;\n    iface->get_run_attributes = NULL;\n    iface->get_default_attributes = NULL;\n    iface->get_character_extents = NULL;\n    iface->get_offset_at_point = NULL;\n    iface->set_caret_offset = NULL;\n    iface->set_selection = NULL;\n    iface->get_n_selections = NULL;\n    iface->get_range_extents = NULL;\n    iface->get_bounded_ranges = NULL;\n}\n\n/*\n * ATK select interface. Stubs only since we handle selection at\n * script level for virtual widgets.\n */\n\nstatic gboolean tk_selection_add_selection(\n    TCL_UNUSED(AtkSelection *),\n    TCL_UNUSED(gint))\n{\n    return FALSE;\n}\n\nstatic gboolean tk_selection_remove_selection(\n    TCL_UNUSED(AtkSelection *),\n    TCL_UNUSED(gint))\n{\n    return FALSE;\n}\n\nstatic gboolean tk_selection_clear_selection(\n    TCL_UNUSED(AtkSelection *))\n{\n    return FALSE;\n}\n\nstatic gint tk_selection_get_selection_count(\n    TCL_UNUSED(AtkSelection *))\n{\n    return 0;\n}\n\nstatic gboolean tk_selection_is_child_selected(\n    TCL_UNUSED(AtkSelection *),\n    TCL_UNUSED(gint))\n{\n    return FALSE;\n}\n\nstatic AtkObject *tk_selection_ref_selection(\n    TCL_UNUSED(AtkSelection *),\n    TCL_UNUSED(gint))\n{\n    return NULL;\n}\n\nstatic gboolean tk_selection_select_all_selection(\n    TCL_UNUSED(AtkSelection *))\n{\n    return FALSE;\n}\n\nstatic void tk_atk_selection_interface_init(AtkSelectionIface *iface)\n{\n    /* Keep minimal interface for compatibility. */\n    iface->add_selection = tk_selection_add_selection;\n    iface->clear_selection = tk_selection_clear_selection;\n    iface->get_selection_count = tk_selection_get_selection_count;\n    iface->is_child_selected = tk_selection_is_child_selected;\n    iface->ref_selection = tk_selection_ref_selection;\n    iface->remove_selection = tk_selection_remove_selection;\n    iface->select_all_selection = tk_selection_select_all_selection;\n}\n\n\n/*\n * Functions to initialize and manage the parent ATK class and object instances.\n */\n\nstatic void tk_atk_accessible_init(TkAtkAccessible *self)\n{\n    self->tkwin = NULL;\n    self->interp = NULL;\n    self->path = NULL;\n}\n\nstatic void tk_atk_accessible_finalize(GObject *gobject)\n{\n    TkAtkAccessible *self = (TkAtkAccessible*)gobject;\n    if (!self) return;\n\n    if (self->tkwin) {\n\t/* Clean up from tracking structures. */\n\tUnregisterAtkObjectForTkWindow(self->tkwin);\n\tif (Tk_IsTopLevel(self->tkwin)) {\n\t    UnregisterToplevelWindow(ATK_OBJECT(self));\n\t}\n\tself->tkwin = NULL;\n    }\n\n    g_free(self->path);\n    /* Chain up to parent finalizer. */\n    G_OBJECT_CLASS(tk_atk_accessible_parent_class)->finalize(gobject);\n}\n\nstatic void tk_atk_accessible_class_init(TkAtkAccessibleClass *klass)\n{\n    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);\n    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);\n\n    /* Register custom AT-SPI signals. */\n    window_create_signal_id = g_signal_new(\"window-create\",\n\t\t\t\t\t   TK_ATK_TYPE_ACCESSIBLE,\n\t\t\t\t\t   G_SIGNAL_RUN_LAST,\n\t\t\t\t\t   0,\n\t\t\t\t\t   NULL, NULL,\n\t\t\t\t\t   g_cclosure_marshal_VOID__VOID,\n\t\t\t\t\t   G_TYPE_NONE, 0);\n\n    window_activate_signal_id = g_signal_new(\"window-activate\",\n\t\t\t\t\t     TK_ATK_TYPE_ACCESSIBLE,\n\t\t\t\t\t     G_SIGNAL_RUN_LAST,\n\t\t\t\t\t     0,\n\t\t\t\t\t     NULL, NULL,\n\t\t\t\t\t     g_cclosure_marshal_VOID__VOID,\n\t\t\t\t\t     G_TYPE_NONE, 0);\n\n    window_deactivate_signal_id = g_signal_new(\"window-deactivate\",\n\t\t\t\t\t       TK_ATK_TYPE_ACCESSIBLE,\n\t\t\t\t\t       G_SIGNAL_RUN_LAST,\n\t\t\t\t\t       0,\n\t\t\t\t\t       NULL, NULL,\n\t\t\t\t\t       g_cclosure_marshal_VOID__VOID,\n\t\t\t\t\t       G_TYPE_NONE, 0);\n\n    gobject_class->finalize = tk_atk_accessible_finalize;\n\n    /* Map ATK class functions to Tk functions.  */\n    atk_class->get_name = tk_get_name;\n    atk_class->get_description = tk_get_description;\n    atk_class->get_role = tk_get_role;\n    atk_class->ref_state_set = tk_ref_state_set;\n    atk_class->get_n_children = tk_get_n_children;\n    atk_class->ref_child = tk_ref_child;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Registration and mapping functions. These functions set, track and update\n * the association between Tk windows and ATK objects.\n *\n *----------------------------------------------------------------------\n */\n\n/* Function to complete toplevel registration with proper hierarchy. */\nstatic void RegisterToplevelWindow(Tcl_Interp *interp, Tk_Window tkwin, AtkObject *accessible)\n{\n    if (!accessible || !tkwin || !G_IS_OBJECT(accessible)) {\n\tg_warning(\"RegisterToplevelWindow: Invalid tkwin or accessible\");\n\treturn;\n    }\n\n    if (!tk_root_accessible) {\n\ttk_root_accessible = tk_util_get_root();\n\tif (tk_root_accessible) {\n\t    tk_set_name(tk_root_accessible, \"Tk Application\");\n\t}\n    }\n\n    AtkObject *existing = GetAtkObjectForTkWindow(tkwin);\n    if (existing && existing != accessible) {\n\tg_warning(\"RegisterToplevelWindow: Toplevel %s already registered with different AtkObject\",\n\t\t  Tk_PathName(tkwin));\n\treturn;\n    }\n\n    g_object_ref(accessible);\n\n    AtkObject *parentAcc = NULL;\n\n    if (Tk_IsTopLevel(tkwin)) {\n\tparentAcc = tk_root_accessible;\n\n\tif (!g_list_find(toplevel_accessible_objects, accessible)) {\n\t    toplevel_accessible_objects = g_list_append(toplevel_accessible_objects, accessible);\n\t    gint index = g_list_index(toplevel_accessible_objects, accessible);\n\t    if (index >= 0 && tk_root_accessible) {\n\t\tg_signal_emit_by_name(tk_root_accessible, \"children-changed::add\", index, accessible);\n\t    }\n\t}\n    } else {\n\tTk_Window parentWin = Tk_Parent(tkwin);\n\tif (parentWin) {\n\t    AtkObject *parentObj = GetAtkObjectForTkWindow(parentWin);\n\t    if (!parentObj) {\n\t\tparentObj = TkCreateAccessibleAtkObject(interp, parentWin, Tk_PathName(parentWin));\n\t\tif (parentObj) {\n\t\t    RegisterAtkObjectForTkWindow(parentWin, parentObj);\n\t\t    if (Tk_IsTopLevel(parentWin)) {\n\t\t\tRegisterToplevelWindow(interp, parentWin, parentObj);\n\t\t    }\n\t\t}\n\t    }\n\t    parentAcc = parentObj;\n\t}\n\n\tif (!parentAcc) {\n\t    parentAcc = tk_root_accessible;\n\t}\n\n\tatk_object_set_parent(accessible, parentAcc);\n\tRegisterAtkObjectForTkWindow(tkwin, accessible);\n\n\t/* Always emit children-changed::add for non-toplevel children. */\n\tgint child_count = atk_object_get_n_accessible_children(parentAcc);\n\tg_signal_emit_by_name(parentAcc, \"children-changed::add\", child_count, accessible);\n    }\n\n    const gchar *name = tk_get_name(accessible);\n    if (!name || !*name) {\n\ttk_set_name(accessible, Tk_PathName(tkwin));\n    }\n\n    AtkRole role = GetAtkRoleForWidget(tkwin);\n    atk_object_set_role(accessible, role);\n\n    TkAtkAccessible_RegisterEventHandlers(tkwin, (TkAtkAccessible *)accessible);\n\n    if (Tk_IsMapped(tkwin)) {\n\tatk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_VISIBLE, TRUE);\n\tatk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_SHOWING, TRUE);\n    }\n}\n\n/* Remove toplevel window from ATK object list. */\nstatic void UnregisterToplevelWindow(AtkObject *accessible)\n{\n    if (!accessible) return;\n\n    if (g_list_find(toplevel_accessible_objects, accessible)) {\n\t/* Find position before removal. */\n\tgint index = g_list_index(toplevel_accessible_objects, accessible);\n\n\t/* Remove from toplevel list. */\n\ttoplevel_accessible_objects = g_list_remove(toplevel_accessible_objects, accessible);\n\n\t/* Notify about removed child. */\n\tg_signal_emit_by_name(tk_root_accessible, \"children-changed::remove\", index, accessible);\n    }\n}\n\n/* Recursively register widget and all its children with proper events. */\nstatic void RegisterWidgetRecursive(Tcl_Interp *interp, Tk_Window tkwin)\n{\n    if (!tkwin) return;\n\n    AtkObject *acc = GetAtkObjectForTkWindow(tkwin);\n\n    /* Create accessible object if it doesn't exist. */\n    if (!acc) {\n\tacc = TkCreateAccessibleAtkObject(interp, tkwin, Tk_PathName(tkwin));\n\tif (!acc) return;\n\n\tAtkObject *parentAcc = NULL;\n\n\tif (Tk_IsTopLevel(tkwin)) {\n\t    /* Toplevel window - register with root. */\n\t    RegisterToplevelWindow(interp, tkwin, acc);\n\t} else {\n\t    /* Non-toplevel widget - ensure parent is registered first. */\n\t    Tk_Window parent = Tk_Parent(tkwin);\n\t    if (parent) {\n\t\tAtkObject *parentObj = GetAtkObjectForTkWindow(parent);\n\t\tif (!parentObj) {\n\t\t    /* Recursively register parent first. */\n\t\t    RegisterWidgetRecursive(interp, parent);\n\t\t    parentObj = GetAtkObjectForTkWindow(parent);\n\t\t}\n\t\tparentAcc = parentObj;\n\t    }\n\n\t    /* Fallback to root accessible if no parent found. */\n\t    if (!parentAcc) {\n\t\tparentAcc = tk_root_accessible;\n\t    }\n\n\t    /* Set parent-child relationship. */\n\t    atk_object_set_parent(acc, parentAcc);\n\t    RegisterAtkObjectForTkWindow(tkwin, acc);\n\n\t    /* Force children-changed signal to refresh ATK hierarchy. */\n\t    if (parentAcc) {\n\t\tgint child_index = atk_object_get_n_accessible_children(parentAcc);\n\t\tg_signal_emit_by_name(parentAcc, \"children-changed::add\", child_index, acc);\n\t    }\n\n\t    /* Register event handlers for this widget. */\n\t    TkAtkAccessible_RegisterEventHandlers(tkwin, (TkAtkAccessible *)acc);\n\t}\n\n\t/* Notify visibility if already mapped. */\n\tif (Tk_IsMapped(tkwin)) {\n\t    atk_object_notify_state_change(acc, ATK_STATE_VISIBLE, TRUE);\n\t    atk_object_notify_state_change(acc, ATK_STATE_SHOWING, TRUE);\n\n\t    /* Also ensure SHOWING state is set for parents. */\n\t    Tk_Window current = tkwin;\n\t    while (current && !Tk_IsTopLevel(current)) {\n\t\tTk_Window parent = Tk_Parent(current);\n\t\tif (parent) {\n\t\t    AtkObject *pAcc = GetAtkObjectForTkWindow(parent);\n\t\t    if (pAcc) {\n\t\t\tatk_object_notify_state_change(pAcc, ATK_STATE_SHOWING, TRUE);\n\t\t    }\n\t\t}\n\t\tcurrent = parent;\n\t    }\n\t}\n\n\t/* If this widget currently has focus, update focus state. */\n\tTkWindow *focusPtr = TkGetFocusWin((TkWindow*)tkwin);\n\tif (focusPtr == (TkWindow*)tkwin) {\n\t    TkAtkAccessible *tkAcc = (TkAtkAccessible *)acc;\n\t    tkAcc->is_focused = true;\n\t    atk_object_notify_state_change(acc, ATK_STATE_FOCUSED, TRUE);\n\t    g_signal_emit_by_name(acc, \"focus-event\", TRUE);\n\n\t    /* Notify parent about active descendant. */\n\t    if (!Tk_IsTopLevel(tkwin)) {\n\t\tTk_Window parent = Tk_Parent(tkwin);\n\t\tAtkObject *parentAc = GetAtkObjectForTkWindow(parent);\n\t\tif (parentAc) {\n\t\t    g_signal_emit_by_name(parentAc, \"active-descendant-changed\", acc);\n\t\t}\n\t    }\n\t}\n    }\n\n    /* Recursively register all children. */\n    TkWindow *child;\n    for (child = ((TkWindow*)tkwin)->childList;\n\t child != NULL;\n\t child = child->nextPtr) {\n\tRegisterWidgetRecursive(interp, (Tk_Window)child);\n    }\n\n    /* After registering all children, emit one more children-changed\n     * for this container to ensure ATK sees all children. */\n    if (acc) {\n\tg_signal_emit_by_name(acc, \"children-changed::add\",\n\t\t\t      atk_object_get_n_accessible_children(acc),\n\t\t\t      NULL);\n    }\n}\n\n /*  Function to ensure a widget and all its ancestors are in the ATK hierarchy. */\nstatic void EnsureWidgetInAtkHierarchy(Tcl_Interp *interp, Tk_Window tkwin)\n{\n    if (!tkwin) return;\n\n    /* First ensure all ancestors exist. */\n    Tk_Window current = tkwin;\n    GList *widgets_to_process = NULL;\n\n    /* Collect all widgets from leaf to root. */\n    while (current) {\n\twidgets_to_process = g_list_prepend(widgets_to_process, current);\n\tif (Tk_IsTopLevel(current)) break;\n\tcurrent = Tk_Parent(current);\n    }\n\n    /* Process from root to leaf to ensure proper parent-child relationships. */\n    GList *iter;\n    for (iter = widgets_to_process; iter != NULL; iter = iter->next) {\n\tTk_Window win = (Tk_Window)iter->data;\n\tAtkObject *acc = GetAtkObjectForTkWindow(win);\n\n\tif (!acc) {\n\t    acc = TkCreateAccessibleAtkObject(interp, win, Tk_PathName(win));\n\t    if (acc) {\n\t\t/* Set up parent relationship. */\n\t\tif (!Tk_IsTopLevel(win)) {\n\t\t    Tk_Window parent = Tk_Parent(win);\n\t\t    AtkObject *parentAcc = GetAtkObjectForTkWindow(parent);\n\t\t    if (parentAcc) {\n\t\t\tatk_object_set_parent(acc, parentAcc);\n\n\t\t\t/* Notify ATK about the new child. */\n\t\t\tgint childCount = atk_object_get_n_accessible_children(parentAcc);\n\t\t\tg_signal_emit_by_name(parentAcc, \"children-changed::add\", childCount - 1, acc);\n\t\t    }\n\t\t}\n\n\t\tRegisterAtkObjectForTkWindow(win, acc);\n\t\tTkAtkAccessible_RegisterEventHandlers(win, (TkAtkAccessible *)acc);\n\n\t\t/* Update state if widget is mapped. */\n\t\tif (Tk_IsMapped(win)) {\n\t\t    atk_object_notify_state_change(acc, ATK_STATE_VISIBLE, TRUE);\n\t\t    atk_object_notify_state_change(acc, ATK_STATE_SHOWING, TRUE);\n\t\t}\n\t    }\n\t}\n    }\n\n    g_list_free(widgets_to_process);\n}\n\n\n /*  Function to update the ATK focus chain when a widget receives focus. */\n static void UpdateAtkFocusChain(Tk_Window focused)\n{\n    if (!focused) return;\n\n    Tcl_Interp *interp = Tk_Interp(focused);\n    if (!interp) return;\n\n    /* Ensure widget is in ATK hierarchy. */\n    EnsureWidgetInAtkHierarchy(interp, focused);\n\n    AtkObject *focusedAcc = GetAtkObjectForTkWindow(focused);\n    if (!focusedAcc) return;\n\n    TkAtkAccessible *focusedTkAcc = (TkAtkAccessible *)focusedAcc;\n\n    /* Update focus state. */\n    focusedTkAcc->is_focused = true;\n    atk_object_notify_state_change(focusedAcc, ATK_STATE_FOCUSED, TRUE);\n    g_signal_emit_by_name(focusedAcc, \"focus-event\", TRUE);\n\n    /* Walk up the hierarchy and update parent focus states. */\n    Tk_Window current = focused;\n    while (current && !Tk_IsTopLevel(current)) {\n\tTk_Window parent = Tk_Parent(current);\n\tif (parent) {\n\t    AtkObject *parentAcc = GetAtkObjectForTkWindow(parent);\n\t    if (parentAcc) {\n\t\t/* Notify parent about active descendant. */\n\t\tAtkObject *childAcc = GetAtkObjectForTkWindow(current);\n\t\tif (childAcc) {\n\t\t    g_signal_emit_by_name(parentAcc, \"active-descendant-changed\", childAcc);\n\t\t}\n\n\t\t/* Also emit children-changed to refresh ATK's view. */\n\t\tg_signal_emit_by_name(parentAcc, \"children-changed::add\",\n\t\t\t\t      atk_object_get_n_accessible_children(parentAcc) - 1,\n\t\t\t\t      childAcc);\n\t    }\n\t}\n\tcurrent = parent;\n    }\n\n    /* If this is a toplevel, emit window activation. */\n    if (Tk_IsTopLevel(focused)) {\n\tg_signal_emit_by_name(focusedAcc, \"window-activate\");\n    }\n}\n\n/* Function to return the toplevel window that contains a given Tk widget. */\nTk_Window GetToplevelOfWidget(Tk_Window tkwin)\n{\n    if (!tkwin) return NULL;\n    Tk_Window current = tkwin;\n    if (Tk_IsTopLevel(current)) return current;\n    while (current != NULL && Tk_WindowId(current) != None) {\n\tTk_Window parent = Tk_Parent(current);\n\tif (parent == NULL || Tk_IsTopLevel(current)) break;\n\tcurrent = parent;\n    }\n    return Tk_IsTopLevel(current) ? current : NULL;\n}\n\n/*\n * Root window setup. These are the foundation of the\n * accessibility object system in ATK. atk_get_root() is the\n * critical link to at-spi - it is called by the ATK system\n * and at-spi bridge initialization will silently fail if this\n * function is not implemented. This API is confusing because\n * atk_get_root cannot be called directly in our functions, but\n * it still must be implemented if we are using a custom setup,\n * as we are here.\n */\n\nstatic AtkObject *tk_util_get_root(void)\n{\n    if (!tk_root_accessible) {\n\tTkAtkAccessible *acc = (TkAtkAccessible *)g_object_new(TK_ATK_TYPE_ACCESSIBLE, NULL);\n\ttk_root_accessible = ATK_OBJECT(acc);\n\tatk_object_initialize(tk_root_accessible, NULL);\n\t/* Set proper name and role.  */\n\tatk_object_set_role(tk_root_accessible, ATK_ROLE_APPLICATION);\n\ttk_set_name(tk_root_accessible, \"Tk Application\");\n    }\n\n    return tk_root_accessible;\n}\n\n/* Core function linking Tk objects to the ATK root object and at-spi. */\nAtkObject *atk_get_root(void) {\n    return tk_util_get_root();\n}\n\n/* ATK-Tk object creation with proper parent/child relationship. */\nAtkObject *TkCreateAccessibleAtkObject(Tcl_Interp *interp, Tk_Window tkwin, const char *path)\n{\n    if (!interp || !tkwin) return NULL;\n\n    AtkObject *existing = GetAtkObjectForTkWindow(tkwin);\n    if (existing) return existing;\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)g_object_new(TK_ATK_TYPE_ACCESSIBLE, NULL);\n    acc->interp = interp;\n    acc->tkwin = tkwin;\n    acc->path = g_utf8_make_valid(path, -1);\n\n    AtkObject *obj = ATK_OBJECT(acc);\n    AtkRole role = GetAtkRoleForWidget(tkwin);\n    atk_object_set_role(obj, role);\n\n    gchar *name = GetAtkNameForWidget(tkwin);\n    if (name) {\n\tatk_object_set_name(obj, name);\n\tg_free(name);\n    }\n\n    /* Check if widget has focus using TkGetFocusWin. */\n    if (role == ATK_ROLE_PUSH_BUTTON || role == ATK_ROLE_CHECK_BOX ||\n\trole == ATK_ROLE_RADIO_BUTTON || role == ATK_ROLE_TOGGLE_BUTTON ||\n\trole == ATK_ROLE_ENTRY || role == ATK_ROLE_TEXT ||\n\trole == ATK_ROLE_LIST_ITEM ||\n\trole == ATK_ROLE_TREE_ITEM || role == ATK_ROLE_COMBO_BOX ||\n\trole == ATK_ROLE_SPIN_BUTTON || role == ATK_ROLE_TOGGLE_BUTTON) {\n\tTkWindow *focusPtr = TkGetFocusWin((TkWindow*)tkwin);\n\tacc->is_focused = (focusPtr == (TkWindow*)tkwin);\n    }\n\n    RegisterAtkObjectForTkWindow(tkwin, obj);\n    TkAtkAccessible_RegisterEventHandlers(tkwin, acc);\n\n    return obj;\n}\n\n/*\n * Functions to map Tk window to its corresponding ATK object.\n */\n\nvoid InitAtkTkMapping(void)\n{\n    if (!tk_to_atk_map) {\n\ttk_to_atk_map = g_hash_table_new_full(g_direct_hash, g_direct_equal,\n\t\t\t\t\t      NULL, (GDestroyNotify)g_object_unref);\n    }\n}\n\nvoid RegisterAtkObjectForTkWindow(Tk_Window tkwin, AtkObject *atkobj)\n{\n    if (!tkwin || !atkobj) return;\n    InitAtkTkMapping();\n    g_object_ref(atkobj); /*Increment ref count because hash table takes ownership. */\n    g_hash_table_insert(tk_to_atk_map, tkwin, atkobj);\n}\n\nAtkObject *GetAtkObjectForTkWindow(Tk_Window tkwin)\n{\n    if (!tk_to_atk_map || !tkwin) return NULL;\n    return (AtkObject *)g_hash_table_lookup(tk_to_atk_map, tkwin);\n}\n\nvoid UnregisterAtkObjectForTkWindow(Tk_Window tkwin)\n{\n    if (!tk_to_atk_map || !tkwin) return;\n\n    AtkObject *atkobj = (AtkObject *)g_hash_table_lookup(tk_to_atk_map, tkwin);\n    if (atkobj) {\n\t/* If toplevel, unregister from toplevel list. */\n\tif (g_list_find(toplevel_accessible_objects, atkobj)) {\n\t    UnregisterToplevelWindow(atkobj);\n\t}\n\n\tg_hash_table_remove(tk_to_atk_map, tkwin);\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Event handlers - update Tk and ATK in response to various X events.\n *\n *----------------------------------------------------------------------\n */\n\n/* Configure event handlers. */\nvoid TkAtkAccessible_RegisterEventHandlers(Tk_Window tkwin, void *tkAccessible)\n{\n    if (!tkwin || !tkAccessible) return;\n\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t\t\t  TkAtkAccessible_DestroyHandler, tkAccessible);\n    Tk_CreateEventHandler(tkwin, FocusChangeMask,\n\t\t\t  TkAtkAccessible_FocusHandler, tkAccessible);\n    Tk_CreateEventHandler(tkwin, SubstructureNotifyMask,\n\t\t\t  TkAtkAccessible_CreateHandler, tkAccessible);\n    Tk_CreateEventHandler(tkwin, ConfigureNotify,\n\t\t\t  TkAtkAccessible_ConfigureHandler, tkAccessible);\n\n}\n\n/* Respond to <CreateNotify> events. */\nstatic void TkAtkAccessible_CreateHandler(void *clientData, XEvent *eventPtr)\n{\n    if (!eventPtr || eventPtr->type != CreateNotify) {\n\treturn;\n    }\n\n    Tk_Window parentWin = (Tk_Window)clientData;\n    if (!parentWin) return;\n\n    Tcl_Interp *interp = Tk_Interp(parentWin);\n    if (!interp) return;\n\n    Window childWindow = eventPtr->xcreatewindow.window;\n    Tk_Window childWin = Tk_IdToWindow(Tk_Display(parentWin), childWindow);\n    if (!childWin) return;\n\n    if (GetAtkObjectForTkWindow(childWin)) {\n\treturn; /* Already registered. */\n    }\n\n    AtkObject *childAcc = TkCreateAccessibleAtkObject(interp, childWin, Tk_PathName(childWin));\n    if (!childAcc) return;\n\n    AtkObject *parentAcc = GetAtkObjectForTkWindow(parentWin);\n    if (!parentAcc) {\n\tparentAcc = TkCreateAccessibleAtkObject(interp, parentWin, Tk_PathName(parentWin));\n\tif (parentAcc) {\n\t    RegisterAtkObjectForTkWindow(parentWin, parentAcc);\n\t    if (Tk_IsTopLevel(parentWin)) {\n\t\tRegisterToplevelWindow(interp, parentWin, parentAcc);\n\t    }\n\t}\n    }\n\n    if (!parentAcc) {\n\tparentAcc = tk_root_accessible;\n    }\n\n    atk_object_set_parent(childAcc, parentAcc);\n    RegisterAtkObjectForTkWindow(childWin, childAcc);\n    TkAtkAccessible_RegisterEventHandlers(childWin, (TkAtkAccessible *)childAcc);\n\n    /* Emit children-changed::add.*/\n    gint idx = atk_object_get_n_accessible_children(parentAcc);\n    g_signal_emit_by_name(parentAcc, \"children-changed::add\", idx, childAcc);\n\n    /* Notify visibility if mapped. */\n    if (Tk_IsMapped(childWin)) {\n\tatk_object_notify_state_change(childAcc, ATK_STATE_VISIBLE, TRUE);\n\tatk_object_notify_state_change(childAcc, ATK_STATE_SHOWING, TRUE);\n    }\n}\n\n\n\n/* Respond to <DestroyNotify> events. */\nstatic void TkAtkAccessible_DestroyHandler(void *clientData, XEvent *eventPtr)\n{\n    if (eventPtr->type != DestroyNotify) return;\n\n    TkAtkAccessible *acc = (TkAtkAccessible *)clientData;\n    if (!acc) return;\n\n    GObject *obj =  (GObject*)acc;\n\n    tk_atk_accessible_finalize(obj);\n}\n\n\n/* Respond to <Configure> events. */\nstatic void TkAtkAccessible_ConfigureHandler(void *clientData, XEvent *eventPtr)\n{\n    if (!eventPtr || eventPtr->type != ConfigureNotify) {\n\treturn;\n    }\n\n    Tk_Window tkwin = (Tk_Window)clientData;\n    if (!tkwin) {\n\treturn;\n    }\n\n    AtkObject *accObj = GetAtkObjectForTkWindow(tkwin);\n    if (!accObj) {\n\treturn;\n    }\n\n    /* Update geometry on configure. */\n    gint x, y, w, h;\n    tk_get_extents(ATK_COMPONENT(accObj), &x, &y, &w, &h, ATK_XY_SCREEN);\n\n    /* If the widget just became mapped/visible, fire state-change signals. */\n    if (Tk_IsMapped(tkwin)) {\n\tatk_object_notify_state_change(accObj, ATK_STATE_VISIBLE, TRUE);\n\tatk_object_notify_state_change(accObj, ATK_STATE_SHOWING, TRUE);\n\n\t/* For child widgets of a non-root toplevel, also nudge with children-changed. */\n\tif (!Tk_IsTopLevel(tkwin)) {\n\t    Tk_Window parentWin = Tk_Parent(tkwin);\n\t    AtkObject *parentAcc = GetAtkObjectForTkWindow(parentWin);\n\t    if (parentAcc) {\n\t\tgint idx = atk_object_get_n_accessible_children(parentAcc) - 1;\n\t\tif (idx < 0) idx = 0;\n\t\tg_signal_emit_by_name(parentAcc, \"children-changed::add\", idx, accObj);\n\t    }\n\t}\n    } else {\n\tatk_object_notify_state_change(accObj, ATK_STATE_SHOWING, FALSE);\n\tatk_object_notify_state_change(accObj, ATK_STATE_VISIBLE, FALSE);\n    }\n}\n\n/* Respond to <FocusIn/Out> events. */\nstatic void TkAtkAccessible_FocusHandler(void *clientData, XEvent *eventPtr)\n{\n    TkAtkAccessible *acc = (TkAtkAccessible *)clientData;\n    if (!acc || !acc->tkwin) return;\n\n    bool focused = (eventPtr->type == FocusIn);\n    AtkObject *obj = ATK_OBJECT(acc);\n    AtkRole role = GetAtkRoleForWidget(acc->tkwin);\n\n    /* Update this widget's focus state. */\n    acc->is_focused = focused;\n    atk_object_notify_state_change(obj, ATK_STATE_FOCUSED, focused);\n    g_signal_emit_by_name(obj, \"focus-event\", focused);\n\n    /* Track the last focused widget globally. */\n    static Tk_Window last_focused_win = NULL;\n\n    if (focused) {\n\t/* Widget gained focus - update the global tracker. */\n\tlast_focused_win = acc->tkwin;\n\n\t/* Notify parent container about active descendant. */\n\tif (role != ATK_ROLE_WINDOW) {\n\t    AtkObject *parent = atk_object_get_parent(obj);\n\t    if (parent) {\n\t\tg_signal_emit_by_name(parent, \"active-descendant-changed\", obj);\n\n\t\t/* Also emit children-changed to refresh ATK's view. */\n\t\tg_signal_emit_by_name(parent, \"children-changed::add\",\n\t\t\t\t      atk_object_get_n_accessible_children(parent) - 1,\n\t\t\t\t      obj);\n\t    }\n\t}\n    } else {\n\t/* Widget lost focus - clear from global tracker if it was this widget. */\n\tif (last_focused_win == acc->tkwin) {\n\t    last_focused_win = NULL;\n\t}\n    }\n\n    /* Handle window activation/deactivation for toplevels. */\n    if (role == ATK_ROLE_WINDOW) {\n\tif (focused) {\n\t    g_signal_emit_by_name(obj, \"window-activate\");\n\t} else {\n\t    g_signal_emit_by_name(obj, \"window-deactivate\");\n\t}\n    }\n}\n/*\n *----------------------------------------------------------------------\n *\n * Tcl command implementations - expose these API's to Tcl scripts and\n * initialize ATK integration in Tcl/Tk.\n *\n *----------------------------------------------------------------------\n */\n\n/*\n *----------------------------------------------------------------------\n *\n * EmitSelectionChanged --\n *\n *  Accessibility system notification when selection changed.\n *\n * Results:\n *\n * Accessibility system is made aware when selection or value data is changed.\n *\n * Side effects:\n *\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int EmitSelectionChanged(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    const char *windowName = Tcl_GetString(objv[1]);\n    Tk_Window tkwin = Tk_NameToWindow(interp, windowName, Tk_MainWindow(interp));\n    if (!tkwin) return TCL_OK;\n\n    /* Ensure AtkObject exists. */\n    AtkObject *obj = GetAtkObjectForTkWindow(tkwin);\n    if (!obj) {\n\tobj = TkCreateAccessibleAtkObject(interp, tkwin, windowName);\n\tif (!obj) return TCL_OK;\n\tTkAtkAccessible_RegisterEventHandlers(tkwin, (TkAtkAccessible *)obj);\n    }\n\n    AtkRole role = GetAtkRoleForWidget(tkwin);\n\n    /* For checkboxes and radiobuttons, emit state-changed signal. */\n    if (role == ATK_ROLE_CHECK_BOX || role == ATK_ROLE_RADIO_BUTTON || role == ATK_ROLE_TOGGLE_BUTTON) {\n\tconst char *value = GetAtkValueForWidget(tkwin);\n\tbool checked = (value != NULL) && (strcmp(value, \"selected\") == 0 || strcmp(value, \"1\") == 0);\n\n\t/* Emit the state change notification */\n\tatk_object_notify_state_change(obj, ATK_STATE_CHECKED, checked);\n    }\n\n    /* For value-supporting widgets, emit text-changed or value-changed */\n    if (role == ATK_ROLE_ENTRY || role == ATK_ROLE_TEXT || role == ATK_ROLE_COMBO_BOX) {\n\t/* Use text-changed for text-based widgets. */\n\tg_signal_emit_by_name(obj, \"text-changed::insert\", 0, 0);\n    } else if (role == ATK_ROLE_SPIN_BUTTON || role == ATK_ROLE_SLIDER ||\n\t       role == ATK_ROLE_PROGRESS_BAR || role == ATK_ROLE_SCROLL_BAR) {\n\t/* For numeric widgets, emit value-changed on the AtkValue interface. */\n\tif (ATK_IS_VALUE(obj)) {\n\t    g_object_notify(G_OBJECT(obj), \"accessible-value\");\n\t}\n    }\n\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * EmitFocusChanged --\n *\n * Accessibility system notification when focus changed.\n *\n * Results:\n *\n * Accessibility system is made aware when focus is changed.\n *\n * Side effects:\n *\n * None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int EmitFocusChanged(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    /* No-op on X11. All work is done in FocusHandler. */\n\n    return TCL_OK;\n}\n\n\n/*\n *----------------------------------------------------------------------\n *\n * IsScreenReaderRunning --\n *\n * Runtime check to see if screen reader is running.\n *\n * Results:\n *\n * Returns if screen reader is active or not.\n *\n * Side effects:\n *\n * None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int IsScreenReaderRunning(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    TCL_UNUSED(Tcl_Obj *const *)) /* objv */\n{\n    bool result = IsScreenReaderActive();\n\n    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));\n    return TCL_OK;\n}\n\n/*\n * Helper function to determine if screen reader is running. Separate function\n * because it can be called internally as well as a Tcl command.\n */\nstatic bool IsScreenReaderActive(void)\n{\n    FILE *fp = popen(\"pgrep -x orca\", \"r\");\n    if (!fp) return 0;\n\n    char buffer[16];\n    bool running = (fgets(buffer, sizeof(buffer), fp) != NULL);\n    pclose(fp);\n\n    return running;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkAtkAccessibleObjCmd --\n *\n *   Main command for adding and managing accessibility objects to Tk\n *   widgets on Linux using the ATK accessibility API.\n *\n * Results:\n *\n *   A standard Tcl result.\n *\n * Side effects:\n *\n *   Tk widgets are now accessible to screen readers.\n *\n *----------------------------------------------------------------------\n */\n\nint TkAtkAccessibleObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n\n    const char *windowName = Tcl_GetString(objv[1]);\n    if (!windowName) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"Window name cannot be null.\", -1));\n\treturn TCL_ERROR;\n    }\n\n    Tk_Window tkwin = Tk_NameToWindow(interp, windowName, Tk_MainWindow(interp));\n    if (tkwin == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"Invalid window name.\", -1));\n\treturn TCL_ERROR;\n    }\n\n    /* Use the recursive registration. */\n    RegisterWidgetRecursive(interp, tkwin);\n\n    /* Also ensure the entire hierarchy is in ATK. */\n    EnsureWidgetInAtkHierarchy(interp, tkwin);\n\n    /* If widget has focus, update ATK focus chain. */\n    TkWindow *focusPtr = TkGetFocusWin((TkWindow*)tkwin);\n    if (focusPtr == (TkWindow*)tkwin) {\n\tUpdateAtkFocusChain(tkwin);\n    }\n\n    return TCL_OK;\n}\n#endif\n\n/*\n *----------------------------------------------------------------------\n *\n * TkAtkAccessibility_Init --\n *\n *  Initializes the accessibility module.\n *\n * Results:\n *\n *   A standard Tcl result.\n *\n * Side effects:\n *\n *  Accessibility module is now activated.\n *\n *----------------------------------------------------------------------\n */\n\n#ifdef HAVE_ATK\nint TkAtkAccessibility_Init(Tcl_Interp *interp)\n{\n    /* Initialize AT-SPI bridge. */\n    if (atk_bridge_adaptor_init(NULL, NULL) != 0) {\n\tTcl_SetResult(interp, \"Failed to initialize AT-SPI bridge\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    /* Get and initialize root accessible. */\n    tk_root_accessible = tk_util_get_root();\n    if (!tk_root_accessible) {\n\tTcl_SetResult(interp, \"Failed to create root accessible object\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    /* Activate widget-object hash table mapping. */\n    InitAtkTkMapping();\n\n    /* Establish GLib context for event loop processing. */\n    acc_context = ATK_CONTEXT;\n    Tcl_CreateEventSource(Atk_Event_Setup, Atk_Event_Check, 0);\n\n    /* Shut off GLib warnings. */\n    g_log_set_handler(\"Atk\", G_LOG_LEVEL_CRITICAL, ignore_atk_critical, NULL);\n    g_log_set_handler(\"GLib-GObject\", G_LOG_LEVEL_CRITICAL, ignore_atk_critical, NULL);\n\n    /* Initialize main window */\n    Tk_Window mainWin = Tk_MainWindow(interp);\n    if (!mainWin) {\n\tTcl_SetResult(interp, \"Failed to get main window\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    AtkObject *main_acc = TkCreateAccessibleAtkObject(interp, mainWin, Tk_PathName(mainWin));\n    if (!main_acc) {\n\tTcl_SetResult(interp, \"Failed to create AtkObject for root window\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    atk_object_set_role(main_acc, ATK_ROLE_WINDOW);\n    tk_set_name(main_acc, \"Tk Application\");\n    RegisterAtkObjectForTkWindow(mainWin, main_acc);\n    RegisterToplevelWindow(interp, mainWin, main_acc);\n\n    /* Recursively register ALL existing widgets. */\n    RegisterWidgetRecursive(interp, mainWin);\n\n\t/* Force initial children-changed signals for all toplevels (helps Orca at startup).  */\n    GList *l;\n    for (l = toplevel_accessible_objects; l != NULL; l = l->next) {\n\tAtkObject *top = ATK_OBJECT(l->data);\n\tgint idx = g_list_index(toplevel_accessible_objects, top);\n\tif (idx >= 0 && tk_root_accessible) {\n\t    g_signal_emit_by_name(tk_root_accessible, \"children-changed::add\", idx, top);\n\t}\n\n\t/* Also notify showing if mapped */\n\tif (Tk_IsMapped(((TkAtkAccessible*)top)->tkwin)) {\n\t    atk_object_notify_state_change(top, ATK_STATE_SHOWING, TRUE);\n\t    atk_object_notify_state_change(top, ATK_STATE_VISIBLE, TRUE);\n\t}\n    }\n\n    /* Register X event handlers for main window. */\n    TkAtkAccessible_RegisterEventHandlers(mainWin, (TkAtkAccessible *)main_acc);\n\n    /* Register Tcl commands. */\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::add_acc_object\",\n\t    TkAtkAccessibleObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_selection_change\",\n\t    EmitSelectionChanged, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_focus_change\",\n\t    EmitFocusChanged, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::check_screenreader\",\n\t    IsScreenReaderRunning, NULL, NULL);\n\n    return TCL_OK;\n}\n#else\n/* Stub command to run if Tk is compiled without accessibility support. */\n\nstatic int\nTkAccessibleStubObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    TCL_UNUSED(Tcl_Obj *const *)) /* objv */\n{\n    static int warned = 0;\n\n    if (!warned) {\n\tTcl_SetObjResult(interp,\n\tTcl_NewStringObj(\"Warning: Tk accessibility support not available in this build.\", -1));\n\twarned = 1;\n    } else {\n\tTcl_SetObjResult(interp, Tcl_NewObj()); /* Empty string after first warning. */\n    }\n\n    return TCL_OK;\n}\n\nint TkAtkAccessibility_Init(Tcl_Interp *interp)\n{\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::add_acc_object\", TkAccessibleStubObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_selection_change\", TkAccessibleStubObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_focus_change\", TkAccessibleStubObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::check_screenreader\", TkAccessibleStubObjCmd, NULL, NULL);\n    return TCL_OK;\n}\n#endif\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixBidiFont.c",
    "content": "/*\n * tkUnixBidiFont.c --\n *\n * Alternate implementation of tkUnixFont.c using Xft with proper\n * text shaping.\n *\n * Copyright (c) 2002-2003 Keith Packard\n * Copyright (c) 2026 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkFont.h\"\n#include <X11/Xft/Xft.h>\n#include <ft2build.h>\n#include FT_FREETYPE_H\n#include <math.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <hb.h>\n#include <hb-ft.h>\n#include <SheenBidi/SheenBidi.h>\n\n#define MAX_CACHED_COLORS 16\n#define MAX_GLYPHS 512\n#define MAX_FONTS 200\n#define MAX_BIDI_RUNS 32\n#define MAX_STRING_CACHE 1024\n\n#define TK_DRAW_IN_CONTEXT\n\n/*\n * ---------------------------------------------------------------\n * BidiRun --\n *\n *   Structure to hold bidirectional run information.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    int offset;                 /* Byte offset in original UTF-8 string. */\n    int len;                    /* Length in bytes. */\n    int isRTL;                  /* 1 if this run is RTL, 0 if LTR. */\n} BidiRun;\n\n/*\n * ---------------------------------------------------------------\n * UnixFtFace --\n *\n *   Structure representing a single font face from fontconfig,\n *   with cached Xft fonts for rotated and unrotated versions.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    XftFont *ftFont;           /* Rotated font. */\n    XftFont *ft0Font;          /* Unrotated font. */\n    FcPattern *source;         /* Fontconfig pattern. */\n    FcCharSet *charset;        /* Supported characters. */\n    double angle;              /* Current rotation angle. */\n\n    /* HarfBuzz font mapping. */\n    hb_font_t *hbFont;         /* Corresponding HarfBuzz font. */\n    hb_blob_t *hbBlob;         /* Font blob (kept alive for hbFont lifetime) */\n    hb_face_t *hbFace;         /* HarfBuzz face (kept alive for hbFont lifetime) */\n    int isLoaded;              /* Whether hbFont was successfully loaded. */\n\n    /* Font metrics for scaling. */\n    double unitsPerEm;         /* For scaling glyph positions. */\n    double ascender;           /* Font ascender in design units. */\n    double descender;          /* Font descender in design units. */\n} UnixFtFace;\n\n/*\n * ---------------------------------------------------------------\n * UnixFtColorList --\n *\n *   Cached XftColor entry with LRU next pointer.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    XftColor color;\n    int next;\n} UnixFtColorList;\n\n/*\n * ---------------------------------------------------------------\n * ShapedGlyphBuffer --\n *\n *   Pure output buffer for shaped glyphs. No shaper state; no cache.\n *   Callers stack-allocate this, pass it to shaping functions.\n *\n *   Note on glyph IDs: HarfBuzz operates on FreeType glyph indices,\n *   which match Xft's internal glyph space. IDs are directly usable\n *   with XftDrawGlyphFontSpec provided the same font file+face is used\n *   for both shaping and rendering. fontIndex tracks which UnixFtFace\n *   produced each glyph to ensure this invariant.\n *\n *   byteOffset records the cluster start AND clusterLen records\n *   the cluster length in bytes. This enables accurate cursor placement and\n *   text selection by mapping pixel positions back to byte ranges.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    struct {\n        int fontIndex;         /* Index into UnixFtFont->faces[]. */\n        unsigned int glyphId;  /* FreeType glyph index (HarfBuzz == Xft space). */\n        int x, y;              /* Pen position for this glyph. */\n        int advanceX;          /* Advance width in pixels. */\n        int byteOffset;        /* Byte offset of cluster start in source string. */\n        int clusterLen;        /* Length of cluster in bytes. */\n        int isRTL;             /* 1 if this glyph is part of an RTL run. */\n    } glyphs[MAX_GLYPHS];\n    int glyphCount;\n    int totalAdvance;          /* Total advance width in pixels. */\n    \n    /*\n     * Visual index for cursor positioning.\n     * \n     * Parallel structure that maps visual (screen) positions back to logical \n     * (source string) byte offsets. Built in sync with word reversal so that\n     * cursor positioning works correctly for LTR, RTL, and mixed text.\n     * \n     * visualIndex[i] corresponds to glyphs[i] and contains:\n     * - x: visual X position of this glyph\n     * - advanceX: width of this glyph\n     * - byteEnd: logical byte offset after this glyph (byteOffset + clusterLen)\n     * \n     * For cursor positioning: binary search to find glyph at visual position X,\n     * then return the corresponding byteEnd.\n     */\n    struct {\n        int x;              /* Visual X position of glyph */\n        int advanceX;       /* Glyph width */\n        int byteEnd;        /* Logical byte end (byteOffset + clusterLen) */\n    } visualIndex[MAX_GLYPHS];\n    int indexCount;         /* Should equal glyphCount; kept separate for clarity */\n} ShapedGlyphBuffer;\n\n/*\n * ---------------------------------------------------------------\n * X11Shaper --\n *\n *   Persistent per-font shaping state. Owns the HarfBuzz context,\n *   font mapping, and string cache.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    hb_buffer_t *buffer;\n    /* Font mapping - bidirectional. */\n    struct {\n        hb_font_t *hbFont;\n        int faceIndex;\n    } fontMap[MAX_FONTS];\n    int numFonts;\n    /* Simple string cache for common measurements. */\n    struct {\n        char text[MAX_STRING_CACHE];\n        int len;\n        ShapedGlyphBuffer buffer;\n        int valid;\n    } cache;\n    /* Error tracking. */\n    int shapeErrors;\n    int lastError;\n} X11Shaper;\n\n/*\n * ---------------------------------------------------------------\n * UnixFtFont --\n *\n *   Main font structure - must have TkFont as first member.\n *   Contains all faces, shaper state, and cached resources.\n * ---------------------------------------------------------------\n */\n\ntypedef struct {\n    TkFont font;                /* Must be first. */\n    UnixFtFace *faces;\n    int nfaces;\n    FcFontSet *fontset;\n    FcPattern *pattern;\n    Display *display;\n    int screen;\n    Colormap colormap;\n    Visual *visual;\n    int ncolors;\n    int firstColor;\n    UnixFtColorList colors[MAX_CACHED_COLORS];\n    X11Shaper shaper;\n    /* Precomputed scale factors. */\n    double pixelScale;          /* Global pixel scaling factor. */\n} UnixFtFont;\n\n/*\n * Used to describe the current clipping box. Can't be passed normally because\n * the information isn't retrievable from the GC.\n */\n\ntypedef struct {\n    Region clipRegion;\t\t/* The clipping region, or None. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\nTCL_DECLARE_MUTEX(xftMutex);\n#define LOCK Tcl_MutexLock(&xftMutex)\n#define UNLOCK Tcl_MutexUnlock(&xftMutex)\n\n/* Function prototypes. */\nstatic void X11Shaper_Init(X11Shaper *s, UnixFtFont *fontPtr);\nstatic void X11Shaper_Destroy(X11Shaper *s);\nstatic int X11Shaper_ShapeString(X11Shaper *shaper, UnixFtFont *fontPtr,\n                                 const char *source, int numBytes,\n                                 ShapedGlyphBuffer *buffer);\nstatic int GetBidiRuns(FcChar32 *ucs4, int charCount, BidiRun *runs, int maxRuns);\nstatic XftFont * GetFont(UnixFtFont *fontPtr, FcChar32 ucs4, double angle);\nstatic XftFont * GetFaceFont(UnixFtFont *fontPtr, int faceIndex, double angle);\nstatic XftColor * LookUpColor(Display *display, UnixFtFont *fontPtr,\n                             unsigned long pixel);\nstatic int IsLatinOnly(const char *str, int len);  /* fast-path helper */\nstatic int GetRunFaceIndex(UnixFtFont *fontPtr, FcChar32 *ucs4Chars,\n\t\t\t   int runStart, int runLen);\n\n/*\n * ---------------------------------------------------------------\n * IsLatinOnly --\n *\n *   Returns 1 if every codepoint in the UTF-8 string falls within\n *   the Latin \"simple\" range: Basic Latin (U+0000-U+007F), Latin-1\n *   Supplement (U+0080-U+00FF), Latin Extended-A (U+0100-U+017F),\n *   or Latin Extended-B (U+0180-U+024F).\n *\n *   All codepoints in this range (U+0000-U+024F) are precomposed\n *   or trivially handled by a single Xft font face with no BiDi\n *   reordering, no ligature shaping, and no multi-face fallback.\n *   Using XftTextExtentsUtf8 / XftDrawStringUtf8 directly is both\n *   correct and significantly faster for these scripts.\n *\n *   Returns 0 as soon as any out-of-range codepoint is found.\n * ---------------------------------------------------------------\n */\n\nstatic int\nIsLatinOnly(const char *str, int len)\n{\n    int i = 0;\n    while (i < len) {\n        unsigned char c = (unsigned char)str[i];\n\n        if (c < 0x80) {\n            /* Single-byte ASCII — always fine. */\n            i++;\n            continue;\n        }\n\n        /* Decode the leading byte to determine codepoint range. */\n        FcChar32 uc;\n        int clen = FcUtf8ToUcs4((const FcChar8 *)(str + i), &uc, len - i);\n        if (clen <= 0) {\n            /* Invalid UTF-8 — route to shaper for safe handling. */\n            return 0;\n        }\n\n        /* Accept U+0080 through U+024F (Latin-1 Supplement through\n         * Latin Extended-B).  Everything above U+024F needs the shaper.\n         */\n        if (uc > 0x024F) {\n            return 0;\n        }\n\n        i += clen;\n    }\n    return 1;\n}\n\n/*\n * ---------------------------------------------------------------\n * GetFaceFont --\n *\n *   Retrieve or create an XftFont for a specific face index and rotation\n *   angle.\n *\n * Results:\n *   Pointer to XftFont, or NULL if not available.\n *\n * Side effects:\n *   May create new XftFont if not already cached.\n * ---------------------------------------------------------------\n */\n\nstatic XftFont *\nGetFaceFont(\n    UnixFtFont *fontPtr,\n    int faceIndex,\n    double angle)\n{\n    if (faceIndex < 0 || faceIndex >= fontPtr->nfaces) {\n        faceIndex = 0;\n    }\n\n    UnixFtFace *face = &fontPtr->faces[faceIndex];\n\n    if (angle == 0.0) {\n        if (!face->ft0Font) {\n            FcPattern *pat = FcFontRenderPrepare(NULL, fontPtr->pattern,\n                                                 face->source);\n            LOCK;\n            face->ft0Font = XftFontOpenPattern(fontPtr->display, pat);\n            UNLOCK;\n\n            if (!face->ft0Font) {\n                /* Safer fallback using size from original pattern. */\n                double size = 12.0;\n                FcPatternGetDouble(fontPtr->pattern, FC_SIZE, 0, &size);\n\n                LOCK;\n                face->ft0Font = XftFontOpen(fontPtr->display, fontPtr->screen,\n                                           FC_FAMILY, FcTypeString, \"sans-serif\",\n                                           FC_SIZE, FcTypeDouble, size, NULL);\n                UNLOCK;\n\n                if (!face->ft0Font) {\n                    LOCK;\n                    face->ft0Font = XftFontOpen(fontPtr->display, fontPtr->screen,\n                                               FC_FAMILY, FcTypeString, \"fixed\",\n                                               FC_SIZE, FcTypeDouble, size, NULL);\n                    UNLOCK;\n                }\n            }\n\n            /* Extract metrics. */\n            if (face->ft0Font && face->unitsPerEm == 0) {\n                FT_Face ftFace = XftLockFace(face->ft0Font);\n                if (ftFace) {\n                    face->unitsPerEm = ftFace->units_per_EM;\n                    face->ascender   = ftFace->ascender;\n                    face->descender  = ftFace->descender;\n                    XftUnlockFace(face->ft0Font);\n                }\n            }\n\n            XSync(fontPtr->display, False);   /* Helps PostScript tests. */\n        }\n        return face->ft0Font;\n    } \n    else {\n        /* Rotated font handling. */\n        if (!face->ftFont || face->angle != angle) {\n            FcPattern *pat = FcFontRenderPrepare(NULL, fontPtr->pattern,\n                                                 face->source);\n\n            double rad = angle * M_PI / 180.0;\n            double s = sin(rad), c = cos(rad);\n            FcMatrix mat;\n            mat.xx = c;\n            mat.xy = -s;\n            mat.yx = s;\n            mat.yy = c;\n            FcPatternAddMatrix(pat, FC_MATRIX, &mat);\n\n            LOCK;\n            XftFont *ftFont = XftFontOpenPattern(fontPtr->display, pat);\n            UNLOCK;\n\n            if (!ftFont) {\n                /* Fallback with correct size. */\n                double size = 12.0;\n                FcPatternGetDouble(fontPtr->pattern, FC_SIZE, 0, &size);\n\n                LOCK;\n                ftFont = XftFontOpen(fontPtr->display, fontPtr->screen,\n                                     FC_FAMILY, FcTypeString, \"sans-serif\",\n                                     FC_SIZE, FcTypeDouble, size,\n                                     FC_MATRIX, FcTypeMatrix, &mat,\n                                     NULL);\n                UNLOCK;\n            }\n\n            if (face->ftFont) {\n                LOCK;\n                XftFontClose(fontPtr->display, face->ftFont);\n                UNLOCK;\n            }\n            face->ftFont = ftFont;\n            face->angle = angle;\n\n            XSync(fontPtr->display, False);   /* Helps stability. */\n        }\n        return face->ftFont;\n    }\n}\n\n/*\n * ---------------------------------------------------------------\n * GetFont --\n *\n *   Retrieve an XftFont for a given character and rotation angle.\n *   Selects the face that contains the character, falling back to first face.\n *\n * Results:\n *   Pointer to XftFont, or NULL if not available.\n *\n * Side effects:\n *   May create new XftFont if not already cached.\n * ---------------------------------------------------------------\n */\n\nstatic XftFont *\nGetFont(\n    UnixFtFont *fontPtr,\n    FcChar32 ucs4,\n    double angle)\n{\n    int i;\n\n    /* Find face containing this character. */\n    if (ucs4) {\n        for (i = 0; i < fontPtr->nfaces; i++) {\n            FcCharSet *charset = fontPtr->faces[i].charset;\n            if (charset && FcCharSetHasChar(charset, ucs4)) {\n                break;\n            }\n        }\n        if (i == fontPtr->nfaces) {\n            i = 0;  /* Fallback to first face. */\n        }\n    } else {\n        i = 0;\n    }\n\n    return GetFaceFont(fontPtr, i, angle);\n}\n\n/*\n * ---------------------------------------------------------------\n * LookUpColor --\n *\n *   Convert a pixel value to an XftColor. Uses a small LRU cache.\n *\n * Results:\n *   Pointer to XftColor, or NULL if cache is full.\n *\n * Side effects:\n *   May update the color cache.\n * ---------------------------------------------------------------\n */\n\nstatic XftColor *\nLookUpColor(\n    Display *display,\n    UnixFtFont *fontPtr,\n    unsigned long pixel)\n{\n    int i, last = -1, last2 = -1;\n    XColor xcolor;\n\n    for (i = fontPtr->firstColor;\n         i >= 0; last2 = last, last = i, i = fontPtr->colors[i].next) {\n\n        if (pixel == fontPtr->colors[i].color.pixel) {\n            if (last >= 0) {\n                fontPtr->colors[last].next  = fontPtr->colors[i].next;\n                fontPtr->colors[i].next     = fontPtr->firstColor;\n                fontPtr->firstColor         = i;\n            }\n            return &fontPtr->colors[i].color;\n        }\n    }\n\n    if (fontPtr->ncolors < MAX_CACHED_COLORS) {\n        last2 = -1;\n        last  = fontPtr->ncolors++;\n    } else {\n        return NULL;\n    }\n\n    xcolor.pixel = pixel;\n    XQueryColor(display, fontPtr->colormap, &xcolor);\n\n    fontPtr->colors[last].color.color.red   = xcolor.red;\n    fontPtr->colors[last].color.color.green = xcolor.green;\n    fontPtr->colors[last].color.color.blue  = xcolor.blue;\n    fontPtr->colors[last].color.color.alpha = 0xFFFF;\n    fontPtr->colors[last].color.pixel       = pixel;\n\n    if (last2 >= 0) {\n        fontPtr->colors[last2].next = fontPtr->colors[last].next;\n    }\n    fontPtr->colors[last].next = fontPtr->firstColor;\n    fontPtr->firstColor        = last;\n\n    return &fontPtr->colors[last].color;\n}\n\n/*\n * ---------------------------------------------------------------\n * GetTkFontAttributes --\n *\n *   Fill in TkFontAttributes from an XftFont.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   The TkFontAttributes structure is updated.\n * ---------------------------------------------------------------\n */\n\nstatic void\nGetTkFontAttributes(\n    Tk_Window tkwin,\n    XftFont *ftFont,\n    TkFontAttributes *faPtr)\n{\n    const char *family = \"Unknown\";\n    const char *const *familyPtr = &family;\n    double ptSize, dblPxSize, size;\n    int intPxSize, weight, slant;\n\n    (void) XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0, familyPtr);\n\n    if (XftPatternGetDouble(ftFont->pattern, XFT_SIZE, 0, &ptSize) == XftResultMatch) {\n        size = ptSize;\n    } else if (XftPatternGetDouble(ftFont->pattern, XFT_PIXEL_SIZE, 0,\n                                   &dblPxSize) == XftResultMatch) {\n        size = -dblPxSize;\n    } else if (XftPatternGetInteger(ftFont->pattern, XFT_PIXEL_SIZE, 0,\n                                    &intPxSize) == XftResultMatch) {\n        size = (double)-intPxSize;\n    } else {\n        size = 12.0;\n    }\n\n    if (XftPatternGetInteger(ftFont->pattern, XFT_WEIGHT, 0, &weight) != XftResultMatch) {\n        weight = XFT_WEIGHT_MEDIUM;\n    }\n    if (XftPatternGetInteger(ftFont->pattern, XFT_SLANT, 0, &slant) != XftResultMatch) {\n        slant = XFT_SLANT_ROMAN;\n    }\n\n    faPtr->family = Tk_GetUid(family);\n    faPtr->size = TkFontGetPoints(tkwin, size);\n    faPtr->weight = (weight > XFT_WEIGHT_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;\n    faPtr->slant = (slant > XFT_SLANT_ROMAN) ? TK_FS_ITALIC : TK_FS_ROMAN;\n    faPtr->underline = 0;\n    faPtr->overstrike = 0;\n}\n\n/*\n * ---------------------------------------------------------------\n * GetTkFontMetrics --\n *\n *   Fill in TkFontMetrics from an XftFont.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   The TkFontMetrics structure is updated.\n * ---------------------------------------------------------------\n */\n\nstatic void\nGetTkFontMetrics(\n    XftFont *ftFont,\n    TkFontMetrics *fmPtr)\n{\n    int spacing;\n\n    if (XftPatternGetInteger(ftFont->pattern, XFT_SPACING, 0,\n                             &spacing) != XftResultMatch) {\n        spacing = XFT_PROPORTIONAL;\n    }\n\n    fmPtr->ascent = ftFont->ascent;\n    fmPtr->descent = ftFont->descent;\n    fmPtr->maxWidth = ftFont->max_advance_width;\n    fmPtr->fixed = (spacing != XFT_PROPORTIONAL);\n}\n\n/*\n * ---------------------------------------------------------------\n * GetBidiRuns --\n *\n *   Use SheenBidi to properly analyze text per UAX#9 and split it into\n *   level runs with correct directionality in visual order.\n *\n * Results:\n *   Returns number of runs created (at least 1). Fills runs array\n *   in visual display order (left-to-right on screen).\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nstatic int\nGetBidiRuns(\n    FcChar32 *ucs4,\n    int charCount,\n    BidiRun *runs,\n    int maxRuns)\n{\n    if (charCount <= 0) {\n        runs[0].offset = 0;\n        runs[0].len    = 0;\n        runs[0].isRTL  = 0;\n        return 1;\n    }\n\n    /* Fast path: check if any strong RTL characters exist. */\n    int needsBidi = 0;\n    for (int i = 0; i < charCount; i++) {\n        if (ucs4[i] >= 0x0590) {  /* Hebrew/Arabic/Thaana/etc. start. */\n            needsBidi = 1;\n            break;\n        }\n    }\n\n    if (!needsBidi) {\n        runs[0].offset = 0;\n        runs[0].len    = charCount;\n        runs[0].isRTL  = 0;\n        return 1;\n    }\n\n    /* Full bidi analysis. */\n    SBCodepointSequence seq = {SBStringEncodingUTF32, ucs4, (SBUInteger)charCount};\n    SBAlgorithmRef algo = SBAlgorithmCreate(&seq);\n\n    /* Use explicit LTR base level (common default for Tk apps). */\n    SBParagraphRef para = SBAlgorithmCreateParagraph(algo, 0, (SBUInteger)charCount,\n                                                     SBLevelDefaultLTR);\n\n    SBLineRef line = SBParagraphCreateLine(para, 0, (SBUInteger)charCount);\n\n    SBUInteger runCount = SBLineGetRunCount(line);\n    const SBRun *bidiRuns = SBLineGetRunsPtr(line);\n\n    int outRuns = 0;\n    for (int i = 0; i < (int)runCount && outRuns < maxRuns; i++) {\n        runs[outRuns].offset = (int)bidiRuns[i].offset;\n        runs[outRuns].len    = (int)bidiRuns[i].length;\n        runs[outRuns].isRTL  = (bidiRuns[i].level & 1);\n        outRuns++;\n    }\n\n    SBLineRelease(line);\n    SBParagraphRelease(para);\n    SBAlgorithmRelease(algo);\n\n    /* Always return at least one run. */\n    return outRuns > 0 ? outRuns : 1;\n}\n\n/*\n * ---------------------------------------------------------------\n * InitFont --\n *\n *   Initializes the fields of a UnixFtFont structure. If fontPtr is NULL,\n *   also allocates a new UnixFtFont.\n *\n * Results:\n *   On error, frees fontPtr and returns NULL, otherwise returns fontPtr.\n *\n * Side effects:\n *   Allocates memory, loads fonts, initializes shaper.\n * ---------------------------------------------------------------\n */\n\nstatic void FinishedWithFont(UnixFtFont *fontPtr);\n\nstatic int\nInitFontErrorProc(\n    void *clientData,\n    TCL_UNUSED(XErrorEvent *))\n{\n    int *errorFlagPtr = (int *)clientData;\n\n    if (errorFlagPtr != NULL) {\n\t*errorFlagPtr = 1;\n    }\n    return 0;\n}\n\nstatic UnixFtFont *\nInitFont(\n    Tk_Window tkwin,\n    FcPattern *pattern,\n    UnixFtFont *fontPtr)\n{\n    FcFontSet *set;\n    FcCharSet *charset;\n    FcResult result;\n    XftFont *ftFont;\n    int i, iWidth, errorFlag;\n    Tk_ErrorHandler handler;\n\n    if (!fontPtr) {\n        fontPtr = (UnixFtFont *)Tcl_Alloc(sizeof(UnixFtFont));\n        if (!fontPtr) {\n            return NULL;\n        }\n        memset(fontPtr, 0, sizeof(UnixFtFont));\n    }\n\n    FcConfigSubstitute(0, pattern, FcMatchPattern);\n    XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern);\n\n    /*\n     * Generate the list of fonts.\n     */\n    set = FcFontSort(0, pattern, FcTrue, NULL, &result);\n    if (!set || set->nfont == 0) {\n        if (!fontPtr->font.fid) {\n            Tcl_Free(fontPtr);\n        }\n        FcPatternDestroy(pattern);\n        return NULL;\n    }\n\n    fontPtr->fontset = set;\n    fontPtr->pattern = pattern;\n    fontPtr->faces = (UnixFtFace *)Tcl_Alloc(set->nfont * sizeof(UnixFtFace));\n    if (!fontPtr->faces) {\n        FcFontSetDestroy(set);\n        Tcl_Free(fontPtr);\n        FcPatternDestroy(pattern);\n        return NULL;\n    }\n    fontPtr->nfaces = set->nfont;\n\n    /*\n     * Fill in information about each returned font.\n     */\n    for (i = 0; i < set->nfont; i++) {\n        fontPtr->faces[i].ftFont     = NULL;\n        fontPtr->faces[i].ft0Font    = NULL;\n        fontPtr->faces[i].source     = set->fonts[i];\n        fontPtr->faces[i].angle      = 0.0;\n        fontPtr->faces[i].hbFont     = NULL;\n        fontPtr->faces[i].hbBlob     = NULL;\n        fontPtr->faces[i].hbFace     = NULL;\n        fontPtr->faces[i].isLoaded   = 0;\n        fontPtr->faces[i].unitsPerEm = 0.0;\n        fontPtr->faces[i].ascender   = 0.0;\n        fontPtr->faces[i].descender  = 0.0;\n\n        if (FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0, &charset) == FcResultMatch) {\n            fontPtr->faces[i].charset = FcCharSetCopy(charset);\n        } else {\n            fontPtr->faces[i].charset = NULL;\n        }\n    }\n\n    /*\n     * Initialize the shaper before calling GetFont() or Tk_MeasureChars()\n     * because both can trigger shaping operations.\n     */\n    X11Shaper_Init(&fontPtr->shaper, fontPtr);\n\n    /* Set a safe default pixel scale (will be overridden\n     * per-face when metrics are loaded).\n     */\n    fontPtr->pixelScale = 1.0;\n\n    fontPtr->display   = Tk_Display(tkwin);\n    fontPtr->screen    = Tk_ScreenNumber(tkwin);\n    fontPtr->colormap  = Tk_Colormap(tkwin);\n    fontPtr->visual    = Tk_Visual(tkwin);\n    fontPtr->ncolors   = 0;\n    fontPtr->firstColor = -1;\n\n    /*\n     * Fill in platform-specific fields of TkFont.\n     */\n    errorFlag = 0;\n    handler = Tk_CreateErrorHandler(Tk_Display(tkwin),\n                    -1, -1, -1, InitFontErrorProc, (void *)&errorFlag);\n\n    ftFont = GetFont(fontPtr, 0, 0.0);\n    if ((ftFont == NULL) || errorFlag) {\n        Tk_DeleteErrorHandler(handler);\n        FinishedWithFont(fontPtr);\n        if (!fontPtr->font.fid) {\n            Tcl_Free(fontPtr);\n        }\n        return NULL;\n    }\n\n    fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), \"fixed\");\n\n    GetTkFontAttributes(tkwin, ftFont, &fontPtr->font.fa);\n    GetTkFontMetrics(ftFont, &fontPtr->font.fm);\n\n    Tk_DeleteErrorHandler(handler);\n    if (errorFlag) {\n        FinishedWithFont(fontPtr);\n        if (!fontPtr->font.fid) {\n            Tcl_Free(fontPtr);\n        }\n        return NULL;\n    }\n\n    /*\n     * Compute underline position and thickness.\n     */\n    {\n        TkFont *fPtr = &fontPtr->font;\n\n        fPtr->underlinePos = fPtr->fm.descent / 2;\n\n        errorFlag = 0;\n        handler = Tk_CreateErrorHandler(Tk_Display(tkwin),\n                        -1, -1, -1, InitFontErrorProc, (void *)&errorFlag);\n\n        Tk_MeasureChars((Tk_Font)fPtr, \"I\", 1, -1, 0, &iWidth);\n\n        Tk_DeleteErrorHandler(handler);\n        if (errorFlag) {\n            FinishedWithFont(fontPtr);\n            if (!fontPtr->font.fid) {\n                Tcl_Free(fontPtr);\n            }\n            return NULL;\n        }\n\n        fPtr->underlineHeight = iWidth / 3;\n        if (fPtr->underlineHeight == 0) {\n            fPtr->underlineHeight = 1;\n        }\n        if (fPtr->underlineHeight + fPtr->underlinePos > fPtr->fm.descent) {\n            fPtr->underlineHeight = fPtr->fm.descent - fPtr->underlinePos;\n            if (fPtr->underlineHeight == 0) {\n                fPtr->underlinePos--;\n                fPtr->underlineHeight = 1;\n            }\n        }\n    }\n\n    return fontPtr;\n}\n\n/*\n * ---------------------------------------------------------------\n * FinishedWithFont --\n *\n *   Release all resources associated with a UnixFtFont.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Font data is freed, Xft fonts closed, shaper destroyed.\n * ---------------------------------------------------------------\n */\n\nstatic void\nFinishedWithFont(\n    UnixFtFont *fontPtr)\n{\n    Display *display = fontPtr->display;\n    int i;\n    Tk_ErrorHandler handler =\n\t    Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n    for (i = 0; i < fontPtr->nfaces; i++) {\n\tif (fontPtr->faces[i].ftFont) {\n\t    LOCK;\n\t    XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);\n\t    UNLOCK;\n\t}\n\tif (fontPtr->faces[i].ft0Font) {\n\t    LOCK;\n\t    XftFontClose(fontPtr->display, fontPtr->faces[i].ft0Font);\n\t    UNLOCK;\n\t}\n\tif (fontPtr->faces[i].hbFont) {\n\t    /* Don't destroy - fonts/faces/blobs stay alive for program lifetime */\n\t    fontPtr->faces[i].hbFont = NULL;\n\t}\n\tif (fontPtr->faces[i].charset) {\n\t    FcCharSetDestroy(fontPtr->faces[i].charset);\n\t}\n    }\n    if (fontPtr->faces) {\n\tTcl_Free(fontPtr->faces);\n    }\n    if (fontPtr->pattern) {\n\tFcPatternDestroy(fontPtr->pattern);\n    }\n    if (fontPtr->font.fid) {\n\tXUnloadFont(fontPtr->display, fontPtr->font.fid);\n    }\n    if (fontPtr->fontset) {\n\tFcFontSetDestroy(fontPtr->fontset);\n    }\n\n    X11Shaper_Destroy(&fontPtr->shaper);\n\n    Tk_DeleteErrorHandler(handler);\n}\n\n/*\n * ---------------------------------------------------------------\n * X11Shaper_Init --\n *\n *   Initialize persistent shaping context.\n *   Fonts are loaded lazily on first use (see X11Shaper_ShapeString).\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Allocates shaping buffer.\n * ---------------------------------------------------------------\n */\n\nstatic void\nX11Shaper_Init(\n    X11Shaper *s,\n    UnixFtFont *fontPtr)\n{\n    memset(s, 0, sizeof(*s));\n\n    /* Create a HarfBuzz buffer for shaping. */\n    s->buffer = hb_buffer_create();\n    if (!s->buffer) {\n        return;\n    }\n\n    s->numFonts = 0;\n    s->cache.valid = 0;\n    s->shapeErrors = 0;\n\n    /* Fonts are loaded lazily on first shape call.\n     * This avoids issues with XftFace locking during font initialization.\n     */\n}\n\n/*\n * ---------------------------------------------------------------\n * X11Shaper_Destroy --\n *\n *   Release shaping context.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Frees shaping context.\n * ---------------------------------------------------------------\n */\n\nstatic void\nX11Shaper_Destroy(\n    X11Shaper *s)\n{\n    if (s->buffer) {\n        hb_buffer_destroy(s->buffer);\n        s->buffer = NULL;\n    }\n}\n\n/* ---------------------------------------------------------------\n * GetRunFaceIndex --\n *\n *  Choose the best font face for a given run based on the first character.\n *\n *  Results:\n *    Font face; falls back to face 0 if no match is found.\n *\n *  Side effects:\n *    None.\n * ---------------------------------------------------------------\n */\n\nstatic int\nGetRunFaceIndex(UnixFtFont *fontPtr, FcChar32 *ucs4Chars, int runStart, int runLen)\n{\n    if (runLen <= 0 || runStart < 0) {\n        return 0;\n    }\n\n    FcChar32 uc = ucs4Chars[runStart];\n\n    for (int fi = 0; fi < fontPtr->nfaces; fi++) {\n        if (fontPtr->faces[fi].charset &&\n            FcCharSetHasChar(fontPtr->faces[fi].charset, uc)) {\n            return fi;\n        }\n    }\n    return 0;   /* Fallback. */\n}\n\n/*\n * ---------------------------------------------------------------\n * X11Shaper_ShapeString --\n *\n *   Shape a UTF-8 string using HarfBuzz and produce glyph buffer.\n *\n *   Computes actual clusterLen for each glyph.\n *   Clamps byteOffset to valid range to prevent buffer overruns.\n *   Shapes all runs LTR, then reverses RTL runs manually to fix\n *   word-level BiDi (was reversing glyphs within words incorrectly).\n *   Stores isRTL flag per-glyph for cursor movement logic.\n *\n *   For each output glyph, glyphs[i].fontIndex identifies which\n *   UnixFtFace produced the glyph ID. Since HarfBuzz operates in raw\n *   FreeType glyph index space (same as Xft), the ID is valid for\n *   XftDrawGlyphFontSpec as long as the same font file+face is used\n *   for rendering. fontIndex is the key that enforces this.\n *\n *   glyphs[i].byteOffset records the byte offset of the cluster's\n *   start in the original source string, and glyphs[i].clusterLen\n *   records the length in bytes. Together these enable accurate\n *   byte-count returns from Tk_MeasureChars and pixel-to-byte\n *   mapping for cursor placement.\n *\n * Results:\n *   1 on success, 0 on failure.\n *\n * Side effects:\n *   Updates the shaper cache; buffer is filled.\n * ---------------------------------------------------------------\n */\n\nstatic int\nX11Shaper_ShapeString(\n    X11Shaper *shaper,\n    UnixFtFont *fontPtr,\n    const char *source,\n    int numBytes,\n    ShapedGlyphBuffer *buffer)\n{\n    if (!shaper->buffer || !source || numBytes <= 0 || !buffer) {\n        return 0;\n    }\n\n    /* Initialize output buffer counts to prevent garbage reads. */\n    buffer->glyphCount   = 0;\n    buffer->indexCount   = 0;\n    buffer->totalAdvance = 0;\n\n    /* Latin-only fast path. */\n    if (IsLatinOnly(source, numBytes)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, 0.0);\n        if (ftFont) {\n            int penX = 0;\n            int i = 0;\n            while (i < numBytes && buffer->glyphCount < MAX_GLYPHS) {\n                FcChar32 uc;\n                int clen = FcUtf8ToUcs4((const FcChar8 *)(source + i), &uc, numBytes - i);\n                if (clen <= 0) { i++; continue; }\n\n                unsigned int glyphId = XftCharIndex(fontPtr->display, ftFont, uc);\n                XGlyphInfo metrics;\n                XftGlyphExtents(fontPtr->display, ftFont, &glyphId, 1, &metrics);\n\n                buffer->glyphs[buffer->glyphCount].fontIndex  = 0;\n                buffer->glyphs[buffer->glyphCount].glyphId    = glyphId;\n                buffer->glyphs[buffer->glyphCount].x          = penX;\n                buffer->glyphs[buffer->glyphCount].y          = 0;\n                buffer->glyphs[buffer->glyphCount].advanceX   = metrics.xOff;\n                buffer->glyphs[buffer->glyphCount].byteOffset = i;\n                buffer->glyphs[buffer->glyphCount].clusterLen = clen;\n                buffer->glyphs[buffer->glyphCount].isRTL      = 0;\n\n                penX += metrics.xOff;\n                buffer->glyphCount++;\n                i += clen;\n            }\n            buffer->totalAdvance = penX;\n            \n            /* Build visualIndex for cursor positioning. */\n            buffer->indexCount = buffer->glyphCount;\n            for (int j = 0; j < buffer->glyphCount; j++) {\n                buffer->visualIndex[j].x        = buffer->glyphs[j].x;\n                buffer->visualIndex[j].advanceX = buffer->glyphs[j].advanceX;\n                buffer->visualIndex[j].byteEnd  = buffer->glyphs[j].byteOffset + buffer->glyphs[j].clusterLen;\n            }\n            return 1;\n        }\n    }\n    \n    /* Cache check. */\n    if (shaper->cache.valid &&\n        shaper->cache.len == numBytes &&\n        numBytes <= MAX_STRING_CACHE &&\n        memcmp(source, shaper->cache.text, numBytes) == 0) {\n        *buffer = shaper->cache.buffer;\n        return 1;\n    }\n\n    /* UCS-4 conversion. */\n    int stackCharBounds[256];\n    FcChar32 stackUcs4Chars[256];\n    int *charBounds = stackCharBounds;\n    FcChar32 *ucs4Chars = stackUcs4Chars;\n    int needFree = 0;\n\n    if (numBytes >= 256) {\n        charBounds = (int *)malloc((numBytes + 1) * sizeof(int));\n        ucs4Chars = (FcChar32 *)malloc(numBytes * sizeof(FcChar32));\n        if (!charBounds || !ucs4Chars) {\n            free(charBounds); free(ucs4Chars);\n            return 0;\n        }\n        needFree = 1;\n    }\n\n    charBounds[0] = 0;\n    int bytePos = 0, charCount = 0;\n    while (bytePos < numBytes && charCount < MAX_GLYPHS) {\n        FcChar32 uc;\n        int clen = FcUtf8ToUcs4((const FcChar8 *)(source + bytePos), &uc, numBytes - bytePos);\n        if (clen <= 0) { bytePos++; continue; }\n\n        if ((uc < 0x0020 && uc != 0x0009 && uc != 0x000A && uc != 0x000D) ||\n            (uc >= 0x0080 && uc <= 0x009F) || uc == 0xFFFD) {\n            bytePos += clen;\n            continue;\n        }\n\n        ucs4Chars[charCount] = uc;\n        charCount++;\n        bytePos += clen;\n        charBounds[charCount] = bytePos;\n    }\n\n    if (charCount == 0) {\n        if (needFree) { free(charBounds); free(ucs4Chars); }\n        /* buffer counts already zeroed at function entry */\n        return 1;\n    }\n\n    BidiRun bidiRuns[MAX_BIDI_RUNS];\n    int numRuns = GetBidiRuns(ucs4Chars, charCount, bidiRuns, MAX_BIDI_RUNS);\n\n    int globalPenX = 0;\n\n    for (int r = 0; r < numRuns; r++) {\n        int runStart = bidiRuns[r].offset;\n        int runLen   = bidiRuns[r].len;\n        int runIsRTL = bidiRuns[r].isRTL;\n\n        if (runLen <= 0) continue;\n\n        int runByteStart = charBounds[runStart];\n        int runByteEnd   = charBounds[runStart + runLen];\n        int runByteLen   = runByteEnd - runByteStart;\n        if (runByteLen <= 0) continue;\n\n        int hasVisibleChars = 0;\n        for (int ci = runStart; ci < runStart + runLen; ci++) {\n            if (ucs4Chars[ci] >= 0x0020 || ucs4Chars[ci] == 0x0009 ||\n                ucs4Chars[ci] == 0x000A || ucs4Chars[ci] == 0x000D) {\n                hasVisibleChars = 1;\n                break;\n            }\n        }\n        if (!hasVisibleChars) continue;\n\n        int runFaceIndex = GetRunFaceIndex(fontPtr, ucs4Chars, runStart, runLen);\n\n        /* Lazy load HarfBuzz fonts if needed. */\n        if (shaper->numFonts == 0) {\n            for (int fi = 0; fi < fontPtr->nfaces && shaper->numFonts < MAX_FONTS; fi++) {\n                FcPattern *facePattern = fontPtr->faces[fi].source;\n                FcChar8 *fontFile = NULL;\n                int fontIndex = 0;\n                if (FcPatternGetString(facePattern, FC_FILE, 0, &fontFile) != FcResultMatch) continue;\n                FcPatternGetInteger(facePattern, FC_INDEX, 0, &fontIndex);\n\n                hb_blob_t *blob = hb_blob_create_from_file_or_fail((const char *)fontFile);\n                if (!blob) continue;\n                hb_face_t *face = hb_face_create(blob, fontIndex);\n                if (!face) { hb_blob_destroy(blob); continue; }\n                hb_font_t *font = hb_font_create(face);\n                if (!font) { hb_face_destroy(face); hb_blob_destroy(blob); continue; }\n\n                XftFont *xftFont = GetFaceFont(fontPtr, fi, 0.0);\n                if (xftFont) {\n                    int pixelSize = 12;\n                    if (XftPatternGetInteger(xftFont->pattern, XFT_PIXEL_SIZE, 0, &pixelSize) != XftResultMatch) {\n                        double ptSize = 12.0;\n                        XftPatternGetDouble(xftFont->pattern, XFT_SIZE, 0, &ptSize);\n                        pixelSize = (int)(ptSize * 96.0 / 72.0 + 0.5);\n                    }\n                    hb_font_set_scale(font, pixelSize * 64, pixelSize * 64);\n                }\n\n                shaper->fontMap[shaper->numFonts].hbFont = font;\n                shaper->fontMap[shaper->numFonts].faceIndex = fi;\n                fontPtr->faces[fi].hbFont = font;\n                fontPtr->faces[fi].hbBlob = blob;\n                fontPtr->faces[fi].hbFace = face;\n                fontPtr->faces[fi].isLoaded = 1;\n                shaper->numFonts++;\n            }\n        }\n\n        hb_buffer_clear_contents(shaper->buffer);\n        hb_buffer_add_utf8(shaper->buffer, source + runByteStart, runByteLen, 0, runByteLen);\n        hb_buffer_set_direction(shaper->buffer, runIsRTL ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);\n        hb_buffer_set_cluster_level(shaper->buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);\n\n        hb_font_t *runHbFont = NULL;\n        int shapeFaceIndex = runFaceIndex;\n        if (shapeFaceIndex < fontPtr->nfaces && fontPtr->faces[shapeFaceIndex].isLoaded)\n            runHbFont = fontPtr->faces[shapeFaceIndex].hbFont;\n        else if (shaper->numFonts > 0) {\n            runHbFont = shaper->fontMap[0].hbFont;\n            shapeFaceIndex = shaper->fontMap[0].faceIndex;\n        }\n        if (!runHbFont) continue;\n\n        hb_shape(runHbFont, shaper->buffer, NULL, 0);\n\n        unsigned int glyphCount = hb_buffer_get_length(shaper->buffer);\n        hb_glyph_info_t *glyphInfo = hb_buffer_get_glyph_infos(shaper->buffer, NULL);\n        hb_glyph_position_t *glyphPos = hb_buffer_get_glyph_positions(shaper->buffer, NULL);\n        if (!glyphInfo || !glyphPos) continue;\n\n        /* Use temp buffer for safety and correct positioning. */\n        struct {\n            int fontIndex;\n            unsigned int glyphId;\n            int x, y;\n            int advanceX;\n            int byteOffset;\n            int clusterLen;\n        } tempGlyphs[MAX_GLYPHS];\n        int tempCount = 0;\n\n        int runPenX = 0;\n        for (unsigned int i = 0; i < glyphCount && tempCount < MAX_GLYPHS; i++) {\n            tempGlyphs[tempCount].fontIndex  = shapeFaceIndex;\n            tempGlyphs[tempCount].glyphId    = glyphInfo[i].codepoint;\n            tempGlyphs[tempCount].x          = globalPenX + runPenX + (int)(glyphPos[i].x_offset / 64.0 + 0.5);\n            tempGlyphs[tempCount].y          = -(int)(glyphPos[i].y_offset / 64.0 + 0.5);\n            tempGlyphs[tempCount].advanceX   = (int)(glyphPos[i].x_advance / 64.0 + 0.5);\n            tempGlyphs[tempCount].byteOffset = runByteStart + glyphInfo[i].cluster;\n\n            runPenX += tempGlyphs[tempCount].advanceX;\n            tempCount++;\n        }\n\n        /* Correct cluster lengths (handles RTL). */\n        for (int i = 0; i < tempCount; i++) {\n            int start = tempGlyphs[i].byteOffset;\n            int end = runByteEnd;\n            for (int j = i + 1; j < tempCount; j++) {\n                if (tempGlyphs[j].byteOffset > start) {\n                    end = tempGlyphs[j].byteOffset;\n                    break;\n                }\n            }\n            tempGlyphs[i].clusterLen = end - start;\n            if (tempGlyphs[i].clusterLen <= 0)\n                tempGlyphs[i].clusterLen = 1;\n        }\n\n        /* Copy to final buffer. */\n        for (int i = 0; i < tempCount; i++) {\n            int idx = buffer->glyphCount;\n            if (idx >= MAX_GLYPHS) break;\n\n            buffer->glyphs[idx].fontIndex  = tempGlyphs[i].fontIndex;\n            buffer->glyphs[idx].glyphId    = tempGlyphs[i].glyphId;\n            buffer->glyphs[idx].x          = tempGlyphs[i].x;\n            buffer->glyphs[idx].y          = tempGlyphs[i].y;\n            buffer->glyphs[idx].advanceX   = tempGlyphs[i].advanceX;\n            buffer->glyphs[idx].byteOffset = tempGlyphs[i].byteOffset;\n            buffer->glyphs[idx].clusterLen = tempGlyphs[i].clusterLen;\n            buffer->glyphs[idx].isRTL      = runIsRTL;\n\n            buffer->glyphCount++;\n        }\n\n        globalPenX += runPenX;\n    }\n\n    buffer->totalAdvance = globalPenX;\n\n    /* Visual index for cursor positioning. */\n    buffer->indexCount = buffer->glyphCount;\n    for (int i = 0; i < buffer->glyphCount; i++) {\n        buffer->visualIndex[i].x        = buffer->glyphs[i].x;\n        buffer->visualIndex[i].advanceX = buffer->glyphs[i].advanceX;\n        int byteEnd = buffer->glyphs[i].byteOffset + buffer->glyphs[i].clusterLen;\n        if (byteEnd < 0) byteEnd = 0;\n        if (byteEnd > numBytes) byteEnd = numBytes;\n        buffer->visualIndex[i].byteEnd = byteEnd;\n    }\n\n      /*\n     * Sort visualIndex by X coordinate (left-to-right screen order).\n     * This ensures cursor positioning works correctly for mixed BiDi text.\n     * Without this, the visualIndex is in run-emission order, causing\n     * cursor jumps when navigating between LTR and RTL runs.\n     */\n    for (int i = 0; i < buffer->indexCount - 1; i++) {\n        for (int j = i + 1; j < buffer->indexCount; j++) {\n            if (buffer->visualIndex[j].x < buffer->visualIndex[i].x) {\n                /* Swap visualIndex[i] and visualIndex[j] */\n                int temp_x = buffer->visualIndex[i].x;\n                int temp_advanceX = buffer->visualIndex[i].advanceX;\n                int temp_byteEnd = buffer->visualIndex[i].byteEnd;\n                \n                buffer->visualIndex[i].x = buffer->visualIndex[j].x;\n                buffer->visualIndex[i].advanceX = buffer->visualIndex[j].advanceX;\n                buffer->visualIndex[i].byteEnd = buffer->visualIndex[j].byteEnd;\n                \n                buffer->visualIndex[j].x = temp_x;\n                buffer->visualIndex[j].advanceX = temp_advanceX;\n                buffer->visualIndex[j].byteEnd = temp_byteEnd;\n            }\n        }\n    }\n    \n    /* Update cache. */\n    if (numBytes <= MAX_STRING_CACHE) {\n        shaper->cache.valid = 0;\n        memcpy(shaper->cache.text, source, numBytes);\n        shaper->cache.len = numBytes;\n        shaper->cache.buffer = *buffer;\n        shaper->cache.valid = 1;\n    }\n\n    if (needFree) {\n        free(charBounds);\n        free(ucs4Chars);\n    }\n\n    return 1;\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpFontPkgInit --\n *\n *   This procedure is called when an application is created. It\n *   initializes all the structures that are used by the\n *   platform-dependant code on a per application basis.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpFontPkgInit(\n    TCL_UNUSED(TkMainInfo *))\t/* The application being created. */\n{\n    /* Nothing to initialize. */\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpGetNativeFont --\n *\n *   Create a Tk font from a platform-specific font name (XLFD).\n *\n * Results:\n *   Returns a pointer to a TkFont, or NULL on failure.\n *\n * Side effects:\n *   Allocates font resources.\n * ---------------------------------------------------------------\n */\n\nTkFont *\nTkpGetNativeFont(\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const char *name)\t\t/* Platform-specific font name. */\n{\n\n    FcPattern *pattern = XftXlfdParse(name, FcFalse, FcFalse);\n    if (!pattern) {\n        return NULL;\n    }\n\n    UnixFtFont *fontPtr = InitFont(tkwin, pattern, NULL);\n    if (!fontPtr) {\n        FcPatternDestroy(pattern);\n        return NULL;\n    }\n\n    return &fontPtr->font;\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpGetFontFromAttributes --\n *\n *   Create a Tk font matching the given attributes.\n *\n * Results:\n *   Returns a pointer to a TkFont, or NULL on failure.\n *\n * Side effects:\n *   Allocates font resources; may reuse an existing font structure.\n * ---------------------------------------------------------------\n */\n\nTkFont *\nTkpGetFontFromAttributes(\n\t\t\t TkFont *tkFontPtr,\n\t\t\t Tk_Window tkwin,\n\t\t\t const TkFontAttributes *faPtr)\n{\n    XftPattern *pattern = XftPatternCreate();\n    const char *family = faPtr->family;\n\n    if (!family || family[0] == '\\0') {\n        family = \"sans-serif\";\n    }\n\n    /* Force Fontconfig to treat this as a preferred family. */\n    XftPatternAddString(pattern, XFT_FAMILY, family);\n\n    /* Explicitly tell Xft we want a sans-serif style if the family is generic. */\n    if (strcmp(family, \"sans-serif\") == 0) {\n        XftPatternAddInteger(pattern, XFT_SPACING, XFT_PROPORTIONAL);\n        XftPatternAddString(pattern, FC_STYLE, \"Regular\");\n    }\n\n    double size = (faPtr->size > 0.0) ? faPtr->size :\n                 ((faPtr->size < 0.0) ? TkFontGetPoints(tkwin, faPtr->size) : 12.0);\n    XftPatternAddDouble(pattern, XFT_SIZE, size);\n\n    int weight = (faPtr->weight == TK_FW_BOLD) ? XFT_WEIGHT_BOLD : XFT_WEIGHT_MEDIUM;\n    XftPatternAddInteger(pattern, XFT_WEIGHT, weight);\n\n    int slant = (faPtr->slant == TK_FS_ROMAN) ? XFT_SLANT_ROMAN : XFT_SLANT_ITALIC;\n    XftPatternAddInteger(pattern, XFT_SLANT, slant);\n\n    /* Perform system substitution. */\n    XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern);\n    FcConfigSubstitute(NULL, pattern, FcMatchPattern);\n\n    UnixFtFont *fontPtr = (UnixFtFont *)tkFontPtr;\n    fontPtr = InitFont(tkwin, pattern, fontPtr);\n\n    if (!fontPtr) {\n        /* Emergency Fallback: If \"sans-serif\" failed, try \"sans.\" */\n        XftPatternDestroy(pattern);\n        pattern = XftPatternBuild(NULL, XFT_FAMILY, XftTypeString, \"sans\",\n                                  XFT_SIZE, XftTypeDouble, size, NULL);\n        fontPtr = InitFont(tkwin, pattern, (UnixFtFont *)tkFontPtr);\n    }\n\n    return (TkFont *)fontPtr;\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpDeleteFont --\n *\n *   Release all resources associated with a font.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Font data is freed.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpDeleteFont(\n    TkFont *tkFontPtr)\t\t/* Token of font to be deleted. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkFontPtr;\n    FinishedWithFont(fontPtr);\n    /* Note: tkFontPtr itself is freed by generic code. */\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpGetFontFamilies --\n *\n *   Return information about the font families that are available on the\n *   display of the given window.\n *\n * Results:\n *   Modifies interp's result object to hold a list of all the available\n *   font families.\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpGetFontFamilies(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Window tkwin)\t\t/* For display to query. */\n{\n    Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);\n    XftFontSet *list = XftListFonts(Tk_Display(tkwin), Tk_ScreenNumber(tkwin),\n                                    NULL, XFT_FAMILY, NULL);\n\n    for (int i = 0; i < list->nfont; i++) {\n        char *family, **familyPtr = &family;\n        if (XftPatternGetString(list->fonts[i], XFT_FAMILY, 0, familyPtr) == XftResultMatch) {\n            Tcl_ListObjAppendElement(NULL, resultPtr,\n                                     Tcl_NewStringObj(family, TCL_INDEX_NONE));\n        }\n    }\n\n    XftFontSetDestroy(list);\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpGetSubFonts --\n *\n *   Called by [testfont subfonts] in the Tk testing package.\n *\n * Results:\n *   Sets interp's result to a list of the faces used by tkfont.\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpGetSubFonts(\n    Tcl_Interp *interp,\n    Tk_Font tkfont)\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n    Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);\n\n    for (int i = 0; i < fontPtr->nfaces; i++) {\n        FcPattern *pat = FcFontRenderPrepare(NULL, fontPtr->pattern,\n                                             fontPtr->faces[i].source);\n        const char *family  = \"Unknown\";\n        const char *const *familyPtr  = &family;\n        const char *foundry = \"Unknown\";\n        const char *const *foundryPtr = &foundry;\n\n        XftPatternGetString(pat, XFT_FAMILY,  0, familyPtr);\n        XftPatternGetString(pat, XFT_FOUNDRY, 0, foundryPtr);\n\n        Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);\n        Tcl_ListObjAppendElement(NULL, listObj,\n                                 Tcl_NewStringObj(family,  TCL_INDEX_NONE));\n        Tcl_ListObjAppendElement(NULL, listObj,\n                                 Tcl_NewStringObj(foundry, TCL_INDEX_NONE));\n        Tcl_ListObjAppendElement(NULL, resultPtr, listObj);\n\n        FcPatternDestroy(pat);\n    }\n\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpGetFontAttrsForChar --\n *\n *   Retrieve the font attributes of the actual font used to render a given\n *   character.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   The TkFontAttributes structure is filled.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpGetFontAttrsForChar(\n    Tk_Window tkwin,\t\t/* Window on the font's display. */\n    Tk_Font tkfont,\t\t/* Font to query. */\n    int c,\t\t\t/* Character of interest. */\n    TkFontAttributes *faPtr)\t/* Output: Font attributes. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n    XftFont *ftFont = GetFont(fontPtr, (FcChar32)c, 0.0);\n\n    if (ftFont) {\n        GetTkFontAttributes(tkwin, ftFont, faPtr);\n    } else {\n        *faPtr = fontPtr->font.fa;\n    }\n\n    faPtr->underline   = fontPtr->font.fa.underline;\n    faPtr->overstrike  = fontPtr->font.fa.overstrike;\n}\n\n/*\n * ---------------------------------------------------------------\n * Tk_MeasureChars --\n *\n *   Measure the width of a string when drawn in the given font.\n *\n *   FIX: Track minimum and maximum logical byte boundaries to ensure\n *   returned byte counts are monotonically increasing as maxLength increases.\n *   This prevents infinite loops in the text widget's cursor-position search.\n *\n * Results:\n *   Returns number of bytes consumed; *lengthPtr filled with pixel width.\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nint\nTk_MeasureChars(\n\tTk_Font tkfont,\n\tconst char *source,\n\tTcl_Size numBytes,\n\tint maxLength,\n\tint flags,\n\tint *lengthPtr)\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n\n    /*\n     * Fast path for Latin-only strings (ASCII through Latin Extended-B,\n     * U+0000-U+024F).  XftTextExtentsUtf8 handles the full UTF-8 encoding\n     * of these codepoints correctly with a single font face.\n     *\n     * IMPORTANT: check only the bytes we are asked to measure, not any\n     * larger surrounding buffer.  The caller may pass a slice of a\n     * mixed-script string whose other portions contain non-Latin text.\n     */\n    if (IsLatinOnly(source, (int)numBytes)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, 0.0);\n        if (!ftFont) {\n            *lengthPtr = 0;\n            return 0;\n        }\n\n        /* Total width of the entire string. */\n        XGlyphInfo extents;\n        XftTextExtentsUtf8(fontPtr->display, ftFont,\n                           (const FcChar8 *)source, (int)numBytes, &extents);\n        int totalWidth = extents.xOff;\n\n        if (maxLength < 0) {\n            *lengthPtr = totalWidth;\n            return (int)numBytes;\n        }\n\n        /*\n         * Linear scan for the longest prefix that fits, advancing one\n         * full codepoint at a time.\n         *\n         * A binary search on raw byte offsets is incorrect for multi-byte\n         * UTF-8: the midpoint can land inside a sequence, making\n         * XftTextExtentsUtf8 measure a truncated, invalid sequence.\n         */\n        int best = 0, bestWidth = 0;\n        int pos = 0;\n        while (pos < (int)numBytes) {\n            FcChar32 uc;\n            int clen = FcUtf8ToUcs4((const FcChar8 *)(source + pos), &uc,\n                                    (int)numBytes - pos);\n            if (clen <= 0) clen = 1;  /* skip invalid byte */\n            int next = pos + clen;\n\n            XftTextExtentsUtf8(fontPtr->display, ftFont,\n                               (const FcChar8 *)source, next, &extents);\n            if (extents.xOff > maxLength) break;\n\n            best = next;\n            bestWidth = extents.xOff;\n            pos = next;\n        }\n\n        /* Whole-word break if requested. */\n        if ((flags & TK_WHOLE_WORDS) && best < (int)numBytes) {\n            int spacePos = -1;\n            for (int i = 0; i < best; i++) {\n                if (source[i] == ' ' || source[i] == '\\t')\n                    spacePos = i;\n            }\n            if (spacePos >= 0) {\n                best = spacePos + 1;\n                XftTextExtentsUtf8(fontPtr->display, ftFont,\n                                   (const FcChar8 *)source, best, &extents);\n                bestWidth = extents.xOff;\n            }\n        }\n\n        /* At least one full codepoint if requested and nothing fit yet. */\n        if ((flags & TK_AT_LEAST_ONE) && best == 0 && (int)numBytes > 0) {\n            FcChar32 uc;\n            int clen = FcUtf8ToUcs4((const FcChar8 *)source, &uc, (int)numBytes);\n            if (clen <= 0) clen = 1;\n            best = clen;\n            XftTextExtentsUtf8(fontPtr->display, ftFont,\n                               (const FcChar8 *)source, best, &extents);\n            bestWidth = extents.xOff;\n        }\n\n        *lengthPtr = bestWidth;\n        return best;\n    }\n\n    /* Shaping path for non-Latin. */\n    ShapedGlyphBuffer buffer;\n    if (!X11Shaper_ShapeString(&fontPtr->shaper, fontPtr, source, (int)numBytes, &buffer)) {\n        *lengthPtr = 0;\n        return (int)numBytes;\n    }\n\n    int curX = 0;\n    int lastBreakByte = 0;\n    int lastBreakX = 0;\n\n    /*\n     * Cursor positioning with visual index:\n     * \n     * The visualIndex maps visual (screen) positions to logical (source) byte\n     * offsets, enabling accurate cursor positioning for all text directions.\n     */\n    int prevByteEnd = 0;\n    \n    for (int i = 0; i < buffer.indexCount; i++) {\n        int glyphX = buffer.visualIndex[i].x;\n        int glyphAdvance = buffer.visualIndex[i].advanceX;\n        int glyphXEnd = glyphX + glyphAdvance;\n        int byteEnd = buffer.visualIndex[i].byteEnd;\n        \n        if (byteEnd < 0) byteEnd = 0;\n        if (byteEnd > (int)numBytes) byteEnd = (int)numBytes;\n\n        /* Record word-break opportunities based on source character. */\n        if (byteEnd > 0 && byteEnd <= (int)numBytes) {\n            if (source[byteEnd - 1] == ' ' || source[byteEnd - 1] == '\\t') {\n                lastBreakByte = byteEnd;\n                lastBreakX = glyphXEnd;\n            }\n        }\n\n        if (maxLength >= 0 && glyphXEnd > maxLength) {\n            if (lastBreakByte > 0 && (flags & TK_WHOLE_WORDS)) {\n                *lengthPtr = lastBreakX;\n                return lastBreakByte;\n            }\n            \n            /* Ensure we return at least one character if TK_AT_LEAST_ONE is set. */\n            if (prevByteEnd == 0 && (flags & TK_AT_LEAST_ONE)) {\n                *lengthPtr = glyphXEnd;\n                return byteEnd;\n            }\n            \n            *lengthPtr = curX;\n            return prevByteEnd;\n        }\n\n        curX = glyphXEnd;\n        prevByteEnd = byteEnd;\n    }\n\n    /* All glyphs fit - return total. */\n    if (prevByteEnd == 0 && (int)numBytes > 0) {\n        prevByteEnd = (int)numBytes;\n    }\n\n    *lengthPtr = (maxLength < 0) ? buffer.totalAdvance : curX;\n    return prevByteEnd;\n}\n\n/*\n * ---------------------------------------------------------------\n * Tk_MeasureCharsInContext --\n *\n *   Measure a substring of a larger string, preserving shaping context.\n *\n *   Shapes the FULL string and extracts metrics for the\n *   requested range. This preserves ligatures, kerning, and BiDi\n *   analysis across substring boundaries.\n *\n * Results:\n *   Returns number of bytes consumed; *lengthPtr filled with pixel width.\n *\n * Side effects:\n *   None.\n * ---------------------------------------------------------------\n */\n\nint\nTk_MeasureCharsInContext(\n    Tk_Font tkfont,\n    const char *source,\n    Tcl_Size numBytes,\n    Tcl_Size rangeStart,\n    Tcl_Size rangeLength,\n    int maxLength,\n    int flags,\n    int *lengthPtr)\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n\n    /*\n     * Fast path for Latin-only strings (U+0000-U+024F).\n     *\n     * Check only the substring [rangeStart, rangeStart+rangeLength).\n     */\n    if (IsLatinOnly(source + rangeStart, (int)rangeLength)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, 0.0);\n        if (!ftFont) {\n            *lengthPtr = 0;\n            return 0;\n        }\n\n        const char *sub = source + rangeStart;\n        int subLen = (int)rangeLength;\n\n        XGlyphInfo extents;\n        XftTextExtentsUtf8(fontPtr->display, ftFont,\n                           (const FcChar8 *)sub, subLen, &extents);\n        int totalWidth = extents.xOff;\n\n        if (maxLength < 0) {\n            *lengthPtr = totalWidth;\n            return subLen;\n        }\n\n        /*\n         * Linear codepoint scan — same reasoning as Tk_MeasureChars above.\n         */\n        int best = 0, bestWidth = 0;\n        int pos = 0;\n        while (pos < subLen) {\n            FcChar32 uc;\n            int clen = FcUtf8ToUcs4((const FcChar8 *)(sub + pos), &uc,\n                                    subLen - pos);\n            if (clen <= 0) clen = 1;\n            int next = pos + clen;\n\n            XftTextExtentsUtf8(fontPtr->display, ftFont,\n                               (const FcChar8 *)sub, next, &extents);\n            if (extents.xOff > maxLength) break;\n\n            best = next;\n            bestWidth = extents.xOff;\n            pos = next;\n        }\n\n        /* Whole-word break if requested (within substring). */\n        if ((flags & TK_WHOLE_WORDS) && best < subLen) {\n            int spacePos = -1;\n            for (int i = 0; i < best; i++) {\n                if (sub[i] == ' ' || sub[i] == '\\t')\n                    spacePos = i;\n            }\n            if (spacePos >= 0) {\n                best = spacePos + 1;\n                XftTextExtentsUtf8(fontPtr->display, ftFont,\n                                   (const FcChar8 *)sub, best, &extents);\n                bestWidth = extents.xOff;\n            }\n        }\n\n        /* At least one full codepoint if requested. */\n        if ((flags & TK_AT_LEAST_ONE) && best == 0 && subLen > 0) {\n            FcChar32 uc;\n            int clen = FcUtf8ToUcs4((const FcChar8 *)sub, &uc, subLen);\n            if (clen <= 0) clen = 1;\n            best = clen;\n            XftTextExtentsUtf8(fontPtr->display, ftFont,\n                               (const FcChar8 *)sub, best, &extents);\n            bestWidth = extents.xOff;\n        }\n\n        *lengthPtr = bestWidth;\n        return best;\n    }\n\n    /* Shaping path for non-Latin. */\n    ShapedGlyphBuffer buffer;\n    if (!X11Shaper_ShapeString(&fontPtr->shaper, fontPtr, source,\n                                (int)numBytes, &buffer)) {\n        *lengthPtr = 0;\n        return (int)rangeLength;\n    }\n\n    int totalWidth = 0;\n    int rangeEnd = (int)(rangeStart + rangeLength);\n    int lastBreakPos = (int)rangeStart;\n    int lastBreakWidth = 0;\n    int lastBreakGlyph = -1;\n    int bytesConsumed = (int)rangeStart;\n\n    /*\n     * Cursor positioning in range with visual index.\n     */\n    for (int i = 0; i < buffer.indexCount; i++) {\n        int glyphAdvance = buffer.visualIndex[i].advanceX;\n        int byteEnd = buffer.visualIndex[i].byteEnd;\n\n        if (byteEnd < 0) byteEnd = 0;\n        if (byteEnd > (int)numBytes) byteEnd = (int)numBytes;\n\n        /* Skip glyphs outside the range. */\n        if (byteEnd <= (int)rangeStart || \n            (i == 0 && buffer.glyphs[i].byteOffset >= rangeEnd)) {\n            continue;\n        }\n\n        int nextWidth = totalWidth + glyphAdvance;\n\n        /* Record word-break opportunities. */\n        if (byteEnd > 0 && byteEnd <= (int)numBytes) {\n            if (source[byteEnd - 1] == ' ' || \n                source[byteEnd - 1] == '\\t' || \n                source[byteEnd - 1] == '\\n') {\n                lastBreakPos   = byteEnd;\n                lastBreakWidth = nextWidth;\n                lastBreakGlyph = i;\n            }\n        }\n\n        if (maxLength >= 0 && nextWidth > maxLength) {\n            if (lastBreakGlyph >= 0 && (flags & TK_WHOLE_WORDS)) {\n                totalWidth = lastBreakWidth;\n                bytesConsumed = lastBreakPos;\n            } else if (bytesConsumed == (int)rangeStart) {\n                /* Nothing consumed yet - include this glyph. */\n                totalWidth = nextWidth;\n                bytesConsumed = byteEnd;\n            }\n            break;\n        }\n\n        totalWidth = nextWidth;\n        if (byteEnd > bytesConsumed) {\n            bytesConsumed = byteEnd;\n        }\n    }\n\n    if (bytesConsumed < (int)rangeStart) bytesConsumed = (int)rangeStart;\n    if (bytesConsumed > rangeEnd) bytesConsumed = rangeEnd;\n\n    /* If we consumed nothing and the range is non-empty, skip to end. */\n    if (bytesConsumed == (int)rangeStart && rangeLength > 0) {\n        bytesConsumed = rangeEnd;\n    }\n\n    *lengthPtr = totalWidth;\n    return (bytesConsumed - (int)rangeStart);\n}\n\n/*\n * ---------------------------------------------------------------\n * Tk_DrawChars --\n *\n *   Draw a UTF-8 string using the given font.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Draws text on the specified drawable.\n * ---------------------------------------------------------------\n */\n\nvoid\nTk_DrawChars(\n    Display *display,      /* Display on which to draw. */\n    Drawable drawable,     /* Window or pixmap in which to draw. */\n    GC gc,                 /* Graphics context for drawing characters. */\n    Tk_Font tkfont,        /* Font in which characters will be drawn. */\n    const char *source,    /* UTF-8 string to be displayed. */\n    Tcl_Size numBytes,     /* Number of bytes in string. */\n    int x, int y)          /* Coordinates at which to place origin. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    XftDraw *ftDraw = NULL;\n\n    if (numBytes <= 0) return;\n\n    /* Create a temporary XftDraw for this draw operation. */\n    ftDraw = XftDrawCreate(display, drawable,\n                          fontPtr->visual, fontPtr->colormap);\n    if (!ftDraw) return;\n\n    XGCValues values;\n    XGetGCValues(display, gc, GCForeground, &values);\n    XftColor *xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (!xftcolor) {\n        XftDrawDestroy(ftDraw);\n        return;\n    }\n\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, tsdPtr->clipRegion);\n    }\n\n    /*\n     * Fast path for Latin-only strings (U+0000-U+024F).\n     * Check only the bytes being drawn, not any larger buffer.\n     */\n    if (IsLatinOnly(source, (int)numBytes)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, 0.0);\n        if (ftFont) {\n            XftDrawStringUtf8(ftDraw, xftcolor, ftFont,\n                              x, y, (const FcChar8 *)source, (int)numBytes);\n        }\n        goto done;\n    }\n\n    /* Full shaping path. */\n    {\n        ShapedGlyphBuffer buffer;\n        if (!X11Shaper_ShapeString(&fontPtr->shaper, fontPtr, source,\n                                    (int)numBytes, &buffer)) {\n            goto done;\n        }\n\n        XftGlyphFontSpec specs[MAX_GLYPHS];\n        int nspec = 0;\n\n        for (int i = 0; i < buffer.glyphCount && nspec < MAX_GLYPHS; i++) {\n            int faceIdx = buffer.glyphs[i].fontIndex;\n            if (faceIdx < 0 || faceIdx >= fontPtr->nfaces) faceIdx = 0;\n\n            XftFont *ftFont = GetFaceFont(fontPtr, faceIdx, 0.0);\n            if (!ftFont) continue;\n\n            unsigned int actualGlyph = buffer.glyphs[i].glyphId;\n\n            /* Fallback logic for missing glyphs in primary font. */\n            if (actualGlyph == 0) {\n                FcChar32 ucs4 = 0;\n                int byteOff = buffer.glyphs[i].byteOffset;\n                if (byteOff >= 0 && byteOff < (int)numBytes) {\n                    FcUtf8ToUcs4((const FcChar8 *)(source + byteOff), &ucs4,\n                                 (int)numBytes - byteOff);\n                }\n\n                if (ucs4 != 0) {\n                    XftFont *fallbackFont = GetFont(fontPtr, ucs4, 0.0);\n                    if (fallbackFont) {\n                        actualGlyph = XftCharIndex(display, fallbackFont, ucs4);\n                        if (actualGlyph != 0) ftFont = fallbackFont;\n                    }\n                }\n                if (actualGlyph == 0) continue;\n            }\n\n            specs[nspec].font  = ftFont;\n            specs[nspec].glyph = actualGlyph;\n            specs[nspec].x     = x + (int)buffer.glyphs[i].x;\n            specs[nspec].y     = y + (int)buffer.glyphs[i].y;\n            nspec++;\n        }\n\n        if (nspec > 0) {\n            LOCK;\n            XftDrawGlyphFontSpec(ftDraw, xftcolor, specs, nspec);\n            UNLOCK;\n        }\n    }\n\ndone:\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, NULL);\n    }\n    \n    /* Always destroy the temporary XftDraw. */\n    XftDrawDestroy(ftDraw);\n}\n\n/*\n * ---------------------------------------------------------------\n * Tk_DrawCharsInContext --\n *\n *   Draws a substring of text using full shaping + bidi logic,\n *   preserving context from surrounding text for proper ligatures\n *   and BiDi reordering.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Draws the specified range of characters.\n * ---------------------------------------------------------------\n */\n\nvoid\nTk_DrawCharsInContext(\n    Display *display,\n    Drawable drawable,\n    GC gc,\n    Tk_Font tkfont,\n    const char *source,\n    Tcl_Size numBytes,        /* Total bytes in source string. */\n    Tcl_Size rangeStart,      /* Byte offset of substring start. */\n    Tcl_Size rangeLength,     /* Byte length of substring. */\n    int x, int y)              /* Coordinates at which to place origin. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (rangeLength <= 0) return;\n    \n    XftDraw *ftDraw = NULL;\n\n    /* Create a temporary XftDraw for this draw operation. */\n    ftDraw = XftDrawCreate(display, drawable,\n                          fontPtr->visual, fontPtr->colormap);\n    if (!ftDraw) return;\n\n    XGCValues values;\n    XGetGCValues(display, gc, GCForeground, &values);\n    XftColor *xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (!xftcolor) return;\n\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, tsdPtr->clipRegion);\n    }\n\n    /*\n     * Fast path for Latin-only strings (U+0000-U+024F).\n     * Check only the substring being drawn.\n     */\n    if (IsLatinOnly(source + rangeStart, (int)rangeLength)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, 0.0);\n        if (ftFont) {\n            XftDrawStringUtf8(ftDraw, xftcolor, ftFont,\n                              x, y,\n                              (const FcChar8 *)(source + rangeStart),\n                              (int)rangeLength);\n        }\n        goto done;\n    }\n\n    /* Shape the FULL string to preserve context for ligatures and BiDi. */\n    ShapedGlyphBuffer fullBuffer;\n    if (!X11Shaper_ShapeString(&fontPtr->shaper, fontPtr, source,\n                                (int)numBytes, &fullBuffer)) {\n        goto done;\n    }\n\n    /* Find the glyphs that overlap our requested range. */\n    XftGlyphFontSpec specs[MAX_GLYPHS];\n    int nspec = 0;\n    int rangeEnd = rangeStart + rangeLength;\n    int firstGlyphFound = 0;\n\n    /*\n     * Find the X position of the first glyph that starts\n     * at or after rangeStart.\n     */\n    int rangeStartX = 0;\n    int rangeStartFound = 0;\n\n    for (int i = 0; i < fullBuffer.glyphCount; i++) {\n        int glyphStart = fullBuffer.glyphs[i].byteOffset;\n        int glyphEnd = glyphStart + fullBuffer.glyphs[i].clusterLen;\n\n        if (glyphEnd <= rangeStart) {\n            /* Glyph is entirely before our range. */\n            continue;\n        }\n\n        if (!rangeStartFound) {\n            /* This is the first glyph that overlaps our range. */\n            rangeStartX = fullBuffer.glyphs[i].x;\n            rangeStartFound = 1;\n            break;\n        }\n    }\n\n    /* Second pass: Draw the glyphs that overlap our range. */\n    for (int i = 0; i < fullBuffer.glyphCount && nspec < MAX_GLYPHS; i++) {\n        int glyphStart = fullBuffer.glyphs[i].byteOffset;\n        int glyphEnd = glyphStart + fullBuffer.glyphs[i].clusterLen;\n\n        /* Skip glyphs entirely before our range. */\n        if (glyphEnd <= rangeStart) {\n            continue;\n        }\n\n        /* Stop when we've passed our range. */\n        if (glyphStart >= rangeEnd) {\n            break;\n        }\n\n        /* This glyph overlaps our range - draw it. */\n        int faceIdx = fullBuffer.glyphs[i].fontIndex;\n        if (faceIdx < 0 || faceIdx >= fontPtr->nfaces) faceIdx = 0;\n\n        XftFont *ftFont = GetFaceFont(fontPtr, faceIdx, 0.0);\n        if (!ftFont) continue;\n\n        unsigned int actualGlyph = fullBuffer.glyphs[i].glyphId;\n\n        /* Fallback logic for missing glyphs in primary font. */\n        if (actualGlyph == 0) {\n            FcChar32 ucs4 = 0;\n            int byteOff = fullBuffer.glyphs[i].byteOffset;\n            if (byteOff >= 0 && byteOff < (int)numBytes) {\n                FcUtf8ToUcs4((const FcChar8 *)(source + byteOff), &ucs4,\n                             (int)numBytes - byteOff);\n            }\n\n            if (ucs4 != 0) {\n                XftFont *fallbackFont = GetFont(fontPtr, ucs4, 0.0);\n                if (fallbackFont) {\n                    actualGlyph = XftCharIndex(display, fallbackFont, ucs4);\n                    if (actualGlyph != 0) ftFont = fallbackFont;\n                }\n            }\n            if (actualGlyph == 0) continue;\n        }\n\n        /*\n\t * Calculate screen position: baseX + (glyph X - rangeStartX).\n\t */\n        int glyphScreenX = x + (fullBuffer.glyphs[i].x - rangeStartX);\n\n        specs[nspec].font  = ftFont;\n        specs[nspec].glyph = actualGlyph;\n        specs[nspec].x     = glyphScreenX;\n        specs[nspec].y     = y + (int)fullBuffer.glyphs[i].y;\n        nspec++;\n\n        if (!firstGlyphFound) {\n            firstGlyphFound = 1;\n        }\n    }\n\n    /* Draw the glyphs. */\n    if (nspec > 0) {\n        LOCK;\n        XftDrawGlyphFontSpec(ftDraw, xftcolor, specs, nspec);\n        UNLOCK;\n    }\n\ndone:\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, NULL);\n    }\n    XftDrawDestroy(ftDraw);\n}\n\n/*\n * ---------------------------------------------------------------\n * TkDrawAngledChars --\n *\n *   Draw some characters at an angle.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Draws rotated text.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkDrawAngledChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    double x, double y,\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *)tkfont;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (numBytes == 0) return;\n\n    /* Create XftDraw context. */\n    XftDraw *ftDraw = XftDrawCreate(display, drawable,\n                                     fontPtr->visual, fontPtr->colormap);\n    if (!ftDraw) return;\n\n    /* Get foreground color. */\n    XGCValues values;\n    XGetGCValues(display, gc, GCForeground, &values);\n    XftColor *xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (!xftcolor) {\n        XftDrawDestroy(ftDraw);\n        return;\n    }\n\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, tsdPtr->clipRegion);\n    }\n\n    /*\n     * Fast path for Latin-only strings: use XftDrawStringUtf8 directly\n     * with a rotated font.\n     */\n    if (IsLatinOnly(source, (int)numBytes)) {\n        XftFont *ftFont = GetFaceFont(fontPtr, 0, angle);\n        if (ftFont) {\n            XftDrawStringUtf8(ftDraw, xftcolor, ftFont,\n                              (int)x, (int)y,\n                              (const FcChar8 *)source, (int)numBytes);\n        }\n        goto done;\n    }\n    \n/*\n * Complex text: use full shaping + bidi pipeline,\n * then rotate glyph positions.\n */\n    \n{\n    ShapedGlyphBuffer buffer;\n    if (!X11Shaper_ShapeString(&fontPtr->shaper, fontPtr, source,\n                                (int)numBytes, &buffer)) {\n        goto done;\n    }\n\n    /* Rotation setup. */\n    double radians = angle * (M_PI / 180.0);\n    double cosA = cos(radians);\n    double sinA = sin(radians);\n\n    XftGlyphFontSpec specs[MAX_GLYPHS];\n    int nspec = 0;\n\n    for (int i = 0; i < buffer.glyphCount && nspec < MAX_GLYPHS; i++) {\n        int faceIdx = buffer.glyphs[i].fontIndex;\n        if (faceIdx < 0 || faceIdx >= fontPtr->nfaces) faceIdx = 0;\n\n        XftFont *ftFont = GetFaceFont(fontPtr, faceIdx, angle);\n        if (!ftFont) continue;\n\n        unsigned int glyph = buffer.glyphs[i].glyphId;\n        if (glyph == 0) continue;\n\n        /* Original (unrotated) glyph position. */\n        double gx = buffer.glyphs[i].x;\n        double gy = buffer.glyphs[i].y;\n\n        /*\n         * Rotate around (0,0), then translate to (x,y).\n         * Y is inverted for X11 coordinates.\n         */\n        double rx = gx * cosA - gy * sinA;\n        double ry = gx * sinA + gy * cosA;\n\n        specs[nspec].font  = ftFont;\n        specs[nspec].glyph = glyph;\n        specs[nspec].x     = (int)(x + rx);\n        specs[nspec].y     = (int)(y - ry);\n        nspec++;\n    }\n\n    if (nspec > 0) {\n        LOCK;\n        XftDrawGlyphFontSpec(ftDraw, xftcolor, specs, nspec);\n        UNLOCK;\n    }\n}\n    \ndone:\n    if (tsdPtr->clipRegion) {\n        XftDrawSetClip(ftDraw, NULL);\n    }\n    XftDrawDestroy(ftDraw);\n}\n\n/*\n * ---------------------------------------------------------------\n * TkpDrawAngledCharsInContext --\n *\n *   Draw a substring of rotated text.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Draws rotated characters.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkpDrawAngledCharsInContext(\n    Display *display,\n    Drawable drawable,\n    GC gc,\n    Tk_Font tkfont,\n    const char *source,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Size rangeStart,\n    Tcl_Size rangeLength,\n    double x, double y,\n    double angle)\n{\n    TkDrawAngledChars(display, drawable, gc, tkfont,\n                      source + rangeStart, rangeLength, x, y, angle);\n}\n\n/*\n * ---------------------------------------------------------------\n * TkUnixSetXftClipRegion --\n *\n *   Set the clipping region for subsequent Xft drawing.\n *\n * Results:\n *   None.\n *\n * Side effects:\n *   Updates thread-local clipping region.\n * ---------------------------------------------------------------\n */\n\nvoid\nTkUnixSetXftClipRegion(\n    Region clipRegion)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    tsdPtr->clipRegion = clipRegion;\n}\n\n/*\n * Local Variables:\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixButton.c",
    "content": "/*\n * tkUnixButton.c --\n *\n *\tThis file implements the Unix specific portion of the button widgets.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkButton.h\"\n#include \"tk3d.h\"\n\n/*\n * Shared with menu widget.\n */\n\nMODULE_SCOPE void\tTkpDrawCheckIndicator(Tk_Window tkwin,\n\t\t\t    Display *display, Drawable d, int x, int y,\n\t\t\t    Tk_3DBorder bgBorder, XColor *indicatorColor,\n\t\t\t    XColor *selectColor, XColor *disColor, int on,\n\t\t\t    int disabled, int mode);\n\n/*\n * Declaration of Unix specific button structure.\n */\n\ntypedef struct UnixButton {\n    TkButton info;\t\t/* Generic button info. */\n} UnixButton;\n\n/*\n * The class function table for the button widgets.\n */\n\nconst Tk_ClassProcs tkpButtonProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TkButtonWorldChanged,\t/* worldChangedProc */\n    NULL,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n/*\n * Indicator draw modes\n */\n\n#define CHECK_BUTTON 0\n#define CHECK_MENU   1\n#define RADIO_BUTTON 2\n#define RADIO_MENU   3\n\n/*\n * Indicator sizes\n */\n\n#define CHECK_BUTTON_DIM 16\n#define CHECK_MENU_DIM    8\n#define RADIO_BUTTON_DIM 16\n#define RADIO_MENU_DIM    8\n\n/*\n * Data of the SVG images used for drawing the indicators\n */\n\nstatic const char checkbtnOffData[] =\n    \"<svg id='checkbutton' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <path id='borderdark' d='m0 0v16l1-1v-14h14l1-1h-16z' fill='#DARKKK'/>\\n\"\n    \" <path id='borderlight' d='m16 0-1 1v14h-14l-1 1h16v-16z' fill='#LIGHTT'/>\\n\"\n    \" <rect id='rectbackdrop' x='2' y='2' width='12' height='12' fill='#INTROR'/>\\n\"\n    \"</svg>\";\n\nstatic const char checkbtnOnData[] =\n    \"<svg id='checkbutton' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <path id='borderdark' d='m0 0v16l1-1v-14h14l1-1h-16z' fill='#DARKKK'/>\\n\"\n    \" <path id='borderlight' d='m16 0-1 1v14h-14l-1 1h16v-16z' fill='#LIGHTT'/>\\n\"\n    \" <rect id='rectbackdrop' x='2' y='2' width='12' height='12' fill='#INTROR'/>\\n\"\n    \" <path id='indicator' d='m4.5 8 3 3 4-6' fill='none' stroke='#INDCTR' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/>\\n\"\n    \"</svg>\";\n\nstatic const char radiobtnOffData[] =\n    \"<svg id='radiobutton' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <defs>\\n\"\n    \"  <linearGradient id='gradient' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\"\n    \"   <stop stop-color='#DARKKK' offset='0'/>\\n\"\n    \"   <stop stop-color='#LIGHTT' offset='1' stop-opacity='0'/>\\n\"\n    \"  </linearGradient>\\n\"\n    \" </defs>\\n\"\n    \" <circle cx='8' cy='8' r='8' fill='url(#gradient)'/>\\n\"\n    \" <circle cx='8' cy='8' r='6.5' fill='#INTROR'/>\\n\"\n    \"</svg>\";\n\nstatic const char radiobtnOnData[] =\n    \"<svg id='radiobutton' width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <defs>\\n\"\n    \"  <linearGradient id='gradient' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\"\n    \"   <stop stop-color='#DARKKK' offset='0'/>\\n\"\n    \"   <stop stop-color='#LIGHTT' offset='1' stop-opacity='0'/>\\n\"\n    \"  </linearGradient>\\n\"\n    \" </defs>\\n\"\n    \" <circle cx='8' cy='8' r='8' fill='url(#gradient)'/>\\n\"\n    \" <circle cx='8' cy='8' r='7' fill='#INTROR'/>\\n\"\n    \" <circle cx='8' cy='8' r='4' fill='#INDCTR'/>\\n\"\n    \"</svg>\";\n\nstatic const char menuOffData[] =\n    \"<svg width='8' height='8' version='1.1' xmlns='http://www.w3.org/2000/svg'></svg>\";\n\nstatic const char checkmenuOnData[] =\n    \"<svg width='8' height='8' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <path id='indicator' d='m1 3.5 2.5 3 3.5-5' fill='none' stroke='#INDCTR' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.975'/>\\n\"\n    \"</svg>\";\n\nstatic const char radiomenuOnData[] =\n    \"<svg width='8' height='8' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\"\n    \" <circle cx='4' cy='4' r='3' fill='#INDCTR'/>\\n\"\n    \"</svg>\";\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawCheckIndicator -\n *\n *\tDraws the checkbox image in the drawable at the (x,y) location, value,\n *\tand state given. This routine is used by the button and menu widgets.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn image is drawn in the drawable at the location given.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nColorToStr(\n    const XColor *colorPtr,\t/* specifies a color */\n    char *colorStr)\t\t/* memory area to which the color is to be\n\t\t\t\t   output in the format \"RRGGBB\" */\n{\n    snprintf(colorStr, 7, \"%02x%02x%02x\",\n\t     colorPtr->red >> 8, colorPtr->green >> 8, colorPtr->blue >> 8);\n}\n\nstatic void\nImageChanged(\t\t\t/* to be passed to Tk_GetImage() */\n    void *clientData,\n    int x, int y, int width, int height,\n    int imageWidth, int imageHeight)\n{\n    (void)clientData;\n    (void)x; (void)y; (void)width; (void)height;\n    (void)imageWidth; (void)imageHeight;\n}\n\nvoid\nTkpDrawCheckIndicator(\n    Tk_Window tkwin,\t\t/* handle for resource alloc */\n    Display *display,\n    Drawable d,\t\t\t/* what to draw on */\n    int x, int y,\t\t/* where to draw */\n    Tk_3DBorder bgBorder,\t/* colors of the border */\n    XColor *indicatorColor,\t/* color of the indicator */\n    XColor *selectColor,\t/* color when selected */\n    XColor *disableColor,\t/* color when disabled */\n    int on,\t\t\t/* are we on? */\n    int disabled,\t\t/* are we disabled? */\n    int mode)\t\t\t/* kind of indicator to draw */\n{\n    const char *svgDataPtr;\n    int hasBorder, hasInterior, dim;\n    double scalingLevel = TkScalingLevel(tkwin);\n    TkBorder *bg_brdr = (TkBorder*)bgBorder;\n    char darkColorStr[7], lightColorStr[7], interiorColorStr[7], indicatorColorStr[7];\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[60];\n    Tk_Image img;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *darkColorPtr, *lightColorPtr, *interiorColorPtr, *indicatorColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n    /*\n     * Sanity check\n     */\n\n    if (tkwin == NULL || display == NULL || d == None || bgBorder == NULL\n\t    || indicatorColor == NULL) {\n\treturn;\n    }\n\n    if (disableColor == NULL) {\n\tdisableColor = bg_brdr->bgColorPtr;\n    }\n\n    if (selectColor == NULL) {\n\tselectColor = bg_brdr->bgColorPtr;\n    }\n\n    /*\n     * Determine the SVG data to use for the\n     * photo image and the latter's dimensions\n     */\n\n    switch (mode) {\n    default:\n    case CHECK_BUTTON:\n\tsvgDataPtr = (on == 0 ? checkbtnOffData : checkbtnOnData);\n\thasBorder = 1; hasInterior = 1;\n\tdim = CHECK_BUTTON_DIM;\n\tbreak;\n\n    case CHECK_MENU:\n\tsvgDataPtr = (on == 0 ? menuOffData : checkmenuOnData);\n\thasBorder = 0; hasInterior = 0;\n\tdim = CHECK_MENU_DIM;\n\tbreak;\n\n    case RADIO_BUTTON:\n\tsvgDataPtr = (on == 0 ? radiobtnOffData : radiobtnOnData);\n\thasBorder = 1; hasInterior = 1;\n\tdim = RADIO_BUTTON_DIM;\n\tbreak;\n\n    case RADIO_MENU:\n\tsvgDataPtr = (on == 0 ? menuOffData : radiomenuOnData);\n\thasBorder = 0; hasInterior = 0;\n\tdim = RADIO_MENU_DIM;\n\tbreak;\n    }\n    dim = (int)(dim * scalingLevel);\n\n    /*\n     * Construct the color strings darkColorStr, lightColorStr,\n     * interiorColorStr, and indicatorColorStr\n     */\n\n    TkpGetShadows(bg_brdr, tkwin);\n\n    if (bg_brdr->darkColorPtr == NULL) {\n\tstrcpy(darkColorStr, \"000000\");\n    } else {\n\tColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr),\n\t\t   darkColorStr);\n    }\n    if (bg_brdr->lightColorPtr == NULL) {\n\tstrcpy(lightColorStr, \"ffffff\");\n    } else {\n\tColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr),\n\t\t   lightColorStr);\n    }\n    if (on == 2 || disabled) {\t\t\t/* tri-state or disabled */\n\tColorToStr(Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr),\n\t\t   interiorColorStr);\n\tColorToStr(Tk_GetColorByValue(tkwin, disableColor),\n\t\t   indicatorColorStr);\n    } else {\n\tColorToStr(Tk_GetColorByValue(tkwin, selectColor),\n\t\t   interiorColorStr);\n\tColorToStr(Tk_GetColorByValue(tkwin, indicatorColor),\n\t\t   indicatorColorStr);\n    }\n\n    /*\n     * Check whether there is an SVG image of this size\n     * for the value of mode and these color strings\n     */\n\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::indicator%d_%d_%s_%s_%s_%s\",\n\t     dim, mode,\n\t     hasBorder ? darkColorStr : \"XXXXXX\",\n\t     hasBorder ? lightColorStr : \"XXXXXX\",\n\t     hasInterior ? interiorColorStr : \"XXXXXX\",\n\t     on ? indicatorColorStr : \"XXXXXX\");\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\n\tdarkColorPtr =      strstr(svgDataCopy, \"DARKKK\");\n\tlightColorPtr =     strstr(svgDataCopy, \"LIGHTT\");\n\tinteriorColorPtr =  strstr(svgDataCopy, \"INTROR\");\n\tindicatorColorPtr = strstr(svgDataCopy, \"INDCTR\");\n\n\tif (darkColorPtr != NULL) {\n\t    memcpy(darkColorPtr, darkColorStr, 6);\n\t}\n\tif (lightColorPtr != NULL) {\n\t    memcpy(lightColorPtr, lightColorStr, 6);\n\t}\n\tif (interiorColorPtr != NULL) {\n\t    memcpy(interiorColorPtr, interiorColorStr, 6);\n\t}\n\tif (indicatorColorPtr != NULL) {\n\t    memcpy(indicatorColorPtr, indicatorColorStr, 6);\n\t}\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Adjust the image's coordinates in the drawable and display the image\n     */\n\n    x -= dim/2;\n    y -= dim/2;\n    Tk_RedrawImage(img, 0, 0, dim, dim, d, x, y);\n    Tk_FreeImage(img);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateButton --\n *\n *\tAllocate a new TkButton structure.\n *\n * Results:\n *\tReturns a newly allocated TkButton structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkButton *\nTkpCreateButton(\n    TCL_UNUSED(Tk_Window))\n{\n    return (TkButton *)Tcl_Alloc(sizeof(UnixButton));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayButton --\n *\n *\tThis function is invoked to display a button widget. It is normally\n *\tinvoked as an idle handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the button in its current mode.\n *\tThe REDRAW_PENDING flag is cleared.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nShiftByOffset(\n    TkButton *butPtr,\n    int relief,\n    int *x,\t\t/* shift this x coordinate */\n    int *y,\t\t/* shift this y coordinate */\n    int width,\t\t/* width of image/text */\n    int height)\t\t/* height of image/text */\n{\n    if (relief != TK_RELIEF_RAISED\n\t    && butPtr->type == TYPE_BUTTON\n\t    && !Tk_StrictMotif(butPtr->tkwin)) {\n\tint shiftX;\n\tint shiftY;\n\n\t/*\n\t * This is an (unraised) button widget, so we offset the text to make\n\t * the button appear to move up and down as the relief changes.\n\t */\n\n\tshiftX = shiftY = (relief == TK_RELIEF_SUNKEN) ? 2 : 1;\n\n\tif (relief != TK_RELIEF_RIDGE) {\n\t    /*\n\t     * Take back one pixel if the padding is even, otherwise the\n\t     * content will be displayed too far right/down.\n\t     */\n\n\t    if ((Tk_Width(butPtr->tkwin) - width) % 2 == 0) {\n\t\tshiftX -= 1;\n\t    }\n\t    if ((Tk_Height(butPtr->tkwin) - height) % 2 == 0) {\n\t\tshiftY -= 1;\n\t    }\n\t}\n\n\t*x += shiftX;\n\t*y += shiftY;\n    }\n}\n\nvoid\nTkpDisplayButton(\n    void *clientData)\t/* Information about widget. */\n{\n    TkButton *butPtr = (TkButton *)clientData;\n    GC gc;\n    Tk_3DBorder border;\n    Pixmap pixmap;\n    int x = 0;\t\t\t/* Initialization only needed to stop compiler\n\t\t\t\t * warning. */\n    int y, relief;\n    Tk_Window tkwin = butPtr->tkwin;\n    int width = 0, height = 0, fullWidth, fullHeight;\n    int textXOffset, textYOffset;\n    int haveImage = 0, haveText = 0;\n    int imageWidth, imageHeight;\n    int imageXOffset = 0, imageYOffset = 0;\n\t\t\t\t/* image information that will be used to\n\t\t\t\t * restrict disabled pixmap as well */\n    int padX, padY, borderWidth, highlightWidth;\n\n    butPtr->flags &= ~REDRAW_PENDING;\n    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    border = butPtr->normalBorder;\n    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {\n\tgc = butPtr->disabledGC;\n    } else if ((butPtr->state == STATE_ACTIVE)\n\t    && !Tk_StrictMotif(butPtr->tkwin)) {\n\tgc = butPtr->activeTextGC;\n\tborder = butPtr->activeBorder;\n    } else {\n\tgc = butPtr->normalTextGC;\n    }\n    if ((butPtr->flags & SELECTED) && (butPtr->selectBorder != NULL)\n\t    && !butPtr->indicatorOn) {\n\tborder = butPtr->selectBorder;\n    }\n\n    /*\n     * Override the relief specified for the button if this is a checkbutton\n     * or radiobutton and there's no indicator. The new relief is as follows:\n     *      If the button is select  --> \"sunken\"\n     *      If relief==overrelief    --> relief\n     *      Otherwise                --> overrelief\n     *\n     * The effect we are trying to achieve is as follows:\n     *\n     *      value    mouse-over?   -->   relief\n     *     -------  ------------        --------\n     *       off        no               flat\n     *       off        yes              raised\n     *       on         no               sunken\n     *       on         yes              sunken\n     *\n     * This is accomplished by configuring the checkbutton or radiobutton like\n     * this:\n     *\n     *     -indicatoron 0 -overrelief raised -offrelief flat\n     *\n     * Bindings (see library/button.tcl) will copy the -overrelief into\n     * -relief on mouseover. Hence, we can tell if we are in mouse-over by\n     * comparing relief against overRelief. This is an aweful kludge, but it\n     * gives use the desired behavior while keeping the code backwards\n     * compatible.\n     */\n\n    relief = butPtr->relief;\n    if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {\n\tif (butPtr->flags & SELECTED) {\n\t    relief = TK_RELIEF_SUNKEN;\n\t} else if (butPtr->overRelief != relief) {\n\t    relief = butPtr->offRelief;\n\t}\n    }\n\n    /*\n     * In order to avoid screen flashes, this function redraws the button in a\n     * pixmap, then copies the pixmap to the screen in a single operation.\n     * This means that there's no point in time where the on-screen image has\n     * been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n    Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),\n\t    Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\n    /*\n     * Display image or bitmap or text for button.\n     */\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n    imageWidth = width;\n    imageHeight = height;\n\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->highlightWidthObj, &highlightWidth);\n\n    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);\n\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\ttextXOffset = 0;\n\ttextYOffset = 0;\n\tfullWidth = 0;\n\tfullHeight = 0;\n\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_TOP) {\n\t\ttextYOffset = height + padY;\n\t    } else {\n\t\timageYOffset = butPtr->textHeight + padY;\n\t    }\n\t    fullHeight = height + butPtr->textHeight + padY;\n\t    fullWidth = (width > butPtr->textWidth ? width :\n\t\t    butPtr->textWidth);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text.\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_LEFT) {\n\t\ttextXOffset = width + padX;\n\t    } else {\n\t\timageXOffset = butPtr->textWidth + padX;\n\t    }\n\t    fullWidth = butPtr->textWidth + padX + width;\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    fullWidth = (width > butPtr->textWidth ? width :\n\t\t    butPtr->textWidth);\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\n\tTkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\tbutPtr->indicatorSpace + fullWidth, fullHeight, &x, &y);\n\n\tx += butPtr->indicatorSpace;\n\tShiftByOffset(butPtr, relief, &x, &y, width, height);\n\timageXOffset += x;\n\timageYOffset += y;\n\n\tif (butPtr->image != NULL) {\n\t    /*\n\t     * Do boundary clipping, so that Tk_RedrawImage is passed valid\n\t     * coordinates. [Bug 979239]\n\t     */\n\n\t    if (imageXOffset < 0) {\n\t\timageXOffset = 0;\n\t    }\n\t    if (imageYOffset < 0) {\n\t\timageYOffset = 0;\n\t    }\n\t    if (width > Tk_Width(tkwin)) {\n\t\twidth = Tk_Width(tkwin);\n\t    }\n\t    if (height > Tk_Height(tkwin)) {\n\t\theight = Tk_Height(tkwin);\n\t    }\n\t    if ((width + imageXOffset) > Tk_Width(tkwin)) {\n\t\timageXOffset = Tk_Width(tkwin) - width;\n\t    }\n\t    if ((height + imageYOffset) > Tk_Height(tkwin)) {\n\t\timageYOffset = Tk_Height(tkwin) - height;\n\t    }\n\n\t    if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {\n\t\tTk_RedrawImage(butPtr->selectImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) {\n\t\tTk_RedrawImage(butPtr->tristateImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else {\n\t\tTk_RedrawImage(butPtr->image, 0, 0, width,\n\t\t\theight, pixmap, imageXOffset, imageYOffset);\n\t    }\n\t} else {\n\t    XSetClipOrigin(butPtr->display, gc, imageXOffset, imageYOffset);\n\t    XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc,\n\t\t    0, 0, (unsigned int) width, (unsigned int) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(butPtr->display, gc, 0, 0);\n\t}\n\n\tTk_DrawTextLayout(butPtr->display, pixmap, gc,\n\t\tbutPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\tbutPtr->textLayout, x + textXOffset, y + textYOffset,\n\t\tbutPtr->underline);\n\ty += fullHeight/2;\n    } else {\n\tif (haveImage) {\n\t    TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,\n\t\t    butPtr->indicatorSpace + width, height, &x, &y);\n\t    x += butPtr->indicatorSpace;\n\t    ShiftByOffset(butPtr, relief, &x, &y, width, height);\n\t    imageXOffset += x;\n\t    imageYOffset += y;\n\t    if (butPtr->image != NULL) {\n\t\t/*\n\t\t * Do boundary clipping, so that Tk_RedrawImage is passed\n\t\t * valid coordinates. [Bug 979239]\n\t\t */\n\n\t\tif (imageXOffset < 0) {\n\t\t    imageXOffset = 0;\n\t\t}\n\t\tif (imageYOffset < 0) {\n\t\t    imageYOffset = 0;\n\t\t}\n\t\tif (width > Tk_Width(tkwin)) {\n\t\t    width = Tk_Width(tkwin);\n\t\t}\n\t\tif (height > Tk_Height(tkwin)) {\n\t\t    height = Tk_Height(tkwin);\n\t\t}\n\t\tif ((width + imageXOffset) > Tk_Width(tkwin)) {\n\t\t    imageXOffset = Tk_Width(tkwin) - width;\n\t\t}\n\t\tif ((height + imageYOffset) > Tk_Height(tkwin)) {\n\t\t    imageYOffset = Tk_Height(tkwin) - height;\n\t\t}\n\n\t\tif ((butPtr->selectImage != NULL) &&\n\t\t\t(butPtr->flags & SELECTED)) {\n\t\t    Tk_RedrawImage(butPtr->selectImage, 0, 0, width,\n\t\t\t    height, pixmap, imageXOffset, imageYOffset);\n\t\t} else if ((butPtr->tristateImage != NULL) &&\n\t\t\t(butPtr->flags & TRISTATED)) {\n\t\t    Tk_RedrawImage(butPtr->tristateImage, 0, 0, width,\n\t\t\t    height, pixmap, imageXOffset, imageYOffset);\n\t\t} else {\n\t\t    Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,\n\t\t\t    imageXOffset, imageYOffset);\n\t\t}\n\t    } else {\n\t\tXSetClipOrigin(butPtr->display, gc, x, y);\n\t\tXCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,\n\t\t\t(unsigned int) width, (unsigned int) height, x, y, 1);\n\t\tXSetClipOrigin(butPtr->display, gc, 0, 0);\n\t    }\n\t    y += height/2;\n\t} else {\n\t    TkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\t    butPtr->indicatorSpace + butPtr->textWidth,\n\t\t    butPtr->textHeight, &x, &y);\n\n\t    x += butPtr->indicatorSpace;\n\t    ShiftByOffset(butPtr, relief, &x, &y, width, height);\n\t    Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,\n\t\t    x, y, 0, -1);\n\t    Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\t    butPtr->textLayout, x, y, butPtr->underline);\n\t    y += butPtr->textHeight/2;\n\t}\n    }\n\n    /*\n     * Draw the indicator for check buttons and radio buttons. At this point,\n     * x and y refer to the top-left corner of the text or image or bitmap.\n     */\n\n    if ((butPtr->type == TYPE_CHECK_BUTTON || butPtr->type == TYPE_RADIO_BUTTON)\n\t    && butPtr->indicatorOn\n\t    && butPtr->indicatorDiameter > 2 * borderWidth) {\n\tTkBorder *selBorder = (TkBorder *) butPtr->selectBorder;\n\tXColor *selColor = NULL;\n\tint btype = (butPtr->type == TYPE_CHECK_BUTTON ?\n\t\t     CHECK_BUTTON : RADIO_BUTTON);\n\n\tif (selBorder != NULL) {\n\t    selColor = selBorder->bgColorPtr;\n\t}\n\tx -= butPtr->indicatorSpace/2;\n\ty = Tk_Height(tkwin)/2;\n\tTkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y,\n\t\tborder, butPtr->normalFg, selColor, butPtr->disabledFg,\n\t\t((butPtr->flags & SELECTED) ? 1 :\n\t\t (butPtr->flags & TRISTATED) ? 2 : 0),\n\t\t (butPtr->state == STATE_DISABLED), btype);\n    }\n\n    /*\n     * If the button is disabled with a stipple rather than a special\n     * foreground color, generate the stippled effect. If the widget is\n     * selected and we use a different background color when selected, must\n     * temporarily modify the GC so the stippling is the right color.\n     */\n\n    if ((butPtr->state == STATE_DISABLED)\n\t    && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {\n\tif ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t&& (butPtr->selectBorder != NULL)) {\n\t    XSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t    Tk_3DBorderColor(butPtr->selectBorder)->pixel);\n\t}\n\n\t/*\n\t * Stipple the whole button if no disabledFg was specified, otherwise\n\t * restrict stippling only to displayed image\n\t */\n\n\tif (butPtr->disabledFg == NULL) {\n\t    XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0,\n\t\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin));\n\t} else {\n\t    XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,\n\t\t    imageXOffset, imageYOffset,\n\t\t    (unsigned) imageWidth, (unsigned) imageHeight);\n\t}\n\tif ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t&& (butPtr->selectBorder != NULL)) {\n\t    XSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t    Tk_3DBorderColor(butPtr->normalBorder)->pixel);\n\t}\n    }\n\n    /*\n     * Draw the border and traversal highlight last. This way, if the button's\n     * contents overflow they'll be covered up by the border. This code is\n     * complicated by the possible combinations of focus highlight and default\n     * rings. We draw the focus and highlight rings using the highlight border\n     * and highlight foreground color.\n     */\n\n    if (relief != TK_RELIEF_FLAT) {\n\tint inset = highlightWidth;\n\n\tif (butPtr->defaultState == DEFAULT_ACTIVE) {\n\t    /*\n\t     * Draw the default ring with 2 pixels of space between the\n\t     * default ring and the button and the default ring and the focus\n\t     * ring. Note that we need to explicitly draw the space in the\n\t     * highlightBorder color to ensure that we overwrite any overflow\n\t     * text and/or a different button background color.\n\t     */\n\n\t    Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,\n\t\t    inset, Tk_Width(tkwin) - 2 * inset,\n\t\t    Tk_Height(tkwin) - 2 * inset, 2, TK_RELIEF_FLAT);\n\t    inset += 2;\n\t    Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,\n\t\t    inset, Tk_Width(tkwin) - 2 * inset,\n\t\t    Tk_Height(tkwin) - 2 * inset, 1, TK_RELIEF_SUNKEN);\n\t    inset++;\n\t    Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,\n\t\t    inset, Tk_Width(tkwin) - 2 * inset,\n\t\t    Tk_Height(tkwin) - 2 * inset, 2, TK_RELIEF_FLAT);\n\n\t    inset += 2;\n\t} else if (butPtr->defaultState == DEFAULT_NORMAL) {\n\t    /*\n\t     * Leave room for the default ring and write over any text or\n\t     * background color.\n\t     */\n\n\t    Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0,\n\t\t    0, Tk_Width(tkwin), Tk_Height(tkwin), 5, TK_RELIEF_FLAT);\n\t    inset += 5;\n\t}\n\n\t/*\n\t * Draw the button border.\n\t */\n\n\tTk_Draw3DRectangle(tkwin, pixmap, border, inset, inset,\n\t\tTk_Width(tkwin) - 2 * inset, Tk_Height(tkwin) - 2 * inset,\n\t\tborderWidth, relief);\n    }\n    if (highlightWidth > 0) {\n\tif (butPtr->flags & GOT_FOCUS) {\n\t    gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);\n\t} else {\n\t    gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder),\n\t\t    pixmap);\n\t}\n\n\t/*\n\t * Make sure the focus ring shrink-wraps the actual button, not the\n\t * padding space left for a default ring.\n\t */\n\n\tif (butPtr->defaultState == DEFAULT_NORMAL) {\n\t    TkDrawInsetFocusHighlight(tkwin, gc, highlightWidth,\n\t\t    pixmap, 5);\n\t} else {\n\t    Tk_DrawFocusHighlight(tkwin, gc, highlightWidth, pixmap);\n\t}\n    }\n\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),\n\t    butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),\n\t    (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(butPtr->display, pixmap);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeButtonGeometry --\n *\n *\tAfter changes in a button's text or bitmap, this function recomputes\n *\tthe button's geometry and passes this information along to the\n *\tgeometry manager for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe button's window may change size.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeButtonGeometry(\n    TkButton *butPtr)\t/* Button whose geometry may have changed. */\n{\n    int width, height, avgWidth, txtWidth, txtHeight;\n    int haveImage = 0, haveText = 0;\n    Tk_FontMetrics fm;\n    int padX, padY, borderWidth, highlightWidth, wrapLength;\n    int butPtrWidth, butPtrHeight;\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->wrapLengthObj, &wrapLength);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->widthObj, &butPtrWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->heightObj, &butPtrHeight);\n\n    butPtr->inset = highlightWidth + borderWidth;\n\n    /*\n     * Leave room for the default ring if needed.\n     */\n\n    if (butPtr->defaultState != DEFAULT_DISABLED) {\n\tbutPtr->inset += 5;\n    }\n    butPtr->indicatorSpace = 0;\n\n    width = 0;\n    height = 0;\n    txtWidth = 0;\n    txtHeight = 0;\n    avgWidth = 0;\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {\n\tTk_FreeTextLayout(butPtr->textLayout);\n\n\tbutPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,\n\t\tTcl_GetString(butPtr->textPtr), TCL_INDEX_NONE, wrapLength,\n\t\tbutPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);\n\n\ttxtWidth = butPtr->textWidth;\n\ttxtHeight = butPtr->textHeight;\n\tavgWidth = Tk_TextWidth(butPtr->tkfont, \"0\", 1);\n\tTk_GetFontMetrics(butPtr->tkfont, &fm);\n\thaveText = (txtWidth != 0 && txtHeight != 0);\n    }\n\n    /*\n     * If the button is compound (i.e., it shows both an image and text), the\n     * new geometry is a combination of the image and text geometry. We only\n     * honor the compound bit if the button has both text and an image,\n     * because otherwise it is not really a compound button.\n     */\n\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    height += txtHeight + padY;\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text.\n\t     */\n\n\t    width += txtWidth + padX;\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\tif (butPtrWidth > 0) {\n\t    width = butPtrWidth;\n\t}\n\tif (butPtrHeight > 0) {\n\t    height = butPtrHeight;\n\t}\n\n\tif ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {\n\t    butPtr->indicatorSpace = height;\n\t    if (butPtr->type == TYPE_CHECK_BUTTON) {\n\t\tbutPtr->indicatorDiameter = (65*height)/100;\n\t    } else {\n\t\tbutPtr->indicatorDiameter = (75*height)/100;\n\t    }\n\t}\n\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    } else {\n\tif (haveImage) {\n\t    if (butPtrWidth > 0) {\n\t\twidth = butPtrWidth;\n\t    }\n\t    if (butPtrHeight > 0) {\n\t\theight = butPtrHeight;\n\t    }\n\n\t    if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {\n\t\tbutPtr->indicatorSpace = height;\n\t\tif (butPtr->type == TYPE_CHECK_BUTTON) {\n\t\t    butPtr->indicatorDiameter = (65*height)/100;\n\t\t} else {\n\t\t    butPtr->indicatorDiameter = (75*height)/100;\n\t\t}\n\t    }\n\t} else {\n\t    width = txtWidth;\n\t    height = txtHeight;\n\n\t    if (butPtrWidth > 0) {\n\t\twidth = butPtrWidth * avgWidth;\n\t    }\n\t    if (butPtrHeight > 0) {\n\t\theight = butPtrHeight * fm.linespace;\n\t    }\n\t    if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {\n\t\tbutPtr->indicatorDiameter = fm.linespace;\n\t\tbutPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;\n\t    }\n\t}\n    }\n\n    /*\n     * When issuing the geometry request, add extra space for the indicator,\n     * if any, and for the border and padding, plus two extra pixels so the\n     * display can be offset by 1 pixel in either direction for the raised or\n     * lowered effect.\n     */\n\n    if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    }\n    if ((butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin)) {\n\twidth += 2;\n\theight += 2;\n    }\n    Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace\n\t    + 2 * butPtr->inset), (int) (height + 2 * butPtr->inset));\n    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixColor.c",
    "content": "/*\n * tkUnixColor.c --\n *\n *\tThis file contains the platform specific color routines needed for X\n *\tsupport.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkColor.h\"\n\n/*\n * If a colormap fills up, attempts to allocate new colors from that colormap\n * will fail. When that happens, we'll just choose the closest color from\n * those that are available in the colormap. One of the following structures\n * will be created for each \"stressed\" colormap to keep track of the colors\n * that are available in the colormap (otherwise we would have to re-query\n * from the server on each allocation, which would be very slow). These\n * entries are flushed after a few seconds, since other clients may release or\n * reallocate colors over time.\n */\n\nstruct TkStressedCmap {\n    Colormap colormap;\t\t/* X's token for the colormap. */\n    int numColors;\t\t/* Number of entries currently active at\n\t\t\t\t * *colorPtr. */\n    XColor *colorPtr;\t\t/* Pointer to malloc'ed array of all colors\n\t\t\t\t * that seem to be available in the colormap.\n\t\t\t\t * Some may not actually be available, e.g.\n\t\t\t\t * because they are read-write for another\n\t\t\t\t * client; when we find this out, we remove\n\t\t\t\t * them from the array. */\n    struct TkStressedCmap *nextPtr;\n\t\t\t\t/* Next in list of all stressed colormaps for\n\t\t\t\t * the display. */\n};\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tDeleteStressedCmap(Display *display,\n\t\t\t    Colormap colormap);\nstatic void\t\tFindClosestColor(Tk_Window tkwin,\n\t\t\t    XColor *desiredColorPtr, XColor *actualColorPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeColor --\n *\n *\tRelease the specified color back to the system.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tInvalidates the colormap cache for the colormap associated with the\n *\tgiven color.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeColor(\n    TkColor *tkColPtr)\t\t/* Color to be released. Must have been\n\t\t\t\t * allocated by TkpGetColor or\n\t\t\t\t * TkpGetColorByValue. */\n{\n    Visual *visual;\n    Screen *screen = tkColPtr->screen;\n\n    /*\n     * Careful! Don't free black or white, since this will make some servers\n     * very unhappy. Also, there is a bug in some servers (such Sun's X11/NeWS\n     * server) where reference counting is performed incorrectly, so that if a\n     * color is allocated twice in different places and then freed twice, the\n     * second free generates an error (this bug existed as of 10/1/92). To get\n     * around this problem, ignore errors that occur during the free\n     * operation.\n     */\n\n    visual = tkColPtr->visual;\n    if ((visual->c_class != StaticGray) && (visual->c_class != StaticColor)\n\t    && (tkColPtr->color.pixel != BlackPixelOfScreen(screen))\n\t    && (tkColPtr->color.pixel != WhitePixelOfScreen(screen))) {\n\tTk_ErrorHandler handler;\n\n\thandler = Tk_CreateErrorHandler(DisplayOfScreen(screen),\n\t\t-1, -1, -1, NULL, NULL);\n\tXFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,\n\t\t&tkColPtr->color.pixel, 1, 0L);\n\tTk_DeleteErrorHandler(handler);\n    }\n    DeleteStressedCmap(DisplayOfScreen(screen), tkColPtr->colormap);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColor --\n *\n *\tAllocate a new TkColor for the color with the given name.\n *\n * Results:\n *\tReturns a newly allocated TkColor, or NULL on failure.\n *\n * Side effects:\n *\tMay invalidate the colormap cache associated with tkwin upon\n *\tallocating a new colormap entry. Allocates a new TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColor(\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    const char *name)\t\t/* Name of color to allocated (in form\n\t\t\t\t * suitable for passing to XParseColor). */\n{\n    Display *display = Tk_Display(tkwin);\n    Colormap colormap = Tk_Colormap(tkwin);\n    XColor color;\n    TkColor *tkColPtr;\n\n    /*\n     * Map from the name to a pixel value. Call XAllocNamedColor rather than\n     * XParseColor for non-# names: this saves a server round-trip for those\n     * names.\n     */\n\n    if (*name != '#') {\n\tXColor screen;\n\n\tif (((*name - 'A') & 0xDF) < sizeof(tkWebColors)/sizeof(tkWebColors[0])) {\n\t    if (!((name[0] - 'G') & 0xDF) && !((name[1] - 'R') & 0xDF)\n\t\t    && !((name[2] - 'A') & 0xDB) && !((name[3] - 'Y') & 0xDF)\n\t\t    && !name[4]) {\n\t\tname = \"#808080808080\";\n\t\tgoto gotWebColor;\n\t    } else {\n\t\tconst char *p = tkWebColors[((*name - 'A') & 0x1F)];\n\t\tif (p) {\n\t\t    const char *q = name;\n\t\t    while (!((*p - *(++q)) & 0xDF)) {\n\t\t\tif (!*p++) {\n\t\t\t    name = p;\n\t\t\t    goto gotWebColor;\n\t\t\t}\n\t\t    }\n\t\t}\n\t}\n\t}\n\tif (strlen(name) > 99) {\n\t/* Don't bother to parse this. [Bug 2809525]*/\n\treturn NULL;\n    } else if (XAllocNamedColor(display, colormap, name, &screen, &color) != 0) {\n\t    DeleteStressedCmap(display, colormap);\n\t} else {\n\t    /*\n\t     * Couldn't allocate the color. Try translating the name to a\n\t     * color value, to see whether the problem is a bad color name or\n\t     * a full colormap. If the colormap is full, then pick an\n\t     * approximation to the desired color.\n\t     */\n\n\t    if (XLookupColor(display, colormap, name, &color, &screen) == 0) {\n\t\treturn NULL;\n\t    }\n\t    FindClosestColor(tkwin, &screen, &color);\n\t}\n    } else {\n    gotWebColor:\n\tif (TkParseColor(display, colormap, name, &color) == 0) {\n\t    return NULL;\n\t}\n\tif (XAllocColor(display, colormap, &color) != 0) {\n\t    DeleteStressedCmap(display, colormap);\n\t} else {\n\t    FindClosestColor(tkwin, &color, &color);\n\t}\n    }\n\n    tkColPtr = (TkColor *)Tcl_Alloc(sizeof(TkColor));\n    tkColPtr->color = color;\n\n    return tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColorByValue --\n *\n *\tGiven a desired set of red-green-blue intensities for a color, locate\n *\ta pixel value to use to draw that color in a given window.\n *\n * Results:\n *\tThe return value is a pointer to an TkColor structure that indicates\n *\tthe closest red, blue, and green intensities available to those\n *\tspecified in colorPtr, and also specifies a pixel value to use to draw\n *\tin that color.\n *\n * Side effects:\n *\tMay invalidate the colormap cache for the specified window. Allocates\n *\ta new TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColorByValue(\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    XColor *colorPtr)\t\t/* Red, green, and blue fields indicate\n\t\t\t\t * desired color. */\n{\n    Display *display = Tk_Display(tkwin);\n    Colormap colormap = Tk_Colormap(tkwin);\n    TkColor *tkColPtr = (TkColor *)Tcl_Alloc(sizeof(TkColor));\n\n    tkColPtr->color.red = colorPtr->red;\n    tkColPtr->color.green = colorPtr->green;\n    tkColPtr->color.blue = colorPtr->blue;\n    if (XAllocColor(display, colormap, &tkColPtr->color) != 0) {\n\tDeleteStressedCmap(display, colormap);\n    } else {\n\tFindClosestColor(tkwin, &tkColPtr->color, &tkColPtr->color);\n    }\n\n    return tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindClosestColor --\n *\n *\tWhen Tk can't allocate a color because a colormap has filled up, this\n *\tfunction is called to find and allocate the closest available color in\n *\tthe colormap.\n *\n * Results:\n *\tThere is no return value, but *actualColorPtr is filled in with\n *\tinformation about the closest available color in tkwin's colormap.\n *\tThis color has been allocated via X, so it must be released by the\n *\tcaller when the caller is done with it.\n *\n * Side effects:\n *\tA color is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFindClosestColor(\n    Tk_Window tkwin,\t\t/* Window where color will be used. */\n    XColor *desiredColorPtr,\t/* RGB values of color that was wanted (but\n\t\t\t\t * unavailable). */\n    XColor *actualColorPtr)\t/* Structure to fill in with RGB and pixel for\n\t\t\t\t * closest available color. */\n{\n    TkStressedCmap *stressPtr;\n    double tmp, distance, closestDistance;\n    int i, closest, numFound;\n    XColor *colorPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    Colormap colormap = Tk_Colormap(tkwin);\n    XVisualInfo templ, *visInfoPtr;\n\n    /*\n     * Find the TkStressedCmap structure for this colormap, or create a new\n     * one if needed.\n     */\n\n    for (stressPtr = dispPtr->stressPtr; ; stressPtr = stressPtr->nextPtr) {\n\tif (stressPtr == NULL) {\n\t    stressPtr = (TkStressedCmap *)Tcl_Alloc(sizeof(TkStressedCmap));\n\t    stressPtr->colormap = colormap;\n\t    templ.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));\n\n\t    visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),\n\t\t    VisualIDMask, &templ, &numFound);\n\t    if (numFound < 1) {\n\t\tTcl_Panic(\"FindClosestColor couldn't lookup visual\");\n\t    }\n\n\t    stressPtr->numColors = visInfoPtr->colormap_size;\n\t    XFree(visInfoPtr);\n\t    stressPtr->colorPtr = (XColor *)\n\t\t    Tcl_Alloc((size_t)stressPtr->numColors * sizeof(XColor));\n\t    for (i = 0; i < stressPtr->numColors; i++) {\n\t\tstressPtr->colorPtr[i].pixel = (unsigned long) i;\n\t    }\n\n\t    XQueryColors(dispPtr->display, colormap, stressPtr->colorPtr,\n\t\t    stressPtr->numColors);\n\n\t    stressPtr->nextPtr = dispPtr->stressPtr;\n\t    dispPtr->stressPtr = stressPtr;\n\t    break;\n\t}\n\tif (stressPtr->colormap == colormap) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Find the color that best approximates the desired one, then try to\n     * allocate that color. If that fails, it must mean that the color was\n     * read-write (so we can't use it, since it's owner might change it) or\n     * else it was already freed. Try again, over and over again, until\n     * something succeeds.\n     */\n\n    while (1) {\n\tif (stressPtr->numColors == 0) {\n\t    Tcl_Panic(\"FindClosestColor ran out of colors\");\n\t}\n\tclosestDistance = 1e30;\n\tclosest = 0;\n\tfor (colorPtr = stressPtr->colorPtr, i = 0; i < stressPtr->numColors;\n\t\tcolorPtr++, i++) {\n\t    /*\n\t     * Use Euclidean distance in RGB space, weighted by Y (of YIQ) as\n\t     * the objective function; this accounts for differences in the\n\t     * color sensitivity of the eye.\n\t     */\n\n\t    tmp = .30*(((int) desiredColorPtr->red) - (int) colorPtr->red);\n\t    distance = tmp*tmp;\n\t    tmp = .61*(((int) desiredColorPtr->green) - (int) colorPtr->green);\n\t    distance += tmp*tmp;\n\t    tmp = .11*(((int) desiredColorPtr->blue) - (int) colorPtr->blue);\n\t    distance += tmp*tmp;\n\t    if (distance < closestDistance) {\n\t\tclosest = i;\n\t\tclosestDistance = distance;\n\t    }\n\t}\n\tif (XAllocColor(dispPtr->display, colormap,\n\t\t&stressPtr->colorPtr[closest]) != 0) {\n\t    *actualColorPtr = stressPtr->colorPtr[closest];\n\t    return;\n\t}\n\n\t/*\n\t * Couldn't allocate the color. Remove it from the table and go back\n\t * to look for the next best color.\n\t */\n\n\tstressPtr->colorPtr[closest] =\n\t\tstressPtr->colorPtr[stressPtr->numColors-1];\n\tstressPtr->numColors -= 1;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DeleteStressedCmap --\n *\n *\tThis function releases the information cached for \"colormap\" so that\n *\tit will be refetched from the X server the next time it is needed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe TkStressedCmap structure for colormap is deleted; the colormap is\n *\tno longer considered to be \"stressed\".\n *\n * Note:\n *\tThis function is invoked whenever a color in a colormap is freed, and\n *\twhenever a color allocation in a colormap succeeds. This guarantees\n *\tthat TkStressedCmap structures are always deleted before the\n *\tcorresponding Colormap is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDeleteStressedCmap(\n    Display *display,\t\t/* Xlib's handle for the display containing\n\t\t\t\t * the colormap. */\n    Colormap colormap)\t\t/* Colormap to flush. */\n{\n    TkStressedCmap *prevPtr, *stressPtr;\n    TkDisplay *dispPtr = TkGetDisplay(display);\n\n    for (prevPtr = NULL, stressPtr = dispPtr->stressPtr; stressPtr != NULL;\n\t    prevPtr = stressPtr, stressPtr = stressPtr->nextPtr) {\n\tif (stressPtr->colormap == colormap) {\n\t    if (prevPtr == NULL) {\n\t\tdispPtr->stressPtr = stressPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = stressPtr->nextPtr;\n\t    }\n\t    Tcl_Free(stressPtr->colorPtr);\n\t    Tcl_Free(stressPtr);\n\t    return;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCmapStressed --\n *\n *\tCheck to see whether a given colormap is known to be out of entries.\n *\n * Results:\n *\t1 is returned if \"colormap\" is stressed (i.e. it has run out of\n *\tentries recently), 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\n#undef TkpCmapStressed\nbool\nTkpCmapStressed(\n    Tk_Window tkwin,\t\t/* Window that identifies the display\n\t\t\t\t * containing the colormap. */\n    Colormap colormap)\t\t/* Colormap to check for stress. */\n{\n    TkStressedCmap *stressPtr;\n\n    for (stressPtr = ((TkWindow *) tkwin)->dispPtr->stressPtr;\n\t    stressPtr != NULL; stressPtr = stressPtr->nextPtr) {\n\tif (stressPtr->colormap == colormap) {\n\t    return true;\n\t}\n    }\n    return false;\n}\n\f\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixConfig.c",
    "content": "/*\n * tkUnixConfig.c --\n *\n *\tThis module implements the Unix system defaults for the configuration\n *\tpackage.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetSystemDefault --\n *\n *\tGiven a dbName and className for a configuration option, return a\n *\tstring representation of the option.\n *\n * Results:\n *\tReturns a Tcl_Obj* with the string identifier that identifies this\n *\toption. Returns NULL if there are no system defaults that match this\n *\tpair.\n *\n * Side effects:\n *\tNone, once the package is initialized.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_GetSystemDefault(\n    Tk_Window tkwin,\t\t/* A window to use. */\n    const char *dbName,\t\t/* The option database name. */\n    const char *className)\t/* The name of the option class. */\n{\n    (void)tkwin;\n    (void)dbName;\n    (void)className;\n\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixCursor.c",
    "content": "/*\n * tkUnixCursor.c --\n *\n *\tThis file contains X specific cursor manipulation routines.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include <X11/cursorfont.h>\n\n/*\n * The following data structure is a superset of the TkCursor structure\n * defined in tkCursor.c. Each system specific cursor module will define a\n * different cursor structure. All of these structures must have the same\n * header consisting of the fields in TkCursor.\n */\n\ntypedef struct {\n    TkCursor info;\t\t/* Generic cursor info used by tkCursor.c */\n    Display *display;\t\t/* Display for which cursor is valid. */\n} TkUnixCursor;\n\n/*\n * The table below is used to map from the name of a cursor to its index in\n * the official cursor font:\n */\n\nstatic const struct CursorName {\n    const char *name;\n    unsigned int shape;\n} cursorNames[] = {\n    {\"X_cursor\",\t\tXC_X_cursor},\n    {\"arrow\",\t\t\tXC_arrow},\n    {\"based_arrow_down\",\tXC_based_arrow_down},\n    {\"based_arrow_up\",\t\tXC_based_arrow_up},\n    {\"boat\",\t\t\tXC_boat},\n    {\"bogosity\",\t\tXC_bogosity},\n    {\"bottom_left_corner\",\tXC_bottom_left_corner},\n    {\"bottom_right_corner\",\tXC_bottom_right_corner},\n    {\"bottom_side\",\t\tXC_bottom_side},\n    {\"bottom_tee\",\t\tXC_bottom_tee},\n    {\"box_spiral\",\t\tXC_box_spiral},\n    {\"center_ptr\",\t\tXC_center_ptr},\n    {\"circle\",\t\t\tXC_circle},\n    {\"clock\",\t\t\tXC_clock},\n    {\"coffee_mug\",\t\tXC_coffee_mug},\n    {\"cross\",\t\t\tXC_cross},\n    {\"cross_reverse\",\t\tXC_cross_reverse},\n    {\"crosshair\",\t\tXC_crosshair},\n    {\"diamond_cross\",\t\tXC_diamond_cross},\n    {\"dot\",\t\t\tXC_dot},\n    {\"dotbox\",\t\t\tXC_dotbox},\n    {\"double_arrow\",\t\tXC_double_arrow},\n    {\"draft_large\",\t\tXC_draft_large},\n    {\"draft_small\",\t\tXC_draft_small},\n    {\"draped_box\",\t\tXC_draped_box},\n    {\"exchange\",\t\tXC_exchange},\n    {\"fleur\",\t\t\tXC_fleur},\n    {\"gobbler\",\t\t\tXC_gobbler},\n    {\"gumby\",\t\t\tXC_gumby},\n    {\"hand1\",\t\t\tXC_hand1},\n    {\"hand2\",\t\t\tXC_hand2},\n    {\"heart\",\t\t\tXC_heart},\n    {\"icon\",\t\t\tXC_icon},\n    {\"iron_cross\",\t\tXC_iron_cross},\n    {\"left_ptr\",\t\tXC_left_ptr},\n    {\"left_side\",\t\tXC_left_side},\n    {\"left_tee\",\t\tXC_left_tee},\n    {\"leftbutton\",\t\tXC_leftbutton},\n    {\"ll_angle\",\t\tXC_ll_angle},\n    {\"lr_angle\",\t\tXC_lr_angle},\n    {\"man\",\t\t\tXC_man},\n    {\"middlebutton\",\t\tXC_middlebutton},\n    {\"mouse\",\t\t\tXC_mouse},\n    {\"pencil\",\t\t\tXC_pencil},\n    {\"pirate\",\t\t\tXC_pirate},\n    {\"plus\",\t\t\tXC_plus},\n    {\"question_arrow\",\t\tXC_question_arrow},\n    {\"right_ptr\",\t\tXC_right_ptr},\n    {\"right_side\",\t\tXC_right_side},\n    {\"right_tee\",\t\tXC_right_tee},\n    {\"rightbutton\",\t\tXC_rightbutton},\n    {\"rtl_logo\",\t\tXC_rtl_logo},\n    {\"sailboat\",\t\tXC_sailboat},\n    {\"sb_down_arrow\",\t\tXC_sb_down_arrow},\n    {\"sb_h_double_arrow\",\tXC_sb_h_double_arrow},\n    {\"sb_left_arrow\",\t\tXC_sb_left_arrow},\n    {\"sb_right_arrow\",\t\tXC_sb_right_arrow},\n    {\"sb_up_arrow\",\t\tXC_sb_up_arrow},\n    {\"sb_v_double_arrow\",\tXC_sb_v_double_arrow},\n    {\"shuttle\",\t\t\tXC_shuttle},\n    {\"sizing\",\t\t\tXC_sizing},\n    {\"spider\",\t\t\tXC_spider},\n    {\"spraycan\",\t\tXC_spraycan},\n    {\"star\",\t\t\tXC_star},\n    {\"target\",\t\t\tXC_target},\n    {\"tcross\",\t\t\tXC_tcross},\n    {\"top_left_arrow\",\t\tXC_top_left_arrow},\n    {\"top_left_corner\",\t\tXC_top_left_corner},\n    {\"top_right_corner\",\tXC_top_right_corner},\n    {\"top_side\",\t\tXC_top_side},\n    {\"top_tee\",\t\t\tXC_top_tee},\n    {\"trek\",\t\t\tXC_trek},\n    {\"ul_angle\",\t\tXC_ul_angle},\n    {\"umbrella\",\t\tXC_umbrella},\n    {\"ur_angle\",\t\tXC_ur_angle},\n    {\"watch\",\t\t\tXC_watch},\n    {\"xterm\",\t\t\tXC_xterm},\n    {NULL,\t\t\t0}\n};\n\n/*\n * The table below is used to map from a cursor name to the data that defines\n * the cursor. This table is used for cursors defined by Tk that don't exist\n * in the X cursor table.\n */\n\n#define CURSOR_NONE_DATA \\\n\"#define none_width 1\\n\" \\\n\"#define none_height 1\\n\" \\\n\"#define none_x_hot 0\\n\" \\\n\"#define none_y_hot 0\\n\" \\\n\"static unsigned char none_bits[] = {\\n\" \\\n\"  0x00};\"\n\n/*\n * Define test cursor to check that mask fg and bg color settings are working.\n *\n * . configure -cursor {center_ptr green red}\n * . configure -cursor {@myarrow.xbm myarrow-mask.xbm green red}\n * . configure -cursor {myarrow green red}\n */\n\n/*#define DEFINE_MYARROW_CURSOR*/\n\n#ifdef DEFINE_MYARROW_CURSOR\n#define CURSOR_MYARROW_DATA \\\n\"#define myarrow_width 16\\n\" \\\n\"#define myarrow_height 16\\n\" \\\n\"#define myarrow_x_hot 7\\n\" \\\n\"#define myarrow_y_hot 0\\n\" \\\n\"static unsigned char myarrow_bits[] = {\\n\" \\\n\"   0x7f, 0xff, 0xbf, 0xfe, 0xdf, 0xfd, 0xef, 0xfb, 0xf7, 0xf7, 0xfb, 0xef,\\n\" \\\n\"   0xfd, 0xdf, 0xfe, 0xbf, 0x80, 0x00, 0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe,\\n\" \\\n\"   0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe, 0x3f, 0xfe};\"\n\n#define CURSOR_MYARROW_MASK \\\n\"#define myarrow-mask_width 16\\n\" \\\n\"#define myarrow-mask_height 16\\n\" \\\n\"#define myarrow-mask_x_hot 7\\n\" \\\n\"#define myarrow-mask_y_hot 0\\n\" \\\n\"static unsigned char myarrow-mask_bits[] = {\\n\" \\\n\"   0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, 0x1f,\\n\" \\\n\"   0xfe, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,\\n\" \\\n\"   0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};\"\n\n#endif /* DEFINE_MYARROW_CURSOR */\n\nstatic const struct TkCursorName {\n    const char *name;\n    const char *data;\n    char *mask;\n} tkCursorNames[] = {\n    {\"none\",\tCURSOR_NONE_DATA,\tNULL},\n#ifdef DEFINE_MYARROW_CURSOR\n    {\"myarrow\",\tCURSOR_MYARROW_DATA,\tCURSOR_MYARROW_MASK},\n#endif /* DEFINE_MYARROW_CURSOR */\n    {NULL,\tNULL,\t\t\tNULL}\n};\n\n/*\n * Font to use for cursors:\n */\n\n#ifndef CURSORFONT\n#define CURSORFONT \"cursor\"\n#endif\n\nstatic Cursor\t\tCreateCursorFromTableOrFile(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, Tcl_Size argc, const char **argv,\n\t\t\t    const struct TkCursorName *tkCursorPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetCursorByName --\n *\n *\tRetrieve a cursor by name. Parse the cursor name into fields and\n *\tcreate a cursor, either from the standard cursor font or from bitmap\n *\tfiles.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkGetCursorByName(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *string)\t\t/* Description of cursor. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    TkUnixCursor *cursorPtr = NULL;\n    Cursor cursor = None;\n    Tcl_Size argc;\n    const char **argv = NULL;\n    Display *display = Tk_Display(tkwin);\n    int inTkTable = 0;\n    const struct TkCursorName *tkCursorPtr = NULL;\n\n    if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {\n\treturn NULL;\n    }\n    if (argc == 0) {\n\tgoto badString;\n    }\n\n    /*\n     * Check Tk specific table of cursor names. The cursor names don't overlap\n     * with cursors defined in the X table so search order does not matter.\n     */\n\n    if (argv[0][0] != '@') {\n\tfor (tkCursorPtr = tkCursorNames; ; tkCursorPtr++) {\n\t    if (tkCursorPtr->name == NULL) {\n\t\ttkCursorPtr = NULL;\n\t\tbreak;\n\t    }\n\t    if ((tkCursorPtr->name[0] == argv[0][0]) &&\n\t\t    (strcmp(tkCursorPtr->name, argv[0]) == 0)) {\n\t\tinTkTable = 1;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    if ((argv[0][0] != '@') && !inTkTable) {\n\tXColor fg, bg;\n\tunsigned int maskIndex;\n\tconst struct CursorName *namePtr;\n\tTkDisplay *dispPtr;\n\n\t/*\n\t * The cursor is to come from the standard cursor font. If one arg, it\n\t * is cursor name (use black and white for fg and bg). If two args,\n\t * they are name and fg color (ignore mask). If three args, they are\n\t * name, fg, bg. Some of the code below is stolen from the\n\t * XCreateFontCursor Xlib function.\n\t */\n\n\tif (argc > 3) {\n\t    goto badString;\n\t}\n\tfor (namePtr = cursorNames; ; namePtr++) {\n\t    if (namePtr->name == NULL) {\n\t\tgoto badString;\n\t    }\n\t    if ((namePtr->name[0] == argv[0][0])\n\t\t    && (strcmp(namePtr->name, argv[0]) == 0)) {\n\t\tbreak;\n\t    }\n\t}\n\n\tmaskIndex = namePtr->shape + 1;\n\tif (argc == 1) {\n\t    fg.red = fg.green = fg.blue = 0;\n\t    bg.red = bg.green = bg.blue = 65535;\n\t} else {\n\t    if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"invalid color name \\\"%s\\\"\", argv[1]));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\t\tgoto cleanup;\n\t    }\n\t    if (argc == 2) {\n\t\tbg.red = bg.green = bg.blue = 0;\n\t\tmaskIndex = namePtr->shape;\n\t    } else if (TkParseColor(display, Tk_Colormap(tkwin), argv[2],\n\t\t    &bg) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"invalid color name \\\"%s\\\"\", argv[2]));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\t\tgoto cleanup;\n\t    }\n\t}\n\tdispPtr = ((TkWindow *) tkwin)->dispPtr;\n\tif (dispPtr->cursorFont == None) {\n\t    dispPtr->cursorFont = XLoadFont(display, CURSORFONT);\n\t    if (dispPtr->cursorFont == None) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't load cursor font\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"FONT\", (char *)NULL);\n\t\tgoto cleanup;\n\t    }\n\t}\n\tcursor = XCreateGlyphCursor(display, dispPtr->cursorFont,\n\t\tdispPtr->cursorFont, namePtr->shape, maskIndex,\n\t\t&fg, &bg);\n    } else {\n\t/*\n\t * Prevent file system access in safe interpreters.\n\t */\n\n\tif (!inTkTable && Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"cannot get cursor from a file in a safe interpreter\",\n\t\t    TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"CURSOR_FILE\", (char *)NULL);\n\t    cursorPtr = NULL;\n\t    goto cleanup;\n\t}\n\n\t/*\n\t * If the cursor is to be created from bitmap files, then there should\n\t * be either two elements in the list (source, color) or four (source\n\t * mask fg bg). A cursor defined in the Tk table accepts the same\n\t * arguments as an X cursor.\n\t */\n\n\tif (inTkTable && (argc != 1) && (argc != 2) && (argc != 3)) {\n\t    goto badString;\n\t}\n\n\tif (!inTkTable && (argc != 2) && (argc != 4)) {\n\t    goto badString;\n\t}\n\n\tcursor = CreateCursorFromTableOrFile(interp, tkwin, argc, argv,\n\t\ttkCursorPtr);\n    }\n\n    if (cursor != None) {\n\tcursorPtr = (TkUnixCursor *)Tcl_Alloc(sizeof(TkUnixCursor));\n\tcursorPtr->info.cursor = (Tk_Cursor) cursor;\n\tcursorPtr->display = display;\n    }\n\n  cleanup:\n    if (argv != NULL) {\n\tTcl_Free(argv);\n    }\n    return (TkCursor *) cursorPtr;\n\n  badString:\n    if (argv) {\n\tTcl_Free(argv);\n    }\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"bad cursor spec \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CURSOR\", (char *)NULL);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateCursorFromTableOrFile --\n *\n *\tCreate a cursor defined in a file or the Tk static cursor table. A\n *\tcursor defined in a file starts with the '@' character. This method\n *\tassumes that the number of arguments in argv has been validated\n *\talready.\n *\n * Results:\n *\tReturns a new cursor, or None on error.\n *\n * Side effects:\n *\tAllocates a new X cursor.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Cursor\nCreateCursorFromTableOrFile(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    Tcl_Size argc,\n    const char **argv,\t\t/* Cursor spec parsed into elements. */\n    const struct TkCursorName *tkCursorPtr)\n\t\t\t\t/* Non-NULL when cursor is defined in Tk\n\t\t\t\t * table. */\n{\n    Cursor cursor = None;\n\n    int width, height, maskWidth, maskHeight;\n    int xHot = -1, yHot = -1;\n    int dummy1, dummy2;\n    XColor fg, bg;\n    const char *fgColor;\n    const char *bgColor;\n    int inTkTable = (tkCursorPtr != NULL);\n\n    Display *display = Tk_Display(tkwin);\n    Drawable drawable = RootWindowOfScreen(Tk_Screen(tkwin));\n\n    Pixmap source = None;\n    Pixmap mask = None;\n\n    /*\n     * A cursor defined in a file accepts either 2 or 4 arguments.\n     *\n     * {srcfile fg}\n     * {srcfile maskfile fg bg}\n     *\n     * A cursor defined in the Tk table accepts 1, 2, or 3 arguments.\n     *\n     * {tkcursorname}\n     * {tkcursorname fg}\n     * {tkcursorname fg bg}\n     */\n\n    if (inTkTable) {\n\t/*\n\t * This logic is like TkReadBitmapFile().\n\t */\n\n\tchar *data;\n\n\tdata = TkGetBitmapData(NULL, tkCursorPtr->data, NULL,\n\t\t&width, &height, &xHot, &yHot);\n\tif (data == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error reading bitmap data for \\\"%s\\\"\", argv[0]));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"BITMAP_DATA\", (char *)NULL);\n\t    goto cleanup;\n\t}\n\n\tsource = XCreateBitmapFromData(display, drawable, data, (unsigned)width, (unsigned)height);\n\tTcl_Free(data);\n    } else {\n\tif (TkReadBitmapFile(display, drawable, &argv[0][1],\n\t\t(unsigned *) &width, (unsigned *) &height,\n\t\t&source, &xHot, &yHot) != BitmapSuccess) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"cleanup reading bitmap file \\\"%s\\\"\", &argv[0][1]));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"BITMAP_FILE\", (char *)NULL);\n\t    goto cleanup;\n\t}\n    }\n\n    if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) {\n\tif (inTkTable) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad hot spot in bitmap data for \\\"%s\\\"\", argv[0]));\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad hot spot in bitmap file \\\"%s\\\"\", &argv[0][1]));\n\t}\n\tTcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"HOTSPOT\", (char *)NULL);\n\tgoto cleanup;\n    }\n\n    /*\n     * Parse color names from optional fg and bg arguments\n     */\n\n    if (argc == 1) {\n\tfg.red = fg.green = fg.blue = 0;\n\tbg.red = bg.green = bg.blue = 65535;\n    } else if (argc == 2) {\n\tfgColor = argv[1];\n\tif (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"invalid color name \\\"%s\\\"\", fgColor));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\t    goto cleanup;\n\t}\n\tif (inTkTable) {\n\t    bg.red = bg.green = bg.blue = 0;\n\t} else {\n\t    bg = fg;\n\t}\n    } else {\n\t/* 3 or 4 arguments */\n\tif (inTkTable) {\n\t    fgColor = argv[1];\n\t    bgColor = argv[2];\n\t} else {\n\t    fgColor = argv[2];\n\t    bgColor = argv[3];\n\t}\n\tif (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"invalid color name \\\"%s\\\"\", fgColor));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\t    goto cleanup;\n\t}\n\tif (TkParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"invalid color name \\\"%s\\\"\", bgColor));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"COLOR\", (char *)NULL);\n\t    goto cleanup;\n\t}\n    }\n\n    /*\n     * If there is no mask data, then create the cursor now.\n     */\n\n    if ((!inTkTable && (argc == 2)) || (inTkTable && tkCursorPtr->mask == NULL)) {\n\tcursor = XCreatePixmapCursor(display, source, source,\n\t\t&fg, &fg, (unsigned) xHot, (unsigned) yHot);\n\tgoto cleanup;\n    }\n\n    /*\n     * Parse bitmap mask data and create cursor with fg and bg colors.\n     */\n\n    if (inTkTable) {\n\t/*\n\t * This logic is like TkReadBitmapFile().\n\t */\n\n\tchar *data;\n\n\tdata = TkGetBitmapData(NULL, tkCursorPtr->mask, NULL,\n\t\t&maskWidth, &maskHeight, &dummy1, &dummy2);\n\tif (data == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error reading bitmap mask data for \\\"%s\\\"\", argv[0]));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"MASK_DATA\", (char *)NULL);\n\t    goto cleanup;\n\t}\n\n\tmask = XCreateBitmapFromData(display, drawable, data, (unsigned)maskWidth,\n\t\t(unsigned)maskHeight);\n\n\tTcl_Free(data);\n    } else {\n\tif (TkReadBitmapFile(display, drawable, argv[1],\n\t\t(unsigned int *) &maskWidth, (unsigned int *) &maskHeight,\n\t\t&mask, &dummy1, &dummy2) != BitmapSuccess) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"cleanup reading bitmap file \\\"%s\\\"\", argv[1]));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"MASK_FILE\", (char *)NULL);\n\t    goto cleanup;\n\t}\n    }\n\n    if ((maskWidth != width) || (maskHeight != height)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"source and mask bitmaps have different sizes\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"CURSOR\", \"SIZE_MATCH\", (char *)NULL);\n\tgoto cleanup;\n    }\n\n    cursor = XCreatePixmapCursor(display, source, mask,\n\t    &fg, &bg, (unsigned) xHot, (unsigned) yHot);\n\n  cleanup:\n    if (source != None) {\n\tTk_FreePixmap(display, source);\n    }\n    if (mask != None) {\n\tTk_FreePixmap(display, mask);\n    }\n    return cursor;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateCursorFromData --\n *\n *\tCreates a cursor from the source and mask bits.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkCreateCursorFromData(\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *source,\t\t/* Bitmap data for cursor shape. */\n    const char *mask,\t\t/* Bitmap data for cursor mask. */\n    int width, int height,\t/* Dimensions of cursor. */\n    int xHot, int yHot,\t\t/* Location of hot-spot in cursor. */\n    XColor fgColor,\t\t/* Foreground color for cursor. */\n    XColor bgColor)\t\t/* Background color for cursor. */\n{\n    Cursor cursor;\n    Pixmap sourcePixmap, maskPixmap;\n    TkUnixCursor *cursorPtr = NULL;\n    Display *display = Tk_Display(tkwin);\n\n    sourcePixmap = XCreateBitmapFromData(display,\n\t    RootWindowOfScreen(Tk_Screen(tkwin)), source, (unsigned) width,\n\t    (unsigned) height);\n    maskPixmap = XCreateBitmapFromData(display,\n\t    RootWindowOfScreen(Tk_Screen(tkwin)), mask, (unsigned) width,\n\t    (unsigned) height);\n    cursor = XCreatePixmapCursor(display, sourcePixmap,\n\t    maskPixmap, &fgColor, &bgColor, (unsigned) xHot, (unsigned) yHot);\n    Tk_FreePixmap(display, sourcePixmap);\n    Tk_FreePixmap(display, maskPixmap);\n\n    if (cursor != None) {\n\tcursorPtr = (TkUnixCursor *)Tcl_Alloc(sizeof(TkUnixCursor));\n\tcursorPtr->info.cursor = (Tk_Cursor) cursor;\n\tcursorPtr->display = display;\n    }\n    return (TkCursor *) cursorPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeCursor --\n *\n *\tThis function is called to release a cursor allocated by\n *\tTkGetCursorByName.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor data structure is deallocated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeCursor(\n    TkCursor *cursorPtr)\n{\n    TkUnixCursor *unixCursorPtr = (TkUnixCursor *) cursorPtr;\n\n    XFreeCursor(unixCursorPtr->display, (Cursor) unixCursorPtr->info.cursor);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixDefault.h",
    "content": "/*\n * tkUnixDefault.h --\n *\n *\tThis file defines the defaults for all options for all of\n *\tthe Tk widgets.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKUNIXDEFAULT\n#define _TKUNIXDEFAULT\n\n/*\n * The definitions below provide symbolic names for the default colors.\n * NORMAL_BG -\t\tNormal background color.\n * ACTIVE_BG -\t\tBackground color when widget is active.\n * SELECT_BG -\t\tBackground color for selected text.\n * TROUGH -\t\tBackground color for troughs in scales and scrollbars.\n * INDICATOR -\t\tColor for indicator when button is selected.\n * DISABLED -\t\tForeground color when widget is disabled.\n * PLACEHOLDER_FG -\tForeground color for placeholder text.\n */\n\n#define BLACK\t\t\"#000000\"\n#define WHITE\t\t\"#ffffff\"\n\n#define NORMAL_BG\t\"#d9d9d9\"\n#define ACTIVE_BG\t\"#ececec\"\n#define SELECT_BG\t\"#c3c3c3\"\n#define TROUGH\t\t\"#b3b3b3\"\n#define INDICATOR\tWHITE\n#define DISABLED\t\"#a3a3a3\"\n#define PLACEHOLDER_FG\t\"#b3b3b3\"\t/* grey70 */\n\n/*\n * Defaults for labels, buttons, checkbuttons, and radiobuttons:\n */\n\n#define DEF_BUTTON_ANCHOR\t\t\"center\"\n#define DEF_BUTTON_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_BUTTON_ACTIVE_BG_MONO\tBLACK\n#define DEF_BUTTON_ACTIVE_FG_COLOR\tBLACK\n#define DEF_CHKRAD_ACTIVE_FG_COLOR\tDEF_BUTTON_ACTIVE_FG_COLOR\n#define DEF_BUTTON_ACTIVE_FG_MONO\tWHITE\n#define DEF_BUTTON_BG_COLOR\t\tNORMAL_BG\n#define DEF_BUTTON_BG_MONO\t\tWHITE\n#define DEF_BUTTON_BITMAP\t\t\"\"\n#define DEF_BUTTON_BORDER_WIDTH\t\t\"1\"\n#define DEF_BUTTON_CURSOR\t\t\"\"\n#define DEF_BUTTON_COMPOUND\t\t\"none\"\n#define DEF_BUTTON_COMMAND\t\t\"\"\n#define DEF_BUTTON_DEFAULT\t\t\"disabled\"\n#define DEF_BUTTON_DISABLED_FG_COLOR\tDISABLED\n#define DEF_BUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_LABEL_FG\t\t\tBLACK\n#define DEF_BUTTON_FG\t\t\tBLACK\n#define DEF_CHKRAD_FG\t\t\tDEF_BUTTON_FG\n#define DEF_BUTTON_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_BUTTON_HEIGHT\t\t\"0\"\n#define DEF_BUTTON_HIGHLIGHT_BG_COLOR\tDEF_BUTTON_BG_COLOR\n#define DEF_BUTTON_HIGHLIGHT_BG_MONO\tDEF_BUTTON_BG_MONO\n#define DEF_BUTTON_HIGHLIGHT\t\tBLACK\n#define DEF_LABEL_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_BUTTON_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_BUTTON_IMAGE\t\tNULL\n#define DEF_BUTTON_INDICATOR\t\t\"1\"\n#define DEF_BUTTON_JUSTIFY\t\t\"center\"\n#define DEF_BUTTON_OFF_VALUE\t\t\"0\"\n#define DEF_BUTTON_ON_VALUE\t\t\"1\"\n#define DEF_BUTTON_TRISTATE_VALUE\t\"\"\n#define DEF_BUTTON_OVER_RELIEF\t\t\"\"\n#define DEF_BUTTON_PADX\t\t\t\"3m\"\n#define DEF_LABCHKRAD_PADX\t\t\"1\"\n#define DEF_BUTTON_PADY\t\t\t\"1m\"\n#define DEF_LABCHKRAD_PADY\t\t\"1\"\n#define DEF_BUTTON_RELIEF\t\t\"raised\"\n#define DEF_LABCHKRAD_RELIEF\t\t\"flat\"\n#define DEF_BUTTON_REPEAT_DELAY\t\t\"0\"\n#define DEF_BUTTON_REPEAT_INTERVAL\t\"0\"\n#define DEF_BUTTON_SELECT_COLOR\t\tINDICATOR\n#define DEF_BUTTON_SELECT_MONO\t\tBLACK\n#define DEF_BUTTON_SELECT_IMAGE\t\tNULL\n#define DEF_BUTTON_STATE\t\t\"normal\"\n#define DEF_LABEL_TAKE_FOCUS\t\t\"0\"\n#define DEF_BUTTON_TAKE_FOCUS\t\tNULL\n#define DEF_BUTTON_TEXT\t\t\t\"\"\n#define DEF_BUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_BUTTON_VALUE\t\t\"\"\n#define DEF_BUTTON_WIDTH\t\t\"0\"\n#define DEF_BUTTON_WRAP_LENGTH\t\t\"0\"\n#define DEF_RADIOBUTTON_VARIABLE\t\"selectedButton\"\n#define DEF_CHECKBUTTON_VARIABLE\t\"\"\n\n/*\n * Defaults for canvases:\n */\n\n#define DEF_CANVAS_BG_COLOR\t\tNORMAL_BG\n#define DEF_CANVAS_BG_MONO\t\tWHITE\n#define DEF_CANVAS_BORDER_WIDTH\t\t\"0\"\n#define DEF_CANVAS_CLOSE_ENOUGH\t\t\"1\"\n#define DEF_CANVAS_CONFINE\t\t\"1\"\n#define DEF_CANVAS_CURSOR\t\t\"\"\n#define DEF_CANVAS_HEIGHT\t\t\"7c\"\n#define DEF_CANVAS_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_CANVAS_HIGHLIGHT\t\tBLACK\n#define DEF_CANVAS_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_CANVAS_INSERT_BG\t\tBLACK\n#define DEF_CANVAS_INSERT_BD_COLOR\t\"0\"\n#define DEF_CANVAS_INSERT_BD_MONO\t\"0\"\n#define DEF_CANVAS_INSERT_OFF_TIME\t\"300\"\n#define DEF_CANVAS_INSERT_ON_TIME\t\"600\"\n#define DEF_CANVAS_INSERT_WIDTH\t\t\"2\"\n#define DEF_CANVAS_RELIEF\t\t\"flat\"\n#define DEF_CANVAS_SCROLL_REGION\t\"\"\n#define DEF_CANVAS_SELECT_COLOR\t\tSELECT_BG\n#define DEF_CANVAS_SELECT_MONO\t\tBLACK\n#define DEF_CANVAS_SELECT_BD_COLOR\t\"1\"\n#define DEF_CANVAS_SELECT_BD_MONO\t\"0\"\n#define DEF_CANVAS_SELECT_FG_COLOR\tBLACK\n#define DEF_CANVAS_SELECT_FG_MONO\tWHITE\n#define DEF_CANVAS_TAKE_FOCUS\t\tNULL\n#define DEF_CANVAS_WIDTH\t\t\"10c\"\n#define DEF_CANVAS_X_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_X_SCROLL_INCREMENT\t\"0\"\n#define DEF_CANVAS_Y_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_Y_SCROLL_INCREMENT\t\"0\"\n\n/*\n * Defaults for entries:\n */\n\n#define DEF_ENTRY_BG_COLOR\t\tWHITE\n#define DEF_ENTRY_BG_MONO\t\tWHITE\n#define DEF_ENTRY_BORDER_WIDTH\t\t\"1\"\n#define DEF_ENTRY_CURSOR\t\t\"xterm\"\n#define DEF_ENTRY_DISABLED_BG_COLOR\tNORMAL_BG\n#define DEF_ENTRY_DISABLED_BG_MONO\tWHITE\n#define DEF_ENTRY_DISABLED_FG\t\tDISABLED\n#define DEF_ENTRY_EXPORT_SELECTION\t\"1\"\n#define DEF_ENTRY_FONT\t\t\t\"TkTextFont\"\n#define DEF_ENTRY_FG\t\t\tBLACK\n#define DEF_ENTRY_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_ENTRY_HIGHLIGHT\t\tBLACK\n#define DEF_ENTRY_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_ENTRY_INSERT_BG\t\tBLACK\n#define DEF_ENTRY_INSERT_BD_COLOR\t\"0\"\n#define DEF_ENTRY_INSERT_BD_MONO\t\"0\"\n#define DEF_ENTRY_INSERT_OFF_TIME\t\"300\"\n#define DEF_ENTRY_INSERT_ON_TIME\t\"600\"\n#define DEF_ENTRY_INSERT_WIDTH\t\t\"2\"\n#define DEF_ENTRY_JUSTIFY\t\t\"left\"\n#define DEF_ENTRY_PLACEHOLDER\t\t\"\"\n#define DEF_ENTRY_PLACEHOLDERFG\t\tPLACEHOLDER_FG\n#define DEF_ENTRY_READONLY_BG_COLOR\tNORMAL_BG\n#define DEF_ENTRY_READONLY_BG_MONO\tWHITE\n#define DEF_ENTRY_RELIEF\t\t\"sunken\"\n#define DEF_ENTRY_SCROLL_COMMAND\t\"\"\n#define DEF_ENTRY_SELECT_COLOR\t\tSELECT_BG\n#define DEF_ENTRY_SELECT_MONO\t\tBLACK\n#define DEF_ENTRY_SELECT_BD_COLOR\t\"0\"\n#define DEF_ENTRY_SELECT_BD_MONO\t\"0\"\n#define DEF_ENTRY_SELECT_FG_COLOR\tBLACK\n#define DEF_ENTRY_SELECT_FG_MONO\tWHITE\n#define DEF_ENTRY_SHOW\t\t\tNULL\n#define DEF_ENTRY_STATE\t\t\t\"normal\"\n#define DEF_ENTRY_TAKE_FOCUS\t\tNULL\n#define DEF_ENTRY_TEXT_VARIABLE\t\t\"\"\n#define DEF_ENTRY_WIDTH\t\t\t\"20\"\n\n/*\n * Defaults for frames:\n */\n\n#define DEF_FRAME_BG_COLOR\t\tNORMAL_BG\n#define DEF_FRAME_BG_IMAGE\t\tNULL\n#define DEF_FRAME_BG_MONO\t\tWHITE\n#define DEF_FRAME_BG_TILE\t\t\"0\"\n#define DEF_FRAME_BORDER_WIDTH\t\t\"0\"\n#define DEF_FRAME_CLASS\t\t\t\"Frame\"\n#define DEF_FRAME_COLORMAP\t\t\"\"\n#define DEF_FRAME_CONTAINER\t\t\"0\"\n#define DEF_FRAME_CURSOR\t\t\"\"\n#define DEF_FRAME_HEIGHT\t\t\"0\"\n#define DEF_FRAME_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_FRAME_HIGHLIGHT\t\tBLACK\n#define DEF_FRAME_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_FRAME_LABEL\t\t\t\"\"\n#define DEF_FRAME_PADX\t\t\t\"0\"\n#define DEF_FRAME_PADY\t\t\t\"0\"\n#define DEF_FRAME_RELIEF\t\t\"flat\"\n#define DEF_FRAME_TAKE_FOCUS\t\t\"0\"\n#define DEF_FRAME_VISUAL\t\t\"\"\n#define DEF_FRAME_WIDTH\t\t\t\"0\"\n\n/*\n * Defaults for labelframes:\n */\n\n#define DEF_LABELFRAME_BORDER_WIDTH\t\"2\"\n#define DEF_LABELFRAME_CLASS\t\t\"Labelframe\"\n#define DEF_LABELFRAME_RELIEF\t\t\"groove\"\n#define DEF_LABELFRAME_FG\t\tBLACK\n#define DEF_LABELFRAME_FONT\t\t\"TkDefaultFont\"\n#define DEF_LABELFRAME_TEXT\t\t\"\"\n#define DEF_LABELFRAME_LABELANCHOR\t\"nw\"\n\n/*\n * Defaults for listboxes:\n */\n\n#define DEF_LISTBOX_ACTIVE_STYLE\t\"dotbox\"\n#define DEF_LISTBOX_BG_COLOR\t\tWHITE\n#define DEF_LISTBOX_BG_MONO\t\tWHITE\n#define DEF_LISTBOX_BORDER_WIDTH\t\"1\"\n#define DEF_LISTBOX_CURSOR\t\t\"\"\n#define DEF_LISTBOX_DISABLED_FG\t\tDISABLED\n#define DEF_LISTBOX_EXPORT_SELECTION\t\"1\"\n#define DEF_LISTBOX_FONT\t\t\"TkDefaultFont\"\n#define DEF_LISTBOX_FG\t\t\tBLACK\n#define DEF_LISTBOX_HEIGHT\t\t\"10\"\n#define DEF_LISTBOX_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_LISTBOX_HIGHLIGHT\t\tBLACK\n#define DEF_LISTBOX_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_LISTBOX_JUSTIFY\t\t\"left\"\n#define DEF_LISTBOX_RELIEF\t\t\"sunken\"\n#define DEF_LISTBOX_SCROLL_COMMAND\t\"\"\n#define DEF_LISTBOX_LIST_VARIABLE\t\"\"\n#define DEF_LISTBOX_INACTIVE_SELECT_COLOR\tNULL\n#define DEF_LISTBOX_SELECT_COLOR\tSELECT_BG\n#define DEF_LISTBOX_SELECT_MONO\t\tBLACK\n#define DEF_LISTBOX_SELECT_BD\t\t\"0\"\n#define DEF_LISTBOX_INACTIVE_SELECT_FG_COLOR\tNULL\n#define DEF_LISTBOX_SELECT_FG_COLOR\tBLACK\n#define DEF_LISTBOX_SELECT_FG_MONO\tWHITE\n#define DEF_LISTBOX_SELECT_MODE\t\t\"browse\"\n#define DEF_LISTBOX_SET_GRID\t\t\"0\"\n#define DEF_LISTBOX_STATE\t\t\"normal\"\n#define DEF_LISTBOX_TAKE_FOCUS\t\tNULL\n#define DEF_LISTBOX_WIDTH\t\t\"20\"\n\n/*\n * Defaults for individual entries of menus:\n */\n\n#define DEF_MENU_ENTRY_ACTIVE_BG\tNULL\n#define DEF_MENU_ENTRY_ACTIVE_FG\tNULL\n#define DEF_MENU_ENTRY_ACCELERATOR\tNULL\n#define DEF_MENU_ENTRY_BG\t\tNULL\n#define DEF_MENU_ENTRY_BITMAP\t\tNULL\n#define DEF_MENU_ENTRY_COLUMN_BREAK\t\"0\"\n#define DEF_MENU_ENTRY_COMMAND\t\tNULL\n#define DEF_MENU_ENTRY_COMPOUND\t\"none\"\n#define DEF_MENU_ENTRY_FG\t\tNULL\n#define DEF_MENU_ENTRY_FONT\t\tNULL\n#define DEF_MENU_ENTRY_HIDE_MARGIN\t\"0\"\n#define DEF_MENU_ENTRY_IMAGE\t\tNULL\n#define DEF_MENU_ENTRY_INDICATOR\t\"1\"\n#define DEF_MENU_ENTRY_LABEL\t\tNULL\n#define DEF_MENU_ENTRY_MENU\t\tNULL\n#define DEF_MENU_ENTRY_OFF_VALUE\t\"0\"\n#define DEF_MENU_ENTRY_ON_VALUE\t\t\"1\"\n#define DEF_MENU_ENTRY_SELECT_IMAGE\tNULL\n#define DEF_MENU_ENTRY_STATE\t\t\"normal\"\n#define DEF_MENU_ENTRY_VALUE\t\tNULL\n#define DEF_MENU_ENTRY_CHECK_VARIABLE\tNULL\n#define DEF_MENU_ENTRY_RADIO_VARIABLE\t\"selectedButton\"\n#define DEF_MENU_ENTRY_SELECT\t\tNULL\n\n/*\n * Defaults for menus overall:\n */\n\n#define DEF_MENU_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_MENU_ACTIVE_BG_MONO\t\tBLACK\n#define DEF_MENU_ACTIVE_BORDER_WIDTH\t\"1\"\n#define DEF_MENU_ACTIVE_FG_COLOR\tBLACK\n#define DEF_MENU_ACTIVE_FG_MONO\t\tWHITE\n#define DEF_MENU_ACTIVE_RELIEF\t\t\"raised\"\n#define DEF_MENU_BG_COLOR\t\tNORMAL_BG\n#define DEF_MENU_BG_MONO\t\tWHITE\n#define DEF_MENU_BORDER_WIDTH\t\t\"1\"\n#define DEF_MENU_CURSOR\t\t\t\"arrow\"\n#define DEF_MENU_DISABLED_FG_COLOR\tDISABLED\n#define DEF_MENU_DISABLED_FG_MONO\t\"\"\n#define DEF_MENU_FONT\t\t\t\"TkMenuFont\"\n#define DEF_MENU_FG\t\t\tBLACK\n#define DEF_MENU_POST_COMMAND\t\t\"\"\n#define DEF_MENU_RELIEF\t\t\t\"raised\"\n#define DEF_MENU_SELECT_COLOR\t\tBLACK\n#define DEF_MENU_SELECT_MONO\t\tBLACK\n#define DEF_MENU_TAKE_FOCUS\t\t\"0\"\n#define DEF_MENU_TEAROFF\t\t\"0\"\n#define DEF_MENU_TEAROFF_CMD\t\tNULL\n#define DEF_MENU_TITLE\t\t\t\"\"\n#define DEF_MENU_TYPE\t\t\t\"normal\"\n\n/*\n * Defaults for menubuttons:\n */\n\n#define DEF_MENUBUTTON_ANCHOR\t\t\"center\"\n#define DEF_MENUBUTTON_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_MENUBUTTON_ACTIVE_BG_MONO\tBLACK\n#define DEF_MENUBUTTON_ACTIVE_FG_COLOR\tBLACK\n#define DEF_MENUBUTTON_ACTIVE_FG_MONO\tWHITE\n#define DEF_MENUBUTTON_BG_COLOR\t\tNORMAL_BG\n#define DEF_MENUBUTTON_BG_MONO\t\tWHITE\n#define DEF_MENUBUTTON_BITMAP\t\t\"\"\n#define DEF_MENUBUTTON_BORDER_WIDTH\t\"1\"\n#define DEF_MENUBUTTON_CURSOR\t\t\"\"\n#define DEF_MENUBUTTON_DIRECTION\t\"below\"\n#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED\n#define DEF_MENUBUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_MENUBUTTON_FONT\t\t\"TkDefaultFont\"\n#define DEF_MENUBUTTON_FG\t\tBLACK\n#define DEF_MENUBUTTON_HEIGHT\t\t\"0\"\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO  DEF_MENUBUTTON_BG_MONO\n#define DEF_MENUBUTTON_HIGHLIGHT\tBLACK\n#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MENUBUTTON_IMAGE\t\tNULL\n#define DEF_MENUBUTTON_INDICATOR\t\"0\"\n#define DEF_MENUBUTTON_JUSTIFY\t\t\"center\"\n#define DEF_MENUBUTTON_MENU\t\t\"\"\n#define DEF_MENUBUTTON_PADX\t\t\"4p\"\n#define DEF_MENUBUTTON_PADY\t\t\"3p\"\n#define DEF_MENUBUTTON_RELIEF\t\t\"flat\"\n#define DEF_MENUBUTTON_STATE\t\t\"normal\"\n#define DEF_MENUBUTTON_TAKE_FOCUS\t\"0\"\n#define DEF_MENUBUTTON_TEXT\t\t\"\"\n#define DEF_MENUBUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_MENUBUTTON_WIDTH\t\t\"0\"\n#define DEF_MENUBUTTON_WRAP_LENGTH\t\"0\"\n\n/*\n * Defaults for messages:\n */\n\n#define DEF_MESSAGE_ANCHOR\t\t\"center\"\n#define DEF_MESSAGE_ASPECT\t\t\"150\"\n#define DEF_MESSAGE_BG_COLOR\t\tNORMAL_BG\n#define DEF_MESSAGE_BG_MONO\t\tWHITE\n#define DEF_MESSAGE_BORDER_WIDTH\t\"1\"\n#define DEF_MESSAGE_CURSOR\t\t\"\"\n#define DEF_MESSAGE_FG\t\t\tBLACK\n#define DEF_MESSAGE_FONT\t\t\"TkDefaultFont\"\n#define DEF_MESSAGE_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_MESSAGE_HIGHLIGHT\t\tBLACK\n#define DEF_MESSAGE_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MESSAGE_JUSTIFY\t\t\"left\"\n#define DEF_MESSAGE_PADX\t\tNULL\n#define DEF_MESSAGE_PADY\t\tNULL\n#define DEF_MESSAGE_RELIEF\t\t\"flat\"\n#define DEF_MESSAGE_TAKE_FOCUS\t\t\"0\"\n#define DEF_MESSAGE_TEXT\t\t\"\"\n#define DEF_MESSAGE_TEXT_VARIABLE\t\"\"\n#define DEF_MESSAGE_WIDTH\t\t\"0\"\n\n/*\n * Defaults for panedwindows\n */\n\n#define DEF_PANEDWINDOW_BG_COLOR\tNORMAL_BG\n#define DEF_PANEDWINDOW_BG_MONO\t\tWHITE\n#define DEF_PANEDWINDOW_BORDERWIDTH\t\"1\"\n#define DEF_PANEDWINDOW_CURSOR\t\t\"\"\n#define DEF_PANEDWINDOW_HANDLEPAD\t\"8\"\n#define DEF_PANEDWINDOW_HANDLESIZE\t\"8\"\n#define DEF_PANEDWINDOW_HEIGHT\t\t\"\"\n#define DEF_PANEDWINDOW_OPAQUERESIZE\t\"1\"\n#define DEF_PANEDWINDOW_ORIENT\t\t\"horizontal\"\n#define DEF_PANEDWINDOW_PROXYBORDER\t\"2\"\n#define DEF_PANEDWINDOW_RELIEF\t\t\"flat\"\n#define DEF_PANEDWINDOW_SASHCURSOR\t\"\"\n#define DEF_PANEDWINDOW_SASHPAD\t\t\"0\"\n#define DEF_PANEDWINDOW_SASHRELIEF\t\"flat\"\n#define DEF_PANEDWINDOW_SASHWIDTH\t\"3\"\n#define DEF_PANEDWINDOW_SHOWHANDLE\t\"0\"\n#define DEF_PANEDWINDOW_WIDTH\t\t\"\"\n\n/*\n * Defaults for panedwindow panes\n */\n\n#define DEF_PANEDWINDOW_PANE_AFTER\t\"\"\n#define DEF_PANEDWINDOW_PANE_BEFORE\t\"\"\n#define DEF_PANEDWINDOW_PANE_HEIGHT\t\"\"\n#define DEF_PANEDWINDOW_PANE_MINSIZE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADX\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADY\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STICKY\t\"nsew\"\n#define DEF_PANEDWINDOW_PANE_WIDTH\t\"\"\n#define DEF_PANEDWINDOW_PANE_HIDE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STRETCH\t\"last\"\n\n/*\n * Defaults for scales:\n */\n\n#define DEF_SCALE_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCALE_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCALE_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCALE_BG_MONO\t\tWHITE\n#define DEF_SCALE_BIG_INCREMENT\t\t\"0.0\"\n#define DEF_SCALE_BORDER_WIDTH\t\t\"1\"\n#define DEF_SCALE_COMMAND\t\t\"\"\n#define DEF_SCALE_CURSOR\t\t\"\"\n#define DEF_SCALE_DIGITS\t\t\"0\"\n#define DEF_SCALE_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_SCALE_FG_COLOR\t\tBLACK\n#define DEF_SCALE_FG_MONO\t\tBLACK\n#define DEF_SCALE_FROM\t\t\t\"0.0\"\n#define DEF_SCALE_HIGHLIGHT_BG_COLOR\tDEF_SCALE_BG_COLOR\n#define DEF_SCALE_HIGHLIGHT_BG_MONO\tDEF_SCALE_BG_MONO\n#define DEF_SCALE_HIGHLIGHT\t\tBLACK\n#define DEF_SCALE_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_SCALE_LABEL\t\t\t\"\"\n#define DEF_SCALE_LENGTH\t\t\"100\"\n#define DEF_SCALE_ORIENT\t\t\"vertical\"\n#define DEF_SCALE_RELIEF\t\t\"flat\"\n#define DEF_SCALE_REPEAT_DELAY\t\t\"300\"\n#define DEF_SCALE_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCALE_RESOLUTION\t\t\"1.0\"\n#define DEF_SCALE_TROUGH_COLOR\t\tTROUGH\n#define DEF_SCALE_TROUGH_MONO\t\tWHITE\n#define DEF_SCALE_SHOW_VALUE\t\t\"1\"\n#define DEF_SCALE_SLIDER_LENGTH\t\t\"30\"\n#define DEF_SCALE_SLIDER_RELIEF\t\t\"raised\"\n#define DEF_SCALE_STATE\t\t\t\"normal\"\n#define DEF_SCALE_TAKE_FOCUS\t\tNULL\n#define DEF_SCALE_TICK_INTERVAL\t\t\"0.0\"\n#define DEF_SCALE_TO\t\t\t\"100.0\"\n#define DEF_SCALE_VARIABLE\t\t\"\"\n#define DEF_SCALE_WIDTH\t\t\t\"15\"\n\n/*\n * Defaults for scrollbars:\n */\n\n#define DEF_SCROLLBAR_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCROLLBAR_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCROLLBAR_ACTIVE_RELIEF\t\"raised\"\n#define DEF_SCROLLBAR_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCROLLBAR_BG_MONO\t\tWHITE\n#define DEF_SCROLLBAR_BORDER_WIDTH\t\"1\"\n#define DEF_SCROLLBAR_COMMAND\t\t\"\"\n#define DEF_SCROLLBAR_CURSOR\t\t\"\"\n#define DEF_SCROLLBAR_EL_BORDER_WIDTH\tNULL\n#define DEF_SCROLLBAR_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_SCROLLBAR_HIGHLIGHT\t\tBLACK\n#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_SCROLLBAR_JUMP\t\t\"0\"\n#define DEF_SCROLLBAR_ORIENT\t\t\"vertical\"\n#define DEF_SCROLLBAR_RELIEF\t\t\"sunken\"\n#define DEF_SCROLLBAR_REPEAT_DELAY\t\"300\"\n#define DEF_SCROLLBAR_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCROLLBAR_TAKE_FOCUS\tNULL\n#define DEF_SCROLLBAR_TROUGH_COLOR\tTROUGH\n#define DEF_SCROLLBAR_TROUGH_MONO\tWHITE\n#define DEF_SCROLLBAR_WIDTH\t\t\"11\"\n\n/*\n * Defaults for texts:\n */\n\n#define DEF_TEXT_AUTO_SEPARATORS\t\"1\"\n#define DEF_TEXT_BG_COLOR\t\tWHITE\n#define DEF_TEXT_BG_MONO\t\tWHITE\n#define DEF_TEXT_BLOCK_CURSOR\t\t\"0\"\n#define DEF_TEXT_BORDER_WIDTH\t\t\"1\"\n#define DEF_TEXT_CURSOR\t\t\t\"xterm\"\n#define DEF_TEXT_FG\t\t\tBLACK\n#define DEF_TEXT_EXPORT_SELECTION\t\"1\"\n#define DEF_TEXT_FONT\t\t\t\"TkFixedFont\"\n#define DEF_TEXT_HEIGHT\t\t\t\"24\"\n#define DEF_TEXT_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_TEXT_HIGHLIGHT\t\tBLACK\n#define DEF_TEXT_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_TEXT_INSERT_BG\t\tBLACK\n#define DEF_TEXT_INSERT_BD_COLOR\t\"0\"\n#define DEF_TEXT_INSERT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_INSERT_OFF_TIME\t\"300\"\n#define DEF_TEXT_INSERT_ON_TIME\t\t\"600\"\n#define DEF_TEXT_INSERT_UNFOCUSSED\t\"none\"\n#define DEF_TEXT_INSERT_WIDTH\t\t\"2\"\n#define DEF_TEXT_MAX_UNDO\t\t\"0\"\n#define DEF_TEXT_PADX\t\t\t\"1\"\n#define DEF_TEXT_PADY\t\t\t\"1\"\n#define DEF_TEXT_RELIEF\t\t\t\"sunken\"\n#define DEF_TEXT_INACTIVE_SELECT_BG_COLOR\tSELECT_BG\n#define DEF_TEXT_SELECT_COLOR\t\tSELECT_BG\n#define DEF_TEXT_SELECT_MONO\t\tBLACK\n#define DEF_TEXT_SELECT_BD_COLOR\t\"0\"\n#define DEF_TEXT_SELECT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_SELECT_FG_COLOR\tBLACK\n#define DEF_TEXT_SELECT_FG_MONO\t\tWHITE\n#define DEF_TEXT_SELECT_RELIEF\t\t\"raised\"\n#define DEF_TEXT_SET_GRID\t\t\"0\"\n#define DEF_TEXT_SPACING1\t\t\"0\"\n#define DEF_TEXT_SPACING2\t\t\"0\"\n#define DEF_TEXT_SPACING3\t\t\"0\"\n#define DEF_TEXT_STATE\t\t\t\"normal\"\n#define DEF_TEXT_TABS\t\t\t\"\"\n#define DEF_TEXT_TABSTYLE\t\t\"tabular\"\n#define DEF_TEXT_TAKE_FOCUS\t\tNULL\n#define DEF_TEXT_UNDO\t\t\t\"0\"\n#define DEF_TEXT_WIDTH\t\t\t\"80\"\n#define DEF_TEXT_WRAP\t\t\t\"char\"\n#define DEF_TEXT_XSCROLL_COMMAND\t\"\"\n#define DEF_TEXT_YSCROLL_COMMAND\t\"\"\n\n/*\n * Defaults for canvas text:\n */\n\n#define DEF_CANVTEXT_FONT\t\t\"TkDefaultFont\"\n\n/*\n * Defaults for canvas items\n * (arcs, bitmaps, lines, polygons, rectangles, and ovals):\n */\n\n#define DEF_CANVBMAP_FG\t\t\tBLACK\n#define DEF_CANVITEM_OUTLINE\t\tBLACK\n\n/*\n * Defaults for toplevels (most of the defaults for frames also apply\n * to toplevels):\n */\n\n#define DEF_TOPLEVEL_CLASS\t\t\"Toplevel\"\n#define DEF_TOPLEVEL_MENU\t\t\"\"\n#define DEF_TOPLEVEL_SCREEN\t\t\"\"\n#define DEF_TOPLEVEL_USE\t\t\"\"\n\n/*\n * Defaults for busy windows:\n */\n\n#define DEF_BUSY_CURSOR\t\t\t\"watch\"\n\n#endif /* _TKUNIXDEFAULT */\n"
  },
  {
    "path": "unix/tkUnixDraw.c",
    "content": "/*\n * tkUnixDraw.c --\n *\n *\tThis file contains X specific drawing routines.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#ifndef _WIN32\n#include \"tkUnixInt.h\"\n#endif\n\n/*\n * The following structure is used to pass information to ScrollRestrictProc\n * from TkScrollWindow.\n */\n\ntypedef struct ScrollInfo {\n    int done;\t\t\t/* Flag is 0 until filtering is done. */\n    Display *display;\t\t/* Display to filter. */\n    Window window;\t\t/* Window to filter. */\n    Region region;\t\t/* Region into which damage is accumulated. */\n    int dx, dy;\t\t\t/* Amount by which window was shifted. */\n} ScrollInfo;\n\n/*\n * Forward declarations for functions declared later in this file:\n */\n\nstatic Tk_RestrictProc ScrollRestrictProc;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScrollWindow --\n *\n *\tScroll a rectangle of the specified window and accumulate damage\n *\tinformation in the specified Region.\n *\n * Results:\n *\tReturns false if no damage additional damage was generated. Sets damageRgn\n *\tto contain the damaged areas and returns true if GraphicsExpose events\n *\twere detected.\n *\n * Side effects:\n *\tScrolls the bits in the window and enters the event loop looking for\n *\tdamage events.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkScrollWindow(\n    Tk_Window tkwin,\t\t/* The window to be scrolled. */\n    GC gc,\t\t\t/* GC for window to be scrolled. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Position rectangle to be scrolled. */\n    int dx, int dy,\t\t/* Distance rectangle should be moved. */\n    Region damageRgn)\t\t/* Region to accumulate damage in. */\n{\n    Tk_RestrictProc *prevProc;\n    void *prevArg;\n    ScrollInfo info;\n\n    XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,\n\t    x, y, (unsigned) width, (unsigned) height, x+dx, y+dy);\n\n    info.done = 0;\n    info.window = Tk_WindowId(tkwin);\n    info.display = Tk_Display(tkwin);\n    info.region = damageRgn;\n    info.dx = dx;\n    info.dy = dy;\n\n    /*\n     * Sync the event stream so all of the expose events will be on the Tk\n     * event queue before we start filtering. This avoids busy waiting while\n     * we filter events.\n     */\n\n    TkpSync(info.display);\n    prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg);\n    while (!info.done) {\n\tTcl_ServiceEvent(TCL_WINDOW_EVENTS);\n    }\n    Tk_RestrictEvents(prevProc, prevArg, &prevArg);\n\n    return !XEmptyRegion(damageRgn);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScrollRestrictProc --\n *\n *\tA Tk_RestrictProc used by TkScrollWindow to gather up Expose\n *\tinformation into a single damage region. It accumulates damage events\n *\ton the specified window until a NoExpose or the last GraphicsExpose\n *\tevent is detected.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDiscards Expose events after accumulating damage information\n *\tfor a particular window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_RestrictAction\nScrollRestrictProc(\n    void *arg,\n    XEvent *eventPtr)\n{\n    ScrollInfo *info = (ScrollInfo *) arg;\n    XRectangle rect;\n\n    /*\n     * Defer events which aren't for the specified window.\n     */\n\n    if (info->done || (eventPtr->xany.display != info->display)\n\t    || (eventPtr->xany.window != info->window)) {\n\treturn TK_DEFER_EVENT;\n    }\n\n    if (eventPtr->type == NoExpose) {\n\tinfo->done = 1;\n    } else if (eventPtr->type == GraphicsExpose) {\n\trect.x = (short)eventPtr->xgraphicsexpose.x;\n\trect.y = (short)eventPtr->xgraphicsexpose.y;\n\trect.width = (unsigned short)eventPtr->xgraphicsexpose.width;\n\trect.height = (unsigned short)eventPtr->xgraphicsexpose.height;\n\tXUnionRectWithRegion(&rect, info->region,\n\t\tinfo->region);\n\n\tif (eventPtr->xgraphicsexpose.count == 0) {\n\t    info->done = 1;\n\t}\n    } else if (eventPtr->type == Expose) {\n\t/*\n\t * This case is tricky. This event was already queued before the\n\t * XCopyArea was issued. If this area overlaps the area being copied,\n\t * then some of the copied area may be invalid. The easiest way to\n\t * handle this case is to mark both the original area and the shifted\n\t * area as damaged.\n\t */\n\n\trect.x = (short)eventPtr->xexpose.x;\n\trect.y = (short)eventPtr->xexpose.y;\n\trect.width = (unsigned short)eventPtr->xexpose.width;\n\trect.height = (unsigned short)eventPtr->xexpose.height;\n\tXUnionRectWithRegion(&rect, info->region,\n\t\tinfo->region);\n\trect.x += (short)info->dx;\n\trect.y += (short)info->dy;\n\tXUnionRectWithRegion(&rect, info->region,\n\t\tinfo->region);\n    } else {\n\treturn TK_DEFER_EVENT;\n    }\n    return TK_DISCARD_EVENT;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DrawHighlightBorder --\n *\n *\tThis function draws a rectangular ring around the outside of a widget\n *\tto indicate that it has received the input focus.\n *\n *      On Unix, we just draw the simple inset ring. On other sytems, e.g. the\n *      Mac, the focus ring is a little more complicated, so we need this\n *      abstraction.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA rectangle \"width\" pixels wide is drawn in \"drawable\", corresponding\n *\tto the outer area of \"tkwin\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DrawHighlightBorder(\n    Tk_Window tkwin,\n    GC fgGC,\n    GC bgGC,\n    int highlightWidth,\n    Drawable drawable)\n{\n    (void)bgGC;\n\n    TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawFrameEx --\n *\n *\tThis function draws the rectangular frame area.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws inside the tkwin area.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawFrameEx(\n    Tk_Window tkwin,\n    Drawable drawable,\n    Tk_3DBorder border,\n    int highlightWidth,\n    int borderWidth,\n    int relief)\n{\n    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,\n\t    highlightWidth, Tk_Width(tkwin) - 2*highlightWidth,\n\t    Tk_Height(tkwin) - 2*highlightWidth, borderWidth, relief);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixEmbed.c",
    "content": "/*\n * tkUnixEmbed.c --\n *\n *\tThis file contains platform-specific functions for UNIX to provide\n *\tbasic operations needed for application embedding (where one\n *\tapplication can use as its main window an internal window from some\n *\tother application). Also includes code to support busy windows.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkBusy.h\"\n\n/*\n * One of the following structures exists for each container in this\n * application. It keeps track of the container window and its associated\n * embedded window.\n */\n\ntypedef struct Container {\n    Window parent;\t\t/* X's window id for the parent of the pair\n\t\t\t\t * (the container). */\n    Window parentRoot;\t\t/* Id for the root window of parent's\n\t\t\t\t * screen. */\n    TkWindow *parentPtr;\t/* Tk's information about the container, or\n\t\t\t\t * NULL if the container isn't in this\n\t\t\t\t * process. */\n    Window wrapper;\t\t/* X's window id for the wrapper window for\n\t\t\t\t * the embedded window. Starts off as None,\n\t\t\t\t * but gets filled in when the window is\n\t\t\t\t * eventually created. */\n    TkWindow *embeddedPtr;\t/* Tk's information about the embedded window,\n\t\t\t\t * or NULL if the embedded application isn't\n\t\t\t\t * in this process. Note that this is *not*\n\t\t\t\t * the same window as wrapper: wrapper is the\n\t\t\t\t * parent of embeddedPtr. */\n    struct Container *nextPtr;\t/* Next in list of all containers in this\n\t\t\t\t * process. */\n} Container;\n\ntypedef struct {\n    Container *firstContainerPtr;\n\t\t\t\t/* First in list of all containers managed by\n\t\t\t\t * this process. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Prototypes for static functions defined in this file:\n */\n\nstatic void\t\tContainerEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEmbeddedEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tEmbedErrorProc(void *clientData,\n\t\t\t    XErrorEvent *errEventPtr);\nstatic void\t\tEmbedFocusProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEmbedGeometryRequest(Container *containerPtr,\n\t\t\t    int width, int height);\nstatic void\t\tEmbedSendConfigure(Container *containerPtr);\nstatic void\t\tEmbedStructureProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEmbedWindowDeleted(TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UseWindow --\n *\n *\tThis function causes a Tk window to use a given X window as its parent\n *\twindow, rather than the root window for the screen. It is invoked by\n *\tan embedded application to specify the window in which it is embedded.\n *\n * Results:\n *\tThe return value is normally TCL_OK. If an error occurs (such as\n *\tstring not being a valid window spec), then the return value is\n *\tTCL_ERROR and an error message is left in the interp's result if\n *\tinterp is non-NULL.\n *\n * Side effects:\n *\tChanges the colormap and other visual information to match that of the\n *\tparent window given by \"string\".\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_UseWindow(\n    Tcl_Interp *interp,\t\t/* If not NULL, used for error reporting if\n\t\t\t\t * string is bogus. */\n    Tk_Window tkwin,\t\t/* Tk window that does not yet have an\n\t\t\t\t * associated X window. */\n    const char *string)\t\t/* String identifying an X window to use for\n\t\t\t\t * tkwin; must be an integer value. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkWindow *usePtr;\n    int anyError;\n    Window parent;\n    Tk_ErrorHandler handler;\n    Container *containerPtr;\n    XWindowAttributes parentAtts;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->window != None) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't modify container after widget is created\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"POST_CREATE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (TkpScanWindowId(interp, string, &parent) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent);\n    if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" doesn't have -container option set\",\n\t\tusePtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"CONTAINER\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Tk sets the window colormap to the screen default colormap in\n     * tkWindow.c:AllocWindow. This doesn't work well for embedded windows. So\n     * we override the colormap and visual settings to be the same as the\n     * parent window (which is in the container app).\n     */\n\n    anyError = 0;\n    handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,\n\t    EmbedErrorProc, &anyError);\n    if (!XGetWindowAttributes(winPtr->display, parent, &parentAtts)) {\n\tanyError = 1;\n    }\n    XSync(winPtr->display, False);\n    Tk_DeleteErrorHandler(handler);\n    if (anyError) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"couldn't create child of window \\\"%s\\\"\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"NO_TARGET\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n    Tk_SetWindowVisual(tkwin, parentAtts.visual, parentAtts.depth,\n\t    parentAtts.colormap);\n\n    /*\n     * Create an event handler to clean up the Container structure when tkwin\n     * is eventually deleted.\n     */\n\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,\n\t    winPtr);\n\n    /*\n     * Save information about the container and the embedded window in a\n     * Container structure. If there is already an existing Container\n     * structure, it means that both container and embedded app. are in the\n     * same process.\n     */\n\n    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->parent == parent) {\n\t    winPtr->flags |= TK_BOTH_HALVES;\n\t    containerPtr->parentPtr->flags |= TK_BOTH_HALVES;\n\t    break;\n\t}\n    }\n    if (containerPtr == NULL) {\n\tcontainerPtr = (Container *)Tcl_Alloc(sizeof(Container));\n\tcontainerPtr->parent = parent;\n\tcontainerPtr->parentRoot = parentAtts.root;\n\tcontainerPtr->parentPtr = NULL;\n\tcontainerPtr->wrapper = None;\n\tcontainerPtr->nextPtr = tsdPtr->firstContainerPtr;\n\ttsdPtr->firstContainerPtr = containerPtr;\n    }\n    containerPtr->embeddedPtr = winPtr;\n    winPtr->flags |= TK_EMBEDDED;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeWindow --\n *\n *\tCreate an actual window system window object based on the current\n *\tattributes of the specified TkWindow.\n *\n * Results:\n *\tReturns the handle to the new window, or None on failure.\n *\n * Side effects:\n *\tCreates a new X window.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTk_MakeWindow(\n    Tk_Window tkwin,\t\t/* Tk's information about the window that is\n\t\t\t\t * to be instantiated. */\n    Window parent)\t\t/* Window system token for the parent in which\n\t\t\t\t * the window is to be created. */\n{\n    Container *containerPtr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\t/*\n\t * This window is embedded. Don't create the new window in the given\n\t * parent; instead, create it as a child of the root window of the\n\t * container's screen. The window will get reparented into a wrapper\n\t * window later.\n\t */\n\n\tfor (containerPtr = tsdPtr->firstContainerPtr; ;\n\t\tcontainerPtr = containerPtr->nextPtr) {\n\t    if (containerPtr == NULL) {\n\t\tTcl_Panic(\"TkMakeWindow couldn't find container for window\");\n\t    }\n\t    if (containerPtr->embeddedPtr == winPtr) {\n\t\tbreak;\n\t    }\n\t}\n\tparent = containerPtr->parentRoot;\n    }\n\n    return XCreateWindow(winPtr->display, parent, winPtr->changes.x,\n\t    winPtr->changes.y, (unsigned) winPtr->changes.width,\n\t    (unsigned) winPtr->changes.height,\n\t    (unsigned) winPtr->changes.border_width, winPtr->depth,\n\t    InputOutput, winPtr->visual, winPtr->dirtyAtts,\n\t    &winPtr->atts);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeContainer --\n *\n *\tThis function is called to indicate that a particular window will be a\n *\tcontainer for an embedded application. This changes certain aspects of\n *\tthe window's behavior, such as whether it will receive events anymore.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MakeContainer(\n    Tk_Window tkwin)\t\t/* Token for a window that is about to become\n\t\t\t\t * a container. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Register the window as a container so that, for example, we can find\n     * out later if the embedded app. is in the same process.\n     */\n\n    Tk_MakeWindowExist(tkwin);\n    containerPtr = (Container *)Tcl_Alloc(sizeof(Container));\n    containerPtr->parent = Tk_WindowId(tkwin);\n    containerPtr->parentRoot = RootWindowOfScreen(Tk_Screen(tkwin));\n    containerPtr->parentPtr = winPtr;\n    containerPtr->wrapper = None;\n    containerPtr->embeddedPtr = NULL;\n    containerPtr->nextPtr = tsdPtr->firstContainerPtr;\n    tsdPtr->firstContainerPtr = containerPtr;\n    winPtr->flags |= TK_CONTAINER;\n\n    /*\n     * Request SubstructureNotify events so that we can find out when the\n     * embedded application creates its window or attempts to resize it. Also\n     * watch Configure events on the container so that we can resize the child\n     * to match.\n     */\n\n    winPtr->atts.event_mask |= SubstructureRedirectMask|SubstructureNotifyMask;\n    XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask);\n    Tk_CreateEventHandler(tkwin,\n\t    SubstructureNotifyMask|SubstructureRedirectMask,\n\t    ContainerEventProc, winPtr);\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc,\n\t    containerPtr);\n    Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc,\n\t    containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedErrorProc --\n *\n *\tThis function is invoked if an error occurs while creating an embedded\n *\twindow.\n *\n * Results:\n *\tAlways returns 0 to indicate that the error has been properly handled.\n *\n * Side effects:\n *\tThe integer pointed to by the clientData argument is set to 1.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nEmbedErrorProc(\n    void *clientData,\t/* Points to integer to set. */\n    XErrorEvent *errEventPtr)\t/* Points to information about error (not\n\t\t\t\t * used). */\n{\n    int *iPtr = (int *)clientData;\n    (void)errEventPtr;\n\n    *iPtr = 1;\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbeddedEventProc --\n *\n *\tThis function is invoked by the Tk event dispatcher when various\n *\tuseful events are received for a window that is embedded in another\n *\tapplication.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOur internal state gets cleaned up when an embedded window is\n *\tdestroyed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbeddedEventProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tEmbedWindowDeleted(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ContainerEventProc --\n *\n *\tThis function is invoked by the Tk event dispatcher when various\n *\tuseful events are received for the children of a container window. It\n *\tforwards relevant information, such as geometry requests, from the\n *\tevents into the container's application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the event. For example, when ConfigureRequest events occur,\n *\tgeometry information gets set for the container window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nContainerEventProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    Container *containerPtr;\n    Tk_ErrorHandler errHandler;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Ignore any X protocol errors that happen in this function (almost any\n     * operation could fail, for example, if the embedded application has\n     * deleted its window).\n     */\n\n    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,\n\t    -1, -1, NULL, NULL);\n\n    /*\n     * Find the Container structure associated with the parent window.\n     */\n\n    for (containerPtr = tsdPtr->firstContainerPtr;\n\t    containerPtr->parent != eventPtr->xmaprequest.parent;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr == NULL) {\n\t    Tcl_Panic(\"ContainerEventProc couldn't find Container record\");\n\t}\n    }\n\n    if (eventPtr->type == CreateNotify) {\n\t/*\n\t * A new child window has been created in the container. Record its id\n\t * in the Container structure (if more than one child is created, just\n\t * remember the last one and ignore the earlier ones). Also set the\n\t * child's size to match the container.\n\t */\n\n\tcontainerPtr->wrapper = eventPtr->xcreatewindow.window;\n\tXMoveResizeWindow(eventPtr->xcreatewindow.display,\n\t\tcontainerPtr->wrapper, 0, 0,\n\t\t(unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr),\n\t\t(unsigned) Tk_Height((Tk_Window) containerPtr->parentPtr));\n    } else if (eventPtr->type == ConfigureRequest) {\n\tif ((eventPtr->xconfigurerequest.x != 0)\n\t\t|| (eventPtr->xconfigurerequest.y != 0)) {\n\t    /*\n\t     * The embedded application is trying to move itself, which isn't\n\t     * legal. At this point, the window hasn't actually moved, but we\n\t     * need to send it a ConfigureNotify event to let it know that its\n\t     * request has been denied. If the embedded application was also\n\t     * trying to resize itself, a ConfigureNotify will be sent by the\n\t     * geometry management code below, so we don't need to do\n\t     * anything. Otherwise, generate a synthetic event.\n\t     */\n\n\t    if ((eventPtr->xconfigurerequest.width == winPtr->changes.width)\n\t\t    && (eventPtr->xconfigurerequest.height\n\t\t    == winPtr->changes.height)) {\n\t\tEmbedSendConfigure(containerPtr);\n\t    }\n\t}\n\tEmbedGeometryRequest(containerPtr,\n\t\teventPtr->xconfigurerequest.width,\n\t\teventPtr->xconfigurerequest.height);\n    } else if (eventPtr->type == MapRequest) {\n\t/*\n\t * The embedded application's map request was ignored and simply\n\t * passed on to us, so we have to map the window for it to appear on\n\t * the screen.\n\t */\n\n\tXMapWindow(eventPtr->xmaprequest.display,\n\t\teventPtr->xmaprequest.window);\n    } else if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * The embedded application is gone. Destroy the container window.\n\t */\n\n\tTk_DestroyWindow((Tk_Window) winPtr);\n    }\n    Tk_DeleteErrorHandler(errHandler);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedStructureProc --\n *\n *\tThis function is invoked by the Tk event dispatcher when a container\n *\twindow owned by this application gets resized (and also at several\n *\tother times that we don't care about). This function reflects the size\n *\tchange in the embedded window that corresponds to the container.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe embedded window gets resized to match the container.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedStructureProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Tk_ErrorHandler errHandler;\n\n    if (eventPtr->type == ConfigureNotify) {\n\t/*\n\t * Send a ConfigureNotify  to the embedded application.\n\t */\n\n\tif (containerPtr->embeddedPtr != NULL) {\n\t    TkDoConfigureNotify(containerPtr->embeddedPtr);\n\t}\n\tif (containerPtr->wrapper != None) {\n\n\t    /*\n\t     * Ignore errors, since the embedded application could have\n\t     * deleted its window.\n\t     */\n\n\t    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,\n\t\t    -1, -1, NULL, NULL);\n\t    XMoveResizeWindow(eventPtr->xconfigure.display,\n\t\t    containerPtr->wrapper, 0, 0,\n\t\t    (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr),\n\t\t    (unsigned) Tk_Height((Tk_Window) containerPtr->parentPtr));\n\t    Tk_DeleteErrorHandler(errHandler);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\tEmbedWindowDeleted(containerPtr->parentPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedFocusProc --\n *\n *\tThis function is invoked by the Tk event dispatcher when FocusIn and\n *\tFocusOut events occur for a container window owned by this\n *\tapplication. It is responsible for moving the focus back and forth\n *\tbetween a container application and an embedded application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe X focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedFocusProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Tk_ErrorHandler errHandler;\n    Display *display;\n\n    display = Tk_Display(containerPtr->parentPtr);\n    if (eventPtr->type == FocusIn) {\n\t/*\n\t * The focus just arrived at the container. Change the X focus to move\n\t * it to the embedded application, if there is one. Ignore X errors\n\t * that occur during this operation (it's possible that the new focus\n\t * window isn't mapped).\n\t */\n\n\tif (containerPtr->wrapper != None) {\n\t    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,\n\t\t    -1, -1, NULL, NULL);\n\t    XSetInputFocus(display, containerPtr->wrapper, RevertToParent,\n\t\t    CurrentTime);\n\t    Tk_DeleteErrorHandler(errHandler);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedGeometryRequest --\n *\n *\tThis function is invoked when an embedded application requests a\n *\tparticular size. It processes the request (which may or may not\n *\tactually honor the request) and reflects the results back to the\n *\tembedded application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf we deny the child's size change request, a Configure event is\n *\tsynthesized to let the child know how big it ought to be. Events get\n *\tprocessed while we're waiting for the geometry managers to do their\n *\tthing.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedGeometryRequest(\n    Container *containerPtr,\t/* Information about the embedding. */\n    int width, int height)\t/* Size that the child has requested. */\n{\n    TkWindow *winPtr = containerPtr->parentPtr;\n\n    /*\n     * Forward the requested size into our geometry management hierarchy via\n     * the container window. We need to send a Configure event back to the\n     * embedded application if we decide not to honor its request; to make\n     * this happen, process all idle event handlers synchronously here (so\n     * that the geometry managers have had a chance to do whatever they want\n     * to do), and if the window's size didn't change then generate a\n     * configure event.\n     */\n\n    Tk_GeometryRequest((Tk_Window) winPtr, width, height);\n    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {\n\t/* Empty loop body. */\n    }\n    if ((winPtr->changes.width != width)\n\t    || (winPtr->changes.height != height)) {\n\tEmbedSendConfigure(containerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedSendConfigure --\n *\n *\tThis function synthesizes a ConfigureNotify event to notify an\n *\tembedded application of its current size and location. This function\n *\tis called when the embedded application made a geometry request that\n *\twe did not grant, so that the embedded application knows that its\n *\tgeometry didn't change after all.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedSendConfigure(\n    Container *containerPtr)\t/* Information about the embedding. */\n{\n    TkWindow *winPtr = containerPtr->parentPtr;\n    XEvent event;\n\n    event.xconfigure.type = ConfigureNotify;\n    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xconfigure.send_event = True;\n    event.xconfigure.display = winPtr->display;\n    event.xconfigure.event = containerPtr->wrapper;\n    event.xconfigure.window = containerPtr->wrapper;\n    event.xconfigure.x = 0;\n    event.xconfigure.y = 0;\n    event.xconfigure.width = winPtr->changes.width;\n    event.xconfigure.height = winPtr->changes.height;\n    event.xconfigure.above = None;\n    event.xconfigure.override_redirect = False;\n\n    /*\n     * Note: when sending the event below, the ButtonPressMask causes the\n     * event to be sent only to applications that have selected for\n     * ButtonPress events, which should be just the embedded application.\n     */\n\n    XSendEvent(winPtr->display, containerPtr->wrapper, False,\n\t    0, &event);\n\n    /*\n     * The following needs to be done if the embedded window is not in the\n     * same application as the container window.\n     */\n\n    if (containerPtr->embeddedPtr == NULL) {\n\tXMoveResizeWindow(winPtr->display, containerPtr->wrapper, 0, 0,\n\t\t(unsigned) winPtr->changes.width,\n\t\t(unsigned) winPtr->changes.height);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOtherWindow --\n *\n *\tIf both the container and embedded window are in the same process,\n *\tthis function will return either one, given the other.\n *\n * Results:\n *\tIf tkwin is a container, the return value is the token for the\n *\tembedded window, and vice versa. If the \"other\" window isn't in this\n *\tprocess, NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_GetOtherWindow(\n    Tk_Window tkwin)\t\t/* Tk's structure for a container or embedded\n\t\t\t\t * window. */\n{\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (containerPtr = tsdPtr->firstContainerPtr;\n\t    containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif ((Tk_Window)containerPtr->embeddedPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->parentPtr;\n\t} else if ((Tk_Window)containerPtr->parentPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->embeddedPtr;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpRedirectKeyEvent --\n *\n *\tThis function is invoked when a key press or release event arrives for\n *\tan application that does not believe it owns the input focus. This can\n *\thappen because of embedding; for example, X can send an event to an\n *\tembedded application when the real focus window is in the container\n *\tapplication and is an ancestor of the container. This function's job\n *\tis to forward the event back to the application where it really\n *\tbelongs.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe event may get sent to a different application.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpRedirectKeyEvent(\n    TkWindow *winPtr,\t\t/* Window to which the event was originally\n\t\t\t\t * reported. */\n    XEvent *eventPtr)\t\t/* X event to redirect (should be KeyPress or\n\t\t\t\t * KeyRelease). */\n{\n    Container *containerPtr;\n    Window saved;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * First, find the top-level window corresponding to winPtr.\n     */\n\n    while (1) {\n\tif (winPtr == NULL) {\n\t    /*\n\t     * This window is being deleted. This is too confusing a case to\n\t     * handle so discard the event.\n\t     */\n\n\t    return;\n\t}\n\tif (winPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n\twinPtr = winPtr->parentPtr;\n    }\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\t/*\n\t * This application is embedded. If we got a key event without\n\t * officially having the focus, it means that the focus is really in\n\t * the container, but the mouse was over the embedded application.\n\t * Send the event back to the container.\n\t */\n\n\tfor (containerPtr = tsdPtr->firstContainerPtr;\n\t\tcontainerPtr->embeddedPtr != winPtr;\n\t\tcontainerPtr = containerPtr->nextPtr) {\n\t    /* Empty loop body. */\n\t}\n\tsaved = eventPtr->xkey.window;\n\teventPtr->xkey.window = containerPtr->parent;\n\tXSendEvent(eventPtr->xkey.display, eventPtr->xkey.window, False,\n\t\tKeyPressMask|KeyReleaseMask, eventPtr);\n\teventPtr->xkey.window = saved;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpClaimFocus --\n *\n *\tThis function is invoked when someone asks or the input focus to be\n *\tput on a window in an embedded application, but the application\n *\tdoesn't currently have the focus. It requests the input focus from the\n *\tcontainer application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe input focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpClaimFocus(\n    TkWindow *topLevelPtr,\t/* Top-level window containing desired focus\n\t\t\t\t * window; should be embedded. */\n    int force)\t\t\t/* One means that the container should claim\n\t\t\t\t * the focus if it doesn't currently have\n\t\t\t\t * it. */\n{\n    XEvent event;\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!(topLevelPtr->flags & TK_EMBEDDED)) {\n\treturn;\n    }\n\n    for (containerPtr = tsdPtr->firstContainerPtr;\n\t    containerPtr->embeddedPtr != topLevelPtr;\n\t    containerPtr = containerPtr->nextPtr) {\n\t/* Empty loop body. */\n    }\n\n    event.xfocus.type = FocusIn;\n    event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);\n    event.xfocus.send_event = 1;\n    event.xfocus.display = topLevelPtr->display;\n    event.xfocus.window = containerPtr->parent;\n    event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;\n    event.xfocus.detail = force;\n    XSendEvent(event.xfocus.display, event.xfocus.window, False, 0, &event);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTestembedCmd --\n *\n *\tThis function implements the \"testembed\" command. It returns some or\n *\tall of the information in the list pointed to by firstContainerPtr.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpTestembedCmd(\n    void *dummy,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    int all;\n    Container *containerPtr;\n    Tcl_DString dString;\n    char buffer[50];\n    Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    (void)dummy;\n\n    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), \"all\") == 0)) {\n\tall = 1;\n    } else {\n\tall = 0;\n    }\n    Tcl_DStringInit(&dString);\n    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->embeddedPtr != NULL) {\n\t    embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;\n\t}\n\tif (containerPtr->parentPtr != NULL) {\n\t    parentInterp = containerPtr->parentPtr->mainPtr->interp;\n\t}\n\tif (embeddedInterp != interp && parentInterp != interp) {\n\t    continue;\n\t}\n\tTcl_DStringStartSublist(&dString);\n\t/* Parent id */\n\tif (containerPtr->parent == None) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else if (all) {\n\t    snprintf(buffer, sizeof(buffer), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t) containerPtr->parent);\n\t    Tcl_DStringAppendElement(&dString, buffer);\n\t} else {\n\t    Tcl_DStringAppendElement(&dString, \"XXX\");\n\t}\n\t/* Parent pathName */\n\tif (containerPtr->parentPtr == NULL ||\n\t    parentInterp != interp) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else {\n\t    Tcl_DStringAppendElement(&dString,\n\t\t    containerPtr->parentPtr->pathName);\n\t}\n\t/* Wrapper */\n\tif (containerPtr->wrapper == None) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else if (all) {\n\t    snprintf(buffer, sizeof(buffer), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t) containerPtr->wrapper);\n\t    Tcl_DStringAppendElement(&dString, buffer);\n\t} else {\n\t    Tcl_DStringAppendElement(&dString, \"XXX\");\n\t}\n\t/* Embedded window pathName */\n\tif (containerPtr->embeddedPtr == NULL ||\n\t    embeddedInterp != interp) {\n\t    Tcl_DStringAppendElement(&dString, \"\");\n\t} else {\n\t    Tcl_DStringAppendElement(&dString,\n\t\t    containerPtr->embeddedPtr->pathName);\n\t}\n\tTcl_DStringEndSublist(&dString);\n    }\n    Tcl_DStringResult(interp, &dString);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedWindowDeleted --\n *\n *\tThis function is invoked when a window involved in embedding (as\n *\teither the container or the embedded application) is destroyed. It\n *\tcleans up the Container structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Container structure may be freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedWindowDeleted(\n    TkWindow *winPtr)\t\t/* Tk's information about window that was\n\t\t\t\t * deleted. */\n{\n    Container *containerPtr, *prevPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Find the Container structure for this window work. Delete the\n     * information about the embedded application and free the container's\n     * record.\n     */\n\n    prevPtr = NULL;\n    containerPtr = tsdPtr->firstContainerPtr;\n    while (1) {\n\tif (containerPtr == NULL) return;\n\tif (containerPtr->embeddedPtr == winPtr) {\n\t    containerPtr->wrapper = None;\n\t    containerPtr->embeddedPtr = NULL;\n\t    break;\n\t}\n\tif (containerPtr->parentPtr == winPtr) {\n\t    containerPtr->parentPtr = NULL;\n\t    break;\n\t}\n\tprevPtr = containerPtr;\n\tcontainerPtr = containerPtr->nextPtr;\n    }\n    if ((containerPtr->embeddedPtr == NULL)\n\t    && (containerPtr->parentPtr == NULL)) {\n\tif (prevPtr == NULL) {\n\t    tsdPtr->firstContainerPtr = containerPtr->nextPtr;\n\t} else {\n\t    prevPtr->nextPtr = containerPtr->nextPtr;\n\t}\n\tTcl_Free(containerPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUnixContainerId --\n *\n *\tGiven an embedded window, this function returns the X window\n *\tidentifier for the associated container window.\n *\n * Results:\n *\tThe return value is the X window identifier for winPtr's container\n *\twindow.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTkUnixContainerId(\n    TkWindow *winPtr)\t\t/* Tk's structure for an embedded window. */\n{\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (containerPtr = tsdPtr->firstContainerPtr;\n\t    containerPtr != NULL; containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->embeddedPtr == winPtr) {\n\t    return containerPtr->parent;\n\t}\n    }\n    Tcl_Panic(\"TkUnixContainerId couldn't find window\");\n    return None;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpShowBusyWindow --\n *\n *\tMakes a busy window \"appear\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the busy window to start intercepting events and the\n *\tcursor to change to the configured \"hey, I'm busy!\" setting.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpShowBusyWindow(\n    TkBusy busy)\n{\n    Busy *busyPtr = (Busy *) busy;\n\n    if (busyPtr->tkBusy != NULL) {\n\tTk_MapWindow(busyPtr->tkBusy);\n\n\t/*\n\t * Always raise the busy window just in case new sibling windows have\n\t * been created in the meantime. Can't use Tk_RestackWindow because it\n\t * doesn't work under Win32.\n\t */\n\n\tXRaiseWindow(Tk_Display(busyPtr->tkBusy),\n\t\tTk_WindowId(busyPtr->tkBusy));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpHideBusyWindow --\n *\n *\tMakes a busy window \"disappear\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the busy window to stop intercepting events, and the\n *\tcursor to change back to its normal setting.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpHideBusyWindow(\n    TkBusy busy)\n{\n    Busy *busyPtr = (Busy *) busy;\n\n    if (busyPtr->tkBusy != NULL) {\n\tTk_UnmapWindow(busyPtr->tkBusy);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMakeTransparentWindowExist --\n *\n *\tConstruct the platform-specific resources for a transparent window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves the specified window in the stacking order.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMakeTransparentWindowExist(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Window parent)\t\t/* Parent window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    unsigned long mask = CWDontPropagate | CWEventMask;\n\n    /*\n     * Ignore the important events while the window is mapped.\n     */\n\n#define USER_EVENTS \\\n\t(EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | \\\n\tButtonPressMask | ButtonReleaseMask | PointerMotionMask)\n#define PROP_EVENTS \\\n\t(KeyPressMask | KeyReleaseMask | ButtonPressMask | \\\n\tButtonReleaseMask | PointerMotionMask)\n\n    winPtr->atts.do_not_propagate_mask = PROP_EVENTS;\n    winPtr->atts.event_mask = USER_EVENTS;\n    winPtr->changes.border_width = 0;\n    winPtr->depth = 0;\n\n    winPtr->window = XCreateWindow(winPtr->display, parent,\n\t    winPtr->changes.x, winPtr->changes.y,\n\t    (unsigned) winPtr->changes.width,\t\t/* width */\n\t    (unsigned) winPtr->changes.height,\t\t/* height */\n\t    (unsigned) winPtr->changes.border_width,\t/* border_width */\n\t    winPtr->depth, InputOnly, winPtr->visual, mask, &winPtr->atts);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateBusy --\n *\n *\tConstruct the platform-specific parts of a busy window. Note that this\n *\tpostpones the actual creation of the window resource until later.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets up part of the busy window structure.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCreateBusy(\n    Tk_FakeWin *winPtr,\n    Tk_Window tkRef,\n    Window *parentPtr,\n    Tk_Window tkParent,\n    TkBusy busy)\n{\n    Window root, parent, *dummy;\n    unsigned int count;\n    (void)busy;\n\n    if (winPtr->flags & TK_REPARENTED) {\n\t/*\n\t * This works around a bug in the implementation of menubars for\n\t * non-MacIntosh window systems (Win32 and X11). Tk doesn't reset the\n\t * pointers to the parent window when the menu is reparented (since\n\t * winPtr->parentPtr points to the wrong window). We get around this\n\t * by determining the parent via the native API calls.\n\t */\n\n\tif (XQueryTree(Tk_Display(tkRef), Tk_WindowId(tkRef), &root,\n\t\t&parent, &dummy, &count) > 0) {\n\t    XFree(dummy);\n\t    *parentPtr = parent;\n\t} else {\n\t    *parentPtr = None;\n\t}\n    } else {\n\t*parentPtr = Tk_WindowId(tkParent);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixEvent.c",
    "content": "/*\n * tkUnixEvent.c --\n *\n *\tThis file implements an event source for X displays for the UNIX\n *\tversion of Tk.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include <signal.h>\n#undef register /* Keyword \"register\" is used in XKBlib.h, so don't try tricky things here */\n#define XkbOpenDisplay XkbOpenDisplay_ /* Move out of the way, conflicting definitions */\n#include <X11/XKBlib.h>\n#undef XkbOpenDisplay\n\n/*\n * The following static indicates whether this module has been initialized in\n * the current thread.\n */\n\ntypedef struct {\n    bool initialized;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Prototypes for functions that are referenced only in this file:\n */\n\nstatic void\t\tDisplayCheckProc(void *clientData, int flags);\nstatic void\t\tDisplayExitHandler(void *clientData);\nstatic void\t\tDisplayFileProc(void *clientData, int flags);\nstatic void\t\tDisplaySetupProc(void *clientData, int flags);\nstatic void\t\tTransferXEventsToTcl(Display *display);\n#ifdef TK_USE_INPUT_METHODS\nstatic void\t\tInstantiateIMCallback(Display *, XPointer client_data, XPointer call_data);\nstatic void\t\tDestroyIMCallback(XIM im, XPointer client_data, XPointer call_data);\nstatic void\t\tOpenIM(TkDisplay *dispPtr);\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateXEventSource --\n *\n *\tThis function is called during Tk initialization to create the event\n *\tsource for X Window events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new event source is created.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkCreateXEventSource(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\tTcl_CreateEventSource(DisplaySetupProc, DisplayCheckProc, NULL);\n\tTkCreateExitHandler(DisplayExitHandler, NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayExitHandler --\n *\n *\tThis function is called during finalization to clean up the display\n *\tmodule.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayExitHandler(\n    void *dummy)\t/* Not used. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    (void)dummy;\n\n    Tcl_DeleteEventSource(DisplaySetupProc, DisplayCheckProc, NULL);\n    tsdPtr->initialized = false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpOpenDisplay --\n *\n *\tAllocates a new TkDisplay, opens the X display, and establishes the\n *\tfile handler for the connection.\n *\n * Results:\n *\tA pointer to a Tk display structure.\n *\n * Side effects:\n *\tOpens a display.\n *\n *----------------------------------------------------------------------\n */\n\nTkDisplay *\nTkpOpenDisplay(\n    const char *displayNameStr)\n{\n    TkDisplay *dispPtr;\n    Display *display;\n    int event = 0;\n    int error = 0;\n    int major = 1;\n    int minor = 0;\n    int reason = 0;\n    /* Disabled, until we have a better test. See [Bug 3613668] */\n#if 0\n    static int xinited = 0;\n    static Tcl_Mutex xinitMutex = NULL;\n\n    if (!xinited) {\n\tTcl_MutexLock(&xinitMutex);\n\tif (!xinited) {\n\t    /* Necessary for threaded apps, of no consequence otherwise  */\n\t    /* need only be called once, but must be called before *any* */\n\t    /* Xlib call is made. If xinitMutex is still NULL after the  */\n\t    /* Tcl_MutexLock call, Tcl was compiled without threads so   */\n\t    /* we cannot use XInitThreads() either.                      */\n\t    if (xinitMutex != NULL){\n\t\tXInitThreads();\n\t    }\n\t    xinited = 1;\n\t}\n\tTcl_MutexUnlock(&xinitMutex);\n    }\n#endif\n\n    /*\n    ** Bug [3607830]: Before using Xkb, it must be initialized and confirmed\n    **                that the server supports it.  The XkbOpenDisplay call\n    **                will perform this check and return NULL if the extension\n    **                is not supported.\n    */\n    display = XkbOpenDisplay(displayNameStr, &event, &error, &major,\n\t    &minor, &reason);\n\n    if (display == NULL) {\n\treturn NULL;\n    }\n    dispPtr = (TkDisplay *)Tcl_Alloc(sizeof(TkDisplay));\n    memset(dispPtr, 0, sizeof(TkDisplay));\n    dispPtr->display = display;\n#ifdef TK_USE_INPUT_METHODS\n    XSetLocaleModifiers(\"\");\n    OpenIM(dispPtr);\n    XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,\n\t    InstantiateIMCallback, (XPointer) dispPtr);\n#endif\n    Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE,\n\t    DisplayFileProc, dispPtr);\n\n    /*\n     * Observed weird WidthMMOfScreen() in X on Wayland on a\n     * Fedora 30/i386 running in a VM. Fallback to 75 dpi,\n     * otherwise many other strange things may happen later.\n     * See: [https://core.tcl-lang.org/tk/tktview?name=a01b6f7227]\n     */\n    if (WidthMMOfScreen(DefaultScreenOfDisplay(display)) <= 0) {\n\tint mm;\n\n\tmm = (int)(WidthOfScreen(DefaultScreenOfDisplay(display)) * (25.4 / 75.0));\n\tWidthMMOfScreen(DefaultScreenOfDisplay(display)) = mm;\n    }\n    if (HeightMMOfScreen(DefaultScreenOfDisplay(display)) <= 0) {\n\tint mm;\n\n\tmm = (int)(HeightOfScreen(DefaultScreenOfDisplay(display)) * (25.4 / 75.0));\n\tHeightMMOfScreen(DefaultScreenOfDisplay(display)) = mm;\n    }\n\n    /*\n     * Key map info must be available immediately, because of \"send event\".\n     */\n    TkpInitKeymapInfo(dispPtr);\n\n    return dispPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCloseDisplay --\n *\n *\tCancels notifier callbacks and closes a display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeallocates the displayPtr and unix-specific resources.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCloseDisplay(\n    TkDisplay *dispPtr)\n{\n    TkSendCleanup(dispPtr);\n\n    TkWmCleanup(dispPtr);\n\n#ifdef TK_USE_INPUT_METHODS\n    if (dispPtr->inputXfs) {\n\tXFreeFontSet(dispPtr->display, dispPtr->inputXfs);\n    }\n    if (dispPtr->inputMethod) {\n\tXCloseIM(dispPtr->inputMethod);\n    }\n#endif\n\n    if (dispPtr->display != 0) {\n\tTcl_DeleteFileHandler(ConnectionNumber(dispPtr->display));\n\t(void) XSync(dispPtr->display, False);\n\t(void) XCloseDisplay(dispPtr->display);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkClipCleanup --\n *\n *\tThis function is called to cleanup resources associated with claiming\n *\tclipboard ownership and for receiving selection get results. This\n *\tfunction is called in tkWindow.c. This has to be called by the display\n *\tcleanup function because we still need the access display elements.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources are freed - the clipboard may no longer be used.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkClipCleanup(\n    TkDisplay *dispPtr)\t\t/* Display associated with clipboard */\n{\n    if (dispPtr->clipWindow != NULL) {\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->applicationAtom);\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->windowAtom);\n\n\tTk_DestroyWindow(dispPtr->clipWindow);\n\tTcl_Release(dispPtr->clipWindow);\n\tdispPtr->clipWindow = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplaySetupProc --\n *\n *\tThis function implements the setup part of the UNIX X display event\n *\tsource. It is invoked by Tcl_DoOneEvent before entering the notifier\n *\tto check for events on all displays.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf data is queued on a display inside Xlib, then the maximum block\n *\ttime will be set to 0 to ensure that the notifier returns control to\n *\tTcl even if there is no more data on the X connection.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplaySetupProc(\n    void *dummy,\t/* Not used. */\n    int flags)\n{\n    TkDisplay *dispPtr;\n    static Tcl_Time blockTime = { 0, 0 };\n    (void)dummy;\n\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn;\n    }\n\n    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\t/*\n\t * Flush the display. If data is pending on the X queue, set the block\n\t * time to zero. This ensures that we won't block in the notifier if\n\t * there is data in the X queue, but not on the server socket.\n\t */\n\n\tXFlush(dispPtr->display);\n\tif (QLength(dispPtr->display) > 0) {\n\t    Tcl_SetMaxBlockTime(&blockTime);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TransferXEventsToTcl --\n *\n *\tTransfer events from the X event queue to the Tk event queue.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves queued X events onto the Tcl event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTransferXEventsToTcl(\n    Display *display)\n{\n    union {\n\tint type;\n\tXEvent x;\n\tTkKeyEvent k;\n    } event;\n    Window w;\n    TkDisplay *dispPtr = NULL;\n\n    /*\n     * Transfer events from the X event queue to the Tk event queue after XIM\n     * event filtering. KeyPress and KeyRelease events need special treatment\n     * so that they get directed according to Tk's focus rules during XIM\n     * handling. Theoretically they can go to the wrong place still (if\n     * there's a focus change in the queue) but if we push the handling off\n     * until Tk_HandleEvent then many input methods actually cease to work\n     * correctly. Most of the time, Tk processes its event queue fast enough\n     * for this to not be an issue anyway. [Bug 1924761]\n     */\n\n    while (QLength(display) > 0) {\n\tXNextEvent(display, &event.x);\n\tif ((event.type >= VirtualEvent) && (event.type <= MouseWheelEvent)) {\n\t    /* See [fe87e9af39]. Those are internal Tk event types, if they come\n\t     * from an external source they most likely would be totally mis-interpreted */\n\t    continue;\n\t}\n\tw = None;\n\tif (event.type == KeyPress || event.type == KeyRelease) {\n\t    for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {\n\t\tif (dispPtr == NULL) {\n\t\t    break;\n\t\t} else if (dispPtr->display == event.x.xany.display) {\n\t\t    if (dispPtr->focusPtr != NULL) {\n\t\t\tw = dispPtr->focusPtr->window;\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (XFilterEvent(&event.x, w)) {\n\t    continue;\n\t}\n\tif (event.type == KeyPress || event.type == KeyRelease) {\n\t    event.k.charValuePtr = NULL;\n\t    event.k.charValueLen = 0;\n\t    event.k.keysym = NoSymbol;\n\n\t    /*\n\t     * Force the calling of the input method engine now. The results\n\t     * from it will be cached in the event so that they don't get lost\n\t     * (to a race condition with other XIM-handled key events) between\n\t     * entering the event queue and getting serviced. [Bug 1924761]\n\t     */\n\n#ifdef TK_USE_INPUT_METHODS\n\t    if (event.type == KeyPress && dispPtr &&\n\t\t    (dispPtr->flags & TK_DISPLAY_USE_IM)) {\n\t\tif (dispPtr->focusPtr && dispPtr->focusPtr->inputContext) {\n\t\t    Tcl_DString ds;\n\n\t\t    Tcl_DStringInit(&ds);\n\t\t    (void) TkpGetString(dispPtr->focusPtr, &event.x, &ds);\n\t\t    Tcl_DStringFree(&ds);\n\t\t}\n\t    }\n#endif\n\t}\n\tTk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayCheckProc --\n *\n *\tThis function checks for events sitting in the X event queue.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves queued events onto the Tcl event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayCheckProc(\n    void *dummy,\t/* Not used. */\n    int flags)\n{\n    TkDisplay *dispPtr;\n    (void)dummy;\n\n    if (!(flags & TCL_WINDOW_EVENTS)) {\n\treturn;\n    }\n\n    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tXFlush(dispPtr->display);\n\tTransferXEventsToTcl(dispPtr->display);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayFileProc --\n *\n *\tThis function implements the file handler for the X connection.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMakes entries on the Tcl event queue for all the events available from\n *\tall the displays.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayFileProc(\n    void *clientData,\t/* The display pointer. */\n    int flags)\t\t\t/* Should be TCL_READABLE. */\n{\n    TkDisplay *dispPtr = (TkDisplay *)clientData;\n    Display *display = dispPtr->display;\n    int numFound;\n    (void)flags;\n\n    XFlush(display);\n    numFound = XEventsQueued(display, QueuedAfterReading);\n    if (numFound == 0) {\n\t/*\n\t * Things are very tricky if there aren't any events readable at this\n\t * point (after all, there was supposedly data available on the\n\t * connection). A couple of things could have occurred:\n\t *\n\t * One possibility is that there were only error events in the input\n\t * from the server. If this happens, we should return (we don't want\n\t * to go to sleep in XNextEvent below, since this would block out\n\t * other sources of input to the process).\n\t *\n\t * Another possibility is that our connection to the server has been\n\t * closed. This will not necessarily be detected in XEventsQueued (!!)\n\t * so if we just return then there will be an infinite loop. To detect\n\t * such an error, generate a NoOp protocol request to exercise the\n\t * connection to the server, then return. However, must disable\n\t * SIGPIPE while sending the request, or else the process will die\n\t * from the signal and won't invoke the X error function to print a\n\t * nice (?!) message.\n\t */\n\n\tvoid (*oldHandler)(int);\n\n\toldHandler = (void (*)(int)) signal(SIGPIPE, SIG_IGN);\n\tXNoOp(display);\n\tXFlush(display);\n\t(void) signal(SIGPIPE, oldHandler);\n    }\n\n    TransferXEventsToTcl(display);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUnixDoOneXEvent --\n *\n *\tThis routine waits for an X event to be processed or for a timeout to\n *\toccur. The timeout is specified as an absolute time. This routine is\n *\tcalled when Tk needs to wait for a particular X event without letting\n *\tarbitrary events be processed. The caller will typically call\n *\tTk_RestrictEvents to set up an event filter before calling this\n *\troutine. This routine will service at most one event per invocation.\n *\n * Results:\n *\tReturns 0 if the timeout has expired, otherwise returns 1.\n *\n * Side effects:\n *\tCan invoke arbitrary Tcl scripts.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkUnixDoOneXEvent(\n    Tcl_Time *timePtr)\t\t/* Specifies the absolute time when the call\n\t\t\t\t * should time out. */\n{\n    TkDisplay *dispPtr;\n    static fd_mask readMask[MASK_SIZE];\n    struct timeval blockTime, *timeoutPtr;\n    Tcl_Time now;\n    int fd, index, numFound, numFdBits = 0;\n    fd_mask bit, *readMaskPtr = readMask;\n\n    /*\n     * Look for queued events first.\n     */\n\n    if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {\n\treturn true;\n    }\n\n    /*\n     * Compute the next block time and check to see if we have timed out. Note\n     * that HP-UX defines tv_sec to be unsigned so we have to be careful in\n     * our arithmetic.\n     */\n\n    if (timePtr) {\n\tTcl_GetTime(&now);\n\tblockTime.tv_sec = timePtr->sec;\n\tblockTime.tv_usec = timePtr->usec - now.usec;\n\tif (blockTime.tv_usec < 0) {\n\t    now.sec += 1;\n\t    blockTime.tv_usec += 1000000;\n\t}\n\tif (blockTime.tv_sec < now.sec) {\n\t    blockTime.tv_sec = 0;\n\t    blockTime.tv_usec = 0;\n\t} else {\n\t    blockTime.tv_sec -= now.sec;\n\t}\n\ttimeoutPtr = &blockTime;\n    } else {\n\ttimeoutPtr = NULL;\n    }\n\n    /*\n     * Set up the select mask for all of the displays. If a display has data\n     * pending, then we want to poll instead of blocking.\n     */\n\n    memset(readMask, 0, MASK_SIZE*sizeof(fd_mask));\n    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tXFlush(dispPtr->display);\n\tif (QLength(dispPtr->display) > 0) {\n\t    blockTime.tv_sec = 0;\n\t    blockTime.tv_usec = 0;\n\t}\n\tfd = ConnectionNumber(dispPtr->display);\n\tindex = fd/(NBBY*(int)sizeof(fd_mask));\n\tbit = ((fd_mask)1) << (fd%(NBBY*(int)sizeof(fd_mask)));\n\treadMask[index] |= bit;\n\tif (numFdBits <= fd) {\n\t    numFdBits = fd+1;\n\t}\n    }\n\n    numFound = select(numFdBits, (SELECT_MASK *) readMaskPtr, NULL, NULL,\n\t    timeoutPtr);\n    if (numFound <= 0) {\n\t/*\n\t * Some systems don't clear the masks after an error, so we have to do\n\t * it here.\n\t */\n\n\tmemset(readMask, 0, MASK_SIZE*sizeof(fd_mask));\n    }\n\n    /*\n     * Process any new events on the display connections.\n     */\n\n    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tfd = ConnectionNumber(dispPtr->display);\n\tindex = fd/(NBBY*(int)sizeof(fd_mask));\n\tbit = ((fd_mask)1) << (fd%(NBBY*(int)sizeof(fd_mask)));\n\tif ((readMask[index] & bit) || (QLength(dispPtr->display) > 0)) {\n\t    DisplayFileProc(dispPtr, TCL_READABLE);\n\t}\n    }\n    if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {\n\treturn true;\n    }\n\n    /*\n     * Check to see if we timed out.\n     */\n\n    if (timePtr) {\n\tTcl_GetTime(&now);\n\tif ((now.sec > timePtr->sec) || ((now.sec == timePtr->sec)\n\t\t&& (now.usec > timePtr->usec))) {\n\t    return false;\n\t}\n    }\n\n    /*\n     * We had an event but we did not generate a Tcl event from it. Behave as\n     * though we dealt with it. (JYL&SS)\n     */\n\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSync --\n *\n *\tThis routine ensures that all pending X requests have been seen by the\n *\tserver, and that any pending X events have been moved onto the Tk\n *\tevent queue.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPlaces new events on the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\n#undef TkpSync\nvoid\nTkpSync(\n    Display *display)\t\t/* Display to sync. */\n{\n    XSync(display, False);\n\n    /*\n     * Transfer events from the X event queue to the Tk event queue.\n     */\n\n    TransferXEventsToTcl(display);\n}\n#ifdef TK_USE_INPUT_METHODS\n\f\nstatic void\nInstantiateIMCallback(\n    Display      *display,\n    XPointer     client_data,\n    XPointer     call_data)\n{\n    TkDisplay    *dispPtr;\n    (void)display;\n    (void)call_data;\n\n    dispPtr = (TkDisplay *) client_data;\n    OpenIM(dispPtr);\n    XUnregisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,\n\t    InstantiateIMCallback, (XPointer) dispPtr);\n}\n\nstatic void\nDestroyIMCallback(\n    XIM         im,\n    XPointer    client_data,\n    XPointer    call_data)\n{\n    TkDisplay   *dispPtr;\n    (void)im;\n    (void)call_data;\n\n    dispPtr = (TkDisplay *) client_data;\n    dispPtr->inputMethod = NULL;\n    ++dispPtr->ximGeneration;\n    XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,\n\t    InstantiateIMCallback, (XPointer) dispPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * OpenIM --\n *\n *\tTries to open an X input method associated with the given display.\n *\n * Results:\n *\tStores the input method in dispPtr->inputMethod; if there isn't a\n *\tsuitable input method, then NULL is stored in dispPtr->inputMethod.\n *\n * Side effects:\n *\tAn input method gets opened.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nOpenIM(\n    TkDisplay *dispPtr)\t\t/* Tk's structure for the display. */\n{\n    int i;\n    XIMStyles *stylePtr;\n    XIMStyle bestStyle = 0;\n\n    ++dispPtr->ximGeneration;\n    dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL);\n    if (dispPtr->inputMethod == NULL) {\n\treturn;\n    }\n\n    /* Require X11R6 */\n    {\n\tXIMCallback destroy_cb;\n\n\tdestroy_cb.callback = DestroyIMCallback;\n\tdestroy_cb.client_data = (XPointer) dispPtr;\n\tif (XSetIMValues(dispPtr->inputMethod, XNDestroyCallback,\n\t\t&destroy_cb, NULL))\n\t    goto error;\n    }\n\n    if ((XGetIMValues(dispPtr->inputMethod, XNQueryInputStyle, &stylePtr,\n\t    NULL) != NULL) || (stylePtr == NULL)) {\n\tgoto error;\n    }\n\n    /*\n     * Select the best input style supported by both the IM and Tk.\n     */\n    for (i = 0; i < stylePtr->count_styles; i++) {\n\tXIMStyle thisStyle = stylePtr->supported_styles[i];\n\tif (thisStyle == (XIMPreeditPosition | XIMStatusNothing)) {\n\t    bestStyle = thisStyle;\n\t    break;\n\t} else if (thisStyle == (XIMPreeditNothing | XIMStatusNothing)) {\n\t    bestStyle = thisStyle;\n\t}\n    }\n    XFree(stylePtr);\n    if (bestStyle == 0) {\n\tgoto error;\n    }\n\n    dispPtr->inputStyle = bestStyle;\n\n    /*\n     * Create an XFontSet for preedit area.\n     */\n    if (dispPtr->inputStyle & XIMPreeditPosition) {\n\tchar **missing_list;\n\tint missing_count;\n\tchar *def_string;\n\n\tdispPtr->inputXfs = XCreateFontSet(dispPtr->display,\n\t\t\"-*-*-*-R-Normal--14-130-75-75-*-*\",\n\t\t&missing_list, &missing_count, &def_string);\n\tif (missing_count > 0) {\n\t    XFreeStringList(missing_list);\n\t}\n    }\n\n    return;\n\nerror:\n    if (dispPtr->inputMethod) {\n\tXCloseIM(dispPtr->inputMethod);\n\tdispPtr->inputMethod = NULL;\n\t++dispPtr->ximGeneration;\n    }\n}\n#endif /* TK_USE_INPUT_METHODS */\n\f\nvoid\nTkpWarpPointer(\n    TkDisplay *dispPtr)\n{\n    Window w;\t\t\t/* Which window to warp relative to. */\n\n    if (dispPtr->warpWindow != NULL) {\n\tw = Tk_WindowId(dispPtr->warpWindow);\n    } else {\n\tw = RootWindow(dispPtr->display,\n\t\tTk_ScreenNumber(dispPtr->warpMainwin));\n    }\n    XWarpPointer(dispPtr->display, None, w, 0, 0, 0, 0,\n\t    (int) dispPtr->warpX, (int) dispPtr->warpY);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixFocus.c",
    "content": "/*\n * tkUnixFocus.c --\n *\n *\tThis file contains platform specific functions that manage focus for\n *\tTk.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpChangeFocus --\n *\n *\tThis function is invoked to move the official X focus from one window\n *\tto another.\n *\n * Results:\n *\tThe return value is the serial number of the command that changed the\n *\tfocus. It may be needed by the caller to filter out focus change\n *\tevents that were queued before the command. If the function doesn't\n *\tactually change the focus then it returns 0.\n *\n * Side effects:\n *\tThe official X focus window changes; the application's focus window\n *\tisn't changed by this function.\n *\n *----------------------------------------------------------------------\n */\n\nsize_t\nTkpChangeFocus(\n    TkWindow *winPtr,\t\t/* Window that is to receive the X focus. */\n    int force)\t\t\t/* Non-zero means claim the focus even if it\n\t\t\t\t * didn't originally belong to topLevelPtr's\n\t\t\t\t * application. */\n{\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    Tk_ErrorHandler errHandler;\n    Window window, root, parent, *children;\n    unsigned int numChildren;\n    size_t serial;\n    TkWindow *winPtr2;\n    int dummy;\n\n    /*\n     * Don't set the X focus to a window that's marked override-redirect.\n     * This is a hack to avoid problems with menus under olvwm: if we move\n     * the focus then the focus can get lost during keyboard traversal.\n     * Fortunately, we don't really need to move the focus for menus: events\n     * will still find their way to the focus window, and menus aren't\n     * decorated anyway so the window manager doesn't need to hear about the\n     * focus change in order to redecorate the menu.\n     */\n\n    serial = 0;\n    if (winPtr->atts.override_redirect) {\n\treturn serial;\n    }\n\n    /*\n     * Check to make sure that the focus is still in one of the windows of\n     * this application or one of their descendants. Furthermore, grab the\n     * server to make sure that the focus doesn't change in the middle of this\n     * operation.\n     */\n\n    XGrabServer(dispPtr->display);\n    if (!force) {\n\t/*\n\t * Find the focus window, then see if it or one of its ancestors is a\n\t * window in our application (it's possible that the focus window is\n\t * in an embedded application, which may or may not be in the same\n\t * process.\n\t */\n\n\tXGetInputFocus(dispPtr->display, &window, &dummy);\n\twhile (1) {\n\t    winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);\n\t    if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) {\n\t\tbreak;\n\t    }\n\t    if ((window == PointerRoot) || (window == None)) {\n\t\tgoto done;\n\t    }\n\t    XQueryTree(dispPtr->display, window, &root, &parent, &children,\n\t\t    &numChildren);\n\t    if (children != NULL) {\n\t\tXFree(children);\n\t    }\n\t    if (parent == root) {\n\t\tgoto done;\n\t    }\n\t    window = parent;\n\t}\n    }\n\n    /*\n     * Tell X to change the focus. Ignore errors that occur when changing the\n     * focus: it is still possible that the window we're focussing to could\n     * have gotten unmapped, which will generate an error.\n     */\n\n    errHandler = Tk_CreateErrorHandler(dispPtr->display, -1,-1,-1, NULL,NULL);\n    if (winPtr->window == None) {\n\tTcl_Panic(\"ChangeXFocus got null X window\");\n    }\n    XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,\n\t    CurrentTime);\n    Tk_DeleteErrorHandler(errHandler);\n\n    /*\n     * Remember the current serial number for the X server and issue a dummy\n     * server request. This marks the position at which we changed the focus,\n     * so we can distinguish FocusIn and FocusOut events on either side of the\n     * mark.\n     */\n\n    serial = NextRequest(winPtr->display);\n    XNoOp(winPtr->display);\n\n  done:\n    XUngrabServer(dispPtr->display);\n\n    /*\n     * After ungrabbing the server, it's important to flush the output\n     * immediately so that the server sees the ungrab command. Otherwise we\n     * might do something else that needs to communicate with the server (such\n     * as invoking a subprocess that needs to do I/O to the screen); if the\n     * ungrab command is still sitting in our output buffer, we could\n     * deadlock.\n     */\n\n    XFlush(dispPtr->display);\n    return serial;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixFont.c",
    "content": "/*\n * tkUnixFont.c --\n *\n *\tContains the Unix implementation of the platform-independent font\n *\tpackage interface.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkFont.h\"\n\n/*\n * The preferred font encodings.\n */\n\nstatic const char encodingList[][10] = {\n    \"iso8859-1\", \"jis0208\", \"jis0212\"\n};\n\n/*\n * The following structure represents a font family. It is assumed that all\n * screen fonts constructed from the same \"font family\" share certain\n * properties; all screen fonts with the same \"font family\" point to a shared\n * instance of this structure. The most important shared property is the\n * character existence metrics, used to determine if a screen font can display\n * a given Unicode character.\n *\n * Under Unix, there are three attributes that uniquely identify a \"font\n * family\": the foundry, face name, and charset.\n */\n\n#define FONTMAP_SHIFT\t\t10\n\n#define FONTMAP_BITSPERPAGE\t(1 << FONTMAP_SHIFT)\n#define FONTMAP_NUMCHARS\t0x40000\n#define FONTMAP_PAGES\t\t(FONTMAP_NUMCHARS / FONTMAP_BITSPERPAGE)\n\ntypedef struct FontFamily {\n    struct FontFamily *nextPtr;\t/* Next in list of all known font families. */\n    size_t refCount;\t\t/* How many SubFonts are referring to this\n\t\t\t\t * FontFamily. When the refCount drops to\n\t\t\t\t * zero, this FontFamily may be freed. */\n    /*\n     * Key.\n     */\n\n    Tk_Uid foundry;\t\t/* Foundry key for this FontFamily. */\n    Tk_Uid faceName;\t\t/* Face name key for this FontFamily. */\n    Tcl_Encoding encoding;\t/* Encoding key for this FontFamily. */\n\n    /*\n     * Derived properties.\n     */\n\n    int isTwoByteFont;\t\t/* 1 if this is a double-byte font, 0\n\t\t\t\t * otherwise. */\n    char *fontMap[FONTMAP_PAGES];\n\t\t\t\t/* Two-level sparse table used to determine\n\t\t\t\t * quickly if the specified character exists.\n\t\t\t\t * As characters are encountered, more pages\n\t\t\t\t * in this table are dynamically allocated. The\n\t\t\t\t * contents of each page is a bitmask\n\t\t\t\t * consisting of FONTMAP_BITSPERPAGE bits,\n\t\t\t\t * representing whether this font can be used\n\t\t\t\t * to display the given character at the\n\t\t\t\t * corresponding bit position. The high bits\n\t\t\t\t * of the character are used to pick which\n\t\t\t\t * page of the table is used. */\n} FontFamily;\n\n/*\n * The following structure encapsulates an individual screen font. A font\n * object is made up of however many SubFonts are necessary to display a\n * stream of multilingual characters.\n */\n\ntypedef struct SubFont {\n    char **fontMap;\t\t/* Pointer to font map from the FontFamily,\n\t\t\t\t * cached here to save a dereference. */\n    XFontStruct *fontStructPtr;\t/* The specific screen font that will be used\n\t\t\t\t * when displaying/measuring chars belonging\n\t\t\t\t * to the FontFamily. */\n    FontFamily *familyPtr;\t/* The FontFamily for this SubFont. */\n} SubFont;\n\n/*\n * The following structure represents Unix's implementation of a font object.\n */\n\n#define SUBFONT_SPACE\t\t3\n#define BASE_CHARS\t\t256\n\ntypedef struct UnixFont {\n    TkFont font;\t\t/* Stuff used by generic font package. Must be\n\t\t\t\t * first in structure. */\n    SubFont staticSubFonts[SUBFONT_SPACE];\n\t\t\t\t/* Builtin space for a limited number of\n\t\t\t\t * SubFonts. */\n    int numSubFonts;\t\t/* Length of following array. */\n    SubFont *subFontArray;\t/* Array of SubFonts that have been loaded in\n\t\t\t\t * order to draw/measure all the characters\n\t\t\t\t * encountered by this font so far. All fonts\n\t\t\t\t * start off with one SubFont initialized by\n\t\t\t\t * InitFont() from the original set of font\n\t\t\t\t * attributes. Usually points to\n\t\t\t\t * staticSubFonts, but may point to malloced\n\t\t\t\t * space if there are lots of SubFonts. */\n    SubFont controlSubFont;\t/* Font to use to display control-character\n\t\t\t\t * expansions. */\n\n    Display *display;\t\t/* Display that owns font. */\n    int pixelSize;\t\t/* Original pixel size used when font was\n\t\t\t\t * constructed. */\n    TkXLFDAttributes xa;\t/* Additional attributes that specify the\n\t\t\t\t * preferred foundry and encoding to use when\n\t\t\t\t * constructing additional SubFonts. */\n    int widths[BASE_CHARS];\t/* Widths of first 256 chars in the base font,\n\t\t\t\t * for handling common case. */\n    int underlinePos;\t\t/* Offset from baseline to origin of underline\n\t\t\t\t * bar (used when drawing underlined font)\n\t\t\t\t * (pixels). */\n    int barHeight;\t\t/* Height of underline or overstrike bar (used\n\t\t\t\t * when drawing underlined or strikeout font)\n\t\t\t\t * (pixels). */\n} UnixFont;\n\n/*\n * The following structure and definition is used to keep track of the\n * alternative names for various encodings. Asking for an encoding that\n * matches one of the alias patterns will result in actually getting the\n * encoding by its real name.\n */\n\ntypedef struct EncodingAlias {\n    const char *realName;\t/* The real name of the encoding to load if\n\t\t\t\t * the provided name matched the pattern. */\n    const char *aliasPattern;\t/* Pattern for encoding name, of the form that\n\t\t\t\t * is acceptable to Tcl_StringMatch. */\n} EncodingAlias;\n\n/*\n * Just some utility structures used for passing around values in helper\n * functions.\n */\n\ntypedef struct FontAttributes {\n    TkFontAttributes fa;\n    TkXLFDAttributes xa;\n} FontAttributes;\n\ntypedef struct {\n    FontFamily *fontFamilyList; /* The list of font families that are\n\t\t\t\t * currently loaded. As screen fonts are\n\t\t\t\t * loaded, this list grows to hold information\n\t\t\t\t * about what characters exist in each font\n\t\t\t\t * family. */\n    FontFamily controlFamily;\t/* FontFamily used to handle control character\n\t\t\t\t * expansions. The encoding of this FontFamily\n\t\t\t\t * converts UTF-8 to backslashed escape\n\t\t\t\t * sequences. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The set of builtin encoding alises to convert the XLFD names for the\n * encodings into the names expected by the Tcl encoding package.\n */\n\nstatic const EncodingAlias encodingAliases[] = {\n    {\"gb2312-raw\",\t\"gb2312*\"},\n    {\"big5\",\t\t\"big5*\"},\n    {\"cns11643-1\",\t\"cns11643*-1\"},\n    {\"cns11643-1\",\t\"cns11643*.1-0\"},\n    {\"cns11643-2\",\t\"cns11643*-2\"},\n    {\"cns11643-2\",\t\"cns11643*.2-0\"},\n    {\"jis0201\",\t\t\"jisx0201*\"},\n    {\"jis0201\",\t\t\"jisx0202*\"},\n    {\"jis0208\",\t\t\"jisc6226*\"},\n    {\"jis0208\",\t\t\"jisx0208*\"},\n    {\"jis0212\",\t\t\"jisx0212*\"},\n    {\"tis620\",\t\t\"tis620*\"},\n    {\"ksc5601\",\t\t\"ksc5601*\"},\n    {\"dingbats\",\t\"*dingbats\"},\n    {\"ucs-2be\",\t\t\"iso10646-1\"},\n    {NULL,\t\tNULL}\n};\n\n/*\n * Functions used only in this file.\n */\n\nstatic void\t\tFontPkgCleanup(void *clientData);\nstatic FontFamily *\tAllocFontFamily(Display *display,\n\t\t\t    XFontStruct *fontStructPtr, int base);\nstatic SubFont *\tCanUseFallback(UnixFont *fontPtr,\n\t\t\t    const char *fallbackName, int ch,\n\t\t\t    SubFont **fixSubFontPtrPtr);\nstatic SubFont *\tCanUseFallbackWithAliases(UnixFont *fontPtr,\n\t\t\t    const char *fallbackName, int ch,\n\t\t\t    Tcl_DString *nameTriedPtr,\n\t\t\t    SubFont **fixSubFontPtrPtr);\nstatic int\t\tControlUtfProc(void *clientData, const char *src,\n\t\t\t    int srcLen, int flags, Tcl_EncodingState*statePtr,\n\t\t\t    char *dst, int dstLen, int *srcReadPtr,\n\t\t\t    int *dstWrotePtr, int *dstCharsPtr);\nstatic XFontStruct *\tCreateClosestFont(Tk_Window tkwin,\n\t\t\t    const TkFontAttributes *faPtr,\n\t\t\t    const TkXLFDAttributes *xaPtr);\nstatic SubFont *\tFindSubFontForChar(UnixFont *fontPtr, int ch,\n\t\t\t    SubFont **fixSubFontPtrPtr);\nstatic void\t\tFontMapInsert(SubFont *subFontPtr, int ch);\nstatic void\t\tFontMapLoadPage(SubFont *subFontPtr, int row);\nstatic int\t\tFontMapLookup(SubFont *subFontPtr, int ch);\nstatic void\t\tFreeFontFamily(FontFamily *afPtr);\nstatic const char *\tGetEncodingAlias(const char *name);\nstatic int\t\tGetFontAttributes(Display *display,\n\t\t\t    XFontStruct *fontStructPtr, FontAttributes *faPtr);\nstatic XFontStruct *\tGetScreenFont(Display *display,\n\t\t\t    FontAttributes *wantPtr, char **nameList,\n\t\t\t    int bestIdx[], unsigned bestScore[]);\nstatic XFontStruct *\tGetSystemFont(Display *display);\nstatic int\t\tIdentifySymbolEncodings(FontAttributes *faPtr);\nstatic void\t\tInitFont(Tk_Window tkwin, XFontStruct *fontStructPtr,\n\t\t\t    UnixFont *fontPtr);\nstatic void\t\tInitSubFont(Display *display,\n\t\t\t    XFontStruct *fontStructPtr, int base,\n\t\t\t    SubFont *subFontPtr);\nstatic char **\t\tListFonts(Display *display, const char *faceName,\n\t\t\t    int *numNamesPtr);\nstatic char **\t\tListFontOrAlias(Display *display, const char*faceName,\n\t\t\t    int *numNamesPtr);\nstatic unsigned\t\tRankAttributes(FontAttributes *wantPtr,\n\t\t\t    FontAttributes *gotPtr);\nstatic void\t\tReleaseFont(UnixFont *fontPtr);\nstatic void\t\tReleaseSubFont(Display *display, SubFont *subFontPtr);\nstatic int\t\tSeenName(const char *name, Tcl_DString *dsPtr);\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * XLoadQueryFontNoXError --\n *\n *\tThis function is XLoadQueryFont wrapped in a NULL error handler.\n *\tIt is a temporary workaround for ticket [36e379c01b],\n *\t\"macOS Ventura, X11 build with XQuartz: crash in XLoadQueryFont\",\n *\twhich actually is issue #216 in XQuartz:\n *\thttps://github.com/XQuartz/XQuartz/issues/216\n *\n *-------------------------------------------------------------------------\n */\n\nstatic XFontStruct *\nXLoadQueryFontNoXError(Display *display, const char *name)\n{\n    XFontStruct *fontStructPtr = NULL;\n    Tk_ErrorHandler handler;\n\n    /* 45 is the major opcode of X_OpenFont */\n    handler = Tk_CreateErrorHandler(display, BadValue, 45, -1, NULL, NULL);\n    fontStructPtr = XLoadQueryFont(display, name);\n    Tk_DeleteErrorHandler(handler);\n    return fontStructPtr;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FontPkgCleanup --\n *\n *\tThis function is called when an application is created. It initializes\n *\tall the structures that are used by the platform-dependent code on a\n *\tper application basis.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tReleases thread-specific resources used by font pkg.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFontPkgCleanup(\n    TCL_UNUSED(void *))\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->controlFamily.encoding != NULL) {\n\tFontFamily *familyPtr = &tsdPtr->controlFamily;\n\tint i;\n\n\tTcl_FreeEncoding(familyPtr->encoding);\n\tfor (i = 0; i < FONTMAP_PAGES; i++) {\n\t    if (familyPtr->fontMap[i] != NULL) {\n\t\tTcl_Free(familyPtr->fontMap[i]);\n\t    }\n\t}\n\ttsdPtr->controlFamily.encoding = NULL;\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpFontPkgInit --\n *\n *\tThis function is called when an application is created. It initializes\n *\tall the structures that are used by the platform-dependent code on a\n *\tper application basis.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpFontPkgInit(\n    TCL_UNUSED(TkMainInfo *))\t/* The application being created. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    SubFont dummy;\n    int i;\n\n    if (tsdPtr->controlFamily.encoding == NULL) {\n\n\tTcl_EncodingType type = {\"X11ControlChars\", ControlUtfProc, ControlUtfProc, NULL, NULL, 0};\n\ttsdPtr->controlFamily.refCount = 2;\n\ttsdPtr->controlFamily.encoding = Tcl_CreateEncoding(&type);\n\ttsdPtr->controlFamily.isTwoByteFont = 0;\n\n\tdummy.familyPtr = &tsdPtr->controlFamily;\n\tdummy.fontMap = tsdPtr->controlFamily.fontMap;\n\tfor (i = 0x00; i < 0x20; i++) {\n\t    FontMapInsert(&dummy, i);\n\t    FontMapInsert(&dummy, i + 0x80);\n\t}\n\n\t/*\n\t * UCS-2BE is unicode (UCS-2) in big-endian format. Define this if\n\t * if it doesn't exist yet. It is used in iso10646 fonts.\n\t */\n\n\tTcl_CreateThreadExitHandler(FontPkgCleanup, NULL);\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * ControlUtfProc --\n *\n *\tConvert from UTF-8 into the ASCII expansion of a control character.\n *\n * Results:\n *\tReturns TCL_OK if conversion was successful.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nControlUtfProc(\n    TCL_UNUSED(void *),\t/* Not used. */\n    const char *src,\t\t/* Source string in UTF-8. */\n    int srcLen,\t\t\t/* Source string length in bytes. */\n    TCL_UNUSED(int),\t\t\t/* Conversion control flags. */\n    TCL_UNUSED(Tcl_EncodingState *),/* Place for conversion routine to store state\n\t\t\t\t * information used during a piecewise\n\t\t\t\t * conversion. Contents of statePtr are\n\t\t\t\t * initialized and/or reset by conversion\n\t\t\t\t * routine under control of flags argument. */\n    char *dst,\t\t\t/* Output buffer in which converted string is\n\t\t\t\t * stored. */\n    int dstLen,\t\t\t/* The maximum length of output buffer in\n\t\t\t\t * bytes. */\n    int *srcReadPtr,\t\t/* Filled with the number of bytes from the\n\t\t\t\t * source string that were converted. This may\n\t\t\t\t * be less than the original source length if\n\t\t\t\t * there was a problem converting some source\n\t\t\t\t * characters. */\n    int *dstWrotePtr,\t\t/* Filled with the number of bytes that were\n\t\t\t\t * stored in the output buffer as a result of\n\t\t\t\t * the conversion. */\n    int *dstCharsPtr)\t\t/* Filled with the number of characters that\n\t\t\t\t * correspond to the bytes stored in the\n\t\t\t\t * output buffer. */\n{\n    const char *srcStart, *srcEnd;\n    char *dstStart, *dstEnd;\n    int ch, result;\n    static const char hexChars[] = \"0123456789ABCDEF\";\n    static const char mapChars[] = {\n\t0, 0, 0, 0, 0, 0, 0,\n\t'a', 'b', 't', 'n', 'v', 'f', 'r'\n    };\n\n    result = TCL_OK;\n\n    srcStart = src;\n    srcEnd = src + srcLen;\n\n    dstStart = dst;\n    dstEnd = dst + dstLen - 6;\n\n    for ( ; src < srcEnd; ) {\n\tif (dst > dstEnd) {\n\t    result = TCL_CONVERT_NOSPACE;\n\t    break;\n\t}\n\tsrc += Tcl_UtfToUniChar(src, &ch);\n\tdst[0] = '\\\\';\n\tif (((size_t)ch < sizeof(mapChars)) && (mapChars[ch] != 0)) {\n\t    dst[1] = mapChars[ch];\n\t    dst += 2;\n\t} else if ((size_t)ch < 256) {\n\t    dst[1] = 'x';\n\t    dst[2] = hexChars[(ch >> 4) & 0xF];\n\t    dst[3] = hexChars[ch & 0xF];\n\t    dst += 4;\n\t} else if ((size_t)ch < 0x10000) {\n\t    dst[1] = 'u';\n\t    dst[2] = hexChars[(ch >> 12) & 0xF];\n\t    dst[3] = hexChars[(ch >> 8) & 0xF];\n\t    dst[4] = hexChars[(ch >> 4) & 0xF];\n\t    dst[5] = hexChars[ch & 0xF];\n\t    dst += 6;\n\t} else {\n\t    /* TODO we can do better here */\n\t    dst[1] = 'u';\n\t    dst[2] = 'F';\n\t    dst[3] = 'F';\n\t    dst[4] = 'F';\n\t    dst[5] = 'D';\n\t    dst += 6;\n\t}\n    }\n    *srcReadPtr = src - srcStart;\n    *dstWrotePtr = dst - dstStart;\n    *dstCharsPtr = dst - dstStart;\n    return result;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetNativeFont --\n *\n *\tMap a platform-specific native font name to a TkFont.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the native\n *\tfont. If a native font by the given name could not be found, the\n *\treturn value is NULL.\n *\n *\tEvery call to this function returns a new TkFont structure, even if\n *\tthe name has already been seen before. The caller should call\n *\tTkpDeleteFont() when the font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generic TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetNativeFont(\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const char *name)\t\t/* Platform-specific font name. */\n{\n    UnixFont *fontPtr;\n    XFontStruct *fontStructPtr;\n    FontAttributes fa;\n    const char *p;\n    int hasSpace, dashes, hasWild;\n\n    /*\n     * The behavior of X when given a name that isn't an XLFD is unspecified.\n     * For example, Exceed 6 returns a valid font for any random string. This\n     * is awkward since system names have higher priority than the other Tk\n     * font syntaxes. So, we need to perform a quick sanity check on the name\n     * and fail if it looks suspicious. We fail if the name:\n     *     - contains a space immediately before a dash\n     *\t   - contains a space, but no '*' characters and fewer than 14 dashes\n     */\n\n    hasSpace = dashes = hasWild = 0;\n    for (p = name; *p != '\\0'; p++) {\n\tif (*p == ' ') {\n\t    if (p[1] == '-') {\n\t\treturn NULL;\n\t    }\n\t    hasSpace = 1;\n\t} else if (*p == '-') {\n\t    dashes++;\n\t} else if (*p == '*') {\n\t    hasWild = 1;\n\t}\n    }\n    if ((dashes < 14) && !hasWild && hasSpace) {\n\treturn NULL;\n    }\n\n    fontStructPtr = XLoadQueryFontNoXError(Tk_Display(tkwin), (char *)name);\n    if (fontStructPtr == NULL) {\n\t/*\n\t * Handle all names that look like XLFDs here. Otherwise, when\n\t * TkpGetFontFromAttributes is called from generic code, any foundry\n\t * or encoding information specified in the XLFD will have been parsed\n\t * out and lost. But make sure we don't have an \"-option value\" string\n\t * since TkFontParseXLFD would return a false success when attempting\n\t * to parse it.\n\t */\n\n\tif (name[0] == '-') {\n\t    if (name[1] != '*') {\n\t\tconst char *dash;\n\n\t\tdash = strchr(name + 1, '-');\n\t\tif ((dash == NULL) || (isspace(UCHAR(dash[-1])))) {\n\t\t    return NULL;\n\t\t}\n\t    }\n\t} else if (name[0] != '*') {\n\t    return NULL;\n\t}\n\tif (TkFontParseXLFD(name, &fa.fa, &fa.xa) != TCL_OK) {\n\t    return NULL;\n\t}\n\tfontStructPtr = CreateClosestFont(tkwin, &fa.fa, &fa.xa);\n    }\n    fontPtr = (UnixFont *)Tcl_Alloc(sizeof(UnixFont));\n    InitFont(tkwin, fontStructPtr, fontPtr);\n\n    return (TkFont *) fontPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFromAttributes --\n *\n *\tGiven a desired set of attributes for a font, find a font with the\n *\tclosest matching attributes.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the font\n *\twith the desired attributes. If a font with the desired attributes\n *\tcould not be constructed, some other font will be substituted\n *\tautomatically.\n *\n *\tEvery call to this function returns a new TkFont structure, even if\n *\tthe specified attributes have already been seen before. The caller\n *\tshould call TkpDeleteFont() to free the platform- specific data when\n *\tthe font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generic TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetFontFromAttributes(\n    TkFont *tkFontPtr,\t\t/* If non-NULL, store the information in this\n\t\t\t\t * existing TkFont structure, rather than\n\t\t\t\t * allocating a new structure to hold the\n\t\t\t\t * font; the existing contents of the font\n\t\t\t\t * will be released. If NULL, a new TkFont\n\t\t\t\t * structure is allocated. */\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const TkFontAttributes *faPtr)\n\t\t\t\t/* Set of attributes to match. */\n{\n    UnixFont *fontPtr;\n    TkXLFDAttributes xa;\n    XFontStruct *fontStructPtr;\n\n    TkInitXLFDAttributes(&xa);\n    fontStructPtr = CreateClosestFont(tkwin, faPtr, &xa);\n\n    fontPtr = (UnixFont *) tkFontPtr;\n    if (fontPtr == NULL) {\n\tfontPtr = (UnixFont *)Tcl_Alloc(sizeof(UnixFont));\n    } else {\n\tReleaseFont(fontPtr);\n    }\n    InitFont(tkwin, fontStructPtr, fontPtr);\n\n    fontPtr->font.fa.underline = faPtr->underline;\n    fontPtr->font.fa.overstrike = faPtr->overstrike;\n\n    return (TkFont *) fontPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpDeleteFont --\n *\n *\tCalled to release a font allocated by TkpGetNativeFont() or\n *\tTkpGetFontFromAttributes(). The caller should have already released\n *\tthe fields of the TkFont that are used exclusively by the generic\n *\tTkFont code.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTkFont is deallocated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpDeleteFont(\n    TkFont *tkFontPtr)\t\t/* Token of font to be deleted. */\n{\n    UnixFont *fontPtr = (UnixFont *) tkFontPtr;\n\n    ReleaseFont(fontPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFamilies --\n *\n *\tReturn information about the font families that are available on the\n *\tdisplay of the given window.\n *\n * Results:\n *\tModifies interp's result object to hold a list of all the available\n *\tfont families.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontFamilies(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Window tkwin)\t\t/* For display to query. */\n{\n    int i, isNew, numNames;\n    char *family, **nameList;\n    Tcl_HashTable familyTable;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n    Tcl_Obj *resultPtr, *strPtr;\n\n    Tcl_InitHashTable(&familyTable, TCL_STRING_KEYS);\n    nameList = ListFonts(Tk_Display(tkwin), \"*\", &numNames);\n    for (i = 0; i < numNames; i++) {\n\tchar *familyEnd;\n\n\tfamily = strchr(nameList[i] + 1, '-');\n\tif (family == NULL) {\n\t    /*\n\t     * Apparently, sometimes ListFonts() can return a font name with\n\t     * zero or one '-' character in it. This is probably indicative of\n\t     * a server misconfiguration, but crashing because of it is a very\n\t     * bad idea anyway. [Bug 1475865]\n\t     */\n\n\t    continue;\n\t}\n\tfamily++;\t\t\t/* Advance to char after '-'. */\n\tfamilyEnd = strchr(family, '-');\n\tif (familyEnd == NULL) {\n\t    continue;\t\t\t/* See comment above. */\n\t}\n\t*familyEnd = '\\0';\n\tTcl_CreateHashEntry(&familyTable, family, &isNew);\n    }\n    XFreeFontNames(nameList);\n\n    hPtr = Tcl_FirstHashEntry(&familyTable, &search);\n    resultPtr = Tcl_NewObj();\n    while (hPtr != NULL) {\n\tstrPtr = Tcl_NewStringObj((const char *)Tcl_GetHashKey(&familyTable, hPtr), TCL_INDEX_NONE);\n\tTcl_ListObjAppendElement(NULL, resultPtr, strPtr);\n\thPtr = Tcl_NextHashEntry(&search);\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n\n    Tcl_DeleteHashTable(&familyTable);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpGetSubFonts --\n *\n *\tA function used by the testing package for querying the actual screen\n *\tfonts that make up a font object.\n *\n * Results:\n *\tModifies interp's result object to hold a list containing the names of\n *\tthe screen fonts that make up the given font object.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpGetSubFonts(\n    Tcl_Interp *interp,\n    Tk_Font tkfont)\n{\n    int i;\n    Tcl_Obj *objv[3], *resultPtr, *listPtr;\n    UnixFont *fontPtr;\n    FontFamily *familyPtr;\n\n    resultPtr = Tcl_NewObj();\n    fontPtr = (UnixFont *) tkfont;\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tfamilyPtr = fontPtr->subFontArray[i].familyPtr;\n\tobjv[0] = Tcl_NewStringObj(familyPtr->faceName, TCL_INDEX_NONE);\n\tobjv[1] = Tcl_NewStringObj(familyPtr->foundry, TCL_INDEX_NONE);\n\tobjv[2] = Tcl_NewStringObj(\n\t\tTcl_GetEncodingName(familyPtr->encoding), TCL_INDEX_NONE);\n\tlistPtr = Tcl_NewListObj(3, objv);\n\tTcl_ListObjAppendElement(NULL, resultPtr, listPtr);\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetFontAttrsForChar --\n *\n *\tRetrieve the font attributes of the actual font used to render a given\n *\tcharacter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe font attributes are stored in *faPtr.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontAttrsForChar(\n    Tk_Window tkwin,\t\t/* Window on the font's display */\n    Tk_Font tkfont,\t\t/* Font to query */\n    int c,\t\t\t/* Character of interest */\n    TkFontAttributes *faPtr)\t/* Output: Font attributes */\n{\n    FontAttributes atts;\n    UnixFont *fontPtr = (UnixFont *) tkfont;\n\t\t\t\t/* Structure describing the logical font */\n    SubFont *lastSubFontPtr = &fontPtr->subFontArray[0];\n\t\t\t\t/* Pointer to subfont array in case\n\t\t\t\t * FindSubFontForChar needs to fix up the\n\t\t\t\t * memory allocation */\n    SubFont *thisSubFontPtr = FindSubFontForChar(fontPtr, c, &lastSubFontPtr);\n\t\t\t\t/* Pointer to the subfont to use for the given\n\t\t\t\t * character */\n\n    GetFontAttributes(Tk_Display(tkwin), thisSubFontPtr->fontStructPtr, &atts);\n    *faPtr = atts.fa;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureChars --\n *\n *\tDetermine the number of characters from the string that will fit in\n *\tthe given horizontal span. The measurement is done under the\n *\tassumption that Tk_DrawChars() will be used to actually display the\n *\tcharacters.\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureChars(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    Tcl_Size numBytes,\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length in pixels; don't\n\t\t\t\t * consider any character that would cross\n\t\t\t\t * this x-position. If < 0, then line length\n\t\t\t\t * is unbounded and the flags argument is\n\t\t\t\t * ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fit on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character even if\n\t\t\t\t * no characters fit. */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    UnixFont *fontPtr;\n    SubFont *lastSubFontPtr;\n    Tcl_Size curByte;\n    int curX, ch;\n\n    /*\n     * Unix does not use kerning or fractional character widths when\n     * displaying text on the screen. So that means we can safely measure\n     * individual characters or spans of characters and add up the widths w/o\n     * any \"off-by-one-pixel\" errors.\n     */\n\n    fontPtr = (UnixFont *) tkfont;\n\n    lastSubFontPtr = &fontPtr->subFontArray[0];\n\n    if (numBytes == 0) {\n\tcurX = 0;\n\tcurByte = 0;\n    } else if (maxLength < 0) {\n\tconst char *p, *end, *next;\n\tSubFont *thisSubFontPtr;\n\tFontFamily *familyPtr;\n\tTcl_DString runString;\n\n\t/*\n\t * A three step process:\n\t * 1. Find a contiguous range of characters that can all be\n\t *    represented by a single screen font.\n\t * 2. Convert those chars to the encoding of that font.\n\t * 3. Measure converted chars.\n\t */\n\n\tcurX = 0;\n\tend = source + numBytes;\n\tfor (p = source; p < end; ) {\n\t    next = p + Tcl_UtfToUniChar(p, &ch);\n\t    thisSubFontPtr = FindSubFontForChar(fontPtr, ch, &lastSubFontPtr);\n\t    if (thisSubFontPtr != lastSubFontPtr) {\n\t\tfamilyPtr = lastSubFontPtr->familyPtr;\n\t\t(void)Tcl_UtfToExternalDString(familyPtr->encoding, source,\n\t\t\tp - source, &runString);\n\t\tif (familyPtr->isTwoByteFont) {\n\t\t    curX += XTextWidth16(lastSubFontPtr->fontStructPtr,\n\t\t\t    (XChar2b *) Tcl_DStringValue(&runString),\n\t\t\t    Tcl_DStringLength(&runString) / 2);\n\t\t} else {\n\t\t    curX += XTextWidth(lastSubFontPtr->fontStructPtr,\n\t\t\t    Tcl_DStringValue(&runString),\n\t\t\t    Tcl_DStringLength(&runString));\n\t\t}\n\t\tTcl_DStringFree(&runString);\n\t\tlastSubFontPtr = thisSubFontPtr;\n\t\tsource = p;\n\t    }\n\t    p = next;\n\t}\n\tfamilyPtr = lastSubFontPtr->familyPtr;\n\t(void)Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,\n\t\t&runString);\n\tif (familyPtr->isTwoByteFont) {\n\t    curX += XTextWidth16(lastSubFontPtr->fontStructPtr,\n\t\t    (XChar2b *) Tcl_DStringValue(&runString),\n\t\t    Tcl_DStringLength(&runString) >> 1);\n\t} else {\n\t    curX += XTextWidth(lastSubFontPtr->fontStructPtr,\n\t\t    Tcl_DStringValue(&runString),\n\t\t    Tcl_DStringLength(&runString));\n\t}\n\tTcl_DStringFree(&runString);\n\tcurByte = numBytes;\n    } else {\n\tconst char *p, *end, *next, *term;\n\tint newX, termX, sawNonSpace, dstWrote;\n\tFontFamily *familyPtr;\n\tXChar2b buf[8];\n\n\t/*\n\t * How many chars will fit in the space allotted? This first version\n\t * may be inefficient because it measures every character\n\t * individually.\n\t */\n\n\tnext = source + Tcl_UtfToUniChar(source, &ch);\n\tnewX = curX = termX = 0;\n\n\tterm = source;\n\tend = source + numBytes;\n\n\tsawNonSpace = (ch > 255) || !isspace(ch);\n\tfamilyPtr = lastSubFontPtr->familyPtr;\n\tfor (p = source; ; ) {\n\t    if ((ch < BASE_CHARS) && (fontPtr->widths[ch] != 0)) {\n\t\tnewX += fontPtr->widths[ch];\n\t    } else {\n\t\tlastSubFontPtr = FindSubFontForChar(fontPtr, ch, NULL);\n\t\tfamilyPtr = lastSubFontPtr->familyPtr;\n\t\tTcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p, TCL_ENCODING_PROFILE_TCL8, NULL,\n\t\t\t(char *)&buf[0].byte1, sizeof(buf), NULL, &dstWrote, NULL);\n\t\tif (familyPtr->isTwoByteFont) {\n\t\t    newX += XTextWidth16(lastSubFontPtr->fontStructPtr,\n\t\t\t    buf, dstWrote >> 1);\n\t\t} else {\n\t\t    newX += XTextWidth(lastSubFontPtr->fontStructPtr,\n\t\t\t    (char *)&buf[0].byte1, dstWrote);\n\t\t}\n\t    }\n\t    if (newX > maxLength) {\n\t\tbreak;\n\t    }\n\t    curX = newX;\n\t    p = next;\n\t    if (p >= end) {\n\t\tterm = end;\n\t\ttermX = curX;\n\t\tbreak;\n\t    }\n\n\t    next += Tcl_UtfToUniChar(next, &ch);\n\t    if ((ch < 256) && isspace(ch)) {\n\t\tif (sawNonSpace) {\n\t\t    term = p;\n\t\t    termX = curX;\n\t\t    sawNonSpace = 0;\n\t\t}\n\t    } else {\n\t\tsawNonSpace = 1;\n\t    }\n\t}\n\n\t/*\n\t * P points to the first character that doesn't fit in the desired\n\t * span. Use the flags to figure out what to return.\n\t */\n\n\tif ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {\n\t    /*\n\t     * Include the first character that didn't quite fit in the\n\t     * desired span. The width returned will include the width of that\n\t     * extra character.\n\t     */\n\n\t    curX = newX;\n\t    p += Tcl_UtfToUniChar(p, &ch);\n\t}\n\tif ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {\n\t    term = p;\n\t    termX = curX;\n\t    if (term == source) {\n\t\tterm += Tcl_UtfToUniChar(term, &ch);\n\t\ttermX = newX;\n\t    }\n\t} else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {\n\t    term = p;\n\t    termX = curX;\n\t}\n\n\tcurX = termX;\n\tcurByte = term - source;\n    }\n\n    *lengthPtr = curX;\n    return curByte;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureCharsInContext --\n *\n *\tDetermine the number of bytes from the string that will fit in the\n *\tgiven horizontal span. The measurement is done under the assumption\n *\tthat Tk_DrawCharsInContext() will be used to actually display the\n *\tcharacters.\n *\n *\tThis one is almost the same as Tk_MeasureChars(), but with access to\n *\tall the characters on the line for context. On X11 this context isn't\n *\tconsulted, so we just call Tk_MeasureChars().\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureCharsInContext(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string in all. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to measure. */\n    Tcl_Size rangeLength,\t\t/* Length of range to measure in bytes. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length; don't consider any\n\t\t\t\t * character that would cross this x-position.\n\t\t\t\t * If < 0, then line length is unbounded and\n\t\t\t\t * the flags argument is ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fit on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character even if\n\t\t\t\t * no characters fit. TK_ISOLATE_END means\n\t\t\t\t * that the last character should not be\n\t\t\t\t * considered in context with the rest of the\n\t\t\t\t * string (used for breaking lines). */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,\n\t    maxLength, flags, lengthPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawChars --\n *\n *\tDraw a string of characters on the screen. Tk_DrawChars() expands\n *\tcontrol characters that occur in the string to \\xNN sequences.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int x, int y)\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n{\n    UnixFont *fontPtr = (UnixFont *) tkfont;\n    SubFont *thisSubFontPtr, *lastSubFontPtr;\n    Tcl_DString runString;\n    const char *p, *end, *next;\n    int xStart, needWidth, window_width, do_width, ch;\n    FontFamily *familyPtr;\n#ifdef TK_DRAW_CHAR_XWINDOW_CHECK\n    int rx, ry;\n    unsigned width, height, border_width, depth;\n    Drawable root;\n#endif\n\n    lastSubFontPtr = &fontPtr->subFontArray[0];\n    xStart = x;\n\n#ifdef TK_DRAW_CHAR_XWINDOW_CHECK\n    /*\n     * Get the window width so we can abort drawing outside of the window\n     */\n\n    if (XGetGeometry(display, drawable, &root, &rx, &ry, &width, &height,\n\t    &border_width, &depth) == False) {\n\twindow_width = INT_MAX;\n    } else {\n\twindow_width = width;\n    }\n#else\n    /*\n     * This is used by default until we find a solution that doesn't do a\n     * round-trip to the X server (needed to get Tk cached window width).\n     */\n\n    window_width = 32768;\n#endif\n\n    end = source + numBytes;\n    needWidth = fontPtr->font.fa.underline + fontPtr->font.fa.overstrike;\n    for (p = source; p <= end; ) {\n\tif (p < end) {\n\t    next = p + Tcl_UtfToUniChar(p, &ch);\n\t    thisSubFontPtr = FindSubFontForChar(fontPtr, ch, &lastSubFontPtr);\n\t} else {\n\t    next = p + 1;\n\t    thisSubFontPtr = lastSubFontPtr;\n\t}\n\tif ((thisSubFontPtr != lastSubFontPtr)\n\t\t|| (p == end) || (p-source > 200)) {\n\t    if (p > source) {\n\t\tdo_width = (needWidth || (p != end)) ? 1 : 0;\n\t\tfamilyPtr = lastSubFontPtr->familyPtr;\n\n\t\t(void)Tcl_UtfToExternalDString(familyPtr->encoding, source,\n\t\t\tp - source, &runString);\n\t\tif (familyPtr->isTwoByteFont) {\n\t\t    XDrawString16(display, drawable, gc, x, y,\n\t\t\t    (XChar2b *) Tcl_DStringValue(&runString),\n\t\t\t    Tcl_DStringLength(&runString) / 2);\n\t\t    if (do_width) {\n\t\t\tx += XTextWidth16(lastSubFontPtr->fontStructPtr,\n\t\t\t\t(XChar2b *) Tcl_DStringValue(&runString),\n\t\t\t\tTcl_DStringLength(&runString) / 2);\n\t\t    }\n\t\t} else {\n\t\t    XDrawString(display, drawable, gc, x, y,\n\t\t\t    Tcl_DStringValue(&runString),\n\t\t\t    Tcl_DStringLength(&runString));\n\t\t    if (do_width) {\n\t\t\tx += XTextWidth(lastSubFontPtr->fontStructPtr,\n\t\t\t\tTcl_DStringValue(&runString),\n\t\t\t\tTcl_DStringLength(&runString));\n\t\t    }\n\t\t}\n\t\tTcl_DStringFree(&runString);\n\t    }\n\t    lastSubFontPtr = thisSubFontPtr;\n\t    source = p;\n\t    XSetFont(display, gc, lastSubFontPtr->fontStructPtr->fid);\n\t    if (x > window_width) {\n\t\tbreak;\n\t    }\n\t}\n\tp = next;\n    }\n\n    if (lastSubFontPtr != &fontPtr->subFontArray[0]) {\n\tXSetFont(display, gc, fontPtr->subFontArray[0].fontStructPtr->fid);\n    }\n\n    if (fontPtr->font.fa.underline != 0) {\n\tXFillRectangle(display, drawable, gc, xStart,\n\t\ty + fontPtr->underlinePos,\n\t\t(unsigned) (x - xStart), (unsigned) fontPtr->barHeight);\n    }\n    if (fontPtr->font.fa.overstrike != 0) {\n\ty -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10;\n\tXFillRectangle(display, drawable, gc, xStart, y,\n\t\t(unsigned) (x - xStart), (unsigned) fontPtr->barHeight);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawCharsInContext --\n *\n *\tDraw a string of characters on the screen like Tk_DrawChars(), but\n *\twith access to all the characters on the line for context. On X11 this\n *\tcontext isn't consulted, so we just call Tk_DrawChars().\n *\n *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this\n *            function is unused.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    int x, int y)\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n{\n    int widthUntilStart;\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+widthUntilStart, y);\n}\n\f\nvoid\nTkpDrawAngledCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength1,\t\t/* Length of range to draw in bytes. */\n    double x, double y,\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    int rangeLength = rangeLength1;\n    int widthUntilStart;\n    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * CreateClosestFont --\n *\n *\tHelper for TkpGetNativeFont() and TkpGetFontFromAttributes(). Given a\n *\tset of font attributes, construct a close XFontStruct. If requested\n *\tface name is not available, automatically substitutes an alias for\n *\trequested face name. If encoding is not specified (or the requested\n *\tone is not available), automatically chooses another encoding from the\n *\tlist of preferred encodings. If the foundry is not specified (or is\n *\tnot available) automatically prefers \"adobe\" foundry. For all other\n *\tattributes, if the requested value was not available, the appropriate\n *\t\"close\" value will be used.\n *\n * Results:\n *\tReturn value is the XFontStruct that best matched the requested\n *\tattributes. The return value is never NULL; some font will always be\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic XFontStruct *\nCreateClosestFont(\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const TkFontAttributes *faPtr,\n\t\t\t\t/* Set of generic attributes to match. */\n    const TkXLFDAttributes *xaPtr)\n\t\t\t\t/* Set of X-specific attributes to match. */\n{\n    FontAttributes want;\n    char **nameList;\n    int numNames, nameIdx, bestIdx[2];\n    Display *display;\n    XFontStruct *fontStructPtr;\n    unsigned bestScore[2];\n\n    want.fa = *faPtr;\n    want.xa = *xaPtr;\n\n    if (want.xa.foundry == NULL) {\n\twant.xa.foundry = Tk_GetUid(\"adobe\");\n    }\n    if (want.fa.family == NULL) {\n\twant.fa.family = Tk_GetUid(\"fixed\");\n    }\n    want.fa.size = -TkFontGetPixels(tkwin, faPtr->size);\n    if (want.xa.charset == NULL || *want.xa.charset == '\\0') {\n\twant.xa.charset = Tk_GetUid(\"iso8859-1\");\t/* locale. */\n    }\n\n    display = Tk_Display(tkwin);\n\n    /*\n     * Algorithm to get the closest font to the name requested.\n     *\n     * try fontname\n     * try all aliases for fontname\n     * foreach fallback for fontname\n     *\t    try the fallback\n     *\t    try all aliases for the fallback\n     */\n\n    nameList = ListFontOrAlias(display, want.fa.family, &numNames);\n    if (numNames == 0) {\n\tconst char *const *const *fontFallbacks;\n\tint i, j;\n\tconst char *fallback;\n\n\tfontFallbacks = TkFontGetFallbacks();\n\tfor (i = 0; fontFallbacks[i] != NULL; i++) {\n\t    for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t\tif (strcasecmp(want.fa.family, fallback) == 0) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (fallback != NULL) {\n\t\tfor (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t\t    nameList = ListFontOrAlias(display, fallback, &numNames);\n\t\t    if (numNames != 0) {\n\t\t\tgoto found;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tnameList = ListFonts(display, \"fixed\", &numNames);\n\tif (numNames == 0) {\n\t    nameList = ListFonts(display, \"*\", &numNames);\n\t}\n\tif (numNames == 0) {\n\t    return GetSystemFont(display);\n\t}\n    }\n\n  found:\n    bestIdx[0] = -1;\n    bestIdx[1] = -1;\n    bestScore[0] = (unsigned) -1;\n    bestScore[1] = (unsigned) -1;\n    for (nameIdx = 0; nameIdx < numNames; nameIdx++) {\n\tFontAttributes got;\n\tint scalable;\n\tunsigned score;\n\n\tif (TkFontParseXLFD(nameList[nameIdx], &got.fa, &got.xa) != TCL_OK) {\n\t    continue;\n\t}\n\tIdentifySymbolEncodings(&got);\n\tscalable = (got.fa.size == 0.0);\n\tscore = RankAttributes(&want, &got);\n\tif (score < bestScore[scalable]) {\n\t    bestIdx[scalable] = nameIdx;\n\t    bestScore[scalable] = score;\n\t}\n\tif (score == 0) {\n\t    break;\n\t}\n    }\n\n    fontStructPtr = GetScreenFont(display, &want, nameList, bestIdx,\n\t    bestScore);\n    XFreeFontNames(nameList);\n\n    if (fontStructPtr == NULL) {\n\treturn GetSystemFont(display);\n    }\n    return fontStructPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitFont --\n *\n *\tHelper for TkpGetNativeFont() and TkpGetFontFromAttributes().\n *\tInitializes the memory for a new UnixFont that wraps the\n *\tplatform-specific data.\n *\n *\tThe caller is responsible for initializing the fields of the TkFont\n *\tthat are used exclusively by the generic TkFont code, and for\n *\treleasing those fields before calling TkpDeleteFont().\n *\n * Results:\n *\tFills the WinFont structure.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitFont(\n    Tk_Window tkwin,\t\t/* For screen where font will be used. */\n    XFontStruct *fontStructPtr,\t/* X information about font. */\n    UnixFont *fontPtr)\t\t/* Filled with information constructed from\n\t\t\t\t * the above arguments. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    unsigned long value;\n    int minHi, maxHi, minLo, maxLo, fixed, width, limit, i, n;\n    FontAttributes fa;\n    TkFontAttributes *faPtr;\n    TkFontMetrics *fmPtr;\n    SubFont *controlPtr, *subFontPtr;\n    char *pageMap;\n    Display *display;\n\n    /*\n     * Get all font attributes and metrics.\n     */\n\n    display = Tk_Display(tkwin);\n    GetFontAttributes(display, fontStructPtr, &fa);\n\n    minHi = fontStructPtr->min_byte1;\n    maxHi = fontStructPtr->max_byte1;\n    minLo = fontStructPtr->min_char_or_byte2;\n    maxLo = fontStructPtr->max_char_or_byte2;\n\n    fixed = 1;\n    if (fontStructPtr->per_char != NULL) {\n\twidth = 0;\n\tlimit = (maxHi - minHi + 1) * (maxLo - minLo + 1);\n\tfor (i = 0; i < limit; i++) {\n\t    n = fontStructPtr->per_char[i].width;\n\t    if (n != 0) {\n\t\tif (width == 0) {\n\t\t    width = n;\n\t\t} else if (width != n) {\n\t\t    fixed = 0;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    }\n\n    fontPtr->font.fid = fontStructPtr->fid;\n\n    faPtr = &fontPtr->font.fa;\n    faPtr->family = fa.fa.family;\n    faPtr->size = TkFontGetPoints(tkwin, fa.fa.size);\n    faPtr->weight = fa.fa.weight;\n    faPtr->slant = fa.fa.slant;\n    faPtr->underline = 0;\n    faPtr->overstrike = 0;\n\n    fmPtr = &fontPtr->font.fm;\n    fmPtr->ascent = fontStructPtr->ascent;\n    fmPtr->descent = fontStructPtr->descent;\n    fmPtr->maxWidth = fontStructPtr->max_bounds.width;\n    fmPtr->fixed = fixed;\n\n    fontPtr->display = display;\n    fontPtr->pixelSize = (int)(TkFontGetPixels(tkwin, fa.fa.size) + 0.5);\n    fontPtr->xa = fa.xa;\n\n    fontPtr->numSubFonts = 1;\n    fontPtr->subFontArray = fontPtr->staticSubFonts;\n    InitSubFont(display, fontStructPtr, 1, &fontPtr->subFontArray[0]);\n\n    fontPtr->controlSubFont = fontPtr->subFontArray[0];\n    subFontPtr = FindSubFontForChar(fontPtr, '0', NULL);\n    controlPtr = &fontPtr->controlSubFont;\n    controlPtr->fontStructPtr = subFontPtr->fontStructPtr;\n    controlPtr->familyPtr = &tsdPtr->controlFamily;\n    controlPtr->fontMap = tsdPtr->controlFamily.fontMap;\n\n    pageMap = fontPtr->subFontArray[0].fontMap[0];\n    for (i = 0; i < 256; i++) {\n\tif ((minHi > 0) || (i < minLo) || (i > maxLo)\n\t\t|| !((pageMap[i>>3] >> (i&7)) & 1)) {\n\t    n = 0;\n\t} else if (fontStructPtr->per_char == NULL) {\n\t    n = fontStructPtr->max_bounds.width;\n\t} else {\n\t    n = fontStructPtr->per_char[i - minLo].width;\n\t}\n\tfontPtr->widths[i] = n;\n    }\n\n    if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_POSITION, &value)) {\n\tfontPtr->underlinePos = value;\n    } else {\n\t/*\n\t * If the XA_UNDERLINE_POSITION property does not exist, the X manual\n\t * recommends using the following value:\n\t */\n\n\tfontPtr->underlinePos = fontStructPtr->descent / 2;\n    }\n    fontPtr->barHeight = 0;\n    if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_THICKNESS, &value)) {\n\tfontPtr->barHeight = value;\n    }\n    if (fontPtr->barHeight == 0) {\n\t/*\n\t * If the XA_UNDERLINE_THICKNESS property does not exist, the X manual\n\t * recommends using the width of the stem on a capital letter. I don't\n\t * know of a way to get the stem width of a letter, so guess and use\n\t * 1/3 the width of a capital I.\n\t */\n\n\tfontPtr->barHeight = fontPtr->widths[(unsigned char)'I'] / 3;\n\tif (fontPtr->barHeight == 0) {\n\t    fontPtr->barHeight = 1;\n\t}\n    }\n    if (fontPtr->underlinePos + fontPtr->barHeight > fontStructPtr->descent) {\n\t/*\n\t * If this set of cobbled together values would cause the bottom of\n\t * the underline bar to stick below the descent of the font, jack the\n\t * underline up a bit higher.\n\t */\n\n\tfontPtr->barHeight = fontStructPtr->descent - fontPtr->underlinePos;\n\tif (fontPtr->barHeight == 0) {\n\t    fontPtr->underlinePos--;\n\t    fontPtr->barHeight = 1;\n\t}\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * ReleaseFont --\n *\n *\tCalled to release the unix-specific contents of a TkFont. The caller\n *\tis responsible for freeing the memory used by the font itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nReleaseFont(\n    UnixFont *fontPtr)\t\t/* The font to delete. */\n{\n    int i;\n\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tReleaseSubFont(fontPtr->display, &fontPtr->subFontArray[i]);\n    }\n    if (fontPtr->subFontArray != fontPtr->staticSubFonts) {\n\tTcl_Free(fontPtr->subFontArray);\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * InitSubFont --\n *\n *\tWrap a screen font and load the FontFamily that represents it. Used to\n *\tprepare a SubFont so that characters can be mapped from UTF-8 to the\n *\tcharset of the font.\n *\n * Results:\n *\tThe subFontPtr is filled with information about the font.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nInitSubFont(\n    Display *display,\t\t/* Display in which font will be used. */\n    XFontStruct *fontStructPtr,\t/* The screen font. */\n    int base,\t\t\t/* Non-zero if this SubFont is being used as\n\t\t\t\t * the base font for a font object. */\n    SubFont *subFontPtr)\t/* Filled with SubFont constructed from above\n\t\t\t\t * attributes. */\n{\n    subFontPtr->fontStructPtr = fontStructPtr;\n    subFontPtr->familyPtr = AllocFontFamily(display, fontStructPtr, base);\n    subFontPtr->fontMap = subFontPtr->familyPtr->fontMap;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * ReleaseSubFont --\n *\n *\tCalled to release the contents of a SubFont. The caller is responsible\n *\tfor freeing the memory used by the SubFont itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and resources are freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nReleaseSubFont(\n    Display *display,\t\t/* Display which owns screen font. */\n    SubFont *subFontPtr)\t/* The SubFont to delete. */\n{\n    XFreeFont(display, subFontPtr->fontStructPtr);\n    FreeFontFamily(subFontPtr->familyPtr);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * AllocFontFamily --\n *\n *\tFind the FontFamily structure associated with the given font name.\n *\tThe information should be stored by the caller in a SubFont and used\n *\twhen determining if that SubFont supports a character.\n *\n *\tCannot use the string name used to construct the font as the key,\n *\tbecause the capitalization may not be canonical. Therefore use the\n *\tface name actually retrieved from the font metrics as the key.\n *\n * Results:\n *\tA pointer to a FontFamily. The reference count in the FontFamily is\n *\tautomatically incremented. When the SubFont is released, the reference\n *\tcount is decremented. When no SubFont is using this FontFamily, it may\n *\tbe deleted.\n *\n * Side effects:\n *\tA new FontFamily structure will be allocated if this font family has\n *\tnot been seen. TrueType character existence metrics are loaded into\n *\tthe FontFamily structure.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic FontFamily *\nAllocFontFamily(\n    Display *display,\t\t/* Display in which font will be used. */\n    XFontStruct *fontStructPtr,\t/* Screen font whose FontFamily is to be\n\t\t\t\t * returned. */\n    TCL_UNUSED(int))\t\t\t/* Non-zero if this font family is to be used\n\t\t\t\t * in the base font of a font object. */\n{\n    FontFamily *familyPtr;\n    FontAttributes fa;\n    Tcl_Encoding encoding;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    GetFontAttributes(display, fontStructPtr, &fa);\n    encoding = Tcl_GetEncoding(NULL, GetEncodingAlias(fa.xa.charset));\n\n    familyPtr = tsdPtr->fontFamilyList;\n    for (; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {\n\tif ((familyPtr->faceName == fa.fa.family)\n\t\t&& (familyPtr->foundry == fa.xa.foundry)\n\t\t&& (familyPtr->encoding == encoding)) {\n\t    if (encoding) {\n\t\tTcl_FreeEncoding(encoding);\n\t    }\n\t    familyPtr->refCount++;\n\t    return familyPtr;\n\t}\n    }\n\n    familyPtr = (FontFamily *)Tcl_Alloc(sizeof(FontFamily));\n    memset(familyPtr, 0, sizeof(FontFamily));\n    familyPtr->nextPtr = tsdPtr->fontFamilyList;\n    tsdPtr->fontFamilyList = familyPtr;\n\n    /*\n     * Set key for this FontFamily.\n     */\n\n    familyPtr->foundry = fa.xa.foundry;\n    familyPtr->faceName = fa.fa.family;\n    familyPtr->encoding = encoding;\n\n    /*\n     * An initial refCount of 2 means that FontFamily information will persist\n     * even when the SubFont that loaded the FontFamily is released. Change it\n     * to 1 to cause FontFamilies to be unloaded when not in use.\n     */\n\n    familyPtr->refCount = 2;\n\n    /*\n     * One byte/character fonts have both min_byte1 and max_byte1 0, and\n     * max_char_or_byte2 <= 255. Anything else specifies a two byte/character\n     * font.\n     */\n\n    familyPtr->isTwoByteFont = !(\n\t    (fontStructPtr->min_byte1 == 0) &&\n\t    (fontStructPtr->max_byte1 == 0) &&\n\t    (fontStructPtr->max_char_or_byte2 < 256));\n    return familyPtr;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FreeFontFamily --\n *\n *\tCalled to free an FontFamily when the SubFont is finished using it.\n *\tFrees the contents of the FontFamily and the memory used by the\n *\tFontFamily itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFreeFontFamily(\n    FontFamily *familyPtr)\t/* The FontFamily to delete. */\n{\n    FontFamily **familyPtrPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    int i;\n\n    if (familyPtr == NULL) {\n\treturn;\n    }\n    if (familyPtr->refCount-- > 1) {\n\treturn;\n    }\n    if (familyPtr->encoding) {\n\tTcl_FreeEncoding(familyPtr->encoding);\n    }\n    for (i = 0; i < FONTMAP_PAGES; i++) {\n\tif (familyPtr->fontMap[i] != NULL) {\n\t    Tcl_Free(familyPtr->fontMap[i]);\n\t}\n    }\n\n    /*\n     * Delete from list.\n     */\n\n    for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {\n\tif (*familyPtrPtr == familyPtr) {\n\t    *familyPtrPtr = familyPtr->nextPtr;\n\t    break;\n\t}\n\tfamilyPtrPtr = &(*familyPtrPtr)->nextPtr;\n    }\n\n    Tcl_Free(familyPtr);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FindSubFontForChar --\n *\n *\tDetermine which screen font is necessary to use to display the given\n *\tcharacter. If the font object does not have a screen font that can\n *\tdisplay the character, another screen font may be loaded into the font\n *\tobject, following a set of preferred fallback rules.\n *\n * Results:\n *\tThe return value is the SubFont to use to display the given character.\n *\n * Side effects:\n *\tThe contents of fontPtr are modified to cache the results of the\n *\tlookup and remember any SubFonts that were dynamically loaded. The\n *\ttable of SubFonts might be extended, and if a non-NULL reference to a\n *\tsubfont pointer is available, it is updated if it previously pointed\n *\tinto the old subfont table.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic SubFont *\nFindSubFontForChar(\n    UnixFont *fontPtr,\t\t/* The font object with which the character\n\t\t\t\t * will be displayed. */\n    int ch,\t\t\t/* The Unicode character to be displayed. */\n    SubFont **fixSubFontPtrPtr)\t/* Subfont reference to fix up if we\n\t\t\t\t * reallocate our subfont table. */\n{\n    int i, j, k, numNames;\n    Tk_Uid faceName;\n    const char *fallback;\n    const char *const *aliases;\n    char **nameList;\n    const char *const *anyFallbacks;\n    const char *const *const *fontFallbacks;\n    SubFont *subFontPtr;\n    Tcl_DString ds;\n\n    if (ch < 0 || ch >= FONTMAP_NUMCHARS) {\n\tch = 0xFFFD;\n    }\n\n    if (FontMapLookup(&fontPtr->controlSubFont, ch)) {\n\treturn &fontPtr->controlSubFont;\n    }\n\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tif (FontMapLookup(&fontPtr->subFontArray[i], ch)) {\n\t    return &fontPtr->subFontArray[i];\n\t}\n    }\n\n    /*\n     * Keep track of all face names that we check, so we don't check some name\n     * multiple times if it can be reached by multiple paths.\n     */\n\n    Tcl_DStringInit(&ds);\n\n    /*\n     * Are there any other fonts with the same face name as the base font that\n     * could display this character, e.g., if the base font is\n     * adobe:fixed:iso8859-1, we could might be able to use\n     * misc:fixed:iso8859-8 or sony:fixed:jisx0208.1983-0\n     */\n\n    faceName = fontPtr->font.fa.family;\n    if (SeenName(faceName, &ds) == 0) {\n\tsubFontPtr = CanUseFallback(fontPtr, faceName, ch, fixSubFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    goto end;\n\t}\n    }\n\n    aliases = TkFontGetAliasList(faceName);\n\n    subFontPtr = NULL;\n    fontFallbacks = TkFontGetFallbacks();\n    for (i = 0; fontFallbacks[i] != NULL; i++) {\n\tfor (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t    if (strcasecmp(fallback, faceName) == 0) {\n\t\t/*\n\t\t * If the base font has a fallback...\n\t\t */\n\n\t\tgoto tryfallbacks;\n\t    } else if (aliases != NULL) {\n\t\t/*\n\t\t * Or if an alias for the base font has a fallback...\n\t\t */\n\n\t\tfor (k = 0; aliases[k] != NULL; k++) {\n\t\t    if (strcasecmp(fallback, aliases[k]) == 0) {\n\t\t\tgoto tryfallbacks;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tcontinue;\n\n    tryfallbacks:\n\n\t/*\n\t * ...then see if we can use one of the fallbacks, or an alias for one\n\t * of the fallbacks.\n\t */\n\n\tfor (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t    subFontPtr = CanUseFallbackWithAliases(fontPtr, fallback, ch, &ds,\n\t\t    fixSubFontPtrPtr);\n\t    if (subFontPtr != NULL) {\n\t\tgoto end;\n\t    }\n\t}\n    }\n\n    /*\n     * See if we can use something from the global fallback list.\n     */\n\n    anyFallbacks = TkFontGetGlobalClass();\n    for (i = 0; (fallback = anyFallbacks[i]) != NULL; i++) {\n\tsubFontPtr = CanUseFallbackWithAliases(fontPtr, fallback, ch, &ds,\n\t\tfixSubFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    goto end;\n\t}\n    }\n\n    /*\n     * Try all face names available in the whole system until we find one that\n     * can be used.\n     */\n\n    nameList = ListFonts(fontPtr->display, \"*\", &numNames);\n    for (i = 0; i < numNames; i++) {\n\tfallback = strchr(nameList[i] + 1, '-') + 1;\n\tstrchr((char *)fallback, '-')[0] = '\\0';\n\tif (SeenName(fallback, &ds) == 0) {\n\t    subFontPtr = CanUseFallback(fontPtr, fallback, ch,\n\t\t    fixSubFontPtrPtr);\n\t    if (subFontPtr != NULL) {\n\t\tXFreeFontNames(nameList);\n\t\tgoto end;\n\t    }\n\t}\n    }\n    XFreeFontNames(nameList);\n\n  end:\n    Tcl_DStringFree(&ds);\n\n    if (subFontPtr == NULL) {\n\t/*\n\t * No font can display this character, so it will be displayed as a\n\t * control character expansion.\n\t */\n\n\tsubFontPtr = &fontPtr->controlSubFont;\n\tFontMapInsert(subFontPtr, ch);\n    }\n    return subFontPtr;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapLookup --\n *\n *\tSee if the screen font can display the given character.\n *\n * Results:\n *\tThe return value is 0 if the screen font cannot display the character,\n *\tnon-zero otherwise.\n *\n * Side effects:\n *\tNew pages are added to the font mapping cache whenever the character\n *\tbelongs to a page that hasn't been seen before. When a page is loaded,\n *\tinformation about all the characters on that page is stored, not just\n *\tfor the single character in question.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nFontMapLookup(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be queried\n\t\t\t\t * and possibly updated. */\n    int ch)\t\t\t/* Character to be tested. */\n{\n    int row, bitOffset;\n\n    if (ch < 0 ||  ch >= FONTMAP_NUMCHARS) {\n\treturn 0;\n    }\n    row = ch >> FONTMAP_SHIFT;\n    if (subFontPtr->fontMap[row] == NULL) {\n\tFontMapLoadPage(subFontPtr, row);\n    }\n    bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);\n    return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapInsert --\n *\n *\tTell the font mapping cache that the given screen font should be used\n *\tto display the specified character. This is called when no font on the\n *\tsystem can be be found that can display that character; we lie to the\n *\tfont and tell it that it can display the character, otherwise we would\n *\tend up re-searching the entire fallback hierarchy every time that\n *\tcharacter was seen.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNew pages are added to the font mapping cache whenever the character\n *\tbelongs to a page that hasn't been seen before. When a page is loaded,\n *\tinformation about all the characters on that page is stored, not just\n *\tfor the single character in question.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFontMapInsert(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be\n\t\t\t\t * updated. */\n    int ch)\t\t\t/* Character to be added to cache. */\n{\n    int row, bitOffset;\n\n    if (ch >= 0 &&  ch < FONTMAP_NUMCHARS) {\n\trow = ch >> FONTMAP_SHIFT;\n\tif (subFontPtr->fontMap[row] == NULL) {\n\t    FontMapLoadPage(subFontPtr, row);\n\t}\n\tbitOffset = ch & (FONTMAP_BITSPERPAGE - 1);\n\tsubFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapLoadPage --\n *\n *\tLoad information about all the characters on a given page. This\n *\tinformation consists of one bit per character that indicates whether\n *\tthe associated screen font can (1) or cannot (0) display the\n *\tcharacters on the page.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *-------------------------------------------------------------------------\n */\nstatic void\nFontMapLoadPage(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be\n\t\t\t\t * updated. */\n    int row)\t\t\t/* Index of the page to be loaded into the\n\t\t\t\t * cache. */\n{\n    char buf[16], src[6];\n    int minHi, maxHi, minLo, maxLo, scale, checkLo;\n    int i, end, bitOffset, isTwoByteFont, n;\n    Tcl_Encoding encoding;\n    XFontStruct *fontStructPtr;\n    XCharStruct *widths;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    subFontPtr->fontMap[row] = (char *)Tcl_Alloc(FONTMAP_BITSPERPAGE / 8);\n    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);\n\n    if (subFontPtr->familyPtr == &tsdPtr->controlFamily) {\n\treturn;\n    }\n\n    fontStructPtr = subFontPtr->fontStructPtr;\n    encoding = subFontPtr->familyPtr->encoding;\n    isTwoByteFont = subFontPtr->familyPtr->isTwoByteFont;\n\n    widths = fontStructPtr->per_char;\n    minHi = fontStructPtr->min_byte1;\n    maxHi = fontStructPtr->max_byte1;\n    minLo = fontStructPtr->min_char_or_byte2;\n    maxLo = fontStructPtr->max_char_or_byte2;\n    scale = maxLo - minLo + 1;\n    checkLo = minLo;\n\n    if (! isTwoByteFont) {\n\tif (minLo < 32) {\n\t    checkLo = 32;\n\t}\n    }\n\n    end = (row + 1) << FONTMAP_SHIFT;\n    for (i = row << FONTMAP_SHIFT; i < end; i++) {\n\tint hi, lo;\n\n\tif (Tcl_UtfToExternal(NULL, encoding, src, Tcl_UniCharToUtf(i, src),\n\t\tTCL_ENCODING_PROFILE_STRICT, NULL, buf, sizeof(buf), NULL,\n\t\tNULL, NULL) != TCL_OK) {\n\t    continue;\n\t}\n\tif (isTwoByteFont) {\n\t    hi = ((unsigned char *) buf)[0];\n\t    lo = ((unsigned char *) buf)[1];\n\t} else {\n\t    hi = 0;\n\t    lo = ((unsigned char *) buf)[0];\n\t}\n\tif ((hi < minHi) || (hi > maxHi) || (lo < checkLo) || (lo > maxLo)) {\n\t    continue;\n\t}\n\tn = (hi - minHi) * scale + lo - minLo;\n\tif ((widths == NULL) || (widths[n].width + widths[n].rbearing != 0)) {\n\t    bitOffset = i & (FONTMAP_BITSPERPAGE - 1);\n\t    subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);\n\t}\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * CanUseFallbackWithAliases --\n *\n *\tHelper function for FindSubFontForChar. Determine if the specified\n *\tface name (or an alias of the specified face name) can be used to\n *\tconstruct a screen font that can display the given character.\n *\n * Results:\n *\tSee CanUseFallback().\n *\n * Side effects:\n *\tIf the name and/or one of its aliases was rejected, the rejected\n *\tstring is recorded in nameTriedPtr so that it won't be tried again.\n *\tThe table of SubFonts might be extended, and if a non-NULL reference\n *\tto a subfont pointer is available, it is updated if it previously\n *\tpointed into the old subfont table.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic SubFont *\nCanUseFallbackWithAliases(\n    UnixFont *fontPtr,\t\t/* The font object that will own the new\n\t\t\t\t * screen font. */\n    const char *faceName,\t\t/* Desired face name for new screen font. */\n    int ch,\t\t\t/* The Unicode character that the new screen\n\t\t\t\t * font must be able to display. */\n    Tcl_DString *nameTriedPtr,\t/* Records face names that have already been\n\t\t\t\t * tried. It is possible for the same face\n\t\t\t\t * name to be queried multiple times when\n\t\t\t\t * trying to find a suitable screen font. */\n    SubFont **fixSubFontPtrPtr)\t/* Subfont reference to fix up if we\n\t\t\t\t * reallocate our subfont table. */\n{\n    SubFont *subFontPtr;\n    const char *const *aliases;\n    int i;\n\n    if (SeenName(faceName, nameTriedPtr) == 0) {\n\tsubFontPtr = CanUseFallback(fontPtr, faceName, ch, fixSubFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    return subFontPtr;\n\t}\n    }\n    aliases = TkFontGetAliasList(faceName);\n    if (aliases != NULL) {\n\tfor (i = 0; aliases[i] != NULL; i++) {\n\t    if (SeenName(aliases[i], nameTriedPtr) == 0) {\n\t\tsubFontPtr = CanUseFallback(fontPtr, aliases[i], ch,\n\t\t\tfixSubFontPtrPtr);\n\t\tif (subFontPtr != NULL) {\n\t\t    return subFontPtr;\n\t\t}\n\t    }\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * SeenName --\n *\n *\tUsed to determine we have already tried and rejected the given face\n *\tname when looking for a screen font that can support some Unicode\n *\tcharacter.\n *\n * Results:\n *\tThe return value is 0 if this face name has not already been seen,\n *\tnon-zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nSeenName(\n    const char *name,\t\t/* The name to check. */\n    Tcl_DString *dsPtr)\t\t/* Contains names that have already been\n\t\t\t\t * seen. */\n{\n    const char *seen, *end;\n\n    seen = Tcl_DStringValue(dsPtr);\n    end = seen + Tcl_DStringLength(dsPtr);\n    while (seen < end) {\n\tif (strcasecmp(seen, name) == 0) {\n\t    return 1;\n\t}\n\tseen += strlen(seen) + 1;\n    }\n    Tcl_DStringAppend(dsPtr, name, (int) (strlen(name) + 1));\n    return 0;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * CanUseFallback --\n *\n *\tIf the specified screen font has not already been loaded into the font\n *\tobject, determine if the specified screen font can display the given\n *\tcharacter.\n *\n * Results:\n *\tThe return value is a pointer to a newly allocated SubFont, owned by\n *\tthe font object. This SubFont can be used to display the given\n *\tcharacter. The SubFont represents the screen font with the base set of\n *\tfont attributes from the font object, but using the specified face\n *\tname. NULL is returned if the font object already holds a reference to\n *\tthe specified font or if the specified font doesn't exist or cannot\n *\tdisplay the given character.\n *\n * Side effects:\n *\tThe font object's subFontArray is updated to contain a reference to\n *\tthe newly allocated SubFont. The table of SubFonts might be extended,\n *\tand if a non-NULL reference to a subfont pointer is available, it is\n *\tupdated if it previously pointed into the old subfont table.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic SubFont *\nCanUseFallback(\n    UnixFont *fontPtr,\t\t/* The font object that will own the new\n\t\t\t\t * screen font. */\n    const char *faceName,\t/* Desired face name for new screen font. */\n    int ch,\t\t\t/* The Unicode character that the new screen\n\t\t\t\t * font must be able to display. */\n    SubFont **fixSubFontPtrPtr)\t/* Subfont reference to fix up if we\n\t\t\t\t * reallocate our subfont table. */\n{\n    int i, nameIdx, numNames, srcLen, numEncodings, bestIdx[2];\n    Tk_Uid hateFoundry;\n    const char *charset, *hateCharset;\n    unsigned bestScore[2];\n    char **nameList;\n    char **nameListOrig;\n    char src[6];\n    FontAttributes want, got;\n    Display *display;\n    SubFont subFont;\n    XFontStruct *fontStructPtr;\n    Tcl_DString dsEncodings;\n    Tcl_Encoding *encodingCachePtr;\n\n    /*\n     * Assume: the face name is times.\n     * Assume: adobe:times:iso8859-1 has already been used.\n     *\n     * Are there any versions of times that can display this character (e.g.,\n     *    perhaps linotype:times:iso8859-2)?\n     *\t  a. Get list of all times fonts.\n     *\t  b1. Cross out all names whose encodings we've already used.\n     *\t  b2. Cross out all names whose foundry & encoding we've already seen.\n     *\t  c. Cross out all names whose encoding cannot handle the character.\n     *\t  d. Rank each name and pick the best match.\n     *\t  e. If that font cannot actually display the character, cross out all\n     *\t     names with the same foundry and encoding and go back to (c).\n     */\n\n    display = fontPtr->display;\n    nameList = ListFonts(display, faceName, &numNames);\n    if (numNames == 0) {\n\treturn NULL;\n    }\n    nameListOrig = nameList;\n\n    srcLen = Tcl_UniCharToUtf(ch, src);\n\n    want.fa = fontPtr->font.fa;\n    want.xa = fontPtr->xa;\n\n    want.fa.family = Tk_GetUid(faceName);\n    want.fa.size = (double)-fontPtr->pixelSize;\n\n    hateFoundry = NULL;\n    hateCharset = NULL;\n    numEncodings = 0;\n    Tcl_DStringInit(&dsEncodings);\n\n    charset = NULL;\t/* numNames must be > 0 to get here. */\n\n  retry:\n    bestIdx[0] = -1;\n    bestIdx[1] = -1;\n    bestScore[0] = (unsigned) -1;\n    bestScore[1] = (unsigned) -1;\n    for (nameIdx = 0; nameIdx < numNames; nameIdx++) {\n\tTcl_Encoding encoding;\n\tchar dst[16];\n\tint scalable, srcRead, dstWrote;\n\tunsigned score;\n\n\tif (nameList[nameIdx] == NULL) {\n\t    continue;\n\t}\n\tif (TkFontParseXLFD(nameList[nameIdx], &got.fa, &got.xa) != TCL_OK) {\n\t    goto crossout;\n\t}\n\tIdentifySymbolEncodings(&got);\n\tcharset = GetEncodingAlias(got.xa.charset);\n\tif (hateFoundry != NULL) {\n\t    /*\n\t     * E. If the font we picked cannot actually display the character,\n\t     * cross out all names with the same foundry and encoding.\n\t     */\n\n\t    if ((hateFoundry == got.xa.foundry)\n\t\t    && (strcmp(hateCharset, charset) == 0)) {\n\t\tgoto crossout;\n\t    }\n\t} else {\n\t    /*\n\t     * B. Cross out all names whose encodings we've already used.\n\t     */\n\n\t    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\t\tencoding = fontPtr->subFontArray[i].familyPtr->encoding;\n\t\tif (strcmp(charset, Tcl_GetEncodingName(encoding)) == 0) {\n\t\t    goto crossout;\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * C. Cross out all names whose encoding cannot handle the character.\n\t */\n\n\tencodingCachePtr = (Tcl_Encoding *) Tcl_DStringValue(&dsEncodings);\n\tfor (i = numEncodings; --i >= 0; encodingCachePtr++) {\n\t    encoding = *encodingCachePtr;\n\t    if (strcmp(Tcl_GetEncodingName(encoding), charset) == 0) {\n\t\tbreak;\n\t    }\n\t}\n\tif (i < 0) {\n\t    encoding = Tcl_GetEncoding(NULL, charset);\n\t    if (encoding == NULL) {\n\t\tgoto crossout;\n\t    }\n\n\t    Tcl_DStringAppend(&dsEncodings, (char *) &encoding,\n\t\t    sizeof(encoding));\n\t    numEncodings++;\n\t}\n\tTcl_UtfToExternal(NULL, encoding, src, srcLen,\n\t\tTCL_ENCODING_PROFILE_STRICT, NULL, dst, sizeof(dst), &srcRead,\n\t\t&dstWrote, NULL);\n\tif (dstWrote == 0) {\n\t    goto crossout;\n\t}\n\n\t/*\n\t * D. Rank each name and pick the best match.\n\t */\n\n\tscalable = (got.fa.size == 0.0);\n\tscore = RankAttributes(&want, &got);\n\tif (score < bestScore[scalable]) {\n\t    bestIdx[scalable] = nameIdx;\n\t    bestScore[scalable] = score;\n\t}\n\tif (score == 0) {\n\t    break;\n\t}\n\tcontinue;\n\n    crossout:\n\tif (nameList == nameListOrig) {\n\t    /*\n\t     * Not allowed to change pointers to memory that X gives you, so\n\t     * make a copy.\n\t     */\n\n\t    nameList = (char **)Tcl_Alloc(numNames * sizeof(char *));\n\t    memcpy(nameList, nameListOrig, numNames * sizeof(char *));\n\t}\n\tnameList[nameIdx] = NULL;\n    }\n\n    fontStructPtr = GetScreenFont(display, &want, nameList, bestIdx,\n\t    bestScore);\n\n    encodingCachePtr = (Tcl_Encoding *) Tcl_DStringValue(&dsEncodings);\n    for (i = numEncodings; --i >= 0; encodingCachePtr++) {\n\tTcl_FreeEncoding(*encodingCachePtr);\n    }\n    Tcl_DStringFree(&dsEncodings);\n    numEncodings = 0;\n\n    if (fontStructPtr == NULL) {\n\tif (nameList != nameListOrig) {\n\t    Tcl_Free(nameList);\n\t}\n\tXFreeFontNames(nameListOrig);\n\treturn NULL;\n    }\n\n    InitSubFont(display, fontStructPtr, 0, &subFont);\n    if (FontMapLookup(&subFont, ch) == 0) {\n\t/*\n\t * E. If the font we picked cannot actually display the character,\n\t * cross out all names with the same foundry and encoding and pick\n\t * another font.\n\t */\n\n\thateFoundry = got.xa.foundry;\n\thateCharset = charset;\n\tReleaseSubFont(display, &subFont);\n\tgoto retry;\n    }\n    if (nameList != nameListOrig) {\n\tTcl_Free(nameList);\n    }\n    XFreeFontNames(nameListOrig);\n\n    if (fontPtr->numSubFonts >= SUBFONT_SPACE) {\n\tSubFont *newPtr;\n\n\tnewPtr = (SubFont *)Tcl_Alloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));\n\tmemcpy(newPtr, fontPtr->subFontArray,\n\t\tfontPtr->numSubFonts * sizeof(SubFont));\n\tif (fixSubFontPtrPtr != NULL) {\n\t    SubFont *fixSubFontPtr = *fixSubFontPtrPtr;\n\n\t    if (fixSubFontPtr != &fontPtr->controlSubFont) {\n\t\t*fixSubFontPtrPtr =\n\t\t\tnewPtr + (fixSubFontPtr - fontPtr->subFontArray);\n\t    }\n\t}\n\tif (fontPtr->subFontArray != fontPtr->staticSubFonts) {\n\t    Tcl_Free(fontPtr->subFontArray);\n\t}\n\tfontPtr->subFontArray = newPtr;\n    }\n    fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;\n    fontPtr->numSubFonts++;\n    return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * RankAttributes --\n *\n *\tDetermine how close the attributes of the font in question match the\n *\tattributes that we want.\n *\n * Results:\n *\tThe return value is the score; lower numbers are better. *scalablePtr\n *\tis set to 0 if the font was not scalable, 1 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic unsigned\nRankAttributes(\n    FontAttributes *wantPtr,\t/* The desired attributes. */\n    FontAttributes *gotPtr)\t/* The attributes we have to live with. */\n{\n    unsigned penalty;\n\n    penalty = 0;\n    if (gotPtr->xa.foundry != wantPtr->xa.foundry) {\n\tpenalty += 4500;\n    }\n    if (gotPtr->fa.family != wantPtr->fa.family) {\n\tpenalty += 9000;\n    }\n    if (gotPtr->fa.weight != wantPtr->fa.weight) {\n\tpenalty += 90;\n    }\n    if (gotPtr->fa.slant != wantPtr->fa.slant) {\n\tpenalty += 60;\n    }\n    if (gotPtr->xa.slant != wantPtr->xa.slant) {\n\tpenalty += 10;\n    }\n    if (gotPtr->xa.setwidth != wantPtr->xa.setwidth) {\n\tpenalty += 1000;\n    }\n\n    if (gotPtr->fa.size == 0.0) {\n\t/*\n\t * A scalable font is almost always acceptable, but the corresponding\n\t * bitmapped font would be better.\n\t */\n\n\tpenalty += 10;\n    } else {\n\tint diff;\n\n\t/*\n\t * It's worse to be too large than to be too small.\n\t */\n\n\tdiff = (int) (150 * (-gotPtr->fa.size - -wantPtr->fa.size));\n\tif (diff > 0) {\n\t    penalty += 600;\n\t} else if (diff < 0) {\n\t    penalty += 150;\n\t    diff = -diff;\n\t}\n\tpenalty += diff;\n    }\n    if (gotPtr->xa.charset != wantPtr->xa.charset) {\n\tsize_t i;\n\tconst char *gotAlias, *wantAlias;\n\n\tpenalty += 65000;\n\tgotAlias = GetEncodingAlias(gotPtr->xa.charset);\n\twantAlias = GetEncodingAlias(wantPtr->xa.charset);\n\tif (strcmp(gotAlias, wantAlias) != 0) {\n\t    penalty += 30000;\n\t    for (i = 0; i < sizeof(encodingList)/sizeof(encodingList[0]); i++) {\n\t\tif (strcmp(gotAlias, encodingList[i]) == 0) {\n\t\t    penalty -= 30000;\n\t\t    break;\n\t\t}\n\t\tpenalty += 20000;\n\t    }\n\t}\n    }\n    return penalty;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetScreenFont --\n *\n *\tGiven the names for the best scalable and best bitmapped font,\n *\tactually construct an XFontStruct based on the best XLFD. This is\n *\twhere all the alias and fallback substitution bottoms out.\n *\n * Results:\n *\tThe screen font that best corresponds to the set of attributes.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic XFontStruct *\nGetScreenFont(\n    Display *display,\t\t/* Display for new XFontStruct. */\n    FontAttributes *wantPtr,\t/* Contains desired actual pixel-size if the\n\t\t\t\t * best font was scalable. */\n    char **nameList,\t\t/* Array of XLFDs. */\n    int bestIdx[],\t\t/* Indices into above array for XLFD of best\n\t\t\t\t * bitmapped and best scalable font. */\n    unsigned bestScore[])\t/* Scores of best bitmapped and best scalable\n\t\t\t\t * font. XLFD corresponding to lowest score\n\t\t\t\t * will be constructed. */\n{\n    XFontStruct *fontStructPtr;\n\n    if ((bestIdx[0] < 0) && (bestIdx[1] < 0)) {\n\treturn NULL;\n    }\n\n    /*\n     * Now we know which is the closest matching scalable font and the closest\n     * matching bitmapped font. If the scalable font was a better match, try\n     * getting the scalable font; however, if the scalable font was not\n     * actually available in the desired pointsize, fall back to the closest\n     * bitmapped font.\n     */\n\n    fontStructPtr = NULL;\n    if (bestScore[1] < bestScore[0]) {\n\tchar *str, *rest, buf[256];\n\tint i;\n\n\t/*\n\t * Fill in the desired pixel size for this font.\n\t */\n\n    tryscale:\n\tstr = nameList[bestIdx[1]];\n\tfor (i = 0; i < XLFD_PIXEL_SIZE; i++) {\n\t    str = strchr(str + 1, '-');\n\t}\n\trest = str;\n\tfor (i = XLFD_PIXEL_SIZE; i < XLFD_CHARSET; i++) {\n\t    rest = strchr(rest + 1, '-');\n\t}\n\t*str = '\\0';\n\tsnprintf(buf, sizeof(buf), \"%.200s-%d-*-*-*-*-*%s\", nameList[bestIdx[1]],\n\t\t(int)(-wantPtr->fa.size+0.5), rest);\n\t*str = '-';\n\tfontStructPtr = XLoadQueryFontNoXError(display, buf);\n\tbestScore[1] = INT_MAX;\n    }\n    if (fontStructPtr == NULL) {\n\tfontStructPtr = XLoadQueryFontNoXError(display, nameList[bestIdx[0]]);\n\tif (fontStructPtr == NULL) {\n\t    /*\n\t     * This shouldn't happen because the font name is one of the names\n\t     * that X gave us to use, but it does anyhow.\n\t     */\n\n\t    if (bestScore[1] < INT_MAX) {\n\t\tgoto tryscale;\n\t    }\n\t    return GetSystemFont(display);\n\t}\n    }\n    return fontStructPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetSystemFont --\n *\n *\tAbsolute fallback mechanism, called when we need a font and no other\n *\tfont can be found and/or instantiated.\n *\n * Results:\n *\tA pointer to a font. Never NULL.\n *\n * Side effects:\n *\tIf there are NO fonts installed on the system, this call will panic,\n *\tbut how did you get X running in that case?\n *\n *---------------------------------------------------------------------------\n */\n\nstatic XFontStruct *\nGetSystemFont(\n    Display *display)\t\t/* Display for new XFontStruct. */\n{\n    XFontStruct *fontStructPtr;\n\n    fontStructPtr = XLoadQueryFontNoXError(display, \"fixed\");\n    if (fontStructPtr == NULL) {\n\tfontStructPtr = XLoadQueryFontNoXError(display, \"*\");\n\tif (fontStructPtr == NULL) {\n\t    Tcl_Panic(\"TkpGetFontFromAttributes: cannot get any font\");\n\t}\n    }\n    return fontStructPtr;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetFontAttributes --\n *\n *\tGiven a screen font, determine its actual attributes, which are not\n *\tnecessarily the attributes that were used to construct it.\n *\n * Results:\n *\t*faPtr is filled with the screen font's attributes.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nGetFontAttributes(\n    Display *display,\t\t/* Display that owns the screen font. */\n    XFontStruct *fontStructPtr,\t/* Screen font to query. */\n    FontAttributes *faPtr)\t/* For storing attributes of screen font. */\n{\n    unsigned long value;\n    char *name;\n\n    if ((XGetFontProperty(fontStructPtr, XA_FONT, &value) != False) &&\n\t    (value != 0)) {\n\tname = XGetAtomName(display, (Atom) value);\n\tif (TkFontParseXLFD(name, &faPtr->fa, &faPtr->xa) != TCL_OK) {\n\t    faPtr->fa.family = Tk_GetUid(name);\n\t    faPtr->xa.foundry = Tk_GetUid(\"\");\n\t    faPtr->xa.charset = Tk_GetUid(\"\");\n\t}\n\tXFree(name);\n    } else {\n\tTkInitFontAttributes(&faPtr->fa);\n\tTkInitXLFDAttributes(&faPtr->xa);\n    }\n\n    /*\n     * Do last ditch check for family. It seems that some X servers can fail\n     * on the X font calls above, slipping through earlier checks. X-Win32 5.4\n     * is one of these.\n     */\n\n    if (faPtr->fa.family == NULL) {\n\tfaPtr->fa.family = Tk_GetUid(\"\");\n\tfaPtr->xa.foundry = Tk_GetUid(\"\");\n\tfaPtr->xa.charset = Tk_GetUid(\"\");\n    }\n    return IdentifySymbolEncodings(faPtr);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * ListFonts --\n *\n *\tUtility function to return the array of all XLFDs on the system with\n *\tthe specified face name.\n *\n * Results:\n *\tThe return value is an array of XLFDs, which should be freed with\n *\tXFreeFontNames(), or NULL if no XLFDs matched the requested name.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic char **\nListFonts(\n    Display *display,\t\t/* Display to query. */\n    const char *faceName,\t/* Desired face name, or \"*\" for all. */\n    int *numNamesPtr)\t\t/* Filled with length of returned array, or 0\n\t\t\t\t * if no names were found. */\n{\n    char buf[256];\n\n    snprintf(buf, sizeof(buf), \"-*-%.80s-*-*-*-*-*-*-*-*-*-*-*-*\", faceName);\n    return XListFonts(display, buf, 10000, numNamesPtr);\n}\n\nstatic char **\nListFontOrAlias(\n    Display *display,\t\t/* Display to query. */\n    const char *faceName,\t/* Desired face name, or \"*\" for all. */\n    int *numNamesPtr)\t\t/* Filled with length of returned array, or 0\n\t\t\t\t * if no names were found. */\n{\n    char **nameList;\n    const char *const *aliases;\n    int i;\n\n    nameList = ListFonts(display, faceName, numNamesPtr);\n    if (nameList != NULL) {\n\treturn nameList;\n    }\n    aliases = TkFontGetAliasList(faceName);\n    if (aliases != NULL) {\n\tfor (i = 0; aliases[i] != NULL; i++) {\n\t    nameList = ListFonts(display, aliases[i], numNamesPtr);\n\t    if (nameList != NULL) {\n\t\treturn nameList;\n\t    }\n\t}\n    }\n    *numNamesPtr = 0;\n    return NULL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * IdentifySymbolEncodings --\n *\n *\tIf the font attributes refer to a symbol font, update the charset\n *\tfield of the font attributes so that it reflects the encoding of that\n *\tsymbol font. In general, the raw value for the charset field parsed\n *\tfrom an XLFD is meaningless for symbol fonts.\n *\n *\tSymbol fonts are all fonts whose name appears in the symbolClass.\n *\n * Results:\n *\tThe return value is non-zero if the font attributes specify a symbol\n *\tfont, or 0 otherwise. If a non-zero value is returned the charset\n *\tfield of the font attributes will be changed to the string that\n *\trepresents the actual encoding for the symbol font.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nIdentifySymbolEncodings(\n    FontAttributes *faPtr)\n{\n    int i, j;\n    const char *const *aliases;\n    const char *const *symbolClass;\n\n    symbolClass = TkFontGetSymbolClass();\n    for (i = 0; symbolClass[i] != NULL; i++) {\n\tif (strcasecmp(faPtr->fa.family, symbolClass[i]) == 0) {\n\t    faPtr->xa.charset = Tk_GetUid(GetEncodingAlias(symbolClass[i]));\n\t    return 1;\n\t}\n\taliases = TkFontGetAliasList(symbolClass[i]);\n\tfor (j = 0; (aliases != NULL) && (aliases[j] != NULL); j++) {\n\t    if (strcasecmp(faPtr->fa.family, aliases[j]) == 0) {\n\t\tfaPtr->xa.charset = Tk_GetUid(GetEncodingAlias(aliases[j]));\n\t\treturn 1;\n\t    }\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetEncodingAlias --\n *\n *\tMap the name of an encoding to another name that should be used when\n *\tactually loading the encoding. For instance, the encodings\n *\t\"jisc6226.1978\", \"jisx0208.1983\", \"jisx0208.1990\", and \"jisx0208.1996\"\n *\tare well-known names for the same encoding and are represented by one\n *\tencoding table: \"jis0208\".\n *\n * Results:\n *\tAs above. If the name has no alias, the original name is returned.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic const char *\nGetEncodingAlias(\n    const char *name)\t\t/* The name to look up. */\n{\n    const EncodingAlias *aliasPtr;\n\n    for (aliasPtr = encodingAliases; aliasPtr->aliasPattern != NULL; ) {\n\tif (Tcl_StringCaseMatch(name, aliasPtr->aliasPattern, 0)) {\n\t    return aliasPtr->realName;\n\t}\n\taliasPtr++;\n    }\n    return name;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkDrawAngledChars --\n *\n *\tDraw some characters at an angle. This is awkward here because we have\n *\tno reliable way of drawing any characters at an angle in classic X11;\n *\twe have to draw on a Pixmap which is converted to an XImage (from\n *\thelper function GetImageOfText), rotate the image (hokey code!) onto\n *\tanother XImage (from helper function InitDestImage), and then use the\n *\trotated image as a mask when drawing. This is pretty awful; improved\n *\tversions are welcomed!\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTarget drawable is updated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic inline XImage *\nGetImageOfText(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int *realWidthPtr, int *realHeightPtr)\n{\n    int width, height;\n    TkFont *fontPtr = (TkFont *) tkfont;\n    Pixmap bitmap;\n    GC bitmapGC;\n    XGCValues values;\n    XImage *image = NULL;\n\n    (void) Tk_MeasureChars(tkfont, source, numBytes, -1, 0, &width);\n    height = fontPtr->fm.ascent + fontPtr->fm.descent;\n\n    if ((width > 0) && (height > 0)) {\n\tbitmap = Tk_GetPixmap(display, drawable, width, height, 1);\n\tvalues.graphics_exposures = False;\n\tvalues.foreground = BlackPixel(display, DefaultScreen(display));\n\tbitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,\n\t\t&values);\n\tXFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);\n\n\tvalues.font = Tk_FontId(tkfont);\n\tvalues.foreground = WhitePixel(display, DefaultScreen(display));\n\tvalues.background = BlackPixel(display, DefaultScreen(display));\n\tXChangeGC(display, bitmapGC, GCFont|GCForeground|GCBackground, &values);\n\tTk_DrawChars(display, bitmap, bitmapGC, tkfont, source, numBytes, 0,\n\t\tfontPtr->fm.ascent);\n\tXFreeGC(display, bitmapGC);\n\n\timage = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,\n\t\tZPixmap);\n\tTk_FreePixmap(display, bitmap);\n    }\n\n    *realWidthPtr = width;\n    *realHeightPtr = height;\n    return image;\n}\n\nstatic inline XImage *\nInitDestImage(\n    Display *display,\n    Drawable drawable,\n    int width,\n    int height,\n    Pixmap *bitmapPtr)\n{\n    Pixmap bitmap = None;\n    XImage *image = NULL;\n    GC bitmapGC;\n    XGCValues values;\n\n    if ((width > 0) && (height > 0)) {\n\tbitmap = Tk_GetPixmap(display, drawable, width, height, 1);\n\tvalues.graphics_exposures = False;\n\tvalues.foreground = BlackPixel(display, DefaultScreen(display));\n\tbitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,\n\t\t&values);\n\tXFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);\n\tXFreeGC(display, bitmapGC);\n\n\timage = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,\n\t\tZPixmap);\n    }\n    *bitmapPtr = bitmap;\n    return image;\n}\n\nvoid\nTkDrawAngledChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    double x, double y,\n    double angle)\n{\n    if (angle == 0.0) {\n\tTk_DrawChars(display, drawable, gc, tkfont, source, numBytes, x, y);\n    } else {\n\tdouble sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\tint bufHeight, bufWidth, srcWidth, srcHeight, i, j, dx, dy;\n\tPixmap buf;\n\tXImage *srcImage = GetImageOfText(display, drawable, tkfont, source,\n\t\tnumBytes, &srcWidth, &srcHeight);\n\tXImage *dstImage;\n\tenum {Q0=1,R1,Q1,R2,Q2,R3,Q3} quadrant;\n\tGC bwgc, cpgc;\n\tXGCValues values;\n\tint ascent = ((TkFont *) tkfont)->fm.ascent;\n\n\t/*\n\t * First, work out what quadrant we are operating in. We also handle\n\t * the rectilinear rotations as special cases. Conceptually, there's\n\t * also R0 (angle == 0.0) but that has been already handled as a\n\t * special case above.\n\t *\n\t *        R1\n\t *   Q1   |   Q0\n\t *        |\n\t * R2 ----+---- R0\n\t *        |\n\t *   Q2   |   Q3\n\t *        R3\n\t */\n\n\tif (angle < 90.0) {\n\t    quadrant = Q0;\n\t} else if (angle == 90.0) {\n\t    quadrant = R1;\n\t} else if (angle < 180.0) {\n\t    quadrant = Q1;\n\t} else if (angle == 180.0) {\n\t    quadrant = R2;\n\t} else if (angle < 270.0) {\n\t    quadrant = Q2;\n\t} else if (angle == 270.0) {\n\t    quadrant = R3;\n\t} else {\n\t    quadrant = Q3;\n\t}\n\n\tif (srcImage == NULL) {\n\t    return;\n\t}\n\tbufWidth = srcWidth*fabs(cosA) + srcHeight*fabs(sinA);\n\tbufHeight = srcHeight*fabs(cosA) + srcWidth*fabs(sinA);\n\tdstImage = InitDestImage(display, drawable, bufWidth,bufHeight, &buf);\n\tif (dstImage == NULL) {\n\t    Tk_FreePixmap(display, buf);\n\t    XDestroyImage(srcImage);\n\t    return;\n\t}\n\n\t/*\n\t * Do the rotation, setting or resetting pixels in the destination\n\t * image dependent on whether the corresponding pixel (after rotation\n\t * to source image space) is set.\n\t */\n\n\tfor (i=0 ; i<srcWidth ; i++) {\n\t    for (j=0 ; j<srcHeight ; j++) {\n\t\tswitch (quadrant) {\n\t\tcase Q0:\n\t\t    dx = ROUND16(i*cosA + j*sinA);\n\t\t    dy = ROUND16(j*cosA + (srcWidth - i)*sinA);\n\t\t    break;\n\t\tcase R1:\n\t\t    dx = j;\n\t\t    dy = srcWidth - i;\n\t\t    break;\n\t\tcase Q1:\n\t\t    dx = ROUND16((i - srcWidth)*cosA + j*sinA);\n\t\t    dy = ROUND16((srcWidth-i)*sinA + (j-srcHeight)*cosA);\n\t\t    break;\n\t\tcase R2:\n\t\t    dx = srcWidth - i;\n\t\t    dy = srcHeight - j;\n\t\t    break;\n\t\tcase Q2:\n\t\t    dx = ROUND16((i-srcWidth)*cosA + (j-srcHeight)*sinA);\n\t\t    dy = ROUND16((j - srcHeight)*cosA - i*sinA);\n\t\t    break;\n\t\tcase R3:\n\t\t    dx = srcHeight - j;\n\t\t    dy = i;\n\t\t    break;\n\t\tdefault:\n\t\t    dx = ROUND16(i*cosA + (j - srcHeight)*sinA);\n\t\t    dy = ROUND16(j*cosA - i*sinA);\n\t\t}\n\n\t\tif (dx < 0 || dy < 0 || dx >= bufWidth || dy >= bufHeight) {\n\t\t    continue;\n\t\t}\n\t\tXPutPixel(dstImage, dx, dy,\n\t\t\tXGetPixel(dstImage,dx,dy) | XGetPixel(srcImage,i,j));\n\t    }\n\t}\n\tXDestroyImage(srcImage);\n\n\t/*\n\t * Schlep the data back to the Xserver.\n\t */\n\n\tvalues.function = GXcopy;\n\tvalues.foreground = WhitePixel(display, DefaultScreen(display));\n\tvalues.background = BlackPixel(display, DefaultScreen(display));\n\tbwgc = XCreateGC(display, buf, GCFunction|GCForeground|GCBackground,\n\t\t&values);\n\tXPutImage(display, buf, bwgc, dstImage, 0,0, 0,0, bufWidth,bufHeight);\n\tXFreeGC(display, bwgc);\n\tXDestroyImage(dstImage);\n\n\t/*\n\t * Calculate where we want to draw the text.\n\t */\n\n\tswitch (quadrant) {\n\tcase Q0:\n\t    dx = x;\n\t    dy = y - srcWidth*sinA;\n\t    break;\n\tcase R1:\n\t    dx = x;\n\t    dy = y - srcWidth;\n\t    break;\n\tcase Q1:\n\t    dx = x + srcWidth*cosA;\n\t    dy = y + srcHeight*cosA - srcWidth*sinA;\n\t    break;\n\tcase R2:\n\t    dx = x - srcWidth;\n\t    dy = y - srcHeight;\n\t    break;\n\tcase Q2:\n\t    dx = x + srcWidth*cosA + srcHeight*sinA;\n\t    dy = y + srcHeight*cosA;\n\t    break;\n\tcase R3:\n\t    dx = x - srcHeight;\n\t    dy = y;\n\t    break;\n\tdefault:\n\t    dx = x + srcHeight*sinA;\n\t    dy = y;\n\t}\n\n\t/*\n\t * Apply a correction to deal with the fact that we aren't told to\n\t * draw from our top-left corner but rather from the left-end of our\n\t * baseline.\n\t */\n\n\tdx -= ascent*sinA;\n\tdy -= ascent*cosA;\n\n\t/*\n\t * Transfer the text to the screen. This is done by using it as a mask\n\t * and then drawing through that mask with the original drawing color.\n\t */\n\n\tvalues.function = GXcopy;\n\tvalues.fill_style = FillSolid;\n\tvalues.clip_mask = buf;\n\tvalues.clip_x_origin = dx;\n\tvalues.clip_y_origin = dy;\n\tcpgc = XCreateGC(display, drawable,\n\t\tGCFunction|GCFillStyle|GCClipMask|GCClipXOrigin|GCClipYOrigin,\n\t\t&values);\n\tXCopyGC(display, gc, GCForeground, cpgc);\n\tXFillRectangle(display, drawable, cpgc, dx, dy, bufWidth,\n\t\tbufHeight);\n\tXFreeGC(display, cpgc);\n\n\tTk_FreePixmap(display, buf);\n\treturn;\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixInit.c",
    "content": "/*\n * tkUnixInit.c --\n *\n *\tThis file contains Unix-specific interpreter initialization functions.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n#ifdef HAVE_COREFOUNDATION\nstatic int\t\tGetLibraryPath(Tcl_Interp *interp);\n#else\n#define GetLibraryPath(dummy)\t(void)dummy\n#endif /* HAVE_COREFOUNDATION */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpInit --\n *\n *\tPerforms Unix-specific interpreter initialization related to the\n *      tk_library variable.\n *\n * Results:\n *\tReturns a standard Tcl result. Leaves an error message or result in\n *\tthe interp's result.\n *\n * Side effects:\n *\tSets \"tk_library\" Tcl variable, runs \"tk.tcl\" script.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpInit(\n    Tcl_Interp *interp)\n{\n    TkCreateXEventSource();\n    GetLibraryPath(interp);\n    Tktray_Init(interp);\n    (void)SysNotify_Init (interp);\n    Icu_Init(interp);\n    Cups_Init(interp);\n    TkAtkAccessibility_Init(interp);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetAppName --\n *\n *\tRetrieves the name of the current application from a platform specific\n *\tlocation. For Unix, the application name is the tail of the path\n *\tcontained in the tcl variable argv0.\n *\n * Results:\n *\tReturns the application name in the given Tcl_DString.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetAppName(\n    Tcl_Interp *interp,\n    Tcl_DString *namePtr)\t/* A previously initialized Tcl_DString. */\n{\n    const char *p, *name;\n\n    name = Tcl_GetVar2(interp, \"argv0\", NULL, TCL_GLOBAL_ONLY);\n    if ((name == NULL) || (*name == 0)) {\n\tname = \"tk\";\n    } else {\n\tp = strrchr(name, '/');\n\tif (p != NULL) {\n\t    name = p+1;\n\t}\n    }\n    Tcl_DStringAppend(namePtr, name, TCL_INDEX_NONE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayWarning --\n *\n *\tThis routines is called from Tk_Main to display warning messages that\n *\toccur during startup.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates messages on stdout.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayWarning(\n    const char *msg,\t\t/* Message to be displayed. */\n    const char *title)\t\t/* Title of warning. */\n{\n    Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);\n\n    if (errChannel) {\n\tTcl_WriteChars(errChannel, title, TCL_INDEX_NONE);\n\tTcl_WriteChars(errChannel, \": \", 2);\n\tTcl_WriteChars(errChannel, msg, TCL_INDEX_NONE);\n\tTcl_WriteChars(errChannel, \"\\n\", 1);\n    }\n}\n\f\n#ifdef HAVE_COREFOUNDATION\n\n/*\n *----------------------------------------------------------------------\n *\n * GetLibraryPath --\n *\n *\tIf we have a bundle structure for the Tk installation, then check\n *\tthere first to see if we can find the libraries there.\n *\n * Results:\n *\tTCL_OK if we have found the tk library; TCL_ERROR otherwise.\n *\n * Side effects:\n *\tSame as for Tcl_MacOSXOpenVersionedBundleResources.\n *\n *----------------------------------------------------------------------\n */\n\n#ifdef TK_FRAMEWORK\nstatic int\nGetLibraryPath(\n    Tcl_Interp *interp)\n{\n    int foundInFramework = TCL_ERROR;\n    char tkLibPath[PATH_MAX + 1];\n\n    foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,\n\t    \"com.tcltk.tklibrary\", TK_FRAMEWORK_VERSION, 0, PATH_MAX,\n\t    tkLibPath);\n    if (tkLibPath[0] != '\\0') {\n\tTcl_SetVar2(interp, \"tk_library\", NULL, tkLibPath, TCL_GLOBAL_ONLY);\n    }\n    return foundInFramework;\n}\n#else\nstatic int\nGetLibraryPath(\n    TCL_UNUSED(Tcl_Interp *))\n{\n    return TCL_ERROR;\n}\n#endif\n#endif /* HAVE_COREFOUNDATION */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixInt.h",
    "content": "/*\n * tkUnixInt.h --\n *\n *\tThis file contains declarations that are shared among the\n *\tUNIX-specific parts of Tk but aren't used by the rest of Tk.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKUNIXINT\n#define _TKUNIXINT\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Prototypes for procedures that are referenced in files other than the ones\n * they're defined in.\n */\n\n#include \"tkIntPlatDecls.h\"  /* IWYU pragma: export */\n\nMODULE_SCOPE  int       Tktray_Init (Tcl_Interp* interp);\nMODULE_SCOPE  int       SysNotify_Init (Tcl_Interp* interp);\nMODULE_SCOPE  int       Cups_Init (Tcl_Interp* interp);\nMODULE_SCOPE  int       TkAtkAccessibility_Init (Tcl_Interp *interp) ;\n\n#endif /* _TKUNIXINT */\n\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixKey.c",
    "content": "/*\n * tkUnixKey.c --\n *\n *\tThis file contains routines for dealing with international keyboard\n *\tinput.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n#undef register /* Keyword \"register\" is used in XKBlib.h, so don't try tricky things here */\n#define XkbOpenDisplay XkbOpenDisplay_ /* Move out of the way, conflicting definitions */\n#include <X11/XKBlib.h>\n#undef XkbOpenDisplay\n\n/*\n * Prototypes for local functions defined in this file:\n */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetCaretPos --\n *\n *\tThis enables correct placement of the XIM caret. This is called by\n *\twidgets to indicate their cursor placement. This is currently only\n *\tused for over-the-spot XIM.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetCaretPos(\n    Tk_Window tkwin,\n    int x,\n    int y,\n    int height)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n\n    if ((dispPtr->caret.winPtr == winPtr)\n\t    && (dispPtr->caret.x == x)\n\t    && (dispPtr->caret.y == y)\n\t    && (dispPtr->caret.height == height)) {\n\treturn;\n    }\n\n    dispPtr->caret.winPtr = winPtr;\n    dispPtr->caret.x = x;\n    dispPtr->caret.y = y;\n    dispPtr->caret.height = height;\n\n    /*\n     * Adjust the XIM caret position.\n     */\n\n#ifdef TK_USE_INPUT_METHODS\n    if ((dispPtr->flags & TK_DISPLAY_USE_IM)\n\t    && (dispPtr->inputStyle & XIMPreeditPosition)\n\t    && (winPtr->inputContext != NULL)) {\n\tXVaNestedList preedit_attr;\n\tXPoint spot;\n\n\tspot.x = dispPtr->caret.x;\n\tspot.y = dispPtr->caret.y + dispPtr->caret.height;\n\tpreedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);\n\tXSetICValues(winPtr->inputContext, XNPreeditAttributes, preedit_attr,\n\t\tNULL);\n\tXFree(preedit_attr);\n    }\n#endif\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetString --\n *\n *\tRetrieve the UTF string associated with a keyboard event.\n *\n * Results:\n *\tReturns the UTF string.\n *\n * Side effects:\n *\tStores the input string in the specified Tcl_DString. Modifies the\n *\tinternal input state. This routine can only be called once for a given\n *\tevent.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkpGetString(\n    TkWindow *winPtr,\t\t/* Window where event occurred */\n    XEvent *eventPtr,\t\t/* X keyboard event. */\n    Tcl_DString *dsPtr)\t\t/* Initialized, empty string to hold result. */\n{\n    Tcl_Size len;\n    Tcl_DString buf;\n    TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;\n\n    /*\n     * If we have the value cached already, use it now. [Bug 1373712]\n     */\n\n    if (kePtr->charValuePtr != NULL) {\n\tTcl_DStringSetLength(dsPtr, kePtr->charValueLen);\n\tmemcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr,\n\t\tkePtr->charValueLen+1);\n\treturn Tcl_DStringValue(dsPtr);\n    }\n\n    /*\n     * Only do this for KeyPress events, otherwise\n     * further Xlib function behavior might be undefined.\n     */\n\n    if (eventPtr->type != KeyPress) {\n\tlen = 0;\n\tTcl_DStringSetLength(dsPtr, len);\n\tgoto done;\n    }\n\n#ifdef TK_USE_INPUT_METHODS\n    if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)\n\t    && (winPtr->inputContext != NULL)) {\n\tStatus status;\n\n#if X_HAVE_UTF8_STRING\n\tTcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1);\n\tlen = (Tcl_Size)Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey,\n\t\tTcl_DStringValue(dsPtr), (int)Tcl_DStringLength(dsPtr),\n\t\t&kePtr->keysym, &status);\n\n\tif (status == XBufferOverflow) {\n\t    /*\n\t     * Expand buffer and try again.\n\t     */\n\n\t    Tcl_DStringSetLength(dsPtr, len);\n\t    len =(Tcl_Size) Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey,\n\t\t    Tcl_DStringValue(dsPtr), (int)Tcl_DStringLength(dsPtr),\n\t\t    &kePtr->keysym, &status);\n\t}\n\tif ((status != XLookupChars) && (status != XLookupBoth)) {\n\t    len = 0;\n\t}\n\tTcl_DStringSetLength(dsPtr, len);\n#else /* !X_HAVE_UTF8_STRING */\n\t/*\n\t * Overallocate the dstring to the maximum stack amount.\n\t */\n\n\tTcl_DStringInit(&buf);\n\tTcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);\n\tlen = XmbLookupString(winPtr->inputContext, &eventPtr->xkey,\n\t\tTcl_DStringValue(&buf), Tcl_DStringLength(&buf),\n\t\t&kePtr->keysym, &status);\n\n\t/*\n\t * If the buffer wasn't big enough, grow the buffer and try again.\n\t */\n\n\tif (status == XBufferOverflow) {\n\t    Tcl_DStringSetLength(&buf, len);\n\t    len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey,\n\t\t    Tcl_DStringValue(&buf), len, &kePtr->keysym, &status);\n\t}\n\tif ((status != XLookupChars) && (status != XLookupBoth)) {\n\t    len = 0;\n\t}\n\tTcl_DStringSetLength(&buf, len);\n\tTcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr);\n\tTcl_DStringFree(&buf);\n#endif /* X_HAVE_UTF8_STRING */\n    } else\n#endif /* TK_USE_INPUT_METHODS */\n    {\n\t/*\n\t * Fall back to convert a keyboard event to a UTF-8 string using\n\t * XLookupString. This is used when input methods are turned off.\n\t *\n\t * Note: XLookupString() normally returns a single ISO Latin 1 or\n\t * ASCII control character.\n\t */\n\n\tTcl_DStringInit(&buf);\n\tTcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);\n\tlen = (Tcl_Size)XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf),\n\t\tTCL_DSTRING_STATIC_SIZE, &kePtr->keysym, 0);\n\tTcl_DStringValue(&buf)[len] = '\\0';\n\n\tif (len == 1) {\n\t    len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0],\n\t\t    Tcl_DStringValue(dsPtr));\n\t    Tcl_DStringSetLength(dsPtr, len);\n\t} else {\n\t    /*\n\t     * len > 1 should only happen if someone has called XRebindKeysym.\n\t     * Assume UTF-8.\n\t     */\n\n\t    Tcl_DStringSetLength(dsPtr, len);\n\t    strncpy(Tcl_DStringValue(dsPtr), Tcl_DStringValue(&buf), len);\n\t}\n    }\n\n    /*\n     * Cache the string in the event so that if/when we return to this\n     * function, we will be able to produce it without asking X. This stops us\n     * from having to reenter the XIM engine. [Bug 1373712]\n     */\n\ndone:\n    kePtr->charValuePtr = (char *)Tcl_Alloc(len + 1);\n    kePtr->charValueLen = len;\n    memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), len + 1);\n    return Tcl_DStringValue(dsPtr);\n}\n\f\n/*\n * When mapping from a keysym to a keycode, need information about the\n * modifier state to be used so that when they call XbkKeycodeToKeysym taking\n * into account the xkey.state, they will get back the original keysym.\n */\n\nvoid\nTkpSetKeycodeAndState(\n    Tk_Window tkwin,\n    KeySym keySym,\n    XEvent *eventPtr)\n{\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    int state, mincode, maxcode;\n    KeyCode keycode;\n\n    if (keySym == NoSymbol) {\n\tkeycode = 0;\n    } else {\n\tkeycode = XKeysymToKeycode(dispPtr->display, keySym);\n    }\n    eventPtr->xkey.keycode = keycode;\n    if (keycode != 0) {\n\tfor (state = 0; state < 4; state++) {\n\t    if (XLookupKeysym(&eventPtr->xkey, state) == keySym) {\n\t\tif (state & 1) {\n\t\t    eventPtr->xkey.state |= ShiftMask;\n\t\t}\n\t\tif (state & 2) {\n\t\t    eventPtr->xkey.state |= dispPtr->modeModMask;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * Filter keycodes out of range, otherwise further Xlib function\n     * behavior might be undefined, in particular XIM could cause crashes.\n     */\n\n    mincode = 0;\n    maxcode = -1;\n    XDisplayKeycodes(dispPtr->display, &mincode, &maxcode);\n    if (keycode < (KeyCode)mincode) {\n\tkeycode = mincode;\n    } else if (keycode > (KeyCode)maxcode) {\n\tkeycode = maxcode;\n    }\n\n    eventPtr->xkey.keycode = keycode;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetKeySym --\n *\n *\tGiven an X KeyPress or KeyRelease event, map the keycode in the event\n *\tinto a KeySym.\n *\n * Results:\n *\tThe return value is the KeySym corresponding to eventPtr, or NoSymbol\n *\tif no matching Keysym could be found.\n *\n * Side effects:\n *\tIn the first call for a given display, keycode-to-KeySym maps get\n *\tloaded.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nTkpGetKeySym(\n    TkDisplay *dispPtr,\t\t/* Display in which to map keycode. */\n    XEvent *eventPtr)\t\t/* Description of X event. */\n{\n    KeySym sym;\n    int index;\n    TkKeyEvent* kePtr = (TkKeyEvent*) eventPtr;\n\n    /*\n     * X11 keycodes always lie in the inclusive range [8,255].\n     */\n\n    if (eventPtr->xkey.keycode > 0xff) {\n\treturn NoSymbol;\n    }\n\n    /*\n     * Refresh the mapping information if it's stale. This must happen before\n     * we do any input method processing. [Bug 3599312]\n     */\n\n    if (dispPtr->bindInfoStale) {\n\tTkpInitKeymapInfo(dispPtr);\n    }\n\n#ifdef TK_USE_INPUT_METHODS\n    /*\n     * If input methods are active, we may already have determined a keysym.\n     * Return it.\n     */\n\n    if (eventPtr->type == KeyPress && dispPtr\n\t    && (dispPtr->flags & TK_DISPLAY_USE_IM)) {\n\tif (kePtr->charValuePtr == NULL) {\n\t    Tcl_DString ds;\n\t    TkWindow *winPtr = (TkWindow *)\n\t\tTk_IdToWindow(eventPtr->xany.display, eventPtr->xany.window);\n\n\t    Tcl_DStringInit(&ds);\n\t    (void) TkpGetString(winPtr, eventPtr, &ds);\n\t    Tcl_DStringFree(&ds);\n\t}\n\tif (kePtr->charValuePtr != NULL) {\n\t    return kePtr->keysym;\n\t}\n    }\n#endif\n\n    /*\n     * Figure out which of the four slots in the keymap vector to use for this\n     * key. Refer to Xlib documentation for more info on how this computation\n     * works.\n     */\n\n    index = 0;\n    if (eventPtr->xkey.state & dispPtr->modeModMask) {\n\tindex = 2;\n    }\n    if ((eventPtr->xkey.state & ShiftMask)\n\t    || ((dispPtr->lockUsage != LU_IGNORE)\n\t    && (eventPtr->xkey.state & LockMask))) {\n\tindex += 1;\n    }\n    sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0,\n\t    index);\n\n    /*\n     * Special handling: if the key was shifted because of Lock, but lock is\n     * only caps lock, not shift lock, and the shifted keysym isn't upper-case\n     * alphabetic, then switch back to the unshifted keysym.\n     */\n\n#ifndef XK_Oslash\n    /* XK_Oslash is the official name, but might not be present in older X11 headers */\n#   define XK_Oslash XK_Ooblique\n#endif\n    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)\n\t    && (dispPtr->lockUsage == LU_CAPS)) {\n\tif (!(((sym >= XK_A) && (sym <= XK_Z))\n\t\t|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))\n\t\t|| ((sym >= XK_Oslash) && (sym <= XK_Thorn)))) {\n\t    index &= ~1;\n\t    sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,\n\t\t    0, index);\n\t}\n    }\n\n    /*\n     * Another bit of special handling: if this is a shifted key and there is\n     * no keysym defined, then use the keysym for the unshifted key.\n     */\n\n    if ((index & 1) && (sym == NoSymbol)) {\n\tsym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,\n\t\t0, index & ~1);\n    }\n    return sym;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitKeymapInfo --\n *\n *\tThis function is invoked to scan keymap information to recompute stuff\n *\tthat's important for binding, such as the modifier key (if any) that\n *\tcorresponds to \"mode switch\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tKeymap-related information in dispPtr is updated.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitKeymapInfo(\n    TkDisplay *dispPtr)\t\t/* Display for which to recompute keymap\n\t\t\t\t * information. */\n{\n    XModifierKeymap *modMapPtr;\n    KeyCode *codePtr;\n    KeySym keysym;\n    int count, i, max;\n    Tcl_Size j, arraySize;\n#define KEYCODE_ARRAY_SIZE 20\n\n    dispPtr->bindInfoStale = 0;\n    modMapPtr = XGetModifierMapping(dispPtr->display);\n\n    /*\n     * Check the keycodes associated with the Lock modifier. If any of them is\n     * associated with the XK_Shift_Lock modifier, then Lock has to be\n     * interpreted as Shift Lock, not Caps Lock.\n     */\n\n    dispPtr->lockUsage = LU_IGNORE;\n    codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;\n    for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\tkeysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);\n\tif (keysym == XK_Shift_Lock) {\n\t    dispPtr->lockUsage = LU_SHIFT;\n\t    break;\n\t}\n\tif (keysym == XK_Caps_Lock) {\n\t    dispPtr->lockUsage = LU_CAPS;\n\t    break;\n\t}\n    }\n\n    /*\n     * Look through the keycodes associated with modifiers to see if the the\n     * \"mode switch\", \"meta\", or \"alt\" keysyms are associated with any\n     * modifiers. If so, remember their modifier mask bits.\n     */\n\n    dispPtr->modeModMask = 0;\n    dispPtr->metaModMask = 0;\n    dispPtr->altModMask = 0;\n    codePtr = modMapPtr->modifiermap;\n    max = 8 * modMapPtr->max_keypermod;\n    for (i = 0; i < max; i++, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\tkeysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);\n\n\tif (keysym == XK_Mode_switch) {\n\t    dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n\tif ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {\n\t    dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n\tif ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {\n\t    dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n    }\n\n    /*\n     * Create an array of the keycodes for all modifier keys.\n     */\n\n    if (dispPtr->modKeyCodes != NULL) {\n\tTcl_Free(dispPtr->modKeyCodes);\n    }\n    dispPtr->numModKeyCodes = 0;\n    arraySize = KEYCODE_ARRAY_SIZE;\n    dispPtr->modKeyCodes = (KeyCode *)Tcl_Alloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));\n    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\n\t/*\n\t * Make sure that the keycode isn't already in the array.\n\t */\n\n\tfor (j = 0; j < dispPtr->numModKeyCodes; j++) {\n\t    if (dispPtr->modKeyCodes[j] == *codePtr) {\n\t\t/*\n\t\t * 'continue' the outer loop.\n\t\t */\n\n\t\tgoto nextModCode;\n\t    }\n\t}\n\tif (dispPtr->numModKeyCodes >= arraySize) {\n\t    KeyCode *newCodes;\n\n\t    /*\n\t     * Ran out of space in the array; grow it.\n\t     */\n\n\t    arraySize *= 2;\n\t    newCodes = (KeyCode *)Tcl_Alloc(arraySize * sizeof(KeyCode));\n\t    memcpy(newCodes, dispPtr->modKeyCodes,\n\t\t    dispPtr->numModKeyCodes * sizeof(KeyCode));\n\t    Tcl_Free(dispPtr->modKeyCodes);\n\t    dispPtr->modKeyCodes = newCodes;\n\t}\n\tdispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;\n\tdispPtr->numModKeyCodes++;\n    nextModCode:\n\tcontinue;\n    }\n    XFreeModifiermap(modMapPtr);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixMenu.c",
    "content": "/*\n * tkUnixMenu.c --\n *\n *\tThis module implements the UNIX platform-specific features of menus.\n *\n * Copyright © 1996-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkMenu.h\"\n\n/*\n * Constants used for menu drawing.\n */\n\n#define MENU_MARGIN_WIDTH\t2\n#define MENU_DIVIDER_HEIGHT\t2\n#define CASCADE_ARROW_SIZE\t4\n\n/*\n * Platform specific flags for Unix.\n */\n\n#define ENTRY_HELP_MENU\t\tENTRY_PLATFORM_FLAG1\n\n/*\n * Shared with button widget.\n */\n\nMODULE_SCOPE void\tTkpDrawCheckIndicator(Tk_Window tkwin,\n\t\t\t    Display *display, Drawable d, int x, int y,\n\t\t\t    Tk_3DBorder bgBorder, XColor *indicatorColor,\n\t\t\t    XColor *selectColor, XColor *disColor, int on,\n\t\t\t    int disabled, int mode);\n/*\n * Indicator Draw Modes\n */\n\n#define CHECK_BUTTON 0\n#define CHECK_MENU   1\n#define RADIO_BUTTON 2\n#define RADIO_MENU   3\n\n/*\n * Procedures used internally.\n */\n\nstatic void\t\tSetHelpMenu(TkMenu *menuPtr);\nstatic void\t\tDrawMenuEntryBackground(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d,\n\t\t\t    Tk_3DBorder activeBorder, Tk_3DBorder bgBorder,\n\t\t\t    int x, int y, int width, int heigth);\nstatic void\t\tDrawMenuEntryIndicator(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d,\n\t\t\t    Tk_3DBorder border, XColor *indicatorColor,\n\t\t\t    XColor *disableColor, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int x, int y,\n\t\t\t    int width, int height);\nstatic void\t\tDrawMenuEntryLabel(TkMenu * menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tDrawMenuSeparator(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tDrawTearoffEntry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tDrawMenuUnderline(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tGetMenuAccelGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int *widthPtr,\n\t\t\t    int *heightPtr);\nstatic void\t\tGetMenuLabelGeometry(TkMenuEntry *mePtr,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetMenuIndicatorGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetMenuSeparatorGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetTearoffEntryGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int *widthPtr,\n\t\t\t    int *heightPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpNewMenu --\n *\n *\tGets the platform-specific piece of the menu. Invoked during idle\n *\tafter the generic part of the menu has been created.\n *\n * Results:\n *\tStandard TCL error.\n *\n * Side effects:\n *\tAllocates any platform specific allocations and places them in the\n *\tplatformData field of the menuPtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpNewMenu(\n    TkMenu *menuPtr)\n{\n    SetHelpMenu(menuPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenu --\n *\n *\tDestroys platform-specific menu structures. Called when the generic\n *\tmenu structure is destroyed for the menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll platform-specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenu(\n    TCL_UNUSED(TkMenu *))\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenuEntry --\n *\n *\tCleans up platform-specific menu entry items. Called when entry is\n *\tdestroyed in the generic code.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll platform specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenuEntry(\n    TCL_UNUSED(TkMenuEntry *))\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureMenuEntry --\n *\n *\tProcesses configuration options for menu entries. Called when the\n *\tgeneric options are processed for the menu.\n *\n * Results:\n *\tReturns standard TCL result. If TCL_ERROR is returned, then the\n *\tinterp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information get set for mePtr; old resources get freed,\n *\tif any need it.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpConfigureMenuEntry(\n    TkMenuEntry *mePtr)/* Information about menu entry; may or may\n\t\t\t\t * not already have values for some fields. */\n{\n    /*\n     * If this is a cascade menu, and the child menu exists, check to see if\n     * the child menu is a help menu.\n     */\n\n    if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {\n\tTkMenuReferences *menuRefPtr;\n\n\tmenuRefPtr = TkFindMenuReferencesObj(mePtr->menuPtr->interp,\n\t\tmePtr->namePtr);\n\tif ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {\n\t    SetHelpMenu(menuRefPtr->menuPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNewEntry --\n *\n *\tCalled when a new entry is created in a menu. Fills in platform\n *\tspecific data for the entry. The platformEntryData field is used to\n *\tstore the indicator diameter for radio button and check box entries.\n *\n * Results:\n *\tStandard TCL error.\n *\n * Side effects:\n *\tNone on Unix.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpMenuNewEntry(\n    TCL_UNUSED(TkMenuEntry *))\n{\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetWindowMenuBar --\n *\n *\tSets up the menu as a menubar in the given window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRecomputes geometry of given window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetWindowMenuBar(\n    Tk_Window tkwin,\t\t/* The window we are setting */\n    TkMenu *menuPtr)\t\t/* The menu we are setting */\n{\n    if (menuPtr == NULL) {\n\tTkUnixSetMenubar(tkwin, NULL);\n    } else {\n\tTkUnixSetMenubar(tkwin, menuPtr->tkwin);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetMainMenuBar --\n *\n *\tCalled when a toplevel widget is brought to front. On the Macintosh,\n *\tsets up the menubar that goes accross the top of the main monitor. On\n *\tother platforms, nothing is necessary.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRecompute geometry of given window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetMainMenubar(\n    TCL_UNUSED(Tcl_Interp *),\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(const char *))\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuIndicatorGeometry --\n *\n *\tFills out the geometry of the indicator in a menu item. Note that the\n *\tmePtr->height field must have already been filled in by\n *\tGetMenuLabelGeometry since this height depends on the label height.\n *\n * Results:\n *\twidthPtr and heightPtr point to the new geometry values.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMenuIndicatorGeometry(\n    TkMenu *menuPtr,\t\t\t/* The menu we are drawing. */\n    TkMenuEntry *mePtr,\t\t\t/* The entry we are interested in. */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    TCL_UNUSED(const Tk_FontMetrics *),\t/* The precalculated metrics */\n    int *widthPtr,\t\t\t/* The resulting width */\n    int *heightPtr)\t\t\t/* The resulting height */\n{\n    int borderWidth;\n\n    if ((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    || (mePtr->type == RADIO_BUTTON_ENTRY)) {\n\tif (!mePtr->hideMargin && mePtr->indicatorOn) {\n\t    if ((mePtr->image != NULL) || (mePtr->bitmapPtr != NULL)) {\n\t\t*widthPtr = (14 * mePtr->height) / 10;\n\t\t*heightPtr = mePtr->height;\n\t\tif (mePtr->type == CHECK_BUTTON_ENTRY) {\n\t\t    mePtr->platformEntryData = (TkMenuPlatformEntryData)\n\t\t\t    INT2PTR((65 * mePtr->height) / 100);\n\t\t} else {\n\t\t    mePtr->platformEntryData = (TkMenuPlatformEntryData)\n\t\t\t    INT2PTR((75 * mePtr->height) / 100);\n\t\t}\n\t    } else {\n\t\t*widthPtr = *heightPtr = mePtr->height;\n\t\tif (mePtr->type == CHECK_BUTTON_ENTRY) {\n\t\t    mePtr->platformEntryData = (TkMenuPlatformEntryData)\n\t\t\t    INT2PTR((80 * mePtr->height) / 100);\n\t\t} else {\n\t\t    mePtr->platformEntryData = (TkMenuPlatformEntryData)\n\t\t\t    INT2PTR(mePtr->height);\n\t\t}\n\t    }\n\t} else {\n\t    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t\t    &borderWidth);\n\t    *heightPtr = 0;\n\t    *widthPtr = borderWidth;\n\t}\n    } else {\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t\t&borderWidth);\n\t*heightPtr = 0;\n\t*widthPtr = borderWidth;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuAccelGeometry --\n *\n *\tGet the geometry of the accelerator area of a menu item.\n *\n * Results:\n *\theightPtr and widthPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMenuAccelGeometry(\n    TkMenu *menuPtr,\t\t/* The menu was are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are getting the geometry for */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int *widthPtr,\t\t/* The width of the acclerator area */\n    int *heightPtr)\t\t/* The height of the accelerator area */\n{\n    *heightPtr = fmPtr->linespace;\n    if (mePtr->type == CASCADE_ENTRY) {\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint arrowWidth = (int)(CASCADE_ARROW_SIZE * scalingLevel) + 1;\n\n\t*widthPtr = 2 * arrowWidth;\n    } else if ((menuPtr->menuType != MENUBAR) && (mePtr->accelPtr != NULL)) {\n\tconst char *accel = Tcl_GetString(mePtr->accelPtr);\n\n\t*widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);\n    } else {\n\t*widthPtr = 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryBackground --\n *\n *\tThis procedure draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryBackground(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing. */\n    Drawable d,\t\t\t/* The drawable we are drawing into */\n    Tk_3DBorder activeBorder,\t/* The border for an active item */\n    Tk_3DBorder bgBorder,\t/* The background border */\n    int x,\t\t\t/* Left coordinate of entry rect */\n    int y,\t\t\t/* Right coordinate of entry rect */\n    int width,\t\t\t/* Width of entry rect */\n    int height)\t\t\t/* Height of entry rect */\n{\n    if (mePtr->state == ENTRY_ACTIVE) {\n\tint relief;\n\tint activeBorderWidth;\n\n\tbgBorder = activeBorder;\n\n\tif ((menuPtr->menuType == MENUBAR)\n\t\t&& ((menuPtr->postedCascade == NULL)\n\t\t|| (menuPtr->postedCascade != mePtr))) {\n\t    relief = TK_RELIEF_FLAT;\n\t} else {\n\t    relief = menuPtr->activeRelief;\n\t}\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\tTk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,\n\t\tactiveBorderWidth, relief);\n    } else {\n\tTk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,\n\t\t0, TK_RELIEF_FLAT);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryAccelerator --\n *\n *\tThis procedure draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryAccelerator(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* The drawable we are drawing into */\n    GC gc,\t\t\t/* The precalculated gc to draw with */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */\n    int x,\t\t\t/* Left coordinate of entry rect */\n    int y,\t\t\t/* Top coordinate of entry rect */\n    int width,\t\t\t/* Width of entry */\n    int height,\t\t\t/* Height of entry */\n    bool drawArrow)\t\t/* Whether or not to draw arrow. */\n{\n    int borderWidth, activeBorderWidth;\n    double scalingLevel = TkScalingLevel(menuPtr->tkwin);\n    int arrowSize = (int)(CASCADE_ARROW_SIZE * scalingLevel);\n    int arrowWidth = arrowSize + 1, arrowHeight = 2*arrowSize + 1;\n    XPoint points[4];\n\n    /*\n     * Draw accelerator or cascade arrow.\n     */\n\n    if (menuPtr->menuType == MENUBAR) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t    &borderWidth);\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,\n\t    &activeBorderWidth);\n    if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {\n\t/*\n\t * The value of points[0].x below is based on the following equations:\n\t * points[0].x + arrowWidth + cascadeOffset = menuWidth\n\t * cascadeOffset = borderWidth + activeBorderWidth + 2*scalingLevel\n\t * (see function AdjustMenuCoords() in file tkMenuDraw.c)\n\t * menuWidth = x + width + borderWidth\n\t */\n\n\tpoints[0].x = x + width - activeBorderWidth - (int)round(2*scalingLevel)\n\t\t      - arrowWidth;\n\tpoints[0].y = y + (height - arrowHeight)/2;\n\tpoints[1].x = points[0].x;\n\tpoints[1].y = points[0].y + arrowHeight - 1;\n\tpoints[2].x = points[0].x + arrowSize;\n\tpoints[2].y = points[0].y + arrowSize;\n\tpoints[3].x = points[0].x;\n\tpoints[3].y = points[0].y;\n\n\tXFillPolygon(Tk_Display(menuPtr->tkwin), d, gc, points, 3, Complex,\n\t\tCoordModeOrigin);\n\tXDrawLines(Tk_Display(menuPtr->tkwin), d, gc, points, 4,\n\t\tCoordModeOrigin);\n\n\t/* Work around bug [77527326e5] */\n\tXDrawPoint(Tk_Display(menuPtr->tkwin), d, gc, points[2].x, points[2].y);\n    } else if (mePtr->accelPtr != NULL) {\n\tconst char *accel = Tcl_GetString(mePtr->accelPtr);\n\tint left = x + mePtr->labelWidth + activeBorderWidth\n\t\t+ mePtr->indicatorSpace;\n\n\tif (menuPtr->menuType == MENUBAR) {\n\t    left += (int)round(5*scalingLevel);\n\t}\n\tTk_DrawChars(menuPtr->display, d, gc, tkfont, accel,\n\t\tmePtr->accelLength, left,\n\t\t(y + (height + fmPtr->ascent - fmPtr->descent) / 2));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryIndicator --\n *\n *\tThis procedure draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryIndicator(\n    TkMenu *menuPtr,\t\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t\t/* The drawable to draw into */\n    Tk_3DBorder border,\t\t\t/* The background color */\n    XColor *indicatorColor,\t\t/* The color to draw indicators with */\n    XColor *disableColor,\t\t/* The color use use when disabled */\n    TCL_UNUSED(Tk_Font),\t\t/* The font to draw with */\n    TCL_UNUSED(const Tk_FontMetrics *),\t/* The font metrics of the font */\n    int x,\t\t\t\t/* The left of the entry rect */\n    int y,\t\t\t\t/* The top of the entry rect */\n    TCL_UNUSED(int),\t\t\t/* Width of menu entry */\n    int height)\t\t\t\t/* Height of menu entry */\n{\n    /*\n     * Draw check-button indicator.\n     */\n\n    if ((mePtr->type == CHECK_BUTTON_ENTRY) && mePtr->indicatorOn) {\n\tint top, left, activeBorderWidth;\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint disabled = (mePtr->state == ENTRY_DISABLED);\n\tXColor *bg;\n\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\tbg = Tk_3DBorderColor(border);\n\ttop = y + height/2;\n\tleft = x + activeBorderWidth\n\t\t+ (int)round(DECORATION_BORDER_WIDTH * scalingLevel)\n\t\t+ mePtr->indicatorSpace/2;\n\n\tTkpDrawCheckIndicator(menuPtr->tkwin, menuPtr->display, d, left, top,\n\t\tborder, indicatorColor, bg, disableColor,\n\t\t(mePtr->entryFlags & ENTRY_SELECTED), disabled, CHECK_MENU);\n    }\n\n    /*\n     * Draw radio-button indicator.\n     */\n\n    if ((mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn) {\n\tint top, left, activeBorderWidth;\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint disabled = (mePtr->state == ENTRY_DISABLED);\n\tXColor *bg;\n\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\tbg = Tk_3DBorderColor(border);\n\ttop = y + height/2;\n\tleft = x + activeBorderWidth\n\t\t+ (int)round(DECORATION_BORDER_WIDTH * scalingLevel)\n\t\t+ mePtr->indicatorSpace/2;\n\n\tTkpDrawCheckIndicator(menuPtr->tkwin, menuPtr->display, d, left, top,\n\t\tborder, indicatorColor, bg, disableColor,\n\t\t(mePtr->entryFlags & ENTRY_SELECTED), disabled, RADIO_MENU);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuSeparator --\n *\n *\tThis procedure draws a separator menu item.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuSeparator(\n    TkMenu *menuPtr,\t\t\t/* The menu we are drawing */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t\t/* The drawable we are using */\n    TCL_UNUSED(GC),\t\t\t/* The gc to draw into */\n    TCL_UNUSED(Tk_Font),\t\t/* The font to draw with */\n    TCL_UNUSED(const Tk_FontMetrics *),\t/* The font metrics from the font */\n    int x, int y,\n    int width, int height)\n{\n    XPoint points[2];\n    Tk_3DBorder border;\n    if (menuPtr->menuType == MENUBAR) {\n\treturn;\n    }\n\n    points[0].x = x;\n    points[0].y = y + height/2;\n    points[1].x = x + width - 1;\n    points[1].y = points[0].y;\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,\n\t    TK_RELIEF_RAISED);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryLabel --\n *\n *\tThis procedure draws the label part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryLabel(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing. */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing. */\n    Drawable d,\t\t\t/* What we are drawing into. */\n    GC gc,\t\t\t/* The gc we are drawing into.*/\n    Tk_Font tkfont,\t\t/* The precalculated font. */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics. */\n    int x,\t\t\t/* Left edge. */\n    int y,\t\t\t/* Top edge. */\n    int width,\t\t\t/* width of entry. */\n    int height)\t\t\t/* height of entry. */\n{\n    int indicatorSpace = mePtr->indicatorSpace;\n    int activeBorderWidth, leftEdge, imageHeight, imageWidth;\n    int textHeight = 0, textWidth = 0;\t/* stop GCC warning */\n    int haveImage = 0, haveText = 0;\n    int imageXOffset = 0, imageYOffset = 0;\n    int textXOffset = 0, textYOffset = 0;\n\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,\n\t    &activeBorderWidth);\n    leftEdge = x + indicatorSpace + activeBorderWidth;\n    if (menuPtr->menuType == MENUBAR) {\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tleftEdge += (int)round(5*scalingLevel);\n    }\n\n    /*\n     * Work out what we will need to draw first.\n     */\n\n    if (mePtr->image != NULL) {\n\tTk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);\n\thaveImage = 1;\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\n\tTk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight);\n\thaveImage = 1;\n    }\n    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {\n\tif (mePtr->labelLength > 0) {\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\n\t    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);\n\t    textHeight = fmPtr->linespace;\n\t    haveText = 1;\n\t}\n    }\n\n    /*\n     * Now work out what the relative positions are.\n     */\n\n    if (haveImage && haveText) {\n\tint fullWidth = (imageWidth > textWidth ? imageWidth : textWidth);\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint scaled2 = (int)round(2*scalingLevel);\n\n\tswitch ((enum compound) mePtr->compound) {\n\tcase COMPOUND_TOP:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = imageHeight/2 + scaled2;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = -textHeight/2;\n\t    break;\n\tcase COMPOUND_BOTTOM:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = -imageHeight/2;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = textHeight/2 + scaled2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\t    /*\n\t     * Position image in the indicator space to the left of the\n\t     * entries, unless this entry is a radio|check button because then\n\t     * the indicator space will be used.\n\t     */\n\n\t    textXOffset = imageWidth + scaled2;\n\t    textYOffset = 0;\n\t    imageXOffset = 0;\n\t    imageYOffset = 0;\n\t    if ((mePtr->type != CHECK_BUTTON_ENTRY)\n\t\t    && (mePtr->type != RADIO_BUTTON_ENTRY)) {\n\t\ttextXOffset -= indicatorSpace;\n\t\tif (textXOffset < 0) {\n\t\t    textXOffset = 0;\n\t\t}\n\t\timageXOffset = -indicatorSpace;\n\t    }\n\t    break;\n\tcase COMPOUND_RIGHT:\n\t    textXOffset = 0;\n\t    textYOffset = 0;\n\t    imageXOffset = textWidth + scaled2;\n\t    imageYOffset = 0;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = 0;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = 0;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n    } else {\n\ttextXOffset = 0;\n\ttextYOffset = 0;\n\timageXOffset = 0;\n\timageYOffset = 0;\n    }\n\n    /*\n     * Draw label and/or bitmap or image for entry.\n     */\n\n    if (mePtr->image != NULL) {\n\tif ((mePtr->selectImage != NULL)\n\t\t&& (mePtr->entryFlags & ENTRY_SELECTED)) {\n\t    Tk_RedrawImage(mePtr->selectImage, 0, 0,\n\t\t    imageWidth, imageHeight, d, leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));\n\t} else {\n\t    Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,\n\t\t    imageHeight, d, leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));\n\t}\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\n\tXCopyPlane(menuPtr->display, bitmap, d,\tgc, 0, 0,\n\t\t(unsigned) imageWidth, (unsigned) imageHeight,\n\t\tleftEdge + imageXOffset,\n\t\t(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);\n    }\n    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {\n\tint baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;\n\n\tif (mePtr->labelLength > 0) {\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\n\t    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,\n\t\t    mePtr->labelLength, leftEdge + textXOffset,\n\t\t    baseline + textYOffset);\n\t    DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\t    x + textXOffset, y + textYOffset,\n\t\t    width, height);\n\t}\n    }\n\n    if (mePtr->state == ENTRY_DISABLED) {\n\tif (menuPtr->disabledFgPtr == NULL) {\n\t    XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,\n\t\t    (unsigned) width, (unsigned) height);\n\t} else if ((mePtr->image != NULL)\n\t\t&& (menuPtr->disabledImageGC != NULL)) {\n\t    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,\n\t\t    leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),\n\t\t    (unsigned) imageWidth, (unsigned) imageHeight);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuUnderline --\n *\n *\tOn appropriate platforms, draw the underline character for the menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuUnderline(\n    TkMenu *menuPtr,\t\t/* The menu to draw into */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc to draw into */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int x, int y,\n    TCL_UNUSED(int), int height)\n{\n    if (mePtr->labelPtr != NULL) {\n\tint len;\n\n\tlen = Tcl_GetCharLength(mePtr->labelPtr);\n\tif (mePtr->underline < len && mePtr->underline >= -len) {\n\t    int activeBorderWidth, leftEdge, ch;\n\t    const char *label, *start, *end;\n\n\t    label = Tcl_GetString(mePtr->labelPtr);\n\t    start = Tcl_UtfAtIndex(label, (mePtr->underline < 0) ? mePtr->underline + len : mePtr->underline);\n\t    end = start + Tcl_UtfToUniChar(start, &ch);\n\n\t    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\t    menuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\t    leftEdge = x + mePtr->indicatorSpace + activeBorderWidth;\n\t    if (menuPtr->menuType == MENUBAR) {\n\t\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\t\tleftEdge += (int)round(5*scalingLevel);\n\t    }\n\n\t    Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, label, leftEdge,\n\t\t    y + (height + fmPtr->ascent - fmPtr->descent) / 2,\n\t\t    start - label, end - label);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostMenu --\n *\n *\tPosts a menu on the screen so that the top left corner of the\n *      specified entry is located at the point (x, y) in screen coordinates.\n *      If the entry parameter is negative, the upper left corner of the\n *      menu itself is placed at the point.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu is posted and handled.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostMenu(\n    Tcl_Interp *interp,\n    TkMenu *menuPtr,\n    int x, int y, Tcl_Size index)\n{\n    return TkpPostTearoffMenu(interp, menuPtr, x, y, index);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostTearoffMenu --\n *\n *\tPosts a tearoff menu on the screen so that the top left corner of the\n *      specified entry is located at the point (x, y) in screen coordinates.\n *      If the index parameter is negative, the upper left corner of the menu\n *      itself is placed at the point.  On unix this is called when posting\n *      any menu.  Adjusts the menu's position so that it fits on the screen,\n *      and maps and raises the menu.\n *\n * Results:\n *\tReturns a standard Tcl Error.\n *\n * Side effects:\n *\tThe menu is posted.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostTearoffMenu(\n    TCL_UNUSED(Tcl_Interp *),\t/* The interpreter of the menu */\n    TkMenu *menuPtr,\t\t/* The menu we are posting */\n    int x, int y, Tcl_Size index)\t/* The root X,Y coordinates where the\n\t\t\t\t * specified entry will be posted */\n{\n    int vRootX, vRootY, vRootWidth, vRootHeight;\n    int result;\n\n    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n    TkRecomputeMenu(menuPtr);\n    result = TkPostCommand(menuPtr);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * The post commands could have deleted the menu, which means we are dead\n     * and should go away.\n     */\n\n    if (menuPtr->tkwin == NULL) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Adjust the menu y position so that the specified entry will be located\n     * at the given coordinates.\n     */\n\n    if (index >= menuPtr->numEntries) {\n\tindex = menuPtr->numEntries - 1;\n    }\n    if (index >= 0) {\n\ty -= menuPtr->entries[index]->y;\n    }\n\n    /*\n     * Adjust the position of the menu if necessary to keep it visible on the\n     * screen. There are two special tricks to make this work right:\n     *\n     * 1. If a virtual root window manager is being used then the coordinates\n     *    are in the virtual root window of menuPtr's parent; since the menu\n     *    uses override-redirect mode it will be in the *real* root window for\n     *    the screen, so we have to map the coordinates from the virtual root\n     *    (if any) to the real root. Can't get the virtual root from the menu\n     *    itself (it will never be seen by the wm) so use its parent instead\n     *    (it would be better to have an an option that names a window to use\n     *    for this...).\n     * 2. The menu may not have been mapped yet, so its current size might be\n     *    the default 1x1. To compute how much space it needs, use its\n     *    requested size, not its actual size.\n     */\n\n    Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,\n\t&vRootWidth, &vRootHeight);\n    vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);\n    if (x > vRootX + vRootWidth) {\n\tx = vRootX + vRootWidth;\n    }\n    if (x < vRootX) {\n\tx = vRootX;\n    }\n    vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);\n    if (y > vRootY + vRootHeight) {\n\ty = vRootY + vRootHeight;\n    }\n    if (y < vRootY) {\n\ty = vRootY;\n    }\n    Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);\n    if (!Tk_IsMapped(menuPtr->tkwin)) {\n\tTk_MapWindow(menuPtr->tkwin);\n    }\n    TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuSeparatorGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMenuSeparatorGeometry(\n    TCL_UNUSED(TkMenu *),\t\t/* The menu we are measuring */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are measuring */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,\t/* The precalcualted font metrics */\n    int *widthPtr,\t\t\t/* The resulting width */\n    int *heightPtr)\t\t\t/* The resulting height */\n{\n    *widthPtr = 0;\n    *heightPtr = fmPtr->linespace;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTearoffEntryGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetTearoffEntryGeometry(\n    TkMenu *menuPtr,\t\t\t/* The menu we are drawing */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are measuring */\n    Tk_Font tkfont,\t\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,\t/* The precalculated font metrics */\n    int *widthPtr,\t\t\t/* The resulting width */\n    int *heightPtr)\t\t\t/* The resulting height */\n{\n    if (menuPtr->menuType != MAIN_MENU) {\n\t*heightPtr = 0;\n\t*widthPtr = 0;\n    } else {\n\t*heightPtr = fmPtr->linespace;\n\t*widthPtr = Tk_TextWidth(tkfont, \"W\", 1);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeMenubarGeometry --\n *\n *\tThis procedure is invoked to recompute the size and layout of a menu\n *\tthat is a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeMenubarGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    Tk_Font tkfont, menuFont;\n    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;\n    int width, height, x, y, currentRowHeight, maxWidth;\n    Tcl_Size i, j, lastRowBreak;\n    int maxWindowWidth, lastEntry;\n    int activeBorderWidth, helpMenuIndex = -1;\n    TkMenuEntry *mePtr;\n\n    if (menuPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,\n\t    &activeBorderWidth);\n    maxWidth = 0;\n    if (menuPtr->numEntries == 0) {\n\theight = 0;\n    } else {\n\tint borderWidth;\n\tdouble scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\tint scaled10 = (int)round(10*scalingLevel);\n\n\tmaxWindowWidth = Tk_Width(menuPtr->tkwin);\n\tif (maxWindowWidth == 1) {\n\t    maxWindowWidth = INT_MAX;\n\t}\n\tcurrentRowHeight = 0;\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t\t&borderWidth);\n\tx = y = borderWidth;\n\tlastRowBreak = 0;\n\n\t/*\n\t * On the Mac especially, getting font metrics can be quite slow, so\n\t * we want to do it intelligently. We are going to precalculate them\n\t * and pass them down to all of the measuring and drawing routines.\n\t * We will measure the font metrics of the menu once, and if an entry\n\t * has a font set, we will measure it as we come to it, and then we\n\t * decide which set to give the geometry routines.\n\t */\n\n\tmenuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n\tTk_GetFontMetrics(menuFont, &menuMetrics);\n\n\tfor (i = 0; i < menuPtr->numEntries; i++) {\n\t    mePtr = menuPtr->entries[i];\n\t    mePtr->entryFlags &= ~ENTRY_LAST_COLUMN;\n\t    if (mePtr->fontPtr != NULL) {\n\t\ttkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);\n\t\tTk_GetFontMetrics(tkfont, &entryMetrics);\n\t\tfmPtr = &entryMetrics;\n\t    } else {\n\t\ttkfont = menuFont;\n\t\tfmPtr = &menuMetrics;\n\t    }\n\n\t    /*\n\t     * For every entry, we need to check to see whether or not we\n\t     * wrap. If we do wrap, then we have to adjust all of the previous\n\t     * entries' height and y position, because when we see them the\n\t     * first time, we don't know how big its neighbor might be.\n\t     */\n\n\t    if ((mePtr->type == SEPARATOR_ENTRY)\n\t\t    || (mePtr->type == TEAROFF_ENTRY)) {\n\t\tmePtr->height = mePtr->width = 0;\n\t    } else {\n\t\tGetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height);\n\t\tmePtr->height = height + 2 * activeBorderWidth + scaled10;\n\t\tmePtr->width = width;\n\n\t\tGetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr,\n\t\t\t&width, &height);\n\t\tmePtr->indicatorSpace = width;\n\t\tif (width > 0) {\n\t\t    mePtr->width += width;\n\t\t}\n\t\tmePtr->width += 2 * activeBorderWidth + scaled10;\n\t    }\n\t    if (mePtr->entryFlags & ENTRY_HELP_MENU) {\n\t\thelpMenuIndex = i;\n\t    } else if (x + mePtr->width + borderWidth > maxWindowWidth) {\n\t\tif (i == lastRowBreak) {\n\t\t    mePtr->y = y;\n\t\t    mePtr->x = x;\n\t\t    lastRowBreak++;\n\t\t    y += mePtr->height;\n\t\t    currentRowHeight = 0;\n\t\t} else {\n\t\t    x = borderWidth;\n\t\t    for (j = lastRowBreak; j < i; j++) {\n\t\t\tmenuPtr->entries[j]->y = y + currentRowHeight\n\t\t\t\t- menuPtr->entries[j]->height;\n\t\t\tmenuPtr->entries[j]->x = x;\n\t\t\tx += menuPtr->entries[j]->width;\n\t\t    }\n\t\t    lastRowBreak = i;\n\t\t    y += currentRowHeight;\n\t\t    currentRowHeight = mePtr->height;\n\t\t}\n\t\tif (x > maxWidth) {\n\t\t    maxWidth = x;\n\t\t}\n\t\tx = borderWidth;\n\t    } else {\n\t\tx += mePtr->width;\n\t\tif (mePtr->height > currentRowHeight) {\n\t\t    currentRowHeight = mePtr->height;\n\t\t}\n\t    }\n\t}\n\n\tlastEntry = menuPtr->numEntries - 1;\n\tif (helpMenuIndex == lastEntry) {\n\t    lastEntry--;\n\t}\n\tif ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width\n\t\t+ borderWidth > maxWidth)) {\n\t    maxWidth = x + menuPtr->entries[lastEntry]->width + borderWidth;\n\t}\n\tx = borderWidth;\n\tfor (j = lastRowBreak; j < menuPtr->numEntries; j++) {\n\t    if (j == helpMenuIndex) {\n\t\tcontinue;\n\t    }\n\t    menuPtr->entries[j]->y = y + currentRowHeight\n\t\t    - menuPtr->entries[j]->height;\n\t    menuPtr->entries[j]->x = x;\n\t    x += menuPtr->entries[j]->width;\n\t}\n\n\n\tif (helpMenuIndex != -1) {\n\t    mePtr = menuPtr->entries[helpMenuIndex];\n\t    if (x + mePtr->width + borderWidth > maxWindowWidth) {\n\t\ty += currentRowHeight;\n\t\tcurrentRowHeight = mePtr->height;\n\t\tx = borderWidth;\n\t    } else if (mePtr->height > currentRowHeight) {\n\t\tcurrentRowHeight = mePtr->height;\n\t    }\n\t    mePtr->x = maxWindowWidth - borderWidth - mePtr->width;\n\t    mePtr->y = y + currentRowHeight - mePtr->height;\n\t}\n\theight = y + currentRowHeight + borderWidth;\n    }\n    width = Tk_Width(menuPtr->tkwin);\n\n    /*\n     * The X server doesn't like zero dimensions, so round up to at least 1 (a\n     * zero-sized menu should never really occur, anyway).\n     */\n\n    if (width <= 0) {\n\twidth = 1;\n    }\n    if (height <= 0) {\n\theight = 1;\n    }\n    menuPtr->totalWidth = maxWidth;\n    menuPtr->totalHeight = height;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawTearoffEntry --\n *\n *\tThis procedure draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawTearoffEntry(\n    TkMenu *menuPtr,\t\t\t/* The menu we are drawing */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t\t/* The drawable we are drawing into */\n    TCL_UNUSED(GC),\t\t\t/* The gc we are drawing with */\n    TCL_UNUSED(Tk_Font),\t\t/* The font we are drawing with */\n    TCL_UNUSED(const Tk_FontMetrics *),\t/* The metrics we are drawing with */\n    int x, int y,\n    int width, int height)\n{\n    XPoint points[2];\n    int segmentWidth, maxX;\n    Tk_3DBorder border;\n\n    if (menuPtr->menuType != MAIN_MENU) {\n\treturn;\n    }\n\n    points[0].x = x;\n    points[0].y = y + height/2;\n    points[1].y = points[0].y;\n    segmentWidth = 6;\n    maxX = x + width - 1;\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n\n    while (points[0].x < maxX) {\n\tpoints[1].x = points[0].x + segmentWidth;\n\tif (points[1].x > maxX) {\n\t    points[1].x = maxX;\n\t}\n\tTk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,\n\t\tTK_RELIEF_RAISED);\n\tpoints[0].x += 2 * segmentWidth;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitializeMenuBindings --\n *\n *\tFor every interp, initializes the bindings for Windows menus. Does\n *\tnothing on Mac or XWindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tC-level bindings are setup for the interp which will handle Alt-key\n *\tsequences for menus without beeping or interfering with user-defined\n *\tAlt-key bindings.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitializeMenuBindings(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* The interpreter to set. */\n    TCL_UNUSED(Tk_BindingTable))\t/* The table to add to. */\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetHelpMenu --\n *\n *\tGiven a menu, check to see whether or not it is a help menu cascade in\n *\ta menubar. If it is, the entry that points to this menu will be\n *\tmarked.\n *\n * RESULTS:\n *\tNone.\n *\n * Side effects:\n *\tWill set the ENTRY_HELP_MENU flag appropriately.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSetHelpMenu(\n    TkMenu *menuPtr)\t\t/* The menu we are checking */\n{\n    TkMenuEntry *cascadeEntryPtr;\n    int useMotifHelp = 0;\n    const char *option = NULL;\n    if (menuPtr->tkwin) {\n\toption = Tk_GetOption(menuPtr->tkwin, \"useMotifHelp\", \"UseMotifHelp\");\n\tif (option != NULL) {\n\t    Tcl_GetBoolean(NULL, option, &useMotifHelp);\n\t}\n    }\n\n    if (!useMotifHelp) {\n\treturn;\n    }\n\n    for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;\n\t    cascadeEntryPtr != NULL;\n\t    cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {\n\tif ((cascadeEntryPtr->menuPtr->menuType == MENUBAR)\n\t\t&& (cascadeEntryPtr->menuPtr->mainMenuPtr->tkwin != NULL)\n\t\t&& (menuPtr->mainMenuPtr->tkwin != NULL)) {\n\t    TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->mainMenuPtr;\n\t    char *helpMenuName = (char *)Tcl_Alloc(strlen(Tk_PathName(\n\t\t    mainMenuPtr->tkwin)) + strlen(\".help\") + 1);\n\n\t    strcpy(helpMenuName, Tk_PathName(mainMenuPtr->tkwin));\n\t    strcat(helpMenuName, \".help\");\n\t    if (strcmp(helpMenuName,\n\t\t    Tk_PathName(menuPtr->mainMenuPtr->tkwin)) == 0) {\n\t\tcascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU;\n\t    } else {\n\t\tcascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU;\n\t    }\n\t    Tcl_Free(helpMenuName);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawMenuEntry --\n *\n *\tDraws the given menu entry at the given coordinates with the given\n *\tattributes.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tX Server commands are executed to display the menu entry.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawMenuEntry(\n    TkMenuEntry *mePtr,\t\t/* The entry to draw */\n    Drawable d,\t\t\t/* What to draw into */\n    Tk_Font tkfont,\t\t/* Precalculated font for menu */\n    const Tk_FontMetrics *menuMetricsPtr,\n\t\t\t\t/* Precalculated metrics for menu */\n    int x,\t\t\t/* X-coordinate of topleft of entry */\n    int y,\t\t\t/* Y-coordinate of topleft of entry */\n    int width,\t\t\t/* Width of the entry rectangle */\n    int height,\t\t\t/* Height of the current rectangle */\n    DrawMenuFlags drawingParameters)\t/* Flags */\n{\n    GC gc, indicatorGC;\n    XColor *indicatorColor, *disableColor = NULL;\n    TkMenu *menuPtr = mePtr->menuPtr;\n    Tk_3DBorder bgBorder, activeBorder;\n    const Tk_FontMetrics *fmPtr;\n    Tk_FontMetrics entryMetrics;\n    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;\n    int adjustedY = y + padY;\n    int adjustedHeight = height - 2 * padY;\n\n    /*\n     * Choose the gc for drawing the foreground part of the entry.\n     */\n\n    if ((mePtr->state == ENTRY_ACTIVE) && !(drawingParameters & DRAW_MENU_ENTRY_STRICTMOTIF)) {\n\tgc = mePtr->activeGC;\n\tif (gc == NULL) {\n\t    gc = menuPtr->activeGC;\n\t}\n    } else {\n\tTkMenuEntry *cascadeEntryPtr;\n\tint parentDisabled = 0;\n\n\tfor (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;\n\t\tcascadeEntryPtr != NULL;\n\t\tcascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {\n\t    if (cascadeEntryPtr->namePtr != NULL) {\n\t\tconst char *name = Tcl_GetString(cascadeEntryPtr->namePtr);\n\n\t\tif (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {\n\t\t    if (cascadeEntryPtr->state == ENTRY_DISABLED) {\n\t\t\tparentDisabled = 1;\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\n\tif (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))\n\t\t&& (menuPtr->disabledFgPtr != NULL)) {\n\t    gc = mePtr->disabledGC;\n\t    if (gc == NULL) {\n\t\tgc = menuPtr->disabledGC;\n\t    }\n\t} else {\n\t    gc = mePtr->textGC;\n\t    if (gc == NULL) {\n\t\tgc = menuPtr->textGC;\n\t    }\n\t}\n    }\n    indicatorGC = mePtr->indicatorGC;\n    if (indicatorGC == NULL) {\n\tindicatorGC = menuPtr->indicatorGC;\n    }\n    if (mePtr->indicatorFgPtr) {\n\tindicatorColor = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\tmePtr->indicatorFgPtr);\n    } else {\n\tindicatorColor = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\tmenuPtr->indicatorFgPtr);\n    }\n\n    if (menuPtr->disabledFgPtr != NULL) {\n\tdisableColor = Tk_GetColorFromObj(menuPtr->tkwin,\n\t\tmenuPtr->disabledFgPtr);\n    }\n\n    bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t    (mePtr->borderPtr == NULL)\n\t    ? menuPtr->borderPtr : mePtr->borderPtr);\n    if (drawingParameters & DRAW_MENU_ENTRY_STRICTMOTIF) {\n\tactiveBorder = bgBorder;\n    } else {\n\tactiveBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t    (mePtr->activeBorderPtr == NULL)\n\t    ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr);\n    }\n\n    if (mePtr->fontPtr == NULL) {\n\tfmPtr = menuMetricsPtr;\n    } else {\n\ttkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);\n\tTk_GetFontMetrics(tkfont, &entryMetrics);\n\tfmPtr = &entryMetrics;\n    }\n\n    /*\n     * Need to draw the entire background, including padding. On Unix, for\n     * menubars, we have to draw the rest of the entry taking into account the\n     * padding.\n     */\n\n    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,\n\t    bgBorder, x, y, width, height);\n\n    if (mePtr->type == SEPARATOR_ENTRY) {\n\tDrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,\n\t\tfmPtr, x, adjustedY, width, adjustedHeight);\n    } else if (mePtr->type == TEAROFF_ENTRY) {\n\tDrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,\n\t\twidth, adjustedHeight);\n    } else {\n\tDrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,\n\t\twidth, adjustedHeight);\n\tDrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\tx, adjustedY, width, adjustedHeight,\n\t\t(drawingParameters & DRAW_MENU_ENTRY_ARROW) != 0);\n\tif (!mePtr->hideMargin) {\n\t    if (mePtr->state == ENTRY_ACTIVE) {\n\t\tbgBorder = activeBorder;\n\t    }\n\t    DrawMenuEntryIndicator(menuPtr, mePtr, d, bgBorder, indicatorColor,\n\t\t    disableColor, tkfont, fmPtr, x, adjustedY, width,\n\t\t    adjustedHeight);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuLabelGeometry --\n *\n *\tFigures out the size of the label portion of a menu item.\n *\n * Results:\n *\twidthPtr and heightPtr are filled in with the correct geometry\n *\tinformation.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMenuLabelGeometry(\n    TkMenuEntry *mePtr,\t\t/* The entry we are computing */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */\n    int *widthPtr,\t\t/* The resulting width of the label portion */\n    int *heightPtr)\t\t/* The resulting height of the label\n\t\t\t\t * portion */\n{\n    TkMenu *menuPtr = mePtr->menuPtr;\n    int haveImage = 0;\n\n    if (mePtr->image != NULL) {\n\tTk_SizeOfImage(mePtr->image, widthPtr, heightPtr);\n\thaveImage = 1;\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\n\tTk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);\n\thaveImage = 1;\n    } else {\n\t*heightPtr = 0;\n\t*widthPtr = 0;\n    }\n\n    if (haveImage && (mePtr->compound == COMPOUND_NONE)) {\n\t/*\n\t * We don't care about the text in this case.\n\t */\n    } else {\n\t/*\n\t * Either it is compound or we don't have an image.\n\t */\n\n\tif (mePtr->labelPtr != NULL) {\n\t    int textWidth;\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\t    double scalingLevel = TkScalingLevel(menuPtr->tkwin);\n\t    int scaled2 = (int)round(2*scalingLevel);\n\n\t    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);\n\t    if ((mePtr->compound != COMPOUND_NONE) && haveImage) {\n\t\tswitch ((enum compound) mePtr->compound) {\n\t\tcase COMPOUND_TOP:\n\t\tcase COMPOUND_BOTTOM:\n\t\t    if (textWidth > *widthPtr) {\n\t\t\t*widthPtr = textWidth;\n\t\t    }\n\n\t\t    /*\n\t\t     * Add text and padding.\n\t\t     */\n\n\t\t    *heightPtr += fmPtr->linespace + scaled2;\n\t\t    break;\n\t\tcase COMPOUND_LEFT:\n\t\tcase COMPOUND_RIGHT:\n\t\t    if (fmPtr->linespace > *heightPtr) {\n\t\t\t*heightPtr = fmPtr->linespace;\n\t\t    }\n\n\t\t    /*\n\t\t     * Add text and padding.\n\t\t     */\n\n\t\t    *widthPtr += textWidth + scaled2;\n\t\t    break;\n\t\tcase COMPOUND_CENTER:\n\t\t    if (fmPtr->linespace > *heightPtr) {\n\t\t\t*heightPtr = fmPtr->linespace;\n\t\t    }\n\t\t    if (textWidth > *widthPtr) {\n\t\t\t*widthPtr = textWidth;\n\t\t    }\n\t\t    break;\n\t\tcase COMPOUND_NONE:\n\t\t    break;\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * We don't have an image or we're not compound.\n\t\t */\n\n\t\t*heightPtr = fmPtr->linespace;\n\t\t*widthPtr = textWidth;\n\t    }\n\t} else {\n\t    /*\n\t     * An empty entry still has this height.\n\t     */\n\n\t    *heightPtr = fmPtr->linespace;\n\t}\n    }\n    *heightPtr += 1;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeStandardMenuGeometry --\n *\n *\tThis procedure is invoked to recompute the size and layout of a menu\n *\tthat is not a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeStandardMenuGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    Tk_Font tkfont, menuFont;\n    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;\n    int x, y, height, width, indicatorSpace, labelWidth, accelWidth;\n    int windowWidth, windowHeight, accelSpace;\n    Tcl_Size i, j, lastColumnBreak = 0;\n    TkMenuEntry *mePtr;\n    int borderWidth, activeBorderWidth;\n    double scalingLevel = TkScalingLevel(menuPtr->tkwin);\n    int menuMarginWidth = (int)round(MENU_MARGIN_WIDTH * scalingLevel);\n    int menuDeviderHeight = (int)round(MENU_DIVIDER_HEIGHT * scalingLevel);\n\n    if (menuPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthObj,\n\t    &borderWidth);\n    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,\n\t    &activeBorderWidth);\n    x = y = borderWidth;\n    indicatorSpace = labelWidth = accelWidth = 0;\n    windowHeight = windowWidth = 0;\n\n    /*\n     * On the Mac especially, getting font metrics can be quite slow, so we\n     * want to do it intelligently. We are going to precalculate them and pass\n     * them down to all of the measuring and drawing routines. We will measure\n     * the font metrics of the menu once. If an entry does not have its own\n     * font set, then we give the geometry/drawing routines the menu's font\n     * and metrics. If an entry has its own font, we will measure that font\n     * and give all of the geometry/drawing the entry's font and metrics.\n     */\n\n    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n    Tk_GetFontMetrics(menuFont, &menuMetrics);\n    accelSpace = Tk_TextWidth(menuFont, \"M\", 1);\n\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tmePtr = menuPtr->entries[i];\n\tif (mePtr->fontPtr == NULL) {\n\t    tkfont = menuFont;\n\t    fmPtr = &menuMetrics;\n\t} else {\n\t    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);\n\t    Tk_GetFontMetrics(tkfont, &entryMetrics);\n\t    fmPtr = &entryMetrics;\n\t}\n\n\tif ((i > 0) && mePtr->columnBreak) {\n\t    if (accelWidth != 0) {\n\t\tlabelWidth += accelSpace;\n\t    }\n\t    for (j = lastColumnBreak; j < i; j++) {\n\t\tmenuPtr->entries[j]->indicatorSpace = indicatorSpace;\n\t\tmenuPtr->entries[j]->labelWidth = labelWidth;\n\t\tmenuPtr->entries[j]->width = indicatorSpace + labelWidth\n\t\t\t+ accelWidth + 2 * activeBorderWidth;\n\t\tmenuPtr->entries[j]->x = x;\n\t\tmenuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;\n\t    }\n\t    x += indicatorSpace + labelWidth + accelWidth\n\t\t    + 2 * activeBorderWidth;\n\t    windowWidth = x;\n\t    indicatorSpace = labelWidth = accelWidth = 0;\n\t    lastColumnBreak = i;\n\t    y = borderWidth;\n\t}\n\n\tif (mePtr->type == SEPARATOR_ENTRY) {\n\t    GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr,\n\t\t    &width, &height);\n\t    mePtr->height = height;\n\t} else if (mePtr->type == TEAROFF_ENTRY) {\n\t    GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr,\n\t\t    &width, &height);\n\t    mePtr->height = height;\n\t    labelWidth = width;\n\t} else {\n\t    /*\n\t     * For each entry, compute the height required by that particular\n\t     * entry, plus three widths: the width of the label, the width to\n\t     * allow for an indicator to be displayed to the left of the label\n\t     * (if any), and the width of the accelerator to be displayed to\n\t     * the right of the label (if any). These sizes depend, of course,\n\t     * on the type of the entry.\n\t     */\n\n\t    GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height);\n\t    mePtr->height = height;\n\t    if (!mePtr->hideMargin) {\n\t\twidth += menuMarginWidth;\n\t    }\n\t    if (width > labelWidth) {\n\t\tlabelWidth = width;\n\t    }\n\n\t    GetMenuAccelGeometry(menuPtr, mePtr, tkfont,\n\t\t    fmPtr, &width, &height);\n\t    if (height > mePtr->height) {\n\t\tmePtr->height = height;\n\t    }\n\t    if (!mePtr->hideMargin) {\n\t\twidth += menuMarginWidth;\n\t    }\n\t    if (width > accelWidth) {\n\t\taccelWidth = width;\n\t    }\n\n\t    GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr,\n\t\t    &width, &height);\n\t    if (height > mePtr->height) {\n\t\tmePtr->height = height;\n\t    }\n\t    if (!mePtr->hideMargin) {\n\t\twidth += menuMarginWidth;\n\t    }\n\t    if (width > indicatorSpace) {\n\t\tindicatorSpace = width;\n\t    }\n\n\t    mePtr->height += 2 * activeBorderWidth + menuDeviderHeight;\n\t}\n\tmePtr->y = y;\n\ty += mePtr->height;\n\tif (y > windowHeight) {\n\t    windowHeight = y;\n\t}\n    }\n\n    if (accelWidth != 0) {\n\tlabelWidth += accelSpace;\n    }\n    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {\n\tmenuPtr->entries[j]->indicatorSpace = indicatorSpace;\n\tmenuPtr->entries[j]->labelWidth = labelWidth;\n\tmenuPtr->entries[j]->width = indicatorSpace + labelWidth\n\t\t+ accelWidth + 2 * activeBorderWidth;\n\tmenuPtr->entries[j]->x = x;\n\tmenuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;\n    }\n    windowWidth = x + indicatorSpace + labelWidth + accelWidth\n\t    + 2 * activeBorderWidth + borderWidth;\n    windowHeight += borderWidth;\n\n    /*\n     * The X server doesn't like zero dimensions, so round up to at least 1 (a\n     * zero-sized menu should never really occur, anyway).\n     */\n\n    if (windowWidth <= 0) {\n\twindowWidth = 1;\n    }\n    if (windowHeight <= 0) {\n\twindowHeight = 1;\n    }\n    menuPtr->totalWidth = windowWidth;\n    menuPtr->totalHeight = windowHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNotifyToplevelCreate --\n *\n *\tThis routine reconfigures the menu and the clones indicated by\n *\tmenuName becuase a toplevel has been created and any system menus need\n *\tto be created. Not applicable to UNIX.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn idle handler is set up to do the reconfiguration.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuNotifyToplevelCreate(\n    TCL_UNUSED(Tcl_Interp *),\t/* The interp the menu lives in. */\n    TCL_UNUSED(const char *))\t/* The name of the menu to reconfigure. */\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuInit --\n *\n *\tDoes platform-specific initialization of menus.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuInit(void)\n{\n    /*\n     * Nothing to do.\n     */\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuThreadInit --\n *\n *\tDoes platform-specific initialization of thread-specific menu state.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuThreadInit(void)\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixMenubu.c",
    "content": "/*\n * tkUnixMenubu.c --\n *\n *\tThis file implements the Unix specific portion of the menubutton\n *\twidget.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkMenubutton.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateMenuButton --\n *\n *\tAllocate a new TkMenuButton structure.\n *\n * Results:\n *\tReturns a newly allocated TkMenuButton structure.\n *\n * Side effects:\n *\tNone\n *\n *----------------------------------------------------------------------\n */\n\nTkMenuButton *\nTkpCreateMenuButton(\n    TCL_UNUSED(Tk_Window))\n{\n    return (TkMenuButton *)Tcl_Alloc(sizeof(TkMenuButton));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayMenuButton --\n *\n *\tThis function is invoked to display a menubutton widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menubutton in its current\n *\tmode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayMenuButton(\n    void *clientData)\t/* Information about widget. */\n{\n    TkMenuButton *mbPtr = (TkMenuButton *)clientData;\n    GC gc;\n    Tk_3DBorder border;\n    Pixmap pixmap;\n    int x = 0;\t\t\t/* Initialization needed only to stop compiler\n\t\t\t\t * warning. */\n    int y = 0;\n    Tk_Window tkwin = mbPtr->tkwin;\n    int fullWidth, fullHeight;\n    int textXOffset, textYOffset;\n    int imageWidth, imageHeight;\n    int imageXOffset, imageYOffset;\n    int width = 0, height = 0;\n\t\t\t\t/* Image information that will be used to\n\t\t\t\t * restrict disabled pixmap as well */\n    int haveImage = 0, haveText = 0;\n    int padX, padY;\n    int mbPtrBorderWidth, highlightWidth;\n\n    mbPtr->flags &= ~REDRAW_PENDING;\n    if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) {\n\tgc = mbPtr->disabledGC;\n\tborder = mbPtr->normalBorder;\n    } else if ((mbPtr->state == STATE_ACTIVE)\n\t       && !Tk_StrictMotif(mbPtr->tkwin)) {\n\tgc = mbPtr->activeTextGC;\n\tborder = mbPtr->activeBorder;\n    } else {\n\tgc = mbPtr->normalTextGC;\n\tborder = mbPtr->normalBorder;\n    }\n\n    if (mbPtr->image != NULL) {\n\tTk_SizeOfImage(mbPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (mbPtr->bitmap != None) {\n\tTk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n    imageWidth\t= width;\n    imageHeight = height;\n\n    haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0);\n\n    /*\n     * In order to avoid screen flashes, this function redraws the menu button\n     * in a pixmap, then copies the pixmap to the screen in a single\n     * operation. This means that there's no point in time where the on-sreen\n     * image has been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(mbPtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n    Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),\n\t    Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\n    imageXOffset = 0;\n    imageYOffset = 0;\n    textXOffset = 0;\n    textYOffset = 0;\n    fullWidth = 0;\n    fullHeight = 0;\n\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->padYObj, &padY);\n    if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tswitch ((enum compound) mbPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    if (mbPtr->compound == COMPOUND_TOP) {\n\t\ttextYOffset = height + padY;\n\t    } else {\n\t\timageYOffset = mbPtr->textHeight + padY;\n\t    }\n\t    fullHeight = height + mbPtr->textHeight + padY;\n\t    fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth);\n\t    textXOffset = (fullWidth - mbPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text.\n\t     */\n\n\t    if (mbPtr->compound == COMPOUND_LEFT) {\n\t\ttextXOffset = width + padX;\n\t    } else {\n\t\timageXOffset = mbPtr->textWidth + padX;\n\t    }\n\t    fullWidth = mbPtr->textWidth + padX + width;\n\t    fullHeight = (height > mbPtr->textHeight ? height :\n\t\t    mbPtr->textHeight);\n\t    textYOffset = (fullHeight - mbPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth);\n\t    fullHeight = (height > mbPtr->textHeight ? height :\n\t\t    mbPtr->textHeight);\n\t    textXOffset = (fullWidth - mbPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    textYOffset = (fullHeight - mbPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\n\tTkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,\n\t\tmbPtr->indicatorWidth + fullWidth, fullHeight, &x, &y);\n\n\timageXOffset += x;\n\timageYOffset += y;\n\tif (mbPtr->image != NULL) {\n\t    Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,\n\t\t    imageXOffset, imageYOffset);\n\t} else if (mbPtr->bitmap != None) {\n\t    XSetClipOrigin(mbPtr->display, gc, imageXOffset, imageYOffset);\n\t    XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,\n\t\t    gc, 0, 0, (unsigned) width, (unsigned) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(mbPtr->display, gc, 0, 0);\n\t}\n\n\tTk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,\n\t\tx + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,\n\t\tx + textXOffset, y + textYOffset, mbPtr->underline);\n    } else if (haveImage) {\n\tTkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,\n\t\twidth + mbPtr->indicatorWidth, height, &x, &y);\n\timageXOffset += x;\n\timageYOffset += y;\n\tif (mbPtr->image != NULL) {\n\t    Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,\n\t\t    imageXOffset, imageYOffset);\n\t} else if (mbPtr->bitmap != None) {\n\t    XSetClipOrigin(mbPtr->display, gc, x, y);\n\t    XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,\n\t\t    gc, 0, 0, (unsigned) width, (unsigned) height,\n\t\t    x, y, 1);\n\t    XSetClipOrigin(mbPtr->display, gc, 0, 0);\n\t}\n    } else {\n\tTkComputeAnchor(mbPtr->anchor, tkwin, padX, padY,\n\t\tmbPtr->textWidth + mbPtr->indicatorWidth,\n\t\tmbPtr->textHeight, &x, &y);\n\tTk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,\n\t\tx + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(mbPtr->display, pixmap, gc,\n\t\tmbPtr->textLayout, x + textXOffset, y + textYOffset,\n\t\tmbPtr->underline);\n    }\n\n    /*\n     * If the menu button is disabled with a stipple rather than a special\n     * foreground color, generate the stippled effect.\n     */\n\n    if ((mbPtr->state == STATE_DISABLED)\n\t    && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) {\n\t/*\n\t * Stipple the whole button if no disabledFg was specified, otherwise\n\t * restrict stippling only to displayed image\n\t */\n\n\tif (mbPtr->disabledFg == NULL) {\n\t    XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC,\n\t\t    mbPtr->inset, mbPtr->inset,\n\t\t    (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),\n\t\t    (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));\n\t} else {\n\t    XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC,\n\t\t    imageXOffset, imageYOffset,\n\t\t    (unsigned) imageWidth, (unsigned) imageHeight);\n\t}\n    }\n\n    /*\n     * Draw the cascade indicator for the menu button on the right side of the\n     * window, if desired.\n     */\n\n    if (mbPtr->indicatorOn) {\n\tint borderWidth;\n\n\tborderWidth = (mbPtr->indicatorHeight+1)/3;\n\tif (borderWidth < 1) {\n\t    borderWidth = 1;\n\t}\n\t/*y += mbPtr->textHeight / 2;*/\n\tTk_Fill3DRectangle(tkwin, pixmap, border,\n\t\tTk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth\n\t\t+ mbPtr->indicatorHeight,\n\t\t((int) (Tk_Height(tkwin) - mbPtr->indicatorHeight))/2,\n\t\tmbPtr->indicatorWidth - 2*mbPtr->indicatorHeight,\n\t\tmbPtr->indicatorHeight, borderWidth, TK_RELIEF_RAISED);\n    }\n\n    /*\n     * Draw the border and traversal highlight last. This way, if the menu\n     * button's contents overflow onto the border they'll be covered up by the\n     * border.\n     */\n\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->borderWidthObj, &mbPtrBorderWidth);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->highlightWidthObj, &highlightWidth);\n    if (mbPtr->relief != TK_RELIEF_FLAT) {\n\tTk_Draw3DRectangle(tkwin, pixmap, border,\n\t\thighlightWidth, highlightWidth,\n\t\tTk_Width(tkwin) - 2 * highlightWidth,\n\t\tTk_Height(tkwin) - 2 * highlightWidth,\n\t\tmbPtrBorderWidth, mbPtr->relief);\n    }\n    if (highlightWidth > 0) {\n\tif (mbPtr->flags & GOT_FOCUS) {\n\t    gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap);\n\t} else {\n\t    gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap);\n\t}\n\tTk_DrawFocusHighlight(tkwin, gc, highlightWidth, pixmap);\n    }\n\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(mbPtr->display, pixmap, Tk_WindowId(tkwin),\n\t    mbPtr->normalTextGC, 0, 0, (unsigned) Tk_Width(tkwin),\n\t    (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(mbPtr->display, pixmap);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenuButton --\n *\n *\tFree data structures associated with the menubutton control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the default control state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenuButton(\n    TCL_UNUSED(TkMenuButton *))\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeMenuButtonGeometry --\n *\n *\tAfter changes in a menu button's text or bitmap, this function\n *\trecomputes the menu button's geometry and passes this information\n *\talong to the geometry manager for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu button's window may change size.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeMenuButtonGeometry(\n    TkMenuButton *mbPtr)\t/* Widget record for menu button. */\n{\n    int width, height, mm, pixels;\n    int\t avgWidth, txtWidth, txtHeight;\n    int haveImage = 0, haveText = 0;\n    Tk_FontMetrics fm;\n    int borderWidth, highlightWidth, wrapLength;\n    int padX, padY;\n\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->padYObj, &padY);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, mbPtr->tkwin, mbPtr->wrapLengthObj, &wrapLength);\n    mbPtr->inset = highlightWidth + borderWidth;\n\n    width = 0;\n    height = 0;\n    txtWidth = 0;\n    txtHeight = 0;\n    avgWidth = 0;\n\n    if (mbPtr->image != NULL) {\n\tTk_SizeOfImage(mbPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (mbPtr->bitmap != None) {\n\tTk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n\n    if (haveImage == 0 || mbPtr->compound != COMPOUND_NONE) {\n\tTk_FreeTextLayout(mbPtr->textLayout);\n\n\tmbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->textObj ? Tcl_GetString(mbPtr->textObj) : \"\",\n\t\tTCL_INDEX_NONE, wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,\n\t\t&mbPtr->textHeight);\n\ttxtWidth = mbPtr->textWidth;\n\ttxtHeight = mbPtr->textHeight;\n\tavgWidth = Tk_TextWidth(mbPtr->tkfont, \"0\", 1);\n\tTk_GetFontMetrics(mbPtr->tkfont, &fm);\n\thaveText = (txtWidth != 0 && txtHeight != 0);\n    }\n\n    /*\n     * If the menubutton is compound (ie, it shows both an image and text),\n     * the new geometry is a combination of the image and text geometry. We\n     * only honor the compound bit if the menubutton has both text and an\n     * image, because otherwise it is not really a compound menubutton.\n     */\n\n    if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tswitch ((enum compound) mbPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    height += txtHeight + padY;\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    break;\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text.\n\t     */\n\n\t    width += txtWidth + padX;\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    width = (width > txtWidth ? width : txtWidth);\n\t    height = (height > txtHeight ? height : txtHeight);\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\tif (mbPtr->width > 0) {\n\t    width = mbPtr->width;\n\t}\n\tif (mbPtr->height > 0) {\n\t    height = mbPtr->height;\n\t}\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    } else {\n\tif (haveImage) {\n\t    if (mbPtr->width > 0) {\n\t\twidth = mbPtr->width;\n\t    }\n\t    if (mbPtr->height > 0) {\n\t\theight = mbPtr->height;\n\t    }\n\t} else {\n\t    width = txtWidth;\n\t    height = txtHeight;\n\t    if (mbPtr->width > 0) {\n\t\twidth = mbPtr->width * avgWidth;\n\t    }\n\t    if (mbPtr->height > 0) {\n\t\theight = mbPtr->height * fm.linespace;\n\t    }\n\t}\n    }\n\n    if (! haveImage) {\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    }\n\n    if (mbPtr->indicatorOn) {\n\tmm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));\n\tpixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));\n\tmbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm);\n\tmbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm)\n\t\t+ 2 * mbPtr->indicatorHeight;\n\twidth += mbPtr->indicatorWidth;\n    } else {\n\tmbPtr->indicatorHeight = 0;\n\tmbPtr->indicatorWidth = 0;\n    }\n\n    Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2 * mbPtr->inset),\n\t    (int) (height + 2 * mbPtr->inset));\n    Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixPort.h",
    "content": "/*\n * tkUnixPort.h --\n *\n *\tThis file is included by all of the Tk C files.  It contains\n *\tinformation that may be configuration-dependent, such as\n *\t#includes for system include files and a few other things.\n *\n * Copyright © 1991-1993 The Regents of the University of California.\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _UNIXPORT\n#define _UNIXPORT\n\n#define __UNIX__ 1\n\n#include <stdio.h>\n#include <pwd.h>\n#include <assert.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <ctype.h>\n#include <math.h>\n#include <string.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <sys/file.h>\n#ifdef HAVE_SYS_SELECT_H\n#   include <sys/select.h>\n#endif\n#include <sys/stat.h>\n#ifndef _TCL\n#   include <tcl.h>\n#endif\n#ifdef HAVE_SYS_TIME_H\n#\tinclude <sys/time.h>\n#endif\n#include <time.h>\n#include <inttypes.h>\n#include <unistd.h>\n#if defined(__GNUC__) && !defined(__cplusplus)\n#   pragma GCC diagnostic ignored \"-Wc++-compat\"\n#endif\n\n/*\n * The following macro defines the type of the mask arguments to\n * select:\n */\n\n#ifndef NO_FD_SET\n#   define SELECT_MASK fd_set\n#else\n#   ifndef _AIX\n\ttypedef long fd_mask;\n#   endif\n#   if defined(_IBMR2)\n#\tdefine SELECT_MASK void\n#   else\n#\tdefine SELECT_MASK int\n#   endif\n#endif\n\n/*\n * The following macro defines the number of fd_masks in an fd_set:\n */\n\n#ifndef FD_SETSIZE\n#   ifdef OPEN_MAX\n#\tdefine FD_SETSIZE OPEN_MAX\n#   else\n#\tdefine FD_SETSIZE 256\n#   endif\n#endif\n#if !defined(howmany)\n#   define howmany(x, y) (((x)+((y)-1))/(y))\n#endif\n#ifndef NFDBITS\n#   define NFDBITS NBBY*sizeof(fd_mask)\n#endif\n#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS)\n\n/*\n * Define \"NBBY\" (number of bits per byte) if it's not already defined.\n */\n\n#ifndef NBBY\n#   define NBBY 8\n#endif\n\n#include \"tkIntXlibDecls.h\"  /* IWYU pragma: export */\n#define UINT unsigned int\n#define HWND void *\n#define HDC void *\n#define HINSTANCE void *\n#define COLORREF void *\n#define HMENU void *\n#define TkWinDCState void\n#define HPALETTE void *\n#define WNDPROC void *\n#define WPARAM void *\n#define LPARAM void *\n#define LRESULT void *\n\n/*\n * Supply macros for seek offsets, if they're not already provided by\n * an include file.\n */\n\n#ifndef SEEK_SET\n#   define SEEK_SET 0\n#endif\n\n#ifndef SEEK_CUR\n#   define SEEK_CUR 1\n#endif\n\n#ifndef SEEK_END\n#   define SEEK_END 2\n#endif\n\n/*\n * Declarations for various library procedures that may not be declared\n * in any other header file.\n */\n\n\n/*\n * These functions do nothing under Unix, so we just eliminate calls to them.\n */\n\n#define TkpButtonSetDefaults() {}\n#define TkpDestroyButton(butPtr) {}\n#define TkSelUpdateClipboard(a,b) {}\n#ifndef __CYGWIN__\n#define TkSetPixmapColormap(p,c) {}\n#endif\n\n/*\n * This macro stores a representation of the window handle in a string.\n * This should perhaps use the real size of an XID.\n */\n\n#ifndef __CYGWIN__\n#define TkpPrintWindowId(buf,w) \\\n\tsnprintf((buf), TCL_INTEGER_SPACE, \"0x%lx\", (unsigned long) (w))\n#endif\n\n#endif /* _UNIXPORT */\n"
  },
  {
    "path": "unix/tkUnixPrint.c",
    "content": "/*\n * tkUnixPrint.c --\n *\n *      tkUnixPrint.c implements a \"::tk::print::cups\" Tcl command which\n *      interfaces the libcups2 API with the [tk print] command.\n *\n * Copyright © 2024 Emiliano Gavilán.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n#ifdef HAVE_CUPS\n#include <cups/cups.h>\n\ntypedef int (CupsSubCmdOp)(Tcl_Interp *, Tcl_Size, Tcl_Obj *const []);\n\nstatic Tcl_ObjCmdProc2 Cups_Cmd;\nstatic CupsSubCmdOp DefaultPrinterOp;\nstatic CupsSubCmdOp GetPrintersOp;\nstatic CupsSubCmdOp PrintOp;\nstatic Tcl_ArgvGenFuncProc ParseEnumOptions;\nstatic Tcl_ArgvGenFuncProc ParseOptions;\nstatic Tcl_ArgvGenFuncProc ParseMargins;\nstatic Tcl_ArgvGenFuncProc ParseNup;\nstatic cups_dest_t* GetPrinterFromObj(Tcl_Obj *);\n\nstatic cups_dest_t *\nGetPrinterFromObj(Tcl_Obj *nameObj)\n{\n    cups_dest_t *printer;\n    Tcl_Size len;\n    const char *nameStr = Tcl_GetStringFromObj(nameObj, &len);\n    char *p;\n    char *name, *instance = NULL;\n    Tcl_DString ds;\n\n    Tcl_DStringInit(&ds);\n    name = Tcl_DStringAppend(&ds, nameStr, len);\n    p = strchr(name, '/');\n    if (p) {\n\t*p = '\\0';\n\tinstance = p+1;\n    }\n\n    printer = cupsGetNamedDest(CUPS_HTTP_DEFAULT, name, instance);\n    Tcl_DStringFree(&ds);\n\n    return printer;\n}\n\nstatic int\nCups_Cmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    static const struct CupsCmds {\n\tconst char *subcmd;\n\tCupsSubCmdOp *subCmd;\n    } cupsCmds[] = {\n\t{\"defaultprinter\"   , DefaultPrinterOp},\n\t{\"getprinters\"      , GetPrintersOp},\n\t{\"print\"            , PrintOp},\n\t{NULL, NULL}\n    };\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"subcommand ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], cupsCmds,\n\t    sizeof(struct CupsCmds), \"subcommand\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    return cupsCmds[index].subCmd(interp, objc, objv);\n}\n\nstatic int\nDefaultPrinterOp(\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    cups_dest_t *printer;\n    Tcl_Obj *resultObj;\n\n    printer = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);\n    if (printer) {\n\tif (printer->instance) {\n\t    resultObj = Tcl_ObjPrintf(\"%s/%s\", printer->name,\n\t\tprinter->instance);\n\t} else {\n\t    resultObj = Tcl_NewStringObj(printer->name, -1);\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n    }\n\n    cupsFreeDests(1, printer);\n    return TCL_OK;\n}\n\nstatic int\nGetPrintersOp(\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    cups_dest_t *dests;\n    cups_option_t *option;\n    int num_dests, i, j;\n    Tcl_Obj *keyPtr, *optPtr, *resultObj;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 2, objv, NULL);\n\treturn TCL_ERROR;\n    }\n\n    num_dests = cupsGetDests2(CUPS_HTTP_DEFAULT, &dests);\n    resultObj = Tcl_NewObj();\n\n    for (i = 0; i < num_dests; i++) {\n\tif (dests[i].instance)\n\t    keyPtr = Tcl_ObjPrintf(\"%s/%s\", dests[i].name, dests[i].instance);\n\telse\n\t    keyPtr = Tcl_NewStringObj(dests[i].name, -1);\n\n\toption = dests[i].options;\n\toptPtr = Tcl_NewObj();\n\tfor(j = 0; j < dests[i].num_options; j++) {\n\t    Tcl_DictObjPut(NULL, optPtr,\n\t\tTcl_NewStringObj(option[j].name, -1),\n\t\tTcl_NewStringObj(option[j].value, -1));\n\t}\n\n\tTcl_DictObjPut(NULL, resultObj, keyPtr, optPtr);\n    }\n\n    cupsFreeDests(num_dests, dests);\n    Tcl_SetObjResult(interp, resultObj);\n    return TCL_OK;\n}\n\n/* Information needed for parsing */\nstruct CupsOptions {\n    const char *name;\n    const char *cupsName;\n};\n\nstatic const struct CupsOptions colormodeOpts[] = {\n    {\"auto\",       CUPS_PRINT_COLOR_MODE_AUTO},\n    {\"color\",      CUPS_PRINT_COLOR_MODE_COLOR},\n    {\"monochrome\", CUPS_PRINT_COLOR_MODE_MONOCHROME},\n    {NULL, NULL}\n};\n\nstatic const struct CupsOptions formatOpts[] = {\n    {\"auto\",       CUPS_FORMAT_AUTO},\n    {\"pdf\",        CUPS_FORMAT_PDF},\n    {\"postscript\", CUPS_FORMAT_POSTSCRIPT},\n    {\"text\",       CUPS_FORMAT_TEXT},\n    {NULL, NULL}\n};\n\nstatic const struct CupsOptions mediaOpts[] = {\n    {\"a4\",     CUPS_MEDIA_A4},\n    {\"legal\",  CUPS_MEDIA_LEGAL},\n    {\"letter\", CUPS_MEDIA_LETTER},\n    {NULL, NULL}\n};\n\nstatic const struct CupsOptions orientationOpts[] = {\n    {\"portrait\",  CUPS_ORIENTATION_PORTRAIT},\n    {\"landscape\", CUPS_ORIENTATION_LANDSCAPE},\n    {NULL, NULL}\n};\n\nenum {PARSECOLORMODE, PARSEFORMAT, PARSEMEDIA, PARSEORIENTATION};\n\nstatic const struct ParseData {\n    const char *message;\n    const struct CupsOptions *optionTable;\n} parseData[] = {\n    {\"colormode\",   colormodeOpts},\n    {\"format\",      formatOpts},\n    {\"media\",       mediaOpts},\n    {\"orientation\", orientationOpts},\n    {NULL, NULL}\n};\n\nstatic int\nPrintOp(\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    cups_dest_t *printer;\n    cups_dinfo_t *info;\n    int result = TCL_OK;\n    int job_id;\n\n    /* variables for Tcl_ParseArgsObjv */\n    Tcl_Obj *const *parseObjv;\n    Tcl_Size count;\n\n    /* options related vaiables */\n    cups_option_t *options = NULL;\n    int num_options = 0;\n    int copies = 0, pprint = 0;\n    const char *media = NULL, *color = NULL, *orient = NULL, *format = NULL,\n\t*nup = NULL, *title = NULL;\n    Tcl_Obj *marginsObj = NULL, *optionsObj = NULL;\n    double tzoom = 1.0;\n\n    /* Data to print\n     * this is a binary buffer, since it can contain data such as\n     * jpg or compressed pdf which might contain any bytes.\n     * USE [encoding convertto] with a proper encoding when passing\n     * text data to print.\n     */\n    const unsigned char *buffer; Tcl_Size buflen;\n\n    const Tcl_ArgvInfo argTable[] = {\n\t{TCL_ARGV_GENFUNC,  \"-colormode\",   (void *)ParseEnumOptions, &color,\n\t    \"color mode\", (void *)&parseData[PARSECOLORMODE]},\n\t{TCL_ARGV_INT   ,   \"-copies\",                  NULL, &copies,\n\t    \"number of copies\", NULL},\n\t{TCL_ARGV_GENFUNC,  \"-format\",      (void *)ParseEnumOptions, &format,\n\t    \"data format\", (void *)&parseData[PARSEFORMAT]},\n\t{TCL_ARGV_GENFUNC,  \"-margins\",         (void *)ParseMargins, &marginsObj,\n\t    \"media page size\", NULL},\n\t{TCL_ARGV_GENFUNC,  \"-media\",       (void *)ParseEnumOptions, &media,\n\t    \"media page size\", (void *)&parseData[PARSEMEDIA]},\n\t{TCL_ARGV_GENFUNC,  \"-nup\",                 (void *)ParseNup, &nup,\n\t    \"pages per sheet\", NULL},\n\t{TCL_ARGV_GENFUNC,  \"-options\",         (void *)ParseOptions, &optionsObj,\n\t    \"generic options\", NULL},\n\t{TCL_ARGV_GENFUNC,  \"-orientation\", (void *)ParseEnumOptions, &orient,\n\t    \"page orientation\", (void *)&parseData[PARSEORIENTATION]},\n\t{TCL_ARGV_CONSTANT, \"-prettyprint\",        (void *)1, &pprint,\n\t    \"print header\", NULL},\n\t{TCL_ARGV_STRING,   \"-title\",                   NULL, &title,\n\t    \"job title\", NULL},\n\t{TCL_ARGV_FLOAT,    \"-tzoom\",                   NULL, &tzoom,\n\t    \"text zoom\", NULL},\n\tTCL_ARGV_TABLE_END\n    };\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"printer data ?-opt arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    printer = GetPrinterFromObj(objv[2]);\n    if (!printer) {\n\tTcl_SetObjResult(interp,\n\t    Tcl_ObjPrintf(\"unknown printer or class \\\"%s\\\"\",\n\t\tTcl_GetString(objv[2])));\n\treturn TCL_ERROR;\n    }\n\n    /* T_PAO discards the first arg, but we have 4 before the options */\n    parseObjv = objv+3;\n    count = objc-3;\n\n    if (Tcl_ParseArgsObjv(interp, argTable, &count, parseObjv, NULL)!=TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (copies < 0 || copies > 100) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"copies must be an integer\"\n\t    \"between 0 and 100\", -1));\n\tcupsFreeDests(1, printer);\n\treturn TCL_ERROR;\n    }\n    if (tzoom < 0.5 || tzoom > 2.0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"tzoom must be a number\"\n\t    \"between 0.5 and 2.0\", -1));\n\tcupsFreeDests(1, printer);\n\treturn TCL_ERROR;\n    }\n\n/*  Add options */\n    if (copies != 0) {\n\tchar copiesbuf[4];\n\n\tsnprintf(copiesbuf, 4, \"%d\", copies);\n\tnum_options = cupsAddOption(CUPS_COPIES, copiesbuf,\n\t    num_options, &options);\n    }\n    if (color) {\n\tnum_options = cupsAddOption(CUPS_PRINT_COLOR_MODE, color,\n\t    num_options, &options);\n    }\n    if (media) {\n\tnum_options = cupsAddOption(CUPS_MEDIA, media,\n\t    num_options, &options);\n    }\n    if (nup) {\n\tnum_options = cupsAddOption(CUPS_NUMBER_UP, nup,\n\t    num_options, &options);\n    }\n    if (orient) {\n\tnum_options = cupsAddOption(CUPS_ORIENTATION, orient,\n\t    num_options, &options);\n    }\n    if (pprint) {\n\tnum_options = cupsAddOption(\"prettyprint\", \"yes\",\n\t    num_options, &options);\n    }\n    if (marginsObj) {\n\tTcl_Size n;\n\tTcl_Obj **listArr;\n\n\tTcl_ListObjGetElements(NULL, marginsObj, &n, &listArr);\n\tnum_options = cupsAddOption(\"page-top\",    Tcl_GetString(listArr[0]),\n\t    num_options, &options);\n\tnum_options = cupsAddOption(\"page-left\",   Tcl_GetString(listArr[1]),\n\t    num_options, &options);\n\tnum_options = cupsAddOption(\"page-bottom\", Tcl_GetString(listArr[2]),\n\t    num_options, &options);\n\tnum_options = cupsAddOption(\"page-right\",  Tcl_GetString(listArr[3]),\n\t    num_options, &options);\n    }\n    if (optionsObj) {\n\tTcl_DictSearch search;\n\tint done = 0;\n\tTcl_Obj *key, *value;\n\n\tfor (Tcl_DictObjFirst(interp, optionsObj, &search, &key, &value, &done)\n\t    ; !done ; Tcl_DictObjNext(&search, &key, &value, &done))\n\t{\n\t    num_options = cupsAddOption(Tcl_GetString(key),\n\t\tTcl_GetString(value), num_options, &options);\n\t}\n    }\n    /* prettyprint mess with the default values if set, so we force it */\n    if (tzoom != 1.0 || pprint) {\n\tchar cpibuf[TCL_DOUBLE_SPACE + 1];\n\tchar lpibuf[TCL_DOUBLE_SPACE + 1];\n\n\tTcl_PrintDouble(interp, 10.0 / tzoom, cpibuf);\n\tTcl_PrintDouble(interp,  6.0 / tzoom, lpibuf);\n\tnum_options = cupsAddOption(\"cpi\", cpibuf,\n\t    num_options, &options);\n\tnum_options = cupsAddOption(\"lpi\", lpibuf,\n\t    num_options, &options);\n    }\n\n    /* set title and format */\n    if (!title) {\n\ttitle = \"Tk print job\";\n    }\n    if (!format) {\n\tformat = CUPS_FORMAT_AUTO;\n    }\n\n    info = cupsCopyDestInfo(CUPS_HTTP_DEFAULT, printer);\n\n    if (cupsCreateDestJob(CUPS_HTTP_DEFAULT, printer, info, &job_id,\n\t    title, num_options, options) != IPP_STATUS_OK) {\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"Error creating job: \\\"%s\\\"\",\n\t    cupsLastErrorString()));\n\tresult = TCL_ERROR;\n\tgoto cleanup;\n    }\n\n    buffer = Tcl_GetByteArrayFromObj(objv[3], &buflen);\n\n    if (cupsStartDestDocument(CUPS_HTTP_DEFAULT, printer, info, job_id,\n\t\"(stdin)\", format, 0, NULL, 1) != HTTP_STATUS_CONTINUE) {\n\t// Can't start document\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"Error starting document: \\\"%s\\\"\",\n\t    cupsLastErrorString()));\n\tresult = TCL_ERROR;\n\tgoto cleanup;\n    }\n\n    if (cupsWriteRequestData(CUPS_HTTP_DEFAULT,(char *) buffer, buflen) !=\n\t    HTTP_STATUS_CONTINUE) {\n\t// some error ocurred\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"Error writing data: \\\"%s\\\"\",\n\t    cupsLastErrorString()));\n\tresult = TCL_ERROR;\n\tgoto cleanup;\n    }\n\n    if (cupsFinishDestDocument(CUPS_HTTP_DEFAULT, printer, info) ==\n\t    IPP_STATUS_OK) {\n\t// all OK\n\tTcl_SetObjResult(interp, Tcl_NewIntObj(job_id));\n    } else {\n\t// some error ocurred\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"Error finishing document: \\\"%s\\\"\",\n\t    cupsLastErrorString()));\n\tresult = TCL_ERROR;\n\tgoto cleanup;\n    }\n\ncleanup:\n    cupsFreeDestInfo(info);\n    cupsFreeOptions(num_options, options);\n    cupsFreeDests(1, printer);\n    return result;\n}\n\nstatic Tcl_Size\nParseEnumOptions(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    int index;\n    const char **dest = (const char **) dstPtr;\n    struct ParseData *pdata = (struct ParseData *)clientData;\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[0], pdata->optionTable,\n\t    sizeof(struct CupsOptions), pdata->message, 0, &index) != TCL_OK) {\n\treturn -1;\n    }\n\n    *dest = pdata->optionTable[index].cupsName;\n    return 1;\n}\n\nstatic Tcl_Size\nParseOptions(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    Tcl_Obj **objPtr = (Tcl_Obj **) dstPtr;\n    Tcl_Size n;\n\n    /* check for a valid dictionary */\n    if (Tcl_DictObjSize(NULL, objv[0], &n) != TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"options must be a proper\"\n\t    \"dictionary\", -1));\n\treturn -1;\n    }\n\n    *objPtr = objv[0];\n    return 1;\n}\n\nstatic Tcl_Size\nParseMargins(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    Tcl_Obj **objPtr = (Tcl_Obj **) dstPtr;\n    Tcl_Obj **listArr;\n    Tcl_Size n;\n    int i;\n\n    if (Tcl_ListObjGetElements(NULL, objv[0], &n, &listArr) != TCL_OK ||\n\tn != 4 ||\n\tTcl_GetIntFromObj(NULL, listArr[0], &i) != TCL_OK ||\n\tTcl_GetIntFromObj(NULL, listArr[1], &i) != TCL_OK ||\n\tTcl_GetIntFromObj(NULL, listArr[2], &i) != TCL_OK ||\n\tTcl_GetIntFromObj(NULL, listArr[3], &i) != TCL_OK\n    ) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"margins must be a list \"\n\t    \"of four integers: top left bottom right\" , -1));\n\treturn -1;\n    }\n\n    *objPtr = objv[0];\n    return 1;\n}\n\nstatic Tcl_Size\nParseNup(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    const char **nup = (const char **) dstPtr;\n    int n;\n\n    if (Tcl_GetIntFromObj(NULL, objv[0], &n) != TCL_OK ||\n\t(n != 1 && n != 2 && n != 4 && n != 6 && n != 9 && n != 16)\n    ) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"wrong number-up value: \"\n\t    \"should be 1, 2, 4, 6, 9 or 16\", -1));\n\treturn -1;\n    }\n\n    *nup = Tcl_GetString(objv[0]);\n    return 1;\n}\n#endif /*HAVE_CUPS*/\n\nint\n#ifdef HAVE_CUPS\nCups_Init(Tcl_Interp *interp)\n{\n    Tcl_Namespace *ns;\n    ns = Tcl_FindNamespace(interp, \"::tk::print\", NULL, TCL_GLOBAL_ONLY);\n    if (!ns)\n\tns = Tcl_CreateNamespace(interp, \"::tk::print\", NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::cups\", Cups_Cmd, NULL, NULL);\n    Tcl_Export(interp, ns, \"cups\", 0);\n#else\nCups_Init(TCL_UNUSED(Tcl_Interp *))\n{\n    /* Do nothing */\n#endif\n    return TCL_OK;\n}\n"
  },
  {
    "path": "unix/tkUnixRFont.c",
    "content": " /*\n * tkUnixRFont.c --\n *\n *\tAlternate implementation of tkUnixFont.c using Xft.\n *\n * Copyright © 2002-2003 Keith Packard\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n#include \"tkFont.h\"\n#include <X11/Xft/Xft.h>\n\n#define MAX_CACHED_COLORS 16\n\n/*\n * Debugging support...\n */\n\n#define DEBUG_FONTSEL 0\n#define DEBUG(arguments) \\\n    if (DEBUG_FONTSEL) { \\\n\tprintf arguments; fflush(stdout); \\\n    }\n\ntypedef struct {\n    XftFont *ftFont;\n    XftFont *ft0Font;\n    FcPattern *source;\n    FcCharSet *charset;\n    double angle;\n} UnixFtFace;\n\ntypedef struct {\n    XftColor color;\n    int next;\n} UnixFtColorList;\n\ntypedef struct {\n    TkFont font;\t\t/* Stuff used by generic font package. Must be\n\t\t\t\t * first in structure. */\n    UnixFtFace *faces;\n    int nfaces;\n    FcFontSet *fontset;\n    FcPattern *pattern;\n\n    Display *display;\n    int screen;\n    Colormap colormap;\n    Visual *visual;\n    XftDraw *ftDraw;\n    int ncolors;\n    int firstColor;\n    UnixFtColorList colors[MAX_CACHED_COLORS];\n} UnixFtFont;\n\n/*\n * Used to describe the current clipping box. Can't be passed normally because\n * the information isn't retrievable from the GC.\n */\n\ntypedef struct {\n    Region clipRegion;\t\t/* The clipping region, or None. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\nTCL_DECLARE_MUTEX(xftMutex);\n#define LOCK Tcl_MutexLock(&xftMutex)\n#define UNLOCK Tcl_MutexUnlock(&xftMutex)\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpFontPkgInit --\n *\n *\tThis procedure is called when an application is created. It\n *\tinitializes all the structures that are used by the\n *\tplatform-dependant code on a per application basis.\n *\tNote that this is called before TkpInit() !\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic Tcl_Size utf8ToUcs4(const char *source, FcChar32 *c, Tcl_Size numBytes)\n{\n    if (numBytes >= 6) {\n\treturn Tcl_UtfToUniChar(source, (int *)c);\n    }\n    return FcUtf8ToUcs4((const FcChar8 *)source, c, numBytes);\n}\n\nvoid\nTkpFontPkgInit(\n    TCL_UNUSED(TkMainInfo *))\t/* The application being created. */\n{\n}\n\f\nstatic XftFont *\nGetFont(\n    UnixFtFont *fontPtr,\n    FcChar32 ucs4,\n    double angle)\n{\n    int i;\n\n    if (ucs4) {\n\tfor (i = 0; i < fontPtr->nfaces; i++) {\n\t    FcCharSet *charset = fontPtr->faces[i].charset;\n\n\t    if (charset && FcCharSetHasChar(charset, ucs4)) {\n\t\tbreak;\n\t    }\n\t}\n\tif (i == fontPtr->nfaces) {\n\t    i = 0;\n\t}\n    } else {\n\ti = 0;\n    }\n    if ((angle == 0.0 && !fontPtr->faces[i].ft0Font) || (angle != 0.0 &&\n\t    (!fontPtr->faces[i].ftFont || fontPtr->faces[i].angle != angle))){\n\tFcPattern *pat = FcFontRenderPrepare(0, fontPtr->pattern,\n\t\tfontPtr->faces[i].source);\n\tdouble s = sin(angle*PI/180.0), c = cos(angle*PI/180.0);\n\tFcMatrix mat;\n\tXftFont *ftFont;\n\n\t/*\n\t * Initialize the matrix manually so this can compile with HP-UX cc\n\t * (which does not allow non-constant structure initializers). [Bug\n\t * 2978410]\n\t */\n\n\tmat.xx = mat.yy = c;\n\tmat.xy = -(mat.yx = s);\n\n\tif (angle != 0.0) {\n\t    FcPatternAddMatrix(pat, FC_MATRIX, &mat);\n\t}\n\tLOCK;\n\tftFont = XftFontOpenPattern(fontPtr->display, pat);\n\tUNLOCK;\n\tif (!ftFont) {\n\t    /*\n\t     * The previous call to XftFontOpenPattern() should not fail, but\n\t     * sometimes does anyway. Usual cause appears to be a\n\t     * misconfigured fontconfig installation; see [Bug 1090382]. Try a\n\t     * fallback:\n\t     */\n\n\t    LOCK;\n\t    ftFont = XftFontOpen(fontPtr->display, fontPtr->screen,\n\t\t    FC_FAMILY, FcTypeString, \"sans\",\n\t\t    FC_SIZE, FcTypeDouble, 12.0,\n\t\t    FC_MATRIX, FcTypeMatrix, &mat,\n\t\t    NULL);\n\t    UNLOCK;\n\t}\n\tif (!ftFont) {\n\t    /*\n\t     * The previous call should definitely not fail. Impossible to\n\t     * proceed at this point.\n\t     */\n\n\t    Tcl_Panic(\"Cannot find a usable font\");\n\t}\n\n\tif (angle == 0.0) {\n\t    fontPtr->faces[i].ft0Font = ftFont;\n\t} else {\n\t    if (fontPtr->faces[i].ftFont) {\n\t\tLOCK;\n\t\tXftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);\n\t\tUNLOCK;\n\t    }\n\t    fontPtr->faces[i].ftFont = ftFont;\n\t    fontPtr->faces[i].angle = angle;\n\t}\n    }\n    return (angle==0.0? fontPtr->faces[i].ft0Font : fontPtr->faces[i].ftFont);\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetTkFontAttributes --\n *\tFill in TkFontAttributes from an XftFont.\n */\n\nstatic void\nGetTkFontAttributes(\n    Tk_Window tkwin,\n    XftFont *ftFont,\n    TkFontAttributes *faPtr)\n{\n    const char *family = \"Unknown\";\n    const char *const *familyPtr = &family;\n    double ptSize, dblPxSize, size;\n    int intPxSize, weight, slant;\n\n    (void) XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0, familyPtr);\n    if (XftPatternGetDouble(ftFont->pattern, XFT_SIZE, 0,\n\t    &ptSize) == XftResultMatch) {\n\tsize = ptSize;\n    } else if (XftPatternGetDouble(ftFont->pattern, XFT_PIXEL_SIZE, 0,\n\t    &dblPxSize) == XftResultMatch) {\n\tsize = -dblPxSize;\n    } else if (XftPatternGetInteger(ftFont->pattern, XFT_PIXEL_SIZE, 0,\n\t    &intPxSize) == XftResultMatch) {\n\tsize = (double)-intPxSize;\n    } else {\n\tsize = 12.0;\n    }\n    if (XftPatternGetInteger(ftFont->pattern, XFT_WEIGHT, 0,\n\t    &weight) != XftResultMatch) {\n\tweight = XFT_WEIGHT_MEDIUM;\n    }\n    if (XftPatternGetInteger(ftFont->pattern, XFT_SLANT, 0,\n\t    &slant) != XftResultMatch) {\n\tslant = XFT_SLANT_ROMAN;\n    }\n\n    DEBUG((\"GetTkFontAttributes: family %s size %ld weight %d slant %d\\n\",\n\t    family, lround(size), weight, slant));\n\n    faPtr->family = Tk_GetUid(family);\n    /*\n     * Make sure that faPtr->size will be > 0 even\n     * in the very unprobable case that size < 0\n     */\n    faPtr->size = TkFontGetPoints(tkwin, size);\n    faPtr->weight = (weight > XFT_WEIGHT_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;\n    faPtr->slant = (slant > XFT_SLANT_ROMAN) ? TK_FS_ITALIC : TK_FS_ROMAN;\n    faPtr->underline = 0;\n    faPtr->overstrike = 0;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * GetTkFontMetrics --\n *\tFill in TkFontMetrics from an XftFont.\n */\n\nstatic void\nGetTkFontMetrics(\n    XftFont *ftFont,\n    TkFontMetrics *fmPtr)\n{\n    int spacing;\n\n    if (XftPatternGetInteger(ftFont->pattern, XFT_SPACING, 0,\n\t    &spacing) != XftResultMatch) {\n\tspacing = XFT_PROPORTIONAL;\n    }\n\n    fmPtr->ascent = ftFont->ascent;\n    fmPtr->descent = ftFont->descent;\n    fmPtr->maxWidth = ftFont->max_advance_width;\n    fmPtr->fixed = spacing != XFT_PROPORTIONAL;\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * InitFont --\n *\n *\tInitializes the fields of a UnixFtFont structure. If fontPtr is NULL,\n *\talso allocates a new UnixFtFont.\n *\n * Results:\n *\tOn error, frees fontPtr and returns NULL, otherwise returns fontPtr.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nFinishedWithFont(\n    UnixFtFont *fontPtr);\n\nstatic int\nInitFontErrorProc(\n    void *clientData,\n    TCL_UNUSED(XErrorEvent *))\n{\n    int *errorFlagPtr = (int *)clientData;\n\n    if (errorFlagPtr != NULL) {\n\t*errorFlagPtr = 1;\n    }\n    return 0;\n}\n\nstatic UnixFtFont *\nInitFont(\n    Tk_Window tkwin,\n    FcPattern *pattern,\n    UnixFtFont *fontPtr)\n{\n    FcFontSet *set;\n    FcCharSet *charset;\n    FcResult result;\n    XftFont *ftFont;\n    int i, iWidth, errorFlag;\n    Tk_ErrorHandler handler;\n\n    if (!fontPtr) {\n\tfontPtr = (UnixFtFont *)Tcl_Alloc(sizeof(UnixFtFont));\n    }\n\n    FcConfigSubstitute(0, pattern, FcMatchPattern);\n    XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern);\n\n    /*\n     * Generate the list of fonts\n     */\n\n    set = FcFontSort(0, pattern, FcTrue, NULL, &result);\n    if (!set || set->nfont == 0) {\n\tTcl_Free(fontPtr);\n\treturn NULL;\n    }\n\n    fontPtr->fontset = set;\n    fontPtr->pattern = pattern;\n    fontPtr->faces = (UnixFtFace *)Tcl_Alloc(set->nfont * sizeof(UnixFtFace));\n    fontPtr->nfaces = set->nfont;\n\n    /*\n     * Fill in information about each returned font\n     */\n\n    for (i = 0; i < set->nfont; i++) {\n\tfontPtr->faces[i].ftFont = 0;\n\tfontPtr->faces[i].ft0Font = 0;\n\tfontPtr->faces[i].source = set->fonts[i];\n\tif (FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0,\n\t\t&charset) == FcResultMatch) {\n\t    fontPtr->faces[i].charset = FcCharSetCopy(charset);\n\t} else {\n\t    fontPtr->faces[i].charset = 0;\n\t}\n\tfontPtr->faces[i].angle = 0.0;\n    }\n\n    fontPtr->display = Tk_Display(tkwin);\n    fontPtr->screen = Tk_ScreenNumber(tkwin);\n    fontPtr->colormap = Tk_Colormap(tkwin);\n    fontPtr->visual = Tk_Visual(tkwin);\n    fontPtr->ftDraw = 0;\n    fontPtr->ncolors = 0;\n    fontPtr->firstColor = -1;\n\n    /*\n     * Fill in platform-specific fields of TkFont.\n     */\n\n    errorFlag = 0;\n    handler = Tk_CreateErrorHandler(Tk_Display(tkwin),\n\t\t    -1, -1, -1, InitFontErrorProc, (void *)&errorFlag);\n    ftFont = GetFont(fontPtr, 0, 0.0);\n    if ((ftFont == NULL) || errorFlag) {\n\tTk_DeleteErrorHandler(handler);\n\tFinishedWithFont(fontPtr);\n\tTcl_Free(fontPtr);\n\treturn NULL;\n    }\n    fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), \"fixed\");\n    GetTkFontAttributes(tkwin, ftFont, &fontPtr->font.fa);\n    GetTkFontMetrics(ftFont, &fontPtr->font.fm);\n    Tk_DeleteErrorHandler(handler);\n    if (errorFlag) {\n\tFinishedWithFont(fontPtr);\n\tTcl_Free(fontPtr);\n\treturn NULL;\n    }\n\n    /*\n     * Fontconfig can't report any information about the position or thickness\n     * of underlines or overstrikes. Thus, we use some defaults that are\n     * hacked around from backup defaults in tkUnixFont.c, which are in turn\n     * based on recommendations in the X manual. The comments from that file\n     * leading to these computations were:\n     *\n     *\t    If the XA_UNDERLINE_POSITION property does not exist, the X manual\n     *\t    recommends using half the descent.\n     *\n     *\t    If the XA_UNDERLINE_THICKNESS property does not exist, the X\n     *\t    manual recommends using the width of the stem on a capital letter.\n     *\t    I don't know of a way to get the stem width of a letter, so guess\n     *\t    and use 1/3 the width of a capital I.\n     *\n     * Note that nothing corresponding to *either* property is reported by\n     * Fontconfig at all. [Bug 1961455]\n     */\n\n    {\n\tTkFont *fPtr = &fontPtr->font;\n\n\tfPtr->underlinePos = fPtr->fm.descent / 2;\n\thandler = Tk_CreateErrorHandler(Tk_Display(tkwin),\n\t\t\t-1, -1, -1, InitFontErrorProc, (void *)&errorFlag);\n\terrorFlag = 0;\n\tTk_MeasureChars((Tk_Font) fPtr, \"I\", 1, -1, 0, &iWidth);\n\tTk_DeleteErrorHandler(handler);\n\tif (errorFlag) {\n\t    FinishedWithFont(fontPtr);\n\t    Tcl_Free(fontPtr);\n\t    return NULL;\n\t}\n\tfPtr->underlineHeight = iWidth / 3;\n\tif (fPtr->underlineHeight == 0) {\n\t    fPtr->underlineHeight = 1;\n\t}\n\tif (fPtr->underlineHeight + fPtr->underlinePos > fPtr->fm.descent) {\n\t    fPtr->underlineHeight = fPtr->fm.descent - fPtr->underlinePos;\n\t    if (fPtr->underlineHeight == 0) {\n\t\tfPtr->underlinePos--;\n\t\tfPtr->underlineHeight = 1;\n\t    }\n\t}\n    }\n\n    return fontPtr;\n}\n\f\nstatic void\nFinishedWithFont(\n    UnixFtFont *fontPtr)\n{\n    Display *display = fontPtr->display;\n    int i;\n    Tk_ErrorHandler handler =\n\t    Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n    for (i = 0; i < fontPtr->nfaces; i++) {\n\tif (fontPtr->faces[i].ftFont) {\n\t    LOCK;\n\t    XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);\n\t    UNLOCK;\n\t}\n\tif (fontPtr->faces[i].ft0Font) {\n\t    LOCK;\n\t    XftFontClose(fontPtr->display, fontPtr->faces[i].ft0Font);\n\t    UNLOCK;\n\t}\n\tif (fontPtr->faces[i].charset) {\n\t    FcCharSetDestroy(fontPtr->faces[i].charset);\n\t}\n    }\n    if (fontPtr->faces) {\n\tTcl_Free(fontPtr->faces);\n    }\n    if (fontPtr->pattern) {\n\tFcPatternDestroy(fontPtr->pattern);\n    }\n    if (fontPtr->ftDraw) {\n\tXftDrawDestroy(fontPtr->ftDraw);\n    }\n    if (fontPtr->font.fid) {\n\tXUnloadFont(fontPtr->display, fontPtr->font.fid);\n    }\n    if (fontPtr->fontset) {\n\tFcFontSetDestroy(fontPtr->fontset);\n    }\n    Tk_DeleteErrorHandler(handler);\n}\n\f\nTkFont *\nTkpGetNativeFont(\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const char *name)\t\t/* Platform-specific font name. */\n{\n    UnixFtFont *fontPtr;\n    FcPattern *pattern;\n\n    DEBUG((\"TkpGetNativeFont: %s\\n\", name));\n\n    pattern = XftXlfdParse(name, FcFalse, FcFalse);\n    if (!pattern) {\n\treturn NULL;\n    }\n\n    /*\n     * Should also try: pattern = FcNameParse(name); but generic/tkFont.c\n     * expects TkpGetNativeFont() to only work on XLFD names under Unix.\n     */\n\n    fontPtr = InitFont(tkwin, pattern, NULL);\n    if (!fontPtr) {\n\tFcPatternDestroy(pattern);\n\treturn NULL;\n    }\n    return &fontPtr->font;\n}\n\f\nTkFont *\nTkpGetFontFromAttributes(\n    TkFont *tkFontPtr,\t\t/* If non-NULL, store the information in this\n\t\t\t\t * existing TkFont structure, rather than\n\t\t\t\t * allocating a new structure to hold the\n\t\t\t\t * font; the existing contents of the font\n\t\t\t\t * will be released. If NULL, a new TkFont\n\t\t\t\t * structure is allocated. */\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const TkFontAttributes *faPtr)\n\t\t\t\t/* Set of attributes to match. */\n{\n    XftPattern *pattern;\n    int weight, slant;\n    UnixFtFont *fontPtr;\n\n    DEBUG((\"TkpGetFontFromAttributes: %s %ld %d %d\\n\", faPtr->family,\n\t    lround(faPtr->size), faPtr->weight, faPtr->slant));\n\n    pattern = XftPatternCreate();\n    if (faPtr->family) {\n\tXftPatternAddString(pattern, XFT_FAMILY, faPtr->family);\n    }\n    if (faPtr->size > 0.0) {\n\tXftPatternAddDouble(pattern, XFT_SIZE, faPtr->size);\n    } else if (faPtr->size < 0.0) {\n\tXftPatternAddDouble(pattern, XFT_SIZE, TkFontGetPoints(tkwin, faPtr->size));\n    } else {\n\tXftPatternAddDouble(pattern, XFT_SIZE, 12.0);\n    }\n    switch (faPtr->weight) {\n    case TK_FW_NORMAL:\n    default:\n\tweight = XFT_WEIGHT_MEDIUM;\n\tbreak;\n    case TK_FW_BOLD:\n\tweight = XFT_WEIGHT_BOLD;\n\tbreak;\n    }\n    XftPatternAddInteger(pattern, XFT_WEIGHT, weight);\n    switch (faPtr->slant) {\n    case TK_FS_ROMAN:\n    default:\n\tslant = XFT_SLANT_ROMAN;\n\tbreak;\n    case TK_FS_ITALIC:\n\tslant = XFT_SLANT_ITALIC;\n\tbreak;\n    case TK_FS_OBLIQUE:\n\tslant = XFT_SLANT_OBLIQUE;\n\tbreak;\n    }\n    XftPatternAddInteger(pattern, XFT_SLANT, slant);\n\n    fontPtr = (UnixFtFont *) tkFontPtr;\n    if (fontPtr != NULL) {\n\tFinishedWithFont(fontPtr);\n    }\n    fontPtr = InitFont(tkwin, pattern, fontPtr);\n\n    /*\n     * Hack to work around issues with weird issues with Xft/Xrender\n     * connection. For details, see comp.lang.tcl thread starting from\n     * <adcc99ed-c73e-4efc-bb5d-e57a57a051e8@l35g2000pra.googlegroups.com>\n     */\n\n    if (!fontPtr) {\n\tXftPatternAddBool(pattern, XFT_RENDER, FcFalse);\n\tfontPtr = InitFont(tkwin, pattern, fontPtr);\n    }\n\n    if (!fontPtr) {\n\tFcPatternDestroy(pattern);\n\treturn NULL;\n    }\n\n    fontPtr->font.fa.underline = faPtr->underline;\n    fontPtr->font.fa.overstrike = faPtr->overstrike;\n    return &fontPtr->font;\n}\n\f\nvoid\nTkpDeleteFont(\n    TkFont *tkFontPtr)\t\t/* Token of font to be deleted. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *) tkFontPtr;\n\n    FinishedWithFont(fontPtr);\n    /* XXX tkUnixFont.c doesn't free tkFontPtr... */\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFamilies --\n *\n *\tReturn information about the font families that are available on the\n *\tdisplay of the given window.\n *\n * Results:\n *\tModifies interp's result object to hold a list of all the available\n *\tfont families.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontFamilies(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Window tkwin)\t\t/* For display to query. */\n{\n    Tcl_Obj *resultPtr;\n    XftFontSet *list;\n    int i;\n\n    resultPtr = Tcl_NewListObj(0, NULL);\n\n    list = XftListFonts(Tk_Display(tkwin), Tk_ScreenNumber(tkwin),\n\t\t(char *) 0,\t\t/* pattern elements */\n\t\tXFT_FAMILY, (char*) 0);\t/* fields */\n    for (i = 0; i < list->nfont; i++) {\n\tchar *family, **familyPtr = &family;\n\n\tif (XftPatternGetString(list->fonts[i], XFT_FAMILY, 0, familyPtr)\n\t\t== XftResultMatch) {\n\t    Tcl_Obj *strPtr = Tcl_NewStringObj(family, TCL_INDEX_NONE);\n\n\t    Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);\n\t}\n    }\n    XftFontSetDestroy(list);\n\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkpGetSubFonts --\n *\n *\tCalled by [testfont subfonts] in the Tk testing package.\n *\n * Results:\n *\tSets interp's result to a list of the faces used by tkfont\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpGetSubFonts(\n    Tcl_Interp *interp,\n    Tk_Font tkfont)\n{\n    Tcl_Obj *objv[3], *listPtr, *resultPtr;\n    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;\n    FcPattern *pattern;\n    const char *family = \"Unknown\";\n    const char *const *familyPtr = &family;\n    const char *foundry = \"Unknown\";\n    const char *const *foundryPtr = &foundry;\n    const char *encoding = \"Unknown\";\n    const char *const *encodingPtr = &encoding;\n    int i;\n\n    resultPtr = Tcl_NewListObj(0, NULL);\n\n    for (i = 0; i < fontPtr->nfaces ; ++i) {\n\tpattern = FcFontRenderPrepare(0, fontPtr->pattern,\n\t\tfontPtr->faces[i].source);\n\n\tXftPatternGetString(pattern, XFT_FAMILY, 0, familyPtr);\n\tXftPatternGetString(pattern, XFT_FOUNDRY, 0, foundryPtr);\n\tXftPatternGetString(pattern, XFT_ENCODING, 0, encodingPtr);\n\tobjv[0] = Tcl_NewStringObj(family, TCL_INDEX_NONE);\n\tobjv[1] = Tcl_NewStringObj(foundry, TCL_INDEX_NONE);\n\tobjv[2] = Tcl_NewStringObj(encoding, TCL_INDEX_NONE);\n\tlistPtr = Tcl_NewListObj(3, objv);\n\tTcl_ListObjAppendElement(NULL, resultPtr, listPtr);\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetFontAttrsForChar --\n *\n *\tRetrieve the font attributes of the actual font used to render a given\n *\tcharacter.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontAttrsForChar(\n    Tk_Window tkwin,\t\t/* Window on the font's display */\n    Tk_Font tkfont,\t\t/* Font to query */\n    int c,\t\t/* Character of interest */\n    TkFontAttributes *faPtr)\t/* Output: Font attributes */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;\n\t\t\t\t/* Structure describing the logical font */\n    FcChar32 ucs4 = (FcChar32) c;\n\t\t\t\t/* UCS-4 character to map */\n    XftFont *ftFont = GetFont(fontPtr, ucs4, 0.0);\n\t\t\t\t/* Actual font used to render the character */\n\n    GetTkFontAttributes(tkwin, ftFont, faPtr);\n    faPtr->underline = fontPtr->font.fa.underline;\n    faPtr->overstrike = fontPtr->font.fa.overstrike;\n}\n\f\nint\nTk_MeasureChars(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    Tcl_Size numBytes,\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length in pixels; don't\n\t\t\t\t * consider any character that would cross\n\t\t\t\t * this x-position. If < 0, then line length\n\t\t\t\t * is unbounded and the flags argument is\n\t\t\t\t * ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fit on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character even if\n\t\t\t\t * no characters fit. */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;\n    XftFont *ftFont;\n    FcChar32 c;\n    XGlyphInfo extents;\n    Tcl_Size clen;\n    int curX, newX, curByte, newByte, sawNonSpace;\n    int termByte = 0, termX = 0, errorFlag = 0;\n    Tk_ErrorHandler handler;\n#if DEBUG_FONTSEL\n    char string[256];\n    int len = 0;\n#endif /* DEBUG_FONTSEL */\n\n    handler = Tk_CreateErrorHandler(fontPtr->display,\n\t    -1, -1, -1, InitFontErrorProc, &errorFlag);\n    curX = 0;\n    curByte = 0;\n    sawNonSpace = 0;\n    while (numBytes > 0) {\n\tint unichar;\n\n\tclen = Tcl_UtfToUniChar(source, &unichar);\n\tc = (FcChar32) unichar;\n\n\tif (clen <= 0) {\n\t    /*\n\t     * This can't happen (but see #1185640)\n\t     */\n\n\t    goto measureCharsEnd;\n\t}\n\n\tsource += clen;\n\tnumBytes -= clen;\n\tif (c < 256 && isspace(c)) {\t\t/* I18N: ??? */\n\t    if (sawNonSpace) {\n\t\ttermByte = curByte;\n\t\ttermX = curX;\n\t\tsawNonSpace = 0;\n\t    }\n\t} else {\n\t    sawNonSpace = 1;\n\t}\n\n#if DEBUG_FONTSEL\n\tstring[len++] = (char) c;\n#endif /* DEBUG_FONTSEL */\n\tftFont = GetFont(fontPtr, c, 0.0);\n\n\tif (!errorFlag) {\n\t    LOCK;\n\t    XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);\n\t    UNLOCK;\n\t}\n\tif (errorFlag) {\n\t    extents.xOff = 0;\n\t    errorFlag = 0;\n\t}\n\n\tnewX = curX + extents.xOff;\n\tnewByte = curByte + clen;\n\tif (maxLength >= 0 && newX > maxLength) {\n\t    if (flags & TK_PARTIAL_OK ||\n\t\t    (flags & TK_AT_LEAST_ONE && curByte == 0)) {\n\t\tcurX = newX;\n\t\tcurByte = newByte;\n\t    } else if (flags & TK_WHOLE_WORDS) {\n\t\tif ((flags & TK_AT_LEAST_ONE) && (termX == 0)) {\n\t\t    /*\n\t\t     * No space was seen before reaching the right\n\t\t     * of the allotted maxLength space, i.e. no word\n\t\t     * boundary. Return the string that fills the\n\t\t     * allotted space, without overfill.\n\t\t     * curX and curByte are already the right ones:\n\t\t     */\n\t\t} else {\n\t\t    curX = termX;\n\t\t    curByte = termByte;\n\t\t}\n\t    }\n\t    break;\n\t}\n\n\tcurX = newX;\n\tcurByte = newByte;\n    }\nmeasureCharsEnd:\n    Tk_DeleteErrorHandler(handler);\n#if DEBUG_FONTSEL\n    string[len] = '\\0';\n    DEBUG((\"MeasureChars: %s length %d bytes %d\\n\", string, curX, curByte));\n#endif /* DEBUG_FONTSEL */\n    *lengthPtr = curX;\n    return curByte;\n}\n\f\nint\nTk_MeasureCharsInContext(\n    Tk_Font tkfont,\n    const char *source,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Size rangeStart,\n    Tcl_Size rangeLength,\n    int maxLength,\n    int flags,\n    int *lengthPtr)\n{\n    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,\n\t    maxLength, flags, lengthPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * LookUpColor --\n *\n *\tConvert a pixel value to an XftColor.  This can be slow due to the\n * need to call XQueryColor, which involves a server round-trip.  To\n * avoid that, a least-recently-used cache of up to MAX_CACHED_COLORS\n * is kept, in the form of a linked list.  The returned color is moved\n * to the front of the list, so repeatedly asking for the same one\n * should be fast.\n *\n * Results:\n *      A pointer to the XftColor structure for the requested color is\n * returned.\n *\n * Side effects:\n *      The converted color is stored in a cache in the UnixFtFont structure.  The cache\n * can hold at most MAX_CACHED_COLORS colors.  If no more slots are available, the least\n * recently used color is replaced with the new one.\n *----------------------------------------------------------------------\n */\n\nstatic XftColor *\nLookUpColor(Display *display,      /* Display to lookup colors on */\n\t    UnixFtFont *fontPtr,   /* Font to search for cached colors */\n\t    unsigned long pixel)   /* Pixel value to translate to XftColor */\n{\n    int i, last = -1, last2 = -1;\n    XColor xcolor;\n\n    for (i = fontPtr->firstColor;\n\t i >= 0; last2 = last, last = i, i = fontPtr->colors[i].next) {\n\n\tif (pixel == fontPtr->colors[i].color.pixel) {\n\t    /*\n\t     * Color found in cache.  Move it to the front of the list and return it.\n\t     */\n\t    if (last >= 0) {\n\t\tfontPtr->colors[last].next = fontPtr->colors[i].next;\n\t\tfontPtr->colors[i].next = fontPtr->firstColor;\n\t\tfontPtr->firstColor = i;\n\t    }\n\n\t    return &fontPtr->colors[i].color;\n\t}\n    }\n\n    /*\n     * Color wasn't found, so it needs to be added to the cache.\n     * If a spare slot is available, it can be put there.  If not, last\n     * will now point to the least recently used color, so replace that one.\n     */\n\n    if (fontPtr->ncolors < MAX_CACHED_COLORS) {\n\tlast2 = -1;\n\tlast = fontPtr->ncolors++;\n    }\n\n    /*\n     * Translate the pixel value to a color.  Needs a server round-trip.\n     */\n    xcolor.pixel = pixel;\n    XQueryColor(display, fontPtr->colormap, &xcolor);\n\n    fontPtr->colors[last].color.color.red = xcolor.red;\n    fontPtr->colors[last].color.color.green = xcolor.green;\n    fontPtr->colors[last].color.color.blue = xcolor.blue;\n    fontPtr->colors[last].color.color.alpha = 0xFFFF;\n    fontPtr->colors[last].color.pixel = pixel;\n\n    /*\n     * Put at the front of the list.\n     */\n    if (last2 >= 0) {\n\tfontPtr->colors[last2].next = fontPtr->colors[last].next;\n    }\n    fontPtr->colors[last].next = fontPtr->firstColor;\n    fontPtr->firstColor = last;\n\n    return &fontPtr->colors[last].color;\n}\n\f\n#define NUM_SPEC    1024\n\nvoid\nTk_DrawChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int x, int y)\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n{\n    const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */\n    const int minCoord = -maxCoord-1;\n    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;\n    XGCValues values;\n    XftColor *xftcolor;\n    int clen, nspec, xStart = x;\n    XftGlyphFontSpec specs[NUM_SPEC];\n    XGlyphInfo metrics;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (fontPtr->ftDraw == 0) {\n\tDEBUG((\"Switch to drawable 0x%lx\\n\", drawable));\n\tfontPtr->ftDraw = XftDrawCreate(display, drawable,\n\t\tfontPtr->visual, fontPtr->colormap);\n} else {\n\tTk_ErrorHandler handler =\n\t\tTk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n\tXftDrawChange(fontPtr->ftDraw, drawable);\n\tTk_DeleteErrorHandler(handler);\n    }\n    XGetGCValues(display, gc, GCForeground, &values);\n    xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (tsdPtr->clipRegion != NULL) {\n\tXftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);\n    }\n    nspec = 0;\n    while (numBytes > 0) {\n\tXftFont *ftFont;\n\tFcChar32 c;\n\n\tclen = utf8ToUcs4(source, &c, numBytes);\n\tif (clen <= 0) {\n\t    /*\n\t     * This should not happen, but it can.\n\t     */\n\n\t    goto doUnderlineStrikeout;\n\t}\n\tsource += clen;\n\tnumBytes -= clen;\n\n\tftFont = GetFont(fontPtr, c, 0.0);\n\tif (ftFont) {\n\t    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);\n\t    LOCK;\n\t    XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,\n\t\t    &metrics);\n\t    UNLOCK;\n\n\t    /*\n\t     * Draw glyph only when it fits entirely into 16 bit coords.\n\t     */\n\n\t    if (x >= minCoord && y >= minCoord &&\n\t\tx <= maxCoord - metrics.width &&\n\t\ty <= maxCoord - metrics.height) {\n\t\tspecs[nspec].font = ftFont;\n\t\tspecs[nspec].x = x;\n\t\tspecs[nspec].y = y;\n\t\tif (++nspec == NUM_SPEC) {\n\t\t    LOCK;\n\t\t    XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,\n\t\t\t    specs, nspec);\n\t\t    UNLOCK;\n\t\t    nspec = 0;\n\t\t}\n\t    }\n\t    x += metrics.xOff;\n\t    y += metrics.yOff;\n\t}\n    }\n    if (nspec) {\n\tLOCK;\n\tXftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);\n\tUNLOCK;\n    }\n\n  doUnderlineStrikeout:\n    if (tsdPtr->clipRegion != NULL) {\n\tXftDrawSetClip(fontPtr->ftDraw, NULL);\n    }\n    if (fontPtr->font.fa.underline != 0) {\n\tXFillRectangle(display, drawable, gc, xStart,\n\t\ty + fontPtr->font.underlinePos, (unsigned) (x - xStart),\n\t\t(unsigned) fontPtr->font.underlineHeight);\n    }\n    if (fontPtr->font.fa.overstrike != 0) {\n\ty -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10;\n\tXFillRectangle(display, drawable, gc, xStart, y,\n\t\t(unsigned) (x - xStart),\n\t\t(unsigned) fontPtr->font.underlineHeight);\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * TkDrawAngledChars --\n *\n *\tDraw some characters at an angle. This would be simple code, except\n *\tXft has bugs with cumulative errors in character positioning which are\n *\tcaused by trying to perform all calculations internally with integers.\n *\tSo we have to do the work ourselves with floating-point math.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTarget drawable is updated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkDrawAngledChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    double x, double y,\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */\n    const int minCoord = -maxCoord-1;\n    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;\n    XGCValues values;\n    XftColor *xftcolor;\n    int xStart = x, yStart = y;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n#ifdef XFT_HAS_FIXED_ROTATED_PLACEMENT\n    int clen, nglyph;\n    FT_UInt glyphs[NUM_SPEC];\n    XGlyphInfo metrics;\n    XftFont *currentFtFont;\n    int originX, originY;\n\n    if (fontPtr->ftDraw == 0) {\n\tDEBUG((\"Switch to drawable 0x%lx\\n\", drawable));\n\tfontPtr->ftDraw = XftDrawCreate(display, drawable,\n\t\tfontPtr->visual, fontPtr->colormap);\n    } else {\n\tTk_ErrorHandler handler =\n\t\tTk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n\tXftDrawChange(fontPtr->ftDraw, drawable);\n\tTk_DeleteErrorHandler(handler);\n    }\n\n    XGetGCValues(display, gc, GCForeground, &values);\n    xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (tsdPtr->clipRegion != None) {\n\tXftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);\n    }\n\n    nglyph = 0;\n    currentFtFont = NULL;\n    originX = originY = 0;\n\n    while (numBytes > 0) {\n\tXftFont *ftFont;\n\tFcChar32 c;\n\n\tclen = utf8ToUcs4(source, &c, numBytes);\n\tif (clen <= 0) {\n\t    /*\n\t     * This should not happen, but it can.\n\t     */\n\n\t    goto doUnderlineStrikeout;\n\t}\n\tsource += clen;\n\tnumBytes -= clen;\n\n\tftFont = GetFont(fontPtr, c, angle);\n\tif (!ftFont) {\n\t    continue;\n\t}\n\n\tif (ftFont != currentFtFont || nglyph == NUM_SPEC) {\n\t    if (nglyph) {\n\t\t/*\n\t\t * We pass multiple glyphs at once to enable the code to\n\t\t * perform better rendering of sub-pixel inter-glyph spacing.\n\t\t * If only the current Xft implementation could make use of\n\t\t * this information... but we'll be ready when it does!\n\t\t */\n\n\t\tLOCK;\n\t\tXftGlyphExtents(fontPtr->display, currentFtFont, glyphs,\n\t\t\tnglyph, &metrics);\n\t\tUNLOCK;\n\n\t\t/*\n\t\t * Draw glyph only when it fits entirely into 16 bit coords.\n\t\t */\n\n\t\tif (x >= minCoord && y >= minCoord &&\n\t\t    x <= maxCoord - metrics.width &&\n\t\t    y <= maxCoord - metrics.height) {\n\n\t\t    /*\n\t\t     * NOTE:\n\t\t     * The whole algorithm has a design problem, the choice of\n\t\t     * NUM_SPEC is arbitrary, and so the inter-glyph spacing could\n\t\t     * look arbitrary. This algorithm has to draw the whole string\n\t\t     * at once (or whole blocks with same font), this requires a\n\t\t     * dynamic 'glyphs' array. In case of overflow the array has to\n\t\t     * be divided until the maximal string will fit. (GC)\n\t\t     * Given the resolution of current displays though, this should\n\t\t     * not be a huge issue since NUM_SPEC is 1024 and thus able to\n\t\t     * cover about 6000 pixels for a 6 pixel wide font (which is\n\t\t     * a very small barely readable font)\n\t\t     */\n\n\t\t    LOCK;\n\t\t    XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,\n\t\t\t    originX, originY, glyphs, nglyph);\n\t\t    UNLOCK;\n\t\t}\n\t    }\n\t    originX = ROUND16(x);\n\t    originY = ROUND16(y);\n\t    currentFtFont = ftFont;\n\t}\n\tglyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c);\n    }\n    if (nglyph) {\n\tLOCK;\n\tXftGlyphExtents(fontPtr->display, currentFtFont, glyphs,\n\t\tnglyph, &metrics);\n\tUNLOCK;\n\n\t/*\n\t * Draw glyph only when it fits entirely into 16 bit coords.\n\t */\n\n\tif (x >= minCoord && y >= minCoord &&\n\t    x <= maxCoord - metrics.width &&\n\t    y <= maxCoord - metrics.height) {\n\t    LOCK;\n\t    XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,\n\t\t    originX, originY, glyphs, nglyph);\n\t    UNLOCK;\n\t}\n    }\n#else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */\n    Tcl_Size clen;\n    int nspec;\n    XftGlyphFontSpec specs[NUM_SPEC];\n    XGlyphInfo metrics;\n    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\n    if (fontPtr->ftDraw == 0) {\n\tDEBUG((\"Switch to drawable 0x%lx\\n\", drawable));\n\tfontPtr->ftDraw = XftDrawCreate(display, drawable,\n\t\tfontPtr->visual, fontPtr->colormap);\n    } else {\n\tTk_ErrorHandler handler =\n\t\tTk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);\n\n\tXftDrawChange(fontPtr->ftDraw, drawable);\n\tTk_DeleteErrorHandler(handler);\n    }\n    XGetGCValues(display, gc, GCForeground, &values);\n    xftcolor = LookUpColor(display, fontPtr, values.foreground);\n    if (tsdPtr->clipRegion != NULL) {\n\tXftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);\n    }\n    nspec = 0;\n    while (numBytes > 0) {\n\tXftFont *ftFont, *ft0Font;\n\tFcChar32 c;\n\n\tclen = utf8ToUcs4(source, &c, numBytes);\n\tif (clen <= 0) {\n\t    /*\n\t     * This should not happen, but it can.\n\t     */\n\n\t    goto doUnderlineStrikeout;\n\t}\n\tsource += clen;\n\tnumBytes -= clen;\n\n\tftFont = GetFont(fontPtr, c, angle);\n\tft0Font = GetFont(fontPtr, c, 0.0);\n\tif (ftFont && ft0Font) {\n\t    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);\n\t    LOCK;\n\t    XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,\n\t\t    &metrics);\n\t    UNLOCK;\n\n\t    /*\n\t     * Draw glyph only when it fits entirely into 16 bit coords.\n\t     */\n\n\t    if (x >= minCoord && y >= minCoord &&\n\t\tx <= maxCoord - metrics.width &&\n\t\ty <= maxCoord - metrics.height) {\n\t\tspecs[nspec].font = ftFont;\n\t\tspecs[nspec].x = ROUND16(x);\n\t\tspecs[nspec].y = ROUND16(y);\n\t\tif (++nspec == NUM_SPEC) {\n\t\t    LOCK;\n\t\t    XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,\n\t\t\t    specs, nspec);\n\t\t    UNLOCK;\n\t\t    nspec = 0;\n\t\t}\n\t    }\n\t    x += metrics.xOff*cosA + metrics.yOff*sinA;\n\t    y += metrics.yOff*cosA - metrics.xOff*sinA;\n\t}\n    }\n    if (nspec) {\n\tLOCK;\n\tXftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);\n\tUNLOCK;\n    }\n#endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */\n\n  doUnderlineStrikeout:\n    if (tsdPtr->clipRegion != NULL) {\n\tXftDrawSetClip(fontPtr->ftDraw, NULL);\n    }\n    if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) {\n\tXPoint points[5];\n\tdouble width = (x - xStart) * cosA + (yStart - y) * sinA;\n\tdouble barHeight = fontPtr->font.underlineHeight;\n\tdouble dy = fontPtr->font.underlinePos;\n\n\tif (fontPtr->font.fa.underline != 0) {\n\t    if (fontPtr->font.underlineHeight == 1) {\n\t\tdy++;\n\t    }\n\t    points[0].x = xStart + ROUND16(dy*sinA);\n\t    points[0].y = yStart + ROUND16(dy*cosA);\n\t    points[1].x = xStart + ROUND16(dy*sinA + width*cosA);\n\t    points[1].y = yStart + ROUND16(dy*cosA - width*sinA);\n\t    if (fontPtr->font.underlineHeight == 1) {\n\t\tXDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);\n\t    } else {\n\t\tpoints[2].x = xStart + ROUND16(dy*sinA + width*cosA\n\t\t\t+ barHeight*sinA);\n\t\tpoints[2].y = yStart + ROUND16(dy*cosA - width*sinA\n\t\t\t+ barHeight*cosA);\n\t\tpoints[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA);\n\t\tpoints[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA);\n\t\tpoints[4].x = points[0].x;\n\t\tpoints[4].y = points[0].y;\n\t\tXFillPolygon(display, drawable, gc, points, 5, Complex,\n\t\t\tCoordModeOrigin);\n\t\tXDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);\n\t    }\n\t}\n\tif (fontPtr->font.fa.overstrike != 0) {\n\t    dy = -fontPtr->font.fm.descent\n\t\t   - (fontPtr->font.fm.ascent) / 10;\n\t    points[0].x = xStart + ROUND16(dy*sinA);\n\t    points[0].y = yStart + ROUND16(dy*cosA);\n\t    points[1].x = xStart + ROUND16(dy*sinA + width*cosA);\n\t    points[1].y = yStart + ROUND16(dy*cosA - width*sinA);\n\t    if (fontPtr->font.underlineHeight == 1) {\n\t\tXDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);\n\t    } else {\n\t\tpoints[2].x = xStart + ROUND16(dy*sinA + width*cosA\n\t\t\t+ barHeight*sinA);\n\t\tpoints[2].y = yStart + ROUND16(dy*cosA - width*sinA\n\t\t\t+ barHeight*cosA);\n\t\tpoints[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA);\n\t\tpoints[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA);\n\t\tpoints[4].x = points[0].x;\n\t\tpoints[4].y = points[0].y;\n\t\tXFillPolygon(display, drawable, gc, points, 5, Complex,\n\t\t\tCoordModeOrigin);\n\t\tXDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawCharsInContext --\n *\n *\tDraw a string of characters on the screen like Tk_DrawChars(), but\n *\twith access to all the characters on the line for context. On X11 this\n *\tcontext isn't consulted, so we just call Tk_DrawChars().\n *\n *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this\n *            function is unused.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    int x, int y)\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n{\n    int widthUntilStart;\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+widthUntilStart, y);\n}\n\f\nvoid\nTkpDrawAngledCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    double x, double y,\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    int widthUntilStart;\n    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);\n}\n\f\nvoid\nTkUnixSetXftClipRegion(\n    Region clipRegion)\t/* The clipping region to install. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->clipRegion = clipRegion;\n}\n\f\n/*\n * Local Variables:\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixScale.c",
    "content": "/*\n * tkUnixScale.c --\n *\n *\tThis file implements the X specific portion of the scale widget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkScale.h\"\n\n#ifdef _WIN32\n#include \"tkWinInt.h\"\n#endif\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tDisplayHorizontalScale(TkScale *scalePtr,\n\t\t\t    Drawable drawable, XRectangle *drawnAreaPtr);\nstatic void\t\tDisplayHorizontalValue(TkScale *scalePtr,\n\t\t\t    Drawable drawable, double value, int top,\n\t\t\t    const char *format);\nstatic void\t\tDisplayVerticalScale(TkScale *scalePtr,\n\t\t\t    Drawable drawable, XRectangle *drawnAreaPtr);\nstatic void\t\tDisplayVerticalValue(TkScale *scalePtr,\n\t\t\t    Drawable drawable, double value, int rightEdge,\n\t\t\t    const char *format);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateScale --\n *\n *\tAllocate a new TkScale structure.\n *\n * Results:\n *\tReturns a newly allocated TkScale structure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkScale *\nTkpCreateScale(\n    TCL_UNUSED(Tk_Window))\n{\n    return (TkScale *)Tcl_Alloc(sizeof(TkScale));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyScale --\n *\n *\tDestroy a TkScale structure. It's necessary to do this with\n *\tTcl_EventuallyFree to allow the Tcl_Preserve(scalePtr) to work as\n *\texpected in TkpDisplayScale. (hobbs)\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tMemory is freed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyScale(\n    TkScale *scalePtr)\n{\n    Tcl_EventuallyFree(scalePtr, TCL_DYNAMIC);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayVerticalScale --\n *\n *\tThis function redraws the contents of a vertical scale window. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's\n *\tnothing else for the application to do.\n *\n * Results:\n *\tThere is no return value. If only a part of the scale needs to be\n *\tredrawn, then drawnAreaPtr is modified to reflect the area that was\n *\tactually modified.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayVerticalScale(\n    TkScale *scalePtr,\t\t/* Widget record for scale. */\n    Drawable drawable,\t\t/* Where to display scale (window or\n\t\t\t\t * pixmap). */\n    XRectangle *drawnAreaPtr)\t/* Initally contains area of window; if only a\n\t\t\t\t * part of the scale is redrawn, gets modified\n\t\t\t\t * to reflect the part of the window that was\n\t\t\t\t * redrawn. */\n{\n    Tk_Window tkwin = scalePtr->tkwin;\n    int x, y, width, height, shadowWidth;\n    double tickValue, tickInterval = scalePtr->tickInterval;\n    Tk_3DBorder sliderBorder;\n    int scaleWidth, borderWidth, sliderLength;\n\n    /*\n     * Display the information from left to right across the window.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->widthObj, &scaleWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->sliderLengthObj, &sliderLength);\n    if (!(scalePtr->flags & REDRAW_OTHER)) {\n\tdrawnAreaPtr->x = (short)scalePtr->vertTickRightX;\n\tdrawnAreaPtr->y = (short)scalePtr->inset;\n\tdrawnAreaPtr->width = (short)(scalePtr->vertTroughX + scaleWidth\n\t\t+ 2 * borderWidth - scalePtr->vertTickRightX);\n\tdrawnAreaPtr->height -= (short)(2 * scalePtr->inset);\n    }\n    Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,\n\t    drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,\n\t    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);\n    if (scalePtr->flags & REDRAW_OTHER) {\n\t/*\n\t * Display the tick marks.\n\t */\n\n\tif (tickInterval != 0) {\n\t    double ticks, maxTicks;\n\n\t    /*\n\t     * Ensure that we will only draw enough of the tick values such\n\t     * that they don't overlap\n\t     */\n\n\t    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)\n\t\t    / tickInterval);\n\t    maxTicks = (double) Tk_Height(tkwin)\n\t\t    / (double) scalePtr->fontHeight;\n\t    if (ticks > maxTicks) {\n\t\ttickInterval *= (ticks / maxTicks);\n\t    }\n\t    for (tickValue = scalePtr->fromValue; ;\n\t\t    tickValue += tickInterval) {\n\t\t/*\n\t\t * The TkRoundValueToResolution call gets rid of accumulated\n\t\t * round-off errors, if any.\n\t\t */\n\n\t\ttickValue = TkRoundValueToResolution(scalePtr, tickValue);\n\t\tif (scalePtr->toValue >= scalePtr->fromValue) {\n\t\t    if (tickValue > scalePtr->toValue) {\n\t\t\tbreak;\n\t\t    }\n\t\t} else {\n\t\t    if (tickValue < scalePtr->toValue) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tDisplayVerticalValue(scalePtr, drawable, tickValue,\n\t\t\tscalePtr->vertTickRightX, scalePtr->tickFormat);\n\t    }\n\t}\n    }\n\n    /*\n     * Display the value, if it is desired.\n     */\n\n    if (scalePtr->showValue) {\n\tDisplayVerticalValue(scalePtr, drawable, scalePtr->value,\n\t\tscalePtr->vertValueRightX, scalePtr->valueFormat);\n    }\n\n    /*\n     * Display the trough and the slider.\n     */\n\n    Tk_Draw3DRectangle(tkwin, drawable,\n\t    scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset,\n\t    scaleWidth + 2 * borderWidth,\n\t    Tk_Height(tkwin) - 2 * scalePtr->inset, borderWidth,\n\t    TK_RELIEF_SUNKEN);\n    XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,\n\t    scalePtr->vertTroughX + borderWidth,\n\t    scalePtr->inset + borderWidth,\n\t    (unsigned) scaleWidth,\n\t    (unsigned) (Tk_Height(tkwin) - 2 * scalePtr->inset\n\t\t- 2 * borderWidth));\n    if (scalePtr->state == STATE_ACTIVE) {\n\tsliderBorder = scalePtr->activeBorder;\n    } else {\n\tsliderBorder = scalePtr->bgBorder;\n    }\n    width = scaleWidth;\n    height = sliderLength / 2;\n    x = scalePtr->vertTroughX + borderWidth;\n    y = TkScaleValueToPixel(scalePtr, scalePtr->value) - height;\n    shadowWidth = borderWidth / 2;\n    if (shadowWidth == 0) {\n\tshadowWidth = 1;\n    }\n    Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width,\n\t    2 * height, shadowWidth, scalePtr->sliderRelief);\n    x += shadowWidth;\n    y += shadowWidth;\n    width -= 2 * shadowWidth;\n    height -= shadowWidth;\n    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width,\n\t    height, shadowWidth, scalePtr->sliderRelief);\n    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height,\n\t    width, height, shadowWidth, scalePtr->sliderRelief);\n\n    /*\n     * Draw the label to the right of the scale.\n     */\n\n    if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelObj != NULL)) {\n\tTk_FontMetrics fm;\n\tTcl_Size labelLength;\n\tconst char *label = Tcl_GetStringFromObj(scalePtr->labelObj, &labelLength);\n\n\tTk_GetFontMetrics(scalePtr->tkfont, &fm);\n\tTk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,\n\t\tscalePtr->tkfont, label, labelLength, scalePtr->vertLabelX,\n\t\tscalePtr->inset + (3 * fm.ascent) / 2);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayVerticalValue --\n *\n *\tThis function is called to display values (scale readings) for\n *\tvertically-oriented scales.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe numerical value corresponding to value is displayed with its right\n *\tedge at \"rightEdge\", and at a vertical position in the scale that\n *\tcorresponds to \"value\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayVerticalValue(\n    TkScale *scalePtr,\t/* Information about widget in which to\n\t\t\t\t * display value. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw the\n\t\t\t\t * value. */\n    double value,\t\t/* Y-coordinate of number to display,\n\t\t\t\t * specified in application coords, not in\n\t\t\t\t * pixels (we'll compute pixels). */\n    int rightEdge,\t\t/* X-coordinate of right edge of text,\n\t\t\t\t * specified in pixels. */\n    const char *format)\t\t/* Format string to use for the value */\n{\n    Tk_Window tkwin = scalePtr->tkwin;\n    int y, width;\n    char valueString[TCL_DOUBLE_SPACE];\n    Tk_FontMetrics fm;\n\n    Tk_GetFontMetrics(scalePtr->tkfont, &fm);\n    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    Tcl_Size length = strlen(valueString);\n    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);\n\n    /*\n     * Adjust the y-coordinate if necessary to keep the text entirely inside\n     * the window.\n     */\n\n    if (y - fm.ascent < scalePtr->inset + SPACING) {\n\ty = scalePtr->inset + SPACING + fm.ascent;\n    }\n    if (y + fm.descent > Tk_Height(tkwin) - scalePtr->inset - SPACING) {\n\ty = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent;\n    }\n    Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,\n\t    scalePtr->tkfont, valueString, length, rightEdge - width, y);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DisplayHorizontalScale --\n *\n *\tThis function redraws the contents of a horizontal scale window. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's\n *\tnothing else for the application to do.\n *\n * Results:\n *\tThere is no return value. If only a part of the scale needs to be\n *\tredrawn, then drawnAreaPtr is modified to reflect the area that was\n *\tactually modified.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDisplayHorizontalScale(\n    TkScale *scalePtr,\t\t/* Widget record for scale. */\n    Drawable drawable,\t\t/* Where to display scale (window or\n\t\t\t\t * pixmap). */\n    XRectangle *drawnAreaPtr)\t/* Initally contains area of window; if only a\n\t\t\t\t * part of the scale is redrawn, gets modified\n\t\t\t\t * to reflect the part of the window that was\n\t\t\t\t * redrawn. */\n{\n    Tk_Window tkwin = scalePtr->tkwin;\n    int x, y, width, height, shadowWidth;\n    double tickInterval = scalePtr->tickInterval;\n    Tk_3DBorder sliderBorder;\n    int scaleWidth, borderWidth, sliderLength;\n\n    /*\n     * Display the information from bottom to top across the window.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->widthObj, &scaleWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->sliderLengthObj, &sliderLength);\n    if (!(scalePtr->flags & REDRAW_OTHER)) {\n\tdrawnAreaPtr->x = (short)scalePtr->inset;\n\tdrawnAreaPtr->y = (short)scalePtr->horizValueY;\n\tdrawnAreaPtr->width -= (short)(2*scalePtr->inset);\n\tdrawnAreaPtr->height = (short)(scalePtr->horizTroughY + scaleWidth\n\t\t+ 2 * borderWidth - scalePtr->horizValueY);\n    }\n    Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,\n\t    drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,\n\t    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);\n    if (scalePtr->flags & REDRAW_OTHER) {\n\t/*\n\t * Display the tick marks.\n\t */\n\n\tif (tickInterval != 0) {\n\t    char valueString[TCL_DOUBLE_SPACE];\n\t    double ticks, maxTicks, tickValue;\n\n\t    /*\n\t     * Ensure that we will only draw enough of the tick values such\n\t     * that they don't overlap. We base this off the width that\n\t     * fromValue would take. Not exact, but better than no constraint.\n\t     */\n\n\t    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)\n\t\t    / tickInterval);\n\t    if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,\n\t\t    scalePtr->fromValue) < 0) {\n\t\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n\t    }\n\t    maxTicks = (double) Tk_Width(tkwin)\n\t\t    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);\n\t    if (ticks > maxTicks) {\n\t\ttickInterval *= ticks / maxTicks;\n\t    }\n\t    tickValue = scalePtr->fromValue;\n\t    while (1) {\n\t\t/*\n\t\t * The TkRoundValueToResolution call gets rid of accumulated\n\t\t * round-off errors, if any.\n\t\t */\n\n\t\ttickValue = TkRoundValueToResolution(scalePtr, tickValue);\n\t\tif (scalePtr->toValue >= scalePtr->fromValue) {\n\t\t    if (tickValue > scalePtr->toValue) {\n\t\t\tbreak;\n\t\t    }\n\t\t} else {\n\t\t    if (tickValue < scalePtr->toValue) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tDisplayHorizontalValue(scalePtr, drawable, tickValue,\n\t\t\tscalePtr->horizTickY, scalePtr->tickFormat);\n\t\ttickValue += tickInterval;\n\t    }\n\t}\n    }\n\n    /*\n     * Display the value, if it is desired.\n     */\n\n    if (scalePtr->showValue) {\n\tDisplayHorizontalValue(scalePtr, drawable, scalePtr->value,\n\t\tscalePtr->horizValueY, scalePtr->valueFormat);\n    }\n\n    /*\n     * Display the trough and the slider.\n     */\n\n    y = scalePtr->horizTroughY;\n    Tk_Draw3DRectangle(tkwin, drawable,\n\t    scalePtr->bgBorder, scalePtr->inset, y,\n\t    Tk_Width(tkwin) - 2 * scalePtr->inset,\n\t    scaleWidth + 2 * borderWidth,\n\t    borderWidth, TK_RELIEF_SUNKEN);\n    XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,\n\t    scalePtr->inset + borderWidth,\n\t    y + borderWidth,\n\t    (unsigned) (Tk_Width(tkwin) - 2 * scalePtr->inset\n\t\t- 2 * borderWidth),\n\t    (unsigned) scaleWidth);\n    if (scalePtr->state == STATE_ACTIVE) {\n\tsliderBorder = scalePtr->activeBorder;\n    } else {\n\tsliderBorder = scalePtr->bgBorder;\n    }\n    width = sliderLength / 2;\n    height = scaleWidth;\n    x = TkScaleValueToPixel(scalePtr, scalePtr->value) - width;\n    y += borderWidth;\n    shadowWidth = borderWidth / 2;\n    if (shadowWidth == 0) {\n\tshadowWidth = 1;\n    }\n    Tk_Draw3DRectangle(tkwin, drawable, sliderBorder,\n\t    x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief);\n    x += shadowWidth;\n    y += shadowWidth;\n    width -= shadowWidth;\n    height -= 2*shadowWidth;\n    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height,\n\t    shadowWidth, scalePtr->sliderRelief);\n    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y,\n\t    width, height, shadowWidth, scalePtr->sliderRelief);\n\n    /*\n     * Draw the label at the top of the scale.\n     */\n\n    if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelObj != NULL)) {\n\tTk_FontMetrics fm;\n\tTcl_Size labelLength;\n\tconst char *label = Tcl_GetStringFromObj(scalePtr->labelObj, &labelLength);\n\n\tTk_GetFontMetrics(scalePtr->tkfont, &fm);\n\tTk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,\n\t\tscalePtr->tkfont, label, labelLength, scalePtr->inset + fm.ascent/2,\n\t\tscalePtr->horizLabelY + fm.ascent);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DisplayHorizontalValue --\n *\n *\tThis function is called to display values (scale readings) for\n *\thorizontally-oriented scales.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe numerical value corresponding to value is displayed with its\n *\tbottom edge at \"bottom\", and at a horizontal position in the scale\n *\tthat corresponds to \"value\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayHorizontalValue(\n    TkScale *scalePtr,\t/* Information about widget in which to\n\t\t\t\t * display value. */\n    Drawable drawable,\t\t/* Pixmap or window in which to draw the\n\t\t\t\t * value. */\n    double value,\t\t/* X-coordinate of number to display,\n\t\t\t\t * specified in application coords, not in\n\t\t\t\t * pixels (we'll compute pixels). */\n    int top,\t\t\t/* Y-coordinate of top edge of text, specified\n\t\t\t\t * in pixels. */\n    const char *format)\t\t/* Format string to use for the value */\n{\n    Tk_Window tkwin = scalePtr->tkwin;\n    int x, y, width;\n    char valueString[TCL_DOUBLE_SPACE];\n    Tk_FontMetrics fm;\n\n    x = TkScaleValueToPixel(scalePtr, value);\n    Tk_GetFontMetrics(scalePtr->tkfont, &fm);\n    y = top + fm.ascent;\n    if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) {\n\tvalueString[TCL_DOUBLE_SPACE - 1] = '\\0';\n    }\n    Tcl_Size length = strlen(valueString);\n    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);\n\n    /*\n     * Adjust the x-coordinate if necessary to keep the text entirely inside\n     * the window.\n     */\n\n    x -= width / 2;\n    if (x < scalePtr->inset + SPACING) {\n\tx = scalePtr->inset + SPACING;\n    }\n\n    /*\n     * Check the right border so use starting point +text width for the check.\n     */\n\n    if (x + width >= (Tk_Width(tkwin) - scalePtr->inset)) {\n\tx = Tk_Width(tkwin) - scalePtr->inset - SPACING - width;\n    }\n    Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,\n\t    scalePtr->tkfont, valueString, length, x, y);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayScale --\n *\n *\tThis function is invoked as an idle handler to redisplay the contents\n *\tof a scale widget.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe scale gets redisplayed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayScale(\n    void *clientData)\t/* Widget record for scale. */\n{\n    TkScale *scalePtr = (TkScale *)clientData;\n    Tk_Window tkwin = scalePtr->tkwin;\n    Tcl_Interp *interp = scalePtr->interp;\n    Pixmap pixmap;\n    int result;\n    char string[TCL_DOUBLE_SPACE];\n    XRectangle drawnArea;\n    Tcl_DString buf;\n    int highlightWidth, borderWidth;\n\n    scalePtr->flags &= ~REDRAW_PENDING;\n    if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\tgoto done;\n    }\n\n    /*\n     * Invoke the scale's command if needed.\n     */\n\n    Tcl_Preserve(scalePtr);\n    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->commandObj != NULL)) {\n\tTcl_Preserve(interp);\n\tif (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,\n\t\tscalePtr->value) < 0) {\n\t    string[TCL_DOUBLE_SPACE - 1] = '\\0';\n\t}\n\tTcl_DStringInit(&buf);\n\tTcl_DStringAppend(&buf, Tcl_GetString(scalePtr->commandObj), TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, \" \", TCL_INDEX_NONE);\n\tTcl_DStringAppend(&buf, string, TCL_INDEX_NONE);\n\tresult = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_DStringFree(&buf);\n\tif (result != TCL_OK) {\n\t    Tcl_AddErrorInfo(interp, \"\\n    (command executed by scale)\");\n\t    Tcl_BackgroundException(interp, result);\n\t}\n\tTcl_Release(interp);\n    }\n    scalePtr->flags &= ~INVOKE_COMMAND;\n    if (scalePtr->flags & SCALE_DELETED) {\n\tTcl_Release(scalePtr);\n\treturn;\n    }\n    Tcl_Release(scalePtr);\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * In order to avoid screen flashes, this function redraws the scale in a\n     * pixmap, then copies the pixmap to the screen in a single operation.\n     * This means that there's no point in time where the on-sreen image has\n     * been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n#else\n    pixmap = Tk_WindowId(tkwin);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n    drawnArea.x = 0;\n    drawnArea.y = 0;\n    drawnArea.width = (short)Tk_Width(tkwin);\n    drawnArea.height = (short)Tk_Height(tkwin);\n\n    /*\n     * Much of the redisplay is done totally differently for horizontal and\n     * vertical scales. Handle the part that's different.\n     */\n\n    if (scalePtr->orient == ORIENT_VERTICAL) {\n\tDisplayVerticalScale(scalePtr, pixmap, &drawnArea);\n    } else {\n\tDisplayHorizontalScale(scalePtr, pixmap, &drawnArea);\n    }\n\n    /*\n     * Now handle the part of redisplay that is the same for horizontal and\n     * vertical scales: border and traversal highlight.\n     */\n\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, scalePtr->borderWidthObj, &borderWidth);\n    if (scalePtr->flags & REDRAW_OTHER) {\n\tif (scalePtr->relief != TK_RELIEF_FLAT) {\n\t    Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder,\n\t\t    highlightWidth, highlightWidth,\n\t\t    Tk_Width(tkwin) - 2 * highlightWidth,\n\t\t    Tk_Height(tkwin) - 2 * highlightWidth,\n\t\t    borderWidth, scalePtr->relief);\n\t}\n\tif (highlightWidth > 0) {\n\t    GC gc;\n\n\t    if (scalePtr->flags & GOT_FOCUS) {\n\t\tgc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);\n\t    } else {\n\t\tgc = Tk_GCForColor(\n\t\t\tTk_3DBorderColor(scalePtr->highlightBorder), pixmap);\n\t    }\n\t    Tk_DrawFocusHighlight(tkwin, gc, highlightWidth, pixmap);\n\t}\n    }\n\n#ifndef TK_NO_DOUBLE_BUFFERING\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin),\n\t    scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width,\n\t    drawnArea.height, drawnArea.x, drawnArea.y);\n    Tk_FreePixmap(scalePtr->display, pixmap);\n#endif /* TK_NO_DOUBLE_BUFFERING */\n\n  done:\n    scalePtr->flags &= ~REDRAW_ALL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpScaleElement --\n *\n *\tDetermine which part of a scale widget lies under a given point.\n *\n * Results:\n *\tThe return value is either TROUGH1, SLIDER, TROUGH2, or OTHER,\n *\tdepending on which of the scale's active elements (if any) is under\n *\tthe point at (x,y).\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpScaleElement(\n    TkScale *scalePtr,\t\t/* Widget record for scale. */\n    int x, int y)\t\t/* Coordinates within scalePtr's window. */\n{\n    int sliderFirst, width, borderWidth, sliderLength;\n\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->widthObj, &width);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scalePtr->tkwin, scalePtr->sliderLengthObj, &sliderLength);\n    if (scalePtr->orient == ORIENT_VERTICAL) {\n\tif ((x < scalePtr->vertTroughX)\n\t\t|| (x >= (scalePtr->vertTroughX + 2 * borderWidth +\n\t\twidth))) {\n\t    return OTHER;\n\t}\n\tif ((y < scalePtr->inset)\n\t\t|| (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) {\n\t    return OTHER;\n\t}\n\tsliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)\n\t\t- sliderLength/2;\n\tif (y < sliderFirst) {\n\t    return TROUGH1;\n\t}\n\tif (y < sliderFirst + sliderLength) {\n\t    return SLIDER;\n\t}\n\treturn TROUGH2;\n    }\n\n    if ((y < scalePtr->horizTroughY)\n\t    || (y >= (scalePtr->horizTroughY + 2 * borderWidth +\n\t    width))) {\n\treturn OTHER;\n    }\n    if ((x < scalePtr->inset)\n\t    || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) {\n\treturn OTHER;\n    }\n    sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)\n\t    - sliderLength / 2;\n    if (x < sliderFirst) {\n\treturn TROUGH1;\n    }\n    if (x < sliderFirst + sliderLength) {\n\treturn SLIDER;\n    }\n    return TROUGH2;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixScrlbr.c",
    "content": "/*\n * tkUnixScrollbar.c --\n *\n *\tThis file implements the Unix specific portion of the scrollbar\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkScrollbar.h\"\n\n/*\n * Minimum slider length, in pixels (designed to make sure that the slider is\n * always easy to grab with the mouse).\n */\n\n#define MIN_SLIDER_LENGTH\t5\n\n/*\n * Declaration of Unix specific scrollbar structure.\n */\n\ntypedef struct UnixScrollbar {\n    TkScrollbar info;\t\t/* Generic scrollbar info. */\n    GC troughGC;\t\t/* For drawing trough. */\n    GC copyGC;\t\t\t/* Used for copying from pixmap onto screen. */\n} UnixScrollbar;\n\n/*\n * The class procedure table for the scrollbar widget. All fields except size\n * are left initialized to NULL, which should happen automatically since the\n * variable is declared at this scope.\n */\n\nconst Tk_ClassProcs tkpScrollbarProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    NULL,\t\t\t\t\t/* worldChangedProc */\n    NULL,\t\t\t\t\t/* createProc */\n    NULL\t\t\t\t\t/* modalProc */\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateScrollbar --\n *\n *\tAllocate a new TkScrollbar structure.\n *\n * Results:\n *\tReturns a newly allocated TkScrollbar structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkScrollbar *\nTkpCreateScrollbar(\n    Tk_Window tkwin)\n{\n    UnixScrollbar *scrollPtr = (UnixScrollbar *)Tcl_Alloc(sizeof(UnixScrollbar));\n\n    scrollPtr->troughGC = NULL;\n    scrollPtr->copyGC = NULL;\n\n    Tk_CreateEventHandler(tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask,\n\t    TkScrollbarEventProc, scrollPtr);\n\n    return (TkScrollbar *) scrollPtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDisplayScrollbar --\n *\n *\tThis procedure redraws the contents of a scrollbar window. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's\n *\tnothing else for the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpDisplayScrollbar(\n    void *clientData)\t/* Information about window. */\n{\n    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;\n    Tk_Window tkwin = scrollPtr->tkwin;\n    XPoint points[7];\n    Tk_3DBorder border;\n    int relief, width, elementBorderWidth;\n    int borderWidth, highlightWidth;\n    Pixmap pixmap;\n\n    if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\tgoto done;\n    }\n\n    if (scrollPtr->vertical) {\n\twidth = Tk_Width(tkwin) - 2 * scrollPtr->inset;\n    } else {\n\twidth = Tk_Height(tkwin) - 2 * scrollPtr->inset;\n    }\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->borderWidthObj, &borderWidth);\n    if (scrollPtr->elementBorderWidthObj) {\n\tTk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->elementBorderWidthObj, &elementBorderWidth);\n    } else {\n\telementBorderWidth = borderWidth;\n    }\n\n    /*\n     * In order to avoid screen flashes, this procedure redraws the scrollbar\n     * in a pixmap, then copies the pixmap to the screen in a single\n     * operation. This means that there's no point in time where the on-sreen\n     * image has been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(scrollPtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n    if (highlightWidth > 0) {\n\tGC gc;\n\n\tif (scrollPtr->flags & GOT_FOCUS) {\n\t    gc = Tk_GCForColor(scrollPtr->highlightColorPtr, pixmap);\n\t} else {\n\t    gc = Tk_GCForColor(scrollPtr->highlightBgColorPtr, pixmap);\n\t}\n\tTk_DrawFocusHighlight(tkwin, gc, highlightWidth, pixmap);\n    }\n    Tk_Draw3DRectangle(tkwin, pixmap, scrollPtr->bgBorder,\n\t    highlightWidth, highlightWidth,\n\t    Tk_Width(tkwin) - 2 * highlightWidth,\n\t    Tk_Height(tkwin) - 2 * highlightWidth,\n\t    borderWidth, scrollPtr->relief);\n    XFillRectangle(scrollPtr->display, pixmap,\n\t    ((UnixScrollbar*)scrollPtr)->troughGC,\n\t    scrollPtr->inset, scrollPtr->inset,\n\t    (unsigned) (Tk_Width(tkwin) - 2 * scrollPtr->inset),\n\t    (unsigned) (Tk_Height(tkwin) - 2 * scrollPtr->inset));\n\n    /*\n     * Draw the top or left arrow. The coordinates of the polygon points\n     * probably seem odd, but they were carefully chosen with respect to X's\n     * rules for filling polygons. These point choices cause the arrows to\n     * just fill the narrow dimension of the scrollbar and be properly\n     * centered.\n     */\n\n    if (scrollPtr->activeField == TOP_ARROW) {\n\tborder = scrollPtr->activeBorder;\n\trelief = scrollPtr->activeField == TOP_ARROW ? scrollPtr->activeRelief\n\t\t: TK_RELIEF_RAISED;\n    } else {\n\tborder = scrollPtr->bgBorder;\n\trelief = TK_RELIEF_RAISED;\n    }\n    if (scrollPtr->vertical) {\n\tpoints[0].x = scrollPtr->inset - 1;\n\tpoints[0].y = scrollPtr->arrowLength + scrollPtr->inset - 1;\n\tpoints[1].x = width + scrollPtr->inset;\n\tpoints[1].y = points[0].y;\n\tpoints[2].x = width/2 + scrollPtr->inset;\n\tpoints[2].y = scrollPtr->inset - 1;\n\tTk_Fill3DPolygon(tkwin, pixmap, border, points, 3,\n\t\telementBorderWidth, relief);\n    } else {\n\tpoints[0].x = scrollPtr->arrowLength + scrollPtr->inset - 1;\n\tpoints[0].y = scrollPtr->inset - 1;\n\tpoints[1].x = scrollPtr->inset;\n\tpoints[1].y = width/2 + scrollPtr->inset;\n\tpoints[2].x = points[0].x;\n\tpoints[2].y = width + scrollPtr->inset;\n\tTk_Fill3DPolygon(tkwin, pixmap, border, points, 3,\n\t\telementBorderWidth, relief);\n    }\n\n    /*\n     * Display the bottom or right arrow.\n     */\n\n    if (scrollPtr->activeField == BOTTOM_ARROW) {\n\tborder = scrollPtr->activeBorder;\n\trelief = scrollPtr->activeField == BOTTOM_ARROW\n\t\t? scrollPtr->activeRelief : TK_RELIEF_RAISED;\n    } else {\n\tborder = scrollPtr->bgBorder;\n\trelief = TK_RELIEF_RAISED;\n    }\n    if (scrollPtr->vertical) {\n\tpoints[0].x = scrollPtr->inset;\n\tpoints[0].y = Tk_Height(tkwin) - scrollPtr->arrowLength\n\t\t- scrollPtr->inset + 1;\n\tpoints[1].x = width/2 + scrollPtr->inset;\n\tpoints[1].y = Tk_Height(tkwin) - scrollPtr->inset;\n\tpoints[2].x = width + scrollPtr->inset;\n\tpoints[2].y = points[0].y;\n\tTk_Fill3DPolygon(tkwin, pixmap, border,\n\t\tpoints, 3, elementBorderWidth, relief);\n    } else {\n\tpoints[0].x = Tk_Width(tkwin) - scrollPtr->arrowLength\n\t\t- scrollPtr->inset + 1;\n\tpoints[0].y = scrollPtr->inset - 1;\n\tpoints[1].x = points[0].x;\n\tpoints[1].y = width + scrollPtr->inset;\n\tpoints[2].x = Tk_Width(tkwin) - scrollPtr->inset;\n\tpoints[2].y = width/2 + scrollPtr->inset;\n\tTk_Fill3DPolygon(tkwin, pixmap, border,\n\t\tpoints, 3, elementBorderWidth, relief);\n    }\n\n    /*\n     * Display the slider.\n     */\n\n    if (scrollPtr->activeField == SLIDER) {\n\tborder = scrollPtr->activeBorder;\n\trelief = scrollPtr->activeField == SLIDER ? scrollPtr->activeRelief\n\t\t: TK_RELIEF_RAISED;\n    } else {\n\tborder = scrollPtr->bgBorder;\n\trelief = TK_RELIEF_RAISED;\n    }\n    if (scrollPtr->vertical) {\n\tTk_Fill3DRectangle(tkwin, pixmap, border,\n\t\tscrollPtr->inset, scrollPtr->sliderFirst,\n\t\twidth, scrollPtr->sliderLast - scrollPtr->sliderFirst,\n\t\telementBorderWidth, relief);\n    } else {\n\tTk_Fill3DRectangle(tkwin, pixmap, border,\n\t\tscrollPtr->sliderFirst, scrollPtr->inset,\n\t\tscrollPtr->sliderLast - scrollPtr->sliderFirst, width,\n\t\telementBorderWidth, relief);\n    }\n\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(scrollPtr->display, pixmap, Tk_WindowId(tkwin),\n\t    ((UnixScrollbar*)scrollPtr)->copyGC, 0, 0,\n\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(scrollPtr->display, pixmap);\n\n  done:\n    scrollPtr->flags &= ~REDRAW_PENDING;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeScrollbarGeometry --\n *\n *\tAfter changes in a scrollbar's size or configuration, this procedure\n *\trecomputes various geometry information used in displaying the\n *\tscrollbar.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe scrollbar will be displayed differently.\n *\n *----------------------------------------------------------------------\n */\n\nextern void\nTkpComputeScrollbarGeometry(\n    TkScrollbar *scrollPtr)\n\t\t\t\t/* Scrollbar whose geometry may have\n\t\t\t\t * changed. */\n{\n    int width, fieldLength;\n    int borderWidth, highlightWidth;\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->highlightWidthObj, &highlightWidth);\n    scrollPtr->inset = highlightWidth + borderWidth;\n    width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin)\n\t    : Tk_Height(scrollPtr->tkwin);\n\n    /*\n     * Next line assumes that the arrow area is a square.\n     */\n\n    scrollPtr->arrowLength = width - 2 * scrollPtr->inset + 1;\n    fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)\n\t    : Tk_Width(scrollPtr->tkwin))\n\t    - 2 * (scrollPtr->arrowLength + scrollPtr->inset);\n    if (fieldLength < 0) {\n\tfieldLength = 0;\n    }\n    scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;\n    scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;\n\n    /*\n     * Adjust the slider so that some piece of it is always displayed in the\n     * scrollbar and so that it has at least a minimal width (so it can be\n     * grabbed with the mouse).\n     */\n\n    if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {\n\tscrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;\n    }\n    if (scrollPtr->sliderFirst < 0) {\n\tscrollPtr->sliderFirst = 0;\n    }\n    if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {\n\tscrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;\n    }\n    if (scrollPtr->sliderLast > fieldLength) {\n\tscrollPtr->sliderLast = fieldLength;\n    }\n    scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset;\n    scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset;\n\n    /*\n     * Register the desired geometry for the window (leave enough space for\n     * the two arrows plus a minimum-size slider, plus border around the whole\n     * window, if any). Then arrange for the window to be redisplayed.\n     */\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->widthObj, &width);\n    if (scrollPtr->vertical) {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\twidth + 2 * scrollPtr->inset,\n\t\t2 * (scrollPtr->arrowLength + borderWidth\n\t\t+ scrollPtr->inset));\n    } else {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\t2 * (scrollPtr->arrowLength + borderWidth\n\t\t+ scrollPtr->inset), width + 2 * scrollPtr->inset);\n    }\n    Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyScrollbar --\n *\n *\tFree data structures associated with the scrollbar control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees the GCs associated with the scrollbar.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyScrollbar(\n    TkScrollbar *scrollPtr)\n{\n    UnixScrollbar *unixScrollPtr = (UnixScrollbar *)scrollPtr;\n\n    if (unixScrollPtr->troughGC != NULL) {\n\tTk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);\n    }\n    if (unixScrollPtr->copyGC != NULL) {\n\tTk_FreeGC(scrollPtr->display, unixScrollPtr->copyGC);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureScrollbar --\n *\n *\tThis procedure is called after the generic code has finished\n *\tprocessing configuration options, in order to configure platform\n *\tspecific options.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfiguration info may get changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpConfigureScrollbar(\n    TkScrollbar *scrollPtr)\n\t\t\t\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n{\n    XGCValues gcValues;\n    GC newGC;\n    UnixScrollbar *unixScrollPtr = (UnixScrollbar *) scrollPtr;\n\n    Tk_SetBackgroundFromBorder(scrollPtr->tkwin, scrollPtr->bgBorder);\n\n    gcValues.foreground = scrollPtr->troughColorPtr->pixel;\n    newGC = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues);\n    if (unixScrollPtr->troughGC != NULL) {\n\tTk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);\n    }\n    unixScrollPtr->troughGC = newGC;\n    if (unixScrollPtr->copyGC == NULL) {\n\tgcValues.graphics_exposures = False;\n\tunixScrollPtr->copyGC = Tk_GetGC(scrollPtr->tkwin,\n\t\tGCGraphicsExposures, &gcValues);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpScrollbarPosition --\n *\n *\tDetermine the scrollbar element corresponding to a given position.\n *\n * Results:\n *\tOne of TOP_ARROW, TOP_GAP, etc., indicating which element of the\n *\tscrollbar covers the position given by (x, y). If (x,y) is outside the\n *\tscrollbar entirely, then OUTSIDE is returned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkpScrollbarPosition(\n    TkScrollbar *scrollPtr,\n\t\t\t\t/* Scrollbar widget record. */\n    int x, int y)\t\t/* Coordinates within scrollPtr's window. */\n{\n    int length, width, tmp;\n    const int inset = scrollPtr->inset;\n\n    if (scrollPtr->vertical) {\n\tlength = Tk_Height(scrollPtr->tkwin);\n\twidth = Tk_Width(scrollPtr->tkwin);\n    } else {\n\ttmp = x;\n\tx = y;\n\ty = tmp;\n\tlength = Tk_Width(scrollPtr->tkwin);\n\twidth = Tk_Height(scrollPtr->tkwin);\n    }\n\n    if (x<inset || x>=width-inset || y<inset || y>=length-inset) {\n\treturn OUTSIDE;\n    }\n\n    /*\n     * All of the calculations in this procedure mirror those in\n     * TkpDisplayScrollbar. Be sure to keep the two consistent.\n     */\n\n    if (y < inset + scrollPtr->arrowLength) {\n\treturn TOP_ARROW;\n    }\n    if (y < scrollPtr->sliderFirst) {\n\treturn TOP_GAP;\n    }\n    if (y < scrollPtr->sliderLast) {\n\treturn SLIDER;\n    }\n    if (y >= length - (scrollPtr->arrowLength + inset)) {\n\treturn BOTTOM_ARROW;\n    }\n    return BOTTOM_GAP;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixSelect.c",
    "content": "/*\n * tkUnixSelect.c --\n *\n *\tThis file contains X specific routines for manipulating selections.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkSelect.h\"\n\ntypedef struct ConvertInfo {\n    int offset;\t\t\t/* The starting byte offset into the selection\n\t\t\t\t * for the next chunk; -1 means all data has\n\t\t\t\t * been transferred for this conversion. -2\n\t\t\t\t * means only the final zero-length transfer\n\t\t\t\t * still has to be done. Otherwise it is the\n\t\t\t\t * offset of the next chunk of data to\n\t\t\t\t * transfer. */\n    Tcl_EncodingState state;\t/* The encoding state needed across chunks. */\n    char buffer[4];\t/* A buffer to hold part of a UTF character\n\t\t\t\t * that is split across chunks.*/\n} ConvertInfo;\n\n/*\n * When handling INCR-style selection retrievals, the selection owner uses the\n * following data structure to communicate between the ConvertSelection\n * function and TkSelPropProc.\n */\n\ntypedef struct IncrInfo {\n    TkWindow *winPtr;\t\t/* Window that owns selection. */\n    Atom selection;\t\t/* Selection that is being retrieved. */\n    Atom *multAtoms;\t\t/* Information about conversions to perform:\n\t\t\t\t * one or more pairs of (target, property).\n\t\t\t\t * This either points to a retrieved property\n\t\t\t\t * (for MULTIPLE retrievals) or to a static\n\t\t\t\t * array. */\n    unsigned long numConversions;\n\t\t\t\t/* Number of entries in converts (same as # of\n\t\t\t\t * pairs in multAtoms). */\n    ConvertInfo *converts;\t/* One entry for each pair in multAtoms. This\n\t\t\t\t * array is malloc-ed. */\n    char **tempBufs;\t\t/* One pointer for each pair in multAtoms;\n\t\t\t\t * each pointer is either NULL, or it points\n\t\t\t\t * to a small bit of character data that was\n\t\t\t\t * left over from the previous chunk. */\n    Tcl_EncodingState *state;\t/* One state info per pair in multAtoms: State\n\t\t\t\t * info for encoding conversions that span\n\t\t\t\t * multiple buffers. */\n    int *flags;\t\t\t/* One state flag per pair in multAtoms:\n\t\t\t\t * Encoding flags, set to TCL_ENCODING_START\n\t\t\t\t * at the beginning of an INCR transfer. */\n    int numIncrs;\t\t/* Number of entries in converts that aren't\n\t\t\t\t * -1 (i.e. # of INCR-mode transfers not yet\n\t\t\t\t * completed). */\n    Tcl_TimerToken timeout;\t/* Token for timer function. */\n    int idleTime;\t\t/* Number of seconds since we heard anything\n\t\t\t\t * from the selection requestor. */\n    Window reqWindow;\t\t/* Requestor's window id. */\n    Time time;\t\t\t/* Timestamp corresponding to selection at\n\t\t\t\t * beginning of request; used to abort\n\t\t\t\t * transfer if selection changes. */\n    struct IncrInfo *nextPtr;\t/* Next in list of all INCR-style retrievals\n\t\t\t\t * currently pending. */\n} IncrInfo;\n\ntypedef struct {\n    IncrInfo *pendingIncrs;\t/* List of all incr structures currently\n\t\t\t\t * active. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Largest property that we'll accept when sending or receiving the selection:\n */\n\n#define MAX_PROP_WORDS 100000\n\nstatic TkSelRetrievalInfo *pendingRetrievals = NULL;\n\t\t\t\t/* List of all retrievals currently being\n\t\t\t\t * waited for. */\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tConvertSelection(TkWindow *winPtr,\n\t\t\t    XSelectionRequestEvent *eventPtr);\nstatic void\t\tIncrTimeoutProc(void *clientData);\nstatic void\t\tSelCvtFromX32(long *propPtr, unsigned long numValues, Atom type,\n\t\t\t    Tk_Window tkwin, Tcl_DString *dsPtr);\nstatic void\t\tSelCvtFromX8(char *propPtr, unsigned long numValues, Atom type,\n\t\t\t    Tk_Window tkwin, Tcl_DString *dsPtr);\nstatic long *\t\tSelCvtToX(char *string, Atom type, Tk_Window tkwin,\n\t\t\t    Tcl_Size *numLongsPtr);\nstatic int\t\tSelectionSize(TkSelHandler *selPtr);\nstatic void\t\tSelRcvIncrProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tSelTimeoutProc(void *clientData);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelGetSelection --\n *\n *\tRetrieve the specified selection from another process.\n *\n * Results:\n *\tThe return value is a standard Tcl return value. If an error occurs\n *\t(such as no selection exists) then an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkSelGetSelection(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tk_Window tkwin,\t\t/* Window on whose behalf to retrieve the\n\t\t\t\t * selection (determines display from which to\n\t\t\t\t * retrieve). */\n    Atom selection,\t\t/* Selection to retrieve. */\n    Atom target,\t\t/* Desired form in which selection is to be\n\t\t\t\t * returned. */\n    Tk_GetSelProc *proc,\t/* Function to call to process the selection,\n\t\t\t\t * once it has been retrieved. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    TkSelRetrievalInfo retr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n\n    /*\n     * The selection is owned by some other process. To retrieve it, first\n     * record information about the retrieval in progress. Use an internal\n     * window as the requestor.\n     */\n\n    retr.interp = interp;\n    if (dispPtr->clipWindow == NULL) {\n\tint result;\n\n\tresult = TkClipInit(interp, dispPtr);\n\tif (result != TCL_OK) {\n\t    return result;\n\t}\n    }\n    retr.winPtr = (TkWindow *) dispPtr->clipWindow;\n    retr.selection = selection;\n    retr.property = selection;\n    retr.target = target;\n    retr.proc = proc;\n    retr.clientData = clientData;\n    retr.result = -1;\n    retr.idleTime = 0;\n    retr.encFlags = TCL_ENCODING_START;\n    retr.nextPtr = pendingRetrievals;\n    Tcl_DStringInit(&retr.buf);\n    pendingRetrievals = &retr;\n\n    /*\n     * Delete the property to indicate that no parameters are supplied for\n     * the conversion request.\n     */\n\n    XDeleteProperty(winPtr->display, retr.winPtr->window, retr.property);\n\n    /*\n     * Initiate the request for the selection. Note: can't use TkCurrentTime\n     * for the time. If we do, and this application hasn't received any X\n     * events in a long time, the current time will be way in the past and\n     * could even predate the time when the selection was made; if this\n     * happens, the request will be rejected.\n     */\n\n    XConvertSelection(winPtr->display, retr.selection, retr.target,\n\t    retr.property, retr.winPtr->window, CurrentTime);\n\n    /*\n     * Enter a loop processing X events until the selection has been retrieved\n     * and processed. If no response is received within a few seconds, then\n     * timeout.\n     */\n\n    retr.timeout = Tcl_CreateTimerHandler(1000, SelTimeoutProc,\n\t    &retr);\n    while (retr.result == -1) {\n\tTcl_DoOneEvent(0);\n    }\n    Tcl_DeleteTimerHandler(retr.timeout);\n\n    /*\n     * Unregister the information about the selection retrieval in progress.\n     */\n\n    if (pendingRetrievals == &retr) {\n\tpendingRetrievals = retr.nextPtr;\n    } else {\n\tTkSelRetrievalInfo *retrPtr;\n\n\tfor (retrPtr = pendingRetrievals; retrPtr != NULL;\n\t\tretrPtr = retrPtr->nextPtr) {\n\t    if (retrPtr->nextPtr == &retr) {\n\t\tretrPtr->nextPtr = retr.nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    Tcl_DStringFree(&retr.buf);\n    return retr.result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelPropProc --\n *\n *\tThis function is invoked when property-change events occur on windows\n *\tnot known to the toolkit. Its function is to implement the sending\n *\tside of the INCR selection retrieval protocol when the selection\n *\trequestor deletes the property containing a part of the selection.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf the property that is receiving the selection was just deleted, then\n *\ta new piece of the selection is fetched and placed in the property,\n *\tuntil eventually there's no more selection to fetch.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelPropProc(\n    XEvent *eventPtr)\t/* X PropertyChange event. */\n{\n    IncrInfo *incrPtr;\n    TkSelHandler *selPtr;\n    int length;\n    Tcl_Size numItems;\n    unsigned long i;\n    Atom target, formatType;\n    long buffer[TK_SEL_WORDS_AT_ONCE];\n    TkDisplay *dispPtr = TkGetDisplay(eventPtr->xany.display);\n    Tk_ErrorHandler errorHandler;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * See if this event announces the deletion of a property being used for\n     * an INCR transfer. If so, then add the next chunk of data to the\n     * property.\n     */\n\n    if (eventPtr->xproperty.state != PropertyDelete) {\n\treturn;\n    }\n    for (incrPtr = tsdPtr->pendingIncrs; incrPtr != NULL;\n\t    incrPtr = incrPtr->nextPtr) {\n\tif (incrPtr->reqWindow != eventPtr->xproperty.window) {\n\t    continue;\n\t}\n\n\t/*\n\t * For each conversion that has been requested, handle any chunks that\n\t * haven't been transmitted yet.\n\t */\n\n\tfor (i = 0; i < incrPtr->numConversions; i++) {\n\t    if ((eventPtr->xproperty.atom != incrPtr->multAtoms[2*i + 1])\n\t\t    || (incrPtr->converts[i].offset == -1)) {\n\t\tcontinue;\n\t    }\n\t    target = incrPtr->multAtoms[2*i];\n\t    incrPtr->idleTime = 0;\n\n\t    /*\n\t     * Look for a matching selection handler.\n\t     */\n\n\t    for (selPtr = incrPtr->winPtr->selHandlerList; ;\n\t\t    selPtr = selPtr->nextPtr) {\n\t\tif (selPtr == NULL) {\n\t\t    /*\n\t\t     * No handlers match, so mark the conversion as done.\n\t\t     */\n\n\t\t    incrPtr->multAtoms[2*i + 1] = None;\n\t\t    incrPtr->converts[i].offset = -1;\n\t\t    incrPtr->numIncrs --;\n\t\t    return;\n\t\t}\n\t\tif ((selPtr->target == target)\n\t\t\t&& (selPtr->selection == incrPtr->selection)) {\n\t\t    break;\n\t\t}\n\t    }\n\n\t    /*\n\t     * We found a handler, so get the next chunk from it.\n\t     */\n\n\t    formatType = selPtr->format;\n\t    if (incrPtr->converts[i].offset == -2) {\n\t\t/*\n\t\t * We already got the last chunk, so send a null chunk to\n\t\t * indicate that we are finished.\n\t\t */\n\n\t\tnumItems = 0;\n\t\tlength = 0;\n\t    } else {\n\t\tTkSelInProgress ip;\n\n\t\tip.selPtr = selPtr;\n\t\tip.nextPtr = TkSelGetInProgress();\n\t\tTkSelSetInProgress(&ip);\n\n\t\t/*\n\t\t * Copy any bytes left over from a partial character at the\n\t\t * end of the previous chunk into the beginning of the buffer.\n\t\t * Pass the rest of the buffer space into the selection\n\t\t * handler.\n\t\t */\n\n\t\tlength = strlen(incrPtr->converts[i].buffer);\n\t\tstrcpy((char *)buffer, incrPtr->converts[i].buffer);\n\n\t\tnumItems = selPtr->proc(selPtr->clientData,\n\t\t\tincrPtr->converts[i].offset,\n\t\t\t((char *) buffer) + length,\n\t\t\tTK_SEL_BYTES_AT_ONCE - length);\n\t\tTkSelSetInProgress(ip.nextPtr);\n\t\tif (ip.selPtr == NULL) {\n\t\t    /*\n\t\t     * The selection handler deleted itself.\n\t\t     */\n\n\t\t    return;\n\t\t}\n\t\tif (numItems == TCL_INDEX_NONE) {\n\t\t    numItems = 0;\n\t\t}\n\t\tnumItems += length;\n\t\tif (numItems > TK_SEL_BYTES_AT_ONCE) {\n\t\t    Tcl_Panic(\"selection handler returned too many bytes\");\n\t\t}\n\t    }\n\t    ((char *) buffer)[numItems] = 0;\n\n\t    errorHandler = Tk_CreateErrorHandler(eventPtr->xproperty.display,\n\t\t    -1, -1, -1, NULL, NULL);\n\n\t    /*\n\t     * Encode the data using the proper format for each type.\n\t     */\n\n\t    if ((formatType == XA_STRING)\n\t\t    || (dispPtr && formatType==dispPtr->utf8Atom)\n\t\t    || (dispPtr && formatType==dispPtr->compoundTextAtom)) {\n\t\tTcl_DString ds;\n\t\tint encodingCvtFlags;\n\t\tint srcLen, dstLen, result, srcRead, dstWrote, soFar;\n\t\tchar *src, *dst;\n\t\tTcl_Encoding encoding;\n\n\t\t/*\n\t\t * Set up the encoding state based on the format and whether\n\t\t * this is the first and/or last chunk.\n\t\t */\n\n\t\tencodingCvtFlags = TCL_ENCODING_PROFILE_TCL8;\n\t\tif (incrPtr->converts[i].offset == 0) {\n\t\t    encodingCvtFlags |= TCL_ENCODING_START;\n\t\t}\n\t\tif (numItems < TK_SEL_BYTES_AT_ONCE) {\n\t\t    encodingCvtFlags |= TCL_ENCODING_END;\n\t\t}\n\t\tif (formatType == XA_STRING) {\n\t\t    encoding = Tcl_GetEncoding(NULL, \"iso8859-1\");\n\t\t} else if (dispPtr && formatType==dispPtr->utf8Atom) {\n\t\t    encoding = Tcl_GetEncoding(NULL, \"utf-8\");\n\t\t} else {\n\t\t    encoding = Tcl_GetEncoding(NULL, \"iso2022\");\n\t\t}\n\n\t\t/*\n\t\t * Now convert the data.\n\t\t */\n\n\t\tsrc = (char *)buffer;\n\t\tsrcLen = numItems;\n\t\tTcl_DStringInit(&ds);\n\t\tdst = Tcl_DStringValue(&ds);\n\t\tdstLen = ds.spaceAvl - 1;\n\n\n\t\t/*\n\t\t * Now convert the data, growing the destination buffer as\n\t\t * needed.\n\t\t */\n\n\t\twhile (1) {\n\t\t    result = Tcl_UtfToExternal(NULL, encoding, src, srcLen,\n\t\t\t    encodingCvtFlags, &incrPtr->converts[i].state,\n\t\t\t    dst, dstLen, &srcRead, &dstWrote, NULL);\n\t\t    soFar = dst + dstWrote - Tcl_DStringValue(&ds);\n\t\t    encodingCvtFlags &= ~TCL_ENCODING_START;\n\t\t    src += srcRead;\n\t\t    srcLen -= srcRead;\n\t\t    if (result != TCL_CONVERT_NOSPACE) {\n\t\t\tTcl_DStringSetLength(&ds, soFar);\n\t\t\tbreak;\n\t\t    }\n\t\t    if (Tcl_DStringLength(&ds) == 0) {\n\t\t\tTcl_DStringSetLength(&ds, dstLen);\n\t\t    }\n\t\t    Tcl_DStringSetLength(&ds, 2 * Tcl_DStringLength(&ds) + 1);\n\t\t    dst = Tcl_DStringValue(&ds) + soFar;\n\t\t    dstLen = Tcl_DStringLength(&ds) - soFar - 1;\n\t\t}\n\t\tTcl_DStringSetLength(&ds, soFar);\n\n\t\tif (encoding) {\n\t\t    Tcl_FreeEncoding(encoding);\n\t\t}\n\n\t\t/*\n\t\t * Set the property to the encoded string value.\n\t\t */\n\n\t\tXChangeProperty(eventPtr->xproperty.display,\n\t\t\teventPtr->xproperty.window, eventPtr->xproperty.atom,\n\t\t\tformatType, 8, PropModeReplace,\n\t\t\t(unsigned char *) Tcl_DStringValue(&ds),\n\t\t\tTcl_DStringLength(&ds));\n\n\t\t/*\n\t\t * Preserve any left-over bytes.\n\t\t */\n\n\t\tif (srcLen > 3) {\n\t\t    Tcl_Panic(\"selection conversion left too many bytes unconverted\");\n\t\t}\n\t\tmemcpy(incrPtr->converts[i].buffer, src, srcLen + 1);\n\t\tTcl_DStringFree(&ds);\n\t    } else {\n\t\t/*\n\t\t * Set the property to the encoded string value.\n\t\t */\n\n\t\tchar *propPtr = (char *) SelCvtToX((char *) buffer,\n\t\t\tformatType, (Tk_Window) incrPtr->winPtr, &numItems);\n\n\t\tif (propPtr == NULL) {\n\t\t    numItems = 0;\n\t\t}\n\t\tXChangeProperty(eventPtr->xproperty.display,\n\t\t\teventPtr->xproperty.window, eventPtr->xproperty.atom,\n\t\t\tformatType, 32, PropModeReplace,\n\t\t\t(unsigned char *) propPtr, numItems);\n\t\tif (propPtr != NULL) {\n\t\t    Tcl_Free(propPtr);\n\t\t}\n\t    }\n\t    Tk_DeleteErrorHandler(errorHandler);\n\n\t    /*\n\t     * Compute the next offset value. If this was the last chunk, then\n\t     * set the offset to -2. If this was an empty chunk, then set the\n\t     * offset to -1 to indicate we are done.\n\t     */\n\n\t    if (numItems < TK_SEL_BYTES_AT_ONCE) {\n\t\tif (numItems < 1) {\n\t\t    incrPtr->converts[i].offset = -1;\n\t\t    incrPtr->numIncrs--;\n\t\t} else {\n\t\t    incrPtr->converts[i].offset = -2;\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * Advance over the selection data that was consumed this\n\t\t * time.\n\t\t */\n\n\t\tincrPtr->converts[i].offset += numItems - length;\n\t    }\n\t    return;\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkSelEventProc --\n *\n *\tThis function is invoked whenever a selection-related event occurs.\n *\tIt does the lion's share of the work in implementing the selection\n *\tprotocol.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLots: depends on the type of event.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkSelEventProc(\n    Tk_Window tkwin,\t\t/* Window for which event was targeted. */\n    XEvent *eventPtr)\t/* X event: either SelectionClear,\n\t\t\t\t * SelectionRequest, or SelectionNotify. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    Tcl_Interp *interp;\n\n    /*\n     * Case #1: SelectionClear events.\n     */\n\n    if (eventPtr->type == SelectionClear) {\n\tTkSelClearSelection(tkwin, eventPtr);\n    }\n\n    /*\n     * Case #2: SelectionNotify events. Call the relevant function to handle\n     * the incoming selection.\n     */\n\n    if (eventPtr->type == SelectionNotify) {\n\tTkSelRetrievalInfo *retrPtr;\n\tchar *propInfo, **propInfoPtr = &propInfo;\n\tAtom type;\n\tint format, result;\n\tunsigned long numItems, bytesAfter;\n\n\tfor (retrPtr = pendingRetrievals; ; retrPtr = retrPtr->nextPtr) {\n\t    if (retrPtr == NULL) {\n\t\treturn;\n\t    }\n\t    if ((retrPtr->winPtr == winPtr)\n\t\t    && (retrPtr->selection == eventPtr->xselection.selection)\n\t\t    && (retrPtr->target == eventPtr->xselection.target)\n\t\t    && (retrPtr->result == -1)) {\n\t\tif (retrPtr->property == eventPtr->xselection.property) {\n\t\t    break;\n\t\t}\n\t\tif (eventPtr->xselection.property == None) {\n\t\t    Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t\t    \"%s selection doesn't exist or form \\\"%s\\\" not defined\",\n\t\t\t    Tk_GetAtomName(tkwin, retrPtr->selection),\n\t\t\t    Tk_GetAtomName(tkwin, retrPtr->target)));\n\t\t    Tcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\",\n\t\t\t    \"NONE\", NULL);\n\t\t    retrPtr->result = TCL_ERROR;\n\t\t    return;\n\t\t}\n\t    }\n\t}\n\n\tpropInfo = NULL;\n\tresult = XGetWindowProperty(eventPtr->xselection.display,\n\t\teventPtr->xselection.requestor, retrPtr->property,\n\t\t0, MAX_PROP_WORDS, False, (Atom) AnyPropertyType,\n\t\t&type, &format, &numItems, &bytesAfter,\n\t\t(unsigned char **) propInfoPtr);\n\tif ((result != Success) || (type == None)) {\n\t    return;\n\t}\n\tif (bytesAfter != 0) {\n\t    Tcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj(\n\t\t    \"selection property too large\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"SIZE\", (char *)NULL);\n\t    retrPtr->result = TCL_ERROR;\n\t    XFree(propInfo);\n\t    return;\n\t}\n\tif ((type == XA_STRING) || (type == dispPtr->textAtom)\n\t\t|| (type == dispPtr->compoundTextAtom)) {\n\t    Tcl_Encoding encoding;\n\t\tTcl_DString ds;\n\n\t    if (format != 8) {\n\t\tTcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t\t\"bad format for string selection: wanted \\\"8\\\", got \\\"%d\\\"\",\n\t\t\tformat));\n\t\tTcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"FORMAT\",\n\t\t\tNULL);\n\t\tretrPtr->result = TCL_ERROR;\n\t\treturn;\n\t    }\n\t    interp = retrPtr->interp;\n\t    Tcl_Preserve(interp);\n\n\t    /*\n\t     * Convert the X selection data into UTF before passing it to the\n\t     * selection callback. Note that the COMPOUND_TEXT uses a modified\n\t     * iso2022 encoding, not the current system encoding. For now\n\t     * we'll just blindly apply the iso2022 encoding. This is probably\n\t     * wrong, but it's a placeholder until we figure out what we're\n\t     * really supposed to do. For STRING, we need to use Latin-1\n\t     * instead. Again, it's not really the full iso8859-1 space, but\n\t     * this is close enough.\n\t     */\n\n\t    if (type == dispPtr->compoundTextAtom) {\n\t\tencoding = Tcl_GetEncoding(NULL, \"iso2022\");\n\t    } else {\n\t\tencoding = Tcl_GetEncoding(NULL, \"iso8859-1\");\n\t    }\n\t    char *str = Tcl_ExternalToUtfDString(encoding, propInfo, numItems, &ds);\n\t    if (encoding) {\n\t\tTcl_FreeEncoding(encoding);\n\t    }\n\n\t    retrPtr->result = retrPtr->proc(retrPtr->clientData, interp, str);\n\t    Tcl_DStringFree(&ds);\n\t    Tcl_Release(interp);\n\t} else if (type == dispPtr->utf8Atom) {\n\t    /*\n\t     * The X selection data is in UTF-8 format already. We can't\n\t     * guarantee that propInfo is NULL-terminated, so we might have to\n\t     * copy the string.\n\t     */\n\n\t    char *propData = propInfo;\n\n\t    if (format != 8) {\n\t\tTcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t\t\"bad format for string selection: wanted \\\"8\\\", got \\\"%d\\\"\",\n\t\t\tformat));\n\t\tTcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"FORMAT\",\n\t\t\tNULL);\n\t\tretrPtr->result = TCL_ERROR;\n\t\treturn;\n\t    }\n\n\t    if (propInfo[numItems] != '\\0') {\n\t\tpropData = (char *)Tcl_Alloc(numItems + 1);\n\t\tstrcpy(propData, propInfo);\n\t\tpropData[numItems] = '\\0';\n\t    }\n\t    retrPtr->result = retrPtr->proc(retrPtr->clientData,\n\t\t    retrPtr->interp, propData);\n\t    if (propData != propInfo) {\n\t\tTcl_Free(propData);\n\t    }\n\n\t} else if (type == dispPtr->incrAtom) {\n\t    /*\n\t     * It's a !?#@!?!! INCR-style reception. Arrange to receive the\n\t     * selection in pieces, using the ICCCM protocol, then hang around\n\t     * until either the selection is all here or a timeout occurs.\n\t     */\n\n\t    retrPtr->idleTime = 0;\n\t    Tk_CreateEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc,\n\t\t    retrPtr);\n\t    XDeleteProperty(Tk_Display(tkwin), Tk_WindowId(tkwin),\n\t\t    retrPtr->property);\n\t    while (retrPtr->result == -1) {\n\t\tTcl_DoOneEvent(0);\n\t    }\n\t    Tk_DeleteEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc,\n\t\t    retrPtr);\n\t} else {\n\t    Tcl_DString ds;\n\n\t    if (format != 32 && format != 8) {\n\t\tTcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t\t\"bad format for selection: wanted \\\"32\\\" or \"\n\t\t\t\"\\\"8\\\", got \\\"%d\\\"\", format));\n\t\tTcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"FORMAT\",\n\t\t\tNULL);\n\t\tretrPtr->result = TCL_ERROR;\n\t\treturn;\n\t    }\n\t    Tcl_DStringInit(&ds);\n\t    if (format == 32) {\n\t\tSelCvtFromX32((long *) propInfo, numItems, type,\n\t\t\t(Tk_Window) winPtr, &ds);\n\t    } else {\n\t\tSelCvtFromX8((char *) propInfo, numItems, type,\n\t\t\t(Tk_Window) winPtr, &ds);\n\t    }\n\t    interp = retrPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    retrPtr->result = retrPtr->proc(retrPtr->clientData,\n\t\t    interp, Tcl_DStringValue(&ds));\n\t    Tcl_Release(interp);\n\t    Tcl_DStringFree(&ds);\n\t}\n\tXFree(propInfo);\n\treturn;\n    }\n\n    /*\n     * Case #3: SelectionRequest events. Call ConvertSelection to do the dirty\n     * work.\n     */\n\n    if (eventPtr->type == SelectionRequest) {\n\tConvertSelection(winPtr, &eventPtr->xselectionrequest);\n\treturn;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SelTimeoutProc --\n *\n *\tThis function is invoked once every second while waiting for the\n *\tselection to be returned. After a while it gives up and aborts the\n *\tselection retrieval.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new timer callback is created to call us again in another second,\n *\tunless time has expired, in which case an error is recorded for the\n *\tretrieval.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSelTimeoutProc(\n    void *clientData)\t/* Information about retrieval in progress. */\n{\n    TkSelRetrievalInfo *retrPtr = (TkSelRetrievalInfo *)clientData;\n\n    /*\n     * Make sure that the retrieval is still in progress. Then see how long\n     * it's been since any sort of response was received from the other side.\n     */\n\n    if (retrPtr->result != -1) {\n\treturn;\n    }\n    retrPtr->idleTime++;\n    if (retrPtr->idleTime >= 5) {\n\t/*\n\t * Use a careful function to store the error message, because the\n\t * result could already be partially filled in with a partial\n\t * selection return.\n\t */\n\n\tTcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj(\n\t\t\"selection owner didn't respond\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"IGNORED\", (char *)NULL);\n\tretrPtr->result = TCL_ERROR;\n    } else {\n\tretrPtr->timeout = Tcl_CreateTimerHandler(1000, SelTimeoutProc,\n\t\tretrPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConvertSelection --\n *\n *\tThis function is invoked to handle SelectionRequest events. It\n *\tresponds to the requests, obeying the ICCCM protocols.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties are created for the selection requestor, and a\n *\tSelectionNotify event is generated for the selection requestor. In the\n *\tevent of long selections, this function implements INCR-mode\n *\ttransfers, using the ICCCM protocol.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConvertSelection(\n    TkWindow *winPtr,\t\t/* Window that received the conversion\n\t\t\t\t * request; may not be selection's current\n\t\t\t\t * owner, be we set it to the current\n\t\t\t\t * owner. */\n    XSelectionRequestEvent *eventPtr)\n\t\t\t\t/* Event describing request. */\n{\n\tunion {\n\t\tXSelectionEvent xsel;\n\t\tXEvent ev;\n\t} reply;\t/* Used to notify requestor that selection\n\t\t\t\t * info is ready. */\n    int multiple;\t\t/* Non-zero means a MULTIPLE request is being\n\t\t\t\t * handled. */\n    IncrInfo incr;\t\t/* State of selection conversion. */\n    Atom singleInfo[2];\t\t/* incr.multAtoms points here except for\n\t\t\t\t * multiple conversions. */\n    unsigned long i;\n    Tk_ErrorHandler errorHandler;\n    TkSelectionInfo *infoPtr;\n    TkSelInProgress ip;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    errorHandler = Tk_CreateErrorHandler(eventPtr->display, -1, -1,\n\t    -1, NULL, NULL);\n\n    /*\n     * Initialize the reply event.\n     */\n\n    reply.xsel.type = SelectionNotify;\n    reply.xsel.serial = 0;\n    reply.xsel.send_event = True;\n    reply.xsel.display = eventPtr->display;\n    reply.xsel.requestor = eventPtr->requestor;\n    reply.xsel.selection = eventPtr->selection;\n    reply.xsel.target = eventPtr->target;\n    reply.xsel.property = eventPtr->property;\n    if (reply.xsel.property == None) {\n\treply.xsel.property = reply.xsel.target;\n    }\n    reply.xsel.time = eventPtr->time;\n\n    for (infoPtr = winPtr->dispPtr->selectionInfoPtr; infoPtr != NULL;\n\t    infoPtr = infoPtr->nextPtr) {\n\tif (infoPtr->selection == eventPtr->selection) {\n\t    break;\n\t}\n    }\n    if (infoPtr == NULL) {\n\tgoto refuse;\n    }\n    winPtr = (TkWindow *) infoPtr->owner;\n\n    /*\n     * Figure out which kind(s) of conversion to perform. If handling a\n     * MULTIPLE conversion, then read the property describing which\n     * conversions to perform.\n     */\n\n    incr.winPtr = winPtr;\n    incr.selection = eventPtr->selection;\n    if (eventPtr->target != winPtr->dispPtr->multipleAtom) {\n\tmultiple = 0;\n\tsingleInfo[0] = reply.xsel.target;\n\tsingleInfo[1] = reply.xsel.property;\n\tincr.multAtoms = singleInfo;\n\tincr.numConversions = 1;\n    } else {\n\tAtom type, **multAtomsPtr = &incr.multAtoms;\n\tint format, result;\n\tunsigned long bytesAfter;\n\n\tmultiple = 1;\n\tincr.multAtoms = NULL;\n\tif (eventPtr->property == None) {\n\t    goto refuse;\n\t}\n\tresult = XGetWindowProperty(eventPtr->display, eventPtr->requestor,\n\t\teventPtr->property, 0, MAX_PROP_WORDS, False,\n\t\twinPtr->dispPtr->atomPairAtom, &type, &format,\n\t\t&incr.numConversions, &bytesAfter,\n\t\t(unsigned char **) multAtomsPtr);\n\tif ((result != Success) || (bytesAfter != 0) || (format != 32)\n\t\t|| (type == None)) {\n\t    if (incr.multAtoms != NULL) {\n\t\tXFree(incr.multAtoms);\n\t    }\n\t    goto refuse;\n\t}\n\tincr.numConversions /= 2;\t/* Two atoms per conversion. */\n    }\n\n    /*\n     * Loop through all of the requested conversions, and either return the\n     * entire converted selection, if it can be returned in a single bunch, or\n     * return INCR information only (the actual selection will be returned\n     * below).\n     */\n\n    incr.converts = (ConvertInfo *)Tcl_Alloc(incr.numConversions * sizeof(ConvertInfo));\n    incr.numIncrs = 0;\n    for (i = 0; i < incr.numConversions; i++) {\n\tAtom target, property, type;\n\tlong buffer[TK_SEL_WORDS_AT_ONCE];\n\tTkSelHandler *selPtr;\n\tTcl_Size numItems;\n\tint format;\n\tchar *propPtr;\n\n\ttarget = incr.multAtoms[2*i];\n\tproperty = incr.multAtoms[2*i + 1];\n\tincr.converts[i].offset = -1;\n\tincr.converts[i].buffer[0] = '\\0';\n\n\tfor (selPtr = winPtr->selHandlerList; selPtr != NULL;\n\t\tselPtr = selPtr->nextPtr) {\n\t    if ((selPtr->target == target)\n\t\t    && (selPtr->selection == eventPtr->selection)) {\n\t\tbreak;\n\t    }\n\t}\n\n\tif (selPtr == NULL) {\n\t    /*\n\t     * Nobody seems to know about this kind of request. If it's of a\n\t     * sort that we can handle without any help, do it. Otherwise mark\n\t     * the request as an error.\n\t     */\n\n\t    numItems = TkSelDefaultSelection(infoPtr, target, (char *) buffer,\n\t\t    TK_SEL_BYTES_AT_ONCE, &type);\n\t    if (numItems == TCL_INDEX_NONE) {\n\t\tincr.multAtoms[2*i + 1] = None;\n\t\tcontinue;\n\t    }\n\t} else {\n\t    ip.selPtr = selPtr;\n\t    ip.nextPtr = TkSelGetInProgress();\n\t    TkSelSetInProgress(&ip);\n\t    type = selPtr->format;\n\t    numItems = selPtr->proc(selPtr->clientData, 0, (char *) buffer,\n\t\t    TK_SEL_BYTES_AT_ONCE);\n\t    TkSelSetInProgress(ip.nextPtr);\n\t    if ((ip.selPtr == NULL) || (numItems == TCL_INDEX_NONE)) {\n\t\tincr.multAtoms[2*i + 1] = None;\n\t\tcontinue;\n\t    }\n\t    if (numItems > TK_SEL_BYTES_AT_ONCE) {\n\t\tTcl_Panic(\"selection handler returned too many bytes\");\n\t    }\n\t    ((char *) buffer)[numItems] = '\\0';\n\t}\n\n\t/*\n\t * Got the selection; store it back on the requestor's property.\n\t */\n\n\tif (numItems == TK_SEL_BYTES_AT_ONCE) {\n\t    /*\n\t     * Selection is too big to send at once; start an INCR-mode\n\t     * transfer.\n\t     */\n\n\t    incr.numIncrs++;\n\t    type = winPtr->dispPtr->incrAtom;\n\t    buffer[0] = SelectionSize(selPtr);\n\t    if (buffer[0] == 0) {\n\t\tincr.multAtoms[2*i + 1] = None;\n\t\tcontinue;\n\t    }\n\t    numItems = 1;\n\t    propPtr = (char *) buffer;\n\t    format = 32;\n\t    incr.converts[i].offset = 0;\n\t    XChangeProperty(reply.xsel.display, reply.xsel.requestor,\n\t\t    property, type, format, PropModeReplace,\n\t\t    (unsigned char *) propPtr, numItems);\n\t} else if (type == winPtr->dispPtr->utf8Atom) {\n\t    /*\n\t     * This matches selection requests of type UTF8_STRING, which\n\t     * allows us to pass our utf-8 information untouched.\n\t     */\n\n\t    XChangeProperty(reply.xsel.display, reply.xsel.requestor,\n\t\t    property, type, 8, PropModeReplace,\n\t\t    (unsigned char *) buffer, numItems);\n\t} else if ((type == XA_STRING)\n\t\t|| (type == winPtr->dispPtr->compoundTextAtom)) {\n\t    Tcl_DString ds;\n\t    Tcl_Encoding encoding;\n\n\t    /*\n\t     * STRING is Latin-1, COMPOUND_TEXT is an iso2022 variant. We need\n\t     * to convert the selection text into these external forms before\n\t     * modifying the property.\n\t     */\n\n\t    if (type == XA_STRING) {\n\t\tencoding = Tcl_GetEncoding(NULL, \"iso8859-1\");\n\t    } else {\n\t\tencoding = Tcl_GetEncoding(NULL, \"iso2022\");\n\t    }\n\t    unsigned char *str = (unsigned char *)Tcl_UtfToExternalDString(encoding,\n\t\t    (char *) buffer, TCL_INDEX_NONE, &ds);\n\t    XChangeProperty(reply.xsel.display, reply.xsel.requestor,\n\t\t    property, type, 8, PropModeReplace, str,\n\t\t    Tcl_DStringLength(&ds));\n\t    if (encoding) {\n\t\tTcl_FreeEncoding(encoding);\n\t    }\n\t    Tcl_DStringFree(&ds);\n\t} else {\n\t    propPtr = (char *) SelCvtToX((char *) buffer,\n\t\t    type, (Tk_Window) winPtr, &numItems);\n\t    if (propPtr == NULL) {\n\t\tgoto refuse;\n\t    }\n\t    format = 32;\n\t    XChangeProperty(reply.xsel.display, reply.xsel.requestor,\n\t\t    property, type, format, PropModeReplace,\n\t\t    (unsigned char *) propPtr, numItems);\n\t    Tcl_Free(propPtr);\n\t}\n    }\n\n    /*\n     * Send an event back to the requestor to indicate that the first stage of\n     * conversion is complete (everything is done except for long conversions\n     * that have to be done in INCR mode).\n     */\n\n    if (incr.numIncrs > 0) {\n\tXSelectInput(reply.xsel.display, reply.xsel.requestor,\n\t\tPropertyChangeMask);\n\tincr.timeout = Tcl_CreateTimerHandler(1000, IncrTimeoutProc, &incr);\n\tincr.idleTime = 0;\n\tincr.reqWindow = reply.xsel.requestor;\n\tincr.time = infoPtr->time;\n\tincr.nextPtr = tsdPtr->pendingIncrs;\n\ttsdPtr->pendingIncrs = &incr;\n    }\n    if (multiple) {\n\tXChangeProperty(reply.xsel.display, reply.xsel.requestor,\n\t\treply.xsel.property, winPtr->dispPtr->atomPairAtom,\n\t\t32, PropModeReplace, (unsigned char *) incr.multAtoms,\n\t\tincr.numConversions*2);\n    } else {\n\t/*\n\t * Not a MULTIPLE request. The first property in \"multAtoms\" got set\n\t * to None if there was an error in conversion.\n\t */\n\n\treply.xsel.property = incr.multAtoms[1];\n    }\n    XSendEvent(reply.xsel.display, reply.xsel.requestor, False, 0, &reply.ev);\n    Tk_DeleteErrorHandler(errorHandler);\n\n    /*\n     * Handle any remaining INCR-mode transfers. This all happens in callbacks\n     * to TkSelPropProc, so just wait until the number of uncompleted INCR\n     * transfers drops to zero.\n     */\n\n    if (incr.numIncrs > 0) {\n\tIncrInfo *incrPtr2;\n\n\twhile (incr.numIncrs > 0) {\n\t    Tcl_DoOneEvent(0);\n\t}\n\tTcl_DeleteTimerHandler(incr.timeout);\n\terrorHandler = Tk_CreateErrorHandler(winPtr->display,\n\t\t-1, -1, -1, NULL, NULL);\n\tXSelectInput(reply.xsel.display, reply.xsel.requestor, 0L);\n\tTk_DeleteErrorHandler(errorHandler);\n\tif (tsdPtr->pendingIncrs == &incr) {\n\t    tsdPtr->pendingIncrs = incr.nextPtr;\n\t} else {\n\t    for (incrPtr2 = tsdPtr->pendingIncrs; incrPtr2 != NULL;\n\t\t    incrPtr2 = incrPtr2->nextPtr) {\n\t\tif (incrPtr2->nextPtr == &incr) {\n\t\t    incrPtr2->nextPtr = incr.nextPtr;\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * All done. Cleanup and return.\n     */\n\n    Tcl_Free(incr.converts);\n    if (multiple) {\n\tXFree(incr.multAtoms);\n    }\n    return;\n\n    /*\n     * An error occurred. Send back a refusal message.\n     */\n\n  refuse:\n    reply.xsel.property = None;\n    XSendEvent(reply.xsel.display, reply.xsel.requestor, False, 0, &reply.ev);\n    Tk_DeleteErrorHandler(errorHandler);\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SelRcvIncrProc --\n *\n *\tThis function handles the INCR protocol on the receiving side. It is\n *\tinvoked in response to property changes on the requestor's window\n *\t(which hopefully are because a new chunk of the selection arrived).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf a new piece of selection has arrived, a function is invoked to deal\n *\twith that piece. When the whole selection is here, a flag is left for\n *\tthe higher-level function that initiated the selection retrieval.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSelRcvIncrProc(\n    void *clientData,\t/* Information about retrieval. */\n    XEvent *eventPtr)\t/* X PropertyChange event. */\n{\n    TkSelRetrievalInfo *retrPtr = (TkSelRetrievalInfo *)clientData;\n    char *propInfo, **propInfoPtr = &propInfo;\n    Atom type;\n    int format, result;\n    unsigned long numItems, bytesAfter;\n    Tcl_Interp *interp;\n\n    if ((eventPtr->xproperty.atom != retrPtr->property)\n\t    || (eventPtr->xproperty.state != PropertyNewValue)\n\t    || (retrPtr->result != -1)) {\n\treturn;\n    }\n    propInfo = NULL;\n    result = XGetWindowProperty(eventPtr->xproperty.display,\n\t    eventPtr->xproperty.window, retrPtr->property, 0, MAX_PROP_WORDS,\n\t    True, (Atom) AnyPropertyType, &type, &format, &numItems,\n\t    &bytesAfter, (unsigned char **) propInfoPtr);\n    if ((result != Success) || (type == None)) {\n\treturn;\n    }\n    if (bytesAfter != 0) {\n\tTcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj(\n\t\t\"selection property too large\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"SIZE\", (char *)NULL);\n\tretrPtr->result = TCL_ERROR;\n\tgoto done;\n    }\n    if ((type == XA_STRING)\n\t    || (type == retrPtr->winPtr->dispPtr->textAtom)\n\t    || (type == retrPtr->winPtr->dispPtr->utf8Atom)\n\t    || (type == retrPtr->winPtr->dispPtr->compoundTextAtom)) {\n\tchar *dst, *src;\n\tint srcLen, dstLen, srcRead, dstWrote, soFar;\n\tTcl_Encoding encoding;\n\tTcl_DString *dstPtr, temp;\n\n\tif (format != 8) {\n\t    Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t    \"bad format for string selection: wanted \\\"8\\\", got \\\"%d\\\"\",\n\t\t    format));\n\t    Tcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"FORMAT\",\n\t\t    NULL);\n\t    retrPtr->result = TCL_ERROR;\n\t    goto done;\n\t}\n\tinterp = retrPtr->interp;\n\tTcl_Preserve(interp);\n\n\tif (type == retrPtr->winPtr->dispPtr->compoundTextAtom) {\n\t    encoding = Tcl_GetEncoding(NULL, \"iso2022\");\n\t} else if (type == retrPtr->winPtr->dispPtr->utf8Atom) {\n\t    encoding = Tcl_GetEncoding(NULL, \"utf-8\");\n\t} else {\n\t    encoding = Tcl_GetEncoding(NULL, \"iso8859-1\");\n\t}\n\n\t/*\n\t * Check to see if there is any data left over from the previous\n\t * chunk. If there is, copy the old data and the new data into a new\n\t * buffer.\n\t */\n\n\tTcl_DStringInit(&temp);\n\tif (Tcl_DStringLength(&retrPtr->buf) > 0) {\n\t    Tcl_DStringAppend(&temp, Tcl_DStringValue(&retrPtr->buf),\n\t\t    Tcl_DStringLength(&retrPtr->buf));\n\t    if (numItems > 0) {\n\t\tTcl_DStringAppend(&temp, propInfo, (int)numItems);\n\t    }\n\t    src = Tcl_DStringValue(&temp);\n\t    srcLen = Tcl_DStringLength(&temp);\n\t} else if (numItems == 0) {\n\t    /*\n\t     * There is no new data, so we're done.\n\t     */\n\n\t    retrPtr->result = TCL_OK;\n\t    Tcl_Release(interp);\n\t    goto done;\n\t} else {\n\t    src = propInfo;\n\t    srcLen = numItems;\n\t}\n\n\t/*\n\t * Set up the destination buffer so we can use as much space as is\n\t * available.\n\t */\n\n\tdstPtr = &retrPtr->buf;\n\tdst = Tcl_DStringValue(dstPtr);\n\tdstLen = dstPtr->spaceAvl - 1;\n\n\t/*\n\t * Now convert the data, growing the destination buffer as needed.\n\t */\n\n\twhile (1) {\n\t    result = Tcl_ExternalToUtf(NULL, encoding, src, srcLen,\n\t\t    TCL_ENCODING_PROFILE_TCL8|retrPtr->encFlags,\n\t\t    &retrPtr->encState, dst, dstLen, &srcRead, &dstWrote, NULL);\n\t    soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);\n\t    retrPtr->encFlags &= ~TCL_ENCODING_START;\n\t    src += srcRead;\n\t    srcLen -= srcRead;\n\t    if (result != TCL_CONVERT_NOSPACE) {\n\t\tTcl_DStringSetLength(dstPtr, soFar);\n\t\tbreak;\n\t    }\n\t    if (Tcl_DStringLength(dstPtr) == 0) {\n\t\tTcl_DStringSetLength(dstPtr, dstLen);\n\t    }\n\t    Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1);\n\t    dst = Tcl_DStringValue(dstPtr) + soFar;\n\t    dstLen = Tcl_DStringLength(dstPtr) - soFar - 1;\n\t}\n\tTcl_DStringSetLength(dstPtr, soFar);\n\n\tresult = retrPtr->proc(retrPtr->clientData, interp,\n\t\tTcl_DStringValue(dstPtr));\n\tTcl_Release(interp);\n\n\t/*\n\t * Copy any unused data into the destination buffer so we can pick it\n\t * up next time around.\n\t */\n\n\tTcl_DStringSetLength(dstPtr, 0);\n\tTcl_DStringAppend(dstPtr, src, srcLen);\n\n\tTcl_DStringFree(&temp);\n\tif (encoding) {\n\t    Tcl_FreeEncoding(encoding);\n\t}\n\tif (result != TCL_OK) {\n\t    retrPtr->result = result;\n\t}\n    } else if (numItems == 0) {\n\tretrPtr->result = TCL_OK;\n    } else {\n\tTcl_DString ds;\n\n\tif (format != 32 && format != 8) {\n\t    Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(\n\t\t    \"bad format for selection: wanted \\\"32\\\" or \"\n\t\t    \"\\\"8\\\", got \\\"%d\\\"\", format));\n\t    Tcl_SetErrorCode(retrPtr->interp, \"TK\", \"SELECTION\", \"FORMAT\",\n\t\t    NULL);\n\t    retrPtr->result = TCL_ERROR;\n\t    goto done;\n\t}\n\tTcl_DStringInit(&ds);\n\tif (format == 32) {\n\t    SelCvtFromX32((long *) propInfo, numItems, type,\n\t\t    (Tk_Window) retrPtr->winPtr, &ds);\n\t} else {\n\t    SelCvtFromX8((char *) propInfo, numItems, type,\n\t\t    (Tk_Window) retrPtr->winPtr, &ds);\n\t}\n\tinterp = retrPtr->interp;\n\tTcl_Preserve(interp);\n\tresult = retrPtr->proc(retrPtr->clientData, interp,\n\t\tTcl_DStringValue(&ds));\n\tTcl_Release(interp);\n\tTcl_DStringFree(&ds);\n\tif (result != TCL_OK) {\n\t    retrPtr->result = result;\n\t}\n    }\n\n  done:\n    XFree(propInfo);\n    retrPtr->idleTime = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SelectionSize --\n *\n *\tThis function is called when the selection is too large to send in a\n *\tsingle buffer; it computes the total length of the selection in bytes.\n *\n * Results:\n *\tThe return value is the number of bytes in the selection given by\n *\tselPtr.\n *\n * Side effects:\n *\tThe selection is retrieved from its current owner (this is the only\n *\tway to compute its size).\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSelectionSize(\n    TkSelHandler *selPtr)\t/* Information about how to retrieve the\n\t\t\t\t * selection whose size is wanted. */\n{\n    char buffer[TK_SEL_BYTES_AT_ONCE+1];\n    int size, chunkSize;\n    TkSelInProgress ip;\n\n    size = TK_SEL_BYTES_AT_ONCE;\n    ip.selPtr = selPtr;\n    ip.nextPtr = TkSelGetInProgress();\n    TkSelSetInProgress(&ip);\n\n    do {\n\tchunkSize = selPtr->proc(selPtr->clientData, size, (char *) buffer,\n\t\tTK_SEL_BYTES_AT_ONCE);\n\tif (ip.selPtr == NULL) {\n\t    size = 0;\n\t    break;\n\t}\n\tsize += chunkSize;\n    } while (chunkSize == TK_SEL_BYTES_AT_ONCE);\n\n    TkSelSetInProgress(ip.nextPtr);\n    return size;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IncrTimeoutProc --\n *\n *\tThis function is invoked once a second while sending the selection to\n *\ta requestor in INCR mode. After a while it gives up and aborts the\n *\tselection operation.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA new timeout gets registered so that this function gets called again\n *\tin another second, unless too many seconds have elapsed, in which case\n *\tincrPtr is marked as \"all done\".\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nIncrTimeoutProc(\n    void *clientData)\t/* Information about INCR-mode selection\n\t\t\t\t * retrieval for which we are selection\n\t\t\t\t * owner. */\n{\n    IncrInfo *incrPtr = (IncrInfo *)clientData;\n\n    incrPtr->idleTime++;\n    if (incrPtr->idleTime >= 5) {\n\tincrPtr->numIncrs = 0;\n    } else {\n\tincrPtr->timeout = Tcl_CreateTimerHandler(1000, IncrTimeoutProc,\n\t\tincrPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SelCvtToX --\n *\n *\tGiven a selection represented as a string (the normal Tcl form),\n *\tconvert it to the ICCCM-mandated format for X, depending on the type\n *\targument. This function and SelCvtFromX are inverses.\n *\n * Results:\n *\tThe return value is a malloc'ed buffer holding a value equivalent to\n *\t\"string\", but formatted as for \"type\". It is the caller's\n *\tresponsibility to free the string when done with it. The word at\n *\t*numLongsPtr is filled in with the number of 32-bit words returned in\n *\tthe result. If NULL is returned, the input list was not actually a\n *\tlist.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic long *\nSelCvtToX(\n    char *string,\t\t/* String representation of selection. */\n    Atom type,\t\t\t/* Atom specifying the X format that is\n\t\t\t\t * desired for the selection. Should not be\n\t\t\t\t * XA_STRING (if so, don't bother calling this\n\t\t\t\t * function at all). */\n    Tk_Window tkwin,\t\t/* Window that governs atom conversion. */\n    Tcl_Size *numLongsPtr)\t\t/* Number of 32-bit words contained in the\n\t\t\t\t * result. */\n{\n    const char **field;\n    Tcl_Size numFields, i;\n    long *propPtr;\n\n    /*\n     * The string is assumed to consist of fields separated by spaces. The\n     * property gets generated by converting each field to an integer number,\n     * in one of two ways:\n     * 1. If type is XA_ATOM, convert each field to its corresponding atom.\n     * 2. If type is anything else, convert each field from an ASCII number to\n     *    a 32-bit binary number.\n     */\n\n    if (Tcl_SplitList(NULL, string, &numFields, &field) != TCL_OK) {\n\treturn NULL;\n    }\n    propPtr = (long *)Tcl_Alloc(numFields * sizeof(long));\n\n    /*\n     * Convert the fields one-by-one.\n     */\n\n    for (i=0 ; i<numFields ; i++) {\n\tif (type == XA_ATOM) {\n\t    propPtr[i] = (long) Tk_InternAtom(tkwin, field[i]);\n\t} else {\n\t    char *dummy;\n\n\t    /*\n\t     * If this fails to parse a number, we just plunge on regardless\n\t     * anyway.\n\t     */\n\n\t    propPtr[i] = strtol(field[i], &dummy, 0);\n\t}\n    }\n\n    /*\n     * Release the parsed list.\n     */\n\n    Tcl_Free(field);\n    *numLongsPtr = i;\n    return propPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SelCvtFromX32, SelCvtFromX8 --\n *\n *\tGiven an X property value, formatted as a collection of 32-bit or\n *\t8-bit values according to \"type\" and the ICCCM conventions, convert\n *\tthe value to a string suitable for manipulation by Tcl. These\n *\tfunctions are the inverse of SelCvtToX.\n *\n * Results:\n *\tThe return value (stored in a Tcl_DString) is the string equivalent of\n *\t\"property\". It is up to the caller to initialize and free the DString.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSelCvtFromX32(\n    long *propPtr,\t/* Property value from X. */\n    unsigned long numValues,\t\t/* Number of 32-bit values in property. */\n    Atom type,\t\t\t/* Type of property Should not be XA_STRING\n\t\t\t\t * (if so, don't bother calling this function\n\t\t\t\t * at all). */\n    Tk_Window tkwin,\t\t/* Window to use for atom conversion. */\n    Tcl_DString *dsPtr)\t\t/* Where to store the converted string. */\n{\n    /*\n     * Convert each long in the property to a string value, which is either\n     * the name of an atom (if type is XA_ATOM) or a hexadecimal string. We\n     * build the list in a Tcl_DString because this is easier than trying to\n     * get the quoting correct ourselves; this is tricky because atoms can\n     * contain spaces in their names (encountered when the atoms are really\n     * MIME types). [Bug 1353414]\n     */\n\n    for ( ; numValues > 0; propPtr++, numValues--) {\n\tif (type == XA_ATOM) {\n\t    Tcl_DStringAppendElement(dsPtr,\n\t\t    Tk_GetAtomName(tkwin, (Atom) *propPtr));\n\t} else {\n\t    char buf[12];\n\n\t    snprintf(buf, sizeof(buf), \"0x%x\", (unsigned int) *propPtr);\n\t    Tcl_DStringAppendElement(dsPtr, buf);\n\t}\n    }\n    Tcl_DStringAppend(dsPtr, \" \", 1);\n}\n\nstatic void\nSelCvtFromX8(\n    char *propPtr,\t/* Property value from X. */\n    unsigned long numValues,\t\t/* Number of 8-bit values in property. */\n    TCL_UNUSED(Atom),\t\t\t/* Type of property Should not be XA_STRING\n\t\t\t\t * (if so, don't bother calling this function\n\t\t\t\t * at all). */\n    TCL_UNUSED(Tk_Window),\t\t/* Window to use for atom conversion. */\n    Tcl_DString *dsPtr)\t\t/* Where to store the converted string. */\n{\n    /*\n     * Convert each long in the property to a string value, which is a\n     * hexadecimal string. We build the list in a Tcl_DString because this is\n     * easier than trying to get the quoting correct ourselves.\n     */\n\n    for ( ; numValues > 0; propPtr++, numValues--) {\n\tchar buf[12];\n\n\tsnprintf(buf, sizeof(buf), \"0x%x\", (unsigned char) *propPtr);\n\tTcl_DStringAppendElement(dsPtr, buf);\n    }\n    Tcl_DStringAppend(dsPtr, \" \", 1);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixSend.c",
    "content": "/*\n * tkUnixSend.c --\n *\n *\tThis file provides functions that implement the \"send\" command,\n *\tallowing commands to be passed from interpreter to interpreter.\n *\n * Copyright © 1989-1994 The Regents of the University of California.\n * Copyright © 1994-1996 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n/*\n * The following structure is used to keep track of the interpreters\n * registered by this process.\n */\n\ntypedef struct RegisteredInterp {\n    char *name;\t\t\t/* Interpreter's name (malloc-ed). */\n    Tcl_Interp *interp;\t\t/* Interpreter associated with name. NULL\n\t\t\t\t * means that the application was unregistered\n\t\t\t\t * or deleted while a send was in progress to\n\t\t\t\t * it. */\n    TkDisplay *dispPtr;\t\t/* Display for the application. Needed because\n\t\t\t\t * we may need to unregister the interpreter\n\t\t\t\t * after its main window has been deleted. */\n    struct RegisteredInterp *nextPtr;\n\t\t\t\t/* Next in list of names associated with\n\t\t\t\t * interps in this process. NULL means end of\n\t\t\t\t * list. */\n} RegisteredInterp;\n\n/*\n * A registry of all interpreters for a display is kept in a property\n * \"InterpRegistry\" on the root window of the display. It is organized as a\n * series of zero or more concatenated strings (in no particular order), each\n * of the form\n *\twindow space name '\\0'\n * where \"window\" is the hex id of the comm. window to use to talk to an\n * interpreter named \"name\".\n *\n * When the registry is being manipulated by an application (e.g. to add or\n * remove an entry), it is loaded into memory using a structure of the\n * following type:\n */\n\ntypedef struct NameRegistry {\n    TkDisplay *dispPtr;\t\t/* Display from which the registry was\n\t\t\t\t * read. */\n    int locked;\t\t\t/* Non-zero means that the display was locked\n\t\t\t\t * when the property was read in. */\n    int modified;\t\t/* Non-zero means that the property has been\n\t\t\t\t * modified, so it needs to be written out\n\t\t\t\t * when the NameRegistry is closed. */\n    unsigned long propLength;\t/* Length of the property, in bytes. */\n    char *property;\t\t/* The contents of the property, or NULL if\n\t\t\t\t * none. See format description above; this is\n\t\t\t\t * *not* terminated by the first null\n\t\t\t\t * character. Dynamically allocated. */\n    bool allocedByX;\t\t/* Non-zero means must free property with\n\t\t\t\t * XFree; zero means use Tcl_Free. */\n} NameRegistry;\n\n/*\n * When a result is being awaited from a sent command, one of the following\n * structures is present on a list of all outstanding sent commands. The\n * information in the structure is used to process the result when it arrives.\n * You're probably wondering how there could ever be multiple outstanding sent\n * commands. This could happen if interpreters invoke each other recursively.\n * It's unlikely, but possible.\n */\n\ntypedef struct PendingCommand {\n    int serial;\t\t\t/* Serial number expected in result. */\n    TkDisplay *dispPtr;\t\t/* Display being used for communication. */\n    const char *target;\t\t/* Name of interpreter command is being sent\n\t\t\t\t * to. */\n    Window commWindow;\t\t/* Target's communication window. */\n    Tcl_Interp *interp;\t\t/* Interpreter from which the send was\n\t\t\t\t * invoked. */\n    int code;\t\t\t/* Tcl return code for command will be stored\n\t\t\t\t * here. */\n    char *result;\t\t/* String result for command (malloc'ed), or\n\t\t\t\t * NULL. */\n    char *errorInfo;\t\t/* Information for \"errorInfo\" variable, or\n\t\t\t\t * NULL (malloc'ed). */\n    char *errorCode;\t\t/* Information for \"errorCode\" variable, or\n\t\t\t\t * NULL (malloc'ed). */\n    int gotResponse;\t\t/* 1 means a response has been received, 0\n\t\t\t\t * means the command is still outstanding. */\n    struct PendingCommand *nextPtr;\n\t\t\t\t/* Next in list of all outstanding commands.\n\t\t\t\t * NULL means end of list. */\n} PendingCommand;\n\ntypedef struct {\n    PendingCommand *pendingCommands;\n\t\t\t\t/* List of all commands currently being waited\n\t\t\t\t * for. */\n    RegisteredInterp *interpListPtr;\n\t\t\t\t/* List of all interpreters registered in the\n\t\t\t\t * current process. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The information below is used for communication between processes during\n * \"send\" commands. Each process keeps a private window, never even mapped,\n * with one property, \"Comm\". When a command is sent to an interpreter, the\n * command is appended to the comm property of the communication window\n * associated with the interp's process. Similarly, when a result is returned\n * from a sent command, it is also appended to the comm property.\n *\n * Each command and each result takes the form of ASCII text. For a command,\n * the text consists of a zero character followed by several null-terminated\n * ASCII strings. The first string consists of the single letter \"c\".\n * Subsequent strings have the form \"option value\" where the following options\n * are supported:\n *\n * -r commWindow serial\n *\n *\tThis option means that a response should be sent to the window whose X\n *\tidentifier is \"commWindow\" (in hex), and the response should be\n *\tidentified with the serial number given by \"serial\" (in decimal). If\n *\tthis option isn't specified then the send is asynchronous and no\n *\tresponse is sent.\n *\n * -n name\n *\n *\t\"Name\" gives the name of the application for which the command is\n *\tintended. This option must be present.\n *\n * -s script\n *\n *\t\"Script\" is the script to be executed. This option must be present.\n *\n * The options may appear in any order. The -n and -s options must be present,\n * but -r may be omitted for asynchronous RPCs. For compatibility with future\n * releases that may add new features, there may be additional options\n * present; as long as they start with a \"-\" character, they will be ignored.\n *\n * A result also consists of a zero character followed by several null-\n * terminated ASCII strings. The first string consists of the single letter\n * \"r\". Subsequent strings have the form \"option value\" where the following\n * options are supported:\n *\n * -s serial\n *\n *\tIdentifies the command for which this is the result. It is the same as\n *\tthe \"serial\" field from the -s option in the command. This option must\n *\tbe present.\n *\n * -c code\n *\n *\t\"Code\" is the completion code for the script, in decimal. If the code\n *\tis omitted it defaults to TCL_OK.\n *\n * -r result\n *\n *\t\"Result\" is the result string for the script, which may be either a\n *\tresult or an error message. If this field is omitted then it defaults\n *\tto an empty string.\n *\n * -i errorInfo\n *\n *\t\"ErrorInfo\" gives a string with which to initialize the errorInfo\n *\tvariable. This option may be omitted; it is ignored unless the\n *\tcompletion code is TCL_ERROR.\n *\n * -e errorCode\n *\n *\t\"ErrorCode\" gives a string with with to initialize the errorCode\n *\tvariable. This option may be omitted; it is ignored unless the\n *\tcompletion code is TCL_ERROR.\n *\n * Options may appear in any order, and only the -s option must be present. As\n * with commands, there may be additional options besides these; unknown\n * options are ignored.\n */\n\n/*\n * Other miscellaneous per-process data:\n */\n\nstatic struct {\n    int sendSerial;\t\t/* The serial number that was used in the last\n\t\t\t\t * \"send\" command. */\n    int sendDebug;\t\t/* This can be set while debugging to do\n\t\t\t\t * things like skip locking the server. */\n} localData = {0, 0};\n\n/*\n * Maximum size property that can be read at one time by this module:\n */\n\n#define MAX_PROP_WORDS 100000\n\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic int\t\tAppendErrorProc(void *clientData,\n\t\t\t    XErrorEvent *errorPtr);\nstatic void\t\tAppendPropCarefully(Display *display,\n\t\t\t    Window window, Atom property, char *value,\n\t\t\t    int length, PendingCommand *pendingPtr);\nstatic Tcl_CmdDeleteProc DeleteProc;\nstatic void\t\tRegAddName(NameRegistry *regPtr,\n\t\t\t    const char *name, Window commWindow);\nstatic void\t\tRegClose(NameRegistry *regPtr);\nstatic void\t\tRegDeleteName(NameRegistry *regPtr, const char *name);\nstatic Window\t\tRegFindName(NameRegistry *regPtr, const char *name);\nstatic NameRegistry *\tRegOpen(Tcl_Interp *interp,\n\t\t\t    TkDisplay *dispPtr, int lock);\nstatic void\t\tSendEventProc(void *clientData, XEvent *eventPtr);\nstatic int\t\tSendInit(Tcl_Interp *interp, TkDisplay *dispPtr);\nstatic Tk_RestrictProc SendRestrictProc;\nstatic int\t\tServerSecure(TkDisplay *dispPtr);\nstatic void\t\tUpdateCommWindow(TkDisplay *dispPtr);\nstatic int\t\tValidateName(TkDisplay *dispPtr, const char *name,\n\t\t\t    Window commWindow, int oldOK);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegOpen --\n *\n *\tThis function loads the name registry for a display into memory so\n *\tthat it can be manipulated.\n *\n * Results:\n *\tThe return value is a pointer to the loaded registry.\n *\n * Side effects:\n *\tIf \"lock\" is set then the server will be locked. It is the caller's\n *\tresponsibility to call RegClose when finished with the registry, so\n *\tthat we can write back the registry if needed, unlock the server if\n *\tneeded, and free memory.\n *\n *----------------------------------------------------------------------\n */\n\nstatic NameRegistry *\nRegOpen(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting\n\t\t\t\t * (errors cause a panic so in fact no error\n\t\t\t\t * is ever returned, but the interpreter is\n\t\t\t\t * needed anyway). */\n    TkDisplay *dispPtr,\t\t/* Display whose name registry is to be\n\t\t\t\t * opened. */\n    int lock)\t\t\t/* Non-zero means lock the window server when\n\t\t\t\t * opening the registry, so no-one else can\n\t\t\t\t * use the registry until we close it. */\n{\n    NameRegistry *regPtr;\n    int result, actualFormat;\n    unsigned long bytesAfter;\n    Atom actualType;\n    char **propertyPtr;\n    Tk_ErrorHandler handler;\n\n    if (dispPtr->commTkwin == NULL) {\n\tSendInit(interp, dispPtr);\n    }\n\n    handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL);\n\n    regPtr = (NameRegistry *)Tcl_Alloc(sizeof(NameRegistry));\n    regPtr->dispPtr = dispPtr;\n    regPtr->locked = 0;\n    regPtr->modified = 0;\n    regPtr->allocedByX = true;\n    propertyPtr = &regPtr->property;\n\n    if (lock && !localData.sendDebug) {\n\tXGrabServer(dispPtr->display);\n\tregPtr->locked = 1;\n    }\n\n    /*\n     * Read the registry property.\n     */\n\n    result = XGetWindowProperty(dispPtr->display,\n\t    RootWindow(dispPtr->display, 0),\n\t    dispPtr->registryProperty, 0, MAX_PROP_WORDS,\n\t    False, XA_STRING, &actualType, &actualFormat,\n\t    &regPtr->propLength, &bytesAfter,\n\t    (unsigned char **) propertyPtr);\n\n    if (actualType == None) {\n\tregPtr->propLength = 0;\n\tregPtr->property = NULL;\n    } else if ((result != Success) || (actualFormat != 8)\n\t    || (actualType != XA_STRING)) {\n\t/*\n\t * The property is improperly formed; delete it.\n\t */\n\n\tif (regPtr->property != NULL) {\n\t    XFree(regPtr->property);\n\t    regPtr->propLength = 0;\n\t    regPtr->property = NULL;\n\t}\n\tXDeleteProperty(dispPtr->display,\n\t\tRootWindow(dispPtr->display, 0),\n\t\tdispPtr->registryProperty);\n\tXSync(dispPtr->display, False);\n    }\n\n    Tk_DeleteErrorHandler(handler);\n\n    /*\n     * Xlib placed an extra null byte after the end of the property, just to\n     * make sure that it is always NULL-terminated. Be sure to include this\n     * byte in our count if it's needed to ensure null termination (note: as\n     * of 8/95 I'm no longer sure why this code is needed; seems like it\n     * shouldn't be).\n     */\n\n    if ((regPtr->propLength > 0)\n\t    && (regPtr->property[regPtr->propLength-1] != 0)) {\n\tregPtr->propLength++;\n    }\n    return regPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegFindName --\n *\n *\tGiven an open name registry, this function finds an entry with a given\n *\tname, if there is one, and returns information about that entry.\n *\n * Results:\n *\tThe return value is the X identifier for the comm window for the\n *\tapplication named \"name\", or None if there is no such entry in the\n *\tregistry.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Window\nRegFindName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name)\t\t/* Name of an application. */\n{\n    char *p;\n\n    for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) {\n\tchar *entry = p;\n\n\twhile ((*p != 0) && (!isspace(UCHAR(*p)))) {\n\t    p++;\n\t}\n\tif ((*p != 0) && (strcmp(name, p+1) == 0)) {\n\t    unsigned id;\n\n\t    if (sscanf(entry, \"%x\", &id) == 1) {\n\t\t/*\n\t\t * Must cast from an unsigned int to a Window in case we are\n\t\t * on a 64-bit architecture.\n\t\t */\n\n\t\treturn (Window) id;\n\t    }\n\t}\n\twhile (*p != 0) {\n\t    p++;\n\t}\n\tp++;\n    }\n    return None;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegDeleteName --\n *\n *\tThis function deletes the entry for a given name from an open\n *\tregistry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there used to be an entry named \"name\" in the registry, then it is\n *\tdeleted and the registry is marked as modified so it will be written\n *\tback when closed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegDeleteName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name)\t\t/* Name of an application. */\n{\n    char *p;\n\n    for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) {\n\tchar *entry = p, *entryName;\n\n\twhile ((*p != 0) && (!isspace(UCHAR(*p)))) {\n\t    p++;\n\t}\n\tif (*p != 0) {\n\t    p++;\n\t}\n\tentryName = p;\n\twhile (*p != 0) {\n\t    p++;\n\t}\n\tp++;\n\tif (strcmp(name, entryName) == 0) {\n\t    int count;\n\n\t    /*\n\t     * Found the matching entry. Copy everything after it down on top\n\t     * of it.\n\t     */\n\n\t    count = regPtr->propLength - (p - regPtr->property);\n\t    if (count > 0) {\n\t\tchar *src, *dst;\n\n\t\tfor (src=p , dst=entry ; count>0 ; src++, dst++, count--) {\n\t\t    *dst = *src;\n\t\t}\n\t    }\n\t    regPtr->propLength -= p - entry;\n\t    regPtr->modified = 1;\n\t    return;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegAddName --\n *\n *\tAdd a new entry to an open registry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe open registry is expanded; it is marked as modified so that it\n *\twill be written back when closed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegAddName(\n    NameRegistry *regPtr,\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n    const char *name,\t\t/* Name of an application. The caller must\n\t\t\t\t * ensure that this name isn't already\n\t\t\t\t * registered. */\n    Window commWindow)\t\t/* X identifier for comm. window of\n\t\t\t\t * application. */\n{\n    char id[30], *newProp;\n    int idLength, newBytes;\n\n    snprintf(id, sizeof(id), \"%x \", (unsigned) commWindow);\n    idLength = strlen(id);\n    newBytes = idLength + strlen(name) + 1;\n    newProp = (char *)Tcl_Alloc(regPtr->propLength + newBytes);\n    strcpy(newProp, id);\n    strcpy(newProp+idLength, name);\n    if (regPtr->property != NULL) {\n\tmemcpy(newProp + newBytes, regPtr->property, regPtr->propLength);\n\tif (regPtr->allocedByX) {\n\t    XFree(regPtr->property);\n\t} else {\n\t    Tcl_Free(regPtr->property);\n\t}\n    }\n    regPtr->modified = 1;\n    regPtr->propLength += newBytes;\n    regPtr->property = newProp;\n    regPtr->allocedByX = false;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegClose --\n *\n *\tThis function is called to end a series of operations on a name\n *\tregistry.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe registry is written back if it has been modified, and the X server\n *\tis unlocked if it was locked. Memory for the registry is freed, so the\n *\tcaller should never use regPtr again.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRegClose(\n    NameRegistry *regPtr)\t/* Pointer to a registry opened with a\n\t\t\t\t * previous call to RegOpen. */\n{\n    Tk_ErrorHandler handler;\n\n    handler = Tk_CreateErrorHandler(regPtr->dispPtr->display, -1, -1, -1,\n\t    NULL, NULL);\n\n    if (regPtr->modified) {\n\tif (!regPtr->locked && !localData.sendDebug) {\n\t    Tcl_Panic(\"The name registry was modified without being locked!\");\n\t}\n\tXChangeProperty(regPtr->dispPtr->display,\n\t\tRootWindow(regPtr->dispPtr->display, 0),\n\t\tregPtr->dispPtr->registryProperty, XA_STRING, 8,\n\t\tPropModeReplace, (unsigned char *) regPtr->property,\n\t\t(int) regPtr->propLength);\n    }\n\n    if (regPtr->locked) {\n\tXUngrabServer(regPtr->dispPtr->display);\n    }\n\n    /*\n     * After ungrabbing the server, it's important to flush the output\n     * immediately so that the server sees the ungrab command. Otherwise we\n     * might do something else that needs to communicate with the server (such\n     * as invoking a subprocess that needs to do I/O to the screen); if the\n     * ungrab command is still sitting in our output buffer, we could\n     * deadlock.\n     */\n\n    XFlush(regPtr->dispPtr->display);\n\n    Tk_DeleteErrorHandler(handler);\n\n    if (regPtr->property != NULL) {\n\tif (regPtr->allocedByX) {\n\t    XFree(regPtr->property);\n\t} else {\n\t    Tcl_Free(regPtr->property);\n\t}\n    }\n    Tcl_Free(regPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ValidateName --\n *\n *\tThis function checks to see if an entry in the registry is still\n *\tvalid.\n *\n * Results:\n *\tThe return value is 1 if the given commWindow exists and its name is\n *\t\"name\". Otherwise 0 is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nValidateName(\n    TkDisplay *dispPtr,\t\t/* Display for which to perform the\n\t\t\t\t * validation. */\n    const char *name,\t\t/* The name of an application. */\n    Window commWindow,\t\t/* X identifier for the application's comm.\n\t\t\t\t * window. */\n    int oldOK)\t\t\t/* Non-zero means that we should consider an\n\t\t\t\t * application to be valid even if it looks\n\t\t\t\t * like an old-style (pre-4.0) one; 0 means\n\t\t\t\t * consider these invalid. */\n{\n    int result, actualFormat;\n    Tcl_Size argc, i;\n    unsigned long length, bytesAfter;\n    Atom actualType;\n    char *property, **propertyPtr = &property;\n    Tk_ErrorHandler handler;\n    const char **argv;\n\n    property = NULL;\n\n    /*\n     * Ignore X errors when reading the property (e.g., the window might not\n     * exist). If an error occurs, result will be some value other than\n     * Success.\n     */\n\n    handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL);\n    result = XGetWindowProperty(dispPtr->display, commWindow,\n\t    dispPtr->appNameProperty, 0, MAX_PROP_WORDS,\n\t    False, XA_STRING, &actualType, &actualFormat,\n\t    &length, &bytesAfter, (unsigned char **) propertyPtr);\n\n    if ((result == Success) && (actualType == None)) {\n\tXWindowAttributes atts;\n\n\t/*\n\t * The comm. window exists but the property we're looking for doesn't\n\t * exist. This probably means that the application comes from an older\n\t * version of Tk (< 4.0) that didn't set the property; if this is the\n\t * case, then assume for compatibility's sake that everything's OK.\n\t * However, it's also possible that some random application has\n\t * re-used the window id for something totally unrelated. Check a few\n\t * characteristics of the window, such as its dimensions and mapped\n\t * state, to be sure that it still \"smells\" like a commWindow.\n\t */\n\n\tif (!oldOK\n\t\t|| !XGetWindowAttributes(dispPtr->display, commWindow, &atts)\n\t\t|| (atts.width != 1) || (atts.height != 1)\n\t\t|| (atts.map_state != IsUnmapped)) {\n\t    result = 0;\n\t} else {\n\t    result = 1;\n\t}\n    } else if ((result == Success) && (actualFormat == 8)\n\t    && (actualType == XA_STRING)) {\n\tresult = 0;\n\tif (Tcl_SplitList(NULL, property, &argc, &argv) == TCL_OK) {\n\t    for (i = 0; i < argc; i++) {\n\t\tif (strcmp(argv[i], name) == 0) {\n\t\t    result = 1;\n\t\t    break;\n\t\t}\n\t    }\n\t    Tcl_Free(argv);\n\t}\n    } else {\n\tresult = 0;\n    }\n    Tk_DeleteErrorHandler(handler);\n    if (property != NULL) {\n\tXFree(property);\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ServerSecure --\n *\n *\tCheck whether a server is secure enough for us to trust Tcl scripts\n *\tarriving via that server.\n *\n * Results:\n *\tThe return value is 1 if the server is secure, which means that\n *\thost-style authentication is turned on but there are no hosts in the\n *\tenabled list. This means that some other form of authorization\n *\t(presumably more secure, such as xauth) is in use.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nServerSecure(\n    TkDisplay *dispPtr)\t\t/* Display to check. */\n{\n#ifdef TK_NO_SECURITY\n    return 1;\n#else\n    XHostAddress *addrPtr;\n    int numHosts, secure;\n    Bool enabled;\n\n    addrPtr = XListHosts(dispPtr->display, &numHosts, &enabled);\n    if (!enabled) {\n    insecure:\n\tsecure = 0;\n    } else if (numHosts == 0) {\n\tsecure = 1;\n    } else {\n\t/*\n\t * Recent versions of X11 have the extra feature of allowing more\n\t * sophisticated authorization checks to be performed than the dozy\n\t * old ones that used to plague xhost usage. However, not all deployed\n\t * versions of Xlib know how to deal with this feature, so this code\n\t * is conditional on having the right #def in place. [Bug 1909931]\n\t *\n\t * Note that at this point we know that there's at least one entry in\n\t * the list returned by XListHosts. However there may be multiple\n\t * entries; as long as each is one of either 'SI:localhost:*' or\n\t * 'SI:localgroup:*' then we will claim to be secure enough.\n\t */\n\n#ifdef FamilyServerInterpreted\n\tXServerInterpretedAddress *siPtr;\n\tint i;\n\n\tfor (i=0 ; i<numHosts ; i++) {\n\t    if (addrPtr[i].family != FamilyServerInterpreted) {\n\t\t/*\n\t\t * We don't understand what the X server is letting in, so we\n\t\t * err on the side of safety.\n\t\t */\n\n\t\tgoto insecure;\n\t    }\n\t    siPtr = (XServerInterpretedAddress *) addrPtr[0].address;\n\n\t    /*\n\t     * We don't check the username or group here. This is because it's\n\t     * officially non-portable and we are just making sure there\n\t     * aren't silly misconfigurations. (Apparently 'root' is not a\n\t     * very good choice, but we still don't put any effort in to spot\n\t     * that.) However we do check to see that the constraints are\n\t     * imposed against the connecting user and/or group.\n\t     */\n\n\t    if (       !(siPtr->typelength == 9 /* ==strlen(\"localuser\") */\n\t\t\t&& !memcmp(siPtr->type, \"localuser\", 9))\n\t\t    && !(siPtr->typelength == 10 /* ==strlen(\"localgroup\") */\n\t\t\t&& !memcmp(siPtr->type, \"localgroup\", 10))) {\n\t\t/*\n\t\t * The other defined types of server-interpreted controls\n\t\t * involve particular hosts. These are still insecure for the\n\t\t * same reasons that classic xhost access is insecure; there's\n\t\t * just no way to be sure that the users on those systems are\n\t\t * the ones who should be allowed to connect to this display.\n\t\t */\n\n\t\tgoto insecure;\n\t    }\n\t}\n\tsecure = 1;\n#else\n\t/*\n\t * We don't understand what the X server is letting in, so we err on\n\t * the side of safety.\n\t */\n\n\tsecure = 0;\n#endif /* FamilyServerInterpreted */\n    }\n    if (addrPtr != NULL) {\n\tXFree(addrPtr);\n    }\n    return secure;\n#endif /* TK_NO_SECURITY */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetAppName --\n *\n *\tThis function is called to associate an ASCII name with a Tk\n *\tapplication. If the application has already been named, the name\n *\treplaces the old one.\n *\n * Results:\n *\tThe return value is the name actually given to the application. This\n *\twill normally be the same as name, but if name was already in use for\n *\tan application then a name of the form \"name #2\" will be chosen, with\n *\ta high enough number to make the name unique.\n *\n * Side effects:\n *\tRegistration info is saved, thereby allowing the \"send\" command to be\n *\tused later to invoke commands in the application. In addition, the\n *\t\"send\" command is created in the application's interpreter. The\n *\tregistration will be removed automatically if the interpreter is\n *\tdeleted or the \"send\" command is removed.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTk_SetAppName(\n    Tk_Window tkwin,\t\t/* Token for any window in the application to\n\t\t\t\t * be named: it is just used to identify the\n\t\t\t\t * application and the display. */\n    const char *name)\t\t/* The name that will be used to refer to the\n\t\t\t\t * interpreter in later \"send\" commands. Must\n\t\t\t\t * be globally unique. */\n{\n    RegisteredInterp *riPtr, *riPtr2;\n    Window w;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    NameRegistry *regPtr;\n    Tcl_Interp *interp;\n    const char *actualName;\n    Tcl_DString dString;\n    int offset, i;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    interp = winPtr->mainPtr->interp;\n    if (dispPtr->commTkwin == NULL) {\n\tSendInit(interp, winPtr->dispPtr);\n    }\n\n    /*\n     * See if the application is already registered; if so, remove its current\n     * name from the registry.\n     */\n\n    regPtr = RegOpen(interp, winPtr->dispPtr, 1);\n    for (riPtr = tsdPtr->interpListPtr; ; riPtr = riPtr->nextPtr) {\n\tif (riPtr == NULL) {\n\t    /*\n\t     * This interpreter isn't currently registered; create the data\n\t     * structure that will be used to register it locally, plus add\n\t     * the \"send\" command to the interpreter.\n\t     */\n\n\t    riPtr = (RegisteredInterp *)Tcl_Alloc(sizeof(RegisteredInterp));\n\t    riPtr->interp = interp;\n\t    riPtr->dispPtr = winPtr->dispPtr;\n\t    riPtr->nextPtr = tsdPtr->interpListPtr;\n\t    tsdPtr->interpListPtr = riPtr;\n\t    riPtr->name = NULL;\n\t    Tcl_CreateObjCommand2(interp, \"send\", Tk_SendObjCmd, riPtr, DeleteProc);\n\t    if (Tcl_IsSafe(interp)) {\n\t\tTcl_HideCommand(interp, \"send\", \"send\");\n\t    }\n\t    break;\n\t}\n\tif (riPtr->interp == interp) {\n\t    /*\n\t     * The interpreter is currently registered; remove it from the\n\t     * name registry.\n\t     */\n\n\t    if (riPtr->name) {\n\t\tRegDeleteName(regPtr, riPtr->name);\n\t\tTcl_Free(riPtr->name);\n\t    }\n\t    break;\n\t}\n    }\n\n    /*\n     * Pick a name to use for the application. Use \"name\" if it's not already\n     * in use. Otherwise add a suffix such as \" #2\", trying larger and larger\n     * numbers until we eventually find one that is unique.\n     */\n\n    actualName = name;\n    offset = 0;\t\t\t\t/* Needed only to avoid \"used before\n\t\t\t\t\t * set\" compiler warnings. */\n    for (i = 1; ; i++) {\n\tif (i > 1) {\n\t    if (i == 2) {\n\t\tTcl_DStringInit(&dString);\n\t\tTcl_DStringAppend(&dString, name, TCL_INDEX_NONE);\n\t\tTcl_DStringAppend(&dString, \" #\", 2);\n\t\toffset = Tcl_DStringLength(&dString);\n\t\tTcl_DStringSetLength(&dString, offset+TCL_INTEGER_SPACE);\n\t\tactualName = Tcl_DStringValue(&dString);\n\t    }\n\t    snprintf(Tcl_DStringValue(&dString) + offset, TCL_INTEGER_SPACE, \"%d\", i);\n\t}\n\tw = RegFindName(regPtr, actualName);\n\tif (w == None) {\n\t    break;\n\t}\n\n\t/*\n\t * The name appears to be in use already, but double-check to be sure\n\t * (perhaps the application died without removing its name from the\n\t * registry?).\n\t */\n\n\tif (w == Tk_WindowId(dispPtr->commTkwin)) {\n\t    for (riPtr2 = tsdPtr->interpListPtr; riPtr2 != NULL;\n\t\t    riPtr2 = riPtr2->nextPtr) {\n\t\tif ((riPtr2->interp != interp) &&\n\t\t\t(strcmp(riPtr2->name, actualName) == 0)) {\n\t\t    goto nextSuffix;\n\t\t}\n\t    }\n\t    RegDeleteName(regPtr, actualName);\n\t    break;\n\t} else if (!ValidateName(winPtr->dispPtr, actualName, w, 1)) {\n\t    RegDeleteName(regPtr, actualName);\n\t    break;\n\t}\n    nextSuffix:\n\tcontinue;\n    }\n\n    /*\n     * We've now got a name to use. Store it in the name registry and in the\n     * local entry for this application, plus put it in a property on the\n     * commWindow.\n     */\n\n    RegAddName(regPtr, actualName, Tk_WindowId(dispPtr->commTkwin));\n    RegClose(regPtr);\n    riPtr->name = (char *)Tcl_Alloc(strlen(actualName) + 1);\n    strcpy(riPtr->name, actualName);\n    if (actualName != name) {\n\tTcl_DStringFree(&dString);\n    }\n    UpdateCommWindow(dispPtr);\n\n    return riPtr->name;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SendObjCmd --\n *\n *\tThis function is invoked to process the \"send\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SendObjCmd(\n    TCL_UNUSED(void *),\t/* Information about sender (only dispPtr\n\t\t\t\t * field is used). */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    enum {\n\tSEND_ASYNC, SEND_DISPLAYOF, SEND_LAST\n    };\n    static const char *const sendOptions[] = {\n\t\"-async\",   \"-displayof\",   \"--\",  NULL\n    };\n    const char *stringRep, *destName;\n    TkWindow *winPtr;\n    Window commWindow;\n    PendingCommand pending;\n    RegisteredInterp *riPtr;\n    int result, async, index;\n    Tcl_Size i, firstArg;\n    Tk_RestrictProc *prevProc;\n    void *prevArg;\n    TkDisplay *dispPtr;\n    Tcl_Time timeout;\n    NameRegistry *regPtr;\n    Tcl_DString request;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_Interp *localInterp;\t/* Used when the interpreter to send the\n\t\t\t\t * command to is within the same process. */\n\n    /*\n     * Process options, if any.\n     */\n\n    async = 0;\n    winPtr = (TkWindow *) Tk_MainWindow(interp);\n    if (winPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Process the command options.\n     */\n\n    for (i = 1; i < (objc - 1); i++) {\n\tstringRep = Tcl_GetString(objv[i]);\n\tif (stringRep[0] == '-') {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions,\n\t\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (index == SEND_ASYNC) {\n\t\t++async;\n\t    } else if (index == SEND_DISPLAYOF) {\n\t\twinPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[++i]),\n\t\t\t(Tk_Window) winPtr);\n\t\tif (winPtr == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else /* if (index == SEND_LAST) */ {\n\t\ti++;\n\t\tbreak;\n\t    }\n\t} else {\n\t    break;\n\t}\n    }\n\n    if (objc < (i + 2)) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"?-option value ...? interpName arg ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n    destName = Tcl_GetString(objv[i]);\n    firstArg = i+1;\n\n    dispPtr = winPtr->dispPtr;\n    if (dispPtr->commTkwin == NULL) {\n\tSendInit(interp, winPtr->dispPtr);\n    }\n\n    /*\n     * See if the target interpreter is local. If so, execute the command\n     * directly without going through the X server. The only tricky thing is\n     * passing the result from the target interpreter to the invoking\n     * interpreter. Watch out: they could be the same!\n     */\n\n    for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;\n\t    riPtr = riPtr->nextPtr) {\n\tif ((riPtr->dispPtr != dispPtr)\n\t\t|| (strcmp(riPtr->name, destName) != 0)) {\n\t    continue;\n\t}\n\tTcl_Preserve(riPtr);\n\tlocalInterp = riPtr->interp;\n\tTcl_Preserve(localInterp);\n\tif (firstArg == (objc-1)) {\n\t    result = Tcl_EvalEx(localInterp, Tcl_GetString(objv[firstArg]), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t} else {\n\t    Tcl_DStringInit(&request);\n\t    Tcl_DStringAppend(&request, Tcl_GetString(objv[firstArg]), TCL_INDEX_NONE);\n\t    for (i = firstArg+1; i < objc; i++) {\n\t\tTcl_DStringAppend(&request, \" \", 1);\n\t\tTcl_DStringAppend(&request, Tcl_GetString(objv[i]), TCL_INDEX_NONE);\n\t    }\n\t    result = Tcl_EvalEx(localInterp, Tcl_DStringValue(&request), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    Tcl_DStringFree(&request);\n\t}\n\tif (interp != localInterp) {\n\t    if (result == TCL_ERROR) {\n\t\tTcl_Obj *errorObjPtr;\n\n\t\t/*\n\t\t * An error occurred, so transfer error information from the\n\t\t * destination interpreter back to our interpreter. Must clear\n\t\t * interp's result before calling Tcl_AddErrorInfo, since\n\t\t * Tcl_AddErrorInfo will store the interp's result in\n\t\t * errorInfo before appending riPtr's $errorInfo; we've\n\t\t * already got everything we need in riPtr's $errorInfo.\n\t\t */\n\n\t\tTcl_ResetResult(interp);\n\t\tTcl_AddErrorInfo(interp, Tcl_GetVar2(localInterp,\n\t\t\t\"errorInfo\", NULL, TCL_GLOBAL_ONLY));\n\t\terrorObjPtr = Tcl_GetVar2Ex(localInterp, \"errorCode\", NULL,\n\t\t\tTCL_GLOBAL_ONLY);\n\t\tTcl_SetObjErrorCode(interp, errorObjPtr);\n\t    }\n\t    Tcl_SetObjResult(interp, Tcl_GetObjResult(localInterp));\n\t    Tcl_ResetResult(localInterp);\n\t}\n\tTcl_Release(riPtr);\n\tTcl_Release(localInterp);\n\treturn result;\n    }\n\n    /*\n     * Bind the interpreter name to a communication window.\n     */\n\n    regPtr = RegOpen(interp, winPtr->dispPtr, 0);\n    commWindow = RegFindName(regPtr, destName);\n    RegClose(regPtr);\n    if (commWindow == None) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"no application named \\\"%s\\\"\", destName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"APPLICATION\", destName,\n\t\tNULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Send the command to the target interpreter by appending it to the comm\n     * window in the communication window.\n     */\n\n    localData.sendSerial++;\n    Tcl_DStringInit(&request);\n    Tcl_DStringAppend(&request, \"\\0c\\0-n \", 6);\n    Tcl_DStringAppend(&request, destName, TCL_INDEX_NONE);\n    if (!async) {\n\tchar buffer[TCL_INTEGER_SPACE * 2];\n\n\tsnprintf(buffer, sizeof(buffer), \"%x %d\",\n\t\t(unsigned) Tk_WindowId(dispPtr->commTkwin),\n\t\tlocalData.sendSerial);\n\tTcl_DStringAppend(&request, \"\\0-r \", 4);\n\tTcl_DStringAppend(&request, buffer, TCL_INDEX_NONE);\n    }\n    Tcl_DStringAppend(&request, \"\\0-s \", 4);\n    Tcl_DStringAppend(&request, Tcl_GetString(objv[firstArg]), TCL_INDEX_NONE);\n    for (i = firstArg+1; i < objc; i++) {\n\tTcl_DStringAppend(&request, \" \", 1);\n\tTcl_DStringAppend(&request, Tcl_GetString(objv[i]), TCL_INDEX_NONE);\n    }\n\n    if (!async) {\n\t/*\n\t * Register the fact that we're waiting for a command to complete\n\t * (this is needed by SendEventProc and by AppendErrorProc to pass\n\t * back the command's results). Set up a timeout handler so that\n\t * we can check during long sends to make sure that the destination\n\t * application is still alive.\n\t *\n\t * We prepare the pending struct here in order to catch potential\n\t * early X errors from AppendPropCarefully() due to XSync().\n\t */\n\n\tpending.serial = localData.sendSerial;\n\tpending.dispPtr = dispPtr;\n\tpending.target = destName;\n\tpending.commWindow = commWindow;\n\tpending.interp = interp;\n\tpending.result = NULL;\n\tpending.errorInfo = NULL;\n\tpending.errorCode = NULL;\n\tpending.gotResponse = 0;\n\tpending.nextPtr = tsdPtr->pendingCommands;\n\ttsdPtr->pendingCommands = &pending;\n    }\n    (void) AppendPropCarefully(dispPtr->display, commWindow,\n\t    dispPtr->commProperty, Tcl_DStringValue(&request),\n\t    Tcl_DStringLength(&request) + 1, (async ? NULL : &pending));\n    Tcl_DStringFree(&request);\n    if (async) {\n\t/*\n\t * This is an asynchronous send: return immediately without waiting\n\t * for a response.\n\t */\n\n\treturn TCL_OK;\n    }\n\n    /*\n     * Enter a loop processing X events until the result comes in or the\n     * target is declared to be dead. While waiting for a result, look only at\n     * send-related events so that the send is synchronous with respect to\n     * other events in the application.\n     */\n\n    prevProc = Tk_RestrictEvents(SendRestrictProc, NULL, &prevArg);\n    Tcl_GetTime(&timeout);\n    timeout.sec += 2;\n    while (!pending.gotResponse) {\n\tif (!TkUnixDoOneXEvent(&timeout)) {\n\t    /*\n\t     * An unusually long amount of time has elapsed during the\n\t     * processing of a sent command. Check to make sure that the\n\t     * target application still exists. If it does, reset the timeout.\n\t     */\n\n\t    if (!ValidateName(pending.dispPtr, pending.target,\n\t\t    pending.commWindow, 0)) {\n\t\tconst char *msg;\n\n\t\tif (ValidateName(pending.dispPtr, pending.target,\n\t\t\tpending.commWindow, 1)) {\n\t\t    msg = \"target application died or uses a Tk version before 4.0\";\n\t\t} else {\n\t\t    msg = \"target application died\";\n\t\t}\n\t\tpending.code = TCL_ERROR;\n\t\tpending.result = (char *)Tcl_Alloc(strlen(msg) + 1);\n\t\tstrcpy(pending.result, msg);\n\t\tpending.gotResponse = 1;\n\t    } else {\n\t\tTcl_GetTime(&timeout);\n\t\ttimeout.sec += 2;\n\t    }\n\t}\n    }\n    Tk_RestrictEvents(prevProc, prevArg, &prevArg);\n\n    /*\n     * Unregister the information about the pending command and return the\n     * result.\n     */\n\n    if (tsdPtr->pendingCommands != &pending) {\n\tTcl_Panic(\"Tk_SendCmd: corrupted send stack\");\n    }\n    tsdPtr->pendingCommands = pending.nextPtr;\n    if (pending.errorInfo != NULL) {\n\t/*\n\t * Special trick: must clear the interp's result before calling\n\t * Tcl_AddErrorInfo, since Tcl_AddErrorInfo will store the interp's\n\t * result in errorInfo before appending pending.errorInfo; we've\n\t * already got everything we need in pending.errorInfo.\n\t */\n\n\tTcl_ResetResult(interp);\n\tTcl_AddErrorInfo(interp, pending.errorInfo);\n\tTcl_Free(pending.errorInfo);\n    }\n    if (pending.errorCode != NULL) {\n\tTcl_SetObjErrorCode(interp, Tcl_NewStringObj(pending.errorCode, TCL_INDEX_NONE));\n\tTcl_Free(pending.errorCode);\n    }\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(pending.result, TCL_INDEX_NONE));\n    Tcl_Free(pending.result);\n    return pending.code;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetInterpNames --\n *\n *\tThis function is invoked to fetch a list of all the interpreter names\n *\tcurrently registered for the display of a particular window.\n *\n * Results:\n *\tA standard Tcl return value. The interp's result will be set to hold a\n *\tlist of all the interpreter names defined for tkwin's display. If an\n *\terror occurs, then TCL_ERROR is returned and the interp's result will\n *\thold an error message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetInterpNames(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning a result. */\n    Tk_Window tkwin)\t\t/* Window whose display is to be used for the\n\t\t\t\t * lookup. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    NameRegistry *regPtr;\n    Tcl_Obj *resultObj = Tcl_NewObj();\n    char *p;\n\n    /*\n     * Read the registry property, then scan through all of its entries.\n     * Validate each entry to be sure that its application still exists.\n     */\n\n    regPtr = RegOpen(interp, winPtr->dispPtr, 1);\n    for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) {\n\tchar *entry = p, *entryName;\n\tWindow commWindow;\n\tunsigned id;\n\n\tif (sscanf(p, \"%x\", (unsigned *) &id) != 1) {\n\t    commWindow = None;\n\t} else {\n\t    commWindow = id;\n\t}\n\twhile ((*p != 0) && (!isspace(UCHAR(*p)))) {\n\t    p++;\n\t}\n\tif (*p != 0) {\n\t    p++;\n\t}\n\tentryName = p;\n\twhile (*p != 0) {\n\t    p++;\n\t}\n\tp++;\n\tif (ValidateName(winPtr->dispPtr, entryName, commWindow, 1)) {\n\t    /*\n\t     * The application still exists; add its name to the result.\n\t     */\n\n\t    Tcl_ListObjAppendElement(NULL, resultObj,\n\t\t    Tcl_NewStringObj(entryName, TCL_INDEX_NONE));\n\t} else {\n\t    int count;\n\n\t    /*\n\t     * This name is bogus (perhaps the application died without\n\t     * cleaning up its entry in the registry?). Delete the name.\n\t     */\n\n\t    count = regPtr->propLength - (p - regPtr->property);\n\t    if (count > 0) {\n\t\tchar *src, *dst;\n\n\t\tfor (src = p, dst = entry; count > 0; src++, dst++, count--) {\n\t\t    *dst = *src;\n\t\t}\n\t    }\n\t    regPtr->propLength -= p - entry;\n\t    regPtr->modified = 1;\n\t    p = entry;\n\t}\n    }\n    RegClose(regPtr);\n    Tcl_SetObjResult(interp, resultObj);\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkSendCleanup --\n *\n *\tThis function is called to free resources used by the communication\n *\tchannels for sending commands and receiving results.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees various data structures and windows.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkSendCleanup(\n    TkDisplay *dispPtr)\n{\n    if (dispPtr->commTkwin != NULL) {\n\tTk_DeleteEventHandler(dispPtr->commTkwin, PropertyChangeMask,\n\t\tSendEventProc, dispPtr);\n\tTk_DestroyWindow(dispPtr->commTkwin);\n\tTcl_Release(dispPtr->commTkwin);\n\tdispPtr->commTkwin = NULL;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SendInit --\n *\n *\tThis function is called to initialize the communication channels for\n *\tsending commands and receiving results.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets up various data structures and windows.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nSendInit(\n    TCL_UNUSED(Tcl_Interp *),\t/* Interpreter to use for error reporting (no\n\t\t\t\t * errors are ever returned, but the\n\t\t\t\t * interpreter is needed anyway). */\n    TkDisplay *dispPtr)\t\t/* Display to initialize. */\n{\n    XSetWindowAttributes atts;\n\n    /*\n     * Create the window used for communication, and set up an event handler\n     * for it.\n     */\n\n    dispPtr->commTkwin = (Tk_Window) TkAllocWindow(dispPtr,\n\tDefaultScreen(dispPtr->display), NULL);\n    Tcl_Preserve(dispPtr->commTkwin);\n    ((TkWindow *) dispPtr->commTkwin)->flags |=\n\t    TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;\n    TkWmNewWindow((TkWindow *) dispPtr->commTkwin);\n    atts.override_redirect = True;\n    Tk_ChangeWindowAttributes(dispPtr->commTkwin,\n\t    CWOverrideRedirect, &atts);\n    Tk_CreateEventHandler(dispPtr->commTkwin, PropertyChangeMask,\n\t    SendEventProc, dispPtr);\n    Tk_MakeWindowExist(dispPtr->commTkwin);\n\n    /*\n     * Get atoms used as property names.\n     */\n\n    dispPtr->commProperty = Tk_InternAtom(dispPtr->commTkwin, \"Comm\");\n    dispPtr->registryProperty = Tk_InternAtom(dispPtr->commTkwin,\n\t    \"InterpRegistry\");\n    dispPtr->appNameProperty = Tk_InternAtom(dispPtr->commTkwin,\n\t    \"TK_APPLICATION\");\n\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * SendEventProc --\n *\n *\tThis function is invoked automatically by the toolkit event manager\n *\twhen a property changes on the communication window. This function\n *\treads the property and handles command requests and responses.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf there are command requests in the property, they are executed. If\n *\tthere are responses in the property, their information is saved for\n *\tthe (ostensibly waiting) \"send\" commands. The property is deleted.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nSendEventProc(\n    void *clientData,\t/* Display information. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkDisplay *dispPtr = (TkDisplay *)clientData;\n    char *propInfo, **propInfoPtr = &propInfo;\n    const char *p;\n    int result, actualFormat;\n    unsigned long numItems, bytesAfter;\n    Atom actualType;\n    Tcl_Interp *remoteInterp;\t/* Interp in which to execute the command. */\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if ((eventPtr->xproperty.atom != dispPtr->commProperty)\n\t    || (eventPtr->xproperty.state != PropertyNewValue)) {\n\treturn;\n    }\n\n    /*\n     * Read the comm property and delete it.\n     */\n\n    propInfo = NULL;\n    result = XGetWindowProperty(dispPtr->display,\n\t    Tk_WindowId(dispPtr->commTkwin), dispPtr->commProperty, 0,\n\t    MAX_PROP_WORDS, True, XA_STRING, &actualType, &actualFormat,\n\t    &numItems, &bytesAfter, (unsigned char **) propInfoPtr);\n\n    /*\n     * If the property doesn't exist or is improperly formed then ignore it.\n     */\n\n    if ((result != Success) || (actualType != XA_STRING)\n\t    || (actualFormat != 8)) {\n\tif (propInfo != NULL) {\n\t    XFree(propInfo);\n\t}\n\treturn;\n    }\n\n    /*\n     * Several commands and results could arrive in the property at one time;\n     * each iteration through the outer loop handles a single command or\n     * result.\n     */\n\n    for (p = propInfo; (p-propInfo) < (int) numItems; ) {\n\t/*\n\t * Ignore leading NULLs; each command or result starts with a NULL so\n\t * that no matter how badly formed a preceding command is, we'll be\n\t * able to tell that a new command/result is starting.\n\t */\n\n\tif (*p == 0) {\n\t    p++;\n\t    continue;\n\t}\n\n\tif ((*p == 'c') && (p[1] == 0)) {\n\t    Window commWindow;\n\t    const char *interpName, *script, *serial;\n\t    char *end;\n\t    Tcl_DString reply;\n\t    RegisteredInterp *riPtr;\n\n\t    /*\n\t     *----------------------------------------------------------\n\t     * This is an incoming command from some other application.\n\t     * Iterate over all of its options. Stop when we reach the end of\n\t     * the property or something that doesn't look like an option.\n\t     *----------------------------------------------------------\n\t     */\n\n\t    p += 2;\n\t    interpName = NULL;\n\t    commWindow = None;\n\t    serial = \"\";\n\t    script = NULL;\n\t    while (((p-propInfo) < (int) numItems) && (*p == '-')) {\n\t\tswitch (p[1]) {\n\t\tcase 'r':\n\t\t    commWindow = (Window) strtoul(p+2, &end, 16);\n\t\t    if ((end == p+2) || (*end != ' ')) {\n\t\t\tcommWindow = None;\n\t\t    } else {\n\t\t\tp = serial = end+1;\n\t\t    }\n\t\t    break;\n\t\tcase 'n':\n\t\t    if (p[2] == ' ') {\n\t\t\tinterpName = p+3;\n\t\t    }\n\t\t    break;\n\t\tcase 's':\n\t\t    if (p[2] == ' ') {\n\t\t\tscript = p+3;\n\t\t    }\n\t\t    break;\n\t\t}\n\t\twhile (*p != 0) {\n\t\t    p++;\n\t\t}\n\t\tp++;\n\t    }\n\n\t    if ((script == NULL) || (interpName == NULL)) {\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * Initialize the result property, so that we're ready at any time\n\t     * if we need to return an error.\n\t     */\n\n\t    if (commWindow != None) {\n\t\tTcl_DStringInit(&reply);\n\t\tTcl_DStringAppend(&reply, \"\\0r\\0-s \", 6);\n\t\tTcl_DStringAppend(&reply, serial, TCL_INDEX_NONE);\n\t\tTcl_DStringAppend(&reply, \"\\0-r \", 4);\n\t    }\n\n\t    if (!ServerSecure(dispPtr)) {\n\t\tif (commWindow != None) {\n\t\t    Tcl_DStringAppend(&reply,\n\t\t\t    \"X server insecure (must use xauth-style \"\n\t\t\t    \"authorization); command ignored\", TCL_INDEX_NONE);\n\t\t}\n\t\tresult = TCL_ERROR;\n\t\tgoto returnResult;\n\t    }\n\n\t    /*\n\t     * Locate the application, then execute the script.\n\t     */\n\n\t    for (riPtr = tsdPtr->interpListPtr; ; riPtr = riPtr->nextPtr) {\n\t\tif (riPtr == NULL) {\n\t\t    if (commWindow != None) {\n\t\t\tTcl_DStringAppend(&reply,\n\t\t\t\t\"receiver never heard of interpreter \\\"\", TCL_INDEX_NONE);\n\t\t\tTcl_DStringAppend(&reply, interpName, TCL_INDEX_NONE);\n\t\t\tTcl_DStringAppend(&reply, \"\\\"\", 1);\n\t\t    }\n\t\t    result = TCL_ERROR;\n\t\t    goto returnResult;\n\t\t}\n\t\tif (strcmp(riPtr->name, interpName) == 0) {\n\t\t    break;\n\t\t}\n\t    }\n\t    Tcl_Preserve(riPtr);\n\n\t    /*\n\t     * We must protect the interpreter because the script may enter\n\t     * another event loop, which might call Tcl_DeleteInterp.\n\t     */\n\n\t    remoteInterp = riPtr->interp;\n\t    Tcl_Preserve(remoteInterp);\n\n\t    result = Tcl_EvalEx(remoteInterp, script, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\n\t    /*\n\t     * The call to Tcl_Release may have released the interpreter which\n\t     * will cause the \"send\" command for that interpreter to be\n\t     * deleted. The command deletion callback will set the\n\t     * riPtr->interp field to NULL, hence the check below for NULL.\n\t     */\n\n\t    if (commWindow != None) {\n\t\tTcl_DStringAppend(&reply, Tcl_GetString(Tcl_GetObjResult(remoteInterp)),\n\t\t\t-1);\n\t\tif (result == TCL_ERROR) {\n\t\t    const char *varValue;\n\n\t\t    varValue = Tcl_GetVar2(remoteInterp, \"errorInfo\",\n\t\t\t    NULL, TCL_GLOBAL_ONLY);\n\t\t    if (varValue != NULL) {\n\t\t\tTcl_DStringAppend(&reply, \"\\0-i \", 4);\n\t\t\tTcl_DStringAppend(&reply, varValue, TCL_INDEX_NONE);\n\t\t    }\n\t\t    varValue = Tcl_GetVar2(remoteInterp, \"errorCode\",\n\t\t\t    NULL, TCL_GLOBAL_ONLY);\n\t\t    if (varValue != NULL) {\n\t\t\tTcl_DStringAppend(&reply, \"\\0-e \", 4);\n\t\t\tTcl_DStringAppend(&reply, varValue, TCL_INDEX_NONE);\n\t\t    }\n\t\t}\n\t    }\n\t    Tcl_Release(remoteInterp);\n\t    Tcl_Release(riPtr);\n\n\t    /*\n\t     * Return the result to the sender if a commWindow was specified\n\t     * (if none was specified then this is an asynchronous call).\n\t     * Right now reply has everything but the completion code, but it\n\t     * needs the NULL to terminate the current option.\n\t     */\n\n\treturnResult:\n\t    if (commWindow != None) {\n\t\tif (result != TCL_OK) {\n\t\t    char buffer[TCL_INTEGER_SPACE];\n\n\t\t    snprintf(buffer, sizeof(buffer), \"%d\", result);\n\t\t    Tcl_DStringAppend(&reply, \"\\0-c \", 4);\n\t\t    Tcl_DStringAppend(&reply, buffer, TCL_INDEX_NONE);\n\t\t}\n\t\t(void) AppendPropCarefully(dispPtr->display, commWindow,\n\t\t\tdispPtr->commProperty, Tcl_DStringValue(&reply),\n\t\t\tTcl_DStringLength(&reply) + 1, NULL);\n\t\tXFlush(dispPtr->display);\n\t\tTcl_DStringFree(&reply);\n\t    }\n\t} else if ((*p == 'r') && (p[1] == 0)) {\n\t    int serial, code, gotSerial;\n\t    const char *errorInfo, *errorCode, *resultString;\n\t    PendingCommand *pcPtr;\n\n\t    /*\n\t     *----------------------------------------------------------\n\t     * This is a reply to some command that we sent out. Iterate over\n\t     * all of its options. Stop when we reach the end of the property\n\t     * or something that doesn't look like an option.\n\t     *----------------------------------------------------------\n\t     */\n\n\t    p += 2;\n\t    code = TCL_OK;\n\t    gotSerial = 0;\n\t    errorInfo = NULL;\n\t    errorCode = NULL;\n\t    resultString = \"\";\n\t    while (((p-propInfo) < (int) numItems) && (*p == '-')) {\n\t\tswitch (p[1]) {\n\t\tcase 'c':\n\t\t    if (sscanf(p+2, \" %d\", &code) != 1) {\n\t\t\tcode = TCL_OK;\n\t\t    }\n\t\t    break;\n\t\tcase 'e':\n\t\t    if (p[2] == ' ') {\n\t\t\terrorCode = p+3;\n\t\t    }\n\t\t    break;\n\t\tcase 'i':\n\t\t    if (p[2] == ' ') {\n\t\t\terrorInfo = p+3;\n\t\t    }\n\t\t    break;\n\t\tcase 'r':\n\t\t    if (p[2] == ' ') {\n\t\t\tresultString = p+3;\n\t\t    }\n\t\t    break;\n\t\tcase 's':\n\t\t    if (sscanf(p+2, \" %d\", &serial) == 1) {\n\t\t\tgotSerial = 1;\n\t\t    }\n\t\t    break;\n\t\t}\n\t\twhile (*p != 0) {\n\t\t    p++;\n\t\t}\n\t\tp++;\n\t    }\n\n\t    if (!gotSerial) {\n\t\tcontinue;\n\t    }\n\n\t    /*\n\t     * Give the result information to anyone who's waiting for it.\n\t     */\n\n\t    for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL;\n\t\t    pcPtr = pcPtr->nextPtr) {\n\t\tif ((serial != pcPtr->serial) || (pcPtr->result != NULL)) {\n\t\t    continue;\n\t\t}\n\t\tpcPtr->code = code;\n\t\tif (resultString != NULL) {\n\t\t    pcPtr->result = (char *)Tcl_Alloc(strlen(resultString) + 1);\n\t\t    strcpy(pcPtr->result, resultString);\n\t\t}\n\t\tif (code == TCL_ERROR) {\n\t\t    if (errorInfo != NULL) {\n\t\t\tpcPtr->errorInfo = (char *)Tcl_Alloc(strlen(errorInfo) + 1);\n\t\t\tstrcpy(pcPtr->errorInfo, errorInfo);\n\t\t    }\n\t\t    if (errorCode != NULL) {\n\t\t\tpcPtr->errorCode = (char *)Tcl_Alloc(strlen(errorCode) + 1);\n\t\t\tstrcpy(pcPtr->errorCode, errorCode);\n\t\t    }\n\t\t}\n\t\tpcPtr->gotResponse = 1;\n\t\tbreak;\n\t    }\n\t} else {\n\t    /*\n\t     * Didn't recognize this thing. Just skip through the next null\n\t     * character and try again.\n\t     */\n\n\t    while (*p != 0) {\n\t\tp++;\n\t    }\n\t    p++;\n\t}\n    }\n    XFree(propInfo);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * AppendPropCarefully --\n *\n *\tAppend a given property to a given window, but set up an X error\n *\thandler so that if the append fails this function can return an error\n *\tcode rather than having Xlib panic.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe given property on the given window is appended to. If this\n *\toperation fails and if pendingPtr is non-NULL, then the pending\n *\toperation is marked as complete with an error.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nAppendPropCarefully(\n    Display *display,\t\t/* Display on which to operate. */\n    Window window,\t\t/* Window whose property is to be modified. */\n    Atom property,\t\t/* Name of property. */\n    char *value,\t\t/* Characters to append to property. */\n    int length,\t\t\t/* Number of bytes to append. */\n    PendingCommand *pendingPtr)\t/* Pending command to mark complete if an\n\t\t\t\t * error occurs during the property op. NULL\n\t\t\t\t * means just ignore the error. */\n{\n    Tk_ErrorHandler handler;\n\n    handler = Tk_CreateErrorHandler(display, -1, -1, -1, AppendErrorProc,\n\t    pendingPtr);\n    XChangeProperty(display, window, property, XA_STRING, 8,\n\t    PropModeAppend, (unsigned char *) value, length);\n    Tk_DeleteErrorHandler(handler);\n}\n\n/*\n * The function below is invoked if an error occurs during the XChangeProperty\n * operation above.\n */\n\nstatic int\nAppendErrorProc(\n    void *clientData,\t/* Command to mark complete, or NULL. */\n    TCL_UNUSED(XErrorEvent *))\t/* Information about error. */\n{\n    PendingCommand *pendingPtr = (PendingCommand *)clientData;\n    PendingCommand *pcPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (pendingPtr == NULL) {\n\treturn 0;\n    }\n\n    /*\n     * Make sure this command is still pending.\n     */\n\n    for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL;\n\t    pcPtr = pcPtr->nextPtr) {\n\tif ((pcPtr == pendingPtr) && (pcPtr->result == NULL)) {\n\t    pcPtr->result = (char *)Tcl_Alloc(strlen(pcPtr->target) + 50);\n\t    snprintf(pcPtr->result, strlen(pcPtr->target) + 50, \"no application named \\\"%s\\\"\",\n\t\t    pcPtr->target);\n\t    pcPtr->code = TCL_ERROR;\n\t    pcPtr->gotResponse = 1;\n\t    break;\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * DeleteProc --\n *\n *\tThis function is invoked by Tcl when the \"send\" command is deleted in\n *\tan interpreter. It unregisters the interpreter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe interpreter given by riPtr is unregistered.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nDeleteProc(\n    void *clientData)\t/* Info about registration */\n{\n    RegisteredInterp *riPtr = (RegisteredInterp *)clientData;\n    RegisteredInterp *riPtr2;\n    NameRegistry *regPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    regPtr = RegOpen(riPtr->interp, riPtr->dispPtr, 1);\n    RegDeleteName(regPtr, riPtr->name);\n    RegClose(regPtr);\n\n    if (tsdPtr->interpListPtr == riPtr) {\n\ttsdPtr->interpListPtr = riPtr->nextPtr;\n    } else {\n\tfor (riPtr2 = tsdPtr->interpListPtr; riPtr2 != NULL;\n\t\triPtr2 = riPtr2->nextPtr) {\n\t    if (riPtr2->nextPtr == riPtr) {\n\t\triPtr2->nextPtr = riPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    Tcl_Free(riPtr->name);\n    riPtr->interp = NULL;\n    UpdateCommWindow(riPtr->dispPtr);\n    Tcl_EventuallyFree(riPtr, TCL_DYNAMIC);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SendRestrictProc --\n *\n *\tThis function filters incoming events when a \"send\" command is\n *\toutstanding. It defers all events except those containing send\n *\tcommands and results.\n *\n * Results:\n *\tFalse is returned except for property-change events on a commWindow.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_RestrictAction\nSendRestrictProc(\n    TCL_UNUSED(void *),\t\t/* Not used. */\n    XEvent *eventPtr)\t\t/* Event that just arrived. */\n{\n    TkDisplay *dispPtr;\n\n    if (eventPtr->type != PropertyNotify) {\n\treturn TK_DEFER_EVENT;\n    }\n    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;\n\t    dispPtr = dispPtr->nextPtr) {\n\tif ((eventPtr->xany.display == dispPtr->display)\n\t\t&& (eventPtr->xproperty.window\n\t\t== Tk_WindowId(dispPtr->commTkwin))) {\n\t    return TK_PROCESS_EVENT;\n\t}\n    }\n    return TK_DEFER_EVENT;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateCommWindow --\n *\n *\tThis function updates the list of application names stored on our\n *\tcommWindow. It is typically called when interpreters are registered\n *\tand unregistered.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe TK_APPLICATION property on the comm window is updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateCommWindow(\n    TkDisplay *dispPtr)\t\t/* Display whose commWindow is to be\n\t\t\t\t * updated. */\n{\n    Tcl_DString names;\n    RegisteredInterp *riPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    Tcl_DStringInit(&names);\n    for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;\n\t    riPtr = riPtr->nextPtr) {\n\tTcl_DStringAppendElement(&names, riPtr->name);\n    }\n    XChangeProperty(dispPtr->display, Tk_WindowId(dispPtr->commTkwin),\n\t    dispPtr->appNameProperty, XA_STRING, 8, PropModeReplace,\n\t    (unsigned char *) Tcl_DStringValue(&names),\n\t    Tcl_DStringLength(&names));\n    Tcl_DStringFree(&names);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTestsendCmd --\n *\n *\tThis function implements the \"testsend\" command. It provides a set of\n *\tfunctions for testing the \"send\" command and support function in\n *\ttkSend.c.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tDepends on option; see below.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpTestsendCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    enum {\n\tTESTSEND_BOGUS, TESTSEND_PROP, TESTSEND_SERIAL\n    };\n    static const char *const testsendOptions[] = {\n\t\"bogus\",   \"prop\",   \"serial\",  NULL\n    };\n    TkWindow *winPtr = (TkWindow *)clientData;\n    Tk_ErrorHandler handler;\n    int index;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"option ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,\n\t\tsizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (index == TESTSEND_BOGUS) {\n\thandler = Tk_CreateErrorHandler(winPtr->dispPtr->display, -1, -1, -1,\n\t\tNULL, NULL);\n\tXChangeProperty(winPtr->dispPtr->display,\n\t\tRootWindow(winPtr->dispPtr->display, 0),\n\t\twinPtr->dispPtr->registryProperty, XA_INTEGER, 32,\n\t\tPropModeReplace,\n\t\t(unsigned char *) \"This is bogus information\", 6);\n\tTk_DeleteErrorHandler(handler);\n    } else if (index == TESTSEND_PROP) {\n\tint result, actualFormat;\n\tunsigned long length, bytesAfter;\n\tAtom actualType, propName;\n\tchar *property, **propertyPtr = &property, *p, *end;\n\tWindow w;\n\n\tif ((objc != 4) && (objc != 5)) {\n\t\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\t\"prop window name ?value ?\");\n\t    return TCL_ERROR;\n\t}\n\tif (strcmp(Tcl_GetString(objv[2]), \"root\") == 0) {\n\t    w = RootWindow(winPtr->dispPtr->display, 0);\n\t} else if (strcmp(Tcl_GetString(objv[2]), \"comm\") == 0) {\n\t    w = Tk_WindowId(winPtr->dispPtr->commTkwin);\n\t} else {\n\t    w = strtoul(Tcl_GetString(objv[2]), &end, 0);\n\t}\n\tpropName = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));\n\tif (objc == 4) {\n\t    property = NULL;\n\t    result = XGetWindowProperty(winPtr->dispPtr->display, w, propName,\n\t\t    0, 100000, False, XA_STRING, &actualType, &actualFormat,\n\t\t    &length, &bytesAfter, (unsigned char **) propertyPtr);\n\t    if ((result == Success) && (actualType != None)\n\t\t    && (actualFormat == 8) && (actualType == XA_STRING)) {\n\t\tfor (p = property; (unsigned long)(p-property) < length; p++) {\n\t\t    if (*p == 0) {\n\t\t\t*p = '\\n';\n\t\t    }\n\t\t}\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(property, TCL_INDEX_NONE));\n\t    }\n\t    if (property != NULL) {\n\t\tXFree(property);\n\t    }\n\t} else if (Tcl_GetString(objv[4])[0] == 0) {\n\t    handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,\n\t\t    -1, -1, -1, NULL, NULL);\n\t    XDeleteProperty(winPtr->dispPtr->display, w, propName);\n\t    Tk_DeleteErrorHandler(handler);\n\t} else {\n\t    Tcl_DString tmp;\n\n\t    Tcl_DStringInit(&tmp);\n\t    for (p = Tcl_DStringAppend(&tmp, Tcl_GetString(objv[4]),\n\t\t    (int) strlen(Tcl_GetString(objv[4]))); *p != 0; p++) {\n\t\tif (*p == '\\n') {\n\t\t    *p = 0;\n\t\t}\n\t    }\n\t    handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,\n\t\t    -1, -1, -1, NULL, NULL);\n\t    XChangeProperty(winPtr->dispPtr->display, w, propName, XA_STRING,\n\t\t    8, PropModeReplace, (unsigned char*)Tcl_DStringValue(&tmp),\n\t\t    p-Tcl_DStringValue(&tmp));\n\t    Tk_DeleteErrorHandler(handler);\n\t    Tcl_DStringFree(&tmp);\n\t}\n    } else if (index == TESTSEND_SERIAL) {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(localData.sendSerial+1));\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixSysNotify.c",
    "content": "/*\n * tkUnixSysNotify.c --\n *\n *\ttkUnixSysNotify.c implements a \"sysnotify\" Tcl command which\n *\tpermits one to post system notifications based on the libnotify API.\n *\n * Copyright © 2020 Kevin Walzer\n * Copyright © 2020 Christian Werner for runtime linking\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkUnixInt.h\"\n\n/*\n * Runtime linking of libnotify.\n */\n\ntypedef int\t(*fn_ln_init)(const char *);\ntypedef void\t(*fn_ln_uninit)(void);\ntypedef void *\t(*fn_ln_notification_new)(const char *, const char *,\n\t\t\tconst char *, void *);\ntypedef int\t(*fn_ln_notification_show)(void *, int *);\n\nstatic struct {\n    int\t\t\t\tnopen;\n    Tcl_LoadHandle\t\tlib;\n    fn_ln_init\t\t\tinit;\n    fn_ln_uninit\t\tuninit;\n    fn_ln_notification_new\tnotification_new;\n    fn_ln_notification_show\tnotification_show;\n} ln_fns = {\n    0, NULL, NULL, NULL, NULL, NULL\n};\n\n#define notify_init\t\t\tln_fns.init\n#define notify_uninit\t\t\tln_fns.uninit\n#define notify_notification_new\t\tln_fns.notification_new\n#define notify_notification_show\tln_fns.notification_show\n\nTCL_DECLARE_MUTEX(ln_mutex);\n\n/*\n * Forward declarations for procedures defined in this file.\n */\n\nstatic Tcl_CmdDeleteProc SysNotifyDeleteCmd;\nstatic Tcl_ObjCmdProc2 SysNotifyCmd;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SysNotifyDeleteCmd --\n *\n *      Delete notification and clean up.\n *\n * Results:\n *\tWindow destroyed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSysNotifyDeleteCmd (\n    TCL_UNUSED(void *))\n{\n    Tcl_MutexLock(&ln_mutex);\n    if (--ln_fns.nopen == 0) {\n\tif (notify_uninit) {\n\t    notify_uninit();\n\t}\n\tif (ln_fns.lib != NULL) {\n\t    Tcl_FSUnloadFile(NULL, ln_fns.lib);\n\t}\n\tmemset(&ln_fns, 0, sizeof(ln_fns));\n    }\n    Tcl_MutexUnlock(&ln_mutex);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SysNotifyCreateCmd --\n *\n *      Create tray command and (unreal) window.\n *\n * Results:\n *\tIcon tray and hidden window created.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSysNotifyCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    const char *title;\n    const char *message;\n    const char *icon;\n    const char *appname = \"Wish\";\n    void *notif;\n\n    if (objc < 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"title message\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Pass strings to notification, and use a sane platform-specific\n     * icon in the alert.\n     */\n\n    title = Tcl_GetString(objv[1]);\n    message = Tcl_GetString(objv[2]);\n    icon = \"dialog-information\";\n\n\n    /* Use the appname for libnotify initialization\n     * See bug f63c37be3a for a discussion whether this should be\n     * allowed at all on safe interpreters\n     */\n    if (!Tcl_IsSafe(interp)) {\n\tappname = ((TkWindow *)Tk_MainWindow(interp))->nameUid;\n    }\n\n    /*\n     * Call to notify_init should go here to prevent test suite failure.\n     */\n\n    if (notify_init && notify_notification_new && notify_notification_show) {\n\tTcl_Encoding enc;\n\tTcl_DString dst, dsm;\n\n\tTcl_DStringInit(&dst);\n\tTcl_DStringInit(&dsm);\n\tenc = Tcl_GetEncoding(NULL, \"utf-8\");\n\tchar *dstStr = Tcl_UtfToExternalDString(enc, title, TCL_INDEX_NONE, &dst);\n\tchar *dsmStr = Tcl_UtfToExternalDString(enc, message, TCL_INDEX_NONE, &dsm);\n\tnotify_init(appname);\n\tnotif = notify_notification_new(dstStr, dsmStr, icon, NULL);\n\tnotify_notification_show(notif, NULL);\n\tTcl_DStringFree(&dsm);\n\tTcl_DStringFree(&dst);\n\tTcl_FreeEncoding(enc);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SysNotify_Init --\n *\n *      Initialize the command.\n *\n * Results:\n *\tCommand initialized.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nSysNotify_Init(\n    Tcl_Interp *interp)\n{\n    Tcl_MutexLock(&ln_mutex);\n    if (ln_fns.nopen == 0) {\n\tint i = 0;\n\tTcl_Obj *nameobj;\n\tstatic const char *lnlibs[] = {\n\t    \"libnotify.so.4\",\n\t    \"libnotify.so.3\",\n\t    \"libnotify.so.2\",\n\t    \"libnotify.so.1\",\n\t    \"libnotify.so\",\n\t    NULL\n\t};\n\n\twhile (lnlibs[i] != NULL) {\n\t    Tcl_ResetResult(interp);\n\t    nameobj = Tcl_NewStringObj(lnlibs[i], TCL_INDEX_NONE);\n\t    Tcl_IncrRefCount(nameobj);\n\t    if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &ln_fns.lib)\n\t\t    == TCL_OK) {\n\t\tTcl_DecrRefCount(nameobj);\n\t\tbreak;\n\t    }\n\t    Tcl_DecrRefCount(nameobj);\n\t    ++i;\n\t}\n\tif (ln_fns.lib != NULL) {\n#define LN_SYM(name)\t\t\t\t\t\t\t\\\n\t    ln_fns.name = (fn_ln_ ## name)\t\t\t\t\\\n\t\tTcl_FindSymbol(NULL, ln_fns.lib, \"notify_\" #name)\n\t    LN_SYM(init);\n\t    LN_SYM(uninit);\n\t    LN_SYM(notification_new);\n\t    LN_SYM(notification_show);\n#undef LN_SYM\n\t}\n    }\n    ln_fns.nopen++;\n    Tcl_MutexUnlock(&ln_mutex);\n    if (!notify_init) return TCL_OK;\n\n    Tcl_CreateObjCommand2(interp, \"::tk::sysnotify::_sysnotify\", SysNotifyCmd,\n\t    interp, SysNotifyDeleteCmd);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixSysTray.c",
    "content": "/*\n * tkUnixSysTray.c --\n *\n *\ttkUnixSysTray.c implements a \"systray\" Tcl command which permits to\n *\tchange the system tray/taskbar icon of a Tk toplevel window and\n *\tto post system notifications.\n *\n * Copyright © 2005 Anton Kovalenko\n * Copyright © 2020 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkUnixInt.h\"\n\n/* XEmbed definitions\n * See http://www.freedesktop.org/wiki/Standards_2fxembed_2dspec\n * */\n#define XEMBED_MAPPED           (1<<0)\n/* System tray opcodes\n * See http://www.freedesktop.org/wiki/Standards_2fsystemtray_2dspec\n * */\n#define SYSTEM_TRAY_REQUEST_DOCK    0\n#define SYSTEM_TRAY_BEGIN_MESSAGE   1\n#define SYSTEM_TRAY_CANCEL_MESSAGE  2\n\n/* Flags of widget configuration options */\n#define ICON_CONF_IMAGE         (1<<0)  /* Image changed */\n#define ICON_CONF_REDISPLAY     (1<<1)  /* Redisplay required */\n#define ICON_CONF_XEMBED        (1<<2)  /* Remapping or unmapping required */\n#define ICON_CONF_CLASS         (1<<3)   /* TODO WM_CLASS update required */\n#define ICON_CONF_FIRST_TIME    (1<<4)  /* For IconConfigureMethod invoked by the constructor */\n\n/* Widget states */\n#define ICON_FLAG_REDRAW_PENDING    (1<<0)\n#define ICON_FLAG_ARGB32            (1<<1)\n#define ICON_FLAG_DIRTY_EDGES       (1<<2)\n\n#define TKU_NO_BAD_WINDOW_BEGIN(display) \\\n    { Tk_ErrorHandler error__handler = \\\n\t    Tk_CreateErrorHandler(display, BadWindow, -1, -1, NULL, NULL);\n#define TKU_NO_BAD_WINDOW_END Tk_DeleteErrorHandler(error__handler); }\n\n/*Declaration for utility functions.*/\nstatic void TKU_WmWithdraw(Tk_Window winPtr, Tcl_Interp* interp);\nstatic Tk_Window TKU_GetWrapper(Tk_Window winPtr);\nvoid TKU_AddInput(Display* dpy, Window win, long add_to_mask);\nstatic Tk_Window TKU_Wrapper(Tk_Window w, Tcl_Interp* interp);\nstatic Window TKU_XID(Tk_Window w);\n\n/* Customized window withdraw */\nstatic void\nTKU_WmWithdraw(\n    Tk_Window winPtr,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    TkpWmSetState((TkWindow*)winPtr, WithdrawnState);\n}\n\n/* The wrapper should exist */\nstatic Tk_Window\nTKU_GetWrapper(\n    Tk_Window winPtr)\n{\n    return (Tk_Window)\n\t    TkpGetWrapperWindow((TkWindow*)winPtr);\n}\n\n/* Subscribe for extra X11 events (needed for MANAGER selection) */\nvoid\nTKU_AddInput(\n    Display* dpy,\n    Window win,\n    long add_to_mask)\n{\n    XWindowAttributes xswa;\n    TKU_NO_BAD_WINDOW_BEGIN(dpy)\n\tXGetWindowAttributes(dpy,win,&xswa);\n\tXSelectInput(dpy,win,xswa.your_event_mask|add_to_mask);\n    TKU_NO_BAD_WINDOW_END\n}\n\n/* Get Tk Window wrapper (make it exist if ny) */\nstatic Tk_Window\nTKU_Wrapper(\n    Tk_Window w,\n    Tcl_Interp* interp)\n{\n    Tk_Window wrapper = TKU_GetWrapper(w);\n    if (!wrapper) {\n\tTk_MakeWindowExist(w);\n\tTKU_WmWithdraw(w, interp);\n\tTk_MapWindow(w);\n\twrapper = (Tk_Window) TKU_GetWrapper(w);\n    }\n    return wrapper;\n}\n\n/* Return X window id for Tk window (make it exist if ny) */\nstatic Window\nTKU_XID(\n    Tk_Window w)\n{\n    Window xid = Tk_WindowId(w);\n    if (xid == None) {\n\tTk_MakeWindowExist(w);\n\txid = Tk_WindowId(w);\n    }\n    return xid;\n}\n\n/* Data structure representing dock widget */\ntypedef struct {\n    /* standard for widget */\n    Tk_Window tkwin, drawingWin;\n    Window wrapper;\n    Window myManager;\n    Window trayManager;\n\n    Tk_OptionTable options;\n    Tcl_Interp *interp;\n    Tcl_Command widgetCmd;\n\n    Tk_Image image; /* image to be drawn */\n\n    /* Only one of imageVisualInstance and photo is needed for argb32\n     * operations. Unless imageString changes, imageVisualInstance is\n     * always valid for the same drawingWin instance, but photo is\n     * invalidated by any \"whole image\" type change. */\n\n    Tk_Image imageVisualInstance; /* image instance for use with argb32 */\n    Tk_PhotoHandle photo;\t  /* !null if it's really a photo */\n\n    /* Offscreen pixmap is created for a given imageWidth,\n     * imageHeight, drawingWin, and invalidated (and freed) on image\n     * resize or drawingWin destruction.\n\n     * Contents of this pixmap is synced on demand; when image changes\n     * but is not resized, pixmap is marked as out-of-sync. Next time\n     * when redisplay is needed, pixmap is updated before drawing\n     * operation.\n     */\n\n    Pixmap offscreenPixmap;\n    /* There is no need to recreate GC ever; it remains valid once\n     * created */\n\n    GC offscreenGC;\n\n    /* XImage for drawing ARGB32 photo on offscreenPixmap.  Should be\n     * freed and nullified each time when a pixmap is freed.  Needed\n     * (and created) when redrawing an image being a photo on ARGB32\n     * offscreen pixmap. */\n    XImage *offscreenImage;\t/* for photo (argb32) drawing code */\n\n    Visual *bestVisual;\t\t/* Visual, when it's specified by tray\n\t\t\t\t * manager AND is guessed to be\n\t\t\t\t * ARGB32 */\n    Colormap bestColormap;\t/* Colormap for bestVisual */\n\n    Atom aMANAGER;\n    Atom a_NET_SYSTEM_TRAY_Sn;\n    Atom a_XEMBED_INFO;\n    Atom a_NET_SYSTEM_TRAY_MESSAGE_DATA;\n    Atom a_NET_SYSTEM_TRAY_OPCODE;\n    Atom a_NET_SYSTEM_TRAY_ORIENTATION;\n    Atom a_NET_SYSTEM_TRAY_VISUAL;\n\n    int flags; /* ICON_FLAG_ - see defines above */\n    int msgid; /* Last balloon message ID */\n    bool useShapeExt;\n\n    int x,y,width,height;\n    int imageWidth, imageHeight;\n    int requestedWidth, requestedHeight;\n    bool visible; /* whether XEMBED_MAPPED should be set */\n    bool docked;\t /* whether an icon should be docked */\n    Tcl_Obj *imageObj; /* option: -image */\n    Tcl_Obj *classObj; /* option: -class */\n} DockIcon;\n\n/*\n * Forward declarations for procedures defined in this file.\n */\n\nstatic Tcl_ObjCmdProc2 TrayIconCreateCmd;\nstatic Tcl_ObjCmdProc2 TrayIconObjectCmd;\nstatic int TrayIconConfigureMethod(DockIcon *icon, Tcl_Interp *interp,\n\tTcl_Size objc, Tcl_Obj *const objv[], int addflags);\nstatic int PostBalloon(DockIcon* icon, const char *utf8msg,\n\tlong timeout);\nstatic void CancelBalloon(DockIcon* icon, int msgid);\nstatic int QueryTrayOrientation(DockIcon* icon);\n\nstatic Tcl_CmdDeleteProc TrayIconDeleteProc;\nstatic Atom DockSelectionAtomFor(Tk_Window tkwin);\nstatic void DockToManager(DockIcon *icon);\nstatic void CreateTrayIconWindow(DockIcon *icon);\n\nstatic void TrayIconRequestSize(DockIcon* icon, int w, int h);\nstatic void TrayIconForceImageChange(DockIcon* icon);\nstatic void TrayIconUpdate(DockIcon* icon, int mask);\n\nstatic void EventuallyRedrawIcon(DockIcon* icon);\nstatic void DisplayIcon(void *cd);\n\nstatic void RetargetEvent(DockIcon *icon, XEvent *ev);\n\nstatic void TrayIconEvent(void *cd, XEvent* ev);\nstatic void UserIconEvent(void *cd, XEvent* ev);\nstatic void TrayIconWrapperEvent(void *cd, XEvent* ev);\nstatic int IconGenericHandler(void *cd, XEvent *ev);\n\nint Tktray_Init (Tcl_Interp* interp );\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconObjectCmd --\n *\n *\tManage attributes of tray icon.\n *\n * Results:\n *\tVarious values of the tray icon are set and retrieved.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTrayIconObjectCmd(\n    void *cd,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    DockIcon *icon = (DockIcon*)cd;\n    int bbox[4] = {0,0,0,0};\n    Tcl_Obj * bboxObj;\n    int wcmd;\n    int i;\n    XWindowAttributes xwa;\n    Window bogus;\n    int msgid;\n\n    enum {XWC_CONFIGURE = 0, XWC_CGET, XWC_BALLOON, XWC_CANCEL,\n\t    XWC_BBOX, XWC_DOCKED, XWC_ORIENTATION};\n    const char *st_wcmd[] = {\"configure\", \"cget\", \"balloon\", \"cancel\",\n\t    \"bbox\", \"docked\", \"orientation\", NULL};\n\n    long timeout = 0;\n    Tcl_Obj* optionValue;\n\n    if (objc<2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"subcommand ?args?\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[1], st_wcmd,\n\t    \"subcommand\", TCL_EXACT, &wcmd) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    switch (wcmd) {\n    case XWC_CONFIGURE:\n\treturn TrayIconConfigureMethod(icon,interp,objc-2,objv+2,0);\n\n    case XWC_CGET:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp,2,objv,\"option\");\n\t    return TCL_ERROR;\n\t}\n\toptionValue = Tk_GetOptionValue(interp,(char*)icon,\n\t\ticon->options,objv[2],icon->tkwin);\n\tif (optionValue) {\n\t    Tcl_SetObjResult(interp,optionValue);\n\t    return TCL_OK;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n\n    case XWC_BALLOON:\n\tif ((objc != 3) && (objc != 4)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"message ?timeout?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 4) {\n\t    if (Tcl_GetLongFromObj(interp,objv[3],&timeout) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tmsgid = PostBalloon(icon,Tcl_GetString(objv[2]), timeout);\n\tTcl_SetObjResult(interp,Tcl_NewIntObj(msgid));\n\treturn TCL_OK;\n\n    case XWC_CANCEL:\n\tif (objc != 3) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"messageId\");\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIntFromObj(interp,objv[2],&msgid) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (msgid) {\n\t    CancelBalloon(icon,msgid);\n\t}\n\treturn TCL_OK;\n\n    case XWC_BBOX:\n\tif (icon->drawingWin) {\n\t    XGetWindowAttributes(Tk_Display(icon->drawingWin),\n\t\t    TKU_XID(icon->drawingWin), &xwa);\n\n\t    XTranslateCoordinates(Tk_Display(icon->drawingWin),\n\t\t    TKU_XID(icon->drawingWin), xwa.root, 0,0,\n\t\t    &icon->x, &icon->y, &bogus);\n\t    bbox[0] = icon->x;\n\t    bbox[1] = icon->y;\n\t    bbox[2] = bbox[0] + icon->width - 1;\n\t    bbox[3] = bbox[1] + icon->height - 1;\n\t}\n\tbboxObj = Tcl_NewObj();\n\tfor (i = 0; i < 4; ++i) {\n\t    Tcl_ListObjAppendElement(interp, bboxObj, Tcl_NewIntObj(bbox[i]));\n\t}\n\tTcl_SetObjResult(interp, bboxObj);\n\treturn TCL_OK;\n\n    case XWC_DOCKED:\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(icon->myManager != None));\n\treturn TCL_OK;\n\n    case XWC_ORIENTATION:\n\tif (icon->myManager == None || icon->wrapper == None) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"none\", TCL_INDEX_NONE));\n\t} else {\n\t    switch(QueryTrayOrientation(icon)) {\n\t    case 0:\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"horizontal\", TCL_INDEX_NONE));\n\t\tbreak;\n\t    case 1:\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"vertical\", TCL_INDEX_NONE));\n\t\tbreak;\n\t    default:\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"unknown\", TCL_INDEX_NONE));\n\t\tbreak;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * QueryTrayOrientation --\n *\n *\tObtain the orientation of the tray icon.\n *\n * Results:\n *\tOrientation is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nQueryTrayOrientation(\n    DockIcon* icon)\n{\n    Atom retType = None;\n    int retFormat = 32;\n    unsigned long retNitems, retBytesAfter;\n    unsigned char *retProp = NULL;\n    int result = -1;\n\n    if (icon->wrapper != None && icon->myManager != None) {\n\tXGetWindowProperty(Tk_Display(icon->tkwin),\n\t\t\t   icon->myManager,\n\t\t\t   icon->a_NET_SYSTEM_TRAY_ORIENTATION,\n\t\t\t   /* offset */ 0,\n\t\t\t   /* length */ 1,\n\t\t\t   /* delete */ False,\n\t\t\t   /* type */ XA_CARDINAL,\n\t\t\t   &retType, &retFormat, &retNitems,\n\t\t\t   &retBytesAfter, &retProp);\n\tif (retType == XA_CARDINAL && retFormat == 32 && retNitems == 1) {\n\t    result = (int) *(long*)retProp;\n\t}\n\tif (retProp) {\n\t    XFree(retProp);\n\t}\n    }\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DockSelectionAtomFor --\n *\n *\tObtain the dock selection atom.\n *\n * Results:\n *\tSelection returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Atom\nDockSelectionAtomFor(\n    Tk_Window tkwin)\n{\n    char buf[256];\n    snprintf(buf,256,\"_NET_SYSTEM_TRAY_S%d\",Tk_ScreenNumber(tkwin));\n    return Tk_InternAtom(tkwin,buf);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XembedSetState --\n *\n *\tSet the xembed state.\n *\n * Results:\n *\tUpdates the xembed state.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nXembedSetState(\n    DockIcon *icon,\n    long xembedState)\n{\n    long info[] = { 0, 0 };\n    info[1] = xembedState;\n    if (icon->drawingWin) {\n\tXChangeProperty(Tk_Display(icon->drawingWin),\n\t\t\ticon->wrapper,\n\t\t\ticon->a_XEMBED_INFO,\n\t\t\ticon->a_XEMBED_INFO, 32,\n\t\t\tPropModeReplace, (unsigned char*)info, 2);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XembedRequestDock --\n *\n *\tObtain the docking window.\n *\n * Results:\n *\tThe dock window is requested.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nXembedRequestDock(\n    DockIcon *icon)\n{\n    Tk_Window tkwin = icon->drawingWin;\n    XEvent ev;\n    Display *dpy = Tk_Display(tkwin);\n\n    memset(&ev, 0, sizeof(ev));\n    ev.xclient.type = ClientMessage;\n    ev.xclient.window = icon->myManager;\n    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;\n    ev.xclient.format = 32;\n    ev.xclient.data.l[0] = 0;\n    ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;\n    ev.xclient.data.l[2] = icon->wrapper;\n    ev.xclient.data.l[3] = 0;\n    ev.xclient.data.l[4] = 0;\n    XSendEvent(dpy, icon->myManager, True, StructureNotifyMask|SubstructureNotifyMask, &ev);\n }\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckArgbVisual --\n *\n *\tFind out if a visual is recommended and if it looks like argb32.\n *\n * Results:\n *\tRender the visual as needed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCheckArgbVisual(\n    DockIcon *icon)\n{\n    /* Find out if a visual is recommended and if it looks like argb32.\n     * For such visuals we should:\n     * Recreate a window if it's created but the depth is wrong;\n     * Don't use ParentRelative but blank background.\n     * For photo images, draw into a window by XPutImage.\n     */\n    Atom retType = None;\n    int retFormat = 32;\n    unsigned long retNitems, retBytesAfter;\n    unsigned char *retProp = NULL;\n    Visual *match = NULL;\n    int depth = 0;\n    Colormap cmap = None;\n\n    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))\n\tXGetWindowProperty(Tk_Display(icon->tkwin),\n\t\ticon->trayManager,\n\t\ticon->a_NET_SYSTEM_TRAY_VISUAL,\n\t\t/* offset */ 0,\n\t\t/* length */ 1,\n\t\t/* delete */ False,\n\t\t/* type */ XA_VISUALID,\n\t\t&retType, &retFormat, &retNitems,\n\t\t&retBytesAfter, &retProp);\n    TKU_NO_BAD_WINDOW_END\n    if (retType == XA_VISUALID &&\n\t    retNitems == 1 &&\n\t    retFormat == 32) {\n\tchar numeric[256];\n\tsnprintf(numeric,256,\"%ld\",*(long*)retProp);\n\tXFree(retProp);\n\tmatch = Tk_GetVisual(icon->interp, icon->tkwin,\n\t\tnumeric, &depth, &cmap);\n    }\n    if (match&& depth == 32 &&\n\t    match->red_mask == 0xFF0000UL &&\n\t    match->green_mask == 0x00FF00UL &&\n\t    match->blue_mask == 0x0000FFUL) {\n\ticon->bestVisual = match;\n\ticon->bestColormap = cmap;\n    } else {\n\ticon->bestVisual = NULL;\n\ticon->bestColormap = None;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateTrayIconWindow --\n *\n *\tCreate and configure the window for the icon tray.\n *\n * Results:\n *\tThe window is created and displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCreateTrayIconWindow(\n    DockIcon *icon)\n{\n    Tcl_InterpState saved;\n    Tk_Window tkwin;\n    Tk_Window wrapper;\n    XSetWindowAttributes attr;\n\n    saved = Tcl_SaveInterpState(icon->interp, TCL_OK);\n    /* Use the same name (tail) as the widget name, to enable\n     * name-based icon management for supporting trays, as promised by\n     * the docs.\n     */\n    tkwin = icon->drawingWin = Tk_CreateWindow(icon->interp, icon->tkwin,\n\t    Tk_Name(icon->tkwin), \"\");\n    if (tkwin) {\n\tTk_SetClass(icon->drawingWin, Tcl_GetString(icon->classObj));\n\tTk_CreateEventHandler(icon->drawingWin,ExposureMask|StructureNotifyMask|\n\t\tButtonPressMask|ButtonReleaseMask|\n\t\tEnterWindowMask|LeaveWindowMask|PointerMotionMask,\n\t\tTrayIconEvent, icon);\n\tif(icon->bestVisual) {\n\t    Tk_SetWindowVisual(icon->drawingWin,icon->bestVisual,\n\t\t    32,icon->bestColormap);\n\t    icon->flags |= ICON_FLAG_ARGB32;\n\t    Tk_SetWindowBackground(tkwin, 0);\n\t} else {\n\t    Tk_SetWindowBackgroundPixmap(tkwin, ParentRelative);\n\t    icon->flags &= ~ICON_FLAG_ARGB32;\n\t}\n\tTk_MakeWindowExist(tkwin);\n\tTKU_WmWithdraw(tkwin,icon->interp);\n\twrapper = TKU_Wrapper(tkwin,icon->interp);\n\n\tattr.override_redirect = True;\n\tTk_ChangeWindowAttributes(wrapper,CWOverrideRedirect,&attr);\n\tTk_CreateEventHandler(wrapper,StructureNotifyMask,TrayIconWrapperEvent, icon);\n\tif (!icon->bestVisual) {\n\t    Tk_SetWindowBackgroundPixmap(wrapper, ParentRelative);\n\t} else {\n\t    Tk_SetWindowBackground(tkwin, 0);\n\t}\n\ticon->wrapper = TKU_XID(wrapper);\n\tTrayIconForceImageChange(icon);\n    } else {\n\tTcl_BackgroundError(icon->interp);\n    }\n    Tcl_RestoreInterpState(icon->interp, saved);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DockToManager --\n *\n *\tHelper function to manage icon in display.\n *\n * Results:\n *\tIcon is created and displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDockToManager(\n    DockIcon *icon)\n{\n    icon->myManager = icon->trayManager;\n    Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid(\"IconCreate\"), NULL);\n    XembedSetState(icon, icon->visible ? XEMBED_MAPPED : 0);\n    XembedRequestDock(icon);\n}\n\f\nstatic const\nTk_OptionSpec IconOptionSpec[] = {\n    {TK_OPTION_STRING,\"-image\",\"image\",\"Image\",\n\tNULL, offsetof(DockIcon, imageObj), TCL_INDEX_NONE,\n\tTK_OPTION_NULL_OK, NULL,\n\tICON_CONF_IMAGE | ICON_CONF_REDISPLAY},\n    {TK_OPTION_STRING,\"-class\",\"class\",\"Class\",\n\t\"TrayIcon\", offsetof(DockIcon, classObj), TCL_INDEX_NONE,\n\t0, NULL, ICON_CONF_CLASS},\n    {TK_OPTION_BOOLEAN,\"-docked\",\"docked\",\"Docked\",\n\t\"1\", TCL_INDEX_NONE, offsetof(DockIcon, docked), TK_OPTION_VAR(bool), NULL,\n\tICON_CONF_XEMBED | ICON_CONF_REDISPLAY},\n    {TK_OPTION_BOOLEAN,\"-shape\",\"shape\",\"Shape\",\n\t\"0\", TCL_INDEX_NONE, offsetof(DockIcon, useShapeExt), TK_OPTION_VAR(bool), NULL,\n\tICON_CONF_IMAGE | ICON_CONF_REDISPLAY},\n    {TK_OPTION_BOOLEAN,\"-visible\",\"visible\",\"Visible\",\n\t\"1\", TCL_INDEX_NONE, offsetof(DockIcon, visible), TK_OPTION_VAR(bool), NULL,\n\tICON_CONF_XEMBED | ICON_CONF_REDISPLAY},\n    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconRequestSize --\n *\n *\tSet icon size.\n *\n * Results:\n *\tIcon size is obtained/set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconRequestSize(\n    DockIcon* icon,\n    int w,\n    int h)\n{\n    if (icon->drawingWin) {\n\tif (icon->requestedWidth != w ||\n\t\ticon->requestedHeight != h) {\n\t    Tk_SetMinimumRequestSize(icon->drawingWin,w,h);\n\t    Tk_GeometryRequest(icon->drawingWin,w,h);\n\t    Tk_SetGrid(icon->drawingWin,1,1,w,h);\n\t    icon->requestedWidth = w;\n\t    icon->requestedHeight = h;\n\t}\n    } else {\n\t/* Sign that no size is requested yet */\n\ticon->requestedWidth = 0;\n\ticon->requestedHeight = 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconImageChanged --\n *\n *\tFires when icon state changes.\n *\n * Results:\n *\tIcon changes are rendered.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconImageChanged(\n    void *cd,\n    int x,\n    int y,\n    int w,\n    int h,\n    int imgw,\n    int imgh)\n{\n    DockIcon *icon = (DockIcon*) cd;\n    if (imgw != icon->imageWidth || imgh != icon->imageHeight) {\n\tif (icon->offscreenImage) {\n\t    XDestroyImage(icon->offscreenImage);\n\t    icon->offscreenImage = NULL;\n\t}\n\tif (icon->offscreenPixmap) {\n\t    /* its size is bad */\n\t    Tk_FreePixmap(Tk_Display(icon->tkwin), icon->offscreenPixmap);\n\t    icon->offscreenPixmap = None;\n\t}\n\t/* if some image dimension decreases,\n\t * empty areas around the image should be cleared */\n\tif (imgw < icon->imageWidth || imgh < icon->imageHeight) {\n\t    icon->flags |= ICON_FLAG_DIRTY_EDGES;\n\t}\n    }\n    icon->imageWidth = imgw;\n    icon->imageHeight = imgh;\n    if (imgw == w && imgh == h && x == 0 && y == 0) {\n\ticon->photo = NULL;\t/* invalidate */\n    }\n    TrayIconRequestSize(icon,imgw,imgh);\n    EventuallyRedrawIcon(icon);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IgnoreImageChange --\n *\n *\tCurrently no-op.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nIgnoreImageChange(\n    TCL_UNUSED(void *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ForceImageChange --\n *\n *\tPush icon changes through.\n *\n * Results:\n *\tIcon image is updated.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconForceImageChange(\n    DockIcon* icon)\n{\n    if (icon->image) {\n\tint w,h;\n\tTk_SizeOfImage(icon->image,&w,&h);\n\tTrayIconImageChanged(icon, 0, 0, w, h, w, h);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n *  EventuallyRedrawIcon --\n *\n *\tUpdate image icon.\n *\n * Results:\n *\tIcon image is updated.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEventuallyRedrawIcon(\n    DockIcon* icon)\n{\n    if (icon->drawingWin && icon->myManager) {\t/* don't redraw invisible icon */\n\tif (!(icon->flags & ICON_FLAG_REDRAW_PENDING)) { /* don't schedule multiple redraw ops */\n\t    icon->flags |= ICON_FLAG_REDRAW_PENDING;\n\t    Tcl_DoWhenIdle(DisplayIcon, icon);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n *  DisplayIcon --\n *\n *\tMain function for displaying icon.\n *\n * Results:\n *\tIcon image is displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDisplayIcon(\n    void *cd)\n{\n    DockIcon *icon = (DockIcon*)cd;\n    int w = icon->imageWidth, h = icon->imageHeight;\n    int imgx, imgy, outx, outy, outw, outh;\n    imgx = (icon->width >= w) ? 0 : -(icon->width - w)/2;\n    imgy = (icon->height >= h) ? 0 : -(icon->height - h)/2;\n    outx = (icon->width >= w) ? (icon->width - w)/2 : 0;\n    outy = (icon->height >= h) ? (icon->height - h)/2 : 0;\n    outw = (icon->width >= w) ? w : icon->width;\n    outh = (icon->height >= h) ? h : icon->height;\n\n    icon->flags &= (~ICON_FLAG_REDRAW_PENDING);\n\n    if (icon->drawingWin && icon->docked) {\n\tif (icon->flags & ICON_FLAG_ARGB32) {\n\t    /* ARGB32 redraw: never use a ParentRelative method, and\n\t       no need to clear window except FIXME when its size changed.\n\t       Draw on the offscreen pixmap instead, then copy to the window.\n\t     */\n\t    if (icon->offscreenPixmap == None) {\n\t\ticon->offscreenPixmap = Tk_GetPixmap(Tk_Display(icon->drawingWin),\n\t\t\tTk_WindowId(icon->drawingWin), w, h, 32);\n\t    }\n\t    if (!icon->photo) {\n\t\ticon->photo = Tk_FindPhoto(icon->interp, Tcl_GetString(icon->imageObj));\n\t    }\n\t    if (!icon->photo && !icon->imageVisualInstance) {\n\t\tTcl_InterpState saved\n\t\t\t= Tcl_SaveInterpState(icon->interp, TCL_OK);\n\t\ticon->imageVisualInstance = Tk_GetImage(icon->interp,icon->drawingWin,\n\t\t\tTcl_GetString(icon->imageObj), IgnoreImageChange, NULL);\n\t\tTcl_RestoreInterpState(icon->interp,saved);\n\t    }\n\t    if (icon->photo && !icon->offscreenImage) {\n\t\ticon->offscreenImage = XGetImage(Tk_Display(icon->drawingWin),\n\t\t\ticon->offscreenPixmap, 0, 0, w, h, AllPlanes, ZPixmap);\n\t    }\n\t    if (icon->offscreenGC == NULL) {\n\t\tXGCValues gcv;\n\t\tgcv.function = GXcopy;\n\t\tgcv.plane_mask = AllPlanes;\n\t\tgcv.foreground = 0;\n\t\tgcv.background = 0;\n\t\ticon->offscreenGC = Tk_GetGC(icon->drawingWin,\n\t\t\tGCFunction|GCPlaneMask|GCForeground|GCBackground, &gcv);\n\t    }\n\t    if (icon->flags & ICON_FLAG_DIRTY_EDGES) {\n\t\tXClearWindow(Tk_Display(icon->drawingWin), TKU_XID(icon->drawingWin));\n\t\ticon->flags &= ~ICON_FLAG_DIRTY_EDGES;\n\t    }\n\t    if (icon->photo) {\n\t\tTk_PhotoImageBlock pib;\n\t\tint cx,cy;\n\t\tXImage *xim = icon->offscreenImage;\n\t\t/* redraw photo using raw data */\n\t\tTk_PhotoGetImage(icon->photo,&pib);\n\t\tfor (cy = 0; cy < h; ++cy) {\n\t\t    for (cx = 0; cx < w; ++cx) {\n\t\t\tXPutPixel(xim,cx,cy,\n\t\t\t\t  (*(pib.pixelPtr +\n\t\t\t\t     pib.pixelSize*cx +\n\t\t\t\t     pib.pitch*cy +\n\t\t\t\t     pib.offset[0])<<16) |\n\t\t\t\t  (*(pib.pixelPtr +\n\t\t\t\t     pib.pixelSize*cx +\n\t\t\t\t     pib.pitch*cy +\n\t\t\t\t     pib.offset[1])<<8) |\n\t\t\t\t  (*(pib.pixelPtr +\n\t\t\t\t     pib.pixelSize*cx +\n\t\t\t\t     pib.pitch*cy +\n\t\t\t\t     pib.offset[2])) |\n\t\t\t\t  (pib.offset[3] ?\n\t\t\t\t   (*(pib.pixelPtr +\n\t\t\t\t      pib.pixelSize*cx +\n\t\t\t\t      pib.pitch*cy +\n\t\t\t\t      pib.offset[3])<<24) : 0));\n\t\t    }\n\t\t}\n\t\tXPutImage(Tk_Display(icon->drawingWin),\n\t\t\ticon->offscreenPixmap,\n\t\t\ticon->offscreenGC,\n\t\t\ticon->offscreenImage,\n\t\t\t0,0,0,0,w,h);\n\t    } else {\n\t\tXFillRectangle(Tk_Display(icon->drawingWin),\n\t\t\ticon->offscreenPixmap,\n\t\t\ticon->offscreenGC,\n\t\t\t0,0,w,h);\n\t\tif (icon->imageVisualInstance) {\n\t\t    Tk_RedrawImage(icon->imageVisualInstance,\n\t\t\t    0,0,w,h,\n\t\t\t    icon->offscreenPixmap,\n\t\t\t    0,0);\n\t\t}\n\t    }\n\t    XCopyArea(Tk_Display(icon->drawingWin),\n\t\t    icon->offscreenPixmap,\n\t\t    TKU_XID(icon->drawingWin),\n\t\t    icon->offscreenGC,\n\t\t    imgx,imgy,outw,outh,outx,outy);\n\t} else {\n\t    /* Non-argb redraw: clear window and draw an image over it.\n\t       For photos it gives a correct alpha blending with a parent\n\t       window background, even if it's a fancy pixmap (proved to\n\t       work with lxpanel fancy backgrounds).\n\t    */\n\t    XClearWindow(Tk_Display(icon->drawingWin),\n\t\t    TKU_XID(icon->drawingWin));\n\t    if (icon->image && icon->visible) {\n\t\tTk_RedrawImage(icon->image,imgx,imgy,outw,outh,\n\t\t\tTKU_XID(icon->drawingWin), outx, outy);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n *  RetargetEvent --\n *\n *\tRedirect X events to widgets.\n *\n * Results:\n *\tIcon image is displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRetargetEvent(\n    DockIcon *icon,\n    XEvent *ev)\n{\n    int send = 0;\n    Window* saveWin1 = NULL, *saveWin2 = NULL;\n    if (!icon->visible) {\n\treturn;\n    }\n    switch (ev->type) {\n    case MotionNotify:\n\tsend = 1;\n\tsaveWin1 = &ev->xmotion.subwindow;\n\tsaveWin2 = &ev->xmotion.window;\n\tbreak;\n    case LeaveNotify:\n    case EnterNotify:\n\tsend = 1;\n\tsaveWin1 = &ev->xcrossing.subwindow;\n\tsaveWin2 = &ev->xcrossing.window;\n\tbreak;\n    case ButtonPress:\n    case ButtonRelease:\n\tsend = 1;\n\tsaveWin1 = &ev->xbutton.subwindow;\n\tsaveWin2 = &ev->xbutton.window;\n\tbreak;\n    case MappingNotify:\n\tsend = 1;\n\tsaveWin1 = &ev->xmapping.window;\n    }\n    if (saveWin1) {\n\tTk_MakeWindowExist(icon->tkwin);\n\t*saveWin1 = Tk_WindowId(icon->tkwin);\n\tif (saveWin2) *saveWin2 = *saveWin1;\n    }\n    if (send) {\n\tev->xany.send_event = 0x147321ac;\n\tTk_HandleEvent(ev);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n *  TrayIconWrapperEvent --\n *\n *\tEnsure automapping in root window is done in withdrawn state.\n *\n * Results:\n *\tIcon image is displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconWrapperEvent(\n    void *cd,\n    XEvent* ev)\n{\n  /* Some embedders, like Docker, add icon windows to save set\n   * (XAddToSaveSet), so when they crash the icon is reparented to root.\n   * We have to make sure that automatic mapping in root is done in\n   * withdrawn state (no way to prevent it entirely)\n   */\n    DockIcon *icon = (DockIcon*)cd;\n    XWindowAttributes attr;\n    if (icon->drawingWin) {\n\tswitch(ev->type) {\n\tcase ReparentNotify:\n\t    /* With virtual roots and screen roots etc, the only way\n\t       to check for reparent-to-root is to ask for this root\n\t       first */\n\t    XGetWindowAttributes(ev->xreparent.display,\n\t\t    ev->xreparent.window, &attr);\n\t    if (attr.root == ev->xreparent.parent) {\n\t\t/* upon reparent to root, */\n\t\tif (icon->drawingWin) {\n\t\t    /* we were sent away to root */\n\t\t    TKU_WmWithdraw(icon->drawingWin,icon->interp);\n\t\t    if (icon->myManager) {\n\t\t\tTk_SendVirtualEvent(icon->tkwin,Tk_GetUid(\"IconDestroy\"), NULL);\n\t\t    }\n\t\t    icon->myManager = None;\n\t\t}\n\t    } /* Reparenting into some other embedder is theoretically possible,\n\t       * and everything would just work in this case.\n\t       */\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconEvent --\n *\n *\tHandle X events.\n *\n * Results:\n *\tEvents are handled and processed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconEvent(\n    void *cd,\n    XEvent* ev)\n{\n    DockIcon *icon = (DockIcon*)cd;\n\n    switch (ev->type) {\n    case Expose:\n\tif (!ev->xexpose.count) {\n\t    EventuallyRedrawIcon(icon);\n\t}\n\tbreak;\n\n    case DestroyNotify:\n\t/* If anonymous window is destroyed first, then either\n\t * something went wrong with a tray (if -visible) or we just\n\t * reconfigured to invisibility: nothing to be done in both\n\t * cases.\n\t * If unreal window is destroyed first, freeing the data structures\n\t * is the only thing to do.\n\t */\n\tif (icon->myManager) {\n\t    Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid(\"IconDestroy\"), NULL);\n\t}\n\tTcl_CancelIdleCall(DisplayIcon, icon);\n\ticon->flags &= ~ICON_FLAG_REDRAW_PENDING;\n\ticon->drawingWin = NULL;\n\ticon->requestedWidth = 0; /* trigger re-request on recreation */\n\ticon->requestedHeight = 0;\n\ticon->wrapper = None;\n\ticon->myManager = None;\n\tbreak;\n\n    case ConfigureNotify:\n\tTk_SendVirtualEvent(icon->tkwin,Tk_GetUid(\"IconConfigure\"), NULL);\n\tif (icon->width != ev->xconfigure.width ||\n\t\ticon->height != ev->xconfigure.height) {\n\t    icon->width = ev->xconfigure.width;\n\t    icon->height = ev->xconfigure.height;\n\t    icon->flags |= ICON_FLAG_DIRTY_EDGES;\n\t    EventuallyRedrawIcon(icon);\n\t}\n\tRetargetEvent(icon,ev);\n\tbreak;\n\n    case MotionNotify:  /* fall through */\n    case ButtonPress:   /* fall through */\n    case ButtonRelease: /* fall through */\n    case EnterNotify:   /* fall through */\n    case LeaveNotify:\n\tRetargetEvent(icon,ev);\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UserIconEvent --\n *\n *\tHandle user events.\n *\n * Results:\n *\tEvents are handled and processed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUserIconEvent(\n    void *cd,\n    XEvent* ev)\n{\n    DockIcon *icon = (DockIcon*)cd;\n\n    switch (ev->type) {\n\n    case DestroyNotify:\n\tTk_DeleteGenericHandler(IconGenericHandler, icon);\n\tif(icon->drawingWin) {\n\t    icon->visible = 0;\n\t    Tcl_CancelIdleCall(DisplayIcon, icon);\n\t    icon->flags &= ~ICON_FLAG_REDRAW_PENDING;\n\t    Tk_DestroyWindow(icon->drawingWin);\n\t}\n\tif(icon->imageVisualInstance) {\n\t    Tk_FreeImage(icon->imageVisualInstance);\n\t    icon->image = NULL;\n\t}\n\tif(icon->offscreenImage) {\n\t    XDestroyImage(icon->offscreenImage);\n\t    icon->offscreenImage = NULL;\n\t}\n\tif(icon->offscreenGC) {\n\t    Tk_FreeGC(Tk_Display(icon->tkwin),icon->offscreenGC);\n\t    icon->offscreenGC = NULL;\n\t}\n\tif(icon->offscreenPixmap) {\n\t    Tk_FreePixmap(Tk_Display(icon->tkwin),icon->offscreenPixmap);\n\t}\n\tif(icon->image) {\n\t    Tk_FreeImage(icon->image);\n\t    icon->image = NULL;\n\t}\n\tif(icon->widgetCmd)\n\t    Tcl_DeleteCommandFromToken(icon->interp,icon->widgetCmd);\n\tTk_FreeConfigOptions((char*)icon, icon->options, icon->tkwin);\n\tbreak;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PostBalloon --\n *\n *\tDisplay tooltip/balloon window over tray icon.\n *\n * Results:\n *\tWindow is displayed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPostBalloon(\n    DockIcon *icon,\n    const char *utf8msg,\n    long timeout)\n{\n    Tk_Window tkwin = icon -> tkwin;\n    Display* dpy = Tk_Display(tkwin);\n    int length = strlen(utf8msg);\n    XEvent ev;\n\n    if (!(icon->drawingWin) || (icon->myManager == None)) {\n\treturn 0;\n    }\n\n    /* overflow protection */\n    if (icon->msgid < 0) {\n\ticon->msgid = 0;\n    }\n\n    memset(&ev, 0, sizeof(ev));\n    ev.xclient.type = ClientMessage;\n    ev.xclient.window = icon->wrapper;\n    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;\n    ev.xclient.format = 32;\n    ev.xclient.data.l[0] = CurrentTime;\n    ev.xclient.data.l[1] = SYSTEM_TRAY_BEGIN_MESSAGE;\n    ev.xclient.data.l[2] = timeout;\n    ev.xclient.data.l[3] = length;\n    ev.xclient.data.l[4] = ++icon->msgid;\n    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))\n\tXSendEvent(dpy, icon->myManager , True, StructureNotifyMask|SubstructureNotifyMask, &ev);\n\tXSync(dpy, False);\n\n\t/* Sending message elements */\n\twhile (length>0) {\n\t    ev.type = ClientMessage;\n\t    ev.xclient.window = icon->wrapper;\n\t    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_MESSAGE_DATA;\n\t    ev.xclient.format = 8;\n\t    memset(ev.xclient.data.b,0,20);\n\t    strncpy(ev.xclient.data.b,utf8msg,length<20?length:20);\n\t    XSendEvent(dpy, icon->myManager, True, StructureNotifyMask|SubstructureNotifyMask, &ev);\n\t    XSync(dpy,False);\n\t    utf8msg += 20;\n\t    length -= 20;\n\t}\n    TKU_NO_BAD_WINDOW_END;\n    return icon->msgid;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CancelBalloon --\n *\n *\tRemove balloon from display over tray icon.\n *\n * Results:\n *\tWindow is destroyed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCancelBalloon(\n    DockIcon *icon,\n    int msgid)\n{\n    Tk_Window tkwin = icon -> tkwin;\n    Display* dpy = Tk_Display(tkwin);\n    XEvent ev;\n\n    if (!(icon->drawingWin) || (icon->myManager == None)) {\n\treturn;\n    }\n    /* overflow protection */\n    if (icon->msgid < 0) {\n\ticon->msgid = 0;\n    }\n\n    memset(&ev, 0, sizeof(ev));\n    ev.type = ClientMessage;\n    ev.xclient.window = icon->wrapper;\n    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;\n    ev.xclient.format = 32;\n    ev.xclient.data.l[0] = CurrentTime;\n    ev.xclient.data.l[1] = SYSTEM_TRAY_CANCEL_MESSAGE;\n    ev.xclient.data.l[2]  =msgid;\n    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))\n\tXSendEvent(dpy, icon->myManager , True,\n\t\tStructureNotifyMask|SubstructureNotifyMask, &ev);\n    TKU_NO_BAD_WINDOW_END\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * IconGenericHandler --\n *\n *\tProcess non-tk events.\n *\n * Results:\n *\tEvents are processed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nIconGenericHandler(\n    void *cd,\n    XEvent *ev)\n{\n    DockIcon *icon = (DockIcon*)cd;\n\n    if ((ev->type == ClientMessage) &&\n\t    (ev->xclient.message_type == icon->aMANAGER) &&\n\t    ((Atom)ev->xclient.data.l[1] == icon->a_NET_SYSTEM_TRAY_Sn)) {\n\ticon->trayManager = (Window)ev->xclient.data.l[2];\n\tXSelectInput(ev->xclient.display,icon->trayManager,StructureNotifyMask);\n\tif (icon->myManager == None) {\n\t    TrayIconUpdate(icon, ICON_CONF_XEMBED);\n\t}\n\treturn 1;\n    }\n    if (ev->type == DestroyNotify) {\n\tif (ev->xdestroywindow.window == icon->trayManager) {\n\t    icon->trayManager = None;\n\t}\n\tif (ev->xdestroywindow.window == icon->myManager) {\n\t    icon->myManager = None;\n\t    icon->wrapper = None;\n\t    if (icon->drawingWin) {\n\t\tTk_DestroyWindow(icon->drawingWin);\n\t\ticon->drawingWin = NULL;\n\t    }\n\t}\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconUpdate --\n *\n *\tGet in touch with new options that are certainly valid.\n *\n * Results:\n *\tOptions updated.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconUpdate(\n    DockIcon *icon,\n    int mask)\n{\n    /* why should someone need this option?\n     * anyway, let's handle it if we provide it.\n     */\n    if (mask & ICON_CONF_CLASS) {\n\tif (icon->drawingWin) {\n\t    Tk_SetClass(icon->drawingWin,Tk_GetUid(Tcl_GetString(icon->classObj)));\n\t}\n    }\n    /*\n     * First, ensure right icon visibility.\n     * If should be visible and not yet managed,\n     * we have to get the tray or wait for it.\n     * If should be invisible and managed,\n     * real-window is simply destroyed.\n     * If should be invisible and not managed,\n     * generic handler should be abandoned.\n     */\n    if (mask & ICON_CONF_XEMBED) {\n\tif (icon->myManager == None &&\n\t\ticon->trayManager != None &&\n\t\ticon->docked) {\n\t    CheckArgbVisual(icon);\n\t    if (icon->drawingWin &&\n\t\t    ((icon->bestVisual && !(icon->flags & ICON_FLAG_ARGB32)) ||\n\t\t     (!icon->bestVisual && (icon->flags & ICON_FLAG_ARGB32)))) {\n\t\ticon->myManager = None;\n\t\ticon->wrapper = None;\n\t\ticon->requestedWidth = icon->requestedHeight = 0;\n\t\tTk_DestroyWindow(icon->drawingWin);\n\t\ticon->drawingWin = NULL;\n\t    }\n\t    if (!icon->drawingWin) {\n\t\tCreateTrayIconWindow(icon);\n\t    }\n\t    if (icon->drawingWin) {\n\t\tDockToManager(icon);\n\t    }\n\t}\n\tif (icon->myManager != None &&\n\t\ticon->drawingWin != NULL &&\n\t\t!icon->docked) {\n\t    Tk_DestroyWindow(icon->drawingWin);\n\t    icon->drawingWin = NULL;\n\t    icon->myManager = None;\n\t    icon->wrapper = None;\n\t}\n\tif (icon->drawingWin) {\n\t    XembedSetState(icon, icon->visible ? XEMBED_MAPPED : 0);\n\t}\n    }\n    if (mask & ICON_CONF_IMAGE) {\n\tTrayIconForceImageChange(icon);\n    }\n    if (mask & ICON_CONF_REDISPLAY) {\n\tEventuallyRedrawIcon(icon);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconConfigureMethod --\n *\n *      Returns TCL_ERROR if some option is invalid,\n *      or else retrieve resource references and free old resources.\n *\n * Results:\n *\tWidget configured.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTrayIconConfigureMethod(\n    DockIcon *icon,\n    Tcl_Interp* interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[],\n    int addflags)\n{\n    Tk_SavedOptions saved;\n    Tk_Image newImage = NULL;\n    int mask = 0;\n\n    if (objc <= 1 && !(addflags & ICON_CONF_FIRST_TIME)) {\n\tTcl_Obj* info = Tk_GetOptionInfo(interp, (char*)icon, icon->options,\n\t\tobjc? objv[0] : NULL, icon->tkwin);\n\tif (info) {\n\t    Tcl_SetObjResult(interp,info);\n\t    return TCL_OK;\n\t} else {\n\t    return TCL_ERROR; /* msg by Tk_GetOptionInfo */\n\t}\n    }\n\n    if (Tk_SetOptions(interp, icon,icon->options,objc,objv,\n\t    icon->tkwin,&saved,&mask) != TCL_OK) {\n\treturn TCL_ERROR; /* msg by Tk_SetOptions */\n    }\n    mask |= addflags;\n    /* now check option validity */\n    if (mask & ICON_CONF_IMAGE) {\n\tif (icon->imageObj) {\n\t    newImage = Tk_GetImage(interp, icon->tkwin, Tcl_GetString(icon->imageObj),\n\t\t    TrayIconImageChanged, icon);\n\t    if (!newImage) {\n\t\tTk_RestoreSavedOptions(&saved);\n\t\treturn TCL_ERROR; /* msg by Tk_GetImage */\n\t    }\n\t}\n\tif (icon->image) {\n\t    Tk_FreeImage(icon->image);\n\t    icon->image = NULL;\n\t}\n\tif (icon->imageVisualInstance) {\n\t    Tk_FreeImage(icon->imageVisualInstance);\n\t    icon->imageVisualInstance = NULL;\n\t}\n\ticon->image = newImage; /* may be null, as intended */\n\ticon->photo = NULL; /* invalidate photo reference */\n    }\n    Tk_FreeSavedOptions(&saved);\n    /* Now as we are reconfigured... */\n    TrayIconUpdate(icon,mask);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconDeleteProc --\n *\n *      Delete tray window and clean up.\n *\n * Results:\n *\tWindow destroyed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTrayIconDeleteProc(\n    void *cd )\n{\n    DockIcon *icon = (DockIcon *)cd;\n    Tk_DestroyWindow(icon->tkwin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TrayIconCreateCmd --\n *\n *      Create tray command and (unreal) window.\n *\n * Results:\n *\tIcon tray and hidden window created.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTrayIconCreateCmd(\n    void *cd,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tk_Window mainWindow = (Tk_Window)cd;\n    DockIcon *icon;\n\n    icon = (DockIcon*)Tcl_AttemptAlloc(sizeof(DockIcon));\n    if (!icon) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"running out of memory\", TCL_INDEX_NONE));\n\tgoto handleErrors;\n    }\n    memset(icon,0,sizeof(*icon));\n\n    if (objc < 2||(objc%2)) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"pathName ?option value ...?\");\n\tgoto handleErrors;\n    }\n\n    /* It's not a toplevel window by now. It really doesn't matter,\n     * because it's not really shown.\n     */\n    icon->tkwin = Tk_CreateWindowFromPath(interp, mainWindow,\n\t    Tcl_GetString(objv[1]),\"\");\n    if (icon->tkwin == NULL) {\n\tgoto handleErrors;\n    }\n\n    /* Subscribe to StructureNotify */\n    TKU_AddInput(Tk_Display(icon->tkwin),\n\t    RootWindowOfScreen(Tk_Screen(icon->tkwin)),StructureNotifyMask);\n    TKU_AddInput(Tk_Display(icon->tkwin),\n\t    RootWindow(Tk_Display(icon->tkwin),0),StructureNotifyMask);\n    /* Spec says \"screen 0\" not \"default\", but... */\n    TKU_AddInput(Tk_Display(icon->tkwin),\n\t    DefaultRootWindow(Tk_Display(icon->tkwin)),StructureNotifyMask);\n\n    /* Early tracking of DestroyNotify is essential */\n    Tk_CreateEventHandler(icon->tkwin,StructureNotifyMask,\n\t    UserIconEvent, icon);\n\n    /* Now try setting options */\n    icon->options = Tk_CreateOptionTable(interp,IconOptionSpec);\n    /* Class name is used for retrieving defaults, so... */\n    Tk_SetClass(icon->tkwin, Tk_GetUid(\"TrayIcon\"));\n    if (Tk_InitOptions(interp,(char*)icon,icon->options,icon->tkwin) != TCL_OK) {\n\tgoto handleErrors;\n    }\n\n    icon->a_NET_SYSTEM_TRAY_Sn = DockSelectionAtomFor(icon->tkwin);\n    icon->a_NET_SYSTEM_TRAY_OPCODE = Tk_InternAtom(icon->tkwin,\"_NET_SYSTEM_TRAY_OPCODE\");\n    icon->a_NET_SYSTEM_TRAY_MESSAGE_DATA = Tk_InternAtom(icon->tkwin,\"_NET_SYSTEM_TRAY_MESSAGE_DATA\");\n    icon->a_NET_SYSTEM_TRAY_ORIENTATION = Tk_InternAtom(icon->tkwin,\"_NET_SYSTEM_TRAY_ORIENTATION\");\n    icon->a_NET_SYSTEM_TRAY_VISUAL = Tk_InternAtom(icon->tkwin,\"_NET_SYSTEM_TRAY_VISUAL\");\n    icon->a_XEMBED_INFO = Tk_InternAtom(icon->tkwin,\"_XEMBED_INFO\");\n    icon->aMANAGER = Tk_InternAtom(icon->tkwin,\"MANAGER\");\n\n    icon->interp = interp;\n\n    icon->trayManager = XGetSelectionOwner(Tk_Display(icon->tkwin), icon->a_NET_SYSTEM_TRAY_Sn);\n    if (icon->trayManager) {\n\tXSelectInput(Tk_Display(icon->tkwin),icon->trayManager, StructureNotifyMask);\n    }\n\n    Tk_CreateGenericHandler(IconGenericHandler, icon);\n\n    if (objc>3) {\n\tif (TrayIconConfigureMethod(icon, interp, objc-2, objv+2,\n\t\tICON_CONF_XEMBED|ICON_CONF_IMAGE|ICON_CONF_FIRST_TIME) != TCL_OK) {\n\t    goto handleErrors;\n\t}\n    }\n\n    icon->widgetCmd = Tcl_CreateObjCommand2(interp, Tcl_GetString(objv[1]),\n\t    TrayIconObjectCmd, icon, TrayIconDeleteProc);\n\n    /* Sometimes a command just can't be created... */\n    if (!icon->widgetCmd) {\n\tgoto handleErrors;\n    }\n\n    Tcl_SetObjResult(interp,objv[1]);\n    return TCL_OK;\n\nhandleErrors:\n    /* Rolling back */\n    if (icon) {\n\tif (icon->options) {\n\t    Tk_DeleteOptionTable(icon->options);\n\t    icon->options = NULL;\n\t}\n\tif (icon->tkwin) {\n\t    /* Resources will be freed by DestroyNotify handler */\n\t    Tk_DestroyWindow(icon->tkwin);\n\t}\n\tTcl_Free(icon);\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tktray_Init --\n *\n *      Initialize the command.\n *\n * Results:\n *\tCommand initialized.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTktray_Init(\n    Tcl_Interp *interp)\n{\n    Tcl_CreateObjCommand2(interp, \"::tk::systray::_systray\",\n\t    TrayIconCreateCmd, Tk_MainWindow(interp), NULL);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 79\n * coding: utf-8\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixWm.c",
    "content": "/*\n * tkUnixWm.c --\n *\n *\tThis module takes care of the interactions between a Tk-based\n *\tapplication and the window manager. Among other things, it implements\n *\tthe \"wm\" command and passes geometry information to the window\n *\tmanager.\n *\n * Copyright © 1991-1994 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n/*\n * A data structure of the following type holds information for each window\n * manager protocol (such as WM_DELETE_WINDOW) for which a handler (i.e. a Tcl\n * command) has been defined for a particular top-level window.\n */\n\ntypedef struct ProtocolHandler {\n    Atom protocol;\t\t/* Identifies the protocol. */\n    struct ProtocolHandler *nextPtr;\n\t\t\t\t/* Next in list of protocol handlers for the\n\t\t\t\t * same top-level window, or NULL for end of\n\t\t\t\t * list. */\n    Tcl_Interp *interp;\t/* Interpreter in which to invoke command. */\n    char command[TKFLEXARRAY];\t/* Tcl command to invoke when a client message\n\t\t\t\t * for this protocol arrives. The actual size\n\t\t\t\t * of the structure varies to accommodate the\n\t\t\t\t * needs of the actual command. THIS MUST BE\n\t\t\t\t * THE LAST FIELD OF THE STRUCTURE. */\n} ProtocolHandler;\n\n#define HANDLER_SIZE(cmdLength) \\\n    (offsetof(ProtocolHandler, command) + 1 + cmdLength)\n\n/*\n * Data for [wm attributes] command:\n */\n\ntypedef struct {\n    double alpha;\t\t/* Transparency; 0.0=transparent, 1.0=opaque */\n    int topmost;\t\t/* Flag: true=>stay-on-top */\n    int zoomed;\t\t\t/* Flag: true=>maximized */\n    int fullscreen;\t\t/* Flag: true=>fullscreen */\n} WmAttributes;\n\ntypedef enum {\n    WMATT_ALPHA, WMATT_FULLSCREEN, WMATT_TOPMOST, WMATT_TYPE,\n    WMATT_ZOOMED, _WMATT_LAST_ATTRIBUTE\n} WmAttribute;\n\nstatic const char *const WmAttributeNames[] = {\n    \"-alpha\", \"-fullscreen\", \"-topmost\", \"-type\",\n    \"-zoomed\", NULL\n};\n\n/*\n * A data structure of the following type holds window-manager-related\n * information for each top-level window in an application.\n */\n\ntypedef struct TkWmInfo {\n    TkWindow *winPtr;\t\t/* Pointer to main Tk information for this\n\t\t\t\t * window. */\n    Window reparent;\t\t/* If the window has been reparented, this\n\t\t\t\t * gives the ID of the ancestor of the window\n\t\t\t\t * that is a child of the root window (may not\n\t\t\t\t * be window's immediate parent). If the\n\t\t\t\t * window isn't reparented, this has the value\n\t\t\t\t * None. */\n    char *title;\t\t/* Title to display in window caption. If\n\t\t\t\t * NULL, use name of widget. Malloced. */\n    char *iconName;\t\t/* Name to display in icon. Malloced. */\n    XWMHints hints;\t\t/* Various pieces of information for window\n\t\t\t\t * manager. */\n    char *leaderName;\t\t/* Path name of leader of window group\n\t\t\t\t * (corresponds to hints.window_group).\n\t\t\t\t * Malloc-ed. Note: this field doesn't get\n\t\t\t\t * updated if leader is destroyed. */\n    TkWindow *containerPtr;\t/* Container window for TRANSIENT_FOR property,\n\t\t\t\t * or NULL. */\n    Tk_Window icon;\t\t/* Window to use as icon for this window, or\n\t\t\t\t * NULL. */\n    Tk_Window iconFor;\t\t/* Window for which this window is icon, or\n\t\t\t\t * NULL if this isn't an icon for anyone. */\n    int withdrawn;\t\t/* Non-zero means window has been withdrawn. */\n\n    /*\n     * In order to support menubars transparently under X, each toplevel\n     * window is encased in an additional window, called the wrapper, that\n     * holds the toplevel and the menubar, if any. The information below is\n     * used to keep track of the wrapper and the menubar.\n     */\n\n    TkWindow *wrapperPtr;\t/* Pointer to information about the wrapper.\n\t\t\t\t * This is the \"real\" toplevel window as seen\n\t\t\t\t * by the window manager. Although this is an\n\t\t\t\t * official Tk window, it doesn't appear in\n\t\t\t\t * the application's window hierarchy. NULL\n\t\t\t\t * means that the wrapper hasn't been created\n\t\t\t\t * yet. */\n    Tk_Window menubar;\t\t/* Pointer to information about the menubar,\n\t\t\t\t * or NULL if there is no menubar for this\n\t\t\t\t * toplevel. */\n    int menuHeight;\t\t/* Amount of vertical space needed for\n\t\t\t\t * menubar, measured in pixels. If menubar is\n\t\t\t\t * non-NULL, this is >= 1 (X servers don't\n\t\t\t\t * like dimensions of 0). */\n\n    /*\n     * Information used to construct an XSizeHints structure for the window\n     * manager:\n     */\n\n    int sizeHintsFlags;\t\t/* Flags word for XSizeHints structure. If the\n\t\t\t\t * PBaseSize flag is set then the window is\n\t\t\t\t * gridded; otherwise it isn't gridded. */\n    int minWidth, minHeight;\t/* Minimum dimensions of window, in pixels or\n\t\t\t\t * grid units. */\n    int maxWidth, maxHeight;\t/* Maximum dimensions of window, in pixels or\n\t\t\t\t * grid units. 0 to default.*/\n    Tk_Window gridWin;\t\t/* Identifies the window that controls\n\t\t\t\t * gridding for this top-level, or NULL if the\n\t\t\t\t * top-level isn't currently gridded. */\n    int widthInc, heightInc;\t/* Increments for size changes (# pixels per\n\t\t\t\t * step). */\n    struct {\n\tint x;\t\t\t/* numerator */\n\tint y;\t\t\t/* denominator */\n    } minAspect, maxAspect;\t/* Min/max aspect ratios for window. */\n    int reqGridWidth, reqGridHeight;\n\t\t\t\t/* The dimensions of the window (in grid\n\t\t\t\t * units) requested through the geometry\n\t\t\t\t * manager. */\n    int gravity;\t\t/* Desired window gravity. */\n\n    /*\n     * Information used to manage the size and location of a window.\n     */\n\n    int width, height;\t\t/* Desired dimensions of window, specified in\n\t\t\t\t * pixels or grid units. These values are set\n\t\t\t\t * by the \"wm geometry\" command and by\n\t\t\t\t * ConfigureNotify events (for when wm resizes\n\t\t\t\t * window). -1 means user hasn't requested\n\t\t\t\t * dimensions. */\n    int x, y;\t\t\t/* Desired X and Y coordinates for window.\n\t\t\t\t * These values are set by \"wm geometry\", plus\n\t\t\t\t * by ConfigureNotify events (when wm moves\n\t\t\t\t * window). These numbers are different than\n\t\t\t\t * the numbers stored in winPtr->changes\n\t\t\t\t * because (a) they could be measured from the\n\t\t\t\t * right or bottom edge of the screen (see\n\t\t\t\t * WM_NEGATIVE_X and WM_NEGATIVE_Y flags) and\n\t\t\t\t * (b) if the window has been reparented then\n\t\t\t\t * they refer to the parent rather than the\n\t\t\t\t * window itself. */\n    int parentWidth, parentHeight;\n\t\t\t\t/* Width and height of reparent, in pixels\n\t\t\t\t * *including border*. If window hasn't been\n\t\t\t\t * reparented then these will be the outer\n\t\t\t\t * dimensions of the window, including\n\t\t\t\t * border. */\n    int xInParent, yInParent;\t/* Offset of wrapperPtr within reparent,\n\t\t\t\t * measured in pixels from upper-left outer\n\t\t\t\t * corner of reparent's border to upper-left\n\t\t\t\t * outer corner of wrapperPtr's border. If not\n\t\t\t\t * reparented then these are zero. */\n    int configWidth, configHeight;\n\t\t\t\t/* Dimensions passed to last request that we\n\t\t\t\t * issued to change geometry of the wrapper.\n\t\t\t\t * Used to eliminate redundant resize\n\t\t\t\t * operations. */\n\n    /*\n     * Information about the virtual root window for this top-level, if there\n     * is one.\n     */\n\n    Window vRoot;\t\t/* Virtual root window for this top-level, or\n\t\t\t\t * None if there is no virtual root window\n\t\t\t\t * (i.e. just use the screen's root). */\n    int vRootX, vRootY;\t\t/* Position of the virtual root inside the\n\t\t\t\t * root window. If the WM_VROOT_OFFSET_STALE\n\t\t\t\t * flag is set then this information may be\n\t\t\t\t * incorrect and needs to be refreshed from\n\t\t\t\t * the X server. If vRoot is None then these\n\t\t\t\t * values are both 0. */\n    int vRootWidth, vRootHeight;/* Dimensions of the virtual root window. If\n\t\t\t\t * vRoot is None, gives the dimensions of the\n\t\t\t\t * containing screen. This information is\n\t\t\t\t * never stale, even though vRootX and vRootY\n\t\t\t\t * can be. */\n\n    /*\n     * Miscellaneous information.\n     */\n\n    WmAttributes attributes;\t/* Current state of [wm attributes] */\n    WmAttributes reqState;\t/* Requested state of [wm attributes] */\n    ProtocolHandler *protPtr;\t/* First in list of protocol handlers for this\n\t\t\t\t * window (NULL means none). */\n    Tcl_Size cmdArgc;\t\t/* Number of elements in cmdArgv below. */\n    const char **cmdArgv;\t/* Array of strings to store in the WM_COMMAND\n\t\t\t\t * property. NULL means nothing available. */\n    char *clientMachine;\t/* String to store in WM_CLIENT_MACHINE\n\t\t\t\t * property, or NULL. */\n    int flags;\t\t\t/* Miscellaneous flags, defined below. */\n    int numTransients;\t\t/* number of transients on this window */\n    int iconDataSize;\t\t/* size of iconphoto image data */\n    unsigned char *iconDataPtr;\t/* iconphoto image data, if set */\n    struct TkWmInfo *nextPtr;\t/* Next in list of all top-level windows. */\n} WmInfo;\n\n/*\n * Flag values for WmInfo structures:\n *\n * WM_NEVER_MAPPED -\t\tnon-zero means window has never been mapped;\n *\t\t\t\tneed to update all info when window is first\n *\t\t\t\tmapped.\n * WM_UPDATE_PENDING -\t\tnon-zero means a call to UpdateGeometryInfo\n *\t\t\t\thas already been scheduled for this window;\n *\t\t\t\tno need to schedule another one.\n * WM_NEGATIVE_X -\t\tnon-zero means x-coordinate is measured in\n *\t\t\t\tpixels from right edge of screen, rather than\n *\t\t\t\tfrom left edge.\n * WM_NEGATIVE_Y -\t\tnon-zero means y-coordinate is measured in\n *\t\t\t\tpixels up from bottom of screen, rather than\n *\t\t\t\tdown from top.\n * WM_UPDATE_SIZE_HINTS -\tnon-zero means that new size hints need to be\n *\t\t\t\tpropagated to window manager.\n * WM_SYNC_PENDING -\t\tset to non-zero while waiting for the window\n *\t\t\t\tmanager to respond to some state change.\n * WM_VROOT_OFFSET_STALE -\tnon-zero means that (x,y) offset information\n *\t\t\t\tabout the virtual root window is stale and\n *\t\t\t\tneeds to be fetched fresh from the X server.\n * WM_ABOUT_TO_MAP -\t\tnon-zero means that the window is about to be\n *\t\t\t\tmapped by TkWmMapWindow. This is used by\n *\t\t\t\tUpdateGeometryInfo to modify its behavior.\n * WM_MOVE_PENDING -\t\tnon-zero means the application has requested a\n *\t\t\t\tnew position for the window, but it hasn't\n *\t\t\t\tbeen reflected through the window manager yet.\n * WM_COLORMAPS_EXPLICIT -\tnon-zero means the colormap windows were set\n *\t\t\t\texplicitly via \"wm colormapwindows\".\n * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when \"wm colormapwindows\"\n *\t\t\t\twas called the top-level itself wasn't\n *\t\t\t\tspecified, so we added it implicitly at the\n *\t\t\t\tend of the list.\n * WM_WIDTH_NOT_RESIZABLE -\tnon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the width of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n * WM_HEIGHT_NOT_RESIZABLE -\tnon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the height of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n * WM_WITHDRAWN -\t\tnon-zero means that this window has explicitly\n *\t\t\t\tbeen withdrawn. If it's a transient, it should\n *\t\t\t\tnot mirror state changes in the container.\n */\n\n#define WM_NEVER_MAPPED\t\t\t1\n#define WM_UPDATE_PENDING\t\t2\n#define WM_NEGATIVE_X\t\t\t4\n#define WM_NEGATIVE_Y\t\t\t8\n#define WM_UPDATE_SIZE_HINTS\t\t0x10\n#define WM_SYNC_PENDING\t\t\t0x20\n#define WM_VROOT_OFFSET_STALE\t\t0x40\n#define WM_ABOUT_TO_MAP\t\t\t0x100\n#define WM_MOVE_PENDING\t\t\t0x200\n#define WM_COLORMAPS_EXPLICIT\t\t0x400\n#define WM_ADDED_TOPLEVEL_COLORMAP\t0x800\n#define WM_WIDTH_NOT_RESIZABLE\t\t0x1000\n#define WM_HEIGHT_NOT_RESIZABLE\t\t0x2000\n#define WM_WITHDRAWN\t\t\t0x4000\n\n/*\n * Wrapper for XGetWindowProperty and XChangeProperty to make them a *bit*\n * less verbose.\n */\n\n#define GetWindowProperty(wrapperPtr, atom, length, type, typePtr, formatPtr, numItemsPtr, bytesAfterPtr, itemsPtr) \\\n    (XGetWindowProperty((wrapperPtr)->display, (wrapperPtr)->window,\t\\\n\t    (atom), 0, (long) (length), False, (type),\t\t\t\\\n\t    (typePtr), (formatPtr), (numItemsPtr), (bytesAfterPtr),\t\\\n\t    (unsigned char **) (itemsPtr)) == Success)\n#define SetWindowProperty(wrapperPtr, atomName, type, width, data, length) \\\n    XChangeProperty((wrapperPtr)->display, (wrapperPtr)->window,\t\\\n\t    Tk_InternAtom((Tk_Window) wrapperPtr, (atomName)),\t\t\\\n\t    (type), (width), PropModeReplace, (unsigned char *) (data), \\\n\t    (int) (length))\n\n/*\n * This module keeps a list of all top-level windows, primarily to simplify\n * the job of Tk_CoordsToWindow. The list is called firstWmPtr and is stored\n * in the TkDisplay structure.\n */\n\n/*\n * The following structures are the official type records for geometry\n * management of top-level and menubar windows.\n */\n\nstatic void\t\tTopLevelReqProc(void *dummy, Tk_Window tkwin);\nstatic void\t\tRemapWindows(TkWindow *winPtr, TkWindow *parentPtr);\nstatic void\t\tMenubarReqProc(void *clientData,\n\t\t\t    Tk_Window tkwin);\n\nstatic const Tk_GeomMgr wmMgrType = {\n    \"wm\",\t\t\t/* name */\n    TopLevelReqProc,\t\t/* requestProc */\n    NULL,\t\t\t/* lostContentProc */\n};\nstatic const Tk_GeomMgr menubarMgrType = {\n    \"menubar\",\t\t\t/* name */\n    MenubarReqProc,\t\t/* requestProc */\n    NULL,\t\t\t/* lostContentProc */\n};\n\n/*\n * Structures of the following type are used for communication between\n * WaitForEvent, WaitRestrictProc, and WaitTimeoutProc.\n */\n\ntypedef struct WaitRestrictInfo {\n    Display *display;\t\t/* Window belongs to this display. */\n    WmInfo *wmInfoPtr;\n    int type;\t\t\t/* We only care about this type of event. */\n    XEvent *eventPtr;\t\t/* Where to store the event when it's found. */\n    int foundEvent;\t\t/* Non-zero means that an event of the desired\n\t\t\t\t * type has been found. */\n} WaitRestrictInfo;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic bool\t\tComputeReparentGeometry(WmInfo *wmPtr);\nstatic void\t\tConfigureEvent(WmInfo *wmPtr,\n\t\t\t    XConfigureEvent *eventPtr);\nstatic void\t\tCreateWrapper(WmInfo *wmPtr);\nstatic void\t\tGetMaxSize(WmInfo *wmPtr, int *maxWidthPtr,\n\t\t\t    int *maxHeightPtr);\nstatic void\t\tMenubarDestroyProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tParseGeometry(Tcl_Interp *interp, const char *string,\n\t\t\t    TkWindow *winPtr);\nstatic void\t\tReparentEvent(WmInfo *wmPtr, XReparentEvent *eventPtr);\nstatic void\t\tPropertyEvent(WmInfo *wmPtr, XPropertyEvent *eventPtr);\nstatic void\t\tTkWmStackorderToplevelWrapperMap(TkWindow *winPtr,\n\t\t\t    Display *display, Tcl_HashTable *reparentTable);\nstatic void\t\tTopLevelReqProc(void *dummy, Tk_Window tkwin);\nstatic void\t\tRemapWindows(TkWindow *winPtr, TkWindow *parentPtr);\nstatic void\t\tUpdateCommand(TkWindow *winPtr);\nstatic void\t\tUpdateGeometryInfo(void *clientData);\nstatic void\t\tUpdateHints(TkWindow *winPtr);\nstatic void\t\tUpdateSizeHints(TkWindow *winPtr,\n\t\t\t    int newWidth, int newHeight);\nstatic void\t\tUpdateTitle(TkWindow *winPtr);\nstatic void\t\tUpdatePhotoIcon(TkWindow *winPtr);\nstatic void\t\tUpdateVRootGeometry(WmInfo *wmPtr);\nstatic void\t\tUpdateWmProtocols(WmInfo *wmPtr);\nstatic int\t\tSetNetWmType(TkWindow *winPtr, Tcl_Obj *typePtr);\nstatic Tcl_Obj *\tGetNetWmType(TkWindow *winPtr);\nstatic void\t\tSetNetWmState(TkWindow*, const char *atomName, int on);\nstatic void\t\tCheckNetWmState(WmInfo *, Atom *atoms, int numAtoms);\nstatic void\t\tUpdateNetWmState(WmInfo *);\nstatic void\t\tWaitForConfigureNotify(TkWindow *winPtr,\n\t\t\t    unsigned long serial);\nstatic int\t\tWaitForEvent(Display *display,\n\t\t\t    WmInfo *wmInfoPtr, int type, XEvent *eventPtr);\nstatic void\t\tWaitForMapNotify(TkWindow *winPtr, int mapped);\nstatic Tk_RestrictProc WaitRestrictProc;\nstatic void\t\tWrapperEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tWmWaitMapProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic int\t\tWmAspectCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmClientCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmColormapwindowsCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmCommandCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmForgetCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFrameCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGridCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGroupCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbadgeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmManageCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmOverrideredirectCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmResizableCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStateCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTitleCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTransientCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tWmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmCleanup --\n *\n *\tThis function is invoked to cleanup remaining wm resources associated\n *\twith a display.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll WmInfo structure resources are freed and invalidated.\n *\n *--------------------------------------------------------------\n */\n\nvoid TkWmCleanup(\n    TkDisplay *dispPtr)\n{\n    WmInfo *wmPtr, *nextPtr;\n\n    for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = nextPtr) {\n\t/*\n\t * We can't assume we have access to winPtr's anymore, so some cleanup\n\t * requiring winPtr data is avoided.\n\t */\n\n\tnextPtr = wmPtr->nextPtr;\n\tif (wmPtr->title != NULL) {\n\t    Tcl_Free(wmPtr->title);\n\t}\n\tif (wmPtr->iconName != NULL) {\n\t    Tcl_Free(wmPtr->iconName);\n\t}\n\tif (wmPtr->iconDataPtr != NULL) {\n\t    Tcl_Free(wmPtr->iconDataPtr);\n\t}\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\tif (wmPtr->menubar != NULL) {\n\t    Tk_DestroyWindow(wmPtr->menubar);\n\t}\n\tif (wmPtr->wrapperPtr != NULL) {\n\t    Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr);\n\t}\n\twhile (wmPtr->protPtr != NULL) {\n\t    ProtocolHandler *protPtr = wmPtr->protPtr;\n\n\t    wmPtr->protPtr = protPtr->nextPtr;\n\t    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n\t}\n\tif (wmPtr->cmdArgv != NULL) {\n\t    Tcl_Free(wmPtr->cmdArgv);\n\t}\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_Free(wmPtr->clientMachine);\n\t}\n\tTcl_Free(wmPtr);\n    }\n    if (dispPtr->iconDataPtr != NULL) {\n\tTcl_Free(dispPtr->iconDataPtr);\n\tdispPtr->iconDataPtr = NULL;\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmNewWindow --\n *\n *\tThis function is invoked whenever a new top-level window is created.\n *\tIts job is to initialize the WmInfo structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA WmInfo structure gets allocated and initialized.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmNewWindow(\n    TkWindow *winPtr)\t\t/* Newly-created top-level window. */\n{\n    WmInfo *wmPtr;\n    TkDisplay *dispPtr = winPtr->dispPtr;\n\n    wmPtr = (WmInfo *)Tcl_Alloc(sizeof(WmInfo));\n    memset(wmPtr, 0, sizeof(WmInfo));\n    wmPtr->winPtr = winPtr;\n    wmPtr->reparent = None;\n    wmPtr->containerPtr = NULL;\n    wmPtr->numTransients = 0;\n    wmPtr->hints.flags = InputHint | StateHint;\n    wmPtr->hints.input = True;\n    wmPtr->hints.initial_state = NormalState;\n    wmPtr->hints.icon_pixmap = None;\n    wmPtr->hints.icon_window = None;\n    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;\n    wmPtr->hints.icon_mask = None;\n    wmPtr->hints.window_group = None;\n\n    /*\n     * Initialize attributes.\n     */\n\n    wmPtr->attributes.alpha = 1.0;\n    wmPtr->attributes.topmost = 0;\n    wmPtr->attributes.zoomed = 0;\n    wmPtr->attributes.fullscreen = 0;\n    wmPtr->reqState = wmPtr->attributes;\n\n    /*\n     * Default the maximum dimensions to the size of the display, minus a\n     * guess about how space is needed for window manager decorations.\n     */\n\n    wmPtr->gridWin = NULL;\n    wmPtr->minWidth = wmPtr->minHeight = 1;\n    wmPtr->maxWidth = wmPtr->maxHeight = 0;\n    wmPtr->widthInc = wmPtr->heightInc = 1;\n    wmPtr->minAspect.x = wmPtr->minAspect.y = 1;\n    wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;\n    wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;\n    wmPtr->gravity = NorthWestGravity;\n    wmPtr->width = -1;\n    wmPtr->height = -1;\n    wmPtr->x = winPtr->changes.x;\n    wmPtr->y = winPtr->changes.y;\n    wmPtr->parentWidth = winPtr->changes.width\n\t    + 2*winPtr->changes.border_width;\n    wmPtr->parentHeight = winPtr->changes.height\n\t    + 2*winPtr->changes.border_width;\n    wmPtr->configWidth = -1;\n    wmPtr->configHeight = -1;\n    wmPtr->vRoot = None;\n    wmPtr->flags = WM_NEVER_MAPPED;\n    wmPtr->nextPtr = (WmInfo *) dispPtr->firstWmPtr;\n    dispPtr->firstWmPtr = wmPtr;\n    winPtr->wmInfoPtr = wmPtr;\n\n    UpdateVRootGeometry(wmPtr);\n\n    /*\n     * Arrange for geometry requests to be reflected from the window to the\n     * window manager.\n     */\n\n    Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, NULL);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmMapWindow --\n *\n *\tThis function is invoked to map a top-level window. This module gets a\n *\tchance to update all window-manager-related information in properties\n *\tbefore the window manager sees the map event and checks the\n *\tproperties. It also gets to decide whether or not to even map the\n *\twindow after all.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties of winPtr may get updated to provide up-to-date information\n *\tto the window manager. The window may also get mapped, but it may not\n *\tbe if this function decides that isn't appropriate (e.g. because the\n *\twindow is withdrawn).\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmMapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * mapped. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    XTextProperty textProp;\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\tTcl_DString ds;\n\n\twmPtr->flags &= ~WM_NEVER_MAPPED;\n\n\t/*\n\t * This is the first time this window has ever been mapped. First\n\t * create the wrapper window that provides space for a menubar.\n\t */\n\n\tif (wmPtr->wrapperPtr == NULL) {\n\t    CreateWrapper(wmPtr);\n\t}\n\n\t/*\n\t * Store all the window-manager-related information for the window.\n\t */\n\n\tTkWmSetClass(winPtr);\n\tUpdateTitle(winPtr);\n\tUpdatePhotoIcon(winPtr);\n\n\tif (wmPtr->containerPtr != NULL) {\n\t    /*\n\t     * Don't map a transient if the container is not mapped.\n\t     */\n\n\t    if (!Tk_IsMapped(wmPtr->containerPtr)) {\n\t\twmPtr->withdrawn = 1;\n\t\twmPtr->hints.initial_state = WithdrawnState;\n\t    }\n\n\t    /*\n\t     * Make sure that we actually set the transient-for property, even\n\t     * if we are withdrawn. [Bug 1163496]\n\t     */\n\n\t    XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t    wmPtr->containerPtr->wmInfoPtr->wrapperPtr->window);\n\t}\n\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n\tUpdateHints(winPtr);\n\tUpdateWmProtocols(wmPtr);\n\tif (wmPtr->cmdArgv != NULL) {\n\t    UpdateCommand(winPtr);\n\t}\n\tif (wmPtr->clientMachine != NULL) {\n\t    (void)Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, TCL_INDEX_NONE, &ds);\n\t    if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,\n\t\t    &textProp) != 0) {\n\t\tunsigned long pid = (unsigned long) getpid();\n\n\t\tXSetWMClientMachine(winPtr->display,\n\t\t\twmPtr->wrapperPtr->window, &textProp);\n\t\tXFree(textProp.value);\n\n\t\t/*\n\t\t * Inform the server (and more particularly any session\n\t\t * manager) what our process ID is. We only do this when the\n\t\t * CLIENT_MACHINE property is set since the spec for\n\t\t * _NET_WM_PID requires that to be set too.\n\t\t */\n\n\t\tSetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_PID\",\n\t\t\tXA_CARDINAL, 32, &pid, 1);\n\t    }\n\t    Tcl_DStringFree(&ds);\n\t}\n    }\n    if (wmPtr->hints.initial_state == WithdrawnState) {\n\treturn;\n    }\n    if (wmPtr->iconFor != NULL) {\n\t/*\n\t * This window is an icon for somebody else. Make sure that the\n\t * geometry is up-to-date, then return without mapping the window.\n\t */\n\n\tif (wmPtr->flags & WM_UPDATE_PENDING) {\n\t    Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n\t}\n\tUpdateGeometryInfo(winPtr);\n\treturn;\n    }\n    wmPtr->flags |= WM_ABOUT_TO_MAP;\n    if (wmPtr->flags & WM_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n    }\n    UpdateGeometryInfo(winPtr);\n    wmPtr->flags &= ~WM_ABOUT_TO_MAP;\n\n    /*\n     * Update _NET_WM_STATE hints:\n     */\n    UpdateNetWmState(wmPtr);\n\n    /*\n     * Map the window, then wait to be sure that the window manager has\n     * processed the map operation.\n     */\n\n    XMapWindow(winPtr->display, wmPtr->wrapperPtr->window);\n    if (wmPtr->hints.initial_state == NormalState) {\n\tWaitForMapNotify(winPtr, 1);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmUnmapWindow --\n *\n *\tThis function is invoked to unmap a top-level window. The only thing\n *\tit does special is to wait for the window actually to be unmapped.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUnmaps the window.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmUnmapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * mapped. */\n{\n    /*\n     * It seems to be important to wait after unmapping a top-level window\n     * until the window really gets unmapped. I don't completely understand\n     * all the interactions with the window manager, but if we go on without\n     * waiting, and if the window is then mapped again quickly, events seem to\n     * get lost so that we think the window isn't mapped when in fact it is\n     * mapped. I suspect that this has something to do with the window manager\n     * filtering Map events (and possily not filtering Unmap events?).\n     */\n\n    XUnmapWindow(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window);\n    WaitForMapNotify(winPtr, 0);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmDeadWindow --\n *\n *\tThis function is invoked when a top-level window is about to be\n *\tdeleted. It cleans up the wm-related data structures for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe WmInfo structure for winPtr gets freed up.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmDeadWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's being deleted. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    WmInfo *wmPtr2;\n\n    if (wmPtr == NULL) {\n\treturn;\n    }\n    if ((WmInfo *) winPtr->dispPtr->firstWmPtr == wmPtr) {\n\twinPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;\n    } else {\n\tWmInfo *prevPtr;\n\n\tfor (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;\n\t\tprevPtr = prevPtr->nextPtr) {\n\t    /* ASSERT: prevPtr != NULL [Bug 1789819] */\n\t    if (prevPtr->nextPtr == wmPtr) {\n\t\tprevPtr->nextPtr = wmPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n    if (wmPtr->title != NULL) {\n\tTcl_Free(wmPtr->title);\n    }\n    if (wmPtr->iconName != NULL) {\n\tTcl_Free(wmPtr->iconName);\n    }\n    if (wmPtr->iconDataPtr != NULL) {\n\tTcl_Free(wmPtr->iconDataPtr);\n    }\n    if (wmPtr->hints.flags & IconPixmapHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n    }\n    if (wmPtr->hints.flags & IconMaskHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n    }\n    if (wmPtr->leaderName != NULL) {\n\tTcl_Free(wmPtr->leaderName);\n    }\n    if (wmPtr->icon != NULL) {\n\twmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\twmPtr2->iconFor = NULL;\n\twmPtr2->withdrawn = 1;\n    }\n    if (wmPtr->iconFor != NULL) {\n\twmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;\n\twmPtr2->icon = NULL;\n\twmPtr2->hints.flags &= ~IconWindowHint;\n\tUpdateHints((TkWindow *) wmPtr->iconFor);\n    }\n    if (wmPtr->menubar != NULL) {\n\tTk_DestroyWindow(wmPtr->menubar);\n    }\n    if (wmPtr->wrapperPtr != NULL) {\n\t/*\n\t * The rest of Tk doesn't know that we reparent the toplevel inside\n\t * the wrapper, so reparent it back out again before deleting the\n\t * wrapper; otherwise the toplevel will get deleted twice (once\n\t * implicitly by the deletion of the wrapper).\n\t */\n\n\tXUnmapWindow(winPtr->display, winPtr->window);\n\tXReparentWindow(winPtr->display, winPtr->window,\n\t\tXRootWindow(winPtr->display, winPtr->screenNum), 0, 0);\n\tTk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr);\n    }\n    while (wmPtr->protPtr != NULL) {\n\tProtocolHandler *protPtr = wmPtr->protPtr;\n\n\twmPtr->protPtr = protPtr->nextPtr;\n\tTcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n    }\n    if (wmPtr->cmdArgv != NULL) {\n\tTcl_Free(wmPtr->cmdArgv);\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    if (wmPtr->flags & WM_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n    }\n\n    /*\n     * Reset all transient windows whose container is the dead window.\n     */\n\n    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;\n\t    wmPtr2 = wmPtr2->nextPtr) {\n\tif (wmPtr2->containerPtr == winPtr) {\n\t    wmPtr->numTransients--;\n\t    Tk_DeleteEventHandler((Tk_Window) wmPtr2->containerPtr,\n\t\t    StructureNotifyMask, WmWaitMapProc, wmPtr2->winPtr);\n\t    wmPtr2->containerPtr = NULL;\n\t    if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t\tXDeleteProperty(winPtr->display, wmPtr2->wrapperPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr, \"WM_TRANSIENT_FOR\"));\n\n\t\t/*\n\t\t * FIXME: Need a call like Win32's UpdateWrapper() so we can\n\t\t * recreate the wrapper and get rid of the transient window\n\t\t * decorations.\n\t\t */\n\t    }\n\t}\n    }\n    /* ASSERT: numTransients == 0 [Bug 1789819] */\n\n    if (wmPtr->containerPtr != NULL) {\n\twmPtr2 = wmPtr->containerPtr->wmInfoPtr;\n\n\t/*\n\t * If we had a container, tell them that we aren't tied to them anymore\n\t */\n\n\tif (wmPtr2 != NULL) {\n\t    wmPtr2->numTransients--;\n\t}\n\tTk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,\n\t\tStructureNotifyMask, WmWaitMapProc, winPtr);\n\twmPtr->containerPtr = NULL;\n    }\n    Tcl_Free(wmPtr);\n    winPtr->wmInfoPtr = NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmSetClass --\n *\n *\tThis function is invoked whenever a top-level window's class is\n *\tchanged. If the window has been mapped then this function updates the\n *\twindow manager property for the class. If the window hasn't been\n *\tmapped, the update is deferred until just before the first mapping.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA window property may get updated.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmSetClass(\n    TkWindow *winPtr)\t\t/* Newly-created top-level window. */\n{\n    if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {\n\treturn;\n    }\n\n    if (winPtr->classUid != NULL) {\n\tXClassHint *classPtr;\n\tTcl_DString name, ds;\n\n\t(void)Tcl_UtfToExternalDString(NULL, winPtr->nameUid, TCL_INDEX_NONE, &name);\n\t(void)Tcl_UtfToExternalDString(NULL, winPtr->classUid, TCL_INDEX_NONE, &ds);\n\tclassPtr = XAllocClassHint();\n\tclassPtr->res_name = Tcl_DStringValue(&name);\n\tclassPtr->res_class = Tcl_DStringValue(&ds);\n\tXSetClassHint(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window,\n\t\tclassPtr);\n\tXFree(classPtr);\n\tTcl_DStringFree(&name);\n\tTcl_DStringFree(&ds);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_WmObjCmd --\n *\n *\tThis function is invoked to process the \"wm\" Tcl command.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_WmObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    static const char *const optionStrings[] = {\n\t\"aspect\", \"attributes\", \"client\", \"colormapwindows\",\n\t\"command\", \"deiconify\", \"focusmodel\", \"forget\",\n\t\"frame\", \"geometry\", \"grid\", \"group\", \"iconbadge\", \"iconbitmap\",\n\t\"iconify\", \"iconmask\", \"iconname\", \"iconphoto\",\n\t\"iconposition\", \"iconwindow\", \"manage\", \"maxsize\",\n\t\"minsize\", \"overrideredirect\", \"positionfrom\",\n\t\"protocol\", \"resizable\", \"sizefrom\", \"stackorder\",\n\t\"state\", \"title\", \"transient\", \"withdraw\", NULL };\n    enum options {\n\tWMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,\n\tWMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET,\n\tWMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP,\n\tWMOPT_ICONBADGE, WMOPT_ICONBITMAP,\n\tWMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO,\n\tWMOPT_ICONPOSITION, WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE,\n\tWMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM,\n\tWMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER,\n\tWMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW };\n    int index;\n    const char *argv1;\n    TkWindow *winPtr;\n    Tk_Window targetWin;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objc < 2) {\n    wrongNumArgs:\n\tTcl_WrongNumArgs(interp, 1, objv, \"option window ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    argv1 = Tcl_GetString(objv[1]);\n    if ((argv1[0] == 't') && (strncmp(argv1, \"tracing\", objv[1]->length) == 0)\n\t    && (objv[1]->length >= 3)) {\n\tint wmTracing;\n\n\tif ((objc != 2) && (objc != 3)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?boolean?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\t    (dispPtr->flags & TK_DISPLAY_WM_TRACING) != 0));\n\t    return TCL_OK;\n\t}\n\tif (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (wmTracing) {\n\t    dispPtr->flags |= TK_DISPLAY_WM_TRACING;\n\t} else {\n\t    dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;\n\t}\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,\n\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc < 3) {\n\tgoto wrongNumArgs;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], &targetWin) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    winPtr = (TkWindow *) targetWin;\n    if (!Tk_IsTopLevel(winPtr) &&\n\t    (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" isn't a top-level window\", winPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TOPLEVEL\", winPtr->pathName,\n\t\tNULL);\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case WMOPT_ASPECT:\n\treturn WmAspectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ATTRIBUTES:\n\treturn WmAttributesCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_CLIENT:\n\treturn WmClientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COLORMAPWINDOWS:\n\treturn WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COMMAND:\n\treturn WmCommandCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_DEICONIFY:\n\treturn WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FOCUSMODEL:\n\treturn WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FORGET:\n\treturn WmForgetCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FRAME:\n\treturn WmFrameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GEOMETRY:\n\treturn WmGeometryCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GRID:\n\treturn WmGridCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GROUP:\n\treturn WmGroupCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBADGE:\n\treturn WmIconbadgeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBITMAP:\n\treturn WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONIFY:\n\treturn WmIconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONMASK:\n\treturn WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONNAME:\n\treturn WmIconnameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPHOTO:\n\treturn WmIconphotoCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPOSITION:\n\treturn WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONWINDOW:\n\treturn WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MANAGE:\n\treturn WmManageCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MAXSIZE:\n\treturn WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MINSIZE:\n\treturn WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_OVERRIDEREDIRECT:\n\treturn WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_POSITIONFROM:\n\treturn WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_PROTOCOL:\n\treturn WmProtocolCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_RESIZABLE:\n\treturn WmResizableCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_SIZEFROM:\n\treturn WmSizefromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STACKORDER:\n\treturn WmStackorderCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STATE:\n\treturn WmStateCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TITLE:\n\treturn WmTitleCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TRANSIENT:\n\treturn WmTransientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_WITHDRAW:\n\treturn WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);\n    }\n\n    /* This should not happen */\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAspectCmd --\n *\n *\tThis function is invoked to process the \"wm aspect\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAspectCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int numer1, denom1, numer2, denom2;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?minNumer minDenom maxNumer maxDenom?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PAspect) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~PAspect;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||\n\t\t(denom2 <= 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"aspect number can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"ASPECT\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr->minAspect.x = numer1;\n\twmPtr->minAspect.y = denom1;\n\twmPtr->maxAspect.x = numer2;\n\twmPtr->maxAspect.y = denom2;\n\twmPtr->sizeHintsFlags |= PAspect;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmSetAttribute --\n *\n *\tHelper routine for WmAttributesCmd. Sets the value of the specified\n *\tattribute.\n *\n * Returns:\n *\n *\tTCL_OK if successful, TCL_ERROR otherwise. In case of an error, leaves\n *\ta message in the interpreter's result.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmSetAttribute(\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter */\n    WmAttribute attribute,\t/* Code of attribute to set */\n    Tcl_Obj *value)\t\t/* New value */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    switch (attribute) {\n    case WMATT_ALPHA: {\n\tunsigned long opacity;\t/* 0=transparent, 0xFFFFFFFF=opaque */\n\n\tif (TCL_OK != Tcl_GetDoubleFromObj(interp, value,\n\t\t&wmPtr->reqState.alpha)) {\n\t    return TCL_ERROR;\n\t}\n\tif (wmPtr->reqState.alpha < 0.0) {\n\t    wmPtr->reqState.alpha = 0.0;\n\t}\n\tif (wmPtr->reqState.alpha > 1.0) {\n\t    wmPtr->reqState.alpha = 1.0;\n\t}\n\n\tif (!wmPtr->wrapperPtr) {\n\t    break;\n\t}\n\n\topacity = 0xFFFFFFFFul * wmPtr->reqState.alpha;\n\tSetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_WINDOW_OPACITY\",\n\t\tXA_CARDINAL, 32, &opacity, 1L);\n\twmPtr->attributes.alpha = wmPtr->reqState.alpha;\n\n\tbreak;\n    }\n    case WMATT_TOPMOST:\n\tif (Tcl_GetBooleanFromObj(interp, value,\n\t\t&wmPtr->reqState.topmost) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tSetNetWmState(winPtr, \"_NET_WM_STATE_ABOVE\", wmPtr->reqState.topmost);\n\tbreak;\n    case WMATT_TYPE:\n\tif (TCL_OK != SetNetWmType(winPtr, value))\n\t    return TCL_ERROR;\n\tbreak;\n    case WMATT_ZOOMED:\n\tif (Tcl_GetBooleanFromObj(interp, value,\n\t\t&wmPtr->reqState.zoomed) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tSetNetWmState(winPtr, \"_NET_WM_STATE_MAXIMIZED_VERT\",\n\t\twmPtr->reqState.zoomed);\n\tSetNetWmState(winPtr, \"_NET_WM_STATE_MAXIMIZED_HORZ\",\n\t\twmPtr->reqState.zoomed);\n\tbreak;\n    case WMATT_FULLSCREEN:\n\tif (Tcl_GetBooleanFromObj(interp, value,\n\t\t&wmPtr->reqState.fullscreen) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tSetNetWmState(winPtr, \"_NET_WM_STATE_FULLSCREEN\",\n\t\twmPtr->reqState.fullscreen);\n\tbreak;\n    case _WMATT_LAST_ATTRIBUTE:\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGetAttribute --\n *\n *\tHelper routine for WmAttributesCmd. Returns the current value of the\n *\tspecified attribute.\n *\n * See also: CheckNetWmState().\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nWmGetAttribute(\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    WmAttribute attribute)\t/* Code of attribute to get */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    switch (attribute) {\n    case WMATT_ALPHA:\n\treturn Tcl_NewDoubleObj(wmPtr->attributes.alpha);\n    case WMATT_TOPMOST:\n\treturn Tcl_NewBooleanObj(wmPtr->attributes.topmost);\n    case WMATT_ZOOMED:\n\treturn Tcl_NewBooleanObj(wmPtr->attributes.zoomed);\n    case WMATT_FULLSCREEN:\n\treturn Tcl_NewBooleanObj(wmPtr->attributes.fullscreen);\n    case WMATT_TYPE:\n\treturn GetNetWmType(winPtr);\n    case _WMATT_LAST_ATTRIBUTE:\n\tbreak;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAttributesCmd --\n *\n *\tThis function is invoked to process the \"wm attributes\" Tcl command.\n *\n * Syntax:\n *\n *\twm attributes $win ?-attribute ?value attribute value...??\n *\n * Notes:\n *\n *\tAttributes of mapped windows are set by sending a _NET_WM_STATE\n *\tClientMessage to the root window (see SetNetWmState). For withdrawn\n *\twindows, we keep track of the requested attribute state, and set the\n *\t_NET_WM_STATE property ourselves immediately prior to mapping the\n *\twindow.\n *\n * See also: TIP#231, EWMH.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAttributesCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int attribute = 0;\n\n    if (objc == 3) {\t\t/* wm attributes $win */\n\tTcl_Obj *result = Tcl_NewListObj(0,0);\n\n\tfor (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) {\n\t    Tcl_ListObjAppendElement(interp, result,\n\t\t    Tcl_NewStringObj(WmAttributeNames[attribute], TCL_INDEX_NONE));\n\t    Tcl_ListObjAppendElement(interp, result,\n\t\t    WmGetAttribute(winPtr, (WmAttribute)attribute));\n\t}\n\tTcl_SetObjResult(interp, result);\n\treturn TCL_OK;\n    } else if (objc == 4) {\t/* wm attributes $win -attribute */\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames,\n\t\tsizeof(char *), \"attribute\", 0, &attribute) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTcl_SetObjResult(interp, WmGetAttribute(winPtr, (WmAttribute)attribute));\n\treturn TCL_OK;\n    } else if ((objc - 3) % 2 == 0) {\t/* wm attributes $win -att value... */\n\tTcl_Size i;\n\n\tfor (i = 3; i < objc; i += 2) {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames,\n\t\t    sizeof(char *), \"attribute\", 0, &attribute) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (WmSetAttribute(winPtr,interp,(WmAttribute)attribute,objv[i+1]) != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n\n    Tcl_WrongNumArgs(interp, 2, objv, \"window ?-attribute ?value ...??\");\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmClientCmd --\n *\n *\tThis function is invoked to process the \"wm client\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmClientCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(wmPtr->clientMachine, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (argv3[0] == 0) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_Free(wmPtr->clientMachine);\n\t    wmPtr->clientMachine = NULL;\n\t    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t\tXDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr,\n\t\t\t\t\"WM_CLIENT_MACHINE\"));\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    wmPtr->clientMachine = (char *)Tcl_Alloc(objv[3]->length + 1);\n    strcpy(wmPtr->clientMachine, argv3);\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tXTextProperty textProp;\n\tTcl_DString ds;\n\n\t(void)Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, TCL_INDEX_NONE, &ds);\n\tif (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,\n\t\t&textProp) != 0) {\n\t    unsigned long pid = (unsigned long) getpid();\n\n\t    XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t    &textProp);\n\t    XFree(textProp.value);\n\n\t    /*\n\t     * Inform the server (and more particularly any session manager)\n\t     * what our process ID is. We only do this when the CLIENT_MACHINE\n\t     * property is set since the spec for _NET_WM_PID requires that to\n\t     * be set too.\n\t     */\n\n\t    SetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_PID\", XA_CARDINAL,\n\t\t    32, &pid, 1);\n\t}\n\tTcl_DStringFree(&ds);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmColormapwindowsCmd --\n *\n *\tThis function is invoked to process the \"wm colormapwindows\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmColormapwindowsCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Window *cmapList;\n    TkWindow *winPtr2;\n    Tcl_Size i, windowObjc;\n    int count, gotToplevel;\n    Tcl_Obj **windowObjv, *resultObj;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?windowList?\");\n\treturn TCL_ERROR;\n    }\n    Tk_MakeWindowExist((Tk_Window) winPtr);\n    if (wmPtr->wrapperPtr == NULL) {\n\tCreateWrapper(wmPtr);\n    }\n    if (objc == 3) {\n\tif (XGetWMColormapWindows(winPtr->display,\n\t\twmPtr->wrapperPtr->window, &cmapList, &count) == 0) {\n\t    return TCL_OK;\n\t}\n\tresultObj = Tcl_NewObj();\n\tfor (i = 0; i < (Tcl_Size)count; i++) {\n\t    if ((i == ((Tcl_Size)count-1))\n\t\t    && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {\n\t\tbreak;\n\t    }\n\t    winPtr2 = (TkWindow *)\n\t\t   Tk_IdToWindow(winPtr->display, cmapList[i]);\n\t    if (winPtr2 == NULL) {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTcl_ObjPrintf(\"0x%lx\", cmapList[i]));\n\t    } else {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTcl_NewStringObj(winPtr2->pathName, TCL_INDEX_NONE));\n\t    }\n\t}\n\tXFree(cmapList);\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    cmapList = (Window *)Tcl_Alloc((windowObjc+1) * sizeof(Window));\n    gotToplevel = 0;\n    for (i = 0; i < windowObjc; i++) {\n\tTk_Window mapWin;\n\n\tif (TkGetWindowFromObj(interp, tkwin, windowObjv[i],\n\t\t&mapWin) != TCL_OK) {\n\t    Tcl_Free(cmapList);\n\t    return TCL_ERROR;\n\t}\n\twinPtr2 = (TkWindow *) mapWin;\n\tif (winPtr2 == winPtr) {\n\t    gotToplevel = 1;\n\t}\n\tif (winPtr2->window == None) {\n\t    Tk_MakeWindowExist((Tk_Window) winPtr2);\n\t}\n\tcmapList[i] = winPtr2->window;\n    }\n    if (!gotToplevel) {\n\twmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;\n\tcmapList[windowObjc] = wmPtr->wrapperPtr->window;\n\twindowObjc++;\n    } else {\n\twmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;\n    }\n    wmPtr->flags |= WM_COLORMAPS_EXPLICIT;\n    XSetWMColormapWindows(winPtr->display, wmPtr->wrapperPtr->window,\n\t    cmapList, windowObjc);\n    Tcl_Free(cmapList);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmCommandCmd --\n *\n *\tThis function is invoked to process the \"wm command\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmCommandCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size cmdArgc;\n    const char **cmdArgv;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?value?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->cmdArgv != NULL) {\n\t    char *arg = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);\n\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, TCL_INDEX_NONE));\n\t    Tcl_Free(arg);\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (argv3[0] == 0) {\n\tif (wmPtr->cmdArgv != NULL) {\n\t    Tcl_Free(wmPtr->cmdArgv);\n\t    wmPtr->cmdArgv = NULL;\n\t    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t\tXDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr, \"WM_COMMAND\"));\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->cmdArgv != NULL) {\n\tTcl_Free(wmPtr->cmdArgv);\n    }\n    wmPtr->cmdArgc = cmdArgc;\n    wmPtr->cmdArgv = cmdArgv;\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tUpdateCommand(winPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmDeiconifyCmd --\n *\n *\tThis function is invoked to process the \"wm deiconify\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmDeiconifyCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't deiconify %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"DEICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (winPtr->flags & TK_EMBEDDED) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't deiconify %s: it is an embedded window\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"DEICONIFY\", \"EMBEDDED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    wmPtr->flags &= ~WM_WITHDRAWN;\n    TkpWmSetState(winPtr, NormalState);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFocusmodelCmd --\n *\n *\tThis function is invoked to process the \"wm focusmodel\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFocusmodelCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"active\", \"passive\", NULL };\n    enum options {\n\tOPT_ACTIVE, OPT_PASSIVE };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?active|passive?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\twmPtr->hints.input ? \"passive\" : \"active\", TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t    sizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (index == OPT_ACTIVE) {\n\twmPtr->hints.input = False;\n    } else { /* OPT_PASSIVE */\n\twmPtr->hints.input = True;\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmForgetCmd --\n *\n *\tThis procedure is invoked to process the \"wm forget\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmForgetCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel or Frame to work with */\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t/* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window) winPtr;\n\n    /*\n     * Tk ticket c77b426d: avoid panic on usage after wm forget\n     */\n\n    if (Tk_IsTopLevel(frameWin) && Tk_IsManageable(frameWin)) {\n\tTkFocusJoin(winPtr);\n\tTk_UnmapWindow(frameWin);\n\tTkWmDeadWindow(winPtr);\n\twinPtr->flags &=\n\t\t~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);\n\tRemapWindows(winPtr, winPtr->parentPtr);\n\n\t/*\n\t * Make sure wm no longer manages this window\n\t */\n\tTk_ManageGeometry(frameWin, NULL, NULL);\n\n\t/*\n\t * Flags (above) must be cleared before calling TkMapTopFrame (below).\n\t */\n\n\tTkMapTopFrame(frameWin);\n    } else {\n\t/*\n\t * Already not managed by wm - ignore it.\n\t */\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFrameCmd --\n *\n *\tThis function is invoked to process the \"wm frame\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFrameCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Window window;\n    char buf[TCL_INTEGER_SPACE];\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    window = wmPtr->reparent;\n    if (window == None) {\n\twindow = Tk_WindowId((Tk_Window) winPtr);\n    }\n    snprintf(buf, sizeof(buf), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)window);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGeometryCmd --\n *\n *\tThis function is invoked to process the \"wm geometry\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGeometryCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    char xSign, ySign;\n    int width, height;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newGeometry?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\txSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';\n\tySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';\n\tif (wmPtr->gridWin != NULL) {\n\t    width = wmPtr->reqGridWidth + (winPtr->changes.width\n\t\t    - winPtr->reqWidth)/wmPtr->widthInc;\n\t    height = wmPtr->reqGridHeight + (winPtr->changes.height\n\t\t    - winPtr->reqHeight)/wmPtr->heightInc;\n\t} else {\n\t    width = winPtr->changes.width;\n\t    height = winPtr->changes.height;\n\t}\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%dx%d%c%d%c%d\",\n\t\twidth, height, xSign, wmPtr->x, ySign, wmPtr->y));\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n\tWmUpdateGeom(wmPtr, winPtr);\n\treturn TCL_OK;\n    }\n    return ParseGeometry(interp, argv3, winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGridCmd --\n *\n *\tThis function is invoked to process the \"wm grid\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGridCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int reqWidth, reqHeight, widthInc, heightInc;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?baseWidth baseHeight widthInc heightInc?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PBaseSize) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\t/*\n\t * Turn off gridding and reset the width and height to make sense as\n\t * ungridded numbers.\n\t */\n\n\twmPtr->sizeHintsFlags &= ~PBaseSize;\n\tif (wmPtr->width != -1) {\n\t    wmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t    - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t    wmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t    - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t}\n\twmPtr->widthInc = 1;\n\twmPtr->heightInc = 1;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &heightInc) !=TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif (reqWidth < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"baseWidth can't be < 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (reqHeight < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"baseHeight can't be < 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (widthInc <= 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"widthInc can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (heightInc <= 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"heightInc can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,\n\t\theightInc);\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGroupCmd --\n *\n *\tThis function is invoked to process the \"wm group\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGroupCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    WmInfo *wmPtr2;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & WindowGroupHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\twmPtr->hints.flags &= ~WindowGroupHint;\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->leaderName = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\twhile (!Tk_TopWinHierarchy(tkwin2)) {\n\t    /*\n\t     * Ensure that the group leader is actually a Tk toplevel.\n\t     */\n\n\t    tkwin2 = Tk_Parent(tkwin2);\n\t}\n\tTk_MakeWindowExist(tkwin2);\n\twmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;\n\tif (wmPtr2->wrapperPtr == NULL) {\n\t    CreateWrapper(wmPtr2);\n\t}\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr);\n\twmPtr->hints.flags |= WindowGroupHint;\n\twmPtr->leaderName = (char *)Tcl_Alloc(objv[3]->length + 1);\n\tstrcpy(wmPtr->leaderName, argv3);\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconbadgeCmd --\n *\n *\tThis function is invoked to process the \"wm iconbadge\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbadgeCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *tkWin,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    (void) tkWin;\n    char cmd[4096];\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window badge\");\n\treturn TCL_ERROR;\n    }\n\n    snprintf(cmd, sizeof(cmd), \"::tk::icons::IconBadge {%s} {%s}\",\n\t    Tcl_GetString(objv[2]),\n\t    Tcl_GetString(objv[3]));\n    if (Tcl_EvalEx(interp, cmd, TCL_INDEX_NONE, TCL_EVAL_DIRECT) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconbitmapCmd --\n *\n *\tThis function is invoked to process the \"wm iconbitmap\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbitmapCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Pixmap pixmap;\n    const char *argv3;\n\n    if ((objc < 3) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?bitmap?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconPixmapHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display,\n\t\t\t    wmPtr->hints.icon_pixmap), TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\tif (wmPtr->hints.icon_pixmap != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n\t    wmPtr->hints.icon_pixmap = None;\n\t}\n\twmPtr->hints.flags &= ~IconPixmapHint;\n    } else {\n\tpixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, argv3);\n\tif (pixmap == None) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_pixmap = pixmap;\n\twmPtr->hints.flags |= IconPixmapHint;\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconifyCmd --\n *\n *\tThis function is invoked to process the \"wm iconify\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconifyCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"OVERRIDE_REDIRECT\",\n\t\tNULL);\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->containerPtr != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is a transient\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"TRANSIENT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is an icon for \\\"%s\\\"\",\n\t\twinPtr->pathName, Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (winPtr->flags & TK_EMBEDDED) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is an embedded window\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"EMBEDDED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (TkpWmSetState(winPtr, IconicState) == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"couldn't send iconify message to window manager\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconmaskCmd --\n *\n *\tThis function is invoked to process the \"wm iconmask\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconmaskCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Pixmap pixmap;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?bitmap?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconMaskHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),\n\t\t    -1));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\tif (wmPtr->hints.icon_mask != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n\t}\n\twmPtr->hints.flags &= ~IconMaskHint;\n    } else {\n\tpixmap = Tk_GetBitmap(interp, tkwin, argv3);\n\tif (pixmap == None) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_mask = pixmap;\n\twmPtr->hints.flags |= IconMaskHint;\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconnameCmd --\n *\n *\tThis function is invoked to process the \"wm iconname\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconnameCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->iconName != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    } else {\n\tif (wmPtr->iconName != NULL) {\n\t    Tcl_Free(wmPtr->iconName);\n\t}\n\targv3 = Tcl_GetString(objv[3]);\n\twmPtr->iconName = (char *)Tcl_Alloc(objv[3]->length + 1);\n\tstrcpy(wmPtr->iconName, argv3);\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    UpdateTitle(winPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconphotoCmd --\n *\n *\tThis function is invoked to process the \"wm iconphoto\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconphotoCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_PhotoHandle photo;\n    Tk_PhotoImageBlock block;\n    Tcl_Size i;\n    int size = 0, width, height, index = 0, x, y, isDefault = 0;\n    unsigned long *iconPropertyData;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?-default? image1 ?image2 ...?\");\n\treturn TCL_ERROR;\n    }\n    if (strcmp(Tcl_GetString(objv[3]), \"-default\") == 0) {\n\tisDefault = 1;\n\tif (objc == 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"window ?-default? image1 ?image2 ...?\");\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Iterate over all images to retrieve their sizes, in order to allocate a\n     * buffer large enough to hold all images.\n     */\n\n    for (i = 3 + isDefault; i < objc; i++) {\n\tphoto = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));\n\tif (photo == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't use \\\"%s\\\" as iconphoto: not a photo image\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"PHOTO\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_PhotoGetSize(photo, &width, &height);\n\n\t/*\n\t * We need to cardinals for width & height and one cardinal for each\n\t * image pixel.\n\t */\n\n\tsize += 2 + width * height;\n    }\n\n    /*\n     * We have calculated the size of the data. Try to allocate the needed\n     * memory space. This is an unsigned long array (despite this being twice\n     * as much as is really needed on LP64 platforms) because that's what X\n     * defines CARD32 arrays to use. [Bug 2902814]\n     */\n\n    iconPropertyData = (unsigned long *)Tcl_AttemptAlloc(sizeof(unsigned long) * size);\n    if (iconPropertyData == NULL) {\n\treturn TCL_ERROR;\n    }\n    memset(iconPropertyData, 0, sizeof(unsigned long) * size);\n\n    for (i = 3 + isDefault; i < objc; i++) {\n\tphoto = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));\n\tif (photo == NULL) {\n\t    Tcl_Free(iconPropertyData);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"failed to create an iconphoto with image \\\"%s\\\"\",\n\t\tTcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"IMAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_PhotoGetSize(photo, &width, &height);\n\tTk_PhotoGetImage(photo, &block);\n\n\t/*\n\t * Each image data will be placed as an array of 32bit packed\n\t * CARDINAL, in a window property named \"_NET_WM_ICON\": _NET_WM_ICON\n\t *\n\t * _NET_WM_ICON CARDINAL[][2+n]/32\n\t *\n\t * This is an array of possible icons for the client. This spec. does\n\t * not stipulate what size these icons should be, but individual\n\t * desktop environments or toolkits may do so. The Window Manager MAY\n\t * scale any of these icons to an appropriate size.\n\t *\n\t * This is an array of 32bit packed CARDINAL ARGB with high byte being\n\t * A, low byte being B. The first two cardinals are width, height.\n\t * Data is in rows, left to right and top to bottom. The data will be\n\t * endian-swapped going to the server if necessary. [Bug 2830420]\n\t *\n\t * The image data will be encoded in the iconPropertyData array.\n\t */\n\n\ticonPropertyData[index++] = (unsigned long) width;\n\ticonPropertyData[index++] = (unsigned long) height;\n\tfor (y = 0; y < height; y++) {\n\t    for (x = 0; x < width; x++) {\n\t\tunsigned char *pixelPtr =\n\t\t\tblock.pixelPtr + x*block.pixelSize + y*block.pitch;\n\t\tunsigned long R, G, B, A;\n\n\t\tR = pixelPtr[block.offset[0]];\n\t\tG = pixelPtr[block.offset[1]];\n\t\tB = pixelPtr[block.offset[2]];\n\t\tA = pixelPtr[block.offset[3]];\n\t\ticonPropertyData[index++] = A<<24 | R<<16 | G<<8 | B<<0;\n\t    }\n\t}\n    }\n    if (wmPtr->iconDataPtr != NULL) {\n\tTcl_Free(wmPtr->iconDataPtr);\n\twmPtr->iconDataPtr = NULL;\n    }\n    if (isDefault) {\n\tif (winPtr->dispPtr->iconDataPtr != NULL) {\n\t    Tcl_Free(winPtr->dispPtr->iconDataPtr);\n\t}\n\twinPtr->dispPtr->iconDataPtr = (unsigned char *) iconPropertyData;\n\twinPtr->dispPtr->iconDataSize = size;\n    } else {\n\twmPtr->iconDataPtr = (unsigned char *) iconPropertyData;\n\twmPtr->iconDataSize = size;\n    }\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tUpdatePhotoIcon(winPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconpositionCmd --\n *\n *\tThis function is invoked to process the \"wm iconposition\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconpositionCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?x y?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconPositionHint) {\n\t    Tcl_Obj *results[2];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_GetString(objv[3])[0] == '\\0') {\n\twmPtr->hints.flags &= ~IconPositionHint;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_x = x;\n\twmPtr->hints.icon_y = y;\n\twmPtr->hints.flags |= IconPositionHint;\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconwindowCmd --\n *\n *\tThis function is invoked to process the \"wm iconwindow\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconwindowCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    WmInfo *wmPtr2;\n    XSetWindowAttributes atts;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->icon != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->hints.flags &= ~IconWindowHint;\n\tif (wmPtr->icon != NULL) {\n\t    /*\n\t     * Remove the icon window relationship. In principle we should\n\t     * also re-enable button events for the window, but this doesn't\n\t     * work in general because the window manager is probably\n\t     * selecting on them (we'll get an error if we try to re-enable\n\t     * the events). So, just leave the icon window event-challenged;\n\t     * the user will have to recreate it if they want button events.\n\t     */\n\n\t    wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\t    wmPtr2->iconFor = NULL;\n\t    wmPtr2->withdrawn = 1;\n\t    wmPtr2->hints.initial_state = WithdrawnState;\n\t}\n\twmPtr->icon = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (!Tk_IsTopLevel(tkwin2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't use %s as icon window: not at top level\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"INNER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;\n\tif (wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s is already an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (wmPtr->icon != NULL) {\n\t    WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\n\t    wmPtr3->iconFor = NULL;\n\t    wmPtr3->withdrawn = 1;\n\t    wmPtr3->hints.initial_state = WithdrawnState;\n\t}\n\n\t/*\n\t * Disable button events in the icon window: some window managers\n\t * (like olvwm) want to get the events themselves, but X only allows\n\t * one application at a time to receive button events for a window.\n\t */\n\n\tatts.event_mask = Tk_Attributes(tkwin2)->event_mask\n\t\t& ~ButtonPressMask;\n\tTk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);\n\tTk_MakeWindowExist(tkwin2);\n\tif (wmPtr2->wrapperPtr == NULL) {\n\t    CreateWrapper(wmPtr2);\n\t}\n\twmPtr->hints.icon_window = Tk_WindowId(wmPtr2->wrapperPtr);\n\twmPtr->hints.flags |= IconWindowHint;\n\twmPtr->icon = tkwin2;\n\twmPtr2->iconFor = (Tk_Window) winPtr;\n\tif (!wmPtr2->withdrawn && !(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t    wmPtr2->withdrawn = 0;\n\t    if (XWithdrawWindow(Tk_Display(tkwin2),\n\t\t    Tk_WindowId(wmPtr2->wrapperPtr),\n\t\t    Tk_ScreenNumber(tkwin2)) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't send withdraw message to window manager\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    WaitForMapNotify((TkWindow *) tkwin2, 0);\n\t}\n    }\n    UpdateHints(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmManageCmd --\n *\n *\tThis procedure is invoked to process the \"wm manage\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmManageCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel or Frame to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t/* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window) winPtr;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!Tk_IsTopLevel(frameWin)) {\n\tif (!Tk_IsManageable(frameWin)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" is not manageable: must be a frame,\"\n\t\t    \" labelframe or toplevel\", Tk_PathName(frameWin)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"MANAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTkFocusSplit(winPtr);\n\tTk_UnmapWindow(frameWin);\n\twinPtr->flags |=\n\t\tTK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;\n\tif (wmPtr == NULL) {\n\t    TkWmNewWindow(winPtr);\n\t    TkWmMapWindow(winPtr);\n\t    Tk_UnmapWindow(frameWin);\n\t}\n\twmPtr = winPtr->wmInfoPtr;\n\twinPtr->flags &= ~TK_MAPPED;\n\tRemapWindows(winPtr, wmPtr->wrapperPtr);\n\n\t/*\n\t * Flags (above) must be set before calling TkMapTopFrame (below).\n\t */\n\n\tTkMapTopFrame(frameWin);\n    } else if (Tk_IsTopLevel(frameWin)) {\n\t/*\n\t * Already managed by wm - ignore it.\n\t */\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMaxsizeCmd --\n *\n *\tThis function is invoked to process the \"wm maxsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMaxsizeCmd(\n    Tk_Window tkwin,\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tGetMaxSize(wmPtr, &width, &height);\n\tresults[0] = Tcl_NewWideIntObj(width);\n\tresults[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->maxWidth = width;\n    wmPtr->maxHeight = height;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n\n    if (width <= 0 && height <= 0) {\n\twmPtr->sizeHintsFlags &= ~PMaxSize;\n    } else {\n\twmPtr->sizeHintsFlags |= PMaxSize;\n    }\n\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMinsizeCmd --\n *\n *\tThis function is invoked to process the \"wm minsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMinsizeCmd(\n    Tk_Window tkwin,\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tresults[0] = Tcl_NewWideIntObj(wmPtr->minWidth);\n\tresults[1] = Tcl_NewWideIntObj(wmPtr->minHeight);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->minWidth = width;\n    wmPtr->minHeight = height;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmOverrideredirectCmd --\n *\n *\tThis function is invoked to process the \"wm overrideredirect\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmOverrideredirectCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Bool boolValue, curValue;\n    XSetWindowAttributes atts;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?boolean?\");\n\treturn TCL_ERROR;\n    }\n    curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(curValue));\n\treturn TCL_OK;\n    }\n    if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (curValue != boolValue) {\n\t/*\n\t * Only do this if we are really changing value, because it causes\n\t * some funky stuff to occur\n\t */\n\n\tatts.override_redirect = boolValue;\n\tTk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,\n\t\t&atts);\n\tif (winPtr->wmInfoPtr->wrapperPtr != NULL) {\n\t    Tk_ChangeWindowAttributes(\n\t\t    (Tk_Window) winPtr->wmInfoPtr->wrapperPtr,\n\t\t    CWOverrideRedirect, &atts);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmPositionfromCmd --\n *\n *\tThis function is invoked to process the \"wm positionfrom\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmPositionfromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL };\n    enum options {\n\tOPT_PROGRAM, OPT_USER };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user/program?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tconst char *sourceStr = \"\";\n\n\tif (wmPtr->sizeHintsFlags & USPosition) {\n\t    sourceStr = \"user\";\n\t} else if (wmPtr->sizeHintsFlags & PPosition) {\n\t    sourceStr = \"program\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USPosition|PPosition);\n    } else {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PPosition;\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t} else {\n\t    wmPtr->sizeHintsFlags &= ~USPosition;\n\t    wmPtr->sizeHintsFlags |= PPosition;\n\t}\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmProtocolCmd --\n *\n *\tThis function is invoked to process the \"wm protocol\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmProtocolCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    ProtocolHandler *protPtr, *prevPtr;\n    Atom protocol;\n    const char *cmd;\n    Tcl_Size cmdLength;\n\n    if ((objc < 3) || (objc > 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name? ?command?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\t/*\n\t * Return a list of all defined protocols for the window.\n\t */\n\n\tTcl_Obj *resultObj = Tcl_NewObj();\n\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol),-1));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n    protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));\n    if (objc == 4) {\n\t/*\n\t * Return the command to handle a given protocol.\n\t */\n\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    if (protPtr->protocol == protocol) {\n\t\tTcl_SetObjResult(interp,\n\t\t\tTcl_NewStringObj(protPtr->command, TCL_INDEX_NONE));\n\t\treturn TCL_OK;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n\n    /*\n     * Special case for _NET_WM_PING: that's always handled directly.\n     */\n\n    if (strcmp(Tcl_GetString(objv[3]), \"_NET_WM_PING\") == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"may not alter handling of that protocol\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"PROTOCOL\", \"RESERVED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Delete any current protocol handler, then create a new one with the\n     * specified command, unless the command is empty.\n     */\n\n    for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;\n\t    prevPtr = protPtr, protPtr = protPtr->nextPtr) {\n\tif (protPtr->protocol == protocol) {\n\t    if (prevPtr == NULL) {\n\t\twmPtr->protPtr = protPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = protPtr->nextPtr;\n\t    }\n\t    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n\t    break;\n\t}\n    }\n    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);\n    if (cmdLength > 0) {\n\tprotPtr = (ProtocolHandler *)Tcl_Alloc(HANDLER_SIZE(cmdLength));\n\tprotPtr->protocol = protocol;\n\tprotPtr->nextPtr = wmPtr->protPtr;\n\twmPtr->protPtr = protPtr;\n\tprotPtr->interp = interp;\n\tmemcpy(protPtr->command, cmd, cmdLength + 1);\n    }\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tUpdateWmProtocols(wmPtr);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmResizableCmd --\n *\n *\tThis function is invoked to process the \"wm resizable\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmResizableCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tresults[0] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));\n\tresults[1] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)\n\t    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (width) {\n\twmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;\n    } else {\n\twmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;\n    }\n    if (height) {\n\twmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;\n    } else {\n\twmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmSizefromCmd --\n *\n *\tThis function is invoked to process the \"wm sizefrom\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmSizefromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL };\n    enum options {\n\tOPT_PROGRAM, OPT_USER };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user|program?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tconst char *sourceStr = \"\";\n\n\tif (wmPtr->sizeHintsFlags & USSize) {\n\t    sourceStr = \"user\";\n\t} else if (wmPtr->sizeHintsFlags & PSize) {\n\t    sourceStr = \"program\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USSize|PSize);\n    } else {\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PSize;\n\t    wmPtr->sizeHintsFlags |= USSize;\n\t} else { /* OPT_PROGRAM */\n\t    wmPtr->sizeHintsFlags &= ~USSize;\n\t    wmPtr->sizeHintsFlags |= PSize;\n\t}\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStackorderCmd --\n *\n *\tThis function is invoked to process the \"wm stackorder\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStackorderCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkWindow **windows, **window_ptr;\n    static const char *const optionStrings[] = {\n\t\"isabove\", \"isbelow\", NULL };\n    enum options {\n\tOPT_ISABOVE, OPT_ISBELOW };\n    int index;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?isabove|isbelow window?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\twindows = TkWmStackorderToplevel(winPtr);\n\tif (windows != NULL) {\n\t    Tcl_Obj *resultObj = Tcl_NewObj();\n\n\t    /* ASSERT: true [Bug 1789819]*/\n\t    for (window_ptr = windows; *window_ptr ; window_ptr++) {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTcl_NewStringObj((*window_ptr)->pathName, TCL_INDEX_NONE));\n\t    }\n\t    Tcl_Free(windows);\n\t    Tcl_SetObjResult(interp, resultObj);\n\t    return TCL_OK;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tTk_Window relWin;\n\tTkWindow *winPtr2;\n\tint index1=-1, index2=-1, result;\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[4], &relWin) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\twinPtr2 = (TkWindow *) relWin;\n\n\tif (!Tk_IsTopLevel(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't a top-level window\",\n\t\t    winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"TOPLEVEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsMapped(winPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsMapped(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Lookup stacking order of all toplevels that are children of \".\" and\n\t * find the position of winPtr and winPtr2 in the stacking order.\n\t */\n\n\twindows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);\n\tif (windows == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"TkWmStackorderToplevel failed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (window_ptr = windows; *window_ptr ; window_ptr++) {\n\t    if (*window_ptr == winPtr) {\n\t\tindex1 = (window_ptr - windows);\n\t    }\n\t    if (*window_ptr == winPtr2) {\n\t\tindex2 = (window_ptr - windows);\n\t    }\n\t}\n\t/* ASSERT: index1 != -1 && index2 != -2 [Bug 1789819] */\n\tTcl_Free(windows);\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_ISABOVE) {\n\t    result = index1 > index2;\n\t} else { /* OPT_ISBELOW */\n\t    result = index1 < index2;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(result));\n\treturn TCL_OK;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStateCmd --\n *\n *\tThis function is invoked to process the \"wm state\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStateCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"iconic\", \"normal\", \"withdrawn\", NULL };\n    enum options {\n\tOPT_ICONIC, OPT_NORMAL, OPT_WITHDRAWN };\n    int index;\n\n    if ((objc < 3) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?state?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 4) {\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't change state of %s: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,\n\t\tsizeof(char *), \"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (index == OPT_NORMAL) {\n\t    wmPtr->flags &= ~WM_WITHDRAWN;\n\t    (void) TkpWmSetState(winPtr, NormalState);\n\t} else if (index == OPT_ICONIC) {\n\t    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\",\n\t\t\t\"OVERRIDE_REDIRECT\", NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (wmPtr->containerPtr != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": it is a transient\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"TRANSIENT\",\n\t\t\tNULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (TkpWmSetState(winPtr, IconicState) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't send iconify message to window manager\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else { /* OPT_WITHDRAWN */\n\t    wmPtr->flags |= WM_WITHDRAWN;\n\t    if (TkpWmSetState(winPtr, WithdrawnState) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't send withdraw message to window manager\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n    } else {\n\tconst char *state;\n\n\tif (wmPtr->iconFor != NULL) {\n\t    state = \"icon\";\n\t} else if (wmPtr->withdrawn) {\n\t    state = \"withdrawn\";\n\t} else if (Tk_IsMapped((Tk_Window) winPtr)\n\t\t|| ((wmPtr->flags & WM_NEVER_MAPPED)\n\t\t\t&& (wmPtr->hints.initial_state == NormalState))) {\n\t    state = \"normal\";\n\t} else {\n\t    state = \"iconic\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(state, TCL_INDEX_NONE));\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTitleCmd --\n *\n *\tThis function is invoked to process the \"wm title\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTitleCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newTitle?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->title) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->title, TCL_INDEX_NONE));\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->nameUid, TCL_INDEX_NONE));\n\t}\n    } else {\n\tif (wmPtr->title != NULL) {\n\t    Tcl_Free(wmPtr->title);\n\t}\n\targv3 = Tcl_GetString(objv[3]);\n\twmPtr->title = (char *)Tcl_Alloc(objv[3]->length + 1);\n\tstrcpy(wmPtr->title, argv3);\n\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    UpdateTitle(winPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTransientCmd --\n *\n *\tThis function is invoked to process the \"wm transient\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTransientCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    TkWindow *containerPtr = wmPtr->containerPtr, *w;\n    WmInfo *wmPtr2;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?window?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (containerPtr != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) containerPtr));\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_GetString(objv[3])[0] == '\\0') {\n\tif (containerPtr != NULL) {\n\t    /*\n\t     * If we had a container, tell them that we aren't tied to them\n\t     * anymore\n\t     */\n\n\t    containerPtr->wmInfoPtr->numTransients--;\n\t    Tk_DeleteEventHandler((Tk_Window) containerPtr, StructureNotifyMask,\n\t\t    WmWaitMapProc, winPtr);\n\n\t    /*\n\t     * FIXME: Need a call like Win32's UpdateWrapper() so we can\n\t     * recreate the wrapper and get rid of the transient window\n\t     * decorations.\n\t     */\n\t}\n\n\twmPtr->containerPtr = NULL;\n    } else {\n\tTk_Window container;\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &container)!=TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tcontainerPtr = (TkWindow *) container;\n\twhile (!Tk_TopWinHierarchy(containerPtr)) {\n\t    /*\n\t     * Ensure that the container window is actually a Tk toplevel.\n\t     */\n\n\t    containerPtr = containerPtr->parentPtr;\n\t}\n\tTk_MakeWindowExist((Tk_Window) containerPtr);\n\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a transient: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\twmPtr2 = containerPtr->wmInfoPtr;\n\tif (wmPtr2->wrapperPtr == NULL) {\n\t    CreateWrapper(wmPtr2);\n\t}\n\n\tif (wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a container: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;\n\t    w = (TkWindow *)w->wmInfoPtr->containerPtr) {\n\t    if (w == winPtr) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't set \\\"%s\\\" as container: would cause management loop\",\n\t\t    Tk_PathName(containerPtr)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"SELF\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\tif (containerPtr != wmPtr->containerPtr) {\n\t    /*\n\t     * Remove old container map/unmap binding before setting the new\n\t     * container. The event handler will ensure that transient states\n\t     * reflect the state of the container.\n\t     */\n\n\t    if (wmPtr->containerPtr != NULL) {\n\t\twmPtr->containerPtr->wmInfoPtr->numTransients--;\n\t\tTk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,\n\t\t\tStructureNotifyMask, WmWaitMapProc, winPtr);\n\t    }\n\n\t    containerPtr->wmInfoPtr->numTransients++;\n\t    Tk_CreateEventHandler((Tk_Window) containerPtr,\n\t\t    StructureNotifyMask, WmWaitMapProc, winPtr);\n\n\t    wmPtr->containerPtr = containerPtr;\n\t}\n    }\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tif (wmPtr->containerPtr != NULL && !Tk_IsMapped(wmPtr->containerPtr)) {\n\t    if (TkpWmSetState(winPtr, WithdrawnState) == 0) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"couldn't send withdraw message to window manager\",\n\t\t\t-1));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    if (wmPtr->containerPtr != NULL) {\n\t\tXSetTransientForHint(winPtr->display,\n\t\t\twmPtr->wrapperPtr->window,\n\t\t\twmPtr->containerPtr->wmInfoPtr->wrapperPtr->window);\n\t    } else {\n\t\tXDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr,\"WM_TRANSIENT_FOR\"));\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmWithdrawCmd --\n *\n *\tThis function is invoked to process the \"wm withdraw\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmWithdrawCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't withdraw %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"WITHDRAW\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    wmPtr->flags |= WM_WITHDRAWN;\n    if (TkpWmSetState(winPtr, WithdrawnState) == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"couldn't send withdraw message to window manager\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\n/*\n * Invoked by those wm subcommands that affect geometry. Schedules a geometry\n * update.\n */\n\nstatic void\nWmUpdateGeom(\n    WmInfo *wmPtr,\n    TkWindow *winPtr)\n{\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\n/*\n * Invoked when a MapNotify or UnmapNotify event is delivered for a toplevel\n * that is the container of a transient toplevel.\n */\n\nstatic void\nWmWaitMapProc(\n    void *clientData,\t/* Pointer to window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    TkWindow *containerPtr = winPtr->wmInfoPtr->containerPtr;\n\n    if (containerPtr == NULL) {\n\treturn;\n    }\n\n    if (eventPtr->type == MapNotify) {\n\tif (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN)) {\n\t    (void) TkpWmSetState(winPtr, NormalState);\n\t}\n    } else if (eventPtr->type == UnmapNotify) {\n\t(void) TkpWmSetState(winPtr, WithdrawnState);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetGrid --\n *\n *\tThis function is invoked by a widget when it wishes to set a grid\n *\tcoordinate system that controls the size of a top-level window. It\n *\tprovides a C interface equivalent to the \"wm grid\" command and is\n *\tusually associated with the -setgrid option.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGrid-related information will be passed to the window manager, so that\n *\tthe top-level window associated with tkwin will resize on even grid\n *\tunits. If some other window already controls gridding for the\n *\ttop-level window then this function call has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetGrid(\n    Tk_Window tkwin,\t\t/* Token for window. New window mgr info will\n\t\t\t\t * be posted for the top-level window\n\t\t\t\t * associated with this window. */\n    int reqWidth,\t\t/* Width (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int reqHeight,\t\t/* Height (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int widthInc, int heightInc)/* Pixel increments corresponding to a change\n\t\t\t\t * of one grid unit. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Ensure widthInc and heightInc are greater than 0\n     */\n\n    if (widthInc <= 0) {\n\twidthInc = 1;\n    }\n    if (heightInc <= 0) {\n\theightInc = 1;\n    }\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\twinPtr = winPtr->parentPtr;\n\tif (winPtr == NULL) {\n\t    /*\n\t     * The window is being deleted... just skip this operation.\n\t     */\n\n\t    return;\n\t}\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {\n\treturn;\n    }\n\n    if ((wmPtr->reqGridWidth == reqWidth)\n\t    && (wmPtr->reqGridHeight == reqHeight)\n\t    && (wmPtr->widthInc == widthInc)\n\t    && (wmPtr->heightInc == heightInc)\n\t    && ((wmPtr->sizeHintsFlags & PBaseSize) == PBaseSize)) {\n\treturn;\n    }\n\n    /*\n     * If gridding was previously off, then forget about any window size\n     * requests made by the user or via \"wm geometry\": these are in pixel\n     * units and there's no easy way to translate them to grid units since the\n     * new requested size of the top-level window in pixels may not yet have\n     * been registered yet (it may filter up the hierarchy in DoWhenIdle\n     * handlers). However, if the window has never been mapped yet then just\n     * leave the window size alone: assume that it is intended to be in grid\n     * units but just happened to have been specified before this function was\n     * called.\n     */\n\n    if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n    }\n\n    /*\n     * Set the new gridding information, and start the process of passing all\n     * of this information to the window manager.\n     */\n\n    wmPtr->gridWin = tkwin;\n    wmPtr->reqGridWidth = reqWidth;\n    wmPtr->reqGridHeight = reqHeight;\n    wmPtr->widthInc = widthInc;\n    wmPtr->heightInc = heightInc;\n    wmPtr->sizeHintsFlags |= PBaseSize;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UnsetGrid --\n *\n *\tThis function cancels the effect of a previous call to Tk_SetGrid.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf tkwin currently controls gridding for its top-level window,\n *\tgridding is cancelled for that top-level window; if some other window\n *\tcontrols gridding then this function has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UnsetGrid(\n    Tk_Window tkwin)\t\t/* Token for window that is currently\n\t\t\t\t * controlling gridding. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\twinPtr = winPtr->parentPtr;\n\tif (winPtr == NULL) {\n\t    /*\n\t     * The window is being deleted... just skip this operation.\n\t     */\n\n\t    return;\n\t}\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if (tkwin != wmPtr->gridWin) {\n\treturn;\n    }\n\n    wmPtr->gridWin = NULL;\n    wmPtr->sizeHintsFlags &= ~PBaseSize;\n    if (wmPtr->width != -1) {\n\twmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t- wmPtr->reqGridWidth)*wmPtr->widthInc;\n\twmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t- wmPtr->reqGridHeight)*wmPtr->heightInc;\n    }\n    wmPtr->widthInc = 1;\n    wmPtr->heightInc = 1;\n\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureEvent --\n *\n *\tThis function is called to handle ConfigureNotify events on wrapper\n *\twindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets updated in the WmInfo structure for the window and\n *\tthe toplevel itself gets repositioned within the wrapper.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConfigureEvent(\n    WmInfo *wmPtr,\t\t/* Information about toplevel window. */\n    XConfigureEvent *configEventPtr)\n\t\t\t\t/* Event that just occurred for\n\t\t\t\t * wmPtr->wrapperPtr. */\n{\n    TkWindow *wrapperPtr = wmPtr->wrapperPtr;\n    TkWindow *winPtr = wmPtr->winPtr;\n    TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;\n    Tk_ErrorHandler handler;\n\n    /*\n     * Update size information from the event. There are a couple of tricky\n     * points here:\n     *\n     * 1. If the user changed the size externally then set wmPtr->width and\n     *    wmPtr->height just as if a \"wm geometry\" command had been invoked\n     *    with the same information.\n     * 2. However, if the size is changing in response to a request coming\n     *    from us (WM_SYNC_PENDING is set), then don't set wmPtr->width or\n     *    wmPtr->height if they were previously -1 (otherwise the window will\n     *    stop tracking geometry manager requests).\n     */\n\n    if (((wrapperPtr->changes.width != configEventPtr->width)\n\t    || (wrapperPtr->changes.height != configEventPtr->height))\n\t    && !(wmPtr->flags & WM_SYNC_PENDING)) {\n\tif (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t    printf(\"TopLevelEventProc: user changed %s size to %dx%d\\n\",\n\t\t    winPtr->pathName, configEventPtr->width,\n\t\t    configEventPtr->height);\n\t}\n\tif ((wmPtr->width == -1)\n\t\t&& (configEventPtr->width == winPtr->reqWidth)) {\n\t    /*\n\t     * Don't set external width, since the user didn't change it from\n\t     * what the widgets asked for.\n\t     */\n\t} else {\n\t    /*\n\t     * Note: if this window is embedded then don't set the external\n\t     * size, since it came from the containing application, not the\n\t     * user. In this case we want to keep sending our size requests to\n\t     * the containing application; if the user fixes the size of that\n\t     * application then it will still percolate down to us in the\n\t     * right way.\n\t     */\n\n\t    if (!(winPtr->flags & TK_EMBEDDED)) {\n\t\tif (wmPtr->gridWin != NULL) {\n\t\t    wmPtr->width = wmPtr->reqGridWidth\n\t\t\t    + (configEventPtr->width\n\t\t\t    - winPtr->reqWidth)/wmPtr->widthInc;\n\t\t    if (wmPtr->width < 0) {\n\t\t\twmPtr->width = 0;\n\t\t    }\n\t\t} else {\n\t\t    wmPtr->width = configEventPtr->width;\n\t\t}\n\t    }\n\t}\n\tif ((wmPtr->height == -1)\n\t\t&& (configEventPtr->height ==\n\t\t\t(winPtr->reqHeight + wmPtr->menuHeight))) {\n\t    /*\n\t     * Don't set external height, since the user didn't change it from\n\t     * what the widgets asked for.\n\t     */\n\t} else {\n\t    /*\n\t     * See note for wmPtr->width about not setting external size for\n\t     * embedded windows.\n\t     */\n\n\t    if (!(winPtr->flags & TK_EMBEDDED)) {\n\t\tif (wmPtr->gridWin != NULL) {\n\t\t    wmPtr->height = wmPtr->reqGridHeight\n\t\t\t    + (configEventPtr->height - wmPtr->menuHeight\n\t\t\t    - winPtr->reqHeight)/wmPtr->heightInc;\n\t\t    if (wmPtr->height < 0) {\n\t\t\twmPtr->height = 0;\n\t\t    }\n\t\t} else {\n\t\t    wmPtr->height = configEventPtr->height - wmPtr->menuHeight;\n\t\t}\n\t    }\n\t}\n\twmPtr->configWidth = configEventPtr->width;\n\twmPtr->configHeight = configEventPtr->height;\n    }\n\n    if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"ConfigureEvent: %s x = %d y = %d, width = %d, height = %d\\n\",\n\t\twinPtr->pathName, configEventPtr->x, configEventPtr->y,\n\t\tconfigEventPtr->width, configEventPtr->height);\n\tprintf(\"    send_event = %d, serial = %ld (win %p, wrapper %p)\\n\",\n\t\tconfigEventPtr->send_event, configEventPtr->serial,\n\t\twinPtr, wrapperPtr);\n    }\n    wrapperPtr->changes.width = configEventPtr->width;\n    wrapperPtr->changes.height = configEventPtr->height;\n    wrapperPtr->changes.border_width = configEventPtr->border_width;\n    wrapperPtr->changes.sibling = configEventPtr->above;\n    wrapperPtr->changes.stack_mode = Above;\n\n    /*\n     * Reparenting window managers make life difficult. If the window manager\n     * reparents a top-level window then the x and y information that comes in\n     * events for the window is wrong: it gives the location of the window\n     * inside its decorative parent, rather than the location of the window in\n     * root coordinates, which is what we want. Window managers are supposed\n     * to send synthetic events with the correct information, but ICCCM\n     * doesn't require them to do this under all conditions, and the\n     * information provided doesn't include everything we need here. So, the\n     * code below maintains a bunch of information about the parent window.\n     * If the window hasn't been reparented, we pretend that there is a parent\n     * shrink-wrapped around the window.\n     */\n\n    if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"    %s parent == %p, above %p\\n\",\n\t\twinPtr->pathName, (void *) wmPtr->reparent,\n\t\t(void *) configEventPtr->above);\n    }\n\n    if ((wmPtr->reparent == None) || !ComputeReparentGeometry(wmPtr)) {\n\twmPtr->parentWidth = configEventPtr->width\n\t\t+ 2*configEventPtr->border_width;\n\twmPtr->parentHeight = configEventPtr->height\n\t\t+ 2*configEventPtr->border_width;\n\twrapperPtr->changes.x = wmPtr->x = configEventPtr->x;\n\twrapperPtr->changes.y = wmPtr->y = configEventPtr->y;\n\tif (wmPtr->flags & WM_NEGATIVE_X) {\n\t    wmPtr->x = wmPtr->vRootWidth - (wmPtr->x + wmPtr->parentWidth);\n\t}\n\tif (wmPtr->flags & WM_NEGATIVE_Y) {\n\t    wmPtr->y = wmPtr->vRootHeight - (wmPtr->y + wmPtr->parentHeight);\n\t}\n    }\n\n    /*\n     * Make sure that the toplevel and menubar are properly positioned within\n     * the wrapper. If the menuHeight happens to be zero, we'll get a BadValue\n     * X error that we want to ignore [Bug: 3377]\n     */\n\n    handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL);\n    XMoveResizeWindow(winPtr->display, winPtr->window, 0,\n\t    wmPtr->menuHeight, (unsigned) wrapperPtr->changes.width,\n\t    (unsigned) (wrapperPtr->changes.height - wmPtr->menuHeight));\n    Tk_DeleteErrorHandler(handler);\n    if ((wmPtr->menubar != NULL)\n\t    && ((Tk_Width(wmPtr->menubar) != wrapperPtr->changes.width)\n\t    || (Tk_Height(wmPtr->menubar) != wmPtr->menuHeight))) {\n\tTk_MoveResizeWindow(wmPtr->menubar, 0, 0, wrapperPtr->changes.width,\n\t\twmPtr->menuHeight);\n    }\n\n    /*\n     * Update the coordinates in the toplevel (they should refer to the\n     * position in root window coordinates, not the coordinates of the wrapper\n     * window). Then synthesize a ConfigureNotify event to tell the\n     * application about the change.\n     */\n\n    winPtr->changes.x = wrapperPtr->changes.x;\n    winPtr->changes.y = wrapperPtr->changes.y + wmPtr->menuHeight;\n    winPtr->changes.width = wrapperPtr->changes.width;\n    winPtr->changes.height = wrapperPtr->changes.height - wmPtr->menuHeight;\n    TkDoConfigureNotify(winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReparentEvent --\n *\n *\tThis function is called to handle ReparentNotify events on wrapper\n *\twindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets updated in the WmInfo structure for the window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nReparentEvent(\n    WmInfo *wmPtr,\t\t/* Information about toplevel window. */\n    XReparentEvent *reparentEventPtr)\n\t\t\t\t/* Event that just occurred for\n\t\t\t\t * wmPtr->wrapperPtr. */\n{\n    TkWindow *wrapperPtr = wmPtr->wrapperPtr;\n    Window vRoot, ancestor, *children, dummy2, *virtualRootPtr, **vrPtrPtr;\n    Atom actualType;\n    int actualFormat;\n    unsigned long numItems, bytesAfter;\n    unsigned dummy;\n    Tk_ErrorHandler handler;\n    TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;\n    Atom WM_ROOT = Tk_InternAtom((Tk_Window) wrapperPtr, \"__WM_ROOT\");\n    Atom SWM_ROOT = Tk_InternAtom((Tk_Window) wrapperPtr, \"__SWM_ROOT\");\n\n    /*\n     * Identify the root window for wrapperPtr. This is tricky because of\n     * virtual root window managers like tvtwm. If the window has a property\n     * named __SWM_ROOT or __WM_ROOT then this property gives the id for a\n     * virtual root window that should be used instead of the root window of\n     * the screen.\n     */\n\n    vRoot = RootWindow(wrapperPtr->display, wrapperPtr->screenNum);\n    wmPtr->vRoot = None;\n    handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL);\n    vrPtrPtr = &virtualRootPtr;\t\t/* Silence GCC warning */\n    if ((GetWindowProperty(wrapperPtr, WM_ROOT, 1, XA_WINDOW,\n\t    &actualType, &actualFormat, &numItems, &bytesAfter, vrPtrPtr)\n\t    && (actualType == XA_WINDOW))\n\t|| (GetWindowProperty(wrapperPtr, SWM_ROOT, 1, XA_WINDOW,\n\t    &actualType, &actualFormat, &numItems, &bytesAfter, vrPtrPtr)\n\t    && (actualType == XA_WINDOW))) {\n\tif ((actualFormat == 32) && (numItems == 1)) {\n\t    vRoot = wmPtr->vRoot = *virtualRootPtr;\n\t} else if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t    printf(\"%s format %d numItems %ld\\n\",\n\t\t    \"ReparentEvent got bogus VROOT property:\", actualFormat,\n\t\t    numItems);\n\t}\n\tXFree(virtualRootPtr);\n    }\n    Tk_DeleteErrorHandler(handler);\n\n    if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"ReparentEvent: %s (%p) reparented to 0x%x, vRoot = 0x%x\\n\",\n\t\twmPtr->winPtr->pathName, wmPtr->winPtr,\n\t\t(unsigned) reparentEventPtr->parent, (unsigned) vRoot);\n    }\n\n    /*\n     * Fetch correct geometry information for the new virtual root.\n     */\n\n    UpdateVRootGeometry(wmPtr);\n\n    /*\n     * If the window's new parent is the root window, then mark it as no\n     * longer reparented.\n     */\n\n    if (reparentEventPtr->parent == vRoot) {\n    noReparent:\n\twmPtr->reparent = None;\n\twmPtr->parentWidth = wrapperPtr->changes.width;\n\twmPtr->parentHeight = wrapperPtr->changes.height;\n\twmPtr->xInParent = wmPtr->yInParent = 0;\n\twrapperPtr->changes.x = reparentEventPtr->x;\n\twrapperPtr->changes.y = reparentEventPtr->y;\n\twmPtr->winPtr->changes.x = reparentEventPtr->x;\n\twmPtr->winPtr->changes.y = reparentEventPtr->y + wmPtr->menuHeight;\n\treturn;\n    }\n\n    /*\n     * Search up the window hierarchy to find the ancestor of this window that\n     * is just below the (virtual) root. This is tricky because it's possible\n     * that things have changed since the event was generated so that the\n     * ancestry indicated by the event no longer exists. If this happens then\n     * an error will occur and we just discard the event (there will be a more\n     * up-to-date ReparentNotify event coming later).\n     */\n\n    handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL);\n    wmPtr->reparent = reparentEventPtr->parent;\n    while (1) {\n\tif (XQueryTree(wrapperPtr->display, wmPtr->reparent, &dummy2,\n\t\t&ancestor, &children, &dummy) == 0) {\n\t    Tk_DeleteErrorHandler(handler);\n\t    goto noReparent;\n\t}\n\tXFree(children);\n\tif ((ancestor == vRoot) ||\n\t\t(ancestor == RootWindow(wrapperPtr->display,\n\t\twrapperPtr->screenNum))) {\n\t    break;\n\t}\n\twmPtr->reparent = ancestor;\n    }\n    Tk_DeleteErrorHandler(handler);\n\n    if (!ComputeReparentGeometry(wmPtr)) {\n\tgoto noReparent;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ComputeReparentGeometry --\n *\n *\tThis function is invoked to recompute geometry information related to\n *\ta reparented top-level window, such as the position and total size of\n *\tthe parent and the position within it of the top-level window.\n *\n * Results:\n *\tThe return value is 1 if everything completed successfully and 0 if an\n *\terror occurred while querying information about winPtr's parents. In\n *\tthis case winPtr is marked as no longer being reparented.\n *\n * Side effects:\n *\tGeometry information in wmPtr, wmPtr->winPtr, and wmPtr->wrapperPtr\n *\tgets updated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nComputeReparentGeometry(\n    WmInfo *wmPtr)\t\t/* Information about toplevel window whose\n\t\t\t\t * reparent info is to be recomputed. */\n{\n    TkWindow *wrapperPtr = wmPtr->wrapperPtr;\n    int width, height, bd;\n    unsigned dummy;\n    int xOffset, yOffset, x, y;\n    Window dummy2;\n    Status status;\n    Tk_ErrorHandler handler;\n    TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;\n\n    handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL);\n    (void) XTranslateCoordinates(wrapperPtr->display, wrapperPtr->window,\n\t    wmPtr->reparent, 0, 0, &xOffset, &yOffset, &dummy2);\n    status = XGetGeometry(wrapperPtr->display, wmPtr->reparent,\n\t    &dummy2, &x, &y, (unsigned *) &width, (unsigned *) &height,\n\t    (unsigned *) &bd, &dummy);\n    Tk_DeleteErrorHandler(handler);\n    if (status == 0) {\n\t/*\n\t * It appears that the reparented parent went away and no-one told us.\n\t * Reset the window to indicate that it's not reparented.\n\t */\n\n\twmPtr->reparent = None;\n\twmPtr->xInParent = wmPtr->yInParent = 0;\n\treturn false;\n    }\n    wmPtr->xInParent = xOffset + bd;\n    wmPtr->yInParent = yOffset + bd;\n    wmPtr->parentWidth = width + 2*bd;\n    wmPtr->parentHeight = height + 2*bd;\n\n    /*\n     * Some tricky issues in updating wmPtr->x and wmPtr->y:\n     *\n     * 1. Don't update them if the event occurred because of something we did\n     * (i.e. WM_SYNC_PENDING and WM_MOVE_PENDING are both set). This is\n     * because window managers treat coords differently than Tk, and no two\n     * window managers are alike. If the window manager moved the window\n     * because we told it to, remember the coordinates we told it, not the\n     * ones it actually moved it to. This allows us to move the window back to\n     * the same coordinates later and get the same result. Without this check,\n     * windows can \"walk\" across the screen under some conditions.\n     *\n     * 2. Don't update wmPtr->x and wmPtr->y unless wrapperPtr->changes.x or\n     * wrapperPtr->changes.y has changed (otherwise a size change can spoof us\n     * into thinking that the position changed too and defeat the intent of\n     * (1) above.\n     *\n     * (As of 9/96 the above 2 comments appear to be stale. They're being left\n     * in place as a reminder of what was once true (and perhaps should still\n     * be true?)).\n     *\n     * 3. Ignore size changes coming from the window system if we're about to\n     * change the size ourselves but haven't seen the event for it yet: our\n     * size change is supposed to take priority.\n     */\n\n    if (!(wmPtr->flags & WM_MOVE_PENDING)\n\t    && ((wrapperPtr->changes.x != (x + wmPtr->xInParent))\n\t    || (wrapperPtr->changes.y != (y + wmPtr->yInParent)))) {\n\twmPtr->x = x;\n\tif (wmPtr->flags & WM_NEGATIVE_X) {\n\t    wmPtr->x = wmPtr->vRootWidth - (wmPtr->x + wmPtr->parentWidth);\n\t}\n\twmPtr->y = y;\n\tif (wmPtr->flags & WM_NEGATIVE_Y) {\n\t    wmPtr->y = wmPtr->vRootHeight - (wmPtr->y + wmPtr->parentHeight);\n\t}\n    }\n\n    wrapperPtr->changes.x = x + wmPtr->xInParent;\n    wrapperPtr->changes.y = y + wmPtr->yInParent;\n    if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"wrapperPtr %p coords %d,%d\\n\",\n\t\twrapperPtr, wrapperPtr->changes.x, wrapperPtr->changes.y);\n\tprintf(\"     wmPtr %p coords %d,%d, offsets %d %d\\n\",\n\t\twmPtr, wmPtr->x, wmPtr->y, wmPtr->xInParent, wmPtr->yInParent);\n    }\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PropertyEvent --\n *\n *\tHandle PropertyNotify events on wrapper windows. The following\n *\tproperties are of interest:\n *\n *\t_NET_WM_STATE:\n *\t\tUsed to keep wmPtr->attributes up to date.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nPropertyEvent(\n    WmInfo *wmPtr,\t\t/* Information about toplevel window. */\n    XPropertyEvent *eventPtr)\t/* PropertyNotify event structure */\n{\n    TkWindow *wrapperPtr = wmPtr->wrapperPtr;\n    Atom _NET_WM_STATE =\n\t    Tk_InternAtom((Tk_Window) wmPtr->winPtr, \"_NET_WM_STATE\");\n\n    if (eventPtr->atom == _NET_WM_STATE) {\n\tAtom actualType;\n\tint actualFormat;\n\tunsigned long numItems, bytesAfter;\n\tunsigned char *propertyValue = 0;\n\tlong maxLength = 1024;\n\n\tif (GetWindowProperty(wrapperPtr, _NET_WM_STATE, maxLength, XA_ATOM,\n\t\t&actualType, &actualFormat, &numItems, &bytesAfter,\n\t\t&propertyValue)) {\n\t    CheckNetWmState(wmPtr, (Atom *) propertyValue, (int) numItems);\n\t    XFree(propertyValue);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WrapperEventProc --\n *\n *\tThis function is invoked by the event loop when a wrapper window is\n *\trestructured.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTk's internal data structures for the window get modified to reflect\n *\tthe structural change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const unsigned WrapperEventMask =\n\t(StructureNotifyMask | PropertyChangeMask);\n\nstatic void\nWrapperEventProc(\n    void *clientData,\t/* Information about toplevel window. */\n    XEvent *eventPtr)\t\t/* Event that just happened. */\n{\n    WmInfo *wmPtr = (WmInfo *)clientData;\n    XEvent mapEvent;\n    TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;\n\n    wmPtr->flags |= WM_VROOT_OFFSET_STALE;\n    if (eventPtr->type == DestroyNotify) {\n\tTk_ErrorHandler handler;\n\n\tif (!(wmPtr->wrapperPtr->flags & TK_ALREADY_DEAD)) {\n\t    /*\n\t     * A top-level window was deleted externally (e.g., by the window\n\t     * manager). This is probably not a good thing, but cleanup as\n\t     * best we can. The error handler is needed because\n\t     * Tk_DestroyWindow will try to destroy the window, but of course\n\t     * it's already gone.\n\t     */\n\n\t    handler = Tk_CreateErrorHandler(wmPtr->winPtr->display, -1, -1, -1,\n\t\t    NULL, NULL);\n\t    Tk_DestroyWindow((Tk_Window) wmPtr->winPtr);\n\t    Tk_DeleteErrorHandler(handler);\n\t}\n\tif (dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t    printf(\"TopLevelEventProc: %s deleted\\n\", wmPtr->winPtr->pathName);\n\t}\n    } else if (eventPtr->type == ConfigureNotify) {\n\t/*\n\t * Ignore the event if the window has never been mapped yet. Such an\n\t * event occurs only in weird cases like changing the internal border\n\t * width of a top-level window, which results in a synthetic Configure\n\t * event. These events are not relevant to us, and if we process them\n\t * confusion may result (e.g. we may conclude erroneously that the\n\t * user repositioned or resized the window).\n\t */\n\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    ConfigureEvent(wmPtr, &eventPtr->xconfigure);\n\t}\n    } else if (eventPtr->type == MapNotify) {\n\twmPtr->wrapperPtr->flags |= TK_MAPPED;\n\twmPtr->winPtr->flags |= TK_MAPPED;\n\tXMapWindow(wmPtr->winPtr->display, wmPtr->winPtr->window);\n\tgoto doMapEvent;\n    } else if (eventPtr->type == UnmapNotify) {\n\twmPtr->wrapperPtr->flags &= ~TK_MAPPED;\n\twmPtr->winPtr->flags &= ~TK_MAPPED;\n\tXUnmapWindow(wmPtr->winPtr->display, wmPtr->winPtr->window);\n\tgoto doMapEvent;\n    } else if (eventPtr->type == ReparentNotify) {\n\tReparentEvent(wmPtr, &eventPtr->xreparent);\n    } else if (eventPtr->type == PropertyNotify) {\n\tPropertyEvent(wmPtr, &eventPtr->xproperty);\n    }\n    return;\n\n  doMapEvent:\n    mapEvent = *eventPtr;\n    mapEvent.xmap.event = wmPtr->winPtr->window;\n    mapEvent.xmap.window = wmPtr->winPtr->window;\n    Tk_HandleEvent(&mapEvent);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelReqProc --\n *\n *\tThis function is invoked by the geometry manager whenever the\n *\trequested size for a top-level window is changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArrange for the window to be resized to satisfy the request (this\n *\thappens as a when-idle action).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTopLevelReqProc(\n    TCL_UNUSED(void *),\t\t/* Not used. */\n    Tk_Window tkwin)\t\t/* Information about window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if ((wmPtr->width >= 0) && (wmPtr->height >= 0)) {\n\t/*\n\t * Explicit dimensions have been set for this window, so we should\n\t * ignore the geometry request. It's actually important to ignore the\n\t * geometry request because, due to quirks in window managers,\n\t * invoking UpdateGeometryInfo may cause the window to move. For\n\t * example, if \"wm geometry -10-20\" was invoked, the window may be\n\t * positioned incorrectly the first time it appears (because we didn't\n\t * know the proper width of the window manager borders); if we invoke\n\t * UpdateGeometryInfo again, the window will be positioned correctly,\n\t * which may cause it to jump on the screen.\n\t */\n\n\treturn;\n    }\n\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n\n    /*\n     * If the window isn't being positioned by its upper left corner then we\n     * have to move it as well.\n     */\n\n    if (wmPtr->flags & (WM_NEGATIVE_X | WM_NEGATIVE_Y)) {\n\twmPtr->flags |= WM_MOVE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateGeometryInfo --\n *\n *\tThis function is invoked when a top-level window is first mapped, and\n *\talso as a when-idle function, to bring the geometry and/or position of\n *\ta top-level window back into line with what has been requested by the\n *\tuser and/or widgets. This function doesn't return until the window\n *\tmanager has responded to the geometry change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe size and location of both the toplevel window and its wrapper may\n *\tchange, unless the WM prevents that from happening.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateGeometryInfo(\n    void *clientData)\t/* Pointer to the window's record. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y, width, height, min, max;\n    unsigned long serial;\n\n    wmPtr->flags &= ~WM_UPDATE_PENDING;\n\n    /*\n     * Compute the new size for the top-level window. See the user\n     * documentation for details on this, but the size requested depends on\n     * (a) the size requested internally by the window's widgets, (b) the size\n     * requested by the user in a \"wm geometry\" command or via wm-based\n     * interactive resizing (if any), (c) whether or not the window is\n     * gridded, and (d) the current min or max size for the toplevel. Don't\n     * permit sizes <= 0 because this upsets the X server.\n     */\n\n    if (wmPtr->width == -1) {\n\twidth = winPtr->reqWidth;\n    } else if (wmPtr->gridWin != NULL) {\n\twidth = winPtr->reqWidth\n\t\t+ (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc;\n    } else {\n\twidth = wmPtr->width;\n    }\n    if (width <= 0) {\n\twidth = 1;\n    }\n\n    /*\n     * Account for window max/min width\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqWidth\n\t\t+ (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\tif (wmPtr->maxWidth > 0) {\n\t    max = winPtr->reqWidth\n\t\t+ (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minWidth;\n\tmax = wmPtr->maxWidth;\n    }\n    if (width < min) {\n\twidth = min;\n    } else if ((max > 0) && (width > max)) {\n\twidth = max;\n    }\n\n    if (wmPtr->height == -1) {\n\theight = winPtr->reqHeight;\n    } else if (wmPtr->gridWin != NULL) {\n\theight = winPtr->reqHeight\n\t\t+ (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc;\n    } else {\n\theight = wmPtr->height;\n    }\n    if (height <= 0) {\n\theight = 1;\n    }\n\n    /*\n     * Account for window max/min height\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqHeight\n\t\t+ (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\tif (wmPtr->maxHeight > 0) {\n\t    max = winPtr->reqHeight\n\t\t+ (wmPtr->maxHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minHeight;\n\tmax = wmPtr->maxHeight;\n    }\n    if (height < min) {\n\theight = min;\n    } else if ((max > 0) && (height > max)) {\n\theight = max;\n    }\n\n    /*\n     * Compute the new position for the upper-left pixel of the window's\n     * decorative frame. This is tricky, because we need to include the border\n     * widths supplied by a reparented parent in this calculation, but can't\n     * use the parent's current overall size since that may change as a result\n     * of this code.\n     */\n\n    if (wmPtr->flags & WM_NEGATIVE_X) {\n\tx = wmPtr->vRootWidth - wmPtr->x\n\t\t- (width + (wmPtr->parentWidth - winPtr->changes.width));\n    } else {\n\tx = wmPtr->x;\n    }\n    if (wmPtr->flags & WM_NEGATIVE_Y) {\n\ty = wmPtr->vRootHeight - wmPtr->y\n\t\t- (height + (wmPtr->parentHeight - winPtr->changes.height));\n    } else {\n\ty = wmPtr->y;\n    }\n\n    /*\n     * If the window's size is going to change and the window is supposed to\n     * not be resizable by the user, then we have to update the size hints.\n     * There may also be a size-hint-update request pending from somewhere\n     * else, too.\n     */\n\n    if (((width != winPtr->changes.width)\n\t    || (height != winPtr->changes.height))\n\t    && (wmPtr->gridWin == NULL)\n\t    && !(wmPtr->sizeHintsFlags & (PMinSize|PMaxSize))) {\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    }\n    if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) {\n\tUpdateSizeHints(winPtr, width, height);\n    }\n\n    /*\n     * Reconfigure the wrapper if it isn't already configured correctly. A few\n     * tricky points:\n     *\n     * 1. If the window is embedded and the container is also in this process,\n     *    don't actually reconfigure the window; just pass the desired size on\n     *    to the container. Also, zero out any position information, since\n     *    embedded windows are not allowed to move.\n     * 2. Sometimes the window manager will give us a different size than we\n     *    asked for (e.g. mwm has a minimum size for windows), so base the\n     *    size check on what we *asked for* last time, not what we got.\n     * 3. Can't just reconfigure always, because we may not get a\n     *    ConfigureNotify event back if nothing changed, so\n     *    WaitForConfigureNotify will hang a long time.\n     * 4. Don't move window unless a new position has been requested for it.\n     *\t  This is because of \"features\" in some window managers (e.g. twm, as\n     *\t  of 4/24/91) where they don't interpret coordinates according to\n     *\t  ICCCM. Moving a window to its current location may cause it to shift\n     *\t  position on the screen.\n     */\n\n    if ((winPtr->flags & (TK_EMBEDDED|TK_BOTH_HALVES))\n\t    == (TK_EMBEDDED|TK_BOTH_HALVES)) {\n\tTk_Window childPtr = Tk_GetOtherWindow((Tk_Window)winPtr);\n\n\t/*\n\t * This window is embedded and the container is also in this process,\n\t * so we don't need to do anything special about the geometry, except\n\t * to make sure that the desired size is known by the container. Also,\n\t * zero out any position information, since embedded windows are not\n\t * allowed to move.\n\t */\n\n\twmPtr->x = wmPtr->y = 0;\n\twmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);\n\theight += wmPtr->menuHeight;\n\tif (childPtr != NULL) {\n\t    Tk_GeometryRequest(childPtr, width, height);\n\t}\n\treturn;\n    }\n    serial = NextRequest(winPtr->display);\n    height += wmPtr->menuHeight;\n    if (wmPtr->flags & WM_MOVE_PENDING) {\n\tif ((x + wmPtr->xInParent == winPtr->changes.x) &&\n\t\t(y+wmPtr->yInParent+wmPtr->menuHeight == winPtr->changes.y)\n\t\t&& (width == wmPtr->wrapperPtr->changes.width)\n\t\t&& (height == wmPtr->wrapperPtr->changes.height)) {\n\t    /*\n\t     * The window already has the correct geometry, so don't bother to\n\t     * configure it; the X server appears to ignore these requests, so\n\t     * we won't get back a ConfigureNotify and the\n\t     * WaitForConfigureNotify call below will hang for a while.\n\t     */\n\n\t    wmPtr->flags &= ~WM_MOVE_PENDING;\n\t    return;\n\t}\n\twmPtr->configWidth = width;\n\twmPtr->configHeight = height;\n\tif (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t    printf(\"UpdateGeometryInfo moving to %d %d, resizing to %dx%d,\\n\",\n\t\t    x, y, width, height);\n\t}\n\tXMoveResizeWindow(winPtr->display, wmPtr->wrapperPtr->window, x, y,\n\t\t(unsigned) width, (unsigned) height);\n    } else if ((width != wmPtr->configWidth)\n\t    || (height != wmPtr->configHeight)) {\n\tif ((width == wmPtr->wrapperPtr->changes.width)\n\t\t&& (height == wmPtr->wrapperPtr->changes.height)) {\n\t    /*\n\t     * The window is already just the size we want, so don't bother to\n\t     * configure it; the X server appears to ignore these requests, so\n\t     * we won't get back a ConfigureNotify and the\n\t     * WaitForConfigureNotify call below will hang for a while.\n\t     */\n\n\t    return;\n\t}\n\twmPtr->configWidth = width;\n\twmPtr->configHeight = height;\n\tif (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t    printf(\"UpdateGeometryInfo resizing %p to %d x %d\\n\",\n\t\t    (void *) wmPtr->wrapperPtr->window, width, height);\n\t}\n\tXResizeWindow(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t(unsigned) width, (unsigned) height);\n    } else if ((wmPtr->menubar != NULL)\n\t    && ((Tk_Width(wmPtr->menubar) != wmPtr->wrapperPtr->changes.width)\n\t    || (Tk_Height(wmPtr->menubar) != wmPtr->menuHeight))) {\n\t/*\n\t * It is possible that the window's overall size has not changed but\n\t * the menu size has.\n\t */\n\n\tTk_MoveResizeWindow(wmPtr->menubar, 0, 0,\n\t\twmPtr->wrapperPtr->changes.width, wmPtr->menuHeight);\n\tXResizeWindow(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t(unsigned) width, (unsigned) height);\n    } else {\n\treturn;\n    }\n\n    /*\n     * Wait for the configure operation to complete. Don't need to do this,\n     * however, if the window is about to be mapped: it will be taken care of\n     * elsewhere.\n     */\n\n    if (!(wmPtr->flags & WM_ABOUT_TO_MAP)) {\n\tWaitForConfigureNotify(winPtr, serial);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * UpdateSizeHints --\n *\n *\tThis function is called to update the window manager's size hints\n *\tinformation from the information in a WmInfo structure.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties get changed for winPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nUpdateSizeHints(\n    TkWindow *winPtr,\n    int newWidth,\n    int newHeight)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    XSizeHints *hintsPtr;\n    int maxWidth, maxHeight;\n\n    wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS;\n\n    hintsPtr = XAllocSizeHints();\n    if (hintsPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Compute the pixel-based sizes for the various fields in the size hints\n     * structure, based on the grid-based sizes in our structure.\n     */\n\n    GetMaxSize(wmPtr, &maxWidth, &maxHeight);\n    if (wmPtr->gridWin != NULL) {\n\thintsPtr->base_width = winPtr->reqWidth\n\t\t- (wmPtr->reqGridWidth * wmPtr->widthInc);\n\tif (hintsPtr->base_width < 0) {\n\t    hintsPtr->base_width = 0;\n\t}\n\thintsPtr->base_height = winPtr->reqHeight + wmPtr->menuHeight\n\t\t- (wmPtr->reqGridHeight * wmPtr->heightInc);\n\tif (hintsPtr->base_height < 0) {\n\t    hintsPtr->base_height = 0;\n\t}\n\thintsPtr->min_width = hintsPtr->base_width\n\t\t+ (wmPtr->minWidth * wmPtr->widthInc);\n\thintsPtr->min_height = hintsPtr->base_height\n\t\t+ (wmPtr->minHeight * wmPtr->heightInc);\n\thintsPtr->max_width = hintsPtr->base_width\n\t\t+ (maxWidth * wmPtr->widthInc);\n\thintsPtr->max_height = hintsPtr->base_height\n\t\t+ (maxHeight * wmPtr->heightInc);\n    } else {\n\thintsPtr->min_width = wmPtr->minWidth;\n\thintsPtr->min_height = wmPtr->minHeight;\n\thintsPtr->max_width = maxWidth;\n\thintsPtr->max_height = maxHeight;\n\thintsPtr->base_width = 0;\n\thintsPtr->base_height = 0;\n    }\n    hintsPtr->width_inc = wmPtr->widthInc;\n    hintsPtr->height_inc = wmPtr->heightInc;\n    hintsPtr->min_aspect.x = wmPtr->minAspect.x;\n    hintsPtr->min_aspect.y = wmPtr->minAspect.y;\n    hintsPtr->max_aspect.x = wmPtr->maxAspect.x;\n    hintsPtr->max_aspect.y = wmPtr->maxAspect.y;\n    hintsPtr->win_gravity = wmPtr->gravity;\n    hintsPtr->flags = wmPtr->sizeHintsFlags | PMinSize | PResizeInc;\n\n    /*\n     * If the window isn't supposed to be resizable, then set the minimum and\n     * maximum dimensions to be the same.\n     */\n\n    if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {\n\thintsPtr->max_width = hintsPtr->min_width = newWidth;\n\thintsPtr->flags |= PMaxSize;\n    }\n    if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {\n\thintsPtr->max_height = hintsPtr->min_height =\n\t\tnewHeight + wmPtr->menuHeight;\n\thintsPtr->flags |= PMaxSize;\n    }\n\n    XSetWMNormalHints(winPtr->display, wmPtr->wrapperPtr->window, hintsPtr);\n\n    XFree(hintsPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * UpdateTitle --\n *\n *\tThis function is called to update the window title and icon name. It\n *\tsets the ICCCM-defined properties WM_NAME and WM_ICON_NAME for older\n *\twindow managers, and the freedesktop.org-defined _NET_WM_NAME and\n *\t_NET_WM_ICON_NAME properties for newer ones. The ICCCM properties are\n *\tstored in the system encoding, the newer properties are stored in\n *\tUTF-8.\n *\n *\tNOTE: the ICCCM specifies that WM_NAME and WM_ICON_NAME are stored in\n *\tISO-Latin-1. Tk has historically used the default system encoding\n *\t(since 8.1). It's not clear whether this is correct or not.\n *\n * Side effects:\n *\tProperties get changed for winPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nUpdateTitle(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Atom XA_UTF8_STRING = Tk_InternAtom((Tk_Window) winPtr, \"UTF8_STRING\");\n    const char *string;\n    Tcl_DString ds;\n\n    /*\n     * Set window title:\n     */\n\n    string = (wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid;\n    (void)Tcl_UtfToExternalDString(NULL, string, TCL_INDEX_NONE, &ds);\n    XStoreName(winPtr->display, wmPtr->wrapperPtr->window,\n\t    Tcl_DStringValue(&ds));\n    Tcl_DStringFree(&ds);\n\n    SetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_NAME\", XA_UTF8_STRING, 8,\n\t    string, strlen(string));\n\n    /*\n     * Set icon name:\n     */\n\n    if (wmPtr->iconName != NULL) {\n\t(void)Tcl_UtfToExternalDString(NULL, wmPtr->iconName, TCL_INDEX_NONE, &ds);\n\tXSetIconName(winPtr->display, wmPtr->wrapperPtr->window,\n\t\tTcl_DStringValue(&ds));\n\tTcl_DStringFree(&ds);\n\n\tSetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_ICON_NAME\",\n\t\tXA_UTF8_STRING, 8, wmPtr->iconName, strlen(wmPtr->iconName));\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * UpdatePhotoIcon --\n *\n *\tThis function is called to update the window photo icon. It sets the\n *\tEWMH-defined properties _NET_WM_ICON.\n *\n * Side effects:\n *\tProperties get changed for winPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nUpdatePhotoIcon(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    unsigned char *data = wmPtr->iconDataPtr;\n    int size = wmPtr->iconDataSize;\n\n    if (data == NULL) {\n\tdata = winPtr->dispPtr->iconDataPtr;\n\tsize = winPtr->dispPtr->iconDataSize;\n    }\n    if (data != NULL) {\n\tSetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_ICON\", XA_CARDINAL, 32,\n\t\tdata, size);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetNetWmState --\n *\n *\tSets the specified state property by sending a _NET_WM_STATE\n *\tClientMessage to the root window.\n *\n * Preconditions:\n *\tWrapper window must be created.\n *\n * See also:\n *\tUpdateNetWmState; EWMH spec, section _NET_WM_STATE.\n *\n *----------------------------------------------------------------------\n */\n\n#define _NET_WM_STATE_REMOVE    0l\n#define _NET_WM_STATE_ADD       1l\n#define _NET_WM_STATE_TOGGLE    2l\n\nstatic void\nSetNetWmState(\n    TkWindow *winPtr,\n    const char *atomName,\n    int on)\n{\n    Tk_Window tkwin = (Tk_Window) winPtr;\n    Atom messageType = Tk_InternAtom(tkwin, \"_NET_WM_STATE\");\n    Atom action = on ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;\n    Atom property = Tk_InternAtom(tkwin, atomName);\n    XEvent e;\n\n    if (!winPtr->wmInfoPtr->wrapperPtr) {\n\treturn;\n    }\n\n    e.xany.type = ClientMessage;\n    e.xany.window = winPtr->wmInfoPtr->wrapperPtr->window;\n    e.xclient.message_type = messageType;\n    e.xclient.format = 32;\n    e.xclient.data.l[0] = action;\n    e.xclient.data.l[1] = property;\n    e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l;\n\n    XSendEvent(winPtr->display,\n\tRootWindow(winPtr->display, winPtr->screenNum), 0,\n\tSubstructureNotifyMask|SubstructureRedirectMask, &e);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CheckNetWmState --\n *\n *\tUpdates the window attributes whenever the _NET_WM_STATE property\n *\tchanges.\n *\n * Notes:\n *\n *\tTk uses a single -zoomed state, while the EWMH spec supports separate\n *\tvertical and horizontal maximization. We consider the window to be\n *\t\"zoomed\" if _NET_WM_STATE_MAXIMIZED_VERT and\n *\t_NET_WM_STATE_MAXIMIZED_HORZ are both set.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCheckNetWmState(\n    WmInfo *wmPtr,\n    Atom *atoms,\n    int numAtoms)\n{\n    Tk_Window tkwin = (Tk_Window) wmPtr->wrapperPtr;\n    int i;\n    Atom _NET_WM_STATE_ABOVE\n\t    = Tk_InternAtom(tkwin, \"_NET_WM_STATE_ABOVE\"),\n\t_NET_WM_STATE_MAXIMIZED_VERT\n\t    = Tk_InternAtom(tkwin, \"_NET_WM_STATE_MAXIMIZED_VERT\"),\n\t_NET_WM_STATE_MAXIMIZED_HORZ\n\t    = Tk_InternAtom(tkwin, \"_NET_WM_STATE_MAXIMIZED_HORZ\"),\n\t_NET_WM_STATE_FULLSCREEN\n\t    = Tk_InternAtom(tkwin, \"_NET_WM_STATE_FULLSCREEN\");\n\n    wmPtr->attributes.topmost = 0;\n    wmPtr->attributes.zoomed = 0;\n    wmPtr->attributes.fullscreen = 0;\n    for (i = 0; i < numAtoms; ++i) {\n\tif (atoms[i] == _NET_WM_STATE_ABOVE) {\n\t    wmPtr->attributes.topmost = 1;\n\t} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {\n\t    wmPtr->attributes.zoomed |= 1;\n\t} else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {\n\t    wmPtr->attributes.zoomed |= 2;\n\t} else if (atoms[i] == _NET_WM_STATE_FULLSCREEN) {\n\t    wmPtr->attributes.fullscreen = 1;\n\t}\n    }\n\n    wmPtr->attributes.zoomed = (wmPtr->attributes.zoomed == 3);\n\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateNetWmState --\n *\n *\tSets the _NET_WM_STATE property to match the requested attribute state\n *\tjust prior to mapping a withdrawn window.\n *\n *----------------------------------------------------------------------\n */\n\n#define NET_WM_STATE_MAX_ATOMS 4\n\nstatic void\nUpdateNetWmState(\n    WmInfo *wmPtr)\n{\n    Tk_Window tkwin = (Tk_Window) wmPtr->wrapperPtr;\n    Atom atoms[NET_WM_STATE_MAX_ATOMS];\n    long numAtoms = 0;\n\n    if (wmPtr->reqState.topmost) {\n\tatoms[numAtoms++] = Tk_InternAtom(tkwin,\"_NET_WM_STATE_ABOVE\");\n    }\n    if (wmPtr->reqState.zoomed) {\n\tatoms[numAtoms++] = Tk_InternAtom(tkwin,\"_NET_WM_STATE_MAXIMIZED_VERT\");\n\tatoms[numAtoms++] = Tk_InternAtom(tkwin,\"_NET_WM_STATE_MAXIMIZED_HORZ\");\n    }\n    if (wmPtr->reqState.fullscreen) {\n\tatoms[numAtoms++] = Tk_InternAtom(tkwin, \"_NET_WM_STATE_FULLSCREEN\");\n    }\n\n    SetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_STATE\", XA_ATOM, 32, atoms,\n\t    numAtoms);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WaitForConfigureNotify --\n *\n *\tThis function is invoked in order to synchronize with the window\n *\tmanager. It waits for a ConfigureNotify event to arrive, signalling\n *\tthat the window manager has seen an attempt on our part to move or\n *\tresize a top-level window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDelays the execution of the process until a ConfigureNotify event\n *\tarrives with serial number at least as great as serial. This is useful\n *\tfor two reasons:\n *\n *\t1. It's important to distinguish ConfigureNotify events that are\n *\t   coming in response to a request we've made from those generated\n *\t   spontaneously by the user. The reason for this is that if the user\n *\t   resizes the window we take that as an order to ignore geometry\n *\t   requests coming from inside the window hierarchy. If we\n *\t   accidentally interpret a response to our request as a user-\n *\t   initiated action, the window will stop responding to new geometry\n *\t   requests. To make this distinction, (a) this function sets a flag\n *\t   for TopLevelEventProc to indicate that we're waiting to sync with\n *\t   the wm, and (b) all changes to the size of a top-level window are\n *\t   followed by calls to this function.\n *\t2. Races and confusion can come about if there are multiple operations\n *\t   outstanding at a time (e.g. two different resizes of the top-level\n *\t   window: it's hard to tell which of the ConfigureNotify events\n *\t   coming back is for which request).\n *\tWhile waiting, some events covered by StructureNotifyMask are\n *\tprocessed (ConfigureNotify, MapNotify, and UnmapNotify) and all others\n *\tare deferred.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nWaitForConfigureNotify(\n    TkWindow *winPtr,\t\t/* Top-level window for which we want to see a\n\t\t\t\t * ConfigureNotify. */\n    unsigned long serial)\t/* Serial number of resize request. Want to be\n\t\t\t\t * sure wm has seen this. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    XEvent event;\n    int diff, code;\n    int gotConfig = 0;\n\n    /*\n     * One more tricky detail about this function. In some cases the window\n     * manager will decide to ignore a configure request (e.g. because it\n     * thinks the window is already in the right place). To avoid hanging in\n     * this situation, only wait for a few seconds, then give up.\n     */\n\n    while (!gotConfig) {\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tcode = WaitForEvent(winPtr->display, wmPtr, ConfigureNotify, &event);\n\twmPtr->flags &= ~WM_SYNC_PENDING;\n\tif (code != TCL_OK) {\n\t    if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t\tprintf(\"WaitForConfigureNotify giving up on %s\\n\",\n\t\t\twinPtr->pathName);\n\t    }\n\t    break;\n\t}\n\tdiff = event.xconfigure.serial - serial;\n\tif (diff >= 0) {\n\t    gotConfig = 1;\n\t}\n    }\n    wmPtr->flags &= ~WM_MOVE_PENDING;\n    if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"WaitForConfigureNotify finished with %s, serial %ld\\n\",\n\t\twinPtr->pathName, serial);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WaitForEvent --\n *\n *\tThis function is used by WaitForConfigureNotify and WaitForMapNotify\n *\tto wait for an event of a certain type to arrive.\n *\n * Results:\n *\tUnder normal conditions, TCL_OK is returned and an event for display\n *\tand window that matches \"mask\" is stored in *eventPtr. This event has\n *\talready been processed by Tk before this function returns. If a long\n *\ttime goes by with no event of the right type arriving, or if an error\n *\toccurs while waiting for the event to arrive, then TCL_ERROR is\n *\treturned.\n *\n * Side effects:\n *\tWhile waiting for the desired event to occur, Configurenotify,\n *\tMapNotify, and UnmapNotify events for window are processed, as are all\n *\tReparentNotify events.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWaitForEvent(\n    Display *display,\t\t/* Display event is coming from. */\n    WmInfo *wmInfoPtr,\t\t/* Window for which event is desired. */\n    int type,\t\t\t/* Type of event that is wanted. */\n    XEvent *eventPtr)\t\t/* Place to store event. */\n{\n    WaitRestrictInfo info;\n    Tk_RestrictProc *prevProc;\n    void *prevArg;\n    Tcl_Time timeout;\n\n    /*\n     * Set up an event filter to select just the events we want, and a timer\n     * handler, then wait for events until we get the event we want or a\n     * timeout happens.\n     */\n\n    info.display = display;\n    info.wmInfoPtr = wmInfoPtr;\n    info.type = type;\n    info.eventPtr = eventPtr;\n    info.foundEvent = 0;\n    prevProc = Tk_RestrictEvents(WaitRestrictProc, &info, &prevArg);\n\n    Tcl_GetTime(&timeout);\n    timeout.sec += 2;\n\n    while (!info.foundEvent) {\n\tif (!TkUnixDoOneXEvent(&timeout)) {\n\t    break;\n\t}\n    }\n    Tk_RestrictEvents(prevProc, prevArg, &prevArg);\n    if (info.foundEvent) {\n\treturn TCL_OK;\n    }\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WaitRestrictProc --\n *\n *\tThis function is a Tk_RestrictProc that is used to filter events while\n *\tWaitForEvent is active.\n *\n * Results:\n *\tReturns TK_PROCESS_EVENT if the right event is found. Also returns\n *\tTK_PROCESS_EVENT if any ReparentNotify event is found or if the event\n *\tis a ConfigureNotify, MapNotify, or UnmapNotify for window. Otherwise\n *\treturns TK_DEFER_EVENT.\n *\n * Side effects:\n *\tAn event may get stored in the area indicated by the caller of\n *\tWaitForEvent.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tk_RestrictAction\nWaitRestrictProc(\n    void *clientData,\t/* Pointer to WaitRestrictInfo structure. */\n    XEvent *eventPtr)\t\t/* Event that is about to be handled. */\n{\n    WaitRestrictInfo *infoPtr = (WaitRestrictInfo *)clientData;\n\n    if (eventPtr->type == ReparentNotify) {\n\treturn TK_PROCESS_EVENT;\n    }\n    if (((eventPtr->xany.window != infoPtr->wmInfoPtr->wrapperPtr->window)\n\t    && (eventPtr->xany.window != infoPtr->wmInfoPtr->reparent))\n\t    || (eventPtr->xany.display != infoPtr->display)) {\n\treturn TK_DEFER_EVENT;\n    }\n    if (eventPtr->type == infoPtr->type) {\n\t*infoPtr->eventPtr = *eventPtr;\n\tinfoPtr->foundEvent = 1;\n\treturn TK_PROCESS_EVENT;\n    }\n    if (eventPtr->type == ConfigureNotify || eventPtr->type == MapNotify\n\t    || eventPtr->type == UnmapNotify) {\n\treturn TK_PROCESS_EVENT;\n    }\n    return TK_DEFER_EVENT;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WaitForMapNotify --\n *\n *\tThis function is invoked in order to synchronize with the window\n *\tmanager. It waits for the window's mapped state to reach the value\n *\tgiven by mapped.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDelays the execution of the process until winPtr becomes mapped or\n *\tunmapped, depending on the \"mapped\" argument. This allows us to\n *\tsynchronize with the window manager, and allows us to identify changes\n *\tin window size that come about when the window manager first starts\n *\tmanaging the window (as opposed to those requested interactively by\n *\tthe user later). See the comments for WaitForConfigureNotify and\n *\tWM_SYNC_PENDING. While waiting, some events covered by\n *\tStructureNotifyMask are processed and all others are deferred.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nWaitForMapNotify(\n    TkWindow *winPtr,\t\t/* Top-level window for which we want to see a\n\t\t\t\t * particular mapping state. */\n    int mapped)\t\t\t/* If non-zero, wait for window to become\n\t\t\t\t * mapped, otherwise wait for it to become\n\t\t\t\t * unmapped. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    XEvent event;\n    int code;\n\n    while (1) {\n\tif (mapped) {\n\t    if (winPtr->flags & TK_MAPPED) {\n\t\tbreak;\n\t    }\n\t} else if (!(winPtr->flags & TK_MAPPED)) {\n\t    break;\n\t}\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tcode = WaitForEvent(winPtr->display, wmPtr,\n\t\tmapped ? MapNotify : UnmapNotify, &event);\n\twmPtr->flags &= ~WM_SYNC_PENDING;\n\tif (code != TCL_OK) {\n\t    /*\n\t     * There are some bizarre situations in which the window manager\n\t     * can't respond or chooses not to (e.g. if we've got a grab set\n\t     * it can't respond). If this happens then just quit.\n\t     */\n\n\t    if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\t\tprintf(\"WaitForMapNotify giving up on %s\\n\", winPtr->pathName);\n\t    }\n\t    break;\n\t}\n    }\n    wmPtr->flags &= ~WM_MOVE_PENDING;\n    if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"WaitForMapNotify finished with %s (winPtr %p, wmPtr %p)\\n\",\n\t\twinPtr->pathName, winPtr, wmPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * UpdateHints --\n *\n *\tThis function is called to update the window manager's hints\n *\tinformation from the information in a WmInfo structure.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties get changed for winPtr.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nUpdateHints(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\treturn;\n    }\n    XSetWMHints(winPtr->display, wmPtr->wrapperPtr->window, &wmPtr->hints);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetNetWmType --\n *\n *\tSet the extended window manager hints for a toplevel window to the\n *\ttypes provided. The specification states that this may be a list of\n *\twindow types in preferred order. To permit for future type\n *\tdefinitions, the set of names is unconstrained and names are converted\n *\tto upper-case and appended to \"_NET_WM_WINDOW_TYPE_\" before being\n *\tconverted to an Atom.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetNetWmType(\n    TkWindow *winPtr,\n    Tcl_Obj *typePtr)\n{\n    Atom *atoms = NULL;\n    WmInfo *wmPtr;\n    Tcl_Obj **objv;\n    Tcl_Size objc, n;\n    Tk_Window tkwin = (Tk_Window) winPtr;\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n\n    if (TCL_OK != Tcl_ListObjGetElements(interp, typePtr, &objc, &objv)) {\n\treturn TCL_ERROR;\n    }\n\n    if (!Tk_HasWrapper(tkwin)) {\n\treturn TCL_OK; /* error?? */\n    }\n\n    if (objc > 0) {\n\tatoms = (Atom *)Tcl_Alloc(sizeof(Atom) * objc);\n    }\n\n    for (n = 0; n < objc; ++n) {\n\tTcl_DString ds, dsName;\n\tTcl_Size len;\n\tchar *name = Tcl_GetStringFromObj(objv[n], &len);\n\n\tTcl_UtfToUpper(name);\n\t(void)Tcl_UtfToExternalDString(NULL, name, len, &dsName);\n\tTcl_DStringInit(&ds);\n\tTcl_DStringAppend(&ds, \"_NET_WM_WINDOW_TYPE_\", 20);\n\tTcl_DStringAppend(&ds, Tcl_DStringValue(&dsName),\n\t\tTcl_DStringLength(&dsName));\n\tTcl_DStringFree(&dsName);\n\tatoms[n] = Tk_InternAtom(tkwin, Tcl_DStringValue(&ds));\n\tTcl_DStringFree(&ds);\n    }\n\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr->wrapperPtr == NULL) {\n\tCreateWrapper(wmPtr);\n    }\n\n    SetWindowProperty(wmPtr->wrapperPtr, \"_NET_WM_WINDOW_TYPE\", XA_ATOM, 32,\n\t    atoms, objc);\n\n    Tcl_Free(atoms);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetNetWmType --\n *\n *\tRead the extended window manager type hint from a window and return as\n *\ta list of names suitable for use with SetNetWmType.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetNetWmType(\n    TkWindow *winPtr)\n{\n    Atom typeAtom, actualType, *atoms;\n    int actualFormat;\n    unsigned long n, count, bytesAfter;\n    unsigned char *propertyValue = NULL;\n    long maxLength = 1024;\n    Tk_Window tkwin = (Tk_Window) winPtr;\n    TkWindow *wrapperPtr;\n    Tcl_Obj *typePtr;\n    Tcl_Interp *interp;\n    Tcl_DString ds;\n\n    interp = Tk_Interp(tkwin);\n    typePtr = Tcl_NewListObj(0, NULL);\n\n    if (winPtr->wmInfoPtr->wrapperPtr == NULL) {\n\tCreateWrapper(winPtr->wmInfoPtr);\n    }\n    wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;\n\n    typeAtom = Tk_InternAtom(tkwin, \"_NET_WM_WINDOW_TYPE\");\n    if (GetWindowProperty(wrapperPtr, typeAtom, maxLength, XA_ATOM,\n\t    &actualType, &actualFormat, &count, &bytesAfter, &propertyValue)){\n\tatoms = (Atom *) propertyValue;\n\tfor (n = 0; n < count; ++n) {\n\t    const char *name = Tk_GetAtomName(tkwin, atoms[n]);\n\n\t    if (strncmp(\"_NET_WM_WINDOW_TYPE_\", name, 20) == 0) {\n\t\t(void)Tcl_ExternalToUtfDString(NULL, name+20, TCL_INDEX_NONE, &ds);\n\t\tTcl_UtfToLower(Tcl_DStringValue(&ds));\n\t\tTcl_ListObjAppendElement(interp, typePtr,\n\t\t\tTcl_NewStringObj(Tcl_DStringValue(&ds),\n\t\t\t\tTcl_DStringLength(&ds)));\n\t\tTcl_DStringFree(&ds);\n\t    }\n\t}\n\tXFree(propertyValue);\n    }\n\n    return typePtr;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ParseGeometry --\n *\n *\tThis function parses a geometry string and updates information used to\n *\tcontrol the geometry of a top-level window.\n *\n * Results:\n *\tA standard Tcl return value, plus an error message in the interp's\n *\tresult if an error occurs.\n *\n * Side effects:\n *\tThe size and/or location of winPtr may change.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nParseGeometry(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    const char *string,\t\t/* String containing new geometry. Has the\n\t\t\t\t * standard form \"=wxh+x+y\". */\n    TkWindow *winPtr)\t\t/* Pointer to top-level window whose geometry\n\t\t\t\t * is to be changed. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y, width, height, flags;\n    char *end;\n    const char *p = string;\n\n    /*\n     * The leading \"=\" is optional.\n     */\n\n    if (*p == '=') {\n\tp++;\n    }\n\n    /*\n     * Parse the width and height, if they are present. Don't actually update\n     * any of the fields of wmPtr until we've successfully parsed the entire\n     * geometry string.\n     */\n\n    width = wmPtr->width;\n    height = wmPtr->height;\n    x = wmPtr->x;\n    y = wmPtr->y;\n    flags = wmPtr->flags;\n    if (isdigit(UCHAR(*p))) {\n\twidth = strtoul(p, &end, 10);\n\tp = end;\n\tif (*p != 'x') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p))) {\n\t    goto error;\n\t}\n\theight = strtoul(p, &end, 10);\n\tp = end;\n    }\n\n    /*\n     * Parse the X and Y coordinates, if they are present.\n     */\n\n    if (*p != '\\0') {\n\tflags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_X;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\tx = strtol(p, &end, 10);\n\tp = end;\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_Y;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\ty = strtol(p, &end, 10);\n\tif (*end != '\\0') {\n\t    goto error;\n\t}\n\n\t/*\n\t * Assume that the geometry information came from the user, unless an\n\t * explicit source has been specified. Otherwise most window managers\n\t * assume that the size hints were program-specified and they ignore\n\t * them.\n\t */\n\n\tif (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t    flags |= WM_UPDATE_SIZE_HINTS;\n\t}\n    }\n\n    /*\n     * Everything was parsed OK. Update the fields of *wmPtr and arrange for\n     * the appropriate information to be percolated out to the window manager\n     * at the next idle moment.\n     */\n\n    wmPtr->width = width;\n    wmPtr->height = height;\n    wmPtr->x = x;\n    wmPtr->y = y;\n    flags |= WM_MOVE_PENDING;\n    wmPtr->flags = flags;\n\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n    return TCL_OK;\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad geometry specifier \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GEOMETRY\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetRootCoords --\n *\n *\tGiven a token for a window, this function traces through the window's\n *\tlineage to find the (virtual) root-window coordinates corresponding to\n *\tpoint (0,0) in the window.\n *\n * Results:\n *\tThe locations pointed to by xPtr and yPtr are filled in with the root\n *\tcoordinates of the (0,0) point in tkwin. If a virtual root window is\n *\tin effect for the window, then the coordinates in the virtual root are\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetRootCoords(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    int *xPtr,\t\t\t/* Where to store x-displacement of (0,0). */\n    int *yPtr)\t\t\t/* Where to store y-displacement of (0,0). */\n{\n    int x, y;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    /*\n     * Search back through this window's parents all the way to a top-level\n     * window, combining the offsets of each window within its parent.\n     */\n\n    x = y = 0;\n    while (1) {\n\tx += winPtr->changes.x + winPtr->changes.border_width;\n\ty += winPtr->changes.y + winPtr->changes.border_width;\n\tif ((winPtr->wmInfoPtr != NULL)\n\t\t&& (winPtr->wmInfoPtr->menubar == (Tk_Window) winPtr)) {\n\t    /*\n\t     * This window is a special menubar; switch over to its associated\n\t     * toplevel, compensate for their differences in y coordinates,\n\t     * then continue with the toplevel (in case it's embedded).\n\t     */\n\n\t    y -= winPtr->wmInfoPtr->menuHeight;\n\t    winPtr = winPtr->wmInfoPtr->winPtr;\n\t    continue;\n\t}\n\tif (winPtr->flags & TK_TOP_LEVEL) {\n\t    Tk_Window otherPtr;\n\n\t    if (!(winPtr->flags & TK_EMBEDDED)) {\n\t\tbreak;\n\t    }\n\t    otherPtr = Tk_GetOtherWindow((Tk_Window)winPtr);\n\t    if (otherPtr == NULL) {\n\t\t/*\n\t\t * The container window is not in the same application. Query\n\t\t * the X server.\n\t\t */\n\n\t\tWindow root, dummyChild;\n\t\tint rootX, rootY;\n\n\t\troot = winPtr->wmInfoPtr->vRoot;\n\t\tif (root == None) {\n\t\t    root = RootWindowOfScreen(Tk_Screen((Tk_Window) winPtr));\n\t\t}\n\t\tXTranslateCoordinates(winPtr->display, winPtr->window,\n\t\t\troot, 0, 0, &rootX, &rootY, &dummyChild);\n\t\tx += rootX;\n\t\ty += rootY;\n\t\tbreak;\n\t    } else {\n\t\t/*\n\t\t * The container window is in the same application. Let's\n\t\t * query its coordinates.\n\t\t */\n\n\t\twinPtr = (TkWindow *)otherPtr;\n\t\tcontinue;\n\t    }\n\t}\n\twinPtr = winPtr->parentPtr;\n\tif (winPtr == NULL) {\n\t    break;\n\t}\n    }\n    *xPtr = x;\n    *yPtr = y;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CoordsToWindow --\n *\n *\tGiven the (virtual) root coordinates of a point, this function returns\n *\tthe token for the top-most window covering that point, if there exists\n *\tsuch a window in this application.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\trootX and rootY, or else NULL to indicate that there is no such\n *\twindow.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int PointInWindow(\n    int x,\n    int y,\n    WmInfo *wmPtr)\n{\n    XWindowChanges changes = wmPtr->winPtr->changes;\n    return (x >= changes.x &&\n\t    x < changes.x + changes.width &&\n\t    y >= changes.y - wmPtr->menuHeight &&\n\t    y < changes.y + changes.height);\n}\n\nTk_Window\nTk_CoordsToWindow(\n    int rootX, int rootY,\t/* Coordinates of point in root window. If a\n\t\t\t\t * virtual-root window manager is in use,\n\t\t\t\t * these coordinates refer to the virtual\n\t\t\t\t * root, not the real root. */\n    Tk_Window tkwin)\t\t/* Token for any window in application; used\n\t\t\t\t * to identify the display. */\n{\n    Window window, parent, child;\n    int x, y, childX, childY, tmpx, tmpy, bd;\n    WmInfo *wmPtr;\n    TkWindow *winPtr, *childPtr, *nextPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n    Tk_ErrorHandler handler = NULL;\n\n    /*\n     * Step 1: scan the list of toplevel windows to see if there is a virtual\n     * root for the screen we're interested in. If so, we have to translate\n     * the coordinates from virtual root to root coordinates.\n     */\n\n    parent = window = RootWindowOfScreen(Tk_Screen(tkwin));\n    x = rootX;\n    y = rootY;\n    for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;\n\t    wmPtr = wmPtr->nextPtr) {\n\tif (Tk_Screen(wmPtr->winPtr) != Tk_Screen(tkwin)) {\n\t    continue;\n\t}\n\tif (wmPtr->vRoot == None) {\n\t    continue;\n\t}\n\tUpdateVRootGeometry(wmPtr);\n\tparent = wmPtr->vRoot;\n\tbreak;\n    }\n\n    /*\n     * Step 2: work down through the window hierarchy starting at the root.\n     * For each window, find the child that contains the given point and then\n     * see if this child is either a wrapper for one of our toplevel windows\n     * or a window manager decoration window for one of our toplevels. This\n     * approach handles several tricky cases:\n     *\n     * 1. There may be a virtual root window between the root and one of our\n     *    toplevels.\n     * 2. If a toplevel is embedded, we may have to search through the\n     *    windows of the container application(s) before getting to the\n     *    toplevel.\n     */\n\n    handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL);\n    while (1) {\n\tif (XTranslateCoordinates(Tk_Display(tkwin), parent, window,\n\t\tx, y, &childX, &childY, &child) == False) {\n\t    /*\n\t     * We can end up here when the window is in the middle of being\n\t     * deleted\n\t     */\n\n\t    Tk_DeleteErrorHandler(handler);\n\t    return NULL;\n\t}\n\tif (child == None) {\n\t    Tk_DeleteErrorHandler(handler);\n\t    return NULL;\n\t}\n\tfor (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;\n\t\twmPtr = wmPtr->nextPtr) {\n\t    if (wmPtr->winPtr->mainPtr == NULL) {\n\t\tcontinue;\n\t    }\n\t    if (child == wmPtr->reparent) {\n\t\tif (PointInWindow(x, y, wmPtr)) {\n\t\t    goto gotToplevel;\n\t\t} else {\n\n\t\t    /*\n\t\t     * Return NULL if the point is in the title bar or border.\n\t\t     */\n\n\t\t    return NULL;\n\t\t}\n\t    }\n\t    if (wmPtr->wrapperPtr != NULL) {\n\t\tif (child == wmPtr->wrapperPtr->window) {\n\t\t    goto gotToplevel;\n\t\t} else if (wmPtr->winPtr->flags & TK_EMBEDDED &&\n\t\t\t   Tk_GetOtherWindow((Tk_Window)wmPtr->winPtr) == NULL) {\n\n\t\t    /*\n\t\t     * This toplevel is embedded in a window belonging to\n\t\t     * a different application.\n\t\t     */\n\n\t\t    int rx, ry;\n\t\t    Tk_GetRootCoords((Tk_Window) wmPtr->winPtr, &rx, &ry);\n\t\t    childX -= rx;\n\t\t    childY -= ry;\n\t\t    goto gotToplevel;\n\t\t}\n\t    } else if (child == wmPtr->winPtr->window) {\n\t\tgoto gotToplevel;\n\t    }\n\t}\n\tx = childX;\n\ty = childY;\n\tparent = window;\n\twindow = child;\n    }\n\n  gotToplevel:\n    if (handler) {\n\t/*\n\t * Check value of handler, because we can reach this label from above\n\t * or below\n\t */\n\n\tTk_DeleteErrorHandler(handler);\n\thandler = NULL;\n    }\n    winPtr = wmPtr->winPtr;\n\n    /*\n     * Step 3: at this point winPtr and wmPtr refer to the toplevel that\n     * contains the given coordinates, and childX and childY give the\n     * translated coordinates in the *parent* of the toplevel. Now decide\n     * whether the coordinates are in the menubar or the actual toplevel, and\n     * translate the coordinates into the coordinate system of that window.\n     */\n\n    x = childX - winPtr->changes.x;\n    y = childY - winPtr->changes.y;\n    if ((x < 0) || (x >= winPtr->changes.width)\n\t    || (y >= winPtr->changes.height)) {\n\treturn NULL;\n    }\n    if (y < 0) {\n\twinPtr = (TkWindow *) wmPtr->menubar;\n\tif (winPtr == NULL) {\n\t    return NULL;\n\t}\n\ty += wmPtr->menuHeight;\n\tif (y < 0) {\n\t    return NULL;\n\t}\n    }\n\n    /*\n     * Step 4: work down through the hierarchy underneath the current window.\n     * At each level, scan through all the children to find the highest one in\n     * the stacking order that contains the point. Then repeat the whole\n     * process on that child.\n     */\n\n    while (1) {\n\tnextPtr = NULL;\n\tfor (childPtr = winPtr->childList; childPtr != NULL;\n\t\tchildPtr = childPtr->nextPtr) {\n\t    if (!Tk_IsMapped(childPtr)\n\t\t    || (childPtr->flags & TK_TOP_HIERARCHY)) {\n\t\tcontinue;\n\t    }\n\t    if (childPtr->flags & TK_REPARENTED) {\n\t\tcontinue;\n\t    }\n\t    tmpx = x - childPtr->changes.x;\n\t    tmpy = y - childPtr->changes.y;\n\t    bd = childPtr->changes.border_width;\n\t    if ((tmpx >= -bd) && (tmpy >= -bd)\n\t\t    && (tmpx < (childPtr->changes.width + bd))\n\t\t    && (tmpy < (childPtr->changes.height + bd))) {\n\t\tnextPtr = childPtr;\n\t    }\n\t}\n\tif (nextPtr == NULL) {\n\t    break;\n\t}\n\tx -= nextPtr->changes.x;\n\ty -= nextPtr->changes.y;\n\tif ((nextPtr->flags & TK_CONTAINER)\n\t\t&& (nextPtr->flags & TK_BOTH_HALVES)) {\n\t    /*\n\t     * The window containing the point is a container, and the\n\t     * embedded application is in this same process. Switch over to\n\t     * the toplevel for the embedded application and start processing\n\t     * that toplevel from scratch.\n\t     */\n\t    winPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)nextPtr);\n\t    if (winPtr == NULL) {\n\t\treturn (Tk_Window) nextPtr;\n\t    }\n\t    wmPtr = winPtr->wmInfoPtr;\n\t    childX = x;\n\t    childY = y;\n\t    goto gotToplevel;\n\t} else {\n\t    winPtr = nextPtr;\n\t}\n    }\n    if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {\n\treturn NULL;\n    }\n    return (Tk_Window) winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateVRootGeometry --\n *\n *\tThis function is called to update all the virtual root geometry\n *\tinformation in wmPtr.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe vRootX, vRootY, vRootWidth, and vRootHeight fields in wmPtr are\n *\tfilled with the most up-to-date information.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateVRootGeometry(\n    WmInfo *wmPtr)\t\t/* Window manager information to be updated.\n\t\t\t\t * The wmPtr->vRoot field must be valid. */\n{\n    TkWindow *winPtr = wmPtr->winPtr;\n    int bd;\n    unsigned dummy;\n    Window dummy2;\n    Status status;\n    Tk_ErrorHandler handler;\n\n    /*\n     * If this isn't a virtual-root window manager, just return information\n     * about the screen.\n     */\n\n    wmPtr->flags &= ~WM_VROOT_OFFSET_STALE;\n    if (wmPtr->vRoot == None) {\n    noVRoot:\n\twmPtr->vRootX = wmPtr->vRootY = 0;\n\twmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum);\n\twmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum);\n\treturn;\n    }\n\n    /*\n     * Refresh the virtual root information if it's out of date.\n     */\n\n    handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL);\n    status = XGetGeometry(winPtr->display, wmPtr->vRoot,\n\t    &dummy2, &wmPtr->vRootX, &wmPtr->vRootY,\n\t    (unsigned *) &wmPtr->vRootWidth,\n\t    (unsigned *) &wmPtr->vRootHeight, (unsigned *) &bd,\n\t    &dummy);\n    if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {\n\tprintf(\"UpdateVRootGeometry: x = %d, y = %d, width = %d, \",\n\t\twmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth);\n\tprintf(\"height = %d, status = %d\\n\", wmPtr->vRootHeight, status);\n    }\n    Tk_DeleteErrorHandler(handler);\n    if (status == 0) {\n\t/*\n\t * The virtual root is gone! Pretend that it never existed.\n\t */\n\n\twmPtr->vRoot = None;\n\tgoto noVRoot;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetVRootGeometry --\n *\n *\tThis function returns information about the virtual root window\n *\tcorresponding to a particular Tk window.\n *\n * Results:\n *\tThe values at xPtr, yPtr, widthPtr, and heightPtr are set with the\n *\toffset and dimensions of the root window corresponding to tkwin. If\n *\ttkwin is being managed by a virtual root window manager these values\n *\tcorrespond to the virtual root window being used for tkwin; otherwise\n *\tthe offsets will be 0 and the dimensions will be those of the screen.\n *\n * Side effects:\n *\tVroot window information is refreshed if it is out of date.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetVRootGeometry(\n    Tk_Window tkwin,\t\t/* Window whose virtual root is to be\n\t\t\t\t * queried. */\n    int *xPtr, int *yPtr,\t/* Store x and y offsets of virtual root\n\t\t\t\t * here. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* Store dimensions of virtual root here. */\n{\n    WmInfo *wmPtr;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    /*\n     * Find the top-level window for tkwin, and locate the window manager\n     * information for that window.\n     */\n\n    while (!(winPtr->flags & TK_TOP_HIERARCHY)\n\t    && (winPtr->parentPtr != NULL)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\t/* Punt. */\n\t*xPtr = 0;\n\t*yPtr = 0;\n\t*widthPtr = 0;\n\t*heightPtr = 0;\n    }\n\n    /*\n     * Make sure that the geometry information is up-to-date, then copy it out\n     * to the caller.\n     */\n\n    if (wmPtr->flags & WM_VROOT_OFFSET_STALE) {\n\tUpdateVRootGeometry(wmPtr);\n    }\n    *xPtr = wmPtr->vRootX;\n    *yPtr = wmPtr->vRootY;\n    *widthPtr = wmPtr->vRootWidth;\n    *heightPtr = wmPtr->vRootHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MoveToplevelWindow --\n *\n *\tThis function is called instead of Tk_MoveWindow to adjust the x-y\n *\tlocation of a top-level window. It delays the actual move to a later\n *\ttime and keeps window-manager information up-to-date with the move\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is eventually moved so that its upper-left corner\n *\t(actually, the upper-left corner of the window's decorative frame, if\n *\tthere is one) is at (x,y).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MoveToplevelWindow(\n    Tk_Window tkwin,\t\t/* Window to move. */\n    int x, int y)\t\t/* New location for window (within parent). */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\tTcl_Panic(\"Tk_MoveToplevelWindow called with non-toplevel window\");\n    }\n    wmPtr->x = x;\n    wmPtr->y = y;\n    wmPtr->flags |= WM_MOVE_PENDING;\n    wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);\n    if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\twmPtr->sizeHintsFlags |= USPosition;\n\twmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    }\n\n    /*\n     * If the window has already been mapped, must bring its geometry\n     * up-to-date immediately, otherwise an event might arrive from the server\n     * that would overwrite wmPtr->x and wmPtr->y and lose the new position.\n     */\n\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tif (wmPtr->flags & WM_UPDATE_PENDING) {\n\t    Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n\t}\n\tUpdateGeometryInfo(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateWmProtocols --\n *\n *\tThis function transfers the most up-to-date information about window\n *\tmanager protocols from the WmInfo structure to the actual property on\n *\tthe top-level window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe WM_PROTOCOLS property gets changed for wmPtr's window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateWmProtocols(\n    WmInfo *wmPtr)\t/* Information about top-level window. */\n{\n    ProtocolHandler *protPtr;\n    Atom deleteWindowAtom, pingAtom;\n    int count;\n    Atom *arrayPtr, *atomPtr;\n\n    /*\n     * There are only two tricky parts here. First, there could be any number\n     * of atoms for the window, so count them and malloc an array to hold all\n     * of their atoms. Second, we *always* want to respond to the\n     * WM_DELETE_WINDOW and _NET_WM_PING protocols, even if no-one's\n     * officially asked.\n     */\n\n    for (protPtr = wmPtr->protPtr, count = 2; protPtr != NULL;\n\t    protPtr = protPtr->nextPtr, count++) {\n\t/* Empty loop body; we're just counting the handlers. */\n    }\n    arrayPtr = (Atom *)Tcl_Alloc(count * sizeof(Atom));\n    deleteWindowAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr,\n\t    \"WM_DELETE_WINDOW\");\n    pingAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, \"_NET_WM_PING\");\n    arrayPtr[0] = deleteWindowAtom;\n    arrayPtr[1] = pingAtom;\n    for (protPtr = wmPtr->protPtr, atomPtr = &arrayPtr[1];\n\t    protPtr != NULL; protPtr = protPtr->nextPtr) {\n\tif (protPtr->protocol != deleteWindowAtom\n\t\t&& protPtr->protocol != pingAtom) {\n\t    *(atomPtr++) = protPtr->protocol;\n\t}\n    }\n    SetWindowProperty(wmPtr->wrapperPtr, \"WM_PROTOCOLS\", XA_ATOM, 32,\n\t    arrayPtr, atomPtr-arrayPtr);\n    Tcl_Free(arrayPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmProtocolEventProc --\n *\n *\tThis function is called by the Tk_HandleEvent whenever a ClientMessage\n *\tevent arrives whose type is \"WM_PROTOCOLS\". This function handles the\n *\tmessage from the window manager in an appropriate fashion.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what sort of handler, if any, was set up for the protocol.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmProtocolEventProc(\n    TkWindow *winPtr,\t\t/* Window to which the event was sent. */\n    XEvent *eventPtr)\t\t/* X event. */\n{\n    WmInfo *wmPtr;\n    ProtocolHandler *protPtr;\n    Atom protocol;\n    int result;\n    const char *protocolName;\n    Tcl_Interp *interp;\n\n    protocol = (Atom) eventPtr->xclient.data.l[0];\n\n    /*\n     * If this is a _NET_WM_PING message, send it back to the root window\n     * immediately. We do that here because scripts *cannot* respond correctly\n     * to this protocol.\n     */\n\n    if (protocol == Tk_InternAtom((Tk_Window) winPtr, \"_NET_WM_PING\")) {\n\tWindow root = XRootWindow(winPtr->display, winPtr->screenNum);\n\n\teventPtr->xclient.window = root;\n\t(void) XSendEvent(winPtr->display, root, False,\n\t\t(SubstructureNotifyMask|SubstructureRedirectMask), eventPtr);\n\treturn;\n    }\n\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Note: it's very important to retrieve the protocol name now, before\n     * invoking the command, even though the name won't be used until after\n     * the command returns. This is because the command could delete winPtr,\n     * making it impossible for us to use it later in the call to\n     * Tk_GetAtomName.\n     */\n\n    protocolName = Tk_GetAtomName((Tk_Window) winPtr, protocol);\n    for (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t    protPtr = protPtr->nextPtr) {\n\tif (protocol == protPtr->protocol) {\n\t    Tcl_Preserve(protPtr);\n\t    interp = protPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    result = Tcl_EvalEx(interp, protPtr->command, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    if (result != TCL_OK) {\n\t\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\t\"\\n    (command for \\\"%s\\\" window manager protocol)\",\n\t\t\tprotocolName));\n\t\tTcl_BackgroundException(interp, result);\n\t    }\n\t    Tcl_Release(interp);\n\t    Tcl_Release(protPtr);\n\t    return;\n\t}\n    }\n\n    /*\n     * No handler was present for this protocol. If this is a WM_DELETE_WINDOW\n     * message then just destroy the window.\n     */\n\n    if (protocol == Tk_InternAtom((Tk_Window) winPtr, \"WM_DELETE_WINDOW\")) {\n\tTk_DestroyWindow((Tk_Window) wmPtr->winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevelWrapperMap --\n *\n *\tThis function will create a table that maps the reparent wrapper X id\n *\tfor a toplevel to the TkWindow structure that is wraps. Tk keeps track\n *\tof a mapping from the window X id to the TkWindow structure but that\n *\tdoes us no good here since we only get the X id of the wrapper window.\n *\tOnly those toplevel windows that are mapped have a position in the\n *\tstacking order.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAdds entries to the passed hashtable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkWmStackorderToplevelWrapperMap(\n    TkWindow *winPtr,\t\t/* TkWindow to recurse on */\n    Display *display,\t\t/* X display of parent window */\n    Tcl_HashTable *table)\t/* Maps X id to TkWindow */\n{\n    TkWindow *childPtr;\n\n    if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) &&\n\t    !Tk_IsEmbedded(winPtr) && (winPtr->display == display)) {\n\tWindow wrapper = (winPtr->wmInfoPtr->reparent != None)\n\t\t? winPtr->wmInfoPtr->reparent\n\t\t: winPtr->wmInfoPtr->wrapperPtr->window;\n\tTcl_HashEntry *hPtr;\n\tint newEntry;\n\n\thPtr = Tcl_CreateHashEntry(table, (char *) wrapper, &newEntry);\n\tTcl_SetHashValue(hPtr, winPtr);\n    }\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tTkWmStackorderToplevelWrapperMap(childPtr, display, table);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevel --\n *\n *\tThis function returns the stack order of toplevel windows.\n *\n * Results:\n *\tAn array of pointers to tk window objects in stacking order or else\n *\tNULL if there was an error.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow **\nTkWmStackorderToplevel(\n    TkWindow *parentPtr)\t/* Parent toplevel window. */\n{\n    Window dummy1, dummy2, vRoot;\n    Window *children;\n    unsigned numChildren, i;\n    TkWindow *childWinPtr, **windows, **window_ptr;\n    Tcl_HashTable table;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    /*\n     * Map X Window ids to a TkWindow of the wrapped toplevel.\n     */\n\n    Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);\n    TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);\n\n    window_ptr = windows = (TkWindow **)Tcl_Alloc((table.numEntries+1) * sizeof(TkWindow *));\n    if (windows == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Special cases: If zero or one toplevels were mapped there is no need to\n     * call XQueryTree.\n     */\n\n    switch (table.numEntries) {\n    case 0:\n\twindows[0] = NULL;\n\tgoto done;\n    case 1:\n\thPtr = Tcl_FirstHashEntry(&table, &search);\n\twindows[0] = (TkWindow *)Tcl_GetHashValue(hPtr);\n\twindows[1] = NULL;\n\tgoto done;\n    }\n\n    vRoot = parentPtr->wmInfoPtr->vRoot;\n    if (vRoot == None) {\n\tvRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) parentPtr));\n    }\n\n    if (XQueryTree(parentPtr->display, vRoot, &dummy1, &dummy2,\n\t    &children, &numChildren) == 0) {\n\tTcl_Free(windows);\n\twindows = NULL;\n    } else {\n\tfor (i = 0; i < numChildren; i++) {\n\t    hPtr = Tcl_FindHashEntry(&table, children[i]);\n\t    if (hPtr != NULL) {\n\t\tchildWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);\n\t\t*window_ptr++ = childWinPtr;\n\t    }\n\t}\n\n\t/*\n\t * ASSERT: window_ptr - windows == table.numEntries\n\t * (#matched toplevel windows == #children) [Bug 1789819]\n\t */\n\n\t*window_ptr = NULL;\n\tif (numChildren) {\n\t    XFree(children);\n\t}\n    }\n\n  done:\n    Tcl_DeleteHashTable(&table);\n    return windows;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRestackToplevel --\n *\n *\tThis function restacks a top-level window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr gets restacked as specified by aboveBelow and otherPtr.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmRestackToplevel(\n    TkWindow *winPtr,\t\t/* Window to restack. */\n    int aboveBelow,\t\t/* Gives relative position for restacking;\n\t\t\t\t * must be Above or Below. */\n    TkWindow *otherPtr)\t\t/* Window relative to which to restack; if\n\t\t\t\t * NULL, then winPtr gets restacked above or\n\t\t\t\t * below *all* siblings. */\n{\n    XWindowChanges changes;\n    unsigned mask;\n    TkWindow *wrapperPtr;\n\n    memset(&changes, 0, sizeof(XWindowChanges));\n    changes.stack_mode = aboveBelow;\n    mask = CWStackMode;\n\n    /*\n     * Make sure that winPtr and its wrapper window have been created.\n     */\n\n    if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {\n\tTkWmMapWindow(winPtr);\n    }\n    wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;\n\n    if (otherPtr != NULL) {\n\t/*\n\t * The window is to be restacked with respect to another toplevel.\n\t * Make sure it has been created as well.\n\t */\n\n\tif (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {\n\t    TkWmMapWindow(otherPtr);\n\t}\n\tchanges.sibling = otherPtr->wmInfoPtr->wrapperPtr->window;\n\tmask |= CWSibling;\n    }\n\n    /*\n     * Reconfigure the window. Note that we use XReconfigureWMWindow instead\n     * of XConfigureWindow, in order to handle the case where the window is to\n     * be restacked with respect to another toplevel. See [ICCCM] 4.1.5\n     * \"Configuring the Window\" and XReconfigureWMWindow(3) for details.\n     */\n\n    XReconfigureWMWindow(winPtr->display, wrapperPtr->window,\n\t    Tk_ScreenNumber((Tk_Window) winPtr), mask, &changes);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmAddToColormapWindows --\n *\n *\tThis function is called to add a given window to the\n *\tWM_COLORMAP_WINDOWS property for its top-level, if it isn't already\n *\tthere. It is invoked by the Tk code that creates a new colormap, in\n *\torder to make sure that colormap information is propagated to the\n *\twindow manager by default.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets added to the WM_COLORMAP_WINDOWS property of its\n *\tnearest top-level ancestor, unless the colormaps have been set\n *\texplicitly with the \"wm colormapwindows\" command.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmAddToColormapWindows(\n    TkWindow *winPtr)\t\t/* Window with a non-default colormap. Should\n\t\t\t\t * not be a top-level window. */\n{\n    TkWindow *wrapperPtr;\n    TkWindow *topPtr;\n    Window *oldPtr, *newPtr;\n    int count, i;\n\n    if (winPtr->window == None) {\n\treturn;\n    }\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Window is being deleted. Skip the whole operation.\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n    }\n    if (topPtr->wmInfoPtr == NULL) {\n\treturn;\n    }\n\n    if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {\n\treturn;\n    }\n    if (topPtr->wmInfoPtr->wrapperPtr == NULL) {\n\tCreateWrapper(topPtr->wmInfoPtr);\n    }\n    wrapperPtr = topPtr->wmInfoPtr->wrapperPtr;\n\n    /*\n     * Fetch the old value of the property.\n     */\n\n    if (XGetWMColormapWindows(topPtr->display, wrapperPtr->window,\n\t    &oldPtr, &count) == 0) {\n\toldPtr = NULL;\n\tcount = 0;\n    }\n\n    /*\n     * Make sure that the window isn't already in the list.\n     */\n\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr->window) {\n\t    return;\n\t}\n    }\n\n    /*\n     * Make a new bigger array and use it to reset the property. Automatically\n     * add the toplevel itself as the last element of the list.\n     */\n\n    newPtr = (Window *)Tcl_Alloc((count+2) * sizeof(Window));\n    for (i = 0; i < count; i++) {\n\tnewPtr[i] = oldPtr[i];\n    }\n    if (count == 0) {\n\tcount++;\n    }\n    newPtr[count-1] = winPtr->window;\n    newPtr[count] = topPtr->window;\n    XSetWMColormapWindows(topPtr->display, wrapperPtr->window, newPtr,\n\t    count+1);\n    Tcl_Free(newPtr);\n    if (oldPtr != NULL) {\n\tXFree(oldPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRemoveFromColormapWindows --\n *\n *\tThis function is called to remove a given window from the\n *\tWM_COLORMAP_WINDOWS property for its top-level. It is invoked when\n *\twindows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets removed from the WM_COLORMAP_WINDOWS property of\n *\tits nearest top-level ancestor, unless the top-level itself is being\n *\tdeleted too.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmRemoveFromColormapWindows(\n    TkWindow *winPtr)\t\t/* Window that may be present in\n\t\t\t\t * WM_COLORMAP_WINDOWS property for its\n\t\t\t\t * top-level. Should not be a top-level\n\t\t\t\t * window. */\n{\n    TkWindow *wrapperPtr;\n    TkWindow *topPtr;\n    Window *oldPtr;\n    int count, i, j;\n\n    if (winPtr->window == None) {\n\treturn;\n    }\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Ancestors have been deleted, so skip the whole operation.\n\t     * Seems like this can't ever happen?\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n    }\n    if (topPtr->flags & TK_ALREADY_DEAD) {\n\t/*\n\t * Top-level is being deleted, so there's no need to cleanup the\n\t * WM_COLORMAP_WINDOWS property.\n\t */\n\n\treturn;\n    }\n    if (topPtr->wmInfoPtr == NULL) {\n\treturn;\n    }\n\n    if (topPtr->wmInfoPtr->wrapperPtr == NULL) {\n\tCreateWrapper(topPtr->wmInfoPtr);\n    }\n    wrapperPtr = topPtr->wmInfoPtr->wrapperPtr;\n    if (wrapperPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Fetch the old value of the property.\n     */\n\n    if (XGetWMColormapWindows(topPtr->display, wrapperPtr->window,\n\t    &oldPtr, &count) == 0) {\n\treturn;\n    }\n\n    /*\n     * Find the window and slide the following ones down to cover it up.\n     */\n\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr->window) {\n\t    for (j = i ; j < count-1; j++) {\n\t\toldPtr[j] = oldPtr[j+1];\n\t    }\n\t    XSetWMColormapWindows(topPtr->display, wrapperPtr->window,\n\t\t    oldPtr, count-1);\n\t    break;\n\t}\n    }\n    XFree(oldPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetPointerCoords --\n *\n *\tFetch the position of the mouse pointer.\n *\n * Results:\n *\t*xPtr and *yPtr are filled in with the (virtual) root coordinates of\n *\tthe mouse pointer for tkwin's display. If the pointer isn't on tkwin's\n *\tscreen, then -1 values are returned for both coordinates. The argument\n *\ttkwin must be a toplevel window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetPointerCoords(\n    Tk_Window tkwin,\t\t/* Toplevel window that identifies screen on\n\t\t\t\t * which lookup is to be done. */\n    int *xPtr, int *yPtr)\t/* Store pointer coordinates here. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n    Window w, root, child;\n    int rootX, rootY;\n    unsigned mask;\n\n    wmPtr = winPtr->wmInfoPtr;\n\n    w = wmPtr->vRoot;\n    if (w == None) {\n\tw = RootWindow(winPtr->display, winPtr->screenNum);\n    }\n    if (XQueryPointer(winPtr->display, w, &root, &child, &rootX, &rootY,\n\t    xPtr, yPtr, &mask) != True) {\n\t*xPtr = -1;\n\t*yPtr = -1;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMaxSize --\n *\n *\tThis function computes the current maxWidth and maxHeight values for a\n *\twindow, taking into account the possibility that they may be\n *\tdefaulted.\n *\n * Results:\n *\tThe values at *maxWidthPtr and *maxHeightPtr are filled in with the\n *\tmaximum allowable dimensions of wmPtr's window, in grid units. If no\n *\tmaximum has been specified for the window, then this function computes\n *\tthe largest sizes that will fit on the screen.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMaxSize(\n    WmInfo *wmPtr,\t\t/* Window manager information for the\n\t\t\t\t * window. */\n    int *maxWidthPtr,\t\t/* Where to store the current maximum width of\n\t\t\t\t * the window. */\n    int *maxHeightPtr)\t\t/* Where to store the current maximum height\n\t\t\t\t * of the window. */\n{\n    int tmp;\n\n    if (wmPtr->maxWidth > 0) {\n\t*maxWidthPtr = wmPtr->maxWidth;\n    } else {\n\t/*\n\t * Must compute a default width. Fill up the display, leaving a bit of\n\t * extra space for the window manager's borders.\n\t */\n\n\ttmp = DisplayWidth(wmPtr->winPtr->display, wmPtr->winPtr->screenNum)\n\t    - 15;\n\tif (wmPtr->gridWin != NULL) {\n\t    /*\n\t     * Gridding is turned on; convert from pixels to grid units.\n\t     */\n\n\t    tmp = wmPtr->reqGridWidth\n\t\t    + (tmp - wmPtr->winPtr->reqWidth)/wmPtr->widthInc;\n\t}\n\t*maxWidthPtr = tmp;\n    }\n    if (wmPtr->maxHeight > 0) {\n\t*maxHeightPtr = wmPtr->maxHeight;\n    } else {\n\ttmp = DisplayHeight(wmPtr->winPtr->display, wmPtr->winPtr->screenNum)\n\t    - 30;\n\tif (wmPtr->gridWin != NULL) {\n\t    tmp = wmPtr->reqGridHeight\n\t\t    + (tmp - wmPtr->winPtr->reqHeight)/wmPtr->heightInc;\n\t}\n\t*maxHeightPtr = tmp;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetTransientFor --\n *\n *\tSet a Tk window to be transient with reference to a specified\n *\tparent or the toplevel ancestor if None is passed as parent.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkSetTransientFor(Tk_Window tkwin, Tk_Window parent)\n{\n    if (parent == NULL) {\n\tparent = Tk_Parent(tkwin);\n\twhile (!Tk_IsTopLevel(parent))\n\t    parent = Tk_Parent(parent);\n    }\n    /*\n     * Prevent crash due to incomplete initialization, or other problems.\n     * [Bugs 3554026, 3561016]\n     */\n    if (((TkWindow *)parent)->wmInfoPtr->wrapperPtr == NULL) {\n\tCreateWrapper(((TkWindow *)parent)->wmInfoPtr);\n    }\n    XSetTransientForHint(Tk_Display(tkwin),\n\t((TkWindow *)tkwin)->wmInfoPtr->wrapperPtr->window,\n\t((TkWindow *)parent)->wmInfoPtr->wrapperPtr->window);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMakeMenuWindow --\n *\n *\tConfigure the window to be either a pull-down menu, a pop-up menu, or\n *\tas a toplevel (torn-off) menu or palette.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the style bit used to create a new Mac toplevel.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMakeMenuWindow(\n    Tk_Window tkwin,\t\t/* New window. */\n    int typeFlag)\t\t/* TK_MAKE_MENU_DROPDOWN means menu is only\n\t\t\t\t * posted briefly as a pulldown or cascade,\n\t\t\t\t * TK_MAKE_MENU_POPUP means it is a popup.\n\t\t\t\t * TK_MAKE_MENU_TEAROFF means menu is always\n\t\t\t\t * visible, e.g. as a torn-off menu.\n\t\t\t\t * Determines whether save_under and\n\t\t\t\t * override_redirect should be set, plus how\n\t\t\t\t * to flag it for the window manager. */\n{\n    WmInfo *wmPtr;\n    XSetWindowAttributes atts;\n    TkWindow *wrapperPtr;\n    Tcl_Obj *typeObj;\n\n    if (!Tk_HasWrapper(tkwin)) {\n\treturn;\n    }\n    wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;\n    if (wmPtr->wrapperPtr == NULL) {\n\tCreateWrapper(wmPtr);\n    }\n    wrapperPtr = wmPtr->wrapperPtr;\n    if (typeFlag == TK_MAKE_MENU_TEAROFF) {\n\tatts.override_redirect = False;\n\tatts.save_under = False;\n\ttypeObj = Tcl_NewStringObj(\"menu\", TCL_INDEX_NONE);\n\tTkSetTransientFor(tkwin, NULL);\n    } else {\n\tatts.override_redirect = True;\n\tatts.save_under = True;\n\tif (typeFlag == TK_MAKE_MENU_DROPDOWN) {\n\t    typeObj = Tcl_NewStringObj(\"dropdown_menu\", TCL_INDEX_NONE);\n\t} else {\n\t    typeObj = Tcl_NewStringObj(\"popup_menu\", TCL_INDEX_NONE);\n\t}\n    }\n    Tcl_IncrRefCount(typeObj);\n    SetNetWmType((TkWindow *)tkwin, typeObj);\n    Tcl_DecrRefCount(typeObj);\n\n    /*\n     * The override-redirect and save-under bits must be set on the wrapper\n     * window in order to have the desired effect. However, also set the\n     * override-redirect bit on the window itself, so that the \"wm\n     * overrideredirect\" command will see it.\n     */\n\n    if ((atts.override_redirect!=Tk_Attributes(wrapperPtr)->override_redirect)\n\t    || (atts.save_under != Tk_Attributes(wrapperPtr)->save_under)) {\n\tTk_ChangeWindowAttributes((Tk_Window) wrapperPtr,\n\t\tCWOverrideRedirect|CWSaveUnder, &atts);\n    }\n    if (atts.override_redirect != Tk_Attributes(tkwin)->override_redirect) {\n\tTk_ChangeWindowAttributes(tkwin, CWOverrideRedirect, &atts);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateWrapper --\n *\n *\tThis function is invoked to create the wrapper window for a toplevel\n *\twindow. It is called just before a toplevel is mapped for the first\n *\ttime.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe wrapper is created and the toplevel is reparented inside it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nCreateWrapper(\n    WmInfo *wmPtr)\t\t/* Window manager information for the\n\t\t\t\t * window. */\n{\n    TkWindow *winPtr, *wrapperPtr;\n    Window parent;\n    Tcl_HashEntry *hPtr;\n    int isNew;\n\n    winPtr = wmPtr->winPtr;\n    if (winPtr->window == None) {\n\tTk_MakeWindowExist((Tk_Window) winPtr);\n    }\n\n    /*\n     * The code below is copied from CreateTopLevelWindow, Tk_MakeWindowExist,\n     * and Tk_MakeWindow. The idea is to create an \"official\" Tk window (so\n     * that we can get events on it), but to hide the window outside the\n     * official Tk hierarchy so that it isn't visible to the application. See\n     * the comments for the other functions if you have questions about this\n     * code.\n     */\n\n    wmPtr->wrapperPtr = wrapperPtr = TkAllocWindow(winPtr->dispPtr,\n\t    Tk_ScreenNumber((Tk_Window) winPtr), winPtr);\n    wrapperPtr->dirtyAtts |= CWBorderPixel;\n\n    /*\n     * Tk doesn't normally select for StructureNotifyMask events because the\n     * events are synthesized internally. However, for wrapper windows we need\n     * to know when the window manager modifies the window configuration. We\n     * also need to select on focus change events; these are the only windows\n     * for which we care about focus changes.\n     */\n\n    wrapperPtr->flags |= TK_WRAPPER;\n    wrapperPtr->atts.event_mask |= StructureNotifyMask|FocusChangeMask;\n    wrapperPtr->atts.override_redirect = winPtr->atts.override_redirect;\n    if (winPtr->flags & TK_EMBEDDED) {\n\tparent = TkUnixContainerId(winPtr);\n    } else {\n\tparent = XRootWindow(wrapperPtr->display, wrapperPtr->screenNum);\n    }\n    wrapperPtr->window = XCreateWindow(wrapperPtr->display,\n\t    parent, wrapperPtr->changes.x, wrapperPtr->changes.y,\n\t    (unsigned) wrapperPtr->changes.width,\n\t    (unsigned) wrapperPtr->changes.height,\n\t    (unsigned) wrapperPtr->changes.border_width, wrapperPtr->depth,\n\t    InputOutput, wrapperPtr->visual,\n\t    wrapperPtr->dirtyAtts|CWOverrideRedirect, &wrapperPtr->atts);\n    hPtr = Tcl_CreateHashEntry(&wrapperPtr->dispPtr->winTable,\n\t    (char *) wrapperPtr->window, &isNew);\n    Tcl_SetHashValue(hPtr, wrapperPtr);\n    wrapperPtr->mainPtr = winPtr->mainPtr;\n    wrapperPtr->mainPtr->refCount++;\n    wrapperPtr->dirtyAtts = 0;\n    wrapperPtr->dirtyChanges = 0;\n    wrapperPtr->wmInfoPtr = wmPtr;\n\n    /*\n     * Reparent the toplevel window inside the wrapper.\n     */\n\n    XReparentWindow(wrapperPtr->display, winPtr->window, wrapperPtr->window,\n\t    0, 0);\n\n    /*\n     * Tk must monitor structure events for wrapper windows in order to detect\n     * changes made by window managers such as resizing, mapping, unmapping,\n     * etc..\n     */\n\n    Tk_CreateEventHandler((Tk_Window) wmPtr->wrapperPtr,\n\t    WrapperEventMask, WrapperEventProc, wmPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmFocusToplevel --\n *\n *\tThis is a utility function invoked by focus-management code. The focus\n *\tcode responds to externally generated focus-related events on wrapper\n *\twindows but ignores those events for any other windows. This function\n *\tdetermines whether a given window is a wrapper window and, if so,\n *\treturns the toplevel window corresponding to the wrapper.\n *\n * Results:\n *\tIf winPtr is a wrapper window, returns a pointer to the corresponding\n *\ttoplevel window; otherwise returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkWmFocusToplevel(\n    TkWindow *winPtr)\t\t/* Window that received a focus-related\n\t\t\t\t * event. */\n{\n    if (!(winPtr->flags & TK_WRAPPER)) {\n\treturn NULL;\n    }\n    return winPtr->wmInfoPtr->winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkUnixSetMenubar --\n *\n *\tThis function is invoked by menu management code to specify the window\n *\tto use as a menubar for a given toplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window given by menubar will be mapped and positioned inside the\n *\twrapper for tkwin and above tkwin. Menubar will automatically be\n *\tresized to maintain the height specified by TkUnixSetMenuHeight the\n *\tsame width as tkwin. Any previous menubar specified for tkwin will be\n *\tunmapped and ignored from now on.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkUnixSetMenubar(\n    Tk_Window tkwin,\t\t/* Token for toplevel window. */\n    Tk_Window menubar)\t\t/* Token for window that is to serve as\n\t\t\t\t * menubar for tkwin. Must not be a toplevel\n\t\t\t\t * window. If NULL, any existing menubar is\n\t\t\t\t * canceled and the menu height is reset to\n\t\t\t\t * 0. */\n{\n    WmInfo *wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;\n    Tk_Window parent;\n    TkWindow *menubarPtr = (TkWindow *) menubar;\n\n    /*\n     * Could be a Frame (i.e. not a toplevel).\n     */\n\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if (wmPtr->menubar != NULL) {\n\t/*\n\t * There's already a menubar for this toplevel. If it isn't the same\n\t * as the new menubar, unmap it so that it is out of the way, and\n\t * reparent it back to its original parent.\n\t */\n\n\tif (wmPtr->menubar == menubar) {\n\t    return;\n\t}\n\t((TkWindow *) wmPtr->menubar)->wmInfoPtr = NULL;\n\t((TkWindow *) wmPtr->menubar)->flags &= ~TK_REPARENTED;\n\tTk_UnmapWindow(wmPtr->menubar);\n\tparent = Tk_Parent(wmPtr->menubar);\n\tif (parent != NULL) {\n\t    Tk_MakeWindowExist(parent);\n\t    XReparentWindow(Tk_Display(wmPtr->menubar),\n\t\t    Tk_WindowId(wmPtr->menubar), Tk_WindowId(parent), 0, 0);\n\t}\n\tTk_DeleteEventHandler(wmPtr->menubar, StructureNotifyMask,\n\t\tMenubarDestroyProc, wmPtr->menubar);\n\tTk_ManageGeometry(wmPtr->menubar, NULL, NULL);\n    }\n\n    wmPtr->menubar = menubar;\n    if (menubar == NULL) {\n\twmPtr->menuHeight = 0;\n    } else {\n\tif ((menubarPtr->flags & TK_TOP_LEVEL)\n\t\t|| (Tk_Screen(menubar) != Tk_Screen(tkwin))) {\n\t    Tcl_Panic(\"TkUnixSetMenubar got bad menubar\");\n\t}\n\twmPtr->menuHeight = Tk_ReqHeight(menubar);\n\tif (wmPtr->menuHeight == 0) {\n\t    wmPtr->menuHeight = 1;\n\t}\n\tTk_MakeWindowExist(tkwin);\n\tTk_MakeWindowExist(menubar);\n\tif (wmPtr->wrapperPtr == NULL) {\n\t    CreateWrapper(wmPtr);\n\t}\n\tXReparentWindow(Tk_Display(menubar), Tk_WindowId(menubar),\n\t\twmPtr->wrapperPtr->window, 0, 0);\n\tmenubarPtr->wmInfoPtr = wmPtr;\n\tTk_MoveResizeWindow(menubar, 0, 0, Tk_Width(tkwin), wmPtr->menuHeight);\n\tTk_MapWindow(menubar);\n\tTk_CreateEventHandler(menubar, StructureNotifyMask,\n\t\tMenubarDestroyProc, menubar);\n\tTk_ManageGeometry(menubar, &menubarMgrType, wmPtr);\n\tmenubarPtr->flags |= TK_REPARENTED;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, tkwin);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenubarDestroyProc --\n *\n *\tThis function is invoked by the event dispatcher whenever a menubar\n *\twindow is destroyed (it's also invoked for a few other kinds of\n *\tevents, but we ignore those).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe association between the window and its toplevel is broken, so that\n *\tthe window is no longer considered to be a menubar.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenubarDestroyProc(\n    void *clientData,\t/* TkWindow pointer for menubar. */\n    XEvent *eventPtr)\t\t/* Describes what just happened. */\n{\n    WmInfo *wmPtr;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n    wmPtr = ((TkWindow *) clientData)->wmInfoPtr;\n    wmPtr->menubar = NULL;\n    wmPtr->menuHeight = 0;\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, wmPtr->winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenubarReqProc --\n *\n *\tThis function is invoked by the Tk geometry management code whenever a\n *\tmenubar calls Tk_GeometryRequest to request a new size.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenubarReqProc(\n    void *clientData,\t/* Pointer to the window manager information\n\t\t\t\t * for tkwin's toplevel. */\n    Tk_Window tkwin)\t\t/* Handle for menubar window. */\n{\n    WmInfo *wmPtr = (WmInfo *)clientData;\n\n    wmPtr->menuHeight = Tk_ReqHeight(tkwin);\n    if (wmPtr->menuHeight <= 0) {\n\twmPtr->menuHeight = 1;\n    }\n    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, wmPtr->winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetWrapperWindow --\n *\n *\tGiven a toplevel window return the hidden wrapper window for the\n *\ttoplevel window if available.\n *\n * Results:\n *\tThe wrapper window. NULL is we were not passed a toplevel window or\n *\tthe wrapper has yet to be created.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkpGetWrapperWindow(\n    TkWindow *winPtr)\t\t/* A toplevel window pointer. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if ((winPtr == NULL) || (wmPtr == NULL)) {\n\treturn NULL;\n    }\n\n    return wmPtr->wrapperPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateCommand --\n *\n *\tUpdate the WM_COMMAND property, taking care to translate the command\n *\tstrings into the external encoding.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateCommand(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tcl_DString cmds, ds;\n    Tcl_Size i;\n    int *offsets;\n    char **cmdArgv;\n\n    /*\n     * Translate the argv strings into the external encoding. To avoid\n     * allocating lots of memory, the strings are appended to a buffer with\n     * nulls between each string.\n     *\n     * This code is tricky because we need to pass and array of pointers to\n     * XSetCommand. However, we can't compute the pointers as we go because\n     * the DString buffer space could get reallocated. So, store offsets for\n     * each element as we go, then compute pointers from the offsets once the\n     * entire DString is done.\n     */\n\n    cmdArgv = (char **)Tcl_Alloc(sizeof(char *) * wmPtr->cmdArgc);\n    offsets = (int *)Tcl_Alloc(sizeof(int) * wmPtr->cmdArgc);\n    Tcl_DStringInit(&cmds);\n    for (i = 0; i < wmPtr->cmdArgc; i++) {\n\t(void)Tcl_UtfToExternalDString(NULL, wmPtr->cmdArgv[i], TCL_INDEX_NONE, &ds);\n\toffsets[i] = Tcl_DStringLength(&cmds);\n\tTcl_DStringAppend(&cmds, Tcl_DStringValue(&ds),\n\t\tTcl_DStringLength(&ds)+1);\n\tTcl_DStringFree(&ds);\n    }\n    cmdArgv[0] = Tcl_DStringValue(&cmds);\n    for (i = 1; i < wmPtr->cmdArgc; i++) {\n\tcmdArgv[i] = cmdArgv[0] + offsets[i];\n    }\n\n    XSetCommand(winPtr->display, wmPtr->wrapperPtr->window,\n\t    cmdArgv, wmPtr->cmdArgc);\n    Tcl_DStringFree(&cmds);\n    Tcl_Free(cmdArgv);\n    Tcl_Free(offsets);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWmSetState --\n *\n *\tSets the window manager state for the wrapper window of a given\n *\ttoplevel window.\n *\n * Results:\n *\t0 on error, 1 otherwise\n *\n * Side effects:\n *\tMay minimize, restore, or withdraw a window.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkpWmSetState(\n     TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n     int state)\t\t\t/* One of IconicState, NormalState, or\n\t\t\t\t * WithdrawnState. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (state == WithdrawnState) {\n\twmPtr->hints.initial_state = WithdrawnState;\n\twmPtr->withdrawn = 1;\n\tif (wmPtr->flags & WM_NEVER_MAPPED) {\n\t    return true;\n\t}\n\tif (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window,\n\t\twinPtr->screenNum) == 0) {\n\t    return false;\n\t}\n\tWaitForMapNotify(winPtr, 0);\n    } else if (state == NormalState) {\n\twmPtr->hints.initial_state = NormalState;\n\twmPtr->withdrawn = 0;\n\tif (wmPtr->flags & WM_NEVER_MAPPED) {\n\t    return true;\n\t}\n\tUpdateHints(winPtr);\n\tTk_MapWindow((Tk_Window) winPtr);\n    } else if (state == IconicState) {\n\twmPtr->hints.initial_state = IconicState;\n\tif (wmPtr->flags & WM_NEVER_MAPPED) {\n\t    return true;\n\t}\n\tif (wmPtr->withdrawn) {\n\t    UpdateHints(winPtr);\n\t    Tk_MapWindow((Tk_Window) winPtr);\n\t    wmPtr->withdrawn = 0;\n\t} else {\n\t    if (XIconifyWindow(winPtr->display, wmPtr->wrapperPtr->window,\n\t\t    winPtr->screenNum) == 0) {\n\t\treturn false;\n\t    }\n\t    WaitForMapNotify(winPtr, 0);\n\t}\n    }\n\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemapWindows\n *\n *\tAdjust parent/child relationships of the given window hierarchy.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tKeeps windowing system (X11) happy\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemapWindows(\n    TkWindow *winPtr,\n    TkWindow *parentPtr)\n{\n    XWindowAttributes win_attr;\n\n    if (winPtr->window) {\n\tXGetWindowAttributes(winPtr->display, winPtr->window, &win_attr);\n\tif (parentPtr == NULL) {\n\t    XReparentWindow(winPtr->display, winPtr->window,\n\t\t    XRootWindow(winPtr->display, winPtr->screenNum),\n\t\t    win_attr.x, win_attr.y);\n\t} else if (parentPtr->window) {\n\t    XReparentWindow(parentPtr->display, winPtr->window,\n\t\t    parentPtr->window,\n\t\t    win_attr.x, win_attr.y);\n\t}\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "unix/tkUnixXId.c",
    "content": "/*\n * tkUnixXId.c --\n *\n * Copyright © 1993 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkUnixInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetPixmap --\n *\n *\tSame as the XCreatePixmap function except that it manages resource\n *\tidentifiers better.\n *\n * Results:\n *\tReturns a new pixmap.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetPixmap(\n    Display *display,\t\t/* Display for new pixmap. */\n    Drawable d,\t\t\t/* Drawable where pixmap will be used. */\n    int width, int height,\t/* Dimensions of pixmap. */\n    int depth)\t\t\t/* Bits per pixel for pixmap. */\n{\n    return XCreatePixmap(display, d, (unsigned) width, (unsigned) height,\n\t    (unsigned) depth);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreePixmap --\n *\n *\tSame as the XFreePixmap function except that it also marks the\n *\tresource identifier as free.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe pixmap is freed in the X server and its resource identifier is\n *\tsaved for re-use.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreePixmap(\n    Display *display,\t\t/* Display for which pixmap was allocated. */\n    Pixmap pixmap)\t\t/* Identifier for pixmap. */\n{\n    XFreePixmap(display, pixmap);\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpScanWindowId --\n *\n *\tGiven a string, produce the corresponding Window Id.\n *\n * Results:\n *\tThe return value is normally TCL_OK; in this case *idPtr will be set\n *\tto the Window value equivalent to string. If string is improperly\n *\tformed then TCL_ERROR is returned and an error message will be left in\n *\tthe interp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpScanWindowId(\n    Tcl_Interp *interp,\n    const char *string,\n    Window *idPtr)\n{\n    int code;\n    Tcl_Obj obj;\n\n    obj.refCount = 1;\n    obj.bytes = (char *) string;\t/* DANGER?! */\n    obj.length = strlen(string);\n    obj.typePtr = NULL;\n\n    code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr);\n\n    if (obj.refCount > 1) {\n\tTcl_Panic(\"invalid sharing of Tcl_Obj on C stack\");\n    }\n    if (obj.typePtr && obj.typePtr->freeIntRepProc) {\n\tobj.typePtr->freeIntRepProc(&obj);\n    }\n    return code;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/Makefile.in",
    "content": "#\n# This file is a Makefile for Tk.  If it has the name \"Makefile.in\" then it\n# is a template for a Makefile; to generate the actual Makefile, run\n# \"./configure\", which is a configuration script generated by the \"autoconf\"\n# program (constructs like \"@foo@\" will get replaced in the actual Makefile.\n\nTCLVERSION\t\t= @TCL_VERSION@\nTCLPATCHL\t\t= @TCL_PATCH_LEVEL@\nVERSION\t\t\t= @TK_VERSION@\nPATCH_LEVEL\t\t= @TK_PATCH_LEVEL@\n\n#--------------------------------------------------------------------------\n# Things you can change to personalize the Makefile for your own site (you can\n# make these changes in either Makefile.in or Makefile, but changes to\n# Makefile will get lost if you re-run the configuration script).\n#--------------------------------------------------------------------------\n\n# Default top-level directories in which to install architecture-specific\n# files (exec_prefix) and machine-independent files such as scripts (prefix).\n# The values specified here may be overridden at configure-time with the\n# --exec-prefix and --prefix options to the \"configure\" script.\n\nprefix\t\t\t= @prefix@\nexec_prefix\t\t= @exec_prefix@\nbindir\t\t\t= @bindir@\nlibdir\t\t\t= @libdir@\nincludedir\t\t= @includedir@\ndatarootdir\t\t= @datarootdir@\nrunstatedir\t\t= @runstatedir@\nmandir\t\t\t= @mandir@\n\n# The following definition can be set to non-null for special systems like AFS\n# with replication. It allows the pathnames used for installation to be\n# different than those used for actually reference files at run-time.\n# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.\nINSTALL_ROOT\t=\n\n# Directory from which applications will reference the library of Tk scripts\n# (note: you can set the TK_LIBRARY environment variable at run-time to\n# override this value):\nTK_LIBRARY\t= $(prefix)/lib/tk$(VERSION)\n\n# Path to use at runtime to refer to LIB_INSTALL_DIR:\nLIB_RUNTIME_DIR\t\t= $(libdir)\n\n# Directory in which to install the program wish:\nBIN_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(bindir)\n\n# Directory in which to install the .a or .so binary for the Tk library:\nLIB_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(libdir)\n\n# Path name to use when installing library scripts:\nSCRIPT_INSTALL_DIR\t= $(INSTALL_ROOT)$(TK_LIBRARY)\n\n# Directory in which to install the include file tk.h:\nINCLUDE_INSTALL_DIR\t= $(INSTALL_ROOT)$(includedir)\n\n# Directory in which to (optionally) install the private tk headers:\nPRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)\n\n# Top-level directory in which to install manual entries:\nMAN_INSTALL_DIR\t\t= $(INSTALL_ROOT)$(mandir)\n\n# Directory in which to install manual entry for wish:\nMAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1\n\n# Directory in which to install manual entries for Tk's C library\n# procedures:\nMAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3\n\n# Directory in which to install manual entries for the built-in Tk commands:\nMANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann\n\n# Directory in which to install the pkgIndex.tcl file for loadable Tk\nPKG_INSTALL_DIR\t\t= $(LIB_INSTALL_DIR)/tk$(VERSION)\n\n# Package index file for loadable Tk\nPKG_INDEX\t\t= $(PKG_INSTALL_DIR)/pkgIndex.tcl\n\n# The directory containing the Tcl source and header files.\nTCL_SRC_DIR\t\t= @TCL_SRC_DIR@\n\n# The directory containing the Tcl library archive file appropriate\n# for this version of Tk:\nTCL_BIN_DIR\t\t= @TCL_BIN_DIR@\n\n# The directory containing the Tcl sources and headers appropriate\n# for this version of Tk (\"srcdir\" will be replaced or has already\n# been replaced by the configure script):\nTCL_GENERIC_DIR\t\t= @TCL_SRC_DIR@/generic\n\n# The directory containing the platform specific Tcl sources and headers\n# appropriate for this version of Tk:\nTCL_PLATFORM_DIR\t= @TCL_SRC_DIR@/win\n\nTCL_TOOL_DIR\t\t= @TCL_SRC_DIR@/tools\n\nSRC_DIR\t\t\t= @srcdir@\nROOT_DIR\t\t= @srcdir@/..\nTOP_DIR\t\t\t= $(shell cd @srcdir@/..; pwd -W 2>/dev/null || pwd -P)\nWIN_DIR\t\t\t= $(TOP_DIR)/win\nUNIX_DIR\t\t= $(TOP_DIR)/unix\nGENERIC_DIR\t\t= $(TOP_DIR)/generic\nTTK_DIR\t\t\t= $(GENERIC_DIR)/ttk\nBITMAP_DIR\t\t= $(TOP_DIR)/bitmaps\nXLIB_DIR\t\t= $(TOP_DIR)/xlib\nRC_DIR\t\t\t= $(WIN_DIR)/rc\n\n# Converts a POSIX path to a Windows native path.\nCYGPATH\t\t\t= @CYGPATH@\n\n# The name of the Tcl library.\nTCL_LIB_FILE\t  = \"$(shell $(CYGPATH) '@TCL_BIN_DIR@/@TCL_LIB_FILE@')\"\nTCL_STUB_LIB_FILE = \"$(shell $(CYGPATH) '@TCL_BIN_DIR@/@TCL_STUB_LIB_FILE@')\"\n\nROOT_DIR_NATIVE\t\t= $(shell $(CYGPATH) '$(ROOT_DIR)')\nWIN_DIR_NATIVE\t\t= $(shell $(CYGPATH) '$(WIN_DIR)')\nGENERIC_DIR_NATIVE\t= $(shell $(CYGPATH) '$(GENERIC_DIR)')\nBITMAP_DIR_NATIVE\t= $(shell $(CYGPATH) '$(ROOT_DIR)/bitmaps')\nXLIB_DIR_NATIVE\t= $(shell $(CYGPATH) '$(ROOT_DIR)/xlib')\nRC_DIR_NATIVE\t= $(shell $(CYGPATH) '$(ROOT_DIR)/rc')\nTCL_GENERIC_NATIVE\t\t= $(shell $(CYGPATH) '$(TCL_GENERIC_DIR)')\nTCL_PLATFORM_NATIVE\t\t= $(shell $(CYGPATH) '$(TCL_PLATFORM_DIR)')\nTCL_SRC_DIR_NATIVE\t\t= $(shell $(CYGPATH) '$(TCL_SRC_DIR)')\n\nDLLSUFFIX\t\t= @DLLSUFFIX@\nLIBSUFFIX\t\t= @LIBSUFFIX@\nEXESUFFIX\t\t= @EXESUFFIX@\nTCLVER\t\t\t= @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@\nVER\t\t\t= @TK_MAJOR_VERSION@@TK_MINOR_VERSION@\nDOTVER\t\t\t= @TK_MAJOR_VERSION@.@TK_MINOR_VERSION@\n\nTK_ZIP_FILE\t\t= @TK_ZIP_FILE@\nTK_VFS_PATH\t\t= libtk.vfs/tk_library\nTK_VFS_ROOT\t\t= libtk.vfs\n\nTK_STUB_LIB_FILE\t= @TK_STUB_LIB_FILE@\nTK_LIB_FILE\t\t= @TK_LIB_FILE@\nTK_DLL_FILE\t\t= @TK_DLL_FILE@\nTEST_DLL_FILE\t\t= tktest$(VER)${DLLSUFFIX}\nTEST_LIB_FILE\t\t= @LIBPREFIX@tktest$(VER)${DLLSUFFIX}${LIBSUFFIX}\n\nSHARED_LIBRARIES\t= $(TK_DLL_FILE) $(TK_STUB_LIB_FILE)\nSTATIC_LIBRARIES\t= $(TK_LIB_FILE)\n\nWISH\t\t\t= wish$(VER)${EXESUFFIX}\nTKTEST\t\t\t= tktest${EXESUFFIX}\nCAT32\t\t\t= cat32${EXESUFFIX}\nMAN2TCL\t\t\t= man2tcl${EXESUFFIX}\n\n@SET_MAKE@\n\n# Setting the VPATH variable to a list of paths will cause the\n# makefile to look into these paths when resolving .c to .obj\n# dependencies.\n\nVPATH = $(GENERIC_DIR):$(TTK_DIR):$(WIN_DIR):$(XLIB_DIR):$(RC_DIR)\n\n# warning flags\nCFLAGS_WARNING\t= @CFLAGS_WARNING@\n\n# The default switches for optimization or debugging\nCFLAGS_DEBUG    = @CFLAGS_DEBUG@\nCFLAGS_OPTIMIZE\t= @CFLAGS_OPTIMIZE@\n\n# The default switches for optimization or debugging\nLDFLAGS_DEBUG    = @LDFLAGS_DEBUG@\nLDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@\n\n# To change the compiler switches, for example to change from optimization to\n# debugging symbols, change the following line:\n#CFLAGS\t\t= $(CFLAGS_DEBUG)\n#CFLAGS\t\t= $(CFLAGS_OPTIMIZE)\n#CFLAGS\t\t= $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)\nCFLAGS\t\t= @CFLAGS@ @CFLAGS_DEFAULT@ -D__USE_MINGW_ANSI_STDIO=0\n\n# Special compiler flags to use when building man2tcl on Windows.\nMAN2TCLFLAGS\t= @MAN2TCLFLAGS@\n\nAR\t\t= @AR@\nRANLIB\t\t= @RANLIB@\nCC\t\t= @CC@\nRC\t\t= @RC@\nRES\t\t= @RES@\nTK_RES\t\t= @TK_RES@\nAC_FLAGS\t= @EXTRA_CFLAGS@ @DEFS@\nCPPFLAGS\t= @CPPFLAGS@\nLDFLAGS\t\t= @LDFLAGS@ @LDFLAGS_DEFAULT@\nLDFLAGS_CONSOLE\t= @LDFLAGS_CONSOLE@\nLDFLAGS_WINDOW\t= @LDFLAGS_WINDOW@\nOBJEXT\t\t= @OBJEXT@\nSTLIB_LD\t= @STLIB_LD@\nSHLIB_LD\t= @SHLIB_LD@\nSHLIB_LD_LIBS\t= @SHLIB_LD_LIBS@\nSHLIB_CFLAGS\t= @SHLIB_CFLAGS@\nSHLIB_SUFFIX\t= @SHLIB_SUFFIX@\nLIBS\t\t= $(TCL_STUB_LIB_FILE) @LIBS@ @LIBS_GUI@\nRMDIR\t\t= rm -rf\nMKDIR\t\t= mkdir -p\nSHELL\t\t= @SHELL@\nRM\t\t= rm -f\nCOPY\t\t= cp\nLN\t\t= ln\n\n# Tk does not used deprecated Tcl constructs so it should\n# compile fine with -DTCL_NO_DEPRECATED. To remove its own\n# set of deprecated code uncomment the second line.\nNO_DEPRECATED_FLAGS\t=\n#NO_DEPRECATED_FLAGS\t= -DTCL_NO_DEPRECATED -DTK_NO_DEPRECATED\n\n# TCL_EXE is the name of a tclsh executable that is available *BEFORE*\n# running make for the first time. Certain build targets (make genstubs)\n# need it to be available on the PATH. This executable should *NOT* be\n# required just to do a normal build although it can be required to run\n# make dist.\nTCL_EXE\t\t\t= @TCLSH_PROG@\nWINE\t\t= @WINE@\n\n###\n# Tip 430 - ZipFS Modifications\n###\n\nTK_ZIP_FILE\t\t= @TK_ZIP_FILE@\nTK_VFS_PATH\t\t= libtk.vfs/tk_library\nTK_VFS_ROOT\t\t= libtk.vfs\n\nHOST_CC\t\t        = @CC_FOR_BUILD@\nHOST_EXEEXT             = @EXEEXT_FOR_BUILD@\nHOST_OBJEXT             = @OBJEXT_FOR_BUILD@\nZIPFS_BUILD\t        = @ZIPFS_BUILD@\nNATIVE_ZIP\t\t= @ZIP_PROG@\nZIP_PROG_OPTIONS\t\t= @ZIP_PROG_OPTIONS@\nZIP_PROG_VFSSEARCH  = @ZIP_PROG_VFSSEARCH@\nSHARED_BUILD\t\t= @SHARED_BUILD@\nINSTALL_MSGS            = @INSTALL_MSGS@\nINSTALL_LIBRARIES       = @INSTALL_LIBRARIES@\n\n# Minizip\nMINIZIP_OBJS = \\\n\tadler32.$(HOST_OBJEXT) \\\n\tcompress.$(HOST_OBJEXT) \\\n\tcrc32.$(HOST_OBJEXT) \\\n\tdeflate.$(HOST_OBJEXT) \\\n\tinfback.$(HOST_OBJEXT) \\\n\tinffast.$(HOST_OBJEXT) \\\n\tinflate.$(HOST_OBJEXT) \\\n\tinftrees.$(HOST_OBJEXT) \\\n\tioapi.$(HOST_OBJEXT) \\\n\tiowin32.$(HOST_OBJEXT)  \\\n\ttrees.$(HOST_OBJEXT) \\\n\tuncompr.$(HOST_OBJEXT) \\\n\tzip.$(HOST_OBJEXT) \\\n\tzutil.$(HOST_OBJEXT) \\\n\tminizip.$(HOST_OBJEXT)\n\nZIP_INSTALL_OBJS =  @ZIP_INSTALL_OBJS@\n\nCC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \\\n-I\"${GENERIC_DIR_NATIVE}\" -I\"${WIN_DIR_NATIVE}\" \\\n-I\"${XLIB_DIR_NATIVE}\" -I\"${BITMAP_DIR_NATIVE}\" \\\n-I\"${TCL_GENERIC_NATIVE}\" -I\"${TCL_PLATFORM_NATIVE}\" \\\n${AC_FLAGS} $(NO_DEPRECATED_FLAGS) -DUSE_TCL_STUBS\n\nCC_OBJNAME = @CC_OBJNAME@\nCC_EXENAME = @CC_EXENAME@\n\n# Tk used to let the configure script choose which program to use\n# for installing, but there are just too many different versions of\n# \"install\" around;  better to use the install-sh script that comes\n# with the distribution, which is slower but guaranteed to work.\n\nINSTALL\t\t= cp\nINSTALL_PROGRAM = ${INSTALL}\nINSTALL_DATA\t= ${INSTALL}\n\nWISH_OBJS = \\\n\twinMain.$(OBJEXT)\n\nTKTEST_OBJS = \\\n\ttkSquare.$(OBJEXT) \\\n\ttkTest.$(OBJEXT) \\\n\ttkWinTest.$(OBJEXT)\n\nXLIB_OBJS = \\\n\txcolors.$(OBJEXT) \\\n\txdraw.$(OBJEXT) \\\n\txgc.$(OBJEXT) \\\n\tximage.$(OBJEXT) \\\n\txutil.$(OBJEXT)\n\nTK_OBJS = \\\n\ttkWinAccessibility.$(OBJEXT) \\\n\ttkConsole.$(OBJEXT) \\\n\ttkUnixMenubu.$(OBJEXT) \\\n\ttkUnixScale.$(OBJEXT) \\\n\t$(XLIB_OBJS) \\\n\ttkWin3d.$(OBJEXT) \\\n\ttkWin32Dll.$(OBJEXT) \\\n\ttkWinButton.$(OBJEXT) \\\n\ttkWinClipboard.$(OBJEXT) \\\n\ttkWinColor.$(OBJEXT) \\\n\ttkWinConfig.$(OBJEXT) \\\n\ttkWinCursor.$(OBJEXT) \\\n\ttkWinDialog.$(OBJEXT) \\\n\ttkWinDraw.$(OBJEXT) \\\n\ttkWinEmbed.$(OBJEXT) \\\n\ttkWinFont.$(OBJEXT) \\\n\ttkWinGDI.$(OBJEXT) \\\n\ttkWinIco.$(OBJEXT) \\\n\ttkWinImage.$(OBJEXT) \\\n\ttkWinInit.$(OBJEXT) \\\n\ttkWinKey.$(OBJEXT) \\\n\ttkWinMenu.$(OBJEXT) \\\n\ttkWinPixmap.$(OBJEXT) \\\n\ttkWinPointer.$(OBJEXT) \\\n\ttkWinRegion.$(OBJEXT) \\\n\ttkWinScrlbr.$(OBJEXT) \\\n\ttkWinSend.$(OBJEXT) \\\n\ttkWinSendCom.$(OBJEXT) \\\n\ttkWinSysTray.$(OBJEXT) \\\n\ttkWinWindow.$(OBJEXT) \\\n\ttkWinWm.$(OBJEXT) \\\n\ttkWinX.$(OBJEXT) \\\n\tstubs.$(OBJEXT) \\\n\ttk3d.$(OBJEXT) \\\n\ttkAccessibility.$(OBJEXT) \\\n\ttkArgv.$(OBJEXT) \\\n\ttkAtom.$(OBJEXT) \\\n\ttkBind.$(OBJEXT) \\\n\ttkBitmap.$(OBJEXT) \\\n\ttkBusy.$(OBJEXT) \\\n\ttkButton.$(OBJEXT) \\\n\ttkCanvArc.$(OBJEXT) \\\n\ttkCanvBmap.$(OBJEXT) \\\n\ttkCanvImg.$(OBJEXT) \\\n\ttkCanvLine.$(OBJEXT) \\\n\ttkCanvPoly.$(OBJEXT) \\\n\ttkCanvPs.$(OBJEXT) \\\n\ttkCanvText.$(OBJEXT) \\\n\ttkCanvUtil.$(OBJEXT) \\\n\ttkCanvWind.$(OBJEXT) \\\n\ttkCanvas.$(OBJEXT) \\\n\ttkClipboard.$(OBJEXT) \\\n\ttkCmds.$(OBJEXT) \\\n\ttkColor.$(OBJEXT) \\\n\ttkConfig.$(OBJEXT) \\\n\ttkCursor.$(OBJEXT) \\\n\ttkEntry.$(OBJEXT) \\\n\ttkError.$(OBJEXT) \\\n\ttkEvent.$(OBJEXT) \\\n\ttkFileFilter.$(OBJEXT) \\\n\ttkFocus.$(OBJEXT) \\\n\ttkFont.$(OBJEXT) \\\n\ttkFrame.$(OBJEXT) \\\n\ttkGC.$(OBJEXT) \\\n\ttkGeometry.$(OBJEXT) \\\n\ttkGet.$(OBJEXT) \\\n\ttkGrab.$(OBJEXT) \\\n\ttkGrid.$(OBJEXT) \\\n\ttkIcu.$(OBJEXT) \\\n\ttkImage.$(OBJEXT) \\\n\ttkImgBmap.$(OBJEXT) \\\n\ttkImgListFormat.$(OBJEXT) \\\n\ttkImgGIF.$(OBJEXT) \\\n\ttkImgPNG.$(OBJEXT) \\\n\ttkImgPPM.$(OBJEXT) \\\n\ttkImgSVGnano.$(OBJEXT) \\\n\ttkImgPhoto.$(OBJEXT) \\\n\ttkImgPhInstance.$(OBJEXT) \\\n\ttkImgUtil.$(OBJEXT) \\\n\ttkListbox.$(OBJEXT) \\\n\ttkMacWinMenu.$(OBJEXT) \\\n\ttkMain.$(OBJEXT) \\\n\ttkMain2.$(OBJEXT) \\\n\ttkMenu.$(OBJEXT) \\\n\ttkMenubutton.$(OBJEXT) \\\n\ttkMenuDraw.$(OBJEXT) \\\n\ttkMessage.$(OBJEXT) \\\n\ttkPanedWindow.$(OBJEXT) \\\n\ttkObj.$(OBJEXT) \\\n\ttkOldConfig.$(OBJEXT) \\\n\ttkOption.$(OBJEXT) \\\n\ttkPack.$(OBJEXT) \\\n\ttkPkgConfig.$(OBJEXT) \\\n\ttkPlace.$(OBJEXT) \\\n\ttkPointer.$(OBJEXT) \\\n\ttkRectOval.$(OBJEXT) \\\n\ttkScale.$(OBJEXT) \\\n\ttkScrollbar.$(OBJEXT) \\\n\ttkSelect.$(OBJEXT) \\\n\ttkStyle.$(OBJEXT) \\\n\ttkText.$(OBJEXT) \\\n\ttkTextBTree.$(OBJEXT) \\\n\ttkTextDisp.$(OBJEXT) \\\n\ttkTextImage.$(OBJEXT) \\\n\ttkTextIndex.$(OBJEXT) \\\n\ttkTextMark.$(OBJEXT) \\\n\ttkTextTag.$(OBJEXT) \\\n\ttkTextWind.$(OBJEXT) \\\n\ttkTrig.$(OBJEXT) \\\n\ttkUndo.$(OBJEXT) \\\n\ttkUtil.$(OBJEXT) \\\n\ttkVisual.$(OBJEXT) \\\n\ttkStubInit.$(OBJEXT) \\\n\ttkWindow.$(OBJEXT) \\\n\t$(TTK_OBJS)\n\nTTK_OBJS = \\\n\tttkWinMonitor.$(OBJEXT) \\\n\tttkWinTheme.$(OBJEXT) \\\n\tttkWinVistaTheme.$(OBJEXT) \\\n\tttkBlink.$(OBJEXT) \\\n\tttkButton.$(OBJEXT) \\\n\tttkCache.$(OBJEXT) \\\n\tttkClamTheme.$(OBJEXT) \\\n\tttkClassicTheme.$(OBJEXT) \\\n\tttkDefaultTheme.$(OBJEXT) \\\n\tttkElements.$(OBJEXT) \\\n\tttkEntry.$(OBJEXT) \\\n\tttkFrame.$(OBJEXT) \\\n\tttkImage.$(OBJEXT) \\\n\tttkInit.$(OBJEXT) \\\n\tttkLabel.$(OBJEXT) \\\n\tttkLayout.$(OBJEXT) \\\n\tttkManager.$(OBJEXT) \\\n\tttkNotebook.$(OBJEXT) \\\n\tttkPanedwindow.$(OBJEXT) \\\n\tttkProgress.$(OBJEXT) \\\n\tttkScale.$(OBJEXT) \\\n\tttkScrollbar.$(OBJEXT) \\\n\tttkScroll.$(OBJEXT) \\\n\tttkSeparator.$(OBJEXT) \\\n\tttkSquare.$(OBJEXT) \\\n\tttkState.$(OBJEXT) \\\n\tttkTagSet.$(OBJEXT) \\\n\tttkTheme.$(OBJEXT) \\\n\tttkToggleswitch.$(OBJEXT) \\\n\tttkTrace.$(OBJEXT) \\\n\tttkTrack.$(OBJEXT) \\\n\tttkTreeview.$(OBJEXT) \\\n\tttkWidget.$(OBJEXT) \\\n\tttkStubInit.$(OBJEXT)\n\nSTUB_OBJS = \\\n\ttkStubLib.$(OBJEXT) \\\n\tttkStubLib.$(OBJEXT)\n\nTCL_DOCS = \"$(TCL_SRC_DIR_NATIVE)/doc/*.[13n]\"\nTK_DOCS = \"$(ROOT_DIR_NATIVE)/doc/*.[13n]\"\nCORE_DOCS = $(TCL_DOCS) $(TK_DOCS)\n\nDEMOPROGS = browse hello ixset rmt rolodex square tcolor timer widget\n\nSHELL_ENV = \\\n\t@TCL_LIBRARY=\"$(TCL_SRC_DIR_NATIVE)/library\"; export TCL_LIBRARY; \\\n\tTK_LIBRARY=\"$(ROOT_DIR_NATIVE)/library\"; export TK_LIBRARY; \\\n\tPATH=\"$(TCL_BIN_DIR):$(PATH)\"; export PATH;\n\n# Main targets.  The default target -- all -- builds the binaries,\n# performs any post processing on libraries or documents.\n\nall: binaries libraries doc\n\nbinaries: @LIBRARIES@ $(WISH)\n\nlibraries:\n\n$(ROOT_DIR)/doc/man.macros:\n\t$(INSTALL_DATA) \"$(TCL_SRC_DIR)/doc/man.macros\" \"$(ROOT_DIR)/doc/man.macros\"\n\ndoc: $(ROOT_DIR)/doc/man.macros\n\nwinhelp: $(TCL_SRC_DIR)/tools/man2help.tcl $(MAN2TCL)\n\t$(TCL_EXE) \"$(TCL_SRC_DIR_NATIVE)/tools/man2help.tcl\" tcl \"$(VER)\" $(CORE_DOCS)\n\t$(COPY) \"$(TCL_BIN_DIR)/tcl.hpj\" ./\n\thcw /c /e tcl.hpj\n\t$(COPY) ./tcl$(VER).cnt ./TCL$(VER).HLP \"$(TCL_SRC_DIR_NATIVE)/tools/\"\n\n$(MAN2TCL): $(TCL_SRC_DIR)/tools/man2tcl.c\n\t$(CC) $(CFLAGS_OPTIMIZE) $(MAN2TCLFLAGS) -o $(MAN2TCL) \"$(TCL_SRC_DIR_NATIVE)/tools/man2tcl.c\"\n\n# Specifying TESTFLAGS on the command line is the standard way to pass\n# args to tcltest, ie:\n#\t% make test TESTFLAGS=\"-verbose bps -file fileName.test\"\n\ntest: test-classic test-ttk\n\ntest-classic: binaries $(TKTEST) $(TEST_DLL_FILE) $(CAT32)\n\t$(SHELL_ENV) $(WINE) ./$(TKTEST) \"$(ROOT_DIR_NATIVE)/tests/all.tcl\" \\\n\t$(TESTFLAGS) | $(WINE) ./$(CAT32)\n\ntest-ttk: binaries $(TKTEST) $(TEST_DLL_FILE) $(CAT32)\n\t$(SHELL_ENV) $(WINE) ./$(TKTEST) \"$(ROOT_DIR_NATIVE)/tests/ttk/all.tcl\" \\\n\t$(TESTFLAGS) | $(WINE) ./$(CAT32)\n\nruntest: binaries $(TKTEST) $(TEST_DLL_FILE)\n\t$(SHELL_ENV) $(WINE) ./$(TKTEST) $(TESTFLAGS) $(SCRIPT)\n\n# This target can be used to run wish from the build directory\n# via `make shell` or `make shell SCRIPT=foo.tcl`\nshell: binaries\n\t$(SHELL_ENV) $(WINE) ./$(WISH) $(SCRIPT)\n\ndemo: $(WISH)\n\t$(SHELL_ENV) $(WINE) ./$(WISH) $(ROOT_DIR)/library/demos/widget\n\n# This target can be used to run wish inside either gdb or insight\ngdb: binaries\n\t@echo \"set env TCL_LIBRARY=$(TCL_SRC_DIR_NATIVE)/library\" > gdb.run\n\t@echo \"set env TK_LIBRARY=$(ROOT_DIR_NATIVE)/library\" >> gdb.run\n\tPATH=\"$(TCL_BIN_DIR):$(PATH)\"; export PATH; \\\n\tgdb ./$(WISH) --command=gdb.run\n\t@$(RM) gdb.run\n\ninstall: all install-binaries install-libraries install-doc install-demos\n\ninstall-binaries: binaries\n\t@for i in $(LIB_INSTALL_DIR) $(BIN_INSTALL_DIR) $(PKG_INSTALL_DIR); \\\n\t    do \\\n\t    if [ ! -d $$i ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(MKDIR) $$i; \\\n\t\tchmod 755 $$i; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@for i in $(TK_DLL_FILE) $(WISH); \\\n\t    do \\\n\t    if [ -f $$i ]; then \\\n\t\techo \"Installing $$i to $(BIN_INSTALL_DIR)/\"; \\\n\t\t$(COPY) $$i \"$(BIN_INSTALL_DIR)\"; \\\n\t    fi; \\\n\t    done\n\t@echo \"Creating package index $(PKG_INDEX)\";\n\t@$(RM) $(PKG_INDEX);\n\t@(\\\n\techo \"if {![package vsatisfies [package provide Tcl] 9.0]} return\";\\\n\techo \"if {(\\$$::tcl_platform(platform) eq \\\"unix\\\") && ([info exists ::env(DISPLAY)]\";\\\n\techo \"\t|| ([info exists ::argv] && (\\\"-display\\\" in \\$$::argv)))} {\";\\\n\techo \"    package ifneeded tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \\$$dir .. .. bin cygtcl9tk$(VERSION).dll]]]\";\\\n\techo \"} else {\";\\\n\techo \"    package ifneeded tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \\$$dir .. .. bin $(TK_DLL_FILE)]]]\";\\\n\techo \"}\";\\\n\techo \"package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list package require -exact tk $(VERSION)$(PATCH_LEVEL)]\";\\\n\t) > $(PKG_INDEX);\n\t@for i in tkConfig.sh $(TK_LIB_FILE) $(TK_STUB_LIB_FILE); \\\n\t    do \\\n\t    if [ -f $$i ]; then \\\n\t\techo \"Installing $$i to $(LIB_INSTALL_DIR)/\"; \\\n\t\t$(COPY) $$i \"$(LIB_INSTALL_DIR)\"; \\\n\t    fi; \\\n\t    done\n\t@echo \"Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/\"\n\t@$(MKDIR) \"$(LIB_INSTALL_DIR)/pkgconfig\"\n\t@$(INSTALL_DATA) tk.pc \"$(LIB_INSTALL_DIR)/pkgconfig/tk.pc\"\n\ninstall-libraries: libraries\n\t@for i in \"$$($(CYGPATH) $(prefix)/lib)\" \\\n\t\t\"$(INCLUDE_INSTALL_DIR)\" \"$(INCLUDE_INSTALL_DIR)/X11\" \\\n\t\t\"$(SCRIPT_INSTALL_DIR)\" \"$(SCRIPT_INSTALL_DIR)/images\" \\\n\t\t\"$(SCRIPT_INSTALL_DIR)/msgs\" \"$(SCRIPT_INSTALL_DIR)/ttk\"; \\\n\t    do \\\n\t    if [ ! -d $$i ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(MKDIR) $$i; \\\n\t\tchmod 755 $$i; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing header files to $(INCLUDE_INSTALL_DIR)/\";\n\t@for i in \"$(GENERIC_DIR)/tk.h\" \"$(GENERIC_DIR)/tkPlatDecls.h\" \\\n\t\t\"$(GENERIC_DIR)/tkIntXlibDecls.h\" \"$(GENERIC_DIR)/tkDecls.h\" ; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR); \\\n\t    done;\n\t@for i in $(XLIB_DIR)/X11/*.h; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR)/X11; \\\n\t    done;\n\t@echo \"Installing library files to $(SCRIPT_INSTALL_DIR)\";\n\t@for i in $(ROOT_DIR)/library/*.tcl $(ROOT_DIR)/library/tclIndex \\\n\t\t$(UNIX_DIR)/tkAppInit.c; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR); \\\n\t    done;\n\t@echo \"Installing library ttk directory\";\n\t@for i in $(ROOT_DIR)/library/ttk/*.tcl; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/ttk; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing library images directory\";\n\t@for i in $(ROOT_DIR)/library/images/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/images; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing translation directory\";\n\t@for i in $(ROOT_DIR)/library/msgs/*.msg; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/msgs; \\\n\t    fi; \\\n\t    done;\n\ninstall-demos:\n\t@for i in $(INSTALL_ROOT)$(prefix)/lib $(SCRIPT_INSTALL_DIR) \\\n\t\t$(SCRIPT_INSTALL_DIR)/demos \\\n\t\t$(SCRIPT_INSTALL_DIR)/demos/images ; \\\n\t    do \\\n\t    if [ ! -d $$i ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(MKDIR) $$i; \\\n\t\tchmod 755 $$i; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing demos to $(SCRIPT_INSTALL_DIR)/demos/\";\n\t@for i in $(ROOT_DIR)/library/demos/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\tsed -e '3 s|exec wish|exec wish$(VER)|' \\\n\t\t\t$$i > $(SCRIPT_INSTALL_DIR)/demos/`basename $$i`; \\\n\t    fi; \\\n\t    done;\n\t@for i in $(DEMOPROGS); \\\n\t    do \\\n\t    if test $$i = \"square\"; then \\\n\t    rm -f  $(SCRIPT_INSTALL_DIR)/demos/$$i; \\\n\t    else \\\n\t    chmod 755 $(SCRIPT_INSTALL_DIR)/demos/$$i; \\\n\t    fi; \\\n\t    done;\n\t@echo \"Installing demo images\";\n\t@for i in $(ROOT_DIR)/library/demos/images/*; \\\n\t    do \\\n\t    if [ -f $$i ] ; then \\\n\t\t$(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/demos/images; \\\n\t\tfi; \\\n\t    done;\n\ninstall-doc: doc\n\t@for i in \"$(MAN_INSTALL_DIR)\" \"$(MAN1_INSTALL_DIR)\" \"$(MAN3_INSTALL_DIR)\" \"$(MANN_INSTALL_DIR)\" ; \\\n\t    do \\\n\t    if [ ! -d \"$$i\" ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\tmkdir -p \"$$i\"; \\\n\t\tchmod 755 \"$$i\"; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing and cross-linking top-level (.1) docs\";\n\t@for i in $(ROOT_DIR)/doc/*.1; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MAN1_INSTALL_DIR)\"; \\\n\tdone\n\t@echo \"Installing and cross-linking C API (.3) docs\";\n\t@for i in $(ROOT_DIR)/doc/*.3; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MAN3_INSTALL_DIR)\"; \\\n\tdone\n\t@echo \"Installing and cross-linking command (.n) docs\";\n\t@for i in $(ROOT_DIR)/doc/*.n; do \\\n\t    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i \"$(MANN_INSTALL_DIR)\"; \\\n\tdone\n\n# Optional target to install private headers\ninstall-private-headers: libraries\n\t@for i in $(PRIVATE_INCLUDE_INSTALL_DIR); \\\n\t    do \\\n\t    if [ ! -d $$i ] ; then \\\n\t\techo \"Making directory $$i\"; \\\n\t\t$(MKDIR) $$i; \\\n\t\tchmod 755 $$i; \\\n\t\telse true; \\\n\t\tfi; \\\n\t    done;\n\t@echo \"Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/\";\n\t@for i in \"$(GENERIC_DIR)/tkInt.h\" \"$(GENERIC_DIR)/tkIntDecls.h\" \\\n\t\t\"$(GENERIC_DIR)/tkIntPlatDecls.h\" \"$(GENERIC_DIR)/tkPort.h\" \\\n\t\t\"$(WIN_DIR)/tkWinPort.h\" \"$(WIN_DIR)/tkWinInt.h\" \"$(WIN_DIR)/tkWin.h\"; \\\n\t    do \\\n\t    $(INSTALL_DATA) $$i $(PRIVATE_INCLUDE_INSTALL_DIR); \\\n\t    done;\n\n$(WISH): $(WISH_OBJS) @LIBRARIES@ $(TK_STUB_LIB_FILE) wish.$(RES) ${TK_ZIP_FILE}\n\t$(CC) $(CFLAGS) $(WISH_OBJS) $(TK_LIB_FILE) \\\n\t$(TK_STUB_LIB_FILE) $(TCL_LIB_FILE) $(LIBS) \\\n\twish.$(RES) $(CC_EXENAME) $(LDFLAGS_WINDOW)\n\t@VC_MANIFEST_EMBED_EXE@\n\t@if test \"${ZIPFS_BUILD}\" = \"2\" ; then \\\n\t\tcat ${TK_ZIP_FILE} >> ${WISH}; \\\n\tfi\n\ntktest: $(TKTEST)\n\n$(TKTEST): testMain.$(OBJEXT) $(TEST_DLL_FILE) @LIBRARIES@ $(TK_STUB_LIB_FILE) wish.$(RES)\n\t$(CC) $(CFLAGS) testMain.$(OBJEXT) $(TEST_LIB_FILE) $(TK_LIB_FILE) \\\n\t$(TK_STUB_LIB_FILE) $(TCL_LIB_FILE) $(LIBS) \\\n\twish.$(RES) $(CC_EXENAME) $(LDFLAGS_WINDOW)\n\t@VC_MANIFEST_EMBED_EXE@\n\n${TEST_DLL_FILE}: ${TKTEST_OBJS} ${TK_STUB_LIB_FILE}\n\t@MAKE_DLL@ ${TKTEST_OBJS} $(TK_STUB_LIB_FILE) $(SHLIB_LD_LIBS)\n\n$(TOP_DIR)/manifest.uuid:\n\tprintf \"git-\" >$(TOP_DIR)/manifest.uuid\n\t(cd $(TOP_DIR); git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid || printf \"unknown\" >$(TOP_DIR)/manifest.uuid)\n\ntkUuid.h:\t$(TOP_DIR)/manifest.uuid\n\techo \"#define TK_VERSION_UUID \\\\\" >$@\n\tcat $(TOP_DIR)/manifest.uuid >>$@\n\techo \"\" >>$@\n\n# Msys make requires this next rule for some reason.\n$(TCL_SRC_DIR)/win/cat.c:\n\ncat32.${OBJEXT}: $(TCL_SRC_DIR)/win/cat.c\n\t$(CC) -c $(CC_SWITCHES) -DUNICODE -D_UNICODE \"$(TCL_SRC_DIR)/win/cat.c\" $(CC_OBJNAME)\n\n$(CAT32): cat32.${OBJEXT}\n\t$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)\n\ntkzipfile: ${TK_ZIP_FILE}\n\n${TK_ZIP_FILE}:  ${ZIP_INSTALL_OBJS}\n\t@$(RMDIR) ${TK_VFS_ROOT}\n\t@mkdir -p ${TK_VFS_PATH}\n\t@echo \"creating ${TK_VFS_PATH} (prepare compression)\"\n\t@( \\\n\t  $(COPY) -a $(TOP_DIR)/library/* ${TK_VFS_PATH}; \\\n\t)\n\t@$(RMDIR) $(TK_VFS_PATH)/demos\n\t-@if test \"${ZIPFS_BUILD}\" = \"2\" ; then \\\n\t    cp ${TCL_BIN_DIR}/tclsh${TCLVER}s.exe ${TK_VFS_ROOT}/../${TK_ZIP_FILE} || cp ${TCL_BIN_DIR}/../bin/tclsh${TCLVER}s.exe ${TK_VFS_ROOT}/../${TK_ZIP_FILE}; \\\n\t    (zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}') 2>/dev/null || \\\n\t\t(echo '${NATIVE_ZIP}' | sed \"s?^\\./?$$(pwd)/?\")`; \\\n\t\tcd ${TK_VFS_ROOT} && $$zip -A ../${TK_ZIP_FILE} && $$zip -J ../${TK_ZIP_FILE}) \\\n\tfi\n\t(zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}') 2>/dev/null || \\\n\t  (echo '${NATIVE_ZIP}' | sed \"s?^\\./?$$(pwd)/?\")`; \\\n\t  cd ${TK_VFS_ROOT} && \\\n\t  $$zip ${ZIP_PROG_OPTIONS} ../${TK_ZIP_FILE} ${ZIP_PROG_VFSSEARCH} >/dev/null && \\\n\t  echo \"${TK_ZIP_FILE} successful created with $$zip\" && \\\n\t  cd ..)\n\n\n# The following targets are configured by autoconf to generate either\n# a shared library or static library\n\n${TK_STUB_LIB_FILE}: ${STUB_OBJS}\n\t@$(RM) ${TK_STUB_LIB_FILE}\n\t@MAKE_STUB_LIB@ ${STUB_OBJS}\n\t@POST_MAKE_LIB@\n\n${TK_DLL_FILE}: ${TK_OBJS} $(TK_RES) ${TK_ZIP_FILE}\n\t@$(RM) ${TK_DLL_FILE}\n\t@MAKE_DLL@ ${TK_OBJS} $(TK_RES) $(SHLIB_LD_LIBS)\n\t@VC_MANIFEST_EMBED_DLL@\n\t@if test \"${ZIPFS_BUILD}\" = \"1\" ; then \\\n\t\tcat ${TK_ZIP_FILE} >> ${TK_DLL_FILE}; \\\n\tfi\n\n${TK_LIB_FILE}: ${TK_OBJS}\n\t@$(RM) ${TK_LIB_FILE}\n\t@MAKE_LIB@ ${TK_OBJS}\n\t@POST_MAKE_LIB@\n\n# Special case object file targets\n\nwinMain.$(OBJEXT): winMain.c\n\t$(CC) -c $(CC_SWITCHES) -DUNICODE=1 -D_UNICODE=1 @DEPARG@ $(CC_OBJNAME)\n\ntestMain.$(OBJEXT): winMain.c\n\t$(CC) -c $(CC_SWITCHES) -DTK_TEST -DUNICODE=1 -D_UNICODE=1 @DEPARG@ $(CC_OBJNAME)\n\ntkTest.$(OBJEXT): tkTest.c\n\t$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)\n\ntkWinTest.$(OBJEXT): tkWinTest.c\n\t$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)\n\ntkSquare.$(OBJEXT): tkSquare.c\n\t$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)\n\ntkStubLib.$(OBJEXT): tkStubLib.c\n\t$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)\n\nttkStubLib.$(OBJEXT): ${TTK_DIR}/ttkStubLib.c\n\t$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)\n\ntkMain2.$(OBJEXT): tkMain.c\n\t$(CC) -c $(CC_SWITCHES) -DBUILD_tk -DUNICODE=1 -D_UNICODE=1 @DEPARG@ $(CC_OBJNAME)\n\ntkUnixMenubu.$(OBJEXT): ${UNIX_DIR}/tkUnixMenubu.c\n\t$(CC) -c $(CC_SWITCHES) -DBUILD_tk -DBUILD_ttk @DEPARG@ $(CC_OBJNAME)\n\ntkUnixScale.$(OBJEXT): ${UNIX_DIR}/tkUnixScale.c\n\t$(CC) -c $(CC_SWITCHES) -DBUILD_tk -DBUILD_ttk @DEPARG@ $(CC_OBJNAME)\n\ntkPkgConfig.$(OBJEXT): $(GENERIC_DIR)/tkPkgConfig.c\n\t$(CC) -c $(CC_SWITCHES)\t -DBUILD_tk -DBUILD_ttk\t\t\\\n\t\t-DCFG_RUNTIME_DLLFILE=\"\\\"$(TK_DLL_FILE)\\\"\" \\\n\t\t@DEPARG@ $(CC_OBJNAME)\n\n\ntkWindow.$(OBJEXT): ${GENERIC_DIR}/tkWindow.c configure Makefile tkUuid.h\n\t$(CC) -c $(CC_SWITCHES) -I. -DBUILD_tk @DEPARG@ $(CC_OBJNAME)\n\n# Extra dependency info\ntkConsole.$(OBJEXT): configure Makefile\ntkMain.$(OBJEXT): configure Makefile\ntkMain2.$(OBJEXT): configure Makefile\n\n# Add the object extension to the implicit rules.  By default .obj is not\n# automatically added.\n\n.SUFFIXES: .${OBJEXT}\n.SUFFIXES: .$(RES)\n.SUFFIXES: .rc\n\n# Implicit rule for all object files that will end up in the Tk library\n\n%.$(OBJEXT): %.c\n\t$(CC) -c $(CC_SWITCHES) -DBUILD_tk -DBUILD_ttk @DEPARG@ $(CC_OBJNAME)\n\n.rc.$(RES):\n\t$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ \"$(GENERIC_DIR_NATIVE)\" @RC_INCLUDE@ \"$(TCL_GENERIC_NATIVE)\" @RC_INCLUDE@ \"$(RC_DIR_NATIVE)\" @DEPARG@\n\ndepend:\n\ncleanhelp:\n\t$(RM) *.hlp *.cnt *.hpj *.GID *.rtf man2tcl.exe\n\nclean: cleanhelp\n\t$(RM) *.lib *.a *.exp *.dll *.res *.${OBJEXT} *~ \\#* TAGS a.out\n\t$(RM) $(WISH) $(TKTEST) $(CAT32)\n\t$(RM) *.pch *.ilk *.pdb *.zip\n\t$(RMDIR) *.vfs\n\ndistclean: clean\n\t$(RM) Makefile config.status config.cache config.log tkConfig.sh \\\n\t\twish.exe.manifest tkUuid.h\n\nMakefile: $(SRC_DIR)/Makefile.in\n\t./config.status\n\n#\n# Regenerate the stubs files.\n#\n\n$(GENERIC_DIR)/tkStubInit.c: $(GENERIC_DIR)/tk.decls \\\n\t\t$(GENERIC_DIR)/tkInt.decls\n\t@echo \"Warning: tkStubInit.c may be out of date.\"\n\t@echo \"Developers may want to run \\\"make genstubs\\\" to regenerate.\"\n\t@echo \"This warning can be safely ignored, do not report as a bug!\"\n\ngenstubs:\n\t$(TCL_EXE) \"$(TCL_TOOL_DIR)/genStubs.tcl\" \\\n\t    \"$(GENERIC_DIR_NATIVE)\" \\\n\t    \"$(GENERIC_DIR_NATIVE)/tk.decls\" \\\n\t    \"$(GENERIC_DIR_NATIVE)/tkInt.decls\"\n\t$(TCL_EXE) \"$(TCL_TOOL_DIR)/genStubs.tcl\" \\\n\t    \"$(TTK_DIR)\" \\\n\t    \"$(TTK_DIR)/ttk.decls\"\n\n#\n# The list of all the targets that do not correspond to real files. This stops\n# 'make' from getting confused when someone makes an error in a rule.\n#\n\n.PHONY: all binaries libraries doc tkLibObjs objs tktest-real test test-classic\n.PHONY: test-ttk testlang runtest shell demo gdb install install-strip\n.PHONY: install-binaries install-libraries install-demos install-doc\n.PHONY: install-private-headers clean distclean depend genstubs checkstubs\n.PHONY: checkuchar checkexports rpm dist alldist allpatch html html-tcl html-tk\n\n# DO NOT DELETE THIS LINE -- make depend depends on it.\n"
  },
  {
    "path": "win/README",
    "content": "Tk 9.1 for Windows\n\nOriginally by Scott Stanton while at Sun Microsystems Labs\n\nThis is the directory where you configure and compile the Windows\nversion of Tk.  This directory also contains source files for Tk\nthat are specific to Microsoft Windows.  The rest of this file\ncontains information specific to the Windows version of Tk.\n\nPlease see the README and win/README files that come with the\nassociated Tcl release for an extensive set of pointers to\ndocumentation.  You will need to obtain and compile the\nTcl release before using the Tk source distrition.\n\nIf you install the Tk sources next to the Tcl sources, then\nthe Tk Makefiles (e.g., makefile.vc for VC++) will properly\nlocate the necessary Tcl files.  Otherwise you may need to\nedit makefile.vc and adjust the path to Tcl accordingly.\n\nInformation about compiling for windows is maintained at:\n    https://www.tcl-lang.org/doc/howto/compile.html\n"
  },
  {
    "path": "win/aclocal.m4",
    "content": "builtin(include,tcl.m4)\n"
  },
  {
    "path": "win/buildall.vc.bat",
    "content": "@echo off\r\n\r\n::  This is an example batchfile for building everything. Please\r\n::  edit this (or make your own) for your needs and wants using\r\n::  the instructions for calling makefile.vc found in makefile.vc\r\n\r\nset SYMBOLS=\r\n\r\n:OPTIONS\r\nif \"%1\" == \"/?\" goto help\r\nif /i \"%1\" == \"/help\" goto help\r\nif %1.==symbols. goto SYMBOLS\r\nif %1.==debug. goto SYMBOLS\r\ngoto OPTIONS_DONE\r\n\r\n:SYMBOLS\r\n   set SYMBOLS=symbols\r\n   shift\r\n   goto OPTIONS\r\n\r\n:OPTIONS_DONE\r\n\r\n:: reset errorlevel\r\ncd > nul\r\n\r\n:: You might have installed your developer studio to add itself to the\r\n:: path or have already run vcvars32.bat.  Testing these envars proves\r\n:: cl.exe and friends are in your path.\r\n::\r\nif defined VCINSTALLDIR  (goto :startBuilding)\r\nif defined MSDEVDIR      (goto :startBuilding)\r\nif defined MSVCDIR       (goto :startBuilding)\r\nif defined MSSDK         (goto :startBuilding)\r\nif defined WINDOWSSDKDIR (goto :startBuilding)\r\n\r\n:: We need to run the development environment batch script that comes\r\n:: with developer studio (v4,5,6,7,etc...)  All have it.  This path\r\n:: might not be correct.  You should call it yourself prior to running\r\n:: this batchfile.\r\n::\r\ncall \"C:\\Program Files\\Microsoft Developer Studio\\vc98\\bin\\vcvars32.bat\"\r\nif errorlevel 1 (goto no_vcvars)\r\n\r\n:startBuilding\r\n\r\necho.\r\necho Sit back and have a cup of coffee while this grinds through ;)\r\necho You asked for *everything*, remember?\r\necho.\r\ntitle Building Tk, please wait...\r\n\r\n\r\n:: makefile.vc uses this for its default anyways, but show its use here\r\n:: just to be explicit and convey understanding to the user.  Setting\r\n:: the INSTALLDIR envar prior to running this batchfile affects all builds.\r\n::\r\nif \"%INSTALLDIR%\" == \"\" set INSTALLDIR=C:\\Program Files\\Tcl\r\n\r\n\r\n:: Where is the Tcl source directory?\r\n:: You can set the TCLDIR environment variable to your Tcl HEAD checkout\r\nif \"%TCLDIR%\" == \"\" set TCLDIR=..\\..\\tcl\r\n\r\n:: Build the normal stuff along with the help file.\r\n::\r\nset OPTS=none\r\nif not %SYMBOLS%.==. set OPTS=symbols\r\nnmake -nologo -f makefile.vc release htmlhelp OPTS=%OPTS% %1\r\nif errorlevel 1 goto error\r\n\r\n:: Build the static core and shell.\r\n::\r\nset OPTS=static,msvcrt\r\nif not %SYMBOLS%.==. set OPTS=symbols,static,msvcrt\r\nnmake -nologo -f makefile.vc shell OPTS=%OPTS% %1\r\nif errorlevel 1 goto error\r\n\r\nset OPTS=\r\nset SYMBOLS=\r\ngoto end\r\n\r\n:error\r\necho *** BOOM! ***\r\ngoto end\r\n\r\n:no_vcvars\r\necho vcvars32.bat was not run prior to this batchfile, nor are the MS tools in your path.\r\ngoto out\r\n\r\n:help\r\ntitle buildall.vc.bat help message\r\necho usage:\r\necho   %0                 : builds Tk for all build types (do this first)\r\necho   %0 install         : installs all the release builds (do this second)\r\necho   %0 symbols         : builds Tk for all debugging build types\r\necho   %0 symbols install : install all the debug builds.\r\necho.\r\ngoto out\r\n\r\n:end\r\ntitle Building Tk, please wait... DONE!\r\necho DONE!\r\ngoto out\r\n\r\n:out\r\npause\r\ntitle Command Prompt\r\n"
  },
  {
    "path": "win/configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.73 for tk 9.1.\n#\n#\n# Copyright (C) 1992-1996, 1998-2017, 2020-2026 Free Software Foundation,\n# Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as 'sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf '%s\\n' \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\ncase $# in # ((\n  0) exec $CONFIG_SHELL $as_opts \"$as_myself\" ;;\n  *) exec $CONFIG_SHELL $as_opts \"$as_myself\" \"$@\" ;;\nesac\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed 'exec'.\nprintf '%s\\n' \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test \\${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" )\nthen :\n\nelse case e in #(\n  e) exitcode=1; echo positional parameters were not saved. ;;\nesac\nfi\ntest x\\$exitcode = x0 || exit 1\nblah=\\$(echo \\$(echo blah))\ntest x\\\"\\$blah\\\" = xblah || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null\nthen :\n  as_have_required=yes\nelse case e in #(\n  e) as_have_required=no ;;\nesac\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null\nthen :\n\nelse case e in #(\n  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_suggested\" 2>/dev/null\nthen :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\nIFS=$as_save_IFS\nif $as_found\nthen :\n\nelse case e in #(\n  e) if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      as_run=a \"$SHELL\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi ;;\nesac\nfi\n\n\n      if test \"x$CONFIG_SHELL\" != x\nthen :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\ncase $# in # ((\n  0) exec $CONFIG_SHELL $as_opts \"$as_myself\" ;;\n  *) exec $CONFIG_SHELL $as_opts \"$as_myself\" \"$@\" ;;\nesac\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed 'exec'.\nprintf '%s\\n' \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno\nthen :\n  printf '%s\\n' \"$0: This script requires a shell more modern than all\"\n  printf '%s\\n' \"$0: the shells that I found on your system.\"\n  if test ${ZSH_VERSION+y} ; then\n    printf '%s\\n' \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    printf '%s\\n' \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    printf '%s\\n' \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi ;;\nesac\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf '%s\\n' \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse case e in #(\n  e) as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  } ;;\nesac\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse case e in #(\n  e) as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  } ;;\nesac\nfi # as_fn_arith\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf '%s\\n' \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      t clear\n      :clear\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { printf '%s\\n' \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.\n    # In both cases, we have to default to 'cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_sed_cpp=\"y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_cpp=\"eval sed '$as_sed_cpp'\" # deprecated\n\n# Sed expression to map a string onto a valid variable name.\nas_sed_sh=\"y%*+%pp%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_sh=\"eval sed '$as_sed_sh'\" # deprecated\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_CONFIG_STATUS=\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME='tk'\nPACKAGE_TARNAME='tk'\nPACKAGE_VERSION='9.1'\nPACKAGE_STRING='tk 9.1'\nPACKAGE_BUGREPORT=''\nPACKAGE_URL=''\n\nac_unique_file=\"../generic/tk.h\"\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stddef.h>\n#ifdef HAVE_STDIO_H\n# include <stdio.h>\n#endif\n#ifdef HAVE_STDLIB_H\n# include <stdlib.h>\n#endif\n#ifdef HAVE_STRING_H\n# include <string.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_header_c_list=\nac_subst_vars='LTLIBOBJS\nLIBOBJS\nXFT_LIBS\nXLIBSW\nRES\nRC_DEFINES\nRC_DEFINE\nRC_INCLUDE\nRC_TYPE\nRC_OUT\nTK_LD_SEARCH_FLAGS\nTK_CC_SEARCH_FLAGS\nTK_BUILD_STUB_LIB_PATH\nTK_STUB_LIB_PATH\nTK_STUB_LIB_SPEC\nTK_BUILD_LIB_SPEC\nTK_LIB_SPEC\nTK_LIB_FLAG\nMAKE_EXE\nMAKE_DLL\nPOST_MAKE_LIB\nMAKE_STUB_LIB\nMAKE_LIB\nLIBRARIES\nEXESUFFIX\nLIBSUFFIX\nLIBPREFIX\nDLLSUFFIX\nLIBS_GUI\nTK_SHARED_BUILD\nSHLIB_SUFFIX\nSHLIB_CFLAGS\nSHLIB_LD_LIBS\nSHLIB_LD\nSTLIB_LD\nTK_RES\nLDFLAGS_WINDOW\nLDFLAGS_CONSOLE\nLDFLAGS_OPTIMIZE\nLDFLAGS_DEBUG\nCC_EXENAME\nCC_OBJNAME\nDEPARG\nEXTRA_CFLAGS\nCFG_TK_UNSHARED_LIB_SUFFIX\nCFG_TK_SHARED_LIB_SUFFIX\nTCL_PATCH_LEVEL\nTCL_MINOR_VERSION\nTCL_MAJOR_VERSION\nTK_BIN_DIR\nTK_SRC_DIR\nTK_BUILD_STUB_LIB_SPEC\nTK_STUB_LIB_FLAG\nTK_STUB_LIB_FILE\nTK_DLL_FILE\nTK_LIB_FILE\nTK_PATCH_LEVEL\nTK_MINOR_VERSION\nTK_MAJOR_VERSION\nTK_VERSION\nMACHINE\nTK_WIN_VERSION\nINSTALL_MSGS\nINSTALL_LIBRARIES\nTK_ZIP_FILE\nZIPFS_BUILD\nZIP_INSTALL_OBJS\nZIP_PROG_VFSSEARCH\nZIP_PROG_OPTIONS\nZIP_PROG\nEXEEXT_FOR_BUILD\nCC_FOR_BUILD\nTCLSH_PROG\nBUILD_TCLSH\nVC_MANIFEST_EMBED_EXE\nVC_MANIFEST_EMBED_DLL\nCPP\nLDFLAGS_DEFAULT\nCFLAGS_DEFAULT\nMAN2TCLFLAGS\nCFLAGS_NOLTO\nCFLAGS_WARNING\nCFLAGS_OPTIMIZE\nCFLAGS_DEBUG\nDL_LIBS\nWINE\nCYGPATH\nTCL_DEFS\nTCL_STUB_LIB_SPEC\nTCL_STUB_LIB_FLAG\nTCL_STUB_LIB_FILE\nTCL_LIB_SPEC\nTCL_LIB_FLAG\nTCL_LIB_FILE\nTCL_SRC_DIR\nTCL_BIN_DIR\nTCL_VERSION\nSHARED_BUILD\nSET_MAKE\nRC\nRANLIB\nAR\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nECHO_T\nECHO_N\nECHO_C\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nrunstatedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL\nOBJEXT_FOR_BUILD'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nenable_shared\nwith_tcl\nenable_64bit\nenable_symbols\nenable_embedded_manifest\nenable_zipfs\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nrunstatedir='${localstatedir}/run'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE_TARNAME}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -runstatedir | --runstatedir | --runstatedi | --runstated \\\n  | --runstate | --runstat | --runsta | --runst | --runs \\\n  | --run | --ru | --r)\n    ac_prev=runstatedir ;;\n  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \\\n  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \\\n  | --run=* | --ru=* | --r=*)\n    runstatedir=$ac_optarg ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: '$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf '%s\\n' \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: '$ac_option'\nTry '$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: '$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    printf '%s\\n' \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      printf '%s\\n' \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`printf '%s\\n' $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     printf '%s\\n' \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir runstatedir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: '$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but 'cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n'configure' configures tk 9.1 to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print 'checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for '--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or '..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, 'make install' will install all the files in\n'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than '$ac_default_prefix' using '--prefix',\nfor instance '--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/tk]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n  case $ac_init_help in\n     short | recursive ) echo \"Configuration of tk 9.1:\";;\n   esac\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n  --enable-shared         build and link with shared libraries (default: on)\n  --enable-64bit          enable 64bit support (where applicable)\n  --enable-symbols        build with debugging symbols (default: off)\n  --enable-embedded-manifest\n                          embed manifest if possible (default: yes)\n  --enable-zipfs          build with Zipfs support (default: on)\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-tcl              directory containing tcl configuration\n                          (tclConfig.sh)\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n\nUse these variables to override the choices made by 'configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf '%s\\n' \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf '%s\\n' \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for configure.gnu first; this name is used for a wrapper for\n    # Metaconfig's \"Configure\" on case-insensitive file systems.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      printf '%s\\n' \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\ntk configure 9.1\ngenerated by GNU Autoconf 2.73\n\nCopyright (C) 2026 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1 ;;\nesac\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  eval \"$3=yes\"\nelse case e in #(\n  e) eval \"$3=no\" ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\neval ac_res=\\$$3\n\t       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf '%s\\n' \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1 ;;\nesac\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_check_type LINENO TYPE VAR INCLUDES\n# -------------------------------------------\n# Tests whether TYPE exists after having included INCLUDES, setting cache\n# variable VAR accordingly.\nac_fn_c_check_type ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) eval \"$3=no\"\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain (void)\n{\nif (sizeof ($2))\n\t return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain (void)\n{\nif (sizeof (($2)))\n\t    return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) eval \"$3=yes\" ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\neval ac_res=\\$$3\n\t       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf '%s\\n' \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_type\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } > conftest.i && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1 ;;\nesac\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\nac_configure_args_raw=\nfor ac_arg\ndo\n  case $ac_arg in\n  *\\'*)\n    ac_arg=`printf '%s\\n' \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n  esac\n  as_fn_append ac_configure_args_raw \" '$ac_arg'\"\ndone\n\ncase $ac_configure_args_raw in\n  *$as_nl*)\n    ac_safe_unquote= ;;\n  *)\n    ac_unsafe_z='|&;<>()$`\\\\\"*?[ ''\t' # This string ends in space, tab.\n    ac_unsafe_a=\"$ac_unsafe_z#~\"\n    ac_safe_unquote=\"s/ '\\\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\\\)'/ \\\\1/g\"\n    ac_configure_args_raw=`      printf '%s\\n' \"$ac_configure_args_raw\" | sed \"$ac_safe_unquote\"`;;\nesac\n\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by tk $as_me 9.1, which was\ngenerated by GNU Autoconf 2.73.  Invocation command line was\n\n  $ $0$ac_configure_args_raw\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    printf '%s\\n' \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`printf '%s\\n' \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# Dump the cache to stdout.  It can be in a pipe (this is a requirement).\nac_cache_dump ()\n{\n  # The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\nprintf '%s\\n' \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # 'set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # 'set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n}\n\n# Print debugging info to stdout.\nac_dump_debugging_info ()\n{\n  echo\n\n  printf '%s\\n' \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n  echo\n  ac_cache_dump\n  echo\n\n  printf '%s\\n' \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n  echo\n  for ac_var in $ac_subst_vars\n  do\n    eval ac_val=\\$$ac_var\n    case $ac_val in\n    *\\'*) ac_val=`printf '%s\\n' \"$ac_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n    esac\n    printf '%s\\n' \"$ac_var='$ac_val'\"\n  done | sort\n  echo\n\n  if test -n \"$ac_subst_files\"; then\n    printf '%s\\n' \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n    echo\n    for ac_var in $ac_subst_files\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'*) ac_val=`printf '%s\\n' \"$ac_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n      esac\n      printf '%s\\n' \"$ac_var='$ac_val'\"\n    done | sort\n    echo\n  fi\n\n  if test -s confdefs.h; then\n    printf '%s\\n' \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n    echo\n    cat confdefs.h\n    echo\n  fi\n  test \"$ac_signal\" != 0 &&\n    printf '%s\\n' \"$as_me: caught signal $ac_signal\"\n  printf '%s\\n' \"$as_me: exit $exit_status\"\n}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.\nac_exit_trap ()\n{\n  exit_status=\n  # Sanitize IFS.\n  IFS=\" \"\"\t$as_nl\"\n  # Save into config.log some information that might help in debugging.\n  ac_dump_debugging_info >&5\n  eval \"rm -f $ac_clean_CONFIG_STATUS core *.core core.conftest.*\" &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n}\n\ntrap 'ac_exit_trap $?' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\nprintf '%s\\n' \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\nprintf '%s\\n' \"#define PACKAGE_NAME \\\"$PACKAGE_NAME\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_TARNAME \\\"$PACKAGE_TARNAME\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_VERSION \\\"$PACKAGE_VERSION\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_STRING \\\"$PACKAGE_STRING\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_BUGREPORT \\\"$PACKAGE_BUGREPORT\\\"\" >>confdefs.h\n\nprintf '%s\\n' \"#define PACKAGE_URL \\\"$PACKAGE_URL\\\"\" >>confdefs.h\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nif test -n \"$CONFIG_SITE\"; then\n  ac_site_files=\"$CONFIG_SITE\"\nelif test \"x$prefix\" != xNONE; then\n  ac_site_files=\"$prefix/share/config.site $prefix/etc/config.site\"\nelse\n  ac_site_files=\"$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site\"\nfi\n\nfor ac_site_file in $ac_site_files\ndo\n  case $ac_site_file in #(\n  */*) :\n     ;; #(\n  *) :\n    ac_site_file=./$ac_site_file ;;\nesac\n  if test -f \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\nprintf '%s\\n' \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Test code for whether the C compiler supports C23 (global declarations)\nac_c_conftest_c23_globals='\n/* Does the compiler advertise conformance to C17 or earlier?\n   Although GCC 14 does not do that, even with -std=gnu23,\n   it is close enough, and defines __STDC_VERSION == 202000L.  */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ <= 201710L\n# error \"Compiler advertises conformance to C17 or earlier\"\n#endif\n\n// Check alignas.\nchar alignas (double) c23_aligned_as_double;\nchar alignas (0) c23_no_special_alignment;\nextern char c23_aligned_as_int;\nchar alignas (0) alignas (int) c23_aligned_as_int;\n\n// Check alignof.\nenum\n{\n  c23_int_alignment = alignof (int),\n  c23_int_array_alignment = alignof (int[100]),\n  c23_char_alignment = alignof (char)\n};\nstatic_assert (0 < -alignof (int), \"alignof is signed\");\n\nint function_with_unnamed_parameter (int) { return 0; }\n\nvoid c23_noreturn ();\n\n/* Test parsing of string and char UTF-8 literals (including hex escapes).\n   The parens pacify GCC 15.  */\nbool use_u8 = (!sizeof u8\"\\xFF\") == (!u8'\\''x'\\'');\n\nbool check_that_bool_works = true | false | !nullptr;\n#if !true\n# error \"true does not work in #if\"\n#endif\n#if false\n#elifdef __STDC_VERSION__\n#else\n# error \"#elifdef does not work\"\n#endif\n\n#ifndef __has_c_attribute\n# error \"__has_c_attribute not defined\"\n#endif\n\n#ifndef __has_include\n# error \"__has_include not defined\"\n#endif\n\n#define LPAREN() (\n#define FORTY_TWO(x) 42\n#define VA_OPT_TEST(r, x, ...) __VA_OPT__ (FORTY_TWO r x))\nstatic_assert (VA_OPT_TEST (LPAREN (), 0, <:-) == 42);\n\nstatic_assert (0b101010 == 42);\nstatic_assert (0B101010 == 42);\nstatic_assert (0xDEAD'\\''BEEF == 3'\\''735'\\''928'\\''559);\nstatic_assert (0.500'\\''000'\\''000 == 0.5);\n\nenum unsignedish : unsigned int { uione = 1 };\nstatic_assert (0 < -uione);\n\n#include <stddef.h>\nconstexpr nullptr_t null_pointer = nullptr;\n\nstatic typeof (1 + 1L) two () { return 2; }\nstatic long int three () { return 3; }\n'\n\n# Test code for whether the C compiler supports C23 (body of main).\nac_c_conftest_c23_main='\n  {\n    label_before_declaration:\n      int arr[10] = {};\n      if (arr[0])\n        goto label_before_declaration;\n      if (!arr[0])\n        goto label_at_end_of_block;\n    label_at_end_of_block:\n  }\n  ok |= !null_pointer;\n  ok |= two != three;\n'\n\n# Test code for whether the C compiler supports C23 (complete).\nac_c_conftest_c23_program=\"${ac_c_conftest_c23_globals}\n\nint\nmain (int, char **)\n{\n  int ok = 0;\n  ${ac_c_conftest_c23_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C89 (global declarations)\nac_c_conftest_c89_globals='\n/* Do not test the value of __STDC__, because some compilers define it to 0\n   or do not define it, while otherwise adequately conforming.  */\n\n#include <stddef.h>\n#include <stdarg.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */\nstruct buf { int x; };\nstruct buf * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (char **p, int i)\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* C89 style stringification. */\n#define noexpand_stringify(a) #a\nconst char *stringified = noexpand_stringify(arbitrary+token=sequence);\n\n/* C89 style token pasting.  Exercises some of the corner cases that\n   e.g. old MSVC gets wrong, but not very hard. */\n#define noexpand_concat(a,b) a##b\n#define expand_concat(a,b) noexpand_concat(a,b)\nextern int vA;\nextern int vbee;\n#define aye A\n#define bee B\nint *pvA = &expand_concat(v,aye);\nint *pvbee = &noexpand_concat(v,bee);\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not \\xHH hex character constants.\n   These do not provoke an error unfortunately, instead are silently treated\n   as an \"x\".  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously \\x00 != x always comes out true, for an\n   array size at least.  It is necessary to write \\x00 == 0 to get something\n   that is true only with -std.  */\nint osf4_cc_array ['\\''\\x00'\\'' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) '\\''x'\\''\nint xlc6_cc_array[FOO(a) == '\\''x'\\'' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),\n               int, int);'\n\n# Test code for whether the C compiler supports C89 (body of main).\nac_c_conftest_c89_main='\nok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);\n'\n\n# Test code for whether the C compiler supports C99 (global declarations)\nac_c_conftest_c99_globals='\n/* Does the compiler advertise C99 conformance? */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L\n# error \"Compiler does not advertise C99 conformance\"\n#endif\n\n// See if C++-style comments work.\n\n#include <stdbool.h>\nextern int puts (const char *);\nextern int printf (const char *, ...);\nextern int dprintf (int, const char *, ...);\nextern void *malloc (size_t);\nextern void free (void *);\n\n// Check varargs macros.  These examples are taken from C99 6.10.3.5.\n// dprintf is used instead of fprintf to avoid needing to declare\n// FILE and stderr, and \"aND\" is used instead of \"and\" to work around\n// GCC bug 40564 which is irrelevant here.\n#define debug(...) dprintf (2, __VA_ARGS__)\n#define showlist(...) puts (#__VA_ARGS__)\n#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))\nstatic void\ntest_varargs_macros (void)\n{\n  int x = 1234;\n  int y = 5678;\n  debug (\"Flag\");\n  debug (\"X = %d\\n\", x);\n  showlist (The first, second, aND third items.);\n  report (x>y, \"x is %d but y is %d\", x, y);\n}\n\n// Check long long types.\n#define BIG64 18446744073709551615ull\n#define BIG32 4294967295ul\n#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)\n#if !BIG_OK\n  #error \"your preprocessor is broken\"\n#endif\n#if BIG_OK\n#else\n  #error \"your preprocessor is broken\"\n#endif\nstatic long long int bignum = -9223372036854775807LL;\nstatic unsigned long long int ubignum = BIG64;\n\nstruct incomplete_array\n{\n  int datasize;\n  double data[];\n};\n\nstruct named_init {\n  int number;\n  const wchar_t *name;\n  double average;\n};\n\ntypedef const char *ccp;\n\nstatic inline int\ntest_restrict (ccp restrict text)\n{\n  // Iterate through items via the restricted pointer.\n  // Also check for declarations in for loops.\n  for (unsigned int i = 0; *(text+i) != '\\''\\0'\\''; ++i)\n    continue;\n  return 0;\n}\n\n// Check varargs and va_copy.\nstatic bool\ntest_varargs (const char *format, ...)\n{\n  va_list args;\n  va_start (args, format);\n  va_list args_copy;\n  va_copy (args_copy, args);\n\n  const char *str = \"\";\n  int number = 0;\n  float fnumber = 0;\n\n  while (*format)\n    {\n      switch (*format++)\n\t{\n\tcase '\\''s'\\'': // string\n\t  str = va_arg (args_copy, const char *);\n\t  break;\n\tcase '\\''d'\\'': // int\n\t  number = va_arg (args_copy, int);\n\t  break;\n\tcase '\\''f'\\'': // float\n\t  fnumber = va_arg (args_copy, double);\n\t  break;\n\tdefault:\n\t  break;\n\t}\n    }\n  va_end (args_copy);\n  va_end (args);\n\n  return *str && number && fnumber;\n}\n'\n\n# Test code for whether the C compiler supports C99 (body of main).\nac_c_conftest_c99_main='\n  // Check bool.\n  _Bool success = false;\n  success |= (argc != 0);\n\n  // Check restrict.\n  if (test_restrict (\"String literal\") == 0)\n    success = true;\n  const char *restrict newvar = \"Another string\";\n\n  // Check varargs.\n  success &= test_varargs (\"s, d'\\'' f .\", \"string\", 65, 34.234);\n  test_varargs_macros ();\n\n  // Check flexible array members.\n  static struct incomplete_array *volatile incomplete_array_pointer;\n  struct incomplete_array *ia = incomplete_array_pointer;\n  ia->datasize = 10;\n  for (int i = 0; i < ia->datasize; ++i)\n    ia->data[i] = i * 1.234;\n  // Work around memory leak warnings.\n  free (ia);\n\n  // Check named initializers.\n  struct named_init ni = {\n    .number = 34,\n    .name = L\"Test wide string\",\n    .average = 543.34343,\n  };\n\n  ni.number = 58;\n\n  // Do not test for VLAs, as some otherwise-conforming compilers lack them.\n  // C code should instead use __STDC_NO_VLA__; see Autoconf manual.\n\n  // work around unused variable warnings\n  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\\''x'\\''\n\t || ni.number != 58);\n'\n\n# Test code for whether the C compiler supports C11 (global declarations)\nac_c_conftest_c11_globals='\n/* Does the compiler advertise C11 conformance? */\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L\n# error \"Compiler does not advertise C11 conformance\"\n#endif\n\n// Check _Alignas.\nchar _Alignas (double) aligned_as_double;\nchar _Alignas (0) no_special_alignment;\nextern char aligned_as_int;\nchar _Alignas (0) _Alignas (int) aligned_as_int;\n\n// Check _Alignof.\nenum\n{\n  int_alignment = _Alignof (int),\n  int_array_alignment = _Alignof (int[100]),\n  char_alignment = _Alignof (char)\n};\n_Static_assert (0 < -_Alignof (int), \"_Alignof is signed\");\n\n// Check _Noreturn.\nint _Noreturn does_not_return (void) { for (;;) continue; }\n\n// Check _Static_assert.\nstruct test_static_assert\n{\n  int x;\n  _Static_assert (sizeof (int) <= sizeof (long int),\n                  \"_Static_assert does not work in struct\");\n  long int y;\n};\n\n// Check UTF-8 literals.\n#define u8 syntax error!\nchar const utf8_literal[] = u8\"happens to be ASCII\" \"another string\";\n\n// Check duplicate typedefs.\ntypedef long *long_ptr;\ntypedef long int *long_ptr;\ntypedef long_ptr long_ptr;\n\n// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.\nstruct anonymous\n{\n  union {\n    struct { int i; int j; };\n    struct { int k; long int l; } w;\n  };\n  int m;\n} v1;\n'\n\n# Test code for whether the C compiler supports C11 (body of main).\nac_c_conftest_c11_main='\n  _Static_assert ((offsetof (struct anonymous, i)\n\t\t   == offsetof (struct anonymous, w.k)),\n\t\t  \"Anonymous union alignment botch\");\n  v1.i = 2;\n  v1.w.k = 5;\n  ok |= v1.i != 5;\n'\n\n# Test code for whether the C compiler supports C11 (complete).\nac_c_conftest_c11_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n${ac_c_conftest_c11_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  ${ac_c_conftest_c11_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C99 (complete).\nac_c_conftest_c99_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C89 (complete).\nac_c_conftest_c89_program=\"${ac_c_conftest_c89_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  return ok;\n}\n\"\n\nas_fn_append ac_header_c_list \" stdio.h stdio_h HAVE_STDIO_H\"\nas_fn_append ac_header_c_list \" stdlib.h stdlib_h HAVE_STDLIB_H\"\nas_fn_append ac_header_c_list \" string.h string_h HAVE_STRING_H\"\nas_fn_append ac_header_c_list \" inttypes.h inttypes_h HAVE_INTTYPES_H\"\nas_fn_append ac_header_c_list \" stdint.h stdint_h HAVE_STDINT_H\"\nas_fn_append ac_header_c_list \" strings.h strings_h HAVE_STRINGS_H\"\nas_fn_append ac_header_c_list \" sys/stat.h sys_stat_h HAVE_SYS_STAT_H\"\nas_fn_append ac_header_c_list \" sys/types.h sys_types_h HAVE_SYS_TYPES_H\"\nas_fn_append ac_header_c_list \" unistd.h unistd_h HAVE_UNISTD_H\"\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=\n\tfor ac_val in x $ac_old_val; do\n\t  ac_old_val_w=\"$ac_old_val_w $ac_val\"\n\tdone\n\tac_new_val_w=\n\tfor ac_val in x $ac_new_val; do\n\t  ac_new_val_w=\"$ac_new_val_w $ac_val\"\n\tdone\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:\" >&5\nprintf '%s\\n' \"$as_me: error: '$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:\" >&5\nprintf '%s\\n' \"$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'\" >&5\nprintf '%s\\n' \"$as_me:   former value:  '$ac_old_val'\" >&2;}\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'\" >&5\nprintf '%s\\n' \"$as_me:   current value: '$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`printf '%s\\n' \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\nprintf '%s\\n' \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run '${MAKE-make} distclean' and/or 'rm $cache_file'\n\t    and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\n\n# Determine whether it's possible to make 'echo' print without a newline.\n# These variables are no longer used directly by Autoconf, but are AC_SUBSTed\n# for compatibility with existing Makefiles.\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n\n# The following define is needed when building with Cygwin since newer\n# versions of autoconf incorrectly set SHELL to /bin/bash instead of\n# /bin/sh. The bash shell seems to suffer from some strange failures.\nSHELL=/bin/sh\n\nTK_VERSION=9.1\nTK_MAJOR_VERSION=9\nTK_MINOR_VERSION=1\nTK_PATCH_LEVEL=\"a2\"\nVER=$TK_MAJOR_VERSION$TK_MINOR_VERSION\n\n#------------------------------------------------------------------------\n# Handle the --prefix=... option\n#------------------------------------------------------------------------\n\nif test \"${prefix}\" = \"NONE\"; then\n    prefix=/usr/local\nfi\nif test \"${exec_prefix}\" = \"NONE\"; then\n    exec_prefix=$prefix\nfi\n# libdir must be a fully qualified path (not ${exec_prefix}/lib)\neval libdir=\"$libdir\"\n\n#------------------------------------------------------------------------\n# Standard compiler checks\n#------------------------------------------------------------------------\n\n# If the user did not set CFLAGS, set it now to keep\n# the AC_PROG_CC macro from adding \"-g -O2\".\nif test \"${CFLAGS+set}\" != \"set\" ; then\n    CFLAGS=\"\"\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir$ac_word${1+' '}$@\"\n  fi\nfi\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}clang\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}clang; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}clang\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf '%s\\n' \"$CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"clang\", so it can be a program name with args.\nset dummy clang; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"clang\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf '%s\\n' \"$ac_ct_CC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\nprintf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion -version; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\nprintf %s \"checking whether the C compiler works... \" >&6; }\nac_link_default=`printf '%s\\n' \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.\n# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test ${ac_cv_exeext+y} && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an '-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse case e in #(\n  e) ac_file='' ;;\nesac\nfi\nif test -z \"$ac_file\"\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nprintf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee 'config.log' for more details\" \"$LINENO\" 5; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; } ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\nprintf %s \"checking for C compiler default output file name... \" >&6; }\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\nprintf '%s\\n' \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\nprintf %s \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)\n# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will\n# work properly (i.e., refer to 'conftest.exe'), while it won't with\n# 'rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse case e in #(\n  e) { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\nprintf '%s\\n' \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain (void)\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n if (!f)\n  return 1;\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\nprintf %s \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot run C compiled programs.\nIf you meant to cross compile, use '--host'.\nSee 'config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\nprintf '%s\\n' \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext \\\n  conftest.o conftest.obj conftest.out\nac_clean_files=$ac_clean_files_save\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\nprintf %s \"checking for suffix of object files... \" >&6; }\nif test ${ac_cv_objext+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\nprintf '%s\\n' \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C\" >&5\nprintf %s \"checking whether the compiler supports GNU C... \" >&6; }\nif test ${ac_cv_c_compiler_gnu+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_compiler_gnu=yes\nelse case e in #(\n  e) ac_compiler_gnu=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\nprintf '%s\\n' \"$ac_cv_c_compiler_gnu\" >&6; }\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+y}\nac_save_CFLAGS=$CFLAGS\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\nprintf %s \"checking whether $CC accepts -g... \" >&6; }\nif test ${ac_cv_prog_cc_g+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nelse case e in #(\n  e) CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_g\" >&6; }\nif test $ac_test_CFLAGS; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\nac_prog_cc_stdc=no\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C23 features\" >&5\nprintf %s \"checking for $CC option to enable C23 features... \" >&6; }\nif test ${ac_cv_prog_cc_c23+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c23=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c23_program\n_ACEOF\nfor ac_arg in '' -std=gnu23\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c23=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c23\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c23\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c23\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c23\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c23\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c23\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c23\n  ac_prog_cc_stdc=c23 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features\" >&5\nprintf %s \"checking for $CC option to enable C11 features... \" >&6; }\nif test ${ac_cv_prog_cc_c11+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c11=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c11_program\n_ACEOF\nfor ac_arg in '' -std=gnu11 -std:c11\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c11=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c11\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c11\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c11\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c11\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c11\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11\n  ac_prog_cc_stdc=c11 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features\" >&5\nprintf %s \"checking for $CC option to enable C99 features... \" >&6; }\nif test ${ac_cv_prog_cc_c99+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c99=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c99_program\n_ACEOF\nfor ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c99=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c99\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c99\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c99\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c99\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c99\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99\n  ac_prog_cc_stdc=c99 ;;\nesac\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features\" >&5\nprintf %s \"checking for $CC option to enable C89 features... \" >&6; }\nif test ${ac_cv_prog_cc_c89+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c89_program\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC ;;\nesac\nfi\n\nif test \"x$ac_cv_prog_cc_c89\" = xno\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf '%s\\n' \"unsupported\" >&6; }\nelse case e in #(\n  e) if test \"x$ac_cv_prog_cc_c89\" = x\nthen :\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf '%s\\n' \"none needed\" >&6; }\nelse case e in #(\n  e) { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\nprintf '%s\\n' \"$ac_cv_prog_cc_c89\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c89\" ;;\nesac\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89\n  ac_prog_cc_stdc=c89 ;;\nesac\nfi\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for inline\" >&5\nprintf %s \"checking for inline... \" >&6; }\nif test ${ac_cv_c_inline+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) ac_cv_c_inline=no\nfor ac_kw in inline __inline__ __inline; do\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __cplusplus\ntypedef int foo_t;\nstatic $ac_kw foo_t static_foo (void) {return 0; }\n$ac_kw foo_t foo (void) {return 0; }\n#endif\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_c_inline=$ac_kw\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n  test \"$ac_cv_c_inline\" != no && break\ndone\n ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline\" >&5\nprintf '%s\\n' \"$ac_cv_c_inline\" >&6; }\n\ncase $ac_cv_c_inline in\n  inline | yes) ;;\n  *)\n    case $ac_cv_c_inline in\n      no) ac_val=;;\n      *) ac_val=$ac_cv_c_inline;;\n    esac\n    cat >>confdefs.h <<_ACEOF\n#ifndef __cplusplus\n#define inline $ac_val\n#endif\n_ACEOF\n    ;;\nesac\n\nac_header= ac_cache=\nfor ac_item in $ac_header_c_list\ndo\n  if test $ac_cache; then\n    ac_fn_c_check_header_compile \"$LINENO\" $ac_header ac_cv_header_$ac_cache \"$ac_includes_default\"\n    if eval test \\\"x\\$ac_cv_header_$ac_cache\\\" = xyes; then\n      printf '%s\\n' \"#define $ac_item 1\" >> confdefs.h\n    fi\n    ac_header= ac_cache=\n  elif test $ac_header; then\n    ac_cache=$ac_item\n  else\n    ac_header=$ac_item\n  fi\ndone\n\n\n\n\n\n\n\n\nif test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes\nthen :\n\nprintf '%s\\n' \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ar\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ar; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_AR+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$AR\"; then\n  ac_cv_prog_AR=\"$AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AR=\"${ac_tool_prefix}ar\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nAR=$ac_cv_prog_AR\nif test -n \"$AR\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $AR\" >&5\nprintf '%s\\n' \"$AR\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_AR\"; then\n  ac_ct_AR=$AR\n  # Extract the first word of \"ar\", so it can be a program name with args.\nset dummy ar; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_AR+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_AR\"; then\n  ac_cv_prog_ac_ct_AR=\"$ac_ct_AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_AR=\"ar\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_AR=$ac_cv_prog_ac_ct_AR\nif test -n \"$ac_ct_AR\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR\" >&5\nprintf '%s\\n' \"$ac_ct_AR\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_AR\" = x; then\n    AR=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    AR=$ac_ct_AR\n  fi\nelse\n  AR=\"$ac_cv_prog_AR\"\nfi\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_RANLIB+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\nprintf '%s\\n' \"$RANLIB\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_RANLIB+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\nprintf '%s\\n' \"$ac_ct_RANLIB\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}windres\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}windres; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_RC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$RC\"; then\n  ac_cv_prog_RC=\"$RC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RC=\"${ac_tool_prefix}windres\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nRC=$ac_cv_prog_RC\nif test -n \"$RC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $RC\" >&5\nprintf '%s\\n' \"$RC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RC\"; then\n  ac_ct_RC=$RC\n  # Extract the first word of \"windres\", so it can be a program name with args.\nset dummy windres; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_RC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$ac_ct_RC\"; then\n  ac_cv_prog_ac_ct_RC=\"$ac_ct_RC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RC=\"windres\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nac_ct_RC=$ac_cv_prog_ac_ct_RC\nif test -n \"$ac_ct_RC\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC\" >&5\nprintf '%s\\n' \"$ac_ct_RC\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RC\" = x; then\n    RC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf '%s\\n' \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RC=$ac_ct_RC\n  fi\nelse\n  RC=\"$ac_cv_prog_RC\"\nfi\n\n\n#--------------------------------------------------------------------\n# Checks to see if the make program sets the $MAKE variable.\n#--------------------------------------------------------------------\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \\$(MAKE)\" >&5\nprintf %s \"checking whether ${MAKE-make} sets \\$(MAKE)... \" >&6; }\nset x ${MAKE-make}\nac_make=`printf '%s\\n' \"$2\" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`\nif eval test \\${ac_cv_prog_make_${ac_make}_set+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat >conftest.make <<\\_ACEOF\nSHELL = /bin/sh\nall:\n\t@printf '%s\\n' '@@@%%%=$(MAKE)=@@@%%%'\n_ACEOF\n# GNU make sometimes prints \"make[1]: Entering ...\", which would confuse us.\ncase `${MAKE-make} -f conftest.make 2>/dev/null` in\n  *@@@%%%=?*=@@@%%%*)\n    eval ac_cv_prog_make_${ac_make}_set=yes;;\n  *)\n    eval ac_cv_prog_make_${ac_make}_set=no;;\nesac\nrm -f conftest.make ;;\nesac\nfi\nif eval test \\$ac_cv_prog_make_${ac_make}_set = yes; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n  SET_MAKE=\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n  SET_MAKE=\"MAKE=${MAKE-make}\"\nfi\n\n\n#--------------------------------------------------------------------\n# Determines the correct binary file extension (.o, .obj, .exe etc.)\n#--------------------------------------------------------------------\n\n\n\n\n#--------------------------------------------------------------------\n# The statements below define a collection of symbols related to\n# building libtk as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking how to build libraries\" >&5\nprintf %s \"checking how to build libraries... \" >&6; }\n    # Check whether --enable-shared was given.\nif test ${enable_shared+y}\nthen :\n  enableval=$enable_shared; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=yes ;;\nesac\nfi\n\n    if test \"$tcl_ok\" = \"yes\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: shared\" >&5\nprintf '%s\\n' \"shared\" >&6; }\n\tSHARED_BUILD=1\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: static\" >&5\nprintf '%s\\n' \"static\" >&6; }\n\tSHARED_BUILD=0\n\nprintf '%s\\n' \"#define STATIC_BUILD 1\" >>confdefs.h\n\n    fi\n\n\n\n#--------------------------------------------------------------------\n# Locate and source the tclConfig.sh file.\n#--------------------------------------------------------------------\n\n\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\n# Check whether --with-tcl was given.\nif test ${with_tcl+y}\nthen :\n  withval=$with_tcl; with_tclconfig=\"${withval}\"\nfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for Tcl configuration\" >&5\nprintf %s \"checking for Tcl configuration... \" >&6; }\n\tif test ${ac_cv_c_tclconfig+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase \"${with_tclconfig}\" in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f \"${with_tclconfig}\"; then\n\t\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&5\nprintf '%s\\n' \"$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself\" >&2;}\n\t\t\t    with_tclconfig=\"`echo \"${with_tclconfig}\" | sed 's!/tclConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd \"${with_tclconfig}\"; pwd)`\"\n\t\telse\n\t\t    as_fn_error $? \"${with_tclconfig} directory doesn't contain tclConfig.sh\" \"$LINENO\" 5\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/win; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd $i/win; pwd)`\"\n\t\t    break\n\t\tfi\n\t\tdone\n\t    fi\n\t ;;\nesac\nfi\n\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    as_fn_error $? \"Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh\" \"$LINENO\" 5\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=\"${ac_cv_c_tclconfig}\"\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf '%s\\n' \"found ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n\tfi\n    fi\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf %s \"checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... \" >&6; }\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: loading\" >&5\nprintf '%s\\n' \"loading\" >&6; }\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&5\nprintf '%s\\n' \"could not find ${TCL_BIN_DIR}/tclConfig.sh\" >&6; }\n    fi\n\n    #\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    #\n\n    if test -f $TCL_BIN_DIR/Makefile ; then\n\tTCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}\n\tTCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}\n\tTCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}\n    fi\n\n    eval \"TCL_STUB_LIB_FILE=\\\"${TCL_STUB_LIB_FILE}\\\"\"\n    eval \"TCL_STUB_LIB_FLAG=\\\"${TCL_STUB_LIB_FLAG}\\\"\"\n    eval \"TCL_STUB_LIB_SPEC=\\\"${TCL_STUB_LIB_SPEC}\\\"\"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nif test \"${TCL_MAJOR_VERSION}\" -lt 9 ; then\n    as_fn_error $? \"${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.\nTk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 9.0+.\nUse --with-tcl= option to indicate location of tclConfig.sh file for Tcl 9.0 or better.\" \"$LINENO\" 5\nfi\n\n#--------------------------------------------------------------------\n# The statements below define a collection of compile flags.  This\n# macro depends on the value of SHARED_BUILD, and should be called\n# after SC_ENABLE_SHARED checks the configure switches.\n#--------------------------------------------------------------------\n\n\n\n    # Step 0: Enable 64 bit support?\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested\" >&5\nprintf %s \"checking if 64bit support is requested... \" >&6; }\n    # Check whether --enable-64bit was given.\nif test ${enable_64bit+y}\nthen :\n  enableval=$enable_64bit; do64bit=$enableval\nelse case e in #(\n  e) do64bit=no ;;\nesac\nfi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $do64bit\" >&5\nprintf '%s\\n' \"$do64bit\" >&6; }\n\n    # Set some defaults (may get changed below)\n    EXTRA_CFLAGS=\"\"\n\nprintf '%s\\n' \"#define MODULE_SCOPE extern\" >>confdefs.h\n\n\n    # Extract the first word of \"cygpath\", so it can be a program name with args.\nset dummy cygpath; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CYGPATH+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$CYGPATH\"; then\n  ac_cv_prog_CYGPATH=\"$CYGPATH\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CYGPATH=\"cygpath -m\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_prog_CYGPATH\" && ac_cv_prog_CYGPATH=\"echo\"\nfi ;;\nesac\nfi\nCYGPATH=$ac_cv_prog_CYGPATH\nif test -n \"$CYGPATH\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CYGPATH\" >&5\nprintf '%s\\n' \"$CYGPATH\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n    # Extract the first word of \"wine\", so it can be a program name with args.\nset dummy wine; ac_word=$2\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_WINE+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -n \"$WINE\"; then\n  ac_cv_prog_WINE=\"$WINE\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_WINE=\"wine\"\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi ;;\nesac\nfi\nWINE=$ac_cv_prog_WINE\nif test -n \"$WINE\"; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $WINE\" >&5\nprintf '%s\\n' \"$WINE\" >&6; }\nelse\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nfi\n\n\n\n    SHLIB_SUFFIX=\".dll\"\n\n    # MACHINE is IX86 for LINK, but this is used by the manifest,\n    # which requires x86|amd64|arm64|ia64.\n    MACHINE=\"X86\"\n\n    if test \"$GCC\" = \"yes\"; then\n\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc\" >&5\nprintf %s \"checking for cross-compile version of gcc... \" >&6; }\nif test ${ac_cv_cross+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t    #ifndef _WIN32\n\t\t#error cross-compiler\n\t    #endif\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_cross=no\nelse case e in #(\n  e) ac_cv_cross=yes ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n       ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross\" >&5\nprintf '%s\\n' \"$ac_cv_cross\" >&6; }\n\n      if test \"$ac_cv_cross\" = \"yes\"; then\n\tcase \"$do64bit\" in\n\t    amd64|x64|yes)\n\t\tCC=\"x86_64-w64-mingw32-${CC}\"\n\t\tLD=\"x86_64-w64-mingw32-ld\"\n\t\tAR=\"x86_64-w64-mingw32-ar\"\n\t\tRANLIB=\"x86_64-w64-mingw32-ranlib\"\n\t\tRC=\"x86_64-w64-mingw32-windres\"\n\t    ;;\n\t    arm64|aarch64)\n\t\tCC=\"aarch64-w64-mingw32-${CC}\"\n\t\tLD=\"aarch64-w64-mingw32-ld\"\n\t\tAR=\"aarch64-w64-mingw32-ar\"\n\t\tRANLIB=\"aarch64-w64-mingw32-ranlib\"\n\t\tRC=\"aarch64-w64-mingw32-windres\"\n\t    ;;\n\t    *)\n\t\tCC=\"i686-w64-mingw32-${CC}\"\n\t\tLD=\"i686-w64-mingw32-ld\"\n\t\tAR=\"i686-w64-mingw32-ar\"\n\t\tRANLIB=\"i686-w64-mingw32-ranlib\"\n\t\tRC=\"i686-w64-mingw32-windres\"\n\t    ;;\n\tesac\n      fi\n    fi\n\n    # Check for a bug in gcc's windres that causes the\n    # compile to fail when a Windows native path is\n    # passed into windres. The mingw toolchain requires\n    # Windows native paths while Cygwin should work\n    # with both. Avoid the bug by passing a POSIX\n    # path when using the Cygwin toolchain.\n\n    if test \"$GCC\" = \"yes\" && test \"$CYGPATH\" != \"echo\" ; then\n\tconftest=/tmp/conftest.rc\n\techo \"STRINGTABLE BEGIN\" > $conftest\n\techo \"101 \\\"name\\\"\" >> $conftest\n\techo \"END\" >> $conftest\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for Windows native path bug in windres\" >&5\nprintf %s \"checking for Windows native path bug in windres... \" >&6; }\n\tcyg_conftest=`$CYGPATH $conftest`\n\tif { ac_try='$RC -o conftest.res.o $cyg_conftest'\n  { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_try\\\"\"; } >&5\n  (eval $ac_try) 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; } ; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\telse\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n\t    CYGPATH=echo\n\tfi\n\tconftest=\n\tcyg_conftest=\n    fi\n\n    if test \"$CYGPATH\" = \"echo\"; then\n\tDEPARG='\"$<\"'\n    else\n\tDEPARG='\"$(shell $(CYGPATH) $<)\"'\n    fi\n\n    # set various compiler flags depending on whether we are using gcc or cl\n\n    if test \"${GCC}\" = \"yes\" ; then\n\textra_cflags=\"-pipe\"\n\textra_ldflags=\"-pipe -static-libgcc -municode\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for mingw32 version of gcc\" >&5\nprintf %s \"checking for mingw32 version of gcc... \" >&6; }\nif test ${ac_cv_win32+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t\t#ifdef _WIN32\n\t\t    #error win32\n\t\t#endif\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_win32=no\nelse case e in #(\n  e) ac_cv_win32=yes ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32\" >&5\nprintf '%s\\n' \"$ac_cv_win32\" >&6; }\n\tif test \"$ac_cv_win32\" != \"yes\"; then\n\t    as_fn_error $? \"${CC} cannot produce win32 executables.\" \"$LINENO\" 5\n\tfi\n\tif test \"$do64bit\" != \"arm64\" -a \"$do64bit\" != \"aarch64\"; then\n\t    extra_cflags=\"$extra_cflags -DHAVE_CPUID=1\"\n\tfi\n\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -fno-lto\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for working -fno-lto\" >&5\nprintf %s \"checking for working -fno-lto... \" >&6; }\nif test ${ac_cv_nolto+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_nolto=yes\nelse case e in #(\n  e) ac_cv_nolto=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_nolto\" >&5\nprintf '%s\\n' \"$ac_cv_nolto\" >&6; }\n\tCFLAGS=$hold_cflags\n\tif test \"$ac_cv_nolto\" = \"yes\" ; then\n\t    CFLAGS_NOLTO=\"-fno-lto\"\n\telse\n\t    CFLAGS_NOLTO=\"\"\n\tfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if the linker understands --disable-high-entropy-va\" >&5\nprintf %s \"checking if the linker understands --disable-high-entropy-va... \" >&6; }\nif test ${tcl_cv_ld_high_entropy+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS  -Wl,--disable-high-entropy-va\"\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_ld_high_entropy=yes\nelse case e in #(\n  e) tcl_cv_ld_high_entropy=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_high_entropy\" >&5\nprintf '%s\\n' \"$tcl_cv_ld_high_entropy\" >&6; }\n\tif test $tcl_cv_ld_high_entropy = yes; then\n\t    extra_ldflags=\"$extra_ldflags -Wl,--disable-high-entropy-va\"\n\tfi\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking if the compiler understands -finput-charset\" >&5\nprintf %s \"checking if the compiler understands -finput-charset... \" >&6; }\nif test ${tcl_cv_cc_input_charset+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_cc_input_charset=yes\nelse case e in #(\n  e) tcl_cv_cc_input_charset=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t    CFLAGS=$hold_cflags ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_input_charset\" >&5\nprintf '%s\\n' \"$tcl_cv_cc_input_charset\" >&6; }\n\tif test $tcl_cv_cc_input_charset = yes; then\n\t    extra_cflags=\"$extra_cflags -finput-charset=UTF-8\"\n\tfi\n    fi\n\n    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Wl,--enable-auto-image-base\"\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for working --enable-auto-image-base\" >&5\nprintf %s \"checking for working --enable-auto-image-base... \" >&6; }\nif test ${ac_cv_enable_auto_image_base+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_enable_auto_image_base=yes\nelse case e in #(\n  e) ac_cv_enable_auto_image_base=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\n     ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_auto_image_base\" >&5\nprintf '%s\\n' \"$ac_cv_enable_auto_image_base\" >&6; }\n    CFLAGS=$hold_cflags\n    if test \"$ac_cv_enable_auto_image_base\" = \"yes\" ; then\n\textra_ldflags=\"$extra_ldflags -Wl,--enable-auto-image-base\"\n    fi\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking compiler flags\" >&5\nprintf %s \"checking compiler flags... \" >&6; }\n    if test \"${GCC}\" = \"yes\" ; then\n\tSHLIB_LD=\"\"\n\tSHLIB_LD_LIBS='${LIBS}'\n\tLIBS=\"-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32\"\n\t# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't\n\tLIBS_GUI=\"-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -loleacc -lole32 -loleaut32 -lwinspool -luxtheme -lusp10\"\n\tSTLIB_LD='${AR} cr'\n\tRC_OUT=-o\n\tRC_TYPE=\n\tRC_INCLUDE=--include\n\tRC_DEFINE=--define\n\tRES=res.o\n\tMAKE_LIB=\"\\${STLIB_LD} \\$@\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} \\$@\"\n\tPOST_MAKE_LIB=\"\\${RANLIB} \\$@\"\n\tMAKE_EXE=\"\\${CC} -o \\$@\"\n\tLIBPREFIX=\"lib\"\n\n\tif test \"${SHARED_BUILD}\" = \"0\" ; then\n\t    # static\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: using static flags\" >&5\nprintf '%s\\n' \"using static flags\" >&6; }\n\t    runtime=\n\t    LIBRARIES=\"\\${STATIC_LIBRARIES}\"\n\t    EXESUFFIX=\"s.exe\"\n\telse\n\t    # dynamic\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: using shared flags\" >&5\nprintf '%s\\n' \"using shared flags\" >&6; }\n\n\t    # ad-hoc check to see if CC supports -shared.\n\t    if \"${CC}\" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then\n\t\tas_fn_error $? \"${CC} does not support the -shared option.\n\t\tYou will need to upgrade to a newer version of the toolchain.\" \"$LINENO\" 5\n\t    fi\n\n\t    runtime=\n\t    # Add SHLIB_LD_LIBS to the Make rule, not here.\n\n\t    EXESUFFIX=\".exe\"\n\t    LIBRARIES=\"\\${SHARED_LIBRARIES}\"\n\tfi\n\t# Link with gcc since ld does not link to default libs like\n\t# -luser32 and -lmsvcrt by default.\n\tSHLIB_LD='${CC} -shared'\n\tSHLIB_LD_LIBS='${LIBS}'\n\tMAKE_DLL=\"\\${SHLIB_LD} \\$(LDFLAGS) -o \\$@ ${extra_ldflags} \\\n\t    -Wl,--out-implib,\\$(patsubst %.dll,lib%.dll.a,\\$@)\"\n\t# DLLSUFFIX is separate because it is the building block for\n\t# users of tclConfig.sh that may build shared or static.\n\tDLLSUFFIX=\".dll\"\n\tLIBSUFFIX=\".a\"\n\tLIBFLAGSUFFIX=\"\"\n\tSHLIB_SUFFIX=.dll\n\n\tEXTRA_CFLAGS=\"${extra_cflags}\"\n\n\tCFLAGS_DEBUG=-g\n\tCFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\tCFLAGS_WARNING=\"-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith\"\n\tLDFLAGS_DEBUG=\n\tLDFLAGS_OPTIMIZE=\n\n\tcase \"${CC}\" in\n\t    *++)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wno-format\"\n\t\t;;\n\t    *)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers\"\n\t\t;;\n\tesac\n\n\t# Specify the CC output file names based on the target name\n\tCC_OBJNAME=\"-o \\$@\"\n\tCC_EXENAME=\"-o \\$@\"\n\n\t# Specify linker flags depending on the type of app being\n\t# built -- Console vs. Window.\n\t#\n\t# ORIGINAL COMMENT:\n\t# We need to pass -e _WinMain@16 so that ld will use\n\t# WinMain() instead of main() as the entry point. We can't\n\t# use autoconf to check for this case since it would need\n\t# to run an executable and that does not work when\n\t# cross compiling. Remove this -e workaround once we\n\t# require a gcc that does not have this bug.\n\t#\n\t# MK NOTE: Tk should use a different mechanism. This causes\n\t# interesting problems, such as wish dying at startup.\n\t#LDFLAGS_WINDOW=\"-mwindows -e _WinMain@16 ${extra_ldflags}\"\n\tLDFLAGS_CONSOLE=\"-mconsole ${extra_ldflags}\"\n\tLDFLAGS_WINDOW=\"-mwindows ${extra_ldflags}\"\n\n\tcase \"$do64bit\" in\n\t    amd64|x64|yes)\n\t\tMACHINE=\"AMD64\" ; # assume AMD64 as default 64-bit build\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode\" >&5\nprintf '%s\\n' \"   Using 64-bit $MACHINE mode\" >&6; }\n\t\t;;\n\t    arm64|aarch64)\n\t\tMACHINE=\"ARM64\"\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result:    Using ARM64 $MACHINE mode\" >&5\nprintf '%s\\n' \"   Using ARM64 $MACHINE mode\" >&6; }\n\t\t;;\n\t    ia64)\n\t\tMACHINE=\"IA64\"\n\t\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result:    Using IA64 $MACHINE mode\" >&5\nprintf '%s\\n' \"   Using IA64 $MACHINE mode\" >&6; }\n\t\t;;\n\t    *)\n\t\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t\t    #ifndef _WIN64\n\t\t\t#error 32-bit\n\t\t    #endif\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_win_64bit=yes\nelse case e in #(\n  e) tcl_win_64bit=no\n\t\t ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t\tif test \"$tcl_win_64bit\" = \"yes\" ; then\n\t\t    do64bit=amd64\n\t\t    MACHINE=\"AMD64\"\n\t\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode\" >&5\nprintf '%s\\n' \"   Using 64-bit $MACHINE mode\" >&6; }\n\t\tfi\n\t\t;;\n\tesac\n    else\n\tif test \"${SHARED_BUILD}\" = \"0\" ; then\n\t    # static\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: using static flags\" >&5\nprintf '%s\\n' \"using static flags\" >&6; }\n\t    runtime=-MT\n\t    LIBRARIES=\"\\${STATIC_LIBRARIES}\"\n\t    EXESUFFIX=\"s.exe\"\n\telse\n\t    # dynamic\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: using shared flags\" >&5\nprintf '%s\\n' \"using shared flags\" >&6; }\n\t    runtime=-MD\n\t    # Add SHLIB_LD_LIBS to the Make rule, not here.\n\t    LIBRARIES=\"\\${SHARED_LIBRARIES}\"\n\t    EXESUFFIX=\".exe\"\n\t    case \"x`echo \\${VisualStudioVersion}`\" in\n\t\tx1[4-9]*)\n\t\t    lflags=\"${lflags} -nodefaultlib:ucrt.lib\"\n\t\t    ;;\n\t\t*)\n\t\t    ;;\n\t    esac\n\tfi\n\tMAKE_DLL=\"\\${SHLIB_LD} \\$(LDFLAGS) -out:\\$@\"\n\t# DLLSUFFIX is separate because it is the building block for\n\t# users of tclConfig.sh that may build shared or static.\n\tDLLSUFFIX=\".dll\"\n\tLIBSUFFIX=\".lib\"\n\tLIBFLAGSUFFIX=\"\"\n\n\tif test \"$do64bit\" != \"no\" ; then\n\t    case \"$do64bit\" in\n\t\tamd64|x64|yes)\n\t\t    MACHINE=\"AMD64\" ; # assume AMD64 as default 64-bit build\n\t\t    ;;\n\t\tarm64|aarch64)\n\t\t    MACHINE=\"ARM64\"\n\t\t    ;;\n\t\tia64)\n\t\t    MACHINE=\"IA64\"\n\t\t    ;;\n\t    esac\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode\" >&5\nprintf '%s\\n' \"   Using 64-bit $MACHINE mode\" >&6; }\n\tfi\n\n\tLIBS=\"netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib\"\n\n\tcase \"x`echo \\${VisualStudioVersion}`\" in\n\t\tx1[4-9]*)\n\t\t    LIBS=\"$LIBS ucrt.lib\"\n\t\t    ;;\n\t\t*)\n\t\t    ;;\n\tesac\n\n\tif test \"$do64bit\" != \"no\" ; then\n\t    RC=\"rc\"\n\t    CFLAGS_DEBUG=\"-nologo -Zi -Od ${runtime}d\"\n\t    CFLAGS_OPTIMIZE=\"-nologo -O2 ${runtime}\"\n\t    lflags=\"${lflags} -nologo -MACHINE:${MACHINE}\"\n\t    LINKBIN=\"link\"\n\t    # Avoid 'unresolved external symbol __security_cookie' errors.\n\t    # c.f. http://support.microsoft.com/?id=894573\n\t    LIBS=\"$LIBS bufferoverflowU.lib\"\n\telse\n\t    RC=\"rc\"\n\t    # -Od - no optimization\n\t    # -WX - warnings as errors\n\t    CFLAGS_DEBUG=\"-nologo -Z7 -Od -WX ${runtime}d\"\n\t    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)\n\t    CFLAGS_OPTIMIZE=\"-nologo -O2 ${runtime}\"\n\t    lflags=\"${lflags} -nologo\"\n\t    LINKBIN=\"link\"\n\tfi\n\n\tLIBS_GUI=\"gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib uxtheme.lib oleacc.lib ole32.lib usp10.lib\"\n\n\tSHLIB_LD=\"${LINKBIN} -dll -incremental:no ${lflags}\"\n\tSHLIB_LD_LIBS='${LIBS}'\n\t# link -lib only works when -lib is the first arg\n\tSTLIB_LD=\"${LINKBIN} -lib ${lflags}\"\n\tRC_OUT=-fo\n\tRC_TYPE=-r\n\tRC_INCLUDE=-i\n\tRC_DEFINE=-d\n\tRES=res\n\tMAKE_LIB=\"\\${STLIB_LD} -out:\\$@\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} -nodefaultlib -out:\\$@\"\n\tPOST_MAKE_LIB=\n\tMAKE_EXE=\"\\${CC} -Fe\\$@\"\n\tLIBPREFIX=\"\"\n\n\tCFLAGS_DEBUG=\"${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE\"\n\tCFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE\"\n\n\tEXTRA_CFLAGS=\"\"\n\tCFLAGS_WARNING=\"-W3\"\n\tLDFLAGS_DEBUG=\"-debug\"\n\tLDFLAGS_OPTIMIZE=\"-release\"\n\n\t# Specify the CC output file names based on the target name\n\tCC_OBJNAME=\"-Fo\\$@\"\n\tCC_EXENAME=\"-Fe\\\"\\$(shell \\$(CYGPATH) '\\$@')\\\"\"\n\n\t# Specify linker flags depending on the type of app being\n\t# built -- Console vs. Window.\n\tif test \"${TARGETCPU}\" != \"X86\"; then\n\t    LDFLAGS_CONSOLE=\"-link ${lflags}\"\n\t    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}\n\telse\n\t    LDFLAGS_CONSOLE=\"-link -subsystem:console ${lflags}\"\n\t    LDFLAGS_WINDOW=\"-link -subsystem:windows ${lflags}\"\n\tfi\n    fi\n\n    if test \"$do64bit\" != \"no\" ; then\n\tprintf '%s\\n' \"#define TCL_CFG_DO64BIT 1\" >>confdefs.h\n\n    fi\n\n    if test \"${GCC}\" = \"yes\" ; then\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler\" >&5\nprintf %s \"checking for SEH support in compiler... \" >&6; }\nif test ${tcl_cv_seh+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test \"$cross_compiling\" = yes\nthen :\n  tcl_cv_seh=no\nelse case e in #(\n  e)\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that\n# executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf '%s\\n' \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }\nthen :\n  ac_retval=0\nelse case e in #(\n  e) printf '%s\\n' \"$as_me: program exited with status $ac_status\" >&5\n       printf '%s\\n' \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status ;;\nesac\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\t    #define WIN32_LEAN_AND_MEAN\n\t    #include <windows.h>\n\t    #undef WIN32_LEAN_AND_MEAN\n\n\t    int main(int argc, char** argv) {\n\t\tint a, b = 0;\n\t\t__try {\n\t\t    a = 666 / b;\n\t\t}\n\t\t__except (EXCEPTION_EXECUTE_HANDLER) {\n\t\t    return 0;\n\t\t}\n\t\treturn 1;\n\t    }\n\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"\nthen :\n  tcl_cv_seh=yes\nelse case e in #(\n  e) tcl_cv_seh=no ;;\nesac\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;\nesac\nfi\n\n\t ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh\" >&5\nprintf '%s\\n' \"$tcl_cv_seh\" >&6; }\n\tif test \"$tcl_cv_seh\" = \"no\" ; then\n\nprintf '%s\\n' \"#define HAVE_NO_SEH 1\" >>confdefs.h\n\n\tfi\n\n\t#\n\t# Check to see if the excpt.h include file provided contains the\n\t# definition for EXCEPTION_DISPOSITION; if not, which is the case\n\t# with Cygwin's version as of 2002-04-10, define it to be int,\n\t# sufficient for getting the current code to work.\n\t#\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files\" >&5\nprintf %s \"checking for EXCEPTION_DISPOSITION support in include files... \" >&6; }\nif test ${tcl_cv_eh_disposition+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#\t    define WIN32_LEAN_AND_MEAN\n#\t    include <windows.h>\n#\t    undef WIN32_LEAN_AND_MEAN\n\nint\nmain (void)\n{\n\n\t\tEXCEPTION_DISPOSITION x;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_eh_disposition=yes\nelse case e in #(\n  e) tcl_cv_eh_disposition=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition\" >&5\nprintf '%s\\n' \"$tcl_cv_eh_disposition\" >&6; }\n\tif test \"$tcl_cv_eh_disposition\" = \"no\" ; then\n\nprintf '%s\\n' \"#define EXCEPTION_DISPOSITION int\" >>confdefs.h\n\n\tfi\n\n\t# See if the compiler supports casting to a union type.\n\t# This is used to stop gcc from printing a compiler\n\t# warning when initializing a union member.\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for cast to union support\" >&5\nprintf %s \"checking for cast to union support... \" >&6; }\nif test ${tcl_cv_cast_to_union+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n\t\t  union foo { int i; double d; };\n\t\t  union foo f = (union foo) (int) 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_cv_cast_to_union=yes\nelse case e in #(\n  e) tcl_cv_cast_to_union=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union\" >&5\nprintf '%s\\n' \"$tcl_cv_cast_to_union\" >&6; }\n\tif test \"$tcl_cv_cast_to_union\" = \"yes\"; then\n\nprintf '%s\\n' \"#define HAVE_CAST_TO_UNION 1\" >>confdefs.h\n\n\tfi\n    fi\n\n    # DL_LIBS is empty, but then we match the Unix version\n\n\n\n\n\n\n\nac_fn_c_check_type \"$LINENO\" \"intptr_t\" \"ac_cv_type_intptr_t\" \"\n#include <stdint.h>\n\n\"\nif test \"x$ac_cv_type_intptr_t\" = xyes\nthen :\n\nprintf '%s\\n' \"#define HAVE_INTPTR_T 1\" >>confdefs.h\n\n\nfi\nac_fn_c_check_type \"$LINENO\" \"uintptr_t\" \"ac_cv_type_uintptr_t\" \"\n#include <stdint.h>\n\n\"\nif test \"x$ac_cv_type_uintptr_t\" = xyes\nthen :\n\nprintf '%s\\n' \"#define HAVE_UINTPTR_T 1\" >>confdefs.h\n\n\nfi\n\n\n#--------------------------------------------------------------------\n# man2tcl needs this so that it can use errno.h\n#--------------------------------------------------------------------\n\nac_fn_c_check_header_compile \"$LINENO\" \"errno.h\" \"ac_cv_header_errno_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_errno_h\" = xyes\nthen :\n\nelse case e in #(\n  e) MAN2TCLFLAGS=\"-DNO_ERRNO_H\" ;;\nesac\nfi\n\n\n\n#-------------------------------------------\n#     Check for _strtoi64\n#-------------------------------------------\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking availability of _strtoi64\" >&5\nprintf %s \"checking availability of _strtoi64... \" >&6; }\nif test ${tcl_cv_strtoi64+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain (void)\n{\n_strtoi64(0,0,0)\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  tcl_cv_strtoi64=yes\nelse case e in #(\n  e) tcl_cv_strtoi64=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtoi64\" >&5\nprintf '%s\\n' \"$tcl_cv_strtoi64\" >&6; }\nif test $tcl_cv_strtoi64 = no; then\n\nprintf '%s\\n' \"#define NO_STRTOI64 1\" >>confdefs.h\n\nfi\n\nac_fn_c_check_type \"$LINENO\" \"intptr_t\" \"ac_cv_type_intptr_t\" \"$ac_includes_default\"\nif test \"x$ac_cv_type_intptr_t\" = xyes\nthen :\n\n\nprintf '%s\\n' \"#define HAVE_INTPTR_T 1\" >>confdefs.h\n\nelse case e in #(\n  e)\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for pointer-size signed integer type\" >&5\nprintf %s \"checking for pointer-size signed integer type... \" >&6; }\nif test ${tcl_cv_intptr_t+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    for tcl_cv_intptr_t in \"int\" \"long\" \"__int64\" none; do\n\tif test \"$tcl_cv_intptr_t\" != none; then\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain (void)\n{\nstatic int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_ok=yes\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t    test \"$tcl_ok\" = yes && break; fi\n    done ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intptr_t\" >&5\nprintf '%s\\n' \"$tcl_cv_intptr_t\" >&6; }\n    if test \"$tcl_cv_intptr_t\" != none; then\n\nprintf '%s\\n' \"#define intptr_t $tcl_cv_intptr_t\" >>confdefs.h\n\n    fi\n ;;\nesac\nfi\n\nac_fn_c_check_type \"$LINENO\" \"uintptr_t\" \"ac_cv_type_uintptr_t\" \"$ac_includes_default\"\nif test \"x$ac_cv_type_uintptr_t\" = xyes\nthen :\n\n\nprintf '%s\\n' \"#define HAVE_UINTPTR_T 1\" >>confdefs.h\n\nelse case e in #(\n  e)\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type\" >&5\nprintf %s \"checking for pointer-size unsigned integer type... \" >&6; }\nif test ${tcl_cv_uintptr_t+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    for tcl_cv_uintptr_t in \"unsigned int\" \"unsigned long\" \"unsigned __int64\" \\\n\t    none; do\n\tif test \"$tcl_cv_uintptr_t\" != none; then\n\t    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain (void)\n{\nstatic int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  tcl_ok=yes\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n\t    test \"$tcl_ok\" = yes && break; fi\n    done ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t\" >&5\nprintf '%s\\n' \"$tcl_cv_uintptr_t\" >&6; }\n    if test \"$tcl_cv_uintptr_t\" != none; then\n\nprintf '%s\\n' \"#define uintptr_t $tcl_cv_uintptr_t\" >>confdefs.h\n\n    fi\n ;;\nesac\nfi\n\n\n#--------------------------------------------------------------------\n# Set the default compiler switches based on the --enable-symbols\n# option.  This macro depends on C flags, and should be called\n# after SC_CONFIG_CFLAGS macro is called.\n#--------------------------------------------------------------------\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for build with symbols\" >&5\nprintf %s \"checking for build with symbols... \" >&6; }\n    # Check whether --enable-symbols was given.\nif test ${enable_symbols+y}\nthen :\n  enableval=$enable_symbols; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=no ;;\nesac\nfi\n\n# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'\n\nprintf '%s\\n' \"#define NDEBUG 1\" >>confdefs.h\n\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\n\n\tprintf '%s\\n' \"#define TCL_CFG_OPTIMIZED 1\" >>confdefs.h\n\n    else\n\tCFLAGS_DEFAULT='$(CFLAGS_DEBUG)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)\" >&5\nprintf '%s\\n' \"yes (standard debugging)\" >&6; }\n\tfi\n    fi\n\n\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\nprintf '%s\\n' \"#define TCL_MEM_DEBUG 1\" >>confdefs.h\n\n    fi\n\n    if test \"$tcl_ok\" = \"compile\" -o \"$tcl_ok\" = \"all\"; then\n\nprintf '%s\\n' \"#define TCL_COMPILE_DEBUG 1\" >>confdefs.h\n\n\nprintf '%s\\n' \"#define TCL_COMPILE_STATS 1\" >>confdefs.h\n\n    fi\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging\" >&5\nprintf '%s\\n' \"enabled symbols mem compile debugging\" >&6; }\n\telse\n\t    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging\" >&5\nprintf '%s\\n' \"enabled $tcl_ok debugging\" >&6; }\n\tfi\n    fi\n\n\n#--------------------------------------------------------------------\n# Embed the manifest if we can determine how\n#--------------------------------------------------------------------\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\nprintf %s \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if test ${ac_cv_prog_CPP+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)     # Double quotes because $CC needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" cpp /lib/cpp\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) # Broken: fails on valid input.\ncontinue ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  # Broken: success on invalid input.\ncontinue\nelse case e in #(\n  e) # Passes both tests.\nac_preproc_ok=:\nbreak ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok\nthen :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n   ;;\nesac\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\nprintf '%s\\n' \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n\nelse case e in #(\n  e) # Broken: fails on valid input.\ncontinue ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"\nthen :\n  # Broken: success on invalid input.\ncontinue\nelse case e in #(\n  e) # Passes both tests.\nac_preproc_ok=:\nbreak ;;\nesac\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok\nthen :\n\nelse case e in #(\n  e) { { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':\" >&5\nprintf '%s\\n' \"$as_me: error: in '$ac_pwd':\" >&2;}\nas_fn_error $? \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee 'config.log' for more details\" \"$LINENO\" 5; } ;;\nesac\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for egrep -e\" >&5\nprintf %s \"checking for egrep -e... \" >&6; }\nif test ${ac_cv_path_EGREP_TRADITIONAL+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) if test -z \"$EGREP_TRADITIONAL\"; then\n  ac_path_EGREP_TRADITIONAL_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_prog in grep ggrep\n   do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP_TRADITIONAL=\"$as_dir$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP_TRADITIONAL\" || continue\n# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.\n  # Check for GNU $ac_path_EGREP_TRADITIONAL\ncase `\"$ac_path_EGREP_TRADITIONAL\" --version 2>&1` in #(\n*GNU*)\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\" ac_path_EGREP_TRADITIONAL_found=:;;\n#(\n*)\n  ac_count=0\n  printf %s 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    printf '%s\\n' 'EGREP_TRADITIONAL' >> \"conftest.nl\"\n    \"$ac_path_EGREP_TRADITIONAL\" -E 'EGR(EP|AC)_TRADITIONAL$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\"\n      ac_path_EGREP_TRADITIONAL_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_TRADITIONAL_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP_TRADITIONAL\"; then\n    :\n  fi\nelse\n  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL\nfi\n\n    if test \"$ac_cv_path_EGREP_TRADITIONAL\"\nthen :\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_cv_path_EGREP_TRADITIONAL -E\"\nelse case e in #(\n  e) if test -z \"$EGREP_TRADITIONAL\"; then\n  ac_path_EGREP_TRADITIONAL_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_prog in egrep\n   do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP_TRADITIONAL=\"$as_dir$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP_TRADITIONAL\" || continue\n# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.\n  # Check for GNU $ac_path_EGREP_TRADITIONAL\ncase `\"$ac_path_EGREP_TRADITIONAL\" --version 2>&1` in #(\n*GNU*)\n  ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\" ac_path_EGREP_TRADITIONAL_found=:;;\n#(\n*)\n  ac_count=0\n  printf %s 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    printf '%s\\n' 'EGREP_TRADITIONAL' >> \"conftest.nl\"\n    \"$ac_path_EGREP_TRADITIONAL\" 'EGR(EP|AC)_TRADITIONAL$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP_TRADITIONAL=\"$ac_path_EGREP_TRADITIONAL\"\n      ac_path_EGREP_TRADITIONAL_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_TRADITIONAL_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP_TRADITIONAL\"; then\n    as_fn_error $? \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL\nfi\n ;;\nesac\nfi ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL\" >&5\nprintf '%s\\n' \"$ac_cv_path_EGREP_TRADITIONAL\" >&6; }\n EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking whether to embed manifest\" >&5\nprintf %s \"checking whether to embed manifest... \" >&6; }\n    # Check whether --enable-embedded-manifest was given.\nif test ${enable_embedded_manifest+y}\nthen :\n  enableval=$enable_embedded_manifest; embed_ok=$enableval\nelse case e in #(\n  e) embed_ok=yes ;;\nesac\nfi\n\n\n    VC_MANIFEST_EMBED_DLL=\n    VC_MANIFEST_EMBED_EXE=\n    result=no\n    if test \"$embed_ok\" = \"yes\" -a \"${SHARED_BUILD}\" = \"1\" \\\n       -a \"$GCC\" != \"yes\" ; then\n\t# Add the magic to embed the manifest into the dll/exe\n\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#if defined(_MSC_VER) && _MSC_VER >= 1400\nprint(\"manifest needed\")\n#endif\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP_TRADITIONAL \"manifest needed\" >/dev/null 2>&1\nthen :\n\n\t# Could do a CHECK_PROG for mt, but should always be with MSVC8+\n\t# Could add 'if test -f' check, but manifest should be created\n\t# in this compiler case\n\t# Add in a manifest argument that may be specified\n\t# XXX Needs improvement so that the test for existence accounts\n\t# XXX for a provided (known) manifest\n\tVC_MANIFEST_EMBED_DLL=\"if test -f \\$@.manifest ; then mt.exe -nologo -manifest \\$@.manifest wish.exe.manifest -outputresource:\\$@\\;2 ; fi\"\n\tVC_MANIFEST_EMBED_EXE=\"if test -f \\$@.manifest ; then mt.exe -nologo -manifest \\$@.manifest wish.exe.manifest -outputresource:\\$@\\;1 ; fi\"\n\tresult=yes\n\tif test \"xwish.exe.manifest\" != x ; then\n\t    result=\"yes (wish.exe.manifest)\"\n\tfi\n\nfi\nrm -rf conftest*\n\n    fi\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $result\" >&5\nprintf '%s\\n' \"$result\" >&6; }\n\n\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for tclsh in Tcl build directory\" >&5\nprintf %s \"checking for tclsh in Tcl build directory... \" >&6; }\n    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}\\${EXESUFFIX}\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $BUILD_TCLSH\" >&5\nprintf '%s\\n' \"$BUILD_TCLSH\" >&6; }\n\n\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for tclsh\" >&5\nprintf %s \"checking for tclsh... \" >&6; }\n\n    if test ${ac_cv_path_tclsh+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/tclsh[8-9]*.exe 2> /dev/null` \\\n\t\t    `ls -r $dir/tclsh* 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_tclsh\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_tclsh=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n     ;;\nesac\nfi\n\n\n    if test -f \"$ac_cv_path_tclsh\" ; then\n\tTCLSH_PROG=\"$ac_cv_path_tclsh\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG\" >&5\nprintf '%s\\n' \"$TCLSH_PROG\" >&6; }\n    else\n\t# It is not an error if an installed version of Tcl can't be located.\n\tTCLSH_PROG=\"\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH\" >&5\nprintf '%s\\n' \"No tclsh found on PATH\" >&6; }\n    fi\n\n\n\n#--------------------------------------------------------------------\n#\tZipfs support - Tip 430\n#--------------------------------------------------------------------\n# Check whether --enable-zipfs was given.\nif test ${enable_zipfs+y}\nthen :\n  enableval=$enable_zipfs; tcl_ok=$enableval\nelse case e in #(\n  e) tcl_ok=yes ;;\nesac\nfi\n\nif test \"$tcl_ok\" = \"yes\" ; then\n    #\n    # Find a native compiler\n    #\n    # Put a plausible default for CC_FOR_BUILD in Makefile.\nif test -z \"$CC_FOR_BUILD\"; then\n  if test \"x$cross_compiling\" = \"xno\"; then\n    CC_FOR_BUILD='$(CC)'\n  else\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for gcc\" >&5\nprintf %s \"checking for gcc... \" >&6; }\n    if test ${ac_cv_path_cc+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/gcc 2> /dev/null` \\\n\t\t    `ls -r $dir/gcc 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_cc\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_cc=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n     ;;\nesac\nfi\n\n  fi\nfi\n\n# Also set EXEEXT_FOR_BUILD.\nif test \"x$cross_compiling\" = \"xno\"; then\n  EXEEXT_FOR_BUILD='$(EXEEXT)'\n  OBJEXT_FOR_BUILD='$(OBJEXT)'\nelse\n  OBJEXT_FOR_BUILD='.no'\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for build system executable suffix\" >&5\nprintf %s \"checking for build system executable suffix... \" >&6; }\nif test ${bfd_cv_build_exeext+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e) rm -f conftest*\n     echo 'int main () { return 0; }' > conftest.c\n     bfd_cv_build_exeext=\n     ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5\n     for file in conftest.*; do\n       case $file in\n       *.c | *.o | *.obj | *.ilk | *.pdb) ;;\n       *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;\n       esac\n     done\n     rm -f conftest*\n     test x\"${bfd_cv_build_exeext}\" = x && bfd_cv_build_exeext=no ;;\nesac\nfi\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext\" >&5\nprintf '%s\\n' \"$bfd_cv_build_exeext\" >&6; }\n  EXEEXT_FOR_BUILD=\"\"\n  test x\"${bfd_cv_build_exeext}\" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}\nfi\n\n    #\n    # Find a native zip implementation\n    #\n\n    ZIP_PROG=\"\"\n    ZIP_PROG_OPTIONS=\"\"\n    ZIP_PROG_VFSSEARCH=\"\"\n    ZIP_INSTALL_OBJS=\"\"\n\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for zip\" >&5\nprintf %s \"checking for zip... \" >&6; }\n    if test ${ac_cv_path_zip+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse case e in #(\n  e)\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/zip 2> /dev/null` \\\n\t    `ls -r $dir/zip 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_zip\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_zip=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n     ;;\nesac\nfi\n\n    if test -f \"$ac_cv_path_zip\" ; then\n\tZIP_PROG=\"$ac_cv_path_zip\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG\" >&5\nprintf '%s\\n' \"$ZIP_PROG\" >&6; }\n\tZIP_PROG_OPTIONS=\"-rq\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: Found INFO Zip in environment\" >&5\nprintf '%s\\n' \"Found INFO Zip in environment\" >&6; }\n\t# Use standard arguments for zip\n    else\n\t# It is not an error if an installed version of Zip can't be located.\n\t# We can use the locally distributed minizip instead\n\tZIP_PROG=\"./minizip${EXEEXT_FOR_BUILD}\"\n\tZIP_PROG_OPTIONS=\"-o -r\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\tZIP_INSTALL_OBJS=\"minizip${EXEEXT_FOR_BUILD}\"\n\t{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: No zip found on PATH building minizip\" >&5\nprintf '%s\\n' \"No zip found on PATH building minizip\" >&6; }\n    fi\n\n\n\n\n\n\tZIPFS_BUILD=1\n\tTK_ZIP_FILE=libtk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_PATCH_LEVEL}.zip\nelse\n\tZIPFS_BUILD=0\n\tTCL_ZIP_FILE=\nfi\n# Do checking message here to not mess up interleaved configure output\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: checking for building with zipfs\" >&5\nprintf %s \"checking for building with zipfs... \" >&6; }\nif test \"${ZIPFS_BUILD}\" = 1; then\n    if test \"${SHARED_BUILD}\" = 0; then\n       ZIPFS_BUILD=2;\n\nprintf '%s\\n' \"#define ZIPFS_BUILD 2\" >>confdefs.h\n\n       INSTALL_LIBRARIES=install-libraries-zipfs-static\n       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n     else\n\nprintf '%s\\n' \"#define ZIPFS_BUILD 1\" >>confdefs.h\n\\\n       INSTALL_LIBRARIES=install-libraries-zipfs-shared\n       { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf '%s\\n' \"yes\" >&6; }\n    fi\nelse\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf '%s\\n' \"no\" >&6; }\nINSTALL_LIBRARIES=install-libraries\nINSTALL_MSGS=install-msgs\nfi\n\n\n\n\n\n\n#------------------------------------------------------------------------\n# tkConfig.sh refers to this by a different name\n#------------------------------------------------------------------------\n\nTK_SHARED_BUILD=${SHARED_BUILD}\n\n#--------------------------------------------------------------------\n# Perform final evaluations of variables with possible substitutions.\n#--------------------------------------------------------------------\n\nTK_SHARED_LIB_SUFFIX=\"\\${NODOT_VERSION}${DLLSUFFIX}\"\nTK_UNSHARED_LIB_SUFFIX=\"\\${NODOT_VERSION}${LIBSUFFIX}\"\n\neval \"TK_SRC_DIR=\\\"`cd $srcdir/..; $CYGPATH $(pwd)`\\\"\"\n\neval \"TK_DLL_FILE=tcl9tk$VER${DLLSUFFIX}\"\nif test ${SHARED_BUILD} = 0 -o \"$GCC\" != \"yes\" ; then\n eval \"TK_LIB_FILE=${LIBPREFIX}tcl9tk${VER}${LIBSUFFIX}\"\nelse\n eval \"TK_LIB_FILE=${LIBPREFIX}tcl9tk${VER}${DLLSUFFIX}.a\"\nfi\n\neval \"TK_STUB_LIB_FILE=${LIBPREFIX}tkstub${LIBSUFFIX}\" ;\n# FIXME: All of this var junk needs to be done in tcl.m4 !!!!\n# I left out the other vars that also need to get defined here.\n# we also need to double check about spaces in path names\nTK_LIB_FLAG=\"-ltcl9\"\neval \"TK_LIB_FLAG=\\\"${TK_LIB_FLAG}tk${VER}${LIBFLAGSUFFIX}\\\"\"\nTK_LIB_SPEC=\"-L${libdir} ${TK_LIB_FLAG}\"\neval \"TK_BUILD_LIB_SPEC=\\\"-L`$CYGPATH $(pwd)` ${TK_LIB_FLAG}\\\"\"\n\neval \"TK_STUB_LIB_FLAG=\\\"-ltkstub${LIBFLAGSUFFIX}\\\"\"\neval \"TK_BUILD_STUB_LIB_SPEC=\\\"-L`$CYGPATH $(pwd)` ${TK_STUB_LIB_FLAG}\\\"\"\n\nTK_STUB_LIB_SPEC=\"-L${libdir} ${TK_STUB_LIB_FLAG}\"\nTK_STUB_LIB_PATH=\"${libdir}/${TK_STUB_LIB_FILE}\"\neval \"TK_BUILD_STUB_LIB_PATH=\\\"`$CYGPATH $(pwd)`/${TK_STUB_LIB_FILE}\\\"\"\n\neval \"DLLSUFFIX=${DLLSUFFIX}\"\neval \"LIBPREFIX=${LIBPREFIX}\"\neval \"LIBSUFFIX=${LIBSUFFIX}\"\neval \"EXESUFFIX=${EXESUFFIX}\"\n\nCFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}\nCFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}\n\n#--------------------------------------------------------------------\n# Adjust the defines for how the resources are built depending\n# on symbols and static vs. shared.\n#--------------------------------------------------------------------\n\nif test ${SHARED_BUILD} = 0; then\n    RC_DEFINES=\"${RC_DEFINE} STATIC_BUILD\"\n    TK_RES=\"\"\nelse\n    RC_DEFINES=\"\"\n    TK_RES='tk.$(RES)'\nfi\n\n# The wish.exe.manifest requires these\n# TK_WIN_VERSION is the 4 dotted pair Windows version format which needs\n# the release level, and must account for interim release versioning\ncase \"$TK_PATCH_LEVEL\" in\n     *a*) TK_RELEASE_LEVEL=0 ;;\n     *b*) TK_RELEASE_LEVEL=1 ;;\n     *)   TK_RELEASE_LEVEL=2 ;;\nesac\nTK_WIN_VERSION=\"$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.`\"\n\n# X86|AMD64|IA64 for manifest\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\n\n\n\n\n\n# win/tcl.m4 doesn't set (LDFLAGS)\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\n\n\n\n\n\n\n\n\n\n\n# undefined at this point for win\n\n\n\n\n\n\n\n\n\n\n\n\nac_config_files=\"$ac_config_files tk.pc:../unix/tk.pc.in\"\n\n\nac_config_files=\"$ac_config_files Makefile tkConfig.sh wish.exe.manifest\"\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# 'ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* 'ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\nac_cache_dump |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test ${\\1+y} || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\nprintf '%s\\n' \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\n# Transform confdefs.h into DEFS.\n# Protect against shell expansion while executing Makefile rules.\n# Protect against Makefile macro expansion.\n#\n# If the first sed substitution is executed (which looks for macros that\n# take arguments), then branch to the quote section.  Otherwise,\n# look for a macro that doesn't take arguments.\nac_script='\n:mline\n/\\\\$/{\n N\n s,\\\\\\n,,\n b mline\n}\nt clear\n:clear\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t (][^\t (]*([^)]*)\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t ][^\t ]*\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\nb any\n:quote\ns/[][\t `~#$^&*(){}\\\\|;'\\''\"<>?]/\\\\&/g\ns/\\$/$$/g\nH\n:any\n${\n\tg\n\ts/^\\n//\n\ts/\\n/ /g\n\tp\n}\n'\nDEFS=`sed -n \"$ac_script\" confdefs.h`\n\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`printf '%s\\n' \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n\n: \"${CONFIG_STATUS=./config.status}\"\ncase $CONFIG_STATUS in #(\n  -*) :\n    CONFIG_STATUS=./$CONFIG_STATUS ;; #(\n  */*) :\n     ;; #(\n  *) :\n    CONFIG_STATUS=./$CONFIG_STATUS ;;\nesac\n\nac_write_fail=0\nac_clean_CONFIG_STATUS='\"$CONFIG_STATUS\"'\n{ printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\nprintf '%s\\n' \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >\"$CONFIG_STATUS\" <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # contradicts POSIX and common usage.  Disable this.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse case e in #(\n  e) case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as 'sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf '%s\\n' \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf '%s\\n' \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse case e in #(\n  e) as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  } ;;\nesac\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse case e in #(\n  e) as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  } ;;\nesac\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.\n    # In both cases, we have to default to 'cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf '%s\\n' \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_sed_cpp=\"y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_cpp=\"eval sed '$as_sed_cpp'\" # deprecated\n\n# Sed expression to map a string onto a valid variable name.\nas_sed_sh=\"y%*+%pp%;s%[^_$as_cr_alnum]%_%g\"\nas_tr_sh=\"eval sed '$as_sed_sh'\" # deprecated\n\n\nexec 6>&1\n## ------------------------------------- ##\n## Main body of \"$CONFIG_STATUS\" script. ##\n## ------------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x \"$CONFIG_STATUS\" || ac_write_fail=1\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by tk $as_me 9.1, which was\ngenerated by GNU Autoconf 2.73.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\n\n\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\n\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n'$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n\nConfiguration files:\n$config_files\n\nReport bugs to the package provider.\"\n\n_ACEOF\nac_cs_config=`printf '%s\\n' \"$ac_configure_args\" | sed \"$ac_safe_unquote\"`\nac_cs_config_escaped=`printf '%s\\n' \"$ac_cs_config\" | sed \"s/^ //; s/'/'\\\\\\\\\\\\\\\\''/g\"`\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nac_cs_config='$ac_cs_config_escaped'\nac_cs_version=\"\\\\\ntk config.status 9.1\nconfigured by $0, generated by GNU Autoconf 2.73,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2026 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\ntest -n \"\\$AWK\" || {\n  awk '' </dev/null ||\n    as_fn_error \\$? \"try installing gawk\"\n  AWK=awk\n}\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    printf '%s\\n' \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    printf '%s\\n' \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`printf '%s\\n' \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h |  --help | --hel | -h )\n    printf '%s\\n' \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: '$1'\nTry '$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\printf '%s\\n' \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  printf '%s\\n' \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"tk.pc\") CONFIG_FILES=\"$CONFIG_FILES tk.pc:../unix/tk.pc.in\" ;;\n    \"Makefile\") CONFIG_FILES=\"$CONFIG_FILES Makefile\" ;;\n    \"tkConfig.sh\") CONFIG_FILES=\"$CONFIG_FILES tkConfig.sh\" ;;\n    \"wish.exe.manifest\") CONFIG_FILES=\"$CONFIG_FILES wish.exe.manifest\" ;;\n\n  *) as_fn_error $? \"invalid argument: '$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to '$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with './config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | sed -n '$='`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | sed -n '$='`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>\"$CONFIG_STATUS\" || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n\neval set X \"  :F $CONFIG_FILES      \"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag '$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain ':'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: '$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`printf '%s\\n' \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is 'configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  printf '%s\\n' \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\nprintf '%s\\n' \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`printf '%s\\n' \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf '%s\\n' X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf '%s\\n' \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf '%s\\n' \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n_ACEOF\n\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\nprintf '%s\\n' \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when '$srcdir' = '.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>\"$CONFIG_STATUS\" <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>\"$CONFIG_STATUS\" <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\nprintf '%s\\n' \"$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n\n\n\n  esac\n\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_CONFIG_STATUS=\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  case $CONFIG_STATUS in #(\n  -*) :\n    ac_no_opts=-- ;; #(\n  *) :\n    ac_no_opts= ;;\nesac\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $ac_no_opts \"$CONFIG_STATUS\" $ac_config_status_args ||\n    ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { printf '%s\\n' \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\nprintf '%s\\n' \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n\n\n"
  },
  {
    "path": "win/configure.ac",
    "content": "#! /bin/bash -norc\n# This file is an input file used by the GNU \"autoconf\" program to\n# generate the file \"configure\", which is run during Tk installation\n# to configure the system for the local environment.\n\nAC_INIT([tk],[9.1])\nAC_CONFIG_SRCDIR([../generic/tk.h])\nAC_PREREQ([2.73])\n\n# The following define is needed when building with Cygwin since newer\n# versions of autoconf incorrectly set SHELL to /bin/bash instead of\n# /bin/sh. The bash shell seems to suffer from some strange failures.\nSHELL=/bin/sh\n\nTK_VERSION=9.1\nTK_MAJOR_VERSION=9\nTK_MINOR_VERSION=1\nTK_PATCH_LEVEL=\"a2\"\nVER=$TK_MAJOR_VERSION$TK_MINOR_VERSION\n\n#------------------------------------------------------------------------\n# Handle the --prefix=... option\n#------------------------------------------------------------------------\n\nif test \"${prefix}\" = \"NONE\"; then\n    prefix=/usr/local\nfi\nif test \"${exec_prefix}\" = \"NONE\"; then\n    exec_prefix=$prefix\nfi\n# libdir must be a fully qualified path (not ${exec_prefix}/lib)\neval libdir=\"$libdir\"\n\n#------------------------------------------------------------------------\n# Standard compiler checks\n#------------------------------------------------------------------------\n\n# If the user did not set CFLAGS, set it now to keep\n# the AC_PROG_CC macro from adding \"-g -O2\".\nif test \"${CFLAGS+set}\" != \"set\" ; then\n    CFLAGS=\"\"\nfi\n\nAC_PROG_CC\nAC_C_INLINE\nAC_CHECK_INCLUDES_DEFAULT\n\nAC_CHECK_TOOL(AR, ar)\nAC_CHECK_TOOL(RANLIB, ranlib)\nAC_CHECK_TOOL(RC, windres)\n\n#--------------------------------------------------------------------\n# Checks to see if the make program sets the $MAKE variable.\n#--------------------------------------------------------------------\n\nAC_PROG_MAKE_SET\n\n#--------------------------------------------------------------------\n# Determines the correct binary file extension (.o, .obj, .exe etc.)\n#--------------------------------------------------------------------\n\nAC_OBJEXT\nAC_EXEEXT\n\n#--------------------------------------------------------------------\n# The statements below define a collection of symbols related to\n# building libtk as a shared library instead of a static library.\n#--------------------------------------------------------------------\n\nSC_ENABLE_SHARED\n\n#--------------------------------------------------------------------\n# Locate and source the tclConfig.sh file.\n#--------------------------------------------------------------------\n\nSC_PATH_TCLCONFIG($TK_PATCH_LEVEL)\nSC_LOAD_TCLCONFIG\n\nif test \"${TCL_MAJOR_VERSION}\" -lt 9 ; then\n    AC_MSG_ERROR([${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.\nTk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 9.0+.\nUse --with-tcl= option to indicate location of tclConfig.sh file for Tcl 9.0 or better.])\nfi\n\n#--------------------------------------------------------------------\n# The statements below define a collection of compile flags.  This\n# macro depends on the value of SHARED_BUILD, and should be called\n# after SC_ENABLE_SHARED checks the configure switches.\n#--------------------------------------------------------------------\n\nSC_CONFIG_CFLAGS\n\nAC_CHECK_TYPES([intptr_t, uintptr_t],,,[[\n#include <stdint.h>\n]])\n\n#--------------------------------------------------------------------\n# man2tcl needs this so that it can use errno.h\n#--------------------------------------------------------------------\n\nAC_CHECK_HEADER(errno.h, , MAN2TCLFLAGS=\"-DNO_ERRNO_H\")\nAC_SUBST(MAN2TCLFLAGS)\n\n#-------------------------------------------\n#     Check for _strtoi64\n#-------------------------------------------\n\nAC_CACHE_CHECK([availability of _strtoi64], tcl_cv_strtoi64, [\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>]],\n    [[_strtoi64(0,0,0)]])],[tcl_cv_strtoi64=yes],[tcl_cv_strtoi64=no])])\nif test $tcl_cv_strtoi64 = no; then\n    AC_DEFINE(NO_STRTOI64, 1, [Is _strtoi64 function available?])\nfi\n\nAC_CHECK_TYPE([intptr_t], [\n    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [\n    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [\n    for tcl_cv_intptr_t in \"int\" \"long\" \"__int64\" none; do\n\tif test \"$tcl_cv_intptr_t\" != none; then\n\t    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],\n\t\t    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],\n\t\t[tcl_ok=yes], [tcl_ok=no])\n\t    test \"$tcl_ok\" = yes && break; fi\n    done])\n    if test \"$tcl_cv_intptr_t\" != none; then\n\tAC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer\n\t   type wide enough to hold a pointer.])\n    fi\n])\nAC_CHECK_TYPE([uintptr_t], [\n    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [\n    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [\n    for tcl_cv_uintptr_t in \"unsigned int\" \"unsigned long\" \"unsigned __int64\" \\\n\t    none; do\n\tif test \"$tcl_cv_uintptr_t\" != none; then\n\t    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],\n\t\t    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],\n\t\t[tcl_ok=yes], [tcl_ok=no])\n\t    test \"$tcl_ok\" = yes && break; fi\n    done])\n    if test \"$tcl_cv_uintptr_t\" != none; then\n\tAC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer\n\t   type wide enough to hold a pointer.])\n    fi\n])\n\n#--------------------------------------------------------------------\n# Set the default compiler switches based on the --enable-symbols\n# option.  This macro depends on C flags, and should be called\n# after SC_CONFIG_CFLAGS macro is called.\n#--------------------------------------------------------------------\n\nSC_ENABLE_SYMBOLS\n\n#--------------------------------------------------------------------\n# Embed the manifest if we can determine how\n#--------------------------------------------------------------------\n\nSC_EMBED_MANIFEST(wish.exe.manifest)\n\nSC_BUILD_TCLSH\nSC_PROG_TCLSH\n\n#--------------------------------------------------------------------\n#\tZipfs support - Tip 430\n#--------------------------------------------------------------------\nAC_ARG_ENABLE(zipfs,\n    AS_HELP_STRING([--enable-zipfs],\n\t[build with Zipfs support (default: on)]),\n    [tcl_ok=$enableval], [tcl_ok=yes])\nif test \"$tcl_ok\" = \"yes\" ; then\n    #\n    # Find a native compiler\n    #\n    AX_CC_FOR_BUILD\n    #\n    # Find a native zip implementation\n    #\n    SC_ZIPFS_SUPPORT\n\tZIPFS_BUILD=1\n\tTK_ZIP_FILE=libtk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_PATCH_LEVEL}.zip\nelse\n\tZIPFS_BUILD=0\n\tTCL_ZIP_FILE=\nfi\n# Do checking message here to not mess up interleaved configure output\nAC_MSG_CHECKING([for building with zipfs])\nif test \"${ZIPFS_BUILD}\" = 1; then\n    if test \"${SHARED_BUILD}\" = 0; then\n       ZIPFS_BUILD=2;\n       AC_DEFINE(ZIPFS_BUILD, 2, [Are we building with zipfs enabled?])\n       INSTALL_LIBRARIES=install-libraries-zipfs-static\n       AC_MSG_RESULT([yes])\n     else\n       AC_DEFINE(ZIPFS_BUILD, 1, [Are we building with zipfs enabled?])\\\n       INSTALL_LIBRARIES=install-libraries-zipfs-shared\n       AC_MSG_RESULT([yes])\n    fi\nelse\nAC_MSG_RESULT([no])\nINSTALL_LIBRARIES=install-libraries\nINSTALL_MSGS=install-msgs\nfi\nAC_SUBST(ZIPFS_BUILD)\nAC_SUBST(TK_ZIP_FILE)\nAC_SUBST(INSTALL_LIBRARIES)\nAC_SUBST(INSTALL_MSGS)\n\n\n#------------------------------------------------------------------------\n# tkConfig.sh refers to this by a different name\n#------------------------------------------------------------------------\n\nTK_SHARED_BUILD=${SHARED_BUILD}\n\n#--------------------------------------------------------------------\n# Perform final evaluations of variables with possible substitutions.\n#--------------------------------------------------------------------\n\nTK_SHARED_LIB_SUFFIX=\"\\${NODOT_VERSION}${DLLSUFFIX}\"\nTK_UNSHARED_LIB_SUFFIX=\"\\${NODOT_VERSION}${LIBSUFFIX}\"\n\neval \"TK_SRC_DIR=\\\"`cd $srcdir/..; $CYGPATH $(pwd)`\\\"\"\n\neval \"TK_DLL_FILE=tcl9tk$VER${DLLSUFFIX}\"\nif test ${SHARED_BUILD} = 0 -o \"$GCC\" != \"yes\" ; then\n eval \"TK_LIB_FILE=${LIBPREFIX}tcl9tk${VER}${LIBSUFFIX}\"\nelse\n eval \"TK_LIB_FILE=${LIBPREFIX}tcl9tk${VER}${DLLSUFFIX}.a\"\nfi\n\neval \"TK_STUB_LIB_FILE=${LIBPREFIX}tkstub${LIBSUFFIX}\" ;\n# FIXME: All of this var junk needs to be done in tcl.m4 !!!!\n# I left out the other vars that also need to get defined here.\n# we also need to double check about spaces in path names\nTK_LIB_FLAG=\"-ltcl9\"\neval \"TK_LIB_FLAG=\\\"${TK_LIB_FLAG}tk${VER}${LIBFLAGSUFFIX}\\\"\"\nTK_LIB_SPEC=\"-L${libdir} ${TK_LIB_FLAG}\"\neval \"TK_BUILD_LIB_SPEC=\\\"-L`$CYGPATH $(pwd)` ${TK_LIB_FLAG}\\\"\"\n\neval \"TK_STUB_LIB_FLAG=\\\"-ltkstub${LIBFLAGSUFFIX}\\\"\"\neval \"TK_BUILD_STUB_LIB_SPEC=\\\"-L`$CYGPATH $(pwd)` ${TK_STUB_LIB_FLAG}\\\"\"\n\nTK_STUB_LIB_SPEC=\"-L${libdir} ${TK_STUB_LIB_FLAG}\"\nTK_STUB_LIB_PATH=\"${libdir}/${TK_STUB_LIB_FILE}\"\neval \"TK_BUILD_STUB_LIB_PATH=\\\"`$CYGPATH $(pwd)`/${TK_STUB_LIB_FILE}\\\"\"\n\neval \"DLLSUFFIX=${DLLSUFFIX}\"\neval \"LIBPREFIX=${LIBPREFIX}\"\neval \"LIBSUFFIX=${LIBSUFFIX}\"\neval \"EXESUFFIX=${EXESUFFIX}\"\n\nCFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}\nCFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}\n\n#--------------------------------------------------------------------\n# Adjust the defines for how the resources are built depending\n# on symbols and static vs. shared.\n#--------------------------------------------------------------------\n\nif test ${SHARED_BUILD} = 0; then\n    RC_DEFINES=\"${RC_DEFINE} STATIC_BUILD\"\n    TK_RES=\"\"\nelse\n    RC_DEFINES=\"\"\n    TK_RES='tk.$(RES)'\nfi\n\n# The wish.exe.manifest requires these\n# TK_WIN_VERSION is the 4 dotted pair Windows version format which needs\n# the release level, and must account for interim release versioning\ncase \"$TK_PATCH_LEVEL\" in\n     *a*) TK_RELEASE_LEVEL=0 ;;\n     *b*) TK_RELEASE_LEVEL=1 ;;\n     *)   TK_RELEASE_LEVEL=2 ;;\nesac\nTK_WIN_VERSION=\"$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.`\"\nAC_SUBST(TK_WIN_VERSION)\n# X86|AMD64|IA64 for manifest\nAC_SUBST(MACHINE)\n\nAC_SUBST(TK_VERSION)\nAC_SUBST(TK_MAJOR_VERSION)\nAC_SUBST(TK_MINOR_VERSION)\nAC_SUBST(TK_PATCH_LEVEL)\nAC_SUBST(TK_LIB_FILE)\nAC_SUBST(TK_DLL_FILE)\nAC_SUBST(TK_STUB_LIB_FILE)\nAC_SUBST(TK_STUB_LIB_FLAG)\nAC_SUBST(TK_BUILD_STUB_LIB_SPEC)\nAC_SUBST(TK_SRC_DIR)\nAC_SUBST(TK_BIN_DIR)\n\nAC_SUBST(TCL_VERSION)\nAC_SUBST(TCL_MAJOR_VERSION)\nAC_SUBST(TCL_MINOR_VERSION)\nAC_SUBST(TCL_PATCH_LEVEL)\n\nAC_SUBST(TCL_SRC_DIR)\nAC_SUBST(TCL_BIN_DIR)\nAC_SUBST(CFG_TK_SHARED_LIB_SUFFIX)\nAC_SUBST(CFG_TK_UNSHARED_LIB_SUFFIX)\n\nAC_SUBST(CFLAGS_DEFAULT)\nAC_SUBST(EXTRA_CFLAGS)\nAC_SUBST(CYGPATH)\nAC_SUBST(DEPARG)\nAC_SUBST(CC_OBJNAME)\nAC_SUBST(CC_EXENAME)\n\n# win/tcl.m4 doesn't set (LDFLAGS)\nAC_SUBST(LDFLAGS_DEFAULT)\nAC_SUBST(LDFLAGS_DEBUG)\nAC_SUBST(LDFLAGS_OPTIMIZE)\nAC_SUBST(LDFLAGS_CONSOLE)\nAC_SUBST(LDFLAGS_WINDOW)\nAC_SUBST(AR)\nAC_SUBST(RANLIB)\nAC_SUBST(TK_RES)\n\nAC_SUBST(STLIB_LD)\nAC_SUBST(SHLIB_LD)\nAC_SUBST(SHLIB_LD_LIBS)\nAC_SUBST(SHLIB_CFLAGS)\nAC_SUBST(SHLIB_SUFFIX)\nAC_SUBST(TK_SHARED_BUILD)\n\nAC_SUBST(LIBS)\nAC_SUBST(LIBS_GUI)\nAC_SUBST(DLLSUFFIX)\nAC_SUBST(LIBPREFIX)\nAC_SUBST(LIBSUFFIX)\nAC_SUBST(EXESUFFIX)\nAC_SUBST(LIBRARIES)\nAC_SUBST(MAKE_LIB)\nAC_SUBST(MAKE_STUB_LIB)\nAC_SUBST(POST_MAKE_LIB)\nAC_SUBST(MAKE_DLL)\nAC_SUBST(MAKE_EXE)\n\nAC_SUBST(TK_LIB_FLAG)\nAC_SUBST(TK_LIB_SPEC)\nAC_SUBST(TK_BUILD_LIB_SPEC)\nAC_SUBST(TK_STUB_LIB_SPEC)\nAC_SUBST(TK_STUB_LIB_PATH)\nAC_SUBST(TK_BUILD_STUB_LIB_PATH)\n\n# undefined at this point for win\nAC_SUBST(TK_CC_SEARCH_FLAGS)\nAC_SUBST(TK_LD_SEARCH_FLAGS)\n\nAC_SUBST(RC)\nAC_SUBST(RC_OUT)\nAC_SUBST(RC_TYPE)\nAC_SUBST(RC_INCLUDE)\nAC_SUBST(RC_DEFINE)\nAC_SUBST(RC_DEFINES)\nAC_SUBST(RES)\nAC_SUBST(XLIBSW)\nAC_SUBST(XFT_LIBS)\nAC_CONFIG_FILES([\n    tk.pc:../unix/tk.pc.in\n])\n\nAC_CONFIG_FILES([Makefile tkConfig.sh wish.exe.manifest])\nAC_OUTPUT\n\ndnl Local Variables:\ndnl mode: autoconf\ndnl End:\n"
  },
  {
    "path": "win/gitmanifest.in",
    "content": "git-"
  },
  {
    "path": "win/makefile.vc",
    "content": "#------------------------------------------------------------- -*- makefile -*-\r\n# makefile.vc --\r\n#\r\n#\tMicrosoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)\r\n#\r\n# See the file \"license.terms\" for information on usage and redistribution\r\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\r\n#\r\n# Copyright (c) 1995-1996 Sun Microsystems, Inc.\r\n# Copyright (c) 1998-2000 Ajuba Solutions.\r\n# Copyright (c) 2001-2005 ActiveState Corporation.\r\n# Copyright (c) 2001-2004 David Gravereaux.\r\n# Copyright (c) 2003-2008 Pat Thoyts.\r\n# Copyright (c) 2017 Ashok P. Nadkarni\r\n#------------------------------------------------------------------------------\r\n\r\n# General usage:\r\n#   nmake [-nologo] -f makefile.vc [TARGET|MACRODEF [TARGET|MACRODEF] [...]]\r\n#\r\n# For MACRODEF, see TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md)\r\n# or examine Sections 7-9 in rules.vc. This makefile has the following\r\n# values for the OPTS macro in addition to the ones described there.\r\n#       noembed  = Embeds Tcl scripts into the wish executable. Currently only\r\n#                  applicable for static builds. Non-static builds currently\r\n#                  never embed.\r\n#\tsquare   = Include the demo square widget.\r\n#\r\n# Possible values for TARGET are:\r\n#\trelease  -- Builds the core, the shell and the dlls. (default)\r\n#\tdlls     -- Just builds the windows extensions.\r\n#\tshell    -- Just builds the shell and the core.\r\n#\tcore     -- Only builds the core [tkXX.(dll|lib)].\r\n#\tall      -- Builds everything.\r\n#\ttest     -- Builds and runs the test suite.\r\n#\ttktest   -- Just builds the test shell.\r\n#\tinstall  -- Installs the built binaries and libraries to $(INSTALLDIR)\r\n#\t\t    as the root of the install tree.\r\n#\tcwish    -- Builds a console version of wish.\r\n#\ttidy/clean/hose -- varying levels of cleaning.\r\n#\tgenstubs -- Rebuilds the Stubs table and support files (dev only).\r\n#\tdepend   -- Generates an accurate set of source dependancies for this\r\n#\t\t    makefile.  Helpful to avoid problems when the sources are\r\n#\t\t    refreshed and you rebuild, but can \"overbuild\" when common\r\n#\t\t    headers like tkInt.h just get small changes.\r\n#\thtmlhelp -- Builds a Windows .chm help file for Tcl and Tk from the\r\n#\t\t    troff manual pages found in $(ROOT)\\doc. You need to\r\n#\t\t    have installed the HTML Help Compiler package from Microsoft\r\n#\t\t    to produce the .chm file.\r\n#\r\n# The steps to setup a Visual C++ environment depend on which\r\n# version of Visual Studio and/or the Windows SDK you are building\r\n# against and are not described here. The simplest method is generally\r\n# to start a command shell using one of the short cuts installed by\r\n# Visual Studio/Windows SDK for the appropriate target architecture.\r\n#\r\n# NOTE: For older (Visual C++ 6 or the 2003 SDK), to use the Platform\r\n# SDK (not expressly needed), run setenv.bat after vcvars32.bat\r\n# according to the instructions for it.  This can also turn on the\r\n# 64-bit compiler, if your SDK has it.\r\n#\r\n# Examples:\r\n# Assuming Tcl sources lie in ../../tcl\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc release\r\n# If Tcl sources are not in ../../tcl, use the TCLDIR macro to specify dir\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc release TCLDIR=c:\\src\\tcl\r\n# Run the test suite\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc test\r\n# Install Tk in location specified by INSTALLDIR macro\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc install INSTALLDIR=c:\\progra~1\\tcl\r\n# Build release with PDB files\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc release OPTS=pdbs\r\n# Build debug version\r\n#       c:\\tcl_src\\win\\>nmake -f makefile.vc release OPTS=symbols\r\n#\r\n###############################################################################\r\n\r\n# The PROJECT macro is used by rules.vc for generating appropriate\r\n# macros and rules.\r\nPROJECT = tk\r\n\r\n# Default target to build if no target is specified. If unspecified, the\r\n# rules.vc file will set up \"all\" as the target.\r\nDEFAULT_BUILD_TARGET = release\r\n\r\n# We have a custom resource file\r\nRCFILE = tk.rc\r\n\r\n# The rules.vc file does much of the hard work in terms of defining\r\n# the build configuration, macros, output directories etc.\r\n!include \"rules-ext.vc\"\r\n\r\n# TCLINSTALL is set to 1 by rules.vc to indicate we are building against\r\n# an installed Tcl and 0 if building against Tcl source. Tk needs the latter.\r\n!if $(TCLINSTALL)\r\n!message *** Warning: Tk requires the source distribution of Tcl to build from,\r\n!message ***    at this time, sorry.  Please set the TCLDIR macro to point to the\r\n!message ***    Tcl sources.\r\n!endif\r\n\r\n# Extra makefile options processing for non-standard OPTS values ...\r\n!if \"$(OPTS)\" == \"\" || [nmakehlp -f \"$(OPTS)\" \"none\"]\r\nTTK_SQUARE_WIDGET = 0\r\nTK_EMBED_SCRIPTS  = 1\r\n!else\r\n!if [nmakehlp -f \"$(OPTS)\" \"square\"]\r\n!message *** Include ttk square demo widget\r\nTTK_SQUARE_WIDGET   = 1\r\n!else\r\nTTK_SQUARE_WIDGET   = 0\r\n!endif\r\n!if [nmakehlp -f $(OPTS) \"noembed\"]\r\n!message *** Option noembed specified. Tk script library will not be appended to the binary.\r\nTK_EMBED_SCRIPTS = 0\r\n!else\r\n!message *** Tk script library will be appended to the binary.\r\nTK_EMBED_SCRIPTS = 1\r\n!endif\r\n!endif\r\n\r\nTK_NO_DEPRECATED = 0\r\n!if \"$(CHECKS)\" != \"\" && ![nmakehlp -f \"$(CHECKS)\" \"none\"]\r\n!if [nmakehlp -f $(CHECKS) \"nodep\"]\r\nTK_NO_DEPRECATED = 1\r\n!endif\r\n!endif\r\n\r\nWISHC\t\t= \"$(OUT_DIR)\\$(WISHNAMEPREFIX)c$(VERSION)$(SUFX).exe\"\r\n\r\nTKTEST\t\t= \"$(OUT_DIR)\\$(PROJECT)test$(VERSION)$(SUFX).exe\"\r\nCAT32\t\t= \"$(OUT_DIR)\\cat32.exe\"\r\n\r\nWISHOBJS = \\\r\n\t$(TMP_DIR)\\winMain.obj \\\r\n!if $(STATIC_BUILD) && !$(STATIC_BUILD)\r\n\t$(TCLDDELIB) \\\r\n\t$(TCLREGLIB) \\\r\n!endif\r\n\t$(TMP_DIR)\\wish.res\r\n\r\nTKTESTOBJS = \\\r\n\t$(TMP_DIR)\\testMain.obj \\\r\n\t$(TMP_DIR)\\tkSquare.obj \\\r\n\t$(TMP_DIR)\\tkTest.obj \\\r\n\t$(TMP_DIR)\\tkWinTest.obj \\\r\n\t$(TMP_DIR)\\tktest.res\r\n\r\nXLIBOBJS = \\\r\n\t$(TMP_DIR)\\xcolors.obj \\\r\n\t$(TMP_DIR)\\xdraw.obj \\\r\n\t$(TMP_DIR)\\xgc.obj \\\r\n\t$(TMP_DIR)\\ximage.obj \\\r\n\t$(TMP_DIR)\\xutil.obj\r\n\r\nTKOBJS = \\\r\n\t$(TMP_DIR)\\tkConsole.obj \\\r\n\t$(TMP_DIR)\\tkUnixMenubu.obj \\\r\n\t$(TMP_DIR)\\tkUnixScale.obj \\\r\n\t$(XLIBOBJS) \\\r\n\t$(TMP_DIR)\\tkWin3d.obj \\\r\n\t$(TMP_DIR)\\tkWin32Dll.obj \\\r\n\t$(TMP_DIR)\\tkWinAccessibility.obj \\\r\n\t$(TMP_DIR)\\tkWinButton.obj \\\r\n\t$(TMP_DIR)\\tkWinClipboard.obj \\\r\n\t$(TMP_DIR)\\tkWinColor.obj \\\r\n\t$(TMP_DIR)\\tkWinConfig.obj \\\r\n\t$(TMP_DIR)\\tkWinCursor.obj \\\r\n\t$(TMP_DIR)\\tkWinDialog.obj \\\r\n\t$(TMP_DIR)\\tkWinDraw.obj \\\r\n\t$(TMP_DIR)\\tkWinEmbed.obj \\\r\n\t$(TMP_DIR)\\tkWinFont.obj \\\r\n\t$(TMP_DIR)\\tkWinGDI.obj \\\r\n\t$(TMP_DIR)\\tkWinIco.obj \\\r\n\t$(TMP_DIR)\\tkWinImage.obj \\\r\n\t$(TMP_DIR)\\tkWinInit.obj \\\r\n\t$(TMP_DIR)\\tkWinKey.obj \\\r\n\t$(TMP_DIR)\\tkWinMenu.obj \\\r\n\t$(TMP_DIR)\\tkWinPixmap.obj \\\r\n\t$(TMP_DIR)\\tkWinPointer.obj \\\r\n\t$(TMP_DIR)\\tkWinRegion.obj \\\r\n\t$(TMP_DIR)\\tkWinScrlbr.obj \\\r\n\t$(TMP_DIR)\\tkWinSend.obj \\\r\n\t$(TMP_DIR)\\tkWinSendCom.obj \\\r\n\t$(TMP_DIR)\\tkWinSysTray.obj \\\r\n\t$(TMP_DIR)\\tkWinWindow.obj \\\r\n\t$(TMP_DIR)\\tkWinWm.obj \\\r\n\t$(TMP_DIR)\\tkWinX.obj \\\r\n\t$(TMP_DIR)\\stubs.obj \\\r\n\t$(TMP_DIR)\\tk3d.obj \\\r\n\t$(TMP_DIR)\\tkAccessibility.obj \\\r\n\t$(TMP_DIR)\\tkArgv.obj \\\r\n\t$(TMP_DIR)\\tkAtom.obj \\\r\n\t$(TMP_DIR)\\tkBind.obj \\\r\n\t$(TMP_DIR)\\tkBitmap.obj \\\r\n\t$(TMP_DIR)\\tkBusy.obj \\\r\n\t$(TMP_DIR)\\tkButton.obj \\\r\n\t$(TMP_DIR)\\tkCanvArc.obj \\\r\n\t$(TMP_DIR)\\tkCanvBmap.obj \\\r\n\t$(TMP_DIR)\\tkCanvImg.obj \\\r\n\t$(TMP_DIR)\\tkCanvLine.obj \\\r\n\t$(TMP_DIR)\\tkCanvPoly.obj \\\r\n\t$(TMP_DIR)\\tkCanvPs.obj \\\r\n\t$(TMP_DIR)\\tkCanvText.obj \\\r\n\t$(TMP_DIR)\\tkCanvUtil.obj \\\r\n\t$(TMP_DIR)\\tkCanvWind.obj \\\r\n\t$(TMP_DIR)\\tkCanvas.obj \\\r\n\t$(TMP_DIR)\\tkClipboard.obj \\\r\n\t$(TMP_DIR)\\tkCmds.obj \\\r\n\t$(TMP_DIR)\\tkColor.obj \\\r\n\t$(TMP_DIR)\\tkConfig.obj \\\r\n\t$(TMP_DIR)\\tkCursor.obj \\\r\n\t$(TMP_DIR)\\tkEntry.obj \\\r\n\t$(TMP_DIR)\\tkError.obj \\\r\n\t$(TMP_DIR)\\tkEvent.obj \\\r\n\t$(TMP_DIR)\\tkFileFilter.obj \\\r\n\t$(TMP_DIR)\\tkFocus.obj \\\r\n\t$(TMP_DIR)\\tkFont.obj \\\r\n\t$(TMP_DIR)\\tkFrame.obj \\\r\n\t$(TMP_DIR)\\tkGC.obj \\\r\n\t$(TMP_DIR)\\tkGeometry.obj \\\r\n\t$(TMP_DIR)\\tkGet.obj \\\r\n\t$(TMP_DIR)\\tkGrab.obj \\\r\n\t$(TMP_DIR)\\tkGrid.obj \\\r\n\t$(TMP_DIR)\\tkIcu.obj \\\r\n\t$(TMP_DIR)\\tkImage.obj \\\r\n\t$(TMP_DIR)\\tkImgBmap.obj \\\r\n\t$(TMP_DIR)\\tkImgListFormat.obj \\\r\n\t$(TMP_DIR)\\tkImgGIF.obj \\\r\n\t$(TMP_DIR)\\tkImgPNG.obj \\\r\n\t$(TMP_DIR)\\tkImgPPM.obj \\\r\n\t$(TMP_DIR)\\tkImgSVGnano.obj \\\r\n\t$(TMP_DIR)\\tkImgPhoto.obj \\\r\n\t$(TMP_DIR)\\tkImgPhInstance.obj \\\r\n\t$(TMP_DIR)\\tkImgUtil.obj \\\r\n\t$(TMP_DIR)\\tkListbox.obj \\\r\n\t$(TMP_DIR)\\tkMacWinMenu.obj \\\r\n\t$(TMP_DIR)\\tkMain.obj \\\r\n\t$(TMP_DIR)\\tkMain2.obj \\\r\n\t$(TMP_DIR)\\tkMenu.obj \\\r\n\t$(TMP_DIR)\\tkMenubutton.obj \\\r\n\t$(TMP_DIR)\\tkMenuDraw.obj \\\r\n\t$(TMP_DIR)\\tkMessage.obj \\\r\n\t$(TMP_DIR)\\tkPanedWindow.obj \\\r\n\t$(TMP_DIR)\\tkObj.obj \\\r\n\t$(TMP_DIR)\\tkOldConfig.obj \\\r\n\t$(TMP_DIR)\\tkOption.obj \\\r\n\t$(TMP_DIR)\\tkPack.obj \\\r\n\t$(TMP_DIR)\\tkPkgConfig.obj \\\r\n\t$(TMP_DIR)\\tkPlace.obj \\\r\n\t$(TMP_DIR)\\tkPointer.obj \\\r\n\t$(TMP_DIR)\\tkRectOval.obj \\\r\n\t$(TMP_DIR)\\tkScale.obj \\\r\n\t$(TMP_DIR)\\tkScrollbar.obj \\\r\n\t$(TMP_DIR)\\tkSelect.obj \\\r\n\t$(TMP_DIR)\\tkStyle.obj \\\r\n\t$(TMP_DIR)\\tkText.obj \\\r\n\t$(TMP_DIR)\\tkTextBTree.obj \\\r\n\t$(TMP_DIR)\\tkTextDisp.obj \\\r\n\t$(TMP_DIR)\\tkTextImage.obj \\\r\n\t$(TMP_DIR)\\tkTextIndex.obj \\\r\n\t$(TMP_DIR)\\tkTextMark.obj \\\r\n\t$(TMP_DIR)\\tkTextTag.obj \\\r\n\t$(TMP_DIR)\\tkTextWind.obj \\\r\n\t$(TMP_DIR)\\tkTrig.obj \\\r\n\t$(TMP_DIR)\\tkUndo.obj \\\r\n\t$(TMP_DIR)\\tkUtil.obj \\\r\n\t$(TMP_DIR)\\tkVisual.obj \\\r\n\t$(TMP_DIR)\\tkStubInit.obj \\\r\n\t$(TMP_DIR)\\tkWindow.obj \\\r\n\t$(TTK_OBJS) \\\r\n!if !$(STATIC_BUILD)\r\n\t$(TMP_DIR)\\tk.res\r\n!endif\r\n\r\nTTK_OBJS = \\\r\n\t$(TMP_DIR)\\ttkWinMonitor.obj \\\r\n\t$(TMP_DIR)\\ttkWinTheme.obj \\\r\n\t$(TMP_DIR)\\ttkWinVistaTheme.obj \\\r\n\t$(TMP_DIR)\\ttkBlink.obj \\\r\n\t$(TMP_DIR)\\ttkButton.obj \\\r\n\t$(TMP_DIR)\\ttkCache.obj \\\r\n\t$(TMP_DIR)\\ttkClamTheme.obj \\\r\n\t$(TMP_DIR)\\ttkClassicTheme.obj \\\r\n\t$(TMP_DIR)\\ttkDefaultTheme.obj \\\r\n\t$(TMP_DIR)\\ttkElements.obj \\\r\n\t$(TMP_DIR)\\ttkEntry.obj \\\r\n\t$(TMP_DIR)\\ttkFrame.obj \\\r\n\t$(TMP_DIR)\\ttkImage.obj \\\r\n\t$(TMP_DIR)\\ttkInit.obj \\\r\n\t$(TMP_DIR)\\ttkLabel.obj \\\r\n\t$(TMP_DIR)\\ttkLayout.obj \\\r\n\t$(TMP_DIR)\\ttkManager.obj \\\r\n\t$(TMP_DIR)\\ttkNotebook.obj \\\r\n\t$(TMP_DIR)\\ttkPanedwindow.obj \\\r\n\t$(TMP_DIR)\\ttkProgress.obj \\\r\n\t$(TMP_DIR)\\ttkScale.obj \\\r\n\t$(TMP_DIR)\\ttkScrollbar.obj \\\r\n\t$(TMP_DIR)\\ttkScroll.obj \\\r\n\t$(TMP_DIR)\\ttkSeparator.obj \\\r\n\t$(TMP_DIR)\\ttkSquare.obj \\\r\n\t$(TMP_DIR)\\ttkState.obj \\\r\n\t$(TMP_DIR)\\ttkTagSet.obj \\\r\n\t$(TMP_DIR)\\ttkTheme.obj \\\r\n\t$(TMP_DIR)\\ttkToggleswitch.obj \\\r\n\t$(TMP_DIR)\\ttkTrace.obj \\\r\n\t$(TMP_DIR)\\ttkTrack.obj \\\r\n\t$(TMP_DIR)\\ttkTreeview.obj \\\r\n\t$(TMP_DIR)\\ttkWidget.obj \\\r\n\t$(TMP_DIR)\\ttkStubInit.obj\r\n\r\nTKSTUBOBJS = \\\r\n\t$(TMP_DIR)\\tkStubLib.obj \\\r\n\t$(TMP_DIR)\\ttkStubLib.obj\r\n\r\n### The following paths CANNOT have spaces in them as they appear on\r\n### the left side of implicit rules.\r\nXLIBDIR\t\t= $(ROOT)\\xlib\r\nTTKDIR\t\t= $(ROOT)\\generic\\ttk\r\nBITMAPDIR\t= $(ROOT)\\bitmaps\r\n\r\n# Directories where to build TIP430 ZIP files\r\n# One for Tk - always built, contains Tk scripts\r\n# One for Wish - for static builds, contains Tcl+Tk scripts\r\nLIBTKVFS = $(OUT_DIR)\\libtk.vfs\r\nWISHSCRIPTZIP = $(OUT_DIR)\\wish.zip\r\n\r\n# Additional include and C macro definitions for the implicit rules\r\n# defined in rules.vc\r\nPRJ_INCLUDES\t= -I\"$(BITMAPDIR)\" -I\"$(XLIBDIR)\"\r\n\r\nCONFIG_DEFS     =/DHAVE_SYS_TYPES_H=1 /DHAVE_SYS_STAT_H=1 \\\r\n\t\t /DHAVE_STRING_H=1 /DHAVE_MEMORY_H=1 \\\r\n\t\t /DHAVE_STRINGS_H=1 \\\r\n!if $(TTK_SQUARE_WIDGET)\r\n\t\t /DTTK_SQUARE_WIDGET=1 \\\r\n!endif\r\n!if $(TK_NO_DEPRECATED)\r\n\t\t /DTK_NO_DEPRECATED=1\r\n!endif\r\n\r\nPRJ_DEFINES\t= /DBUILD_ttk $(CONFIG_DEFS) /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE\r\n\r\n# Additional Link libraries needed beyond those in rules.vc\r\nPRJ_LIBS   = netapi32.lib gdi32.lib user32.lib userenv.lib winspool.lib shell32.lib ole32.lib uuid.lib oleacc.lib usp10.lib\r\n\r\n#---------------------------------------------------------------------\r\n# TkTest flags\r\n#---------------------------------------------------------------------\r\n\r\n!if \"$(TESTPAT)\" != \"\"\r\nTESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)\r\n!endif\r\n\r\n#---------------------------------------------------------------------\r\n# Project specific targets\r\n#---------------------------------------------------------------------\r\n\r\nrelease:  setup $(TKSTUBLIB) $(WISH) libtkzip embed\r\nall:\t  release $(CAT32)\r\ncore:\t  setup $(TKSTUBLIB) $(TKLIB)\r\ncwish:\t  $(WISHC)\r\nlibtkzip: setup $(TKSCRIPTZIP)\r\n!if $(TK_EMBED_SCRIPTS)\r\n!if $(STATIC_BUILD)\r\nembed:    setup $(WISH) $(WISHSCRIPTZIP)\r\n\t@copy /y /b \"$(WISH)\"+\"$(WISHSCRIPTZIP)\" \"$(WISH)\"\r\n!else\r\nembed:    setup $(TKLIB) $(TKSCRIPTZIP)\r\n\t@copy /y /b \"$(TKLIB)\"+\"$(TKSCRIPTZIP)\" \"$(TKLIB)\"\r\n!endif\r\n!else\r\n# ! TK_EMBED_SCRIPTS - still need to build the zip even if not embedded\r\nembed: $(TKSCRIPTZIP)\r\n!endif\r\n\r\ninstall:  install-binaries install-libraries install-docs\r\n!if $(SYMBOLS)\r\ninstall:    install-pdbs\r\n!endif\r\ntktest:\t  setup $(TKTEST) $(CAT32)\r\n\r\nsetup: default-setup\r\n\r\ntest: test-classic test-ttk\r\n\r\ntest-classic: setup $(TKTEST) $(TKLIB) $(CAT32)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\t$(DEBUGGER) $(TKTEST) \"$(ROOT:\\=/)/tests/all.tcl\" $(TESTFLAGS) | $(CAT32)\r\n\r\ntest-ttk: setup $(TKTEST) $(TKLIB) $(CAT32)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\t$(DEBUGGER) $(TKTEST) \"$(ROOT:\\=/)/tests/ttk/all.tcl\" $(TESTFLAGS) | $(CAT32)\r\n\r\nruntest: setup $(TKTEST) $(TKLIB) $(CAT32)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\t$(DEBUGGER) $(TKTEST)\r\n\r\nrundemo: setup $(TKTEST) $(TKLIB) $(CAT32)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\t$(TKTEST) $(ROOT:\\=/)\\library\\demos\\widget\r\n\r\nshell: setup $(WISH)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\t$(DEBUGGER) $(WISH) <<\r\n\tconsole show\r\n<<\r\n\r\ndbgshell: setup $(WISH)\r\n\t@set TCL_LIBRARY=$(TCL_LIBRARY:\\=/)\r\n\t@set TK_LIBRARY=$(LIBDIR:\\=/)\r\n\t@set TCLLIBPATH=\r\n!if $(TCLINSTALL)\r\n\t@set PATH=$(_TCLDIR)\\bin;$(PATH)\r\n!else\r\n\t@set PATH=$(_TCLDIR)\\win\\$(BUILDDIRTOP);$(PATH)\r\n!endif\r\n\twindbg $(WISH)\r\n\r\n!if $(STATIC_BUILD)\r\n\r\n$(TKLIB): $(TKOBJS)\r\n\t$(LIBCMD) @<<\r\n$**\r\n<<\r\n\r\n!else\r\n\r\n$(TKLIB): $(TKOBJS)\r\n\t$(DLLCMD) @<<\r\n$**\r\n<<\r\n\t$(_VC_MANIFEST_EMBED_DLL)\r\n\t@if exist $*.exp del $*.exp\r\n\r\n$(TKIMPLIB): $(TKLIB)\r\n\r\n!endif # $(STATIC_BUILD)\r\n\r\n$(TKSTUBLIB): $(TKSTUBOBJS)\r\n\t$(LIBCMD) -nodefaultlib $**\r\n\r\n\r\n$(WISH): $(WISHOBJS) $(TKSTUBLIB) $(TKIMPLIB)\r\n\t$(GUIEXECMD) -stack:2300000 $**\r\n\t$(_VC_MANIFEST_EMBED_EXE)\r\n\r\n\r\n$(WISHC): $(WISHOBJS) $(TKSTUBLIB) $(TKIMPLIB)\r\n\t$(CONEXECMD) -stack:2300000 $**\r\n\t$(_VC_MANIFEST_EMBED_EXE)\r\n\r\n\r\n$(TKTEST): $(TKTESTOBJS) $(TKSTUBLIB) $(TKIMPLIB)\r\n\t$(GUIEXECMD) -stack:2300000 $**\r\n\t$(_VC_MANIFEST_EMBED_EXE)\r\n\r\n$(TKSCRIPTZIP): .PHONY\r\n\t@echo Building Tk library zip file\r\n\t@if not exist \"$(LIBTKVFS)\" $(MKDIR) \"$(LIBTKVFS)\"\r\n\t@if exist \"$(LIBTKVFS)\\tk_library\" $(RMDIR) \"$(LIBTKVFS)\\tk_library\"\r\n\t@$(CPYDIR) $(LIBDIR) \"$(LIBTKVFS)\\tk_library\"\r\n\t@$(TCLSH) <<\r\ncd {$(OUT_DIR)}\r\nfile delete -force {libtk.vfs/tk_library/demos}\r\nfile delete -force {$@}\r\nzipfs mkzip {$@} {$(LIBTKVFS)} {$(LIBTKVFS)}\r\n<<\r\n\r\n!if $(STATIC_BUILD)\r\n$(WISHSCRIPTZIP): $(TKSCRIPTZIP)\r\n\t@echo Building Wish Tcl+Tk library zip file\r\n\t@if exist \"$(LIBTKVFS)\\tcl_library\" $(RMDIR) \"$(LIBTKVFS)\\tcl_library\"\r\n\t@$(TCLSH) <<\r\ncd {$(OUT_DIR)}\r\nfile delete -force {libtk.vfs/tk_library/demos}\r\nfile delete -force {$@}\r\nzipfs mount \"$(TCLSCRIPTZIP:\\=/)\" mnt\r\nfile copy [file join [zipfs root] mnt tcl_library] \"$(LIBTKVFS:\\=/)\"\r\nzipfs mkzip {$@} {$(LIBTKVFS)} {$(LIBTKVFS)}\r\n<<\r\n!endif\r\n\r\n\r\n$(CAT32): $(_TCLDIR)\\win\\cat.c\r\n\t$(cc32) $(cflags) $(crt) /D_CRT_NONSTDC_NO_DEPRECATE /DCONSOLE /DUNICODE /D_UNICODE -Fo$(TMP_DIR)\\ $?\r\n\t$(CONEXECMD) -stack:16384 $(TMP_DIR)\\cat.obj\r\n\t$(_VC_MANIFEST_EMBED_EXE)\r\n\r\n#---------------------------------------------------------------------\r\n# Regenerate the stubs files.  [Development use only]\r\n#---------------------------------------------------------------------\r\n\r\ngenstubs:\r\n!if !exist($(TCLSH))\r\n\t@echo Build tclsh first!\r\n!else\r\n\tset TCL_LIBRARY=$(TCL_LIBRARY)\r\n\t$(TCLSH) $(_TCLDIR)\\tools\\genStubs.tcl $(GENERICDIR) \\\r\n\t\t$(GENERICDIR)\\$(PROJECT).decls $(GENERICDIR)\\$(PROJECT)Int.decls\r\n\t$(TCLSH) $(_TCLDIR)\\tools\\genStubs.tcl $(GENERICDIR)\\ttk $(GENERICDIR)\\ttk\\ttk.decls\r\n!endif\r\n\r\n\r\n#---------------------------------------------------------------------\r\n# Build the Windows HTML help file.\r\n#---------------------------------------------------------------------\r\n\r\n!if defined(PROCESSOR_ARCHITECTURE) && \"$(PROCESSOR_ARCHITECTURE)\" == \"AMD64\"\r\nHHC=\"%ProgramFiles(x86)%\\HTML Help Workshop\\hhc.exe\"\r\n!else\r\nHHC=\"%ProgramFiles%\\HTML Help Workshop\\hhc.exe\"\r\n!endif\r\nHTMLDIR=$(OUT_DIR)\\html\r\nHTMLBASE=TclTk$(TCL_VERSION)\r\nHHPFILE=$(HTMLDIR)\\$(HTMLBASE).hhp\r\nCHMFILE=$(HTMLDIR)\\$(HTMLBASE).chm\r\n\r\nhtmlhelp: $(CHMFILE)\r\n\r\nhtmldocs: $(DOCDIR)\\*\r\n\t@$(TCLSH) $(TCLTOOLSDIR)\\tcltk-man2html.tcl \"--htmldir=$(HTMLDIR)\"\r\n\r\n$(CHMFILE): htmldocs chmsetup\r\n\t@echo Compiling HTML help project\r\n\t-\"$(HHC)\" <<$(HHPFILE) >NUL\r\n[OPTIONS]\r\nCompatibility=1.1 or later\r\nCompiled file=$(HTMLBASE).chm\r\nDefault topic=index.html\r\nDisplay compile progress=no\r\nError log file=$(HTMLBASE).log\r\nFull-text search=Yes\r\nLanguage=0x409 English (United States)\r\nTitle=Tcl/Tk $(TCL_DOTVERSION) Help\r\n[FILES]\r\nindex.html\r\ndocs.css\r\nKeywords\\*.html\r\nTclCmd\\*.html\r\nTclLib\\*.html\r\nTkCmd\\*.html\r\nTkLib\\*.html\r\nUserCmd\\*.html\r\n<<\r\n\r\nchmsetup:\r\n\t@if not exist $(HTMLDIR)\\nul mkdir $(HTMLDIR)\r\n\r\ninstall-docs:\r\n!if exist(\"$(CHMFILE)\")\r\n\t@echo Installing compiled HTML help\r\n\t@$(CPY) \"$(CHMFILE)\" \"$(DOC_INSTALL_DIR)\\\"\r\n!endif\r\n# \"emacs font-lock highlighting fix\r\n\r\ninstall-pdbs:\r\n\t@echo Installing debug symbols\r\n\t@$(CPY) \"$(OUT_DIR)\\*.pdb\" \"$(BIN_INSTALL_DIR)\\\"\r\n# \"emacs font-lock highlighting fix\r\n\r\n#---------------------------------------------------------------------\r\n# Special case object file targets\r\n#---------------------------------------------------------------------\r\n\r\n# Note: Static builds now always mandate statically linking Tcl registry etc.\r\n$(TMP_DIR)\\testMain.obj: $(WIN_DIR)\\winMain.c\r\n\t$(cc32) $(appcflags_nostubs) /DTK_TEST /DUNICODE /D_UNICODE \\\r\n\t    /DTCL_USE_STATIC_PACKAGES=$(STATIC_BUILD) \\\r\n\t    -Fo$@ $?\r\n\r\n$(ROOT)\\manifest.uuid:\r\n   copy $(WIN_DIR)\\gitmanifest.in $(ROOT)\\manifest.uuid\r\n   git rev-parse HEAD >>$(ROOT)\\manifest.uuid\r\n\r\n$(TMP_DIR)\\tkUuid.h:\t$(ROOT)\\manifest.uuid\r\n\tcopy $(WIN_DIR)\\tkUuid.h.in+$(ROOT)\\manifest.uuid $(TMP_DIR)\\tkUuid.h\r\n\r\n$(TMP_DIR)\\tkTest.obj: $(GENERICDIR)\\tkTest.c\r\n\t$(cc32) $(appcflags_nostubs) -Fo$@ $?\r\n\r\n$(TMP_DIR)\\tkWinTest.obj: $(WIN_DIR)\\tkWinTest.c\r\n\t$(cc32) $(appcflags_nostubs) -Fo$@ $?\r\n\r\n$(TMP_DIR)\\tkSquare.obj: $(GENERICDIR)\\tkSquare.c\r\n\t$(cc32) $(appcflags_nostubs) -Fo$@ $?\r\n\r\n# Note: Static builds now always mandate statically linking Tcl registry etc.\r\n$(TMP_DIR)\\winMain.obj: $(WIN_DIR)\\winMain.c\r\n\t$(cc32) $(appcflags_nostubs) /DUNICODE /D_UNICODE \\\r\n\t    /DTCL_USE_STATIC_PACKAGES=$(STATIC_BUILD) \\\r\n\t    -Fo$@ $?\r\n\r\n$(TMP_DIR)\\tkMain2.obj: $(GENERICDIR)\\tkMain.c\r\n\t$(cc32) $(pkgcflags) /DUNICODE /D_UNICODE -Fo$@ $?\r\n\r\n$(TMP_DIR)\\tkPkgConfig.obj: $(GENERICDIR)\\tkPkgConfig.c\r\n\t$(cc32) $(pkgcflags)\t\t\\\r\n\t\t-DCFG_RUNTIME_DLLFILE=\"\\\"$(TKLIBNAME)\\\"\" \\\r\n\t\t-Fo$@ $?\r\n\r\n$(TMP_DIR)\\tkWindow.obj: $(GENERICDIR)\\tkWindow.c $(TMP_DIR)\\tkUuid.h\r\n\t$(cc32) $(pkgcflags) -I$(TMP_DIR) -Fo$@ $?\r\n\r\n# The following objects are part of the stub library and should not\r\n# be built as DLL objects but none of the symbols should be exported\r\n# and no reference made to a C runtime.\r\n\r\n$(TMP_DIR)\\tkStubLib.obj : $(GENERICDIR)\\tkStubLib.c\r\n\t$(cc32) $(stubscflags) -Fo$@ $?\r\n\r\n$(TMP_DIR)\\ttkStubLib.obj : $(TTKDIR)\\ttkStubLib.c\r\n\t$(cc32) $(stubscflags) -Fo$@ $?\r\n\r\n$(TMP_DIR)\\wish.exe.manifest: $(WIN_DIR)\\wish.exe.manifest.in\r\n\t@nmakehlp -s << $** >$@\r\n@MACHINE@\t  $(MACHINE:IX86=X86)\r\n@TK_WIN_VERSION@  $(DOTVERSION).0.0\r\n<<\r\n\r\n#---------------------------------------------------------------------\r\n# Generate the source dependencies.  Having dependency rules will\r\n# improve incremental build accuracy without having to resort to a\r\n# full rebuild just because some non-global header file like\r\n# tclCompile.h was changed.  These rules aren't needed when building\r\n# from scratch.\r\n#---------------------------------------------------------------------\r\n\r\ndepend:\r\n!if !exist($(TCLSH))\r\n\t@echo Build tclsh first!\r\n!else\r\n\tset TCL_LIBRARY=$(TCL_LIBRARY)\r\n\t$(TCLSH) $(TCLTOOLSDIR:\\=/)/mkdepend.tcl -vc32 -out:\"$(OUT_DIR)\\depend.mk\" \\\r\n\t\t-passthru:\"/DBUILD_tk $(TK_INCLUDES)\" $(GENERICDIR),$$(GENERICDIR) \\\r\n\t\t$(WIN_DIR),$$(WIN_DIR) $(TTKDIR),$$(TTKDIR) $(XLIBDIR),$$(XLIBDIR) \\\r\n\t\t$(BITMAPDIR),$$(BITMAPDIR) @<<\r\n$(TKOBJS)\r\n<<\r\n!endif\r\n\r\n#---------------------------------------------------------------------\r\n# Dependency rules\r\n#---------------------------------------------------------------------\r\n\r\n$(TMP_DIR)\\tk.res: \\\r\n    $(RCDIR)\\cursor*.cur \\\r\n    $(RCDIR)\\tk.ico\r\n\r\n!if exist(\"$(OUT_DIR)\\depend.mk\")\r\n!include \"$(OUT_DIR)\\depend.mk\"\r\n!message *** Dependency rules in use.\r\n!else\r\n!message *** Dependency rules are not being used.\r\n!endif\r\n\r\n### add a spacer in the output\r\n!message\r\n\r\n#---------------------------------------------------------------------\r\n# Implicit rules\r\n#---------------------------------------------------------------------\r\n\r\n{$(XLIBDIR)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(TTKDIR)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(ROOT)\\unix}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n$(TMP_DIR)\\tk.res: $(TMP_DIR)\\wish.exe.manifest\r\n$(TMP_DIR)\\wish.res: $(TMP_DIR)\\wish.exe.manifest\r\n$(TMP_DIR)\\tktest.res: $(TMP_DIR)\\wish.exe.manifest\r\n\r\n.SUFFIXES:\r\n.SUFFIXES:.c .rc\r\n\r\n\r\n#---------------------------------------------------------------------\r\n# Installation.\r\n#---------------------------------------------------------------------\r\n\r\ninstall-binaries:\r\n\t@echo installing binaries\r\n\t@$(CPY) \"$(WISH)\" \"$(BIN_INSTALL_DIR)\\\"\r\n!if \"$(TKLIB)\" != \"$(TKIMPLIB)\"\r\n\t@$(CPY) \"$(TKLIB)\" \"$(BIN_INSTALL_DIR)\\\"\r\n!endif\r\n\t@$(CPY) \"$(TKIMPLIB)\" \"$(LIB_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(TKSTUBLIB)\" \"$(LIB_INSTALL_DIR)\\\"\r\n!if !$(STATIC_BUILD)\r\n\t@echo creating package index\r\n\t@type << > $(OUT_DIR)\\pkgIndex.tcl\r\nif {![package vsatisfies [package provide Tcl] 9.0]} return\r\nif {($$::tcl_platform(platform) eq \"unix\") && ([info exists ::env(DISPLAY)]\r\n\t|| ([info exists ::argv] && (\"-display\" in $$::argv)))} {\r\n    package ifneeded tk $(TK_PATCH_LEVEL) [list load [file normalize [file join $$dir .. .. bin cygtcl9tk$(DOTVERSION).dll]]]\r\n} else {\r\n    package ifneeded tk $(TK_PATCH_LEVEL) [list load [file normalize [file join $$dir .. .. bin $(TKLIBNAME)]]]\r\n}\r\npackage ifneeded Tk $(TK_PATCH_LEVEL) [list package require -exact tk $(TK_PATCH_LEVEL)]\r\n<<\r\n\t@$(CPY) $(OUT_DIR)\\pkgIndex.tcl \"$(SCRIPT_INSTALL_DIR)\\\"\r\n!endif\r\n\r\n#\"\r\n\r\ninstall-libraries:\r\n\t@echo installing Tk headers\r\n\t@$(CPY) \"$(GENERICDIR)\\tk.h\" \"$(INCLUDE_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(GENERICDIR)\\tkDecls.h\" \"$(INCLUDE_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(GENERICDIR)\\tkPlatDecls.h\" \"$(INCLUDE_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(GENERICDIR)\\tkIntXlibDecls.h\" \"$(INCLUDE_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(XLIBDIR)\\X11\\*.h\" \"$(INCLUDE_INSTALL_DIR)\\X11\\\"\r\n\t@$(CPY) \"$(TKSCRIPTZIP)\" \"$(LIB_INSTALL_DIR)\"\r\n!if !$(TK_EMBED_SCRIPTS)\r\n\t@echo installing script library\r\n\t@$(CPY) \"$(LIBDIR)\\*\" \"$(SCRIPT_INSTALL_DIR)\\\"\r\n\t@echo installing theme library\r\n\t@$(CPY) \"$(LIBDIR)\\ttk\\*\" \"$(SCRIPT_INSTALL_DIR)\\ttk\\\"\r\n\t@echo installing images\r\n\t@$(CPY) \"$(LIBDIR)\\images\\*\" \"$(SCRIPT_INSTALL_DIR)\\images\\\"\r\n\t@echo installing language files\r\n\t@$(CPY) \"$(LIBDIR)\\msgs\\*\" \"$(SCRIPT_INSTALL_DIR)\\msgs\\\"\r\n!endif\r\n\t@echo installing demos\r\n\t@$(CPY) \"$(DEMODIR)\\*\" \"$(DEMO_INSTALL_DIR)\\\"\r\n\t@$(CPY) \"$(DEMODIR)\\images\\*\" \"$(DEMO_INSTALL_DIR)\\images\\\"\r\n\r\n#\"\r\n\r\n#---------------------------------------------------------------------\r\n# Clean up\r\n#---------------------------------------------------------------------\r\n\r\nclean: default-clean\r\nrealclean: hose\r\nhose: default-hose\r\ntidy:\r\n!if \"$(TKLIB)\" != \"$(TKIMPLIB)\"\r\n\t@echo Removing $(TKLIB) ...\r\n\t@if exist $(TKLIB) del $(TKLIB)\r\n!endif\r\n\t@echo Removing $(TKIMPLIB) ...\r\n\t@if exist $(TKIMPLIB) del $(TKIMPLIB)\r\n\t@echo Removing $(WISH) ...\r\n\t@if exist $(WISH) del $(WISH)\r\n\t@echo Removing $(TKTEST) ...\r\n\t@if exist $(TKTEST) del $(TKTEST)\r\n\t@echo Removing $(TKSTUBLIB) ...\r\n\t@if exist $(TKSTUBLIB) del $(TKSTUBLIB)\r\n\r\n.PHONY:\r\n\r\n# Local Variables:\r\n# mode: makefile\r\n# End:\r\n"
  },
  {
    "path": "win/nmakehlp.c",
    "content": "/*\n * ----------------------------------------------------------------------------\n * nmakehlp.c --\n *\n *\tThis is used to fix limitations within nmake and the environment.\n *\n * Copyright (c) 2002 David Gravereaux.\n * Copyright (c) 2006 Pat Thoyts\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n * ----------------------------------------------------------------------------\n */\n\n#define _CRT_SECURE_NO_DEPRECATE\n#include <windows.h>\n#ifdef _MSC_VER\n#pragma comment (lib, \"user32.lib\")\n#pragma comment (lib, \"kernel32.lib\")\n#endif\n#include <stdio.h>\n\n/*\n * This library is required for x64 builds with _some_ versions of MSVC\n */\n#if defined(_M_IA64) || defined(_M_AMD64)\n#if _MSC_VER >= 1400 && _MSC_VER < 1500\n#pragma comment(lib, \"bufferoverflowU\")\n#endif\n#endif\n\n/* ISO hack for dumb VC++ */\n#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1900\n#define   snprintf\t_snprintf\n#endif\n\n\n/* protos */\n\nstatic int CheckForCompilerFeature(const char *option);\nstatic int CheckForLinkerFeature(char **options, int count);\nstatic int IsIn(const char *string, const char *substring);\nstatic int SubstituteFile(const char *substs, const char *filename);\nstatic int QualifyPath(const char *path);\nstatic int LocateDependency(const char *keyfile);\nstatic const char *GetVersionFromFile(const char *filename, const char *match, int numdots);\nstatic DWORD WINAPI ReadFromPipe(LPVOID args);\n\n/* globals */\n\n#define CHUNK\t25\n#define STATICBUFFERSIZE    1000\ntypedef struct {\n    HANDLE pipe;\n    char buffer[STATICBUFFERSIZE];\n} pipeinfo;\n\npipeinfo Out = {INVALID_HANDLE_VALUE, \"\"};\npipeinfo Err = {INVALID_HANDLE_VALUE, \"\"};\n\f\n/*\n * exitcodes: 0 == no, 1 == yes, 2 == error\n */\n\nint\nmain(\n    int argc,\n    char *argv[])\n{\n    char msg[300];\n    DWORD dwWritten;\n    int chars;\n    const char *s;\n\n    /*\n     * Make sure children (cl.exe and link.exe) are kept quiet.\n     */\n\n    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);\n\n    /*\n     * Make sure the compiler and linker aren't effected by the outside world.\n     */\n\n    SetEnvironmentVariable(\"CL\", \"\");\n    SetEnvironmentVariable(\"LINK\", \"\");\n\n    if (argc > 1 && *argv[1] == '-') {\n\tswitch (*(argv[1]+1)) {\n\tcase 'c':\n\t    if (argc != 3) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t\t\"usage: %s -c <compiler option>\\n\"\n\t\t\t\"Tests for whether cl.exe supports an option\\n\"\n\t\t\t\"exitcodes: 0 == no, 1 == yes, 2 == error\\n\", argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t\t&dwWritten, NULL);\n\t\treturn 2;\n\t    }\n\t    return CheckForCompilerFeature(argv[2]);\n\tcase 'l':\n\t    if (argc < 3) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t\t\"usage: %s -l <linker option> ?<mandatory option> ...?\\n\"\n\t\t\t\"Tests for whether link.exe supports an option\\n\"\n\t\t\t\"exitcodes: 0 == no, 1 == yes, 2 == error\\n\", argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t\t&dwWritten, NULL);\n\t\treturn 2;\n\t    }\n\t    return CheckForLinkerFeature(&argv[2], argc-2);\n\tcase 'f':\n\t    if (argc == 2) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t\t\"usage: %s -f <string> <substring>\\n\"\n\t\t\t\"Find a substring within another\\n\"\n\t\t\t\"exitcodes: 0 == no, 1 == yes, 2 == error\\n\", argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t\t&dwWritten, NULL);\n\t\treturn 2;\n\t    } else if (argc == 3) {\n\t\t/*\n\t\t * If the string is blank, there is no match.\n\t\t */\n\n\t\treturn 0;\n\t    } else {\n\t\treturn IsIn(argv[2], argv[3]);\n\t    }\n\tcase 's':\n\t    if (argc == 2) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t\t\"usage: %s -s <substitutions file> <file>\\n\"\n\t\t\t\"Perform a set of string map type substutitions on a file\\n\"\n\t\t\t\"exitcodes: 0\\n\",\n\t\t\targv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t\t&dwWritten, NULL);\n\t\treturn 2;\n\t    }\n\t    return SubstituteFile(argv[2], argv[3]);\n\tcase 'V':\n\t    if (argc != 4) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t    \"usage: %s -V filename matchstring\\n\"\n\t\t    \"Extract a version from a file:\\n\"\n\t\t    \"eg: pkgIndex.tcl \\\"package ifneeded http\\\"\",\n\t\t    argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t    &dwWritten, NULL);\n\t\treturn 0;\n\t    }\n\t    s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');\n\t    if (s && *s) {\n\t\tprintf(\"%s\\n\", s);\n\t\treturn 0;\n\t    } else\n\t\treturn 1; /* Version not found. Return non-0 exit code */\n\n\tcase 'Q':\n\t    if (argc != 3) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t    \"usage: %s -Q path\\n\"\n\t\t    \"Emit the fully qualified path\\n\"\n\t\t    \"exitcodes: 0 == no, 1 == yes, 2 == error\\n\", argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t    &dwWritten, NULL);\n\t\treturn 2;\n\t    }\n\t    return QualifyPath(argv[2]);\n\n\tcase 'L':\n\t    if (argc != 3) {\n\t\tchars = snprintf(msg, sizeof(msg) - 1,\n\t\t    \"usage: %s -L keypath\\n\"\n\t\t    \"Emit the fully qualified path of directory containing keypath\\n\"\n\t\t    \"exitcodes: 0 == success, 1 == not found, 2 == error\\n\", argv[0]);\n\t\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,\n\t\t    &dwWritten, NULL);\n\t\treturn 2;\n\t    }\n\t    return LocateDependency(argv[2]);\n\t}\n    }\n    chars = snprintf(msg, sizeof(msg) - 1,\n\t    \"usage: %s -c|-f|-l|-Q|-s|-V ...\\n\"\n\t    \"This is a little helper app to equalize shell differences between WinNT and\\n\"\n\t    \"Win9x and get nmake.exe to accomplish its job.\\n\",\n\t    argv[0]);\n    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);\n    return 2;\n}\n\f\nstatic int\nCheckForCompilerFeature(\n    const char *option)\n{\n    STARTUPINFO si;\n    PROCESS_INFORMATION pi;\n    SECURITY_ATTRIBUTES sa;\n    DWORD threadID;\n    char msg[300];\n    BOOL ok;\n    HANDLE hProcess, h, pipeThreads[2];\n    char cmdline[100];\n\n    hProcess = GetCurrentProcess();\n\n    memset(&pi, 0, sizeof(PROCESS_INFORMATION));\n    memset(&si, 0, sizeof(STARTUPINFO));\n    si.cb = sizeof(STARTUPINFO);\n    si.dwFlags   = STARTF_USESTDHANDLES;\n    si.hStdInput = INVALID_HANDLE_VALUE;\n\n    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));\n    sa.nLength = sizeof(SECURITY_ATTRIBUTES);\n    sa.lpSecurityDescriptor = NULL;\n    sa.bInheritHandle = FALSE;\n\n    /*\n     * Create a non-inheritable pipe.\n     */\n\n    CreatePipe(&Out.pipe, &h, &sa, 0);\n\n    /*\n     * Dupe the write side, make it inheritable, and close the original.\n     */\n\n    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,\n\t    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\n    /*\n     * Same as above, but for the error side.\n     */\n\n    CreatePipe(&Err.pipe, &h, &sa, 0);\n    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,\n\t    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\n    /*\n     * Base command line.\n     */\n\n    lstrcpy(cmdline, \"cl.exe -nologo -c -TC -Zs -X -Fp.\\\\_junk.pch \");\n\n    /*\n     * Append our option for testing\n     */\n\n    lstrcat(cmdline, option);\n\n    /*\n     * Filename to compile, which exists, but is nothing and empty.\n     */\n\n    lstrcat(cmdline, \" .\\\\nul\");\n\n    ok = CreateProcess(\n\t    NULL,\t    /* Module name. */\n\t    cmdline,\t    /* Command line. */\n\t    NULL,\t    /* Process handle not inheritable. */\n\t    NULL,\t    /* Thread handle not inheritable. */\n\t    TRUE,\t    /* yes, inherit handles. */\n\t    DETACHED_PROCESS, /* No console for you. */\n\t    NULL,\t    /* Use parent's environment block. */\n\t    NULL,\t    /* Use parent's starting directory. */\n\t    &si,\t    /* Pointer to STARTUPINFO structure. */\n\t    &pi);\t    /* Pointer to PROCESS_INFORMATION structure. */\n\n    if (!ok) {\n\tDWORD err = GetLastError();\n\tint chars = snprintf(msg, sizeof(msg) - 1,\n\t\t\"Tried to launch: \\\"%s\\\", but got error [%lu]: \", cmdline, err);\n\n\tFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|\n\t\tFORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],\n\t\t(300-chars), 0);\n\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);\n\treturn 2;\n    }\n\n    /*\n     * Close our references to the write handles that have now been inherited.\n     */\n\n    CloseHandle(si.hStdOutput);\n    CloseHandle(si.hStdError);\n\n    WaitForInputIdle(pi.hProcess, 5000);\n    CloseHandle(pi.hThread);\n\n    /*\n     * Start the pipe reader threads.\n     */\n\n    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);\n    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);\n\n    /*\n     * Block waiting for the process to end.\n     */\n\n    WaitForSingleObject(pi.hProcess, INFINITE);\n    CloseHandle(pi.hProcess);\n\n    /*\n     * Wait for our pipe to get done reading, should it be a little slow.\n     */\n\n    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);\n    CloseHandle(pipeThreads[0]);\n    CloseHandle(pipeThreads[1]);\n\n    /*\n     * Look for the commandline warning code in both streams.\n     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.\n     */\n\n    return !(strstr(Out.buffer, \"D4002\") != NULL\n\t    || strstr(Err.buffer, \"D4002\") != NULL\n\t    || strstr(Out.buffer, \"D9002\") != NULL\n\t    || strstr(Err.buffer, \"D9002\") != NULL\n\t    || strstr(Out.buffer, \"D2021\") != NULL\n\t    || strstr(Err.buffer, \"D2021\") != NULL);\n}\n\f\nstatic int\nCheckForLinkerFeature(\n    char **options,\n    int count)\n{\n    STARTUPINFO si;\n    PROCESS_INFORMATION pi;\n    SECURITY_ATTRIBUTES sa;\n    DWORD threadID;\n    char msg[300];\n    BOOL ok;\n    HANDLE hProcess, h, pipeThreads[2];\n    int i;\n    char cmdline[255];\n\n    hProcess = GetCurrentProcess();\n\n    memset(&pi, 0, sizeof(PROCESS_INFORMATION));\n    memset(&si, 0, sizeof(STARTUPINFO));\n    si.cb = sizeof(STARTUPINFO);\n    si.dwFlags   = STARTF_USESTDHANDLES;\n    si.hStdInput = INVALID_HANDLE_VALUE;\n\n    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));\n    sa.nLength = sizeof(SECURITY_ATTRIBUTES);\n    sa.lpSecurityDescriptor = NULL;\n    sa.bInheritHandle = TRUE;\n\n    /*\n     * Create a non-inheritible pipe.\n     */\n\n    CreatePipe(&Out.pipe, &h, &sa, 0);\n\n    /*\n     * Dupe the write side, make it inheritable, and close the original.\n     */\n\n    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,\n\t    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\n    /*\n     * Same as above, but for the error side.\n     */\n\n    CreatePipe(&Err.pipe, &h, &sa, 0);\n    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,\n\t    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\n    /*\n     * Base command line.\n     */\n\n    lstrcpy(cmdline, \"link.exe -nologo \");\n\n    /*\n     * Append our option for testing.\n     */\n\n    for (i = 0; i < count; i++) {\n\tlstrcat(cmdline, \" \\\"\");\n\tlstrcat(cmdline, options[i]);\n\tlstrcat(cmdline, \"\\\"\");\n    }\n\n    ok = CreateProcess(\n\t    NULL,\t    /* Module name. */\n\t    cmdline,\t    /* Command line. */\n\t    NULL,\t    /* Process handle not inheritable. */\n\t    NULL,\t    /* Thread handle not inheritable. */\n\t    TRUE,\t    /* yes, inherit handles. */\n\t    DETACHED_PROCESS, /* No console for you. */\n\t    NULL,\t    /* Use parent's environment block. */\n\t    NULL,\t    /* Use parent's starting directory. */\n\t    &si,\t    /* Pointer to STARTUPINFO structure. */\n\t    &pi);\t    /* Pointer to PROCESS_INFORMATION structure. */\n\n    if (!ok) {\n\tDWORD err = GetLastError();\n\tint chars = snprintf(msg, sizeof(msg) - 1,\n\t\t\"Tried to launch: \\\"%s\\\", but got error [%lu]: \", cmdline, err);\n\n\tFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|\n\t\tFORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],\n\t\t(300-chars), 0);\n\tWriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err, NULL);\n\treturn 2;\n    }\n\n    /*\n     * Close our references to the write handles that have now been inherited.\n     */\n\n    CloseHandle(si.hStdOutput);\n    CloseHandle(si.hStdError);\n\n    WaitForInputIdle(pi.hProcess, 5000);\n    CloseHandle(pi.hThread);\n\n    /*\n     * Start the pipe reader threads.\n     */\n\n    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);\n    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);\n\n    /*\n     * Block waiting for the process to end.\n     */\n\n    WaitForSingleObject(pi.hProcess, INFINITE);\n    CloseHandle(pi.hProcess);\n\n    /*\n     * Wait for our pipe to get done reading, should it be a little slow.\n     */\n\n    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);\n    CloseHandle(pipeThreads[0]);\n    CloseHandle(pipeThreads[1]);\n\n    /*\n     * Look for the commandline warning code in the stderr stream.\n     */\n\n    return !(strstr(Out.buffer, \"LNK1117\") != NULL ||\n\t    strstr(Err.buffer, \"LNK1117\") != NULL ||\n\t    strstr(Out.buffer, \"LNK4044\") != NULL ||\n\t    strstr(Err.buffer, \"LNK4044\") != NULL ||\n\t    strstr(Out.buffer, \"LNK4224\") != NULL ||\n\t    strstr(Err.buffer, \"LNK4224\") != NULL);\n}\n\f\nstatic DWORD WINAPI\nReadFromPipe(\n    LPVOID args)\n{\n    pipeinfo *pi = (pipeinfo *) args;\n    char *lastBuf = pi->buffer;\n    DWORD dwRead;\n    BOOL ok;\n\n  again:\n    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {\n\tCloseHandle(pi->pipe);\n\treturn (DWORD)-1;\n    }\n    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);\n    if (!ok || dwRead == 0) {\n\tCloseHandle(pi->pipe);\n\treturn 0;\n    }\n    lastBuf += dwRead;\n    goto again;\n\n    return 0;  /* makes the compiler happy */\n}\n\f\nstatic int\nIsIn(\n    const char *string,\n    const char *substring)\n{\n    return (strstr(string, substring) != NULL);\n}\n\f\n/*\n * GetVersionFromFile --\n *\tLooks for a match string in a file and then returns the version\n *\tfollowing the match where a version is anything acceptable to\n *\tpackage provide or package ifneeded.\n */\n\nstatic const char *\nGetVersionFromFile(\n    const char *filename,\n    const char *match,\n    int numdots)\n{\n    static char szBuffer[100];\n    char *szResult = NULL;\n    FILE *fp = fopen(filename, \"rt\");\n\n    if (fp != NULL) {\n\t/*\n\t * Read data until we see our match string.\n\t */\n\n\twhile (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {\n\t    LPSTR p, q;\n\n\t    p = strstr(szBuffer, match);\n\t    if (p != NULL) {\n\t\t/*\n\t\t * Skip to first digit after the match.\n\t\t */\n\n\t\tp += strlen(match);\n\t\twhile (*p && !isdigit((unsigned char)*p)) {\n\t\t    ++p;\n\t\t}\n\n\t\t/*\n\t\t * Find ending whitespace.\n\t\t */\n\n\t\tq = p;\n\t\twhile (*q && (strchr(\"0123456789.ab\", *q)) && (((!strchr(\".ab\", *q)\n\t\t\t    && !strchr(\"ab\", q[-1])) || --numdots))) {\n\t\t    ++q;\n\t\t}\n\n\t\t*q = 0;\n\t\tszResult = p;\n\t\tbreak;\n\t    }\n\t}\n\tfclose(fp);\n    }\n    return szResult;\n}\n\f\n/*\n * List helpers for the SubstituteFile function\n */\n\ntypedef struct list_item_t {\n    struct list_item_t *nextPtr;\n    char * key;\n    char * value;\n} list_item_t;\n\n/* insert a list item into the list (list may be null) */\nstatic list_item_t *\nlist_insert(list_item_t **listPtrPtr, const char *key, const char *value)\n{\n    list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));\n    if (itemPtr) {\n\titemPtr->key = strdup(key);\n\titemPtr->value = strdup(value);\n\titemPtr->nextPtr = NULL;\n\n\twhile(*listPtrPtr) {\n\t    listPtrPtr = &(*listPtrPtr)->nextPtr;\n\t}\n\t*listPtrPtr = itemPtr;\n    }\n    return itemPtr;\n}\n\nstatic void\nlist_free(list_item_t **listPtrPtr)\n{\n    list_item_t *tmpPtr, *listPtr = *listPtrPtr;\n    while (listPtr) {\n\ttmpPtr = listPtr;\n\tlistPtr = listPtr->nextPtr;\n\tfree(tmpPtr->key);\n\tfree(tmpPtr->value);\n\tfree(tmpPtr);\n    }\n}\n\f\n/*\n * SubstituteFile --\n *\tAs windows doesn't provide anything useful like sed and it's unreliable\n *\tto use the tclsh you are building against (consider x-platform builds -\n *\te.g. compiling AMD64 target from IX86) we provide a simple substitution\n *\toption here to handle autoconf style substitutions.\n *\tThe substitution file is whitespace and line delimited. The file should\n *\tconsist of lines matching the regular expression:\n *\t  \\s*\\S+\\s+\\S*$\n *\n *\tUsage is something like:\n *\t  nmakehlp -S << $** > $@\n *\t    @PACKAGE_NAME@ $(PACKAGE_NAME)\n *\t    @PACKAGE_VERSION@ $(PACKAGE_VERSION)\n *\t    <<\n */\n\nstatic int\nSubstituteFile(\n    const char *substitutions,\n    const char *filename)\n{\n    static char szBuffer[1024], szCopy[1024];\n    list_item_t *substPtr = NULL;\n    FILE *fp, *sp;\n\n    fp = fopen(filename, \"rt\");\n    if (fp != NULL) {\n\n\t/*\n\t * Build a list of substitutions from the first filename\n\t */\n\n\tsp = fopen(substitutions, \"rt\");\n\tif (sp != NULL) {\n\t    while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {\n\t\tunsigned char *ks, *ke, *vs, *ve;\n\t\tks = (unsigned char*)szBuffer;\n\t\twhile (ks && *ks && isspace(*ks)) ++ks;\n\t\tke = ks;\n\t\twhile (ke && *ke && !isspace(*ke)) ++ke;\n\t\tvs = ke;\n\t\twhile (vs && *vs && isspace(*vs)) ++vs;\n\t\tve = vs;\n\t\twhile (ve && *ve && !(*ve == '\\r' || *ve == '\\n')) ++ve;\n\t\t*ke = 0, *ve = 0;\n\t\tlist_insert(&substPtr, (char*)ks, (char*)vs);\n\t    }\n\t    fclose(sp);\n\t}\n\n\t/* debug: dump the list */\n#ifndef NDEBUG\n\t{\n\t    int n = 0;\n\t    list_item_t *p = NULL;\n\t    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {\n\t\tfprintf(stderr, \"% 3d '%s' => '%s'\\n\", n, p->key, p->value);\n\t    }\n\t}\n#endif\n\n\t/*\n\t * Run the substitutions over each line of the input\n\t */\n\n\twhile (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {\n\t    list_item_t *p = NULL;\n\t    for (p = substPtr; p != NULL; p = p->nextPtr) {\n\t\tchar *m = strstr(szBuffer, p->key);\n\t\tif (m) {\n\t\t    char *cp, *op, *sp;\n\t\t    cp = szCopy;\n\t\t    op = szBuffer;\n\t\t    while (op != m) *cp++ = *op++;\n\t\t    sp = p->value;\n\t\t    while (sp && *sp) *cp++ = *sp++;\n\t\t    op += strlen(p->key);\n\t\t    while (*op) *cp++ = *op++;\n\t\t    *cp = 0;\n\t\t    memcpy(szBuffer, szCopy, sizeof(szCopy));\n\t\t}\n\t    }\n\t    printf(\"%s\", szBuffer);\n\t}\n\n\tlist_free(&substPtr);\n    }\n    fclose(fp);\n    return 0;\n}\n\f\nBOOL FileExists(LPCTSTR szPath)\n{\n#ifndef INVALID_FILE_ATTRIBUTES\n    #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)\n#endif\n    DWORD pathAttr = GetFileAttributes(szPath);\n    return (pathAttr != INVALID_FILE_ATTRIBUTES &&\n\t    !(pathAttr & FILE_ATTRIBUTE_DIRECTORY));\n}\n\f\n\n/*\n * QualifyPath --\n *\n *\tThis composes the current working directory with a provided path\n *\tand returns the fully qualified and normalized path.\n *\tMostly needed to setup paths for testing.\n */\n\nstatic int\nQualifyPath(\n    const char *szPath)\n{\n    char szCwd[MAX_PATH + 1];\n\n    GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);\n    printf(\"%s\\n\", szCwd);\n    return 0;\n}\n\n/*\n * Implements LocateDependency for a single directory. See that command\n * for an explanation.\n * Returns 0 if found after printing the directory.\n * Returns 1 if not found but no errors.\n * Returns 2 on any kind of error\n * Basically, these are used as exit codes for the process.\n */\nstatic int LocateDependencyHelper(const char *dir, const char *keypath)\n{\n    HANDLE hSearch;\n    char path[MAX_PATH+1];\n    size_t dirlen;\n    int keylen, ret;\n    WIN32_FIND_DATA finfo;\n\n    if (dir == NULL || keypath == NULL) {\n\treturn 2; /* Have no real error reporting mechanism into nmake */\n    }\n    dirlen = strlen(dir);\n    if (dirlen > sizeof(path) - 3) {\n\treturn 2;\n    }\n    strncpy(path, dir, dirlen);\n    strncpy(path+dirlen, \"\\\\*\", 3);\t/* Including terminating \\0 */\n    keylen = strlen(keypath);\n\n#if 0 /* This function is not available in Visual C++ 6 */\n    /*\n     * Use numerics 0 -> FindExInfoStandard,\n     * 1 -> FindExSearchLimitToDirectories,\n     * as these are not defined in Visual C++ 6\n     */\n    hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);\n#else\n    hSearch = FindFirstFile(path, &finfo);\n#endif\n    if (hSearch == INVALID_HANDLE_VALUE) {\n\treturn 1; /* Not found */\n    }\n\n    /* Loop through all subdirs checking if the keypath is under there */\n    ret = 1; /* Assume not found */\n    do {\n\tint sublen;\n\t/*\n\t * We need to check it is a directory despite the\n\t * FindExSearchLimitToDirectories in the above call. See SDK docs\n\t */\n\tif ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {\n\t    continue;\n\t}\n\tsublen = strlen(finfo.cFileName);\n\tif ((dirlen+1+sublen+1+keylen+1) > sizeof(path)) {\n\t    continue;\t\t/* Path does not fit, assume not matched */\n\t}\n\tstrncpy(path+dirlen+1, finfo.cFileName, sublen);\n\tpath[dirlen+1+sublen] = '\\\\';\n\tstrncpy(path+dirlen+1+sublen+1, keypath, keylen+1);\n\tif (FileExists(path)) {\n\t    /* Found a match, print to stdout */\n\t    path[dirlen+1+sublen] = '\\0';\n\t    QualifyPath(path);\n\t    ret = 0;\n\t    break;\n\t}\n    } while (FindNextFile(hSearch, &finfo));\n    FindClose(hSearch);\n    return ret;\n}\n\n/*\n * LocateDependency --\n *\n *\tLocates a dependency for a package.\n *\t    keypath - a relative path within the package directory\n *\t      that is used to confirm it is the correct directory.\n *\tThe search path for the package directory is currently only\n *\t    the parent and grandparent of the current working directory.\n *\t    If found, the command prints\n *\t      name_DIRPATH=<full path of located directory>\n *\t    and returns 0. If not found, does not print anything and returns 1.\n */\nstatic int LocateDependency(const char *keypath)\n{\n    size_t i;\n    int ret;\n    static const char *const paths[] = {\"..\", \"..\\\\..\", \"..\\\\..\\\\..\"};\n\n    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {\n\tret = LocateDependencyHelper(paths[i], keypath);\n\tif (ret == 0) {\n\t    return ret;\n\t}\n    }\n    return ret;\n}\n\n\n/*\n * Local variables:\n *   mode: c\n *   c-basic-offset: 4\n *   fill-column: 78\n *   indent-tabs-mode: t\n *   tab-width: 8\n * End:\n */\n"
  },
  {
    "path": "win/rc/tk.rc",
    "content": "//\r\n// Version Resource Script\r\n//\r\n\r\n#include <windows.h>\r\n#include <tk.h>\r\n\r\n//\r\n// build-up the name suffix that defines the type of build this is.\r\n//\r\n#if DEBUG && !UNCHECKED\r\n#define SUFFIX_DEBUG\t    \"g\"\r\n#else\r\n#define SUFFIX_DEBUG\t    \"\"\r\n#endif\r\n\r\n#define SUFFIX\t\t    SUFFIX_DEBUG\r\n\r\n\r\nVS_VERSION_INFO\tVERSIONINFO\r\n FILEVERSION\tTK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n PRODUCTVERSION\tTK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n FILEFLAGSMASK\t0x3fL\r\n#ifdef DEBUG\r\n FILEFLAGS\tVS_FF_DEBUG\r\n#else\r\n FILEFLAGS\t0x0L\r\n#endif\r\n FILEOS\t\tVOS__WINDOWS32\r\n FILETYPE\tVFT_DLL\r\n FILESUBTYPE\t0x0L\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n\tBLOCK \"040904b0\"\r\n\tBEGIN\r\n\t    VALUE \"FileDescription\", \"Tk DLL\\0\"\r\n\t    VALUE \"OriginalFilename\", \"tk\" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX \".dll\\0\"\r\n\t    VALUE \"FileVersion\", TK_PATCH_LEVEL\r\n\t    VALUE \"LegalCopyright\", \"Copyright \\251 1987-2022 Regents of the University of California and other parties\\0\"\r\n\t    VALUE \"ProductName\", \"Tk \" TK_VERSION \" for Windows\\0\"\r\n\t    VALUE \"ProductVersion\", TK_PATCH_LEVEL\r\n\tEND\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n\tVALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n//\r\n//  Include the base resources.\r\n//\r\n\r\n#include \"tk_base.rc\"\r\n\r\n//\r\n// This enables themed scrollbars in XP by trying to use comctl32 v6.\r\n//\r\n\r\n#ifndef RT_MANIFEST\r\n#define RT_MANIFEST     24\r\n#endif\r\n#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID\r\n#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1\r\n#endif\r\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST \"wish.exe.manifest\"\r\n"
  },
  {
    "path": "win/rc/tk_base.rc",
    "content": "//\r\n//  Base resources needed by Tk whether it's a DLL or a static library.\r\n//\r\n\r\n#include <windows.h>\r\n\r\n//\r\n//  Tk Icon\r\n//\r\n//  The BASE_NO_TK_ICON symbol can be defined to avoid\r\n//  creating an icon named \"tk\" in this resource file.\r\n//  The user can then create another icon named tk in\r\n//  another resource file and link both resource files.\r\n//  Tk will then use the custom icon instead of tk.ico.\r\n\r\n#ifndef BASE_NO_TK_ICON\r\ntk                      ICON    DISCARDABLE     \"tk.ico\"\r\n#endif\r\n\r\n#include <dlgs.h>\r\n\r\nFILEOPENORD DIALOG DISCARDABLE  36, 24, 218, 138\r\nSTYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU\r\nCAPTION \"Choose Directory\"\r\nFONT 8, \"Helv\"\r\nBEGIN\r\n    LTEXT           \"Directory &name:\",-1,8,6,118,9\r\n    EDITTEXT        edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL\r\n    LISTBOX         lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED |\r\n\t\t    LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT |\r\n\t\t    LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP\r\n    LTEXT           \"Dri&ves:\",stc4,8,106,92,9\r\n    COMBOBOX        cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |\r\n\t\t    CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |\r\n\t\t    WS_VSCROLL | WS_TABSTOP\r\n    DEFPUSHBUTTON   \"OK\",1,160,6,50,14,WS_GROUP\r\n    PUSHBUTTON      \"Cancel\",2,160,24,50,14,WS_GROUP\r\n    PUSHBUTTON      \"&Help\",psh15,160,42,50,14,WS_GROUP\r\n    CHECKBOX        \"&Read only\",chx1,160,66,50,12,WS_GROUP\r\n    PUSHBUTTON      \"Net&work...\",psh14,160,115,50,14,WS_GROUP\r\n\r\n    LTEXT           \"a\",stc3,9,143,114,15\r\n    EDITTEXT        edt1,7,158,135,20,NOT WS_TABSTOP\r\n    LISTBOX         lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT\r\n    COMBOBOX        cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |\r\n\t\t    CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |\r\n\t\t    WS_VSCROLL\r\n\r\nEND\r\n\r\n\r\n//\r\n// Cursors\r\n//\r\n\r\nX_cursor                CURSOR  DISCARDABLE     \"cursor00.cur\"\r\narrow                   CURSOR  DISCARDABLE     \"cursor02.cur\"\r\nbased_arrow_down        CURSOR  DISCARDABLE     \"cursor04.cur\"\r\nbased_arrow_up          CURSOR  DISCARDABLE     \"cursor06.cur\"\r\nboat                    CURSOR  DISCARDABLE     \"cursor08.cur\"\r\nbogosity                CURSOR  DISCARDABLE     \"cursor0a.cur\"\r\nbottom_left_corner      CURSOR  DISCARDABLE     \"cursor0c.cur\"\r\nbottom_right_corner     CURSOR  DISCARDABLE     \"cursor0e.cur\"\r\nbottom_side             CURSOR  DISCARDABLE     \"cursor10.cur\"\r\nbottom_tee              CURSOR  DISCARDABLE     \"cursor12.cur\"\r\nbox_spiral              CURSOR  DISCARDABLE     \"cursor14.cur\"\r\ncenter_ptr              CURSOR  DISCARDABLE     \"cursor16.cur\"\r\ncircle                  CURSOR  DISCARDABLE     \"cursor18.cur\"\r\nclock                   CURSOR  DISCARDABLE     \"cursor1a.cur\"\r\ncoffee_mug              CURSOR  DISCARDABLE     \"cursor1c.cur\"\r\ncross                   CURSOR  DISCARDABLE     \"cursor1e.cur\"\r\ncross_reverse           CURSOR  DISCARDABLE     \"cursor20.cur\"\r\ncrosshair               CURSOR  DISCARDABLE     \"cursor22.cur\"\r\ndiamond_cross           CURSOR  DISCARDABLE     \"cursor24.cur\"\r\ndot                     CURSOR  DISCARDABLE     \"cursor26.cur\"\r\ndotbox                  CURSOR  DISCARDABLE     \"cursor28.cur\"\r\ndouble_arrow            CURSOR  DISCARDABLE     \"cursor2a.cur\"\r\ndraft_large             CURSOR  DISCARDABLE     \"cursor2c.cur\"\r\ndraft_small             CURSOR  DISCARDABLE     \"cursor2e.cur\"\r\ndraped_box              CURSOR  DISCARDABLE     \"cursor30.cur\"\r\nexchange                CURSOR  DISCARDABLE     \"cursor32.cur\"\r\nfleur                   CURSOR  DISCARDABLE     \"cursor34.cur\"\r\ngobbler                 CURSOR  DISCARDABLE     \"cursor36.cur\"\r\ngumby                   CURSOR  DISCARDABLE     \"cursor38.cur\"\r\nhand1                   CURSOR  DISCARDABLE     \"cursor3a.cur\"\r\nhand2                   CURSOR  DISCARDABLE     \"cursor3c.cur\"\r\nheart                   CURSOR  DISCARDABLE     \"cursor3e.cur\"\r\nicon                    CURSOR  DISCARDABLE     \"cursor40.cur\"\r\niron_cross              CURSOR  DISCARDABLE     \"cursor42.cur\"\r\nleft_ptr                CURSOR  DISCARDABLE     \"cursor44.cur\"\r\nleft_side               CURSOR  DISCARDABLE     \"cursor46.cur\"\r\nleft_tee                CURSOR  DISCARDABLE     \"cursor48.cur\"\r\nleftbutton              CURSOR  DISCARDABLE     \"cursor4a.cur\"\r\nll_angle                CURSOR  DISCARDABLE     \"cursor4c.cur\"\r\nlr_angle                CURSOR  DISCARDABLE     \"cursor4e.cur\"\r\nman                     CURSOR  DISCARDABLE     \"cursor50.cur\"\r\nmiddlebutton            CURSOR  DISCARDABLE     \"cursor52.cur\"\r\nmouse                   CURSOR  DISCARDABLE     \"cursor54.cur\"\r\npencil                  CURSOR  DISCARDABLE     \"cursor56.cur\"\r\npirate                  CURSOR  DISCARDABLE     \"cursor58.cur\"\r\nplus                    CURSOR  DISCARDABLE     \"cursor5a.cur\"\r\nquestion_arrow          CURSOR  DISCARDABLE     \"cursor5c.cur\"\r\nright_ptr               CURSOR  DISCARDABLE     \"cursor5e.cur\"\r\nright_side              CURSOR  DISCARDABLE     \"cursor60.cur\"\r\nright_tee               CURSOR  DISCARDABLE     \"cursor62.cur\"\r\nrightbutton             CURSOR  DISCARDABLE     \"cursor64.cur\"\r\nrtl_logo                CURSOR  DISCARDABLE     \"cursor66.cur\"\r\nsailboat                CURSOR  DISCARDABLE     \"cursor68.cur\"\r\nsb_down_arrow           CURSOR  DISCARDABLE     \"cursor6a.cur\"\r\nsb_h_double_arrow       CURSOR  DISCARDABLE     \"cursor6c.cur\"\r\nsb_left_arrow           CURSOR  DISCARDABLE     \"cursor6e.cur\"\r\nsb_right_arrow          CURSOR  DISCARDABLE     \"cursor70.cur\"\r\nsb_up_arrow             CURSOR  DISCARDABLE     \"cursor72.cur\"\r\nsb_v_double_arrow       CURSOR  DISCARDABLE     \"cursor74.cur\"\r\nshuttle                 CURSOR  DISCARDABLE     \"cursor76.cur\"\r\nsizing                  CURSOR  DISCARDABLE     \"cursor78.cur\"\r\nspider                  CURSOR  DISCARDABLE     \"cursor7a.cur\"\r\nspraycan                CURSOR  DISCARDABLE     \"cursor7c.cur\"\r\nstar                    CURSOR  DISCARDABLE     \"cursor7e.cur\"\r\ntarget                  CURSOR  DISCARDABLE     \"cursor80.cur\"\r\ntcross                  CURSOR  DISCARDABLE     \"cursor82.cur\"\r\ntop_left_arrow          CURSOR  DISCARDABLE     \"cursor84.cur\"\r\ntop_left_corner         CURSOR  DISCARDABLE     \"cursor86.cur\"\r\ntop_right_corner        CURSOR  DISCARDABLE     \"cursor88.cur\"\r\ntop_side                CURSOR  DISCARDABLE     \"cursor8a.cur\"\r\ntop_tee                 CURSOR  DISCARDABLE     \"cursor8c.cur\"\r\ntrek                    CURSOR  DISCARDABLE     \"cursor8e.cur\"\r\nul_angle                CURSOR  DISCARDABLE     \"cursor90.cur\"\r\numbrella                CURSOR  DISCARDABLE     \"cursor92.cur\"\r\nur_angle                CURSOR  DISCARDABLE     \"cursor94.cur\"\r\nwatch                   CURSOR  DISCARDABLE     \"cursor96.cur\"\r\nxterm                   CURSOR  DISCARDABLE     \"cursor98.cur\"\r\nnone                    CURSOR  DISCARDABLE     \"cursor9a.cur\"\r\n\r\n"
  },
  {
    "path": "win/rc/tktest.rc",
    "content": "//\r\n// Version Resource Script\r\n//\r\n\r\n#include <windows.h>\r\n#include <tk.h>\r\n\r\n//\r\n// build-up the name suffix that defines the type of build this is.\r\n//\r\n#if STATIC_BUILD\r\n#define SUFFIX_STATIC\t    \"s\"\r\n#else\r\n#define SUFFIX_STATIC\t    \"\"\r\n#endif\r\n\r\n#if DEBUG && !UNCHECKED\r\n#define SUFFIX_DEBUG\t    \"g\"\r\n#else\r\n#define SUFFIX_DEBUG\t    \"\"\r\n#endif\r\n\r\n#define SUFFIX\t\t    SUFFIX_STATIC SUFFIX_DEBUG\r\n\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\n FILEVERSION    TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n FILEFLAGSMASK\t0x3fL\r\n#ifdef DEBUG\r\n FILEFLAGS\tVS_FF_DEBUG\r\n#else\r\n FILEFLAGS\t0x0L\r\n#endif\r\n FILEOS\t\tVOS__WINDOWS32\r\n FILETYPE\tVFT_APP\r\n FILESUBTYPE\t0x0L\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n\tBLOCK \"040904b0\"\r\n\tBEGIN\r\n\t    VALUE \"FileDescription\", \"Tktest Application\\0\"\r\n\t    VALUE \"OriginalFilename\", \"tktest\" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX \".exe\\0\"\r\n\t    VALUE \"FileVersion\", TK_PATCH_LEVEL\r\n\t    VALUE \"LegalCopyright\", \"Copyright \\251 1987-2022 Regents of the University of California and other parties\\0\"\r\n\t    VALUE \"ProductName\", \"Tk \" TK_VERSION \" for Windows\\0\"\r\n\t    VALUE \"ProductVersion\", TK_PATCH_LEVEL\r\n\tEND\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n\tVALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n//\r\n// Icon\r\n//\r\n//   The icon whose name or resource ID is lexigraphically first, is used\r\n//   as the application's icon.\r\n//\r\n\r\napp                      ICON    DISCARDABLE     \"wish.ico\"\r\n\r\n#if STATIC_BUILD\r\n#include \"tk_base.rc\"\r\n#endif\r\n\r\n//\r\n// This enables themed scrollbars in XP by trying to use comctl32 v6.\r\n//\r\n\r\n#ifndef RT_MANIFEST\r\n#define RT_MANIFEST     24\r\n#endif\r\n#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID\r\n#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1\r\n#endif\r\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST \"wish.exe.manifest\"\r\n"
  },
  {
    "path": "win/rc/wish.rc",
    "content": "//\r\n// Version Resource Script\r\n//\r\n\r\n#include <windows.h>\r\n#include <tk.h>\r\n\r\n//\r\n// build-up the name suffix that defines the type of build this is.\r\n//\r\n#if STATIC_BUILD\r\n#define SUFFIX_STATIC\t    \"s\"\r\n#else\r\n#define SUFFIX_STATIC\t    \"\"\r\n#endif\r\n\r\n#if DEBUG && !UNCHECKED\r\n#define SUFFIX_DEBUG\t    \"g\"\r\n#else\r\n#define SUFFIX_DEBUG\t    \"\"\r\n#endif\r\n\r\n#define SUFFIX\t\t    SUFFIX_STATIC SUFFIX_DEBUG\r\n\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\n FILEVERSION    TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL\r\n FILEFLAGSMASK\t0x3fL\r\n#ifdef DEBUG\r\n FILEFLAGS\tVS_FF_DEBUG\r\n#else\r\n FILEFLAGS\t0x0L\r\n#endif\r\n FILEOS\t\tVOS__WINDOWS32\r\n FILETYPE\tVFT_APP\r\n FILESUBTYPE\t0x0L\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n\tBLOCK \"040904b0\"\r\n\tBEGIN\r\n\t    VALUE \"FileDescription\", \"Wish Application\\0\"\r\n\t    VALUE \"OriginalFilename\", \"wish\" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX \".exe\\0\"\r\n\t    VALUE \"FileVersion\", TK_PATCH_LEVEL\r\n\t    VALUE \"LegalCopyright\", \"Copyright \\251 1987-2022 Regents of the University of California and other parties\\0\"\r\n\t    VALUE \"ProductName\", \"Tk \" TK_VERSION \" for Windows\\0\"\r\n\t    VALUE \"ProductVersion\", TK_PATCH_LEVEL\r\n\tEND\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n\tVALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n//\r\n// Icon\r\n//\r\n//   The icon whose name or resource ID is lexigraphically first, is used\r\n//   as the application's icon.\r\n//\r\n\r\napp                      ICON    DISCARDABLE     \"wish.ico\"\r\n\r\n#if STATIC_BUILD\r\n#include \"tk_base.rc\"\r\n#endif\r\n\r\n//\r\n// This enables themed scrollbars in XP by trying to use comctl32 v6.\r\n//\r\n\r\n#ifndef RT_MANIFEST\r\n#define RT_MANIFEST     24\r\n#endif\r\n#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID\r\n#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1\r\n#endif\r\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST \"wish.exe.manifest\"\r\n"
  },
  {
    "path": "win/rules-ext.vc",
    "content": "# This file should only be included in makefiles for Tcl extensions,\r\n# NOT in the makefile for Tcl itself.\r\n\r\n!ifndef _RULES_EXT_VC\r\n\r\n# We need to run from the directory the parent makefile is located in.\r\n# nmake does not tell us what makefile was used to invoke it so parent\r\n# makefile has to set the MAKEFILEVC macro or we just make a guess and\r\n# warn if we think that is not the case.\r\n!if \"$(MAKEFILEVC)\" == \"\"\r\n\r\n!if exist(\"$(PROJECT).vc\")\r\nMAKEFILEVC = $(PROJECT).vc\r\n!elseif exist(\"makefile.vc\")\r\nMAKEFILEVC = makefile.vc\r\n!endif\r\n!endif # \"$(MAKEFILEVC)\" == \"\"\r\n\r\n!if !exist(\"$(MAKEFILEVC)\")\r\nMSG = ^\r\nYou must run nmake from the directory containing the project makefile.^\r\nIf you are doing that and getting this message, set the MAKEFILEVC^\r\nmacro to the name of the project makefile.\r\n!message WARNING: $(MSG)\r\n!endif\r\n\r\n!if \"$(PROJECT)\" == \"tcl\"\r\n!error The rules-ext.vc file is not intended for Tcl itself.\r\n!endif\r\n\r\n# We extract version numbers using the nmakehlp program. For now use\r\n# the local copy of nmakehlp. Once we locate Tcl, we will use that\r\n# one if it is newer.\r\n!if \"$(MACHINE)\" == \"IX86\" || \"$(MACHINE)\" == \"$(NATIVE_ARCH)\"\r\n!if [$(CC) -nologo -DNDEBUG \"nmakehlp.c\" -link -subsystem:console > nul]\r\n!endif\r\n!else\r\n!if [copy x86_64-w64-mingw32-nmakehlp.exe nmakehlp.exe >NUL]\r\n!endif\r\n!endif\r\n\r\n# First locate the Tcl directory that we are working with.\r\n!if \"$(TCLDIR)\" != \"\"\r\n\r\n_RULESDIR = $(TCLDIR:/=\\)\r\n\r\n!else\r\n\r\n# If an installation path is specified, that is also the Tcl directory.\r\n# Also Tk never builds against an installed Tcl, it needs Tcl sources\r\n!if defined(INSTALLDIR) && \"$(PROJECT)\" != \"tk\"\r\n_RULESDIR=$(INSTALLDIR:/=\\)\r\n!else\r\n# Locate Tcl sources\r\n!if [echo _RULESDIR = \\> nmakehlp.out] \\\r\n   || [nmakehlp -L generic\\tcl.h >> nmakehlp.out]\r\n_RULESDIR = ..\\..\\tcl\r\n!else\r\n!include nmakehlp.out\r\n!endif\r\n\r\n!endif # defined(INSTALLDIR)....\r\n\r\n!endif # ifndef TCLDIR\r\n\r\n# Now look for the targets.vc file under the Tcl root. Note we check this\r\n# file and not rules.vc because the latter also exists on older systems.\r\n!if exist(\"$(_RULESDIR)\\lib\\nmake\\targets.vc\") # Building against installed Tcl\r\n_RULESDIR = $(_RULESDIR)\\lib\\nmake\r\n!elseif exist(\"$(_RULESDIR)\\win\\targets.vc\")   # Building against Tcl sources\r\n_RULESDIR = $(_RULESDIR)\\win\r\n!else\r\n# If we have not located Tcl's targets file, most likely we are compiling\r\n# against an older version of Tcl and so must use our own support files.\r\n_RULESDIR = .\r\n!endif\r\n\r\n!if \"$(_RULESDIR)\" != \".\"\r\n# Potentially using Tcl's support files. If this extension has its own\r\n# nmake support files, need to compare the versions and pick newer.\r\n\r\n!if exist(\"rules.vc\") # The extension has its own copy\r\n\r\n!if [echo TCL_RULES_MAJOR = \\> versions.vc] \\\r\n   && [nmakehlp -V \"$(_RULESDIR)\\rules.vc\" RULES_VERSION_MAJOR >> versions.vc]\r\n!endif\r\n!if [echo TCL_RULES_MINOR = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_RULESDIR)\\rules.vc\" RULES_VERSION_MINOR >> versions.vc]\r\n!endif\r\n\r\n!if [echo OUR_RULES_MAJOR = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"rules.vc\" RULES_VERSION_MAJOR >> versions.vc]\r\n!endif\r\n!if [echo OUR_RULES_MINOR = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"rules.vc\" RULES_VERSION_MINOR >> versions.vc]\r\n!endif\r\n!include versions.vc\r\n# We have a newer version of the support files, use them\r\n!if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR))\r\n_RULESDIR = .\r\n!endif\r\n\r\n!endif # if exist(\"rules.vc\")\r\n\r\n!endif # if $(_RULESDIR) != \".\"\r\n\r\n# Let rules.vc know what copy of nmakehlp.c to use.\r\nNMAKEHLPC = $(_RULESDIR)\\nmakehlp.c\r\n\r\n# Get rid of our internal defines before calling rules.vc\r\n!undef TCL_RULES_MAJOR\r\n!undef TCL_RULES_MINOR\r\n!undef OUR_RULES_MAJOR\r\n!undef OUR_RULES_MINOR\r\n\r\n!if exist(\"$(_RULESDIR)\\rules.vc\")\r\n!message *** Using $(_RULESDIR)\\rules.vc\r\n!include \"$(_RULESDIR)\\rules.vc\"\r\n!else\r\n!error *** Could not locate rules.vc in $(_RULESDIR)\r\n!endif\r\n\r\n!endif # _RULES_EXT_VC"
  },
  {
    "path": "win/rules.vc",
    "content": "#------------------------------------------------------------- -*- makefile -*-\r\n# rules.vc --\r\n#\r\n# Part of the nmake based build system for Tcl and its extensions.\r\n# This file does all the hard work in terms of parsing build options,\r\n# compiler switches, defining common targets and macros. The Tcl makefile\r\n# directly includes this. Extensions include it via \"rules-ext.vc\".\r\n#\r\n# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for\r\n# detailed documentation.\r\n#\r\n# See the file \"license.terms\" for information on usage and redistribution\r\n# of this file, and for a DISCLAIMER OF ALL WARRANTIES.\r\n#\r\n# Copyright (c) 2001-2003 David Gravereaux.\r\n# Copyright (c) 2003-2008 Patrick Thoyts\r\n# Copyright (c) 2017      Ashok P. Nadkarni\r\n#------------------------------------------------------------------------------\r\n\r\n!ifndef _RULES_VC\r\n_RULES_VC = 1\r\n\r\n# The following macros define the version of the rules.vc nmake build system\r\n# For modifications that are not backward-compatible, you *must* change\r\n# the major version.\r\nRULES_VERSION_MAJOR = 1\r\nRULES_VERSION_MINOR = 16\r\n\r\n# The PROJECT macro must be defined by parent makefile.\r\n!if \"$(PROJECT)\" == \"\"\r\n!error *** Error: Macro PROJECT not defined! Please define it before including rules.vc\r\n!endif\r\n\r\n!if \"$(PRJ_PACKAGE_TCLNAME)\" == \"\"\r\nPRJ_PACKAGE_TCLNAME = $(PROJECT)\r\n!endif\r\n\r\n# Also special case Tcl and Tk to save some typing later\r\nDOING_TCL = 0\r\nDOING_TK  = 0\r\n!if \"$(PROJECT)\" == \"tcl\"\r\nDOING_TCL = 1\r\n!elseif \"$(PROJECT)\" == \"tk\"\r\nDOING_TK = 1\r\n!endif\r\n\r\n!ifndef NEED_TK\r\n# Backwards compatibility\r\n!ifdef PROJECT_REQUIRES_TK\r\nNEED_TK = $(PROJECT_REQUIRES_TK)\r\n!else\r\nNEED_TK = 0\r\n!endif\r\n!endif\r\n\r\n!ifndef NEED_TCL_SOURCE\r\nNEED_TCL_SOURCE = 0\r\n!endif\r\n\r\n!ifdef NEED_TK_SOURCE\r\n!if $(NEED_TK_SOURCE)\r\nNEED_TK = 1\r\n!endif\r\n!else\r\nNEED_TK_SOURCE = 0\r\n!endif\r\n\r\n################################################################\r\n# Nmake is a pretty weak environment in syntax and capabilities\r\n# so this file is necessarily verbose. It's broken down into\r\n# the following parts.\r\n#\r\n# 0. Sanity check that compiler environment is set up and initialize\r\n#    any built-in settings from the parent makefile\r\n# 1. First define the external tools used for compiling, copying etc.\r\n#    as this is independent of everything else.\r\n# 2. Figure out our build structure in terms of the directory, whether\r\n#    we are building Tcl or an extension, etc.\r\n# 3. Determine the compiler and linker versions\r\n# 4. Build the nmakehlp helper application\r\n# 5. Determine the supported compiler options and features\r\n# 6. Extract Tcl, Tk, and possibly extensions, version numbers from the\r\n#    headers\r\n# 7. Parse the OPTS macro value for user-specified build configuration\r\n# 8. Parse the STATS macro value for statistics instrumentation\r\n# 9. Parse the CHECKS macro for additional compilation checks\r\n# 10. Based on this selected configuration, construct the output\r\n#     directory and file paths\r\n# 11. Construct the paths where the package is to be installed\r\n# 12. Set up the actual options passed to compiler and linker based\r\n#     on the information gathered above.\r\n# 13. Define some standard build targets and implicit rules. These may\r\n#     be optionally disabled by the parent makefile.\r\n# 14. (For extensions only.) Compare the configuration of the target\r\n#     Tcl and the extensions and warn against discrepancies.\r\n#\r\n# One final note about the macro names used. They are as they are\r\n# for historical reasons. We would like legacy extensions to\r\n# continue to work with this make include file so be wary of\r\n# changing them for consistency or clarity.\r\n\r\n# 0. Sanity check compiler environment\r\n\r\n# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or\r\n# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir)\r\n\r\n!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR)\r\nMSG = ^\r\nVisual C++ compiler environment not initialized.\r\n!error $(MSG)\r\n!endif\r\n\r\n# We need to run from the directory the parent makefile is located in.\r\n# nmake does not tell us what makefile was used to invoke it so parent\r\n# makefile has to set the MAKEFILEVC macro or we just make a guess and\r\n# warn if we think that is not the case.\r\n!if \"$(MAKEFILEVC)\" == \"\"\r\n\r\n!if exist(\"$(PROJECT).vc\")\r\nMAKEFILEVC = $(PROJECT).vc\r\n!elseif exist(\"makefile.vc\")\r\nMAKEFILEVC = makefile.vc\r\n!endif\r\n!endif # \"$(MAKEFILEVC)\" == \"\"\r\n\r\n!if !exist(\"$(MAKEFILEVC)\")\r\nMSG = ^\r\nYou must run nmake from the directory containing the project makefile.^\r\nIf you are doing that and getting this message, set the MAKEFILEVC^\r\nmacro to the name of the project makefile.\r\n!message WARNING: $(MSG)\r\n!endif\r\n\r\n\r\n################################################################\r\n# 1. Define external programs being used\r\n\r\n#----------------------------------------------------------\r\n# Set the proper copy method to avoid overwrite questions\r\n# to the user when copying files and selecting the right\r\n# \"delete all\" method.\r\n#----------------------------------------------------------\r\n# Tcl Bug be40b736: use rd/md instead rmdir/mkdir.\r\n# Otherwise, an eventual cygwin version with different\r\n# parameters may be used.\r\n#----------------------------------------------------------\r\n\r\nRMDIR\t= rd /S /Q\r\nCPY\t= xcopy /i /y >NUL\r\nCPYDIR  = xcopy /e /i /y >NUL\r\nCOPY\t= copy /y >NUL\r\nMKDIR   = md\r\n\r\n######################################################################\r\n# 2. Figure out our build environment in terms of what we're building.\r\n#\r\n# (a) Tcl itself\r\n# (b) Tk\r\n# (c) a Tcl extension using libraries/includes from an *installed* Tcl\r\n# (d) a Tcl extension using libraries/includes from Tcl source directory\r\n#\r\n# This last is needed because some extensions still need\r\n# some Tcl interfaces that are not publicly exposed.\r\n#\r\n# The fragment will set the following macros:\r\n# ROOT - root of this module sources\r\n# COMPATDIR - source directory that holds compatibility sources\r\n# DOCDIR - source directory containing documentation files\r\n# GENERICDIR - platform-independent source directory\r\n# WIN_DIR - Windows-specific source directory\r\n# TESTDIR - directory containing test files\r\n# TOOLSDIR - directory containing build tools\r\n# _TCLDIR - root of the Tcl installation OR the Tcl sources. Not set\r\n#    when building Tcl itself.\r\n# _INSTALLDIR - native form of the installation path. For Tcl\r\n#    this will be the root of the Tcl installation. For extensions\r\n#    this will be the lib directory under the root.\r\n# TCLINSTALL  - set to 1 if _TCLDIR refers to\r\n#    headers and libraries from an installed Tcl, and 0 if built against\r\n#    Tcl sources. Not set when building Tcl itself. Yes, not very well\r\n#    named.\r\n# _TCL_H - native path to the tcl.h file\r\n#\r\n# If Tk is involved, also sets the following\r\n# _TKDIR - native form Tk installation OR Tk source. Not set if building\r\n#    Tk itself.\r\n# TKINSTALL - set 1 if _TKDIR refers to installed Tk and 0 if Tk sources\r\n# _TK_H - native path to the tk.h file\r\n\r\n# Root directory for sources and assumed subdirectories\r\nROOT = $(MAKEDIR)\\..\r\n# The following paths CANNOT have spaces in them as they appear on the\r\n# left side of implicit rules.\r\n!ifndef COMPATDIR\r\nCOMPATDIR\t= $(ROOT)\\compat\r\n!endif\r\n!ifndef DOCDIR\r\nDOCDIR\t\t= $(ROOT)\\doc\r\n!endif\r\n!ifndef GENERICDIR\r\nGENERICDIR\t= $(ROOT)\\generic\r\n!endif\r\n!ifndef TOOLSDIR\r\nTOOLSDIR\t= $(ROOT)\\tools\r\n!endif\r\n!ifndef TESTDIR\r\nTESTDIR\t= $(ROOT)\\tests\r\n!endif\r\n!ifndef LIBDIR\r\n!if exist(\"$(ROOT)\\library\")\r\nLIBDIR          = $(ROOT)\\library\r\n!else\r\nLIBDIR          = $(ROOT)\\lib\r\n!endif\r\n!endif\r\n!ifndef DEMODIR\r\n!if exist(\"$(LIBDIR)\\demos\")\r\nDEMODIR\t\t= $(LIBDIR)\\demos\r\n!else\r\nDEMODIR\t\t= $(ROOT)\\demos\r\n!endif\r\n!endif # ifndef DEMODIR\r\n# Do NOT use WINDIR because it is Windows internal environment\r\n# variable to point to c:\\windows!\r\nWIN_DIR\t\t= $(ROOT)\\win\r\n\r\n!ifndef RCDIR\r\n!if exist(\"$(WIN_DIR)\\rc\")\r\nRCDIR           = $(WIN_DIR)\\rc\r\n!else\r\nRCDIR           = $(WIN_DIR)\r\n!endif\r\n!endif\r\nRCDIR = $(RCDIR:/=\\)\r\n\r\n# The target directory where the built packages and binaries will be installed.\r\n# INSTALLDIR is the (optional) path specified by the user.\r\n# _INSTALLDIR is INSTALLDIR using the backslash separator syntax\r\n!ifdef INSTALLDIR\r\n### Fix the path separators.\r\n_INSTALLDIR\t= $(INSTALLDIR:/=\\)\r\n!else\r\n### Assume the normal default.\r\n_INSTALLDIR\t= $(HOMEDRIVE)\\Tcl\r\n!endif\r\n\r\n!if $(DOING_TCL)\r\n\r\n# BEGIN Case 2(a) - Building Tcl itself\r\n\r\n# Only need to define _TCL_H\r\n_TCL_H = ..\\generic\\tcl.h\r\n\r\n# END Case 2(a) - Building Tcl itself\r\n\r\n!elseif $(DOING_TK)\r\n\r\n# BEGIN Case 2(b) - Building Tk\r\n\r\nTCLINSTALL = 0 # Tk always builds against Tcl source, not an installed Tcl\r\n!if \"$(TCLDIR)\" == \"\"\r\n!if [echo TCLDIR = \\> nmakehlp.out] \\\r\n   || [nmakehlp -L generic\\tcl.h >> nmakehlp.out]\r\n!error *** Could not locate Tcl source directory.\r\n!endif\r\n!include nmakehlp.out\r\n!endif # TCLDIR == \"\"\r\n\r\n_TCLDIR\t= $(TCLDIR:/=\\)\r\n_TCL_H  = $(_TCLDIR)\\generic\\tcl.h\r\n!if !exist(\"$(_TCL_H)\")\r\n!error Could not locate tcl.h. Please set the TCLDIR macro to point to the Tcl *source* directory.\r\n!endif\r\n\r\n_TK_H = ..\\generic\\tk.h\r\n\r\n# END Case 2(b) - Building Tk\r\n\r\n!else\r\n\r\n# BEGIN Case 2(c) or (d) - Building an extension other than Tk\r\n\r\n# If command line has specified Tcl location through TCLDIR, use it\r\n# else default to the INSTALLDIR setting\r\n!if \"$(TCLDIR)\" != \"\"\r\n\r\n_TCLDIR\t= $(TCLDIR:/=\\)\r\n!if exist(\"$(_TCLDIR)\\include\\tcl.h\") # Case 2(c) with TCLDIR defined\r\nTCLINSTALL\t= 1\r\n_TCL_H          = $(_TCLDIR)\\include\\tcl.h\r\n!elseif exist(\"$(_TCLDIR)\\generic\\tcl.h\") # Case 2(d) with TCLDIR defined\r\nTCLINSTALL\t= 0\r\n_TCL_H          = $(_TCLDIR)\\generic\\tcl.h\r\n!endif\r\n\r\n!else  #  # Case 2(c) for extensions with TCLDIR undefined\r\n\r\n# Need to locate Tcl depending on whether it needs Tcl source or not.\r\n# If we don't, check the INSTALLDIR for an installed Tcl first\r\n\r\n!if exist(\"$(_INSTALLDIR)\\include\\tcl.h\") && !$(NEED_TCL_SOURCE)\r\n\r\nTCLINSTALL\t= 1\r\nTCLDIR          = $(_INSTALLDIR)\\..\r\n# NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions\r\n# later so the \\.. accounts for the /lib\r\n_TCLDIR\t\t= $(_INSTALLDIR)\\..\r\n_TCL_H          = $(_TCLDIR)\\include\\tcl.h\r\n\r\n!else # exist(...) && !$(NEED_TCL_SOURCE)\r\n\r\n!if [echo _TCLDIR = \\> nmakehlp.out] \\\r\n   || [nmakehlp -L generic\\tcl.h >> nmakehlp.out]\r\n!error *** Could not locate Tcl source directory.\r\n!endif\r\n!include nmakehlp.out\r\nTCLINSTALL      = 0\r\nTCLDIR         = $(_TCLDIR)\r\n_TCL_H          = $(_TCLDIR)\\generic\\tcl.h\r\n\r\n!endif # exist(...) && !$(NEED_TCL_SOURCE)\r\n\r\n!endif # TCLDIR\r\n\r\n!ifndef _TCL_H\r\nMSG =^\r\nFailed to find tcl.h. The TCLDIR macro is set incorrectly or is not set and default path does not contain tcl.h.\r\n!error $(MSG)\r\n!endif\r\n\r\n# Now do the same to locate Tk headers and libs if project requires Tk\r\n!if $(NEED_TK)\r\n\r\n!if \"$(TKDIR)\" != \"\"\r\n\r\n_TKDIR = $(TKDIR:/=\\)\r\n!if exist(\"$(_TKDIR)\\include\\tk.h\")\r\nTKINSTALL      = 1\r\n_TK_H          = $(_TKDIR)\\include\\tk.h\r\n!elseif exist(\"$(_TKDIR)\\generic\\tk.h\")\r\nTKINSTALL      = 0\r\n_TK_H          = $(_TKDIR)\\generic\\tk.h\r\n!endif\r\n\r\n!else # TKDIR not defined\r\n\r\n# Need to locate Tcl depending on whether it needs Tcl source or not.\r\n# If we don't, check the INSTALLDIR for an installed Tcl first\r\n\r\n!if exist(\"$(_INSTALLDIR)\\include\\tk.h\") && !$(NEED_TK_SOURCE)\r\n\r\nTKINSTALL      = 1\r\n# NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions\r\n# later so the \\.. accounts for the /lib\r\n_TKDIR         = $(_INSTALLDIR)\\..\r\n_TK_H          = $(_TKDIR)\\include\\tk.h\r\nTKDIR          = $(_TKDIR)\r\n\r\n!else # exist(\"$(_INSTALLDIR)\\include\\tk.h\") && !$(NEED_TK_SOURCE)\r\n\r\n!if [echo _TKDIR = \\> nmakehlp.out] \\\r\n   || [nmakehlp -L generic\\tk.h >> nmakehlp.out]\r\n!error *** Could not locate Tk source directory.\r\n!endif\r\n!include nmakehlp.out\r\nTKINSTALL      = 0\r\nTKDIR          = $(_TKDIR)\r\n_TK_H          = $(_TKDIR)\\generic\\tk.h\r\n\r\n!endif # exist(\"$(_INSTALLDIR)\\include\\tk.h\") && !$(NEED_TK_SOURCE)\r\n\r\n!endif # TKDIR\r\n\r\n!ifndef _TK_H\r\nMSG =^\r\nFailed to find tk.h. The TKDIR macro is set incorrectly or is not set and default path does not contain tk.h.\r\n!error $(MSG)\r\n!endif\r\n\r\n!endif # NEED_TK\r\n\r\n!if $(NEED_TCL_SOURCE) && $(TCLINSTALL)\r\nMSG = ^\r\n*** Warning: This extension requires the source distribution of Tcl.^\r\n*** Please set the TCLDIR macro to point to the Tcl sources.\r\n!error $(MSG)\r\n!endif\r\n\r\n!if $(NEED_TK_SOURCE)\r\n!if $(TKINSTALL)\r\nMSG = ^\r\n*** Warning: This extension requires the source distribution of Tk.^\r\n*** Please set the TKDIR macro to point to the Tk sources.\r\n!error $(MSG)\r\n!endif\r\n!endif\r\n\r\n\r\n# If INSTALLDIR set to Tcl installation root dir then reset to the\r\n# lib dir for installing extensions\r\n!if exist(\"$(_INSTALLDIR)\\include\\tcl.h\")\r\n_INSTALLDIR=$(_INSTALLDIR)\\lib\r\n!endif\r\n\r\n# END Case 2(c) or (d) - Building an extension\r\n!endif # if $(DOING_TCL)\r\n\r\n################################################################\r\n# 3. Determine compiler version and architecture\r\n# In this section, we figure out the compiler version and the\r\n# architecture for which we are building. This sets the\r\n# following macros:\r\n# VCVERSION - the internal compiler version as 1200, 1400, 1910 etc.\r\n#     This is also printed by the compiler in dotted form 19.10 etc.\r\n# VCVER - the \"marketing version\", for example Visual C++ 6 for internal\r\n#     compiler version 1200. This is kept only for legacy reasons as it\r\n#     does not make sense for recent Microsoft compilers. Only used for\r\n#     output directory names.\r\n# ARCH - set to IX86, ARM64 or AMD64 depending on 32- or 64-bit target\r\n# NATIVE_ARCH - set to IX86, ARM64 or AMD64 for the host machine\r\n# MACHINE - same as $(ARCH) - legacy\r\n# _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed\r\n\r\ncc32\t\t= $(CC)   # built-in default.\r\nlink32\t\t= link\r\nlib32\t\t= lib\r\nrc32\t\t= $(RC)   # built-in default.\r\n\r\n#----------------------------------------------------------------\r\n# Figure out the compiler architecture and version by writing\r\n# the C macros to a file, preprocessing them with the C\r\n# preprocessor and reading back the created file\r\n\r\n_HASH=^#\r\n_VC_MANIFEST_EMBED_EXE=\r\n_VC_MANIFEST_EMBED_DLL=\r\nVCVER=0\r\n!if ![echo VCVERSION=_MSC_VER > vercl.x] \\\r\n    && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \\\r\n    && ![echo ARCH=IX86 >> vercl.x] \\\r\n    && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \\\r\n    && ![echo ARCH=AMD64 >> vercl.x] \\\r\n    && ![echo $(_HASH)elif defined(_M_ARM64) >> vercl.x] \\\r\n    && ![echo ARCH=ARM64 >> vercl.x] \\\r\n    && ![echo $(_HASH)endif >> vercl.x] \\\r\n    && ![$(cc32) -nologo -TC -P vercl.x 2>NUL]\r\n!include vercl.i\r\n!if $(VCVERSION) < 1900\r\n!if ![echo VCVER= ^\\> vercl.vc] \\\r\n    && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]\r\n!include vercl.vc\r\n!endif\r\n!else\r\n# The simple calculation above does not apply to new Visual Studio releases\r\n# Keep the compiler version in its native form.\r\nVCVER = $(VCVERSION)\r\n!endif\r\n!endif\r\n\r\n!if ![del 2>NUL /q/f vercl.x vercl.i vercl.vc]\r\n!endif\r\n\r\n#----------------------------------------------------------------\r\n# The MACHINE macro is used by legacy makefiles so set it as well\r\n!ifdef MACHINE\r\n!if \"$(MACHINE)\" == \"x86\"\r\n!undef MACHINE\r\nMACHINE = IX86\r\n!elseif \"$(MACHINE)\" == \"arm64\"\r\n!undef MACHINE\r\nMACHINE = ARM64\r\n!elseif \"$(MACHINE)\" == \"x64\"\r\n!undef MACHINE\r\nMACHINE = AMD64\r\n!endif\r\n!if \"$(MACHINE)\" != \"$(ARCH)\"\r\n!error Specified MACHINE macro $(MACHINE) does not match detected target architecture $(ARCH).\r\n!endif\r\n!else\r\nMACHINE=$(ARCH)\r\n!endif\r\n\r\n#---------------------------------------------------------------\r\n# The PLATFORM_IDENTIFY macro matches the values returned by\r\n# the Tcl platform::identify command\r\n!if \"$(MACHINE)\" == \"AMD64\"\r\nPLATFORM_IDENTIFY = win32-x86_64\r\n!elseif \"$(MACHINE)\" == \"ARM64\"\r\nPLATFORM_IDENTIFY = win32-arm\r\n!else\r\nPLATFORM_IDENTIFY = win32-ix86\r\n!endif\r\n\r\n# The MULTIPLATFORM macro controls whether binary extensions are installed\r\n# in platform-specific directories. Intended to be set/used by extensions.\r\n!ifndef MULTIPLATFORM_INSTALL\r\nMULTIPLATFORM_INSTALL = 0\r\n!endif\r\n\r\n#------------------------------------------------------------\r\n# Figure out the *host* architecture by reading the registry\r\n\r\n!if ![reg query HKLM\\Hardware\\Description\\System\\CentralProcessor\\0 /v Identifier | findstr /i x86]\r\nNATIVE_ARCH=IX86\r\n!elseif ![reg query HKLM\\Hardware\\Description\\System\\CentralProcessor\\0 /v Identifier | findstr /i ARM | findstr /i 64-bit]\r\nNATIVE_ARCH=ARM64\r\n!else\r\nNATIVE_ARCH=AMD64\r\n!endif\r\n\r\n# Since MSVC8 we must deal with manifest resources.\r\n!if $(VCVERSION) >= 1400\r\n_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1\r\n_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2\r\n!endif\r\n\r\n################################################################\r\n# 4. Build the nmakehlp program\r\n# This is a helper app we need to overcome nmake's limiting\r\n# environment. We will call out to it to get various bits of\r\n# information about supported compiler options etc.\r\n#\r\n# Tcl itself will always use the nmakehlp.c program which is\r\n# in its own source. It will be kept updated there.\r\n#\r\n# Extensions built against an installed Tcl will use the installed\r\n# copy of Tcl's nmakehlp.c if there is one and their own version\r\n# otherwise. In the latter case, they would also be using their own\r\n# rules.vc. Note that older versions of Tcl do not install nmakehlp.c\r\n# or rules.vc.\r\n#\r\n# Extensions built against Tcl sources will use the one from the Tcl source.\r\n#\r\n# When building an extension using a sufficiently new version of Tcl,\r\n# rules-ext.vc will define NMAKEHLPC appropriately to point to the\r\n# copy of nmakehlp.c to be used.\r\n\r\n!ifndef NMAKEHLPC\r\n# Default to the one in the current directory (the extension's own nmakehlp.c)\r\nNMAKEHLPC = nmakehlp.c\r\n\r\n!if !$(DOING_TCL)\r\n!if $(TCLINSTALL)\r\n!if exist(\"$(_TCLDIR)\\lib\\nmake\\nmakehlp.c\")\r\nNMAKEHLPC = $(_TCLDIR)\\lib\\nmake\\nmakehlp.c\r\n!endif\r\n!else # !$(TCLINSTALL)\r\n!if exist(\"$(_TCLDIR)\\win\\nmakehlp.c\")\r\nNMAKEHLPC = $(_TCLDIR)\\win\\nmakehlp.c\r\n!endif\r\n!endif # $(TCLINSTALL)\r\n!endif # !$(DOING_TCL)\r\n\r\n!endif # NMAKEHLPC\r\n\r\n# We always build nmakehlp even if it exists since we do not know\r\n# what source it was built from.\r\n!if \"$(MACHINE)\" == \"IX86\" || \"$(MACHINE)\" == \"$(NATIVE_ARCH)\"\r\n!if [$(cc32) -nologo \"$(NMAKEHLPC)\" -link -subsystem:console > nul]\r\n!endif\r\n!else\r\n!if [copy $(NMAKEHLPC:nmakehlp.c=x86_64-w64-mingw32-nmakehlp.exe) nmakehlp.exe >NUL]\r\n!endif\r\n!endif\r\n\r\n################################################################\r\n# 5. Test for compiler features\r\n# Visual C++ compiler options have changed over the years. Check\r\n# which options are supported by the compiler in use.\r\n#\r\n# The following macros are set:\r\n# OPTIMIZATIONS - the compiler flags to be used for optimized builds\r\n# DEBUGFLAGS - the compiler flags to be used for debug builds\r\n# LINKERFLAGS - Flags passed to the linker\r\n#\r\n# Note that these are the compiler settings *available*, not those\r\n# that will be *used*. The latter depends on the OPTS macro settings\r\n# which we have not yet parsed.\r\n#\r\n# Also note that some of the flags in OPTIMIZATIONS are not really\r\n# related to optimization. They are placed there only for legacy reasons\r\n# as some extensions expect them to be included in that macro.\r\n\r\n# -Op improves float consistency. Note only needed for older compilers\r\n# Newer compilers do not need or support this option.\r\n!if [nmakehlp -c -Op]\r\nFPOPTS  = -Op\r\n!endif\r\n\r\n# Strict floating point semantics - present in newer compilers in lieu of -Op\r\n!if [nmakehlp -c -fp:strict]\r\nFPOPTS  = $(FPOPTS) -fp:strict\r\n!endif\r\n\r\n!if \"$(MACHINE)\" == \"IX86\"\r\n### test for pentium errata\r\n!if [nmakehlp -c -QI0f]\r\n!message *** Compiler has 'Pentium 0x0f fix'\r\nFPOPTS  = $(FPOPTS) -QI0f\r\n!else\r\n!message *** Compiler does not have 'Pentium 0x0f fix'\r\n!endif\r\n!endif\r\n\r\n### test for optimizations\r\n# /O2 optimization includes /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy as per\r\n# documentation. Note we do NOT want /Gs as that inserts a _chkstk\r\n# stack probe at *every* function entry, not just those with more than\r\n# a page of stack allocation resulting in a performance hit.  However,\r\n# /O2 documentation is misleading as its stack probes are simply the\r\n# default page size locals allocation probes and not what is implied\r\n# by an explicit /Gs option.\r\n\r\nOPTIMIZATIONS = $(FPOPTS)\r\n\r\n!if [nmakehlp -c -O2]\r\nOPTIMIZING = 1\r\nOPTIMIZATIONS   = $(OPTIMIZATIONS) -O2\r\n!else\r\n# Legacy, really. All modern compilers support this\r\n!message *** Compiler does not have 'Optimizations'\r\nOPTIMIZING = 0\r\n!endif\r\n\r\n# Checks for buffer overflows in local arrays\r\n!if [nmakehlp -c -GS]\r\nOPTIMIZATIONS  = $(OPTIMIZATIONS) -GS\r\n!endif\r\n\r\n# Link time optimization. Note that this option (potentially) makes\r\n# generated libraries only usable by the specific VC++ version that\r\n# created it. Requires /LTCG linker option\r\n!if [nmakehlp -c -GL]\r\nOPTIMIZATIONS  = $(OPTIMIZATIONS) -GL\r\nCC_GL_OPT_ENABLED = 1\r\n!else\r\n# In newer compilers -GL and -YX are incompatible.\r\n!if [nmakehlp -c -YX]\r\nOPTIMIZATIONS  = $(OPTIMIZATIONS) -YX\r\n!endif\r\n!endif # [nmakehlp -c -GL]\r\n\r\nDEBUGFLAGS     = $(FPOPTS)\r\n\r\n# Run time error checks. Not available or valid in a release, non-debug build\r\n# RTC is for modern compilers, -GZ is legacy\r\n!if [nmakehlp -c -RTC1]\r\nDEBUGFLAGS     = $(DEBUGFLAGS) -RTC1\r\n!elseif [nmakehlp -c -GZ]\r\nDEBUGFLAGS     = $(DEBUGFLAGS) -GZ\r\n!endif\r\n\r\n#----------------------------------------------------------------\r\n# Linker flags\r\n\r\n# LINKER_TESTFLAGS are for internal use when we call nmakehlp to test\r\n# if the linker supports a specific option. Without these flags link will\r\n# return \"LNK1561: entry point must be defined\" error compiling from VS-IDE:\r\n# They are not passed through to the actual application / extension\r\n# link rules.\r\n!ifndef LINKER_TESTFLAGS\r\nLINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmakehlp.out\r\n!endif\r\n\r\nLINKERFLAGS     =\r\n\r\n# If compiler has enabled link time optimization, linker must too with -ltcg\r\n!ifdef CC_GL_OPT_ENABLED\r\n!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]\r\nLINKERFLAGS     = $(LINKERFLAGS) -ltcg\r\n!endif\r\n!endif\r\n\r\n\r\n################################################################\r\n# 6. Extract various version numbers from headers\r\n# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h\r\n# respectively. For extensions, versions are extracted from the\r\n# configure.in or configure.ac from the TEA configuration if it\r\n# exists, and unset otherwise.\r\n# Sets the following macros:\r\n# TCL_MAJOR_VERSION\r\n# TCL_MINOR_VERSION\r\n# TCL_RELEASE_SERIAL\r\n# TCL_PATCH_LEVEL\r\n# TCL_PATCH_LETTER\r\n# TCL_VERSION\r\n# TK_MAJOR_VERSION\r\n# TK_MINOR_VERSION\r\n# TK_RELEASE_SERIAL\r\n# TK_PATCH_LEVEL\r\n# TK_PATCH_LETTER\r\n# TK_VERSION\r\n# DOTVERSION - set as (for example) 2.5\r\n# VERSION - set as (for example 25)\r\n#--------------------------------------------------------------\r\n\r\n!if [echo REM = This file is generated from rules.vc > versions.vc]\r\n!endif\r\n!if [echo TCL_MAJOR_VERSION = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_TCL_H)\" \"define TCL_MAJOR_VERSION\" >> versions.vc]\r\n!endif\r\n!if [echo TCL_MINOR_VERSION = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_TCL_H)\" \"define TCL_MINOR_VERSION\" >> versions.vc]\r\n!endif\r\n!if [echo TCL_RELEASE_SERIAL = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_TCL_H)\" TCL_RELEASE_SERIAL >> versions.vc]\r\n!endif\r\n!if [echo TCL_PATCH_LEVEL = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_TCL_H)\" TCL_PATCH_LEVEL >> versions.vc]\r\n!endif\r\n\r\n!if defined(_TK_H)\r\n!if [echo TK_MAJOR_VERSION = \\>> versions.vc] \\\r\n   && [nmakehlp -V $(_TK_H) \"define TK_MAJOR_VERSION\" >> versions.vc]\r\n!endif\r\n!if [echo TK_MINOR_VERSION = \\>> versions.vc] \\\r\n   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]\r\n!endif\r\n!if [echo TK_RELEASE_SERIAL = \\>> versions.vc] \\\r\n   && [nmakehlp -V \"$(_TK_H)\" TK_RELEASE_SERIAL >> versions.vc]\r\n!endif\r\n!if [echo TK_PATCH_LEVEL = \\>> versions.vc] \\\r\n   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]\r\n!endif\r\n!endif # _TK_H\r\n\r\n!include versions.vc\r\n\r\nTCL_VERSION\t= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)\r\nTCL_DOTVERSION\t= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)\r\n!if [nmakehlp -f $(TCL_PATCH_LEVEL) \"a\"]\r\nTCL_PATCH_LETTER = a\r\n!elseif [nmakehlp -f $(TCL_PATCH_LEVEL) \"b\"]\r\nTCL_PATCH_LETTER = b\r\n!else\r\nTCL_PATCH_LETTER = .\r\n!endif\r\n\r\n!if defined(_TK_H)\r\n\r\nTK_VERSION\t= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)\r\nTK_DOTVERSION\t= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)\r\n!if [nmakehlp -f $(TK_PATCH_LEVEL) \"a\"]\r\nTK_PATCH_LETTER = a\r\n!elseif [nmakehlp -f $(TK_PATCH_LEVEL) \"b\"]\r\nTK_PATCH_LETTER = b\r\n!else\r\nTK_PATCH_LETTER = .\r\n!endif\r\n\r\n!endif\r\n\r\n# Set DOTVERSION and VERSION\r\n!if $(DOING_TCL)\r\n\r\nDOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)\r\nVERSION = $(TCL_VERSION)\r\n\r\n!elseif $(DOING_TK)\r\n\r\nDOTVERSION = $(TK_DOTVERSION)\r\nVERSION = $(TK_VERSION)\r\n\r\n!else # Doing a non-Tk extension\r\n\r\n# If parent makefile has not defined DOTVERSION, try to get it from TEA\r\n# first from a configure.in file, and then from configure.ac\r\n!ifndef DOTVERSION\r\n!if [echo DOTVERSION = \\> versions.vc] \\\r\n   || [nmakehlp -V $(ROOT)\\configure.in ^[$(PROJECT)^] >> versions.vc]\r\n!if [echo DOTVERSION = \\> versions.vc] \\\r\n   || [nmakehlp -V $(ROOT)\\configure.ac ^[$(PROJECT)^] >> versions.vc]\r\n!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.\r\n!endif\r\n!endif\r\n!include versions.vc\r\n!endif # DOTVERSION\r\nVERSION         = $(DOTVERSION:.=)\r\n\r\n!endif # $(DOING_TCL) ... etc.\r\n\r\n# Windows RC files have 3 version components. Ensure this irrespective\r\n# of how many components the package has specified. Basically, ensure\r\n# minimum 4 components by appending 4 0's and then pick out the first 4.\r\n# Also take care of the fact that DOTVERSION may have \"a\" or \"b\" instead\r\n# of \".\" separating the version components.\r\nDOTSEPARATED=$(DOTVERSION:a=.)\r\nDOTSEPARATED=$(DOTSEPARATED:b=.)\r\n!if [echo RCCOMMAVERSION = \\> versions.vc] \\\r\n  || [for /f \"tokens=1,2,3,4,5* delims=.\" %a in (\"$(DOTSEPARATED).0.0.0.0\") do echo %a,%b,%c,%d >> versions.vc]\r\n!error *** Could not generate RCCOMMAVERSION ***\r\n!endif\r\n!include versions.vc\r\n\r\n########################################################################\r\n# 7. Parse the OPTS macro to work out the requested build configuration.\r\n# Based on this, we will construct the actual switches to be passed to the\r\n# compiler and linker using the macros defined in the previous section.\r\n# The following macros are defined by this section based on OPTS\r\n# STATIC_BUILD - 0 -> Tcl is to be built as a shared library\r\n#                1 -> build as a static library and shell\r\n# TCL_THREADS - legacy but always 1 on Windows since winsock requires it.\r\n# DEBUG - 1 -> debug build, 0 -> release builds\r\n# SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's\r\n# PROFILE - 1 -> generate profiling info, 0 -> no profiling\r\n# PGO     - 1 -> profile based optimization, 0 -> no\r\n# MSVCRT  - 1 -> link to dynamic C runtime even when building static Tcl build\r\n#           0 -> link to static C runtime for static Tcl build.\r\n#           Does not impact shared Tcl builds (STATIC_BUILD == 0)\r\n#           Default: 1 for Tcl 9.0 and up, 0 otherwise.\r\n# TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions\r\n#           in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does\r\n#           not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 9.0.\r\n# USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation.\r\n#           0 -> Use the non-thread allocator.\r\n# UNCHECKED - 1 -> when doing a debug build with symbols, use the release\r\n#           C runtime, 0 -> use the debug C runtime.\r\n# USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking\r\n# CONFIG_CHECK - 1 -> check current build configuration against Tcl\r\n#           configuration (ignored for Tcl itself)\r\n# _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build\r\n#           (CRT library should support this, not needed for Tcl 9.x)\r\n# Further, LINKERFLAGS are modified based on above.\r\n\r\n# Default values for all the above\r\nSTATIC_BUILD\t= 0\r\nTCL_THREADS\t= 1\r\nDEBUG\t\t= 0\r\nSYMBOLS\t\t= 0\r\nPROFILE\t\t= 0\r\nPGO\t\t= 0\r\nMSVCRT\t\t= 1\r\nTCL_USE_STATIC_PACKAGES\t= 0\r\nUSE_THREAD_ALLOC = 1\r\nUNCHECKED\t= 0\r\nCONFIG_CHECK    = 1\r\n!if $(DOING_TCL)\r\nUSE_STUBS       = 0\r\n!else\r\nUSE_STUBS       = 1\r\n!endif\r\n\r\n# If OPTS is not empty AND does not contain \"none\" which turns off all OPTS\r\n# set the above macros based on OPTS content\r\n!if \"$(OPTS)\" != \"\" && ![nmakehlp -f \"$(OPTS)\" \"none\"]\r\n\r\n# OPTS are specified, parse them\r\n\r\n!if [nmakehlp -f $(OPTS) \"static\"]\r\n!message *** Doing static\r\nSTATIC_BUILD\t= 1\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"nostubs\"]\r\n!message *** Not using stubs\r\nUSE_STUBS\t= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"nomsvcrt\"]\r\n!message *** Doing nomsvcrt\r\nMSVCRT\t\t= 0\r\n!else\r\n!if [nmakehlp -f $(OPTS) \"msvcrt\"]\r\n!message *** Doing msvcrt\r\n!else\r\n!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD)\r\nMSVCRT\t\t= 0\r\n!endif\r\n!endif\r\n!endif # [nmakehlp -f $(OPTS) \"nomsvcrt\"]\r\n\r\n!if [nmakehlp -f $(OPTS) \"staticpkg\"] && $(STATIC_BUILD)\r\n!message *** Doing staticpkg\r\nTCL_USE_STATIC_PACKAGES\t= 1\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"nothreads\"]\r\n!message *** Compile explicitly for non-threaded tcl\r\nTCL_THREADS = 0\r\nUSE_THREAD_ALLOC= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"tcl8\"]\r\n!message *** Build for Tcl8\r\nTCL_BUILD_FOR = 8\r\n!endif\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8\r\n!if [nmakehlp -f $(OPTS) \"time64bit\"]\r\n!message *** Force 64-bit time_t\r\n_USE_64BIT_TIME_T = 1\r\n!endif\r\n!endif\r\n\r\n# Yes, it's weird that the \"symbols\" option controls DEBUG and\r\n# the \"pdbs\" option controls SYMBOLS. That's historical.\r\n!if [nmakehlp -f $(OPTS) \"symbols\"]\r\n!message *** Doing symbols\r\nDEBUG\t\t= 1\r\n!else\r\nDEBUG\t\t= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"pdbs\"]\r\n!message *** Doing pdbs\r\nSYMBOLS\t\t= 1\r\n!else\r\nSYMBOLS\t\t= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"profile\"]\r\n!message *** Doing profile\r\nPROFILE\t\t= 1\r\n!else\r\nPROFILE\t\t= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"pgi\"]\r\n!message *** Doing profile guided optimization instrumentation\r\nPGO\t\t= 1\r\n!elseif [nmakehlp -f $(OPTS) \"pgo\"]\r\n!message *** Doing profile guided optimization\r\nPGO\t\t= 2\r\n!else\r\nPGO\t\t= 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"loimpact\"]\r\n!message *** Warning: ignoring option \"loimpact\" - deprecated on modern Windows.\r\n!endif\r\n\r\n# TBD - should get rid of this option\r\n!if [nmakehlp -f $(OPTS) \"thrdalloc\"]\r\n!message *** Doing thrdalloc\r\nUSE_THREAD_ALLOC = 1\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"tclalloc\"]\r\nUSE_THREAD_ALLOC = 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"unchecked\"]\r\n!message *** Doing unchecked\r\nUNCHECKED = 1\r\n!else\r\nUNCHECKED = 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(OPTS) \"noconfigcheck\"]\r\nCONFIG_CHECK = 1\r\n!else\r\nCONFIG_CHECK = 0\r\n!endif\r\n\r\n!endif # \"$(OPTS)\" != \"\"  && ... parsing of OPTS\r\n\r\n# Set linker flags based on above\r\n\r\n!if $(PGO) > 1\r\n!if [nmakehlp -l -ltcg:pgoptimize $(LINKER_TESTFLAGS)]\r\nLINKERFLAGS\t= $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize\r\n!else\r\nMSG=^\r\nThis compiler does not support profile guided optimization.\r\n!error $(MSG)\r\n!endif\r\n!elseif $(PGO) > 0\r\n!if [nmakehlp -l -ltcg:pginstrument $(LINKER_TESTFLAGS)]\r\nLINKERFLAGS\t= $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument\r\n!else\r\nMSG=^\r\nThis compiler does not support profile guided optimization.\r\n!error $(MSG)\r\n!endif\r\n!endif\r\n\r\n################################################################\r\n# 8. Parse the STATS macro to configure code instrumentation\r\n# The following macros are set by this section:\r\n# TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation\r\n#                 0 -> disables\r\n# TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging\r\n#                     0 -> disables\r\n\r\n# Default both are off\r\nTCL_MEM_DEBUG\t    = 0\r\nTCL_COMPILE_DEBUG   = 0\r\n\r\n!if \"$(STATS)\" != \"\" && ![nmakehlp -f \"$(STATS)\" \"none\"]\r\n\r\n!if [nmakehlp -f $(STATS) \"memdbg\"]\r\n!message *** Doing memdbg\r\nTCL_MEM_DEBUG\t    = 1\r\n!else\r\nTCL_MEM_DEBUG\t    = 0\r\n!endif\r\n\r\n!if [nmakehlp -f $(STATS) \"compdbg\"]\r\n!message *** Doing compdbg\r\nTCL_COMPILE_DEBUG   = 1\r\n!else\r\nTCL_COMPILE_DEBUG   = 0\r\n!endif\r\n\r\n!endif\r\n\r\n####################################################################\r\n# 9. Parse the CHECKS macro to configure additional compiler checks\r\n# The following macros are set by this section:\r\n# WARNINGS - compiler switches that control the warnings level\r\n# TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions\r\n#                     0 -> enable deprecated functions\r\n\r\n# Defaults - Permit deprecated functions and warning level 3\r\nTCL_NO_DEPRECATED\t    = 0\r\nWARNINGS\t\t    = -W3\r\n\r\n!if \"$(CHECKS)\" != \"\" && ![nmakehlp -f \"$(CHECKS)\" \"none\"]\r\n\r\n!if [nmakehlp -f $(CHECKS) \"nodep\"]\r\n!message *** Doing nodep check\r\nTCL_NO_DEPRECATED\t    = 1\r\n!endif\r\n\r\n!if [nmakehlp -f $(CHECKS) \"fullwarn\"]\r\n!message *** Doing full warnings check\r\nWARNINGS\t\t    = -W4\r\n!if [nmakehlp -l -warn:3 $(LINKER_TESTFLAGS)]\r\nLINKERFLAGS\t\t    = $(LINKERFLAGS) -warn:3\r\n!endif\r\n!endif\r\n\r\n!if [nmakehlp -f $(CHECKS) \"64bit\"] && [nmakehlp -c -Wp64]\r\n!message *** Doing 64bit portability warnings\r\nWARNINGS\t\t    = $(WARNINGS) -Wp64\r\n!endif\r\n\r\n!endif\r\n\r\n\r\n################################################################\r\n# 10. Construct output directory and file paths\r\n# Figure-out how to name our intermediate and output directories.\r\n# In order to avoid inadvertent mixing of object files built using\r\n# different compilers, build configurations etc.,\r\n#\r\n# Naming convention (suffixes):\r\n#   t = full thread support. (Not used for Tcl >= 9.0)\r\n#   s = static library (as opposed to an import library)\r\n#   g = linked to the debug enabled C run-time.\r\n#   x = special static build when it links to the dynamic C run-time.\r\n#\r\n# The following macros are set in this section:\r\n# SUFX - the suffix to use for binaries based on above naming convention\r\n# BUILDDIRTOP - the toplevel default output directory\r\n#      is of the form {Release,Debug}[_AMD64][_COMPILERVERSION]\r\n# TMP_DIR - directory where object files are created\r\n# OUT_DIR - directory where output executables are created\r\n# Both TMP_DIR and OUT_DIR are defaulted only if not defined by the\r\n# parent makefile (or command line). The default values are\r\n# based on BUILDDIRTOP.\r\n# STUBPREFIX - name of the stubs library for this project\r\n# PRJIMPLIB - output path of the generated project import library\r\n# PRJLIBNAME - name of generated project library\r\n# PRJLIB     - output path of generated project library\r\n# PRJSTUBLIBNAME - name of the generated project stubs library\r\n# PRJSTUBLIB - output path of the generated project stubs library\r\n# RESFILE - output resource file (only if not static build)\r\n\r\nSUFX\t    = tsgx\r\n\r\n!if $(DEBUG)\r\nBUILDDIRTOP = Debug\r\n!else\r\nBUILDDIRTOP = Release\r\n!endif\r\n\r\n!if \"$(MACHINE)\" != \"IX86\"\r\nBUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)\r\n!endif\r\n!if $(VCVER) > 6\r\nBUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)\r\n!endif\r\n\r\n!if !$(DEBUG) || $(TCL_VERSION) > 86 || $(DEBUG) && $(UNCHECKED)\r\nSUFX\t    = $(SUFX:g=)\r\n!endif\r\n\r\nTMP_DIRFULL = .\\$(BUILDDIRTOP)\\$(PROJECT)_ThreadedDynamicStaticX\r\n\r\n!if !$(STATIC_BUILD)\r\nTMP_DIRFULL = $(TMP_DIRFULL:Static=)\r\nSUFX\t    = $(SUFX:s=)\r\nEXT\t    = dll\r\nTMP_DIRFULL = $(TMP_DIRFULL:X=)\r\nSUFX\t    = $(SUFX:x=)\r\n!else\r\nTMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)\r\nEXT\t    = lib\r\n!if $(MSVCRT) && $(TCL_VERSION) > 86 || !$(MSVCRT) && $(TCL_VERSION) < 87\r\nTMP_DIRFULL = $(TMP_DIRFULL:X=)\r\nSUFX\t    = $(SUFX:x=)\r\n!endif\r\n!endif\r\n\r\n!if !$(TCL_THREADS) || $(TCL_VERSION) > 86\r\nTMP_DIRFULL = $(TMP_DIRFULL:Threaded=)\r\nSUFX\t    = $(SUFX:t=)\r\n!endif\r\n\r\n!ifndef TMP_DIR\r\nTMP_DIR\t    = $(TMP_DIRFULL)\r\n!ifndef OUT_DIR\r\nOUT_DIR\t    = .\\$(BUILDDIRTOP)\r\n!endif\r\n!else\r\n!ifndef OUT_DIR\r\nOUT_DIR\t    = $(TMP_DIR)\r\n!endif\r\n!endif\r\n\r\n# Relative paths -> absolute\r\n!if [echo OUT_DIR = \\> nmakehlp.out] \\\r\n   || [nmakehlp -Q \"$(OUT_DIR)\" >> nmakehlp.out]\r\n!error *** Could not fully qualify path OUT_DIR=$(OUT_DIR)\r\n!endif\r\n!if [echo TMP_DIR = \\>> nmakehlp.out] \\\r\n   || [nmakehlp -Q \"$(TMP_DIR)\" >> nmakehlp.out]\r\n!error *** Could not fully qualify path TMP_DIR=$(TMP_DIR)\r\n!endif\r\n!include nmakehlp.out\r\n\r\n# The name of the stubs library for the project being built\r\nSTUBPREFIX      = $(PROJECT)stub\r\n\r\n#\r\n# Set up paths to various Tcl executables and libraries needed by extensions\r\n#\r\n\r\n# TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc\r\nTCL_ZIP_FILE = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip\r\nTK_ZIP_FILE = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip\r\n\r\n!if $(DOING_TCL)\r\nTCLSHNAME       = $(PROJECT)sh$(VERSION)$(SUFX).exe\r\nTCLSH\t\t= $(OUT_DIR)\\$(TCLSHNAME)\r\nTCLIMPLIB\t= $(OUT_DIR)\\$(PROJECT)$(VERSION)$(SUFX).lib\r\nTCLLIBNAME\t= $(PROJECT)$(VERSION)$(SUFX).$(EXT)\r\nTCLLIB\t\t= $(OUT_DIR)\\$(TCLLIBNAME)\r\nTCLSCRIPTZIP    = $(OUT_DIR)\\$(TCL_ZIP_FILE)\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8\r\nTCLSTUBLIBNAME\t= $(STUBPREFIX)$(VERSION).lib\r\n!else\r\nTCLSTUBLIBNAME\t= $(STUBPREFIX).lib\r\n!endif\r\nTCLSTUBLIB\t= $(OUT_DIR)\\$(TCLSTUBLIBNAME)\r\nTCL_INCLUDES    = -I\"$(WIN_DIR)\" -I\"$(GENERICDIR)\"\r\n\r\n!else # !$(DOING_TCL)\r\n\r\n!if $(TCLINSTALL) # Building against an installed Tcl\r\n\r\n# When building extensions, we need to locate tclsh. Depending on version\r\n# of Tcl we are building against, this may or may not have a \"t\" suffix.\r\n# Try various possibilities in turn.\r\nTCLSH\t\t= $(_TCLDIR)\\bin\\tclsh$(TCL_VERSION)$(SUFX:t=).exe\r\n!if !exist(\"$(TCLSH)\")\r\nTCLSH           = $(_TCLDIR)\\bin\\tclsh$(TCL_VERSION)t$(SUFX:t=).exe\r\n!endif\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8\r\nTCLSTUBLIB\t= $(_TCLDIR)\\lib\\tclstub$(TCL_VERSION).lib\r\n!else\r\nTCLSTUBLIB\t= $(_TCLDIR)\\lib\\tclstub.lib\r\n!endif\r\nTCLIMPLIB\t= $(_TCLDIR)\\lib\\tcl$(TCL_VERSION)$(SUFX:t=).lib\r\n# When building extensions, may be linking against Tcl that does not add\r\n# \"t\" suffix (e.g. 8.6). If lib not found check for that possibility.\r\n!if !exist(\"$(TCLIMPLIB)\")\r\nTCLIMPLIB\t= $(_TCLDIR)\\lib\\tcl$(TCL_VERSION)t$(SUFX:t=).lib\r\n!endif\r\nTCL_LIBRARY\t= $(_TCLDIR)\\lib\r\nTCLREGLIB\t= $(_TCLDIR)\\lib\\tclreg13$(SUFX:t=).lib\r\nTCLDDELIB\t= $(_TCLDIR)\\lib\\tcldde14$(SUFX:t=).lib\r\nTCLSCRIPTZIP\t= $(_TCLDIR)\\lib\\$(TCL_ZIP_FILE)\r\nTCLTOOLSDIR\t= \\must\\have\\tcl\\sources\\to\\build\\this\\target\r\nTCL_INCLUDES    = -I\"$(_TCLDIR)\\include\"\r\n\r\n!else # Building against Tcl sources\r\n\r\nTCLSH\t\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tclsh$(TCL_VERSION)$(SUFX:t=).exe\r\n!if !exist($(TCLSH))\r\nTCLSH\t\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tclsh$(TCL_VERSION)t$(SUFX:t=).exe\r\n!endif\r\n!if $(TCL_MAJOR_VERSION) == 8\r\nTCLSTUBLIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tclstub$(TCL_VERSION).lib\r\n!else\r\nTCLSTUBLIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tclstub.lib\r\n!endif\r\nTCLIMPLIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tcl$(TCL_VERSION)$(SUFX:t=).lib\r\n# When building extensions, may be linking against Tcl that does not add\r\n# \"t\" suffix (e.g. 8.6). If lib not found check for that possibility.\r\n!if !exist(\"$(TCLIMPLIB)\")\r\nTCLIMPLIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tcl$(TCL_VERSION)t$(SUFX:t=).lib\r\n!endif\r\nTCL_LIBRARY\t= $(_TCLDIR)\\library\r\nTCLREGLIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tclreg13$(SUFX:t=).lib\r\nTCLDDELIB\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tcldde14$(SUFX:t=).lib\r\nTCLSCRIPTZIP\t= $(_TCLDIR)\\win\\$(BUILDDIRTOP)\\$(TCL_ZIP_FILE)\r\nTCLTOOLSDIR\t= $(_TCLDIR)\\tools\r\nTCL_INCLUDES\t= -I\"$(_TCLDIR)\\generic\" -I\"$(_TCLDIR)\\win\"\r\n\r\n!endif # TCLINSTALL\r\n\r\n!if !$(STATIC_BUILD) && \"$(TCL_BUILD_FOR)\" == \"8\"\r\ntcllibs = \"$(TCLSTUBLIB)\"\r\n!else\r\ntcllibs = \"$(TCLSTUBLIB)\" \"$(TCLIMPLIB)\"\r\n!endif\r\n\r\n!endif # $(DOING_TCL)\r\n\r\n# We need a tclsh that will run on the host machine as part of the build.\r\n# IX86 runs on all architectures.\r\n!ifndef TCLSH_NATIVE\r\n!if \"$(MACHINE)\" == \"IX86\" || \"$(MACHINE)\" == \"$(NATIVE_ARCH)\"\r\nTCLSH_NATIVE\t= $(TCLSH)\r\n!else\r\n!error You must explicitly set TCLSH_NATIVE for cross-compilation\r\n!endif\r\n!endif\r\n\r\n# Do the same for Tk and Tk extensions that require the Tk libraries\r\n!if $(DOING_TK) || $(NEED_TK)\r\nWISHNAMEPREFIX = wish\r\nWISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe\r\nTKLIBNAME8\t= tk$(TK_VERSION)$(SUFX).$(EXT)\r\nTKLIBNAME9\t= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)\r\n!if $(TCL_MAJOR_VERSION) == 8 || \"$(TCL_BUILD_FOR)\" == \"8\"\r\nTKLIBNAME\t= tk$(TK_VERSION)$(SUFX).$(EXT)\r\nTKIMPLIBNAME\t= tk$(TK_VERSION)$(SUFX).lib\r\n!else\r\nTKLIBNAME\t= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)\r\nTKIMPLIBNAME\t= tcl9tk$(TK_VERSION)$(SUFX).lib\r\n!endif\r\n!if $(TK_MAJOR_VERSION) == 8\r\nTKSTUBLIBNAME\t= tkstub$(TK_VERSION).lib\r\n!else\r\nTKSTUBLIBNAME\t= tkstub.lib\r\n!endif\r\n\r\n!if $(DOING_TK)\r\nWISH\t\t= $(OUT_DIR)\\$(WISHNAME)\r\nTKSTUBLIB\t= $(OUT_DIR)\\$(TKSTUBLIBNAME)\r\nTKIMPLIB\t= $(OUT_DIR)\\$(TKIMPLIBNAME)\r\nTKLIB\t\t= $(OUT_DIR)\\$(TKLIBNAME)\r\nTK_INCLUDES     = -I\"$(WIN_DIR)\" -I\"$(GENERICDIR)\"\r\nTKSCRIPTZIP     = $(OUT_DIR)\\$(TK_ZIP_FILE)\r\n\r\n!else # effectively NEED_TK\r\n\r\n!if $(TKINSTALL) # Building against installed Tk\r\nWISH\t\t= $(_TKDIR)\\bin\\$(WISHNAME)\r\nTKSTUBLIB\t= $(_TKDIR)\\lib\\$(TKSTUBLIBNAME)\r\nTKIMPLIB\t= $(_TKDIR)\\lib\\$(TKIMPLIBNAME)\r\n# When building extensions, may be linking against Tk that does not add\r\n# \"t\" suffix (e.g. 8.6). If lib not found check for that possibility.\r\n!if !exist(\"$(TKIMPLIB)\")\r\nTKIMPLIBNAME\t= tk$(TK_VERSION)$(SUFX:t=).lib\r\nTKIMPLIB\t= $(_TKDIR)\\lib\\$(TKIMPLIBNAME)\r\n!endif\r\nTK_INCLUDES     = -I\"$(_TKDIR)\\include\"\r\nTKSCRIPTZIP     = $(_TKDIR)\\lib\\$(TK_ZIP_FILE)\r\n\r\n!else # Building against Tk sources\r\n\r\nWISH\t\t= $(_TKDIR)\\win\\$(BUILDDIRTOP)\\$(WISHNAME)\r\nTKSTUBLIB\t= $(_TKDIR)\\win\\$(BUILDDIRTOP)\\$(TKSTUBLIBNAME)\r\nTKIMPLIB\t= $(_TKDIR)\\win\\$(BUILDDIRTOP)\\$(TKIMPLIBNAME)\r\n# When building extensions, may be linking against Tk that does not add\r\n# \"t\" suffix (e.g. 8.6). If lib not found check for that possibility.\r\n!if !exist(\"$(TKIMPLIB)\")\r\nTKIMPLIBNAME\t= tk$(TK_VERSION)$(SUFX:t=).lib\r\nTKIMPLIB\t= $(_TKDIR)\\win\\$(BUILDDIRTOP)\\$(TKIMPLIBNAME)\r\n!endif\r\nTK_INCLUDES     = -I\"$(_TKDIR)\\generic\" -I\"$(_TKDIR)\\win\" -I\"$(_TKDIR)\\xlib\"\r\nTKSCRIPTZIP     = $(_TKDIR)\\win\\$(BUILDDIRTOP)\\$(TK_ZIP_FILE)\r\n\r\n!endif # TKINSTALL\r\n\r\ntklibs = \"$(TKSTUBLIB)\" \"$(TKIMPLIB)\"\r\n\r\n!endif # $(DOING_TK)\r\n!endif # $(DOING_TK) || $(NEED_TK)\r\n\r\n# Various output paths\r\nPRJIMPLIB\t= $(OUT_DIR)\\$(PROJECT)$(VERSION)$(SUFX).lib\r\n# Even when building against Tcl 9, PRJLIBNAME8 must have \"t\"\r\nPRJLIBNAME8\t= $(PROJECT)$(VERSION)t$(SUFX:t=).$(EXT)\r\n# Even when building against Tcl 8, PRJLIBNAME9 must not have \"t\"\r\nPRJLIBNAME9\t= tcl9$(PROJECT)$(VERSION)$(SUFX:t=).$(EXT)\r\n!if $(TCL_MAJOR_VERSION) == 8 || \"$(TCL_BUILD_FOR)\" == \"8\"\r\nPRJLIBNAME\t= $(PRJLIBNAME8)\r\n!else\r\nPRJLIBNAME\t= $(PRJLIBNAME9)\r\n!endif\r\nPRJLIB\t\t= $(OUT_DIR)\\$(PRJLIBNAME)\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8\r\nPRJSTUBLIBNAME\t= $(STUBPREFIX)$(VERSION).lib\r\n!else\r\nPRJSTUBLIBNAME\t= $(STUBPREFIX).lib\r\n!endif\r\nPRJSTUBLIB\t= $(OUT_DIR)\\$(PRJSTUBLIBNAME)\r\n\r\n# If extension parent makefile has not defined a resource definition file,\r\n# we will generate one from standard template.\r\n!if !$(DOING_TCL) && !$(DOING_TK) && !$(STATIC_BUILD)\r\n!ifdef RCFILE\r\nRESFILE = $(TMP_DIR)\\$(RCFILE:.rc=.res)\r\n!else\r\nRESFILE = $(TMP_DIR)\\$(PROJECT).res\r\n!endif\r\n!endif\r\n\r\n###################################################################\r\n# 11. Construct the paths for the installation directories\r\n# The following macros get defined in this section:\r\n# LIB_INSTALL_DIR - where libraries should be installed\r\n# BIN_INSTALL_DIR - where the executables should be installed\r\n# DOC_INSTALL_DIR - where documentation should be installed\r\n# SCRIPT_INSTALL_DIR - where scripts should be installed\r\n# INCLUDE_INSTALL_DIR - where C include files should be installed\r\n# DEMO_INSTALL_DIR - where demos should be installed\r\n# PRJ_INSTALL_DIR - where package will be installed (not set for Tcl and Tk)\r\n\r\n!if $(DOING_TCL) || $(DOING_TK)\r\nLIB_INSTALL_DIR\t\t= $(_INSTALLDIR)\\lib\r\nBIN_INSTALL_DIR\t\t= $(_INSTALLDIR)\\bin\r\nDOC_INSTALL_DIR\t\t= $(_INSTALLDIR)\\doc\r\n!if $(DOING_TCL)\r\nSCRIPT_INSTALL_DIR\t= $(_INSTALLDIR)\\lib\\$(PROJECT)$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)\r\nMODULE_INSTALL_DIR\t= $(_INSTALLDIR)\\lib\\tcl$(TCL_MAJOR_VERSION)\r\n!else # DOING_TK\r\nSCRIPT_INSTALL_DIR\t= $(_INSTALLDIR)\\lib\\$(PROJECT)$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)\r\n!endif\r\nDEMO_INSTALL_DIR\t= $(SCRIPT_INSTALL_DIR)\\demos\r\nINCLUDE_INSTALL_DIR\t= $(_INSTALLDIR)\\include\r\n\r\n!else # extension other than Tk\r\n\r\nPRJ_INSTALL_DIR         = $(_INSTALLDIR)\\$(PROJECT)$(DOTVERSION)\r\n!if $(MULTIPLATFORM_INSTALL)\r\nLIB_INSTALL_DIR\t\t= $(PRJ_INSTALL_DIR)\\$(PLATFORM_IDENTIFY)\r\nBIN_INSTALL_DIR\t\t= $(PRJ_INSTALL_DIR)\\$(PLATFORM_IDENTIFY)\r\n!else\r\nLIB_INSTALL_DIR\t\t= $(PRJ_INSTALL_DIR)\r\nBIN_INSTALL_DIR\t\t= $(PRJ_INSTALL_DIR)\r\n!endif\r\nDOC_INSTALL_DIR\t\t= $(PRJ_INSTALL_DIR)\r\nSCRIPT_INSTALL_DIR\t= $(PRJ_INSTALL_DIR)\r\nDEMO_INSTALL_DIR\t= $(PRJ_INSTALL_DIR)\\demos\r\nINCLUDE_INSTALL_DIR\t= $(_INSTALLDIR)\\..\\include\r\n\r\n!endif\r\n\r\n###################################################################\r\n# 12. Set up actual options to be passed to the compiler and linker\r\n# Now we have all the information we need, set up the actual flags and\r\n# options that we will pass to the compiler and linker. The main\r\n# makefile should use these in combination with whatever other flags\r\n# and switches are specific to it.\r\n# The following macros are defined, names are for historical compatibility:\r\n# OPTDEFINES - /Dxxx C macro flags based on user-specified OPTS\r\n# COMPILERFLAGS - /Dxxx C macro flags independent of any configuration options\r\n# crt - Compiler switch that selects the appropriate C runtime\r\n# cdebug - Compiler switches related to debug AND optimizations\r\n# cwarn - Compiler switches that set warning levels\r\n# cflags - complete compiler switches (subsumes cdebug and cwarn)\r\n# ldebug - Linker switches controlling debug information and optimization\r\n# lflags - complete linker switches (subsumes ldebug) except subsystem type\r\n# dlllflags - complete linker switches to build DLLs (subsumes lflags)\r\n# conlflags - complete linker switches for console program (subsumes lflags)\r\n# guilflags - complete linker switches for GUI program (subsumes lflags)\r\n# baselibs - minimum Windows libraries required. Parent makefile can\r\n#    define PRJ_LIBS before including rules.rc if additional libs are needed\r\n\r\nOPTDEFINES\t= /DSTDC_HEADERS /DUSE_NMAKE=1\r\n!if $(VCVERSION) > 1600\r\nOPTDEFINES\t= $(OPTDEFINES) /DHAVE_STDINT_H=1\r\n!else\r\nOPTDEFINES\t= $(OPTDEFINES) /DMP_NO_STDINT=1\r\n!endif\r\n!if $(VCVERSION) >= 1800\r\nOPTDEFINES\t= $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1\r\n!endif\r\n\r\n!if $(TCL_MEM_DEBUG)\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_MEM_DEBUG\r\n!endif\r\n!if $(TCL_COMPILE_DEBUG)\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS\r\n!endif\r\n!if $(TCL_THREADS) && $(TCL_VERSION) < 87\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_THREADS=1\r\n!if $(USE_THREAD_ALLOC) && $(TCL_VERSION) < 87\r\nOPTDEFINES\t= $(OPTDEFINES) /DUSE_THREAD_ALLOC=1\r\n!endif\r\n!endif\r\n!if $(STATIC_BUILD)\r\nOPTDEFINES\t= $(OPTDEFINES) /DSTATIC_BUILD\r\n!elseif $(TCL_VERSION) > 86\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH\r\n!if \"$(MACHINE)\" == \"AMD64\" || \"$(MACHINE)\" == \"ARM64\"\r\nOPTDEFINES\t= $(OPTDEFINES) /DMP_64BIT\r\n!endif\r\n!endif\r\n!if $(TCL_NO_DEPRECATED)\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_NO_DEPRECATED\r\n!endif\r\n\r\n!if $(USE_STUBS)\r\n# Note we do not define USE_TCL_STUBS even when building tk since some\r\n# test targets in tk do not use stubs\r\n!if !$(DOING_TCL)\r\nUSE_STUBS_DEFS  = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS\r\n!if $(NEED_TK)\r\nUSE_STUBS_DEFS  = $(USE_STUBS_DEFS) /DUSE_TK_STUBS\r\n!endif\r\n!endif\r\n!endif # USE_STUBS\r\n\r\n!if !$(DEBUG)\r\nOPTDEFINES\t= $(OPTDEFINES) /DNDEBUG\r\n!if $(OPTIMIZING)\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED\r\n!endif\r\n!endif\r\n!if $(PROFILE)\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_CFG_PROFILED\r\n!endif\r\n!if \"$(MACHINE)\" == \"AMD64\" || \"$(MACHINE)\" == \"ARM64\"\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_CFG_DO64BIT\r\n!endif\r\n!if $(VCVERSION) < 1300\r\nOPTDEFINES\t= $(OPTDEFINES) /DNO_STRTOI64=1\r\n!endif\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8\r\n!if \"$(_USE_64BIT_TIME_T)\" == \"1\"\r\nOPTDEFINES\t= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1\r\n!endif\r\n!endif\r\n!if \"$(TCL_BUILD_FOR)\" == \"8\"\r\nOPTDEFINES\t= $(OPTDEFINES) /DTCL_MAJOR_VERSION=8 /DTK_MAJOR_VERSION=8\r\n!endif\r\n\r\n# Like the TEA system only set this non empty for non-Tk extensions\r\n# Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME\r\n# so we pass both\r\n!if !$(DOING_TCL) && !$(DOING_TK)\r\nPKGNAMEFLAGS = /DPACKAGE_NAME=\"\\\"$(PRJ_PACKAGE_TCLNAME)\\\"\" \\\r\n\t/DPACKAGE_TCLNAME=\"\\\"$(PRJ_PACKAGE_TCLNAME)\\\"\" \\\r\n\t/DPACKAGE_VERSION=\"\\\"$(DOTVERSION)\\\"\" \\\r\n\t/DMODULE_SCOPE=extern\r\n!endif\r\n\r\n# crt picks the C run time based on selected OPTS\r\n!if $(MSVCRT)\r\n!if $(DEBUG) && !$(UNCHECKED)\r\ncrt = -MDd\r\n!else\r\ncrt = -MD\r\n!endif\r\n!else\r\n!if $(DEBUG) && !$(UNCHECKED)\r\ncrt = -MTd\r\n!else\r\ncrt = -MT\r\n!endif\r\n!endif\r\n\r\n# cdebug includes compiler options for debugging as well as optimization.\r\n!if $(DEBUG)\r\n\r\n# In debugging mode, optimizations need to be disabled\r\ncdebug = -Zi -Od $(DEBUGFLAGS)\r\n\r\n!else\r\n\r\ncdebug = $(OPTIMIZATIONS)\r\n!if $(SYMBOLS)\r\ncdebug = $(cdebug) -Zi\r\n!endif\r\n\r\n!endif # $(DEBUG)\r\n\r\n# cwarn includes default warning levels, also C4090 (buggy) and C4146 is useless.\r\ncwarn = $(WARNINGS) -wd4090 -wd4146\r\n\r\n!if \"$(MACHINE)\" == \"AMD64\" || \"$(MACHINE)\" == \"ARM64\"\r\n# Disable pointer<->int warnings related to cast between different sizes\r\n# There are a gadzillion of these due to use of ClientData and\r\n# clutter up compiler\r\n# output increasing chance of a real warning getting lost. So disable them.\r\n# Eventually some day, Tcl will be 64-bit clean.\r\ncwarn = $(cwarn) -wd4311 -wd4312\r\n!endif\r\n\r\n### Common compiler options that are architecture specific\r\n!if \"$(MACHINE)\" == \"ARM\"\r\ncarch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE\r\n!else\r\ncarch =\r\n!endif\r\n\r\n# cpuid is only available on intel machines\r\n!if \"$(MACHINE)\" == \"IX86\" || \"$(MACHINE)\" == \"AMD64\"\r\ncarch = $(carch) /DHAVE_CPUID=1\r\n!endif\r\n\r\n!if $(DEBUG)\r\n# Turn warnings into errors\r\ncwarn = $(cwarn) -WX\r\n!endif\r\n\r\nINCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES)\r\n!if !$(DOING_TCL) && !$(DOING_TK)\r\nINCLUDES = $(INCLUDES) -I\"$(GENERICDIR)\" -I\"$(WIN_DIR)\" -I\"$(COMPATDIR)\"\r\n!endif\r\n\r\n# These flags are defined roughly in the order of the pre-reform\r\n# rules.vc/makefile.vc to help visually compare that the pre- and\r\n# post-reform build logs\r\n\r\n# cflags contains generic flags used for building practically all object files\r\ncflags = -nologo -c $(COMPILERFLAGS) $(carch) $(cwarn) -Fp$(TMP_DIR)^\\ $(cdebug)\r\n\r\n!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7\r\ncflags = $(cflags) -DTcl_Size=int\r\n!endif\r\n\r\n# appcflags contains $(cflags) and flags for building the application\r\n# object files (e.g. tclsh, or wish) pkgcflags contains $(cflags) plus\r\n# flags used for building shared object files The two differ in the\r\n# BUILD_$(PROJECT) macro which should be defined only for the shared\r\n# library *implementation* and not for its caller interface\r\n\r\nappcflags_nostubs = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES)\r\nappcflags = $(appcflags_nostubs) $(USE_STUBS_DEFS)\r\npkgcflags = $(appcflags) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)\r\npkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)\r\n\r\n# stubscflags contains $(cflags) plus flags used for building a stubs\r\n# library for the package.  Note: /DSTATIC_BUILD is defined in\r\n# $(OPTDEFINES) only if the OPTS configuration indicates a static\r\n# library. However the stubs library is ALWAYS static hence included\r\n# here irrespective of the OPTS setting.\r\n#\r\n# TBD - tclvfs has a comment that stubs libs should not be compiled with -GL\r\n# without stating why. Tcl itself compiled stubs libs with this flag.\r\n# so we do not remove it from cflags. -GL may prevent extensions\r\n# compiled with one VC version to fail to link against stubs library\r\n# compiled with another VC version. Check for this and fix accordingly.\r\nstubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) /Zl /GL- /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS)\r\n\r\n# Link flags\r\n\r\n!if $(DEBUG)\r\nldebug\t= -debug -debugtype:cv\r\n!else\r\nldebug\t= -release -opt:ref -opt:icf,3\r\n!if $(SYMBOLS)\r\nldebug\t= $(ldebug) -debug -debugtype:cv\r\n!endif\r\n!endif\r\n\r\n# Note: Profiling is currently only possible with the Visual Studio Enterprise\r\n!if $(PROFILE)\r\nldebug= $(ldebug) -profile\r\n!endif\r\n\r\n### Declarations common to all linker versions\r\nlflags\t= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)\r\n\r\n!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900\r\nlflags\t= $(lflags) -nodefaultlib:ucrt.lib\r\n!endif\r\n\r\ndlllflags = $(lflags) -dll\r\nconlflags = $(lflags) -subsystem:console\r\nguilflags = $(lflags) -subsystem:windows\r\n\r\n# Libraries that are required for every image.\r\n# Extensions should define any additional libraries with $(PRJ_LIBS)\r\nwinlibs   = kernel32.lib advapi32.lib\r\n\r\n!if $(NEED_TK)\r\nwinlibs = $(winlibs) gdi32.lib user32.lib uxtheme.lib\r\n!endif\r\n\r\n# Avoid 'unresolved external symbol __security_cookie' errors.\r\n# c.f. http://support.microsoft.com/?id=894573\r\n!if \"$(MACHINE)\" == \"AMD64\"\r\n!if $(VCVERSION) > 1399 && $(VCVERSION) < 1500\r\nwinlibs   = $(winlibs) bufferoverflowU.lib\r\n!endif\r\n!endif\r\n\r\nbaselibs = $(winlibs) $(PRJ_LIBS)\r\n\r\n!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900\r\nbaselibs   = $(baselibs) ucrt.lib\r\n!endif\r\n\r\n################################################################\r\n# 13. Define standard commands, common make targets and implicit rules\r\n\r\nCCPKGCMD = $(cc32) $(pkgcflags) -Fo$(TMP_DIR)^\\\r\nCCAPPCMD = $(cc32) $(appcflags) -Fo$(TMP_DIR)^\\\r\nCCSTUBSCMD = $(cc32) $(stubscflags) -Fo$(TMP_DIR)^\\\r\n\r\nLIBCMD = $(lib32) -nologo $(LINKERFLAGS) -out:$@\r\nDLLCMD = $(link32) $(dlllflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)\r\n\r\nCONEXECMD = $(link32) $(conlflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)\r\nGUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)\r\nRESCMD  = $(rc32) -fo $@ -r -i \"$(GENERICDIR)\" -i \"$(TMP_DIR)\" \\\r\n\t    $(TCL_INCLUDES) /DSTATIC_BUILD=$(STATIC_BUILD) \\\r\n\t    /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \\\r\n\t    /DCOMMAVERSION=$(RCCOMMAVERSION) \\\r\n\t    /DDOTVERSION=\\\"$(DOTVERSION)\\\" \\\r\n\t    /DVERSION=\\\"$(VERSION)\\\" \\\r\n\t    /DSUFX=\\\"$(SUFX)\\\" \\\r\n\t    /DPROJECT=\\\"$(PROJECT)\\\" \\\r\n\t    /DPRJLIBNAME=\\\"$(PRJLIBNAME)\\\"\r\n\r\n!ifndef DEFAULT_BUILD_TARGET\r\nDEFAULT_BUILD_TARGET = $(PROJECT)\r\n!endif\r\n\r\ndefault-target: $(DEFAULT_BUILD_TARGET)\r\n\r\n!if $(MULTIPLATFORM_INSTALL)\r\ndefault-pkgindex:\r\n\t@echo if {[package vsatisfies [package provide Tcl] 9.0]} { > $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \\\r\n\t    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME9)]] >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo } else { >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \\\r\n\t    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME8)]] >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo } >> $(OUT_DIR)\\pkgIndex.tcl\r\n!else\r\ndefault-pkgindex:\r\n\t@echo if {[package vsatisfies [package provide Tcl] 9.0]} { > $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \\\r\n\t    [list load [file join $$dir $(PRJLIBNAME9)]] >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo } else { >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \\\r\n\t    [list load [file join $$dir $(PRJLIBNAME8)]] >> $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo } >> $(OUT_DIR)\\pkgIndex.tcl\r\n!endif\r\n\r\ndefault-pkgindex-tea:\r\n\t@if exist $(ROOT)\\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\\pkgIndex.tcl.in > $(OUT_DIR)\\pkgIndex.tcl\r\n@PACKAGE_VERSION@    $(DOTVERSION)\r\n@PACKAGE_NAME@       $(PRJ_PACKAGE_TCLNAME)\r\n@PACKAGE_TCLNAME@    $(PRJ_PACKAGE_TCLNAME)\r\n@PKG_LIB_FILE@       $(PRJLIBNAME)\r\n@PKG_LIB_FILE8@      $(PRJLIBNAME8)\r\n@PKG_LIB_FILE9@      $(PRJLIBNAME9)\r\n<<\r\n\r\ndefault-install: default-install-binaries default-install-libraries\r\n!if $(SYMBOLS)\r\ndefault-install: default-install-pdbs\r\n!endif\r\n\r\n# Again to deal with historical brokenness, there is some confusion\r\n# in terminlogy. For extensions, the \"install-binaries\" was used to\r\n# locate target directory for *binary shared libraries* and thus\r\n# the appropriate macro is LIB_INSTALL_DIR since BIN_INSTALL_DIR is\r\n# for executables (exes). On the other hand the \"install-libraries\"\r\n# target is for *scripts* and should have been called \"install-scripts\".\r\ndefault-install-binaries: $(PRJLIB)\r\n\t@echo Installing binaries to '$(LIB_INSTALL_DIR)'\r\n\t@if not exist \"$(LIB_INSTALL_DIR)\" mkdir \"$(LIB_INSTALL_DIR)\"\r\n\t@$(CPY) $(PRJLIB) \"$(LIB_INSTALL_DIR)\" >NUL\r\n\r\n# Alias for default-install-scripts\r\ndefault-install-libraries: default-install-scripts\r\n\r\ndefault-install-scripts: $(OUT_DIR)\\pkgIndex.tcl\r\n\t@echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'\r\n\t@if not exist \"$(SCRIPT_INSTALL_DIR)\" mkdir \"$(SCRIPT_INSTALL_DIR)\"\r\n\t@if exist $(LIBDIR) $(CPY) $(LIBDIR)\\*.tcl \"$(SCRIPT_INSTALL_DIR)\"\r\n\t@echo Installing package index in '$(SCRIPT_INSTALL_DIR)'\r\n\t@$(CPY) $(OUT_DIR)\\pkgIndex.tcl $(SCRIPT_INSTALL_DIR)\r\n\r\ndefault-install-stubs:\r\n\t@echo Installing stubs library to '$(SCRIPT_INSTALL_DIR)'\r\n\t@if not exist \"$(SCRIPT_INSTALL_DIR)\" mkdir \"$(SCRIPT_INSTALL_DIR)\"\r\n\t@$(CPY) $(PRJSTUBLIB) \"$(SCRIPT_INSTALL_DIR)\" >NUL\r\n\r\ndefault-install-pdbs:\r\n\t@echo Installing PDBs to '$(LIB_INSTALL_DIR)'\r\n\t@if not exist \"$(LIB_INSTALL_DIR)\" mkdir \"$(LIB_INSTALL_DIR)\"\r\n\t@$(CPY) \"$(OUT_DIR)\\*.pdb\" \"$(LIB_INSTALL_DIR)\\\"\r\n\r\n# \"emacs font-lock highlighting fix\r\n\r\ndefault-install-docs-html:\r\n\t@echo Installing documentation files to '$(DOC_INSTALL_DIR)'\r\n\t@if not exist \"$(DOC_INSTALL_DIR)\" mkdir \"$(DOC_INSTALL_DIR)\"\r\n\t@if exist $(DOCDIR) for %f in (\"$(DOCDIR)\\*.html\" \"$(DOCDIR)\\*.css\" \"$(DOCDIR)\\*.png\") do @$(COPY) %f \"$(DOC_INSTALL_DIR)\"\r\n\r\ndefault-install-docs-n:\r\n\t@echo Installing documentation files to '$(DOC_INSTALL_DIR)'\r\n\t@if not exist \"$(DOC_INSTALL_DIR)\" mkdir \"$(DOC_INSTALL_DIR)\"\r\n\t@if exist $(DOCDIR) for %f in (\"$(DOCDIR)\\*.n\") do @$(COPY) %f \"$(DOC_INSTALL_DIR)\"\r\n\r\ndefault-install-demos:\r\n\t@echo Installing demos to '$(DEMO_INSTALL_DIR)'\r\n\t@if not exist \"$(DEMO_INSTALL_DIR)\" mkdir \"$(DEMO_INSTALL_DIR)\"\r\n\t@if exist $(DEMODIR) $(CPYDIR) \"$(DEMODIR)\" \"$(DEMO_INSTALL_DIR)\"\r\n\r\ndefault-clean:\r\n\t@echo Cleaning $(TMP_DIR)\\* ...\r\n\t@if exist $(TMP_DIR)\\nul $(RMDIR) $(TMP_DIR)\r\n\t@echo Cleaning $(WIN_DIR)\\nmakehlp.obj, nmakehlp.exe ...\r\n\t@if exist $(WIN_DIR)\\nmakehlp.obj del $(WIN_DIR)\\nmakehlp.obj\r\n\t@if exist $(WIN_DIR)\\nmakehlp.exe del $(WIN_DIR)\\nmakehlp.exe\r\n\t@if exist $(WIN_DIR)\\nmakehlp.out del $(WIN_DIR)\\nmakehlp.out\r\n\t@echo Cleaning $(WIN_DIR)\\nmhlp-out.txt ...\r\n\t@if exist $(WIN_DIR)\\nmhlp-out.txt del $(WIN_DIR)\\nmhlp-out.txt\r\n\t@echo Cleaning $(WIN_DIR)\\_junk.pch ...\r\n\t@if exist $(WIN_DIR)\\_junk.pch del $(WIN_DIR)\\_junk.pch\r\n\t@echo Cleaning $(WIN_DIR)\\vercl.x, vercl.i ...\r\n\t@if exist $(WIN_DIR)\\vercl.x del $(WIN_DIR)\\vercl.x\r\n\t@if exist $(WIN_DIR)\\vercl.i del $(WIN_DIR)\\vercl.i\r\n\t@echo Cleaning $(WIN_DIR)\\versions.vc, version.vc ...\r\n\t@if exist $(WIN_DIR)\\versions.vc del $(WIN_DIR)\\versions.vc\r\n\t@if exist $(WIN_DIR)\\version.vc del $(WIN_DIR)\\version.vc\r\n\r\ndefault-hose: default-clean\r\n\t@echo Hosing $(OUT_DIR)\\* ...\r\n\t@if exist $(OUT_DIR)\\nul $(RMDIR) $(OUT_DIR)\r\n\r\n# Only for backward compatibility\r\ndefault-distclean: default-hose\r\n\r\ndefault-setup:\r\n\t@if not exist $(OUT_DIR)\\nul mkdir $(OUT_DIR)\r\n\t@if not exist $(TMP_DIR)\\nul mkdir $(TMP_DIR)\r\n\r\n!if \"$(TESTPAT)\" != \"\"\r\nTESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)\r\n!endif\r\n\r\ndefault-test: default-setup $(PROJECT)\r\n\t@set TCLLIBPATH=$(OUT_DIR:\\=/)\r\n\t@if exist $(LIBDIR) for %f in (\"$(LIBDIR)\\*.tcl\") do @$(COPY) %f \"$(OUT_DIR)\"\r\n\tcd \"$(TESTDIR)\" && $(DEBUGGER) $(TCLSH) all.tcl $(TESTFLAGS)\r\n\r\ndefault-shell: default-setup $(PROJECT)\r\n\t@set TCLLIBPATH=$(OUT_DIR:\\=/)\r\n\t@if exist $(LIBDIR) for %f in (\"$(LIBDIR)\\*.tcl\") do @$(COPY) %f \"$(OUT_DIR)\"\r\n\t$(DEBUGGER) $(TCLSH)\r\n\r\n# Generation of Windows version resource\r\n!ifdef RCFILE\r\n\r\n# Note: don't use $** in below rule because there may be other dependencies\r\n# and only the \"main\" rc must be passed to the resource compiler\r\n$(TMP_DIR)\\$(PROJECT).res: $(RCDIR)\\$(PROJECT).rc\r\n\t$(RESCMD) $(RCDIR)\\$(PROJECT).rc\r\n\r\n!else\r\n\r\n# If parent makefile has not defined a resource definition file,\r\n# we will generate one from standard template.\r\n$(TMP_DIR)\\$(PROJECT).res: $(TMP_DIR)\\$(PROJECT).rc\r\n\r\n$(TMP_DIR)\\$(PROJECT).rc:\r\n\t@$(COPY) << $(TMP_DIR)\\$(PROJECT).rc\r\n#include <winver.h>\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\n FILEVERSION\tCOMMAVERSION\r\n PRODUCTVERSION\tCOMMAVERSION\r\n FILEFLAGSMASK\t0x3fL\r\n#ifdef DEBUG\r\n FILEFLAGS\tVS_FF_DEBUG\r\n#else\r\n FILEFLAGS\t0x0L\r\n#endif\r\n FILEOS\t\tVOS_NT_WINDOWS32\r\n FILETYPE\tVFT_DLL\r\n FILESUBTYPE\t0x0L\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n\tBLOCK \"040904b0\"\r\n\tBEGIN\r\n\t    VALUE \"FileDescription\",  \"Tcl extension \" PROJECT\r\n\t    VALUE \"OriginalFilename\", PRJLIBNAME\r\n\t    VALUE \"FileVersion\",      DOTVERSION\r\n\t    VALUE \"ProductName\",      \"Package \" PROJECT \" for Tcl\"\r\n\t    VALUE \"ProductVersion\",   DOTVERSION\r\n\tEND\r\n    END\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n\tVALUE \"Translation\", 0x409, 1200\r\n    END\r\nEND\r\n\r\n<<\r\n\r\n!endif # ifdef RCFILE\r\n\r\n!ifndef DISABLE_IMPLICIT_RULES\r\nDISABLE_IMPLICIT_RULES = 0\r\n!endif\r\n\r\n!if !$(DISABLE_IMPLICIT_RULES)\r\n# Implicit rule definitions - only for building library objects. For stubs and\r\n# main application, the makefile should define explicit rules.\r\n\r\n{$(ROOT)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(WIN_DIR)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::\r\n\t$(CCPKGCMD) @<<\r\n$<\r\n<<\r\n\r\n{$(RCDIR)}.rc{$(TMP_DIR)}.res:\r\n\t$(RESCMD) $<\r\n\r\n{$(WIN_DIR)}.rc{$(TMP_DIR)}.res:\r\n\t$(RESCMD) $<\r\n\r\n{$(TMP_DIR)}.rc{$(TMP_DIR)}.res:\r\n\t$(RESCMD) $<\r\n\r\n.SUFFIXES:\r\n.SUFFIXES:.c .rc\r\n\r\n!endif\r\n\r\n################################################################\r\n# 14. Sanity check selected options against Tcl build options\r\n# When building an extension, certain configuration options should\r\n# match the ones used when Tcl was built. Here we check and\r\n# warn on a mismatch.\r\n!if !$(DOING_TCL)\r\n\r\n!if $(TCLINSTALL) # Building against an installed Tcl\r\n!if exist(\"$(_TCLDIR)\\lib\\nmake\\tcl.nmake\")\r\nTCLNMAKECONFIG = \"$(_TCLDIR)\\lib\\nmake\\tcl.nmake\"\r\n!endif\r\n!else # !$(TCLINSTALL) - building against Tcl source\r\n!if exist(\"$(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tcl.nmake\")\r\nTCLNMAKECONFIG\t= \"$(_TCLDIR)\\win\\$(BUILDDIRTOP)\\tcl.nmake\"\r\n!endif\r\n!endif # TCLINSTALL\r\n\r\n!if $(CONFIG_CHECK)\r\n!ifdef TCLNMAKECONFIG\r\n!include $(TCLNMAKECONFIG)\r\n\r\n!if defined(CORE_MACHINE) && \"$(CORE_MACHINE)\" != \"$(MACHINE)\"\r\n!error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)).\r\n!endif\r\n!if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)\r\n!message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)).\r\n!endif\r\n!if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG)\r\n!message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)).\r\n!endif\r\n!endif\r\n\r\n!endif # TCLNMAKECONFIG\r\n\r\n!endif # !$(DOING_TCL)\r\n\r\n\r\n#----------------------------------------------------------\r\n# Display stats being used.\r\n#----------------------------------------------------------\r\n\r\n!if !$(DOING_TCL)\r\n!message *** Building against Tcl at '$(_TCLDIR)'\r\n!endif\r\n!if !$(DOING_TK) && $(NEED_TK)\r\n!message *** Building against Tk at '$(_TKDIR)'\r\n!endif\r\n!message *** Intermediate directory will be '$(TMP_DIR)'\r\n!message *** Output directory will be '$(OUT_DIR)'\r\n!message *** Installation, if selected, will be in '$(_INSTALLDIR)'\r\n!message *** Suffix for binaries will be '$(SUFX)'\r\n!message *** Compiler version $(VCVER). Target $(MACHINE), host $(NATIVE_ARCH).\r\n\r\n!endif # ifdef _RULES_VC\r\n"
  },
  {
    "path": "win/stubs.c",
    "content": "#include \"tkInt.h\"\n\n/*\n * Undocumented Xlib internal function\n */\n\nint\n_XInitImageFuncPtrs(\n    TCL_UNUSED(XImage *))\n{\n    return Success;\n}\n\n/*\n * From Xutil.h\n */\n\nvoid\nXSetWMClientMachine(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(XTextProperty *))\n{\n}\n\nStatus\nXStringListToTextProperty(\n    TCL_UNUSED(char **),\n    TCL_UNUSED(int),\n    TCL_UNUSED(XTextProperty *))\n{\n    return Success;\n}\n\n/*\n * From Xlib.h\n */\n\nint\nXChangeProperty(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(const unsigned char *),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nXIC\nXCreateIC(TCL_UNUSED(XIM), ...)\n{\n    return NULL;\n}\n\nint\nXDeleteProperty(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom))\n{\n    return Success;\n}\n\nBool\nXFilterEvent(\n    TCL_UNUSED(XEvent *),\n    TCL_UNUSED(Window))\n{\n    return 0;\n}\n\nint\nXForceScreenSaver(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXFreeCursor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Cursor))\n{\n    return Success;\n}\n\nGContext\nXGContextFromGC(\n    TCL_UNUSED(GC))\n{\n    return (GContext) NULL;\n}\n\nchar *\nXGetAtomName(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Atom))\n{\n    return NULL;\n}\n\nint\nXGetWindowAttributes(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(XWindowAttributes *))\n{\n    return Success;\n}\n\nStatus\nXGetWMColormapWindows(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window **),\n    TCL_UNUSED(int *))\n{\n    return Success;\n}\n\nint\nXIconifyWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nXHostAddress *\nXListHosts(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(Bool *))\n{\n    return NULL;\n}\n\nint\nXLookupColor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(XColor *),\n    TCL_UNUSED(XColor *))\n{\n    return Success;\n}\n\nint\nXNextEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXPutBackEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXQueryColors(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    TCL_UNUSED(XColor *),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXQueryTree(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window **),\n    TCL_UNUSED(unsigned int *))\n{\n    return Success;\n}\n\nint\nXRefreshKeyboardMapping(\n    TCL_UNUSED(XMappingEvent *))\n{\n    return Success;\n}\n\nWindow\nXRootWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int))\n{\n    return (Window) NULL;\n}\n\nint\nXSelectInput(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(long))\n{\n    return Success;\n}\n\nint\nXSendEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Bool),\n    TCL_UNUSED(long),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXSetCommand(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(char **),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nXErrorHandler\nXSetErrorHandler(\n    TCL_UNUSED(XErrorHandler))\n{\n    return NULL;\n}\n\nint\nXSetIconName(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(const char *))\n{\n    return Success;\n}\n\nint\nXSetWindowBackground(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned long))\n{\n    return Success;\n}\n\nint\nXSetWindowBackgroundPixmap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Pixmap))\n{\n    return Success;\n}\n\nint\nXSetWindowBorder(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned long))\n{\n    return Success;\n}\n\nint\nXSetWindowBorderPixmap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Pixmap))\n{\n    return Success;\n}\n\nint\nXSetWindowBorderWidth(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(unsigned int))\n{\n    return Success;\n}\n\nint\nXSetWindowColormap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Colormap))\n{\n    return Success;\n}\n\nBool\nXTranslateCoordinates(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(Window *))\n{\n    return 0;\n}\n\nint\nXWindowEvent(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(long),\n    TCL_UNUSED(XEvent *))\n{\n    return Success;\n}\n\nint\nXWithdrawWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int))\n{\n    return Success;\n}\n\nint\nXmbLookupString(\n    TCL_UNUSED(XIC),\n    TCL_UNUSED(XKeyPressedEvent *),\n    TCL_UNUSED(char *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(KeySym *),\n    TCL_UNUSED(Status *))\n{\n    return Success;\n}\n\f\nint\nXGetWindowProperty(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Atom),\n    TCL_UNUSED(long),\n    TCL_UNUSED(long),\n    TCL_UNUSED(Bool),\n    TCL_UNUSED(Atom),\n    Atom *actual_type_return,\n    int *actual_format_return,\n    unsigned long *nitems_return,\n    unsigned long *bytes_after_return,\n    unsigned char **prop_return)\n{\n    *actual_type_return = None;\n    *actual_format_return = 0;\n    *nitems_return = 0;\n    *bytes_after_return = 0;\n    *prop_return = NULL;\n    return BadValue;\n}\n\n/*\n * The following functions were implemented as macros under Windows.\n */\n\nint\nXFlush(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\nint\nXGrabServer(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\nint\nXUngrabServer(\n    TCL_UNUSED(Display *))\n{\n    return 0;\n}\n\nint\nXFree(\n    void *data)\n{\n\tif (data != NULL) {\n\t\tTcl_Free(data);\n\t}\n    return 0;\n}\n\nint\nXNoOp(\n    Display *display)\n{\n    LastKnownRequestProcessed(display)++;\n    return 0;\n}\n\nXAfterFunction\nXSynchronize(\n    Display *display,\n    TCL_UNUSED(Bool))\n{\n    LastKnownRequestProcessed(display)++;\n    return NULL;\n}\n\nint\nXSync(\n    Display *display,\n    TCL_UNUSED(Bool))\n{\n    LastKnownRequestProcessed(display)++;\n    return 0;\n}\n\nVisualID\nXVisualIDFromVisual(\n    Visual *visual)\n{\n    return visual->visualid;\n}\n"
  },
  {
    "path": "win/svnmanifest.in",
    "content": "svn-r"
  },
  {
    "path": "win/targets.vc",
    "content": "#------------------------------------------------------------- -*- makefile -*-\r\n# targets.vc --\r\n#\r\n# Part of the nmake based build system for Tcl and its extensions.\r\n# This file defines some standard targets for the convenience of extensions\r\n# and can be optionally included by the extension makefile.\r\n# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs.\r\n\r\n$(PROJECT): setup pkgindex $(PRJLIB)\r\n\r\n!ifdef PRJ_STUBOBJS\r\n$(PROJECT): $(PRJSTUBLIB)\r\n$(PRJSTUBLIB): $(PRJ_STUBOBJS)\r\n\t$(LIBCMD) $**\r\n\r\n$(PRJ_STUBOBJS):\r\n\t$(CCSTUBSCMD) %s\r\n!endif # PRJ_STUBOBJS\r\n\r\n!ifdef PRJ_MANIFEST\r\n$(PROJECT): $(PRJLIB).manifest\r\n$(PRJLIB).manifest: $(PRJ_MANIFEST)\r\n\t@nmakehlp -s << $** >$@\r\n@MACHINE@\t  $(MACHINE:IX86=X86)\r\n<<\r\n!endif\r\n\r\n!if \"$(PROJECT)\" != \"tcl\" && \"$(PROJECT)\" != \"tk\"\r\n$(PRJLIB): $(PRJ_OBJS) $(RESFILE)\r\n!if $(STATIC_BUILD)\r\n       $(LIBCMD) $**\r\n!else\r\n       $(DLLCMD) $**\r\n       $(_VC_MANIFEST_EMBED_DLL)\r\n!endif\r\n       -@del $*.exp\r\n!endif\r\n\r\n!if \"$(PRJ_HEADERS)\" != \"\" && \"$(PRJ_OBJS)\" != \"\"\r\n$(PRJ_OBJS): $(PRJ_HEADERS)\r\n!endif\r\n\r\n# If parent makefile has defined stub objects, add their installation\r\n# to the default install\r\n!if \"$(PRJ_STUBOBJS)\" != \"\"\r\ndefault-install: default-install-stubs\r\n!endif\r\n\r\n# Unlike the other default targets, these cannot be in rules.vc because\r\n# the executed command depends on existence of macro PRJ_HEADERS_PUBLIC\r\n# that the parent makefile will not define until after including rules-ext.vc\r\n!if \"$(PRJ_HEADERS_PUBLIC)\" != \"\"\r\ndefault-install: default-install-headers\r\ndefault-install-headers:\r\n\t@echo Installing headers to '$(INCLUDE_INSTALL_DIR)'\r\n\t@if not exist \"$(INCLUDE_INSTALL_DIR)\" $(MKDIR) \"$(INCLUDE_INSTALL_DIR)\"\r\n\t@for %f in ($(PRJ_HEADERS_PUBLIC)) do @$(COPY) %f \"$(INCLUDE_INSTALL_DIR)\"\r\n!endif\r\n\r\n!if \"$(DISABLE_STANDARD_TARGETS)\" == \"\"\r\nDISABLE_STANDARD_TARGETS = 0\r\n!endif\r\n\r\n!if \"$(DISABLE_TARGET_setup)\" == \"\"\r\nDISABLE_TARGET_setup = 0\r\n!endif\r\n!if \"$(DISABLE_TARGET_install)\" == \"\"\r\nDISABLE_TARGET_install = 0\r\n!endif\r\n!if \"$(DISABLE_TARGET_clean)\" == \"\"\r\nDISABLE_TARGET_clean = 0\r\n!endif\r\n!if \"$(DISABLE_TARGET_test)\" == \"\"\r\nDISABLE_TARGET_test = 0\r\n!endif\r\n!if \"$(DISABLE_TARGET_shell)\" == \"\"\r\nDISABLE_TARGET_shell = 0\r\n!endif\r\n\r\n!if !$(DISABLE_STANDARD_TARGETS)\r\n!if !$(DISABLE_TARGET_setup)\r\nsetup: default-setup\r\n!endif\r\n!if !$(DISABLE_TARGET_install)\r\ninstall: default-install\r\n!endif\r\n!if !$(DISABLE_TARGET_clean)\r\nclean: default-clean\r\nrealclean: hose\r\nhose: default-hose\r\ndistclean: realclean default-distclean\r\n!endif\r\n!if !$(DISABLE_TARGET_test)\r\ntest: default-test\r\n!endif\r\n!if !$(DISABLE_TARGET_shell)\r\nshell: default-shell\r\n!endif\r\n!endif # DISABLE_STANDARD_TARGETS\r\n"
  },
  {
    "path": "win/tcl.m4",
    "content": "#------------------------------------------------------------------------\n# SC_PATH_TCLCONFIG --\n#\n#\tLocate the tclConfig.sh file and perform a sanity check on\n#\tthe Tcl compile flags\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tcl=...\n#\n#\tDefines the following vars:\n#\t\tTCL_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tclConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PATH_TCLCONFIG], [\n    #\n    # Ok, lets find the tcl configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tcl\n    #\n\n    if test x\"${no_tcl}\" = x ; then\n\t# we reset no_tcl in case something fails here\n\tno_tcl=true\n\tAC_ARG_WITH(tcl,\n\t    AS_HELP_STRING([--with-tcl],\n\t\t[directory containing tcl configuration (tclConfig.sh)]),\n\t    [with_tclconfig=\"${withval}\"])\n\tAC_MSG_CHECKING([for Tcl configuration])\n\tAC_CACHE_VAL(ac_cv_c_tclconfig,[\n\n\t    # First check to see if --with-tcl was specified.\n\t    if test x\"${with_tclconfig}\" != x ; then\n\t\tcase \"${with_tclconfig}\" in\n\t\t    */tclConfig.sh )\n\t\t\tif test -f \"${with_tclconfig}\"; then\n\t\t\t    AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])\n\t\t\t    with_tclconfig=\"`echo \"${with_tclconfig}\" | sed 's!/tclConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tclconfig}/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd \"${with_tclconfig}\"; pwd)`\"\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tcl installation\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tcl \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tcl \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tcl \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i/win; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tclConfig.sh\" ; then\n\t\t\tac_cv_c_tclconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tcl \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tclConfig.sh\" ; then\n\t\t    ac_cv_c_tclconfig=\"`(cd $i/win; pwd)`\"\n\t\t    break\n\t\tfi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tclconfig}\" = x ; then\n\t    TCL_BIN_DIR=\"# no Tcl configs found\"\n\t    AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])\n\telse\n\t    no_tcl=\n\t    TCL_BIN_DIR=\"${ac_cv_c_tclconfig}\"\n\t    AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_PATH_TKCONFIG --\n#\n#\tLocate the tkConfig.sh file\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tk=...\n#\n#\tDefines the following vars:\n#\t\tTK_BIN_DIR\tFull path to the directory containing\n#\t\t\t\tthe tkConfig.sh file\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PATH_TKCONFIG], [\n    #\n    # Ok, lets find the tk configuration\n    # First, look for one uninstalled.\n    # the alternative search directory is invoked by --with-tk\n    #\n\n    if test x\"${no_tk}\" = x ; then\n\t# we reset no_tk in case something fails here\n\tno_tk=true\n\tAC_ARG_WITH(tk,\n\t    AS_HELP_STRING([--with-tk],\n\t\t[directory containing tk configuration (tkConfig.sh)]),\n\t    [with_tkconfig=\"${withval}\"])\n\tAC_MSG_CHECKING([for Tk configuration])\n\tAC_CACHE_VAL(ac_cv_c_tkconfig,[\n\n\t    # First check to see if --with-tkconfig was specified.\n\t    if test x\"${with_tkconfig}\" != x ; then\n\t\tcase \"${with_tkconfig}\" in\n\t\t    */tkConfig.sh )\n\t\t\tif test -f \"${with_tkconfig}\"; then\n\t\t\t    AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])\n\t\t\t    with_tkconfig=\"`echo \"${with_tkconfig}\" | sed 's!/tkConfig\\.sh$!!'`\"\n\t\t\tfi ;;\n\t\tesac\n\t\tif test -f \"${with_tkconfig}/tkConfig.sh\" ; then\n\t\t    ac_cv_c_tkconfig=\"`(cd \"${with_tkconfig}\"; pwd)`\"\n\t\telse\n\t\t    AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])\n\t\tfi\n\t    fi\n\n\t    # then check for a private Tk library\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t../tk \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../tk \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t../../../tk \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i/win; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few common install locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in `ls -d ${libdir} 2>/dev/null` \\\n\t\t\t`ls -d ${exec_prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d ${prefix}/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Tcl/lib 2>/dev/null` \\\n\t\t\t`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \\\n\t\t\t; do\n\t\t    if test -f \"$i/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\n\t    # check in a few other private locations\n\t    if test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t\tfor i in \\\n\t\t\t${srcdir}/../tk \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \\\n\t\t\t`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do\n\t\t    if test -f \"$i/win/tkConfig.sh\" ; then\n\t\t\tac_cv_c_tkconfig=\"`(cd $i/win; pwd)`\"\n\t\t\tbreak\n\t\t    fi\n\t\tdone\n\t    fi\n\t])\n\n\tif test x\"${ac_cv_c_tkconfig}\" = x ; then\n\t    TK_BIN_DIR=\"# no Tk configs found\"\n\t    AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])\n\telse\n\t    no_tk=\n\t    TK_BIN_DIR=\"${ac_cv_c_tkconfig}\"\n\t    AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])\n\tfi\n    fi\n])\n\n#------------------------------------------------------------------------\n# SC_LOAD_TCLCONFIG --\n#\n#\tLoad the tclConfig.sh file.\n#\n# Arguments:\n#\n#\tRequires the following vars to be set:\n#\t\tTCL_BIN_DIR\n#\n# Results:\n#\n#\tSubstitutes the following vars:\n#\t\tTCL_BIN_DIR\n#\t\tTCL_SRC_DIR\n#\t\tTCL_LIB_FILE\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_LOAD_TCLCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])\n\n    if test -f \"${TCL_BIN_DIR}/tclConfig.sh\" ; then\n\tAC_MSG_RESULT([loading])\n\t. \"${TCL_BIN_DIR}/tclConfig.sh\"\n    else\n\tAC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])\n    fi\n\n    #\n    # If the TCL_BIN_DIR is the build directory (not the install directory),\n    # then set the common variable name to the value of the build variables.\n    # For example, the variable TCL_LIB_SPEC will be set to the value\n    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC\n    # instead of TCL_BUILD_LIB_SPEC since it will work with both an\n    # installed and uninstalled version of Tcl.\n    #\n\n    if test -f $TCL_BIN_DIR/Makefile ; then\n\tTCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}\n\tTCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}\n\tTCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}\n    fi\n\n    eval \"TCL_STUB_LIB_FILE=\\\"${TCL_STUB_LIB_FILE}\\\"\"\n    eval \"TCL_STUB_LIB_FLAG=\\\"${TCL_STUB_LIB_FLAG}\\\"\"\n    eval \"TCL_STUB_LIB_SPEC=\\\"${TCL_STUB_LIB_SPEC}\\\"\"\n\n    AC_SUBST(TCL_VERSION)\n    AC_SUBST(TCL_BIN_DIR)\n    AC_SUBST(TCL_SRC_DIR)\n\n    AC_SUBST(TCL_LIB_FILE)\n    AC_SUBST(TCL_LIB_FLAG)\n    AC_SUBST(TCL_LIB_SPEC)\n\n    AC_SUBST(TCL_STUB_LIB_FILE)\n    AC_SUBST(TCL_STUB_LIB_FLAG)\n    AC_SUBST(TCL_STUB_LIB_SPEC)\n\n    AC_SUBST(TCL_DEFS)\n])\n\n#------------------------------------------------------------------------\n# SC_LOAD_TKCONFIG --\n#\n#\tLoad the tkConfig.sh file\n#\n# Arguments:\n#\n#\tRequires the following vars to be set:\n#\t\tTK_BIN_DIR\n#\n# Results:\n#\n#\tSets the following vars that should be in tkConfig.sh:\n#\t\tTK_BIN_DIR\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_LOAD_TKCONFIG], [\n    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])\n\n    if test -f \"${TK_BIN_DIR}/tkConfig.sh\" ; then\n\tAC_MSG_RESULT([loading])\n\t. \"${TK_BIN_DIR}/tkConfig.sh\"\n    else\n\tAC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])\n    fi\n\n\n    AC_SUBST(TK_BIN_DIR)\n    AC_SUBST(TK_SRC_DIR)\n    AC_SUBST(TK_LIB_FILE)\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_SHARED --\n#\n#\tAllows the building of shared libraries\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-shared=yes|no\n#\n#\tDefines the following vars:\n#\t\tSTATIC_BUILD\tUsed for building import/export libraries\n#\t\t\t\ton Windows.\n#\n#\tSets the following vars:\n#\t\tSHARED_BUILD\tValue of 1 or 0\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_SHARED], [\n    AC_MSG_CHECKING([how to build libraries])\n    AC_ARG_ENABLE(shared,\n\t[  --enable-shared         build and link with shared libraries (default: on)],\n\t[tcl_ok=$enableval], [tcl_ok=yes])\n    if test \"$tcl_ok\" = \"yes\" ; then\n\tAC_MSG_RESULT([shared])\n\tSHARED_BUILD=1\n    else\n\tAC_MSG_RESULT([static])\n\tSHARED_BUILD=0\n\tAC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])\n    fi\n    AC_SUBST(SHARED_BUILD)\n])\n\n#------------------------------------------------------------------------\n# SC_ENABLE_SYMBOLS --\n#\n#\tSpecify if debugging symbols should be used.\n#\tMemory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging\n#\tcan also be enabled.\n#\n# Arguments:\n#\tnone\n#\n#\tRequires the following vars to be set in the Makefile:\n#\t\tCFLAGS_DEBUG\n#\t\tCFLAGS_OPTIMIZE\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--enable-symbols\n#\n#\tDefines the following vars:\n#\t\tCFLAGS_DEFAULT\tSets to $(CFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(CFLAGS_OPTIMIZE) if false\n#\t\tLDFLAGS_DEFAULT\tSets to $(LDFLAGS_DEBUG) if true\n#\t\t\t\tSets to $(LDFLAGS_OPTIMIZE) if false\n#\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ENABLE_SYMBOLS], [\n    AC_MSG_CHECKING([for build with symbols])\n    AC_ARG_ENABLE(symbols, [  --enable-symbols        build with debugging symbols (default: off)],    [tcl_ok=$enableval], [tcl_ok=no])\n# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.\n    if test \"$tcl_ok\" = \"no\"; then\n\tCFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'\n\tAC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])\n\tAC_MSG_RESULT([no])\n\n\tAC_DEFINE(TCL_CFG_OPTIMIZED)\n    else\n\tCFLAGS_DEFAULT='$(CFLAGS_DEBUG)'\n\tLDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'\n\tif test \"$tcl_ok\" = \"yes\"; then\n\t    AC_MSG_RESULT([yes (standard debugging)])\n\tfi\n    fi\n    AC_SUBST(CFLAGS_DEFAULT)\n    AC_SUBST(LDFLAGS_DEFAULT)\n\n    if test \"$tcl_ok\" = \"mem\" -o \"$tcl_ok\" = \"all\"; then\n\tAC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])\n    fi\n\n    if test \"$tcl_ok\" = \"compile\" -o \"$tcl_ok\" = \"all\"; then\n\tAC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])\n\tAC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])\n    fi\n\n    if test \"$tcl_ok\" != \"yes\" -a \"$tcl_ok\" != \"no\"; then\n\tif test \"$tcl_ok\" = \"all\"; then\n\t    AC_MSG_RESULT([enabled symbols mem compile debugging])\n\telse\n\t    AC_MSG_RESULT([enabled $tcl_ok debugging])\n\tfi\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_CONFIG_CFLAGS\n#\n#\tTry to determine the proper flags to pass to the compiler\n#\tfor building shared libraries and other such nonsense.\n#\n#\tNOTE: The backslashes in quotes below are substituted twice\n#\tdue to the fact that they are in a macro and then inlined\n#\tin the final configure script.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tCan the following vars:\n#\t\tEXTRA_CFLAGS\n#\t\tCFLAGS_DEBUG\n#\t\tCFLAGS_OPTIMIZE\n#\t\tCFLAGS_WARNING\n#\t\tCFLAGS_NOLTO\n#\t\tLDFLAGS_DEBUG\n#\t\tLDFLAGS_OPTIMIZE\n#\t\tLDFLAGS_CONSOLE\n#\t\tLDFLAGS_WINDOW\n#\t\tCC_OBJNAME\n#\t\tCC_EXENAME\n#\t\tCYGPATH\n#\t\tSTLIB_LD\n#\t\tSHLIB_LD\n#\t\tSHLIB_LD_LIBS\n#\t\tLIBS\n#\t\tAR\n#\t\tRC\n#\t\tRES\n#\n#\t\tMAKE_LIB\n#\t\tMAKE_STUB_LIB\n#\t\tMAKE_EXE\n#\t\tMAKE_DLL\n#\n#\t\tLIBSUFFIX\n#\t\tLIBFLAGSUFFIX\n#\t\tLIBPREFIX\n#\t\tLIBRARIES\n#\t\tEXESUFFIX\n#\t\tDLLSUFFIX\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_CONFIG_CFLAGS], [\n\n    # Step 0: Enable 64 bit support?\n\n    AC_MSG_CHECKING([if 64bit support is requested])\n    AC_ARG_ENABLE(64bit,[  --enable-64bit          enable 64bit support (where applicable)], [do64bit=$enableval], [do64bit=no])\n    AC_MSG_RESULT($do64bit)\n\n    # Set some defaults (may get changed below)\n    EXTRA_CFLAGS=\"\"\n\tAC_DEFINE(MODULE_SCOPE, [extern], [No need to mark inidividual symbols as hidden])\n\n    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)\n    AC_CHECK_PROG(WINE, wine, wine,)\n\n    SHLIB_SUFFIX=\".dll\"\n\n    # MACHINE is IX86 for LINK, but this is used by the manifest,\n    # which requires x86|amd64|arm64|ia64.\n    MACHINE=\"X86\"\n\n    if test \"$GCC\" = \"yes\"; then\n\n      AC_CACHE_CHECK(for cross-compile version of gcc,\n\tac_cv_cross,\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t    #ifndef _WIN32\n\t\t#error cross-compiler\n\t    #endif\n\t]], [[]])],\n\t[ac_cv_cross=no],\n\t[ac_cv_cross=yes])\n      )\n\n      if test \"$ac_cv_cross\" = \"yes\"; then\n\tcase \"$do64bit\" in\n\t    amd64|x64|yes)\n\t\tCC=\"x86_64-w64-mingw32-${CC}\"\n\t\tLD=\"x86_64-w64-mingw32-ld\"\n\t\tAR=\"x86_64-w64-mingw32-ar\"\n\t\tRANLIB=\"x86_64-w64-mingw32-ranlib\"\n\t\tRC=\"x86_64-w64-mingw32-windres\"\n\t    ;;\n\t    arm64|aarch64)\n\t\tCC=\"aarch64-w64-mingw32-${CC}\"\n\t\tLD=\"aarch64-w64-mingw32-ld\"\n\t\tAR=\"aarch64-w64-mingw32-ar\"\n\t\tRANLIB=\"aarch64-w64-mingw32-ranlib\"\n\t\tRC=\"aarch64-w64-mingw32-windres\"\n\t    ;;\n\t    *)\n\t\tCC=\"i686-w64-mingw32-${CC}\"\n\t\tLD=\"i686-w64-mingw32-ld\"\n\t\tAR=\"i686-w64-mingw32-ar\"\n\t\tRANLIB=\"i686-w64-mingw32-ranlib\"\n\t\tRC=\"i686-w64-mingw32-windres\"\n\t    ;;\n\tesac\n      fi\n    fi\n\n    # Check for a bug in gcc's windres that causes the\n    # compile to fail when a Windows native path is\n    # passed into windres. The mingw toolchain requires\n    # Windows native paths while Cygwin should work\n    # with both. Avoid the bug by passing a POSIX\n    # path when using the Cygwin toolchain.\n\n    if test \"$GCC\" = \"yes\" && test \"$CYGPATH\" != \"echo\" ; then\n\tconftest=/tmp/conftest.rc\n\techo \"STRINGTABLE BEGIN\" > $conftest\n\techo \"101 \\\"name\\\"\" >> $conftest\n\techo \"END\" >> $conftest\n\n\tAC_MSG_CHECKING([for Windows native path bug in windres])\n\tcyg_conftest=`$CYGPATH $conftest`\n\tif AC_TRY_COMMAND($RC -o conftest.res.o $cyg_conftest) ; then\n\t    AC_MSG_RESULT([no])\n\telse\n\t    AC_MSG_RESULT([yes])\n\t    CYGPATH=echo\n\tfi\n\tconftest=\n\tcyg_conftest=\n    fi\n\n    if test \"$CYGPATH\" = \"echo\"; then\n\tDEPARG='\"$<\"'\n    else\n\tDEPARG='\"$(shell $(CYGPATH) $<)\"'\n    fi\n\n    # set various compiler flags depending on whether we are using gcc or cl\n\n    if test \"${GCC}\" = \"yes\" ; then\n\textra_cflags=\"-pipe\"\n\textra_ldflags=\"-pipe -static-libgcc -municode\"\n\tAC_CACHE_CHECK(for mingw32 version of gcc,\n\t    ac_cv_win32,\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t#ifdef _WIN32\n\t\t    #error win32\n\t\t#endif\n\t    ]], [[]])],\n\t    [ac_cv_win32=no],\n\t    [ac_cv_win32=yes])\n\t)\n\tif test \"$ac_cv_win32\" != \"yes\"; then\n\t    AC_MSG_ERROR([${CC} cannot produce win32 executables.])\n\tfi\n\tif test \"$do64bit\" != \"arm64\" -a \"$do64bit\" != \"aarch64\"; then\n\t    extra_cflags=\"$extra_cflags -DHAVE_CPUID=1\"\n\tfi\n\n\thold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -fno-lto\"\n\tAC_CACHE_CHECK(for working -fno-lto,\n\t    ac_cv_nolto,\n\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],\n\t    [ac_cv_nolto=yes],\n\t    [ac_cv_nolto=no])\n\t)\n\tCFLAGS=$hold_cflags\n\tif test \"$ac_cv_nolto\" = \"yes\" ; then\n\t    CFLAGS_NOLTO=\"-fno-lto\"\n\telse\n\t    CFLAGS_NOLTO=\"\"\n\tfi\n\n\tAC_CACHE_CHECK([if the linker understands --disable-high-entropy-va],\n\t    tcl_cv_ld_high_entropy, [\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS  -Wl,--disable-high-entropy-va\"\n\t    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_ld_high_entropy=yes],[tcl_cv_ld_high_entropy=no])\n\t    CFLAGS=$hold_cflags])\n\tif test $tcl_cv_ld_high_entropy = yes; then\n\t    extra_ldflags=\"$extra_ldflags -Wl,--disable-high-entropy-va\"\n\tfi\n\n\tAC_CACHE_CHECK([if the compiler understands -finput-charset],\n\t    tcl_cv_cc_input_charset, [\n\t    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -finput-charset=UTF-8\"\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_input_charset=yes],[tcl_cv_cc_input_charset=no])\n\t    CFLAGS=$hold_cflags])\n\tif test $tcl_cv_cc_input_charset = yes; then\n\t    extra_cflags=\"$extra_cflags -finput-charset=UTF-8\"\n\tfi\n    fi\n\n    hold_cflags=$CFLAGS; CFLAGS=\"$CFLAGS -Wl,--enable-auto-image-base\"\n    AC_CACHE_CHECK(for working --enable-auto-image-base,\n\tac_cv_enable_auto_image_base,\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([])],\n\t[ac_cv_enable_auto_image_base=yes],\n\t[ac_cv_enable_auto_image_base=no])\n    )\n    CFLAGS=$hold_cflags\n    if test \"$ac_cv_enable_auto_image_base\" = \"yes\" ; then\n\textra_ldflags=\"$extra_ldflags -Wl,--enable-auto-image-base\"\n    fi\n\n    AC_MSG_CHECKING([compiler flags])\n    if test \"${GCC}\" = \"yes\" ; then\n\tSHLIB_LD=\"\"\n\tSHLIB_LD_LIBS='${LIBS}'\n\tLIBS=\"-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32\"\n\t# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't\n\tLIBS_GUI=\"-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -loleacc -lole32 -loleaut32 -lwinspool -luxtheme -lusp10\"\n\tSTLIB_LD='${AR} cr'\n\tRC_OUT=-o\n\tRC_TYPE=\n\tRC_INCLUDE=--include\n\tRC_DEFINE=--define\n\tRES=res.o\n\tMAKE_LIB=\"\\${STLIB_LD} \\[$]@\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} \\[$]@\"\n\tPOST_MAKE_LIB=\"\\${RANLIB} \\[$]@\"\n\tMAKE_EXE=\"\\${CC} -o \\[$]@\"\n\tLIBPREFIX=\"lib\"\n\n\tif test \"${SHARED_BUILD}\" = \"0\" ; then\n\t    # static\n\t    AC_MSG_RESULT([using static flags])\n\t    runtime=\n\t    LIBRARIES=\"\\${STATIC_LIBRARIES}\"\n\t    EXESUFFIX=\"s.exe\"\n\telse\n\t    # dynamic\n\t    AC_MSG_RESULT([using shared flags])\n\n\t    # ad-hoc check to see if CC supports -shared.\n\t    if \"${CC}\" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then\n\t\tAC_MSG_ERROR([${CC} does not support the -shared option.\n\t\tYou will need to upgrade to a newer version of the toolchain.])\n\t    fi\n\n\t    runtime=\n\t    # Add SHLIB_LD_LIBS to the Make rule, not here.\n\n\t    EXESUFFIX=\".exe\"\n\t    LIBRARIES=\"\\${SHARED_LIBRARIES}\"\n\tfi\n\t# Link with gcc since ld does not link to default libs like\n\t# -luser32 and -lmsvcrt by default.\n\tSHLIB_LD='${CC} -shared'\n\tSHLIB_LD_LIBS='${LIBS}'\n\tMAKE_DLL=\"\\${SHLIB_LD} \\$(LDFLAGS) -o \\[$]@ ${extra_ldflags} \\\n\t    -Wl,--out-implib,\\$(patsubst %.dll,lib%.dll.a,\\[$]@)\"\n\t# DLLSUFFIX is separate because it is the building block for\n\t# users of tclConfig.sh that may build shared or static.\n\tDLLSUFFIX=\".dll\"\n\tLIBSUFFIX=\".a\"\n\tLIBFLAGSUFFIX=\"\"\n\tSHLIB_SUFFIX=.dll\n\n\tEXTRA_CFLAGS=\"${extra_cflags}\"\n\n\tCFLAGS_DEBUG=-g\n\tCFLAGS_OPTIMIZE=\"-O2 -fomit-frame-pointer\"\n\tCFLAGS_WARNING=\"-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith\"\n\tLDFLAGS_DEBUG=\n\tLDFLAGS_OPTIMIZE=\n\n\tcase \"${CC}\" in\n\t    *++)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wno-format\"\n\t\t;;\n\t    *)\n\t\tCFLAGS_WARNING=\"${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers\"\n\t\t;;\n\tesac\n\n\t# Specify the CC output file names based on the target name\n\tCC_OBJNAME=\"-o \\[$]@\"\n\tCC_EXENAME=\"-o \\[$]@\"\n\n\t# Specify linker flags depending on the type of app being\n\t# built -- Console vs. Window.\n\t#\n\t# ORIGINAL COMMENT:\n\t# We need to pass -e _WinMain@16 so that ld will use\n\t# WinMain() instead of main() as the entry point. We can't\n\t# use autoconf to check for this case since it would need\n\t# to run an executable and that does not work when\n\t# cross compiling. Remove this -e workaround once we\n\t# require a gcc that does not have this bug.\n\t#\n\t# MK NOTE: Tk should use a different mechanism. This causes\n\t# interesting problems, such as wish dying at startup.\n\t#LDFLAGS_WINDOW=\"-mwindows -e _WinMain@16 ${extra_ldflags}\"\n\tLDFLAGS_CONSOLE=\"-mconsole ${extra_ldflags}\"\n\tLDFLAGS_WINDOW=\"-mwindows ${extra_ldflags}\"\n\n\tcase \"$do64bit\" in\n\t    amd64|x64|yes)\n\t\tMACHINE=\"AMD64\" ; # assume AMD64 as default 64-bit build\n\t\tAC_MSG_RESULT([   Using 64-bit $MACHINE mode])\n\t\t;;\n\t    arm64|aarch64)\n\t\tMACHINE=\"ARM64\"\n\t\tAC_MSG_RESULT([   Using ARM64 $MACHINE mode])\n\t\t;;\n\t    ia64)\n\t\tMACHINE=\"IA64\"\n\t\tAC_MSG_RESULT([   Using IA64 $MACHINE mode])\n\t\t;;\n\t    *)\n\t\tAC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n\t\t    #ifndef _WIN64\n\t\t\t#error 32-bit\n\t\t    #endif\n\t\t]], [[]])],\n\t\t\t[tcl_win_64bit=yes],\n\t\t\t[tcl_win_64bit=no]\n\t\t)\n\t\tif test \"$tcl_win_64bit\" = \"yes\" ; then\n\t\t    do64bit=amd64\n\t\t    MACHINE=\"AMD64\"\n\t\t    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])\n\t\tfi\n\t\t;;\n\tesac\n    else\n\tif test \"${SHARED_BUILD}\" = \"0\" ; then\n\t    # static\n\t    AC_MSG_RESULT([using static flags])\n\t    runtime=-MT\n\t    LIBRARIES=\"\\${STATIC_LIBRARIES}\"\n\t    EXESUFFIX=\"s.exe\"\n\telse\n\t    # dynamic\n\t    AC_MSG_RESULT([using shared flags])\n\t    runtime=-MD\n\t    # Add SHLIB_LD_LIBS to the Make rule, not here.\n\t    LIBRARIES=\"\\${SHARED_LIBRARIES}\"\n\t    EXESUFFIX=\".exe\"\n\t    case \"x`echo \\${VisualStudioVersion}`\" in\n\t\tx1[[4-9]]*)\n\t\t    lflags=\"${lflags} -nodefaultlib:ucrt.lib\"\n\t\t    ;;\n\t\t*)\n\t\t    ;;\n\t    esac\n\tfi\n\tMAKE_DLL=\"\\${SHLIB_LD} \\$(LDFLAGS) -out:\\[$]@\"\n\t# DLLSUFFIX is separate because it is the building block for\n\t# users of tclConfig.sh that may build shared or static.\n\tDLLSUFFIX=\".dll\"\n\tLIBSUFFIX=\".lib\"\n\tLIBFLAGSUFFIX=\"\"\n\n\tif test \"$do64bit\" != \"no\" ; then\n\t    case \"$do64bit\" in\n\t\tamd64|x64|yes)\n\t\t    MACHINE=\"AMD64\" ; # assume AMD64 as default 64-bit build\n\t\t    ;;\n\t\tarm64|aarch64)\n\t\t    MACHINE=\"ARM64\"\n\t\t    ;;\n\t\tia64)\n\t\t    MACHINE=\"IA64\"\n\t\t    ;;\n\t    esac\n\t    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])\n\tfi\n\n\tLIBS=\"netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib\"\n\n\tcase \"x`echo \\${VisualStudioVersion}`\" in\n\t\tx1[[4-9]]*)\n\t\t    LIBS=\"$LIBS ucrt.lib\"\n\t\t    ;;\n\t\t*)\n\t\t    ;;\n\tesac\n\n\tif test \"$do64bit\" != \"no\" ; then\n\t    RC=\"rc\"\n\t    CFLAGS_DEBUG=\"-nologo -Zi -Od ${runtime}d\"\n\t    CFLAGS_OPTIMIZE=\"-nologo -O2 ${runtime}\"\n\t    lflags=\"${lflags} -nologo -MACHINE:${MACHINE}\"\n\t    LINKBIN=\"link\"\n\t    # Avoid 'unresolved external symbol __security_cookie' errors.\n\t    # c.f. http://support.microsoft.com/?id=894573\n\t    LIBS=\"$LIBS bufferoverflowU.lib\"\n\telse\n\t    RC=\"rc\"\n\t    # -Od - no optimization\n\t    # -WX - warnings as errors\n\t    CFLAGS_DEBUG=\"-nologo -Z7 -Od -WX ${runtime}d\"\n\t    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)\n\t    CFLAGS_OPTIMIZE=\"-nologo -O2 ${runtime}\"\n\t    lflags=\"${lflags} -nologo\"\n\t    LINKBIN=\"link\"\n\tfi\n\n\tLIBS_GUI=\"gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib uxtheme.lib oleacc.lib ole32.lib usp10.lib\"\n\n\tSHLIB_LD=\"${LINKBIN} -dll -incremental:no ${lflags}\"\n\tSHLIB_LD_LIBS='${LIBS}'\n\t# link -lib only works when -lib is the first arg\n\tSTLIB_LD=\"${LINKBIN} -lib ${lflags}\"\n\tRC_OUT=-fo\n\tRC_TYPE=-r\n\tRC_INCLUDE=-i\n\tRC_DEFINE=-d\n\tRES=res\n\tMAKE_LIB=\"\\${STLIB_LD} -out:\\[$]@\"\n\tMAKE_STUB_LIB=\"\\${STLIB_LD} -nodefaultlib -out:\\[$]@\"\n\tPOST_MAKE_LIB=\n\tMAKE_EXE=\"\\${CC} -Fe\\[$]@\"\n\tLIBPREFIX=\"\"\n\n\tCFLAGS_DEBUG=\"${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE\"\n\tCFLAGS_OPTIMIZE=\"${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE\"\n\n\tEXTRA_CFLAGS=\"\"\n\tCFLAGS_WARNING=\"-W3\"\n\tLDFLAGS_DEBUG=\"-debug\"\n\tLDFLAGS_OPTIMIZE=\"-release\"\n\n\t# Specify the CC output file names based on the target name\n\tCC_OBJNAME=\"-Fo\\[$]@\"\n\tCC_EXENAME=\"-Fe\\\"\\$(shell \\$(CYGPATH) '\\[$]@')\\\"\"\n\n\t# Specify linker flags depending on the type of app being\n\t# built -- Console vs. Window.\n\tif test \"${TARGETCPU}\" != \"X86\"; then\n\t    LDFLAGS_CONSOLE=\"-link ${lflags}\"\n\t    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}\n\telse\n\t    LDFLAGS_CONSOLE=\"-link -subsystem:console ${lflags}\"\n\t    LDFLAGS_WINDOW=\"-link -subsystem:windows ${lflags}\"\n\tfi\n    fi\n\n    if test \"$do64bit\" != \"no\" ; then\n\tAC_DEFINE(TCL_CFG_DO64BIT)\n    fi\n\n    if test \"${GCC}\" = \"yes\" ; then\n\tAC_CACHE_CHECK(for SEH support in compiler,\n\t    tcl_cv_seh,\n\tAC_RUN_IFELSE([AC_LANG_SOURCE([[\n\t    #define WIN32_LEAN_AND_MEAN\n\t    #include <windows.h>\n\t    #undef WIN32_LEAN_AND_MEAN\n\n\t    int main(int argc, char** argv) {\n\t\tint a, b = 0;\n\t\t__try {\n\t\t    a = 666 / b;\n\t\t}\n\t\t__except (EXCEPTION_EXECUTE_HANDLER) {\n\t\t    return 0;\n\t\t}\n\t\treturn 1;\n\t    }\n\t]])],\n\t    [tcl_cv_seh=yes],\n\t    [tcl_cv_seh=no],\n\t    [tcl_cv_seh=no])\n\t)\n\tif test \"$tcl_cv_seh\" = \"no\" ; then\n\t    AC_DEFINE(HAVE_NO_SEH, 1,\n\t\t    [Defined when mingw does not support SEH])\n\tfi\n\n\t#\n\t# Check to see if the excpt.h include file provided contains the\n\t# definition for EXCEPTION_DISPOSITION; if not, which is the case\n\t# with Cygwin's version as of 2002-04-10, define it to be int,\n\t# sufficient for getting the current code to work.\n\t#\n\tAC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,\n\t    tcl_cv_eh_disposition,\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n#\t    define WIN32_LEAN_AND_MEAN\n#\t    include <windows.h>\n#\t    undef WIN32_LEAN_AND_MEAN\n\t    ]], [[\n\t\tEXCEPTION_DISPOSITION x;\n\t    ]])],\n\t\t[tcl_cv_eh_disposition=yes],\n\t\t[tcl_cv_eh_disposition=no])\n\t)\n\tif test \"$tcl_cv_eh_disposition\" = \"no\" ; then\n\tAC_DEFINE(EXCEPTION_DISPOSITION, int,\n\t\t[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])\n\tfi\n\n\t# See if the compiler supports casting to a union type.\n\t# This is used to stop gcc from printing a compiler\n\t# warning when initializing a union member.\n\n\tAC_CACHE_CHECK(for cast to union support,\n\t    tcl_cv_cast_to_union,\n\t    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[\n\t\t  union foo { int i; double d; };\n\t\t  union foo f = (union foo) (int) 0;\n\t    ]])],\n\t    [tcl_cv_cast_to_union=yes],\n\t    [tcl_cv_cast_to_union=no])\n\t)\n\tif test \"$tcl_cv_cast_to_union\" = \"yes\"; then\n\t    AC_DEFINE(HAVE_CAST_TO_UNION, 1,\n\t\t    [Defined when compiler supports casting to union type.])\n\tfi\n    fi\n\n    # DL_LIBS is empty, but then we match the Unix version\n    AC_SUBST(DL_LIBS)\n    AC_SUBST(CFLAGS_DEBUG)\n    AC_SUBST(CFLAGS_OPTIMIZE)\n    AC_SUBST(CFLAGS_WARNING)\n    AC_SUBST(CFLAGS_NOLTO)\n])\n\n#------------------------------------------------------------------------\n# SC_WITH_TCL --\n#\n#\tLocation of the Tcl build directory.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\n#\tAdds the following arguments to configure:\n#\t\t--with-tcl=...\n#\n#\tDefines the following vars:\n#\t\tTCL_BIN_DIR\tFull path to the tcl build dir.\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_WITH_TCL], [\n    if test -d ../../tcl9.1$1/win;  then\n\tTCL_BIN_DEFAULT=../../tcl9.1$1/win\n    else\n\tTCL_BIN_DEFAULT=../../tcl9.1/win\n    fi\n\n    AC_ARG_WITH(tcl, [  --with-tcl=DIR          use Tcl 9.x binaries from DIR],\n\t    TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd $TCL_BIN_DEFAULT; pwd`)\n    if test ! -d $TCL_BIN_DIR; then\n\tAC_MSG_ERROR(Tcl directory $TCL_BIN_DIR does not exist)\n    fi\n    if test ! -f $TCL_BIN_DIR/Makefile; then\n\tAC_MSG_ERROR(There is no Makefile in $TCL_BIN_DIR:  perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?)\n    else\n\techo \"building against Tcl binaries in: $TCL_BIN_DIR\"\n    fi\n    AC_SUBST(TCL_BIN_DIR)\n])\n\n#------------------------------------------------------------------------\n# SC_PROG_TCLSH\n#\tLocate a tclsh shell installed on the system path. This macro\n#\twill only find a Tcl shell that already exists on the system.\n#\tIt will not find a Tcl shell in the Tcl build directory or\n#\ta Tcl shell that has been installed from the Tcl build directory.\n#\tIf a Tcl shell can't be located on the PATH, then TCLSH_PROG will\n#\tbe set to \"\". Extensions should take care not to create Makefile\n#\trules that are run by default and depend on TCLSH_PROG. An\n#\textension can't assume that an executable Tcl shell exists at\n#\tbuild time.\n#\n# Arguments\n#\tnone\n#\n# Results\n#\tSubstitutes the following values:\n#\t\tTCLSH_PROG\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_PROG_TCLSH], [\n    AC_MSG_CHECKING([for tclsh])\n\n    AC_CACHE_VAL(ac_cv_path_tclsh, [\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/tclsh[[8-9]]*.exe 2> /dev/null` \\\n\t\t    `ls -r $dir/tclsh* 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_tclsh\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_tclsh=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n    ])\n\n    if test -f \"$ac_cv_path_tclsh\" ; then\n\tTCLSH_PROG=\"$ac_cv_path_tclsh\"\n\tAC_MSG_RESULT($TCLSH_PROG)\n    else\n\t# It is not an error if an installed version of Tcl can't be located.\n\tTCLSH_PROG=\"\"\n\tAC_MSG_RESULT([No tclsh found on PATH])\n    fi\n    AC_SUBST(TCLSH_PROG)\n])\n\n#------------------------------------------------------------------------\n# SC_BUILD_TCLSH\n#\tDetermine the fully qualified path name of the tclsh executable\n#\tin the Tcl build directory. This macro will correctly determine\n#\tthe name of the tclsh executable even if tclsh has not yet\n#\tbeen built in the build directory. The build tclsh must be used\n#\twhen running tests from an extension build directory. It is not\n#\tcorrect to use the TCLSH_PROG in cases like this.\n#\n# Arguments\n#\tnone\n#\n# Results\n#\tSubstitutes the following values:\n#\t\tBUILD_TCLSH\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_BUILD_TCLSH], [\n    AC_MSG_CHECKING([for tclsh in Tcl build directory])\n    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}\\${EXESUFFIX}\n    AC_MSG_RESULT($BUILD_TCLSH)\n    AC_SUBST(BUILD_TCLSH)\n])\n\n#--------------------------------------------------------------------\n# SC_TCL_CFG_ENCODING\tTIP #59\n#\n#\tDeclare the encoding to use for embedded configuration information.\n#\n# Arguments:\n#\tNone.\n#\n# Results:\n#\tMight append to the following vars:\n#\t\tDEFS\t(implicit)\n#\n#\tWill define the following vars:\n#\t\tTCL_CFGVAL_ENCODING\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_TCL_CFG_ENCODING], [\n    AC_ARG_WITH(encoding, [  --with-encoding         encoding for configuration values], with_tcencoding=${withval})\n\n    if test x\"${with_tcencoding}\" != x ; then\n\tAC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,\"${with_tcencoding}\")\n    else\n\tAC_DEFINE(TCL_CFGVAL_ENCODING,\"utf-8\")\n    fi\n])\n\n#--------------------------------------------------------------------\n# SC_EMBED_MANIFEST\n#\n#\tFigure out if we can embed the manifest where necessary\n#\n# Arguments:\n#\tAn optional manifest to merge into DLL/EXE.\n#\n# Results:\n#\tWill define the following vars:\n#\t\tVC_MANIFEST_EMBED_DLL\n#\t\tVC_MANIFEST_EMBED_EXE\n#\n#--------------------------------------------------------------------\n\nAC_DEFUN([SC_EMBED_MANIFEST], [\n    AC_MSG_CHECKING(whether to embed manifest)\n    AC_ARG_ENABLE(embedded-manifest,\n\tAS_HELP_STRING([--enable-embedded-manifest],\n\t\t[embed manifest if possible (default: yes)]),\n\t[embed_ok=$enableval], [embed_ok=yes])\n\n    VC_MANIFEST_EMBED_DLL=\n    VC_MANIFEST_EMBED_EXE=\n    result=no\n    if test \"$embed_ok\" = \"yes\" -a \"${SHARED_BUILD}\" = \"1\" \\\n       -a \"$GCC\" != \"yes\" ; then\n\t# Add the magic to embed the manifest into the dll/exe\n\tAC_EGREP_CPP([manifest needed], [\n#if defined(_MSC_VER) && _MSC_VER >= 1400\nprint(\"manifest needed\")\n#endif\n\t], [\n\t# Could do a CHECK_PROG for mt, but should always be with MSVC8+\n\t# Could add 'if test -f' check, but manifest should be created\n\t# in this compiler case\n\t# Add in a manifest argument that may be specified\n\t# XXX Needs improvement so that the test for existence accounts\n\t# XXX for a provided (known) manifest\n\tVC_MANIFEST_EMBED_DLL=\"if test -f \\[$]@.manifest ; then mt.exe -nologo -manifest \\[$]@.manifest $1 -outputresource:\\[$]@\\;2 ; fi\"\n\tVC_MANIFEST_EMBED_EXE=\"if test -f \\[$]@.manifest ; then mt.exe -nologo -manifest \\[$]@.manifest $1 -outputresource:\\[$]@\\;1 ; fi\"\n\tresult=yes\n\tif test \"x$1\" != x ; then\n\t    result=\"yes ($1)\"\n\tfi\n\t])\n    fi\n    AC_MSG_RESULT([$result])\n    AC_SUBST(VC_MANIFEST_EMBED_DLL)\n    AC_SUBST(VC_MANIFEST_EMBED_EXE)\n])\n\n#------------------------------------------------------------------------\n# SC_CC_FOR_BUILD\n#\tFor cross compiles, locate a C compiler that can generate native binaries.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following vars:\n#\t\tCC_FOR_BUILD\n#\t\tEXEEXT_FOR_BUILD\n#------------------------------------------------------------------------\n\ndnl Get a default for CC_FOR_BUILD to put into Makefile.\nAC_DEFUN([AX_CC_FOR_BUILD],\n[# Put a plausible default for CC_FOR_BUILD in Makefile.\nif test -z \"$CC_FOR_BUILD\"; then\n  if test \"x$cross_compiling\" = \"xno\"; then\n    CC_FOR_BUILD='$(CC)'\n  else\n    AC_MSG_CHECKING([for gcc])\n    AC_CACHE_VAL(ac_cv_path_cc, [\n\tsearch_path=`echo ${PATH} | sed -e 's/:/ /g'`\n\tfor dir in $search_path ; do\n\t    for j in `ls -r $dir/gcc 2> /dev/null` \\\n\t\t    `ls -r $dir/gcc 2> /dev/null` ; do\n\t\tif test x\"$ac_cv_path_cc\" = x ; then\n\t\t    if test -f \"$j\" ; then\n\t\t\tac_cv_path_cc=$j\n\t\t\tbreak\n\t\t    fi\n\t\tfi\n\t    done\n\tdone\n    ])\n  fi\nfi\nAC_SUBST(CC_FOR_BUILD)\n# Also set EXEEXT_FOR_BUILD.\nif test \"x$cross_compiling\" = \"xno\"; then\n  EXEEXT_FOR_BUILD='$(EXEEXT)'\n  OBJEXT_FOR_BUILD='$(OBJEXT)'\nelse\n  OBJEXT_FOR_BUILD='.no'\n  AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,\n    [rm -f conftest*\n     echo 'int main () { return 0; }' > conftest.c\n     bfd_cv_build_exeext=\n     ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5\n     for file in conftest.*; do\n       case $file in\n       *.c | *.o | *.obj | *.ilk | *.pdb) ;;\n       *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;\n       esac\n     done\n     rm -f conftest*\n     test x\"${bfd_cv_build_exeext}\" = x && bfd_cv_build_exeext=no])\n  EXEEXT_FOR_BUILD=\"\"\n  test x\"${bfd_cv_build_exeext}\" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}\nfi\nAC_SUBST(EXEEXT_FOR_BUILD)])dnl\nAC_SUBST(OBJEXT_FOR_BUILD)])dnl\n\n\n\n#------------------------------------------------------------------------\n# SC_ZIPFS_SUPPORT\n#\tLocate a zip encoder installed on the system path, or none.\n#\n# Arguments:\n#\tnone\n#\n# Results:\n#\tSubstitutes the following vars:\n#\t\tZIP_PROG\n#       ZIP_PROG_OPTIONS\n#       ZIP_PROG_VFSSEARCH\n#       ZIP_INSTALL_OBJS\n#------------------------------------------------------------------------\n\nAC_DEFUN([SC_ZIPFS_SUPPORT], [\n    ZIP_PROG=\"\"\n    ZIP_PROG_OPTIONS=\"\"\n    ZIP_PROG_VFSSEARCH=\"\"\n    ZIP_INSTALL_OBJS=\"\"\n\n    AC_MSG_CHECKING([for zip])\n    AC_CACHE_VAL(ac_cv_path_zip, [\n    search_path=`echo ${PATH} | sed -e 's/:/ /g'`\n    for dir in $search_path ; do\n\tfor j in `ls -r $dir/zip 2> /dev/null` \\\n\t    `ls -r $dir/zip 2> /dev/null` ; do\n\tif test x\"$ac_cv_path_zip\" = x ; then\n\t    if test -f \"$j\" ; then\n\t    ac_cv_path_zip=$j\n\t    break\n\t    fi\n\tfi\n\tdone\n    done\n    ])\n    if test -f \"$ac_cv_path_zip\" ; then\n\tZIP_PROG=\"$ac_cv_path_zip\"\n\tAC_MSG_RESULT([$ZIP_PROG])\n\tZIP_PROG_OPTIONS=\"-rq\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\tAC_MSG_RESULT([Found INFO Zip in environment])\n\t# Use standard arguments for zip\n    else\n\t# It is not an error if an installed version of Zip can't be located.\n\t# We can use the locally distributed minizip instead\n\tZIP_PROG=\"./minizip${EXEEXT_FOR_BUILD}\"\n\tZIP_PROG_OPTIONS=\"-o -r\"\n\tZIP_PROG_VFSSEARCH=\"*\"\n\tZIP_INSTALL_OBJS=\"minizip${EXEEXT_FOR_BUILD}\"\n\tAC_MSG_RESULT([No zip found on PATH building minizip])\n    fi\n    AC_SUBST(ZIP_PROG)\n    AC_SUBST(ZIP_PROG_OPTIONS)\n    AC_SUBST(ZIP_PROG_VFSSEARCH)\n    AC_SUBST(ZIP_INSTALL_OBJS)\n])\n"
  },
  {
    "path": "win/tkConfig.sh.in",
    "content": "# tkConfig.sh --\n#\n# This shell script (for sh) is generated automatically by Tk's\n# configure script.  It will create shell variables for most of\n# the configuration options discovered by the configure script.\n# This script is intended to be included by the configure scripts\n# for Tk extensions so that they don't have to figure this all\n# out for themselves.  This file does not duplicate information\n# already provided by tclConfig.sh, so you may need to use that\n# file in addition to this one.\n#\n# The information in this file is specific to a single platform.\n\nTK_DLL_FILE=\"@TK_DLL_FILE@\"\n\n# Tk's version number.\nTK_VERSION='@TK_VERSION@'\nTK_MAJOR_VERSION='@TK_MAJOR_VERSION@'\nTK_MINOR_VERSION='@TK_MINOR_VERSION@'\nTK_PATCH_LEVEL='@TK_PATCH_LEVEL@'\n\n# -D flags for use with the C compiler.\nTK_DEFS='@DEFS@'\n\n# Flag, 1: we built a shared lib, 0 we didn't\nTK_SHARED_BUILD=@TK_SHARED_BUILD@\n\n# TK_DBGX used to be used to distinguish debug vs. non-debug builds.\n# This was a righteous pain so the core doesn't do that any more.\nTK_DBGX=\n\n# The name of the Tk library (may be either a .a file or a shared library):\nTK_LIB_FILE='@TK_LIB_FILE@'\n\n# Additional libraries to use when linking Tk.\nTK_LIBS='@LIBS@ @LIBS_GUI@'\n\n# Top-level directory in which Tk's platform-independent files are\n# installed.\nTK_PREFIX='@prefix@'\n\n# Top-level directory in which Tk's platform-specific files (e.g.\n# executables) are installed.\nTK_EXEC_PREFIX='@exec_prefix@'\n\n# -l flag to pass to the linker to pick up the Tk library\nTK_LIB_FLAG='@TK_LIB_FLAG@'\n\n# String to pass to linker to pick up the Tk library from its\n# build directory.\nTK_BUILD_LIB_SPEC='@TK_BUILD_LIB_SPEC@'\n\n# String to pass to linker to pick up the Tk library from its\n# installed directory.\nTK_LIB_SPEC='@TK_LIB_SPEC@'\n\n# Location of the top-level source directory from which Tk was built.\n# This is the directory that contains a README file as well as\n# subdirectories such as generic, unix, etc.  If Tk was compiled in a\n# different place than the directory containing the source files, this\n# points to the location of the sources, not the location where Tk was\n# compiled.\nTK_SRC_DIR='@TK_SRC_DIR@'\n\n# Needed if you want to make a 'fat' shared library library\n# containing tk objects or link a different wish.\nTK_CC_SEARCH_FLAGS='@TK_CC_SEARCH_FLAGS@'\nTK_LD_SEARCH_FLAGS='@TK_LD_SEARCH_FLAGS@'\n\n# The name of the Tk stub library (.a):\nTK_STUB_LIB_FILE='@TK_STUB_LIB_FILE@'\n\n# -l flag to pass to the linker to pick up the Tk stub library\nTK_STUB_LIB_FLAG='@TK_STUB_LIB_FLAG@'\n\n# String to pass to linker to pick up the Tk stub library from its\n# build directory.\nTK_BUILD_STUB_LIB_SPEC='@TK_BUILD_STUB_LIB_SPEC@'\n\n# String to pass to linker to pick up the Tk stub library from its\n# installed directory.\nTK_STUB_LIB_SPEC='@TK_STUB_LIB_SPEC@'\n\n# Path to the Tk stub library in the build directory.\nTK_BUILD_STUB_LIB_PATH='@TK_BUILD_STUB_LIB_PATH@'\n\n# Path to the Tk stub library in the install directory.\nTK_STUB_LIB_PATH='@TK_STUB_LIB_PATH@'\n"
  },
  {
    "path": "win/tkUuid.h.in",
    "content": "#define TK_VERSION_UUID \\\n"
  },
  {
    "path": "win/tkWin.h",
    "content": "/*\n * tkWin.h --\n *\n *\tDeclarations of public types and interfaces that are only\n *\tavailable under Windows.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKWIN\n#define _TKWIN\n\n/*\n * We must specify the lowest version we intend to support.\n *\n * 0x0A00 means Windows 10 and above\n */\n\n#ifndef _WIN32_WINNT\n#   define _WIN32_WINNT 0x0A00\n#endif\n#ifndef WINVER\n#   define WINVER _WIN32_WINNT\t\t/* Should match _WIN32_WINNT */\n#endif\n#ifndef _TK\n#include <tk.h>\n#endif\n\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#undef WIN32_LEAN_AND_MEAN\n\n/*\n * The following messages are used to communicate between a Tk toplevel\n * and its container window. A Tk container may not be able to provide\n * service to all of the following requests at the moment. But an embedded\n * Tk window will send out these requests to support external Tk container\n * application.\n */\n\n#define TK_CLAIMFOCUS\t    (WM_USER)\t    /* an embedded window requests to focus */\n#define TK_GEOMETRYREQ\t    (WM_USER+1)\t    /* an embedded window requests to change size */\n#define TK_ATTACHWINDOW\t    (WM_USER+2)\t    /* an embedded window requests to attach */\n#define TK_DETACHWINDOW\t    (WM_USER+3)\t    /* an embedded window requests to detach */\n#define TK_MOVEWINDOW\t    (WM_USER+4)\t    /* an embedded window requests to move */\n#define TK_RAISEWINDOW\t    (WM_USER+5)\t    /* an embedded window requests to raise */\n#define TK_ICONIFY\t    (WM_USER+6)\t    /* an embedded window requests to iconify */\n#define TK_DEICONIFY\t    (WM_USER+7)\t    /* an embedded window requests to deiconify */\n#define TK_WITHDRAW\t    (WM_USER+8)\t    /* an embedded window requests to withdraw */\n#define TK_GETFRAMEWID\t    (WM_USER+9)\t    /* an embedded window requests a frame window id */\n#define TK_OVERRIDEREDIRECT (WM_USER+10)    /* an embedded window requests to overrideredirect */\n#define TK_SETMENU\t    (WM_USER+11)    /* an embedded window requests to setup menu */\n#define TK_STATE\t    (WM_USER+12)    /* an embedded window sets/gets state */\n#define TK_INFO\t\t    (WM_USER+13)    /* an embedded window requests a container's info */\n\n/*\n * The following are sub-messages (wParam) for TK_INFO.  An embedded window may\n * send a TK_INFO message with one of the sub-messages to query a container\n * for verification and availability\n */\n#define TK_CONTAINER_VERIFY\t    0x01\n#define TK_CONTAINER_ISAVAILABLE    0x02\n\n\f\n/*\n *--------------------------------------------------------------\n *\n * Exported procedures defined for the Windows platform only.\n *\n *--------------------------------------------------------------\n */\n\n#include \"tkPlatDecls.h\"  /* IWYU pragma: export */\n\n#endif /* _TKWIN */\n"
  },
  {
    "path": "win/tkWin32Dll.c",
    "content": "/*\n * tkWin32Dll.c --\n *\n *\tThis file contains a stub dll entry point.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#ifndef STATIC_BUILD\n\n#if defined(__GNUC__)\n\n/*\n * Need to add noinline flag to DllMain declaration so that gcc -O3 does not\n * inline asm code into DllEntryPoint and cause a compile time error because\n * of redefined local labels.\n */\n\nBOOL APIENTRY\t\tDllMain(HINSTANCE hInst, DWORD reason,\n\t\t\t    LPVOID reserved) __attribute__ ((noinline));\n\n#else\n\n/*\n * The following declaration is for the VC++ DLL entry point.\n */\n\nBOOL APIENTRY\t\tDllMain(HINSTANCE hInst, DWORD reason,\n\t\t\t    LPVOID reserved);\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DllEntryPoint --\n *\n *\tThis wrapper function is used by Borland to invoke the initialization\n *\tcode for Tk. It simply calls the DllMain routine.\n *\n * Results:\n *\tSee DllMain.\n *\n * Side effects:\n *\tSee DllMain.\n *\n *----------------------------------------------------------------------\n */\n\nBOOL APIENTRY\nDllEntryPoint(\n    HINSTANCE hInst,\t\t/* Library instance handle. */\n    DWORD reason,\t\t/* Reason this function is being called. */\n    LPVOID reserved)\t\t/* Not used. */\n{\n    return DllMain(hInst, reason, reserved);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DllMain --\n *\n *\tDLL entry point. It is only necessary to specify our dll here so that\n *\tresources are found correctly. Otherwise Tk will initialize and clean\n *\tup after itself through other methods, in order to be consistent\n *\twhether the build is static or dynamic.\n *\n * Results:\n *\tAlways TRUE.\n *\n * Side effects:\n *\tThis might call some synchronization functions, but MSDN documentation\n *\tstates: \"Waiting on synchronization objects in DllMain can cause a\n *\tdeadlock.\"\n *\n *----------------------------------------------------------------------\n */\n\nBOOL APIENTRY\nDllMain(\n    HINSTANCE hInstance,\n    DWORD reason,\n    LPVOID reserved)\n{\n    (void)reserved;\n\n    /*\n     * If we are attaching to the DLL from a new process, tell Tk about the\n     * hInstance to use.\n     */\n\n    switch (reason) {\n    case DLL_PROCESS_ATTACH:\n\tDisableThreadLibraryCalls(hInstance);\n\tTkWinSetHINSTANCE(hInstance);\n\tbreak;\n\n    case DLL_PROCESS_DETACH:\n\tTkFinalize(NULL);\n\tbreak;\n    }\n    return TRUE;\n}\n\n#endif /* !STATIC_BUILD */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWin3d.c",
    "content": "/*\n * tkWin3d.c --\n *\n *\tThis file contains the platform specific routines for drawing 3D\n *\tborders in the Windows 95 style.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tk3d.h\"\n\n/*\n * This structure is used to keep track of the extra colors used by Windows 3D\n * borders.\n */\n\ntypedef struct {\n    TkBorder info;\n    XColor *light2ColorPtr;\t/* System3dLight */\n    XColor *dark2ColorPtr;\t/* System3dDarkShadow */\n} WinBorder;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetBorder --\n *\n *\tThis function allocates a new TkBorder structure.\n *\n * Results:\n *\tReturns a newly allocated TkBorder.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkBorder *\nTkpGetBorder(void)\n{\n    WinBorder *borderPtr = (WinBorder *)Tcl_Alloc(sizeof(WinBorder));\n\n    borderPtr->light2ColorPtr = NULL;\n    borderPtr->dark2ColorPtr = NULL;\n    return (TkBorder *) borderPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeBorder --\n *\n *\tThis function frees any colors allocated by the platform specific part\n *\tof this module.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay deallocate some colors.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeBorder(\n    TkBorder *borderPtr)\n{\n    WinBorder *winBorderPtr = (WinBorder *) borderPtr;\n    if (winBorderPtr->light2ColorPtr) {\n\tTk_FreeColor(winBorderPtr->light2ColorPtr);\n    }\n    if (winBorderPtr->dark2ColorPtr) {\n\tTk_FreeColor(winBorderPtr->dark2ColorPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_3DVerticalBevel --\n *\n *\tThis procedure draws a vertical bevel along one side of an object. The\n *\tbevel is always rectangular in shape:\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\t\t\t|||\n *\tAn appropriate shadow color is chosen for the bevel based on the\n *\tleftBevel and relief arguments. Normally this procedure is called\n *\tfirst, then Tk_3DHorizontalBevel is called next to draw neat corners.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGraphics are drawn in drawable.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_3DVerticalBevel(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Area of vertical bevel. */\n    int leftBevel,\t\t/* Non-zero means this bevel forms the left\n\t\t\t\t * side of the object; 0 means it forms the\n\t\t\t\t * right side. */\n    int relief)\t\t\t/* Kind of bevel to draw. For example,\n\t\t\t\t * TK_RELIEF_RAISED means interior of object\n\t\t\t\t * should appear higher than exterior. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    int left, right;\n    Display *display = Tk_Display(tkwin);\n    TkWinDCState state;\n    HDC dc = TkWinGetDrawableDC(display, drawable, &state);\n    int half;\n\n    if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n\n    switch (relief) {\n    case TK_RELIEF_RAISED:\n\tleft = (leftBevel)\n\t\t? borderPtr->lightGC->foreground\n\t\t: borderPtr->darkGC->foreground;\n\tright = (leftBevel)\n\t\t? ((WinBorder *)borderPtr)->light2ColorPtr->pixel\n\t\t: ((WinBorder *)borderPtr)->dark2ColorPtr->pixel;\n\tbreak;\n    case TK_RELIEF_SUNKEN:\n\tleft = (leftBevel)\n\t\t? borderPtr->darkGC->foreground\n\t\t: ((WinBorder *)borderPtr)->light2ColorPtr->pixel;\n\tright = (leftBevel)\n\t\t? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel\n\t\t: borderPtr->lightGC->foreground;\n\tbreak;\n    case TK_RELIEF_RIDGE:\n\tleft = borderPtr->lightGC->foreground;\n\tright = borderPtr->darkGC->foreground;\n\tbreak;\n    case TK_RELIEF_GROOVE:\n\tleft = borderPtr->darkGC->foreground;\n\tright = borderPtr->lightGC->foreground;\n\tbreak;\n    case TK_RELIEF_FLAT:\n\tleft = right = borderPtr->bgGC->foreground;\n\tbreak;\n    case TK_RELIEF_SOLID:\n    default:\n\tleft = right = RGB(0,0,0);\n\tbreak;\n    }\n    half = width/2;\n    if (leftBevel && (width & 1)) {\n\thalf++;\n    }\n    TkWinFillRect(dc, x, y, half, height, left);\n    TkWinFillRect(dc, x+half, y, width-half, height, right);\n    TkWinReleaseDrawableDC(drawable, dc, &state);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_3DHorizontalBevel --\n *\n *\tThis procedure draws a horizontal bevel along one side of an object.\n *\tThe bevel has mitered corners (depending on leftIn and rightIn\n *\targuments).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTk_3DHorizontalBevel(\n    Tk_Window tkwin,\t\t/* Window for which border was allocated. */\n    Drawable drawable,\t\t/* X window or pixmap in which to draw. */\n    Tk_3DBorder border,\t\t/* Token for border to draw. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Bounding box of area of bevel. Height gives\n\t\t\t\t * width of border. */\n    int leftIn, int rightIn,\t/* Describes whether the left and right edges\n\t\t\t\t * of the bevel angle in or out as they go\n\t\t\t\t * down. For example, if \"leftIn\" is true, the\n\t\t\t\t * left side of the bevel looks like this:\n\t\t\t\t *\t___________\n\t\t\t\t *\t __________\n\t\t\t\t *\t  _________\n\t\t\t\t *\t   ________\n\t\t\t\t */\n    int topBevel,\t\t/* Non-zero means this bevel forms the top\n\t\t\t\t * side of the object; 0 means it forms the\n\t\t\t\t * bottom side. */\n    int relief)\t\t\t/* Kind of bevel to draw. For example,\n\t\t\t\t * TK_RELIEF_RAISED means interior of object\n\t\t\t\t * should appear higher than exterior. */\n{\n    TkBorder *borderPtr = (TkBorder *) border;\n    Display *display = Tk_Display(tkwin);\n    int bottom, halfway, x1, x2, x1Delta, x2Delta;\n    TkWinDCState state;\n    HDC dc = TkWinGetDrawableDC(display, drawable, &state);\n    int topColor, bottomColor;\n\n    if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {\n\tTkpGetShadows(borderPtr, tkwin);\n    }\n\n    /*\n     * Compute a GC for the top half of the bevel and a GC for the bottom half\n     * (they're the same in many cases).\n     */\n\n    switch (relief) {\n    case TK_RELIEF_RAISED:\n\ttopColor = (topBevel)\n\t\t? borderPtr->lightGC->foreground\n\t\t: borderPtr->darkGC->foreground;\n\tbottomColor = (topBevel)\n\t\t? ((WinBorder *)borderPtr)->light2ColorPtr->pixel\n\t\t: ((WinBorder *)borderPtr)->dark2ColorPtr->pixel;\n\tbreak;\n    case TK_RELIEF_SUNKEN:\n\ttopColor = (topBevel)\n\t\t? borderPtr->darkGC->foreground\n\t\t: ((WinBorder *)borderPtr)->light2ColorPtr->pixel;\n\tbottomColor = (topBevel)\n\t\t? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel\n\t\t: borderPtr->lightGC->foreground;\n\tbreak;\n    case TK_RELIEF_RIDGE:\n\ttopColor = borderPtr->lightGC->foreground;\n\tbottomColor = borderPtr->darkGC->foreground;\n\tbreak;\n    case TK_RELIEF_GROOVE:\n\ttopColor = borderPtr->darkGC->foreground;\n\tbottomColor = borderPtr->lightGC->foreground;\n\tbreak;\n    case TK_RELIEF_FLAT:\n\ttopColor = bottomColor = borderPtr->bgGC->foreground;\n\tbreak;\n    case TK_RELIEF_SOLID:\n    default:\n\ttopColor = bottomColor = RGB(0,0,0);\n    }\n\n    /*\n     * Compute various other geometry-related stuff.\n     */\n\n    if (leftIn) {\n\tx1 = x+1;\n    } else {\n\tx1 = x+height-1;\n    }\n    x2 = x+width;\n    if (rightIn) {\n\tx2--;\n    } else {\n\tx2 -= height;\n    }\n    x1Delta = (leftIn) ? 1 : -1;\n    x2Delta = (rightIn) ? -1 : 1;\n    halfway = y + height/2;\n    if (topBevel && (height & 1)) {\n\thalfway++;\n    }\n    bottom = y + height;\n\n    /*\n     * Draw one line for each y-coordinate covered by the bevel.\n     */\n\n    for ( ; y < bottom; y++) {\n\t/*\n\t * In some weird cases (such as large border widths for skinny\n\t * rectangles) x1 can be >= x2. Don't draw the lines in these cases.\n\t */\n\n\tif (x1 < x2) {\n\t    TkWinFillRect(dc, x1, y, x2-x1, 1,\n\t\t(y < halfway) ? topColor : bottomColor);\n\t}\n\tx1 += x1Delta;\n\tx2 += x2Delta;\n    }\n    TkWinReleaseDrawableDC(drawable, dc, &state);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetShadows --\n *\n *\tThis procedure computes the shadow colors for a 3-D border and fills\n *\tin the corresponding fields of the Border structure. It's called\n *\tlazily, so that the colors aren't allocated until something is\n *\tactually drawn with them. That way, if a border is only used for flat\n *\tbackgrounds the shadow colors will never be allocated.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe lightGC and darkGC fields in borderPtr get filled in, if they\n *\tweren't already.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetShadows(\n    TkBorder *borderPtr,\t/* Information about border. */\n    Tk_Window tkwin)\t\t/* Window where border will be used for\n\t\t\t\t * drawing. */\n{\n    XColor lightColor, darkColor;\n    int tmp1, tmp2;\n    unsigned short r, g, b;\n    XGCValues gcValues;\n\n    if (borderPtr->lightGC != NULL) {\n\treturn;\n    }\n\n    /*\n     * Handle the special case of the default system colors.\n     */\n\n    if ((TkWinIndexOfColor(borderPtr->bgColorPtr) == COLOR_3DFACE)\n\t    || (TkWinIndexOfColor(borderPtr->bgColorPtr) == COLOR_WINDOW)) {\n\tborderPtr->darkColorPtr = Tk_GetColor(NULL, tkwin,\n\t\t\"SystemButtonShadow\");\n\tgcValues.foreground = borderPtr->darkColorPtr->pixel;\n\tborderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\tborderPtr->lightColorPtr = Tk_GetColor(NULL, tkwin,\n\t\t\"SystemButtonHighlight\");\n\tgcValues.foreground = borderPtr->lightColorPtr->pixel;\n\tborderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\t((WinBorder*)borderPtr)->dark2ColorPtr = Tk_GetColor(NULL, tkwin,\n\t\t\"System3dDarkShadow\");\n\t((WinBorder*)borderPtr)->light2ColorPtr = Tk_GetColor(NULL, tkwin,\n\t\t\"System3dLight\");\n\treturn;\n    }\n    darkColor.red = 0;\n    darkColor.green = 0;\n    darkColor.blue = 0;\n    ((WinBorder*)borderPtr)->dark2ColorPtr = Tk_GetColorByValue(tkwin,\n\t    &darkColor);\n    lightColor = *(borderPtr->bgColorPtr);\n    ((WinBorder*)borderPtr)->light2ColorPtr = Tk_GetColorByValue(tkwin,\n\t    &lightColor);\n\n    /*\n     * First, handle the case of a color display with lots of colors. The\n     * shadow colors get computed using whichever formula results in the\n     * greatest change in color:\n     * 1. Lighter shadow is half-way to white, darker shadow is half way to\n     *    dark.\n     * 2. Lighter shadow is 40% brighter than background, darker shadow is 40%\n     *    darker than background.\n     */\n\n    if (Tk_Depth(tkwin) >= 6) {\n\t/*\n\t * This is a color display with lots of colors. For the dark shadow,\n\t * cut 40% from each of the background color components. But if the\n\t * background is already very dark, make the dark color a little\n\t * lighter than the background by increasing each color component\n\t * 1/4th of the way to MAX_INTENSITY.\n\t *\n\t * For the light shadow, boost each component by 40% or half-way to\n\t * white, whichever is greater (the first approach works better for\n\t * unsaturated colors, the second for saturated ones). But if the\n\t * background is already very bright, instead choose a slightly darker\n\t * color for the light shadow by reducing each color component by 10%.\n\t *\n\t * Compute the colors using integers, not using lightColor.red etc.:\n\t * these are shorts and may have problems with integer overflow.\n\t */\n\n\t/*\n\t * Compute the dark shadow color\n\t */\n\n\tr = borderPtr->bgColorPtr->red;\n\tg = borderPtr->bgColorPtr->green;\n\tb = borderPtr->bgColorPtr->blue;\n\n\tif (r*0.5*r + g*1.0*g + b*0.28*b < MAX_INTENSITY*0.05*MAX_INTENSITY) {\n\t    darkColor.red = (unsigned short)((MAX_INTENSITY + 3*r)/4);\n\t    darkColor.green = (unsigned short)((MAX_INTENSITY + 3*g)/4);\n\t    darkColor.blue = (unsigned short)((MAX_INTENSITY + 3*b)/4);\n\t} else {\n\t    darkColor.red = (unsigned short)((60 * r)/100);\n\t    darkColor.green = (unsigned short)((60 * g)/100);\n\t    darkColor.blue = (unsigned short)((60 * b)/100);\n\t}\n\n\t/*\n\t * Allocate the dark shadow color and its GC\n\t */\n\n\tborderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor);\n\tgcValues.foreground = borderPtr->darkColorPtr->pixel;\n\tborderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\n\t/*\n\t * Compute the light shadow color\n\t */\n\n\tif (g > MAX_INTENSITY*0.95) {\n\t    lightColor.red = (unsigned short)((90 * r)/100);\n\t    lightColor.green = (unsigned short)((90 * g)/100);\n\t    lightColor.blue = (unsigned short)((90 * b)/100);\n\t} else {\n\t    tmp1 = (14 * r)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + r)/2;\n\t    lightColor.red = (unsigned short)((tmp1 > tmp2) ? tmp1 : tmp2);\n\t    tmp1 = (14 * g)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + g)/2;\n\t    lightColor.green = (unsigned short)((tmp1 > tmp2) ? tmp1 : tmp2);\n\t    tmp1 = (14 * b)/10;\n\t    if (tmp1 > MAX_INTENSITY) {\n\t\ttmp1 = MAX_INTENSITY;\n\t    }\n\t    tmp2 = (MAX_INTENSITY + b)/2;\n\t    lightColor.blue = (unsigned short)((tmp1 > tmp2) ? tmp1 : tmp2);\n\t}\n\n\t/*\n\t * Allocate the light shadow color and its GC\n\t */\n\n\tborderPtr->lightColorPtr = Tk_GetColorByValue(tkwin, &lightColor);\n\tgcValues.foreground = borderPtr->lightColorPtr->pixel;\n\tborderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n\treturn;\n    }\n\n    if (borderPtr->shadow == None) {\n\tborderPtr->shadow = Tk_GetBitmap(NULL, tkwin, \"gray50\");\n\tif (borderPtr->shadow == None) {\n\t    Tcl_Panic(\"TkpGetShadows couldn't allocate bitmap for border\");\n\t}\n    }\n    if (borderPtr->visual->map_entries > 2) {\n\t/*\n\t * This isn't a monochrome display, but the colormap either ran out of\n\t * entries or didn't have very many to begin with. Generate the light\n\t * shadows with a white stipple and the dark shadows with a black\n\t * stipple.\n\t */\n\n\tgcValues.foreground = borderPtr->bgColorPtr->pixel;\n\tgcValues.background = BlackPixelOfScreen(borderPtr->screen);\n\tgcValues.stipple = borderPtr->shadow;\n\tgcValues.fill_style = FillOpaqueStippled;\n\tborderPtr->darkGC = Tk_GetGC(tkwin,\n\t\tGCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n\tgcValues.foreground = WhitePixelOfScreen(borderPtr->screen);\n\tgcValues.background = borderPtr->bgColorPtr->pixel;\n\tborderPtr->lightGC = Tk_GetGC(tkwin,\n\t\tGCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n\treturn;\n    }\n\n    /*\n     * This is just a measly monochrome display, hardly even worth its\n     * existence on this earth. Make one shadow a 50% stipple and the other\n     * the opposite of the background.\n     */\n\n    gcValues.foreground = WhitePixelOfScreen(borderPtr->screen);\n    gcValues.background = BlackPixelOfScreen(borderPtr->screen);\n    gcValues.stipple = borderPtr->shadow;\n    gcValues.fill_style = FillOpaqueStippled;\n    borderPtr->lightGC = Tk_GetGC(tkwin,\n\t    GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);\n    if (borderPtr->bgColorPtr->pixel\n\t    == WhitePixelOfScreen(borderPtr->screen)) {\n\tgcValues.foreground = BlackPixelOfScreen(borderPtr->screen);\n\tborderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    } else {\n\tborderPtr->darkGC = borderPtr->lightGC;\n\tborderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetBorderPixels --\n *\n *\tThis routine returns the 5 COLORREFs used to draw a given 3d border.\n *\n * Results:\n *\tReturns the colors in the specified array.\n *\n * Side effects:\n *\tMay cause the remaining colors to be allocated.\n *\n *----------------------------------------------------------------------\n */\n\nCOLORREF\nTkWinGetBorderPixels(\n    Tk_Window tkwin,\n    Tk_3DBorder border,\n    int which)\t\t\t/* One of TK_3D_FLAT_GC, TK_3D_LIGHT_GC,\n\t\t\t\t * TK_3D_DARK_GC, TK_3D_LIGHT2, TK_3D_DARK2 */\n{\n    WinBorder *borderPtr = (WinBorder *) border;\n\n    if (borderPtr->info.lightGC == NULL) {\n\tTkpGetShadows(&borderPtr->info, tkwin);\n    }\n    switch (which) {\n    case TK_3D_FLAT_GC:\n\treturn borderPtr->info.bgColorPtr->pixel;\n    case TK_3D_LIGHT_GC:\n\tif (borderPtr->info.lightColorPtr == NULL) {\n\t    return WhitePixelOfScreen(borderPtr->info.screen);\n\t}\n\treturn borderPtr->info.lightColorPtr->pixel;\n    case TK_3D_DARK_GC:\n\tif (borderPtr->info.darkColorPtr == NULL) {\n\t    return BlackPixelOfScreen(borderPtr->info.screen);\n\t}\n\treturn borderPtr->info.darkColorPtr->pixel;\n    case TK_3D_LIGHT2:\n\treturn borderPtr->light2ColorPtr->pixel;\n    case TK_3D_DARK2:\n\treturn borderPtr->dark2ColorPtr->pixel;\n    }\n    return 0;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinAccessibility.c",
    "content": "/*\n * tkWinAccessibility.c\n *\n *    This file implements the platform-native Microsoft Active\n *    Accessibility API for Tk on Windows and supports UI Automation\n *    through the MSAA-UIA bridge provided by Windows.\n *\n * Copyright © 2024-2025 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n */\n\n#include \"tkWinInt.h\"\n#include <tcl.h>\n#include <tk.h>\n#include <oleacc.h>\n#include <oaidl.h>\n#include <oleauto.h>\n\n#include <initguid.h>\n#include <tlhelp32.h>\n#include <tchar.h>\n#include <stdarg.h>\n#include <limits.h>\n\n/*\n *----------------------------------------------------------------------\n *\n * Data definitions for MSAA-Tk integration.\n *\n *----------------------------------------------------------------------\n */\n\n/* Define global lock constants. */\nstatic CRITICAL_SECTION TkGlobalLock;\nstatic INIT_ONCE TkInitOnce = INIT_ONCE_STATIC_INIT;\n#define TkGlobalLock()   EnterCriticalSection(&TkGlobalLock)\n#define TkGlobalUnlock() LeaveCriticalSection(&TkGlobalLock)\n\n/* TkRootAccessible structure. */\ntypedef struct TkRootAccessible {\n    IAccessibleVtbl *lpVtbl;\n    Tk_Window win;\n    Tk_Window toplevel;\n    Tcl_Interp *interp;\n    HWND hwnd;\n    char *pathName;\n    IAccessible **children;\n    int numChildren;\n    LONG refCount;\n} TkRootAccessible;\n\n/*\n * Map script-level roles to C roles for MSAA.\n */\n\nstruct WinRoleMap {\n    const char *tkrole;\n    LONG winrole;\n};\n\nconst struct WinRoleMap roleMap[] = {\n    {\"Button\", ROLE_SYSTEM_PUSHBUTTON},\n    {\"Canvas\", ROLE_SYSTEM_CLIENT},\n    {\"Checkbutton\", ROLE_SYSTEM_CHECKBUTTON},\n    {\"Combobox\", ROLE_SYSTEM_COMBOBOX},\n    {\"Entry\", ROLE_SYSTEM_TEXT},\n    {\"Label\", ROLE_SYSTEM_STATICTEXT},\n    {\"Listbox\", ROLE_SYSTEM_LIST},\n    {\"Notebook\", ROLE_SYSTEM_PAGETABLIST},\n    {\"Progressbar\", ROLE_SYSTEM_PROGRESSBAR},\n    {\"Radiobutton\", ROLE_SYSTEM_RADIOBUTTON},\n    {\"Scale\", ROLE_SYSTEM_SLIDER},\n    {\"Scrollbar\", ROLE_SYSTEM_SCROLLBAR},\n    {\"Spinbox\", ROLE_SYSTEM_SPINBUTTON},\n    {\"Table\", ROLE_SYSTEM_TABLE},\n    {\"Text\", ROLE_SYSTEM_TEXT},\n    {\"Tree\", ROLE_SYSTEM_OUTLINE},\n    {\"Toggleswitch\", ROLE_SYSTEM_CHECKBUTTON},\n    {NULL, 0}\n};\n\n/* Hash table for managing accessibility attributes. */\nextern Tcl_HashTable *TkAccessibilityObject;\n\n/* Hash tables for linking Tk windows to accessibility object and HWND. */\nstatic Tcl_HashTable *tkAccessibleTable;\nstatic bool tkAccessibleTableInitialized = false;\nstatic Tcl_HashTable *toplevelChildTables = NULL;\n\n/* Data structures for managing execution on main thread. */\ntypedef void (*MainThreadFunc)(int num_args, void** args);\n\ntypedef struct {\n    Tcl_Event header;\n    MainThreadFunc func;\n    int num_args;\n    void* args[6];\n    HANDLE doneEvent;\n} MainThreadSyncEvent;\n\n/*\n * Need main thread, main interp, and command struct\n * for accessible operations on main thread\n * defined here.\n */\nstatic Tcl_ThreadId mainThreadId;\nstatic volatile HRESULT mainThreadResult = E_FAIL;\n\ntypedef struct {\n    Tcl_Event header;\n    char *command;\n    Tk_Window win;\n} ActionEvent;\n\n/*\n *----------------------------------------------------------------------\n *\n * Prototypes for toplevel MSAA objects. These will always run on background\n * threads. Any calls into Tcl/Tk functions must be guarded with a global\n * thread lock or explicitly pushed to the main thread because Tk is not\n * thread safe.\n *\n *----------------------------------------------------------------------\n */\n\n/* Protoypes of glue functions to the IAccessible COM API - toplevels. */\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_QueryInterface(IAccessible *this, REFIID riid, void **ppvObject);\nstatic ULONG STDMETHODCALLTYPE TkRootAccessible_AddRef(IAccessible *this);\nstatic ULONG STDMETHODCALLTYPE TkRootAccessible_Release(IAccessible *this);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_GetTypeInfoCount(IAccessible *this, UINT *pctinfo);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_GetTypeInfo(IAccessible *this, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_GetIDsOfNames(IAccessible *this, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_Invoke(IAccessible *this, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);\n\n/* Prototypes of empty stub functions required by MSAA-toplevels. */\nHRESULT STDMETHODCALLTYPE TkRootAccessible_get_accHelpTopic(IAccessible *this, BSTR *pszHelpFile, VARIANT varChild, long *pidTopic);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_get_accKeyboardShortcut(IAccessible *this, VARIANT varChild, BSTR *pszKeyboardShortcut);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_get_accSelection(IAccessible *this, VARIANT *pvarChildren);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_accNavigate(IAccessible *this, long navDir, VARIANT varStart, VARIANT *pvarEndUpAt);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_accHitTest(IAccessible *this, long xLeft, long yTop, VARIANT *pvarChild);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_put_accName(IAccessible *this, VARIANT varChild, BSTR szName);\nHRESULT STDMETHODCALLTYPE TkRootAccessible_put_accValue(IAccessible *this, VARIANT varChild, BSTR szValue);\n\n/* Prototypes of the MSAA functions that actually implement accessibility for Tk widgets on Windows - toplevels. */\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accName(IAccessible *this, VARIANT varChild, BSTR *pszName);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accRole(IAccessible *this, VARIANT varChild, VARIANT *pvarRole);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accState(IAccessible *this, VARIANT varChild, VARIANT *pvarState);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accValue(IAccessible *this, VARIANT varChild, BSTR *pszValue);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accParent(IAccessible *this, IDispatch **ppdispParent);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accChildCount(IAccessible *this, LONG *pcChildren);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accChild(IAccessible *this, VARIANT varChild, IDispatch **ppdispChild);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_accLocation(IAccessible *this, LONG *pxLeft, LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varChild);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_accSelect(IAccessible *this, long flags, VARIANT varChild);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accDefaultAction(IAccessible *this, VARIANT varChild, BSTR *pszDefaultAction);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_accDoDefaultAction(IAccessible *this, VARIANT varChild);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accHelp(IAccessible *this, VARIANT varChild, BSTR* pszHelp);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accDescription(IAccessible *this, VARIANT varChild, BSTR *pszDescription);\nstatic HRESULT STDMETHODCALLTYPE TkRootAccessible_get_accFocus(IAccessible *this, VARIANT *pvarChild);\n\n/* VTable for MSAA root accessible. */\nstatic IAccessibleVtbl tkRootAccessibleVtbl = {\n    TkRootAccessible_QueryInterface,\n    TkRootAccessible_AddRef,\n    TkRootAccessible_Release,\n    TkRootAccessible_GetTypeInfoCount,\n    TkRootAccessible_GetTypeInfo,\n    TkRootAccessible_GetIDsOfNames,\n    TkRootAccessible_Invoke,\n    TkRootAccessible_get_accParent,\n    TkRootAccessible_get_accChildCount,\n    TkRootAccessible_get_accChild,\n    TkRootAccessible_get_accName,\n    TkRootAccessible_get_accValue,\n    TkRootAccessible_get_accDescription,\n    TkRootAccessible_get_accRole,\n    TkRootAccessible_get_accState,\n    TkRootAccessible_get_accHelp,\n    TkRootAccessible_get_accHelpTopic,\n    TkRootAccessible_get_accKeyboardShortcut,\n    TkRootAccessible_get_accFocus,\n    TkRootAccessible_get_accSelection,\n    TkRootAccessible_get_accDefaultAction,\n    TkRootAccessible_accSelect,\n    TkRootAccessible_accLocation,\n    TkRootAccessible_accNavigate,\n    TkRootAccessible_accHitTest,\n    TkRootAccessible_accDoDefaultAction,\n    TkRootAccessible_put_accName,\n    TkRootAccessible_put_accValue\n};\n\n/*\n *----------------------------------------------------------------------\n *\n * Prototypes for child widgets using MSAA childId. These will be called\n * from a global lock or explicitly run on the main thread.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HRESULT TkAccRole(Tk_Window win, VARIANT *pvarRole);\nstatic void ComputeAndCacheCheckedState(Tk_Window win, Tcl_Interp *interp);\nstatic HRESULT TkAccState(Tk_Window win, VARIANT *pvarState);\nstatic void TkAccFocus(int num_args, void **args);\nstatic HRESULT TkAccDescription(Tk_Window win, BSTR *pDesc);\nstatic HRESULT TkAccValue(Tk_Window win, BSTR *pValue);\nstatic void TkDoDefaultAction(int num_args, void **args);\nstatic HRESULT TkAccHelp(Tk_Window win, BSTR *pszHelp);\nstatic int TkAccChildCount(Tk_Window win);\nstatic int ActionEventProc(Tcl_Event *ev, int flags);\nstatic HRESULT TkAccChild_GetRect(Tcl_Interp *interp, char *path, RECT *rect);\n\n\n/*\n *----------------------------------------------------------------------\n *\n * Prototypes for functions to manage threading activities.\n *\n *----------------------------------------------------------------------\n */\nint ExecuteOnMainThreadSync(Tcl_Event *ev, int flags);\nvoid RunOnMainThreadSync(MainThreadFunc func, int num_args, ...);\nvoid HandleWMGetObjectOnMainThread(int num_args, void **args);\nBOOL CALLBACK InitGlobalLockOnce(PINIT_ONCE InitOnce, PVOID param, PVOID *Context);\nvoid EnsureGlobalLockInitialized(void);\n\n/*\n *----------------------------------------------------------------------\n *\n * Prototypes of Tk functions that support MSAA integration\n * and help implement the script-level API.\n *\n *----------------------------------------------------------------------\n */\n\nvoid InitTkAccessibleTable(void);\nvoid InitChildIdTable(void);\nvoid ClearChildIdTableForToplevel(Tk_Window toplevel);\nTkRootAccessible *GetTkAccessibleForWindow(Tk_Window win);\nstatic TkRootAccessible *CreateRootAccessible(Tcl_Interp *interp, HWND hwnd, const char *pathName);\nstatic void SetChildIdForTkWindow(Tk_Window win, int id, Tcl_HashTable *childIdTable);\nstatic int GetChildIdForTkWindow(Tk_Window win, Tcl_HashTable *childIdTable);\nTk_Window GetToplevelOfWidget(Tk_Window tkwin);\nstatic Tcl_HashTable *GetChildIdTableForToplevel(Tk_Window toplevel);\nTk_Window GetTkWindowForChildId(int id, Tk_Window toplevel);\nint IsScreenReaderRunning(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int EmitSelectionChanged(void *clientData,Tcl_Interp *ip, Tcl_Size objc, Tcl_Obj *const *objv);\nstatic int EmitFocusChanged(void *cd, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv);\nvoid TkRootAccessible_RegisterForCleanup(Tk_Window tkwin, void *tkAccessible);\nstatic void TkRootAccessible_DestroyHandler(void *clientData, XEvent *eventPtr);\nstatic void AssignChildIdsRecursive(Tk_Window win, int *nextId, Tcl_Interp *interp, Tk_Window toplevel);\nvoid InitAccessibilityMainThread(void);\nint TkRootAccessibleObjCmd(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv);\nint TkWinAccessiblity_Init(Tcl_Interp *interp);\n\n/*\n *----------------------------------------------------------------------\n *\n * Glue functions to the IAccessible COM API - toplevels.\n *\n *----------------------------------------------------------------------\n */\n\n/* Empty stub functions required by MSAA. */\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accHelpTopic(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(BSTR *), /* pszHelpFile */\n    TCL_UNUSED(VARIANT), /* varChild */\n    TCL_UNUSED(long *)) /* pidTopic */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accKeyboardShortcut(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(VARIANT), /* varChild */\n    TCL_UNUSED(BSTR *)) /* pszKeyboardShortcut */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accSelection(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(VARIANT *)) /*pvarChildren */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_accNavigate(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(long), /* navDir */\n    TCL_UNUSED(VARIANT), /* varStart */\n    TCL_UNUSED(VARIANT *)) /* pvarEndUpAt */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_accHitTest(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(long), /* xLeft */\n    TCL_UNUSED(long), /* yTop */\n    TCL_UNUSED(VARIANT *)) /* pvarChild */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_put_accName(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(VARIANT), /* varChild */\n    TCL_UNUSED(BSTR)) /* szName */\n{\n    return E_NOTIMPL;\n}\n\nHRESULT STDMETHODCALLTYPE\nTkRootAccessible_put_accValue(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(VARIANT), /* varChild */\n    TCL_UNUSED(BSTR)) /* szValue */\n{\n    return E_NOTIMPL;\n}\n\n/*\n *----------------------------------------------------------------------\n * Begin active MSAA functions. These are run on a background thread\n * and if they need to call into Tk to read data, a global thread lock\n * will be applied.\n *----------------------------------------------------------------------\n */\n\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_QueryInterface(\n    IAccessible *this,\n    REFIID riid,\n    void **ppvObject)\n{\n    if (!ppvObject) return E_INVALIDARG;\n    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IAccessible)) {\n\t*ppvObject = this;\n\tTkRootAccessible_AddRef(this);\n\treturn S_OK;\n    }\n    *ppvObject = NULL;\n    return E_NOINTERFACE;\n}\n\n/* Function to add memory reference to the MSAA object. */\nstatic ULONG STDMETHODCALLTYPE\nTkRootAccessible_AddRef(\n    IAccessible *this)\n{\n    if (!this) return E_INVALIDARG;\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    return InterlockedIncrement(&tkAccessible->refCount);\n}\n\n/* Function to free the MSAA object. */\nstatic ULONG STDMETHODCALLTYPE\nTkRootAccessible_Release(\n    IAccessible *this)\n{\n    if (!this) return E_INVALIDARG;\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    ULONG count = InterlockedDecrement(&tkAccessible->refCount);\n    if (count == 0) {\n\tTkGlobalLock();\n\tif (tkAccessible->win && tkAccessibleTableInitialized) {\n\t    Tcl_HashEntry *entry = Tcl_FindHashEntry(tkAccessibleTable, tkAccessible->win);\n\t    if (entry) {\n\t\tTcl_DeleteHashEntry(entry);\n\t    }\n\t}\n\tif (tkAccessible->pathName) {\n\t    Tcl_Free(tkAccessible->pathName);\n\t    tkAccessible->pathName = NULL;\n\t}\n\tTcl_Free(tkAccessible);\n\tTkGlobalUnlock();\n    }\n    return count;\n}\n\n/* The number of type information interfaces provided by the object. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_GetTypeInfoCount(\n    TCL_UNUSED(IAccessible *), /* this */\n    UINT *pctinfo)\n{\n    if (!pctinfo) return E_INVALIDARG;\n    *pctinfo = 1;\n    return S_OK;\n}\n\n/*\n * Retrieves the type information for an object, which can then be used\n * to get the type information for an interface.\n */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_GetTypeInfo(\n    TCL_UNUSED(IAccessible *), /* this */\n    UINT iTInfo,\n    LCID lcid,\n    ITypeInfo **ppTInfo)\n{\n    if (!ppTInfo) return E_INVALIDARG;\n    *ppTInfo = NULL;\n    if (iTInfo != 0) return DISP_E_BADINDEX;\n\n    ITypeLib *pTypeLib = NULL;\n    HRESULT hr = LoadRegTypeLib(&LIBID_Accessibility, 1, 1, lcid, &pTypeLib);\n    if (FAILED(hr)) return hr;\n\n    ITypeInfo *pTypeInfo = NULL;\n    hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, &IID_IAccessible, &pTypeInfo);\n    pTypeLib->lpVtbl->Release(pTypeLib);\n    if (FAILED(hr)) return hr;\n\n    *ppTInfo = pTypeInfo;\n    return S_OK;\n}\n\n/*\n * Maps a single member and an optional set of argument names to a\n * corresponding set of integer DISPIDs, which can be used on subsequent calls\n * to Invoke.\n */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_GetIDsOfNames(\n    IAccessible *this,\n    TCL_UNUSED(REFIID), /* riid */\n    LPOLESTR *rgszNames,\n    UINT cNames,\n    LCID lcid,\n    DISPID *rgDispId)\n{\n    if (!rgszNames || !rgDispId) return E_INVALIDARG;\n    ITypeInfo *pTypeInfo = NULL;\n    HRESULT hr = TkRootAccessible_GetTypeInfo(this, 0, lcid, &pTypeInfo);\n    if (FAILED(hr) || !pTypeInfo) return E_FAIL;\n\n    hr = DispGetIDsOfNames(pTypeInfo, rgszNames, cNames, rgDispId);\n    pTypeInfo->lpVtbl->Release(pTypeInfo);\n    return hr;\n}\n\n/* Provides access to properties and methods exposed by an MSAA object. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_Invoke(\n    IAccessible *this,\n    DISPID dispIdMember,\n    TCL_UNUSED(REFIID), /* riid */\n    TCL_UNUSED(LCID), /* lcid */\n    TCL_UNUSED(WORD), /* wFlags */\n    TCL_UNUSED(DISPPARAMS *), /* pDispParams */\n    VARIANT *pVarResult,\n    TCL_UNUSED(EXCEPINFO *), /* pExcepInfo */\n    TCL_UNUSED(UINT *)) /* puArgErr */\n{\n    if (!pVarResult) return E_INVALIDARG;\n    VariantInit(pVarResult);\n\n    VARIANT selfVar;\n    selfVar.vt = VT_I4;\n    selfVar.lVal = CHILDID_SELF;\n\n    switch (dispIdMember) {\n    case DISPID_ACC_NAME:\n\treturn TkRootAccessible_get_accName(this, selfVar, &pVarResult->bstrVal);\n    case DISPID_ACC_VALUE:\n\treturn TkRootAccessible_get_accValue(this, selfVar, &pVarResult->bstrVal);\n    case DISPID_ACC_ROLE:\n\treturn TkRootAccessible_get_accRole(this, selfVar, pVarResult);\n    case DISPID_ACC_STATE:\n\treturn TkRootAccessible_get_accState(this, selfVar, pVarResult);\n    case DISPID_ACC_DESCRIPTION:\n\treturn TkRootAccessible_get_accDescription(this, selfVar, &pVarResult->bstrVal);\n    case DISPID_ACC_HELP:\n\treturn TkRootAccessible_get_accHelp(this, selfVar, &pVarResult->bstrVal);\n    case DISPID_ACC_DEFAULTACTION:\n\treturn TkRootAccessible_get_accDefaultAction(this, selfVar, &pVarResult->bstrVal);\n    case DISPID_ACC_DODEFAULTACTION:\n\treturn TkRootAccessible_accDoDefaultAction(this, selfVar);\n    case DISPID_ACC_FOCUS:\n\treturn TkRootAccessible_get_accFocus(this, pVarResult);\n    }\n    return S_OK;\n}\n\n/*\n * Function to map accessible name to MSAA. We pass the description string\n * to the name property so that we can get correct labeling on both NVDA\n * and Narrator.\n */\n\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accName(\n    IAccessible *this,\n    VARIANT varChild,\n    BSTR *pszName)\n{\n    if (!pszName) return E_INVALIDARG;\n    *pszName = NULL;\n\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n\n    /* Toplevel. */\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\tHWND hwnd = Tk_GetHWND(Tk_WindowId(tkAccessible->toplevel));\n\tint wlen = GetWindowTextLengthW(hwnd);\n\tWCHAR *wbuf = (WCHAR *)Tcl_Alloc((wlen + 1) * sizeof(WCHAR));\n\n\t/* Read the actual UTF-16 title. */\n\tif (!GetWindowTextW(hwnd, wbuf, wlen + 1)) {\n\t    Tcl_Free(wbuf);\n\t    *pszName = SysAllocString(L\"\");\n\t    TkGlobalUnlock();\n\t    return S_OK;\n\t}\n\t*pszName = SysAllocString(wbuf);\n\tTcl_Free(wbuf);\n\tTkGlobalUnlock();\n\treturn S_OK;\n    }\n\n\n    /* Child widgets - return description. */\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (child) {\n\t    HRESULT hr = TkAccDescription(child, pszName);\n\t    TkGlobalUnlock();\n\t    return hr;\n\t}\n    }\n\n    TkGlobalUnlock();\n    return E_INVALIDARG;\n}\n\n/* Function to map accessible role to MSAA. For toplevels, return ROLE_SYSTEM_WINDOW. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accRole(\n    IAccessible *this,\n    VARIANT varChild,\n    VARIANT *pvarRole)\n{\n    if (!pvarRole) return E_INVALIDARG;\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\tpvarRole->vt = VT_I4;\n\tpvarRole->lVal = ROLE_SYSTEM_WINDOW;\n\treturn S_OK;\n    }\n\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tHRESULT hr = TkAccRole(child, pvarRole);\n\tTkGlobalUnlock();\n\treturn hr;\n    }\n    TkGlobalUnlock();\n    return E_INVALIDARG;\n}\n\n/* Function to map accessible state to MSAA. For toplevel, return STATE_SYSTEM_FOCUSABLE. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accState(\n    IAccessible *this,\n    VARIANT varChild,\n    VARIANT *pvarState)\n{\n    if (!pvarState) return E_INVALIDARG;\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\tpvarState->vt = VT_I4;\n\tpvarState->lVal = STATE_SYSTEM_FOCUSABLE;\n\treturn S_OK;\n    }\n\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tHRESULT hr = TkAccState(child, pvarState);\n\tTkGlobalUnlock();\n\treturn hr;\n    }\n    TkGlobalUnlock();\n    return DISP_E_MEMBERNOTFOUND;\n}\n\n/* Function to map accessible value to MSAA. For toplevel, return NULL. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accValue(\n    IAccessible *this,\n    VARIANT varChild,\n    BSTR *pszValue)\n{\n    if (!pszValue) return E_INVALIDARG;\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\t*pszValue = NULL;\n\treturn DISP_E_MEMBERNOTFOUND;\n    }\n\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tHRESULT hr = TkAccValue(child, pszValue);\n\tTkGlobalUnlock();\n\treturn hr;\n    }\n    TkGlobalUnlock();\n    return DISP_E_MEMBERNOTFOUND;\n}\n\n/* Function to get accessible parent. For toplevel, return NULL. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accParent(\n    TCL_UNUSED(IAccessible *), /* this */\n    IDispatch **ppdispParent)\n{\n    if (!ppdispParent) return E_INVALIDARG;\n    *ppdispParent = NULL;\n    return S_OK;\n}\n\n/* Function to get number of accessible children to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accChildCount(\n    IAccessible *this,\n    LONG *pcChildren)\n{\n    if (!pcChildren) return E_INVALIDARG;\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel) {\n\tTkGlobalUnlock();\n\t*pcChildren = 0;\n\treturn S_FALSE;\n    }\n    int count = TkAccChildCount(tkAccessible->toplevel);\n    TkGlobalUnlock();\n\n    *pcChildren = count < 0 ? 0 : count;\n    return S_OK;\n}\n\n/* Function to get accessible children to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accChild(\n    IAccessible *this,\n    VARIANT varChild,\n    IDispatch **ppdispChild)\n{\n    if (!ppdispChild) return E_INVALIDARG;\n    *ppdispChild = NULL;\n    if (varChild.vt != VT_I4 || varChild.lVal <= 0) return E_INVALIDARG;\n\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    ClearChildIdTableForToplevel(tkAccessible->toplevel);\n    int nextId = 1;\n    AssignChildIdsRecursive(tkAccessible->toplevel, &nextId, tkAccessible->interp, tkAccessible->toplevel);\n    Tk_Window childWin = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n    if (!childWin) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    TkGlobalUnlock();\n    return S_OK;\n}\n\n/* Function to get accessible frame to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_accLocation(\n    IAccessible *this,\n    LONG *pxLeft,\n    LONG *pyTop,\n    LONG *pcxWidth,\n    LONG *pcyHeight,\n    VARIANT varChild)\n{\n    if (!pxLeft || !pyTop || !pcxWidth || !pcyHeight) return E_INVALIDARG;\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel || !tkAccessible->hwnd) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\tRECT clientRect;\n\tGetClientRect(tkAccessible->hwnd, &clientRect);\n\tPOINT screenCoords = { clientRect.left, clientRect.top };\n\tMapWindowPoints(tkAccessible->hwnd, HWND_DESKTOP, &screenCoords, 1);\n\t*pxLeft = screenCoords.x;\n\t*pyTop = screenCoords.y;\n\t*pcxWidth = clientRect.right - clientRect.left;\n\t*pcyHeight = clientRect.bottom - clientRect.top;\n\tTkGlobalUnlock();\n\treturn S_OK;\n    }\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tRECT rect = { 0 };\n\tHRESULT hr = TkAccChild_GetRect(tkAccessible->interp, Tk_PathName(child), &rect);\n\tif (hr == S_OK) {\n\t    *pxLeft = rect.left;\n\t    *pyTop = rect.top;\n\t    *pcxWidth = rect.right - rect.left;\n\t    *pcyHeight = rect.bottom - rect.top;\n\t    TkGlobalUnlock();\n\t    return S_OK;\n\t}\n    }\n    TkGlobalUnlock();\n    return E_INVALIDARG;\n}\n\n/* Function to set accessible selection on Tk widget. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_accSelect(\n    TCL_UNUSED(IAccessible *), /* this */\n    TCL_UNUSED(long), /* flags */\n    TCL_UNUSED(VARIANT)) /* varChild */\n{\n    return E_NOTIMPL;\n}\n\n/* Function to return default action for role. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accDefaultAction(\n    IAccessible *this,\n    VARIANT varChild,\n    BSTR *pszDefaultAction)\n{\n    if (!pszDefaultAction) return E_INVALIDARG;\n    *pszDefaultAction = NULL;\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) return S_FALSE; /* Top-level window has no default action. */\n\n    VARIANT varRole;\n    VariantInit(&varRole);\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    HRESULT hr = tkAccessible->lpVtbl->get_accRole(this, varChild, &varRole);\n    if (FAILED(hr) || varRole.vt != VT_I4) {\n\tVariantClear(&varRole);\n\tTkGlobalUnlock();\n\treturn S_FALSE;\n    }\n    const wchar_t *action = NULL;\n    switch (varRole.lVal) {\n    case ROLE_SYSTEM_PUSHBUTTON:\n    case ROLE_SYSTEM_RADIOBUTTON:\n    case ROLE_SYSTEM_CHECKBUTTON:\n\taction = L\"Press\";\n\tbreak;\n    case ROLE_SYSTEM_TEXT:\n\taction = L\"Edit\";\n\tbreak;\n    case ROLE_SYSTEM_OUTLINE:\n    case ROLE_SYSTEM_TABLE:\n\taction = L\"Select\";\n\tbreak;\n    default:\n\tbreak;\n    }\n    VariantClear(&varRole);\n    if (action) {\n\t*pszDefaultAction = SysAllocString(action);\n\tTkGlobalUnlock();\n\treturn S_OK;\n    }\n    TkGlobalUnlock();\n    return S_FALSE;\n}\n\n\n/* Function to get button press to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_accDoDefaultAction(\n    TCL_UNUSED(IAccessible *), /* this */\n    VARIANT varChild)\n{\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) return S_OK;\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tmainThreadResult = E_FAIL;\n\tMainThreadFunc func = (MainThreadFunc)TkDoDefaultAction;\n\tint childId = varChild.lVal;\n\tRunOnMainThreadSync(func, 1, INT2PTR(childId));\n\treturn mainThreadResult;\n    }\n    return E_INVALIDARG;\n}\n\n/* Function to get accessible help to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accHelp(\n    IAccessible *this,\n    VARIANT varChild,\n    BSTR* pszHelp)\n{\n    if (!pszHelp) return E_INVALIDARG;\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tHRESULT hr = TkAccHelp(child, pszHelp);\n\tTkGlobalUnlock();\n\treturn hr;\n    }\n    TkGlobalUnlock();\n    return E_INVALIDARG;\n}\n\n/* Function to get accessible focus to MSAA. */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accFocus(\n    IAccessible *this,\n    VARIANT *pvarChild)\n{\n    if (!pvarChild) return E_INVALIDARG;\n    VariantInit(pvarChild);\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel || !tkAccessible->hwnd) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    HWND hwnd = tkAccessible->hwnd;\n    TkGlobalUnlock();\n    MainThreadFunc func = (MainThreadFunc)TkAccFocus;\n    RunOnMainThreadSync(func, 2, (void*)hwnd, (void*)pvarChild);\n    return S_OK;\n}\n\n/*\n * Function to get accessible description to MSAA.\n */\nstatic HRESULT STDMETHODCALLTYPE\nTkRootAccessible_get_accDescription(\n\tIAccessible *this,\n\tVARIANT varChild,\n\tBSTR *pszDescription)\n{\n    if (!pszDescription) return E_INVALIDARG;\n    TkGlobalLock();\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)this;\n    if (!tkAccessible->toplevel) {\n\tTkGlobalUnlock();\n\treturn E_INVALIDARG;\n    }\n    if (varChild.vt == VT_I4 && varChild.lVal == CHILDID_SELF) {\n\t*pszDescription = SysAllocString(L\"Window\");\n\tTkGlobalUnlock();\n\treturn S_OK;\n    }\n    if (varChild.vt == VT_I4 && varChild.lVal > 0) {\n\tTk_Window child = GetTkWindowForChildId(varChild.lVal, tkAccessible->toplevel);\n\tif (!child) {\n\t    TkGlobalUnlock();\n\t    return E_INVALIDARG;\n\t}\n\tHRESULT hr = TkAccDescription(child, pszDescription);\n\tTkGlobalUnlock();\n\treturn hr;\n    }\n    TkGlobalUnlock();\n    return E_INVALIDARG;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Glue functions - child widgets.\n *\n *----------------------------------------------------------------------\n */\n\n/* Function to map accessible role to MSAA. */\nstatic HRESULT\nTkAccRole(\n    Tk_Window win,\n    VARIANT *pvarRole)\n{\n    if (!win || !pvarRole) return E_INVALIDARG;\n    TkGlobalLock();\n\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\tTkGlobalUnlock();\n\treturn S_FALSE;\n    }\n\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n    if (!hPtr2) {\n\tTkGlobalUnlock();\n\treturn S_FALSE;\n    }\n\n    const char *tkrole = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n    LONG result = ROLE_SYSTEM_CLIENT; /* Fallback value */\n\n    for (int i = 0; roleMap[i].tkrole != NULL; i++) {\n\tif (strcmp(tkrole, roleMap[i].tkrole) == 0) {\n\t    result = roleMap[i].winrole;\n\t    break;\n\t}\n    }\n\n    pvarRole->vt = VT_I4;\n    pvarRole->lVal = result;\n\n    TkGlobalUnlock();\n    return S_OK;\n}\n\n/*\n * Helper function to get selected state on check/radiobuttons.\n */\n\nstatic void\nComputeAndCacheCheckedState(\n    Tk_Window win,\n    Tcl_Interp *interp)\n{\n    if (!win || !interp) {\n\treturn;\n    }\n\n    /* Look up accessibility attributes table for this window. */\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (!hPtr) {\n\treturn;\n    }\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n\n    /* Find role */\n    Tcl_HashEntry *rolePtr = Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n    const char *tkrole = NULL;\n    if (rolePtr) {\n\ttkrole = Tcl_GetString(Tcl_GetHashValue(rolePtr));\n    }\n    if (!tkrole) {\n\treturn;\n    }\n\n    /* Only handle check-like widgets */\n    if (strcmp(tkrole, \"Checkbutton\") != 0 &&\n\tstrcmp(tkrole, \"Radiobutton\") != 0 &&\n\tstrcmp(tkrole, \"Toggleswitch\") != 0) {\n\treturn;\n    }\n\n    int isChecked = 0;\n    const char *path = Tk_PathName(win);\n\n    /* Special-case: ttk::toggleswitch — ALWAYS use instate selected. */\n    if (strcmp(tkrole, \"Toggleswitch\") == 0) {\n\tTcl_Obj *stateCmd = Tcl_ObjPrintf(\"%s instate selected\", path);\n\tif (!stateCmd) return;\n\tTcl_IncrRefCount(stateCmd);\n\tif (Tcl_EvalObjEx(interp, stateCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t    const char *result = Tcl_GetStringResult(interp);\n\t    if (result && strcmp(result, \"1\") == 0) {\n\t\tisChecked = 1;\n\t    }\n\t}\n\tTcl_DecrRefCount(stateCmd);\n\n\t/* Proceed to cache/notify below. */\n\tgoto cache_and_notify;\n    }\n\n    /*\n\t * For Checkbutton and Radiobutton: prefer -variable based detection if present.\n     * Note: ttk widgets sometimes auto-create variables — but toggleswitch was handled above.\n     */\n\n    Tcl_Obj *varCmd = Tcl_ObjPrintf(\"%s cget -variable\", path);\n    if (!varCmd) return;\n    Tcl_IncrRefCount(varCmd);\n\n    const char *varName = NULL;\n    int haveVarName = 0;\n    if (Tcl_EvalObjEx(interp, varCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\tvarName = Tcl_GetStringResult(interp);\n\tif (varName && *varName) {\n\t    haveVarName = 1;\n\t}\n    } else {\n\t/* evaluation failed; clean up and return */\n\tTcl_DecrRefCount(varCmd);\n\treturn;\n    }\n    Tcl_DecrRefCount(varCmd);\n\n    if (haveVarName) {\n\t/* Grab the variable value (global). */\n\tconst char *varVal = Tcl_GetVar(interp, varName, TCL_GLOBAL_ONLY);\n\tif (varVal) {\n\t    /* Determine which cget to use: -onvalue for checkbutton, -value for radiobutton. */\n\t    Tcl_Obj *valueCmd = NULL;\n\t    if (strcmp(tkrole, \"Checkbutton\") == 0) {\n\t\tvalueCmd = Tcl_ObjPrintf(\"%s cget -onvalue\", path);\n\t    } else if (strcmp(tkrole, \"Radiobutton\") == 0) {\n\t\tvalueCmd = Tcl_ObjPrintf(\"%s cget -value\", path);\n\t    }\n\n\t    if (valueCmd) {\n\t\tTcl_IncrRefCount(valueCmd);\n\t\tconst char *onValue = NULL;\n\t\tif (Tcl_EvalObjEx(interp, valueCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t\t    onValue = Tcl_GetStringResult(interp);\n\t\t}\n\t\tTcl_DecrRefCount(valueCmd);\n\n\t\tif (onValue && varVal && strcmp(varVal, onValue) == 0) {\n\t\t    isChecked = 1;\n\t\t}\n\t    }\n\t} else {\n\t    /* variable exists but has no value — fall back to instate selected. */\n\t    Tcl_Obj *stateCmd = Tcl_ObjPrintf(\"%s instate selected\", path);\n\t    if (!stateCmd) return;\n\t    Tcl_IncrRefCount(stateCmd);\n\t    if (Tcl_EvalObjEx(interp, stateCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t\tconst char *result = Tcl_GetStringResult(interp);\n\t\tif (result && strcmp(result, \"1\") == 0) {\n\t\t    isChecked = 1;\n\t\t}\n\t    }\n\t    Tcl_DecrRefCount(stateCmd);\n\t}\n    } else {\n\t/* No variable: fall back to widget state (works for ttk and classic when variable not used). */\n\tTcl_Obj *stateCmd = Tcl_ObjPrintf(\"%s instate selected\", path);\n\tif (!stateCmd) return;\n\tTcl_IncrRefCount(stateCmd);\n\tif (Tcl_EvalObjEx(interp, stateCmd, TCL_EVAL_GLOBAL) == TCL_OK) {\n\t    const char *result = Tcl_GetStringResult(interp);\n\t    if (result && strcmp(result, \"1\") == 0) {\n\t\tisChecked = 1;\n\t    }\n\t}\n\tTcl_DecrRefCount(stateCmd);\n    }\n\ncache_and_notify:\n    /* Cache the checked state as a Tcl_Obj string \"0\" or \"1\" in AccessibleAttributes->\"value\". */\n    TkGlobalLock();\n    Tcl_HashEntry *valuePtr;\n    int newEntry;\n    valuePtr = Tcl_CreateHashEntry(AccessibleAttributes, \"value\", &newEntry);\n\n    char buf[2];\n    snprintf(buf, sizeof(buf), \"%d\", isChecked);\n    Tcl_Obj *valObj = Tcl_NewStringObj(buf, -1);\n    Tcl_IncrRefCount(valObj);\n\n    if (!newEntry) {\n\t/* Replace existing value: free previous Tcl_Obj if present. */\n\tTcl_Obj *old = (Tcl_Obj *)Tcl_GetHashValue(valuePtr);\n\tif (old) {\n\t    Tcl_DecrRefCount(old);\n\t}\n    }\n    Tcl_SetHashValue(valuePtr, valObj);\n    TkGlobalUnlock();\n\n    /* Notify MSAA about both value and state changes. */\n    {\n\tTk_Window toplevel = GetToplevelOfWidget(win);\n\tif (!toplevel) {\n\t    return;\n\t}\n\tTcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n\tLONG childId = GetChildIdForTkWindow(win, childIdTable);\n\tif (childId > 0) {\n\t    HWND hwnd = Tk_GetHWND(Tk_WindowId(toplevel));\n\t    NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, hwnd, OBJID_CLIENT, childId);\n\t    NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, childId);\n\t}\n    }\n}\n\n/* Function to map accessible state to MSAA. */\nstatic HRESULT\nTkAccState(\n    Tk_Window win,\n    VARIANT *pvarState)\n{\n    if (!win || !pvarState) {\n\treturn E_INVALIDARG;\n    }\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) {\n\treturn S_FALSE;\n    }\n    Tcl_HashTable *AccessibleAttributes = Tcl_GetHashValue(hPtr);\n\n    long state = STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_SELECTABLE; /* Reasonable default. */\n\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"state\");\n    if (hPtr2) {\n\tconst char *stateresult = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n\tif (strcmp(stateresult, \"disabled\") == 0) {\n\t    state = STATE_SYSTEM_UNAVAILABLE;\n\t}\n    }\n\n    /* Check for checked state using cached value. */\n    Tcl_HashEntry *rolePtr = Tcl_FindHashEntry(AccessibleAttributes, \"role\");\n    if (rolePtr) {\n\tconst char *tkrole = Tcl_GetString(Tcl_GetHashValue(rolePtr));\n\tif (strcmp(tkrole, \"Checkbutton\") == 0 ||\n\t    strcmp(tkrole, \"Radiobutton\") == 0 ||\n\t    strcmp(tkrole, \"Toggleswitch\") == 0) {\n\t    Tcl_HashEntry *valuePtr = Tcl_FindHashEntry(AccessibleAttributes, \"value\");\n\t    if (valuePtr) {\n\t\tconst char *value = Tcl_GetString(Tcl_GetHashValue(valuePtr));\n\t\tif (value && strcmp(value, \"1\") == 0) {\n\t\t    state |= STATE_SYSTEM_CHECKED;\n\t\t}\n\t    } else {\n\t    }\n\t}\n    }\n\n    TkWindow *focusPtr = TkGetFocusWin((TkWindow *)win);\n    if (focusPtr == (TkWindow *)win) {\n\tstate |= STATE_SYSTEM_FOCUSED;\n    }\n\n    pvarState->vt = VT_I4;\n    pvarState->lVal = state;\n    return S_OK;\n}\n\n/* Function to map accessible value to MSAA. */\nstatic HRESULT\nTkAccValue(\n    Tk_Window win,\n    BSTR *pValue)\n{\n    if (!win || !pValue) return E_INVALIDARG;\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) return S_FALSE;\n    Tcl_HashTable *AccessibleAttributes = Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"value\");\n    if (!hPtr2) return S_FALSE;\n    const char *val = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n    *pValue = SysAllocString(Tcl_UtfToWCharDString(val, -1, &ds));\n    Tcl_DStringFree(&ds);\n    return S_OK;\n}\n\n/* Event proc which calls the ActionEventProc procedure. */\nstatic int\nActionEventProc(\n    Tcl_Event *ev,\n    TCL_UNUSED(int)) /* flags */\n{\n    ActionEvent *event = (ActionEvent *)ev;\n    if (!event || !event->win || !event->command) return 1;\n    Tcl_Interp *interp = Tk_Interp(event->win);\n    if (!interp) return 1;\n    int code = Tcl_EvalEx(interp, event->command, -1, TCL_EVAL_GLOBAL);\n    if (code != TCL_OK) return TCL_ERROR;\n    Tcl_Free(event->command);\n    return 1;\n}\n\n/* Function to get button press to MSAA. */\nstatic void\nTkDoDefaultAction(\n    TCL_UNUSED(int), /* num_args */\n    void **args)\n{\n    int childId = (int)PTR2INT(args[0]);\n    ActionEvent *event = NULL;\n    if (!childId) {\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    TkGlobalLock();\n    Tk_Window toplevel = NULL;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entry;\n    for (entry = Tcl_FirstHashEntry(tkAccessibleTable, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) {\n\tTkRootAccessible *acc = (TkRootAccessible *)Tcl_GetHashValue(entry);\n\tTk_Window win = GetTkWindowForChildId(childId, acc->toplevel);\n\tif (win) {\n\t    toplevel = acc->toplevel;\n\t    break;\n\t}\n    }\n    if (!toplevel) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    Tk_Window win = GetTkWindowForChildId(childId, toplevel);\n    if (!win) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, (char *)win);\n    if (!hPtr) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    Tcl_HashTable *AccessibleAttributes = (Tcl_HashTable *)Tcl_GetHashValue(hPtr);\n    if (!AccessibleAttributes) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"action\");\n    if (!hPtr2) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    const char *action = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n    if (!action) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_INVALIDARG;\n\treturn;\n    }\n    event = (ActionEvent *)Tcl_Alloc(sizeof(ActionEvent));\n    if (event == NULL) {\n\tTkGlobalUnlock();\n\tmainThreadResult = E_OUTOFMEMORY;\n\treturn;\n    }\n    event->header.proc = ActionEventProc;\n    event->command = (char *)Tcl_Alloc(strlen(action) + 1);\n    strcpy(event->command, action);\n    event->win = win;\n\n    /* Update checked state and notify MSAA. */\n    ComputeAndCacheCheckedState(win, Tk_Interp(win));\n\n    TkGlobalUnlock();\n    Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);\n    mainThreadResult = S_OK;\n    return;\n}\n\n/* Function to get MSAA focus. */\nstatic void\nTkAccFocus(\n    TCL_UNUSED(int), /* num_args */\n    void **args)\n{\n    HWND hwnd = (HWND)args[0];\n    VARIANT *pvarChild = (VARIANT*)args[1];\n    if (!hwnd || !pvarChild) return;\n    Tk_Window win = Tk_HWNDToWindow(hwnd);\n    if (!win) return;\n    Tk_Window toplevel = GetToplevelOfWidget(win);\n    if (!toplevel) return;\n    TkWindow *focusPtr = TkGetFocusWin((TkWindow *)win);\n    Tk_Window focusWin = (Tk_Window)focusPtr;\n    if (!focusWin || focusWin == win) {\n\tpvarChild->vt = VT_I4;\n\tpvarChild->lVal = CHILDID_SELF;\n\treturn;\n    }\n    TkGlobalLock();\n    ClearChildIdTableForToplevel(toplevel);\n    int nextId = 1;\n    AssignChildIdsRecursive(toplevel, &nextId, Tk_Interp(win), toplevel);\n    int childId = GetChildIdForTkWindow(focusWin, GetChildIdTableForToplevel(toplevel));\n    TkGlobalUnlock();\n    if (childId > 0) {\n\tpvarChild->vt = VT_I4;\n\tpvarChild->lVal = childId;\n\treturn;\n    } else {\n\tpvarChild->vt = VT_I4;\n\tpvarChild->lVal = CHILDID_SELF;\n\treturn;\n    }\n}\n\n/* Function to get MSAA description. */\nstatic HRESULT\nTkAccDescription(\n    Tk_Window win,\n    BSTR *pDesc)\n{\n    if (!win || !pDesc) return E_INVALIDARG;\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) return S_FALSE;\n    Tcl_HashTable *AccessibleAttributes = Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"description\");\n    if (!hPtr2) return S_FALSE;\n    const char *desc = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n    *pDesc = SysAllocString(Tcl_UtfToWCharDString(desc, -1, &ds));\n    Tcl_DStringFree(&ds);\n    return S_OK;\n}\n\n/* Function to get MSAA help. */\nstatic HRESULT\nTkAccHelp(\n    Tk_Window win,\n    BSTR *pszHelp)\n{\n    if (!win || !pszHelp) return E_INVALIDARG;\n    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(TkAccessibilityObject, win);\n    if (!hPtr) return S_FALSE;\n    Tcl_HashTable *AccessibleAttributes = Tcl_GetHashValue(hPtr);\n    Tcl_HashEntry *hPtr2 = Tcl_FindHashEntry(AccessibleAttributes, \"help\");\n    if (!hPtr2) return S_FALSE;\n    const char *help = Tcl_GetString(Tcl_GetHashValue(hPtr2));\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n    *pszHelp = SysAllocString(Tcl_UtfToWCharDString(help, -1, &ds));\n    Tcl_DStringFree(&ds);\n    return S_OK;\n}\n\n/* Function to get number of child window objects. */\nstatic int\nTkAccChildCount(\n    Tk_Window win)\n{\n    if (!win) return -1;\n    int count = 0;\n    TkWindow *child = (TkWindow*)win;\n    Tk_Window toplevel = GetToplevelOfWidget(win);\n    if (!toplevel) return -1;\n    TkWindow *winPtr = (TkWindow *)toplevel;\n\n    /* Step through all child widgets of toplevel to get child count. */\n    for (child = winPtr->childList; child != NULL; child = child->nextPtr) {\n\tif (Tk_IsMapped(child)) count++;\n    }\n\n    return count;\n}\n\n/* Function to get child rect. */\nstatic HRESULT TkAccChild_GetRect(\n    Tcl_Interp *interp,\n    char *path,\n    RECT *rect)\n{\n    if (!interp || !path || !rect) return S_FALSE;\n    Tk_Window child = Tk_NameToWindow(interp, path, Tk_MainWindow(interp));\n    if (!child || !Tk_IsMapped(child)) return S_FALSE;\n    int x, y;\n    Tk_GetRootCoords(child, &x, &y);\n    int w = Tk_Width(child);\n    int h = Tk_Height(child);\n    rect->left = x;\n    rect->top = y;\n    rect->right = x + w;\n    rect->bottom = y + h;\n    return S_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * General/utility functions to help integrate the MSAA API to\n * the Tcl script-level API. We are using HWND's for toplevel windows\n * and unique childIDs for all accessible child widgets. We are using\n * several hash tables to maintain bidrectional mappings between widgets\n * and childIDs.\n *\n *----------------------------------------------------------------------\n */\n\n/* Function to map Tk window to MSAA attributes. */\nstatic TkRootAccessible *CreateRootAccessible(\n    Tcl_Interp *interp,\n    HWND hwnd,\n    const char *pathName)\n{\n    if (!interp || !hwnd || !pathName) {\n\tTcl_SetResult(interp, \"Invalid arguments to CreateRootAccessible\", TCL_STATIC);\n\treturn NULL;\n    }\n    Tk_Window win = Tk_NameToWindow(interp, pathName, Tk_MainWindow(interp));\n    if (!win) {\n\tTcl_SetResult(interp, \"Window not found\", TCL_STATIC);\n\treturn NULL;\n    }\n    if (!Tk_IsTopLevel(win)) {\n\tTcl_SetResult(interp, \"Window is not a toplevel\", TCL_STATIC);\n\treturn NULL;\n    }\n    Tk_MakeWindowExist(win);\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)Tcl_Alloc(sizeof(TkRootAccessible));\n    if (!tkAccessible) {\n\tTcl_SetResult(interp, \"Memory allocation failed for TkRootAccessible\", TCL_STATIC);\n\treturn NULL;\n    }\n    tkAccessible->pathName = (char *)Tcl_Alloc(strlen(pathName) + 1);\n    if (!tkAccessible->pathName) {\n\tTcl_Free(tkAccessible);\n\tTcl_SetResult(interp, \"Memory allocation failed for pathName\", TCL_STATIC);\n\treturn NULL;\n    }\n    strcpy(tkAccessible->pathName, pathName);\n    tkAccessible->lpVtbl = &tkRootAccessibleVtbl;\n    tkAccessible->interp = interp;\n    tkAccessible->hwnd = hwnd;\n    tkAccessible->refCount = 1;\n    tkAccessible->win = win;\n    tkAccessible->toplevel = win;\n    tkAccessible->children = NULL;\n    tkAccessible->numChildren = 0;\n    Tcl_HashEntry *entry;\n    int newEntry;\n    TkGlobalLock();\n    if (!tkAccessibleTableInitialized) {\n\tInitTkAccessibleTable();\n    }\n    entry = Tcl_CreateHashEntry(tkAccessibleTable, win, &newEntry);\n    Tcl_SetHashValue(entry, tkAccessible);\n    TkGlobalUnlock();\n    TkRootAccessible_AddRef((IAccessible*)tkAccessible);\n    NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CLIENT, CHILDID_SELF);\n    NotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CLIENT, CHILDID_SELF);\n    NotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF);\n    return tkAccessible;\n}\n\n/* Function to map Tk window to MSAA ID's. */\nstatic void SetChildIdForTkWindow(\n    Tk_Window win,\n    int id,\n    Tcl_HashTable *childIdTable)\n{\n    if (!win || !childIdTable) return;\n    Tcl_HashEntry *entry;\n    int newEntry;\n    TkGlobalLock();\n    entry = Tcl_CreateHashEntry(childIdTable, win, &newEntry);\n    Tcl_SetHashValue(entry, INT2PTR(id));\n    TkGlobalUnlock();\n}\n\n/* Function to retrieve MSAA ID for a specifc Tk window. */\nstatic int GetChildIdForTkWindow(\n    Tk_Window win,\n    Tcl_HashTable *childIdTable)\n{\n    if (!win || !childIdTable) return -1;\n    Tcl_HashEntry *entry;\n    TkGlobalLock();\n    entry = Tcl_FindHashEntry(childIdTable, win);\n    if (!entry) {\n\tTkGlobalUnlock();\n\treturn -1;\n    }\n    int id = (int)PTR2INT(Tcl_GetHashValue(entry));\n    TkGlobalUnlock();\n    return id;\n}\n\n/* Function to retrieve Tk window for a specifc MSAA ID. */\nTk_Window GetTkWindowForChildId(\n    int id,\n    Tk_Window toplevel)\n{\n    if (!toplevel) return NULL;\n    /*\n     * We are looking for a specific child ID within a specific toplevel,\n     * each one tracked separately in this hash table.\n     */\n    Tcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n    if (!childIdTable) return NULL;\n    Tcl_HashSearch search;\n    Tcl_HashEntry *entry;\n    TkGlobalLock();\n    for (entry = Tcl_FirstHashEntry(childIdTable, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) {\n\tif (PTR2INT(Tcl_GetHashValue(entry)) == id) {\n\t    Tk_Window win = (Tk_Window)Tcl_GetHashKey(childIdTable, entry);\n\t    TkGlobalUnlock();\n\t    return win;\n\t}\n    }\n    TkGlobalUnlock();\n    return NULL;\n}\n\n/* Function to get child ID table for a toplevel. We are using a separate table for each toplevel. */\nstatic Tcl_HashTable *GetChildIdTableForToplevel(\n    Tk_Window toplevel)\n{\n    if (!toplevel || !toplevelChildTables) return NULL;\n    Tcl_HashEntry *entry;\n    int newEntry;\n    Tcl_HashTable *childIdTable;\n    TkGlobalLock();\n    entry = Tcl_CreateHashEntry(toplevelChildTables, toplevel, &newEntry);\n    if (newEntry) {\n\tchildIdTable = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tif (!childIdTable) {\n\t    TkGlobalUnlock();\n\t    return NULL;\n\t}\n\tTcl_InitHashTable(childIdTable, TCL_ONE_WORD_KEYS);\n\tTcl_SetHashValue(entry, childIdTable);\n    } else {\n\tchildIdTable = (Tcl_HashTable *)Tcl_GetHashValue(entry);\n    }\n    TkGlobalUnlock();\n    return childIdTable;\n}\n\n/* Function to return the toplevel window that contains a given Tk widget. */\nTk_Window GetToplevelOfWidget(\n    Tk_Window tkwin)\n{\n    if (!tkwin) return NULL;\n    Tk_Window current = tkwin;\n    if (Tk_IsTopLevel(current)) return current;\n    while (current != NULL && Tk_WindowId(current) != None) {\n\tTk_Window parent = Tk_Parent(current);\n\tif (parent == NULL || Tk_IsTopLevel(current)) break;\n\tcurrent = parent;\n    }\n    return Tk_IsTopLevel(current) ? current : NULL;\n}\n\n/* Function to initialize Tk -> MSAA hash table. */\nvoid InitTkAccessibleTable(void)\n{\n    if (!tkAccessibleTableInitialized) {\n\ttkAccessibleTable = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tif (tkAccessibleTable) {\n\t    Tcl_InitHashTable(tkAccessibleTable, TCL_ONE_WORD_KEYS);\n\t    tkAccessibleTableInitialized = true;\n\t}\n    }\n}\n\n/* Function to initialize childId hash table. */\nvoid InitChildIdTable(void)\n{\n    if (!toplevelChildTables) {\n\ttoplevelChildTables = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));\n\tif (toplevelChildTables) {\n\t    Tcl_InitHashTable(toplevelChildTables, TCL_ONE_WORD_KEYS);\n\t}\n    }\n}\n\n/* Function to clear childId hash table for a toplevel. */\nvoid ClearChildIdTableForToplevel(\n\t\t\t\t  Tk_Window toplevel)\n{\n    if (!toplevel || !toplevelChildTables) return;\n    Tcl_HashEntry *entry = Tcl_FindHashEntry(toplevelChildTables, toplevel);\n    if (!entry) return;\n    Tcl_HashTable *childIdTable = (Tcl_HashTable *)Tcl_GetHashValue(entry);\n    Tcl_HashSearch search;\n    Tcl_HashEntry *childEntry;\n    TkGlobalLock();\n    for (childEntry = Tcl_FirstHashEntry(childIdTable, &search); childEntry != NULL; childEntry = Tcl_NextHashEntry(&search)) {\n\tTcl_DeleteHashEntry(childEntry);\n    }\n    Tcl_DeleteHashEntry(entry); /* Remove toplevel entry to prevent memory leaks. */\n    Tcl_Free(childIdTable);\n    TkGlobalUnlock();\n}\n\n/* Function to retrieve accessible object associated with Tk window. */\nTkRootAccessible *GetTkAccessibleForWindow(\n    Tk_Window win)\n{\n    if (!win || !tkAccessibleTableInitialized) return NULL;\n    Tcl_HashEntry *entry = Tcl_FindHashEntry(tkAccessibleTable, win);\n    if (entry) return (TkRootAccessible *)Tcl_GetHashValue(entry);\n    return NULL;\n}\n\n/* Function to assign childId's dynamically. */\nstatic void AssignChildIdsRecursive(\n    Tk_Window win,\n    int *nextId,\n    Tcl_Interp *interp,\n    Tk_Window toplevel)\n{\n    if (!win || !interp || !toplevel || !Tk_IsMapped(win)) {\n\treturn;\n    }\n    Tcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n    if (!childIdTable) {\n\treturn;\n    }\n    SetChildIdForTkWindow(win, *nextId, childIdTable);\n    (*nextId)++;\n\n    /* Initialize checked state for checkbuttons and radiobuttons. */\n    ComputeAndCacheCheckedState(win, interp);\n\n    TkWindow *winPtr = (TkWindow *)win;\n    for (TkWindow *child = winPtr->childList; child != NULL; child = child->nextPtr) {\n\tAssignChildIdsRecursive((Tk_Window)child, nextId, interp, toplevel);\n    }\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * Threading functions. These manage the integration of accessibility operations\n * on background threads and Tk execution on the main thread.\n *\n *----------------------------------------------------------------------\n */\n\n/* Handle WM_GETOBJECT call on main thread. */\nvoid HandleWMGetObjectOnMainThread(\n    TCL_UNUSED(int), /* num_args */\n    void **args)\n{\n    HWND hwnd = (HWND)args[0];\n    WPARAM wParam = (WPARAM)args[1];\n    LPARAM lParam = (LPARAM)args[2];\n    LRESULT *outResult = (LRESULT *)args[3];\n    if (outResult) *outResult = 0;\n\n    Tk_Window tkwin = Tk_HWNDToWindow(hwnd);\n\n    /* Handle MSAA requests. */\n    if ((LONG)lParam == OBJID_CLIENT) {\n\tTkRootAccessible *msaaProvider = GetTkAccessibleForWindow(tkwin);\n\tif (!msaaProvider) {\n\t    Tcl_Interp *interp = Tk_Interp(tkwin);\n\t    if (!interp) return;\n\n\t    msaaProvider = CreateRootAccessible(interp, hwnd, Tk_PathName(tkwin));\n\t    if (msaaProvider) {\n\t\tTkRootAccessible_RegisterForCleanup(tkwin, msaaProvider);\n\t    }\n\t}\n\n\tif (msaaProvider && outResult) {\n\t    *outResult = LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)msaaProvider);\n\t}\n    }\n}\n\n/* Event handler that executes on main thread. */\nint ExecuteOnMainThreadSync(\n    Tcl_Event *ev,\n    TCL_UNUSED(int)) /*flags */\n{\n    MainThreadSyncEvent *event = (MainThreadSyncEvent *)ev;\n    if (!event) return 1;\n    switch(event->num_args) {\n    case 0: event->func(0, NULL); break;\n    case 1: event->func(1, event->args); break;\n    case 2: event->func(2, event->args); break;\n    case 3: event->func(3, event->args); break;\n    case 4: event->func(4, event->args); break;\n    case 5: event->func(5, event->args); break;\n    }\n    SetEvent(event->doneEvent);\n    Tcl_Free(event);\n    return 1;\n}\n\n/* Synchronous execution with variable arguments. */\nvoid RunOnMainThreadSync(\n    MainThreadFunc func,\n    int num_args, ...)\n{\n    if (Tcl_GetCurrentThread() == mainThreadId) {\n\tvoid *args[6];\n\tva_list ap;\n\tva_start(ap, num_args);\n\tfor (int i = 0; i < num_args; i++) {\n\t    args[i] = va_arg(ap, void*);\n\t}\n\tva_end(ap);\n\tfunc(num_args, args);\n\treturn;\n    }\n    MainThreadSyncEvent *event = (MainThreadSyncEvent *)Tcl_Alloc(sizeof(MainThreadSyncEvent));\n    if (!event) return;\n    event->header.proc = ExecuteOnMainThreadSync;\n    event->func = func;\n    event->num_args = num_args;\n    event->doneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\n    if (!event->doneEvent) {\n\tTcl_Free(event);\n\treturn;\n    }\n    va_list ap;\n    va_start(ap, num_args);\n    for (int i = 0; i < num_args; i++) {\n\tevent->args[i] = va_arg(ap, void*);\n    }\n    va_end(ap);\n    Tcl_ThreadQueueEvent(mainThreadId, (Tcl_Event *)event, TCL_QUEUE_TAIL);\n    Tcl_ThreadAlert(mainThreadId);\n    DWORD result = WaitForSingleObject(event->doneEvent, 500);\n    if (result == WAIT_TIMEOUT) {\n\tCloseHandle(event->doneEvent);\n\tTcl_Free(event);\n    }\n    CloseHandle(event->doneEvent);\n}\n\n/* Initialize during Tcl startup. */\nvoid InitAccessibilityMainThread(void)\n{\n    mainThreadId = Tcl_GetCurrentThread();\n}\n\n/* Initiate global thread lock. */\nBOOL CALLBACK InitGlobalLockOnce(\n    TCL_UNUSED(PINIT_ONCE), /* InitOnce */\n    TCL_UNUSED(PVOID), /* param */\n    TCL_UNUSED(PVOID *)) /* Context */\n{\n    InitializeCriticalSection(&TkGlobalLock);\n    return TRUE;\n}\n\n/* Wrapper for global thread lock. */\nvoid EnsureGlobalLockInitialized(void)\n{\n    InitOnceExecuteOnce(&TkInitOnce, InitGlobalLockOnce, NULL, NULL);\n}\n\n/*\n * Functions to implement direct script-level\n * Tcl commands.\n */\n\n/*\n *----------------------------------------------------------------------\n *\n * IsScreenReaderRunning --\n *\n * Runtime check to see if screen reader is running.\n *\n * Results:\n *    Returns if screen reader is active or not.\n *\n * Side effects:\n *    None.\n *\n *----------------------------------------------------------------------\n */\nint IsScreenReaderRunning(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size), /* objc */\n    TCL_UNUSED(Tcl_Obj *const *)) /* objv */\n{\n    BOOL screenReader = FALSE;\n\n    /* First check the system-wide flag (covers NVDA, JAWS, etc.) */\n    SystemParametersInfo(SPI_GETSCREENREADER, 0, &screenReader, 0);\n\n    if (!screenReader) {\n\t/* Fallback: explicitly check for Narrator.exe */\n\tHANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n\tif (hSnapshot != INVALID_HANDLE_VALUE) {\n\t    PROCESSENTRY32 pe;\n\t    pe.dwSize = sizeof(PROCESSENTRY32);\n\t    if (Process32First(hSnapshot, &pe)) {\n\t\tdo {\n\t\t    if (_tcsicmp(pe.szExeFile, TEXT(\"Narrator.exe\")) == 0) {\n\t\t\tscreenReader = TRUE;\n\t\t\tbreak;\n\t\t    }\n\t\t} while (Process32Next(hSnapshot, &pe));\n\t    }\n\t    CloseHandle(hSnapshot);\n\t}\n    }\n\n    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(screenReader));\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * EmitSelectionChanged --\n *\n * Accessibility system notification when selection changed.\n *\n * Results:\n *    Accessibility system is made aware when a selection is changed.\n *\n * Side effects:\n *    None.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int EmitSelectionChanged(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *ip,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(ip, 1, objv, \"window?\");\n\treturn TCL_ERROR;\n    }\n\n    Tk_Window path = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));\n    if (!path) {\n\tTcl_SetResult(ip, \"Invalid window name\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    Tk_Window toplevel = GetToplevelOfWidget(path);\n    if (!toplevel || !Tk_IsTopLevel(toplevel)) {\n\tTcl_SetResult(ip, \"Window must be in a toplevel\", TCL_STATIC);\n\treturn TCL_ERROR;\n    }\n\n    Tk_MakeWindowExist(path);\n\n    /* Update checked state. */\n    ComputeAndCacheCheckedState(path, ip);\n\n    TkGlobalLock();\n    Tcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n    LONG childId = GetChildIdForTkWindow(path, childIdTable);\n\n    if (childId > 0) {\n\tHWND hwnd = Tk_GetHWND(Tk_WindowId(toplevel));\n\n\t/* Send comprehensive notifications for Narrator compatibility. */\n\tNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, hwnd, OBJID_CLIENT, childId);\n\tNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, childId);\n\tNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, childId);\n\tNotifyWinEvent(EVENT_OBJECT_SELECTION, hwnd, OBJID_CLIENT, childId);\n    }\n\n    TkGlobalUnlock();\n    return TCL_OK;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * TkRootAccessible_RegisterForCleanup --\n *\n * Register event handler for destroying accessibility element.\n *\n * Results:\n *      Event handler is registered.\n *\n * Side effects:\n *    None.\n *\n *----------------------------------------------------------------------\n */\nvoid TkRootAccessible_RegisterForCleanup(\n    Tk_Window tkwin,\n    void *tkAccessible)\n{\n    if (!tkwin || !tkAccessible) return;\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask, TkRootAccessible_DestroyHandler, tkAccessible);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkRootAccessible_DestroyHandler --\n *\n * Clean up accessibility element structures when window is destroyed.\n *\n * Results:\n *    Accessibility element is deallocated.\n *\n * Side effects:\n *    None.\n *\n *----------------------------------------------------------------------\n */\nstatic void TkRootAccessible_DestroyHandler(\n    void *clientData,\n    XEvent *eventPtr)\n{\n    if (!clientData|| eventPtr->type != DestroyNotify) return;\n    TkRootAccessible *tkAccessible = (TkRootAccessible *)clientData;\n    if (!tkAccessible || !tkAccessible->toplevel) return;\n    TkGlobalLock();\n\n    /* Clean up MSAA table. */\n    if (tkAccessibleTableInitialized) {\n\tTcl_HashEntry *entry = Tcl_FindHashEntry(tkAccessibleTable, tkAccessible->toplevel);\n\tif (entry) {\n\t    Tcl_DeleteHashEntry(entry);\n\t}\n    }\n\n    ClearChildIdTableForToplevel(tkAccessible->toplevel);\n    TkRootAccessible_Release((IAccessible *)tkAccessible);\n    TkGlobalUnlock();\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * EmitFocusChanged --\n *\n * Accessibility system notification when focus changed.\n *\n * Results:\n *    Accessibility system is made aware when focus is changed.\n *\n * Side effects:\n *    None.\n *\n *----------------------------------------------------------------------\n */\nstatic int EmitFocusChanged(\n    TCL_UNUSED(void *), /* cd */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    const char *path = Tcl_GetString(objv[1]);\n    Tk_Window win = Tk_NameToWindow(interp, path, Tk_MainWindow(interp));\n    if (!win) {\n\tTcl_SetResult(interp, \"Invalid window name\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    Tk_MakeWindowExist(win);\n    Tk_Window toplevel = GetToplevelOfWidget(win);\n    if (!toplevel || !Tk_IsTopLevel(toplevel)) {\n\tTcl_SetResult(interp, \"Window must be in a toplevel\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    TkGlobalLock();\n    Tcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n    if (!childIdTable) {\n\tTcl_SetResult(interp, \"Failed to get child ID table for toplevel\", TCL_STATIC);\n\tTkGlobalUnlock();\n\treturn TCL_OK;\n    }\n    ClearChildIdTableForToplevel(toplevel);\n    int nextId = 1;\n    AssignChildIdsRecursive(toplevel, &nextId, interp, toplevel);\n    LONG childId = GetChildIdForTkWindow(win, childIdTable);\n    if (childId <= 0) {\n\tTcl_AppendResult(interp, \"Failed to find child ID for \", path, (char *)NULL);\n\tTkGlobalUnlock();\n\treturn TCL_OK;\n    }\n    NotifyWinEvent(EVENT_OBJECT_FOCUS, Tk_GetHWND(Tk_WindowId(toplevel)), OBJID_CLIENT, childId);\n    TkGlobalUnlock();\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkRootAccessibleObjCmd --\n *\n *    Main command for adding and managing accessibility objects to Tk\n *    widgets on Windows using the Microsoft Active Accessibility API.\n *\n * Results:\n *      A standard Tcl result.\n *\n * Side effects:\n *    Tk widgets are now accessible to screen readers.\n *\n *----------------------------------------------------------------------\n */\nint TkRootAccessibleObjCmd(\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    char *windowName = Tcl_GetString(objv[1]);\n    Tk_Window tkwin = Tk_NameToWindow(interp, windowName, Tk_MainWindow(interp));\n    if (!tkwin) {\n\tTcl_SetResult(interp, \"Invalid window name\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    Tk_Window toplevel = GetToplevelOfWidget(tkwin);\n    if (!toplevel || !Tk_IsTopLevel(toplevel)) {\n\tTcl_SetResult(interp, \"Window must be a toplevel\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    Tk_MakeWindowExist(toplevel);\n    HWND hwnd = Tk_GetHWND(Tk_WindowId(toplevel));\n    if (!hwnd) {\n\tTcl_SetResult(interp, \"Failed to get HWND for toplevel\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    TkGlobalLock();\n    TkRootAccessible *accessible = CreateRootAccessible(interp, hwnd, windowName);\n    if (!accessible) {\n\tTkGlobalUnlock();\n\tTcl_SetResult(interp, \"Unable to create accessible object\", TCL_STATIC);\n\treturn TCL_OK;\n    }\n    TkRootAccessible_RegisterForCleanup(toplevel, accessible);\n    Tcl_HashTable *childIdTable = GetChildIdTableForToplevel(toplevel);\n    if (!childIdTable) {\n\tTkRootAccessible_Release((IAccessible *)accessible);\n\tTcl_SetResult(interp, \"Failed to create child ID table for toplevel\", TCL_STATIC);\n\tTkGlobalUnlock();\n\treturn TCL_OK;\n    }\n    ClearChildIdTableForToplevel(toplevel);\n    int nextId = 1;\n    AssignChildIdsRecursive(toplevel, &nextId, interp, toplevel);\n    TkGlobalUnlock();\n    return TCL_OK;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkWinAccessiblity_Init --\n *\n *    Initializes the accessibility module.\n *\n * Results:\n *      A standard Tcl result.\n *\n * Side effects:\n *    Accessibility module is now activated.\n *\n *----------------------------------------------------------------------\n */\nint TkWinAccessiblity_Init(\n    Tcl_Interp *interp)\n{\n    /* Initialize global lock, hash tables, and main thread. */\n    EnsureGlobalLockInitialized();\n    TkGlobalLock();\n    InitAccessibilityMainThread();\n    InitTkAccessibleTable();\n    InitChildIdTable();\n    TkGlobalUnlock();\n\n    /* Initialize Tcl commands. */\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::add_acc_object\", TkRootAccessibleObjCmd, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_selection_change\", EmitSelectionChanged, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::emit_focus_change\", EmitFocusChanged, NULL, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::accessible::check_screenreader\", IsScreenReaderRunning, NULL, NULL);\n    return TCL_OK;\n}\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinButton.c",
    "content": "/*\n * tkWinButton.c --\n *\n *\tThis file implements the Windows specific portion of the button\n *\twidgets.\n *\n * Copyright © 1996-1998 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#define OEMRESOURCE\n#include \"tkWinInt.h\"\n#include \"tkButton.h\"\n\n/*\n * These macros define the base style flags for the different button types.\n */\n\n#define LABEL_STYLE (BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS)\n#define PUSH_STYLE  (LABEL_STYLE | BS_PUSHBUTTON)\n#define CHECK_STYLE (LABEL_STYLE | BS_CHECKBOX)\n#define RADIO_STYLE (LABEL_STYLE | BS_RADIOBUTTON)\n\n/*\n * Declaration of Windows specific button structure.\n */\n\ntypedef struct WinButton {\n    TkButton info;\t\t/* Generic button info. */\n    WNDPROC oldProc;\t\t/* Old window procedure. */\n    HWND hwnd;\t\t\t/* Current window handle. */\n    Pixmap pixmap;\t\t/* Bitmap for rendering the button. */\n    DWORD style;\t\t/* Window style flags. */\n} WinButton;\n\n/*\n * Cached information about the checkbutton and radiobutton indicator boxes\n */\n\ntypedef struct {\n    bool initialized;\n    int boxSize;\t\t/* Width & height of the box. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Data of the SVG images used for drawing the indicators\n */\n\nstatic const char checkbtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v15h1v-14h14v-1z' fill='#a0a0a0'/>\\n\\\n     <path d='m1 1v13h1v-12h12v-1z' fill='#696969'/>\\n\\\n     <path d='m14 1v13h-13v1h14v-14z' fill='#e3e3e3'/>\\n\\\n     <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\\n\\\n     <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char checkbtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <path d='m0 0v15h1v-14h14v-1z' fill='#a0a0a0'/>\\n\\\n     <path d='m1 1v13h1v-12h12v-1z' fill='#696969'/>\\n\\\n     <path d='m14 1v13h-13v1h14v-14z' fill='#e3e3e3'/>\\n\\\n     <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\\n\\\n     <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\\n\\\n     <path d='m4.5 8 3 3 4-6' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnOffData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradientOuter' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#a0a0a0' offset='0'/>\\n\\\n       <stop stop-color='#eeeeee' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n      <linearGradient id='linearGradientInner' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#696969' offset='0'/>\\n\\\n       <stop stop-color='#e3e3e3' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradientOuter)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='url(#linearGradientInner)'/>\\n\\\n     <circle cx='8' cy='8' r='6' fill='#ffffff'/>\\n\\\n    </svg>\";\n\nstatic const char radiobtnOnData[] = \"\\\n    <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\\n\\\n     <defs>\\n\\\n      <linearGradient id='linearGradientOuter' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#a0a0a0' offset='0'/>\\n\\\n       <stop stop-color='#eeeeee' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n      <linearGradient id='linearGradientInner' x1='5' y1='5' x2='11' y2='11' gradientUnits='userSpaceOnUse'>\\n\\\n       <stop stop-color='#696969' offset='0'/>\\n\\\n       <stop stop-color='#e3e3e3' offset='1'/>\\n\\\n      </linearGradient>\\n\\\n     </defs>\\n\\\n     <circle cx='8' cy='8' r='8' fill='url(#linearGradientOuter)'/>\\n\\\n     <circle cx='8' cy='8' r='7' fill='url(#linearGradientInner)'/>\\n\\\n     <circle cx='8' cy='8' r='6' fill='#ffffff'/>\\n\\\n     <circle cx='8' cy='8' r='3' fill='#000000'/>\\n\\\n    </svg>\";\n\n/*\n * Declarations for functions defined in this file.\n */\n\nstatic LRESULT CALLBACK\tButtonProc(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam);\nstatic Window\t\tCreateProc(Tk_Window tkwin, Window parent,\n\t\t\t    void *instanceData);\nstatic void\t\tInitBoxes(Tk_Window tkwin);\nstatic void\t\tColorToStr(COLORREF color, char *colorStr);\nstatic void\t\tImageChanged(void *clientData,\n\t\t\t    int x, int y, int width, int height,\n\t\t\t    int imageWidth, int imageHeight);\nstatic void\t\tTkpDrawIndicator(TkButton *butPtr, Drawable d,\n\t\t\t    Tk_3DBorder border, GC gc, int dim, int x, int y);\n\n/*\n * The class procedure table for the button widgets.\n */\n\nconst Tk_ClassProcs tkpButtonProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    TkButtonWorldChanged,\t/* worldChangedProc */\n    CreateProc,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitBoxes --\n *\n *\tThis function computes the size of the checkbutton and radiobutton\n *\tindicator boxes, according to the display's scaling percentage.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPopulates the thread-private data.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitBoxes(Tk_Window tkwin)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    double scalingLevel = TkScalingLevel(tkwin);\n\n    tsdPtr->boxSize = (int)(16.0 * scalingLevel);\n    tsdPtr->initialized = true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpButtonSetDefaults --\n *\n *\tThis procedure is invoked before option tables are created for\n *\tbuttons. It modifies some of the default values to match the current\n *\tvalues defined for this platform.\n *\n * Results:\n *\tSome of the default values in *specPtr are modified.\n *\n * Side effects:\n *\tUpdates some of.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpButtonSetDefaults(void)\n{\n    int width = GetSystemMetrics(SM_CXEDGE);\n\tif (width > 0) {\n\t    snprintf(tkDefButtonBorderWidth, sizeof(tkDefButtonBorderWidth), \"%d\", width);\n\t}\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateButton --\n *\n *\tAllocate a new TkButton structure.\n *\n * Results:\n *\tReturns a newly allocated TkButton structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkButton *\nTkpCreateButton(\n    TCL_UNUSED(Tk_Window))\n{\n    WinButton *butPtr;\n\n    butPtr = (WinButton *)Tcl_Alloc(sizeof(WinButton));\n    butPtr->hwnd = NULL;\n    return (TkButton *) butPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateProc --\n *\n *\tThis function creates a new Button control, subclasses the instance,\n *\tand generates a new Window object.\n *\n * Results:\n *\tReturns the newly allocated Window object, or None on failure.\n *\n * Side effects:\n *\tCauses a new Button control to come into existence.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Window\nCreateProc(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Window parentWin,\t\t/* Parent of new window. */\n    void *instanceData)\t\t/* Button instance data. */\n{\n    Window window;\n    HWND parent;\n    LPCWSTR windowClass;\n    WinButton *butPtr = (WinButton *)instanceData;\n\n    parent = Tk_GetHWND(parentWin);\n    if (butPtr->info.type == TYPE_LABEL) {\n\twindowClass = L\"STATIC\";\n\tbutPtr->style = SS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;\n    } else {\n\twindowClass = L\"BUTTON\";\n\tbutPtr->style = BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;\n    }\n    butPtr->hwnd = CreateWindowW(windowClass, NULL, butPtr->style,\n\t    Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),\n\t    parent, NULL, Tk_GetHINSTANCE(), NULL);\n    SetWindowPos(butPtr->hwnd, HWND_TOP, 0, 0, 0, 0,\n\t\t    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n    butPtr->oldProc = (WNDPROC)SetWindowLongPtrW(butPtr->hwnd, GWLP_WNDPROC,\n\t    (LONG_PTR) ButtonProc);\n\n    window = Tk_AttachHWND(tkwin, butPtr->hwnd);\n    return window;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyButton --\n *\n *\tFree data structures associated with the button control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the default control state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyButton(\n    TkButton *butPtr)\n{\n    WinButton *winButPtr = (WinButton *)butPtr;\n    HWND hwnd = winButPtr->hwnd;\n\n    if (hwnd) {\n\tSetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) winButPtr->oldProc);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ColorToStr --\n *\n *\tWrites a given color to a string, in the format \"RRGGBB\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the content of the memory area pointed to by the 2nd argument.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nColorToStr(\n    COLORREF color,\t/* specifies a color */\n    char *colorStr)\t/* memory area to which the color is to be\n\t\t\t   output in the format \"RRGGBB\" */\n{\n    snprintf(colorStr, 7, \"%02x%02x%02x\",\n\t     GetRValue(color), GetGValue(color), GetBValue(color));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageChanged --\n *\n *\tDummy function to be passed to Tk_GetImage().\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nImageChanged(\n    void *clientData,\n    int x, int y, int width, int height,\n    int imageWidth, int imageHeight)\n{\n    (void)clientData;\n    (void)x; (void)y; (void)width; (void)height;\n    (void)imageWidth; (void)imageHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawIndicator -\n *\n *      Draws the indicator image in the drawable at the (x,y) location.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      An image is drawn in the drawable at the given location.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkpDrawIndicator(\n    TkButton *butPtr,\t\t/* checkbutton or radiobutton */\n    Drawable d,\t\t\t/* what to draw on */\n    Tk_3DBorder border,\t\t/* colors of the border */\n    GC gc,\t\t\t/* graphics context */\n    int dim,\t\t\t/* width & height of the indicator */\n    int x, int y)\t\t/* where to draw */\n{\n    Tk_Window tkwin = butPtr->tkwin;\n    char topOuterColorStr[7], btmOuterColorStr[7], topInnerColorStr[7],\n\t btmInnerColorStr[7], interiorColorStr[7], checkColorStr[7];\n    Tcl_Interp *interp = Tk_Interp(tkwin);\n    char imgName[80];\n    Tk_Image img;\n    const char *svgDataPtr;\n    size_t svgDataLen;\n    char *svgDataCopy;\n    char *topOuterColorPtr, *btmOuterColorPtr, *topInnerColorPtr,\n\t *btmInnerColorPtr, *interiorColorPtr, *checkColorPtr;\n    const char *cmdFmt;\n    size_t scriptSize;\n    char *script;\n    int code;\n\n    /*\n     * Construct the color strings topOuterColorStr, btmOuterColorStr,\n     * topInnerColorStr, btmInnerColorStr, interiorColorStr, and checkColorStr\n     */\n\n    ColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_DARK_GC),\n\t       topOuterColorStr);\n    ColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT_GC),\n\t       btmOuterColorStr);\n    ColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_DARK2),\n\t       topInnerColorStr);\n    ColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT2),\n\t       btmInnerColorStr);\n\n    if (butPtr->state == STATE_ACTIVE) {\n\tColorToStr(TkWinGetBorderPixels(tkwin, butPtr->activeBorder,\n\t\t   TK_3D_FLAT_GC), interiorColorStr);\n    } else if (butPtr->state == STATE_DISABLED || (butPtr->flags & TRISTATED)) {\n\tColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT2),\n\t\t   interiorColorStr);\n    } else if (butPtr->selectBorder != NULL) {\n\tColorToStr(TkWinGetBorderPixels(tkwin, butPtr->selectBorder,\n\t\t   TK_3D_FLAT_GC), interiorColorStr);\n    } else {\n\tColorToStr(GetSysColor(COLOR_WINDOW), interiorColorStr);\n    }\n\n    if (butPtr->state == STATE_DISABLED && butPtr->disabledFg == NULL) {\n\tColorToStr(TkWinGetBorderPixels(tkwin, border, TK_3D_DARK_GC),\n\t\t   checkColorStr);\n    } else {\n\tColorToStr(gc->foreground, checkColorStr);\n    }\n\n    /*\n    * Check whether there is an SVG image of this size for the indicator's\n    * type (0 = checkbtn, 1 = radiobtn) and these color strings\n    */\n\n    snprintf(imgName, sizeof(imgName),\n\t     \"::tk::icons::indicator%d_%d_%s_%s_%s_%s_%s_%s\",\n\t     dim, butPtr->type == TYPE_RADIO_BUTTON,\n\t     topOuterColorStr, btmOuterColorStr, topInnerColorStr,\n\t     btmInnerColorStr, interiorColorStr,\n\t     (butPtr->flags & (SELECTED|TRISTATED)) ? checkColorStr : \"XXXXXX\");\n    img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    if (img == NULL) {\n\t/*\n\t * Determine the SVG data to use for the photo image\n\t */\n\n\tif (butPtr->type == TYPE_CHECK_BUTTON) {\n\t    svgDataPtr = ((butPtr->flags & (SELECTED|TRISTATED)) ?\n\t\t\t  checkbtnOnData : checkbtnOffData);\n\t} else {\n\t    svgDataPtr = ((butPtr->flags & (SELECTED|TRISTATED)) ?\n\t\t\t  radiobtnOnData : radiobtnOffData);\n\t}\n\n\t/*\n\t * Copy the string pointed to by svgDataPtr to\n\t * a newly allocated memory area svgDataCopy\n\t */\n\n\tsvgDataLen = strlen(svgDataPtr);\n\tsvgDataCopy = (char *)Tcl_AttemptAlloc(svgDataLen + 1);\n\tif (svgDataCopy == NULL) {\n\t    return;\n\t}\n\tmemcpy(svgDataCopy, svgDataPtr, svgDataLen);\n\tsvgDataCopy[svgDataLen] = '\\0';\n\n\t/*\n\t * Update the colors within svgDataCopy\n\t */\n\n\ttopOuterColorPtr = strstr(svgDataCopy, \"a0a0a0\");\n\tbtmOuterColorPtr = strstr(svgDataCopy, \"eeeeee\");\n\ttopInnerColorPtr = strstr(svgDataCopy, \"696969\");\n\tbtmInnerColorPtr = strstr(svgDataCopy, \"e3e3e3\");\n\tinteriorColorPtr = strstr(svgDataCopy, \"ffffff\");\n\tcheckColorPtr =    strstr(svgDataCopy, \"000000\");\n\n\tassert(topOuterColorPtr);\n\tassert(btmOuterColorPtr);\n\tassert(topInnerColorPtr);\n\tassert(btmInnerColorPtr);\n\tassert(interiorColorPtr);\n\n\tmemcpy(topOuterColorPtr, topOuterColorStr, 6);\n\tmemcpy(btmOuterColorPtr, btmOuterColorStr, 6);\n\tmemcpy(topInnerColorPtr, topInnerColorStr, 6);\n\tmemcpy(btmInnerColorPtr, btmInnerColorStr, 6);\n\tmemcpy(interiorColorPtr, interiorColorStr, 6);\n\tif (checkColorPtr != NULL) {\n\t    memcpy(checkColorPtr, checkColorStr, 6);\n\t}\n\n\t/*\n\t * Create an SVG photo image from svgDataCopy\n\t */\n\n\tcmdFmt = \"image create photo %s -format $::tk::svgFmt -data {%s}\";\n\tscriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen;\n\tscript = (char *)Tcl_AttemptAlloc(scriptSize);\n\tif (script == NULL) {\n\t    Tcl_Free(svgDataCopy);\n\t    return;\n\t}\n\tsnprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy);\n\tTcl_Free(svgDataCopy);\n\tcode = Tcl_EvalEx(interp, script, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tTcl_Free(script);\n\tif (code != TCL_OK) {\n\t    Tcl_BackgroundException(interp, code);\n\t    return;\n\t}\n\timg = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL);\n    }\n\n    /*\n     * Display the image\n     */\n\n    Tk_RedrawImage(img, 0, 0, dim, dim, d, x, y);\n    Tk_FreeImage(img);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayButton --\n *\n *\tThis procedure is invoked to display a button widget. It is normally\n *\tinvoked as an idle handler.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen. The REDRAW_PENDING flag is cleared.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayButton(\n    void *clientData)\t/* Information about widget. */\n{\n    TkWinDCState state;\n    HDC dc;\n    TkButton *butPtr = (TkButton *)clientData;\n    GC gc;\n    Tk_3DBorder border;\n    Pixmap pixmap;\n    int x = 0;\t\t\t/* Initialization only needed to stop compiler\n\t\t\t\t * warning. */\n    int y, relief;\n    Tk_Window tkwin = butPtr->tkwin;\n    int width = 0, height = 0, haveImage = 0, haveText = 0, drawRing = 0;\n    int defaultWidth;\t\t/* Width of default ring. */\n    int offset;\t\t\t/* 0 means this is a label widget. 1 means it\n\t\t\t\t * is a flavor of button, so we offset the\n\t\t\t\t * text to make the button appear to move up\n\t\t\t\t * and down as the relief changes. */\n    int textXOffset = 0, textYOffset = 0;\n\t\t\t\t/* Text offsets for use with compound buttons\n\t\t\t\t * and focus ring. */\n    int imageWidth, imageHeight;\n    int imageXOffset = 0, imageYOffset = 0;\n\t\t\t\t/* Image information that will be used to\n\t\t\t\t * restrict disabled pixmap as well. */\n    int padX, padY, borderWidth, highlightWidth;\n\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    butPtr->flags &= ~REDRAW_PENDING;\n    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, tkwin, butPtr->padYObj, &padY);\n\n    border = butPtr->normalBorder;\n    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {\n\tgc = butPtr->disabledGC;\n    } else if ((butPtr->state == STATE_ACTIVE)\n\t    && !Tk_StrictMotif(butPtr->tkwin)) {\n\tgc = butPtr->activeTextGC;\n\tborder = butPtr->activeBorder;\n    } else {\n\tgc = butPtr->normalTextGC;\n    }\n    if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)\n\t    && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {\n\tborder = butPtr->selectBorder;\n    }\n\n    /*\n     * Override the relief specified for the button if this is a checkbutton\n     * or radiobutton and there's no indicator. The new relief is as follows:\n     *      If the button is select  --> \"sunken\"\n     *      If relief==overrelief    --> relief\n     *      Otherwise                --> overrelief\n     *\n     * The effect we are trying to achieve is as follows:\n     *\n     *      value    mouse-over?   -->   relief\n     *     -------  ------------        --------\n     *       off        no               flat\n     *       off        yes              raised\n     *       on         no               sunken\n     *       on         yes              sunken\n     *\n     * This is accomplished by configuring the checkbutton or radiobutton like\n     * this:\n     *\n     *     -indicatoron 0 -overrelief raised -offrelief flat\n     *\n     * Bindings (see library/button.tcl) will copy the -overrelief into\n     * -relief on mouseover. Hence, we can tell if we are in mouse-over by\n     * comparing relief against overRelief. This is an aweful kludge, but it\n     * gives use the desired behavior while keeping the code backwards\n     * compatible.\n     */\n\n    relief = butPtr->relief;\n    if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {\n\tif (butPtr->flags & SELECTED) {\n\t    relief = TK_RELIEF_SUNKEN;\n\t} else if (butPtr->overRelief != relief) {\n\t    relief = butPtr->offRelief;\n\t}\n    }\n\n    /*\n     * Compute width of default ring and offset for pushed buttons.\n     */\n\n    if (butPtr->type == TYPE_LABEL) {\n\tdefaultWidth = highlightWidth;\n\toffset = 0;\n    } else if (butPtr->type == TYPE_BUTTON) {\n\tdefaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE)\n\t\t? highlightWidth : 0);\n\toffset = 1;\n    } else {\n\tdefaultWidth = 0;\n\tif ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {\n\t    offset = 1;\n\t} else {\n\t    offset = 0;\n\t}\n    }\n\n    /*\n     * In order to avoid screen flashes, this procedure redraws the button in\n     * a pixmap, then copies the pixmap to the screen in a single operation.\n     * This means that there's no point in time where the on-sreen image has\n     * been cleared.\n     */\n\n    pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),\n\t    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));\n    Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),\n\t    Tk_Height(tkwin), 0, TK_RELIEF_FLAT);\n\n    /*\n     * Display image or bitmap or text for button.\n     */\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &width, &height);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);\n\thaveImage = 1;\n    }\n    imageWidth = width;\n    imageHeight = height;\n\n    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);\n\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tint fullWidth = 0, fullHeight = 0;\n\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_TOP) {\n\t\ttextYOffset = height + padY;\n\t    } else {\n\t\timageYOffset = butPtr->textHeight + padY;\n\t    }\n\t    fullHeight = height + butPtr->textHeight + padY;\n\t    fullWidth = (width > butPtr->textWidth ? width :\n\t\t    butPtr->textWidth);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    break;\n\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\t    /*\n\t     * Image is left or right of text.\n\t     */\n\n\t    if (butPtr->compound == COMPOUND_LEFT) {\n\t\ttextXOffset = width + padX;\n\t    } else {\n\t\timageXOffset = butPtr->textWidth + padX;\n\t    }\n\t    fullWidth = butPtr->textWidth + padX + width;\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    fullWidth = (width > butPtr->textWidth ? width :\n\t\t    butPtr->textWidth);\n\t    fullHeight = (height > butPtr->textHeight ? height :\n\t\t    butPtr->textHeight);\n\t    textXOffset = (fullWidth - butPtr->textWidth)/2;\n\t    imageXOffset = (fullWidth - width)/2;\n\t    textYOffset = (fullHeight - butPtr->textHeight)/2;\n\t    imageYOffset = (fullHeight - height)/2;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n\tTkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\tbutPtr->indicatorSpace + fullWidth, fullHeight, &x, &y);\n\tx += butPtr->indicatorSpace;\n\n\tif (relief == TK_RELIEF_SUNKEN) {\n\t    x += offset;\n\t    y += offset;\n\t}\n\timageXOffset += x;\n\timageYOffset += y;\n\tif (butPtr->image != NULL) {\n\t    if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {\n\t\tTk_RedrawImage(butPtr->selectImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else if ((butPtr->tristateImage != NULL)\n\t\t    && (butPtr->flags & TRISTATED)) {\n\t\tTk_RedrawImage(butPtr->tristateImage, 0, 0,\n\t\t\twidth, height, pixmap, imageXOffset, imageYOffset);\n\t    } else {\n\t\tTk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,\n\t\t\timageXOffset, imageYOffset);\n\t    }\n\t} else {\n\t    XSetClipOrigin(butPtr->display, gc, imageXOffset, imageYOffset);\n\t    XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc,\n\t\t    0, 0, (unsigned int) width, (unsigned int) height,\n\t\t    imageXOffset, imageYOffset, 1);\n\t    XSetClipOrigin(butPtr->display, gc, 0, 0);\n\t}\n\tif ((butPtr->state == STATE_DISABLED) &&\n\t\t(butPtr->disabledFg != NULL)) {\n\t    COLORREF oldFgColor = gc->foreground;\n\n\t    if (gc->background == GetSysColor(COLOR_BTNFACE)) {\n\t\tgc->foreground = GetSysColor(COLOR_3DHILIGHT);\n\t\tTk_DrawTextLayout(butPtr->display, pixmap, gc,\n\t\t    butPtr->textLayout, x + textXOffset + 1,\n\t\t    y + textYOffset + 1, 0, -1);\n\t\tTk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\t    butPtr->textLayout, x + textXOffset + 1,\n\t\t    y + textYOffset + 1,\n\t\t    butPtr->underline);\n\t\tgc->foreground = oldFgColor;\n\t    }\n\t}\n\n\tTk_DrawTextLayout(butPtr->display, pixmap, gc,\n\t\tbutPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1);\n\tTk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\tbutPtr->textLayout, x + textXOffset, y + textYOffset,\n\t\tbutPtr->underline);\n\theight = fullHeight;\n\tdrawRing = 1;\n    } else {\n\tif (haveImage) {\n\t    TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,\n\t\t    butPtr->indicatorSpace + width, height, &x, &y);\n\t    x += butPtr->indicatorSpace;\n\n\t    if (relief == TK_RELIEF_SUNKEN) {\n\t\tx += offset;\n\t\ty += offset;\n\t    }\n\t    imageXOffset += x;\n\t    imageYOffset += y;\n\t    if (butPtr->image != NULL) {\n\t\tif ((butPtr->selectImage != NULL) &&\n\t\t\t(butPtr->flags & SELECTED)) {\n\t\t    Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height,\n\t\t\t    pixmap, imageXOffset, imageYOffset);\n\t\t} else if ((butPtr->tristateImage != NULL) &&\n\t\t\t(butPtr->flags & TRISTATED)) {\n\t\t    Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height,\n\t\t\t    pixmap, imageXOffset, imageYOffset);\n\t\t} else {\n\t\t    Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,\n\t\t\t    imageXOffset, imageYOffset);\n\t\t}\n\t    } else {\n\t\tXSetClipOrigin(butPtr->display, gc, x, y);\n\t\tXCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,\n\t\t\t(unsigned int) width, (unsigned int) height, x, y, 1);\n\t\tXSetClipOrigin(butPtr->display, gc, 0, 0);\n\t    }\n\t} else {\n\t    TkComputeAnchor(butPtr->anchor, tkwin, padX, padY,\n\t\t    butPtr->indicatorSpace + butPtr->textWidth,\n\t\t    butPtr->textHeight,\t&x, &y);\n\n\t    x += butPtr->indicatorSpace;\n\n\t    if (relief == TK_RELIEF_SUNKEN) {\n\t\tx += offset;\n\t\ty += offset;\n\t    }\n\t    if ((butPtr->state == STATE_DISABLED) &&\n\t\t    (butPtr->disabledFg != NULL)) {\n\t\tCOLORREF oldFgColor = gc->foreground;\n\t\tif (gc->background == GetSysColor(COLOR_BTNFACE)) {\n\t\t    gc->foreground = GetSysColor(COLOR_3DHILIGHT);\n\t\t    Tk_DrawTextLayout(butPtr->display, pixmap, gc,\n\t\t\t    butPtr->textLayout, x + 1, y + 1, 0, -1);\n\t\t    Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\t\t    butPtr->textLayout, x + 1, y + 1, butPtr->underline);\n\t\t    gc->foreground = oldFgColor;\n\t\t}\n\t    }\n\t    Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,\n\t\t    x, y, 0, -1);\n\t    Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,\n\t\t    butPtr->textLayout, x, y, butPtr->underline);\n\n\t    height = butPtr->textHeight;\n\t    drawRing = 1;\n\t}\n    }\n\n    /*\n     * Draw the focus ring. If this is a push button then we need to put it\n     * around the inner edge of the border, otherwise we put it around the\n     * text. The text offsets are only non-zero when this is a compound\n     * button.\n     */\n\n    if (drawRing && butPtr->flags & GOT_FOCUS && butPtr->type != TYPE_LABEL) {\n\tif (butPtr->type == TYPE_BUTTON || !butPtr->indicatorOn) {\n\t    int dottedWidth = borderWidth + 1 + defaultWidth;\n\t    TkWinDrawDottedRect(butPtr->display, pixmap, gc->foreground,\n\t\t    dottedWidth, dottedWidth,\n\t\t    Tk_Width(tkwin) - 2*dottedWidth,\n\t\t    Tk_Height(tkwin) - 2*dottedWidth);\n\t} else {\n\t    TkWinDrawDottedRect(butPtr->display, pixmap, gc->foreground,\n\t\t    x-1 + textXOffset, y-1 + textYOffset,\n\t\t    butPtr->textWidth + 2, butPtr->textHeight + 3);\n\t}\n    }\n\n    y += height/2;\n\n    /*\n     * Draw the indicator for check buttons and radio buttons. At this point\n     * x and y refer to the top-left corner of the text or image or bitmap.\n     */\n\n    if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn\n\t    && tsdPtr->initialized) {\n\tx -= butPtr->indicatorSpace;\n\ty -= butPtr->indicatorDiameter / 2;\n\n\tTkpDrawIndicator(butPtr, pixmap, border, gc, tsdPtr->boxSize, x, y + 1);\n    }\n\n    /*\n     * If the button is disabled with a stipple rather than a special\n     * foreground color, generate the stippled effect. If the widget is\n     * selected and we use a different background color when selected, must\n     * temporarily modify the GC so the stippling is the right color.\n     */\n\n    if ((butPtr->state == STATE_DISABLED)\n\t    && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {\n\tif ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t&& (butPtr->selectBorder != NULL)) {\n\t    XSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t    Tk_3DBorderColor(butPtr->selectBorder)->pixel);\n\t}\n\n\t/*\n\t * Stipple the whole button if no disabledFg was specified, otherwise\n\t * restrict stippling only to displayed image\n\t */\n\n\tif (butPtr->disabledFg == NULL) {\n\t    XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0,\n\t\t    (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin));\n\t} else {\n\t    XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,\n\t\t    imageXOffset, imageYOffset,\n\t\t    (unsigned) imageWidth, (unsigned) imageHeight);\n\t}\n\tif ((butPtr->flags & SELECTED) && !butPtr->indicatorOn\n\t\t&& (butPtr->selectBorder != NULL)) {\n\t    XSetForeground(butPtr->display, butPtr->stippleGC,\n\t\t    Tk_3DBorderColor(butPtr->normalBorder)->pixel);\n\t}\n    }\n\n    /*\n     * Draw the border and traversal highlight last. This way, if the button's\n     * contents overflow they'll be covered up by the border.\n     */\n\n    if (relief != TK_RELIEF_FLAT) {\n\tTk_Draw3DRectangle(tkwin, pixmap, border,\n\t\tdefaultWidth, defaultWidth,\n\t\tTk_Width(tkwin) - 2 * defaultWidth,\n\t\tTk_Height(tkwin) - 2 * defaultWidth,\n\t\tborderWidth, relief);\n    }\n    if (defaultWidth != 0) {\n\tint highlightColor;\n\n\tdc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);\n\tif (butPtr->type == TYPE_LABEL) {\n\t    highlightColor = (int) Tk_3DBorderColor(butPtr->highlightBorder)->pixel;\n\t} else {\n\t    highlightColor = (int) butPtr->highlightColorPtr->pixel;\n\t}\n\tTkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth,\n\t\thighlightColor);\n\tTkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin),\n\t\thighlightColor);\n\tTkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth,\n\t\tTk_Width(tkwin), defaultWidth,\n\t\thighlightColor);\n\tTkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0,\n\t\tdefaultWidth, Tk_Height(tkwin),\n\t\thighlightColor);\n\tTkWinReleaseDrawableDC(pixmap, dc, &state);\n    }\n\n    if (butPtr->flags & GOT_FOCUS) {\n\tTk_SetCaretPos(tkwin, x, y, 0 /* not used */);\n    }\n\n    /*\n     * Copy the information from the off-screen pixmap onto the screen, then\n     * delete the pixmap.\n     */\n\n    XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),\n\t    butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),\n\t    (unsigned) Tk_Height(tkwin), 0, 0);\n    Tk_FreePixmap(butPtr->display, pixmap);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeButtonGeometry --\n *\n *\tAfter changes in a button's text or bitmap, this procedure recomputes\n *\tthe button's geometry and passes this information along to the\n *\tgeometry manager for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe button's window may change size.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeButtonGeometry(\n    TkButton *butPtr)\t/* Button whose geometry may have changed. */\n{\n    int txtWidth, txtHeight;\t/* Width and height of text */\n    int imgWidth, imgHeight;\t/* Width and height of image */\n    int width = 0, height = 0;\t/* Width and height of button */\n    int haveImage, haveText;\n    int avgWidth;\n    int minWidth;\n    /* Vertical and horizontal dialog units size in pixels. */\n    double vDLU, hDLU;\n    Tk_FontMetrics fm;\n    int borderWidth, highlightWidth, wrapLength;\n    int butPtrWidth, butPtrHeight;\n    int padX, padY;\n\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->highlightWidthObj, &highlightWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->borderWidthObj, &borderWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->wrapLengthObj, &wrapLength);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->widthObj, &butPtrWidth);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->heightObj, &butPtrHeight);\n\n    butPtr->inset = highlightWidth + borderWidth;\n    butPtr->indicatorSpace = 0;\n\n    if (!tsdPtr->initialized) {\n\tInitBoxes(butPtr->tkwin);\n    }\n\n    /*\n     * Figure out image metrics.\n     */\n\n    if (butPtr->image != NULL) {\n\tTk_SizeOfImage(butPtr->image, &imgWidth, &imgHeight);\n\thaveImage = 1;\n    } else if (butPtr->bitmap != None) {\n\tTk_SizeOfBitmap(butPtr->display, butPtr->bitmap,\n\t\t&imgWidth, &imgHeight);\n\thaveImage = 1;\n    } else {\n\timgWidth = 0;\n\timgHeight = 0;\n\thaveImage = 0;\n    }\n\n    /*\n     * Figure out font metrics (even if we don't have text because we need\n     * DLUs (based on font, not text) for some spacing calculations below).\n     */\n\n    Tk_FreeTextLayout(butPtr->textLayout);\n    butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,\n\t    Tcl_GetString(butPtr->textPtr), TCL_INDEX_NONE, wrapLength,\n\t    butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);\n\n    txtWidth = butPtr->textWidth;\n    txtHeight = butPtr->textHeight;\n    haveText = (*(Tcl_GetString(butPtr->textPtr)) != '\\0');\n    avgWidth = (Tk_TextWidth(butPtr->tkfont,\n\t    \"abcdefghijklmnopqurstuvwzyABCDEFGHIJKLMNOPQURSTUVWZY\",\n\t    52) + 26) / 52;\n    Tk_GetFontMetrics(butPtr->tkfont, &fm);\n\n    /*\n     * Compute dialog units for layout calculations.\n     */\n\n    hDLU = avgWidth / 4.0;\n    vDLU = fm.linespace / 8.0;\n\n    /*\n     * First, let's try to compute button size \"by the book\" (See \"Microsoft\n     * Windows User Experience\" (ISBN 0-7356-0566-1), Chapter 14 - Visual\n     * Design, Section 4 - Layout (page 448)).\n     *\n     * Note, that Tk \"buttons\" are Microsoft \"Command buttons\", Tk\n     * \"checkbuttons\" are Microsoft \"check boxes\", Tk \"radiobuttons\" are\n     * Microsoft \"option buttons\", and Tk \"labels\" are Microsoft \"text\n     * labels\".\n     */\n\n    /*\n     * Set width and height by button type; See User Experience table, p449.\n     * These are text-based measurements, even if the text is \"\". If there is\n     * an image, height will get set again later.\n     */\n\n    switch (butPtr->type) {\n    case TYPE_BUTTON:\n\t/*\n\t * First compute the minimum width of the button in characters. MWUE\n\t * says that the button should be 50 DLUs. We allow 6 DLUs padding\n\t * left and right. (There is no rule but this is consistent with the\n\t * fact that button text is 8 DLUs high and buttons are 14 DLUs high.)\n\t *\n\t * The width is specified in characters. A character is, by\n\t * definition, 4 DLUs wide. 11 char * 4 DLU is 44 DLU + 6 DLU padding\n\t * = 50 DLU. Therefore, width = -11 -> MWUE compliant buttons.\n\t */\n\n\tif (butPtrWidth < 0) {\n\t    minWidth = -(butPtrWidth);\t    /* Min width in chars */\n\t    width = avgWidth * minWidth;\t    /* Allow for characters */\n\t    width += (int)(0.5 + (6 * hDLU));\t    /* Add for padding */\n\t}\n\n\t/*\n\t * If shrink-wrapping was requested (width = 0) or if the text is\n\t * wider than the default button width, adjust the button width up to\n\t * suit.\n\t */\n\n\tif (butPtrWidth == 0\n\t\t|| (txtWidth + (int)(0.5 + (6 * hDLU)) > width)) {\n\t    width = txtWidth + (int)(0.5 + (6 * hDLU));\n\t}\n\n\t/*\n\t * The User Experience says 14 DLUs. Since text is, by definition, 8\n\t * DLU/line, this allows for multi-line text while working perfectly\n\t * for single-line text.\n\t */\n\n\theight = txtHeight + (int)(0.5 + (6 * vDLU));\n\n\t/*\n\t * The above includes 6 DLUs of padding which should include defaults\n\t * of 1 pixel of highlightwidth, 2 pixels of borderwidth, 1 pixel of\n\t * padding and 1 pixel of extra inset on each side. Those will be\n\t * added later so reduce width and height now to compensate.\n\t */\n\n\twidth -= 10;\n\theight -= 10;\n\n\tif (!haveImage) {\n\t    /*\n\t     * Extra inset for the focus ring.\n\t     */\n\n\t    butPtr->inset += 1;\n\t}\n\tbreak;\n\n    case TYPE_LABEL:\n\t/*\n\t * The User Experience says, \"as wide as needed\".\n\t */\n\n\twidth = txtWidth;\n\n\t/*\n\t * The User Experience says, \"8 (DLUs) per line of text\". Since text\n\t * is, by definition, 8 DLU/line, this allows for multi-line text\n\t * while working perfectly for single-line text.\n\t */\n\n\tif (txtHeight) {\n\t    height = txtHeight;\n\t} else {\n\t    /*\n\t     * If there's no text, we want the height to be one linespace.\n\t     */\n\t    height = fm.linespace;\n\t}\n\tbreak;\n\n    case TYPE_RADIO_BUTTON:\n    case TYPE_CHECK_BUTTON: {\n\t/*\n\t * See note for TYPE_LABEL.\n\t */\n\n\twidth = txtWidth;\n\n\t/*\n\t * The User Experience says 10 DLUs. (Is that one DLU above and below\n\t * for the focus ring?) See note above about multi-line text and 8\n\t * DLU/line.\n\t */\n\n\theight = txtHeight + (int)(0.5 + (2.0 * vDLU));\n\n\t/*\n\t * The above includes 2 DLUs of padding which should include defaults\n\t * of 1 pixel of highlightwidth, 0 pixels of borderwidth, and 1 pixel\n\t * of padding on each side. Those will be added later so reduce height\n\t * now to compensate.\n\t */\n\n\theight -= 4;\n\n\t/*\n\t * Extra inset for the focus ring.\n\t */\n\tbutPtr->inset += 1;\n\tbreak;\n    }\n    }/* switch */\n\n    /*\n     * At this point, the width and height are correct for a Tk text button,\n     * excluding padding and inset, but we have to allow for compound buttons.\n     * The image may be above, below, left, or right of the text.\n     */\n\n    /*\n     * If the button is compound (i.e., it shows both an image and text), the\n     * new geometry is a combination of the image and text geometry. We only\n     * honor the compound bit if the button has both text and an image,\n     * because otherwise it is not really a compound button.\n     */\n\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padXObj, &padX);\n    Tk_GetPixelsFromObj(NULL, butPtr->tkwin, butPtr->padYObj, &padY);\n\n    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {\n\tswitch ((enum compound) butPtr->compound) {\n\tcase COMPOUND_TOP:\n\tcase COMPOUND_BOTTOM:\n\t    /*\n\t     * Image is above or below text.\n\t     */\n\n\t    if (imgWidth > width) {\n\t\twidth = imgWidth;\n\t    }\n\t    height += imgHeight + padY;\n\t    break;\n\n\tcase COMPOUND_LEFT:\n\tcase COMPOUND_RIGHT:\n\n\t    /*\n\t     * Image is left or right of text.\n\t     *\n\t     * Only increase width of button if image doesn't fit in slack\n\t     * space of default button width\n\t     */\n\n\t    if ((imgWidth + txtWidth + padX) > width) {\n\t\twidth = imgWidth + txtWidth + padX;\n\t    }\n\n\t    if (imgHeight > height) {\n\t\theight = imgHeight;\n\t    }\n\t    break;\n\n\tcase COMPOUND_CENTER:\n\t    /*\n\t     * Image and text are superimposed.\n\t     */\n\n\t    if (imgWidth > width) {\n\t\twidth = imgWidth;\n\t    }\n\t    if (imgHeight > height) {\n\t\theight = imgHeight;\n\t    }\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t} /* switch */\n\n\t/*\n\t * Fix up for minimum width.\n\t */\n\n\tif (butPtrWidth < 0) {\n\t    /*\n\t     * minWidth in pixels (because there's an image.\n\t     */\n\n\t    minWidth = -(butPtrWidth);\n\t    if (width < minWidth) {\n\t\twidth = minWidth;\n\t    }\n\t} else if (butPtrWidth > 0) {\n\t    width = butPtrWidth;\n\t}\n\n\tif (butPtrHeight > 0) {\n\t    height = butPtrHeight;\n\t}\n\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    } else if (haveImage) {\n\tif (butPtrWidth > 0) {\n\t    width = butPtrWidth;\n\t} else {\n\t    width = imgWidth;\n\t}\n\tif (butPtrHeight > 0) {\n\t    height = butPtrHeight;\n\t} else {\n\t    height = imgHeight;\n\t}\n    } else {\n\t/*\n\t * No image. May or may not be text. May or may not be compound.\n\t */\n\n\t/*\n\t * butPtr->width is in characters. We need to allow for that many\n\t * characters on the face, not in the over-all button width\n\t */\n\n\tif (butPtrWidth > 0) {\n\t    width = butPtrWidth * avgWidth;\n\t}\n\n\t/*\n\t * butPtr->height is in lines of text. We need to allow for that many\n\t * lines on the face, not in the over-all button height.\n\t */\n\n\tif (butPtrHeight > 0) {\n\t    height = butPtrHeight * fm.linespace;\n\n\t    /*\n\t     * Make the same adjustments as above to get same height for e.g.\n\t     * a one line text with -height 0 or 1. [Bug #565485]\n\t     */\n\n\t    switch (butPtr->type) {\n\t    case TYPE_BUTTON: {\n\t\theight += (int)(0.5 + (6 * vDLU)) - 10;\n\t\tbreak;\n\t    }\n\t    case TYPE_RADIO_BUTTON:\n\t    case TYPE_CHECK_BUTTON: {\n\t\theight += (int)(0.5 + (2.0 * vDLU)) - 4;\n\t\tbreak;\n\t    }\n\t    }\n\t}\n\n\twidth += 2 * padX;\n\theight += 2 * padY;\n    }\n\n    /*\n     * Fix up width and height for indicator sizing and spacing.\n     */\n\n    if (butPtr->type == TYPE_RADIO_BUTTON\n\t    || butPtr->type == TYPE_CHECK_BUTTON) {\n\tif (butPtr->indicatorOn) {\n\t    butPtr->indicatorDiameter = tsdPtr->boxSize;\n\n\t    /*\n\t     * Make sure we can see the whole indicator, even if the text or\n\t     * image is very small.\n\t     */\n\n\t    if (height < butPtr->indicatorDiameter) {\n\t\theight = butPtr->indicatorDiameter;\n\t    }\n\n\t    /*\n\t     * There is no rule for space between the indicator and the text\n\t     * (the two are atomic on 'Windows) but the User Experience page\n\t     * 451 says leave 3 hDLUs between \"text labels and their\n\t     * associated controls\".\n\t     */\n\n\t    butPtr->indicatorSpace = butPtr->indicatorDiameter +\n\t\t    (int)(0.5 + (3.0 * hDLU));\n\t    width += butPtr->indicatorSpace;\n\t}\n    }\n\n    /*\n     * Inset is always added to the size.\n     */\n\n    width += 2 * butPtr->inset;\n    height += 2 * butPtr->inset;\n\n    Tk_GeometryRequest(butPtr->tkwin, width, height);\n    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ButtonProc --\n *\n *\tThis function is called by Windows whenever an event occurs on a\n *\tbutton control created by Tk.\n *\n * Results:\n *\tStandard Windows return value.\n *\n * Side effects:\n *\tMay generate events.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nButtonProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    LRESULT result;\n    WinButton *butPtr;\n    Tk_Window tkwin = Tk_HWNDToWindow(hwnd);\n\n    if (tkwin == NULL) {\n\tTcl_Panic(\"ButtonProc called on an invalid HWND\");\n    }\n    butPtr = (WinButton *)((TkWindow*)tkwin)->instanceData;\n\n    switch(message) {\n    case WM_ERASEBKGND:\n\treturn 0;\n\n    case BM_GETCHECK:\n\tif (((butPtr->info.type == TYPE_CHECK_BUTTON)\n\t\t|| (butPtr->info.type == TYPE_RADIO_BUTTON))\n\t\t&& butPtr->info.indicatorOn) {\n\t    return (butPtr->info.flags & SELECTED)\n\t\t    ? BST_CHECKED : BST_UNCHECKED;\n\t}\n\treturn 0;\n\n    case BM_GETSTATE: {\n\tDWORD state = 0;\n\n\tif (((butPtr->info.type == TYPE_CHECK_BUTTON)\n\t\t|| (butPtr->info.type == TYPE_RADIO_BUTTON))\n\t\t&& butPtr->info.indicatorOn) {\n\t    state = (butPtr->info.flags & SELECTED)\n\t\t    ? BST_CHECKED : BST_UNCHECKED;\n\t}\n\tif (butPtr->info.flags & GOT_FOCUS) {\n\t    state |= BST_FOCUS;\n\t}\n\treturn state;\n    }\n    case WM_ENABLE:\n\tbreak;\n\n    case WM_PAINT: {\n\tPAINTSTRUCT ps;\n\tBeginPaint(hwnd, &ps);\n\tEndPaint(hwnd, &ps);\n\tTkpDisplayButton(butPtr);\n\n\t/*\n\t * Special note: must cancel any existing idle handler for\n\t * TkpDisplayButton; it's no longer needed, and TkpDisplayButton\n\t * cleared the REDRAW_PENDING flag.\n\t */\n\n\tTcl_CancelIdleCall(TkpDisplayButton, butPtr);\n\treturn 0;\n    }\n    case BN_CLICKED: {\n\t/*\n\t * OOPS: chromium fires WM_NULL regularly to ping if plugin is still\n\t * alive. When using an external window (i.e. via the tcl plugin), this\n\t * causes all buttons to fire once a second, so we need to make sure\n\t * that we are not dealing with the chromium life check.\n\t*/\n\tif (wParam != 0 || lParam != 0) {\n\t    int code;\n\t    Tcl_Interp *interp = butPtr->info.interp;\n\n\t    if (butPtr->info.state != STATE_DISABLED) {\n\t\tTcl_Preserve(interp);\n\t\tcode = TkInvokeButton((TkButton*)butPtr);\n\t\tif (code != TCL_OK && code != TCL_CONTINUE\n\t\t\t&& code != TCL_BREAK) {\n\t\t    Tcl_AddErrorInfo(interp, \"\\n    (button invoke)\");\n\t\t    Tcl_BackgroundException(interp, code);\n\t\t}\n\t\tTcl_Release(interp);\n\t    }\n\t    Tcl_ServiceAll();\n\t    return 0;\n\t}\n    }\n    /* FALLTHRU */\n    default:\n\tif (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {\n\t    return result;\n\t}\n    }\n    return DefWindowProcW(hwnd, message, wParam, lParam);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinClipboard.c",
    "content": "/*\n * tkWinClipboard.c --\n *\n *\tThis file contains functions for managing the clipboard.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkSelect.h\"\n#include <shlobj.h>    /* for DROPFILES */\n\nstatic void\t\tUpdateClipboard(HWND hwnd);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelGetSelection --\n *\n *\tRetrieve the specified selection from another process. For now, only\n *\tfetching XA_STRING from CLIPBOARD is supported. Eventually other types\n *\tshould be allowed.\n *\n * Results:\n *\tThe return value is a standard Tcl return value. If an error occurs\n *\t(such as no selection exists) then an error message is left in the\n *\tinterp's result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkSelGetSelection(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for reporting errors. */\n    Tk_Window tkwin,\t\t/* Window on whose behalf to retrieve the\n\t\t\t\t * selection (determines display from which to\n\t\t\t\t * retrieve). */\n    Atom selection,\t\t/* Selection to retrieve. */\n    Atom target,\t\t/* Desired form in which selection is to be\n\t\t\t\t * returned. */\n    Tk_GetSelProc *proc,\t/* Procedure to call to process the selection,\n\t\t\t\t * once it has been retrieved. */\n    void *clientData)\t/* Arbitrary value to pass to proc. */\n{\n    char *data, *destPtr;\n    Tcl_DString ds;\n    HGLOBAL handle;\n    Tcl_Encoding encoding;\n    int result, locale, noBackslash = 0;\n\n    if ((selection != Tk_InternAtom(tkwin, \"CLIPBOARD\"))\n\t    || (target != XA_STRING)) {\n\tgoto error;\n    }\n    if (!OpenClipboard(NULL)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"clipboard cannot be opened, another application grabbed it\"));\n\tTcl_SetErrorCode(interp, \"TK\", \"CLIPBOARD\", \"BUSY\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Attempt to get the data in Unicode form if available as this is less\n     * work that CF_TEXT.\n     */\n\n    result = TCL_ERROR;\n    if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {\n\thandle = GetClipboardData(CF_UNICODETEXT);\n\tif (!handle) {\n\t    CloseClipboard();\n\t    goto error;\n\t}\n\tdata = (char *)GlobalLock(handle);\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString((WCHAR *)data, wcslen((WCHAR *)data), &ds);\n\tGlobalUnlock(handle);\n    } else if (IsClipboardFormatAvailable(CF_TEXT)) {\n\t/*\n\t * Determine the encoding to use to convert this text.\n\t */\n\n\tif (IsClipboardFormatAvailable(CF_LOCALE)) {\n\t    handle = GetClipboardData(CF_LOCALE);\n\t    if (!handle) {\n\t\tCloseClipboard();\n\t\tgoto error;\n\t    }\n\n\t    /*\n\t     * Get the locale identifier, determine the proper code page to\n\t     * use, and find the corresponding encoding.\n\t     */\n\n\t    Tcl_DStringInit(&ds);\n\t    Tcl_DStringAppend(&ds, \"cp######\", TCL_INDEX_NONE);\n\t    data = (char *)GlobalLock(handle);\n\n\t    /*\n\t     * Even though the documentation claims that GetLocaleInfo expects\n\t     * an LCID, on Windows 9x it really seems to expect a LanguageID.\n\t     */\n\n\t    locale = LANGIDFROMLCID(*((int*)data));\n\t    GetLocaleInfoA((ULONG)locale, LOCALE_IDEFAULTANSICODEPAGE,\n\t\t    Tcl_DStringValue(&ds)+2, (int)Tcl_DStringLength(&ds)-2);\n\t    GlobalUnlock(handle);\n\n\t    encoding = Tcl_GetEncoding(NULL, Tcl_DStringValue(&ds));\n\t    Tcl_DStringFree(&ds);\n\t} else {\n\t    encoding = NULL;\n\t}\n\n\t/*\n\t * Fetch the text and convert it to UTF.\n\t */\n\n\thandle = GetClipboardData(CF_TEXT);\n\tif (!handle) {\n\t    if (encoding) {\n\t\tTcl_FreeEncoding(encoding);\n\t    }\n\t    CloseClipboard();\n\t    goto error;\n\t}\n\tdata = (char *)GlobalLock(handle);\n\t(void)Tcl_ExternalToUtfDString(encoding, data, TCL_INDEX_NONE, &ds);\n\tGlobalUnlock(handle);\n\tif (encoding) {\n\t    Tcl_FreeEncoding(encoding);\n\t}\n    } else if (IsClipboardFormatAvailable(CF_HDROP)) {\n\tDROPFILES *drop;\n\n\thandle = GetClipboardData(CF_HDROP);\n\tif (!handle) {\n\t    CloseClipboard();\n\t    goto error;\n\t}\n\tTcl_DStringInit(&ds);\n\tdrop = (DROPFILES *) GlobalLock(handle);\n\tif (drop->fWide) {\n\t    WCHAR *fname = (WCHAR *) ((char *) drop + drop->pFiles);\n\t    Tcl_DString dsTmp;\n\t    int count = 0;\n\t    size_t len;\n\n\t    while (*fname != 0) {\n\t\tif (count) {\n\t\t    Tcl_DStringAppend(&ds, \"\\n\", 1);\n\t\t}\n\t\tlen = wcslen(fname);\n\t\tTcl_DStringInit(&dsTmp);\n\t\tTcl_WCharToUtfDString(fname, len, &dsTmp);\n\t\tTcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp),\n\t\t\tTcl_DStringLength(&dsTmp));\n\t\tTcl_DStringFree(&dsTmp);\n\t\tfname += len + 1;\n\t\tcount++;\n\t    }\n\t    noBackslash = (count > 0);\n\t}\n\tGlobalUnlock(handle);\n    } else {\n\tCloseClipboard();\n\tgoto error;\n    }\n\n    /*\n     * Translate CR/LF to LF.\n     */\n\n    data = destPtr = Tcl_DStringValue(&ds);\n    while (*data) {\n\tif (data[0] == '\\r' && data[1] == '\\n') {\n\t    data++;\n\t} else if (noBackslash && data[0] == '\\\\') {\n\t    data++;\n\t    *destPtr++ = '/';\n\t} else {\n\t    *destPtr++ = *data++;\n\t}\n    }\n    *destPtr = '\\0';\n\n    /*\n     * Pass the data off to the selection procedure.\n     */\n\n    result = proc(clientData, interp, Tcl_DStringValue(&ds));\n    Tcl_DStringFree(&ds);\n    CloseClipboard();\n    return result;\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"%s selection doesn't exist or form \\\"%s\\\" not defined\",\n\t    Tk_GetAtomName(tkwin, selection), Tk_GetAtomName(tkwin, target)));\n    Tcl_SetErrorCode(interp, \"TK\", \"SELECTION\", \"EXISTS\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetSelectionOwner --\n *\n *\tThis function claims ownership of the specified selection. If the\n *\tselection is CLIPBOARD, then we empty the system clipboard.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEmpties the system clipboard, and claims ownership.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetSelectionOwner(\n    TCL_UNUSED(Display *),\n    Atom selection,\n    Window owner,\n    TCL_UNUSED(Time))\n{\n    HWND hwnd = owner ? TkWinGetHWND(owner) : NULL;\n    Tk_Window tkwin;\n\n    /*\n     * This is a gross hack because the Tk_InternAtom interface is broken. It\n     * expects a Tk_Window, even though it only needs a Tk_Display.\n     */\n\n    tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;\n\n    if (selection == Tk_InternAtom(tkwin, \"CLIPBOARD\")) {\n\t/*\n\t * Only claim and empty the clipboard if we aren't already the owner\n\t * of the clipboard.\n\t */\n\n\tif (GetClipboardOwner() != hwnd) {\n\t    UpdateClipboard(hwnd);\n\t}\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinClipboardRender --\n *\n *\tThis function supplies the contents of the clipboard in response to a\n *\tWM_RENDERFORMAT message.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the contents of the clipboard.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinClipboardRender(\n    TkDisplay *dispPtr,\n    TCL_UNUSED(UINT))\n{\n    TkClipboardTarget *targetPtr;\n    TkClipboardBuffer *cbPtr;\n    HGLOBAL handle;\n    char *buffer, *p, *rawText, *endPtr;\n    size_t length;\n    Tcl_DString ds;\n\n    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;\n\t    targetPtr = targetPtr->nextPtr) {\n\tif (targetPtr->type == XA_STRING) {\n\t    break;\n\t}\n    }\n\n    /*\n     * Count the number of newlines so we can add space for them in the\n     * resulting string.\n     */\n\n    length = 0;\n    if (targetPtr != NULL) {\n\tfor (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;\n\t\tcbPtr = cbPtr->nextPtr) {\n\t    length += cbPtr->length;\n\t    for (p = cbPtr->buffer, endPtr = p + cbPtr->length;\n\t\t    p < endPtr; p++) {\n\t\tif (*p == '\\n') {\n\t\t    length++;\n\t\t}\n\t    }\n\t}\n    }\n\n    /*\n     * Copy the data and change EOL characters.\n     */\n\n    buffer = rawText = (char *)Tcl_Alloc(length + 1);\n    if (targetPtr != NULL) {\n\tfor (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;\n\t\tcbPtr = cbPtr->nextPtr) {\n\t    for (p = cbPtr->buffer, endPtr = p + cbPtr->length;\n\t\t    p < endPtr; p++) {\n\t\tif (*p == '\\n') {\n\t\t    *buffer++ = '\\r';\n\t\t}\n\t\t*buffer++ = *p;\n\t    }\n\t}\n    }\n    *buffer = '\\0';\n\n\tTcl_DStringInit(&ds);\n\tTcl_UtfToWCharDString(rawText, TCL_INDEX_NONE, &ds);\n\tTcl_Free(rawText);\n\thandle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,\n\t\tTcl_DStringLength(&ds) + 2);\n\tif (!handle) {\n\t    Tcl_DStringFree(&ds);\n\t    return;\n\t}\n\tbuffer = (char *)GlobalLock(handle);\n\tmemcpy(buffer, Tcl_DStringValue(&ds),\n\t\tTcl_DStringLength(&ds) + 2);\n\tGlobalUnlock(handle);\n\tTcl_DStringFree(&ds);\n\tSetClipboardData(CF_UNICODETEXT, handle);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelUpdateClipboard --\n *\n *\tThis function is called to force the clipboard to be updated after new\n *\tdata is added.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tClears the current contents of the clipboard.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelUpdateClipboard(\n    TkWindow *winPtr,\n    clipboardOption opt)\n{\n    if (opt == CLIPBOARD_APPEND || opt == CLIPBOARD_CLEAR) {\n\tHWND hwnd = TkWinGetHWND(winPtr->window);\n\n\tUpdateClipboard(hwnd);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateClipboard --\n *\n *\tTake ownership of the clipboard, clear it, and indicate to the system\n *\tthe supported formats.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateClipboard(\n    HWND hwnd)\n{\n    TkWinUpdatingClipboard(TRUE);\n    OpenClipboard(hwnd);\n    EmptyClipboard();\n\n    SetClipboardData(CF_UNICODETEXT, NULL);\n    CloseClipboard();\n    TkWinUpdatingClipboard(FALSE);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkSelEventProc --\n *\n *\tThis procedure is invoked whenever a selection-related event occurs.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tLots: depends on the type of event.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkSelEventProc(\n    Tk_Window tkwin,\t\t/* Window for which event was targeted. */\n    XEvent *eventPtr)\t/* X event: either SelectionClear,\n\t\t\t\t * SelectionRequest, or SelectionNotify. */\n{\n    if (eventPtr->type == SelectionClear) {\n\tTkSelClearSelection(tkwin, eventPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSelPropProc --\n *\n *\tThis procedure is invoked when property-change events occur on windows\n *\tnot known to the toolkit. This is a stub function under Windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSelPropProc(\n    TCL_UNUSED(XEvent *))\t/* X PropertyChange event. */\n{\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinColor.c",
    "content": "/*\n * tkWinColor.c --\n *\n *\tFunctions to map color names to system color values.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n * Copyright © 1994 Software Research Associates, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkColor.h\"\n\n/*\n * The following structure is used to keep track of each color that is\n * allocated by this module.\n */\n\ntypedef struct WinColor {\n    TkColor info;\t\t/* Generic color information. */\n    int index;\t\t\t/* Index for GetSysColor(), -1 if color is not\n\t\t\t\t * a \"live\" system color. */\n} WinColor;\n\n/*\n * The sysColors array contains the names and index values for the Windows\n * indirect system color names. In use, all of the names will have the string\n * \"System\" prepended, but we omit it in the table to save space.\n */\n\ntypedef struct {\n    const char *name;\n    int index;\n} SystemColorEntry;\n\nstatic const SystemColorEntry sysColors[] = {\n    {\"3dDarkShadow\",\t\tCOLOR_3DDKSHADOW},\n    {\"3dLight\",\t\t\tCOLOR_3DLIGHT},\n    {\"ActiveBorder\",\t\tCOLOR_ACTIVEBORDER},\n    {\"ActiveCaption\",\t\tCOLOR_ACTIVECAPTION},\n    {\"AppWorkspace\",\t\tCOLOR_APPWORKSPACE},\n    {\"Background\",\t\tCOLOR_BACKGROUND},\n    {\"ButtonFace\",\t\tCOLOR_BTNFACE},\n    {\"ButtonHighlight\",\t\tCOLOR_BTNHIGHLIGHT},\n    {\"ButtonShadow\",\t\tCOLOR_BTNSHADOW},\n    {\"ButtonText\",\t\tCOLOR_BTNTEXT},\n    {\"CaptionText\",\t\tCOLOR_CAPTIONTEXT},\n    {\"DisabledText\",\t\tCOLOR_GRAYTEXT},\n    {\"GrayText\",\t\tCOLOR_GRAYTEXT},\n    {\"Highlight\",\t\tCOLOR_HIGHLIGHT},\n    {\"HighlightText\",\t\tCOLOR_HIGHLIGHTTEXT},\n    {\"InactiveBorder\",\t\tCOLOR_INACTIVEBORDER},\n    {\"InactiveCaption\",\t\tCOLOR_INACTIVECAPTION},\n    {\"InactiveCaptionText\",\tCOLOR_INACTIVECAPTIONTEXT},\n    {\"InfoBackground\",\t\tCOLOR_INFOBK},\n    {\"InfoText\",\t\tCOLOR_INFOTEXT},\n    {\"Menu\",\t\t\tCOLOR_MENU},\n    {\"MenuText\",\t\tCOLOR_MENUTEXT},\n    {\"PlaceHolderText\",\t\tCOLOR_GRAYTEXT},\n    {\"Scrollbar\",\t\tCOLOR_SCROLLBAR},\n    {\"Window\",\t\t\tCOLOR_WINDOW},\n    {\"WindowFrame\",\t\tCOLOR_WINDOWFRAME},\n    {\"WindowText\",\t\tCOLOR_WINDOWTEXT}\n};\n\n/*\n * Forward declarations for functions defined later in this file.\n */\n\nstatic int\t\tFindSystemColor(const char *name, XColor *colorPtr,\n\t\t\t    int *indexPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindSystemColor --\n *\n *\tThis routine finds the color entry that corresponds to the specified\n *\tcolor.\n *\n * Results:\n *\tReturns non-zero on success. The RGB values of the XColor will be\n *\tinitialized to the proper values on success.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nFindSystemColor(\n    const char *name,\t\t/* Color name. */\n    XColor *colorPtr,\t\t/* Where to store results. */\n    int *indexPtr)\t\t/* Out parameter to store color index. */\n{\n    int l, u, r, i;\n    int index;\n\n    /*\n     * Perform a binary search on the sorted array of colors.\n     */\n\n    l = 0;\n    u = (sizeof(sysColors) / sizeof(sysColors[0])) - 1;\n    while (l <= u) {\n\ti = (l + u) / 2;\n\tr = strcasecmp(name, sysColors[i].name);\n\tif (r == 0) {\n\t    break;\n\t} else if (r < 0) {\n\t    u = i-1;\n\t} else {\n\t    l = i+1;\n\t}\n    }\n    if (l > u) {\n\treturn 0;\n    }\n\n    *indexPtr = index = sysColors[i].index;\n    colorPtr->pixel = GetSysColor(index);\n\n    /*\n     * x257 is (value<<8 + value) to get the properly bit shifted and padded\n     * value. [Bug: 4919]\n     */\n\n    colorPtr->red = GetRValue(colorPtr->pixel) * 257;\n    colorPtr->green = GetGValue(colorPtr->pixel) * 257;\n    colorPtr->blue = GetBValue(colorPtr->pixel) * 257;\n    colorPtr->flags = DoRed|DoGreen|DoBlue;\n    colorPtr->pad = 0;\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColor --\n *\n *\tAllocate a new TkColor for the color with the given name.\n *\n * Results:\n *\tReturns a newly allocated TkColor, or NULL on failure.\n *\n * Side effects:\n *\tMay invalidate the colormap cache associated with tkwin upon\n *\tallocating a new colormap entry. Allocates a new TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColor(\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    const char *name)\t\t/* Name of color to allocated (in form\n\t\t\t\t * suitable for passing to XParseColor). */\n{\n    WinColor *winColPtr;\n    XColor color;\n    int index = -1;\t\t/* -1 indicates that this is not an indirect\n\t\t\t\t * system color. */\n\n    /*\n     * Check to see if it is a system color or an X color string. If the color\n     * is found, allocate a new WinColor and store the XColor and the system\n     * color index.\n     */\n\n    if (((strncasecmp(name, \"system\", 6) == 0)\n\t    && FindSystemColor(name+6, &color, &index))\n\t    || TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name,\n\t\t    &color) != 0) {\n\twinColPtr = (WinColor *)Tcl_Alloc(sizeof(WinColor));\n\twinColPtr->info.color = color;\n\twinColPtr->index = index;\n\n\tXAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin),\n\t\t&winColPtr->info.color);\n\treturn (TkColor *)winColPtr;\n    }\n    return (TkColor *)NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetColorByValue --\n *\n *\tGiven a desired set of red-green-blue intensities for a color, locate\n *\ta pixel value to use to draw that color in a given window.\n *\n * Results:\n *\tThe return value is a pointer to an TkColor structure that indicates\n *\tthe closest red, blue, and green intensities available to those\n *\tspecified in colorPtr, and also specifies a pixel value to use to draw\n *\tin that color.\n *\n * Side effects:\n *\tMay invalidate the colormap cache for the specified window. Allocates\n *\ta new TkColor structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkColor *\nTkpGetColorByValue(\n    Tk_Window tkwin,\t\t/* Window in which color will be used. */\n    XColor *colorPtr)\t\t/* Red, green, and blue fields indicate\n\t\t\t\t * desired color. */\n{\n    WinColor *tkColPtr = (WinColor *)Tcl_Alloc(sizeof(WinColor));\n\n    tkColPtr->info.color.red = colorPtr->red;\n    tkColPtr->info.color.green = colorPtr->green;\n    tkColPtr->info.color.blue = colorPtr->blue;\n    tkColPtr->info.color.pixel = 0;\n    tkColPtr->index = -1;\n    XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin), &tkColPtr->info.color);\n    return (TkColor *) tkColPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeColor --\n *\n *\tRelease the specified color back to the system.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tInvalidates the colormap cache for the colormap associated with the\n *\tgiven color.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeColor(\n    TkColor *tkColPtr)\t\t/* Color to be released. Must have been\n\t\t\t\t * allocated by TkpGetColor or\n\t\t\t\t * TkpGetColorByValue. */\n{\n    Screen *screen = tkColPtr->screen;\n\n    XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,\n\t    &tkColPtr->color.pixel, 1, 0L);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinIndexOfColor --\n *\n *\tGiven a color, return the system color index that was used to create\n *\tthe color.\n *\n * Results:\n *\tIf the color was allocated using a system indirect color name, then\n *\tthe corresponding GetSysColor() index is returned. Otherwise, -1 is\n *\treturned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkWinIndexOfColor(\n    XColor *colorPtr)\n{\n    WinColor *winColPtr = (WinColor *) colorPtr;\n    if (winColPtr->info.magic == COLOR_MAGIC) {\n\treturn winColPtr->index;\n    }\n    return -1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XAllocColor --\n *\n *\tFind the closest available color to the specified XColor.\n *\n * Results:\n *\tUpdates the color argument and returns 1 on success. Otherwise returns\n *\t0.\n *\n * Side effects:\n *\tAllocates a new color in the palette.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXAllocColor(\n    TCL_UNUSED(Display *),\n    Colormap colormap,\n    XColor *color)\n{\n    TkWinColormap *cmap = (TkWinColormap *) colormap;\n    PALETTEENTRY entry, closeEntry;\n    HDC dc = GetDC(NULL);\n\n    entry.peRed = (BYTE)((color->red) >> 8);\n    entry.peGreen = (BYTE)((color->green) >> 8);\n    entry.peBlue = (BYTE)((color->blue) >> 8);\n    entry.peFlags = 0;\n\n    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {\n\tunsigned long sizePalette = (unsigned long)GetDeviceCaps(dc, SIZEPALETTE);\n\tUINT newPixel, closePixel;\n\tint isNew;\n\tsize_t refCount;\n\tTcl_HashEntry *entryPtr;\n\tUINT index;\n\n\t/*\n\t * Find the nearest existing palette entry.\n\t */\n\n\tnewPixel = RGB(entry.peRed, entry.peGreen, entry.peBlue);\n\tindex = GetNearestPaletteIndex(cmap->palette, newPixel);\n\tGetPaletteEntries(cmap->palette, index, 1, &closeEntry);\n\tclosePixel = RGB(closeEntry.peRed, closeEntry.peGreen,\n\t\tcloseEntry.peBlue);\n\n\t/*\n\t * If this is not a duplicate, allocate a new entry. Note that we may\n\t * get values for index that are above the current size of the\n\t * palette. This happens because we don't shrink the size of the\n\t * palette object when we deallocate colors so there may be stale\n\t * values that match in the upper slots. We should ignore those values\n\t * and just put the new color in as if the colors had not matched.\n\t */\n\n\tif ((index >= cmap->size) || (newPixel != closePixel)) {\n\t    if (cmap->size == sizePalette) {\n\t\tcolor->red   = closeEntry.peRed * 257;\n\t\tcolor->green = closeEntry.peGreen * 257;\n\t\tcolor->blue  = closeEntry.peBlue * 257;\n\t\tentry = closeEntry;\n\t\tif (index >= cmap->size) {\n\t\t    OutputDebugStringW(L\"XAllocColor: Colormap is bigger than we thought\");\n\t\t}\n\t    } else {\n\t\tcmap->size++;\n\t\tResizePalette(cmap->palette, cmap->size);\n\t\tSetPaletteEntries(cmap->palette, cmap->size - 1, 1, &entry);\n\t    }\n\t}\n\n\tcolor->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);\n\tentryPtr = Tcl_CreateHashEntry(&cmap->refCounts,\n\t\tINT2PTR(color->pixel), &isNew);\n\tif (isNew) {\n\t    refCount = 1;\n\t} else {\n\t    refCount = (size_t)Tcl_GetHashValue(entryPtr) + 1;\n\t}\n\tTcl_SetHashValue(entryPtr, INT2PTR(refCount));\n    } else {\n\t/*\n\t * Determine what color will actually be used on non-colormap systems.\n\t */\n\n\tcolor->pixel = GetNearestColor(dc,\n\t\tRGB(entry.peRed, entry.peGreen, entry.peBlue));\n\tcolor->red    = GetRValue(color->pixel) * 257;\n\tcolor->green  = GetGValue(color->pixel) * 257;\n\tcolor->blue   = GetBValue(color->pixel) * 257;\n    }\n\n    ReleaseDC(NULL, dc);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFreeColors --\n *\n *\tDeallocate a block of colors.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRemoves entries for the current palette and compacts the remaining\n *\tset.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFreeColors(\n    TCL_UNUSED(Display *),\n    Colormap colormap,\n    unsigned long *pixels,\n    int npixels,\n    TCL_UNUSED(unsigned long))\n{\n    TkWinColormap *cmap = (TkWinColormap *) colormap;\n    COLORREF cref;\n    UINT count, index;\n    size_t refCount;\n    int i;\n    PALETTEENTRY entry, *entries;\n    Tcl_HashEntry *entryPtr;\n    HDC dc = GetDC(NULL);\n\n    /*\n     * We don't have to do anything for non-palette devices.\n     */\n\n    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {\n\t/*\n\t * This is really slow for large values of npixels.\n\t */\n\n\tfor (i = 0; i < npixels; i++) {\n\t    entryPtr = Tcl_FindHashEntry(&cmap->refCounts, INT2PTR(pixels[i]));\n\t    if (!entryPtr) {\n\t\tTcl_Panic(\"Tried to free a color that isn't allocated\");\n\t    }\n\t    refCount = (size_t)Tcl_GetHashValue(entryPtr) - 1;\n\t    if (refCount == 0) {\n\t\tcref = pixels[i] & 0x00ffffff;\n\t\tindex = GetNearestPaletteIndex(cmap->palette, cref);\n\t\tGetPaletteEntries(cmap->palette, index, 1, &entry);\n\t\tif (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) {\n\t\t    count = cmap->size - index;\n\t\t    entries = (PALETTEENTRY *)Tcl_Alloc(sizeof(PALETTEENTRY) * count);\n\t\t    GetPaletteEntries(cmap->palette, index+1, count, entries);\n\t\t    SetPaletteEntries(cmap->palette, index, count, entries);\n\t\t    Tcl_Free(entries);\n\t\t    cmap->size--;\n\t\t} else {\n\t\t    Tcl_Panic(\"Tried to free a color that isn't allocated\");\n\t\t}\n\t\tTcl_DeleteHashEntry(entryPtr);\n\t    } else {\n\t\tTcl_SetHashValue(entryPtr, INT2PTR(refCount));\n\t    }\n\t}\n    }\n    ReleaseDC(NULL, dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateColormap --\n *\n *\tAllocate a new colormap.\n *\n * Results:\n *\tReturns a newly allocated colormap.\n *\n * Side effects:\n *\tAllocates an empty palette and color list.\n *\n *----------------------------------------------------------------------\n */\n\nColormap\nXCreateColormap(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Visual *),\n    TCL_UNUSED(int))\n{\n    char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];\n    LOGPALETTE *logPalettePtr;\n    PALETTEENTRY *entryPtr;\n    TkWinColormap *cmap;\n    Tcl_HashEntry *hashPtr;\n    int isNew;\n    UINT i;\n    HPALETTE sysPal;\n\n    /*\n     * Allocate a starting palette with all of the reserved colors.\n     */\n\n    logPalettePtr = (LOGPALETTE *) logPalBuf;\n    logPalettePtr->palVersion = 0x300;\n    sysPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);\n    logPalettePtr->palNumEntries = (WORD)GetPaletteEntries(sysPal, 0, 256,\n\t    logPalettePtr->palPalEntry);\n\n    cmap = (TkWinColormap *)Tcl_Alloc(sizeof(TkWinColormap));\n    cmap->size = logPalettePtr->palNumEntries;\n    cmap->stale = 0;\n    cmap->palette = CreatePalette(logPalettePtr);\n\n    /*\n     * Add hash entries for each of the static colors.\n     */\n\n    Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);\n    for (i = 0; i < logPalettePtr->palNumEntries; i++) {\n\tentryPtr = logPalettePtr->palPalEntry + i;\n\thashPtr = Tcl_CreateHashEntry(&cmap->refCounts, INT2PTR(PALETTERGB(\n\t\tentryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue)), &isNew);\n\tTcl_SetHashValue(hashPtr, INT2PTR(1));\n    }\n\n    return (Colormap)cmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFreeColormap --\n *\n *\tFrees the resources associated with the given colormap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeletes the palette associated with the colormap. Note that the\n *\tpalette must not be selected into a device context when this occurs.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFreeColormap(\n    TCL_UNUSED(Display *),\n    Colormap colormap)\n{\n    TkWinColormap *cmap = (TkWinColormap *) colormap;\n\n    if (!DeleteObject(cmap->palette)) {\n\tTcl_Panic(\"Unable to free colormap, palette is still selected\");\n    }\n    Tcl_DeleteHashTable(&cmap->refCounts);\n    Tcl_Free(cmap);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinSelectPalette --\n *\n *\tThis function sets up the specified device context with a given\n *\tpalette. If the palette is stale, it realizes it in the background\n *\tunless the palette is the current global palette.\n *\n * Results:\n *\tReturns the previous palette selected into the device context.\n *\n * Side effects:\n *\tMay change the system palette.\n *\n *----------------------------------------------------------------------\n */\n\nHPALETTE\nTkWinSelectPalette(\n    HDC dc,\n    Colormap colormap)\n{\n    TkWinColormap *cmap = (TkWinColormap *) colormap;\n    HPALETTE oldPalette;\n\n    oldPalette = SelectPalette(dc, cmap->palette,\n\t    (cmap->palette == TkWinGetSystemPalette()) ? FALSE : TRUE);\n    RealizePalette(dc);\n    return oldPalette;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinConfig.c",
    "content": "/*\n * tkWinConfig.c --\n *\n *\tThis module implements the Windows system defaults for the\n *\tconfiguration package.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetSystemDefault --\n *\n *\tGiven a dbName and className for a configuration option, return a\n *\tstring representation of the option.\n *\n * Results:\n *\tReturns a Tcl_Obj* with the string identifier that identifies this\n *\toption. Returns NULL if there are no system defaults that match this\n *\tpair.\n *\n * Side effects:\n *\tNone, once the package is initialized.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTk_GetSystemDefault(\n    Tk_Window tkwin,\t\t/* A window to use. */\n    const char *dbName,\t\t/* The option database name. */\n    const char *className)\t/* The name of the option class. */\n{\n    Tcl_Obj *valueObjPtr;\n    Tk_Uid classUid;\n\n    if (tkwin == NULL) {\n\treturn NULL;\n    }\n\n    valueObjPtr = NULL;\n    classUid = Tk_Class(tkwin);\n\n    if (strcmp(classUid, \"Menu\") == 0) {\n\tvalueObjPtr = TkWinGetMenuSystemDefault(tkwin, dbName, className);\n    }\n\n    return valueObjPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinCursor.c",
    "content": "/*\n * tkWinCursor.c --\n *\n *\tThis file contains Win32 specific cursor related routines.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n/*\n * The following data structure contains the system specific data necessary to\n * control Windows cursors.\n */\n\ntypedef struct {\n    TkCursor info;\t\t/* Generic cursor info used by tkCursor.c */\n    HCURSOR winCursor;\t\t/* Win32 cursor handle. */\n    int system;\t\t\t/* 1 if cursor is a system cursor, else 0. */\n} TkWinCursor;\n\n/*\n * The HAND cursor is only present when WINVER >= 0x0500. If this is not\n * available at runtime, it will default to the unix-style cursor.\n */\n\n#ifndef IDC_HAND\n#define IDC_HAND MAKEINTRESOURCE(32649)\n#endif\n#ifndef IDC_HELP\n#define IDC_HELP MAKEINTRESOURCE(32651)\n#endif\n\n/*\n * The table below is used to map from the name of a predefined cursor to its\n * resource identifier.\n */\n\nstatic const struct CursorName {\n    const char *name;\n    LPCTSTR id;\n} cursorNames[] = {\n    {\"starting\",\t\tIDC_APPSTARTING},\n    {\"arrow\",\t\t\tIDC_ARROW},\n    {\"ibeam\",\t\t\tIDC_IBEAM},\n    {\"icon\",\t\t\tIDC_ICON},\n    {\"no\",\t\t\tIDC_NO},\n    {\"size\",\t\t\tIDC_SIZEALL},\n    {\"size_ne_sw\",\t\tIDC_SIZENESW},\n    {\"size_ns\",\t\t\tIDC_SIZENS},\n    {\"size_nw_se\",\t\tIDC_SIZENWSE},\n    {\"size_we\",\t\t\tIDC_SIZEWE},\n    {\"uparrow\",\t\t\tIDC_UPARROW},\n    {\"wait\",\t\t\tIDC_WAIT},\n    {\"crosshair\",\t\tIDC_CROSS},\n    {\"fleur\",\t\t\tIDC_SIZEALL},\n    {\"sb_v_double_arrow\",\tIDC_SIZENS},\n    {\"sb_h_double_arrow\",\tIDC_SIZEWE},\n    {\"center_ptr\",\t\tIDC_UPARROW},\n    {\"watch\",\t\t\tIDC_WAIT},\n    {\"xterm\",\t\t\tIDC_IBEAM},\n    {\"hand2\",\t\t\tIDC_HAND},\n    {\"question_arrow\",\t\tIDC_HELP},\n    {NULL,\t\t\t0}\n};\n\n/*\n * The default cursor is used whenever no other cursor has been specified.\n */\n\n#define TK_DEFAULT_CURSOR\t(LPCWSTR)IDC_ARROW\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetCursorByName --\n *\n *\tRetrieve a system cursor by name.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkGetCursorByName(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *string)\t\t/* Description of cursor. See manual entry for\n\t\t\t\t * details on legal syntax. */\n{\n    const struct CursorName *namePtr;\n    TkWinCursor *cursorPtr;\n    Tcl_Size argc;\n    const char **argv = NULL;\n    (void)tkwin;\n\n    /*\n     * All cursor names are valid lists of one element (for\n     * Unix-compatibility), even unadorned system cursor names.\n     */\n\n    if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {\n\treturn NULL;\n    }\n    if (argc == 0) {\n\tgoto badCursorSpec;\n    }\n\n    cursorPtr = (TkWinCursor *)Tcl_Alloc(sizeof(TkWinCursor));\n    cursorPtr->info.cursor = (Tk_Cursor) cursorPtr;\n    cursorPtr->winCursor = NULL;\n    cursorPtr->system = 0;\n\n    if (argv[0][0] == '@') {\n\t/*\n\t * Check for system cursor of type @<filename>, where only the name is\n\t * allowed. This accepts any of:\n\t *\t-cursor @/winnt/cursors/globe.ani\n\t *\t-cursor @C:/Winnt/cursors/E_arrow.cur\n\t *\t-cursor {@C:/Program\\ Files/Cursors/bart.ani}\n\t *\t-cursor {{@C:/Program Files/Cursors/bart.ani}}\n\t *\t-cursor [list @[file join \"C:/Program Files\" Cursors bart.ani]]\n\t */\n\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"cannot get cursor from a file in a safe interpreter\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SAFE\", \"CURSOR_FILE\", (char *)NULL);\n\t    Tcl_Free(argv);\n\t    Tcl_Free(cursorPtr);\n\t    return NULL;\n\t}\n\tcursorPtr->winCursor = LoadCursorFromFileA(&(argv[0][1]));\n    } else {\n\t/*\n\t * Check for the cursor in the system cursor set.\n\t */\n\n\tfor (namePtr = cursorNames; namePtr->name != NULL; namePtr++) {\n\t    if (strcmp(namePtr->name, argv[0]) == 0) {\n\t\tcursorPtr->winCursor = LoadCursorW(NULL, (LPCWSTR) namePtr->id);\n\t\tbreak;\n\t    }\n\t}\n\n\tif (cursorPtr->winCursor == NULL) {\n\t    /*\n\t     * Hmm, it is not in the system cursor set. Check to see if it is\n\t     * one of our application resources.\n\t     */\n\n\t    cursorPtr->winCursor = LoadCursorA(Tk_GetHINSTANCE(), argv[0]);\n\t} else {\n\t    cursorPtr->system = 1;\n\t}\n    }\n\n    if (cursorPtr->winCursor == NULL) {\n\tTcl_Free(cursorPtr);\n    badCursorSpec:\n\tTcl_Free(argv);\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"bad cursor spec \\\"%s\\\"\", string));\n\tTcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"CURSOR\", (char *)NULL);\n\treturn NULL;\n    }\n    Tcl_Free(argv);\n    return (TkCursor *) cursorPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkCreateCursorFromData --\n *\n *\tCreates a cursor from the source and mask bits.\n *\n * Results:\n *\tReturns a new cursor, or NULL on errors.\n *\n * Side effects:\n *\tAllocates a new cursor.\n *\n *----------------------------------------------------------------------\n */\n\nTkCursor *\nTkCreateCursorFromData(\n    Tk_Window tkwin,\t\t/* Window in which cursor will be used. */\n    const char *source,\t\t/* Bitmap data for cursor shape. */\n    const char *mask,\t\t/* Bitmap data for cursor mask. */\n    int width, int height,\t/* Dimensions of cursor. */\n    int xHot, int yHot,\t\t/* Location of hot-spot in cursor. */\n    XColor fgColor,\t\t/* Foreground color for cursor. */\n    XColor bgColor)\t\t/* Background color for cursor. */\n{\n    (void)tkwin;\n    (void)source;\n    (void)mask;\n    (void)width;\n    (void)height;\n    (void)xHot;\n    (void)yHot;\n    (void)fgColor;\n    (void)bgColor;\n\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpFreeCursor --\n *\n *\tThis procedure is called to release a cursor allocated by\n *\tTkGetCursorByName.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe cursor data structure is deallocated.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpFreeCursor(\n    TkCursor *cursorPtr)\n{\n    (void)cursorPtr;\n\n    /* TkWinCursor *winCursorPtr = (TkWinCursor *) cursorPtr; */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetCursor --\n *\n *\tSet the global cursor. If the cursor is None, then use the default Tk\n *\tcursor.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the mouse cursor.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetCursor(\n    Cursor cursor)\n{\n    HCURSOR hcursor;\n    TkWinCursor *winCursor = (TkWinCursor *) cursor;\n\n    if (winCursor == NULL || winCursor->winCursor == NULL) {\n\thcursor = LoadCursorW(NULL, TK_DEFAULT_CURSOR);\n    } else {\n\thcursor = winCursor->winCursor;\n    }\n\n    if (hcursor != NULL) {\n\tSetCursor(hcursor);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinDefault.h",
    "content": "/*\n * tkWinDefault.h --\n *\n *\tThis file defines the defaults for all options for all of\n *\tthe Tk widgets.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKWINDEFAULT\n#define _TKWINDEFAULT\n\n/*\n * The definitions below provide symbolic names for the default colors.\n * NORMAL_BG -\t\tNormal background color.\n * ACTIVE_BG -\t\tBackground color when widget is active.\n * SELECT_BG -\t\tBackground color for selected text.\n * TROUGH -\t\tBackground color for troughs in scales and scrollbars.\n * INDICATOR -\t\tColor for indicator when button is selected.\n * DISABLED -\t\tForeground color when widget is disabled.\n */\n\n#define BLACK\t\t\t\"Black\"\n#define WHITE\t\t\t\"White\"\n\n#define NORMAL_BG\t\t\"SystemButtonFace\"\n#define NORMAL_FG\t\t\"SystemButtonText\"\n#define ACTIVE_BG\t\tNORMAL_BG\n#define TEXT_FG\t\t\t\"SystemWindowText\"\n#define SELECT_BG\t\t\"SystemHighlight\"\n#define SELECT_FG\t\t\"SystemHighlightText\"\n#define INACTIVE_SELECT_BG\t\"#d9d9d9\"\n#define TROUGH\t\t\t\"SystemScrollbar\"\n#define INDICATOR\t\t\"SystemWindow\"\n#define DISABLED\t\t\"SystemDisabledText\"\n#define MENU_BG\t\t\t\"SystemMenu\"\n#define MENU_FG\t\t\t\"SystemMenuText\"\n#define HIGHLIGHT\t\t\"SystemWindowFrame\"\n\n/*\n * Defaults for labels, buttons, checkbuttons, and radiobuttons:\n */\n\n#define DEF_BUTTON_ANCHOR\t\t\"center\"\n#define DEF_BUTTON_ACTIVE_BG_COLOR\tNORMAL_BG\n#define DEF_BUTTON_ACTIVE_BG_MONO\tBLACK\n#define DEF_BUTTON_ACTIVE_FG_COLOR\tNORMAL_FG\n#define DEF_CHKRAD_ACTIVE_FG_COLOR\tTEXT_FG\n#define DEF_BUTTON_ACTIVE_FG_MONO\tWHITE\n#define DEF_BUTTON_BG_COLOR\t\tNORMAL_BG\n#define DEF_BUTTON_BG_MONO\t\tWHITE\n#define DEF_BUTTON_BITMAP\t\t\"\"\n#define DEF_BUTTON_BORDER_WIDTH\t\"2\"\n#define DEF_BUTTON_CURSOR\t\t\"\"\n#define DEF_BUTTON_COMMAND\t\t\"\"\n#define DEF_BUTTON_COMPOUND\t\t\"none\"\n#define DEF_BUTTON_DEFAULT\t\t\"disabled\"\n#define DEF_BUTTON_DISABLED_FG_COLOR\tDISABLED\n#define DEF_BUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_LABEL_FG\t\t\tNORMAL_FG\n#define DEF_BUTTON_FG\t\t\tNORMAL_FG\n#define DEF_CHKRAD_FG\t\t\tTEXT_FG\n#define DEF_BUTTON_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_BUTTON_HEIGHT\t\t\"0\"\n#define DEF_BUTTON_HIGHLIGHT_BG_COLOR\tDEF_BUTTON_BG_COLOR\n#define DEF_BUTTON_HIGHLIGHT_BG_MONO\tDEF_BUTTON_BG_MONO\n#define DEF_BUTTON_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_LABEL_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_BUTTON_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_BUTTON_IMAGE\t\tNULL\n#define DEF_BUTTON_INDICATOR\t\t\"1\"\n#define DEF_BUTTON_JUSTIFY\t\t\"center\"\n#define DEF_BUTTON_OFF_VALUE\t\t\"0\"\n#define DEF_BUTTON_ON_VALUE\t\t\"1\"\n#define DEF_BUTTON_OVER_RELIEF\t\t\"\"\n#define DEF_BUTTON_PADX\t\t\t\"1\"\n#define DEF_LABCHKRAD_PADX\t\t\"1\"\n#define DEF_BUTTON_PADY\t\t\t\"1\"\n#define DEF_LABCHKRAD_PADY\t\t\"1\"\n#define DEF_BUTTON_RELIEF\t\t\"raised\"\n#define DEF_LABCHKRAD_RELIEF\t\t\"flat\"\n#define DEF_BUTTON_REPEAT_DELAY\t\t\"0\"\n#define DEF_BUTTON_REPEAT_INTERVAL\t\"0\"\n#define DEF_BUTTON_SELECT_COLOR\t\tINDICATOR\n#define DEF_BUTTON_SELECT_MONO\t\tBLACK\n#define DEF_BUTTON_SELECT_IMAGE\t\tNULL\n#define DEF_BUTTON_STATE\t\t\"normal\"\n#define DEF_LABEL_TAKE_FOCUS\t\t\"0\"\n#define DEF_BUTTON_TAKE_FOCUS\t\tNULL\n#define DEF_BUTTON_TEXT\t\t\t\"\"\n#define DEF_BUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_BUTTON_TRISTATE_VALUE\t\"\"\n#define DEF_BUTTON_VALUE\t\t\"\"\n#define DEF_BUTTON_WIDTH\t\t\"0\"\n#define DEF_BUTTON_WRAP_LENGTH\t\t\"0\"\n#define DEF_RADIOBUTTON_VARIABLE\t\"selectedButton\"\n#define DEF_CHECKBUTTON_VARIABLE\t\"\"\n\n/*\n * Defaults for canvases:\n */\n\n#define DEF_CANVAS_BG_COLOR\t\tNORMAL_BG\n#define DEF_CANVAS_BG_MONO\t\tWHITE\n#define DEF_CANVAS_BORDER_WIDTH\t\t\"0\"\n#define DEF_CANVAS_CLOSE_ENOUGH\t\t\"1\"\n#define DEF_CANVAS_CONFINE\t\t\"1\"\n#define DEF_CANVAS_CURSOR\t\t\"\"\n#define DEF_CANVAS_HEIGHT\t\t\"7c\"\n#define DEF_CANVAS_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_CANVAS_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_CANVAS_HIGHLIGHT_WIDTH\t\"2\"\n#define DEF_CANVAS_INSERT_BG\t\tNORMAL_FG\n#define DEF_CANVAS_INSERT_BD_COLOR\t\"0\"\n#define DEF_CANVAS_INSERT_BD_MONO\t\"0\"\n#define DEF_CANVAS_INSERT_OFF_TIME\t\"300\"\n#define DEF_CANVAS_INSERT_ON_TIME\t\"600\"\n#define DEF_CANVAS_INSERT_WIDTH\t\t\"2\"\n#define DEF_CANVAS_RELIEF\t\t\"flat\"\n#define DEF_CANVAS_SCROLL_REGION\t\"\"\n#define DEF_CANVAS_SELECT_COLOR\t\tSELECT_BG\n#define DEF_CANVAS_SELECT_MONO\t\tBLACK\n#define DEF_CANVAS_SELECT_BD_COLOR\t\"1\"\n#define DEF_CANVAS_SELECT_BD_MONO\t\"0\"\n#define DEF_CANVAS_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_CANVAS_SELECT_FG_MONO\tWHITE\n#define DEF_CANVAS_TAKE_FOCUS\t\tNULL\n#define DEF_CANVAS_WIDTH\t\t\"10c\"\n#define DEF_CANVAS_X_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_X_SCROLL_INCREMENT\t\"0\"\n#define DEF_CANVAS_Y_SCROLL_CMD\t\t\"\"\n#define DEF_CANVAS_Y_SCROLL_INCREMENT\t\"0\"\n\n/*\n * Defaults for entries:\n */\n\n#define DEF_ENTRY_BG_COLOR\t\t\"SystemWindow\"\n#define DEF_ENTRY_BG_MONO\t\tWHITE\n#define DEF_ENTRY_BORDER_WIDTH\t\t\"1\"\n#define DEF_ENTRY_CURSOR\t\t\"xterm\"\n#define DEF_ENTRY_DISABLED_BG_COLOR\t\"SystemButtonFace\"\n#define DEF_ENTRY_DISABLED_BG_MONO\tWHITE\n#define DEF_ENTRY_DISABLED_FG\t\tDISABLED\n#define DEF_ENTRY_EXPORT_SELECTION\t\"1\"\n#define DEF_ENTRY_FONT\t\t\t\"TkTextFont\"\n#define DEF_ENTRY_FG\t\t\tTEXT_FG\n#define DEF_ENTRY_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_ENTRY_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_ENTRY_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_ENTRY_INSERT_BG\t\tTEXT_FG\n#define DEF_ENTRY_INSERT_BD_COLOR\t\"0\"\n#define DEF_ENTRY_INSERT_BD_MONO\t\"0\"\n#define DEF_ENTRY_INSERT_OFF_TIME\t\"300\"\n#define DEF_ENTRY_INSERT_ON_TIME\t\"600\"\n#define DEF_ENTRY_INSERT_WIDTH\t\t\"2\"\n#define DEF_ENTRY_JUSTIFY\t\t\"left\"\n#define DEF_ENTRY_PLACEHOLDER\t\t\"\"\n#define DEF_ENTRY_PLACEHOLDERFG\t\t\"SystemPlaceHolderText\"\n#define DEF_ENTRY_READONLY_BG_COLOR\t\"SystemButtonFace\"\n#define DEF_ENTRY_READONLY_BG_MONO\tWHITE\n#define DEF_ENTRY_RELIEF\t\t\"sunken\"\n#define DEF_ENTRY_SCROLL_COMMAND\t\"\"\n#define DEF_ENTRY_SELECT_COLOR\t\tSELECT_BG\n#define DEF_ENTRY_SELECT_MONO\t\tBLACK\n#define DEF_ENTRY_SELECT_BD_COLOR\t\"0\"\n#define DEF_ENTRY_SELECT_BD_MONO\t\"0\"\n#define DEF_ENTRY_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_ENTRY_SELECT_FG_MONO\tWHITE\n#define DEF_ENTRY_SHOW\t\t\tNULL\n#define DEF_ENTRY_STATE\t\t\t\"normal\"\n#define DEF_ENTRY_TAKE_FOCUS\t\tNULL\n#define DEF_ENTRY_TEXT_VARIABLE\t\t\"\"\n#define DEF_ENTRY_WIDTH\t\t\t\"20\"\n\n/*\n * Defaults for frames:\n */\n\n#define DEF_FRAME_BG_COLOR\t\tNORMAL_BG\n#define DEF_FRAME_BG_IMAGE\t\tNULL\n#define DEF_FRAME_BG_MONO\t\tWHITE\n#define DEF_FRAME_BG_TILE\t\t\"0\"\n#define DEF_FRAME_BORDER_WIDTH\t\t\"0\"\n#define DEF_FRAME_CLASS\t\t\t\"Frame\"\n#define DEF_FRAME_COLORMAP\t\t\"\"\n#define DEF_FRAME_CONTAINER\t\t\"0\"\n#define DEF_FRAME_CURSOR\t\t\"\"\n#define DEF_FRAME_HEIGHT\t\t\"0\"\n#define DEF_FRAME_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_FRAME_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_FRAME_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_FRAME_PADX\t\t\t\"0\"\n#define DEF_FRAME_PADY\t\t\t\"0\"\n#define DEF_FRAME_RELIEF\t\t\"flat\"\n#define DEF_FRAME_TAKE_FOCUS\t\t\"0\"\n#define DEF_FRAME_VISUAL\t\t\"\"\n#define DEF_FRAME_WIDTH\t\t\t\"0\"\n\n/*\n * Defaults for labelframes:\n */\n\n#define DEF_LABELFRAME_BORDER_WIDTH\t\"2\"\n#define DEF_LABELFRAME_CLASS\t\t\"Labelframe\"\n#define DEF_LABELFRAME_RELIEF\t\t\"groove\"\n#define DEF_LABELFRAME_FG\t\tNORMAL_FG\n#define DEF_LABELFRAME_FONT\t\t\"TkDefaultFont\"\n#define DEF_LABELFRAME_TEXT\t\t\"\"\n#define DEF_LABELFRAME_LABELANCHOR\t\"nw\"\n\n/*\n * Defaults for listboxes:\n */\n\n#define DEF_LISTBOX_ACTIVE_STYLE\t\"underline\"\n#define DEF_LISTBOX_BG_COLOR\t\t\"SystemWindow\"\n#define DEF_LISTBOX_BG_MONO\t\tWHITE\n#define DEF_LISTBOX_BORDER_WIDTH\t\"1\"\n#define DEF_LISTBOX_CURSOR\t\t\"\"\n#define DEF_LISTBOX_DISABLED_FG\t\tDISABLED\n#define DEF_LISTBOX_EXPORT_SELECTION\t\"1\"\n#define DEF_LISTBOX_FONT\t\t\"TkDefaultFont\"\n#define DEF_LISTBOX_FG\t\t\tNORMAL_FG\n#define DEF_LISTBOX_HEIGHT\t\t\"10\"\n#define DEF_LISTBOX_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_LISTBOX_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_LISTBOX_HIGHLIGHT_WIDTH\t\"1\"\n#define DEF_LISTBOX_JUSTIFY\t\t\"left\"\n#define DEF_LISTBOX_RELIEF\t\t\"sunken\"\n#define DEF_LISTBOX_SCROLL_COMMAND\t\"\"\n#define DEF_LISTBOX_LIST_VARIABLE\t\"\"\n#define DEF_LISTBOX_INACTIVE_SELECT_COLOR\tINACTIVE_SELECT_BG\n#define DEF_LISTBOX_SELECT_COLOR\tSELECT_BG\n#define DEF_LISTBOX_SELECT_MONO\t\tBLACK\n#define DEF_LISTBOX_SELECT_BD\t\t\"0\"\n#define DEF_LISTBOX_INACTIVE_SELECT_FG_COLOR\tNORMAL_FG\n#define DEF_LISTBOX_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_LISTBOX_SELECT_FG_MONO\tWHITE\n#define DEF_LISTBOX_SELECT_MODE\t\t\"browse\"\n#define DEF_LISTBOX_SET_GRID\t\t\"0\"\n#define DEF_LISTBOX_STATE\t\t\"normal\"\n#define DEF_LISTBOX_TAKE_FOCUS\t\tNULL\n#define DEF_LISTBOX_WIDTH\t\t\"20\"\n\n/*\n * Defaults for individual entries of menus:\n */\n\n#define DEF_MENU_ENTRY_ACTIVE_BG\tNULL\n#define DEF_MENU_ENTRY_ACTIVE_FG\tNULL\n#define DEF_MENU_ENTRY_ACCELERATOR\tNULL\n#define DEF_MENU_ENTRY_BG\t\tNULL\n#define DEF_MENU_ENTRY_BITMAP\t\tNULL\n#define DEF_MENU_ENTRY_COLUMN_BREAK\t\"0\"\n#define DEF_MENU_ENTRY_COMMAND\t\tNULL\n#define DEF_MENU_ENTRY_COMPOUND\t\"none\"\n#define DEF_MENU_ENTRY_FG\t\tNULL\n#define DEF_MENU_ENTRY_FONT\t\tNULL\n#define DEF_MENU_ENTRY_HIDE_MARGIN\t\"0\"\n#define DEF_MENU_ENTRY_IMAGE\t\tNULL\n#define DEF_MENU_ENTRY_INDICATOR\t\"1\"\n#define DEF_MENU_ENTRY_LABEL\t\tNULL\n#define DEF_MENU_ENTRY_MENU\t\tNULL\n#define DEF_MENU_ENTRY_OFF_VALUE\t\"0\"\n#define DEF_MENU_ENTRY_ON_VALUE\t\t\"1\"\n#define DEF_MENU_ENTRY_SELECT_IMAGE\tNULL\n#define DEF_MENU_ENTRY_STATE\t\t\"normal\"\n#define DEF_MENU_ENTRY_VALUE\t\tNULL\n#define DEF_MENU_ENTRY_CHECK_VARIABLE\tNULL\n#define DEF_MENU_ENTRY_RADIO_VARIABLE\t\"selectedButton\"\n#define DEF_MENU_ENTRY_SELECT\t\tNULL\n\n/*\n * Defaults for menus overall:\n */\n\n#define DEF_MENU_ACTIVE_BG_COLOR\tSELECT_BG\n#define DEF_MENU_ACTIVE_BG_MONO\t\tBLACK\n#define DEF_MENU_ACTIVE_BORDER_WIDTH\t\"0\"\n#define DEF_MENU_ACTIVE_FG_COLOR\tSELECT_FG\n#define DEF_MENU_ACTIVE_FG_MONO\t\tWHITE\n#define DEF_MENU_ACTIVE_RELIEF\t\t\"flat\"\n#define DEF_MENU_BG_COLOR\t\tMENU_BG\n#define DEF_MENU_BG_MONO\t\tWHITE\n#define DEF_MENU_BORDER_WIDTH\t\t\"0\"\n#define DEF_MENU_CURSOR\t\t\t\"arrow\"\n#define DEF_MENU_DISABLED_FG_COLOR\tDISABLED\n#define DEF_MENU_DISABLED_FG_MONO\t\"\"\n#define DEF_MENU_FONT\t\t\t\"TkMenuFont\"\n#define DEF_MENU_FG\t\t\tMENU_FG\n#define DEF_MENU_POST_COMMAND\t\t\"\"\n#define DEF_MENU_RELIEF\t\t\t\"flat\"\n#define DEF_MENU_SELECT_COLOR\t\tMENU_FG\n#define DEF_MENU_SELECT_MONO\t\tBLACK\n#define DEF_MENU_TAKE_FOCUS\t\t\"0\"\n#define DEF_MENU_TEAROFF\t\t\"0\"\n#define DEF_MENU_TEAROFF_CMD\t\tNULL\n#define DEF_MENU_TITLE\t\t\t\"\"\n#define DEF_MENU_TYPE\t\t\t\"normal\"\n\n/*\n * Defaults for menubuttons:\n */\n\n#define DEF_MENUBUTTON_ANCHOR\t\t\"center\"\n#define DEF_MENUBUTTON_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_MENUBUTTON_ACTIVE_BG_MONO\tBLACK\n#define DEF_MENUBUTTON_ACTIVE_FG_COLOR\tNORMAL_FG\n#define DEF_MENUBUTTON_ACTIVE_FG_MONO\tWHITE\n#define DEF_MENUBUTTON_BG_COLOR\t\tNORMAL_BG\n#define DEF_MENUBUTTON_BG_MONO\t\tWHITE\n#define DEF_MENUBUTTON_BITMAP\t\t\"\"\n#define DEF_MENUBUTTON_BORDER_WIDTH\t\"1\"\n#define DEF_MENUBUTTON_CURSOR\t\t\"\"\n#define DEF_MENUBUTTON_DIRECTION\t\"below\"\n#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED\n#define DEF_MENUBUTTON_DISABLED_FG_MONO\t\"\"\n#define DEF_MENUBUTTON_FONT\t\t\"TkDefaultFont\"\n#define DEF_MENUBUTTON_FG\t\tNORMAL_FG\n#define DEF_MENUBUTTON_HEIGHT\t\t\"0\"\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR\n#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO  DEF_MENUBUTTON_BG_MONO\n#define DEF_MENUBUTTON_HIGHLIGHT\tHIGHLIGHT\n#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MENUBUTTON_IMAGE\t\tNULL\n#define DEF_MENUBUTTON_INDICATOR\t\"0\"\n#define DEF_MENUBUTTON_JUSTIFY\t\t\"center\"\n#define DEF_MENUBUTTON_MENU\t\t\"\"\n#define DEF_MENUBUTTON_PADX\t\t\"4p\"\n#define DEF_MENUBUTTON_PADY\t\t\"3p\"\n#define DEF_MENUBUTTON_RELIEF\t\t\"flat\"\n#define DEF_MENUBUTTON_STATE\t\t\"normal\"\n#define DEF_MENUBUTTON_TAKE_FOCUS\t\"0\"\n#define DEF_MENUBUTTON_TEXT\t\t\"\"\n#define DEF_MENUBUTTON_TEXT_VARIABLE\t\"\"\n#define DEF_MENUBUTTON_WIDTH\t\t\"0\"\n#define DEF_MENUBUTTON_WRAP_LENGTH\t\"0\"\n\n/*\n * Defaults for messages:\n */\n\n#define DEF_MESSAGE_ANCHOR\t\t\"center\"\n#define DEF_MESSAGE_ASPECT\t\t\"150\"\n#define DEF_MESSAGE_BG_COLOR\t\tNORMAL_BG\n#define DEF_MESSAGE_BG_MONO\t\tWHITE\n#define DEF_MESSAGE_BORDER_WIDTH\t\"1\"\n#define DEF_MESSAGE_CURSOR\t\t\"\"\n#define DEF_MESSAGE_FG\t\t\tNORMAL_FG\n#define DEF_MESSAGE_FONT\t\t\"TkDefaultFont\"\n#define DEF_MESSAGE_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_MESSAGE_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_MESSAGE_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_MESSAGE_JUSTIFY\t\t\"left\"\n#define DEF_MESSAGE_PADX\t\tNULL\n#define DEF_MESSAGE_PADY\t\tNULL\n#define DEF_MESSAGE_RELIEF\t\t\"flat\"\n#define DEF_MESSAGE_TAKE_FOCUS\t\t\"0\"\n#define DEF_MESSAGE_TEXT\t\t\"\"\n#define DEF_MESSAGE_TEXT_VARIABLE\t\"\"\n#define DEF_MESSAGE_WIDTH\t\t\"0\"\n\n/*\n * Defaults for panedwindows\n */\n\n#define DEF_PANEDWINDOW_BG_COLOR\tNORMAL_BG\n#define DEF_PANEDWINDOW_BG_MONO\t\tWHITE\n#define DEF_PANEDWINDOW_BORDERWIDTH\t\"1\"\n#define DEF_PANEDWINDOW_CURSOR\t\t\"\"\n#define DEF_PANEDWINDOW_HANDLEPAD\t\"8\"\n#define DEF_PANEDWINDOW_HANDLESIZE\t\"8\"\n#define DEF_PANEDWINDOW_HEIGHT\t\t\"\"\n#define DEF_PANEDWINDOW_OPAQUERESIZE\t\"1\"\n#define DEF_PANEDWINDOW_ORIENT\t\t\"horizontal\"\n#define DEF_PANEDWINDOW_PROXYBORDER\t\"2\"\n#define DEF_PANEDWINDOW_RELIEF\t\t\"flat\"\n#define DEF_PANEDWINDOW_SASHCURSOR\t\"\"\n#define DEF_PANEDWINDOW_SASHPAD\t\t\"0\"\n#define DEF_PANEDWINDOW_SASHRELIEF\t\"flat\"\n#define DEF_PANEDWINDOW_SASHWIDTH\t\"3\"\n#define DEF_PANEDWINDOW_SHOWHANDLE\t\"0\"\n#define DEF_PANEDWINDOW_WIDTH\t\t\"\"\n\n/*\n * Defaults for panedwindow panes\n */\n\n#define DEF_PANEDWINDOW_PANE_AFTER\t\"\"\n#define DEF_PANEDWINDOW_PANE_BEFORE\t\"\"\n#define DEF_PANEDWINDOW_PANE_HEIGHT\t\"\"\n#define DEF_PANEDWINDOW_PANE_MINSIZE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADX\t\"0\"\n#define DEF_PANEDWINDOW_PANE_PADY\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STICKY\t\"nsew\"\n#define DEF_PANEDWINDOW_PANE_WIDTH\t\"\"\n#define DEF_PANEDWINDOW_PANE_HIDE\t\"0\"\n#define DEF_PANEDWINDOW_PANE_STRETCH\t\"last\"\n\n/*\n * Defaults for scales:\n */\n\n#define DEF_SCALE_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCALE_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCALE_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCALE_BG_MONO\t\tWHITE\n#define DEF_SCALE_BIG_INCREMENT\t\t\"0.0\"\n#define DEF_SCALE_BORDER_WIDTH\t\t\"1\"\n#define DEF_SCALE_COMMAND\t\t\"\"\n#define DEF_SCALE_CURSOR\t\t\"\"\n#define DEF_SCALE_DIGITS\t\t\"0\"\n#define DEF_SCALE_FONT\t\t\t\"TkDefaultFont\"\n#define DEF_SCALE_FG_COLOR\t\tNORMAL_FG\n#define DEF_SCALE_FG_MONO\t\tBLACK\n#define DEF_SCALE_FROM\t\t\t\"0.0\"\n#define DEF_SCALE_HIGHLIGHT_BG_COLOR\tDEF_SCALE_BG_COLOR\n#define DEF_SCALE_HIGHLIGHT_BG_MONO\tDEF_SCALE_BG_MONO\n#define DEF_SCALE_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_SCALE_HIGHLIGHT_WIDTH\t\"2\"\n#define DEF_SCALE_LABEL\t\t\t\"\"\n#define DEF_SCALE_LENGTH\t\t\"100\"\n#define DEF_SCALE_ORIENT\t\t\"vertical\"\n#define DEF_SCALE_RELIEF\t\t\"flat\"\n#define DEF_SCALE_REPEAT_DELAY\t\t\"300\"\n#define DEF_SCALE_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCALE_RESOLUTION\t\t\"1.0\"\n#define DEF_SCALE_TROUGH_COLOR\t\tTROUGH\n#define DEF_SCALE_TROUGH_MONO\t\tWHITE\n#define DEF_SCALE_SHOW_VALUE\t\t\"1\"\n#define DEF_SCALE_SLIDER_LENGTH\t\t\"30\"\n#define DEF_SCALE_SLIDER_RELIEF\t\t\"raised\"\n#define DEF_SCALE_STATE\t\t\t\"normal\"\n#define DEF_SCALE_TAKE_FOCUS\t\tNULL\n#define DEF_SCALE_TICK_INTERVAL\t\t\"0.0\"\n#define DEF_SCALE_TO\t\t\t\"100.0\"\n#define DEF_SCALE_VARIABLE\t\t\"\"\n#define DEF_SCALE_WIDTH\t\t\t\"15\"\n\n/*\n * Defaults for scrollbars:\n */\n\n#define DEF_SCROLLBAR_ACTIVE_BG_COLOR\tACTIVE_BG\n#define DEF_SCROLLBAR_ACTIVE_BG_MONO\tBLACK\n#define DEF_SCROLLBAR_ACTIVE_RELIEF\t\"raised\"\n#define DEF_SCROLLBAR_BG_COLOR\t\tNORMAL_BG\n#define DEF_SCROLLBAR_BG_MONO\t\tWHITE\n#define DEF_SCROLLBAR_BORDER_WIDTH\t\"0\"\n#define DEF_SCROLLBAR_COMMAND\t\t\"\"\n#define DEF_SCROLLBAR_CURSOR\t\t\"\"\n#define DEF_SCROLLBAR_EL_BORDER_WIDTH\tNULL\n#define DEF_SCROLLBAR_HIGHLIGHT_BG\tNORMAL_BG\n#define DEF_SCROLLBAR_HIGHLIGHT\tHIGHLIGHT\n#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_SCROLLBAR_JUMP\t\t\"0\"\n#define DEF_SCROLLBAR_ORIENT\t\t\"vertical\"\n#define DEF_SCROLLBAR_RELIEF\t\t\"sunken\"\n#define DEF_SCROLLBAR_REPEAT_DELAY\t\"300\"\n#define DEF_SCROLLBAR_REPEAT_INTERVAL\t\"100\"\n#define DEF_SCROLLBAR_TAKE_FOCUS\tNULL\n#define DEF_SCROLLBAR_TROUGH_COLOR\tTROUGH\n#define DEF_SCROLLBAR_TROUGH_MONO\tWHITE\n#define DEF_SCROLLBAR_WIDTH\t\t\"10\"\n\n/*\n * Defaults for texts:\n */\n\n#define DEF_TEXT_AUTO_SEPARATORS\t\"1\"\n#define DEF_TEXT_BG_COLOR\t\t\"SystemWindow\"\n#define DEF_TEXT_BG_MONO\t\tWHITE\n#define DEF_TEXT_BLOCK_CURSOR\t\t\"0\"\n#define DEF_TEXT_BORDER_WIDTH\t\t\"1\"\n#define DEF_TEXT_CURSOR\t\t\t\"xterm\"\n#define DEF_TEXT_FG\t\t\tTEXT_FG\n#define DEF_TEXT_EXPORT_SELECTION\t\"1\"\n#define DEF_TEXT_FONT\t\t\t\"TkFixedFont\"\n#define DEF_TEXT_HEIGHT\t\t\t\"24\"\n#define DEF_TEXT_HIGHLIGHT_BG\t\tNORMAL_BG\n#define DEF_TEXT_HIGHLIGHT\t\tHIGHLIGHT\n#define DEF_TEXT_HIGHLIGHT_WIDTH\t\"0\"\n#define DEF_TEXT_INSERT_BG\t\tTEXT_FG\n#define DEF_TEXT_INSERT_BD_COLOR\t\"0\"\n#define DEF_TEXT_INSERT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_INSERT_OFF_TIME\t\"300\"\n#define DEF_TEXT_INSERT_ON_TIME\t\t\"600\"\n#define DEF_TEXT_INSERT_UNFOCUSSED\t\"none\"\n#define DEF_TEXT_INSERT_WIDTH\t\t\"2\"\n#define DEF_TEXT_MAX_UNDO\t\t\"0\"\n#define DEF_TEXT_PADX\t\t\t\"1\"\n#define DEF_TEXT_PADY\t\t\t\"1\"\n#define DEF_TEXT_RELIEF\t\t\t\"sunken\"\n#define DEF_TEXT_INACTIVE_SELECT_BG_COLOR\tNULL\n#define DEF_TEXT_SELECT_COLOR\t\tSELECT_BG\n#define DEF_TEXT_SELECT_MONO\t\tBLACK\n#define DEF_TEXT_SELECT_BD_COLOR\t\"0\"\n#define DEF_TEXT_SELECT_BD_MONO\t\t\"0\"\n#define DEF_TEXT_SELECT_FG_COLOR\tSELECT_FG\n#define DEF_TEXT_SELECT_FG_MONO\t\tWHITE\n#define DEF_TEXT_SELECT_RELIEF\t\t\"flat\"\n#define DEF_TEXT_SET_GRID\t\t\"0\"\n#define DEF_TEXT_SPACING1\t\t\"0\"\n#define DEF_TEXT_SPACING2\t\t\"0\"\n#define DEF_TEXT_SPACING3\t\t\"0\"\n#define DEF_TEXT_STATE\t\t\t\"normal\"\n#define DEF_TEXT_TABS\t\t\t\"\"\n#define DEF_TEXT_TABSTYLE\t\t\"tabular\"\n#define DEF_TEXT_TAKE_FOCUS\t\tNULL\n#define DEF_TEXT_UNDO\t\t\t\"0\"\n#define DEF_TEXT_WIDTH\t\t\t\"80\"\n#define DEF_TEXT_WRAP\t\t\t\"char\"\n#define DEF_TEXT_XSCROLL_COMMAND\t\"\"\n#define DEF_TEXT_YSCROLL_COMMAND\t\"\"\n\n/*\n * Defaults for canvas text:\n */\n\n#define DEF_CANVTEXT_FONT\t\t\"TkDefaultFont\"\n\n/*\n * Defaults for canvas items\n * (arcs, bitmaps, lines, polygons, rectangles, and ovals):\n */\n\n#define DEF_CANVBMAP_FG\t\t\tNORMAL_FG\n#define DEF_CANVITEM_OUTLINE\t\tNORMAL_FG\n\n/*\n * Defaults for toplevels (most of the defaults for frames also apply\n * to toplevels):\n */\n\n#define DEF_TOPLEVEL_CLASS\t\t\"Toplevel\"\n#define DEF_TOPLEVEL_MENU\t\t\"\"\n#define DEF_TOPLEVEL_SCREEN\t\t\"\"\n#define DEF_TOPLEVEL_USE\t\t\"\"\n\n/*\n * Defaults for busy windows:\n */\n\n#define DEF_BUSY_CURSOR\t\t\t\"wait\"\n\n#endif /* _TKWINDEFAULT */\n"
  },
  {
    "path": "win/tkWinDialog.c",
    "content": "/*\n * tkWinDialog.c --\n *\n *\tContains the Windows implementation of the common dialog boxes.\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkFileFilter.h\"\n#include \"tkFont.h\"\n\n#include <commdlg.h>\t\t/* includes common dialog functionality */\n#include <dlgs.h>\t\t/* includes common dialog template defines */\n#include <cderr.h>\t\t/* includes the common dialog error codes */\n\n#include <shlobj.h>\t\t/* includes SHBrowseForFolder */\n\n#ifdef _MSC_VER\n#   pragma comment (lib, \"shell32.lib\")\n#   pragma comment (lib, \"comdlg32.lib\")\n#   pragma comment (lib, \"uuid.lib\")\n#endif\n\ntypedef struct {\n    int debugFlag;\t\t/* Flags whether we should output debugging\n\t\t\t\t * information while displaying a builtin\n\t\t\t\t * dialog. */\n    Tcl_Interp *debugInterp;\t/* Interpreter to used for debugging. */\n    UINT WM_LBSELCHANGED;\t/* Holds a registered windows event used for\n\t\t\t\t * communicating between the Directory Chooser\n\t\t\t\t * dialog and its hook proc. */\n    HHOOK hMsgBoxHook;\t\t/* Hook proc for tk_messageBox and the */\n    HICON hSmallIcon;\t\t/* icons used by a parent to be used in */\n    HICON hBigIcon;\t\t/* the message box */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The following structures are used by Tk_MessageBoxCmd() to parse arguments\n * and return results.\n */\n\nstatic const TkStateMap iconMap[] = {\n    {MB_ICONERROR,\t\t\"error\"},\n    {MB_ICONINFORMATION,\t\"info\"},\n    {MB_ICONQUESTION,\t\t\"question\"},\n    {MB_ICONWARNING,\t\t\"warning\"},\n    {-1,\t\t\tNULL}\n};\n\nstatic const TkStateMap typeMap[] = {\n    {MB_ABORTRETRYIGNORE,\t\"abortretryignore\"},\n    {MB_OK,\t\t\t\"ok\"},\n    {MB_OKCANCEL,\t\t\"okcancel\"},\n    {MB_RETRYCANCEL,\t\t\"retrycancel\"},\n    {MB_YESNO,\t\t\t\"yesno\"},\n    {MB_YESNOCANCEL,\t\t\"yesnocancel\"},\n    {-1,\t\t\tNULL}\n};\n\nstatic const TkStateMap buttonMap[] = {\n    {IDABORT,\t\t\t\"abort\"},\n    {IDRETRY,\t\t\t\"retry\"},\n    {IDIGNORE,\t\t\t\"ignore\"},\n    {IDOK,\t\t\t\"ok\"},\n    {IDCANCEL,\t\t\t\"cancel\"},\n    {IDNO,\t\t\t\"no\"},\n    {IDYES,\t\t\t\"yes\"},\n    {-1,\t\t\tNULL}\n};\n\nstatic const int buttonFlagMap[] = {\n    MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON4\n};\n\nstatic const struct {int type; int btnIds[3];} allowedTypes[] = {\n    {MB_ABORTRETRYIGNORE,\t{IDABORT, IDRETRY,  IDIGNORE}},\n    {MB_OK,\t\t\t{IDOK,\t  -1,\t    -1\t    }},\n    {MB_OKCANCEL,\t\t{IDOK,\t  IDCANCEL, -1\t    }},\n    {MB_RETRYCANCEL,\t\t{IDRETRY, IDCANCEL, -1\t    }},\n    {MB_YESNO,\t\t\t{IDYES,\t  IDNO,\t    -1\t    }},\n    {MB_YESNOCANCEL,\t\t{IDYES,\t  IDNO,\t    IDCANCEL}}\n};\n\n#define NUM_TYPES (sizeof(allowedTypes) / sizeof(allowedTypes[0]))\n\n/*\n * Abstract trivial differences between Win32 and Win64.\n */\n\n#define TkWinGetHInstance(from) \\\n\t((HINSTANCE) GetWindowLongPtrW((from), GWLP_HINSTANCE))\n#define TkWinGetUserData(from) \\\n\tGetWindowLongPtrW((from), GWLP_USERDATA)\n#define TkWinSetUserData(to,what) \\\n\tSetWindowLongPtrW((to), GWLP_USERDATA, (LPARAM)(what))\n\n/*\n * The following structure is used to pass information between GetFileName\n * function and OFN dialog hook procedures. [Bug 2896501, Patch 2898255]\n */\n\ntypedef struct OFNData {\n    Tcl_Interp *interp;\t\t/* Interp, used only if debug is turned on,\n\t\t\t\t * for setting the variable\n\t\t\t\t * \"::tk::test::dialog::testDialog\". */\n    int dynFileBufferSize;\t/* Dynamic filename buffer size, stored to\n\t\t\t\t * avoid shrinking and expanding the buffer\n\t\t\t\t * when selection changes */\n    WCHAR *dynFileBuffer;\t/* Dynamic filename buffer */\n} OFNData;\n\n/*\n * The following structure is used to gather options used by various\n * file dialogs\n */\ntypedef struct OFNOpts {\n    Tk_Window tkwin;            /* Owner window for dialog */\n    Tcl_Obj *extObj;            /* Default extension */\n    Tcl_Obj *titleObj;          /* Title for dialog */\n    Tcl_Obj *filterObj;         /* File type filter list */\n    Tcl_Obj *typeVariableObj;   /* Variable in which to store type selected */\n    Tcl_Obj *initialTypeObj;    /* Initial value of above, or NULL */\n    Tcl_DString utfDirString;   /* Initial dir */\n    int multi;                  /* Multiple selection enabled */\n    int confirmOverwrite;       /* Confirm before overwriting */\n    int mustExist;              /* Used only for  */\n    Tcl_DString utf16FileName;  /* File name */\n} OFNOpts;\n\n/* Define the operation for which option parsing is to be done. */\nenum OFNOper {\n    OFN_FILE_SAVE,              /* tk_getOpenFile */\n    OFN_FILE_OPEN,              /* tk_getSaveFile */\n    OFN_DIR_CHOOSE              /* tk_chooseDirectory */\n};\n\n/*\n * Definitions of functions used only in this file.\n */\n\nstatic UINT CALLBACK\tColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam,\n\t\t\t    LPARAM lParam);\nstatic void             CleanupOFNOptions(OFNOpts *optsPtr);\nstatic int              ParseOFNOptions(void *clientData,\n\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[], enum OFNOper oper, OFNOpts *optsPtr);\nstatic int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,\n\t\t\t    enum OFNOper oper);\nstatic int\t\tGetFileName(void *clientData,\n\t\t\t\t    Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t\t    Tcl_Obj *const objv[], enum OFNOper oper);\nstatic int MakeFilterVista(Tcl_Interp *interp, OFNOpts *optsPtr,\n\t       DWORD *countPtr, COMDLG_FILTERSPEC **dlgFilterPtrPtr,\n\t       DWORD *defaultFilterIndexPtr);\nstatic void FreeFilterVista(DWORD count, COMDLG_FILTERSPEC *dlgFilterPtr);\nstatic LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam);\nstatic void\t\tSetTestDialog(void *clientData);\nstatic const char *ConvertExternalFilename(LPCWSTR, Tcl_DString *);\n\n/*\n *-------------------------------------------------------------------------\n *\n * EatSpuriousMessageBugFix --\n *\n *\tIn the file open/save dialog, double clicking on a list item causes\n *\tthe dialog box to close, but an unwanted WM_LBUTTONUP message is sent\n *\tto the window underneath. If the window underneath happens to be a\n *\twindows control (eg a button) then it will be activated by accident.\n *\n *\tThis problem does not occur in dialog boxes, because windows must do\n *\tsome special processing to solve the problem. (separate message\n *\tprocessing functions are used to cope with keyboard navigation of\n *\tcontrols.)\n *\n *\tHere is one solution. After returning, we flush all mouse events\n *      for 1/4 second. In 8.6.5 and earlier, the code used to\n *      poll the message queue consuming WM_LBUTTONUP messages.\n *\tOn seeing a WM_LBUTTONDOWN message, it would exit early, since the user\n *\tmust be doing something new. However this early exit does not work\n *      on Vista and later because the Windows sends both BUTTONDOWN and\n *      BUTTONUP after the DBLCLICK instead of just BUTTONUP as on XP.\n *      Rather than try and figure out version specific sequences, we\n *      ignore all mouse events in that interval.\n *\n *      This fix only works for the current application, so the problem will\n *\tstill occur if the open dialog happens to be over another applications\n *\tbutton. However this is a fairly rare occurrance.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConsumes unwanted mouse related messages.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nEatSpuriousMessageBugFix(void)\n{\n    MSG msg;\n    DWORD nTime = GetTickCount() + 250;\n\n    while (GetTickCount() < nTime) {\n\tPeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE);\n    }\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * TkWinDialogDebug --\n *\n *\tFunction to turn on/off debugging support for common dialogs under\n *\twindows. The variable \"::tk::test::dialog::testDialog\" is set to the\n *\tidentifier of the dialog window when the modal dialog window pops up\n *\tand it is safe to send messages to the dialog.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThis variable only makes sense if just one dialog is up at a time.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkWinDialogDebug(\n    int debug)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->debugFlag = debug;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * Tk_ChooseColorObjCmd --\n *\n *\tThis function implements the color dialog box for the Windows\n *\tplatform. See the user documentation for details on what it does.\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tA dialog window is created the first time this function is called.\n *\tThis window is not destroyed and will be reused the next time the\n *\tapplication invokes the \"tk_chooseColor\" command.\n *\n *-------------------------------------------------------------------------\n */\n\nint\nTk_ChooseColorObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData, parent;\n    HWND hWnd;\n    Tcl_Size i;\n    int oldMode, winCode, result;\n    CHOOSECOLORW chooseColor;\n    static int inited = 0;\n    static COLORREF dwCustColors[16];\n    static long oldColor;\t\t/* the color selected last time */\n    static const char *const optionStrings[] = {\n\t\"-initialcolor\", \"-parent\", \"-title\", NULL\n    };\n    enum options {\n\tCOLOR_INITIAL, COLOR_PARENT, COLOR_TITLE\n    };\n\n    result = TCL_OK;\n    if (inited == 0) {\n\t/*\n\t * dwCustColors stores the custom color which the user can modify. We\n\t * store these colors in a static array so that the next time the\n\t * color dialog pops up, the same set of custom colors remain in the\n\t * dialog.\n\t */\n\n\tfor (i = 0; i < 16; i++) {\n\t    dwCustColors[i] = RGB(255-i * 10, i, i * 10);\n\t}\n\toldColor = RGB(0xa0, 0xa0, 0xa0);\n\tinited = 1;\n    }\n\n    parent\t\t\t= tkwin;\n    chooseColor.lStructSize\t= sizeof(CHOOSECOLORW);\n    chooseColor.hwndOwner\t= NULL;\n    chooseColor.hInstance\t= NULL;\n    chooseColor.rgbResult\t= oldColor;\n    chooseColor.lpCustColors\t= dwCustColors;\n    chooseColor.Flags\t\t= CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;\n    chooseColor.lCustData\t= (LPARAM) NULL;\n    chooseColor.lpfnHook\t= (LPOFNHOOKPROC)(void *)ColorDlgHookProc;\n    chooseColor.lpTemplateName\t= (LPWSTR) interp;\n\n    for (i = 1; i < objc; i += 2) {\n\tint index;\n\tconst char *string;\n\tTcl_Obj *optionPtr, *valuePtr;\n\n\toptionPtr = objv[i];\n\tvaluePtr = objv[i + 1];\n\n\tif (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings,\n\t\t\"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(optionPtr)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"COLORDIALOG\", \"VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tstring = Tcl_GetString(valuePtr);\n\tswitch ((enum options) index) {\n\tcase COLOR_INITIAL: {\n\t    XColor *colorPtr;\n\n\t    colorPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr);\n\t    if (colorPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    chooseColor.rgbResult = RGB(colorPtr->red / 0x100,\n\t\t    colorPtr->green / 0x100, colorPtr->blue / 0x100);\n\t    break;\n\t}\n\tcase COLOR_PARENT:\n\t    parent = Tk_NameToWindow(interp, string, tkwin);\n\t    if (parent == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\tcase COLOR_TITLE:\n\t    chooseColor.lCustData = (LPARAM) string;\n\t    break;\n\t}\n    }\n\n    Tk_MakeWindowExist(parent);\n    chooseColor.hwndOwner = NULL;\n    hWnd = Tk_GetHWND(Tk_WindowId(parent));\n    chooseColor.hwndOwner = hWnd;\n\n    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n    winCode = ChooseColorW(&chooseColor);\n    (void) Tcl_SetServiceMode(oldMode);\n\n    /*\n     * Ensure that hWnd is enabled, because it can happen that we have updated\n     * the wrapper of the parent, which causes us to leave this child disabled\n     * (Windows loses sync).\n     */\n\n    EnableWindow(hWnd, 1);\n\n    /*\n     * Clear the interp result since anything may have happened during the\n     * modal loop.\n     */\n\n    Tcl_ResetResult(interp);\n\n    /*\n     * 3. Process the result of the dialog\n     */\n\n    if (winCode) {\n\t/*\n\t * User has selected a color\n\t */\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"#%02x%02x%02x\",\n\t\tGetRValue(chooseColor.rgbResult),\n\t\tGetGValue(chooseColor.rgbResult),\n\t\tGetBValue(chooseColor.rgbResult)));\n\toldColor = chooseColor.rgbResult;\n\tresult = TCL_OK;\n    }\n\n    return result;\n}\n\f\n/*\n *-------------------------------------------------------------------------\n *\n * ColorDlgHookProc --\n *\n *\tProvides special handling of messages for the Color common dialog box.\n *\tUsed to set the title when the dialog first appears.\n *\n * Results:\n *\tThe return value is 0 if the default dialog box function should handle\n *\tthe message, non-zero otherwise.\n *\n * Side effects:\n *\tChanges the title of the dialog window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic UINT CALLBACK\nColorDlgHookProc(\n    HWND hDlg,\t\t\t/* Handle to the color dialog. */\n    UINT uMsg,\t\t\t/* Type of message. */\n    TCL_UNUSED(WPARAM),\t/* First message parameter. */\n    LPARAM lParam)\t\t/* Second message parameter. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    const char *title;\n    CHOOSECOLORW *ccPtr;\n\n    if (WM_INITDIALOG == uMsg) {\n\n\t/*\n\t * Set the title string of the dialog.\n\t */\n\n\tccPtr = (CHOOSECOLORW *) lParam;\n\ttitle = (const char *) ccPtr->lCustData;\n\n\tif ((title != NULL) && (title[0] != '\\0')) {\n\t    Tcl_DString ds;\n\n\t    Tcl_DStringInit(&ds);\n\t    SetWindowTextW(hDlg, Tcl_UtfToWCharDString(title, TCL_INDEX_NONE, &ds));\n\t    Tcl_DStringFree(&ds);\n\t}\n\tif (tsdPtr->debugFlag) {\n\t    tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName;\n\t    Tcl_DoWhenIdle(SetTestDialog, hDlg);\n\t}\n\treturn TRUE;\n    }\n    return FALSE;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOpenFileObjCmd --\n *\n *\tThis function implements the \"open file\" dialog box for the Windows\n *\tplatform. See the user documentation for details on what it does.\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tA dialog window is created the first this function is called.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetOpenFileObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    return GetFileName(clientData, interp, objc, objv, OFN_FILE_OPEN);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetSaveFileObjCmd --\n *\n *\tSame as Tk_GetOpenFileObjCmd but opens a \"save file\" dialog box\n *\tinstead\n *\n * Results:\n *\tSame as Tk_GetOpenFileObjCmd.\n *\n * Side effects:\n *\tSame as Tk_GetOpenFileObjCmd.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_GetSaveFileObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    return GetFileName(clientData, interp, objc, objv, OFN_FILE_SAVE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CleanupOFNOptions --\n *\n *\tCleans up any storage allocated by ParseOFNOptions\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tReleases resources held by *optsPtr\n *----------------------------------------------------------------------\n */\nstatic void CleanupOFNOptions(OFNOpts *optsPtr)\n{\n    Tcl_DStringFree(&optsPtr->utfDirString);\n    Tcl_DStringFree(&optsPtr->utf16FileName);\n}\n\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ParseOFNOptions --\n *\n *\tOption parsing for tk_get{Open,Save}File\n *\n * Results:\n *\tTCL_OK on success, TCL_ERROR otherwise\n *\n * Side effects:\n *\tReturns option values in *optsPtr. Note these may include string\n *      pointers into objv[]\n *----------------------------------------------------------------------\n */\n\nstatic int\nParseOFNOptions(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    enum OFNOper oper,\t\t\t/* 1 for Open, 0 for Save */\n    OFNOpts *optsPtr)           /* Output, uninitialized on entry */\n{\n    Tcl_Size i;\n    Tcl_DString ds;\n    enum options {\n\tFILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT,\n\tFILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW,\n\tFILE_MUSTEXIST,\n    };\n    struct Options {\n\tconst char *name;\n\tenum options value;\n    };\n    static const struct Options saveOptions[] = {\n\t{\"-confirmoverwrite\",\tFILE_CONFIRMOW},\n\t{\"-defaultextension\",\tFILE_DEFAULT},\n\t{\"-filetypes\",\t\tFILE_TYPES},\n\t{\"-initialdir\",\t\tFILE_INITDIR},\n\t{\"-initialfile\",\tFILE_INITFILE},\n\t{\"-parent\",\t\tFILE_PARENT},\n\t{\"-title\",\t\tFILE_TITLE},\n\t{\"-typevariable\",\tFILE_TYPEVARIABLE},\n\t{NULL,\t\t\tFILE_DEFAULT/*ignored*/ }\n    };\n    static const struct Options openOptions[] = {\n\t{\"-defaultextension\",\tFILE_DEFAULT},\n\t{\"-filetypes\",\t\tFILE_TYPES},\n\t{\"-initialdir\",\t\tFILE_INITDIR},\n\t{\"-initialfile\",\tFILE_INITFILE},\n\t{\"-multiple\",\t\tFILE_MULTIPLE},\n\t{\"-parent\",\t\tFILE_PARENT},\n\t{\"-title\",\t\tFILE_TITLE},\n\t{\"-typevariable\",\tFILE_TYPEVARIABLE},\n\t{NULL,\t\t\tFILE_DEFAULT/*ignored*/ }\n    };\n    static const struct Options dirOptions[] = {\n\t{\"-initialdir\", FILE_INITDIR},\n\t{\"-mustexist\",  FILE_MUSTEXIST},\n\t{\"-parent\",\tFILE_PARENT},\n\t{\"-title\",\tFILE_TITLE},\n\t{NULL,\t\tFILE_DEFAULT/*ignored*/ }\n    };\n\n    const struct Options *options = NULL;\n\n    switch (oper) {\n    case OFN_FILE_SAVE: options = saveOptions; break;\n    case OFN_DIR_CHOOSE: options = dirOptions; break;\n    case OFN_FILE_OPEN: options = openOptions; break;\n    }\n\n    memset(optsPtr, 0, sizeof(*optsPtr));\n    optsPtr->tkwin = (Tk_Window)clientData;\n    optsPtr->confirmOverwrite = 1; /* By default we ask for confirmation */\n    Tcl_DStringInit(&optsPtr->utfDirString);\n    Tcl_DStringInit(&optsPtr->utf16FileName);\n\n    for (i = 1; i < objc; i += 2) {\n\tint index;\n\tconst char *string;\n\tTcl_Obj *valuePtr;\n\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], options,\n\t\tsizeof(struct Options), \"option\", 0, &index) != TCL_OK) {\n\t    goto error_return;\n\t} else if (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\t \"value for \\\"%s\\\" missing\", options[index].name));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FILEDIALOG\", \"VALUE\", (char *)NULL);\n\t    goto error_return;\n\t}\n\n\tvaluePtr = objv[i + 1];\n\tstring = Tcl_GetString(valuePtr);\n\tswitch (options[index].value) {\n\tcase FILE_DEFAULT:\n\t    optsPtr->extObj = valuePtr;\n\t    break;\n\tcase FILE_TYPES:\n\t    optsPtr->filterObj = valuePtr;\n\t    break;\n\tcase FILE_INITDIR:\n\t    Tcl_DStringFree(&optsPtr->utfDirString);\n\t    if (Tcl_TranslateFileName(interp, string,\n\t\t\t\t      &optsPtr->utfDirString) == NULL)\n\t\tgoto error_return;\n\t    break;\n\tcase FILE_INITFILE:\n\t    if (Tcl_TranslateFileName(interp, string, &ds) == NULL)\n\t\tgoto error_return;\n\t    Tcl_UtfToExternalDStringEx(interp, TkWinGetUnicodeEncoding(),\n\t\tTcl_DStringValue(&ds), Tcl_DStringLength(&ds),\n\t\tTCL_ENCODING_PROFILE_REPLACE, &optsPtr->utf16FileName, NULL);\n\t    Tcl_DStringFree(&ds);\n\t    break;\n\tcase FILE_PARENT:\n\t    optsPtr->tkwin = Tk_NameToWindow(interp, string, (Tk_Window)clientData);\n\t    if (optsPtr->tkwin == NULL)\n\t\tgoto error_return;\n\t    break;\n\tcase FILE_TITLE:\n\t    optsPtr->titleObj = valuePtr;\n\t    break;\n\tcase FILE_TYPEVARIABLE:\n\t    optsPtr->typeVariableObj = valuePtr;\n\t    optsPtr->initialTypeObj = Tcl_ObjGetVar2(interp, valuePtr,\n\t\t\t\t\t\t     NULL, TCL_GLOBAL_ONLY);\n\t    break;\n\tcase FILE_MULTIPLE:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr,\n\t\t\t\t      &optsPtr->multi) != TCL_OK)\n\t\tgoto error_return;\n\t    break;\n\tcase FILE_CONFIRMOW:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr,\n\t\t\t\t      &optsPtr->confirmOverwrite) != TCL_OK)\n\t\tgoto error_return;\n\t    break;\n\tcase FILE_MUSTEXIST:\n\t    if (Tcl_GetBooleanFromObj(interp, valuePtr,\n\t\t\t\t      &optsPtr->mustExist) != TCL_OK)\n\t\tgoto error_return;\n\t    break;\n\t}\n    }\n\n    return TCL_OK;\n\nerror_return:                   /* interp should already hold error */\n    /* On error, we need to clean up anything we might have allocated */\n    CleanupOFNOptions(optsPtr);\n    return TCL_ERROR;\n\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetFileNameVista --\n *\n *\tDisplays the new file dialogs on Vista and later.\n *\n * Results:\n *\tTCL_OK - dialog was successfully displayed, results returned in interp\n *      TCL_ERROR - error return\n *\n * Side effects:\n *      Dialogs is displayed\n *----------------------------------------------------------------------\n */\nstatic int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,\n\t\t\t    enum OFNOper oper)\n{\n    HRESULT hr;\n    HWND hWnd;\n    DWORD flags, nfilters, defaultFilterIndex;\n    COMDLG_FILTERSPEC *filterPtr = NULL;\n    IFileDialog *fdlgIf = NULL;\n    IShellItem *dirIf = NULL;\n    LPWSTR wstr;\n    Tcl_Obj *resultObj = NULL;\n    int oldMode;\n\n    /*\n     * At this point new interfaces are supposed to be available.\n     * fdlgIf is actually a IFileOpenDialog or IFileSaveDialog\n     * both of which inherit from IFileDialog. We use the common\n     * IFileDialog interface for the most part, casting only for\n     * type-specific calls.\n     */\n    Tk_MakeWindowExist(optsPtr->tkwin);\n    hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));\n\n    /*\n     * The only validation we need to do w.r.t caller supplied data\n     * is the filter specification so do that before creating\n     */\n    if (MakeFilterVista(interp, optsPtr, &nfilters, &filterPtr,\n\t\t\t&defaultFilterIndex) != TCL_OK)\n\treturn TCL_ERROR;\n\n    /*\n     * Beyond this point, do not just return on error as there will be\n     * resources that need to be released/freed.\n     */\n\n    if (oper == OFN_FILE_OPEN || oper == OFN_DIR_CHOOSE)\n\thr = CoCreateInstance(&CLSID_FileOpenDialog, NULL,\n\t\t\t      CLSCTX_INPROC_SERVER, &IID_IFileOpenDialog, (void **) &fdlgIf);\n    else\n\thr = CoCreateInstance(&CLSID_FileSaveDialog, NULL,\n\t\t\t      CLSCTX_INPROC_SERVER, &IID_IFileSaveDialog, (void **) &fdlgIf);\n\n    if (FAILED(hr))\n\tgoto vamoose;\n\n    /*\n     * Get current settings first because we want to preserve existing\n     * settings like whether to show hidden files etc. based on the\n     * user's existing preference\n     */\n    hr = fdlgIf->lpVtbl->GetOptions(fdlgIf, &flags);\n    if (FAILED(hr))\n\tgoto vamoose;\n\n    if (filterPtr) {\n\t/*\n\t * Causes -filetypes {{All *}} -defaultextension ext to return\n\t * foo.ext.ext when foo is typed into the entry box\n\t *     flags |= FOS_STRICTFILETYPES;\n\t */\n\thr = fdlgIf->lpVtbl->SetFileTypes(fdlgIf, nfilters, filterPtr);\n\tif (FAILED(hr))\n\t    goto vamoose;\n\thr = fdlgIf->lpVtbl->SetFileTypeIndex(fdlgIf, defaultFilterIndex);\n\tif (FAILED(hr))\n\t    goto vamoose;\n    }\n\n    /* Flags are equivalent to those we used in the older API */\n\n    /*\n     * Following flags must be set irrespective of original setting\n     * XXX - should FOS_NOVALIDATE be there ? Note FOS_NOVALIDATE has different\n     * semantics than OFN_NOVALIDATE in the old API.\n     */\n    flags |=\n\tFOS_FORCEFILESYSTEM | /* Only want files, not other shell items */\n\tFOS_NOVALIDATE |           /* Don't check for access denied etc. */\n\tFOS_PATHMUSTEXIST;           /* The *directory* path must exist */\n\n\n    if (oper == OFN_DIR_CHOOSE) {\n\tflags |= FOS_PICKFOLDERS;\n\tif (optsPtr->mustExist)\n\t    flags |= FOS_FILEMUSTEXIST; /* XXX - check working */\n    } else\n\tflags &= ~ FOS_PICKFOLDERS;\n\n    if (optsPtr->multi)\n\tflags |= FOS_ALLOWMULTISELECT;\n    else\n\tflags &= ~FOS_ALLOWMULTISELECT;\n\n    if (optsPtr->confirmOverwrite)\n\tflags |= FOS_OVERWRITEPROMPT;\n    else\n\tflags &= ~FOS_OVERWRITEPROMPT;\n\n    hr = fdlgIf->lpVtbl->SetOptions(fdlgIf, flags);\n    if (FAILED(hr))\n\tgoto vamoose;\n\n    if (optsPtr->extObj != NULL) {\n\tTcl_DString ds;\n\tconst char *src;\n\n\tsrc = Tcl_GetString(optsPtr->extObj);\n\tTcl_DStringInit(&ds);\n\twstr = Tcl_UtfToWCharDString(src, optsPtr->extObj->length, &ds);\n\tif (wstr[0] == '.')\n\t    ++wstr;\n\thr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr);\n\tTcl_DStringFree(&ds);\n\tif (FAILED(hr))\n\t    goto vamoose;\n    }\n\n    if (optsPtr->titleObj != NULL) {\n\tTcl_DString ds;\n\tconst char *src;\n\n\tsrc = Tcl_GetString(optsPtr->titleObj);\n\tTcl_DStringInit(&ds);\n\twstr = Tcl_UtfToWCharDString(src, optsPtr->titleObj->length, &ds);\n\thr = fdlgIf->lpVtbl->SetTitle(fdlgIf, wstr);\n\tTcl_DStringFree(&ds);\n\tif (FAILED(hr))\n\t    goto vamoose;\n    }\n\n    WCHAR *fileNamePtr = (WCHAR *)Tcl_DStringValue(&optsPtr->utf16FileName);\n    if (*fileNamePtr) {\n\thr = fdlgIf->lpVtbl->SetFileName(fdlgIf, fileNamePtr);\n\tif (FAILED(hr))\n\t    goto vamoose;\n    }\n\n    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\\0') {\n\tTcl_Obj *normPath, *iniDirPath;\n\tiniDirPath = Tcl_NewStringObj(Tcl_DStringValue(&optsPtr->utfDirString), TCL_INDEX_NONE);\n\tTcl_IncrRefCount(iniDirPath);\n\tnormPath = Tcl_FSGetNormalizedPath(interp, iniDirPath);\n\t/* XXX - Note on failures do not raise error, simply ignore ini dir */\n\tif (normPath) {\n\t    LPCWSTR nativePath;\n\t    Tcl_IncrRefCount(normPath);\n\t    nativePath = (LPCWSTR)Tcl_FSGetNativePath(normPath); /* Points INTO normPath*/\n\t    if (nativePath) {\n\t\thr = SHCreateItemFromParsingName(\n\t\t    nativePath, NULL,\n\t\t    &IID_IShellItem, (void **) &dirIf);\n\t\tif (SUCCEEDED(hr)) {\n\t\t    /* Note we use SetFolder, not SetDefaultFolder - see MSDN */\n\t\t    fdlgIf->lpVtbl->SetFolder(fdlgIf, dirIf); /* Ignore errors */\n\t\t}\n\t    }\n\t    Tcl_DecrRefCount(normPath); /* ALSO INVALIDATES nativePath !! */\n\t}\n\tTcl_DecrRefCount(iniDirPath);\n    }\n\n    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n    hr = fdlgIf->lpVtbl->Show(fdlgIf, hWnd);\n    Tcl_SetServiceMode(oldMode);\n    EatSpuriousMessageBugFix();\n\n    /*\n     * Ensure that hWnd is enabled, because it can happen that we have updated\n     * the wrapper of the parent, which causes us to leave this child disabled\n     * (Windows loses sync).\n     */\n\n    if (hWnd)\n\tEnableWindow(hWnd, 1);\n\n    /*\n     * Clear interp result since it might have been set during the modal loop.\n     * https://core.tcl-lang.org/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6\n     */\n    Tcl_ResetResult(interp);\n\n    if (SUCCEEDED(hr)) {\n\tif ((oper == OFN_FILE_OPEN) && optsPtr->multi) {\n\t    IShellItemArray *multiIf;\n\t    DWORD dw, count;\n\t    IFileOpenDialog *fodIf = (IFileOpenDialog *) fdlgIf;\n\t    hr = fodIf->lpVtbl->GetResults(fodIf, &multiIf);\n\t    if (SUCCEEDED(hr)) {\n\t\tTcl_Obj *multiObj;\n\t\thr = multiIf->lpVtbl->GetCount(multiIf, &count);\n\t\tmultiObj = Tcl_NewListObj(count, NULL);\n\t\tif (SUCCEEDED(hr)) {\n\t\t    IShellItem *itemIf;\n\t\t    for (dw = 0; dw < count; ++dw) {\n\t\t\thr = multiIf->lpVtbl->GetItemAt(multiIf, dw, &itemIf);\n\t\t\tif (FAILED(hr))\n\t\t\t    break;\n\t\t\thr = itemIf->lpVtbl->GetDisplayName(itemIf,\n\t\t\t\t\tSIGDN_FILESYSPATH, &wstr);\n\t\t\tif (SUCCEEDED(hr)) {\n\t\t\t    Tcl_DString fnds;\n\n\t\t\t    ConvertExternalFilename(wstr, &fnds);\n\t\t\t    CoTaskMemFree(wstr);\n\t\t\t    Tcl_ListObjAppendElement(\n\t\t\t\tinterp, multiObj,\n\t\t\t\tTcl_NewStringObj(Tcl_DStringValue(&fnds),\n\t\t\t\t\t\t Tcl_DStringLength(&fnds)));\n\t\t\t    Tcl_DStringFree(&fnds);\n\t\t\t}\n\t\t\titemIf->lpVtbl->Release(itemIf);\n\t\t\tif (FAILED(hr))\n\t\t\t    break;\n\t\t    }\n\t\t}\n\t\tmultiIf->lpVtbl->Release(multiIf);\n\t\tif (SUCCEEDED(hr))\n\t\t    resultObj = multiObj;\n\t\telse\n\t\t    Tcl_DecrRefCount(multiObj);\n\t    }\n\t} else {\n\t    IShellItem *resultIf;\n\t    hr = fdlgIf->lpVtbl->GetResult(fdlgIf, &resultIf);\n\t    if (SUCCEEDED(hr)) {\n\t\thr = resultIf->lpVtbl->GetDisplayName(resultIf, SIGDN_FILESYSPATH,\n\t\t\t\t\t\t      &wstr);\n\t\tif (SUCCEEDED(hr)) {\n\t\t    Tcl_DString fnds;\n\n\t\t    ConvertExternalFilename(wstr, &fnds);\n\t\t    resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds),\n\t\t\t\t\t\t Tcl_DStringLength(&fnds));\n\t\t    CoTaskMemFree(wstr);\n\t\t    Tcl_DStringFree(&fnds);\n\t\t}\n\t\tresultIf->lpVtbl->Release(resultIf);\n\t    }\n\t}\n\tif (SUCCEEDED(hr)) {\n\t    if (filterPtr && optsPtr->typeVariableObj) {\n\t\tUINT ftix;\n\n\t\thr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix);\n\t\tif (SUCCEEDED(hr)) {\n\t\t    /* Note ftix is a 1-based index */\n\t\t    if (ftix > 0 && ftix <= nfilters) {\n\t\t\tTcl_DString ftds;\n\t\t\tTcl_Obj *ftobj;\n\n\t\t\tTcl_DStringInit(&ftds);\n\t\t\tTcl_WCharToUtfDString(filterPtr[ftix-1].pszName, wcslen(filterPtr[ftix-1].pszName), &ftds);\n\t\t\tftobj = Tcl_NewStringObj(Tcl_DStringValue(&ftds),\n\t\t\t\tTcl_DStringLength(&ftds));\n\t\t\tTcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,\n\t\t\t\tftobj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);\n\t\t\tTcl_DStringFree(&ftds);\n\t\t    }\n\t\t}\n\t    }\n\t}\n    } else {\n\tif (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))\n\t    hr = 0;             /* User cancelled, return empty string */\n    }\n\nvamoose: /* (hr != 0) => error */\n    if (dirIf)\n\tdirIf->lpVtbl->Release(dirIf);\n    if (fdlgIf)\n\tfdlgIf->lpVtbl->Release(fdlgIf);\n\n    if (filterPtr)\n\tFreeFilterVista(nfilters, filterPtr);\n\n    if (hr == 0) {\n\tif (resultObj)          /* May be NULL if user cancelled */\n\t    Tcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    } else {\n\tif (resultObj)\n\t    Tcl_DecrRefCount(resultObj);\n\tTcl_SetObjResult(interp, TkWin32ErrorObj(hr));\n\treturn TCL_ERROR;\n    }\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetFileName --\n *\n *\tCalls GetOpenFileName() or GetSaveFileName().\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tSee user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetFileName(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[],\t/* Argument objects. */\n    enum OFNOper oper)\t/* 1 to call GetOpenFileName(), 0 to call\n\t\t\t\t * GetSaveFileName(). */\n{\n    OFNOpts ofnOpts;\n    int result;\n\n    result = ParseOFNOptions(clientData, interp, objc, objv, oper, &ofnOpts);\n    if (result != TCL_OK)\n\treturn result;\n\n    result = GetFileNameVista(interp, &ofnOpts, oper);\n\n    CleanupOFNOptions(&ofnOpts);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeFilterVista\n *\n *      Frees storage previously allocated by MakeFilterVista.\n *      count is the number of elements in dlgFilterPtr[]\n */\nstatic void FreeFilterVista(DWORD count, COMDLG_FILTERSPEC *dlgFilterPtr)\n{\n    if (dlgFilterPtr != NULL) {\n\tDWORD dw;\n\tfor (dw = 0; dw < count; ++dw) {\n\t    if (dlgFilterPtr[dw].pszName != NULL)\n\t\tTcl_Free((void *)dlgFilterPtr[dw].pszName);\n\t    if (dlgFilterPtr[dw].pszSpec != NULL)\n\t\tTcl_Free((void *)dlgFilterPtr[dw].pszSpec);\n\t}\n\tTcl_Free(dlgFilterPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MakeFilterVista --\n *\n *\tReturns file type filters in a format required\n *\tby the Vista file dialogs.\n *\n * Results:\n *\tA standard TCL return value.\n *\n * Side effects:\n *      Various values are returned through the parameters as\n *      described in the comments below.\n *----------------------------------------------------------------------\n */\nstatic int MakeFilterVista(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    OFNOpts *optsPtr,           /* Caller specified options */\n    DWORD *countPtr,            /* Will hold number of filters */\n    COMDLG_FILTERSPEC **dlgFilterPtrPtr, /* Will hold pointer to filter array.\n\t\t\t\t\t Set to NULL if no filters specified.\n\t\t\t\t\t Must be freed by calling\n\t\t\t\t\t FreeFilterVista */\n    DWORD *initialIndexPtr)     /* Will hold index of default type */\n{\n    COMDLG_FILTERSPEC *dlgFilterPtr;\n    const char *initial = NULL;\n    FileFilterList flist;\n    FileFilter *filterPtr;\n    DWORD initialIndex = 0;\n    Tcl_DString ds, patterns;\n    int       i;\n\n    if (optsPtr->filterObj == NULL) {\n\t*dlgFilterPtrPtr = NULL;\n\t*countPtr = 0;\n\treturn TCL_OK;\n    }\n\n    if (optsPtr->initialTypeObj)\n\tinitial = Tcl_GetString(optsPtr->initialTypeObj);\n\n    TkInitFileFilters(&flist);\n    if (TkGetFileFilters(interp, &flist, optsPtr->filterObj, 1) != TCL_OK)\n\treturn TCL_ERROR;\n\n    if (flist.filters == NULL) {\n\t*dlgFilterPtrPtr = NULL;\n\t*countPtr = 0;\n\treturn TCL_OK;\n    }\n\n    Tcl_DStringInit(&ds);\n    Tcl_DStringInit(&patterns);\n    dlgFilterPtr = (COMDLG_FILTERSPEC *)Tcl_Alloc(flist.numFilters * sizeof(*dlgFilterPtr));\n\n    for (i = 0, filterPtr = flist.filters;\n\t filterPtr;\n\t filterPtr = filterPtr->next, ++i) {\n\tconst char *sep;\n\tFileFilterClause *clausePtr;\n\tsize_t nbytes;\n\n\t/* Check if this entry should be shown as the default */\n\tif (initial && strcmp(initial, filterPtr->name) == 0)\n\t    initialIndex = i+1; /* Windows filter indices are 1-based */\n\n\t/* First stash away the text description of the pattern */\n\tTcl_DStringInit(&ds);\n\tTcl_UtfToWCharDString(filterPtr->name, TCL_INDEX_NONE, &ds);\n\tnbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */\n\tnbytes += sizeof(WCHAR);         /* Terminating \\0 */\n\tdlgFilterPtr[i].pszName = (LPCWSTR)Tcl_Alloc(nbytes);\n\tmemmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);\n\tTcl_DStringFree(&ds);\n\n\t/*\n\t * Loop through and join patterns with a \";\" Each \"clause\"\n\t * corresponds to a single textual description (called typename)\n\t * in the tk_getOpenFile docs. Each such typename may occur\n\t * multiple times and all these form a single filter entry\n\t * with one clause per occurence. Further each clause may specify\n\t * multiple patterns. Hence the nested loop here.\n\t */\n\tsep = \"\";\n\tfor (clausePtr=filterPtr->clauses ; clausePtr;\n\t     clausePtr=clausePtr->next) {\n\t    GlobPattern *globPtr;\n\t    for (globPtr = clausePtr->patterns; globPtr;\n\t\t    globPtr = globPtr->next) {\n\t\tTcl_DStringAppend(&patterns, sep, TCL_INDEX_NONE);\n\t\tTcl_DStringAppend(&patterns, globPtr->pattern, TCL_INDEX_NONE);\n\t\tsep = \";\";\n\t    }\n\t}\n\n\t/* Again we need a Unicode form of the string */\n\tTcl_DStringInit(&ds);\n\tTcl_UtfToWCharDString(Tcl_DStringValue(&patterns), TCL_INDEX_NONE, &ds);\n\tnbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */\n\tnbytes += sizeof(WCHAR);         /* Terminating \\0 */\n\tdlgFilterPtr[i].pszSpec = (LPCWSTR)Tcl_Alloc(nbytes);\n\tmemmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);\n\tTcl_DStringFree(&ds);\n\tTcl_DStringSetLength(&patterns, 0);\n    }\n    Tcl_DStringFree(&patterns);\n\n    if (initialIndex == 0) {\n\tinitialIndex = 1;       /* If no default, show first entry */\n    }\n    *initialIndexPtr = initialIndex;\n    *dlgFilterPtrPtr = dlgFilterPtr;\n    *countPtr = flist.numFilters;\n\n    TkFreeFileFilters(&flist);\n    return TCL_OK;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ChooseDirectoryObjCmd --\n *\n *\tThis function implements the \"tk_chooseDirectory\" dialog box for the\n *\tWindows platform. See the user documentation for details on what it\n *\tdoes. Uses the newer SHBrowseForFolder explorer type interface.\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tA modal dialog window is created. Tcl_SetServiceMode() is called to\n *\tallow background events to be processed\n *\n *----------------------------------------------------------------------\n *\n * The function tk_chooseDirectory pops up a dialog box for the user to select\n * a directory. The following option-value pairs are possible as command line\n * arguments:\n *\n * -initialdir dirname\n *\n * Specifies that the directories in directory should be displayed when the\n * dialog pops up. If this parameter is not specified, then the directories in\n * the current working directory are displayed. If the parameter specifies a\n * relative path, the return value will convert the relative path to an\n * absolute path. This option may not always work on the Macintosh. This is\n * not a bug. Rather, the General Controls control panel on the Mac allows the\n * end user to override the application default directory.\n *\n * -parent window\n *\n * Makes window the logical parent of the dialog. The dialog is displayed on\n * top of its parent window.\n *\n * -title titleString\n *\n * Specifies a string to display as the title of the dialog box. If this\n * option is not specified, then a default title will be displayed.\n *\n * -mustexist boolean\n *\n * Specifies whether the user may specify non-existant directories. If this\n * parameter is true, then the user may only select directories that already\n * exist. The default value is false.\n *\n * New Behaviour:\n *\n * - If mustexist = 0 and a user entered folder does not exist, a prompt will\n *   pop-up asking if the user wants another chance to change it. The old\n *   dialog just returned the bogus entry. On mustexist = 1, the entries MUST\n *   exist before exiting the box with OK.\n *\n *   Bugs:\n *\n * - If valid abs directory name is entered into the entry box and Enter\n *   pressed, the box will close returning the name. This is inconsistent when\n *   entering relative names or names with forward slashes, which are\n *   invalidated then corrected in the callback. After correction, the box is\n *   held open to allow further modification by the user.\n *\n * - Not sure how to implement localization of message prompts.\n *\n * - -title is really -message.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_ChooseDirectoryObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    int result;\n    OFNOpts ofnOpts;\n\n    result = ParseOFNOptions(clientData, interp, objc, objv,\n\t\t OFN_DIR_CHOOSE, &ofnOpts);\n    if (result != TCL_OK)\n\treturn result;\n\n    result = GetFileNameVista(interp, &ofnOpts, OFN_DIR_CHOOSE);\n    CleanupOFNOptions(&ofnOpts);\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MessageBoxObjCmd --\n *\n *\tThis function implements the MessageBox window for the Windows\n *\tplatform. See the user documentation for details on what it does.\n *\n * Results:\n *\tSee user documentation.\n *\n * Side effects:\n *\tNone. The MessageBox window will be destroyed before this function\n *\treturns.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_MessageBoxObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData, parent;\n    HWND hWnd;\n    Tcl_Obj *messageObj, *titleObj, *detailObj, *tmpObj;\n    int defaultBtn, icon, type, oldMode, winCode;\n    Tcl_Size i;\n    UINT flags;\n    static const char *const optionStrings[] = {\n\t\"-default\",\t\"-detail\",\t\"-icon\",\t\"-message\",\n\t\"-parent\",\t\"-title\",\t\"-type\",\tNULL\n    };\n    enum options {\n\tMSG_DEFAULT,\tMSG_DETAIL,\tMSG_ICON,\tMSG_MESSAGE,\n\tMSG_PARENT,\tMSG_TITLE,\tMSG_TYPE\n    };\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    Tcl_DString titleBuf, tmpBuf;\n    LPCWSTR titlePtr, tmpPtr;\n    const char *src;\n\n    defaultBtn = -1;\n    detailObj = NULL;\n    icon = MB_ICONINFORMATION;\n    messageObj = NULL;\n    parent = tkwin;\n    titleObj = NULL;\n    type = MB_OK;\n\n    for (i = 1; i < objc; i += 2) {\n\tint index;\n\tTcl_Obj *optionPtr, *valuePtr;\n\n\toptionPtr = objv[i];\n\tvaluePtr = objv[i + 1];\n\n\tif (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings,\n\t\t\"option\", TCL_EXACT, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(optionPtr)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"MSGBOX\", \"VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tswitch ((enum options) index) {\n\tcase MSG_DEFAULT:\n\t    defaultBtn = TkFindStateNumObj(interp, optionPtr, buttonMap,\n\t\t    valuePtr);\n\t    if (defaultBtn < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\n\tcase MSG_DETAIL:\n\t    detailObj = valuePtr;\n\t    break;\n\n\tcase MSG_ICON:\n\t    icon = TkFindStateNumObj(interp, optionPtr, iconMap, valuePtr);\n\t    if (icon < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\n\tcase MSG_MESSAGE:\n\t    messageObj = valuePtr;\n\t    break;\n\n\tcase MSG_PARENT:\n\t    parent = Tk_NameToWindow(interp, Tcl_GetString(valuePtr), tkwin);\n\t    if (parent == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\n\tcase MSG_TITLE:\n\t    titleObj = valuePtr;\n\t    break;\n\n\tcase MSG_TYPE:\n\t    type = TkFindStateNumObj(interp, optionPtr, typeMap, valuePtr);\n\t    if (type < 0) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    break;\n\t}\n    }\n\n    while (!Tk_IsTopLevel(parent)) {\n\tparent = Tk_Parent(parent);\n    }\n    Tk_MakeWindowExist(parent);\n    hWnd = Tk_GetHWND(Tk_WindowId(parent));\n\n    flags = 0;\n    if (defaultBtn >= 0) {\n\tint defaultBtnIdx = -1;\n\n\tfor (i = 0; i < (int) NUM_TYPES; i++) {\n\t    if (type == allowedTypes[i].type) {\n\t\tint j;\n\n\t\tfor (j = 0; j < 3; j++) {\n\t\t    if (allowedTypes[i].btnIds[j] == defaultBtn) {\n\t\t\tdefaultBtnIdx = j;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tif (defaultBtnIdx < 0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"invalid default button \\\"%s\\\"\",\n\t\t\t    TkFindStateString(buttonMap, defaultBtn)));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"MSGBOX\", \"DEFAULT\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\tflags = buttonFlagMap[defaultBtnIdx];\n    }\n\n    flags |= icon | type | MB_TASKMODAL | MB_SETFOREGROUND;\n\n    tmpObj = messageObj ? Tcl_DuplicateObj(messageObj) : Tcl_NewObj();\n    Tcl_IncrRefCount(tmpObj);\n    if (detailObj) {\n\tTcl_AppendStringsToObj(tmpObj, \"\\n\\n\", (char *)NULL);\n\tTcl_AppendObjToObj(tmpObj, detailObj);\n    }\n\n    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n\n    /*\n     * MessageBoxW exists for all platforms. Use it to allow unicode error\n     * message to be displayed correctly where possible by the OS.\n     *\n     * In order to have the parent window icon reflected in a MessageBox, we\n     * have to create a hook that will trigger when the MessageBox is being\n     * created.\n     */\n\n    tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL);\n    tsdPtr->hBigIcon   = TkWinGetIcon(parent, ICON_BIG);\n    tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL,\n\t    GetCurrentThreadId());\n    src = Tcl_GetString(tmpObj);\n    Tcl_DStringInit(&tmpBuf);\n    tmpPtr = Tcl_UtfToWCharDString(src, tmpObj->length, &tmpBuf);\n    if (titleObj != NULL) {\n\tsrc = Tcl_GetString(titleObj);\n\tTcl_DStringInit(&titleBuf);\n\ttitlePtr = Tcl_UtfToWCharDString(src, titleObj->length, &titleBuf);\n    } else {\n\ttitlePtr = L\"\";\n\tTcl_DStringInit(&titleBuf);\n    }\n    winCode = MessageBoxW(hWnd, tmpPtr, titlePtr, flags);\n    Tcl_DStringFree(&titleBuf);\n    Tcl_DStringFree(&tmpBuf);\n    UnhookWindowsHookEx(tsdPtr->hMsgBoxHook);\n    (void) Tcl_SetServiceMode(oldMode);\n\n    /*\n     * Ensure that hWnd is enabled, because it can happen that we have updated\n     * the wrapper of the parent, which causes us to leave this child disabled\n     * (Windows loses sync).\n     */\n\n    EnableWindow(hWnd, 1);\n\n    Tcl_DecrRefCount(tmpObj);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    TkFindStateString(buttonMap, winCode), TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\f\nstatic LRESULT CALLBACK\nMsgBoxCBTProc(\n    int nCode,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (nCode == HCBT_CREATEWND) {\n\t/*\n\t * Window owned by our task is being created. Since the hook is\n\t * installed just before the MessageBox call and removed after the\n\t * MessageBox call, the window being created is either the message box\n\t * or one of its controls. Check that the class is WC_DIALOG to ensure\n\t * that it's the one we want.\n\t */\n\n\tLPCBT_CREATEWND lpcbtcreate = (LPCBT_CREATEWND) lParam;\n\n\tif (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) {\n\t    HWND hwnd = (HWND) wParam;\n\n\t    SendMessageW(hwnd, WM_SETICON, ICON_SMALL,\n\t\t    (LPARAM) tsdPtr->hSmallIcon);\n\t    SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);\n\t}\n    }\n\n    /*\n     * Call the next hook proc, if there is one\n     */\n\n    return CallNextHookEx(tsdPtr->hMsgBoxHook, nCode, wParam, lParam);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * SetTestDialog --\n *\n *\tRecords the HWND for a native dialog in the variable\n *\t\"::tk::test::dialog::testDialog\" so that the test-suite can operate\n *\ton the correct dialog window. Use of this is enabled when a test\n *\tprogram calls TkWinDialogDebug by calling the test command\n *\t'testwinevent debug 1'.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\nSetTestDialog(\n    void *clientData)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    char buf[32];\n\n    snprintf(buf, sizeof(buf), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)clientData);\n    Tcl_SetVar2(tsdPtr->debugInterp, \"::tk::test::dialog::testDialog\", NULL,\n\t\tbuf, TCL_GLOBAL_ONLY);\n}\n\f\n/*\n * Factored out a common pattern in use in this file.\n */\n\nstatic const char *\nConvertExternalFilename(\n    LPCWSTR  filename,\n    Tcl_DString *dsPtr)\n{\n    char *p;\n\n    Tcl_DStringInit(dsPtr);\n    Tcl_WCharToUtfDString(filename, wcslen(filename), dsPtr);\n    for (p = Tcl_DStringValue(dsPtr); *p != '\\0'; p++) {\n\t/*\n\t * Change the pathname to the Tcl \"normalized\" pathname, where back\n\t * slashes are used instead of forward slashes\n\t */\n\n\tif (*p == '\\\\') {\n\t    *p = '/';\n\t}\n    }\n    return Tcl_DStringValue(dsPtr);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * GetFontObj --\n *\n *\tConvert a windows LOGFONT into a Tk font description.\n *\n * Result:\n *\tA list containing a Tk font description.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic Tcl_Obj *\nGetFontObj(\n    HDC hdc,\n    LOGFONTW *plf)\n{\n    Tcl_DString ds;\n    Tcl_Obj *resObj;\n    int pt = 0;\n\n    resObj = Tcl_NewListObj(0, NULL);\n    Tcl_DStringInit(&ds);\n    Tcl_WCharToUtfDString(plf->lfFaceName, wcslen(plf->lfFaceName), &ds);\n    Tcl_ListObjAppendElement(NULL, resObj,\n\t    Tcl_NewStringObj(Tcl_DStringValue(&ds), TCL_INDEX_NONE));\n    Tcl_DStringFree(&ds);\n    pt = -MulDiv(plf->lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY));\n    Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewWideIntObj(pt));\n    if (plf->lfWeight >= 700) {\n\tTcl_ListObjAppendElement(NULL, resObj, Tcl_NewStringObj(\"bold\", TCL_INDEX_NONE));\n    }\n    if (plf->lfItalic) {\n\tTcl_ListObjAppendElement(NULL, resObj,\n\t\tTcl_NewStringObj(\"italic\", TCL_INDEX_NONE));\n    }\n    if (plf->lfUnderline) {\n\tTcl_ListObjAppendElement(NULL, resObj,\n\t\tTcl_NewStringObj(\"underline\", TCL_INDEX_NONE));\n    }\n    if (plf->lfStrikeOut) {\n\tTcl_ListObjAppendElement(NULL, resObj,\n\t\tTcl_NewStringObj(\"overstrike\", TCL_INDEX_NONE));\n    }\n    return resObj;\n}\n\f\nstatic void\nApplyLogfont(\n    Tcl_Interp *interp,\n    Tcl_Obj *cmdObj,\n    HDC hdc,\n    LOGFONTW *logfontPtr)\n{\n    Tcl_Size objc;\n    Tcl_Obj **objv, **tmpv;\n\n    Tcl_ListObjGetElements(NULL, cmdObj, &objc, &objv);\n    tmpv = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * (objc + 2));\n    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);\n    tmpv[objc] = GetFontObj(hdc, logfontPtr);\n    TkBackgroundEvalObjv(interp, objc+1, tmpv, TCL_EVAL_GLOBAL);\n    Tcl_Free(tmpv);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * HookProc --\n *\n *\tFont selection hook. If the user selects Apply on the dialog, we call\n *\tthe applyProc script with the currently selected font as arguments.\n *\n * ----------------------------------------------------------------------\n */\n\ntypedef struct HookData {\n    Tcl_Interp *interp;\n    Tcl_Obj *titleObj;\n    Tcl_Obj *cmdObj;\n    Tcl_Obj *parentObj;\n    Tcl_Obj *fontObj;\n    HWND hwnd;\n    Tk_Window parent;\n} HookData;\n\nstatic UINT_PTR CALLBACK\nHookProc(\n    HWND hwndDlg,\n    UINT msg,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    CHOOSEFONTW *pcf = (CHOOSEFONTW *) lParam;\n    HWND hwndCtrl;\n    static HookData *phd = NULL;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (WM_INITDIALOG == msg && lParam != 0) {\n\tphd = (HookData *) pcf->lCustData;\n\tphd->hwnd = hwndDlg;\n\tif (tsdPtr->debugFlag) {\n\t    tsdPtr->debugInterp = phd->interp;\n\t    Tcl_DoWhenIdle(SetTestDialog, hwndDlg);\n\t}\n\tif (phd->titleObj != NULL) {\n\t    Tcl_DString title;\n\n\t    Tcl_DStringInit(&title);\n\t    Tcl_UtfToWCharDString(Tcl_GetString(phd->titleObj), TCL_INDEX_NONE, &title);\n\t    if (Tcl_DStringLength(&title) > 0) {\n\t\tSetWindowTextW(hwndDlg, (LPCWSTR) Tcl_DStringValue(&title));\n\t    }\n\t    Tcl_DStringFree(&title);\n\t}\n\n\t/*\n\t * Disable the colour combobox (0x473) and its label (0x443).\n\t */\n\n\thwndCtrl = GetDlgItem(hwndDlg, 0x443);\n\tif (IsWindow(hwndCtrl)) {\n\t    EnableWindow(hwndCtrl, FALSE);\n\t}\n\thwndCtrl = GetDlgItem(hwndDlg, 0x473);\n\tif (IsWindow(hwndCtrl)) {\n\t    EnableWindow(hwndCtrl, FALSE);\n\t}\n\tTk_SendVirtualEvent(phd->parent, \"TkFontchooserVisibility\", NULL);\n\treturn 1; /* we handled the message */\n    }\n\n    if (WM_DESTROY == msg) {\n\tphd->hwnd = NULL;\n\tTk_SendVirtualEvent(phd->parent, \"TkFontchooserVisibility\", NULL);\n\treturn 0;\n    }\n\n    /*\n     * Handle apply button by calling the provided command script as a\n     * background evaluation (ie: errors dont come back here).\n     */\n\n    if (WM_COMMAND == msg && LOWORD(wParam) == 1026) {\n\tLOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0}};\n\tHDC hdc = GetDC(hwndDlg);\n\n\tSendMessageW(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);\n\tif (phd && phd->cmdObj) {\n\t    ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf);\n\t}\n\tif (phd && phd->parent) {\n\t    Tk_SendVirtualEvent(phd->parent, \"TkFontchooserFontChanged\", NULL);\n\t}\n\treturn 1;\n    }\n    return 0; /* pass on for default processing */\n}\n\f\n/*\n * Helper for the FontchooserConfigure command to return the current value of\n * any of the options (which may be NULL in the structure)\n */\n\ntypedef enum {\n    FontchooserCmd, FontchooserFont, FontchooserParent, FontchooserTitle,\n    FontchooserVisible\n} FontchooserOption;\n\nstatic Tcl_Obj *\nFontchooserCget(\n    HookData *hdPtr,\n    FontchooserOption optionIndex)\n{\n    Tcl_Obj *resObj = NULL;\n\n    switch(optionIndex) {\n    case FontchooserParent:\n\tif (hdPtr->parentObj) {\n\t    resObj = hdPtr->parentObj;\n\t} else {\n\t    resObj = Tcl_NewStringObj(\".\", 1);\n\t}\n\tbreak;\n    case FontchooserTitle:\n\tif (hdPtr->titleObj) {\n\t    resObj = hdPtr->titleObj;\n\t} else {\n\t    resObj =  Tcl_NewStringObj(\"\", 0);\n\t}\n\tbreak;\n    case FontchooserFont:\n\tif (hdPtr->fontObj) {\n\t    resObj = hdPtr->fontObj;\n\t} else {\n\t    resObj = Tcl_NewStringObj(\"\", 0);\n\t}\n\tbreak;\n    case FontchooserCmd:\n\tif (hdPtr->cmdObj) {\n\t    resObj = hdPtr->cmdObj;\n\t} else {\n\t    resObj = Tcl_NewStringObj(\"\", 0);\n\t}\n\tbreak;\n    case FontchooserVisible:\n\tresObj = Tcl_NewBooleanObj((hdPtr->hwnd != NULL) && IsWindow(hdPtr->hwnd));\n\tbreak;\n    default:\n\tresObj = Tcl_NewStringObj(\"\", 0);\n    }\n    return resObj;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserConfigureCmd --\n *\n *\tImplementation of the 'tk fontchooser configure' ensemble command. See\n *\tthe user documentation for what it does.\n *\n * Results:\n *\tSee the user documentation.\n *\n * Side effects:\n *\tPer-interp data structure may be modified\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserConfigureCmd(\n    void *clientData,\t/* Main window */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    HookData *hdPtr = NULL;\n    Tcl_Size i;\n    int r = TCL_OK;\n    static const char *const optionStrings[] = {\n\t\"-command\", \"-font\", \"-parent\", \"-title\", \"-visible\", NULL\n    };\n\n    hdPtr = (HookData *)Tcl_GetAssocData(interp, \"::tk::fontchooser\", NULL);\n\n    /*\n     * With no arguments we return all the options in a dict.\n     */\n\n    if (objc == 1) {\n\tTcl_Obj *keyObj, *valueObj;\n\tTcl_Obj *dictObj = Tcl_NewDictObj();\n\n\tfor (i = 0; r == TCL_OK && optionStrings[i] != NULL; ++i) {\n\t    keyObj = Tcl_NewStringObj(optionStrings[i], TCL_INDEX_NONE);\n\t    valueObj = FontchooserCget(hdPtr, (FontchooserOption)i);\n\t    r = Tcl_DictObjPut(interp, dictObj, keyObj, valueObj);\n\t}\n\tif (r == TCL_OK) {\n\t    Tcl_SetObjResult(interp, dictObj);\n\t}\n\treturn r;\n    }\n\n    for (i = 1; i < objc; i += 2) {\n\tint optionIndex;\n\n\tif (Tcl_GetIndexFromObj(interp, objv[i], optionStrings,\n\t\t\"option\", 0, &optionIndex) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 2) {\n\t    /*\n\t     * If one option and no arg - return the current value.\n\t     */\n\n\t    Tcl_SetObjResult(interp, FontchooserCget(hdPtr, optionIndex));\n\t    return TCL_OK;\n\t}\n\tif (i + 1 == objc) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"value for \\\"%s\\\" missing\", Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FONTDIALOG\", \"VALUE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tswitch (optionIndex) {\n\tcase FontchooserVisible: {\n\t    static const char *msg = \"cannot change read-only option \"\n\t\t    \"\\\"-visible\\\": use the show or hide command\";\n\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"FONTDIALOG\", \"READONLY\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tcase FontchooserParent: {\n\t    Tk_Window parent = Tk_NameToWindow(interp,\n\t\t    Tcl_GetString(objv[i+1]), tkwin);\n\n\t    if (parent == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (hdPtr->parentObj) {\n\t\tTcl_DecrRefCount(hdPtr->parentObj);\n\t    }\n\t    hdPtr->parentObj = objv[i+1];\n\t    if (Tcl_IsShared(hdPtr->parentObj)) {\n\t\thdPtr->parentObj = Tcl_DuplicateObj(hdPtr->parentObj);\n\t    }\n\t    Tcl_IncrRefCount(hdPtr->parentObj);\n\t    break;\n\t}\n\tcase FontchooserTitle:\n\t    if (hdPtr->titleObj) {\n\t\tTcl_DecrRefCount(hdPtr->titleObj);\n\t    }\n\t    hdPtr->titleObj = objv[i+1];\n\t    if (Tcl_IsShared(hdPtr->titleObj)) {\n\t\thdPtr->titleObj = Tcl_DuplicateObj(hdPtr->titleObj);\n\t    }\n\t    Tcl_IncrRefCount(hdPtr->titleObj);\n\t    break;\n\tcase FontchooserFont:\n\t    if (hdPtr->fontObj) {\n\t\tTcl_DecrRefCount(hdPtr->fontObj);\n\t    }\n\t    Tcl_GetString(objv[i+1]);\n\t    if (objv[i+1]->length) {\n\t\thdPtr->fontObj = objv[i+1];\n\t\tif (Tcl_IsShared(hdPtr->fontObj)) {\n\t\t    hdPtr->fontObj = Tcl_DuplicateObj(hdPtr->fontObj);\n\t\t}\n\t\tTcl_IncrRefCount(hdPtr->fontObj);\n\t    } else {\n\t\thdPtr->fontObj = NULL;\n\t    }\n\t    break;\n\tcase FontchooserCmd:\n\t    if (hdPtr->cmdObj) {\n\t\tTcl_DecrRefCount(hdPtr->cmdObj);\n\t    }\n\t    Tcl_GetString(objv[i+1]);\n\t    if (objv[i+1]->length) {\n\t\thdPtr->cmdObj = objv[i+1];\n\t\tif (Tcl_IsShared(hdPtr->cmdObj)) {\n\t\t    hdPtr->cmdObj = Tcl_DuplicateObj(hdPtr->cmdObj);\n\t\t}\n\t\tTcl_IncrRefCount(hdPtr->cmdObj);\n\t    } else {\n\t\thdPtr->cmdObj = NULL;\n\t    }\n\t    break;\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserShowCmd --\n *\n *\tImplements the 'tk fontchooser show' ensemble command. The per-interp\n *\tconfiguration data for the dialog is held in an interp associated\n *\tstructure.\n *\n *\tCalls the Win32 FontChooser API which provides a modal dialog. See\n *\tHookProc where we make a few changes to the dialog and set some\n *\tadditional state.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserShowCmd(\n    void *clientData,\t/* Main window */\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    Tcl_DString ds;\n    Tk_Window tkwin = (Tk_Window)clientData, parent;\n    CHOOSEFONTW cf;\n    LOGFONTW lf;\n    HDC hdc;\n    HookData *hdPtr;\n    int r = TCL_OK, oldMode = 0;\n\n    hdPtr = (HookData *)Tcl_GetAssocData(interp, \"::tk::fontchooser\", NULL);\n\n    parent = tkwin;\n    if (hdPtr->parentObj) {\n\tparent = Tk_NameToWindow(interp, Tcl_GetString(hdPtr->parentObj),\n\t\ttkwin);\n\tif (parent == NULL) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    Tk_MakeWindowExist(parent);\n\n    memset(&cf, 0, sizeof(CHOOSEFONTW));\n    memset(&lf, 0, sizeof(LOGFONTW));\n    lf.lfCharSet = DEFAULT_CHARSET;\n    cf.lStructSize = sizeof(CHOOSEFONTW);\n    cf.hwndOwner = Tk_GetHWND(Tk_WindowId(parent));\n    cf.lpLogFont = &lf;\n    cf.nFontType = SCREEN_FONTTYPE;\n    cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_ENABLEHOOK;\n    cf.rgbColors = RGB(0,0,0);\n    cf.lpfnHook = HookProc;\n    cf.lCustData = (INT_PTR) hdPtr;\n    hdPtr->interp = interp;\n    hdPtr->parent = parent;\n    hdc = GetDC(cf.hwndOwner);\n\n    if (hdPtr->fontObj != NULL) {\n\tTkFont *fontPtr;\n\tTk_Font f = Tk_AllocFontFromObj(interp, tkwin, hdPtr->fontObj);\n\n\tif (f == NULL) {\n\t    return TCL_ERROR;\n\t}\n\tfontPtr = (TkFont *) f;\n\tcf.Flags |= CF_INITTOLOGFONTSTRUCT;\n\tTcl_DStringInit(&ds);\n\twcsncpy(lf.lfFaceName, Tcl_UtfToWCharDString(fontPtr->fa.family, TCL_INDEX_NONE, &ds),\n\t\tLF_FACESIZE-1);\n\tTcl_DStringFree(&ds);\n\tlf.lfFaceName[LF_FACESIZE-1] = 0;\n\tlf.lfHeight = -MulDiv((int)(TkFontGetPoints(tkwin, fontPtr->fa.size) + 0.5),\n\t    GetDeviceCaps(hdc, LOGPIXELSY), 72);\n\tif (fontPtr->fa.weight == TK_FW_BOLD) {\n\t    lf.lfWeight = FW_BOLD;\n\t}\n\tif (fontPtr->fa.slant != TK_FS_ROMAN) {\n\t    lf.lfItalic = TRUE;\n\t}\n\tif (fontPtr->fa.underline) {\n\t    lf.lfUnderline = TRUE;\n\t}\n\tif (fontPtr->fa.overstrike) {\n\t    lf.lfStrikeOut = TRUE;\n\t}\n\tTk_FreeFont(f);\n    }\n\n    if (TCL_OK == r && hdPtr->cmdObj != NULL) {\n\tTcl_Size len = 0;\n\n\tr = Tcl_ListObjLength(interp, hdPtr->cmdObj, &len);\n\tif (len > 0) {\n\t    cf.Flags |= CF_APPLY;\n\t}\n    }\n\n    if (TCL_OK == r) {\n\toldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n\tif (ChooseFontW(&cf)) {\n\t    if (hdPtr->cmdObj) {\n\t\tApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf);\n\t    }\n\t    if (hdPtr->parent) {\n\t\tTk_SendVirtualEvent(hdPtr->parent, \"TkFontchooserFontChanged\", NULL);\n\t    }\n\t}\n\tTcl_SetServiceMode(oldMode);\n\tEnableWindow(cf.hwndOwner, 1);\n    }\n\n    ReleaseDC(cf.hwndOwner, hdc);\n    return r;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * FontchooserHideCmd --\n *\n *\tImplementation of the 'tk fontchooser hide' ensemble. See the user\n *\tdocumentation for details.\n *\tAs the Win32 FontChooser function is always modal all we do here is\n *\tdestroy the dialog\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nFontchooserHideCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    HookData *hdPtr = (HookData *)Tcl_GetAssocData(interp, \"::tk::fontchooser\", NULL);\n\n    if (hdPtr->hwnd && IsWindow(hdPtr->hwnd)) {\n\tEndDialog(hdPtr->hwnd, 0);\n    }\n    return TCL_OK;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * DeleteHookData --\n *\n *\tClean up the font chooser configuration data when the interp is\n *\tdestroyed.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\nDeleteHookData(\n    void *clientData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    HookData *hdPtr = (HookData *)clientData;\n\n    if (hdPtr->parentObj) {\n\tTcl_DecrRefCount(hdPtr->parentObj);\n    }\n    if (hdPtr->fontObj) {\n\tTcl_DecrRefCount(hdPtr->fontObj);\n    }\n    if (hdPtr->titleObj) {\n\tTcl_DecrRefCount(hdPtr->titleObj);\n    }\n    if (hdPtr->cmdObj) {\n\tTcl_DecrRefCount(hdPtr->cmdObj);\n    }\n    Tcl_Free(hdPtr);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkInitFontchooser --\n *\n *\tAssociate the font chooser configuration data with the Tcl\n *\tinterpreter. There is one font chooser per interp.\n *\n * ----------------------------------------------------------------------\n */\n\nMODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[];\nconst TkEnsemble tkFontchooserEnsemble[] = {\n    { \"configure\", FontchooserConfigureCmd, NULL },\n    { \"show\", FontchooserShowCmd, NULL },\n    { \"hide\", FontchooserHideCmd, NULL },\n    { NULL, NULL, NULL }\n};\n\nint\nTkInitFontchooser(\n    Tcl_Interp *interp,\n    TCL_UNUSED(void *))\n{\n    HookData *hdPtr = (HookData *)Tcl_Alloc(sizeof(HookData));\n\n    memset(hdPtr, 0, sizeof(HookData));\n    Tcl_SetAssocData(interp, \"::tk::fontchooser\", DeleteHookData, hdPtr);\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinDraw.c",
    "content": "/*\n * tkWinDraw.c --\n *\n *\tThis file contains the Xlib emulation functions pertaining to actually\n *\tdrawing objects on a window.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n * Copyright © 1994 Software Research Associates, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n/*\n * These macros convert between X's bizarre angle units to radians.\n */\n\n#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);\n\n/*\n * Translation table between X gc functions and Win32 raster op modes.\n */\n\nconst int tkpWinRopModes[] = {\n    R2_BLACK,\t\t\t/* GXclear */\n    R2_MASKPEN,\t\t\t/* GXand */\n    R2_MASKPENNOT,\t\t/* GXandReverse */\n    R2_COPYPEN,\t\t\t/* GXcopy */\n    R2_MASKNOTPEN,\t\t/* GXandInverted */\n    R2_NOP,\t\t\t/* GXnoop */\n    R2_XORPEN,\t\t\t/* GXxor */\n    R2_MERGEPEN,\t\t/* GXor */\n    R2_NOTMERGEPEN,\t\t/* GXnor */\n    R2_NOTXORPEN,\t\t/* GXequiv */\n    R2_NOT,\t\t\t/* GXinvert */\n    R2_MERGEPENNOT,\t\t/* GXorReverse */\n    R2_NOTCOPYPEN,\t\t/* GXcopyInverted */\n    R2_MERGENOTPEN,\t\t/* GXorInverted */\n    R2_NOTMASKPEN,\t\t/* GXnand */\n    R2_WHITE\t\t\t/* GXset */\n};\n\n/*\n * Translation table between X gc functions and Win32 BitBlt op modes. Some of\n * the operations defined in X don't have names, so we have to construct new\n * opcodes for those functions. This is arcane and probably not all that\n * useful, but at least it's accurate.\n */\n\n#define NOTSRCAND\t(DWORD)0x00220326 /* dest = (NOT source) AND dest */\n#define NOTSRCINVERT\t(DWORD)0x00990066 /* dest = (NOT source) XOR dest */\n#define SRCORREVERSE\t(DWORD)0x00DD0228 /* dest = source OR (NOT dest) */\n#define SRCNAND\t\t(DWORD)0x007700E6 /* dest = NOT (source AND dest) */\n\nconst int tkpWinBltModes[] = {\n    BLACKNESS,\t\t\t/* GXclear */\n    SRCAND,\t\t\t/* GXand */\n    SRCERASE,\t\t\t/* GXandReverse */\n    SRCCOPY,\t\t\t/* GXcopy */\n    NOTSRCAND,\t\t\t/* GXandInverted */\n    PATCOPY,\t\t\t/* GXnoop */\n    SRCINVERT,\t\t\t/* GXxor */\n    SRCPAINT,\t\t\t/* GXor */\n    NOTSRCERASE,\t\t/* GXnor */\n    NOTSRCINVERT,\t\t/* GXequiv */\n    DSTINVERT,\t\t\t/* GXinvert */\n    SRCORREVERSE,\t\t/* GXorReverse */\n    NOTSRCCOPY,\t\t\t/* GXcopyInverted */\n    MERGEPAINT,\t\t\t/* GXorInverted */\n    SRCNAND,\t\t\t/* GXnand */\n    WHITENESS\t\t\t/* GXset */\n};\n\n/*\n * The following raster op uses the source bitmap as a mask for the pattern.\n * This is used to draw in a foreground color but leave the background color\n * transparent.\n */\n\n#define MASKPAT\t\t0x00E20746 /* dest = (src & pat) | (!src & dst) */\n\n/*\n * The following two raster ops are used to copy the foreground and background\n * bits of a source pattern as defined by a stipple used as the pattern.\n */\n\n#define COPYFG\t\t0x00CA0749 /* dest = (pat & src) | (!pat & dst) */\n#define COPYBG\t\t0x00AC0744 /* dest = (!pat & src) | (pat & dst) */\n\n/*\n * Macros used later in the file.\n */\n#ifndef MIN\n#   define MIN(a,b)\t((a>b) ? b : a)\n#   define MAX(a,b)\t((a<b) ? b : a)\n#endif\n\n/*\n * The followng typedef is used to pass Windows GDI drawing functions.\n */\n\ntypedef BOOL (CALLBACK *WinDrawFunc)(HDC dc, const POINT *points, int npoints);\n\ntypedef struct {\n    POINT *winPoints;\t\t/* Array of points that is reused. */\n    int nWinPoints;\t\t/* Current size of point array. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic POINT *\t\tConvertPoints(XPoint *points, int npoints, int mode,\n\t\t\t    RECT *bbox);\nstatic int\t\tDrawOrFillArc(Display *display, Drawable d, GC gc,\n\t\t\t    int x, int y, unsigned int width,\n\t\t\t    unsigned int height, int start, int extent,\n\t\t\t    int fill);\nstatic void\t\tRenderObject(HDC dc, GC gc, XPoint* points,\n\t\t\t    int npoints, int mode, HPEN pen, WinDrawFunc func);\nstatic HPEN\t\tSetUpGraphicsPort(GC gc);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetDrawableDC --\n *\n *\tRetrieve the DC from a drawable.\n *\n * Results:\n *\tReturns the window DC for windows. Returns a new memory DC for\n *\tpixmaps.\n *\n * Side effects:\n *\tSets up the palette for the device context, and saves the old device\n *\tcontext state in the passed in TkWinDCState structure.\n *\n *----------------------------------------------------------------------\n */\n\nHDC\nTkWinGetDrawableDC(\n    Display *display,\n    Drawable d,\n    TkWinDCState *state)\n{\n    HDC dc;\n    TkWinDrawable *twdPtr = (TkWinDrawable *)d;\n    Colormap cmap;\n\n    if (twdPtr->type == TWD_WINDOW) {\n\tTkWindow *winPtr = twdPtr->window.winPtr;\n\n\tdc = GetDC(twdPtr->window.handle);\n\tif (winPtr == NULL) {\n\t    cmap = DefaultColormap(display, DefaultScreen(display));\n\t} else {\n\t    cmap = winPtr->atts.colormap;\n\t}\n    } else if (twdPtr->type == TWD_WINDC) {\n\tdc = twdPtr->winDC.hdc;\n\tcmap = DefaultColormap(display, DefaultScreen(display));\n    } else {\n\tdc = CreateCompatibleDC(NULL);\n\tSelectObject(dc, twdPtr->bitmap.handle);\n\tcmap = twdPtr->bitmap.colormap;\n    }\n    state->palette = TkWinSelectPalette(dc, cmap);\n    state->bkmode  = GetBkMode(dc);\n    return dc;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinReleaseDrawableDC --\n *\n *\tFrees the resources associated with a drawable's DC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the old bitmap handle to the memory DC for pixmaps.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinReleaseDrawableDC(\n    Drawable d,\n    HDC dc,\n    TkWinDCState *state)\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *)d;\n\n    SetBkMode(dc, state->bkmode);\n    SelectPalette(dc, state->palette, TRUE);\n    RealizePalette(dc);\n    if (twdPtr->type == TWD_WINDOW) {\n\tReleaseDC(TkWinGetHWND(d), dc);\n    } else if (twdPtr->type == TWD_BITMAP) {\n\tDeleteDC(dc);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConvertPoints --\n *\n *\tConvert an array of X points to an array of Win32 points.\n *\n * Results:\n *\tReturns the converted array of POINTs.\n *\n * Side effects:\n *\tAllocates a block of memory in thread local storage that should not be\n *\tfreed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic POINT *\nConvertPoints(\n    XPoint *points,\n    int npoints,\n    int mode,\t\t\t/* CoordModeOrigin or CoordModePrevious. */\n    RECT *bbox)\t\t\t/* Bounding box of points. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    int i;\n\n    /*\n     * To avoid paying the cost of a malloc on every drawing routine, we reuse\n     * the last array if it is large enough.\n     */\n\n    if (npoints > tsdPtr->nWinPoints) {\n\tif (tsdPtr->winPoints != NULL) {\n\t    Tcl_Free(tsdPtr->winPoints);\n\t}\n\ttsdPtr->winPoints = (POINT *)Tcl_Alloc(sizeof(POINT) * (size_t)npoints);\n\tif (tsdPtr->winPoints == NULL) {\n\t    tsdPtr->nWinPoints = -1;\n\t    return NULL;\n\t}\n\ttsdPtr->nWinPoints = npoints;\n    }\n\n    bbox->left = bbox->right = points[0].x;\n    bbox->top = bbox->bottom = points[0].y;\n\n    if (mode == CoordModeOrigin) {\n\tfor (i = 0; i < npoints; i++) {\n\t    tsdPtr->winPoints[i].x = points[i].x;\n\t    tsdPtr->winPoints[i].y = points[i].y;\n\t    bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);\n\t    bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);\n\t    bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);\n\t    bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);\n\t}\n    } else {\n\ttsdPtr->winPoints[0].x = points[0].x;\n\ttsdPtr->winPoints[0].y = points[0].y;\n\tfor (i = 1; i < npoints; i++) {\n\t    tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x;\n\t    tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y;\n\t    bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);\n\t    bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);\n\t    bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);\n\t    bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);\n\t}\n    }\n    return tsdPtr->winPoints;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCopyArea --\n *\n *\tCopies data from one drawable to another using block transfer\n *\troutines.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tData is moved from a window or bitmap to a second window or bitmap.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXCopyArea(\n    Display *display,\n    Drawable src,\n    Drawable dest,\n    GC gc,\n    int src_x, int src_y,\n    unsigned int width, unsigned int height,\n    int dest_x, int dest_y)\n{\n    HDC srcDC, destDC;\n    TkWinDCState srcState, destState;\n    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;\n\n    srcDC = TkWinGetDrawableDC(display, src, &srcState);\n\n    if (src != dest) {\n\tdestDC = TkWinGetDrawableDC(display, dest, &destState);\n    } else {\n\tdestDC = srcDC;\n    }\n\n    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {\n\tSelectClipRgn(destDC, (HRGN) clipPtr->value.region);\n\tOffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);\n    }\n\n    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,\n\t    src_x, src_y, (DWORD) tkpWinBltModes[gc->function]);\n\n    SelectClipRgn(destDC, NULL);\n\n    if (src != dest) {\n\tTkWinReleaseDrawableDC(dest, destDC, &destState);\n    }\n    TkWinReleaseDrawableDC(src, srcDC, &srcState);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCopyPlane --\n *\n *\tCopies a bitmap from a source drawable to a destination drawable. The\n *\tplane argument specifies which bit plane of the source contains the\n *\tbitmap. Note that this implementation ignores the gc->function.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the destination drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXCopyPlane(\n    Display *display,\n    Drawable src,\n    Drawable dest,\n    GC gc,\n    int src_x, int src_y,\n    unsigned int width, unsigned int height,\n    int dest_x, int dest_y,\n    unsigned long plane)\n{\n    HDC srcDC, destDC;\n    TkWinDCState srcState, destState;\n    HBRUSH bgBrush, fgBrush, oldBrush;\n    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;\n\n    LastKnownRequestProcessed(display)++;\n\n    if (plane != 1) {\n\tTcl_Panic(\"Unexpected plane specified for XCopyPlane\");\n    }\n\n    srcDC = TkWinGetDrawableDC(display, src, &srcState);\n\n    if (src != dest) {\n\tdestDC = TkWinGetDrawableDC(display, dest, &destState);\n    } else {\n\tdestDC = srcDC;\n    }\n\n    if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {\n\t/*\n\t * Case 1: opaque bitmaps. Windows handles the conversion from one bit\n\t * to multiple bits by setting 0 to the foreground color, and 1 to the\n\t * background color (seems backwards, but there you are).\n\t */\n\n\tif (clipPtr && clipPtr->type == TKP_CLIP_REGION) {\n\t    SelectClipRgn(destDC, (HRGN) clipPtr->value.region);\n\t    OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);\n\t}\n\n\tSetBkMode(destDC, OPAQUE);\n\tSetBkColor(destDC, gc->foreground);\n\tSetTextColor(destDC, gc->background);\n\tBitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,\n\t\tsrc_x, src_y, SRCCOPY);\n\n\tSelectClipRgn(destDC, NULL);\n    } else if (clipPtr->type == TKP_CLIP_PIXMAP) {\n\tif (clipPtr->value.pixmap == src) {\n\n\t    /*\n\t     * Case 2: transparent bitmaps are handled by setting the\n\t     * destination to the foreground color whenever the source pixel\n\t     * is set.\n\t     */\n\n\t    fgBrush = CreateSolidBrush(gc->foreground);\n\t    oldBrush = (HBRUSH)SelectObject(destDC, fgBrush);\n\t    SetBkColor(destDC, RGB(255,255,255));\n\t    SetTextColor(destDC, RGB(0,0,0));\n\t    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,\n\t\t    src_x, src_y, MASKPAT);\n\t    SelectObject(destDC, oldBrush);\n\t    DeleteObject(fgBrush);\n\t} else {\n\n\t    /*\n\t     * Case 3: two arbitrary bitmaps. Copy the source rectangle into a\n\t     * color pixmap. Use the result as a brush when copying the clip\n\t     * mask into the destination.\n\t     */\n\n\t    HDC memDC, maskDC;\n\t    HBITMAP bitmap;\n\t    TkWinDCState maskState;\n\n\t    fgBrush = CreateSolidBrush(gc->foreground);\n\t    bgBrush = CreateSolidBrush(gc->background);\n\t    maskDC = TkWinGetDrawableDC(display, clipPtr->value.pixmap,\n\t\t    &maskState);\n\t    memDC = CreateCompatibleDC(destDC);\n\t    bitmap = CreateBitmap((int) width, (int) height, 1, 1, NULL);\n\t    SelectObject(memDC, bitmap);\n\n\t    /*\n\t     * Set foreground bits. We create a new bitmap containing (source\n\t     * AND mask), then use it to set the foreground color into the\n\t     * destination.\n\t     */\n\n\t    BitBlt(memDC, 0, 0, (int) width, (int) height, srcDC, src_x, src_y,\n\t\t    SRCCOPY);\n\t    BitBlt(memDC, 0, 0, (int) width, (int) height, maskDC,\n\t\t    dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,\n\t\t    SRCAND);\n\t    oldBrush = (HBRUSH)SelectObject(destDC, fgBrush);\n\t    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, memDC,\n\t\t    0, 0, MASKPAT);\n\n\t    /*\n\t     * Set background bits. Same as foreground, except we use ((NOT\n\t     * source) AND mask) and the background brush.\n\t     */\n\n\t    BitBlt(memDC, 0, 0, (int) width, (int) height, srcDC, src_x, src_y,\n\t\t    NOTSRCCOPY);\n\t    BitBlt(memDC, 0, 0, (int) width, (int) height, maskDC,\n\t\t    dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,\n\t\t    SRCAND);\n\t    SelectObject(destDC, bgBrush);\n\t    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, memDC,\n\t\t    0, 0, MASKPAT);\n\n\t    TkWinReleaseDrawableDC(clipPtr->value.pixmap, maskDC, &maskState);\n\t    SelectObject(destDC, oldBrush);\n\t    DeleteDC(memDC);\n\t    DeleteObject(bitmap);\n\t    DeleteObject(fgBrush);\n\t    DeleteObject(bgBrush);\n\t}\n    }\n    if (src != dest) {\n\tTkWinReleaseDrawableDC(dest, destDC, &destState);\n    }\n    TkWinReleaseDrawableDC(src, srcDC, &srcState);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkPutImage, XPutImage --\n *\n *\tCopies a subimage from an in-memory image to a rectangle of the\n *\tspecified drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws the image on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkPutImage(\n    unsigned long *colors,\t/* Array of pixel values used by this image.\n\t\t\t\t * May be NULL. */\n    int ncolors,\t\t/* Number of colors used, or 0. */\n    Display *display,\n    Drawable d,\t\t\t/* Destination drawable. */\n    GC gc,\n    XImage *image,\t\t/* Source image. */\n    int src_x, int src_y,\t/* Offset of subimage. */\n    int dest_x, int dest_y,\t/* Position of subimage origin in drawable. */\n    unsigned int width, unsigned int height)\n\t\t\t\t/* Dimensions of subimage. */\n{\n    HDC dc, dcMem;\n    TkWinDCState state;\n    BITMAPINFO *infoPtr;\n    HBITMAP bitmap;\n    char *data;\n\n    LastKnownRequestProcessed(display)++;\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n    dcMem = CreateCompatibleDC(dc);\n\n    if (image->bits_per_pixel == 1) {\n\t/*\n\t * If the image isn't in the right format, we have to copy it into a\n\t * new buffer in MSBFirst and word-aligned format.\n\t */\n\n\tif ((image->bitmap_bit_order != MSBFirst)\n\t\t|| (image->bitmap_pad != sizeof(WORD))) {\n\t    data = TkAlignImageData(image, sizeof(WORD), MSBFirst);\n\t    bitmap = CreateBitmap(image->width, image->height, 1, 1, data);\n\t    Tcl_Free(data);\n\t} else {\n\t    bitmap = CreateBitmap(image->width, image->height, 1, 1,\n\t\t    image->data);\n\t}\n\tSetTextColor(dc, gc->foreground);\n\tSetBkColor(dc, gc->background);\n    } else {\n\tint i, usePalette;\n\n\t/*\n\t * Do not use a palette for TrueColor images.\n\t */\n\n\tusePalette = (image->bits_per_pixel < 16);\n\n\tif (usePalette) {\n\t    infoPtr = (BITMAPINFO *)Tcl_Alloc(sizeof(BITMAPINFOHEADER)\n\t\t    + sizeof(RGBQUAD)*(size_t)ncolors);\n\t} else {\n\t    infoPtr = (BITMAPINFO *)Tcl_Alloc(sizeof(BITMAPINFOHEADER));\n\t}\n\n\tinfoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n\tinfoPtr->bmiHeader.biWidth = image->width;\n\tinfoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */\n\tinfoPtr->bmiHeader.biPlanes = 1;\n\tinfoPtr->bmiHeader.biBitCount = (WORD)image->bits_per_pixel;\n\tinfoPtr->bmiHeader.biCompression = BI_RGB;\n\tinfoPtr->bmiHeader.biSizeImage = 0;\n\tinfoPtr->bmiHeader.biXPelsPerMeter = 0;\n\tinfoPtr->bmiHeader.biYPelsPerMeter = 0;\n\tinfoPtr->bmiHeader.biClrImportant = 0;\n\n\tif (usePalette) {\n\t    infoPtr->bmiHeader.biClrUsed = (DWORD)ncolors;\n\t    for (i = 0; i < ncolors; i++) {\n\t\tinfoPtr->bmiColors[i].rgbBlue = GetBValue(colors[i]);\n\t\tinfoPtr->bmiColors[i].rgbGreen = GetGValue(colors[i]);\n\t\tinfoPtr->bmiColors[i].rgbRed = GetRValue(colors[i]);\n\t\tinfoPtr->bmiColors[i].rgbReserved = 0;\n\t    }\n\t} else {\n\t    infoPtr->bmiHeader.biClrUsed = 0;\n\t}\n\tbitmap = CreateDIBitmap(dc, &infoPtr->bmiHeader, CBM_INIT,\n\t\timage->data, infoPtr, DIB_RGB_COLORS);\n\tTcl_Free(infoPtr);\n    }\n    if (!bitmap) {\n\tDeleteDC(dcMem);\n\tTkWinReleaseDrawableDC(d, dc, &state);\n\treturn BadValue;\n    }\n    bitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n    BitBlt(dc, dest_x, dest_y, (int) width, (int) height, dcMem, src_x, src_y,\n\t    SRCCOPY);\n    DeleteObject(SelectObject(dcMem, bitmap));\n    DeleteDC(dcMem);\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\n#undef XPutImage\nint\nXPutImage(\n    Display *display,\n    Drawable d,\t\t\t/* Destination drawable. */\n    GC gc,\n    XImage *image,\t\t/* Source image. */\n    int src_x, int src_y,\t/* Offset of subimage. */\n    int dest_x, int dest_y,\t/* Position of subimage origin in drawable. */\n    unsigned int width, unsigned int height)\n\t\t\t\t/* Dimensions of subimage. */\n{\n    return TkPutImage(NULL, 0, display, d, gc, image,\n\t\tsrc_x, src_y, dest_x, dest_y, width, height);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillRectangles --\n *\n *\tFill multiple rectangular areas in the given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws onto the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillRectangles(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XRectangle *rectangles,\n    int nrectangles)\n{\n    HDC dc;\n    RECT rect;\n    TkWinDCState state;\n    HBRUSH brush, oldBrush;\n\n    if (d == None) {\n\treturn BadDrawable;\n    }\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n    brush = CreateSolidBrush(gc->foreground);\n\n    if ((gc->fill_style == FillStippled\n\t    || gc->fill_style == FillOpaqueStippled)\n\t    && gc->stipple != None) {\n\tTkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;\n\tHBRUSH stipple;\n\tHBITMAP oldBitmap, bitmap;\n\tHDC dcMem;\n\tHBRUSH bgBrush = CreateSolidBrush(gc->background);\n\n\tif (twdPtr->type != TWD_BITMAP) {\n\t    Tcl_Panic(\"unexpected drawable type in stipple\");\n\t}\n\n\t/*\n\t * Select stipple pattern into destination dc.\n\t */\n\n\tstipple = CreatePatternBrush(twdPtr->bitmap.handle);\n\tSetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);\n\toldBrush = (HBRUSH)SelectObject(dc, stipple);\n\tdcMem = CreateCompatibleDC(dc);\n\n\t/*\n\t * For each rectangle, create a drawing surface which is the size of\n\t * the rectangle and fill it with the background color. Then merge the\n\t * result with the stipple pattern.\n\t */\n\n\twhile (nrectangles-- > 0) {\n\t    bitmap = CreateCompatibleBitmap(dc, rectangles[0].width,\n\t\t    rectangles[0].height);\n\t    oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n\t    rect.left = 0;\n\t    rect.top = 0;\n\t    rect.right = rectangles[0].width;\n\t    rect.bottom = rectangles[0].height;\n\t    FillRect(dcMem, &rect, brush);\n\t    BitBlt(dc, rectangles[0].x, rectangles[0].y, rectangles[0].width,\n\t\t    rectangles[0].height, dcMem, 0, 0, COPYFG);\n\t    if (gc->fill_style == FillOpaqueStippled) {\n\t\tFillRect(dcMem, &rect, bgBrush);\n\t\tBitBlt(dc, rectangles[0].x, rectangles[0].y,\n\t\t\trectangles[0].width, rectangles[0].height, dcMem,\n\t\t\t0, 0, COPYBG);\n\t    }\n\t    SelectObject(dcMem, oldBitmap);\n\t    DeleteObject(bitmap);\n\t    ++rectangles;\n\t}\n\n\tDeleteDC(dcMem);\n\tSelectObject(dc, oldBrush);\n\tDeleteObject(stipple);\n\tDeleteObject(bgBrush);\n    } else {\n\tif (gc->function == GXcopy) {\n\t    while (nrectangles-- > 0) {\n\t\trect.left = rectangles[0].x;\n\t\trect.right = rect.left + rectangles[0].width;\n\t\trect.top = rectangles[0].y;\n\t\trect.bottom = rect.top + rectangles[0].height;\n\t\tFillRect(dc, &rect, brush);\n\t\t++rectangles;\n\t    }\n\t} else {\n\t    HPEN newPen = CreatePen(PS_NULL, 0, gc->foreground);\n\t    HPEN oldPen = (HPEN)SelectObject(dc, newPen);\n\t    oldBrush = (HBRUSH)SelectObject(dc, brush);\n\n\t    while (nrectangles-- > 0) {\n\t\tRectangle(dc, rectangles[0].x, rectangles[0].y,\n\t\t    rectangles[0].x + rectangles[0].width + 1,\n\t\t    rectangles[0].y + rectangles[0].height + 1);\n\t\t++rectangles;\n\t    }\n\n\t    SelectObject(dc, oldBrush);\n\t    SelectObject(dc, oldPen);\n\t    DeleteObject(newPen);\n\t}\n    }\n    DeleteObject(brush);\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MakeAndStrokePath --\n *\n *\tThis function draws a shape using a list of points, a stipple pattern,\n *\tand the specified drawing function. It does it through creation of a\n *\tso-called 'path' (see GDI documentation on MSDN).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\nstatic void\nMakeAndStrokePath(\n    HDC dc,\n    POINT *winPoints,\n    int npoints,\n    WinDrawFunc func)        /* Name of the Windows GDI drawing function:\n\t\t\t\tthis is either Polyline or Polygon. */\n{\n    BeginPath(dc);\n    func(dc, winPoints, (int)npoints);\n    /*\n     * In the case of closed polylines, the first and last points\n     * are the same. We want miter or bevel join be rendered also\n     * at this point, this needs telling the Windows GDI that the\n     * path is closed.\n     */\n    if (func == Polyline) {\n\tif ((winPoints[0].x == winPoints[npoints-1].x) &&\n\t\t(winPoints[0].y == winPoints[npoints-1].y)) {\n\t    CloseFigure(dc);\n\t}\n\tEndPath(dc);\n\tStrokePath(dc);\n    } else {\n\tEndPath(dc);\n\tStrokeAndFillPath(dc);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RenderObject --\n *\n *\tThis function draws a shape using a list of points, a stipple pattern,\n *\tand the specified drawing function.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRenderObject(\n    HDC dc,\n    GC gc,\n    XPoint *points,\n    int npoints,\n    int mode,\n    HPEN pen,\n    WinDrawFunc func)\n{\n    RECT rect = {0,0,0,0};\n    HPEN oldPen;\n    HBRUSH oldBrush;\n    POINT *winPoints = ConvertPoints(points, npoints, mode, &rect);\n\n    if ((gc->fill_style == FillStippled\n\t    || gc->fill_style == FillOpaqueStippled)\n\t    && gc->stipple != None) {\n\n\tTkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;\n\tHDC dcMem;\n\tLONG width, height;\n\tHBITMAP oldBitmap;\n\tint i;\n\tHBRUSH oldMemBrush;\n\n\tif (twdPtr->type != TWD_BITMAP) {\n\t    Tcl_Panic(\"unexpected drawable type in stipple\");\n\t}\n\n\t/*\n\t * Grow the bounding box enough to account for line width.\n\t */\n\n\trect.left -= gc->line_width;\n\trect.top -= gc->line_width;\n\trect.right += gc->line_width;\n\trect.bottom += gc->line_width;\n\n\twidth = rect.right - rect.left;\n\theight = rect.bottom - rect.top;\n\n\t/*\n\t * Select stipple pattern into destination dc.\n\t */\n\n\tSetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);\n\toldBrush = (HBRUSH)SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));\n\n\t/*\n\t * Create temporary drawing surface containing a copy of the\n\t * destination equal in size to the bounding box of the object.\n\t */\n\n\tdcMem = CreateCompatibleDC(dc);\n\toldBitmap = (HBITMAP)SelectObject(dcMem, CreateCompatibleBitmap(dc, width,\n\t\theight));\n\toldPen = (HPEN)SelectObject(dcMem, pen);\n\tBitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);\n\n\t/*\n\t * Translate the object for rendering in the temporary drawing\n\t * surface.\n\t */\n\n\tfor (i = 0; i < npoints; i++) {\n\t    winPoints[i].x -= rect.left;\n\t    winPoints[i].y -= rect.top;\n\t}\n\n\t/*\n\t * Draw the object in the foreground color and copy it to the\n\t * destination wherever the pattern is set.\n\t */\n\n\tSetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE\n\t\t: WINDING);\n\toldMemBrush = (HBRUSH)SelectObject(dcMem, CreateSolidBrush(gc->foreground));\n\tMakeAndStrokePath(dcMem, winPoints, npoints, func);\n\tBitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);\n\n\t/*\n\t * If we are rendering an opaque stipple, then draw the polygon in the\n\t * background color and copy it to the destination wherever the\n\t * pattern is clear.\n\t */\n\n\tif (gc->fill_style == FillOpaqueStippled) {\n\t    DeleteObject(SelectObject(dcMem,\n\t\t    CreateSolidBrush(gc->background)));\n\t    MakeAndStrokePath(dcMem, winPoints, npoints, func);\n\t    BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0,\n\t\t    COPYBG);\n\t}\n\n\tSelectObject(dcMem, oldPen);\n\tDeleteObject(SelectObject(dcMem, oldMemBrush));\n\tDeleteObject(SelectObject(dcMem, oldBitmap));\n\tDeleteDC(dcMem);\n    } else {\n\toldPen = (HPEN)SelectObject(dc, pen);\n\toldBrush = (HBRUSH)SelectObject(dc, CreateSolidBrush(gc->foreground));\n\tSetROP2(dc, tkpWinRopModes[gc->function]);\n\n\tSetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE\n\t\t: WINDING);\n\tMakeAndStrokePath(dc, winPoints, npoints, func);\n\tSelectObject(dc, oldPen);\n    }\n    DeleteObject(SelectObject(dc, oldBrush));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawLines --\n *\n *\tDraw connected lines.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRenders a series of connected lines.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawLines(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XPoint *points,\n    int npoints,\n    int mode)\n{\n    HPEN pen;\n    TkWinDCState state;\n    HDC dc;\n\n    if (d == None) {\n\treturn BadDrawable;\n    }\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n\n    pen = SetUpGraphicsPort(gc);\n    SetBkMode(dc, TRANSPARENT);\n    RenderObject(dc, gc, points, npoints, mode, pen, Polyline);\n    DeleteObject(pen);\n\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillPolygon --\n *\n *\tDraws a filled polygon.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a filled polygon on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillPolygon(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XPoint *points,\n    int npoints,\n    TCL_UNUSED(int),\n    int mode)\n{\n    HPEN pen;\n    TkWinDCState state;\n    HDC dc;\n\n    if (d == None) {\n\treturn BadDrawable;\n    }\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n\n    pen = (HPEN)GetStockObject(NULL_PEN);\n    RenderObject(dc, gc, points, npoints, mode, pen, Polygon);\n\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawRectangle, XDrawRectangles --\n *\n *\tDraws a rectangle.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a rectangle on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawRectangle(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x, int y,\n    unsigned int width, unsigned int height)\n{\n    HPEN pen, oldPen;\n    TkWinDCState state;\n    HBRUSH oldBrush;\n    HDC dc;\n\n    if (d == None) {\n\treturn BadDrawable;\n    }\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n\n    pen = SetUpGraphicsPort(gc);\n    SetBkMode(dc, TRANSPARENT);\n    oldPen = (HPEN)SelectObject(dc, pen);\n    oldBrush = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n\n    Rectangle(dc, x, y, x + (int)width + 1, y + (int)height + 1);\n\n    DeleteObject(SelectObject(dc, oldPen));\n    SelectObject(dc, oldBrush);\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\nint\nXDrawRectangles(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XRectangle rects[],\n    int nrects)\n{\n    int ret = Success;\n\n    while (nrects-- > 0) {\n\tret = XDrawRectangle(display, d, gc, rects[0].x, rects[0].y,\n\t\t    rects[0].width, rects[0].height);\n\tif (ret != Success) {\n\t    break;\n\t}\n\t++rects;\n    }\n    return ret;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawArc, XDrawArcs --\n *\n *\tDraw an arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws an arc on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawArc(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x, int y,\n    unsigned int width, unsigned int height,\n    int start, int extent)\n{\n    LastKnownRequestProcessed(display)++;\n\n    return DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 0);\n}\n\nint\nXDrawArcs(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XArc *arcs,\n    int narcs)\n{\n    int ret = Success;\n\n    LastKnownRequestProcessed(display)++;\n\n    while (narcs-- > 0) {\n\tret = DrawOrFillArc(display, d, gc, arcs[0].x, arcs[0].y,\n\t\t    arcs[0].width, arcs[0].height,\n\t\t    arcs[0].angle1, arcs[0].angle2, 0);\n\tif (ret != Success) {\n\t    break;\n\t}\n\t++arcs;\n    }\n    return ret;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillArc, XFillArcs --\n *\n *\tDraw a filled arc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a filled arc on the specified drawable.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillArc(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x, int y,\n    unsigned int width, unsigned int height,\n    int start, int extent)\n{\n    LastKnownRequestProcessed(display)++;\n\n    return DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 1);\n}\n\nint\nXFillArcs(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XArc *arcs,\n    int narcs)\n{\n    int ret = Success;\n\n    LastKnownRequestProcessed(display)++;\n\n    while (narcs-- > 0) {\n\tret = DrawOrFillArc(display, d, gc, arcs[0].x, arcs[0].y,\n\t\t    arcs[0].width, arcs[0].height,\n\t\t    arcs[0].angle1, arcs[0].angle2, 1);\n\tif (ret != Success) {\n\t    break;\n\t}\n\t++arcs;\n    }\n    return ret;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawOrFillArc --\n *\n *\tThis function handles the rendering of drawn or filled arcs and\n *\tchords.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRenders the requested arc.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDrawOrFillArc(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x, int y,\t\t/* left top */\n    unsigned int width, unsigned int height,\n    int start,\t\t\t/* start: three-o'clock (deg*64) */\n    int extent,\t\t\t/* extent: relative (deg*64) */\n    int fill)\t\t\t/* ==0 draw, !=0 fill */\n{\n    HDC dc;\n    HBRUSH brush, oldBrush;\n    HPEN pen, oldPen;\n    TkWinDCState state;\n    int clockwise = (extent < 0); /* non-zero if clockwise */\n    int xstart, ystart, xend, yend;\n    double radian_start, radian_end, xr, yr;\n\n    if (d == None) {\n\treturn BadDrawable;\n    }\n\n    dc = TkWinGetDrawableDC(display, d, &state);\n\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n\n    /*\n     * Compute the absolute starting and ending angles in normalized radians.\n     * Swap the start and end if drawing clockwise.\n     */\n\n    bool extent_is_360_deg = (extent >= (64*360) || extent <= -(64*360));\n    start = start % (64*360);\n    if (start < 0) {\n\tstart += (64*360);\n    }\n    extent = (start+extent) % (64*360);\n    if (extent < 0) {\n\textent += (64*360);\n    }\n    if (clockwise) {\n\tint tmp = start;\n\tstart = extent;\n\textent = tmp;\n    }\n    radian_start = XAngleToRadians(start);\n    radian_end = XAngleToRadians(extent);\n\n    /*\n     * Now compute points on the radial lines that define the starting and\n     * ending angles. Be sure to take into account that the y-coordinate\n     * system is inverted.\n     */\n\n    xr = x + width / 2.0;\n    yr = y + height / 2.0;\n    xstart = (int)((xr + cos(radian_start)*width/2.0) + 0.5);\n    ystart = (int)((yr + sin(-radian_start)*height/2.0) + 0.5);\n    xend = (int)((xr + cos(radian_end)*width/2.0) + 0.5);\n    yend = (int)((yr + sin(-radian_end)*height/2.0) + 0.5);\n\n    if ((xstart == xend) && (ystart == yend) && !extent_is_360_deg) {\n\t/*\n\t * The extent is so small that the arc size is less than one pixel.\n\t * If the Arc, Chord, or Pie GDI function later received this, then\n\t * a complete ellipse would be drawn instead of the desired 1-pixel\n\t * size arc. The end point must be made different from the start\n\t * point. Since (at this level in the code) arcs are always drawn\n\t * counterclockwise, either xend or yend needs adjustment, depending\n\t * on the sub-range where radian_start lies (it was constrained to\n\t * the [0 ; 2*PI[ range earlier). See bug [6051a9fc]\n\t */\n\tif (radian_start > PI/4) {\n\t    if (radian_start < 3*PI/4) {\n\t\txend--;\n\t    } else if (radian_start < 5*PI/4) {\n\t\tyend++;\n\t    } else if (radian_start < 7*PI/4) {\n\t\txend++;\n\t    } else {\n\t\tyend--;\n\t    }\n\t} else {\n\t    yend--;\n\t}\n    }\n\n    /*\n     * Now draw a filled or open figure. Note that we have to increase the\n     * size of the bounding box by one to account for the difference in pixel\n     * definitions between X and Windows.\n     */\n\n    pen = SetUpGraphicsPort(gc);\n    oldPen = (HPEN)SelectObject(dc, pen);\n    if (!fill) {\n\t/*\n\t * Note that this call will leave a gap of one pixel at the end of the\n\t * arc for thin arcs. We can't use ArcTo because it's only supported\n\t * under Windows NT.\n\t */\n\n\tSetBkMode(dc, TRANSPARENT);\n\tArc(dc, x, y,  x + (int)width + 1, y + (int)height + 1, xstart, ystart,\n\t\txend, yend);\n    } else {\n\tbrush = CreateSolidBrush(gc->foreground);\n\toldBrush = (HBRUSH)SelectObject(dc, brush);\n\tif (gc->arc_mode == ArcChord) {\n\t    Chord(dc, x, y,  x + (int)width + 1, y + (int)height + 1,\n\t\t    xstart, ystart, xend, yend);\n\t} else if (gc->arc_mode == ArcPieSlice) {\n\t    Pie(dc, x, y,  x+(int)width+1, y + (int)height + 1,\n\t\t    xstart, ystart, xend, yend);\n\t}\n\tDeleteObject(SelectObject(dc, oldBrush));\n    }\n    DeleteObject(SelectObject(dc, oldPen));\n    TkWinReleaseDrawableDC(d, dc, &state);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetUpGraphicsPort --\n *\n *\tSet up the graphics port from the given GC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe current port is adjusted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HPEN\nSetUpGraphicsPort(\n    GC gc)\n{\n    DWORD style;\n\n    if (gc->line_style == LineOnOffDash) {\n\tunsigned char *p = (unsigned char *) &(gc->dashes);\n\t\t\t\t/* pointer to the dash-list */\n\n\t/*\n\t * Below is a simple translation of serveral dash patterns to valid\n\t * windows pen types. Far from complete, but I don't know how to do it\n\t * better. Any ideas: <mailto:j.nijtmans@chello.nl>\n\t */\n\n\tif (p[1] && p[2]) {\n\t    if (!p[3] || p[4]) {\n\t\tstyle = PS_DASHDOTDOT;\t\t/*\t-..\t*/\n\t    } else {\n\t\tstyle = PS_DASHDOT;\t\t/*\t-.\t*/\n\t    }\n\t} else {\n\t    if (p[0] > (4 * gc->line_width)) {\n\t\tstyle = PS_DASH;\t\t/*\t-\t*/\n\t    } else {\n\t\tstyle = PS_DOT;\t\t\t/*\t.\t*/\n\t    }\n\t}\n    } else {\n\tstyle = PS_SOLID;\n    }\n    if (gc->line_width < 2) {\n\treturn CreatePen((int) style, gc->line_width, gc->foreground);\n    } else {\n\tLOGBRUSH lb;\n\n\tlb.lbStyle = BS_SOLID;\n\tlb.lbColor = gc->foreground;\n\tlb.lbHatch = 0;\n\n\tstyle |= PS_GEOMETRIC;\n\tswitch (gc->cap_style) {\n\tcase CapNotLast:\n\tcase CapButt:\n\t    style |= PS_ENDCAP_FLAT;\n\t    break;\n\tcase CapRound:\n\t    style |= PS_ENDCAP_ROUND;\n\t    break;\n\tdefault:\n\t    style |= PS_ENDCAP_SQUARE;\n\t    break;\n\t}\n\tswitch (gc->join_style) {\n\tcase JoinMiter:\n\t    style |= PS_JOIN_MITER;\n\t    break;\n\tcase JoinRound:\n\t    style |= PS_JOIN_ROUND;\n\t    break;\n\tdefault:\n\t    style |= PS_JOIN_BEVEL;\n\t    break;\n\t}\n\treturn ExtCreatePen(style, (DWORD) gc->line_width, &lb, 0, NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkScrollWindow --\n *\n *\tScroll a rectangle of the specified window and accumulate a damage\n *\tregion.\n *\n * Results:\n *\tReturns false if the scroll genereated no additional damage. Otherwise,\n *\tsets the region that needs to be repainted after scrolling and returns\n *\ttrue.\n *\n * Side effects:\n *\tScrolls the bits in the window.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkScrollWindow(\n    Tk_Window tkwin,\t\t/* The window to be scrolled. */\n    TCL_UNUSED(GC),\t\t\t/* GC for window to be scrolled. */\n    int x, int y, int width, int height,\n\t\t\t\t/* Position rectangle to be scrolled. */\n    int dx, int dy,\t\t/* Distance rectangle should be moved. */\n    Region damageRgn)\t\t/* Region to accumulate damage in. */\n{\n    HWND hwnd = TkWinGetHWND(Tk_WindowId(tkwin));\n    RECT scrollRect;\n\n    scrollRect.left = x;\n    scrollRect.top = y;\n    scrollRect.right = x + width;\n    scrollRect.bottom = y + height;\n    return (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,\n\t    NULL, 0) != NULLREGION);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinFillRect --\n *\n *\tThis routine fills a rectangle with the foreground color from the\n *\tspecified GC ignoring all other GC values. This is the fastest way to\n *\tfill a drawable with a solid color.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tModifies the contents of the DC drawing surface.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinFillRect(\n    HDC dc,\n    int x, int y, int width, int height,\n    int pixel)\n{\n    RECT rect;\n    COLORREF oldColor;\n\n    rect.left = x;\n    rect.top = y;\n    rect.right = x + width;\n    rect.bottom = y + height;\n    oldColor = SetBkColor(dc, (COLORREF)pixel);\n    SetBkMode(dc, OPAQUE);\n    ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);\n    SetBkColor(dc, oldColor);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DrawHighlightBorder --\n *\n *\tThis function draws a rectangular ring around the outside of a widget\n *\tto indicate that it has received the input focus.\n *\n *      On Windows, we just draw the simple inset ring. On other sytems, e.g.\n *      the Mac, the focus ring is a little more complicated, so we need this\n *      abstraction.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA rectangle \"width\" pixels wide is drawn in \"drawable\", corresponding\n *\tto the outer area of \"tkwin\".\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_DrawHighlightBorder(\n    Tk_Window tkwin,\n    GC fgGC,\n    TCL_UNUSED(GC),\n    int highlightWidth,\n    Drawable drawable)\n{\n    TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinDrawDottedRect --\n *\n *      This function draws a dotted rectangle, used as focus ring of Ttk\n *      widgets and for rendering the active element of a listbox.\n *\n * Results:\n *      None.\n *\n * Side effects:\n *      A dotted rectangle is drawn in the specified Drawable.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinDrawDottedRect(\n    Display *disp,\t\t/* Display containing the dotted rectangle. */\n    Drawable d,\t\t\t/* Where to draw the rectangle (typically a\n\t\t\t\t * pixmap for double buffering). */\n    long pixel,\t\t\t/* Color to use for drawing the rectangle.  If\n\t\t\t\t * pixel < 0 then the black color and the\n\t\t\t\t * foreground mix mode R2_NOT are used. */\n    int x, int y,\t\t/* Coordinates of the top-left corner. */\n    int width, int height)\t/* Width & height, _including the border_. */\n{\n    TkWinDCState state;\n    HDC dc;\n    LOGBRUSH lb;\n    HPEN pen;\n    int widthMod2 = width % 2, heightMod2 = height % 2;\n    int x2 = x + width - 1, y2 = y + height - 1;\n\n    dc = TkWinGetDrawableDC(disp, d, &state);\n\n    lb.lbStyle = BS_SOLID;\n    lb.lbColor = pixel < 0 ? RGB(0, 0, 0) : (COLORREF)pixel;\n    lb.lbHatch = 0;\n\n    if (pixel < 0) {\n\tSetROP2(dc, R2_NOT);\n\tSetBkMode(dc, TRANSPARENT);\n    }\n\n    pen = ExtCreatePen(PS_COSMETIC | PS_ALTERNATE, 1, &lb, 0, NULL);\n    SelectObject(dc, pen);\n    SelectObject(dc, GetStockObject(NULL_BRUSH));\n\n    if (widthMod2 == 0 && heightMod2 == 0) {\n\tMoveToEx(dc, x+1, y,  NULL);\tLineTo(dc, x2,   y);\t/* N */\n\tMoveToEx(dc, x+2, y2, NULL);\tLineTo(dc, x2+1, y2);\t/* S */\n\tMoveToEx(dc, x,  y+2, NULL);\tLineTo(dc, x,  y2+1);\t/* W */\n\tMoveToEx(dc, x2, y+1, NULL);\tLineTo(dc, x2, y2);\t/* E */\n    } else {\n\tint dx = widthMod2, dy = heightMod2;\n\n\tMoveToEx(dc, x+1, y,  NULL);\tLineTo(dc, x2+dx, y);\t/* N */\n\tMoveToEx(dc, x+1, y2, NULL);\tLineTo(dc, x2+dx, y2);\t/* S */\n\tMoveToEx(dc, x,  y+1, NULL);\tLineTo(dc, x,  y2+dy);\t/* W */\n\tMoveToEx(dc, x2, y+1, NULL);\tLineTo(dc, x2, y2+dy);\t/* E */\n    }\n\n    DeleteObject(pen);\n    TkWinReleaseDrawableDC(d, dc, &state);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawFrameEx --\n *\n *\tThis function draws the rectangular frame area.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws inside the tkwin area.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawFrameEx(\n    Tk_Window tkwin,\n    Drawable drawable,\n    Tk_3DBorder border,\n    int highlightWidth,\n    int borderWidth,\n    int relief)\n{\n    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,\n\t    highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth,\n\t    Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinEmbed.c",
    "content": "/*\n * tkWinEmbed.c --\n *\n *\tThis file contains platform specific procedures for Windows platforms\n *\tto provide basic operations needed for application embedding (where\n *\tone application can use as its main window an internal window from\n *\tanother application).\n *\n * Copyright © 1996-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n/*\n * One of the following structures exists for each container in this\n * application. It keeps track of the container window and its associated\n * embedded window.\n */\n\ntypedef struct Container {\n    HWND parentHWnd;\t\t/* Windows HWND to the parent window */\n    TkWindow *parentPtr;\t/* Tk's information about the container or\n\t\t\t\t * NULL if the container isn't in this\n\t\t\t\t * process. */\n    HWND embeddedHWnd;\t\t/* Windows HWND to the embedded window. */\n    TkWindow *embeddedPtr;\t/* Tk's information about the embedded window,\n\t\t\t\t * or NULL if the embedded application isn't\n\t\t\t\t * in this process. */\n    HWND embeddedMenuHWnd;\t/* Tk's embedded menu window handler. */\n    struct Container *nextPtr;\t/* Next in list of all containers in this\n\t\t\t\t * process. */\n} Container;\n\ntypedef struct {\n    Container *firstContainerPtr;\n\t\t\t\t/* First in list of all containers managed by\n\t\t\t\t * this process. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\nstatic void\t\tContainerEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tEmbedGeometryRequest(Container *containerPtr,\n\t\t\t    int width, int height);\nstatic void\t\tEmbedWindowDeleted(TkWindow *winPtr);\nstatic void\t\tTk_MapEmbeddedWindow(TkWindow* winPtr);\nHWND\t\t\tTk_GetEmbeddedHWnd(TkWindow* winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinCleanupContainerList --\n *\n *\tFinalizes the list of containers.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tReleases memory occupied by containers of embedded windows.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinCleanupContainerList(void)\n{\n    Container *nextPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (; tsdPtr->firstContainerPtr != NULL;\n\t    tsdPtr->firstContainerPtr = nextPtr) {\n\tnextPtr = tsdPtr->firstContainerPtr->nextPtr;\n\tTcl_Free(tsdPtr->firstContainerPtr);\n    }\n    tsdPtr->firstContainerPtr = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpTestembedCmd --\n *\n *\tTest command for the embedding facility.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tCurrently it does not do anything.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpTestembedCmd(\n    void *dummy,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    (void)dummy;\n    (void)interp;\n    (void)objc;\n    (void)objv;\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_DetachEmbeddedWindow --\n *\n *\tThis function detaches an embedded window\n *\n * Results:\n *\tNo return value. Detach the embedded window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic\nvoid\nTk_DetachEmbeddedWindow(\n    TkWindow *winPtr,\t\t/* an embedded window */\n    BOOL detachFlag)\t\t/* a flag of truely detaching */\n{\n    TkpWinToplevelDetachWindow(winPtr);\n    if(detachFlag) {\n\tTkpWinToplevelOverrideRedirect(winPtr, 0);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MapEmbeddedWindow --\n *\n *\tThis function is required for mapping an embedded window during idle.\n *\tThe input winPtr must be preserved using Tcl_Preserve before call this\n *\tfunction and will be released by this function.\n *\n * Results:\n *\tNo return value. Map the embedded window if it is not dead.\n *\n * Side effects:\n *\tThe embedded window may change its state as the container's.\n *\n *----------------------------------------------------------------------\n */\n\nstatic\nvoid Tk_MapEmbeddedWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * mapped. */\n{\n    if(!(winPtr->flags & TK_ALREADY_DEAD)) {\n\tHWND hwnd = (HWND)winPtr->privatePtr;\n\tint state = (int)SendMessageW(hwnd, TK_STATE, -1, (WPARAM)-1) - 1;\n\n\tif (state < 0 || state > 3) {\n\t    state = NormalState;\n\t}\n\n\twhile (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {\n\t    /* empty body */\n\t}\n\n\tTkpWmSetState(winPtr, state);\n\tTkWmMapWindow(winPtr);\n    }\n    Tcl_Release(winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UseWindow --\n *\n *\tThis procedure causes a Tk window to use a given Windows handle for a\n *\twindow as its underlying window, rather than a new Windows window\n *\tbeing created automatically. It is invoked by an embedded application\n *\tto specify the window in which the application is embedded.\n *\n *\tThis procedure uses a simple attachment protocol by sending TK_INFO\n *\tmessages to the window to use with two sub messages:\n *\n *\t    TK_CONTAINER_VERIFY - if a window handles this message, it should\n *\t\treturn either a (long)hwnd for a container or a -(long)hwnd\n *\t\tfor a non-container.\n *\n *\t    TK_CONTAINER_ISAVAILABLE - a container window should return either\n *\t\ta TRUE (non-zero) if it is available for use or a FALSE (zero)\n *\t\tothersize.\n *\n *\tThe TK_INFO messages are required in order to verify if the window to\n *\tuse is a valid container. Without an id verification, an invalid\n *\twindow attachment may cause unexpected crashes/panics (bug 1096074).\n *\tAdditional sub messages may be defined/used in future for other\n *\tneeds.\n *\n *\tWe do not enforce the above protocol for the reason of backward\n *\tcompatibility. If the window to use is unable to handle TK_INFO\n *\tmessages (e.g., legacy Tk container applications before 8.5), a dialog\n *\tbox with a warning message pops up and the user is asked to confirm if\n *\tthe attachment should proceed. However, we may have to enforce it in\n *\tfuture.\n *\n * Results:\n *\tThe return value is normally TCL_OK. If an error occurred (such as if\n *\tthe argument does not identify a legal Windows window handle or it is\n *\talready in use or a cancel button is pressed by a user in confirming\n *\tthe use window as a Tk container) the return value is TCL_ERROR and an\n *\terror message is left in the the interp's result if interp is not\n *\tNULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_UseWindow(\n    Tcl_Interp *interp,\t\t/* If not NULL, used for error reporting if\n\t\t\t\t * string is bogus. */\n    Tk_Window tkwin,\t\t/* Tk window that does not yet have an\n\t\t\t\t * associated X window. */\n    const char *string)\t\t/* String identifying an X window to use for\n\t\t\t\t * tkwin; must be an integer value. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    Tcl_Size id;\n    HWND hwnd;\n/*\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n*/\n\n/*\n    if (winPtr->window != None) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"can't modify container after widget is created\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"POST_CREATE\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n*/\n\n    if (strcmp(string, \"\") == 0) {\n\tif (winPtr->flags & TK_EMBEDDED) {\n\t    Tk_DetachEmbeddedWindow(winPtr, TRUE);\n\t}\n\treturn TCL_OK;\n    }\n\n    if (\n#ifdef _WIN64\n\t    (sscanf(string, \"0x%p\", &hwnd) != 1) &&\n#endif\n\t    Tcl_GetInt(interp, string, (int *) &hwnd) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if ((HWND)winPtr->privatePtr == hwnd) {\n\treturn TCL_OK;\n    }\n\n    /*\n     * Check if the window is a valid handle. If it is invalid, return\n     * TCL_ERROR and potentially leave an error message in the interp's\n     * result.\n     */\n\n    if (!IsWindow(hwnd)) {\n\tif (interp != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" does not exist\", string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"EXIST\", (char *)NULL);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    id = SendMessageW(hwnd, TK_INFO, TK_CONTAINER_VERIFY, 0);\n    if (id == PTR2INT(hwnd)) {\n\tif (!SendMessageW(hwnd, TK_INFO, TK_CONTAINER_ISAVAILABLE, 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"The container is already in use\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"IN_USE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    } else if (id == -PTR2INT(hwnd)) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\"the window to use is not a Tk container\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"CONTAINER\", (char *)NULL);\n\treturn TCL_ERROR;\n    } else {\n\t/*\n\t * Proceed if the user decide to do so because it can be a legacy\n\t * container application. However we may have to return a TCL_ERROR in\n\t * order to avoid bug 1096074 in future.\n\t */\n\n\tWCHAR msg[256];\n\n\twsprintfW(msg, L\"Unable to get information of window \\\"%.40hs\\\".  Attach to this\\nwindow may have unpredictable results if it is not a valid container.\\n\\nPress Ok to proceed or Cancel to abort attaching.\", string);\n\tif (IDCANCEL == MessageBoxW(hwnd, msg, L\"Tk Warning\",\n\t\tMB_OKCANCEL | MB_ICONWARNING)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Operation has been canceled\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"EMBED\", \"CANCEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    Tk_DetachEmbeddedWindow(winPtr, FALSE);\n\n    /*\n     * Store the parent window in the platform private data slot so\n     * TkWmMapWindow can use it when creating the wrapper window.\n     */\n\n    winPtr->privatePtr = (struct TkWindowPrivate*) hwnd;\n    winPtr->flags |= TK_EMBEDDED;\n    winPtr->flags &= ~(TK_MAPPED);\n\n    /*\n     * Preserve the winPtr and create an idle handler to map the embedded\n     * window.\n     */\n\n    Tcl_Preserve(winPtr);\n    Tcl_DoWhenIdle((Tcl_IdleProc*) Tk_MapEmbeddedWindow, winPtr);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeContainer --\n *\n *\tThis procedure is called to indicate that a particular window will be\n *\ta container for an embedded application. This changes certain aspects\n *\tof the window's behavior, such as whether it will receive events\n *\tanymore.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MakeContainer(\n    Tk_Window tkwin)\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Register the window as a container so that, for example, we can find\n     * out later if the embedded app. is in the same process.\n     */\n\n    Tk_MakeWindowExist(tkwin);\n    containerPtr = (Container *)Tcl_Alloc(sizeof(Container));\n    containerPtr->parentPtr = winPtr;\n    containerPtr->parentHWnd = Tk_GetHWND(Tk_WindowId(tkwin));\n    containerPtr->embeddedHWnd = NULL;\n    containerPtr->embeddedPtr = NULL;\n    containerPtr->embeddedMenuHWnd = NULL;\n    containerPtr->nextPtr = tsdPtr->firstContainerPtr;\n    tsdPtr->firstContainerPtr = containerPtr;\n    winPtr->flags |= TK_CONTAINER;\n\n    /*\n     * Unlike in tkUnixEmbed.c, we don't make any requests for events in the\n     * embedded window here. Now we just allow the embedding of another TK\n     * application into TK windows. When the embedded window makes a request,\n     * that will be done by sending to the container window a WM_USER message,\n     * which will be intercepted by TkWinContainerProc.\n     *\n     * We need to get structure events of the container itself, though.\n     */\n\n    Tk_CreateEventHandler(tkwin, StructureNotifyMask,\n\t    ContainerEventProc, containerPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinEmbeddedEventProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when various\n *\tuseful events are received for the *children* of a container window.\n *\tIt forwards relevant information, such as geometry requests, from the\n *\tevents into the container's application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the event. For example, when ConfigureRequest events occur,\n *\tgeometry information gets set for the container window.\n *\n *----------------------------------------------------------------------\n */\n\nLRESULT\nTkWinEmbeddedEventProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    Tcl_Size result = 1;\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Find the Container structure associated with the parent window.\n     */\n\n    for (containerPtr = tsdPtr->firstContainerPtr;\n\t    containerPtr && containerPtr->parentHWnd != hwnd;\n\t    containerPtr = containerPtr->nextPtr) {\n\t/* empty loop body */\n    }\n\n    if (containerPtr) {\n\tTkWindow *topwinPtr = NULL;\n\tif(Tk_IsTopLevel(containerPtr->parentPtr)) {\n\t    topwinPtr = containerPtr->parentPtr;\n\t}\n\tswitch (message) {\n\tcase TK_INFO:\n\t    /*\n\t     * An embedded window may send this message for container\n\t     * verification and availability before attach.\n\t     *\n\t     * wParam - a sub message\n\t     *\n\t     *\t    TK_CONTAINER_ISAVAILABLE - if the container is available\n\t     *\t\tfor use?\n\t     *\t\tresult = 1 for yes and 0 for no;\n\t     *\n\t     *\t    TK_CONTAINER_VERIFY - request the container to verify its\n\t     *\t\tidentification\n\t     *\t\tresult =  (Tcl_Size)hwnd if this window is a container\n\t     *\t\t\t -(Tcl_Size)hwnd otherwise\n\t     *\n\t     * lParam - N/A\n\t     */\n\n\t    switch(wParam) {\n\t    case TK_CONTAINER_ISAVAILABLE:\n\t\tresult = containerPtr->embeddedHWnd == NULL? 1:0;\n\t\tbreak;\n\t    case TK_CONTAINER_VERIFY:\n\t\tresult = PTR2INT(containerPtr->parentHWnd);\n\t\tbreak;\n\t    default:\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_ATTACHWINDOW:\n\t    /*\n\t     * An embedded window (either from this application or from\n\t     * another application) is trying to attach to this container. We\n\t     * attach it only if this container is not yet containing any\n\t     * window.\n\t     *\n\t     * wParam - a handle of an embedded window\n\t     * lParam - N/A\n\t     *\n\t     * An embedded window may send this message with a wParam of NULL\n\t     * to test if a window is able to provide embedding service. The\n\t     * container returns its window handle for accepting the\n\t     * attachment and identifying itself or a zero for being already\n\t     * in use.\n\t     *\n\t     * Return value:\n\t     * 0    - the container is unable to be used.\n\t     * hwnd - the container is ready to be used.\n\t     */\n\t    if (containerPtr->embeddedHWnd == NULL) {\n\t\tif (wParam) {\n\t\t    TkWindow *winPtr = (TkWindow *)\n\t\t\t    Tk_HWNDToWindow((HWND) wParam);\n\t\t    if (winPtr) {\n\t\t\twinPtr->flags |= TK_BOTH_HALVES;\n\t\t\tcontainerPtr->embeddedPtr = winPtr;\n\t\t\tcontainerPtr->parentPtr->flags |= TK_BOTH_HALVES;\n\t\t    }\n\t\t    containerPtr->embeddedHWnd = (HWND)wParam;\n\t\t}\n\t\tresult = PTR2INT(containerPtr->parentHWnd);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_DETACHWINDOW:\n\t    /*\n\t     * An embedded window notifies the container that it is detached.\n\t     * The container should clearn the related variables and redraw\n\t     * its window.\n\t     *\n\t     * wParam - N/A\n\t     * lParam - N/A\n\t     *\n\t     * Return value:\n\t     * 0\t- the message is not processed.\n\t     * others\t- the message is processed.\n\t     */\n\n\t    containerPtr->embeddedMenuHWnd = NULL;\n\t    containerPtr->embeddedHWnd = NULL;\n\t    containerPtr->parentPtr->flags &= ~TK_BOTH_HALVES;\n\t    if (topwinPtr) {\n\t\tTkWinSetMenu((Tk_Window) topwinPtr, 0);\n\t    }\n\t    InvalidateRect(hwnd, NULL, TRUE);\n\t    break;\n\n\tcase TK_GEOMETRYREQ:\n\t    /*\n\t     * An embedded window requests a window size change.\n\t     *\n\t     * wParam - window width\n\t     * lParam - window height\n\t     *\n\t     * Return value:\n\t     * 0\t- the message is not processed.\n\t     * others\t- the message is processed.\n\t     */\n\n\t    EmbedGeometryRequest(containerPtr, (int)wParam, (int)lParam);\n\t    break;\n\n\tcase TK_RAISEWINDOW:\n\t    /*\n\t     * An embedded window requests to change its Z-order.\n\t     *\n\t     * wParam - a window handle as a z-order stack reference\n\t     * lParam - a flag of above-below: 0 - above; 1 or others: - below\n\t     *\n\t     * Return value:\n\t     * 0\t- the message is not processed.\n\t     * others\t- the message is processed.\n\t     */\n\n\t    TkWinSetWindowPos(GetParent(containerPtr->parentHWnd),\n\t\t    (HWND)wParam, (int)lParam);\n\t    break;\n\n\tcase TK_GETFRAMEWID:\n\t    /*\n\t     * An embedded window requests to get the frame window's id.\n\t     *\n\t     * wParam - N/A\n\t     * lParam - N/A\n\t     *\n\t     * Return vlaue:\n\t     *\n\t     * A handle of the frame window. If it is not availble, a zero is\n\t     * returned.\n\t     */\n\t    if (topwinPtr) {\n\t\tresult = PTR2INT(GetParent(containerPtr->parentHWnd));\n\t    } else {\n\t\ttopwinPtr = containerPtr->parentPtr;\n\t\twhile (!(topwinPtr->flags & TK_TOP_HIERARCHY)) {\n\t\t    topwinPtr = topwinPtr->parentPtr;\n\t\t}\n\t\tif (topwinPtr && topwinPtr->window) {\n\t\t    result = PTR2INT(GetParent(Tk_GetHWND(topwinPtr->window)));\n\t\t} else {\n\t\t    result = 0;\n\t\t}\n\t    }\n\t    break;\n\n\tcase TK_CLAIMFOCUS:\n\t    /*\n\t     * An embedded window requests a focus.\n\t     *\n\t     * wParam - a flag of forcing focus\n\t     * lParam - N/A\n\t     *\n\t     * Return value:\n\t     * 0    - the message is not processed\n\t     * 1    - the message is processed\n\t     */\n\n\t    if (!SetFocus(containerPtr->embeddedHWnd) && wParam) {\n\t\t/*\n\t\t * forcing focus TBD\n\t\t */\n\t    }\n\t    break;\n\n\tcase TK_WITHDRAW:\n\t    /*\n\t     * An embedded window requests withdraw.\n\t     *\n\t     * wParam\t- N/A\n\t     * lParam\t- N/A\n\t     *\n\t     * Return value\n\t     * 0    - the message is not processed\n\t     * 1    - the message is processed\n\t     */\n\n\t    if (topwinPtr) {\n\t\tTkpWinToplevelWithDraw(topwinPtr);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_ICONIFY:\n\t    /*\n\t     * An embedded window requests iconification.\n\t     *\n\t     * wParam\t- N/A\n\t     * lParam\t- N/A\n\t     *\n\t     * Return value\n\t     * 0    - the message is not processed\n\t     * 1    - the message is processed\n\t     */\n\n\t    if (topwinPtr) {\n\t\tTkpWinToplevelIconify(topwinPtr);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_DEICONIFY:\n\t    /*\n\t     * An embedded window requests deiconification.\n\t     *\n\t     * wParam\t- N/A\n\t     * lParam\t- N/A\n\t     *\n\t     * Return value\n\t     * 0    - the message is not processed\n\t     * 1    - the message is processed\n\t     */\n\t    if (topwinPtr) {\n\t\tTkpWinToplevelDeiconify(topwinPtr);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_MOVEWINDOW:\n\t    /*\n\t     * An embedded window requests to move position if both wParam and\n\t     * lParam are greater or equal to 0.\n\t     *\t    wParam - x value of the frame's upper left\n\t     *\t    lParam - y value of the frame's upper left\n\t     *\n\t     * Otherwise an embedded window requests the current position\n\t     *\n\t     * Return value: an encoded window position in a 32bit long, i.e,\n\t     * ((x << 16) & 0xffff0000) | (y & 0xffff)\n\t     *\n\t     * Only a toplevel container may move the embedded.\n\t     */\n\n\t    result = TkpWinToplevelMove(containerPtr->parentPtr,\n\t\t    (int)wParam, (int)lParam);\n\t    break;\n\n\tcase TK_OVERRIDEREDIRECT:\n\t    /*\n\t     * An embedded window request overrideredirect.\n\t     *\n\t     * wParam\n\t     *\t0\t- add a frame if there is no one\n\t     *  1\t- remove the frame if there is a one\n\t     *  < 0\t- query the current overrideredirect value\n\t     *\n\t     * lParam\t- N/A\n\t     *\n\t     * Return value:\n\t     * 1 + the current value of overrideredirect if the container is a\n\t     * toplevel. Otherwise 0.\n\t     */\n\t    if (topwinPtr) {\n\t\tresult = 1 + TkpWinToplevelOverrideRedirect(topwinPtr, (int)wParam);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_SETMENU:\n\t    /*\n\t     * An embedded requests to set a menu.\n\t     *\n\t     * wParam\t- a menu handle\n\t     * lParam\t- a menu window handle\n\t     *\n\t     * Return value:\n\t     * 1    - the message is processed\n\t     * 0    - the message is not processed\n\t     */\n\t    if (topwinPtr) {\n\t\tcontainerPtr->embeddedMenuHWnd = (HWND)lParam;\n\t\tTkWinSetMenu((Tk_Window)topwinPtr, (HMENU)wParam);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\tcase TK_STATE:\n\t    /*\n\t     * An embedded window request set/get state services.\n\t     *\n\t     * wParam\t- service directive\n\t     *\t    0 - 3 for setting state\n\t     *\t\t0 - withdrawn state\n\t     *\t\t1 - normal state\n\t     *\t\t2 - zoom state\n\t     *\t\t3 - icon state\n\t     * others for gettting state\n\t     *\n\t     * lParam\t- N/A\n\t     *\n\t     * Return value\n\t     * 1 + the current state or 0 if the container is not a toplevel\n\t     */\n\n\t    if (topwinPtr) {\n\t\tif (wParam <= 3) {\n\t\t    TkpWmSetState(topwinPtr, (int)wParam);\n\t\t}\n\t\tresult = 1+TkpWmGetState(topwinPtr);\n\t    } else {\n\t\tresult = 0;\n\t    }\n\t    break;\n\n\t    /*\n\t     * Return 0 since the current Tk container implementation is\n\t     * unable to provide following services.\n\t     */\n\tdefault:\n\t    result = 0;\n\t    break;\n\t}\n    } else {\n\tif ((message == TK_INFO) && (wParam == TK_CONTAINER_VERIFY)) {\n\t    /*\n\t     * Reply the message sender: this is not a Tk container\n\t     */\n\n\t    return -PTR2INT(hwnd);\n\t} else {\n\t    result = 0;\n\t}\n    }\n\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedGeometryRequest --\n *\n *\tThis procedure is invoked when an embedded application requests a\n *\tparticular size. It processes the request (which may or may not\n *\tactually resize the window) and reflects the results back to the\n *\tembedded application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf we deny the child's size change request, a Configure event is\n *\tsynthesized to let the child know that the size is the same as it used\n *\tto be. Events get processed while we're waiting for the geometry\n *\tmanagers to do their thing.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nEmbedGeometryRequest(\n    Container *containerPtr,\t/* Information about the container window. */\n    int width, int height)\t/* Size that the child has requested. */\n{\n    TkWindow *winPtr = containerPtr->parentPtr;\n\n    /*\n     * Forward the requested size into our geometry management hierarchy via\n     * the container window. We need to send a Configure event back to the\n     * embedded application even if we decide not to resize the window; to\n     * make this happen, process all idle event handlers synchronously here\n     * (so that the geometry managers have had a chance to do whatever they\n     * want to do), and if the window's size didn't change then generate a\n     * configure event.\n     */\n\n    Tk_GeometryRequest((Tk_Window)winPtr, width, height);\n\n    if (containerPtr->embeddedHWnd != NULL) {\n\twhile (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {\n\t    /* Empty loop body. */\n\t}\n\n\tSetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,\n\t\twinPtr->changes.width, winPtr->changes.height, SWP_NOZORDER);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ContainerEventProc --\n *\n *\tThis procedure is invoked by the Tk event dispatcher when various\n *\tuseful events are received for the container window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on the event. For example, when ConfigureRequest events occur,\n *\tgeometry information gets set for the container window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nContainerEventProc(\n    void *clientData,\t/* Token for container window. */\n    XEvent *eventPtr)\t\t/* ResizeRequest event. */\n{\n    Container *containerPtr = (Container *)clientData;\n    Tk_Window tkwin = (Tk_Window)containerPtr->parentPtr;\n\n    if (eventPtr->type == ConfigureNotify) {\n\n\t/*\n\t * Send a ConfigureNotify  to the embedded application.\n\t */\n\n\tif (containerPtr->embeddedPtr != NULL) {\n\t    TkDoConfigureNotify(containerPtr->embeddedPtr);\n\t}\n\n\t/*\n\t * Resize the embedded window, if there is any.\n\t */\n\n\tif (containerPtr->embeddedHWnd) {\n\t    SetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,\n\t\t    Tk_Width(tkwin), Tk_Height(tkwin), SWP_NOZORDER);\n\t}\n    } else if (eventPtr->type == DestroyNotify) {\n\t/*\n\t * The container is gone, remove it from the list.\n\t */\n\n\tEmbedWindowDeleted(containerPtr->parentPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetOtherWindow --\n *\n *\tIf both the container and embedded window are in the same process,\n *\tthis procedure will return either one, given the other.\n *\n * Results:\n *\tIf tkwin is a container, the return value is the token for the\n *\tembedded window, and vice versa. If the \"other\" window isn't in this\n *\tprocess, NULL is returned.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_GetOtherWindow(\n    Tk_Window tkwin)\t\t/* Tk's structure for a container or embedded\n\t\t\t\t * window. */\n{\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif ((Tk_Window)containerPtr->embeddedPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->parentPtr;\n\t} else if ((Tk_Window)containerPtr->parentPtr == tkwin) {\n\t    return (Tk_Window)containerPtr->embeddedPtr;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetEmbeddedHWnd --\n *\n *\tThis function returns the embedded window id.\n *\n * Results:\n *\tIf winPtr is a container, the return value is the HWND for the\n *\tembedded window. Otherwise it returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHWND\nTk_GetEmbeddedHWnd(\n    TkWindow *winPtr)\n{\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->parentPtr == winPtr) {\n\t    return containerPtr->embeddedHWnd;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetEmbeddedMenuHWND --\n *\n *\tThis function returns the embedded menu window id.\n *\n * Results:\n *\tIf winPtr is a container, the return value is the HWND for the\n *\tembedded menu window. Otherwise it returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHWND\nTkGetEmbeddedMenuHWND(\n    Tk_Window tkwin)\n{\n    TkWindow *winPtr = (TkWindow*)tkwin;\n    Container *containerPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;\n\t    containerPtr = containerPtr->nextPtr) {\n\tif (containerPtr->parentPtr == winPtr) {\n\t    return containerPtr->embeddedMenuHWnd;\n\t}\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpClaimFocus --\n *\n *\tThis procedure is invoked when someone asks or the input focus to be\n *\tput on a window in an embedded application, but the application\n *\tdoesn't currently have the focus. It requests the input focus from the\n *\tcontainer application.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe input focus may change.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpClaimFocus(\n    TkWindow *topLevelPtr,\t/* Top-level window containing desired focus\n\t\t\t\t * window; should be embedded. */\n    int force)\t\t\t/* One means that the container should claim\n\t\t\t\t * the focus if it doesn't currently have\n\t\t\t\t * it. */\n{\n    HWND hwnd = GetParent(Tk_GetHWND(topLevelPtr->window));\n    SendMessageW(hwnd, TK_CLAIMFOCUS, (WPARAM) force, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpRedirectKeyEvent --\n *\n *\tThis procedure is invoked when a key press or release event arrives\n *\tfor an application that does not believe it owns the input focus.\n *\tThis can happen because of embedding; for example, X can send an event\n *\tto an embedded application when the real focus window is in the\n *\tcontainer application and is an ancestor of the container. This\n *\tprocedure's job is to forward the event back to the application where\n *\tit really belongs.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe event may get sent to a different application.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpRedirectKeyEvent(\n    TkWindow *winPtr,\t\t/* Window to which the event was originally\n\t\t\t\t * reported. */\n    XEvent *eventPtr)\t\t/* X event to redirect (should be KeyPress or\n\t\t\t\t * KeyRelease). */\n{\n    (void)winPtr;\n    (void)eventPtr;\n    /* not implemented */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * EmbedWindowDeleted --\n *\n *\tThis procedure is invoked when a window involved in embedding (as\n *\teither the container or the embedded application) is destroyed. It\n *\tcleans up the Container structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA Container structure may be freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nEmbedWindowDeleted(\n    TkWindow *winPtr)\t\t/* Tk's information about window that was\n\t\t\t\t * deleted. */\n{\n    Container *containerPtr, *prevPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Find the Container structure for this window work. Delete the\n     * information about the embedded application and free the container's\n     * record. The main container may be null. [Bug #476176]\n     */\n\n    prevPtr = NULL;\n    containerPtr = tsdPtr->firstContainerPtr;\n    while (1) {\n\tif (containerPtr == NULL) return;\n\tif (containerPtr->embeddedPtr == winPtr) {\n\t    containerPtr->embeddedHWnd = NULL;\n\t    containerPtr->embeddedPtr = NULL;\n\t    break;\n\t}\n\tif (containerPtr->parentPtr == winPtr) {\n\t    SendMessageW(containerPtr->embeddedHWnd, WM_CLOSE, 0, 0);\n\t    containerPtr->parentPtr = NULL;\n\t    containerPtr->embeddedPtr = NULL;\n\t    break;\n\t}\n\tprevPtr = containerPtr;\n\tcontainerPtr = containerPtr->nextPtr;\n\tif (containerPtr == NULL) {\n\t    return;\n\t}\n    }\n    if ((containerPtr->embeddedPtr == NULL)\n\t    && (containerPtr->parentPtr == NULL)) {\n\tif (prevPtr == NULL) {\n\t    tsdPtr->firstContainerPtr = containerPtr->nextPtr;\n\t} else {\n\t    prevPtr->nextPtr = containerPtr->nextPtr;\n\t}\n\tTcl_Free(containerPtr);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinFont.c",
    "content": "/*\n * tkWinFont.c --\n *\n *\tContains the Windows implementation of the platform-independent font\n *\tpackage interface with support for shaping and RTL support with complex\n *  script languages like Arabic.\n *\n * Copyright © 1994 Software Research Associates, Inc.\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n * Copyright © 2026 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkFont.h\"\n#include <usp10.h>      /* Uniscribe */\n\n/*\n * The following structure represents a font family. It is assumed that all\n * screen fonts constructed from the same \"font family\" share certain\n * properties; all screen fonts with the same \"font family\" point to a shared\n * instance of this structure. The most important shared property is the\n * character existence metrics, used to determine if a screen font can display\n * a given Unicode character.\n *\n * Under Windows, a \"font family\" is uniquely identified by its face name.\n */\n\n#define FONTMAP_SHIFT\t    10\n\n#define FONTMAP_BITSPERPAGE\t(1 << FONTMAP_SHIFT)\n/* Cover the full Unicode range (0x110000) */\n#define FONTMAP_NUMCHARS\t0x110000\n#define FONTMAP_PAGES\t\t(FONTMAP_NUMCHARS / FONTMAP_BITSPERPAGE)\n\ntypedef struct FontFamily {\n    struct FontFamily *nextPtr;\t/* Next in list of all known font families. */\n    size_t refCount;\t\t/* How many SubFonts are referring to this\n\t\t\t\t * FontFamily. When the refCount drops to\n\t\t\t\t * zero, this FontFamily may be freed. */\n    /*\n     * Key.\n     */\n\n    Tk_Uid faceName;\t\t/* Face name key for this FontFamily. */\n\n    /*\n     * Derived properties.\n     */\n\n    Tcl_Encoding encoding;\t/* Encoding for this font family. */\n    int isSymbolFont;\t\t/* Non-zero if this is a symbol font. */\n    int isWideFont;\t\t/* 1 if this is a double-byte font, 0\n\t\t\t\t * otherwise. */\n    BOOL (WINAPI *textOutProc)(HDC hdc, int x, int y, WCHAR *str, int len);\n\t\t\t\t/* The procedure to use to draw text after it\n\t\t\t\t * has been converted from UTF-8 to the\n\t\t\t\t * encoding of this font. */\n    BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, WCHAR *, int, LPSIZE);\n\t\t\t\t/* The procedure to use to measure text after\n\t\t\t\t * it has been converted from UTF-8 to the\n\t\t\t\t * encoding of this font. */\n\n    char *fontMap[FONTMAP_PAGES];\n\t\t\t\t/* Two-level sparse table used to determine\n\t\t\t\t * quickly if the specified character exists.\n\t\t\t\t * As characters are encountered, more pages\n\t\t\t\t * in this table are dynamically added. The\n\t\t\t\t * contents of each page is a bitmask\n\t\t\t\t * consisting of FONTMAP_BITSPERPAGE bits,\n\t\t\t\t * representing whether this font can be used\n\t\t\t\t * to display the given character at the\n\t\t\t\t * corresponding bit position. The high bits\n\t\t\t\t * of the character are used to pick which\n\t\t\t\t * page of the table is used. */\n\n    /*\n     * Cached Truetype font info.\n     */\n\n    int segCount;\t\t/* The length of the following arrays. */\n    USHORT *startCount;\t\t/* Truetype information about the font, */\n    USHORT *endCount;\t\t/* indicating which characters this font can\n\t\t\t\t * display (malloced). The format of this\n\t\t\t\t * information is (relatively) compact, but\n\t\t\t\t * would take longer to search than indexing\n\t\t\t\t * into the fontMap[][] table. */\n} FontFamily;\n\n/*\n * The following structure encapsulates an individual screen font. A font\n * object is made up of however many SubFonts are necessary to display a\n * stream of multilingual characters.\n */\n\ntypedef struct SubFont {\n    char **fontMap;\t\t/* Pointer to font map from the FontFamily,\n\t\t\t\t * cached here to save a dereference. */\n    HFONT hFont0;\t\t/* The specific screen font that will be used\n\t\t\t\t * when displaying/measuring chars belonging\n\t\t\t\t * to the FontFamily. */\n    FontFamily *familyPtr;\t/* The FontFamily for this SubFont. */\n    HFONT hFontAngled;\n    double angle;\n} SubFont;\n\n/*\n * The following structure represents Windows' implementation of a font\n * object.\n */\n\n#define SUBFONT_SPACE\t\t3\n#define BASE_CHARS\t\t128\n\ntypedef struct WinFont {\n    TkFont font;\t\t/* Stuff used by generic font package. Must be\n\t\t\t\t * first in structure. */\n    SubFont staticSubFonts[SUBFONT_SPACE];\n\t\t\t\t/* Builtin space for a limited number of\n\t\t\t\t * SubFonts. */\n    int numSubFonts;\t\t/* Length of following array. */\n    SubFont *subFontArray;\t/* Array of SubFonts that have been loaded in\n\t\t\t\t * order to draw/measure all the characters\n\t\t\t\t * encountered by this font so far. All fonts\n\t\t\t\t * start off with one SubFont initialized by\n\t\t\t\t * InitFont() from the original set of font\n\t\t\t\t * attributes. Usually points to\n\t\t\t\t * staticSubFonts, but may point to malloced\n\t\t\t\t * space if there are lots of SubFonts. */\n    SCRIPT_CACHE staticScriptCaches[SUBFONT_SPACE];\n\t\t\t\t/* Inline SCRIPT_CACHE storage parallel to\n\t\t\t\t * staticSubFonts.  Each slot corresponds to\n\t\t\t\t * the SubFont at the same index and is passed\n\t\t\t\t * to ScriptShape/ScriptPlace so that Uniscribe\n\t\t\t\t * can amortise per-font analysis work across\n\t\t\t\t * calls.  Must be zero-initialised; freed with\n\t\t\t\t * ScriptFreeCache() in ReleaseFont(). */\n    SCRIPT_CACHE *scriptCacheArray;\n\t\t\t\t/* Points to staticScriptCaches normally, or\n\t\t\t\t * to a malloced array when subFontArray\n\t\t\t\t * overflows SUBFONT_SPACE.  Always kept in\n\t\t\t\t * sync with subFontArray. */\n    HWND hwnd;\t\t\t/* Toplevel window of application that owns\n\t\t\t\t * this font, used for getting HDC for\n\t\t\t\t * offscreen measurements. */\n    int pixelSize;\t\t/* Original pixel size used when font was\n\t\t\t\t * constructed. */\n    int widths[BASE_CHARS];\t/* Widths of first 128 chars in the base font,\n\t\t\t\t * for handling common case. The base font is\n\t\t\t\t * always used to draw characters between\n\t\t\t\t * 0x0000 and 0x007f. */\n} WinFont;\n\n/*\n * The following structure is passed as the LPARAM when calling the font\n * enumeration procedure to determine if a font can support the given\n * character.\n */\n\ntypedef struct CanUse {\n    HDC hdc;\n    WinFont *fontPtr;\n    Tcl_DString *nameTriedPtr;\n    int ch;\n    SubFont *subFontPtr;\n    SubFont **subFontPtrPtr;\n} CanUse;\n\n/*\n * The following structure represents a single fully-shaped, bidi-reordered\n * run ready for drawing or advance-width summation.  The shaping layer\n * produces an array of these; the drawing layer consumes them without any\n * further Unicode processing.\n *\n * Ownership: glyphs, advances, and offsets are allocated by\n * TkWinShapeString() and freed by TkWinFreeShapedRuns().\n *\n * The scriptCache field points into the owning WinFont's scriptCacheArray at\n * the slot that was used for ScriptShape and ScriptPlace.  ScriptTextOut\n * MUST receive the same cache pointer; passing NULL causes Uniscribe to\n * discard all shaping work and produce no visible output.  Do not free this\n * pointer here — it is owned by the WinFont.\n */\ntypedef struct TkWinShapedRun {\n    HFONT        hFont;         /* Font selected when ScriptTextOut is called.\n\t\t\t\t * Owned by the WinFont subfont; do not delete\n\t\t\t\t * here. */\n    SubFont     *subFontPtr;    /* The SubFont that owns hFont.  Used by the\n\t\t\t\t * draw layer to retrieve the face name for\n\t\t\t\t * constructing rotated variants of this run's\n\t\t\t\t * font.  Points into fontPtr->subFontArray;\n\t\t\t\t * do not free. */\n    SCRIPT_CACHE *scriptCache;  /* Points to fontPtr->scriptCacheArray[i] for\n\t\t\t\t * the subfont that shaped this run.  Must be\n\t\t\t\t * the same slot passed to ScriptShape and\n\t\t\t\t * ScriptPlace, and must be passed to\n\t\t\t\t * ScriptTextOut.  Never NULL after a\n\t\t\t\t * successful shape+place. Do not free here. */\n    SCRIPT_ANALYSIS sa;         /* Uniscribe analysis for this run (carries\n\t\t\t\t * bidi level, script tag, etc.). */\n    int          glyphCount;    /* Number of entries in glyphs[]. */\n    WORD        *glyphs;        /* Glyph index array (malloced). */\n    int         *advances;      /* Glyph advance widths in pixels (malloced).*/\n    GOFFSET     *offsets;       /* Per-glyph x/y offsets (malloced). */\n    ABC          abc;           /* Total run A+B+C metrics from ScriptPlace. */\n} TkWinShapedRun;\n\n/*\n * The following structure is used to map between the Tcl strings that\n * represent the system fonts and the numbers used by Windows.\n */\n\nstatic const TkStateMap systemMap[] = {\n    {ANSI_FIXED_FONT,\t    \"ansifixed\"},\n    {ANSI_FIXED_FONT,\t    \"fixed\"},\n    {ANSI_VAR_FONT,\t    \"ansi\"},\n    {DEVICE_DEFAULT_FONT,   \"device\"},\n    {DEFAULT_GUI_FONT,\t    \"defaultgui\"},\n    {OEM_FIXED_FONT,\t    \"oemfixed\"},\n    {SYSTEM_FIXED_FONT,\t    \"systemfixed\"},\n    {SYSTEM_FONT,\t    \"system\"},\n    {-1,\t\t    NULL}\n};\n\ntypedef struct {\n    FontFamily *fontFamilyList; /* The list of font families that are\n\t\t\t\t * currently loaded. As screen fonts are\n\t\t\t\t * loaded, this list grows to hold information\n\t\t\t\t * about what characters exist in each font\n\t\t\t\t * family. */\n    Tcl_HashTable uidTable;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Procedures used only in this file.\n */\n\nstatic FontFamily *\tAllocFontFamily(HDC hdc, HFONT hFont, int base);\nstatic SubFont *\tCanUseFallback(HDC hdc, WinFont *fontPtr,\n\t\t\t    const char *fallbackName, int ch,\n\t\t\t    SubFont **subFontPtrPtr);\nstatic SubFont *\tCanUseFallbackWithAliases(HDC hdc, WinFont *fontPtr,\n\t\t\t    const char *faceName, int ch,\n\t\t\t    Tcl_DString *nameTriedPtr,\n\t\t\t    SubFont **subFontPtrPtr);\nstatic int\t\tFamilyExists(HDC hdc, const char *faceName);\nstatic const char *\tFamilyOrAliasExists(HDC hdc, const char *faceName);\nstatic SubFont *\tFindSubFontForChar(WinFont *fontPtr, int ch,\n\t\t\t    SubFont **subFontPtrPtr);\nstatic void\t\tFontMapInsert(SubFont *subFontPtr, int ch);\nstatic void\t\tFontMapLoadPage(SubFont *subFontPtr, int row);\nstatic int\t\tFontMapLookup(SubFont *subFontPtr, int ch);\nstatic void\t\tFreeFontFamily(FontFamily *familyPtr);\nstatic HFONT\t\tGetScreenFont(const TkFontAttributes *faPtr,\n\t\t\t    const char *faceName, int pixelSize,\n\t\t\t    double angle);\nstatic void\t\tInitFont(Tk_Window tkwin, HFONT hFont,\n\t\t\t    int overstrike, WinFont *tkFontPtr);\nstatic inline void\tInitSubFont(HDC hdc, HFONT hFont, int base,\n\t\t\t    SubFont *subFontPtr);\nstatic int\t\tCreateNamedSystemLogFont(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, const char* name,\n\t\t\t    LOGFONTW* logFontPtr);\nstatic int\t\tCreateNamedSystemFont(Tcl_Interp *interp,\n\t\t\t    Tk_Window tkwin, const char* name, HFONT hFont);\nstatic int\t\tLoadFontRanges(HDC hdc, HFONT hFont,\n\t\t\t    USHORT **startCount, USHORT **endCount,\n\t\t\t    int *symbolPtr);\nstatic void\t\tMultiFontTextOut(HDC hdc, WinFont *fontPtr,\n\t\t\t    const char *source, int numBytes,\n\t\t\t    double x, double y, double angle);\nstatic void\t\tReleaseFont(WinFont *fontPtr);\nstatic inline void\tReleaseSubFont(SubFont *subFontPtr);\nstatic int\t\tSeenName(const char *name, Tcl_DString *dsPtr);\nstatic inline void\tSwapLong(PULONG p);\nstatic inline void\tSwapShort(USHORT *p);\nstatic int CALLBACK\tWinFontCanUseProc(ENUMLOGFONTW *lfPtr,\n\t\t\t    NEWTEXTMETRIC *tmPtr, int fontType,\n\t\t\t    LPARAM lParam);\nstatic int CALLBACK\tWinFontExistProc(ENUMLOGFONTW *lfPtr,\n\t\t\t    NEWTEXTMETRIC *tmPtr, int fontType,\n\t\t\t    LPARAM lParam);\nstatic int CALLBACK\tWinFontFamilyEnumProc(ENUMLOGFONTW *lfPtr,\n\t\t\t    NEWTEXTMETRIC *tmPtr, int fontType,\n\t\t\t    LPARAM lParam);\n\n/* Uniscribe shaping layer - declared here, defined before first use site. */\nstatic int\t\tTkWinShapeString(HDC hdc, WinFont *fontPtr,\n\t\t\t    const WCHAR *wstr, int wlen,\n\t\t\t    TkWinShapedRun **runsOut, int *runCountOut);\nstatic void\t\tTkWinFreeShapedRuns(TkWinShapedRun *runs, int nRuns);\nstatic int\t\tTkWinShapedRunsWidth(const TkWinShapedRun *runs,\n\t\t\t    int nRuns);\n\n/*\n *-------------------------------------------------------------------------\n *\n * TkpFontPkgInit --\n *\n *\tThis procedure is called when an application is created. It\n *\tinitializes all the structures that are used by the platform-dependent\n *\tcode on a per application basis.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpFontPkgInit(\n    TkMainInfo *mainPtr)\t/* The application being created. */\n{\n    TkWinSetupSystemFonts(mainPtr);\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetNativeFont --\n *\n *\tMap a platform-specific native font name to a TkFont.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the native\n *\tfont. If a native font by the given name could not be found, the\n *\treturn value is NULL.\n *\n *\tEvery call to this procedure returns a new TkFont structure, even if\n *\tthe name has already been seen before. The caller should call\n *\tTkpDeleteFont() when the font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generic TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetNativeFont(\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const char *name)\t\t/* Platform-specific font name. */\n{\n    int object;\n    WinFont *fontPtr;\n\n    object = TkFindStateNum(NULL, NULL, systemMap, name);\n    if (object < 0) {\n\treturn NULL;\n    }\n\n    tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;\n    fontPtr = (WinFont *)Tcl_Alloc(sizeof(WinFont));\n    InitFont(tkwin, (HFONT)GetStockObject(object), 0, fontPtr);\n\n    return (TkFont *) fontPtr;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * CreateNamedSystemFont --\n *\n *\tThis function registers a Windows logical font description with the Tk\n *\tnamed font mechanism.\n *\n * Side effects:\n *\tA new named font is added to the Tk font registry.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nCreateNamedSystemLogFont(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    const char* name,\n    LOGFONTW* logFontPtr)\n{\n    HFONT hFont;\n    int r;\n\n    hFont = CreateFontIndirectW(logFontPtr);\n    r = CreateNamedSystemFont(interp, tkwin, name, hFont);\n    DeleteObject((HGDIOBJ)hFont);\n    return r;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * CreateNamedSystemFont --\n *\n *\tThis function registers a Windows font with the Tk named font\n *\tmechanism.\n *\n * Side effects:\n *\tA new named font is added to the Tk font registry.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nCreateNamedSystemFont(\n    Tcl_Interp *interp,\n    Tk_Window tkwin,\n    const char* name,\n    HFONT hFont)\n{\n    WinFont winfont;\n    int r;\n\n    TkDeleteNamedFont(NULL, tkwin, name);\n    InitFont(tkwin, hFont, 0, &winfont);\n    r = TkCreateNamedFont(interp, tkwin, name, &winfont.font.fa);\n    TkpDeleteFont((TkFont *)&winfont);\n    return r;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkWinSystemFonts --\n *\n *\tCreate some platform specific named fonts that to give access to the\n *\tsystem fonts. These are all defined for the Windows desktop\n *\tparameters.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkWinSetupSystemFonts(\n    TkMainInfo *mainPtr)\n{\n    Tcl_Interp *interp;\n    Tk_Window tkwin;\n    const TkStateMap *mapPtr;\n    NONCLIENTMETRICSW ncMetrics;\n    ICONMETRICSW iconMetrics;\n    HFONT hFont;\n\n    interp = (Tcl_Interp *) mainPtr->interp;\n    tkwin = (Tk_Window) mainPtr->winPtr;\n\n    /* force this for now */\n    if (((TkWindow *) tkwin)->mainPtr == NULL) {\n\t((TkWindow *) tkwin)->mainPtr = mainPtr;\n    }\n\n    /*\n     * If this API call fails then we will fallback to setting these named\n     * fonts from script in ttk/fonts.tcl. So far I've only seen it fail when\n     * WINVER has been defined for a higher platform than we are running on.\n     * (i.e. WINVER=0x0600 and running on XP).\n     */\n\n    memset(&ncMetrics, 0, sizeof(ncMetrics));\n    ncMetrics.cbSize = sizeof(ncMetrics);\n    if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,\n\t    sizeof(ncMetrics), &ncMetrics, 0)) {\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkDefaultFont\",\n\t\t&ncMetrics.lfMessageFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkHeadingFont\",\n\t\t&ncMetrics.lfMessageFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkTextFont\",\n\t\t&ncMetrics.lfMessageFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkMenuFont\",\n\t\t&ncMetrics.lfMenuFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkTooltipFont\",\n\t\t&ncMetrics.lfStatusFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkCaptionFont\",\n\t\t&ncMetrics.lfCaptionFont);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkSmallCaptionFont\",\n\t\t&ncMetrics.lfSmCaptionFont);\n    }\n\n    iconMetrics.cbSize = sizeof(iconMetrics);\n    if (SystemParametersInfoW(SPI_GETICONMETRICS, sizeof(iconMetrics),\n\t    &iconMetrics, 0)) {\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkIconFont\",\n\t\t&iconMetrics.lfFont);\n    }\n\n    /*\n     * Identify an available fixed font. Equivalent to ANSI_FIXED_FONT but\n     * more reliable on Russian Windows.\n     */\n\n    {\n\tLOGFONTW lfFixed = {\n\t    0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,\n\t    0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L\"\"\n\t};\n\tlong pointSize, dpi;\n\tHDC hdc = GetDC(NULL);\n\tdpi = GetDeviceCaps(hdc, LOGPIXELSY);\n\tpointSize = -MulDiv(ncMetrics.lfMessageFont.lfHeight, 72, dpi);\n\tlfFixed.lfHeight = -MulDiv(pointSize+1, dpi, 72);\n\tReleaseDC(NULL, hdc);\n\tCreateNamedSystemLogFont(interp, tkwin, \"TkFixedFont\", &lfFixed);\n    }\n\n    /*\n     * Setup the remaining standard Tk font names as named fonts.\n     */\n\n    for (mapPtr = systemMap; mapPtr->strKey != NULL; mapPtr++) {\n\thFont = (HFONT) GetStockObject(mapPtr->numKey);\n\tCreateNamedSystemFont(interp, tkwin, mapPtr->strKey, hFont);\n    }\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFromAttributes --\n *\n *\tGiven a desired set of attributes for a font, find a font with the\n *\tclosest matching attributes.\n *\n * Results:\n *\tThe return value is a pointer to a TkFont that represents the font\n *\twith the desired attributes. If a font with the desired attributes\n *\tcould not be constructed, some other font will be substituted\n *\tautomatically. NULL is never returned.\n *\n *\tEvery call to this procedure returns a new TkFont structure, even if\n *\tthe specified attributes have already been seen before. The caller\n *\tshould call TkpDeleteFont() to free the platform- specific data when\n *\tthe font is no longer needed.\n *\n *\tThe caller is responsible for initializing the memory associated with\n *\tthe generic TkFont when this function returns and releasing the\n *\tcontents of the generic TkFont before calling TkpDeleteFont().\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nTkFont *\nTkpGetFontFromAttributes(\n    TkFont *tkFontPtr,\t\t/* If non-NULL, store the information in this\n\t\t\t\t * existing TkFont structure, rather than\n\t\t\t\t * allocating a new structure to hold the\n\t\t\t\t * font; the existing contents of the font\n\t\t\t\t * will be released. If NULL, a new TkFont\n\t\t\t\t * structure is allocated. */\n    Tk_Window tkwin,\t\t/* For display where font will be used. */\n    const TkFontAttributes *faPtr)\n\t\t\t\t/* Set of attributes to match. */\n{\n    int i, j;\n    HDC hdc;\n    HWND hwnd;\n    HFONT hFont;\n    Window window;\n    WinFont *fontPtr;\n    const char *const *const *fontFallbacks;\n    Tk_Uid faceName, fallback, actualName;\n\n    tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;\n    window = Tk_WindowId(tkwin);\n    hwnd = (window == None) ? NULL : TkWinGetHWND(window);\n    hdc = GetDC(hwnd);\n\n    /*\n     * Algorithm to get the closest font name to the one requested.\n     *\n     * try fontname\n     * try all aliases for fontname\n     * foreach fallback for fontname\n     *\t    try the fallback\n     *\t    try all aliases for the fallback\n     */\n\n    faceName = faPtr->family;\n    if (faceName != NULL) {\n\tactualName = FamilyOrAliasExists(hdc, faceName);\n\tif (actualName != NULL) {\n\t    faceName = actualName;\n\t    goto found;\n\t}\n\tfontFallbacks = TkFontGetFallbacks();\n\tfor (i = 0; fontFallbacks[i] != NULL; i++) {\n\t    for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t\tif (strcasecmp(faceName, fallback) == 0) {\n\t\t    break;\n\t\t}\n\t    }\n\t    if (fallback != NULL) {\n\t\tfor (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {\n\t\t    actualName = FamilyOrAliasExists(hdc, fallback);\n\t\t    if (actualName != NULL) {\n\t\t\tfaceName = actualName;\n\t\t\tgoto found;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n  found:\n    ReleaseDC(hwnd, hdc);\n\n    hFont = GetScreenFont(faPtr, faceName,\n\t    (int)(TkFontGetPixels(tkwin, faPtr->size) + 0.5), 0.0);\n    if (tkFontPtr == NULL) {\n\tfontPtr = (WinFont *)Tcl_Alloc(sizeof(WinFont));\n    } else {\n\tfontPtr = (WinFont *) tkFontPtr;\n\tReleaseFont(fontPtr);\n    }\n    InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);\n\n    return (TkFont *) fontPtr;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkpDeleteFont --\n *\n *\tCalled to release a font allocated by TkpGetNativeFont() or\n *\tTkpGetFontFromAttributes(). The caller should have already released\n *\tthe fields of the TkFont that are used exclusively by the generic\n *\tTkFont code.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTkFont is deallocated.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpDeleteFont(\n    TkFont *tkFontPtr)\t\t/* Token of font to be deleted. */\n{\n    WinFont *fontPtr;\n\n    fontPtr = (WinFont *) tkFontPtr;\n    ReleaseFont(fontPtr);\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkpGetFontFamilies, WinFontFamilyEnumProc --\n *\n *\tReturn information about the font families that are available on the\n *\tdisplay of the given window.\n *\n * Results:\n *\tModifies interp's result object to hold a list of all the available\n *\tfont families.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontFamilies(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Window tkwin)\t\t/* For display to query. */\n{\n    HDC hdc;\n    HWND hwnd;\n    Window window;\n    Tcl_Obj *resultObj;\n\n    window = Tk_WindowId(tkwin);\n    hwnd = (window == None) ? NULL : TkWinGetHWND(window);\n    hdc = GetDC(hwnd);\n    resultObj = Tcl_NewObj();\n\n    /*\n     * On any version NT, there may fonts with international names. Use the\n     * NT-only Unicode version of EnumFontFamilies to get the font names. If\n     * we used the ANSI version on a non-internationalized version of NT, we\n     * would get font names with '?' replacing all the international\n     * characters.\n     *\n     * On a non-internationalized verson of 95, fonts with international names\n     * are not allowed, so the ANSI version of EnumFontFamilies will work. On\n     * an internationalized version of 95, there may be fonts with\n     * international names; the ANSI version will work, fetching the name in\n     * the system code page. Can't use the Unicode version of EnumFontFamilies\n     * because it only exists under NT.\n     */\n\n    EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,\n\t    (LPARAM) resultObj);\n    ReleaseDC(hwnd, hdc);\n    Tcl_SetObjResult(interp, resultObj);\n}\n\nstatic int CALLBACK\nWinFontFamilyEnumProc(\n    ENUMLOGFONTW *lfPtr,\t\t/* Logical-font data. */\n    TCL_UNUSED(NEWTEXTMETRIC *),\t/* Physical-font data (not used). */\n    TCL_UNUSED(int),\t\t/* Type of font (not used). */\n    LPARAM lParam)\t\t/* Result object to hold result. */\n{\n    WCHAR *faceName = lfPtr->elfLogFont.lfFaceName;\n    Tcl_Obj *resultObj = (Tcl_Obj *) lParam;\n    Tcl_DString faceString;\n\n    Tcl_DStringInit(&faceString);\n    Tcl_WCharToUtfDString(faceName, wcslen(faceName), &faceString);\n    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t    Tcl_DStringValue(&faceString), Tcl_DStringLength(&faceString)));\n    Tcl_DStringFree(&faceString);\n    return 1;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * TkpGetSubFonts --\n *\n *\tA function used by the testing package for querying the actual screen\n *\tfonts that make up a font object.\n *\n * Results:\n *\tModifies interp's result object to hold a list containing the names of\n *\tthe screen fonts that make up the given font object.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nvoid\nTkpGetSubFonts(\n    Tcl_Interp *interp,\t\t/* Interp to hold result. */\n    Tk_Font tkfont)\t\t/* Font object to query. */\n{\n    int i;\n    WinFont *fontPtr;\n    FontFamily *familyPtr;\n    Tcl_Obj *resultPtr, *strPtr;\n\n    resultPtr = Tcl_NewObj();\n    fontPtr = (WinFont *) tkfont;\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tfamilyPtr = fontPtr->subFontArray[i].familyPtr;\n\tstrPtr = Tcl_NewStringObj(familyPtr->faceName, TCL_INDEX_NONE);\n\tTcl_ListObjAppendElement(NULL, resultPtr, strPtr);\n    }\n    Tcl_SetObjResult(interp, resultPtr);\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetFontAttrsForChar --\n *\n *\tRetrieve the font attributes of the actual font used to render a given\n *\tcharacter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe font attributes are stored in *faPtr.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetFontAttrsForChar(\n    Tk_Window tkwin,\t\t/* Window on the font's display */\n    Tk_Font tkfont,\t\t/* Font to query */\n    int c,\t\t\t/* Character of interest */\n    TkFontAttributes *faPtr)\t/* Output: Font attributes */\n{\n    WinFont *fontPtr = (WinFont *) tkfont;\n\t\t\t\t/* Structure describing the logical font */\n    HDC hdc = GetDC(fontPtr->hwnd);\n\t\t\t\t/* GDI device context */\n    SubFont *lastSubFontPtr = &fontPtr->subFontArray[0];\n\t\t\t\t/* Pointer to subfont array in case\n\t\t\t\t * FindSubFontForChar needs to fix up the\n\t\t\t\t * memory allocation */\n    SubFont *thisSubFontPtr =\n\t    FindSubFontForChar(fontPtr, c, &lastSubFontPtr);\n\t\t\t\t/* Pointer to the subfont to use for the given\n\t\t\t\t * character */\n    FontFamily *familyPtr = thisSubFontPtr->familyPtr;\n    HFONT oldfont;\t\t/* Saved font from the device context */\n    TEXTMETRICW tm;\t\t/* Font metrics of the selected subfont */\n\n    /*\n     * Get the font attributes.\n     */\n\n    oldfont = (HFONT)SelectObject(hdc, thisSubFontPtr->hFont0);\n    GetTextMetricsW(hdc, &tm);\n    SelectObject(hdc, oldfont);\n    ReleaseDC(fontPtr->hwnd, hdc);\n    faPtr->family = familyPtr->faceName;\n    faPtr->size = TkFontGetPoints(tkwin,\n\t    (double)(tm.tmInternalLeading - tm.tmHeight));\n    faPtr->weight = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;\n    faPtr->slant = tm.tmItalic ? TK_FS_ITALIC : TK_FS_ROMAN;\n    faPtr->underline = (tm.tmUnderlined != 0);\n    faPtr->overstrike = fontPtr->font.fa.overstrike;\n}\n\n/*\n * UNISCRIBE SHAPING LAYER\n *\n * The three functions below form a strict boundary:\n *\n *   TkWinShapeString()        - UTF-8 in, TkWinShapedRun[] out.\n *   TkWinFreeShapedRuns()     - Release memory owned by the run array.\n *   TkWinShapedRunsWidth()    - Sum advance widths across all runs.\n *\n * No code below this boundary may call Tcl_UtfToUniChar, ScriptItemize,\n * ScriptShape, or ScriptPlace.  The drawing and measuring functions receive\n * fully composed, bidi-reordered glyph buffers and call only ScriptTextOut /\n * the advance arrays.\n */\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkWinShapeString --\n *\n *\tConvert a UTF-8 string to a bidi-reordered, shaped array of glyph\n *\truns using Uniscribe.\n *\n *\tPipeline:\n *\t  1. UTF-8 -> UTF-16 (Tcl_UtfToWCharDString)\n *\t  2. ScriptItemize  -- split into script/bidi items\n *\t  3. ScriptLayout   -- compute visual order of items\n *\t  4. For each item in visual order:\n *\t       a. Select the appropriate WinFont subfont (with fallback).\n *\t       b. ScriptShape  -- map chars -> glyphs\n *\t       c. ScriptPlace  -- compute advance widths and offsets\n *\t  5. Return the run array to the caller.\n *\n *\tSubfont fallback: if ScriptShape returns a missing-glyph for any\n *\tposition we retry with every subfont in fontPtr->subFontArray (and\n *\tload new ones via FindSubFontForChar) until a match is found or we\n *\tgive up and leave the .notdef glyph in place.\n *\n * Results:\n *\tReturns the number of runs stored in *runsOut on success, or -1 on a\n *\thard failure (OOM). *runsOut is set to a Tcl_Alloc'd array that the\n *\tcaller must release with TkWinFreeShapedRuns().\n *\n * Side effects:\n *\tMay load additional SubFonts into fontPtr->subFontArray.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nTkWinShapeString(\n    HDC hdc,\n    WinFont *fontPtr,\n    const WCHAR *wstr,          /* UTF-16 input string. */\n    int wlen,                   /* Length in WCHARs (not bytes). */\n    TkWinShapedRun **runsOut,   /* OUT: caller frees with TkWinFreeShapedRuns*/\n    int *runCountOut)           /* OUT: number of runs in *runsOut. */\n{\n    /*\n     * ScriptItemize:\n     * Ask Uniscribe to split the string into script/bidi items.  We start\n     * with a modest stack buffer and re-try with a heap buffer if the string\n     * is unusually complex.\n     */\n#define ITEM_STACK 64\n    SCRIPT_ITEM  stackItems[ITEM_STACK + 1];\n    SCRIPT_ITEM *items     = stackItems;\n    int          itemCount = 0;\n    HRESULT      hr;\n\n    hr = ScriptItemize(wstr, wlen, ITEM_STACK, NULL, NULL,\n\t    items, &itemCount);\n    if (hr == E_OUTOFMEMORY) {\n\t/* String has more than ITEM_STACK items -- allocate on heap. */\n\tint maxItems = wlen + 1;\n\titems = (SCRIPT_ITEM *)Tcl_Alloc(sizeof(SCRIPT_ITEM) * (maxItems + 1));\n\thr = ScriptItemize(wstr, wlen, maxItems, NULL, NULL,\n\t\titems, &itemCount);\n    }\n    if (FAILED(hr)) {\n\tif (items != stackItems) {\n\tTcl_Free(items);\n\t}\n\t*runsOut = NULL;\n\t*runCountOut = 0;\n\treturn -1;\n    }\n\n    /*\n     * ScriptLayout:\n     * Compute the visual (left-to-right) order of the logical items so we\n     * can iterate them in the correct paint order.\n     */\n    int *visualToLogical = (int *)Tcl_Alloc(sizeof(int) * itemCount);\n    {\n\tBYTE *levels = (BYTE *)Tcl_Alloc(sizeof(BYTE) * itemCount);\n\tint   i;\n\tfor (i = 0; i < itemCount; i++) {\n\t    levels[i] = (BYTE)items[i].a.s.uBidiLevel;\n\t}\n\thr = ScriptLayout(itemCount, levels, visualToLogical, NULL);\n\tTcl_Free(levels);\n\tif (FAILED(hr)) {\n\t    /* Fallback: identity order. */\n\t    for (i = 0; i < itemCount; i++) visualToLogical[i] = i;\n\t}\n    }\n\n    /*\n     * Shape and place each item in visual order.\n     */\n    TkWinShapedRun *runs = (TkWinShapedRun *)\n\t    Tcl_Alloc(sizeof(TkWinShapedRun) * itemCount);\n    int nRuns = 0;\n\n    for (int vi = 0; vi < itemCount; vi++) {\n\tint li = visualToLogical[vi];   /* logical item index */\n\tSCRIPT_ITEM *item = &items[li];\n\tint itemStart = item->iCharPos;\n\tint itemLen   = items[li + 1].iCharPos - itemStart;\n\n\t/*\n\t * Allocate worst-case glyph buffer: Uniscribe may produce more glyphs\n\t * than characters (e.g. ligature decomposition).  The recommended\n\t * ceiling is 3/2 * charCount + 16.\n\t */\n\tint    maxGlyphs = (itemLen * 3) / 2 + 16;\n\tWORD  *glyphs    = (WORD *)Tcl_Alloc(sizeof(WORD) * maxGlyphs);\n\tWORD  *logClust  = (WORD *)Tcl_Alloc(sizeof(WORD) * itemLen);\n\tSCRIPT_VISATTR *visAttr =\n\t\t(SCRIPT_VISATTR *)Tcl_Alloc(sizeof(SCRIPT_VISATTR) * maxGlyphs);\n\tint    glyphCount = 0;\n\n\t/*\n\t * Pick the initial subfont from the first character of this item,\n\t * decoding surrogates to the full codepoint so FindSubFontForChar\n\t * can look up the correct fallback.\n\t */\n\tint firstCh;\n\tif (IS_HIGH_SURROGATE(wstr[itemStart]) &&\n\t\t(itemStart + 1) < wlen &&\n\t\tIS_LOW_SURROGATE(wstr[itemStart + 1])) {\n\t    firstCh = 0x10000\n\t\t+ ((wstr[itemStart]     - 0xD800) << 10)\n\t\t+  (wstr[itemStart + 1] - 0xDC00);\n\t} else {\n\t    firstCh = (int)(unsigned)wstr[itemStart];\n\t}\n\n\tSubFont *subFontPtr = &fontPtr->subFontArray[0];\n\tif (firstCh >= BASE_CHARS) {\n\t    /*\n\t     * Pass &subFontPtr (not a dummy) so that if FindSubFontForChar\n\t     * reallocates subFontArray, our local pointer gets fixed up too.\n\t     */\n\t    subFontPtr = FindSubFontForChar(fontPtr, firstCh, &subFontPtr);\n\t}\n\n\t/*\n\t * Find which index in subFontArray this subfont occupies so we can\n\t * pass the matching SCRIPT_CACHE slot to ScriptShape/ScriptPlace.\n\t * FindSubFontForChar always returns a pointer into subFontArray.\n\t */\n\tint subFontIdx = (int)(subFontPtr - fontPtr->subFontArray);\n\n\tHFONT hFont = subFontPtr->hFont0;\n\tSelectObject(hdc, hFont);\n\n\t/*\n\t * ScriptShape: map characters to glyphs.\n\t * Pass the per-subfont SCRIPT_CACHE so Uniscribe can reuse shaping\n\t * tables across calls on the same font.\n\t */\n\thr = ScriptShape(hdc, &fontPtr->scriptCacheArray[subFontIdx],\n\t\twstr + itemStart, itemLen,\n\t\tmaxGlyphs, &item->a,\n\t\tglyphs, logClust, visAttr, &glyphCount);\n\n\tif (hr == E_OUTOFMEMORY) {\n\t    /* Grow glyph buffer and retry once. */\n\t    maxGlyphs *= 2;\n\t    Tcl_Free(glyphs);\n\t    Tcl_Free(visAttr);\n\t    glyphs  = (WORD *)Tcl_Alloc(sizeof(WORD) * maxGlyphs);\n\t    visAttr = (SCRIPT_VISATTR *)\n\t\t    Tcl_Alloc(sizeof(SCRIPT_VISATTR) * maxGlyphs);\n\t    hr = ScriptShape(hdc, &fontPtr->scriptCacheArray[subFontIdx],\n\t\t    wstr + itemStart, itemLen,\n\t\t    maxGlyphs, &item->a,\n\t\t    glyphs, logClust, visAttr, &glyphCount);\n\t}\n\n\tif (FAILED(hr)) {\n\t    /*\n\t     * Shaping failed – try to find a fallback font for the whole\n\t     * item.  Pass &subFontPtr so the pointer is kept valid across\n\t     * any reallocation of subFontArray.\n\t     */\n\t    SubFont *fb = FindSubFontForChar(fontPtr, firstCh, &subFontPtr);\n\t    if (fb != subFontPtr) {\n\t\tsubFontPtr = fb;\n\t\tsubFontIdx = (int)(subFontPtr - fontPtr->subFontArray);\n\t\thFont = subFontPtr->hFont0;\n\t\tSelectObject(hdc, hFont);\n\t\thr = ScriptShape(hdc, &fontPtr->scriptCacheArray[subFontIdx],\n\t\t\twstr + itemStart, itemLen,\n\t\t\tmaxGlyphs, &item->a,\n\t\t\tglyphs, logClust, visAttr, &glyphCount);\n\t    }\n\t    if (FAILED(hr)) {\n\t\t/* Still failing – skip this item. */\n\t\tTcl_Free(glyphs); Tcl_Free(logClust); Tcl_Free(visAttr);\n\t\tcontinue;\n\t    }\n\t}\n\n\t/*\n\t * Subfont fallback for missing glyphs.\n\t * Uniscribe places the font's .notdef glyph (index 0) for any\n\t * character it cannot map.  Walk the cluster map: for each character\n\t * position whose cluster glyph is 0, decode the codepoint (handling\n\t * surrogates) and ask FindSubFontForChar for a better subfont.\n\t * Re-shape the whole item with the new font.  One retry only.\n\t *\n\t * Pass &subFontPtr — not a dummy — to\n\t * FindSubFontForChar.  If CanUseFallback reallocates subFontArray,\n\t * the fixup path inside FindSubFontForChar updates *subFontPtrPtr,\n\t * which is our live subFontPtr variable.  Using a dummy local means\n\t * the realloc goes undetected and the subsequent pointer subtraction\n\t * produces a garbage subFontIdx.\n\t */\n\t{\n\t    int ci, foundMissing = 0;\n\t    for (ci = 0; ci < itemLen && !foundMissing; ci++) {\n\t\tint gi = logClust[ci];\n\t\tif (glyphs[gi] == 0) {\n\t\t    /* Decode surrogate pair if present. */\n\t\t    int ch;\n\t\t    if (IS_HIGH_SURROGATE(wstr[itemStart + ci]) &&\n\t\t\t    (ci + 1) < itemLen &&\n\t\t\t    IS_LOW_SURROGATE(wstr[itemStart + ci + 1])) {\n\t\t\tch = 0x10000\n\t\t\t    + ((wstr[itemStart + ci]     - 0xD800) << 10)\n\t\t\t    +  (wstr[itemStart + ci + 1] - 0xDC00);\n\t\t    } else {\n\t\t\tch = (int)(unsigned)wstr[itemStart + ci];\n\t\t    }\n\n\t\t    SubFont *fb = FindSubFontForChar(fontPtr, ch, &subFontPtr);\n\t\t    if (fb != subFontPtr) {\n\t\t\tsubFontPtr  = fb;\n\t\t\tsubFontIdx  = (int)(subFontPtr - fontPtr->subFontArray);\n\t\t\thFont       = subFontPtr->hFont0;\n\t\t\tSelectObject(hdc, hFont);\n\t\t\t/* Re-shape with the new font and its cache slot. */\n\t\t\tScriptShape(hdc, &fontPtr->scriptCacheArray[subFontIdx],\n\t\t\t\twstr + itemStart, itemLen,\n\t\t\t\tmaxGlyphs, &item->a,\n\t\t\t\tglyphs, logClust, visAttr, &glyphCount);\n\t\t\tfoundMissing = 1; /* one retry only */\n\t\t    }\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * ScriptPlace: compute advance widths and glyph offsets.\n\t * Use the same cache slot that was used for shaping.\n\t */\n\tint     *advances = (int *)Tcl_Alloc(sizeof(int) * glyphCount);\n\tGOFFSET *offsets  = (GOFFSET *)Tcl_Alloc(sizeof(GOFFSET) * glyphCount);\n\tABC      abc;\n\thr = ScriptPlace(hdc, &fontPtr->scriptCacheArray[subFontIdx],\n\t\tglyphs, glyphCount, visAttr, &item->a,\n\t\tadvances, offsets, &abc);\n\tif (FAILED(hr)) {\n\t    Tcl_Free(glyphs); Tcl_Free(logClust); Tcl_Free(visAttr);\n\t    Tcl_Free(advances); Tcl_Free(offsets);\n\t    continue;\n\t}\n\n\t/* logClust and visAttr are not needed past this point. */\n\tTcl_Free(logClust);\n\tTcl_Free(visAttr);\n\n\t/*\n\t * Store the completed run.\n\t *\n\t * Carry scriptCache in the run so MultiFontTextOut\n\t * can pass the correct SCRIPT_CACHE* to ScriptTextOut.  Passing NULL\n\t * there causes Uniscribe to discard all shaping work and produce no\n\t * visible output.\n\t */\n\truns[nRuns].hFont       = hFont;\n\truns[nRuns].subFontPtr  = subFontPtr;\n\truns[nRuns].scriptCache = &fontPtr->scriptCacheArray[subFontIdx];\n\truns[nRuns].sa          = item->a;\n\truns[nRuns].glyphCount  = glyphCount;\n\truns[nRuns].glyphs      = glyphs;\n\truns[nRuns].advances    = advances;\n\truns[nRuns].offsets     = offsets;\n\truns[nRuns].abc         = abc;\n\tnRuns++;\n    }\n\n    if (items != stackItems) Tcl_Free(items);\n    Tcl_Free(visualToLogical);\n\n    *runsOut     = runs;\n    *runCountOut = nRuns;\n    return nRuns;\n#undef ITEM_STACK\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkWinFreeShapedRuns --\n *\n *\tRelease all memory owned by a TkWinShapedRun array produced by\n *\tTkWinShapeString().\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nTkWinFreeShapedRuns(\n    TkWinShapedRun *runs,\n    int nRuns)\n{\n    int i;\n    if (runs == NULL) return;\n    for (i = 0; i < nRuns; i++) {\n\tTcl_Free(runs[i].glyphs);\n\tTcl_Free(runs[i].advances);\n\tTcl_Free(runs[i].offsets);\n    }\n    Tcl_Free(runs);\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * TkWinShapedRunsWidth --\n *\n *\tReturn the total advance width in pixels of a shaped run array.  This\n *\tis the measure path: no drawing occurs.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nTkWinShapedRunsWidth(\n    const TkWinShapedRun *runs,\n    int nRuns)\n{\n    int total = 0, i, g;\n    for (i = 0; i < nRuns; i++) {\n\tfor (g = 0; g < runs[i].glyphCount; g++) {\n\t    total += runs[i].advances[g];\n\t}\n    }\n    return total;\n}\n\n/*\n *\n * End of shaping layer.\n *\n */\n\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureChars --\n *\n *\tDetermine the number of bytes from the string that will fit in the\n *\tgiven horizontal span. The measurement is done under the assumption\n *\tthat Tk_DrawChars() will be used to actually display the characters.\n *\n *\tThis implementation uses the Uniscribe shaping layer so that advance\n *\twidths account for ligatures, kerning, and complex scripts.  Shaping\n *\tis performed on the whole string first; we then walk the shaped runs\n *\tsumming glyph advances until we exceed maxLength.\n *\n *\tIf shaping fails (TkWinShapeString returns error or no runs), we fall\n *\tback to plain GDI measurement with the base font.  This ensures that\n *\tbasic text still works.\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureChars(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    Tcl_Size numBytes,\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length in pixels; don't\n\t\t\t\t * consider any character that would cross\n\t\t\t\t * this x-position. If < 0, then line length\n\t\t\t\t * is unbounded and the flags argument is\n\t\t\t\t * ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fits on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character (or at\n\t\t\t\t * least the first partial word in case\n\t\t\t\t * TK_WHOLE_WORDS is also set) even if no\n\t\t\t\t * characters (words) fit. */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    WinFont *fontPtr;\n    HDC hdc;\n    Tcl_DString uniStr;\n    WCHAR *wstr;\n    int wlen;\n    TkWinShapedRun *runs = NULL;\n    int nRuns = 0;\n    int curX = 0;\n    int bytesFit;\n\n    if (numBytes == 0) {\n\t*lengthPtr = 0;\n\treturn 0;\n    }\n\n    fontPtr = (WinFont *) tkfont;\n    hdc = GetDC(fontPtr->hwnd);\n\n    /*\n     * Convert UTF-8 to UTF-16 for Uniscribe.\n     */\n    Tcl_DStringInit(&uniStr);\n    Tcl_UtfToWCharDString(source, numBytes, &uniStr);\n    wstr = (WCHAR *)Tcl_DStringValue(&uniStr);\n    wlen = (int)(Tcl_DStringLength(&uniStr) / sizeof(WCHAR));\n\n    if (TkWinShapeString(hdc, fontPtr, wstr, wlen, &runs, &nRuns) < 0 || nRuns == 0) {\n\t/* Shaping failed – fall back to plain GDI measurement with base font. */\n\tSIZE size;\n\tSelectObject(hdc, fontPtr->subFontArray[0].hFont0);\n\tGetTextExtentPoint32W(hdc, wstr, wlen, &size);\n\tReleaseDC(fontPtr->hwnd, hdc);\n\tTcl_DStringFree(&uniStr);\n\t*lengthPtr = size.cx;\n\treturn (int)numBytes;\n    }\n\n    ReleaseDC(fontPtr->hwnd, hdc);\n\n    if (maxLength < 0) {\n\t/*\n\t * Unbounded: all bytes fit; return total advance width.\n\t */\n\tcurX = TkWinShapedRunsWidth(runs, nRuns);\n\tTkWinFreeShapedRuns(runs, nRuns);\n\tTcl_DStringFree(&uniStr);\n\t*lengthPtr = curX;\n\treturn (int)numBytes;\n    }\n\n    /*\n     * Walk glyph advances to find the last run/glyph that fits.\n     * Because Uniscribe has already bidi-reordered and shaped the runs,\n     * we can simply accumulate advances left-to-right in visual order.\n     */\n    {\n\tint i, g;\n\tbytesFit = 0;\n\n\tfor (i = 0; i < nRuns; i++) {\n\t    for (g = 0; g < runs[i].glyphCount; g++) {\n\t\tint newX = curX + runs[i].advances[g];\n\t\tif (newX > maxLength) {\n\t\t    /*\n\t\t     * This glyph pushes us over the limit.\n\t\t     */\n\t\t    if ((flags & TK_PARTIAL_OK) && (curX != maxLength)) {\n\t\t\tcurX = newX;\n\t\t\t/* include this glyph - we still need byte count\n\t\t\t * but glyph->byte mapping is not tracked here;\n\t\t\t * fall through to return full string if partial. */\n\t\t    }\n\t\t    goto doneMeasure;\n\t\t}\n\t\tcurX  = newX;\n\t    }\n\t}\n\t/* All glyphs fit. */\n\tbytesFit = (int)numBytes;\n    }\n\n  doneMeasure:\n    if (bytesFit == 0 && curX == TkWinShapedRunsWidth(runs, nRuns)) {\n\tbytesFit = (int)numBytes;\n    } else if (bytesFit == 0) {\n\t/*\n\t * We stopped mid-string.  Map back to a byte count by re-measuring\n\t * the UTF-8 string character by character until we match curX.\n\t * This is the same approach the legacy code uses for its\n\t * \"moretomeasure\" path and is correct for BMP text.\n\t */\n\tconst char *p = source;\n\tconst char *end = source + numBytes;\n\tint accumX = 0;\n\tbytesFit = 0;\n\n\t/* Re-shape prefix substrings until we bracket curX. */\n\twhile (p < end) {\n\t    int ch;\n\t    const char *next = p + Tcl_UtfToUniChar(p, &ch);\n\t    int charBytes = (int)(next - source);\n\n\t    HDC hdc2 = GetDC(fontPtr->hwnd);\n\t    WCHAR *ws2;\n\t    int wl2;\n\t    TkWinShapedRun *r2 = NULL;\n\t    int nr2 = 0;\n\t    Tcl_DString ds2;\n\n\t    Tcl_DStringInit(&ds2);\n\t    Tcl_UtfToWCharDString(source, charBytes, &ds2);\n\t    ws2 = (WCHAR *)Tcl_DStringValue(&ds2);\n\t    wl2 = (int)(Tcl_DStringLength(&ds2) / sizeof(WCHAR));\n\t    if (TkWinShapeString(hdc2, fontPtr, ws2, wl2, &r2, &nr2) < 0 || nr2 == 0) {\n\t\t/* Fallback to GDI */\n\t\tSIZE size;\n\t\tSelectObject(hdc2, fontPtr->subFontArray[0].hFont0);\n\t\tGetTextExtentPoint32W(hdc2, ws2, wl2, &size);\n\t\taccumX = size.cx;\n\t    } else {\n\t\taccumX = TkWinShapedRunsWidth(r2, nr2);\n\t\tTkWinFreeShapedRuns(r2, nr2);\n\t    }\n\t    ReleaseDC(fontPtr->hwnd, hdc2);\n\t    Tcl_DStringFree(&ds2);\n\n\t    if (accumX > maxLength) {\n\t\tif ((flags & TK_PARTIAL_OK) && curX != maxLength) {\n\t\t    bytesFit = charBytes;\n\t\t    curX = accumX;\n\t\t} else if ((p == source) && (flags & TK_AT_LEAST_ONE)) {\n\t\t    bytesFit = charBytes;\n\t\t    curX = accumX;\n\t\t}\n\t\tbreak;\n\t    }\n\t    bytesFit = charBytes;\n\t    curX = accumX;\n\t    p = next;\n\t}\n    }\n\n    TkWinFreeShapedRuns(runs, nRuns);\n    Tcl_DStringFree(&uniStr);\n\n    /*\n     * TK_WHOLE_WORDS: scan back to last word boundary and re-measure.\n     */\n    if ((flags & TK_WHOLE_WORDS) && (bytesFit < (int)numBytes)) {\n\tconst char *lastWordBreak = NULL;\n\tconst char *p = source;\n\tconst char *end = source + bytesFit;\n\tint ch = ' ', ch2;\n\n\twhile (p < end) {\n\t    const char *next = p + Tcl_UtfToUniChar(p, &ch2);\n\t    if ((ch != ' ') && (ch2 == ' ')) {\n\t\tlastWordBreak = p;\n\t    }\n\t    p = next;\n\t    ch = ch2;\n\t}\n\tif (lastWordBreak != NULL) {\n\t    return Tk_MeasureChars(tkfont, source,\n\t\t    lastWordBreak - source, -1, 0, lengthPtr);\n\t}\n\tif (flags & TK_AT_LEAST_ONE) {\n\t    /* bytesFit already set above. */\n\t} else {\n\t    bytesFit = 0;\n\t    curX = 0;\n\t}\n    }\n\n    *lengthPtr = curX;\n    return bytesFit;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_MeasureCharsInContext --\n *\n *\tDetermine the number of bytes from the string that will fit in the\n *\tgiven horizontal span. The measurement is done under the assumption\n *\tthat Tk_DrawCharsInContext() will be used to actually display the\n *\tcharacters.\n *\n *\tThis one is almost the same as Tk_MeasureChars(), but with access to\n *\tall the characters on the line for context. On Windows this context\n *\tisn't consulted, so we just call Tk_MeasureChars().\n *\n * Results:\n *\tThe return value is the number of bytes from source that fit into the\n *\tspan that extends from 0 to maxLength. *lengthPtr is filled with the\n *\tx-coordinate of the right edge of the last character that did fit.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nint\nTk_MeasureCharsInContext(\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Maximum number of bytes to consider from\n\t\t\t\t * source string in all. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to measure. */\n    Tcl_Size rangeLength,\t\t/* Length of range to measure in bytes. */\n    int maxLength,\t\t/* If >= 0, maxLength specifies the longest\n\t\t\t\t * permissible line length; don't consider any\n\t\t\t\t * character that would cross this x-position.\n\t\t\t\t * If < 0, then line length is unbounded and\n\t\t\t\t * the flags argument is ignored. */\n    int flags,\t\t\t/* Various flag bits OR-ed together:\n\t\t\t\t * TK_PARTIAL_OK means include the last char\n\t\t\t\t * which only partially fit on this line.\n\t\t\t\t * TK_WHOLE_WORDS means stop on a word\n\t\t\t\t * boundary, if possible. TK_AT_LEAST_ONE\n\t\t\t\t * means return at least one character even if\n\t\t\t\t * no characters fit. TK_ISOLATE_END means\n\t\t\t\t * that the last character should not be\n\t\t\t\t * considered in context with the rest of the\n\t\t\t\t * string (used for breaking lines). */\n    int *lengthPtr)\t\t/* Filled with x-location just after the\n\t\t\t\t * terminating character. */\n{\n    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,\n\t    maxLength, flags, lengthPtr);\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawChars --\n *\n *\tDraw a string of characters on the screen.\n *\n *\tThe drawing path calls TkWinShapeString() once to obtain fully shaped,\n *\tbidi-reordered glyph runs, then iterates over those runs calling\n *\tScriptTextOut.  No Unicode parsing or subfont selection occurs during\n *\tdrawing.\n *\n *\tIf shaping fails, we fall back to plain GDI drawing with the base\n *\tfont.  This ensures that text always appears, even when Uniscribe\n *\tcannot process the string.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    TCL_UNUSED(Tk_Font),\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    int x, int y)\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n{\n    HDC dc;\n    WinFont *fontPtr;\n    TkWinDCState state;\n\n    fontPtr = (WinFont *) gc->font;\n    LastKnownRequestProcessed(display)++;\n\n    if (drawable == None) {\n\treturn;\n    }\n\n    dc = TkWinGetDrawableDC(display, drawable, &state);\n\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n\n    if ((gc->clip_mask != None) &&\n\t    ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {\n\tSelectClipRgn(dc, (HRGN)((TkpClipMask *)gc->clip_mask)->value.region);\n    }\n\n    if ((gc->fill_style == FillStippled\n\t    || gc->fill_style == FillOpaqueStippled)\n\t    && gc->stipple != None) {\n\tTkWinDrawable *twdPtr = (TkWinDrawable *) gc->stipple;\n\tHBRUSH oldBrush, stipple;\n\tHBITMAP oldBitmap, bitmap;\n\tHDC dcMem;\n\tTEXTMETRICW tm;\n\tSIZE size;\n\n\tif (twdPtr->type != TWD_BITMAP) {\n\t    Tcl_Panic(\"unexpected drawable type in stipple\");\n\t}\n\n\t/*\n\t * Select stipple pattern into destination dc.\n\t */\n\n\tdcMem = CreateCompatibleDC(dc);\n\n\tstipple = CreatePatternBrush(twdPtr->bitmap.handle);\n\tSetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);\n\toldBrush = (HBRUSH)SelectObject(dc, stipple);\n\n\tSetTextAlign(dcMem, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dcMem, gc->foreground);\n\tSetBkMode(dcMem, TRANSPARENT);\n\tSetBkColor(dcMem, RGB(0, 0, 0));\n\n\t/*\n\t * Compute the bounding box and create a compatible bitmap.\n\t */\n\n\tGetTextExtentPointA(dcMem, source, (int)numBytes, &size);\n\tGetTextMetricsW(dcMem, &tm);\n\tsize.cx -= tm.tmOverhang;\n\tbitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);\n\toldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n\n\t/*\n\t * The following code is tricky because fonts are rendered in multiple\n\t * colors. First we draw onto a black background and copy the white\n\t * bits. Then we draw onto a white background and copy the black bits.\n\t * Both the foreground and background bits of the font are ANDed with\n\t * the stipple pattern as they are copied.\n\t */\n\n\tPatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, 0.0);\n\tBitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, 0xEA02E9);\n\tPatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, 0.0);\n\tBitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, 0x8A0E06);\n\n\t/*\n\t * Destroy the temporary bitmap and restore the device context.\n\t */\n\n\tSelectObject(dcMem, oldBitmap);\n\tDeleteObject(bitmap);\n\tDeleteDC(dcMem);\n\tSelectObject(dc, oldBrush);\n\tDeleteObject(stipple);\n    } else if (gc->function == GXcopy) {\n\tSetTextAlign(dc, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dc, gc->foreground);\n\tSetBkMode(dc, TRANSPARENT);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, 0.0);\n    } else {\n\tHBITMAP oldBitmap, bitmap;\n\tHDC dcMem;\n\tTEXTMETRICW tm;\n\tSIZE size;\n\n\tdcMem = CreateCompatibleDC(dc);\n\n\tSetTextAlign(dcMem, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dcMem, gc->foreground);\n\tSetBkMode(dcMem, TRANSPARENT);\n\tSetBkColor(dcMem, RGB(0, 0, 0));\n\n\t/*\n\t * Compute the bounding box and create a compatible bitmap.\n\t */\n\n\tGetTextExtentPointA(dcMem, source, (int)numBytes, &size);\n\tGetTextMetricsW(dcMem, &tm);\n\tsize.cx -= tm.tmOverhang;\n\tbitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);\n\toldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n\n\tMultiFontTextOut(dcMem, fontPtr, source, (int)numBytes, 0, tm.tmAscent,\n\t\t0.0);\n\tBitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, (DWORD) tkpWinBltModes[gc->function]);\n\n\t/*\n\t * Destroy the temporary bitmap and restore the device context.\n\t */\n\n\tSelectObject(dcMem, oldBitmap);\n\tDeleteObject(bitmap);\n\tDeleteDC(dcMem);\n    }\n    TkWinReleaseDrawableDC(drawable, dc, &state);\n}\n\nvoid\nTkDrawAngledChars(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    TCL_UNUSED(Tk_Font),\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    Tcl_Size numBytes,\t\t/* Number of bytes in string. */\n    double x, double y,\t\t/* Coordinates at which to place origin of\n\t\t\t\t * string when drawing. */\n    double angle)\n{\n    HDC dc;\n    WinFont *fontPtr;\n    TkWinDCState state;\n\n    fontPtr = (WinFont *) gc->font;\n    LastKnownRequestProcessed(display)++;\n\n    if (drawable == None) {\n\treturn;\n    }\n\n    dc = TkWinGetDrawableDC(display, drawable, &state);\n\n    SetROP2(dc, tkpWinRopModes[gc->function]);\n\n    if ((gc->clip_mask != None) &&\n\t    ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {\n\tSelectClipRgn(dc, (HRGN)((TkpClipMask *)gc->clip_mask)->value.region);\n    }\n\n    if ((gc->fill_style == FillStippled\n\t    || gc->fill_style == FillOpaqueStippled)\n\t    && gc->stipple != None) {\n\tTkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;\n\tHBRUSH oldBrush, stipple;\n\tHBITMAP oldBitmap, bitmap;\n\tHDC dcMem;\n\tTEXTMETRICW tm;\n\tSIZE size;\n\n\tif (twdPtr->type != TWD_BITMAP) {\n\t    Tcl_Panic(\"unexpected drawable type in stipple\");\n\t}\n\n\t/*\n\t * Select stipple pattern into destination dc.\n\t */\n\n\tdcMem = CreateCompatibleDC(dc);\n\n\tstipple = CreatePatternBrush(twdPtr->bitmap.handle);\n\tSetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);\n\toldBrush = (HBRUSH)SelectObject(dc, stipple);\n\n\tSetTextAlign(dcMem, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dcMem, gc->foreground);\n\tSetBkMode(dcMem, TRANSPARENT);\n\tSetBkColor(dcMem, RGB(0, 0, 0));\n\n\t/*\n\t * Compute the bounding box and create a compatible bitmap.\n\t */\n\n\tGetTextExtentPointA(dcMem, source, (int)numBytes, &size);\n\tGetTextMetricsW(dcMem, &tm);\n\tsize.cx -= tm.tmOverhang;\n\tbitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);\n\toldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n\n\t/*\n\t * The following code is tricky because fonts are rendered in multiple\n\t * colors. First we draw onto a black background and copy the white\n\t * bits. Then we draw onto a white background and copy the black bits.\n\t * Both the foreground and background bits of the font are ANDed with\n\t * the stipple pattern as they are copied.\n\t */\n\n\tPatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, angle);\n\tBitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, 0xEA02E9);\n\tPatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, angle);\n\tBitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, 0x8A0E06);\n\n\t/*\n\t * Destroy the temporary bitmap and restore the device context.\n\t */\n\n\tSelectObject(dcMem, oldBitmap);\n\tDeleteObject(bitmap);\n\tDeleteDC(dcMem);\n\tSelectObject(dc, oldBrush);\n\tDeleteObject(stipple);\n    } else if (gc->function == GXcopy) {\n\tSetTextAlign(dc, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dc, gc->foreground);\n\tSetBkMode(dc, TRANSPARENT);\n\tMultiFontTextOut(dc, fontPtr, source, (int)numBytes, x, y, angle);\n    } else {\n\tHBITMAP oldBitmap, bitmap;\n\tHDC dcMem;\n\tTEXTMETRICW tm;\n\tSIZE size;\n\n\tdcMem = CreateCompatibleDC(dc);\n\n\tSetTextAlign(dcMem, TA_LEFT | TA_BASELINE);\n\tSetTextColor(dcMem, gc->foreground);\n\tSetBkMode(dcMem, TRANSPARENT);\n\tSetBkColor(dcMem, RGB(0, 0, 0));\n\n\t/*\n\t * Compute the bounding box and create a compatible bitmap.\n\t */\n\n\tGetTextExtentPointA(dcMem, source, (int)numBytes, &size);\n\tGetTextMetricsW(dcMem, &tm);\n\tsize.cx -= tm.tmOverhang;\n\tbitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);\n\toldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);\n\n\tMultiFontTextOut(dcMem, fontPtr, source, (int)numBytes, 0, tm.tmAscent,\n\t\tangle);\n\tBitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,\n\t\t0, 0, (DWORD) tkpWinBltModes[gc->function]);\n\n\t/*\n\t * Destroy the temporary bitmap and restore the device context.\n\t */\n\n\tSelectObject(dcMem, oldBitmap);\n\tDeleteObject(bitmap);\n\tDeleteDC(dcMem);\n    }\n    TkWinReleaseDrawableDC(drawable, dc, &state);\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * Tk_DrawCharsInContext --\n *\n *\tDraw a string of characters on the screen like Tk_DrawChars(), but\n *\twith access to all the characters on the line for context. On Windows\n *\tthis context isn't consulted, so we just call Tk_DrawChars().\n  *\n *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this\n *            function is unused.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen.\n *\n *---------------------------------------------------------------------------\n */\n\nvoid\nTk_DrawCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn;\n\t\t\t\t * must be the same as font used in GC. */\n    const char *source,\t\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that\n\t\t\t\t * is passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    int x, int y)\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n{\n    int widthUntilStart;\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+widthUntilStart, y);\n}\n\nvoid\nTkpDrawAngledCharsInContext(\n    Display *display,\t\t/* Display on which to draw. */\n    Drawable drawable,\t\t/* Window or pixmap in which to draw. */\n    GC gc,\t\t\t/* Graphics context for drawing characters. */\n    Tk_Font tkfont,\t\t/* Font in which characters will be drawn; must\n\t\t\t\t * be the same as font used in GC. */\n    const char * source,\t/* UTF-8 string to be displayed. Need not be\n\t\t\t\t * '\\0' terminated. All Tk meta-characters\n\t\t\t\t * (tabs, control characters, and newlines)\n\t\t\t\t * should be stripped out of the string that is\n\t\t\t\t * passed to this function. If they are not\n\t\t\t\t * stripped out, they will be displayed as\n\t\t\t\t * regular printing characters. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of bytes in string. */\n    Tcl_Size rangeStart,\t\t/* Index of first byte to draw. */\n    Tcl_Size rangeLength,\t\t/* Length of range to draw in bytes. */\n    double x, double y,\t\t/* Coordinates at which to place origin of the\n\t\t\t\t * whole (not just the range) string when\n\t\t\t\t * drawing. */\n    double angle)\t\t/* What angle to put text at, in degrees. */\n{\n    int widthUntilStart;\n    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);\n\n    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);\n    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,\n\t    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * MultiFontTextOut --\n *\n *\tRender a UTF-8 string using the Uniscribe shaping layer.\n *\n *\tThis function is the sole drawing entry point.  It calls\n *\tTkWinShapeString() to obtain fully shaped, bidi-reordered\n *\tTkWinShapedRun buffers, then dispatches each run to the appropriate\n *\tGDI rendering path:\n *\n *\t  - Runs whose subfont contains color glyph tables (COLR/CPAL or CBLC,\n *\t    i.e. color emoji such as Segoe UI Emoji) are drawn with\n *\t    ExtTextOutW and ETO_GLYPH_INDEX.  ScriptTextOut uses the legacy\n *\t    GDI monochrome rasterizer which ignores color tables entirely,\n *\t    producing tofu (empty boxes) for every emoji glyph.\n *\n *\t  - All other runs use ScriptTextOut as before so that Uniscribe\n *\t    shaping (ligatures, mark positioning, bidi, etc.) is preserved.\n *\n *\tIf shaping fails entirely we fall back to plain GDI drawing with the\n *\tbase font so that text always appears.\n *\n *\tThe 'angle' parameter rotates the escapement of the font before\n *\tshaping so that TrueType rotation is applied correctly per run.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation gets drawn on the screen. Contents of fontPtr may be\n *\tmodified if more subfonts were loaded in order to draw all the\n *\tmultilingual characters in the given string.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nMultiFontTextOut(\n    HDC hdc,\n    WinFont *fontPtr,\n    const char *source,\n    int numBytes,\n    double x, double y,\n    double angle)\n{\n    Tcl_DString uniStr;\n    WCHAR *wstr;\n    int wlen;\n    int i;\n    HFONT oldFont;\n\n    if (numBytes == 0) return;\n\n    Tcl_DStringInit(&uniStr);\n    Tcl_UtfToWCharDString(source, numBytes, &uniStr);\n    wstr = (WCHAR *)Tcl_DStringValue(&uniStr);\n    wlen = (int)(Tcl_DStringLength(&uniStr) / sizeof(WCHAR));\n\n    /*\n     * Global emoji detection -\n     *\n     * If the string contains surrogate pairs → Uniscribe cannot shape it.\n     * Bypass shaping entirely and use ExtTextOutW.\n     */\n    bool hasSurrogate = false;\n    for (i = 0; i < wlen; i++) {\n\tWCHAR wc = wstr[i];\n\tif (wc >= 0xD800 && wc <= 0xDBFF) {\n\t    hasSurrogate = true;\n\t    break;\n\t}\n    }\n\n    if (hasSurrogate) {\n\t/* Choose fallback font inline. */\n\tHFONT hEmoji = NULL;\n\tstatic const char *const emojiFonts[] = {\n\t    \"Segoe UI Emoji\",      /* Color emoji */\n\t    \"Segoe UI Symbol\",     /* Monochrome emoji */\n\t    \"Segoe UI\",\n\t    \"Arial Unicode MS\",\n\t    \"Lucida Sans Unicode\",\n\t    NULL\n\t};\n\tfor (int ef = 0; emojiFonts[ef]; ef++) {\n\t    HFONT h = GetScreenFont(&fontPtr->font.fa,\n\t\t\t\t    emojiFonts[ef],\n\t\t\t\t    fontPtr->pixelSize,\n\t\t\t\t    angle);\n\t    if (h) { hEmoji = h; break; }\n\t}\n\tif (!hEmoji) {\n\t    hEmoji = fontPtr->subFontArray[0].hFont0;\n\t}\n\n\tHFONT old = (HFONT)SelectObject(hdc, hEmoji);\n\tSetBkMode(hdc, TRANSPARENT);\n\n\tExtTextOutW(\n\t    hdc,\n\t    (int)(x + 0.5), (int)(y + 0.5),\n\t    0,\n\t    NULL,\n\t    wstr,\n\t    wlen,\n\t    NULL);\n\n\tSelectObject(hdc, old);\n\tTcl_DStringFree(&uniStr);\n\treturn;\n    }\n\n    /*\n     * Normal Uniscribe path -\n     *\n     * Used for all non-emoji text: Arabic, Hebrew, Indic, Thai, etc.\n     */\n\n    TkWinShapedRun *runs = NULL;\n    int nRuns = 0;\n\n    if (TkWinShapeString(hdc, fontPtr, wstr, wlen, &runs, &nRuns) < 0 || nRuns == 0) {\n\tHFONT old = (HFONT)SelectObject(hdc, fontPtr->subFontArray[0].hFont0);\n\tSetBkMode(hdc, TRANSPARENT);\n\tTextOutW(hdc, (int)x, (int)y, wstr, wlen);\n\tSelectObject(hdc, old);\n\tTcl_DStringFree(&uniStr);\n\treturn;\n    }\n\n    oldFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);\n    int oldBkMode = SetBkMode(hdc, TRANSPARENT);\n\n    double sinA = sin(angle * PI / 180.0);\n    double cosA = cos(angle * PI / 180.0);\n\n    for (i = 0; i < nRuns; i++) {\n\tTkWinShapedRun *run = &runs[i];\n\tHFONT hDrawFont = run->hFont;\n\tHFONT hAngled = NULL;\n\tint runWidth = 0;\n\n\t/* Rotation support. */\n\tif (angle != 0.0) {\n\t    hAngled = GetScreenFont(&fontPtr->font.fa,\n\t\t\t\t    run->subFontPtr->familyPtr->faceName,\n\t\t\t\t    fontPtr->pixelSize,\n\t\t\t\t    angle);\n\t    if (hAngled) {\n\t\thDrawFont = hAngled;\n\t    }\n\t}\n\n\tSelectObject(hdc, hDrawFont);\n\n\tScriptTextOut(\n\t    hdc,\n\t    run->scriptCache,\n\t    (int)(x + 0.5), (int)(y + 0.5),\n\t    0,\n\t    NULL,\n\t    &run->sa,\n\t    NULL, 0,\n\t    run->glyphs,\n\t    run->glyphCount,\n\t    run->advances,\n\t    NULL,\n\t    run->offsets);\n\n\tfor (int g = 0; g < run->glyphCount; g++) {\n\t    runWidth += run->advances[g];\n\t}\n\n\tx += cosA * runWidth;\n\ty -= sinA * runWidth;\n\n\tif (hAngled) {\n\t    DeleteObject(hAngled);\n\t}\n    }\n\n    SetBkMode(hdc, oldBkMode);\n    SelectObject(hdc, oldFont);\n    TkWinFreeShapedRuns(runs, nRuns);\n    Tcl_DStringFree(&uniStr);\n}\n\n\n\n/*\n *---------------------------------------------------------------------------\n *\n * InitFont --\n *\n *\tHelper for TkpGetNativeFont() and TkpGetFontFromAttributes().\n *\tInitializes the memory for a new WinFont that wraps the\n *\tplatform-specific data.\n *\n *\tThe caller is responsible for initializing the fields of the WinFont\n *\tthat are used exclusively by the generic TkFont code, and for\n *\treleasing those fields before calling TkpDeleteFont().\n *\n * Results:\n *\tFills the WinFont structure.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nInitFont(\n    Tk_Window tkwin,\t\t/* Main window of interp in which font will be\n\t\t\t\t * used, for getting HDC. */\n    HFONT hFont,\t\t/* Windows token for font. */\n    int overstrike,\t\t/* The overstrike attribute of logfont used to\n\t\t\t\t * allocate this font. For some reason, the\n\t\t\t\t * TEXTMETRICWs may contain incorrect info in\n\t\t\t\t * the tmStruckOut field. */\n    WinFont *fontPtr)\t\t/* Filled with information constructed from\n\t\t\t\t * the above arguments. */\n{\n    HDC hdc;\n    HWND hwnd;\n    HFONT oldFont;\n    TEXTMETRICW tm;\n    Window window;\n    TkFontMetrics *fmPtr;\n    Tcl_Encoding encoding;\n    Tcl_DString faceString;\n    TkFontAttributes *faPtr;\n    WCHAR buf[LF_FACESIZE];\n\n    window = Tk_WindowId(tkwin);\n    hwnd = (window == None) ? NULL : TkWinGetHWND(window);\n    hdc = GetDC(hwnd);\n    oldFont = (HFONT)SelectObject(hdc, hFont);\n\n    GetTextMetricsW(hdc, &tm);\n\n    GetTextFaceW(hdc, LF_FACESIZE, buf);\n    Tcl_DStringInit(&faceString);\n    Tcl_WCharToUtfDString(buf, wcslen(buf), &faceString);\n\n    fontPtr->font.fid\t= (Font) fontPtr;\n    fontPtr->hwnd\t= hwnd;\n    fontPtr->pixelSize\t= tm.tmHeight - tm.tmInternalLeading;\n\n    faPtr\t\t= &fontPtr->font.fa;\n    faPtr->family\t= Tk_GetUid(Tcl_DStringValue(&faceString));\n\n    faPtr->size =\n\tTkFontGetPoints(tkwin,  (double)-(fontPtr->pixelSize));\n    faPtr->weight =\n\t    (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;\n    faPtr->slant\t= (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;\n    faPtr->underline\t= (tm.tmUnderlined != 0) ? 1 : 0;\n    faPtr->overstrike\t= overstrike;\n\n    fmPtr\t\t= &fontPtr->font.fm;\n    fmPtr->ascent\t= tm.tmAscent;\n    fmPtr->descent\t= tm.tmDescent;\n    fmPtr->maxWidth\t= tm.tmMaxCharWidth;\n    fmPtr->fixed\t= !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);\n\n    fontPtr->numSubFonts\t= 1;\n    fontPtr->subFontArray\t= fontPtr->staticSubFonts;\n    memset(fontPtr->staticScriptCaches, 0, sizeof(fontPtr->staticScriptCaches));\n    fontPtr->scriptCacheArray\t= fontPtr->staticScriptCaches;\n    InitSubFont(hdc, hFont, 1, &fontPtr->subFontArray[0]);\n\n    encoding = fontPtr->subFontArray[0].familyPtr->encoding;\n    if (encoding == TkWinGetUnicodeEncoding()) {\n\tGetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);\n    } else {\n\tGetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);\n    }\n    Tcl_DStringFree(&faceString);\n\n    SelectObject(hdc, oldFont);\n    ReleaseDC(hwnd, hdc);\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * ReleaseFont --\n *\n *\tCalled to release the windows-specific contents of a TkFont. The\n *\tcaller is responsible for freeing the memory used by the font itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory is freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic void\nReleaseFont(\n    WinFont *fontPtr)\t\t/* The font to delete. */\n{\n    int i;\n\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tReleaseSubFont(&fontPtr->subFontArray[i]);\n\tScriptFreeCache(&fontPtr->scriptCacheArray[i]);\n    }\n    if (fontPtr->subFontArray != fontPtr->staticSubFonts) {\n\tTcl_Free(fontPtr->subFontArray);\n    }\n    if (fontPtr->scriptCacheArray != fontPtr->staticScriptCaches) {\n\tTcl_Free(fontPtr->scriptCacheArray);\n    }\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * InitSubFont --\n *\n *\tWrap a screen font and load the FontFamily that represents it. Used to\n *\tprepare a SubFont so that characters can be mapped from UTF-8 to the\n *\tcharset of the font.\n *\n * Results:\n *\tThe subFontPtr is filled with information about the font.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\n/*\n * FOURCC_TAG --\n *\n *   Build a big-endian DWORD from four characters, as required by\n *   GetFontData() for OpenType table tags.  The Windows GDI expects\n *   the tag in the byte order used in the font file, which is big-endian.\n *   So \"COLR\" becomes 0x434F4C52.\n */\n#ifndef FOURCC_TAG\n#define FOURCC_TAG(a,b,c,d) \\\n    ((DWORD)(BYTE)(a) << 24 | (DWORD)(BYTE)(b) << 16 | \\\n     (DWORD)(BYTE)(c) << 8  | (DWORD)(BYTE)(d))\n#endif\n\nstatic inline void\nInitSubFont(\n    HDC hdc,\t\t\t/* HDC in which font can be selected. */\n    HFONT hFont,\t\t/* The screen font. */\n    int base,\t\t\t/* Non-zero if this SubFont is being used as\n\t\t\t\t * the base font for a font object. */\n    SubFont *subFontPtr)\t/* Filled with SubFont constructed from above\n\t\t\t\t * attributes. */\n{\n\n    subFontPtr->hFont0\t    = hFont;\n    subFontPtr->familyPtr   = AllocFontFamily(hdc, hFont, base);\n    subFontPtr->fontMap\t    = subFontPtr->familyPtr->fontMap;\n    subFontPtr->hFontAngled = NULL;\n    subFontPtr->angle\t    = 0.0;\n\n    SelectObject(hdc, hFont);\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * ReleaseSubFont --\n *\n *\tCalled to release the contents of a SubFont. The caller is responsible\n *\tfor freeing the memory used by the SubFont itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory and resources are freed.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic inline void\nReleaseSubFont(\n    SubFont *subFontPtr)\t/* The SubFont to delete. */\n{\n    DeleteObject(subFontPtr->hFont0);\n    if (subFontPtr->hFontAngled) {\n\tDeleteObject(subFontPtr->hFontAngled);\n    }\n    FreeFontFamily(subFontPtr->familyPtr);\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * AllocFontFamily --\n *\n *\tFind the FontFamily structure associated with the given font name. The\n *\tinformation should be stored by the caller in a SubFont and used when\n *\tdetermining if that SubFont supports a character.\n *\n *\tCannot use the string name used to construct the font as the key,\n *\tbecause the capitalization may not be canonical. Therefore use the\n *\tface name actually retrieved from the font metrics as the key.\n *\n * Results:\n *\tA pointer to a FontFamily. The reference count in the FontFamily is\n *\tautomatically incremented. When the SubFont is released, the reference\n *\tcount is decremented. When no SubFont is using this FontFamily, it may\n *\tbe deleted.\n *\n * Side effects:\n *\tA new FontFamily structure will be allocated if this font family has\n *\tnot been seen. TrueType character existence metrics are loaded into\n *\tthe FontFamily structure.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic FontFamily *\nAllocFontFamily(\n    HDC hdc,\t\t\t/* HDC in which font can be selected. */\n    HFONT hFont,\t\t/* Screen font whose FontFamily is to be\n\t\t\t\t * returned. */\n    TCL_UNUSED(int))\t\t\t/* Non-zero if this font family is to be used\n\t\t\t\t * in the base font of a font object. */\n{\n    Tk_Uid faceName;\n    FontFamily *familyPtr;\n    Tcl_DString faceString;\n    Tcl_Encoding encoding;\n    WCHAR buf[LF_FACESIZE];\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    hFont = (HFONT)SelectObject(hdc, hFont);\n    GetTextFaceW(hdc, LF_FACESIZE, buf);\n    Tcl_DStringInit(&faceString);\n    Tcl_WCharToUtfDString(buf, wcslen(buf), &faceString);\n    faceName = Tk_GetUid(Tcl_DStringValue(&faceString));\n    Tcl_DStringFree(&faceString);\n    hFont = (HFONT)SelectObject(hdc, hFont);\n\n    familyPtr = tsdPtr->fontFamilyList;\n    for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {\n\tif (familyPtr->faceName == faceName) {\n\t    familyPtr->refCount++;\n\t    return familyPtr;\n\t}\n    }\n\n    familyPtr = (FontFamily *)Tcl_Alloc(sizeof(FontFamily));\n    memset(familyPtr, 0, sizeof(FontFamily));\n    familyPtr->nextPtr = tsdPtr->fontFamilyList;\n    tsdPtr->fontFamilyList = familyPtr;\n\n    /*\n     * Set key for this FontFamily.\n     */\n\n    familyPtr->faceName = faceName;\n\n    /*\n     * An initial refCount of 2 means that FontFamily information will persist\n     * even when the SubFont that loaded the FontFamily is released. Change it\n     * to 1 to cause FontFamilies to be unloaded when not in use.\n     */\n\n    familyPtr->refCount = 2;\n\n    familyPtr->segCount = LoadFontRanges(hdc, hFont, &familyPtr->startCount,\n\t    &familyPtr->endCount, &familyPtr->isSymbolFont);\n\n    encoding = NULL;\n    if (familyPtr->isSymbolFont) {\n\t/*\n\t * Symbol fonts are handled specially. For instance, Unicode 0393\n\t * (GREEK CAPITAL GAMMA) must be mapped to Symbol character 0047\n\t * (GREEK CAPITAL GAMMA), because the Symbol font doesn't have a GREEK\n\t * CAPITAL GAMMA at location 0393. If Tk interpreted the Symbol font\n\t * using the Unicode encoding, it would decide that the Symbol font\n\t * has no GREEK CAPITAL GAMMA, because the Symbol encoding (of course)\n\t * reports that character 0393 doesn't exist.\n\t *\n\t * With non-symbol Windows fonts, such as Times New Roman, if the font\n\t * has a GREEK CAPITAL GAMMA, it will be found in the correct Unicode\n\t * location (0393); the GREEK CAPITAL GAMMA will not be off hiding at\n\t * some other location.\n\t */\n\n\tencoding = Tcl_GetEncoding(NULL, faceName);\n    }\n\n    if (encoding == NULL) {\n\tencoding = TkWinGetUnicodeEncoding();\n\tfamilyPtr->textOutProc =\n\t    (BOOL (WINAPI *)(HDC, int, int, WCHAR *, int)) TextOutW;\n\tfamilyPtr->getTextExtentPoint32Proc =\n\t    (BOOL (WINAPI *)(HDC, WCHAR *, int, LPSIZE)) GetTextExtentPoint32W;\n\tfamilyPtr->isWideFont = 1;\n    } else {\n\tfamilyPtr->textOutProc =\n\t    (BOOL (WINAPI *)(HDC, int, int, WCHAR *, int)) TextOutA;\n\tfamilyPtr->getTextExtentPoint32Proc =\n\t    (BOOL (WINAPI *)(HDC, WCHAR *, int, LPSIZE)) GetTextExtentPoint32A;\n\tfamilyPtr->isWideFont = 0;\n    }\n\n    familyPtr->encoding = encoding;\n\n    return familyPtr;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FreeFontFamily --\n *\n *\tCalled to free a FontFamily when the SubFont is finished using it.\n *\tFrees the contents of the FontFamily and the memory used by the\n *\tFontFamily itself.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFreeFontFamily(\n    FontFamily *familyPtr)\t/* The FontFamily to delete. */\n{\n    int i;\n    FontFamily **familyPtrPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (familyPtr == NULL) {\n\treturn;\n    }\n    if (familyPtr->refCount-- > 1) {\n\treturn;\n    }\n    for (i = 0; i < FONTMAP_PAGES; i++) {\n\tif (familyPtr->fontMap[i] != NULL) {\n\t    Tcl_Free(familyPtr->fontMap[i]);\n\t}\n    }\n    if (familyPtr->startCount != NULL) {\n\tTcl_Free(familyPtr->startCount);\n    }\n    if (familyPtr->endCount != NULL) {\n\tTcl_Free(familyPtr->endCount);\n    }\n    if (familyPtr->encoding != TkWinGetUnicodeEncoding()) {\n\tTcl_FreeEncoding(familyPtr->encoding);\n    }\n\n    /*\n     * Delete from list.\n     */\n\n    for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {\n\tif (*familyPtrPtr == familyPtr) {\n\t    *familyPtrPtr = familyPtr->nextPtr;\n\t    break;\n\t}\n\tfamilyPtrPtr = &(*familyPtrPtr)->nextPtr;\n    }\n\n    Tcl_Free(familyPtr);\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FindSubFontForChar --\n *\n *\tDetermine which screen font is necessary to use to display the given\n *\tcharacter. If the font object does not have a screen font that can\n *\tdisplay the character, another screen font may be loaded into the font\n *\tobject, following a set of preferred fallback rules.\n *\n *\tNote: For characters below BASE_CHARS, we now check the base font's\n *\tcoverage via FontMapLookup. If the base font cannot display the\n *\tcharacter, we continue to the fallback search. This ensures that even\n *\tbasic ASCII can be provided by a fallback font if the base font lacks\n *\tit.\n *\n * Results:\n *\tThe return value is the SubFont to use to display the given character.\n *\n * Side effects:\n *\tThe contents of fontPtr are modified to cache the results of the\n *\tlookup and remember any SubFonts that were dynamically loaded.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic SubFont *\nFindSubFontForChar(\n    WinFont *fontPtr,\t\t/* The font object with which the character\n\t\t\t\t * will be displayed. */\n    int ch,\t\t\t/* The Unicode character to be displayed. */\n    SubFont **subFontPtrPtr)\t/* Pointer to var to be fixed up if we\n\t\t\t\t * reallocate the subfont table. */\n{\n    HDC hdc;\n    int i, j, k;\n    CanUse canUse;\n    const char *const *aliases;\n    const char *const *anyFallbacks;\n    const char *const *const *fontFallbacks;\n    const char *fallbackName;\n    SubFont *subFontPtr;\n    Tcl_DString ds;\n\n    /* For characters >= FONTMAP_NUMCHARS, just use base font. */\n    if (ch >= FONTMAP_NUMCHARS) {\n\treturn &fontPtr->subFontArray[0];\n    }\n\n    /* For characters below BASE_CHARS, check if base font can display them. */\n    if (ch < BASE_CHARS) {\n\tif (FontMapLookup(&fontPtr->subFontArray[0], ch)) {\n\t    return &fontPtr->subFontArray[0];\n\t}\n\t/* Otherwise fall through to fallback search. */\n    }\n\n    /* First, see if any already-loaded subfont can display the character. */\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tif (FontMapLookup(&fontPtr->subFontArray[i], ch)) {\n\t    return &fontPtr->subFontArray[i];\n\t}\n    }\n\n    /*\n     * Keep track of all face names that we check, so we don't check some name\n     * multiple times if it can be reached by multiple paths.\n     */\n\n    Tcl_DStringInit(&ds);\n    hdc = GetDC(fontPtr->hwnd);\n\n    aliases = TkFontGetAliasList(fontPtr->font.fa.family);\n\n    fontFallbacks = TkFontGetFallbacks();\n    for (i = 0; fontFallbacks[i] != NULL; i++) {\n\tfor (j = 0; fontFallbacks[i][j] != NULL; j++) {\n\t    fallbackName = fontFallbacks[i][j];\n\t    if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) {\n\t\t/*\n\t\t * If the base font has a fallback...\n\t\t */\n\n\t\tgoto tryfallbacks;\n\t    } else if (aliases != NULL) {\n\t\t/*\n\t\t * Or if an alias for the base font has a fallback...\n\t\t */\n\n\t\tfor (k = 0; aliases[k] != NULL; k++) {\n\t\t    if (strcasecmp(aliases[k], fallbackName) == 0) {\n\t\t\tgoto tryfallbacks;\n\t\t    }\n\t\t}\n\t    }\n\t}\n\tcontinue;\n\n\t/*\n\t * ...then see if we can use one of the fallbacks, or an alias for one\n\t * of the fallbacks.\n\t */\n\n    tryfallbacks:\n\tfor (j = 0; fontFallbacks[i][j] != NULL; j++) {\n\t    fallbackName = fontFallbacks[i][j];\n\t    subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,\n\t\t    ch, &ds, subFontPtrPtr);\n\t    if (subFontPtr != NULL) {\n\t\tgoto end;\n\t    }\n\t}\n    }\n\n    /*\n     * See if we can use something from the global fallback list.\n     */\n\n    anyFallbacks = TkFontGetGlobalClass();\n    for (i = 0; anyFallbacks[i] != NULL; i++) {\n\tfallbackName = anyFallbacks[i];\n\tsubFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,\n\t\tch, &ds, subFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    goto end;\n\t}\n    }\n\n    /*\n     * Try all face names available in the whole system until we find one that\n     * can be used.\n     */\n\n    canUse.hdc = hdc;\n    canUse.fontPtr = fontPtr;\n    canUse.nameTriedPtr = &ds;\n    canUse.ch = ch;\n    canUse.subFontPtr = NULL;\n    canUse.subFontPtrPtr = subFontPtrPtr;\n    EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,\n\t    (LPARAM) &canUse);\n    subFontPtr = canUse.subFontPtr;\n\n  end:\n    Tcl_DStringFree(&ds);\n\n    if (subFontPtr == NULL) {\n\t/*\n\t * No font can display this character. We will use the base font and\n\t * have it display the \"unknown\" character.\n\t */\n\n\tsubFontPtr = &fontPtr->subFontArray[0];\n\tFontMapInsert(subFontPtr, ch);\n    }\n    ReleaseDC(fontPtr->hwnd, hdc);\n    return subFontPtr;\n}\n\nstatic int CALLBACK\nWinFontCanUseProc(\n    ENUMLOGFONTW *lfPtr,\t\t/* Logical-font data. */\n    TCL_UNUSED(NEWTEXTMETRIC *),\t/* Physical-font data (not used). */\n    TCL_UNUSED(int),\t\t/* Type of font (not used). */\n    LPARAM lParam)\t\t/* Result object to hold result. */\n{\n    int ch;\n    HDC hdc;\n    WinFont *fontPtr;\n    CanUse *canUsePtr;\n    char *fallbackName;\n    SubFont *subFontPtr;\n    Tcl_DString faceString;\n    Tcl_DString *nameTriedPtr;\n\n    canUsePtr\t    = (CanUse *) lParam;\n    ch\t\t    = canUsePtr->ch;\n    hdc\t\t    = canUsePtr->hdc;\n    fontPtr\t    = canUsePtr->fontPtr;\n    nameTriedPtr    = canUsePtr->nameTriedPtr;\n\n    fallbackName = (char *) lfPtr->elfLogFont.lfFaceName;\n    Tcl_DStringInit(&faceString);\n    Tcl_WCharToUtfDString((WCHAR *)fallbackName, wcslen((WCHAR *)fallbackName), &faceString);\n    fallbackName = Tcl_DStringValue(&faceString);\n\n    if (SeenName(fallbackName, nameTriedPtr) == 0) {\n\tsubFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch,\n\t\tcanUsePtr->subFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    canUsePtr->subFontPtr = subFontPtr;\n\t    Tcl_DStringFree(&faceString);\n\t    return 0;\n\t}\n    }\n    Tcl_DStringFree(&faceString);\n    return 1;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapLookup --\n *\n *\tSee if the screen font can display the given character.\n *\n * Results:\n *\tThe return value is 0 if the screen font cannot display the character,\n *\tnon-zero otherwise.\n *\n * Side effects:\n *\tNew pages are added to the font mapping cache whenever the character\n *\tbelongs to a page that hasn't been seen before. When a page is loaded,\n *\tinformation about all the characters on that page is stored, not just\n *\tfor the single character in question.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nFontMapLookup(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be queried\n\t\t\t\t * and possibly updated. */\n    int ch)\t\t\t/* Character to be tested. */\n{\n    int row, bitOffset;\n\n    if (ch < 0 || ch >= FONTMAP_NUMCHARS) {\n\treturn 0;\n    }\n\n    row = ch >> FONTMAP_SHIFT;\n    if (subFontPtr->fontMap[row] == NULL) {\n\tFontMapLoadPage(subFontPtr, row);\n    }\n    bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);\n    return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapInsert --\n *\n *\tTell the font mapping cache that the given screen font should be used\n *\tto display the specified character. This is called when no font on the\n *\tsystem can be be found that can display that character; we lie to the\n *\tfont and tell it that it can display the character, otherwise we would\n *\tend up re-searching the entire fallback hierarchy every time that\n *\tcharacter was seen.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNew pages are added to the font mapping cache whenever the character\n *\tbelongs to a page that hasn't been seen before. When a page is loaded,\n *\tinformation about all the characters on that page is stored, not just\n *\tfor the single character in question.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFontMapInsert(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be\n\t\t\t\t * updated. */\n    int ch)\t\t\t/* Character to be added to cache. */\n{\n    int row, bitOffset;\n\n    if (ch >= 0 && ch < FONTMAP_NUMCHARS) {\n\trow = ch >> FONTMAP_SHIFT;\n\tif (subFontPtr->fontMap[row] == NULL) {\n\t    FontMapLoadPage(subFontPtr, row);\n\t}\n\tbitOffset = ch & (FONTMAP_BITSPERPAGE - 1);\n\tsubFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);\n    }\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FontMapLoadPage --\n *\n *\tLoad information about all the characters on a given page. This\n *\tinformation consists of one bit per character that indicates whether\n *\tthe associated HFONT can (1) or cannot (0) display the characters on\n *\tthe page.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMemory allocated.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic void\nFontMapLoadPage(\n    SubFont *subFontPtr,\t/* Contains font mapping cache to be\n\t\t\t\t * updated. */\n    int row)\t\t\t/* Index of the page to be loaded into the\n\t\t\t\t * cache. */\n{\n    FontFamily *familyPtr;\n    Tcl_Encoding encoding;\n    int i, j, bitOffset, end, segCount;\n    USHORT *startCount, *endCount;\n    char buf[16], src[6];\n\n    subFontPtr->fontMap[row] = (char *)Tcl_Alloc(FONTMAP_BITSPERPAGE / 8);\n    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);\n\n    familyPtr = subFontPtr->familyPtr;\n    encoding = familyPtr->encoding;\n\n    if (familyPtr->encoding == TkWinGetUnicodeEncoding()) {\n\t/*\n\t * Font is Unicode. Few fonts are going to have all characters, so\n\t * examine the TrueType character existence metrics to determine what\n\t * characters actually exist in this font.\n\t */\n\n\tsegCount    = familyPtr->segCount;\n\tstartCount  = familyPtr->startCount;\n\tendCount    = familyPtr->endCount;\n\n\tj = 0;\n\tend = (row + 1) << FONTMAP_SHIFT;\n\tfor (i = row << FONTMAP_SHIFT; i < end; i++) {\n\t    for ( ; j < segCount; j++) {\n\t\tif (endCount[j] >= i) {\n\t\t    if (startCount[j] <= i) {\n\t\t\tbitOffset = i & (FONTMAP_BITSPERPAGE - 1);\n\t\t\tsubFontPtr->fontMap[row][bitOffset >> 3] |=\n\t\t\t\t1 << (bitOffset & 7);\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n    } else if (familyPtr->isSymbolFont) {\n\t/*\n\t * Assume that a symbol font with a known encoding has all the\n\t * characters that its encoding claims it supports.\n\t *\n\t * The test for \"encoding == unicodeEncoding\" must occur before this\n\t * case, to catch all symbol fonts (such as {Comic Sans MS} or\n\t * Wingdings) for which we don't have encoding information; those\n\t * symbol fonts are treated as if they were in the Unicode encoding\n\t * and their symbolic character existence metrics are treated as if\n\t * they were Unicode character existence metrics. This way, although\n\t * we don't know the proper Unicode -> symbol font mapping, we can\n\t * install the symbol font as the base font and access its glyphs.\n\t */\n\n\tend = (row + 1) << FONTMAP_SHIFT;\n\tfor (i = row << FONTMAP_SHIFT; i < end; i++) {\n\t    if (Tcl_UtfToExternal(NULL, encoding, src,\n\t\t    Tcl_UniCharToUtf(i, src), TCL_ENCODING_PROFILE_STRICT, NULL,\n\t\t    buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {\n\t\tcontinue;\n\t    }\n\t    bitOffset = i & (FONTMAP_BITSPERPAGE - 1);\n\t    subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);\n\t}\n    }\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * CanUseFallbackWithAliases --\n *\n *\tHelper function for FindSubFontForChar. Determine if the specified\n *\tface name (or an alias of the specified face name) can be used to\n *\tconstruct a screen font that can display the given character.\n *\n * Results:\n *\tSee CanUseFallback().\n *\n * Side effects:\n *\tIf the name and/or one of its aliases was rejected, the rejected\n *\tstring is recorded in nameTriedPtr so that it won't be tried again.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic SubFont *\nCanUseFallbackWithAliases(\n    HDC hdc,\t\t\t/* HDC in which font can be selected. */\n    WinFont *fontPtr,\t\t/* The font object that will own the new\n\t\t\t\t * screen font. */\n    const char *faceName,\t/* Desired face name for new screen font. */\n    int ch,\t\t\t/* The Unicode character that the new screen\n\t\t\t\t * font must be able to display. */\n    Tcl_DString *nameTriedPtr,\t/* Records face names that have already been\n\t\t\t\t * tried. It is possible for the same face\n\t\t\t\t * name to be queried multiple times when\n\t\t\t\t * trying to find a suitable screen font. */\n    SubFont **subFontPtrPtr)\t/* Variable to fixup if we reallocate the\n\t\t\t\t * array of subfonts. */\n{\n    int i;\n    const char *const *aliases;\n    SubFont *subFontPtr;\n\n    if (SeenName(faceName, nameTriedPtr) == 0) {\n\tsubFontPtr = CanUseFallback(hdc, fontPtr, faceName, ch, subFontPtrPtr);\n\tif (subFontPtr != NULL) {\n\t    return subFontPtr;\n\t}\n    }\n    aliases = TkFontGetAliasList(faceName);\n    if (aliases != NULL) {\n\tfor (i = 0; aliases[i] != NULL; i++) {\n\t    if (SeenName(aliases[i], nameTriedPtr) == 0) {\n\t\tsubFontPtr = CanUseFallback(hdc, fontPtr, aliases[i], ch,\n\t\t\tsubFontPtrPtr);\n\t\tif (subFontPtr != NULL) {\n\t\t    return subFontPtr;\n\t\t}\n\t    }\n\t}\n    }\n    return NULL;\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * SeenName --\n *\n *\tUsed to determine we have already tried and rejected the given face\n *\tname when looking for a screen font that can support some Unicode\n *\tcharacter.\n *\n * Results:\n *\tThe return value is 0 if this face name has not already been seen,\n *\tnon-zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic int\nSeenName(\n    const char *name,\t\t/* The name to check. */\n    Tcl_DString *dsPtr)\t\t/* Contains names that have already been\n\t\t\t\t * seen. */\n{\n    const char *seen, *end;\n\n    seen = Tcl_DStringValue(dsPtr);\n    end = seen + Tcl_DStringLength(dsPtr);\n    while (seen < end) {\n\tif (strcasecmp(seen, name) == 0) {\n\t    return 1;\n\t}\n\tseen += strlen(seen) + 1;\n    }\n    Tcl_DStringAppend(dsPtr, name, (int) (strlen(name) + 1));\n    return 0;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * CanUseFallback --\n *\n *\tIf the specified screen font has not already been loaded into the font\n *\tobject, determine if it can display the given character.\n *\n * Results:\n *\tThe return value is a pointer to a newly allocated SubFont, owned by\n *\tthe font object. This SubFont can be used to display the given\n *\tcharacter. The SubFont represents the screen font with the base set of\n *\tfont attributes from the font object, but using the specified font\n *\tname. NULL is returned if the font object already holds a reference to\n *\tthe specified physical font or if the specified physical font cannot\n *\tdisplay the given character.\n *\n * Side effects:\n *\tThe font object's subFontArray is updated to contain a reference to\n *\tthe newly allocated SubFont.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic SubFont *\nCanUseFallback(\n    HDC hdc,\t\t\t/* HDC in which font can be selected. */\n    WinFont *fontPtr,\t\t/* The font object that will own the new\n\t\t\t\t * screen font. */\n    const char *faceName,\t/* Desired face name for new screen font. */\n    int ch,\t\t\t/* The Unicode character that the new screen\n\t\t\t\t * font must be able to display. */\n    SubFont **subFontPtrPtr)\t/* Variable to fix-up if we realloc the array\n\t\t\t\t * of subfonts. */\n{\n    int i;\n    HFONT hFont;\n    SubFont subFont;\n\n    if (FamilyExists(hdc, faceName) == 0) {\n\treturn NULL;\n    }\n\n    /*\n     * Skip all fonts we've already used.\n     */\n\n    for (i = 0; i < fontPtr->numSubFonts; i++) {\n\tif (faceName == fontPtr->subFontArray[i].familyPtr->faceName) {\n\t    return NULL;\n\t}\n    }\n\n    /*\n     * Load this font and see if it has the desired character.\n     */\n\n    hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize,\n\t    0.0);\n    InitSubFont(hdc, hFont, 0, &subFont);\n    if (((ch < 256) && (subFont.familyPtr->isSymbolFont))\n\t    || (FontMapLookup(&subFont, ch) == 0)) {\n\t/*\n\t * Don't use a symbol font as a fallback font for characters below\n\t * 256.\n\t */\n\n\tReleaseSubFont(&subFont);\n\treturn NULL;\n    }\n\n    if (fontPtr->numSubFonts >= SUBFONT_SPACE) {\n\tSubFont *newPtr;\n\tSCRIPT_CACHE *newCachePtr;\n\tint newCount = fontPtr->numSubFonts + 1;\n\n\tnewPtr = (SubFont *)Tcl_Alloc(sizeof(SubFont) * newCount);\n\tmemcpy(newPtr, fontPtr->subFontArray,\n\t\tfontPtr->numSubFonts * sizeof(SubFont));\n\tif (fontPtr->subFontArray != fontPtr->staticSubFonts) {\n\t    Tcl_Free(fontPtr->subFontArray);\n\t}\n\n\tnewCachePtr = (SCRIPT_CACHE *)Tcl_Alloc(sizeof(SCRIPT_CACHE) * newCount);\n\tmemcpy(newCachePtr, fontPtr->scriptCacheArray,\n\t\tfontPtr->numSubFonts * sizeof(SCRIPT_CACHE));\n\tif (fontPtr->scriptCacheArray != fontPtr->staticScriptCaches) {\n\t    Tcl_Free(fontPtr->scriptCacheArray);\n\t}\n\t/* Zero the new slot so Uniscribe treats it as uninitialised. */\n\tmemset(&newCachePtr[fontPtr->numSubFonts], 0, sizeof(SCRIPT_CACHE));\n\n\t/*\n\t * Fix up the variable pointed to by subFontPtrPtr so it still points\n\t * into the live array. [Bug 618872]\n\t */\n\n\t*subFontPtrPtr = newPtr + (*subFontPtrPtr - fontPtr->subFontArray);\n\tfontPtr->subFontArray    = newPtr;\n\tfontPtr->scriptCacheArray = newCachePtr;\n    } else {\n\t/* Still within inline storage; zero the next cache slot. */\n\tmemset(&fontPtr->scriptCacheArray[fontPtr->numSubFonts], 0,\n\t\tsizeof(SCRIPT_CACHE));\n    }\n    fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;\n    fontPtr->numSubFonts++;\n    return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];\n}\n\n/*\n *---------------------------------------------------------------------------\n *\n * GetScreenFont --\n *\n *\tGiven the name and other attributes, construct an HFONT. This is where\n *\tall the alias and fallback substitution bottoms out.\n *\n * Results:\n *\tThe screen font that corresponds to the attributes.\n *\n * Side effects:\n *\tNone.\n *\n *---------------------------------------------------------------------------\n */\n\nstatic HFONT\nGetScreenFont(\n    const TkFontAttributes *faPtr,\n\t\t\t\t/* Desired font attributes for new HFONT. */\n    const char *faceName,\t/* Overrides font family specified in font\n\t\t\t\t * attributes. */\n    int pixelSize,\t\t/* Overrides size specified in font\n\t\t\t\t * attributes. */\n    double angle)\t\t/* What is the desired orientation of the\n\t\t\t\t * font. */\n{\n    HFONT hFont;\n    LOGFONTW lf;\n\n    memset(&lf, 0, sizeof(lf));\n    lf.lfHeight\t\t= -pixelSize;\n    lf.lfWidth\t\t= 0;\n    lf.lfEscapement\t= ROUND16(angle * 10);\n    lf.lfOrientation\t= ROUND16(angle * 10);\n    lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;\n    lf.lfItalic\t\t= (BYTE)faPtr->slant;\n    lf.lfUnderline\t= (BYTE)faPtr->underline;\n    lf.lfStrikeOut\t= (BYTE)faPtr->overstrike;\n    lf.lfCharSet\t= DEFAULT_CHARSET;\n    lf.lfOutPrecision\t= OUT_TT_PRECIS;\n    lf.lfClipPrecision\t= CLIP_DEFAULT_PRECIS;\n    lf.lfQuality\t= DEFAULT_QUALITY;\n    lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;\n\n    MultiByteToWideChar(CP_UTF8, 0, faceName, -1, lf.lfFaceName, LF_FACESIZE);\n    lf.lfFaceName[LF_FACESIZE-1] = 0;\n    hFont = CreateFontIndirectW(&lf);\n    return hFont;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * FamilyExists, FamilyOrAliasExists, WinFontExistsProc --\n *\n *\tDetermines if any physical screen font exists on the system with the\n *\tgiven family name. If the family exists, then it should be possible to\n *\tconstruct some physical screen font with that family name.\n *\n * Results:\n *\tThe return value is 0 if the specified font family does not exist,\n *\tnon-zero otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nFamilyExists(\n    HDC hdc,\t\t\t/* HDC in which font family will be used. */\n    const char *faceName)\t/* Font family to query. */\n{\n    int result;\n    Tcl_DString faceString;\n\n    Tcl_DStringInit(&faceString);\n    Tcl_UtfToWCharDString(faceName, TCL_INDEX_NONE, &faceString);\n\n    /*\n     * If the family exists, WinFontExistProc() will be called and\n     * EnumFontFamilies() will return whatever WinFontExistProc() returns. If\n     * the family doesn't exist, EnumFontFamilies() will just return a\n     * non-zero value.\n     */\n\n    result = EnumFontFamiliesW(hdc, (WCHAR *)Tcl_DStringValue(&faceString),\n\t    (FONTENUMPROCW) WinFontExistProc, 0);\n    Tcl_DStringFree(&faceString);\n    return (result == 0);\n}\n\nstatic const char *\nFamilyOrAliasExists(\n    HDC hdc,\n    const char *faceName)\n{\n    const char *const *aliases;\n    int i;\n\n    if (FamilyExists(hdc, faceName) != 0) {\n\treturn faceName;\n    }\n    aliases = TkFontGetAliasList(faceName);\n    if (aliases != NULL) {\n\tfor (i = 0; aliases[i] != NULL; i++) {\n\t    if (FamilyExists(hdc, aliases[i]) != 0) {\n\t\treturn aliases[i];\n\t    }\n\t}\n    }\n    return NULL;\n}\n\nstatic int CALLBACK\nWinFontExistProc(\n    TCL_UNUSED(ENUMLOGFONTW *),\t\t/* Logical-font data. */\n    TCL_UNUSED(NEWTEXTMETRIC *),\t/* Physical-font data (not used). */\n    TCL_UNUSED(int),\t\t/* Type of font (not used). */\n    TCL_UNUSED(LPARAM))\t\t/* EnumFontData to hold result. */\n{\n    return 0;\n}\n\n/*\n * The following data structures are used when querying a TrueType font file\n * to determine which characters the font supports.\n */\n\n#pragma pack(1)\t\t\t/* Structures are byte aligned in file. */\n\n#define CMAPHEX 0x636d6170\t/* Key for character map resource. */\n\ntypedef struct CMAPTABLE {\n    USHORT version;\t\t/* Table version number (0). */\n    USHORT numTables;\t\t/* Number of encoding tables following. */\n} CMAPTABLE;\n\ntypedef struct ENCODINGTABLE {\n    USHORT platform;\t\t/* Platform for which data is targeted. 3\n\t\t\t\t * means data is for Windows. */\n    USHORT encoding;\t\t/* How characters in font are encoded. 1 means\n\t\t\t\t * that the following subtable is keyed based\n\t\t\t\t * on Unicode. */\n    ULONG offset;\t\t/* Byte offset from beginning of CMAPTABLE to\n\t\t\t\t * the subtable for this encoding. */\n} ENCODINGTABLE;\n\ntypedef struct ANYTABLE {\n    USHORT format;\t\t/* Format number. */\n    USHORT length;\t\t/* The actual length in bytes of this\n\t\t\t\t * subtable. */\n    USHORT version;\t\t/* Version number (starts at 0). */\n} ANYTABLE;\n\ntypedef struct BYTETABLE {\n    USHORT format;\t\t/* Format number is set to 0. */\n    USHORT length;\t\t/* The actual length in bytes of this\n\t\t\t\t * subtable. */\n    USHORT version;\t\t/* Version number (starts at 0). */\n    BYTE glyphIdArray[256];\t/* Array that maps up to 256 single-byte char\n\t\t\t\t * codes to glyph indices. */\n} BYTETABLE;\n\ntypedef struct SUBHEADER {\n    USHORT firstCode;\t\t/* First valid low byte for subHeader. */\n    USHORT entryCount;\t\t/* Number valid low bytes for subHeader. */\n    SHORT idDelta;\t\t/* Constant adder to get base glyph index. */\n    USHORT idRangeOffset;\t/* Byte offset from here to appropriate\n\t\t\t\t * glyphIndexArray. */\n} SUBHEADER;\n\ntypedef struct HIBYTETABLE {\n    USHORT format;\t\t/* Format number is set to 2. */\n    USHORT length;\t\t/* The actual length in bytes of this\n\t\t\t\t * subtable. */\n    USHORT version;\t\t/* Version number (starts at 0). */\n    USHORT subHeaderKeys[256];\t/* Maps high bytes to subHeaders: value is\n\t\t\t\t * subHeader index * 8. */\n#if 0\n    SUBHEADER subHeaders[];\t/* Variable-length array of SUBHEADERs. */\n    USHORT glyphIndexArray[];\t/* Variable-length array containing subarrays\n\t\t\t\t * used for mapping the low byte of 2-byte\n\t\t\t\t * characters. */\n#endif\n} HIBYTETABLE;\n\ntypedef struct SEGMENTTABLE {\n    USHORT format;\t\t/* Format number is set to 4. */\n    USHORT length;\t\t/* The actual length in bytes of this\n\t\t\t\t * subtable. */\n    USHORT version;\t\t/* Version number (starts at 0). */\n    USHORT segCountX2;\t\t/* 2 x segCount. */\n    USHORT searchRange;\t\t/* 2 x (2**floor(log2(segCount))). */\n    USHORT entrySelector;\t/* log2(searchRange/2). */\n    USHORT rangeShift;\t\t/* 2 x segCount - searchRange. */\n#if 0\n    USHORT endCount[segCount]\t/* End characterCode for each segment. */\n    USHORT reservedPad;\t\t/* Set to 0. */\n    USHORT startCount[segCount];/* Start character code for each segment. */\n    USHORT idDelta[segCount];\t/* Delta for all character in segment. */\n    USHORT idRangeOffset[segCount]; /* Offsets into glyphIdArray or 0. */\n    USHORT glyphIdArray[]\t/* Glyph index array. */\n#endif\n} SEGMENTTABLE;\n\ntypedef struct TRIMMEDTABLE {\n    USHORT format;\t\t/* Format number is set to 6. */\n    USHORT length;\t\t/* The actual length in bytes of this\n\t\t\t\t * subtable. */\n    USHORT version;\t\t/* Version number (starts at 0). */\n    USHORT firstCode;\t\t/* First character code of subrange. */\n    USHORT entryCount;\t\t/* Number of character codes in subrange. */\n#if 0\n    USHORT glyphIdArray[];\t/* Array of glyph index values for\n\t\t\t\t * character codes in the range. */\n#endif\n} TRIMMEDTABLE;\n\ntypedef union SUBTABLE {\n    ANYTABLE any;\n    BYTETABLE byte;\n    HIBYTETABLE hiByte;\n    SEGMENTTABLE segment;\n    TRIMMEDTABLE trimmed;\n} SUBTABLE;\n\n#pragma pack()\n\n/*\n *-------------------------------------------------------------------------\n *\n * LoadFontRanges --\n *\n *\tGiven an HFONT, get the information about the characters that this\n *\tfont can display.\n *\n * Results:\n *\tIf the font has no Unicode character information, the return value is\n *\t0 and *startCountPtr and *endCountPtr are filled with NULL. Otherwise,\n *\t*startCountPtr and *endCountPtr are set to pointers to arrays of\n *\tTrueType character existence information and the return value is the\n *\tlength of the arrays (the two arrays are always the same length as\n *\teach other).\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic int\nLoadFontRanges(\n    HDC hdc,\t\t\t/* HDC into which font can be selected. */\n    HFONT hFont,\t\t/* HFONT to query. */\n    USHORT **startCountPtr,\t/* Filled with malloced pointer to character\n\t\t\t\t * range information. */\n    USHORT **endCountPtr,\t/* Filled with malloced pointer to character\n\t\t\t\t * range information. */\n    int *symbolPtr)\n {\n    int n, i, j, k, swapped, segCount;\n    size_t cbData, offset;\n    DWORD cmapKey;\n    USHORT *startCount, *endCount;\n    CMAPTABLE cmapTable;\n    ENCODINGTABLE encTable;\n    SUBTABLE subTable;\n    char *s;\n\n    segCount = 0;\n    startCount = NULL;\n    endCount = NULL;\n    *symbolPtr = 0;\n\n    hFont = (HFONT)SelectObject(hdc, hFont);\n\n    i = 0;\n    s = (char *) &i;\n    *s = '\\1';\n    swapped = 0;\n\n    if (i == 1) {\n\tswapped = 1;\n    }\n\n    cmapKey = CMAPHEX;\n    if (swapped) {\n\tSwapLong(&cmapKey);\n    }\n\n    n = GetFontData(hdc, cmapKey, 0, &cmapTable, sizeof(cmapTable));\n    if (n != (int) GDI_ERROR) {\n\tif (swapped) {\n\t    SwapShort(&cmapTable.numTables);\n\t}\n\tfor (i = 0; i < cmapTable.numTables; i++) {\n\t    offset = sizeof(cmapTable) + i * sizeof(encTable);\n\t    GetFontData(hdc, cmapKey, (DWORD) offset, &encTable,\n\t\t    sizeof(encTable));\n\t    if (swapped) {\n\t\tSwapShort(&encTable.platform);\n\t\tSwapShort(&encTable.encoding);\n\t\tSwapLong(&encTable.offset);\n\t    }\n\t    if (encTable.platform != 3) {\n\t\t/*\n\t\t * Not Microsoft encoding.\n\t\t */\n\n\t\tcontinue;\n\t    }\n\t    if (encTable.encoding == 0) {\n\t\t*symbolPtr = 1;\n\t    } else if (encTable.encoding != 1) {\n\t\tcontinue;\n\t    }\n\n\t    GetFontData(hdc, cmapKey, (DWORD) encTable.offset, &subTable,\n\t\t    sizeof(subTable));\n\t    if (swapped) {\n\t\tSwapShort(&subTable.any.format);\n\t    }\n\t    if (subTable.any.format == 4) {\n\t\tif (swapped) {\n\t\t    SwapShort(&subTable.segment.segCountX2);\n\t\t}\n\t\tsegCount = subTable.segment.segCountX2 / 2;\n\t\tcbData = segCount * sizeof(USHORT);\n\n\t\tstartCount = (USHORT *)Tcl_Alloc(cbData);\n\t\tendCount = (USHORT *)Tcl_Alloc(cbData);\n\n\t\toffset = encTable.offset + sizeof(subTable.segment);\n\t\tGetFontData(hdc, cmapKey, (DWORD) offset, endCount, (DWORD)cbData);\n\t\toffset += cbData + sizeof(USHORT);\n\t\tGetFontData(hdc, cmapKey, (DWORD) offset, startCount, (DWORD)cbData);\n\t\tif (swapped) {\n\t\t    for (j = 0; j < segCount; j++) {\n\t\t\tSwapShort(&endCount[j]);\n\t\t\tSwapShort(&startCount[j]);\n\t\t    }\n\t\t}\n\t\tif (*symbolPtr != 0) {\n\t\t    /*\n\t\t     * Empirically determined: When a symbol font is loaded,\n\t\t     * the character existence metrics obtained from the\n\t\t     * system are mildly wrong. If the real range of the\n\t\t     * symbol font is from 0020 to 00FE, then the metrics are\n\t\t     * reported as F020 to F0FE. When we load a symbol font,\n\t\t     * we must fix the character existence metrics.\n\t\t     *\n\t\t     * Symbol fonts should only use the symbol encoding for\n\t\t     * 8-bit characters [note Bug: 2406]\n\t\t     */\n\n\t\t    for (k = 0; k < segCount; k++) {\n\t\t\tif (((startCount[k] & 0xff00) == 0xf000)\n\t\t\t\t&& ((endCount[k] & 0xff00) == 0xf000)) {\n\t\t\t    startCount[k] &= 0xff;\n\t\t\t    endCount[k] &= 0xff;\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    } else if (GetTextCharset(hdc) == ANSI_CHARSET) {\n\t/*\n\t * Bitmap font. We should also support ranges for the other *_CHARSET\n\t * values.\n\t */\n\n\tsegCount = 1;\n\tcbData = segCount * sizeof(USHORT);\n\tstartCount = (USHORT *)Tcl_Alloc(cbData);\n\tendCount = (USHORT *)Tcl_Alloc(cbData);\n\tstartCount[0] = 0x0000;\n\tendCount[0] = 0x00ff;\n    }\n    SelectObject(hdc, hFont);\n\n    *startCountPtr = startCount;\n    *endCountPtr = endCount;\n    return segCount;\n}\n\n/*\n *-------------------------------------------------------------------------\n *\n * SwapShort, SwapLong --\n *\n *\tHelper functions to convert the data loaded from TrueType font files\n *\tto Intel byte ordering.\n *\n * Results:\n *\tBytes of input value are swapped and stored back in argument.\n *\n * Side effects:\n *\tNone.\n *\n *-------------------------------------------------------------------------\n */\n\nstatic inline void\nSwapShort(\n    PUSHORT p)\n{\n    *p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));\n}\n\nstatic inline void\nSwapLong(\n    PULONG p)\n{\n    ULONG temp;\n\n    temp = (LONG) ((BYTE) *p);\n    temp <<= 8;\n    *p >>=8;\n\n    temp += (LONG) ((BYTE) *p);\n    temp <<= 8;\n    *p >>=8;\n\n    temp += (LONG) ((BYTE) *p);\n    temp <<= 8;\n    *p >>=8;\n\n    temp += (LONG) ((BYTE) *p);\n    *p = temp;\n}\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinGDI.c",
    "content": "/*\n * tkWinGDI.c --\n *\n *      This module implements access to the Win32 GDI API.\n *\n * Copyright © 1991-2018 Microsoft Corp.\n * Copyright © 2009, Michael I. Schwartz\n * Copyright © 1998-2019 Harald Oehlmann, Elmicron GmbH\n * Copyright © 2021 Kevin Walzer\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n\n#include \"tkWinInt.h\"\n#include <wtypes.h>\n#include <winspool.h>\n#include <commdlg.h>\n#include <wingdi.h>\n\n#define DEG2RAD(x) (0.017453292519943295 * (x))\n#define ROUND32(x) ((LONG)floor((x) + 0.5))\n\n/*\n * Create a standard \"DrawFunc\" to make this more workable....\n */\n#ifdef _MSC_VER\ntypedef BOOL (WINAPI *DrawFunc) (\n\tHDC, int, int, int, int, int, int, int, int); /* Arc, Chord, Pie. */\n#else\ntypedef BOOL WINAPI (*DrawFunc) (\n\tHDC, int, int, int, int, int, int, int, int); /* Arc, Chord, Pie. */\n#endif\n\n/* Real functions. */\nstatic Tcl_ObjCmdProc2 GdiArc;\nstatic Tcl_ObjCmdProc2 GdiBitmap;\nstatic Tcl_ObjCmdProc2 GdiCharWidths;\nstatic Tcl_ObjCmdProc2 GdiImage;\nstatic Tcl_ObjCmdProc2 GdiPhoto;\nstatic Tcl_ObjCmdProc2 GdiLine;\nstatic Tcl_ObjCmdProc2 GdiOval;\nstatic Tcl_ObjCmdProc2 GdiPolygon;\nstatic Tcl_ObjCmdProc2 GdiRectangle;\nstatic Tcl_ObjCmdProc2 GdiText;\nstatic Tcl_ObjCmdProc2 GdiTextPlain;\nstatic Tcl_ObjCmdProc2 GdiMap;\nstatic Tcl_ObjCmdProc2 GdiCopyBits;\n\n/* Local copies of similar routines elsewhere in Tcl/Tk. */\nstatic int GdiGetColor(Tcl_Obj *nameObj, COLORREF *color);\n\n/*\n * Helper functions.\n */\nstatic int\t\tGdiMakeLogFont(Tcl_Interp *interp, Tcl_Obj *specPtr,\n\t\t\t    LOGFONTW *lf, HDC hDC);\nstatic int\t\tGdiMakePen(Tcl_Interp *interp, double dwidth,\n\t\t\t    int dashstyle, const char *dashstyledata,\n\t\t\t    int capstyle, int joinstyle,\n\t\t\t    int stipplestyle, const char *stippledata,\n\t\t\t    unsigned long color, HDC hDC, HGDIOBJ *oldPen);\nstatic int\t\tGdiFreePen(Tcl_Interp *interp, HDC hDC, HGDIOBJ oldPen);\nstatic int\t\tGdiMakeBrush(unsigned long color, long hatch,\n\t\t\t    LOGBRUSH *lb, HDC hDC, HBRUSH *oldBrush);\nstatic void\t\tGdiFreeBrush(Tcl_Interp *interp, HDC hDC,\n\t\t\t    HGDIOBJ oldBrush);\nstatic int\t\tGdiGetHdcInfo(HDC hdc,\n\t\t\t    LPPOINT worigin, LPSIZE wextent,\n\t\t\t    LPPOINT vorigin, LPSIZE vextent);\n\n/* Helper functions for printing the window client area. */\nenum PrintType { PTWindow = 0, PTClient = 1, PTScreen = 2 };\n\nstatic HANDLE\t\tCopyToDIB(HWND wnd, enum PrintType type);\nstatic HBITMAP\t\tCopyScreenToBitmap(LPRECT lpRect);\nstatic HANDLE\t\tBitmapToDIB(HBITMAP hb, HPALETTE hp);\nstatic HANDLE\t\tCopyScreenToDIB(LPRECT lpRect);\nstatic int\t\tDIBNumColors(LPBITMAPINFOHEADER lpDIB);\nstatic int\t\tPalEntriesOnDevice(HDC hDC);\nstatic HPALETTE\t\tGetSystemPalette(void);\nstatic void\t\tGetDisplaySize(LONG *width, LONG *height);\nstatic int\t\tGdiParseFontWords(Tcl_Interp *interp, LOGFONTW *lf,\n\t\t\t    Tcl_Obj *const *objv, Tcl_Size argc);\nstatic Tcl_ObjCmdProc2 PrintSelectPrinter;\nstatic Tcl_ObjCmdProc2 PrintOpenPrinter;\nstatic Tcl_ObjCmdProc2 PrintClosePrinter;\nstatic Tcl_ObjCmdProc2 PrintOpenDoc;\nstatic Tcl_ObjCmdProc2 PrintCloseDoc;\nstatic Tcl_ObjCmdProc2 PrintOpenPage;\nstatic Tcl_ObjCmdProc2 PrintClosePage;\n\n/*\n * Global state.\n */\n/*\nstatic DOCINFOW di;\nstatic HDC printDC;\nstatic Tcl_DString jobNameW;\n*/\n\ntypedef struct WinprintData {\n    DOCINFOW di;\n    HDC printDC;\n    Tcl_DString jobNameW;\n} WinprintData;\n\n/*\n * To make the \"subcommands\" follow a standard convention, add them to this\n * array. The first element is the subcommand name, and the second a standard\n * Tcl command handler.\n */\n\nstatic const struct gdi_command {\n    const char *command_string;\n    Tcl_ObjCmdProc2 *command;\n} gdi_commands[] = {\n    { \"arc\",        GdiArc },\n    { \"bitmap\",     GdiBitmap },\n    { \"characters\", GdiCharWidths },\n    { \"image\",      GdiImage },\n    { \"line\",       GdiLine },\n    { \"map\",        GdiMap },\n    { \"oval\",       GdiOval },\n    { \"photo\",      GdiPhoto },\n    { \"polygon\",    GdiPolygon },\n    { \"rectangle\",  GdiRectangle },\n    { \"text\",       GdiText },\n    { \"textplain\",  GdiTextPlain },\n    { \"copybits\",   GdiCopyBits },\n};\n\f\n/*\n * Helper functions for Tcl_ParseArgsObjv.\n * These are used in parsing \"-option value\" pairs in the different GDI\n * subcommands.\n */\n\n/*\n * This structure represents a canvas color, which can be any color\n * accepted by Tk_GetColor, or the empty string to mean\n * \"don't draw the element\"\n */\ntypedef struct CanvasColor {\n    COLORREF color; /* Color */\n    char isempty;   /* 1 if color is {}, 0 otherwise */\n} CanvasColor;\n\nstatic Tcl_Size ParseColor (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    CanvasColor *ccolor = (CanvasColor *)dstPtr;\n    const char *colorname;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp, \"option \\\"\", Tcl_GetString(objv[-1]),\n\t    \"\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (GdiGetColor(objv[0], &(ccolor->color))) {\n\tccolor->isempty = 0;\n\treturn 1;\n    }\n\n    colorname = Tcl_GetString(objv[0]);\n    if (colorname[0] == '\\0') {\n\tccolor->color = 0;\n\tccolor->isempty = 1;\n\treturn 1;\n    }\n\n    Tcl_AppendResult(interp, \"unknown color name \\\"\", colorname, \"\\\"\", (char *)NULL);\n    return -1;\n}\n\nstatic Tcl_Size ParseDash (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    const char *dashspec;\n    Tk_Dash dash;\n    int staticsize = (int) sizeof(char *);\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-dash\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    dashspec = Tcl_GetString(objv[0]);\n    /* Tk_GetDash might potentially call Tcl_Free() on dash.pattern.pt if\n     * dash.number is not initialized to 0\n     */\n    dash.number = 0;\n    if (Tk_GetDash(interp, dashspec, &dash) != TCL_OK) {\n\treturn -1;\n    }\n\n    if (dash.number == 0) {\n\t/* empty string; do nothing */\n\treturn 1;\n    }\n\n    /* free the possibly allocated space */\n    if (dash.number > staticsize || dash.number < -staticsize) {\n\tTcl_Free(dash.pattern.pt);\n    }\n\n    *(const char **)dstPtr = dashspec;\n    return 1;\n}\n\nstatic Tcl_Size ParseAnchor (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    Tk_Anchor anchor;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-anchor\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tk_GetAnchorFromObj(interp, objv[0], &anchor) != TCL_OK) {\n\treturn -1;\n    }\n    *(Tk_Anchor *)dstPtr = anchor;\n    return 1;\n}\n\nstatic Tcl_Size ParseFont (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    Tcl_Size fcount;\n    Tcl_Obj **fobjs;\n    const char *fstring;\n    int size;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-font\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    fstring = Tcl_GetString(objv[0]);\n    /* Accept font description in the same format as provided by\n     * Tk_FontGetDescription(), a list of\n     * family size ?normal|bold? ?roman|italic? ?underline? ?overstrike?\n     */\n    if (Tcl_ListObjGetElements(NULL, objv[0], &fcount, &fobjs) != TCL_OK\n\t    || (fcount < 2 || fcount > 6)) {\n\tTcl_AppendResult(interp, \"bad font description \\\"\", fstring,\n\t    \"\\\"\", (char *)NULL);\n\treturn -1;\n    }\n\n    /* canvas font size should be in pixels (negative)\n     * text font size should be in points (positive)\n     */\n    if (Tcl_GetIntFromObj(interp, fobjs[1], &size) != TCL_OK) {\n\tconst char *value = Tcl_GetString(fobjs[1]);\n\tTcl_AppendResult(interp, \"bad size \\\"\", value,\n\t    \"\\\"; should be an integer\", (char *)NULL);\n\treturn -1;\n    }\n\n    *(Tcl_Obj **)dstPtr = objv[0];\n    return 1;\n}\n\nstatic Tcl_Size ParseJoinStyle (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    int join;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-joinstyle\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tk_GetJoinStyle(interp, Tcl_GetString(objv[0]), &join) != TCL_OK) {\n\treturn -1;\n    }\n    switch (join) {\n\tcase JoinBevel:\n\t    *(int *)dstPtr = PS_JOIN_BEVEL;\n\t    break;\n\tcase JoinMiter:\n\t    *(int *)dstPtr = PS_JOIN_MITER;\n\t    break;\n\tcase JoinRound:\n\t    *(int *)dstPtr = PS_JOIN_ROUND;\n\t    break;\n    }\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Arc specific: parse \"-style\"\n *\n *----------------------------------------------------------------------\n */\nstatic Tcl_Size ParseStyle (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    DrawFunc *func = (DrawFunc *)dstPtr;\n    Tcl_Size index;\n\n    static struct FuncMap {\n\tconst char *name;\n\tDrawFunc gdifunc;\n    } funcmap[] = {\n\t{\"arc\",      Arc  },\n\t{\"chord\",    Chord},\n\t{\"pieslice\", Pie  },\n\t{NULL, NULL}\n    };\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-style\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[0], funcmap,\n\tsizeof(struct FuncMap), \"-style option\", 0, &index) != TCL_OK) {\n\treturn -1;\n    }\n    *func = funcmap[index].gdifunc;\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiArc --\n *\n *\tMap canvas arcs to GDI context.\n *\n * Results:\n *\tRenders arcs.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiArc(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    HDC hDC = dataPtr->printDC;\n    double x1, y1, x2, y2;\n    int xr0, yr0, xr1, yr1;\n\n     /* canvas arc item defaults */\n    double extent         = 90.0;\n    double start          = 0.0;\n    double width          = 1.0;\n    CanvasColor outline   = {0, 0};\n    CanvasColor fill      = {0, 1};\n    const char *dash      = NULL;\n    const char *stipple   = NULL;\n    const char *olstipple = NULL;\n    DrawFunc drawfunc     = Pie;\n\n    LOGBRUSH lbrush;\n    HGDIOBJ oldbrush = NULL, oldpen = NULL;\n\n    /* Verrrrrry simple for now.... */\n    if (objc < 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x1 y1 x2 y2 ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &x1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &y1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[4], &x2) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[5], &y2) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    objv += 6;\n    objc -= 6;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo arcArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-dash\",    ParseDash,  &dash,      NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-extent\",  NULL,       &extent,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",    ParseColor, &fill,      NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-outline\", ParseColor, &outline,   NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-outlinestipple\", NULL,&olstipple, NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-start\",   NULL,       &start,     NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\", NULL,       &stipple,   NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-style\",   ParseStyle, &drawfunc,  NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-width\",   NULL,       &width,     NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, arcArgvInfo, &argc, objv, NULL) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /* a simple check: if both -outline and -fill are empty, return */\n    if (outline.isempty && fill.isempty) {\n\treturn TCL_OK;\n    }\n\n    xr0 = xr1 = (x1 + x2) / 2;\n    yr0 = yr1 = (y1 + y2) / 2;\n\n    /*\n     * The angle used by the arc must be \"warped\" by the eccentricity of the\n     * ellipse.  Thanks to Nigel Dodd <nigel.dodd@avellino.com> for bringing a\n     * nice example.\n     */\n\n    xr0 += (int)(100.0 * (x2 - x1) * cos(DEG2RAD(start)));\n    yr0 -= (int)(100.0 * (y2 - y1) * sin(DEG2RAD(start)));\n    xr1 += (int)(100.0 * (x2 - x1) * cos(DEG2RAD(start+extent)));\n    yr1 -= (int)(100.0 * (y2 - y1) * sin(DEG2RAD(start+extent)));\n\n    /*\n     * Under Win95, SetArcDirection isn't implemented--so we have to assume\n     * that arcs are drawn counterclockwise (e.g., positive extent) So if it's\n     * negative, switch the coordinates!\n     */\n\n    if (extent < 0) {\n\tint xr2 = xr0;\n\tint yr2 = yr0;\n\n\txr0 = xr1;\n\txr1 = xr2;\n\tyr0 = yr1;\n\tyr1 = yr2;\n    }\n\n    if (fill.isempty) {\n\toldbrush = SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));\n    } else {\n\tGdiMakeBrush(fill.color, 0, &lbrush, hDC, (HBRUSH *)&oldbrush);\n    }\n\n    if (outline.isempty) {\n\toldpen = SelectObject(hDC, GetStockObject(NULL_PEN));\n    } else {\n\tGdiMakePen(interp, width, (dash != NULL), dash,\n\t    PS_ENDCAP_FLAT, PS_JOIN_BEVEL, 0, 0,\n\t    outline.color, hDC, &oldpen);\n    }\n\n    (*drawfunc)(hDC, x1, y1, x2, y2, xr0, yr0, xr1, yr1);\n\n    GdiFreePen(interp, hDC, oldpen);\n    GdiFreeBrush(interp, hDC, oldbrush);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiBitmap --\n *\n *\tUnimplemented for now. Should use the same techniques as\n *\tCanvasPsBitmap (tkCanvPs.c).\n *\n * Results:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiBitmap(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv)\n{\n    /*\n     * Skip this for now. Should be based on common code with the copybits\n     * command.\n     */\n\n    Tcl_WrongNumArgs(interp, 1, objv, \"hdc x y \"\n\t    \"-anchor [center|n|e|s|w] -background color \"\n\t    \"-bitmap bitmap -foreground color\\n\"\n\t    \"Not implemented yet. Sorry!\");\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiImage --\n *\n *\tUnimplemented for now. Unimplemented for now. Should switch on image\n *\ttype and call either GdiPhoto or GdiBitmap. This code is similar to\n *\tthat in tkWinImage.c.\n *\n * Results:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiImage(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    Tcl_Obj *const *objv)\n{\n    /* Skip this for now..... */\n    /* Should be based on common code with the copybits command. */\n\n    Tcl_WrongNumArgs(interp, 1, objv, \"hdc x y -anchor [center|n|e|s|w] -image name\\n\"\n\t    \"Not implemented yet. Sorry!\");\n    /* Normally, usage results in TCL_ERROR--but wait til' it's implemented. */\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiPhoto --\n *\n *\tContributed by Lukas Rosenthaler <lukas.rosenthaler@balcab.ch>\n *\n *\tNote: The canvas doesn't directly support photos (only as images), so\n *\tthis is the first ::tk::print::_gdi command without an equivalent\n *\tcanvas command.  This code may be modified to support photo images on\n *\tthe canvas.\n *\n * Results:\n *\tRenders a photo.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiPhoto(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n    int hDC_x = 0, hDC_y = 0, hDC_w = 0, hDC_h = 0;\n    int nx, ny, sll;\n    const char *photoname = NULL;\t/* For some reason Tk_FindPhoto takes a char *. */\n    Tk_PhotoHandle photo_handle;\n    Tk_PhotoImageBlock img_block;\n    BITMAPINFO bitmapinfo;\t/* Since we don't need the bmiColors table,\n\t\t\t\t * there is no need for dynamic allocation. */\n    int oldmode;\t\t/* For saving the old stretch mode. */\n    POINT pt;\t\t\t/* For saving the brush org. */\n    char *pbuf = NULL;\n    int i, k;\n    int retval = TCL_OK;\n    double x, y;\n    Tk_Anchor anchor = TK_ANCHOR_CENTER;\n\n    /*\n     * Parse the arguments.\n     */\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x y ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Next, check to see if 'hDC' can support BitBlt.\n     * If not, raise an error.\n     */\n\n    if ((GetDeviceCaps(hDC, RASTERCAPS) & RC_STRETCHDIB) == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"::tk::print::_gdi photo not supported on device context (0x%s)\",\n\t\tTcl_GetString(objv[1])));\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    hDC_x = ROUND32(x);\n    hDC_y = ROUND32(y);\n    objc -= 4;\n    objv += 4;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo photoArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-anchor\", ParseAnchor, &anchor,    NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-photo\",  NULL,        &photoname, NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, photoArgvInfo, &argc, objv, NULL)\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (! photoname) { /* No photo provided. */\n\tTcl_AppendResult(interp, \"no photo name provided\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    photo_handle = Tk_FindPhoto(interp, photoname);\n    if (! photo_handle) {\n\tTcl_AppendResult(interp, \"photo name \\\"\", photoname,\n\t    \"\\\" can't be located\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    Tk_PhotoGetImage(photo_handle, &img_block);\n\n    hDC_w = nx = img_block.width;\n    hDC_h = ny = img_block.height;\n    sll = ((3*nx + 3) / 4)*4; /* Must be multiple of 4. */\n\n    /*\n     * Buffer is potentially large enough that failure to allocate might be\n     * recoverable.\n     */\n\n    pbuf = (char *)Tcl_AttemptAlloc(sll * ny * sizeof(char));\n    if (! pbuf) { /* Memory allocation failure. */\n\tTcl_AppendResult(interp,\n\t\t\"::tk::print::_gdi photo failed--out of memory\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* After this, all returns must go through retval. */\n\n    /* BITMAP expects BGR; photo provides RGB. */\n    for (k = 0; k < ny; k++) {\n\tfor (i = 0; i < nx; i++) {\n\t    pbuf[k*sll + 3*i] = img_block.pixelPtr[\n\t\t    k*img_block.pitch + i*img_block.pixelSize + img_block.offset[2]];\n\t    pbuf[k*sll + 3*i + 1] = img_block.pixelPtr[\n\t\t    k*img_block.pitch + i*img_block.pixelSize + img_block.offset[1]];\n\t    pbuf[k*sll + 3*i + 2] = img_block.pixelPtr[\n\t\t    k*img_block.pitch + i*img_block.pixelSize + img_block.offset[0]];\n\t}\n    }\n\n    memset(&bitmapinfo, 0L, sizeof(BITMAPINFO));\n\n    bitmapinfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);\n    bitmapinfo.bmiHeader.biWidth         = nx;\n    bitmapinfo.bmiHeader.biHeight        = -ny;\n    bitmapinfo.bmiHeader.biPlanes        = 1;\n    bitmapinfo.bmiHeader.biBitCount      = 24;\n    bitmapinfo.bmiHeader.biCompression   = BI_RGB;\n    bitmapinfo.bmiHeader.biSizeImage     = 0; /* sll*ny;. */\n    bitmapinfo.bmiHeader.biXPelsPerMeter = 0;\n    bitmapinfo.bmiHeader.biYPelsPerMeter = 0;\n    bitmapinfo.bmiHeader.biClrUsed       = 0;\n    bitmapinfo.bmiHeader.biClrImportant  = 0;\n\n    oldmode = SetStretchBltMode(hDC, HALFTONE);\n    /*\n     * According to the Win32 Programmer's Manual, we have to set the brush\n     * org, now.\n     */\n    SetBrushOrgEx(hDC, 0, 0, &pt);\n\n    /* adjust coords based on the anchor point */\n    switch (anchor) {\n\tcase TK_ANCHOR_N:\n\t    hDC_x -= hDC_w/2;\n\t    break;\n\tcase TK_ANCHOR_NE:\n\t    hDC_x -= hDC_w;\n\t    break;\n\tcase TK_ANCHOR_W:\n\t    hDC_y -= hDC_h/2;\n\t    break;\n\tcase TK_ANCHOR_CENTER:\n\t    hDC_x -= hDC_w/2;\n\t    hDC_y -= hDC_h/2;\n\t    break;\n\tcase TK_ANCHOR_E:\n\t    hDC_x -= hDC_w;\n\t    hDC_y -= hDC_h/2;\n\t    break;\n\tcase TK_ANCHOR_SW:\n\t    hDC_y -= hDC_h;\n\t    break;\n\tcase TK_ANCHOR_S:\n\t    hDC_x -= hDC_w/2;\n\t    hDC_y -= hDC_h;\n\t    break;\n\tcase TK_ANCHOR_SE:\n\t    hDC_x -= hDC_w;\n\t    hDC_y -= hDC_h;\n\t    break;\n\tdefault:\n\t    /* nothing */\n\t    break;\n    }\n\n    if (StretchDIBits(hDC, hDC_x, hDC_y, hDC_w, hDC_h, 0, 0, nx, ny,\n\t    pbuf, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY) == (int)GDI_ERROR) {\n\tint errcode = GetLastError();\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"::tk::print::_gdi photo internal failure: \"\n\t\t\"StretchDIBits error code %d\", errcode));\n\tretval = TCL_ERROR;\n    }\n\n    /* Clean up the hDC. */\n    if (oldmode != 0) {\n\tSetStretchBltMode(hDC, oldmode);\n\tSetBrushOrgEx(hDC, pt.x, pt.y, &pt);\n    }\n\n    Tcl_Free(pbuf);\n\n    if (retval == TCL_OK) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"%d %d %d %d\", hDC_x, hDC_y, hDC_w, hDC_h));\n    }\n\n    return retval;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Smoothize --\n *\n *\tInterface to Tk's line smoother, used for lines and pollies.\n *\tProvided by Jasper Taylor <jasper.taylor@ed.ac.uk>.\n *\n * Results:\n *\tSmooths lines.\n *\n *----------------------------------------------------------------------\n */\n#define SMOOTH_NONE   0\n#define SMOOTH_BEZIER 1\n#define SMOOTH_RAW    2\nstatic int Smoothize(\n    POINT* polypoints,\n    int npoly,\n    int nStep,\n    int smooth, /* either SMOOTH_BEZIER or SMOOTH_RAW */\n    POINT** bpointptr)\n{\n    /* First, translate my points into a list of doubles. */\n    double *inPointList, *outPointList;\n    int n;\n    int nbpoints = 0;\n    POINT* bpoints;\n\n    inPointList = (double *)Tcl_AttemptAlloc(2 * sizeof(double) * npoly);\n    if (inPointList == 0) {\n\t/* TODO: unreachable */\n\treturn nbpoints; /* 0. */\n    }\n\n    for (n=0; n<npoly; n++) {\n\tinPointList[2*n] = polypoints[n].x;\n\tinPointList[2*n + 1] = polypoints[n].y;\n    }\n\n    nbpoints = 1 + npoly * nStep; /* this is the upper limit. */\n    outPointList = (double *)Tcl_AttemptAlloc(2 * sizeof(double) * nbpoints);\n    if (outPointList == 0) {\n\t/* TODO: unreachable */\n\tTcl_Free(inPointList);\n\treturn 0;\n    }\n\n    if (smooth == SMOOTH_BEZIER) {\n\tnbpoints = TkMakeBezierCurve(NULL, inPointList, npoly, nStep,\n\t\tNULL, outPointList);\n    } else {   /* SMOOTH_RAW */\n\tnbpoints = TkMakeRawCurve(NULL, inPointList, npoly, nStep,\n\t\tNULL, outPointList);\n    }\n\n    Tcl_Free(inPointList);\n    bpoints = (POINT *)Tcl_AttemptAlloc(sizeof(POINT)*nbpoints);\n    if (bpoints == 0) {\n\t/* TODO: unreachable */\n\tTcl_Free(outPointList);\n\treturn 0;\n    }\n\n    for (n=0; n<nbpoints; n++) {\n\tbpoints[n].x = (long)outPointList[2*n];\n\tbpoints[n].y = (long)outPointList[2*n + 1];\n    }\n    Tcl_Free(outPointList);\n    *bpointptr = bpoints;\n    return nbpoints;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Line specific: parse \"-arrow\"\n *\n *----------------------------------------------------------------------\n */\n#define ARROW_NONE  0\n#define ARROW_FIRST 1\n#define ARROW_LAST  2\nstatic Tcl_Size ParseArrow (\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    int index;\n\n    static struct ArrowMap {\n\tconst char *name;\n\tint arrow;\n    } arrowmap[] = {\n\t{\"none\",  ARROW_NONE},\n\t{\"first\", ARROW_FIRST},\n\t{\"last\",  ARROW_LAST},\n\t{\"both\",  (ARROW_FIRST | ARROW_LAST)},\n\t{NULL, 0},\n    };\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-arrow\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[0], arrowmap,\n\tsizeof(struct ArrowMap), \"-arrow option\", 0, &index) != TCL_OK) {\n\treturn -1;\n    }\n\n    *(int *)dstPtr = arrowmap[index].arrow;\n    return 1;\n}\n/*\n *----------------------------------------------------------------------\n *\n * Line specific: parse \"-arrowshape\"\n *\n *----------------------------------------------------------------------\n */\nstatic Tcl_Size ParseArrShp(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    int *arrowShape = (int *)dstPtr;\n    Tcl_Obj **shpObjs;\n    double a0, a1, a2;\n    Tcl_Size count;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-arrowshape\\\" requires an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n    if (Tcl_ListObjGetElements(interp, objv[0], &count, &shpObjs) != TCL_OK) {\n\treturn -1;\n    }\n    if (count != 3 ||\n\t    Tcl_GetDoubleFromObj(NULL, shpObjs[0], &a0) != TCL_OK ||\n\t    Tcl_GetDoubleFromObj(NULL, shpObjs[1], &a1) != TCL_OK ||\n\t    Tcl_GetDoubleFromObj(NULL, shpObjs[2], &a2) != TCL_OK) {\n\tTcl_AppendResult(interp, \"arrow shape should be a list \",\n\t    \"with three numbers\", (char *)NULL);\n\treturn -1;\n    }\n    arrowShape[0] = ROUND32(a0);\n    arrowShape[1] = ROUND32(a1);\n    arrowShape[2] = ROUND32(a2);\n    return 1;\n}\n/*\n *----------------------------------------------------------------------\n *\n * Line specific: parse \"-capstyle\"\n *\n *----------------------------------------------------------------------\n */\nstatic Tcl_Size ParseCapStyle (\n    TCL_UNUSED(void *), /* clientData */\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    int cap;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-capstyle\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tk_GetCapStyle(interp, Tcl_GetString(objv[0]), &cap) != TCL_OK) {\n\treturn -1;\n    }\n    switch (cap) {\n\tcase CapButt:\n\t    *(int *)dstPtr = PS_ENDCAP_FLAT;\n\t    break;\n\tcase CapProjecting:\n\t    *(int *)dstPtr = PS_ENDCAP_SQUARE;\n\t    break;\n\tcase CapRound:\n\t    *(int *)dstPtr = PS_ENDCAP_ROUND;\n\t    break;\n    }\n    return 1;\n}\n/*\n *----------------------------------------------------------------------\n *\n * Line specific: parse \"-smooth\"\n *\n *----------------------------------------------------------------------\n */\nstatic Tcl_Size ParseSmooth(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    bool boolValue;\n    Tcl_Size index;\n\n    static const struct SmoothMethod {\n\tconst char *name;\n\tint method;\n    } smoothmethods[] = {\n\t{\"bezier\", SMOOTH_BEZIER},\n\t{\"raw\",    SMOOTH_RAW},\n\t{NULL,     0}\n    };\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-smooth\\\" requires an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n    /* Argument is a boolean value, \"bezier\" or \"raw\". */\n    if (Tcl_GetBooleanFromObj(NULL, objv[0], &boolValue) == TCL_OK) {\n\t*(int *)dstPtr = boolValue;\n\treturn 1;\n    }\n\n    if (Tcl_GetIndexFromObjStruct(interp, objv[0], smoothmethods,\n\t    sizeof(struct SmoothMethod), \"smooth method\", 0, &index) != TCL_OK) {\n\tTcl_AppendResult(interp, \" or a boolean value\", (char *)NULL);\n\treturn -1;\n    }\n    *(int *)dstPtr = smoothmethods[index].method;\n    return 1;\n}\n/*\n *----------------------------------------------------------------------\n *\n * GdiLine --\n *\n *\tMaps lines to GDI context.\n *\n * Results:\n *\tRenders lines.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiLine(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n    double p1x, p1y, p2x, p2y;\n    POINT *polypoints;\n    int npoly;\n\n     /* canvas line item defaults */\n    double width      = 1.0;\n    CanvasColor fill  = {0, 0};\n    int smooth        = SMOOTH_NONE;\n    int arrow         = ARROW_NONE; /* 0=none; 1=end; 2=start; 3=both. */\n    int arrowshape[3] = {8, 10, 3};\n    int nStep         = 12;\n    const char *dash  = NULL;\n    int capstyle      = PS_ENDCAP_FLAT;\n    int joinstyle     = PS_JOIN_ROUND;\n    /* ignored for now */\n    const char *stipple = NULL;\n    const char *dashoffset = NULL;\n\n    LOGBRUSH lbrush;\n    HGDIOBJ oldpen = NULL, oldbrush = NULL;\n    double shapeA = 0, shapeB = 0, shapeC = 0, fracHeight = 0, backup = 0;\n\n    /* Verrrrrry simple for now.... */\n    if (objc < 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x1 y1... xn yn ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &p1x) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &p1y) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[4], &p2x) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[5], &p2y) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    polypoints = (POINT *)Tcl_AttemptAlloc((objc - 2)/2 * sizeof(POINT));\n    if (polypoints == NULL) {\n\tTcl_AppendResult(interp, \"Out of memory in GdiLine\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    polypoints[0].x = ROUND32(p1x);\n    polypoints[0].y = ROUND32(p1y);\n    polypoints[1].x = ROUND32(p2x);\n    polypoints[1].y = ROUND32(p2y);\n    objc -= 6;\n    objv += 6;\n    npoly = 2;\n\n    while (objc >= 2 &&\n\t    Tcl_GetDoubleFromObj(NULL, objv[0], &p1x) == TCL_OK &&\n\t    Tcl_GetDoubleFromObj(NULL, objv[1], &p1y) == TCL_OK) {\n\tpolypoints[npoly].x = ROUND32(p1x);\n\tpolypoints[npoly].y = ROUND32(p1y);\n\tnpoly++;\n\tobjc -= 2;\n\tobjv += 2;\n    }\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo lineArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-arrow\",      ParseArrow,    &arrow,     NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-arrowshape\", ParseArrShp,   arrowshape, NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-capstyle\",   ParseCapStyle, &capstyle,  NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-dash\",       ParseDash,     &dash,      NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-dashoffset\", NULL,          &dashoffset,NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",       ParseColor,    &fill,      NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-joinstyle\",  ParseJoinStyle,&joinstyle, NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-smooth\",     ParseSmooth,   &smooth,    NULL, NULL},\n\t    {TCL_ARGV_INT,     \"-splinesteps\",NULL,          &nStep,     NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\",    NULL,          &stipple,   NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-width\",      NULL,          &width,     NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, lineArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    Tcl_Free(polypoints);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (fill.isempty) {\n\tTcl_Free(polypoints);\n\treturn TCL_OK;\n    }\n    if (arrow != ARROW_NONE) {\n\t/* if -arrow is specified, capstyle is ignored */\n\tcapstyle = PS_ENDCAP_FLAT;\n    }\n\n    if (smooth != SMOOTH_NONE) { /* Use Smoothize. */\n\tint nspoints;\n\tPOINT *spoints;\n\n\tnspoints = Smoothize(polypoints, npoly, nStep, smooth, &spoints);\n\tif (nspoints > 0) {\n\t    /* replace the old point list with the new one */\n\t    Tcl_Free(polypoints);\n\t    polypoints = spoints;\n\t    npoly = nspoints;\n\t}\n    }\n\n    if (arrow != ARROW_NONE) {\n\tGdiMakeBrush(fill.color, 0, &lbrush, hDC, (HBRUSH *)&oldbrush);\n\tGdiMakePen(interp, 1, 0, 0, 0, PS_JOIN_MITER, 0, 0,\n\t    fill.color, hDC, &oldpen);\n\tshapeA = arrowshape[0] + 0.001;\n\tshapeB = arrowshape[1] + 0.001;\n\tshapeC = arrowshape[2] + width/2.0 + 0.001;\n\tfracHeight = (width/2.0)/shapeC;\n\tbackup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;\n    }\n\n    /* draw the arrowheads, if any. */\n    if (arrow & ARROW_LAST) {\n\t/* Arrowhead at end = polypoints[npoly-1].x, polypoints[npoly-1].y. */\n\tPOINT ahead[6];\n\tdouble dx, dy, length;\n\tdouble sinTheta, cosTheta;\n\tdouble vertX, vertY, temp;\n\n\tahead[0].x = ahead[5].x = polypoints[npoly-1].x;\n\tahead[0].y = ahead[5].y = polypoints[npoly-1].y;\n\tdx = ahead[0].x - polypoints[npoly-2].x;\n\tdy = ahead[0].y - polypoints[npoly-2].y;\n\tif ((length = hypot(dx, dy)) == 0) {\n\t    sinTheta = cosTheta = 0.0;\n\t} else {\n\t    sinTheta = dy / length;\n\t    cosTheta = dx / length;\n\t}\n\tvertX = ahead[0].x - shapeA*cosTheta;\n\tvertY = ahead[0].y - shapeC*sinTheta;\n\ttemp = shapeC*sinTheta;\n\tahead[1].x = ROUND32(ahead[0].x - shapeB*cosTheta + temp);\n\tahead[4].x = ROUND32(ahead[1].x - 2 * temp);\n\ttemp = shapeC*cosTheta;\n\tahead[1].y = ROUND32(ahead[0].y - shapeB*sinTheta - temp);\n\tahead[4].y = ROUND32(ahead[1].y + 2 * temp);\n\tahead[2].x = ROUND32(ahead[1].x*fracHeight + vertX*(1.0-fracHeight));\n\tahead[2].y = ROUND32(ahead[1].y*fracHeight + vertY*(1.0-fracHeight));\n\tahead[3].x = ROUND32(ahead[4].x*fracHeight + vertX*(1.0-fracHeight));\n\tahead[3].y = ROUND32(ahead[4].y*fracHeight + vertY*(1.0-fracHeight));\n\n\tPolygon(hDC, ahead, 6);\n\tpolypoints[npoly-1].x = ROUND32(ahead[0].x - backup*cosTheta);\n\tpolypoints[npoly-1].y = ROUND32(ahead[0].y - backup*sinTheta);\n    }\n\n    if (arrow & ARROW_FIRST) {\n\t/* Arrowhead at beginning = polypoints[0].x, polypoints[0].y. */\n\tPOINT ahead[6];\n\tdouble dx, dy, length;\n\tdouble sinTheta, cosTheta;\n\tdouble vertX, vertY, temp;\n\n\tahead[0].x = ahead[5].x = polypoints[0].x;\n\tahead[0].y = ahead[5].y = polypoints[0].y;\n\tdx = ahead[0].x - polypoints[1].x;\n\tdy = ahead[0].y - polypoints[1].y;\n\tif ((length = hypot(dx, dy)) == 0) {\n\t    sinTheta = cosTheta = 0.0;\n\t} else {\n\t    sinTheta = dy / length;\n\t    cosTheta = dx / length;\n\t}\n\tvertX = ahead[0].x - shapeA*cosTheta;\n\tvertY = ahead[0].y - shapeA*sinTheta;\n\ttemp = shapeC*sinTheta;\n\tahead[1].x = ROUND32(ahead[0].x - shapeB*cosTheta + temp);\n\tahead[4].x = ROUND32(ahead[1].x - 2 * temp);\n\ttemp = shapeC*cosTheta;\n\tahead[1].y = ROUND32(ahead[0].y - shapeB*sinTheta - temp);\n\tahead[4].y = ROUND32(ahead[1].y + 2 * temp);\n\tahead[2].x = ROUND32(ahead[1].x*fracHeight + vertX*(1.0-fracHeight));\n\tahead[2].y = ROUND32(ahead[1].y*fracHeight + vertY*(1.0-fracHeight));\n\tahead[3].x = ROUND32(ahead[4].x*fracHeight + vertX*(1.0-fracHeight));\n\tahead[3].y = ROUND32(ahead[4].y*fracHeight + vertY*(1.0-fracHeight));\n\n\tPolygon(hDC, ahead, 6);\n\tpolypoints[0].x = ROUND32(ahead[0].x - backup*cosTheta);\n\tpolypoints[0].y = ROUND32(ahead[0].y - backup*sinTheta);\n    }\n\n    /* free arrow's pen and brush (if any) */\n    if (arrow != ARROW_NONE) {\n\tGdiFreePen(interp, hDC, oldpen);\n\tGdiFreeBrush(interp, hDC, oldbrush);\n    }\n\n    /* draw the line */\n    GdiMakePen(interp, width, (dash != NULL), dash,\n\tcapstyle, joinstyle, 0, 0, fill.color, hDC, &oldpen);\n    Polyline(hDC, polypoints, npoly);\n    GdiFreePen(interp, hDC, oldpen);\n\n    Tcl_Free(polypoints);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiOval --\n *\n *\tMaps ovals to GDI context.\n *\n * Results:\n *\tRenders ovals.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiOval(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n\n     /* canvas oval item defaults */\n    double width = 1.0;\n    CanvasColor outline = {0, 0};\n    CanvasColor fill    = {0, 1};\n    const char *dash    = NULL;\n    const char *stipple = NULL;\n\n    LOGBRUSH lbrush;\n    HGDIOBJ oldpen = NULL, oldbrush = NULL;\n    double x1, y1, x2, y2;\n\n    /* Verrrrrry simple for now.... */\n    if (objc < 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x1 y1 x2 y2 ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &x1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &y1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[4], &x2) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[5], &y2) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (x1 > x2) {\n\tdouble x3 = x1;\n\tx1 = x2;\n\tx2 = x3;\n    }\n    if (y1 > y2) {\n\tdouble y3 = y1;\n\ty1 = y2;\n\ty2 = y3;\n    }\n    objc -= 6;\n    objv += 6;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo ovalArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-dash\",    ParseDash,  &dash,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",    ParseColor, &fill,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-outline\", ParseColor, &outline, NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\", NULL,       &stipple, NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-width\",   NULL,       &width,   NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, ovalArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (outline.isempty && fill.isempty) {\n\treturn TCL_OK;\n    }\n\n    if (fill.isempty) {\n\toldbrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));\n    } else {\n\tGdiMakeBrush(fill.color, 0, &lbrush, hDC, (HBRUSH *)&oldbrush);\n    }\n\n    if (outline.isempty) {\n\toldpen = SelectObject(hDC, GetStockObject(NULL_PEN));\n    } else {\n\tGdiMakePen(interp, width, (dash != NULL), dash,\n\t    0, 0, 0, 0, outline.color, hDC, &oldpen);\n    }\n    /*\n     * Per Win32, Ellipse includes lower and right edges--per Tcl8.3.2 and\n     * earlier documentation, canvas oval does not. Thus, add 1 to right\n     * and lower bounds to get appropriate behavior.\n     */\n    Ellipse(hDC, ROUND32(x1), ROUND32(y1), ROUND32(x2+1), ROUND32(y2+1));\n\n    GdiFreePen(interp, hDC, oldpen);\n    GdiFreeBrush(interp, hDC, oldbrush);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiPolygon --\n *\n *\tMaps polygons to GDI context.\n *\n * Results:\n *\tRenders polygons.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiPolygon(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n    POINT *polypoints;\n    int npoly;\n\n     /* canvas polygon item defaults */\n    double width        = 1.0;\n    CanvasColor outline = {0, 0};\n    CanvasColor fill    = {0, 1};\n    int joinstyle       = PS_JOIN_ROUND;\n    int smooth          = SMOOTH_NONE;\n    int nStep           = 12;\n    const char *dash    = NULL;\n    const char *stipple = NULL;\n\n    LOGBRUSH lbrush;\n    HGDIOBJ oldpen = NULL, oldbrush = NULL;\n    double p1x, p1y, p2x, p2y;\n\n    /* Verrrrrry simple for now.... */\n    if (objc < 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x1 y1 ... xn yn ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &p1x) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &p1y) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[4], &p2x) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[5], &p2y) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    polypoints = (POINT *)Tcl_AttemptAlloc((objc - 2)/2 * sizeof(POINT));\n    if (polypoints == NULL) {\n\t/* TODO: unreachable */\n\tTcl_AppendResult(interp, \"Out of memory in GdiPolygon\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    polypoints[0].x = ROUND32(p1x);\n    polypoints[0].y = ROUND32(p1y);\n    polypoints[1].x = ROUND32(p2x);\n    polypoints[1].y = ROUND32(p2y);\n    objc -= 6;\n    objv += 6;\n    npoly = 2;\n\n    while (objc >= 2 &&\n\t    Tcl_GetDoubleFromObj(NULL, objv[0], &p1x) == TCL_OK &&\n\t    Tcl_GetDoubleFromObj(NULL, objv[1], &p1y) == TCL_OK) {\n\tpolypoints[npoly].x = ROUND32(p1x);\n\tpolypoints[npoly].y = ROUND32(p1y);\n\tnpoly++;\n\tobjc -= 2;\n\tobjv += 2;\n    }\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo polyArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-dash\",       ParseDash,     &dash,      NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",       ParseColor,    &fill,      NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-joinstyle\",  ParseJoinStyle,&joinstyle, NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-outline\",    ParseColor,    &outline,   NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-smooth\",     ParseSmooth,   &smooth,    NULL, NULL},\n\t    {TCL_ARGV_INT,     \"-splinesteps\",NULL,          &nStep,     NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\",    NULL,          &stipple,   NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-width\",      NULL,          &width,     NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, polyArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    Tcl_Free(polypoints);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    if (outline.isempty && fill.isempty) {\n\treturn TCL_OK;\n    }\n\n    if (outline.isempty) {\n\toldpen = SelectObject(hDC, GetStockObject(NULL_PEN));\n    } else {\n\tGdiMakePen(interp, width, (dash != NULL), dash, 0, joinstyle, 0, 0,\n\t    outline.color, hDC, &oldpen);\n    }\n\n    if (fill.isempty) {\n\toldbrush = SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));\n    } else {\n\tGdiMakeBrush(fill.color, 0, &lbrush, hDC, (HBRUSH *)&oldbrush);\n    }\n\n    if (smooth) { /* Use Smoothize. */\n\tint nspoints;\n\tPOINT *spoints;\n\n\tnspoints = Smoothize(polypoints, npoly, nStep, smooth, &spoints);\n\tif (nspoints > 0) {\n\t    /* replace the old point list with the new one */\n\t    Tcl_Free(polypoints);\n\t    polypoints = spoints;\n\t    npoly = nspoints;\n\t}\n    }\n\n    Polygon(hDC, polypoints, npoly);\n\n    GdiFreePen(interp, hDC, oldpen);\n    GdiFreeBrush(interp, hDC, oldbrush);\n\n    Tcl_Free(polypoints);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiRectangle --\n *\n *\tMaps rectangles to GDI context.\n *\n * Results:\n *\tRenders rectangles.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiRectangle(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n\n     /* canvas rectangle item defaults */\n    double width = 1.0;\n    CanvasColor outline = {0, 0};\n    CanvasColor fill    = {0, 1};\n    const char *dash    = NULL;\n    const char *stipple = NULL;\n\n    LOGBRUSH lbrush;\n    HGDIOBJ oldpen = NULL, oldbrush = NULL;\n\n    double x1, y1, x2, y2;\n\n    /* Verrrrrry simple for now.... */\n    if (objc < 6) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x1 y1 x2 y2 ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &x1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &y1) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[4], &x2) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[5], &y2) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (x1 > x2) {\n\tdouble x3 = x1;\n\tx1 = x2;\n\tx2 = x3;\n    }\n    if (y1 > y2) {\n\tdouble y3 = y1;\n\ty1 = y2;\n\ty2 = y3;\n    }\n    objc -= 6;\n    objv += 6;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo rectArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-dash\",    ParseDash,  &dash,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",    ParseColor, &fill,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-outline\", ParseColor, &outline, NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\", NULL,       &stipple, NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-width\",   NULL,       &width,   NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, rectArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n    if (outline.isempty && fill.isempty) {\n\treturn TCL_OK;\n    }\n\n    if (fill.isempty) {\n\toldbrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));\n    } else {\n\tGdiMakeBrush(fill.color, 0, &lbrush, hDC, (HBRUSH *)&oldbrush);\n    }\n\n    if (outline.isempty) {\n\toldpen = SelectObject(hDC, GetStockObject(NULL_PEN));\n    } else {\n\tGdiMakePen(interp, width, (dash != NULL), dash,\n\t    0, PS_JOIN_MITER, 0, 0, outline.color, hDC, &oldpen);\n    }\n\n    /*\n     * Per Win32, Rectangle includes lower and right edges--per Tcl8.3.2 and\n     * earlier documentation, canvas rectangle does not. Thus, add 1 to\n     * right and lower bounds to get appropriate behavior.\n     */\n    Rectangle(hDC, ROUND32(x1), ROUND32(y1), ROUND32(x2+1), ROUND32(y2+1));\n\n    GdiFreePen(interp, hDC, oldpen);\n    GdiFreeBrush(interp, hDC, oldbrush);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiCharWidths --\n *\n *\tComputes /character widths. This is completely inadequate for\n *\ttypesetting, but should work for simple text manipulation.\n *\n * Results:\n *\tReturns character width.\n *\n *----------------------------------------------------------------------\n */\n\n\nstatic int GdiCharWidths(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    /*\n     * Returns widths of characters from font in an associative array.\n     * Font is currently selected font for HDC if not specified.\n     * Array name is GdiCharWidths if not specified.\n     * Widths should be in the same measures as all other values (1/1000 inch).\n     */\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n\n    const char *aryvarname = \"GdiCharWidths\";\n    Tcl_Obj *fontobj       = NULL;\n\n    LOGFONTW lf;\n    HFONT hfont;\n    HGDIOBJ oldfont = NULL;\n    /* For now, assume 256 characters in the font.... */\n    int widths[256];\n    int retval;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc ?opton value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    objc -= 2;\n    objv += 2;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo cwArgvInfo[] = {\n\t    {TCL_ARGV_STRING,  \"-array\", NULL,      &aryvarname, NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-font\",  ParseFont, &fontobj,    NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, cwArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /* is an error not providing a font */\n    if (! fontobj) {\n\tTcl_AppendResult(interp, \"error: font must be specified\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (GdiMakeLogFont(interp, fontobj, &lf, hDC)) {\n\tif ((hfont = CreateFontIndirectW(&lf)) != NULL) {\n\t    oldfont = SelectObject(hDC, hfont);\n\t}\n    } else {\n\treturn TCL_ERROR;\n    }\n\n    /* Now, get the widths using the correct function for font type. */\n    if ((retval = GetCharWidth32W(hDC, 0, 255, widths)) == FALSE) {\n\tretval = GetCharWidthW(hDC, 0, 255, widths);\n    }\n\n    /*\n     * Retval should be 1 (TRUE) if the function succeeded. If the function\n     * fails, get the \"extended\" error code and return. Be sure to deallocate\n     * the font if necessary.\n     */\n    if (retval == FALSE) {\n\tDWORD val = GetLastError();\n\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"::tk::print::_gdi character failed with code %ld\", val));\n\tif (oldfont) {\n\t    SelectObject(hDC, oldfont);\n\t    DeleteObject(hfont);\n\t}\n\treturn TCL_ERROR;\n    }\n\n    {\n\tunsigned char i;\n\tchar ind[2];\n\tind[1] = '\\0';\n\n\tfor (i = 0; i < 255; i++) {\n\t    /* TODO: use a bytearray for the index name so NUL works */\n\t    ind[0] = i;\n\t    Tcl_SetVar2Ex(interp, aryvarname, ind, Tcl_NewIntObj(widths[i]),\n\t\t    TCL_GLOBAL_ONLY);\n\t}\n    }\n    /* Now, remove the font if we created it only for this function. */\n    if (oldfont) {\n\tSelectObject(hDC, oldfont);\n\tDeleteObject(hfont);\n    }\n\n    /* The return value should be the array name(?). */\n    Tcl_AppendResult(interp, aryvarname, (char *)NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiText --\n *\n *\tMaps text to GDI context.\n *\n * Results:\n *\tRenders text.\n *\n *----------------------------------------------------------------------\n */\ntypedef struct LayoutChunk {\n    const char *start;\t\t/* Pointer to simple string to be displayed.\n\t\t * This is a pointer into the TkTextLayout's\n\t\t * string. */\n    Tcl_Size numBytes;\t\t/* The number of bytes in this chunk. */\n    Tcl_Size numChars;\t\t/* The number of characters in this chunk. */\n    Tcl_Size numDisplayChars;\t/* The number of characters to display when\n\t\t * this chunk is displayed. Can be less than\n\t\t * numChars if extra space characters were\n\t\t * absorbed by the end of the chunk. This will\n\t\t * be < 0 if this is a chunk that is holding a\n\t\t * tab or newline. */\n    int x, y;\t\t\t/* The origin of the first character in this\n\t\t * chunk with respect to the upper-left hand\n\t\t * corner of the TextLayout. */\n    int totalWidth;\t\t/* Width in pixels of this chunk. Used when\n\t\t * hit testing the invisible spaces at the end\n\t\t * of a chunk. */\n    int displayWidth;\t\t/* Width in pixels of the displayable\n\t\t * characters in this chunk. Can be less than\n\t\t * width if extra space characters were\n\t\t * absorbed by the end of the chunk. */\n} LayoutChunk;\n\ntypedef struct TextLayout {\n    Tk_Font tkfont;\t\t/* The font used when laying out the text. */\n    const char *string;\t\t/* The string that was layed out. */\n    int width;\t\t\t/* The maximum width of all lines in the text\n\t\t * layout. */\n    Tcl_Size numChunks;\t\t/* Number of chunks actually used in following\n\t\t * array. */\n    LayoutChunk chunks[TKFLEXARRAY];/* Array of chunks. The actual size will be\n\t\t * maxChunks. THIS FIELD MUST BE THE LAST IN\n\t\t * THE STRUCTURE. */\n} TextLayout;\n\n\nstatic Tcl_Size ParseJustify (\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv,\n    void *dstPtr)\n{\n    Tk_Justify justify;\n\n    if (objc == 0) {\n\tTcl_AppendResult(interp,\n\t    \"option \\\"-justify\\\" needs an additional argument\", (char *)NULL);\n\treturn -1;\n    }\n\n    if (Tk_GetJustifyFromObj(interp, objv[0], &justify) != TCL_OK) {\n\treturn -1;\n    }\n\n    *(Tk_Justify *)dstPtr = justify;\n    return 1;\n}\n\nstatic int GdiText(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n\n    double x0, y0;\n\n    Tk_Anchor anchor    = TK_ANCHOR_NW;\n    double angle        = 0.0;\n    CanvasColor fill    = {0, 0};\n    Tcl_Obj *fontobj    = NULL; /* -font shall be provided */\n    Tk_Justify justify  = TK_JUSTIFY_LEFT;\n    const char *string  = NULL;\n    int wraplen         = 0;\n    const char *stipple = NULL;\n\n    LOGFONTW lf;\n    HFONT hfont;\n    HGDIOBJ oldfont;\n    int made_font = 0;\n    COLORREF oldtextcolor = 0;\n    int bgmode;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x y ?option value ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /* Parse the command. */\n    if ((Tcl_GetDoubleFromObj(interp, objv[2], &x0) != TCL_OK)\n\t    || (Tcl_GetDoubleFromObj(interp, objv[3], &y0) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    objc -= 4;\n    objv += 4;\n\n    if (objc > 0) {\n\tTcl_Size argc = objc + 1;\n\tobjv--;\n\n\tconst Tcl_ArgvInfo textArgvInfo[] = {\n\t    {TCL_ARGV_GENFUNC, \"-anchor\",  ParseAnchor,  &anchor,  NULL, NULL},\n\t    {TCL_ARGV_FLOAT,   \"-angle\",   NULL,         &angle,   NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-fill\",    ParseColor,   &fill,    NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-font\",    ParseFont,    &fontobj, NULL, NULL},\n\t    {TCL_ARGV_GENFUNC, \"-justify\", ParseJustify, &justify, NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-stipple\", NULL,         &stipple, NULL, NULL},\n\t    {TCL_ARGV_STRING,  \"-text\",    NULL,         &string,  NULL, NULL},\n\t    {TCL_ARGV_INT,     \"-width\",   NULL,         &wraplen, NULL, NULL},\n\t    TCL_ARGV_TABLE_END\n\t};\n\n\tif (Tcl_ParseArgsObjv(interp, textArgvInfo, &argc, objv, NULL )\n\t\t!= TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /* if we have no text, nothing to do */\n    if (! string) {\n\treturn TCL_OK;\n    }\n    /* if we got empty color, nothing to do */\n    if (fill.isempty) {\n\treturn TCL_OK;\n    }\n    /* is an error not providing a font */\n    if (! fontobj) {\n\tTcl_AppendResult(interp, \"error: font must be specified\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (GdiMakeLogFont(interp, fontobj, &lf, hDC)) {\n\tlf.lfEscapement = lf.lfOrientation = 10.0 * angle;\n\tif ((hfont = CreateFontIndirectW(&lf)) != NULL) {\n\t    made_font = 1;\n\t    oldfont = SelectObject(hDC, hfont);\n\t}\n    }\n\n    oldtextcolor = SetTextColor(hDC, fill.color);\n    bgmode = SetBkMode(hDC, TRANSPARENT);\n\n    /* Recreate the text layout here, so we get the same width and\n     * line breaks.\n     */\n    Tk_Window tkwin = Tk_MainWindow(interp);\n    Tk_Font tkfont = Tk_AllocFontFromObj(interp, tkwin, fontobj);\n    if (!tkfont) {\n\treturn TCL_ERROR;\n    }\n    int width, height;\n    TextLayout *layout = (TextLayout *)Tk_ComputeTextLayout(tkfont,\n\tstring, TCL_INDEX_NONE, wraplen, justify, 0, &width, &height);\n\n    /* Calculate the anchor position in local coordinates\n     * Origin point is x0, y0\n     */\n    int xa = 0;\n    int ya = 0;\n    /* values for the default anchor nw */\n    switch (anchor) {\n\tcase TK_ANCHOR_NULL:\n\tcase TK_ANCHOR_NW:\n\t    xa = 0;\n\t    ya = 0;\n\t    break;\n\tcase TK_ANCHOR_N:\n\t    xa = -width / 2;\n\t    ya = 0;\n\t    break;\n\tcase TK_ANCHOR_NE:\n\t    xa = -width;\n\t    ya = 0;\n\t    break;\n\tcase TK_ANCHOR_W:\n\t    xa = 0;\n\t    ya = -height / 2;\n\t    break;\n\tcase TK_ANCHOR_CENTER:\n\t    xa = -width / 2;\n\t    ya = -height / 2;\n\t    break;\n\tcase TK_ANCHOR_E:\n\t    xa = -width;\n\t    ya = -height / 2;\n\t    break;\n\tcase TK_ANCHOR_SW:\n\t    xa = 0;\n\t    ya = -height;\n\t    break;\n\tcase TK_ANCHOR_S:\n\t    xa = -width / 2;\n\t    ya = -height;\n\t    break;\n\tcase TK_ANCHOR_SE:\n\t    xa = -width;\n\t    ya = -height;\n\t    break;\n    }\n    /* Set the align and adjust the x anchor point accordingly */\n    UINT align = TA_TOP;\n    switch (justify) {\n\tcase TK_JUSTIFY_NULL:\n\tcase TK_JUSTIFY_LEFT:\n\t    align |= TA_LEFT;\n\t    break;\n\tcase TK_JUSTIFY_CENTER:\n\t    align |= TA_CENTER;\n\t    xa += width / 2;\n\t    break;\n\tcase TK_JUSTIFY_RIGHT:\n\t    align |= TA_RIGHT;\n\t    xa += width;\n\t    break;\n    }\n    SetTextAlign(hDC, align);\n\n    Tk_FontMetrics fm;\n    Tk_GetFontMetrics(tkfont, &fm);\n    /* Our coordinate system has the y axis inverted.\n     * Invert the angle to get the values right.\n     */\n    const double sinA = sin(DEG2RAD(-angle));\n    const double cosA = cos(DEG2RAD(-angle));\n    /* now, print each text chunk adjusting the anchor point */\n    int retval = 1;\n    int nlseen = 0;\n    for (Tcl_Size i = 0; (i < layout->numChunks) && retval; i++) {\n\tWCHAR *wstring;\n\tTcl_DString ds;\n\tint xi, yi;\n\n\tif (layout->chunks[i].start[0] == '\\n') {\n\t    if (nlseen) {\n\t\tya += fm.linespace;\n\t    } else {\n\t\tnlseen = 1;\n\t    }\n\t    continue;\n\t}\n\txi = floor(x0 + (xa * cosA - ya * sinA) + 0.5);\n\tyi = floor(y0 + (xa * sinA + ya * cosA) + 0.5);\n\tTcl_DStringInit(&ds);\n\twstring = Tcl_UtfToWCharDString(layout->chunks[i].start,\n\t    layout->chunks[i].numBytes, &ds);\n\tretval = TextOutW(hDC, xi, yi, wstring, (int)Tcl_DStringLength(&ds)/2);\n\tTcl_DStringFree(&ds);\n\tya += fm.linespace;\n\tnlseen = 0;\n    }\n\n    /* All done. Cleanup */\n    Tk_FreeTextLayout((Tk_TextLayout) layout);\n    Tk_FreeFont(tkfont);\n\n    /* Get the color set back. */\n    SetTextColor(hDC, oldtextcolor);\n    SetBkMode(hDC, bgmode);\n\n    if (made_font) {\n\tSelectObject(hDC, oldfont);\n\tDeleteObject(hfont);\n    }\n    return TCL_OK;\n}\n\nstatic int GdiTextPlain(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n    int x0, y0, retval;\n    WCHAR *wstring;\n    const char *string;\n    Tcl_Size strlen;\n    Tcl_DString ds;\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hdc x y text\");\n\treturn TCL_ERROR;\n    }\n\n    if ((Tcl_GetIntFromObj(interp, objv[2], &x0) != TCL_OK)\n\t    || (Tcl_GetIntFromObj(interp, objv[3], &y0) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n\n    string = Tcl_GetStringFromObj(objv[4], &strlen);\n    Tcl_DStringInit(&ds);\n    wstring = Tcl_UtfToWCharDString(string, strlen, &ds);\n    retval = TextOutW(hDC, x0, y0, wstring, (int)Tcl_DStringLength(&ds)/2);\n    Tcl_DStringFree(&ds);\n    Tcl_SetObjResult(interp, Tcl_NewIntObj(retval));\n    return TCL_OK;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiGetHdcInfo --\n *\n *\tGets salient characteristics of the CTM.\n *\n * Results:\n *\tThe return value is 0 if any failure occurs--in which case none of the\n *\tother values are meaningful.  Otherwise the return value is the\n *\tcurrent mapping mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiGetHdcInfo(\n    HDC hdc,\n    LPPOINT worigin,\n    LPSIZE wextent,\n    LPPOINT vorigin,\n    LPSIZE vextent)\n{\n    int mapmode;\n    int retval;\n\n    memset(worigin, 0, sizeof(POINT));\n    memset(vorigin, 0, sizeof(POINT));\n    memset(wextent, 0, sizeof(SIZE));\n    memset(vextent, 0, sizeof(SIZE));\n\n    if ((mapmode = GetMapMode(hdc)) == 0) {\n\t/* Failed! */\n\tretval = 0;\n    } else {\n\tretval = mapmode;\n    }\n\n    if (GetWindowExtEx(hdc, wextent) == FALSE) {\n\t/* Failed! */\n\tretval = 0;\n    }\n    if (GetViewportExtEx(hdc, vextent) == FALSE) {\n\t/* Failed! */\n\tretval = 0;\n    }\n    if (GetWindowOrgEx(hdc, worigin) == FALSE) {\n\t/* Failed! */\n\tretval = 0;\n    }\n    if (GetViewportOrgEx(hdc, vorigin) == FALSE) {\n\t/* Failed! */\n\tretval = 0;\n    }\n\n    return retval;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiNameToMode --\n *\n *\tConverts Windows mapping mode names.\n *\n * Results:\n *\tMapping modes are delineated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiNameToMode(\n    const char *name)\n{\n    static const struct gdimodes {\n\tint mode;\n\tconst char *name;\n    } modes[] = {\n\t{ MM_ANISOTROPIC, \"MM_ANISOTROPIC\" },\n\t{ MM_HIENGLISH,   \"MM_HIENGLISH\" },\n\t{ MM_HIMETRIC,    \"MM_HIMETRIC\" },\n\t{ MM_ISOTROPIC,   \"MM_ISOTROPIC\" },\n\t{ MM_LOENGLISH,   \"MM_LOENGLISH\" },\n\t{ MM_LOMETRIC,    \"MM_LOMETRIC\" },\n\t{ MM_TEXT,        \"MM_TEXT\" },\n\t{ MM_TWIPS,       \"MM_TWIPS\" }\n    };\n\n    size_t i;\n    for (i=0; i < sizeof(modes) / sizeof(struct gdimodes); i++) {\n\tif (strcmp(modes[i].name, name) == 0) {\n\t    return modes[i].mode;\n\t}\n    }\n    return atoi(name);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiModeToName --\n *\n *\tConverts the mode number to a printable form.\n *\n * Results:\n *\tMapping numbers are delineated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic const char *GdiModeToName(\n    int mode)\n{\n    static const struct gdi_modes {\n\tint mode;\n\tconst char *name;\n    } modes[] = {\n\t{ MM_ANISOTROPIC, \"Anisotropic\" },\n\t{ MM_HIENGLISH,   \"1/1000 inch\" },\n\t{ MM_HIMETRIC,    \"1/100 mm\" },\n\t{ MM_ISOTROPIC,   \"Isotropic\" },\n\t{ MM_LOENGLISH,   \"1/100 inch\" },\n\t{ MM_LOMETRIC,    \"1/10 mm\" },\n\t{ MM_TEXT,        \"1 to 1\" },\n\t{ MM_TWIPS,       \"1/1440 inch\" }\n    };\n\n    size_t i;\n    for (i=0; i < sizeof(modes) / sizeof(struct gdi_modes); i++) {\n\tif (modes[i].mode == mode) {\n\t    return modes[i].name;\n\t}\n    }\n    return \"Unknown\";\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiMap --\n *\n *\tSets mapping mode between logical and physical device space.\n *\n * Results:\n *\tBridges map modes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiMap(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC hDC = dataPtr->printDC;\n\n    static const char usage_message[] =\n\t\"::tk::print::_gdi map hdc \"\n\t\"[-logical x[y]] [-physical x[y]] \"\n\t\"[-offset {x y} ] [-default] [-mode mode]\";\n    int mapmode;\t/* Mapping mode. */\n    SIZE wextent;\t/* Device extent. */\n    SIZE vextent;\t/* Viewport extent. */\n    POINT worigin;\t/* Device origin. */\n    POINT vorigin;\t/* Viewport origin. */\n    Tcl_Size argno;\n\n    /* Keep track of what parts of the function need to be executed. */\n    int need_usage   = 0;\n    int use_logical  = 0;\n    int use_physical = 0;\n    int use_offset   = 0;\n    int use_default  = 0;\n    int use_mode     = 0;\n\n    /* Required parameter: HDC for printer. */\n    if (objc < 2) {\n\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if ((mapmode = GdiGetHdcInfo(hDC, &worigin, &wextent, &vorigin, &vextent)) == 0) {\n\t/* Failed!. */\n\tTcl_AppendResult(interp, \"Cannot get current HDC info\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* Parse remaining arguments. */\n    for (argno = 2; argno < objc; argno++) {\n\tif (strcmp(Tcl_GetString(objv[argno]), \"-default\") == 0) {\n\t    vextent.cx = vextent.cy = wextent.cx = wextent.cy = 1;\n\t    vorigin.x = vorigin.y = worigin.x = worigin.y = 0;\n\t    mapmode = MM_TEXT;\n\t    use_default = 1;\n\t} else if (strcmp(Tcl_GetString(objv[argno]), \"-mode\") == 0) {\n\t    if (argno + 1 >= objc) {\n\t\tneed_usage = 1;\n\t    } else {\n\t\tmapmode = GdiNameToMode(Tcl_GetString(objv[argno + 1]));\n\t\tuse_mode = 1;\n\t\targno++;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[argno]), \"-offset\") == 0) {\n\t    if (argno + 1 >= objc) {\n\t\tneed_usage = 1;\n\t    } else {\n\t\t/* It would be nice if this parsed units as well.... */\n\t\tif (sscanf(Tcl_GetString(objv[argno + 1]), \"%ld%ld\",\n\t\t\t&vorigin.x, &vorigin.y) == 2) {\n\t\t    use_offset = 1;\n\t\t} else {\n\t\t    need_usage = 1;\n\t\t}\n\t\targno++;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[argno]), \"-logical\") == 0) {\n\t    if (argno + 1 >= objc) {\n\t\tneed_usage = 1;\n\t    } else {\n\t\tint count;\n\n\t\targno++;\n\t\t/* In \"real-life\", this should parse units as well.. */\n\t\tif ((count = sscanf(Tcl_GetString(objv[argno]), \"%ld%ld\",\n\t\t\t&wextent.cx, &wextent.cy)) != 2) {\n\t\t    if (count == 1) {\n\t\t\tmapmode = MM_ISOTROPIC;\n\t\t\tuse_logical = 1;\n\t\t\twextent.cy = wextent.cx;  /* Make them the same. */\n\t\t    } else {\n\t\t\tneed_usage = 1;\n\t\t    }\n\t\t} else {\n\t\t    mapmode = MM_ANISOTROPIC;\n\t\t    use_logical = 2;\n\t\t}\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[argno]), \"-physical\") == 0) {\n\t    if (argno + 1 >= objc) {\n\t\tneed_usage = 1;\n\t    } else {\n\t\tint count;\n\n\t\targno++;\n\t\t/* In \"real-life\", this should parse units as well.. */\n\t\tif ((count = sscanf(Tcl_GetString(objv[argno]), \"%ld%ld\",\n\t\t\t&vextent.cx, &vextent.cy)) != 2) {\n\t\t    if (count == 1) {\n\t\t\tmapmode = MM_ISOTROPIC;\n\t\t\tuse_physical = 1;\n\t\t\tvextent.cy = vextent.cx;  /* Make them the same. */\n\t\t    } else {\n\t\t\tneed_usage = 1;\n\t\t    }\n\t\t} else {\n\t\t    mapmode = MM_ANISOTROPIC;\n\t\t    use_physical = 2;\n\t\t}\n\t    }\n\t}\n    }\n\n    /* Check for any impossible combinations. */\n    if (use_logical != use_physical) {\n\tneed_usage = 1;\n    }\n    if (use_default && (use_logical || use_offset || use_mode)) {\n\tneed_usage = 1;\n    }\n    if (use_mode && use_logical &&\n\t    (mapmode != MM_ISOTROPIC && mapmode != MM_ANISOTROPIC)) {\n\tneed_usage = 1;\n    }\n\n    if (need_usage) {\n\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* Call Windows CTM functions. */\n    if (use_logical || use_default || use_mode) { /* Don't call for offset only. */\n\tSetMapMode(hDC, mapmode);\n    }\n\n    if (use_offset || use_default) {\n\tPOINT oldorg;\n\tSetViewportOrgEx(hDC, vorigin.x, vorigin.y, &oldorg);\n\tSetWindowOrgEx(hDC, worigin.x, worigin.y, &oldorg);\n    }\n\n    if (use_logical) {  /* Same as use_physical. */\n\tSIZE oldsiz;\n\tSetWindowExtEx(hDC, wextent.cx, wextent.cy, &oldsiz);\n\tSetViewportExtEx(hDC, vextent.cx, vextent.cy, &oldsiz);\n    }\n\n    /*\n     * Since we may not have set up every parameter, get them again for the\n     * report.\n     */\n    mapmode = GdiGetHdcInfo(hDC, &worigin, &wextent, &vorigin, &vextent);\n\n    /*\n     * Output current CTM info.\n     * Note: This should really be in terms that can be used in a\n     * ::tk::print::_gdi map command!\n     */\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"Transform: \\\"(%ld, %ld) -> (%ld, %ld)\\\" \"\n\t    \"Origin: \\\"(%ld, %ld)\\\" \"\n\t    \"MappingMode: \\\"%s\\\"\",\n\t    vextent.cx, vextent.cy, wextent.cx, wextent.cy,\n\t    vorigin.x, vorigin.y,\n\t    GdiModeToName(mapmode)));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiCopyBits --\n *\n *\tCopies window bits from source to destination.\n *\n * Results:\n *\tCopies window bits.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiCopyBits(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    HDC dst = dataPtr->printDC;\n    /* Goal: get the Tk_Window from the top-level\n     * convert it to an HWND\n     * get the HDC\n     * Do a bitblt to the given hdc\n     * Use an optional parameter to point to an arbitrary window instead of\n     * the main\n     * Use optional parameters to map to the width and height required for the\n     * dest.\n     */\n    static const char usage_message[] =\n\t\"::tk::print::_gdi copybits hdc [-window w|-screen] [-client] \"\n\t\"[-source \\\"a b c d\\\"] \"\n\t\"[-destination \\\"a b c d\\\"] [-scale number] [-calc]\";\n\n    Tk_Window mainWin;\n    Tk_Window workwin;\n    Window wnd;\n    HDC src;\n    HWND hwnd = 0;\n\n    HANDLE hDib;    /* Handle for device-independent bitmap. */\n    LPBITMAPINFOHEADER lpDIBHdr;\n    LPSTR lpBits;\n    enum PrintType wintype = PTWindow;\n\n    int hgt, wid;\n    char *strend;\n    long errcode;\n    Tcl_Size k;\n\n    /* Variables to remember what we saw in the arguments. */\n    int do_window = 0;\n    int do_screen = 0;\n    int do_scale = 0;\n    int do_print = 1;\n\n    /* Variables to remember the values in the arguments. */\n    const char *window_spec;\n    double scale = 1.0;\n    int src_x = 0, src_y = 0, src_w = 0, src_h = 0;\n    int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;\n    bool is_toplevel = false;\n\n    /*\n     * The following steps are peculiar to the top level window.\n     * There is likely a clever way to do the mapping of a widget pathname to\n     * the proper window, to support the idea of using a parameter for this\n     * purpose.\n     */\n    if ((workwin = mainWin = Tk_MainWindow(interp)) == 0) {\n\tTcl_AppendResult(interp, \"Can't find main Tk window\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse the arguments.\n     */\n    /* HDC is required. */\n    if (objc < 2) {\n\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Next, check to see if 'dst' can support BitBlt.  If not, raise an\n     * error.\n     */\n    if ((GetDeviceCaps(dst, RASTERCAPS) & RC_BITBLT) == 0) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"Can't do bitmap operations on device context\\n\"));\n\treturn TCL_ERROR;\n    }\n\n    /* Loop through the remaining arguments. */\n    for (k=2; k<objc; k++) {\n\tif (strcmp(Tcl_GetString(objv[k]), \"-window\") == 0) {\n\t    if (Tcl_GetString(objv[k+1]) && Tcl_GetString(objv[k+1])[0] == '.') {\n\t\tdo_window = 1;\n\t\tworkwin = Tk_NameToWindow(interp, window_spec = Tcl_GetString(objv[++k]), mainWin);\n\t\tif (workwin == NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"Can't find window %s in this application\",\n\t\t\t    window_spec));\n\t\t    return TCL_ERROR;\n\t\t}\n\t    } else {\n\t\t/* Use strtoul() so octal or hex representations will be\n\t\t * parsed. */\n\t\thwnd = (HWND) INT2PTR(strtoul(Tcl_GetString(objv[++k]), &strend, 0));\n\t\tif (strend == 0 || strend == Tcl_GetString(objv[k])) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"Can't understand window id %s\", Tcl_GetString(objv[k])));\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-screen\") == 0) {\n\t    do_screen = 1;\n\t    wintype = PTScreen;\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-client\") == 0) {\n\t    wintype = PTClient;\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-source\") == 0) {\n\t    float a, b, c, d;\n\t    int count = sscanf(Tcl_GetString(objv[++k]), \"%f%f%f%f\", &a, &b, &c, &d);\n\n\t    if (count < 2) { /* Can't make heads or tails of it.... */\n\t\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    src_x = (int)a;\n\t    src_y = (int)b;\n\t    if (count == 4) {\n\t\tsrc_w = (int)c;\n\t\tsrc_h = (int)d;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-destination\") == 0) {\n\t    float a, b, c, d;\n\t    int count;\n\n\t    count = sscanf(Tcl_GetString(objv[++k]), \"%f%f%f%f\", &a, &b, &c, &d);\n\t    if (count < 2) { /* Can't make heads or tails of it.... */\n\t\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    dst_x = (int)a;\n\t    dst_y = (int)b;\n\t    if (count == 3) {\n\t\tdst_w = (int)c;\n\t\tdst_h = -1;\n\t    } else if (count == 4) {\n\t\tdst_w = (int)c;\n\t\tdst_h = (int)d;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-scale\") == 0) {\n\t    if (Tcl_GetString(objv[++k])) {\n\t\tif (Tcl_GetDouble(interp, Tcl_GetString(objv[k]), &scale) != TCL_OK) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (scale <= 0.01 || scale >= 100.0) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"Unreasonable scale specification %s\", Tcl_GetString(objv[k])));\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tdo_scale = 1;\n\t    }\n\t} else if (strcmp(Tcl_GetString(objv[k]), \"-noprint\") == 0\n\t\t|| strncmp(Tcl_GetString(objv[k]), \"-calc\", 5) == 0) {\n\t    /* This option suggested by Pascal Bouvier to get sizes without\n\t     * printing. */\n\t    do_print = 0;\n\t}\n    }\n\n    /*\n     * Check to ensure no incompatible arguments were used.\n     */\n    if (do_window && do_screen) {\n\tTcl_AppendResult(interp, usage_message, (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Get the MS Window we want to copy.  Given the HDC, we can get the\n     * \"Window\".\n     */\n    if (hwnd == 0) {\n\tif (Tk_IsTopLevel(workwin)) {\n\t    is_toplevel = true;\n\t}\n\n\tif ((wnd = Tk_WindowId(workwin)) == 0) {\n\t    Tcl_AppendResult(interp, \"Can't get id for Tk window\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/* Given the \"Window\" we can get a Microsoft Windows HWND. */\n\n\tif ((hwnd = Tk_GetHWND(wnd)) == 0) {\n\t    Tcl_AppendResult(interp, \"Can't get Windows handle for Tk window\",\n\t\t    (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * If it's a toplevel, give it special treatment: Get the top-level\n\t * window instead.  If the user only wanted the client, the -client\n\t * flag will take care of it.  This uses \"windows\" tricks rather than\n\t * Tk since the obvious method of getting the wrapper window didn't\n\t * seem to work.\n\t */\n\tif (is_toplevel) {\n\t    HWND tmpWnd = hwnd;\n\t    while ((tmpWnd = GetParent(tmpWnd)) != 0) {\n\t\thwnd = tmpWnd;\n\t    }\n\t}\n    }\n\n    /* Given the HWND, we can get the window's device context. */\n    if ((src = GetWindowDC(hwnd)) == 0) {\n\tTcl_AppendResult(interp, \"Can't get device context for Tk window\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (do_screen) {\n\tLONG w, h;\n\tGetDisplaySize(&w, &h);\n\twid = w;\n\thgt = h;\n    } else if (is_toplevel) {\n\tRECT tl;\n\tGetWindowRect(hwnd, &tl);\n\twid = tl.right - tl.left;\n\thgt = tl.bottom - tl.top;\n    } else {\n\tif ((hgt = Tk_Height(workwin)) <= 0) {\n\t    Tcl_AppendResult(interp, \"Can't get height of Tk window\", (char *)NULL);\n\t    ReleaseDC(hwnd,src);\n\t    return TCL_ERROR;\n\t}\n\n\tif ((wid = Tk_Width(workwin)) <= 0) {\n\t    Tcl_AppendResult(interp, \"Can't get width of Tk window\", (char *)NULL);\n\t    ReleaseDC(hwnd,src);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * Ensure all the widths and heights are set up right\n     * A: No dimensions are negative\n     * B: No dimensions exceed the maximums\n     * C: The dimensions don't lead to a 0 width or height image.\n     */\n    if (src_x < 0) {\n\tsrc_x = 0;\n    }\n    if (src_y < 0) {\n\tsrc_y = 0;\n    }\n    if (dst_x < 0) {\n\tdst_x = 0;\n    }\n    if (dst_y < 0) {\n\tdst_y = 0;\n    }\n\n    if (src_w > wid || src_w <= 0) {\n\tsrc_w = wid;\n    }\n\n    if (src_h > hgt || src_h <= 0) {\n\tsrc_h = hgt;\n    }\n\n    if (do_scale && dst_w == 0) {\n\t/* Calculate destination width and height based on scale. */\n\tdst_w = (int)(scale * src_w);\n\tdst_h = (int)(scale * src_h);\n    }\n\n    if (dst_h == -1) {\n\tdst_h = (int) (((long)src_h * dst_w) / (src_w + 1)) + 1;\n    }\n\n    if (dst_h == 0 || dst_w == 0) {\n\tdst_h = src_h;\n\tdst_w = src_w;\n    }\n\n    if (do_print) {\n\t/*\n\t * Based on notes from Heiko Schock and Arndt Roger Schneider, create\n\t * this as a DIBitmap, to allow output to a greater range of devices.\n\t * This approach will also allow selection of\n\t *   a) Whole screen\n\t *   b) Whole window\n\t *   c) Client window only\n\t * for the \"grab\"\n\t */\n\thDib = CopyToDIB(hwnd, wintype);\n\n\t/* GdiFlush();. */\n\n\tif (!hDib) {\n\t    Tcl_AppendResult(interp, \"Can't create DIB\", (char *)NULL);\n\t    ReleaseDC(hwnd,src);\n\t    return TCL_ERROR;\n\t}\n\n\tlpDIBHdr = (LPBITMAPINFOHEADER) GlobalLock(hDib);\n\tif (!lpDIBHdr) {\n\t    Tcl_AppendResult(interp, \"Can't get DIB header\", (char *)NULL);\n\t    ReleaseDC(hwnd,src);\n\t    return TCL_ERROR;\n\t}\n\n\tlpBits = (LPSTR) lpDIBHdr + lpDIBHdr->biSize + DIBNumColors(lpDIBHdr) * sizeof(RGBQUAD);\n\n\t/* stretch the DIBbitmap directly in the target device. */\n\n\tif (StretchDIBits(dst,\n\t\tdst_x, dst_y, dst_w, dst_h,\n\t\tsrc_x, src_y, src_w, src_h,\n\t\tlpBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS,\n\t\tSRCCOPY) == (int)GDI_ERROR) {\n\t    errcode = GetLastError();\n\t    GlobalUnlock(hDib);\n\t    GlobalFree(hDib);\n\t    ReleaseDC(hwnd,src);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"StretchDIBits failed with code %ld\", errcode));\n\t    return TCL_ERROR;\n\t}\n\n\t/* free allocated memory. */\n\tGlobalUnlock(hDib);\n\tGlobalFree(hDib);\n    }\n\n    ReleaseDC(hwnd,src);\n\n    /*\n     * The return value should relate to the size in the destination space.\n     * At least the height should be returned (for page layout purposes).\n     */\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"%d %d %d %d\", dst_x, dst_y, dst_w, dst_h));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DIBNumColors --\n *\n *\tComputes the number of colors required for a DIB palette.\n *\n * Results:\n *\tReturns number of colors.\n\n *\n *----------------------------------------------------------------------\n */\n\nstatic int DIBNumColors(\n    LPBITMAPINFOHEADER lpDIB)\n{\n    WORD wBitCount;\t/* DIB bit count. */\n    DWORD dwClrUsed;\n\n    /*\n     * If this is a Windows-style DIB, the number of colors in the color table\n     * can be less than the number of bits per pixel allows for (i.e.\n     * lpbi->biClrUsed can be set to some value).  If this is the case, return\n     * the appropriate value..\n     */\n\n    dwClrUsed = lpDIB->biClrUsed;\n    if (dwClrUsed) {\n\treturn (WORD) dwClrUsed;\n    }\n\n    /*\n     * Calculate the number of colors in the color table based on.\n     * The number of bits per pixel for the DIB.\n     */\n\n    wBitCount = lpDIB->biBitCount;\n\n    /* Return number of colors based on bits per pixel. */\n\n    switch (wBitCount) {\n    case 1:\n\treturn 2;\n    case 4:\n\treturn 16;\n    case 8:\n\treturn 256;\n    default:\n\treturn 0;\n    }\n}\n\f\n/*\n * Helper functions\n */\n\n/*\n * ParseFontWords converts various keywords to modifyers of a\n * font specification.\n * For all words, later occurrences override earlier occurrences.\n * Overstrike and underline cannot be \"undone\" by other words\n */\n\n/*\n *----------------------------------------------------------------------\n *\n * GdiParseFontWords --\n *\n *\tConverts various keywords to modifiers of a font specification.  For\n *\tall words, later occurrences override earlier occurrences.  Overstrike\n *\tand underline cannot be \"undone\" by other words\n *\n * Results:\n *\t Keywords converted to modifiers.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiParseFontWords(\n    TCL_UNUSED(Tcl_Interp *),\n    LOGFONTW *lf,\n    Tcl_Obj *const *objv,\n    Tcl_Size argc)\n{\n    Tcl_Size i;\n    int retval = 0; /* Number of words that could not be parsed. */\n\n    enum fontStyles {\n\tSTY_BOLD, STY_ITALIC, STY_NORMAL, STY_OVERSTRIKE, STY_ROMAN,\n\tSTY_UNDERLINE\n    };\n    const char *const styleNames[] = {\n\t\"bold\", \"italic\", \"normal\", \"overstrike\", \"roman\", \"underline\", NULL\n    };\n    enum fontStyles sty;\n\n    for (i = 0; i < argc; i++) {\n\tif (Tcl_GetIndexFromObj(NULL, objv[i], styleNames, NULL, 0, &sty)\n\t\t!= TCL_OK) {\n\t    retval++;\n\t    continue;\n\t}\n\tswitch (sty) {\n\t    case STY_BOLD:\n\t\tlf->lfWeight = FW_BOLD;\n\t\tbreak;\n\t    case STY_ITALIC:\n\t\tlf->lfItalic = TRUE;\n\t\tbreak;\n\t    case STY_NORMAL:\n\t\tlf->lfWeight = FW_NORMAL;\n\t\tbreak;\n\t    case STY_OVERSTRIKE:\n\t\tlf->lfStrikeOut = TRUE;\n\t\tbreak;\n\t    case STY_ROMAN:\n\t\tlf->lfItalic = FALSE;\n\t\tbreak;\n\t    case STY_UNDERLINE:\n\t\tlf->lfUnderline = TRUE;\n\t}\n    }\n    return retval;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MakeLogFont --\n *\n *\tTakes the font description Tcl_Obj and converts this into a logical\n *\tfont spec.\n *      The expected font format is a list of {family size ?style ...?}\n *\n * Results:\n *\t Sets font weight.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiMakeLogFont(\n    Tcl_Interp *interp,\n    Tcl_Obj *specPtr,\n    LOGFONTW *lf,\n    HDC hDC)\n{\n    Tcl_Obj **listPtr;\n    Tcl_Size count;\n\n    /* Set up defaults for logical font. */\n    memset(lf, 0, sizeof(*lf));\n    lf->lfWeight  = FW_NORMAL;\n    lf->lfCharSet = DEFAULT_CHARSET;\n    lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\n    lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\n    lf->lfQuality = DEFAULT_QUALITY;\n    lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;\n\n    if (!specPtr ||\n\t    Tcl_ListObjGetElements(interp, specPtr, &count, &listPtr) != TCL_OK) {\n\treturn 0;\n    }\n\n    /* Now we have the font structure broken into name, size, weight. */\n    if (count >= 1) {\n\tTcl_DString ds;\n\tconst char *str = Tcl_GetString(listPtr[0]);\n\n\tTcl_DStringInit(&ds);\n\twcsncpy(lf->lfFaceName, Tcl_UtfToWCharDString(str, TCL_INDEX_NONE, &ds),\n\t\tLF_FACESIZE);\n\tlf->lfFaceName[LF_FACESIZE-1] = 0;\n\tTcl_DStringFree(&ds);\n    } else {\n\treturn 0;\n    }\n\n    if (count >= 2) {\n\tint siz;\n\n\t/*\n\t * Assumptions:\n\t * 1) Like canvas, if a positive number is specified, it's in points.\n\t * 2) Like canvas, if a negative number is specified, it's in pixels.\n\t */\n\tif (Tcl_GetIntFromObj(NULL, listPtr[1], &siz) == TCL_OK) { /* If it looks like a number, it is a number.... */\n\t    if (siz > 0) {  /* Size is in points. */\n\t\tSIZE wextent, vextent;\n\t\tPOINT worigin, vorigin;\n\t\tdouble factor;\n\n\t\tswitch (GdiGetHdcInfo(hDC, &worigin, &wextent, &vorigin, &vextent)) {\n\t\tcase MM_ISOTROPIC:\n\t\t    if (vextent.cy < -1 || vextent.cy > 1) {\n\t\t\tfactor = (double)wextent.cy / vextent.cy;\n\t\t\tif (factor < 0.0) {\n\t\t\t    factor = -factor;\n\t\t\t}\n\t\t\tlf->lfHeight = (int)(-siz * GetDeviceCaps(hDC, LOGPIXELSY) * factor / 72.0);\n\t\t    } else if (vextent.cx < -1 || vextent.cx > 1) {\n\t\t\tfactor = (double)wextent.cx / vextent.cx;\n\t\t\tif (factor < 0.0) {\n\t\t\t    factor = -factor;\n\t\t\t}\n\t\t\tlf->lfHeight = (int)(-siz * GetDeviceCaps(hDC, LOGPIXELSY) * factor / 72.0);\n\t\t    } else {\n\t\t\tlf->lfHeight = -siz; /* This is bad news.... */\n\t\t    }\n\t\t    break;\n\t\tcase MM_ANISOTROPIC:\n\t\t    if (vextent.cy != 0) {\n\t\t\tfactor = (double)wextent.cy / vextent.cy;\n\t\t\tif (factor < 0.0) {\n\t\t\t    factor = -factor;\n\t\t\t}\n\t\t\tlf->lfHeight = (int)(-siz * GetDeviceCaps(hDC, LOGPIXELSY) * factor / 72.0);\n\t\t    } else {\n\t\t\tlf->lfHeight = -siz; /* This is bad news.... */\n\t\t    }\n\t\t    break;\n\t\tcase MM_TEXT:\n\t\tdefault:\n\t\t    /* If mapping mode is MM_TEXT, use the documented\n\t\t     * formula. */\n\t\t    lf->lfHeight = -MulDiv(siz, GetDeviceCaps(hDC, LOGPIXELSY), 72);\n\t\t    break;\n\t\tcase MM_HIENGLISH:\n\t\t    lf->lfHeight = -MulDiv(siz, 1000, 72);\n\t\t    break;\n\t\tcase MM_LOENGLISH:\n\t\t    lf->lfHeight = -MulDiv(siz, 100, 72);\n\t\t    break;\n\t\tcase MM_HIMETRIC:\n\t\t    lf->lfHeight = -MulDiv(siz, (int)(1000*2.54), 72);\n\t\t    break;\n\t\tcase MM_LOMETRIC:\n\t\t    lf->lfHeight = -MulDiv(siz, (int)(100*2.54), 72);\n\t\t    break;\n\t\tcase MM_TWIPS:\n\t\t    lf->lfHeight = -MulDiv(siz, 1440, 72);\n\t\t    break;\n\t\t}\n\t    } else if (siz == 0) {   /* Use default size of 12 points. */\n\t\tlf->lfHeight = -MulDiv(12, GetDeviceCaps(hDC, LOGPIXELSY), 72);\n\t    } else {                 /* Use pixel size. */\n\t\tlf->lfHeight = siz;  /* Leave this negative. */\n\t    }\n\t} else {\n\t    /*  what, no size ?? */\n\t    GdiParseFontWords(interp, lf, listPtr+1, count-1);\n\t}\n    }\n\n    if (count >= 3) {\n\tGdiParseFontWords(interp, lf, listPtr+2, count-2);\n    }\n\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiMakePen --\n *\n *\tCreates a logical pen based on input parameters and selects it into\n *\tthe hDC.\n *\n * Results:\n *\tSets rendering pen.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiMakePen(\n    Tcl_Interp *interp,\n    double dwidth,\n    int dashstyle,\n    const char *dashstyledata,\n    int endStyle,\n    int joinStyle,\n    TCL_UNUSED(int),\n    TCL_UNUSED(const char *),\t/* Ignored for now. */\n    unsigned long color,\n    HDC hDC,\n    HGDIOBJ *oldPen)\n{\n    /*\n     * The LOGPEN structure takes the following dash options:\n     * PS_SOLID: a solid pen\n     * PS_DASH:  a dashed pen\n     * PS_DOT:   a dotted pen\n     * PS_DASHDOT: a pen with a dash followed by a dot\n     * PS_DASHDOTDOT: a pen with a dash followed by 2 dots\n     *\n     * It seems that converting to ExtCreatePen may be more advantageous, as\n     * it matches the Tk canvas pens much better--but not for Win95, which\n     * does not support PS_USERSTYLE. An explicit test (or storage in a static\n     * after first failure) may suffice for working around this. The\n     * ExtCreatePen is not supported at all under Win32.\n     */\n    int width = ROUND32(dwidth);\n    HPEN hPen;\n    LOGBRUSH lBrush;\n    DWORD pStyle = PS_SOLID;           /* -dash should override*/\n    DWORD styleCount = 0;\n    DWORD *styleArray = 0;\n\n    /*\n     * To limit the propagation of allocated memory, the dashes will have a\n     * maximum here.  If one wishes to remove the static allocation, please be\n     * sure to update GdiFreePen and ensure that the array is NOT freed if the\n     * LOGPEN option is used.\n     */\n    static DWORD pStyleData[24];\n    if (dashstyle != 0 && dashstyledata != 0) {\n\tconst char *cp;\n\tsize_t i;\n\tchar *dup = (char *)Tcl_Alloc(strlen(dashstyledata) + 1);\n\tstrcpy(dup, dashstyledata);\n\t/* DEBUG. */\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"DEBUG: Found a dash spec of |%s|\\n\",\n\t\tdashstyledata));\n\n\t/* Parse the dash spec. */\n\tif (isdigit(dashstyledata[0])) {\n\t    cp = strtok(dup, \" \\t,;\");\n\t    for (i = 0; cp && i < sizeof(pStyleData) / sizeof(DWORD); i++) {\n\t\tpStyleData[styleCount++] = atoi(cp);\n\t\tcp = strtok(NULL, \" \\t,;\");\n\t    }\n\t} else {\n\t    for (i=0; dashstyledata[i] != '\\0' && i< sizeof(pStyleData) / sizeof(DWORD); i++) {\n\t\tswitch (dashstyledata[i]) {\n\t\tcase ' ':\n\t\t    pStyleData[styleCount++] = 8;\n\t\t    break;\n\t\tcase ',':\n\t\t    pStyleData[styleCount++] = 4;\n\t\t    break;\n\t\tcase '_':\n\t\t    pStyleData[styleCount++] = 6;\n\t\t    break;\n\t\tcase '-':\n\t\t    pStyleData[styleCount++] = 4;\n\t\t    break;\n\t\tcase '.':\n\t\t    pStyleData[styleCount++] = 2;\n\t\t    break;\n\t\tdefault:\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (styleCount > 0) {\n\t    styleArray = pStyleData;\n\t} else {\n\t    dashstyle = 0;\n\t}\n\tif (dup) {\n\t    Tcl_Free(dup);\n\t}\n    }\n\n    if (dashstyle != 0) {\n\tpStyle = PS_USERSTYLE;\n    }\n\n    /* -stipple could affect this.... */\n    lBrush.lbStyle = BS_SOLID;\n    lBrush.lbColor = color;\n    lBrush.lbHatch = 0;\n\n    /* We only use geometric pens, even for 1-pixel drawing. */\n    hPen = ExtCreatePen(PS_GEOMETRIC|pStyle|endStyle|joinStyle,\n\t    width, &lBrush, styleCount, styleArray);\n\n    if (hPen == 0) { /* Failed for some reason...Fall back on CreatePenIndirect. */\n\tLOGPEN lf;\n\tlf.lopnWidth.x = width;\n\tlf.lopnWidth.y = 0;\t\t/* Unused in LOGPEN. */\n\tif (dashstyle == 0) {\n\t    lf.lopnStyle = PS_SOLID;\t/* For now...convert 'style' in the future. */\n\t} else {\n\t    lf.lopnStyle = PS_DASH;\t/* REALLLLY simple for now. */\n\t}\n\tlf.lopnColor = color;\t\t/* Assume we're getting a COLORREF. */\n\t/* Now we have a logical pen. Create the \"real\" pen and put it in the\n\t * hDC. */\n\thPen = CreatePenIndirect(&lf);\n    }\n\n    *oldPen = SelectObject(hDC, hPen);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiFreePen --\n *\n *\tWraps the protocol to delete a created pen.\n *\n * Results:\n *\tDeletes pen.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiFreePen(\n    TCL_UNUSED(Tcl_Interp *),\n    HDC hDC,\n    HGDIOBJ oldPen)\n{\n    HGDIOBJ gonePen = SelectObject(hDC, oldPen);\n\n    DeleteObject(gonePen);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiMakeBrush--\n *\n *\tCreates a logical brush based on input parameters, and selects it into\n *\tthe hdc.\n *\n * Results:\n *\t Creates brush.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiMakeBrush(\n    unsigned long color,\n    long hatch,\n    LOGBRUSH *lb,\n    HDC hDC,\n    HBRUSH *oldBrush)\n{\n    HBRUSH hBrush;\n    lb->lbStyle = BS_SOLID; /* Support other styles later. */\n    lb->lbColor = color;    /* Assume this is a COLORREF. */\n    lb->lbHatch = hatch;    /* Ignored for now, given BS_SOLID in the Style. */\n\n    /* Now we have the logical brush. Create the \"real\" brush and put it in\n     * the hDC. */\n    hBrush = CreateBrushIndirect(lb);\n    *oldBrush = (HBRUSH)SelectObject(hDC, hBrush);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiFreeBrush --\n *\n *\tWraps the protocol to delete a created brush.\n *\n * Results:\n *\t Deletes brush.\n *\n *----------------------------------------------------------------------\n */\nstatic void GdiFreeBrush(\n    TCL_UNUSED(Tcl_Interp *),\n    HDC hDC,\n    HGDIOBJ oldBrush)\n{\n    HGDIOBJ goneBrush;\n\n    goneBrush = SelectObject(hDC, oldBrush);\n    DeleteObject(goneBrush);\n}\n\f\n/*\n * Utility functions from elsewhere in Tcl.\n * Functions have removed reliance on X and Tk libraries, as well as removing\n * the need for TkWindows.\n * GdiGetColor is a copy of a TkpGetColor from tkWinColor.c\n */\ntypedef struct {\n    const char *name;\n    int index;\n} SystemColorEntry;\n\nstatic const SystemColorEntry sysColors[] = {\n    {\"3dDarkShadow\",\t\tCOLOR_3DDKSHADOW},\n    {\"3dLight\",\t\t\tCOLOR_3DLIGHT},\n    {\"ActiveBorder\",\t\tCOLOR_ACTIVEBORDER},\n    {\"ActiveCaption\",\t\tCOLOR_ACTIVECAPTION},\n    {\"AppWorkspace\",\t\tCOLOR_APPWORKSPACE},\n    {\"Background\",\t\tCOLOR_BACKGROUND},\n    {\"ButtonFace\",\t\tCOLOR_BTNFACE},\n    {\"ButtonHighlight\",\t\tCOLOR_BTNHIGHLIGHT},\n    {\"ButtonShadow\",\t\tCOLOR_BTNSHADOW},\n    {\"ButtonText\",\t\tCOLOR_BTNTEXT},\n    {\"CaptionText\",\t\tCOLOR_CAPTIONTEXT},\n    {\"DisabledText\",\t\tCOLOR_GRAYTEXT},\n    {\"GrayText\",\t\tCOLOR_GRAYTEXT},\n    {\"Highlight\",\t\tCOLOR_HIGHLIGHT},\n    {\"HighlightText\",\t\tCOLOR_HIGHLIGHTTEXT},\n    {\"InactiveBorder\",\t\tCOLOR_INACTIVEBORDER},\n    {\"InactiveCaption\",\t\tCOLOR_INACTIVECAPTION},\n    {\"InactiveCaptionText\",\tCOLOR_INACTIVECAPTIONTEXT},\n    {\"InfoBackground\",\t\tCOLOR_INFOBK},\n    {\"InfoText\",\t\tCOLOR_INFOTEXT},\n    {\"Menu\",\t\t\tCOLOR_MENU},\n    {\"MenuText\",\t\tCOLOR_MENUTEXT},\n    {\"Scrollbar\",\t\tCOLOR_SCROLLBAR},\n    {\"Window\",\t\t\tCOLOR_WINDOW},\n    {\"WindowFrame\",\t\tCOLOR_WINDOWFRAME},\n    {\"WindowText\",\t\tCOLOR_WINDOWTEXT}\n};\n\nstatic const size_t numsyscolors = sizeof(sysColors) / sizeof(SystemColorEntry);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GdiGetColor --\n *\n *\tConvert color name to color specification.\n *\n * Results:\n *\t Color name converted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int GdiGetColor(\n    Tcl_Obj *nameObj,\n    COLORREF *color)\n{\n    const char *name = Tcl_GetString(nameObj);\n\n    if (_strnicmp(name, \"system\", 6) == 0) {\n\tsize_t i, l, u;\n\tint r;\n\n\tl = 0;\n\tu = numsyscolors;\n\twhile (l <= u) {\n\t    i = (l + u) / 2;\n\t    if ((r = _strcmpi(name+6, sysColors[i].name)) == 0) {\n\t\tbreak;\n\t    }\n\t    if (r < 0) {\n\t\tu = i - 1;\n\t    } else {\n\t\tl = i + 1;\n\t    }\n\t}\n\tif (l > u) {\n\t    return 0;\n\t}\n\t*color = GetSysColor(sysColors[i].index);\n\treturn 1;\n    } else {\n    int result;\n    XColor xcolor;\n\tresult = XParseColor(NULL, 0, name, &xcolor);\n\t*color = ((xcolor.red & 0xFF00)>>8) | (xcolor.green & 0xFF00)\n\t\t| ((xcolor.blue & 0xFF00)<<8);\n    return result;\n    }\n}\n\f\n/*\n * Beginning of functions for screen-to-dib translations.\n *\n * Several of these functions are based on those in the WINCAP32 program\n * provided as a sample by Microsoft on the VC++ 5.0 disk. The copyright on\n * these functions is retained, even for those with significant changes.\n */\n\n/*\n *----------------------------------------------------------------------\n *\n * CopyToDIB --\n *\n *\tCopy window bits to a DIB.\n *\n * Results:\n *\t Color specification converted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HANDLE CopyToDIB(\n    HWND hWnd,\n    enum PrintType type)\n{\n    HANDLE hDIB;\n    HBITMAP hBitmap;\n    HPALETTE hPalette;\n\n    /* Check for a valid window handle. */\n\n    if (!hWnd) {\n\treturn NULL;\n    }\n\n    switch (type) {\n    case PTWindow: {\t/* Copy entire window. */\n\tRECT rectWnd;\n\n\t/* Get the window rectangle. */\n\n\tGetWindowRect(hWnd, &rectWnd);\n\n\t/*\n\t * Get the DIB of the window by calling CopyScreenToDIB and passing it\n\t * the window rect.\n\t */\n\n\thDIB = CopyScreenToDIB(&rectWnd);\n\tbreak;\n    }\n\n    case PTClient: {\t/* Copy client area. */\n\tRECT rectClient;\n\tPOINT pt1, pt2;\n\n\t/* Get the client area dimensions. */\n\n\tGetClientRect(hWnd, &rectClient);\n\n\t/* Convert client coords to screen coords. */\n\n\tpt1.x = rectClient.left;\n\tpt1.y = rectClient.top;\n\tpt2.x = rectClient.right;\n\tpt2.y = rectClient.bottom;\n\tClientToScreen(hWnd, &pt1);\n\tClientToScreen(hWnd, &pt2);\n\trectClient.left = pt1.x;\n\trectClient.top = pt1.y;\n\trectClient.right = pt2.x;\n\trectClient.bottom = pt2.y;\n\n\t/*\n\t * Get the DIB of the client area by calling CopyScreenToDIB and\n\t * passing it the client rect.\n\t */\n\n\thDIB = CopyScreenToDIB(&rectClient);\n\tbreak;\n    }\n\n    case PTScreen: { /* Entire screen. */\n\tRECT Rect;\n\n\t/*\n\t * Get the device-dependent bitmap in lpRect by calling\n\t * CopyScreenToBitmap and passing it the rectangle to grab.\n\t */\n\tRect.top = Rect.left = 0;\n\tGetDisplaySize(&Rect.right, &Rect.bottom);\n\n\thBitmap = CopyScreenToBitmap(&Rect);\n\n\t/* Check for a valid bitmap handle. */\n\n\tif (!hBitmap) {\n\t    return NULL;\n\t}\n\n\t/* Get the current palette. */\n\n\thPalette = GetSystemPalette();\n\n\t/* Convert the bitmap to a DIB. */\n\n\thDIB = BitmapToDIB(hBitmap, hPalette);\n\n\t/* Clean up. */\n\n\tDeleteObject(hPalette);\n\tDeleteObject(hBitmap);\n\n\t/* Return handle to the packed-DIB. */\n\tbreak;\n    }\n    default:\t/* Invalid print area. */\n\treturn NULL;\n    }\n\n    /* Return the handle to the DIB. */\n    return hDIB;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetDisplaySize--\n *\n *\tGetDisplaySize does just that.  There may be an easier way, but it is\n *\tnot apparent.\n *\n * Results:\n *\tReturns display size.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void GetDisplaySize(\n    LONG *width,\n    LONG *height)\n{\n    HDC hDC;\n\n    hDC = CreateDCW(L\"DISPLAY\", 0, 0, 0);\n    *width = GetDeviceCaps(hDC, HORZRES);\n    *height = GetDeviceCaps(hDC, VERTRES);\n    DeleteDC(hDC);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CopyScreenToBitmap--\n *\n *\tCopies screen to bitmap.\n *\n * Results:\n *\tScreen is copied.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HBITMAP CopyScreenToBitmap(\n    LPRECT lpRect)\n{\n    HDC     hScrDC, hMemDC;\t/* Screen DC and memory DC. */\n    HGDIOBJ hBitmap, hOldBitmap; /* Handles to deice-dependent bitmaps. */\n    int     nX, nY, nX2, nY2;\t/* Coordinates of rectangle to grab. */\n    int     nWidth, nHeight;\t/* DIB width and height */\n    int     xScrn, yScrn;\t/* Screen resolution. */\n\n    /* Check for an empty rectangle. */\n\n    if (IsRectEmpty(lpRect)) {\n\treturn NULL;\n    }\n\n    /*\n     * Create a DC for the screen and create a memory DC compatible to screen\n     * DC.\n     */\n\n    hScrDC = CreateDCW(L\"DISPLAY\", NULL, NULL, NULL);\n    hMemDC = CreateCompatibleDC(hScrDC);\n\n    /* Get points of rectangle to grab. */\n\n    nX = lpRect->left;\n    nY = lpRect->top;\n    nX2 = lpRect->right;\n    nY2 = lpRect->bottom;\n\n    /* Get screen resolution. */\n\n    xScrn = GetDeviceCaps(hScrDC, HORZRES);\n    yScrn = GetDeviceCaps(hScrDC, VERTRES);\n\n    /* Make sure bitmap rectangle is visible. */\n\n    if (nX < 0) {\n\tnX = 0;\n    }\n    if (nY < 0) {\n\tnY = 0;\n    }\n    if (nX2 > xScrn) {\n\tnX2 = xScrn;\n    }\n    if (nY2 > yScrn) {\n\tnY2 = yScrn;\n    }\n\n    nWidth = nX2 - nX;\n    nHeight = nY2 - nY;\n\n    /* Create a bitmap compatible with the screen DC. */\n    hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);\n\n    /* Select new bitmap into memory DC. */\n    hOldBitmap = SelectObject(hMemDC, hBitmap);\n\n    /* Bitblt screen DC to memory DC. */\n    BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);\n\n    /*\n     * Select old bitmap back into memory DC and get handle to bitmap of the\n     * screen.\n     */\n\n    hBitmap = SelectObject(hMemDC, hOldBitmap);\n\n    /* Clean up. */\n\n    DeleteDC(hScrDC);\n    DeleteDC(hMemDC);\n\n    /* Return handle to the bitmap. */\n\n    return (HBITMAP)hBitmap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BitmapToDIB--\n *\n *\tConverts bitmap to DIB.\n *\n * Results:\n *\tBitmap converted.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HANDLE BitmapToDIB(\n    HBITMAP hBitmap,\n    HPALETTE hPal)\n{\n    BITMAP              bm;\n    BITMAPINFOHEADER    bi;\n    LPBITMAPINFOHEADER  lpbi;\n    DWORD               dwLen;\n    HANDLE              hDIB;\n    HANDLE              h;\n    HDC                 hDC;\n    WORD                biBits;\n\n    /* Check if bitmap handle is valid. */\n\n    if (!hBitmap) {\n\treturn NULL;\n    }\n\n    /* Fill in BITMAP structure, return NULL if it didn't work. */\n\n    if (!GetObjectW(hBitmap, sizeof(bm), (LPWSTR)&bm)) {\n\treturn NULL;\n    }\n\n    /* Ff no palette is specified, use default palette. */\n\n    if (hPal == NULL) {\n\thPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);\n    }\n\n    /* Calculate bits per pixel. */\n\n    biBits = bm.bmPlanes * bm.bmBitsPixel;\n\n    /* Make sure bits per pixel is valid. */\n\n    if (biBits <= 1) {\n\tbiBits = 1;\n    } else if (biBits <= 4) {\n\tbiBits = 4;\n    } else if (biBits <= 8) {\n\tbiBits = 8;\n    } else { /* If greater than 8-bit, force to 24-bit. */\n\tbiBits = 24;\n    }\n\n    /* Initialize BITMAPINFOHEADER. */\n\n    bi.biSize = sizeof(BITMAPINFOHEADER);\n    bi.biWidth = bm.bmWidth;\n    bi.biHeight = bm.bmHeight;\n    bi.biPlanes = 1;\n    bi.biBitCount = biBits;\n    bi.biCompression = BI_RGB;\n    bi.biSizeImage = 0;\n    bi.biXPelsPerMeter = 0;\n    bi.biYPelsPerMeter = 0;\n    bi.biClrUsed = 0;\n    bi.biClrImportant = 0;\n\n    /* Calculate size of memory block required to store BITMAPINFO. */\n\n    dwLen = (DWORD)(bi.biSize + DIBNumColors(&bi) * sizeof(RGBQUAD));\n\n    /* Get a DC. */\n\n    hDC = GetDC(NULL);\n\n    /* Select and realize our palette. */\n\n    hPal = SelectPalette(hDC, hPal, FALSE);\n    RealizePalette(hDC);\n\n    /* Alloc memory block to store our bitmap. */\n\n    hDIB = GlobalAlloc(GHND, dwLen);\n\n    /* If we couldn't get memory block. */\n\n    if (!hDIB) {\n\t/* clean up and return NULL. */\n\n\tSelectPalette(hDC, hPal, TRUE);\n\tRealizePalette(hDC);\n\tReleaseDC(NULL, hDC);\n\treturn NULL;\n    }\n\n    /* Lock memory and get pointer to it. */\n\n    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n    /* Use our bitmap info. to fill BITMAPINFOHEADER. */\n\n    *lpbi = bi;\n\n    /* Call GetDIBits with a NULL lpBits param, so it will calculate the\n     * biSizeImage field for us\n     */\n\n    GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,\n\t    DIB_RGB_COLORS);\n\n    /* get the info. returned by GetDIBits and unlock memory block. */\n\n    bi = *lpbi;\n    GlobalUnlock(hDIB);\n\n    /* If the driver did not fill in the biSizeImage field, make one up. */\n    if (bi.biSizeImage == 0) {\n\tbi.biSizeImage = (((((DWORD)bm.bmWidth * biBits) + 31) / 32) * 4)\n\t\t* bm.bmHeight;\n    }\n\n    /* Realloc the buffer big enough to hold all the bits. */\n\n    dwLen = (DWORD)(bi.biSize + DIBNumColors(&bi) * sizeof(RGBQUAD) + bi.biSizeImage);\n\n    if ((h = GlobalReAlloc(hDIB, dwLen, 0)) != 0) {\n\thDIB = h;\n    } else {\n\t/* Clean up and return NULL. */\n\n\tGlobalFree(hDIB);\n\tSelectPalette(hDC, hPal, TRUE);\n\tRealizePalette(hDC);\n\tReleaseDC(NULL, hDC);\n\treturn NULL;\n    }\n\n    /* Lock memory block and get pointer to it. */\n\n    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);\n\n    /* Call GetDIBits with a NON-NULL lpBits param, and actualy get the\n     * bits this time.\n     */\n\n    if (GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, (LPSTR)lpbi +\n\t    (WORD)lpbi->biSize + DIBNumColors(lpbi) * sizeof(RGBQUAD),\n\t    (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0) {\n\t/* Clean up and return NULL. */\n\n\tGlobalUnlock(hDIB);\n\tSelectPalette(hDC, hPal, TRUE);\n\tRealizePalette(hDC);\n\tReleaseDC(NULL, hDC);\n\treturn NULL;\n    }\n\n    bi = *lpbi;\n\n    /* Clean up. */\n    GlobalUnlock(hDIB);\n    SelectPalette(hDC, hPal, TRUE);\n    RealizePalette(hDC);\n    ReleaseDC(NULL, hDC);\n\n    /* Return handle to the DIB. */\n    return hDIB;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CopyScreenToDIB--\n *\n *\tCopies screen to DIB.\n *\n * Results:\n *\tScreen copied.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HANDLE CopyScreenToDIB(\n    LPRECT lpRect)\n{\n    HBITMAP     hBitmap;\n    HPALETTE    hPalette;\n    HANDLE      hDIB;\n\n    /*\n     * Get the device-dependent bitmap in lpRect by calling CopyScreenToBitmap\n     * and passing it the rectangle to grab.\n     */\n\n    hBitmap = CopyScreenToBitmap(lpRect);\n\n    /* Check for a valid bitmap handle. */\n\n    if (!hBitmap) {\n\treturn NULL;\n    }\n\n    /* Get the current palette. */\n\n    hPalette = GetSystemPalette();\n\n    /* convert the bitmap to a DIB. */\n\n    hDIB = BitmapToDIB(hBitmap, hPalette);\n\n    /* Clean up. */\n\n    DeleteObject(hPalette);\n    DeleteObject(hBitmap);\n\n    /* Return handle to the packed-DIB. */\n    return hDIB;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetSystemPalette--\n *\n *\tObtains the system palette.\n *\n * Results:\n *\tReturns palette.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HPALETTE GetSystemPalette(void)\n{\n    HDC hDC;                /* Handle to a DC. */\n    static HPALETTE hPal = NULL;   /* Handle to a palette. */\n    HANDLE hLogPal;         /* Handle to a logical palette. */\n    LPLOGPALETTE lpLogPal;  /* Pointer to a logical palette. */\n    int nColors;            /* Number of colors. */\n\n    /* Find out how many palette entries we want.. */\n\n    hDC = GetDC(NULL);\n    if (!hDC) {\n\treturn NULL;\n    }\n\n    nColors = PalEntriesOnDevice(hDC);   /* Number of palette entries. */\n\n    /* Allocate room for the palette and lock it.. */\n\n    hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *\n\t    sizeof(PALETTEENTRY));\n    if (!hLogPal) {\n\t/* If we didn't get a logical palette, return NULL. */\n\n\treturn NULL;\n    }\n\n    /* get a pointer to the logical palette. */\n\n    lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);\n\n    /* Set some important fields. */\n\n    lpLogPal->palVersion = 0x300;\n    lpLogPal->palNumEntries = (WORD)nColors;\n\n    /* Copy the current system palette into our logical palette. */\n\n    GetSystemPaletteEntries(hDC, 0, nColors,\n\t    (LPPALETTEENTRY) lpLogPal->palPalEntry);\n\n    /*\n     * Go ahead and create the palette.  Once it's created, we no longer need\n     * the LOGPALETTE, so free it.\n     */\n\n    hPal = CreatePalette(lpLogPal);\n\n    /* Clean up. */\n\n    GlobalUnlock(hLogPal);\n    GlobalFree(hLogPal);\n    ReleaseDC(NULL, hDC);\n\n    return hPal;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PalEntriesOnDevice--\n *\n *\tReturns the palettes on the device.\n *\n * Results:\n *\tReturns palettes.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int PalEntriesOnDevice(\n    HDC hDC)\n{\n    return (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * WinprintDeleted--\n *\n *\tFree interp's print resources.\n *\n * -------------------------------------------------------------------------\n */\nstatic void WinprintDeleted(\n    void *clientData,\n    TCL_UNUSED(Tcl_Interp *))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n\n    if (dataPtr->printDC != NULL) {\n\tDeleteDC(dataPtr->printDC);\n\tTcl_DStringFree(&dataPtr->jobNameW);\n    }\n    Tcl_Free(dataPtr);\n}\n\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * Winprint_Init--\n *\n *\tInitializes printing module on Windows.\n *\n * Results:\n *\tModule initialized.\n *\n * -------------------------------------------------------------------------\n */\n\nint Winprint_Init(\n    Tcl_Interp * interp)\n{\n    size_t i;\n    Tcl_Namespace *namespacePtr;\n    static const char *gdiName = \"::tk::print::_gdi\";\n    static const size_t numCommands =\n\t    sizeof(gdi_commands) / sizeof(struct gdi_command);\n    WinprintData *dataPtr = (WinprintData *)Tcl_Alloc(sizeof(WinprintData));\n\n    /*\n     * Set up the low-level [_gdi] command.\n     */\n    namespacePtr = Tcl_CreateNamespace(interp, gdiName,\n\t    NULL, (Tcl_NamespaceDeleteProc *) NULL);\n    for (i=0; i<numCommands; i++) {\n\tchar buffer[100];\n\n\tsnprintf(buffer, sizeof(buffer), \"%s::%s\", gdiName, gdi_commands[i].command_string);\n\tTcl_CreateObjCommand2(interp, buffer, gdi_commands[i].command,\n\t    dataPtr, NULL);\n\tTcl_Export(interp, namespacePtr, gdi_commands[i].command_string, 0);\n    }\n    Tcl_CreateEnsemble(interp, gdiName, namespacePtr, 0);\n\n    /*\n     * The other printing-related commands.\n     */\n\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_selectprinter\",\n\t    PrintSelectPrinter, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_openprinter\",\n\t    PrintOpenPrinter, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_closeprinter\",\n\t    PrintClosePrinter, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_opendoc\",\n\t    PrintOpenDoc, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_closedoc\",\n\t    PrintCloseDoc, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_openpage\",\n\t    PrintOpenPage, dataPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::print::_closepage\",\n\t    PrintClosePage, dataPtr, NULL);\n\n    dataPtr->printDC = NULL;\n    Tcl_CallWhenDeleted(interp, WinprintDeleted, dataPtr);\n    return TCL_OK;\n}\n\f\n/* Print API functions. */\n\n/*----------------------------------------------------------------------\n *\n * PrintSelectPrinter--\n *\n *\tMain dialog for selecting printer and initializing data for print job.\n *\n * Results:\n *\tPrinter selected.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int PrintSelectPrinter(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj* const*))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC != NULL) {\n\tTcl_AppendResult(interp, \"device context still in use: call \"\n\t    \"_closedoc first\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    PRINTDLGW pd;\n    LPCWSTR printerName = NULL;\n    PDEVMODEW devmode = NULL;\n    LPDEVNAMES devnames = NULL;\n\n    int copies = 0;\n    int paper_width = 0;\n    int paper_height = 0;\n    int dpi_x = 0;\n    int dpi_y = 0;\n    int returnVal = TCL_OK;\n\n    /* Set up print dialog and initalize property structure. */\n    memset(&pd, 0, sizeof(pd));\n    pd.lStructSize = sizeof(pd);\n    pd.hwndOwner = GetDesktopWindow();\n    pd.Flags = PD_HIDEPRINTTOFILE | PD_DISABLEPRINTTOFILE | PD_NOSELECTION |\n\tPD_RETURNDC;\n\n    if (! PrintDlgW(&pd)) {\n\tunsigned int errorcode = CommDlgExtendedError();\n\t/*\n\t * The user cancelled, or there was an error\n\t * The code on the Tcl side checks if the variable\n\t * ::tk::print::printer_name is defined to determine\n\t * that a valid selection was made.\n\t * So we better unset this here, unconditionally.\n\t */\n\tTcl_UnsetVar(interp, \"::tk::print::printer_name\", 0);\n\tif (errorcode != 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\"print failed: error %04x\",\n\t\t    errorcode));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"PRINT\", \"DIALOG\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\treturn TCL_OK;\n    }\n\n    devmode = (PDEVMODEW) GlobalLock(pd.hDevMode);\n    devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);\n    if (! devmode) {\n\tTcl_AppendResult(interp, \"selected printer doesn't have extended info\",\n\t    (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (! devnames) {\n\tTcl_AppendResult(interp, \"can't get device names\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    printerName = (LPCWSTR) devnames + devnames->wDeviceOffset;\n    /* Get values from user-set and built-in properties. */\n    dpi_y = devmode->dmYResolution;\n    dpi_x = devmode->dmPrintQuality;\n    /* Convert height and width to logical points. */\n    paper_height = (int) devmode->dmPaperLength / 0.254;\n    paper_width = (int) devmode->dmPaperWidth / 0.254;\n    copies = pd.nCopies;\n    /* Set device context here for all GDI printing operations. */\n    dataPtr->printDC = pd.hDC;\n\n    /*\n     * Store print properties in variables so they can be accessed from\n     * script level.\n     */\n    if (printerName != NULL) {\n\tTcl_DString prname;\n\n\tTcl_DStringInit(&prname);\n\tTcl_WCharToUtfDString((WCHAR *)printerName, TCL_INDEX_NONE, &prname);\n\tTcl_SetVar2Ex(interp, \"::tk::print::printer_name\", NULL,\n\t\tTcl_DStringToObj(&prname), 0);\n\tTcl_SetVar2Ex(interp, \"::tk::print::copies\", NULL,\n\t\tTcl_NewIntObj(copies), 0);\n\tTcl_SetVar2Ex(interp, \"::tk::print::dpi_x\", NULL,\n\t\tTcl_NewIntObj(dpi_x), 0);\n\tTcl_SetVar2Ex(interp, \"::tk::print::dpi_y\", NULL,\n\t\tTcl_NewIntObj(dpi_y), 0);\n\tTcl_SetVar2Ex(interp, \"::tk::print::paper_width\", NULL,\n\t\tTcl_NewIntObj(paper_width), 0);\n\tTcl_SetVar2Ex(interp, \"::tk::print::paper_height\", NULL,\n\t\tTcl_NewIntObj(paper_height), 0);\n    } else {\n\tTcl_UnsetVar(interp, \"::tk::print::printer_name\", 0);\n\tTcl_AppendResult(interp, \"selected printer doesn't have name\", (char *)NULL);\n\tDeleteDC(dataPtr->printDC);\n\tdataPtr->printDC = NULL;\n\treturnVal = TCL_ERROR;\n    }\n\n    GlobalUnlock(devmode);\n    GlobalFree(devmode);\n    GlobalUnlock(devnames);\n    GlobalFree(devnames);\n    return returnVal;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintOpenPrinter--\n *\n *\tOpen the given printer.\n *\n * Results:\n *\tOpens the selected printer.\n *\n * -------------------------------------------------------------------------\n */\n\nint PrintOpenPrinter(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    Tcl_DString ds;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"printer\");\n\treturn TCL_ERROR;\n    }\n\n    /*Start an individual page.*/\n    if (StartPage(dataPtr->printDC) <= 0) {\n\treturn TCL_ERROR;\n    }\n\n    const char *printer = Tcl_GetString(objv[1]);\n\n    Tcl_DStringInit(&ds);\n    if ((OpenPrinterW(Tcl_UtfToWCharDString(printer, -1, &ds),\n\t    (LPHANDLE)&dataPtr->printDC, NULL)) == FALSE) {\n\tTcl_AppendResult(interp, \"unable to open printer\", (char *)NULL);\n\tTcl_DStringFree(&ds);\n\treturn TCL_ERROR;\n    }\n\n    Tcl_DStringFree(&ds);\n    return TCL_OK;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintClosePrinter--\n *\n *\tCloses the given printer.\n *\n * Results:\n *\tPrinter closed.\n *\n * -------------------------------------------------------------------------\n */\n\nint PrintClosePrinter(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    ClosePrinter(dataPtr->printDC);\n    return TCL_OK;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintOpenDoc--\n *\n *     Opens the document for printing.\n *\n * Results:\n *      Opens the print document.\n *\n * -------------------------------------------------------------------------\n */\nint PrintOpenDoc(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const *objv)\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    int output = 0;\n    const char *jobname;\n    Tcl_Size len;\n\n    if (objc < 2 || objc > 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"jobname ?font?\");\n\treturn TCL_ERROR;\n    }\n\n    jobname = Tcl_GetStringFromObj(objv[1], &len);\n    Tcl_DStringInit(&dataPtr->jobNameW);\n\n    /*Get document info.*/\n    memset(&dataPtr->di, 0, sizeof(dataPtr->di));\n    dataPtr->di.cbSize = sizeof(dataPtr->di);\n    dataPtr->di.lpszDocName = Tcl_UtfToWCharDString(jobname, len,\n\t&dataPtr->jobNameW);\n\n    /*\n     * Start printing.\n     */\n    output = StartDocW(dataPtr->printDC, &dataPtr->di);\n    if (output <= 0) {\n\tTcl_AppendResult(interp, \"unable to start document\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /* the optional argument \"font\" is useful for plain text documents.\n     * we set the font and other defaults here, and return the font width\n     * and height just once\n     */\n    if (objc == 3) {\n\tLOGFONTW lf;\n\tHFONT hfont;\n\tTEXTMETRICW tmw;\n\n\tif (GdiMakeLogFont(interp, objv[2], &lf, dataPtr->printDC)) {\n\t    if ((hfont = CreateFontIndirectW(&lf)) != NULL) {\n\t\tSelectObject(dataPtr->printDC, hfont);\n\t    }\n\t}\n\tSetTextAlign(dataPtr->printDC, TA_LEFT);\n\tSetTextColor(dataPtr->printDC, 0);\n\tSetBkMode(dataPtr->printDC, TRANSPARENT);\n\n\tif (GetTextMetricsW(dataPtr->printDC, &tmw) != 0) {\n\t    Tcl_Obj *ret[2];\n\n\t    ret[0] = Tcl_NewIntObj((int)tmw.tmAveCharWidth);\n\t    ret[1] = Tcl_NewIntObj((int)tmw.tmHeight);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, ret));\n\t} else {\n\t    Tcl_AppendResult(interp, \"_opendoc: can't determine font \",\n\t\t\"width and height\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintCloseDoc--\n *\n *\tCloses the document for printing.\n *\n * Results:\n *\tCloses the print document.\n *\n * -------------------------------------------------------------------------\n */\n\nint PrintCloseDoc(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (EndDoc(dataPtr->printDC) <= 0) {\n\tTcl_AppendResult(interp, \"unable to close document\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    /* delete the font object that might be created as default */\n    DeleteObject(SelectObject (dataPtr->printDC,\n\tGetStockObject(DEVICE_DEFAULT_FONT)));\n    DeleteDC(dataPtr->printDC);\n    dataPtr->printDC = NULL;\n    Tcl_DStringFree(&dataPtr->jobNameW);\n    return TCL_OK;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintOpenPage--\n *\n *    Opens a page for printing.\n *\n * Results:\n *      Opens the print page.\n *\n * -------------------------------------------------------------------------\n */\n\nint PrintOpenPage(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*Start an individual page.*/\n    if (StartPage(dataPtr->printDC) <= 0) {\n\tTcl_AppendResult(interp, \"unable to start page\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n * --------------------------------------------------------------------------\n *\n * PrintClosePage--\n *\n *\tCloses the printed page.\n *\n * Results:\n *\tCloses the page.\n *\n * -------------------------------------------------------------------------\n */\n\nint PrintClosePage(\n    void *clientData,\n    Tcl_Interp *interp,\n    TCL_UNUSED(Tcl_Size),\n    TCL_UNUSED(Tcl_Obj *const *))\n{\n    WinprintData *dataPtr = (WinprintData *)clientData;\n    if (dataPtr->printDC == NULL) {\n\tTcl_AppendResult(interp, \"device context not initialized\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (EndPage(dataPtr->printDC) <= 0) {\n\tTcl_AppendResult(interp, \"unable to close page\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinIco.c",
    "content": "/*\n * tkWinIco.c --\n *\n *\tThis file contains functions for icon-manipulation routines\n *      in Windows.\n *\n * Copyright Â© 1995-1996 Microsoft Corp.\n * Copyright Â© 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tclWinPort.h\"\t\t\t\t/* for the macro S_ISDIR */\n#include \"tkInt.h\"\n#include \"tkWinIco.h\"\n\n#ifndef SHIL_JUMBO\n#   define SHIL_JUMBO 0x4\n#endif\n\n/*\n *----------------------------------------------------------------------\n *\n * DIBNumColors --\n *\n *\tCalculates the number of entries in the color table, given by LPSTR\n *\tlpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.\n *\n * Results:\n *\tWORD - Number of entries in the color table.\n *\n *----------------------------------------------------------------------\n */\n\nstatic WORD\nDIBNumColors(\n    LPSTR lpbi)\n{\n    WORD wBitCount;\n    DWORD dwClrUsed;\n\n    dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;\n\n    if (dwClrUsed) {\n\treturn (WORD) dwClrUsed;\n    }\n\n    wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;\n\n    switch (wBitCount) {\n    case 1:\n\treturn 2;\n    case 4:\n\treturn 16;\n    case 8:\n\treturn 256;\n    default:\n\treturn 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PaletteSize --\n *\n *\tCalculates the number of bytes in the color table, as given by LPSTR\n *\tlpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.\n *\n * Results:\n *\tNumber of bytes in the color table\n *\n *----------------------------------------------------------------------\n */\nstatic WORD\nPaletteSize(\n    LPSTR lpbi)\n{\n    return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD));\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FindDIBits --\n *\n *\tLocate the image bits in a CF_DIB format DIB, as given by LPSTR lpbi -\n *\tpointer to the CF_DIB memory block. Used by titlebar icon code.\n *\n * Results:\n *\tpointer to the image bits\n *\n * Side effects: None\n *\n *\n *----------------------------------------------------------------------\n */\n\nLPSTR\nFindDIBBits(\n    LPSTR lpbi)\n{\n    return lpbi + *((LPDWORD) lpbi) + PaletteSize(lpbi);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * BytesPerLine --\n *\n *\tCalculates the number of bytes in one scan line, as given by\n *\tLPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER that\n *\tbegins the CF_DIB block. Used by titlebar icon code.\n *\n * Results:\n *\tnumber of bytes in one scan line (DWORD aligned)\n *\n *----------------------------------------------------------------------\n */\n\nDWORD\nBytesPerLine(\n    LPBITMAPINFOHEADER lpBMIH)\n{\n    return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);\n}\n/*\n *----------------------------------------------------------------------\n *\n * CreateIcoFromPhoto --\n *\n *\tCreate ico pointer from Tk photo block.\n *\n * Results:\n *\tIcon image is created from a valid Tk photo image.\n *\n * Side effects:\n *\tIcon is created.\n *\n *----------------------------------------------------------------------\n */\n\nHICON\nCreateIcoFromPhoto(\n    int width,                  /* Width of image. */\n    int height,                 /* Height of image. */\n    Tk_PhotoImageBlock block)   /* Image block to convert. */\n{\n    int idx, bufferSize;\n    union {unsigned char *ptr; void *voidPtr;} bgraPixel;\n    union {unsigned char *ptr; void *voidPtr;} bgraMask;\n    HICON hIcon;\n    BITMAPINFO bmInfo;\n    ICONINFO iconInfo;\n\n    /*\n     * Don't use CreateIcon to create the icon, as it requires color\n     * bitmap data in device-dependent format. Instead we use\n     * CreateIconIndirect which takes device-independent bitmaps and\n     * converts them as required. Initialise icon info structure.\n     */\n\n    memset(&iconInfo, 0, sizeof(iconInfo));\n    iconInfo.fIcon = TRUE;\n\n    /*\n     * Create device-independent color bitmap.\n     */\n\n    memset(&bmInfo, 0, sizeof bmInfo);\n    bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    bmInfo.bmiHeader.biWidth = width;\n    bmInfo.bmiHeader.biHeight = -height;\n    bmInfo.bmiHeader.biPlanes = 1;\n    bmInfo.bmiHeader.biBitCount = 32;\n    bmInfo.bmiHeader.biCompression = BI_RGB;\n\n    iconInfo.hbmColor = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,\n\t    &bgraPixel.voidPtr, NULL, 0);\n    if (!iconInfo.hbmColor) {\n\treturn NULL;\n    }\n\n    /*\n     * Convert the photo image data into BGRA format (RGBQUAD).\n     */\n\n    bufferSize = height * width * 4;\n    for (idx = 0 ; idx < bufferSize ; idx += 4) {\n\tbgraPixel.ptr[idx] = block.pixelPtr[idx+2];\n\tbgraPixel.ptr[idx+1] = block.pixelPtr[idx+1];\n\tbgraPixel.ptr[idx+2] = block.pixelPtr[idx+0];\n\tbgraPixel.ptr[idx+3] = block.pixelPtr[idx+3];\n    }\n\n    /*\n     * Create a dummy mask bitmap. The contents of this don't appear to\n     * matter, as CreateIconIndirect will setup the icon mask based on the\n     * alpha channel in our color bitmap.\n     */\n\n    bmInfo.bmiHeader.biBitCount = 1;\n\n    iconInfo.hbmMask = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,\n\t    &bgraMask.voidPtr, NULL, 0);\n    if (!iconInfo.hbmMask) {\n\tDeleteObject(iconInfo.hbmColor);\n\treturn NULL;\n    }\n\n    memset(bgraMask.ptr, 0, width*height/8);\n\n    /*\n     * Create an icon from the bitmaps.\n     */\n\n    hIcon = CreateIconIndirect(&iconInfo);\n    DeleteObject(iconInfo.hbmColor);\n    DeleteObject(iconInfo.hbmMask);\n    if (hIcon == NULL) {\n\treturn NULL;\n    }\n\n    return hIcon;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetFileIcon --\n *\n * Given a file path, retrieves the system-defined icon for that file.\n * Source: Mark Janssen, https://wiki.tcl-lang.org/page/Retrieve+file+icon+using+the+Win32+API\n * Updated for Tk 9 by Paul Obermeier\n *\n * Results:\n *\tIcon image is created from a file path.\n *\n * Side effects:\n *\tIcon is created.\n *\n *----------------------------------------------------------------------\n */\n\n\nint\nGetFileIcon(\n    TCL_UNUSED(void *),         /* Not used. */\n    Tcl_Interp *interp,         /* Current interpreter */\n    int objc,                   /* Number of arguments */\n    Tcl_Obj *const objv[]       /* Argument strings */\n)\n{\n    SHFILEINFOW shfi;\n    ICONINFO iconInfo;\n    BITMAP bmp;\n    long imageSize;\n    char *bitBuffer = NULL;\n    unsigned char *byteBuffer = NULL;\n    int i, hasAlpha;\n    const wchar_t *iconPath;\n    Tk_PhotoHandle photo;\n    Tk_PhotoImageBlock block;\n    int bitSize;\n    int pixelSize;\n    int shil;\n    DWORD attrs = 0;\n    DWORD flags = SHGFI_SYSICONINDEX;\n    Tcl_StatBuf buf;\n    IImageList *iml = NULL;\n    HICON hIcon = NULL;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"fileName pixelSize\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[2], &pixelSize) != TCL_OK) {\n\t\tTcl_NewStringObj(\"Unable to parse icon size\", -1);\n\treturn TCL_ERROR;\n    }\n\n    /* Size → SHIL mapping. */\n    if (pixelSize <= 16) shil = SHIL_SMALL;\n    else if (pixelSize <= 32) shil = SHIL_LARGE;\n    else if (pixelSize <= 48) shil = SHIL_EXTRALARGE;\n    else shil = SHIL_JUMBO;\n\n    ZeroMemory(&shfi, sizeof(shfi));\n\n    /* Try native filesystem path. */\n    iconPath = (const wchar_t *)Tcl_FSGetNativePath(objv[1]);\n\n    if (iconPath == NULL) {\n\t/* Virtual filesystem fallback. */\n\ticonPath = L\"dummy\";\n\tflags |= SHGFI_USEFILEATTRIBUTES;\n\tattrs = Tcl_FSStat(objv[1], &buf) == 0 && S_ISDIR(buf.st_mode)\n\t\t? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;\n    }\n\n    if (!SHGetFileInfoW(\n\t    iconPath,\n\t    attrs,\n\t    &shfi,\n\t    sizeof(shfi),\n\t    flags))\n    {\n\tTcl_SetObjResult(interp,\n\t    Tcl_NewStringObj(\"Unable to retrieve system icon index\", -1));\n\treturn TCL_ERROR;\n    }\n\n    if (FAILED(SHGetImageList(shil, &IID_IImageList, (void **)&iml))) {\n\tTcl_SetObjResult(interp,\n\t    Tcl_NewStringObj(\"Unable to retrieve system image list\", -1));\n\treturn TCL_ERROR;\n    }\n\n    if (FAILED(iml->lpVtbl->GetIcon(\n\t    iml, shfi.iIcon, ILD_TRANSPARENT, &hIcon)))\n    {\n\timl->lpVtbl->Release(iml);\n\tTcl_SetObjResult(interp,\n\t    Tcl_NewStringObj(\"Unable to extract icon\", -1));\n\treturn TCL_ERROR;\n    }\n\n    iml->lpVtbl->Release(iml);\n\n    /* Bitmap extraction. */\n\n    GetIconInfo(hIcon, &iconInfo);\n\n    GetObject(iconInfo.hbmMask, sizeof(BITMAP), &bmp);\n    bitSize = bmp.bmWidth * bmp.bmHeight * bmp.bmBitsPixel / 8;\n    bitBuffer = (char *)Tcl_Alloc(bitSize);\n    GetBitmapBits(iconInfo.hbmMask, bitSize, bitBuffer);\n\n    GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmp);\n    imageSize = bmp.bmWidth * bmp.bmHeight * bmp.bmBitsPixel / 8;\n    byteBuffer = (unsigned char *)Tcl_Alloc(imageSize);\n    GetBitmapBits(iconInfo.hbmColor, imageSize, byteBuffer);\n\n    hasAlpha = 0;\n    for (i = 0; i < imageSize; i += 4) {\n\tif (byteBuffer[i + 3] != 0) {\n\t    hasAlpha = 1;\n\t    break;\n\t}\n    }\n\n#define BIT_SET(x,y) (((x) >> (7-(y))) & 1)\n\n    if (!hasAlpha) {\n\tfor (i = 0; i < bitSize; i++) {\n\t    int bit;\n\t    for (bit = 0; bit < 8; bit++) {\n\t\tbyteBuffer[(i*8 + bit)*4 + 3] =\n\t\t    BIT_SET(bitBuffer[i], bit) ? 0 : 255;\n\t    }\n\t}\n    }\n\n    block.pixelPtr  = byteBuffer;\n    block.width     = bmp.bmWidth;\n    block.height    = bmp.bmHeight;\n    block.pitch     = bmp.bmWidthBytes;\n    block.pixelSize = bmp.bmBitsPixel / 8;\n    block.offset[0] = 2;\n    block.offset[1] = 1;\n    block.offset[2] = 0;\n    block.offset[3] = 3;\n\n    if (Tcl_Eval(interp, \"image create photo\") != TCL_OK) {\n\tgoto cleanup;\n    }\n\n    photo = Tk_FindPhoto(interp, Tcl_GetStringResult(interp));\n\n    Tk_PhotoPutBlock(\n\tinterp, photo, &block,\n\t0, 0, block.width, block.height,\n\tTK_PHOTO_COMPOSITE_SET);\n\ncleanup:\n    if (bitBuffer) Tcl_Free(bitBuffer);\n    if (byteBuffer) Tcl_Free(byteBuffer);\n\n    DeleteObject(iconInfo.hbmMask);\n    DeleteObject(iconInfo.hbmColor);\n    DestroyIcon(hIcon);\n\n    return TCL_OK;\n}\n\n\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinIco.h",
    "content": "/*\n * tkWinIco.h --\n *\n *\tThis file contains declarations for icon-manipulation routines\n *      in Windows.\n *\n * Copyright © 1995-1996 Microsoft Corp.\n * Copyright © 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWin.h\"\n#include <windows.h>\n#include <shlobj.h>\n#include <initguid.h>\n#include <shellapi.h>\n#include <commoncontrols.h>\n\n/*\n * These structures represent the contents of a icon, in terms of its image\n * or resource.\n */\n\ntypedef struct {\n    UINT Width, Height, Colors;\t/* Width, Height and bpp */\n    LPBYTE lpBits;\t\t/* Ptr to DIB bits */\n    DWORD dwNumBytes;\t\t/* How many bytes? */\n    LPBITMAPINFO lpbi;\t\t/* Ptr to header */\n    LPBYTE lpXOR;\t\t/* Ptr to XOR image bits */\n    LPBYTE lpAND;\t\t/* Ptr to AND image bits */\n    HICON hIcon;\t\t/* DAS ICON */\n} ICONIMAGE, *LPICONIMAGE;\n\n/*\n * This structure is how we represent a block of the above items. We will\n * reallocate these structures according to how many images they need to\n * contain.\n */\n\ntypedef struct {\n    int nNumImages;\t\t/* How many images? */\n    ICONIMAGE IconImages[1];\t/* Image entries */\n} BlockOfIconImages, *BlockOfIconImagesPtr;\n\n/*\n * These two structures are used to read in icons from an 'icon directory'\n * (i.e. the contents of a .icr file, say). We only use these structures\n * temporarily, since we copy the information we want into a\n * BlockOfIconImages.\n */\n\ntypedef struct {\n    BYTE bWidth;\t\t/* Width of the image */\n    BYTE bHeight;\t\t/* Height of the image (times 2) */\n    BYTE bColorCount;\t\t/* Number of colors in image (0 if >=8bpp) */\n    BYTE bReserved;\t\t/* Reserved */\n    WORD wPlanes;\t\t/* Color Planes */\n    WORD wBitCount;\t\t/* Bits per pixel */\n    DWORD dwBytesInRes;\t\t/* How many bytes in this resource? */\n    DWORD dwImageOffset;\t/* Where in the file is this image */\n} ICONDIRENTRY, *LPICONDIRENTRY;\n\ntypedef struct {\n    WORD idReserved;\t\t/* Reserved */\n    WORD idType;\t\t/* Resource type (1 for icons) */\n    WORD idCount;\t\t/* How many images? */\n    ICONDIRENTRY idEntries[1];\t/* The entries for each image */\n} ICONDIR, *LPICONDIR;\n\n/*\n * Used in BytesPerLine\n */\n\n#define WIDTHBYTES(bits)\t((((bits) + 31)>>5)<<2)\n\n/*\n * The following are implemented in tkWinIco.c and also used in tkWinWm.c and tkWinSysTray.c.\n */\n\nDWORD BytesPerLine(LPBITMAPINFOHEADER lpBMIH);\nLPSTR FindDIBBits(LPSTR lpbi);\nHICON CreateIcoFromPhoto(int width, int height, Tk_PhotoImageBlock block);\nint GetFileIcon(void *cdata, Tcl_Interp *interp, int objc,  Tcl_Obj * const objv[]);\n\n\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n\n\n\n"
  },
  {
    "path": "win/tkWinImage.c",
    "content": "/*\n * tkWinImage.c --\n *\n *\tThis file contains routines for manipulation full-color images.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\nstatic int\t\tDestroyImage(XImage* data);\nstatic unsigned long\tImageGetPixel(XImage *image, int x, int y);\nstatic int\t\tPutPixel(XImage *image, int x, int y,\n\t\t\t    unsigned long pixel);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DestroyImage --\n *\n *\tThis is a trivial wrapper around Tcl_Free to make it possible to pass\n *\tTcl_Free as a pointer.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeallocates the image.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nDestroyImage(\n    XImage *imagePtr)\t\t/* Image to free. */\n{\n    if (imagePtr) {\n\tif (imagePtr->data) {\n\t    Tcl_Free(imagePtr->data);\n\t}\n\tTcl_Free(imagePtr);\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ImageGetPixel --\n *\n *\tGet a single pixel from an image.\n *\n * Results:\n *\tReturns the 32 bit pixel value.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic unsigned long\nImageGetPixel(\n    XImage *image,\n    int x, int y)\n{\n    unsigned long pixel = 0;\n    unsigned char *srcPtr = (unsigned char *) &(image->data[(y * image->bytes_per_line)\n\t    + ((x * image->bits_per_pixel) / NBBY)]);\n\n    switch (image->bits_per_pixel) {\n    case 32:\n    case 24:\n\tpixel = RGB(srcPtr[2], srcPtr[1], srcPtr[0]);\n\tbreak;\n    case 16:\n\tpixel = RGB(((((WORD*)srcPtr)[0]) >> 7) & 0xf8,\n\t\t((((WORD*)srcPtr)[0]) >> 2) & 0xf8,\n\t\t((((WORD*)srcPtr)[0]) << 3) & 0xf8);\n\tbreak;\n    case 8:\n\tpixel = srcPtr[0];\n\tbreak;\n    case 4:\n\tpixel = ((x%2) ? (*srcPtr) : ((*srcPtr) >> 4)) & 0x0f;\n\tbreak;\n    case 1:\n\tpixel = ((*srcPtr) & (0x80 >> (x%8))) ? 1 : 0;\n\tbreak;\n    }\n    return pixel;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * PutPixel --\n *\n *\tSet a single pixel in an image.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nPutPixel(\n    XImage *image,\n    int x, int y,\n    unsigned long pixel)\n{\n    unsigned char *destPtr = (unsigned char *) &(image->data[(y * image->bytes_per_line)\n\t    + ((x * image->bits_per_pixel) / NBBY)]);\n\n    switch  (image->bits_per_pixel) {\n    case 32:\n\t/*\n\t * Pixel is DWORD: 0x00BBGGRR\n\t */\n\n\tdestPtr[3] = 0;\n\t/* FALLTHRU */\n    case 24:\n\t/*\n\t * Pixel is triplet: 0xBBGGRR.\n\t */\n\n\tdestPtr[0] = (unsigned char) GetBValue(pixel);\n\tdestPtr[1] = (unsigned char) GetGValue(pixel);\n\tdestPtr[2] = (unsigned char) GetRValue(pixel);\n\tbreak;\n    case 16:\n\t/*\n\t * Pixel is WORD: 5-5-5 (R-G-B)\n\t */\n\n\t(*(WORD*)destPtr) = ((GetRValue(pixel) & 0xf8) << 7)\n\t\t| ((GetGValue(pixel) & 0xf8) <<2)\n\t\t| ((GetBValue(pixel) & 0xf8) >> 3);\n\tbreak;\n    case 8:\n\t/*\n\t * Pixel is 8-bit index into color table.\n\t */\n\n\t(*destPtr) = (unsigned char) pixel;\n\tbreak;\n    case 4:\n\t/*\n\t * Pixel is 4-bit index in MSBFirst order.\n\t */\n\n\tif (x%2) {\n\t    (*destPtr) = (unsigned char) (((*destPtr) & 0xf0)\n\t\t    | (pixel & 0x0f));\n\t} else {\n\t    (*destPtr) = (unsigned char) (((*destPtr) & 0x0f)\n\t\t    | ((pixel << 4) & 0xf0));\n\t}\n\tbreak;\n    case 1: {\n\t/*\n\t * Pixel is bit in MSBFirst order.\n\t */\n\n\tunsigned char mask = (0x80 >> (x%8));\n\n\tif (pixel) {\n\t    (*destPtr) |= mask;\n\t} else {\n\t    (*destPtr) &= ~mask;\n\t}\n\tbreak;\n    }\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateImage --\n *\n *\tAllocates storage for a new XImage.\n *\n * Results:\n *\tReturns a newly allocated XImage.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nXImage *\nXCreateImage(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Visual *),\n    unsigned int depth,\n    int format,\n    int offset,\n    char *data,\n    unsigned int width,\n    unsigned int height,\n    int bitmap_pad,\n    int bytes_per_line)\n{\n    XImage* imagePtr = (XImage*)Tcl_Alloc(sizeof(XImage));\n\n    imagePtr->width = width;\n    imagePtr->height = height;\n    imagePtr->xoffset = offset;\n    imagePtr->format = format;\n    imagePtr->data = data;\n    imagePtr->byte_order = LSBFirst;\n    imagePtr->bitmap_unit = 8;\n    imagePtr->bitmap_bit_order = LSBFirst;\n    imagePtr->bitmap_pad = bitmap_pad;\n    imagePtr->bits_per_pixel = depth;\n    imagePtr->depth = depth;\n\n    /*\n     * Under Windows, bitmap_pad must be on an LONG data-type boundary.\n     */\n\n#define LONGBITS    (sizeof(LONG) * 8)\n\n    bitmap_pad = (bitmap_pad + LONGBITS - 1) / LONGBITS * LONGBITS;\n\n    /*\n     * Round to the nearest bitmap_pad boundary.\n     */\n\n    if (bytes_per_line) {\n\timagePtr->bytes_per_line = bytes_per_line;\n    } else {\n\timagePtr->bytes_per_line = (((depth * width)\n\t\t+ (bitmap_pad - 1)) >> 3) & ~((bitmap_pad >> 3) - 1);\n    }\n\n    imagePtr->red_mask = 0;\n    imagePtr->green_mask = 0;\n    imagePtr->blue_mask = 0;\n\n    imagePtr->f.put_pixel = PutPixel;\n    imagePtr->f.get_pixel = ImageGetPixel;\n    imagePtr->f.destroy_image = DestroyImage;\n    imagePtr->f.create_image = NULL;\n    imagePtr->f.sub_image = NULL;\n    imagePtr->f.add_pixel = NULL;\n\n    return imagePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetImageZPixmap --\n *\n *\tThis function copies data from a pixmap or window into an XImage. This\n *\thandles the ZPixmap case only.\n *\n * Results:\n *\tReturns a newly allocated image containing the data from the given\n *\trectangle of the given drawable.\n *\n * Side effects:\n *\tNone.\n *\n * This procedure is adapted from the XGetImage implementation in TkNT. That\n * code is Copyright © 1994 Software Research Associates, Inc.\n *\n *----------------------------------------------------------------------\n */\n\nstatic XImage *\nXGetImageZPixmap(\n    Display *display,\n    Drawable d,\n    int x, int y,\n    unsigned int width, unsigned int height,\n    TCL_UNUSED(unsigned long),\n    int\tformat)\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *)d;\n    XImage *ret_image;\n    HDC hdc, hdcMem;\n    HBITMAP hbmp, hbmpPrev;\n    BITMAPINFO *bmInfo = NULL;\n    HPALETTE hPal, hPalPrev1 = 0, hPalPrev2 = 0;\n    size_t size;\n    unsigned int n;\n    unsigned int depth;\n    unsigned char *data;\n    TkWinDCState state;\n    BOOL ret;\n\n    if (format != ZPixmap) {\n\tTkpDisplayWarning(\"Only ZPixmap types are implemented\",\n\t\t\"XGetImageZPixmap Failure\");\n\treturn NULL;\n    }\n\n    hdc = TkWinGetDrawableDC(display, d, &state);\n\n    /*\n     * Need to do a Blt operation to copy into a new bitmap.\n     */\n\n    hbmp = CreateCompatibleBitmap(hdc, (int) width, (int) height);\n    hdcMem = CreateCompatibleDC(hdc);\n    hbmpPrev = (HBITMAP)SelectObject(hdcMem, hbmp);\n    hPal = state.palette;\n    if (hPal) {\n\thPalPrev1 = SelectPalette(hdcMem, hPal, FALSE);\n\tn = RealizePalette(hdcMem);\n\tif (n > 0) {\n\t    UpdateColors(hdcMem);\n\t}\n\thPalPrev2 = SelectPalette(hdc, hPal, FALSE);\n\tn = RealizePalette(hdc);\n\tif (n > 0) {\n\t    UpdateColors(hdc);\n\t}\n    }\n\n    ret = BitBlt(hdcMem, 0, 0, (int) width, (int) height, hdc, x, y, SRCCOPY);\n    if (hPal) {\n\tSelectPalette(hdc, hPalPrev2, FALSE);\n    }\n    SelectObject(hdcMem, hbmpPrev);\n    TkWinReleaseDrawableDC(d, hdc, &state);\n    if (ret == FALSE) {\n\tret_image = NULL;\n\tgoto cleanup;\n    }\n    if (twdPtr->type == TWD_WINDOW) {\n\tdepth = Tk_Depth((Tk_Window) twdPtr->window.winPtr);\n    } else {\n\tdepth = twdPtr->bitmap.depth;\n    }\n\n    size = sizeof(BITMAPINFO);\n    if (depth <= 8) {\n\tsize += sizeof(unsigned short) << depth;\n    }\n    bmInfo = (BITMAPINFO *)Tcl_Alloc(size);\n\n    bmInfo->bmiHeader.biSize\t\t= sizeof(BITMAPINFOHEADER);\n    bmInfo->bmiHeader.biWidth\t\t= width;\n    bmInfo->bmiHeader.biHeight\t\t= -(int) height;\n    bmInfo->bmiHeader.biPlanes\t\t= 1;\n    bmInfo->bmiHeader.biBitCount\t= (WORD)depth;\n    bmInfo->bmiHeader.biCompression\t= BI_RGB;\n    bmInfo->bmiHeader.biSizeImage\t= 0;\n    bmInfo->bmiHeader.biXPelsPerMeter\t= 0;\n    bmInfo->bmiHeader.biYPelsPerMeter\t= 0;\n    bmInfo->bmiHeader.biClrUsed\t\t= 0;\n    bmInfo->bmiHeader.biClrImportant\t= 0;\n\n    if (depth == 1) {\n\tunsigned char *p, *pend;\n\n\tGetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);\n\tdata = (unsigned char *)Tcl_Alloc(bmInfo->bmiHeader.biSizeImage);\n\tif (!data) {\n\t    /* printf(\"Failed to allocate data area for XImage.\\n\"); */\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tret_image = XCreateImage(display, NULL, depth, ZPixmap, 0, (char *) data,\n\t\twidth, height, 32, (int) ((width + 31) >> 3) & ~1);\n\tif (ret_image == NULL) {\n\t    Tcl_Free(data);\n\t    goto cleanup;\n\t}\n\n\t/*\n\t * Get the BITMAP info into the Image.\n\t */\n\n\tif (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,\n\t\tDIB_PAL_COLORS) == 0) {\n\t    Tcl_Free(ret_image->data);\n\t    Tcl_Free(ret_image);\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tp = data;\n\tpend = data + bmInfo->bmiHeader.biSizeImage;\n\twhile (p < pend) {\n\t    *p = ~*p;\n\t    p++;\n\t}\n    } else if (depth == 8) {\n\tunsigned short *palette;\n\tunsigned int i;\n\tunsigned char *p;\n\n\tGetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);\n\tdata = (unsigned char *)Tcl_Alloc(bmInfo->bmiHeader.biSizeImage);\n\tif (!data) {\n\t    /* printf(\"Failed to allocate data area for XImage.\\n\"); */\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tret_image = XCreateImage(display, NULL, 8, ZPixmap, 0, (char *) data,\n\t\twidth, height, 8, (int) width);\n\tif (ret_image == NULL) {\n\t    Tcl_Free(data);\n\t    goto cleanup;\n\t}\n\n\t/*\n\t * Get the BITMAP info into the Image.\n\t */\n\n\tif (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,\n\t\tDIB_PAL_COLORS) == 0) {\n\t    Tcl_Free(ret_image->data);\n\t    Tcl_Free(ret_image);\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tp = data;\n\tpalette = (unsigned short *) bmInfo->bmiColors;\n\tfor (i = 0; i < bmInfo->bmiHeader.biSizeImage; i++, p++) {\n\t    *p = (unsigned char) palette[*p];\n\t}\n    } else if (depth == 16) {\n\tGetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);\n\tdata = (unsigned char *)Tcl_Alloc(bmInfo->bmiHeader.biSizeImage);\n\tif (!data) {\n\t    /* printf(\"Failed to allocate data area for XImage.\\n\"); */\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tret_image = XCreateImage(display, NULL, 16, ZPixmap, 0, (char *) data,\n\t\twidth, height, 16, 0 /* will be calc'ed from bitmap_pad */);\n\tif (ret_image == NULL) {\n\t    Tcl_Free(data);\n\t    goto cleanup;\n\t}\n\n\t/*\n\t * Get the BITMAP info directly into the Image.\n\t */\n\n\tif (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,\n\t\tDIB_RGB_COLORS) == 0) {\n\t    Tcl_Free(ret_image->data);\n\t    Tcl_Free(ret_image);\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n    } else {\n\tGetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);\n\tdata = (unsigned char *)Tcl_Alloc(width * height * 4);\n\tif (!data) {\n\t    /* printf(\"Failed to allocate data area for XImage.\\n\"); */\n\t    ret_image = NULL;\n\t    goto cleanup;\n\t}\n\tret_image = XCreateImage(display, NULL, 32, ZPixmap, 0, (char *) data,\n\t\twidth, height, 0, (int) width * 4);\n\tif (ret_image == NULL) {\n\t    Tcl_Free(data);\n\t    goto cleanup;\n\t}\n\n\tif (depth <= 24) {\n\t    /*\n\t     * This used to handle 16 and 24 bpp, but now just handles 24. It\n\t     * can likely be optimized for that. -- hobbs\n\t     */\n\n\t    unsigned char *smallBitData, *smallBitBase, *bigBitData;\n\t    unsigned int byte_width, h, w;\n\n\t    byte_width = ((width * 3 + 3) & ~(unsigned)3);\n\t    smallBitBase = (unsigned char *)Tcl_Alloc(byte_width * height);\n\t    if (!smallBitBase) {\n\t\tTcl_Free(ret_image->data);\n\t\tTcl_Free(ret_image);\n\t\tret_image = NULL;\n\t\tgoto cleanup;\n\t    }\n\t    smallBitData = smallBitBase;\n\n\t    /*\n\t     * Get the BITMAP info into the Image.\n\t     */\n\n\t    if (GetDIBits(hdcMem, hbmp, 0, height, smallBitData, bmInfo,\n\t\t    DIB_RGB_COLORS) == 0) {\n\t\tTcl_Free(ret_image->data);\n\t\tTcl_Free(ret_image);\n\t\tTcl_Free(smallBitBase);\n\t\tret_image = NULL;\n\t\tgoto cleanup;\n\t    }\n\n\t    /*\n\t     * Copy the 24 Bit Pixmap to a 32-Bit one.\n\t     */\n\n\t    for (h = 0; h < height; h++) {\n\t\tbigBitData   = (unsigned char *) ret_image->data + h * ret_image->bytes_per_line;\n\t\tsmallBitData = smallBitBase + h * byte_width;\n\n\t\tfor (w = 0; w < width; w++) {\n\t\t    *bigBitData++ = ((*smallBitData++));\n\t\t    *bigBitData++ = ((*smallBitData++));\n\t\t    *bigBitData++ = ((*smallBitData++));\n\t\t    *bigBitData++ = 0;\n\t\t}\n\t    }\n\n\t    /*\n\t     * Free the Device contexts, and the Bitmap.\n\t     */\n\n\t    Tcl_Free(smallBitBase);\n\t} else {\n\t    /*\n\t     * Get the BITMAP info directly into the Image.\n\t     */\n\n\t    if (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,\n\t\t    DIB_RGB_COLORS) == 0) {\n\t\tTcl_Free(ret_image->data);\n\t\tTcl_Free(ret_image);\n\t\tret_image = NULL;\n\t\tgoto cleanup;\n\t    }\n\t}\n    }\n\n  cleanup:\n    if (bmInfo) {\n\tTcl_Free(bmInfo);\n    }\n    if (hPal) {\n\tSelectPalette(hdcMem, hPalPrev1, FALSE);\n    }\n    DeleteDC(hdcMem);\n    DeleteObject(hbmp);\n\n    return ret_image;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetImage --\n *\n *\tThis function copies data from a pixmap or window into an XImage.\n *\n * Results:\n *\tReturns a newly allocated image containing the data from the given\n *\trectangle of the given drawable.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nXImage *\nXGetImage(\n    Display* display,\n    Drawable d,\n    int x, int y,\n    unsigned int width, unsigned int height,\n    unsigned long plane_mask,\n    int\tformat)\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *)d;\n    XImage *imagePtr;\n    HDC dc;\n\n    LastKnownRequestProcessed(display)++;\n\n    if (twdPtr == NULL) {\n\t/*\n\t * Avoid unmapped windows or bad drawables\n\t */\n\n\treturn NULL;\n    }\n\n    if (twdPtr->type != TWD_BITMAP) {\n\t/*\n\t * This handles TWD_WINDOW or TWD_WINDC, always creating a 32bit\n\t * image. If the window being copied isn't visible (unmapped or\n\t * obscured), we quietly stop copying (no user error). The user will\n\t * see black where the widget should be. This branch is likely\n\t * followed in favor of XGetImageZPixmap as postscript printed widgets\n\t * require RGB data.\n\t */\n\n\tTkWinDCState state;\n\tunsigned int xx, yy, size;\n\tCOLORREF pixel;\n\n\tdc = TkWinGetDrawableDC(display, d, &state);\n\n\timagePtr = XCreateImage(display, NULL, 32, format, 0, NULL,\n\t\twidth, height, 32, 0);\n\tsize = imagePtr->bytes_per_line * imagePtr->height;\n\timagePtr->data = (char *)Tcl_Alloc(size);\n\tmemset(imagePtr->data, 0, size);\n\n\tfor (yy = 0; yy < height; yy++) {\n\t    for (xx = 0; xx < width; xx++) {\n\t\tpixel = GetPixel(dc, x+(int)xx, y+(int)yy);\n\t\tif (pixel == CLR_INVALID) {\n\t\t    break;\n\t\t}\n\t\tPutPixel(imagePtr, (int) xx, (int) yy, pixel);\n\t    }\n\t}\n\n\tTkWinReleaseDrawableDC(d, dc, &state);\n    } else if (format == ZPixmap) {\n\t/*\n\t * This actually handles most TWD_WINDOW requests, but it varies from\n\t * the above in that it really does a screen capture of an area, which\n\t * is consistent with the Unix behavior, but does not appear to handle\n\t * all bit depths correctly. -- hobbs\n\t */\n\n\timagePtr = XGetImageZPixmap(display, d, x, y,\n\t\twidth, height, plane_mask, format);\n    } else {\n\tconst char *errMsg = NULL;\n\tchar infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];\n\tBITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;\n\n\tif (twdPtr->bitmap.handle == NULL) {\n\t    errMsg = \"XGetImage: not implemented for empty bitmap handles\";\n\t} else if (format != XYPixmap) {\n\t    errMsg = \"XGetImage: not implemented for format != XYPixmap\";\n\t} else if (plane_mask != 1) {\n\t    errMsg = \"XGetImage: not implemented for plane_mask != 1\";\n\t}\n\tif (errMsg != NULL) {\n\t    /*\n\t     * Do a soft warning for the unsupported XGetImage types.\n\t     */\n\n\t    TkpDisplayWarning(errMsg, \"XGetImage Failure\");\n\t    return NULL;\n\t}\n\n\timagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,\n\t\twidth, height, 32, 0);\n\timagePtr->data = (char *)Tcl_Alloc(imagePtr->bytes_per_line * imagePtr->height);\n\n\tdc = GetDC(NULL);\n\n\tGetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,\n\t\tinfoPtr, DIB_RGB_COLORS);\n\n\tinfoPtr->bmiHeader.biSize\t\t= sizeof(BITMAPINFOHEADER);\n\tinfoPtr->bmiHeader.biWidth\t\t= width;\n\tinfoPtr->bmiHeader.biHeight\t\t= -(LONG)height;\n\tinfoPtr->bmiHeader.biPlanes\t\t= 1;\n\tinfoPtr->bmiHeader.biBitCount\t\t= 1;\n\tinfoPtr->bmiHeader.biCompression\t= BI_RGB;\n\tinfoPtr->bmiHeader.biSizeImage\t\t= 0;\n\tinfoPtr->bmiHeader.biXPelsPerMeter\t= 0;\n\tinfoPtr->bmiHeader.biYPelsPerMeter\t= 0;\n\tinfoPtr->bmiHeader.biClrUsed\t\t= 0;\n\tinfoPtr->bmiHeader.biClrImportant\t= 0;\n\n\tGetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,\n\t\tinfoPtr, DIB_RGB_COLORS);\n\tReleaseDC(NULL, dc);\n    }\n\n    return imagePtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinInit.c",
    "content": "/*\n * tkWinInit.c --\n *\n *\tThis file contains Windows-specific interpreter initialization\n *\tfunctions.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\nextern int TkWinAccessiblity_Init(Tcl_Interp *interp);\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpInit --\n *\n *\tPerforms Windows-specific interpreter initialization related to the\n *      tk_library variable.\n *\n * Results:\n *\tA standard Tcl completion code (TCL_OK or TCL_ERROR). Also leaves\n *\tinformation in the interp's result.\n *\n * Side effects:\n *\tSets \"tk_library\" Tcl variable, runs \"tk.tcl\" script.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpInit(\n    Tcl_Interp *interp)\n{\n    /*\n     * This is necessary for static initialization, and is ok otherwise\n     * because TkWinXInit flips a static bit to do its work just once. Also,\n     * initialize accessibility, printing and systray API's here.\n     */\n\n    WinIcoInit(interp);\n    Winprint_Init(interp);\n    TkWinXInit(Tk_GetHINSTANCE());\n    Icu_Init(interp);\n    TkWinAccessiblity_Init(interp);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetAppName --\n *\n *\tRetrieves the name of the current application from a platform specific\n *\tlocation. For Windows, the application name is the root of the tail of\n *\tthe path contained in the tcl variable argv0.\n *\n * Results:\n *\tReturns the application name in the given Tcl_DString.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpGetAppName(\n    Tcl_Interp *interp,\n    Tcl_DString *namePtr)\t/* A previously initialized Tcl_DString. */\n{\n    Tcl_Size argc, namelength;\n    const char **argv = NULL, *name, *p;\n\n    name = Tcl_GetVar2(interp, \"argv0\", NULL, TCL_GLOBAL_ONLY);\n    namelength = -1;\n    if (name != NULL) {\n\tTcl_SplitPath(name, &argc, &argv);\n\tif (argc > 0) {\n\t    name = argv[argc-1];\n\t    p = strrchr(name, '.');\n\t    if (p != NULL) {\n\t\tnamelength = p - name;\n\t    }\n\t} else {\n\t    name = NULL;\n\t}\n    }\n    if ((name == NULL) || (*name == 0)) {\n\tname = \"tk\";\n\tnamelength = -1;\n    }\n    Tcl_DStringAppend(namePtr, name, namelength);\n    if (argv != NULL) {\n\tTcl_Free(argv);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDisplayWarning --\n *\n *\tThis routines is called from Tk_Main to display warning messages that\n *\toccur during startup.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDisplays a message box.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDisplayWarning(\n    const char *msg,\t\t/* Message to be displayed. */\n    const char *title)\t\t/* Title of warning. */\n{\n#define TK_MAX_WARN_LEN 1024\n    WCHAR titleString[TK_MAX_WARN_LEN];\n    WCHAR *msgString; /* points to titleString, just after title, leaving space for \": \" */\n    int len; /* size of title, including terminating NULL */\n\n    /* If running on Cygwin and we have a stderr channel, use it. */\n#if !defined(STATIC_BUILD)\n\tif (tclStubsPtr->tcl_CreateFileHandler) {\n\tTcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);\n\tif (errChannel) {\n\t    Tcl_WriteChars(errChannel, title, TCL_INDEX_NONE);\n\t    Tcl_WriteChars(errChannel, \": \", 2);\n\t    Tcl_WriteChars(errChannel, msg, TCL_INDEX_NONE);\n\t    Tcl_WriteChars(errChannel, \"\\n\", 1);\n\t    return;\n\t}\n    }\n#endif /* !STATIC_BUILD */\n\n    len = MultiByteToWideChar(CP_UTF8, 0, title, -1, titleString, TK_MAX_WARN_LEN);\n    msgString = &titleString[len + 1];\n    titleString[TK_MAX_WARN_LEN - 1] = '\\0';\n    MultiByteToWideChar(CP_UTF8, 0, msg, -1, msgString, (TK_MAX_WARN_LEN - 1) - len);\n    /*\n     * Truncate MessageBox string if it is too long to not overflow the screen\n     * and cause possible oversized window error.\n     */\n    if (titleString[TK_MAX_WARN_LEN - 1] != '\\0') {\n\tmemcpy(titleString + (TK_MAX_WARN_LEN - 5), L\" ...\", 5 * sizeof(WCHAR));\n    }\n    if (IsDebuggerPresent()) {\n\ttitleString[len - 1] = ':';\n\ttitleString[len] = ' ';\n\tOutputDebugStringW(titleString);\n    } else {\n\ttitleString[len - 1] = '\\0';\n\tMessageBoxW(NULL, msgString, titleString,\n\t\tMB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL\n\t\t| MB_SETFOREGROUND | MB_TOPMOST);\n    }\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * Win32ErrorObj --\n *\n *\tReturns a string object containing text from a COM or Win32 error code\n *\n * Results:\n *\tA Tcl_Obj containing the Win32 error message.\n *\n * Side effects:\n *\tRemoved the error message from the COM threads error object.\n *\n * ----------------------------------------------------------------------\n */\n\nTcl_Obj*\nTkWin32ErrorObj(\n    HRESULT hrError)\n{\n    LPWSTR lpBuffer = NULL, p = NULL;\n    WCHAR  sBuffer[30];\n    Tcl_Obj* errPtr = NULL;\n    Tcl_DString ds;\n\n    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM\n\t    | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError,\n\t    LANG_NEUTRAL, (LPWSTR)&lpBuffer, 0, NULL);\n\n    if (lpBuffer == NULL) {\n\tlpBuffer = sBuffer;\n\twsprintfW(sBuffer, L\"Error Code: %08lX\", hrError);\n    }\n\n    if ((p = wcsrchr(lpBuffer, '\\r')) != NULL) {\n\t*p = '\\0';\n    }\n\n    Tcl_DStringInit(&ds);\n    Tcl_WCharToUtfDString(lpBuffer, wcslen(lpBuffer), &ds);\n    errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n    Tcl_DStringFree(&ds);\n\n    if (lpBuffer != sBuffer) {\n\tLocalFree((HLOCAL)lpBuffer);\n    }\n\n    return errPtr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinInt.h",
    "content": "/*\n * tkWinInt.h --\n *\n *\tThis file contains declarations that are shared among the\n *\tWindows-specific parts of Tk, but aren't used by the rest of Tk.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _TKWININT\n#define _TKWININT\n\n/*\n * Include platform specific public interfaces as the very first step. This is\n * necessary because definitions provided by subsequent header files depend on\n * the interface versions defined in tkWin.h\n */\n\n#ifndef _TKWIN\n#include \"tkWin.h\"\n#endif\n\n#ifndef _TKINT\n#include \"tkInt.h\"\n#endif\n\n/*\n * Define constants missing from older Win32 SDK header files.\n */\n\n#ifndef WS_EX_TOOLWINDOW\n#define WS_EX_TOOLWINDOW\t0x00000080L\n#endif\n#ifndef SPI_SETKEYBOARDCUES\n#define SPI_SETKEYBOARDCUES 0x100B\n#endif\n\n/*\n * The TkWinDCState is used to save the state of a device context so that it\n * can be restored later.\n */\n\ntypedef struct TkWinDCState {\n    HPALETTE palette;\n    int bkmode;\n} TkWinDCState;\n\n/*\n * The TkWinDrawable is the internal implementation of an X Drawable (either a\n * Window or a Pixmap). The following constants define the valid Drawable\n * types.\n */\n\n#define TWD_BITMAP\t1\n#define TWD_WINDOW\t2\n#define TWD_WINDC\t3\n\ntypedef struct {\n    int type;\n    HWND handle;\n    TkWindow *winPtr;\n} TkWinWindow;\n\ntypedef struct {\n    int type;\n    HBITMAP handle;\n    Colormap colormap;\n    int depth;\n} TkWinBitmap;\n\ntypedef struct {\n    int type;\n    HDC hdc;\n}TkWinDC;\n\ntypedef union {\n    int type;\n    TkWinWindow window;\n    TkWinBitmap bitmap;\n    TkWinDC winDC;\n} TkWinDrawable;\n\n/*\n * The following macros are used to retrieve internal values from a Drawable.\n */\n\n#define TkWinGetHWND(w)\t\t(((TkWinDrawable *) w)->window.handle)\n#define TkWinGetWinPtr(w)\t(((TkWinDrawable *) w)->window.winPtr)\n#define TkWinGetHBITMAP(w)\t(((TkWinDrawable *) w)->bitmap.handle)\n#define TkWinGetColormap(w)\t(((TkWinDrawable *) w)->bitmap.colormap)\n#define TkWinGetHDC(w)\t\t(((TkWinDrawable *) w)->winDC.hdc)\n\n/*\n * The following structure is used to encapsulate palette information.\n */\n\ntypedef struct {\n    HPALETTE palette;\t\t/* Palette handle used when drawing. */\n    UINT size;\t\t\t/* Number of entries in the palette. */\n    int stale;\t\t\t/* 1 if palette needs to be realized,\n\t\t\t\t * otherwise 0. If the palette is stale, then\n\t\t\t\t * an idle handler is scheduled to realize the\n\t\t\t\t * palette. */\n    Tcl_HashTable refCounts;\t/* Hash table of palette entry reference\n\t\t\t\t * counts indexed by pixel value. */\n} TkWinColormap;\n\n/*\n * The following macro retrieves the Win32 palette from a colormap.\n */\n\n#define TkWinGetPalette(colormap) (((TkWinColormap *) colormap)->palette)\n\n/*\n * The following macros define the class names for Tk Window types.\n */\n\n#define TK_WIN_TOPLEVEL_CLASS_NAME L\"TkTopLevel\"\n#define TK_WIN_CHILD_CLASS_NAME L\"TkChild\"\n\n/*\n * The following variable is a translation table between X gc functions and\n * Win32 raster and BitBlt op modes.\n */\n\nMODULE_SCOPE const int tkpWinRopModes[];\nMODULE_SCOPE const int tkpWinBltModes[];\n\n/*\n * The following defines are used with TkWinGetBorderPixels to get the extra 2\n * border colors from a Tk_3DBorder.\n */\n\n#define TK_3D_LIGHT2 TK_3D_DARK_GC+1\n#define TK_3D_DARK2 TK_3D_DARK_GC+2\n\n/*\n * Internal functions used by more than one source file.\n */\n\n#include \"tkIntPlatDecls.h\"  /* IWYU pragma: export */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n/*\n * Special proc needed as tsd accessor function between\n * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard\n */\n\nMODULE_SCOPE void TkWinUpdatingClipboard(int mode);\n\n/*\n * Used by tkWinDialog.c to associate the right icon with tk_messageBox\n */\n\nMODULE_SCOPE HICON TkWinGetIcon(Tk_Window tkw, DWORD iconsize);\n\n/*\n * Used by tkWinX.c on for certain system display change messages and cleanup\n * up containers\n */\n\nMODULE_SCOPE void TkWinDisplayChanged(Display *display);\nMODULE_SCOPE void TkWinCleanupContainerList(void);\nMODULE_SCOPE LRESULT TkWinEmbeddedEventProc(HWND, UINT, WPARAM, LPARAM);\nMODULE_SCOPE unsigned int TkWinGetModifierState(void);\nMODULE_SCOPE HPALETTE TkWinGetSystemPalette(void);\nMODULE_SCOPE int TkWinIndexOfColor(XColor *colorPtr);\nMODULE_SCOPE HWND TkWinGetWrapperWindow(Tk_Window tkwin);\nMODULE_SCOPE HPALETTE TkWinSelectPalette(HDC, Colormap);\n\n\n/*\n * Used by tkWinWm.c for embedded menu handling.\n */\n\nMODULE_SCOPE HWND TkGetMenuHWND(Tk_Window tkwin);\nMODULE_SCOPE HWND TkGetEmbeddedMenuHWND(Tk_Window tkwin);\nMODULE_SCOPE void TkWinCancelMouseTimer(void);\nMODULE_SCOPE int TkWinHandleMenuEvent(HWND *, UINT *, WPARAM *, LPARAM *, LRESULT *);\nMODULE_SCOPE void TkWinSetMenu(Tk_Window, HMENU);\nMODULE_SCOPE Tcl_Obj *TkWinGetMenuSystemDefault(Tk_Window, const char *, const char *);\n\n\n/*\n * The following allows us to cache these encoding for multiple functions.\n */\n\n\nMODULE_SCOPE Tcl_Encoding\tTkWinGetKeyInputEncoding(void);\nMODULE_SCOPE Tcl_Encoding\tTkWinGetUnicodeEncoding(void);\nMODULE_SCOPE void\t\tTkWinSetupSystemFonts(TkMainInfo *mainPtr);\n\n/*\n * Values used to be returned by TkWinGetPlatformTheme.\n */\n\n#ifndef TK_NO_DEPRECATED\n#   define TK_THEME_WIN_CLASSIC    1\n#   define TK_THEME_WIN_XP         2\n#   define TK_THEME_WIN_VISTA      3\n#endif\n\n/*\n * The following is implemented in tkWinWm and used by tkWinEmbed.c\n */\n\nMODULE_SCOPE void\tTkpWinToplevelWithDraw(TkWindow *winPtr);\nMODULE_SCOPE void\tTkpWinToplevelIconify(TkWindow *winPtr);\nMODULE_SCOPE void\tTkpWinToplevelDeiconify(TkWindow *winPtr);\nMODULE_SCOPE long\tTkpWinToplevelIsControlledByWm(TkWindow *winPtr);\nMODULE_SCOPE long\tTkpWinToplevelMove(TkWindow *winPtr, int x, int y);\nMODULE_SCOPE long\tTkpWinToplevelOverrideRedirect(TkWindow *winPtr,\n\t\t\t    int reqValue);\nMODULE_SCOPE void\tTkpWinToplevelDetachWindow(TkWindow *winPtr);\nMODULE_SCOPE int\tTkpWmGetState(TkWindow *winPtr);\n\nMODULE_SCOPE int\tTkTranslateWinEvent(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam, LRESULT *result);\nMODULE_SCOPE void\tTkWinPointerEvent(HWND hwnd, int x, int y);\n\n/*\n * The following is implemented in tkWinPointer.c and also used in tkWinWindow.c\n */\n\nMODULE_SCOPE void\tTkSetCursorPos(int x, int y);\n\n/*\n * The following is implemented in tkWinSysTray.c\n */\n\nMODULE_SCOPE  int\tWinIcoInit (Tcl_Interp* interp);\n\n/*\n * The following is implemented in tkWinGDI.c\n */\n\nMODULE_SCOPE  int\tWinprint_Init(Tcl_Interp* interp);\n\n/*\n * The following is implemented in tkWinDraw.c and used in tkUtil.c\n */\n\nMODULE_SCOPE  void\tTkWinDrawDottedRect(Display *disp, Drawable d,\n\t\t\t    long pixel, int x, int y, int width, int height);\n\n/*\n * Common routines used in Windows implementation\n */\nMODULE_SCOPE Tcl_Obj *\tTkWin32ErrorObj(HRESULT hrError);\n\n\n/*\n * The following functions are not present in old versions of Windows\n * API headers but are used in the Tk source to ensure 64bit\n * compatibility.\n */\n\n#ifndef GetClassLongPtr\n#   define GetClassLongPtrW\tGetClassLongW\n#   define SetClassLongPtrW\tSetClassLongW\n#endif /* !GetClassLongPtr */\n#ifndef GCLP_HICON\n#   define GCLP_HICON\t\tGCL_HICON\n#endif /* !GCLP_HICON */\n#ifndef GCLP_HICONSM\n#   define GCLP_HICONSM\t\t(-34)\n#endif /* !GCLP_HICONSM */\n\n#ifndef GetWindowLongPtr\n#   define GetWindowLongPtrW\tGetWindowLongW\n#   define SetWindowLongPtrW\tSetWindowLongW\n#endif /* !GetWindowLongPtr */\n#ifndef GWLP_WNDPROC\n#define GWLP_WNDPROC\t\tGWL_WNDPROC\n#define GWLP_HINSTANCE\t\tGWL_HINSTANCE\n#define GWLP_HWNDPARENT\t\tGWL_HWNDPARENT\n#define GWLP_USERDATA\t\tGWL_USERDATA\n#define GWLP_ID\t\t\tGWL_ID\n#endif /* !GWLP_WNDPROC */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _TKWININT */\n"
  },
  {
    "path": "win/tkWinKey.c",
    "content": "/*\n * tkWinKey.c --\n *\n *\tThis file contains X emulation routines for keyboard related\n *\tfunctions.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"X11/XF86keysym.h\"\n\n/*\n * The keymap table holds mappings of Windows keycodes to X keysyms. If\n * Windows ever comes along and changes the value of their keycodes, this will\n * break all kinds of things. However, this table lookup is much faster than\n * the alternative, in which we walked a list of keycodes looking for a match.\n * Since this lookup is performed for every Windows keypress event, it seems\n * like a worthwhile improvement to use the table.\n */\n\n#define MAX_KEYCODE 183 /* VK_LAUNCH_APP2 is the last entry in our table below */\n/* cf. https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx */\n\nstatic const KeySym keymap[] = {\n    NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol, /*0 0x0*/\n    NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab, /*5 0x5*/\n    NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol, /*10 0xA*/\n    NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause, /*15 0xE*/\n    XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*20 0x14*/\n    NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol, /*25 0x19*/\n    NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next, /*30 0x1E*/\n    XK_End, XK_Home, XK_Left, XK_Up, XK_Right, /*35 0x23*/\n    XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol, /*40 0x28*/\n    XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol, /*45 0x2D*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*50 0x32*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*55 0x37*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*60 0x3C*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*65 0x41*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*70 0x46*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*75 0x4B*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*80 0x50*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*85 0x55*/\n    NoSymbol, XK_Super_L, XK_Super_R, XK_Menu, NoSymbol, /*90 0x5A*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*95 0x5F*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*100 0x64*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*105 0x69*/\n    NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3, /*110 0x6E*/\n    XK_F4, XK_F5, XK_F6, XK_F7, XK_F8, /*115 0x73*/\n    XK_F9, XK_F10, XK_F11, XK_F12, XK_F13, /*120 0x78*/\n    XK_F14, XK_F15, XK_F16, XK_F17, XK_F18, /*125 0x7D*/\n    XK_F19, XK_F20, XK_F21, XK_F22, XK_F23, /*130 0x82*/\n    XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*135 0x87*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock, /*140 0x8C*/\n    XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*145 0x91*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*150 0x96*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*155 0x9B*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*160 0xA0*/\n    NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*165 0xA5*/\n    NoSymbol, NoSymbol, NoSymbol, XF86XK_AudioMute, XF86XK_AudioLowerVolume, /*170 0xAA*/\n    XF86XK_AudioRaiseVolume, XF86XK_AudioNext, XF86XK_AudioPrev, XF86XK_AudioStop, XF86XK_AudioPlay, /*175 0xAF*/\n    XF86XK_Mail, XF86XK_AudioMedia, XF86XK_Launch0, XF86XK_Launch1  /*180 0xB4*/\n};\n\n/*\n * Prototypes for local functions defined in this file:\n */\n\nstatic KeySym\t\tKeycodeToKeysym(unsigned int keycode,\n\t\t\t    int state, int noascii);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetString --\n *\n *\tRetrieve the UTF string equivalent for the given keyboard event.\n *\n * Results:\n *\tReturns the UTF string.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkpGetString(\n    TCL_UNUSED(TkWindow *),\t\t/* Window where event occurred: needed to get\n\t\t\t\t * input context. */\n    XEvent *eventPtr,\t\t/* X keyboard event. */\n    Tcl_DString *dsPtr)\t\t/* Uninitialized or empty string to hold\n\t\t\t\t * result. */\n{\n    XKeyEvent *keyEv = &eventPtr->xkey;\n    Tcl_Size len;\n    char buf[6];\n\n    Tcl_DStringInit(dsPtr);\n    if (keyEv->send_event == -1) {\n\tTkKeyEvent *ev = (TkKeyEvent *)keyEv;\n\tif (ev->nbytes > 0) {\n\t    (void)Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(),\n\t\t    ev->trans_chars, ev->nbytes, dsPtr);\n\t}\n    } else if (keyEv->send_event == -3) {\n\n\t/*\n\t * Special case for WM_UNICHAR and win2000 multilingual IME input\n\t */\n\n\tlen = Tcl_UniCharToUtf(keyEv->keycode, buf);\n\tTcl_DStringAppend(dsPtr, buf, len);\n    } else {\n\t/*\n\t * This is an event generated from generic code. It has no nchars or\n\t * trans_chars members.\n\t */\n\n\tKeySym keysym = KeycodeToKeysym(keyEv->keycode, keyEv->state, 0);\n\n\tif (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))\n\t\t|| (keysym == XK_Return) || (keysym == XK_Tab)) {\n\t    len = Tcl_UniCharToUtf(keysym & 255, buf);\n\t    Tcl_DStringAppend(dsPtr, buf, len);\n\t}\n    }\n    return Tcl_DStringValue(dsPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XkbKeycodeToKeysym --\n *\n *\tTranslate from a system-dependent keycode to a system-independent\n *\tkeysym.\n *\n * Results:\n *\tReturns the translated keysym, or NoSymbol on failure.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nXkbKeycodeToKeysym(\n    TCL_UNUSED(Display *),\n    unsigned int keycode,\n    TCL_UNUSED(int),\n    int index)\n{\n    int state = 0;\n\n    if (index & 0x01) {\n\tstate |= ShiftMask;\n    }\n    return KeycodeToKeysym(keycode, state, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * KeycodeToKeysym --\n *\n *\tTranslate from a system-dependent keycode to a system-independent\n *\tkeysym.\n *\n * Results:\n *\tReturns the translated keysym, or NoSymbol on failure.\n *\n * Side effects:\n *\tIt may affect the internal state of the keyboard, such as remembered\n *\tdead key or lock indicator lamps.\n *\n *----------------------------------------------------------------------\n */\n\nstatic KeySym\nKeycodeToKeysym(\n    unsigned int keycode,\n    int state,\n    int noascii)\n{\n    BYTE keys[256];\n    int result, deadkey, shift;\n    WCHAR buf[4];\n    unsigned int scancode = MapVirtualKeyW(keycode, 0);\n\n    /*\n     * Do not run keycodes of lock keys through ToUnicode(). One of ToUnicode()'s\n     * side effects is to handle the lights on the keyboard, and we don't want\n     * to mess that up.\n     */\n\n    if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||\n\t    keycode == VK_NUMLOCK) {\n\tgoto skipToUnicode;\n    }\n\n    /*\n     * Use MapVirtualKeyW() to detect some dead keys.\n     */\n\n    if (MapVirtualKeyW(keycode, 2) > 0x7fffUL) {\n\treturn XK_Multi_key;\n    }\n\n    /*\n     * Set up a keyboard with correct modifiers\n     */\n\n    memset(keys, 0, 256);\n    if (state & ShiftMask) {\n\tkeys[VK_SHIFT] = 0x80;\n    }\n    if (state & ControlMask) {\n\tkeys[VK_CONTROL] = 0x80;\n    }\n    if (state & Mod2Mask) {\n\tkeys[VK_MENU] = 0x80;\n    }\n\n    /*\n     * Make sure all lock button info is correct so we don't mess up the\n     * lights.\n     */\n\n    if (state & LockMask) {\n\tkeys[VK_CAPITAL] = 1;\n    }\n    if (state & Mod3Mask) {\n\tkeys[VK_SCROLL] = 1;\n    }\n    if (state & Mod1Mask) {\n\tkeys[VK_NUMLOCK] = 1;\n    }\n\n    result = ToUnicode(keycode, scancode, keys, buf, 4, 0);\n\n    if (result < 0) {\n\t/*\n\t * Win95/98: This was a dead char, which is now remembered by the\n\t * keyboard. Call ToUnicode() again to forget it.\n\t * WinNT: This was a dead char, overwriting any previously remembered\n\t * key. Calling ToUnicode() again does not affect anything.\n\t */\n\n\tToUnicode(keycode, scancode, keys, buf, 4, 0);\n\treturn XK_Multi_key;\n    }\n\n    if (result == 2) {\n\t/*\n\t * This was a dead char, and there were one previously remembered by\n\t * the keyboard. Call ToUnicode() again with proper parameters to\n\t * restore it.\n\t *\n\t * Get information about the old char\n\t */\n\n\tdeadkey = VkKeyScanW(buf[0]);\n\tshift = deadkey >> 8;\n\tdeadkey &= 255;\n\tscancode = MapVirtualKeyW(deadkey, 0);\n\n\t/*\n\t * Set up a keyboard with proper modifier keys\n\t */\n\n\tmemset(keys, 0, 256);\n\tif (shift & 1) {\n\t    keys[VK_SHIFT] = 0x80;\n\t}\n\tif (shift & 2) {\n\t    keys[VK_CONTROL] = 0x80;\n\t}\n\tif (shift & 4) {\n\t    keys[VK_MENU] = 0x80;\n\t}\n\tToUnicode(deadkey, scancode, keys, buf, 4, 0);\n\treturn XK_Multi_key;\n    }\n\n    /*\n     * Keycode mapped to a valid Unicode character. Since the keysyms for\n     * alphanumeric characters map onto Unicode, we just return it.\n     *\n     * We treat 0x7F as a special case mostly for backwards compatibility. In\n     * versions of Tk<=8.2, Control-Backspace returned \"XK_BackSpace\" as the X\n     * Keysym. This was due to the fact that we did not initialize the keys\n     * array properly when we passed it to ToUnicode, above. We had previously\n     * not been setting the state bit for the Control key. When we fixed that,\n     * we found that Control-Backspace on Windows is interpreted as ASCII-127\n     * (0x7F), which corresponds to the Delete key.\n     *\n     * Upon discovering this, we realized we had two choices: return XK_Delete\n     * or return XK_BackSpace. If we returned XK_Delete, that could be\n     * considered \"more correct\" (although the correctness would be dependent\n     * on whether you believe that ToUnicode is doing the right thing in that\n     * case); however, this would break backwards compatibility, and worse, it\n     * would limit application programmers; they would effectively be unable\n     * to bind to <Control-Backspace> on Windows. We therefore chose instead\n     * to return XK_BackSpace (handled here by letting the code \"fall-through\"\n     * to the return statement below, which works because the keycode for this\n     * event is VK_BACKSPACE, and the keymap table maps that keycode to\n     * XK_BackSpace).\n     */\n\n    if (result == 1 && buf[0] >= 0x20 && buf[0] != 0x7F) {\n\treturn (KeySym) buf[0];\n    }\n\n    /*\n     * Keycode is a non-alphanumeric key, so we have to do the lookup.\n     */\n\n  skipToUnicode:\n    if (keycode > MAX_KEYCODE) {\n\treturn NoSymbol;\n    }\n    switch (keycode) {\n\t/*\n\t * Windows only gives us an undifferentiated VK_CONTROL code (for\n\t * example) when either Control key is pressed. To distinguish between\n\t * left and right, we use the Extended flag. Indeed, the right Control\n\t * and Alt (aka Menu) keys are such extended keys (which their left\n\t * counterparts are not).\n\t * Regarding the shift case, Windows does not set the Extended flag for\n\t * the neither the left nor the right shift key. As a consequence another\n\t * way to distinguish between the two keys is to query the state of one\n\t * of the two to determine which was actually pressed. So if the keycode\n\t * indicates Shift, do this extra test. If the right-side key was\n\t * pressed, return the appropriate keycode. Otherwise, we fall through\n\t * and rely on the keymap table to hold the correct keysym value.\n\t * Note: this little trick only works for KeyPress, not for KeyRelease,\n\t * for reasons stated in bug [2945130]\n\t */\n\n    case VK_CONTROL:\n\tif (state & EXTENDED_MASK) {\n\t    return XK_Control_R;\n\t}\n\tbreak;\n    case VK_SHIFT:\n\tif (GetKeyState(VK_RSHIFT) & 0x80) {\n\t    return XK_Shift_R;\n\t}\n\tbreak;\n    case VK_MENU:\n\tif (state & EXTENDED_MASK) {\n\t    return XK_Alt_R;\n\t}\n\tbreak;\n    }\n    return keymap[keycode];\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetKeySym --\n *\n *\tGiven an X KeyPress or KeyRelease event, map the keycode in the event\n *\tinto a KeySym.\n *\n * Results:\n *\tThe return value is the KeySym corresponding to eventPtr, or NoSymbol\n *\tif no matching Keysym could be found.\n *\n * Side effects:\n *\tIn the first call for a given display, keycode-to-KeySym maps get\n *\tloaded.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nTkpGetKeySym(\n    TkDisplay *dispPtr,\t\t/* Display in which to map keycode. */\n    XEvent *eventPtr)\t\t/* Description of X event. */\n{\n    KeySym sym;\n    int state = eventPtr->xkey.state;\n\n    /*\n     * Refresh the mapping information if it's stale\n     */\n\n    if (dispPtr->bindInfoStale) {\n\tTkpInitKeymapInfo(dispPtr);\n    }\n\n    sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);\n\n    /*\n     * Special handling: if this is a ctrl-alt or shifted key, and there is no\n     * keysym defined, try without the modifiers.\n     */\n\n    if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {\n\tstate &= ~(ControlMask | Mod2Mask);\n\tsym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);\n    }\n    if ((sym == NoSymbol) && (state & ShiftMask)) {\n\tstate &= ~ShiftMask;\n\tsym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);\n    }\n    return sym;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitKeymapInfo --\n *\n *\tThis function is invoked to scan keymap information to recompute stuff\n *\tthat's important for binding, such as the modifier key (if any) that\n *\tcorresponds to \"mode switch\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tKeymap-related information in dispPtr is updated.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitKeymapInfo(\n    TkDisplay *dispPtr)\t\t/* Display for which to recompute keymap\n\t\t\t\t * information. */\n{\n    XModifierKeymap *modMapPtr;\n    KeyCode *codePtr;\n    KeySym keysym;\n    int count, i, max;\n    Tcl_Size j, arraySize;\n#define KEYCODE_ARRAY_SIZE 20\n\n    dispPtr->bindInfoStale = 0;\n    modMapPtr = XGetModifierMapping(dispPtr->display);\n\n    /*\n     * Check the keycodes associated with the Lock modifier. If any of them is\n     * associated with the XK_Shift_Lock modifier, then Lock has to be\n     * interpreted as Shift Lock, not Caps Lock.\n     */\n\n    dispPtr->lockUsage = LU_IGNORE;\n    codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;\n    for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\tkeysym = KeycodeToKeysym(*codePtr, 0, 1);\n\tif (keysym == XK_Shift_Lock) {\n\t    dispPtr->lockUsage = LU_SHIFT;\n\t    break;\n\t}\n\tif (keysym == XK_Caps_Lock) {\n\t    dispPtr->lockUsage = LU_CAPS;\n\t    break;\n\t}\n    }\n\n    /*\n     * Look through the keycodes associated with modifiers to see if the the\n     * \"mode switch\", \"meta\", or \"alt\" keysyms are associated with any\n     * modifiers. If so, remember their modifier mask bits.\n     */\n\n    dispPtr->modeModMask = 0;\n    dispPtr->metaModMask = 0;\n    dispPtr->altModMask = 0;\n    codePtr = modMapPtr->modifiermap;\n    max = 8*modMapPtr->max_keypermod;\n    for (i = 0; i < max; i++, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\tkeysym = KeycodeToKeysym(*codePtr, 0, 1);\n\tif (keysym == XK_Mode_switch) {\n\t    dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n\tif ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {\n\t    dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n\tif ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {\n\t    dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);\n\t}\n    }\n\n    /*\n     * Create an array of the keycodes for all modifier keys.\n     */\n\n    if (dispPtr->modKeyCodes != NULL) {\n\tTcl_Free(dispPtr->modKeyCodes);\n    }\n    dispPtr->numModKeyCodes = 0;\n    arraySize = KEYCODE_ARRAY_SIZE;\n    dispPtr->modKeyCodes = (KeyCode *)Tcl_Alloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));\n    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {\n\tif (*codePtr == 0) {\n\t    continue;\n\t}\n\n\t/*\n\t * Make sure that the keycode isn't already in the array.\n\t */\n\n\tfor (j = 0; j < dispPtr->numModKeyCodes; j++) {\n\t    if (dispPtr->modKeyCodes[j] == *codePtr) {\n\t\tgoto nextModCode;\n\t    }\n\t}\n\tif (dispPtr->numModKeyCodes >= arraySize) {\n\t    KeyCode *newKey;\n\n\t    /*\n\t     * Ran out of space in the array; grow it.\n\t     */\n\n\t    arraySize *= 2;\n\t    newKey = (KeyCode *)Tcl_Alloc(arraySize * sizeof(KeyCode));\n\t    memcpy(newKey, dispPtr->modKeyCodes,\n\t\t    dispPtr->numModKeyCodes * sizeof(KeyCode));\n\t    Tcl_Free(dispPtr->modKeyCodes);\n\t    dispPtr->modKeyCodes = newKey;\n\t}\n\tdispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;\n\tdispPtr->numModKeyCodes++;\n\tnextModCode: continue;\n    }\n    XFreeModifiermap(modMapPtr);\n}\n\f\n/*\n * When mapping from a keysym to a keycode, need information about the\n * modifier state that should be used so that when they call XkbKeycodeToKeysym\n * taking into account the xkey.state, they will get back the original keysym.\n */\n\nvoid\nTkpSetKeycodeAndState(\n    TCL_UNUSED(Tk_Window),\n    KeySym keySym,\n    XEvent *eventPtr)\n{\n    int i;\n    SHORT result;\n    int shift;\n\n    eventPtr->xkey.keycode = 0;\n    if (keySym == NoSymbol) {\n\treturn;\n    }\n\n    /*\n     * We check our private map first for a virtual keycode, as VkKeyScan will\n     * return values that don't map to X for the \"extended\" Syms. This may be\n     * due to just casting problems below, but this works.\n     */\n\n    for (i = 0; i <= MAX_KEYCODE; i++) {\n\tif (keymap[i] == keySym) {\n\t    eventPtr->xkey.keycode = i;\n\t    return;\n\t}\n    }\n    if (keySym >= 0x20) {\n\tresult = VkKeyScanW((WCHAR) keySym);\n\tif (result != -1) {\n\t    shift = result >> 8;\n\t    if (shift & 1)\n\t\teventPtr->xkey.state |= ShiftMask;\n\t    if (shift & 2)\n\t\teventPtr->xkey.state |= ControlMask;\n\t    if (shift & 4)\n\t\teventPtr->xkey.state |= Mod2Mask;\n\t    eventPtr->xkey.keycode = (KeyCode) (result & 0xff);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XKeysymToKeycode --\n *\n *\tTranslate a keysym back into a keycode.\n *\n * Results:\n *\tReturns the keycode that would generate the specified keysym.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeyCode\nXKeysymToKeycode(\n    TCL_UNUSED(Display *),\n    KeySym keysym)\n{\n    int i;\n    SHORT result;\n\n    /*\n     * We check our private map first for a virtual keycode, as VkKeyScan will\n     * return values that don't map to X for the \"extended\" Syms. This may be\n     * due to just casting problems below, but this works.\n     */\n\n    if (keysym == NoSymbol) {\n\treturn 0;\n    }\n    for (i = 0; i <= MAX_KEYCODE; i++) {\n\tif (keymap[i] == keysym) {\n\t    return ((KeyCode) i);\n\t}\n    }\n    if (keysym >= 0x20) {\n\tresult = VkKeyScanW((WCHAR) keysym);\n\tif (result != -1) {\n\t    return (KeyCode) (result & 0xff);\n\t}\n    }\n\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetModifierMapping --\n *\n *\tFetch the current keycodes used as modifiers.\n *\n * Results:\n *\tReturns a new modifier map.\n *\n * Side effects:\n *\tAllocates a new modifier map data structure.\n *\n *----------------------------------------------------------------------\n */\n\nXModifierKeymap\t*\nXGetModifierMapping(\n    TCL_UNUSED(Display *))\n{\n    XModifierKeymap *map = (XModifierKeymap *)Tcl_Alloc(sizeof(XModifierKeymap));\n\n    map->max_keypermod = 1;\n    map->modifiermap = (KeyCode *)Tcl_Alloc(sizeof(KeyCode) * 8);\n    map->modifiermap[ShiftMapIndex] = VK_SHIFT;\n    map->modifiermap[LockMapIndex] = VK_CAPITAL;\n    map->modifiermap[ControlMapIndex] = VK_CONTROL;\n    map->modifiermap[Mod1MapIndex] = VK_NUMLOCK;\n    map->modifiermap[Mod2MapIndex] = VK_MENU;\n    map->modifiermap[Mod3MapIndex] = VK_SCROLL;\n    map->modifiermap[Mod4MapIndex] = 0;\n    map->modifiermap[Mod5MapIndex] = 0;\n    return map;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFreeModifiermap --\n *\n *\tDeallocate a modifier map that was created by XGetModifierMapping.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees the datastructure referenced by modmap.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFreeModifiermap(\n    XModifierKeymap *modmap)\n{\n    Tcl_Free(modmap->modifiermap);\n    Tcl_Free(modmap);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XStringToKeysym --\n *\n *\tTranslate a keysym name to the matching keysym.\n *\n * Results:\n *\tReturns the keysym. Since this is already handled by Tk's\n *\tStringToKeysym function, we just return NoSymbol.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nKeySym\nXStringToKeysym(\n    TCL_UNUSED(const char *))\n{\n    return NoSymbol;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XKeysymToString --\n *\n *\tConvert a keysym to character form.\n *\n * Results:\n *\tReturns NULL, since Tk will have handled this already.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nchar *\nXKeysymToString(\n    TCL_UNUSED(KeySym))\n{\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinMenu.c",
    "content": "/*\n * tkWinMenu.c --\n *\n *\tThis module implements the Windows platform-specific features of\n *\tmenus.\n *\n * Copyright © 1996-1998 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#define OEMRESOURCE\n#include \"tkWinInt.h\"\n#include \"tkMenu.h\"\n\n/*\n * The class of the window for popup menus.\n */\n\n#define MENU_CLASS_NAME\t\t\tL\"MenuWindowClass\"\n#define EMBEDDED_MENU_CLASS_NAME\tL\"EmbeddedMenuWindowClass\"\n\n/*\n * Used to align a windows bitmap inside a rectangle\n */\n\n#define ALIGN_BITMAP_LEFT\t0x00000001\n#define ALIGN_BITMAP_RIGHT\t0x00000002\n#define ALIGN_BITMAP_TOP\t0x00000004\n#define ALIGN_BITMAP_BOTTOM\t0x00000008\n\n\n/*\n * Platform-specific menu flags:\n *\n * MENU_SYSTEM_MENU\tNon-zero means that the Windows menu handle was\n *\t\t\tretrieved with GetSystemMenu and needs to be disposed\n *\t\t\tof specially.\n * MENU_RECONFIGURE_PENDING\n *\t\t\tNon-zero means that an idle handler has been set up to\n *\t\t\treconfigure the Windows menu handle for this menu.\n */\n\n#define MENU_SYSTEM_MENU\t\tMENU_PLATFORM_FLAG1\n#define MENU_RECONFIGURE_PENDING\tMENU_PLATFORM_FLAG2\n\n/*\n * ODS_NOACCEL flag forbids drawing accelerator cues (i.e. underlining labels)\n * on Windows 2000 and above.  The ODS_NOACCEL define is missing from mingw32\n * headers and undefined for _WIN32_WINNT < 0x0500 in Microsoft SDK.  We might\n * check for _WIN32_WINNT here, but I think it's not needed, as checking for\n * this flag does no harm on even on NT: reserved bits should be zero, and in\n * fact they are.\n */\n\n#ifndef ODS_NOACCEL\n#define ODS_NOACCEL 0x100\n#endif\n#ifndef SPI_GETKEYBOARDCUES\n#define SPI_GETKEYBOARDCUES             0x100A\n#endif\n#ifndef WM_UPDATEUISTATE\n#define WM_UPDATEUISTATE                0x0128\n#endif\n#ifndef UIS_SET\n#define UIS_SET                         1\n#endif\n#ifndef UIS_CLEAR\n#define UIS_CLEAR                       2\n#endif\n#ifndef UISF_HIDEACCEL\n#define UISF_HIDEACCEL                  2\n#endif\n\n#ifndef WM_UNINITMENUPOPUP\n#define WM_UNINITMENUPOPUP              0x0125\n#endif\n\nstatic int indicatorDimensions[2];\n\t\t\t\t/* The dimensions of the indicator space in a\n\t\t\t\t * menu entry. Calculated at init time to save\n\t\t\t\t * time. */\n\nstatic BOOL showMenuAccelerators;\n\ntypedef struct {\n    int inPostMenu;\t\t/* We cannot be re-entrant like X Windows. */\n    WORD lastCommandID;\t\t/* The last command ID we allocated. */\n    HWND menuHWND;\t\t/* A window to service popup-menu messages\n\t\t\t\t * in. */\n    HWND embeddedMenuHWND;\t/* A window to service embedded menu\n\t\t\t\t * messages */\n    int oldServiceMode;\t\t/* Used while processing a menu; we need to\n\t\t\t\t * set the event mode specially when we enter\n\t\t\t\t * the menu processing modal loop and reset it\n\t\t\t\t * when menus go away. */\n    TkMenu *modalMenuPtr;\t/* The menu we are processing inside the modal\n\t\t\t\t * loop. We need this to reset all of the\n\t\t\t\t * active items when menus go away since\n\t\t\t\t * Windows does not see fit to give this to us\n\t\t\t\t * when it sends its WM_MENUSELECT. */\n    Tcl_HashTable commandTable;\t/* A map of command ids to menu entries */\n    Tcl_HashTable winMenuTable;\t/* Need this to map HMENUs back to menuPtrs */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The following are default menu value strings.\n */\n\nstatic int defaultBorderWidth;\t/* The windows default border width. */\nstatic Tcl_DString menuFontDString;\n\t\t\t\t/* A buffer to store the default menu font\n\t\t\t\t * string. */\n/*\n * Forward declarations for functions defined later in this file:\n */\n\nstatic void\t\tDrawMenuEntryAccelerator(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    Tk_3DBorder activeBorder, int x, int y,\n\t\t\t    int width, int height);\nstatic void\t\tDrawMenuEntryBackground(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d,\n\t\t\t    Tk_3DBorder activeBorder, Tk_3DBorder bgBorder,\n\t\t\t    int x, int y, int width, int heigth);\nstatic void\t\tDrawMenuEntryIndicator(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Drawable d, GC gc,\n\t\t\t    GC indicatorGC, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int x, int y,\n\t\t\t    int width, int height);\nstatic void\t\tDrawMenuSeparator(TkMenu *menuPtr, TkMenuEntry *mePtr,\n\t\t\t    Drawable d, GC gc, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr,\n\t\t\t    int x, int y, int width, int height);\nstatic void\t\tDrawTearoffEntry(TkMenu *menuPtr, TkMenuEntry *mePtr,\n\t\t\t    Drawable d, GC gc, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int x, int y,\n\t\t\t    int width, int height);\nstatic void\t\tDrawMenuUnderline(TkMenu *menuPtr, TkMenuEntry *mePtr,\n\t\t\t    Drawable d, GC gc, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int x, int y,\n\t\t\t    int width, int height);\nstatic void\t\tDrawWindowsSystemBitmap(Display *display,\n\t\t\t    Drawable drawable, GC gc, const RECT *rectPtr,\n\t\t\t    int bitmapID, int alignFlags);\nstatic void\t\tFreeID(WORD commandID);\nstatic char *\t\tGetEntryText(TkMenu *menuPtr, TkMenuEntry *mePtr);\nstatic void\t\tGetMenuAccelGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int *widthPtr,\n\t\t\t    int *heightPtr);\nstatic void\t\tGetMenuLabelGeometry(TkMenuEntry *mePtr,\n\t\t\t    Tk_Font tkfont, const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetMenuIndicatorGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetMenuSeparatorGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr,\n\t\t\t    int *widthPtr, int *heightPtr);\nstatic void\t\tGetTearoffEntryGeometry(TkMenu *menuPtr,\n\t\t\t    TkMenuEntry *mePtr, Tk_Font tkfont,\n\t\t\t    const Tk_FontMetrics *fmPtr, int *widthPtr,\n\t\t\t    int *heightPtr);\nstatic int\t\tGetNewID(TkMenuEntry *mePtr, WORD *menuIDPtr);\nstatic Tcl_ObjCmdProc2 TkWinMenuKeyObjCmd;\nstatic void\t\tMenuSelectEvent(TkMenu *menuPtr);\nstatic void\t\tReconfigureWindowsMenu(void *clientData);\nstatic void\t\tRecursivelyClearActiveMenu(TkMenu *menuPtr);\nstatic void\t\tSetDefaults(int firstTime);\nstatic LRESULT CALLBACK\tTkWinMenuProc(HWND hwnd, UINT message, WPARAM wParam,\n\t\t\t    LPARAM lParam);\nstatic LRESULT CALLBACK\tTkWinEmbeddedMenuProc(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam);\n\f\nstatic inline void\nScheduleMenuReconfigure(\n    TkMenu *menuPtr)\n{\n    if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {\n\tmenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;\n\tTcl_DoWhenIdle(ReconfigureWindowsMenu, menuPtr);\n    }\n}\n\nstatic inline void\nCallPendingReconfigureImmediately(\n    TkMenu *menuPtr)\n{\n    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {\n\tTcl_CancelIdleCall(ReconfigureWindowsMenu, menuPtr);\n\tReconfigureWindowsMenu(menuPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetNewID --\n *\n *\tAllocates a new menu id and marks it in use.\n *\n * Results:\n *\tReturns TCL_OK if succesful; TCL_ERROR if there are no more ids of the\n *\tappropriate type to allocate. menuIDPtr contains the new id if\n *\tsuccesful.\n *\n * Side effects:\n *\tAn entry is created for the menu in the command hash table, and the\n *\thash entry is stored in the appropriate field in the menu data\n *\tstructure.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetNewID(\n    TkMenuEntry *mePtr,\t\t/* The menu we are working with. */\n    WORD *menuIDPtr)\t\t/* The resulting id. */\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n    WORD curID = tsdPtr->lastCommandID;\n\n    while (1) {\n\tTcl_HashEntry *commandEntryPtr;\n\tint isNew;\n\n\t/*\n\t * Try the next ID number, taking care to wrap rather than stray\n\t * into the system menu IDs.  [Bug 3235256]\n\t */\n\tif (++curID >= 0xF000) {\n\t    curID = 1;\n\t}\n\n\t/* Return error when we've checked all IDs without success. */\n\tif (curID == tsdPtr->lastCommandID) {\n\t    return TCL_ERROR;\n\t}\n\n\tcommandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,\n\t\tINT2PTR(curID), &isNew);\n\tif (isNew) {\n\t    Tcl_SetHashValue(commandEntryPtr, mePtr);\n\t    *menuIDPtr = curID;\n\t    tsdPtr->lastCommandID = curID;\n\t    return TCL_OK;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeID --\n *\n *\tMarks the itemID as free.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe hash table entry for the ID is cleared.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeID(\n    WORD commandID)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * If the menuHWND is NULL, this table has been finalized already.\n     */\n\n    if (tsdPtr->menuHWND != NULL) {\n\tTcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,\n\t\tINT2PTR(commandID));\n\n\tif (entryPtr != NULL) {\n\t    Tcl_DeleteHashEntry(entryPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpNewMenu --\n *\n *\tGets a new blank menu. Only the platform specific options are filled\n *\tin.\n *\n * Results:\n *\tStandard TCL error.\n *\n * Side effects:\n *\tAllocates a Windows menu handle and places it in the platformData\n *\tfield of the menuPtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpNewMenu(\n    TkMenu *menuPtr)\t\t/* The common structure we are making the\n\t\t\t\t * platform structure for. */\n{\n    HMENU winMenuHdl;\n    Tcl_HashEntry *hashEntryPtr;\n    int newEntry;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    winMenuHdl = CreatePopupMenu();\n    if (winMenuHdl == NULL) {\n\tTcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj(\n\t\t\"No more menus can be allocated.\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(menuPtr->interp, \"TK\", \"MENU\", \"SYSTEM_RESOURCES\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * We hash all of the HMENU's so that we can get their menu ptrs back when\n     * dispatch messages.\n     */\n\n    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,\n\t    (char *) winMenuHdl, &newEntry);\n    Tcl_SetHashValue(hashEntryPtr, menuPtr);\n\n    menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenu --\n *\n *\tDestroys platform-specific menu structures.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAll platform-specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenu(\n    TkMenu *menuPtr)\t\t/* The common menu structure */\n{\n    HMENU winMenuHdl = (HMENU) menuPtr->platformData;\n    const char *searchName;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {\n\tTcl_CancelIdleCall(ReconfigureWindowsMenu, menuPtr);\n    }\n\n    if (winMenuHdl == NULL) {\n\treturn;\n    }\n\n    if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {\n\tTkMenuEntry *searchEntryPtr;\n\tTcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);\n\tchar *menuName = (char *)Tcl_GetHashKey(tablePtr,\n\t\tmenuPtr->menuRefPtr->hashEntryPtr);\n\n\t/*\n\t * Search for the menu in the menubar, if it is present, get the\n\t * wrapper window associated with the toplevel and reset its\n\t * system menu to the default menu.\n\t */\n\n\tfor (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;\n\t\tsearchEntryPtr != NULL;\n\t\tsearchEntryPtr = searchEntryPtr->nextCascadePtr) {\n\t    searchName = Tcl_GetString(searchEntryPtr->namePtr);\n\t    if (strcmp(searchName, menuName) == 0) {\n\t\tTk_Window parentTopLevelPtr = searchEntryPtr\n\t\t\t->menuPtr->parentTopLevelPtr;\n\n\t\tif (parentTopLevelPtr != NULL) {\n\t\t    GetSystemMenu(\n\t\t\t    TkWinGetWrapperWindow(parentTopLevelPtr), TRUE);\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    } else {\n\t/*\n\t * Remove the menu from the menu hash table, then destroy the handle.\n\t * If the menuHWND is NULL, this table has been finalized already.\n\t */\n\n\tif (tsdPtr->menuHWND != NULL) {\n\t    Tcl_HashEntry *hashEntryPtr =\n\t\tTcl_FindHashEntry(&tsdPtr->winMenuTable, winMenuHdl);\n\n\t    if (hashEntryPtr != NULL) {\n\t\tTcl_DeleteHashEntry(hashEntryPtr);\n\t    }\n\t}\n\tDestroyMenu(winMenuHdl);\n    }\n    menuPtr->platformData = NULL;\n\n    if (menuPtr == tsdPtr->modalMenuPtr) {\n\ttsdPtr->modalMenuPtr = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyMenuEntry --\n *\n *\tCleans up platform-specific menu entry items.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tAll platform-specific allocations are freed up.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyMenuEntry(\n    TkMenuEntry *mePtr)\t\t/* The entry to destroy */\n{\n    TkMenu *menuPtr = mePtr->menuPtr;\n    HMENU winMenuHdl = (HMENU) menuPtr->platformData;\n\n    if (NULL != winMenuHdl) {\n\tScheduleMenuReconfigure(menuPtr);\n    }\n    FreeID((WORD) PTR2INT(mePtr->platformEntryData));\n    mePtr->platformEntryData = NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetEntryText --\n *\n *\tGiven a menu entry, gives back the text that should go in it.\n *\tSeparators should be done by the caller, as they have to be handled\n *\tspecially. Allocates the memory with alloc. The caller should free the\n *\tmemory.\n *\n * Results:\n *\titemText points to the new text for the item.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic char *\nGetEntryText(\n    TkMenu *menuPtr,\t\t/* The menu considered. */\n    TkMenuEntry *mePtr)\t\t/* A pointer to the menu entry. */\n{\n    char *itemText;\n\n    if (mePtr->type == TEAROFF_ENTRY) {\n\titemText = (char *)Tcl_Alloc(sizeof(\"(Tear-off)\"));\n\tstrcpy(itemText, \"(Tear-off)\");\n    } else if (mePtr->imagePtr != NULL) {\n\titemText = (char *)Tcl_Alloc(sizeof(\"(Image)\"));\n\tstrcpy(itemText, \"(Image)\");\n    } else if (mePtr->bitmapPtr != NULL) {\n\titemText = (char *)Tcl_Alloc(sizeof(\"(Pixmap)\"));\n\tstrcpy(itemText, \"(Pixmap)\");\n    } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {\n\titemText = (char *)Tcl_Alloc(sizeof(\"( )\"));\n\tstrcpy(itemText, \"( )\");\n    } else {\n\tint i;\n\tconst char *label = (mePtr->labelPtr == NULL) ? \"\"\n\t\t: Tcl_GetString(mePtr->labelPtr);\n\tconst char *accel = ((menuPtr->menuType == MENUBAR) || (mePtr->accelPtr == NULL)) ? \"\"\n\t\t: Tcl_GetString(mePtr->accelPtr);\n\tconst char *p, *next;\n\tTcl_DString itemString;\n\tTcl_UniChar ch = 0;\n\n\t/*\n\t * We have to construct the string with an ampersand preceding the\n\t * underline character, and a tab separating the text and the accel\n\t * text. We have to be careful with ampersands in the string.\n\t */\n\n\tTcl_DStringInit(&itemString);\n\n\tfor (p = label, i = 0; *p != '\\0'; i++, p = next) {\n\t    if (i == mePtr->underline) {\n\t\tTcl_DStringAppend(&itemString, \"&\", 1);\n\t    }\n\t    if (*p == '&') {\n\t\tTcl_DStringAppend(&itemString, \"&\", 1);\n\t    }\n\t    next = p + Tcl_UtfToUniChar(p, &ch);\n\t    Tcl_DStringAppend(&itemString, p, (int) (next - p));\n\t}\n\tch = 0;\n\tif (mePtr->accelLength > 0) {\n\t    Tcl_DStringAppend(&itemString, \"\\t\", 1);\n\t    for (p = accel, i = 0; *p != '\\0'; i++, p = next) {\n\t\tif (*p == '&') {\n\t\t    Tcl_DStringAppend(&itemString, \"&\", 1);\n\t\t}\n\t\tnext = p + Tcl_UtfToUniChar(p, &ch);\n\t\tTcl_DStringAppend(&itemString, p, (int) (next - p));\n\t    }\n\t}\n\n\titemText = (char *)Tcl_Alloc(Tcl_DStringLength(&itemString) + 1);\n\tstrcpy(itemText, Tcl_DStringValue(&itemString));\n\tTcl_DStringFree(&itemString);\n    }\n    return itemText;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReconfigureWindowsMenu --\n *\n *\tTears down and rebuilds the platform-specific part of this menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tConfiguration information get set for mePtr; old resources get freed,\n *\tif any need it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nReconfigureWindowsMenu(\n    void *clientData)\t/* The menu we are rebuilding */\n{\n    TkMenu *menuPtr = (TkMenu *)clientData;\n    TkMenuEntry *mePtr;\n    HMENU winMenuHdl = (HMENU) menuPtr->platformData;\n    LPCWSTR lpNewItem;\n    UINT flags;\n    UINT itemID;\n    Tcl_Size i, count;\n    int systemMenu = 0, base;\n    MENUITEMINFOW itemInfo;\n\n    if (NULL == winMenuHdl) {\n\treturn;\n    }\n\n    /*\n     * Reconstruct the entire menu. Takes care of nasty system menu and index\n     * problem.\n     */\n\n    base = (menuPtr->menuFlags & MENU_SYSTEM_MENU) ? 7 : 0;\n    count = GetMenuItemCount(winMenuHdl);\n    for (i = base; i < count; i++) {\n\tRemoveMenu(winMenuHdl, base, MF_BYPOSITION);\n    }\n\n    count = menuPtr->numEntries;\n    for (i = 0; i < count; i++) {\n\tchar *itemText = NULL;\n\tTcl_DString translatedText;\n\n\tmePtr = menuPtr->entries[i];\n\tlpNewItem = NULL;\n\tflags = MF_BYPOSITION;\n\titemID = 0;\n\tTcl_DStringInit(&translatedText);\n\n\tif ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {\n\t    continue;\n\t}\n\n\titemText = GetEntryText(menuPtr, mePtr);\n\tif ((menuPtr->menuType == MENUBAR)\n\t\t|| (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {\n\t\tTcl_UtfToWCharDString(itemText, TCL_INDEX_NONE, &translatedText);\n\t    lpNewItem = (LPCWSTR) Tcl_DStringValue(&translatedText);\n\t    flags |= MF_STRING;\n\t} else {\n\t    lpNewItem = (LPCWSTR) mePtr;\n\t    flags |= MF_OWNERDRAW;\n\t}\n\n\t/*\n\t * Set enabling and disabling correctly.\n\t */\n\n\tif (mePtr->state == ENTRY_DISABLED) {\n\t    flags |= MF_DISABLED | MF_GRAYED;\n\t}\n\n\t/*\n\t * Set the check mark for check entries and radio entries.\n\t */\n\n\tif (((mePtr->type == CHECK_BUTTON_ENTRY)\n\t\t|| (mePtr->type == RADIO_BUTTON_ENTRY))\n\t\t&& (mePtr->entryFlags & ENTRY_SELECTED)) {\n\t    flags |= MF_CHECKED;\n\t}\n\n\t/*\n\t * Set the SEPARATOR bit for separator entries. This bit is not used\n\t * by our internal drawing functions, but it is used by the system\n\t * when drawing the system menu (we do not draw the system menu\n\t * ourselves). If this bit is not set, separator entries on the system\n\t * menu will not be drawn correctly.\n\t */\n\n\tif (mePtr->type == SEPARATOR_ENTRY) {\n\t    flags |= MF_SEPARATOR;\n\t}\n\n\tif (mePtr->columnBreak) {\n\t    flags |= MF_MENUBREAK;\n\t}\n\n\titemID = (UINT)PTR2INT(mePtr->platformEntryData);\n\tif ((mePtr->type == CASCADE_ENTRY)\n\t\t&& (mePtr->childMenuRefPtr != NULL)\n\t\t&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {\n\t    HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr\n\t\t->platformData;\n\t    if (childMenuHdl != NULL) {\n\t\t/*\n\t\t * Win32 draws the popup arrow in the wrong color for a\n\t\t * disabled cascade menu, so do it by hand. Given it is\n\t\t * disabled, there's no need for it to be connected to its\n\t\t * child.\n\t\t */\n\n\t\tif (mePtr->state != ENTRY_DISABLED) {\n\t\t    flags |= MF_POPUP;\n\t\t    /*\n\t\t     * If the MF_POPUP flag is set, then the id is interpreted\n\t\t     * as the handle of a submenu.\n\t\t     */\n\t\t    itemID = (UINT)PTR2INT(childMenuHdl);\n\t\t}\n\t    }\n\t    if ((menuPtr->menuType == MENUBAR)\n\t\t    && !(mePtr->childMenuRefPtr->menuPtr->menuFlags\n\t\t\t    & MENU_SYSTEM_MENU)) {\n\t\tTcl_DString ds;\n\t\tTkMenuReferences *menuRefPtr;\n\t\tTkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;\n\n\t\tTcl_DStringInit(&ds);\n\t\tTcl_DStringAppend(&ds,\n\t\t\tTk_PathName(menuPtr->mainMenuPtr->tkwin), TCL_INDEX_NONE);\n\t\tTcl_DStringAppend(&ds, \".system\", 7);\n\n\t\tmenuRefPtr = TkFindMenuReferences(menuPtr->interp,\n\t\t\tTcl_DStringValue(&ds));\n\n\t\tTcl_DStringFree(&ds);\n\n\t\tif ((menuRefPtr != NULL)\n\t\t\t&& (menuRefPtr->menuPtr != NULL)\n\t\t\t&& (menuPtr->parentTopLevelPtr != NULL)\n\t\t\t&& (systemMenuPtr->mainMenuPtr\n\t\t\t\t== menuRefPtr->menuPtr)) {\n\t\t    HMENU systemMenuHdl = (HMENU) systemMenuPtr->platformData;\n\t\t    HWND wrapper = TkWinGetWrapperWindow(menuPtr\n\t\t\t    ->parentTopLevelPtr);\n\n\t\t    if (wrapper != NULL) {\n\t\t\tDestroyMenu(systemMenuHdl);\n\t\t\tsystemMenuHdl = GetSystemMenu(wrapper, FALSE);\n\t\t\tsystemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;\n\t\t\tsystemMenuPtr->platformData =\n\t\t\t\t(TkMenuPlatformData) systemMenuHdl;\n\t\t\tScheduleMenuReconfigure(systemMenuPtr);\n\t\t    }\n\t\t}\n\t    }\n\t    if (mePtr->childMenuRefPtr->menuPtr->menuFlags\n\t\t    & MENU_SYSTEM_MENU) {\n\t\tsystemMenu++;\n\t    }\n\t}\n\tif (!systemMenu) {\n\t    InsertMenuW(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);\n\t}\n\t/*\n\t * For owner-drawn items, set the menu item string data\n\t * so screen readers can access the label text.\n\t */\n\tif ((flags & MF_OWNERDRAW) && itemText != NULL) {\n\t    Tcl_DString accessText;\n\n\t    memset(&itemInfo, 0, sizeof(itemInfo));\n\t    itemInfo.cbSize = sizeof(MENUITEMINFOW);\n\t    itemInfo.fMask = MIIM_STRING | MIIM_DATA;\n\n\t    /* Convert to wide string for accessibility. */\n\t    Tcl_DStringInit(&accessText);\n\t    Tcl_UtfToWCharDString(itemText, TCL_INDEX_NONE, &accessText);\n\t    itemInfo.dwTypeData = (LPWSTR)Tcl_DStringValue(&accessText);\n\t    itemInfo.cch = (UINT)Tcl_DStringLength(&accessText) / sizeof(WCHAR);\n\t    itemInfo.dwItemData = (ULONG_PTR)mePtr;\n\n\t    /* Set the menu item info - this makes text available to screen readers. */\n\t    SetMenuItemInfoW(winMenuHdl, (UINT)i, TRUE, &itemInfo);\n\n\t    Tcl_DStringFree(&accessText);\n\t}\n\tTcl_DStringFree(&translatedText);\n\tif (itemText != NULL) {\n\t    Tcl_Free(itemText);\n\t    itemText = NULL;\n\t}\n    }\n\n    if ((menuPtr->menuType == MENUBAR)\n\t    && (menuPtr->parentTopLevelPtr != NULL)) {\n\tHWND bar = TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr);\n\n\tif (bar) {\n\t    DrawMenuBar(bar);\n\t}\n    }\n\n    menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostMenu --\n *\n *\tPosts a menu on the screen so that the top left corner of the\n *      specified entry is located at the point (x, y) in screen coordinates.\n *      If the entry parameter is negative, the upper left corner of the\n *      menu itself is placed at the point.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu is posted and handled.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostMenu(\n    TCL_UNUSED(Tcl_Interp *),\n    TkMenu *menuPtr,\n    int x, int y, Tcl_Size index)\n{\n    HMENU winMenuHdl = (HMENU) menuPtr->platformData;\n    int result, flags;\n    RECT noGoawayRect;\n    POINT point;\n    Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);\n    int oldServiceMode = Tcl_GetServiceMode();\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->inPostMenu++;\n    CallPendingReconfigureImmediately(menuPtr);\n\n    result = TkPreprocessMenu(menuPtr);\n    if (result != TCL_OK) {\n\ttsdPtr->inPostMenu--;\n\treturn result;\n    }\n\n    if (index >= menuPtr->numEntries) {\n\tindex = menuPtr->numEntries - 1;\n    }\n    if (index >= 0) {\n\ty -= menuPtr->entries[index]->y;\n    }\n\n    /*\n     * The post commands could have deleted the menu, which means\n     * we are dead and should go away.\n     */\n\n    if (menuPtr->tkwin == NULL) {\n\ttsdPtr->inPostMenu--;\n\treturn TCL_OK;\n    }\n\n    if (NULL == parentWindow) {\n\tnoGoawayRect.top = y - 50;\n\tnoGoawayRect.bottom = y + 50;\n\tnoGoawayRect.left = x - 50;\n\tnoGoawayRect.right = x + 50;\n    } else {\n\tint left, top;\n\tTk_GetRootCoords(parentWindow, &left, &top);\n\tnoGoawayRect.left = left;\n\tnoGoawayRect.top = top;\n\tnoGoawayRect.bottom = noGoawayRect.top + Tk_Height(parentWindow);\n\tnoGoawayRect.right = noGoawayRect.left + Tk_Width(parentWindow);\n    }\n\n    Tcl_SetServiceMode(TCL_SERVICE_NONE);\n\n    /*\n     * Make an assumption here. If the right button is down,\n     * then we want to track it. Otherwise, track the left mouse button.\n     */\n\n    flags = TPM_LEFTALIGN;\n    if (GetSystemMetrics(SM_SWAPBUTTON)) {\n\tif (GetAsyncKeyState(VK_LBUTTON) < 0) {\n\t    flags |= TPM_RIGHTBUTTON;\n\t} else {\n\t    flags |= TPM_LEFTBUTTON;\n\t}\n    } else {\n\tif (GetAsyncKeyState(VK_RBUTTON) < 0) {\n\t    flags |= TPM_RIGHTBUTTON;\n\t} else {\n\t    flags |= TPM_LEFTBUTTON;\n\t}\n    }\n\n    TrackPopupMenu(winMenuHdl, flags, x, y, 0,\n\t    tsdPtr->menuHWND, &noGoawayRect);\n    Tcl_SetServiceMode(oldServiceMode);\n\n    GetCursorPos(&point);\n    TkWinPointerEvent(NULL, point.x, point.y);\n\n    if (tsdPtr->inPostMenu) {\n\ttsdPtr->inPostMenu = 0;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPostTearoffMenu --\n *\n *\tPosts a tearoff menu on the screen so that the top left corner of the\n *      specified entry is located at the point (x, y) in screen coordinates.\n *      If the index parameter is negative, the upper left corner of the menu\n *      itself is placed at the point.  Adjusts the menu's position so that it\n *      fits on the screen, and maps and raises the menu.\n *\n * Results:\n *\tReturns a standard Tcl Error.\n *\n * Side effects:\n *\tThe menu is posted.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpPostTearoffMenu(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* The interpreter of the menu */\n    TkMenu *menuPtr,\t\t/* The menu we are posting */\n    int x, int y, Tcl_Size index)\t/* The root X,Y coordinates where we are\n\t\t\t\t * posting */\n{\n    int vRootX, vRootY, vRootWidth, vRootHeight;\n    int result;\n\n    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n    TkRecomputeMenu(menuPtr);\n    result = TkPostCommand(menuPtr);\n    if (result != TCL_OK) {\n\treturn result;\n    }\n\n    /*\n     * The post commands could have deleted the menu, which means we are dead\n     * and should go away.\n     */\n\n    if (menuPtr->tkwin == NULL) {\n\treturn TCL_OK;\n    }\n\n     /*\n     * Adjust the menu y position so that the specified entry will be located\n     * at the given coordinates.\n     */\n\n    if (index >= menuPtr->numEntries) {\n\tindex = menuPtr->numEntries - 1;\n    }\n    if (index >= 0) {\n\ty -= menuPtr->entries[index]->y;\n    }\n\n   /*\n     * Adjust the position of the menu if necessary to keep it visible on the\n     * screen. There are two special tricks to make this work right:\n     *\n     * 1. If a virtual root window manager is being used then the coordinates\n     *    are in the virtual root window of menuPtr's parent; since the menu\n     *    uses override-redirect mode it will be in the *real* root window for\n     *    the screen, so we have to map the coordinates from the virtual root\n     *    (if any) to the real root. Can't get the virtual root from the menu\n     *    itself (it will never be seen by the wm) so use its parent instead\n     *    (it would be better to have an an option that names a window to use\n     *    for this...).\n     * 2. The menu may not have been mapped yet, so its current size might be\n     *    the default 1x1. To compute how much space it needs, use its\n     *    requested size, not its actual size.\n     */\n\n    Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,\n\t&vRootWidth, &vRootHeight);\n    vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);\n    if (x > vRootX + vRootWidth) {\n\tx = vRootX + vRootWidth;\n    }\n    if (x < vRootX) {\n\tx = vRootX;\n    }\n    vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);\n    if (y > vRootY + vRootHeight) {\n\ty = vRootY + vRootHeight;\n    }\n    if (y < vRootY) {\n\ty = vRootY;\n    }\n    Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);\n    if (!Tk_IsMapped(menuPtr->tkwin)) {\n\tTk_MapWindow(menuPtr->tkwin);\n    }\n    TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNewEntry --\n *\n *\tAdds a pointer to a new menu entry structure with the platform-\n *\tspecific fields filled in.\n *\n * Results:\n *\tStandard TCL error.\n *\n * Side effects:\n *\tA new command ID is allocated and stored in the platformEntryData\n *\tfield of mePtr.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpMenuNewEntry(\n    TkMenuEntry *mePtr)\n{\n    WORD commandID;\n    TkMenu *menuPtr = mePtr->menuPtr;\n\n    if (GetNewID(mePtr, &commandID) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    ScheduleMenuReconfigure(menuPtr);\n    mePtr->platformEntryData = (TkMenuPlatformEntryData) INT2PTR(commandID);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinMenuProc --\n *\n *\tThe window proc for the dummy window we put popups in. This allows\n *\tis to post a popup whether or not we know what the parent window\n *\tis.\n *\n * Results:\n *\tReturns whatever is appropriate for the message in question.\n *\n * Side effects:\n *\tNormal side-effect for windows messages.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nTkWinMenuProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    LRESULT lResult;\n\n    if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {\n\tlResult = DefWindowProcW(hwnd, message, wParam, lParam);\n    }\n    return lResult;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateEmbeddedMenu --\n *\n *\tThis function is used as work-around for updating the pull-down window\n *\tof an embedded menu which may show as a blank popup window.\n *\n * Results:\n *\tInvalidate the client area of the embedded pull-down menu and\n *\tredraw it.\n *\n * Side effects:\n *\tRedraw the embedded menu window.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateEmbeddedMenu(\n    void *clientData)\n{\n    RECT rc;\n    HWND hMenuWnd = (HWND)clientData;\n\n    GetClientRect(hMenuWnd, &rc);\n    InvalidateRect(hMenuWnd, &rc, FALSE);\n    UpdateWindow(hMenuWnd);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinEmbeddedMenuProc --\n *\n *\tThis window proc is for the embedded menu windows. It provides\n *\tmessage services to an embedded menu in a different process.\n *\n * Results:\n *\tReturns 1 if the message has been handled or 0 otherwise.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nTkWinEmbeddedMenuProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    static int nIdles = 0;\n    LRESULT lResult = 1;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    switch(message) {\n    case WM_ENTERIDLE:\n\tif ((wParam == MSGF_MENU) && (nIdles < 1)\n\t\t&& (hwnd == tsdPtr->embeddedMenuHWND)) {\n\t    Tcl_CreateTimerHandler(200, UpdateEmbeddedMenu,\n\t\t    (void *) lParam);\n\t    nIdles++;\n\t}\n\tbreak;\n\n    case WM_INITMENUPOPUP:\n\tnIdles = 0;\n\tbreak;\n\n    case WM_SETTINGCHANGE:\n\tif (wParam == SPI_SETNONCLIENTMETRICS\n\t\t|| wParam == SPI_SETKEYBOARDCUES) {\n\t    SetDefaults(0);\n\t}\n\tbreak;\n\n    case WM_INITMENU:\n    case WM_SYSCOMMAND:\n    case WM_COMMAND:\n    case WM_MENUCHAR:\n    case WM_MEASUREITEM:\n    case WM_DRAWITEM:\n    case WM_MENUSELECT:\n\tlResult = TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,\n\t\t&lResult);\n\tif (lResult || (GetCapture() != hwnd)) {\n\t    break;\n\t}\n\t/* FALLTHRU */\n    default:\n\tlResult = DefWindowProcW(hwnd, message, wParam, lParam);\n\tbreak;\n    }\n    return lResult;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinHandleMenuEvent --\n *\n *\tFilters out menu messages from messages passed to a top-level. Will\n *\trespond appropriately to WM_COMMAND, WM_MENUSELECT, WM_MEASUREITEM,\n *\tWM_DRAWITEM\n *\n * Result:\n *\tReturns 1 if this handled the message; 0 if it did not.\n *\n * Side effects:\n *\tAll of the parameters may be modified so that the caller can think it\n *\tis getting a different message. plResult points to the result that\n *\tshould be returned to windows from this message.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkWinHandleMenuEvent(\n    TCL_UNUSED(HWND *),\n    UINT *pMessage,\n    WPARAM *pwParam,\n    LPARAM *plParam,\n    LRESULT *plResult)\n{\n    Tcl_HashEntry *hashEntryPtr;\n    int returnResult = 0;\n    TkMenu *menuPtr;\n    TkMenuEntry *mePtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    switch (*pMessage) {\n    case WM_UNINITMENUPOPUP:\n\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,\n\t\t*pwParam);\n\tif (hashEntryPtr != NULL) {\n\t    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);\n\t    if ((menuPtr->menuRefPtr != NULL)\n\t\t    && (menuPtr->menuRefPtr->parentEntryPtr != NULL)) {\n\t\tTkPostSubmenu(menuPtr->interp,\n\t\t\tmenuPtr->menuRefPtr->parentEntryPtr->menuPtr, NULL);\n\t    }\n\t}\n\tbreak;\n\n    case WM_INITMENU:\n\tTkMenuInit();\n\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,\n\t\t*pwParam);\n\tif (hashEntryPtr != NULL) {\n\t    tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n\t    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);\n\t    tsdPtr->modalMenuPtr = menuPtr;\n\t    CallPendingReconfigureImmediately(menuPtr);\n\t    RecursivelyClearActiveMenu(menuPtr);\n\t    if (!tsdPtr->inPostMenu) {\n\t\tTcl_Interp *interp = menuPtr->interp;\n\t\tint code;\n\n\t\tTcl_Preserve(interp);\n\t\tcode = TkPreprocessMenu(menuPtr);\n\t\tif ((code != TCL_OK) && (code != TCL_CONTINUE)\n\t\t\t&& (code != TCL_BREAK)) {\n\t\t    Tcl_AddErrorInfo(interp, \"\\n    (menu preprocess)\");\n\t\t    Tcl_BackgroundException(interp, code);\n\t\t}\n\t\tTcl_Release(interp);\n\t    }\n\t    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n\t    *plResult = 0;\n\t    returnResult = 1;\n\t} else {\n\t    tsdPtr->modalMenuPtr = NULL;\n\t}\n\tbreak;\n\n    case WM_SYSCOMMAND:\n    case WM_COMMAND:\n\tTkMenuInit();\n\tif (HIWORD(*pwParam) != 0) {\n\t    break;\n\t}\n\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,\n\t\tINT2PTR(LOWORD(*pwParam)));\n\tif (hashEntryPtr == NULL) {\n\t    break;\n\t}\n\tmePtr = (TkMenuEntry *)Tcl_GetHashValue(hashEntryPtr);\n\tif (mePtr != NULL) {\n\t    TkMenuReferences *menuRefPtr;\n\t    TkMenuEntry *parentEntryPtr;\n\t    Tcl_Interp *interp;\n\t    int code;\n\n\t    /*\n\t     * We have to set the parent of this menu to be active if this is\n\t     * a submenu so that tearoffs will get the correct title.\n\t     */\n\n\t    menuPtr = mePtr->menuPtr;\n\t    menuRefPtr = TkFindMenuReferences(menuPtr->interp,\n\t\t    Tk_PathName(menuPtr->tkwin));\n\t    if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {\n\t\tfor (parentEntryPtr = menuRefPtr->parentEntryPtr ; ;\n\t\t\tparentEntryPtr = parentEntryPtr->nextCascadePtr) {\n\t\t    const char *name = Tcl_GetString(parentEntryPtr->namePtr);\n\n\t\t    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tif (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]\n\t\t\t->state != ENTRY_DISABLED) {\n\t\t    TkActivateMenuEntry(parentEntryPtr->menuPtr,\n\t\t\t    parentEntryPtr->index);\n\t\t}\n\t    }\n\n\t    interp = menuPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    Tcl_Preserve(menuPtr);\n\t    code = TkInvokeMenu(interp, menuPtr, mePtr->index);\n\t    if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) {\n\t\tTcl_AddErrorInfo(interp, \"\\n    (menu invoke)\");\n\t\tTcl_BackgroundException(interp, code);\n\t    }\n\t    Tcl_Release(menuPtr);\n\t    Tcl_Release(interp);\n\t    *plResult = 0;\n\t    returnResult = 1;\n\t}\n\tbreak;\n\n    case WM_MENUCHAR: {\n\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,\n\t\t*plParam);\n\tif (hashEntryPtr != NULL) {\n\t    Tcl_Size i, len;\n\t    int underline;\n\t    Tcl_Obj *labelPtr;\n\t    WCHAR *wlabel;\n\t    int menuChar;\n\t    Tcl_DString ds;\n\n\t    *plResult = 0;\n\t    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);\n\t    /*\n\t     * Assume we have something directly convertable to Tcl_UniChar.\n\t     * True at least for wide systems.\n\t     */\n\t    menuChar = Tcl_UniCharToUpper(LOWORD(*pwParam));\n\n\t    Tcl_DStringInit(&ds);\n\t    for (i = 0; i < menuPtr->numEntries; i++) {\n\t\tunderline = menuPtr->entries[i]->underline;\n\t\tlabelPtr = menuPtr->entries[i]->labelPtr;\n\t\tif ((underline >= 0) && (labelPtr != NULL)) {\n\t\t    /*\n\t\t     * Ensure we don't exceed the label length, then check\n\t\t     */\n\t\t    const char *src = Tcl_GetStringFromObj(labelPtr, &len);\n\n\t\t    Tcl_DStringFree(&ds);\n\t\t    Tcl_DStringInit(&ds);\n\t\t    wlabel = Tcl_UtfToWCharDString(src, len, &ds);\n\t\t    if ((underline < len) && (menuChar ==\n\t\t\t\tTcl_UniCharToUpper(wlabel[underline]))) {\n\t\t\t*plResult = (2 << 16) | i;\n\t\t\treturnResult = 1;\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t    }\n\t    Tcl_DStringFree(&ds);\n\t}\n\tbreak;\n    }\n\n    case WM_MEASUREITEM: {\n\tLPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam;\n\n\tif (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {\n\t    mePtr = (TkMenuEntry *) itemPtr->itemData;\n\t    menuPtr = mePtr->menuPtr;\n\n\t    TkRecomputeMenu(menuPtr);\n\t    itemPtr->itemHeight = mePtr->height;\n\t    itemPtr->itemWidth = mePtr->width;\n\t    if (mePtr->hideMargin) {\n\t\titemPtr->itemWidth += 2 - indicatorDimensions[1];\n\t    } else {\n\t\tint activeBorderWidth;\n\n\t\tTk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\t\titemPtr->itemWidth += 2 * activeBorderWidth;\n\t    }\n\t    *plResult = 1;\n\t    returnResult = 1;\n\t}\n\tbreak;\n    }\n\n    case WM_DRAWITEM: {\n\tTkWinDrawable *twdPtr;\n\tLPDRAWITEMSTRUCT itemPtr = (LPDRAWITEMSTRUCT) *plParam;\n\tTk_FontMetrics fontMetrics;\n\tDrawMenuFlags drawingParameters = DRAW_MENU_ENTRY_DEFAULT;\n\n\tif (itemPtr != NULL && tsdPtr->modalMenuPtr != NULL) {\n\t    Tk_Font tkfont;\n\n\t    if (itemPtr->itemState & ODS_NOACCEL && !showMenuAccelerators) {\n\t\tdrawingParameters = (DrawMenuFlags)(drawingParameters|DRAW_MENU_ENTRY_NOUNDERLINE);\n\t    }\n\t    mePtr = (TkMenuEntry *) itemPtr->itemData;\n\t    menuPtr = mePtr->menuPtr;\n\t    twdPtr = (TkWinDrawable *)Tcl_Alloc(sizeof(TkWinDrawable));\n\t    twdPtr->type = TWD_WINDC;\n\t    twdPtr->winDC.hdc = itemPtr->hDC;\n\n\t    if (mePtr->state != ENTRY_DISABLED) {\n\t\tif (itemPtr->itemState & ODS_SELECTED) {\n\t\t    TkActivateMenuEntry(menuPtr, mePtr->index);\n\t\t} else {\n\t\t    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * On windows, menu entries should highlight even if they are\n\t\t * disabled. (I know this seems dumb, but it is the way native\n\t\t * windows menus works so we ought to mimic it.) The\n\t\t * ENTRY_PLATFORM_FLAG1 flag will indicate that the entry\n\t\t * should be highlighted even though it is disabled.\n\t\t */\n\n\t\tif (itemPtr->itemState & ODS_SELECTED) {\n\t\t    mePtr->entryFlags |= ENTRY_PLATFORM_FLAG1;\n\t\t} else {\n\t\t    mePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;\n\t\t}\n\n\t\t/*\n\t\t * Also, set the DRAW_MENU_ENTRY_ARROW flag for a disabled\n\t\t * cascade menu since we need to draw the arrow ourselves.\n\t\t */\n\n\t\tif (mePtr->type == CASCADE_ENTRY) {\n\t\t    drawingParameters = (DrawMenuFlags)(drawingParameters|DRAW_MENU_ENTRY_ARROW);\n\t\t}\n\t    }\n\n\t    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n\t    Tk_GetFontMetrics(tkfont, &fontMetrics);\n\t    TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont, &fontMetrics,\n\t\t    itemPtr->rcItem.left, itemPtr->rcItem.top,\n\t\t    itemPtr->rcItem.right - itemPtr->rcItem.left,\n\t\t    itemPtr->rcItem.bottom - itemPtr->rcItem.top,\n\t\t    drawingParameters);\n\n\t    Tcl_Free(twdPtr);\n\t}\n\t*plResult = 1;\n\treturnResult = 1;\n\tbreak;\n    }\n\n    case WM_MENUSELECT: {\n\tUINT flags = HIWORD(*pwParam);\n\n\tTkMenuInit();\n\n\tif ((flags == 0xFFFF) && (*plParam == 0)) {\n\t    if (tsdPtr->modalMenuPtr != NULL) {\n\t\tTcl_SetServiceMode(tsdPtr->oldServiceMode);\n\t\tRecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);\n\t    }\n\t} else {\n\t    menuPtr = NULL;\n\t    if (*plParam != 0) {\n\t\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,\n\t\t\t*plParam);\n\t\tif (hashEntryPtr != NULL) {\n\t\t    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);\n\t\t}\n\t    }\n\n\t    if (menuPtr != NULL) {\n\t\tTcl_Size entryIndex = LOWORD(*pwParam);\n\n\t\tif ((menuPtr->menuType == MENUBAR) && menuPtr->tearoff) {\n\t\t    /*\n\t\t     * Windows passes the entry index starting at 0 for\n\t\t     * the first menu entry. However this entry #0 is the\n\t\t     * tearoff entry for Tk (the menu has -tearoff 1),\n\t\t     * which is ignored for MENUBAR menues on Windows.\n\t\t     */\n\n\t\t\tentryIndex++;\n\t\t}\n\t\tmePtr = NULL;\n\t\tif (flags != 0xFFFF) {\n\t\t    if ((flags&MF_POPUP) && (entryIndex < menuPtr->numEntries)) {\n\t\t\tmePtr = menuPtr->entries[entryIndex];\n\t\t    } else {\n\t\t\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,\n\t\t\t\tINT2PTR(entryIndex));\n\t\t\tif (hashEntryPtr != NULL) {\n\t\t\t    mePtr = (TkMenuEntry *)Tcl_GetHashValue(hashEntryPtr);\n\t\t\t}\n\t\t    }\n\t\t}\n\n\t\tif ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {\n\t\t    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n\t\t} else {\n\t\t    if (mePtr->index >= (int)menuPtr->numEntries) {\n\t\t\tTcl_Panic(\"Trying to activate an entry which does not exist\");\n\t\t    }\n\t\t    TkActivateMenuEntry(menuPtr, mePtr->index);\n\t\t}\n\t\tMenuSelectEvent(menuPtr);\n\t\tTcl_ServiceAll();\n\t\t*plResult = 0;\n\t\treturnResult = 1;\n\t    }\n\t}\n\tbreak;\n    }\n    }\n    return returnResult;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RecursivelyClearActiveMenu --\n *\n *\tRecursively clears the active entry in the menu's cascade hierarchy.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates <<MenuSelect>> virtual events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nRecursivelyClearActiveMenu(\n    TkMenu *menuPtr)\t\t/* The menu to reset. */\n{\n    Tcl_Size i;\n    TkMenuEntry *mePtr;\n\n    TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE);\n    MenuSelectEvent(menuPtr);\n    for (i = 0; i < menuPtr->numEntries; i++) {\n\tmePtr = menuPtr->entries[i];\n\tif (mePtr->state == ENTRY_ACTIVE) {\n\t    mePtr->state = ENTRY_NORMAL;\n\t}\n\tmePtr->entryFlags &= ~ENTRY_PLATFORM_FLAG1;\n\tif (mePtr->type == CASCADE_ENTRY) {\n\t    if ((mePtr->childMenuRefPtr != NULL)\n\t\t    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {\n\t\tRecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetWindowMenuBar --\n *\n *\tAssociates a given menu with a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tOn Windows and UNIX, associates the platform menu with the\n *\tplatform window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetWindowMenuBar(\n    Tk_Window tkwin,\t\t/* The window we are putting the menubar\n\t\t\t\t * into.*/\n    TkMenu *menuPtr)\t\t/* The menu we are inserting */\n{\n    HMENU winMenuHdl;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (menuPtr != NULL) {\n\tTcl_HashEntry *hashEntryPtr;\n\tint newEntry;\n\n\twinMenuHdl = (HMENU) menuPtr->platformData;\n\thashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,\n\t\twinMenuHdl);\n\tTcl_DeleteHashEntry(hashEntryPtr);\n\tDestroyMenu(winMenuHdl);\n\twinMenuHdl = CreateMenu();\n\thashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,\n\t\t(char *) winMenuHdl, &newEntry);\n\tTcl_SetHashValue(hashEntryPtr, menuPtr);\n\tmenuPtr->platformData = (TkMenuPlatformData) winMenuHdl;\n\tTkWinSetMenu(tkwin, winMenuHdl);\n\tScheduleMenuReconfigure(menuPtr);\n    } else {\n\tTkWinSetMenu(tkwin, NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetMainMenubar --\n *\n *\tPuts the menu associated with a window into the menubar. Should only\n *\tbe called when the window is in front.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menubar is changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetMainMenubar(\n    TCL_UNUSED(Tcl_Interp *),\t\t/* The interpreter of the application */\n    TCL_UNUSED(Tk_Window),\t\t/* The frame we are setting up */\n    TCL_UNUSED(const char *))\t/* The name of the menu to put in front. If\n\t\t\t\t * NULL, use the default menu bar. */\n{\n    /*\n     * Nothing to do.\n     */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuIndicatorGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nGetMenuIndicatorGeometry(\n    TkMenu *menuPtr,\t\t/* The menu we are measuring */\n    TkMenuEntry *mePtr,\t\t/* The entry we are measuring */\n    TCL_UNUSED(Tk_Font),\t\t/* Precalculated font */\n    TCL_UNUSED(const Tk_FontMetrics *),/* Precalculated font metrics */\n    int *widthPtr,\t\t/* The resulting width */\n    int *heightPtr)\t\t/* The resulting height */\n{\n    *heightPtr = indicatorDimensions[0];\n    if (mePtr->hideMargin) {\n\t*widthPtr = 0;\n    } else {\n\tint borderWidth;\n\n\tTk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t\tmenuPtr->borderWidthObj, &borderWidth);\n\t*widthPtr = indicatorDimensions[1] - borderWidth;\n\n\t/*\n\t * Quite dubious about the above (why would borderWidth play a role?)\n\t * and about how indicatorDimensions[1] is obtained in SetDefaults().\n\t * At least don't let the result be negative!\n\t */\n\tif (*widthPtr < 0) {\n\t    *widthPtr = 0;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuAccelGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nGetMenuAccelGeometry(\n    TkMenu *menuPtr,\t\t/* The menu we are measuring */\n    TkMenuEntry *mePtr,\t\t/* The entry we are measuring */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int *widthPtr,\t\t/* The resulting width */\n    int *heightPtr)\t\t/* The resulting height */\n{\n    *heightPtr = fmPtr->linespace;\n    if (mePtr->type == CASCADE_ENTRY) {\n\t/*\n\t * Cascade entries have no accelerator but do show an arrow. Set\n\t * this field width to the width of the OBM_MNARROW system bitmap\n\t * used to display the arrow. I couldn't find how to query the\n\t * system for this value, therefore I resort to hardcoding.\n\t */\n\t*widthPtr = CASCADE_ARROW_WIDTH;\n    } else if ((menuPtr->menuType != MENUBAR) && (mePtr->accelPtr != NULL)) {\n\tconst char *accel = Tcl_GetString(mePtr->accelPtr);\n\n\t*widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);\n    } else {\n\t*widthPtr = 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTearoffEntryGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nGetTearoffEntryGeometry(\n    TkMenu *menuPtr,\t\t/* The menu we are measuring */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are measuring */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int *widthPtr,\t\t/* The resulting width */\n    int *heightPtr)\t\t/* The resulting height */\n{\n    if (menuPtr->menuType != MAIN_MENU) {\n\t*heightPtr = 0;\n    } else {\n\t*heightPtr = fmPtr->linespace;\n    }\n    *widthPtr = 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuSeparatorGeometry --\n *\n *\tGets the width and height of the indicator area of a menu.\n *\n * Results:\n *\twidthPtr and heightPtr are set.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nGetMenuSeparatorGeometry(\n    TCL_UNUSED(TkMenu *),\t\t/* The menu we are measuring */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are measuring */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */\n    int *widthPtr,\t\t/* The resulting width */\n    int *heightPtr)\t\t/* The resulting height */\n{\n    *widthPtr = 0;\n    *heightPtr = fmPtr->linespace - (2 * fmPtr->descent);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawWindowsSystemBitmap --\n *\n *\tDraws the windows system bitmap given by bitmapID into the rect given\n *\tby rectPtr in the drawable. The bitmap is centered in the rectangle.\n *\tIt is not clipped, so if the bitmap is bigger than the rect it will\n *\tbleed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDrawing occurs. Some storage is allocated and released.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawWindowsSystemBitmap(\n    Display *display,\t\t/* The display we are drawing into */\n    Drawable drawable,\t\t/* The drawable we are working with */\n    GC gc,\t\t\t/* The GC to draw with */\n    const RECT *rectPtr,\t/* The rectangle to draw into */\n    int bitmapID,\t\t/* The windows id of the system bitmap to\n\t\t\t\t * draw. */\n    int alignFlags)\t\t/* How to align the bitmap inside the\n\t\t\t\t * rectangle. */\n{\n    TkWinDCState state;\n    HDC hdc = TkWinGetDrawableDC(display, drawable, &state);\n    HDC scratchDC;\n    HBITMAP bitmap;\n    BITMAP bm;\n    POINT ptSize;\n    POINT ptOrg;\n    int topOffset, leftOffset;\n\n    SetBkColor(hdc, gc->background);\n    SetTextColor(hdc, gc->foreground);\n\n    scratchDC = CreateCompatibleDC(hdc);\n    bitmap = LoadBitmapW(NULL, (LPCWSTR)MAKEINTRESOURCE(bitmapID));\n\n    SelectObject(scratchDC, bitmap);\n    SetMapMode(scratchDC, GetMapMode(hdc));\n    GetObjectA(bitmap, sizeof(BITMAP), &bm);\n    ptSize.x = bm.bmWidth;\n    ptSize.y = bm.bmHeight;\n    DPtoLP(scratchDC, &ptSize, 1);\n\n    ptOrg.y = ptOrg.x = 0;\n    DPtoLP(scratchDC, &ptOrg, 1);\n\n    if (alignFlags & ALIGN_BITMAP_TOP) {\n\ttopOffset = 0;\n    } else if (alignFlags & ALIGN_BITMAP_BOTTOM) {\n\ttopOffset = (rectPtr->bottom - rectPtr->top) - ptSize.y;\n    } else {\n\ttopOffset = (rectPtr->bottom - rectPtr->top) / 2 - (ptSize.y / 2);\n    }\n\n    if (alignFlags & ALIGN_BITMAP_LEFT) {\n\tleftOffset = 0;\n    } else if (alignFlags & ALIGN_BITMAP_RIGHT) {\n\tleftOffset = (rectPtr->right - rectPtr->left) - ptSize.x;\n    } else {\n\tleftOffset = (rectPtr->right - rectPtr->left) / 2 - (ptSize.x / 2);\n    }\n\n    BitBlt(hdc, rectPtr->left + leftOffset, rectPtr->top + topOffset, ptSize.x,\n\t    ptSize.y, scratchDC, ptOrg.x, ptOrg.y, SRCCOPY);\n    DeleteDC(scratchDC);\n    DeleteObject(bitmap);\n\n    TkWinReleaseDrawableDC(drawable, hdc, &state);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryIndicator --\n *\n *\tThis function draws the indicator part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nDrawMenuEntryIndicator(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc we are drawing with */\n    GC indicatorGC,\t\t/* The gc for indicator objects */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    TCL_UNUSED(const Tk_FontMetrics *),/* The precalculated font metrics */\n    int x,\t\t\t/* Left edge */\n    int y,\t\t\t/* Top edge */\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    if ((mePtr->type == CHECK_BUTTON_ENTRY)\n\t    || (mePtr->type == RADIO_BUTTON_ENTRY)) {\n\tif (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {\n\t    RECT rect;\n\t    GC whichGC;\n\t    int borderWidth, activeBorderWidth;\n\n\t    if (mePtr->state != ENTRY_NORMAL) {\n\t\twhichGC = gc;\n\t    } else {\n\t\twhichGC = indicatorGC;\n\t    }\n\n\t    rect.top = y;\n\t    rect.bottom = y + mePtr->height;\n\t    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t\t    menuPtr->borderWidthObj, &borderWidth);\n\t    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t\t    menuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\t    rect.left = borderWidth + activeBorderWidth + x;\n\t    rect.right = mePtr->indicatorSpace + x;\n\n\t    if ((mePtr->state == ENTRY_DISABLED)\n\t\t    && (menuPtr->disabledFgPtr != NULL)) {\n\t\tRECT hilightRect;\n\t\tCOLORREF oldFgColor = whichGC->foreground;\n\n\t\twhichGC->foreground = GetSysColor(COLOR_3DHILIGHT);\n\t\thilightRect.top = rect.top + 1;\n\t\thilightRect.bottom = rect.bottom + 1;\n\t\thilightRect.left = rect.left + 1;\n\t\thilightRect.right = rect.right + 1;\n\t\tDrawWindowsSystemBitmap(menuPtr->display, d, whichGC,\n\t\t\t&hilightRect, OBM_CHECK, 0);\n\t\twhichGC->foreground = oldFgColor;\n\t    }\n\n\t    DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,\n\t\t    OBM_CHECK, 0);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryAccelerator --\n *\n *\tThis function draws the accelerator part of a menu. For example, the\n *\tstring \"CTRL-Z\" could be drawn to to the right of the label text for\n *\tan Undo menu entry. Need to decide what to draw here. Should we\n *\treplace strings like \"Control\", \"Command\", etc?\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to display the menu in its\n *\tcurrent mode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nDrawMenuEntryAccelerator(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc we are drawing with */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    TCL_UNUSED(Tk_3DBorder),\t/* The border when an item is active */\n    int x,\t\t\t/* left edge */\n    int y,\t\t\t/* top edge */\n    TCL_UNUSED(int),\t\t\t/* Width of menu entry */\n    int height)\t\t\t/* Height of menu entry */\n{\n    int baseline;\n    int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;\n    const char *accel;\n\n    if (menuPtr->menuType == MENUBAR) {\n\treturn;\n    }\n\n    if (mePtr->accelPtr != NULL) {\n\taccel = Tcl_GetString(mePtr->accelPtr);\n    } else {\n\taccel = NULL;\n    }\n\n    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;\n\n    /*\n     * Draw disabled 3D text highlight only with the Win95/98 look.\n     */\n\n    if ((mePtr->state == ENTRY_DISABLED)\n\t    && (menuPtr->disabledFgPtr != NULL) && (accel != NULL)) {\n\tCOLORREF oldFgColor = gc->foreground;\n\n\tgc->foreground = GetSysColor(COLOR_3DHILIGHT);\n\tif (!(mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)) {\n\t    Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,\n\t\t    mePtr->accelLength, leftEdge + 1, baseline + 1);\n\t}\n\tgc->foreground = oldFgColor;\n    }\n\n    if (accel != NULL) {\n\tTk_DrawChars(menuPtr->display, d, gc, tkfont, accel,\n\t\tmePtr->accelLength, leftEdge, baseline);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryArrow --\n *\n *\tThis function draws the arrow bitmap on the right side of a menu\n *\tentry. This function is only used when drawing the arrow for:\n *\t - a disabled cascade item\n *\t - a cascade item in any state in a torn-off menu\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryArrow(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc we are drawing with */\n    TCL_UNUSED(Tk_3DBorder),\t/* The border when an item is active */\n    int x,\t\t\t/* left edge */\n    int y,\t\t\t/* top edge */\n    int width,\t\t\t/* Width of menu entry */\n    int height,\t\t\t/* Height of menu entry */\n    bool drawArrow)\t\t/* For cascade menus, whether of not to draw\n\t\t\t\t * the arrow. I cannot figure out Windows'\n\t\t\t\t * algorithm for where to draw this. */\n{\n    COLORREF oldFgColor;\n    COLORREF oldBgColor;\n    RECT rect;\n\n    if (!drawArrow || (mePtr->type != CASCADE_ENTRY)) {\n\treturn;\n    }\n\n    /*\n     * Don't draw the arrow if a submenu is not attached to this\n     * cascade entry.\n     */\n\n    if ((mePtr->childMenuRefPtr == NULL)\n\t   || (mePtr->childMenuRefPtr->menuPtr == NULL)) {\n\treturn;\n    }\n\n    oldFgColor = gc->foreground;\n    oldBgColor = gc->background;\n\n    /*\n     * Set bitmap bg to highlight color if the menu is highlighted.\n     */\n\n    if (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1) {\n\tXColor *activeBgColor = Tk_3DBorderColor(Tk_Get3DBorderFromObj(\n\t\tmePtr->menuPtr->tkwin, (mePtr->activeBorderPtr == NULL)\n\t\t? mePtr->menuPtr->activeBorderPtr\n\t\t: mePtr->activeBorderPtr));\n\n\tgc->background = activeBgColor->pixel;\n    }\n\n    gc->foreground = GetSysColor((mePtr->state == ENTRY_DISABLED)\n\t? COLOR_GRAYTEXT\n\t\t: ((mePtr->state == ENTRY_ACTIVE)\n\t\t? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));\n\n    rect.top = y + GetSystemMetrics(SM_CYBORDER);\n    rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER);\n    rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth;\n    rect.right = x + width;\n\n    DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,\n\t    ALIGN_BITMAP_RIGHT);\n\n    gc->foreground = oldFgColor;\n    gc->background = oldBgColor;\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuSeparator --\n *\n *\tThe menu separator is drawn.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nDrawMenuSeparator(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    TCL_UNUSED(GC),\t\t\t/* The gc we are drawing with */\n    TCL_UNUSED(Tk_Font),\t\t/* The precalculated font */\n    TCL_UNUSED(const Tk_FontMetrics *),/* The precalculated font metrics */\n    int x,\t\t\t/* left edge */\n    int y,\t\t\t/* top edge */\n    int width,\t\t\t/* width of item */\n    int height)\t\t\t/* height of item */\n{\n    XPoint points[2];\n    Tk_3DBorder border;\n\n    points[0].x = (short)x;\n    points[0].y = (short)(y + height / 2);\n    points[1].x = (short)(x + width - 1);\n    points[1].y = points[0].y;\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,\n\t    TK_RELIEF_RAISED);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuUnderline --\n *\n *\tOn appropriate platforms, draw the underline character for the menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuUnderline(\n    TkMenu *menuPtr,\t\t/* The menu to draw into */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc to draw into */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int x,\t\t\t/* Left Edge */\n    int y,\t\t\t/* Top Edge */\n    TCL_UNUSED(int),\t\t\t/* Width of entry */\n    int height)\t\t\t/* Height of entry */\n{\n    if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {\n\tTcl_Size len;\n\n\tlen = Tcl_GetCharLength(mePtr->labelPtr);\n\tif (mePtr->underline < len) {\n\t    const char *label, *start, *end;\n\t    int activeBorderWidth, ch;\n\n\t    label = Tcl_GetString(mePtr->labelPtr);\n\t    start = Tcl_UtfAtIndex(label, mePtr->underline);\n\t    end = start + Tcl_UtfToUniChar(start, &ch);\n\t    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\t    menuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\t    Tk_UnderlineChars(menuPtr->display, d,\n\t\t    gc, tkfont, label, x + mePtr->indicatorSpace + activeBorderWidth,\n\t\t    y + (height + fmPtr->ascent - fmPtr->descent) / 2,\n\t\t    (int) (start - label), (int) (end - label));\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWinMenuKeyObjCmd --\n *\n *\tThis function is invoked when keys related to pulling down menus is\n *\tpressed. The corresponding Windows events are generated and passed to\n *\tDefWindowProcW if appropriate. This cmd is registered as tk::WinMenuKey\n *\tin the interp.\n *\n * Results:\n *\tAlways returns TCL_OK.\n *\n * Side effects:\n *\tThe menu system may take over and process user events for menu input.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nTkWinMenuKeyObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    UINT scanCode;\n    UINT virtualKey;\n    XEvent *eventPtr;\n    Tk_Window tkwin;\n    TkWindow *winPtr;\n    KeySym keySym;\n    int i;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"window keySym\");\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]),\n\t    Tk_MainWindow(interp));\n\n    if (tkwin == NULL) {\n\t/*\n\t * If we don't find the key, just return, as the window may have\n\t * been destroyed in the binding. [Bug 1236306]\n\t */\n\treturn TCL_OK;\n    }\n\n    eventPtr = TkpGetBindingXEvent(interp);\n\n    winPtr = (TkWindow *)tkwin;\n\n    if (Tcl_GetIntFromObj(interp, objv[2], &i) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    keySym = i;\n\n    if (eventPtr->type == KeyPress) {\n\tswitch (keySym) {\n\tcase XK_Alt_L:\n\t    scanCode = MapVirtualKeyW(VK_LMENU, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYDOWN, VK_MENU,\n\t\t    (int) (scanCode << 16) | (1 << 29));\n\t    break;\n\tcase XK_Alt_R:\n\t    scanCode = MapVirtualKeyW(VK_RMENU, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYDOWN, VK_MENU,\n\t\t    (int) (scanCode << 16) | (1 << 29) | (1 << 24));\n\t    break;\n\tcase XK_F10:\n\t    scanCode = MapVirtualKeyW(VK_F10, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYDOWN, VK_F10, (int) (scanCode << 16));\n\t    break;\n\tdefault:\n\t    virtualKey = XKeysymToKeycode(winPtr->display, keySym);\n\t    scanCode = MapVirtualKeyW(virtualKey, 0);\n\t    if (0 != scanCode) {\n\t\tTkKeyEvent xkey;\n\t\tmemcpy(&xkey, eventPtr, sizeof(xkey));\n\t\tCallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t\tWM_SYSKEYDOWN, virtualKey,\n\t\t\t(int) ((scanCode << 16) | (1 << 29)));\n\t\tfor (i = 0; i < xkey.nbytes; i++) {\n\t\t    CallWindowProcW(DefWindowProcW,\n\t\t\t    Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR,\n\t\t\t    xkey.trans_chars[i],\n\t\t\t    (int) ((scanCode << 16) | (1 << 29)));\n\t\t}\n\t    }\n\t}\n    } else if (eventPtr->type == KeyRelease) {\n\tswitch (keySym) {\n\tcase XK_Alt_L:\n\t    scanCode = MapVirtualKeyW(VK_LMENU, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16)\n\t\t    | (1 << 29) | (1 << 30) | (1 << 31));\n\t    break;\n\tcase XK_Alt_R:\n\t    scanCode = MapVirtualKeyW(VK_RMENU, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16) | (1 << 24)\n\t\t    | (1 << 29) | (1 << 30) | (1 << 31));\n\t    break;\n\tcase XK_F10:\n\t    scanCode = MapVirtualKeyW(VK_F10, 0);\n\t    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t    WM_SYSKEYUP, VK_F10,\n\t\t    (int) (scanCode << 16) | (1 << 30) | (1 << 31));\n\t    break;\n\tdefault:\n\t    virtualKey = XKeysymToKeycode(winPtr->display, keySym);\n\t    scanCode = MapVirtualKeyW(virtualKey, 0);\n\t    if (0 != scanCode) {\n\t\tCallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),\n\t\t\tWM_SYSKEYUP, virtualKey, (int) ((scanCode << 16)\n\t\t\t| (1 << 29) | (1 << 30) | (1 << 31)));\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpInitializeMenuBindings --\n *\n *\tFor every interp, initializes the bindings for Windows menus. Does\n *\tnothing on Mac or XWindows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tbindings are setup for the interp which will handle Alt-key sequences\n *\tfor menus without beeping or interfering with user-defined Alt-key\n *\tbindings.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpInitializeMenuBindings(\n    Tcl_Interp *interp,\t\t/* The interpreter to set. */\n    Tk_BindingTable bindingTable)\n\t\t\t\t/* The table to add to. */\n{\n    Tk_Uid uid = Tk_GetUid(\"all\");\n\n    /*\n     * We need to set up the bindings for menubars. These have to recreate\n     * windows events, so we need to invoke C code to generate the\n     * WM_SYSKEYDOWNS and WM_SYSKEYUPs appropriately. Trick is, we can't\n     * create a C level binding directly since we may want to modify the\n     * binding in Tcl code.\n     */\n\n    (void) Tcl_CreateObjCommand2(interp, \"tk::WinMenuKey\",\n\t    TkWinMenuKeyObjCmd, Tk_MainWindow(interp), NULL);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<Alt_L>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<KeyRelease-Alt_L>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<Alt_R>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<KeyRelease-Alt_R>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<Alt-Key>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<Alt-KeyRelease>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<Key-F10>\", \"tk::WinMenuKey %W %N\", 0);\n\n    (void) Tk_CreateBinding(interp, bindingTable, (void *)uid,\n\t    \"<KeyRelease-F10>\", \"tk::WinMenuKey %W %N\", 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryLabel --\n *\n *\tThis function draws the label part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its\n *\tcurrent mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryLabel(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* What we are drawing into */\n    GC gc,\t\t\t/* The gc we are drawing into */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */\n    int x,\t\t\t/* left edge */\n    int y,\t\t\t/* right edge */\n    int width,\t\t\t/* width of entry */\n    int height,\t\t\t/* height of entry */\n    bool underline)\t\t/* accelerator cue should be drawn */\n{\n    int indicatorSpace = mePtr->indicatorSpace;\n    int activeBorderWidth;\n    int leftEdge;\n    int imageHeight, imageWidth;\n    int textHeight = 0, textWidth = 0;\n    int haveImage = 0, haveText = 0;\n    int imageXOffset = 0, imageYOffset = 0;\n    int textXOffset = 0, textYOffset = 0;\n\n    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t    menuPtr->activeBorderWidthPtr, &activeBorderWidth);\n    leftEdge = x + indicatorSpace + activeBorderWidth;\n\n    /*\n     * Work out what we will need to draw first.\n     */\n\n    if (mePtr->image != NULL) {\n\tTk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);\n\thaveImage = 1;\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\n\tTk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight);\n\thaveImage = 1;\n    }\n    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {\n\tif (mePtr->labelLength > 0) {\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\n\t    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);\n\t    textHeight = fmPtr->linespace;\n\t    haveText = 1;\n\t}\n    }\n\n    /*\n     * Now work out what the relative positions are.\n     */\n\n    if (haveImage && haveText) {\n\tint fullWidth = (imageWidth > textWidth ? imageWidth : textWidth);\n\tswitch ((enum compound) mePtr->compound) {\n\tcase COMPOUND_TOP:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = imageHeight/2 + 2;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = -textHeight/2;\n\t    break;\n\tcase COMPOUND_BOTTOM:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = -imageHeight/2;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = textHeight/2 + 2;\n\t    break;\n\tcase COMPOUND_LEFT:\n\t    /*\n\t     * The standard image position on Windows is in the indicator\n\t     * space to the left of the entries, unless this entry is a\n\t     * radio|check button because then the indicator space will be\n\t     * used.\n\t     */\n\n\t    textXOffset = imageWidth + 2;\n\t    textYOffset = 0;\n\t    imageXOffset = 0;\n\t    imageYOffset = 0;\n\t    if ((mePtr->type != CHECK_BUTTON_ENTRY)\n\t\t    && (mePtr->type != RADIO_BUTTON_ENTRY)) {\n\t\ttextXOffset -= indicatorSpace;\n\t\tif (textXOffset < 0) {\n\t\t    textXOffset = 0;\n\t\t}\n\t\timageXOffset = -indicatorSpace;\n\t    }\n\t    break;\n\tcase COMPOUND_RIGHT:\n\t    textXOffset = 0;\n\t    textYOffset = 0;\n\t    imageXOffset = textWidth + 2;\n\t    imageYOffset = 0;\n\t    break;\n\tcase COMPOUND_CENTER:\n\t    textXOffset = (fullWidth - textWidth)/2;\n\t    textYOffset = 0;\n\t    imageXOffset = (fullWidth - imageWidth)/2;\n\t    imageYOffset = 0;\n\t    break;\n\tcase COMPOUND_NONE:\n\t    break;\n\t}\n    } else {\n\ttextXOffset = 0;\n\ttextYOffset = 0;\n\timageXOffset = 0;\n\timageYOffset = 0;\n    }\n\n    /*\n     * Draw label and/or bitmap or image for entry.\n     */\n\n    if (mePtr->image != NULL) {\n\tif ((mePtr->selectImage != NULL)\n\t\t&& (mePtr->entryFlags & ENTRY_SELECTED)) {\n\t    Tk_RedrawImage(mePtr->selectImage, 0, 0,\n\t\t    imageWidth, imageHeight, d, leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));\n\t} else {\n\t    Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,\n\t\t    imageHeight, d, leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));\n\t}\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\tXCopyPlane(menuPtr->display, bitmap, d,\tgc, 0, 0,\n\t\t(unsigned) imageWidth, (unsigned) imageHeight,\n\t\tleftEdge + imageXOffset,\n\t\t(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);\n    }\n    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {\n\tif (mePtr->labelLength > 0) {\n\t    int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\n\t    /*\n\t     * Win 95/98 systems draw disabled menu text with a 3D\n\t     * highlight, unless the menu item is highlighted,\n\t     */\n\n\t    if ((mePtr->state == ENTRY_DISABLED) &&\n\t\t    !(mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)) {\n\t\tCOLORREF oldFgColor = gc->foreground;\n\n\t\tgc->foreground = GetSysColor(COLOR_3DHILIGHT);\n\t\tTk_DrawChars(menuPtr->display, d, gc, tkfont, label,\n\t\t\tmePtr->labelLength, leftEdge + textXOffset + 1,\n\t\t\tbaseline + textYOffset + 1);\n\t\tgc->foreground = oldFgColor;\n\t    }\n\t    Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,\n\t\t    mePtr->labelLength, leftEdge + textXOffset,\n\t\t    baseline + textYOffset);\n\t    if (underline) {\n\t\tDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\t\tx + textXOffset, y + textYOffset, width, height);\n\t    }\n\t}\n    }\n\n    if (mePtr->state == ENTRY_DISABLED) {\n\tif (menuPtr->disabledFgPtr == NULL) {\n\t    XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,\n\t\t    (unsigned) width, (unsigned) height);\n\t} else if ((mePtr->image != NULL)\n\t\t&& menuPtr->disabledImageGC) {\n\t    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,\n\t\t    leftEdge + imageXOffset,\n\t\t    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),\n\t\t    (unsigned) imageWidth, (unsigned) imageHeight);\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeMenubarGeometry --\n *\n *\tThis function is invoked to recompute the size and layout of a menu\n *\tthat is a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeMenubarGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    TkpComputeStandardMenuGeometry(menuPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawTearoffEntry --\n *\n *\tThis function draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nDrawTearoffEntry(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing */\n    TCL_UNUSED(TkMenuEntry *),\t\t/* The entry we are drawing */\n    Drawable d,\t\t\t/* The drawable we are drawing into */\n    TCL_UNUSED(GC),\t\t\t/* The gc we are drawing with */\n    TCL_UNUSED(Tk_Font),\t\t/* The font we are drawing with */\n    TCL_UNUSED(const Tk_FontMetrics *),/* The metrics we are drawing with */\n    int x, int y,\n    int width, int height)\n{\n    XPoint points[2];\n    int segmentWidth, maxX;\n    Tk_3DBorder border;\n\n    if (menuPtr->menuType != MAIN_MENU) {\n\treturn;\n    }\n\n    points[0].x = (short)x;\n    points[0].y = (short)(y + height/2);\n    points[1].y = points[0].y;\n    segmentWidth = 6;\n    maxX = x + width - 1;\n    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);\n\n    while (points[0].x < maxX) {\n\tpoints[1].x = points[0].x + (short)segmentWidth;\n\tif (points[1].x > maxX) {\n\t    points[1].x = (short)maxX;\n\t}\n\tTk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,\n\t\tTK_RELIEF_RAISED);\n\tpoints[0].x += (short)(2*segmentWidth);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureMenuEntry --\n *\n *\tProcesses configurations for menu entries.\n *\n * Results:\n *\tReturns standard TCL result. If TCL_ERROR is returned, then the\n *\tinterp's result contains an error message.\n *\n * Side effects:\n *\tConfiguration information get set for mePtr; old resources get freed,\n *\tif any need it.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpConfigureMenuEntry(\n    TkMenuEntry *mePtr)/* Information about menu entry; may or may\n\t\t\t\t * not already have values for some fields. */\n{\n    ScheduleMenuReconfigure(mePtr->menuPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDrawMenuEntry --\n *\n *\tDraws the given menu entry at the given coordinates with the given\n *\tattributes.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tX Server commands are executed to display the menu entry.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDrawMenuEntry(\n    TkMenuEntry *mePtr,\t\t/* The entry to draw */\n    Drawable menuDrawable,\t/* Menu to draw into */\n    Tk_Font tkfont,\t\t/* Precalculated font for menu */\n    const Tk_FontMetrics *menuMetricsPtr,\n\t\t\t\t/* Precalculated metrics for menu */\n    int x,\t\t\t/* X-coordinate of topleft of entry */\n    int y,\t\t\t/* Y-coordinate of topleft of entry */\n    int width,\t\t\t/* Width of the entry rectangle */\n    int height,\t\t\t/* Height of the current rectangle */\n    DrawMenuFlags drawingParameters)\t/* Flags */\n{\n    GC gc, indicatorGC;\n    TkMenu *menuPtr = mePtr->menuPtr;\n    Tk_3DBorder bgBorder, activeBorder;\n    const Tk_FontMetrics *fmPtr;\n    Tk_FontMetrics entryMetrics;\n    int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;\n    int adjustedX, adjustedY;\n    int adjustedHeight = height - 2 * padY;\n    TkWinDrawable memWinDraw;\n    TkWinDCState dcState;\n    HBITMAP oldBitmap = NULL;\n    Drawable d;\n    HDC memDc = NULL, menuDc = NULL;\n\n    /*\n     * If the menu entry includes an image then draw the entry into a\n     * compatible bitmap first.  This avoids problems with clipping on\n     * animated menus.  [Bug 1329198]\n     */\n\n    if (mePtr->image != NULL) {\n\tmenuDc = TkWinGetDrawableDC(menuPtr->display, menuDrawable, &dcState);\n\n\tmemDc = CreateCompatibleDC(menuDc);\n\toldBitmap = (HBITMAP)SelectObject(memDc,\n\t\t\tCreateCompatibleBitmap(menuDc, width, height) );\n\n\tmemWinDraw.type = TWD_WINDC;\n\tmemWinDraw.winDC.hdc = memDc;\n\td = (Drawable)&memWinDraw;\n\tadjustedX = 0;\n\tadjustedY = padY;\n\n    } else {\n\td = menuDrawable;\n\tadjustedX = x;\n\tadjustedY = y + padY;\n    }\n\n    /*\n     * Choose the gc for drawing the foreground part of the entry.\n     */\n\n    if ((mePtr->state == ENTRY_ACTIVE) && !(drawingParameters & DRAW_MENU_ENTRY_STRICTMOTIF)) {\n\tgc = mePtr->activeGC;\n\tif (gc == NULL) {\n\t    gc = menuPtr->activeGC;\n\t}\n    } else {\n\tTkMenuEntry *cascadeEntryPtr;\n\tint parentDisabled = 0;\n\tconst char *name;\n\n\tfor (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;\n\t\tcascadeEntryPtr != NULL;\n\t\tcascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {\n\t    name = Tcl_GetString(cascadeEntryPtr->namePtr);\n\t    if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {\n\t\tif (mePtr->state == ENTRY_DISABLED) {\n\t\t    parentDisabled = 1;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\n\tif (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))\n\t\t&& (menuPtr->disabledFgPtr != NULL)) {\n\t    gc = mePtr->disabledGC;\n\t    if (gc == NULL) {\n\t\tgc = menuPtr->disabledGC;\n\t    }\n\t} else {\n\t    gc = mePtr->textGC;\n\t    if (gc == NULL) {\n\t\tgc = menuPtr->textGC;\n\t    }\n\t}\n    }\n    indicatorGC = mePtr->indicatorGC;\n    if (indicatorGC == NULL) {\n\tindicatorGC = menuPtr->indicatorGC;\n    }\n\n    bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t    (mePtr->borderPtr == NULL) ? menuPtr->borderPtr\n\t    : mePtr->borderPtr);\n    if (drawingParameters & DRAW_MENU_ENTRY_STRICTMOTIF) {\n\tactiveBorder = bgBorder;\n    } else {\n\tactiveBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,\n\t    (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr\n\t    : mePtr->activeBorderPtr);\n    }\n\n    if (mePtr->fontPtr == NULL) {\n\tfmPtr = menuMetricsPtr;\n    } else {\n\ttkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);\n\tTk_GetFontMetrics(tkfont, &entryMetrics);\n\tfmPtr = &entryMetrics;\n    }\n\n    /*\n     * Need to draw the entire background, including padding. On Unix, for\n     * menubars, we have to draw the rest of the entry taking into account the\n     * padding.\n     */\n\n    DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,\n\t    bgBorder, adjustedX, adjustedY-padY, width, height);\n\n    if (mePtr->type == SEPARATOR_ENTRY) {\n\tDrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,\n\t\tfmPtr, adjustedX, adjustedY, width, adjustedHeight);\n    } else if (mePtr->type == TEAROFF_ENTRY) {\n\tDrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\tadjustedX, adjustedY, width, adjustedHeight);\n    } else {\n\tDrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\tadjustedX, adjustedY, width, adjustedHeight,\n\t\t!(drawingParameters & DRAW_MENU_ENTRY_NOUNDERLINE));\n\tDrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,\n\t\tactiveBorder, adjustedX, adjustedY, width, adjustedHeight);\n\tDrawMenuEntryArrow(menuPtr, mePtr, d, gc,\n\t\tactiveBorder, adjustedX, adjustedY, width, adjustedHeight,\n\t\t(drawingParameters & DRAW_MENU_ENTRY_ARROW) != 0);\n\tif (!mePtr->hideMargin) {\n\t    DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,\n\t\t    fmPtr, adjustedX, adjustedY, width, adjustedHeight);\n\t}\n    }\n\n    /*\n     * Copy the entry contents from the temporary bitmap to the menu.\n     */\n\n    if (mePtr->image != NULL) {\n\tBitBlt(menuDc, x, y, width, height, memDc, 0, 0, SRCCOPY);\n\tDeleteObject(SelectObject(memDc, oldBitmap));\n\tDeleteDC(memDc);\n\n\tTkWinReleaseDrawableDC(menuDrawable, menuDc, &dcState);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMenuLabelGeometry --\n *\n *\tFigures out the size of the label portion of a menu item.\n *\n * Results:\n *\twidthPtr and heightPtr are filled in with the correct geometry\n *\tinformation.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMenuLabelGeometry(\n    TkMenuEntry *mePtr,\t\t/* The entry we are computing */\n    Tk_Font tkfont,\t\t/* The precalculated font */\n    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */\n    int *widthPtr,\t\t/* The resulting width of the label portion */\n    int *heightPtr)\t\t/* The resulting height of the label\n\t\t\t\t * portion */\n{\n    TkMenu *menuPtr = mePtr->menuPtr;\n    int haveImage = 0;\n\n    if (mePtr->image != NULL) {\n\tTk_SizeOfImage(mePtr->image, widthPtr, heightPtr);\n\thaveImage = 1;\n    } else if (mePtr->bitmapPtr != NULL) {\n\tPixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);\n\n\tTk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);\n\thaveImage = 1;\n    } else {\n\t*heightPtr = 0;\n\t*widthPtr = 0;\n    }\n\n    if (haveImage && (mePtr->compound == COMPOUND_NONE)) {\n\t/*\n\t * We don't care about the text in this case.\n\t */\n    } else {\n\t/*\n\t * Either it is compound or we don't have an image,\n\t */\n\n\tif (mePtr->labelPtr != NULL) {\n\t    int textWidth;\n\t    const char *label = Tcl_GetString(mePtr->labelPtr);\n\n\t    textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength);\n\n\t    if ((mePtr->compound != COMPOUND_NONE) && haveImage) {\n\t\tswitch ((enum compound) mePtr->compound) {\n\t\tcase COMPOUND_TOP:\n\t\tcase COMPOUND_BOTTOM:\n\t\t    if (textWidth > *widthPtr) {\n\t\t\t*widthPtr = textWidth;\n\t\t    }\n\n\t\t    /*\n\t\t     * Add text and padding.\n\t\t     */\n\n\t\t    *heightPtr += fmPtr->linespace + 2;\n\t\t    break;\n\t\tcase COMPOUND_LEFT:\n\t\tcase COMPOUND_RIGHT:\n\t\t    if (fmPtr->linespace > *heightPtr) {\n\t\t\t*heightPtr = fmPtr->linespace;\n\t\t    }\n\n\t\t    /*\n\t\t     * Add text and padding.\n\t\t     */\n\n\t\t    *widthPtr += textWidth + 2;\n\t\t    break;\n\t\tcase COMPOUND_CENTER:\n\t\t    if (fmPtr->linespace > *heightPtr) {\n\t\t\t*heightPtr = fmPtr->linespace;\n\t\t    }\n\t\t    if (textWidth > *widthPtr) {\n\t\t\t*widthPtr = textWidth;\n\t\t    }\n\t\t    break;\n\t\tcase COMPOUND_NONE:\n\t\t    break;\n\t\t}\n\t    } else {\n\t\t/*\n\t\t * We don't have an image or we're not compound.\n\t\t */\n\n\t\t*heightPtr = fmPtr->linespace;\n\t\t*widthPtr = textWidth;\n\t    }\n\t} else {\n\t    /*\n\t     * An empty entry still has this height.\n\t     */\n\n\t    *heightPtr = fmPtr->linespace;\n\t}\n    }\n    *heightPtr += 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DrawMenuEntryBackground --\n *\n *\tThis function draws the background part of a menu.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCommands are output to X to display the menu in its current mode.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDrawMenuEntryBackground(\n    TkMenu *menuPtr,\t\t/* The menu we are drawing. */\n    TkMenuEntry *mePtr,\t\t/* The entry we are drawing. */\n    Drawable d,\t\t\t/* What we are drawing into */\n    Tk_3DBorder activeBorder,\t/* Border for active items */\n    Tk_3DBorder bgBorder,\t/* Border for the background */\n    int x,\t\t\t/* left edge */\n    int y,\t\t\t/* top edge */\n    int width,\t\t\t/* width of rectangle to draw */\n    int height)\t\t\t/* height of rectangle to draw */\n{\n    if (mePtr->state == ENTRY_ACTIVE\n\t\t|| (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)!=0 ) {\n\tint relief;\n\tint activeBorderWidth;\n\n\tbgBorder = activeBorder;\n\n\tif ((menuPtr->menuType == MENUBAR)\n\t\t&& ((menuPtr->postedCascade == NULL)\n\t\t|| (menuPtr->postedCascade != mePtr))) {\n\t    relief = TK_RELIEF_FLAT;\n\t} else {\n\t    relief = menuPtr->activeRelief;\n\t}\n\tTk_GetPixelsFromObj(NULL, menuPtr->tkwin,\n\t\tmenuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\tTk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,\n\t\tactiveBorderWidth, relief);\n    } else {\n\tTk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, 0,\n\t\tTK_RELIEF_FLAT);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpComputeStandardMenuGeometry --\n *\n *\tThis function is invoked to recompute the size and layout of a menu\n *\tthat is not a menubar clone.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFields of menu entries are changed to reflect their current positions,\n *\tand the size of the menu window itself may be changed.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpComputeStandardMenuGeometry(\n    TkMenu *menuPtr)\t\t/* Structure describing menu. */\n{\n    Tk_Font menuFont, tkfont;\n    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;\n    int x, y, height, width, indicatorSpace, labelWidth, accelWidth;\n    int windowWidth, windowHeight, accelSpace;\n    Tcl_Size i, j, lastColumnBreak = 0;\n    int activeBorderWidth, borderWidth;\n\n    if (menuPtr->tkwin == NULL) {\n\treturn;\n    }\n\n    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t    menuPtr->borderWidthObj, &borderWidth);\n    x = y = borderWidth;\n    indicatorSpace = labelWidth = accelWidth = 0;\n    windowHeight = 0;\n\n    /*\n     * On the Mac especially, getting font metrics can be quite slow, so we\n     * want to do it intelligently. We are going to precalculate them and pass\n     * them down to all of the measuring and drawing routines. We will measure\n     * the font metrics of the menu once. If an entry does not have its own\n     * font set, then we give the geometry/drawing routines the menu's font\n     * and metrics. If an entry has its own font, we will measure that font\n     * and give all of the geometry/drawing the entry's font and metrics.\n     */\n\n    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);\n    Tk_GetFontMetrics(menuFont, &menuMetrics);\n    accelSpace = Tk_TextWidth(menuFont, \"M\", 1);\n    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,\n\t    menuPtr->activeBorderWidthPtr, &activeBorderWidth);\n\n    for (i = 0; i < (int)menuPtr->numEntries; i++) {\n\tif (menuPtr->entries[i]->fontPtr == NULL) {\n\t    tkfont = menuFont;\n\t    fmPtr = &menuMetrics;\n\t} else {\n\t    tkfont = Tk_GetFontFromObj(menuPtr->tkwin,\n\t\t    menuPtr->entries[i]->fontPtr);\n\t    Tk_GetFontMetrics(tkfont, &entryMetrics);\n\t    fmPtr = &entryMetrics;\n\t}\n\tif ((i > 0) && menuPtr->entries[i]->columnBreak) {\n\t    if (accelWidth != 0) {\n\t\tlabelWidth += accelSpace;\n\t    }\n\t    for (j = lastColumnBreak; j < i; j++) {\n\t\tmenuPtr->entries[j]->indicatorSpace = indicatorSpace;\n\t\tmenuPtr->entries[j]->labelWidth = labelWidth;\n\t\tmenuPtr->entries[j]->width = indicatorSpace + labelWidth\n\t\t\t+ accelWidth + 2 * activeBorderWidth;\n\t\tmenuPtr->entries[j]->x = x;\n\t\tmenuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;\n\t    }\n\t    x += indicatorSpace + labelWidth + accelWidth\n\t\t    + 2 * activeBorderWidth;\n\t    indicatorSpace = labelWidth = accelWidth = 0;\n\t    lastColumnBreak = i;\n\t    y = borderWidth;\n\t}\n\n\tif (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {\n\t    GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,\n\t\t    fmPtr, &width, &height);\n\t    menuPtr->entries[i]->height = height;\n\t} else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {\n\t    GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,\n\t\t    fmPtr, &width, &height);\n\t    menuPtr->entries[i]->height = height;\n\t} else {\n\t    /*\n\t     * For each entry, compute the height required by that particular\n\t     * entry, plus three widths: the width of the label, the width to\n\t     * allow for an indicator to be displayed to the left of the label\n\t     * (if any), and the width of the accelerator to be displayed to\n\t     * the right of the label (if any). These sizes depend, of course,\n\t     * on the type of the entry.\n\t     */\n\n\t    GetMenuLabelGeometry(menuPtr->entries[i], tkfont, fmPtr, &width,\n\t\t    &height);\n\t    menuPtr->entries[i]->height = height;\n\t    if (width > labelWidth) {\n\t\tlabelWidth = width;\n\t    }\n\n\t    GetMenuAccelGeometry(menuPtr, menuPtr->entries[i], tkfont,\n\t\t    fmPtr, &width, &height);\n\t    if (height > menuPtr->entries[i]->height) {\n\t\tmenuPtr->entries[i]->height = height;\n\t    }\n\t    if (width > accelWidth) {\n\t\taccelWidth = width;\n\t    }\n\n\t    GetMenuIndicatorGeometry(menuPtr, menuPtr->entries[i], tkfont,\n\t\t    fmPtr, &width, &height);\n\t    if (height > menuPtr->entries[i]->height) {\n\t\tmenuPtr->entries[i]->height = height;\n\t    }\n\t    if (width > indicatorSpace) {\n\t\tindicatorSpace = width;\n\t    }\n\n\t    menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;\n\t}\n\tmenuPtr->entries[i]->y = y;\n\ty += menuPtr->entries[i]->height;\n\tif (y > windowHeight) {\n\t    windowHeight = y;\n\t}\n    }\n\n    if (accelWidth != 0) {\n\tlabelWidth += accelSpace;\n    }\n    for (j = lastColumnBreak; j < (int)menuPtr->numEntries; j++) {\n\tmenuPtr->entries[j]->indicatorSpace = indicatorSpace;\n\tmenuPtr->entries[j]->labelWidth = labelWidth;\n\tmenuPtr->entries[j]->width = indicatorSpace + labelWidth\n\t\t+ accelWidth + 2 * activeBorderWidth;\n\tmenuPtr->entries[j]->x = x;\n\tmenuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;\n    }\n    windowWidth = x + indicatorSpace + labelWidth + accelWidth\n\t    + 2 * activeBorderWidth + borderWidth;\n    windowHeight += borderWidth;\n\n    /*\n     * The X server doesn't like zero dimensions, so round up to at least 1 (a\n     * zero-sized menu should never really occur, anyway).\n     */\n\n    if (windowWidth <= 0) {\n\twindowWidth = 1;\n    }\n    if (windowHeight <= 0) {\n\twindowHeight = 1;\n    }\n    menuPtr->totalWidth = windowWidth;\n    menuPtr->totalHeight = windowHeight;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuSelectEvent --\n *\n *\tGenerates a \"MenuSelect\" virtual event. This can be used to do\n *\tcontext-sensitive menu help.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPlaces a virtual event on the event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuSelectEvent(\n    TkMenu *menuPtr)\t\t/* the menu we have selected. */\n{\n    union {XEvent general; XVirtualEvent virt;} event;\n    union {DWORD msgpos; POINTS point;} root;\n\n    memset(&event, 0, sizeof(event));\n    event.virt.type = VirtualEvent;\n    event.virt.serial = LastKnownRequestProcessed(menuPtr->display);\n    event.virt.send_event = 0;\n    event.virt.display = menuPtr->display;\n    Tk_MakeWindowExist(menuPtr->tkwin);\n    event.virt.event = Tk_WindowId(menuPtr->tkwin);\n    event.virt.root = XRootWindow(menuPtr->display, 0);\n    event.virt.subwindow = None;\n    event.virt.time = TkpGetMS();\n\n    root.msgpos = GetMessagePos();\n    event.virt.x_root = root.point.x;\n    event.virt.y_root = root.point.y;\n    event.virt.state = TkWinGetModifierState();\n    event.virt.same_screen = 1;\n    event.virt.name = Tk_GetUid(\"MenuSelect\");\n    event.virt.user_data = NULL;\n    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuNotifyToplevelCreate --\n *\n *\tThis routine reconfigures the menu and the clones indicated by\n *\tmenuName becuase a toplevel has been created and any system menus need\n *\tto be created.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAn idle handler is set up to do the reconfiguration.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuNotifyToplevelCreate(\n    Tcl_Interp *interp,\t\t/* The interp the menu lives in. */\n    const char *menuName)\t/* The name of the menu to reconfigure. */\n{\n    TkMenuReferences *menuRefPtr;\n    TkMenu *menuPtr;\n\n    if ((menuName != NULL) && (menuName[0] != '\\0')) {\n\tmenuRefPtr = TkFindMenuReferences(interp, menuName);\n\tif ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {\n\t    for (menuPtr = menuRefPtr->menuPtr->mainMenuPtr; menuPtr != NULL;\n\t\t    menuPtr = menuPtr->nextInstancePtr) {\n\t\tif (menuPtr->menuType == MENUBAR) {\n\t\t    ScheduleMenuReconfigure(menuPtr);\n\t\t}\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetMenuHWND --\n *\n *\tThis function returns the HWND of a hidden menu Window that processes\n *\tmessages of a popup menu. This hidden menu window is used to handle\n *\teither a dynamic popup menu in the same process or a pull-down menu of\n *\tan embedded window in a different process.\n *\n * Results:\n *\tReturns the HWND of the hidden menu Window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHWND\nTkGetMenuHWND(\n    TCL_UNUSED(Tk_Window))\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    TkMenuInit();\n    return tsdPtr->embeddedMenuHWND;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuExitHandler --\n *\n *\tUnregisters the class of utility windows.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMenus have to be reinitialized next time.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuExitHandler(\n    TCL_UNUSED(void *))\t    /* Not used */\n{\n    UnregisterClassW(MENU_CLASS_NAME, Tk_GetHINSTANCE());\n    UnregisterClassW(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MenuExitHandler --\n *\n *\tThrows away the utility window needed for menus and delete hash\n *\ttables.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMenus have to be reinitialized next time.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nMenuThreadExitHandler(\n    TCL_UNUSED(void *))\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    DestroyWindow(tsdPtr->menuHWND);\n    DestroyWindow(tsdPtr->embeddedMenuHWND);\n    tsdPtr->menuHWND = NULL;\n    tsdPtr->embeddedMenuHWND = NULL;\n\n    Tcl_DeleteHashTable(&tsdPtr->winMenuTable);\n    Tcl_DeleteHashTable(&tsdPtr->commandTable);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetMenuSystemDefault --\n *\n *\tGets the Windows specific default value for a given X resource\n *\tdatabase name.\n *\n * Results:\n *\tReturns a Tcl_Obj* with the default value. If there is no\n *\tWindows-specific default for this attribute, returns NULL. This object\n *\thas a ref count of 0.\n *\n * Side effects:\n *\tStorage is allocated.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Obj *\nTkWinGetMenuSystemDefault(\n    TCL_UNUSED(Tk_Window),\t\t/* A window to use. */\n    const char *dbName,\t\t/* The option database name. */\n    TCL_UNUSED(const char *))\t/* The name of the option class. */\n{\n    Tcl_Obj *valuePtr = NULL;\n\n    if ((strcmp(dbName, \"activeBorderWidth\") == 0) ||\n\t    (strcmp(dbName, \"borderWidth\") == 0)) {\n\tvaluePtr = Tcl_NewWideIntObj(defaultBorderWidth);\n    } else if (strcmp(dbName, \"font\") == 0) {\n\tvaluePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString), TCL_INDEX_NONE);\n    }\n\n    return valuePtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetDefaults --\n *\n *\tRead system menu settings (font, sizes of items, use of accelerators)\n *\tThis is called if the UI theme or settings are changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay result in menu items being redrawn with different appearance.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSetDefaults(\n    int firstTime)\t\t/* Is this the first time this has been\n\t\t\t\t * called? */\n{\n    char sizeString[TCL_INTEGER_SPACE];\n    char faceName[LF_FACESIZE];\n    HDC scratchDC;\n    int bold = 0;\n    int italic = 0;\n    TEXTMETRICW tm;\n    int pointSize;\n    HFONT menuFont;\n    /* See: [Bug #3239768] tk8.4.19 (and later) WIN32 menu font support */\n    NONCLIENTMETRICSW metrics;\n\n    /*\n     * Set all of the default options. The loop will terminate when we run out\n     * of options via a break statement.\n     */\n\n    defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);\n    if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {\n\tdefaultBorderWidth = GetSystemMetrics(SM_CYBORDER);\n    }\n\n    scratchDC = CreateDCW(L\"DISPLAY\", NULL, NULL, NULL);\n    if (!firstTime) {\n\tTcl_DStringFree(&menuFontDString);\n    }\n    Tcl_DStringInit(&menuFontDString);\n\n    metrics.cbSize = sizeof(metrics);\n\n    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, metrics.cbSize,\n\t    &metrics, 0);\n    menuFont = CreateFontIndirectW(&metrics.lfMenuFont);\n    SelectObject(scratchDC, menuFont);\n    GetTextMetricsW(scratchDC, &tm);\n    GetTextFaceA(scratchDC, LF_FACESIZE, faceName);\n    pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,\n\t    72, GetDeviceCaps(scratchDC, LOGPIXELSY));\n    if (tm.tmWeight >= 700) {\n\tbold = 1;\n    }\n    if (tm.tmItalic) {\n\titalic = 1;\n    }\n\n    SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));\n    DeleteDC(scratchDC);\n\n    DeleteObject(menuFont);\n\n    Tcl_DStringAppendElement(&menuFontDString, faceName);\n    snprintf(sizeString, sizeof(sizeString), \"%d\", pointSize);\n    Tcl_DStringAppendElement(&menuFontDString, sizeString);\n\n    if (bold || italic) {\n\tTcl_DString boldItalicDString;\n\n\tTcl_DStringInit(&boldItalicDString);\n\tif (bold) {\n\t    Tcl_DStringAppendElement(&boldItalicDString, \"bold\");\n\t}\n\tif (italic) {\n\t    Tcl_DStringAppendElement(&boldItalicDString, \"italic\");\n\t}\n\tTcl_DStringAppendElement(&menuFontDString,\n\t\tTcl_DStringValue(&boldItalicDString));\n\tTcl_DStringFree(&boldItalicDString);\n    }\n\n    /*\n     * Now we go ahead and get the dimensions of the check mark and the\n     * appropriate margins. Since this is fairly hairy, we do it here to save\n     * time when traversing large sets of menu items.\n     *\n     * The code below was given to me by Microsoft over the phone. It is the\n     * only way to ensure menu items line up, and is not documented.\n     * How strange the calculation of indicatorDimensions[1] is...!\n     */\n\n    indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);\n    indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +\n\t    GetSystemMetrics(SM_CXBORDER)\n\t    + GetSystemMetrics(SM_CXMENUCHECK) + 7) & 0xFFF8)\n\t    - GetSystemMetrics(SM_CXFIXEDFRAME);\n\n    /*\n     * Accelerators used to be always underlines until Win2K when a system\n     * parameter was introduced to hide them unless Alt is pressed.\n     */\n\n    showMenuAccelerators = TRUE;\n    SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuInit --\n *\n *\tSets up the process-wide variables used by the menu package.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tlastMenuID gets initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuInit(void)\n{\n    WNDCLASSW wndClass;\n\n    wndClass.style = CS_OWNDC;\n    wndClass.lpfnWndProc = TkWinMenuProc;\n    wndClass.cbClsExtra = 0;\n    wndClass.cbWndExtra = 0;\n    wndClass.hInstance = Tk_GetHINSTANCE();\n    wndClass.hIcon = NULL;\n    wndClass.hCursor = NULL;\n    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\n    wndClass.lpszMenuName = NULL;\n    wndClass.lpszClassName = MENU_CLASS_NAME;\n    if (!RegisterClassW(&wndClass)) {\n\tTcl_Panic(\"Failed to register menu window class\");\n    }\n\n    wndClass.lpfnWndProc = TkWinEmbeddedMenuProc;\n    wndClass.lpszClassName = EMBEDDED_MENU_CLASS_NAME;\n    if (!RegisterClassW(&wndClass)) {\n\tTcl_Panic(\"Failed to register embedded menu window class\");\n    }\n\n    TkCreateExitHandler(MenuExitHandler, NULL);\n    SetDefaults(1);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMenuThreadInit --\n *\n *\tSets up the thread-local hash tables used by the menu module. Assumes\n *\tthat TkpMenuInit has been called.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tHash tables winMenuTable and commandTable are initialized.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMenuThreadInit(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->menuHWND = CreateWindowW(MENU_CLASS_NAME, L\"MenuWindow\", WS_POPUP,\n\t    0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);\n\n    if (!tsdPtr->menuHWND) {\n\tTcl_Panic(\"Failed to create the menu window\");\n    }\n\n    tsdPtr->embeddedMenuHWND =\n\t    CreateWindowW(EMBEDDED_MENU_CLASS_NAME, L\"EmbeddedMenuWindow\",\n\t    WS_POPUP, 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);\n\n    if (!tsdPtr->embeddedMenuHWND) {\n\tTcl_Panic(\"Failed to create the embedded menu window\");\n    }\n\n    Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);\n    Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);\n\n    TkCreateThreadExitHandler(MenuThreadExitHandler, NULL);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinPixmap.c",
    "content": "/*\n * tkWinPixmap.c --\n *\n *\tThis file contains the Xlib emulation functions pertaining to creating\n *\tand destroying pixmaps.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetPixmap --\n *\n *\tCreates an in memory drawing surface.\n *\n * Results:\n *\tReturns a handle to a new pixmap.\n *\n * Side effects:\n *\tAllocates a new Win32 bitmap.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nTk_GetPixmap(\n    Display *display,\n    Drawable d,\n    int width,\n    int height,\n    int depth)\n{\n    TkWinDrawable *newTwdPtr, *twdPtr;\n    DWORD planes;\n    Screen *screen;\n\n    LastKnownRequestProcessed(display)++;\n\n    newTwdPtr = (TkWinDrawable *)Tcl_Alloc(sizeof(TkWinDrawable));\n    newTwdPtr->type = TWD_BITMAP;\n    newTwdPtr->bitmap.depth = depth;\n    twdPtr = (TkWinDrawable *) d;\n    if (twdPtr->type != TWD_BITMAP) {\n\tif (twdPtr->window.winPtr == NULL) {\n\t    newTwdPtr->bitmap.colormap = DefaultColormap(display,\n\t\t    DefaultScreen(display));\n\t} else {\n\t    newTwdPtr->bitmap.colormap = twdPtr->window.winPtr->atts.colormap;\n\t}\n    } else {\n\tnewTwdPtr->bitmap.colormap = twdPtr->bitmap.colormap;\n    }\n    screen = ScreenOfDisplay(display, 0);\n    planes = 1;\n    if (depth == DefaultDepthOfScreen(screen)) {\n\tplanes = (DWORD)PTR2INT(screen->ext_data);\n\tdepth /= planes;\n    }\n    newTwdPtr->bitmap.handle =\n\t    CreateBitmap(width, height, planes, (DWORD) depth, NULL);\n\n    /*\n     * CreateBitmap tries to use memory on the graphics card. If it fails,\n     * call CreateDIBSection which uses real memory; slower, but at least\n     * still works. [Bug 2080533]\n     */\n\n    if (newTwdPtr->bitmap.handle == NULL) {\n\tstatic int repeatError = 0;\n\tvoid *bits = NULL;\n\tBITMAPINFO bitmapInfo;\n\tHDC dc;\n\n\tmemset(&bitmapInfo, 0, sizeof(bitmapInfo));\n\tbitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);\n\tbitmapInfo.bmiHeader.biWidth = width;\n\tbitmapInfo.bmiHeader.biHeight = height;\n\tbitmapInfo.bmiHeader.biPlanes = (WORD)planes;\n\tbitmapInfo.bmiHeader.biBitCount = (WORD)depth;\n\tbitmapInfo.bmiHeader.biCompression = BI_RGB;\n\tbitmapInfo.bmiHeader.biSizeImage = 0;\n\tdc = GetDC(NULL);\n\tnewTwdPtr->bitmap.handle = CreateDIBSection(dc, &bitmapInfo,\n\t\tDIB_RGB_COLORS, &bits, 0, 0);\n\tReleaseDC(NULL, dc);\n\n\t/*\n\t * Oh no! Things are still going wrong. Pop up a warning message here\n\t * (because things will probably crash soon) which will encourage\n\t * people to report this as a bug...\n\t */\n\n\tif (newTwdPtr->bitmap.handle == NULL && !repeatError) {\n\t    LPVOID lpMsgBuf;\n\n\t    repeatError = 1;\n\t    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |\n\t\t    FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,\n\t\t    NULL, GetLastError(),\n\t\t    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n\t\t    (LPWSTR)&lpMsgBuf, 0, NULL)) {\n\t\tMessageBoxW(NULL, (LPWSTR) lpMsgBuf,\n\t\t\tL\"Tk_GetPixmap: Error from CreateDIBSection\",\n\t\t\tMB_OK | MB_ICONINFORMATION);\n\t\tLocalFree(lpMsgBuf);\n\t    }\n\t}\n    }\n\n    if (newTwdPtr->bitmap.handle == NULL) {\n\tTcl_Free(newTwdPtr);\n\treturn None;\n    }\n\n    return (Pixmap) newTwdPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_FreePixmap --\n *\n *\tRelease the resources associated with a pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDeletes the bitmap created by Tk_GetPixmap.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_FreePixmap(\n    Display *display,\n    Pixmap pixmap)\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *) pixmap;\n\n    LastKnownRequestProcessed(display)++;\n    if (twdPtr != NULL) {\n\tDeleteObject(twdPtr->bitmap.handle);\n\tTcl_Free(twdPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkSetPixmapColormap --\n *\n *\tThe following function is a hack used by the photo widget to\n *\texplicitly set the colormap slot of a Pixmap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkSetPixmapColormap(\n    Pixmap pixmap,\n    Colormap colormap)\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *)pixmap;\n    twdPtr->bitmap.colormap = colormap;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetGeometry --\n *\n *\tRetrieve the geometry of the given drawable. Note that this is a\n *\tdegenerate implementation that only returns the size of a pixmap or\n *\twindow.\n *\n * Results:\n *\tReturns 0.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXGetGeometry(\n    TCL_UNUSED(Display *),\n    Drawable d,\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    unsigned int *width_return,\n    unsigned int *height_return,\n    TCL_UNUSED(unsigned int *),\n    TCL_UNUSED(unsigned int *))\n{\n    TkWinDrawable *twdPtr = (TkWinDrawable *)d;\n\n    if (twdPtr->type == TWD_BITMAP) {\n\tHDC dc;\n\tBITMAPINFO info;\n\n\tif (twdPtr->bitmap.handle == NULL) {\n\t    Tcl_Panic(\"XGetGeometry: invalid pixmap\");\n\t}\n\tdc = GetDC(NULL);\n\tinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n\tinfo.bmiHeader.biBitCount = 0;\n\tif (!GetDIBits(dc, twdPtr->bitmap.handle, 0, 0, NULL, &info,\n\t\tDIB_RGB_COLORS)) {\n\t    Tcl_Panic(\"XGetGeometry: unable to get bitmap size\");\n\t}\n\tReleaseDC(NULL, dc);\n\n\t*width_return = info.bmiHeader.biWidth;\n\t*height_return = info.bmiHeader.biHeight;\n    } else if (twdPtr->type == TWD_WINDOW) {\n\tRECT rect;\n\n\tif (twdPtr->window.handle == NULL) {\n\t    Tcl_Panic(\"XGetGeometry: invalid window\");\n\t}\n\tGetClientRect(twdPtr->window.handle, &rect);\n\t*width_return = rect.right - rect.left;\n\t*height_return = rect.bottom - rect.top;\n    } else {\n\tTcl_Panic(\"XGetGeometry: invalid window\");\n    }\n    return 1;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinPointer.c",
    "content": "/*\n * tkWinPointer.c --\n *\n *\tWindows specific mouse tracking code.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n/*\n * Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds.\n */\n\n#define MOUSE_TIMER_INTERVAL 250\n\n/*\n * Declarations of static variables used in this file.\n */\n\nstatic TkWindow *keyboardWinPtr = NULL; /* Current keyboard grab window. */\nstatic Tcl_TimerToken mouseTimer;\t/* Handle to the latest mouse timer. */\nstatic bool mouseTimerSet = false;\t\t/* true if the mouse timer is active. */\nstatic bool captured = false;\t\t/* 1 if mouse is currently captured. */\n\n/*\n * Forward declarations of procedures used in this file.\n */\n\nstatic void\t\tMouseTimerProc(void *clientData);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetModifierState --\n *\n *\tReturn the modifier state as of the last message.\n *\n * Results:\n *\tReturns the X modifier mask.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nunsigned int\nTkWinGetModifierState(void)\n{\n    unsigned int state = 0;\n\n    if (GetKeyState(VK_SHIFT) & 0x8000) {\n\tstate |= ShiftMask;\n    }\n    if (GetKeyState(VK_CONTROL) & 0x8000) {\n\tstate |= ControlMask;\n    }\n    if (GetKeyState(VK_MENU) & 0x8000) {\n\tstate |= ALT_MASK;\n    }\n    if (GetKeyState(VK_CAPITAL) & 0x0001) {\n\tstate |= LockMask;\n    }\n    if (GetKeyState(VK_NUMLOCK) & 0x0001) {\n\tstate |= Mod1Mask;\n    }\n    if (GetKeyState(VK_SCROLL) & 0x0001) {\n\tstate |= Mod3Mask;\n    }\n    if (GetKeyState(VK_LBUTTON) & 0x8000) {\n\tstate |= Button1Mask;\n    }\n    if (GetKeyState(VK_MBUTTON) & 0x8000) {\n\tstate |= Button2Mask;\n    }\n    if (GetKeyState(VK_RBUTTON) & 0x8000) {\n\tstate |= Button3Mask;\n    }\n    if (GetKeyState(VK_XBUTTON1) & 0x8000) {\n\tstate |= Button4Mask;\n    }\n    if (GetKeyState(VK_XBUTTON2) & 0x8000) {\n\tstate |= Button5Mask;\n    }\n    return state;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinPointerEvent --\n *\n *\tThis procedure is called for each pointer-related event. It converts\n *\tthe position to root coords and updates the global pointer state\n *\tmachine. It also ensures that the mouse timer is scheduled.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay queue events and change the grab state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinPointerEvent(\n    HWND hwnd,\t\t\t/* Window for coords, or NULL for the root\n\t\t\t\t * window. */\n    int x, int y)\t\t/* Coords relative to hwnd, or screen if hwnd\n\t\t\t\t * is NULL. */\n{\n    POINT pos;\n    int state;\n    Tk_Window tkwin;\n\n    pos.x = x;\n    pos.y = y;\n\n    /*\n     * Convert client coords to root coords if we were given a window.\n     */\n\n    if (hwnd) {\n\tClientToScreen(hwnd, &pos);\n    }\n\n    /*\n     * If the mouse is captured, Windows will report all pointer events to the\n     * capture window. So, we need to determine which window the mouse is\n     * really over and change the event. Note that the computed hwnd may point\n     * to a window not owned by Tk, or a toplevel decorative frame, so tkwin\n     * can be NULL.\n     */\n\n    if (captured || hwnd == NULL) {\n\thwnd = WindowFromPoint(pos);\n    }\n    tkwin = Tk_HWNDToWindow(hwnd);\n\n    state = (int)TkWinGetModifierState();\n\n    Tk_UpdatePointer(tkwin, pos.x, pos.y, state);\n\n    if ((captured || tkwin) && !mouseTimerSet) {\n\tmouseTimerSet = true;\n\tmouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL,\n\t\tMouseTimerProc, NULL);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGrabKeyboard --\n *\n *\tSimulates a keyboard grab by setting the focus.\n *\n * Results:\n *\tAlways returns GrabSuccess.\n *\n * Side effects:\n *\tSets the keyboard focus to the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXGrabKeyboard(\n    Display *display,\n    Window grab_window,\n    Bool owner_events,\n    int pointer_mode,\n    int keyboard_mode,\n    Time time)\n{\n    (void)display;\n    (void)owner_events;\n    (void)pointer_mode;\n    (void)keyboard_mode;\n    (void)time;\n\n    keyboardWinPtr = TkWinGetWinPtr(grab_window);\n    return GrabSuccess;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUngrabKeyboard --\n *\n *\tReleases the simulated keyboard grab.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the keyboard focus back to the value before the grab.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUngrabKeyboard(\n    Display *display,\n    Time time)\n{\n    (void)display;\n    (void)time;\n\n    keyboardWinPtr = NULL;\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MouseTimerProc --\n *\n *\tCheck the current mouse position and look for enter/leave events.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay schedule a new timer and/or generate enter/leave events.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nMouseTimerProc(\n    TCL_UNUSED(void *))\n{\n    POINT pos;\n\n    mouseTimerSet = false;\n\n    GetCursorPos(&pos);\n    TkWinPointerEvent(NULL, pos.x, pos.y);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinCancelMouseTimer --\n *\n *    If the mouse timer is set, cancel it.\n *\n * Results:\n *    None.\n *\n * Side effects:\n *    May cancel the mouse timer.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinCancelMouseTimer(void)\n{\n    if (mouseTimerSet) {\n\tTcl_DeleteTimerHandler(mouseTimer);\n\tmouseTimerSet = false;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetPointerCoords --\n *\n *\tFetch the position of the mouse pointer.\n *\n * Results:\n *\t*xPtr and *yPtr are filled in with the root coordinates of the mouse\n *\tpointer for the display.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetPointerCoords(\n    Tk_Window tkwin,\t\t/* Window that identifies screen on which\n\t\t\t\t * lookup is to be done. */\n    int *xPtr, int *yPtr)\t/* Store pointer coordinates here. */\n{\n    POINT point;\n    (void)tkwin;\n\n    GetCursorPos(&point);\n    *xPtr = point.x;\n    *yPtr = point.y;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XQueryPointer --\n *\n *\tCheck the current state of the mouse. This is not a complete\n *\timplementation of this function. It only computes the root coordinates\n *\tand the current mask.\n *\n * Results:\n *\tSets root_x_return, root_y_return, and mask_return. Returns true on\n *\tsuccess.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nBool\nXQueryPointer(\n    Display *display,\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window *),\n    TCL_UNUSED(Window *),\n    int *root_x_return,\n    int *root_y_return,\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    unsigned int *mask_return)\n{\n    LastKnownRequestProcessed(display)++;\n    TkGetPointerCoords(NULL, root_x_return, root_y_return);\n    *mask_return = TkWinGetModifierState();\n    return True;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * XWarpPointer, TkpWarpPointer --\n *\n *\tMove pointer to new location. Note that implementation of XWarpPointer\n *\tis incomplete.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMouse pointer changes position on screen.\n *\n *----------------------------------------------------------------------\n */\n\n/*\n * TkSetCursorPos is a helper function replacing SetCursorPos since this\n * latter Windows function appears to have been broken by Microsoft\n * since Win10 Falls Creator Update - See ticket [69b48f427e] along with\n * several other Internet reports about this breakage.\n */\n\nvoid TkSetCursorPos(\n    int x,\n    int y)\n{\n    INPUT input;\n    int xscreen = (int)(GetSystemMetrics(SM_CXSCREEN) - 1);\n    int yscreen = (int)(GetSystemMetrics(SM_CYSCREEN) - 1);\n\n    /*\n     * A multi-screen system may have different logical pixels/inch, with\n     * Windows applying behind-the-scenes scaling on secondary screens.\n     * Don't try and emulate that, instead fall back to SetCursor if the\n     * requested position is off the primary screen.\n     */\n    if ( x < 0 || x > xscreen || y < 0 || y > yscreen ) {\n\tSetCursorPos(x, y);\n\treturn;\n    }\n\n    input.type = INPUT_MOUSE;\n    input.mi.dx = (x * 65535 + xscreen/2) / xscreen;\n    input.mi.dy = (y * 65535 + yscreen/2) / yscreen;\n\n    /*\n     * Horrible workaround here. There is a bug on Win 10: when warping to\n     * pixel (x = 0, y = 0) the SendInput() below just does not move the\n     * mouse pointer. However, as soon as dx or dy is non zero it moves as\n     * expected. Given the scaling factor of 65535 (see above),\n     * (dx = 1 , dy = 0) still means pixel (x = 0, y = 0).\n     * See ticket [69b48f427e].\n     */\n    if (input.mi.dx == 0 && input.mi.dy == 0) {\n\tinput.mi.dx = 1;\n    }\n\n    input.mi.mouseData = 0;\n    input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;\n    input.mi.time = 0;\n    input.mi.dwExtraInfo = 0;\n    SendInput(1, &input, sizeof(input));\n}\n\nint\nXWarpPointer(\n    Display *display,\n    Window src_w,\n    Window dest_w,\n    int src_x,\n    int src_y,\n    unsigned int src_width,\n    unsigned int src_height,\n    int dest_x,\n    int dest_y)\n{\n    RECT r;\n    (void)display;\n    (void)src_w;\n    (void)src_x;\n    (void)src_y;\n    (void)src_width;\n    (void)src_height;\n\n    GetWindowRect(Tk_GetHWND(dest_w), &r);\n    TkSetCursorPos(r.left+dest_x, r.top+dest_y);\n    return Success;\n}\n\nvoid\nTkpWarpPointer(\n    TkDisplay *dispPtr)\n{\n    int rootx, rooty;\n    unsigned int modifierState;\n\n    if (dispPtr->warpWindow) {\n\tRECT r;\n\tGetWindowRect(Tk_GetHWND(Tk_WindowId(dispPtr->warpWindow)), &r);\n\tTkSetCursorPos(r.left + dispPtr->warpX, r.top + dispPtr->warpY);\n    } else {\n\tTkSetCursorPos(dispPtr->warpX, dispPtr->warpY);\n    }\n\n    XQueryPointer(dispPtr->display, None, NULL, NULL, &rootx, &rooty,\n\t    NULL, NULL, &modifierState);\n    Tk_Window newPointerWin = Tk_CoordsToWindow(rootx, rooty,\n\t    dispPtr->warpMainwin);\n    Tk_UpdatePointer(newPointerWin, rootx, rooty, modifierState);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetInputFocus --\n *\n *\tRetrieves the current keyboard focus window.\n *\n * Results:\n *\tReturns the current focus window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXGetInputFocus(\n    Display *display,\n    Window *focus_return,\n    int *revert_to_return)\n{\n    Tk_Window tkwin = Tk_HWNDToWindow(GetFocus());\n\n    *focus_return = tkwin ? Tk_WindowId(tkwin) : 0;\n    *revert_to_return = RevertToParent;\n    LastKnownRequestProcessed(display)++;\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSetInputFocus --\n *\n *\tSet the current focus window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the keyboard focus and causes the selected window to\n *\tbe activated.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetInputFocus(\n    Display *display,\n    Window focus,\n    TCL_UNUSED(int),\n    TCL_UNUSED(Time))\n{\n    LastKnownRequestProcessed(display)++;\n    if (focus != None) {\n\tSetFocus(Tk_GetHWND(focus));\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpChangeFocus --\n *\n *\tThis procedure is invoked to move the system focus from one window to\n *\tanother.\n *\n * Results:\n *\tThe return value is the serial number of the command that changed the\n *\tfocus. It may be needed by the caller to filter out focus change\n *\tevents that were queued before the command. If the procedure doesn't\n *\tactually change the focus then it returns 0.\n *\n * Side effects:\n *\tThe official Windows focus window changes; the application's focus\n *\twindow isn't changed by this procedure.\n *\n *----------------------------------------------------------------------\n */\n\nsize_t\nTkpChangeFocus(\n    TkWindow *winPtr,\t\t/* Window that is to receive the X focus. */\n    int force)\t\t\t/* Non-zero means claim the focus even if it\n\t\t\t\t * didn't originally belong to topLevelPtr's\n\t\t\t\t * application. */\n{\n    TkDisplay *dispPtr = winPtr->dispPtr;\n    Window focusWindow;\n    int dummy;\n    size_t serial;\n    TkWindow *winPtr2;\n\n    if (!force) {\n\tXGetInputFocus(dispPtr->display, &focusWindow, &dummy);\n\twinPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, focusWindow);\n\tif ((winPtr2 == NULL) || (winPtr2->mainPtr != winPtr->mainPtr)) {\n\t    return 0;\n\t}\n    }\n\n    if (winPtr->window == None) {\n\tTcl_Panic(\"ChangeXFocus got null X window\");\n    }\n\n    /*\n     * Change the foreground window so the focus window is raised to the top\n     * of the system stacking order and gets the keyboard focus.\n     */\n\n    if (force) {\n\tTkWinSetForegroundWindow(winPtr);\n    }\n    XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,\n\t    CurrentTime);\n\n    /*\n     * Remember the current serial number for the X server and issue a dummy\n     * server request. This marks the position at which we changed the focus,\n     * so we can distinguish FocusIn and FocusOut events on either side of the\n     * mark.\n     */\n\n    serial = NextRequest(winPtr->display);\n    XNoOp(winPtr->display);\n    return serial;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpSetCapture --\n *\n *\tThis function captures the mouse so that all future events will be\n *\treported to this window, even if the mouse is outside the window. If\n *\tthe specified window is NULL, then the mouse is released.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the capture flag and captures the mouse.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpSetCapture(\n    TkWindow *winPtr)\t\t/* Capture window, or NULL. */\n{\n    captured = winPtr != NULL;\n    if (captured) {\n\tSetCapture(Tk_GetHWND(Tk_WindowId(winPtr)));\n    } else {\n\tReleaseCapture();\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetCapture --\n *\n *\tThis function requests which window is capturing the mouse.\n *\n * Results:\n *\tThe return value is a pointer to the capture window, if there is\n *      one, otherwise it is NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTkpGetCapture(void)\n{\n    return Tk_HWNDToWindow(GetCapture());\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinPort.h",
    "content": "/*\n * tkWinPort.h --\n *\n *\tThis header file handles porting issues that occur because of\n *\tdifferences between Windows and Unix. It should be the only\n *\tfile that contains #ifdefs to handle different flavors of OS.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _WINPORT\n#define _WINPORT\n\n/*\n *---------------------------------------------------------------------------\n * The following sets of #includes and #ifdefs are required to get Tcl to\n * compile under the windows compilers.\n *---------------------------------------------------------------------------\n */\n\n#include <stdio.h>\n#include <wchar.h>\n#include <io.h>\n#include <assert.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <malloc.h>\n#include <ctype.h>\n#include <math.h>\n#include <string.h>\n#include <limits.h>\n\n/*\n * Need to block out this include for building extensions with MetroWerks\n * compiler for Win32.\n */\n\n#ifndef __MWERKS__\n#include <sys/stat.h>\n#endif\n\n#include <time.h>\n\n#ifdef _MSC_VER\n#   ifndef hypot\n#\tdefine hypot _hypot\n#   endif\n#endif /* _MSC_VER */\n\n/*\n *  Pull in the typedef of TCHAR for windows.\n */\n#include <tchar.h>\n#ifndef _TCHAR_DEFINED\n    /* Borland seems to forget to set this. */\n    typedef _TCHAR TCHAR;\n#   define _TCHAR_DEFINED\n#endif\n#if defined(_MSC_VER) && defined(__STDC__)\n    /* VS2005 SP1 misses this. See [Bug #3110161] */\n    typedef _TCHAR TCHAR;\n#endif\n\n#if defined(__GNUC__) && !defined(__cplusplus)\n#   pragma GCC diagnostic ignored \"-Wc++-compat\"\n#endif\n\n#ifndef __GNUC__\n#    define strncasecmp _strnicmp\n#    define strcasecmp _stricmp\n#endif\n\n#define NBBY 8\n\n#ifndef OPEN_MAX\n#define OPEN_MAX 32\n#endif\n\n/*\n * The following define causes Tk to use its internal keysym hash table\n */\n\n#define REDO_KEYSYM_LOOKUP\n\n/*\n * See ticket [916c1095438eae56]: GetVersionExW triggers warnings\n */\n#if defined(_MSC_VER)\n#   pragma warning(disable:4090) /* see: https://developercommunity.visualstudio.com/t/c-compiler-incorrect-propagation-of-const-qualifie/390711 */\n#   pragma warning(disable:4146)\n#   pragma warning(disable:4267)\n#   pragma warning(disable:4244)\n#   pragma warning(disable:4311)\n#   pragma warning(disable:4312)\n#   pragma warning(disable:4996)\n#if !defined(_WIN64)\n#   pragma warning(disable:4305)\n#endif\n#   pragma warning(disable:5287) /* See [1dcda0e862] in the Tcl repository */\n#endif\n\n/*\n * The following macro checks to see whether there is buffered\n * input data available for a stdio FILE.\n */\n\n#ifdef _MSC_VER\n#    define TK_READ_DATA_PENDING(f) ((f)->_cnt > 0)\n#else /* _MSC_VER */\n#    define TK_READ_DATA_PENDING(f) ((f)->level > 0)\n#endif /* _MSC_VER */\n\n/*\n * The following Tk functions are implemented as macros under Windows.\n */\n\n#define TkpGetPixel(p) (((((p)->red >> 8) & 0xff) \\\n\t| ((p)->green & 0xff00) | (((p)->blue << 8) & 0xff0000)) | 0x20000000)\n\n#endif /* _WINPORT */\n"
  },
  {
    "path": "win/tkWinRegion.c",
    "content": "/*\n * tkWinRegion.c --\n *\n *\tTk Region emulation code.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateRegion --\n *\n *\tConstruct an empty region.\n *\n * Results:\n *\tReturns a new region handle.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nRegion\nXCreateRegion(void)\n{\n    RECT rect;\n    memset(&rect, 0, sizeof(RECT));\n    return (Region)CreateRectRgnIndirect(&rect);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDestroyRegion --\n *\n *\tDestroy the specified region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees the storage associated with the specified region.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDestroyRegion(\n    Region r)\n{\n    DeleteObject((HRGN) r);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XClipBox --\n *\n *\tComputes the bounding box of a region.\n *\n * Results:\n *\tSets rect_return to the bounding box of the region.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXClipBox(\n    Region r,\n    XRectangle* rect_return)\n{\n    RECT rect;\n\n    GetRgnBox((HRGN)r, &rect);\n    rect_return->x = (short) rect.left;\n    rect_return->y = (short) rect.top;\n    rect_return->width = (short) (rect.right - rect.left);\n    rect_return->height = (short) (rect.bottom - rect.top);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XIntersectRegion --\n *\n *\tCompute the intersection of two regions.\n *\n * Results:\n *\tReturns the result in the dr_return region.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXIntersectRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_AND);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUnionRectWithRegion --\n *\n *\tCreate the union of a source region and a rectangle.\n *\n * Results:\n *\tReturns the result in the dr_return region.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUnionRectWithRegion(\n    XRectangle *rectangle,\n    Region src_region,\n    Region dest_region_return)\n{\n    HRGN rectRgn = CreateRectRgn(rectangle->x, rectangle->y,\n\t    rectangle->x + rectangle->width, rectangle->y + rectangle->height);\n\n    CombineRgn((HRGN) dest_region_return, (HRGN) src_region,\n\t    (HRGN) rectRgn, RGN_OR);\n    DeleteObject(rectRgn);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpBuildRegionFromAlphaData --\n *\n *\tSet up a rectangle of the given region based on the supplied alpha\n *\tdata.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tThe region is updated, with extra pixels added to it.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpBuildRegionFromAlphaData(\n    Region region,\n    unsigned int x, unsigned int y,\n\t\t\t\t/* Where in region to update. */\n    unsigned int width, unsigned int height,\n\t\t\t\t/* Size of rectangle to update. */\n    unsigned char *dataPtr,\t/* Data to read from. */\n    unsigned int pixelStride,\t/* Num bytes from one piece of alpha data to\n\t\t\t\t * the next in the line. */\n    unsigned int lineStride)\t/* Num bytes from one line of alpha data to\n\t\t\t\t * the next line. */\n{\n    unsigned char *lineDataPtr;\n    unsigned int x1, y1, end;\n    HRGN rectRgn = CreateRectRgn(0,0,1,1); /* Workspace region. */\n\n    for (y1 = 0; y1 < height; y1++) {\n\tlineDataPtr = dataPtr;\n\tfor (x1 = 0; x1 < width; x1 = end) {\n\t    /*\n\t     * Search for first non-transparent pixel.\n\t     */\n\n\t    while ((x1 < width) && !*lineDataPtr) {\n\t\tx1++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    end = x1;\n\n\t    /*\n\t     * Search for first transparent pixel.\n\t     */\n\n\t    while ((end < width) && *lineDataPtr) {\n\t\tend++;\n\t\tlineDataPtr += pixelStride;\n\t    }\n\t    if (end > x1) {\n\t\t/*\n\t\t * Manipulate Win32 regions directly; it's more efficient.\n\t\t */\n\n\t\tSetRectRgn(rectRgn, (int) (x+x1), (int) (y+y1),\n\t\t\t(int) (x+end), (int) (y+y1+1));\n\t\tCombineRgn((HRGN) region, (HRGN) region, rectRgn, RGN_OR);\n\t    }\n\t}\n\tdataPtr += lineStride;\n    }\n\n    DeleteObject(rectRgn);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XRectInRegion --\n *\n *\tTest whether a given rectangle overlaps with a region.\n *\n * Results:\n *\tReturns RectanglePart or RectangleOut. Note that this is not a\n *\tcomplete implementation since it doesn't test for RectangleIn.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXRectInRegion(\n    Region r,\t\t\t/* Region to inspect */\n    int x, int y,\t\t/* Top-left of rectangle */\n    unsigned int width,\t\t/* Width of rectangle */\n    unsigned int height)\t/* Height of rectangle */\n{\n    RECT rect;\n    rect.top = y;\n    rect.left = x;\n    rect.bottom = y+height;\n    rect.right = x+width;\n    return RectInRegion((HRGN)r, &rect) ? RectanglePart : RectangleOut;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSubtractRegion --\n *\n *\tCompute the set-difference of two regions.\n *\n * Results:\n *\tReturns the result in the dr_return region.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSubtractRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_DIFF);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCopyRegion --\n *\n *  Makes the destination region a copy of the source region.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCopyRegion(\n    Region dst,\n    Region src)\n{\n    CombineRgn((HRGN)dst, (HRGN)src, NULL, RGN_COPY);\n}\n\nint\nXUnionRegion(\n    Region srca,\n    Region srcb,\n    Region dr_return)\n{\n    CombineRgn((HRGN)dr_return, (HRGN)srca, (HRGN)srcb, RGN_OR);\n    return 1;\n}\n\nint\nXOffsetRegion(\n    Region r,\n    int dx,\n    int dy)\n{\n    OffsetRgn((HRGN)r, dx, dy);\n    return 1;\n}\n\nBool\nXPointInRegion(\n    Region r,\n    int x,\n    int y)\n{\n    return PtInRegion((HRGN)r, x, y);\n}\n\nBool\nXEqualRegion(\n    Region r1,\n    Region r2)\n{\n    return EqualRgn((HRGN)r1, (HRGN)r2);\n}\n\nint\nXXorRegion(\n    Region sra,\n    Region srb,\n    Region dr_return)\n{\n    CombineRgn((HRGN)dr_return, (HRGN)sra, (HRGN)srb, RGN_XOR);\n    return 0;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinScrlbr.c",
    "content": "/*\n * tkWinScrollbar.c --\n *\n *\tThis file implements the Windows specific portion of the scrollbar\n *\twidget.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkScrollbar.h\"\n\n/*\n * The following constant is used to specify the maximum scroll position. This\n * value is limited by the Win32 API to either 16-bits or 32-bits, depending\n * on the context. For now we'll just use a value small enough to fit in\n * 16-bits, but which gives us 4-digits of precision.\n */\n\n#define MAX_SCROLL 10000\n\n/*\n * Declaration of Windows specific scrollbar structure.\n */\n\ntypedef struct WinScrollbar {\n    TkScrollbar info;\t\t/* Generic scrollbar info. */\n    WNDPROC oldProc;\t\t/* Old window procedure. */\n    int lastVertical;\t\t/* 1 if was vertical at last refresh. */\n    HWND hwnd;\t\t\t/* Current window handle. */\n    int winFlags;\t\t/* Various flags; see below. */\n} WinScrollbar;\n\n/*\n * Flag bits for native scrollbars:\n *\n * IN_MODAL_LOOP:\t\tNon-zero means this scrollbar is in the middle\n *\t\t\t\tof a modal loop.\n * ALREADY_DEAD:\t\tNon-zero means this scrollbar has been\n *\t\t\t\tdestroyed, but has not been cleaned up.\n */\n\n#define IN_MODAL_LOOP\t1\n#define ALREADY_DEAD\t2\n\n/*\n * Cached system metrics used to determine scrollbar geometry.\n */\n\nstatic bool initialized = false;\nstatic int hArrowWidth, hThumb; /* Horizontal control metrics. */\nstatic int vArrowHeight, vThumb; /* Vertical control metrics. */\n\nTCL_DECLARE_MUTEX(winScrlbrMutex)\n\n/*\n * Declarations for functions defined in this file.\n */\n\nstatic Window\t\tCreateProc(Tk_Window tkwin, Window parent,\n\t\t\t    void *instanceData);\nstatic void\t\tModalLoop(WinScrollbar *, XEvent *eventPtr);\nstatic LRESULT CALLBACK\tScrollbarProc(HWND hwnd, UINT message, WPARAM wParam,\n\t\t\t    LPARAM lParam);\nstatic void\t\tUpdateScrollbar(WinScrollbar *scrollPtr);\nstatic void\t\tUpdateScrollbarMetrics(void);\n\n/*\n * The class procedure table for the scrollbar widget.\n */\n\nconst Tk_ClassProcs tkpScrollbarProcs = {\n    sizeof(Tk_ClassProcs),\t/* size */\n    NULL,\t\t\t/* worldChangedProc */\n    CreateProc,\t\t\t/* createProc */\n    NULL\t\t\t/* modalProc */\n};\n\nstatic void\nWinScrollbarEventProc(void *clientData, XEvent *eventPtr)\n{\n    WinScrollbar *scrollPtr = (WinScrollbar *)clientData;\n\n    if (eventPtr->type == ButtonPress) {\n\tModalLoop(scrollPtr, eventPtr);\n    } else {\n\tTkScrollbarEventProc(clientData, eventPtr);\n    }\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateScrollbar --\n *\n *\tAllocate a new TkScrollbar structure.\n *\n * Results:\n *\tReturns a newly allocated TkScrollbar structure.\n *\n * Side effects:\n *\tRegisters an event handler for the widget.\n *\n *----------------------------------------------------------------------\n */\n\nTkScrollbar *\nTkpCreateScrollbar(\n    Tk_Window tkwin)\n{\n    WinScrollbar *scrollPtr;\n\n    if (!initialized) {\n\tTcl_MutexLock(&winScrlbrMutex);\n\tUpdateScrollbarMetrics();\n\tinitialized = true;\n\tTcl_MutexUnlock(&winScrlbrMutex);\n    }\n\n    scrollPtr = (WinScrollbar *)Tcl_Alloc(sizeof(WinScrollbar));\n    scrollPtr->winFlags = 0;\n    scrollPtr->hwnd = NULL;\n\n    Tk_CreateEventHandler(tkwin,\n\t    ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask,\n\t    WinScrollbarEventProc, scrollPtr);\n\n    return (TkScrollbar *) scrollPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateScrollbar --\n *\n *\tThis function updates the position and size of the scrollbar thumb\n *\tbased on the current settings.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves the thumb.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateScrollbar(\n    WinScrollbar *scrollPtr)\n{\n    SCROLLINFO scrollInfo;\n    double thumbSize;\n\n    /*\n     * Update the current scrollbar position and shape.\n     */\n\n    scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;\n    scrollInfo.cbSize = sizeof(scrollInfo);\n    scrollInfo.nMin = 0;\n    scrollInfo.nMax = MAX_SCROLL;\n    thumbSize = (scrollPtr->info.lastFraction - scrollPtr->info.firstFraction);\n    scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1;\n    if (thumbSize < 1.0) {\n\tscrollInfo.nPos = (int)\n\t\t((scrollPtr->info.firstFraction / (1.0-thumbSize))\n\t\t* (MAX_SCROLL - (scrollInfo.nPage - 1)));\n    } else {\n\tscrollInfo.nPos = 0;\n\n\t/*\n\t * Disable the scrollbar when there is nothing to scroll. This is\n\t * standard Windows style (see eg Notepad). Also prevents possible\n\t * crash on XP+ systems [Bug #624116].\n\t */\n\n\tscrollInfo.fMask |= SIF_DISABLENOSCROLL;\n    }\n    SetScrollInfo(scrollPtr->hwnd, SB_CTL, &scrollInfo, TRUE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateProc --\n *\n *\tThis function creates a new Scrollbar control, subclasses the\n *\tinstance, and generates a new Window object.\n *\n * Results:\n *\tReturns the newly allocated Window object, or None on failure.\n *\n * Side effects:\n *\tCauses a new Scrollbar control to come into existence.\n *\n *----------------------------------------------------------------------\n */\n\nstatic Window\nCreateProc(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Window parentWin,\t\t/* Parent of new window. */\n    void *instanceData)\t/* Scrollbar instance data. */\n{\n    DWORD style;\n    Window window;\n    HWND parent;\n    TkWindow *winPtr;\n    WinScrollbar *scrollPtr = (WinScrollbar *)instanceData;\n\n    parent = Tk_GetHWND(parentWin);\n\n    if (scrollPtr->info.vertical) {\n\tstyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS\n\t\t| SBS_VERT;\n    } else {\n\tstyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS\n\t\t| SBS_HORZ;\n    }\n\n    scrollPtr->hwnd = CreateWindowW(L\"SCROLLBAR\", NULL, style,\n\t    Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),\n\t    parent, NULL, Tk_GetHINSTANCE(), NULL);\n\n    /*\n     * Ensure new window is inserted into the stacking order at the correct\n     * place.\n     */\n\n    SetWindowPos(scrollPtr->hwnd, HWND_TOP, 0, 0, 0, 0,\n\t\t    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n\n    for (winPtr = ((TkWindow*)tkwin)->nextPtr; winPtr != NULL;\n\t    winPtr = winPtr->nextPtr) {\n\tif ((winPtr->window != None) && !(winPtr->flags & TK_TOP_HIERARCHY)) {\n\t    TkWinSetWindowPos(scrollPtr->hwnd, Tk_GetHWND(winPtr->window),\n\t\t    Below);\n\t    break;\n\t}\n    }\n\n    scrollPtr->lastVertical = scrollPtr->info.vertical;\n    scrollPtr->oldProc = (WNDPROC)SetWindowLongPtrW(scrollPtr->hwnd,\n\t    GWLP_WNDPROC, (LONG_PTR) ScrollbarProc);\n    window = Tk_AttachHWND(tkwin, scrollPtr->hwnd);\n\n    UpdateScrollbar(scrollPtr);\n    return window;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpDisplayScrollbar --\n *\n *\tThis procedure redraws the contents of a scrollbar window. It is\n *\tinvoked as a do-when-idle handler, so it only runs when there's\n *\tnothing else for the application to do.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tInformation appears on the screen.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkpDisplayScrollbar(\n    void *clientData)\t/* Information about window. */\n{\n    WinScrollbar *scrollPtr = (WinScrollbar *)clientData;\n    Tk_Window tkwin = scrollPtr->info.tkwin;\n\n    scrollPtr->info.flags &= ~REDRAW_PENDING;\n    if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {\n\treturn;\n    }\n\n    /*\n     * Destroy and recreate the scrollbar control if the orientation has\n     * changed.\n     */\n\n    if (scrollPtr->lastVertical != scrollPtr->info.vertical) {\n\tHWND hwnd = Tk_GetHWND(Tk_WindowId(tkwin));\n\n\tSetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) scrollPtr->oldProc);\n\tDestroyWindow(hwnd);\n\n\tCreateProc(tkwin, Tk_WindowId(Tk_Parent(tkwin)),\n\t\tscrollPtr);\n    } else {\n\tUpdateScrollbar(scrollPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpDestroyScrollbar --\n *\n *\tFree data structures associated with the scrollbar control.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRestores the default control state.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpDestroyScrollbar(\n    TkScrollbar *scrollPtr)\n{\n    WinScrollbar *winScrollPtr = (WinScrollbar *)scrollPtr;\n    HWND hwnd = winScrollPtr->hwnd;\n\n    if (hwnd) {\n\tSetWindowLongPtrW(hwnd, GWLP_WNDPROC, (INT_PTR) winScrollPtr->oldProc);\n\tif (winScrollPtr->winFlags & IN_MODAL_LOOP) {\n\t    ((TkWindow *)scrollPtr->tkwin)->flags |= TK_DONT_DESTROY_WINDOW;\n\t    SetParent(hwnd, NULL);\n\t}\n    }\n    winScrollPtr->winFlags |= ALREADY_DEAD;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateScrollbarMetrics --\n *\n *\tThis function retrieves the current system metrics for a scrollbar.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUpdates the geometry cache info for all scrollbars.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nUpdateScrollbarMetrics(void)\n{\n    int arrowWidth = GetSystemMetrics(SM_CXVSCROLL);\n\n    hArrowWidth = GetSystemMetrics(SM_CXHSCROLL);\n    hThumb = GetSystemMetrics(SM_CXHTHUMB);\n    vArrowHeight = GetSystemMetrics(SM_CYVSCROLL);\n    vThumb = GetSystemMetrics(SM_CYVTHUMB);\n\n    snprintf(tkDefScrollbarWidth, sizeof(tkDefScrollbarWidth), \"%d\", arrowWidth);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpComputeScrollbarGeometry --\n *\n *\tAfter changes in a scrollbar's size or configuration, this procedure\n *\trecomputes various geometry information used in displaying the\n *\tscrollbar.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe scrollbar will be displayed differently.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpComputeScrollbarGeometry(\n    TkScrollbar *scrollPtr)\n\t\t\t\t/* Scrollbar whose geometry may have\n\t\t\t\t * changed. */\n{\n    int fieldLength, minThumbSize;\n    int width;\n\n    /*\n     * Windows doesn't use focus rings on scrollbars, but we still perform\n     * basic sanity checks to appease backwards compatibility.\n     */\n\n    if (scrollPtr->vertical) {\n\tscrollPtr->arrowLength = vArrowHeight;\n\tfieldLength = Tk_Height(scrollPtr->tkwin);\n\tminThumbSize = vThumb;\n    } else {\n\tscrollPtr->arrowLength = hArrowWidth;\n\tfieldLength = Tk_Width(scrollPtr->tkwin);\n\tminThumbSize = hThumb;\n    }\n    fieldLength -= 2 * scrollPtr->arrowLength;\n    if (fieldLength < 0) {\n\tfieldLength = 0;\n    }\n    scrollPtr->sliderFirst = (int) ((double)fieldLength\n\t    * scrollPtr->firstFraction);\n    scrollPtr->sliderLast = (int) ((double)fieldLength\n\t    * scrollPtr->lastFraction);\n\n    /*\n     * Adjust the slider so that some piece of it is always displayed in the\n     * scrollbar and so that it has at least a minimal width (so it can be\n     * grabbed with the mouse).\n     */\n\n    if (scrollPtr->sliderFirst > fieldLength) {\n\tscrollPtr->sliderFirst = fieldLength;\n    }\n    if (scrollPtr->sliderFirst < 0) {\n\tscrollPtr->sliderFirst = 0;\n    }\n    if (scrollPtr->sliderLast < (scrollPtr->sliderFirst\n\t    + minThumbSize)) {\n\tscrollPtr->sliderLast = scrollPtr->sliderFirst + minThumbSize;\n    }\n    if (scrollPtr->sliderLast > fieldLength) {\n\tscrollPtr->sliderLast = fieldLength;\n    }\n    scrollPtr->sliderFirst += scrollPtr->arrowLength;\n    scrollPtr->sliderLast += scrollPtr->arrowLength;\n\n    /*\n     * Register the desired geometry for the window (leave enough space for\n     * the two arrows plus a minimum-size slider, plus border around the whole\n     * window, if any). Then arrange for the window to be redisplayed.\n     */\n\n    Tk_GetPixelsFromObj(NULL, scrollPtr->tkwin, scrollPtr->widthObj, &width);\n    if (scrollPtr->vertical) {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\twidth, 2 * scrollPtr->arrowLength + minThumbSize);\n    } else {\n\tTk_GeometryRequest(scrollPtr->tkwin,\n\t\t2 * scrollPtr->arrowLength + minThumbSize, width);\n    }\n    Tk_SetInternalBorder(scrollPtr->tkwin, 0);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ScrollbarProc --\n *\n *\tThis function is call by Windows whenever an event occurs on a\n *\tscrollbar control created by Tk.\n *\n * Results:\n *\tStandard Windows return value.\n *\n * Side effects:\n *\tMay generate events.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nScrollbarProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    LRESULT result;\n    POINT point;\n    WinScrollbar *scrollPtr;\n    Tk_Window tkwin = Tk_HWNDToWindow(hwnd);\n\n    if (tkwin == NULL) {\n\tTcl_Panic(\"ScrollbarProc called on an invalid HWND\");\n    }\n    scrollPtr = (WinScrollbar *)((TkWindow*)tkwin)->instanceData;\n\n    switch(message) {\n    case WM_HSCROLL:\n    case WM_VSCROLL: {\n\tTcl_Interp *interp;\n\tTcl_DString cmdString;\n\tint command = LOWORD(wParam);\n\tint code;\n\n\tGetCursorPos(&point);\n\tTkTranslateWinEvent(NULL, WM_MOUSEMOVE, 0,\n\t\tMAKELPARAM(point.x, point.y), &result);\n\n\tif (command == SB_ENDSCROLL) {\n\t    return 0;\n\t}\n\n\t/*\n\t * Bail out immediately if there isn't a command to invoke.\n\t */\n\n\tif (!scrollPtr->info.commandObj) {\n\t    Tcl_ServiceAll();\n\t    return 0;\n\t}\n\n\tTcl_DStringInit(&cmdString);\n\tTcl_DStringAppend(&cmdString, Tcl_GetString(scrollPtr->info.commandObj), TCL_INDEX_NONE);\n\n\tif (command == SB_LINELEFT || command == SB_LINERIGHT) {\n\t    Tcl_DStringAppendElement(&cmdString, \"scroll\");\n\t    Tcl_DStringAppendElement(&cmdString,\n\t\t    (command == SB_LINELEFT ) ? \"-1\" : \"1\");\n\t    Tcl_DStringAppendElement(&cmdString, \"units\");\n\t} else if (command == SB_PAGELEFT || command == SB_PAGERIGHT) {\n\t    Tcl_DStringAppendElement(&cmdString, \"scroll\");\n\t    Tcl_DStringAppendElement(&cmdString,\n\t\t    (command == SB_PAGELEFT ) ? \"-1\" : \"1\");\n\t    Tcl_DStringAppendElement(&cmdString, \"pages\");\n\t} else {\n\t    char valueString[TCL_DOUBLE_SPACE];\n\t    double pos = 0.0;\n\n\t    switch (command) {\n\t    case SB_THUMBPOSITION:\n\t\tpos = ((double)HIWORD(wParam)) / MAX_SCROLL;\n\t\tbreak;\n\t    case SB_THUMBTRACK:\n\t\tpos = ((double)HIWORD(wParam)) / MAX_SCROLL;\n\t\tbreak;\n\t    case SB_TOP:\n\t\tpos = 0.0;\n\t\tbreak;\n\t    case SB_BOTTOM:\n\t\tpos = 1.0;\n\t\tbreak;\n\t    }\n\n\t    Tcl_PrintDouble(NULL, pos, valueString);\n\t    Tcl_DStringAppendElement(&cmdString, \"moveto\");\n\t    Tcl_DStringAppendElement(&cmdString, valueString);\n\t}\n\n\tinterp = scrollPtr->info.interp;\n\tcode = Tcl_EvalEx(interp, cmdString.string, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\tif (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) {\n\t    Tcl_AddErrorInfo(interp, \"\\n    (scrollbar command)\");\n\t    Tcl_BackgroundException(interp, code);\n\t}\n\tTcl_DStringFree(&cmdString);\n\n\tTcl_ServiceAll();\n\treturn 0;\n    }\n\n    default:\n\tif (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {\n\t    return result;\n\t}\n    }\n    return CallWindowProcW(scrollPtr->oldProc, hwnd, message, wParam, lParam);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpConfigureScrollbar --\n *\n *\tThis procedure is called after the generic code has finished\n *\tprocessing configuration options, in order to configure platform\n *\tspecific options.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpConfigureScrollbar(\n    TCL_UNUSED(TkScrollbar *))\n\t\t\t\t/* Information about widget; may or may not\n\t\t\t\t * already have values for some fields. */\n{\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ModalLoop --\n *\n *\tThis function is invoked in response to a ButtonPress event.\n *\tIt resends the event to the Scrollbar window procedure,\n *\twhich in turn enters a modal loop.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nModalLoop(\n    WinScrollbar *scrollPtr,\n    XEvent *eventPtr)\n{\n    int oldMode;\n\n    if (scrollPtr->hwnd) {\n\tTcl_Preserve(scrollPtr);\n\tscrollPtr->winFlags |= IN_MODAL_LOOP;\n\toldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n\tTkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);\n\t(void) Tcl_SetServiceMode(oldMode);\n\tscrollPtr->winFlags &= ~IN_MODAL_LOOP;\n\tif (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {\n\t    DestroyWindow(scrollPtr->hwnd);\n\t}\n\tTcl_Release(scrollPtr);\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkpScrollbarPosition --\n *\n *\tDetermine the scrollbar element corresponding to a given position.\n *\n * Results:\n *\tOne of TOP_ARROW, TOP_GAP, etc., indicating which element of the\n *\tscrollbar covers the position given by (x, y). If (x,y) is outside the\n *\tscrollbar entirely, then OUTSIDE is returned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nint\nTkpScrollbarPosition(\n    TkScrollbar *scrollPtr,\n\t\t\t\t/* Scrollbar widget record. */\n    int x, int y)\t\t/* Coordinates within scrollPtr's window. */\n{\n    int length, width, tmp;\n\n    if (scrollPtr->vertical) {\n\tlength = Tk_Height(scrollPtr->tkwin);\n\twidth = Tk_Width(scrollPtr->tkwin);\n    } else {\n\ttmp = x;\n\tx = y;\n\ty = tmp;\n\tlength = Tk_Width(scrollPtr->tkwin);\n\twidth = Tk_Height(scrollPtr->tkwin);\n    }\n\n    if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))\n\t    || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {\n\treturn OUTSIDE;\n    }\n\n    /*\n     * All of the calculations in this procedure mirror those in\n     * TkpDisplayScrollbar. Be sure to keep the two consistent.\n     */\n\n    if (y < (scrollPtr->inset + scrollPtr->arrowLength)) {\n\treturn TOP_ARROW;\n    }\n    if (y < scrollPtr->sliderFirst) {\n\treturn TOP_GAP;\n    }\n    if (y < scrollPtr->sliderLast) {\n\treturn SLIDER;\n    }\n    if (y >= (length - (scrollPtr->arrowLength + scrollPtr->inset))) {\n\treturn BOTTOM_ARROW;\n    }\n    return BOTTOM_GAP;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinSend.c",
    "content": "/*\n * tkWinSend.c --\n *\n *\tThis file provides functions that implement the \"send\" command,\n *\tallowing commands to be passed from interpreter to interpreter.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n * Copyright © 2003 Pat Thoyts <patthoyts@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkWinSendCom.h\"\n#include \"tkWinInt.h\"\n\n/*\n * Should be defined in WTypes.h but mingw 1.0 is missing them.\n */\n\n#ifndef _ROTFLAGS_DEFINED\n#define _ROTFLAGS_DEFINED\n#define ROTFLAGS_REGISTRATIONKEEPSALIVE 0x01\n#define ROTFLAGS_ALLOWANYCLIENT\t\t0x02\n#endif /* ! _ROTFLAGS_DEFINED */\n\n#define TKWINSEND_CLASS_NAME\t\t\"TclEval\"\n#define TKWINSEND_REGISTRATION_BASE\tL\"TclEval\"\n\n#define MK_E_MONIKERALREADYREGISTERED \\\n\tMAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x02A1)\n\n/*\n * Package information structure. This is used to keep interpreter specific\n * details for use when releasing the package resources upon interpreter\n * deletion or package removal.\n */\n\ntypedef struct {\n    char *name;\t\t\t/* The registered application name */\n    DWORD cookie;\t\t/* ROT cookie returned on registration */\n    LPUNKNOWN obj;\t\t/* Interface for the registration object */\n    Tcl_Interp *interp;\n    Tcl_Command token;\t\t/* Winsend command token */\n} RegisteredInterp;\n\ntypedef struct SendEvent {\n    Tcl_Event header;\n    Tcl_Interp *interp;\n    Tcl_Obj *cmdPtr;\n} SendEvent;\n\n#ifdef TK_SEND_ENABLED_ON_WINDOWS\ntypedef struct {\n    bool initialized;\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\n\n/*\n * Functions internal to this file.\n */\n\n#ifdef TK_SEND_ENABLED_ON_WINDOWS\nstatic Tcl_CmdDeleteProc CmdDeleteProc;\nstatic void\t\tRevokeObjectRegistration(RegisteredInterp *riPtr);\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\nstatic HRESULT\t\tBuildMoniker(const char *name, LPMONIKER *pmk);\n#ifdef TK_SEND_ENABLED_ON_WINDOWS\nstatic HRESULT\t\tRegisterInterp(const char *name,\n\t\t\t    RegisteredInterp *riPtr);\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\nstatic int\t\tFindInterpreterObject(Tcl_Interp *interp,\n\t\t\t    const char *name, LPDISPATCH *ppdisp);\nstatic int\t\tSend(LPDISPATCH pdispInterp, Tcl_Interp *interp,\n\t\t\t    int async, void *clientData, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tSendTrace(const char *format, ...);\nstatic Tcl_EventProc\tSendEventProc;\n\n#if defined(DEBUG) || defined(_DEBUG)\n#define TRACE SendTrace\n#else\n#define TRACE 1 ? ((void)0) : SendTrace\n#endif /* DEBUG || _DEBUG */\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SetAppName --\n *\n *\tThis function is called to associate an ASCII name with a Tk\n *\tapplication. If the application has already been named, the name\n *\treplaces the old one.\n *\n * Results:\n *\tThe return value is the name actually given to the application. This\n *\twill normally be the same as name, but if name was already in use for\n *\tan application then a name of the form \"name #2\" will be chosen, with\n *\ta high enough number to make the name unique.\n *\n * Side effects:\n *\tRegistration info is saved, thereby allowing the \"send\" command to be\n *\tused later to invoke commands in the application. In addition, the\n *\t\"send\" command is created in the application's interpreter. The\n *\tregistration will be removed automatically if the interpreter is\n *\tdeleted or the \"send\" command is removed.\n *\n *--------------------------------------------------------------\n */\n\nconst char *\nTk_SetAppName(\n    Tk_Window tkwin,\t\t/* Token for any window in the application to\n\t\t\t\t * be named: it is just used to identify the\n\t\t\t\t * application and the display.  */\n    const char *name)\t\t/* The name that will be used to refer to the\n\t\t\t\t * interpreter in later \"send\" commands. Must\n\t\t\t\t * be globally unique. */\n{\n#ifndef TK_SEND_ENABLED_ON_WINDOWS\n    (void)tkwin;\n\n    /*\n     * Temporarily disabled for bug #858822\n     */\n\n    return name;\n#else /* TK_SEND_ENABLED_ON_WINDOWS */\n\n    ThreadSpecificData *tsdPtr = NULL;\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    RegisteredInterp *riPtr = NULL;\n    Tcl_Interp *interp;\n    HRESULT hr = S_OK;\n\n    interp = winPtr->mainPtr->interp;\n    tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * Initialise the COM library for this interpreter just once.\n     */\n\n    if (!tsdPtr->initialized) {\n\thr = CoInitialize(0);\n\tif (FAILED(hr)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"failed to initialize the COM library\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"SEND\", \"COM\", (char *)NULL);\n\t    return \"\";\n\t}\n\ttsdPtr->initialized = true;\n\tTRACE(\"Initialized COM library for interp 0x%\" TCL_Z_MODIFIER \"x\\n\", (size_t)interp);\n    }\n\n    /*\n     * If the interp hasn't been registered before then we need to create the\n     * registration structure and the COM object. If it has been registered\n     * already then we can reuse all and just register the new name.\n     */\n\n    riPtr = Tcl_GetAssocData(interp, \"tkWinSend::ri\", NULL);\n    if (riPtr == NULL) {\n\tLPUNKNOWN *objPtr;\n\n\triPtr = (RegisteredInterp *)Tcl_Alloc(sizeof(RegisteredInterp));\n\tmemset(riPtr, 0, sizeof(RegisteredInterp));\n\triPtr->interp = interp;\n\n\tobjPtr = &riPtr->obj;\n\thr = TkWinSendCom_CreateInstance(interp, &IID_IUnknown,\n\t\t(void **) objPtr);\n\n\tTcl_CreateObjCommand2(interp, \"send\", Tk_SendObjCmd, riPtr,\n\t\tCmdDeleteProc);\n\tif (Tcl_IsSafe(interp)) {\n\t    Tcl_HideCommand(interp, \"send\", \"send\");\n\t}\n\tTcl_SetAssocData(interp, \"tkWinSend::ri\", NULL, riPtr);\n    } else {\n\tRevokeObjectRegistration(riPtr);\n    }\n\n    RegisterInterp(name, riPtr);\n    return (const char *) riPtr->name;\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetInterpNames --\n *\n *\tThis function is invoked to fetch a list of all the interpreter names\n *\tcurrently registered for the display of a particular window.\n *\n * Results:\n *\tA standard Tcl return value. Interp->result will be set to hold a list\n *\tof all the interpreter names defined for tkwin's display. If an error\n *\toccurs, then TCL_ERROR is returned and interp->result will hold an\n *\terror message.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkGetInterpNames(\n    Tcl_Interp *interp,\t\t/* Interpreter for returning a result. */\n    TCL_UNUSED(Tk_Window))\t/* Window whose display is to be used for the\n\t\t\t\t * lookup. */\n{\n#ifndef TK_SEND_ENABLED_ON_WINDOWS\n    (void)interp;\n    /*\n     * Temporarily disabled for bug #858822\n     */\n\n    return TCL_OK;\n#else /* TK_SEND_ENABLED_ON_WINDOWS */\n\n    LPRUNNINGOBJECTTABLE pROT = NULL;\n    LPCOLESTR oleszStub = TKWINSEND_REGISTRATION_BASE;\n    HRESULT hr = S_OK;\n    Tcl_Obj *objList = NULL;\n    int result = TCL_OK;\n\n    hr = GetRunningObjectTable(0, &pROT);\n    if (SUCCEEDED(hr)) {\n\tIBindCtx* pBindCtx = NULL;\n\tobjList = Tcl_NewListObj(0, NULL);\n\thr = CreateBindCtx(0, &pBindCtx);\n\n\tif (SUCCEEDED(hr)) {\n\t    IEnumMoniker* pEnum;\n\n\t    hr = pROT->lpVtbl->EnumRunning(pROT, &pEnum);\n\t    if (SUCCEEDED(hr)) {\n\t\tIMoniker* pmk = NULL;\n\n\t\twhile (pEnum->lpVtbl->Next(pEnum, 1, &pmk, NULL) == S_OK) {\n\t\t    LPOLESTR olestr;\n\n\t\t    hr = pmk->lpVtbl->GetDisplayName(pmk, pBindCtx, NULL,\n\t\t\t    &olestr);\n\t\t    if (SUCCEEDED(hr)) {\n\t\t\tIMalloc *pMalloc = NULL;\n\n\t\t\tif (wcsncmp(olestr, oleszStub,\n\t\t\t\twcslen(oleszStub)) == 0) {\n\t\t\t    LPOLESTR p = olestr + wcslen(oleszStub);\n\n\t\t\t    if (*p) {\n\t\t\t\tTcl_DString ds;\n\n\t\t\t\tTcl_DStringInit(&ds);\n\t\t\t\tTcl_WCharToUtfDString(p + 1, wcslen(p + 1), &ds);\n\t\t\t\tresult = Tcl_ListObjAppendElement(interp,\n\t\t\t\t\tobjList,\n\t\t\t\t\tTcl_NewStringObj(Tcl_DStringValue(&ds),\n\t\t\t\t\t\tTcl_DStringLength(&ds)));\n\t\t\t\tTcl_DStringFree(&ds);\n\t\t\t    }\n\t\t\t}\n\n\t\t\thr = CoGetMalloc(1, &pMalloc);\n\t\t\tif (SUCCEEDED(hr)) {\n\t\t\t    pMalloc->lpVtbl->Free(pMalloc, (void*)olestr);\n\t\t\t    pMalloc->lpVtbl->Release(pMalloc);\n\t\t\t}\n\t\t    }\n\t\t    pmk->lpVtbl->Release(pmk);\n\t\t}\n\t\tpEnum->lpVtbl->Release(pEnum);\n\t    }\n\t    pBindCtx->lpVtbl->Release(pBindCtx);\n\t}\n\tpROT->lpVtbl->Release(pROT);\n    }\n\n    if (FAILED(hr)) {\n\t/*\n\t * Expire the list if set.\n\t */\n\n\tif (objList != NULL) {\n\t    Tcl_DecrRefCount(objList);\n\t}\n\tTcl_SetObjResult(interp, TkWin32ErrorObj(hr));\n\tresult = TCL_ERROR;\n    }\n\n    if (result == TCL_OK) {\n\tTcl_SetObjResult(interp, objList);\n    }\n\n    return result;\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * Tk_SendCmd --\n *\n *\tThis function is invoked to process the \"send\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *--------------------------------------------------------------\n */\n\nint\nTk_SendObjCmd(\n    void *clientData,\t/* Information about sender (only dispPtr\n\t\t\t\t * field is used). */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument strings. */\n{\n    enum {\n\tSEND_ASYNC, SEND_DISPLAYOF, SEND_LAST\n    };\n    static const char *const sendOptions[] = {\n\t\"-async\",   \"-displayof\",   \"--\",  NULL\n    };\n    const char *stringRep;\n    int result = TCL_OK;\n    int async = 0, index;\n    Tcl_Size i;\n\n    /*\n     * Process the command options.\n     */\n\n    for (i = 1; i < (objc - 1); i++) {\n\tstringRep = Tcl_GetString(objv[i]);\n\tif (stringRep[0] == '-') {\n\t    if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions,\n\t\t    sizeof(char *), \"option\", 0, &index) != TCL_OK) {\n\t\tbreak;\n\t    }\n\t    if (index == SEND_ASYNC) {\n\t\tasync = 1;\n\t    } else if (index == SEND_DISPLAYOF) {\n\t\ti++;\n\t    } else /* if (index == SEND_LAST) */ {\n\t\ti++;\n\t\tbreak;\n\t    }\n\t} else {\n\t    break;\n\t}\n    }\n\n    /*\n     * Ensure we still have a valid command.\n     */\n\n    if (objc < (i + 2)) {\n\tTcl_WrongNumArgs(interp, 1, objv,\n\t\t\"?-async? ?-displayof? ?--? interpName arg ?arg ...?\");\n\tresult = TCL_ERROR;\n    }\n\n    /*\n     * Send the arguments to the foreign interp.\n     */\n    /* FIX ME: we need to check for local interp */\n    if (result == TCL_OK) {\n\tLPDISPATCH pdisp;\n\n\tresult = FindInterpreterObject(interp, Tcl_GetString(objv[i]), &pdisp);\n\tif (result == TCL_OK) {\n\t    i++;\n\t    result = Send(pdisp, interp, async, clientData, objc-i, objv+i);\n\t    pdisp->lpVtbl->Release(pdisp);\n\t}\n    }\n\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * FindInterpreterObject --\n *\n *\tSearch the set of objects currently registered with the Running Object\n *\tTable for one which matches the registered name. Tk objects are named\n *\tusing BuildMoniker by always prefixing with TclEval.\n *\n * Results:\n *\tIf a matching object registration is found, then the registered\n *\tIDispatch interface pointer is returned. If not, then an error message\n *\tis placed in the interpreter and TCL_ERROR is returned.\n *\n * Side effects:\n *\tNone.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nFindInterpreterObject(\n    Tcl_Interp *interp,\n    const char *name,\n    LPDISPATCH *ppdisp)\n{\n    LPRUNNINGOBJECTTABLE pROT = NULL;\n    int result = TCL_OK;\n    HRESULT hr = GetRunningObjectTable(0, &pROT);\n\n    if (SUCCEEDED(hr)) {\n\tIBindCtx* pBindCtx = NULL;\n\n\thr = CreateBindCtx(0, &pBindCtx);\n\tif (SUCCEEDED(hr)) {\n\t    LPMONIKER pmk = NULL;\n\n\t    hr = BuildMoniker(name, &pmk);\n\t    if (SUCCEEDED(hr)) {\n\t\tIUnknown *pUnkInterp = NULL, **ppUnkInterp = &pUnkInterp;\n\n\t\thr = pROT->lpVtbl->IsRunning(pROT, pmk);\n\t\thr = pmk->lpVtbl->BindToObject(pmk, pBindCtx, NULL,\n\t\t\t&IID_IUnknown, (void **) ppUnkInterp);\n\t\tif (SUCCEEDED(hr)) {\n\t\t    hr = pUnkInterp->lpVtbl->QueryInterface(pUnkInterp,\n\t\t\t    &IID_IDispatch, (void **) ppdisp);\n\t\t    pUnkInterp->lpVtbl->Release(pUnkInterp);\n\n\t\t} else {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"no application named \\\"%s\\\"\", name));\n\t\t    Tcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"APPLICATION\",\n\t\t\t    (char *)NULL);\n\t\t    result = TCL_ERROR;\n\t\t}\n\n\t\tpmk->lpVtbl->Release(pmk);\n\t    }\n\t    pBindCtx->lpVtbl->Release(pBindCtx);\n\t}\n\tpROT->lpVtbl->Release(pROT);\n    }\n    if (FAILED(hr) && result == TCL_OK) {\n\tTcl_SetObjResult(interp, TkWin32ErrorObj(hr));\n\tresult = TCL_ERROR;\n    }\n    return result;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * CmdDeleteProc --\n *\n *\tThis function is invoked by Tcl when the \"send\" command is deleted in\n *\tan interpreter. It unregisters the interpreter.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe interpreter given by riPtr is unregistered, the registration\n *\tstructure is free'd and the COM object unregistered and released.\n *\n *--------------------------------------------------------------\n */\n\n#ifdef TK_SEND_ENABLED_ON_WINDOWS\nstatic void\nCmdDeleteProc(\n    void *clientData)\n{\n    RegisteredInterp *riPtr = (RegisteredInterp *)clientData;\n\n    /*\n     * Lock the package structure in memory.\n     */\n\n    Tcl_Preserve(clientData);\n\n    /*\n     * Revoke the ROT registration.\n     */\n\n    RevokeObjectRegistration(riPtr);\n\n    /*\n     * Release the registration object.\n     */\n\n    riPtr->obj->lpVtbl->Release(riPtr->obj);\n    riPtr->obj = NULL;\n\n    Tcl_DeleteAssocData(riPtr->interp, \"tkWinSend::ri\");\n\n    /*\n     * Unlock the package data structure.\n     */\n\n    Tcl_Release(clientData);\n\n    Tcl_Free(clientData);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * RevokeObjectRegistration --\n *\n *\tReleases the interpreters registration object from the Running Object\n *\tTable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe stored cookie value is zeroed and the name is free'd and the\n *\tpointer set to NULL.\n *\n *--------------------------------------------------------------\n */\n\nstatic void\nRevokeObjectRegistration(\n    RegisteredInterp *riPtr)\n{\n    LPRUNNINGOBJECTTABLE pROT = NULL;\n    HRESULT hr = S_OK;\n\n    if (riPtr->cookie != 0) {\n\thr = GetRunningObjectTable(0, &pROT);\n\tif (SUCCEEDED(hr)) {\n\t    hr = pROT->lpVtbl->Revoke(pROT, riPtr->cookie);\n\t    pROT->lpVtbl->Release(pROT);\n\t    riPtr->cookie = 0;\n\t}\n    }\n\n    /*\n     * Release the name storage.\n     */\n\n    if (riPtr->name != NULL) {\n\tfree(riPtr->name);\n\triPtr->name = NULL;\n    }\n}\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * BuildMoniker --\n *\n *\tConstruct a moniker from the given name. This ensures that all our\n *\tmonikers have the same prefix.\n *\n * Results:\n *\tS_OK. If the name cannot be turned into a moniker then a COM error\n *\tcode is returned.\n *\n * Side effects:\n *\tThe moniker created is stored at the address given by ppmk.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic HRESULT\nBuildMoniker(\n    const char *name,\n    LPMONIKER *ppmk)\n{\n    LPMONIKER pmkClass = NULL;\n    HRESULT hr = CreateFileMoniker(TKWINSEND_REGISTRATION_BASE, &pmkClass);\n\n    if (SUCCEEDED(hr)) {\n\tLPMONIKER pmkItem = NULL;\n\tTcl_DString dString;\n\n\tTcl_DStringInit(&dString);\n\tTcl_UtfToWCharDString(name, TCL_INDEX_NONE, &dString);\n\thr = CreateFileMoniker((LPOLESTR)Tcl_DStringValue(&dString), &pmkItem);\n\tTcl_DStringFree(&dString);\n\tif (SUCCEEDED(hr)) {\n\t    hr = pmkClass->lpVtbl->ComposeWith(pmkClass, pmkItem, FALSE, ppmk);\n\t    pmkItem->lpVtbl->Release(pmkItem);\n\t}\n\tpmkClass->lpVtbl->Release(pmkClass);\n    }\n    return hr;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * RegisterInterp --\n *\n *\tAttempts to register the provided name for this interpreter. If the\n *\tgiven name is already in use, then a numeric suffix is appended as\n *\t\" #n\" until we identify a unique name.\n *\n * Results:\n *\tReturns S_OK if successful, else a COM error code.\n *\n * Side effects:\n *\tRegistration returns a cookie value which is stored. We also store a\n *\tcopy of the name.\n *\n * ----------------------------------------------------------------------\n */\n\n#ifdef TK_SEND_ENABLED_ON_WINDOWS\nstatic HRESULT\nRegisterInterp(\n    const char *name,\n    RegisteredInterp *riPtr)\n{\n    HRESULT hr = S_OK;\n    LPRUNNINGOBJECTTABLE pROT = NULL;\n    LPMONIKER pmk = NULL;\n    int i, offset;\n    const char *actualName = name;\n    Tcl_DString dString;\n    Tcl_DStringInit(&dString);\n\n    hr = GetRunningObjectTable(0, &pROT);\n    if (SUCCEEDED(hr)) {\n\toffset = 0;\n\tfor (i = 1; SUCCEEDED(hr); i++) {\n\t    if (i > 1) {\n\t\tif (i == 2) {\n\t\t    Tcl_DStringInit(&dString);\n\t\t    Tcl_DStringAppend(&dString, name, TCL_INDEX_NONE);\n\t\t    Tcl_DStringAppend(&dString, \" #\", 2);\n\t\t    offset = Tcl_DStringLength(&dString);\n\t\t    Tcl_DStringSetLength(&dString, offset + TCL_INTEGER_SPACE);\n\t\t    actualName = Tcl_DStringValue(&dString);\n\t\t}\n\t\tsnprintf(Tcl_DStringValue(&dString) + offset, TCL_INTEGER_SPACE, \"%d\", i);\n\t    }\n\n\t    hr = BuildMoniker(actualName, &pmk);\n\t    if (SUCCEEDED(hr)) {\n\n\t\thr = pROT->lpVtbl->Register(pROT,\n\t\t    ROTFLAGS_REGISTRATIONKEEPSALIVE,\n\t\t    riPtr->obj, pmk, &riPtr->cookie);\n\n\t\tpmk->lpVtbl->Release(pmk);\n\t    }\n\n\t    if (hr == MK_S_MONIKERALREADYREGISTERED) {\n\t\tpROT->lpVtbl->Revoke(pROT, riPtr->cookie);\n\t    } else if (hr == S_OK) {\n\t\tbreak;\n\t    }\n\t}\n\n\tpROT->lpVtbl->Release(pROT);\n    }\n\n    if (SUCCEEDED(hr)) {\n\triPtr->name = strdup(actualName);\n    }\n\n    Tcl_DStringFree(&dString);\n    return hr;\n}\n#endif /* TK_SEND_ENABLED_ON_WINDOWS */\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * Send --\n *\n *\tPerform an interface call to the server object. We convert the Tcl\n *\targuments into a BSTR using 'concat'. The result should be a BSTR that\n *\twe can set as the interp's result string.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nSend(\n    LPDISPATCH pdispInterp,\t/* Pointer to the remote interp's COM\n\t\t\t\t * object. */\n    Tcl_Interp *interp,\t\t/* The local interpreter. */\n    int async,\t\t\t/* Flag for the calling style. */\n    TCL_UNUSED(void *),\n    Tcl_Size objc,\t\t\t/* Number of arguments to be sent. */\n    Tcl_Obj *const objv[])\t/* The arguments to be sent. */\n{\n    VARIANT vCmd, vResult;\n    DISPPARAMS dp;\n    EXCEPINFO ei;\n    UINT uiErr = 0;\n    HRESULT hr = S_OK, ehr = S_OK;\n    Tcl_Obj *cmd = NULL;\n    DISPID dispid;\n    Tcl_DString ds;\n    const char *src;\n\n    cmd = Tcl_ConcatObj(objc, objv);\n\n    /*\n     * Setup the arguments for the COM method call.\n     */\n\n    VariantInit(&vCmd);\n    VariantInit(&vResult);\n    memset(&dp, 0, sizeof(dp));\n    memset(&ei, 0, sizeof(ei));\n\n    vCmd.vt = VT_BSTR;\n    src = Tcl_GetString(cmd);\n    Tcl_DStringInit(&ds);\n    vCmd.bstrVal = SysAllocString(Tcl_UtfToWCharDString(src, cmd->length, &ds));\n    Tcl_DStringFree(&ds);\n\n    dp.cArgs = 1;\n    dp.rgvarg = &vCmd;\n\n    /*\n     * Select the method to use based upon the async flag and call the method.\n     */\n\n    dispid = async ? TKWINSENDCOM_DISPID_ASYNC : TKWINSENDCOM_DISPID_SEND;\n\n    hr = pdispInterp->lpVtbl->Invoke(pdispInterp, dispid,\n\t    &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,\n\t    &dp, &vResult, &ei, &uiErr);\n\n    /*\n     * Convert the result into a string and place in the interps result.\n     */\n\n    ehr = VariantChangeType(&vResult, &vResult, 0, VT_BSTR);\n    if (SUCCEEDED(ehr)) {\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString(vResult.bstrVal, SysStringLen(vResult.bstrVal), &ds);\n\tTcl_DStringResult(interp, &ds);\n    }\n\n    /*\n     * Errors are returned as dispatch exceptions. If an error code was\n     * returned then we decode the exception and setup the Tcl error\n     * variables.\n     */\n\n    if (hr == DISP_E_EXCEPTION && ei.bstrSource != NULL) {\n\tTcl_Obj *opError, *opErrorCode, *opErrorInfo;\n\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString(ei.bstrSource, SysStringLen(ei.bstrSource), &ds);\n\topError = Tcl_NewStringObj(Tcl_DStringValue(&ds),\n\t\tTcl_DStringLength(&ds));\n\tTcl_DStringFree(&ds);\n\tTcl_ListObjIndex(interp, opError, 0, &opErrorCode);\n\tTcl_SetObjErrorCode(interp, opErrorCode);\n\tTcl_ListObjIndex(interp, opError, 1, &opErrorInfo);\n\tTcl_AppendObjToErrorInfo(interp, opErrorInfo);\n    }\n\n    /*\n     * Clean up any COM allocated resources.\n     */\n\n    SysFreeString(ei.bstrDescription);\n    SysFreeString(ei.bstrSource);\n    SysFreeString(ei.bstrHelpFile);\n    VariantClear(&vCmd);\n\n    return (SUCCEEDED(hr) ? TCL_OK : TCL_ERROR);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkWinSend_SetExcepInfo --\n *\n *\tConvert the error information from a Tcl interpreter into a COM\n *\texception structure. This information is then registered with the COM\n *\tthread exception object so that it can be used for rich error\n *\treporting by COM clients.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe current COM thread has its error object modified.\n *\n * ----------------------------------------------------------------------\n */\n\nvoid\nTkWinSend_SetExcepInfo(\n    Tcl_Interp *interp,\n    EXCEPINFO *pExcepInfo)\n{\n    Tcl_Obj *opError, *opErrorInfo, *opErrorCode;\n    ICreateErrorInfo *pCEI;\n    IErrorInfo *pEI, **ppEI = &pEI;\n    HRESULT hr;\n    Tcl_DString ds;\n    const char *src;\n\n    if (!pExcepInfo) {\n\treturn;\n    }\n\n    opError = Tcl_GetObjResult(interp);\n    opErrorInfo = Tcl_GetVar2Ex(interp, \"errorInfo\", NULL, TCL_GLOBAL_ONLY);\n    opErrorCode = Tcl_GetVar2Ex(interp, \"errorCode\", NULL, TCL_GLOBAL_ONLY);\n\n    /*\n     * Pack the trace onto the end of the Tcl exception descriptor.\n     */\n\n    opErrorCode = Tcl_DuplicateObj(opErrorCode);\n    Tcl_IncrRefCount(opErrorCode);\n    Tcl_ListObjAppendElement(interp, opErrorCode, opErrorInfo);\n    /* TODO: Handle failure to append */\n\n    src = Tcl_GetString(opError);\n    Tcl_DStringInit(&ds);\n    pExcepInfo->bstrDescription =\n\t    SysAllocString(Tcl_UtfToWCharDString(src, opError->length, &ds));\n    Tcl_DStringFree(&ds);\n    src = Tcl_GetString(opErrorCode);\n    Tcl_DStringInit(&ds);\n    pExcepInfo->bstrSource =\n\t    SysAllocString(Tcl_UtfToWCharDString(src, opErrorCode->length, &ds));\n    Tcl_DStringFree(&ds);\n    Tcl_DecrRefCount(opErrorCode);\n    pExcepInfo->scode = E_FAIL;\n\n    hr = CreateErrorInfo(&pCEI);\n    if (!SUCCEEDED(hr)) {\n\treturn;\n    }\n\n    hr = pCEI->lpVtbl->SetGUID(pCEI, &IID_IDispatch);\n    hr = pCEI->lpVtbl->SetDescription(pCEI, pExcepInfo->bstrDescription);\n    hr = pCEI->lpVtbl->SetSource(pCEI, pExcepInfo->bstrSource);\n    hr = pCEI->lpVtbl->QueryInterface(pCEI, &IID_IErrorInfo, (void **) ppEI);\n    if (SUCCEEDED(hr)) {\n\tSetErrorInfo(0, pEI);\n\tpEI->lpVtbl->Release(pEI);\n    }\n    pCEI->lpVtbl->Release(pCEI);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkWinSend_QueueCommand --\n *\n *\tQueue a script for asynchronous evaluation. This is called from the\n *\tCOM objects Async method.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n * ----------------------------------------------------------------------\n */\n\nvoid\nTkWinSend_QueueCommand(\n    Tcl_Interp *interp,\n    Tcl_Obj *cmdPtr)\n{\n    SendEvent *evPtr;\n\n    TRACE(\"SendQueueCommand()\\n\");\n\n    evPtr = (SendEvent *)Tcl_Alloc(sizeof(SendEvent));\n    evPtr->header.proc = SendEventProc;\n    evPtr->header.nextPtr = NULL;\n    evPtr->interp = interp;\n    Tcl_Preserve(evPtr->interp);\n\n    if (Tcl_IsShared(cmdPtr)) {\n\tevPtr->cmdPtr = Tcl_DuplicateObj(cmdPtr);\n    } else {\n\tevPtr->cmdPtr = cmdPtr;\n\tTcl_IncrRefCount(evPtr->cmdPtr);\n    }\n\n    Tcl_QueueEvent((Tcl_Event *)evPtr, TCL_QUEUE_TAIL);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * SendEventProc --\n *\n *\tHandle a request for an asynchronous send. Nothing is returned to the\n *\tcaller so the result is discarded.\n *\n * Results:\n *\tReturns 1 if the event was handled or 0 to indicate it has been\n *\tdeferred.\n *\n * Side effects:\n *\tThe target interpreter's result will be modified.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic int\nSendEventProc(\n    Tcl_Event *eventPtr,\n    TCL_UNUSED(int))\n{\n    SendEvent *evPtr = (SendEvent *)eventPtr;\n\n    TRACE(\"SendEventProc\\n\");\n\n    Tcl_EvalObjEx(evPtr->interp, evPtr->cmdPtr,\n\t    TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);\n\n    Tcl_DecrRefCount(evPtr->cmdPtr);\n    Tcl_Release(evPtr->interp);\n\n    return 1; /* 1 to indicate the event has been handled */\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * SendTrace --\n *\n *\tProvide trace information to the Windows debug stream. To use this -\n *\tuse the TRACE macro, which compiles to nothing when DEBUG is not\n *\tdefined.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\nSendTrace(\n    const char *format, ...)\n{\n    va_list args;\n    static char buffer[1024];\n\n    va_start(args, format);\n    _vsnprintf(buffer, 1023, format, args);\n    OutputDebugStringA(buffer);\n    va_end(args);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinSendCom.c",
    "content": "/*\n * tkWinSendCom.c --\n *\n *\tThis file provides support functions that implement the Windows \"send\"\n *\tcommand using COM interfaces, allowing commands to be passed from\n *\tinterpreter to interpreter. See also tkWinSend.c, where most of the\n *\tinteresting functions are.\n *\n * We implement a COM class for use in registering Tcl interpreters with the\n * system's Running Object Table. This class implements an IDispatch interface\n * with the following method:\n *\tSend(String cmd) As String\n * In other words the Send methods takes a string and evaluates this in the\n * Tcl interpreter. The result is returned as another string.\n *\n * Copyright © 2002 Pat Thoyts <patthoyts@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n#include \"tkWinSendCom.h\"\n\n/*\n * ----------------------------------------------------------------------\n * Non-public prototypes.\n *\n *\tThese are the interface methods for IUnknown, IDispatch and\n *\tISupportErrorInfo.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic void\t\tTkWinSendCom_Destroy(LPDISPATCH pdisp);\n\nstatic STDMETHODIMP\tWinSendCom_QueryInterface(IDispatch *This,\n\t\t\t    REFIID riid, void **ppvObject);\nstatic STDMETHODIMP_(ULONG)\tWinSendCom_AddRef(IDispatch *This);\nstatic STDMETHODIMP_(ULONG)\tWinSendCom_Release(IDispatch *This);\nstatic STDMETHODIMP\tWinSendCom_GetTypeInfoCount(IDispatch *This,\n\t\t\t    UINT *pctinfo);\nstatic STDMETHODIMP\tWinSendCom_GetTypeInfo(IDispatch *This, UINT iTInfo,\n\t\t\t    LCID lcid, ITypeInfo **ppTI);\nstatic STDMETHODIMP\tWinSendCom_GetIDsOfNames(IDispatch *This, REFIID riid,\n\t\t\t    LPOLESTR *rgszNames, UINT cNames, LCID lcid,\n\t\t\t    DISPID *rgDispId);\nstatic STDMETHODIMP\tWinSendCom_Invoke(IDispatch *This, DISPID dispidMember,\n\t\t\t    REFIID riid, LCID lcid, WORD wFlags,\n\t\t\t    DISPPARAMS *pDispParams, VARIANT *pvarResult,\n\t\t\t    EXCEPINFO *pExcepInfo, UINT *puArgErr);\nstatic STDMETHODIMP\tISupportErrorInfo_QueryInterface(\n\t\t\t    ISupportErrorInfo *This, REFIID riid,\n\t\t\t    void **ppvObject);\nstatic STDMETHODIMP_(ULONG)\tISupportErrorInfo_AddRef(\n\t\t\t\t    ISupportErrorInfo *This);\nstatic STDMETHODIMP_(ULONG)\tISupportErrorInfo_Release(\n\t\t\t\t    ISupportErrorInfo *This);\nstatic STDMETHODIMP\tISupportErrorInfo_InterfaceSupportsErrorInfo(\n\t\t\t    ISupportErrorInfo *This, REFIID riid);\nstatic HRESULT\t\tSend(TkWinSendCom *obj, VARIANT vCmd,\n\t\t\t    VARIANT *pvResult, EXCEPINFO *pExcepInfo,\n\t\t\t    UINT *puArgErr);\nstatic HRESULT\t\tAsync(TkWinSendCom *obj, VARIANT Cmd,\n\t\t\t    EXCEPINFO *pExcepInfo, UINT *puArgErr);\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * CreateInstance --\n *\n *\tCreate and initialises a new instance of the WinSend COM class and\n *\treturns an interface pointer for you to use.\n *\n * ----------------------------------------------------------------------\n */\n\nHRESULT\nTkWinSendCom_CreateInstance(\n    Tcl_Interp *interp,\n    REFIID riid,\n    void **ppv)\n{\n    /*\n     * Construct v-tables for each interface.\n     */\n\n    static IDispatchVtbl vtbl = {\n\tWinSendCom_QueryInterface,\n\tWinSendCom_AddRef,\n\tWinSendCom_Release,\n\tWinSendCom_GetTypeInfoCount,\n\tWinSendCom_GetTypeInfo,\n\tWinSendCom_GetIDsOfNames,\n\tWinSendCom_Invoke,\n    };\n    static ISupportErrorInfoVtbl vtbl2 = {\n\tISupportErrorInfo_QueryInterface,\n\tISupportErrorInfo_AddRef,\n\tISupportErrorInfo_Release,\n\tISupportErrorInfo_InterfaceSupportsErrorInfo,\n    };\n    TkWinSendCom *obj = NULL;\n\n    /*\n     * This had probably better always be globally visible memory so we shall\n     * use the COM Task allocator.\n     */\n\n    obj = (TkWinSendCom *) CoTaskMemAlloc(sizeof(TkWinSendCom));\n    if (obj == NULL) {\n\t*ppv = NULL;\n\treturn E_OUTOFMEMORY;\n    }\n\n    obj->lpVtbl = &vtbl;\n    obj->lpVtbl2 = &vtbl2;\n    obj->refcount = 0;\n    obj->interp = interp;\n\n    /*\n     * lock the interp? Tcl_AddRef/Retain?\n     */\n\n    return obj->lpVtbl->QueryInterface((IDispatch *) obj, riid, ppv);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * TkWinSendCom_Destroy --\n *\n *\tThis helper function is the destructor for our COM class.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tReleases the storage allocated for this object.\n *\n * ----------------------------------------------------------------------\n */\nstatic void\nTkWinSendCom_Destroy(\n    LPDISPATCH pdisp)\n{\n    CoTaskMemFree(pdisp);\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * IDispatch --\n *\n *\tThe IDispatch interface implements the 'late-binding' COM methods\n *\ttypically used by scripting COM clients. The Invoke method is the most\n *\timportant one.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic STDMETHODIMP\nWinSendCom_QueryInterface(\n    IDispatch *This,\n    REFIID riid,\n    void **ppvObject)\n{\n    HRESULT hr = E_NOINTERFACE;\n    TkWinSendCom *sendCom = (TkWinSendCom *) This;\n    *ppvObject = NULL;\n\n    if (memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0\n\t    || memcmp(riid, &IID_IDispatch, sizeof(IID)) == 0) {\n\t*ppvObject = (void **) sendCom;\n\tsendCom->lpVtbl->AddRef(This);\n\thr = S_OK;\n    } else if (memcmp(riid, &IID_ISupportErrorInfo, sizeof(IID)) == 0) {\n\t*ppvObject = (void **) (sendCom + 1);\n\tsendCom->lpVtbl2->AddRef((ISupportErrorInfo *) (sendCom + 1));\n\thr = S_OK;\n    }\n    return hr;\n}\n\nstatic STDMETHODIMP_(ULONG)\nWinSendCom_AddRef(\n    IDispatch *This)\n{\n    TkWinSendCom *sendCom = (TkWinSendCom*)This;\n\n    return InterlockedIncrement(&sendCom->refcount);\n}\n\nstatic STDMETHODIMP_(ULONG)\nWinSendCom_Release(\n    IDispatch *This)\n{\n    long r = 0;\n    TkWinSendCom *sendCom = (TkWinSendCom*)This;\n\n    if ((r = InterlockedDecrement(&sendCom->refcount)) == 0) {\n\tTkWinSendCom_Destroy(This);\n    }\n    return r;\n}\n\nstatic STDMETHODIMP\nWinSendCom_GetTypeInfoCount(\n    IDispatch *This,\n    UINT *pctinfo)\n{\n    HRESULT hr = E_POINTER;\n    (void)This;\n\n    if (pctinfo != NULL) {\n\t*pctinfo = 0;\n\thr = S_OK;\n    }\n    return hr;\n}\n\nstatic STDMETHODIMP\nWinSendCom_GetTypeInfo(\n    IDispatch *This,\n    UINT iTInfo,\n    LCID lcid,\n    ITypeInfo **ppTI)\n{\n    HRESULT hr = E_POINTER;\n    (void)This;\n    (void)iTInfo;\n    (void)lcid;\n\n    if (ppTI) {\n\t*ppTI = NULL;\n\thr = E_NOTIMPL;\n    }\n    return hr;\n}\n\nstatic STDMETHODIMP\nWinSendCom_GetIDsOfNames(\n    IDispatch *This,\n    REFIID riid,\n    LPOLESTR *rgszNames,\n    UINT cNames,\n    LCID lcid,\n    DISPID *rgDispId)\n{\n    HRESULT hr = E_POINTER;\n    (void)This;\n    (void)riid;\n    (void)cNames;\n    (void)lcid;\n\n    if (rgDispId) {\n\thr = DISP_E_UNKNOWNNAME;\n\tif (_wcsicmp(*rgszNames, L\"Send\") == 0) {\n\t    *rgDispId = TKWINSENDCOM_DISPID_SEND, hr = S_OK;\n\t} else if (_wcsicmp(*rgszNames, L\"Async\") == 0) {\n\t    *rgDispId = TKWINSENDCOM_DISPID_ASYNC, hr = S_OK;\n\t}\n    }\n    return hr;\n}\n\nstatic STDMETHODIMP\nWinSendCom_Invoke(\n    IDispatch *This,\n    DISPID dispidMember,\n    REFIID riid,\n    LCID lcid,\n    WORD wFlags,\n    DISPPARAMS *pDispParams,\n    VARIANT *pvarResult,\n    EXCEPINFO *pExcepInfo,\n    UINT *puArgErr)\n{\n    HRESULT hr = DISP_E_MEMBERNOTFOUND;\n    TkWinSendCom *sendCom = (TkWinSendCom*)This;\n    (void)riid;\n    (void)lcid;\n\n    switch (dispidMember) {\n    case TKWINSENDCOM_DISPID_SEND:\n\tif (wFlags | DISPATCH_METHOD) {\n\t    if (pDispParams->cArgs != 1) {\n\t\thr = DISP_E_BADPARAMCOUNT;\n\t    } else {\n\t\thr = Send(sendCom, pDispParams->rgvarg[0], pvarResult,\n\t\t\tpExcepInfo, puArgErr);\n\t    }\n\t}\n\tbreak;\n\n    case TKWINSENDCOM_DISPID_ASYNC:\n\tif (wFlags | DISPATCH_METHOD) {\n\t    if (pDispParams->cArgs != 1) {\n\t\thr = DISP_E_BADPARAMCOUNT;\n\t    } else {\n\t\thr = Async(sendCom, pDispParams->rgvarg[0], pExcepInfo, puArgErr);\n\t    }\n\t}\n\tbreak;\n    }\n    return hr;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * ISupportErrorInfo --\n *\n *\tThis interface provides rich error information to COM clients. Used by\n *\tVB and scripting COM clients.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic STDMETHODIMP\nISupportErrorInfo_QueryInterface(\n    ISupportErrorInfo *This,\n    REFIID riid,\n    void **ppvObject)\n{\n    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);\n\n    return sendCom->lpVtbl->QueryInterface((IDispatch *) sendCom, riid, ppvObject);\n}\n\nstatic STDMETHODIMP_(ULONG)\nISupportErrorInfo_AddRef(\n    ISupportErrorInfo *This)\n{\n    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);\n\n    return InterlockedIncrement(&sendCom->refcount);\n}\n\nstatic STDMETHODIMP_(ULONG)\nISupportErrorInfo_Release(\n    ISupportErrorInfo *This)\n{\n    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);\n\n    return sendCom->lpVtbl->Release((IDispatch *) sendCom);\n}\n\nstatic STDMETHODIMP\nISupportErrorInfo_InterfaceSupportsErrorInfo(\n    ISupportErrorInfo *This,\n    REFIID riid)\n{\n    (void)This;\n    (void)riid;\n\n    /*TkWinSendCom *sendCom = (TkWinSendCom*)(This - 1);*/\n    return S_OK; /* or S_FALSE */\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * Async --\n *\n *\tQueues the command for evaluation in the assigned interpreter.\n *\n * Results:\n *\tA standard COM HRESULT is returned. The Tcl result is discarded.\n *\n * Side effects:\n *\tThe interpreters state and result will be modified.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic HRESULT\nAsync(\n    TkWinSendCom *obj,\n    VARIANT Cmd,\n    EXCEPINFO *pExcepInfo,\n    UINT *puArgErr)\n{\n    HRESULT hr = S_OK;\n    VARIANT vCmd;\n    Tcl_DString ds;\n    (void)puArgErr;\n\n    VariantInit(&vCmd);\n\n    hr = VariantChangeType(&vCmd, &Cmd, 0, VT_BSTR);\n    if (FAILED(hr)) {\n\tTcl_SetObjResult(obj->interp, Tcl_NewStringObj(\n\t\t\"invalid args: Async(command)\", TCL_INDEX_NONE));\n\tTkWinSend_SetExcepInfo(obj->interp, pExcepInfo);\n\thr = DISP_E_EXCEPTION;\n    }\n\n    if (SUCCEEDED(hr) && obj->interp) {\n\tTcl_Obj *scriptPtr;\n\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString(vCmd.bstrVal, SysStringLen(vCmd.bstrVal), &ds);\n\tscriptPtr =\n\t\tTcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n\tTcl_DStringFree(&ds);\n\tTkWinSend_QueueCommand(obj->interp, scriptPtr);\n    }\n\n    VariantClear(&vCmd);\n    return hr;\n}\n\f\n/*\n * ----------------------------------------------------------------------\n *\n * Send --\n *\n *\tEvaluates the string in the assigned interpreter. If the result is a\n *\tvalid address then set it to the result returned by the evaluation.\n *\tTcl exceptions are converted into COM exceptions.\n *\n * Results:\n *\tA standard COM HRESULT is returned. The Tcl result is set as the\n *\tmethod calls result.\n *\n * Side effects:\n *\tThe interpreters state and result will be modified.\n *\n * ----------------------------------------------------------------------\n */\n\nstatic HRESULT\nSend(\n    TkWinSendCom *comobj,\n    VARIANT vCmd,\n    VARIANT *pvResult,\n    EXCEPINFO *pExcepInfo,\n    UINT *puArgErr)\n{\n    HRESULT hr = S_OK;\n    int result = TCL_OK;\n    VARIANT v;\n    Tcl_Interp *interp = comobj->interp;\n    Tcl_Obj *scriptPtr;\n    Tcl_DString ds;\n    (void)puArgErr;\n\n    if (interp == NULL) {\n\treturn S_OK;\n    }\n    VariantInit(&v);\n    hr = VariantChangeType(&v, &vCmd, 0, VT_BSTR);\n    if (!SUCCEEDED(hr)) {\n\treturn hr;\n    }\n\n    Tcl_DStringInit(&ds);\n    Tcl_WCharToUtfDString(v.bstrVal, SysStringLen(v.bstrVal), &ds);\n    scriptPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n    Tcl_DStringFree(&ds);\n    Tcl_Preserve(interp);\n    Tcl_IncrRefCount(scriptPtr);\n    result = Tcl_EvalObjEx(interp, scriptPtr,\n\t    TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);\n    Tcl_DecrRefCount(scriptPtr);\n    if (pvResult != NULL) {\n\tTcl_Obj *obj;\n\tconst char *src;\n\n\tVariantInit(pvResult);\n\tpvResult->vt = VT_BSTR;\n\tobj = Tcl_GetObjResult(interp);\n\tsrc = Tcl_GetString(obj);\n\tTcl_DStringInit(&ds);\n\tpvResult->bstrVal = SysAllocString(Tcl_UtfToWCharDString(src, obj->length, &ds));\n\tTcl_DStringFree(&ds);\n    }\n    if (result == TCL_ERROR) {\n\thr = DISP_E_EXCEPTION;\n\tTkWinSend_SetExcepInfo(interp, pExcepInfo);\n    }\n    Tcl_Release(interp);\n    VariantClear(&v);\n    return hr;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinSendCom.h",
    "content": "/*\n * tkWinSendCom.h --\n *\n *\tThis file provides procedures that implement the Windows \"send\"\n *\tcommand, allowing commands to be passed from interpreter to\n *\tinterpreter.\n *\n * Copyright © 2002 Pat Thoyts <patthoyts@users.sourceforge.net>\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _tkWinSendCom_h_INCLUDE\n#define _tkWinSendCom_h_INCLUDE\n\n#include \"tkWinInt.h\"\n#include <ole2.h>\n\n#ifdef _MSC_VER\n#   pragma comment (lib, \"ole32.lib\")\n#   pragma comment (lib, \"oleaut32.lib\")\n#   pragma comment (lib, \"uuid.lib\")\n#endif\n\n/*\n * TkWinSendCom CoClass structure\n */\n\ntypedef struct {\n    IDispatchVtbl *lpVtbl;\n    ISupportErrorInfoVtbl *lpVtbl2;\n    long refcount;\n    Tcl_Interp *interp;\n} TkWinSendCom;\n\n/*\n * TkWinSendCom Dispatch IDs\n */\n\n#define TKWINSENDCOM_DISPID_SEND   1\n#define TKWINSENDCOM_DISPID_ASYNC  2\n\n/*\n * TkWinSendCom public functions\n */\n\nMODULE_SCOPE HRESULT    TkWinSendCom_CreateInstance(Tcl_Interp *interp,\n\tREFIID riid, void **ppv);\nMODULE_SCOPE void       TkWinSend_QueueCommand(Tcl_Interp *interp,\n\tTcl_Obj *cmdPtr);\nMODULE_SCOPE void       TkWinSend_SetExcepInfo(Tcl_Interp *interp,\n\tEXCEPINFO *pExcepInfo);\n\n#endif /* _tkWinSendCom_h_INCLUDE */\n\n/*\n * Local Variables:\n * mode: c\n * End:\n */\n"
  },
  {
    "path": "win/tkWinSysTray.c",
    "content": "/*\n * tkWinSysTray.c --\n *\n *\ttkWinSysTray.c implements a \"systray\" Tcl command which permits to\n *\tchange the system tray/taskbar icon of a Tk toplevel window and\n *\ta \"sysnotify\" command to post system notifications.\n *\n * Copyright © 1995-1996 Microsoft Corp.\n * Copyright © 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany\n * Copyright © 2020 Kevin Walzer\n * Copyright © 2020 Eric Boudaillier\n * Copyright © 2020 Francois Vogel\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkInt.h\"\n#include <windows.h>\n#include <shobjidl.h>\n#include <propvarutil.h>\n#include <propkey.h>\n#include \"tkWin.h\"\n#include \"tkWinIco.h\"\n\n#ifndef NOTIFYICON_VERSION_4\n#   define NOTIFYICON_VERSION_4 4\n#endif\n\n/*\n * Based extensively on the winico extension and sample code from Microsoft.\n * Some of the code was adapted into tkWinWM.c to implement the \"wm iconphoto\"\n * command (TIP 159), and here we are borrowing that code to use Tk images\n * to create system tray icons instead of ico files. Additionally, we are\n * removing obsolete parts of the winico extension, and implementing\n * more of the Shell_Notification API to add balloon/system notifications.\n */\n\n#define GETHINSTANCE Tk_GetHINSTANCE()\n\ntypedef struct IcoInfo {\n    HICON hIcon;                /* icon handle returned by LoadIcon. */\n    int id;\t\t\t\t\t\t/* Identifier for command;  used to\n\t\t\t\t\t\t\t\t* cancel it. */\n    Tcl_Obj *taskbar_txt;       /* text to display in the taskbar */\n    Tcl_Interp *interp;         /* interp which created the icon */\n    Tcl_Obj *taskbar_command;   /* command to eval if events in the taskbar\n\t\t\t\t * arrive */\n    int taskbar_flags;          /* taskbar related flags*/\n    HWND hwndFocus;\n    struct IcoInfo *nextPtr;\n} IcoInfo;\n\n/* Per-interp structure */\ntypedef struct IcoInterpInfo {\n    HWND hwnd;                  /* Handler window */\n    int counter;                /* Counter for IcoInfo id generation */\n    IcoInfo *firstIcoPtr;       /* List of created IcoInfo */\n    struct IcoInterpInfo *nextPtr;\n} IcoInterpInfo;\n\n#define TASKBAR_ICON 1\n#define ICON_MESSAGE WM_USER + 1234\n\n#define HANDLER_CLASS \"Wtk_TaskbarHandler\"\nstatic HWND CreateTaskbarHandlerWindow(void);\n\nstatic IcoInterpInfo *firstIcoInterpPtr = NULL;\nstatic Tk_EventProc WinIcoDestroy;\n\f\n/*\n * If someone wants to see the several masks somewhere on the screen...\n * set the ICO_DRAW define and feel free to make some Tcl commands\n * for accessing it.  The normal drawing of an Icon to a DC is really easy:\n * DrawIcon(hdc,x,y,hIcon) or , more complicated\n * DrawIconEx32PlusMoreParameters ...\n */\n\n/* #define ICO_DRAW */\n#ifdef ICO_DRAW\n#define RectWidth(r)((r).right - (r).left + 1)\n#define RectHeight(r)((r).bottom - (r).top + 1)\n\n/*\n *----------------------------------------------------------------------\n *\n * DrawXORMask --\n *\n *\tUsing DIB functions, draw XOR mask on hDC in Rect.\n *\n * Results:\n *\tIcon is rendered.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic BOOL\nDrawXORMask(\n    HDC hDC,\n    RECT Rect,\n    LPLPICONIMAGE lpIcon)\n{\n    int x, y;\n\n    /* Sanity checks */\n    if (lpIcon == NULL) {\n\treturn FALSE;\n    }\n    if (lpIcon->lpBits == NULL) {\n\treturn FALSE;\n    }\n\n    /* Account for height*2 thing */\n    lpIcon->lpbi->bmiHeader.biHeight /= 2;\n\n    /* Locate it */\n    x = Rect.left + ((RectWidth(Rect) - lpIcon->lpbi->bmiHeader.biWidth) / 2);\n    y = Rect.top + ((RectHeight(Rect) - lpIcon->lpbi->bmiHeader.biHeight) / 2);\n\n    /* Blast it to the screen */\n    SetDIBitsToDevice(hDC, x, y,\n\t    lpIcon->lpbi->bmiHeader.biWidth,\n\t    lpIcon->lpbi->bmiHeader.biHeight,\n\t    0, 0, 0, lpIcon->lpbi->bmiHeader.biHeight,\n\t    lpIcon->lpXOR, lpIcon->lpbi, DIB_RGB_COLORS);\n\n    /* UnAccount for height*2 thing */\n    lpIcon->lpbi->bmiHeader.biHeight *= 2;\n\n    return TRUE;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * DrawANDMask --\n *\n *\tUsing DIB functions, draw AND mask on hDC in Rect.\n *\n * Results:\n *\tIcon is rendered.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nBOOL\nDrawANDMask(\n    HDC hDC,\n    RECT Rect,\n    LPLPICONIMAGE lpIcon)\n{\n    LPBITMAPINFO lpbi;\n    int x, y;\n\n    /* Sanity checks */\n    if (lpIcon == NULL) {\n\treturn FALSE;\n    }\n    if (lpIcon->lpBits == NULL) {\n\treturn FALSE;\n    }\n\n    /* Need a bitmap header for the mono mask */\n    lpbi = (LPBITMAPINFO)Tcl_Alloc(sizeof(BITMAPINFO) + (2 * sizeof(RGBQUAD)));\n    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    lpbi->bmiHeader.biWidth = lpIcon->lpbi->bmiHeader.biWidth;\n    lpbi->bmiHeader.biHeight = lpIcon->lpbi->bmiHeader.biHeight / 2;\n    lpbi->bmiHeader.biPlanes = 1;\n    lpbi->bmiHeader.biBitCount = 1;\n    lpbi->bmiHeader.biCompression = BI_RGB;\n    lpbi->miHeader.biSizeImage = 0;\n    lpbi->bmiHeader.biXPelsPerMeter = 0;\n    lpbi->bmiHeader.biYPelsPerMeter = 0;\n    lpbi->bmiHeader.biClrUsed = 0;\n    lpbi->bmiHeader.biClrImportant = 0;\n    lpbi->bmiColors[0].rgbRed = 0;\n    lpbi->bmiColors[0].rgbGreen = 0;\n    lpbi->bmiColors[0].rgbBlue = 0;\n    lpbi->bmiColors[0].rgbReserved = 0;\n    lpbi->bmiColors[1].rgbRed = 255;\n    lpbi->bmiColors[1].rgbGreen = 255;\n    lpbi->bmiColors[1].rgbBlue = 255;\n    lpbi->bmiColors[1].rgbReserved = 0;\n\n    /* Locate it */\n    x = Rect.left + ((RectWidth(Rect) - lpbi->bmiHeader.biWidth) / 2);\n    y = Rect.top + ((RectHeight(Rect) - lpbi->bmiHeader.biHeight) / 2);\n\n    /* Blast it to the screen */\n    SetDIBitsToDevice(hDC, x, y,\n\t    lpbi->bmiHeader.biWidth,\n\t    lpbi->bmiHeader.biHeight,\n\t    0, 0, 0, lpbi->bmiHeader.biHeight,\n\t    lpIcon->lpAND, lpbi, DIB_RGB_COLORS);\n\n    /* clean up */\n    Tcl_Free(lpbi);\n\n    return TRUE;\n}\n#endif /* ICO_DRAW */\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TaskbarOperation --\n *\n *\tManagement of icon display.\n *\n * Results:\n *\tIcon is displayed or deleted.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTaskbarOperation(\n    IcoInterpInfo *icoInterpPtr,\n    IcoInfo *icoPtr,\n    int oper)\n{\n    NOTIFYICONDATAW ni;\n    WCHAR *str;\n\n    ni.cbSize = sizeof(NOTIFYICONDATAW);\n    ni.hWnd = icoInterpPtr->hwnd;\n    ni.uID = icoPtr->id;\n    ni.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;\n    ni.uCallbackMessage = ICON_MESSAGE;\n    ni.hIcon = icoPtr->hIcon;\n\n    if (icoPtr->taskbar_txt != NULL) {\n\tTcl_DString dst;\n\tTcl_DStringInit(&dst);\n\tstr = (WCHAR *)Tcl_UtfToWCharDString(Tcl_GetString(icoPtr->taskbar_txt), TCL_INDEX_NONE, &dst);\n\twcsncpy(ni.szTip, str, sizeof(ni.szTip) / sizeof(WCHAR) - 1);\n\tni.szTip[sizeof(ni.szTip) / sizeof(WCHAR) - 1] = '\\0';\n\tTcl_DStringFree(&dst);\n    } else {\n\tni.szTip[0] = 0;\n    }\n\n    if (Shell_NotifyIconW(oper, &ni) == 1) {\n\tif (oper == NIM_ADD || oper == NIM_MODIFY) {\n\t    icoPtr->taskbar_flags |= TASKBAR_ICON;\n\t}\n\tif (oper == NIM_DELETE) {\n\t    icoPtr->taskbar_flags &= ~TASKBAR_ICON;\n\t}\n    }\n    /* Silently ignore error? */\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NewIcon --\n *\n *\tCreate icon for display in system tray.\n *\n * Results:\n *\tIcon is created for display.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic IcoInfo *\nNewIcon(\n    Tcl_Interp *interp,\n    IcoInterpInfo *icoInterpPtr,\n    HICON hIcon)\n{\n    IcoInfo *icoPtr;\n\n    icoPtr = (IcoInfo *)Tcl_Alloc(sizeof(IcoInfo));\n    memset(icoPtr, 0, sizeof(IcoInfo));\n    icoPtr->id = ++icoInterpPtr->counter;\n    icoPtr->hIcon = hIcon;\n    icoPtr->taskbar_txt = NULL;\n    icoPtr->interp = interp;\n\ticoPtr->taskbar_command = NULL;\n    icoPtr->taskbar_flags = 0;\n    icoPtr->hwndFocus = NULL;\n    icoPtr->nextPtr = icoInterpPtr->firstIcoPtr;\n    icoInterpPtr->firstIcoPtr = icoPtr;\n    return icoPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeIcoPtr --\n *\n *\tDelete icon and free memory.\n *\n * Results:\n *\tIcon is removed from display.\n *\n * Side effects:\n *\tMemory/resources freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeIcoPtr(\n    IcoInterpInfo *icoInterpPtr,\n    IcoInfo *icoPtr)\n{\n    IcoInfo *prevPtr;\n    if (icoInterpPtr->firstIcoPtr == icoPtr) {\n\ticoInterpPtr->firstIcoPtr = icoPtr->nextPtr;\n    } else {\n\tfor (prevPtr = icoInterpPtr->firstIcoPtr; prevPtr->nextPtr != icoPtr;\n\t\tprevPtr = prevPtr->nextPtr) {\n\t    /* Empty loop body. */\n\t}\n\tprevPtr->nextPtr = icoPtr->nextPtr;\n    }\n    if (icoPtr->taskbar_flags & TASKBAR_ICON) {\n\tTaskbarOperation(icoInterpPtr, icoPtr, NIM_DELETE);\n    }\n    if (icoPtr->taskbar_txt != NULL) {\n\tTcl_DecrRefCount(icoPtr->taskbar_txt);\n    }\n    if (icoPtr->taskbar_command != NULL) {\n\tTcl_DecrRefCount(icoPtr->taskbar_command);\n    }\n    Tcl_Free(icoPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetIcoPtr --\n *\n *\tGet pointer to icon for display.\n *\n * Results:\n *\tIcon is obtained for display.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic IcoInfo *\nGetIcoPtr(\n    Tcl_Interp *interp,\n    IcoInterpInfo *icoInterpPtr,\n    Tcl_Obj *obj)\n{\n    IcoInfo *icoPtr;\n    int id;\n    const char *string = Tcl_GetString(obj);\n    const char *start;\n    char *end;\n\n    if (strncmp(string, \"ico#\", 4) != 0) {\n\tgoto notfound;\n    }\n    start = string + 4;\n    id = strtoul(start, &end, 10);\n    if ((end == start) || (*end != 0)) {\n\tgoto notfound;\n    }\n    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {\n\tif (icoPtr->id == id) {\n\t    return icoPtr;\n\t}\n    }\n\nnotfound:\n    Tcl_AppendResult(interp, \"icon \\\"\", string,\n\t\"\\\" does not exist\", (char *)NULL);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetInt --\n *\n * Utility function for calculating buffer length.\n *\n * Results:\n *\tLength.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic size_t\nGetInt(\n    Tcl_Size theint,\n    char *buffer,\n    size_t len)\n{\n    snprintf(buffer, len, \"0x%\" TCL_SIZE_MODIFIER \"x\", theint);\n    buffer[len - 1] = 0;\n    return strlen(buffer);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetIntDec --\n *\n * Utility function for calculating buffer length.\n *\n * Results:\n *\tLength.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nGetIntDec(\n    long theint,\n    char *buffer,\n    size_t len)\n{\n    snprintf(buffer, len - 1, \"%ld\", theint);\n    buffer[len - 1] = 0;\n    return (int) strlen(buffer);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TaskbarExpandPercents --\n *\n * Parse strings in taskbar display.\n *\n * Results:\n *\tStrings.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic char*\nTaskbarExpandPercents(\n    IcoInfo *icoPtr,\n    const char *msgstring,\n    WPARAM wParam,\n    LPARAM lParam,\n    char *before,\n    char *after,\n    size_t *aftersize)\n{\n#define SPACELEFT (*aftersize-(dst-after)-1)\n#define AFTERLEN ((*aftersize>0)?(*aftersize*2):1024)\n#define ALLOCLEN ((len>AFTERLEN)?(len*2):AFTERLEN)\n    char buffer[TCL_INTEGER_SPACE + 5];\n    char* dst;\n    dst = after;\n    while (*before) {\n\tconst char *ptr = before;\n\tsize_t len = 1;\n\tif(*before == '%') {\n\t    switch(before[1]){\n\t\tcase 'M':\n\t\tcase 'm': {\n\t\t    before++;\n\t\t    len = strlen(msgstring);\n\t\t    ptr = msgstring;\n\t\t    break;\n\t\t}\n\t\t/* case 'W': {\n\t\t   before++;\n\t\t   len = strlen(winstring);\n\t\t   ptr = winstring;\n\t\t   break;\n\t\t   }\n\t\t*/\n\t\tcase 'i': {\n\t\t    before++;\n\t\t    snprintf(buffer, sizeof(buffer) - 1, \"ico#%d\", icoPtr->id);\n\t\t    len = strlen(buffer);\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'w': {\n\t\t    before++;\n\t\t    len = GetInt((long)wParam,buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'l': {\n\t\t    before++;\n\t\t    len = GetInt((long)lParam,buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 't': {\n\t\t    before++;\n\t\t    len = GetInt((long)GetTickCount(), buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'x': {\n\t\t    POINT pt;\n\t\t    GetCursorPos(&pt);\n\t\t    before++;\n\t\t    len = GetIntDec((long)pt.x, buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'y': {\n\t\t    POINT pt;\n\t\t    GetCursorPos(&pt);\n\t\t    before++;\n\t\t    len = GetIntDec((long)pt.y,buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'X': {\n\t\t    DWORD dw;\n\t\t    dw = GetMessagePos();\n\t\t    before++;\n\t\t    len = GetIntDec((long)LOWORD(dw),buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'Y': {\n\t\t    DWORD dw;\n\t\t    dw = GetMessagePos();\n\t\t    before++;\n\t\t    len = GetIntDec((long)HIWORD(dw),buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase 'H': {\n\t\t    before++;\n\t\t    len = GetInt(PTR2INT(icoPtr->hwndFocus), buffer, sizeof(buffer));\n\t\t    ptr = buffer;\n\t\t    break;\n\t\t}\n\t\tcase '%': {\n\t\t    before++;\n\t\t    len = 1;\n\t\t    ptr = \"%\";\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\tif (SPACELEFT < len) {\n\t    char *newspace;\n\t    ptrdiff_t dist = dst - after;\n\t    size_t alloclen = ALLOCLEN;\n\t    newspace = (char *)Tcl_Alloc(alloclen);\n\t    if (dist>0) {\n\t\tmemcpy(newspace, after, dist);\n\t    }\n\t    if (after && *aftersize) {\n\t\tTcl_Free(after);\n\t    }\n\t    *aftersize = alloclen;\n\t    after = newspace;\n\t    dst = after + dist;\n\t}\n\tif (len > 0) {\n\t    memcpy(dst, ptr, len);\n\t}\n\tdst += len;\n\tif ((dst-after)>((Tcl_Size)*aftersize-1)) {\n\t    printf(\"oops\\n\");\n\t}\n\tbefore++;\n    }\n    *dst = 0;\n    return after;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TaskbarEval --\n *\n * Parse mouse and keyboard events over taskbar.\n *\n * Results:\n *\tEvent processing.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTaskbarEval(\n    IcoInfo *icoPtr,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    const char *msgstring = \"none\";\n    char evalspace[200];\n    size_t evalsize = 200;\n    char *expanded;\n    int fixup = 0;\n\n    switch (lParam) {\n    case WM_MOUSEMOVE:\n\tmsgstring = \"WM_MOUSEMOVE\";\n\ticoPtr->hwndFocus = GetFocus();\n\tbreak;\n    case WM_LBUTTONDOWN:\n\tmsgstring = \"WM_LBUTTONDOWN\";\n\tfixup = 1;\n\tbreak;\n    case WM_LBUTTONUP:\n\tmsgstring = \"WM_LBUTTONUP\";\n\tfixup = 1;\n\tbreak;\n    case WM_LBUTTONDBLCLK:\n\tmsgstring = \"WM_LBUTTONDBLCLK\";\n\tfixup = 1;\n\tbreak;\n    case WM_RBUTTONDOWN:\n\tmsgstring = \"WM_RBUTTONDOWN\";\n\tfixup = 1;\n\tbreak;\n    case WM_RBUTTONUP:\n\tmsgstring = \"WM_RBUTTONUP\";\n\tfixup = 1;\n\tbreak;\n    case WM_RBUTTONDBLCLK:\n\tmsgstring = \"WM_RBUTTONDBLCLK\";\n\tfixup = 1;\n\tbreak;\n    case WM_MBUTTONDOWN:\n\tmsgstring = \"WM_MBUTTONDOWN\";\n\tfixup = 1;\n\tbreak;\n    case WM_MBUTTONUP:\n\tmsgstring = \"WM_MBUTTONUP\";\n\tfixup = 1;\n\tbreak;\n    case WM_MBUTTONDBLCLK:\n\tmsgstring = \"WM_MBUTTONDBLCLK\";\n\tfixup = 1;\n\tbreak;\n    default:\n\tmsgstring = \"WM_NULL\";\n\tfixup = 0;\n    }\n    expanded = TaskbarExpandPercents(icoPtr, msgstring, wParam, lParam,\n\t    Tcl_GetString(icoPtr->taskbar_command), evalspace, &evalsize);\n    if (icoPtr->interp != NULL) {\n\tint result;\n\tHWND hwnd = NULL;\n\n\t/* See http://support.microsoft.com/kb/q135788/\n\t * Seems to have moved to https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/135788 */\n\tif (fixup) {\n\t    if (icoPtr->hwndFocus != NULL && IsWindow(icoPtr->hwndFocus)) {\n\t\thwnd = icoPtr->hwndFocus;\n\t    } else {\n\t\tTk_Window tkwin = Tk_MainWindow(icoPtr->interp);\n\t\tif (tkwin != NULL) {\n\t\t    hwnd = Tk_GetHWND(Tk_WindowId(tkwin));\n\t\t}\n\t    }\n\t    if (hwnd != NULL) {\n\t\tSetForegroundWindow(hwnd);\n\t    }\n\t}\n\n\tresult = Tcl_GlobalEval(icoPtr->interp, expanded);\n\n\tif (hwnd != NULL) {\n\t    /* See http://support.microsoft.com/kb/q135788/\n\t     * Seems to have moved to https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/135788 */\n\t    PostMessageW(hwnd, WM_NULL, 0, 0);\n\t}\n\tif (result != TCL_OK) {\n\t    char buffer[100];\n\t    snprintf(buffer, 100, \"\\n  (command bound to taskbar-icon ico#%d)\", icoPtr->id);\n\t    Tcl_AddErrorInfo(icoPtr->interp, buffer);\n\t    Tcl_BackgroundError(icoPtr->interp);\n\t}\n    }\n    if (expanded != evalspace) {\n\tTcl_Free(expanded);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TaskbarHandlerProc --\n *\n *\tWindows callback procedure, if ICON_MESSAGE arrives, try to execute\n *\tthe taskbar_command.\n *\n * Results:\n *\tCommand execution.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nTaskbarHandlerProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    static UINT msgTaskbarCreated = 0;\n    IcoInterpInfo *icoInterpPtr;\n    IcoInfo *icoPtr;\n\n    switch (message) {\n    case WM_CREATE:\n\tmsgTaskbarCreated = RegisterWindowMessage(TEXT(\"TaskbarCreated\"));\n\tbreak;\n\n    case ICON_MESSAGE:\n\tfor (icoInterpPtr = firstIcoInterpPtr; icoInterpPtr != NULL; icoInterpPtr = icoInterpPtr->nextPtr) {\n\t    if (icoInterpPtr->hwnd == hwnd) {\n\t\tfor (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {\n\t\t    if (icoPtr->id == (int)wParam) {\n\t\t\tif (icoPtr->taskbar_command != NULL) {\n\t\t\t    TaskbarEval(icoPtr, wParam, lParam);\n\t\t\t}\n\t\t\tbreak;\n\t\t    }\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n\tbreak;\n\n    default:\n\t/*\n\t * Check to see if explorer has been restarted and we need to\n\t * re-add our icons.\n\t */\n\tif (message == msgTaskbarCreated) {\n\t    for (icoInterpPtr = firstIcoInterpPtr; icoInterpPtr != NULL; icoInterpPtr = icoInterpPtr->nextPtr) {\n\t\tif (icoInterpPtr->hwnd == hwnd) {\n\t\t    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {\n\t\t\tif (icoPtr->taskbar_flags & TASKBAR_ICON) {\n\t\t\t    TaskbarOperation(icoInterpPtr, icoPtr, NIM_ADD);\n\t\t\t}\n\t\t    }\n\t\t    break;\n\t\t}\n\t    }\n\t}\n\treturn DefWindowProc(hwnd, message, wParam, lParam);\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RegisterHandlerClass --\n *\n *\tRegisters the handler window class.\n *\n * Results:\n *\tHandler class registered.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nRegisterHandlerClass(\n    HINSTANCE hInstance)\n{\n    WNDCLASS wndclass;\n    memset(&wndclass, 0, sizeof(WNDCLASS));\n    wndclass.style = 0;\n    wndclass.lpfnWndProc = TaskbarHandlerProc;\n    wndclass.cbClsExtra = 0;\n    wndclass.cbWndExtra = 0;\n    wndclass.hInstance = hInstance;\n    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);\n    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);\n    wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);\n    wndclass.lpszMenuName = NULL;\n    wndclass.lpszClassName = HANDLER_CLASS;\n    return RegisterClass(&wndclass);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * CreateTaskbarHandlerWindow --\n *\n *\tCreates a hidden window to handle taskbar messages.\n *\n * Results:\n *\tHidden window created.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HWND\nCreateTaskbarHandlerWindow(void) {\n    static int registered = 0;\n    HINSTANCE hInstance = GETHINSTANCE;\n    if (!registered) {\n\tif (!RegisterHandlerClass(hInstance)) {\n\t    return 0;\n\t}\n\tregistered = 1;\n    }\n    return CreateWindow(HANDLER_CLASS, \"\", WS_OVERLAPPED, 0, 0,\n\t    CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WinIcoDestroy --\n *\n *\tEvent handler to delete systray icons when interp main window\n *\tis deleted, either by destroy, interp deletion or application\n *\texit.\n *\n * Results:\n *\tIcon/window removed and memory freed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nWinIcoDestroy(\n    void *clientData,\n    XEvent *eventPtr)\n{\n    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;\n    IcoInterpInfo *prevIcoInterpPtr;\n    IcoInfo *icoPtr;\n    IcoInfo *nextPtr;\n\n    if (eventPtr->type != DestroyNotify) {\n\treturn;\n    }\n\n    if (firstIcoInterpPtr == icoInterpPtr) {\n\tfirstIcoInterpPtr = icoInterpPtr->nextPtr;\n    } else {\n\tfor (prevIcoInterpPtr = firstIcoInterpPtr; prevIcoInterpPtr->nextPtr != icoInterpPtr;\n\t\tprevIcoInterpPtr = prevIcoInterpPtr->nextPtr) {\n\t    /* Empty loop body. */\n\t}\n\tprevIcoInterpPtr->nextPtr = icoInterpPtr->nextPtr;\n    }\n\n    DestroyWindow(icoInterpPtr->hwnd);\n    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = nextPtr) {\n\t    nextPtr = icoPtr->nextPtr;\n\tFreeIcoPtr(icoInterpPtr, icoPtr);\n    }\n    Tcl_Free(icoInterpPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WinSystrayCmd --\n *\n *\tMain command for creating, displaying, and removing icons from taskbar.\n *\n * Results:\n *\tManagement of icon display in taskbar/system tray.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWinSystrayCmd(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    static const char *const cmdStrings[] = {\n\t\"add\", \"delete\", \"modify\", NULL\n    };\n    enum { CMD_ADD, CMD_DELETE, CMD_MODIFY };\n    static const char *const optStrings[] = {\n\t\"-callback\", \"-image\", \"-text\", NULL\n    };\n    enum { OPT_CALLBACK, OPT_IMAGE, OPT_TEXT };\n    int cmd, opt;\n\n    HICON hIcon;\n    Tcl_Size i;\n    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;\n    IcoInfo *icoPtr = NULL;\n\n    if (objc < 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"command ...\");\n\treturn TCL_ERROR;\n    }\n    if (Tcl_GetIndexFromObj(interp, objv[1], cmdStrings, \"command\",\n\t    0, &cmd) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    switch (cmd) {\n\tcase CMD_ADD:\n\tcase CMD_MODIFY: {\n\t    Tcl_Obj *imageObj = NULL, *textObj = NULL, *callbackObj = NULL;\n\t    int optStart;\n\t    int oper;\n\t    if (cmd == CMD_ADD) {\n\t\toptStart = 2;\n\t\toper = NIM_ADD;\n\t    } else {\n\t\toptStart = 3;\n\t\toper = NIM_MODIFY;\n\t\tif (objc != 5) {\n\t\t    Tcl_WrongNumArgs(interp, 2, objv, \"id option value\");\n\t\t    return TCL_ERROR;\n\t\t}\n\t\ticoPtr = GetIcoPtr(interp, icoInterpPtr, objv[2]);\n\t\tif (icoPtr == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    for (i = optStart; i < objc; i += 2) {\n\t\tif (Tcl_GetIndexFromObj(interp, objv[i], optStrings, \"option\",\n\t\t\t0, &opt) == TCL_ERROR) {\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tif (i+1 >= objc) {\n\t\t    Tcl_AppendResult(interp,\n\t\t\t    \"missing value for option \\\"\", Tcl_GetString(objv[i]),\n\t\t\t    \"\\\"\", (char *)NULL);\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tswitch (opt) {\n\t\t    case OPT_IMAGE:\n\t\t\timageObj = objv[i+1];\n\t\t\tbreak;\n\t\t    case OPT_TEXT:\n\t\t\ttextObj = objv[i+1];\n\t\t\tbreak;\n\t\t    case OPT_CALLBACK:\n\t\t\tcallbackObj = objv[i+1];\n\t\t\tbreak;\n\t\t}\n\t    }\n\t    if (cmd == CMD_ADD && imageObj == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"missing required option \\\"-image\\\"\", TCL_INDEX_NONE));\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (imageObj != NULL) {\n\t\tTk_PhotoHandle photo;\n\t\tint width, height;\n\t\tTk_PhotoImageBlock block;\n\n\t\tphoto = Tk_FindPhoto(interp, Tcl_GetString(imageObj));\n\t\tif (photo == NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"image \\\"%s\\\" does not exist\", Tcl_GetString(imageObj)));\n\t\t    return TCL_ERROR;\n\t\t}\n\t\tTk_PhotoGetSize(photo, &width, &height);\n\t\tTk_PhotoGetImage(photo, &block);\n\t\thIcon = CreateIcoFromPhoto(width, height, block);\n\t\tif (hIcon == NULL) {\n\t\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t    \"failed to create an iconphoto with image \\\"%s\\\"\", Tcl_GetString(imageObj)));\n\t\t    return TCL_ERROR;\n\t\t}\n\t    }\n\t    if (cmd == CMD_ADD) {\n\t\ticoPtr = NewIcon(interp, icoInterpPtr, hIcon);\n\t    } else {\n\t\tif (imageObj != NULL) {\n\t\t    DestroyIcon(icoPtr->hIcon);\n\t\t    icoPtr->hIcon = hIcon;\n\t\t}\n\t    }\n\t    if (callbackObj != NULL) {\n\t\tif (icoPtr->taskbar_command != NULL) {\n\t\t    Tcl_DecrRefCount(icoPtr->taskbar_command);\n\t\t}\n\t\ticoPtr->taskbar_command = callbackObj;\n\t\tTcl_IncrRefCount(icoPtr->taskbar_command);\n\t    }\n\t    if (textObj != NULL) {\n\t\tif (icoPtr->taskbar_txt != NULL) {\n\t\t    Tcl_DecrRefCount(icoPtr->taskbar_txt);\n\t\t}\n\t\ticoPtr->taskbar_txt = textObj;\n\t\tTcl_IncrRefCount(icoPtr->taskbar_txt);\n\t    }\n\t    TaskbarOperation(icoInterpPtr, icoPtr, oper);\n\t    if (cmd == CMD_ADD) {\n\t\tchar buffer[5 + TCL_INTEGER_SPACE];\n\t\tint n;\n\t\tn = snprintf(buffer, sizeof(buffer) - 1, \"ico#%d\", icoPtr->id);\n\t\tbuffer[n] = 0;\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(buffer, n));\n\t    }\n\t    return TCL_OK;\n\t}\n\tcase CMD_DELETE:\n\t    if (objc != 3) {\n\t\tTcl_WrongNumArgs(interp, 2, objv, \"id\");\n\t\treturn TCL_ERROR;\n\t    }\n\t    icoPtr = GetIcoPtr(interp, icoInterpPtr, objv[2]);\n\t    if (icoPtr == NULL) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    FreeIcoPtr(icoInterpPtr, icoPtr);\n\t    return TCL_OK;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WinSysNotifyCmd --\n *\n *\tMain command for creating and displaying notifications/balloons from system tray.\n *\n * Results:\n *\tDisplay of notifications.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWinSysNotifyCmd(\n    void *clientData,\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;\n    IcoInfo *icoPtr;\n\n    if (objc != 5) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"notify id title detail\");\n\treturn TCL_ERROR;\n    }\n    if (strcmp(Tcl_GetString(objv[1]), \"notify\") != 0) {\n\tTcl_AppendResult(interp, \"unknown subcommand \\\"\",\n\t    Tcl_GetString(objv[1]), \"\\\": must be notify\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    icoPtr = GetIcoPtr(interp, icoInterpPtr, objv[2]);\n    if (icoPtr == NULL) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     *  AppUserModelID setup.\n     *  We only set the AppID *once* the first time this routine runs.\n     *  Setting it after the tray icon exists breaks callbacks + image.\n     */\n    static int appidSet = 0;\n    if (!appidSet) {\n\tTk_Window mainWin = Tk_MainWindow(interp);\n\tif (mainWin == NULL) {\n\t    Tcl_AppendResult(interp, \"No main window available\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (Tcl_Eval(interp, \"wm title .\") != TCL_OK) {\n\t    Tcl_AppendResult(interp, \"Failed to obtain window title\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tconst char *titleUtf = Tcl_GetStringResult(interp);\n\tTcl_DString dsTitle;\n\tTcl_DStringInit(&dsTitle);\n\tWCHAR *titleW = Tcl_UtfToWCharDString(titleUtf, TCL_INDEX_NONE, &dsTitle);\n\n\tWCHAR appid[256];\n\tif (titleW[0]) {\n\t    wcsncpy_s(appid, 256, titleW, _TRUNCATE);\n\t} else {\n\t    wcscpy_s(appid, 256, L\"TclApp\");\n\t}\n\tTcl_DStringFree(&dsTitle);\n\n\t/* Sanitize the title string. appID cannot support spaces. */\n\tfor (WCHAR *p = appid; *p; p++) {\n\t    if (*p == L' ' || *p == L'\\t')\n\t\t*p = L'_';\n\t}\n\n\tSetCurrentProcessExplicitAppUserModelID(appid);\n\tappidSet = 1;\n    }\n\n    /*\n     * Send the notification balloon.   DO NOT touch uCallbackMessage\n     * or NIF_MESSAGE - keep callbacks alive. Display\n     * the system tray icon with the NIIF_USER flag - it will\n     * display in the body of the notification window but NOT\n     * the titlebar. This is a limitation of this API when customizing\n     * the titlebar string with AppUserModelID.\n     */\n\n    NOTIFYICONDATAW ni;\n    ZeroMemory(&ni, sizeof(ni));\n    ni.cbSize = sizeof(ni);\n    ni.hWnd  = icoInterpPtr->hwnd;\n    ni.uID   = icoPtr->id;\n    ni.uFlags = NIF_INFO;\n    ni.dwInfoFlags = NIIF_USER;\n\n    Tcl_DString ds;\n    Tcl_DStringInit(&ds);\n\n    WCHAR *wtitle = Tcl_UtfToWCharDString(Tcl_GetString(objv[3]), TCL_INDEX_NONE, &ds);\n    wcsncpy_s(ni.szInfoTitle, ARRAYSIZE(ni.szInfoTitle), wtitle, _TRUNCATE);\n    Tcl_DStringSetLength(&ds, 0);\n\n    WCHAR *wtext = Tcl_UtfToWCharDString(Tcl_GetString(objv[4]), TCL_INDEX_NONE, &ds);\n    wcsncpy_s(ni.szInfo, ARRAYSIZE(ni.szInfo), wtext, _TRUNCATE);\n    Tcl_DStringFree(&ds);\n\n    ni.uVersion = NOTIFYICON_VERSION_4;\n\n    if (!Shell_NotifyIconW(NIM_MODIFY, &ni)) {\n\tchar buf[64];\n\tsprintf_s(buf, sizeof(buf),\n\t\t  \"Notification failed (error %lu)\",\n\t\t  GetLastError());\n\tTcl_AppendResult(interp, buf, (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    return TCL_OK;\n}\n\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WinIcoInit --\n *\n *\tInitialize this package and create script-level commands.\n *\n * Results:\n *\tInitialization of code.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nWinIcoInit(\n    Tcl_Interp *interp)\n{\n    IcoInterpInfo *icoInterpPtr;\n    Tk_Window mainWindow;\n\n    mainWindow = Tk_MainWindow(interp);\n    if (mainWindow == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"main window has been destroyed\", TCL_INDEX_NONE));\n\treturn TCL_ERROR;\n    }\n\n    icoInterpPtr = (IcoInterpInfo*)Tcl_Alloc(sizeof(IcoInterpInfo));\n    icoInterpPtr->counter = 0;\n    icoInterpPtr->firstIcoPtr = NULL;\n    icoInterpPtr->hwnd = CreateTaskbarHandlerWindow();\n    icoInterpPtr->nextPtr = firstIcoInterpPtr;\n    firstIcoInterpPtr = icoInterpPtr;\n    Tcl_CreateObjCommand2(interp, \"::tk::systray::_systray\", WinSystrayCmd,\n\t    icoInterpPtr, NULL);\n    Tcl_CreateObjCommand2(interp, \"::tk::sysnotify::_sysnotify\", WinSysNotifyCmd,\n\t    icoInterpPtr, NULL);\n\t/*\n\t* This command is defined in tkWinIco.c, but that file does not have\n\t* any hooks for script command creation.\n\t*/\n\tTcl_CreateObjCommand(interp, \"::tk:::fileicon::_getwinicon\", GetFileIcon,\n\t    NULL, NULL);\n\n    Tk_CreateEventHandler(mainWindow, StructureNotifyMask,\n\t    WinIcoDestroy, icoInterpPtr);\n\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinTest.c",
    "content": "/*\n * tkWinTest.c --\n *\n *\tContains commands for platform specific tests for the Windows\n *\tplatform.\n *\n * Copyright © 1997 Sun Microsystems, Inc.\n * Copyright © 2000 Scriptics Corporation.\n * Copyright © 2001 ActiveState Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#undef USE_TCL_STUBS\n#define USE_TCL_STUBS\n#undef USE_TK_STUBS\n#define USE_TK_STUBS\n#include \"tkWinInt.h\"\n#undef TCLBOOLWARNING\n#define TCLBOOLWARNING(boolPtr) /* needed here because we compile with -Wc++-compat */\n\nHWND tkWinCurrentDialog;\n\n/*\n * Forward declarations of functions defined later in this file:\n */\n\nstatic Tcl_ObjCmdProc2 TestclipboardObjCmd;\nstatic Tcl_ObjCmdProc2 TestwineventObjCmd;\nstatic Tcl_ObjCmdProc2 TestfindwindowObjCmd;\nstatic Tcl_ObjCmdProc2 TestgetwindowinfoObjCmd;\nstatic Tcl_ObjCmdProc2 TestwinlocaleObjCmd;\nstatic Tk_GetSelProc SetSelectionResult;\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkplatformtestInit --\n *\n *\tDefines commands that test platform specific functionality for Windows\n *\tplatforms.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tDefines new commands.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkplatformtestInit(\n    Tcl_Interp *interp)\t\t/* Interpreter to add commands to. */\n{\n    /*\n     * Add commands for platform specific tests on MacOS here.\n     */\n\n    Tcl_CreateObjCommand2(interp, \"testclipboard\", TestclipboardObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testwinevent\", TestwineventObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testfindwindow\", TestfindwindowObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testgetwindowinfo\", TestgetwindowinfoObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    Tcl_CreateObjCommand2(interp, \"testwinlocale\", TestwinlocaleObjCmd,\n\t    Tk_MainWindow(interp), NULL);\n    return TCL_OK;\n}\n\f\nstruct TestFindControlState {\n    int  id;\n    HWND control;\n};\n\n/* Callback for window enumeration - used for TestFindControl */\nBOOL CALLBACK TestFindControlCallback(\n    HWND hwnd,\n    LPARAM lParam\n)\n{\n    struct TestFindControlState *fcsPtr = (struct TestFindControlState *)lParam;\n    fcsPtr->control = GetDlgItem(hwnd, fcsPtr->id);\n    /* If we have found the control, return FALSE to stop the enumeration */\n    return fcsPtr->control == NULL ? TRUE : FALSE;\n}\n\n/*\n * Finds the descendent control window with the specified ID and returns\n * its HWND.\n */\nHWND TestFindControl(HWND root, int id)\n{\n    struct TestFindControlState fcs;\n\n    fcs.control = GetDlgItem(root, id);\n    if (fcs.control == NULL) {\n\t/* Control is not a direct child. Look in descendents */\n\tfcs.id = id;\n\tfcs.control = NULL;\n\tEnumChildWindows(root, TestFindControlCallback, (LPARAM) &fcs);\n    }\n    return fcs.control;\n}\n\n\f\n/*\n *----------------------------------------------------------------------\n *\n * AppendSystemError --\n *\n *\tThis routine formats a Windows system error message and places it into\n *\tthe interpreter result. Originally from tclWinReg.c.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nAppendSystemError(\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    DWORD error)\t\t/* Result code from error. */\n{\n    Tcl_Size length;\n    WCHAR *wMsgPtr, **wMsgPtrPtr = &wMsgPtr;\n    const char *msg;\n    char id[TCL_INTEGER_SPACE], msgBuf[24 + TCL_INTEGER_SPACE];\n    Tcl_DString ds;\n    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);\n\n    if (Tcl_IsShared(resultPtr)) {\n\tresultPtr = Tcl_DuplicateObj(resultPtr);\n    }\n    length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM\n\t    | FORMAT_MESSAGE_IGNORE_INSERTS\n\t    | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,\n\t    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) wMsgPtrPtr,\n\t    0, NULL);\n    if (length == 0) {\n\tchar *msgPtr;\n\n\tlength = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM\n\t\t| FORMAT_MESSAGE_IGNORE_INSERTS\n\t\t| FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,\n\t\tMAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &msgPtr,\n\t\t0, NULL);\n\tif (length > 0) {\n\t    wMsgPtr = (WCHAR *) LocalAlloc(LPTR, (length + 1) * sizeof(WCHAR));\n\t    MultiByteToWideChar(CP_ACP, 0, msgPtr, (int)length + 1, wMsgPtr,\n\t\t    (int)length + 1);\n\t    LocalFree(msgPtr);\n\t}\n    }\n    if (length == 0) {\n\tif (error == ERROR_CALL_NOT_IMPLEMENTED) {\n\t    strcpy(msgBuf, \"function not supported under Win32s\");\n\t} else {\n\t    snprintf(msgBuf, sizeof(msgBuf), \"unknown error: %ld\", error);\n\t}\n\tmsg = msgBuf;\n    } else {\n\tchar *msgPtr;\n\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString(wMsgPtr, wcslen(wMsgPtr), &ds);\n\tLocalFree(wMsgPtr);\n\n\tmsgPtr = Tcl_DStringValue(&ds);\n\tlength = Tcl_DStringLength(&ds);\n\n\t/*\n\t * Trim the trailing CR/LF from the system message.\n\t */\n\n\tif (msgPtr[length-1] == '\\n') {\n\t    --length;\n\t}\n\tif (msgPtr[length-1] == '\\r') {\n\t    --length;\n\t}\n\tmsgPtr[length] = 0;\n\tmsg = msgPtr;\n    }\n\n    snprintf(id, sizeof(id), \"%ld\", error);\n    Tcl_SetErrorCode(interp, \"WINDOWS\", id, msg, (char *)NULL);\n    Tcl_AppendToObj(resultPtr, msg, length);\n    Tcl_SetObjResult(interp, resultPtr);\n\n    if (length != 0) {\n\tTcl_DStringFree(&ds);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestclipboardObjCmd --\n *\n *\tThis function implements the testclipboard command. It provides a way\n *\tto determine the actual contents of the Windows clipboard.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nSetSelectionResult(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    const char *selection)\n{\n    Tcl_AppendResult(interp, selection, NULL);\n    return TCL_OK;\n}\n\nstatic int\nTestclipboardObjCmd(\n    void *clientData,\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n\n    if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    return TkSelGetSelection(interp, tkwin, Tk_InternAtom(tkwin, \"CLIPBOARD\"),\n\t    XA_STRING, SetSelectionResult, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TestwineventObjCmd --\n *\n *\tThis function implements the testwinevent command. It provides a way\n *\tto send messages to windows dialogs.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nTestwineventObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t\t/* Argument strings. */\n{\n    HWND hwnd = 0;\n    HWND child = 0;\n    HWND control;\n    int id;\n    char *rest;\n    UINT message;\n    WPARAM wParam;\n    LPARAM lParam;\n    LRESULT result;\n    static const TkStateMap messageMap[] = {\n\t{WM_LBUTTONDOWN,\t\"WM_LBUTTONDOWN\"},\n\t{WM_LBUTTONUP,\t\t\"WM_LBUTTONUP\"},\n\t{WM_LBUTTONDBLCLK,\t\t\"WM_LBUTTONDBLCLK\"},\n\t{WM_MBUTTONDOWN,\t\"WM_MBUTTONDOWN\"},\n\t{WM_MBUTTONUP,\t\t\"WM_MBUTTONUP\"},\n\t{WM_MBUTTONDBLCLK,\t\t\"WM_MBUTTONDBLCLK\"},\n\t{WM_RBUTTONDOWN,\t\"WM_RBUTTONDOWN\"},\n\t{WM_RBUTTONUP,\t\t\"WM_RBUTTONUP\"},\n\t{WM_RBUTTONDBLCLK,\t\t\"WM_RBUTTONDBLCLK\"},\n\t{WM_XBUTTONDOWN,\t\"WM_XBUTTONDOWN\"},\n\t{WM_XBUTTONUP,\t\t\"WM_XBUTTONUP\"},\n\t{WM_XBUTTONDBLCLK,\t\t\"WM_XBUTTONDBLCLK\"},\n\t{WM_CHAR,\t\t\"WM_CHAR\"},\n\t{WM_GETTEXT,\t\t\"WM_GETTEXT\"},\n\t{WM_SETTEXT,\t\t\"WM_SETTEXT\"},\n\t{WM_COMMAND,            \"WM_COMMAND\"},\n\t{-1,\t\t\tNULL}\n    };\n\n    if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), \"debug\") == 0)) {\n\tint b;\n\n\tif (Tcl_GetBooleanFromObj(interp, objv[2], &b) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTkWinDialogDebug(b);\n\treturn TCL_OK;\n    }\n\n    if (objc < 4) {\n\treturn TCL_ERROR;\n    }\n\n    hwnd = (HWND)INT2PTR(strtol(Tcl_GetString(objv[1]), &rest, 0));\n    if (rest == Tcl_GetString(objv[1])) {\n\thwnd = FindWindowA(NULL, Tcl_GetString(objv[1]));\n\tif (hwnd == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"no such window\", TCL_INDEX_NONE));\n\t    return TCL_ERROR;\n\t}\n    }\n    UpdateWindow(hwnd);\n\n    id = strtol(Tcl_GetString(objv[2]), &rest, 0);\n    if (rest == Tcl_GetString(objv[2])) {\n\tchar buf[256];\n\n\tchild = GetWindow(hwnd, GW_CHILD);\n\twhile (child != NULL) {\n\t    SendMessageA(child, WM_GETTEXT, (WPARAM) sizeof(buf), (LPARAM) buf);\n\t    if (strcasecmp(buf, Tcl_GetString(objv[2])) == 0) {\n\t\tid = GetDlgCtrlID(child);\n\t\tbreak;\n\t    }\n\t    child = GetWindow(child, GW_HWNDNEXT);\n\t}\n\tif (child == NULL) {\n\t    Tcl_AppendResult(interp, \"could not find a control matching \\\"\",\n\t\tTcl_GetString(objv[2]), \"\\\"\", NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3]));\n    wParam = 0;\n    lParam = 0;\n\n    if (objc > 4) {\n\twParam = strtol(Tcl_GetString(objv[4]), NULL, 0);\n    }\n    if (objc > 5) {\n\tlParam = strtol(Tcl_GetString(objv[5]), NULL, 0);\n    }\n\n    switch (message) {\n    case WM_GETTEXT: {\n\tTcl_DString ds;\n\tchar buf[256];\n\n#if 0\n\tGetDlgItemTextA(hwnd, id, buf, 256);\n#else\n\tcontrol = TestFindControl(hwnd, id);\n\tif (control == NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t\t     Tcl_ObjPrintf(\"Could not find control with id %d\", id));\n\t    return TCL_ERROR;\n\t}\n\tbuf[0] = 0;\n\tSendMessageA(control, WM_GETTEXT, (WPARAM)sizeof(buf),\n\t\t     (LPARAM) buf);\n#endif\n\tTcl_AppendResult(interp, Tcl_ExternalToUtfDString(NULL, buf, TCL_INDEX_NONE, &ds), NULL);\n\tTcl_DStringFree(&ds);\n\tbreak;\n    }\n    case WM_SETTEXT: {\n\tTcl_DString ds;\n\n\tcontrol = TestFindControl(hwnd, id);\n\tif (control == NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_ObjPrintf(\"Could not find control with id %d\", id));\n\t    return TCL_ERROR;\n\t}\n\tTcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), TCL_INDEX_NONE, &ds);\n\tresult = SendMessageA(control, WM_SETTEXT, 0, (LPARAM)Tcl_DStringValue(&ds));\n\tTcl_DStringFree(&ds);\n\tif (result == 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\"failed to send text to dialog: \", TCL_INDEX_NONE));\n\t    AppendSystemError(interp, GetLastError());\n\t    return TCL_ERROR;\n\t}\n\tbreak;\n    }\n    case WM_COMMAND: {\n\tchar buf[TCL_INTEGER_SPACE];\n\tif (objc < 5) {\n\t    wParam = MAKEWPARAM(id, 0);\n\t    lParam = (LPARAM)child;\n\t}\n\tsnprintf(buf, sizeof(buf), \"%d\", (int) SendMessageA(hwnd, message, wParam, lParam));\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n\tbreak;\n    }\n    default: {\n\tchar buf[TCL_INTEGER_SPACE];\n\n\tsnprintf(buf, sizeof(buf), \"%d\",\n\t\t(int) SendDlgItemMessageA(hwnd, id, message, wParam, lParam));\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n\tbreak;\n    }\n    }\n    return TCL_OK;\n}\n\f\n/*\n *  testfindwindow title ?class?\n *\tFind a Windows window using the FindWindow API call. This takes the window\n *\ttitle and optionally the window class and if found returns the HWND and\n *\traises an error if the window is not found.\n *\teg: testfindwindow Console TkTopLevel\n *\t    Can find the console window if it is visible.\n *\teg: testfindwindow \"TkTest #10201\" \"#32770\"\n *\t    Can find a messagebox window with this title.\n */\n\nstatic int\nTestfindwindowObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    LPCWSTR title = NULL, windowClass = NULL;\n    Tcl_DString titleString, classString;\n    HWND hwnd = NULL;\n    int r = TCL_OK;\n    DWORD myPid;\n\n    Tcl_DStringInit(&classString);\n    Tcl_DStringInit(&titleString);\n\n    if (objc < 2 || objc > 3) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"title ?class?\");\n\treturn TCL_ERROR;\n    }\n\n    Tcl_DStringInit(&titleString);\n    title = Tcl_UtfToWCharDString(Tcl_GetString(objv[1]), TCL_INDEX_NONE, &titleString);\n    if (objc == 3) {\n\tTcl_DStringInit(&classString);\n\twindowClass = Tcl_UtfToWCharDString(Tcl_GetString(objv[2]), TCL_INDEX_NONE, &classString);\n    }\n    if (title[0] == 0) {\n\ttitle = NULL;\n    }\n    /* We want find a window the belongs to us and not some other process */\n    hwnd = NULL;\n    myPid = GetCurrentProcessId();\n    while (1) {\n\tDWORD pid, tid;\n\thwnd = FindWindowExW(NULL, hwnd, windowClass, title);\n\tif (hwnd == NULL) {\n\t    break;\n\t}\n\ttid = GetWindowThreadProcessId(hwnd, &pid);\n\tif (tid == 0) {\n\t    /* Window has gone */\n\t    hwnd = NULL;\n\t    break;\n\t}\n\tif (pid == myPid) {\n\t    break;              /* Found it */\n\t}\n    }\n\n    if (hwnd == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"failed to find window: \", TCL_INDEX_NONE));\n\tAppendSystemError(interp, GetLastError());\n\tr = TCL_ERROR;\n    } else {\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(PTR2INT(hwnd)));\n    }\n\n    Tcl_DStringFree(&titleString);\n    Tcl_DStringFree(&classString);\n    return r;\n\n}\n\f\nstatic BOOL CALLBACK\nEnumChildrenProc(\n    HWND hwnd,\n    LPARAM lParam)\n{\n    Tcl_Obj *listObj = (Tcl_Obj *) lParam;\n\n    Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewWideIntObj(PTR2INT(hwnd)));\n    return TRUE;\n}\n\nstatic int\nTestgetwindowinfoObjCmd(\n    TCL_UNUSED(void *),\n    Tcl_Interp *interp,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    Tcl_WideInt hwnd;\n    Tcl_Obj *dictObj = NULL, *classObj = NULL, *textObj = NULL;\n    Tcl_Obj *childrenObj = NULL;\n    WCHAR buf[512];\n    int cch, cchBuf = 256;\n    Tcl_DString ds;\n\n    if (objc != 2) {\n\tTcl_WrongNumArgs(interp, 1, objv, \"hwnd\");\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetWideIntFromObj(interp, objv[1], &hwnd) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    cch = GetClassNameW((HWND)INT2PTR(hwnd), buf, cchBuf);\n    if (cch == 0) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"failed to get class name: \", TCL_INDEX_NONE));\n\tAppendSystemError(interp, GetLastError());\n\treturn TCL_ERROR;\n    } else {\n\tTcl_DStringInit(&ds);\n\tTcl_WCharToUtfDString(buf, wcslen(buf), &ds);\n\tclassObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n\tTcl_DStringFree(&ds);\n    }\n\n    dictObj = Tcl_NewDictObj();\n    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj(\"class\", 5), classObj);\n    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj(\"id\", 2),\n\t    Tcl_NewWideIntObj(GetWindowLongPtr((HWND)(size_t)hwnd, GWL_ID)));\n\n    cch = GetWindowTextW((HWND)INT2PTR(hwnd), buf, cchBuf);\n\tTcl_DStringInit(&ds);\n    Tcl_WCharToUtfDString(buf, cch, &ds);\n    textObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));\n    Tcl_DStringFree(&ds);\n\n    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj(\"text\", 4), textObj);\n    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj(\"parent\", 6),\n\t    Tcl_NewWideIntObj(PTR2INT(GetParent((HWND)(size_t)hwnd))));\n\n    childrenObj = Tcl_NewListObj(0, NULL);\n    EnumChildWindows((HWND)(size_t)hwnd, EnumChildrenProc, (LPARAM)childrenObj);\n    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj(\"children\", TCL_INDEX_NONE), childrenObj);\n\n    Tcl_SetObjResult(interp, dictObj);\n    return TCL_OK;\n}\n\f\nstatic int\nTestwinlocaleObjCmd(\n    TCL_UNUSED(void *),\t/* Main window for application. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument values. */\n{\n    if (objc != 1) {\n\tTcl_WrongNumArgs(interp, 1, objv, NULL);\n\treturn TCL_ERROR;\n    }\n    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetThreadLocale()));\n    return TCL_OK;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinWindow.c",
    "content": "/*\n * tkWinWindow.c --\n *\n *\tXlib emulation routines for Windows related to creating, displaying\n *\tand destroying windows.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include \"tkBusy.h\"\n\ntypedef struct {\n    bool initialized;\t\t/* false means table below needs initializing. */\n    Tcl_HashTable windowTable;  /* The windowTable maps from HWND to Tk_Window\n\t\t\t\t * handles. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic void\t\tNotifyVisibility(XEvent *eventPtr, TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_AttachHWND --\n *\n *\tThis function binds an HWND and a reflection function to the specified\n *\tTk_Window.\n *\n * Results:\n *\tReturns an X Window that encapsulates the HWND.\n *\n * Side effects:\n *\tMay allocate a new X Window. Also enters the HWND into the global\n *\twindow table.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTk_AttachHWND(\n    Tk_Window tkwin,\n    HWND hwnd)\n{\n    int isNew;\n    Tcl_HashEntry *entryPtr;\n    TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin);\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\tTcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);\n\ttsdPtr->initialized = true;\n    }\n\n    /*\n     * Allocate a new drawable if necessary. Otherwise, remove the previous\n     * HWND from from the window table.\n     */\n\n    if (twdPtr == NULL) {\n\ttwdPtr = (TkWinDrawable *)Tcl_Alloc(sizeof(TkWinDrawable));\n\ttwdPtr->type = TWD_WINDOW;\n\ttwdPtr->window.winPtr = (TkWindow *) tkwin;\n    } else if (twdPtr->window.handle != NULL) {\n\tentryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable,\n\t\ttwdPtr->window.handle);\n\tTcl_DeleteHashEntry(entryPtr);\n    }\n\n    /*\n     * Insert the new HWND into the window table.\n     */\n\n    twdPtr->window.handle = hwnd;\n    entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &isNew);\n    Tcl_SetHashValue(entryPtr, tkwin);\n\n    return (Window)twdPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_HWNDToWindow --\n *\n *\tThis function retrieves a Tk_Window from the window table given an\n *\tHWND.\n *\n * Results:\n *\tReturns the matching Tk_Window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_HWNDToWindow(\n    HWND hwnd)\n{\n    Tcl_HashEntry *entryPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\tTcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);\n\ttsdPtr->initialized = true;\n    }\n    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd);\n    if (entryPtr != NULL) {\n\treturn (Tk_Window) Tcl_GetHashValue(entryPtr);\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetHWND --\n *\n *\tThis function extracts the HWND from an X Window.\n *\n * Results:\n *\tReturns the HWND associated with the Window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHWND\nTk_GetHWND(\n    Window window)\n{\n    return ((TkWinDrawable *) window)->window.handle;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpPrintWindowId --\n *\n *\tThis routine stores the string representation of the platform\n *\tdependent window handle for an X Window in the given buffer.\n *\n * Results:\n *\tReturns the result in the specified buffer.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpPrintWindowId(\n    char *buf,\t\t\t/* Pointer to string large enough to hold the\n\t\t\t\t * hex representation of a pointer. */\n    Window window)\t\t/* Window to be printed into buffer. */\n{\n    HWND hwnd = (window) ? Tk_GetHWND(window) : 0;\n\n    snprintf(buf, TCL_INTEGER_SPACE, \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)hwnd);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpScanWindowId --\n *\n *\tGiven a string which represents the platform dependent window handle,\n *\tproduce the X Window id for the window.\n *\n * Results:\n *\tThe return value is normally TCL_OK; in this case *idPtr will be set\n *\tto the X Window id equivalent to string. If string is improperly\n *\tformed then TCL_ERROR is returned and an error message will be left in\n *\tthe interp's result. If the number does not correspond to a Tk Window,\n *\tthen *idPtr will be set to None.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpScanWindowId(\n    Tcl_Interp *interp,\t\t/* Interpreter to use for error reporting. */\n    const char *string,\t\t/* String containing a (possibly signed)\n\t\t\t\t * integer in a form acceptable to strtol. */\n    Window *idPtr)\t\t/* Place to store converted result. */\n{\n    Tk_Window tkwin;\n    union {\n\tHWND hwnd;\n\tint number;\n    } win;\n\n    /*\n     * We want sscanf for the 64-bit check, but if that doesn't work, then\n     * Tcl_GetInt manages the error correctly.\n     */\n\n    if (\n#ifdef _WIN64\n\t    (sscanf(string, \"0x%p\", &win.hwnd) != 1) &&\n#endif\n\t    Tcl_GetInt(interp, string, &win.number) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    tkwin = Tk_HWNDToWindow(win.hwnd);\n    if (tkwin) {\n\t*idPtr = Tk_WindowId(tkwin);\n    } else {\n\t*idPtr = None;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MakeWindow --\n *\n *\tCreates a Windows window object based on the current attributes of the\n *\tspecified TkWindow.\n *\n * Results:\n *\tReturns a pointer to a new TkWinDrawable cast to a Window.\n *\n * Side effects:\n *\tCreates a new window.\n *\n *----------------------------------------------------------------------\n */\n\nWindow\nTk_MakeWindow(\n    Tk_Window tkwin,\n    Window parent)\n{\n    HWND parentWin;\n    int style;\n    HWND hwnd;\n    TkWindow *winPtr = (TkWindow *)tkwin;\n\n    if (parent != None) {\n\tparentWin = Tk_GetHWND(parent);\n\tstyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;\n    } else {\n\tparentWin = NULL;\n\tstyle = WS_POPUP | WS_CLIPCHILDREN;\n    }\n\n    /*\n     * Create the window, then ensure that it is at the top of the stacking\n     * order.\n     */\n\n    hwnd = CreateWindowExW(WS_EX_NOPARENTNOTIFY, TK_WIN_CHILD_CLASS_NAME, NULL,\n\t    (DWORD) style, Tk_X(winPtr), Tk_Y(winPtr), Tk_Width(winPtr),\n\t    Tk_Height(winPtr), parentWin, NULL, Tk_GetHINSTANCE(), NULL);\n    SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\n\t    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n    return Tk_AttachHWND((Tk_Window)winPtr, hwnd);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDestroyWindow --\n *\n *\tDestroys the given window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSends the WM_DESTROY message to the window and then destroys it the\n *\tWin32 resources associated with the window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDestroyWindow(\n    Display *display,\n    Window w)\n{\n    Tcl_HashEntry *entryPtr;\n    TkWinDrawable *twdPtr = (TkWinDrawable *)w;\n    TkWindow *winPtr = TkWinGetWinPtr(w);\n    HWND hwnd = Tk_GetHWND(w);\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    LastKnownRequestProcessed(display)++;\n\n    /*\n     * Remove references to the window in the pointer module then release the\n     * drawable.\n     */\n\n    TkPointerDeadWindow(winPtr);\n\n    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd);\n    if (entryPtr != NULL) {\n\tTcl_DeleteHashEntry(entryPtr);\n    }\n\n    Tcl_Free(twdPtr);\n\n    /*\n     * Don't bother destroying the window if we are going to destroy the\n     * parent later.\n     */\n\n    if (hwnd != NULL && !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {\n\tDestroyWindow(hwnd);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMapWindow --\n *\n *\tCause the given window to become visible.\n *\n * Results:\n *\tAlways returns Success or BadWindow.\n *\n * Side effects:\n *\tCauses the window state to change, and generates a MapNotify event.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMapWindow(\n    Display *display,\n    Window w)\n{\n    XEvent event;\n    TkWindow *parentPtr;\n    TkWindow *winPtr;\n\n    if (!w) {\n\treturn BadWindow;\n    }\n    winPtr = TkWinGetWinPtr(w);\n    LastKnownRequestProcessed(display)++;\n\n    ShowWindow(Tk_GetHWND(w), SW_SHOWNORMAL);\n    winPtr->flags |= TK_MAPPED;\n\n    /*\n     * Check to see if this window is visible now. If all of the parent\n     * windows up to the first toplevel are mapped, then this window and its\n     * mapped children have just become visible.\n     */\n\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\tfor (parentPtr = winPtr->parentPtr; ;\n\t\tparentPtr = parentPtr->parentPtr) {\n\t    if ((parentPtr == NULL) || !(parentPtr->flags & TK_MAPPED)) {\n\t\treturn Success;\n\t    }\n\t    if (parentPtr->flags & TK_TOP_HIERARCHY) {\n\t\tbreak;\n\t    }\n\t}\n    } else {\n\tevent.type = MapNotify;\n\tevent.xmap.serial = LastKnownRequestProcessed(display);\n\tevent.xmap.send_event = False;\n\tevent.xmap.display = display;\n\tevent.xmap.event = winPtr->window;\n\tevent.xmap.window = winPtr->window;\n\tevent.xmap.override_redirect = winPtr->atts.override_redirect;\n\tTk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n    }\n\n    /*\n     * Generate VisibilityNotify events for this window and its mapped\n     * children.\n     */\n\n    event.type = VisibilityNotify;\n    event.xvisibility.serial = LastKnownRequestProcessed(display);\n    event.xvisibility.send_event = False;\n    event.xvisibility.display = display;\n    event.xvisibility.window = winPtr->window;\n    event.xvisibility.state = VisibilityUnobscured;\n    NotifyVisibility(&event, winPtr);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * NotifyVisibility --\n *\n *\tThis function recursively notifies the mapped children of the\n *\tspecified window of a change in visibility. Note that we don't\n *\tproperly report the visibility state, since Windows does not provide\n *\tthat info. The eventPtr argument must point to an event that has been\n *\tcompletely initialized except for the window slot.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates lots of events.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nNotifyVisibility(\n    XEvent *eventPtr,\t\t/* Initialized VisibilityNotify event. */\n    TkWindow *winPtr)\t\t/* Window to notify. */\n{\n    if (winPtr->atts.event_mask & VisibilityChangeMask) {\n\teventPtr->xvisibility.window = winPtr->window;\n\tTk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);\n    }\n    for (winPtr = winPtr->childList; winPtr != NULL;\n\t    winPtr = winPtr->nextPtr) {\n\tif (winPtr->flags & TK_MAPPED) {\n\t    NotifyVisibility(eventPtr, winPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XUnmapWindow --\n *\n *\tCause the given window to become invisible.\n *\n * Results:\n *\tAlways returns Success or BadWindow.\n *\n * Side effects:\n *\tCauses the window state to change, and generates an UnmapNotify event.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXUnmapWindow(\n    Display *display,\n    Window w)\n{\n    XEvent event;\n    TkWindow *winPtr;\n\n    if (!w) {\n\treturn BadWindow;\n    }\n    winPtr = TkWinGetWinPtr(w);\n    LastKnownRequestProcessed(display)++;\n\n    /*\n     * Bug fix: Don't short circuit this routine based on TK_MAPPED because it\n     * will be cleared before XUnmapWindow is called.\n     */\n\n    ShowWindow(Tk_GetHWND(w), SW_HIDE);\n    winPtr->flags &= ~TK_MAPPED;\n\n    if (winPtr->flags & TK_WIN_MANAGED) {\n\tevent.type = UnmapNotify;\n\tevent.xunmap.serial = LastKnownRequestProcessed(display);\n\tevent.xunmap.send_event = False;\n\tevent.xunmap.display = display;\n\tevent.xunmap.event = winPtr->window;\n\tevent.xunmap.window = winPtr->window;\n\tevent.xunmap.from_configure = False;\n\tTk_HandleEvent(&event);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMoveResizeWindow --\n *\n *\tMove and resize a window relative to its parent.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRepositions and resizes the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMoveResizeWindow(\n    Display *display,\n    Window w,\n    int x, int y,\t\t/* Position relative to parent. */\n    unsigned int width, unsigned int height)\n{\n    LastKnownRequestProcessed(display)++;\n    MoveWindow(Tk_GetHWND(w), x, y, (int) width, (int) height, TRUE);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XMoveWindow --\n *\n *\tMove a window relative to its parent.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRepositions the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXMoveWindow(\n    Display *display,\n    Window w,\n    int x, int y)\t\t/* Position relative to parent */\n{\n    TkWindow *winPtr = TkWinGetWinPtr(w);\n\n    LastKnownRequestProcessed(display)++;\n\n    MoveWindow(Tk_GetHWND(w), x, y, winPtr->changes.width,\n\t    winPtr->changes.height, TRUE);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XResizeWindow --\n *\n *\tResize a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResizes the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXResizeWindow(\n    Display *display,\n    Window w,\n    unsigned int width, unsigned int height)\n{\n    TkWindow *winPtr = TkWinGetWinPtr(w);\n\n    LastKnownRequestProcessed(display)++;\n\n    MoveWindow(Tk_GetHWND(w), winPtr->changes.x, winPtr->changes.y, (int)width,\n\t    (int)height, TRUE);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XRaiseWindow, XLowerWindow --\n *\n *\tChange the stacking order of a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the stacking order of the specified window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXRaiseWindow(\n    Display *display,\n    Window w)\n{\n    HWND window = Tk_GetHWND(w);\n\n    LastKnownRequestProcessed(display)++;\n    SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\n    return Success;\n}\n\nint\nXLowerWindow(\n    Display *display,\n    Window w)\n{\n    HWND window = Tk_GetHWND(w);\n\n    LastKnownRequestProcessed(display)++;\n    SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XConfigureWindow --\n *\n *\tChange the size, position, stacking, or border of the specified\n *\twindow.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the attributes of the specified window. Note that we ignore\n *\tthe passed in values and use the values stored in the TkWindow data\n *\tstructure.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXConfigureWindow(\n    Display *display,\n    Window w,\n    unsigned int valueMask,\n    XWindowChanges *values)\n{\n    TkWindow *winPtr = TkWinGetWinPtr(w);\n    HWND hwnd = Tk_GetHWND(w);\n\n    LastKnownRequestProcessed(display)++;\n\n    /*\n     * Change the shape and/or position of the window.\n     */\n\n    if (valueMask & (CWX|CWY|CWWidth|CWHeight)) {\n\tMoveWindow(hwnd, winPtr->changes.x, winPtr->changes.y,\n\t\twinPtr->changes.width, winPtr->changes.height, TRUE);\n    }\n\n    /*\n     * Change the stacking order of the window.\n     */\n\n    if (valueMask & CWStackMode) {\n\tHWND sibling;\n\n\tif ((valueMask & CWSibling) && (values->sibling != None)) {\n\t    sibling = Tk_GetHWND(values->sibling);\n\t} else {\n\t    sibling = NULL;\n\t}\n\tTkWinSetWindowPos(hwnd, sibling, values->stack_mode);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XClearWindow --\n *\n *\tClears the entire window to the current background color.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tErases the current contents of the window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXClearWindow(\n    Display *display,\n    Window w)\n{\n    RECT rc;\n    HBRUSH brush;\n    HPALETTE oldPalette, palette;\n    TkWindow *winPtr;\n    HWND hwnd = Tk_GetHWND(w);\n    HDC dc = GetDC(hwnd);\n\n    palette = TkWinGetPalette(DefaultColormapOfScreen(ScreenOfDisplay(display, 0)));\n    oldPalette = SelectPalette(dc, palette, FALSE);\n\n    LastKnownRequestProcessed(display)++;\n\n    winPtr = TkWinGetWinPtr(w);\n    brush = CreateSolidBrush(winPtr->atts.background_pixel);\n    GetWindowRect(hwnd, &rc);\n    rc.right = rc.right - rc.left;\n    rc.bottom = rc.bottom - rc.top;\n    rc.left = rc.top = 0;\n    FillRect(dc, &rc, brush);\n\n    DeleteObject(brush);\n    SelectPalette(dc, oldPalette, TRUE);\n    ReleaseDC(hwnd, dc);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XChangeWindowAttributes --\n *\n *\tThis function is called when the attributes on a window are updated.\n *\tSince Tk maintains all of the window state, the only relevant value is\n *\tthe cursor.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay cause the mouse position to be updated.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXChangeWindowAttributes(\n    Display *display,\n    Window w,\n    unsigned long valueMask,\n    XSetWindowAttributes* attributes)\n{\n    if (valueMask & CWCursor) {\n\tXDefineCursor(display, w, attributes->cursor);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinSetWindowPos --\n *\n *\tAdjust the stacking order of a window relative to a second window (or\n *\tNULL).\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves the specified window in the stacking order.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinSetWindowPos(\n    HWND hwnd,\t\t\t/* Window to restack. */\n    HWND siblingHwnd,\t\t/* Sibling window. */\n    int pos)\t\t\t/* One of Above or Below. */\n{\n    HWND temp;\n\n    /*\n     * Since Windows does not support Above mode, we place the specified\n     * window below the sibling and then swap them.\n     */\n\n    if (siblingHwnd) {\n\tif (pos == Above) {\n\t    SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0,\n\t\t    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n\t    temp = hwnd;\n\t    hwnd = siblingHwnd;\n\t    siblingHwnd = temp;\n\t}\n    } else {\n\tsiblingHwnd = (pos == Above) ? HWND_TOP : HWND_BOTTOM;\n    }\n\n    SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0,\n\t    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpShowBusyWindow --\n *\n *\tMakes a busy window \"appear\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the busy window to start intercepting events and the\n *\tcursor to change to the configured \"hey, I'm busy!\" setting.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpShowBusyWindow(\n    TkBusy busy)\n{\n    Busy *busyPtr = (Busy *) busy;\n    HWND hWnd;\n    POINT point;\n    Display *display;\n    Window window;\n\n    if (busyPtr->tkBusy != NULL) {\n\tTk_MapWindow(busyPtr->tkBusy);\n\twindow = Tk_WindowId(busyPtr->tkBusy);\n\tdisplay = Tk_Display(busyPtr->tkBusy);\n\thWnd = Tk_GetHWND(window);\n\tLastKnownRequestProcessed(display)++;\n\tSetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\n    }\n\n    /*\n     * Under Win32, cursors aren't associated with windows. Tk fakes this by\n     * watching Motion events on its windows. So Tk will automatically change\n     * the cursor when the pointer enters the Busy window. But Windows does\n     * not immediately change the cursor; it waits for the cursor position to\n     * change or a system call. We need to change the cursor before the\n     * application starts processing, so set the cursor position redundantly\n     * back to the current position.\n     */\n\n    GetCursorPos(&point);\n    TkSetCursorPos(point.x, point.y);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpHideBusyWindow --\n *\n *\tMakes a busy window \"disappear\".\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArranges for the busy window to stop intercepting events, and the\n *\tcursor to change back to its normal setting.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpHideBusyWindow(\n    TkBusy busy)\n{\n    Busy *busyPtr = (Busy *) busy;\n    POINT point;\n\n    if (busyPtr->tkBusy != NULL) {\n\tTk_UnmapWindow(busyPtr->tkBusy);\n    }\n\n    /*\n     * Under Win32, cursors aren't associated with windows. Tk fakes this by\n     * watching Motion events on its windows. So Tk will automatically change\n     * the cursor when the pointer enters the Busy window. But Windows does\n     * not immediately change the cursor: it waits for the cursor position to\n     * change or a system call. We need to change the cursor before the\n     * application starts processing, so set the cursor position redundantly\n     * back to the current position.\n     */\n\n    GetCursorPos(&point);\n    TkSetCursorPos(point.x, point.y);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMakeTransparentWindowExist --\n *\n *\tConstruct the platform-specific resources for a transparent window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMoves the specified window in the stacking order.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMakeTransparentWindowExist(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    Window parent)\t\t/* Parent window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    HWND hParent = (HWND) parent, hWnd;\n    int style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;\n    DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_TOPMOST;\n\n    hWnd = CreateWindowExW(exStyle, TK_WIN_CHILD_CLASS_NAME, NULL, style,\n\t    Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),\n\t    hParent, NULL, Tk_GetHINSTANCE(), NULL);\n    winPtr->window = Tk_AttachHWND(tkwin, hWnd);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCreateBusy --\n *\n *\tConstruct the platform-specific parts of a busy window. Note that this\n *\tpostpones the actual creation of the window resource until later.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets up part of the busy window structure.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCreateBusy(\n    Tk_FakeWin *winPtr,\n    Tk_Window tkRef,\n    Window *parentPtr,\n    Tk_Window tkParent,\n    TkBusy busy)\n{\n    Busy *busyPtr = (Busy *) busy;\n\n    if (winPtr->flags & TK_REPARENTED) {\n\t/*\n\t * This works around a bug in the implementation of menubars for\n\t * non-Macintosh window systems (Win32 and X11). Tk doesn't reset the\n\t * pointers to the parent window when the menu is reparented\n\t * (winPtr->parentPtr points to the wrong window). We get around this\n\t * by determining the parent via the native API calls.\n\t */\n\n\tHWND hWnd = GetParent(Tk_GetHWND(Tk_WindowId(tkRef)));\n\tRECT rect;\n\n\tif (GetWindowRect(hWnd, &rect)) {\n\t    busyPtr->width = rect.right - rect.left;\n\t    busyPtr->height = rect.bottom - rect.top;\n\t}\n    } else {\n\t*parentPtr = Tk_WindowId(tkParent);\n\t*parentPtr = (Window) Tk_GetHWND(*parentPtr);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinWm.c",
    "content": "/*\n * tkWinWm.c --\n *\n *\tThis module takes care of the interactions between a Tk-based\n *\tapplication and the window manager. Among other things, it implements\n *\tthe \"wm\" command and passes geometry information to the window\n *\tmanager.\n *\n * Copyright © 1995-1997 Sun Microsystems, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkWinInt.h\"\n#include <wtypes.h>\n#include <shobjidl.h>\n#include <shlguid.h>\n#include \"tkWinIco.h\"\n/*\n * These next two defines are only valid on Win2K/XP+.\n */\n\n#ifndef WS_EX_LAYERED\n#define WS_EX_LAYERED\t0x00080000\n#endif\n#ifndef LWA_COLORKEY\n#define LWA_COLORKEY\t0x00000001\n#endif\n#ifndef LWA_ALPHA\n#define LWA_ALPHA\t0x00000002\n#endif\n\n/*\n * Event structure for synthetic activation events. These events are placed on\n * the event queue whenever a toplevel gets a WM_MOUSEACTIVATE message or\n * a WM_ACTIVATE. If the window is being moved (*flagPtr will be true)\n * then the handling of this event must be delayed until the operation\n * has completed to avoid a premature WM_EXITSIZEMOVE event.\n */\n\ntypedef struct ActivateEvent {\n    Tcl_Event ev;\n    TkWindow *winPtr;\n    const int *flagPtr;\n    HWND hwnd;\n} ActivateEvent;\n\n/*\n * A data structure of the following type holds information for each window\n * manager protocol (such as WM_DELETE_WINDOW) for which a handler (i.e. a Tcl\n * command) has been defined for a particular top-level window.\n */\n\ntypedef struct ProtocolHandler {\n    Atom protocol;\t\t/* Identifies the protocol. */\n    struct ProtocolHandler *nextPtr;\n\t\t\t\t/* Next in list of protocol handlers for the\n\t\t\t\t * same top-level window, or NULL for end of\n\t\t\t\t * list. */\n    Tcl_Interp *interp;\t/* Interpreter in which to invoke command. */\n    char command[TKFLEXARRAY];\t/* Tcl command to invoke when a client message\n\t\t\t\t * for this protocol arrives. The actual size\n\t\t\t\t * of the structure varies to accommodate the\n\t\t\t\t * needs of the actual command. THIS MUST BE\n\t\t\t\t * THE LAST FIELD OF THE STRUCTURE. */\n} ProtocolHandler;\n\n#define HANDLER_SIZE(cmdLength) \\\n    (offsetof(ProtocolHandler, command) + 1 + cmdLength)\n\n/*\n * Helper type passed via lParam to TkWmStackorderToplevelEnumProc\n */\n\ntypedef struct TkWmStackorderToplevelPair {\n    Tcl_HashTable *table;\n    TkWindow **windowPtr;\n} TkWmStackorderToplevelPair;\n\n\n/*\n * A pointer to one of these structures is associated with each toplevel.\n * This allows us to free up all memory associated with icon resources when a\n * window is deleted or if the window's icon is changed. They are simply\n * reference counted according to:\n *\n * (1) How many WmInfo structures point to this object\n * (2) Whether the ThreadSpecificData defined in this file contains a pointer\n *     to this object.\n *\n * The former count is for windows whose icons are individually set, and the\n * latter is for the global default icon choice.\n *\n * Icons loaded from .icr/.icr use the iconBlock field, icons loaded from\n * .exe/.dll use the hIcon field.\n */\n\ntypedef struct WinIconInstance {\n    size_t refCount;\t/* Number of instances that share this data\n\t\t\t\t * structure. */\n    BlockOfIconImagesPtr iconBlock;\n\t\t\t\t/* Pointer to icon resource data for image */\n} WinIconInstance;\n\ntypedef struct WinIconInstance *WinIconPtr;\n\n/*\n * A data structure of the following type holds window-manager-related\n * information for each top-level window in an application.\n */\n\ntypedef struct TkWmInfo {\n    TkWindow *winPtr;\t\t/* Pointer to main Tk information for this\n\t\t\t\t * window. */\n    HWND wrapper;\t\t/* This is the decorative frame window created\n\t\t\t\t * by the window manager to wrap a toplevel\n\t\t\t\t * window. This window is a direct child of\n\t\t\t\t * the root window. */\n    char *title;\t\t/* Title to display in window caption. If\n\t\t\t\t * NULL, use name of widget. Malloced. */\n    char *iconName;\t\t/* Name to display in icon. Malloced. */\n    XWMHints hints;\t\t/* Various pieces of information for window\n\t\t\t\t * manager. */\n    char *leaderName;\t\t/* Path name of leader of window group\n\t\t\t\t * (corresponds to hints.window_group).\n\t\t\t\t * Malloc-ed. Note: this field doesn't get\n\t\t\t\t * updated if leader is destroyed. */\n    TkWindow *containerPtr;\t/* Container window for TRANSIENT_FOR property,\n\t\t\t\t * or NULL. */\n    Tk_Window icon;\t\t/* Window to use as icon for this window, or\n\t\t\t\t * NULL. */\n    Tk_Window iconFor;\t\t/* Window for which this window is icon, or\n\t\t\t\t * NULL if this isn't an icon for anyone. */\n\n    /*\n     * Information used to construct an XSizeHints structure for the window\n     * manager:\n     */\n\n    int defMinWidth, defMinHeight, defMaxWidth, defMaxHeight;\n\t\t\t\t/* Default resize limits given by system. */\n    int sizeHintsFlags;\t\t/* Flags word for XSizeHints structure. If the\n\t\t\t\t * PBaseSize flag is set then the window is\n\t\t\t\t * gridded; otherwise it isn't gridded. */\n    int minWidth, minHeight;\t/* Minimum dimensions of window, in pixels or\n\t\t\t\t * grid units. */\n    int maxWidth, maxHeight;\t/* Maximum dimensions of window, in pixels or\n\t\t\t\t * grid units. 0 to default. */\n    Tk_Window gridWin;\t\t/* Identifies the window that controls\n\t\t\t\t * gridding for this top-level, or NULL if the\n\t\t\t\t * top-level isn't currently gridded. */\n    int widthInc, heightInc;\t/* Increments for size changes (# pixels per\n\t\t\t\t * step). */\n    struct {\n\tint x;\t/* numerator */\n\tint y;\t/* denominator */\n    } minAspect, maxAspect;\t/* Min/max aspect ratios for window. */\n    int reqGridWidth, reqGridHeight;\n\t\t\t\t/* The dimensions of the window (in grid\n\t\t\t\t * units) requested through the geometry\n\t\t\t\t * manager. */\n    int gravity;\t\t/* Desired window gravity. */\n\n    /*\n     * Information used to manage the size and location of a window.\n     */\n\n    int width, height;\t\t/* Desired dimensions of window, specified in\n\t\t\t\t * pixels or grid units. These values are set\n\t\t\t\t * by the \"wm geometry\" command and by\n\t\t\t\t * ConfigureNotify events (for when wm resizes\n\t\t\t\t * window). -1 means user hasn't requested\n\t\t\t\t * dimensions. */\n    int x, y;\t\t\t/* Desired X and Y coordinates for window.\n\t\t\t\t * These values are set by \"wm geometry\", plus\n\t\t\t\t * by ConfigureNotify events (when wm moves\n\t\t\t\t * window). These numbers are different than\n\t\t\t\t * the numbers stored in winPtr->changes\n\t\t\t\t * because (a) they could be measured from the\n\t\t\t\t * right or bottom edge of the screen (see\n\t\t\t\t * WM_NEGATIVE_X and WM_NEGATIVE_Y flags) and\n\t\t\t\t * (b) if the window has been reparented then\n\t\t\t\t * they refer to the parent rather than the\n\t\t\t\t * window itself. */\n    int borderWidth, borderHeight;\n\t\t\t\t/* Width and height of window dressing, in\n\t\t\t\t * pixels for the current style/exStyle. This\n\t\t\t\t * includes the border on both sides of the\n\t\t\t\t * window. */\n    int configX, configY;\t/* x,y position of toplevel when window is\n\t\t\t\t * switched into fullscreen state, */\n    int configWidth, configHeight;\n\t\t\t\t/* Dimensions passed to last request that we\n\t\t\t\t * issued to change geometry of window. Used\n\t\t\t\t * to eliminate redundant resize operations */\n    HMENU hMenu;\t\t/* the hMenu associated with this menu */\n    DWORD style, exStyle;\t/* Style flags for the wrapper window. */\n    LONG styleConfig;\t\t/* Extra user requested style bits */\n    LONG exStyleConfig;\t\t/* Extra user requested extended style bits */\n    Tcl_Obj *crefObj;\t\t/* COLORREF object for transparent handling */\n    COLORREF colorref;\t\t/* COLORREF for transparent handling */\n    double alpha;\t\t/* Alpha transparency level 0.0 (fully\n\t\t\t\t * transparent) .. 1.0 (opaque) */\n\n    /*\n     * List of children of the toplevel which have private colormaps.\n     */\n\n    TkWindow **cmapList;\t/* Array of window with private colormaps. */\n    Tcl_Size cmapCount;\t\t/* Number of windows in array. */\n\n    /*\n     * Miscellaneous information.\n     */\n\n    ProtocolHandler *protPtr;\t/* First in list of protocol handlers for this\n\t\t\t\t * window (NULL means none). */\n    Tcl_Size cmdArgc;\t\t/* Number of elements in cmdArgv below. */\n    const char **cmdArgv;\t/* Array of strings to store in the WM_COMMAND\n\t\t\t\t * property. NULL means nothing available. */\n    char *clientMachine;\t/* String to store in WM_CLIENT_MACHINE\n\t\t\t\t * property, or NULL. */\n    int flags;\t\t\t/* Miscellaneous flags, defined below. */\n    int numTransients;\t\t/* Number of transients on this window */\n    WinIconPtr iconPtr;\t\t/* Pointer to titlebar icon structure for this\n\t\t\t\t * window, or NULL. */\n    struct TkWmInfo *nextPtr;\t/* Next in list of all top-level windows. */\n} WmInfo;\n\n/*\n * Flag values for WmInfo structures:\n *\n * WM_NEVER_MAPPED -\t\tNon-zero means window has never been mapped;\n *\t\t\t\tneed to update all info when window is first\n *\t\t\t\tmapped.\n * WM_UPDATE_PENDING -\t\tNon-zero means a call to UpdateGeometryInfo\n *\t\t\t\thas already been scheduled for this window;\n *\t\t\t\tno need to schedule another one.\n * WM_NEGATIVE_X -\t\tNon-zero means x-coordinate is measured in\n *\t\t\t\tpixels from right edge of screen, rather than\n *\t\t\t\tfrom left edge.\n * WM_NEGATIVE_Y -\t\tNon-zero means y-coordinate is measured in\n *\t\t\t\tpixels up from bottom of screen, rather than\n *\t\t\t\tdown from top.\n * WM_UPDATE_SIZE_HINTS -\tNon-zero means that new size hints need to be\n *\t\t\t\tpropagated to window manager. Not used on Win.\n * WM_SYNC_PENDING -\t\tSet to non-zero while waiting for the window\n *\t\t\t\tmanager to respond to some state change.\n * WM_MOVE_PENDING -\t\tNon-zero means the application has requested a\n *\t\t\t\tnew position for the window, but it hasn't\n *\t\t\t\tbeen reflected through the window manager yet.\n * WM_COLORMAPS_EXPLICIT -\tNon-zero means the colormap windows were set\n *\t\t\t\texplicitly via \"wm colormapwindows\".\n * WM_ADDED_TOPLEVEL_COLORMAP - Non-zero means that when \"wm colormapwindows\"\n *\t\t\t\twas called the top-level itself wasn't\n *\t\t\t\tspecified, so we added it implicitly at the\n *\t\t\t\tend of the list.\n * WM_WIDTH_NOT_RESIZABLE -\tNon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the width of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n * WM_HEIGHT_NOT_RESIZABLE -\tNon-zero means that we're not supposed to\n *\t\t\t\tallow the user to change the height of the\n *\t\t\t\twindow (controlled by \"wm resizable\" command).\n * WM_WITHDRAWN -\t\tNon-zero means that this window has explicitly\n *\t\t\t\tbeen withdrawn. If it's a transient, it should\n *\t\t\t\tnot mirror state changes in the container.\n * WM_FULLSCREEN -\t\tNon-zero means that this window has been placed\n *\t\t\t\tin the full screen mode. It should be mapped at\n *\t\t\t\t0,0 and be the width and height of the screen.\n */\n\n#define WM_NEVER_MAPPED\t\t\t(1<<0)\n#define WM_UPDATE_PENDING\t\t(1<<1)\n#define WM_NEGATIVE_X\t\t\t(1<<2)\n#define WM_NEGATIVE_Y\t\t\t(1<<3)\n#define WM_UPDATE_SIZE_HINTS\t\t(1<<4)\n#define WM_SYNC_PENDING\t\t\t(1<<5)\n#define WM_CREATE_PENDING\t\t(1<<6)\n#define WM_MOVE_PENDING\t\t\t(1<<7)\n#define WM_COLORMAPS_EXPLICIT\t\t(1<<8)\n#define WM_ADDED_TOPLEVEL_COLORMAP\t(1<<9)\n#define WM_WIDTH_NOT_RESIZABLE\t\t(1<<10)\n#define WM_HEIGHT_NOT_RESIZABLE\t\t(1<<11)\n#define WM_WITHDRAWN\t\t\t(1<<12)\n#define WM_FULLSCREEN\t\t\t(1<<13)\n\n/*\n * Window styles for various types of toplevel windows.\n */\n\n#define WM_OVERRIDE_STYLE (WS_CLIPCHILDREN|WS_CLIPSIBLINGS|CS_DBLCLKS)\n#define EX_OVERRIDE_STYLE (WS_EX_TOOLWINDOW)\n\n#define WM_FULLSCREEN_STYLE (WS_POPUP|WM_OVERRIDE_STYLE)\n#define EX_FULLSCREEN_STYLE (WS_EX_APPWINDOW)\n\n#define WM_TOPLEVEL_STYLE (WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|CS_DBLCLKS)\n#define EX_TOPLEVEL_STYLE (0)\n\n#define WM_TRANSIENT_STYLE \\\n\t\t(WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS)\n/*\n * Bug 159aa5eb: Removed extended style WS_EX_DLGMODALFRAME. This style has\n * the undocumented side effect to enable the unwanted system menu items\n * \"Resize\", \"Minimize\" and \"Maximize\". \"Resise\" menu item may be correctly\n * enabled by \"wm resizable\".\n */\n#define EX_TRANSIENT_STYLE (0)\n\n/*\n * The following structure is the official type record for geometry management\n * of top-level windows.\n */\n\nstatic void\t\tTopLevelReqProc(void *dummy, Tk_Window tkwin);\nstatic void\t\tRemapWindows(TkWindow *winPtr, HWND parentHWND);\n\nstatic const Tk_GeomMgr wmMgrType = {\n    \"wm\",\t\t\t/* name */\n    TopLevelReqProc,\t\t/* requestProc */\n    NULL,\t\t\t/* lostContentProc */\n};\n\ntypedef struct {\n    HPALETTE systemPalette;\t/* System palette; refers to the currently\n\t\t\t\t * installed foreground logical palette. */\n    TkWindow *createWindow;\t/* Window that is being constructed. This\n\t\t\t\t * value is set immediately before a call to\n\t\t\t\t * CreateWindowEx, and is used by SetLimits.\n\t\t\t\t * This is a gross hack needed to work around\n\t\t\t\t * Windows brain damage where it sends the\n\t\t\t\t * WM_GETMINMAXINFO message before the\n\t\t\t\t * WM_CREATE window. */\n    bool initialized;\t\t/* Flag indicating whether thread-specific\n\t\t\t\t * elements of module have been\n\t\t\t\t * initialized. */\n    int firstWindow;\t\t/* Flag, cleared when the first window is\n\t\t\t\t * mapped in a non-iconic state. */\n    WinIconPtr iconPtr;\t\t/* IconPtr being used as default for all\n\t\t\t\t * toplevels, or NULL. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * The following variables cannot be placed in thread local storage because\n * they must be shared across threads.\n */\n\nstatic bool initialized;\t\t/* Flag indicating whether module has been\n\t\t\t\t * initialized. */\n\nTCL_DECLARE_MUTEX(winWmMutex)\n\n/*\n * The following records the \"TaskbarButtonCreated\" message ID\n * for overlay icons.\n */\n\nstatic UINT TaskbarButtonCreatedMessageId = WM_NULL;\n\n/* Reference to taskbarlist API for overlay icons. */\nITaskbarList3 *ptbl;\n\n/*\n * Forward declarations for functions defined in this file:\n */\n\nstatic int\t\tActivateWindow(Tcl_Event *evPtr, int flags);\nstatic void\t\tConfigureTopLevel(WINDOWPOS *pos);\nstatic void\t\tGenerateConfigureNotify(TkWindow *winPtr);\nstatic void\t\tGenerateActivateEvent(TkWindow *winPtr, const int *flagPtr);\nstatic void\t\tGetMaxSize(WmInfo *wmPtr,\n\t\t\t    int *maxWidthPtr, int *maxHeightPtr);\nstatic void\t\tGetMinSize(WmInfo *wmPtr,\n\t\t\t    int *minWidthPtr, int *minHeightPtr);\nstatic TkWindow *\tGetTopLevel(HWND hwnd);\nstatic void\t\tInitWm(void);\nstatic bool\t\tInstallColormaps(HWND hwnd, int message,\n\t\t\t    bool isForemost);\nstatic void\t\tInvalidateSubTree(TkWindow *winPtr, Colormap colormap);\nstatic void\t\tInvalidateSubTreeDepth(TkWindow *winPtr);\nstatic int\t\tParseGeometry(Tcl_Interp *interp, const char *string,\n\t\t\t    TkWindow *winPtr);\nstatic void\t\tRefreshColormap(Colormap colormap, TkDisplay *dispPtr);\nstatic void\t\tSetLimits(HWND hwnd, MINMAXINFO *info);\nstatic void\t\tTkWmStackorderToplevelWrapperMap(TkWindow *winPtr,\n\t\t\t    Display *display, Tcl_HashTable *table);\nstatic LRESULT CALLBACK\tTopLevelProc(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam);\nstatic void\t\tTopLevelEventProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic void\t\tTopLevelReqProc(void *dummy, Tk_Window tkwin);\nstatic void\t\tUpdateGeometryInfo(void *clientData);\nstatic void\t\tUpdateWrapper(TkWindow *winPtr);\nstatic LRESULT CALLBACK\tWmProc(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam);\nstatic void\t\tWmWaitVisibilityOrMapProc(void *clientData,\n\t\t\t    XEvent *eventPtr);\nstatic BlockOfIconImagesPtr ReadIconOrCursorFromFile(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj* fileName, BOOL isIcon);\nstatic WinIconPtr\tReadIconFromFile(Tcl_Interp *interp,\n\t\t\t    Tcl_Obj *fileName);\nstatic BOOL\t\tAdjustIconImagePointers(LPICONIMAGE lpImage);\nstatic WinIconPtr\tGetIconFromPixmap(Display *dsPtr, Pixmap pixmap);\nstatic int\t\tReadICOHeader(Tcl_Channel channel);\nstatic HICON\t\tMakeIconOrCursorFromResource(LPICONIMAGE lpIcon,\n\t\t\t    BOOL isIcon);\nstatic HICON\t\tGetIcon(WinIconPtr titlebaricon, int icon_size);\nstatic int\t\tWinSetIcon(Tcl_Interp *interp,\n\t\t\t    WinIconPtr titlebaricon, Tk_Window tkw);\nstatic void\t\tFreeIconBlock(BlockOfIconImagesPtr lpIR);\nstatic void\t\tDecrIconRefCount(WinIconPtr titlebaricon);\n\nstatic int\t\tWmAspectCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmAttributesCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmClientCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmColormapwindowsCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmCommandCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmDeiconifyCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFocusmodelCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmForgetCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmFrameCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGeometryCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGridCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmGroupCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbadgeCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconbitmapCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconifyCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconmaskCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconnameCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconphotoCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconpositionCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmIconwindowCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmManageCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMaxsizeCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmMinsizeCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmOverrideredirectCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmPositionfromCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmProtocolCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmResizableCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmSizefromCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStackorderCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmStateCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTitleCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmTransientCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic int\t\tWmWithdrawCmd(Tk_Window tkwin,\n\t\t\t    TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc,\n\t\t\t    Tcl_Obj *const objv[]);\nstatic void\t\tWmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * MakeIconOrCursorFromResource --\n *\n *\tConstruct an actual HICON structure from the information in a\n *\tresource.\n *\n * Results:\n *\tIcon\n *\n *----------------------------------------------------------------------\n */\n\nstatic HICON\nMakeIconOrCursorFromResource(\n    LPICONIMAGE lpIcon,\n    BOOL isIcon)\n{\n    HICON hIcon;\n\n    /*\n     * Sanity Check\n     */\n\n    if (lpIcon == NULL || lpIcon->lpBits == NULL) {\n\treturn NULL;\n    }\n\n    /*\n     * Let the OS do the real work :)\n     */\n\n    hIcon = (HICON)CreateIconFromResourceEx(lpIcon->lpBits,\n\t    lpIcon->dwNumBytes, isIcon, 0x00030000, 0, 0, 0);\n\n    /*\n     * It failed, the non-Ex way might work as a fallback.\n     */\n\n    if (hIcon == NULL) {\n\thIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes,\n\t\tisIcon, 0x00030000);\n    }\n    return hIcon;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadICOHeader --\n *\n *\tReads the header from an ICO file, as specfied by channel.\n *\n * Results:\n *\tUINT - Number of images in file, -1 for failure. If this succeeds,\n *\tthere is a decent chance this is a valid icon file.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nReadICOHeader(\n    Tcl_Channel channel)\n{\n    union {\n\tWORD word;\n\tchar bytes[sizeof(WORD)];\n    } input;\n\n    /*\n     * Read the 'reserved' WORD, which should be a zero word.\n     */\n\n    if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) {\n\treturn -1;\n    }\n    if (input.word != 0) {\n\treturn -1;\n    }\n\n    /*\n     * Read the type WORD, which should be of type 1.\n     */\n\n    if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) {\n\treturn -1;\n    }\n    if (input.word != 1) {\n\treturn -1;\n    }\n\n    /*\n     * Get and return the count of images.\n     */\n\n    if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) {\n\treturn -1;\n    }\n    return (int) input.word;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitWindowClass --\n *\n *\tThis routine creates the Wm toplevel decorative frame class.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRegisters a new window class.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nInitWindowClass(\n    WinIconPtr titlebaricon)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\ttsdPtr->initialized = true;\n\ttsdPtr->firstWindow = 1;\n\ttsdPtr->iconPtr = NULL;\n    }\n    if (!initialized) {\n\tTcl_MutexLock(&winWmMutex);\n\tif (!initialized) {\n\t    WNDCLASSW windowClass;\n\n\t    initialized = true;\n\n\t    memset(&windowClass, 0, sizeof(WNDCLASSW));\n\n\t    windowClass.style = CS_HREDRAW | CS_VREDRAW;\n\t    windowClass.hInstance = Tk_GetHINSTANCE();\n\t    windowClass.lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;\n\t    windowClass.lpfnWndProc = WmProc;\n\t    if (titlebaricon == NULL) {\n\t\twindowClass.hIcon = LoadIconW(Tk_GetHINSTANCE(), L\"tk\");\n\t    } else {\n\t\twindowClass.hIcon = GetIcon(titlebaricon, ICON_BIG);\n\t\tif (windowClass.hIcon == NULL) {\n\t\t    return TCL_ERROR;\n\t\t}\n\n\t\t/*\n\t\t * Store pointer to default icon so we know when we need to\n\t\t * free that information\n\t\t */\n\n\t\ttsdPtr->iconPtr = titlebaricon;\n\t    }\n\t    windowClass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);\n\n\t    if (!RegisterClassW(&windowClass)) {\n\t\tTcl_Panic(\"Unable to register TkTopLevel class\");\n\t    }\n\t}\n\tTcl_MutexUnlock(&winWmMutex);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InitWm --\n *\n *\tThis initialises the window manager\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRegisters a new window class.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInitWm(void)\n{\n    /* Ignore return result */\n    (void) InitWindowClass(NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WinSetIcon --\n *\n *\tSets either the default toplevel titlebar icon, or the icon for a\n *\tspecific toplevel (if tkw is given, then only that window is used).\n *\n *\tThe ref-count of the titlebaricon is NOT changed. If this function\n *\treturns successfully, the caller should assume the icon was used (and\n *\ttherefore the ref-count should be adjusted to reflect that fact). If\n *\tthe function returned an error, the caller should assume the icon was\n *\tnot used (and may wish to free the memory associated with it).\n *\n * Results:\n *\tA standard Tcl return code.\n *\n * Side effects:\n *\tOne or all windows may have their icon changed. The Tcl result may be\n *\tmodified. The window-manager will be initialised if it wasn't already.\n *\tThe given window will be forced into existence.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWinSetIcon(\n    Tcl_Interp *interp,\n    WinIconPtr titlebaricon,\n    Tk_Window tkw)\n{\n    WmInfo *wmPtr;\n    HWND hwnd;\n    int application = 0;\n\n    if (tkw == NULL) {\n\ttkw = Tk_MainWindow(interp);\n\tapplication = 1;\n    }\n\n    if (!(Tk_IsTopLevel(tkw))) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" isn't a top-level window\", Tk_PathName(tkw)));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TOPLEVEL\", Tk_PathName(tkw),\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (Tk_WindowId(tkw) == None) {\n\tTk_MakeWindowExist(tkw);\n    }\n\n    /*\n     * We must get the window's wrapper, not the window itself.\n     */\n\n    wmPtr = ((TkWindow *) tkw)->wmInfoPtr;\n    hwnd = wmPtr->wrapper;\n\n    if (application) {\n\tif (hwnd == NULL) {\n\t    /*\n\t     * I don't actually think this is ever the correct thing, unless\n\t     * perhaps the window doesn't have a wrapper. But I believe all\n\t     * windows have wrappers.\n\t     */\n\n\t    hwnd = Tk_GetHWND(Tk_WindowId(tkw));\n\t}\n\n\t/*\n\t * If we aren't initialised, then just initialise with the user's\n\t * icon. Otherwise our icon choice will be ignored moments later when\n\t * Tk finishes initialising.\n\t */\n\n\tif (!initialized) {\n\t    if (InitWindowClass(titlebaricon) != TCL_OK) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"Unable to set icon\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICON\", \"FAILED\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else {\n\t    ThreadSpecificData *tsdPtr;\n\n\t    /*\n\t     * Don't check return result of SetClassLong() or\n\t     * SetClassLongPtrW() since they return the previously set value\n\t     * which is zero on the initial call or in an error case. The MSDN\n\t     * documentation does not indicate that the result needs to be\n\t     * checked.\n\t     */\n\n\t    SetClassLongPtrW(hwnd, GCLP_HICONSM,\n\t\t    (LPARAM) GetIcon(titlebaricon, ICON_SMALL));\n\t    SetClassLongPtrW(hwnd, GCLP_HICON,\n\t\t    (LPARAM) GetIcon(titlebaricon, ICON_BIG));\n\t    tsdPtr = (ThreadSpecificData *)\n\t\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\t    if (tsdPtr->iconPtr != NULL) {\n\t\tDecrIconRefCount(tsdPtr->iconPtr);\n\t    }\n\t    tsdPtr->iconPtr = titlebaricon;\n\t}\n    } else {\n\tif (!initialized) {\n\t    /*\n\t     * Need to initialise the wm otherwise we will fail on code which\n\t     * tries to set a toplevel's icon before that happens. Ignore\n\t     * return result.\n\t     */\n\n\t    (void) InitWindowClass(NULL);\n\t}\n\n\t/*\n\t * The following code is exercised if you do\n\t *\n\t *\ttoplevel .t ; wm titlebaricon .t foo.icr\n\t *\n\t * i.e. the wm hasn't had time to properly create the '.t' window\n\t * before you set the icon.\n\t */\n\n\tif (hwnd == NULL) {\n\t    /*\n\t     * This little snippet is copied from the 'Map' function, and\n\t     * should probably be placed in one proper location.\n\t     */\n\n\t    UpdateWrapper(wmPtr->winPtr);\n\t    wmPtr = ((TkWindow *) tkw)->wmInfoPtr;\n\t    hwnd = wmPtr->wrapper;\n\t    if (hwnd == NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t\t\"Can't set icon; window has no wrapper.\", TCL_INDEX_NONE));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICON\", \"WRAPPER\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tSendMessageW(hwnd, WM_SETICON, ICON_SMALL,\n\t\t(LPARAM) GetIcon(titlebaricon, ICON_SMALL));\n\tSendMessageW(hwnd, WM_SETICON, ICON_BIG,\n\t\t(LPARAM) GetIcon(titlebaricon, ICON_BIG));\n\n\t/*\n\t * Update the iconPtr we keep for each WmInfo structure.\n\t */\n\n\tif (wmPtr->iconPtr != NULL) {\n\t    /*\n\t     * Free any old icon ptr which is associated with this window.\n\t     */\n\n\t    DecrIconRefCount(wmPtr->iconPtr);\n\t}\n\n\t/*\n\t * We do not need to increment the ref count for the titlebaricon,\n\t * because it was already incremented when we retrieved it.\n\t */\n\n\twmPtr->iconPtr = titlebaricon;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetIcon --\n *\n *\tGets either the default toplevel titlebar icon, or the icon for a\n *\tspecific toplevel (ICON_SMALL or ICON_BIG).\n *\n * Results:\n *\tA Windows HICON.\n *\n * Side effects:\n *\tThe given window will be forced into existence.\n *\n *----------------------------------------------------------------------\n */\n\nHICON\nTkWinGetIcon(\n    Tk_Window tkwin,\n    DWORD iconsize)\n{\n    WmInfo *wmPtr;\n    HICON icon;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->iconPtr != NULL) {\n\t/*\n\t * return default toplevel icon\n\t */\n\n\treturn GetIcon(tsdPtr->iconPtr, (int) iconsize);\n    }\n\n    /*\n     * Ensure we operate on the toplevel, that has the icon refs.\n     */\n\n    while (!Tk_IsTopLevel(tkwin)) {\n\ttkwin = Tk_Parent(tkwin);\n\tif (tkwin == NULL) {\n\t    return NULL;\n\t}\n    }\n\n    if (Tk_WindowId(tkwin) == None) {\n\tTk_MakeWindowExist(tkwin);\n    }\n\n    wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;\n    if (wmPtr->iconPtr != NULL) {\n\t/*\n\t * return window toplevel icon\n\t */\n\n\treturn GetIcon(wmPtr->iconPtr, (int) iconsize);\n    }\n\n    /*\n     * Find the icon otherwise associated with the toplevel, or finally with\n     * the window class.\n     */\n\n    icon = (HICON) SendMessageW(wmPtr->wrapper, WM_GETICON, iconsize,\n\t    (LPARAM) NULL);\n    if (icon == (HICON) NULL) {\n\ticon = (HICON) GetClassLongPtrW(wmPtr->wrapper,\n\t\t(iconsize == ICON_BIG) ? GCLP_HICON : GCLP_HICONSM);\n    }\n    return icon;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadIconFromFile --\n *\n *\tRead the contents of a file (usually .ico, .icr) and extract an icon\n *\tresource, if possible, otherwise check if the shell has an icon\n *\tassigned to the given file and use that. If both of those fail, then\n *\tNULL is returned, and an error message will already be in the\n *\tinterpreter.\n *\n * Results:\n *\tA WinIconPtr structure containing the icons in the file, with its ref\n *\tcount already incremented. The calling function should either place\n *\tthis structure inside a WmInfo structure, or it should pass it on to\n *\tDecrIconRefCount() to ensure no memory leaks occur.\n *\n *\tIf the given fileName did not contain a valid icon structure,\n *\treturn NULL.\n *\n * Side effects:\n *\tMemory is allocated for the returned structure and the icons it\n *\tcontains. If the structure is not wanted, it should be passed to\n *\tDecrIconRefCount, and in any case a valid ref count should be ensured\n *\tto avoid memory leaks.\n *\n *\tCurrently icon resources are not shared, so the ref count of one of\n *\tthese structures will always be 0 or 1. However all we need do is\n *\timplement some sort of lookup function between filenames and\n *\tWinIconPtr structures and no other code will need to be changed. The\n *\tpseudo-code for this is implemented below in the 'if (0)' branch. It\n *\tdid not seem necessary to implement this optimisation here, since\n *\tmoving to icon<->image conversions will probably make it obsolete.\n *\n *----------------------------------------------------------------------\n */\n\nstatic WinIconPtr\nReadIconFromFile(\n    Tcl_Interp *interp,\n    Tcl_Obj *fileName)\n{\n    WinIconPtr titlebaricon = NULL;\n    BlockOfIconImagesPtr lpIR;\n\n#if 0 /* TODO: Dead code? */\n    if (0 /* If we already have an icon for this filename */) {\n\ttitlebaricon = NULL; /* Get the real value from a lookup */\n\ttitlebaricon->refCount++;\n\treturn titlebaricon;\n    }\n#endif\n\n    /*\n     * First check if it is a .ico file.\n     */\n\n    lpIR = ReadIconOrCursorFromFile(interp, fileName, TRUE);\n\n    /*\n     * Then see if we can ask the shell for the icon for this file. We\n     * want both the regular and small icons so that the Alt-Tab (task-\n     * switching) display uses the right icon.\n     */\n\n    if (lpIR == NULL) {\n\tSHFILEINFOW sfiSM;\n\tTcl_DString ds, ds2;\n\tDWORD *res;\n\tconst char *file;\n\n\tfile = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds);\n\tif (file == NULL) {\n\t    return NULL;\n\t}\n\tTcl_DStringInit(&ds2);\n\tres = (DWORD *)SHGetFileInfoW(Tcl_UtfToWCharDString(file, TCL_INDEX_NONE, &ds2), 0, &sfiSM,\n\t\tsizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON);\n\tTcl_DStringFree(&ds);\n\n\tif (res != 0) {\n\t    SHFILEINFOW sfi;\n\t    unsigned size;\n\n\t    Tcl_ResetResult(interp);\n\t    res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfi,\n\t\t    sizeof(SHFILEINFO), SHGFI_ICON);\n\n\t    /*\n\t     * Account for extra icon, if necessary.\n\t     */\n\n\t    size = sizeof(BlockOfIconImages)\n\t\t    + ((res != 0) ? sizeof(ICONIMAGE) : 0);\n\t    lpIR = (BlockOfIconImagesPtr)Tcl_Alloc(size);\n\t    if (lpIR == NULL) {\n\t\tif (res != 0) {\n\t\t    DestroyIcon(sfi.hIcon);\n\t\t}\n\t\tDestroyIcon(sfiSM.hIcon);\n\t\tTcl_DStringFree(&ds2);\n\t\treturn NULL;\n\t    }\n\t    memset(lpIR, 0, size);\n\n\t    lpIR->nNumImages\t\t= ((res != 0) ? 2 : 1);\n\t    lpIR->IconImages[0].Width\t= 16;\n\t    lpIR->IconImages[0].Height\t= 16;\n\t    lpIR->IconImages[0].Colors\t= 4;\n\t    lpIR->IconImages[0].hIcon\t= sfiSM.hIcon;\n\n\t    /*\n\t     * All other IconImages fields are ignored.\n\t     */\n\n\t    if (res != 0) {\n\t\tlpIR->IconImages[1].Width\t= 32;\n\t\tlpIR->IconImages[1].Height\t= 32;\n\t\tlpIR->IconImages[1].Colors\t= 4;\n\t\tlpIR->IconImages[1].hIcon\t= sfi.hIcon;\n\t    }\n\t}\n\tTcl_DStringFree(&ds2);\n    }\n    if (lpIR != NULL) {\n\ttitlebaricon = (WinIconPtr)Tcl_Alloc(sizeof(WinIconInstance));\n\ttitlebaricon->iconBlock = lpIR;\n\ttitlebaricon->refCount = 1;\n    }\n    return titlebaricon;\n}\n\f\n\n/*\n *----------------------------------------------------------------------\n *\n * AdjustIconImagePointers --\n *\n *\tAdjusts internal pointers in icon resource struct, as given by\n *\tLPICONIMAGE lpImage - the resource to handle. Used by titlebar icon\n *\tcode.\n *\n * Results:\n *\tBOOL - TRUE for success, FALSE for failure\n *\n *----------------------------------------------------------------------\n */\n\nstatic BOOL\nSetSizeAndColorFromHICON(      /* Helper for AdjustIconImagePointers */\n    HICON hicon,\n    LPICONIMAGE lpImage)\n{\n    ICONINFO info;\n    BOOL bRes;\n    BITMAP bmp;\n\n    memset(&info, 0, sizeof(info));\n\n    bRes = GetIconInfo(hicon, &info);\n    if (!bRes) {\n\treturn FALSE;\n    }\n\n    if (info.hbmColor) {\n\tconst int nWrittenBytes = GetObject(info.hbmColor, sizeof(bmp), &bmp);\n\n\tif (nWrittenBytes > 0) {\n\t    lpImage->Width = bmp.bmWidth;\n\t    lpImage->Height = bmp.bmHeight;\n\t    lpImage->Colors = bmp.bmBitsPixel;\n\t}\n    } else if (info.hbmMask) {\n\t// Icon has no color plane, image data stored in mask\n\tconst int nWrittenBytes = GetObject(info.hbmMask, sizeof(bmp), &bmp);\n\n\tif (nWrittenBytes > 0) {\n\t    lpImage->Width = bmp.bmWidth;\n\t    lpImage->Height = bmp.bmHeight / 2;\n\t    lpImage->Colors = 1;\n\t}\n    }\n\n    if (info.hbmColor) {\n\tDeleteObject(info.hbmColor);\n    }\n    if (info.hbmMask) {\n\tDeleteObject(info.hbmMask);\n    }\n    return TRUE;\n}\n\nstatic BOOL\nAdjustIconImagePointers(\n    LPICONIMAGE lpImage)\n{\n    /*\n     * Sanity check.\n     */\n\n    if (lpImage == NULL) {\n\treturn FALSE;\n    }\n\n    /*\n     * BITMAPINFO is at beginning of bits.\n     */\n\n    lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits;\n\n    /*\n     * Width, height, and number of colors.\n     */\n\n    SetSizeAndColorFromHICON(lpImage->hIcon, lpImage);\n\n    /*\n     * XOR bits follow the header and color table.\n     */\n\n    lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR) lpImage->lpbi);\n\n    /*\n     * AND bits follow the XOR bits.\n     */\n\n    lpImage->lpAND = lpImage->lpXOR +\n\t    lpImage->Height * BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi);\n    return TRUE;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * GetIconFromPixmap --\n *\n *\tTurn a Tk Pixmap (i.e. a bitmap) into an icon resource, if possible,\n *\totherwise NULL is returned.\n *\n * Results:\n *\tA WinIconPtr structure containing a conversion of the given bitmap\n *\tinto an icon, with its ref count already incremented. The calling\n *\tfunction should either place this structure inside a WmInfo structure,\n *\tor it should pass it on to DecrIconRefCount() to ensure no memory\n *\tleaks occur.\n *\n *\tIf the given pixmap did not contain a valid icon structure, return\n *\tNULL.\n *\n * Side effects:\n *\tMemory is allocated for the returned structure and the icons it\n *\tcontains. If the structure is not wanted, it should be passed to\n *\tDecrIconRefCount, and in any case a valid ref count should be ensured\n *\tto avoid memory leaks.\n *\n *\tCurrently icon resources are not shared, so the ref count of one of\n *\tthese structures will always be 0 or 1. However all we need do is\n *\timplement some sort of lookup function between pixmaps and WinIconPtr\n *\tstructures and no other code will need to be changed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic WinIconPtr\nGetIconFromPixmap(\n    Display *dsPtr,\n    Pixmap pixmap)\n{\n    WinIconPtr titlebaricon = NULL;\n    TkWinDrawable *twdPtr = (TkWinDrawable *) pixmap;\n    BlockOfIconImagesPtr lpIR;\n    ICONINFO icon;\n    HICON hIcon;\n    int width, height;\n\n    if (twdPtr == NULL) {\n\treturn NULL;\n    }\n\n#if 0 /* TODO: Dead code?*/\n    if (0 /* If we already have an icon for this pixmap */) {\n\ttitlebaricon = NULL; /* Get the real value from a lookup */\n\ttitlebaricon->refCount++;\n\treturn titlebaricon;\n    }\n#endif\n\n    Tk_SizeOfBitmap(dsPtr, pixmap, &width, &height);\n\n    icon.fIcon = TRUE;\n    icon.xHotspot = 0;\n    icon.yHotspot = 0;\n    icon.hbmMask = twdPtr->bitmap.handle;\n    icon.hbmColor = twdPtr->bitmap.handle;\n\n    hIcon = CreateIconIndirect(&icon);\n    if (hIcon == NULL) {\n\treturn NULL;\n    }\n\n    lpIR = (BlockOfIconImagesPtr)Tcl_Alloc(sizeof(BlockOfIconImages));\n    if (lpIR == NULL) {\n\tDestroyIcon(hIcon);\n\treturn NULL;\n    }\n\n    lpIR->nNumImages = 1;\n    lpIR->IconImages[0].Width = width;\n    lpIR->IconImages[0].Height = height;\n    lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth;\n    lpIR->IconImages[0].hIcon = hIcon;\n\n    /*\n     * These fields are ignored.\n     */\n\n    lpIR->IconImages[0].lpBits = 0;\n    lpIR->IconImages[0].dwNumBytes = 0;\n    lpIR->IconImages[0].lpXOR = 0;\n    lpIR->IconImages[0].lpAND = 0;\n\n    titlebaricon = (WinIconPtr)Tcl_Alloc(sizeof(WinIconInstance));\n    titlebaricon->iconBlock = lpIR;\n    titlebaricon->refCount = 1;\n    return titlebaricon;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * DecrIconRefCount --\n *\n *\tReduces the reference count.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf the ref count falls to zero, free the memory associated with the\n *\ticon resource structures. In this case the pointer passed into this\n *\tfunction is no longer valid.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nDecrIconRefCount(\n    WinIconPtr titlebaricon)\n{\n    if (titlebaricon->refCount-- <= 1) {\n\tif (titlebaricon->iconBlock != NULL) {\n\t    FreeIconBlock(titlebaricon->iconBlock);\n\t}\n\ttitlebaricon->iconBlock = NULL;\n\n\tTcl_Free(titlebaricon);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeIconBlock --\n *\n *\tFrees all memory associated with a previously loaded titlebaricon.\n *\tThe icon block pointer is no longer valid once this function returns.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nFreeIconBlock(\n    BlockOfIconImagesPtr lpIR)\n{\n    int i;\n\n    /*\n     * Free all the bits.\n     */\n\n    for (i=0 ; i<lpIR->nNumImages ; i++) {\n\tif (lpIR->IconImages[i].lpBits != NULL) {\n\t    Tcl_Free(lpIR->IconImages[i].lpBits);\n\t}\n\tif (lpIR->IconImages[i].hIcon != NULL) {\n\t    DestroyIcon(lpIR->IconImages[i].hIcon);\n\t}\n    }\n    Tcl_Free(lpIR);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetIcon --\n *\n *\tExtracts an icon of a given size from an icon resource\n *\n * Results:\n *\tReturns the icon, if found, else NULL.\n *\n *----------------------------------------------------------------------\n */\n\nstatic HICON\nGetIcon(\n    WinIconPtr titlebaricon,\n    int icon_size)\n{\n    BlockOfIconImagesPtr lpIR;\n    unsigned int size = (icon_size == 0 ? 16 : 32);\n    int i;\n\n    if (titlebaricon == NULL) {\n\treturn NULL;\n    }\n\n    lpIR = titlebaricon->iconBlock;\n    if (lpIR == NULL) {\n\treturn NULL;\n    }\n\n    for (i=0 ; i<lpIR->nNumImages ; i++) {\n\t/*\n\t * Take the first or a 32x32 16 color icon\n\t */\n\n\tif ((lpIR->IconImages[i].Height == size)\n\t\t&& (lpIR->IconImages[i].Width == size)\n\t\t&& (lpIR->IconImages[i].Colors >= 4)) {\n\t    return lpIR->IconImages[i].hIcon;\n\t}\n    }\n\n    /*\n     * If we get here, then just return the first one, it will have to do!\n     */\n\n    if (lpIR->nNumImages >= 1) {\n\treturn lpIR->IconImages[0].hIcon;\n    }\n    return NULL;\n}\n\f\n#if 0 /* UNUSED */\nstatic HCURSOR\nTclWinReadCursorFromFile(\n    Tcl_Interp* interp,\n    Tcl_Obj* fileName)\n{\n    BlockOfIconImagesPtr lpIR;\n    HICON res = NULL;\n\n    lpIR = ReadIconOrCursorFromFile(interp, fileName, FALSE);\n    if (lpIR == NULL) {\n\treturn NULL;\n    }\n    if (lpIR->nNumImages >= 1) {\n\tres = CopyImage(lpIR->IconImages[0].hIcon, IMAGE_CURSOR, 0, 0, 0);\n    }\n    FreeIconBlock(lpIR);\n    return res;\n}\n#endif\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ReadIconOrCursorFromFile --\n *\n *\tReads an Icon Resource from an ICO file, as given by char* fileName -\n *\tName of the ICO file. This name should be in Utf format.\n *\n * Results:\n *\tReturns an icon resource, if found, else NULL.\n *\n * Side effects:\n *\tMay leave error messages in the Tcl interpreter.\n *\n *----------------------------------------------------------------------\n */\n\nstatic BlockOfIconImagesPtr\nReadIconOrCursorFromFile(\n    Tcl_Interp *interp,\n    Tcl_Obj *fileName,\n    BOOL isIcon)\n{\n    BlockOfIconImagesPtr lpIR;\n    Tcl_Channel channel;\n    int i;\n    Tcl_Size dwBytesRead;\n    LPICONDIRENTRY lpIDE;\n\n    /*\n     * Open the file.\n     */\n\n    channel = Tcl_FSOpenFileChannel(interp, fileName, \"r\", 0);\n    if (channel == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"error opening file \\\"%s\\\" for reading: %s\",\n\t\tTcl_GetString(fileName), Tcl_PosixError(interp)));\n\treturn NULL;\n    }\n    if (Tcl_SetChannelOption(interp, channel, \"-translation\", \"binary\")\n\t    != TCL_OK) {\n\tTcl_Close(NULL, channel);\n\treturn NULL;\n    }\n\n    /*\n     * Allocate memory for the resource structure\n     */\n\n    lpIR = (BlockOfIconImagesPtr)Tcl_Alloc(sizeof(BlockOfIconImages));\n\n    /*\n     * Read in the header\n     */\n\n    lpIR->nNumImages = ReadICOHeader(channel);\n    if (lpIR->nNumImages == -1) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"Invalid file header\", TCL_INDEX_NONE));\n\tTcl_Close(NULL, channel);\n\tTcl_Free(lpIR);\n\treturn NULL;\n    }\n\n    /*\n     * Adjust the size of the struct to account for the images.\n     */\n\n    lpIR = (BlockOfIconImagesPtr)Tcl_Realloc(lpIR, sizeof(BlockOfIconImages)\n\t    + (lpIR->nNumImages - 1) * sizeof(ICONIMAGE));\n\n    /*\n     * Allocate enough memory for the icon directory entries.\n     */\n\n    lpIDE = (LPICONDIRENTRY)Tcl_Alloc(lpIR->nNumImages * sizeof(ICONDIRENTRY));\n\n    /*\n     * Read in the icon directory entries.\n     */\n\n    dwBytesRead = Tcl_Read(channel, (char *) lpIDE,\n\t    (int) (lpIR->nNumImages * sizeof(ICONDIRENTRY)));\n    if (dwBytesRead != lpIR->nNumImages * (Tcl_Size)sizeof(ICONDIRENTRY)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"error reading file: %s\", Tcl_PosixError(interp)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICON\", \"READ\", (char *)NULL);\n\tTcl_Close(NULL, channel);\n\tTcl_Free(lpIDE);\n\tTcl_Free(lpIR);\n\treturn NULL;\n    }\n\n    /*\n     * NULL-out everything to make memory management easier.\n     */\n\n    for (i = 0; i < lpIR->nNumImages; i++) {\n\tlpIR->IconImages[i].lpBits = NULL;\n    }\n\n    /*\n     * Loop through and read in each image.\n     */\n\n    for (i=0 ; i<lpIR->nNumImages ; i++) {\n\t/*\n\t * Allocate memory for the resource.\n\t */\n\n\tlpIR->IconImages[i].lpBits = (LPBYTE)Tcl_Alloc(lpIDE[i].dwBytesInRes);\n\tlpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes;\n\n\t/*\n\t * Seek to beginning of this image.\n\t */\n\n\tif (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error seeking in file: %s\", Tcl_PosixError(interp)));\n\t    goto readError;\n\t}\n\n\t/*\n\t * Read it in.\n\t */\n\n\tdwBytesRead = Tcl_Read(channel, (char *)lpIR->IconImages[i].lpBits,\n\t\tlpIDE[i].dwBytesInRes);\n\tif (dwBytesRead != lpIDE[i].dwBytesInRes) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"error reading file: %s\", Tcl_PosixError(interp)));\n\t    goto readError;\n\t}\n\n\t/*\n\t * Create the icon from the resource, and set the internal pointers appropriately.\n\t */\n\n\tlpIR->IconImages[i].hIcon =\n\t\tMakeIconOrCursorFromResource(&lpIR->IconImages[i], isIcon);\n\tif (!AdjustIconImagePointers(&lpIR->IconImages[i])) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Error converting to internal format\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICON\", \"FORMAT\", (char *)NULL);\n\t    goto readError;\n\t}\n    }\n\n    /*\n     * Clean up\n     */\n\n    Tcl_Free(lpIDE);\n    Tcl_Close(NULL, channel);\n    return lpIR;\n\n  readError:\n    Tcl_Close(NULL, channel);\n    for (i = 0; i < lpIR->nNumImages; i++) {\n\tif (lpIR->IconImages[i].lpBits != NULL) {\n\t    Tcl_Free(lpIR->IconImages[i].lpBits);\n\t}\n    }\n    Tcl_Free(lpIDE);\n    Tcl_Free(lpIR);\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTopLevel --\n *\n *\tThis function retrieves the TkWindow associated with the given HWND.\n *\n * Results:\n *\tReturns the matching TkWindow.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkWindow *\nGetTopLevel(\n    HWND hwnd)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    /*\n     * If this function is called before the CreateWindowEx call has\n     * completed, then the user data slot will not have been set yet, so we\n     * use the global createWindow variable.\n     */\n\n    if (tsdPtr->createWindow) {\n\treturn tsdPtr->createWindow;\n    }\n    return (TkWindow *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * SetLimits --\n *\n *\tUpdates the minimum and maximum window size constraints.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the values of the info pointer to reflect the current minimum\n *\tand maximum size values.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nSetLimits(\n    HWND hwnd,\n    MINMAXINFO *info)\n{\n    WmInfo *wmPtr;\n    int maxWidth, maxHeight;\n    int minWidth, minHeight;\n    int base;\n    TkWindow *winPtr = GetTopLevel(hwnd);\n\n    if (winPtr == NULL) {\n\treturn;\n    }\n\n    wmPtr = winPtr->wmInfoPtr;\n\n    /*\n     * Copy latest constraint info.\n     */\n\n    wmPtr->defMinWidth = info->ptMinTrackSize.x;\n    wmPtr->defMinHeight = info->ptMinTrackSize.y;\n    wmPtr->defMaxWidth = info->ptMaxTrackSize.x;\n    wmPtr->defMaxHeight = info->ptMaxTrackSize.y;\n\n    GetMaxSize(wmPtr, &maxWidth, &maxHeight);\n    GetMinSize(wmPtr, &minWidth, &minHeight);\n\n    if (wmPtr->gridWin != NULL) {\n\tbase = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tbase += wmPtr->borderWidth;\n\tinfo->ptMinTrackSize.x = base + (minWidth * wmPtr->widthInc);\n\tinfo->ptMaxTrackSize.x = base + (maxWidth * wmPtr->widthInc);\n\n\tbase = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\tbase += wmPtr->borderHeight;\n\tinfo->ptMinTrackSize.y = base + (minHeight * wmPtr->heightInc);\n\tinfo->ptMaxTrackSize.y = base + (maxHeight * wmPtr->heightInc);\n    } else {\n\tinfo->ptMaxTrackSize.x = maxWidth + wmPtr->borderWidth;\n\tinfo->ptMaxTrackSize.y = maxHeight + wmPtr->borderHeight;\n\tinfo->ptMinTrackSize.x = minWidth + wmPtr->borderWidth;\n\tinfo->ptMinTrackSize.y = minHeight + wmPtr->borderHeight;\n    }\n\n    /*\n     * If the window isn't supposed to be resizable, then set the minimum and\n     * maximum dimensions to be the same as the current size.\n     */\n\n    if (!(wmPtr->flags & WM_SYNC_PENDING)) {\n\tif (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {\n\t    info->ptMinTrackSize.x = winPtr->changes.width\n\t\t+ wmPtr->borderWidth;\n\t    info->ptMaxTrackSize.x = info->ptMinTrackSize.x;\n\t}\n\tif (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {\n\t    info->ptMinTrackSize.y = winPtr->changes.height\n\t\t+ wmPtr->borderHeight;\n\t    info->ptMaxTrackSize.y = info->ptMinTrackSize.y;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinWmCleanup --\n *\n *\tUnregisters classes registered by the window manager. This is called\n *\tfrom the DLL main entry point when the DLL is unloaded.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window classes are discarded.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinWmCleanup(\n    HINSTANCE hInstance)\n{\n    ThreadSpecificData *tsdPtr;\n\n    /*\n     * If we're using stubs to access the Tcl library, and they haven't been\n     * initialized, we can't call Tcl_GetThreadData.\n     */\n\n#ifdef USE_TCL_STUBS\n    if (tclStubsPtr == NULL) {\n\treturn;\n    }\n#endif\n\n    if (!initialized) {\n\treturn;\n    }\n    initialized = false;\n\n    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\treturn;\n    }\n    tsdPtr->initialized = false;\n\n    /*\n     * COM library cleanup.\n     */\n\n    CoUninitialize();\n\n    UnregisterClassW(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmNewWindow --\n *\n *\tThis function is invoked whenever a new top-level window is created.\n *\tIts job is to initialize the WmInfo structure for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA WmInfo structure gets allocated and initialized.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmNewWindow(\n    TkWindow *winPtr)\t\t/* Newly-created top-level window. */\n{\n    WmInfo *wmPtr = (WmInfo *)Tcl_Alloc(sizeof(WmInfo));\n\n    /*\n     * Initialize full structure, then set what isn't NULL\n     */\n\n    memset(wmPtr, 0, sizeof(WmInfo));\n    winPtr->wmInfoPtr = wmPtr;\n    wmPtr->winPtr = winPtr;\n    wmPtr->hints.flags = InputHint | StateHint;\n    wmPtr->hints.input = True;\n    wmPtr->hints.initial_state = NormalState;\n    wmPtr->hints.icon_pixmap = None;\n    wmPtr->hints.icon_window = None;\n    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;\n    wmPtr->hints.icon_mask = None;\n    wmPtr->hints.window_group = None;\n\n    /*\n     * Default the maximum dimensions to the size of the display.\n     */\n\n    wmPtr->defMinWidth = wmPtr->defMinHeight = 0;\n    wmPtr->defMaxWidth = DisplayWidth(winPtr->display, winPtr->screenNum);\n    wmPtr->defMaxHeight = DisplayHeight(winPtr->display, winPtr->screenNum);\n    wmPtr->minWidth = wmPtr->minHeight = 1;\n    wmPtr->maxWidth = wmPtr->maxHeight = 0;\n    wmPtr->widthInc = wmPtr->heightInc = 1;\n    wmPtr->minAspect.x = wmPtr->minAspect.y = 1;\n    wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;\n    wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;\n    wmPtr->gravity = NorthWestGravity;\n    wmPtr->width = -1;\n    wmPtr->height = -1;\n    wmPtr->x = winPtr->changes.x;\n    wmPtr->y = winPtr->changes.y;\n    wmPtr->crefObj = NULL;\n    wmPtr->colorref = (COLORREF) 0;\n    wmPtr->alpha = 1.0;\n\n    wmPtr->configWidth = -1;\n    wmPtr->configHeight = -1;\n    wmPtr->flags = WM_NEVER_MAPPED;\n    wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;\n    winPtr->dispPtr->firstWmPtr = wmPtr;\n\n    /*\n     * Tk must monitor structure events for top-level windows, in order to\n     * detect size and position changes caused by window managers.\n     */\n\n    Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,\n\t    TopLevelEventProc, winPtr);\n\n    /*\n     * Arrange for geometry requests to be reflected from the window to the\n     * window manager.\n     */\n\n    Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateWrapper --\n *\n *\tThis function creates the wrapper window that contains the window\n *\tdecorations and menus for a toplevel. This function may be called\n *\tafter a window is mapped to change the window style.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDestroys any old wrapper window and replaces it with a newly created\n *\twrapper.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateWrapper(\n    TkWindow *winPtr)\t\t/* Top-level window to redecorate. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    HWND parentHWND, oldWrapper = wmPtr->wrapper;\n    HWND child, nextHWND, focusHWND;\n    int x, y, width, height, state;\n    WINDOWPLACEMENT place;\n    HICON hSmallIcon = NULL;\n    HICON hBigIcon = NULL;\n    HRESULT hr;\n    Tcl_DString titleString;\n    int *childStateInfo = NULL;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr->window == None) {\n\t/*\n\t * Ensure existence of the window to update the wrapper for.\n\t */\n\n\tTk_MakeWindowExist((Tk_Window) winPtr);\n    }\n\n    child = TkWinGetHWND(winPtr->window);\n    parentHWND = NULL;\n\n    /*\n     * nextHWND will help us maintain Z order. focusHWND will help us maintain\n     * focus, if we had it.\n     */\n\n    nextHWND = NULL;\n    focusHWND = GetFocus();\n    if ((oldWrapper == NULL) || (oldWrapper != GetForegroundWindow())) {\n\tfocusHWND = NULL;\n    }\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\twmPtr->wrapper = (HWND) winPtr->privatePtr;\n\tif (wmPtr->wrapper == NULL) {\n\t    Tcl_Panic(\"UpdateWrapper: Cannot find container window\");\n\t}\n\tif (!IsWindow(wmPtr->wrapper)) {\n\t    Tcl_Panic(\"UpdateWrapper: Container was destroyed\");\n\t}\n    } else {\n\t/*\n\t * Pick the decorative frame style. Override redirect windows get\n\t * created as undecorated popups if they have no transient parent,\n\t * otherwise they are children. This allows splash screens to operate\n\t * as an independent window, while having dropdowns (like for a\n\t * combobox) not grab focus away from their parent. Transient windows\n\t * get a modal dialog frame. Neither override, nor transient windows\n\t * appear in the Windows taskbar. Note that a transient window does\n\t * not resize by default, so we need to explicitly add the\n\t * WS_THICKFRAME style if we want it to be resizeable.\n\t */\n\n\tif (winPtr->atts.override_redirect) {\n\t    wmPtr->style = WM_OVERRIDE_STYLE;\n\t    wmPtr->exStyle = EX_OVERRIDE_STYLE;\n\n\t    /*\n\t     * Parent must be desktop even if we have a transient parent.\n\t     */\n\n\t    parentHWND = GetDesktopWindow();\n\t    if (wmPtr->containerPtr) {\n\t\twmPtr->style |= WS_CHILD;\n\t    } else {\n\t\twmPtr->style |= WS_POPUP;\n\t    }\n\t} else if (wmPtr->flags & WM_FULLSCREEN) {\n\t    wmPtr->style = WM_FULLSCREEN_STYLE;\n\t    wmPtr->exStyle = EX_FULLSCREEN_STYLE;\n\t} else if (wmPtr->containerPtr) {\n\t    wmPtr->style = WM_TRANSIENT_STYLE;\n\t    wmPtr->exStyle = EX_TRANSIENT_STYLE;\n\t    parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->containerPtr));\n\t    if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)\n\t\t    && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {\n\t\twmPtr->style |= WS_THICKFRAME;\n\t    }\n\t} else {\n\t    wmPtr->style = WM_TOPLEVEL_STYLE;\n\t    wmPtr->exStyle = EX_TOPLEVEL_STYLE;\n\t}\n\n\twmPtr->style |= wmPtr->styleConfig;\n\twmPtr->exStyle |= wmPtr->exStyleConfig;\n\n\tif ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)\n\t\t&& (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {\n\t    wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX);\n\t}\n\n\t/*\n\t * Compute the geometry of the parent and child windows.\n\t */\n\n\twmPtr->flags |= WM_CREATE_PENDING|WM_MOVE_PENDING;\n\tUpdateGeometryInfo(winPtr);\n\twmPtr->flags &= ~(WM_CREATE_PENDING|WM_MOVE_PENDING);\n\n\twidth = wmPtr->borderWidth + winPtr->changes.width;\n\theight = wmPtr->borderHeight + winPtr->changes.height;\n\n\t/*\n\t * Set the initial position from the user or program specified\n\t * location. If nothing has been specified, then let the system pick a\n\t * location. In full screen mode the x,y origin is 0,0 and the window\n\t * width and height match that of the screen.\n\t */\n\n\tif (wmPtr->flags & WM_FULLSCREEN) {\n\t    x = 0;\n\t    y = 0;\n\t    width = WidthOfScreen(Tk_Screen(winPtr));\n\t    height = HeightOfScreen(Tk_Screen(winPtr));\n\t} else if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))\n\t\t&& (wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    x = CW_USEDEFAULT;\n\t    y = CW_USEDEFAULT;\n\t} else {\n\t    x = winPtr->changes.x;\n\t    y = winPtr->changes.y;\n\t}\n\n\t/*\n\t * Create the containing window, and set the user data to point to the\n\t * TkWindow.\n\t */\n\n\ttsdPtr->createWindow = winPtr;\n\tTcl_DStringInit(&titleString);\n\tTcl_UtfToWCharDString(((wmPtr->title != NULL) ?\n\t\twmPtr->title : winPtr->nameUid), TCL_INDEX_NONE, &titleString);\n\n\twmPtr->wrapper = CreateWindowExW(wmPtr->exStyle,\n\t\tTK_WIN_TOPLEVEL_CLASS_NAME,\n\t\t(LPCWSTR) Tcl_DStringValue(&titleString),\n\t\twmPtr->style, x, y, width, height,\n\t\tparentHWND, NULL, Tk_GetHINSTANCE(), NULL);\n\tTcl_DStringFree(&titleString);\n\tSetWindowLongPtrW(wmPtr->wrapper, GWLP_USERDATA, (LONG_PTR) winPtr);\n\ttsdPtr->createWindow = NULL;\n\n\tif (wmPtr->exStyleConfig & WS_EX_LAYERED) {\n\t    /*\n\t     * The user supplies a double from [0..1], but Windows wants an\n\t     * int (transparent) 0..255 (opaque), so do the translation. Add\n\t     * the 0.5 to round the value.\n\t     */\n\n\t    SetLayeredWindowAttributes((HWND) wmPtr->wrapper,\n\t\t    wmPtr->colorref, (BYTE) (wmPtr->alpha * 255 + 0.5),\n\t\t    (unsigned)(LWA_ALPHA | (wmPtr->crefObj?LWA_COLORKEY:0)));\n\t} else {\n\t    /*\n\t     * Layering not used or supported.\n\t     */\n\n\t    wmPtr->alpha = 1.0;\n\t    if (wmPtr->crefObj) {\n\t\tTcl_DecrRefCount(wmPtr->crefObj);\n\t\twmPtr->crefObj = NULL;\n\t    }\n\t}\n\n\tplace.length = sizeof(WINDOWPLACEMENT);\n\tGetWindowPlacement(wmPtr->wrapper, &place);\n\twmPtr->x = place.rcNormalPosition.left;\n\twmPtr->y = place.rcNormalPosition.top;\n\n\tif (!(winPtr->flags & TK_ALREADY_DEAD)) {\n\t    TkInstallFrameMenu((Tk_Window) winPtr);\n\t}\n\n\tif (oldWrapper && (oldWrapper != wmPtr->wrapper)\n\t\t&& !(wmPtr->exStyle & WS_EX_TOPMOST)) {\n\t    /*\n\t     * We will adjust wrapper to have the same Z order as oldWrapper\n\t     * if it isn't a TOPMOST window.\n\t     */\n\n\t    nextHWND = GetNextWindow(oldWrapper, GW_HWNDPREV);\n\t}\n    }\n\n    /*\n     * Now we need to reparent the contained window and set its style\n     * appropriately. Be sure to update the style first so that Windows\n     * doesn't try to set the focus to the child window.\n     */\n\n    SetWindowLongPtrW(child, GWL_STYLE,\n\t    WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\tSetWindowLongPtrW(child, GWLP_WNDPROC, (LONG_PTR) TopLevelProc);\n    }\n\n    SetParent(child, wmPtr->wrapper);\n    if (oldWrapper) {\n\thSmallIcon = (HICON)\n\t\tSendMessageW(oldWrapper, WM_GETICON, ICON_SMALL, (LPARAM)NULL);\n\thBigIcon = (HICON)\n\t\tSendMessageW(oldWrapper, WM_GETICON, ICON_BIG, (LPARAM) NULL);\n    }\n\n    if (oldWrapper && (oldWrapper != wmPtr->wrapper)\n\t    && (oldWrapper != GetDesktopWindow())) {\n\tSetWindowLongPtrW(oldWrapper, GWLP_USERDATA, (LONG_PTR) 0);\n\n\tif (wmPtr->numTransients > 0) {\n\t    /*\n\t     * Unset the current wrapper as the parent for all transient\n\t     * children for whom this is the container\n\t     */\n\n\t    WmInfo *wmPtr2;\n\n\t    childStateInfo = (int *)Tcl_Alloc(wmPtr->numTransients * sizeof(int));\n\t    state = 0;\n\t    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;\n\t\t    wmPtr2 = wmPtr2->nextPtr) {\n\t\tif (wmPtr2->containerPtr == winPtr\n\t\t\t&& !(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t\t    childStateInfo[state++] = wmPtr2->hints.initial_state;\n\t\t    SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);\n\t\t}\n\t    }\n\t}\n\n\t/*\n\t * Remove the menubar before destroying the window so the menubar\n\t * isn't destroyed.\n\t */\n\n\tSetMenu(oldWrapper, NULL);\n\tDestroyWindow(oldWrapper);\n    }\n\n    wmPtr->flags &= ~WM_NEVER_MAPPED;\n    if (winPtr->flags & TK_EMBEDDED &&\n\t    SendMessageW(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0)) {\n\tSendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ,\n\t\tTk_ReqWidth((Tk_Window) winPtr),\n\t\tTk_ReqHeight((Tk_Window) winPtr));\n\tSendMessageW(wmPtr->wrapper, TK_SETMENU, (WPARAM) wmPtr->hMenu,\n\t\t(LPARAM) TkGetMenuHWND((Tk_Window) winPtr));\n    }\n\n    /*\n     * Force an initial transition from withdrawn to the real initial state.\n     * Set the Z order based on previous wrapper before we set the state.\n     */\n\n    state = wmPtr->hints.initial_state;\n    wmPtr->hints.initial_state = WithdrawnState;\n    if (nextHWND) {\n\tSetWindowPos(wmPtr->wrapper, nextHWND, 0, 0, 0, 0,\n\t\tSWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOSENDCHANGING\n\t\t|SWP_NOOWNERZORDER);\n    }\n    TkpWmSetState(winPtr, state);\n    wmPtr->hints.initial_state = state;\n\n    if (hSmallIcon != NULL) {\n\tSendMessageW(wmPtr->wrapper, WM_SETICON, ICON_SMALL,\n\t\t(LPARAM) hSmallIcon);\n    }\n    if (hBigIcon != NULL) {\n\tSendMessageW(wmPtr->wrapper, WM_SETICON, ICON_BIG, (LPARAM) hBigIcon);\n    }\n\n    /*\n     * If we are embedded then force a mapping of the window now, because we\n     * do not necessarily own the wrapper and may not get another opportunity\n     * to map ourselves. We should not be in either iconified or zoomed states\n     * when we get here, so it is safe to just check for TK_EMBEDDED without\n     * checking what state we are supposed to be in (default to NormalState).\n     */\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\tif (state+1 != SendMessageW(wmPtr->wrapper, TK_STATE, state, 0)) {\n\t    TkpWmSetState(winPtr, NormalState);\n\t    wmPtr->hints.initial_state = NormalState;\n\t}\n\tXMapWindow(winPtr->display, winPtr->window);\n    }\n\n    /*\n     * Set up menus on the wrapper if required.\n     */\n\n    if (wmPtr->hMenu != NULL) {\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tSetMenu(wmPtr->wrapper, wmPtr->hMenu);\n\twmPtr->flags &= ~WM_SYNC_PENDING;\n    }\n\n    if (childStateInfo) {\n\tif (wmPtr->numTransients > 0) {\n\t    /*\n\t     * Reset all transient children for whom this is the container.\n\t     */\n\n\t    WmInfo *wmPtr2;\n\n\t    state = 0;\n\t    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;\n\t\t    wmPtr2 = wmPtr2->nextPtr) {\n\t\tif (wmPtr2->containerPtr == winPtr\n\t\t\t&& !(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t\t    UpdateWrapper(wmPtr2->winPtr);\n\t\t    TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);\n\t\t}\n\t    }\n\t}\n\n\tTcl_Free(childStateInfo);\n    }\n\n    /*\n     * If this is the first window created by the application, then we should\n     * activate the initial window. Otherwise, if this had the focus, we need\n     * to restore that.\n     * XXX: Rewrapping generates a <FocusOut> and <FocusIn> that would best be\n     * XXX: avoided, if we could safely mask them.\n     */\n\n    if (tsdPtr->firstWindow) {\n\ttsdPtr->firstWindow = 0;\n\tSetActiveWindow(wmPtr->wrapper);\n    } else if (focusHWND) {\n\tSetFocus(focusHWND);\n    }\n\n    /*\n     * Initialize hooks for overlay icon.\n     * Start with TaskbarButtonCreated message.\n     */\n\n    TaskbarButtonCreatedMessageId = RegisterWindowMessage(TEXT(\"TaskbarButtonCreated\"));\n\n    /*\n     * In case the application is run elevated, allow the\n     * TaskbarButtonCreated message through.\n     */\n\n    ChangeWindowMessageFilter(TaskbarButtonCreatedMessageId, MSGFLT_ADD);\n\n    /*\n     * Load COM library for icon overlay.\n     */\n\n    hr = CoInitialize(0);\n    if (SUCCEEDED(hr)) {\n\thr = CoCreateInstance(&CLSID_TaskbarList, NULL,\n\t\tCLSCTX_INPROC_SERVER, &IID_ITaskbarList3, (void **) &ptbl);\n\tif (FAILED(hr)) {\n\t    printf(\"Unable to initialize ITaskbarList3 API\");\n\t    ptbl->lpVtbl->Release(NULL);\n\t    ptbl = NULL;\n\t}\n    }\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmMapWindow --\n *\n *\tThis function is invoked to map a top-level window. This module gets a\n *\tchance to update all window-manager-related information in properties\n *\tbefore the window manager sees the map event and checks the\n *\tproperties. It also gets to decide whether or not to even map the\n *\twindow after all.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tProperties of winPtr may get updated to provide up-to-date information\n *\tto the window manager. The window may also get mapped, but it may not\n *\tbe if this function decides that isn't appropriate (e.g. because the\n *\twindow is withdrawn).\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmMapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * mapped. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (!tsdPtr->initialized) {\n\tInitWm();\n    }\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\t/*\n\t * Don't map a transient if the container is not mapped.\n\t */\n\n\tif (wmPtr->containerPtr != NULL && !Tk_IsMapped(wmPtr->containerPtr)) {\n\t    wmPtr->hints.initial_state = WithdrawnState;\n\t    return;\n\t}\n    } else {\n\tif (wmPtr->hints.initial_state == WithdrawnState) {\n\t    return;\n\t}\n\n\t/*\n\t * Map the window in either the iconified or normal state. Note that\n\t * we only send a map event if the window is in the normal state.\n\t */\n\n\tTkpWmSetState(winPtr, wmPtr->hints.initial_state);\n    }\n\n    /*\n     * This is the first time this window has ever been mapped. Store all the\n     * window-manager-related information for the window.\n     */\n\n    UpdateWrapper(winPtr);\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmUnmapWindow --\n *\n *\tThis function is invoked to unmap a top-level window. The only thing\n *\tit does special is unmap the decorative frame before unmapping the\n *\ttoplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUnmaps the decorative frame and the window.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmUnmapWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's about to be\n\t\t\t\t * unmapped. */\n{\n    TkpWmSetState(winPtr, WithdrawnState);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWmSetState --\n *\n *\tSets the window manager state for the wrapper window of a given\n *\ttoplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay maximize, minimize, restore, or withdraw a window.\n *\n *----------------------------------------------------------------------\n */\n\nbool\nTkpWmSetState(\n    TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n    int state)\t\t\t/* One of IconicState, ZoomState, NormalState,\n\t\t\t\t * or WithdrawnState. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int cmd;\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\twmPtr->hints.initial_state = state;\n\tgoto setStateEnd;\n    }\n\n    wmPtr->flags |= WM_SYNC_PENDING;\n    if (state == WithdrawnState) {\n\tcmd = SW_HIDE;\n    } else if (state == IconicState) {\n\tcmd = SW_SHOWMINNOACTIVE;\n    } else if (state == NormalState) {\n\tcmd = SW_SHOWNOACTIVATE;\n    } else if (state == ZoomState) {\n\tcmd = SW_SHOWMAXIMIZED;\n    } else {\n\tgoto setStateEnd;\n    }\n\n    ShowWindow(wmPtr->wrapper, cmd);\n    wmPtr->flags &= ~WM_SYNC_PENDING;\nsetStateEnd:\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWmSetFullScreen --\n *\n *\tSets the fullscreen state for a toplevel window.\n *\n * Results:\n *\tThe WM_FULLSCREEN flag is updated.\n *\n * Side effects:\n *\tMay create a new wrapper window and raise it.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkpWmSetFullScreen(\n    TkWindow *winPtr,\t\t/* Toplevel window to operate on. */\n    int full_screen_state)\t/* True if window should be full screen */\n{\n    int changed = 0;\n    int full_screen = False;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (full_screen_state) {\n\tif (! (wmPtr->flags & WM_FULLSCREEN)) {\n\t    full_screen = True;\n\t    changed = 1;\n\t}\n    } else {\n\tif (wmPtr->flags & WM_FULLSCREEN) {\n\t    full_screen = False;\n\t    changed = 1;\n\t}\n    }\n\n    if (changed) {\n\tif (full_screen) {\n\t    wmPtr->flags |= WM_FULLSCREEN;\n\t    wmPtr->configX = wmPtr->x;\n\t    wmPtr->configY = wmPtr->y;\n\t} else {\n\t    wmPtr->flags &= ~WM_FULLSCREEN;\n\t    wmPtr->x = wmPtr->configX;\n\t    wmPtr->y = wmPtr->configY;\n\t}\n\n\t/*\n\t * If the window has been mapped, then we need to update the native\n\t * wrapper window, and reset the focus to the widget that had it\n\t * before.\n\t */\n\n\tif (!(wmPtr->flags & (WM_NEVER_MAPPED)\n\t\t&& !(winPtr->flags & TK_EMBEDDED))) {\n\t    TkWindow *focusWinPtr;\n\n\t    UpdateWrapper(winPtr);\n\n\t    focusWinPtr = TkGetFocusWin(winPtr);\n\t    if (focusWinPtr) {\n\t\tTkSetFocusWin(focusWinPtr, 1);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinGetState --\n *\n *\tThis function returns state value of a toplevel window.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tMay deiconify the toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkpWmGetState(\n    TkWindow *winPtr)\n{\n    return winPtr->wmInfoPtr->hints.initial_state;\n}\n\n/*\n *--------------------------------------------------------------\n *\n * TkWmDeadWindow --\n *\n *\tThis function is invoked when a top-level window is about to be\n *\tdeleted. It cleans up the wm-related data structures for the window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe WmInfo structure for winPtr gets freed up.\n *\n *--------------------------------------------------------------\n */\n\nstatic void CheckForPointer(TkWindow *winPtr)\n{\n    if (winPtr == NULL || winPtr->mainPtr == NULL) {\n\t/*\n\t * Bug [d233f01e2a] - clipboard clean up after main window destroyed\n\t * Nothing to do.\n\t */\n\treturn;\n    }\n\n    POINT mouse;\n    int x, y;\n    unsigned int state = TkWinGetModifierState();\n    TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);\n    TkWindow **w;\n    TkGetPointerCoords(NULL, &x, &y);\n    mouse.x = x;\n    mouse.y = y;\n    if (windows != NULL) {\n\tfor (w = windows; *w ; w++) {\n\t    RECT windowRect;\n\t    HWND hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) *w));\n\t    if (GetWindowRect(hwnd, &windowRect) == 0) {\n\t\tcontinue;\n\t    }\n\t    if (winPtr != *w && PtInRect(&windowRect, mouse)) {\n\t\tTk_Window target = Tk_CoordsToWindow(x, y, (Tk_Window) *w);\n\t\tTk_UpdatePointer((Tk_Window) target, x, y, state);\n\t\tbreak;\n\t    }\n\t}\n\tTcl_Free(windows);\n    }\n}\n\nvoid\nTkWmDeadWindow(\n    TkWindow *winPtr)\t\t/* Top-level window that's being deleted. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    WmInfo *wmPtr2;\n\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Clean up event related window info.\n     */\n\n    if (winPtr->dispPtr->firstWmPtr == wmPtr) {\n\twinPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;\n    } else {\n\tWmInfo *prevPtr;\n\n\tfor (prevPtr = winPtr->dispPtr->firstWmPtr; ;\n\t\tprevPtr = prevPtr->nextPtr) {\n\t    if (prevPtr == NULL) {\n\t\tTcl_Panic(\"couldn't unlink window in TkWmDeadWindow\");\n\t    }\n\t    if (prevPtr->nextPtr == wmPtr) {\n\t\tprevPtr->nextPtr = wmPtr->nextPtr;\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /*\n     * Reset all transient windows whose container is the dead window.\n     */\n\n    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;\n\t wmPtr2 = wmPtr2->nextPtr) {\n\tif (wmPtr2->containerPtr == winPtr) {\n\t    wmPtr->numTransients--;\n\t    Tk_DeleteEventHandler((Tk_Window) wmPtr2->containerPtr,\n\t\t    VisibilityChangeMask|StructureNotifyMask,\n\t\t    WmWaitVisibilityOrMapProc, wmPtr2->winPtr);\n\t    wmPtr2->containerPtr = NULL;\n\t    if ((wmPtr2->wrapper != NULL)\n\t\t    && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {\n\t\tUpdateWrapper(wmPtr2->winPtr);\n\t    }\n\t}\n    }\n    if (wmPtr->numTransients != 0) {\n\tTcl_Panic(\"numTransients should be 0\");\n    }\n\n    if (wmPtr->title != NULL) {\n\tTcl_Free(wmPtr->title);\n    }\n    if (wmPtr->iconName != NULL) {\n\tTcl_Free(wmPtr->iconName);\n    }\n    if (wmPtr->hints.flags & IconPixmapHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n    }\n    if (wmPtr->hints.flags & IconMaskHint) {\n\tTk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n    }\n    if (wmPtr->leaderName != NULL) {\n\tTcl_Free(wmPtr->leaderName);\n    }\n    if (wmPtr->icon != NULL) {\n\twmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\twmPtr2->iconFor = NULL;\n    }\n    if (wmPtr->iconFor != NULL) {\n\twmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;\n\twmPtr2->icon = NULL;\n\twmPtr2->hints.flags &= ~IconWindowHint;\n    }\n    while (wmPtr->protPtr != NULL) {\n\tProtocolHandler *protPtr;\n\n\tprotPtr = wmPtr->protPtr;\n\twmPtr->protPtr = protPtr->nextPtr;\n\tTcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n    }\n    if (wmPtr->cmdArgv != NULL) {\n\tTcl_Free(wmPtr->cmdArgv);\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    if (wmPtr->flags & WM_UPDATE_PENDING) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n    }\n    if (wmPtr->containerPtr != NULL) {\n\twmPtr2 = wmPtr->containerPtr->wmInfoPtr;\n\n\t/*\n\t * If we had a container, tell them that we aren't tied to them anymore.\n\t */\n\n\tif (wmPtr2 != NULL) {\n\t    wmPtr2->numTransients--;\n\t}\n\tTk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,\n\t\tVisibilityChangeMask|StructureNotifyMask,\n\t\tWmWaitVisibilityOrMapProc, winPtr);\n\twmPtr->containerPtr = NULL;\n    }\n    if (wmPtr->crefObj != NULL) {\n\tTcl_DecrRefCount(wmPtr->crefObj);\n\twmPtr->crefObj = NULL;\n    }\n\n    /*\n     * Destroy the decorative frame window.\n     */\n\n    if (!(winPtr->flags & TK_EMBEDDED)) {\n\tif (wmPtr->wrapper != NULL) {\n\t    DestroyWindow(wmPtr->wrapper);\n\t} else if (winPtr->window) {\n\t    DestroyWindow(Tk_GetHWND(winPtr->window));\n\t}\n    } else {\n\tif (wmPtr->wrapper != NULL) {\n\t    SendMessageW(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);\n\t}\n    }\n    if (wmPtr->iconPtr != NULL) {\n\t/*\n\t * This may delete the icon resource data. I believe we should do this\n\t * after destroying the decorative frame, because the decorative frame\n\t * is using this icon.\n\t */\n\n\tDecrIconRefCount(wmPtr->iconPtr);\n    }\n\n    /*\n     * Check if the dead window is a toplevel containing the pointer.  If so,\n     * find the window which will inherit the pointer and call\n     * TkUpdatePointer.\n     */\n\n    CheckForPointer(winPtr);\n    Tcl_Free(wmPtr);\n    winPtr->wmInfoPtr = NULL;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * TkWmSetClass --\n *\n *\tThis function is invoked whenever a top-level window's class is\n *\tchanged. If the window has been mapped then this function updates the\n *\twindow manager property for the class. If the window hasn't been\n *\tmapped, the update is deferred until just before the first mapping.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tA window property may get updated.\n *\n *--------------------------------------------------------------\n */\n\nvoid\nTkWmSetClass(\n    TCL_UNUSED(TkWindow *))\t/* Newly-created top-level window. */\n{\n    /* Do nothing */\n    return;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_WmObjCmd --\n *\n *\tThis function is invoked to process the \"wm\" Tcl command. See the user\n *\tdocumentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTk_WmObjCmd(\n    void *clientData,\t/* Main window associated with interpreter. */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    Tk_Window tkwin = (Tk_Window)clientData;\n    static const char *const optionStrings[] = {\n\t\"aspect\", \"attributes\", \"client\", \"colormapwindows\",\n\t\"command\", \"deiconify\", \"focusmodel\", \"forget\", \"frame\",\n\t\"geometry\", \"grid\", \"group\", \"iconbadge\", \"iconbitmap\",\n\t\"iconify\", \"iconmask\", \"iconname\",\n\t\"iconphoto\", \"iconposition\",\n\t\"iconwindow\", \"manage\", \"maxsize\", \"minsize\", \"overrideredirect\",\n\t\"positionfrom\", \"protocol\", \"resizable\", \"sizefrom\",\n\t\"stackorder\", \"state\", \"title\", \"transient\",\n\t\"withdraw\", NULL\n    };\n    enum options {\n\tWMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,\n\tWMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET,\n\tWMOPT_FRAME,\n\tWMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBADGE, WMOPT_ICONBITMAP,\n\tWMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME,\n\tWMOPT_ICONPHOTO, WMOPT_ICONPOSITION,\n\tWMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE,\n\tWMOPT_OVERRIDEREDIRECT,\n\tWMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM,\n\tWMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT,\n\tWMOPT_WITHDRAW\n    };\n    int index;\n    Tcl_Size length;\n    const char *argv1;\n    TkWindow *winPtr, **winPtrPtr = &winPtr;\n    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;\n\n    if (objc < 2) {\n    wrongNumArgs:\n\tTcl_WrongNumArgs(interp, 1, objv, \"option window ?arg ...?\");\n\treturn TCL_ERROR;\n    }\n\n    argv1 = Tcl_GetStringFromObj(objv[1], &length);\n    if ((argv1[0] == 't') && !strncmp(argv1, \"tracing\", length)\n\t    && (length >= 3)) {\n\tint wmTracing;\n\n\tif ((objc != 2) && (objc != 3)) {\n\t    Tcl_WrongNumArgs(interp, 2, objv, \"?boolean?\");\n\t    return TCL_ERROR;\n\t}\n\tif (objc == 2) {\n\t    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(\n\t\t    dispPtr->flags & TK_DISPLAY_WM_TRACING));\n\t    return TCL_OK;\n\t}\n\tif (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (wmTracing) {\n\t    dispPtr->flags |= TK_DISPLAY_WM_TRACING;\n\t} else {\n\t    dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;\n\t}\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings,\n\t    \"option\", 0, &index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n\n    if (objc < 3) {\n\tgoto wrongNumArgs;\n    }\n\n    if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) winPtrPtr)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (!Tk_IsTopLevel(winPtr) && (index != WMOPT_MANAGE)\n\t    && (index != WMOPT_FORGET)) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"window \\\"%s\\\" isn't a top-level window\", winPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"LOOKUP\", \"TOPLEVEL\", winPtr->pathName,\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    switch ((enum options) index) {\n    case WMOPT_ASPECT:\n\treturn WmAspectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ATTRIBUTES:\n\treturn WmAttributesCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_CLIENT:\n\treturn WmClientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COLORMAPWINDOWS:\n\treturn WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_COMMAND:\n\treturn WmCommandCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_DEICONIFY:\n\treturn WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FOCUSMODEL:\n\treturn WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FORGET:\n\treturn WmForgetCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_FRAME:\n\treturn WmFrameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GEOMETRY:\n\treturn WmGeometryCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GRID:\n\treturn WmGridCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_GROUP:\n\treturn WmGroupCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBADGE:\n\treturn WmIconbadgeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONBITMAP:\n\treturn WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONIFY:\n\treturn WmIconifyCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONMASK:\n\treturn WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONNAME:\n\treturn WmIconnameCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPHOTO:\n\treturn WmIconphotoCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONPOSITION:\n\treturn WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_ICONWINDOW:\n\treturn WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MANAGE:\n\treturn WmManageCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MAXSIZE:\n\treturn WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_MINSIZE:\n\treturn WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_OVERRIDEREDIRECT:\n\treturn WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_POSITIONFROM:\n\treturn WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_PROTOCOL:\n\treturn WmProtocolCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_RESIZABLE:\n\treturn WmResizableCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_SIZEFROM:\n\treturn WmSizefromCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STACKORDER:\n\treturn WmStackorderCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_STATE:\n\treturn WmStateCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TITLE:\n\treturn WmTitleCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_TRANSIENT:\n\treturn WmTransientCmd(tkwin, winPtr, interp, objc, objv);\n    case WMOPT_WITHDRAW:\n\treturn WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);\n    }\n\n    /* This should not happen */\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAspectCmd --\n *\n *\tThis function is invoked to process the \"wm aspect\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAspectCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int numer1, denom1, numer2, denom2;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?minNumer minDenom maxNumer maxDenom?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PAspect) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~PAspect;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || (denom2 <= 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"aspect number can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"ASPECT\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr->minAspect.x = numer1;\n\twmPtr->minAspect.y = denom1;\n\twmPtr->maxAspect.x = numer2;\n\twmPtr->maxAspect.y = denom2;\n\twmPtr->sizeHintsFlags |= PAspect;\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmAttributesCmd --\n *\n *\tThis function is invoked to process the \"wm attributes\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmAttributesCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    LONG style, exStyle, styleBit, *stylePtr = NULL;\n    const char *string;\n    int boolValue;\n    Tcl_Size i, length;\n    int config_fullscreen = 0, updatewrapper = 0;\n    int fullscreen_attr_changed = 0, fullscreen_attr = 0;\n\n    if ((objc < 3) || ((objc > 5) && ((objc%2) == 0))) {\n    configArgs:\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window\"\n\t\t\" ?-alpha ?double??\"\n\t\t\" ?-transparentcolor ?color??\"\n\t\t\" ?-disabled ?bool??\"\n\t\t\" ?-fullscreen ?bool??\"\n\t\t\" ?-toolwindow ?bool??\"\n\t\t\" ?-topmost ?bool??\");\n\treturn TCL_ERROR;\n    }\n    exStyle = wmPtr->exStyleConfig;\n    style = wmPtr->styleConfig;\n    if (objc == 3) {\n\tTcl_Obj *objPtr = Tcl_NewObj();\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-alpha\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr, Tcl_NewDoubleObj(wmPtr->alpha));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-transparentcolor\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\twmPtr->crefObj ? wmPtr->crefObj : Tcl_NewObj());\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-disabled\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewBooleanObj(style & WS_DISABLED));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-fullscreen\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewBooleanObj(wmPtr->flags & WM_FULLSCREEN));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-toolwindow\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewBooleanObj(exStyle & WS_EX_TOOLWINDOW));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewStringObj(\"-topmost\", TCL_INDEX_NONE));\n\tTcl_ListObjAppendElement(NULL, objPtr,\n\t\tTcl_NewBooleanObj(exStyle & WS_EX_TOPMOST));\n\tTcl_SetObjResult(interp, objPtr);\n\treturn TCL_OK;\n    }\n    for (i = 3; i < objc; i += 2) {\n\tstring = Tcl_GetStringFromObj(objv[i], &length);\n\tif (strncmp(string, \"-disabled\", length) == 0) {\n\t    stylePtr = &style;\n\t    styleBit = WS_DISABLED;\n\t} else if ((strncmp(string, \"-alpha\", length) == 0)\n\t\t|| ((length > 2) && (strncmp(string, \"-transparentcolor\",\n\t\t\tlength) == 0))) {\n\t    stylePtr = &exStyle;\n\t    styleBit = WS_EX_LAYERED;\n\t} else if (strncmp(string, \"-fullscreen\", length) == 0) {\n\t    config_fullscreen = 1;\n\t    styleBit = 0;\n\t} else if ((length > 3)\n\t\t&& (strncmp(string, \"-toolwindow\", length) == 0)) {\n\t    stylePtr = &exStyle;\n\t    styleBit = WS_EX_TOOLWINDOW;\n\t    if (objc != 4) {\n\t\t/*\n\t\t * Changes to toolwindow style require an update\n\t\t */\n\t\tupdatewrapper = 1;\n\t    }\n\t} else if ((length > 3)\n\t\t&& (strncmp(string, \"-topmost\", length) == 0)) {\n\t    stylePtr = &exStyle;\n\t    styleBit = WS_EX_TOPMOST;\n\t    if ((i < objc-1) && (winPtr->flags & TK_EMBEDDED)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't set topmost flag on %s: it is an embedded window\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ATTR\", \"TOPMOST\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t} else if (i == 3) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"bad attribute \\\"%s\\\": must be -alpha, -disabled, -fullscreen, -toolwindow, -topmost, or -transparentcolor\",\n\t\t    string));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ATTR\", \"UNRECOGNIZED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t} else {\n\t    goto configArgs;\n\t}\n\tif (styleBit == WS_EX_LAYERED) {\n\t    if (objc == 4) {\n\t\tif (string[1] == 'a') {\t\t/* -alpha */\n\t\t    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(wmPtr->alpha));\n\t\t} else {\t\t\t/* -transparentcolor */\n\t\t    Tcl_SetObjResult(interp,\n\t\t\t    wmPtr->crefObj ? wmPtr->crefObj : Tcl_NewObj());\n\t\t}\n\t    } else {\n\t\tif (string[1] == 'a') {\t\t/* -alpha */\n\t\t    double dval;\n\n\t\t    if (Tcl_GetDoubleFromObj(interp, objv[i+1], &dval)\n\t\t\t    != TCL_OK) {\n\t\t\treturn TCL_ERROR;\n\t\t    }\n\n\t\t    /*\n\t\t     * The user should give (transparent) 0 .. 1.0 (opaque),\n\t\t     * but we ignore the setting of this (it will always be 1)\n\t\t     * in the case that the API is not available.\n\t\t     */\n\t\t    if (dval < 0.0) {\n\t\t\tdval = 0;\n\t\t    } else if (dval > 1.0) {\n\t\t\tdval = 1;\n\t\t    }\n\t\t    wmPtr->alpha = dval;\n\t\t} else {\t\t\t/* -transparentcolor */\n\t\t    (void)Tcl_GetStringFromObj(objv[i+1], &length);\n\n\t\t    if (length == 0) {\n\t\t\t/* reset to no transparent color */\n\t\t\tif (wmPtr->crefObj) {\n\t\t\t    Tcl_DecrRefCount(wmPtr->crefObj);\n\t\t\t    wmPtr->crefObj = NULL;\n\t\t\t}\n\t\t    } else {\n\t\t\tXColor *cPtr =\n\t\t\t    Tk_AllocColorFromObj(interp, tkwin, objv[i+1]);\n\t\t\tif (cPtr == NULL) {\n\t\t\t    return TCL_ERROR;\n\t\t\t}\n\n\t\t\tif (wmPtr->crefObj) {\n\t\t\t    Tcl_DecrRefCount(wmPtr->crefObj);\n\t\t\t}\n\t\t\twmPtr->crefObj = objv[i+1];\n\t\t\tTcl_IncrRefCount(wmPtr->crefObj);\n\t\t\twmPtr->colorref = RGB((BYTE) (cPtr->red >> 8),\n\t\t\t\t(BYTE) (cPtr->green >> 8),\n\t\t\t\t(BYTE) (cPtr->blue >> 8));\n\t\t\tTk_FreeColor(cPtr);\n\t\t    }\n\t\t}\n\n\t\t/*\n\t\t * Only ever add the WS_EX_LAYERED bit, as it can cause\n\t\t * flashing to change this window style. This allows things\n\t\t * like fading tooltips to avoid flash ugliness without\n\t\t * forcing all window to be layered.\n\t\t */\n\n\t\tif ((wmPtr->alpha < 1.0) || (wmPtr->crefObj != NULL)) {\n\t\t    *stylePtr |= styleBit;\n\t\t}\n\t\tif (wmPtr->wrapper != NULL) {\n\t\t    /*\n\t\t     * Set the window directly regardless of UpdateWrapper.\n\t\t     * The user supplies a double from [0..1], but Windows\n\t\t     * wants an int (transparent) 0..255 (opaque), so do the\n\t\t     * translation. Add the 0.5 to round the value.\n\t\t     */\n\n\t\t    if (!(wmPtr->exStyleConfig & WS_EX_LAYERED)) {\n\t\t\tSetWindowLongPtrW(wmPtr->wrapper, GWL_EXSTYLE,\n\t\t\t\t*stylePtr);\n\t\t    }\n\t\t    SetLayeredWindowAttributes((HWND) wmPtr->wrapper,\n\t\t\t    wmPtr->colorref, (BYTE) (wmPtr->alpha * 255 + 0.5),\n\t\t\t    (unsigned) (LWA_ALPHA |\n\t\t\t\t    (wmPtr->crefObj ? LWA_COLORKEY : 0)));\n\t\t}\n\t    }\n\t} else {\n\t    if ((i < objc-1)\n\t\t    && Tcl_GetBooleanFromObj(interp, objv[i+1], &boolValue)\n\t\t\t    != TCL_OK) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (config_fullscreen) {\n\t\tif (objc == 4) {\n\t\t    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(\n\t\t\t    (wmPtr->flags & WM_FULLSCREEN) != 0));\n\t\t} else {\n\t\t    fullscreen_attr_changed = 1;\n\t\t    fullscreen_attr = boolValue;\n\t\t}\n\t\tconfig_fullscreen = 0;\n\t    } else if (objc == 4) {\n\t\tTcl_SetObjResult(interp,\n\t\t\tTcl_NewBooleanObj(*stylePtr & styleBit));\n\t    } else if (boolValue) {\n\t\t*stylePtr |= styleBit;\n\t    } else {\n\t\t*stylePtr &= ~styleBit;\n\t    }\n\t}\n\tif ((styleBit == WS_EX_TOPMOST) && (wmPtr->wrapper != NULL)) {\n\t    /*\n\t     * Force the topmost position aspect to ensure that switching\n\t     * between (no)topmost reflects properly when rewrapped.\n\t     */\n\n\t    SetWindowPos(wmPtr->wrapper,\n\t\t    ((exStyle & WS_EX_TOPMOST) ?\n\t\t\t    HWND_TOPMOST : HWND_NOTOPMOST), 0, 0, 0, 0,\n\t\t    SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOSENDCHANGING\n\t\t    |SWP_NOOWNERZORDER);\n\t}\n    }\n    if (wmPtr->styleConfig != style) {\n\t/*\n\t * Currently this means only WS_DISABLED changed, which we can effect\n\t * with EnableWindow.\n\t */\n\n\twmPtr->styleConfig = style;\n\tif ((wmPtr->exStyleConfig == exStyle)\n\t\t&& !(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    EnableWindow(wmPtr->wrapper, (style & WS_DISABLED) ? 0 : 1);\n\t}\n    }\n    if (wmPtr->exStyleConfig != exStyle) {\n\twmPtr->exStyleConfig = exStyle;\n\tif (updatewrapper) {\n\t    /*\n\t     * UpdateWrapper ensure that all effects are properly handled,\n\t     * such as TOOLWINDOW disappearing from the taskbar.\n\t     */\n\n\t    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t\tUpdateWrapper(winPtr);\n\t    }\n\t}\n    }\n    if (fullscreen_attr_changed) {\n\tif (fullscreen_attr) {\n\t    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't set fullscreen attribute for \\\"%s\\\":\"\n\t\t\t\" override-redirect flag is set\", winPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ATTR\",\n\t\t\t\"OVERRIDE_REDIRECT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\n\t    /*\n\t     * Check max width and height if set by the user, don't worry\n\t     * about the default values since they will likely be smaller than\n\t     * screen width/height.\n\t     */\n\n\t    if (((wmPtr->maxWidth > 0) &&\n\t\t    (WidthOfScreen(Tk_Screen(winPtr)) > wmPtr->maxWidth)) ||\n\t\t    ((wmPtr->maxHeight > 0) &&\n\t\t    (HeightOfScreen(Tk_Screen(winPtr)) > wmPtr->maxHeight))) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't set fullscreen attribute for \\\"%s\\\":\"\n\t\t\t\" max width/height is too small\", winPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ATTR\", \"SMALL_MAX\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\n\tTkpWmSetFullScreen(winPtr, fullscreen_attr);\n    }\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmClientCmd --\n *\n *\tThis function is invoked to process the \"wm client\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmClientCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size length;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_SetObjResult(interp,\n\t\t    Tcl_NewStringObj(wmPtr->clientMachine, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    if (argv3[0] == 0) {\n\tif (wmPtr->clientMachine != NULL) {\n\t    Tcl_Free(wmPtr->clientMachine);\n\t    wmPtr->clientMachine = NULL;\n\t    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t\tXDeleteProperty(winPtr->display, winPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr,\"WM_CLIENT_MACHINE\"));\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n    if (wmPtr->clientMachine != NULL) {\n\tTcl_Free(wmPtr->clientMachine);\n    }\n    wmPtr->clientMachine = (char *)Tcl_Alloc(length + 1);\n    memcpy(wmPtr->clientMachine, argv3, length + 1);\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tXTextProperty textProp;\n\n\tif (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)\n\t\t!= 0) {\n\t    XSetWMClientMachine(winPtr->display, winPtr->window,\n\t\t    &textProp);\n\t    XFree(textProp.value);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmColormapwindowsCmd --\n *\n *\tThis function is invoked to process the \"wm colormapwindows\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmColormapwindowsCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    TkWindow **cmapList, *winPtr2, **winPtr2Ptr = &winPtr2;\n    Tcl_Size i, windowObjc;\n    int gotToplevel;\n    Tcl_Obj **windowObjv, *resultObj;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?windowList?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTk_MakeWindowExist((Tk_Window) winPtr);\n\tresultObj = Tcl_NewObj();\n\tfor (i = 0; i < wmPtr->cmapCount; i++) {\n\t    if ((i == (wmPtr->cmapCount-1))\n\t\t    && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {\n\t\tbreak;\n\t    }\n\t    Tcl_ListObjAppendElement(NULL, resultObj,\n\t\t    Tk_NewWindowObj((Tk_Window) wmPtr->cmapList[i]));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)\n\t    != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    cmapList = (TkWindow**)Tcl_Alloc((windowObjc + 1) * sizeof(TkWindow*));\n    gotToplevel = 0;\n    for (i = 0; i < windowObjc; i++) {\n\tif (TkGetWindowFromObj(interp, tkwin, windowObjv[i],\n\t\t(Tk_Window *) winPtr2Ptr) != TCL_OK) {\n\t    Tcl_Free(cmapList);\n\t    return TCL_ERROR;\n\t}\n\tif (winPtr2 == winPtr) {\n\t    gotToplevel = 1;\n\t}\n\tif (winPtr2->window == None) {\n\t    Tk_MakeWindowExist((Tk_Window) winPtr2);\n\t}\n\tcmapList[i] = winPtr2;\n    }\n    if (!gotToplevel) {\n\twmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;\n\tcmapList[windowObjc] = winPtr;\n\twindowObjc++;\n    } else {\n\twmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;\n    }\n    wmPtr->flags |= WM_COLORMAPS_EXPLICIT;\n    if (wmPtr->cmapList != NULL) {\n\tTcl_Free(wmPtr->cmapList);\n    }\n    wmPtr->cmapList = cmapList;\n    wmPtr->cmapCount = windowObjc;\n\n    /*\n     * Now we need to force the updated colormaps to be installed.\n     */\n\n    if (wmPtr == winPtr->dispPtr->foregroundWmPtr) {\n\tInstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, true);\n    } else {\n\tInstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, false);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmCommandCmd --\n *\n *\tThis function is invoked to process the \"wm command\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmCommandCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size cmdArgc;\n    const char **cmdArgv;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?value?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->cmdArgv != NULL) {\n\t    char *merged = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);\n\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(merged, TCL_INDEX_NONE));\n\t    Tcl_Free(merged);\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (argv3[0] == 0) {\n\tif (wmPtr->cmdArgv != NULL) {\n\t    Tcl_Free(wmPtr->cmdArgv);\n\t    wmPtr->cmdArgv = NULL;\n\t    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t\tXDeleteProperty(winPtr->display, winPtr->window,\n\t\t\tTk_InternAtom((Tk_Window) winPtr, \"WM_COMMAND\"));\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->cmdArgv != NULL) {\n\tTcl_Free(wmPtr->cmdArgv);\n    }\n    wmPtr->cmdArgc = cmdArgc;\n    wmPtr->cmdArgv = cmdArgv;\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tXSetCommand(winPtr->display, winPtr->window, (char **) cmdArgv, (int)cmdArgc);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmDeiconifyCmd --\n *\n *\tThis function is invoked to process the \"wm deiconify\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmDeiconifyCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't deiconify %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"DEICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (winPtr->flags & TK_EMBEDDED) {\n\tif (!SendMessageW(wmPtr->wrapper, TK_DEICONIFY, 0, 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't deiconify %s: the container does not support the request\",\n\t\t    winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\treturn TCL_OK;\n    }\n    TkpWinToplevelDeiconify(winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFocusmodelCmd --\n *\n *\tThis function is invoked to process the \"wm focusmodel\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFocusmodelCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"active\", \"passive\", NULL\n    };\n    enum options {\n\tOPT_ACTIVE, OPT_PASSIVE\n    };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?active|passive?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\twmPtr->hints.input ? \"passive\" : \"active\", TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings,\n\t    \"argument\", 0,&index) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (index == OPT_ACTIVE) {\n\twmPtr->hints.input = False;\n    } else { /* OPT_PASSIVE */\n\twmPtr->hints.input = True;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmForgetCmd --\n *\n *\tThis procedure is invoked to process the \"wm forget\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmForgetCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel or Frame to work with */\n    TCL_UNUSED(Tcl_Interp *),\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *))\t/* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window) winPtr;\n\n    /*\n     * Tk ticket c77b426d: avoid panic on usage after wm forget\n     */\n\n    if (Tk_IsTopLevel(frameWin) && Tk_IsManageable(frameWin)) {\n\tTk_UnmapWindow(frameWin);\n\twinPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);\n\tif (winPtr->parentPtr) {\n\t    Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);\n\t    RemapWindows(winPtr, Tk_GetHWND(winPtr->parentPtr->window));\n\t}\n\n\t/*\n\t * Make sure wm no longer manages this window\n\t */\n\tTk_ManageGeometry(frameWin, NULL, NULL);\n\n\tTkWmDeadWindow(winPtr);\n\t/* flags (above) must be cleared before calling */\n\t/* TkMapTopFrame (below) */\n\tTkMapTopFrame(frameWin);\n    } else {\n\t/* Already not managed by wm - ignore it */\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmFrameCmd --\n *\n *\tThis function is invoked to process the \"wm frame\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmFrameCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    HWND hwnd;\n    char buf[TCL_INTEGER_SPACE];\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (Tk_WindowId((Tk_Window) winPtr) == None) {\n\tTk_MakeWindowExist((Tk_Window) winPtr);\n    }\n    hwnd = wmPtr->wrapper;\n    if (hwnd == NULL) {\n\thwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));\n    }\n    snprintf(buf, sizeof(buf), \"0x%\" TCL_Z_MODIFIER \"x\", (size_t)hwnd);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGeometryCmd --\n *\n *\tThis function is invoked to process the \"wm geometry\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGeometryCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    char xSign, ySign;\n    int width, height;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newGeometry?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\txSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';\n\tySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';\n\tif (wmPtr->gridWin != NULL) {\n\t    width = wmPtr->reqGridWidth + (winPtr->changes.width\n\t\t    - winPtr->reqWidth)/wmPtr->widthInc;\n\t    height = wmPtr->reqGridHeight + (winPtr->changes.height\n\t\t    - winPtr->reqHeight)/wmPtr->heightInc;\n\t} else {\n\t    width = winPtr->changes.width;\n\t    height = winPtr->changes.height;\n\t}\n\tif (winPtr->flags & TK_EMBEDDED) {\n\t    LRESULT result = SendMessageW(wmPtr->wrapper, TK_MOVEWINDOW, -1, -1);\n\n\t    wmPtr->x = (short)(result >> 16);\n\t    wmPtr->y = (short)(result & 0x0000ffff);\n\t}\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\"%dx%d%c%d%c%d\",\n\t\twidth, height, xSign, wmPtr->x, ySign, wmPtr->y));\n\treturn TCL_OK;\n    }\n\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n\tWmUpdateGeom(wmPtr, winPtr);\n\treturn TCL_OK;\n    }\n    return ParseGeometry(interp, argv3, winPtr);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGridCmd --\n *\n *\tThis function is invoked to process the \"wm grid\" Tcl command. See the\n *\tuser documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGridCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int reqWidth, reqHeight, widthInc, heightInc;\n\n    if ((objc != 3) && (objc != 7)) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?baseWidth baseHeight widthInc heightInc?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->sizeHintsFlags & PBaseSize) {\n\t    Tcl_Obj *results[4];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);\n\t    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);\n\t    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\t/*\n\t * Turn off gridding and reset the width and height to make sense as\n\t * ungridded numbers.\n\t */\n\n\twmPtr->sizeHintsFlags &= ~PBaseSize;\n\tif (wmPtr->width != -1) {\n\t    wmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t    - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t    wmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t    - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t}\n\twmPtr->widthInc = 1;\n\twmPtr->heightInc = 1;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\tif (reqWidth < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"baseWidth can't be < 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (reqHeight < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"baseHeight can't be < 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (widthInc <= 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"widthInc can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (heightInc <= 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"heightInc can't be <= 0\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GRID\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,\n\t\theightInc);\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmGroupCmd --\n *\n *\tThis function is invoked to process the \"wm group\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmGroupCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    const char *argv3;\n    Tcl_Size length;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & WindowGroupHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, TCL_INDEX_NONE));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetStringFromObj(objv[3], &length);\n    if (*argv3 == '\\0') {\n\twmPtr->hints.flags &= ~WindowGroupHint;\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->leaderName = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tTk_MakeWindowExist(tkwin2);\n\tif (wmPtr->leaderName != NULL) {\n\t    Tcl_Free(wmPtr->leaderName);\n\t}\n\twmPtr->hints.window_group = Tk_WindowId(tkwin2);\n\twmPtr->hints.flags |= WindowGroupHint;\n\twmPtr->leaderName = (char *)Tcl_Alloc(length + 1);\n\tmemcpy(wmPtr->leaderName, argv3, length + 1);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconbadgeCmd --\n *\n *\tThis function is invoked to process the \"wm iconbadge\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbadgeCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TCL_UNUSED(TkWindow *),\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    HWND hwnd;\n    Tk_PhotoHandle photo;\n    Tk_PhotoImageBlock block;\n    int width, height;\n    HICON overlayicon;\n    int badgenumber;\n    char *badgestring = NULL;\n    char photoname[4096];\n    LPCWSTR string;\n    HRESULT hr;\n    Tk_Window badgewindow;\n    WmInfo *wmPtr;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window badge\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Parse args, get native wrapper window, and determine image.\n     */\n\n    badgewindow = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);\n    wmPtr = ((TkWindow *) badgewindow)->wmInfoPtr;\n    hwnd = wmPtr->wrapper;\n    badgestring = Tcl_GetString(objv[3]);\n\n    badgenumber = atoi(badgestring);\n    if (badgenumber > 9) {\n\tstrcpy(photoname, \"::tk::icons::9plus-badge\");\n    } else {\n\tstrcpy(photoname, \"::tk::icons::\");\n\tstrcat(photoname, badgestring);\n\tstrcat(photoname, \"-badge\");\n    }\n\n    /*\n     * If badgestring is empty string, remove icon.\n     */\n\n    if (strcmp(\"\", badgestring) == 0) {\n\tptbl->lpVtbl->SetOverlayIcon(ptbl, hwnd, NULL, NULL);\n\treturn TCL_OK;\n    }\n\n    /*\n     * If photo does not exist, return error. This means we do not have\n     * to test for decimal or negative values; no photo for such values\n     * is present.\n     */\n\n    photo = Tk_FindPhoto(interp, photoname);\n    if (photo == NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't use \\\"%s\\\" as icon badge\", badgestring));\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * We have found the image. Convert to icon.\n     */\n\n    Tk_PhotoGetSize(photo, &width, &height);\n    Tk_PhotoGetImage(photo, &block);\n\n    overlayicon = CreateIcoFromPhoto(width, height, block);\n    if (overlayicon == NULL) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"Failed to create badge icon\", TCL_INDEX_NONE));\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Place overlay icon on taskbar icon.\n     */\n\n    string = L\"Alert\";\n    hr = ptbl->lpVtbl->SetOverlayIcon(ptbl, hwnd, overlayicon, string);\n    if (hr != S_OK) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"Failed to create badge icon\", TCL_INDEX_NONE));\n\treturn TCL_ERROR;\n    }\n    DestroyIcon(overlayicon);\n\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconbitmapCmd --\n *\n *\tThis function is invoked to process the \"wm iconbitmap\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconbitmapCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */\n    const char *string;\n\n    if ((objc < 3) || (objc > 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?-default? ?image?\");\n\treturn TCL_ERROR;\n    } else if (objc == 5) {\n\t/*\n\t * If we have 5 arguments, we must have a '-default' flag.\n\t */\n\n\tconst char *argv3 = Tcl_GetString(objv[3]);\n\n\tif (strcmp(argv3, \"-default\")) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"illegal option \\\"%s\\\" must be \\\"-default\\\"\", argv3));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONBITMAP\", \"OPTION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tuseWinPtr = NULL;\n    } else if (objc == 3) {\n\t/*\n\t * No arguments were given.\n\t */\n\n\tif (wmPtr->hints.flags & IconPixmapHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),\n\t\t    -1));\n\t}\n\treturn TCL_OK;\n    }\n\n    string = Tcl_GetString(objv[objc-1]);\n    if (*string == '\\0') {\n\tif (wmPtr->hints.icon_pixmap != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);\n\t    wmPtr->hints.icon_pixmap = None;\n\t}\n\twmPtr->hints.flags &= ~IconPixmapHint;\n\tif (WinSetIcon(interp, NULL, (Tk_Window) useWinPtr) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\t/*\n\t * In the future this block of code will use Tk's 'image'\n\t * functionality to allow all supported image formats. However, this\n\t * will require a change to the way icons are handled. We will need to\n\t * add icon<->image conversions routines.\n\t *\n\t * Until that happens we simply try to find an icon in the given\n\t * argument, and if that fails, we use the older bitmap code. We do\n\t * things this way round (icon then bitmap), because the bitmap code\n\t * actually seems to have no visible effect, so we want to give the\n\t * icon code the first try at doing something.\n\t */\n\n\t/*\n\t * Either return NULL, or return a valid titlebaricon with its ref\n\t * count already incremented.\n\t */\n\n\tWinIconPtr titlebaricon = ReadIconFromFile(interp, objv[objc-1]);\n\tif (titlebaricon != NULL) {\n\t    /*\n\t     * Try to set the icon for the window. If it is a '-default' icon,\n\t     * we must pass in NULL\n\t     */\n\n\t    if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr)\n\t\t    != TCL_OK) {\n\t\t/*\n\t\t * We didn't use the titlebaricon after all.\n\t\t */\n\n\t\tDecrIconRefCount(titlebaricon);\n\t\ttitlebaricon = NULL;\n\t    }\n\t}\n\tif (titlebaricon == NULL) {\n\t    /*\n\t     * We didn't manage to handle the argument as a valid icon. Try as\n\t     * a bitmap. First we must clear the error message which was\n\t     * placed in the interpreter.\n\t     */\n\n\t    Pixmap pixmap;\n\n\t    Tcl_ResetResult(interp);\n\t    pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, string);\n\t    if (pixmap == None) {\n\t\treturn TCL_ERROR;\n\t    }\n\t    wmPtr->hints.icon_pixmap = pixmap;\n\t    wmPtr->hints.flags |= IconPixmapHint;\n\t    titlebaricon = GetIconFromPixmap(Tk_Display(winPtr), pixmap);\n\t    if (titlebaricon != NULL && WinSetIcon(interp, titlebaricon,\n\t\t    (Tk_Window) useWinPtr) != TCL_OK) {\n\t\t/*\n\t\t * We didn't use the titlebaricon after all.\n\t\t */\n\n\t\tDecrIconRefCount(titlebaricon);\n\t\ttitlebaricon = NULL;\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconifyCmd --\n *\n *\tThis function is invoked to process the \"wm iconify\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconifyCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (winPtr->flags & TK_EMBEDDED) {\n\tif (!SendMessageW(wmPtr->wrapper, TK_ICONIFY, 0, 0)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't iconify \\\"%s\\\": the container does not support the request\",\n\t\t    winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"EMBEDDED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"OVERRIDE_REDIRECT\",\n\t\t(char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->containerPtr != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is a transient\",\n\t\twinPtr->pathName));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"TRANSIENT\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't iconify \\\"%s\\\": it is an icon for \\\"%s\\\"\",\n\t\twinPtr->pathName, Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONIFY\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    TkpWmSetState(winPtr, IconicState);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconmaskCmd --\n *\n *\tThis function is invoked to process the \"wm iconmask\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconmaskCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Pixmap pixmap;\n    const char *argv3;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?bitmap?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconMaskHint) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),\n\t\t    -1));\n\t}\n\treturn TCL_OK;\n    }\n    argv3 = Tcl_GetString(objv[3]);\n    if (*argv3 == '\\0') {\n\tif (wmPtr->hints.icon_mask != None) {\n\t    Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);\n\t}\n\twmPtr->hints.flags &= ~IconMaskHint;\n    } else {\n\tpixmap = Tk_GetBitmap(interp, tkwin, argv3);\n\tif (pixmap == None) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_mask = pixmap;\n\twmPtr->hints.flags |= IconMaskHint;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconnameCmd --\n *\n *\tThis function is invoked to process the \"wm iconname\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconnameCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size length;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t(wmPtr->iconName ? wmPtr->iconName : \"\"), -1));\n\treturn TCL_OK;\n    } else {\n\tif (wmPtr->iconName != NULL) {\n\t    Tcl_Free(wmPtr->iconName);\n\t}\n\targv3 = Tcl_GetStringFromObj(objv[3], &length);\n\twmPtr->iconName = (char *)Tcl_Alloc(length + 1);\n\tmemcpy(wmPtr->iconName, argv3, length + 1);\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconphotoCmd --\n *\n *\tThis function is invoked to process the \"wm iconphoto\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconphotoCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */\n    Tk_PhotoHandle photo;\n    Tk_PhotoImageBlock block;\n    Tcl_Size i;\n    int width, height, startObj = 3;\n    BlockOfIconImagesPtr lpIR;\n    WinIconPtr titlebaricon = NULL;\n    HICON hIcon;\n    size_t size;\n\n    if (objc < 4) {\n\tTcl_WrongNumArgs(interp, 2, objv,\n\t\t\"window ?-default? image1 ?image2 ...?\");\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Iterate over all images to validate their existence.\n     */\n\n    if (strcmp(Tcl_GetString(objv[3]), \"-default\") == 0) {\n\tuseWinPtr = NULL;\n\tstartObj = 4;\n\tif (objc == 4) {\n\t    Tcl_WrongNumArgs(interp, 2, objv,\n\t\t    \"window ?-default? image1 ?image2 ...?\");\n\t    return TCL_ERROR;\n\t}\n    }\n    for (i = startObj; i < objc; i++) {\n\tphoto = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));\n\tif (photo == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't use \\\"%s\\\" as iconphoto: not a photo image\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"PHOTO\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    }\n\n    /*\n     * We have calculated the size of the data. Try to allocate the needed\n     * memory space.\n     */\n\n    size = sizeof(BlockOfIconImages) + (sizeof(ICONIMAGE) * (objc-startObj-1));\n    lpIR = (BlockOfIconImagesPtr)Tcl_AttemptAlloc(size);\n    if (lpIR == NULL) {\n\treturn TCL_ERROR;\n    }\n    memset(lpIR, 0, size);\n\n    for (i = startObj; i < objc; i++) {\n\tphoto = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));\n\tTk_PhotoGetSize(photo, &width, &height);\n\tTk_PhotoGetImage(photo, &block);\n\n\thIcon = CreateIcoFromPhoto(width, height, block);\n\tif (hIcon == NULL) {\n\t    FreeIconBlock(lpIR);\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"failed to create an iconphoto with image \\\"%s\\\"\",\n\t\t    Tcl_GetString(objv[i])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONPHOTO\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tlpIR->IconImages[i-startObj].Width = width;\n\tlpIR->IconImages[i-startObj].Height = height;\n\tlpIR->IconImages[i-startObj].Colors = 4;\n\tlpIR->IconImages[i-startObj].hIcon = hIcon;\n\tlpIR->nNumImages++;\n    }\n\n    titlebaricon = (WinIconPtr)Tcl_Alloc(sizeof(WinIconInstance));\n    titlebaricon->iconBlock = lpIR;\n    titlebaricon->refCount = 1;\n    if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr) != TCL_OK) {\n\t/*\n\t * We didn't use the titlebaricon after all.\n\t */\n\n\tDecrIconRefCount(titlebaricon);\n\treturn TCL_ERROR;\n    }\n    return TCL_OK;\n}\n\f\n\n\n/*\n *----------------------------------------------------------------------\n *\n * WmIconpositionCmd --\n *\n *\tThis function is invoked to process the \"wm iconposition\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconpositionCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?x y?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->hints.flags & IconPositionHint) {\n\t    Tcl_Obj *results[2];\n\n\t    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);\n\t    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);\n\t    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->hints.flags &= ~IconPositionHint;\n    } else {\n\tif ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)\n\t\t|| (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {\n\t    return TCL_ERROR;\n\t}\n\twmPtr->hints.icon_x = x;\n\twmPtr->hints.icon_y = y;\n\twmPtr->hints.flags |= IconPositionHint;\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmIconwindowCmd --\n *\n *\tThis function is invoked to process the \"wm iconwindow\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmIconwindowCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Tk_Window tkwin2;\n    WmInfo *wmPtr2;\n    XSetWindowAttributes atts;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?pathName?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (wmPtr->icon != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));\n\t}\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->hints.flags &= ~IconWindowHint;\n\tif (wmPtr->icon != NULL) {\n\t    /*\n\t     * Let the window use button events again, then remove it as icon\n\t     * window.\n\t     */\n\n\t    atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask\n\t\t    | ButtonPressMask;\n\t    Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);\n\t    wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\t    wmPtr2->iconFor = NULL;\n\t    wmPtr2->hints.initial_state = WithdrawnState;\n\t}\n\twmPtr->icon = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (!Tk_IsTopLevel(tkwin2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't use %s as icon window: not at top level\",\n\t\t    Tcl_GetString(objv[3])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"INNER\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\twmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;\n\tif (wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"%s is already an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"ICONWINDOW\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (wmPtr->icon != NULL) {\n\t    WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;\n\t    wmPtr3->iconFor = NULL;\n\n\t    /*\n\t     * Let the window use button events again.\n\t     */\n\n\t    atts.event_mask = Tk_Attributes(wmPtr->icon)->event_mask\n\t\t    | ButtonPressMask;\n\t    Tk_ChangeWindowAttributes(wmPtr->icon, CWEventMask, &atts);\n\t}\n\n\t/*\n\t * Disable button events in the icon window: some window managers\n\t * (like olvwm) want to get the events themselves, but X only allows\n\t * one application at a time to receive button events for a window.\n\t */\n\n\tatts.event_mask = Tk_Attributes(tkwin2)->event_mask\n\t\t& ~ButtonPressMask;\n\tTk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);\n\tTk_MakeWindowExist(tkwin2);\n\twmPtr->hints.icon_window = Tk_WindowId(tkwin2);\n\twmPtr->hints.flags |= IconWindowHint;\n\twmPtr->icon = tkwin2;\n\twmPtr2->iconFor = (Tk_Window) winPtr;\n\tif (!(wmPtr2->flags & WM_NEVER_MAPPED)) {\n\t    wmPtr2->flags |= WM_WITHDRAWN;\n\t    TkpWmSetState(((TkWindow *) tkwin2), WithdrawnState);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmManageCmd --\n *\n *\tThis procedure is invoked to process the \"wm manage\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmManageCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel or Frame to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    TCL_UNUSED(Tcl_Size),\t\t/* Number of arguments. */\n    TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */\n{\n    Tk_Window frameWin = (Tk_Window) winPtr;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!Tk_IsTopLevel(frameWin)) {\n\tif (!Tk_IsManageable(frameWin)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" is not manageable: must be a frame,\"\n\t\t    \" labelframe or toplevel\", Tk_PathName(frameWin)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"MANAGE\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tTkFocusSplit(winPtr);\n\tTk_UnmapWindow(frameWin);\n\twinPtr->flags |= TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED;\n\tRemapWindows(winPtr, NULL);\n\tif (wmPtr == NULL) {\n\t    TkWmNewWindow(winPtr);\n\t}\n\twmPtr = winPtr->wmInfoPtr;\n\twinPtr->flags &= ~TK_MAPPED;\n\t/* flags (above) must be set before calling */\n\t/* TkMapTopFrame (below) */\n\tTkMapTopFrame (frameWin);\n    } else if (Tk_IsTopLevel(frameWin)) {\n\t/* Already managed by wm - ignore it */\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMaxsizeCmd --\n *\n *\tThis function is invoked to process the \"wm maxsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMaxsizeCmd(\n    Tk_Window tkwin,\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tGetMaxSize(wmPtr, &width, &height);\n\tresults[0] = Tcl_NewWideIntObj(width);\n\tresults[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->maxWidth = width;\n    wmPtr->maxHeight = height;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmMinsizeCmd --\n *\n *\tThis function is invoked to process the \"wm minsize\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmMinsizeCmd(\n    Tk_Window tkwin,\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tGetMinSize(wmPtr, &width, &height);\n\tresults[0] = Tcl_NewWideIntObj(width);\n\tresults[1] = Tcl_NewWideIntObj(height);\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK)\n\t    || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    wmPtr->minWidth = width;\n    wmPtr->minHeight = height;\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmOverrideredirectCmd --\n *\n *\tThis function is invoked to process the \"wm overrideredirect\" Tcl\n *\tcommand. See the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmOverrideredirectCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    Bool boolValue, curValue;\n    XSetWindowAttributes atts;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?boolean?\");\n\treturn TCL_ERROR;\n    }\n    if (winPtr->flags & TK_EMBEDDED) {\n\tcurValue = (Bool)(SendMessageW(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1)-1);\n\tif (curValue < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"Container does not support overrideredirect\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tcurValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;\n    }\n    if (objc == 3) {\n\tTcl_SetObjResult(interp, Tcl_NewBooleanObj(curValue));\n\treturn TCL_OK;\n    }\n    if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (curValue != boolValue) {\n\tif (winPtr->flags & TK_EMBEDDED) {\n\t    SendMessageW(wmPtr->wrapper, TK_OVERRIDEREDIRECT, boolValue, 0);\n\t} else {\n\t    /*\n\t     * Only do this if we are really changing value, because it causes\n\t     * some funky stuff to occur.\n\t     */\n\n\t    atts.override_redirect = boolValue;\n\t    Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,\n\t\t    &atts);\n\t    if (!(wmPtr->flags & (WM_NEVER_MAPPED))\n\t\t    && !(winPtr->flags & TK_EMBEDDED)) {\n\t\tUpdateWrapper(winPtr);\n\t    }\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmPositionfromCmd --\n *\n *\tThis function is invoked to process the \"wm positionfrom\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmPositionfromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL\n    };\n    enum options {\n\tOPT_PROGRAM, OPT_USER\n    };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user/program?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tconst char *sourceStr = \"\";\n\n\tif (wmPtr->sizeHintsFlags & USPosition) {\n\t    sourceStr = \"user\";\n\t} else if (wmPtr->sizeHintsFlags & PPosition) {\n\t    sourceStr = \"program\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USPosition|PPosition);\n    } else {\n\tif (Tcl_GetIndexFromObj(interp, objv[3], optionStrings,\n\t\t\"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PPosition;\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t} else {\n\t    wmPtr->sizeHintsFlags &= ~USPosition;\n\t    wmPtr->sizeHintsFlags |= PPosition;\n\t}\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmProtocolCmd --\n *\n *\tThis function is invoked to process the \"wm protocol\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmProtocolCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    ProtocolHandler *protPtr, *prevPtr;\n    Atom protocol;\n    const char *cmd;\n    Tcl_Size cmdLength;\n    Tcl_Obj *resultObj;\n\n    if ((objc < 3) || (objc > 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?name? ?command?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\t/*\n\t * Return a list of all defined protocols for the window.\n\t */\n\n\tresultObj = Tcl_NewObj();\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(\n\t\t    Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol), TCL_INDEX_NONE));\n\t}\n\tTcl_SetObjResult(interp, resultObj);\n\treturn TCL_OK;\n    }\n    protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));\n    if (objc == 4) {\n\t/*\n\t * Return the command to handle a given protocol.\n\t */\n\n\tfor (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t\tprotPtr = protPtr->nextPtr) {\n\t    if (protPtr->protocol == protocol) {\n\t\tTcl_SetObjResult(interp,\n\t\t\tTcl_NewStringObj(protPtr->command, TCL_INDEX_NONE));\n\t\treturn TCL_OK;\n\t    }\n\t}\n\treturn TCL_OK;\n    }\n\n    /*\n     * Delete any current protocol handler, then create a new one with the\n     * specified command, unless the command is empty.\n     */\n\n    for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;\n\t    prevPtr = protPtr, protPtr = protPtr->nextPtr) {\n\tif (protPtr->protocol == protocol) {\n\t    if (prevPtr == NULL) {\n\t\twmPtr->protPtr = protPtr->nextPtr;\n\t    } else {\n\t\tprevPtr->nextPtr = protPtr->nextPtr;\n\t    }\n\t    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);\n\t    break;\n\t}\n    }\n    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);\n    if (cmdLength > 0) {\n\tprotPtr = (ProtocolHandler *)Tcl_Alloc(HANDLER_SIZE(cmdLength));\n\tprotPtr->protocol = protocol;\n\tprotPtr->nextPtr = wmPtr->protPtr;\n\twmPtr->protPtr = protPtr;\n\tprotPtr->interp = interp;\n\tmemcpy(protPtr->command, cmd, cmdLength + 1);\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmResizableCmd --\n *\n *\tThis function is invoked to process the \"wm resizable\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmResizableCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int width, height;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?width height?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tTcl_Obj *results[2];\n\n\tresults[0] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));\n\tresults[1] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));\n\tTcl_SetObjResult(interp, Tcl_NewListObj(2, results));\n\treturn TCL_OK;\n    }\n    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)\n\t    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {\n\treturn TCL_ERROR;\n    }\n    if (width) {\n\twmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;\n    } else {\n\twmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;\n    }\n    if (height) {\n\twmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;\n    } else {\n\twmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;\n    }\n    if (!((wmPtr->flags & WM_NEVER_MAPPED)\n\t    && !(winPtr->flags & TK_EMBEDDED))) {\n\tUpdateWrapper(winPtr);\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmSizefromCmd --\n *\n *\tThis function is invoked to process the \"wm sizefrom\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmSizefromCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"program\", \"user\", NULL\n    };\n    enum options {\n\tOPT_PROGRAM, OPT_USER\n    };\n    int index;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?user|program?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tconst char *sourceStr = \"\";\n\n\tif (wmPtr->sizeHintsFlags & USSize) {\n\t    sourceStr = \"user\";\n\t} else if (wmPtr->sizeHintsFlags & PSize) {\n\t    sourceStr = \"program\";\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, TCL_INDEX_NONE));\n\treturn TCL_OK;\n    }\n\n    if (TkObjIsEmpty(objv[3])) {\n\twmPtr->sizeHintsFlags &= ~(USSize|PSize);\n    } else {\n\tif (Tcl_GetIndexFromObj(interp, objv[3], optionStrings,\n\t\t\"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_USER) {\n\t    wmPtr->sizeHintsFlags &= ~PSize;\n\t    wmPtr->sizeHintsFlags |= USSize;\n\t} else { /* OPT_PROGRAM */\n\t    wmPtr->sizeHintsFlags &= ~USSize;\n\t    wmPtr->sizeHintsFlags |= PSize;\n\t}\n    }\n    WmUpdateGeom(wmPtr, winPtr);\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStackorderCmd --\n *\n *\tThis function is invoked to process the \"wm stackorder\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStackorderCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    TkWindow **windows, **windowPtr;\n    static const char *const optionStrings[] = {\n\t\"isabove\", \"isbelow\", NULL\n    };\n    enum options {\n\tOPT_ISABOVE, OPT_ISBELOW\n    };\n    Tcl_Obj *resultObj;\n    int index;\n\n    if ((objc != 3) && (objc != 5)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?isabove|isbelow window?\");\n\treturn TCL_ERROR;\n    }\n\n    if (objc == 3) {\n\twindows = TkWmStackorderToplevel(winPtr);\n\tif (windows != NULL) {\n\t    resultObj = Tcl_NewObj();\n\t    for (windowPtr = windows; *windowPtr ; windowPtr++) {\n\t\tTcl_ListObjAppendElement(NULL, resultObj,\n\t\t\tTk_NewWindowObj((Tk_Window) *windowPtr));\n\t    }\n\t    Tcl_SetObjResult(interp, resultObj);\n\t    Tcl_Free(windows);\n\t    return TCL_OK;\n\t} else {\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tTkWindow *winPtr2, **winPtr2Ptr = &winPtr2;\n\tTcl_Size index1 = -1, index2 = -1;\n\tint result;\n\n\tif (TkGetWindowFromObj(interp, tkwin, objv[4],\n\t\t(Tk_Window *) winPtr2Ptr) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsTopLevel(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't a top-level window\",\n\t\t    winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"TOPLEVEL\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsMapped(winPtr)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tif (!Tk_IsMapped(winPtr2)) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"window \\\"%s\\\" isn't mapped\", winPtr2->pathName));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STACK\", \"MAPPED\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\t/*\n\t * Lookup stacking order of all toplevels that are children of \".\" and\n\t * find the position of winPtr and winPtr2 in the stacking order.\n\t */\n\n\twindows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);\n\tif (windows == NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    \"TkWmStackorderToplevel failed\", TCL_INDEX_NONE));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\tfor (windowPtr = windows; *windowPtr ; windowPtr++) {\n\t    if (*windowPtr == winPtr) {\n\t\tindex1 = (windowPtr - windows);\n\t    }\n\t    if (*windowPtr == winPtr2) {\n\t\tindex2 = (windowPtr - windows);\n\t    }\n\t}\n\tif (index1 == -1) {\n\t    Tcl_Panic(\"winPtr window not found\");\n\t} else if (index2 == -1) {\n\t    Tcl_Panic(\"winPtr2 window not found\");\n\t}\n\n\tTcl_Free(windows);\n\n\tif (Tcl_GetIndexFromObj(interp, objv[3], optionStrings,\n\t\t\"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\tif (index == OPT_ISABOVE) {\n\t    result = index1 > index2;\n\t} else { /* OPT_ISBELOW */\n\t    result = index1 < index2;\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewWideIntObj(result));\n\treturn TCL_OK;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmStateCmd --\n *\n *\tThis function is invoked to process the \"wm state\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmStateCmd(\n    TCL_UNUSED(Tk_Window),\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    static const char *const optionStrings[] = {\n\t\"iconic\", \"normal\", \"withdrawn\", \"zoomed\", NULL\n    };\n    enum options {\n\tOPT_ICONIC, OPT_NORMAL, OPT_WITHDRAWN, OPT_ZOOMED\n    };\n    int index;\n\n    if ((objc < 3) || (objc > 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?state?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 4) {\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't change state of %s: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tif (Tcl_GetIndexFromObj(interp, objv[3], optionStrings,\n\t\t\"argument\", 0, &index) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\n\tif (winPtr->flags & TK_EMBEDDED) {\n\t    int state = 0;\n\n\t    switch (index) {\n\t    case OPT_NORMAL:\n\t\tstate = NormalState;\n\t\tbreak;\n\t    case OPT_ICONIC:\n\t\tstate = IconicState;\n\t\tbreak;\n\t    case OPT_WITHDRAWN:\n\t\tstate = WithdrawnState;\n\t\tbreak;\n\t    case OPT_ZOOMED:\n\t\tstate = ZoomState;\n\t\tbreak;\n\t    default:\n\t\tTcl_Panic(\"unexpected index\");\n\t    }\n\n\t    if (state+1 != SendMessageW(wmPtr->wrapper, TK_STATE, state, 0)) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't change state of %s: the container does not support the request\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    return TCL_OK;\n\t}\n\n\tif (index == OPT_NORMAL) {\n\t    wmPtr->flags &= ~WM_WITHDRAWN;\n\t    TkpWmSetState(winPtr, NormalState);\n\n\t    /*\n\t     * This varies from 'wm deiconify' because it does not force the\n\t     * window to be raised and receive focus.\n\t     */\n\t} else if (index == OPT_ICONIC) {\n\t    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": override-redirect flag is set\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\",\n\t\t\t\"OVERRIDE_REDIRECT\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    if (wmPtr->containerPtr != NULL) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"can't iconify \\\"%s\\\": it is a transient\",\n\t\t\twinPtr->pathName));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"STATE\", \"TRANSIENT\",\n\t\t\t(char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t    TkpWmSetState(winPtr, IconicState);\n\t} else if (index == OPT_WITHDRAWN) {\n\t    TkpWinToplevelWithDraw(winPtr);\n\t} else if (index == OPT_ZOOMED) {\n\t    TkpWmSetState(winPtr, ZoomState);\n\t} else {\n\t    Tcl_Panic(\"wm state not matched\");\n\t}\n    } else {\n\tconst char *stateStr = \"\";\n\n\tif (wmPtr->iconFor != NULL) {\n\t    stateStr = \"icon\";\n\t} else {\n\t    int state;\n\n\t    if (winPtr->flags & TK_EMBEDDED) {\n\t\tstate = (int)(SendMessageW(wmPtr->wrapper, TK_STATE, -1, -1) - 1);\n\t    } else {\n\t\tstate = wmPtr->hints.initial_state;\n\t    }\n\t    switch (state) {\n\t    case NormalState:\tstateStr = \"normal\";\tbreak;\n\t    case IconicState:\tstateStr = \"iconic\";\tbreak;\n\t    case WithdrawnState: stateStr = \"withdrawn\"; break;\n\t    case ZoomState:\tstateStr = \"zoomed\";\tbreak;\n\t    }\n\t}\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(stateStr, TCL_INDEX_NONE));\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTitleCmd --\n *\n *\tThis function is invoked to process the \"wm title\" Tcl command. See\n *\tthe user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTitleCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    const char *argv3;\n    Tcl_Size length;\n    HWND wrapper;\n\n    if (objc > 4) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?newTitle?\");\n\treturn TCL_ERROR;\n    }\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\twrapper = (HWND) SendMessageW(wmPtr->wrapper, TK_GETFRAMEWID, 0, 0);\n    } else {\n\twrapper = wmPtr->wrapper;\n    }\n    if (objc == 3) {\n\tif (wrapper) {\n\t    WCHAR buf[256];\n\t    Tcl_DString titleString;\n\t    int size = 256;\n\n\t    GetWindowTextW(wrapper, buf, size);\n\t    Tcl_DStringInit(&titleString);\n\t    Tcl_WCharToUtfDString(buf, wcslen(buf), &titleString);\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    Tcl_DStringValue(&titleString),\n\t\t    Tcl_DStringLength(&titleString)));\n\t    Tcl_DStringFree(&titleString);\n\t} else {\n\t    Tcl_SetObjResult(interp, Tcl_NewStringObj(\n\t\t    (wmPtr->title ? wmPtr->title : winPtr->nameUid), TCL_INDEX_NONE));\n\t}\n    } else {\n\tif (wmPtr->title != NULL) {\n\t    Tcl_Free(wmPtr->title);\n\t}\n\targv3 = Tcl_GetStringFromObj(objv[3], &length);\n\twmPtr->title = (char *)Tcl_Alloc(length + 1);\n\tmemcpy(wmPtr->title, argv3, length + 1);\n\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) {\n\t    Tcl_DString titleString;\n\n\t    Tcl_DStringInit(&titleString);\n\t    Tcl_UtfToWCharDString(wmPtr->title, TCL_INDEX_NONE, &titleString);\n\t    SetWindowTextW(wrapper, (LPCWSTR) Tcl_DStringValue(&titleString));\n\t    Tcl_DStringFree(&titleString);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmTransientCmd --\n *\n *\tThis function is invoked to process the \"wm transient\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmTransientCmd(\n    Tk_Window tkwin,\t\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    TkWindow *containerPtr = wmPtr->containerPtr, **containerPtrPtr = &containerPtr, *w;\n    WmInfo *wmPtr2;\n\n    if ((objc != 3) && (objc != 4)) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window ?window?\");\n\treturn TCL_ERROR;\n    }\n    if (objc == 3) {\n\tif (containerPtr != NULL) {\n\t    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) containerPtr));\n\t}\n\treturn TCL_OK;\n    }\n    if (Tcl_GetString(objv[3])[0] == '\\0') {\n\tif (containerPtr != NULL) {\n\t    /*\n\t     * If we had a container, tell them that we aren't tied to them\n\t     * anymore.\n\t     */\n\n\t    containerPtr->wmInfoPtr->numTransients--;\n\t    Tk_DeleteEventHandler((Tk_Window) containerPtr,\n\t\t    VisibilityChangeMask|StructureNotifyMask,\n\t\t    WmWaitVisibilityOrMapProc, winPtr);\n\t}\n\n\twmPtr->containerPtr = NULL;\n    } else {\n\tif (TkGetWindowFromObj(interp, tkwin, objv[3],\n\t\t(Tk_Window *) containerPtrPtr) != TCL_OK) {\n\t    return TCL_ERROR;\n\t}\n\twhile (!Tk_TopWinHierarchy(containerPtr)) {\n\t    /*\n\t     * Ensure that the container window is actually a Tk toplevel.\n\t     */\n\n\t    containerPtr = containerPtr->parentPtr;\n\t}\n\tTk_MakeWindowExist((Tk_Window) containerPtr);\n\n\tif (wmPtr->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a transient: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\n\twmPtr2 = containerPtr->wmInfoPtr;\n\n\tif (wmPtr2->iconFor != NULL) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't make \\\"%s\\\" a container: it is an icon for %s\",\n\t\t    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"ICON\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n\tfor (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;\n\t    w = (TkWindow *)w->wmInfoPtr->containerPtr) {\n\t    if (w == winPtr) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't set \\\"%s\\\" as container: would cause management loop\",\n\t\t    Tk_PathName(containerPtr)));\n\t\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"TRANSIENT\", \"SELF\", (char *)NULL);\n\t\treturn TCL_ERROR;\n\t    }\n\t}\n\tif (containerPtr != wmPtr->containerPtr) {\n\t    /*\n\t     * Remove old container map/unmap binding before setting the new\n\t     * container. The event handler will ensure that transient states\n\t     * reflect the state of the container.\n\t     */\n\n\t    if (wmPtr->containerPtr != NULL) {\n\t\twmPtr->containerPtr->wmInfoPtr->numTransients--;\n\t\tTk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,\n\t\t\tVisibilityChangeMask|StructureNotifyMask,\n\t\t\tWmWaitVisibilityOrMapProc, winPtr);\n\t    }\n\n\t    containerPtr->wmInfoPtr->numTransients++;\n\t    Tk_CreateEventHandler((Tk_Window) containerPtr,\n\t\t    VisibilityChangeMask|StructureNotifyMask,\n\t\t    WmWaitVisibilityOrMapProc, winPtr);\n\n\t    wmPtr->containerPtr = containerPtr;\n\t}\n    }\n    if (!((wmPtr->flags & WM_NEVER_MAPPED)\n\t    && !(winPtr->flags & TK_EMBEDDED))) {\n\tif (wmPtr->containerPtr != NULL\n\t\t&& !Tk_IsMapped(wmPtr->containerPtr)) {\n\t    TkpWmSetState(winPtr, WithdrawnState);\n\t} else {\n\t    UpdateWrapper(winPtr);\n\t}\n    }\n    return TCL_OK;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmWithdrawCmd --\n *\n *\tThis function is invoked to process the \"wm withdraw\" Tcl command.\n *\tSee the user documentation for details on what it does.\n *\n * Results:\n *\tA standard Tcl result.\n *\n * Side effects:\n *\tSee the user documentation.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nWmWithdrawCmd(\n    TCL_UNUSED(Tk_Window),\t/* Main window of the application. */\n    TkWindow *winPtr,\t\t/* Toplevel to work with */\n    Tcl_Interp *interp,\t\t/* Current interpreter. */\n    Tcl_Size objc,\t\t\t/* Number of arguments. */\n    Tcl_Obj *const objv[])\t/* Argument objects. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (objc != 3) {\n\tTcl_WrongNumArgs(interp, 2, objv, \"window\");\n\treturn TCL_ERROR;\n    }\n    if (wmPtr->iconFor != NULL) {\n\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\"can't withdraw %s: it is an icon for %s\",\n\t\tTcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));\n\tTcl_SetErrorCode(interp, \"TK\", \"WM\", \"WITHDRAW\", \"ICON\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\tif (SendMessageW(wmPtr->wrapper, TK_WITHDRAW, 0, 0) < 0) {\n\t    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t    \"can't withdraw %s: the container does not support the request\",\n\t\t    Tcl_GetString(objv[2])));\n\t    Tcl_SetErrorCode(interp, \"TK\", \"WM\", \"COMMUNICATION\", (char *)NULL);\n\t    return TCL_ERROR;\n\t}\n    } else {\n\tTkpWinToplevelWithDraw(winPtr);\n    }\n    return TCL_OK;\n}\n\n/*\n * Invoked by those wm subcommands that affect geometry. Schedules a geometry\n * update.\n */\n\nstatic void\nWmUpdateGeom(\n    WmInfo *wmPtr,\n    TkWindow *winPtr)\n{\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\nstatic void\nWmWaitVisibilityOrMapProc(\n    void *clientData,\t/* Pointer to window. */\n    XEvent *eventPtr)\t\t/* Information about event. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n    TkWindow *containerPtr = winPtr->wmInfoPtr->containerPtr;\n\n    if (containerPtr == NULL)\n\treturn;\n\n    if (eventPtr->type == MapNotify) {\n\tif (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN)) {\n\t    TkpWmSetState(winPtr, NormalState);\n\t}\n    } else if (eventPtr->type == UnmapNotify) {\n\tTkpWmSetState(winPtr, WithdrawnState);\n    }\n\n    if (eventPtr->type == VisibilityNotify) {\n\tint state = containerPtr->wmInfoPtr->hints.initial_state;\n\n\tif ((state == NormalState) || (state == ZoomState)) {\n\t    state = winPtr->wmInfoPtr->hints.initial_state;\n\t    if ((state == NormalState) || (state == ZoomState)) {\n\t\tUpdateWrapper(winPtr);\n\t    }\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetGrid --\n *\n *\tThis function is invoked by a widget when it wishes to set a grid\n *\tcoordinate system that controls the size of a top-level window. It\n *\tprovides a C interface equivalent to the \"wm grid\" command and is\n *\tusually associated with the -setgrid option.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGrid-related information will be passed to the window manager, so that\n *\tthe top-level window associated with tkwin will resize on even grid\n *\tunits. If some other window already controls gridding for the\n *\ttop-level window then this function call has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetGrid(\n    Tk_Window tkwin,\t\t/* Token for window. New window mgr info will\n\t\t\t\t * be posted for the top-level window\n\t\t\t\t * associated with this window. */\n    int reqWidth,\t\t/* Width (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int reqHeight,\t\t/* Height (in grid units) corresponding to the\n\t\t\t\t * requested geometry for tkwin. */\n    int widthInc, int heightInc)/* Pixel increments corresponding to a change\n\t\t\t\t * of one grid unit. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Ensure widthInc and heightInc are greater than 0\n     */\n\n    if (widthInc <= 0) {\n\twidthInc = 1;\n    }\n    if (heightInc <= 0) {\n\theightInc = 1;\n    }\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {\n\treturn;\n    }\n\n    if ((wmPtr->reqGridWidth == reqWidth)\n\t    && (wmPtr->reqGridHeight == reqHeight)\n\t    && (wmPtr->widthInc == widthInc)\n\t    && (wmPtr->heightInc == heightInc)\n\t    && ((wmPtr->sizeHintsFlags & PBaseSize) == PBaseSize)) {\n\treturn;\n    }\n\n    /*\n     * If gridding was previously off, then forget about any window size\n     * requests made by the user or via \"wm geometry\": these are in pixel\n     * units and there's no easy way to translate them to grid units since the\n     * new requested size of the top-level window in pixels may not yet have\n     * been registered yet (it may filter up the hierarchy in DoWhenIdle\n     * handlers). However, if the window has never been mapped yet then just\n     * leave the window size alone: assume that it is intended to be in grid\n     * units but just happened to have been specified before this function was\n     * called.\n     */\n\n    if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {\n\twmPtr->width = -1;\n\twmPtr->height = -1;\n    }\n\n    /*\n     * Set the new gridding information, and start the process of passing all\n     * of this information to the window manager.\n     */\n\n    wmPtr->gridWin = tkwin;\n    wmPtr->reqGridWidth = reqWidth;\n    wmPtr->reqGridHeight = reqHeight;\n    wmPtr->widthInc = widthInc;\n    wmPtr->heightInc = heightInc;\n    wmPtr->sizeHintsFlags |= PBaseSize;\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_UnsetGrid --\n *\n *\tThis function cancels the effect of a previous call to Tk_SetGrid.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tIf tkwin currently controls gridding for its top-level window,\n *\tgridding is cancelled for that top-level window; if some other window\n *\tcontrols gridding then this function has no effect.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_UnsetGrid(\n    Tk_Window tkwin)\t\t/* Token for window that is currently\n\t\t\t\t * controlling gridding. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n\n    /*\n     * Find the top-level window for tkwin, plus the window manager\n     * information.\n     */\n\n    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\twinPtr = winPtr->parentPtr;\n    }\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n\n    if (tkwin != wmPtr->gridWin) {\n\treturn;\n    }\n\n    wmPtr->gridWin = NULL;\n    wmPtr->sizeHintsFlags &= ~PBaseSize;\n    if (wmPtr->width != -1) {\n\twmPtr->width = winPtr->reqWidth + (wmPtr->width\n\t\t- wmPtr->reqGridWidth)*wmPtr->widthInc;\n\twmPtr->height = winPtr->reqHeight + (wmPtr->height\n\t\t- wmPtr->reqGridHeight)*wmPtr->heightInc;\n    }\n    wmPtr->widthInc = 1;\n    wmPtr->heightInc = 1;\n\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelEventProc --\n *\n *\tThis function is invoked when a top-level (or other externally-managed\n *\twindow) is restructured in any way.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tTk's internal data structures for the window get modified to reflect\n *\tthe structural change.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTopLevelEventProc(\n    void *clientData,\t/* Window for which event occurred. */\n    XEvent *eventPtr)\t\t/* Event that just happened. */\n{\n    TkWindow *winPtr = (TkWindow *)clientData;\n\n    if (eventPtr->type == DestroyNotify) {\n\tTk_ErrorHandler handler;\n\n\tif (!(winPtr->flags & TK_ALREADY_DEAD)) {\n\t    /*\n\t     * A top-level window was deleted externally (e.g., by the window\n\t     * manager). This is probably not a good thing, but cleanup as\n\t     * best we can. The error handler is needed because\n\t     * Tk_DestroyWindow will try to destroy the window, but of course\n\t     * it's already gone.\n\t     */\n\n\t    handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,\n\t\t    NULL, NULL);\n\t    Tk_DestroyWindow((Tk_Window) winPtr);\n\t    Tk_DeleteErrorHandler(handler);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelReqProc --\n *\n *\tThis function is invoked by the geometry manager whenever the\n *\trequested size for a top-level window is changed.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tArrange for the window to be resized to satisfy the request (this\n *\thappens as a when-idle action).\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTopLevelReqProc(\n    TCL_UNUSED(void *),\t\t/* Not used. */\n    Tk_Window tkwin)\t\t/* Information about window. */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr;\n\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr) {\n\tif ((winPtr->flags & TK_EMBEDDED) && (wmPtr->wrapper != NULL)) {\n\t    SendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ, Tk_ReqWidth(tkwin),\n\t\tTk_ReqHeight(tkwin));\n\t}\n\tif (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\t    Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\t    wmPtr->flags |= WM_UPDATE_PENDING;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateGeometryInfo --\n *\n *\tThis function is invoked when a top-level window is first mapped, and\n *\talso as a when-idle function, to bring the geometry and/or position of\n *\ta top-level window back into line with what has been requested by the\n *\tuser and/or widgets. This function doesn't return until the system has\n *\tresponded to the geometry change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window's size and location may change, unless the WM prevents that\n *\tfrom happening.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateGeometryInfo(\n    void *clientData)\t/* Pointer to the window's record. */\n{\n    int x, y;\t\t\t/* Position of border on desktop. */\n    int width, height;\t\t/* Size of client area. */\n    int min, max;\n    RECT rect;\n    TkWindow *winPtr = (TkWindow *)clientData;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    wmPtr->flags &= ~WM_UPDATE_PENDING;\n\n    /*\n     * If the window is minimized or maximized, we should not update our\n     * geometry since it will end up with the wrong values. ConfigureToplevel\n     * will reschedule UpdateGeometryInfo when the state of the window\n     * changes.\n     */\n\n    if (wmPtr->wrapper && (IsIconic(wmPtr->wrapper) ||\n\t    IsZoomed(wmPtr->wrapper) || (wmPtr->flags & WM_FULLSCREEN))) {\n\treturn;\n    }\n\n    /*\n     * Compute the border size for the current window style. This size will\n     * include the resize handles, the title bar and the menubar. Note that\n     * this size will not be correct if the menubar spans multiple lines. The\n     * height will be off by a multiple of the menubar height. It really only\n     * measures the minimum size of the border.\n     */\n\n    rect.left = rect.right = rect.top = rect.bottom = 0;\n    AdjustWindowRectEx(&rect, wmPtr->style, wmPtr->hMenu != NULL,\n\t    wmPtr->exStyle);\n    wmPtr->borderWidth = rect.right - rect.left;\n    wmPtr->borderHeight = rect.bottom - rect.top;\n\n    /*\n     * Compute the new size for the top-level window. See the user\n     * documentation for details on this, but the size requested depends on\n     * (a) the size requested internally by the window's widgets, (b) the size\n     * requested by the user in a \"wm geometry\" command or via wm-based\n     * interactive resizing (if any), (c) whether or not the window is\n     * gridded, and (d) the current min or max size for the toplevel. Don't\n     * permit sizes <= 0 because this upsets the X server.\n     */\n\n    if (wmPtr->width == -1) {\n\twidth = winPtr->reqWidth;\n    } else if (wmPtr->gridWin != NULL) {\n\twidth = winPtr->reqWidth\n\t\t+ (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc;\n    } else {\n\twidth = wmPtr->width;\n    }\n    if (width <= 0) {\n\twidth = 1;\n    }\n\n    /*\n     * Account for window max/min width\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqWidth\n\t\t+ (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\tif (wmPtr->maxWidth > 0) {\n\t    max = winPtr->reqWidth\n\t\t    + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minWidth;\n\tmax = wmPtr->maxWidth;\n    }\n    if (width < min) {\n\twidth = min;\n    } else if ((max > 0) && (width > max)) {\n\twidth = max;\n    }\n\n    if (wmPtr->height == -1) {\n\theight = winPtr->reqHeight;\n    } else if (wmPtr->gridWin != NULL) {\n\theight = winPtr->reqHeight\n\t\t+ (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc;\n    } else {\n\theight = wmPtr->height;\n    }\n    if (height <= 0) {\n\theight = 1;\n    }\n\n    /*\n     * Account for window max/min height\n     */\n\n    if (wmPtr->gridWin != NULL) {\n\tmin = winPtr->reqHeight\n\t\t+ (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;\n\tif (wmPtr->maxHeight > 0) {\n\t    max = winPtr->reqHeight\n\t\t    + (wmPtr->maxHeight-wmPtr->reqGridHeight)*wmPtr->heightInc;\n\t} else {\n\t    max = 0;\n\t}\n    } else {\n\tmin = wmPtr->minHeight;\n\tmax = wmPtr->maxHeight;\n    }\n    if (height < min) {\n\theight = min;\n    } else if ((max > 0) && (height > max)) {\n\theight = max;\n    }\n\n    /*\n     * Compute the new position for the upper-left pixel of the window's\n     * decorative frame. This is tricky, because we need to include the border\n     * widths supplied by a reparented parent in this calculation, but can't\n     * use the parent's current overall size since that may change as a result\n     * of this code.\n     */\n\n    if (wmPtr->flags & WM_NEGATIVE_X) {\n\tx = DisplayWidth(winPtr->display, winPtr->screenNum) - wmPtr->x\n\t\t- (width + wmPtr->borderWidth);\n    } else {\n\tx = wmPtr->x;\n    }\n    if (wmPtr->flags & WM_NEGATIVE_Y) {\n\ty = DisplayHeight(winPtr->display, winPtr->screenNum) - wmPtr->y\n\t\t- (height + wmPtr->borderHeight);\n    } else {\n\ty = wmPtr->y;\n    }\n\n    /*\n     * Reconfigure the window if it isn't already configured correctly. Base\n     * the size check on what we *asked for* last time, not what we got.\n     * Return immediately if there have been no changes in the requested\n     * geometry of the toplevel.\n     */\n\n    /* TODO: need to add flag for possible menu size change */\n\n    if (!(wmPtr->flags & WM_MOVE_PENDING)\n\t    && (width == wmPtr->configWidth)\n\t    && (height == wmPtr->configHeight)) {\n\treturn;\n    }\n    wmPtr->flags &= ~WM_MOVE_PENDING;\n\n    wmPtr->configWidth = width;\n    wmPtr->configHeight = height;\n\n    /*\n     * Don't bother moving the window if we are in the process of creating it.\n     * Just update the geometry info based on what we asked for.\n     */\n\n    if (wmPtr->flags & WM_CREATE_PENDING) {\n\twinPtr->changes.x = x;\n\twinPtr->changes.y = y;\n\twinPtr->changes.width = width;\n\twinPtr->changes.height = height;\n\treturn;\n    }\n\n    wmPtr->flags |= WM_SYNC_PENDING;\n    if (winPtr->flags & TK_EMBEDDED) {\n\t/*\n\t * The wrapper window is in a different process, so we need to send it\n\t * a geometry request. This protocol assumes that the other process\n\t * understands this Tk message, otherwise our requested geometry will\n\t * be ignored.\n\t */\n\n\tSendMessageW(wmPtr->wrapper, TK_MOVEWINDOW, x, y);\n\tSendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ, width, height);\n    } else {\n\tint reqHeight, reqWidth;\n\tRECT windowRect;\n\tint menuInc = GetSystemMetrics(SM_CYMENU);\n\tint newHeight;\n\n\t/*\n\t * We have to keep resizing the window until we get the requested\n\t * height in the client area. If the client area has zero height, then\n\t * the window rect is too small by definition. Try increasing the\n\t * border height and try again. Once we have a positive size, then we\n\t * can adjust the height exactly. If the window rect comes back\n\t * smaller than we requested, we have hit the maximum constraints that\n\t * Windows imposes. Once we find a positive client size, the next size\n\t * is the one we try no matter what.\n\t */\n\n\treqHeight = height + wmPtr->borderHeight;\n\treqWidth = width + wmPtr->borderWidth;\n\n\twhile (1) {\n\t    MoveWindow(wmPtr->wrapper, x, y, reqWidth, reqHeight, TRUE);\n\t    GetWindowRect(wmPtr->wrapper, &windowRect);\n\t    newHeight = windowRect.bottom - windowRect.top;\n\n\t    /*\n\t     * If the request wasn't satisfied, we have hit an external\n\t     * constraint and must stop.\n\t     */\n\n\t    if (newHeight < reqHeight) {\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * Now check the size of the client area against our ideal.\n\t     */\n\n\t    GetClientRect(wmPtr->wrapper, &windowRect);\n\t    newHeight = windowRect.bottom - windowRect.top;\n\n\t    if (newHeight == height) {\n\t\t/*\n\t\t * We're done.\n\t\t */\n\n\t\tbreak;\n\t    } else if (newHeight > height) {\n\t\t/*\n\t\t * One last resize to get rid of the extra space.\n\t\t */\n\n\t\tmenuInc = newHeight - height;\n\t\treqHeight -= menuInc;\n\t\tif (wmPtr->flags & WM_NEGATIVE_Y) {\n\t\t    y += menuInc;\n\t\t}\n\t\tMoveWindow(wmPtr->wrapper, x, y, reqWidth, reqHeight, TRUE);\n\t\tbreak;\n\t    }\n\n\t    /*\n\t     * We didn't get enough space to satisfy our requested height, so\n\t     * the menu must have wrapped. Increase the size of the window by\n\t     * one menu height and move the window if it is positioned\n\t     * relative to the lower right corner of the screen.\n\t     */\n\n\t    reqHeight += menuInc;\n\t    if (wmPtr->flags & WM_NEGATIVE_Y) {\n\t\ty -= menuInc;\n\t    }\n\t}\n\tif (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\t    DrawMenuBar(wmPtr->wrapper);\n\t}\n    }\n    wmPtr->flags &= ~WM_SYNC_PENDING;\n}\n\f\n/*\n *--------------------------------------------------------------\n *\n * ParseGeometry --\n *\n *\tThis function parses a geometry string and updates information used to\n *\tcontrol the geometry of a top-level window.\n *\n * Results:\n *\tA standard Tcl return value, plus an error message in the interp's\n *\tresult if an error occurs.\n *\n * Side effects:\n *\tThe size and/or location of winPtr may change.\n *\n *--------------------------------------------------------------\n */\n\nstatic int\nParseGeometry(\n    Tcl_Interp *interp,\t\t/* Used for error reporting. */\n    const char *string,\t\t/* String containing new geometry. Has the\n\t\t\t\t * standard form \"=wxh+x+y\". */\n    TkWindow *winPtr)\t\t/* Pointer to top-level window whose geometry\n\t\t\t\t * is to be changed. */\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int x, y, width, height, flags;\n    char *end;\n    const char *p = string;\n\n    /*\n     * The leading \"=\" is optional.\n     */\n\n    if (*p == '=') {\n\tp++;\n    }\n\n    /*\n     * Parse the width and height, if they are present. Don't actually update\n     * any of the fields of wmPtr until we've successfully parsed the entire\n     * geometry string.\n     */\n\n    width = wmPtr->width;\n    height = wmPtr->height;\n    x = wmPtr->x;\n    y = wmPtr->y;\n    flags = wmPtr->flags;\n    if (isdigit(UCHAR(*p))) {\n\twidth = strtoul(p, &end, 10);\n\tp = end;\n\tif (*p != 'x') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p))) {\n\t    goto error;\n\t}\n\theight = strtoul(p, &end, 10);\n\tp = end;\n    }\n\n    /*\n     * Parse the X and Y coordinates, if they are present.\n     */\n\n    if (*p != '\\0') {\n\tflags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_X;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\tx = strtol(p, &end, 10);\n\tp = end;\n\tif (*p == '-') {\n\t    flags |= WM_NEGATIVE_Y;\n\t} else if (*p != '+') {\n\t    goto error;\n\t}\n\tp++;\n\tif (!isdigit(UCHAR(*p)) && (*p != '-')) {\n\t    goto error;\n\t}\n\ty = strtol(p, &end, 10);\n\tif (*end != '\\0') {\n\t    goto error;\n\t}\n\n\t/*\n\t * Assume that the geometry information came from the user, unless an\n\t * explicit source has been specified. Otherwise most window managers\n\t * assume that the size hints were program-specified and they ignore\n\t * them.\n\t */\n\n\tif (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\t    wmPtr->sizeHintsFlags |= USPosition;\n\t}\n    }\n\n    /*\n     * Everything was parsed OK. Update the fields of *wmPtr and arrange for\n     * the appropriate information to be percolated out to the window manager\n     * at the next idle moment.\n     */\n\n    wmPtr->width = width;\n    wmPtr->height = height;\n    wmPtr->x = x;\n    wmPtr->y = y;\n    flags |= WM_MOVE_PENDING;\n    wmPtr->flags = flags;\n\n    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\twmPtr->flags |= WM_UPDATE_PENDING;\n    }\n    return TCL_OK;\n\n  error:\n    Tcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t    \"bad geometry specifier \\\"%s\\\"\", string));\n    Tcl_SetErrorCode(interp, \"TK\", \"VALUE\", \"GEOMETRY\", (char *)NULL);\n    return TCL_ERROR;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetRootCoords --\n *\n *\tGiven a token for a window, this function traces through the window's\n *\tlineage to find the (virtual) root-window coordinates corresponding to\n *\tpoint (0,0) in the window.\n *\n * Results:\n *\tThe locations pointed to by xPtr and yPtr are filled in with the root\n *\tcoordinates of the (0,0) point in tkwin.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetRootCoords(\n    Tk_Window tkwin,\t\t/* Token for window. */\n    int *xPtr,\t\t\t/* Where to store x-displacement of (0,0). */\n    int *yPtr)\t\t\t/* Where to store y-displacement of (0,0). */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    /*\n     * If the window is mapped, let Windows figure out the translation.\n     */\n\n    if (winPtr->window != None) {\n\tHWND hwnd = Tk_GetHWND(winPtr->window);\n\tPOINT point;\n\n\tpoint.x = 0;\n\tpoint.y = 0;\n\n\tClientToScreen(hwnd, &point);\n\n\t*xPtr = point.x;\n\t*yPtr = point.y;\n    } else {\n\t*xPtr = 0;\n\t*yPtr = 0;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_CoordsToWindow --\n *\n *\tGiven the (virtual) root coordinates of a point, this function returns\n *\tthe token for the top-most window covering that point, if there exists\n *\tsuch a window in this application.\n *\n * Results:\n *\tThe return result is either a token for the window corresponding to\n *\trootX and rootY, or else NULL to indicate that there is no such\n *\twindow.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTk_Window\nTk_CoordsToWindow(\n    int rootX, int rootY,\t/* Coordinates of point in root window. If a\n\t\t\t\t * virtual-root window manager is in use,\n\t\t\t\t * these coordinates refer to the virtual\n\t\t\t\t * root, not the real root. */\n    Tk_Window tkwin)\t\t/* Token for any window in application; used\n\t\t\t\t * to identify the display. */\n{\n    POINT pos;\n    HWND hwnd;\n    TkWindow *winPtr;\n\n    pos.x = rootX;\n    pos.y = rootY;\n    hwnd = WindowFromPoint(pos);\n\n    winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);\n    if (winPtr && (winPtr->mainPtr == ((TkWindow *) tkwin)->mainPtr)) {\n\treturn (Tk_Window) winPtr;\n    }\n    return NULL;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetVRootGeometry --\n *\n *\tThis function returns information about the virtual root window\n *\tcorresponding to a particular Tk window.\n *\n * Results:\n *\tThe values at xPtr, yPtr, widthPtr, and heightPtr are set with the\n *\toffset and dimensions of the root window corresponding to tkwin. If\n *\ttkwin is being managed by a virtual root window manager these values\n *\tcorrespond to the virtual root window being used for tkwin; otherwise\n *\tthe offsets will be 0 and the dimensions will be those of the screen.\n *\n * Side effects:\n *\tVroot window information is refreshed if it is out of date.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_GetVRootGeometry(\n    TCL_UNUSED(Tk_Window),/* Window whose virtual root is to be\n\t\t\t\t * queried. */\n    int *xPtr, int *yPtr,\t/* Store x and y offsets of virtual root\n\t\t\t\t * here. */\n    int *widthPtr, int *heightPtr)\n\t\t\t\t/* Store dimensions of virtual root here. */\n{\n    *xPtr = GetSystemMetrics(SM_XVIRTUALSCREEN);\n    *yPtr = GetSystemMetrics(SM_YVIRTUALSCREEN);\n    *widthPtr = GetSystemMetrics(SM_CXVIRTUALSCREEN);\n    *heightPtr = GetSystemMetrics(SM_CYVIRTUALSCREEN);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_MoveToplevelWindow --\n *\n *\tThis function is called instead of Tk_MoveWindow to adjust the x-y\n *\tlocation of a top-level window. It delays the actual move to a later\n *\ttime and keeps window-manager information up-to-date with the move\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe window is eventually moved so that its upper-left corner\n *\t(actually, the upper-left corner of the window's decorative frame, if\n *\tthere is one) is at (x,y).\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_MoveToplevelWindow(\n    Tk_Window tkwin,\t\t/* Window to move. */\n    int x, int y)\t\t/* New location for window (within parent). */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!(winPtr->flags & TK_TOP_LEVEL)) {\n\tTcl_Panic(\"Tk_MoveToplevelWindow called with non-toplevel window\");\n    }\n    wmPtr->x = x;\n    wmPtr->y = y;\n    wmPtr->flags |= WM_MOVE_PENDING;\n    wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);\n    if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {\n\twmPtr->sizeHintsFlags |= USPosition;\n    }\n\n    /*\n     * If the window has already been mapped, must bring its geometry\n     * up-to-date immediately, otherwise an event might arrive from the server\n     * that would overwrite wmPtr->x and wmPtr->y and lose the new position.\n     */\n\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tif (wmPtr->flags & WM_UPDATE_PENDING) {\n\t    Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n\t}\n\tUpdateGeometryInfo(winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmProtocolEventProc --\n *\n *\tThis function is called by the Tk_HandleEvent whenever a ClientMessage\n *\tevent arrives whose type is \"WM_PROTOCOLS\". This function handles the\n *\tmessage from the window manager in an appropriate fashion.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDepends on what sort of handler, if any, was set up for the protocol.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmProtocolEventProc(\n    TkWindow *winPtr,\t\t/* Window to which the event was sent. */\n    XEvent *eventPtr)\t\t/* X event. */\n{\n    WmInfo *wmPtr;\n    ProtocolHandler *protPtr;\n    Atom protocol;\n    int result;\n    Tcl_Interp *interp;\n\n    wmPtr = winPtr->wmInfoPtr;\n    if (wmPtr == NULL) {\n\treturn;\n    }\n    protocol = (Atom) eventPtr->xclient.data.l[0];\n    for (protPtr = wmPtr->protPtr; protPtr != NULL;\n\t    protPtr = protPtr->nextPtr) {\n\tif (protocol == protPtr->protocol) {\n\t    /*\n\t     * Cache atom name, as we might destroy the window as a result of\n\t     * the eval.\n\t     */\n\n\t    const char *name = Tk_GetAtomName((Tk_Window) winPtr, protocol);\n\n\t    Tcl_Preserve(protPtr);\n\t    interp = protPtr->interp;\n\t    Tcl_Preserve(interp);\n\t    result = Tcl_EvalEx(interp, protPtr->command, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);\n\t    if (result != TCL_OK) {\n\t\tTcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(\n\t\t\t\"\\n    (command for \\\"%s\\\" window manager protocol)\",\n\t\t\tname));\n\t\tTcl_BackgroundException(interp, result);\n\t    }\n\t    Tcl_Release(interp);\n\t    Tcl_Release(protPtr);\n\t    return;\n\t}\n    }\n\n    /*\n     * No handler was present for this protocol. If this is a WM_DELETE_WINDOW\n     * message then just destroy the window.\n     */\n\n    if (protocol == Tk_InternAtom((Tk_Window) winPtr, \"WM_DELETE_WINDOW\")) {\n\tTk_DestroyWindow((Tk_Window) winPtr);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevelEnumProc --\n *\n *\tThis function is invoked once for each HWND Window on the display as a\n *\tresult of calling EnumWindows from TkWmStackorderToplevel.\n *\n * Results:\n *\tTRUE to request further iteration.\n *\n * Side effects:\n *\tAdds entries to the passed array of TkWindows.\n *\n *----------------------------------------------------------------------\n */\n\nBOOL CALLBACK\nTkWmStackorderToplevelEnumProc(\n    HWND hwnd,\t\t\t/* Handle to parent window */\n    LPARAM lParam)\t\t/* Application-defined value */\n{\n    Tcl_HashEntry *hPtr;\n    TkWindow *childWinPtr;\n\n    TkWmStackorderToplevelPair *pair =\n\t    (TkWmStackorderToplevelPair *) lParam;\n\n    hPtr = Tcl_FindHashEntry(pair->table, hwnd);\n    if (hPtr != NULL) {\n\tchildWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);\n\n\t/*\n\t * Double check that same HWND does not get passed twice.\n\t */\n\n\tif (childWinPtr == NULL) {\n\t    Tcl_Panic(\"duplicate HWND in TkWmStackorderToplevelEnumProc\");\n\t} else {\n\t    Tcl_SetHashValue(hPtr, NULL);\n\t}\n\t/*\n\tfprintf(stderr, \"Found mapped HWND %d -> %x (%s)\\n\", hwnd,\n\t\tchildWinPtr, childWinPtr->pathName);\n\t*/\n\t*(pair->windowPtr)-- = childWinPtr;\n    }\n    return TRUE;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevelWrapperMap --\n *\n *\tThis function will create a table that maps the wrapper HWND id for a\n *\ttoplevel to the TkWindow structure that is wraps.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAdds entries to the passed hashtable.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nTkWmStackorderToplevelWrapperMap(\n    TkWindow *winPtr,\t\t/* TkWindow to recurse on */\n    Display *display,\t\t/* X display of parent window */\n    Tcl_HashTable *table)\t/* Table to maps HWND to TkWindow */\n{\n    TkWindow *childPtr;\n    Tcl_HashEntry *hPtr;\n    HWND wrapper;\n    int newEntry;\n\n    if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)\n\t    && !Tk_IsEmbedded(winPtr) && (winPtr->display == display)) {\n\twrapper = TkWinGetWrapperWindow((Tk_Window) winPtr);\n\n\t/*\n\tfprintf(stderr, \"Mapped HWND %d to %x (%s)\\n\", wrapper,\n\t\twinPtr, winPtr->pathName);\n\t*/\n\n\thPtr = Tcl_CreateHashEntry(table, (char *) wrapper, &newEntry);\n\tTcl_SetHashValue(hPtr, winPtr);\n    }\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tTkWmStackorderToplevelWrapperMap(childPtr, display, table);\n    }\n}\n/*\n *----------------------------------------------------------------------\n *\n * TkWmStackorderToplevel --\n *\n *\tThis function returns the stack order of toplevel windows.\n *\n * Results:\n *\tAn array of pointers to tk window objects in stacking order or else\n *\tNULL if there was an error.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow **\nTkWmStackorderToplevel(\n    TkWindow *parentPtr)\t/* Parent toplevel window. */\n{\n    TkWmStackorderToplevelPair pair;\n    TkWindow **windows;\n    Tcl_HashTable table;\n    Tcl_HashEntry *hPtr;\n    Tcl_HashSearch search;\n\n    /*\n     * Map HWND ids to a TkWindow of the wrapped toplevel.\n     */\n\n    Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);\n    TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);\n\n    windows = (TkWindow **)Tcl_Alloc((table.numEntries+1) * sizeof(TkWindow *));\n\n    /*\n     * Special cases: If zero or one toplevels were mapped there is no need to\n     * call EnumWindows.\n     */\n\n    switch (table.numEntries) {\n    case 0:\n\twindows[0] = NULL;\n\tgoto done;\n    case 1:\n\thPtr = Tcl_FirstHashEntry(&table, &search);\n\twindows[0] = (TkWindow *)Tcl_GetHashValue(hPtr);\n\twindows[1] = NULL;\n\tgoto done;\n    }\n\n    /*\n     * We will be inserting into the array starting at the end and working our\n     * way to the beginning since EnumWindows returns windows in highest to\n     * lowest order.\n     */\n\n    pair.table = &table;\n    pair.windowPtr = windows + table.numEntries;\n    *pair.windowPtr-- = NULL;\n\n    if (EnumWindows((WNDENUMPROC) TkWmStackorderToplevelEnumProc,\n\t    (LPARAM) &pair) == 0) {\n\tTcl_Free(windows);\n\twindows = NULL;\n    }\n\n  done:\n    Tcl_DeleteHashTable(&table);\n    return windows;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRestackToplevel --\n *\n *\tThis function restacks a top-level window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr gets restacked as specified by aboveBelow and otherPtr. This\n *\tfunction doesn't return until the restack has taken effect and the\n *\tConfigureNotify event for it has been received.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmRestackToplevel(\n    TkWindow *winPtr,\t\t/* Window to restack. */\n    int aboveBelow,\t\t/* Gives relative position for restacking;\n\t\t\t\t * must be Above or Below. */\n    TkWindow *otherPtr)\t\t/* Window relative to which to restack; if\n\t\t\t\t * NULL, then winPtr gets restacked above or\n\t\t\t\t * below *all* siblings. */\n{\n    HWND hwnd, insertAfter;\n\n    /*\n     * Can't set stacking order properly until the window is on the screen\n     * (mapping it may give it a reparent window).\n     */\n\n    if (winPtr->window == None) {\n\tTk_MakeWindowExist((Tk_Window) winPtr);\n    }\n    if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {\n\tTkWmMapWindow(winPtr);\n    }\n    hwnd = (winPtr->wmInfoPtr->wrapper != NULL)\n\t? winPtr->wmInfoPtr->wrapper : Tk_GetHWND(winPtr->window);\n\n    if (otherPtr != NULL) {\n\tif (otherPtr->window == None) {\n\t    Tk_MakeWindowExist((Tk_Window) otherPtr);\n\t}\n\tif (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {\n\t    TkWmMapWindow(otherPtr);\n\t}\n\tinsertAfter = (otherPtr->wmInfoPtr->wrapper != NULL)\n\t\t? otherPtr->wmInfoPtr->wrapper : Tk_GetHWND(otherPtr->window);\n    } else {\n\tinsertAfter = NULL;\n    }\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\tSendMessageW(winPtr->wmInfoPtr->wrapper, TK_RAISEWINDOW,\n\t\t(WPARAM) insertAfter, aboveBelow);\n    } else {\n\tTkWinSetWindowPos(hwnd, insertAfter, aboveBelow);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmAddToColormapWindows --\n *\n *\tThis function is called to add a given window to the\n *\tWM_COLORMAP_WINDOWS property for its top-level, if it isn't already\n *\tthere. It is invoked by the Tk code that creates a new colormap, in\n *\torder to make sure that colormap information is propagated to the\n *\twindow manager by default.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets added to the WM_COLORMAP_WINDOWS property of its\n *\tnearest top-level ancestor, unless the colormaps have been set\n *\texplicitly with the \"wm colormapwindows\" command.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmAddToColormapWindows(\n    TkWindow *winPtr)\t\t/* Window with a non-default colormap. Should\n\t\t\t\t * not be a top-level window. */\n{\n    TkWindow *topPtr;\n    TkWindow **oldPtr, **newPtr;\n    Tcl_Size count, i;\n\n    if (winPtr->window == None) {\n\treturn;\n    }\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Window is being deleted. Skip the whole operation.\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_HIERARCHY) {\n\t    break;\n\t}\n    }\n    if (topPtr->wmInfoPtr == NULL) {\n\treturn;\n    }\n\n    if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {\n\treturn;\n    }\n\n    /*\n     * Make sure that the window isn't already in the list.\n     */\n\n    count = topPtr->wmInfoPtr->cmapCount;\n    oldPtr = topPtr->wmInfoPtr->cmapList;\n\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr) {\n\t    return;\n\t}\n    }\n\n    /*\n     * Make a new bigger array and use it to reset the property.\n     * Automatically add the toplevel itself as the last element of the list.\n     */\n\n    newPtr = (TkWindow **)Tcl_Alloc((count+2) * sizeof(TkWindow *));\n    if (count > 0) {\n\tmemcpy(newPtr, oldPtr, count * sizeof(TkWindow*));\n    }\n    if (count == 0) {\n\tcount++;\n    }\n    newPtr[count-1] = winPtr;\n    newPtr[count] = topPtr;\n    if (oldPtr != NULL) {\n\tTcl_Free(oldPtr);\n    }\n\n    topPtr->wmInfoPtr->cmapList = newPtr;\n    topPtr->wmInfoPtr->cmapCount = count+1;\n\n    /*\n     * Now we need to force the updated colormaps to be installed.\n     */\n\n    if (topPtr->wmInfoPtr == winPtr->dispPtr->foregroundWmPtr) {\n\tInstallColormaps(topPtr->wmInfoPtr->wrapper, WM_QUERYNEWPALETTE, true);\n    } else {\n\tInstallColormaps(topPtr->wmInfoPtr->wrapper, WM_PALETTECHANGED, false);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmRemoveFromColormapWindows --\n *\n *\tThis function is called to remove a given window from the\n *\tWM_COLORMAP_WINDOWS property for its top-level. It is invoked when\n *\twindows are deleted.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tWinPtr's window gets removed from the WM_COLORMAP_WINDOWS property of\n *\tits nearest top-level ancestor, unless the top-level itself is being\n *\tdeleted too.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWmRemoveFromColormapWindows(\n    TkWindow *winPtr)\t\t/* Window that may be present in\n\t\t\t\t * WM_COLORMAP_WINDOWS property for its\n\t\t\t\t * top-level. Should not be a top-level\n\t\t\t\t * window. */\n{\n    TkWindow *topPtr;\n    TkWindow **oldPtr;\n    Tcl_Size count, i, j;\n\n    for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {\n\tif (topPtr == NULL) {\n\t    /*\n\t     * Ancestors have been deleted, so skip the whole operation.\n\t     * Seems like this can't ever happen?\n\t     */\n\n\t    return;\n\t}\n\tif (topPtr->flags & TK_TOP_LEVEL) {\n\t    break;\n\t}\n    }\n    if (topPtr->flags & TK_ALREADY_DEAD) {\n\t/*\n\t * Top-level is being deleted, so there's no need to cleanup the\n\t * WM_COLORMAP_WINDOWS property.\n\t */\n\n\treturn;\n    }\n\n    if (topPtr->wmInfoPtr == NULL) {\n\treturn;\n    }\n\n    /*\n     * Find the window and slide the following ones down to cover it up.\n     */\n\n    count = topPtr->wmInfoPtr->cmapCount;\n    oldPtr = topPtr->wmInfoPtr->cmapList;\n    for (i = 0; i < count; i++) {\n\tif (oldPtr[i] == winPtr) {\n\t    for (j = i ; j < count-1; j++) {\n\t\toldPtr[j] = oldPtr[j+1];\n\t    }\n\t    topPtr->wmInfoPtr->cmapCount = count-1;\n\t    break;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinSetMenu--\n *\n *\tAssocicates a given HMENU to a window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tThe menu will end up being drawn in the window, and the geometry of\n *\tthe window will have to be changed.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinSetMenu(\n    Tk_Window tkwin,\t\t/* the window to put the menu in */\n    HMENU hMenu)\t\t/* the menu to set */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    /* Could be a Frame (i.e. not a Toplevel) */\n    if (wmPtr == NULL)\n\treturn;\n\n    wmPtr->hMenu = hMenu;\n    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tint syncPending = wmPtr->flags & WM_SYNC_PENDING;\n\n\twmPtr->flags |= WM_SYNC_PENDING;\n\tSetMenu(wmPtr->wrapper, hMenu);\n\tif (!syncPending) {\n\t    wmPtr->flags &= ~WM_SYNC_PENDING;\n\t}\n    }\n    if (!(winPtr->flags & TK_EMBEDDED)) {\n\tif (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {\n\t    Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\t    wmPtr->flags |= WM_UPDATE_PENDING|WM_MOVE_PENDING;\n\t}\n    } else {\n\tSendMessageW(wmPtr->wrapper, TK_SETMENU, (WPARAM) hMenu,\n\t\t(LPARAM) TkGetMenuHWND(tkwin));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ConfigureTopLevel --\n *\n *\tGenerate a ConfigureNotify event based on the current position\n *\tinformation. This function is called by TopLevelProc.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tQueues a new event.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nConfigureTopLevel(\n    WINDOWPOS *pos)\n{\n    TkWindow *winPtr = GetTopLevel(pos->hwnd);\n    WmInfo *wmPtr;\n    int state;\t\t\t/* Current window state. */\n    RECT rect;\n    WINDOWPLACEMENT windowPos;\n\n    if (winPtr == NULL) {\n\treturn;\n    }\n\n    wmPtr = winPtr->wmInfoPtr;\n\n    /*\n     * Determine the current window state.\n     */\n\n    if (!IsWindowVisible(wmPtr->wrapper)) {\n\tstate = WithdrawnState;\n    } else {\n\twindowPos.length = sizeof(WINDOWPLACEMENT);\n\tGetWindowPlacement(wmPtr->wrapper, &windowPos);\n\tswitch (windowPos.showCmd) {\n\tcase SW_SHOWMAXIMIZED:\n\t    state = ZoomState;\n\t    break;\n\tcase SW_SHOWMINIMIZED:\n\t    state = IconicState;\n\t    break;\n\tcase SW_SHOWNORMAL:\n\tdefault:\n\t    state = NormalState;\n\t    break;\n\t}\n    }\n\n    /*\n     * If the state of the window just changed, be sure to update the\n     * child window information.\n     */\n\n    if (wmPtr->hints.initial_state != state) {\n\twmPtr->hints.initial_state = state;\n\tswitch (state) {\n\tcase WithdrawnState:\n\tcase IconicState:\n\t    XUnmapWindow(winPtr->display, winPtr->window);\n\t    break;\n\n\tcase NormalState:\n\t    /*\n\t     * Schedule a geometry update. Since we ignore geometry requests\n\t     * while in any other state, the geometry info may be stale.\n\t     */\n\n\t    if (!(wmPtr->flags & WM_UPDATE_PENDING)) {\n\t\tTcl_DoWhenIdle(UpdateGeometryInfo, winPtr);\n\t\twmPtr->flags |= WM_UPDATE_PENDING;\n\t    }\n\t    /* fall through */\n\tcase ZoomState:\n\t    XMapWindow(winPtr->display, winPtr->window);\n\t    pos->flags |= SWP_NOMOVE | SWP_NOSIZE;\n\t    break;\n\t}\n    }\n\n    /*\n     * Don't report geometry changes in the Iconic or Withdrawn states.\n     */\n\n    if (state == WithdrawnState || state == IconicState) {\n\treturn;\n    }\n\n\n    /*\n     * Compute the current geometry of the client area, reshape the Tk window\n     * and generate a ConfigureNotify event.\n     */\n\n    GetClientRect(wmPtr->wrapper, &rect);\n    winPtr->changes.x = pos->x;\n    winPtr->changes.y = pos->y;\n    winPtr->changes.width = rect.right - rect.left;\n    winPtr->changes.height = rect.bottom - rect.top;\n    wmPtr->borderHeight = pos->cy - winPtr->changes.height;\n    MoveWindow(Tk_GetHWND(winPtr->window), 0, 0,\n\t    winPtr->changes.width, winPtr->changes.height, TRUE);\n    GenerateConfigureNotify(winPtr);\n\n    /*\n     * Update window manager geometry info if needed.\n     */\n\n    if (state == NormalState) {\n\n\t/*\n\t * Update size information from the event. There are a couple of\n\t * tricky points here:\n\t *\n\t * 1. If the user changed the size externally then set wmPtr->width\n\t *    and wmPtr->height just as if a \"wm geometry\" command had been\n\t *    invoked with the same information.\n\t * 2. However, if the size is changing in response to a request coming\n\t *    from us (sync is set), then don't set wmPtr->width or\n\t *    wmPtr->height (otherwise the window will stop tracking geometry\n\t *    manager requests).\n\t */\n\n\tif (!(wmPtr->flags & WM_SYNC_PENDING)) {\n\t    if (!(pos->flags & SWP_NOSIZE)) {\n\t\tif ((wmPtr->width == -1)\n\t\t\t&& (winPtr->changes.width == winPtr->reqWidth)) {\n\t\t    /*\n\t\t     * Don't set external width, since the user didn't change\n\t\t     * it from what the widgets asked for.\n\t\t     */\n\t\t} else {\n\t\t    if (wmPtr->gridWin != NULL) {\n\t\t\twmPtr->width = wmPtr->reqGridWidth\n\t\t\t\t+ (winPtr->changes.width - winPtr->reqWidth)\n\t\t\t\t/ wmPtr->widthInc;\n\t\t\tif (wmPtr->width < 0) {\n\t\t\t    wmPtr->width = 0;\n\t\t\t}\n\t\t    } else {\n\t\t\twmPtr->width = winPtr->changes.width;\n\t\t    }\n\t\t}\n\t\tif ((wmPtr->height == -1)\n\t\t\t&& (winPtr->changes.height == winPtr->reqHeight)) {\n\t\t    /*\n\t\t     * Don't set external height, since the user didn't change\n\t\t     * it from what the widgets asked for.\n\t\t     */\n\t\t} else {\n\t\t    if (wmPtr->gridWin != NULL) {\n\t\t\twmPtr->height = wmPtr->reqGridHeight\n\t\t\t\t+ (winPtr->changes.height - winPtr->reqHeight)\n\t\t\t\t/ wmPtr->heightInc;\n\t\t\tif (wmPtr->height < 0) {\n\t\t\t    wmPtr->height = 0;\n\t\t\t}\n\t\t    } else {\n\t\t\twmPtr->height = winPtr->changes.height;\n\t\t    }\n\t\t}\n\t\twmPtr->configWidth = winPtr->changes.width;\n\t\twmPtr->configHeight = winPtr->changes.height;\n\t    }\n\n\t    /*\n\t     * If the user moved the window, we should switch back to normal\n\t     * coordinates.\n\t     */\n\n\t    if (!(pos->flags & SWP_NOMOVE)) {\n\t\twmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);\n\t    }\n\t}\n\n\t/*\n\t * Update the wrapper window location information.\n\t */\n\n\tif (wmPtr->flags & WM_NEGATIVE_X) {\n\t    wmPtr->x = DisplayWidth(winPtr->display, winPtr->screenNum)\n\t\t    - winPtr->changes.x - (winPtr->changes.width\n\t\t    + wmPtr->borderWidth);\n\t} else {\n\t    wmPtr->x = winPtr->changes.x;\n\t}\n\tif (wmPtr->flags & WM_NEGATIVE_Y) {\n\t    wmPtr->y = DisplayHeight(winPtr->display, winPtr->screenNum)\n\t\t    - winPtr->changes.y - (winPtr->changes.height\n\t\t    + wmPtr->borderHeight);\n\t} else {\n\t    wmPtr->y = winPtr->changes.y;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateConfigureNotify --\n *\n *\tGenerate a ConfigureNotify event from the current geometry information\n *\tfor the specified toplevel window.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSends an X event.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateConfigureNotify(\n    TkWindow *winPtr)\n{\n    XEvent event;\n\n    /*\n     * Generate a ConfigureNotify event.\n     */\n\n    event.type = ConfigureNotify;\n    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);\n    event.xconfigure.send_event = False;\n    event.xconfigure.display = winPtr->display;\n    event.xconfigure.event = winPtr->window;\n    event.xconfigure.window = winPtr->window;\n    event.xconfigure.border_width = winPtr->changes.border_width;\n    event.xconfigure.override_redirect = winPtr->atts.override_redirect;\n    event.xconfigure.x = winPtr->changes.x;\n    event.xconfigure.y = winPtr->changes.y;\n    event.xconfigure.width = winPtr->changes.width;\n    event.xconfigure.height = winPtr->changes.height;\n    event.xconfigure.above = None;\n    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InstallColormaps --\n *\n *\tInstalls the colormaps associated with the toplevel which is currently\n *\tactive.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay change the system palette and generate damage.\n *\n *----------------------------------------------------------------------\n */\n\nstatic bool\nInstallColormaps(\n    HWND hwnd,\t\t\t/* Toplevel wrapper window whose colormaps\n\t\t\t\t * should be installed. */\n    int message,\t\t/* Either WM_PALETTECHANGED or\n\t\t\t\t * WM_QUERYNEWPALETTE */\n    bool isForemost)\t\t/* true if window is foremost, else false */\n{\n    Tcl_Size i;\n    HDC dc;\n    HPALETTE oldPalette;\n    TkWindow *winPtr = GetTopLevel(hwnd);\n    WmInfo *wmPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (winPtr == NULL || (winPtr->flags & TK_ALREADY_DEAD)) {\n\treturn false;\n    }\n\n    wmPtr = winPtr->wmInfoPtr;\n\n    if (message == WM_QUERYNEWPALETTE) {\n\t/*\n\t * Case 1: This window is about to become the foreground window, so we\n\t * need to install the primary palette. If the system palette was\n\t * updated, then Windows will generate a WM_PALETTECHANGED message.\n\t * Otherwise, we have to synthesize one in order to ensure that the\n\t * secondary palettes are installed properly.\n\t */\n\n\twinPtr->dispPtr->foregroundWmPtr = wmPtr;\n\n\tif (wmPtr->cmapCount > 0) {\n\t    winPtr = wmPtr->cmapList[0];\n\t}\n\n\ttsdPtr->systemPalette = TkWinGetPalette(winPtr->atts.colormap);\n\tdc = GetDC(hwnd);\n\toldPalette = SelectPalette(dc, tsdPtr->systemPalette, FALSE);\n\tif (RealizePalette(dc)) {\n\t    RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);\n\t} else if (wmPtr->cmapCount > 1) {\n\t    SelectPalette(dc, oldPalette, TRUE);\n\t    RealizePalette(dc);\n\t    ReleaseDC(hwnd, dc);\n\t    SendMessageW(hwnd, WM_PALETTECHANGED, (WPARAM) hwnd, (LPARAM) NULL);\n\t    return true;\n\t}\n    } else {\n\t/*\n\t * Window is being notified of a change in the system palette. If this\n\t * window is the foreground window, then we should only install the\n\t * secondary palettes, since the primary was installed in response to\n\t * the WM_QUERYPALETTE message. Otherwise, install all of the\n\t * palettes.\n\t */\n\n\n\tif (!isForemost) {\n\t    if (wmPtr->cmapCount > 0) {\n\t\twinPtr = wmPtr->cmapList[0];\n\t    }\n\t    i = 1;\n\t} else {\n\t    if (wmPtr->cmapCount <= 1) {\n\t\treturn TRUE;\n\t    }\n\t    winPtr = wmPtr->cmapList[1];\n\t    i = 2;\n\t}\n\tdc = GetDC(hwnd);\n\toldPalette = SelectPalette(dc,\n\t\tTkWinGetPalette(winPtr->atts.colormap), TRUE);\n\tif (RealizePalette(dc)) {\n\t    RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);\n\t}\n\tfor (; i < wmPtr->cmapCount; i++) {\n\t    winPtr = wmPtr->cmapList[i];\n\t    SelectPalette(dc, TkWinGetPalette(winPtr->atts.colormap), TRUE);\n\t    if (RealizePalette(dc)) {\n\t\tRefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);\n\t    }\n\t}\n    }\n\n    SelectPalette(dc, oldPalette, TRUE);\n    RealizePalette(dc);\n    ReleaseDC(hwnd, dc);\n    return true;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RefreshColormap --\n *\n *\tThis function is called to force all of the windows that use a given\n *\tcolormap to redraw themselves. The quickest way to do this is to\n *\titerate over the toplevels, looking in the cmapList for matches. This\n *\twill quickly eliminate subtrees that don't use a given colormap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tCauses damage events to be generated.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRefreshColormap(\n    Colormap colormap,\n    TkDisplay *dispPtr)\n{\n    WmInfo *wmPtr;\n    Tcl_Size i;\n\n    for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {\n\tif (wmPtr->cmapCount > 0) {\n\t    for (i = 0; i < wmPtr->cmapCount; i++) {\n\t\tif ((wmPtr->cmapList[i]->atts.colormap == colormap)\n\t\t\t&& Tk_IsMapped(wmPtr->cmapList[i])) {\n\t\t    InvalidateSubTree(wmPtr->cmapList[i], colormap);\n\t\t}\n\t    }\n\t} else if ((wmPtr->winPtr->atts.colormap == colormap)\n\t\t&& Tk_IsMapped(wmPtr->winPtr)) {\n\t    InvalidateSubTree(wmPtr->winPtr, colormap);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvalidateSubTree --\n *\n *\tThis function recursively generates damage for a window and all of its\n *\tmapped children that belong to the same toplevel and are using the\n *\tspecified colormap.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tGenerates damage for the specified subtree.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInvalidateSubTree(\n    TkWindow *winPtr,\n    Colormap colormap)\n{\n    TkWindow *childPtr;\n\n    /*\n     * Generate damage for the current window if it is using the specified\n     * colormap.\n     */\n\n    if (winPtr->atts.colormap == colormap) {\n\tInvalidateRect(Tk_GetHWND(winPtr->window), NULL, FALSE);\n    }\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\t/*\n\t * We can stop the descent when we hit an unmapped or toplevel window.\n\t */\n\n\tif (!Tk_TopWinHierarchy(childPtr) && Tk_IsMapped(childPtr)) {\n\t    InvalidateSubTree(childPtr, colormap);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * InvalidateSubTreeDepth --\n *\n *\tThis function recursively updates depth info for a window and all of\n *\tits children that belong to the same toplevel.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets the depth of each window to that of the display.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nInvalidateSubTreeDepth(\n    TkWindow *winPtr)\n{\n    Display *display = Tk_Display(winPtr);\n    int screenNum = Tk_ScreenNumber(winPtr);\n    TkWindow *childPtr;\n\n    winPtr->depth = DefaultDepth(display, screenNum);\n\n#if 0\n    /*\n     * XXX: What other elements may require changes? Changing just the depth\n     * works for standard windows and 16/24/32-bpp changes. I suspect 8-bit\n     * (palettized) displays may require colormap and/or visual changes as\n     * well.\n     */\n\n    if (winPtr->window) {\n\tInvalidateRect(Tk_GetHWND(winPtr->window), NULL, FALSE);\n    }\n    winPtr->visual = DefaultVisual(display, screenNum);\n    winPtr->atts.colormap = DefaultColormap(display, screenNum);\n    winPtr->dirtyAtts |= CWColormap;\n#endif\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\t/*\n\t * We can stop the descent when we hit a non-embedded toplevel window,\n\t * as it should get its own message.\n\t */\n\n\tif (childPtr->flags & TK_EMBEDDED || !Tk_TopWinHierarchy(childPtr)) {\n\t    InvalidateSubTreeDepth(childPtr);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetSystemPalette --\n *\n *\tRetrieves the currently installed foreground palette.\n *\n * Results:\n *\tReturns the global foreground palette, if there is one. Otherwise,\n *\treturns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHPALETTE\nTkWinGetSystemPalette(void)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    return tsdPtr->systemPalette;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMinSize --\n *\n *\tThis function computes the current minWidth and minHeight values for a\n *\twindow, taking into account the possibility that they may be\n *\tdefaulted.\n *\n * Results:\n *\tThe values at *minWidthPtr and *minHeightPtr are filled in with the\n *\tminimum allowable dimensions of wmPtr's window, in grid units. If the\n *\trequested minimum is smaller than the system required minimum, then\n *\tthis function computes the smallest size that will satisfy both the\n *\tsystem and the grid constraints.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMinSize(\n    WmInfo *wmPtr,\t\t/* Window manager information for the\n\t\t\t\t * window. */\n    int *minWidthPtr,\t\t/* Where to store the current minimum width of\n\t\t\t\t * the window. */\n    int *minHeightPtr)\t\t/* Where to store the current minimum height\n\t\t\t\t * of the window. */\n{\n    int tmp, base;\n    TkWindow *winPtr = wmPtr->winPtr;\n\n    /*\n     * Compute the minimum width by taking the default client size and\n     * rounding it up to the nearest grid unit. Return the greater of the\n     * default minimum and the specified minimum.\n     */\n\n    tmp = wmPtr->defMinWidth - wmPtr->borderWidth;\n    if (tmp < 0) {\n\ttmp = 0;\n    }\n    if (wmPtr->gridWin != NULL) {\n\tbase = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\ttmp = ((tmp - base) + wmPtr->widthInc - 1)/wmPtr->widthInc;\n    }\n    if (tmp < wmPtr->minWidth) {\n\ttmp = wmPtr->minWidth;\n    }\n    *minWidthPtr = tmp;\n\n    /*\n     * Compute the minimum height in a similar fashion.\n     */\n\n    tmp = wmPtr->defMinHeight - wmPtr->borderHeight;\n    if (tmp < 0) {\n\ttmp = 0;\n    }\n    if (wmPtr->gridWin != NULL) {\n\tbase = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc);\n\tif (base < 0) {\n\t    base = 0;\n\t}\n\ttmp = ((tmp - base) + wmPtr->heightInc - 1)/wmPtr->heightInc;\n    }\n    if (tmp < wmPtr->minHeight) {\n\ttmp = wmPtr->minHeight;\n    }\n    *minHeightPtr = tmp;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetMaxSize --\n *\n *\tThis function computes the current maxWidth and maxHeight values for a\n *\twindow, taking into account the possibility that they may be\n *\tdefaulted.\n *\n * Results:\n *\tThe values at *maxWidthPtr and *maxHeightPtr are filled in with the\n *\tmaximum allowable dimensions of wmPtr's window, in grid units. If no\n *\tmaximum has been specified for the window, then this function computes\n *\tthe largest sizes that will fit on the screen.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetMaxSize(\n    WmInfo *wmPtr,\t\t/* Window manager information for the\n\t\t\t\t * window. */\n    int *maxWidthPtr,\t\t/* Where to store the current maximum width of\n\t\t\t\t * the window. */\n    int *maxHeightPtr)\t\t/* Where to store the current maximum height\n\t\t\t\t * of the window. */\n{\n    int tmp;\n\n    if (wmPtr->maxWidth > 0) {\n\t*maxWidthPtr = wmPtr->maxWidth;\n    } else {\n\t/*\n\t * Must compute a default width. Fill up the display, leaving a bit of\n\t * extra space for the window manager's borders.\n\t */\n\n\ttmp = wmPtr->defMaxWidth - wmPtr->borderWidth;\n\tif (wmPtr->gridWin != NULL) {\n\t    /*\n\t     * Gridding is turned on; convert from pixels to grid units.\n\t     */\n\n\t    tmp = wmPtr->reqGridWidth\n\t\t    + (tmp - wmPtr->winPtr->reqWidth)/wmPtr->widthInc;\n\t}\n\t*maxWidthPtr = tmp;\n    }\n    if (wmPtr->maxHeight > 0) {\n\t*maxHeightPtr = wmPtr->maxHeight;\n    } else {\n\ttmp = wmPtr->defMaxHeight - wmPtr->borderHeight;\n\tif (wmPtr->gridWin != NULL) {\n\t    tmp = wmPtr->reqGridHeight\n\t\t    + (tmp - wmPtr->winPtr->reqHeight)/wmPtr->heightInc;\n\t}\n\t*maxHeightPtr = tmp;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TopLevelProc --\n *\n *\tCallback from Windows whenever an event occurs on a top level window.\n *\n * Results:\n *\tStandard Windows return value.\n *\n * Side effects:\n *\tDefault window behavior.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nTopLevelProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    if (message == WM_WINDOWPOSCHANGED || message == WM_WINDOWPOSCHANGING) {\n\tWINDOWPOS *pos = (WINDOWPOS *) lParam;\n\tTkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(pos->hwnd);\n\n\tif (winPtr == NULL) {\n\t    return 0;\n\t}\n\n\t/*\n\t * Update the shape of the contained window.\n\t */\n\n\tif (!(pos->flags & SWP_NOSIZE)) {\n\t    winPtr->changes.width = pos->cx;\n\t    winPtr->changes.height = pos->cy;\n\t}\n\tif (!(pos->flags & SWP_NOMOVE)) {\n\t    int result = (int)SendMessageW(winPtr->wmInfoPtr->wrapper,\n\t\t    TK_MOVEWINDOW, -1, -1);\n\t    winPtr->wmInfoPtr->x = winPtr->changes.x = result >> 16;\n\t    winPtr->wmInfoPtr->y = winPtr->changes.y = result & 0xffff;\n\t}\n\n\tGenerateConfigureNotify(winPtr);\n\n\tTcl_ServiceAll();\n\treturn 0;\n    }\n    return TkWinChildProc(hwnd, message, wParam, lParam);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * WmProc --\n *\n *\tCallback from Windows whenever an event occurs on the decorative\n *\tframe.\n *\n * Results:\n *\tStandard Windows return value.\n *\n * Side effects:\n *\tDefault window behavior.\n *\n *----------------------------------------------------------------------\n */\n\nstatic LRESULT CALLBACK\nWmProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    static int inMoveSize = 0;\n    static int oldMode;\t\t/* This static is set upon entering move/size\n\t\t\t\t * mode and is used to reset the service mode\n\t\t\t\t * after leaving move/size mode. Note that\n\t\t\t\t * this mechanism assumes move/size is only\n\t\t\t\t * one level deep. */\n    LRESULT result = 0;\n    TkWindow *winPtr = NULL;\n\n    switch (message) {\n    case WM_KILLFOCUS:\n    case WM_ERASEBKGND:\n\tresult = 0;\n\tgoto done;\n\n    case WM_ENTERSIZEMOVE:\n\tinMoveSize = 1;\n\n\t/*\n\t * Cancel any current mouse timer. If the mouse timer fires during the\n\t * size/move mouse capture, it will release the capture, which is\n\t * wrong.\n\t */\n\n\tTkWinCancelMouseTimer();\n\n\toldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);\n\tbreak;\n\n    case WM_ACTIVATE:\n\tif (WA_ACTIVE == LOWORD(wParam)) {\n\t    winPtr = GetTopLevel(hwnd);\n\t    if (winPtr && (TkGrabState(winPtr) == TK_GRAB_EXCLUDED)) {\n\t\t/*\n\t\t * There is a grab in progress so queue an Activate event\n\t\t */\n\n\t\tGenerateActivateEvent(winPtr, &inMoveSize);\n\t\tresult = 0;\n\t\tgoto done;\n\t    }\n\t}\n\t/* fall through */\n\n    case WM_EXITSIZEMOVE:\n\tif (inMoveSize) {\n\t    inMoveSize = 0;\n\t    Tcl_SetServiceMode(oldMode);\n\t}\n\tbreak;\n\n    case WM_GETMINMAXINFO:\n\tSetLimits(hwnd, (MINMAXINFO *) lParam);\n\tresult = 0;\n\tgoto done;\n\n    case WM_DISPLAYCHANGE:\n\t/*\n\t * Display and/or color resolution changed.\n\t */\n\n\twinPtr = GetTopLevel(hwnd);\n\tif (winPtr) {\n\t    Screen *screen = Tk_Screen(winPtr);\n\t    if (DefaultDepthOfScreen(screen) != (int) wParam) {\n\t\t/*\n\t\t * Color resolution changed, so do extensive rebuild of\n\t\t * display parameters. This will affect the display for all Tk\n\t\t * windows. We will receive this event for each toplevel, but\n\t\t * this check makes us update only once, for the first\n\t\t * toplevel that receives the message.\n\t\t */\n\n\t\tTkWinDisplayChanged(Tk_Display(winPtr));\n\t    } else {\n\t\tHDC dc = GetDC(NULL);\n\n\t\tWidthOfScreen(screen) = LOWORD(lParam);\t\t/* horizontal res */\n\t\tHeightOfScreen(screen) = HIWORD(lParam);\t/* vertical res */\n\t\tWidthMMOfScreen(screen) = MulDiv(WidthOfScreen(screen), 254,\n\t\t\tGetDeviceCaps(dc, LOGPIXELSX) * 10);\n\t\tHeightMMOfScreen(screen) = MulDiv(HeightOfScreen(screen), 254,\n\t\t\tGetDeviceCaps(dc, LOGPIXELSY) * 10);\n\t\tReleaseDC(NULL, dc);\n\t    }\n\t    if (Tk_Depth(winPtr) != (int) wParam) {\n\t\t/*\n\t\t * Defer the window depth check to here so that each toplevel\n\t\t * will properly update depth info.\n\t\t */\n\n\t\tInvalidateSubTreeDepth(winPtr);\n\t    }\n\t}\n\tresult = 0;\n\tgoto done;\n\n    case WM_SYSCOLORCHANGE:\n\t/*\n\t * XXX: Called when system color changes. We need to update any\n\t * widgets that use a system color.\n\t */\n\n\tbreak;\n\n    case WM_PALETTECHANGED:\n\tresult = InstallColormaps(hwnd, WM_PALETTECHANGED,\n\t\thwnd == (HWND) wParam);\n\tgoto done;\n\n    case WM_QUERYNEWPALETTE:\n\tresult = InstallColormaps(hwnd, WM_QUERYNEWPALETTE, true);\n\tgoto done;\n\n    case WM_SETTINGCHANGE:\n\tif (wParam == SPI_SETNONCLIENTMETRICS) {\n\t    winPtr = GetTopLevel(hwnd);\n\t    TkWinSetupSystemFonts(winPtr->mainPtr);\n\t    result = 0;\n\t    goto done;\n\t}\n\tbreak;\n\n    case WM_WINDOWPOSCHANGED:\n\tConfigureTopLevel((WINDOWPOS *) lParam);\n\tresult = 0;\n\tgoto done;\n\n    case WM_NCHITTEST: {\n\twinPtr = GetTopLevel(hwnd);\n\tif (winPtr && (TkGrabState(winPtr) == TK_GRAB_EXCLUDED)) {\n\t    /*\n\t     * This window is outside the grab hierarchy, so don't let any of\n\t     * the normal non-client processing occur. Note that this\n\t     * implementation is not strictly correct because the grab might\n\t     * change between now and when the event would have been processed\n\t     * by Tk, but it's close enough.\n\t     */\n\n\t    result = HTCLIENT;\n\t    goto done;\n\t}\n\tbreak;\n    }\n\n    case WM_MOUSEACTIVATE: {\n\twinPtr = GetTopLevel((HWND) wParam);\n\tif (winPtr && (TkGrabState(winPtr) != TK_GRAB_EXCLUDED)) {\n\t    /*\n\t     * This allows us to pass the message onto the native menus [Bug:\n\t     * 2272]\n\t     */\n\n\t    result = DefWindowProcW(hwnd, message, wParam, lParam);\n\t    goto done;\n\t}\n\n\t/*\n\t * Don't activate the window yet since there is a grab that takes\n\t * precedence. Instead we need to queue an event so we can check the\n\t * grab state right before we handle the mouse event.\n\t */\n\n\tif (winPtr) {\n\t    GenerateActivateEvent(winPtr, &inMoveSize);\n\t}\n\tresult = MA_NOACTIVATE;\n\tgoto done;\n    }\n\n    case WM_QUERYENDSESSION: {\n\tXEvent event;\n\n\t/*\n\t * Synthesize WM_SAVE_YOURSELF wm protocol message on Windows logout\n\t * or restart.\n\t */\n\twinPtr = GetTopLevel(hwnd);\n\tevent.xclient.message_type =\n\t    Tk_InternAtom((Tk_Window) winPtr, \"WM_PROTOCOLS\");\n\tevent.xclient.data.l[0] =\n\t    Tk_InternAtom((Tk_Window) winPtr, \"WM_SAVE_YOURSELF\");\n\tTkWmProtocolEventProc(winPtr, &event);\n\tbreak;\n    }\n\n    default:\n\tbreak;\n    }\n\n    winPtr = GetTopLevel(hwnd);\n    switch(message) {\n    case WM_SYSCOMMAND:\n\t/*\n\t * If there is a grab in effect then ignore the minimize command\n\t * unless the grab is on the main window (.). This is to permit\n\t * applications that leave a grab on . to work normally.\n\t * All other toplevels are deemed non-minimizable when a grab is\n\t * present.\n\t * If there is a grab in effect and this window is outside the\n\t * grab tree then ignore all system commands. [Bug 1847002]\n\t */\n\n\tif (winPtr) {\n\t    int cmd = wParam & 0xfff0;\n\t    int grab = TkGrabState(winPtr);\n\t    if ((SC_MINIMIZE == cmd)\n\t\t&& (grab == TK_GRAB_IN_TREE || grab == TK_GRAB_ANCESTOR)\n\t\t&& (winPtr != winPtr->mainPtr->winPtr)) {\n\t\tgoto done;\n\t    }\n\t    if (grab == TK_GRAB_EXCLUDED\n\t\t&& !(SC_MOVE == cmd || SC_SIZE == cmd)) {\n\t\tgoto done;\n\t    }\n\t}\n\t/* fall through */\n\n    case WM_INITMENU:\n    case WM_COMMAND:\n    case WM_MENUCHAR:\n    case WM_MEASUREITEM:\n    case WM_DRAWITEM:\n    case WM_MENUSELECT:\n    case WM_ENTERIDLE:\n    case WM_INITMENUPOPUP:\n\tif (winPtr) {\n\t    HWND hMenuHWnd = TkGetEmbeddedMenuHWND((Tk_Window) winPtr);\n\n\t    if (hMenuHWnd) {\n\t\tif (SendMessageW(hMenuHWnd, message, wParam, lParam)) {\n\t\t    goto done;\n\t\t}\n\t    } else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,\n\t\t    &result)) {\n\t\tgoto done;\n\t    }\n\t}\n\tbreak;\n    }\n\n    if (winPtr && winPtr->window) {\n\tHWND child = Tk_GetHWND(winPtr->window);\n\n\tif (message == WM_SETFOCUS) {\n\t    SetFocus(child);\n\t    result = 0;\n\t} else if (!TkTranslateWinEvent(child, message, wParam, lParam,\n\t\t&result)) {\n\t    result = DefWindowProcW(hwnd, message, wParam, lParam);\n\t}\n    } else {\n\tresult = DefWindowProcW(hwnd, message, wParam, lParam);\n    }\n\n  done:\n    Tcl_ServiceAll();\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpMakeMenuWindow --\n *\n *\tConfigure the window to be either a pull-down (or pop-up) menu, or as\n *\ta toplevel (torn-off) menu or palette.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tChanges the style bit used to create a new toplevel.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpMakeMenuWindow(\n    Tk_Window tkwin,\t\t/* New window. */\n    int transient)\t\t/* 1 means menu is only posted briefly as a\n\t\t\t\t * popup or pulldown or cascade. 0 means menu\n\t\t\t\t * is always visible, e.g. as a torn-off menu.\n\t\t\t\t * Determines whether save_under and\n\t\t\t\t * override_redirect should be set. */\n{\n    XSetWindowAttributes atts;\n\n    if (transient) {\n\tatts.override_redirect = True;\n\tatts.save_under = True;\n    } else {\n\tatts.override_redirect = False;\n\tatts.save_under = False;\n    }\n\n    if ((atts.override_redirect != Tk_Attributes(tkwin)->override_redirect)\n\t    || (atts.save_under != Tk_Attributes(tkwin)->save_under)) {\n\tTk_ChangeWindowAttributes(tkwin, CWOverrideRedirect|CWSaveUnder,\n\t\t&atts);\n    }\n\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetWrapperWindow --\n *\n *\tGets the Windows HWND for a given window.\n *\n * Results:\n *\tReturns the wrapper window for a Tk window.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHWND\nTkWinGetWrapperWindow(\n    Tk_Window tkwin)\t\t/* The window we need the wrapper from */\n{\n    TkWindow *winPtr = (TkWindow *) tkwin;\n\n    return winPtr->wmInfoPtr->wrapper;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWmFocusToplevel --\n *\n *\tThis is a utility function invoked by focus-management code. It exists\n *\tbecause of the extra wrapper windows that exist under Unix; its job is\n *\tto map from wrapper windows to the corresponding toplevel windows. On\n *\tPCs and Macs there are no wrapper windows so no mapping is necessary;\n *\tthis function just determines whether a window is a toplevel or not.\n *\n * Results:\n *\tIf winPtr is a toplevel window, returns the pointer to the window;\n *\totherwise returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkWmFocusToplevel(\n    TkWindow *winPtr)\t\t/* Window that received a focus-related\n\t\t\t\t * event. */\n{\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\treturn NULL;\n    }\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetWrapperWindow --\n *\n *\tThis is a utility function invoked by focus-management code. It maps\n *\tto the wrapper for a top-level, which is just the same as the\n *\ttop-level on Macs and PCs.\n *\n * Results:\n *\tIf winPtr is a toplevel window, returns the pointer to the window;\n *\totherwise returns NULL.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTkWindow *\nTkpGetWrapperWindow(\n    TkWindow *winPtr)\t\t/* Window that received a focus-related\n\t\t\t\t * event. */\n{\n    if (!(winPtr->flags & TK_TOP_HIERARCHY)) {\n\treturn NULL;\n    }\n    return winPtr;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateActivateEvent --\n *\n *\tThis function is called to activate a Tk window.\n */\n\nstatic void\nGenerateActivateEvent(TkWindow * winPtr, const int *flagPtr)\n{\n    ActivateEvent *eventPtr = (ActivateEvent *)Tcl_Alloc(sizeof(ActivateEvent));\n\n    eventPtr->ev.proc = ActivateWindow;\n    eventPtr->winPtr = winPtr;\n    eventPtr->flagPtr = flagPtr;\n    eventPtr->hwnd = Tk_GetHWND(winPtr->window);\n    Tcl_QueueEvent((Tcl_Event *)eventPtr, TCL_QUEUE_TAIL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * ActivateWindow --\n *\n *\tThis function is called when an ActivateEvent is processed.\n *\n * Results:\n *\tReturns 1 to indicate that the event was handled, else 0.\n *\n * Side effects:\n *\tMay activate the toplevel window associated with the event.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nActivateWindow(\n    Tcl_Event *evPtr,\t\t/* Pointer to ActivateEvent. */\n    int flags)\t\t\t/* Notifier event mask. */\n{\n    ActivateEvent *eventPtr = (ActivateEvent *)evPtr;\n    TkWindow *winPtr = eventPtr->winPtr;\n\n    if (! (flags & TCL_WINDOW_EVENTS)) {\n\treturn 0;\n    }\n\n    /*\n     * Ensure the window has not been destroyed while we delayed\n     * processing the WM_ACTIVATE message [Bug 2899949].\n     */\n\n    if (!IsWindow(eventPtr->hwnd)) {\n\treturn 1;\n    }\n\n    /*\n     * If the toplevel is in the middle of a move or size operation then\n     * we must delay handling of this event to avoid stealing the focus\n     * while the window manager is in control.\n     */\n\n    if (eventPtr->flagPtr && *eventPtr->flagPtr) {\n\treturn 0;\n    }\n\n    /*\n     * If the window is excluded by a grab, call SetFocus on the grabbed\n     * window instead. [Bug 220908]\n     */\n\n    if (winPtr) {\n\tWindow window;\n\tif (TkGrabState(winPtr) != TK_GRAB_EXCLUDED) {\n\t    window = winPtr->window;\n\t} else {\n\t    window = winPtr->dispPtr->grabWinPtr->window;\n\t}\n\n\t/*\n\t * Ensure the window was not destroyed while we were postponing\n\t * the activation [Bug 2799589]\n\t */\n\n\tif (window) {\n\t    SetFocus(Tk_GetHWND(window));\n\t}\n    }\n\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinSetForegroundWindow --\n *\n *\tThis function is a wrapper for SetForegroundWindow, calling it on the\n *\twrapper window because it has no affect on child windows.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tMay activate the toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinSetForegroundWindow(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (wmPtr->wrapper != NULL) {\n\tSetForegroundWindow(wmPtr->wrapper);\n    } else {\n\tSetForegroundWindow(Tk_GetHWND(winPtr->window));\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelWithdraw --\n *\n *\tThis function is to be used by a window manager to withdraw a toplevel\n *\twindow.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tMay withdraw the toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpWinToplevelWithDraw(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n    int resetTempStyle = 0;\n    LONG_PTR exStyle = 0;\n\n    /*\n     * Special handling of transient toplevels (wmPtr->containerPtr != NULL),\n     * in order to work around a Windows 10 & 11 problem where withdrawn\n     * transients still appear in the thumbnail preview of the parent window,\n     * when hovering over it in the Windows taskbar.  Temporarily setting this\n     * window style to include WS_EX_TOOLWINDOW prevents it being captured in\n     * the Windows thumbnail preview.\n     * See ticket 91d0e9d8.\n     */\n\n    if (!(wmPtr->flags & WM_WITHDRAWN)\n\t     && !(wmPtr->flags & TK_EMBEDDED)\n\t     && !(wmPtr->flags & WM_NEVER_MAPPED)\n\t     && (wmPtr->containerPtr != NULL)) {\n\texStyle = GetWindowLongPtrW(wmPtr->wrapper, GWL_EXSTYLE);\n\tif ( !(exStyle & WS_EX_TOOLWINDOW) ) {\n\t    SetWindowLongPtrW(wmPtr->wrapper, GWL_EXSTYLE,\n\t\t     exStyle | WS_EX_TOOLWINDOW);\n\t    resetTempStyle=1;\n\t}\n    }\n\n    wmPtr->flags |= WM_WITHDRAWN;\n    TkpWmSetState(winPtr, WithdrawnState);\n\n    if (resetTempStyle) {\n\tSetWindowLongPtrW(wmPtr->wrapper, GWL_EXSTYLE,\n\t\texStyle & ~WS_EX_TOOLWINDOW);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelIconify --\n *\n *\tThis function is to be used by a window manager to iconify a toplevel\n *\twindow.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tMay iconify the toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpWinToplevelIconify(\n    TkWindow *winPtr)\n{\n    TkpWmSetState(winPtr, IconicState);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelDeiconify --\n *\n *\tThis function is to be used by a window manager to deiconify a toplevel\n *\twindow.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tMay deiconify the toplevel window.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpWinToplevelDeiconify(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    wmPtr->flags &= ~WM_WITHDRAWN;\n\n    /*\n     * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may need to\n     * be called first to update a withdrawn toplevel's geometry before it is\n     * deiconified by TkpWmSetState. Don't bother if we've never been mapped.\n     */\n\n    if ((wmPtr->flags & WM_UPDATE_PENDING)\n\t    && !(wmPtr->flags & WM_NEVER_MAPPED)) {\n\tTcl_CancelIdleCall(UpdateGeometryInfo, winPtr);\n\tUpdateGeometryInfo(winPtr);\n    }\n\n    /*\n     * If we were in the ZoomState (maximized), 'wm deiconify' should not\n     * cause the window to shrink\n     */\n\n    if (wmPtr->hints.initial_state == ZoomState) {\n\tTkpWmSetState(winPtr, ZoomState);\n    } else {\n\tTkpWmSetState(winPtr, NormalState);\n    }\n\n    /*\n     * An unmapped window will be mapped at idle time by a call to MapFrame.\n     * That calls CreateWrapper which sets the focus and raises the window.\n     */\n\n    if (wmPtr->flags & WM_NEVER_MAPPED) {\n\treturn;\n    }\n\n    /*\n     * Follow Windows-like style here, raising the window to the top.\n     */\n\n    TkWmRestackToplevel(winPtr, Above, NULL);\n    if (!(Tk_Attributes((Tk_Window) winPtr)->override_redirect)) {\n\tTkSetFocusWin(winPtr, 1);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinGeometryIsControlledByWm --\n *\n *\tThis function is to be used by a window manager to see if wm has\n *\tcanceled geometry control.\n *\n * Results:\n *\t0 - if the window manager has canceled its control\n *\t1 - if the window manager controls the geometry\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nlong\nTkpWinToplevelIsControlledByWm(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (!wmPtr) {\n\treturn 0;\n    }\n    return ((wmPtr->width != -1) && (wmPtr->height != -1)) ? 1 : 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelMove --\n *\n *\tThis function is to be used by a container to move an embedded window.\n *\n * Results:\n *\tposition of the upper left frame in a 32-bit long:\n *\t\t16-MSBits - x; 16-LSBits - y\n *\n * Side effects:\n *\tMay move the embedded window.\n *\n *----------------------------------------------------------------------\n */\n\nlong\nTkpWinToplevelMove(\n    TkWindow *winPtr,\n    int x, int y)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (wmPtr && x >= 0 && y >= 0 && !TkpWinToplevelIsControlledByWm(winPtr)) {\n\tTk_MoveToplevelWindow((Tk_Window) winPtr, x, y);\n    }\n    return ((winPtr->changes.x << 16) & 0xffff0000)\n\t    | (winPtr->changes.y & 0xffff);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelOverrideRedirect --\n *\n *\tThis function is to be used by a container to overrideredirect the\n *\tcontaner's frame window.\n *\n * Results:\n *\tThe current overrideredirect value\n *\n * Side effects:\n *\tMay change the overrideredirect value of the container window\n *\n *----------------------------------------------------------------------\n */\n\nlong\nTkpWinToplevelOverrideRedirect(\n    TkWindow *winPtr,\n    int reqValue)\n{\n    int curValue;\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;\n    if (reqValue < 0) {\n\treturn curValue;\n    }\n\n    if (curValue != reqValue) {\n\tXSetWindowAttributes atts;\n\n\t/*\n\t * Only do this if we are really changing value, because it causes\n\t * some funky stuff to occur\n\t */\n\n\tatts.override_redirect = reqValue ? True : False;\n\tTk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,\n\t\t&atts);\n\tif (!(wmPtr->flags & (WM_NEVER_MAPPED))\n\t\t&& !(winPtr->flags & TK_EMBEDDED)) {\n\t    UpdateWrapper(winPtr);\n\t}\n    }\n    return reqValue;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpWinToplevelDetachWindow --\n *\n *\tThis function is to be used for changing a toplevel's wrapper or\n *\tcontainer.\n *\n * Results:\n *\tThe window's wrapper/container is removed.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpWinToplevelDetachWindow(\n    TkWindow *winPtr)\n{\n    WmInfo *wmPtr = winPtr->wmInfoPtr;\n\n    if (winPtr->flags & TK_EMBEDDED) {\n\tint state = (int)(SendMessageW(wmPtr->wrapper, TK_STATE, -1, -1) - 1);\n\n\tSendMessageW(wmPtr->wrapper, TK_SETMENU, 0, 0);\n\tSendMessageW(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);\n\twinPtr->flags &= ~TK_EMBEDDED;\n\twinPtr->privatePtr = NULL;\n\twmPtr->wrapper = NULL;\n\tif (state >= 0 && state <= 3) {\n\t    wmPtr->hints.initial_state = state;\n\t}\n    }\n    if (winPtr->flags & TK_TOP_LEVEL) {\n\tTkpWinToplevelOverrideRedirect(winPtr, 1);\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * RemapWindows\n *\n *\tAdjust parent/child relation ships of the given window hierarchy.\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tkeeps windowing system happy\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nRemapWindows(\n    TkWindow *winPtr,\n    HWND parentHWND)\n{\n    TkWindow *childPtr;\n    const char *className = Tk_Class(winPtr);\n\n    /*\n     * Skip menus as they are handled differently.\n     */\n\n    if (className != NULL && strcmp(className, \"Menu\") == 0) {\n\treturn;\n    }\n    if (winPtr->window) {\n\tSetParent(Tk_GetHWND(winPtr->window), parentHWND);\n    }\n\n    /*\n     * Repeat for all the children.\n     */\n\n    for (childPtr = winPtr->childList; childPtr != NULL;\n\t    childPtr = childPtr->nextPtr) {\n\tRemapWindows(childPtr,\n\t\twinPtr->window ? Tk_GetHWND(winPtr->window) : NULL);\n    }\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/tkWinX.c",
    "content": "/*\n * tkWinX.c --\n *\n *\tThis file contains Windows emulation procedures for X routines.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 1994 Software Research Associates, Inc.\n * Copyright © 1998-2000 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#define XLIB_ILLEGAL_ACCESS\n#include \"tkWinInt.h\"\n\n#include <commctrl.h>\n#ifdef _MSC_VER\n#   pragma comment (lib, \"comctl32.lib\")\n#   pragma comment (lib, \"advapi32.lib\")\n#endif\n\n\n/*\n * The zmouse.h file includes the definition for WM_MOUSEWHEEL.\n */\n\n#include <zmouse.h>\n\n/*\n * WM_MOUSEHWHEEL is normally defined by Winuser.h for Vista/2008 or later,\n * but is also usable on 2000/XP if IntelliPoint drivers are installed.\n */\n\n#ifndef WM_MOUSEHWHEEL\n#define WM_MOUSEHWHEEL 0x020E\n#endif\n\n/* A WM_MOUSEWHEEL message sent by a trackpad contains the number of pixels as\n * the delta value, while low precision scrollwheels always send an integer\n * multiple of WHEELDELTA (= 120) as the delta value.\n */\n\n#define WHEELDELTA 120\n\n/*\n * Our heuristic for deciding whether a WM_MOUSEWHEEL message\n * comes from a high resolution scrolling device is that we\n * assume it is high resolution unless there are two consecutive\n * delta values that are both multiples of 120.  This is static,\n * rather than thread-specific, since input devices are shared\n * by all threads.\n */\n\nstatic int lastMod = 0;\n\n/*\n * The serial field of TouchpadScroll events is a counter for\n * events of this type only.\n */\n\nstatic unsigned long scrollCounter = 0;\n\n/*\n * imm.h is needed by HandleIMEComposition\n */\n\n#include <imm.h>\n#ifdef _MSC_VER\n#   pragma comment (lib, \"imm32.lib\")\n#endif\n\n/*\n * WM_UNICHAR is a message for Unicode input on all windows systems.\n * Perhaps this definition should be moved in another file.\n */\n#ifndef WM_UNICHAR\n#define WM_UNICHAR     0x0109\n#define UNICODE_NOCHAR 0xFFFF\n#endif\n\n/* Miscellaneous accessibility data and functions. */\n#include <oleacc.h>\ntypedef struct TkRootAccessible TkRootAccessible;\ntypedef void (*MainThreadFunc)(int num_args, void **args);\nextern TkRootAccessible *GetTkAccessibleForWindow(Tk_Window win);\nextern Tk_Window GetTkWindowForHwnd(HWND hwnd);\nextern void RunOnMainThreadSync(MainThreadFunc func, int num_args, ...);\nextern void HandleWMGetObjectOnMainThread(int num_args, void **args);\n\n/*\n * Declarations of static variables used in this file.\n */\n\nstatic const char winScreenName[] = \":0\"; /* Default name of windows display. */\nstatic HINSTANCE tkInstance = NULL;\t/* Application instance handle. */\nstatic bool childClassInitialized;\t/* Registered child class? */\nstatic WNDCLASSW childClass;\t\t/* Window class for child windows. */\nstatic Tcl_Encoding keyInputEncoding = NULL;\n\t\t\t\t\t/* The current character encoding for\n\t\t\t\t\t * keyboard input */\nstatic int keyInputCharset = -1;\t/* The Win32 CHARSET for the keyboard\n\t\t\t\t\t * encoding */\nstatic Tcl_Encoding unicodeEncoding = NULL;\n\t\t\t\t\t/* The UNICODE encoding */\n\n/*\n * Thread local storage. Notice that now each thread must have its own\n * TkDisplay structure, since this structure contains most of the thread-\n * specific date for threads.\n */\n\ntypedef struct {\n    TkDisplay *winDisplay;\t/* TkDisplay structure that represents Windows\n\t\t\t\t * screen. */\n    int updatingClipboard;\t/* If 1, we are updating the clipboard. */\n    int surrogateBuffer;\t/* Buffer for first of surrogate pair. */\n} ThreadSpecificData;\nstatic Tcl_ThreadDataKey dataKey;\n\n/*\n * Forward declarations of functions used in this file.\n */\n\nstatic void\t\tGenerateXEvent(HWND hwnd, UINT message,\n\t\t\t    WPARAM wParam, LPARAM lParam);\nstatic unsigned int\tGetState(UINT message, WPARAM wParam, LPARAM lParam);\nstatic void\t\tGetTranslatedKey(TkKeyEvent *xkey, UINT type);\nstatic void\t\tUpdateInputLanguage(int charset);\nstatic int\t\tHandleIMEComposition(HWND hwnd, LPARAM lParam);\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetServerInfo --\n *\n *\tGiven a window, this function returns information about the window\n *\tserver for that window. This function provides the guts of the \"winfo\n *\tserver\" command.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkGetServerInfo(\n    Tcl_Interp *interp,\t\t/* The server information is returned in this\n\t\t\t\t * interpreter's result. */\n    TCL_UNUSED(Tk_Window))\t\t/* Token for window; this selects a particular\n\t\t\t\t * display and server. */\n{\n    char buffer[80];\n    OSVERSIONINFOW os;\n    typedef int(__stdcall getVersionProc)(void *);\n\n    /*\n     * Not a performance critical so don't bother with static cache and MT\n     * synchronization\n     */\n\n    /*\n     * GetVersionExW will not return the \"real\" Windows version so use\n     * RtlGetVersion if available and falling back.\n     */\n    HMODULE handle = GetModuleHandleW(L\"NTDLL\"); /* No need to free this */\n    getVersionProc *getVersion =\n\t(getVersionProc *)(void *)GetProcAddress(handle, \"RtlGetVersion\");\n\n    os.dwOSVersionInfoSize = sizeof(os);\n    if (getVersion == NULL || getVersion(&os) != 0) {\n\t/* Should never happen but ... */\n\tif (!GetVersionExW(&os)) {\n\t    memset(&os, 0, sizeof(os));\n\t}\n    }\n    if (os.dwMajorVersion == 10 &&\n\tos.dwBuildNumber >= 22000) {\n\tos.dwMajorVersion = 11;\n    }\n    snprintf(buffer, sizeof(buffer), \"Windows %d.%d %d %s\",\n\t(int)os.dwMajorVersion, (int)os.dwMinorVersion, (int)os.dwBuildNumber,\n#ifdef _WIN64\n\t\"Win64\"\n#else\n\t\"Win32\"\n#endif\n    );\n    Tcl_AppendResult(interp, buffer, (char *)NULL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetHINSTANCE --\n *\n *\tRetrieves the global instance handle used by the Tk library.\n *\n * Results:\n *\tReturns the global instance handle.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nHINSTANCE\nTk_GetHINSTANCE(void)\n{\n    if (tkInstance == NULL) {\n\ttkInstance = GetModuleHandleW(NULL);\n    }\n    return tkInstance;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinSetHINSTANCE --\n *\n *\tSets the global instance handle used by the Tk library. This should be\n *\tcalled by DllMain.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinSetHINSTANCE(\n    HINSTANCE hInstance)\n{\n    tkInstance = hInstance;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinXInit --\n *\n *\tInitialize Xlib emulation layer.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tSets up various data structures.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinXInit(\n    HINSTANCE hInstance)\n{\n    INITCOMMONCONTROLSEX comctl;\n    CHARSETINFO lpCs;\n    DWORD lpCP;\n\n    if (childClassInitialized) {\n\treturn;\n    }\n    childClassInitialized = true;\n\n    comctl.dwSize = sizeof(INITCOMMONCONTROLSEX);\n    comctl.dwICC = ICC_WIN95_CLASSES;\n    if (!InitCommonControlsEx(&comctl)) {\n\tTcl_Panic(\"Unable to load common controls?!\");\n    }\n\n    childClass.style = CS_HREDRAW | CS_VREDRAW;\n    childClass.cbClsExtra = 0;\n    childClass.cbWndExtra = 0;\n    childClass.hInstance = hInstance;\n    childClass.hbrBackground = NULL;\n    childClass.lpszMenuName = NULL;\n\n    /*\n     * Register the Child window class.\n     */\n\n    childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME;\n    childClass.lpfnWndProc = TkWinChildProc;\n    childClass.hIcon = NULL;\n    childClass.hCursor = NULL;\n\n    if (!RegisterClassW(&childClass)) {\n\tTcl_Panic(\"Unable to register TkChild class\");\n    }\n\n    /*\n     * Initialize input language info\n     */\n\n    if (GetLocaleInfoW(LANGIDFROMLCID(PTR2INT(GetKeyboardLayout(0))),\n\t       LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,\n\t       (LPWSTR) &lpCP, sizeof(lpCP)/sizeof(WCHAR))\n\t    && TranslateCharsetInfo((DWORD *)INT2PTR(lpCP), &lpCs, TCI_SRCCODEPAGE)) {\n\tUpdateInputLanguage((int) lpCs.ciCharset);\n    }\n\n    /*\n     * Make sure we cleanup on finalize.\n     */\n\n    TkCreateExitHandler(TkWinXCleanup, hInstance);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinXCleanup --\n *\n *\tRemoves the registered classes for Tk.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tRemoves window classes from the system.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinXCleanup(\n    void *clientData)\n{\n    HINSTANCE hInstance = (HINSTANCE)clientData;\n\n    /*\n     * Clean up our own class.\n     */\n\n    if (childClassInitialized) {\n\tchildClassInitialized = false;\n\tUnregisterClassW(TK_WIN_CHILD_CLASS_NAME, hInstance);\n    }\n\n    if (unicodeEncoding != NULL) {\n\tTcl_FreeEncoding(unicodeEncoding);\n\tunicodeEncoding = NULL;\n    }\n\n    /*\n     * And let the window manager clean up its own class(es).\n     */\n\n    TkWinWmCleanup(hInstance);\n    TkWinCleanupContainerList();\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkGetDefaultScreenName --\n *\n *\tReturns the name of the screen that Tk should use during\n *\tinitialization.\n *\n * Results:\n *\tReturns a statically allocated string.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nconst char *\nTkGetDefaultScreenName(\n    TCL_UNUSED(Tcl_Interp *),\n    const char *screenName)\t/* If NULL, use default string. */\n{\n    if ((screenName == NULL) || (screenName[0] == '\\0')) {\n\tscreenName = winScreenName;\n    }\n    return screenName;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinDisplayChanged --\n *\n *\tCalled to set up initial screen info or when an event indicated\n *\tdisplay (screen) change.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tMay change info regarding the screen.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinDisplayChanged(\n    Display *display)\n{\n    HDC dc;\n    Screen *screen;\n\n    if (display == NULL || (((_XPrivDisplay)(display))->screens) == NULL) {\n\treturn;\n    }\n    screen = (((_XPrivDisplay)(display))->screens);\n\n    dc = GetDC(NULL);\n    WidthOfScreen(screen) = GetDeviceCaps(dc, HORZRES);\n    HeightOfScreen(screen) = GetDeviceCaps(dc, VERTRES);\n    WidthMMOfScreen(screen) = MulDiv(WidthOfScreen(screen), 254,\n\t    GetDeviceCaps(dc, LOGPIXELSX) * 10);\n    HeightMMOfScreen(screen) = MulDiv(HeightOfScreen(screen), 254,\n\t    GetDeviceCaps(dc, LOGPIXELSY) * 10);\n\n    /*\n     * On windows, when creating a color bitmap, need two pieces of\n     * information: the number of color planes and the number of pixels per\n     * plane. Need to remember both quantities so that when constructing an\n     * HBITMAP for offscreen rendering, we can specify the correct value for\n     * the number of planes. Otherwise the HBITMAP won't be compatible with\n     * the HWND and we'll just get blank spots copied onto the screen.\n     */\n\n    screen->ext_data = (XExtData *)INT2PTR(GetDeviceCaps(dc, PLANES));\n    screen->root_depth = (int)(GetDeviceCaps(dc, BITSPIXEL) * PTR2INT(screen->ext_data));\n\n    if (screen->root_visual != NULL) {\n\tTcl_Free(screen->root_visual);\n    }\n    screen->root_visual = (Visual *)Tcl_Alloc(sizeof(Visual));\n    screen->root_visual->visualid = 0;\n    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {\n\tDefaultVisualOfScreen(screen)->map_entries = GetDeviceCaps(dc, SIZEPALETTE);\n\tDefaultVisualOfScreen(screen)->c_class = PseudoColor;\n\tDefaultVisualOfScreen(screen)->red_mask = 0x0;\n\tDefaultVisualOfScreen(screen)->green_mask = 0x0;\n\tDefaultVisualOfScreen(screen)->blue_mask = 0x0;\n    } else if (DefaultDepthOfScreen(screen) == 4) {\n\tDefaultVisualOfScreen(screen)->c_class = StaticColor;\n\tDefaultVisualOfScreen(screen)->map_entries = 16;\n    } else if (DefaultDepthOfScreen(screen) == 8) {\n\tDefaultVisualOfScreen(screen)->c_class = StaticColor;\n\tDefaultVisualOfScreen(screen)->map_entries = 256;\n    } else if (DefaultDepthOfScreen(screen) == 12) {\n\tDefaultVisualOfScreen(screen)->c_class = TrueColor;\n\tDefaultVisualOfScreen(screen)->map_entries = 32;\n\tDefaultVisualOfScreen(screen)->red_mask = 0xf0;\n\tDefaultVisualOfScreen(screen)->green_mask = 0xf000;\n\tDefaultVisualOfScreen(screen)->blue_mask = 0xf00000;\n    } else if (DefaultDepthOfScreen(screen) == 16) {\n\tDefaultVisualOfScreen(screen)->c_class = TrueColor;\n\tDefaultVisualOfScreen(screen)->map_entries = 64;\n\tDefaultVisualOfScreen(screen)->red_mask = 0xf8;\n\tDefaultVisualOfScreen(screen)->green_mask = 0xfc00;\n\tDefaultVisualOfScreen(screen)->blue_mask = 0xf80000;\n    } else if (DefaultDepthOfScreen(screen) >= 24) {\n\tDefaultVisualOfScreen(screen)->c_class = TrueColor;\n\tDefaultVisualOfScreen(screen)->map_entries = 256;\n\tDefaultVisualOfScreen(screen)->red_mask = 0xff;\n\tDefaultVisualOfScreen(screen)->green_mask = 0xff00;\n\tDefaultVisualOfScreen(screen)->blue_mask = 0xff0000;\n    }\n    DefaultVisualOfScreen(screen)->bits_per_rgb = DefaultDepthOfScreen(screen);\n    ReleaseDC(NULL, dc);\n\n    if (DefaultColormapOfScreen(screen) != None) {\n\tXFreeColormap(display, DefaultColormapOfScreen(screen));\n    }\n    DefaultColormapOfScreen(screen) = XCreateColormap(display, None, DefaultVisualOfScreen(screen),\n\t    AllocNone);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpOpenDisplay/XkbOpenDisplay --\n *\n *\tCreate the Display structure and fill it with device specific\n *\tinformation.\n *\n * Results:\n *\tReturns a TkDisplay structure on success or NULL on failure.\n *\n * Side effects:\n *\tAllocates a new TkDisplay structure.\n *\n *----------------------------------------------------------------------\n */\n\nTkDisplay *\nTkpOpenDisplay(\n    const char *display_name)\n{\n    Display *display;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (tsdPtr->winDisplay != NULL) {\n\tif (!strcmp(DisplayString(tsdPtr->winDisplay->display), display_name)) {\n\t    return tsdPtr->winDisplay;\n\t} else {\n\t    return NULL;\n\t}\n    }\n\n    display = XkbOpenDisplay(display_name, NULL, NULL, NULL, NULL, NULL);\n    TkWinDisplayChanged(display);\n\n    tsdPtr->winDisplay =(TkDisplay *)Tcl_Alloc(sizeof(TkDisplay));\n    memset(tsdPtr->winDisplay, 0, sizeof(TkDisplay));\n    tsdPtr->winDisplay->display = display;\n    tsdPtr->updatingClipboard = FALSE;\n\n    /*\n     * Key map info must be available immediately, because of \"send event\".\n     */\n    TkpInitKeymapInfo(tsdPtr->winDisplay);\n\n    /*\n     * Key map info must be available immediately, because of \"send event\".\n     */\n    TkpInitKeymapInfo(tsdPtr->winDisplay);\n\n    return tsdPtr->winDisplay;\n}\n\nDisplay *\nXkbOpenDisplay(\n\tconst char *name,\n\tint *ev_rtrn,\n\tint *err_rtrn,\n\tint *major_rtrn,\n\tint *minor_rtrn,\n\tint *reason)\n{\n    _XPrivDisplay display = (_XPrivDisplay)Tcl_Alloc(sizeof(Display));\n    Screen *screen = (Screen *)Tcl_Alloc(sizeof(Screen));\n    TkWinDrawable *twdPtr = (TkWinDrawable *)Tcl_Alloc(sizeof(TkWinDrawable));\n\n    memset(screen, 0, sizeof(Screen));\n    memset(display, 0, sizeof(Display));\n\n    /*\n     * Note that these pixel values are not palette relative.\n     */\n\n    WhitePixelOfScreen(screen) = RGB(255, 255, 255);\n    BlackPixelOfScreen(screen) = RGB(0, 0, 0);\n    DefaultColormapOfScreen(screen) = None;\n\n    display->screens\t\t= screen;\n    display->nscreens\t\t= 1;\n    display->default_screen\t= 0;\n\n    twdPtr->type = TWD_WINDOW;\n    twdPtr->window.winPtr = NULL;\n    twdPtr->window.handle = NULL;\n    screen->root = (Window)twdPtr;\n    screen->display = (Display *)display;\n\n    display->display_name = (char  *)Tcl_Alloc(strlen(name) + 1);\n    strcpy(display->display_name, name);\n\n    display->nscreens = 1;\n    display->request = 1;\n    display->qlen = 0;\n\n    if (ev_rtrn) *ev_rtrn = 0;\n    if (err_rtrn) *err_rtrn = 0;\n    if (major_rtrn) *major_rtrn = 0;\n    if (minor_rtrn) *minor_rtrn = 0;\n    if (reason) *reason = 0;\n\n    return (Display *)display;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpCloseDisplay --\n *\n *\tCloses and deallocates a Display structure created with the\n *\tTkpOpenDisplay function.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tFrees up memory.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkpCloseDisplay(\n    TkDisplay *dispPtr)\n{\n    _XPrivDisplay display = (_XPrivDisplay)dispPtr->display;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if (dispPtr != tsdPtr->winDisplay) {\n\tTcl_Panic(\"TkpCloseDisplay: tried to call TkpCloseDisplay on another display\");\n\treturn; /* not reached */\n    }\n\n    tsdPtr->winDisplay = NULL;\n\n    if (display->display_name != NULL) {\n\tTcl_Free(display->display_name);\n    }\n    if (ScreenOfDisplay(display, 0) != NULL) {\n\tif (DefaultVisualOfScreen(ScreenOfDisplay(display, 0)) != NULL) {\n\t    Tcl_Free(DefaultVisualOfScreen(ScreenOfDisplay(display, 0)));\n\t}\n\tif (RootWindowOfScreen(ScreenOfDisplay(display, 0)) != None) {\n\t    Tcl_Free((void *)RootWindowOfScreen(ScreenOfDisplay(display, 0)));\n\t}\n\tif (DefaultColormapOfScreen(ScreenOfDisplay(display, 0)) != None) {\n\t    XFreeColormap(display, DefaultColormapOfScreen(ScreenOfDisplay(display, 0)));\n\t}\n\tTcl_Free(ScreenOfDisplay(display, 0));\n    }\n    Tcl_Free(display);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkClipCleanup --\n *\n *\tThis function is called to cleanup resources associated with claiming\n *\tclipboard ownership and for receiving selection get results. This\n *\tfunction is called in tkWindow.c. This has to be called by the display\n *\tcleanup function because we still need the access display elements.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tResources are freed - the clipboard may no longer be used.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkClipCleanup(\n    TkDisplay *dispPtr)\t\t/* Display associated with clipboard. */\n{\n    if (dispPtr->clipWindow != NULL) {\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->applicationAtom);\n\tTk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,\n\t\tdispPtr->windowAtom);\n\n\tTk_DestroyWindow(dispPtr->clipWindow);\n\tTcl_Release(dispPtr->clipWindow);\n\tdispPtr->clipWindow = NULL;\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XBell --\n *\n *\tGenerate a beep.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tPlays a sounds out the system speakers.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXBell(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int))\n{\n    MessageBeep(MB_OK);\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinChildProc --\n *\n *\tCallback from Windows whenever an event occurs on a child window.\n *\n * Results:\n *\tStandard Windows return value.\n *\n * Side effects:\n *\tMay process events off the Tk event queue.\n *\n *----------------------------------------------------------------------\n */\n\nLRESULT CALLBACK\nTkWinChildProc(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    LRESULT result = 0;\n\n    switch (message) {\n    case WM_INPUTLANGCHANGE:\n\tUpdateInputLanguage((int) wParam);\n\tresult = 1;\n\tbreak;\n\n    case WM_IME_COMPOSITION:\n\tresult = 0;\n\tif (HandleIMEComposition(hwnd, lParam) == 0) {\n\t    result = DefWindowProcW(hwnd, message, wParam, lParam);\n\t}\n\tbreak;\n\n    case WM_SETCURSOR:\n\t/*\n\t * Short circuit the WM_SETCURSOR message since we set the cursor\n\t * elsewhere.\n\t */\n\n\tresult = TRUE;\n\tbreak;\n\n    case WM_CREATE:\n    case WM_ERASEBKGND:\n\tresult = 0;\n\tbreak;\n\n    case WM_PAINT:\n\tGenerateXEvent(hwnd, message, wParam, lParam);\n\tresult = DefWindowProcW(hwnd, message, wParam, lParam);\n\tbreak;\n\n    case TK_CLAIMFOCUS:\n    case TK_GEOMETRYREQ:\n    case TK_ATTACHWINDOW:\n    case TK_DETACHWINDOW:\n    case TK_ICONIFY:\n    case TK_DEICONIFY:\n    case TK_MOVEWINDOW:\n    case TK_WITHDRAW:\n    case TK_RAISEWINDOW:\n    case TK_GETFRAMEWID:\n    case TK_OVERRIDEREDIRECT:\n    case TK_SETMENU:\n    case TK_STATE:\n    case TK_INFO:\n\tresult = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);\n\tbreak;\n\n    case WM_UNICHAR:\n\tif (wParam == UNICODE_NOCHAR) {\n\t    /* If wParam is UNICODE_NOCHAR and the application processes\n\t     * this message, then return TRUE. */\n\t    result = 1;\n\t} else {\n\t    /* If the event was translated, we must return 0 */\n\t    if (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {\n\t\tresult = 0;\n\t    } else {\n\t\tresult = 1;\n\t    }\n\t}\n\tbreak;\n\n     /* Handle MSAA queries. */\n    case WM_GETOBJECT:\n\tif ((LONG)lParam == OBJID_CLIENT) {\n\t    LRESULT resultOnMainThread = 0;\n\t    MainThreadFunc func = (MainThreadFunc)HandleWMGetObjectOnMainThread;\n\t    RunOnMainThreadSync(func, 4, hwnd, (void *)wParam, (void *)lParam, &resultOnMainThread);\n\t    return resultOnMainThread;\n\t}\n\tbreak;\n\n    default:\n\tif (!TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {\n\t    result = DefWindowProcW(hwnd, message, wParam, lParam);\n\t}\n\tbreak;\n    }\n\n    /*\n     * Handle any newly queued events before returning control to Windows.\n     */\n\n    Tcl_ServiceAll();\n    return result;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkTranslateWinEvent --\n *\n *\tThis function is called by widget window functions to handle the\n *\ttranslation from Win32 events to Tk events.\n *\n * Results:\n *\tReturns 1 if the event was handled, else 0.\n *\n * Side effects:\n *\tDepends on the event.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTkTranslateWinEvent(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam,\n    LRESULT *resultPtr)\n{\n    *resultPtr = 0;\n    switch (message) {\n    case WM_RENDERFORMAT: {\n\tTkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);\n\n\tif (winPtr) {\n\t    TkWinClipboardRender(winPtr->dispPtr, (UINT)wParam);\n\t}\n\treturn 1;\n    }\n\n    case WM_RENDERALLFORMATS: {\n\tTkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);\n\n\tif (winPtr && OpenClipboard(hwnd)) {\n\t    /*\n\t     * Make sure that nobody had taken ownership of the clipboard\n\t     * before we opened it.\n\t     */\n\n\t    if (GetClipboardOwner() == hwnd) {\n\t\tTkWinClipboardRender(winPtr->dispPtr, CF_TEXT);\n\t    }\n\t    CloseClipboard();\n\t}\n\treturn 1;\n    }\n\n    case WM_COMMAND:\n    case WM_NOTIFY:\n    case WM_VSCROLL:\n    case WM_HSCROLL: {\n\t/*\n\t * Reflect these messages back to the sender so that they can be\n\t * handled by the window proc for the control. Note that we need to be\n\t * careful not to reflect a message that is targeted to this window,\n\t * or we will loop.\n\t */\n\n\tHWND target = (message == WM_NOTIFY)\n\t\t? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;\n\n\tif (target && target != hwnd) {\n\t    *resultPtr = SendMessageW(target, message, wParam, lParam);\n\t    return 1;\n\t}\n\tbreak;\n    }\n\n    case WM_LBUTTONDOWN:\n    case WM_LBUTTONDBLCLK:\n    case WM_MBUTTONDOWN:\n    case WM_MBUTTONDBLCLK:\n    case WM_RBUTTONDOWN:\n    case WM_RBUTTONDBLCLK:\n    case WM_XBUTTONDOWN:\n    case WM_XBUTTONDBLCLK:\n    case WM_LBUTTONUP:\n    case WM_MBUTTONUP:\n    case WM_RBUTTONUP:\n    case WM_XBUTTONUP:\n    case WM_MOUSEMOVE:\n\tTkWinPointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam));\n\treturn 1;\n\n    case WM_SYSKEYDOWN:\n    case WM_KEYDOWN:\n\tif (wParam == VK_PACKET) {\n\t    /*\n\t     * This will trigger WM_CHAR event(s) with unicode data.\n\t     */\n\t    *resultPtr =\n\t\tPostMessageW(hwnd, message, HIWORD(lParam), LOWORD(lParam));\n\t    return 1;\n\t}\n\t/* else fall through */\n    case WM_CLOSE:\n    case WM_SETFOCUS:\n    case WM_KILLFOCUS:\n    case WM_DESTROYCLIPBOARD:\n    case WM_UNICHAR:\n    case WM_CHAR:\n    case WM_SYSKEYUP:\n    case WM_KEYUP:\n    case WM_MOUSEWHEEL:\n    case WM_MOUSEHWHEEL:\n\tGenerateXEvent(hwnd, message, wParam, lParam);\n\treturn 1;\n    case WM_MENUCHAR:\n\tGenerateXEvent(hwnd, message, wParam, lParam);\n\n\t/*\n\t * MNC_CLOSE is the only one that looks right. This is a hack.\n\t */\n\n\t*resultPtr = MAKELONG (0, MNC_CLOSE);\n\treturn 1;\n    }\n    return 0;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GenerateXEvent --\n *\n *\tThis routine generates an X event from the corresponding Windows\n *\tevent.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tQueues one or more X events.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGenerateXEvent(\n    HWND hwnd,\n    UINT message,\n    WPARAM wParam,\n    LPARAM lParam)\n{\n    union {XEvent x; TkKeyEvent key;} event;\n    TkWindow *winPtr;\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    if ((message == WM_MOUSEWHEEL) || (message == WM_MOUSEHWHEEL)) {\n\tunion {LPARAM lParam; POINTS point;} root;\n\tPOINT pos;\n\troot.lParam = lParam;\n\n\t/*\n\t * Redirect mousewheel events to the window containing the cursor.\n\t * That feels much less strange to users, and is how all the other\n\t * platforms work.\n\t */\n\n\tpos.x = root.point.x;\n\tpos.y = root.point.y;\n\thwnd = WindowFromPoint(pos);\n    }\n\n    winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);\n    if (!winPtr || winPtr->window == None) {\n\treturn;\n    }\n\n    memset(&event.x, 0, sizeof(XEvent));\n    event.x.xany.serial = LastKnownRequestProcessed(winPtr->display)++;\n    event.x.xany.send_event = False;\n    event.x.xany.display = winPtr->display;\n    event.x.xany.window = winPtr->window;\n\n    switch (message) {\n    case WM_PAINT: {\n\tPAINTSTRUCT ps;\n\n\tevent.x.type = Expose;\n\tBeginPaint(hwnd, &ps);\n\tevent.x.xexpose.x = ps.rcPaint.left;\n\tevent.x.xexpose.y = ps.rcPaint.top;\n\tevent.x.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;\n\tevent.x.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;\n\tEndPaint(hwnd, &ps);\n\tevent.x.xexpose.count = 0;\n\tbreak;\n    }\n\n    case WM_CLOSE:\n\tevent.x.type = ClientMessage;\n\tevent.x.xclient.message_type =\n\t\tTk_InternAtom((Tk_Window) winPtr, \"WM_PROTOCOLS\");\n\tevent.x.xclient.format = 32;\n\tevent.x.xclient.data.l[0] =\n\t\tTk_InternAtom((Tk_Window) winPtr, \"WM_DELETE_WINDOW\");\n\tbreak;\n\n    case WM_SETFOCUS:\n    case WM_KILLFOCUS: {\n\tTkWindow *otherWinPtr = (TkWindow *) Tk_HWNDToWindow((HWND) wParam);\n\n\t/*\n\t * Compare toplevel windows to avoid reporting focus changes within\n\t * the same toplevel.\n\t */\n\n\twhile (!(winPtr->flags & TK_TOP_LEVEL)) {\n\t    winPtr = winPtr->parentPtr;\n\t    if (winPtr == NULL) {\n\t\treturn;\n\t    }\n\t}\n\twhile (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {\n\t    otherWinPtr = otherWinPtr->parentPtr;\n\t}\n\n\t/*\n\t * Do a catch-all Tk_SetCaretPos here to make sure that the window\n\t * receiving focus sets the caret at least once.\n\t */\n\n\tif (message == WM_SETFOCUS) {\n\t    Tk_SetCaretPos((Tk_Window) winPtr, 0, 0, 0);\n\t}\n\n\tif (otherWinPtr == winPtr) {\n\t    return;\n\t}\n\n\tevent.x.xany.window = winPtr->window;\n\tevent.x.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;\n\tevent.x.xfocus.mode = NotifyNormal;\n\tevent.x.xfocus.detail = NotifyNonlinear;\n\n\t/*\n\t * Destroy the caret if we own it. If we are moving to another Tk\n\t * window, it will reclaim and reposition it with Tk_SetCaretPos.\n\t */\n\n\tif (message == WM_KILLFOCUS) {\n\t    DestroyCaret();\n\t}\n\tbreak;\n    }\n\n    case WM_DESTROYCLIPBOARD:\n\tif (tsdPtr->updatingClipboard == TRUE) {\n\t    /*\n\t     * We want to avoid this event if we are the ones that caused this\n\t     * event.\n\t     */\n\n\t    return;\n\t}\n\tevent.x.type = SelectionClear;\n\tevent.x.xselectionclear.selection =\n\t\tTk_InternAtom((Tk_Window)winPtr, \"CLIPBOARD\");\n\tevent.x.xselectionclear.time = TkpGetMS();\n\tbreak;\n\n    case WM_MOUSEWHEEL:\n    case WM_MOUSEHWHEEL:\n    case WM_CHAR:\n    case WM_UNICHAR:\n    case WM_SYSKEYDOWN:\n    case WM_SYSKEYUP:\n    case WM_KEYDOWN:\n    case WM_KEYUP: {\n\tunsigned int state = GetState(message, wParam, lParam);\n\tTime time = TkpGetMS();\n\tPOINT clientPoint;\n\tunion {DWORD msgpos; POINTS point;} root;\t/* Note: POINT and POINTS are different */\n\n\t/*\n\t * Compute the screen and window coordinates of the event.\n\t */\n\n\troot.msgpos = GetMessagePos();\n\tclientPoint.x = root.point.x;\n\tclientPoint.y = root.point.y;\n\tScreenToClient(hwnd, &clientPoint);\n\n\t/*\n\t * Set up the common event fields.\n\t */\n\n\tevent.x.xbutton.root = RootWindow(winPtr->display, winPtr->screenNum);\n\tevent.x.xbutton.subwindow = None;\n\tevent.x.xbutton.x = clientPoint.x;\n\tevent.x.xbutton.y = clientPoint.y;\n\tevent.x.xbutton.x_root = root.point.x;\n\tevent.x.xbutton.y_root = root.point.y;\n\tevent.x.xbutton.state = state;\n\tevent.x.xbutton.time = time;\n\tevent.x.xbutton.same_screen = True;\n\n\t/*\n\t * Now set up event specific fields.\n\t */\n\n\tswitch (message) {\n\tcase WM_MOUSEWHEEL: {\n\n\t    /*\n\t     * Send an Xevent using a KeyPress struct, but with the type field\n\t     * set to MouseWheelEvent for low resolution scrolls and to\n\t     * TouchpadScroll for high resolution scroll events. The Y delta\n\t     * is stored in the low order 16 bits of the keycode field.  Set\n\t     * nbytes to 0 to prevent conversion of the keycode to a keysym in\n\t     * TkpGetString. [Bug 1118340].\n\t     */\n\n\t    int delta = (short) HIWORD(wParam);\n\t    int mod = delta % WHEELDELTA;\n\t    if ( mod != 0 || lastMod != 0) {\n\t\t/* High resolution. */\n\t\tevent.x.type = TouchpadScroll;\n\t\tevent.x.xany.send_event = -1;\n\t\tevent.key.nbytes = 0;\n\t\tevent.x.xkey.state = state;\n\t\tevent.x.xany.serial = scrollCounter++;\n\t\tevent.x.xkey.keycode = (unsigned int) (delta & 0xffff);\n\t    } else {\n\t\tevent.x.type = MouseWheelEvent;\n\t\tevent.x.xany.send_event = -1;\n\t\tevent.key.nbytes = 0;\n\t\tevent.x.xkey.keycode = (unsigned int) delta;\n\t    }\n\t    lastMod = mod;\n\t    break;\n\t}\n\tcase WM_MOUSEHWHEEL: {\n\n\t    /*\n\t     * Send an Xevent using a KeyPress struct, but with the type field\n\t     * set to MouseWheelEvent for low resolution scrolls and to\n\t     * TouchpadScroll for high resolution scroll events.  For low\n\t     * resolution scrolls the X delta is stored in the keycode field\n\t     * and For high resolution scrolls the X delta is in the high word\n\t     * of the keycode.  Set nbytes to 0 to prevent conversion of the\n\t     * keycode to a keysym in TkpGetString. [Bug 1118340].\n\t     */\n\n\t    int delta = (short) HIWORD(wParam);\n\t    int mod = delta % WHEELDELTA;\n\t    if ( mod != 0 || lastMod != 0) {\n\t\t/* High resolution. */\n\t\tevent.x.type = TouchpadScroll;\n\t\tevent.x.xany.send_event = -1;\n\t\tevent.key.nbytes = 0;\n\t\tevent.x.xkey.state = state;\n\t\tevent.x.xany.serial = scrollCounter++;\n\t\tevent.x.xkey.keycode = -((unsigned int)delta << 16);\n\t    } else {\n\t\tevent.x.type = MouseWheelEvent;\n\t\tevent.x.xany.send_event = -1;\n\t\tevent.key.nbytes = 0;\n\t\tevent.x.xkey.state |= ShiftMask;\n\t\tevent.x.xkey.keycode = delta;\n\t    }\n\t    lastMod = mod;\n\t    break;\n\t}\n\tcase WM_SYSKEYDOWN:\n\tcase WM_KEYDOWN:\n\t    /*\n\t     * Check for translated characters in the event queue. Setting\n\t     * xany.send_event to -1 indicates to the Windows implementation\n\t     * of TkpGetString() that this event was generated by windows and\n\t     * that the Windows extension xkey.trans_chars is filled with the\n\t     * MBCS characters that came from the TranslateMessage call.\n\t     */\n\n\t    event.x.type = KeyPress;\n\t    event.x.xany.send_event = -1;\n\t    event.x.xkey.keycode = (unsigned)wParam;\n\t    GetTranslatedKey(&event.key, (message == WM_KEYDOWN) ? WM_CHAR :\n\t\t    WM_SYSCHAR);\n\t    break;\n\n\tcase WM_SYSKEYUP:\n\tcase WM_KEYUP:\n\t    /*\n\t     * We don't check for translated characters on keyup because Tk\n\t     * won't know what to do with them. Instead, we wait for the\n\t     * WM_CHAR messages which will follow.\n\t     */\n\n\t    event.x.type = KeyRelease;\n\t    event.x.xkey.keycode = (unsigned)wParam;\n\t    event.key.nbytes = 0;\n\t    break;\n\n\tcase WM_CHAR:\n\t    /*\n\t     * Synthesize both a KeyPress and a KeyRelease. Strings generated\n\t     * by Input Method Editor are handled in the following manner:\n\t     * 1. A series of WM_KEYDOWN & WM_KEYUP messages that cause\n\t     *    GetTranslatedKey() to be called and return immediately\n\t     *    because the WM_KEYDOWNs have no associated WM_CHAR messages\n\t     *    -- the IME window is accumulating the characters and\n\t     *    translating them itself. In the \"bind\" command, you get an\n\t     *    event with a mystery keysym and %A == \"\" for each WM_KEYDOWN\n\t     *    that actually was meant for the IME.\n\t     * 2. A WM_KEYDOWN corresponding to the \"confirm typing\"\n\t     *    character. This causes GetTranslatedKey() to be called.\n\t     * 3. A WM_IME_NOTIFY message saying that the IME is done. A side\n\t     *\t  effect of this message is that GetTranslatedKey() thinks\n\t     *\t  this means that there are no WM_CHAR messages and returns\n\t     *\t  immediately. In the \"bind\" command, you get an another event\n\t     *\t  with a mystery keysym and %A == \"\".\n\t     * 4. A sequence of WM_CHAR messages that correspond to the\n\t     *\t  characters in the IME window. A bunch of simulated\n\t     *\t  KeyPress/KeyRelease events will be generated, one for each\n\t     *\t  character. Adjacent WM_CHAR messages may actually specify\n\t     *\t  the high and low bytes of a multi-byte character -- in that\n\t     *\t  case the two WM_CHAR messages will be combined into one\n\t     *\t  event. It is the event-consumer's responsibility to convert\n\t     *\t  the string returned from XLookupString from system encoding\n\t     *\t  to UTF-8.\n\t     * 5. And finally we get the WM_KEYUP for the \"confirm typing\"\n\t     *    character.\n\t     */\n\n\t    event.x.type = KeyPress;\n\t    event.x.xany.send_event = -1;\n\t    event.x.xkey.keycode = 0;\n\t    if ((int)wParam & 0xff00) {\n\t\tint ch1 = wParam & 0xffff;\n\n\t\tif ((ch1 & 0xfc00) == 0xd800) {\n\t\t    tsdPtr->surrogateBuffer = ch1;\n\t\t    return;\n\t\t}\n\t\tif ((ch1 & 0xfc00) == 0xdc00) {\n\t\t    ch1 = ((tsdPtr->surrogateBuffer & 0x3ff) << 10) |\n\t\t\t    (ch1 & 0x3ff) | 0x10000;\n\t\t    tsdPtr->surrogateBuffer = 0;\n\t\t}\n\t\tevent.x.xany.send_event = -3;\n\t\tevent.key.nbytes = 0;\n\t\tevent.x.xkey.keycode = ch1;\n\t    } else {\n\t\tevent.key.nbytes = 1;\n\t\tevent.key.trans_chars[0] = (char) wParam;\n\n\t\tif (IsDBCSLeadByte((BYTE) wParam)) {\n\t\t    MSG msg;\n\n\t\t    if ((PeekMessageW(&msg, NULL, WM_CHAR, WM_CHAR,\n\t\t\t    PM_NOREMOVE) != 0)\n\t\t\t    && (msg.message == WM_CHAR)) {\n\t\t\tGetMessageW(&msg, NULL, WM_CHAR, WM_CHAR);\n\t\t\tevent.key.nbytes = 2;\n\t\t\tevent.key.trans_chars[1] = (char) msg.wParam;\n\t\t   }\n\t\t}\n\t    }\n\t    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);\n\t    event.x.type = KeyRelease;\n\t    break;\n\n\tcase WM_UNICHAR: {\n\t    event.x.type = KeyPress;\n\t    event.x.xany.send_event = -3;\n\t    event.x.xkey.keycode = (unsigned)wParam;\n\t    event.key.nbytes = 0;\n\t    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);\n\t    event.x.type = KeyRelease;\n\t    break;\n\t}\n\n\t}\n\tbreak;\n    }\n\n    default:\n\t/*\n\t * Don't know how to translate this event, so ignore it. (It probably\n\t * should not have got here, but ignoring it should be harmless.)\n\t */\n\n\treturn;\n    }\n\n    /*\n     * Post the translated event to the main Tk event queue.\n     */\n\n    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetState --\n *\n *\tThis function constructs a state mask for the mouse buttons and\n *\tmodifier keys as they were before the event occurred.\n *\n * Results:\n *\tReturns a composite value of all the modifier and button state flags\n *\tthat were set at the time the event occurred.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic unsigned int\nGetState(\n    UINT message,\t\t/* Win32 message type */\n    WPARAM wParam,\t\t/* wParam of message, used if key message */\n    LPARAM lParam)\t\t/* lParam of message, used if key message */\n{\n    int mask;\n    int prevState;\t\t/* 1 if key was previously down */\n    unsigned int state = TkWinGetModifierState();\n\n    /*\n     * If the event is a key press or release, we check for modifier keys so\n     * we can report the state of the world before the event.\n     */\n\n    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN\n\t    || message == WM_SYSKEYUP || message == WM_KEYUP) {\n\tmask = 0;\n\tprevState = HIWORD(lParam) & KF_REPEAT;\n\tswitch(wParam) {\n\tcase VK_SHIFT:\n\t    mask = ShiftMask;\n\t    break;\n\tcase VK_CONTROL:\n\t    mask = ControlMask;\n\t    break;\n\tcase VK_MENU:\n\t    mask = ALT_MASK;\n\t    break;\n\tcase VK_CAPITAL:\n\t    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {\n\t\tmask = LockMask;\n\t\tprevState = ((state & mask) ^ prevState) ? 0 : 1;\n\t    }\n\t    break;\n\tcase VK_NUMLOCK:\n\t    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {\n\t\tmask = Mod1Mask;\n\t\tprevState = ((state & mask) ^ prevState) ? 0 : 1;\n\t    }\n\t    break;\n\tcase VK_SCROLL:\n\t    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {\n\t\tmask = Mod3Mask;\n\t\tprevState = ((state & mask) ^ prevState) ? 0 : 1;\n\t    }\n\t    break;\n\t}\n\tif (prevState) {\n\t    state |= mask;\n\t} else {\n\t    state &= ~mask;\n\t}\n\tif (HIWORD(lParam) & KF_EXTENDED) {\n\t    state |= EXTENDED_MASK;\n\t}\n    }\n    return state;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * GetTranslatedKey --\n *\n *\tRetrieves WM_CHAR messages that are placed on the system queue by the\n *\tTranslateMessage system call and places them in the given KeyPress\n *\tevent.\n *\n * Results:\n *\tSets the trans_chars and nbytes member of the key event.\n *\n * Side effects:\n *\tRemoves any WM_CHAR messages waiting on the top of the system event\n *\tqueue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nGetTranslatedKey(\n    TkKeyEvent *xkey,\n    UINT type)\n{\n    MSG msg;\n\n    xkey->nbytes = 0;\n\n    while ((xkey->nbytes < sizeof(xkey->trans_chars))\n\t    && (PeekMessageA(&msg, NULL, type, type, PM_NOREMOVE) != 0)) {\n\tif (msg.message != type) {\n\t    break;\n\t}\n\n\tGetMessageA(&msg, NULL, type, type);\n\n\t/*\n\t * If this is a normal character message, we may need to strip off the\n\t * Alt modifier (e.g. Alt-digits). Note that we don't want to do this\n\t * for system messages, because those were presumably generated as an\n\t * Alt-char sequence (e.g. accelerator keys).\n\t */\n\n\tif ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {\n\t    xkey->keyEvent.state = 0;\n\t}\n\txkey->trans_chars[xkey->nbytes++] = (char) msg.wParam;\n\n\tif (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {\n\t    /*\n\t     * Some \"addon\" input devices, such as the popular PenPower\n\t     * Chinese writing pad, generate 16 bit values in WM_CHAR messages\n\t     * (instead of passing them in two separate WM_CHAR messages\n\t     * containing two 8-bit values.\n\t     */\n\n\t    xkey->trans_chars[xkey->nbytes] = (char) (msg.wParam >> 8);\n\t    xkey->nbytes ++;\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * UpdateInputLanguage --\n *\n *\tGets called when a WM_INPUTLANGCHANGE message is received by the Tk\n *\tchild window function. This message is sent by the Input Method Editor\n *\tsystem when the user chooses a different input method. All subsequent\n *\tWM_CHAR messages will contain characters in the new encoding. We\n *\trecord the new encoding so that TkpGetString() knows how to correctly\n *\ttranslate the WM_CHAR into unicode.\n *\n * Results:\n *\tRecords the new encoding in keyInputEncoding.\n *\n * Side effects:\n *\tOld value of keyInputEncoding is freed.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void\nUpdateInputLanguage(\n    int charset)\n{\n    CHARSETINFO charsetInfo;\n    Tcl_Encoding encoding;\n    char codepage[4 + TCL_INTEGER_SPACE];\n\n    if (keyInputCharset == charset) {\n\treturn;\n    }\n    if (TranslateCharsetInfo((DWORD*)INT2PTR(charset), &charsetInfo,\n\t    TCI_SRCCHARSET) == 0) {\n\t/*\n\t * Some mysterious failure.\n\t */\n\n\treturn;\n    }\n\n    if (charsetInfo.ciACP == CP_UTF8) {\n\tstrcpy(codepage, \"utf-8\");\n    } else {\n\tsnprintf(codepage, sizeof(codepage), \"cp%d\", charsetInfo.ciACP);\n    }\n\n    if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) {\n\t/*\n\t * The encoding is not supported by Tcl.\n\t */\n\n\treturn;\n    }\n\n    if (keyInputEncoding != NULL) {\n\tTcl_FreeEncoding(keyInputEncoding);\n    }\n\n    keyInputEncoding = encoding;\n    keyInputCharset = charset;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetKeyInputEncoding --\n *\n *\tReturns the current keyboard input encoding selected by the user (with\n *\tWM_INPUTLANGCHANGE events).\n *\n * Results:\n *\tThe current keyboard input encoding.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Encoding\nTkWinGetKeyInputEncoding(void)\n{\n    return keyInputEncoding;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinGetUnicodeEncoding --\n *\n *\tReturns the cached unicode encoding.\n *\n * Results:\n *\tThe unicode encoding.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nTcl_Encoding\nTkWinGetUnicodeEncoding(void)\n{\n    if (unicodeEncoding == NULL) {\n\tunicodeEncoding = Tcl_GetEncoding(NULL, \"utf-16\");\n\tif (unicodeEncoding == NULL) {\n\t    unicodeEncoding = Tcl_GetEncoding(NULL, \"unicode\");\n\t}\n    }\n    return unicodeEncoding;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * HandleIMEComposition --\n *\n *\tThis function works around a deficiency in some versions of Windows\n *\t2000 to make it possible to entry multi-lingual characters under all\n *\tversions of Windows 2000.\n *\n *\tWhen an Input Method Editor (IME) is ready to send input characters to\n *\tan application, it sends a WM_IME_COMPOSITION message with the\n *\tGCS_RESULTSTR. However, The DefWindowProcW() on English Windows 2000\n *\tarbitrarily converts all non-Latin-1 characters in the composition to\n *\t\"?\".\n *\n *\tThis function correctly processes the composition data and sends the\n *\tUNICODE values of the composed characters to TK's event queue.\n *\n * Results:\n *\tIf this function has processed the composition data, returns 1.\n *\tOtherwise returns 0.\n *\n * Side effects:\n *\tKey events are put into the TK event queue.\n *\n *----------------------------------------------------------------------\n */\n\nstatic int\nHandleIMEComposition(\n    HWND hwnd,\t\t\t/* Window receiving the message. */\n    LPARAM lParam)\t\t/* Flags for the WM_IME_COMPOSITION message */\n{\n    HIMC hIMC;\n    int n;\n    int high = 0;\n\n    if ((lParam & GCS_RESULTSTR) == 0) {\n\t/*\n\t * Composition is not finished yet.\n\t */\n\n\treturn 0;\n    }\n\n    hIMC = ImmGetContext(hwnd);\n    if (!hIMC) {\n\treturn 0;\n    }\n\n    n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);\n\n    if (n > 0) {\n\tWCHAR *buff = (WCHAR *)Tcl_Alloc(n);\n\tTkWindow *winPtr;\n\tXEvent event;\n\tint i;\n\n\tn = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, (unsigned) n) / 2;\n\n\t/*\n\t * Set up the fields pertinent to key event.\n\t *\n\t * We set send_event to the special value of -3, so that TkpGetString\n\t * in tkWinKey.c knows that keycode already contains a UNICODE\n\t * char and there's no need to do encoding conversion.\n\t *\n\t * Note that the event *must* be zeroed out first; Tk plays cunning\n\t * games with the overalls structure. [Bug 2992129]\n\t */\n\n\twinPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);\n\n\tmemset(&event, 0, sizeof(XEvent));\n\tevent.xkey.serial = LastKnownRequestProcessed(winPtr->display)++;\n\tevent.xkey.send_event = -3;\n\tevent.xkey.display = winPtr->display;\n\tevent.xkey.window = winPtr->window;\n\tevent.xkey.root = RootWindow(winPtr->display, winPtr->screenNum);\n\tevent.xkey.subwindow = None;\n\tevent.xkey.state = TkWinGetModifierState();\n\tevent.xkey.time = TkpGetMS();\n\tevent.xkey.same_screen = True;\n\n\tfor (i=0; i<n; ) {\n\t    /*\n\t     * Simulate a pair of KeyPress and KeyRelease events for each\n\t     * UNICODE character in the composition.\n\t     */\n\n\t    event.xkey.keycode = buff[i++];\n\n\t    if ((event.xkey.keycode & 0xfc00) == 0xd800) {\n\t\thigh = ((event.xkey.keycode & 0x3ff) << 10) + 0x10000;\n\t\tbreak;\n\t    } else if (high && (event.xkey.keycode & 0xfc00) == 0xdc00) {\n\t\tevent.xkey.keycode &= 0x3ff;\n\t\tevent.xkey.keycode += high;\n\t\thigh = 0;\n\t    }\n\t    event.type = KeyPress;\n\t    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\n\t    event.type = KeyRelease;\n\t    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);\n\t}\n\n\tTcl_Free(buff);\n    }\n    ImmReleaseContext(hwnd, hIMC);\n    return 1;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinResendEvent --\n *\n *\tThis function converts an X event into a Windows event and invokes the\n *\tspecified window function.\n *\n * Results:\n *\tA standard Windows result.\n *\n * Side effects:\n *\tInvokes the window function\n *\n *----------------------------------------------------------------------\n */\n\nLRESULT\nTkWinResendEvent(\n    WNDPROC wndproc,\n    HWND hwnd,\n    XEvent *eventPtr)\n{\n    UINT msg;\n    WPARAM wparam;\n    LPARAM lparam;\n\n    if (eventPtr->type != ButtonPress) {\n\treturn 0;\n    }\n\n    switch (eventPtr->xbutton.button) {\n    case Button1:\n\tmsg = WM_LBUTTONDOWN;\n\twparam = MK_LBUTTON;\n\tbreak;\n    case Button2:\n\tmsg = WM_MBUTTONDOWN;\n\twparam = MK_MBUTTON;\n\tbreak;\n    case Button3:\n\tmsg = WM_RBUTTONDOWN;\n\twparam = MK_RBUTTON;\n\tbreak;\n    case Button8:\n\tmsg = WM_XBUTTONDOWN;\n\twparam = MAKEWPARAM(MK_XBUTTON1, XBUTTON1);\n\tbreak;\n    case Button9:\n\tmsg = WM_XBUTTONDOWN;\n\twparam = MAKEWPARAM(MK_XBUTTON2, XBUTTON2);\n\tbreak;\n    default:\n\treturn 0;\n    }\n\n    if (eventPtr->xbutton.state & Button1Mask) {\n\twparam |= MK_LBUTTON;\n    }\n    if (eventPtr->xbutton.state & Button2Mask) {\n\twparam |= MK_MBUTTON;\n    }\n    if (eventPtr->xbutton.state & Button3Mask) {\n\twparam |= MK_RBUTTON;\n    }\n    if (eventPtr->xbutton.state & Button4Mask) {\n\twparam |= MK_XBUTTON1;\n    }\n    if (eventPtr->xbutton.state & Button5Mask) {\n\twparam |= MK_XBUTTON2;\n    }\n    if (eventPtr->xbutton.state & ShiftMask) {\n\twparam |= MK_SHIFT;\n    }\n    if (eventPtr->xbutton.state & ControlMask) {\n\twparam |= MK_CONTROL;\n    }\n    lparam = MAKELPARAM((short) eventPtr->xbutton.x,\n\t    (short) eventPtr->xbutton.y);\n    return CallWindowProcW(wndproc, hwnd, msg, wparam, lparam);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkpGetMS --\n *\n *\tReturn a relative time in milliseconds. It doesn't matter when the\n *\tepoch was.\n *\n * Results:\n *\tNumber of milliseconds.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nunsigned long\nTkpGetMS(void)\n{\n    return GetTickCount();\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * TkWinUpdatingClipboard --\n *\n *\n * Results:\n *\tNumber of milliseconds.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTkWinUpdatingClipboard(\n    int mode)\n{\n    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)\n\t    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));\n\n    tsdPtr->updatingClipboard = mode;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_SetCaretPos --\n *\n *\tThis enables correct movement of focus in the MS Magnifier, as well as\n *\tallowing us to correctly position the IME Window. The following Win32\n *\tAPIs are used to work with MS caret:\n *\n *\tCreateCaret\tDestroyCaret\tSetCaretPos\tGetCaretPos\n *\n *\tOnly one instance of caret can be active at any time (e.g.\n *\tDestroyCaret API does not take any argument such as handle). Since\n *\tdo-it-right approach requires to track the create/destroy caret status\n *\tall the time in a global scope among windows (or widgets), we just\n *\timplement this minimal setup to get the job done.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tSets the global Windows caret position.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_SetCaretPos(\n    Tk_Window tkwin,\n    int x, int y,\n    int height)\n{\n    static HWND caretHWND = NULL;\n    TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);\n    Window win;\n\n    /*\n     * Prevent processing anything if the values haven't changed. Windows only\n     * has one display, so we can do this with statics.\n     */\n\n    if ((caretPtr->winPtr == ((TkWindow *) tkwin))\n\t    && (caretPtr->x == x) && (caretPtr->y == y)) {\n\treturn;\n    }\n\n    caretPtr->winPtr = ((TkWindow *) tkwin);\n    caretPtr->x = x;\n    caretPtr->y = y;\n    caretPtr->height = height;\n\n    /*\n     * We adjust to the toplevel to get the coords right, as setting the IME\n     * composition window is based on the toplevel hwnd, so ignore height.\n     */\n\n    while (!Tk_IsTopLevel(tkwin)) {\n\tx += Tk_X(tkwin);\n\ty += Tk_Y(tkwin);\n\ttkwin = Tk_Parent(tkwin);\n\tif (tkwin == NULL) {\n\t    return;\n\t}\n    }\n\n    win = Tk_WindowId(tkwin);\n    if (win) {\n\tHIMC hIMC;\n\tHWND hwnd = Tk_GetHWND(win);\n\n\tif (hwnd != caretHWND) {\n\t    DestroyCaret();\n\t    if (CreateCaret(hwnd, NULL, 0, 0)) {\n\t\tcaretHWND = hwnd;\n\t    }\n\t}\n\n\tif (!SetCaretPos(x, y) && CreateCaret(hwnd, NULL, 0, 0)) {\n\t    caretHWND = hwnd;\n\t    SetCaretPos(x, y);\n\t}\n\n\t/*\n\t * The IME composition window should be updated whenever the caret\n\t * position is changed because a clause of the composition string may\n\t * be converted to the final characters and the other clauses still\n\t * stay on the composition window. -- yamamoto\n\t */\n\n\thIMC = ImmGetContext(hwnd);\n\tif (hIMC) {\n\t    COMPOSITIONFORM cform;\n\n\t    cform.dwStyle = CFS_POINT;\n\t    cform.ptCurrentPos.x = x;\n\t    cform.ptCurrentPos.y = y;\n\t    ImmSetCompositionWindow(hIMC, &cform);\n\t    ImmReleaseContext(hwnd, hIMC);\n\t}\n    }\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_GetUserInactiveTime --\n *\n *\tReturn the number of milliseconds the user was inactive.\n *\n * Results:\n *\tMilliseconds of user inactive time or -1 if GetLastInputInfo\n *\treturns an error.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nlong\nTk_GetUserInactiveTime(\n     TCL_UNUSED(Display *))\n{\n    LASTINPUTINFO li;\n\n    li.cbSize = sizeof(li);\n    if (!GetLastInputInfo(&li)) {\n\treturn -1;\n    }\n\n    /*\n     * Last input info is in milliseconds, since restart time.\n     */\n\n    return (GetTickCount()-li.dwTime);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tk_ResetUserInactiveTime --\n *\n *\tReset the user inactivity timer\n *\n * Results:\n *\tnone\n *\n * Side effects:\n *\tThe user inactivity timer of the underlying windowing system is reset\n *\tto zero.\n *\n *----------------------------------------------------------------------\n */\n\nvoid\nTk_ResetUserInactiveTime(\n    TCL_UNUSED(Display *))\n{\n    INPUT inp;\n\n    inp.type = INPUT_MOUSE;\n    inp.mi.dx = 0;\n    inp.mi.dy = 0;\n    inp.mi.mouseData = 0;\n    inp.mi.dwFlags = MOUSEEVENTF_MOVE;\n    inp.mi.time = 0;\n    inp.mi.dwExtraInfo = (DWORD) 0;\n\n    SendInput(1, &inp, sizeof(inp));\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/ttkWinMonitor.c",
    "content": "#ifdef _MSC_VER\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#include \"tkWinInt.h\"\n#include \"ttk/ttkTheme.h\"\n\n#if !defined(WM_THEMECHANGED)\n#define WM_THEMECHANGED 0x031A\n#endif\n\nstatic LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);\n\n/*\n * RegisterSystemColors --\n *\tRegister all known Windows system colors (as per GetSysColor) as Tk\n *\tnamed colors.\n */\n\ntypedef struct {\n    const char *name;\n    int index;\n} SystemColorEntry;\n\nstatic const SystemColorEntry sysColors[] = {\n\t{ \"System3dDarkShadow\",\t\tCOLOR_3DDKSHADOW },\n\t{ \"System3dLight\",\t\tCOLOR_3DLIGHT },\n\t{ \"SystemActiveBorder\",\t\tCOLOR_ACTIVEBORDER },\n\t{ \"SystemActiveCaption\",\tCOLOR_ACTIVECAPTION },\n\t{ \"SystemAppWorkspace\",\t\tCOLOR_APPWORKSPACE },\n\t{ \"SystemBackground\",\t\tCOLOR_BACKGROUND },\n\t{ \"SystemButtonFace\",\t\tCOLOR_BTNFACE },\n\t{ \"SystemButtonHighlight\",\tCOLOR_BTNHIGHLIGHT },\n\t{ \"SystemButtonShadow\",\t\tCOLOR_BTNSHADOW },\n\t{ \"SystemButtonText\",\t\tCOLOR_BTNTEXT },\n\t{ \"SystemCaptionText\",\t\tCOLOR_CAPTIONTEXT },\n\t{ \"SystemDisabledText\",\t\tCOLOR_GRAYTEXT },\n\t{ \"SystemGrayText\",\t\tCOLOR_GRAYTEXT },\n\t{ \"SystemHighlight\",\t\tCOLOR_HIGHLIGHT },\n\t{ \"SystemHighlightText\",\tCOLOR_HIGHLIGHTTEXT },\n\t{ \"SystemInactiveBorder\",\tCOLOR_INACTIVEBORDER },\n\t{ \"SystemInactiveCaption\",\tCOLOR_INACTIVECAPTION },\n\t{ \"SystemInactiveCaptionText\",\tCOLOR_INACTIVECAPTIONTEXT },\n\t{ \"SystemInfoBackground\",\tCOLOR_INFOBK },\n\t{ \"SystemInfoText\",\t\tCOLOR_INFOTEXT },\n\t{ \"SystemMenu\",\t\t\tCOLOR_MENU },\n\t{ \"SystemMenuText\",\t\tCOLOR_MENUTEXT },\n\t{ \"SystemScrollbar\",\t\tCOLOR_SCROLLBAR },\n\t{ \"SystemWindow\",\t\tCOLOR_WINDOW },\n\t{ \"SystemWindowFrame\",\t\tCOLOR_WINDOWFRAME },\n\t{ \"SystemWindowText\",\t\tCOLOR_WINDOWTEXT },\n\t{ NULL, 0 }\n};\n\nstatic void RegisterSystemColors(Tcl_Interp *interp)\n{\n    Ttk_ResourceCache cache = Ttk_GetResourceCache(interp);\n    const SystemColorEntry *sysColor;\n\n    for (sysColor = sysColors; sysColor->name; ++sysColor) {\n\tDWORD pixel = GetSysColor(sysColor->index);\n\tXColor colorSpec;\n\tcolorSpec.red = GetRValue(pixel) * 257;\n\tcolorSpec.green = GetGValue(pixel) * 257;\n\tcolorSpec.blue = GetBValue(pixel) * 257;\n\tTtk_RegisterNamedColor(cache, sysColor->name, &colorSpec);\n    }\n}\n\f\nstatic HWND\nCreateThemeMonitorWindow(HINSTANCE hinst, Tcl_Interp *interp)\n{\n    WNDCLASSEXW wc;\n    HWND       hwnd = NULL;\n    WCHAR      title[32] = L\"TtkMonitorWindow\";\n    WCHAR      name[32] = L\"TtkMonitorClass\";\n\n    wc.cbSize        = sizeof(WNDCLASSEXW);\n    wc.style         = CS_HREDRAW | CS_VREDRAW;\n    wc.lpfnWndProc   = (WNDPROC)WndProc;\n    wc.cbClsExtra    = 0;\n    wc.cbWndExtra    = 0;\n    wc.hInstance     = hinst;\n    wc.hIcon         = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);\n    wc.hIconSm       = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);\n    wc.hCursor       = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);\n    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;\n    wc.lpszMenuName  = name;\n    wc.lpszClassName = name;\n\n    if (RegisterClassExW(&wc)) {\n\thwnd = CreateWindowW( name, title, WS_OVERLAPPEDWINDOW,\n\t    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\n\t    NULL, NULL, hinst, NULL );\n\tSetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) interp);\n\tShowWindow(hwnd, SW_HIDE);\n\tUpdateWindow(hwnd);\n    }\n    return hwnd;\n}\n\nstatic void\nDestroyThemeMonitorWindow(void *clientData)\n{\n    HWND hwnd = (HWND)clientData;\n    DestroyWindow(hwnd);\n}\n\f\nstatic LRESULT WINAPI\nWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)\n{\n    Tcl_Interp *interp = (Tcl_Interp *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);\n    Ttk_Theme theme;\n\n    switch (msg) {\n    case WM_DESTROY:\n\tbreak;\n\n    case WM_SYSCOLORCHANGE:\n\tRegisterSystemColors(interp);\n\tbreak;\n\n    case WM_THEMECHANGED:\n\t/*\n\t * Reset the application theme.\n\t * On windows, it is possible to sign in as a second user, change\n\t * the theme to 'winnative' (by setting the ui to 'best performance'),\n\t * which is a machine-wide change, and then sign back on to the original user.\n\t * Ttk_UseTheme needs to be executed again in order to process the fallback\n\t * from vista to winnative.\n\t */\n\n\ttheme = Ttk_GetCurrentTheme(interp);\n\tif (theme) {\n\t    Ttk_UseTheme(interp, theme);\n\t    /* @@@ What to do about errors here? */\n\t}\n\tbreak;\n    }\n    return DefWindowProcW(hwnd, msg, wp, lp);\n}\n\f\n/*\n * Windows-specific platform initialization:\n */\n\nMODULE_SCOPE int TtkWinTheme_Init(Tcl_Interp *, HWND hwnd);\nMODULE_SCOPE int TtkWinVistaTheme_Init(Tcl_Interp *, HWND hwnd);\nMODULE_SCOPE int Ttk_WinPlatformInit(Tcl_Interp *interp);\n\nMODULE_SCOPE int Ttk_WinPlatformInit(Tcl_Interp *interp)\n{\n    HWND hwnd;\n\n    hwnd = CreateThemeMonitorWindow(Tk_GetHINSTANCE(), interp);\n    Ttk_RegisterCleanup(interp, hwnd, DestroyThemeMonitorWindow);\n\n    TtkWinTheme_Init(interp, hwnd);\n    TtkWinVistaTheme_Init(interp, hwnd);\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "win/ttkWinTheme.c",
    "content": "/* winTheme.c - Copyright © 2004 Pat Thoyts <patthoyts@users.sf.net>\n */\n\n#ifdef _MSC_VER\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#include \"tkWinInt.h\"\n\n#ifndef DFCS_HOT\t/* Windows 98/Me, Windows 2000/XP only */\n#define DFCS_HOT 0\n#endif\n\n#include \"ttk/ttkTheme.h\"\n\n/*\n * BoxToRect --\n *\tHelper routine.  Converts a Ttk_Box to a Win32 RECT.\n */\nstatic RECT BoxToRect(Ttk_Box b)\n{\n    RECT rc;\n    rc.top = b.y;\n    rc.left = b.x;\n    rc.bottom = b.y + b.height;\n    rc.right = b.x + b.width;\n    return rc;\n}\n\n/*\n * ReliefToEdge --\n *\tConvert a Tk \"relief\" value into an Windows \"edge\" value.\n *\tNB: Caller must check for RELIEF_FLAT and RELIEF_SOLID,\n *\twhich must be handled specially.\n *\n *\tPassing the BF_FLAT flag to DrawEdge() yields something similar\n *\tto TK_RELIEF_SOLID. TK_RELIEF_FLAT can be implemented by not\n *\tdrawing anything.\n */\nstatic unsigned int ReliefToEdge(int relief)\n{\n    switch (relief) {\n\tcase TK_RELIEF_RAISED: return EDGE_RAISED;\n\tcase TK_RELIEF_SUNKEN: return EDGE_SUNKEN;\n\tcase TK_RELIEF_RIDGE:  return EDGE_BUMP;\n\tcase TK_RELIEF_GROOVE: return EDGE_ETCHED;\n\tcase TK_RELIEF_SOLID:  return BDR_RAISEDOUTER;\n\tdefault:\n\tcase TK_RELIEF_FLAT:   return BDR_RAISEDOUTER;\n    }\n}\n\n/*------------------------------------------------------------------------\n * +++ State tables for FrameControlElements.\n */\n\nstatic const Ttk_StateTable checkbutton_statemap[] = { /* see also SF#1865898 */\n    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_INACTIVE,\n\tTTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0 },\n    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_PUSHED,\n\tTTK_STATE_ALTERNATE|TTK_STATE_PRESSED, 0 },\n    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_HOT,\n\tTTK_STATE_ALTERNATE|TTK_STATE_ACTIVE, 0 },\n    { DFCS_BUTTON3STATE|DFCS_CHECKED,\n\tTTK_STATE_ALTERNATE, 0 },\n\n    { DFCS_CHECKED|DFCS_INACTIVE, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },\n    { DFCS_CHECKED|DFCS_PUSHED,   TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0 },\n    { DFCS_CHECKED|DFCS_HOT,      TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0 },\n    { DFCS_CHECKED,\t          TTK_STATE_SELECTED, 0 },\n\n    { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 },\n    { DFCS_PUSHED,   TTK_STATE_PRESSED, 0 },\n    { DFCS_HOT,      TTK_STATE_ACTIVE, 0 },\n    { 0, 0, 0 },\n};\n\nstatic const Ttk_StateTable pushbutton_statemap[] = {\n    { DFCS_INACTIVE,\t  TTK_STATE_DISABLED, 0 },\n    { DFCS_PUSHED,\t  TTK_STATE_PRESSED, 0 },\n    { DFCS_HOT,\t\t  TTK_STATE_ACTIVE, 0 },\n    { 0, 0, 0 }\n};\n\nstatic const Ttk_StateTable arrow_statemap[] = {\n    { DFCS_INACTIVE,            TTK_STATE_DISABLED, 0 },\n    { DFCS_PUSHED | DFCS_FLAT,  TTK_STATE_PRESSED,  0 },\n    { 0, 0, 0 }\n};\n\n/*------------------------------------------------------------------------\n * +++ FrameControlElement --\n *\tGeneral-purpose element for things drawn with DrawFrameControl\n */\ntypedef struct {\n    const char *name;\t\t/* element name */\n    int classId;\t\t/* class id for DrawFrameControl */\n    int partId;\t\t\t/* part id for DrawFrameControl  */\n    unsigned cxId;\t\t/* system metric ids for width/height... */\n    unsigned cyId;\t\t/* ... or size if FIXEDSIZE bit set */\n    const Ttk_StateTable *stateMap;\t/* map Tk states to Win32 flags */\n    Ttk_Padding margins;\t/* additional placement padding */\n} FrameControlElementData;\n\n#define BASE_DIM    16\n#define _FIXEDSIZE  0x80000000UL\n#define _HALFMETRIC 0x40000000UL\n#define FIXEDSIZE(id) ((id)|_FIXEDSIZE)\n#define HALFMETRIC(id) ((id)|_HALFMETRIC)\n#define GETMETRIC(m) \\\n    ((m) & _FIXEDSIZE ? (int)((m) & ~_FIXEDSIZE) : GetSystemMetrics((m)&0xFFFFFFF))\n\nstatic FrameControlElementData FrameControlElements[] = {\n    { \"Checkbutton.indicator\",\n\tDFC_BUTTON, DFCS_BUTTONCHECK, FIXEDSIZE(BASE_DIM), FIXEDSIZE(BASE_DIM),\n\tcheckbutton_statemap, {0,0,4,0} },\n    { \"Radiobutton.indicator\",\n\tDFC_BUTTON, DFCS_BUTTONRADIO, FIXEDSIZE(BASE_DIM), FIXEDSIZE(BASE_DIM),\n\tcheckbutton_statemap, {0,0,4,0} },\n    { \"uparrow\",\n\tDFC_SCROLL, DFCS_SCROLLUP, SM_CXVSCROLL, SM_CYVSCROLL,\n\tarrow_statemap, {0,0,0,0} },\n    { \"downarrow\",\n\tDFC_SCROLL, DFCS_SCROLLDOWN, SM_CXVSCROLL, SM_CYVSCROLL,\n\tarrow_statemap, {0,0,0,0} },\n    { \"leftarrow\",\n\tDFC_SCROLL, DFCS_SCROLLLEFT, SM_CXHSCROLL, SM_CYHSCROLL,\n\tarrow_statemap, {0,0,0,0} },\n    { \"rightarrow\",\n\tDFC_SCROLL, DFCS_SCROLLRIGHT, SM_CXHSCROLL, SM_CYHSCROLL,\n\tarrow_statemap, {0,0,0,0} },\n    { \"sizegrip\",\n\tDFC_SCROLL, DFCS_SCROLLSIZEGRIP, SM_CXVSCROLL, SM_CYHSCROLL,\n\tarrow_statemap, {0,0,0,0} },\n    { \"Spinbox.uparrow\",\n\tDFC_SCROLL, DFCS_SCROLLUP, SM_CXVSCROLL, HALFMETRIC(SM_CYVSCROLL),\n\tarrow_statemap, {0,0,0,0} },\n    { \"Spinbox.downarrow\",\n\tDFC_SCROLL, DFCS_SCROLLDOWN, SM_CXVSCROLL, HALFMETRIC(SM_CYVSCROLL),\n\tarrow_statemap, {0,0,0,0} },\n\n    { 0,0,0,0,0,0, {0,0,0,0} }\n};\n\n/* ---------------------------------------------------------------------- */\n\nstatic void FrameControlElementSize(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    FrameControlElementData *p = (FrameControlElementData *)clientData;\n    int cx = GETMETRIC(p->cxId);\n    int cy = GETMETRIC(p->cyId);\n\n    if ((p->cxId & _FIXEDSIZE) && cx == BASE_DIM) {\n\tdouble scalingLevel = TkScalingLevel(tkwin);\n\tcx = (int)(cx * scalingLevel);\n\tcy = (int)(cy * scalingLevel);\n\n\t/*\n\t * Update the corresponding element of the array FrameControlElements\n\t */\n\tp->cxId = FIXEDSIZE((unsigned long)cx);\n\tp->cyId = FIXEDSIZE((unsigned long)cy);\n    }\n\n    if (p->cxId & _HALFMETRIC) cx /= 2;\n    if (p->cyId & _HALFMETRIC) cy /= 2;\n\n    *widthPtr = cx + Ttk_PaddingWidth(p->margins);\n    *heightPtr = cy + Ttk_PaddingHeight(p->margins);\n}\n\nstatic void FrameControlElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    FrameControlElementData *elementData = (FrameControlElementData *)clientData;\n    RECT rc = BoxToRect(Ttk_PadBox(b, elementData->margins));\n    TkWinDCState dcState;\n    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\n    DrawFrameControl(hdc, &rc,\n\t(UINT)elementData->classId,\n\t(UINT)(elementData->partId|Ttk_StateTableLookup(elementData->stateMap, state)));\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec FrameControlElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    FrameControlElementSize,\n    FrameControlElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Border element implementation.\n */\n\ntypedef struct {\n    Tcl_Obj\t*reliefObj;\n} BorderElement;\n\nstatic const Ttk_ElementOptionSpec BorderElementOptions[] = {\n    { \"-relief\",TK_OPTION_RELIEF, offsetof(BorderElement,reliefObj), \"flat\" },\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\n\nstatic void BorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    paddingPtr->left = paddingPtr->right = (short)GetSystemMetrics(SM_CXEDGE);\n    paddingPtr->top = paddingPtr->bottom = (short)GetSystemMetrics(SM_CYEDGE);\n}\n\nstatic void BorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    BorderElement *border = (BorderElement *)elementRecord;\n    RECT rc = BoxToRect(b);\n    int relief = TK_RELIEF_FLAT;\n    TkWinDCState dcState;\n    HDC hdc;\n\n    Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);\n\n    if (relief != TK_RELIEF_FLAT) {\n\tUINT xFlags = (relief == TK_RELIEF_SOLID) ? BF_FLAT : 0;\n\thdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\tDrawEdge(hdc, &rc, ReliefToEdge(relief), BF_RECT | xFlags);\n\tTkWinReleaseDrawableDC(d, hdc, &dcState);\n    }\n}\n\nstatic const Ttk_ElementSpec BorderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(BorderElement),\n    BorderElementOptions,\n    BorderElementSize,\n    BorderElementDraw\n};\n\n/*\n * Entry field borders:\n * Sunken border; also fill with window color.\n */\n\ntypedef struct {\n    Tcl_Obj\t*backgroundObj;\n} FieldElement;\n\nstatic const Ttk_ElementOptionSpec FieldElementOptions[] = {\n    { \"-fieldbackground\", TK_OPTION_BORDER,\n\toffsetof(FieldElement,backgroundObj), \"white\" },\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void FieldElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    paddingPtr->left = paddingPtr->right = (short)GetSystemMetrics(SM_CXEDGE);\n    paddingPtr->top = paddingPtr->bottom = (short)GetSystemMetrics(SM_CYEDGE);\n}\n\nstatic void FieldElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    FieldElement *field = (FieldElement *)elementRecord;\n    Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);\n    RECT rc = BoxToRect(b);\n    TkWinDCState dcState;\n    HDC hdc;\n\n    Tk_Fill3DRectangle(\n\ttkwin, d, bg, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT);\n\n    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n    DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT);\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec FieldElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FieldElement),\n    FieldElementOptions,\n    FieldElementSize,\n    FieldElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Button borders.\n *\tDrawn with DrawFrameControl instead of DrawEdge;\n *\tAlso draw default indicator and focus ring.\n */\ntypedef struct {\n    Tcl_Obj\t*reliefObj;\n    Tcl_Obj\t*highlightColorObj;\n    Tcl_Obj\t*defaultStateObj;\n} ButtonBorderElement;\n\nstatic const Ttk_ElementOptionSpec ButtonBorderElementOptions[] = {\n    { \"-relief\",TK_OPTION_RELIEF,\n\toffsetof(ButtonBorderElement,reliefObj), \"flat\" },\n    { \"-highlightcolor\",TK_OPTION_COLOR,\n\toffsetof(ButtonBorderElement,highlightColorObj), \"black\" },\n    { \"-default\", TK_OPTION_ANY,\n\toffsetof(ButtonBorderElement,defaultStateObj), \"disabled\" },\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\n\nstatic void ButtonBorderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;\n    int relief = TK_RELIEF_RAISED;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n    short int cx, cy;\n\n    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n    cx = (short)GetSystemMetrics(SM_CXEDGE);\n    cy = (short)GetSystemMetrics(SM_CYEDGE);\n\n    /* Space for default indicator:\n     */\n    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {\n\t++cx; ++cy;\n    }\n\n    /* Space for focus ring:\n     */\n    cx += 2;\n    cy += 2;\n\n    *paddingPtr = Ttk_MakePadding(cx, cy, cx, cy);\n}\n\nstatic void ButtonBorderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;\n    int relief = TK_RELIEF_FLAT;\n    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;\n    TkWinDCState dcState;\n    HDC hdc;\n    RECT rc;\n\n    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);\n    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);\n\n    if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {\n\tXColor *highlightColor =\n\t    Tk_GetColorFromObj(tkwin, bd->highlightColorObj);\n\tGC gc = Tk_GCForColor(highlightColor, d);\n\tXDrawRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, (UINT)(b.width - 1), (UINT)(b.height - 1));\n    }\n    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {\n\t++b.x; ++b.y; b.width -= 2; b.height -= 2;\n    }\n\n    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\n    rc = BoxToRect(b);\n    DrawFrameControl(hdc, &rc,\n\tDFC_BUTTON,\t/* classId */\n\t(UINT)(DFCS_BUTTONPUSH | Ttk_StateTableLookup(pushbutton_statemap, state)));\n\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n\n    /* Draw focus ring:\n     */\n    if (state & TTK_STATE_FOCUS) {\n\tshort int borderWidth = 3;\t/* @@@ Use GetSystemMetrics?*/\n\tb = Ttk_PadBox(b, Ttk_UniformPadding(borderWidth));\n\tTkWinDrawDottedRect(Tk_Display(tkwin), d, -1, b.x, b.y,\n\t    b.width, b.height);\n    }\n}\n\nstatic const Ttk_ElementSpec ButtonBorderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ButtonBorderElement),\n    ButtonBorderElementOptions,\n    ButtonBorderElementSize,\n    ButtonBorderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Focus element.\n *\tDraw dotted focus rectangle.\n */\n\nstatic void FocusElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    *paddingPtr = Ttk_UniformPadding(1);\n}\n\nstatic void FocusElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    if (state & TTK_STATE_FOCUS) {\n\tTkWinDrawDottedRect(Tk_Display(tkwin), d, -1, b.x, b.y,\n\t    b.width, b.height);\n    }\n}\n\nstatic const Ttk_ElementSpec FocusElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    FocusElementSize,\n    FocusElementDraw\n};\n\n/* FillFocusElement --\n *\tDraws a focus ring filled with the selection color\n */\n\ntypedef struct {\n    Tcl_Obj *fillColorObj;\n} FillFocusElement;\n\nstatic const Ttk_ElementOptionSpec FillFocusElementOptions[] = {\n    { \"-focusfill\", TK_OPTION_COLOR,\n\toffsetof(FillFocusElement,fillColorObj), \"white\" },\n    {NULL, TK_OPTION_BOOLEAN, 0, NULL}\n};\n\n\t/* @@@ FIX THIS */\nstatic void FillFocusElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    if (state & TTK_STATE_FOCUS) {\n\tFillFocusElement *focus = (FillFocusElement *)elementRecord;\n\tXColor *fillColor = Tk_GetColorFromObj(tkwin, focus->fillColorObj);\n\tGC gc = Tk_GCForColor(fillColor, d);\n\tXFillRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, (unsigned)b.width, (unsigned)b.height);\n\n\tTkWinDrawDottedRect(Tk_Display(tkwin), d, -1, b.x, b.y,\n\t    b.width, b.height);\n    }\n}\n\n/*\n * ComboboxFocusElement --\n *\tRead-only comboboxes have a filled focus ring, editable ones do not.\n */\nstatic void ComboboxFocusElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    if (state & TTK_STATE_READONLY) {\n\tFillFocusElementDraw(clientData, elementRecord, tkwin, d, b, state);\n    }\n}\n\nstatic const Ttk_ElementSpec ComboboxFocusElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(FillFocusElement),\n    FillFocusElementOptions,\n    FocusElementSize,\n    ComboboxFocusElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Scrollbar trough element.\n *\n * The native windows scrollbar is drawn using a pattern brush giving a\n * stippled appearance when the trough might otherwise be invisible.\n * We can deal with this here.\n */\n\ntypedef struct {\t/* clientData for Trough element */\n    HBRUSH     PatternBrush;\n    HBITMAP    PatternBitmap;\n} TroughClientData;\n\nstatic const WORD Pattern[] = {\n    0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa\n};\n\nstatic void TroughClientDataDeleteProc(void *clientData)\n{\n    TroughClientData *cd = (TroughClientData *)clientData;\n    DeleteObject(cd->PatternBrush);\n    DeleteObject(cd->PatternBitmap);\n    Tcl_Free(clientData);\n}\n\nstatic TroughClientData *TroughClientDataInit(Tcl_Interp *interp)\n{\n    TroughClientData *cd = (TroughClientData *)Tcl_Alloc(sizeof(*cd));\n    cd->PatternBitmap = CreateBitmap(8, 8, 1, 1, Pattern);\n    cd->PatternBrush  = CreatePatternBrush(cd->PatternBitmap);\n    Ttk_RegisterCleanup(interp, cd, TroughClientDataDeleteProc);\n    return cd;\n}\n\nstatic void TroughElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    TroughClientData *cd = (TroughClientData *)clientData;\n    TkWinDCState dcState;\n    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n    HBRUSH hbr;\n    COLORREF bk, oldbk, oldtxt;\n\n    hbr = (HBRUSH)SelectObject(hdc, GetSysColorBrush(COLOR_SCROLLBAR));\n    bk = GetSysColor(COLOR_3DHIGHLIGHT);\n    oldtxt = SetTextColor(hdc, GetSysColor(COLOR_3DFACE));\n    oldbk = SetBkColor(hdc, bk);\n\n    /* WAS: if (bk (COLOR_3DHIGHLIGHT) == GetSysColor(COLOR_WINDOW)) ... */\n    if (GetSysColor(COLOR_SCROLLBAR) == GetSysColor(COLOR_BTNFACE)) {\n\t/* Draw using the pattern brush */\n\tSelectObject(hdc, cd->PatternBrush);\n    }\n\n    PatBlt(hdc, b.x, b.y, b.width, b.height, PATCOPY);\n    SetBkColor(hdc, oldbk);\n    SetTextColor(hdc, oldtxt);\n    SelectObject(hdc, hbr);\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec TroughElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TtkNullElementSize,\n    TroughElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Thumb element.\n */\n\ntypedef struct {\n    Tcl_Obj *orientObj;\n} ThumbElement;\n\nstatic const Ttk_ElementOptionSpec ThumbElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY, offsetof(ThumbElement,orientObj),\"horizontal\"},\n    { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void ThumbElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    TCL_UNUSED(Tk_Window),\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    ThumbElement *thumbPtr = (ThumbElement *)elementRecord;\n    Ttk_Orient orient;\n\n    Ttk_GetOrientFromObj(NULL, thumbPtr->orientObj, &orient);\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*widthPtr = GetSystemMetrics(SM_CXHTHUMB);\n\t*heightPtr = GetSystemMetrics(SM_CYHSCROLL);\n    } else {\n\t*widthPtr = GetSystemMetrics(SM_CXVSCROLL);\n\t*heightPtr = GetSystemMetrics(SM_CYVTHUMB);\n    }\n}\n\nstatic void ThumbElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    RECT rc = BoxToRect(b);\n    TkWinDCState dcState;\n    HDC hdc;\n\n    /* Windows doesn't show a thumb when the scrollbar is disabled */\n    if (state & TTK_STATE_DISABLED) {\n\treturn;\n    }\n\n    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE);\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec ThumbElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(ThumbElement),\n    ThumbElementOptions,\n    ThumbElementSize,\n    ThumbElementDraw\n};\n\n/* ----------------------------------------------------------------------\n * The slider element is the shaped thumb used in the slider widget.\n * Windows likes to call this a trackbar.\n */\n\ntypedef struct {\n    Tcl_Obj *orientObj;  /* orientation of the slider widget */\n} SliderElement;\n\nstatic const Ttk_ElementOptionSpec SliderElementOptions[] = {\n    { \"-orient\", TK_OPTION_ANY, offsetof(SliderElement,orientObj),\n      \"horizontal\" },\n      { NULL, TK_OPTION_BOOLEAN, 0, NULL }\n};\n\nstatic void SliderElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    TCL_UNUSED(Tk_Window),\n    int *widthPtr,\n    int *heightPtr,\n    TCL_UNUSED(Ttk_Padding *))\n{\n    SliderElement *slider = (SliderElement *)elementRecord;\n    Ttk_Orient orient;\n\n    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);\n    if (orient == TTK_ORIENT_HORIZONTAL) {\n\t*widthPtr = (GetSystemMetrics(SM_CXHTHUMB) / 2) | 1;\n\t*heightPtr = GetSystemMetrics(SM_CYHSCROLL);\n    } else {\n\t*widthPtr = GetSystemMetrics(SM_CXVSCROLL);\n\t*heightPtr = (GetSystemMetrics(SM_CYVTHUMB) / 2) | 1;\n    }\n}\n\nstatic void SliderElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    RECT rc = BoxToRect(b);\n    TkWinDCState dcState;\n    HDC hdc;\n\n    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE);\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec SliderElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(SliderElement),\n    SliderElementOptions,\n    SliderElementSize,\n    SliderElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Notebook elements.\n */\n\ntypedef struct {\n    Tcl_Obj *borderWidthObj;\n    Tcl_Obj *backgroundObj;\n} TabElement;\n\nstatic const Ttk_ElementOptionSpec TabElementOptions[] = {\n    { \"-borderwidth\", TK_OPTION_PIXELS,\n\toffsetof(TabElement,borderWidthObj), \"1\" },\n    { \"-background\", TK_OPTION_BORDER,\n\toffsetof(TabElement,backgroundObj), DEFAULT_BACKGROUND },\n    {0,TK_OPTION_BOOLEAN,0,0}\n};\n\nstatic void TabElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    TabElement *tab = (TabElement *)elementRecord;\n    int borderWidth = 1;\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth);\n    *paddingPtr = Ttk_UniformPadding((short)borderWidth);\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    paddingPtr->bottom = 0;\n\t    break;\n\tcase TTK_STICK_N:\n\t    paddingPtr->top = 0;\n\t    break;\n\tcase TTK_STICK_E:\n\t    paddingPtr->right = 0;\n\t    break;\n\tcase TTK_STICK_W:\n\t    paddingPtr->left = 0;\n\t    break;\n    }\n}\n\nstatic void TabElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    void *elementRecord,\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    Ttk_PositionSpec nbTabPosStickBit = TTK_STICK_W;\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    TabElement *tab = (TabElement *)elementRecord;\n    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);\n    XPoint pts[6];\n    double scalingLevel = TkScalingLevel(tkwin);\n    int cut = (int)round(2 * scalingLevel);\n    Display *disp = Tk_Display(tkwin);\n    int once = 1, borderWidth = 1;\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPosStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPosition & 0x0f);\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    if (state & TTK_STATE_SELECTED) {\n\t/*\n\t * Draw slightly outside of the allocated parcel,\n\t * to overwrite the client area border.\n\t */\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t\tb.height += 2;\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t\tb.height += 2; b.y -= 2;\n\t\tbreak;\n\t    case TTK_STICK_E:\n\t\tb.width += 2;\n\t\tbreak;\n\t    case TTK_STICK_W:\n\t\tb.width += 2; b.x -= 2;\n\t\tbreak;\n\t}\n    }\n\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    pts[0].x = (short)b.x;  pts[0].y = (short)(b.y + b.height - 1);\n\t    pts[1].x = (short)b.x;  pts[1].y = (short)(b.y + cut);\n\t    pts[2].x = (short)(b.x + cut);  pts[2].y = (short)b.y;\n\t    pts[3].x = (short)(b.x + b.width - 1 - cut);  pts[3].y = (short)b.y;\n\t    pts[4].x = (short)(b.x + b.width - 1);  pts[4].y = (short)(b.y + cut);\n\t    pts[5].x = (short)(b.x + b.width - 1);  pts[5].y = (short)(b.y + b.height);\n\t    break;\n\tcase TTK_STICK_N:\n\t    pts[0].x = (short)b.x;  pts[0].y = (short)b.y;\n\t    pts[1].x = (short)b.x;  pts[1].y = (short)(b.y + b.height - 1 - cut);\n\t    pts[2].x = (short)(b.x + cut);  pts[2].y = (short)(b.y + b.height - 1);\n\t    pts[3].x = (short)(b.x + b.width - 1 - cut);  pts[3].y = (short)(b.y + b.height - 1);\n\t    pts[4].x = (short)(b.x + b.width - 1);  pts[4].y = (short)(b.y + b.height - 1 - cut);\n\t    pts[5].x = (short)(b.x + b.width - 1);  pts[5].y = (short)(b.y - 1);\n\t    break;\n\tcase TTK_STICK_E:\n\t    pts[0].x = (short)(b.x + b.width - 1);  pts[0].y = (short)b.y;\n\t    pts[1].x = (short)(b.x + cut);  pts[1].y = (short)b.y;\n\t    pts[2].x = (short)b.x;  pts[2].y = (short)(b.y + cut);\n\t    pts[3].x = (short)b.x;  pts[3].y = (short)(b.y + b.height - 1 - cut);\n\t    pts[4].x = (short)(b.x + cut);  pts[4].y = (short)(b.y + b.height - 1);\n\t    pts[5].x = (short)(b.x + b.width);  pts[5].y = (short)(b.y + b.height - 1);\n\t    break;\n\tcase TTK_STICK_W:\n\t    pts[0].x = (short)b.x;  pts[0].y = (short)b.y;\n\t    pts[1].x = (short)(b.x + b.width - 1 - cut);  pts[1].y = (short)b.y;\n\t    pts[2].x = (short)(b.x + b.width - 1);  pts[2].y = (short)(b.y + cut);\n\t    pts[3].x = (short)(b.x + b.width - 1);  pts[3].y = (short)(b.y + b.height - 1 - cut);\n\t    pts[4].x = (short)(b.x + b.width - 1 - cut);  pts[4].y = (short)(b.y + b.height - 1);\n\t    pts[5].x = (short)(b.x - 1);  pts[5].y = (short)(b.y + b.height - 1);\n\t    break;\n    }\n\n    XFillPolygon(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC),\n\t    pts, 6, Convex, CoordModeOrigin);\n\n    Tk_GetPixelsFromObj(NULL, tkwin, tab->borderWidthObj, &borderWidth);\n    while (borderWidth--) {\n\tint n;\n\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t    case TTK_STICK_E:\n\t\tn = 3;\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t    case TTK_STICK_W:\n\t\tn = 5;\n\t\tbreak;\n\t}\n\tif ((state & (TTK_STATE_LAST | TTK_STATE_SELECTED)) ==\n\t\t(TTK_STATE_LAST | TTK_STATE_SELECTED) &&\n\t\t(nbTabPosStickBit == TTK_STICK_E ||\n\t\t nbTabPosStickBit == TTK_STICK_S)) {\n\t    --n;\n\t}\n\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t    case TTK_STICK_E:\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t\tpts, 4, CoordModeOrigin);\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t\tpts+3, n, CoordModeOrigin);\n\t\tif (n == 2 && once--) {\n\t\t    HDC hdc;\n\t\t    TkWinDCState dcState;\n\t\t    RECT rc;\n\n\t\t    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\t\t    if (nbTabPlcStickBit == TTK_STICK_S) {\n\t\t\trc.left = pts[0].x;\n\t\t\trc.top = pts[4].y;\n\t\t\trc.right = pts[4].x + 1;\n\t\t\trc.bottom = pts[0].y+ 1;\n\t\t    } else {\n\t\t\trc.left = pts[4].x;\n\t\t\trc.top = pts[0].y;\n\t\t\trc.right = pts[0].x + 1;\n\t\t\trc.bottom = pts[4].y + 1;\n\t\t    }\n\t\t    DrawEdge(hdc, &rc, EDGE_RAISED,\n\t\t\t    (nbTabPlcStickBit == TTK_STICK_E) ?\n\t\t\t    BF_BOTTOM : BF_RIGHT);\n\t\t    TkWinReleaseDrawableDC(d, hdc, &dcState);\n\t\t}\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t    case TTK_STICK_W:\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),\n\t\t\tpts, 2, CoordModeOrigin);\n\t\tXDrawLines(disp, d,\n\t\t\tTk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),\n\t\t\tpts+1, n, CoordModeOrigin);\n\t\tif (n == 4 && once--) {\n\t\t    HDC hdc;\n\t\t    TkWinDCState dcState;\n\t\t    RECT rc;\n\n\t\t    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\t\t    rc.left = pts[0].x;\n\t\t    rc.top = pts[0].y;\n\t\t    rc.right = pts[4].x + 1;\n\t\t    rc.bottom = pts[4].y + 1;\n\t\t    DrawEdge(hdc, &rc, EDGE_RAISED,\n\t\t\t    (nbTabPlcStickBit == TTK_STICK_W) ?\n\t\t\t    BF_BOTTOM : BF_RIGHT);\n\t\t    TkWinReleaseDrawableDC(d, hdc, &dcState);\n\t\t}\n\t\tbreak;\n\t}\n\n\tswitch (nbTabPlcStickBit) {\n\t    default:\n\t    case TTK_STICK_S:\n\t\t++pts[0].x;  ++pts[1].x;  ++pts[2].y;\n\t\t++pts[3].y;  --pts[4].x;  --pts[5].x;\n\t\tbreak;\n\t    case TTK_STICK_N:\n\t\t++pts[0].x;  ++pts[1].x;  --pts[2].y;\n\t\t--pts[3].y;  --pts[4].x;  --pts[5].x;\n\t\tbreak;\n\t    case TTK_STICK_E:\n\t\t++pts[0].y;  ++pts[1].y;  ++pts[2].x;\n\t\t++pts[3].x;  --pts[4].y;  --pts[5].y;\n\t\tbreak;\n\t    case TTK_STICK_W:\n\t\t++pts[0].y;  ++pts[1].y;  --pts[2].x;\n\t\t--pts[3].x;  --pts[4].y;  --pts[5].y;\n\t\tbreak;\n\t}\n    }\n}\n\nstatic const Ttk_ElementSpec TabElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(TabElement),\n    TabElementOptions,\n    TabElementSize,\n    TabElementDraw\n};\n\nstatic void ClientElementSize(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    TCL_UNUSED(Tk_Window),\n    TCL_UNUSED(int *), /* widthPtr */\n    TCL_UNUSED(int *), /* heightPtr */\n    Ttk_Padding *paddingPtr)\n{\n    paddingPtr->left = paddingPtr->right = (short)GetSystemMetrics(SM_CXEDGE);\n    paddingPtr->top = paddingPtr->bottom = (short)GetSystemMetrics(SM_CYEDGE);\n}\n\nstatic void ClientElementDraw(\n    TCL_UNUSED(void *), /* clientData */\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    TCL_UNUSED(Ttk_State))\n{\n    RECT rc = BoxToRect(b);\n    TkWinDCState dcState;\n    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);\n\n    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_SOFT);\n    TkWinReleaseDrawableDC(d, hdc, &dcState);\n}\n\nstatic const Ttk_ElementSpec ClientElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    ClientElementSize,\n    ClientElementDraw\n};\n\n/*------------------------------------------------------------------------\n * +++ Layouts.\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"TButton\",\n    TTK_GROUP(\"Button.border\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Button.label\", TTK_FILL_BOTH))))\n\nTTK_LAYOUT(\"TCombobox\",\n    TTK_GROUP(\"Combobox.field\", TTK_FILL_BOTH,\n\tTTK_NODE(\"Combobox.downarrow\", TTK_PACK_RIGHT|TTK_FILL_Y)\n\tTTK_GROUP(\"Combobox.padding\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Combobox.focus\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Combobox.textarea\", TTK_FILL_BOTH)))))\n\nTTK_END_LAYOUT_TABLE\n\n/* ---------------------------------------------------------------------- */\n\nMODULE_SCOPE int\nTtkWinTheme_Init(\n    Tcl_Interp *interp,\n    TCL_UNUSED(HWND))\n{\n    Ttk_Theme themePtr, parentPtr;\n    const FrameControlElementData *fce = FrameControlElements;\n\n    parentPtr = Ttk_GetTheme(interp, \"alt\");\n    themePtr = Ttk_CreateTheme(interp, \"winnative\", parentPtr);\n    if (!themePtr) {\n\treturn TCL_ERROR;\n    }\n\n    Ttk_RegisterElement(NULL, themePtr, \"border\", &BorderElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"Button.border\",\n\t&ButtonBorderElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"field\", &FieldElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"focus\", &FocusElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"Combobox.focus\",\n\t&ComboboxFocusElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"thumb\", &ThumbElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"slider\", &SliderElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"Scrollbar.trough\", &TroughElementSpec,\n\tTroughClientDataInit(interp));\n\n    Ttk_RegisterElement(NULL, themePtr, \"tab\", &TabElementSpec, NULL);\n    Ttk_RegisterElement(NULL, themePtr, \"client\", &ClientElementSpec, NULL);\n\n    for (fce = FrameControlElements; fce->name != 0; ++fce) {\n\tTtk_RegisterElement(NULL, themePtr, fce->name,\n\t\t&FrameControlElementSpec, (void *)fce);\n    }\n\n    Ttk_RegisterLayouts(themePtr, LayoutTable);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::winnative\", TTK_VERSION);\n    return TCL_OK;\n}\n\n"
  },
  {
    "path": "win/ttkWinVistaTheme.c",
    "content": "/*\n * Tk theme engine which uses the Windows \"Visual Styles\" API\n * Adapted from Georgios Petasis' XP theme patch.\n *\n * Copyright © 2003 Georgios Petasis, petasis@iit.demokritos.gr.\n * Copyright © 2003 Joe English\n * Copyright © 2003 Pat Thoyts\n *\n * See the file \"license.terms\" for information on usage and redistribution\n * of this file, and for a DISCLAIMER OF ALL WARRANTIES.\n *\n * See also:\n *\n * <URL: http://msdn.microsoft.com/library/en-us/\n *\tshellcc/platform/commctls/userex/refentry.asp >\n */\n\n#include \"tkWinInt.h\"\n#include <uxtheme.h>\n#include <vssym32.h>\n#include \"ttk/ttkThemeInt.h\"\n#ifdef _MSC_VER\n#   pragma comment (lib, \"uxtheme.lib\")\n#endif\n\n/*\n * VistaThemeDeleteProc --\n *\n *      Release any theme allocated resources.\n */\n\nstatic void\nVistaThemeDeleteProc(\n    TCL_UNUSED(void *))\n{\n}\n\nstatic int\nVistaThemeEnabled(\n    TCL_UNUSED(Ttk_Theme),\n    TCL_UNUSED(void *))\n{\n    int active = IsThemeActive();\n    int themed = IsAppThemed();\n\n    return (active && themed);\n}\n\n/*\n * BoxToRect --\n *\tHelper routine.  Returns a RECT data structure.\n */\nstatic RECT\nBoxToRect(Ttk_Box b)\n{\n    RECT rc;\n    rc.top = b.y;\n    rc.left = b.x;\n    rc.bottom = b.y + b.height;\n    rc.right = b.x + b.width;\n    return rc;\n}\n\n/*\n * Map Tk state bitmaps to Vista style enumerated values.\n */\nstatic const Ttk_StateTable null_statemap[] = { {0,0,0} };\n\n/*\n * Pushbuttons (Tk: \"Button\")\n */\nstatic const Ttk_StateTable pushbutton_statemap[] =\n{\n    { PBS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { PBS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { PBS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { PBS_DEFAULTED,\tTTK_STATE_ALTERNATE, 0 },\n    { PBS_NORMAL,\t0, 0 }\n};\n\n/*\n * Checkboxes (Tk: \"Checkbutton\")\n */\nstatic const Ttk_StateTable checkbox_statemap[] =\n{\n{CBS_MIXEDDISABLED,\tTTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0},\n{CBS_MIXEDPRESSED,\tTTK_STATE_ALTERNATE|TTK_STATE_PRESSED, 0},\n{CBS_MIXEDHOT,\tTTK_STATE_ALTERNATE|TTK_STATE_ACTIVE, 0},\n{CBS_MIXEDNORMAL,\tTTK_STATE_ALTERNATE, 0},\n{CBS_CHECKEDDISABLED,\tTTK_STATE_SELECTED|TTK_STATE_DISABLED, 0},\n{CBS_CHECKEDPRESSED,\tTTK_STATE_SELECTED|TTK_STATE_PRESSED, 0},\n{CBS_CHECKEDHOT,\tTTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0},\n{CBS_CHECKEDNORMAL,\tTTK_STATE_SELECTED, 0},\n{CBS_UNCHECKEDDISABLED,\tTTK_STATE_DISABLED, 0},\n{CBS_UNCHECKEDPRESSED,\tTTK_STATE_PRESSED, 0},\n{CBS_UNCHECKEDHOT,\tTTK_STATE_ACTIVE, 0},\n{CBS_UNCHECKEDNORMAL,\t0,0 }\n};\n\n/*\n * Radiobuttons:\n */\nstatic const Ttk_StateTable radiobutton_statemap[] =\n{\n{RBS_UNCHECKEDDISABLED,\tTTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0},\n{RBS_UNCHECKEDNORMAL,\tTTK_STATE_ALTERNATE, 0},\n{RBS_CHECKEDDISABLED,\tTTK_STATE_SELECTED|TTK_STATE_DISABLED, 0},\n{RBS_CHECKEDPRESSED,\tTTK_STATE_SELECTED|TTK_STATE_PRESSED, 0},\n{RBS_CHECKEDHOT,\tTTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0},\n{RBS_CHECKEDNORMAL,\tTTK_STATE_SELECTED, 0},\n{RBS_UNCHECKEDDISABLED,\tTTK_STATE_DISABLED, 0},\n{RBS_UNCHECKEDPRESSED,\tTTK_STATE_PRESSED, 0},\n{RBS_UNCHECKEDHOT,\tTTK_STATE_ACTIVE, 0},\n{RBS_UNCHECKEDNORMAL,\t0,0 }\n};\n\n/*\n * Groupboxes (tk: \"frame\")\n */\nstatic const Ttk_StateTable groupbox_statemap[] =\n{\n{GBS_DISABLED,\tTTK_STATE_DISABLED, 0},\n{GBS_NORMAL,\t0,0 }\n};\n\n/*\n * Edit fields (tk: \"entry\")\n */\nstatic const Ttk_StateTable edittext_statemap[] =\n{\n    { ETS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { ETS_READONLY,\tTTK_STATE_READONLY, 0 },\n    { ETS_FOCUSED,\tTTK_STATE_FOCUS, 0 },\n    { ETS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { ETS_NORMAL,\t0, 0 }\n/* NOT USED: ETS_ASSIST, ETS_SELECTED */\n};\n\n/*\n * Combobox text field statemap:\n * Same as edittext_statemap, but doesn't use ETS_READONLY\n * (fixes: #1032409)\n */\nstatic const Ttk_StateTable combotext_statemap[] =\n{\n    { ETS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { ETS_FOCUSED,\tTTK_STATE_FOCUS, 0 },\n    { ETS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { ETS_NORMAL,\t0, 0 }\n};\n\n/*\n * Combobox button: (CBP_DROPDOWNBUTTON)\n */\nstatic const Ttk_StateTable combobox_statemap[] = {\n    { CBXS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { CBXS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { CBXS_HOT,\tTTK_STATE_ACTIVE, 0 },\n    { CBXS_HOT,\tTTK_STATE_HOVER, 0 },\n    { CBXS_NORMAL,\t0, 0 }\n};\n\n/*\n * Toolbar buttons (TP_BUTTON):\n */\nstatic const Ttk_StateTable toolbutton_statemap[] =  {\n    { TS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { TS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { TS_HOTCHECKED,\tTTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0 },\n    { TS_CHECKED,\tTTK_STATE_SELECTED, 0 },\n    { TS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { TS_NORMAL,\t0,0 }\n};\n\n/*\n * Scrollbars (Tk: \"Scrollbar.thumb\")\n */\nstatic const Ttk_StateTable scrollbar_statemap[] =\n{\n    { SCRBS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { SCRBS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { SCRBS_HOT,\tTTK_STATE_ACTIVE, 0 },\n    { SCRBS_NORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable uparrow_statemap[] =\n{\n    { ABS_UPDISABLED,\tTTK_STATE_DISABLED, 0 },\n    { ABS_UPPRESSED,\tTTK_STATE_PRESSED, 0 },\n    { ABS_UPHOT,\tTTK_STATE_ACTIVE, 0 },\n    { ABS_UPNORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable downarrow_statemap[] =\n{\n    { ABS_DOWNDISABLED,\tTTK_STATE_DISABLED, 0 },\n    { ABS_DOWNPRESSED,\tTTK_STATE_PRESSED, 0 },\n    { ABS_DOWNHOT,\tTTK_STATE_ACTIVE, 0 },\n    { ABS_DOWNNORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable leftarrow_statemap[] =\n{\n    { ABS_LEFTDISABLED,\tTTK_STATE_DISABLED, 0 },\n    { ABS_LEFTPRESSED,\tTTK_STATE_PRESSED, 0 },\n    { ABS_LEFTHOT,\tTTK_STATE_ACTIVE, 0 },\n    { ABS_LEFTNORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable rightarrow_statemap[] =\n{\n    { ABS_RIGHTDISABLED,TTK_STATE_DISABLED, 0 },\n    { ABS_RIGHTPRESSED, TTK_STATE_PRESSED, 0 },\n    { ABS_RIGHTHOT,\tTTK_STATE_ACTIVE, 0 },\n    { ABS_RIGHTNORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable spinbutton_statemap[] =\n{\n    { DNS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { DNS_PRESSED,\tTTK_STATE_PRESSED,  0 },\n    { DNS_HOT,\t\tTTK_STATE_ACTIVE,   0 },\n    { DNS_NORMAL,\t0,\t\t    0 },\n};\n\n/*\n * Trackbar thumb: (Tk: \"scale slider\")\n */\nstatic const Ttk_StateTable scale_statemap[] =\n{\n    { TUS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { TUS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { TUS_FOCUSED,\tTTK_STATE_FOCUS, 0 },\n    { TUS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { TUS_NORMAL,\t0, 0 }\n};\n\nstatic const Ttk_StateTable tabitem_statemap[] =\n{\n    { TIS_DISABLED,     TTK_STATE_DISABLED, 0 },\n    { TIS_SELECTED,     TTK_STATE_SELECTED, 0 },\n    { TIS_HOT,          TTK_STATE_ACTIVE,   0 },\n    { TIS_FOCUSED,      TTK_STATE_FOCUS,    0 },\n    { TIS_NORMAL,       0,                  0 },\n};\n\n\n/*\n *----------------------------------------------------------------------\n * +++ Element data:\n *\n * The following structure is passed as the 'clientData' pointer\n * to most elements in this theme.  It contains data relevant\n * to a single Vista Theme \"part\".\n *\n * <<NOTE-GetThemeMargins>>:\n *\tIn theory, we should be call GetThemeMargins(...TMT_CONTENTRECT...)\n *\tto calculate the internal padding.  In practice, this routine\n *\tonly seems to work properly for BP_PUSHBUTTON.  So we hardcode\n *\tthe required padding at element registration time instead.\n *\n *\tThe PAD_MARGINS flag bit determines whether the padding\n *\tshould be added on the inside (0) or outside (1) of the element.\n *\n * <<NOTE-GetThemePartSize>>:\n *\tThis gives bogus metrics for some parts (in particular,\n *\tBP_PUSHBUTTONS).  Set the IGNORE_THEMESIZE flag to skip this call.\n */\n\ntypedef struct\t/* Vista element specifications */\n{\n    const char\t*elementName;\t/* Tk theme engine element name */\n    const Ttk_ElementSpec *elementSpec;\n\t\t\t\t/* Element spec (usually GenericElementSpec) */\n    LPCWSTR\tclassName;\t/* Windows window class name */\n    int\tpartId;\t\t/* BP_PUSHBUTTON, BP_CHECKBUTTON, etc. */\n    const Ttk_StateTable *statemap;\t/* Map Tk states to Vista states */\n    Ttk_Padding\tpadding;\t/* See NOTE-GetThemeMargins */\n    unsigned\tflags;\n#   define\tIGNORE_THEMESIZE 0x80000000U /* See NOTE-GetThemePartSize */\n#   define\tPAD_MARGINS\t 0x40000000U /* See NOTE-GetThemeMargins */\n#   define\tHEAP_ELEMENT\t 0x20000000U /* ElementInfo is on heap */\n#   define\tHALF_HEIGHT\t 0x10000000U /* Used by GenericSizedElements */\n#   define\tHALF_WIDTH\t 0x08000000U /* Used by GenericSizedElements */\n} ElementInfo;\n\ntypedef struct\n{\n    /*\n     * Static data, initialized when element is registered:\n     */\n    const ElementInfo\t*info;\n    HWND parentHwnd;\n\n    /*\n     * Dynamic data, allocated by InitElementData:\n     */\n    HTHEME\thTheme;\n    HDC\t\thDC;\n    HWND\thwnd;\n\n    /* For TkWinDrawableReleaseDC: */\n    Drawable\tdrawable;\n    TkWinDCState dcState;\n} ElementData;\n\nstatic ElementData *\nNewElementData(HWND hwnd, const ElementInfo *info)\n{\n    ElementData *elementData = (ElementData *)Tcl_Alloc(sizeof(ElementData));\n\n    elementData->parentHwnd = hwnd;\n    elementData->info = info;\n    elementData->hTheme = elementData->hDC = 0;\n\n    return elementData;\n}\n\n/*\n * Destroy elements. If the element was created by the element factory\n * then the info member is dynamically allocated. Otherwise it was\n * static data from the C object and only the ElementData needs freeing.\n */\nstatic void DestroyElementData(void *clientData)\n{\n    ElementData *elementData = (ElementData *)clientData;\n    if (elementData->info->flags & HEAP_ELEMENT) {\n\tTcl_Free((void *)elementData->info->statemap);\n\tTcl_Free((void *)elementData->info->className);\n\tTcl_Free((void *)elementData->info->elementName);\n\tTcl_Free((void *)elementData->info);\n    }\n    Tcl_Free(clientData);\n}\n\n/*\n * InitElementData --\n *\tLooks up theme handle.  If Drawable argument is non-NULL,\n *\talso initializes DC.\n *\n * Returns:\n *\t1 on success, 0 on error.\n *\tCaller must later call FreeElementData() so this element\n *\tcan be reused.\n */\n\nstatic int\nInitElementData(ElementData *elementData, Tk_Window tkwin, Drawable d)\n{\n    Window win = Tk_WindowId(tkwin);\n\n    if (win) {\n\telementData->hwnd = Tk_GetHWND(win);\n    } else  {\n\telementData->hwnd = elementData->parentHwnd;\n    }\n\n    elementData->hTheme = OpenThemeData(\n\t    elementData->hwnd, elementData->info->className);\n\n    if (!elementData->hTheme) {\n\treturn 0;\n    }\n\n    elementData->drawable = d;\n    if (d != 0) {\n\telementData->hDC = TkWinGetDrawableDC(Tk_Display(tkwin), d,\n\t\t&elementData->dcState);\n    }\n\n    return 1;\n}\n\nstatic void\nFreeElementData(ElementData *elementData)\n{\n    CloseThemeData(elementData->hTheme);\n    if (elementData->drawable != 0) {\n\tTkWinReleaseDrawableDC(\n\t    elementData->drawable, elementData->hDC, &elementData->dcState);\n    }\n}\n\n/*----------------------------------------------------------------------\n * +++ Generic element implementation.\n *\n * Used for elements which are handled entirely by the Vista Theme API,\n * such as radiobutton and checkbutton indicators, scrollbar arrows, etc.\n */\n\nstatic void GenericElementSize(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    Ttk_Padding *paddingPtr)\n{\n    ElementData *elementData = (ElementData *)clientData;\n    HRESULT result;\n    SIZE size;\n\n    if (!InitElementData(elementData, tkwin, 0)) {\n\treturn;\n    }\n\n    if (!(elementData->info->flags & IGNORE_THEMESIZE)) {\n\tresult = GetThemePartSize(\n\t    elementData->hTheme,\n\t    NULL,\n\t    elementData->info->partId,\n\t    Ttk_StateTableLookup(elementData->info->statemap, 0),\n\t    NULL /*RECT *prc*/,\n\t    TS_TRUE,\n\t    &size);\n\n\tif (SUCCEEDED(result)) {\n\t    *widthPtr = size.cx;\n\t    *heightPtr = size.cy;\n\t}\n    }\n\n    /* See NOTE-GetThemeMargins\n     */\n    *paddingPtr = elementData->info->padding;\n    if (elementData->info->flags & PAD_MARGINS) {\n\t*widthPtr += Ttk_PaddingWidth(elementData->info->padding);\n\t*heightPtr += Ttk_PaddingHeight(elementData->info->padding);\n    }\n}\n\nstatic void GenericElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ElementData *elementData = (ElementData *)clientData;\n    RECT rc;\n\n    if (!InitElementData(elementData, tkwin, d)) {\n\treturn;\n    }\n\n    if (elementData->info->flags & PAD_MARGINS) {\n\tb = Ttk_PadBox(b, elementData->info->padding);\n    }\n    rc = BoxToRect(b);\n\n    DrawThemeBackground(\n\telementData->hTheme,\n\telementData->hDC,\n\telementData->info->partId,\n\tTtk_StateTableLookup(elementData->info->statemap, state),\n\t&rc,\n\tNULL/*pContentRect*/);\n\n    FreeElementData(elementData);\n}\n\nstatic const Ttk_ElementSpec GenericElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    GenericElementSize,\n    GenericElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Sized element implementation.\n *\n * Used for elements which are handled entirely by the Vista Theme API,\n * but that require a fixed size adjustment.\n * Note that GetThemeSysSize calls through to GetSystemMetrics\n */\n\nstatic void\nGenericSizedElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)\n{\n    ElementData *elementData = (ElementData *)clientData;\n\n    if (!InitElementData(elementData, tkwin, 0)) {\n\treturn;\n    }\n\n    GenericElementSize(clientData, elementRecord, tkwin,\n\twidthPtr, heightPtr, paddingPtr);\n\n    *widthPtr = GetThemeSysSize(NULL,\n\t(elementData->info->flags >> 8) & 0xff);\n    *heightPtr = GetThemeSysSize(NULL,\n\telementData->info->flags & 0xff);\n    if (elementData->info->flags & HALF_HEIGHT) {\n\t*heightPtr /= 2;\n    }\n    if (elementData->info->flags & HALF_WIDTH) {\n\t*widthPtr /= 2;\n    }\n}\n\nstatic const Ttk_ElementSpec GenericSizedElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    GenericSizedElementSize,\n    GenericElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Spinbox arrow element.\n *     These are half-height scrollbar buttons.\n */\n\nstatic void\nSpinboxArrowElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)\n{\n    ElementData *elementData = (ElementData *)clientData;\n\n    if (!InitElementData(elementData, tkwin, 0)) {\n\treturn;\n    }\n\n    GenericSizedElementSize(clientData, elementRecord, tkwin,\n\twidthPtr, heightPtr, paddingPtr);\n\n    /* force the arrow button height to half size */\n    *heightPtr /= 2;\n}\n\nstatic const Ttk_ElementSpec SpinboxArrowElementSpec = {\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    SpinboxArrowElementSize,\n    GenericElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Scrollbar thumb element.\n *     Same as a GenericElement, but don't draw in the disabled state.\n */\n\nstatic void ThumbElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    ElementData *elementData = (ElementData *)clientData;\n    int stateId = Ttk_StateTableLookup(elementData->info->statemap, state);\n    RECT rc = BoxToRect(b);\n\n    /*\n     * Don't draw the thumb if we are disabled.\n     */\n    if (state & TTK_STATE_DISABLED) {\n\treturn;\n    }\n\n    if (!InitElementData(elementData, tkwin, d)) {\n\treturn;\n    }\n\n    DrawThemeBackground(elementData->hTheme,\n\telementData->hDC, elementData->info->partId, stateId,\n\t&rc, NULL);\n\n    FreeElementData(elementData);\n}\n\nstatic const Ttk_ElementSpec ThumbElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    GenericElementSize,\n    ThumbElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Progress bar element.\n *\tIncreases the requested length of PP_CHUNK and PP_CHUNKVERT parts\n *\tso that indeterminate progress bars show 3 bars instead of 1.\n */\n\nstatic void PbarElementSize(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)\n{\n    ElementData *elementData = (ElementData *)clientData;\n    int nBars = 3;\n\n    GenericElementSize(clientData, elementRecord, tkwin,\n\twidthPtr, heightPtr, paddingPtr);\n\n    if (elementData->info->partId == PP_CHUNK) {\n\t*widthPtr *= nBars;\n    } else if (elementData->info->partId == PP_CHUNKVERT) {\n\t*heightPtr *= nBars;\n    }\n}\n\nstatic const Ttk_ElementSpec PbarElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    PbarElementSize,\n    GenericElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++  Notebook tab element.\n *\tSame as generic element, with additional logic to select\n *\tproper iPartID for the leftmost tab.\n *\n *\tNotes: TABP_TABITEMRIGHTEDGE (or TABP_TOPTABITEMRIGHTEDGE,\n *\twhich appears to be identical) should be used if the\n *\ttab is exactly at the right edge of the notebook, but\n *\tnot if it's simply the rightmost tab.  This information\n *\tis not available.\n *\n *\tThe TIS_* and TILES_* definitions are identical, so\n *\twe can use the same statemap no matter what the partId.\n */\n\nstatic void TabElementSize(\n    void *clientData,\n    void *elementRecord,\n    Tk_Window tkwin,\n    int *widthPtr,\n    int *heightPtr,\n    Ttk_Padding *paddingPtr)\n{\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    GenericElementSize(clientData, elementRecord, tkwin,\n\t    widthPtr, heightPtr, paddingPtr);\n\n    *paddingPtr = Ttk_UniformPadding(3);\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    paddingPtr->bottom = 0;\n\t    break;\n\tcase TTK_STICK_N:\n\t    paddingPtr->top = 0;\n\t    break;\n\tcase TTK_STICK_E:\n\t    paddingPtr->right = 0;\n\t    break;\n\tcase TTK_STICK_W:\n\t    paddingPtr->left = 0;\n\t    break;\n    }\n}\n\nstatic void TabElementDraw(\n    void *clientData,\n    TCL_UNUSED(void *), /* elementRecord */\n    Tk_Window tkwin,\n    Drawable d,\n    Ttk_Box b,\n    Ttk_State state)\n{\n    Ttk_PositionSpec nbTabPosStickBit = TTK_STICK_W;\n    Ttk_PositionSpec nbTabPlcStickBit = TTK_STICK_S;\n    TkMainInfo *mainInfoPtr = ((TkWindow *) tkwin)->mainPtr;\n    ElementData *elementData = (ElementData *)clientData;\n    int partId = elementData->info->partId;\n    int isSelected = (state & TTK_STATE_SELECTED);\n    int stateId = Ttk_StateTableLookup(elementData->info->statemap, state);\n\n    if (mainInfoPtr != NULL) {\n\tnbTabPosStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPosition & 0x0f);\n\tnbTabPlcStickBit =\n\t    (Ttk_PositionSpec) (mainInfoPtr->nbTabPlacement & 0x0f);\n    }\n\n    /*\n     * Correct the members of b if needed\n     */\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    break;\n\tcase TTK_STICK_N:\n\t    b.y -= isSelected ? 0 : 1; b.height -= isSelected ? 1 : 0;\n\t    if (nbTabPosStickBit == TTK_STICK_E && isSelected &&\n\t\t    (state & TTK_STATE_LAST)) {\t\t/* rightmost tab */\n\t\tb.x -= 2;\n\t    }\n\t    break;\n\tcase TTK_STICK_E:\n\t    b.width -= isSelected ? 1 : 0;\n\t    if (nbTabPosStickBit == TTK_STICK_S && isSelected &&\n\t\t    (state & TTK_STATE_LAST)) {\t\t/* bottommost tab */\n\t\tb.y -= 1;\n\t    }\n\t    break;\n\tcase TTK_STICK_W:\n\t    b.x -= isSelected ? 1 : 2; b.width -= isSelected ? 1 : 0;\n\t    if (nbTabPosStickBit == TTK_STICK_S && isSelected &&\n\t\t    (state & TTK_STATE_LAST)) {\t\t/* bottommost tab */\n\t\tb.y -= 1;\n\t    }\n\t    break;\n    }\n\n    RECT rc = BoxToRect(b);\n\n    if (!InitElementData(elementData, tkwin, d)) {\n\treturn;\n    }\n\n    if (nbTabPlcStickBit == TTK_STICK_S) {\n\tif (state & TTK_STATE_FIRST) {\n\t    partId = TABP_TABITEMLEFTEDGE;\n\t} else if (state & TTK_STATE_LAST) {\n\t    partId = TABP_TABITEMRIGHTEDGE;\n\t}\n\n\t/*\n\t * Draw the border and fill into rc\n\t */\n\tDrawThemeBackground(\n\t    elementData->hTheme, elementData->hDC, partId, stateId, &rc, NULL);\n    } else {\n\t/*\n\t * Draw the fill but no border into rc\n\t */\n\tRECT rc2 = rc;\n\t--rc2.top; --rc2.left; ++rc2.bottom; ++rc2.right;\n\tDrawThemeBackground(\n\t    elementData->hTheme, elementData->hDC, partId, stateId, &rc2, &rc);\n    }\n\n    /*\n     * Draw a flat border at 3 edges\n     */\n    switch (nbTabPlcStickBit) {\n\tdefault:\n\tcase TTK_STICK_S:\n\t    break;\n\tcase TTK_STICK_N:\n\t    DrawThemeEdge(\n\t\telementData->hTheme, elementData->hDC, partId, stateId, &rc,\n\t\tBDR_RAISEDINNER, BF_FLAT|BF_LEFT|BF_RIGHT|BF_BOTTOM, NULL);\n\t    break;\n\tcase TTK_STICK_E:\n\t    DrawThemeEdge(\n\t\telementData->hTheme, elementData->hDC, partId, stateId, &rc,\n\t\tBDR_RAISEDINNER, BF_FLAT|BF_LEFT|BF_TOP|BF_BOTTOM, NULL);\n\t    break;\n\tcase TTK_STICK_W:\n\t    DrawThemeEdge(\n\t\telementData->hTheme, elementData->hDC, partId, stateId, &rc,\n\t\tBDR_RAISEDINNER, BF_FLAT|BF_TOP|BF_RIGHT|BF_BOTTOM, NULL);\n\t    break;\n    }\n\n    FreeElementData(elementData);\n}\n\nstatic const Ttk_ElementSpec TabElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    TabElementSize,\n    TabElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++  Tree indicator element.\n *\n *\tGeneric element, but don't display at all if TTK_STATE_LEAF set\n */\n\nstatic const Ttk_StateTable header_statemap[] =\n{\n    { HIS_PRESSED,\tTTK_STATE_PRESSED, 0 },\n    { HIS_HOT,\t\tTTK_STATE_ACTIVE, 0 },\n    { HIS_NORMAL,\t0,0 },\n};\n\nstatic const Ttk_StateTable treeview_statemap[] =\n{\n    { TREIS_DISABLED,\tTTK_STATE_DISABLED, 0 },\n    { TREIS_SELECTED,\tTTK_STATE_SELECTED, 0},\n    { TREIS_HOT,\tTTK_STATE_ACTIVE, 0 },\n    { TREIS_NORMAL,\t0,0 },\n};\n\nstatic const Ttk_StateTable tvpglyph_statemap[] =\n{\n    { GLPS_OPENED,\tTTK_STATE_OPEN, 0 },\n    { GLPS_CLOSED,\t0,0 },\n};\n\nstatic void TreeIndicatorElementDraw(\n    void *clientData, void *elementRecord, Tk_Window tkwin,\n    Drawable d, Ttk_Box b, Ttk_State state)\n{\n    if (!(state & TTK_STATE_LEAF)) {\n\tGenericElementDraw(clientData,elementRecord,tkwin,d,b,state);\n    }\n}\n\nstatic const Ttk_ElementSpec TreeIndicatorElementSpec =\n{\n    TK_STYLE_VERSION_2,\n    sizeof(NullElement),\n    TtkNullElementOptions,\n    GenericElementSize,\n    TreeIndicatorElementDraw\n};\n\n/*----------------------------------------------------------------------\n * +++ Widget layouts:\n */\n\nTTK_BEGIN_LAYOUT_TABLE(LayoutTable)\n\nTTK_LAYOUT(\"TButton\",\n    TTK_GROUP(\"Button.button\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Button.focus\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Button.padding\", TTK_FILL_BOTH,\n\t\tTTK_NODE(\"Button.label\", TTK_FILL_BOTH)))))\n\nTTK_LAYOUT(\"TMenubutton\",\n    TTK_NODE(\"Menubutton.dropdown\", TTK_PACK_RIGHT|TTK_FILL_Y)\n    TTK_GROUP(\"Menubutton.button\", TTK_FILL_BOTH,\n\t    TTK_GROUP(\"Menubutton.padding\", TTK_FILL_X,\n\t\tTTK_NODE(\"Menubutton.label\", 0))))\n\nTTK_LAYOUT(\"Horizontal.TScrollbar\",\n    TTK_GROUP(\"Horizontal.Scrollbar.trough\", TTK_FILL_X,\n\tTTK_NODE(\"Horizontal.Scrollbar.leftarrow\", TTK_PACK_LEFT)\n\tTTK_NODE(\"Horizontal.Scrollbar.rightarrow\", TTK_PACK_RIGHT)\n\tTTK_GROUP(\"Horizontal.Scrollbar.thumb\", TTK_FILL_BOTH|TTK_UNIT,\n\t    TTK_NODE(\"Horizontal.Scrollbar.grip\", 0))))\n\nTTK_LAYOUT(\"Vertical.TScrollbar\",\n    TTK_GROUP(\"Vertical.Scrollbar.trough\", TTK_FILL_Y,\n\tTTK_NODE(\"Vertical.Scrollbar.uparrow\", TTK_PACK_TOP)\n\tTTK_NODE(\"Vertical.Scrollbar.downarrow\", TTK_PACK_BOTTOM)\n\tTTK_GROUP(\"Vertical.Scrollbar.thumb\", TTK_FILL_BOTH|TTK_UNIT,\n\t    TTK_NODE(\"Vertical.Scrollbar.grip\", 0))))\n\nTTK_LAYOUT(\"Horizontal.TScale\",\n    TTK_GROUP(\"Scale.focus\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Horizontal.Scale.trough\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Horizontal.Scale.track\", TTK_FILL_X)\n\t    TTK_NODE(\"Horizontal.Scale.slider\", TTK_PACK_LEFT) )))\n\nTTK_LAYOUT(\"Vertical.TScale\",\n    TTK_GROUP(\"Scale.focus\", TTK_FILL_BOTH,\n\tTTK_GROUP(\"Vertical.Scale.trough\", TTK_FILL_BOTH,\n\t    TTK_NODE(\"Vertical.Scale.track\", TTK_FILL_Y)\n\t    TTK_NODE(\"Vertical.Scale.slider\", TTK_PACK_TOP) )))\n\nTTK_END_LAYOUT_TABLE\n\n/*----------------------------------------------------------------------\n * +++ Vista element info table:\n */\n\n#define PAD(l,t,r,b) {l,t,r,b}\n#define NOPAD {0,0,0,0}\n\n/* name spec className partId statemap padding flags */\n\nstatic const ElementInfo ElementInfoTable[] = {\n    { \"Checkbutton.indicator\", &GenericElementSpec, L\"BUTTON\",\n\tBP_CHECKBOX, checkbox_statemap, PAD(0, 0, 4, 0), PAD_MARGINS },\n    { \"Radiobutton.indicator\", &GenericElementSpec, L\"BUTTON\",\n\tBP_RADIOBUTTON, radiobutton_statemap, PAD(0, 0, 4, 0), PAD_MARGINS },\n    { \"Button.button\", &GenericElementSpec, L\"BUTTON\",\n\tBP_PUSHBUTTON, pushbutton_statemap, PAD(3, 3, 3, 3), IGNORE_THEMESIZE },\n    { \"Labelframe.border\", &GenericElementSpec, L\"BUTTON\",\n\tBP_GROUPBOX, groupbox_statemap, PAD(2, 2, 2, 2), 0 },\n    { \"Entry.field\", &GenericElementSpec, L\"EDIT\", EP_EDITTEXT,\n\tedittext_statemap, PAD(1, 1, 1, 1), 0 },\n    { \"Combobox.field\", &GenericElementSpec, L\"EDIT\",\n\tEP_EDITTEXT, combotext_statemap, PAD(1, 1, 1, 1), 0 },\n    { \"Combobox.downarrow\", &GenericSizedElementSpec, L\"COMBOBOX\",\n\tCP_DROPDOWNBUTTON, combobox_statemap, NOPAD,\n\t(SM_CXVSCROLL << 8) | SM_CYVSCROLL },\n    { \"Vertical.Scrollbar.trough\", &GenericElementSpec, L\"SCROLLBAR\",\n\tSBP_UPPERTRACKVERT, scrollbar_statemap, NOPAD, 0 },\n    { \"Vertical.Scrollbar.thumb\", &ThumbElementSpec, L\"SCROLLBAR\",\n\tSBP_THUMBBTNVERT, scrollbar_statemap, NOPAD, 0 },\n    { \"Vertical.Scrollbar.grip\", &GenericElementSpec, L\"SCROLLBAR\",\n\tSBP_GRIPPERVERT, scrollbar_statemap, NOPAD, 0 },\n    { \"Horizontal.Scrollbar.trough\", &GenericElementSpec, L\"SCROLLBAR\",\n\tSBP_UPPERTRACKHORZ, scrollbar_statemap, NOPAD, 0 },\n    { \"Horizontal.Scrollbar.thumb\", &ThumbElementSpec, L\"SCROLLBAR\",\n\tSBP_THUMBBTNHORZ, scrollbar_statemap, NOPAD, 0 },\n    { \"Horizontal.Scrollbar.grip\", &GenericElementSpec, L\"SCROLLBAR\",\n\tSBP_GRIPPERHORZ, scrollbar_statemap, NOPAD, 0 },\n    { \"Scrollbar.uparrow\", &GenericSizedElementSpec, L\"SCROLLBAR\",\n\tSBP_ARROWBTN, uparrow_statemap, NOPAD,\n\t(SM_CXVSCROLL << 8) | SM_CYVSCROLL },\n    { \"Scrollbar.downarrow\", &GenericSizedElementSpec, L\"SCROLLBAR\",\n\tSBP_ARROWBTN, downarrow_statemap, NOPAD,\n\t(SM_CXVSCROLL << 8) | SM_CYVSCROLL },\n    { \"Scrollbar.leftarrow\", &GenericSizedElementSpec, L\"SCROLLBAR\",\n\tSBP_ARROWBTN, leftarrow_statemap, NOPAD,\n\t(SM_CXHSCROLL << 8) | SM_CYHSCROLL },\n    { \"Scrollbar.rightarrow\", &GenericSizedElementSpec, L\"SCROLLBAR\",\n\tSBP_ARROWBTN, rightarrow_statemap, NOPAD,\n\t(SM_CXHSCROLL << 8) | SM_CYHSCROLL },\n    { \"Horizontal.Scale.slider\", &GenericElementSpec, L\"TRACKBAR\",\n\tTKP_THUMB, scale_statemap, NOPAD, 0 },\n    { \"Vertical.Scale.slider\", &GenericElementSpec, L\"TRACKBAR\",\n\tTKP_THUMBVERT, scale_statemap, NOPAD, 0 },\n    { \"Horizontal.Scale.track\", &GenericElementSpec, L\"TRACKBAR\",\n\tTKP_TRACK, scale_statemap, NOPAD, 0 },\n    { \"Vertical.Scale.track\", &GenericElementSpec, L\"TRACKBAR\",\n\tTKP_TRACKVERT, scale_statemap, NOPAD, 0 },\n    /* ttk::progressbar elements */\n    { \"Horizontal.Progressbar.pbar\", &PbarElementSpec, L\"PROGRESS\",\n\tPP_CHUNK, null_statemap, NOPAD, 0 },\n    { \"Vertical.Progressbar.pbar\", &PbarElementSpec, L\"PROGRESS\",\n\tPP_CHUNKVERT, null_statemap, NOPAD, 0 },\n    { \"Horizontal.Progressbar.trough\", &GenericElementSpec, L\"PROGRESS\",\n\tPP_BAR, null_statemap, PAD(3,3,3,3), IGNORE_THEMESIZE },\n    { \"Vertical.Progressbar.trough\", &GenericElementSpec, L\"PROGRESS\",\n\tPP_BARVERT, null_statemap, PAD(3,3,3,3), IGNORE_THEMESIZE },\n    /* ttk::notebook */\n    { \"tab\", &TabElementSpec, L\"TAB\",\n\tTABP_TABITEM, tabitem_statemap, PAD(3,3,3,0), 0 },\n    { \"client\", &GenericElementSpec, L\"TAB\",\n\tTABP_PANE, null_statemap, PAD(1,1,3,3), 0 },\n    { \"NotebookPane.background\", &GenericElementSpec, L\"TAB\",\n\tTABP_BODY, null_statemap, NOPAD, 0 },\n    { \"Toolbutton.border\", &GenericElementSpec, L\"TOOLBAR\",\n\tTP_BUTTON, toolbutton_statemap, NOPAD, 0 },\n    { \"Menubutton.button\", &GenericElementSpec, L\"TOOLBAR\",\n\tTP_SPLITBUTTON, toolbutton_statemap, NOPAD, 0 },\n    { \"Menubutton.dropdown\", &GenericSizedElementSpec, L\"TOOLBAR\",\n\tTP_SPLITBUTTONDROPDOWN, toolbutton_statemap, NOPAD,\n\t(SM_CXVSCROLL << 8) | SM_CYVSCROLL },\n    { \"Treeview.field\", &GenericElementSpec, L\"TREEVIEW\",\n\tTVP_TREEITEM, treeview_statemap, PAD(1, 1, 1, 1), IGNORE_THEMESIZE },\n    { \"Treeitem.indicator\", &TreeIndicatorElementSpec, L\"TREEVIEW\",\n\tTVP_GLYPH, tvpglyph_statemap, PAD(1,1,6,0), PAD_MARGINS },\n    { \"Treeheading.border\", &GenericElementSpec, L\"HEADER\",\n\tHP_HEADERITEM, header_statemap, PAD(4,0,4,0), 0 },\n    { \"sizegrip\", &GenericElementSpec, L\"STATUS\",\n\tSP_GRIPPER, null_statemap, NOPAD, 0 },\n    { \"Spinbox.field\", &GenericElementSpec, L\"EDIT\",\n\tEP_EDITTEXT, edittext_statemap, PAD(1, 1, 1, 1), 0 },\n    { \"Spinbox.uparrow\", &SpinboxArrowElementSpec, L\"SPIN\",\n\tSPNP_UP, spinbutton_statemap, NOPAD,\n\tPAD_MARGINS | ((SM_CXVSCROLL << 8) | SM_CYVSCROLL) },\n    { \"Spinbox.downarrow\", &SpinboxArrowElementSpec, L\"SPIN\",\n\tSPNP_DOWN, spinbutton_statemap, NOPAD,\n\tPAD_MARGINS | ((SM_CXVSCROLL << 8) | SM_CYVSCROLL) },\n    { 0, 0, 0, 0, 0, NOPAD, 0 }\n};\n#undef PAD\n\n\nstatic int\nGetSysFlagFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr)\n{\n    static const char *const names[] = {\n\t\"SM_CXBORDER\", \"SM_CYBORDER\", \"SM_CXVSCROLL\", \"SM_CYVSCROLL\",\n\t\"SM_CXHSCROLL\", \"SM_CYHSCROLL\", \"SM_CXMENUCHECK\", \"SM_CYMENUCHECK\",\n\t\"SM_CXMENUSIZE\", \"SM_CYMENUSIZE\", \"SM_CXSIZE\", \"SM_CYSIZE\", \"SM_CXSMSIZE\",\n\t\"SM_CYSMSIZE\", NULL\n    };\n    int flags[] = {\n\tSM_CXBORDER, SM_CYBORDER, SM_CXVSCROLL, SM_CYVSCROLL,\n\tSM_CXHSCROLL, SM_CYHSCROLL, SM_CXMENUCHECK, SM_CYMENUCHECK,\n\tSM_CXMENUSIZE, SM_CYMENUSIZE, SM_CXSIZE, SM_CYSIZE, SM_CXSMSIZE,\n\tSM_CYSMSIZE\n    };\n\n    Tcl_Obj **objv;\n    Tcl_Size i, objc;\n\n    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    if (objc != 2) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\"wrong # args\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TCL\", \"WRONGARGS\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n    for (i = 0; i < objc; ++i) {\n\tint option;\n\tif (Tcl_GetIndexFromObjStruct(interp, objv[i], names,\n\t\tsizeof(char *), \"system constant\", 0, &option) != TCL_OK)\n\t    return TCL_ERROR;\n\t*resultPtr |= (flags[option] << (8 * (1 - i)));\n    }\n    return TCL_OK;\n}\n\n/*----------------------------------------------------------------------\n * Windows Visual Styles API Element Factory\n *\n * The Vista release has shown that the Windows Visual Styles can be\n * extended with additional elements. This element factory can permit\n * the programmer to create elements for use with script-defined layouts\n *\n * eg: to create the small close button:\n * style element create smallclose vsapi \\\n *    WINDOW 19 {disabled 4 pressed 3 active 2 {} 1}\n */\n\nstatic int\nTtk_CreateVsapiElement(\n    Tcl_Interp *interp,\n    void *clientData,\n    Ttk_Theme theme,\n    const char *elementName,\n    Tcl_Size objc,\n    Tcl_Obj *const objv[])\n{\n    HWND hwnd = (HWND)clientData;\n    ElementInfo *elementPtr = NULL;\n    void *elementData;\n    LPCWSTR className;\n    int partId = 0;\n    Ttk_StateTable *stateTable;\n    Ttk_Padding pad = {0, 0, 0, 0};\n    unsigned flags = 0;\n    Tcl_Size length = 0;\n    char *name;\n    LPWSTR wname;\n    const Ttk_ElementSpec *elementSpec = &GenericElementSpec;\n    Tcl_DString classBuf;\n\n    static const char *const optionStrings[] =\n\t{ \"-halfheight\", \"-halfwidth\", \"-height\", \"-margins\", \"-padding\",\n\t  \"-syssize\", \"-width\", NULL };\n    enum { O_HALFHEIGHT, O_HALFWIDTH, O_HEIGHT, O_MARGINS, O_PADDING,\n\t   O_SYSSIZE, O_WIDTH };\n\n    if (objc < 2) {\n\tTcl_SetObjResult(interp, Tcl_NewStringObj(\n\t    \"missing required arguments 'class' and/or 'partId'\", TCL_INDEX_NONE));\n\tTcl_SetErrorCode(interp, \"TTK\", \"VSAPI\", \"REQUIRED\", (char *)NULL);\n\treturn TCL_ERROR;\n    }\n\n    if (Tcl_GetIntFromObj(interp, objv[1], &partId) != TCL_OK) {\n\treturn TCL_ERROR;\n    }\n    name = Tcl_GetStringFromObj(objv[0], &length);\n    Tcl_DStringInit(&classBuf);\n    className = Tcl_UtfToWCharDString(name, length, &classBuf);\n\n    /* flags or padding */\n    if (objc > 3) {\n\tTcl_Size i = 3;\n\tint option = 0;\n\tfor (i = 3; i < objc; i += 2) {\n\t    int tmp = 0;\n\t    if (i == objc -1) {\n\t\tTcl_SetObjResult(interp, Tcl_ObjPrintf(\n\t\t\t\"Missing value for \\\"%s\\\".\",\n\t\t\tTcl_GetString(objv[i])));\n\t\tTcl_SetErrorCode(interp, \"TTK\", \"VSAPI\", \"MISSING\", (char *)NULL);\n\t\tgoto retErr;\n\t    }\n\t    if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings,\n\t\t    \"option\", 0, &option) != TCL_OK)\n\t\tgoto retErr;\n\t    switch (option) {\n\t    case O_PADDING:\n\t\tif (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tbreak;\n\t    case O_MARGINS:\n\t\tif (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tflags |= PAD_MARGINS;\n\t\tbreak;\n\t    case O_WIDTH:\n\t\tif (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tpad.left = pad.right = (short)tmp;\n\t\tflags |= IGNORE_THEMESIZE;\n\t\tbreak;\n\t    case O_HEIGHT:\n\t\tif (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tpad.top = pad.bottom = (short)tmp;\n\t\tflags |= IGNORE_THEMESIZE;\n\t\tbreak;\n\t    case O_SYSSIZE:\n\t\tif (GetSysFlagFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\telementSpec = &GenericSizedElementSpec;\n\t\tflags |= (tmp & 0xFFFF);\n\t\tbreak;\n\t    case O_HALFHEIGHT:\n\t\tif (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tif (tmp) {\n\t\t    flags |= HALF_HEIGHT;\n\t\t}\n\t\tbreak;\n\t    case O_HALFWIDTH:\n\t\tif (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {\n\t\t    goto retErr;\n\t\t}\n\t\tif (tmp) {\n\t\t    flags |= HALF_WIDTH;\n\t\t}\n\t\tbreak;\n\t    }\n\t}\n    }\n\n    /* convert a statemap into a state table */\n    if (objc > 2) {\n\tTcl_Obj **specs;\n\tTcl_Size n, j, count;\n\tint status = TCL_OK;\n\tif (Tcl_ListObjGetElements(interp, objv[2], &count, &specs) != TCL_OK) {\n\t    goto retErr;\n\t}\n\t/* we over-allocate to ensure there is a terminating entry */\n\tstateTable = (Ttk_StateTable *)Tcl_Alloc(sizeof(Ttk_StateTable) * ((size_t)count + 1));\n\tmemset(stateTable, 0, sizeof(Ttk_StateTable) * ((size_t)count + 1));\n\tfor (n = 0, j = 0; status == TCL_OK && n < count; n += 2, ++j) {\n\t    Ttk_StateSpec spec = {0,0};\n\t    status = Ttk_GetStateSpecFromObj(interp, specs[n], &spec);\n\t    if (status == TCL_OK) {\n\t\tstateTable[j].onBits = spec.onbits;\n\t\tstateTable[j].offBits = spec.offbits;\n\t\tstatus = Tcl_GetIntFromObj(interp, specs[n+1],\n\t\t\t&stateTable[j].index);\n\t    }\n\t}\n\tif (status != TCL_OK) {\n\t    Tcl_Free(stateTable);\n\t    Tcl_DStringFree(&classBuf);\n\t    return status;\n\t}\n    } else {\n\tstateTable = (Ttk_StateTable *)Tcl_Alloc(sizeof(Ttk_StateTable));\n\tmemset(stateTable, 0, sizeof(Ttk_StateTable));\n    }\n\n    elementPtr = (ElementInfo *)Tcl_Alloc(sizeof(ElementInfo));\n    elementPtr->elementSpec = elementSpec;\n    elementPtr->partId = partId;\n    elementPtr->statemap = stateTable;\n    elementPtr->padding = pad;\n    elementPtr->flags = HEAP_ELEMENT | (unsigned)flags;\n\n    /* set the element name to an allocated copy */\n    name = (char *)Tcl_Alloc(strlen(elementName) + 1);\n    strcpy(name, elementName);\n    elementPtr->elementName = name;\n\n    /* set the class name to an allocated copy */\n    wname = (LPWSTR)Tcl_Alloc((size_t)Tcl_DStringLength(&classBuf) + sizeof(WCHAR));\n    wcscpy(wname, className);\n    elementPtr->className = wname;\n\n    elementData = NewElementData(hwnd, elementPtr);\n    Ttk_RegisterElement(NULL,\n\ttheme, elementName, elementPtr->elementSpec, elementData);\n\n    Ttk_RegisterCleanup(interp, elementData, DestroyElementData);\n    Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, TCL_INDEX_NONE));\n    Tcl_DStringFree(&classBuf);\n    return TCL_OK;\n\nretErr:\n    Tcl_DStringFree(&classBuf);\n    return TCL_ERROR;\n}\n\n/*----------------------------------------------------------------------\n * +++ Initialization routine:\n */\n\nMODULE_SCOPE int\nTtkWinVistaTheme_Init(Tcl_Interp *interp, HWND hwnd)\n{\n    Ttk_Theme themePtr, parentPtr;\n    const ElementInfo *infoPtr;\n\n    /*\n     * Create the new style engine.\n     */\n    parentPtr = Ttk_GetTheme(interp, \"winnative\");\n    themePtr = Ttk_CreateTheme(interp, \"vista\", parentPtr);\n\n    if (!themePtr) {\n\treturn TCL_ERROR;\n    }\n\n    /*\n     * Set theme data and cleanup proc\n     */\n\n    Ttk_SetThemeEnabledProc(themePtr, VistaThemeEnabled, hwnd);\n    Ttk_RegisterCleanup(interp, hwnd, VistaThemeDeleteProc);\n    Ttk_RegisterElementFactory(interp, \"vsapi\", Ttk_CreateVsapiElement, hwnd);\n\n    /*\n     * New elements:\n     */\n    for (infoPtr = ElementInfoTable; infoPtr->elementName != 0; ++infoPtr) {\n\tvoid *clientData = NewElementData(hwnd, infoPtr);\n\tTtk_RegisterElement(NULL,\n\t    themePtr, infoPtr->elementName, infoPtr->elementSpec, clientData);\n\tTtk_RegisterCleanup(interp, clientData, DestroyElementData);\n    }\n\n    Ttk_RegisterElement(NULL, themePtr, \"Scale.trough\", &ttkNullElementSpec, 0);\n\n    /*\n     * Layouts:\n     */\n    Ttk_RegisterLayouts(themePtr, LayoutTable);\n\n    Tcl_PkgProvide(interp, \"ttk::theme::vista\", TTK_VERSION);\n\n    return TCL_OK;\n}\n"
  },
  {
    "path": "win/winMain.c",
    "content": "/*\n * winMain.c --\n *\n *\tProvides a default version of the main program and Tcl_AppInit\n *\tprocedure for wish and other Tk-based applications.\n *\n * Copyright © 1993 The Regents of the University of California.\n * Copyright © 1994-1997 Sun Microsystems, Inc.\n * Copyright © 1998-1999 Scriptics Corporation.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n/*\n * Explanation on following undef USE_TCL_STUBS by JN 2023-12-19 on the core list:\n * What's going on is related to TIP #596:\n *  Stubs support for Embedding Tcl in other applications\n *\n * If an application using Tcl_Main() is compiled with USE_TCL_STUBS,\n * Tcl_Main() will be replaced by a stub function, which loads\n * libtcl9.1.so/tcl91.dll and then calls its Tcl_MainEx(). If\n * libtcl9.1.so/tcl91.dll is not present (at runtime), a crash is what happens.\n *\n * So ... tkAppInit.c should not be compiled with USE_TCL_STUBS\n * (unless you want to use the TIP #596 functionality)\n *\n * The proper solution is to make sure that Makefile.in doesn't use\n * TCL_USE_STUBS when compiling tkAppInit.c. But that's a\n * quite big re-organization just before a b1 release. Simpler\n * is just to #undef'ine USE_TCL_STUBS, it has the same effect.\n */\n#undef USE_TCL_STUBS\n#include \"tk.h\"\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#undef WIN32_LEAN_AND_MEAN\n#include <locale.h>\n#include <stdlib.h>\n#include <tchar.h>\n#if (TCL_MAJOR_VERSION < 9)\n#   define Tcl_LibraryInitProc Tcl_PackageInitProc\n#   define Tcl_StaticLibrary Tcl_StaticPackage\n#endif\n\n#if defined(__GNUC__)\nint _CRT_glob = 0;\n#endif /* __GNUC__ */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef TK_TEST\nextern Tcl_LibraryInitProc Tktest_Init;\n#endif /* TK_TEST */\n\n#if !defined(TCL_USE_STATIC_PACKAGES)\n#   if TCL_MAJOR_VERSION > 8\n#\tdefine TCL_USE_STATIC_PACKAGES 1\n#   else\n#\tdefine TCL_USE_STATIC_PACKAGES 0\n#   endif\n#endif\n\n#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES\nextern Tcl_LibraryInitProc Registry_Init;\nextern Tcl_LibraryInitProc Dde_Init;\nextern Tcl_LibraryInitProc Dde_SafeInit;\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n/*\n * Forward declarations for procedures defined later in this file:\n */\n\nstatic BOOL consoleRequired = TRUE;\n\n/*\n * The following #if block allows you to change the AppInit function by using\n * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The\n * #if checks for that #define and uses Tcl_AppInit if it doesn't exist.\n */\n\n#ifndef TK_LOCAL_APPINIT\n#define TK_LOCAL_APPINIT Tcl_AppInit\n#endif\n#ifndef MODULE_SCOPE\n#   ifdef __cplusplus\n#\tdefine MODULE_SCOPE extern \"C\"\n#   else\n#\tdefine MODULE_SCOPE extern\n#   endif\n#endif\nMODULE_SCOPE int TK_LOCAL_APPINIT(Tcl_Interp *interp);\n\n/*\n * The following #if block allows you to change how Tcl finds the startup\n * script, prime the library or encoding paths, fiddle with the argv, etc.,\n * without needing to rewrite Tk_Main()\n */\n\n#ifdef TK_LOCAL_MAIN_HOOK\nMODULE_SCOPE int TK_LOCAL_MAIN_HOOK(int *argc, TCHAR ***argv);\n#endif\n\n/* Make sure the stubbed variants of those are never used. */\n#undef Tcl_ObjSetVar2\n#undef Tcl_NewStringObj\n\f\n/*\n *----------------------------------------------------------------------\n *\n * _tWinMain --\n *\n *\tMain entry point from Windows.\n *\n * Results:\n *\tReturns false if initialization fails, otherwise it never returns.\n *\n * Side effects:\n *\tJust about anything, since from here we call arbitrary Tcl code.\n *\n *----------------------------------------------------------------------\n */\n\nint APIENTRY\n_tWinMain(\n    HINSTANCE hInstance,\n    HINSTANCE hPrevInstance,\n    LPTSTR lpszCmdLine,\n    int nCmdShow)\n{\n    TCHAR **argv;\n    int argc;\n    TCHAR *p;\n    (void)hInstance;\n    (void)hPrevInstance;\n    (void)lpszCmdLine;\n    (void)nCmdShow;\n\n    /*\n     * Create the console channels and install them as the standard channels.\n     * All I/O will be discarded until Tk_CreateConsoleWindow is called to\n     * attach the console to a text widget.\n     */\n\n    consoleRequired = TRUE;\n\n    /*\n     * Get our args from the c-runtime. Ignore lpszCmdLine.\n     */\n\n    argc = __argc;\n    argv = __targv;\n\n    /*\n     * Forward slashes substituted for backslashes.\n     */\n\n    for (p = argv[0]; *p != '\\0'; p++) {\n\tif (*p == '\\\\') {\n\t    *p = '/';\n\t}\n    }\n\n#ifdef TK_LOCAL_MAIN_HOOK\n    TK_LOCAL_MAIN_HOOK(&argc, &argv);\n#elif defined(UNICODE) && (TCL_MAJOR_VERSION > 8)\n    /* This doesn't work on Windows without UNICODE, neither does it work with Tcl 8.6 */\n    TclZipfs_AppHook(&argc, &argv);\n#endif\n\n    Tk_Main(argc, argv, TK_LOCAL_APPINIT);\n    return 0;\t\t\t/* Needed only to prevent compiler warning. */\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * Tcl_AppInit --\n *\n *\tThis procedure performs application-specific initialization. Most\n *\tapplications, especially those that incorporate additional packages,\n *\twill have their own version of this procedure.\n *\n * Results:\n *\tReturns a standard Tcl completion code, and leaves an error message in\n *\tthe interp's result if an error occurs.\n *\n * Side effects:\n *\tDepends on the startup script.\n *\n *----------------------------------------------------------------------\n */\n\nint\nTcl_AppInit(\n    Tcl_Interp *interp)\t\t/* Interpreter for application. */\n{\n    if ((Tcl_Init)(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES\n    if (Registry_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Registry\", Registry_Init, 0);\n\n    if (Dde_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Dde\", Dde_Init, Dde_SafeInit);\n#endif\n    if (Tk_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Tk\", Tk_Init, Tk_SafeInit);\n\n    /*\n     * Initialize the console only if we are running as an interactive\n     * application.\n     */\n\n    if (consoleRequired) {\n\tif (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {\n\t    return TCL_ERROR;\n\t}\n    }\n#ifdef TK_TEST\n    if (Tktest_Init(interp) == TCL_ERROR) {\n\treturn TCL_ERROR;\n    }\n    Tcl_StaticLibrary(interp, \"Tktest\", Tktest_Init, 0);\n#endif /* TK_TEST */\n\n    /*\n     * Call the init procedures for included packages. Each call should look\n     * like this:\n     *\n     * if (Mod_Init(interp) == TCL_ERROR) {\n     *     return TCL_ERROR;\n     * }\n     *\n     * where \"Mod\" is the name of the module. (Dynamically-loadable packages\n     * should have the same entry-point name.)\n     */\n\n    /*\n     * Call Tcl_CreateObjCommand2 for application-specific commands, if they\n     * weren't already created by the init procedures called above.\n     */\n\n    /*\n     * Specify a user-specific startup file to invoke if the application is\n     * run interactively. Typically the startup file is \"~/.apprc\" where \"app\"\n     * is the name of the application. If this line is deleted then no\n     * user-specific startup file will be run under any conditions.\n     */\n\n    (void) Tcl_EvalEx(interp,\n\t    \"set tcl_rcFileName [file tildeexpand ~/wishrc.tcl]\",\n\t    -1, TCL_EVAL_GLOBAL);\n    return TCL_OK;\n}\n\f\n#if defined(TK_TEST)\n/*\n *----------------------------------------------------------------------\n *\n * _tmain --\n *\n *\tMain entry point from the console.\n *\n * Results:\n *\tNone: Tk_Main never returns here, so this procedure never returns\n *\teither.\n *\n * Side effects:\n *\tWhatever the applications does.\n *\n *----------------------------------------------------------------------\n */\n\nint\n_tmain(\n    int argc,\n    TCHAR **argv)\n{\n    /*\n     * Console emulation widget not required as this entry is from the\n     * console subsystem, thus stdin,out,err already have end-points.\n     */\n\n    consoleRequired = FALSE;\n\n#ifdef TK_LOCAL_MAIN_HOOK\n    TK_LOCAL_MAIN_HOOK(&argc, &argv);\n#endif\n\n    Tk_Main(argc, argv, Tcl_AppInit);\n    return 0;\n}\n#endif /* !__GNUC__ || TK_TEST */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "win/wish.exe.manifest.in",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"\n\txmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n    <assemblyIdentity\n\t    version=\"@TK_WIN_VERSION@\"\n\t    processorArchitecture=\"@MACHINE@\"\n\t    name=\"Tcl.Tk.wish\"\n\t    type=\"win32\"\n\t/>\n    <description>Tcl/Tk windowing shell (wish)</description>\n    <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\t<security>\n\t    <requestedPrivileges>\n\t\t<requestedExecutionLevel\n\t\t\tlevel=\"asInvoker\"\n\t\t\tuiAccess=\"false\"\n\t\t    />\n\t    </requestedPrivileges>\n\t</security>\n    </trustInfo>\n    <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n\t<application>\n\t    <!-- Windows 10 -->\n\t    <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\t    <!-- Windows 8.1 -->\n\t    <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\"/>\n\t    <!-- Windows 8 -->\n\t    <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\"/>\n\t    <!-- Windows 7 -->\n\t    <supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\"/>\n\t</application>\n    </compatibility>\n    <asmv3:application>\n\t<asmv3:windowsSettings>\n\t    <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true</dpiAware>\n\t    <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n\t    <longPathAware xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">true</longPathAware>\n\t</asmv3:windowsSettings>\n    </asmv3:application>\n    <dependency>\n\t<dependentAssembly>\n\t    <assemblyIdentity\n\t\t    type=\"win32\"\n\t\t    name=\"Microsoft.Windows.Common-Controls\"\n\t\t    version=\"6.0.0.0\"\n\t\t    processorArchitecture=\"@MACHINE@\"\n\t\t    publicKeyToken=\"6595b64144ccf1df\"\n\t\t    language=\"*\"\n\t\t/>\n\t</dependentAssembly>\n    </dependency>\n</assembly>\n"
  },
  {
    "path": "xlib/X11/DECkeysym.h",
    "content": "/***********************************************************\n\nCopyright 1988, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n\nCopyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n/*\n * DEC private keysyms\n * (29th bit set)\n */\n\n/* two-key compose sequence initiators, chosen to map to Latin1 characters */\n\n#define DXK_ring_accent              0x1000feb0\n#define DXK_circumflex_accent        0x1000fe5e\n#define DXK_cedilla_accent           0x1000fe2c\n#define DXK_acute_accent             0x1000fe27\n#define DXK_grave_accent             0x1000fe60\n#define DXK_tilde                    0x1000fe7e\n#define DXK_diaeresis                0x1000fe22\n\n/* special keysym for LK2** \"Remove\" key on editing keypad */\n\n#define DXK_Remove                   0x1000ff00  /* Remove */\n"
  },
  {
    "path": "xlib/X11/HPkeysym.h",
    "content": "/*\n\nCopyright 1987, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall\nnot be used in advertising or otherwise to promote the sale, use or\nother dealings in this Software without prior written authorization\nfrom The Open Group.\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the names of Hewlett Packard\nor Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\nHEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD\nTO THIS SOFTWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  Hewlett-Packard shall not be liable for errors\ncontained herein or direct, indirect, special, incidental or\nconsequential damages in connection with the furnishing,\nperformance, or use of this material.\n\n*/\n\n#ifndef _HPKEYSYM_H\n\n#define _HPKEYSYM_H\n\n#define hpXK_ClearLine               0x1000ff6f\n#define hpXK_InsertLine              0x1000ff70\n#define hpXK_DeleteLine              0x1000ff71\n#define hpXK_InsertChar              0x1000ff72\n#define hpXK_DeleteChar              0x1000ff73\n#define hpXK_BackTab                 0x1000ff74\n#define hpXK_KP_BackTab              0x1000ff75\n#define hpXK_Modelock1               0x1000ff48\n#define hpXK_Modelock2               0x1000ff49\n#define hpXK_Reset                   0x1000ff6c\n#define hpXK_System                  0x1000ff6d\n#define hpXK_User                    0x1000ff6e\n#define hpXK_mute_acute              0x100000a8\n#define hpXK_mute_grave              0x100000a9\n#define hpXK_mute_asciicircum        0x100000aa\n#define hpXK_mute_diaeresis          0x100000ab\n#define hpXK_mute_asciitilde         0x100000ac\n#define hpXK_lira                    0x100000af\n#define hpXK_guilder                 0x100000be\n#define hpXK_Ydiaeresis              0x100000ee\n#define hpXK_IO                      0x100000ee  /* deprecated alias for hpYdiaeresis */\n#define hpXK_longminus               0x100000f6\n#define hpXK_block                   0x100000fc\n\n\n#ifndef _OSF_Keysyms\n#define _OSF_Keysyms\n\n#define osfXK_Copy                   0x1004ff02\n#define osfXK_Cut                    0x1004ff03\n#define osfXK_Paste                  0x1004ff04\n#define osfXK_BackTab                0x1004ff07\n#define osfXK_BackSpace              0x1004ff08\n#define osfXK_Clear                  0x1004ff0b\n#define osfXK_Escape                 0x1004ff1b\n#define osfXK_AddMode                0x1004ff31\n#define osfXK_PrimaryPaste           0x1004ff32\n#define osfXK_QuickPaste             0x1004ff33\n#define osfXK_PageLeft               0x1004ff40\n#define osfXK_PageUp                 0x1004ff41\n#define osfXK_PageDown               0x1004ff42\n#define osfXK_PageRight              0x1004ff43\n#define osfXK_Activate               0x1004ff44\n#define osfXK_MenuBar                0x1004ff45\n#define osfXK_Left                   0x1004ff51\n#define osfXK_Up                     0x1004ff52\n#define osfXK_Right                  0x1004ff53\n#define osfXK_Down                   0x1004ff54\n#define osfXK_EndLine                0x1004ff57\n#define osfXK_BeginLine              0x1004ff58\n#define osfXK_EndData                0x1004ff59\n#define osfXK_BeginData              0x1004ff5a\n#define osfXK_PrevMenu               0x1004ff5b\n#define osfXK_NextMenu               0x1004ff5c\n#define osfXK_PrevField              0x1004ff5d\n#define osfXK_NextField              0x1004ff5e\n#define osfXK_Select                 0x1004ff60\n#define osfXK_Insert                 0x1004ff63\n#define osfXK_Undo                   0x1004ff65\n#define osfXK_Menu                   0x1004ff67\n#define osfXK_Cancel                 0x1004ff69\n#define osfXK_Help                   0x1004ff6a\n#define osfXK_SelectAll              0x1004ff71\n#define osfXK_DeselectAll            0x1004ff72\n#define osfXK_Reselect               0x1004ff73\n#define osfXK_Extend                 0x1004ff74\n#define osfXK_Restore                0x1004ff78\n#define osfXK_Delete                 0x1004ffff\n\n#endif /* _OSF_Keysyms */\n\n\n/**************************************************************\n * The use of the following macros is deprecated.\n * They are listed below only for backwards compatibility.\n */\n#define XK_Reset                     0x1000ff6c  /* deprecated alias for hpReset */\n#define XK_System                    0x1000ff6d  /* deprecated alias for hpSystem */\n#define XK_User                      0x1000ff6e  /* deprecated alias for hpUser */\n#define XK_ClearLine                 0x1000ff6f  /* deprecated alias for hpClearLine */\n#define XK_InsertLine                0x1000ff70  /* deprecated alias for hpInsertLine */\n#define XK_DeleteLine                0x1000ff71  /* deprecated alias for hpDeleteLine */\n#define XK_InsertChar                0x1000ff72  /* deprecated alias for hpInsertChar */\n#define XK_DeleteChar                0x1000ff73  /* deprecated alias for hpDeleteChar */\n#define XK_BackTab                   0x1000ff74  /* deprecated alias for hpBackTab */\n#define XK_KP_BackTab                0x1000ff75  /* deprecated alias for hpKP_BackTab */\n#define XK_Ext16bit_L                0x1000ff76  /* deprecated */\n#define XK_Ext16bit_R                0x1000ff77  /* deprecated */\n#define XK_mute_acute                0x100000a8  /* deprecated alias for hpmute_acute */\n#define XK_mute_grave                0x100000a9  /* deprecated alias for hpmute_grave */\n#define XK_mute_asciicircum          0x100000aa  /* deprecated alias for hpmute_asciicircum */\n#define XK_mute_diaeresis            0x100000ab  /* deprecated alias for hpmute_diaeresis */\n#define XK_mute_asciitilde           0x100000ac  /* deprecated alias for hpmute_asciitilde */\n#define XK_lira                      0x100000af  /* deprecated alias for hplira */\n#define XK_guilder                   0x100000be  /* deprecated alias for hpguilder */\n#ifndef XK_Ydiaeresis\n#define XK_Ydiaeresis                0x100000ee  /* deprecated */\n#endif\n#define XK_IO                        0x100000ee  /* deprecated alias for hpYdiaeresis */\n#define XK_longminus                 0x100000f6  /* deprecated alias for hplongminus */\n#define XK_block                     0x100000fc  /* deprecated alias for hpblock */\n\n#endif /* _HPKEYSYM_H */\n"
  },
  {
    "path": "xlib/X11/Sunkeysym.h",
    "content": "/*\n * Copyright (c) 1991, Oracle and/or its affiliates.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n/************************************************************\n\nCopyright 1991, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n***********************************************************/\n\n/*\n * Floating Accent\n */\n\n#define SunXK_FA_Grave               0x1005ff00\n#define SunXK_FA_Circum              0x1005ff01\n#define SunXK_FA_Tilde               0x1005ff02\n#define SunXK_FA_Acute               0x1005ff03\n#define SunXK_FA_Diaeresis           0x1005ff04\n#define SunXK_FA_Cedilla             0x1005ff05\n\n/*\n * Miscellaneous Functions\n */\n\n#define SunXK_F36                    0x1005ff10  /* Labeled F11 */\n#define SunXK_F37                    0x1005ff11  /* Labeled F12 */\n\n#define SunXK_Sys_Req                0x1005ff60\n#define SunXK_Print_Screen           0x0000ff61  /* Same as XK_Print */\n\n/*\n * International & Multi-Key Character Composition\n */\n\n#define SunXK_Compose                0x0000ff20  /* Same as XK_Multi_key */\n#define SunXK_AltGraph               0x0000ff7e  /* Same as XK_Mode_switch */\n\n/*\n * Cursor Control\n */\n\n#define SunXK_PageUp                 0x0000ff55  /* Same as XK_Prior */\n#define SunXK_PageDown               0x0000ff56  /* Same as XK_Next */\n\n/*\n * Open Look Functions\n */\n\n#define SunXK_Undo                   0x0000ff65  /* Same as XK_Undo */\n#define SunXK_Again                  0x0000ff66  /* Same as XK_Redo */\n#define SunXK_Find                   0x0000ff68  /* Same as XK_Find */\n#define SunXK_Stop                   0x0000ff69  /* Same as XK_Cancel */\n#define SunXK_Props                  0x1005ff70\n#define SunXK_Front                  0x1005ff71\n#define SunXK_Copy                   0x1005ff72\n#define SunXK_Open                   0x1005ff73\n#define SunXK_Paste                  0x1005ff74\n#define SunXK_Cut                    0x1005ff75\n\n#define SunXK_PowerSwitch            0x1005ff76\n#define SunXK_AudioLowerVolume       0x1005ff77\n#define SunXK_AudioMute              0x1005ff78\n#define SunXK_AudioRaiseVolume       0x1005ff79\n#define SunXK_VideoDegauss           0x1005ff7a\n#define SunXK_VideoLowerBrightness   0x1005ff7b\n#define SunXK_VideoRaiseBrightness   0x1005ff7c\n#define SunXK_PowerSwitchShift       0x1005ff7d\n"
  },
  {
    "path": "xlib/X11/X.h",
    "content": "/* Definitions for the X window system likely to be used by applications */\n\n#ifndef X_H\n#define X_H\n\n/***********************************************************\n\nCopyright 1987, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n#define X_PROTOCOL\t11\t\t/* current protocol version */\n#define X_PROTOCOL_REVISION 0\t\t/* current minor version */\n\n/* Resources */\n\n/*\n * _XSERVER64 must ONLY be defined when compiling X server sources on\n * systems where unsigned long is not 32 bits, must NOT be used in\n * client or library code.\n */\n#ifndef _XSERVER64\n#  ifndef _XTYPEDEF_XID\n#    define _XTYPEDEF_XID\n#    ifdef _WIN64\ntypedef unsigned long long XID;\n#    else\ntypedef unsigned long XID;\n#    endif\n#  endif\n#  ifndef _XTYPEDEF_MASK\n#    define _XTYPEDEF_MASK\ntypedef unsigned long Mask;\n#  endif\n#  ifndef _XTYPEDEF_ATOM\n#    define _XTYPEDEF_ATOM\ntypedef unsigned long Atom;\t\t/* Also in Xdefs.h */\n#  endif\ntypedef unsigned long VisualID;\ntypedef unsigned long Time;\n#else\n#  include <X11/Xmd.h>\n#  ifndef _XTYPEDEF_XID\n#    define _XTYPEDEF_XID\ntypedef CARD32 XID;\n#  endif\n#  ifndef _XTYPEDEF_MASK\n#    define _XTYPEDEF_MASK\ntypedef CARD32 Mask;\n#  endif\n#  ifndef _XTYPEDEF_ATOM\n#    define _XTYPEDEF_ATOM\ntypedef CARD32 Atom;\n#  endif\ntypedef CARD32 VisualID;\ntypedef CARD32 Time;\n#endif\n\ntypedef XID Window;\ntypedef XID Drawable;\n#ifndef _XTYPEDEF_FONT\n#  define _XTYPEDEF_FONT\ntypedef XID Font;\n#endif\ntypedef XID Pixmap;\ntypedef XID Cursor;\ntypedef XID Colormap;\ntypedef XID GContext;\ntypedef XID KeySym;\n\ntypedef unsigned int KeyCode;\t/* In order to use IME, the Macintosh needs\n\t\t\t\t * to pack 3 bytes into the keyCode field in\n\t\t\t\t * the XEvent.  In the real X.h, a KeyCode is\n\t\t\t\t * defined as an unsigned char, which wouldn't\n\t\t\t\t * be big enough. */\n\n/*****************************************************************\n * RESERVED RESOURCE AND CONSTANT DEFINITIONS\n *****************************************************************/\n\n#ifndef None\n/* Perl-Tk expects None to be a macro. See ticket [593eb0227c] */\n#define None                 None /* See bug [9e31fd9449] and below */\n#endif\n\n#define ParentRelative       1L\t/* background pixmap in CreateWindow\n\t\t\t\t    and ChangeWindowAttributes */\n\n#define CopyFromParent       0L\t/* border pixmap in CreateWindow\n\t\t\t\t       and ChangeWindowAttributes\n\t\t\t\t   special VisualID and special window\n\t\t\t\t       class passed to CreateWindow */\n\n#define PointerWindow        0L\t/* destination window in SendEvent */\n#define InputFocus           1L\t/* destination window in SendEvent */\n\n#define PointerRoot          1L\t/* focus window in SetInputFocus */\n\n#define AnyPropertyType      0L\t/* special Atom, passed to GetProperty */\n\n#define AnyKey\t\t     0L\t/* special Key Code, passed to GrabKey */\n\n#define AnyButton            0L\t/* special Button Code, passed to GrabButton */\n\n#define AllTemporary         0L\t/* special Resource ID passed to KillClient */\n\n#define CurrentTime          0L\t/* special Time */\n\n#define NoSymbol\t     0L\t/* special KeySym */\n\n/*****************************************************************\n * EVENT DEFINITIONS\n *****************************************************************/\n\n/* Input Event Masks. Used as event-mask window attribute and as arguments\n   to Grab requests.  Not to be confused with event names.  */\n\n#define NoEventMask\t\t\t0L\n#define KeyPressMask\t\t\t(1L<<0)\n#define KeyReleaseMask\t\t\t(1L<<1)\n#define ButtonPressMask\t\t\t(1L<<2)\n#define ButtonReleaseMask\t\t(1L<<3)\n#define EnterWindowMask\t\t\t(1L<<4)\n#define LeaveWindowMask\t\t\t(1L<<5)\n#define PointerMotionMask\t\t(1L<<6)\n#define PointerMotionHintMask\t\t(1L<<7)\n#define Button1MotionMask\t\t(1L<<8)\n#define Button2MotionMask\t\t(1L<<9)\n#define Button3MotionMask\t\t(1L<<10)\n#define Button4MotionMask\t\t(1L<<11)\n#define Button5MotionMask\t\t(1L<<12)\n#define ButtonMotionMask\t\t(1L<<13)\n#define KeymapStateMask\t\t\t(1L<<14)\n#define ExposureMask\t\t\t(1L<<15)\n#define VisibilityChangeMask\t\t(1L<<16)\n#define StructureNotifyMask\t\t(1L<<17)\n#define ResizeRedirectMask\t\t(1L<<18)\n#define SubstructureNotifyMask\t\t(1L<<19)\n#define SubstructureRedirectMask\t(1L<<20)\n#define FocusChangeMask\t\t\t(1L<<21)\n#define PropertyChangeMask\t\t(1L<<22)\n#define ColormapChangeMask\t\t(1L<<23)\n#define OwnerGrabButtonMask\t\t(1L<<24)\n\n/* Event names.  Used in \"type\" field in XEvent structures.  Not to be\nconfused with event masks above.  They start from 2 because 0 and 1\nare reserved in the protocol for errors and replies. */\n\n#define KeyPress\t\t2\n#define KeyRelease\t\t3\n#define ButtonPress\t\t4\n#define ButtonRelease\t\t5\n#define MotionNotify\t\t6\n#define EnterNotify\t\t7\n#define LeaveNotify\t\t8\n#define FocusIn\t\t\t9\n#define FocusOut\t\t10\n#define KeymapNotify\t\t11\n#define Expose\t\t\t12\n#define GraphicsExpose\t\t13\n#define NoExpose\t\t14\n#define VisibilityNotify\t15\n#define CreateNotify\t\t16\n#define DestroyNotify\t\t17\n#define UnmapNotify\t\t18\n#define MapNotify\t\t19\n#define MapRequest\t\t20\n#define ReparentNotify\t\t21\n#define ConfigureNotify\t\t22\n#define ConfigureRequest\t23\n#define GravityNotify\t\t24\n#define ResizeRequest\t\t25\n#define CirculateNotify\t\t26\n#define CirculateRequest\t27\n#define PropertyNotify\t\t28\n#define SelectionClear\t\t29\n#define SelectionRequest\t30\n#define SelectionNotify\t\t31\n#define ColormapNotify\t\t32\n#define ClientMessage\t\t33\n#define MappingNotify\t\t34\n#define GenericEvent\t\t35\n#define LASTEvent\t\t36\t/* must be bigger than any event # */\n\n\n/* Key masks. Used as modifiers to GrabButton and GrabKey, results of QueryPointer,\n   state in various key-, mouse-, and button-related events. */\n\n#define ShiftMask\t\t(1<<0)\n#define LockMask\t\t(1<<1)\n/* Perl-Tk expects ControlMask to be a macro. See ticket [593eb0227c] */\n#define ControlMask\t\tControlMask /* See bug [9e31fd9449] and below */\n#define Mod1Mask\t\t(1<<3)\n#define Mod2Mask\t\t(1<<4)\n#define Mod3Mask\t\t(1<<5)\n#define Mod4Mask\t\t(1<<6)\n#define Mod5Mask\t\t(1<<7)\n\n/* See bug [9e31fd9449], this way prevents conflicts with Win32 headers */\nenum { None = 0, ControlMask = (1<<2) };\n\n/* modifier names.  Used to build a SetModifierMapping request or\n   to read a GetModifierMapping request.  These correspond to the\n   masks defined above. */\n#define ShiftMapIndex\t\t0\n#define LockMapIndex\t\t1\n#define ControlMapIndex\t\t2\n#define Mod1MapIndex\t\t3\n#define Mod2MapIndex\t\t4\n#define Mod3MapIndex\t\t5\n#define Mod4MapIndex\t\t6\n#define Mod5MapIndex\t\t7\n\n\n/* button masks.  Used in same manner as Key masks above. Not to be confused\n   with button names below. */\n\n#define Button1Mask\t\t(1<<8)\n#define Button2Mask\t\t(1<<9)\n#define Button3Mask\t\t(1<<10)\n#define Button4Mask\t\t(1<<11)\n#define Button5Mask\t\t(1<<12)\n\n#define AnyModifier\t\t(1<<15)  /* used in GrabButton, GrabKey */\n\n\n/* button names. Used as arguments to GrabButton and as detail in ButtonPress\n   and ButtonRelease events.  Not to be confused with button masks above.\n   Note that 0 is already defined above as \"AnyButton\".  */\n\n#define Button1\t\t\t1\n#define Button2\t\t\t2\n#define Button3\t\t\t3\n#define Button4\t\t\t4\n#define Button5\t\t\t5\n\n/* Notify modes */\n\n#define NotifyNormal\t\t0\n#define NotifyGrab\t\t1\n#define NotifyUngrab\t\t2\n#define NotifyWhileGrabbed\t3\n\n#define NotifyHint\t\t1\t/* for MotionNotify events */\n\n/* Notify detail */\n\n#define NotifyAncestor\t\t0\n#define NotifyVirtual\t\t1\n#define NotifyInferior\t\t2\n#define NotifyNonlinear\t\t3\n#define NotifyNonlinearVirtual\t4\n#define NotifyPointer\t\t5\n#define NotifyPointerRoot\t6\n#define NotifyDetailNone\t7\n\n/* Visibility notify */\n\n#define VisibilityUnobscured\t\t0\n#define VisibilityPartiallyObscured\t1\n#define VisibilityFullyObscured\t\t2\n\n/* Circulation request */\n\n#define PlaceOnTop\t\t0\n#define PlaceOnBottom\t\t1\n\n/* protocol families */\n\n#define FamilyInternet\t\t0\t/* IPv4 */\n#define FamilyDECnet\t\t1\n#define FamilyChaos\t\t2\n#define FamilyInternet6\t\t6\t/* IPv6 */\n\n/* authentication families not tied to a specific protocol */\n#define FamilyServerInterpreted 5\n\n/* Property notification */\n\n#define PropertyNewValue\t0\n#define PropertyDelete\t\t1\n\n/* Color Map notification */\n\n#define ColormapUninstalled\t0\n#define ColormapInstalled\t1\n\n/* GrabPointer, GrabButton, GrabKeyboard, GrabKey Modes */\n\n#define GrabModeSync\t\t0\n#define GrabModeAsync\t\t1\n\n/* GrabPointer, GrabKeyboard reply status */\n\n#define GrabSuccess\t\t0\n#define AlreadyGrabbed\t\t1\n#define GrabInvalidTime\t\t2\n#define GrabNotViewable\t\t3\n#define GrabFrozen\t\t4\n\n/* AllowEvents modes */\n\n#define AsyncPointer\t\t0\n#define SyncPointer\t\t1\n#define ReplayPointer\t\t2\n#define AsyncKeyboard\t\t3\n#define SyncKeyboard\t\t4\n#define ReplayKeyboard\t\t5\n#define AsyncBoth\t\t6\n#define SyncBoth\t\t7\n\n/* Used in SetInputFocus, GetInputFocus */\n\n#define RevertToNone\t\t(int)None\n#define RevertToPointerRoot\t(int)PointerRoot\n#define RevertToParent\t\t2\n\n/*****************************************************************\n * ERROR CODES\n *****************************************************************/\n\n#define Success\t\t   0\t/* everything's okay */\n#define BadRequest\t   1\t/* bad request code */\n#define BadValue\t   2\t/* int parameter out of range */\n#define BadWindow\t   3\t/* parameter not a Window */\n#define BadPixmap\t   4\t/* parameter not a Pixmap */\n#define BadAtom\t\t   5\t/* parameter not an Atom */\n#define BadCursor\t   6\t/* parameter not a Cursor */\n#define BadFont\t\t   7\t/* parameter not a Font */\n#define BadMatch\t   8\t/* parameter mismatch */\n#define BadDrawable\t   9\t/* parameter not a Pixmap or Window */\n#define BadAccess\t  10\t/* depending on context:\n\t\t\t\t - key/button already grabbed\n\t\t\t\t - attempt to free an illegal\n\t\t\t\t   cmap entry\n\t\t\t\t- attempt to store into a read-only\n\t\t\t\t   color map entry.\n \t\t\t\t- attempt to modify the access control\n\t\t\t\t   list from other than the local host.\n\t\t\t\t*/\n#define BadAlloc\t  11\t/* insufficient resources */\n#define BadColor\t  12\t/* no such colormap */\n#define BadGC\t\t  13\t/* parameter not a GC */\n#define BadIDChoice\t  14\t/* choice not in range or already used */\n#define BadName\t\t  15\t/* font or color name doesn't exist */\n#define BadLength\t  16\t/* Request length incorrect */\n#define BadImplementation 17\t/* server is defective */\n\n#define FirstExtensionError\t128\n#define LastExtensionError\t255\n\n/*****************************************************************\n * WINDOW DEFINITIONS\n *****************************************************************/\n\n/* Window classes used by CreateWindow */\n/* Note that CopyFromParent is already defined as 0 above */\n\n#define InputOutput\t\t1\n#define InputOnly\t\t2\n\n/* Window attributes for CreateWindow and ChangeWindowAttributes */\n\n#define CWBackPixmap\t\t(1L<<0)\n#define CWBackPixel\t\t(1L<<1)\n#define CWBorderPixmap\t\t(1L<<2)\n#define CWBorderPixel           (1L<<3)\n#define CWBitGravity\t\t(1L<<4)\n#define CWWinGravity\t\t(1L<<5)\n#define CWBackingStore          (1L<<6)\n#define CWBackingPlanes\t        (1L<<7)\n#define CWBackingPixel\t        (1L<<8)\n#define CWOverrideRedirect\t(1L<<9)\n#define CWSaveUnder\t\t(1L<<10)\n#define CWEventMask\t\t(1L<<11)\n#define CWDontPropagate\t        (1L<<12)\n#define CWColormap\t\t(1L<<13)\n#define CWCursor\t        (1L<<14)\n\n/* ConfigureWindow structure */\n\n#define CWX\t\t\t(1<<0)\n#define CWY\t\t\t(1<<1)\n#define CWWidth\t\t\t(1<<2)\n#define CWHeight\t\t(1<<3)\n#define CWBorderWidth\t\t(1<<4)\n#define CWSibling\t\t(1<<5)\n#define CWStackMode\t\t(1<<6)\n\n\n/* Bit Gravity */\n\n#define ForgetGravity\t\t0\n#define NorthWestGravity\t1\n#define NorthGravity\t\t2\n#define NorthEastGravity\t3\n#define WestGravity\t\t4\n#define CenterGravity\t\t5\n#define EastGravity\t\t6\n#define SouthWestGravity\t7\n#define SouthGravity\t\t8\n#define SouthEastGravity\t9\n#define StaticGravity\t\t10\n\n/* Window gravity + bit gravity above */\n\n#define UnmapGravity\t\t0\n\n/* Used in CreateWindow for backing-store hint */\n\n#define NotUseful               0\n#define WhenMapped              1\n#define Always                  2\n\n/* Used in GetWindowAttributes reply */\n\n#define IsUnmapped\t\t0\n#define IsUnviewable\t\t1\n#define IsViewable\t\t2\n\n/* Used in ChangeSaveSet */\n\n#define SetModeInsert           0\n#define SetModeDelete           1\n\n/* Used in ChangeCloseDownMode */\n\n#define DestroyAll              0\n#define RetainPermanent         1\n#define RetainTemporary         2\n\n/* Window stacking method (in configureWindow) */\n\n#define Above                   0\n#define Below                   1\n#define TopIf                   2\n#define BottomIf                3\n#define Opposite                4\n\n/* Circulation direction */\n\n#define RaiseLowest             0\n#define LowerHighest            1\n\n/* Property modes */\n\n#define PropModeReplace         0\n#define PropModePrepend         1\n#define PropModeAppend          2\n\n/*****************************************************************\n * GRAPHICS DEFINITIONS\n *****************************************************************/\n\n/* graphics functions, as in GC.alu */\n\n#define\tGXclear\t\t\t0x0\t\t/* 0 */\n#define GXand\t\t\t0x1\t\t/* src AND dst */\n#define GXandReverse\t\t0x2\t\t/* src AND NOT dst */\n#define GXcopy\t\t\t0x3\t\t/* src */\n#define GXandInverted\t\t0x4\t\t/* NOT src AND dst */\n#define\tGXnoop\t\t\t0x5\t\t/* dst */\n#define GXxor\t\t\t0x6\t\t/* src XOR dst */\n#define GXor\t\t\t0x7\t\t/* src OR dst */\n#define GXnor\t\t\t0x8\t\t/* NOT src AND NOT dst */\n#define GXequiv\t\t\t0x9\t\t/* NOT src XOR dst */\n#define GXinvert\t\t0xa\t\t/* NOT dst */\n#define GXorReverse\t\t0xb\t\t/* src OR NOT dst */\n#define GXcopyInverted\t\t0xc\t\t/* NOT src */\n#define GXorInverted\t\t0xd\t\t/* NOT src OR dst */\n#define GXnand\t\t\t0xe\t\t/* NOT src OR NOT dst */\n#define GXset\t\t\t0xf\t\t/* 1 */\n\n/* LineStyle */\n\n#define LineSolid\t\t0\n#define LineOnOffDash\t\t1\n#define LineDoubleDash\t\t2\n\n/* capStyle */\n\n#define CapNotLast\t\t0\n#define CapButt\t\t\t1\n#define CapRound\t\t2\n#define CapProjecting\t\t3\n\n/* joinStyle */\n\n#define JoinMiter\t\t0\n#define JoinRound\t\t1\n#define JoinBevel\t\t2\n\n/* fillStyle */\n\n#define FillSolid\t\t0\n#define FillTiled\t\t1\n#define FillStippled\t\t2\n#define FillOpaqueStippled\t3\n\n/* fillRule */\n\n#define EvenOddRule\t\t0\n#define WindingRule\t\t1\n\n/* subwindow mode */\n\n#define ClipByChildren\t\t0\n#define IncludeInferiors\t1\n\n/* SetClipRectangles ordering */\n\n#define Unsorted\t\t0\n#define YSorted\t\t\t1\n#define YXSorted\t\t2\n#define YXBanded\t\t3\n\n/* CoordinateMode for drawing routines */\n\n#define CoordModeOrigin\t\t0\t/* relative to the origin */\n#define CoordModePrevious       1\t/* relative to previous point */\n\n/* Polygon shapes */\n\n#define Complex\t\t\t0\t/* paths may intersect */\n#define Nonconvex\t\t1\t/* no paths intersect, but not convex */\n#define Convex\t\t\t2\t/* wholly convex */\n\n/* Arc modes for PolyFillArc */\n\n#define ArcChord\t\t0\t/* join endpoints of arc */\n#define ArcPieSlice\t\t1\t/* join endpoints to center of arc */\n\n/* GC components: masks used in CreateGC, CopyGC, ChangeGC, OR'ed into\n   GC.stateChanges */\n\n#define GCFunction              (1L<<0)\n#define GCPlaneMask             (1L<<1)\n#define GCForeground            (1L<<2)\n#define GCBackground            (1L<<3)\n#define GCLineWidth             (1L<<4)\n#define GCLineStyle             (1L<<5)\n#define GCCapStyle              (1L<<6)\n#define GCJoinStyle\t\t(1L<<7)\n#define GCFillStyle\t\t(1L<<8)\n#define GCFillRule\t\t(1L<<9)\n#define GCTile\t\t\t(1L<<10)\n#define GCStipple\t\t(1L<<11)\n#define GCTileStipXOrigin\t(1L<<12)\n#define GCTileStipYOrigin\t(1L<<13)\n#define GCFont \t\t\t(1L<<14)\n#define GCSubwindowMode\t\t(1L<<15)\n#define GCGraphicsExposures     (1L<<16)\n#define GCClipXOrigin\t\t(1L<<17)\n#define GCClipYOrigin\t\t(1L<<18)\n#define GCClipMask\t\t(1L<<19)\n#define GCDashOffset\t\t(1L<<20)\n#define GCDashList\t\t(1L<<21)\n#define GCArcMode\t\t(1L<<22)\n\n#define GCLastBit\t\t22\n/*****************************************************************\n * FONTS\n *****************************************************************/\n\n/* used in QueryFont -- draw direction */\n\n#define FontLeftToRight\t\t0\n#define FontRightToLeft\t\t1\n\n#define FontChange\t\t255\n\n/*****************************************************************\n *  IMAGING\n *****************************************************************/\n\n/* ImageFormat -- PutImage, GetImage */\n\n#define XYBitmap\t\t0\t/* depth 1, XYFormat */\n#define XYPixmap\t\t1\t/* depth == drawable depth */\n#define ZPixmap\t\t\t2\t/* depth == drawable depth */\n\n/*****************************************************************\n *  COLOR MAP STUFF\n *****************************************************************/\n\n/* For CreateColormap */\n\n#define AllocNone\t\t0\t/* create map with no entries */\n#define AllocAll\t\t1\t/* allocate entire map writeable */\n\n\n/* Flags used in StoreNamedColor, StoreColors */\n\n#define DoRed\t\t\t(1<<0)\n#define DoGreen\t\t\t(1<<1)\n#define DoBlue\t\t\t(1<<2)\n\n/*****************************************************************\n * CURSOR STUFF\n *****************************************************************/\n\n/* QueryBestSize Class */\n\n#define CursorShape\t\t0\t/* largest size that can be displayed */\n#define TileShape\t\t1\t/* size tiled fastest */\n#define StippleShape\t\t2\t/* size stippled fastest */\n\n/*****************************************************************\n * KEYBOARD/POINTER STUFF\n *****************************************************************/\n\n#define AutoRepeatModeOff\t0\n#define AutoRepeatModeOn\t1\n#define AutoRepeatModeDefault\t2\n\n#define LedModeOff\t\t0\n#define LedModeOn\t\t1\n\n/* masks for ChangeKeyboardControl */\n\n#define KBKeyClickPercent\t(1L<<0)\n#define KBBellPercent\t\t(1L<<1)\n#define KBBellPitch\t\t(1L<<2)\n#define KBBellDuration\t\t(1L<<3)\n#define KBLed\t\t\t(1L<<4)\n#define KBLedMode\t\t(1L<<5)\n#define KBKey\t\t\t(1L<<6)\n#define KBAutoRepeatMode\t(1L<<7)\n\n#define MappingSuccess     \t0\n#define MappingBusy        \t1\n#define MappingFailed\t\t2\n\n#define MappingModifier\t\t0\n#define MappingKeyboard\t\t1\n#define MappingPointer\t\t2\n\n/*****************************************************************\n * SCREEN SAVER STUFF\n *****************************************************************/\n\n#define DontPreferBlanking\t0\n#define PreferBlanking\t\t1\n#define DefaultBlanking\t\t2\n\n#define DisableScreenSaver\t0\n#define DisableScreenInterval\t0\n\n#define DontAllowExposures\t0\n#define AllowExposures\t\t1\n#define DefaultExposures\t2\n\n/* for ForceScreenSaver */\n\n#define ScreenSaverReset 0\n#define ScreenSaverActive 1\n\n/*****************************************************************\n * HOSTS AND CONNECTIONS\n *****************************************************************/\n\n/* for ChangeHosts */\n\n#define HostInsert\t\t0\n#define HostDelete\t\t1\n\n/* for ChangeAccessControl */\n\n#define EnableAccess\t\t1\n#define DisableAccess\t\t0\n\n/* Display classes  used in opening the connection\n * Note that the statically allocated ones are even numbered and the\n * dynamically changeable ones are odd numbered */\n\n#define StaticGray\t\t0\n#define GrayScale\t\t1\n#define StaticColor\t\t2\n#define PseudoColor\t\t3\n#define TrueColor\t\t4\n#define DirectColor\t\t5\n\n\n/* Byte order  used in imageByteOrder and bitmapBitOrder */\n\n#define LSBFirst\t\t0\n#define MSBFirst\t\t1\n\n#endif /* X_H */\n"
  },
  {
    "path": "xlib/X11/XF86keysym.h",
    "content": "/*\n * XFree86 vendor specific keysyms.\n *\n * The XFree86 keysym range is 0x10080001 - 0x1008ffff.\n *\n * The XF86 set of keysyms is a catch-all set of defines for keysyms found\n * on various multimedia keyboards. Originally specific to XFree86 they have\n * been been adopted over time and are considered a \"standard\" part of X\n * keysym definitions.\n * XFree86 never properly commented these keysyms, so we have done our\n * best to explain the semantic meaning of these keys.\n *\n * XFree86 has removed their mail archives of the period, that might have\n * shed more light on some of these definitions. Until/unless we resurrect\n * these archives, these are from memory and usage.\n */\n\n/*\n * ModeLock\n *\n * This one is old, and not really used any more since XKB offers this\n * functionality.\n */\n\n#define XF86XK_ModeLock              0x1008ff01  /* Mode Switch Lock */\n\n/* Backlight controls. */\n#define XF86XK_MonBrightnessUp       0x1008ff02  /* Monitor/panel brightness */\n#define XF86XK_MonBrightnessDown     0x1008ff03  /* Monitor/panel brightness */\n#define XF86XK_KbdLightOnOff         0x1008ff04  /* Keyboards may be lit     */\n#define XF86XK_KbdBrightnessUp       0x1008ff05  /* Keyboards may be lit     */\n#define XF86XK_KbdBrightnessDown     0x1008ff06  /* Keyboards may be lit     */\n#define XF86XK_MonBrightnessCycle    0x1008ff07  /* Monitor/panel brightness */\n\n/*\n * Keys found on some \"Internet\" keyboards.\n */\n#define XF86XK_Standby               0x1008ff10  /* System into standby mode   */\n#define XF86XK_AudioLowerVolume      0x1008ff11  /* Volume control down        */\n#define XF86XK_AudioMute             0x1008ff12  /* Mute sound from the system */\n#define XF86XK_AudioRaiseVolume      0x1008ff13  /* Volume control up          */\n#define XF86XK_AudioPlay             0x1008ff14  /* Start playing of audio >   */\n#define XF86XK_AudioStop             0x1008ff15  /* Stop playing audio         */\n#define XF86XK_AudioPrev             0x1008ff16  /* Previous track             */\n#define XF86XK_AudioNext             0x1008ff17  /* Next track                 */\n#define XF86XK_HomePage              0x1008ff18  /* Display user's home page   */\n#define XF86XK_Mail                  0x1008ff19  /* Invoke user's mail program */\n#define XF86XK_Start                 0x1008ff1a  /* Start application          */\n#define XF86XK_Search                0x1008ff1b  /* Search                     */\n#define XF86XK_AudioRecord           0x1008ff1c  /* Record audio application   */\n\n/* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere)   */\n#define XF86XK_Calculator            0x1008ff1d  /* Invoke calculator program  */\n#define XF86XK_Memo                  0x1008ff1e  /* Invoke Memo taking program */\n#define XF86XK_ToDoList              0x1008ff1f  /* Invoke To Do List program  */\n#define XF86XK_Calendar              0x1008ff20  /* Invoke Calendar program    */\n#define XF86XK_PowerDown             0x1008ff21  /* Deep sleep the system      */\n#define XF86XK_ContrastAdjust        0x1008ff22  /* Adjust screen contrast     */\n#define XF86XK_RockerUp              0x1008ff23  /* Rocker switches exist up   */\n#define XF86XK_RockerDown            0x1008ff24  /* and down                   */\n#define XF86XK_RockerEnter           0x1008ff25  /* and let you press them     */\n\n/* Some more \"Internet\" keyboard symbols */\n#define XF86XK_Back                  0x1008ff26  /* Like back on a browser     */\n#define XF86XK_Forward               0x1008ff27  /* Like forward on a browser  */\n#define XF86XK_Stop                  0x1008ff28  /* Stop current operation     */\n#define XF86XK_Refresh               0x1008ff29  /* Refresh the page           */\n#define XF86XK_PowerOff              0x1008ff2a  /* Power off system entirely  */\n#define XF86XK_WakeUp                0x1008ff2b  /* Wake up system from sleep  */\n#define XF86XK_Eject                 0x1008ff2c  /* Eject device (e.g. DVD)    */\n#define XF86XK_ScreenSaver           0x1008ff2d  /* Invoke screensaver         */\n#define XF86XK_WWW                   0x1008ff2e  /* Invoke web browser         */\n#define XF86XK_Sleep                 0x1008ff2f  /* Put system to sleep        */\n#define XF86XK_Favorites             0x1008ff30  /* Show favorite locations    */\n#define XF86XK_AudioPause            0x1008ff31  /* Pause audio playing        */\n#define XF86XK_AudioMedia            0x1008ff32  /* Launch media collection app */\n#define XF86XK_MyComputer            0x1008ff33  /* Display \"My Computer\" window */\n#define XF86XK_VendorHome            0x1008ff34  /* Display vendor home web site */\n#define XF86XK_LightBulb             0x1008ff35  /* Light bulb keys exist       */\n#define XF86XK_Shop                  0x1008ff36  /* Display shopping web site   */\n#define XF86XK_History               0x1008ff37  /* Show history of web surfing */\n#define XF86XK_OpenURL               0x1008ff38  /* Open selected URL           */\n#define XF86XK_AddFavorite           0x1008ff39  /* Add URL to favorites list   */\n#define XF86XK_HotLinks              0x1008ff3a  /* Show \"hot\" links            */\n#define XF86XK_BrightnessAdjust      0x1008ff3b  /* Invoke brightness adj. UI   */\n#define XF86XK_Finance               0x1008ff3c  /* Display financial site      */\n#define XF86XK_Community             0x1008ff3d  /* Display user's community    */\n#define XF86XK_AudioRewind           0x1008ff3e  /* \"rewind\" audio track        */\n#define XF86XK_BackForward           0x1008ff3f  /* ??? */\n#define XF86XK_Launch0               0x1008ff40  /* Launch Application          */\n#define XF86XK_Launch1               0x1008ff41  /* Launch Application          */\n#define XF86XK_Launch2               0x1008ff42  /* Launch Application          */\n#define XF86XK_Launch3               0x1008ff43  /* Launch Application          */\n#define XF86XK_Launch4               0x1008ff44  /* Launch Application          */\n#define XF86XK_Launch5               0x1008ff45  /* Launch Application          */\n#define XF86XK_Launch6               0x1008ff46  /* Launch Application          */\n#define XF86XK_Launch7               0x1008ff47  /* Launch Application          */\n#define XF86XK_Launch8               0x1008ff48  /* Launch Application          */\n#define XF86XK_Launch9               0x1008ff49  /* Launch Application          */\n#define XF86XK_LaunchA               0x1008ff4a  /* Launch Application          */\n#define XF86XK_LaunchB               0x1008ff4b  /* Launch Application          */\n#define XF86XK_LaunchC               0x1008ff4c  /* Launch Application          */\n#define XF86XK_LaunchD               0x1008ff4d  /* Launch Application          */\n#define XF86XK_LaunchE               0x1008ff4e  /* Launch Application          */\n#define XF86XK_LaunchF               0x1008ff4f  /* Launch Application          */\n\n#define XF86XK_ApplicationLeft       0x1008ff50  /* switch to application, left */\n#define XF86XK_ApplicationRight      0x1008ff51  /* switch to application, right*/\n#define XF86XK_Book                  0x1008ff52  /* Launch bookreader           */\n#define XF86XK_CD                    0x1008ff53  /* Launch CD/DVD player        */\n#define XF86XK_Calculater            0x1008ff54  /* Launch Calculater           */\n#define XF86XK_Clear                 0x1008ff55  /* Clear window, screen        */\n#define XF86XK_Close                 0x1008ff56  /* Close window                */\n#define XF86XK_Copy                  0x1008ff57  /* Copy selection              */\n#define XF86XK_Cut                   0x1008ff58  /* Cut selection               */\n#define XF86XK_Display               0x1008ff59  /* Output switch key           */\n#define XF86XK_DOS                   0x1008ff5a  /* Launch DOS (emulation)      */\n#define XF86XK_Documents             0x1008ff5b  /* Open documents window       */\n#define XF86XK_Excel                 0x1008ff5c  /* Launch spread sheet         */\n#define XF86XK_Explorer              0x1008ff5d  /* Launch file explorer        */\n#define XF86XK_Game                  0x1008ff5e  /* Launch game                 */\n#define XF86XK_Go                    0x1008ff5f  /* Go to URL                   */\n#define XF86XK_iTouch                0x1008ff60  /* Logitech iTouch- don't use  */\n#define XF86XK_LogOff                0x1008ff61  /* Log off system              */\n#define XF86XK_Market                0x1008ff62  /* ??                          */\n#define XF86XK_Meeting               0x1008ff63  /* enter meeting in calendar   */\n#define XF86XK_MenuKB                0x1008ff65  /* distinguish keyboard from PB */\n#define XF86XK_MenuPB                0x1008ff66  /* distinguish PB from keyboard */\n#define XF86XK_MySites               0x1008ff67  /* Favourites                  */\n#define XF86XK_New                   0x1008ff68  /* New (folder, document...    */\n#define XF86XK_News                  0x1008ff69  /* News                        */\n#define XF86XK_OfficeHome            0x1008ff6a  /* Office home (old Staroffice)*/\n#define XF86XK_Open                  0x1008ff6b  /* Open                        */\n#define XF86XK_Option                0x1008ff6c  /* ?? */\n#define XF86XK_Paste                 0x1008ff6d  /* Paste                       */\n#define XF86XK_Phone                 0x1008ff6e  /* Launch phone; dial number   */\n#define XF86XK_Q                     0x1008ff70  /* Compaq's Q - don't use      */\n#define XF86XK_Reply                 0x1008ff72  /* Reply e.g., mail            */\n#define XF86XK_Reload                0x1008ff73  /* Reload web page, file, etc. */\n#define XF86XK_RotateWindows         0x1008ff74  /* Rotate windows e.g. xrandr  */\n#define XF86XK_RotationPB            0x1008ff75  /* don't use                   */\n#define XF86XK_RotationKB            0x1008ff76  /* don't use                   */\n#define XF86XK_Save                  0x1008ff77  /* Save (file, document, state */\n#define XF86XK_ScrollUp              0x1008ff78  /* Scroll window/contents up   */\n#define XF86XK_ScrollDown            0x1008ff79  /* Scrool window/contentd down */\n#define XF86XK_ScrollClick           0x1008ff7a  /* Use XKB mousekeys instead   */\n#define XF86XK_Send                  0x1008ff7b  /* Send mail, file, object     */\n#define XF86XK_Spell                 0x1008ff7c  /* Spell checker               */\n#define XF86XK_SplitScreen           0x1008ff7d  /* Split window or screen      */\n#define XF86XK_Support               0x1008ff7e  /* Get support (??)            */\n#define XF86XK_TaskPane              0x1008ff7f  /* Show tasks */\n#define XF86XK_Terminal              0x1008ff80  /* Launch terminal emulator    */\n#define XF86XK_Tools                 0x1008ff81  /* toolbox of desktop/app.     */\n#define XF86XK_Travel                0x1008ff82  /* ?? */\n#define XF86XK_UserPB                0x1008ff84  /* ?? */\n#define XF86XK_User1KB               0x1008ff85  /* ?? */\n#define XF86XK_User2KB               0x1008ff86  /* ?? */\n#define XF86XK_Video                 0x1008ff87  /* Launch video player       */\n#define XF86XK_WheelButton           0x1008ff88  /* button from a mouse wheel */\n#define XF86XK_Word                  0x1008ff89  /* Launch word processor     */\n#define XF86XK_Xfer                  0x1008ff8a\n#define XF86XK_ZoomIn                0x1008ff8b  /* zoom in view, map, etc.   */\n#define XF86XK_ZoomOut               0x1008ff8c  /* zoom out view, map, etc.  */\n\n#define XF86XK_Away                  0x1008ff8d  /* mark yourself as away     */\n#define XF86XK_Messenger             0x1008ff8e  /* as in instant messaging   */\n#define XF86XK_WebCam                0x1008ff8f  /* Launch web camera app.    */\n#define XF86XK_MailForward           0x1008ff90  /* Forward in mail           */\n#define XF86XK_Pictures              0x1008ff91  /* Show pictures             */\n#define XF86XK_Music                 0x1008ff92  /* Launch music application  */\n\n#define XF86XK_Battery               0x1008ff93  /* Display battery information */\n#define XF86XK_Bluetooth             0x1008ff94  /* Enable/disable Bluetooth    */\n#define XF86XK_WLAN                  0x1008ff95  /* Enable/disable WLAN         */\n#define XF86XK_UWB                   0x1008ff96  /* Enable/disable UWB\t    */\n\n#define XF86XK_AudioForward          0x1008ff97  /* fast-forward audio track    */\n#define XF86XK_AudioRepeat           0x1008ff98  /* toggle repeat mode          */\n#define XF86XK_AudioRandomPlay       0x1008ff99  /* toggle shuffle mode         */\n#define XF86XK_Subtitle              0x1008ff9a  /* cycle through subtitle      */\n#define XF86XK_AudioCycleTrack       0x1008ff9b  /* cycle through audio tracks  */\n#define XF86XK_CycleAngle            0x1008ff9c  /* cycle through angles        */\n#define XF86XK_FrameBack             0x1008ff9d  /* video: go one frame back    */\n#define XF86XK_FrameForward          0x1008ff9e  /* video: go one frame forward */\n#define XF86XK_Time                  0x1008ff9f  /* display, or shows an entry for time seeking */\n#define XF86XK_Select                0x1008ffa0  /* Select button on joypads and remotes */\n#define XF86XK_View                  0x1008ffa1  /* Show a view options/properties */\n#define XF86XK_TopMenu               0x1008ffa2  /* Go to a top-level menu in a video */\n\n#define XF86XK_Red                   0x1008ffa3  /* Red button                  */\n#define XF86XK_Green                 0x1008ffa4  /* Green button                */\n#define XF86XK_Yellow                0x1008ffa5  /* Yellow button               */\n#define XF86XK_Blue                  0x1008ffa6  /* Blue button                 */\n\n#define XF86XK_Suspend               0x1008ffa7  /* Sleep to RAM                */\n#define XF86XK_Hibernate             0x1008ffa8  /* Sleep to disk               */\n#define XF86XK_TouchpadToggle        0x1008ffa9  /* Toggle between touchpad/trackstick */\n#define XF86XK_TouchpadOn            0x1008ffb0  /* The touchpad got switched on */\n#define XF86XK_TouchpadOff           0x1008ffb1  /* The touchpad got switched off */\n\n#define XF86XK_AudioMicMute          0x1008ffb2  /* Mute the Mic from the system */\n\n#define XF86XK_Keyboard              0x1008ffb3  /* User defined keyboard related action */\n\n#define XF86XK_WWAN                  0x1008ffb4  /* Toggle WWAN (LTE, UMTS, etc.) radio */\n#define XF86XK_RFKill                0x1008ffb5  /* Toggle radios on/off */\n\n#define XF86XK_AudioPreset           0x1008ffb6  /* Select equalizer preset, e.g. theatre-mode */\n\n#define XF86XK_RotationLockToggle    0x1008ffb7  /* Toggle screen rotation lock on/off */\n\n#define XF86XK_FullScreen            0x1008ffb8  /* Toggle fullscreen */\n\n/* Keys for special action keys (hot keys) */\n/* Virtual terminals on some operating systems */\n#define XF86XK_Switch_VT_1           0x1008fe01\n#define XF86XK_Switch_VT_2           0x1008fe02\n#define XF86XK_Switch_VT_3           0x1008fe03\n#define XF86XK_Switch_VT_4           0x1008fe04\n#define XF86XK_Switch_VT_5           0x1008fe05\n#define XF86XK_Switch_VT_6           0x1008fe06\n#define XF86XK_Switch_VT_7           0x1008fe07\n#define XF86XK_Switch_VT_8           0x1008fe08\n#define XF86XK_Switch_VT_9           0x1008fe09\n#define XF86XK_Switch_VT_10          0x1008fe0a\n#define XF86XK_Switch_VT_11          0x1008fe0b\n#define XF86XK_Switch_VT_12          0x1008fe0c\n\n#define XF86XK_Ungrab                0x1008fe20  /* force ungrab               */\n#define XF86XK_ClearGrab             0x1008fe21  /* kill application with grab */\n#define XF86XK_Next_VMode            0x1008fe22  /* next video mode available  */\n#define XF86XK_Prev_VMode            0x1008fe23  /* prev. video mode available */\n#define XF86XK_LogWindowTree         0x1008fe24  /* print window tree to log   */\n#define XF86XK_LogGrabInfo           0x1008fe25  /* print all active grabs to log */\n\n\n/*\n * Reserved range for evdev symbols: 0x10081000-0x10081FFF\n *\n * Key syms within this range must match the Linux kernel\n * input-event-codes.h file in the format:\n *     XF86XK_CamelCaseKernelName\t_EVDEVK(kernel value)\n * For example, the kernel\n *   #define KEY_MACRO_RECORD_START\t0x2b0\n * effectively ends up as:\n *   #define XF86XK_MacroRecordStart\t0x100812b0\n *\n * For historical reasons, some keysyms within the reserved range will be\n * missing, most notably all \"normal\" keys that are mapped through default\n * XKB layouts (e.g. KEY_Q).\n *\n * CamelCasing is done with a human control as last authority, e.g. see VOD\n * instead of Vod for the Video on Demand key.\n *\n * The format for #defines is strict:\n *\n * #define XF86XK_FOO<tab...>_EVDEVK(0xABC)<tab><tab> |* kver KEY_FOO *|\n *\n * Where\n * - alignment by tabs\n * - the _EVDEVK macro must be used\n * - the hex code must be in uppercase hex\n * - the kernel version (kver) is in the form v5.10\n * - kver and key name are within a slash-star comment (a pipe is used in\n *   this example for technical reasons)\n * These #defines are parsed by scripts. Do not stray from the given format.\n *\n * Where the evdev keycode is mapped to a different symbol, please add a\n * comment line starting with Use: but otherwise the same format, e.g.\n *  Use: XF86XK_RotationLockToggle\t_EVDEVK(0x231)\t\t   v4.16 KEY_ROTATE_LOCK_TOGGLE\n *\n */\n#define _EVDEVK(_v) (0x10081000 + _v)\n/* Use: XF86XK_Eject                    _EVDEVK(0x0a2)             KEY_EJECTCLOSECD */\n/* Use: XF86XK_New                      _EVDEVK(0x0b5)     v2.6.14 KEY_NEW */\n/* Use: XK_Redo                         _EVDEVK(0x0b6)     v2.6.14 KEY_REDO */\n/* KEY_DASHBOARD has been mapped to LaunchB in xkeyboard-config since 2011 */\n/* Use: XF86XK_LaunchB                  _EVDEVK(0x0cc)     v2.6.28 KEY_DASHBOARD */\n/* Use: XF86XK_Display                  _EVDEVK(0x0e3)     v2.6.12 KEY_SWITCHVIDEOMODE */\n/* Use: XF86XK_KbdLightOnOff            _EVDEVK(0x0e4)     v2.6.12 KEY_KBDILLUMTOGGLE */\n/* Use: XF86XK_KbdBrightnessDown        _EVDEVK(0x0e5)     v2.6.12 KEY_KBDILLUMDOWN */\n/* Use: XF86XK_KbdBrightnessUp          _EVDEVK(0x0e6)     v2.6.12 KEY_KBDILLUMUP */\n/* Use: XF86XK_Send                     _EVDEVK(0x0e7)     v2.6.14 KEY_SEND */\n/* Use: XF86XK_Reply                    _EVDEVK(0x0e8)     v2.6.14 KEY_REPLY */\n/* Use: XF86XK_MailForward              _EVDEVK(0x0e9)     v2.6.14 KEY_FORWARDMAIL */\n/* Use: XF86XK_Save                     _EVDEVK(0x0ea)     v2.6.14 KEY_SAVE */\n/* Use: XF86XK_Documents                _EVDEVK(0x0eb)     v2.6.14 KEY_DOCUMENTS */\n/* Use: XF86XK_Battery                  _EVDEVK(0x0ec)     v2.6.17 KEY_BATTERY */\n/* Use: XF86XK_Bluetooth                _EVDEVK(0x0ed)     v2.6.19 KEY_BLUETOOTH */\n/* Use: XF86XK_WLAN                     _EVDEVK(0x0ee)     v2.6.19 KEY_WLAN */\n/* Use: XF86XK_UWB                      _EVDEVK(0x0ef)     v2.6.24 KEY_UWB */\n/* Use: XF86XK_Next_VMode               _EVDEVK(0x0f1)     v2.6.23 KEY_VIDEO_NEXT */\n/* Use: XF86XK_Prev_VMode               _EVDEVK(0x0f2)     v2.6.23 KEY_VIDEO_PREV */\n/* Use: XF86XK_MonBrightnessCycle       _EVDEVK(0x0f3)     v2.6.23 KEY_BRIGHTNESS_CYCLE */\n#define XF86XK_BrightnessAuto           _EVDEVK(0x0f4)  /* v3.16   KEY_BRIGHTNESS_AUTO */\n#define XF86XK_DisplayOff               _EVDEVK(0x0f5)  /* v2.6.23 KEY_DISPLAY_OFF */\n/* Use: XF86XK_WWAN                     _EVDEVK(0x0f6)     v3.13   KEY_WWAN */\n/* Use: XF86XK_RFKill                   _EVDEVK(0x0f7)     v2.6.33 KEY_RFKILL */\n/* Use: XF86XK_AudioMicMute             _EVDEVK(0x0f8)     v3.1    KEY_MICMUTE */\n#define XF86XK_Info                     _EVDEVK(0x166)  /*         KEY_INFO */\n/* Use: XF86XK_CycleAngle               _EVDEVK(0x173)             KEY_ANGLE */\n/* Use: XF86XK_FullScreen               _EVDEVK(0x174)     v5.1    KEY_FULL_SCREEN */\n#define XF86XK_AspectRatio              _EVDEVK(0x177)  /* v5.1    KEY_ASPECT_RATIO */\n#define XF86XK_DVD                      _EVDEVK(0x185)  /*         KEY_DVD */\n#define XF86XK_Audio                    _EVDEVK(0x188)  /*         KEY_AUDIO */\n/* Use: XF86XK_Video                    _EVDEVK(0x189)             KEY_VIDEO */\n/* Use: XF86XK_Calendar                 _EVDEVK(0x18d)             KEY_CALENDAR */\n#define XF86XK_ChannelUp                _EVDEVK(0x192)  /*         KEY_CHANNELUP */\n#define XF86XK_ChannelDown              _EVDEVK(0x193)  /*         KEY_CHANNELDOWN */\n/* Use: XF86XK_AudioRandomPlay          _EVDEVK(0x19a)             KEY_SHUFFLE */\n#define XF86XK_Break                    _EVDEVK(0x19b)  /*         KEY_BREAK */\n#define XF86XK_VideoPhone               _EVDEVK(0x1a0)  /* v2.6.20 KEY_VIDEOPHONE */\n/* Use: XF86XK_Game                     _EVDEVK(0x1a1)     v2.6.20 KEY_GAMES */\n/* Use: XF86XK_ZoomIn                   _EVDEVK(0x1a2)     v2.6.20 KEY_ZOOMIN */\n/* Use: XF86XK_ZoomOut                  _EVDEVK(0x1a3)     v2.6.20 KEY_ZOOMOUT */\n#define XF86XK_ZoomReset                _EVDEVK(0x1a4)  /* v2.6.20 KEY_ZOOMRESET */\n/* Use: XF86XK_Word                     _EVDEVK(0x1a5)     v2.6.20 KEY_WORDPROCESSOR */\n#define XF86XK_Editor                   _EVDEVK(0x1a6)  /* v2.6.20 KEY_EDITOR */\n/* Use: XF86XK_Excel                    _EVDEVK(0x1a7)     v2.6.20 KEY_SPREADSHEET */\n#define XF86XK_GraphicsEditor           _EVDEVK(0x1a8)  /* v2.6.20 KEY_GRAPHICSEDITOR */\n#define XF86XK_Presentation             _EVDEVK(0x1a9)  /* v2.6.20 KEY_PRESENTATION */\n#define XF86XK_Database                 _EVDEVK(0x1aa)  /* v2.6.20 KEY_DATABASE */\n/* Use: XF86XK_News                     _EVDEVK(0x1ab)     v2.6.20 KEY_NEWS */\n#define XF86XK_Voicemail                _EVDEVK(0x1ac)  /* v2.6.20 KEY_VOICEMAIL */\n#define XF86XK_Addressbook              _EVDEVK(0x1ad)  /* v2.6.20 KEY_ADDRESSBOOK */\n/* Use: XF86XK_Messenger                _EVDEVK(0x1ae)     v2.6.20 KEY_MESSENGER */\n#define XF86XK_DisplayToggle            _EVDEVK(0x1af)  /* v2.6.20 KEY_DISPLAYTOGGLE */\n#define XF86XK_SpellCheck               _EVDEVK(0x1b0)  /* v2.6.24 KEY_SPELLCHECK */\n/* Use: XF86XK_LogOff                   _EVDEVK(0x1b1)     v2.6.24 KEY_LOGOFF */\n/* Use: XK_dollar                       _EVDEVK(0x1b2)     v2.6.24 KEY_DOLLAR */\n/* Use: XK_EuroSign                     _EVDEVK(0x1b3)     v2.6.24 KEY_EURO */\n/* Use: XF86XK_FrameBack                _EVDEVK(0x1b4)     v2.6.24 KEY_FRAMEBACK */\n/* Use: XF86XK_FrameForward             _EVDEVK(0x1b5)     v2.6.24 KEY_FRAMEFORWARD */\n#define XF86XK_ContextMenu              _EVDEVK(0x1b6)  /* v2.6.24 KEY_CONTEXT_MENU */\n#define XF86XK_MediaRepeat              _EVDEVK(0x1b7)  /* v2.6.26 KEY_MEDIA_REPEAT */\n#define XF86XK_10ChannelsUp             _EVDEVK(0x1b8)  /* v2.6.38 KEY_10CHANNELSUP */\n#define XF86XK_10ChannelsDown           _EVDEVK(0x1b9)  /* v2.6.38 KEY_10CHANNELSDOWN */\n#define XF86XK_Images                   _EVDEVK(0x1ba)  /* v2.6.39 KEY_IMAGES */\n#define XF86XK_NotificationCenter       _EVDEVK(0x1bc)  /* v5.10   KEY_NOTIFICATION_CENTER */\n#define XF86XK_PickupPhone              _EVDEVK(0x1bd)  /* v5.10   KEY_PICKUP_PHONE */\n#define XF86XK_HangupPhone              _EVDEVK(0x1be)  /* v5.10   KEY_HANGUP_PHONE */\n#define XF86XK_Fn                       _EVDEVK(0x1d0)  /*         KEY_FN */\n#define XF86XK_Fn_Esc                   _EVDEVK(0x1d1)  /*         KEY_FN_ESC */\n#define XF86XK_FnRightShift             _EVDEVK(0x1e5)  /* v5.10   KEY_FN_RIGHT_SHIFT */\n/* Use: XK_braille_dot_1                _EVDEVK(0x1f1)     v2.6.17 KEY_BRL_DOT1 */\n/* Use: XK_braille_dot_2                _EVDEVK(0x1f2)     v2.6.17 KEY_BRL_DOT2 */\n/* Use: XK_braille_dot_3                _EVDEVK(0x1f3)     v2.6.17 KEY_BRL_DOT3 */\n/* Use: XK_braille_dot_4                _EVDEVK(0x1f4)     v2.6.17 KEY_BRL_DOT4 */\n/* Use: XK_braille_dot_5                _EVDEVK(0x1f5)     v2.6.17 KEY_BRL_DOT5 */\n/* Use: XK_braille_dot_6                _EVDEVK(0x1f6)     v2.6.17 KEY_BRL_DOT6 */\n/* Use: XK_braille_dot_7                _EVDEVK(0x1f7)     v2.6.17 KEY_BRL_DOT7 */\n/* Use: XK_braille_dot_8                _EVDEVK(0x1f8)     v2.6.17 KEY_BRL_DOT8 */\n/* Use: XK_braille_dot_9                _EVDEVK(0x1f9)     v2.6.23 KEY_BRL_DOT9 */\n/* Use: XK_braille_dot_1                _EVDEVK(0x1fa)     v2.6.23 KEY_BRL_DOT10 */\n#define XF86XK_Numeric0                 _EVDEVK(0x200)  /* v2.6.28 KEY_NUMERIC_0 */\n#define XF86XK_Numeric1                 _EVDEVK(0x201)  /* v2.6.28 KEY_NUMERIC_1 */\n#define XF86XK_Numeric2                 _EVDEVK(0x202)  /* v2.6.28 KEY_NUMERIC_2 */\n#define XF86XK_Numeric3                 _EVDEVK(0x203)  /* v2.6.28 KEY_NUMERIC_3 */\n#define XF86XK_Numeric4                 _EVDEVK(0x204)  /* v2.6.28 KEY_NUMERIC_4 */\n#define XF86XK_Numeric5                 _EVDEVK(0x205)  /* v2.6.28 KEY_NUMERIC_5 */\n#define XF86XK_Numeric6                 _EVDEVK(0x206)  /* v2.6.28 KEY_NUMERIC_6 */\n#define XF86XK_Numeric7                 _EVDEVK(0x207)  /* v2.6.28 KEY_NUMERIC_7 */\n#define XF86XK_Numeric8                 _EVDEVK(0x208)  /* v2.6.28 KEY_NUMERIC_8 */\n#define XF86XK_Numeric9                 _EVDEVK(0x209)  /* v2.6.28 KEY_NUMERIC_9 */\n#define XF86XK_NumericStar              _EVDEVK(0x20a)  /* v2.6.28 KEY_NUMERIC_STAR */\n#define XF86XK_NumericPound             _EVDEVK(0x20b)  /* v2.6.28 KEY_NUMERIC_POUND */\n#define XF86XK_NumericA                 _EVDEVK(0x20c)  /* v4.1    KEY_NUMERIC_A */\n#define XF86XK_NumericB                 _EVDEVK(0x20d)  /* v4.1    KEY_NUMERIC_B */\n#define XF86XK_NumericC                 _EVDEVK(0x20e)  /* v4.1    KEY_NUMERIC_C */\n#define XF86XK_NumericD                 _EVDEVK(0x20f)  /* v4.1    KEY_NUMERIC_D */\n#define XF86XK_CameraFocus              _EVDEVK(0x210)  /* v2.6.33 KEY_CAMERA_FOCUS */\n#define XF86XK_WPSButton                _EVDEVK(0x211)  /* v2.6.34 KEY_WPS_BUTTON */\n/* Use: XF86XK_TouchpadToggle           _EVDEVK(0x212)     v2.6.37 KEY_TOUCHPAD_TOGGLE */\n/* Use: XF86XK_TouchpadOn               _EVDEVK(0x213)     v2.6.37 KEY_TOUCHPAD_ON */\n/* Use: XF86XK_TouchpadOff              _EVDEVK(0x214)     v2.6.37 KEY_TOUCHPAD_OFF */\n#define XF86XK_CameraZoomIn             _EVDEVK(0x215)  /* v2.6.39 KEY_CAMERA_ZOOMIN */\n#define XF86XK_CameraZoomOut            _EVDEVK(0x216)  /* v2.6.39 KEY_CAMERA_ZOOMOUT */\n#define XF86XK_CameraUp                 _EVDEVK(0x217)  /* v2.6.39 KEY_CAMERA_UP */\n#define XF86XK_CameraDown               _EVDEVK(0x218)  /* v2.6.39 KEY_CAMERA_DOWN */\n#define XF86XK_CameraLeft               _EVDEVK(0x219)  /* v2.6.39 KEY_CAMERA_LEFT */\n#define XF86XK_CameraRight              _EVDEVK(0x21a)  /* v2.6.39 KEY_CAMERA_RIGHT */\n#define XF86XK_AttendantOn              _EVDEVK(0x21b)  /* v3.10   KEY_ATTENDANT_ON */\n#define XF86XK_AttendantOff             _EVDEVK(0x21c)  /* v3.10   KEY_ATTENDANT_OFF */\n#define XF86XK_AttendantToggle          _EVDEVK(0x21d)  /* v3.10   KEY_ATTENDANT_TOGGLE */\n#define XF86XK_LightsToggle             _EVDEVK(0x21e)  /* v3.10   KEY_LIGHTS_TOGGLE */\n#define XF86XK_ALSToggle                _EVDEVK(0x230)  /* v3.13   KEY_ALS_TOGGLE */\n/* Use: XF86XK_RotationLockToggle       _EVDEVK(0x231)     v4.16   KEY_ROTATE_LOCK_TOGGLE */\n#define XF86XK_Buttonconfig             _EVDEVK(0x240)  /* v3.16   KEY_BUTTONCONFIG */\n#define XF86XK_Taskmanager              _EVDEVK(0x241)  /* v3.16   KEY_TASKMANAGER */\n#define XF86XK_Journal                  _EVDEVK(0x242)  /* v3.16   KEY_JOURNAL */\n#define XF86XK_ControlPanel             _EVDEVK(0x243)  /* v3.16   KEY_CONTROLPANEL */\n#define XF86XK_AppSelect                _EVDEVK(0x244)  /* v3.16   KEY_APPSELECT */\n#define XF86XK_Screensaver              _EVDEVK(0x245)  /* v3.16   KEY_SCREENSAVER */\n#define XF86XK_VoiceCommand             _EVDEVK(0x246)  /* v3.16   KEY_VOICECOMMAND */\n#define XF86XK_Assistant                _EVDEVK(0x247)  /* v4.13   KEY_ASSISTANT */\n/* Use: XK_ISO_Next_Group               _EVDEVK(0x248)     v5.2    KEY_KBD_LAYOUT_NEXT */\n#define XF86XK_EmojiPicker              _EVDEVK(0x249)  /* v5.13   KEY_EMOJI_PICKER */\n#define XF86XK_Dictate                  _EVDEVK(0x24a)  /* v5.17   KEY_DICTATE */\n#define XF86XK_CameraAccessEnable       _EVDEVK(0x24b)  /* v6.2    KEY_CAMERA_ACCESS_ENABLE */\n#define XF86XK_CameraAccessDisable      _EVDEVK(0x24c)  /* v6.2    KEY_CAMERA_ACCESS_DISABLE */\n#define XF86XK_CameraAccessToggle       _EVDEVK(0x24d)  /* v6.2    KEY_CAMERA_ACCESS_TOGGLE */\n#define XF86XK_BrightnessMin            _EVDEVK(0x250)  /* v3.16   KEY_BRIGHTNESS_MIN */\n#define XF86XK_BrightnessMax            _EVDEVK(0x251)  /* v3.16   KEY_BRIGHTNESS_MAX */\n#define XF86XK_KbdInputAssistPrev       _EVDEVK(0x260)  /* v3.18   KEY_KBDINPUTASSIST_PREV */\n#define XF86XK_KbdInputAssistNext       _EVDEVK(0x261)  /* v3.18   KEY_KBDINPUTASSIST_NEXT */\n#define XF86XK_KbdInputAssistPrevgroup  _EVDEVK(0x262)  /* v3.18   KEY_KBDINPUTASSIST_PREVGROUP */\n#define XF86XK_KbdInputAssistNextgroup  _EVDEVK(0x263)  /* v3.18   KEY_KBDINPUTASSIST_NEXTGROUP */\n#define XF86XK_KbdInputAssistAccept     _EVDEVK(0x264)  /* v3.18   KEY_KBDINPUTASSIST_ACCEPT */\n#define XF86XK_KbdInputAssistCancel     _EVDEVK(0x265)  /* v3.18   KEY_KBDINPUTASSIST_CANCEL */\n#define XF86XK_RightUp                  _EVDEVK(0x266)  /* v4.7    KEY_RIGHT_UP */\n#define XF86XK_RightDown                _EVDEVK(0x267)  /* v4.7    KEY_RIGHT_DOWN */\n#define XF86XK_LeftUp                   _EVDEVK(0x268)  /* v4.7    KEY_LEFT_UP */\n#define XF86XK_LeftDown                 _EVDEVK(0x269)  /* v4.7    KEY_LEFT_DOWN */\n#define XF86XK_RootMenu                 _EVDEVK(0x26a)  /* v4.7    KEY_ROOT_MENU */\n#define XF86XK_MediaTopMenu             _EVDEVK(0x26b)  /* v4.7    KEY_MEDIA_TOP_MENU */\n#define XF86XK_Numeric11                _EVDEVK(0x26c)  /* v4.7    KEY_NUMERIC_11 */\n#define XF86XK_Numeric12                _EVDEVK(0x26d)  /* v4.7    KEY_NUMERIC_12 */\n#define XF86XK_AudioDesc                _EVDEVK(0x26e)  /* v4.7    KEY_AUDIO_DESC */\n#define XF86XK_3DMode                   _EVDEVK(0x26f)  /* v4.7    KEY_3D_MODE */\n#define XF86XK_NextFavorite             _EVDEVK(0x270)  /* v4.7    KEY_NEXT_FAVORITE */\n#define XF86XK_StopRecord               _EVDEVK(0x271)  /* v4.7    KEY_STOP_RECORD */\n#define XF86XK_PauseRecord              _EVDEVK(0x272)  /* v4.7    KEY_PAUSE_RECORD */\n#define XF86XK_VOD                      _EVDEVK(0x273)  /* v4.7    KEY_VOD */\n#define XF86XK_Unmute                   _EVDEVK(0x274)  /* v4.7    KEY_UNMUTE */\n#define XF86XK_FastReverse              _EVDEVK(0x275)  /* v4.7    KEY_FASTREVERSE */\n#define XF86XK_SlowReverse              _EVDEVK(0x276)  /* v4.7    KEY_SLOWREVERSE */\n#define XF86XK_Data                     _EVDEVK(0x277)  /* v4.7    KEY_DATA */\n#define XF86XK_OnScreenKeyboard         _EVDEVK(0x278)  /* v4.12   KEY_ONSCREEN_KEYBOARD */\n#define XF86XK_PrivacyScreenToggle      _EVDEVK(0x279)  /* v5.5    KEY_PRIVACY_SCREEN_TOGGLE */\n#define XF86XK_SelectiveScreenshot      _EVDEVK(0x27a)  /* v5.6    KEY_SELECTIVE_SCREENSHOT */\n#define XF86XK_NextElement              _EVDEVK(0x27b)  /* v5.18   KEY_NEXT_ELEMENT */\n#define XF86XK_PreviousElement          _EVDEVK(0x27c)  /* v5.18   KEY_PREVIOUS_ELEMENT */\n#define XF86XK_AutopilotEngageToggle    _EVDEVK(0x27d)  /* v5.18   KEY_AUTOPILOT_ENGAGE_TOGGLE */\n#define XF86XK_MarkWaypoint             _EVDEVK(0x27e)  /* v5.18   KEY_MARK_WAYPOINT */\n#define XF86XK_Sos                      _EVDEVK(0x27f)  /* v5.18   KEY_SOS */\n#define XF86XK_NavChart                 _EVDEVK(0x280)  /* v5.18   KEY_NAV_CHART */\n#define XF86XK_FishingChart             _EVDEVK(0x281)  /* v5.18   KEY_FISHING_CHART */\n#define XF86XK_SingleRangeRadar         _EVDEVK(0x282)  /* v5.18   KEY_SINGLE_RANGE_RADAR */\n#define XF86XK_DualRangeRadar           _EVDEVK(0x283)  /* v5.18   KEY_DUAL_RANGE_RADAR */\n#define XF86XK_RadarOverlay             _EVDEVK(0x284)  /* v5.18   KEY_RADAR_OVERLAY */\n#define XF86XK_TraditionalSonar         _EVDEVK(0x285)  /* v5.18   KEY_TRADITIONAL_SONAR */\n#define XF86XK_ClearvuSonar             _EVDEVK(0x286)  /* v5.18   KEY_CLEARVU_SONAR */\n#define XF86XK_SidevuSonar              _EVDEVK(0x287)  /* v5.18   KEY_SIDEVU_SONAR */\n#define XF86XK_NavInfo                  _EVDEVK(0x288)  /* v5.18   KEY_NAV_INFO */\n/* Use: XF86XK_BrightnessAdjust         _EVDEVK(0x289)     v5.18   KEY_BRIGHTNESS_MENU */\n#define XF86XK_Macro1                   _EVDEVK(0x290)  /* v5.5    KEY_MACRO1 */\n#define XF86XK_Macro2                   _EVDEVK(0x291)  /* v5.5    KEY_MACRO2 */\n#define XF86XK_Macro3                   _EVDEVK(0x292)  /* v5.5    KEY_MACRO3 */\n#define XF86XK_Macro4                   _EVDEVK(0x293)  /* v5.5    KEY_MACRO4 */\n#define XF86XK_Macro5                   _EVDEVK(0x294)  /* v5.5    KEY_MACRO5 */\n#define XF86XK_Macro6                   _EVDEVK(0x295)  /* v5.5    KEY_MACRO6 */\n#define XF86XK_Macro7                   _EVDEVK(0x296)  /* v5.5    KEY_MACRO7 */\n#define XF86XK_Macro8                   _EVDEVK(0x297)  /* v5.5    KEY_MACRO8 */\n#define XF86XK_Macro9                   _EVDEVK(0x298)  /* v5.5    KEY_MACRO9 */\n#define XF86XK_Macro10                  _EVDEVK(0x299)  /* v5.5    KEY_MACRO10 */\n#define XF86XK_Macro11                  _EVDEVK(0x29a)  /* v5.5    KEY_MACRO11 */\n#define XF86XK_Macro12                  _EVDEVK(0x29b)  /* v5.5    KEY_MACRO12 */\n#define XF86XK_Macro13                  _EVDEVK(0x29c)  /* v5.5    KEY_MACRO13 */\n#define XF86XK_Macro14                  _EVDEVK(0x29d)  /* v5.5    KEY_MACRO14 */\n#define XF86XK_Macro15                  _EVDEVK(0x29e)  /* v5.5    KEY_MACRO15 */\n#define XF86XK_Macro16                  _EVDEVK(0x29f)  /* v5.5    KEY_MACRO16 */\n#define XF86XK_Macro17                  _EVDEVK(0x2a0)  /* v5.5    KEY_MACRO17 */\n#define XF86XK_Macro18                  _EVDEVK(0x2a1)  /* v5.5    KEY_MACRO18 */\n#define XF86XK_Macro19                  _EVDEVK(0x2a2)  /* v5.5    KEY_MACRO19 */\n#define XF86XK_Macro20                  _EVDEVK(0x2a3)  /* v5.5    KEY_MACRO20 */\n#define XF86XK_Macro21                  _EVDEVK(0x2a4)  /* v5.5    KEY_MACRO21 */\n#define XF86XK_Macro22                  _EVDEVK(0x2a5)  /* v5.5    KEY_MACRO22 */\n#define XF86XK_Macro23                  _EVDEVK(0x2a6)  /* v5.5    KEY_MACRO23 */\n#define XF86XK_Macro24                  _EVDEVK(0x2a7)  /* v5.5    KEY_MACRO24 */\n#define XF86XK_Macro25                  _EVDEVK(0x2a8)  /* v5.5    KEY_MACRO25 */\n#define XF86XK_Macro26                  _EVDEVK(0x2a9)  /* v5.5    KEY_MACRO26 */\n#define XF86XK_Macro27                  _EVDEVK(0x2aa)  /* v5.5    KEY_MACRO27 */\n#define XF86XK_Macro28                  _EVDEVK(0x2ab)  /* v5.5    KEY_MACRO28 */\n#define XF86XK_Macro29                  _EVDEVK(0x2ac)  /* v5.5    KEY_MACRO29 */\n#define XF86XK_Macro30                  _EVDEVK(0x2ad)  /* v5.5    KEY_MACRO30 */\n#define XF86XK_MacroRecordStart         _EVDEVK(0x2b0)  /* v5.5    KEY_MACRO_RECORD_START */\n#define XF86XK_MacroRecordStop          _EVDEVK(0x2b1)  /* v5.5    KEY_MACRO_RECORD_STOP */\n#define XF86XK_MacroPresetCycle         _EVDEVK(0x2b2)  /* v5.5    KEY_MACRO_PRESET_CYCLE */\n#define XF86XK_MacroPreset1             _EVDEVK(0x2b3)  /* v5.5    KEY_MACRO_PRESET1 */\n#define XF86XK_MacroPreset2             _EVDEVK(0x2b4)  /* v5.5    KEY_MACRO_PRESET2 */\n#define XF86XK_MacroPreset3             _EVDEVK(0x2b5)  /* v5.5    KEY_MACRO_PRESET3 */\n#define XF86XK_KbdLcdMenu1              _EVDEVK(0x2b8)  /* v5.5    KEY_KBD_LCD_MENU1 */\n#define XF86XK_KbdLcdMenu2              _EVDEVK(0x2b9)  /* v5.5    KEY_KBD_LCD_MENU2 */\n#define XF86XK_KbdLcdMenu3              _EVDEVK(0x2ba)  /* v5.5    KEY_KBD_LCD_MENU3 */\n#define XF86XK_KbdLcdMenu4              _EVDEVK(0x2bb)  /* v5.5    KEY_KBD_LCD_MENU4 */\n#define XF86XK_KbdLcdMenu5              _EVDEVK(0x2bc)  /* v5.5    KEY_KBD_LCD_MENU5 */\n#undef _EVDEVK\n"
  },
  {
    "path": "xlib/X11/Xatom.h",
    "content": "#ifndef XATOM_H\n#define XATOM_H 1\n\n/* THIS IS A GENERATED FILE\n *\n * Do not change!  Changing this file implies a protocol change!\n */\n\n#define XA_PRIMARY ((Atom) 1)\n#define XA_SECONDARY ((Atom) 2)\n#define XA_ARC ((Atom) 3)\n#define XA_ATOM ((Atom) 4)\n#define XA_BITMAP ((Atom) 5)\n#define XA_CARDINAL ((Atom) 6)\n#define XA_COLORMAP ((Atom) 7)\n#define XA_CURSOR ((Atom) 8)\n#define XA_CUT_BUFFER0 ((Atom) 9)\n#define XA_CUT_BUFFER1 ((Atom) 10)\n#define XA_CUT_BUFFER2 ((Atom) 11)\n#define XA_CUT_BUFFER3 ((Atom) 12)\n#define XA_CUT_BUFFER4 ((Atom) 13)\n#define XA_CUT_BUFFER5 ((Atom) 14)\n#define XA_CUT_BUFFER6 ((Atom) 15)\n#define XA_CUT_BUFFER7 ((Atom) 16)\n#define XA_DRAWABLE ((Atom) 17)\n#define XA_FONT ((Atom) 18)\n#define XA_INTEGER ((Atom) 19)\n#define XA_PIXMAP ((Atom) 20)\n#define XA_POINT ((Atom) 21)\n#define XA_RECTANGLE ((Atom) 22)\n#define XA_RESOURCE_MANAGER ((Atom) 23)\n#define XA_RGB_COLOR_MAP ((Atom) 24)\n#define XA_RGB_BEST_MAP ((Atom) 25)\n#define XA_RGB_BLUE_MAP ((Atom) 26)\n#define XA_RGB_DEFAULT_MAP ((Atom) 27)\n#define XA_RGB_GRAY_MAP ((Atom) 28)\n#define XA_RGB_GREEN_MAP ((Atom) 29)\n#define XA_RGB_RED_MAP ((Atom) 30)\n#define XA_STRING ((Atom) 31)\n#define XA_VISUALID ((Atom) 32)\n#define XA_WINDOW ((Atom) 33)\n#define XA_WM_COMMAND ((Atom) 34)\n#define XA_WM_HINTS ((Atom) 35)\n#define XA_WM_CLIENT_MACHINE ((Atom) 36)\n#define XA_WM_ICON_NAME ((Atom) 37)\n#define XA_WM_ICON_SIZE ((Atom) 38)\n#define XA_WM_NAME ((Atom) 39)\n#define XA_WM_NORMAL_HINTS ((Atom) 40)\n#define XA_WM_SIZE_HINTS ((Atom) 41)\n#define XA_WM_ZOOM_HINTS ((Atom) 42)\n#define XA_MIN_SPACE ((Atom) 43)\n#define XA_NORM_SPACE ((Atom) 44)\n#define XA_MAX_SPACE ((Atom) 45)\n#define XA_END_SPACE ((Atom) 46)\n#define XA_SUPERSCRIPT_X ((Atom) 47)\n#define XA_SUPERSCRIPT_Y ((Atom) 48)\n#define XA_SUBSCRIPT_X ((Atom) 49)\n#define XA_SUBSCRIPT_Y ((Atom) 50)\n#define XA_UNDERLINE_POSITION ((Atom) 51)\n#define XA_UNDERLINE_THICKNESS ((Atom) 52)\n#define XA_STRIKEOUT_ASCENT ((Atom) 53)\n#define XA_STRIKEOUT_DESCENT ((Atom) 54)\n#define XA_ITALIC_ANGLE ((Atom) 55)\n#define XA_X_HEIGHT ((Atom) 56)\n#define XA_QUAD_WIDTH ((Atom) 57)\n#define XA_WEIGHT ((Atom) 58)\n#define XA_POINT_SIZE ((Atom) 59)\n#define XA_RESOLUTION ((Atom) 60)\n#define XA_COPYRIGHT ((Atom) 61)\n#define XA_NOTICE ((Atom) 62)\n#define XA_FONT_NAME ((Atom) 63)\n#define XA_FAMILY_NAME ((Atom) 64)\n#define XA_FULL_NAME ((Atom) 65)\n#define XA_CAP_HEIGHT ((Atom) 66)\n#define XA_WM_CLASS ((Atom) 67)\n#define XA_WM_TRANSIENT_FOR ((Atom) 68)\n\n#define XA_LAST_PREDEFINED ((Atom) 68)\n#endif /* XATOM_H */\n"
  },
  {
    "path": "xlib/X11/Xfuncproto.h",
    "content": "/*\n *\nCopyright 1989, 1991, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n *\n */\n\n/* Definitions to make function prototypes manageable */\n\n#ifndef _XFUNCPROTO_H_\n#define _XFUNCPROTO_H_\n\n#ifndef NeedFunctionPrototypes\n#define NeedFunctionPrototypes 1\n#endif /* NeedFunctionPrototypes */\n\n#ifndef NeedVarargsPrototypes\n#define NeedVarargsPrototypes 1\n#endif /* NeedVarargsPrototypes */\n\n#if NeedFunctionPrototypes\n\n#ifndef NeedNestedPrototypes\n#define NeedNestedPrototypes 1\n#endif /* NeedNestedPrototypes */\n\n#ifndef _Xconst\n#define _Xconst const\n#endif /* _Xconst */\n\n/* Function prototype configuration (see configure for more info) */\n#if !defined(NARROWPROTO) && \\\n    (defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))\n#define NARROWPROTO\n#endif\n#ifndef FUNCPROTO\n#define FUNCPROTO 15\n#endif\n\n#ifndef NeedWidePrototypes\n#ifdef NARROWPROTO\n#define NeedWidePrototypes 0\n#else\n#define NeedWidePrototypes 1\t\t/* default to make interropt. easier */\n#endif\n#endif /* NeedWidePrototypes */\n\n#endif /* NeedFunctionPrototypes */\n\n#ifndef _XFUNCPROTOBEGIN\n#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */\n#define _XFUNCPROTOBEGIN extern \"C\" {\t/* do not leave open across includes */\n#define _XFUNCPROTOEND }\n#else\n#define _XFUNCPROTOBEGIN\n#define _XFUNCPROTOEND\n#endif\n#endif /* _XFUNCPROTOBEGIN */\n\n/* http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute */\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n#ifndef __has_feature\n# define __has_feature(x) 0    /* Compatibility with non-clang compilers. */\n#endif\n#ifndef __has_extension\n# define __has_extension(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n/* Added in X11R6.9, so available in any version of modular xproto */\n#if __has_attribute(__sentinel__) || (defined(__GNUC__) && (__GNUC__ >= 4))\n# define _X_SENTINEL(x) __attribute__ ((__sentinel__(x)))\n#else\n# define _X_SENTINEL(x)\n#endif /* GNUC >= 4 */\n\n/* Added in X11R6.9, so available in any version of modular xproto */\n#if (__has_attribute(visibility) || (defined(__GNUC__) && (__GNUC__ >= 4))) \\\n    && !defined(__CYGWIN__) && !defined(__MINGW32__)\n# define _X_EXPORT      __attribute__((visibility(\"default\")))\n# define _X_HIDDEN      __attribute__((visibility(\"hidden\")))\n# define _X_INTERNAL    __attribute__((visibility(\"internal\")))\n#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)\n# define _X_EXPORT      __global\n# define _X_HIDDEN      __hidden\n# define _X_INTERNAL    __hidden\n#else /* not gcc >= 4 and not Sun Studio >= 8 */\n# define _X_EXPORT\n# define _X_HIDDEN\n# define _X_INTERNAL\n#endif /* GNUC >= 4 */\n\n/* Branch prediction hints for individual conditionals */\n/* requires xproto >= 7.0.9 */\n#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303)\n# define _X_LIKELY(x)   __builtin_expect(!!(x), 1)\n# define _X_UNLIKELY(x) __builtin_expect(!!(x), 0)\n#else /* not gcc >= 3.3 */\n# define _X_LIKELY(x)   (x)\n# define _X_UNLIKELY(x) (x)\n#endif\n\n/* Bulk branch prediction hints via marking error path functions as \"cold\" */\n/* requires xproto >= 7.0.25 */\n#if __has_attribute(__cold__) || \\\n    (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) /* 4.3+ */\n# define _X_COLD __attribute__((__cold__))\n#else\n# define _X_COLD /* nothing */\n#endif\n\n/* Added in X11R6.9, so available in any version of modular xproto */\n#if __has_attribute(deprecated) \\\n    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 301)) \\\n    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5130))\n# define _X_DEPRECATED  __attribute__((deprecated))\n#else /* not gcc >= 3.1 */\n# define _X_DEPRECATED\n#endif\n\n/* requires xproto >= 7.0.30 */\n#if __has_extension(attribute_deprecated_with_message) || \\\n                (defined(__GNUC__) && ((__GNUC__ >= 5) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))))\n# define _X_DEPRECATED_MSG(_msg) __attribute__((deprecated(_msg)))\n#else\n# define _X_DEPRECATED_MSG(_msg) _X_DEPRECATED\n#endif\n\n/* requires xproto >= 7.0.17 */\n#if __has_attribute(noreturn) \\\n    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \\\n    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))\n# define _X_NORETURN __attribute((noreturn))\n#else\n# define _X_NORETURN\n#endif /* GNUC  */\n\n/* Added in X11R6.9, so available in any version of modular xproto */\n#if __has_attribute(__format__) \\\n    || defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)\n# define _X_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))\n#else /* not gcc >= 2.3 */\n# define _X_ATTRIBUTE_PRINTF(x,y)\n#endif\n\n/* requires xproto >= 7.0.22 */\n#if __has_attribute(__unused__) \\\n    || defined(__GNUC__) &&  ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)\n#define _X_UNUSED  __attribute__((__unused__))\n#else\n#define _X_UNUSED  /* */\n#endif\n\n/* C99 keyword \"inline\" or equivalent extensions in pre-C99 compilers */\n/* requires xproto >= 7.0.9\n   (introduced in 7.0.8 but didn't support all compilers until 7.0.9) */\n#if defined(inline) /* assume autoconf set it correctly */ || \\\n   (defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L)) /* C99 */ || \\\n   (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550))\n# define _X_INLINE inline\n#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) /* gcc w/C89+extensions */\n# define _X_INLINE __inline__\n#else\n# define _X_INLINE\n#endif\n\n/* C99 keyword \"restrict\" or equivalent extensions in pre-C99 compilers */\n/* requires xproto >= 7.0.21 */\n#ifndef _X_RESTRICT_KYWD\n# if defined(restrict) /* assume autoconf set it correctly */ || \\\n    (defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L) /* C99 */ \\\n     && !defined(__cplusplus)) /* Workaround g++ issue on Solaris */\n#  define _X_RESTRICT_KYWD  restrict\n# elif defined(__GNUC__) && !defined(__STRICT_ANSI__) /* gcc w/C89+extensions */\n#  define _X_RESTRICT_KYWD __restrict__\n# else\n#  define _X_RESTRICT_KYWD\n# endif\n#endif\n\n/* requires xproto >= 7.0.30 */\n#if __has_attribute(no_sanitize_thread)\n# define _X_NOTSAN __attribute__((no_sanitize_thread))\n#else\n# define _X_NOTSAN\n#endif\n\n/* Mark a char array/pointer as not containing a NUL-terminated string */\n/* requires xproto >= 7.0.33 */\n#if __has_attribute(nonstring)\n# define _X_NONSTRING __attribute__((nonstring))\n#else\n# define _X_NONSTRING\n#endif\n\n#endif /* _XFUNCPROTO_H_ */\n"
  },
  {
    "path": "xlib/X11/Xlib.h",
    "content": "/*\n\nCopyright 1985, 1986, 1987, 1991, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n*/\n\n\n/*\n *\tXlib.h - Header definition and support file for the C subroutine\n *\tinterface library (Xlib) to the X Window System Protocol (V11).\n *\tStructures and symbols starting with \"_\" are private to the library.\n */\n#ifndef _X11_XLIB_H_\n#define _X11_XLIB_H_\n\n#define XlibSpecificationRelease 6\n\n#include <sys/types.h>\n\n#if defined(__SCO__) || defined(__UNIXWARE__)\n#include <stdint.h>\n#endif\n\n#include <X11/X.h>\n\n/* applications should not depend on these two headers being included! */\n#include <X11/Xfuncproto.h>\n\n#ifndef X_WCHAR\n#include <stddef.h>\n#else\n/* replace this with #include or typedef appropriate for your system */\ntypedef unsigned long wchar_t;\n#endif\n\n#ifndef EXTERN\n#   define EXTERN extern TCL_STORAGE_CLASS\n#endif\n#if defined(STATIC_BUILD) || !defined(_WIN32)\n# ifndef TCL_STORAGE_CLASS\n#   define TCL_STORAGE_CLASS\n# endif\n#elif defined(BUILD_tk)\n# undef TCL_STORAGE_CLASS\n# define TCL_STORAGE_CLASS __declspec(dllexport)\n#elif !defined(TCL_STORAGE_CLASS)\n# define TCL_STORAGE_CLASS __declspec(dllimport)\n#endif\n\nEXTERN int\n_Xmblen(\n    char *str,\n    int len\n    );\n\n/* API mentioning \"UTF8\" or \"utf8\" is an XFree86 extension, introduced in\n   November 2000. Its presence is indicated through the following macro. */\n#define X_HAVE_UTF8_STRING 1\n\n/* The Xlib structs are full of implicit padding to properly align members.\n   We can't clean that up without breaking ABI, so tell clang not to bother\n   complaining about it. */\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n#endif\n\ntypedef char *XPointer;\n\n#define Bool int\n#if defined(MAC_OSX_TK)\n/* Use define rather than typedef, since may need to undefine this later */\n#define Status int\n#else\ntypedef int Status;\n#endif\n#define True 1\n#define False 0\n\n#define QueuedAlready 0\n#define QueuedAfterReading 1\n#define QueuedAfterFlush 2\n\n#define ConnectionNumber(dpy) \t(((_XPrivDisplay)(dpy))->fd)\n#define RootWindow(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->root)\n#define DefaultScreen(dpy) \t(((_XPrivDisplay)(dpy))->default_screen)\n#define DefaultRootWindow(dpy) \t(ScreenOfDisplay(dpy,DefaultScreen(dpy))->root)\n#define DefaultVisual(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_visual)\n#define DefaultGC(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->default_gc)\n#define BlackPixel(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->black_pixel)\n#define WhitePixel(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->white_pixel)\n#define AllPlanes \t\t((unsigned long)~0L)\n#define QLength(dpy) \t\t(((_XPrivDisplay)(dpy))->qlen)\n#define DisplayWidth(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->width)\n#define DisplayHeight(dpy, scr) (ScreenOfDisplay(dpy,scr)->height)\n#define DisplayWidthMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mwidth)\n#define DisplayHeightMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mheight)\n#define DisplayPlanes(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth)\n#define DisplayCells(dpy, scr) \t(DefaultVisual(dpy,scr)->map_entries)\n#define ScreenCount(dpy) \t(((_XPrivDisplay)(dpy))->nscreens)\n#define ServerVendor(dpy) \t(((_XPrivDisplay)(dpy))->vendor)\n#define ProtocolVersion(dpy) \t(((_XPrivDisplay)(dpy))->proto_major_version)\n#define ProtocolRevision(dpy) \t(((_XPrivDisplay)(dpy))->proto_minor_version)\n#define VendorRelease(dpy) \t(((_XPrivDisplay)(dpy))->release)\n#define DisplayString(dpy) \t(((_XPrivDisplay)(dpy))->display_name)\n#define DefaultDepth(dpy, scr) \t(ScreenOfDisplay(dpy,scr)->root_depth)\n#define DefaultColormap(dpy, scr)(ScreenOfDisplay(dpy,scr)->cmap)\n#define BitmapUnit(dpy) \t(((_XPrivDisplay)(dpy))->bitmap_unit)\n#define BitmapBitOrder(dpy) \t(((_XPrivDisplay)(dpy))->bitmap_bit_order)\n#define BitmapPad(dpy) \t\t(((_XPrivDisplay)(dpy))->bitmap_pad)\n#define ImageByteOrder(dpy) \t(((_XPrivDisplay)(dpy))->byte_order)\n#define NextRequest(dpy)\t(((_XPrivDisplay)(dpy))->request + 1)\n#define LastKnownRequestProcessed(dpy)\t(((_XPrivDisplay)(dpy))->request)\n\n/* macros for screen oriented applications (toolkit) */\n#define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)(dpy))->screens[scr])\n#define DefaultScreenOfDisplay(dpy) ScreenOfDisplay(dpy,DefaultScreen(dpy))\n#define DisplayOfScreen(s)\t((s)->display)\n#define RootWindowOfScreen(s)\t((s)->root)\n#define BlackPixelOfScreen(s)\t((s)->black_pixel)\n#define WhitePixelOfScreen(s)\t((s)->white_pixel)\n#define DefaultColormapOfScreen(s)((s)->cmap)\n#define DefaultDepthOfScreen(s)\t((s)->root_depth)\n#define DefaultGCOfScreen(s)\t((s)->default_gc)\n#define DefaultVisualOfScreen(s)((s)->root_visual)\n#define WidthOfScreen(s)\t((s)->width)\n#define HeightOfScreen(s)\t((s)->height)\n#define WidthMMOfScreen(s)\t((s)->mwidth)\n#define HeightMMOfScreen(s)\t((s)->mheight)\n#define PlanesOfScreen(s)\t((s)->root_depth)\n#define CellsOfScreen(s)\t(DefaultVisualOfScreen((s))->map_entries)\n#define MinCmapsOfScreen(s)\t((s)->min_maps)\n#define MaxCmapsOfScreen(s)\t((s)->max_maps)\n#define DoesSaveUnders(s)\t((s)->save_unders)\n#define DoesBackingStore(s)\t((s)->backing_store)\n#define EventMaskOfScreen(s)\t((s)->root_input_mask)\n\n/*\n * Extensions need a way to hang private data on some structures.\n */\ntypedef struct _XExtData {\n\tint number;\t\t/* number returned by XRegisterExtension */\n\tstruct _XExtData *next;\t/* next item on list of data for structure */\n\tint (*free_private)(\t/* called to free private storage */\n\tstruct _XExtData *extension\n\t);\n\tXPointer private_data;\t/* data private to this extension. */\n} XExtData;\n\n/*\n * This file contains structures used by the extension mechanism.\n */\ntypedef struct {\t\t/* public to extension, cannot be changed */\n\tint extension;\t\t/* extension number */\n\tint major_opcode;\t/* major op-code assigned by server */\n\tint first_event;\t/* first event number for the extension */\n\tint first_error;\t/* first error number for the extension */\n} XExtCodes;\n\n/*\n * Data structure for retrieving info about pixmap formats.\n */\n\ntypedef struct {\n    int depth;\n    int bits_per_pixel;\n    int scanline_pad;\n} XPixmapFormatValues;\n\n\n/*\n * Data structure for setting graphics context.\n */\ntypedef struct {\n\tint function;\t\t/* logical operation */\n\tunsigned long plane_mask;/* plane mask */\n\tunsigned long foreground;/* foreground pixel */\n\tunsigned long background;/* background pixel */\n\tint line_width;\t\t/* line width */\n\tint line_style;\t \t/* LineSolid, LineOnOffDash, LineDoubleDash */\n\tint cap_style;\t  \t/* CapNotLast, CapButt,\n\t\t\t\t   CapRound, CapProjecting */\n\tint join_style;\t \t/* JoinMiter, JoinRound, JoinBevel */\n\tint fill_style;\t \t/* FillSolid, FillTiled,\n\t\t\t\t   FillStippled, FillOpaqueStippled */\n\tint fill_rule;\t  \t/* EvenOddRule, WindingRule */\n\tint arc_mode;\t\t/* ArcChord, ArcPieSlice */\n\tPixmap tile;\t\t/* tile pixmap for tiling operations */\n\tPixmap stipple;\t\t/* stipple 1 plane pixmap for stippling */\n\tint ts_x_origin;\t/* offset for tile or stipple operations */\n\tint ts_y_origin;\n        Font font;\t        /* default text font for text operations */\n\tint subwindow_mode;     /* ClipByChildren, IncludeInferiors */\n\tBool graphics_exposures;/* boolean, should exposures be generated */\n\tint clip_x_origin;\t/* origin for clipping */\n\tint clip_y_origin;\n\tPixmap clip_mask;\t/* bitmap clipping; other calls for rects */\n\tint dash_offset;\t/* patterned/dashed line information */\n\tchar dashes;\n} XGCValues;\n\n/*\n * Graphics context.  The contents of this structure are implementation\n * dependent.  A GC should be treated as opaque by application code.\n */\n\ntypedef XGCValues *GC;\n\n/*\n * Visual structure; contains information about colormapping possible.\n */\ntypedef struct {\n\tXExtData *ext_data;\t/* hook for extension to hang data */\n\tVisualID visualid;\t/* visual id of this visual */\n#if defined(__cplusplus) || defined(c_plusplus)\n\tint c_class;\t\t/* C++ class of screen (monochrome, etc.) */\n#else\n\tint class;\t\t/* class of screen (monochrome, etc.) */\n#endif\n\tunsigned long red_mask, green_mask, blue_mask;\t/* mask values */\n\tint bits_per_rgb;\t/* log base 2 of distinct color values */\n\tint map_entries;\t/* color map entries */\n} Visual;\n\n/*\n * Depth structure; contains information for each possible depth.\n */\ntypedef struct {\n\tint depth;\t\t/* this depth (Z) of the depth */\n\tint nvisuals;\t\t/* number of Visual types at this depth */\n\tVisual *visuals;\t/* list of visuals possible at this depth */\n} Depth;\n\n/*\n * Information about the screen.  The contents of this structure are\n * implementation dependent.  A Screen should be treated as opaque\n * by application code.\n */\n\nstruct _XDisplay;\t\t/* Forward declare before use for C++ */\n\ntypedef struct {\n\tXExtData *ext_data;\t/* hook for extension to hang data */\n\tstruct _XDisplay *display;/* back pointer to display structure */\n\tWindow root;\t\t/* Root window id. */\n\tint width, height;\t/* width and height of screen */\n\tint mwidth, mheight;\t/* width and height of  in millimeters */\n\tint ndepths;\t\t/* number of depths possible */\n\tDepth *depths;\t\t/* list of allowable depths on the screen */\n\tint root_depth;\t\t/* bits per pixel */\n\tVisual *root_visual;\t/* root visual */\n\tGC default_gc;\t\t/* GC for the root root visual */\n\tColormap cmap;\t\t/* default color map */\n\tunsigned long white_pixel;\n\tunsigned long black_pixel;\t/* White and Black pixel values */\n\tint max_maps, min_maps;\t/* max and min color maps */\n\tint backing_store;\t/* Never, WhenMapped, Always */\n\tBool save_unders;\n\tlong root_input_mask;\t/* initial root input mask */\n} Screen;\n\n/*\n * Format structure; describes ZFormat data the screen will understand.\n */\ntypedef struct {\n\tXExtData *ext_data;\t/* hook for extension to hang data */\n\tint depth;\t\t/* depth of this image format */\n\tint bits_per_pixel;\t/* bits/pixel at this depth */\n\tint scanline_pad;\t/* scanline must padded to this multiple */\n} ScreenFormat;\n\n/*\n * Data structure for setting window attributes.\n */\ntypedef struct {\n    Pixmap background_pixmap;\t/* background or None or ParentRelative */\n    unsigned long background_pixel;\t/* background pixel */\n    Pixmap border_pixmap;\t/* border of the window */\n    unsigned long border_pixel;\t/* border pixel value */\n    int bit_gravity;\t\t/* one of bit gravity values */\n    int win_gravity;\t\t/* one of the window gravity values */\n    int backing_store;\t\t/* NotUseful, WhenMapped, Always */\n    unsigned long backing_planes;/* planes to be preserved if possible */\n    unsigned long backing_pixel;/* value to use in restoring planes */\n    Bool save_under;\t\t/* should bits under be saved? (popups) */\n    long event_mask;\t\t/* set of events that should be saved */\n    long do_not_propagate_mask;\t/* set of events that should not propagate */\n    Bool override_redirect;\t/* boolean value for override-redirect */\n    Colormap colormap;\t\t/* color map to be associated with window */\n    Cursor cursor;\t\t/* cursor to be displayed (or None) */\n} XSetWindowAttributes;\n\ntypedef struct {\n    int x, y;\t\t\t/* location of window */\n    int width, height;\t\t/* width and height of window */\n    int border_width;\t\t/* border width of window */\n    int depth;          \t/* depth of window */\n    Visual *visual;\t\t/* the associated visual structure */\n    Window root;        \t/* root of screen containing window */\n#if defined(__cplusplus) || defined(c_plusplus)\n    int c_class;\t\t/* C++ InputOutput, InputOnly*/\n#else\n    int class;\t\t\t/* InputOutput, InputOnly*/\n#endif\n    int bit_gravity;\t\t/* one of bit gravity values */\n    int win_gravity;\t\t/* one of the window gravity values */\n    int backing_store;\t\t/* NotUseful, WhenMapped, Always */\n    unsigned long backing_planes;/* planes to be preserved if possible */\n    unsigned long backing_pixel;/* value to be used when restoring planes */\n    Bool save_under;\t\t/* boolean, should bits under be saved? */\n    Colormap colormap;\t\t/* color map to be associated with window */\n    Bool map_installed;\t\t/* boolean, is color map currently installed*/\n    int map_state;\t\t/* IsUnmapped, IsUnviewable, IsViewable */\n    long all_event_masks;\t/* set of events all people have interest in*/\n    long your_event_mask;\t/* my event mask */\n    long do_not_propagate_mask; /* set of events that should not propagate */\n    Bool override_redirect;\t/* boolean value for override-redirect */\n    Screen *screen;\t\t/* back pointer to correct screen */\n} XWindowAttributes;\n\n/*\n * Data structure for host setting; getting routines.\n *\n */\n\ntypedef struct {\n\tint family;\t\t/* for example FamilyInternet */\n\tint length;\t\t/* length of address, in bytes */\n\tchar *address;\t\t/* pointer to where to find the bytes */\n} XHostAddress;\n\n/*\n * Data structure for ServerFamilyInterpreted addresses in host routines\n */\ntypedef struct {\n\tint typelength;\t\t/* length of type string, in bytes */\n\tint valuelength;\t/* length of value string, in bytes */\n\tchar *type;\t\t/* pointer to where to find the type string */\n\tchar *value;\t\t/* pointer to where to find the address */\n} XServerInterpretedAddress;\n\n/*\n * Data structure for \"image\" data, used by image manipulation routines.\n */\ntypedef struct _XImage {\n    int width, height;\t\t/* size of image */\n    int xoffset;\t\t/* number of pixels offset in X direction */\n    int format;\t\t\t/* XYBitmap, XYPixmap, ZPixmap */\n    char *data;\t\t\t/* pointer to image data */\n    int byte_order;\t\t/* data byte order, LSBFirst, MSBFirst */\n    int bitmap_unit;\t\t/* quant. of scanline 8, 16, 32 */\n    int bitmap_bit_order;\t/* LSBFirst, MSBFirst */\n    int bitmap_pad;\t\t/* 8, 16, 32 either XY or ZPixmap */\n    int depth;\t\t\t/* depth of image */\n    int bytes_per_line;\t\t/* accelerator to next line */\n    int bits_per_pixel;\t\t/* bits per pixel (ZPixmap) */\n    unsigned long red_mask;\t/* bits in z arrangement */\n    unsigned long green_mask;\n    unsigned long blue_mask;\n    XPointer obdata;\t\t/* hook for the object routines to hang on */\n    struct funcs {\t\t/* image manipulation routines */\n\tstruct _XImage *(*create_image)(\n\t\tstruct _XDisplay* /* display */,\n\t\tVisual*\t\t/* visual */,\n\t\tunsigned int\t/* depth */,\n\t\tint\t\t/* format */,\n\t\tint\t\t/* offset */,\n\t\tchar*\t\t/* data */,\n\t\tunsigned int\t/* width */,\n\t\tunsigned int\t/* height */,\n\t\tint\t\t/* bitmap_pad */,\n\t\tint\t\t/* bytes_per_line */);\n\tint (*destroy_image)        (struct _XImage *);\n\tunsigned long (*get_pixel)  (struct _XImage *, int, int);\n\tint (*put_pixel)            (struct _XImage *, int, int, unsigned long);\n\tstruct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);\n\tint (*add_pixel)            (struct _XImage *, long);\n\t} f;\n} XImage;\n\n/*\n * Data structure for XReconfigureWindow\n */\ntypedef struct {\n    int x, y;\n    int width, height;\n    int border_width;\n    Window sibling;\n    int stack_mode;\n} XWindowChanges;\n\n/*\n * Data structure used by color operations\n */\ntypedef struct {\n\tunsigned long pixel;\n\tunsigned short red, green, blue;\n\tchar flags;  /* do_red, do_green, do_blue */\n\tchar pad;\n} XColor;\n\n/*\n * Data structures for graphics operations.  On most machines, these are\n * congruent with the wire protocol structures, so reformatting the data\n * can be avoided on these architectures.\n */\ntypedef struct {\n    short x1, y1, x2, y2;\n} XSegment;\n\ntypedef struct {\n    short x, y;\n} XPoint;\n\ntypedef struct {\n    short x, y;\n    unsigned short width, height;\n} XRectangle;\n\ntypedef struct {\n    short x, y;\n    unsigned short width, height;\n    short angle1, angle2;\n} XArc;\n\n\n/* Data structure for XChangeKeyboardControl */\n\ntypedef struct {\n        int key_click_percent;\n        int bell_percent;\n        int bell_pitch;\n        int bell_duration;\n        int led;\n        int led_mode;\n        int key;\n        int auto_repeat_mode;   /* On, Off, Default */\n} XKeyboardControl;\n\n/* Data structure for XGetKeyboardControl */\n\ntypedef struct {\n        int key_click_percent;\n\tint bell_percent;\n\tunsigned int bell_pitch, bell_duration;\n\tunsigned long led_mask;\n\tint global_auto_repeat;\n\tchar auto_repeats[32];\n} XKeyboardState;\n\n/* Data structure for XGetMotionEvents.  */\n\ntypedef struct {\n        Time time;\n\tshort x, y;\n} XTimeCoord;\n\n/* Data structure for X{Set,Get}ModifierMapping */\n\ntypedef struct {\n \tint max_keypermod;\t/* The server's max # of keys per modifier */\n \tKeyCode *modifiermap;\t/* An 8 by max_keypermod array of modifiers */\n} XModifierKeymap;\n\n\n/*\n * Display datatype maintaining display specific data.\n * The contents of this structure are implementation dependent.\n * A Display should be treated as opaque by application code.\n */\n#ifndef XLIB_ILLEGAL_ACCESS\ntypedef struct _XDisplay Display;\n#endif\n\nstruct _XPrivate;\t\t/* Forward declare before use for C++ */\nstruct _XrmHashBucketRec;\n\ntypedef struct\n#ifdef XLIB_ILLEGAL_ACCESS\n_XDisplay\n#endif\n{\n\tXExtData *ext_data;\t/* hook for extension to hang data */\n\tstruct _XPrivate *private1;\n\tint fd;\t\t\t/* Network socket. */\n\tint private2;\n\tint proto_major_version;/* major version of server's X protocol */\n\tint proto_minor_version;/* minor version of servers X protocol */\n\tchar *vendor;\t\t/* vendor of the server hardware */\n        XID private3;\n\tXID private4;\n\tXID private5;\n\tint private6;\n\tXID (*resource_alloc)(\t/* allocator function */\n\t\tstruct _XDisplay*\n\t);\n\tint byte_order;\t\t/* screen byte order, LSBFirst, MSBFirst */\n\tint bitmap_unit;\t/* padding and data requirements */\n\tint bitmap_pad;\t\t/* padding requirements on bitmaps */\n\tint bitmap_bit_order;\t/* LeastSignificant or MostSignificant */\n\tint nformats;\t\t/* number of pixmap formats in list */\n\tScreenFormat *pixmap_format;\t/* pixmap format list */\n\tint private8;\n\tint release;\t\t/* release of the server */\n\tstruct _XPrivate *private9, *private10;\n\tint qlen;\t\t/* Length of input event queue */\n\tunsigned long last_request_read; /* seq number of last event read */\n\tunsigned long request;\t/* sequence number of last request. */\n\tXPointer private11;\n\tXPointer private12;\n\tXPointer private13;\n\tXPointer private14;\n\tunsigned max_request_size; /* maximum number 32 bit words in request*/\n\tstruct _XrmHashBucketRec *db;\n\tint (*private15)(\n\t\tstruct _XDisplay*\n\t\t);\n\tchar *display_name;\t/* \"host:display\" string used on this connect*/\n\tint default_screen;\t/* default screen for operations */\n\tint nscreens;\t\t/* number of screens on this server*/\n\tScreen *screens;\t/* pointer to list of screens */\n\tunsigned long motion_buffer;\t/* size of motion buffer */\n\tunsigned long private16;\n\tint min_keycode;\t/* minimum defined keycode */\n\tint max_keycode;\t/* maximum defined keycode */\n\tXPointer private17;\n\tXPointer private18;\n\tint private19;\n\tchar *xdefaults;\t/* contents of defaults from server */\n\t/* there is more to this structure, but it is private to Xlib */\n}\n#ifdef XLIB_ILLEGAL_ACCESS\nDisplay,\n#endif\n*_XPrivDisplay;\n\n#undef _XEVENT_\n#ifndef _XEVENT_\n/*\n * Definitions of specific events.\n */\ntypedef struct {\n\tint type;\t\t/* of event */\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t        /* \"event\" window it is reported relative to */\n\tWindow root;\t        /* root window that the event occurred on */\n\tWindow subwindow;\t/* child window */\n\tTime time;\t\t/* milliseconds */\n\tint x, y;\t\t/* pointer x, y coordinates in event window */\n\tint x_root, y_root;\t/* coordinates relative to root */\n\tunsigned int state;\t/* key or button mask */\n\tunsigned int keycode;\t/* detail */\n\tBool same_screen;\t/* same screen flag */\n} XKeyEvent;\ntypedef XKeyEvent XKeyPressedEvent;\ntypedef XKeyEvent XKeyReleasedEvent;\n\ntypedef struct {\n\tint type;\t\t/* of event */\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t        /* \"event\" window it is reported relative to */\n\tWindow root;\t        /* root window that the event occurred on */\n\tWindow subwindow;\t/* child window */\n\tTime time;\t\t/* milliseconds */\n\tint x, y;\t\t/* pointer x, y coordinates in event window */\n\tint x_root, y_root;\t/* coordinates relative to root */\n\tunsigned int state;\t/* key or button mask */\n\tunsigned int button;\t/* detail */\n\tBool same_screen;\t/* same screen flag */\n} XButtonEvent;\ntypedef XButtonEvent XButtonPressedEvent;\ntypedef XButtonEvent XButtonReleasedEvent;\n\ntypedef struct {\n\tint type;\t\t/* of event */\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t        /* \"event\" window reported relative to */\n\tWindow root;\t        /* root window that the event occurred on */\n\tWindow subwindow;\t/* child window */\n\tTime time;\t\t/* milliseconds */\n\tint x, y;\t\t/* pointer x, y coordinates in event window */\n\tint x_root, y_root;\t/* coordinates relative to root */\n\tunsigned int state;\t/* key or button mask */\n\tchar is_hint;\t\t/* detail */\n\tBool same_screen;\t/* same screen flag */\n} XMotionEvent;\ntypedef XMotionEvent XPointerMovedEvent;\n\ntypedef struct {\n\tint type;\t\t/* of event */\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t        /* \"event\" window reported relative to */\n\tWindow root;\t        /* root window that the event occurred on */\n\tWindow subwindow;\t/* child window */\n\tTime time;\t\t/* milliseconds */\n\tint x, y;\t\t/* pointer x, y coordinates in event window */\n\tint x_root, y_root;\t/* coordinates relative to root */\n\tint mode;\t\t/* NotifyNormal, NotifyGrab, NotifyUngrab */\n\tint detail;\n\t/*\n\t * NotifyAncestor, NotifyVirtual, NotifyInferior,\n\t * NotifyNonlinear,NotifyNonlinearVirtual\n\t */\n\tBool same_screen;\t/* same screen flag */\n\tBool focus;\t\t/* boolean focus */\n\tunsigned int state;\t/* key or button mask */\n} XCrossingEvent;\ntypedef XCrossingEvent XEnterWindowEvent;\ntypedef XCrossingEvent XLeaveWindowEvent;\n\ntypedef struct {\n\tint type;\t\t/* FocusIn or FocusOut */\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t\t/* window of event */\n\tint mode;\t\t/* NotifyNormal, NotifyWhileGrabbed,\n\t\t\t\t   NotifyGrab, NotifyUngrab */\n\tint detail;\n\t/*\n\t * NotifyAncestor, NotifyVirtual, NotifyInferior,\n\t * NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer,\n\t * NotifyPointerRoot, NotifyDetailNone\n\t */\n} XFocusChangeEvent;\ntypedef XFocusChangeEvent XFocusInEvent;\ntypedef XFocusChangeEvent XFocusOutEvent;\n\n/* generated on EnterWindow and FocusIn  when KeyMapState selected */\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tchar key_vector[32];\n} XKeymapEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tint x, y;\n\tint width, height;\n\tint count;\t\t/* if non-zero, at least this many more */\n} XExposeEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tDrawable drawable;\n\tint x, y;\n\tint width, height;\n\tint count;\t\t/* if non-zero, at least this many more */\n\tint major_code;\t\t/* core is CopyArea or CopyPlane */\n\tint minor_code;\t\t/* not defined in the core */\n} XGraphicsExposeEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tDrawable drawable;\n\tint major_code;\t\t/* core is CopyArea or CopyPlane */\n\tint minor_code;\t\t/* not defined in the core */\n} XNoExposeEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tint state;\t\t/* Visibility state */\n} XVisibilityEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow parent;\t\t/* parent of the window */\n\tWindow window;\t\t/* window id of window created */\n\tint x, y;\t\t/* window location */\n\tint width, height;\t/* size of window */\n\tint border_width;\t/* border width */\n\tBool override_redirect;\t/* creation should be overridden */\n} XCreateWindowEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n} XDestroyWindowEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tBool from_configure;\n} XUnmapEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tBool override_redirect;\t/* boolean, is override set... */\n} XMapEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow parent;\n\tWindow window;\n} XMapRequestEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tWindow parent;\n\tint x, y;\n\tBool override_redirect;\n} XReparentEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tint x, y;\n\tint width, height;\n\tint border_width;\n\tWindow above;\n\tBool override_redirect;\n} XConfigureEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tint x, y;\n} XGravityEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tint width, height;\n} XResizeRequestEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow parent;\n\tWindow window;\n\tint x, y;\n\tint width, height;\n\tint border_width;\n\tWindow above;\n\tint detail;\t\t/* Above, Below, TopIf, BottomIf, Opposite */\n\tunsigned long value_mask;\n} XConfigureRequestEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow event;\n\tWindow window;\n\tint place;\t\t/* PlaceOnTop, PlaceOnBottom */\n} XCirculateEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow parent;\n\tWindow window;\n\tint place;\t\t/* PlaceOnTop, PlaceOnBottom */\n} XCirculateRequestEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tAtom atom;\n\tTime time;\n\tint state;\t\t/* NewValue, Deleted */\n} XPropertyEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tAtom selection;\n\tTime time;\n} XSelectionClearEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow owner;\n\tWindow requestor;\n\tAtom selection;\n\tAtom target;\n\tAtom property;\n\tTime time;\n} XSelectionRequestEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow requestor;\n\tAtom selection;\n\tAtom target;\n\tAtom property;\t\t/* ATOM or None */\n\tTime time;\n} XSelectionEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tColormap colormap;\t/* COLORMAP or None */\n#if defined(__cplusplus) || defined(c_plusplus)\n\tBool c_new;\t\t/* C++ */\n#else\n\tBool new;\n#endif\n\tint state;\t\t/* ColormapInstalled, ColormapUninstalled */\n} XColormapEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\n\tAtom message_type;\n\tint format;\n\tunion {\n\t\tchar b[20];\n\t\tshort s[10];\n\t\tlong l[5];\n\t\t} data;\n} XClientMessageEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;\t/* Display the event was read from */\n\tWindow window;\t\t/* unused */\n\tint request;\t\t/* one of MappingModifier, MappingKeyboard,\n\t\t\t\t   MappingPointer */\n\tint first_keycode;\t/* first keycode */\n\tint count;\t\t/* defines range of change w. first_keycode*/\n} XMappingEvent;\n\ntypedef struct {\n\tint type;\n\tDisplay *display;\t/* Display the event was read from */\n\tXID resourceid;\t\t/* resource id */\n\tunsigned long serial;\t/* serial number of failed request */\n\tunsigned char error_code;\t/* error code of failed request */\n\tunsigned char request_code;\t/* Major op-code of failed request */\n\tunsigned char minor_code;\t/* Minor op-code of failed request */\n} XErrorEvent;\n\ntypedef struct {\n\tint type;\n\tunsigned long serial;\t/* # of last request processed by server */\n\tBool send_event;\t/* true if this came from a SendEvent request */\n\tDisplay *display;/* Display the event was read from */\n\tWindow window;\t/* window on which event was requested in event mask */\n} XAnyEvent;\n\n\n/***************************************************************\n *\n * GenericEvent.  This event is the standard event for all newer extensions.\n */\n\ntypedef struct\n    {\n    int            type;         /* of event. Always GenericEvent */\n    unsigned long  serial;       /* # of last request processed */\n    Bool           send_event;   /* true if from SendEvent request */\n    Display        *display;     /* Display the event was read from */\n    int            extension;    /* major opcode of extension that caused the event */\n    int            evtype;       /* actual event type. */\n    } XGenericEvent;\n\ntypedef struct {\n    int            type;         /* of event. Always GenericEvent */\n    unsigned long  serial;       /* # of last request processed */\n    Bool           send_event;   /* true if from SendEvent request */\n    Display        *display;     /* Display the event was read from */\n    int            extension;    /* major opcode of extension that caused the event */\n    int            evtype;       /* actual event type. */\n    unsigned int   cookie;\n    void           *data;\n} XGenericEventCookie;\n\n/*\n * this union is defined so Xlib can always use the same sized\n * event structure internally, to avoid memory fragmentation.\n */\ntypedef union _XEvent {\n        int type;\t\t/* must not be changed; first element */\n\tXAnyEvent xany;\n\tXKeyEvent xkey;\n\tXButtonEvent xbutton;\n\tXMotionEvent xmotion;\n\tXCrossingEvent xcrossing;\n\tXFocusChangeEvent xfocus;\n\tXExposeEvent xexpose;\n\tXGraphicsExposeEvent xgraphicsexpose;\n\tXNoExposeEvent xnoexpose;\n\tXVisibilityEvent xvisibility;\n\tXCreateWindowEvent xcreatewindow;\n\tXDestroyWindowEvent xdestroywindow;\n\tXUnmapEvent xunmap;\n\tXMapEvent xmap;\n\tXMapRequestEvent xmaprequest;\n\tXReparentEvent xreparent;\n\tXConfigureEvent xconfigure;\n\tXGravityEvent xgravity;\n\tXResizeRequestEvent xresizerequest;\n\tXConfigureRequestEvent xconfigurerequest;\n\tXCirculateEvent xcirculate;\n\tXCirculateRequestEvent xcirculaterequest;\n\tXPropertyEvent xproperty;\n\tXSelectionClearEvent xselectionclear;\n\tXSelectionRequestEvent xselectionrequest;\n\tXSelectionEvent xselection;\n\tXColormapEvent xcolormap;\n\tXClientMessageEvent xclient;\n\tXMappingEvent xmapping;\n\tXErrorEvent xerror;\n\tXKeymapEvent xkeymap;\n\tXGenericEvent xgeneric;\n\tXGenericEventCookie xcookie;\n\tXID pad[24];\n} XEvent;\n#endif\n\n#define XAllocID(dpy) ((*((_XPrivDisplay)(dpy))->resource_alloc)((dpy)))\n\n/*\n * per character font metric information.\n */\ntypedef struct {\n    short\tlbearing;\t/* origin to left edge of raster */\n    short\trbearing;\t/* origin to right edge of raster */\n    short\twidth;\t\t/* advance to next char's origin */\n    short\tascent;\t\t/* baseline to top edge of raster */\n    short\tdescent;\t/* baseline to bottom edge of raster */\n    unsigned short attributes;\t/* per char flags (not predefined) */\n} XCharStruct;\n\n/*\n * To allow arbitrary information with fonts, there are additional properties\n * returned.\n */\ntypedef struct {\n    Atom name;\n    unsigned long card32;\n} XFontProp;\n\ntypedef struct {\n    XExtData\t*ext_data;\t/* hook for extension to hang data */\n    Font        fid;            /* Font id for this font */\n    unsigned\tdirection;\t/* hint about direction the font is painted */\n    unsigned\tmin_char_or_byte2;/* first character */\n    unsigned\tmax_char_or_byte2;/* last character */\n    unsigned\tmin_byte1;\t/* first row that exists */\n    unsigned\tmax_byte1;\t/* last row that exists */\n    Bool\tall_chars_exist;/* flag if all characters have non-zero size*/\n    unsigned\tdefault_char;\t/* char to print for undefined character */\n    int         n_properties;   /* how many properties there are */\n    XFontProp\t*properties;\t/* pointer to array of additional properties*/\n    XCharStruct\tmin_bounds;\t/* minimum bounds over all existing char*/\n    XCharStruct\tmax_bounds;\t/* maximum bounds over all existing char*/\n    XCharStruct\t*per_char;\t/* first_char to last_char information */\n    int\t\tascent;\t\t/* log. extent above baseline for spacing */\n    int\t\tdescent;\t/* log. descent below baseline for spacing */\n} XFontStruct;\n\n/*\n * PolyText routines take these as arguments.\n */\ntypedef struct {\n    char *chars;\t\t/* pointer to string */\n    int nchars;\t\t\t/* number of characters */\n    int delta;\t\t\t/* delta between strings */\n    Font font;\t\t\t/* font to print it in, None don't change */\n} XTextItem;\n\ntypedef struct {\t\t/* normal 16 bit characters are two bytes */\n    unsigned char byte1;\n    unsigned char byte2;\n} XChar2b;\n\ntypedef struct {\n    XChar2b *chars;\t\t/* two byte characters */\n    int nchars;\t\t\t/* number of characters */\n    int delta;\t\t\t/* delta between strings */\n    Font font;\t\t\t/* font to print it in, None don't change */\n} XTextItem16;\n\n\ntypedef union { Display *display;\n\t\tGC gc;\n\t\tVisual *visual;\n\t\tScreen *screen;\n\t\tScreenFormat *pixmap_format;\n\t\tXFontStruct *font; } XEDataObject;\n\ntypedef struct {\n    XRectangle      max_ink_extent;\n    XRectangle      max_logical_extent;\n} XFontSetExtents;\n\n/* unused:\ntypedef void (*XOMProc)();\n */\n\ntypedef struct _XOM *XOM;\ntypedef struct _XOC *XOC, *XFontSet;\n\ntypedef struct {\n    char           *chars;\n    int             nchars;\n    int             delta;\n    XFontSet        font_set;\n} XmbTextItem;\n\ntypedef struct {\n    wchar_t        *chars;\n    int             nchars;\n    int             delta;\n    XFontSet        font_set;\n} XwcTextItem;\n\n#define XNRequiredCharSet \"requiredCharSet\"\n#define XNQueryOrientation \"queryOrientation\"\n#define XNBaseFontName \"baseFontName\"\n#define XNOMAutomatic \"omAutomatic\"\n#define XNMissingCharSet \"missingCharSet\"\n#define XNDefaultString \"defaultString\"\n#define XNOrientation \"orientation\"\n#define XNDirectionalDependentDrawing \"directionalDependentDrawing\"\n#define XNContextualDrawing \"contextualDrawing\"\n#define XNFontInfo \"fontInfo\"\n\ntypedef struct {\n    int charset_count;\n    char **charset_list;\n} XOMCharSetList;\n\ntypedef enum {\n    XOMOrientation_LTR_TTB,\n    XOMOrientation_RTL_TTB,\n    XOMOrientation_TTB_LTR,\n    XOMOrientation_TTB_RTL,\n    XOMOrientation_Context\n} XOrientation;\n\ntypedef struct {\n    int num_orientation;\n    XOrientation *orientation;\t/* Input Text description */\n} XOMOrientation;\n\ntypedef struct {\n    int num_font;\n    XFontStruct **font_struct_list;\n    char **font_name_list;\n} XOMFontInfo;\n\ntypedef struct _XIM *XIM;\ntypedef struct _XIC *XIC;\n\ntypedef void (*XIMProc)(\n    XIM,\n    XPointer,\n    XPointer\n);\n\ntypedef Bool (*XICProc)(\n    XIC,\n    XPointer,\n    XPointer\n);\n\ntypedef void (*XIDProc)(\n    Display*,\n    XPointer,\n    XPointer\n);\n\ntypedef unsigned long XIMStyle;\n\ntypedef struct {\n    unsigned short count_styles;\n    XIMStyle *supported_styles;\n} XIMStyles;\n\n#define XIMPreeditArea\t\t0x0001L\n#define XIMPreeditCallbacks\t0x0002L\n#define XIMPreeditPosition\t0x0004L\n#define XIMPreeditNothing\t0x0008L\n#define XIMPreeditNone\t\t0x0010L\n#define XIMStatusArea\t\t0x0100L\n#define XIMStatusCallbacks\t0x0200L\n#define XIMStatusNothing\t0x0400L\n#define XIMStatusNone\t\t0x0800L\n\n#define XNVaNestedList \"XNVaNestedList\"\n#define XNQueryInputStyle \"queryInputStyle\"\n#define XNClientWindow \"clientWindow\"\n#define XNInputStyle \"inputStyle\"\n#define XNFocusWindow \"focusWindow\"\n#define XNResourceName \"resourceName\"\n#define XNResourceClass \"resourceClass\"\n#define XNGeometryCallback \"geometryCallback\"\n#define XNDestroyCallback \"destroyCallback\"\n#define XNFilterEvents \"filterEvents\"\n#define XNPreeditStartCallback \"preeditStartCallback\"\n#define XNPreeditDoneCallback \"preeditDoneCallback\"\n#define XNPreeditDrawCallback \"preeditDrawCallback\"\n#define XNPreeditCaretCallback \"preeditCaretCallback\"\n#define XNPreeditStateNotifyCallback \"preeditStateNotifyCallback\"\n#define XNPreeditAttributes \"preeditAttributes\"\n#define XNStatusStartCallback \"statusStartCallback\"\n#define XNStatusDoneCallback \"statusDoneCallback\"\n#define XNStatusDrawCallback \"statusDrawCallback\"\n#define XNStatusAttributes \"statusAttributes\"\n#define XNArea \"area\"\n#define XNAreaNeeded \"areaNeeded\"\n#define XNSpotLocation \"spotLocation\"\n#define XNColormap \"colorMap\"\n#define XNStdColormap \"stdColorMap\"\n#define XNForeground \"foreground\"\n#define XNBackground \"background\"\n#define XNBackgroundPixmap \"backgroundPixmap\"\n#define XNFontSet \"fontSet\"\n#define XNLineSpace \"lineSpace\"\n#define XNCursor \"cursor\"\n\n#define XNQueryIMValuesList \"queryIMValuesList\"\n#define XNQueryICValuesList \"queryICValuesList\"\n#define XNVisiblePosition \"visiblePosition\"\n#define XNR6PreeditCallback \"r6PreeditCallback\"\n#define XNStringConversionCallback \"stringConversionCallback\"\n#define XNStringConversion \"stringConversion\"\n#define XNResetState \"resetState\"\n#define XNHotKey \"hotKey\"\n#define XNHotKeyState \"hotKeyState\"\n#define XNPreeditState \"preeditState\"\n#define XNSeparatorofNestedList \"separatorofNestedList\"\n\n#define XBufferOverflow\t\t-1\n#define XLookupNone\t\t1\n#define XLookupChars\t\t2\n#define XLookupKeySym\t\t3\n#define XLookupBoth\t\t4\n\ntypedef void *XVaNestedList;\n\ntypedef struct {\n    XPointer client_data;\n    XIMProc callback;\n} XIMCallback;\n\ntypedef struct {\n    XPointer client_data;\n    XICProc callback;\n} XICCallback;\n\ntypedef unsigned long XIMFeedback;\n\n#define XIMReverse\t\t1L\n#define XIMUnderline\t\t(1L<<1)\n#define XIMHighlight\t\t(1L<<2)\n#define XIMPrimary\t \t(1L<<5)\n#define XIMSecondary\t\t(1L<<6)\n#define XIMTertiary\t \t(1L<<7)\n#define XIMVisibleToForward \t(1L<<8)\n#define XIMVisibleToBackword \t(1L<<9)\n#define XIMVisibleToCenter \t(1L<<10)\n\ntypedef struct _XIMText {\n    unsigned short length;\n    XIMFeedback *feedback;\n    Bool encoding_is_wchar;\n    union {\n\tchar *multi_byte;\n\twchar_t *wide_char;\n    } string;\n} XIMText;\n\ntypedef\tunsigned long\t XIMPreeditState;\n\n#define\tXIMPreeditUnKnown\t0L\n#define\tXIMPreeditEnable\t1L\n#define\tXIMPreeditDisable\t(1L<<1)\n\ntypedef\tstruct\t_XIMPreeditStateNotifyCallbackStruct {\n    XIMPreeditState state;\n} XIMPreeditStateNotifyCallbackStruct;\n\ntypedef\tunsigned long\t XIMResetState;\n\n#define\tXIMInitialState\t\t1L\n#define\tXIMPreserveState\t(1L<<1)\n\ntypedef unsigned long XIMStringConversionFeedback;\n\n#define\tXIMStringConversionLeftEdge\t(0x00000001)\n#define\tXIMStringConversionRightEdge\t(0x00000002)\n#define\tXIMStringConversionTopEdge\t(0x00000004)\n#define\tXIMStringConversionBottomEdge\t(0x00000008)\n#define\tXIMStringConversionConcealed\t(0x00000010)\n#define\tXIMStringConversionWrapped\t(0x00000020)\n\ntypedef struct _XIMStringConversionText {\n    unsigned short length;\n    XIMStringConversionFeedback *feedback;\n    Bool encoding_is_wchar;\n    union {\n\tchar *mbs;\n\twchar_t *wcs;\n    } string;\n} XIMStringConversionText;\n\ntypedef\tunsigned short\tXIMStringConversionPosition;\n\ntypedef\tunsigned short\tXIMStringConversionType;\n\n#define\tXIMStringConversionBuffer\t(0x0001)\n#define\tXIMStringConversionLine\t\t(0x0002)\n#define\tXIMStringConversionWord\t\t(0x0003)\n#define\tXIMStringConversionChar\t\t(0x0004)\n\ntypedef\tunsigned short\tXIMStringConversionOperation;\n\n#define\tXIMStringConversionSubstitution\t(0x0001)\n#define\tXIMStringConversionRetrieval\t(0x0002)\n\ntypedef enum {\n    XIMForwardChar, XIMBackwardChar,\n    XIMForwardWord, XIMBackwardWord,\n    XIMCaretUp, XIMCaretDown,\n    XIMNextLine, XIMPreviousLine,\n    XIMLineStart, XIMLineEnd,\n    XIMAbsolutePosition,\n    XIMDontChange\n} XIMCaretDirection;\n\ntypedef struct _XIMStringConversionCallbackStruct {\n    XIMStringConversionPosition position;\n    XIMCaretDirection direction;\n    XIMStringConversionOperation operation;\n    unsigned short factor;\n    XIMStringConversionText *text;\n} XIMStringConversionCallbackStruct;\n\ntypedef struct _XIMPreeditDrawCallbackStruct {\n    int caret;\t\t/* Cursor offset within pre-edit string */\n    int chg_first;\t/* Starting change position */\n    int chg_length;\t/* Length of the change in character count */\n    XIMText *text;\n} XIMPreeditDrawCallbackStruct;\n\ntypedef enum {\n    XIMIsInvisible,\t/* Disable caret feedback */\n    XIMIsPrimary,\t/* UI defined caret feedback */\n    XIMIsSecondary\t/* UI defined caret feedback */\n} XIMCaretStyle;\n\ntypedef struct _XIMPreeditCaretCallbackStruct {\n    int position;\t\t /* Caret offset within pre-edit string */\n    XIMCaretDirection direction; /* Caret moves direction */\n    XIMCaretStyle style;\t /* Feedback of the caret */\n} XIMPreeditCaretCallbackStruct;\n\ntypedef enum {\n    XIMTextType,\n    XIMBitmapType\n} XIMStatusDataType;\n\ntypedef struct _XIMStatusDrawCallbackStruct {\n    XIMStatusDataType type;\n    union {\n\tXIMText *text;\n\tPixmap  bitmap;\n    } data;\n} XIMStatusDrawCallbackStruct;\n\ntypedef struct _XIMHotKeyTrigger {\n    KeySym\t keysym;\n    int\t\t modifier;\n    int\t\t modifier_mask;\n} XIMHotKeyTrigger;\n\ntypedef struct _XIMHotKeyTriggers {\n    int\t\t\t num_hot_key;\n    XIMHotKeyTrigger\t*key;\n} XIMHotKeyTriggers;\n\ntypedef\tunsigned long\t XIMHotKeyState;\n\n#define\tXIMHotKeyStateON\t(0x0001L)\n#define\tXIMHotKeyStateOFF\t(0x0002L)\n\ntypedef struct {\n    unsigned short count_values;\n    char **supported_values;\n} XIMValuesList;\n\n_XFUNCPROTOBEGIN\n\n#if defined(WIN32) && !defined(_XLIBINT_)\n#define _Xdebug *_Xdebug_p\n#endif\n\nEXTERN int _Xdebug;\n\nEXTERN XFontStruct *XLoadQueryFont(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* name */\n);\n\nEXTERN XFontStruct *XQueryFont(\n    Display*\t\t/* display */,\n    XID\t\t\t/* font_ID */\n);\n\n\nEXTERN XTimeCoord *XGetMotionEvents(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Time\t\t/* start */,\n    Time\t\t/* stop */,\n    int*\t\t/* nevents_return */\n);\n\nEXTERN XModifierKeymap *XDeleteModifiermapEntry(\n    XModifierKeymap*\t/* modmap */,\n#if NeedWidePrototypes\n    unsigned int\t/* keycode_entry */,\n#else\n    KeyCode\t\t/* keycode_entry */,\n#endif\n    int\t\t\t/* modifier */\n);\n\nEXTERN XModifierKeymap\t*XGetModifierMapping(\n    Display*\t\t/* display */\n);\n\nEXTERN XModifierKeymap\t*XInsertModifiermapEntry(\n    XModifierKeymap*\t/* modmap */,\n#if NeedWidePrototypes\n    unsigned int\t/* keycode_entry */,\n#else\n    KeyCode\t\t/* keycode_entry */,\n#endif\n    int\t\t\t/* modifier */\n);\n\nEXTERN XModifierKeymap *XNewModifiermap(\n    int\t\t\t/* max_keys_per_mod */\n);\n\nEXTERN XImage *XCreateImage(\n    Display*\t\t/* display */,\n    Visual*\t\t/* visual */,\n    unsigned int\t/* depth */,\n    int\t\t\t/* format */,\n    int\t\t\t/* offset */,\n    char*\t\t/* data */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* bitmap_pad */,\n    int\t\t\t/* bytes_per_line */\n);\nEXTERN Status XInitImage(\n    XImage*\t\t/* image */\n);\nEXTERN XImage *XGetImage(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned long\t/* plane_mask */,\n    int\t\t\t/* format */\n);\nEXTERN XImage *XGetSubImage(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned long\t/* plane_mask */,\n    int\t\t\t/* format */,\n    XImage*\t\t/* dest_image */,\n    int\t\t\t/* dest_x */,\n    int\t\t\t/* dest_y */\n);\n\n/*\n * X function declarations.\n */\nEXTERN Display *XOpenDisplay(\n    _Xconst char*\t/* display_name */\n);\n\nEXTERN void XrmInitialize(\n    void\n);\n\nEXTERN char *XFetchBytes(\n    Display*\t\t/* display */,\n    int*\t\t/* nbytes_return */\n);\nEXTERN char *XFetchBuffer(\n    Display*\t\t/* display */,\n    int*\t\t/* nbytes_return */,\n    int\t\t\t/* buffer */\n);\nEXTERN char *XGetAtomName(\n    Display*\t\t/* display */,\n    Atom\t\t/* atom */\n);\nEXTERN Status XGetAtomNames(\n    Display*\t\t/* dpy */,\n    Atom*\t\t/* atoms */,\n    int\t\t\t/* count */,\n    char**\t\t/* names_return */\n);\nEXTERN char *XGetDefault(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* program */,\n    _Xconst char*\t/* option */\n);\nEXTERN char *XDisplayName(\n    _Xconst char*\t/* string */\n);\nEXTERN char *XKeysymToString(\n    KeySym\t\t/* keysym */\n);\n\nEXTERN int (*XSynchronize(\n    Display*\t\t/* display */,\n    Bool\t\t/* onoff */\n))(\n    Display*\t\t/* display */\n);\nEXTERN int (*XSetAfterFunction(\n    Display*\t\t/* display */,\n    int (*) (\n\t     Display*\t/* display */\n            )\t\t/* procedure */\n))(\n    Display*\t\t/* display */\n);\nEXTERN Atom XInternAtom(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* atom_name */,\n    Bool\t\t/* only_if_exists */\n);\nEXTERN Status XInternAtoms(\n    Display*\t\t/* dpy */,\n    char**\t\t/* names */,\n    int\t\t\t/* count */,\n    Bool\t\t/* onlyIfExists */,\n    Atom*\t\t/* atoms_return */\n);\nEXTERN Colormap XCopyColormapAndFree(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */\n);\nEXTERN Colormap XCreateColormap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Visual*\t\t/* visual */,\n    int\t\t\t/* alloc */\n);\nEXTERN Cursor XCreatePixmapCursor(\n    Display*\t\t/* display */,\n    Pixmap\t\t/* source */,\n    Pixmap\t\t/* mask */,\n    XColor*\t\t/* foreground_color */,\n    XColor*\t\t/* background_color */,\n    unsigned int\t/* x */,\n    unsigned int\t/* y */\n);\nEXTERN Cursor XCreateGlyphCursor(\n    Display*\t\t/* display */,\n    Font\t\t/* source_font */,\n    Font\t\t/* mask_font */,\n    unsigned int\t/* source_char */,\n    unsigned int\t/* mask_char */,\n    XColor _Xconst *\t/* foreground_color */,\n    XColor _Xconst *\t/* background_color */\n);\nEXTERN Cursor XCreateFontCursor(\n    Display*\t\t/* display */,\n    unsigned int\t/* shape */\n);\nEXTERN Font XLoadFont(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* name */\n);\nEXTERN GC XCreateGC(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    unsigned long\t/* valuemask */,\n    XGCValues*\t\t/* values */\n);\nEXTERN GContext XGContextFromGC(\n    GC\t\t\t/* gc */\n);\nEXTERN void XFlushGC(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */\n);\nEXTERN Pixmap XCreatePixmap(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int\t/* depth */\n);\nEXTERN Pixmap XCreateBitmapFromData(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    _Xconst char*\t/* data */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\nEXTERN Pixmap XCreatePixmapFromBitmapData(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    char*\t\t/* data */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned long\t/* fg */,\n    unsigned long\t/* bg */,\n    unsigned int\t/* depth */\n);\nEXTERN Window XCreateSimpleWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* parent */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int\t/* border_width */,\n    unsigned long\t/* border */,\n    unsigned long\t/* background */\n);\nEXTERN Window XGetSelectionOwner(\n    Display*\t\t/* display */,\n    Atom\t\t/* selection */\n);\nEXTERN Window XCreateWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* parent */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int\t/* border_width */,\n    int\t\t\t/* depth */,\n    unsigned int\t/* class */,\n    Visual*\t\t/* visual */,\n    unsigned long\t/* valuemask */,\n    XSetWindowAttributes*\t/* attributes */\n);\nEXTERN Colormap *XListInstalledColormaps(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int*\t\t/* num_return */\n);\nEXTERN char **XListFonts(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* pattern */,\n    int\t\t\t/* maxnames */,\n    int*\t\t/* actual_count_return */\n);\nEXTERN char **XListFontsWithInfo(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* pattern */,\n    int\t\t\t/* maxnames */,\n    int*\t\t/* count_return */,\n    XFontStruct**\t/* info_return */\n);\nEXTERN char **XGetFontPath(\n    Display*\t\t/* display */,\n    int*\t\t/* npaths_return */\n);\nEXTERN char **XListExtensions(\n    Display*\t\t/* display */,\n    int*\t\t/* nextensions_return */\n);\nEXTERN Atom *XListProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int*\t\t/* num_prop_return */\n);\nEXTERN XHostAddress *XListHosts(\n    Display*\t\t/* display */,\n    int*\t\t/* nhosts_return */,\n    Bool*\t\t/* state_return */\n);\nEXTERN _X_DEPRECATED KeySym XKeycodeToKeysym(\n    Display*\t\t/* display */,\n#if NeedWidePrototypes\n    unsigned int\t/* keycode */,\n#else\n    KeyCode\t\t/* keycode */,\n#endif\n    int\t\t\t/* index */\n);\nEXTERN KeySym XLookupKeysym(\n    XKeyEvent*\t\t/* key_event */,\n    int\t\t\t/* index */\n);\nEXTERN KeySym *XGetKeyboardMapping(\n    Display*\t\t/* display */,\n#if NeedWidePrototypes\n    unsigned int\t/* first_keycode */,\n#else\n    KeyCode\t\t/* first_keycode */,\n#endif\n    int\t\t\t/* keycode_count */,\n    int*\t\t/* keysyms_per_keycode_return */\n);\nEXTERN KeySym XStringToKeysym(\n    _Xconst char*\t/* string */\n);\nEXTERN long XMaxRequestSize(\n    Display*\t\t/* display */\n);\nEXTERN long XExtendedMaxRequestSize(\n    Display*\t\t/* display */\n);\nEXTERN char *XResourceManagerString(\n    Display*\t\t/* display */\n);\nEXTERN char *XScreenResourceString(\n\tScreen*\t\t/* screen */\n);\nEXTERN unsigned long XDisplayMotionBufferSize(\n    Display*\t\t/* display */\n);\nEXTERN VisualID XVisualIDFromVisual(\n    Visual*\t\t/* visual */\n);\n\n/* multithread routines */\n\nEXTERN Status XInitThreads(\n    void\n);\n\nEXTERN Status XFreeThreads(\n    void\n);\n\nEXTERN void XLockDisplay(\n    Display*\t\t/* display */\n);\n\nEXTERN void XUnlockDisplay(\n    Display*\t\t/* display */\n);\n\n/* routines for dealing with extensions */\n\nEXTERN XExtCodes *XInitExtension(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* name */\n);\n\nEXTERN XExtCodes *XAddExtension(\n    Display*\t\t/* display */\n);\nEXTERN XExtData *XFindOnExtensionList(\n    XExtData**\t\t/* structure */,\n    int\t\t\t/* number */\n);\nEXTERN XExtData **XEHeadOfExtensionList(\n    XEDataObject\t/* object */\n);\n\n/* these are routines for which there are also macros */\nEXTERN Window XRootWindow(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Window XDefaultRootWindow(\n    Display*\t\t/* display */\n);\nEXTERN Window XRootWindowOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN Visual *XDefaultVisual(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Visual *XDefaultVisualOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN GC XDefaultGC(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN GC XDefaultGCOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN unsigned long XBlackPixel(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN unsigned long XWhitePixel(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN unsigned long XAllPlanes(\n    void\n);\nEXTERN unsigned long XBlackPixelOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN unsigned long XWhitePixelOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN unsigned long XNextRequest(\n    Display*\t\t/* display */\n);\nEXTERN unsigned long XLastKnownRequestProcessed(\n    Display*\t\t/* display */\n);\nEXTERN char *XServerVendor(\n    Display*\t\t/* display */\n);\nEXTERN char *XDisplayString(\n    Display*\t\t/* display */\n);\nEXTERN Colormap XDefaultColormap(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Colormap XDefaultColormapOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN Display *XDisplayOfScreen(\n    Screen*\t\t/* screen */\n);\nEXTERN Screen *XScreenOfDisplay(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Screen *XDefaultScreenOfDisplay(\n    Display*\t\t/* display */\n);\nEXTERN long XEventMaskOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XScreenNumberOfScreen(\n    Screen*\t\t/* screen */\n);\n\ntypedef int (*XErrorHandler) (\t    /* WARNING, this type not in Xlib spec */\n    Display*\t\t/* display */,\n    XErrorEvent*\t/* error_event */\n);\n\nEXTERN XErrorHandler XSetErrorHandler (\n    XErrorHandler\t/* handler */\n);\n\n\ntypedef int (*XIOErrorHandler) (    /* WARNING, this type not in Xlib spec */\n    Display*\t\t/* display */\n);\n\nEXTERN XIOErrorHandler XSetIOErrorHandler (\n    XIOErrorHandler\t/* handler */\n);\n\ntypedef void (*XIOErrorExitHandler) ( /* WARNING, this type not in Xlib spec */\n    Display*,\t\t/* display */\n    void*\t\t/* user_data */\n);\n\nEXTERN void XSetIOErrorExitHandler (\n    Display*,\t\t\t/* display */\n    XIOErrorExitHandler,\t/* handler */\n    void*\t\t\t/* user_data */\n);\n\nEXTERN XPixmapFormatValues *XListPixmapFormats(\n    Display*\t\t/* display */,\n    int*\t\t/* count_return */\n);\nEXTERN int *XListDepths(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */,\n    int*\t\t/* count_return */\n);\n\n/* ICCCM routines for things that don't require special include files; */\n/* other declarations are given in Xutil.h                             */\nEXTERN Status XReconfigureWMWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* screen_number */,\n    unsigned int\t/* mask */,\n    XWindowChanges*\t/* changes */\n);\n\nEXTERN Status XGetWMProtocols(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom**\t\t/* protocols_return */,\n    int*\t\t/* count_return */\n);\nEXTERN Status XSetWMProtocols(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom*\t\t/* protocols */,\n    int\t\t\t/* count */\n);\nEXTERN Status XIconifyWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Status XWithdrawWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* screen_number */\n);\nEXTERN Status XGetCommand(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    char***\t\t/* argv_return */,\n    int*\t\t/* argc_return */\n);\nEXTERN Status XGetWMColormapWindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window**\t\t/* windows_return */,\n    int*\t\t/* count_return */\n);\nEXTERN Status XSetWMColormapWindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window*\t\t/* colormap_windows */,\n    int\t\t\t/* count */\n);\nEXTERN void XFreeStringList(\n    char**\t\t/* list */\n);\nEXTERN int XSetTransientForHint(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window\t\t/* prop_window */\n);\n\n/* The following are given in alphabetical order */\n\nEXTERN int XActivateScreenSaver(\n    Display*\t\t/* display */\n);\n\nEXTERN int XAddHost(\n    Display*\t\t/* display */,\n    XHostAddress*\t/* host */\n);\n\nEXTERN int XAddHosts(\n    Display*\t\t/* display */,\n    XHostAddress*\t/* hosts */,\n    int\t\t\t/* num_hosts */\n);\n\nEXTERN int XAddToExtensionList(\n    struct _XExtData**\t/* structure */,\n    XExtData*\t\t/* ext_data */\n);\n\nEXTERN int XAddToSaveSet(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN Status XAllocColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    XColor*\t\t/* screen_in_out */\n);\n\nEXTERN Status XAllocColorCells(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    Bool\t        /* contig */,\n    unsigned long*\t/* plane_masks_return */,\n    unsigned int\t/* nplanes */,\n    unsigned long*\t/* pixels_return */,\n    unsigned int \t/* npixels */\n);\n\nEXTERN Status XAllocColorPlanes(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    Bool\t\t/* contig */,\n    unsigned long*\t/* pixels_return */,\n    int\t\t\t/* ncolors */,\n    int\t\t\t/* nreds */,\n    int\t\t\t/* ngreens */,\n    int\t\t\t/* nblues */,\n    unsigned long*\t/* rmask_return */,\n    unsigned long*\t/* gmask_return */,\n    unsigned long*\t/* bmask_return */\n);\n\nEXTERN Status XAllocNamedColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    _Xconst char*\t/* color_name */,\n    XColor*\t\t/* screen_def_return */,\n    XColor*\t\t/* exact_def_return */\n);\n\nEXTERN int XAllowEvents(\n    Display*\t\t/* display */,\n    int\t\t\t/* event_mode */,\n    Time\t\t/* time */\n);\n\nEXTERN int XAutoRepeatOff(\n    Display*\t\t/* display */\n);\n\nEXTERN int XAutoRepeatOn(\n    Display*\t\t/* display */\n);\n\nEXTERN int XBell(\n    Display*\t\t/* display */,\n    int\t\t\t/* percent */\n);\n\nEXTERN int XBitmapBitOrder(\n    Display*\t\t/* display */\n);\n\nEXTERN int XBitmapPad(\n    Display*\t\t/* display */\n);\n\nEXTERN int XBitmapUnit(\n    Display*\t\t/* display */\n);\n\nEXTERN int XCellsOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XChangeActivePointerGrab(\n    Display*\t\t/* display */,\n    unsigned int\t/* event_mask */,\n    Cursor\t\t/* cursor */,\n    Time\t\t/* time */\n);\n\nEXTERN int XChangeGC(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long\t/* valuemask */,\n    XGCValues*\t\t/* values */\n);\n\nEXTERN int XChangeKeyboardControl(\n    Display*\t\t/* display */,\n    unsigned long\t/* value_mask */,\n    XKeyboardControl*\t/* values */\n);\n\nEXTERN int XChangeKeyboardMapping(\n    Display*\t\t/* display */,\n    int\t\t\t/* first_keycode */,\n    int\t\t\t/* keysyms_per_keycode */,\n    KeySym*\t\t/* keysyms */,\n    int\t\t\t/* num_codes */\n);\n\nEXTERN int XChangePointerControl(\n    Display*\t\t/* display */,\n    Bool\t\t/* do_accel */,\n    Bool\t\t/* do_threshold */,\n    int\t\t\t/* accel_numerator */,\n    int\t\t\t/* accel_denominator */,\n    int\t\t\t/* threshold */\n);\n\nEXTERN int XChangeProperty(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom\t\t/* property */,\n    Atom\t\t/* type */,\n    int\t\t\t/* format */,\n    int\t\t\t/* mode */,\n    _Xconst unsigned char*\t/* data */,\n    int\t\t\t/* nelements */\n);\n\nEXTERN int XChangeSaveSet(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* change_mode */\n);\n\nEXTERN int XChangeWindowAttributes(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned long\t/* valuemask */,\n    XSetWindowAttributes* /* attributes */\n);\n\nEXTERN Bool XCheckIfEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event_return */,\n    Bool (*) (\n\t       Display*\t\t\t/* display */,\n               XEvent*\t\t\t/* event */,\n               XPointer\t\t\t/* arg */\n             )\t\t/* predicate */,\n    XPointer\t\t/* arg */\n);\n\nEXTERN Bool XCheckMaskEvent(\n    Display*\t\t/* display */,\n    long\t\t/* event_mask */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN Bool XCheckTypedEvent(\n    Display*\t\t/* display */,\n    int\t\t\t/* event_type */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN Bool XCheckTypedWindowEvent(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* event_type */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN Bool XCheckWindowEvent(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    long\t\t/* event_mask */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN int XCirculateSubwindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* direction */\n);\n\nEXTERN int XCirculateSubwindowsDown(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XCirculateSubwindowsUp(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XClearArea(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    Bool\t\t/* exposures */\n);\n\nEXTERN int XClearWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XCloseDisplay(\n    Display*\t\t/* display */\n);\n\nEXTERN int XConfigureWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned int\t/* value_mask */,\n    XWindowChanges*\t/* values */\n);\n\nEXTERN int XConnectionNumber(\n    Display*\t\t/* display */\n);\n\nEXTERN int XConvertSelection(\n    Display*\t\t/* display */,\n    Atom\t\t/* selection */,\n    Atom \t\t/* target */,\n    Atom\t\t/* property */,\n    Window\t\t/* requestor */,\n    Time\t\t/* time */\n);\n\nEXTERN int XCopyArea(\n    Display*\t\t/* display */,\n    Drawable\t\t/* src */,\n    Drawable\t\t/* dest */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* src_x */,\n    int\t\t\t/* src_y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* dest_x */,\n    int\t\t\t/* dest_y */\n);\n\nEXTERN int XCopyGC(\n    Display*\t\t/* display */,\n    GC\t\t\t/* src */,\n    unsigned long\t/* valuemask */,\n    GC\t\t\t/* dest */\n);\n\nEXTERN int XCopyPlane(\n    Display*\t\t/* display */,\n    Drawable\t\t/* src */,\n    Drawable\t\t/* dest */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* src_x */,\n    int\t\t\t/* src_y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* dest_x */,\n    int\t\t\t/* dest_y */,\n    unsigned long\t/* plane */\n);\n\nEXTERN int XDefaultDepth(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDefaultDepthOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XDefaultScreen(\n    Display*\t\t/* display */\n);\n\nEXTERN int XDefineCursor(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Cursor\t\t/* cursor */\n);\n\nEXTERN int XDeleteProperty(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom\t\t/* property */\n);\n\nEXTERN int XDestroyWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XDestroySubwindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XDoesBackingStore(\n    Screen*\t\t/* screen */\n);\n\nEXTERN Bool XDoesSaveUnders(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XDisableAccessControl(\n    Display*\t\t/* display */\n);\n\n\nEXTERN int XDisplayCells(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDisplayHeight(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDisplayHeightMM(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDisplayKeycodes(\n    Display*\t\t/* display */,\n    int*\t\t/* min_keycodes_return */,\n    int*\t\t/* max_keycodes_return */\n);\n\nEXTERN int XDisplayPlanes(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDisplayWidth(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDisplayWidthMM(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */\n);\n\nEXTERN int XDrawArc(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* angle1 */,\n    int\t\t\t/* angle2 */\n);\n\nEXTERN int XDrawArcs(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XArc*\t\t/* arcs */,\n    int\t\t\t/* narcs */\n);\n\nEXTERN int XDrawImageString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* string */,\n    int\t\t\t/* length */\n);\n\nEXTERN int XDrawImageString16(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst XChar2b*\t/* string */,\n    int\t\t\t/* length */\n);\n\nEXTERN int XDrawLine(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x1 */,\n    int\t\t\t/* y1 */,\n    int\t\t\t/* x2 */,\n    int\t\t\t/* y2 */\n);\n\nEXTERN int XDrawLines(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XPoint*\t\t/* points */,\n    int\t\t\t/* npoints */,\n    int\t\t\t/* mode */\n);\n\nEXTERN int XDrawPoint(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */\n);\n\nEXTERN int XDrawPoints(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XPoint*\t\t/* points */,\n    int\t\t\t/* npoints */,\n    int\t\t\t/* mode */\n);\n\nEXTERN int XDrawRectangle(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XDrawRectangles(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XRectangle*\t\t/* rectangles */,\n    int\t\t\t/* nrectangles */\n);\n\nEXTERN int XDrawSegments(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XSegment*\t\t/* segments */,\n    int\t\t\t/* nsegments */\n);\n\nEXTERN int XDrawString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* string */,\n    int\t\t\t/* length */\n);\n\nEXTERN int XDrawString16(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst XChar2b*\t/* string */,\n    int\t\t\t/* length */\n);\n\nEXTERN int XDrawText(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    XTextItem*\t\t/* items */,\n    int\t\t\t/* nitems */\n);\n\nEXTERN int XDrawText16(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    XTextItem16*\t/* items */,\n    int\t\t\t/* nitems */\n);\n\nEXTERN int XEnableAccessControl(\n    Display*\t\t/* display */\n);\n\nEXTERN int XEventsQueued(\n    Display*\t\t/* display */,\n    int\t\t\t/* mode */\n);\n\nEXTERN Status XFetchName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    char**\t\t/* window_name_return */\n);\n\nEXTERN int XFillArc(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* angle1 */,\n    int\t\t\t/* angle2 */\n);\n\nEXTERN int XFillArcs(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XArc*\t\t/* arcs */,\n    int\t\t\t/* narcs */\n);\n\nEXTERN int XFillPolygon(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XPoint*\t\t/* points */,\n    int\t\t\t/* npoints */,\n    int\t\t\t/* shape */,\n    int\t\t\t/* mode */\n);\n\nEXTERN int XFillRectangle(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XFillRectangles(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XRectangle*\t\t/* rectangles */,\n    int\t\t\t/* nrectangles */\n);\n\nEXTERN int XFlush(\n    Display*\t\t/* display */\n);\n\nEXTERN int XForceScreenSaver(\n    Display*\t\t/* display */,\n    int\t\t\t/* mode */\n);\n\nEXTERN int XFree(\n    void*\t\t/* data */\n);\n\nEXTERN int XFreeColormap(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */\n);\n\nEXTERN int XFreeColors(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    unsigned long*\t/* pixels */,\n    int\t\t\t/* npixels */,\n    unsigned long\t/* planes */\n);\n\nEXTERN int XFreeCursor(\n    Display*\t\t/* display */,\n    Cursor\t\t/* cursor */\n);\n\nEXTERN int XFreeExtensionList(\n    char**\t\t/* list */\n);\n\nEXTERN int XFreeFont(\n    Display*\t\t/* display */,\n    XFontStruct*\t/* font_struct */\n);\n\nEXTERN int XFreeFontInfo(\n    char**\t\t/* names */,\n    XFontStruct*\t/* free_info */,\n    int\t\t\t/* actual_count */\n);\n\nEXTERN int XFreeFontNames(\n    char**\t\t/* list */\n);\n\nEXTERN int XFreeFontPath(\n    char**\t\t/* list */\n);\n\nEXTERN int XFreeGC(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */\n);\n\nEXTERN int XFreeModifiermap(\n    XModifierKeymap*\t/* modmap */\n);\n\nEXTERN int XFreePixmap(\n    Display*\t\t/* display */,\n    Pixmap\t\t/* pixmap */\n);\n\nEXTERN int XGeometry(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen */,\n    _Xconst char*\t/* position */,\n    _Xconst char*\t/* default_position */,\n    unsigned int\t/* bwidth */,\n    unsigned int\t/* fwidth */,\n    unsigned int\t/* fheight */,\n    int\t\t\t/* xadder */,\n    int\t\t\t/* yadder */,\n    int*\t\t/* x_return */,\n    int*\t\t/* y_return */,\n    int*\t\t/* width_return */,\n    int*\t\t/* height_return */\n);\n\nEXTERN int XGetErrorDatabaseText(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* name */,\n    _Xconst char*\t/* message */,\n    _Xconst char*\t/* default_string */,\n    char*\t\t/* buffer_return */,\n    int\t\t\t/* length */\n);\n\nEXTERN int XGetErrorText(\n    Display*\t\t/* display */,\n    int\t\t\t/* code */,\n    char*\t\t/* buffer_return */,\n    int\t\t\t/* length */\n);\n\nEXTERN Bool XGetFontProperty(\n    XFontStruct*\t/* font_struct */,\n    Atom\t\t/* atom */,\n    unsigned long*\t/* value_return */\n);\n\nEXTERN Status XGetGCValues(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long\t/* valuemask */,\n    XGCValues*\t\t/* values_return */\n);\n\nEXTERN Status XGetGeometry(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    Window*\t\t/* root_return */,\n    int*\t\t/* x_return */,\n    int*\t\t/* y_return */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */,\n    unsigned int*\t/* border_width_return */,\n    unsigned int*\t/* depth_return */\n);\n\nEXTERN Status XGetIconName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    char**\t\t/* icon_name_return */\n);\n\nEXTERN int XGetInputFocus(\n    Display*\t\t/* display */,\n    Window*\t\t/* focus_return */,\n    int*\t\t/* revert_to_return */\n);\n\nEXTERN int XGetKeyboardControl(\n    Display*\t\t/* display */,\n    XKeyboardState*\t/* values_return */\n);\n\nEXTERN int XGetPointerControl(\n    Display*\t\t/* display */,\n    int*\t\t/* accel_numerator_return */,\n    int*\t\t/* accel_denominator_return */,\n    int*\t\t/* threshold_return */\n);\n\nEXTERN int XGetPointerMapping(\n    Display*\t\t/* display */,\n    unsigned char*\t/* map_return */,\n    int\t\t\t/* nmap */\n);\n\nEXTERN int XGetScreenSaver(\n    Display*\t\t/* display */,\n    int*\t\t/* timeout_return */,\n    int*\t\t/* interval_return */,\n    int*\t\t/* prefer_blanking_return */,\n    int*\t\t/* allow_exposures_return */\n);\n\nEXTERN Status XGetTransientForHint(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window*\t\t/* prop_window_return */\n);\n\nEXTERN int XGetWindowProperty(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom\t\t/* property */,\n    long\t\t/* long_offset */,\n    long\t\t/* long_length */,\n    Bool\t\t/* delete */,\n    Atom\t\t/* req_type */,\n    Atom*\t\t/* actual_type_return */,\n    int*\t\t/* actual_format_return */,\n    unsigned long*\t/* nitems_return */,\n    unsigned long*\t/* bytes_after_return */,\n    unsigned char**\t/* prop_return */\n);\n\nEXTERN Status XGetWindowAttributes(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XWindowAttributes*\t/* window_attributes_return */\n);\n\nEXTERN int XGrabButton(\n    Display*\t\t/* display */,\n    unsigned int\t/* button */,\n    unsigned int\t/* modifiers */,\n    Window\t\t/* grab_window */,\n    Bool\t\t/* owner_events */,\n    unsigned int\t/* event_mask */,\n    int\t\t\t/* pointer_mode */,\n    int\t\t\t/* keyboard_mode */,\n    Window\t\t/* confine_to */,\n    Cursor\t\t/* cursor */\n);\n\nEXTERN int XGrabKey(\n    Display*\t\t/* display */,\n    int\t\t\t/* keycode */,\n    unsigned int\t/* modifiers */,\n    Window\t\t/* grab_window */,\n    Bool\t\t/* owner_events */,\n    int\t\t\t/* pointer_mode */,\n    int\t\t\t/* keyboard_mode */\n);\n\nEXTERN int XGrabKeyboard(\n    Display*\t\t/* display */,\n    Window\t\t/* grab_window */,\n    Bool\t\t/* owner_events */,\n    int\t\t\t/* pointer_mode */,\n    int\t\t\t/* keyboard_mode */,\n    Time\t\t/* time */\n);\n\nEXTERN int XGrabPointer(\n    Display*\t\t/* display */,\n    Window\t\t/* grab_window */,\n    Bool\t\t/* owner_events */,\n    unsigned int\t/* event_mask */,\n    int\t\t\t/* pointer_mode */,\n    int\t\t\t/* keyboard_mode */,\n    Window\t\t/* confine_to */,\n    Cursor\t\t/* cursor */,\n    Time\t\t/* time */\n);\n\nEXTERN int XGrabServer(\n    Display*\t\t/* display */\n);\n\nEXTERN int XHeightMMOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XHeightOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XIfEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event_return */,\n    Bool (*) (\n\t       Display*\t\t\t/* display */,\n               XEvent*\t\t\t/* event */,\n               XPointer\t\t\t/* arg */\n             )\t\t/* predicate */,\n    XPointer\t\t/* arg */\n);\n\nEXTERN int XImageByteOrder(\n    Display*\t\t/* display */\n);\n\nEXTERN int XInstallColormap(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */\n);\n\nEXTERN KeyCode XKeysymToKeycode(\n    Display*\t\t/* display */,\n    KeySym\t\t/* keysym */\n);\n\nEXTERN int XKillClient(\n    Display*\t\t/* display */,\n    XID\t\t\t/* resource */\n);\n\nEXTERN Status XLookupColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    _Xconst char*\t/* color_name */,\n    XColor*\t\t/* exact_def_return */,\n    XColor*\t\t/* screen_def_return */\n);\n\nEXTERN int XLowerWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XMapRaised(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XMapSubwindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XMapWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XMaskEvent(\n    Display*\t\t/* display */,\n    long\t\t/* event_mask */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN int XMaxCmapsOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XMinCmapsOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XMoveResizeWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XMoveWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */\n);\n\nEXTERN int XNextEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN int XNoOp(\n    Display*\t\t/* display */\n);\n\nEXTERN Status XParseColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    _Xconst char*\t/* spec */,\n    XColor*\t\t/* exact_def_return */\n);\n\nEXTERN int XParseGeometry(\n    _Xconst char*\t/* parsestring */,\n    int*\t\t/* x_return */,\n    int*\t\t/* y_return */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */\n);\n\nEXTERN int XPeekEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN int XPeekIfEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event_return */,\n    Bool (*) (\n\t       Display*\t\t/* display */,\n               XEvent*\t\t/* event */,\n               XPointer\t\t/* arg */\n             )\t\t/* predicate */,\n    XPointer\t\t/* arg */\n);\n\nEXTERN int XPending(\n    Display*\t\t/* display */\n);\n\nEXTERN int XPlanesOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XProtocolRevision(\n    Display*\t\t/* display */\n);\n\nEXTERN int XProtocolVersion(\n    Display*\t\t/* display */\n);\n\n\nEXTERN int XPutBackEvent(\n    Display*\t\t/* display */,\n    XEvent*\t\t/* event */\n);\n\nEXTERN int XPutImage(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    XImage*\t\t/* image */,\n    int\t\t\t/* src_x */,\n    int\t\t\t/* src_y */,\n    int\t\t\t/* dest_x */,\n    int\t\t\t/* dest_y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XQLength(\n    Display*\t\t/* display */\n);\n\nEXTERN Status XQueryBestCursor(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    unsigned int        /* width */,\n    unsigned int\t/* height */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */\n);\n\nEXTERN Status XQueryBestSize(\n    Display*\t\t/* display */,\n    int\t\t\t/* class */,\n    Drawable\t\t/* which_screen */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */\n);\n\nEXTERN Status XQueryBestStipple(\n    Display*\t\t/* display */,\n    Drawable\t\t/* which_screen */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */\n);\n\nEXTERN Status XQueryBestTile(\n    Display*\t\t/* display */,\n    Drawable\t\t/* which_screen */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */\n);\n\nEXTERN int XQueryColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    XColor*\t\t/* def_in_out */\n);\n\nEXTERN int XQueryColors(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    XColor*\t\t/* defs_in_out */,\n    int\t\t\t/* ncolors */\n);\n\nEXTERN Bool XQueryExtension(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* name */,\n    int*\t\t/* major_opcode_return */,\n    int*\t\t/* first_event_return */,\n    int*\t\t/* first_error_return */\n);\n\nEXTERN int XQueryKeymap(\n    Display*\t\t/* display */,\n    char [32]\t\t/* keys_return */\n);\n\nEXTERN Bool XQueryPointer(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window*\t\t/* root_return */,\n    Window*\t\t/* child_return */,\n    int*\t\t/* root_x_return */,\n    int*\t\t/* root_y_return */,\n    int*\t\t/* win_x_return */,\n    int*\t\t/* win_y_return */,\n    unsigned int*       /* mask_return */\n);\n\nEXTERN int XQueryTextExtents(\n    Display*\t\t/* display */,\n    XID\t\t\t/* font_ID */,\n    _Xconst char*\t/* string */,\n    int\t\t\t/* nchars */,\n    int*\t\t/* direction_return */,\n    int*\t\t/* font_ascent_return */,\n    int*\t\t/* font_descent_return */,\n    XCharStruct*\t/* overall_return */\n);\n\nEXTERN int XQueryTextExtents16(\n    Display*\t\t/* display */,\n    XID\t\t\t/* font_ID */,\n    _Xconst XChar2b*\t/* string */,\n    int\t\t\t/* nchars */,\n    int*\t\t/* direction_return */,\n    int*\t\t/* font_ascent_return */,\n    int*\t\t/* font_descent_return */,\n    XCharStruct*\t/* overall_return */\n);\n\nEXTERN Status XQueryTree(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window*\t\t/* root_return */,\n    Window*\t\t/* parent_return */,\n    Window**\t\t/* children_return */,\n    unsigned int*\t/* nchildren_return */\n);\n\nEXTERN int XRaiseWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XReadBitmapFile(\n    Display*\t\t/* display */,\n    Drawable \t\t/* d */,\n    _Xconst char*\t/* filename */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */,\n    Pixmap*\t\t/* bitmap_return */,\n    int*\t\t/* x_hot_return */,\n    int*\t\t/* y_hot_return */\n);\n\nEXTERN int XReadBitmapFileData(\n    _Xconst char*\t/* filename */,\n    unsigned int*\t/* width_return */,\n    unsigned int*\t/* height_return */,\n    unsigned char**\t/* data_return */,\n    int*\t\t/* x_hot_return */,\n    int*\t\t/* y_hot_return */\n);\n\nEXTERN int XRebindKeysym(\n    Display*\t\t/* display */,\n    KeySym\t\t/* keysym */,\n    KeySym*\t\t/* list */,\n    int\t\t\t/* mod_count */,\n    _Xconst unsigned char*\t/* string */,\n    int\t\t\t/* bytes_string */\n);\n\nEXTERN int XRecolorCursor(\n    Display*\t\t/* display */,\n    Cursor\t\t/* cursor */,\n    XColor*\t\t/* foreground_color */,\n    XColor*\t\t/* background_color */\n);\n\nEXTERN int XRefreshKeyboardMapping(\n    XMappingEvent*\t/* event_map */\n);\n\nEXTERN int XRemoveFromSaveSet(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XRemoveHost(\n    Display*\t\t/* display */,\n    XHostAddress*\t/* host */\n);\n\nEXTERN int XRemoveHosts(\n    Display*\t\t/* display */,\n    XHostAddress*\t/* hosts */,\n    int\t\t\t/* num_hosts */\n);\n\nEXTERN int XReparentWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Window\t\t/* parent */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */\n);\n\nEXTERN int XResetScreenSaver(\n    Display*\t\t/* display */\n);\n\nEXTERN int XResizeWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XRestackWindows(\n    Display*\t\t/* display */,\n    Window*\t\t/* windows */,\n    int\t\t\t/* nwindows */\n);\n\nEXTERN int XRotateBuffers(\n    Display*\t\t/* display */,\n    int\t\t\t/* rotate */\n);\n\nEXTERN int XRotateWindowProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Atom*\t\t/* properties */,\n    int\t\t\t/* num_prop */,\n    int\t\t\t/* npositions */\n);\n\nEXTERN int XScreenCount(\n    Display*\t\t/* display */\n);\n\nEXTERN int XSelectInput(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    long\t\t/* event_mask */\n);\n\nEXTERN Status XSendEvent(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Bool\t\t/* propagate */,\n    long\t\t/* event_mask */,\n    XEvent*\t\t/* event_send */\n);\n\nEXTERN int XSetAccessControl(\n    Display*\t\t/* display */,\n    int\t\t\t/* mode */\n);\n\nEXTERN int XSetArcMode(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* arc_mode */\n);\n\nEXTERN int XSetBackground(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long\t/* background */\n);\n\nEXTERN int XSetClipMask(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Pixmap\t\t/* pixmap */\n);\n\nEXTERN int XSetClipOrigin(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* clip_x_origin */,\n    int\t\t\t/* clip_y_origin */\n);\n\nEXTERN int XSetClipRectangles(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* clip_x_origin */,\n    int\t\t\t/* clip_y_origin */,\n    XRectangle*\t\t/* rectangles */,\n    int\t\t\t/* n */,\n    int\t\t\t/* ordering */\n);\n\nEXTERN int XSetCloseDownMode(\n    Display*\t\t/* display */,\n    int\t\t\t/* close_mode */\n);\n\nEXTERN int XSetCommand(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    char**\t\t/* argv */,\n    int\t\t\t/* argc */\n);\n\nEXTERN int XSetDashes(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* dash_offset */,\n    _Xconst char*\t/* dash_list */,\n    int\t\t\t/* n */\n);\n\nEXTERN int XSetFillRule(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* fill_rule */\n);\n\nEXTERN int XSetFillStyle(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* fill_style */\n);\n\nEXTERN int XSetFont(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Font\t\t/* font */\n);\n\nEXTERN int XSetFontPath(\n    Display*\t\t/* display */,\n    char**\t\t/* directories */,\n    int\t\t\t/* ndirs */\n);\n\nEXTERN int XSetForeground(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long\t/* foreground */\n);\n\nEXTERN int XSetFunction(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* function */\n);\n\nEXTERN int XSetGraphicsExposures(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Bool\t\t/* graphics_exposures */\n);\n\nEXTERN int XSetIconName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    _Xconst char*\t/* icon_name */\n);\n\nEXTERN int XSetInputFocus(\n    Display*\t\t/* display */,\n    Window\t\t/* focus */,\n    int\t\t\t/* revert_to */,\n    Time\t\t/* time */\n);\n\nEXTERN int XSetLineAttributes(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned int\t/* line_width */,\n    int\t\t\t/* line_style */,\n    int\t\t\t/* cap_style */,\n    int\t\t\t/* join_style */\n);\n\nEXTERN int XSetModifierMapping(\n    Display*\t\t/* display */,\n    XModifierKeymap*\t/* modmap */\n);\n\nEXTERN int XSetPlaneMask(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long\t/* plane_mask */\n);\n\nEXTERN int XSetPointerMapping(\n    Display*\t\t/* display */,\n    _Xconst unsigned char*\t/* map */,\n    int\t\t\t/* nmap */\n);\n\nEXTERN int XSetScreenSaver(\n    Display*\t\t/* display */,\n    int\t\t\t/* timeout */,\n    int\t\t\t/* interval */,\n    int\t\t\t/* prefer_blanking */,\n    int\t\t\t/* allow_exposures */\n);\n\nEXTERN int XSetSelectionOwner(\n    Display*\t\t/* display */,\n    Atom\t        /* selection */,\n    Window\t\t/* owner */,\n    Time\t\t/* time */\n);\n\nEXTERN int XSetState(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    unsigned long \t/* foreground */,\n    unsigned long\t/* background */,\n    int\t\t\t/* function */,\n    unsigned long\t/* plane_mask */\n);\n\nEXTERN int XSetStipple(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Pixmap\t\t/* stipple */\n);\n\nEXTERN int XSetSubwindowMode(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* subwindow_mode */\n);\n\nEXTERN int XSetTSOrigin(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* ts_x_origin */,\n    int\t\t\t/* ts_y_origin */\n);\n\nEXTERN int XSetTile(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Pixmap\t\t/* tile */\n);\n\nEXTERN int XSetWindowBackground(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned long\t/* background_pixel */\n);\n\nEXTERN int XSetWindowBackgroundPixmap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Pixmap\t\t/* background_pixmap */\n);\n\nEXTERN int XSetWindowBorder(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned long\t/* border_pixel */\n);\n\nEXTERN int XSetWindowBorderPixmap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Pixmap\t\t/* border_pixmap */\n);\n\nEXTERN int XSetWindowBorderWidth(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    unsigned int\t/* width */\n);\n\nEXTERN int XSetWindowColormap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    Colormap\t\t/* colormap */\n);\n\nEXTERN int XStoreBuffer(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* bytes */,\n    int\t\t\t/* nbytes */,\n    int\t\t\t/* buffer */\n);\n\nEXTERN int XStoreBytes(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* bytes */,\n    int\t\t\t/* nbytes */\n);\n\nEXTERN int XStoreColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    XColor*\t\t/* color */\n);\n\nEXTERN int XStoreColors(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    XColor*\t\t/* color */,\n    int\t\t\t/* ncolors */\n);\n\nEXTERN int XStoreName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    _Xconst char*\t/* window_name */\n);\n\nEXTERN int XStoreNamedColor(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */,\n    _Xconst char*\t/* color */,\n    unsigned long\t/* pixel */,\n    int\t\t\t/* flags */\n);\n\nEXTERN int XSync(\n    Display*\t\t/* display */,\n    Bool\t\t/* discard */\n);\n\nEXTERN int XTextExtents(\n    XFontStruct*\t/* font_struct */,\n    _Xconst char*\t/* string */,\n    int\t\t\t/* nchars */,\n    int*\t\t/* direction_return */,\n    int*\t\t/* font_ascent_return */,\n    int*\t\t/* font_descent_return */,\n    XCharStruct*\t/* overall_return */\n);\n\nEXTERN int XTextExtents16(\n    XFontStruct*\t/* font_struct */,\n    _Xconst XChar2b*\t/* string */,\n    int\t\t\t/* nchars */,\n    int*\t\t/* direction_return */,\n    int*\t\t/* font_ascent_return */,\n    int*\t\t/* font_descent_return */,\n    XCharStruct*\t/* overall_return */\n);\n\nEXTERN int XTextWidth(\n    XFontStruct*\t/* font_struct */,\n    _Xconst char*\t/* string */,\n    int\t\t\t/* count */\n);\n\nEXTERN int XTextWidth16(\n    XFontStruct*\t/* font_struct */,\n    _Xconst XChar2b*\t/* string */,\n    int\t\t\t/* count */\n);\n\nEXTERN Bool XTranslateCoordinates(\n    Display*\t\t/* display */,\n    Window\t\t/* src_w */,\n    Window\t\t/* dest_w */,\n    int\t\t\t/* src_x */,\n    int\t\t\t/* src_y */,\n    int*\t\t/* dest_x_return */,\n    int*\t\t/* dest_y_return */,\n    Window*\t\t/* child_return */\n);\n\nEXTERN int XUndefineCursor(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XUngrabButton(\n    Display*\t\t/* display */,\n    unsigned int\t/* button */,\n    unsigned int\t/* modifiers */,\n    Window\t\t/* grab_window */\n);\n\nEXTERN int XUngrabKey(\n    Display*\t\t/* display */,\n    int\t\t\t/* keycode */,\n    unsigned int\t/* modifiers */,\n    Window\t\t/* grab_window */\n);\n\nEXTERN int XUngrabKeyboard(\n    Display*\t\t/* display */,\n    Time\t\t/* time */\n);\n\nEXTERN int XUngrabPointer(\n    Display*\t\t/* display */,\n    Time\t\t/* time */\n);\n\nEXTERN int XUngrabServer(\n    Display*\t\t/* display */\n);\n\nEXTERN int XUninstallColormap(\n    Display*\t\t/* display */,\n    Colormap\t\t/* colormap */\n);\n\nEXTERN int XUnloadFont(\n    Display*\t\t/* display */,\n    Font\t\t/* font */\n);\n\nEXTERN int XUnmapSubwindows(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XUnmapWindow(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN int XVendorRelease(\n    Display*\t\t/* display */\n);\n\nEXTERN int XWarpPointer(\n    Display*\t\t/* display */,\n    Window\t\t/* src_w */,\n    Window\t\t/* dest_w */,\n    int\t\t\t/* src_x */,\n    int\t\t\t/* src_y */,\n    unsigned int\t/* src_width */,\n    unsigned int\t/* src_height */,\n    int\t\t\t/* dest_x */,\n    int\t\t\t/* dest_y */\n);\n\nEXTERN int XWidthMMOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XWidthOfScreen(\n    Screen*\t\t/* screen */\n);\n\nEXTERN int XWindowEvent(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    long\t\t/* event_mask */,\n    XEvent*\t\t/* event_return */\n);\n\nEXTERN int XWriteBitmapFile(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* filename */,\n    Pixmap\t\t/* bitmap */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */,\n    int\t\t\t/* x_hot */,\n    int\t\t\t/* y_hot */\n);\n\nEXTERN Bool XSupportsLocale (void);\n\nEXTERN char *XSetLocaleModifiers(\n    const char*\t\t/* modifier_list */\n);\n\nEXTERN XOM XOpenOM(\n    Display*\t\t\t/* display */,\n    struct _XrmHashBucketRec*\t/* rdb */,\n    _Xconst char*\t\t/* res_name */,\n    _Xconst char*\t\t/* res_class */\n);\n\nEXTERN Status XCloseOM(\n    XOM\t\t\t/* om */\n);\n\nEXTERN char *XSetOMValues(\n    XOM\t\t\t/* om */,\n    ...\n) _X_SENTINEL(0);\n\nEXTERN char *XGetOMValues(\n    XOM\t\t\t/* om */,\n    ...\n) _X_SENTINEL(0);\n\nEXTERN Display *XDisplayOfOM(\n    XOM\t\t\t/* om */\n);\n\nEXTERN char *XLocaleOfOM(\n    XOM\t\t\t/* om */\n);\n\nEXTERN XOC XCreateOC(\n    XOM\t\t\t/* om */,\n    ...\n) _X_SENTINEL(0);\n\nEXTERN void XDestroyOC(\n    XOC\t\t\t/* oc */\n);\n\nEXTERN XOM XOMOfOC(\n    XOC\t\t\t/* oc */\n);\n\nEXTERN char *XSetOCValues(\n    XOC\t\t\t/* oc */,\n    ...\n) _X_SENTINEL(0);\n\nEXTERN char *XGetOCValues(\n    XOC\t\t\t/* oc */,\n    ...\n) _X_SENTINEL(0);\n\nEXTERN XFontSet XCreateFontSet(\n    Display*\t\t/* display */,\n    _Xconst char*\t/* base_font_name_list */,\n    char***\t\t/* missing_charset_list */,\n    int*\t\t/* missing_charset_count */,\n    char**\t\t/* def_string */\n);\n\nEXTERN void XFreeFontSet(\n    Display*\t\t/* display */,\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN int XFontsOfFontSet(\n    XFontSet\t\t/* font_set */,\n    XFontStruct***\t/* font_struct_list */,\n    char***\t\t/* font_name_list */\n);\n\nEXTERN char *XBaseFontNameListOfFontSet(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN char *XLocaleOfFontSet(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN Bool XContextDependentDrawing(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN Bool XDirectionalDependentDrawing(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN Bool XContextualDrawing(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN XFontSetExtents *XExtentsOfFontSet(\n    XFontSet\t\t/* font_set */\n);\n\nEXTERN int XmbTextEscapement(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN int XwcTextEscapement(\n    XFontSet\t\t/* font_set */,\n    _Xconst wchar_t*\t/* text */,\n    int\t\t\t/* num_wchars */\n);\n\nEXTERN int Xutf8TextEscapement(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN int XmbTextExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN int XwcTextExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst wchar_t*\t/* text */,\n    int\t\t\t/* num_wchars */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN int Xutf8TextExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN Status XmbTextPerCharExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */,\n    XRectangle*\t\t/* ink_extents_buffer */,\n    XRectangle*\t\t/* logical_extents_buffer */,\n    int\t\t\t/* buffer_size */,\n    int*\t\t/* num_chars */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN Status XwcTextPerCharExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst wchar_t*\t/* text */,\n    int\t\t\t/* num_wchars */,\n    XRectangle*\t\t/* ink_extents_buffer */,\n    XRectangle*\t\t/* logical_extents_buffer */,\n    int\t\t\t/* buffer_size */,\n    int*\t\t/* num_chars */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN Status Xutf8TextPerCharExtents(\n    XFontSet\t\t/* font_set */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */,\n    XRectangle*\t\t/* ink_extents_buffer */,\n    XRectangle*\t\t/* logical_extents_buffer */,\n    int\t\t\t/* buffer_size */,\n    int*\t\t/* num_chars */,\n    XRectangle*\t\t/* overall_ink_return */,\n    XRectangle*\t\t/* overall_logical_return */\n);\n\nEXTERN void XmbDrawText(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    XmbTextItem*\t/* text_items */,\n    int\t\t\t/* nitems */\n);\n\nEXTERN void XwcDrawText(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    XwcTextItem*\t/* text_items */,\n    int\t\t\t/* nitems */\n);\n\nEXTERN void Xutf8DrawText(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    XmbTextItem*\t/* text_items */,\n    int\t\t\t/* nitems */\n);\n\nEXTERN void XmbDrawString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN void XwcDrawString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst wchar_t*\t/* text */,\n    int\t\t\t/* num_wchars */\n);\n\nEXTERN void Xutf8DrawString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN void XmbDrawImageString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN void XwcDrawImageString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst wchar_t*\t/* text */,\n    int\t\t\t/* num_wchars */\n);\n\nEXTERN void Xutf8DrawImageString(\n    Display*\t\t/* display */,\n    Drawable\t\t/* d */,\n    XFontSet\t\t/* font_set */,\n    GC\t\t\t/* gc */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    _Xconst char*\t/* text */,\n    int\t\t\t/* bytes_text */\n);\n\nEXTERN XIM XOpenIM(\n    Display*\t\t\t/* dpy */,\n    struct _XrmHashBucketRec*\t/* rdb */,\n    char*\t\t\t/* res_name */,\n    char*\t\t\t/* res_class */\n);\n\nEXTERN Status XCloseIM(\n    XIM /* im */\n);\n\nEXTERN char *XGetIMValues(\n    XIM /* im */, ...\n) _X_SENTINEL(0);\n\nEXTERN char *XSetIMValues(\n    XIM /* im */, ...\n) _X_SENTINEL(0);\n\nEXTERN Display *XDisplayOfIM(\n    XIM /* im */\n);\n\nEXTERN char *XLocaleOfIM(\n    XIM /* im*/\n);\n\nEXTERN XIC XCreateIC(\n    XIM /* im */, ...\n) _X_SENTINEL(0);\n\nEXTERN void XDestroyIC(\n    XIC /* ic */\n);\n\nEXTERN void XSetICFocus(\n    XIC /* ic */\n);\n\nEXTERN void XUnsetICFocus(\n    XIC /* ic */\n);\n\nEXTERN wchar_t *XwcResetIC(\n    XIC /* ic */\n);\n\nEXTERN char *XmbResetIC(\n    XIC /* ic */\n);\n\nEXTERN char *Xutf8ResetIC(\n    XIC /* ic */\n);\n\nEXTERN char *XSetICValues(\n    XIC /* ic */, ...\n) _X_SENTINEL(0);\n\nEXTERN char *XGetICValues(\n    XIC /* ic */, ...\n) _X_SENTINEL(0);\n\nEXTERN XIM XIMOfIC(\n    XIC /* ic */\n);\n\nEXTERN Bool XFilterEvent(\n    XEvent*\t/* event */,\n    Window\t/* window */\n);\n\nEXTERN int XmbLookupString(\n    XIC\t\t\t/* ic */,\n    XKeyPressedEvent*\t/* event */,\n    char*\t\t/* buffer_return */,\n    int\t\t\t/* bytes_buffer */,\n    KeySym*\t\t/* keysym_return */,\n    Status*\t\t/* status_return */\n);\n\nEXTERN int XwcLookupString(\n    XIC\t\t\t/* ic */,\n    XKeyPressedEvent*\t/* event */,\n    wchar_t*\t\t/* buffer_return */,\n    int\t\t\t/* wchars_buffer */,\n    KeySym*\t\t/* keysym_return */,\n    Status*\t\t/* status_return */\n);\n\nEXTERN int Xutf8LookupString(\n    XIC\t\t\t/* ic */,\n    XKeyPressedEvent*\t/* event */,\n    char*\t\t/* buffer_return */,\n    int\t\t\t/* bytes_buffer */,\n    KeySym*\t\t/* keysym_return */,\n    Status*\t\t/* status_return */\n);\n\nEXTERN XVaNestedList XVaCreateNestedList(\n    int /*unused*/, ...\n) _X_SENTINEL(0);\n\n/* internal connections for IMs */\n\nEXTERN Bool XRegisterIMInstantiateCallback(\n    Display*\t\t\t/* dpy */,\n    struct _XrmHashBucketRec*\t/* rdb */,\n    char*\t\t\t/* res_name */,\n    char*\t\t\t/* res_class */,\n    XIDProc\t\t\t/* callback */,\n    XPointer\t\t\t/* client_data */\n);\n\nEXTERN Bool XUnregisterIMInstantiateCallback(\n    Display*\t\t\t/* dpy */,\n    struct _XrmHashBucketRec*\t/* rdb */,\n    char*\t\t\t/* res_name */,\n    char*\t\t\t/* res_class */,\n    XIDProc\t\t\t/* callback */,\n    XPointer\t\t\t/* client_data */\n);\n\ntypedef void (*XConnectionWatchProc)(\n    Display*\t\t\t/* dpy */,\n    XPointer\t\t\t/* client_data */,\n    int\t\t\t\t/* fd */,\n    Bool\t\t\t/* opening */,\t /* open or close flag */\n    XPointer*\t\t\t/* watch_data */ /* open sets, close uses */\n);\n\n\nEXTERN Status XInternalConnectionNumbers(\n    Display*\t\t\t/* dpy */,\n    int**\t\t\t/* fd_return */,\n    int*\t\t\t/* count_return */\n);\n\nEXTERN void XProcessInternalConnection(\n    Display*\t\t\t/* dpy */,\n    int\t\t\t\t/* fd */\n);\n\nEXTERN Status XAddConnectionWatch(\n    Display*\t\t\t/* dpy */,\n    XConnectionWatchProc\t/* callback */,\n    XPointer\t\t\t/* client_data */\n);\n\nEXTERN void XRemoveConnectionWatch(\n    Display*\t\t\t/* dpy */,\n    XConnectionWatchProc\t/* callback */,\n    XPointer\t\t\t/* client_data */\n);\n\nEXTERN void XSetAuthorization(\n    char *\t\t\t/* name */,\n    int\t\t\t\t/* namelen */,\n    char *\t\t\t/* data */,\n    int\t\t\t\t/* datalen */\n);\n\nEXTERN int _Xmbtowc(\n    wchar_t *\t\t\t/* wstr */,\n    char *\t\t\t/* str */,\n    int\t\t\t\t/* len */\n);\n\nEXTERN int _Xwctomb(\n    char *\t\t\t/* str */,\n    wchar_t\t\t\t/* wc */\n);\n\nEXTERN Bool XGetEventData(\n    Display*\t\t\t/* dpy */,\n    XGenericEventCookie*\t/* cookie*/\n);\n\nEXTERN void XFreeEventData(\n    Display*\t\t\t/* dpy */,\n    XGenericEventCookie*\t/* cookie*/\n);\n\n#include \"tkIntXlibDecls.h\"  /* IWYU pragma: export */\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n_XFUNCPROTOEND\n\n#endif /* _X11_XLIB_H_ */\n"
  },
  {
    "path": "xlib/X11/Xutil.h",
    "content": "\n/***********************************************************\n\nCopyright 1987, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n#ifndef _X11_XUTIL_H_\n#define _X11_XUTIL_H_\n\n/* You must include <X11/Xlib.h> before including this file */\n#include <X11/Xlib.h>\n#include <X11/keysym.h>\n\n/* The Xlib structs are full of implicit padding to properly align members.\n   We can't clean that up without breaking ABI, so tell clang not to bother\n   complaining about it. */\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n#endif\n\n/*\n * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding\n * value (x, y, width, height) was found in the parsed string.\n */\n#define NoValue\t\t0x0000\n#define XValue  \t0x0001\n#define YValue\t\t0x0002\n#define WidthValue  \t0x0004\n#define HeightValue  \t0x0008\n#define AllValues \t0x000F\n#define XNegative \t0x0010\n#define YNegative \t0x0020\n\n/*\n * new version containing base_width, base_height, and win_gravity fields;\n * used with WM_NORMAL_HINTS.\n */\ntypedef struct {\n    \tlong flags;\t/* marks which fields in this structure are defined */\n\tint x, y;\t\t/* obsolete for new window mgrs, but clients */\n\tint width, height;\t/* should set so old wm's don't mess up */\n\tint min_width, min_height;\n\tint max_width, max_height;\n    \tint width_inc, height_inc;\n\tstruct {\n\t\tint x;\t/* numerator */\n\t\tint y;\t/* denominator */\n\t} min_aspect, max_aspect;\n\tint base_width, base_height;\t\t/* added by ICCCM version 1 */\n\tint win_gravity;\t\t\t/* added by ICCCM version 1 */\n} XSizeHints;\n\n/*\n * The next block of definitions are for window manager properties that\n * clients and applications use for communication.\n */\n\n/* flags argument in size hints */\n#define USPosition\t(1L << 0) /* user specified x, y */\n#define USSize\t\t(1L << 1) /* user specified width, height */\n\n#define PPosition\t(1L << 2) /* program specified position */\n#define PSize\t\t(1L << 3) /* program specified size */\n#define PMinSize\t(1L << 4) /* program specified minimum size */\n#define PMaxSize\t(1L << 5) /* program specified maximum size */\n#define PResizeInc\t(1L << 6) /* program specified resize increments */\n#define PAspect\t\t(1L << 7) /* program specified min and max aspect ratios */\n#define PBaseSize\t(1L << 8) /* program specified base for incrementing */\n#define PWinGravity\t(1L << 9) /* program specified window gravity */\n\n/* obsolete */\n#define PAllHints (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect)\n\n\n\ntypedef struct {\n\tlong flags;\t/* marks which fields in this structure are defined */\n\tBool input;\t/* does this application rely on the window manager to\n\t\t\tget keyboard input? */\n\tint initial_state;\t/* see below */\n\tPixmap icon_pixmap;\t/* pixmap to be used as icon */\n\tWindow icon_window; \t/* window to be used as icon */\n\tint icon_x, icon_y; \t/* initial position of icon */\n\tPixmap icon_mask;\t/* icon mask bitmap */\n\tXID window_group;\t/* id of related window group */\n\t/* this structure may be extended in the future */\n} XWMHints;\n\n/* definition for flags of XWMHints */\n\n#define InputHint \t\t(1L << 0)\n#define StateHint \t\t(1L << 1)\n#define IconPixmapHint\t\t(1L << 2)\n#define IconWindowHint\t\t(1L << 3)\n#define IconPositionHint \t(1L << 4)\n#define IconMaskHint\t\t(1L << 5)\n#define WindowGroupHint\t\t(1L << 6)\n#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint| \\\nIconPositionHint|IconMaskHint|WindowGroupHint)\n#define XUrgencyHint\t\t(1L << 8)\n\n/* definitions for initial window state */\n#define WithdrawnState 0\t/* for windows that are not mapped */\n#define NormalState 1\t/* most applications want to start this way */\n#define IconicState 3\t/* application wants to start as an icon */\n\n/*\n * Obsolete states no longer defined by ICCCM\n */\n#define DontCareState 0\t/* don't know or care */\n#define ZoomState 2\t/* application wants to start zoomed */\n#define InactiveState 4\t/* application believes it is seldom used; */\n\t\t\t/* some wm's may put it on inactive menu */\n\n\n/*\n * new structure for manipulating TEXT properties; used with WM_NAME,\n * WM_ICON_NAME, WM_CLIENT_MACHINE, and WM_COMMAND.\n */\ntypedef struct {\n    unsigned char *value;\t\t/* same as Property routines */\n    Atom encoding;\t\t\t/* prop type */\n    int format;\t\t\t\t/* prop data format: 8, 16, or 32 */\n    unsigned long nitems;\t\t/* number of data items in value */\n} XTextProperty;\n\n#define XNoMemory -1\n#define XLocaleNotSupported -2\n#define XConverterNotFound -3\n\ntypedef enum {\n    XStringStyle,\t\t/* STRING */\n    XCompoundTextStyle,\t\t/* COMPOUND_TEXT */\n    XTextStyle,\t\t\t/* text in owner's encoding (current locale)*/\n    XStdICCTextStyle,\t\t/* STRING, else COMPOUND_TEXT */\n    /* The following is an XFree86 extension, introduced in November 2000 */\n    XUTF8StringStyle\t\t/* UTF8_STRING */\n} XICCEncodingStyle;\n\ntypedef struct {\n\tint min_width, min_height;\n\tint max_width, max_height;\n\tint width_inc, height_inc;\n} XIconSize;\n\ntypedef struct {\n\tchar *res_name;\n\tchar *res_class;\n} XClassHint;\n\n#ifndef EXTERN\n#   define EXTERN extern TCL_STORAGE_CLASS\n#endif\n#if defined(STATIC_BUILD) || !defined(_WIN32)\n# ifndef TCL_STORAGE_CLASS\n#   define TCL_STORAGE_CLASS\n# endif\n#elif defined(BUILD_tk)\n# undef TCL_STORAGE_CLASS\n# define TCL_STORAGE_CLASS __declspec(dllexport)\n#elif !defined(TCL_STORAGE_CLASS)\n# define TCL_STORAGE_CLASS __declspec(dllimport)\n#endif\n\n#ifdef XUTIL_DEFINE_FUNCTIONS\nEXTERN int XDestroyImage(\n        XImage *ximage);\nEXTERN unsigned long XGetPixel(\n        XImage *ximage,\n        int x, int y);\nEXTERN int XPutPixel(\n        XImage *ximage,\n        int x, int y,\n        unsigned long pixel);\nEXTERN XImage *XSubImage(\n        XImage *ximage,\n        int x, int y,\n        unsigned int width, unsigned int height);\nEXTERN int XAddPixel(\n        XImage *ximage,\n        long value);\n#else\n/*\n * These macros are used to give some sugar to the image routines so that\n * naive people are more comfortable with them.\n */\n#define XDestroyImage(ximage) \\\n\t((*((ximage)->f.destroy_image))((ximage)))\n#define XGetPixel(ximage, x, y) \\\n\t((*((ximage)->f.get_pixel))((ximage), (x), (y)))\n#define XPutPixel(ximage, x, y, pixel) \\\n\t((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel)))\n#define XSubImage(ximage, x, y, width, height)  \\\n\t((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height)))\n#define XAddPixel(ximage, value) \\\n\t((*((ximage)->f.add_pixel))((ximage), (value)))\n#endif\n\n/*\n * Compose sequence status structure, used in calling XLookupString.\n */\ntypedef struct _XComposeStatus {\n    XPointer compose_ptr;\t/* state table pointer */\n    int chars_matched;\t\t/* match state */\n} XComposeStatus;\n\n/*\n * Keysym macros, used on Keysyms to test for classes of symbols\n */\n#define IsKeypadKey(keysym) \\\n  (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal))\n\n#define IsPrivateKeypadKey(keysym) \\\n  (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))\n\n#define IsCursorKey(keysym) \\\n  (((KeySym)(keysym) >= XK_Home)     && ((KeySym)(keysym) <  XK_Select))\n\n#define IsPFKey(keysym) \\\n  (((KeySym)(keysym) >= XK_KP_F1)     && ((KeySym)(keysym) <= XK_KP_F4))\n\n#define IsFunctionKey(keysym) \\\n  (((KeySym)(keysym) >= XK_F1)       && ((KeySym)(keysym) <= XK_F35))\n\n#define IsMiscFunctionKey(keysym) \\\n  (((KeySym)(keysym) >= XK_Select)   && ((KeySym)(keysym) <= XK_Break))\n\n#ifdef XK_XKB_KEYS\n#define IsModifierKey(keysym) \\\n  ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \\\n   || (((KeySym)(keysym) >= XK_ISO_Lock) && \\\n       ((KeySym)(keysym) <= XK_ISO_Level5_Lock)) \\\n   || ((KeySym)(keysym) == XK_Mode_switch) \\\n   || ((KeySym)(keysym) == XK_Num_Lock))\n#else\n#define IsModifierKey(keysym) \\\n  ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \\\n   || ((KeySym)(keysym) == XK_Mode_switch) \\\n   || ((KeySym)(keysym) == XK_Num_Lock))\n#endif\n/*\n * opaque reference to Region data type\n */\ntypedef struct _XRegion *Region;\n\n/* Return values from XRectInRegion() */\n\n#define RectangleOut 0\n#define RectangleIn  1\n#define RectanglePart 2\n\n\n/*\n * Information used by the visual utility routines to find desired visual\n * type from the many visuals a display may support.\n */\n\ntypedef struct {\n  Visual *visual;\n  VisualID visualid;\n  int screen;\n  int depth;\n#if defined(__cplusplus) || defined(c_plusplus)\n  int c_class;\t\t\t\t\t/* C++ */\n#else\n  int class;\n#endif\n  unsigned long red_mask;\n  unsigned long green_mask;\n  unsigned long blue_mask;\n  int colormap_size;\n  int bits_per_rgb;\n} XVisualInfo;\n\n#define VisualNoMask\t\t0x0\n#define VisualIDMask \t\t0x1\n#define VisualScreenMask\t0x2\n#define VisualDepthMask\t\t0x4\n#define VisualClassMask\t\t0x8\n#define VisualRedMaskMask\t0x10\n#define VisualGreenMaskMask\t0x20\n#define VisualBlueMaskMask\t0x40\n#define VisualColormapSizeMask\t0x80\n#define VisualBitsPerRGBMask\t0x100\n#define VisualAllMask\t\t0x1FF\n\n/*\n * This defines a window manager property that clients may use to\n * share standard color maps of type RGB_COLOR_MAP:\n */\ntypedef struct {\n\tColormap colormap;\n\tunsigned long red_max;\n\tunsigned long red_mult;\n\tunsigned long green_max;\n\tunsigned long green_mult;\n\tunsigned long blue_max;\n\tunsigned long blue_mult;\n\tunsigned long base_pixel;\n\tVisualID visualid;\t\t/* added by ICCCM version 1 */\n\tXID killid;\t\t\t/* added by ICCCM version 1 */\n} XStandardColormap;\n\n#define ReleaseByFreeingColormap ((XID) 1L)  /* for killid field above */\n\n\n/*\n * return codes for XReadBitmapFile and XWriteBitmapFile\n */\n#define BitmapSuccess\t\t0\n#define BitmapOpenFailed \t1\n#define BitmapFileInvalid \t2\n#define BitmapNoMemory\t\t3\n\n/****************************************************************\n *\n * Context Management\n *\n ****************************************************************/\n\n\n/* Associative lookup table return codes */\n\n#define XCSUCCESS 0\t/* No error. */\n#define XCNOMEM   1    /* Out of memory */\n#define XCNOENT   2    /* No entry in table */\n\ntypedef int XContext;\n\n#define XUniqueContext()       ((XContext) XrmUniqueQuark())\n#define XStringToContext(string)   ((XContext) XrmStringToQuark(string))\n\n_XFUNCPROTOBEGIN\n\n/* The following declarations are alphabetized. */\n\nEXTERN XClassHint *XAllocClassHint (\n    void\n);\n\nEXTERN XIconSize *XAllocIconSize (\n    void\n);\n\nEXTERN XSizeHints *XAllocSizeHints (\n    void\n);\n\nEXTERN XStandardColormap *XAllocStandardColormap (\n    void\n);\n\nEXTERN XWMHints *XAllocWMHints (\n    void\n);\n\nEXTERN int XClipBox(\n    Region\t\t/* r */,\n    XRectangle*\t\t/* rect_return */\n);\n\nEXTERN Region XCreateRegion(\n    void\n);\n\nEXTERN const char *XDefaultString (void);\n\nEXTERN int XDeleteContext(\n    Display*\t\t/* display */,\n    XID\t\t\t/* rid */,\n    XContext\t\t/* context */\n);\n\nEXTERN int XDestroyRegion(\n    Region\t\t/* r */\n);\n\nEXTERN Bool XEmptyRegion(\n    Region\t\t/* r */\n);\n\nEXTERN Bool XEqualRegion(\n    Region\t\t/* r1 */,\n    Region\t\t/* r2 */\n);\n\nEXTERN int XFindContext(\n    Display*\t\t/* display */,\n    XID\t\t\t/* rid */,\n    XContext\t\t/* context */,\n    XPointer*\t\t/* data_return */\n);\n\nEXTERN Status XGetClassHint(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XClassHint*\t\t/* class_hints_return */\n);\n\nEXTERN Status XGetIconSizes(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XIconSize**\t\t/* size_list_return */,\n    int*\t\t/* count_return */\n);\n\nEXTERN Status XGetNormalHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints_return */\n);\n\nEXTERN Status XGetRGBColormaps(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XStandardColormap** /* stdcmap_return */,\n    int*\t\t/* count_return */,\n    Atom\t\t/* property */\n);\n\nEXTERN Status XGetSizeHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints_return */,\n    Atom\t\t/* property */\n);\n\nEXTERN Status XGetStandardColormap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XStandardColormap*\t/* colormap_return */,\n    Atom\t\t/* property */\n);\n\nEXTERN Status XGetTextProperty(\n    Display*\t\t/* display */,\n    Window\t\t/* window */,\n    XTextProperty*\t/* text_prop_return */,\n    Atom\t\t/* property */\n);\n\nEXTERN XVisualInfo *XGetVisualInfo(\n    Display*\t\t/* display */,\n    long\t\t/* vinfo_mask */,\n    XVisualInfo*\t/* vinfo_template */,\n    int*\t\t/* nitems_return */\n);\n\nEXTERN Status XGetWMClientMachine(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop_return */\n);\n\nEXTERN XWMHints *XGetWMHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */\n);\n\nEXTERN Status XGetWMIconName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop_return */\n);\n\nEXTERN Status XGetWMName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop_return */\n);\n\nEXTERN Status XGetWMNormalHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints_return */,\n    long*\t\t/* supplied_return */\n);\n\nEXTERN Status XGetWMSizeHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints_return */,\n    long*\t\t/* supplied_return */,\n    Atom\t\t/* property */\n);\n\nEXTERN Status XGetZoomHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* zhints_return */\n);\n\nEXTERN int XIntersectRegion(\n    Region\t\t/* sra */,\n    Region\t\t/* srb */,\n    Region\t\t/* dr_return */\n);\n\nEXTERN void XConvertCase(\n    KeySym\t\t/* sym */,\n    KeySym*\t\t/* lower */,\n    KeySym*\t\t/* upper */\n);\n\nEXTERN int XLookupString(\n    XKeyEvent*\t\t/* event_struct */,\n    char*\t\t/* buffer_return */,\n    int\t\t\t/* bytes_buffer */,\n    KeySym*\t\t/* keysym_return */,\n    XComposeStatus*\t/* status_in_out */\n);\n\nEXTERN Status XMatchVisualInfo(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen */,\n    int\t\t\t/* depth */,\n    int\t\t\t/* class */,\n    XVisualInfo*\t/* vinfo_return */\n);\n\nEXTERN int XOffsetRegion(\n    Region\t\t/* r */,\n    int\t\t\t/* dx */,\n    int\t\t\t/* dy */\n);\n\nEXTERN Bool XPointInRegion(\n    Region\t\t/* r */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */\n);\n\nEXTERN Region XPolygonRegion(\n    XPoint*\t\t/* points */,\n    int\t\t\t/* n */,\n    int\t\t\t/* fill_rule */\n);\n\nEXTERN int XRectInRegion(\n    Region\t\t/* r */,\n    int\t\t\t/* x */,\n    int\t\t\t/* y */,\n    unsigned int\t/* width */,\n    unsigned int\t/* height */\n);\n\nEXTERN int XSaveContext(\n    Display*\t\t/* display */,\n    XID\t\t\t/* rid */,\n    XContext\t\t/* context */,\n    _Xconst char*\t/* data */\n);\n\nEXTERN int XSetClassHint(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XClassHint*\t\t/* class_hints */\n);\n\nEXTERN int XSetIconSizes(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XIconSize*\t\t/* size_list */,\n    int\t\t\t/* count */\n);\n\nEXTERN int XSetNormalHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints */\n);\n\nEXTERN void XSetRGBColormaps(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XStandardColormap*\t/* stdcmaps */,\n    int\t\t\t/* count */,\n    Atom\t\t/* property */\n);\n\nEXTERN int XSetSizeHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints */,\n    Atom\t\t/* property */\n);\n\nEXTERN int XSetStandardProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    _Xconst char*\t/* window_name */,\n    _Xconst char*\t/* icon_name */,\n    Pixmap\t\t/* icon_pixmap */,\n    char**\t\t/* argv */,\n    int\t\t\t/* argc */,\n    XSizeHints*\t\t/* hints */\n);\n\nEXTERN void XSetTextProperty(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop */,\n    Atom\t\t/* property */\n);\n\nEXTERN void XSetWMClientMachine(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop */\n);\n\nEXTERN int XSetWMHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XWMHints*\t\t/* wm_hints */\n);\n\nEXTERN void XSetWMIconName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop */\n);\n\nEXTERN void XSetWMName(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* text_prop */\n);\n\nEXTERN void XSetWMNormalHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints */\n);\n\nEXTERN void XSetWMProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XTextProperty*\t/* window_name */,\n    XTextProperty*\t/* icon_name */,\n    char**\t\t/* argv */,\n    int\t\t\t/* argc */,\n    XSizeHints*\t\t/* normal_hints */,\n    XWMHints*\t\t/* wm_hints */,\n    XClassHint*\t\t/* class_hints */\n);\n\nEXTERN void XmbSetWMProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    _Xconst char*\t/* window_name */,\n    _Xconst char*\t/* icon_name */,\n    char**\t\t/* argv */,\n    int\t\t\t/* argc */,\n    XSizeHints*\t\t/* normal_hints */,\n    XWMHints*\t\t/* wm_hints */,\n    XClassHint*\t\t/* class_hints */\n);\n\nEXTERN void Xutf8SetWMProperties(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    _Xconst char*\t/* window_name */,\n    _Xconst char*\t/* icon_name */,\n    char**\t\t/* argv */,\n    int\t\t\t/* argc */,\n    XSizeHints*\t\t/* normal_hints */,\n    XWMHints*\t\t/* wm_hints */,\n    XClassHint*\t\t/* class_hints */\n);\n\nEXTERN void XSetWMSizeHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* hints */,\n    Atom\t\t/* property */\n);\n\nEXTERN int XSetRegion(\n    Display*\t\t/* display */,\n    GC\t\t\t/* gc */,\n    Region\t\t/* r */\n);\n\nEXTERN void XSetStandardColormap(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XStandardColormap*\t/* colormap */,\n    Atom\t\t/* property */\n);\n\nEXTERN int XSetZoomHints(\n    Display*\t\t/* display */,\n    Window\t\t/* w */,\n    XSizeHints*\t\t/* zhints */\n);\n\nEXTERN int XShrinkRegion(\n    Region\t\t/* r */,\n    int\t\t\t/* dx */,\n    int\t\t\t/* dy */\n);\n\nEXTERN Status XStringListToTextProperty(\n    char**\t\t/* list */,\n    int\t\t\t/* count */,\n    XTextProperty*\t/* text_prop_return */\n);\n\nEXTERN int XSubtractRegion(\n    Region\t\t/* sra */,\n    Region\t\t/* srb */,\n    Region\t\t/* dr_return */\n);\n\nEXTERN int XmbTextListToTextProperty(\n    Display*\t\tdisplay,\n    char**\t\tlist,\n    int\t\t\tcount,\n    XICCEncodingStyle\tstyle,\n    XTextProperty*\ttext_prop_return\n);\n\nEXTERN int XwcTextListToTextProperty(\n    Display*\t\tdisplay,\n    wchar_t**\t\tlist,\n    int\t\t\tcount,\n    XICCEncodingStyle\tstyle,\n    XTextProperty*\ttext_prop_return\n);\n\nEXTERN int Xutf8TextListToTextProperty(\n    Display*\t\tdisplay,\n    char**\t\tlist,\n    int\t\t\tcount,\n    XICCEncodingStyle\tstyle,\n    XTextProperty*\ttext_prop_return\n);\n\nEXTERN void XwcFreeStringList(\n    wchar_t**\t\tlist\n);\n\nEXTERN Status XTextPropertyToStringList(\n    XTextProperty*\t/* text_prop */,\n    char***\t\t/* list_return */,\n    int*\t\t/* count_return */\n);\n\nEXTERN int XmbTextPropertyToTextList(\n    Display*\t\tdisplay,\n    const XTextProperty* text_prop,\n    char***\t\tlist_return,\n    int*\t\tcount_return\n);\n\nEXTERN int XwcTextPropertyToTextList(\n    Display*\t\tdisplay,\n    const XTextProperty* text_prop,\n    wchar_t***\t\tlist_return,\n    int*\t\tcount_return\n);\n\nEXTERN int Xutf8TextPropertyToTextList(\n    Display*\t\tdisplay,\n    const XTextProperty* text_prop,\n    char***\t\tlist_return,\n    int*\t\tcount_return\n);\n\nEXTERN int XUnionRectWithRegion(\n    XRectangle*\t\t/* rectangle */,\n    Region\t\t/* src_region */,\n    Region\t\t/* dest_region_return */\n);\n\nEXTERN int XUnionRegion(\n    Region\t\t/* sra */,\n    Region\t\t/* srb */,\n    Region\t\t/* dr_return */\n);\n\nEXTERN int XWMGeometry(\n    Display*\t\t/* display */,\n    int\t\t\t/* screen_number */,\n    _Xconst char*\t/* user_geometry */,\n    _Xconst char*\t/* default_geometry */,\n    unsigned int\t/* border_width */,\n    XSizeHints*\t\t/* hints */,\n    int*\t\t/* x_return */,\n    int*\t\t/* y_return */,\n    int*\t\t/* width_return */,\n    int*\t\t/* height_return */,\n    int*\t\t/* gravity_return */\n);\n\nEXTERN int XXorRegion(\n    Region\t\t/* sra */,\n    Region\t\t/* srb */,\n    Region\t\t/* dr_return */\n);\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n_XFUNCPROTOEND\n\n#endif /* _X11_XUTIL_H_ */\n"
  },
  {
    "path": "xlib/X11/ap_keysym.h",
    "content": "/******************************************************************\nCopyright 1987 by Apollo Computer Inc., Chelmsford, Massachusetts.\nCopyright 1989 by Hewlett-Packard Company.\n\n                        All Rights Reserved\n\nPermission to use, duplicate, change, and distribute this software and\nits documentation for any purpose and without fee is granted, provided\nthat the above copyright notice appear in such copy and that this\ncopyright notice appear in all supporting documentation, and that the\nnames of Apollo Computer Inc., the Hewlett-Packard Company, or the X\nConsortium not be used in advertising or publicity pertaining to\ndistribution of the software without written prior permission.\n\nHEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD\nTO THIS SOFTWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  Hewlett-Packard shall not be liable for errors\ncontained herein or direct, indirect, special, incidental or\nconsequential damages in connection with the furnishing,\nperformance, or use of this material.\n\nThis software is not subject to any license of the American\nTelephone and Telegraph Company or of the Regents of the\nUniversity of California.\n******************************************************************/\n\n#define apXK_LineDel            0x1000FF00\n#define apXK_CharDel            0x1000FF01\n#define apXK_Copy               0x1000FF02\n#define apXK_Cut                0x1000FF03\n#define apXK_Paste              0x1000FF04\n#define apXK_Move               0x1000FF05\n#define apXK_Grow               0x1000FF06\n#define apXK_Cmd                0x1000FF07\n#define apXK_Shell              0x1000FF08\n#define apXK_LeftBar            0x1000FF09\n#define apXK_RightBar           0x1000FF0A\n#define apXK_LeftBox            0x1000FF0B\n#define apXK_RightBox           0x1000FF0C\n#define apXK_UpBox              0x1000FF0D\n#define apXK_DownBox            0x1000FF0E\n#define apXK_Pop                0x1000FF0F\n#define apXK_Read               0x1000FF10\n#define apXK_Edit               0x1000FF11\n#define apXK_Save               0x1000FF12\n#define apXK_Exit               0x1000FF13\n#define apXK_Repeat             0x1000FF14\n\n#define apXK_KP_parenleft       0x1000FFA8\n#define apXK_KP_parenright      0x1000FFA9\n"
  },
  {
    "path": "xlib/X11/cursorfont.h",
    "content": "/*\n\nCopyright 1987, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall\nnot be used in advertising or otherwise to promote the sale, use or\nother dealings in this Software without prior written authorization\nfrom The Open Group.\n\n*/\n\n#ifndef _X11_CURSORFONT_H_\n#define _X11_CURSORFONT_H_\n\n#define XC_num_glyphs 154\n#define XC_X_cursor 0\n#define XC_arrow 2\n#define XC_based_arrow_down 4\n#define XC_based_arrow_up 6\n#define XC_boat 8\n#define XC_bogosity 10\n#define XC_bottom_left_corner 12\n#define XC_bottom_right_corner 14\n#define XC_bottom_side 16\n#define XC_bottom_tee 18\n#define XC_box_spiral 20\n#define XC_center_ptr 22\n#define XC_circle 24\n#define XC_clock 26\n#define XC_coffee_mug 28\n#define XC_cross 30\n#define XC_cross_reverse 32\n#define XC_crosshair 34\n#define XC_diamond_cross 36\n#define XC_dot 38\n#define XC_dotbox 40\n#define XC_double_arrow 42\n#define XC_draft_large 44\n#define XC_draft_small 46\n#define XC_draped_box 48\n#define XC_exchange 50\n#define XC_fleur 52\n#define XC_gobbler 54\n#define XC_gumby 56\n#define XC_hand1 58\n#define XC_hand2 60\n#define XC_heart 62\n#define XC_icon 64\n#define XC_iron_cross 66\n#define XC_left_ptr 68\n#define XC_left_side 70\n#define XC_left_tee 72\n#define XC_leftbutton 74\n#define XC_ll_angle 76\n#define XC_lr_angle 78\n#define XC_man 80\n#define XC_middlebutton 82\n#define XC_mouse 84\n#define XC_pencil 86\n#define XC_pirate 88\n#define XC_plus 90\n#define XC_question_arrow 92\n#define XC_right_ptr 94\n#define XC_right_side 96\n#define XC_right_tee 98\n#define XC_rightbutton 100\n#define XC_rtl_logo 102\n#define XC_sailboat 104\n#define XC_sb_down_arrow 106\n#define XC_sb_h_double_arrow 108\n#define XC_sb_left_arrow 110\n#define XC_sb_right_arrow 112\n#define XC_sb_up_arrow 114\n#define XC_sb_v_double_arrow 116\n#define XC_shuttle 118\n#define XC_sizing 120\n#define XC_spider 122\n#define XC_spraycan 124\n#define XC_star 126\n#define XC_target 128\n#define XC_tcross 130\n#define XC_top_left_arrow 132\n#define XC_top_left_corner 134\n#define XC_top_right_corner 136\n#define XC_top_side 138\n#define XC_top_tee 140\n#define XC_trek 142\n#define XC_ul_angle 144\n#define XC_umbrella 146\n#define XC_ur_angle 148\n#define XC_watch 150\n#define XC_xterm 152\n\n#endif /* _X11_CURSORFONT_H_ */\n"
  },
  {
    "path": "xlib/X11/keysym.h",
    "content": "/***********************************************************\n\nCopyright 1987, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n/* default keysyms */\n#define XK_MISCELLANY\n#define XK_XKB_KEYS\n#define XK_LATIN1\n#define XK_LATIN2\n#define XK_LATIN3\n#define XK_LATIN4\n#define XK_LATIN8\n#define XK_LATIN9\n#define XK_CAUCASUS\n#define XK_GREEK\n#define XK_KATAKANA\n#define XK_ARABIC\n#define XK_CYRILLIC\n#define XK_HEBREW\n#define XK_THAI\n#define XK_KOREAN\n#define XK_ARMENIAN\n#define XK_GEORGIAN\n#define XK_VIETNAMESE\n#define XK_CURRENCY\n#define XK_MATHEMATICAL\n#define XK_BRAILLE\n#define XK_SINHALA\n\n#include <X11/keysymdef.h>\n\n"
  },
  {
    "path": "xlib/X11/keysymdef.h",
    "content": "/***********************************************************\nCopyright 1987, 1994, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall\nnot be used in advertising or otherwise to promote the sale, use or\nother dealings in this Software without prior written authorization\nfrom The Open Group.\n\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n/*\n * The \"X11 Window System Protocol\" standard defines in Appendix A the\n * keysym codes. These 29-bit integer values identify characters or\n * functions associated with each key (e.g., via the visible\n * engraving) of a keyboard layout. This file assigns mnemonic macro\n * names for these keysyms.\n *\n * This file is also compiled (by src/util/makekeys.c in libX11) into\n * hash tables that can be accessed with X11 library functions such as\n * XStringToKeysym() and XKeysymToString().\n *\n * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode\n * character, this is noted in a comment that provides both the U+xxxx\n * Unicode position, as well as the official Unicode name of the\n * character.\n *\n * Some keysyms map to a character already mapped by another keysym,\n * with compatible but more precise semantics, such as the keypad-\n * related keysyms. In this case, none of the keysym are deprecated.\n * The most generic keysym is annotated as previously and more specific\n * keysyms have the same annotation between angle brackets:\n *\n *     #define XK_space                 0x0020  // U+0020 SPACE\n *     #define XK_KP_Space              0xff80  //<U+0020 SPACE>\n *\n * Where the correspondence is either not one-to-one or semantically\n * unclear, the Unicode position and name are enclosed in\n * parentheses. Such legacy keysyms should be considered deprecated\n * and are not recommended for use in future keyboard mappings.\n *\n * For any future extension of the keysyms with characters already\n * found in ISO 10646 / Unicode, the following algorithm shall be\n * used. The new keysym code position will simply be the character's\n * Unicode number plus 0x01000000. The keysym values in the range\n * 0x01000100 to 0x0110ffff are reserved to represent Unicode\n * characters in the range U+0100 to U+10FFFF.\n *\n * While most newer Unicode-based X11 clients do already accept\n * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it\n * will remain necessary for clients -- in the interest of\n * compatibility with existing servers -- to also understand the\n * existing legacy keysym values in the range 0x0100 to 0x20ff.\n *\n * Where several mnemonic names are defined for the same keysym in this\n * file, the first one listed is considered the \"canonical\" name. This\n * is the name that should be used when retrieving a keysym name from\n * its code. The next names are considered \"aliases\" to the canonical\n * name.\n *\n * Aliases are made explicit by writing in their comment \"alias for\",\n * followed by the corresponding canonical name. Example:\n *\n *     #define XK_dead_tilde            0xfe53\n *     #define XK_dead_perispomeni      0xfe53 // alias for dead_tilde\n *\n * The rules to consider a keysym mnemonic name deprecated are:\n *\n *   1. A legacy keysym with its Unicode mapping in parentheses is\n *      deprecated (see above).\n *\n *   2. A keysym name is *explicitly* deprecated by starting its comment\n *      with \"deprecated\". Examples:\n *\n *        #define XK_L1           0xffc8  // deprecated alias for F11\n *        #define XK_quoteleft    0x0060  // deprecated\n *\n *   3. A keysym name is *explicitly* *not* deprecated by starting its\n *      comment with \"non-deprecated alias\". Examples:\n *\n *       #define XK_dead_tilde       0xfe53\n *       #define XK_dead_perispomeni 0xfe53 // non-deprecated alias for dead_tilde\n *\n *   4. If none of the previous rules apply, an alias is *implicitly*\n *      deprecated if there is at least one previous name for the\n *      corresponding keysym that is *not* explicitly deprecated.\n *\n *      Examples:\n *\n *        // SingleCandidate is the canonical name\n *        #define XK_SingleCandidate        0xff3c\n *        // Hangul_SingleCandidate is deprecated because it is an alias\n *        // and it does not start with \"non-deprecated alias\"\n *        #define XK_Hangul_SingleCandidate 0xff3c // Single candidate\n *\n *        // guillemotleft is the canonical name, but it is deprecated\n *        #define XK_guillemotleft  0x00ab // deprecated alias for guillemetleft (misspelling)\n *        // guillemetleft is not deprecated, because the keysym has no endorsed name before it.\n *        #define XK_guillemetleft  0x00ab // U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK\n *        // The following hypothetical name is deprecated because guillemetleft come before.\n *        #define XK_guillemetleft2 0x00ab\n *\n * Mnemonic names for keysyms are defined in this file with lines\n * that match one of these Perl regular expressions:\n *\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*\\/\\* U\\+([0-9A-F]{4,6}) (.*) \\*\\/\\s*$/\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*\\/\\*<U\\+([0-9A-F]{4,6}) (.*)>\\*\\/\\s*$/\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*\\/\\*\\(U\\+([0-9A-F]{4,6}) (.*)\\)\\*\\/\\s*$/\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*(\\/\\*\\s*(.*)\\s*\\*\\/)?\\s*$/\n *\n * Before adding new keysyms, please do consider the following: In\n * addition to the keysym names defined in this file, the\n * XStringToKeysym() and XKeysymToString() functions will also handle\n * any keysym string of the form \"U0020\" to \"U007E\" and \"U00A0\" to\n * \"U10FFFF\" for all possible Unicode characters. In other words,\n * every possible Unicode character has already a keysym string\n * defined algorithmically, even if it is not listed here. Therefore,\n * defining an additional keysym macro is only necessary where a\n * non-hexadecimal mnemonic name is needed, or where the new keysym\n * does not represent any existing Unicode character.\n *\n * When adding new keysyms to this file, do not forget to also update the\n * following as needed:\n *\n *   - the mappings in src/KeyBind.c in the libX11 repo\n *     https://gitlab.freedesktop.org/xorg/lib/libx11\n *\n *   - the protocol specification in specs/keysyms.xml in this repo\n *     https://gitlab.freedesktop.org/xorg/proto/xorgproto\n *\n * Before removing or changing the order of the keysyms, please consider\n * the following: it is very difficult to know what keysyms are used and\n * how.\n *\n *   - A sandboxed application may have incompatibilities with the host\n *     system. For example, if new keysym name is introduced and is made\n *     the canonical name, then an application with an older keysym parser\n *     will not be able to parse the new name.\n *   - Customization of keyboard layout and Compose files are two popular\n *     use cases. Checking the standard keyboard layout database xkeyboard-config\n *     https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config\n *     and the standard Compose files in libx11\n *     https://gitlab.freedesktop.org/xorg/lib/libx11 is a mandatory\n *     step, but may *not* be enough for a proper impact assessment for\n *     e.g. keysyms removals.\n *\n * Therefore, it is advised to proceed to no removal and to make a new\n * name canonical only 10 years after its introduction. This means that\n * some keysyms may have their first listed name deprecated during the\n * period of transition. Once this period is over, the deprecated name\n * should be moved after the new canonical name.\n */\n\n#define XK_VoidSymbol                  0xffffff  /* Void symbol */\n\n#ifdef XK_MISCELLANY\n/*\n * TTY function keys, cleverly chosen to map to ASCII, for convenience of\n * programming, but could have been arbitrary (at the cost of lookup\n * tables in client code).\n */\n\n#define XK_BackSpace                     0xff08  /* U+0008 BACKSPACE */\n#define XK_Tab                           0xff09  /* U+0009 CHARACTER TABULATION */\n#define XK_Linefeed                      0xff0a  /* U+000A LINE FEED */\n#define XK_Clear                         0xff0b  /* U+000B LINE TABULATION */\n#define XK_Return                        0xff0d  /* U+000D CARRIAGE RETURN */\n#define XK_Pause                         0xff13  /* Pause, hold */\n#define XK_Scroll_Lock                   0xff14\n#define XK_Sys_Req                       0xff15\n#define XK_Escape                        0xff1b  /* U+001B ESCAPE */\n#define XK_Delete                        0xffff  /* U+007F DELETE */\n\n\n\n/* International & multi-key character composition */\n\n#define XK_Multi_key                     0xff20  /* Multi-key character compose */\n#define XK_Codeinput                     0xff37\n#define XK_SingleCandidate               0xff3c\n#define XK_MultipleCandidate             0xff3d\n#define XK_PreviousCandidate             0xff3e\n\n/* Japanese keyboard support */\n\n#define XK_Kanji                         0xff21  /* Kanji, Kanji convert */\n#define XK_Muhenkan                      0xff22  /* Cancel Conversion */\n#define XK_Henkan_Mode                   0xff23  /* Start/Stop Conversion */\n#define XK_Henkan                        0xff23  /* non-deprecated alias for Henkan_Mode */\n#define XK_Romaji                        0xff24  /* to Romaji */\n#define XK_Hiragana                      0xff25  /* to Hiragana */\n#define XK_Katakana                      0xff26  /* to Katakana */\n#define XK_Hiragana_Katakana             0xff27  /* Hiragana/Katakana toggle */\n#define XK_Zenkaku                       0xff28  /* to Zenkaku */\n#define XK_Hankaku                       0xff29  /* to Hankaku */\n#define XK_Zenkaku_Hankaku               0xff2a  /* Zenkaku/Hankaku toggle */\n#define XK_Touroku                       0xff2b  /* Add to Dictionary */\n#define XK_Massyo                        0xff2c  /* Delete from Dictionary */\n#define XK_Kana_Lock                     0xff2d  /* Kana Lock */\n#define XK_Kana_Shift                    0xff2e  /* Kana Shift */\n#define XK_Eisu_Shift                    0xff2f  /* Alphanumeric Shift */\n#define XK_Eisu_toggle                   0xff30  /* Alphanumeric toggle */\n#define XK_Kanji_Bangou                  0xff37  /* Codeinput */\n#define XK_Zen_Koho                      0xff3d  /* Multiple/All Candidate(s) */\n#define XK_Mae_Koho                      0xff3e  /* Previous Candidate */\n\n/* 0xff31 thru 0xff3f are under XK_KOREAN */\n\n/* Cursor control & motion */\n\n#define XK_Home                          0xff50\n#define XK_Left                          0xff51  /* Move left, left arrow */\n#define XK_Up                            0xff52  /* Move up, up arrow */\n#define XK_Right                         0xff53  /* Move right, right arrow */\n#define XK_Down                          0xff54  /* Move down, down arrow */\n#define XK_Prior                         0xff55  /* Prior, previous */\n#define XK_Page_Up                       0xff55  /* deprecated alias for Prior */\n#define XK_Next                          0xff56  /* Next */\n#define XK_Page_Down                     0xff56  /* deprecated alias for Next */\n#define XK_End                           0xff57  /* EOL */\n#define XK_Begin                         0xff58  /* BOL */\n\n\n/* Misc functions */\n\n#define XK_Select                        0xff60  /* Select, mark */\n#define XK_Print                         0xff61\n#define XK_Execute                       0xff62  /* Execute, run, do */\n#define XK_Insert                        0xff63  /* Insert, insert here */\n#define XK_Undo                          0xff65\n#define XK_Redo                          0xff66  /* Redo, again */\n#define XK_Menu                          0xff67\n#define XK_Find                          0xff68  /* Find, search */\n#define XK_Cancel                        0xff69  /* Cancel, stop, abort, exit */\n#define XK_Help                          0xff6a  /* Help */\n#define XK_Break                         0xff6b\n#define XK_Mode_switch                   0xff7e  /* Character set switch */\n#define XK_script_switch                 0xff7e  /* non-deprecated alias for Mode_switch */\n#define XK_Num_Lock                      0xff7f\n\n/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */\n\n#define XK_KP_Space                      0xff80  /*<U+0020 SPACE>*/\n#define XK_KP_Tab                        0xff89  /*<U+0009 CHARACTER TABULATION>*/\n#define XK_KP_Enter                      0xff8d  /*<U+000D CARRIAGE RETURN>*/\n#define XK_KP_F1                         0xff91  /* PF1, KP_A, ... */\n#define XK_KP_F2                         0xff92\n#define XK_KP_F3                         0xff93\n#define XK_KP_F4                         0xff94\n#define XK_KP_Home                       0xff95\n#define XK_KP_Left                       0xff96\n#define XK_KP_Up                         0xff97\n#define XK_KP_Right                      0xff98\n#define XK_KP_Down                       0xff99\n#define XK_KP_Prior                      0xff9a\n#define XK_KP_Page_Up                    0xff9a  /* deprecated alias for KP_Prior */\n#define XK_KP_Next                       0xff9b\n#define XK_KP_Page_Down                  0xff9b  /* deprecated alias for KP_Next */\n#define XK_KP_End                        0xff9c\n#define XK_KP_Begin                      0xff9d\n#define XK_KP_Insert                     0xff9e\n#define XK_KP_Delete                     0xff9f\n#define XK_KP_Equal                      0xffbd  /*<U+003D EQUALS SIGN>*/\n#define XK_KP_Multiply                   0xffaa  /*<U+002A ASTERISK>*/\n#define XK_KP_Add                        0xffab  /*<U+002B PLUS SIGN>*/\n#define XK_KP_Separator                  0xffac  /*<U+002C COMMA>*/\n#define XK_KP_Subtract                   0xffad  /*<U+002D HYPHEN-MINUS>*/\n#define XK_KP_Decimal                    0xffae  /*<U+002E FULL STOP>*/\n#define XK_KP_Divide                     0xffaf  /*<U+002F SOLIDUS>*/\n\n#define XK_KP_0                          0xffb0  /*<U+0030 DIGIT ZERO>*/\n#define XK_KP_1                          0xffb1  /*<U+0031 DIGIT ONE>*/\n#define XK_KP_2                          0xffb2  /*<U+0032 DIGIT TWO>*/\n#define XK_KP_3                          0xffb3  /*<U+0033 DIGIT THREE>*/\n#define XK_KP_4                          0xffb4  /*<U+0034 DIGIT FOUR>*/\n#define XK_KP_5                          0xffb5  /*<U+0035 DIGIT FIVE>*/\n#define XK_KP_6                          0xffb6  /*<U+0036 DIGIT SIX>*/\n#define XK_KP_7                          0xffb7  /*<U+0037 DIGIT SEVEN>*/\n#define XK_KP_8                          0xffb8  /*<U+0038 DIGIT EIGHT>*/\n#define XK_KP_9                          0xffb9  /*<U+0039 DIGIT NINE>*/\n\n\n\n/*\n * Auxiliary functions; note the duplicate definitions for left and right\n * function keys;  Sun keyboards and a few other manufacturers have such\n * function key groups on the left and/or right sides of the keyboard.\n * We've not found a keyboard with more than 35 function keys total.\n */\n\n#define XK_F1                            0xffbe\n#define XK_F2                            0xffbf\n#define XK_F3                            0xffc0\n#define XK_F4                            0xffc1\n#define XK_F5                            0xffc2\n#define XK_F6                            0xffc3\n#define XK_F7                            0xffc4\n#define XK_F8                            0xffc5\n#define XK_F9                            0xffc6\n#define XK_F10                           0xffc7\n#define XK_F11                           0xffc8\n#define XK_L1                            0xffc8  /* deprecated alias for F11 */\n#define XK_F12                           0xffc9\n#define XK_L2                            0xffc9  /* deprecated alias for F12 */\n#define XK_F13                           0xffca\n#define XK_L3                            0xffca  /* deprecated alias for F13 */\n#define XK_F14                           0xffcb\n#define XK_L4                            0xffcb  /* deprecated alias for F14 */\n#define XK_F15                           0xffcc\n#define XK_L5                            0xffcc  /* deprecated alias for F15 */\n#define XK_F16                           0xffcd\n#define XK_L6                            0xffcd  /* deprecated alias for F16 */\n#define XK_F17                           0xffce\n#define XK_L7                            0xffce  /* deprecated alias for F17 */\n#define XK_F18                           0xffcf\n#define XK_L8                            0xffcf  /* deprecated alias for F18 */\n#define XK_F19                           0xffd0\n#define XK_L9                            0xffd0  /* deprecated alias for F19 */\n#define XK_F20                           0xffd1\n#define XK_L10                           0xffd1  /* deprecated alias for F20 */\n#define XK_F21                           0xffd2\n#define XK_R1                            0xffd2  /* deprecated alias for F21 */\n#define XK_F22                           0xffd3\n#define XK_R2                            0xffd3  /* deprecated alias for F22 */\n#define XK_F23                           0xffd4\n#define XK_R3                            0xffd4  /* deprecated alias for F23 */\n#define XK_F24                           0xffd5\n#define XK_R4                            0xffd5  /* deprecated alias for F24 */\n#define XK_F25                           0xffd6\n#define XK_R5                            0xffd6  /* deprecated alias for F25 */\n#define XK_F26                           0xffd7\n#define XK_R6                            0xffd7  /* deprecated alias for F26 */\n#define XK_F27                           0xffd8\n#define XK_R7                            0xffd8  /* deprecated alias for F27 */\n#define XK_F28                           0xffd9\n#define XK_R8                            0xffd9  /* deprecated alias for F28 */\n#define XK_F29                           0xffda\n#define XK_R9                            0xffda  /* deprecated alias for F29 */\n#define XK_F30                           0xffdb\n#define XK_R10                           0xffdb  /* deprecated alias for F30 */\n#define XK_F31                           0xffdc\n#define XK_R11                           0xffdc  /* deprecated alias for F31 */\n#define XK_F32                           0xffdd\n#define XK_R12                           0xffdd  /* deprecated alias for F32 */\n#define XK_F33                           0xffde\n#define XK_R13                           0xffde  /* deprecated alias for F33 */\n#define XK_F34                           0xffdf\n#define XK_R14                           0xffdf  /* deprecated alias for F34 */\n#define XK_F35                           0xffe0\n#define XK_R15                           0xffe0  /* deprecated alias for F35 */\n\n/* Modifiers */\n\n#define XK_Shift_L                       0xffe1  /* Left shift */\n#define XK_Shift_R                       0xffe2  /* Right shift */\n#define XK_Control_L                     0xffe3  /* Left control */\n#define XK_Control_R                     0xffe4  /* Right control */\n#define XK_Caps_Lock                     0xffe5  /* Caps lock */\n#define XK_Shift_Lock                    0xffe6  /* Shift lock */\n\n#define XK_Meta_L                        0xffe7  /* Left meta */\n#define XK_Meta_R                        0xffe8  /* Right meta */\n#define XK_Alt_L                         0xffe9  /* Left alt */\n#define XK_Alt_R                         0xffea  /* Right alt */\n#define XK_Super_L                       0xffeb  /* Left super */\n#define XK_Super_R                       0xffec  /* Right super */\n#define XK_Hyper_L                       0xffed  /* Left hyper */\n#define XK_Hyper_R                       0xffee  /* Right hyper */\n#endif /* XK_MISCELLANY */\n\n/*\n * Keyboard (XKB) Extension function and modifier keys\n * (from Appendix C of \"The X Keyboard Extension: Protocol Specification\")\n * Byte 3 = 0xfe\n */\n\n#ifdef XK_XKB_KEYS\n#define XK_ISO_Lock                      0xfe01\n#define XK_ISO_Level2_Latch              0xfe02\n#define XK_ISO_Level3_Shift              0xfe03\n#define XK_ISO_Level3_Latch              0xfe04\n#define XK_ISO_Level3_Lock               0xfe05\n#define XK_ISO_Level5_Shift              0xfe11\n#define XK_ISO_Level5_Latch              0xfe12\n#define XK_ISO_Level5_Lock               0xfe13\n#define XK_ISO_Group_Shift               0xff7e  /* non-deprecated alias for Mode_switch */\n#define XK_ISO_Group_Latch               0xfe06\n#define XK_ISO_Group_Lock                0xfe07\n#define XK_ISO_Next_Group                0xfe08\n#define XK_ISO_Next_Group_Lock           0xfe09\n#define XK_ISO_Prev_Group                0xfe0a\n#define XK_ISO_Prev_Group_Lock           0xfe0b\n#define XK_ISO_First_Group               0xfe0c\n#define XK_ISO_First_Group_Lock          0xfe0d\n#define XK_ISO_Last_Group                0xfe0e\n#define XK_ISO_Last_Group_Lock           0xfe0f\n\n#define XK_ISO_Left_Tab                  0xfe20\n#define XK_ISO_Move_Line_Up              0xfe21\n#define XK_ISO_Move_Line_Down            0xfe22\n#define XK_ISO_Partial_Line_Up           0xfe23\n#define XK_ISO_Partial_Line_Down         0xfe24\n#define XK_ISO_Partial_Space_Left        0xfe25\n#define XK_ISO_Partial_Space_Right       0xfe26\n#define XK_ISO_Set_Margin_Left           0xfe27\n#define XK_ISO_Set_Margin_Right          0xfe28\n#define XK_ISO_Release_Margin_Left       0xfe29\n#define XK_ISO_Release_Margin_Right      0xfe2a\n#define XK_ISO_Release_Both_Margins      0xfe2b\n#define XK_ISO_Fast_Cursor_Left          0xfe2c\n#define XK_ISO_Fast_Cursor_Right         0xfe2d\n#define XK_ISO_Fast_Cursor_Up            0xfe2e\n#define XK_ISO_Fast_Cursor_Down          0xfe2f\n#define XK_ISO_Continuous_Underline      0xfe30\n#define XK_ISO_Discontinuous_Underline   0xfe31\n#define XK_ISO_Emphasize                 0xfe32\n#define XK_ISO_Center_Object             0xfe33\n#define XK_ISO_Enter                     0xfe34\n\n#define XK_dead_grave                    0xfe50\n#define XK_dead_acute                    0xfe51\n#define XK_dead_circumflex               0xfe52\n#define XK_dead_tilde                    0xfe53\n#define XK_dead_perispomeni              0xfe53  /* non-deprecated alias for dead_tilde */\n#define XK_dead_macron                   0xfe54\n#define XK_dead_breve                    0xfe55\n#define XK_dead_abovedot                 0xfe56\n#define XK_dead_diaeresis                0xfe57\n#define XK_dead_abovering                0xfe58\n#define XK_dead_doubleacute              0xfe59\n#define XK_dead_caron                    0xfe5a\n#define XK_dead_cedilla                  0xfe5b\n#define XK_dead_ogonek                   0xfe5c\n#define XK_dead_iota                     0xfe5d\n#define XK_dead_voiced_sound             0xfe5e\n#define XK_dead_semivoiced_sound         0xfe5f\n#define XK_dead_belowdot                 0xfe60\n#define XK_dead_hook                     0xfe61\n#define XK_dead_horn                     0xfe62\n#define XK_dead_stroke                   0xfe63\n#define XK_dead_abovecomma               0xfe64\n#define XK_dead_psili                    0xfe64  /* non-deprecated alias for dead_abovecomma */\n#define XK_dead_abovereversedcomma       0xfe65\n#define XK_dead_dasia                    0xfe65  /* non-deprecated alias for dead_abovereversedcomma */\n#define XK_dead_doublegrave              0xfe66\n#define XK_dead_belowring                0xfe67\n#define XK_dead_belowmacron              0xfe68\n#define XK_dead_belowcircumflex          0xfe69\n#define XK_dead_belowtilde               0xfe6a\n#define XK_dead_belowbreve               0xfe6b\n#define XK_dead_belowdiaeresis           0xfe6c\n#define XK_dead_invertedbreve            0xfe6d\n#define XK_dead_belowcomma               0xfe6e\n#define XK_dead_currency                 0xfe6f\n\n/* extra dead elements for German T3 layout */\n#define XK_dead_lowline                  0xfe90\n#define XK_dead_aboveverticalline        0xfe91\n#define XK_dead_belowverticalline        0xfe92\n#define XK_dead_longsolidusoverlay       0xfe93\n\n/* dead vowels for universal syllable entry */\n#define XK_dead_a                        0xfe80\n#define XK_dead_A                        0xfe81\n#define XK_dead_e                        0xfe82\n#define XK_dead_E                        0xfe83\n#define XK_dead_i                        0xfe84\n#define XK_dead_I                        0xfe85\n#define XK_dead_o                        0xfe86\n#define XK_dead_O                        0xfe87\n#define XK_dead_u                        0xfe88\n#define XK_dead_U                        0xfe89\n#define XK_dead_small_schwa              0xfe8a  /* deprecated alias for dead_schwa */\n#define XK_dead_schwa                    0xfe8a\n#define XK_dead_capital_schwa            0xfe8b  /* deprecated alias for dead_SCHWA */\n#define XK_dead_SCHWA                    0xfe8b\n\n#define XK_dead_greek                    0xfe8c\n#define XK_dead_hamza                    0xfe8d\n\n#define XK_First_Virtual_Screen          0xfed0\n#define XK_Prev_Virtual_Screen           0xfed1\n#define XK_Next_Virtual_Screen           0xfed2\n#define XK_Last_Virtual_Screen           0xfed4\n#define XK_Terminate_Server              0xfed5\n\n#define XK_AccessX_Enable                0xfe70\n#define XK_AccessX_Feedback_Enable       0xfe71\n#define XK_RepeatKeys_Enable             0xfe72\n#define XK_SlowKeys_Enable               0xfe73\n#define XK_BounceKeys_Enable             0xfe74\n#define XK_StickyKeys_Enable             0xfe75\n#define XK_MouseKeys_Enable              0xfe76\n#define XK_MouseKeys_Accel_Enable        0xfe77\n#define XK_Overlay1_Enable               0xfe78\n#define XK_Overlay2_Enable               0xfe79\n#define XK_AudibleBell_Enable            0xfe7a\n\n#define XK_Pointer_Left                  0xfee0\n#define XK_Pointer_Right                 0xfee1\n#define XK_Pointer_Up                    0xfee2\n#define XK_Pointer_Down                  0xfee3\n#define XK_Pointer_UpLeft                0xfee4\n#define XK_Pointer_UpRight               0xfee5\n#define XK_Pointer_DownLeft              0xfee6\n#define XK_Pointer_DownRight             0xfee7\n#define XK_Pointer_Button_Dflt           0xfee8\n#define XK_Pointer_Button1               0xfee9\n#define XK_Pointer_Button2               0xfeea\n#define XK_Pointer_Button3               0xfeeb\n#define XK_Pointer_Button4               0xfeec\n#define XK_Pointer_Button5               0xfeed\n#define XK_Pointer_DblClick_Dflt         0xfeee\n#define XK_Pointer_DblClick1             0xfeef\n#define XK_Pointer_DblClick2             0xfef0\n#define XK_Pointer_DblClick3             0xfef1\n#define XK_Pointer_DblClick4             0xfef2\n#define XK_Pointer_DblClick5             0xfef3\n#define XK_Pointer_Drag_Dflt             0xfef4\n#define XK_Pointer_Drag1                 0xfef5\n#define XK_Pointer_Drag2                 0xfef6\n#define XK_Pointer_Drag3                 0xfef7\n#define XK_Pointer_Drag4                 0xfef8\n#define XK_Pointer_Drag5                 0xfefd\n\n#define XK_Pointer_EnableKeys            0xfef9\n#define XK_Pointer_Accelerate            0xfefa\n#define XK_Pointer_DfltBtnNext           0xfefb\n#define XK_Pointer_DfltBtnPrev           0xfefc\n\n/* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */\n\n#define XK_ch                            0xfea0\n#define XK_Ch                            0xfea1\n#define XK_CH                            0xfea2\n#define XK_c_h                           0xfea3\n#define XK_C_h                           0xfea4\n#define XK_C_H                           0xfea5\n\n#endif /* XK_XKB_KEYS */\n\n/*\n * 3270 Terminal Keys\n * Byte 3 = 0xfd\n */\n\n#ifdef XK_3270\n#define XK_3270_Duplicate                0xfd01\n#define XK_3270_FieldMark                0xfd02\n#define XK_3270_Right2                   0xfd03\n#define XK_3270_Left2                    0xfd04\n#define XK_3270_BackTab                  0xfd05\n#define XK_3270_EraseEOF                 0xfd06\n#define XK_3270_EraseInput               0xfd07\n#define XK_3270_Reset                    0xfd08\n#define XK_3270_Quit                     0xfd09\n#define XK_3270_PA1                      0xfd0a\n#define XK_3270_PA2                      0xfd0b\n#define XK_3270_PA3                      0xfd0c\n#define XK_3270_Test                     0xfd0d\n#define XK_3270_Attn                     0xfd0e\n#define XK_3270_CursorBlink              0xfd0f\n#define XK_3270_AltCursor                0xfd10\n#define XK_3270_KeyClick                 0xfd11\n#define XK_3270_Jump                     0xfd12\n#define XK_3270_Ident                    0xfd13\n#define XK_3270_Rule                     0xfd14\n#define XK_3270_Copy                     0xfd15\n#define XK_3270_Play                     0xfd16\n#define XK_3270_Setup                    0xfd17\n#define XK_3270_Record                   0xfd18\n#define XK_3270_ChangeScreen             0xfd19\n#define XK_3270_DeleteWord               0xfd1a\n#define XK_3270_ExSelect                 0xfd1b\n#define XK_3270_CursorSelect             0xfd1c\n#define XK_3270_PrintScreen              0xfd1d\n#define XK_3270_Enter                    0xfd1e\n#endif /* XK_3270 */\n\n/*\n * Latin 1\n * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)\n * Byte 3 = 0\n */\n#ifdef XK_LATIN1\n#define XK_space                         0x0020  /* U+0020 SPACE */\n#define XK_exclam                        0x0021  /* U+0021 EXCLAMATION MARK */\n#define XK_quotedbl                      0x0022  /* U+0022 QUOTATION MARK */\n#define XK_numbersign                    0x0023  /* U+0023 NUMBER SIGN */\n#define XK_dollar                        0x0024  /* U+0024 DOLLAR SIGN */\n#define XK_percent                       0x0025  /* U+0025 PERCENT SIGN */\n#define XK_ampersand                     0x0026  /* U+0026 AMPERSAND */\n#define XK_apostrophe                    0x0027  /* U+0027 APOSTROPHE */\n#define XK_quoteright                    0x0027  /* deprecated */\n#define XK_parenleft                     0x0028  /* U+0028 LEFT PARENTHESIS */\n#define XK_parenright                    0x0029  /* U+0029 RIGHT PARENTHESIS */\n#define XK_asterisk                      0x002a  /* U+002A ASTERISK */\n#define XK_plus                          0x002b  /* U+002B PLUS SIGN */\n#define XK_comma                         0x002c  /* U+002C COMMA */\n#define XK_minus                         0x002d  /* U+002D HYPHEN-MINUS */\n#define XK_period                        0x002e  /* U+002E FULL STOP */\n#define XK_slash                         0x002f  /* U+002F SOLIDUS */\n#define XK_0                             0x0030  /* U+0030 DIGIT ZERO */\n#define XK_1                             0x0031  /* U+0031 DIGIT ONE */\n#define XK_2                             0x0032  /* U+0032 DIGIT TWO */\n#define XK_3                             0x0033  /* U+0033 DIGIT THREE */\n#define XK_4                             0x0034  /* U+0034 DIGIT FOUR */\n#define XK_5                             0x0035  /* U+0035 DIGIT FIVE */\n#define XK_6                             0x0036  /* U+0036 DIGIT SIX */\n#define XK_7                             0x0037  /* U+0037 DIGIT SEVEN */\n#define XK_8                             0x0038  /* U+0038 DIGIT EIGHT */\n#define XK_9                             0x0039  /* U+0039 DIGIT NINE */\n#define XK_colon                         0x003a  /* U+003A COLON */\n#define XK_semicolon                     0x003b  /* U+003B SEMICOLON */\n#define XK_less                          0x003c  /* U+003C LESS-THAN SIGN */\n#define XK_equal                         0x003d  /* U+003D EQUALS SIGN */\n#define XK_greater                       0x003e  /* U+003E GREATER-THAN SIGN */\n#define XK_question                      0x003f  /* U+003F QUESTION MARK */\n#define XK_at                            0x0040  /* U+0040 COMMERCIAL AT */\n#define XK_A                             0x0041  /* U+0041 LATIN CAPITAL LETTER A */\n#define XK_B                             0x0042  /* U+0042 LATIN CAPITAL LETTER B */\n#define XK_C                             0x0043  /* U+0043 LATIN CAPITAL LETTER C */\n#define XK_D                             0x0044  /* U+0044 LATIN CAPITAL LETTER D */\n#define XK_E                             0x0045  /* U+0045 LATIN CAPITAL LETTER E */\n#define XK_F                             0x0046  /* U+0046 LATIN CAPITAL LETTER F */\n#define XK_G                             0x0047  /* U+0047 LATIN CAPITAL LETTER G */\n#define XK_H                             0x0048  /* U+0048 LATIN CAPITAL LETTER H */\n#define XK_I                             0x0049  /* U+0049 LATIN CAPITAL LETTER I */\n#define XK_J                             0x004a  /* U+004A LATIN CAPITAL LETTER J */\n#define XK_K                             0x004b  /* U+004B LATIN CAPITAL LETTER K */\n#define XK_L                             0x004c  /* U+004C LATIN CAPITAL LETTER L */\n#define XK_M                             0x004d  /* U+004D LATIN CAPITAL LETTER M */\n#define XK_N                             0x004e  /* U+004E LATIN CAPITAL LETTER N */\n#define XK_O                             0x004f  /* U+004F LATIN CAPITAL LETTER O */\n#define XK_P                             0x0050  /* U+0050 LATIN CAPITAL LETTER P */\n#define XK_Q                             0x0051  /* U+0051 LATIN CAPITAL LETTER Q */\n#define XK_R                             0x0052  /* U+0052 LATIN CAPITAL LETTER R */\n#define XK_S                             0x0053  /* U+0053 LATIN CAPITAL LETTER S */\n#define XK_T                             0x0054  /* U+0054 LATIN CAPITAL LETTER T */\n#define XK_U                             0x0055  /* U+0055 LATIN CAPITAL LETTER U */\n#define XK_V                             0x0056  /* U+0056 LATIN CAPITAL LETTER V */\n#define XK_W                             0x0057  /* U+0057 LATIN CAPITAL LETTER W */\n#define XK_X                             0x0058  /* U+0058 LATIN CAPITAL LETTER X */\n#define XK_Y                             0x0059  /* U+0059 LATIN CAPITAL LETTER Y */\n#define XK_Z                             0x005a  /* U+005A LATIN CAPITAL LETTER Z */\n#define XK_bracketleft                   0x005b  /* U+005B LEFT SQUARE BRACKET */\n#define XK_backslash                     0x005c  /* U+005C REVERSE SOLIDUS */\n#define XK_bracketright                  0x005d  /* U+005D RIGHT SQUARE BRACKET */\n#define XK_asciicircum                   0x005e  /* U+005E CIRCUMFLEX ACCENT */\n#define XK_underscore                    0x005f  /* U+005F LOW LINE */\n#define XK_grave                         0x0060  /* U+0060 GRAVE ACCENT */\n#define XK_quoteleft                     0x0060  /* deprecated */\n#define XK_a                             0x0061  /* U+0061 LATIN SMALL LETTER A */\n#define XK_b                             0x0062  /* U+0062 LATIN SMALL LETTER B */\n#define XK_c                             0x0063  /* U+0063 LATIN SMALL LETTER C */\n#define XK_d                             0x0064  /* U+0064 LATIN SMALL LETTER D */\n#define XK_e                             0x0065  /* U+0065 LATIN SMALL LETTER E */\n#define XK_f                             0x0066  /* U+0066 LATIN SMALL LETTER F */\n#define XK_g                             0x0067  /* U+0067 LATIN SMALL LETTER G */\n#define XK_h                             0x0068  /* U+0068 LATIN SMALL LETTER H */\n#define XK_i                             0x0069  /* U+0069 LATIN SMALL LETTER I */\n#define XK_j                             0x006a  /* U+006A LATIN SMALL LETTER J */\n#define XK_k                             0x006b  /* U+006B LATIN SMALL LETTER K */\n#define XK_l                             0x006c  /* U+006C LATIN SMALL LETTER L */\n#define XK_m                             0x006d  /* U+006D LATIN SMALL LETTER M */\n#define XK_n                             0x006e  /* U+006E LATIN SMALL LETTER N */\n#define XK_o                             0x006f  /* U+006F LATIN SMALL LETTER O */\n#define XK_p                             0x0070  /* U+0070 LATIN SMALL LETTER P */\n#define XK_q                             0x0071  /* U+0071 LATIN SMALL LETTER Q */\n#define XK_r                             0x0072  /* U+0072 LATIN SMALL LETTER R */\n#define XK_s                             0x0073  /* U+0073 LATIN SMALL LETTER S */\n#define XK_t                             0x0074  /* U+0074 LATIN SMALL LETTER T */\n#define XK_u                             0x0075  /* U+0075 LATIN SMALL LETTER U */\n#define XK_v                             0x0076  /* U+0076 LATIN SMALL LETTER V */\n#define XK_w                             0x0077  /* U+0077 LATIN SMALL LETTER W */\n#define XK_x                             0x0078  /* U+0078 LATIN SMALL LETTER X */\n#define XK_y                             0x0079  /* U+0079 LATIN SMALL LETTER Y */\n#define XK_z                             0x007a  /* U+007A LATIN SMALL LETTER Z */\n#define XK_braceleft                     0x007b  /* U+007B LEFT CURLY BRACKET */\n#define XK_bar                           0x007c  /* U+007C VERTICAL LINE */\n#define XK_braceright                    0x007d  /* U+007D RIGHT CURLY BRACKET */\n#define XK_asciitilde                    0x007e  /* U+007E TILDE */\n\n#define XK_nobreakspace                  0x00a0  /* U+00A0 NO-BREAK SPACE */\n#define XK_exclamdown                    0x00a1  /* U+00A1 INVERTED EXCLAMATION MARK */\n#define XK_cent                          0x00a2  /* U+00A2 CENT SIGN */\n#define XK_sterling                      0x00a3  /* U+00A3 POUND SIGN */\n#define XK_currency                      0x00a4  /* U+00A4 CURRENCY SIGN */\n#define XK_yen                           0x00a5  /* U+00A5 YEN SIGN */\n#define XK_brokenbar                     0x00a6  /* U+00A6 BROKEN BAR */\n#define XK_section                       0x00a7  /* U+00A7 SECTION SIGN */\n#define XK_diaeresis                     0x00a8  /* U+00A8 DIAERESIS */\n#define XK_copyright                     0x00a9  /* U+00A9 COPYRIGHT SIGN */\n#define XK_ordfeminine                   0x00aa  /* U+00AA FEMININE ORDINAL INDICATOR */\n#define XK_guillemotleft                 0x00ab  /* deprecated alias for guillemetleft (misspelling) */\n#define XK_guillemetleft                 0x00ab  /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */\n#define XK_notsign                       0x00ac  /* U+00AC NOT SIGN */\n#define XK_hyphen                        0x00ad  /* U+00AD SOFT HYPHEN */\n#define XK_registered                    0x00ae  /* U+00AE REGISTERED SIGN */\n#define XK_macron                        0x00af  /* U+00AF MACRON */\n#define XK_degree                        0x00b0  /* U+00B0 DEGREE SIGN */\n#define XK_plusminus                     0x00b1  /* U+00B1 PLUS-MINUS SIGN */\n#define XK_twosuperior                   0x00b2  /* U+00B2 SUPERSCRIPT TWO */\n#define XK_threesuperior                 0x00b3  /* U+00B3 SUPERSCRIPT THREE */\n#define XK_acute                         0x00b4  /* U+00B4 ACUTE ACCENT */\n#define XK_mu                            0x00b5  /* U+00B5 MICRO SIGN */\n#define XK_paragraph                     0x00b6  /* U+00B6 PILCROW SIGN */\n#define XK_periodcentered                0x00b7  /* U+00B7 MIDDLE DOT */\n#define XK_cedilla                       0x00b8  /* U+00B8 CEDILLA */\n#define XK_onesuperior                   0x00b9  /* U+00B9 SUPERSCRIPT ONE */\n#define XK_masculine                     0x00ba  /* deprecated alias for ordmasculine (inconsistent name) */\n#define XK_ordmasculine                  0x00ba  /* U+00BA MASCULINE ORDINAL INDICATOR */\n#define XK_guillemotright                0x00bb  /* deprecated alias for guillemetright (misspelling) */\n#define XK_guillemetright                0x00bb  /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */\n#define XK_onequarter                    0x00bc  /* U+00BC VULGAR FRACTION ONE QUARTER */\n#define XK_onehalf                       0x00bd  /* U+00BD VULGAR FRACTION ONE HALF */\n#define XK_threequarters                 0x00be  /* U+00BE VULGAR FRACTION THREE QUARTERS */\n#define XK_questiondown                  0x00bf  /* U+00BF INVERTED QUESTION MARK */\n#define XK_Agrave                        0x00c0  /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */\n#define XK_Aacute                        0x00c1  /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */\n#define XK_Acircumflex                   0x00c2  /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */\n#define XK_Atilde                        0x00c3  /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */\n#define XK_Adiaeresis                    0x00c4  /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */\n#define XK_Aring                         0x00c5  /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */\n#define XK_AE                            0x00c6  /* U+00C6 LATIN CAPITAL LETTER AE */\n#define XK_Ccedilla                      0x00c7  /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */\n#define XK_Egrave                        0x00c8  /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */\n#define XK_Eacute                        0x00c9  /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */\n#define XK_Ecircumflex                   0x00ca  /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */\n#define XK_Ediaeresis                    0x00cb  /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */\n#define XK_Igrave                        0x00cc  /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */\n#define XK_Iacute                        0x00cd  /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */\n#define XK_Icircumflex                   0x00ce  /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */\n#define XK_Idiaeresis                    0x00cf  /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */\n#define XK_ETH                           0x00d0  /* U+00D0 LATIN CAPITAL LETTER ETH */\n#define XK_Eth                           0x00d0  /* deprecated */\n#define XK_Ntilde                        0x00d1  /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */\n#define XK_Ograve                        0x00d2  /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */\n#define XK_Oacute                        0x00d3  /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */\n#define XK_Ocircumflex                   0x00d4  /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */\n#define XK_Otilde                        0x00d5  /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */\n#define XK_Odiaeresis                    0x00d6  /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */\n#define XK_multiply                      0x00d7  /* U+00D7 MULTIPLICATION SIGN */\n#define XK_Oslash                        0x00d8  /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */\n#define XK_Ooblique                      0x00d8  /* deprecated alias for Oslash */\n#define XK_Ugrave                        0x00d9  /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */\n#define XK_Uacute                        0x00da  /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */\n#define XK_Ucircumflex                   0x00db  /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */\n#define XK_Udiaeresis                    0x00dc  /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */\n#define XK_Yacute                        0x00dd  /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */\n#define XK_THORN                         0x00de  /* U+00DE LATIN CAPITAL LETTER THORN */\n#define XK_Thorn                         0x00de  /* deprecated */\n#define XK_ssharp                        0x00df  /* U+00DF LATIN SMALL LETTER SHARP S */\n#define XK_agrave                        0x00e0  /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */\n#define XK_aacute                        0x00e1  /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */\n#define XK_acircumflex                   0x00e2  /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */\n#define XK_atilde                        0x00e3  /* U+00E3 LATIN SMALL LETTER A WITH TILDE */\n#define XK_adiaeresis                    0x00e4  /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */\n#define XK_aring                         0x00e5  /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */\n#define XK_ae                            0x00e6  /* U+00E6 LATIN SMALL LETTER AE */\n#define XK_ccedilla                      0x00e7  /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */\n#define XK_egrave                        0x00e8  /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */\n#define XK_eacute                        0x00e9  /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */\n#define XK_ecircumflex                   0x00ea  /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */\n#define XK_ediaeresis                    0x00eb  /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */\n#define XK_igrave                        0x00ec  /* U+00EC LATIN SMALL LETTER I WITH GRAVE */\n#define XK_iacute                        0x00ed  /* U+00ED LATIN SMALL LETTER I WITH ACUTE */\n#define XK_icircumflex                   0x00ee  /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */\n#define XK_idiaeresis                    0x00ef  /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */\n#define XK_eth                           0x00f0  /* U+00F0 LATIN SMALL LETTER ETH */\n#define XK_ntilde                        0x00f1  /* U+00F1 LATIN SMALL LETTER N WITH TILDE */\n#define XK_ograve                        0x00f2  /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */\n#define XK_oacute                        0x00f3  /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */\n#define XK_ocircumflex                   0x00f4  /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */\n#define XK_otilde                        0x00f5  /* U+00F5 LATIN SMALL LETTER O WITH TILDE */\n#define XK_odiaeresis                    0x00f6  /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */\n#define XK_division                      0x00f7  /* U+00F7 DIVISION SIGN */\n#define XK_oslash                        0x00f8  /* U+00F8 LATIN SMALL LETTER O WITH STROKE */\n#define XK_ooblique                      0x00f8  /* deprecated alias for oslash */\n#define XK_ugrave                        0x00f9  /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */\n#define XK_uacute                        0x00fa  /* U+00FA LATIN SMALL LETTER U WITH ACUTE */\n#define XK_ucircumflex                   0x00fb  /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */\n#define XK_udiaeresis                    0x00fc  /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */\n#define XK_yacute                        0x00fd  /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */\n#define XK_thorn                         0x00fe  /* U+00FE LATIN SMALL LETTER THORN */\n#define XK_ydiaeresis                    0x00ff  /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */\n#endif /* XK_LATIN1 */\n\n/*\n * Latin 2\n * Byte 3 = 1\n */\n\n#ifdef XK_LATIN2\n#define XK_Aogonek                       0x01a1  /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */\n#define XK_breve                         0x01a2  /* U+02D8 BREVE */\n#define XK_Lstroke                       0x01a3  /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */\n#define XK_Lcaron                        0x01a5  /* U+013D LATIN CAPITAL LETTER L WITH CARON */\n#define XK_Sacute                        0x01a6  /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */\n#define XK_Scaron                        0x01a9  /* U+0160 LATIN CAPITAL LETTER S WITH CARON */\n#define XK_Scedilla                      0x01aa  /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */\n#define XK_Tcaron                        0x01ab  /* U+0164 LATIN CAPITAL LETTER T WITH CARON */\n#define XK_Zacute                        0x01ac  /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */\n#define XK_Zcaron                        0x01ae  /* U+017D LATIN CAPITAL LETTER Z WITH CARON */\n#define XK_Zabovedot                     0x01af  /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */\n#define XK_aogonek                       0x01b1  /* U+0105 LATIN SMALL LETTER A WITH OGONEK */\n#define XK_ogonek                        0x01b2  /* U+02DB OGONEK */\n#define XK_lstroke                       0x01b3  /* U+0142 LATIN SMALL LETTER L WITH STROKE */\n#define XK_lcaron                        0x01b5  /* U+013E LATIN SMALL LETTER L WITH CARON */\n#define XK_sacute                        0x01b6  /* U+015B LATIN SMALL LETTER S WITH ACUTE */\n#define XK_caron                         0x01b7  /* U+02C7 CARON */\n#define XK_scaron                        0x01b9  /* U+0161 LATIN SMALL LETTER S WITH CARON */\n#define XK_scedilla                      0x01ba  /* U+015F LATIN SMALL LETTER S WITH CEDILLA */\n#define XK_tcaron                        0x01bb  /* U+0165 LATIN SMALL LETTER T WITH CARON */\n#define XK_zacute                        0x01bc  /* U+017A LATIN SMALL LETTER Z WITH ACUTE */\n#define XK_doubleacute                   0x01bd  /* U+02DD DOUBLE ACUTE ACCENT */\n#define XK_zcaron                        0x01be  /* U+017E LATIN SMALL LETTER Z WITH CARON */\n#define XK_zabovedot                     0x01bf  /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */\n#define XK_Racute                        0x01c0  /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */\n#define XK_Abreve                        0x01c3  /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */\n#define XK_Lacute                        0x01c5  /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */\n#define XK_Cacute                        0x01c6  /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */\n#define XK_Ccaron                        0x01c8  /* U+010C LATIN CAPITAL LETTER C WITH CARON */\n#define XK_Eogonek                       0x01ca  /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */\n#define XK_Ecaron                        0x01cc  /* U+011A LATIN CAPITAL LETTER E WITH CARON */\n#define XK_Dcaron                        0x01cf  /* U+010E LATIN CAPITAL LETTER D WITH CARON */\n#define XK_Dstroke                       0x01d0  /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */\n#define XK_Nacute                        0x01d1  /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */\n#define XK_Ncaron                        0x01d2  /* U+0147 LATIN CAPITAL LETTER N WITH CARON */\n#define XK_Odoubleacute                  0x01d5  /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */\n#define XK_Rcaron                        0x01d8  /* U+0158 LATIN CAPITAL LETTER R WITH CARON */\n#define XK_Uring                         0x01d9  /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */\n#define XK_Udoubleacute                  0x01db  /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */\n#define XK_Tcedilla                      0x01de  /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */\n#define XK_racute                        0x01e0  /* U+0155 LATIN SMALL LETTER R WITH ACUTE */\n#define XK_abreve                        0x01e3  /* U+0103 LATIN SMALL LETTER A WITH BREVE */\n#define XK_lacute                        0x01e5  /* U+013A LATIN SMALL LETTER L WITH ACUTE */\n#define XK_cacute                        0x01e6  /* U+0107 LATIN SMALL LETTER C WITH ACUTE */\n#define XK_ccaron                        0x01e8  /* U+010D LATIN SMALL LETTER C WITH CARON */\n#define XK_eogonek                       0x01ea  /* U+0119 LATIN SMALL LETTER E WITH OGONEK */\n#define XK_ecaron                        0x01ec  /* U+011B LATIN SMALL LETTER E WITH CARON */\n#define XK_dcaron                        0x01ef  /* U+010F LATIN SMALL LETTER D WITH CARON */\n#define XK_dstroke                       0x01f0  /* U+0111 LATIN SMALL LETTER D WITH STROKE */\n#define XK_nacute                        0x01f1  /* U+0144 LATIN SMALL LETTER N WITH ACUTE */\n#define XK_ncaron                        0x01f2  /* U+0148 LATIN SMALL LETTER N WITH CARON */\n#define XK_odoubleacute                  0x01f5  /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */\n#define XK_rcaron                        0x01f8  /* U+0159 LATIN SMALL LETTER R WITH CARON */\n#define XK_uring                         0x01f9  /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */\n#define XK_udoubleacute                  0x01fb  /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */\n#define XK_tcedilla                      0x01fe  /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */\n#define XK_abovedot                      0x01ff  /* U+02D9 DOT ABOVE */\n#endif /* XK_LATIN2 */\n\n/*\n * Latin 3\n * Byte 3 = 2\n */\n\n#ifdef XK_LATIN3\n#define XK_Hstroke                       0x02a1  /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */\n#define XK_Hcircumflex                   0x02a6  /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */\n#define XK_Iabovedot                     0x02a9  /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */\n#define XK_Gbreve                        0x02ab  /* U+011E LATIN CAPITAL LETTER G WITH BREVE */\n#define XK_Jcircumflex                   0x02ac  /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */\n#define XK_hstroke                       0x02b1  /* U+0127 LATIN SMALL LETTER H WITH STROKE */\n#define XK_hcircumflex                   0x02b6  /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */\n#define XK_idotless                      0x02b9  /* U+0131 LATIN SMALL LETTER DOTLESS I */\n#define XK_gbreve                        0x02bb  /* U+011F LATIN SMALL LETTER G WITH BREVE */\n#define XK_jcircumflex                   0x02bc  /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */\n#define XK_Cabovedot                     0x02c5  /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */\n#define XK_Ccircumflex                   0x02c6  /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */\n#define XK_Gabovedot                     0x02d5  /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */\n#define XK_Gcircumflex                   0x02d8  /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */\n#define XK_Ubreve                        0x02dd  /* U+016C LATIN CAPITAL LETTER U WITH BREVE */\n#define XK_Scircumflex                   0x02de  /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */\n#define XK_cabovedot                     0x02e5  /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */\n#define XK_ccircumflex                   0x02e6  /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */\n#define XK_gabovedot                     0x02f5  /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */\n#define XK_gcircumflex                   0x02f8  /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */\n#define XK_ubreve                        0x02fd  /* U+016D LATIN SMALL LETTER U WITH BREVE */\n#define XK_scircumflex                   0x02fe  /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */\n#endif /* XK_LATIN3 */\n\n\n/*\n * Latin 4\n * Byte 3 = 3\n */\n\n#ifdef XK_LATIN4\n#define XK_kra                           0x03a2  /* U+0138 LATIN SMALL LETTER KRA */\n#define XK_kappa                         0x03a2  /* deprecated */\n#define XK_Rcedilla                      0x03a3  /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */\n#define XK_Itilde                        0x03a5  /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */\n#define XK_Lcedilla                      0x03a6  /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */\n#define XK_Emacron                       0x03aa  /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */\n#define XK_Gcedilla                      0x03ab  /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */\n#define XK_Tslash                        0x03ac  /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */\n#define XK_rcedilla                      0x03b3  /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */\n#define XK_itilde                        0x03b5  /* U+0129 LATIN SMALL LETTER I WITH TILDE */\n#define XK_lcedilla                      0x03b6  /* U+013C LATIN SMALL LETTER L WITH CEDILLA */\n#define XK_emacron                       0x03ba  /* U+0113 LATIN SMALL LETTER E WITH MACRON */\n#define XK_gcedilla                      0x03bb  /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */\n#define XK_tslash                        0x03bc  /* U+0167 LATIN SMALL LETTER T WITH STROKE */\n#define XK_ENG                           0x03bd  /* U+014A LATIN CAPITAL LETTER ENG */\n#define XK_eng                           0x03bf  /* U+014B LATIN SMALL LETTER ENG */\n#define XK_Amacron                       0x03c0  /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */\n#define XK_Iogonek                       0x03c7  /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */\n#define XK_Eabovedot                     0x03cc  /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */\n#define XK_Imacron                       0x03cf  /* U+012A LATIN CAPITAL LETTER I WITH MACRON */\n#define XK_Ncedilla                      0x03d1  /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */\n#define XK_Omacron                       0x03d2  /* U+014C LATIN CAPITAL LETTER O WITH MACRON */\n#define XK_Kcedilla                      0x03d3  /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */\n#define XK_Uogonek                       0x03d9  /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */\n#define XK_Utilde                        0x03dd  /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */\n#define XK_Umacron                       0x03de  /* U+016A LATIN CAPITAL LETTER U WITH MACRON */\n#define XK_amacron                       0x03e0  /* U+0101 LATIN SMALL LETTER A WITH MACRON */\n#define XK_iogonek                       0x03e7  /* U+012F LATIN SMALL LETTER I WITH OGONEK */\n#define XK_eabovedot                     0x03ec  /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */\n#define XK_imacron                       0x03ef  /* U+012B LATIN SMALL LETTER I WITH MACRON */\n#define XK_ncedilla                      0x03f1  /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */\n#define XK_omacron                       0x03f2  /* U+014D LATIN SMALL LETTER O WITH MACRON */\n#define XK_kcedilla                      0x03f3  /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */\n#define XK_uogonek                       0x03f9  /* U+0173 LATIN SMALL LETTER U WITH OGONEK */\n#define XK_utilde                        0x03fd  /* U+0169 LATIN SMALL LETTER U WITH TILDE */\n#define XK_umacron                       0x03fe  /* U+016B LATIN SMALL LETTER U WITH MACRON */\n#endif /* XK_LATIN4 */\n\n/*\n * Latin 8\n */\n#ifdef XK_LATIN8\n#define XK_Wcircumflex                0x1000174  /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */\n#define XK_wcircumflex                0x1000175  /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */\n#define XK_Ycircumflex                0x1000176  /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */\n#define XK_ycircumflex                0x1000177  /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */\n#define XK_Babovedot                  0x1001e02  /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */\n#define XK_babovedot                  0x1001e03  /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */\n#define XK_Dabovedot                  0x1001e0a  /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */\n#define XK_dabovedot                  0x1001e0b  /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */\n#define XK_Fabovedot                  0x1001e1e  /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */\n#define XK_fabovedot                  0x1001e1f  /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */\n#define XK_Mabovedot                  0x1001e40  /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */\n#define XK_mabovedot                  0x1001e41  /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */\n#define XK_Pabovedot                  0x1001e56  /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */\n#define XK_pabovedot                  0x1001e57  /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */\n#define XK_Sabovedot                  0x1001e60  /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */\n#define XK_sabovedot                  0x1001e61  /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */\n#define XK_Tabovedot                  0x1001e6a  /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */\n#define XK_tabovedot                  0x1001e6b  /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */\n#define XK_Wgrave                     0x1001e80  /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */\n#define XK_wgrave                     0x1001e81  /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */\n#define XK_Wacute                     0x1001e82  /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */\n#define XK_wacute                     0x1001e83  /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */\n#define XK_Wdiaeresis                 0x1001e84  /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */\n#define XK_wdiaeresis                 0x1001e85  /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */\n#define XK_Ygrave                     0x1001ef2  /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */\n#define XK_ygrave                     0x1001ef3  /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */\n#endif /* XK_LATIN8 */\n\n/*\n * Latin 9\n * Byte 3 = 0x13\n */\n\n#ifdef XK_LATIN9\n#define XK_OE                            0x13bc  /* U+0152 LATIN CAPITAL LIGATURE OE */\n#define XK_oe                            0x13bd  /* U+0153 LATIN SMALL LIGATURE OE */\n#define XK_Ydiaeresis                    0x13be  /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */\n#endif /* XK_LATIN9 */\n\n/*\n * Katakana\n * Byte 3 = 4\n */\n\n#ifdef XK_KATAKANA\n#define XK_overline                      0x047e  /* U+203E OVERLINE */\n#define XK_kana_fullstop                 0x04a1  /* U+3002 IDEOGRAPHIC FULL STOP */\n#define XK_kana_openingbracket           0x04a2  /* U+300C LEFT CORNER BRACKET */\n#define XK_kana_closingbracket           0x04a3  /* U+300D RIGHT CORNER BRACKET */\n#define XK_kana_comma                    0x04a4  /* U+3001 IDEOGRAPHIC COMMA */\n#define XK_kana_conjunctive              0x04a5  /* U+30FB KATAKANA MIDDLE DOT */\n#define XK_kana_middledot                0x04a5  /* deprecated */\n#define XK_kana_WO                       0x04a6  /* U+30F2 KATAKANA LETTER WO */\n#define XK_kana_a                        0x04a7  /* U+30A1 KATAKANA LETTER SMALL A */\n#define XK_kana_i                        0x04a8  /* U+30A3 KATAKANA LETTER SMALL I */\n#define XK_kana_u                        0x04a9  /* U+30A5 KATAKANA LETTER SMALL U */\n#define XK_kana_e                        0x04aa  /* U+30A7 KATAKANA LETTER SMALL E */\n#define XK_kana_o                        0x04ab  /* U+30A9 KATAKANA LETTER SMALL O */\n#define XK_kana_ya                       0x04ac  /* U+30E3 KATAKANA LETTER SMALL YA */\n#define XK_kana_yu                       0x04ad  /* U+30E5 KATAKANA LETTER SMALL YU */\n#define XK_kana_yo                       0x04ae  /* U+30E7 KATAKANA LETTER SMALL YO */\n#define XK_kana_tsu                      0x04af  /* U+30C3 KATAKANA LETTER SMALL TU */\n#define XK_kana_tu                       0x04af  /* deprecated */\n#define XK_prolongedsound                0x04b0  /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */\n#define XK_kana_A                        0x04b1  /* U+30A2 KATAKANA LETTER A */\n#define XK_kana_I                        0x04b2  /* U+30A4 KATAKANA LETTER I */\n#define XK_kana_U                        0x04b3  /* U+30A6 KATAKANA LETTER U */\n#define XK_kana_E                        0x04b4  /* U+30A8 KATAKANA LETTER E */\n#define XK_kana_O                        0x04b5  /* U+30AA KATAKANA LETTER O */\n#define XK_kana_KA                       0x04b6  /* U+30AB KATAKANA LETTER KA */\n#define XK_kana_KI                       0x04b7  /* U+30AD KATAKANA LETTER KI */\n#define XK_kana_KU                       0x04b8  /* U+30AF KATAKANA LETTER KU */\n#define XK_kana_KE                       0x04b9  /* U+30B1 KATAKANA LETTER KE */\n#define XK_kana_KO                       0x04ba  /* U+30B3 KATAKANA LETTER KO */\n#define XK_kana_SA                       0x04bb  /* U+30B5 KATAKANA LETTER SA */\n#define XK_kana_SHI                      0x04bc  /* U+30B7 KATAKANA LETTER SI */\n#define XK_kana_SU                       0x04bd  /* U+30B9 KATAKANA LETTER SU */\n#define XK_kana_SE                       0x04be  /* U+30BB KATAKANA LETTER SE */\n#define XK_kana_SO                       0x04bf  /* U+30BD KATAKANA LETTER SO */\n#define XK_kana_TA                       0x04c0  /* U+30BF KATAKANA LETTER TA */\n#define XK_kana_CHI                      0x04c1  /* U+30C1 KATAKANA LETTER TI */\n#define XK_kana_TI                       0x04c1  /* deprecated */\n#define XK_kana_TSU                      0x04c2  /* U+30C4 KATAKANA LETTER TU */\n#define XK_kana_TU                       0x04c2  /* deprecated */\n#define XK_kana_TE                       0x04c3  /* U+30C6 KATAKANA LETTER TE */\n#define XK_kana_TO                       0x04c4  /* U+30C8 KATAKANA LETTER TO */\n#define XK_kana_NA                       0x04c5  /* U+30CA KATAKANA LETTER NA */\n#define XK_kana_NI                       0x04c6  /* U+30CB KATAKANA LETTER NI */\n#define XK_kana_NU                       0x04c7  /* U+30CC KATAKANA LETTER NU */\n#define XK_kana_NE                       0x04c8  /* U+30CD KATAKANA LETTER NE */\n#define XK_kana_NO                       0x04c9  /* U+30CE KATAKANA LETTER NO */\n#define XK_kana_HA                       0x04ca  /* U+30CF KATAKANA LETTER HA */\n#define XK_kana_HI                       0x04cb  /* U+30D2 KATAKANA LETTER HI */\n#define XK_kana_FU                       0x04cc  /* U+30D5 KATAKANA LETTER HU */\n#define XK_kana_HU                       0x04cc  /* deprecated */\n#define XK_kana_HE                       0x04cd  /* U+30D8 KATAKANA LETTER HE */\n#define XK_kana_HO                       0x04ce  /* U+30DB KATAKANA LETTER HO */\n#define XK_kana_MA                       0x04cf  /* U+30DE KATAKANA LETTER MA */\n#define XK_kana_MI                       0x04d0  /* U+30DF KATAKANA LETTER MI */\n#define XK_kana_MU                       0x04d1  /* U+30E0 KATAKANA LETTER MU */\n#define XK_kana_ME                       0x04d2  /* U+30E1 KATAKANA LETTER ME */\n#define XK_kana_MO                       0x04d3  /* U+30E2 KATAKANA LETTER MO */\n#define XK_kana_YA                       0x04d4  /* U+30E4 KATAKANA LETTER YA */\n#define XK_kana_YU                       0x04d5  /* U+30E6 KATAKANA LETTER YU */\n#define XK_kana_YO                       0x04d6  /* U+30E8 KATAKANA LETTER YO */\n#define XK_kana_RA                       0x04d7  /* U+30E9 KATAKANA LETTER RA */\n#define XK_kana_RI                       0x04d8  /* U+30EA KATAKANA LETTER RI */\n#define XK_kana_RU                       0x04d9  /* U+30EB KATAKANA LETTER RU */\n#define XK_kana_RE                       0x04da  /* U+30EC KATAKANA LETTER RE */\n#define XK_kana_RO                       0x04db  /* U+30ED KATAKANA LETTER RO */\n#define XK_kana_WA                       0x04dc  /* U+30EF KATAKANA LETTER WA */\n#define XK_kana_N                        0x04dd  /* U+30F3 KATAKANA LETTER N */\n#define XK_voicedsound                   0x04de  /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */\n#define XK_semivoicedsound               0x04df  /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */\n#define XK_kana_switch                   0xff7e  /* non-deprecated alias for Mode_switch */\n#endif /* XK_KATAKANA */\n\n/*\n * Arabic\n * Byte 3 = 5\n */\n\n#ifdef XK_ARABIC\n#define XK_Farsi_0                    0x10006f0  /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */\n#define XK_Farsi_1                    0x10006f1  /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */\n#define XK_Farsi_2                    0x10006f2  /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */\n#define XK_Farsi_3                    0x10006f3  /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */\n#define XK_Farsi_4                    0x10006f4  /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */\n#define XK_Farsi_5                    0x10006f5  /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */\n#define XK_Farsi_6                    0x10006f6  /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */\n#define XK_Farsi_7                    0x10006f7  /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */\n#define XK_Farsi_8                    0x10006f8  /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */\n#define XK_Farsi_9                    0x10006f9  /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */\n#define XK_Arabic_percent             0x100066a  /* U+066A ARABIC PERCENT SIGN */\n#define XK_Arabic_superscript_alef    0x1000670  /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */\n#define XK_Arabic_tteh                0x1000679  /* U+0679 ARABIC LETTER TTEH */\n#define XK_Arabic_peh                 0x100067e  /* U+067E ARABIC LETTER PEH */\n#define XK_Arabic_tcheh               0x1000686  /* U+0686 ARABIC LETTER TCHEH */\n#define XK_Arabic_ddal                0x1000688  /* U+0688 ARABIC LETTER DDAL */\n#define XK_Arabic_rreh                0x1000691  /* U+0691 ARABIC LETTER RREH */\n#define XK_Arabic_comma                  0x05ac  /* U+060C ARABIC COMMA */\n#define XK_Arabic_fullstop            0x10006d4  /* U+06D4 ARABIC FULL STOP */\n#define XK_Arabic_0                   0x1000660  /* U+0660 ARABIC-INDIC DIGIT ZERO */\n#define XK_Arabic_1                   0x1000661  /* U+0661 ARABIC-INDIC DIGIT ONE */\n#define XK_Arabic_2                   0x1000662  /* U+0662 ARABIC-INDIC DIGIT TWO */\n#define XK_Arabic_3                   0x1000663  /* U+0663 ARABIC-INDIC DIGIT THREE */\n#define XK_Arabic_4                   0x1000664  /* U+0664 ARABIC-INDIC DIGIT FOUR */\n#define XK_Arabic_5                   0x1000665  /* U+0665 ARABIC-INDIC DIGIT FIVE */\n#define XK_Arabic_6                   0x1000666  /* U+0666 ARABIC-INDIC DIGIT SIX */\n#define XK_Arabic_7                   0x1000667  /* U+0667 ARABIC-INDIC DIGIT SEVEN */\n#define XK_Arabic_8                   0x1000668  /* U+0668 ARABIC-INDIC DIGIT EIGHT */\n#define XK_Arabic_9                   0x1000669  /* U+0669 ARABIC-INDIC DIGIT NINE */\n#define XK_Arabic_semicolon              0x05bb  /* U+061B ARABIC SEMICOLON */\n#define XK_Arabic_question_mark          0x05bf  /* U+061F ARABIC QUESTION MARK */\n#define XK_Arabic_hamza                  0x05c1  /* U+0621 ARABIC LETTER HAMZA */\n#define XK_Arabic_maddaonalef            0x05c2  /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */\n#define XK_Arabic_hamzaonalef            0x05c3  /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */\n#define XK_Arabic_hamzaonwaw             0x05c4  /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */\n#define XK_Arabic_hamzaunderalef         0x05c5  /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */\n#define XK_Arabic_hamzaonyeh             0x05c6  /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */\n#define XK_Arabic_alef                   0x05c7  /* U+0627 ARABIC LETTER ALEF */\n#define XK_Arabic_beh                    0x05c8  /* U+0628 ARABIC LETTER BEH */\n#define XK_Arabic_tehmarbuta             0x05c9  /* U+0629 ARABIC LETTER TEH MARBUTA */\n#define XK_Arabic_teh                    0x05ca  /* U+062A ARABIC LETTER TEH */\n#define XK_Arabic_theh                   0x05cb  /* U+062B ARABIC LETTER THEH */\n#define XK_Arabic_jeem                   0x05cc  /* U+062C ARABIC LETTER JEEM */\n#define XK_Arabic_hah                    0x05cd  /* U+062D ARABIC LETTER HAH */\n#define XK_Arabic_khah                   0x05ce  /* U+062E ARABIC LETTER KHAH */\n#define XK_Arabic_dal                    0x05cf  /* U+062F ARABIC LETTER DAL */\n#define XK_Arabic_thal                   0x05d0  /* U+0630 ARABIC LETTER THAL */\n#define XK_Arabic_ra                     0x05d1  /* U+0631 ARABIC LETTER REH */\n#define XK_Arabic_zain                   0x05d2  /* U+0632 ARABIC LETTER ZAIN */\n#define XK_Arabic_seen                   0x05d3  /* U+0633 ARABIC LETTER SEEN */\n#define XK_Arabic_sheen                  0x05d4  /* U+0634 ARABIC LETTER SHEEN */\n#define XK_Arabic_sad                    0x05d5  /* U+0635 ARABIC LETTER SAD */\n#define XK_Arabic_dad                    0x05d6  /* U+0636 ARABIC LETTER DAD */\n#define XK_Arabic_tah                    0x05d7  /* U+0637 ARABIC LETTER TAH */\n#define XK_Arabic_zah                    0x05d8  /* U+0638 ARABIC LETTER ZAH */\n#define XK_Arabic_ain                    0x05d9  /* U+0639 ARABIC LETTER AIN */\n#define XK_Arabic_ghain                  0x05da  /* U+063A ARABIC LETTER GHAIN */\n#define XK_Arabic_tatweel                0x05e0  /* U+0640 ARABIC TATWEEL */\n#define XK_Arabic_feh                    0x05e1  /* U+0641 ARABIC LETTER FEH */\n#define XK_Arabic_qaf                    0x05e2  /* U+0642 ARABIC LETTER QAF */\n#define XK_Arabic_kaf                    0x05e3  /* U+0643 ARABIC LETTER KAF */\n#define XK_Arabic_lam                    0x05e4  /* U+0644 ARABIC LETTER LAM */\n#define XK_Arabic_meem                   0x05e5  /* U+0645 ARABIC LETTER MEEM */\n#define XK_Arabic_noon                   0x05e6  /* U+0646 ARABIC LETTER NOON */\n#define XK_Arabic_ha                     0x05e7  /* U+0647 ARABIC LETTER HEH */\n#define XK_Arabic_heh                    0x05e7  /* deprecated */\n#define XK_Arabic_waw                    0x05e8  /* U+0648 ARABIC LETTER WAW */\n#define XK_Arabic_alefmaksura            0x05e9  /* U+0649 ARABIC LETTER ALEF MAKSURA */\n#define XK_Arabic_yeh                    0x05ea  /* U+064A ARABIC LETTER YEH */\n#define XK_Arabic_fathatan               0x05eb  /* U+064B ARABIC FATHATAN */\n#define XK_Arabic_dammatan               0x05ec  /* U+064C ARABIC DAMMATAN */\n#define XK_Arabic_kasratan               0x05ed  /* U+064D ARABIC KASRATAN */\n#define XK_Arabic_fatha                  0x05ee  /* U+064E ARABIC FATHA */\n#define XK_Arabic_damma                  0x05ef  /* U+064F ARABIC DAMMA */\n#define XK_Arabic_kasra                  0x05f0  /* U+0650 ARABIC KASRA */\n#define XK_Arabic_shadda                 0x05f1  /* U+0651 ARABIC SHADDA */\n#define XK_Arabic_sukun                  0x05f2  /* U+0652 ARABIC SUKUN */\n#define XK_Arabic_madda_above         0x1000653  /* U+0653 ARABIC MADDAH ABOVE */\n#define XK_Arabic_hamza_above         0x1000654  /* U+0654 ARABIC HAMZA ABOVE */\n#define XK_Arabic_hamza_below         0x1000655  /* U+0655 ARABIC HAMZA BELOW */\n#define XK_Arabic_jeh                 0x1000698  /* U+0698 ARABIC LETTER JEH */\n#define XK_Arabic_veh                 0x10006a4  /* U+06A4 ARABIC LETTER VEH */\n#define XK_Arabic_keheh               0x10006a9  /* U+06A9 ARABIC LETTER KEHEH */\n#define XK_Arabic_gaf                 0x10006af  /* U+06AF ARABIC LETTER GAF */\n#define XK_Arabic_noon_ghunna         0x10006ba  /* U+06BA ARABIC LETTER NOON GHUNNA */\n#define XK_Arabic_heh_doachashmee     0x10006be  /* U+06BE ARABIC LETTER HEH DOACHASHMEE */\n#define XK_Farsi_yeh                  0x10006cc  /* U+06CC ARABIC LETTER FARSI YEH */\n#define XK_Arabic_farsi_yeh           0x10006cc  /* deprecated alias for Farsi_yeh */\n#define XK_Arabic_yeh_baree           0x10006d2  /* U+06D2 ARABIC LETTER YEH BARREE */\n#define XK_Arabic_heh_goal            0x10006c1  /* U+06C1 ARABIC LETTER HEH GOAL */\n#define XK_Arabic_switch                 0xff7e  /* non-deprecated alias for Mode_switch */\n#endif /* XK_ARABIC */\n\n/*\n * Cyrillic\n * Byte 3 = 6\n */\n#ifdef XK_CYRILLIC\n#define XK_Cyrillic_GHE_bar           0x1000492  /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */\n#define XK_Cyrillic_ghe_bar           0x1000493  /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */\n#define XK_Cyrillic_ZHE_descender     0x1000496  /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */\n#define XK_Cyrillic_zhe_descender     0x1000497  /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */\n#define XK_Cyrillic_KA_descender      0x100049a  /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */\n#define XK_Cyrillic_ka_descender      0x100049b  /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */\n#define XK_Cyrillic_KA_vertstroke     0x100049c  /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */\n#define XK_Cyrillic_ka_vertstroke     0x100049d  /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */\n#define XK_Cyrillic_EN_descender      0x10004a2  /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */\n#define XK_Cyrillic_en_descender      0x10004a3  /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */\n#define XK_Cyrillic_U_straight        0x10004ae  /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */\n#define XK_Cyrillic_u_straight        0x10004af  /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */\n#define XK_Cyrillic_U_straight_bar    0x10004b0  /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */\n#define XK_Cyrillic_u_straight_bar    0x10004b1  /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */\n#define XK_Cyrillic_HA_descender      0x10004b2  /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */\n#define XK_Cyrillic_ha_descender      0x10004b3  /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */\n#define XK_Cyrillic_CHE_descender     0x10004b6  /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */\n#define XK_Cyrillic_che_descender     0x10004b7  /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */\n#define XK_Cyrillic_CHE_vertstroke    0x10004b8  /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */\n#define XK_Cyrillic_che_vertstroke    0x10004b9  /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */\n#define XK_Cyrillic_SHHA              0x10004ba  /* U+04BA CYRILLIC CAPITAL LETTER SHHA */\n#define XK_Cyrillic_shha              0x10004bb  /* U+04BB CYRILLIC SMALL LETTER SHHA */\n\n#define XK_Cyrillic_SCHWA             0x10004d8  /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */\n#define XK_Cyrillic_schwa             0x10004d9  /* U+04D9 CYRILLIC SMALL LETTER SCHWA */\n#define XK_Cyrillic_I_macron          0x10004e2  /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */\n#define XK_Cyrillic_i_macron          0x10004e3  /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */\n#define XK_Cyrillic_O_bar             0x10004e8  /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */\n#define XK_Cyrillic_o_bar             0x10004e9  /* U+04E9 CYRILLIC SMALL LETTER BARRED O */\n#define XK_Cyrillic_U_macron          0x10004ee  /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */\n#define XK_Cyrillic_u_macron          0x10004ef  /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */\n\n#define XK_Serbian_dje                   0x06a1  /* U+0452 CYRILLIC SMALL LETTER DJE */\n#define XK_Macedonia_gje                 0x06a2  /* U+0453 CYRILLIC SMALL LETTER GJE */\n#define XK_Cyrillic_io                   0x06a3  /* U+0451 CYRILLIC SMALL LETTER IO */\n#define XK_Ukrainian_ie                  0x06a4  /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */\n#define XK_Ukranian_je                   0x06a4  /* deprecated */\n#define XK_Macedonia_dse                 0x06a5  /* U+0455 CYRILLIC SMALL LETTER DZE */\n#define XK_Ukrainian_i                   0x06a6  /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */\n#define XK_Ukranian_i                    0x06a6  /* deprecated */\n#define XK_Ukrainian_yi                  0x06a7  /* U+0457 CYRILLIC SMALL LETTER YI */\n#define XK_Ukranian_yi                   0x06a7  /* deprecated */\n#define XK_Cyrillic_je                   0x06a8  /* U+0458 CYRILLIC SMALL LETTER JE */\n#define XK_Serbian_je                    0x06a8  /* deprecated */\n#define XK_Cyrillic_lje                  0x06a9  /* U+0459 CYRILLIC SMALL LETTER LJE */\n#define XK_Serbian_lje                   0x06a9  /* deprecated */\n#define XK_Cyrillic_nje                  0x06aa  /* U+045A CYRILLIC SMALL LETTER NJE */\n#define XK_Serbian_nje                   0x06aa  /* deprecated */\n#define XK_Serbian_tshe                  0x06ab  /* U+045B CYRILLIC SMALL LETTER TSHE */\n#define XK_Macedonia_kje                 0x06ac  /* U+045C CYRILLIC SMALL LETTER KJE */\n#define XK_Ukrainian_ghe_with_upturn     0x06ad  /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */\n#define XK_Byelorussian_shortu           0x06ae  /* U+045E CYRILLIC SMALL LETTER SHORT U */\n#define XK_Cyrillic_dzhe                 0x06af  /* U+045F CYRILLIC SMALL LETTER DZHE */\n#define XK_Serbian_dze                   0x06af  /* deprecated */\n#define XK_numerosign                    0x06b0  /* U+2116 NUMERO SIGN */\n#define XK_Serbian_DJE                   0x06b1  /* U+0402 CYRILLIC CAPITAL LETTER DJE */\n#define XK_Macedonia_GJE                 0x06b2  /* U+0403 CYRILLIC CAPITAL LETTER GJE */\n#define XK_Cyrillic_IO                   0x06b3  /* U+0401 CYRILLIC CAPITAL LETTER IO */\n#define XK_Ukrainian_IE                  0x06b4  /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */\n#define XK_Ukranian_JE                   0x06b4  /* deprecated */\n#define XK_Macedonia_DSE                 0x06b5  /* U+0405 CYRILLIC CAPITAL LETTER DZE */\n#define XK_Ukrainian_I                   0x06b6  /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */\n#define XK_Ukranian_I                    0x06b6  /* deprecated */\n#define XK_Ukrainian_YI                  0x06b7  /* U+0407 CYRILLIC CAPITAL LETTER YI */\n#define XK_Ukranian_YI                   0x06b7  /* deprecated */\n#define XK_Cyrillic_JE                   0x06b8  /* U+0408 CYRILLIC CAPITAL LETTER JE */\n#define XK_Serbian_JE                    0x06b8  /* deprecated */\n#define XK_Cyrillic_LJE                  0x06b9  /* U+0409 CYRILLIC CAPITAL LETTER LJE */\n#define XK_Serbian_LJE                   0x06b9  /* deprecated */\n#define XK_Cyrillic_NJE                  0x06ba  /* U+040A CYRILLIC CAPITAL LETTER NJE */\n#define XK_Serbian_NJE                   0x06ba  /* deprecated */\n#define XK_Serbian_TSHE                  0x06bb  /* U+040B CYRILLIC CAPITAL LETTER TSHE */\n#define XK_Macedonia_KJE                 0x06bc  /* U+040C CYRILLIC CAPITAL LETTER KJE */\n#define XK_Ukrainian_GHE_WITH_UPTURN     0x06bd  /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */\n#define XK_Byelorussian_SHORTU           0x06be  /* U+040E CYRILLIC CAPITAL LETTER SHORT U */\n#define XK_Cyrillic_DZHE                 0x06bf  /* U+040F CYRILLIC CAPITAL LETTER DZHE */\n#define XK_Serbian_DZE                   0x06bf  /* deprecated */\n#define XK_Cyrillic_yu                   0x06c0  /* U+044E CYRILLIC SMALL LETTER YU */\n#define XK_Cyrillic_a                    0x06c1  /* U+0430 CYRILLIC SMALL LETTER A */\n#define XK_Cyrillic_be                   0x06c2  /* U+0431 CYRILLIC SMALL LETTER BE */\n#define XK_Cyrillic_tse                  0x06c3  /* U+0446 CYRILLIC SMALL LETTER TSE */\n#define XK_Cyrillic_de                   0x06c4  /* U+0434 CYRILLIC SMALL LETTER DE */\n#define XK_Cyrillic_ie                   0x06c5  /* U+0435 CYRILLIC SMALL LETTER IE */\n#define XK_Cyrillic_ef                   0x06c6  /* U+0444 CYRILLIC SMALL LETTER EF */\n#define XK_Cyrillic_ghe                  0x06c7  /* U+0433 CYRILLIC SMALL LETTER GHE */\n#define XK_Cyrillic_ha                   0x06c8  /* U+0445 CYRILLIC SMALL LETTER HA */\n#define XK_Cyrillic_i                    0x06c9  /* U+0438 CYRILLIC SMALL LETTER I */\n#define XK_Cyrillic_shorti               0x06ca  /* U+0439 CYRILLIC SMALL LETTER SHORT I */\n#define XK_Cyrillic_ka                   0x06cb  /* U+043A CYRILLIC SMALL LETTER KA */\n#define XK_Cyrillic_el                   0x06cc  /* U+043B CYRILLIC SMALL LETTER EL */\n#define XK_Cyrillic_em                   0x06cd  /* U+043C CYRILLIC SMALL LETTER EM */\n#define XK_Cyrillic_en                   0x06ce  /* U+043D CYRILLIC SMALL LETTER EN */\n#define XK_Cyrillic_o                    0x06cf  /* U+043E CYRILLIC SMALL LETTER O */\n#define XK_Cyrillic_pe                   0x06d0  /* U+043F CYRILLIC SMALL LETTER PE */\n#define XK_Cyrillic_ya                   0x06d1  /* U+044F CYRILLIC SMALL LETTER YA */\n#define XK_Cyrillic_er                   0x06d2  /* U+0440 CYRILLIC SMALL LETTER ER */\n#define XK_Cyrillic_es                   0x06d3  /* U+0441 CYRILLIC SMALL LETTER ES */\n#define XK_Cyrillic_te                   0x06d4  /* U+0442 CYRILLIC SMALL LETTER TE */\n#define XK_Cyrillic_u                    0x06d5  /* U+0443 CYRILLIC SMALL LETTER U */\n#define XK_Cyrillic_zhe                  0x06d6  /* U+0436 CYRILLIC SMALL LETTER ZHE */\n#define XK_Cyrillic_ve                   0x06d7  /* U+0432 CYRILLIC SMALL LETTER VE */\n#define XK_Cyrillic_softsign             0x06d8  /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */\n#define XK_Cyrillic_yeru                 0x06d9  /* U+044B CYRILLIC SMALL LETTER YERU */\n#define XK_Cyrillic_ze                   0x06da  /* U+0437 CYRILLIC SMALL LETTER ZE */\n#define XK_Cyrillic_sha                  0x06db  /* U+0448 CYRILLIC SMALL LETTER SHA */\n#define XK_Cyrillic_e                    0x06dc  /* U+044D CYRILLIC SMALL LETTER E */\n#define XK_Cyrillic_shcha                0x06dd  /* U+0449 CYRILLIC SMALL LETTER SHCHA */\n#define XK_Cyrillic_che                  0x06de  /* U+0447 CYRILLIC SMALL LETTER CHE */\n#define XK_Cyrillic_hardsign             0x06df  /* U+044A CYRILLIC SMALL LETTER HARD SIGN */\n#define XK_Cyrillic_YU                   0x06e0  /* U+042E CYRILLIC CAPITAL LETTER YU */\n#define XK_Cyrillic_A                    0x06e1  /* U+0410 CYRILLIC CAPITAL LETTER A */\n#define XK_Cyrillic_BE                   0x06e2  /* U+0411 CYRILLIC CAPITAL LETTER BE */\n#define XK_Cyrillic_TSE                  0x06e3  /* U+0426 CYRILLIC CAPITAL LETTER TSE */\n#define XK_Cyrillic_DE                   0x06e4  /* U+0414 CYRILLIC CAPITAL LETTER DE */\n#define XK_Cyrillic_IE                   0x06e5  /* U+0415 CYRILLIC CAPITAL LETTER IE */\n#define XK_Cyrillic_EF                   0x06e6  /* U+0424 CYRILLIC CAPITAL LETTER EF */\n#define XK_Cyrillic_GHE                  0x06e7  /* U+0413 CYRILLIC CAPITAL LETTER GHE */\n#define XK_Cyrillic_HA                   0x06e8  /* U+0425 CYRILLIC CAPITAL LETTER HA */\n#define XK_Cyrillic_I                    0x06e9  /* U+0418 CYRILLIC CAPITAL LETTER I */\n#define XK_Cyrillic_SHORTI               0x06ea  /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */\n#define XK_Cyrillic_KA                   0x06eb  /* U+041A CYRILLIC CAPITAL LETTER KA */\n#define XK_Cyrillic_EL                   0x06ec  /* U+041B CYRILLIC CAPITAL LETTER EL */\n#define XK_Cyrillic_EM                   0x06ed  /* U+041C CYRILLIC CAPITAL LETTER EM */\n#define XK_Cyrillic_EN                   0x06ee  /* U+041D CYRILLIC CAPITAL LETTER EN */\n#define XK_Cyrillic_O                    0x06ef  /* U+041E CYRILLIC CAPITAL LETTER O */\n#define XK_Cyrillic_PE                   0x06f0  /* U+041F CYRILLIC CAPITAL LETTER PE */\n#define XK_Cyrillic_YA                   0x06f1  /* U+042F CYRILLIC CAPITAL LETTER YA */\n#define XK_Cyrillic_ER                   0x06f2  /* U+0420 CYRILLIC CAPITAL LETTER ER */\n#define XK_Cyrillic_ES                   0x06f3  /* U+0421 CYRILLIC CAPITAL LETTER ES */\n#define XK_Cyrillic_TE                   0x06f4  /* U+0422 CYRILLIC CAPITAL LETTER TE */\n#define XK_Cyrillic_U                    0x06f5  /* U+0423 CYRILLIC CAPITAL LETTER U */\n#define XK_Cyrillic_ZHE                  0x06f6  /* U+0416 CYRILLIC CAPITAL LETTER ZHE */\n#define XK_Cyrillic_VE                   0x06f7  /* U+0412 CYRILLIC CAPITAL LETTER VE */\n#define XK_Cyrillic_SOFTSIGN             0x06f8  /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */\n#define XK_Cyrillic_YERU                 0x06f9  /* U+042B CYRILLIC CAPITAL LETTER YERU */\n#define XK_Cyrillic_ZE                   0x06fa  /* U+0417 CYRILLIC CAPITAL LETTER ZE */\n#define XK_Cyrillic_SHA                  0x06fb  /* U+0428 CYRILLIC CAPITAL LETTER SHA */\n#define XK_Cyrillic_E                    0x06fc  /* U+042D CYRILLIC CAPITAL LETTER E */\n#define XK_Cyrillic_SHCHA                0x06fd  /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */\n#define XK_Cyrillic_CHE                  0x06fe  /* U+0427 CYRILLIC CAPITAL LETTER CHE */\n#define XK_Cyrillic_HARDSIGN             0x06ff  /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */\n#endif /* XK_CYRILLIC */\n\n/*\n * Greek\n * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7)\n * Byte 3 = 7\n */\n\n#ifdef XK_GREEK\n#define XK_Greek_ALPHAaccent             0x07a1  /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */\n#define XK_Greek_EPSILONaccent           0x07a2  /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */\n#define XK_Greek_ETAaccent               0x07a3  /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */\n#define XK_Greek_IOTAaccent              0x07a4  /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */\n#define XK_Greek_IOTAdieresis            0x07a5  /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */\n#define XK_Greek_IOTAdiaeresis           0x07a5  /* deprecated (old typo) */\n#define XK_Greek_OMICRONaccent           0x07a7  /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */\n#define XK_Greek_UPSILONaccent           0x07a8  /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */\n#define XK_Greek_UPSILONdieresis         0x07a9  /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */\n#define XK_Greek_OMEGAaccent             0x07ab  /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */\n#define XK_Greek_accentdieresis          0x07ae  /* U+0385 GREEK DIALYTIKA TONOS */\n#define XK_Greek_horizbar                0x07af  /* U+2015 HORIZONTAL BAR */\n#define XK_Greek_alphaaccent             0x07b1  /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */\n#define XK_Greek_epsilonaccent           0x07b2  /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */\n#define XK_Greek_etaaccent               0x07b3  /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */\n#define XK_Greek_iotaaccent              0x07b4  /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */\n#define XK_Greek_iotadieresis            0x07b5  /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */\n#define XK_Greek_iotaaccentdieresis      0x07b6  /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */\n#define XK_Greek_omicronaccent           0x07b7  /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */\n#define XK_Greek_upsilonaccent           0x07b8  /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */\n#define XK_Greek_upsilondieresis         0x07b9  /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */\n#define XK_Greek_upsilonaccentdieresis   0x07ba  /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */\n#define XK_Greek_omegaaccent             0x07bb  /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */\n#define XK_Greek_ALPHA                   0x07c1  /* U+0391 GREEK CAPITAL LETTER ALPHA */\n#define XK_Greek_BETA                    0x07c2  /* U+0392 GREEK CAPITAL LETTER BETA */\n#define XK_Greek_GAMMA                   0x07c3  /* U+0393 GREEK CAPITAL LETTER GAMMA */\n#define XK_Greek_DELTA                   0x07c4  /* U+0394 GREEK CAPITAL LETTER DELTA */\n#define XK_Greek_EPSILON                 0x07c5  /* U+0395 GREEK CAPITAL LETTER EPSILON */\n#define XK_Greek_ZETA                    0x07c6  /* U+0396 GREEK CAPITAL LETTER ZETA */\n#define XK_Greek_ETA                     0x07c7  /* U+0397 GREEK CAPITAL LETTER ETA */\n#define XK_Greek_THETA                   0x07c8  /* U+0398 GREEK CAPITAL LETTER THETA */\n#define XK_Greek_IOTA                    0x07c9  /* U+0399 GREEK CAPITAL LETTER IOTA */\n#define XK_Greek_KAPPA                   0x07ca  /* U+039A GREEK CAPITAL LETTER KAPPA */\n#define XK_Greek_LAMDA                   0x07cb  /* U+039B GREEK CAPITAL LETTER LAMDA */\n#define XK_Greek_LAMBDA                  0x07cb  /* non-deprecated alias for Greek_LAMDA */\n#define XK_Greek_MU                      0x07cc  /* U+039C GREEK CAPITAL LETTER MU */\n#define XK_Greek_NU                      0x07cd  /* U+039D GREEK CAPITAL LETTER NU */\n#define XK_Greek_XI                      0x07ce  /* U+039E GREEK CAPITAL LETTER XI */\n#define XK_Greek_OMICRON                 0x07cf  /* U+039F GREEK CAPITAL LETTER OMICRON */\n#define XK_Greek_PI                      0x07d0  /* U+03A0 GREEK CAPITAL LETTER PI */\n#define XK_Greek_RHO                     0x07d1  /* U+03A1 GREEK CAPITAL LETTER RHO */\n#define XK_Greek_SIGMA                   0x07d2  /* U+03A3 GREEK CAPITAL LETTER SIGMA */\n#define XK_Greek_TAU                     0x07d4  /* U+03A4 GREEK CAPITAL LETTER TAU */\n#define XK_Greek_UPSILON                 0x07d5  /* U+03A5 GREEK CAPITAL LETTER UPSILON */\n#define XK_Greek_PHI                     0x07d6  /* U+03A6 GREEK CAPITAL LETTER PHI */\n#define XK_Greek_CHI                     0x07d7  /* U+03A7 GREEK CAPITAL LETTER CHI */\n#define XK_Greek_PSI                     0x07d8  /* U+03A8 GREEK CAPITAL LETTER PSI */\n#define XK_Greek_OMEGA                   0x07d9  /* U+03A9 GREEK CAPITAL LETTER OMEGA */\n#define XK_Greek_alpha                   0x07e1  /* U+03B1 GREEK SMALL LETTER ALPHA */\n#define XK_Greek_beta                    0x07e2  /* U+03B2 GREEK SMALL LETTER BETA */\n#define XK_Greek_gamma                   0x07e3  /* U+03B3 GREEK SMALL LETTER GAMMA */\n#define XK_Greek_delta                   0x07e4  /* U+03B4 GREEK SMALL LETTER DELTA */\n#define XK_Greek_epsilon                 0x07e5  /* U+03B5 GREEK SMALL LETTER EPSILON */\n#define XK_Greek_zeta                    0x07e6  /* U+03B6 GREEK SMALL LETTER ZETA */\n#define XK_Greek_eta                     0x07e7  /* U+03B7 GREEK SMALL LETTER ETA */\n#define XK_Greek_theta                   0x07e8  /* U+03B8 GREEK SMALL LETTER THETA */\n#define XK_Greek_iota                    0x07e9  /* U+03B9 GREEK SMALL LETTER IOTA */\n#define XK_Greek_kappa                   0x07ea  /* U+03BA GREEK SMALL LETTER KAPPA */\n#define XK_Greek_lamda                   0x07eb  /* U+03BB GREEK SMALL LETTER LAMDA */\n#define XK_Greek_lambda                  0x07eb  /* non-deprecated alias for Greek_lamda */\n#define XK_Greek_mu                      0x07ec  /* U+03BC GREEK SMALL LETTER MU */\n#define XK_Greek_nu                      0x07ed  /* U+03BD GREEK SMALL LETTER NU */\n#define XK_Greek_xi                      0x07ee  /* U+03BE GREEK SMALL LETTER XI */\n#define XK_Greek_omicron                 0x07ef  /* U+03BF GREEK SMALL LETTER OMICRON */\n#define XK_Greek_pi                      0x07f0  /* U+03C0 GREEK SMALL LETTER PI */\n#define XK_Greek_rho                     0x07f1  /* U+03C1 GREEK SMALL LETTER RHO */\n#define XK_Greek_sigma                   0x07f2  /* U+03C3 GREEK SMALL LETTER SIGMA */\n#define XK_Greek_finalsmallsigma         0x07f3  /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */\n#define XK_Greek_tau                     0x07f4  /* U+03C4 GREEK SMALL LETTER TAU */\n#define XK_Greek_upsilon                 0x07f5  /* U+03C5 GREEK SMALL LETTER UPSILON */\n#define XK_Greek_phi                     0x07f6  /* U+03C6 GREEK SMALL LETTER PHI */\n#define XK_Greek_chi                     0x07f7  /* U+03C7 GREEK SMALL LETTER CHI */\n#define XK_Greek_psi                     0x07f8  /* U+03C8 GREEK SMALL LETTER PSI */\n#define XK_Greek_omega                   0x07f9  /* U+03C9 GREEK SMALL LETTER OMEGA */\n#define XK_Greek_switch                  0xff7e  /* non-deprecated alias for Mode_switch */\n#endif /* XK_GREEK */\n\n/*\n * Technical\n * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html)\n * Byte 3 = 8\n */\n\n#ifdef XK_TECHNICAL\n#define XK_leftradical                   0x08a1  /* U+23B7 RADICAL SYMBOL BOTTOM */\n#define XK_topleftradical                0x08a2  /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/\n#define XK_horizconnector                0x08a3  /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/\n#define XK_topintegral                   0x08a4  /* U+2320 TOP HALF INTEGRAL */\n#define XK_botintegral                   0x08a5  /* U+2321 BOTTOM HALF INTEGRAL */\n#define XK_vertconnector                 0x08a6  /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/\n#define XK_topleftsqbracket              0x08a7  /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */\n#define XK_botleftsqbracket              0x08a8  /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */\n#define XK_toprightsqbracket             0x08a9  /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */\n#define XK_botrightsqbracket             0x08aa  /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */\n#define XK_topleftparens                 0x08ab  /* U+239B LEFT PARENTHESIS UPPER HOOK */\n#define XK_botleftparens                 0x08ac  /* U+239D LEFT PARENTHESIS LOWER HOOK */\n#define XK_toprightparens                0x08ad  /* U+239E RIGHT PARENTHESIS UPPER HOOK */\n#define XK_botrightparens                0x08ae  /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */\n#define XK_leftmiddlecurlybrace          0x08af  /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */\n#define XK_rightmiddlecurlybrace         0x08b0  /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */\n#define XK_topleftsummation              0x08b1\n#define XK_botleftsummation              0x08b2\n#define XK_topvertsummationconnector     0x08b3\n#define XK_botvertsummationconnector     0x08b4\n#define XK_toprightsummation             0x08b5\n#define XK_botrightsummation             0x08b6\n#define XK_rightmiddlesummation          0x08b7\n#define XK_lessthanequal                 0x08bc  /* U+2264 LESS-THAN OR EQUAL TO */\n#define XK_notequal                      0x08bd  /* U+2260 NOT EQUAL TO */\n#define XK_greaterthanequal              0x08be  /* U+2265 GREATER-THAN OR EQUAL TO */\n#define XK_integral                      0x08bf  /* U+222B INTEGRAL */\n#define XK_therefore                     0x08c0  /* U+2234 THEREFORE */\n#define XK_variation                     0x08c1  /* U+221D PROPORTIONAL TO */\n#define XK_infinity                      0x08c2  /* U+221E INFINITY */\n#define XK_nabla                         0x08c5  /* U+2207 NABLA */\n#define XK_approximate                   0x08c8  /* U+223C TILDE OPERATOR */\n#define XK_similarequal                  0x08c9  /* U+2243 ASYMPTOTICALLY EQUAL TO */\n#define XK_ifonlyif                      0x08cd  /* U+21D4 LEFT RIGHT DOUBLE ARROW */\n#define XK_implies                       0x08ce  /* U+21D2 RIGHTWARDS DOUBLE ARROW */\n#define XK_identical                     0x08cf  /* U+2261 IDENTICAL TO */\n#define XK_radical                       0x08d6  /* U+221A SQUARE ROOT */\n#define XK_includedin                    0x08da  /* U+2282 SUBSET OF */\n#define XK_includes                      0x08db  /* U+2283 SUPERSET OF */\n#define XK_intersection                  0x08dc  /* U+2229 INTERSECTION */\n#define XK_union                         0x08dd  /* U+222A UNION */\n#define XK_logicaland                    0x08de  /* U+2227 LOGICAL AND */\n#define XK_logicalor                     0x08df  /* U+2228 LOGICAL OR */\n#define XK_partialderivative             0x08ef  /* U+2202 PARTIAL DIFFERENTIAL */\n#define XK_function                      0x08f6  /* U+0192 LATIN SMALL LETTER F WITH HOOK */\n#define XK_leftarrow                     0x08fb  /* U+2190 LEFTWARDS ARROW */\n#define XK_uparrow                       0x08fc  /* U+2191 UPWARDS ARROW */\n#define XK_rightarrow                    0x08fd  /* U+2192 RIGHTWARDS ARROW */\n#define XK_downarrow                     0x08fe  /* U+2193 DOWNWARDS ARROW */\n#endif /* XK_TECHNICAL */\n\n/*\n * Special\n * (from the DEC VT100 Special Graphics Character Set)\n * Byte 3 = 9\n */\n\n#ifdef XK_SPECIAL\n#define XK_blank                         0x09df\n#define XK_soliddiamond                  0x09e0  /* U+25C6 BLACK DIAMOND */\n#define XK_checkerboard                  0x09e1  /* U+2592 MEDIUM SHADE */\n#define XK_ht                            0x09e2  /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */\n#define XK_ff                            0x09e3  /* U+240C SYMBOL FOR FORM FEED */\n#define XK_cr                            0x09e4  /* U+240D SYMBOL FOR CARRIAGE RETURN */\n#define XK_lf                            0x09e5  /* U+240A SYMBOL FOR LINE FEED */\n#define XK_nl                            0x09e8  /* U+2424 SYMBOL FOR NEWLINE */\n#define XK_vt                            0x09e9  /* U+240B SYMBOL FOR VERTICAL TABULATION */\n#define XK_lowrightcorner                0x09ea  /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */\n#define XK_uprightcorner                 0x09eb  /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */\n#define XK_upleftcorner                  0x09ec  /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */\n#define XK_lowleftcorner                 0x09ed  /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */\n#define XK_crossinglines                 0x09ee  /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */\n#define XK_horizlinescan1                0x09ef  /* U+23BA HORIZONTAL SCAN LINE-1 */\n#define XK_horizlinescan3                0x09f0  /* U+23BB HORIZONTAL SCAN LINE-3 */\n#define XK_horizlinescan5                0x09f1  /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */\n#define XK_horizlinescan7                0x09f2  /* U+23BC HORIZONTAL SCAN LINE-7 */\n#define XK_horizlinescan9                0x09f3  /* U+23BD HORIZONTAL SCAN LINE-9 */\n#define XK_leftt                         0x09f4  /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */\n#define XK_rightt                        0x09f5  /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */\n#define XK_bott                          0x09f6  /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */\n#define XK_topt                          0x09f7  /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */\n#define XK_vertbar                       0x09f8  /* U+2502 BOX DRAWINGS LIGHT VERTICAL */\n#endif /* XK_SPECIAL */\n\n/*\n * Publishing\n * (these are probably from a long forgotten DEC Publishing\n * font that once shipped with DECwrite)\n * Byte 3 = 0x0a\n */\n\n#ifdef XK_PUBLISHING\n#define XK_emspace                       0x0aa1  /* U+2003 EM SPACE */\n#define XK_enspace                       0x0aa2  /* U+2002 EN SPACE */\n#define XK_em3space                      0x0aa3  /* U+2004 THREE-PER-EM SPACE */\n#define XK_em4space                      0x0aa4  /* U+2005 FOUR-PER-EM SPACE */\n#define XK_digitspace                    0x0aa5  /* U+2007 FIGURE SPACE */\n#define XK_punctspace                    0x0aa6  /* U+2008 PUNCTUATION SPACE */\n#define XK_thinspace                     0x0aa7  /* U+2009 THIN SPACE */\n#define XK_hairspace                     0x0aa8  /* U+200A HAIR SPACE */\n#define XK_emdash                        0x0aa9  /* U+2014 EM DASH */\n#define XK_endash                        0x0aaa  /* U+2013 EN DASH */\n#define XK_signifblank                   0x0aac  /*(U+2423 OPEN BOX)*/\n#define XK_ellipsis                      0x0aae  /* U+2026 HORIZONTAL ELLIPSIS */\n#define XK_doubbaselinedot               0x0aaf  /* U+2025 TWO DOT LEADER */\n#define XK_onethird                      0x0ab0  /* U+2153 VULGAR FRACTION ONE THIRD */\n#define XK_twothirds                     0x0ab1  /* U+2154 VULGAR FRACTION TWO THIRDS */\n#define XK_onefifth                      0x0ab2  /* U+2155 VULGAR FRACTION ONE FIFTH */\n#define XK_twofifths                     0x0ab3  /* U+2156 VULGAR FRACTION TWO FIFTHS */\n#define XK_threefifths                   0x0ab4  /* U+2157 VULGAR FRACTION THREE FIFTHS */\n#define XK_fourfifths                    0x0ab5  /* U+2158 VULGAR FRACTION FOUR FIFTHS */\n#define XK_onesixth                      0x0ab6  /* U+2159 VULGAR FRACTION ONE SIXTH */\n#define XK_fivesixths                    0x0ab7  /* U+215A VULGAR FRACTION FIVE SIXTHS */\n#define XK_careof                        0x0ab8  /* U+2105 CARE OF */\n#define XK_figdash                       0x0abb  /* U+2012 FIGURE DASH */\n#define XK_leftanglebracket              0x0abc  /*(U+2329 LEFT-POINTING ANGLE BRACKET)*/\n#define XK_decimalpoint                  0x0abd  /*(U+002E FULL STOP)*/\n#define XK_rightanglebracket             0x0abe  /*(U+232A RIGHT-POINTING ANGLE BRACKET)*/\n#define XK_marker                        0x0abf\n#define XK_oneeighth                     0x0ac3  /* U+215B VULGAR FRACTION ONE EIGHTH */\n#define XK_threeeighths                  0x0ac4  /* U+215C VULGAR FRACTION THREE EIGHTHS */\n#define XK_fiveeighths                   0x0ac5  /* U+215D VULGAR FRACTION FIVE EIGHTHS */\n#define XK_seveneighths                  0x0ac6  /* U+215E VULGAR FRACTION SEVEN EIGHTHS */\n#define XK_trademark                     0x0ac9  /* U+2122 TRADE MARK SIGN */\n#define XK_signaturemark                 0x0aca  /*(U+2613 SALTIRE)*/\n#define XK_trademarkincircle             0x0acb\n#define XK_leftopentriangle              0x0acc  /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/\n#define XK_rightopentriangle             0x0acd  /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/\n#define XK_emopencircle                  0x0ace  /*(U+25CB WHITE CIRCLE)*/\n#define XK_emopenrectangle               0x0acf  /*(U+25AF WHITE VERTICAL RECTANGLE)*/\n#define XK_leftsinglequotemark           0x0ad0  /* U+2018 LEFT SINGLE QUOTATION MARK */\n#define XK_rightsinglequotemark          0x0ad1  /* U+2019 RIGHT SINGLE QUOTATION MARK */\n#define XK_leftdoublequotemark           0x0ad2  /* U+201C LEFT DOUBLE QUOTATION MARK */\n#define XK_rightdoublequotemark          0x0ad3  /* U+201D RIGHT DOUBLE QUOTATION MARK */\n#define XK_prescription                  0x0ad4  /* U+211E PRESCRIPTION TAKE */\n#define XK_permille                      0x0ad5  /* U+2030 PER MILLE SIGN */\n#define XK_minutes                       0x0ad6  /* U+2032 PRIME */\n#define XK_seconds                       0x0ad7  /* U+2033 DOUBLE PRIME */\n#define XK_latincross                    0x0ad9  /* U+271D LATIN CROSS */\n#define XK_hexagram                      0x0ada\n#define XK_filledrectbullet              0x0adb  /*(U+25AC BLACK RECTANGLE)*/\n#define XK_filledlefttribullet           0x0adc  /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/\n#define XK_filledrighttribullet          0x0add  /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/\n#define XK_emfilledcircle                0x0ade  /*(U+25CF BLACK CIRCLE)*/\n#define XK_emfilledrect                  0x0adf  /*(U+25AE BLACK VERTICAL RECTANGLE)*/\n#define XK_enopencircbullet              0x0ae0  /*(U+25E6 WHITE BULLET)*/\n#define XK_enopensquarebullet            0x0ae1  /*(U+25AB WHITE SMALL SQUARE)*/\n#define XK_openrectbullet                0x0ae2  /*(U+25AD WHITE RECTANGLE)*/\n#define XK_opentribulletup               0x0ae3  /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/\n#define XK_opentribulletdown             0x0ae4  /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/\n#define XK_openstar                      0x0ae5  /*(U+2606 WHITE STAR)*/\n#define XK_enfilledcircbullet            0x0ae6  /*(U+2022 BULLET)*/\n#define XK_enfilledsqbullet              0x0ae7  /*(U+25AA BLACK SMALL SQUARE)*/\n#define XK_filledtribulletup             0x0ae8  /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/\n#define XK_filledtribulletdown           0x0ae9  /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/\n#define XK_leftpointer                   0x0aea  /*(U+261C WHITE LEFT POINTING INDEX)*/\n#define XK_rightpointer                  0x0aeb  /*(U+261E WHITE RIGHT POINTING INDEX)*/\n#define XK_club                          0x0aec  /* U+2663 BLACK CLUB SUIT */\n#define XK_diamond                       0x0aed  /* U+2666 BLACK DIAMOND SUIT */\n#define XK_heart                         0x0aee  /* U+2665 BLACK HEART SUIT */\n#define XK_maltesecross                  0x0af0  /* U+2720 MALTESE CROSS */\n#define XK_dagger                        0x0af1  /* U+2020 DAGGER */\n#define XK_doubledagger                  0x0af2  /* U+2021 DOUBLE DAGGER */\n#define XK_checkmark                     0x0af3  /* U+2713 CHECK MARK */\n#define XK_ballotcross                   0x0af4  /* U+2717 BALLOT X */\n#define XK_musicalsharp                  0x0af5  /* U+266F MUSIC SHARP SIGN */\n#define XK_musicalflat                   0x0af6  /* U+266D MUSIC FLAT SIGN */\n#define XK_malesymbol                    0x0af7  /* U+2642 MALE SIGN */\n#define XK_femalesymbol                  0x0af8  /* U+2640 FEMALE SIGN */\n#define XK_telephone                     0x0af9  /* U+260E BLACK TELEPHONE */\n#define XK_telephonerecorder             0x0afa  /* U+2315 TELEPHONE RECORDER */\n#define XK_phonographcopyright           0x0afb  /* U+2117 SOUND RECORDING COPYRIGHT */\n#define XK_caret                         0x0afc  /* U+2038 CARET */\n#define XK_singlelowquotemark            0x0afd  /* U+201A SINGLE LOW-9 QUOTATION MARK */\n#define XK_doublelowquotemark            0x0afe  /* U+201E DOUBLE LOW-9 QUOTATION MARK */\n#define XK_cursor                        0x0aff\n#endif /* XK_PUBLISHING */\n\n/*\n * APL\n * Byte 3 = 0x0b\n */\n\n#ifdef XK_APL\n#define XK_leftcaret                     0x0ba3  /*(U+003C LESS-THAN SIGN)*/\n#define XK_rightcaret                    0x0ba6  /*(U+003E GREATER-THAN SIGN)*/\n#define XK_downcaret                     0x0ba8  /*(U+2228 LOGICAL OR)*/\n#define XK_upcaret                       0x0ba9  /*(U+2227 LOGICAL AND)*/\n#define XK_overbar                       0x0bc0  /*(U+00AF MACRON)*/\n#define XK_downtack                      0x0bc2  /* U+22A4 DOWN TACK */\n#define XK_upshoe                        0x0bc3  /*(U+2229 INTERSECTION)*/\n#define XK_downstile                     0x0bc4  /* U+230A LEFT FLOOR */\n#define XK_underbar                      0x0bc6  /*(U+005F LOW LINE)*/\n#define XK_jot                           0x0bca  /* U+2218 RING OPERATOR */\n#define XK_quad                          0x0bcc  /* U+2395 APL FUNCTIONAL SYMBOL QUAD */\n#define XK_uptack                        0x0bce  /* U+22A5 UP TACK */\n#define XK_circle                        0x0bcf  /* U+25CB WHITE CIRCLE */\n#define XK_upstile                       0x0bd3  /* U+2308 LEFT CEILING */\n#define XK_downshoe                      0x0bd6  /*(U+222A UNION)*/\n#define XK_rightshoe                     0x0bd8  /*(U+2283 SUPERSET OF)*/\n#define XK_leftshoe                      0x0bda  /*(U+2282 SUBSET OF)*/\n#define XK_lefttack                      0x0bdc  /* U+22A3 LEFT TACK */\n#define XK_righttack                     0x0bfc  /* U+22A2 RIGHT TACK */\n#endif /* XK_APL */\n\n/*\n * Hebrew\n * Byte 3 = 0x0c\n */\n\n#ifdef XK_HEBREW\n#define XK_hebrew_doublelowline          0x0cdf  /* U+2017 DOUBLE LOW LINE */\n#define XK_hebrew_aleph                  0x0ce0  /* U+05D0 HEBREW LETTER ALEF */\n#define XK_hebrew_bet                    0x0ce1  /* U+05D1 HEBREW LETTER BET */\n#define XK_hebrew_beth                   0x0ce1  /* deprecated */\n#define XK_hebrew_gimel                  0x0ce2  /* U+05D2 HEBREW LETTER GIMEL */\n#define XK_hebrew_gimmel                 0x0ce2  /* deprecated */\n#define XK_hebrew_dalet                  0x0ce3  /* U+05D3 HEBREW LETTER DALET */\n#define XK_hebrew_daleth                 0x0ce3  /* deprecated */\n#define XK_hebrew_he                     0x0ce4  /* U+05D4 HEBREW LETTER HE */\n#define XK_hebrew_waw                    0x0ce5  /* U+05D5 HEBREW LETTER VAV */\n#define XK_hebrew_zain                   0x0ce6  /* U+05D6 HEBREW LETTER ZAYIN */\n#define XK_hebrew_zayin                  0x0ce6  /* deprecated */\n#define XK_hebrew_chet                   0x0ce7  /* U+05D7 HEBREW LETTER HET */\n#define XK_hebrew_het                    0x0ce7  /* deprecated */\n#define XK_hebrew_tet                    0x0ce8  /* U+05D8 HEBREW LETTER TET */\n#define XK_hebrew_teth                   0x0ce8  /* deprecated */\n#define XK_hebrew_yod                    0x0ce9  /* U+05D9 HEBREW LETTER YOD */\n#define XK_hebrew_finalkaph              0x0cea  /* U+05DA HEBREW LETTER FINAL KAF */\n#define XK_hebrew_kaph                   0x0ceb  /* U+05DB HEBREW LETTER KAF */\n#define XK_hebrew_lamed                  0x0cec  /* U+05DC HEBREW LETTER LAMED */\n#define XK_hebrew_finalmem               0x0ced  /* U+05DD HEBREW LETTER FINAL MEM */\n#define XK_hebrew_mem                    0x0cee  /* U+05DE HEBREW LETTER MEM */\n#define XK_hebrew_finalnun               0x0cef  /* U+05DF HEBREW LETTER FINAL NUN */\n#define XK_hebrew_nun                    0x0cf0  /* U+05E0 HEBREW LETTER NUN */\n#define XK_hebrew_samech                 0x0cf1  /* U+05E1 HEBREW LETTER SAMEKH */\n#define XK_hebrew_samekh                 0x0cf1  /* deprecated */\n#define XK_hebrew_ayin                   0x0cf2  /* U+05E2 HEBREW LETTER AYIN */\n#define XK_hebrew_finalpe                0x0cf3  /* U+05E3 HEBREW LETTER FINAL PE */\n#define XK_hebrew_pe                     0x0cf4  /* U+05E4 HEBREW LETTER PE */\n#define XK_hebrew_finalzade              0x0cf5  /* U+05E5 HEBREW LETTER FINAL TSADI */\n#define XK_hebrew_finalzadi              0x0cf5  /* deprecated */\n#define XK_hebrew_zade                   0x0cf6  /* U+05E6 HEBREW LETTER TSADI */\n#define XK_hebrew_zadi                   0x0cf6  /* deprecated */\n#define XK_hebrew_qoph                   0x0cf7  /* U+05E7 HEBREW LETTER QOF */\n#define XK_hebrew_kuf                    0x0cf7  /* deprecated */\n#define XK_hebrew_resh                   0x0cf8  /* U+05E8 HEBREW LETTER RESH */\n#define XK_hebrew_shin                   0x0cf9  /* U+05E9 HEBREW LETTER SHIN */\n#define XK_hebrew_taw                    0x0cfa  /* U+05EA HEBREW LETTER TAV */\n#define XK_hebrew_taf                    0x0cfa  /* deprecated */\n#define XK_Hebrew_switch                 0xff7e  /* non-deprecated alias for Mode_switch */\n#endif /* XK_HEBREW */\n\n/*\n * Thai\n * Byte 3 = 0x0d\n */\n\n#ifdef XK_THAI\n#define XK_Thai_kokai                    0x0da1  /* U+0E01 THAI CHARACTER KO KAI */\n#define XK_Thai_khokhai                  0x0da2  /* U+0E02 THAI CHARACTER KHO KHAI */\n#define XK_Thai_khokhuat                 0x0da3  /* U+0E03 THAI CHARACTER KHO KHUAT */\n#define XK_Thai_khokhwai                 0x0da4  /* U+0E04 THAI CHARACTER KHO KHWAI */\n#define XK_Thai_khokhon                  0x0da5  /* U+0E05 THAI CHARACTER KHO KHON */\n#define XK_Thai_khorakhang               0x0da6  /* U+0E06 THAI CHARACTER KHO RAKHANG */\n#define XK_Thai_ngongu                   0x0da7  /* U+0E07 THAI CHARACTER NGO NGU */\n#define XK_Thai_chochan                  0x0da8  /* U+0E08 THAI CHARACTER CHO CHAN */\n#define XK_Thai_choching                 0x0da9  /* U+0E09 THAI CHARACTER CHO CHING */\n#define XK_Thai_chochang                 0x0daa  /* U+0E0A THAI CHARACTER CHO CHANG */\n#define XK_Thai_soso                     0x0dab  /* U+0E0B THAI CHARACTER SO SO */\n#define XK_Thai_chochoe                  0x0dac  /* U+0E0C THAI CHARACTER CHO CHOE */\n#define XK_Thai_yoying                   0x0dad  /* U+0E0D THAI CHARACTER YO YING */\n#define XK_Thai_dochada                  0x0dae  /* U+0E0E THAI CHARACTER DO CHADA */\n#define XK_Thai_topatak                  0x0daf  /* U+0E0F THAI CHARACTER TO PATAK */\n#define XK_Thai_thothan                  0x0db0  /* U+0E10 THAI CHARACTER THO THAN */\n#define XK_Thai_thonangmontho            0x0db1  /* U+0E11 THAI CHARACTER THO NANGMONTHO */\n#define XK_Thai_thophuthao               0x0db2  /* U+0E12 THAI CHARACTER THO PHUTHAO */\n#define XK_Thai_nonen                    0x0db3  /* U+0E13 THAI CHARACTER NO NEN */\n#define XK_Thai_dodek                    0x0db4  /* U+0E14 THAI CHARACTER DO DEK */\n#define XK_Thai_totao                    0x0db5  /* U+0E15 THAI CHARACTER TO TAO */\n#define XK_Thai_thothung                 0x0db6  /* U+0E16 THAI CHARACTER THO THUNG */\n#define XK_Thai_thothahan                0x0db7  /* U+0E17 THAI CHARACTER THO THAHAN */\n#define XK_Thai_thothong                 0x0db8  /* U+0E18 THAI CHARACTER THO THONG */\n#define XK_Thai_nonu                     0x0db9  /* U+0E19 THAI CHARACTER NO NU */\n#define XK_Thai_bobaimai                 0x0dba  /* U+0E1A THAI CHARACTER BO BAIMAI */\n#define XK_Thai_popla                    0x0dbb  /* U+0E1B THAI CHARACTER PO PLA */\n#define XK_Thai_phophung                 0x0dbc  /* U+0E1C THAI CHARACTER PHO PHUNG */\n#define XK_Thai_fofa                     0x0dbd  /* U+0E1D THAI CHARACTER FO FA */\n#define XK_Thai_phophan                  0x0dbe  /* U+0E1E THAI CHARACTER PHO PHAN */\n#define XK_Thai_fofan                    0x0dbf  /* U+0E1F THAI CHARACTER FO FAN */\n#define XK_Thai_phosamphao               0x0dc0  /* U+0E20 THAI CHARACTER PHO SAMPHAO */\n#define XK_Thai_moma                     0x0dc1  /* U+0E21 THAI CHARACTER MO MA */\n#define XK_Thai_yoyak                    0x0dc2  /* U+0E22 THAI CHARACTER YO YAK */\n#define XK_Thai_rorua                    0x0dc3  /* U+0E23 THAI CHARACTER RO RUA */\n#define XK_Thai_ru                       0x0dc4  /* U+0E24 THAI CHARACTER RU */\n#define XK_Thai_loling                   0x0dc5  /* U+0E25 THAI CHARACTER LO LING */\n#define XK_Thai_lu                       0x0dc6  /* U+0E26 THAI CHARACTER LU */\n#define XK_Thai_wowaen                   0x0dc7  /* U+0E27 THAI CHARACTER WO WAEN */\n#define XK_Thai_sosala                   0x0dc8  /* U+0E28 THAI CHARACTER SO SALA */\n#define XK_Thai_sorusi                   0x0dc9  /* U+0E29 THAI CHARACTER SO RUSI */\n#define XK_Thai_sosua                    0x0dca  /* U+0E2A THAI CHARACTER SO SUA */\n#define XK_Thai_hohip                    0x0dcb  /* U+0E2B THAI CHARACTER HO HIP */\n#define XK_Thai_lochula                  0x0dcc  /* U+0E2C THAI CHARACTER LO CHULA */\n#define XK_Thai_oang                     0x0dcd  /* U+0E2D THAI CHARACTER O ANG */\n#define XK_Thai_honokhuk                 0x0dce  /* U+0E2E THAI CHARACTER HO NOKHUK */\n#define XK_Thai_paiyannoi                0x0dcf  /* U+0E2F THAI CHARACTER PAIYANNOI */\n#define XK_Thai_saraa                    0x0dd0  /* U+0E30 THAI CHARACTER SARA A */\n#define XK_Thai_maihanakat               0x0dd1  /* U+0E31 THAI CHARACTER MAI HAN-AKAT */\n#define XK_Thai_saraaa                   0x0dd2  /* U+0E32 THAI CHARACTER SARA AA */\n#define XK_Thai_saraam                   0x0dd3  /* U+0E33 THAI CHARACTER SARA AM */\n#define XK_Thai_sarai                    0x0dd4  /* U+0E34 THAI CHARACTER SARA I */\n#define XK_Thai_saraii                   0x0dd5  /* U+0E35 THAI CHARACTER SARA II */\n#define XK_Thai_saraue                   0x0dd6  /* U+0E36 THAI CHARACTER SARA UE */\n#define XK_Thai_sarauee                  0x0dd7  /* U+0E37 THAI CHARACTER SARA UEE */\n#define XK_Thai_sarau                    0x0dd8  /* U+0E38 THAI CHARACTER SARA U */\n#define XK_Thai_sarauu                   0x0dd9  /* U+0E39 THAI CHARACTER SARA UU */\n#define XK_Thai_phinthu                  0x0dda  /* U+0E3A THAI CHARACTER PHINTHU */\n#define XK_Thai_maihanakat_maitho        0x0dde  /*(U+0E3E Unassigned code point)*/\n#define XK_Thai_baht                     0x0ddf  /* U+0E3F THAI CURRENCY SYMBOL BAHT */\n#define XK_Thai_sarae                    0x0de0  /* U+0E40 THAI CHARACTER SARA E */\n#define XK_Thai_saraae                   0x0de1  /* U+0E41 THAI CHARACTER SARA AE */\n#define XK_Thai_sarao                    0x0de2  /* U+0E42 THAI CHARACTER SARA O */\n#define XK_Thai_saraaimaimuan            0x0de3  /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */\n#define XK_Thai_saraaimaimalai           0x0de4  /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */\n#define XK_Thai_lakkhangyao              0x0de5  /* U+0E45 THAI CHARACTER LAKKHANGYAO */\n#define XK_Thai_maiyamok                 0x0de6  /* U+0E46 THAI CHARACTER MAIYAMOK */\n#define XK_Thai_maitaikhu                0x0de7  /* U+0E47 THAI CHARACTER MAITAIKHU */\n#define XK_Thai_maiek                    0x0de8  /* U+0E48 THAI CHARACTER MAI EK */\n#define XK_Thai_maitho                   0x0de9  /* U+0E49 THAI CHARACTER MAI THO */\n#define XK_Thai_maitri                   0x0dea  /* U+0E4A THAI CHARACTER MAI TRI */\n#define XK_Thai_maichattawa              0x0deb  /* U+0E4B THAI CHARACTER MAI CHATTAWA */\n#define XK_Thai_thanthakhat              0x0dec  /* U+0E4C THAI CHARACTER THANTHAKHAT */\n#define XK_Thai_nikhahit                 0x0ded  /* U+0E4D THAI CHARACTER NIKHAHIT */\n#define XK_Thai_leksun                   0x0df0  /* U+0E50 THAI DIGIT ZERO */\n#define XK_Thai_leknung                  0x0df1  /* U+0E51 THAI DIGIT ONE */\n#define XK_Thai_leksong                  0x0df2  /* U+0E52 THAI DIGIT TWO */\n#define XK_Thai_leksam                   0x0df3  /* U+0E53 THAI DIGIT THREE */\n#define XK_Thai_leksi                    0x0df4  /* U+0E54 THAI DIGIT FOUR */\n#define XK_Thai_lekha                    0x0df5  /* U+0E55 THAI DIGIT FIVE */\n#define XK_Thai_lekhok                   0x0df6  /* U+0E56 THAI DIGIT SIX */\n#define XK_Thai_lekchet                  0x0df7  /* U+0E57 THAI DIGIT SEVEN */\n#define XK_Thai_lekpaet                  0x0df8  /* U+0E58 THAI DIGIT EIGHT */\n#define XK_Thai_lekkao                   0x0df9  /* U+0E59 THAI DIGIT NINE */\n#endif /* XK_THAI */\n\n/*\n * Korean\n * Byte 3 = 0x0e\n */\n\n#ifdef XK_KOREAN\n\n#define XK_Hangul                        0xff31  /* Hangul start/stop(toggle) */\n#define XK_Hangul_Start                  0xff32  /* Hangul start */\n#define XK_Hangul_End                    0xff33  /* Hangul end, English start */\n#define XK_Hangul_Hanja                  0xff34  /* Start Hangul->Hanja Conversion */\n#define XK_Hangul_Jamo                   0xff35  /* Hangul Jamo mode */\n#define XK_Hangul_Romaja                 0xff36  /* Hangul Romaja mode */\n#define XK_Hangul_Codeinput              0xff37  /* Hangul code input mode */\n#define XK_Hangul_Jeonja                 0xff38  /* Jeonja mode */\n#define XK_Hangul_Banja                  0xff39  /* Banja mode */\n#define XK_Hangul_PreHanja               0xff3a  /* Pre Hanja conversion */\n#define XK_Hangul_PostHanja              0xff3b  /* Post Hanja conversion */\n#define XK_Hangul_SingleCandidate        0xff3c  /* Single candidate */\n#define XK_Hangul_MultipleCandidate      0xff3d  /* Multiple candidate */\n#define XK_Hangul_PreviousCandidate      0xff3e  /* Previous candidate */\n#define XK_Hangul_Special                0xff3f  /* Special symbols */\n#define XK_Hangul_switch                 0xff7e  /* non-deprecated alias for Mode_switch */\n\n/* Hangul Consonant Characters */\n#define XK_Hangul_Kiyeog                 0x0ea1  /* U+3131 HANGUL LETTER KIYEOK */\n#define XK_Hangul_SsangKiyeog            0x0ea2  /* U+3132 HANGUL LETTER SSANGKIYEOK */\n#define XK_Hangul_KiyeogSios             0x0ea3  /* U+3133 HANGUL LETTER KIYEOK-SIOS */\n#define XK_Hangul_Nieun                  0x0ea4  /* U+3134 HANGUL LETTER NIEUN */\n#define XK_Hangul_NieunJieuj             0x0ea5  /* U+3135 HANGUL LETTER NIEUN-CIEUC */\n#define XK_Hangul_NieunHieuh             0x0ea6  /* U+3136 HANGUL LETTER NIEUN-HIEUH */\n#define XK_Hangul_Dikeud                 0x0ea7  /* U+3137 HANGUL LETTER TIKEUT */\n#define XK_Hangul_SsangDikeud            0x0ea8  /* U+3138 HANGUL LETTER SSANGTIKEUT */\n#define XK_Hangul_Rieul                  0x0ea9  /* U+3139 HANGUL LETTER RIEUL */\n#define XK_Hangul_RieulKiyeog            0x0eaa  /* U+313A HANGUL LETTER RIEUL-KIYEOK */\n#define XK_Hangul_RieulMieum             0x0eab  /* U+313B HANGUL LETTER RIEUL-MIEUM */\n#define XK_Hangul_RieulPieub             0x0eac  /* U+313C HANGUL LETTER RIEUL-PIEUP */\n#define XK_Hangul_RieulSios              0x0ead  /* U+313D HANGUL LETTER RIEUL-SIOS */\n#define XK_Hangul_RieulTieut             0x0eae  /* U+313E HANGUL LETTER RIEUL-THIEUTH */\n#define XK_Hangul_RieulPhieuf            0x0eaf  /* U+313F HANGUL LETTER RIEUL-PHIEUPH */\n#define XK_Hangul_RieulHieuh             0x0eb0  /* U+3140 HANGUL LETTER RIEUL-HIEUH */\n#define XK_Hangul_Mieum                  0x0eb1  /* U+3141 HANGUL LETTER MIEUM */\n#define XK_Hangul_Pieub                  0x0eb2  /* U+3142 HANGUL LETTER PIEUP */\n#define XK_Hangul_SsangPieub             0x0eb3  /* U+3143 HANGUL LETTER SSANGPIEUP */\n#define XK_Hangul_PieubSios              0x0eb4  /* U+3144 HANGUL LETTER PIEUP-SIOS */\n#define XK_Hangul_Sios                   0x0eb5  /* U+3145 HANGUL LETTER SIOS */\n#define XK_Hangul_SsangSios              0x0eb6  /* U+3146 HANGUL LETTER SSANGSIOS */\n#define XK_Hangul_Ieung                  0x0eb7  /* U+3147 HANGUL LETTER IEUNG */\n#define XK_Hangul_Jieuj                  0x0eb8  /* U+3148 HANGUL LETTER CIEUC */\n#define XK_Hangul_SsangJieuj             0x0eb9  /* U+3149 HANGUL LETTER SSANGCIEUC */\n#define XK_Hangul_Cieuc                  0x0eba  /* U+314A HANGUL LETTER CHIEUCH */\n#define XK_Hangul_Khieuq                 0x0ebb  /* U+314B HANGUL LETTER KHIEUKH */\n#define XK_Hangul_Tieut                  0x0ebc  /* U+314C HANGUL LETTER THIEUTH */\n#define XK_Hangul_Phieuf                 0x0ebd  /* U+314D HANGUL LETTER PHIEUPH */\n#define XK_Hangul_Hieuh                  0x0ebe  /* U+314E HANGUL LETTER HIEUH */\n\n/* Hangul Vowel Characters */\n#define XK_Hangul_A                      0x0ebf  /* U+314F HANGUL LETTER A */\n#define XK_Hangul_AE                     0x0ec0  /* U+3150 HANGUL LETTER AE */\n#define XK_Hangul_YA                     0x0ec1  /* U+3151 HANGUL LETTER YA */\n#define XK_Hangul_YAE                    0x0ec2  /* U+3152 HANGUL LETTER YAE */\n#define XK_Hangul_EO                     0x0ec3  /* U+3153 HANGUL LETTER EO */\n#define XK_Hangul_E                      0x0ec4  /* U+3154 HANGUL LETTER E */\n#define XK_Hangul_YEO                    0x0ec5  /* U+3155 HANGUL LETTER YEO */\n#define XK_Hangul_YE                     0x0ec6  /* U+3156 HANGUL LETTER YE */\n#define XK_Hangul_O                      0x0ec7  /* U+3157 HANGUL LETTER O */\n#define XK_Hangul_WA                     0x0ec8  /* U+3158 HANGUL LETTER WA */\n#define XK_Hangul_WAE                    0x0ec9  /* U+3159 HANGUL LETTER WAE */\n#define XK_Hangul_OE                     0x0eca  /* U+315A HANGUL LETTER OE */\n#define XK_Hangul_YO                     0x0ecb  /* U+315B HANGUL LETTER YO */\n#define XK_Hangul_U                      0x0ecc  /* U+315C HANGUL LETTER U */\n#define XK_Hangul_WEO                    0x0ecd  /* U+315D HANGUL LETTER WEO */\n#define XK_Hangul_WE                     0x0ece  /* U+315E HANGUL LETTER WE */\n#define XK_Hangul_WI                     0x0ecf  /* U+315F HANGUL LETTER WI */\n#define XK_Hangul_YU                     0x0ed0  /* U+3160 HANGUL LETTER YU */\n#define XK_Hangul_EU                     0x0ed1  /* U+3161 HANGUL LETTER EU */\n#define XK_Hangul_YI                     0x0ed2  /* U+3162 HANGUL LETTER YI */\n#define XK_Hangul_I                      0x0ed3  /* U+3163 HANGUL LETTER I */\n\n/* Hangul syllable-final (JongSeong) Characters */\n#define XK_Hangul_J_Kiyeog               0x0ed4  /* U+11A8 HANGUL JONGSEONG KIYEOK */\n#define XK_Hangul_J_SsangKiyeog          0x0ed5  /* U+11A9 HANGUL JONGSEONG SSANGKIYEOK */\n#define XK_Hangul_J_KiyeogSios           0x0ed6  /* U+11AA HANGUL JONGSEONG KIYEOK-SIOS */\n#define XK_Hangul_J_Nieun                0x0ed7  /* U+11AB HANGUL JONGSEONG NIEUN */\n#define XK_Hangul_J_NieunJieuj           0x0ed8  /* U+11AC HANGUL JONGSEONG NIEUN-CIEUC */\n#define XK_Hangul_J_NieunHieuh           0x0ed9  /* U+11AD HANGUL JONGSEONG NIEUN-HIEUH */\n#define XK_Hangul_J_Dikeud               0x0eda  /* U+11AE HANGUL JONGSEONG TIKEUT */\n#define XK_Hangul_J_Rieul                0x0edb  /* U+11AF HANGUL JONGSEONG RIEUL */\n#define XK_Hangul_J_RieulKiyeog          0x0edc  /* U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK */\n#define XK_Hangul_J_RieulMieum           0x0edd  /* U+11B1 HANGUL JONGSEONG RIEUL-MIEUM */\n#define XK_Hangul_J_RieulPieub           0x0ede  /* U+11B2 HANGUL JONGSEONG RIEUL-PIEUP */\n#define XK_Hangul_J_RieulSios            0x0edf  /* U+11B3 HANGUL JONGSEONG RIEUL-SIOS */\n#define XK_Hangul_J_RieulTieut           0x0ee0  /* U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH */\n#define XK_Hangul_J_RieulPhieuf          0x0ee1  /* U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH */\n#define XK_Hangul_J_RieulHieuh           0x0ee2  /* U+11B6 HANGUL JONGSEONG RIEUL-HIEUH */\n#define XK_Hangul_J_Mieum                0x0ee3  /* U+11B7 HANGUL JONGSEONG MIEUM */\n#define XK_Hangul_J_Pieub                0x0ee4  /* U+11B8 HANGUL JONGSEONG PIEUP */\n#define XK_Hangul_J_PieubSios            0x0ee5  /* U+11B9 HANGUL JONGSEONG PIEUP-SIOS */\n#define XK_Hangul_J_Sios                 0x0ee6  /* U+11BA HANGUL JONGSEONG SIOS */\n#define XK_Hangul_J_SsangSios            0x0ee7  /* U+11BB HANGUL JONGSEONG SSANGSIOS */\n#define XK_Hangul_J_Ieung                0x0ee8  /* U+11BC HANGUL JONGSEONG IEUNG */\n#define XK_Hangul_J_Jieuj                0x0ee9  /* U+11BD HANGUL JONGSEONG CIEUC */\n#define XK_Hangul_J_Cieuc                0x0eea  /* U+11BE HANGUL JONGSEONG CHIEUCH */\n#define XK_Hangul_J_Khieuq               0x0eeb  /* U+11BF HANGUL JONGSEONG KHIEUKH */\n#define XK_Hangul_J_Tieut                0x0eec  /* U+11C0 HANGUL JONGSEONG THIEUTH */\n#define XK_Hangul_J_Phieuf               0x0eed  /* U+11C1 HANGUL JONGSEONG PHIEUPH */\n#define XK_Hangul_J_Hieuh                0x0eee  /* U+11C2 HANGUL JONGSEONG HIEUH */\n\n/* Ancient Hangul Consonant Characters */\n#define XK_Hangul_RieulYeorinHieuh       0x0eef  /* U+316D HANGUL LETTER RIEUL-YEORINHIEUH */\n#define XK_Hangul_SunkyeongeumMieum      0x0ef0  /* U+3171 HANGUL LETTER KAPYEOUNMIEUM */\n#define XK_Hangul_SunkyeongeumPieub      0x0ef1  /* U+3178 HANGUL LETTER KAPYEOUNPIEUP */\n#define XK_Hangul_PanSios                0x0ef2  /* U+317F HANGUL LETTER PANSIOS */\n#define XK_Hangul_KkogjiDalrinIeung      0x0ef3  /* U+3181 HANGUL LETTER YESIEUNG */\n#define XK_Hangul_SunkyeongeumPhieuf     0x0ef4  /* U+3184 HANGUL LETTER KAPYEOUNPHIEUPH */\n#define XK_Hangul_YeorinHieuh            0x0ef5  /* U+3186 HANGUL LETTER YEORINHIEUH */\n\n/* Ancient Hangul Vowel Characters */\n#define XK_Hangul_AraeA                  0x0ef6  /* U+318D HANGUL LETTER ARAEA */\n#define XK_Hangul_AraeAE                 0x0ef7  /* U+318E HANGUL LETTER ARAEAE */\n\n/* Ancient Hangul syllable-final (JongSeong) Characters */\n#define XK_Hangul_J_PanSios              0x0ef8  /* U+11EB HANGUL JONGSEONG PANSIOS */\n#define XK_Hangul_J_KkogjiDalrinIeung    0x0ef9  /* U+11F0 HANGUL JONGSEONG YESIEUNG */\n#define XK_Hangul_J_YeorinHieuh          0x0efa  /* U+11F9 HANGUL JONGSEONG YEORINHIEUH */\n\n/* Korean currency symbol */\n#define XK_Korean_Won                    0x0eff  /*(U+20A9 WON SIGN)*/\n\n#endif /* XK_KOREAN */\n\n/*\n * Armenian\n */\n\n#ifdef XK_ARMENIAN\n#define XK_Armenian_ligature_ew       0x1000587  /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */\n#define XK_Armenian_full_stop         0x1000589  /* U+0589 ARMENIAN FULL STOP */\n#define XK_Armenian_verjaket          0x1000589  /* deprecated alias for Armenian_full_stop */\n#define XK_Armenian_separation_mark   0x100055d  /* U+055D ARMENIAN COMMA */\n#define XK_Armenian_but               0x100055d  /* deprecated alias for Armenian_separation_mark */\n#define XK_Armenian_hyphen            0x100058a  /* U+058A ARMENIAN HYPHEN */\n#define XK_Armenian_yentamna          0x100058a  /* deprecated alias for Armenian_hyphen */\n#define XK_Armenian_exclam            0x100055c  /* U+055C ARMENIAN EXCLAMATION MARK */\n#define XK_Armenian_amanak            0x100055c  /* deprecated alias for Armenian_exclam */\n#define XK_Armenian_accent            0x100055b  /* U+055B ARMENIAN EMPHASIS MARK */\n#define XK_Armenian_shesht            0x100055b  /* deprecated alias for Armenian_accent */\n#define XK_Armenian_question          0x100055e  /* U+055E ARMENIAN QUESTION MARK */\n#define XK_Armenian_paruyk            0x100055e  /* deprecated alias for Armenian_question */\n#define XK_Armenian_AYB               0x1000531  /* U+0531 ARMENIAN CAPITAL LETTER AYB */\n#define XK_Armenian_ayb               0x1000561  /* U+0561 ARMENIAN SMALL LETTER AYB */\n#define XK_Armenian_BEN               0x1000532  /* U+0532 ARMENIAN CAPITAL LETTER BEN */\n#define XK_Armenian_ben               0x1000562  /* U+0562 ARMENIAN SMALL LETTER BEN */\n#define XK_Armenian_GIM               0x1000533  /* U+0533 ARMENIAN CAPITAL LETTER GIM */\n#define XK_Armenian_gim               0x1000563  /* U+0563 ARMENIAN SMALL LETTER GIM */\n#define XK_Armenian_DA                0x1000534  /* U+0534 ARMENIAN CAPITAL LETTER DA */\n#define XK_Armenian_da                0x1000564  /* U+0564 ARMENIAN SMALL LETTER DA */\n#define XK_Armenian_YECH              0x1000535  /* U+0535 ARMENIAN CAPITAL LETTER ECH */\n#define XK_Armenian_yech              0x1000565  /* U+0565 ARMENIAN SMALL LETTER ECH */\n#define XK_Armenian_ZA                0x1000536  /* U+0536 ARMENIAN CAPITAL LETTER ZA */\n#define XK_Armenian_za                0x1000566  /* U+0566 ARMENIAN SMALL LETTER ZA */\n#define XK_Armenian_E                 0x1000537  /* U+0537 ARMENIAN CAPITAL LETTER EH */\n#define XK_Armenian_e                 0x1000567  /* U+0567 ARMENIAN SMALL LETTER EH */\n#define XK_Armenian_AT                0x1000538  /* U+0538 ARMENIAN CAPITAL LETTER ET */\n#define XK_Armenian_at                0x1000568  /* U+0568 ARMENIAN SMALL LETTER ET */\n#define XK_Armenian_TO                0x1000539  /* U+0539 ARMENIAN CAPITAL LETTER TO */\n#define XK_Armenian_to                0x1000569  /* U+0569 ARMENIAN SMALL LETTER TO */\n#define XK_Armenian_ZHE               0x100053a  /* U+053A ARMENIAN CAPITAL LETTER ZHE */\n#define XK_Armenian_zhe               0x100056a  /* U+056A ARMENIAN SMALL LETTER ZHE */\n#define XK_Armenian_INI               0x100053b  /* U+053B ARMENIAN CAPITAL LETTER INI */\n#define XK_Armenian_ini               0x100056b  /* U+056B ARMENIAN SMALL LETTER INI */\n#define XK_Armenian_LYUN              0x100053c  /* U+053C ARMENIAN CAPITAL LETTER LIWN */\n#define XK_Armenian_lyun              0x100056c  /* U+056C ARMENIAN SMALL LETTER LIWN */\n#define XK_Armenian_KHE               0x100053d  /* U+053D ARMENIAN CAPITAL LETTER XEH */\n#define XK_Armenian_khe               0x100056d  /* U+056D ARMENIAN SMALL LETTER XEH */\n#define XK_Armenian_TSA               0x100053e  /* U+053E ARMENIAN CAPITAL LETTER CA */\n#define XK_Armenian_tsa               0x100056e  /* U+056E ARMENIAN SMALL LETTER CA */\n#define XK_Armenian_KEN               0x100053f  /* U+053F ARMENIAN CAPITAL LETTER KEN */\n#define XK_Armenian_ken               0x100056f  /* U+056F ARMENIAN SMALL LETTER KEN */\n#define XK_Armenian_HO                0x1000540  /* U+0540 ARMENIAN CAPITAL LETTER HO */\n#define XK_Armenian_ho                0x1000570  /* U+0570 ARMENIAN SMALL LETTER HO */\n#define XK_Armenian_DZA               0x1000541  /* U+0541 ARMENIAN CAPITAL LETTER JA */\n#define XK_Armenian_dza               0x1000571  /* U+0571 ARMENIAN SMALL LETTER JA */\n#define XK_Armenian_GHAT              0x1000542  /* U+0542 ARMENIAN CAPITAL LETTER GHAD */\n#define XK_Armenian_ghat              0x1000572  /* U+0572 ARMENIAN SMALL LETTER GHAD */\n#define XK_Armenian_TCHE              0x1000543  /* U+0543 ARMENIAN CAPITAL LETTER CHEH */\n#define XK_Armenian_tche              0x1000573  /* U+0573 ARMENIAN SMALL LETTER CHEH */\n#define XK_Armenian_MEN               0x1000544  /* U+0544 ARMENIAN CAPITAL LETTER MEN */\n#define XK_Armenian_men               0x1000574  /* U+0574 ARMENIAN SMALL LETTER MEN */\n#define XK_Armenian_HI                0x1000545  /* U+0545 ARMENIAN CAPITAL LETTER YI */\n#define XK_Armenian_hi                0x1000575  /* U+0575 ARMENIAN SMALL LETTER YI */\n#define XK_Armenian_NU                0x1000546  /* U+0546 ARMENIAN CAPITAL LETTER NOW */\n#define XK_Armenian_nu                0x1000576  /* U+0576 ARMENIAN SMALL LETTER NOW */\n#define XK_Armenian_SHA               0x1000547  /* U+0547 ARMENIAN CAPITAL LETTER SHA */\n#define XK_Armenian_sha               0x1000577  /* U+0577 ARMENIAN SMALL LETTER SHA */\n#define XK_Armenian_VO                0x1000548  /* U+0548 ARMENIAN CAPITAL LETTER VO */\n#define XK_Armenian_vo                0x1000578  /* U+0578 ARMENIAN SMALL LETTER VO */\n#define XK_Armenian_CHA               0x1000549  /* U+0549 ARMENIAN CAPITAL LETTER CHA */\n#define XK_Armenian_cha               0x1000579  /* U+0579 ARMENIAN SMALL LETTER CHA */\n#define XK_Armenian_PE                0x100054a  /* U+054A ARMENIAN CAPITAL LETTER PEH */\n#define XK_Armenian_pe                0x100057a  /* U+057A ARMENIAN SMALL LETTER PEH */\n#define XK_Armenian_JE                0x100054b  /* U+054B ARMENIAN CAPITAL LETTER JHEH */\n#define XK_Armenian_je                0x100057b  /* U+057B ARMENIAN SMALL LETTER JHEH */\n#define XK_Armenian_RA                0x100054c  /* U+054C ARMENIAN CAPITAL LETTER RA */\n#define XK_Armenian_ra                0x100057c  /* U+057C ARMENIAN SMALL LETTER RA */\n#define XK_Armenian_SE                0x100054d  /* U+054D ARMENIAN CAPITAL LETTER SEH */\n#define XK_Armenian_se                0x100057d  /* U+057D ARMENIAN SMALL LETTER SEH */\n#define XK_Armenian_VEV               0x100054e  /* U+054E ARMENIAN CAPITAL LETTER VEW */\n#define XK_Armenian_vev               0x100057e  /* U+057E ARMENIAN SMALL LETTER VEW */\n#define XK_Armenian_TYUN              0x100054f  /* U+054F ARMENIAN CAPITAL LETTER TIWN */\n#define XK_Armenian_tyun              0x100057f  /* U+057F ARMENIAN SMALL LETTER TIWN */\n#define XK_Armenian_RE                0x1000550  /* U+0550 ARMENIAN CAPITAL LETTER REH */\n#define XK_Armenian_re                0x1000580  /* U+0580 ARMENIAN SMALL LETTER REH */\n#define XK_Armenian_TSO               0x1000551  /* U+0551 ARMENIAN CAPITAL LETTER CO */\n#define XK_Armenian_tso               0x1000581  /* U+0581 ARMENIAN SMALL LETTER CO */\n#define XK_Armenian_VYUN              0x1000552  /* U+0552 ARMENIAN CAPITAL LETTER YIWN */\n#define XK_Armenian_vyun              0x1000582  /* U+0582 ARMENIAN SMALL LETTER YIWN */\n#define XK_Armenian_PYUR              0x1000553  /* U+0553 ARMENIAN CAPITAL LETTER PIWR */\n#define XK_Armenian_pyur              0x1000583  /* U+0583 ARMENIAN SMALL LETTER PIWR */\n#define XK_Armenian_KE                0x1000554  /* U+0554 ARMENIAN CAPITAL LETTER KEH */\n#define XK_Armenian_ke                0x1000584  /* U+0584 ARMENIAN SMALL LETTER KEH */\n#define XK_Armenian_O                 0x1000555  /* U+0555 ARMENIAN CAPITAL LETTER OH */\n#define XK_Armenian_o                 0x1000585  /* U+0585 ARMENIAN SMALL LETTER OH */\n#define XK_Armenian_FE                0x1000556  /* U+0556 ARMENIAN CAPITAL LETTER FEH */\n#define XK_Armenian_fe                0x1000586  /* U+0586 ARMENIAN SMALL LETTER FEH */\n#define XK_Armenian_apostrophe        0x100055a  /* U+055A ARMENIAN APOSTROPHE */\n#endif /* XK_ARMENIAN */\n\n/*\n * Georgian\n */\n\n#ifdef XK_GEORGIAN\n#define XK_Georgian_an                0x10010d0  /* U+10D0 GEORGIAN LETTER AN */\n#define XK_Georgian_ban               0x10010d1  /* U+10D1 GEORGIAN LETTER BAN */\n#define XK_Georgian_gan               0x10010d2  /* U+10D2 GEORGIAN LETTER GAN */\n#define XK_Georgian_don               0x10010d3  /* U+10D3 GEORGIAN LETTER DON */\n#define XK_Georgian_en                0x10010d4  /* U+10D4 GEORGIAN LETTER EN */\n#define XK_Georgian_vin               0x10010d5  /* U+10D5 GEORGIAN LETTER VIN */\n#define XK_Georgian_zen               0x10010d6  /* U+10D6 GEORGIAN LETTER ZEN */\n#define XK_Georgian_tan               0x10010d7  /* U+10D7 GEORGIAN LETTER TAN */\n#define XK_Georgian_in                0x10010d8  /* U+10D8 GEORGIAN LETTER IN */\n#define XK_Georgian_kan               0x10010d9  /* U+10D9 GEORGIAN LETTER KAN */\n#define XK_Georgian_las               0x10010da  /* U+10DA GEORGIAN LETTER LAS */\n#define XK_Georgian_man               0x10010db  /* U+10DB GEORGIAN LETTER MAN */\n#define XK_Georgian_nar               0x10010dc  /* U+10DC GEORGIAN LETTER NAR */\n#define XK_Georgian_on                0x10010dd  /* U+10DD GEORGIAN LETTER ON */\n#define XK_Georgian_par               0x10010de  /* U+10DE GEORGIAN LETTER PAR */\n#define XK_Georgian_zhar              0x10010df  /* U+10DF GEORGIAN LETTER ZHAR */\n#define XK_Georgian_rae               0x10010e0  /* U+10E0 GEORGIAN LETTER RAE */\n#define XK_Georgian_san               0x10010e1  /* U+10E1 GEORGIAN LETTER SAN */\n#define XK_Georgian_tar               0x10010e2  /* U+10E2 GEORGIAN LETTER TAR */\n#define XK_Georgian_un                0x10010e3  /* U+10E3 GEORGIAN LETTER UN */\n#define XK_Georgian_phar              0x10010e4  /* U+10E4 GEORGIAN LETTER PHAR */\n#define XK_Georgian_khar              0x10010e5  /* U+10E5 GEORGIAN LETTER KHAR */\n#define XK_Georgian_ghan              0x10010e6  /* U+10E6 GEORGIAN LETTER GHAN */\n#define XK_Georgian_qar               0x10010e7  /* U+10E7 GEORGIAN LETTER QAR */\n#define XK_Georgian_shin              0x10010e8  /* U+10E8 GEORGIAN LETTER SHIN */\n#define XK_Georgian_chin              0x10010e9  /* U+10E9 GEORGIAN LETTER CHIN */\n#define XK_Georgian_can               0x10010ea  /* U+10EA GEORGIAN LETTER CAN */\n#define XK_Georgian_jil               0x10010eb  /* U+10EB GEORGIAN LETTER JIL */\n#define XK_Georgian_cil               0x10010ec  /* U+10EC GEORGIAN LETTER CIL */\n#define XK_Georgian_char              0x10010ed  /* U+10ED GEORGIAN LETTER CHAR */\n#define XK_Georgian_xan               0x10010ee  /* U+10EE GEORGIAN LETTER XAN */\n#define XK_Georgian_jhan              0x10010ef  /* U+10EF GEORGIAN LETTER JHAN */\n#define XK_Georgian_hae               0x10010f0  /* U+10F0 GEORGIAN LETTER HAE */\n#define XK_Georgian_he                0x10010f1  /* U+10F1 GEORGIAN LETTER HE */\n#define XK_Georgian_hie               0x10010f2  /* U+10F2 GEORGIAN LETTER HIE */\n#define XK_Georgian_we                0x10010f3  /* U+10F3 GEORGIAN LETTER WE */\n#define XK_Georgian_har               0x10010f4  /* U+10F4 GEORGIAN LETTER HAR */\n#define XK_Georgian_hoe               0x10010f5  /* U+10F5 GEORGIAN LETTER HOE */\n#define XK_Georgian_fi                0x10010f6  /* U+10F6 GEORGIAN LETTER FI */\n#endif /* XK_GEORGIAN */\n\n/*\n * Azeri (and other Turkic or Caucasian languages)\n */\n\n#ifdef XK_CAUCASUS\n/* latin */\n#define XK_Xabovedot                  0x1001e8a  /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */\n#define XK_Ibreve                     0x100012c  /* U+012C LATIN CAPITAL LETTER I WITH BREVE */\n#define XK_Zstroke                    0x10001b5  /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */\n#define XK_Gcaron                     0x10001e6  /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */\n#define XK_Ocaron                     0x10001d1  /* U+01D1 LATIN CAPITAL LETTER O WITH CARON */\n#define XK_Obarred                    0x100019f  /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */\n#define XK_xabovedot                  0x1001e8b  /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */\n#define XK_ibreve                     0x100012d  /* U+012D LATIN SMALL LETTER I WITH BREVE */\n#define XK_zstroke                    0x10001b6  /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */\n#define XK_gcaron                     0x10001e7  /* U+01E7 LATIN SMALL LETTER G WITH CARON */\n#define XK_ocaron                     0x10001d2  /* U+01D2 LATIN SMALL LETTER O WITH CARON */\n#define XK_obarred                    0x1000275  /* U+0275 LATIN SMALL LETTER BARRED O */\n#define XK_SCHWA                      0x100018f  /* U+018F LATIN CAPITAL LETTER SCHWA */\n#define XK_schwa                      0x1000259  /* U+0259 LATIN SMALL LETTER SCHWA */\n#define XK_EZH                        0x10001b7  /* U+01B7 LATIN CAPITAL LETTER EZH */\n#define XK_ezh                        0x1000292  /* U+0292 LATIN SMALL LETTER EZH */\n/* those are not really Caucasus */\n/* For Inupiak */\n#define XK_Lbelowdot                  0x1001e36  /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */\n#define XK_lbelowdot                  0x1001e37  /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */\n#endif /* XK_CAUCASUS */\n\n/*\n * Vietnamese\n */\n\n#ifdef XK_VIETNAMESE\n#define XK_Abelowdot                  0x1001ea0  /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */\n#define XK_abelowdot                  0x1001ea1  /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */\n#define XK_Ahook                      0x1001ea2  /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */\n#define XK_ahook                      0x1001ea3  /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */\n#define XK_Acircumflexacute           0x1001ea4  /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */\n#define XK_acircumflexacute           0x1001ea5  /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */\n#define XK_Acircumflexgrave           0x1001ea6  /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */\n#define XK_acircumflexgrave           0x1001ea7  /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */\n#define XK_Acircumflexhook            0x1001ea8  /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_acircumflexhook            0x1001ea9  /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Acircumflextilde           0x1001eaa  /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */\n#define XK_acircumflextilde           0x1001eab  /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */\n#define XK_Acircumflexbelowdot        0x1001eac  /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_acircumflexbelowdot        0x1001ead  /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Abreveacute                0x1001eae  /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */\n#define XK_abreveacute                0x1001eaf  /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */\n#define XK_Abrevegrave                0x1001eb0  /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */\n#define XK_abrevegrave                0x1001eb1  /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */\n#define XK_Abrevehook                 0x1001eb2  /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */\n#define XK_abrevehook                 0x1001eb3  /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */\n#define XK_Abrevetilde                0x1001eb4  /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */\n#define XK_abrevetilde                0x1001eb5  /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */\n#define XK_Abrevebelowdot             0x1001eb6  /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */\n#define XK_abrevebelowdot             0x1001eb7  /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */\n#define XK_Ebelowdot                  0x1001eb8  /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */\n#define XK_ebelowdot                  0x1001eb9  /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */\n#define XK_Ehook                      0x1001eba  /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */\n#define XK_ehook                      0x1001ebb  /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */\n#define XK_Etilde                     0x1001ebc  /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */\n#define XK_etilde                     0x1001ebd  /* U+1EBD LATIN SMALL LETTER E WITH TILDE */\n#define XK_Ecircumflexacute           0x1001ebe  /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */\n#define XK_ecircumflexacute           0x1001ebf  /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */\n#define XK_Ecircumflexgrave           0x1001ec0  /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */\n#define XK_ecircumflexgrave           0x1001ec1  /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */\n#define XK_Ecircumflexhook            0x1001ec2  /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_ecircumflexhook            0x1001ec3  /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Ecircumflextilde           0x1001ec4  /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */\n#define XK_ecircumflextilde           0x1001ec5  /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */\n#define XK_Ecircumflexbelowdot        0x1001ec6  /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_ecircumflexbelowdot        0x1001ec7  /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Ihook                      0x1001ec8  /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */\n#define XK_ihook                      0x1001ec9  /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */\n#define XK_Ibelowdot                  0x1001eca  /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */\n#define XK_ibelowdot                  0x1001ecb  /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */\n#define XK_Obelowdot                  0x1001ecc  /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */\n#define XK_obelowdot                  0x1001ecd  /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */\n#define XK_Ohook                      0x1001ece  /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */\n#define XK_ohook                      0x1001ecf  /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */\n#define XK_Ocircumflexacute           0x1001ed0  /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */\n#define XK_ocircumflexacute           0x1001ed1  /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */\n#define XK_Ocircumflexgrave           0x1001ed2  /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */\n#define XK_ocircumflexgrave           0x1001ed3  /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */\n#define XK_Ocircumflexhook            0x1001ed4  /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_ocircumflexhook            0x1001ed5  /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Ocircumflextilde           0x1001ed6  /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */\n#define XK_ocircumflextilde           0x1001ed7  /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */\n#define XK_Ocircumflexbelowdot        0x1001ed8  /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_ocircumflexbelowdot        0x1001ed9  /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Ohornacute                 0x1001eda  /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */\n#define XK_ohornacute                 0x1001edb  /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */\n#define XK_Ohorngrave                 0x1001edc  /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */\n#define XK_ohorngrave                 0x1001edd  /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */\n#define XK_Ohornhook                  0x1001ede  /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */\n#define XK_ohornhook                  0x1001edf  /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */\n#define XK_Ohorntilde                 0x1001ee0  /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */\n#define XK_ohorntilde                 0x1001ee1  /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */\n#define XK_Ohornbelowdot              0x1001ee2  /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */\n#define XK_ohornbelowdot              0x1001ee3  /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */\n#define XK_Ubelowdot                  0x1001ee4  /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */\n#define XK_ubelowdot                  0x1001ee5  /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */\n#define XK_Uhook                      0x1001ee6  /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */\n#define XK_uhook                      0x1001ee7  /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */\n#define XK_Uhornacute                 0x1001ee8  /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */\n#define XK_uhornacute                 0x1001ee9  /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */\n#define XK_Uhorngrave                 0x1001eea  /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */\n#define XK_uhorngrave                 0x1001eeb  /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */\n#define XK_Uhornhook                  0x1001eec  /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */\n#define XK_uhornhook                  0x1001eed  /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */\n#define XK_Uhorntilde                 0x1001eee  /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */\n#define XK_uhorntilde                 0x1001eef  /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */\n#define XK_Uhornbelowdot              0x1001ef0  /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */\n#define XK_uhornbelowdot              0x1001ef1  /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */\n#define XK_Ybelowdot                  0x1001ef4  /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */\n#define XK_ybelowdot                  0x1001ef5  /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */\n#define XK_Yhook                      0x1001ef6  /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */\n#define XK_yhook                      0x1001ef7  /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */\n#define XK_Ytilde                     0x1001ef8  /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */\n#define XK_ytilde                     0x1001ef9  /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */\n#define XK_Ohorn                      0x10001a0  /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */\n#define XK_ohorn                      0x10001a1  /* U+01A1 LATIN SMALL LETTER O WITH HORN */\n#define XK_Uhorn                      0x10001af  /* U+01AF LATIN CAPITAL LETTER U WITH HORN */\n#define XK_uhorn                      0x10001b0  /* U+01B0 LATIN SMALL LETTER U WITH HORN */\n#define XK_combining_tilde            0x1000303  /* U+0303 COMBINING TILDE */\n#define XK_combining_grave            0x1000300  /* U+0300 COMBINING GRAVE ACCENT */\n#define XK_combining_acute            0x1000301  /* U+0301 COMBINING ACUTE ACCENT */\n#define XK_combining_hook             0x1000309  /* U+0309 COMBINING HOOK ABOVE */\n#define XK_combining_belowdot         0x1000323  /* U+0323 COMBINING DOT BELOW */\n\n#endif /* XK_VIETNAMESE */\n\n#ifdef XK_CURRENCY\n#define XK_EcuSign                    0x10020a0  /* U+20A0 EURO-CURRENCY SIGN */\n#define XK_ColonSign                  0x10020a1  /* U+20A1 COLON SIGN */\n#define XK_CruzeiroSign               0x10020a2  /* U+20A2 CRUZEIRO SIGN */\n#define XK_FFrancSign                 0x10020a3  /* U+20A3 FRENCH FRANC SIGN */\n#define XK_LiraSign                   0x10020a4  /* U+20A4 LIRA SIGN */\n#define XK_MillSign                   0x10020a5  /* U+20A5 MILL SIGN */\n#define XK_NairaSign                  0x10020a6  /* U+20A6 NAIRA SIGN */\n#define XK_PesetaSign                 0x10020a7  /* U+20A7 PESETA SIGN */\n#define XK_RupeeSign                  0x10020a8  /* U+20A8 RUPEE SIGN */\n#define XK_WonSign                    0x10020a9  /* U+20A9 WON SIGN */\n#define XK_NewSheqelSign              0x10020aa  /* U+20AA NEW SHEQEL SIGN */\n#define XK_DongSign                   0x10020ab  /* U+20AB DONG SIGN */\n#define XK_EuroSign                      0x20ac  /* U+20AC EURO SIGN */\n#endif /* XK_CURRENCY */\n\n#ifdef XK_MATHEMATICAL\n/* one, two and three are defined above. */\n#define XK_zerosuperior               0x1002070  /* U+2070 SUPERSCRIPT ZERO */\n#define XK_foursuperior               0x1002074  /* U+2074 SUPERSCRIPT FOUR */\n#define XK_fivesuperior               0x1002075  /* U+2075 SUPERSCRIPT FIVE */\n#define XK_sixsuperior                0x1002076  /* U+2076 SUPERSCRIPT SIX */\n#define XK_sevensuperior              0x1002077  /* U+2077 SUPERSCRIPT SEVEN */\n#define XK_eightsuperior              0x1002078  /* U+2078 SUPERSCRIPT EIGHT */\n#define XK_ninesuperior               0x1002079  /* U+2079 SUPERSCRIPT NINE */\n#define XK_zerosubscript              0x1002080  /* U+2080 SUBSCRIPT ZERO */\n#define XK_onesubscript               0x1002081  /* U+2081 SUBSCRIPT ONE */\n#define XK_twosubscript               0x1002082  /* U+2082 SUBSCRIPT TWO */\n#define XK_threesubscript             0x1002083  /* U+2083 SUBSCRIPT THREE */\n#define XK_foursubscript              0x1002084  /* U+2084 SUBSCRIPT FOUR */\n#define XK_fivesubscript              0x1002085  /* U+2085 SUBSCRIPT FIVE */\n#define XK_sixsubscript               0x1002086  /* U+2086 SUBSCRIPT SIX */\n#define XK_sevensubscript             0x1002087  /* U+2087 SUBSCRIPT SEVEN */\n#define XK_eightsubscript             0x1002088  /* U+2088 SUBSCRIPT EIGHT */\n#define XK_ninesubscript              0x1002089  /* U+2089 SUBSCRIPT NINE */\n#define XK_partdifferential           0x1002202  /* U+2202 PARTIAL DIFFERENTIAL */\n#define XK_emptyset                   0x1002205  /* U+2205 EMPTY SET */\n#define XK_elementof                  0x1002208  /* U+2208 ELEMENT OF */\n#define XK_notelementof               0x1002209  /* U+2209 NOT AN ELEMENT OF */\n#define XK_containsas                 0x100220b  /* U+220B CONTAINS AS MEMBER */\n#define XK_squareroot                 0x100221a  /* U+221A SQUARE ROOT */\n#define XK_cuberoot                   0x100221b  /* U+221B CUBE ROOT */\n#define XK_fourthroot                 0x100221c  /* U+221C FOURTH ROOT */\n#define XK_dintegral                  0x100222c  /* U+222C DOUBLE INTEGRAL */\n#define XK_tintegral                  0x100222d  /* U+222D TRIPLE INTEGRAL */\n#define XK_because                    0x1002235  /* U+2235 BECAUSE */\n#define XK_approxeq                   0x1002248  /*(U+2248 ALMOST EQUAL TO)*/\n#define XK_notapproxeq                0x1002247  /*(U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO)*/\n#define XK_notidentical               0x1002262  /* U+2262 NOT IDENTICAL TO */\n#define XK_stricteq                   0x1002263  /* U+2263 STRICTLY EQUIVALENT TO */\n#endif /* XK_MATHEMATICAL */\n\n#ifdef XK_BRAILLE\n#define XK_braille_dot_1                 0xfff1\n#define XK_braille_dot_2                 0xfff2\n#define XK_braille_dot_3                 0xfff3\n#define XK_braille_dot_4                 0xfff4\n#define XK_braille_dot_5                 0xfff5\n#define XK_braille_dot_6                 0xfff6\n#define XK_braille_dot_7                 0xfff7\n#define XK_braille_dot_8                 0xfff8\n#define XK_braille_dot_9                 0xfff9\n#define XK_braille_dot_10                0xfffa\n#define XK_braille_blank              0x1002800  /* U+2800 BRAILLE PATTERN BLANK */\n#define XK_braille_dots_1             0x1002801  /* U+2801 BRAILLE PATTERN DOTS-1 */\n#define XK_braille_dots_2             0x1002802  /* U+2802 BRAILLE PATTERN DOTS-2 */\n#define XK_braille_dots_12            0x1002803  /* U+2803 BRAILLE PATTERN DOTS-12 */\n#define XK_braille_dots_3             0x1002804  /* U+2804 BRAILLE PATTERN DOTS-3 */\n#define XK_braille_dots_13            0x1002805  /* U+2805 BRAILLE PATTERN DOTS-13 */\n#define XK_braille_dots_23            0x1002806  /* U+2806 BRAILLE PATTERN DOTS-23 */\n#define XK_braille_dots_123           0x1002807  /* U+2807 BRAILLE PATTERN DOTS-123 */\n#define XK_braille_dots_4             0x1002808  /* U+2808 BRAILLE PATTERN DOTS-4 */\n#define XK_braille_dots_14            0x1002809  /* U+2809 BRAILLE PATTERN DOTS-14 */\n#define XK_braille_dots_24            0x100280a  /* U+280A BRAILLE PATTERN DOTS-24 */\n#define XK_braille_dots_124           0x100280b  /* U+280B BRAILLE PATTERN DOTS-124 */\n#define XK_braille_dots_34            0x100280c  /* U+280C BRAILLE PATTERN DOTS-34 */\n#define XK_braille_dots_134           0x100280d  /* U+280D BRAILLE PATTERN DOTS-134 */\n#define XK_braille_dots_234           0x100280e  /* U+280E BRAILLE PATTERN DOTS-234 */\n#define XK_braille_dots_1234          0x100280f  /* U+280F BRAILLE PATTERN DOTS-1234 */\n#define XK_braille_dots_5             0x1002810  /* U+2810 BRAILLE PATTERN DOTS-5 */\n#define XK_braille_dots_15            0x1002811  /* U+2811 BRAILLE PATTERN DOTS-15 */\n#define XK_braille_dots_25            0x1002812  /* U+2812 BRAILLE PATTERN DOTS-25 */\n#define XK_braille_dots_125           0x1002813  /* U+2813 BRAILLE PATTERN DOTS-125 */\n#define XK_braille_dots_35            0x1002814  /* U+2814 BRAILLE PATTERN DOTS-35 */\n#define XK_braille_dots_135           0x1002815  /* U+2815 BRAILLE PATTERN DOTS-135 */\n#define XK_braille_dots_235           0x1002816  /* U+2816 BRAILLE PATTERN DOTS-235 */\n#define XK_braille_dots_1235          0x1002817  /* U+2817 BRAILLE PATTERN DOTS-1235 */\n#define XK_braille_dots_45            0x1002818  /* U+2818 BRAILLE PATTERN DOTS-45 */\n#define XK_braille_dots_145           0x1002819  /* U+2819 BRAILLE PATTERN DOTS-145 */\n#define XK_braille_dots_245           0x100281a  /* U+281A BRAILLE PATTERN DOTS-245 */\n#define XK_braille_dots_1245          0x100281b  /* U+281B BRAILLE PATTERN DOTS-1245 */\n#define XK_braille_dots_345           0x100281c  /* U+281C BRAILLE PATTERN DOTS-345 */\n#define XK_braille_dots_1345          0x100281d  /* U+281D BRAILLE PATTERN DOTS-1345 */\n#define XK_braille_dots_2345          0x100281e  /* U+281E BRAILLE PATTERN DOTS-2345 */\n#define XK_braille_dots_12345         0x100281f  /* U+281F BRAILLE PATTERN DOTS-12345 */\n#define XK_braille_dots_6             0x1002820  /* U+2820 BRAILLE PATTERN DOTS-6 */\n#define XK_braille_dots_16            0x1002821  /* U+2821 BRAILLE PATTERN DOTS-16 */\n#define XK_braille_dots_26            0x1002822  /* U+2822 BRAILLE PATTERN DOTS-26 */\n#define XK_braille_dots_126           0x1002823  /* U+2823 BRAILLE PATTERN DOTS-126 */\n#define XK_braille_dots_36            0x1002824  /* U+2824 BRAILLE PATTERN DOTS-36 */\n#define XK_braille_dots_136           0x1002825  /* U+2825 BRAILLE PATTERN DOTS-136 */\n#define XK_braille_dots_236           0x1002826  /* U+2826 BRAILLE PATTERN DOTS-236 */\n#define XK_braille_dots_1236          0x1002827  /* U+2827 BRAILLE PATTERN DOTS-1236 */\n#define XK_braille_dots_46            0x1002828  /* U+2828 BRAILLE PATTERN DOTS-46 */\n#define XK_braille_dots_146           0x1002829  /* U+2829 BRAILLE PATTERN DOTS-146 */\n#define XK_braille_dots_246           0x100282a  /* U+282A BRAILLE PATTERN DOTS-246 */\n#define XK_braille_dots_1246          0x100282b  /* U+282B BRAILLE PATTERN DOTS-1246 */\n#define XK_braille_dots_346           0x100282c  /* U+282C BRAILLE PATTERN DOTS-346 */\n#define XK_braille_dots_1346          0x100282d  /* U+282D BRAILLE PATTERN DOTS-1346 */\n#define XK_braille_dots_2346          0x100282e  /* U+282E BRAILLE PATTERN DOTS-2346 */\n#define XK_braille_dots_12346         0x100282f  /* U+282F BRAILLE PATTERN DOTS-12346 */\n#define XK_braille_dots_56            0x1002830  /* U+2830 BRAILLE PATTERN DOTS-56 */\n#define XK_braille_dots_156           0x1002831  /* U+2831 BRAILLE PATTERN DOTS-156 */\n#define XK_braille_dots_256           0x1002832  /* U+2832 BRAILLE PATTERN DOTS-256 */\n#define XK_braille_dots_1256          0x1002833  /* U+2833 BRAILLE PATTERN DOTS-1256 */\n#define XK_braille_dots_356           0x1002834  /* U+2834 BRAILLE PATTERN DOTS-356 */\n#define XK_braille_dots_1356          0x1002835  /* U+2835 BRAILLE PATTERN DOTS-1356 */\n#define XK_braille_dots_2356          0x1002836  /* U+2836 BRAILLE PATTERN DOTS-2356 */\n#define XK_braille_dots_12356         0x1002837  /* U+2837 BRAILLE PATTERN DOTS-12356 */\n#define XK_braille_dots_456           0x1002838  /* U+2838 BRAILLE PATTERN DOTS-456 */\n#define XK_braille_dots_1456          0x1002839  /* U+2839 BRAILLE PATTERN DOTS-1456 */\n#define XK_braille_dots_2456          0x100283a  /* U+283A BRAILLE PATTERN DOTS-2456 */\n#define XK_braille_dots_12456         0x100283b  /* U+283B BRAILLE PATTERN DOTS-12456 */\n#define XK_braille_dots_3456          0x100283c  /* U+283C BRAILLE PATTERN DOTS-3456 */\n#define XK_braille_dots_13456         0x100283d  /* U+283D BRAILLE PATTERN DOTS-13456 */\n#define XK_braille_dots_23456         0x100283e  /* U+283E BRAILLE PATTERN DOTS-23456 */\n#define XK_braille_dots_123456        0x100283f  /* U+283F BRAILLE PATTERN DOTS-123456 */\n#define XK_braille_dots_7             0x1002840  /* U+2840 BRAILLE PATTERN DOTS-7 */\n#define XK_braille_dots_17            0x1002841  /* U+2841 BRAILLE PATTERN DOTS-17 */\n#define XK_braille_dots_27            0x1002842  /* U+2842 BRAILLE PATTERN DOTS-27 */\n#define XK_braille_dots_127           0x1002843  /* U+2843 BRAILLE PATTERN DOTS-127 */\n#define XK_braille_dots_37            0x1002844  /* U+2844 BRAILLE PATTERN DOTS-37 */\n#define XK_braille_dots_137           0x1002845  /* U+2845 BRAILLE PATTERN DOTS-137 */\n#define XK_braille_dots_237           0x1002846  /* U+2846 BRAILLE PATTERN DOTS-237 */\n#define XK_braille_dots_1237          0x1002847  /* U+2847 BRAILLE PATTERN DOTS-1237 */\n#define XK_braille_dots_47            0x1002848  /* U+2848 BRAILLE PATTERN DOTS-47 */\n#define XK_braille_dots_147           0x1002849  /* U+2849 BRAILLE PATTERN DOTS-147 */\n#define XK_braille_dots_247           0x100284a  /* U+284A BRAILLE PATTERN DOTS-247 */\n#define XK_braille_dots_1247          0x100284b  /* U+284B BRAILLE PATTERN DOTS-1247 */\n#define XK_braille_dots_347           0x100284c  /* U+284C BRAILLE PATTERN DOTS-347 */\n#define XK_braille_dots_1347          0x100284d  /* U+284D BRAILLE PATTERN DOTS-1347 */\n#define XK_braille_dots_2347          0x100284e  /* U+284E BRAILLE PATTERN DOTS-2347 */\n#define XK_braille_dots_12347         0x100284f  /* U+284F BRAILLE PATTERN DOTS-12347 */\n#define XK_braille_dots_57            0x1002850  /* U+2850 BRAILLE PATTERN DOTS-57 */\n#define XK_braille_dots_157           0x1002851  /* U+2851 BRAILLE PATTERN DOTS-157 */\n#define XK_braille_dots_257           0x1002852  /* U+2852 BRAILLE PATTERN DOTS-257 */\n#define XK_braille_dots_1257          0x1002853  /* U+2853 BRAILLE PATTERN DOTS-1257 */\n#define XK_braille_dots_357           0x1002854  /* U+2854 BRAILLE PATTERN DOTS-357 */\n#define XK_braille_dots_1357          0x1002855  /* U+2855 BRAILLE PATTERN DOTS-1357 */\n#define XK_braille_dots_2357          0x1002856  /* U+2856 BRAILLE PATTERN DOTS-2357 */\n#define XK_braille_dots_12357         0x1002857  /* U+2857 BRAILLE PATTERN DOTS-12357 */\n#define XK_braille_dots_457           0x1002858  /* U+2858 BRAILLE PATTERN DOTS-457 */\n#define XK_braille_dots_1457          0x1002859  /* U+2859 BRAILLE PATTERN DOTS-1457 */\n#define XK_braille_dots_2457          0x100285a  /* U+285A BRAILLE PATTERN DOTS-2457 */\n#define XK_braille_dots_12457         0x100285b  /* U+285B BRAILLE PATTERN DOTS-12457 */\n#define XK_braille_dots_3457          0x100285c  /* U+285C BRAILLE PATTERN DOTS-3457 */\n#define XK_braille_dots_13457         0x100285d  /* U+285D BRAILLE PATTERN DOTS-13457 */\n#define XK_braille_dots_23457         0x100285e  /* U+285E BRAILLE PATTERN DOTS-23457 */\n#define XK_braille_dots_123457        0x100285f  /* U+285F BRAILLE PATTERN DOTS-123457 */\n#define XK_braille_dots_67            0x1002860  /* U+2860 BRAILLE PATTERN DOTS-67 */\n#define XK_braille_dots_167           0x1002861  /* U+2861 BRAILLE PATTERN DOTS-167 */\n#define XK_braille_dots_267           0x1002862  /* U+2862 BRAILLE PATTERN DOTS-267 */\n#define XK_braille_dots_1267          0x1002863  /* U+2863 BRAILLE PATTERN DOTS-1267 */\n#define XK_braille_dots_367           0x1002864  /* U+2864 BRAILLE PATTERN DOTS-367 */\n#define XK_braille_dots_1367          0x1002865  /* U+2865 BRAILLE PATTERN DOTS-1367 */\n#define XK_braille_dots_2367          0x1002866  /* U+2866 BRAILLE PATTERN DOTS-2367 */\n#define XK_braille_dots_12367         0x1002867  /* U+2867 BRAILLE PATTERN DOTS-12367 */\n#define XK_braille_dots_467           0x1002868  /* U+2868 BRAILLE PATTERN DOTS-467 */\n#define XK_braille_dots_1467          0x1002869  /* U+2869 BRAILLE PATTERN DOTS-1467 */\n#define XK_braille_dots_2467          0x100286a  /* U+286A BRAILLE PATTERN DOTS-2467 */\n#define XK_braille_dots_12467         0x100286b  /* U+286B BRAILLE PATTERN DOTS-12467 */\n#define XK_braille_dots_3467          0x100286c  /* U+286C BRAILLE PATTERN DOTS-3467 */\n#define XK_braille_dots_13467         0x100286d  /* U+286D BRAILLE PATTERN DOTS-13467 */\n#define XK_braille_dots_23467         0x100286e  /* U+286E BRAILLE PATTERN DOTS-23467 */\n#define XK_braille_dots_123467        0x100286f  /* U+286F BRAILLE PATTERN DOTS-123467 */\n#define XK_braille_dots_567           0x1002870  /* U+2870 BRAILLE PATTERN DOTS-567 */\n#define XK_braille_dots_1567          0x1002871  /* U+2871 BRAILLE PATTERN DOTS-1567 */\n#define XK_braille_dots_2567          0x1002872  /* U+2872 BRAILLE PATTERN DOTS-2567 */\n#define XK_braille_dots_12567         0x1002873  /* U+2873 BRAILLE PATTERN DOTS-12567 */\n#define XK_braille_dots_3567          0x1002874  /* U+2874 BRAILLE PATTERN DOTS-3567 */\n#define XK_braille_dots_13567         0x1002875  /* U+2875 BRAILLE PATTERN DOTS-13567 */\n#define XK_braille_dots_23567         0x1002876  /* U+2876 BRAILLE PATTERN DOTS-23567 */\n#define XK_braille_dots_123567        0x1002877  /* U+2877 BRAILLE PATTERN DOTS-123567 */\n#define XK_braille_dots_4567          0x1002878  /* U+2878 BRAILLE PATTERN DOTS-4567 */\n#define XK_braille_dots_14567         0x1002879  /* U+2879 BRAILLE PATTERN DOTS-14567 */\n#define XK_braille_dots_24567         0x100287a  /* U+287A BRAILLE PATTERN DOTS-24567 */\n#define XK_braille_dots_124567        0x100287b  /* U+287B BRAILLE PATTERN DOTS-124567 */\n#define XK_braille_dots_34567         0x100287c  /* U+287C BRAILLE PATTERN DOTS-34567 */\n#define XK_braille_dots_134567        0x100287d  /* U+287D BRAILLE PATTERN DOTS-134567 */\n#define XK_braille_dots_234567        0x100287e  /* U+287E BRAILLE PATTERN DOTS-234567 */\n#define XK_braille_dots_1234567       0x100287f  /* U+287F BRAILLE PATTERN DOTS-1234567 */\n#define XK_braille_dots_8             0x1002880  /* U+2880 BRAILLE PATTERN DOTS-8 */\n#define XK_braille_dots_18            0x1002881  /* U+2881 BRAILLE PATTERN DOTS-18 */\n#define XK_braille_dots_28            0x1002882  /* U+2882 BRAILLE PATTERN DOTS-28 */\n#define XK_braille_dots_128           0x1002883  /* U+2883 BRAILLE PATTERN DOTS-128 */\n#define XK_braille_dots_38            0x1002884  /* U+2884 BRAILLE PATTERN DOTS-38 */\n#define XK_braille_dots_138           0x1002885  /* U+2885 BRAILLE PATTERN DOTS-138 */\n#define XK_braille_dots_238           0x1002886  /* U+2886 BRAILLE PATTERN DOTS-238 */\n#define XK_braille_dots_1238          0x1002887  /* U+2887 BRAILLE PATTERN DOTS-1238 */\n#define XK_braille_dots_48            0x1002888  /* U+2888 BRAILLE PATTERN DOTS-48 */\n#define XK_braille_dots_148           0x1002889  /* U+2889 BRAILLE PATTERN DOTS-148 */\n#define XK_braille_dots_248           0x100288a  /* U+288A BRAILLE PATTERN DOTS-248 */\n#define XK_braille_dots_1248          0x100288b  /* U+288B BRAILLE PATTERN DOTS-1248 */\n#define XK_braille_dots_348           0x100288c  /* U+288C BRAILLE PATTERN DOTS-348 */\n#define XK_braille_dots_1348          0x100288d  /* U+288D BRAILLE PATTERN DOTS-1348 */\n#define XK_braille_dots_2348          0x100288e  /* U+288E BRAILLE PATTERN DOTS-2348 */\n#define XK_braille_dots_12348         0x100288f  /* U+288F BRAILLE PATTERN DOTS-12348 */\n#define XK_braille_dots_58            0x1002890  /* U+2890 BRAILLE PATTERN DOTS-58 */\n#define XK_braille_dots_158           0x1002891  /* U+2891 BRAILLE PATTERN DOTS-158 */\n#define XK_braille_dots_258           0x1002892  /* U+2892 BRAILLE PATTERN DOTS-258 */\n#define XK_braille_dots_1258          0x1002893  /* U+2893 BRAILLE PATTERN DOTS-1258 */\n#define XK_braille_dots_358           0x1002894  /* U+2894 BRAILLE PATTERN DOTS-358 */\n#define XK_braille_dots_1358          0x1002895  /* U+2895 BRAILLE PATTERN DOTS-1358 */\n#define XK_braille_dots_2358          0x1002896  /* U+2896 BRAILLE PATTERN DOTS-2358 */\n#define XK_braille_dots_12358         0x1002897  /* U+2897 BRAILLE PATTERN DOTS-12358 */\n#define XK_braille_dots_458           0x1002898  /* U+2898 BRAILLE PATTERN DOTS-458 */\n#define XK_braille_dots_1458          0x1002899  /* U+2899 BRAILLE PATTERN DOTS-1458 */\n#define XK_braille_dots_2458          0x100289a  /* U+289A BRAILLE PATTERN DOTS-2458 */\n#define XK_braille_dots_12458         0x100289b  /* U+289B BRAILLE PATTERN DOTS-12458 */\n#define XK_braille_dots_3458          0x100289c  /* U+289C BRAILLE PATTERN DOTS-3458 */\n#define XK_braille_dots_13458         0x100289d  /* U+289D BRAILLE PATTERN DOTS-13458 */\n#define XK_braille_dots_23458         0x100289e  /* U+289E BRAILLE PATTERN DOTS-23458 */\n#define XK_braille_dots_123458        0x100289f  /* U+289F BRAILLE PATTERN DOTS-123458 */\n#define XK_braille_dots_68            0x10028a0  /* U+28A0 BRAILLE PATTERN DOTS-68 */\n#define XK_braille_dots_168           0x10028a1  /* U+28A1 BRAILLE PATTERN DOTS-168 */\n#define XK_braille_dots_268           0x10028a2  /* U+28A2 BRAILLE PATTERN DOTS-268 */\n#define XK_braille_dots_1268          0x10028a3  /* U+28A3 BRAILLE PATTERN DOTS-1268 */\n#define XK_braille_dots_368           0x10028a4  /* U+28A4 BRAILLE PATTERN DOTS-368 */\n#define XK_braille_dots_1368          0x10028a5  /* U+28A5 BRAILLE PATTERN DOTS-1368 */\n#define XK_braille_dots_2368          0x10028a6  /* U+28A6 BRAILLE PATTERN DOTS-2368 */\n#define XK_braille_dots_12368         0x10028a7  /* U+28A7 BRAILLE PATTERN DOTS-12368 */\n#define XK_braille_dots_468           0x10028a8  /* U+28A8 BRAILLE PATTERN DOTS-468 */\n#define XK_braille_dots_1468          0x10028a9  /* U+28A9 BRAILLE PATTERN DOTS-1468 */\n#define XK_braille_dots_2468          0x10028aa  /* U+28AA BRAILLE PATTERN DOTS-2468 */\n#define XK_braille_dots_12468         0x10028ab  /* U+28AB BRAILLE PATTERN DOTS-12468 */\n#define XK_braille_dots_3468          0x10028ac  /* U+28AC BRAILLE PATTERN DOTS-3468 */\n#define XK_braille_dots_13468         0x10028ad  /* U+28AD BRAILLE PATTERN DOTS-13468 */\n#define XK_braille_dots_23468         0x10028ae  /* U+28AE BRAILLE PATTERN DOTS-23468 */\n#define XK_braille_dots_123468        0x10028af  /* U+28AF BRAILLE PATTERN DOTS-123468 */\n#define XK_braille_dots_568           0x10028b0  /* U+28B0 BRAILLE PATTERN DOTS-568 */\n#define XK_braille_dots_1568          0x10028b1  /* U+28B1 BRAILLE PATTERN DOTS-1568 */\n#define XK_braille_dots_2568          0x10028b2  /* U+28B2 BRAILLE PATTERN DOTS-2568 */\n#define XK_braille_dots_12568         0x10028b3  /* U+28B3 BRAILLE PATTERN DOTS-12568 */\n#define XK_braille_dots_3568          0x10028b4  /* U+28B4 BRAILLE PATTERN DOTS-3568 */\n#define XK_braille_dots_13568         0x10028b5  /* U+28B5 BRAILLE PATTERN DOTS-13568 */\n#define XK_braille_dots_23568         0x10028b6  /* U+28B6 BRAILLE PATTERN DOTS-23568 */\n#define XK_braille_dots_123568        0x10028b7  /* U+28B7 BRAILLE PATTERN DOTS-123568 */\n#define XK_braille_dots_4568          0x10028b8  /* U+28B8 BRAILLE PATTERN DOTS-4568 */\n#define XK_braille_dots_14568         0x10028b9  /* U+28B9 BRAILLE PATTERN DOTS-14568 */\n#define XK_braille_dots_24568         0x10028ba  /* U+28BA BRAILLE PATTERN DOTS-24568 */\n#define XK_braille_dots_124568        0x10028bb  /* U+28BB BRAILLE PATTERN DOTS-124568 */\n#define XK_braille_dots_34568         0x10028bc  /* U+28BC BRAILLE PATTERN DOTS-34568 */\n#define XK_braille_dots_134568        0x10028bd  /* U+28BD BRAILLE PATTERN DOTS-134568 */\n#define XK_braille_dots_234568        0x10028be  /* U+28BE BRAILLE PATTERN DOTS-234568 */\n#define XK_braille_dots_1234568       0x10028bf  /* U+28BF BRAILLE PATTERN DOTS-1234568 */\n#define XK_braille_dots_78            0x10028c0  /* U+28C0 BRAILLE PATTERN DOTS-78 */\n#define XK_braille_dots_178           0x10028c1  /* U+28C1 BRAILLE PATTERN DOTS-178 */\n#define XK_braille_dots_278           0x10028c2  /* U+28C2 BRAILLE PATTERN DOTS-278 */\n#define XK_braille_dots_1278          0x10028c3  /* U+28C3 BRAILLE PATTERN DOTS-1278 */\n#define XK_braille_dots_378           0x10028c4  /* U+28C4 BRAILLE PATTERN DOTS-378 */\n#define XK_braille_dots_1378          0x10028c5  /* U+28C5 BRAILLE PATTERN DOTS-1378 */\n#define XK_braille_dots_2378          0x10028c6  /* U+28C6 BRAILLE PATTERN DOTS-2378 */\n#define XK_braille_dots_12378         0x10028c7  /* U+28C7 BRAILLE PATTERN DOTS-12378 */\n#define XK_braille_dots_478           0x10028c8  /* U+28C8 BRAILLE PATTERN DOTS-478 */\n#define XK_braille_dots_1478          0x10028c9  /* U+28C9 BRAILLE PATTERN DOTS-1478 */\n#define XK_braille_dots_2478          0x10028ca  /* U+28CA BRAILLE PATTERN DOTS-2478 */\n#define XK_braille_dots_12478         0x10028cb  /* U+28CB BRAILLE PATTERN DOTS-12478 */\n#define XK_braille_dots_3478          0x10028cc  /* U+28CC BRAILLE PATTERN DOTS-3478 */\n#define XK_braille_dots_13478         0x10028cd  /* U+28CD BRAILLE PATTERN DOTS-13478 */\n#define XK_braille_dots_23478         0x10028ce  /* U+28CE BRAILLE PATTERN DOTS-23478 */\n#define XK_braille_dots_123478        0x10028cf  /* U+28CF BRAILLE PATTERN DOTS-123478 */\n#define XK_braille_dots_578           0x10028d0  /* U+28D0 BRAILLE PATTERN DOTS-578 */\n#define XK_braille_dots_1578          0x10028d1  /* U+28D1 BRAILLE PATTERN DOTS-1578 */\n#define XK_braille_dots_2578          0x10028d2  /* U+28D2 BRAILLE PATTERN DOTS-2578 */\n#define XK_braille_dots_12578         0x10028d3  /* U+28D3 BRAILLE PATTERN DOTS-12578 */\n#define XK_braille_dots_3578          0x10028d4  /* U+28D4 BRAILLE PATTERN DOTS-3578 */\n#define XK_braille_dots_13578         0x10028d5  /* U+28D5 BRAILLE PATTERN DOTS-13578 */\n#define XK_braille_dots_23578         0x10028d6  /* U+28D6 BRAILLE PATTERN DOTS-23578 */\n#define XK_braille_dots_123578        0x10028d7  /* U+28D7 BRAILLE PATTERN DOTS-123578 */\n#define XK_braille_dots_4578          0x10028d8  /* U+28D8 BRAILLE PATTERN DOTS-4578 */\n#define XK_braille_dots_14578         0x10028d9  /* U+28D9 BRAILLE PATTERN DOTS-14578 */\n#define XK_braille_dots_24578         0x10028da  /* U+28DA BRAILLE PATTERN DOTS-24578 */\n#define XK_braille_dots_124578        0x10028db  /* U+28DB BRAILLE PATTERN DOTS-124578 */\n#define XK_braille_dots_34578         0x10028dc  /* U+28DC BRAILLE PATTERN DOTS-34578 */\n#define XK_braille_dots_134578        0x10028dd  /* U+28DD BRAILLE PATTERN DOTS-134578 */\n#define XK_braille_dots_234578        0x10028de  /* U+28DE BRAILLE PATTERN DOTS-234578 */\n#define XK_braille_dots_1234578       0x10028df  /* U+28DF BRAILLE PATTERN DOTS-1234578 */\n#define XK_braille_dots_678           0x10028e0  /* U+28E0 BRAILLE PATTERN DOTS-678 */\n#define XK_braille_dots_1678          0x10028e1  /* U+28E1 BRAILLE PATTERN DOTS-1678 */\n#define XK_braille_dots_2678          0x10028e2  /* U+28E2 BRAILLE PATTERN DOTS-2678 */\n#define XK_braille_dots_12678         0x10028e3  /* U+28E3 BRAILLE PATTERN DOTS-12678 */\n#define XK_braille_dots_3678          0x10028e4  /* U+28E4 BRAILLE PATTERN DOTS-3678 */\n#define XK_braille_dots_13678         0x10028e5  /* U+28E5 BRAILLE PATTERN DOTS-13678 */\n#define XK_braille_dots_23678         0x10028e6  /* U+28E6 BRAILLE PATTERN DOTS-23678 */\n#define XK_braille_dots_123678        0x10028e7  /* U+28E7 BRAILLE PATTERN DOTS-123678 */\n#define XK_braille_dots_4678          0x10028e8  /* U+28E8 BRAILLE PATTERN DOTS-4678 */\n#define XK_braille_dots_14678         0x10028e9  /* U+28E9 BRAILLE PATTERN DOTS-14678 */\n#define XK_braille_dots_24678         0x10028ea  /* U+28EA BRAILLE PATTERN DOTS-24678 */\n#define XK_braille_dots_124678        0x10028eb  /* U+28EB BRAILLE PATTERN DOTS-124678 */\n#define XK_braille_dots_34678         0x10028ec  /* U+28EC BRAILLE PATTERN DOTS-34678 */\n#define XK_braille_dots_134678        0x10028ed  /* U+28ED BRAILLE PATTERN DOTS-134678 */\n#define XK_braille_dots_234678        0x10028ee  /* U+28EE BRAILLE PATTERN DOTS-234678 */\n#define XK_braille_dots_1234678       0x10028ef  /* U+28EF BRAILLE PATTERN DOTS-1234678 */\n#define XK_braille_dots_5678          0x10028f0  /* U+28F0 BRAILLE PATTERN DOTS-5678 */\n#define XK_braille_dots_15678         0x10028f1  /* U+28F1 BRAILLE PATTERN DOTS-15678 */\n#define XK_braille_dots_25678         0x10028f2  /* U+28F2 BRAILLE PATTERN DOTS-25678 */\n#define XK_braille_dots_125678        0x10028f3  /* U+28F3 BRAILLE PATTERN DOTS-125678 */\n#define XK_braille_dots_35678         0x10028f4  /* U+28F4 BRAILLE PATTERN DOTS-35678 */\n#define XK_braille_dots_135678        0x10028f5  /* U+28F5 BRAILLE PATTERN DOTS-135678 */\n#define XK_braille_dots_235678        0x10028f6  /* U+28F6 BRAILLE PATTERN DOTS-235678 */\n#define XK_braille_dots_1235678       0x10028f7  /* U+28F7 BRAILLE PATTERN DOTS-1235678 */\n#define XK_braille_dots_45678         0x10028f8  /* U+28F8 BRAILLE PATTERN DOTS-45678 */\n#define XK_braille_dots_145678        0x10028f9  /* U+28F9 BRAILLE PATTERN DOTS-145678 */\n#define XK_braille_dots_245678        0x10028fa  /* U+28FA BRAILLE PATTERN DOTS-245678 */\n#define XK_braille_dots_1245678       0x10028fb  /* U+28FB BRAILLE PATTERN DOTS-1245678 */\n#define XK_braille_dots_345678        0x10028fc  /* U+28FC BRAILLE PATTERN DOTS-345678 */\n#define XK_braille_dots_1345678       0x10028fd  /* U+28FD BRAILLE PATTERN DOTS-1345678 */\n#define XK_braille_dots_2345678       0x10028fe  /* U+28FE BRAILLE PATTERN DOTS-2345678 */\n#define XK_braille_dots_12345678      0x10028ff  /* U+28FF BRAILLE PATTERN DOTS-12345678 */\n#endif /* XK_BRAILLE */\n\n/*\n * Sinhala (http://unicode.org/charts/PDF/U0D80.pdf)\n * http://www.nongnu.org/sinhala/doc/transliteration/sinhala-transliteration_6.html\n */\n\n#ifdef XK_SINHALA\n#define XK_Sinh_ng                    0x1000d82  /* U+0D82 SINHALA SIGN ANUSVARAYA */\n#define XK_Sinh_h2                    0x1000d83  /* U+0D83 SINHALA SIGN VISARGAYA */\n#define XK_Sinh_a                     0x1000d85  /* U+0D85 SINHALA LETTER AYANNA */\n#define XK_Sinh_aa                    0x1000d86  /* U+0D86 SINHALA LETTER AAYANNA */\n#define XK_Sinh_ae                    0x1000d87  /* U+0D87 SINHALA LETTER AEYANNA */\n#define XK_Sinh_aee                   0x1000d88  /* U+0D88 SINHALA LETTER AEEYANNA */\n#define XK_Sinh_i                     0x1000d89  /* U+0D89 SINHALA LETTER IYANNA */\n#define XK_Sinh_ii                    0x1000d8a  /* U+0D8A SINHALA LETTER IIYANNA */\n#define XK_Sinh_u                     0x1000d8b  /* U+0D8B SINHALA LETTER UYANNA */\n#define XK_Sinh_uu                    0x1000d8c  /* U+0D8C SINHALA LETTER UUYANNA */\n#define XK_Sinh_ri                    0x1000d8d  /* U+0D8D SINHALA LETTER IRUYANNA */\n#define XK_Sinh_rii                   0x1000d8e  /* U+0D8E SINHALA LETTER IRUUYANNA */\n#define XK_Sinh_lu                    0x1000d8f  /* U+0D8F SINHALA LETTER ILUYANNA */\n#define XK_Sinh_luu                   0x1000d90  /* U+0D90 SINHALA LETTER ILUUYANNA */\n#define XK_Sinh_e                     0x1000d91  /* U+0D91 SINHALA LETTER EYANNA */\n#define XK_Sinh_ee                    0x1000d92  /* U+0D92 SINHALA LETTER EEYANNA */\n#define XK_Sinh_ai                    0x1000d93  /* U+0D93 SINHALA LETTER AIYANNA */\n#define XK_Sinh_o                     0x1000d94  /* U+0D94 SINHALA LETTER OYANNA */\n#define XK_Sinh_oo                    0x1000d95  /* U+0D95 SINHALA LETTER OOYANNA */\n#define XK_Sinh_au                    0x1000d96  /* U+0D96 SINHALA LETTER AUYANNA */\n#define XK_Sinh_ka                    0x1000d9a  /* U+0D9A SINHALA LETTER ALPAPRAANA KAYANNA */\n#define XK_Sinh_kha                   0x1000d9b  /* U+0D9B SINHALA LETTER MAHAAPRAANA KAYANNA */\n#define XK_Sinh_ga                    0x1000d9c  /* U+0D9C SINHALA LETTER ALPAPRAANA GAYANNA */\n#define XK_Sinh_gha                   0x1000d9d  /* U+0D9D SINHALA LETTER MAHAAPRAANA GAYANNA */\n#define XK_Sinh_ng2                   0x1000d9e  /* U+0D9E SINHALA LETTER KANTAJA NAASIKYAYA */\n#define XK_Sinh_nga                   0x1000d9f  /* U+0D9F SINHALA LETTER SANYAKA GAYANNA */\n#define XK_Sinh_ca                    0x1000da0  /* U+0DA0 SINHALA LETTER ALPAPRAANA CAYANNA */\n#define XK_Sinh_cha                   0x1000da1  /* U+0DA1 SINHALA LETTER MAHAAPRAANA CAYANNA */\n#define XK_Sinh_ja                    0x1000da2  /* U+0DA2 SINHALA LETTER ALPAPRAANA JAYANNA */\n#define XK_Sinh_jha                   0x1000da3  /* U+0DA3 SINHALA LETTER MAHAAPRAANA JAYANNA */\n#define XK_Sinh_nya                   0x1000da4  /* U+0DA4 SINHALA LETTER TAALUJA NAASIKYAYA */\n#define XK_Sinh_jnya                  0x1000da5  /* U+0DA5 SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA */\n#define XK_Sinh_nja                   0x1000da6  /* U+0DA6 SINHALA LETTER SANYAKA JAYANNA */\n#define XK_Sinh_tta                   0x1000da7  /* U+0DA7 SINHALA LETTER ALPAPRAANA TTAYANNA */\n#define XK_Sinh_ttha                  0x1000da8  /* U+0DA8 SINHALA LETTER MAHAAPRAANA TTAYANNA */\n#define XK_Sinh_dda                   0x1000da9  /* U+0DA9 SINHALA LETTER ALPAPRAANA DDAYANNA */\n#define XK_Sinh_ddha                  0x1000daa  /* U+0DAA SINHALA LETTER MAHAAPRAANA DDAYANNA */\n#define XK_Sinh_nna                   0x1000dab  /* U+0DAB SINHALA LETTER MUURDHAJA NAYANNA */\n#define XK_Sinh_ndda                  0x1000dac  /* U+0DAC SINHALA LETTER SANYAKA DDAYANNA */\n#define XK_Sinh_tha                   0x1000dad  /* U+0DAD SINHALA LETTER ALPAPRAANA TAYANNA */\n#define XK_Sinh_thha                  0x1000dae  /* U+0DAE SINHALA LETTER MAHAAPRAANA TAYANNA */\n#define XK_Sinh_dha                   0x1000daf  /* U+0DAF SINHALA LETTER ALPAPRAANA DAYANNA */\n#define XK_Sinh_dhha                  0x1000db0  /* U+0DB0 SINHALA LETTER MAHAAPRAANA DAYANNA */\n#define XK_Sinh_na                    0x1000db1  /* U+0DB1 SINHALA LETTER DANTAJA NAYANNA */\n#define XK_Sinh_ndha                  0x1000db3  /* U+0DB3 SINHALA LETTER SANYAKA DAYANNA */\n#define XK_Sinh_pa                    0x1000db4  /* U+0DB4 SINHALA LETTER ALPAPRAANA PAYANNA */\n#define XK_Sinh_pha                   0x1000db5  /* U+0DB5 SINHALA LETTER MAHAAPRAANA PAYANNA */\n#define XK_Sinh_ba                    0x1000db6  /* U+0DB6 SINHALA LETTER ALPAPRAANA BAYANNA */\n#define XK_Sinh_bha                   0x1000db7  /* U+0DB7 SINHALA LETTER MAHAAPRAANA BAYANNA */\n#define XK_Sinh_ma                    0x1000db8  /* U+0DB8 SINHALA LETTER MAYANNA */\n#define XK_Sinh_mba                   0x1000db9  /* U+0DB9 SINHALA LETTER AMBA BAYANNA */\n#define XK_Sinh_ya                    0x1000dba  /* U+0DBA SINHALA LETTER YAYANNA */\n#define XK_Sinh_ra                    0x1000dbb  /* U+0DBB SINHALA LETTER RAYANNA */\n#define XK_Sinh_la                    0x1000dbd  /* U+0DBD SINHALA LETTER DANTAJA LAYANNA */\n#define XK_Sinh_va                    0x1000dc0  /* U+0DC0 SINHALA LETTER VAYANNA */\n#define XK_Sinh_sha                   0x1000dc1  /* U+0DC1 SINHALA LETTER TAALUJA SAYANNA */\n#define XK_Sinh_ssha                  0x1000dc2  /* U+0DC2 SINHALA LETTER MUURDHAJA SAYANNA */\n#define XK_Sinh_sa                    0x1000dc3  /* U+0DC3 SINHALA LETTER DANTAJA SAYANNA */\n#define XK_Sinh_ha                    0x1000dc4  /* U+0DC4 SINHALA LETTER HAYANNA */\n#define XK_Sinh_lla                   0x1000dc5  /* U+0DC5 SINHALA LETTER MUURDHAJA LAYANNA */\n#define XK_Sinh_fa                    0x1000dc6  /* U+0DC6 SINHALA LETTER FAYANNA */\n#define XK_Sinh_al                    0x1000dca  /* U+0DCA SINHALA SIGN AL-LAKUNA */\n#define XK_Sinh_aa2                   0x1000dcf  /* U+0DCF SINHALA VOWEL SIGN AELA-PILLA */\n#define XK_Sinh_ae2                   0x1000dd0  /* U+0DD0 SINHALA VOWEL SIGN KETTI AEDA-PILLA */\n#define XK_Sinh_aee2                  0x1000dd1  /* U+0DD1 SINHALA VOWEL SIGN DIGA AEDA-PILLA */\n#define XK_Sinh_i2                    0x1000dd2  /* U+0DD2 SINHALA VOWEL SIGN KETTI IS-PILLA */\n#define XK_Sinh_ii2                   0x1000dd3  /* U+0DD3 SINHALA VOWEL SIGN DIGA IS-PILLA */\n#define XK_Sinh_u2                    0x1000dd4  /* U+0DD4 SINHALA VOWEL SIGN KETTI PAA-PILLA */\n#define XK_Sinh_uu2                   0x1000dd6  /* U+0DD6 SINHALA VOWEL SIGN DIGA PAA-PILLA */\n#define XK_Sinh_ru2                   0x1000dd8  /* U+0DD8 SINHALA VOWEL SIGN GAETTA-PILLA */\n#define XK_Sinh_e2                    0x1000dd9  /* U+0DD9 SINHALA VOWEL SIGN KOMBUVA */\n#define XK_Sinh_ee2                   0x1000dda  /* U+0DDA SINHALA VOWEL SIGN DIGA KOMBUVA */\n#define XK_Sinh_ai2                   0x1000ddb  /* U+0DDB SINHALA VOWEL SIGN KOMBU DEKA */\n#define XK_Sinh_o2                    0x1000ddc  /* U+0DDC SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */\n#define XK_Sinh_oo2                   0x1000ddd  /* U+0DDD SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */\n#define XK_Sinh_au2                   0x1000dde  /* U+0DDE SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */\n#define XK_Sinh_lu2                   0x1000ddf  /* U+0DDF SINHALA VOWEL SIGN GAYANUKITTA */\n#define XK_Sinh_ruu2                  0x1000df2  /* U+0DF2 SINHALA VOWEL SIGN DIGA GAETTA-PILLA */\n#define XK_Sinh_luu2                  0x1000df3  /* U+0DF3 SINHALA VOWEL SIGN DIGA GAYANUKITTA */\n#define XK_Sinh_kunddaliya            0x1000df4  /* U+0DF4 SINHALA PUNCTUATION KUNDDALIYA */\n#endif /* XK_SINHALA */\n"
  },
  {
    "path": "xlib/rgb.txt",
    "content": "!      Changes compared to Xorg:rgb.txt\n!      name       old value       new value\n!      aqua           -            0 255 255\n!      crimson        -          220  20  60\n!      fuchsia        -          255   0 255\n!      gray      190 190 190     128 128 128\n!      green       0 255   0       0 128   0\n!      grey      190 190 190     128 128 128\n!      indigo         -           75   0 130\n!      lime           -            0 255   0\n!      maroon    176  48  96     128   0   0\n!      olive          -          128 128   0\n!      purple    160  32 240     128   0 128\n!      silver         -          192 192 192\n!      teal           -            0 128 128\n!\n240 248 255\t\taliceBlue\n250 235 215\t\tantiqueWhite\n255 239 219\t\tantiqueWhite1\n238 223 204\t\tantiqueWhite2\n205 192 176\t\tantiqueWhite3\n139 131 120\t\tantiqueWhite4\n  0 255 255\t\taqua\n127 255 212\t\taquamarine\n127 255 212\t\taquamarine1\n118 238 198\t\taquamarine2\n102 205 170\t\taquamarine3\n 69 139 116\t\taquamarine4\n240 255 255\t\tazure\n240 255 255\t\tazure1\n224 238 238\t\tazure2\n193 205 205\t\tazure3\n131 139 139\t\tazure4\n245 245 220\t\tbeige\n255 228 196\t\tbisque\n255 228 196\t\tbisque1\n238 213 183\t\tbisque2\n205 183 158\t\tbisque3\n139 125 107\t\tbisque4\n  0   0   0\t\tblack\n255 235 205\t\tblanchedAlmond\n  0   0 255\t\tblue\n  0   0 255\t\tblue1\n  0   0 238\t\tblue2\n  0   0 205\t\tblue3\n  0   0 139\t\tblue4\n138  43 226\t\tblueViolet\n165  42  42\t\tbrown\n255  64  64\t\tbrown1\n238  59  59\t\tbrown2\n205  51  51\t\tbrown3\n139  35  35\t\tbrown4\n222 184 135\t\tburlywood\n255 211 155\t\tburlywood1\n238 197 145\t\tburlywood2\n205 170 125\t\tburlywood3\n139 115  85\t\tburlywood4\n 95 158 160\t\tcadetBlue\n152 245 255\t\tcadetBlue1\n142 229 238\t\tcadetBlue2\n122 197 205\t\tcadetBlue3\n 83 134 139\t\tcadetBlue4\n127 255   0\t\tchartreuse\n127 255   0\t\tchartreuse1\n118 238   0\t\tchartreuse2\n102 205   0\t\tchartreuse3\n 69 139   0\t\tchartreuse4\n210 105  30\t\tchocolate\n255 127  36\t\tchocolate1\n238 118  33\t\tchocolate2\n205 102  29\t\tchocolate3\n139  69  19\t\tchocolate4\n255 127  80\t\tcoral\n255 114  86\t\tcoral1\n238 106  80\t\tcoral2\n205  91  69\t\tcoral3\n139  62  47\t\tcoral4\n100 149 237\t\tcornflowerBlue\n255 248 220\t\tcornsilk\n255 248 220\t\tcornsilk1\n238 232 205\t\tcornsilk2\n205 200 177\t\tcornsilk3\n139 136 120\t\tcornsilk4\n220  20  60\t\tcrimson\n  0 255 255\t\tcyan\n  0 255 255\t\tcyan1\n  0 238 238\t\tcyan2\n  0 205 205\t\tcyan3\n  0 139 139\t\tcyan4\n  0   0 139\t\tdarkBlue\n  0 139 139\t\tdarkCyan\n184 134  11\t\tdarkGoldenrod\n255 185  15\t\tdarkGoldenrod1\n238 173  14\t\tdarkGoldenrod2\n205 149  12\t\tdarkGoldenrod3\n139 101   8\t\tdarkGoldenrod4\n169 169 169\t\tdarkGray\n  0 100   0\t\tdarkGreen\n169 169 169\t\tdarkGrey\n189 183 107\t\tdarkKhaki\n139   0 139\t\tdarkMagenta\n 85 107  47\t\tdarkOliveGreen\n202 255 112\t\tdarkOliveGreen1\n188 238 104\t\tdarkOliveGreen2\n162 205  90\t\tdarkOliveGreen3\n110 139  61\t\tdarkOliveGreen4\n255 140   0\t\tdarkOrange\n255 127   0\t\tdarkOrange1\n238 118   0\t\tdarkOrange2\n205 102   0\t\tdarkOrange3\n139  69   0\t\tdarkOrange4\n153  50 204\t\tdarkOrchid\n191  62 255\t\tdarkOrchid1\n178  58 238\t\tdarkOrchid2\n154  50 205\t\tdarkOrchid3\n104  34 139\t\tdarkOrchid4\n139   0   0\t\tdarkRed\n233 150 122\t\tdarkSalmon\n143 188 143\t\tdarkSeaGreen\n193 255 193\t\tdarkSeaGreen1\n180 238 180\t\tdarkSeaGreen2\n155 205 155\t\tdarkSeaGreen3\n105 139 105\t\tdarkSeaGreen4\n 72  61 139\t\tdarkSlateBlue\n 47  79  79\t\tdarkSlateGray\n151 255 255\t\tdarkSlateGray1\n141 238 238\t\tdarkSlateGray2\n121 205 205\t\tdarkSlateGray3\n 82 139 139\t\tdarkSlateGray4\n 47  79  79\t\tdarkSlateGrey\n  0 206 209\t\tdarkTurquoise\n148   0 211\t\tdarkViolet\n255  20 147\t\tdeepPink\n255  20 147\t\tdeepPink1\n238  18 137\t\tdeepPink2\n205  16 118\t\tdeepPink3\n139  10  80\t\tdeepPink4\n  0 191 255\t\tdeepSkyBlue\n  0 191 255\t\tdeepSkyBlue1\n  0 178 238\t\tdeepSkyBlue2\n  0 154 205\t\tdeepSkyBlue3\n  0 104 139\t\tdeepSkyBlue4\n105 105 105\t\tdimGray\n105 105 105\t\tdimGrey\n 30 144 255\t\tdodgerBlue\n 30 144 255\t\tdodgerBlue1\n 28 134 238\t\tdodgerBlue2\n 24 116 205\t\tdodgerBlue3\n 16  78 139\t\tdodgerBlue4\n178  34  34\t\tfirebrick\n255  48  48\t\tfirebrick1\n238  44  44\t\tfirebrick2\n205  38  38\t\tfirebrick3\n139  26  26\t\tfirebrick4\n255 250 240\t\tfloralWhite\n 34 139  34\t\tforestGreen\n255   0 255\t\tfuchsia\n220 220 220\t\tgainsboro\n248 248 255\t\tghostWhite\n255 215   0\t\tgold\n255 215   0\t\tgold1\n238 201   0\t\tgold2\n205 173   0\t\tgold3\n139 117   0\t\tgold4\n218 165  32\t\tgoldenrod\n255 193  37\t\tgoldenrod1\n238 180  34\t\tgoldenrod2\n205 155  29\t\tgoldenrod3\n139 105  20\t\tgoldenrod4\n128 128 128\t\tgray\n  3   3   3\t\tgray1\n  5   5   5\t\tgray2\n  8   8   8\t\tgray3\n 10  10  10\t\tgray4\n 13  13  13\t\tgray5\n 15  15  15\t\tgray6\n 18  18  18\t\tgray7\n 20  20  20\t\tgray8\n 23  23  23\t\tgray9\n 26  26  26\t\tgray10\n 28  28  28\t\tgray11\n 31  31  31\t\tgray12\n 33  33  33\t\tgray13\n 36  36  36\t\tgray14\n 38  38  38\t\tgray15\n 41  41  41\t\tgray16\n 43  43  43\t\tgray17\n 46  46  46\t\tgray18\n 48  48  48\t\tgray19\n 51  51  51\t\tgray20\n 54  54  54\t\tgray21\n 56  56  56\t\tgray22\n 59  59  59\t\tgray23\n 61  61  61\t\tgray24\n 64  64  64\t\tgray25\n 66  66  66\t\tgray26\n 69  69  69\t\tgray27\n 71  71  71\t\tgray28\n 74  74  74\t\tgray29\n 77  77  77\t\tgray30\n 79  79  79\t\tgray31\n 82  82  82\t\tgray32\n 84  84  84\t\tgray33\n 87  87  87\t\tgray34\n 89  89  89\t\tgray35\n 92  92  92\t\tgray36\n 94  94  94\t\tgray37\n 97  97  97\t\tgray38\n 99  99  99\t\tgray39\n102 102 102\t\tgray40\n105 105 105\t\tgray41\n107 107 107\t\tgray42\n110 110 110\t\tgray43\n112 112 112\t\tgray44\n115 115 115\t\tgray45\n117 117 117\t\tgray46\n120 120 120\t\tgray47\n122 122 122\t\tgray48\n125 125 125\t\tgray49\n127 127 127\t\tgray50\n130 130 130\t\tgray51\n133 133 133\t\tgray52\n135 135 135\t\tgray53\n138 138 138\t\tgray54\n140 140 140\t\tgray55\n143 143 143\t\tgray56\n145 145 145\t\tgray57\n148 148 148\t\tgray58\n150 150 150\t\tgray59\n153 153 153\t\tgray60\n156 156 156\t\tgray61\n158 158 158\t\tgray62\n161 161 161\t\tgray63\n163 163 163\t\tgray64\n166 166 166\t\tgray65\n168 168 168\t\tgray66\n171 171 171\t\tgray67\n173 173 173\t\tgray68\n176 176 176\t\tgray69\n179 179 179\t\tgray70\n181 181 181\t\tgray71\n184 184 184\t\tgray72\n186 186 186\t\tgray73\n189 189 189\t\tgray74\n191 191 191\t\tgray75\n194 194 194\t\tgray76\n196 196 196\t\tgray77\n199 199 199\t\tgray78\n201 201 201\t\tgray79\n204 204 204\t\tgray80\n207 207 207\t\tgray81\n209 209 209\t\tgray82\n212 212 212\t\tgray83\n214 214 214\t\tgray84\n217 217 217\t\tgray85\n219 219 219\t\tgray86\n222 222 222\t\tgray87\n224 224 224\t\tgray88\n227 227 227\t\tgray89\n229 229 229\t\tgray90\n232 232 232\t\tgray91\n235 235 235\t\tgray92\n237 237 237\t\tgray93\n240 240 240\t\tgray94\n242 242 242\t\tgray95\n245 245 245\t\tgray96\n247 247 247\t\tgray97\n250 250 250\t\tgray98\n252 252 252\t\tgray99\n255 255 255\t\tgray100\n  0   0   0\t\tgray0\n  0 128   0\t\tgreen\n  0 255   0\t\tgreen1\n  0 238   0\t\tgreen2\n  0 205   0\t\tgreen3\n  0 139   0\t\tgreen4\n173 255  47\t\tgreenYellow\n128 128 128\t\tgrey\n  3   3   3\t\tgrey1\n  5   5   5\t\tgrey2\n  8   8   8\t\tgrey3\n 10  10  10\t\tgrey4\n 13  13  13\t\tgrey5\n 15  15  15\t\tgrey6\n 18  18  18\t\tgrey7\n 20  20  20\t\tgrey8\n 23  23  23\t\tgrey9\n 26  26  26\t\tgrey10\n 28  28  28\t\tgrey11\n 31  31  31\t\tgrey12\n 33  33  33\t\tgrey13\n 36  36  36\t\tgrey14\n 38  38  38\t\tgrey15\n 41  41  41\t\tgrey16\n 43  43  43\t\tgrey17\n 46  46  46\t\tgrey18\n 48  48  48\t\tgrey19\n 51  51  51\t\tgrey20\n 54  54  54\t\tgrey21\n 56  56  56\t\tgrey22\n 59  59  59\t\tgrey23\n 61  61  61\t\tgrey24\n 64  64  64\t\tgrey25\n 66  66  66\t\tgrey26\n 69  69  69\t\tgrey27\n 71  71  71\t\tgrey28\n 74  74  74\t\tgrey29\n 77  77  77\t\tgrey30\n 79  79  79\t\tgrey31\n 82  82  82\t\tgrey32\n 84  84  84\t\tgrey33\n 87  87  87\t\tgrey34\n 89  89  89\t\tgrey35\n 92  92  92\t\tgrey36\n 94  94  94\t\tgrey37\n 97  97  97\t\tgrey38\n 99  99  99\t\tgrey39\n102 102 102\t\tgrey40\n105 105 105\t\tgrey41\n107 107 107\t\tgrey42\n110 110 110\t\tgrey43\n112 112 112\t\tgrey44\n115 115 115\t\tgrey45\n117 117 117\t\tgrey46\n120 120 120\t\tgrey47\n122 122 122\t\tgrey48\n125 125 125\t\tgrey49\n127 127 127\t\tgrey50\n130 130 130\t\tgrey51\n133 133 133\t\tgrey52\n135 135 135\t\tgrey53\n138 138 138\t\tgrey54\n140 140 140\t\tgrey55\n143 143 143\t\tgrey56\n145 145 145\t\tgrey57\n148 148 148\t\tgrey58\n150 150 150\t\tgrey59\n153 153 153\t\tgrey60\n156 156 156\t\tgrey61\n158 158 158\t\tgrey62\n161 161 161\t\tgrey63\n163 163 163\t\tgrey64\n166 166 166\t\tgrey65\n168 168 168\t\tgrey66\n171 171 171\t\tgrey67\n173 173 173\t\tgrey68\n176 176 176\t\tgrey69\n179 179 179\t\tgrey70\n181 181 181\t\tgrey71\n184 184 184\t\tgrey72\n186 186 186\t\tgrey73\n189 189 189\t\tgrey74\n191 191 191\t\tgrey75\n194 194 194\t\tgrey76\n196 196 196\t\tgrey77\n199 199 199\t\tgrey78\n201 201 201\t\tgrey79\n204 204 204\t\tgrey80\n207 207 207\t\tgrey81\n209 209 209\t\tgrey82\n212 212 212\t\tgrey83\n214 214 214\t\tgrey84\n217 217 217\t\tgrey85\n219 219 219\t\tgrey86\n222 222 222\t\tgrey87\n224 224 224\t\tgrey88\n227 227 227\t\tgrey89\n229 229 229\t\tgrey90\n232 232 232\t\tgrey91\n235 235 235\t\tgrey92\n237 237 237\t\tgrey93\n240 240 240\t\tgrey94\n242 242 242\t\tgrey95\n245 245 245\t\tgrey96\n247 247 247\t\tgrey97\n250 250 250\t\tgrey98\n252 252 252\t\tgrey99\n255 255 255\t\tgrey100\n  0   0   0\t\tgrey0\n240 255 240\t\thoneydew\n240 255 240\t\thoneydew1\n224 238 224\t\thoneydew2\n193 205 193\t\thoneydew3\n131 139 131\t\thoneydew4\n255 105 180\t\thotPink\n255 110 180\t\thotPink1\n238 106 167\t\thotPink2\n205  96 144\t\thotPink3\n139  58  98\t\thotPink4\n205  92  92\t\tindianRed\n255 106 106\t\tindianRed1\n238  99  99\t\tindianRed2\n205  85  85\t\tindianRed3\n139  58  58\t\tindianRed4\n 75   0 130\t\tindigo\n255 255 240\t\tivory\n255 255 240\t\tivory1\n238 238 224\t\tivory2\n205 205 193\t\tivory3\n139 139 131\t\tivory4\n240 230 140\t\tkhaki\n255 246 143\t\tkhaki1\n238 230 133\t\tkhaki2\n205 198 115\t\tkhaki3\n139 134  78\t\tkhaki4\n230 230 250\t\tlavender\n255 240 245\t\tlavenderBlush\n255 240 245\t\tlavenderBlush1\n238 224 229\t\tlavenderBlush2\n205 193 197\t\tlavenderBlush3\n139 131 134\t\tlavenderBlush4\n124 252   0\t\tlawnGreen\n255 250 205\t\tlemonChiffon\n255 250 205\t\tlemonChiffon1\n238 233 191\t\tlemonChiffon2\n205 201 165\t\tlemonChiffon3\n139 137 112\t\tlemonChiffon4\n173 216 230\t\tlightBlue\n191 239 255\t\tlightBlue1\n178 223 238\t\tlightBlue2\n154 192 205\t\tlightBlue3\n104 131 139\t\tlightBlue4\n240 128 128\t\tlightCoral\n224 255 255\t\tlightCyan\n224 255 255\t\tlightCyan1\n209 238 238\t\tlightCyan2\n180 205 205\t\tlightCyan3\n122 139 139\t\tlightCyan4\n238 221 130\t\tlightGoldenrod\n255 236 139\t\tlightGoldenrod1\n238 220 130\t\tlightGoldenrod2\n205 190 112\t\tlightGoldenrod3\n139 129  76\t\tlightGoldenrod4\n250 250 210\t\tlightGoldenrodYellow\n211 211 211\t\tlightGray\n144 238 144\t\tlightGreen\n211 211 211\t\tlightGrey\n255 182 193\t\tlightPink\n255 174 185\t\tlightPink1\n238 162 173\t\tlightPink2\n205 140 149\t\tlightPink3\n139  95 101\t\tlightPink4\n255 160 122\t\tlightSalmon\n255 160 122\t\tlightSalmon1\n238 149 114\t\tlightSalmon2\n205 129  98\t\tlightSalmon3\n139  87  66\t\tlightSalmon4\n 32 178 170\t\tlightSeaGreen\n135 206 250\t\tlightSkyBlue\n176 226 255\t\tlightSkyBlue1\n164 211 238\t\tlightSkyBlue2\n141 182 205\t\tlightSkyBlue3\n 96 123 139\t\tlightSkyBlue4\n132 112 255\t\tlightSlateBlue\n119 136 153\t\tlightSlateGray\n119 136 153\t\tlightSlateGrey\n176 196 222\t\tlightSteelBlue\n202 225 255\t\tlightSteelBlue1\n188 210 238\t\tlightSteelBlue2\n162 181 205\t\tlightSteelBlue3\n110 123 139\t\tlightSteelBlue4\n255 255 224\t\tlightYellow\n255 255 224\t\tlightYellow1\n238 238 209\t\tlightYellow2\n205 205 180\t\tlightYellow3\n139 139 122\t\tlightYellow4\n  0 255   0\t\tlime\n 50 205  50\t\tlimeGreen\n250 240 230\t\tlinen\n255   0 255\t\tmagenta\n255   0 255\t\tmagenta1\n238   0 238\t\tmagenta2\n205   0 205\t\tmagenta3\n139   0 139\t\tmagenta4\n128   0   0\t\tmaroon\n255  52 179\t\tmaroon1\n238  48 167\t\tmaroon2\n205  41 144\t\tmaroon3\n139  28  98\t\tmaroon4\n102 205 170\t\tmediumAquamarine\n  0   0 205\t\tmediumBlue\n186  85 211\t\tmediumOrchid\n224 102 255\t\tmediumOrchid1\n209  95 238\t\tmediumOrchid2\n180  82 205\t\tmediumOrchid3\n122  55 139\t\tmediumOrchid4\n147 112 219\t\tmediumPurple\n171 130 255\t\tmediumPurple1\n159 121 238\t\tmediumPurple2\n137 104 205\t\tmediumPurple3\n 93  71 139\t\tmediumPurple4\n 60 179 113\t\tmediumSeaGreen\n123 104 238\t\tmediumSlateBlue\n  0 250 154\t\tmediumSpringGreen\n 72 209 204\t\tmediumTurquoise\n199  21 133\t\tmediumVioletRed\n 25  25 112\t\tmidnightBlue\n245 255 250\t\tmintCream\n255 228 225\t\tmistyRose\n255 228 225\t\tmistyRose1\n238 213 210\t\tmistyRose2\n205 183 181\t\tmistyRose3\n139 125 123\t\tmistyRose4\n255 228 181\t\tmoccasin\n255 222 173\t\tnavajoWhite\n255 222 173\t\tnavajoWhite1\n238 207 161\t\tnavajoWhite2\n205 179 139\t\tnavajoWhite3\n139 121  94\t\tnavajoWhite4\n  0   0 128\t\tnavy\n  0   0 128\t\tnavyBlue\n253 245 230\t\toldLace\n128 128   0\t\tolive\n107 142  35\t\toliveDrab\n192 255  62\t\toliveDrab1\n179 238  58\t\toliveDrab2\n154 205  50\t\toliveDrab3\n105 139  34\t\toliveDrab4\n255 165   0\t\torange\n255 165   0\t\torange1\n238 154   0\t\torange2\n205 133   0\t\torange3\n139  90   0\t\torange4\n255  69   0\t\torangeRed\n255  69   0\t\torangeRed1\n238  64   0\t\torangeRed2\n205  55   0\t\torangeRed3\n139  37   0\t\torangeRed4\n218 112 214\t\torchid\n255 131 250\t\torchid1\n238 122 233\t\torchid2\n205 105 201\t\torchid3\n139  71 137\t\torchid4\n238 232 170\t\tpaleGoldenrod\n152 251 152\t\tpaleGreen\n154 255 154\t\tpaleGreen1\n144 238 144\t\tpaleGreen2\n124 205 124\t\tpaleGreen3\n 84 139  84\t\tpaleGreen4\n175 238 238\t\tpaleTurquoise\n187 255 255\t\tpaleTurquoise1\n174 238 238\t\tpaleTurquoise2\n150 205 205\t\tpaleTurquoise3\n102 139 139\t\tpaleTurquoise4\n219 112 147\t\tpaleVioletRed\n255 130 171\t\tpaleVioletRed1\n238 121 159\t\tpaleVioletRed2\n205 104 137\t\tpaleVioletRed3\n139  71  93\t\tpaleVioletRed4\n255 239 213\t\tpapayaWhip\n255 218 185\t\tpeachPuff\n255 218 185\t\tpeachPuff1\n238 203 173\t\tpeachPuff2\n205 175 149\t\tpeachPuff3\n139 119 101\t\tpeachPuff4\n205 133  63\t\tperu\n255 192 203\t\tpink\n255 181 197\t\tpink1\n238 169 184\t\tpink2\n205 145 158\t\tpink3\n139  99 108\t\tpink4\n221 160 221\t\tplum\n255 187 255\t\tplum1\n238 174 238\t\tplum2\n205 150 205\t\tplum3\n139 102 139\t\tplum4\n176 224 230\t\tpowderBlue\n128   0 128\t\tpurple\n155  48 255\t\tpurple1\n145  44 238\t\tpurple2\n125  38 205\t\tpurple3\n 85  26 139\t\tpurple4\n255   0   0\t\tred\n255   0   0\t\tred1\n238   0   0\t\tred2\n205   0   0\t\tred3\n139   0   0\t\tred4\n188 143 143\t\trosyBrown\n255 193 193\t\trosyBrown1\n238 180 180\t\trosyBrown2\n205 155 155\t\trosyBrown3\n139 105 105\t\trosyBrown4\n 65 105 225\t\troyalBlue\n 72 118 255\t\troyalBlue1\n 67 110 238\t\troyalBlue2\n 58  95 205\t\troyalBlue3\n 39  64 139\t\troyalBlue4\n139  69  19\t\tsaddleBrown\n250 128 114\t\tsalmon\n255 140 105\t\tsalmon1\n238 130  98\t\tsalmon2\n205 112  84\t\tsalmon3\n139  76  57\t\tsalmon4\n244 164  96\t\tsandyBrown\n 46 139  87\t\tseaGreen\n 84 255 159\t\tseaGreen1\n 78 238 148\t\tseaGreen2\n 67 205 128\t\tseaGreen3\n 46 139  87\t\tseaGreen4\n255 245 238\t\tseashell\n255 245 238\t\tseashell1\n238 229 222\t\tseashell2\n205 197 191\t\tseashell3\n139 134 130\t\tseashell4\n160  82  45\t\tsienna\n255 130  71\t\tsienna1\n238 121  66\t\tsienna2\n205 104  57\t\tsienna3\n139  71  38\t\tsienna4\n192 192 192\t\tsilver\n135 206 235\t\tskyBlue\n135 206 255\t\tskyBlue1\n126 192 238\t\tskyBlue2\n108 166 205\t\tskyBlue3\n 74 112 139\t\tskyBlue4\n106  90 205\t\tslateBlue\n131 111 255\t\tslateBlue1\n122 103 238\t\tslateBlue2\n105  89 205\t\tslateBlue3\n 71  60 139\t\tslateBlue4\n112 128 144\t\tslateGray\n198 226 255\t\tslateGray1\n185 211 238\t\tslateGray2\n159 182 205\t\tslateGray3\n108 123 139\t\tslateGray4\n112 128 144\t\tslateGrey\n255 250 250\t\tsnow\n255 250 250\t\tsnow1\n238 233 233\t\tsnow2\n205 201 201\t\tsnow3\n139 137 137\t\tsnow4\n  0 255 127\t\tspringGreen\n  0 255 127\t\tspringGreen1\n  0 238 118\t\tspringGreen2\n  0 205 102\t\tspringGreen3\n  0 139  69\t\tspringGreen4\n 70 130 180\t\tsteelBlue\n 99 184 255\t\tsteelBlue1\n 92 172 238\t\tsteelBlue2\n 79 148 205\t\tsteelBlue3\n 54 100 139\t\tsteelBlue4\n210 180 140\t\ttan\n255 165  79\t\ttan1\n238 154  73\t\ttan2\n205 133  63\t\ttan3\n139  90  43\t\ttan4\n  0 128 128\t\tteal\n216 191 216\t\tthistle\n255 225 255\t\tthistle1\n238 210 238\t\tthistle2\n205 181 205\t\tthistle3\n139 123 139\t\tthistle4\n255  99  71\t\ttomato\n255  99  71\t\ttomato1\n238  92  66\t\ttomato2\n205  79  57\t\ttomato3\n139  54  38\t\ttomato4\n 64 224 208\t\tturquoise\n  0 245 255\t\tturquoise1\n  0 229 238\t\tturquoise2\n  0 197 205\t\tturquoise3\n  0 134 139\t\tturquoise4\n238 130 238\t\tviolet\n208  32 144\t\tvioletRed\n255  62 150\t\tvioletRed1\n238  58 140\t\tvioletRed2\n205  50 120\t\tvioletRed3\n139  34  82\t\tvioletRed4\n245 222 179\t\twheat\n255 231 186\t\twheat1\n238 216 174\t\twheat2\n205 186 150\t\twheat3\n139 126 102\t\twheat4\n255 255 255\t\twhite\n245 245 245\t\twhiteSmoke\n255 255   0\t\tyellow\n255 255   0\t\tyellow1\n238 238   0\t\tyellow2\n205 205   0\t\tyellow3\n139 139   0\t\tyellow4\n154 205  50\t\tyellowGreen\n"
  },
  {
    "path": "xlib/xbytes.h",
    "content": "/*\n * xbytes.h --\n *\n *\tDeclaration of table to reverse bit order of bytes.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#ifndef _XBYTES\n#define _XBYTES\n\n/*\n * The bits in a byte can be reversed so the least significant becomes the\n * most significant by indexing xBitReverseTable with the byte to be reversed.\n */\n\nstatic unsigned char xBitReverseTable[256] = {\n    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,\n    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,\n    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,\n    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,\n    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,\n    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,\n    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,\n    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,\n    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,\n    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,\n    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,\n    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,\n    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,\n    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,\n    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,\n    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,\n    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,\n    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,\n    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,\n    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,\n    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,\n    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,\n    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,\n    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,\n    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,\n    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,\n    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,\n    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,\n    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,\n    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,\n    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,\n    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,\n};\n\n#endif /* _XBYTES */\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "xlib/xcolors.c",
    "content": "/*\n * xcolors.c --\n *\n *\tThis file contains the routines used to map from X color names to RGB\n *\tand pixel values.\n *\n * Copyright © 1996 Sun Microsystems, Inc.\n * Copyright © 2012 Jan Nijtmans\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\n/*\n * Index array. For each of the characters 'a'-'y', this table gives the first\n * color starting with that character in the xColors table.\n */\n\nstatic const unsigned char az[] = {\n    0, 5, 13, 21, 45, 46, 50, 60, 62, 65, 66,\n    67, 91, 106, 109, 115, 126, 127, 130, 144, 149, 150, 152, 155, 156, 158\n};\n\n/*\n * Define an array that defines the mapping from color names to RGB values.\n * Note that this array must be kept sorted alphabetically so that the\n * binary search used in XParseColor will succeed.\n *\n * Each color definition consists of exactly 32 characters, and starts with\n * the color name, but without its first character (that character can be\n * reproduced from the az index array). The last byte holds the number\n * of additional color variants. For example \"azure1\" up to \"azure4\" are\n * handled by the same table entry as \"azure\". From the last byte backwards,\n * each group of 3 bytes contain the rgb values of the main color and\n * the available variants.\n *\n * The colors gray and grey have more than 8 variants. gray1 up to gray8\n * are handled by this table, above that is handled especially.\n */\n\ntypedef unsigned char elem[32];\n\nstatic const elem xColors[] = {\n    /* Colors starting with 'a' */\n    {'l', 'i', 'c', 'e', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF0, 0xF8, 0xFF, 0x00},\n    {'n', 't', 'i', 'q', 'u', 'e', 'W', 'h', 'i', 't', 'e', 0, 0, 0, 0, 0,\n\t    0x8B, 0x83, 0x78, 0xCD, 0xC0, 0xB0, 0xEE, 0xDF, 0xCC, 0xFF, 0xEF, 0xDB, 0xFA, 0xEB, 0xD7, 0x04},\n    {'q', 'u', 'a', 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,\n\t    0x00, 0xFF, 0xFF, 0x00},\n    {'q', 'u', 'a', 'm', 'a', 'r', 'i', 'n', 'e', 0, 0, 0, 0, 0, 0, 0,\n\t    0x45, 0x8B, 0x74, 0x66, 0xCD, 0xAA, 0x76, 0xEE, 0xC6, 0x7F, 0xFF, 0xD4, 0x7F, 0xFF, 0xD4, 0x04},\n    {'z', 'u', 'r', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x83, 0x8B, 0x8B, 0xC1, 0xCD, 0xCD, 0xE0, 0xEE, 0xEE, 0xF0, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x04},\n    /* Colors starting with 'b' */\n    {'e', 'i', 'g', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF5, 0xF5, 0xDC, 0x00},\n    {'i', 's', 'q', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x7D, 0x6B, 0xCD, 0xB7, 0x9E, 0xEE, 0xD5, 0xB7, 0xFF, 0xE4, 0xC4, 0xFF, 0xE4, 0xC4, 0x04},\n    {'l', 'a', 'c', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x00, 0x00, 0x00},\n    {'l', 'a', 'n', 'c', 'h', 'e', 'd', 'A', 'l', 'm', 'o', 'n', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0xEB, 0xCD, 0x00},\n    {'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x00, 0x8B, 0x00, 0x00, 0xCD, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x04},\n    {'l', 'u', 'e', 'V', 'i', 'o', 'l', 'e', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8A, 0x2B, 0xE2, 0x00},\n    {'r', 'o', 'w', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x23, 0x23, 0xCD, 0x33, 0x33, 0xEE, 0x3B, 0x3B, 0xFF, 0x40, 0x40, 0xA5, 0x2A, 0x2A, 0x04},\n    {'u', 'r', 'l', 'y', 'w', 'o', 'o', 'd', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x73, 0x55, 0xCD, 0xAA, 0x7D, 0xEE, 0xC5, 0x91, 0xFF, 0xD3, 0x9B, 0xDE, 0xB8, 0x87, 0x04},\n    /* Colors starting with 'c' */\n    {'a', 'd', 'e', 't', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x53, 0x86, 0x8B, 0x7A, 0xC5, 0xCD, 0x8E, 0xE5, 0xEE, 0x98, 0xF5, 0xFF, 0x5F, 0x9E, 0xA0, 0x04},\n    {'h', 'a', 'r', 't', 'r', 'e', 'u', 's', 'e', 0, 0, 0, 0, 0, 0, 0,\n\t    0x45, 0x8B, 0x00, 0x66, 0xCD, 0x00, 0x76, 0xEE, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x04},\n    {'h', 'o', 'c', 'o', 'l', 'a', 't', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x45, 0x13, 0xCD, 0x66, 0x1D, 0xEE, 0x76, 0x21, 0xFF, 0x7F, 0x24, 0xD2, 0x69, 0x1E, 0x04},\n    {'o', 'r', 'a', 'l', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x3E, 0x2F, 0xCD, 0x5B, 0x45, 0xEE, 0x6A, 0x50, 0xFF, 0x72, 0x56, 0xFF, 0x7F, 0x50, 0x04},\n    {'o', 'r', 'n', 'f', 'l', 'o', 'w', 'e', 'r', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x64, 0x95, 0xED, 0x00},\n    {'o', 'r', 'n', 's', 'i', 'l', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x88, 0x78, 0xCD, 0xC8, 0xB1, 0xEE, 0xE8, 0xCD, 0xFF, 0xF8, 0xDC, 0xFF, 0xF8, 0xDC, 0x04},\n    {'r', 'i', 'm', 's', 'o', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xDC, 0x14, 0x3C, 0x00},\n    {'y', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x8B, 0x8B, 0x00, 0xCD, 0xCD, 0x00, 0xEE, 0xEE, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x04},\n    /* Colors starting with 'd' */\n    {'a', 'r', 'k', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x00, 0x8B, 0x00},\n    {'a', 'r', 'k', 'C', 'y', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x8B, 0x8B, 0x00},\n    {'a', 'r', 'k', 'G', 'o', 'l', 'd', 'e', 'n', 'r', 'o', 'd', 0, 0, 0, 0,\n\t    0x8B, 0x65, 0x08, 0xCD, 0x95, 0x0C, 0xEE, 0xAD, 0x0E, 0xFF, 0xB9, 0x0F, 0xB8, 0x86, 0x0B, 0x04},\n    {'a', 'r', 'k', 'G', 'r', 'a', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xA9, 0xA9, 0xA9, 0x00},\n    {'a', 'r', 'k', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x64, 0x00, 0x00},\n    {'a', 'r', 'k', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xA9, 0xA9, 0xA9, 0x00},\n    {'a', 'r', 'k', 'K', 'h', 'a', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xBD, 0xB7, 0x6B, 0x00},\n    {'a', 'r', 'k', 'M', 'a', 'g', 'e', 'n', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x00, 0x8B, 0x00},\n    {'a', 'r', 'k', 'O', 'l', 'i', 'v', 'e', 'G', 'r', 'e', 'e', 'n', 0, 0, 0,\n\t    0x6E, 0x8B, 0x3D, 0xA2, 0xCD, 0x5A, 0xBC, 0xEE, 0x68, 0xCA, 0xFF, 0x70, 0x55, 0x6B, 0x2F, 0x04},\n    {'a', 'r', 'k', 'O', 'r', 'a', 'n', 'g', 'e', 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x45, 0x00, 0xCD, 0x66, 0x00, 0xEE, 0x76, 0x00, 0xFF, 0x7F, 0x00, 0xFF, 0x8C, 0x00, 0x04},\n    {'a', 'r', 'k', 'O', 'r', 'c', 'h', 'i', 'd', 0, 0, 0, 0, 0, 0, 0,\n\t    0x68, 0x22, 0x8B, 0x9A, 0x32, 0xCD, 0xB2, 0x3A, 0xEE, 0xBF, 0x3E, 0xFF, 0x99, 0x32, 0xCC, 0x04},\n    {'a', 'r', 'k', 'R', 'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x00, 0x00, 0x00},\n    {'a', 'r', 'k', 'S', 'a', 'l', 'm', 'o', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xE9, 0x96, 0x7A, 0x00},\n    {'a', 'r', 'k', 'S', 'e', 'a', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0,\n\t    0x69, 0x8B, 0x69, 0x9B, 0xCD, 0x9B, 0xB4, 0xEE, 0xB4, 0xC1, 0xFF, 0xC1, 0x8F, 0xBC, 0x8F, 0x04},\n    {'a', 'r', 'k', 'S', 'l', 'a', 't', 'e', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x48, 0x3D, 0x8B, 0x00},\n    {'a', 'r', 'k', 'S', 'l', 'a', 't', 'e', 'G', 'r', 'a', 'y', 0, 0, 0, 0,\n\t    0x52, 0x8B, 0x8B, 0x79, 0xCD, 0xCD, 0x8D, 0xEE, 0xEE, 0x97, 0xFF, 0xFF, 0x2F, 0x4F, 0x4F, 0x04},\n    {'a', 'r', 'k', 'S', 'l', 'a', 't', 'e', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x2F, 0x4F, 0x4F, 0x00},\n    {'a', 'r', 'k', 'T', 'u', 'r', 'q', 'u', 'o', 'i', 's', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0xCE, 0xD1, 0x00},\n    {'a', 'r', 'k', 'V', 'i', 'o', 'l', 'e', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x94, 0x00, 0xD3, 0x00},\n    {'e', 'e', 'p', 'P', 'i', 'n', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x0A, 0x50, 0xCD, 0x10, 0x76, 0xEE, 0x12, 0x89, 0xFF, 0x14, 0x93, 0xFF, 0x14, 0x93, 0x04},\n    {'e', 'e', 'p', 'S', 'k', 'y', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x68, 0x8B, 0x00, 0x9A, 0xCD, 0x00, 0xB2, 0xEE, 0x00, 0xBF, 0xFF, 0x00, 0xBF, 0xFF, 0x04},\n    {'i', 'm', 'G', 'r', 'a', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x69, 0x69, 0x69, 0x00},\n    {'i', 'm', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x69, 0x69, 0x69, 0x00},\n    {'o', 'd', 'g', 'e', 'r', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0,\n\t    0x10, 0x4E, 0x8B, 0x18, 0x74, 0xCD, 0x1C, 0x86, 0xEE, 0x1E, 0x90, 0xFF, 0x1E, 0x90, 0xFF, 0x04},\n    /* Colors starting with 'e' (placeholder) */\n    {0xFF, 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},\n    /* Colors starting with 'f' */\n    {'i', 'r', 'e', 'b', 'r', 'i', 'c', 'k', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x1A, 0x1A, 0xCD, 0x26, 0x26, 0xEE, 0x2C, 0x2C, 0xFF, 0x30, 0x30, 0xB2, 0x22, 0x22, 0x04},\n    {'l', 'o', 'r', 'a', 'l', 'W', 'h', 'i', 't', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0xFA, 0xF0, 0x00},\n    {'o', 'r', 'e', 's', 't', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x22, 0x8B, 0x22, 0x00},\n    {'u', 'c', 'h', 's', 'i', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0x00, 0xFF, 0x00},\n    /* Colors starting with 'g' */\n    {'a', 'i', 'n', 's', 'b', 'o', 'r', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xDC, 0xDC, 0xDC, 0x00},\n    {'h', 'o', 's', 't', 'W', 'h', 'i', 't', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF8, 0xF8, 0xFF, 0x00},\n    {'o', 'l', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x75, 0x00, 0xCD, 0xAD, 0x00, 0xEE, 0xC9, 0x00, 0xFF, 0xD7, 0x00, 0xFF, 0xD7, 0x00, 0x04},\n    {'o', 'l', 'd', 'e', 'n', 'r', 'o', 'd', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x69, 0x14, 0xCD, 0x9B, 0x1D, 0xEE, 0xB4, 0x22, 0xFF, 0xC1, 0x25, 0xDA, 0xA5, 0x20, 0x04},\n    {'r', 'a', 'y', 0,\n\t    0x14, 0x14, 0x14, 0x12, 0x12, 0x12, 0x0F, 0x0F, 0x0F, 0x0D, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x05, 0x05, 0x05, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, 0x08},\n    {'r', 'a', 'y', '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,\n\t    0x00, 0x00, 0x00, 0x00},\n    {'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x8B, 0x00, 0x00, 0xCD, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x80, 0x00, 0x04},\n    {'r', 'e', 'e', 'n', 'Y', 'e', 'l', 'l', 'o', 'w', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xAD, 0xFF, 0x2F, 0x00},\n    {'r', 'e', 'y', 0,\n\t    0x14, 0x14, 0x14, 0x12, 0x12, 0x12, 0x0F, 0x0F, 0x0F, 0x0D, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x05, 0x05, 0x05, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, 0x08},\n    {'r', 'e', 'y', '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,\n\t    0x00, 0x00, 0x00, 0x00},\n    /* Colors starting with 'h' */\n    {'o', 'n', 'e', 'y', 'd', 'e', 'w', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x83, 0x8B, 0x83, 0xC1, 0xCD, 0xC1, 0xE0, 0xEE, 0xE0, 0xF0, 0xFF, 0xF0, 0xF0, 0xFF, 0xF0, 0x04},\n    {'o', 't', 'P', 'i', 'n', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x3A, 0x62, 0xCD, 0x60, 0x90, 0xEE, 0x6A, 0xA7, 0xFF, 0x6E, 0xB4, 0xFF, 0x69, 0xB4, 0x04},\n    /* Colors starting with 'i' */\n    {'n', 'd', 'i', 'a', 'n', 'R', 'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x3A, 0x3A, 0xCD, 0x55, 0x55, 0xEE, 0x63, 0x63, 0xFF, 0x6A, 0x6A, 0xCD, 0x5C, 0x5C, 0x04},\n    {'n', 'd', 'i', 'g', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x4B, 0x00, 0x82, 0x00},\n    {'v', 'o', 'r', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x8B, 0x83, 0xCD, 0xCD, 0xC1, 0xEE, 0xEE, 0xE0, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xF0, 0x04},\n    /* Colors starting with 'j' (placeholder) */\n    {0xFF, 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},\n    /* Colors starting with 'k' */\n    {'h', 'a', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x86, 0x4E, 0xCD, 0xC6, 0x73, 0xEE, 0xE6, 0x85, 0xFF, 0xF6, 0x8F, 0xF0, 0xE6, 0x8C, 0x04},\n    /* Colors starting with 'l' */\n    {'a', 'v', 'e', 'n', 'd', 'e', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xE6, 0xE6, 0xFA, 0x00},\n    {'a', 'v', 'e', 'n', 'd', 'e', 'r', 'B', 'l', 'u', 's', 'h', 0, 0, 0, 0,\n\t    0x8B, 0x83, 0x86, 0xCD, 0xC1, 0xC5, 0xEE, 0xE0, 0xE5, 0xFF, 0xF0, 0xF5, 0xFF, 0xF0, 0xF5, 0x04},\n    {'a', 'w', 'n', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x7C, 0xFC, 0x00, 0x00},\n    {'e', 'm', 'o', 'n', 'C', 'h', 'i', 'f', 'f', 'o', 'n', 0, 0, 0, 0, 0,\n\t    0x8B, 0x89, 0x70, 0xCD, 0xC9, 0xA5, 0xEE, 0xE9, 0xBF, 0xFF, 0xFA, 0xCD, 0xFF, 0xFA, 0xCD, 0x04},\n    {'i', 'g', 'h', 't', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x68, 0x83, 0x8B, 0x9A, 0xC0, 0xCD, 0xB2, 0xDF, 0xEE, 0xBF, 0xEF, 0xFF, 0xAD, 0xD8, 0xE6, 0x04},\n    {'i', 'g', 'h', 't', 'C', 'o', 'r', 'a', 'l', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF0, 0x80, 0x80, 0x00},\n    {'i', 'g', 'h', 't', 'C', 'y', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x7A, 0x8B, 0x8B, 0xB4, 0xCD, 0xCD, 0xD1, 0xEE, 0xEE, 0xE0, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x04},\n    {'i', 'g', 'h', 't', 'G', 'o', 'l', 'd', 'e', 'n', 'r', 'o', 'd', 0, 0, 0,\n\t    0x8B, 0x81, 0x4C, 0xCD, 0xBE, 0x70, 0xEE, 0xDC, 0x82, 0xFF, 0xEC, 0x8B, 0xEE, 0xDD, 0x82, 0x04},\n    {'i', 'g', 'h', 't', 'G', 'o', 'l', 'd', 'e', 'n', 'r', 'o', 'd', 'Y', 'e', 'l', 'l', 'o', 'w', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFA, 0xFA, 0xD2, 0x00},\n    {'i', 'g', 'h', 't', 'G', 'r', 'a', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xD3, 0xD3, 0xD3, 0x00},\n    {'i', 'g', 'h', 't', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x90, 0xEE, 0x90, 0x00},\n    {'i', 'g', 'h', 't', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xD3, 0xD3, 0xD3, 0x00},\n    {'i', 'g', 'h', 't', 'P', 'i', 'n', 'k', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x5F, 0x65, 0xCD, 0x8C, 0x95, 0xEE, 0xA2, 0xAD, 0xFF, 0xAE, 0xB9, 0xFF, 0xB6, 0xC1, 0x04},\n    {'i', 'g', 'h', 't', 'S', 'a', 'l', 'm', 'o', 'n', 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x57, 0x42, 0xCD, 0x81, 0x62, 0xEE, 0x95, 0x72, 0xFF, 0xA0, 0x7A, 0xFF, 0xA0, 0x7A, 0x04},\n    {'i', 'g', 'h', 't', 'S', 'e', 'a', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x20, 0xB2, 0xAA, 0x00},\n    {'i', 'g', 'h', 't', 'S', 'k', 'y', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0,\n\t    0x60, 0x7B, 0x8B, 0x8D, 0xB6, 0xCD, 0xA4, 0xD3, 0xEE, 0xB0, 0xE2, 0xFF, 0x87, 0xCE, 0xFA, 0x04},\n    {'i', 'g', 'h', 't', 'S', 'l', 'a', 't', 'e', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x84, 0x70, 0xFF, 0x00},\n    {'i', 'g', 'h', 't', 'S', 'l', 'a', 't', 'e', 'G', 'r', 'a', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x77, 0x88, 0x99, 0x00},\n    {'i', 'g', 'h', 't', 'S', 'l', 'a', 't', 'e', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x77, 0x88, 0x99, 0x00},\n    {'i', 'g', 'h', 't', 'S', 't', 'e', 'e', 'l', 'B', 'l', 'u', 'e', 0, 0, 0,\n\t    0x6E, 0x7B, 0x8B, 0xA2, 0xB5, 0xCD, 0xBC, 0xD2, 0xEE, 0xCA, 0xE1, 0xFF, 0xB0, 0xC4, 0xDE, 0x04},\n    {'i', 'g', 'h', 't', 'Y', 'e', 'l', 'l', 'o', 'w', 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x8B, 0x7A, 0xCD, 0xCD, 0xB4, 0xEE, 0xEE, 0xD1, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xE0, 0x04},\n    {'i', 'm', 'e', 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,\n\t    0x00, 0xFF, 0x00, 0x00},\n    {'i', 'm', 'e', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x32, 0xCD, 0x32, 0x00},\n    {'i', 'n', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFA, 0xF0, 0xE6, 0x00},\n    /* Colors starting with 'm' */\n    {'a', 'g', 'e', 'n', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x00, 0x8B, 0xCD, 0x00, 0xCD, 0xEE, 0x00, 0xEE, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x04},\n    {'a', 'r', 'o', 'o', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x1C, 0x62, 0xCD, 0x29, 0x90, 0xEE, 0x30, 0xA7, 0xFF, 0x34, 0xB3, 0x80, 0x00, 0x00, 0x04},\n    {'e', 'd', 'i', 'u', 'm', 'A', 'q', 'u', 'a', 'm', 'a', 'r', 'i', 'n', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x66, 0xCD, 0xAA, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x00, 0xCD, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'O', 'r', 'c', 'h', 'i', 'd', 0, 0, 0, 0, 0,\n\t    0x7A, 0x37, 0x8B, 0xB4, 0x52, 0xCD, 0xD1, 0x5F, 0xEE, 0xE0, 0x66, 0xFF, 0xBA, 0x55, 0xD3, 0x04},\n    {'e', 'd', 'i', 'u', 'm', 'P', 'u', 'r', 'p', 'l', 'e', 0, 0, 0, 0, 0,\n\t    0x5D, 0x47, 0x8B, 0x89, 0x68, 0xCD, 0x9F, 0x79, 0xEE, 0xAB, 0x82, 0xFF, 0x93, 0x70, 0xDB, 0x04},\n    {'e', 'd', 'i', 'u', 'm', 'S', 'e', 'a', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x3C, 0xB3, 0x71, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'S', 'l', 'a', 't', 'e', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x7B, 0x68, 0xEE, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'S', 'p', 'r', 'i', 'n', 'g', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0xFA, 0x9A, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'T', 'u', 'r', 'q', 'u', 'o', 'i', 's', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x48, 0xD1, 0xCC, 0x00},\n    {'e', 'd', 'i', 'u', 'm', 'V', 'i', 'o', 'l', 'e', 't', 'R', 'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xC7, 0x15, 0x85, 0x00},\n    {'i', 'd', 'n', 'i', 'g', 'h', 't', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x19, 0x19, 0x70, 0x00},\n    {'i', 'n', 't', 'C', 'r', 'e', 'a', 'm', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF5, 0xFF, 0xFA, 0x00},\n    {'i', 's', 't', 'y', 'R', 'o', 's', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x7D, 0x7B, 0xCD, 0xB7, 0xB5, 0xEE, 0xD5, 0xD2, 0xFF, 0xE4, 0xE1, 0xFF, 0xE4, 0xE1, 0x04},\n    {'o', 'c', 'c', 'a', 's', 'i', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0xE4, 0xB5, 0x00},\n    /* Colors starting with 'n' */\n    {'a', 'v', 'a', 'j', 'o', 'W', 'h', 'i', 't', 'e', 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x79, 0x5E, 0xCD, 0xB3, 0x8B, 0xEE, 0xCF, 0xA1, 0xFF, 0xDE, 0xAD, 0xFF, 0xDE, 0xAD, 0x04},\n    {'a', 'v', 'y', 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,\n\t    0x00, 0x00, 0x80, 0x00},\n    {'a', 'v', 'y', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x00, 0x80, 0x00},\n    /* Colors starting with 'o' */\n    {'l', 'd', 'L', 'a', 'c', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFD, 0xF5, 0xE6, 0x00},\n    {'l', 'i', 'v', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x80, 0x80, 0x00, 0x00},\n    {'l', 'i', 'v', 'e', 'D', 'r', 'a', 'b', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x69, 0x8B, 0x22, 0x9A, 0xCD, 0x32, 0xB3, 0xEE, 0x3A, 0xC0, 0xFF, 0x3E, 0x6B, 0x8E, 0x23, 0x04},\n    {'r', 'a', 'n', 'g', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x5A, 0x00, 0xCD, 0x85, 0x00, 0xEE, 0x9A, 0x00, 0xFF, 0xA5, 0x00, 0xFF, 0xA5, 0x00, 0x04},\n    {'r', 'a', 'n', 'g', 'e', 'R', 'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x25, 0x00, 0xCD, 0x37, 0x00, 0xEE, 0x40, 0x00, 0xFF, 0x45, 0x00, 0xFF, 0x45, 0x00, 0x04},\n    {'r', 'c', 'h', 'i', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x47, 0x89, 0xCD, 0x69, 0xC9, 0xEE, 0x7A, 0xE9, 0xFF, 0x83, 0xFA, 0xDA, 0x70, 0xD6, 0x04},\n    /* Colors starting with 'p' */\n    {'a', 'l', 'e', 'G', 'o', 'l', 'd', 'e', 'n', 'r', 'o', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xEE, 0xE8, 0xAA, 0x00},\n    {'a', 'l', 'e', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x54, 0x8B, 0x54, 0x7C, 0xCD, 0x7C, 0x90, 0xEE, 0x90, 0x9A, 0xFF, 0x9A, 0x98, 0xFB, 0x98, 0x04},\n    {'a', 'l', 'e', 'T', 'u', 'r', 'q', 'u', 'o', 'i', 's', 'e', 0, 0, 0, 0,\n\t    0x66, 0x8B, 0x8B, 0x96, 0xCD, 0xCD, 0xAE, 0xEE, 0xEE, 0xBB, 0xFF, 0xFF, 0xAF, 0xEE, 0xEE, 0x04},\n    {'a', 'l', 'e', 'V', 'i', 'o', 'l', 'e', 't', 'R', 'e', 'd', 0, 0, 0, 0,\n\t    0x8B, 0x47, 0x5D, 0xCD, 0x68, 0x89, 0xEE, 0x79, 0x9F, 0xFF, 0x82, 0xAB, 0xDB, 0x70, 0x93, 0x04},\n    {'a', 'p', 'a', 'y', 'a', 'W', 'h', 'i', 'p', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0xEF, 0xD5, 0x00},\n    {'e', 'a', 'c', 'h', 'P', 'u', 'f', 'f', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x77, 0x65, 0xCD, 0xAF, 0x95, 0xEE, 0xCB, 0xAD, 0xFF, 0xDA, 0xB9, 0xFF, 0xDA, 0xB9, 0x04},\n    {'e', 'r', 'u', 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,\n\t    0xCD, 0x85, 0x3F, 0x00},\n    {'i', 'n', 'k', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x63, 0x6C, 0xCD, 0x91, 0x9E, 0xEE, 0xA9, 0xB8, 0xFF, 0xB5, 0xC5, 0xFF, 0xC0, 0xCB, 0x04},\n    {'l', 'u', 'm', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x66, 0x8B, 0xCD, 0x96, 0xCD, 0xEE, 0xAE, 0xEE, 0xFF, 0xBB, 0xFF, 0xDD, 0xA0, 0xDD, 0x04},\n    {'o', 'w', 'd', 'e', 'r', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xB0, 0xE0, 0xE6, 0x00},\n    {'u', 'r', 'p', 'l', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x55, 0x1A, 0x8B, 0x7D, 0x26, 0xCD, 0x91, 0x2C, 0xEE, 0x9B, 0x30, 0xFF, 0x80, 0x00, 0x80, 0x04},\n    /* Colors starting with 'q' (placeholder)*/\n    {0xFF, 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},\n    /* Colors starting with 'r' */\n    {'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x00, 0x00, 0xCD, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x04},\n    {'o', 's', 'y', 'B', 'r', 'o', 'w', 'n', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x69, 0x69, 0xCD, 0x9B, 0x9B, 0xEE, 0xB4, 0xB4, 0xFF, 0xC1, 0xC1, 0xBC, 0x8F, 0x8F, 0x04},\n    {'o', 'y', 'a', 'l', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x27, 0x40, 0x8B, 0x3A, 0x5F, 0xCD, 0x43, 0x6E, 0xEE, 0x48, 0x76, 0xFF, 0x41, 0x69, 0xE1, 0x04},\n    /* Colors starting with 's' */\n    {'a', 'd', 'd', 'l', 'e', 'B', 'r', 'o', 'w', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x45, 0x13, 0x00},\n    {'a', 'l', 'm', 'o', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x4C, 0x39, 0xCD, 0x70, 0x54, 0xEE, 0x82, 0x62, 0xFF, 0x8C, 0x69, 0xFA, 0x80, 0x72, 0x04},\n    {'a', 'n', 'd', 'y', 'B', 'r', 'o', 'w', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF4, 0xA4, 0x60, 0x00},\n    {'e', 'a', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x2E, 0x8B, 0x57, 0x43, 0xCD, 0x80, 0x4E, 0xEE, 0x94, 0x54, 0xFF, 0x9F, 0x2E, 0x8B, 0x57, 0x04},\n    {'e', 'a', 's', 'h', 'e', 'l', 'l', 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x86, 0x82, 0xCD, 0xC5, 0xBF, 0xEE, 0xE5, 0xDE, 0xFF, 0xF5, 0xEE, 0xFF, 0xF5, 0xEE, 0x04},\n    {'i', 'e', 'n', 'n', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x47, 0x26, 0xCD, 0x68, 0x39, 0xEE, 0x79, 0x42, 0xFF, 0x82, 0x47, 0xA0, 0x52, 0x2D, 0x04},\n    {'i', 'l', 'v', 'e', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xC0, 0xC0, 0xC0, 0x00},\n    {'k', 'y', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x4A, 0x70, 0x8B, 0x6C, 0xA6, 0xCD, 0x7E, 0xC0, 0xEE, 0x87, 0xCE, 0xFF, 0x87, 0xCE, 0xEB, 0x04},\n    {'l', 'a', 't', 'e', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x47, 0x3C, 0x8B, 0x69, 0x59, 0xCD, 0x7A, 0x67, 0xEE, 0x83, 0x6F, 0xFF, 0x6A, 0x5A, 0xCD, 0x04},\n    {'l', 'a', 't', 'e', 'G', 'r', 'a', 'y', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x6C, 0x7B, 0x8B, 0x9F, 0xB6, 0xCD, 0xB9, 0xD3, 0xEE, 0xC6, 0xE2, 0xFF, 0x70, 0x80, 0x90, 0x04},\n    {'l', 'a', 't', 'e', 'G', 'r', 'e', 'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x70, 0x80, 0x90, 0x00},\n    {'n', 'o', 'w', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x89, 0x89, 0xCD, 0xC9, 0xC9, 0xEE, 0xE9, 0xE9, 0xFF, 0xFA, 0xFA, 0xFF, 0xFA, 0xFA, 0x04},\n    {'p', 'r', 'i', 'n', 'g', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x8B, 0x45, 0x00, 0xCD, 0x66, 0x00, 0xEE, 0x76, 0x00, 0xFF, 0x7F, 0x00, 0xFF, 0x7F, 0x04},\n    {'t', 'e', 'e', 'l', 'B', 'l', 'u', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x36, 0x64, 0x8B, 0x4F, 0x94, 0xCD, 0x5C, 0xAC, 0xEE, 0x63, 0xB8, 0xFF, 0x46, 0x82, 0xB4, 0x04},\n    /* Colors starting with 't' */\n    {'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x5A, 0x2B, 0xCD, 0x85, 0x3F, 0xEE, 0x9A, 0x49, 0xFF, 0xA5, 0x4F, 0xD2, 0xB4, 0x8C, 0x04},\n    {'e', 'a', 'l', 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,\n\t    0x00, 0x80, 0x80, 0x00},\n    {'h', 'i', 's', 't', 'l', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x7B, 0x8B, 0xCD, 0xB5, 0xCD, 0xEE, 0xD2, 0xEE, 0xFF, 0xE1, 0xFF, 0xD8, 0xBF, 0xD8, 0x04},\n    {'o', 'm', 'a', 't', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x36, 0x26, 0xCD, 0x4F, 0x39, 0xEE, 0x5C, 0x42, 0xFF, 0x63, 0x47, 0xFF, 0x63, 0x47, 0x04},\n    {'u', 'r', 'q', 'u', 'o', 'i', 's', 'e', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x00, 0x86, 0x8B, 0x00, 0xC5, 0xCD, 0x00, 0xE5, 0xEE, 0x00, 0xF5, 0xFF, 0x40, 0xE0, 0xD0, 0x04},\n    /* Colors starting with 'u' (placeholder) */\n    {0xFF, 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},\n    /* Colors starting with 'v' */\n    {'i', 'o', 'l', 'e', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xEE, 0x82, 0xEE, 0x00},\n    {'i', 'o', 'l', 'e', 't', 'R', 'e', 'd', 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x22, 0x52, 0xCD, 0x32, 0x78, 0xEE, 0x3A, 0x8C, 0xFF, 0x3E, 0x96, 0xD0, 0x20, 0x90, 0x04},\n    /* Colors starting with 'w' */\n    {'h', 'e', 'a', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x7E, 0x66, 0xCD, 0xBA, 0x96, 0xEE, 0xD8, 0xAE, 0xFF, 0xE7, 0xBA, 0xF5, 0xDE, 0xB3, 0x04},\n    {'h', 'i', 't', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xFF, 0xFF, 0xFF, 0x00},\n    {'h', 'i', 't', 'e', 'S', 'm', 'o', 'k', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0xF5, 0xF5, 0xF5, 0x00},\n    /* Colors starting with 'x' (placeholder) */\n    {0xFF, 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},\n    /* Colors starting with 'y' */\n    {'e', 'l', 'l', 'o', 'w', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x8B, 0x8B, 0x00, 0xCD, 0xCD, 0x00, 0xEE, 0xEE, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x04},\n    {'e', 'l', 'l', 'o', 'w', 'G', 'r', 'e', 'e', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t    0x9A, 0xCD, 0x32, 0x00}\n};\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XParseColor --\n *\n *\tPartial implementation of X color name parsing interface.\n *\n * Results:\n *\tReturns non-zero on success.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n *\n * This only handles hex-strings without 0x prefix. Luckily, that's just what\n * we need.\n */\n\nstatic Tcl_WideInt\nparseHex64bit(\n    const char *spec,\n    char **p)\n{\n    Tcl_WideInt result = 0;\n    char c;\n    while ((c = *spec)) {\n\tif ((c >= '0') && (c <= '9')) {\n\t    c -= '0';\n\t} else if ((c >= 'A') && (c <= 'F')) {\n\t    c += (10 - 'A');\n\t} else if ((c >= 'a') && (c <= 'f')) {\n\t    c += (10 - 'a');\n\t} else {\n\t    break;\n\t}\n\tresult = (result << 4) + c;\n\t++spec;\n    }\n    *p = (char *) spec;\n    return result;\n}\n\nstatic int\ncolorcmp(\n    const char *spec,\n    const unsigned char *pname,\n    unsigned short *special)\n{\n    int r;\n    int c, d;\n    int notequal = 0;\n    int num = 0;\n\n    do {\n\td = *pname++;\n\tc = (*spec == ' ');\n\tif (c) {\n\t    spec++;\n\t}\n\tif ((unsigned)(d - 'A') <= (unsigned)('Z' - 'A')) {\n\t    d += 'a' - 'A';\n\t} else if (c) {\n\t    /*\n\t     * A space doesn't match a lowercase, but we don't know yet\n\t     * whether we should return a negative or positive number. That\n\t     * depends on what follows.\n\t     */\n\n\t    notequal = 1;\n\t}\n\tc = *spec++;\n\tif ((unsigned)(c - 'A') <= (unsigned)('Z' - 'A')) {\n\t    c += 'a' - 'A';\n\t} else if (((unsigned)(c - '1') <= (unsigned)('9' - '1'))) {\n\t    if (d == '0') {\n\t\td += 10;\n\t    } else if (!d) {\n\t\tnum = c - '0';\n\t\twhile ((unsigned)((c = *spec++) - '0') <= (unsigned)('9' - '0')) {\n\t\t    num = num * 10 + c - '0';\n\t\t}\n\t    }\n\t}\n\tr = c - d;\n    } while (!r && d);\n\n    if (!r && notequal) {\n\t/*\n\t * Strings are equal, but difference in spacings only. We should still\n\t * report not-equal, so \"burly wood\" is not a valid color.\n\t */\n\n\tr = 1;\n    }\n    *special = (unsigned short)num;\n    return r;\n}\n\n#define RED(p)\t\t((unsigned char) (p)[0])\n#define GREEN(p)\t((unsigned char) (p)[1])\n#define BLUE(p)\t\t((unsigned char) (p)[2])\n#define US(expr)\t((unsigned short) (expr))\n\nStatus\nXParseColor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Colormap),\n    const char *spec,\n    XColor *colorPtr)\n{\n    if (spec[0] == '#') {\n\tchar *p;\n\tTcl_WideInt value = parseHex64bit(++spec, &p);\n\n\t/*\n\t * If *p does not point to the end of the string, there were invalid\n\t * digits in the spec. Ergo, it is not a valid color string.\n\t * (Bug f0188aca9e)\n\t */\n\n\tif (*p != '\\0') {\n\t    return 0;\n\t}\n\n\tswitch ((int)(p-spec)) {\n\tcase 3:\n\t    colorPtr->red = US(((value >> 8) & 0xf) * 0x1111);\n\t    colorPtr->green = US(((value >> 4) & 0xf) * 0x1111);\n\t    colorPtr->blue = US((value & 0xf) * 0x1111);\n\t    break;\n\tcase 6:\n\t    colorPtr->red = US(((value >> 16) & 0xff) | ((value >> 8) & 0xff00));\n\t    colorPtr->green = US(((value >> 8) & 0xff) | (value & 0xff00));\n\t    colorPtr->blue = US((value & 0xff) | (value << 8));\n\t    break;\n\tcase 9:\n\t    colorPtr->red = US(((value >> 32) & 0xf) | ((value >> 20) & 0xfff0));\n\t    colorPtr->green = US(((value >> 20) & 0xf) | ((value >> 8) & 0xfff0));\n\t    colorPtr->blue = US(((value >> 8) & 0xf) | (value << 4));\n\t    break;\n\tcase 12:\n\t    colorPtr->red = US(value >> 32);\n\t    colorPtr->green = US(value >> 16);\n\t    colorPtr->blue = US(value);\n\t    break;\n\tdefault:\n\t    return 0;\n\t}\n    } else {\n\t/*\n\t * Perform a binary search on the sorted array of colors.\n\t * size = current size of search range\n\t * p    = pointer to current element being considered.\n\t */\n\n\tint size;\n\tunsigned short num;\n\tconst elem *p;\n\tconst unsigned char *q;\n\tint r = (spec[0] - 'A') & 0xdf;\n\n\tif (r >= (int) sizeof(az) - 1) {\n\t    return 0;\n\t}\n\tsize = az[r + 1] - az[r];\n\tp = &xColors[(az[r + 1] + az[r]) >> 1];\n\tr = colorcmp(spec + 1, *p, &num);\n\n\twhile (r != 0) {\n\t    if (r < 0) {\n\t\tsize = (size >> 1);\n\t\tp -= ((size + 1) >> 1);\n\t    } else {\n\t\t--size;\n\t\tsize = (size >> 1);\n\t\tp += ((size + 2) >> 1);\n\t    }\n\t    if (!size) {\n\t\treturn 0;\n\t    }\n\t    r = colorcmp(spec + 1, *p, &num);\n\t}\n\tif (num > (*p)[31]) {\n\t    if (((*p)[31] != 8) || num > 100) {\n\t\treturn 0;\n\t    }\n\t    num = (unsigned short)((num * 255 + 50) / 100);\n\t    if ((num == 230) || (num == 128)) {\n\t\t/*\n\t\t * Those two entries have a deviation i.r.t the table.\n\t\t */\n\n\t\tnum--;\n\t    }\n\t    num |= (num << 8);\n\t    colorPtr->red = colorPtr->green = colorPtr->blue = num;\n\t} else {\n\t    q = *p + 28 - num * 3;\n\t    colorPtr->red = (unsigned short)((RED(q) << 8) | RED(q));\n\t    colorPtr->green = (unsigned short)((GREEN(q) << 8) | GREEN(q));\n\t    colorPtr->blue = (unsigned short)((BLUE(q) << 8) | BLUE(q));\n\t}\n    }\n    colorPtr->pixel = TkpGetPixel(colorPtr);\n    colorPtr->flags = DoRed|DoGreen|DoBlue;\n    colorPtr->pad = 0;\n    return 1;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "xlib/xdraw.c",
    "content": "/*\n * xdraw.c --\n *\n *\tThis file contains generic procedures related to X drawing primitives.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tk.h\"\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XDrawLine --\n *\n *\tDraw a single line between two points in a given drawable.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tDraws a single line segment.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXDrawLine(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x1, int y1,\n    int x2, int y2)\t\t/* Coordinates of line segment. */\n{\n    XPoint points[2];\n\n    points[0].x = (short)x1;\n    points[0].y = (short)y1;\n    points[1].x = (short)x2;\n    points[1].y = (short)y2;\n    return XDrawLines(display, d, gc, points, 2, CoordModeOrigin);\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFillRectangle --\n *\n *\tFills a rectangular area in the given drawable. This procedure is\n *\timplemented as a call to XFillRectangles.\n *\n * Results:\n *\tNone\n *\n * Side effects:\n *\tFills the specified rectangle.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXFillRectangle(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x,\n    int y,\n    unsigned int width,\n    unsigned int height)\n{\n    XRectangle rectangle;\n    rectangle.x = (short)x;\n    rectangle.y = (short)y;\n    rectangle.width = (unsigned short)width;\n    rectangle.height = (unsigned short)height;\n    return XFillRectangles(display, d, gc, &rectangle, 1);\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "xlib/xgc.c",
    "content": "/*\n * xgc.c --\n *\n *\tThis file contains generic routines for manipulating X graphics\n *\tcontexts.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n * Copyright © 2002-2009 Daniel A. Steffen <das@users.sourceforge.net>\n * Copyright © 2008-2009 Apple Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\f\n#define MAX_DASH_LIST_SIZE 10\ntypedef struct {\n    XGCValues gc;\n    char dash[MAX_DASH_LIST_SIZE];\n} XGCValuesWithDash;\n\n/*\n *----------------------------------------------------------------------\n *\n * AllocClipMask --\n *\n *\tStatic helper proc to allocate new or clear existing TkpClipMask.\n *\n * Results:\n *\tReturns ptr to the new/cleared TkpClipMask.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic TkpClipMask *AllocClipMask(GC gc) {\n    TkpClipMask *clip_mask = (TkpClipMask*) gc->clip_mask;\n\n    if (clip_mask == NULL) {\n\tclip_mask = (TkpClipMask *)Tcl_Alloc(sizeof(TkpClipMask));\n\tgc->clip_mask = (Pixmap) clip_mask;\n    } else if (clip_mask->type == TKP_CLIP_REGION) {\n\tXDestroyRegion(clip_mask->value.region);\n    }\n    clip_mask->type = TKP_CLIP_PIXMAP;\n    clip_mask->value.pixmap = None;\n    return clip_mask;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * FreeClipMask --\n *\n *\tStatic helper proc to free TkpClipMask.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nstatic void FreeClipMask(GC gc) {\n    TkpClipMask * clip_mask = (TkpClipMask*)gc->clip_mask;\n    if (clip_mask == NULL) {\n\treturn;\n    }\n    if (clip_mask->type == TKP_CLIP_REGION) {\n\tXDestroyRegion(clip_mask->value.region);\n    }\n    Tcl_Free(clip_mask);\n    gc->clip_mask = None;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateGC --\n *\n *\tAllocate a new GC, and initialize the specified fields.\n *\n * Results:\n *\tReturns a newly allocated GC.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nGC\nXCreateGC(\n    Display *display,\n    TCL_UNUSED(Drawable),\n    unsigned long mask,\n    XGCValues *values)\n{\n    GC gp;\n\n    /*\n     * In order to have room for a dash list, MAX_DASH_LIST_SIZE extra chars\n     * are defined, which is invisible from the outside. The list is assumed\n     * to end with a 0-char, so this must be set explicitly during\n     * initialization.\n     */\n\n    gp = (GC)Tcl_Alloc(sizeof(XGCValuesWithDash));\n\n#define InitField(name,maskbit,default) \\\n\t(gp->name = (mask & (maskbit)) ? values->name : (default))\n\n    InitField(function,\t\t  GCFunction,\t\tGXcopy);\n    InitField(plane_mask,\t  GCPlaneMask,\t\t(unsigned long)(~0));\n    InitField(foreground,\t  GCForeground,\n\t    BlackPixelOfScreen(DefaultScreenOfDisplay(display)));\n    InitField(background,\t  GCBackground,\n\t    WhitePixelOfScreen(DefaultScreenOfDisplay(display)));\n    InitField(line_width,\t  GCLineWidth,\t\t1);\n    InitField(line_style,\t  GCLineStyle,\t\tLineSolid);\n    InitField(cap_style,\t  GCCapStyle,\t\t0);\n    InitField(join_style,\t  GCJoinStyle,\t\t0);\n    InitField(fill_style,\t  GCFillStyle,\t\tFillSolid);\n    InitField(fill_rule,\t  GCFillRule,\t\tEvenOddRule);\n    InitField(arc_mode,\t\t  GCArcMode,\t\tArcPieSlice);\n    InitField(tile,\t\t  GCTile,\t\t0);\n    InitField(stipple,\t\t  GCStipple,\t\t0);\n    InitField(ts_x_origin,\t  GCTileStipXOrigin,\t0);\n    InitField(ts_y_origin,\t  GCTileStipYOrigin,\t0);\n    InitField(font,\t\t  GCFont,\t\t0);\n    InitField(subwindow_mode,\t  GCSubwindowMode,\tClipByChildren);\n    InitField(graphics_exposures, GCGraphicsExposures,\tTrue);\n    InitField(clip_x_origin,\t  GCClipXOrigin,\t0);\n    InitField(clip_y_origin,\t  GCClipYOrigin,\t0);\n    InitField(dash_offset,\t  GCDashOffset,\t\t0);\n    InitField(dashes,\t\t  GCDashList,\t\t4);\n    (&(gp->dashes))[1] = 0;\n\n    gp->clip_mask = None;\n    if (mask & GCClipMask) {\n\tTkpClipMask *clip_mask = AllocClipMask(gp);\n\n\tclip_mask->type = TKP_CLIP_PIXMAP;\n\tclip_mask->value.pixmap = values->clip_mask;\n    }\n    return gp;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XChangeGC --\n *\n *\tChanges the GC components specified by valuemask for the specified GC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tUpdates the specified GC.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXChangeGC(\n    Display *d,\n    GC gc,\n    unsigned long mask,\n    XGCValues *values)\n{\n#define ModifyField(name,maskbit) \\\n\tif (mask & (maskbit)) { gc->name = values->name; }\n\n    ModifyField(function, GCFunction);\n    ModifyField(plane_mask, GCPlaneMask);\n    ModifyField(foreground, GCForeground);\n    ModifyField(background, GCBackground);\n    ModifyField(line_width, GCLineWidth);\n    ModifyField(line_style, GCLineStyle);\n    ModifyField(cap_style, GCCapStyle);\n    ModifyField(join_style, GCJoinStyle);\n    ModifyField(fill_style, GCFillStyle);\n    ModifyField(fill_rule, GCFillRule);\n    ModifyField(arc_mode, GCArcMode);\n    ModifyField(tile, GCTile);\n    ModifyField(stipple, GCStipple);\n    ModifyField(ts_x_origin, GCTileStipXOrigin);\n    ModifyField(ts_y_origin, GCTileStipYOrigin);\n    ModifyField(font, GCFont);\n    ModifyField(subwindow_mode, GCSubwindowMode);\n    ModifyField(graphics_exposures, GCGraphicsExposures);\n    ModifyField(clip_x_origin, GCClipXOrigin);\n    ModifyField(clip_y_origin, GCClipYOrigin);\n    ModifyField(dash_offset, GCDashOffset);\n    if (mask & GCClipMask) {\n\tXSetClipMask(d, gc, values->clip_mask);\n    }\n    if (mask & GCDashList) {\n\tgc->dashes = values->dashes;\n\t(&(gc->dashes))[1] = 0;\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XFreeGC --\n *\n *\tDeallocates the specified graphics context.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nint XFreeGC(\n    TCL_UNUSED(Display *),\n    GC gc)\n{\n    if (gc != NULL) {\n\tFreeClipMask(gc);\n\tTcl_Free(gc);\n    }\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSetForeground, etc. --\n *\n *\tThe following functions are simply accessor functions for the GC\n *\tslots.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tEach function sets some slot in the GC.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetForeground(\n    TCL_UNUSED(Display *),\n    GC gc,\n    unsigned long foreground)\n{\n    gc->foreground = foreground;\n    return Success;\n}\n\nint\nXSetBackground(\n    TCL_UNUSED(Display *),\n    GC gc,\n    unsigned long background)\n{\n    gc->background = background;\n    return Success;\n}\n\nint\nXSetDashes(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int dash_offset,\n    const char *dash_list,\n    int n)\n{\n    char *p = &(gc->dashes);\n\n#ifdef TkWinDeleteBrush\n    TkWinDeleteBrush(gc->fgBrush);\n    TkWinDeletePen(gc->fgPen);\n    TkWinDeleteBrush(gc->bgBrush);\n    TkWinDeletePen(gc->fgExtPen);\n#endif\n    gc->dash_offset = dash_offset;\n    if (n > MAX_DASH_LIST_SIZE) n = MAX_DASH_LIST_SIZE;\n    while (n-- > 0) {\n\t*p++ = *dash_list++;\n    }\n    *p = 0;\n    return Success;\n}\n\nint\nXSetFunction(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int function)\n{\n    gc->function = function;\n    return Success;\n}\n\nint\nXSetFillRule(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int fill_rule)\n{\n    gc->fill_rule = fill_rule;\n    return Success;\n}\n\nint\nXSetFillStyle(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int fill_style)\n{\n    gc->fill_style = fill_style;\n    return Success;\n}\n\nint\nXSetTSOrigin(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int x, int y)\n{\n    gc->ts_x_origin = x;\n    gc->ts_y_origin = y;\n    return Success;\n}\n\nint\nXSetFont(\n    TCL_UNUSED(Display *),\n    GC gc,\n    Font font)\n{\n    gc->font = font;\n    return Success;\n}\n\nint\nXSetArcMode(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int arc_mode)\n{\n    gc->arc_mode = arc_mode;\n    return Success;\n}\n\nint\nXSetStipple(\n    TCL_UNUSED(Display *),\n    GC gc,\n    Pixmap stipple)\n{\n    gc->stipple = stipple;\n    return Success;\n}\n\nint\nXSetLineAttributes(\n    TCL_UNUSED(Display *),\n    GC gc,\n    unsigned int line_width,\n    int line_style,\n    int cap_style,\n    int join_style)\n{\n    gc->line_width = (int)line_width;\n    gc->line_style = line_style;\n    gc->cap_style = cap_style;\n    gc->join_style = join_style;\n    return Success;\n}\n\nint\nXSetClipOrigin(\n    TCL_UNUSED(Display *),\n    GC gc,\n    int clip_x_origin,\n    int clip_y_origin)\n{\n    gc->clip_x_origin = clip_x_origin;\n    gc->clip_y_origin = clip_y_origin;\n    return Success;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XSetRegion, XSetClipMask, XSetClipRectangles --\n *\n *\tSets the clipping region/pixmap for a GC.\n *\n *\tLike the Xlib equivalent, it is safe to delete the\n *\tregion after setting it into the GC.\n *\n * Results:\n *\tNone.\n *\n * Side effects:\n *\tAllocates or deallocates a TkpClipMask.\n *\n *----------------------------------------------------------------------\n */\n\nint\nXSetRegion(\n    TCL_UNUSED(Display *),\n    GC gc,\n    Region r)\n{\n    if (r == NULL) {\n\tTcl_Panic(\"must not pass NULL to XSetRegion for compatibility with X11; use XSetClipMask instead\");\n    } else {\n\tTkpClipMask *clip_mask = AllocClipMask(gc);\n\n\tclip_mask->type = TKP_CLIP_REGION;\n\tclip_mask->value.region = r;\n\tclip_mask->value.region = XCreateRegion();\n\tTkpCopyRegion(clip_mask->value.region, r);\n    }\n    return Success;\n}\n\nint\nXSetClipMask(\n    TCL_UNUSED(Display *),\n    GC gc,\n    Pixmap pixmap)\n{\n    if (pixmap == None) {\n\tFreeClipMask(gc);\n    } else {\n\tTkpClipMask *clip_mask = AllocClipMask(gc);\n\n\tclip_mask->type = TKP_CLIP_PIXMAP;\n\tclip_mask->value.pixmap = pixmap;\n    }\n    return Success;\n}\n\nint\nXSetClipRectangles(\n    TCL_UNUSED(Display*),\n    GC gc,\n    int clip_x_origin,\n    int clip_y_origin,\n    XRectangle* rectangles,\n    int n,\n    TCL_UNUSED(int))\n{\n    Region clipRgn = XCreateRegion();\n    TkpClipMask * clip_mask = AllocClipMask(gc);\n    clip_mask->type = TKP_CLIP_REGION;\n    clip_mask->value.region = clipRgn;\n\n    while (n--) {\n\tXRectangle rect = *rectangles;\n\n\trect.x += (short)clip_x_origin;\n\trect.y += (short)clip_y_origin;\n\tXUnionRectWithRegion(&rect, clipRgn, clipRgn);\n\trectangles++;\n    }\n    return 1;\n}\n\n/*\n * Some additional dummy functions (hopefully implemented soon).\n */\n\n#if 0\nCursor\nXCreateFontCursor(\n    Display *display,\n    unsigned int shape)\n{\n    return (Cursor) 0;\n}\n\nvoid\nXDrawImageString(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x,\n    int y,\n    const char *string,\n    int length)\n{\n}\n#endif\n\nint\nXDrawPoint(\n    Display *display,\n    Drawable d,\n    GC gc,\n    int x,\n    int y)\n{\n    return XDrawLine(display, d, gc, x, y, x, y);\n}\n\nint\nXDrawPoints(\n    Display *display,\n    Drawable d,\n    GC gc,\n    XPoint *points,\n    int npoints,\n    TCL_UNUSED(int))\n{\n    int res = Success;\n\n    while (npoints-- > 0) {\n\tres = XDrawLine(display, d, gc,\n\t\tpoints[0].x, points[0].y, points[0].x, points[0].y);\n\tif (res != Success) break;\n\t++points;\n    }\n    return res;\n}\n\n#if !defined(MAC_OSX_TK)\nint\nXDrawSegments(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Drawable),\n    TCL_UNUSED(GC),\n    TCL_UNUSED(XSegment *),\n    TCL_UNUSED(int))\n{\n    return BadDrawable;\n}\n#endif\n\nchar *\nXFetchBuffer(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int))\n{\n    return (char *) 0;\n}\n\nStatus\nXFetchName(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(char **))\n{\n    return Success;\n}\n\nAtom *\nXListProperties(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int *))\n{\n    return (Atom *) 0;\n}\n\nint\nXMapRaised(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window))\n{\n    return Success;\n}\n\nint\nXQueryTextExtents(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(XID),\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(int *),\n    TCL_UNUSED(XCharStruct *))\n{\n    return Success;\n}\n\nint\nXReparentWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    return BadWindow;\n}\n\nint\nXUndefineCursor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window))\n{\n    return Success;\n}\n\nXVaNestedList\nXVaCreateNestedList(\n    TCL_UNUSED(int), ...)\n{\n    return NULL;\n}\n\nchar *\nXSetICValues(\n    TCL_UNUSED(XIC), ...)\n{\n    return NULL;\n}\n\nchar *\nXGetICValues(\n    TCL_UNUSED(XIC), ...)\n{\n    return NULL;\n}\n\nvoid\nXSetICFocus(\n    TCL_UNUSED(XIC))\n{\n}\n\nWindow\nXCreateWindow(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Window),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(Visual *),\n    TCL_UNUSED(unsigned long),\n    TCL_UNUSED(XSetWindowAttributes *))\n{\n\treturn 0;\n}\n\nRegion\nXPolygonRegion(\n    TCL_UNUSED(XPoint *),\n    TCL_UNUSED(int),\n    TCL_UNUSED(int))\n{\n    return 0;\n}\n\f\nvoid\nXDestroyIC(\n    TCL_UNUSED(XIC))\n{\n}\n\nCursor\nXCreatePixmapCursor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Pixmap),\n    TCL_UNUSED(Pixmap),\n    TCL_UNUSED(XColor *),\n    TCL_UNUSED(XColor *),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(unsigned int))\n{\n    return (Cursor) NULL;\n}\n\nCursor\nXCreateGlyphCursor(\n    TCL_UNUSED(Display *),\n    TCL_UNUSED(Font),\n    TCL_UNUSED(Font),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(unsigned int),\n    TCL_UNUSED(XColor const *),\n    TCL_UNUSED(XColor const *))\n{\n    return (Cursor) NULL;\n}\n\nXFontSet\nXCreateFontSet(\n    TCL_UNUSED(Display *)\t\t/* display */,\n    TCL_UNUSED(const char *)\t/* base_font_name_list */,\n    TCL_UNUSED(char ***)\t\t/* missing_charset_list */,\n    TCL_UNUSED(int *)\t\t/* missing_charset_count */,\n    TCL_UNUSED(char **)\t\t/* def_string */\n) {\n    return (XFontSet)0;\n}\n\nvoid\nXFreeFontSet(\n    TCL_UNUSED(Display *),\t\t/* display */\n    TCL_UNUSED(XFontSet)\t\t/* font_set */\n) {\n}\n\nvoid\nXFreeStringList(\n    TCL_UNUSED(char **)\t\t/* list */\n) {\n}\n\nStatus\nXCloseIM(\n    TCL_UNUSED(XIM) /* im */\n) {\n    return Success;\n}\n\nBool\nXRegisterIMInstantiateCallback(\n    TCL_UNUSED(Display *)\t\t\t/* dpy */,\n    TCL_UNUSED(struct _XrmHashBucketRec *)\t/* rdb */,\n    TCL_UNUSED(char *)\t\t\t/* res_name */,\n    TCL_UNUSED(char *)\t\t\t/* res_class */,\n    TCL_UNUSED(XIDProc)\t\t\t/* callback */,\n    TCL_UNUSED(XPointer)\t\t\t/* client_data */\n) {\n    return False;\n}\n\nBool\nXUnregisterIMInstantiateCallback(\n    TCL_UNUSED(Display *)\t\t/* dpy */,\n    TCL_UNUSED(struct _XrmHashBucketRec *)\t/* rdb */,\n    TCL_UNUSED(char *)\t\t\t/* res_name */,\n    TCL_UNUSED(char *)\t\t\t/* res_class */,\n    TCL_UNUSED(XIDProc)\t\t\t/* callback */,\n    TCL_UNUSED(XPointer)\t\t\t/* client_data */\n) {\n    return False;\n}\n\nchar *\nXSetLocaleModifiers(\n    TCL_UNUSED(const char *)\t\t/* modifier_list */\n) {\n    return NULL;\n}\n\nXIM XOpenIM(\n    TCL_UNUSED(Display *)\t\t\t/* dpy */,\n    TCL_UNUSED(struct _XrmHashBucketRec *)\t/* rdb */,\n    TCL_UNUSED(char *)\t\t\t/* res_name */,\n    TCL_UNUSED(char *)\t\t\t/* res_class */\n) {\n    return NULL;\n}\n\nchar *\nXGetIMValues(\n    TCL_UNUSED(XIM) /* im */, ...\n) {\n    return NULL;\n}\n\nchar *\nXSetIMValues(\n    TCL_UNUSED(XIM) /* im */, ...\n) {\n    return NULL;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "xlib/ximage.c",
    "content": "/*\n * ximage.c --\n *\n *\tX bitmap and image routines.\n *\n * Copyright © 1995 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XCreateBitmapFromData --\n *\n *\tConstruct a single plane pixmap from bitmap data.\n *\n *\tNOTE: This procedure has the correct behavior on Windows and the\n *\tMacintosh, but not on UNIX. This is probably because the emulation for\n *\tXPutImage on those platforms compensates for whatever is wrong here\n *\t:-)\n *\n * Results:\n *\tReturns a new Pixmap.\n *\n * Side effects:\n *\tAllocates a new bitmap and drawable.\n *\n *----------------------------------------------------------------------\n */\n\nPixmap\nXCreateBitmapFromData(\n    Display *display,\n    Drawable d,\n    const char *data,\n    unsigned int width,\n    unsigned int height)\n{\n    XImage *ximage;\n    GC gc;\n    Pixmap pix;\n\n    pix = Tk_GetPixmap(display, d, (int) width, (int) height, 1);\n    gc = XCreateGC(display, pix, 0, NULL);\n    if (gc == NULL) {\n\tTk_FreePixmap(display, pix);\n\treturn None;\n    }\n    ximage = XCreateImage(display, NULL, 1, XYBitmap, 0, (char*) data, width,\n\t    height, 8, ((int)width + 7) / 8);\n    if (ximage) {\n\tximage->bitmap_bit_order = LSBFirst;\n\t_XInitImageFuncPtrs(ximage);\n\tTkPutImage(NULL, 0, display, pix, gc, ximage, 0, 0, 0, 0, width, height);\n\tximage->data = NULL;\n\tXDestroyImage(ximage);\n    }\n    XFreeGC(display, gc);\n    return pix;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  },
  {
    "path": "xlib/xutil.c",
    "content": "/*\n * xutil.c --\n *\n *\tThis function contains generic X emulation routines.\n *\n * Copyright © 1995-1996 Sun Microsystems, Inc.\n *\n * See the file \"license.terms\" for information on usage and redistribution of\n * this file, and for a DISCLAIMER OF ALL WARRANTIES.\n */\n\n#include \"tkInt.h\"\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XInternAtom --\n *\n *\tThis procedure simulates the XInternAtom function by calling Tk_Uid to\n *\tget a unique id for every atom. This is only a partial implementation,\n *\tsince it doesn't work across applications.\n *\n * Results:\n *\tA new Atom.\n *\n * Side effects:\n *\tNone.\n *\n *----------------------------------------------------------------------\n */\n\nAtom\nXInternAtom(\n    Display *display,\n    TCL_UNUSED(const char *),\n    TCL_UNUSED(Bool))\n{\n    static Atom atom = XA_LAST_PREDEFINED;\n\n    LastKnownRequestProcessed(display)++;\n    return ++atom;\n}\n\f\n/*\n *----------------------------------------------------------------------\n *\n * XGetVisualInfo --\n *\n *\tReturns information about the specified visual.\n *\n * Results:\n *\tReturns a newly allocated XVisualInfo structure.\n *\n * Side effects:\n *\tAllocates storage.\n *\n *----------------------------------------------------------------------\n */\n\nXVisualInfo *\nXGetVisualInfo(\n    Display *display,\n    long vinfo_mask,\n    XVisualInfo *vinfo_template,\n    int *nitems_return)\n{\n    XVisualInfo *info = (XVisualInfo *)Tcl_Alloc(sizeof(XVisualInfo));\n\n    info->visual = DefaultVisual(display, 0);\n    info->visualid = info->visual->visualid;\n    info->screen = 0;\n    info->depth = info->visual->bits_per_rgb;\n    info->c_class = info->visual->c_class;\n    info->colormap_size = info->visual->map_entries;\n    info->bits_per_rgb = info->visual->bits_per_rgb;\n    info->red_mask = info->visual->red_mask;\n    info->green_mask = info->visual->green_mask;\n    info->blue_mask = info->visual->blue_mask;\n\n    if (((vinfo_mask & VisualIDMask)\n\t    && (vinfo_template->visualid != info->visualid))\n\t    || ((vinfo_mask & VisualScreenMask)\n\t\t    && (vinfo_template->screen != info->screen))\n\t    || ((vinfo_mask & VisualDepthMask)\n\t\t    && (vinfo_template->depth != info->depth))\n\t    || ((vinfo_mask & VisualClassMask)\n\t\t    && (vinfo_template->c_class != info->c_class))\n\t    || ((vinfo_mask & VisualColormapSizeMask)\n\t\t    && (vinfo_template->colormap_size != info->colormap_size))\n\t    || ((vinfo_mask & VisualBitsPerRGBMask)\n\t\t    && (vinfo_template->bits_per_rgb != info->bits_per_rgb))\n\t    || ((vinfo_mask & VisualRedMaskMask)\n\t\t    && (vinfo_template->red_mask != info->red_mask))\n\t    || ((vinfo_mask & VisualGreenMaskMask)\n\t\t    && (vinfo_template->green_mask != info->green_mask))\n\t    || ((vinfo_mask & VisualBlueMaskMask)\n\t\t    && (vinfo_template->blue_mask != info->blue_mask))\n\t) {\n\tTcl_Free(info);\n\treturn NULL;\n    }\n\n    *nitems_return = 1;\n    return info;\n}\n\f\n/*\n * Local Variables:\n * mode: c\n * c-basic-offset: 4\n * fill-column: 78\n * End:\n */\n"
  }
]